diff --git a/arch/arm/boot/dts/K6000_Plus.dts b/arch/arm/boot/dts/K6000_Plus.dts new file mode 100644 index 0000000000000000000000000000000000000000..8fd1dd2f8e61436de2f521b2f2817b3cd2d73961 --- /dev/null +++ b/arch/arm/boot/dts/K6000_Plus.dts @@ -0,0 +1,907 @@ + +/dts-v1/; + +#include "mt6755.dtsi" +#include "cust.dtsi" + +/ { + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x3e800000>; + }; + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4B434E loglevel=8"; + + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base_h = <0x0>; + atag,videolfb-fb_base_l = <0x7E800000>; + atag,videolfb-islcmfound = <1>; + /* because no lk, so lcm is not inited */ + atag,videolfb-islcm_inited = <0>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35695_fhd_dsi_cmd_truly_nt50358_drv"; + }; + led0:led@0 { + compatible = "mediatek,red"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led1:led@1 { + compatible = "mediatek,green"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led2:led@2 { + compatible = "mediatek,blue"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led3:led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led4:led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led5:led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led6:led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <5>; + }; +/* start sensor */ + cust_accel@0 { + compatible = "mediatek,mpu6515a"; + i2c_num = <1>; + /* i2c_addr = <0x4c 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <16>; + is_batch_supported = <1>; + }; + + cust_alsps@0 { + compatible = "mediatek,cm36686"; + i2c_num = <1>; + i2c_addr = <0x60 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als = <1>; + power_id = <0xffff>; + power_vol = <0>; +/* Total has 15 level*/ + als_level = <0 257 637 1027 2297 5588 6730 11301 20449 25768 31122 45552 57937 57937 57937>; +/* Total has 16 range*/ + als_value = <0 132 304 502 1004 2003 3006 5006 8004 10000 12000 16000 20000 20000 20000 20000>; + ps_threshold_high = <70>; + ps_threshold_low = <40>; + is_batch_supported_ps = <1>; + is_batch_supported_als = <1>; + }; + + cust_mag@0 { + compatible = "mediatek,akm8963"; + i2c_num = <1>; + /* i2c_addr = <0x0F 0 0 0>; */ + direction = <8>; + power_id = <0xffff>; + power_vol = <0>; + /* is_batch_supported = <0>; */ + }; + + cust_gyro@0 { + compatible = "mediatek,mpu6515g"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + + cust_baro@0 { + compatible = "mediatek,bmp280new"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <32>; + is_batch_supported = <0>; + }; +/* end sensor */ +}; +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <6>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 80 220 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; +}; + +/* TOUCH start */ +&touch { + tpd-resolution = <1080 1920>; + use-tpd-button = <0>; + tpd-key-num = <3>; + tpd-key-local= <139 172 158 0>; + tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>; + tpd-max-touch-num = <5>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <146>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <0 0 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: eint0default { + }; + ctp_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_sub_vcamd0: cam1@4 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_sub_vcamd1: cam1@5 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + /*camera_pins_cam_ldo_vcama_0: cam@vcama0 { + }; + camera_pins_cam_ldo_vcama_1: cam@vcama1 { + };*/ + camera_pins_default: camdefault { + }; + +}; + +&kd_camera_hw1 { + pinctrl-names = "default", + "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo_sub_vcamd_0", "cam_ldo_sub_vcamd_1"; + /*"cam2_rst0", "cam2_rst1", "cam2_pnd0", "cam2_pnd1", + "cam_ldo_vcama_0", "cam_ldo_vcama_1";*/ + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_sub_vcamd0>; + pinctrl-10 = <&camera_pins_sub_vcamd1>; + /* for main2 */ + /*pinctrl-9 = <&camera_pins_cam2_rst0>; + pinctrl-10 = <&camera_pins_cam2_rst1>; + pinctrl-11 = <&camera_pins_cam2_pnd0>; + pinctrl-12 = <&camera_pins_cam2_pnd1>;*/ + /* for ldo control by gpio */ + /*pinctrl-13 = <&camera_pins_cam_ldo_vcama_0>; + pinctrl-14 = <&camera_pins_cam_ldo_vcama_1>;*/ + status = "okay"; + +}; +/* CAMERA GPIO end */ + +&pio { + alsps_intpin_cfg: alspspincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + + alsps_intpin_default: alspsdefaultcfg { + + }; + + gyro_intpin_cfg: gyropincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + + gyro_intpin_default: gyrodefaultcfg { + + }; +}; + +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; + +&gyroscope { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_lcd_bias_enp0: lcd_bias_enp0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcd_bias_enp1: lcd_bias_enp1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", "lcd_bias_enp0_gpio", "lcd_bias_enp1_gpio"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_lcd_bias_enp0>; + pinctrl-6 = <&mtkfb_pins_lcd_bias_enp1>; + status = "okay"; +};/* DISPSYS GPIO standardization end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + }; + + gpslna_pins_init: gpslna@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; +}; +/* CONSYS end */ + +/* SPM GPIO standardization */ +&pio { + spm_pins_default: default { + }; + + spm_vmd1_sel: vmd1_sel { + pins_cmd_dat { + pins = ; + }; + }; + +}; + +&sleep{ + pinctrl-names = "default", "vmd1_sel"; + pinctrl-0 = <&spm_pins_default>; + pinctrl-1 = <&spm_vmd1_sel>; + status = "okay"; +}; +/* SPM end */ + +/* AUDIO GPIO standardization */ +&audgpio { + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "audi2s1-mode0", "audi2s1-mode1", "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow", "rcvspk-pullhigh", + "rcvspk-pulllow","hpdepop-pullhigh","hpdepop-pulllow"; + pinctrl-0 = <&aud_pins_default>; + pinctrl-1 = <&aud_pins_pmicclk_mode0>; + pinctrl-2 = <&aud_pins_pmicclk_mode1>; + pinctrl-3 = <&aud_pins_i2s1_mode0>; + pinctrl-4 = <&aud_pins_i2s1_mode1>; + pinctrl-5 = <&aud_pins_extamp_high>; + pinctrl-6 = <&aud_pins_extamp_low>; + pinctrl-7 = <&aud_pins_extamp2_high>; + pinctrl-8 = <&aud_pins_extamp2_low>; + pinctrl-9 = <&aud_pins_rcvspk_high>; + pinctrl-10 = <&aud_pins_rcvspk_low>; + pinctrl-11 = <&aud_pins_hpdepop_high>; + pinctrl-12 = <&aud_pins_hpdepop_low>; + status = "okay"; +}; + +&pio { + aud_pins_default: audiodefault { + }; + + aud_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode0: audi2s1mode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode1: audi2s1mode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_extamp_high: audexamphigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_extamp_low: audexamplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_extamp2_high: audexam2phigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + aud_pins_extamp2_low: audexamp2low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_rcvspk_high: audrcvspkhigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_rcvspk_low: audrcvspklow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_hpdepop_high: audhpdepophigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_hpdepop_low: audhpdepoplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; +/* AUDIO end */ + +/* UART GPIO */ +&apuart0 { + pinctrl-names = "uart0_gpio_default", + "uart0_rx_set", + "uart0_rx_clear", + "uart0_tx_set", + "uart0_tx_clear"; + pinctrl-0 = <&uart0_gpio_def_cfg>; + pinctrl-1 = <&uart0_rx_set_cfg>; + pinctrl-2 = <&uart0_rx_clr_cfg>; + pinctrl-3 = <&uart0_tx_set_cfg>; + pinctrl-4 = <&uart0_tx_clr_cfg>; + status = "okay"; +}; + +&pio { + /* UART GPIO Settings - Start */ + /* UART0: rx set, rx clear, tx clear, tx clear*/ + uart0_gpio_def_cfg:uart0gpiodefault { + + }; + uart0_rx_set_cfg:uart0_rx_set@gpio105 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_rx_clr_cfg:uart0_rx_clear@gpio105 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + uart0_tx_set_cfg:uart0_tx_set@gpio106 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_tx_clr_cfg:uart0_tx_clear@gpio106 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +};/* UART GPIO end */ + +/* IRTX GPIO end */ +&irtx_pwm { + pinctrl-names = "irtx_gpio_led_default", + "irtx_gpio_led_set", + "irtx_gpio_en_default", + "irtx_gpio_en_set"; + + pinctrl-0 = <&irtx_gpio_led_default>; + pinctrl-1 = <&irtx_gpio_led_set>; + pinctrl-2 = <&irtx_gpio_en_default>; + pinctrl-3 = <&irtx_gpio_en_set>; + status = "okay"; +}; +&pio { + /* IRTX GPIO Settings -Start */ + /* default: GPIO0, output, high */ + irtx_gpio_led_default:irtx_gpio_led_def@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_led_set:irtx_gpio_led_set@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + irtx_gpio_en_default:irtx_gpio_en_def@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_en_set:irtx_gpio_en_set@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + +}; /* IRTX GPIO Settings -End */ + +/* NFC GPIO standardization */ +&pio { + nfc_default: default { + + }; + + nfc_ven_high: state_ven_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_ven_low: state_ven_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_rst_high: state_rst_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_rst_low: state_rst_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_eint_high: state_eint_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_eint_low: state_eint_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_irq_init: state_irq_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; +}; + +&nfc { + pinctrl-names = "default", "ven_high", "ven_low", "rst_high", "rst_low", "eint_high", "eint_low", "irq_init"; + pinctrl-0 = <&nfc_default>; + pinctrl-1 = <&nfc_ven_high>; + pinctrl-2 = <&nfc_ven_low>; + pinctrl-3 = <&nfc_rst_high>; + pinctrl-4 = <&nfc_rst_low>; + pinctrl-5 = <&nfc_eint_high>; + pinctrl-6 = <&nfc_eint_low>; + pinctrl-7 = <&nfc_irq_init>; + status = "okay"; +}; +/* NFC end */ + + + + +&pio { + iddig_default: iddig_default { + }; + + iddig_init: iddig_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio43_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + gpio43_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&iddig_init>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio43_mode1_drvvbus_low>; + pinctrl-2 = <&gpio43_mode1_drvvbus_high>; + status = "okay"; +}; + +&i2c1 { + + gyro@68 { + compatible = "mediatek,gyro"; + reg = <0x69>; + status = "okay"; + }; + + gsensor@68 { + compatible = "mediatek,gsensor"; + reg = <0x68>; + status = "okay"; + }; +}; + +&ext_buck_vmd1 { + pinctrl-names = "default", "vmd1_sel_low", "vmd1_sel_high"; + + pinctrl-0 = <&vmd1_default>; + pinctrl-1 = <&vmd1_sel_low>; + pinctrl-2 = <&vmd1_sel_high>; +}; + +&pio { + vmd1_default: vmd10default { + }; + + vmd1_sel_low: vmd1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + vmd1_sel_high: vmd1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; diff --git a/arch/arm/boot/dts/KIICAA_POWER.dts b/arch/arm/boot/dts/KIICAA_POWER.dts new file mode 100644 index 0000000000000000000000000000000000000000..344aab2ee27d1ecf8bcdff439813789a5457e0aa --- /dev/null +++ b/arch/arm/boot/dts/KIICAA_POWER.dts @@ -0,0 +1,769 @@ + +/dts-v1/; + +#include "mt6580.dtsi" + +/ { + memory@80000000 { + device_type = "memory"; + reg = <0 0x80000000 0 0x1E800000>; + }; + + bus { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + }; + flashlight:flashlight { + compatible = "mediatek,mt6580-flashlight"; + }; + led@0 { + compatible = "mediatek,red"; + led_mode = <3>; + data = <2>; + pwm_config = <0 0 0 0 0>; + }; + led@1 { + compatible = "mediatek,green"; + led_mode = <3>; + data = <2>; + pwm_config = <0 0 0 0 0>; + }; + led@2 { + compatible = "mediatek,blue"; + led_mode = <3>; + data = <2>; + pwm_config = <0 0 0 0 0>; + }; + led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <3>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <6>; + }; + + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x84000000,0x400000 loglevel=8"; + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base = <0x9E800000>; + atag,videolfb-islcmfound = <1>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35590_AUO"; + }; + /* start sensor */ + cust_accel@0 { + compatible = "mediatek,kxtj2_1009_new"; + i2c_num = <2>; + i2c_addr = <0xe 0 0 0>; + direction = <0x0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + cust_accel@1 { + compatible = "mediatek,mxc400x"; + i2c_num = <0x2>; + i2c_addr = <0x15 0x0 0x0 0x0>; + direction = <0x0>; + power_id = <0xffff>; + power_vol = <0x0>; + firlen = <0x0>; + is_batch_supported = <0x0>; + }; + + cust_alsps@0 { + compatible = "mediatek,epl2182"; + i2c_num = <2>; + i2c_addr = <0x49 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als= <1>; + power_id = <0xffff>; + power_vol = <0>; + als_level = <0x0 0x148 0x35d 0x561 0xc35 0x1e29 0x1e57 0x314d 0x5a16 0x6f0e 0x81fa 0xb80c 0xe15e 0xe15e 0xffff>; + als_value = <0x0 0x85 0x130 0x1f6 0x3ec 0x7d5 0xbf2 0x138d 0x1f48 0x271a 0x2ee0 0x3e80 0x4e20 0x4e20 0x4e20 0x4e20>; + ps_threshold_high = <500>; + ps_threshold_low = <300>; + is_batch_supported_ps = <0x0>; + is_batch_supported_als = <0x0>; + }; + + /* end sensor */ + + mt-extmem@0 { + compatible = "mediatek,mt-extmem"; + }; +}; + +/* mmc start */ +&mmc0 { + clk_src = /bits/ 8 ; + bus-width = <8>; + max-frequency = <208000000>; + cap-mmc-highspeed; + msdc-sys-suspend; + mmc-hs200-1_8v; + non-removable; + pinctl = <&mmc0_pins_default>; + register_setting = <&mmc0_register_setting_default>; + host_function = /bits/ 8 ; + bootable; + status = "okay"; +}; + +&mmc1 { + clk_src = /bits/ 8 ; + bus-width = <4>; + max-frequency = <208000000>; + msdc-sys-suspend; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + pinctrl-names = "default","insert_cfg"; + pinctrl-0 = <&mmc1_pins_insert_default>; + pinctrl-1 = <&mmc1_pins_insert_cfg>; + pinctl = <&mmc1_pins_default>; + pinctl_sdr104 = <&mmc1_pins_sdr104>; + pinctl_sdr50 = <&mmc1_pins_sdr50>; + pinctl_ddr50 = <&mmc1_pins_ddr50>; + register_setting = <&mmc1_register_setting_default>; + host_function = /bits/ 8 ; + cd_level = /bits/ 8 ; + cd-gpios = <&pio 3 0>; + status = "okay"; + non-removable; +}; + +&pio { + mmc0_pins_default: mmc0@default { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <2>; + }; + pins_rst { + drive-strength = /bits/ 8 <2>; + }; + pins_ds { + drive-strength = /bits/ 8 <2>; + }; + }; + + mmc0_register_setting_default: mmc0@register_default { + dat0rddly = /bits/ 8 <0>; + dat1rddly = /bits/ 8 <0>; + dat2rddly = /bits/ 8 <0>; + dat3rddly = /bits/ 8 <0>; + dat4rddly = /bits/ 8 <0>; + dat5rddly = /bits/ 8 <0>; + dat6rddly = /bits/ 8 <0>; + dat7rddly = /bits/ 8 <0>; + datwrddly = /bits/ 8 <0>; + cmdrrddly = /bits/ 8 <0>; + cmdrddly = /bits/ 8 <0>; + cmd_edge = /bits/ 8 ; + rdata_edge = /bits/ 8 ; + wdata_edge = /bits/ 8 ; + + ett-hs200-cells = <12>; + ett-hs200-default = ; + }; + + mmc1_pins_default: mmc1@default { + pins_cmd { + drive-strength = /bits/ 8 <3>; + }; + pins_dat { + drive-strength = /bits/ 8 <3>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_insert_default: mmc1_ins_default { + }; + + mmc1_pins_insert_cfg: mmc1_ins_cfg { + pins_insert { + pins = ; + input-schmitt-enable =<1>; + slew-rate = <0>; + bias-pull-up =<00>; + }; + }; + + mmc1_pins_sdr104: mmc1@sdr104 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_sdr50: mmc1@sdr50 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_ddr50: mmc1@ddr50 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_register_setting_default: mmc1@register_default { + dat0rddly = /bits/ 8 <0>; + dat1rddly = /bits/ 8 <0>; + dat2rddly = /bits/ 8 <0>; + dat3rddly = /bits/ 8 <0>; + datwrddly = /bits/ 8 <0>; + cmdrrddly = /bits/ 8 <0>; + cmdrddly = /bits/ 8 <0>; + cmd_edge = /bits/ 8 ; + rdata_edge = /bits/ 8 ; + wdata_edge = /bits/ 8 ; + }; +}; +/* mmc end */ + +&pio { + alsps_intpin_cfg: alspspincfg { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + alsps_intpin_default: alspsdefaultcfg { + }; + gyro_intpin_cfg: gyropincfg { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + gyro_intpin_default: gyrodefaultcfg { + }; +}; +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; +&gyro { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x200 1 0x1F0 0x800 0x800 0x20>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <1>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 90 240 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; + /* ACCDET GPIO standardization ACC mode use */ + pinctrl-names = "default", "state_eint_as_int"; + pinctrl-0 = <&ACCDET_pins_default>; + pinctrl-1 = <&ACCDET_pins_eint_as_int>; + status = "okay"; +}; +&pio { + ACCDET_pins_default: eint0default { + }; + ACCDET_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; +}; +/*ACCDET END*/ +/* TOUCH GPIO standardization */ +&touch { + tpd-resolution = <720 1280>; + use-tpd-button = <1>; + tpd-key-num = <4>; + tpd-key-local= <139 158 217 172 0>; + tpd-key-dim-local = <160 2000 70 40 950 2000 70 40 200 2000 70 40 540 2000 70 40 0 0 0 0>; + tpd-max-touch-num = <2>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <93>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <15 15 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: toucheint5default { + }; + ctp_pins_eint_as_int: toucheint@5 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* AUDIO GPIO standardization */ +&audgpio { + + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow"; + pinctrl-0 = <&AUD_pins_default>; + pinctrl-1 = <&AUD_pins_pmicclk_mode0>; + pinctrl-2 = <&AUD_pins_pmicclk_mode1>; + pinctrl-3 = <&AUD_pins_extamp_high>; + pinctrl-4 = <&AUD_pins_extamp_low>; + pinctrl-5 = <&AUD_pins_extamp2_high>; + pinctrl-6 = <&AUD_pins_extamp2_low>; + status = "okay"; +}; +&pio { + AUD_pins_default: audiodefault { + }; + AUD_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + AUD_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + AUD_pins_extamp_high:extampouthigh { + + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + AUD_pins_extamp_low:extampoutlow { + + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + AUD_pins_extamp2_high:extamp2outhigh { + }; + + AUD_pins_extamp2_low:extamp2outlow { + }; + +}; +/* AUDIO end */ + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_pwm_test_pin_mux_gpio66: pwm_test_pin_mux_gpio66 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", + "lcm_rst_out0_gpio", "lcm_rst_out1_gpio", + "pwm_test_pin_mux_gpio66"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_pwm_test_pin_mux_gpio66>; + status = "okay"; +}; +/* DISPSYS GPIO standardization end */ +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ;/*GPIO_CAMERA_CMRST_PIN*/ + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ;/*GPIO_CAMERA_CMRST_PIN*/ + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ;/*GPIO_CAMERA_CMPDN_PIN*/ + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ;/*GPIO_CAMERA_CMPDN_PIN*/ + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ;/*GPIO_CAMERA_CMRST1_PIN*/ + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ;/*GPIO_CAMERA_CMRST1_PIN*/ + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ;/*GPIO_CAMERA_CMPDN1_PIN*/ + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ;/*GPIO_CAMERA_CMPDN1_PIN*/ + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam_ldo0_0: cam@0 { + }; + camera_pins_cam_ldo0_1: cam@1 { + }; + camera_pins_default: camdefault { + }; + camera_pins_cam1_gpio_serial: cam1serial@0{ + pins_cmd_dat { + pins = ; + }; + pins_cmd_dat1 { + pins = ; + }; + pins_cmd_dat2 { + pins = ; + }; + pins_cmd_dat3 { + pins = ; + }; + pins_cmd_dat4 { + pins = ; + }; + }; + camera_pins_cam1_gpio_mipi: cam1mipi@0{ + pins_cmd_dat { + pins = ; + }; + pins_cmd_dat1 { + pins = ; + }; + pins_cmd_dat2 { + pins = ; + }; + pins_cmd_dat3 { + pins = ; + }; + pins_cmd_dat4 { + pins = ; + }; + pins_cmd_dat5 { + pins = ; + }; + }; + camera_pins_cam_mclk1_enable: mclk1enable@0{ + pins_cmd_dat { + pins = ; + }; + }; + camera_pins_cam_mclk1_disable: mclk1disable@0{ + pins_cmd_dat { + pins = ; + }; + }; + camera_pins_cam_mclk2_enable: mclk2enable@0{ + pins_cmd_dat { + pins = ; + }; + }; + camera_pins_cam_mclk2_disable: mclk2disable@0{ + pins_cmd_dat { + pins = ; + }; + }; + + +}; +&kd_camera_hw1 { + pinctrl-names = "default", "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo0_0", "cam_ldo0_1", "cam1_gpio_serial", "cam1_gpio_mipi", + "cam_mclk1_enable","cam_mclk1_disable", + "cam_mclk2_enable","cam_mclk2_disable"; + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_cam_ldo0_0>; + pinctrl-10 = <&camera_pins_cam_ldo0_1>; + pinctrl-11 = <&camera_pins_cam1_gpio_serial>; + pinctrl-12 = <&camera_pins_cam1_gpio_mipi>; + pinctrl-13 = <&camera_pins_cam_mclk1_enable>; + pinctrl-14 = <&camera_pins_cam_mclk1_disable>; + pinctrl-15 = <&camera_pins_cam_mclk2_enable>; + pinctrl-16 = <&camera_pins_cam_mclk2_disable>; + + status = "okay"; + +}; +/* CAMERA GPIO end */ + +/* FLASHLIGHT GPIO standardization */ +&pio { + flashlight_pins_default: default { + }; + + flashlight_pins_hwen_high: hwen_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + flashlight_pins_hwen_low: hwen_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + +}; +&flashlight { + pinctrl-names = "default", "hwen_high", "hwen_low"; + pinctrl-0 = <&flashlight_pins_default>; + pinctrl-1 = <&flashlight_pins_hwen_high>; + pinctrl-2 = <&flashlight_pins_hwen_low>; + status = "okay"; + +}; +/* FLASHLIGHT GPIO end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + + }; + + gpslna_pins_init: gpslna@0 { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; + +}; +/* CONSYS end */ diff --git a/arch/arm/boot/dts/cust_mt6755_msdc.dtsi b/arch/arm/boot/dts/cust_mt6755_msdc.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..cb2251ed3bafa65705083c90233a95821b1ff648 --- /dev/null +++ b/arch/arm/boot/dts/cust_mt6755_msdc.dtsi @@ -0,0 +1,172 @@ +/********************************************** + *MT6755 MSDC DTSI File +********************************************/ + +&mmc0 { + clk_src = /bits/ 8 ; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + msdc-sys-suspend; + /*mmc-ddr-1_8v;*/ + mmc-hs200-1_8v; + mmc-hs400-1_8v; + non-removable; + pinctl = <&mmc0_pins_default>; + register_setting = <&mmc0_register_setting_default>; + host_function = /bits/ 8 ; + bootable; + status = "okay"; + vmmc-supply = <&mt_pmic_vemc_ldo_reg>; +}; + +&mmc1 { + clk_src = /bits/ 8 ; + bus-width = <4>; + max-frequency = <200000000>; + msdc-sys-suspend; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + /*sd-uhs-ddr50;*/ + pinctl = <&mmc1_pins_default>; + pinctl_sdr104 = <&mmc1_pins_sdr104>; + pinctl_sdr50 = <&mmc1_pins_sdr50>; + pinctl_ddr50 = <&mmc1_pins_ddr50>; + register_setting = <&mmc1_register_setting_default>; + host_function = /bits/ 8 ; + cd_level = /bits/ 8 ; + cd-gpios = <&pio 3 0>; + status = "okay"; + vmmc-supply = <&mt_pmic_vmch_ldo_reg>; + vqmmc-supply = <&mt_pmic_vmc_ldo_reg>; +}; + +&mmc2 { + clk_src = /bits/ 8 ; + bus-width = <4>; + max-frequency = <200000000>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; + non-removable; + pinctl = <&mmc2_pins_default>; + register_setting = <&mmc2_register_setting_default>; + host_function = /bits/ 8 ; + status = "disable"; +}; + +&pio { + mmc0_pins_default: mmc0@default { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <2>; + }; + pins_rst { + drive-strength = /bits/ 8 <2>; + }; + pins_ds { + drive-strength = /bits/ 8 <2>; + }; + }; + + mmc0_register_setting_default: mmc0@register_default { + datrddly = /bits/ 8 <0 0 0 0 0 0 0 0>; + datwrddly = /bits/ 8 <0>; + cmdrrddly = /bits/ 8 <0>; + cmdrddly = /bits/ 8 <0>; + cmd_edge = /bits/ 8 ; + rdata_edge = /bits/ 8 ; + wdata_edge = /bits/ 8 ; + }; + + mmc1_pins_default: mmc1@default { + pins_cmd { + drive-strength = /bits/ 8 <3>; + }; + pins_dat { + drive-strength = /bits/ 8 <3>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_sdr104: mmc1@sdr104 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_sdr50: mmc1@sdr50 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_ddr50: mmc1@ddr50 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_register_setting_default: mmc1@register_default { + datrddly = /bits/ 8 <0 0 0 0 0 0 0 0>; + datwrddly = /bits/ 8 <0>; + cmdrrddly = /bits/ 8 <0>; + cmdrddly = /bits/ 8 <0>; + cmd_edge = /bits/ 8 ; + rdata_edge = /bits/ 8 ; + wdata_edge = /bits/ 8 ; + }; + + mmc2_pins_default: mmc2@default { + pins_cmd { + drive-strength = /bits/ 8 <1>; + }; + pins_dat { + drive-strength = /bits/ 8 <1>; + }; + pins_clk { + drive-strength = /bits/ 8 <1>; + }; + }; + + mmc2_register_setting_default: mmc2@register_default { + datrddly = /bits/ 8 <0 0 0 0 0 0 0 0>; + datwrddly = /bits/ 8 <0>; + cmdrrddly = /bits/ 8 <0>; + cmdrddly = /bits/ 8 <0>; + cmd_edge = /bits/ 8 ; + rdata_edge = /bits/ 8 ; + wdata_edge = /bits/ 8 ; + }; +}; diff --git a/arch/arm/boot/dts/mt6755-pinfunc.h b/arch/arm/boot/dts/mt6755-pinfunc.h new file mode 100644 index 0000000000000000000000000000000000000000..fed390c3c9f1a71866074f22e3e47a1986cd80e6 --- /dev/null +++ b/arch/arm/boot/dts/mt6755-pinfunc.h @@ -0,0 +1,1033 @@ +/* + * Generated by MTK SP DrvGen Version 03.13.6 for MT6755. Copyright MediaTek Inc. (C) 2013. + * Wed Jul 22 21:04:21 2015 + * Do Not Modify the File. + */ + +/************************* + * GPIO PINFUNC File +*************************/ + +#ifndef __DTS_MT6755_PINFUNC_H +#define __DTS_MT6755_PINFUNC_H + +#include "mt65xx.h" + +#define PINMUX_GPIO0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) +#define PINMUX_GPIO0__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(0) | 2) +#define PINMUX_GPIO0__FUNC_CLKM0 (MTK_PIN_NO(0) | 3) +#define PINMUX_GPIO0__FUNC_IDDIG (MTK_PIN_NO(0) | 4) +#define PINMUX_GPIO0__FUNC_C2K_EINT0 (MTK_PIN_NO(0) | 5) +#define PINMUX_GPIO0__FUNC_I2S3_MCK (MTK_PIN_NO(0) | 6) + +#define PINMUX_GPIO1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0) +#define PINMUX_GPIO1__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(1) | 2) +#define PINMUX_GPIO1__FUNC_CLKM1 (MTK_PIN_NO(1) | 3) +#define PINMUX_GPIO1__FUNC_USB_DRVVBUS (MTK_PIN_NO(1) | 4) +#define PINMUX_GPIO1__FUNC_C2K_EINT1 (MTK_PIN_NO(1) | 5) +#define PINMUX_GPIO1__FUNC_I2S3_BCK (MTK_PIN_NO(1) | 6) + +#define PINMUX_GPIO2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0) +#define PINMUX_GPIO2__FUNC_CMFLASH (MTK_PIN_NO(2) | 1) +#define PINMUX_GPIO2__FUNC_UTXD1 (MTK_PIN_NO(2) | 2) +#define PINMUX_GPIO2__FUNC_CLKM2 (MTK_PIN_NO(2) | 3) +#define PINMUX_GPIO2__FUNC_MD_URXD2 (MTK_PIN_NO(2) | 4) +#define PINMUX_GPIO2__FUNC_C2K_UTXD1 (MTK_PIN_NO(2) | 5) +#define PINMUX_GPIO2__FUNC_I2S3_LRCK (MTK_PIN_NO(2) | 6) + +#define PINMUX_GPIO3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0) +#define PINMUX_GPIO3__FUNC_PWM_A (MTK_PIN_NO(3) | 1) +#define PINMUX_GPIO3__FUNC_URXD1 (MTK_PIN_NO(3) | 2) +#define PINMUX_GPIO3__FUNC_CLKM3 (MTK_PIN_NO(3) | 3) +#define PINMUX_GPIO3__FUNC_MD_UTXD2 (MTK_PIN_NO(3) | 4) +#define PINMUX_GPIO3__FUNC_C2K_URXD1 (MTK_PIN_NO(3) | 5) +#define PINMUX_GPIO3__FUNC_I2S3_DO (MTK_PIN_NO(3) | 6) +#define PINMUX_GPIO3__FUNC_SPI1_B_MI (MTK_PIN_NO(3) | 7) + +#define PINMUX_GPIO4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0) +#define PINMUX_GPIO4__FUNC_PWM_B (MTK_PIN_NO(4) | 1) +#define PINMUX_GPIO4__FUNC_I2S0_MCK (MTK_PIN_NO(4) | 2) +#define PINMUX_GPIO4__FUNC_UCTS0 (MTK_PIN_NO(4) | 3) +#define PINMUX_GPIO4__FUNC_MD_URXD1 (MTK_PIN_NO(4) | 4) +#define PINMUX_GPIO4__FUNC_C2K_UTXD0 (MTK_PIN_NO(4) | 5) +#define PINMUX_GPIO4__FUNC_ANT_SEL3 (MTK_PIN_NO(4) | 6) +#define PINMUX_GPIO4__FUNC_SPI1_B_MI (MTK_PIN_NO(4) | 7) + +#define PINMUX_GPIO5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0) +#define PINMUX_GPIO5__FUNC_PWM_C (MTK_PIN_NO(5) | 1) +#define PINMUX_GPIO5__FUNC_I2S0_BCK (MTK_PIN_NO(5) | 2) +#define PINMUX_GPIO5__FUNC_URTS0 (MTK_PIN_NO(5) | 3) +#define PINMUX_GPIO5__FUNC_MD_UTXD1 (MTK_PIN_NO(5) | 4) +#define PINMUX_GPIO5__FUNC_C2K_URXD0 (MTK_PIN_NO(5) | 5) +#define PINMUX_GPIO5__FUNC_ANT_SEL4 (MTK_PIN_NO(5) | 6) +#define PINMUX_GPIO5__FUNC_SPI1_B_CSB (MTK_PIN_NO(5) | 7) + +#define PINMUX_GPIO6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0) +#define PINMUX_GPIO6__FUNC_IRTX_OUT (MTK_PIN_NO(6) | 1) +#define PINMUX_GPIO6__FUNC_I2S0_LRCK (MTK_PIN_NO(6) | 2) +#define PINMUX_GPIO6__FUNC_IDDIG (MTK_PIN_NO(6) | 3) +#define PINMUX_GPIO6__FUNC_MD_URXD0 (MTK_PIN_NO(6) | 4) +#define PINMUX_GPIO6__FUNC_SDA0 (MTK_PIN_NO(6) | 5) +#define PINMUX_GPIO6__FUNC_ANT_SEL5 (MTK_PIN_NO(6) | 6) +#define PINMUX_GPIO6__FUNC_SPI1_B_MO (MTK_PIN_NO(6) | 7) + +#define PINMUX_GPIO7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0) +#define PINMUX_GPIO7__FUNC_IRTX_OUT (MTK_PIN_NO(7) | 1) +#define PINMUX_GPIO7__FUNC_I2S0_DI (MTK_PIN_NO(7) | 2) +#define PINMUX_GPIO7__FUNC_USB_DRVVBUS (MTK_PIN_NO(7) | 3) +#define PINMUX_GPIO7__FUNC_MD_UTXD0 (MTK_PIN_NO(7) | 4) +#define PINMUX_GPIO7__FUNC_SCL0 (MTK_PIN_NO(7) | 5) +#define PINMUX_GPIO7__FUNC_PCC_PPC_IO (MTK_PIN_NO(7) | 6) +#define PINMUX_GPIO7__FUNC_SPI1_B_CLK (MTK_PIN_NO(7) | 7) + +#define PINMUX_GPIO8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0) +#define PINMUX_GPIO8__FUNC_PWM_A (MTK_PIN_NO(8) | 1) +#define PINMUX_GPIO8__FUNC_PCC_PPC_IO (MTK_PIN_NO(8) | 2) +#define PINMUX_GPIO8__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(8) | 4) +#define PINMUX_GPIO8__FUNC_C2K_DM_JTINTP (MTK_PIN_NO(8) | 5) +#define PINMUX_GPIO8__FUNC_IO_JTAG_TRSTN (MTK_PIN_NO(8) | 6) +#define PINMUX_GPIO8__FUNC_DBG_MON_A44 (MTK_PIN_NO(8) | 7) + +#define PINMUX_GPIO9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0) +#define PINMUX_GPIO9__FUNC_PWM_B (MTK_PIN_NO(9) | 1) +#define PINMUX_GPIO9__FUNC_UCTS1 (MTK_PIN_NO(9) | 2) +#define PINMUX_GPIO9__FUNC_DAP_SIB1_SWD (MTK_PIN_NO(9) | 3) +#define PINMUX_GPIO9__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(9) | 4) +#define PINMUX_GPIO9__FUNC_IRTX_OUT (MTK_PIN_NO(9) | 5) +#define PINMUX_GPIO9__FUNC_DBG_MON_A45 (MTK_PIN_NO(9) | 7) + +#define PINMUX_GPIO10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0) +#define PINMUX_GPIO10__FUNC_PWM_C (MTK_PIN_NO(10) | 1) +#define PINMUX_GPIO10__FUNC_URTS1 (MTK_PIN_NO(10) | 2) +#define PINMUX_GPIO10__FUNC_DAP_SIB1_SWCK (MTK_PIN_NO(10) | 3) +#define PINMUX_GPIO10__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(10) | 4) +#define PINMUX_GPIO10__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(10) | 5) +#define PINMUX_GPIO10__FUNC_DBG_MON_A46 (MTK_PIN_NO(10) | 7) + +#define PINMUX_GPIO11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0) +#define PINMUX_GPIO11__FUNC_IRTX_OUT (MTK_PIN_NO(11) | 1) +#define PINMUX_GPIO11__FUNC_IDDIG (MTK_PIN_NO(11) | 2) +#define PINMUX_GPIO11__FUNC_I2S1_MCK (MTK_PIN_NO(11) | 3) +#define PINMUX_GPIO11__FUNC_PWM_B (MTK_PIN_NO(11) | 4) +#define PINMUX_GPIO11__FUNC_CLKM0 (MTK_PIN_NO(11) | 5) +#define PINMUX_GPIO11__FUNC_SRCLKENAI1 (MTK_PIN_NO(11) | 6) + +#define PINMUX_GPIO12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0) +#define PINMUX_GPIO12__FUNC_IRTX_OUT (MTK_PIN_NO(12) | 1) +#define PINMUX_GPIO12__FUNC_USB_DRVVBUS (MTK_PIN_NO(12) | 2) +#define PINMUX_GPIO12__FUNC_I2S2_DI (MTK_PIN_NO(12) | 3) +#define PINMUX_GPIO12__FUNC_PWM_C (MTK_PIN_NO(12) | 4) +#define PINMUX_GPIO12__FUNC_CLKM1 (MTK_PIN_NO(12) | 5) +#define PINMUX_GPIO12__FUNC_CMFLASH (MTK_PIN_NO(12) | 6) + +#define PINMUX_GPIO13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0) +#define PINMUX_GPIO13__FUNC_DPI_D0 (MTK_PIN_NO(13) | 1) +#define PINMUX_GPIO13__FUNC_MRG_SYNC (MTK_PIN_NO(13) | 2) +#define PINMUX_GPIO13__FUNC_PCM0_SYNC (MTK_PIN_NO(13) | 3) +#define PINMUX_GPIO13__FUNC_MD_URXD0 (MTK_PIN_NO(13) | 4) +#define PINMUX_GPIO13__FUNC_C2K_EINT0 (MTK_PIN_NO(13) | 5) +#define PINMUX_GPIO13__FUNC_I2S0_MCK (MTK_PIN_NO(13) | 6) +#define PINMUX_GPIO13__FUNC_DBG_MON_A19 (MTK_PIN_NO(13) | 7) + +#define PINMUX_GPIO14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0) +#define PINMUX_GPIO14__FUNC_DPI_D1 (MTK_PIN_NO(14) | 1) +#define PINMUX_GPIO14__FUNC_MRG_CLK (MTK_PIN_NO(14) | 2) +#define PINMUX_GPIO14__FUNC_PCM0_CLK (MTK_PIN_NO(14) | 3) +#define PINMUX_GPIO14__FUNC_MD_UTXD0 (MTK_PIN_NO(14) | 4) +#define PINMUX_GPIO14__FUNC_C2K_EINT1 (MTK_PIN_NO(14) | 5) +#define PINMUX_GPIO14__FUNC_I2S0_BCK (MTK_PIN_NO(14) | 6) +#define PINMUX_GPIO14__FUNC_DBG_MON_A20 (MTK_PIN_NO(14) | 7) + +#define PINMUX_GPIO15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0) +#define PINMUX_GPIO15__FUNC_DPI_D2 (MTK_PIN_NO(15) | 1) +#define PINMUX_GPIO15__FUNC_MRG_DO (MTK_PIN_NO(15) | 2) +#define PINMUX_GPIO15__FUNC_PCM0_DO (MTK_PIN_NO(15) | 3) +#define PINMUX_GPIO15__FUNC_MD_URXD1 (MTK_PIN_NO(15) | 4) +#define PINMUX_GPIO15__FUNC_C2K_DM_EINT0 (MTK_PIN_NO(15) | 5) +#define PINMUX_GPIO15__FUNC_I2S0_LRCK (MTK_PIN_NO(15) | 6) +#define PINMUX_GPIO15__FUNC_DBG_MON_A21 (MTK_PIN_NO(15) | 7) + +#define PINMUX_GPIO16__FUNC_GPIO16 (MTK_PIN_NO(16) | 0) +#define PINMUX_GPIO16__FUNC_DPI_D3 (MTK_PIN_NO(16) | 1) +#define PINMUX_GPIO16__FUNC_MRG_DI (MTK_PIN_NO(16) | 2) +#define PINMUX_GPIO16__FUNC_PCM0_DI (MTK_PIN_NO(16) | 3) +#define PINMUX_GPIO16__FUNC_MD_UTXD1 (MTK_PIN_NO(16) | 4) +#define PINMUX_GPIO16__FUNC_C2K_DM_EINT1 (MTK_PIN_NO(16) | 5) +#define PINMUX_GPIO16__FUNC_I2S0_DI (MTK_PIN_NO(16) | 6) +#define PINMUX_GPIO16__FUNC_DBG_MON_A22 (MTK_PIN_NO(16) | 7) + +#define PINMUX_GPIO17__FUNC_GPIO17 (MTK_PIN_NO(17) | 0) +#define PINMUX_GPIO17__FUNC_DPI_D4 (MTK_PIN_NO(17) | 1) +#define PINMUX_GPIO17__FUNC_UCTS1 (MTK_PIN_NO(17) | 2) +#define PINMUX_GPIO17__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(17) | 3) +#define PINMUX_GPIO17__FUNC_MD_URXD2 (MTK_PIN_NO(17) | 4) +#define PINMUX_GPIO17__FUNC_C2K_URXD0 (MTK_PIN_NO(17) | 5) +#define PINMUX_GPIO17__FUNC_I2S1_MCK (MTK_PIN_NO(17) | 6) +#define PINMUX_GPIO17__FUNC_DBG_MON_A23 (MTK_PIN_NO(17) | 7) + +#define PINMUX_GPIO18__FUNC_GPIO18 (MTK_PIN_NO(18) | 0) +#define PINMUX_GPIO18__FUNC_DPI_D5 (MTK_PIN_NO(18) | 1) +#define PINMUX_GPIO18__FUNC_URTS1 (MTK_PIN_NO(18) | 2) +#define PINMUX_GPIO18__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(18) | 3) +#define PINMUX_GPIO18__FUNC_MD_UTXD2 (MTK_PIN_NO(18) | 4) +#define PINMUX_GPIO18__FUNC_C2K_UTXD0 (MTK_PIN_NO(18) | 5) +#define PINMUX_GPIO18__FUNC_I2S1_BCK (MTK_PIN_NO(18) | 6) +#define PINMUX_GPIO18__FUNC_DBG_MON_A24 (MTK_PIN_NO(18) | 7) + +#define PINMUX_GPIO19__FUNC_GPIO19 (MTK_PIN_NO(19) | 0) +#define PINMUX_GPIO19__FUNC_DPI_D6 (MTK_PIN_NO(19) | 1) +#define PINMUX_GPIO19__FUNC_URXD1 (MTK_PIN_NO(19) | 2) +#define PINMUX_GPIO19__FUNC_CONN_MCU_TDO (MTK_PIN_NO(19) | 3) +#define PINMUX_GPIO19__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(19) | 4) +#define PINMUX_GPIO19__FUNC_I2S1_LRCK (MTK_PIN_NO(19) | 6) +#define PINMUX_GPIO19__FUNC_DBG_MON_A25 (MTK_PIN_NO(19) | 7) + +#define PINMUX_GPIO20__FUNC_GPIO20 (MTK_PIN_NO(20) | 0) +#define PINMUX_GPIO20__FUNC_DPI_D7 (MTK_PIN_NO(20) | 1) +#define PINMUX_GPIO20__FUNC_UTXD1 (MTK_PIN_NO(20) | 2) +#define PINMUX_GPIO20__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(20) | 3) +#define PINMUX_GPIO20__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(20) | 4) +#define PINMUX_GPIO20__FUNC_I2S1_DO (MTK_PIN_NO(20) | 6) +#define PINMUX_GPIO20__FUNC_DBG_MON_A26 (MTK_PIN_NO(20) | 7) + +#define PINMUX_GPIO21__FUNC_GPIO21 (MTK_PIN_NO(21) | 0) +#define PINMUX_GPIO21__FUNC_DPI_D8 (MTK_PIN_NO(21) | 1) +#define PINMUX_GPIO21__FUNC_SRCLKENAI1 (MTK_PIN_NO(21) | 2) +#define PINMUX_GPIO21__FUNC_CONN_MCU_TMS (MTK_PIN_NO(21) | 3) +#define PINMUX_GPIO21__FUNC_DAP_SIB1_SWD (MTK_PIN_NO(21) | 4) +#define PINMUX_GPIO21__FUNC_CONN_MCU_AICE_TMSC (MTK_PIN_NO(21) | 5) +#define PINMUX_GPIO21__FUNC_I2S2_MCK (MTK_PIN_NO(21) | 6) +#define PINMUX_GPIO21__FUNC_DBG_MON_A27 (MTK_PIN_NO(21) | 7) + +#define PINMUX_GPIO22__FUNC_GPIO22 (MTK_PIN_NO(22) | 0) +#define PINMUX_GPIO22__FUNC_DPI_D9 (MTK_PIN_NO(22) | 1) +#define PINMUX_GPIO22__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(22) | 2) +#define PINMUX_GPIO22__FUNC_CONN_MCU_TCK (MTK_PIN_NO(22) | 3) +#define PINMUX_GPIO22__FUNC_DAP_SIB1_SWCK (MTK_PIN_NO(22) | 4) +#define PINMUX_GPIO22__FUNC_CONN_MCU_AICE_TCKC (MTK_PIN_NO(22) | 5) +#define PINMUX_GPIO22__FUNC_I2S2_BCK (MTK_PIN_NO(22) | 6) +#define PINMUX_GPIO22__FUNC_DBG_MON_A28 (MTK_PIN_NO(22) | 7) + +#define PINMUX_GPIO23__FUNC_GPIO23 (MTK_PIN_NO(23) | 0) +#define PINMUX_GPIO23__FUNC_DPI_D10 (MTK_PIN_NO(23) | 1) +#define PINMUX_GPIO23__FUNC_IDDIG (MTK_PIN_NO(23) | 2) +#define PINMUX_GPIO23__FUNC_CONN_MCU_TDI (MTK_PIN_NO(23) | 3) +#define PINMUX_GPIO23__FUNC_PWM_B (MTK_PIN_NO(23) | 5) +#define PINMUX_GPIO23__FUNC_I2S2_LRCK (MTK_PIN_NO(23) | 6) +#define PINMUX_GPIO23__FUNC_DBG_MON_A29 (MTK_PIN_NO(23) | 7) + +#define PINMUX_GPIO24__FUNC_GPIO24 (MTK_PIN_NO(24) | 0) +#define PINMUX_GPIO24__FUNC_DPI_D11 (MTK_PIN_NO(24) | 1) +#define PINMUX_GPIO24__FUNC_USB_DRVVBUS (MTK_PIN_NO(24) | 2) +#define PINMUX_GPIO24__FUNC_CONN_DSP_JCK (MTK_PIN_NO(24) | 3) +#define PINMUX_GPIO24__FUNC_SPI1_A_MI (MTK_PIN_NO(24) | 4) +#define PINMUX_GPIO24__FUNC_PWM_C (MTK_PIN_NO(24) | 5) +#define PINMUX_GPIO24__FUNC_I2S2_DI (MTK_PIN_NO(24) | 6) +#define PINMUX_GPIO24__FUNC_DBG_MON_A30 (MTK_PIN_NO(24) | 7) + +#define PINMUX_GPIO25__FUNC_GPIO25 (MTK_PIN_NO(25) | 0) +#define PINMUX_GPIO25__FUNC_DPI_HSYNC (MTK_PIN_NO(25) | 1) +#define PINMUX_GPIO25__FUNC_SPI1_A_MI (MTK_PIN_NO(25) | 2) +#define PINMUX_GPIO25__FUNC_CONN_DSP_JMS (MTK_PIN_NO(25) | 3) +#define PINMUX_GPIO25__FUNC_CLKM0 (MTK_PIN_NO(25) | 4) +#define PINMUX_GPIO25__FUNC_C2K_UTXD1 (MTK_PIN_NO(25) | 5) +#define PINMUX_GPIO25__FUNC_I2S3_MCK (MTK_PIN_NO(25) | 6) +#define PINMUX_GPIO25__FUNC_DBG_MON_A31 (MTK_PIN_NO(25) | 7) + +#define PINMUX_GPIO26__FUNC_GPIO26 (MTK_PIN_NO(26) | 0) +#define PINMUX_GPIO26__FUNC_DPI_VSYNC (MTK_PIN_NO(26) | 1) +#define PINMUX_GPIO26__FUNC_SPI1_A_CSB (MTK_PIN_NO(26) | 2) +#define PINMUX_GPIO26__FUNC_CONN_DSP_JDI (MTK_PIN_NO(26) | 3) +#define PINMUX_GPIO26__FUNC_CLKM1 (MTK_PIN_NO(26) | 4) +#define PINMUX_GPIO26__FUNC_C2K_URXD1 (MTK_PIN_NO(26) | 5) +#define PINMUX_GPIO26__FUNC_I2S3_BCK (MTK_PIN_NO(26) | 6) +#define PINMUX_GPIO26__FUNC_DBG_MON_A32 (MTK_PIN_NO(26) | 7) + +#define PINMUX_GPIO27__FUNC_GPIO27 (MTK_PIN_NO(27) | 0) +#define PINMUX_GPIO27__FUNC_DPI_DE (MTK_PIN_NO(27) | 1) +#define PINMUX_GPIO27__FUNC_SPI1_A_MO (MTK_PIN_NO(27) | 2) +#define PINMUX_GPIO27__FUNC_CONN_DSP_JDO (MTK_PIN_NO(27) | 3) +#define PINMUX_GPIO27__FUNC_CLKM2 (MTK_PIN_NO(27) | 4) +#define PINMUX_GPIO27__FUNC_C2K_DM_EINT2 (MTK_PIN_NO(27) | 5) +#define PINMUX_GPIO27__FUNC_I2S3_LRCK (MTK_PIN_NO(27) | 6) +#define PINMUX_GPIO27__FUNC_DBG_MON_A33 (MTK_PIN_NO(27) | 7) + +#define PINMUX_GPIO28__FUNC_GPIO28 (MTK_PIN_NO(28) | 0) +#define PINMUX_GPIO28__FUNC_DPI_CK (MTK_PIN_NO(28) | 1) +#define PINMUX_GPIO28__FUNC_SPI1_A_CLK (MTK_PIN_NO(28) | 2) +#define PINMUX_GPIO28__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(28) | 3) +#define PINMUX_GPIO28__FUNC_CLKM3 (MTK_PIN_NO(28) | 4) +#define PINMUX_GPIO28__FUNC_C2K_DM_EINT3 (MTK_PIN_NO(28) | 5) +#define PINMUX_GPIO28__FUNC_I2S3_DO (MTK_PIN_NO(28) | 6) +#define PINMUX_GPIO28__FUNC_DBG_MON_A34 (MTK_PIN_NO(28) | 7) + +#define PINMUX_GPIO29__FUNC_GPIO29 (MTK_PIN_NO(29) | 0) +#define PINMUX_GPIO29__FUNC_SRCLKENA1 (MTK_PIN_NO(29) | 1) + +#define PINMUX_GPIO30__FUNC_GPIO30 (MTK_PIN_NO(30) | 0) +#define PINMUX_GPIO30__FUNC_MSDC1_CLK (MTK_PIN_NO(30) | 1) +#define PINMUX_GPIO30__FUNC_IO_JTAG_TCK (MTK_PIN_NO(30) | 2) +#define PINMUX_GPIO30__FUNC_CONN_DSP_JCK (MTK_PIN_NO(30) | 4) +#define PINMUX_GPIO30__FUNC_C2K_DM_OTCK (MTK_PIN_NO(30) | 5) +#define PINMUX_GPIO30__FUNC_C2K_TCK (MTK_PIN_NO(30) | 6) +#define PINMUX_GPIO30__FUNC_DBG_MON_A53 (MTK_PIN_NO(30) | 7) + +#define PINMUX_GPIO31__FUNC_GPIO31 (MTK_PIN_NO(31) | 0) +#define PINMUX_GPIO31__FUNC_MSDC1_DAT3 (MTK_PIN_NO(31) | 1) +#define PINMUX_GPIO31__FUNC_DAP_SIB1_SWD (MTK_PIN_NO(31) | 3) +#define PINMUX_GPIO31__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(31) | 4) +#define PINMUX_GPIO31__FUNC_C2K_DM_JTINTP (MTK_PIN_NO(31) | 5) +#define PINMUX_GPIO31__FUNC_C2K_RTCK (MTK_PIN_NO(31) | 6) +#define PINMUX_GPIO31__FUNC_DBG_MON_A54 (MTK_PIN_NO(31) | 7) + +#define PINMUX_GPIO32__FUNC_GPIO32 (MTK_PIN_NO(32) | 0) +#define PINMUX_GPIO32__FUNC_MSDC1_CMD (MTK_PIN_NO(32) | 1) +#define PINMUX_GPIO32__FUNC_IO_JTAG_TMS (MTK_PIN_NO(32) | 2) +#define PINMUX_GPIO32__FUNC_CONN_DSP_JMS (MTK_PIN_NO(32) | 4) +#define PINMUX_GPIO32__FUNC_C2K_DM_OTMS (MTK_PIN_NO(32) | 5) +#define PINMUX_GPIO32__FUNC_C2K_TMS (MTK_PIN_NO(32) | 6) +#define PINMUX_GPIO32__FUNC_DBG_MON_A55 (MTK_PIN_NO(32) | 7) + +#define PINMUX_GPIO33__FUNC_GPIO33 (MTK_PIN_NO(33) | 0) +#define PINMUX_GPIO33__FUNC_MSDC1_DAT0 (MTK_PIN_NO(33) | 1) +#define PINMUX_GPIO33__FUNC_IO_JTAG_TDI (MTK_PIN_NO(33) | 2) +#define PINMUX_GPIO33__FUNC_CONN_DSP_JDI (MTK_PIN_NO(33) | 4) +#define PINMUX_GPIO33__FUNC_C2K_DM_OTDI (MTK_PIN_NO(33) | 5) +#define PINMUX_GPIO33__FUNC_C2K_TDI (MTK_PIN_NO(33) | 6) +#define PINMUX_GPIO33__FUNC_DBG_MON_A56 (MTK_PIN_NO(33) | 7) + +#define PINMUX_GPIO34__FUNC_GPIO34 (MTK_PIN_NO(34) | 0) +#define PINMUX_GPIO34__FUNC_MSDC1_DAT2 (MTK_PIN_NO(34) | 1) +#define PINMUX_GPIO34__FUNC_IO_JTAG_TRSTN (MTK_PIN_NO(34) | 2) +#define PINMUX_GPIO34__FUNC_DAP_SIB1_SWCK (MTK_PIN_NO(34) | 5) +#define PINMUX_GPIO34__FUNC_C2K_NTRST (MTK_PIN_NO(34) | 6) +#define PINMUX_GPIO34__FUNC_DBG_MON_A57 (MTK_PIN_NO(34) | 7) + +#define PINMUX_GPIO35__FUNC_GPIO35 (MTK_PIN_NO(35) | 0) +#define PINMUX_GPIO35__FUNC_MSDC1_DAT1 (MTK_PIN_NO(35) | 1) +#define PINMUX_GPIO35__FUNC_IO_JTAG_TDO (MTK_PIN_NO(35) | 2) +#define PINMUX_GPIO35__FUNC_CONN_DSP_JDO (MTK_PIN_NO(35) | 4) +#define PINMUX_GPIO35__FUNC_C2K_DM_OTDO (MTK_PIN_NO(35) | 5) +#define PINMUX_GPIO35__FUNC_C2K_TDO (MTK_PIN_NO(35) | 6) +#define PINMUX_GPIO35__FUNC_DBG_MON_A58 (MTK_PIN_NO(35) | 7) + +#define PINMUX_GPIO36__FUNC_GPIO36 (MTK_PIN_NO(36) | 0) +#define PINMUX_GPIO36__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(36) | 1) +#define PINMUX_GPIO36__FUNC_MD1_SIM1_SIO (MTK_PIN_NO(36) | 3) +#define PINMUX_GPIO36__FUNC_C2K_UIM0_IO (MTK_PIN_NO(36) | 5) +#define PINMUX_GPIO36__FUNC_C2K_UIM1_IO (MTK_PIN_NO(36) | 6) +#define PINMUX_GPIO36__FUNC_DBG_MON_A38 (MTK_PIN_NO(36) | 7) + +#define PINMUX_GPIO37__FUNC_GPIO37 (MTK_PIN_NO(37) | 0) +#define PINMUX_GPIO37__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(37) | 1) +#define PINMUX_GPIO37__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(37) | 3) +#define PINMUX_GPIO37__FUNC_C2K_UIM0_RST (MTK_PIN_NO(37) | 5) +#define PINMUX_GPIO37__FUNC_C2K_UIM1_RST (MTK_PIN_NO(37) | 6) +#define PINMUX_GPIO37__FUNC_DBG_MON_A39 (MTK_PIN_NO(37) | 7) + +#define PINMUX_GPIO38__FUNC_GPIO38 (MTK_PIN_NO(38) | 0) +#define PINMUX_GPIO38__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(38) | 1) +#define PINMUX_GPIO38__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(38) | 3) +#define PINMUX_GPIO38__FUNC_C2K_UIM0_CLK (MTK_PIN_NO(38) | 5) +#define PINMUX_GPIO38__FUNC_C2K_UIM1_CLK (MTK_PIN_NO(38) | 6) +#define PINMUX_GPIO38__FUNC_DBG_MON_A40 (MTK_PIN_NO(38) | 7) + +#define PINMUX_GPIO39__FUNC_GPIO39 (MTK_PIN_NO(39) | 0) +#define PINMUX_GPIO39__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(39) | 1) +#define PINMUX_GPIO39__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(39) | 3) +#define PINMUX_GPIO39__FUNC_C2K_UIM0_CLK (MTK_PIN_NO(39) | 5) +#define PINMUX_GPIO39__FUNC_C2K_UIM1_CLK (MTK_PIN_NO(39) | 6) +#define PINMUX_GPIO39__FUNC_DBG_MON_A41 (MTK_PIN_NO(39) | 7) + +#define PINMUX_GPIO40__FUNC_GPIO40 (MTK_PIN_NO(40) | 0) +#define PINMUX_GPIO40__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(40) | 1) +#define PINMUX_GPIO40__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(40) | 3) +#define PINMUX_GPIO40__FUNC_C2K_UIM0_RST (MTK_PIN_NO(40) | 5) +#define PINMUX_GPIO40__FUNC_C2K_UIM1_RST (MTK_PIN_NO(40) | 6) +#define PINMUX_GPIO40__FUNC_DBG_MON_A42 (MTK_PIN_NO(40) | 7) + +#define PINMUX_GPIO41__FUNC_GPIO41 (MTK_PIN_NO(41) | 0) +#define PINMUX_GPIO41__FUNC_MD1_SIM1_SIO (MTK_PIN_NO(41) | 1) +#define PINMUX_GPIO41__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(41) | 3) +#define PINMUX_GPIO41__FUNC_C2K_UIM0_IO (MTK_PIN_NO(41) | 5) +#define PINMUX_GPIO41__FUNC_C2K_UIM1_IO (MTK_PIN_NO(41) | 6) +#define PINMUX_GPIO41__FUNC_DBG_MON_A43 (MTK_PIN_NO(41) | 7) + +#define PINMUX_GPIO42__FUNC_GPIO42 (MTK_PIN_NO(42) | 0) +#define PINMUX_GPIO42__FUNC_IDDIG (MTK_PIN_NO(42) | 1) +#define PINMUX_GPIO42__FUNC_URXD1 (MTK_PIN_NO(42) | 2) +#define PINMUX_GPIO42__FUNC_UCTS0 (MTK_PIN_NO(42) | 3) +#define PINMUX_GPIO42__FUNC_SDA1 (MTK_PIN_NO(42) | 4) +#define PINMUX_GPIO42__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(42) | 5) +#define PINMUX_GPIO42__FUNC_KPCOL2 (MTK_PIN_NO(42) | 6) +#define PINMUX_GPIO42__FUNC_DBG_MON_A12 (MTK_PIN_NO(42) | 7) + +#define PINMUX_GPIO43__FUNC_GPIO43 (MTK_PIN_NO(43) | 0) +#define PINMUX_GPIO43__FUNC_USB_DRVVBUS (MTK_PIN_NO(43) | 1) +#define PINMUX_GPIO43__FUNC_UTXD1 (MTK_PIN_NO(43) | 2) +#define PINMUX_GPIO43__FUNC_URTS0 (MTK_PIN_NO(43) | 3) +#define PINMUX_GPIO43__FUNC_SCL1 (MTK_PIN_NO(43) | 4) +#define PINMUX_GPIO43__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(43) | 5) +#define PINMUX_GPIO43__FUNC_KPROW2 (MTK_PIN_NO(43) | 6) +#define PINMUX_GPIO43__FUNC_DBG_MON_A13 (MTK_PIN_NO(43) | 7) + +#define PINMUX_GPIO44__FUNC_GPIO44 (MTK_PIN_NO(44) | 0) +#define PINMUX_GPIO44__FUNC_DSI_TE (MTK_PIN_NO(44) | 1) +#define PINMUX_GPIO44__FUNC_DBG_MON_A15 (MTK_PIN_NO(44) | 7) + +#define PINMUX_GPIO45__FUNC_GPIO45 (MTK_PIN_NO(45) | 0) +#define PINMUX_GPIO45__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(45) | 1) +#define PINMUX_GPIO45__FUNC_URXD1 (MTK_PIN_NO(45) | 2) +#define PINMUX_GPIO45__FUNC_UCTS1 (MTK_PIN_NO(45) | 3) +#define PINMUX_GPIO45__FUNC_CLKM0 (MTK_PIN_NO(45) | 4) +#define PINMUX_GPIO45__FUNC_IDDIG (MTK_PIN_NO(45) | 6) +#define PINMUX_GPIO45__FUNC_DBG_MON_A17 (MTK_PIN_NO(45) | 7) + +#define PINMUX_GPIO46__FUNC_GPIO46 (MTK_PIN_NO(46) | 0) +#define PINMUX_GPIO46__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(46) | 1) +#define PINMUX_GPIO46__FUNC_UTXD1 (MTK_PIN_NO(46) | 2) +#define PINMUX_GPIO46__FUNC_URTS1 (MTK_PIN_NO(46) | 3) +#define PINMUX_GPIO46__FUNC_PWM_B (MTK_PIN_NO(46) | 4) +#define PINMUX_GPIO46__FUNC_USB_DRVVBUS (MTK_PIN_NO(46) | 6) +#define PINMUX_GPIO46__FUNC_DBG_MON_A18 (MTK_PIN_NO(46) | 7) + +#define PINMUX_GPIO47__FUNC_GPIO47 (MTK_PIN_NO(47) | 0) +#define PINMUX_GPIO47__FUNC_SCL_APPM (MTK_PIN_NO(47) | 1) + +#define PINMUX_GPIO48__FUNC_GPIO48 (MTK_PIN_NO(48) | 0) +#define PINMUX_GPIO48__FUNC_SDA_APPM (MTK_PIN_NO(48) | 1) + +#define PINMUX_GPIO49__FUNC_GPIO49 (MTK_PIN_NO(49) | 0) +#define PINMUX_GPIO49__FUNC_SCL3 (MTK_PIN_NO(49) | 1) +#define PINMUX_GPIO49__FUNC_IDDIG (MTK_PIN_NO(49) | 2) + +#define PINMUX_GPIO50__FUNC_GPIO50 (MTK_PIN_NO(50) | 0) +#define PINMUX_GPIO50__FUNC_SDA3 (MTK_PIN_NO(50) | 1) +#define PINMUX_GPIO50__FUNC_IDDIG (MTK_PIN_NO(50) | 2) + +#define PINMUX_GPIO51__FUNC_GPIO51 (MTK_PIN_NO(51) | 0) +#define PINMUX_GPIO51__FUNC_BPI_BUS15 (MTK_PIN_NO(51) | 1) +#define PINMUX_GPIO51__FUNC_DBG_MON_B0 (MTK_PIN_NO(51) | 7) + +#define PINMUX_GPIO52__FUNC_GPIO52 (MTK_PIN_NO(52) | 0) +#define PINMUX_GPIO52__FUNC_BPI_BUS14 (MTK_PIN_NO(52) | 1) +#define PINMUX_GPIO52__FUNC_DBG_MON_B1 (MTK_PIN_NO(52) | 7) + +#define PINMUX_GPIO53__FUNC_GPIO53 (MTK_PIN_NO(53) | 0) +#define PINMUX_GPIO53__FUNC_BPI_BUS13 (MTK_PIN_NO(53) | 1) +#define PINMUX_GPIO53__FUNC_DBG_MON_B2 (MTK_PIN_NO(53) | 7) + +#define PINMUX_GPIO54__FUNC_GPIO54 (MTK_PIN_NO(54) | 0) +#define PINMUX_GPIO54__FUNC_BPI_BUS12 (MTK_PIN_NO(54) | 1) +#define PINMUX_GPIO54__FUNC_DBG_MON_B3 (MTK_PIN_NO(54) | 7) + +#define PINMUX_GPIO55__FUNC_GPIO55 (MTK_PIN_NO(55) | 0) +#define PINMUX_GPIO55__FUNC_BPI_BUS11 (MTK_PIN_NO(55) | 1) + +#define PINMUX_GPIO56__FUNC_GPIO56 (MTK_PIN_NO(56) | 0) +#define PINMUX_GPIO56__FUNC_BPI_BUS10 (MTK_PIN_NO(56) | 1) + +#define PINMUX_GPIO57__FUNC_GPIO57 (MTK_PIN_NO(57) | 0) +#define PINMUX_GPIO57__FUNC_BPI_BUS9 (MTK_PIN_NO(57) | 1) +#define PINMUX_GPIO57__FUNC_DBG_MON_B4 (MTK_PIN_NO(57) | 7) + +#define PINMUX_GPIO58__FUNC_GPIO58 (MTK_PIN_NO(58) | 0) +#define PINMUX_GPIO58__FUNC_BPI_BUS8 (MTK_PIN_NO(58) | 1) +#define PINMUX_GPIO58__FUNC_DBG_MON_B5 (MTK_PIN_NO(58) | 7) + +#define PINMUX_GPIO59__FUNC_GPIO59 (MTK_PIN_NO(59) | 0) +#define PINMUX_GPIO59__FUNC_BPI_BUS7 (MTK_PIN_NO(59) | 1) +#define PINMUX_GPIO59__FUNC_DBG_MON_B6 (MTK_PIN_NO(59) | 7) + +#define PINMUX_GPIO60__FUNC_GPIO60 (MTK_PIN_NO(60) | 0) +#define PINMUX_GPIO60__FUNC_BPI_BUS6 (MTK_PIN_NO(60) | 1) +#define PINMUX_GPIO60__FUNC_DBG_MON_B7 (MTK_PIN_NO(60) | 7) + +#define PINMUX_GPIO61__FUNC_GPIO61 (MTK_PIN_NO(61) | 0) +#define PINMUX_GPIO61__FUNC_BPI_BUS5 (MTK_PIN_NO(61) | 1) +#define PINMUX_GPIO61__FUNC_DBG_MON_B8 (MTK_PIN_NO(61) | 7) + +#define PINMUX_GPIO62__FUNC_GPIO62 (MTK_PIN_NO(62) | 0) +#define PINMUX_GPIO62__FUNC_BPI_BUS4 (MTK_PIN_NO(62) | 1) +#define PINMUX_GPIO62__FUNC_DBG_MON_B9 (MTK_PIN_NO(62) | 7) + +#define PINMUX_GPIO63__FUNC_GPIO63 (MTK_PIN_NO(63) | 0) +#define PINMUX_GPIO63__FUNC_MIPI1_SDATA (MTK_PIN_NO(63) | 1) +#define PINMUX_GPIO63__FUNC_DBG_MON_B10 (MTK_PIN_NO(63) | 7) + +#define PINMUX_GPIO64__FUNC_GPIO64 (MTK_PIN_NO(64) | 0) +#define PINMUX_GPIO64__FUNC_MIPI1_SCLK (MTK_PIN_NO(64) | 1) +#define PINMUX_GPIO64__FUNC_DBG_MON_B11 (MTK_PIN_NO(64) | 7) + +#define PINMUX_GPIO65__FUNC_GPIO65 (MTK_PIN_NO(65) | 0) +#define PINMUX_GPIO65__FUNC_MIPI0_SDATA (MTK_PIN_NO(65) | 1) +#define PINMUX_GPIO65__FUNC_DBG_MON_B12 (MTK_PIN_NO(65) | 7) + +#define PINMUX_GPIO66__FUNC_GPIO66 (MTK_PIN_NO(66) | 0) +#define PINMUX_GPIO66__FUNC_MIPI0_SCLK (MTK_PIN_NO(66) | 1) +#define PINMUX_GPIO66__FUNC_DBG_MON_B13 (MTK_PIN_NO(66) | 7) + +#define PINMUX_GPIO67__FUNC_GPIO67 (MTK_PIN_NO(67) | 0) +#define PINMUX_GPIO67__FUNC_RFIC0_BSI_D2 (MTK_PIN_NO(67) | 1) +#define PINMUX_GPIO67__FUNC_SPM_BSI_D2 (MTK_PIN_NO(67) | 2) +#define PINMUX_GPIO67__FUNC_DBG_MON_B14 (MTK_PIN_NO(67) | 7) + +#define PINMUX_GPIO68__FUNC_GPIO68 (MTK_PIN_NO(68) | 0) +#define PINMUX_GPIO68__FUNC_RFIC0_BSI_D1 (MTK_PIN_NO(68) | 1) +#define PINMUX_GPIO68__FUNC_SPM_BSI_D1 (MTK_PIN_NO(68) | 2) +#define PINMUX_GPIO68__FUNC_DBG_MON_B15 (MTK_PIN_NO(68) | 7) + +#define PINMUX_GPIO69__FUNC_GPIO69 (MTK_PIN_NO(69) | 0) +#define PINMUX_GPIO69__FUNC_RFIC0_BSI_D0 (MTK_PIN_NO(69) | 1) +#define PINMUX_GPIO69__FUNC_SPM_BSI_D0 (MTK_PIN_NO(69) | 2) +#define PINMUX_GPIO69__FUNC_DBG_MON_B16 (MTK_PIN_NO(69) | 7) + +#define PINMUX_GPIO70__FUNC_GPIO70 (MTK_PIN_NO(70) | 0) + +#define PINMUX_GPIO71__FUNC_GPIO71 (MTK_PIN_NO(71) | 0) + +#define PINMUX_GPIO72__FUNC_GPIO72 (MTK_PIN_NO(72) | 0) + +#define PINMUX_GPIO73__FUNC_GPIO73 (MTK_PIN_NO(73) | 0) + +#define PINMUX_GPIO74__FUNC_GPIO74 (MTK_PIN_NO(74) | 0) + +#define PINMUX_GPIO75__FUNC_GPIO75 (MTK_PIN_NO(75) | 0) +#define PINMUX_GPIO75__FUNC_MIPI3_SDATA (MTK_PIN_NO(75) | 1) +#define PINMUX_GPIO75__FUNC_PWM_C (MTK_PIN_NO(75) | 2) +#define PINMUX_GPIO75__FUNC_IRTX_OUT (MTK_PIN_NO(75) | 3) +#define PINMUX_GPIO75__FUNC_I2S0_DI (MTK_PIN_NO(75) | 4) +#define PINMUX_GPIO75__FUNC_I2S2_DI (MTK_PIN_NO(75) | 5) +#define PINMUX_GPIO75__FUNC_ANT_SEL5 (MTK_PIN_NO(75) | 6) +#define PINMUX_GPIO75__FUNC_DBG_MON_B19 (MTK_PIN_NO(75) | 7) + +#define PINMUX_GPIO76__FUNC_GPIO76 (MTK_PIN_NO(76) | 0) +#define PINMUX_GPIO76__FUNC_MIPI3_SCLK (MTK_PIN_NO(76) | 1) +#define PINMUX_GPIO76__FUNC_CLKM3 (MTK_PIN_NO(76) | 2) +#define PINMUX_GPIO76__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(76) | 3) +#define PINMUX_GPIO76__FUNC_I2S0_LRCK (MTK_PIN_NO(76) | 4) +#define PINMUX_GPIO76__FUNC_I2S2_LRCK (MTK_PIN_NO(76) | 5) +#define PINMUX_GPIO76__FUNC_ANT_SEL4 (MTK_PIN_NO(76) | 6) +#define PINMUX_GPIO76__FUNC_DBG_MON_B20 (MTK_PIN_NO(76) | 7) + +#define PINMUX_GPIO77__FUNC_GPIO77 (MTK_PIN_NO(77) | 0) +#define PINMUX_GPIO77__FUNC_MIPI2_SDATA (MTK_PIN_NO(77) | 1) +#define PINMUX_GPIO77__FUNC_USB_DRVVBUS (MTK_PIN_NO(77) | 2) +#define PINMUX_GPIO77__FUNC_IRTX_OUT (MTK_PIN_NO(77) | 3) +#define PINMUX_GPIO77__FUNC_I2S0_BCK (MTK_PIN_NO(77) | 4) +#define PINMUX_GPIO77__FUNC_I2S2_BCK (MTK_PIN_NO(77) | 5) +#define PINMUX_GPIO77__FUNC_ANT_SEL3 (MTK_PIN_NO(77) | 6) +#define PINMUX_GPIO77__FUNC_DBG_MON_B21 (MTK_PIN_NO(77) | 7) + +#define PINMUX_GPIO78__FUNC_GPIO78 (MTK_PIN_NO(78) | 0) +#define PINMUX_GPIO78__FUNC_MIPI2_SCLK (MTK_PIN_NO(78) | 1) +#define PINMUX_GPIO78__FUNC_IDDIG (MTK_PIN_NO(78) | 2) +#define PINMUX_GPIO78__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(78) | 3) +#define PINMUX_GPIO78__FUNC_I2S0_MCK (MTK_PIN_NO(78) | 4) +#define PINMUX_GPIO78__FUNC_I2S2_MCK (MTK_PIN_NO(78) | 5) +#define PINMUX_GPIO78__FUNC_PCM1_DO0 (MTK_PIN_NO(78) | 6) +#define PINMUX_GPIO78__FUNC_DBG_MON_B22 (MTK_PIN_NO(78) | 7) + +#define PINMUX_GPIO79__FUNC_GPIO79 (MTK_PIN_NO(79) | 0) +#define PINMUX_GPIO79__FUNC_BPI_BUS3 (MTK_PIN_NO(79) | 1) +#define PINMUX_GPIO79__FUNC_DBG_MON_B23 (MTK_PIN_NO(79) | 7) + +#define PINMUX_GPIO80__FUNC_GPIO80 (MTK_PIN_NO(80) | 0) +#define PINMUX_GPIO80__FUNC_BPI_BUS2 (MTK_PIN_NO(80) | 1) +#define PINMUX_GPIO80__FUNC_DBG_MON_B24 (MTK_PIN_NO(80) | 7) + +#define PINMUX_GPIO81__FUNC_GPIO81 (MTK_PIN_NO(81) | 0) +#define PINMUX_GPIO81__FUNC_BPI_BUS1 (MTK_PIN_NO(81) | 1) +#define PINMUX_GPIO81__FUNC_DBG_MON_B25 (MTK_PIN_NO(81) | 7) + +#define PINMUX_GPIO82__FUNC_GPIO82 (MTK_PIN_NO(82) | 0) +#define PINMUX_GPIO82__FUNC_BPI_BUS0 (MTK_PIN_NO(82) | 1) +#define PINMUX_GPIO82__FUNC_DBG_MON_B26 (MTK_PIN_NO(82) | 7) + +#define PINMUX_GPIO83__FUNC_GPIO83 (MTK_PIN_NO(83) | 0) +#define PINMUX_GPIO83__FUNC_BPI_BUS23 (MTK_PIN_NO(83) | 1) +#define PINMUX_GPIO83__FUNC_DET_BPI1 (MTK_PIN_NO(83) | 2) +#define PINMUX_GPIO83__FUNC_I2S3_DO (MTK_PIN_NO(83) | 4) +#define PINMUX_GPIO83__FUNC_I2S1_DO (MTK_PIN_NO(83) | 5) +#define PINMUX_GPIO83__FUNC_PCM1_DO1 (MTK_PIN_NO(83) | 6) +#define PINMUX_GPIO83__FUNC_DBG_MON_B27 (MTK_PIN_NO(83) | 7) + +#define PINMUX_GPIO84__FUNC_GPIO84 (MTK_PIN_NO(84) | 0) +#define PINMUX_GPIO84__FUNC_BPI_BUS22 (MTK_PIN_NO(84) | 1) +#define PINMUX_GPIO84__FUNC_DET_BPI0 (MTK_PIN_NO(84) | 2) +#define PINMUX_GPIO84__FUNC_I2S3_LRCK (MTK_PIN_NO(84) | 4) +#define PINMUX_GPIO84__FUNC_I2S1_LRCK (MTK_PIN_NO(84) | 5) +#define PINMUX_GPIO84__FUNC_PCM1_CLK (MTK_PIN_NO(84) | 6) +#define PINMUX_GPIO84__FUNC_DBG_MON_B28 (MTK_PIN_NO(84) | 7) + +#define PINMUX_GPIO85__FUNC_GPIO85 (MTK_PIN_NO(85) | 0) +#define PINMUX_GPIO85__FUNC_BPI_BUS21 (MTK_PIN_NO(85) | 1) +#define PINMUX_GPIO85__FUNC_TX_SWAP3 (MTK_PIN_NO(85) | 2) +#define PINMUX_GPIO85__FUNC_DBG_MON_B29 (MTK_PIN_NO(85) | 7) + +#define PINMUX_GPIO86__FUNC_GPIO86 (MTK_PIN_NO(86) | 0) +#define PINMUX_GPIO86__FUNC_BPI_BUS20 (MTK_PIN_NO(86) | 1) +#define PINMUX_GPIO86__FUNC_TX_SWAP2 (MTK_PIN_NO(86) | 2) +#define PINMUX_GPIO86__FUNC_DBG_MON_B30 (MTK_PIN_NO(86) | 7) + +#define PINMUX_GPIO87__FUNC_GPIO87 (MTK_PIN_NO(87) | 0) +#define PINMUX_GPIO87__FUNC_BPI_BUS19 (MTK_PIN_NO(87) | 1) +#define PINMUX_GPIO87__FUNC_TX_SWAP1 (MTK_PIN_NO(87) | 2) +#define PINMUX_GPIO87__FUNC_DBG_MON_B31 (MTK_PIN_NO(87) | 7) + +#define PINMUX_GPIO88__FUNC_GPIO88 (MTK_PIN_NO(88) | 0) +#define PINMUX_GPIO88__FUNC_BPI_BUS18 (MTK_PIN_NO(88) | 1) +#define PINMUX_GPIO88__FUNC_TX_SWAP0 (MTK_PIN_NO(88) | 2) + +#define PINMUX_GPIO89__FUNC_GPIO89 (MTK_PIN_NO(89) | 0) +#define PINMUX_GPIO89__FUNC_BPI_BUS17 (MTK_PIN_NO(89) | 1) +#define PINMUX_GPIO89__FUNC_PA_VM1 (MTK_PIN_NO(89) | 2) +#define PINMUX_GPIO89__FUNC_I2S3_BCK (MTK_PIN_NO(89) | 4) +#define PINMUX_GPIO89__FUNC_I2S1_BCK (MTK_PIN_NO(89) | 5) +#define PINMUX_GPIO89__FUNC_PCM1_SYNC (MTK_PIN_NO(89) | 6) + +#define PINMUX_GPIO90__FUNC_GPIO90 (MTK_PIN_NO(90) | 0) +#define PINMUX_GPIO90__FUNC_BPI_BUS16 (MTK_PIN_NO(90) | 1) +#define PINMUX_GPIO90__FUNC_PA_VM0 (MTK_PIN_NO(90) | 2) +#define PINMUX_GPIO90__FUNC_I2S3_MCK (MTK_PIN_NO(90) | 4) +#define PINMUX_GPIO90__FUNC_I2S1_MCK (MTK_PIN_NO(90) | 5) +#define PINMUX_GPIO90__FUNC_PCM1_DI (MTK_PIN_NO(90) | 6) + +#define PINMUX_GPIO91__FUNC_GPIO91 (MTK_PIN_NO(91) | 0) +#define PINMUX_GPIO91__FUNC_SDA1 (MTK_PIN_NO(91) | 1) +#define PINMUX_GPIO91__FUNC_IDDIG (MTK_PIN_NO(91) | 2) + +#define PINMUX_GPIO92__FUNC_GPIO92 (MTK_PIN_NO(92) | 0) +#define PINMUX_GPIO92__FUNC_SDA0 (MTK_PIN_NO(92) | 1) + +#define PINMUX_GPIO93__FUNC_GPIO93 (MTK_PIN_NO(93) | 0) +#define PINMUX_GPIO93__FUNC_SCL0 (MTK_PIN_NO(93) | 1) + +#define PINMUX_GPIO94__FUNC_GPIO94 (MTK_PIN_NO(94) | 0) +#define PINMUX_GPIO94__FUNC_SCL1 (MTK_PIN_NO(94) | 1) +#define PINMUX_GPIO94__FUNC_IDDIG (MTK_PIN_NO(94) | 2) + +#define PINMUX_GPIO95__FUNC_GPIO95 (MTK_PIN_NO(95) | 0) +#define PINMUX_GPIO95__FUNC_SPI0_MI (MTK_PIN_NO(95) | 1) +#define PINMUX_GPIO95__FUNC_MRG_SYNC (MTK_PIN_NO(95) | 2) +#define PINMUX_GPIO95__FUNC_PCM0_SYNC (MTK_PIN_NO(95) | 3) +#define PINMUX_GPIO95__FUNC_I2S1_BCK (MTK_PIN_NO(95) | 4) +#define PINMUX_GPIO95__FUNC_SPI0_MO (MTK_PIN_NO(95) | 5) +#define PINMUX_GPIO95__FUNC_DFD_TDO (MTK_PIN_NO(95) | 6) +#define PINMUX_GPIO95__FUNC_JTDO_SEL1 (MTK_PIN_NO(95) | 7) + +#define PINMUX_GPIO96__FUNC_GPIO96 (MTK_PIN_NO(96) | 0) +#define PINMUX_GPIO96__FUNC_SPI0_CSB (MTK_PIN_NO(96) | 1) +#define PINMUX_GPIO96__FUNC_MRG_DO (MTK_PIN_NO(96) | 2) +#define PINMUX_GPIO96__FUNC_PCM0_DO (MTK_PIN_NO(96) | 3) +#define PINMUX_GPIO96__FUNC_I2S1_LRCK (MTK_PIN_NO(96) | 4) +#define PINMUX_GPIO96__FUNC_SDA2 (MTK_PIN_NO(96) | 5) +#define PINMUX_GPIO96__FUNC_DFD_TMS (MTK_PIN_NO(96) | 6) +#define PINMUX_GPIO96__FUNC_JTMS_SEL1 (MTK_PIN_NO(96) | 7) + +#define PINMUX_GPIO97__FUNC_GPIO97 (MTK_PIN_NO(97) | 0) +#define PINMUX_GPIO97__FUNC_SPI0_MO (MTK_PIN_NO(97) | 1) +#define PINMUX_GPIO97__FUNC_MRG_CLK (MTK_PIN_NO(97) | 2) +#define PINMUX_GPIO97__FUNC_PCM0_CLK (MTK_PIN_NO(97) | 3) +#define PINMUX_GPIO97__FUNC_I2S1_DO (MTK_PIN_NO(97) | 4) +#define PINMUX_GPIO97__FUNC_SPI0_MI (MTK_PIN_NO(97) | 5) +#define PINMUX_GPIO97__FUNC_DFD_TDI (MTK_PIN_NO(97) | 6) +#define PINMUX_GPIO97__FUNC_JTDI_SEL1 (MTK_PIN_NO(97) | 7) + +#define PINMUX_GPIO98__FUNC_GPIO98 (MTK_PIN_NO(98) | 0) +#define PINMUX_GPIO98__FUNC_SPI0_CLK (MTK_PIN_NO(98) | 1) +#define PINMUX_GPIO98__FUNC_MRG_DI (MTK_PIN_NO(98) | 2) +#define PINMUX_GPIO98__FUNC_PCM0_DI (MTK_PIN_NO(98) | 3) +#define PINMUX_GPIO98__FUNC_I2S1_MCK (MTK_PIN_NO(98) | 4) +#define PINMUX_GPIO98__FUNC_SCL2 (MTK_PIN_NO(98) | 5) +#define PINMUX_GPIO98__FUNC_DFD_TCK_XI (MTK_PIN_NO(98) | 6) +#define PINMUX_GPIO98__FUNC_JTCK_SEL1 (MTK_PIN_NO(98) | 7) + +#define PINMUX_GPIO99__FUNC_GPIO99 (MTK_PIN_NO(99) | 0) +#define PINMUX_GPIO99__FUNC_SRCLKENAI0 (MTK_PIN_NO(99) | 1) +#define PINMUX_GPIO99__FUNC_UTXD1 (MTK_PIN_NO(99) | 2) +#define PINMUX_GPIO99__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(99) | 3) +#define PINMUX_GPIO99__FUNC_CLKM2 (MTK_PIN_NO(99) | 4) +#define PINMUX_GPIO99__FUNC_PCC_PPC_IO (MTK_PIN_NO(99) | 5) +#define PINMUX_GPIO99__FUNC_ANT_SEL3 (MTK_PIN_NO(99) | 6) +#define PINMUX_GPIO99__FUNC_SPI0_MI (MTK_PIN_NO(99) | 7) + +#define PINMUX_GPIO100__FUNC_GPIO100 (MTK_PIN_NO(100) | 0) +#define PINMUX_GPIO100__FUNC_PWM_A (MTK_PIN_NO(100) | 1) +#define PINMUX_GPIO100__FUNC_URXD1 (MTK_PIN_NO(100) | 2) +#define PINMUX_GPIO100__FUNC_MD_INT0 (MTK_PIN_NO(100) | 3) +#define PINMUX_GPIO100__FUNC_CLKM3 (MTK_PIN_NO(100) | 4) +#define PINMUX_GPIO100__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(100) | 5) +#define PINMUX_GPIO100__FUNC_ANT_SEL4 (MTK_PIN_NO(100) | 6) +#define PINMUX_GPIO100__FUNC_DBG_MON_A35 (MTK_PIN_NO(100) | 7) + +#define PINMUX_GPIO101__FUNC_GPIO101 (MTK_PIN_NO(101) | 0) +#define PINMUX_GPIO101__FUNC_KPROW1 (MTK_PIN_NO(101) | 1) +#define PINMUX_GPIO101__FUNC_IRTX_OUT (MTK_PIN_NO(101) | 2) +#define PINMUX_GPIO101__FUNC_C2K_UTXD1 (MTK_PIN_NO(101) | 3) +#define PINMUX_GPIO101__FUNC_C2K_UTXD0 (MTK_PIN_NO(101) | 4) +#define PINMUX_GPIO101__FUNC_C2K_DM_EINT2 (MTK_PIN_NO(101) | 5) +#define PINMUX_GPIO101__FUNC_ANT_SEL5 (MTK_PIN_NO(101) | 6) +#define PINMUX_GPIO101__FUNC_DBG_MON_A36 (MTK_PIN_NO(101) | 7) + +#define PINMUX_GPIO102__FUNC_GPIO102 (MTK_PIN_NO(102) | 0) +#define PINMUX_GPIO102__FUNC_KPROW0 (MTK_PIN_NO(102) | 1) +#define PINMUX_GPIO102__FUNC_C2K_DM_EINT3 (MTK_PIN_NO(102) | 5) +#define PINMUX_GPIO102__FUNC_DBG_MON_A37 (MTK_PIN_NO(102) | 7) + +#define PINMUX_GPIO103__FUNC_GPIO103 (MTK_PIN_NO(103) | 0) +#define PINMUX_GPIO103__FUNC_KPCOL0 (MTK_PIN_NO(103) | 1) +#define PINMUX_GPIO103__FUNC_C2K_DM_EINT0 (MTK_PIN_NO(103) | 5) + +#define PINMUX_GPIO104__FUNC_GPIO104 (MTK_PIN_NO(104) | 0) +#define PINMUX_GPIO104__FUNC_KPCOL1 (MTK_PIN_NO(104) | 1) +#define PINMUX_GPIO104__FUNC_C2K_URXD1 (MTK_PIN_NO(104) | 3) +#define PINMUX_GPIO104__FUNC_C2K_URXD0 (MTK_PIN_NO(104) | 4) +#define PINMUX_GPIO104__FUNC_C2K_DM_EINT1 (MTK_PIN_NO(104) | 5) + +#define PINMUX_GPIO105__FUNC_GPIO105 (MTK_PIN_NO(105) | 0) +#define PINMUX_GPIO105__FUNC_URXD0 (MTK_PIN_NO(105) | 1) +#define PINMUX_GPIO105__FUNC_UTXD0 (MTK_PIN_NO(105) | 2) +#define PINMUX_GPIO105__FUNC_MD_URXD0 (MTK_PIN_NO(105) | 3) +#define PINMUX_GPIO105__FUNC_MD_URXD1 (MTK_PIN_NO(105) | 4) +#define PINMUX_GPIO105__FUNC_C2K_URXD0 (MTK_PIN_NO(105) | 5) +#define PINMUX_GPIO105__FUNC_MD_URXD2 (MTK_PIN_NO(105) | 6) +#define PINMUX_GPIO105__FUNC_C2K_URXD1 (MTK_PIN_NO(105) | 7) + +#define PINMUX_GPIO106__FUNC_GPIO106 (MTK_PIN_NO(106) | 0) +#define PINMUX_GPIO106__FUNC_UTXD0 (MTK_PIN_NO(106) | 1) +#define PINMUX_GPIO106__FUNC_URXD0 (MTK_PIN_NO(106) | 2) +#define PINMUX_GPIO106__FUNC_MD_UTXD0 (MTK_PIN_NO(106) | 3) +#define PINMUX_GPIO106__FUNC_MD_UTXD1 (MTK_PIN_NO(106) | 4) +#define PINMUX_GPIO106__FUNC_C2K_UTXD0 (MTK_PIN_NO(106) | 5) +#define PINMUX_GPIO106__FUNC_MD_UTXD2 (MTK_PIN_NO(106) | 6) +#define PINMUX_GPIO106__FUNC_C2K_UTXD1 (MTK_PIN_NO(106) | 7) + +#define PINMUX_GPIO107__FUNC_GPIO107 (MTK_PIN_NO(107) | 0) +#define PINMUX_GPIO107__FUNC_UCTS0 (MTK_PIN_NO(107) | 1) +#define PINMUX_GPIO107__FUNC_I2S2_MCK (MTK_PIN_NO(107) | 2) +#define PINMUX_GPIO107__FUNC_CONN_MCU_TDO (MTK_PIN_NO(107) | 4) +#define PINMUX_GPIO107__FUNC_C2K_DM_OTDO (MTK_PIN_NO(107) | 5) +#define PINMUX_GPIO107__FUNC_IO_JTAG_TDO (MTK_PIN_NO(107) | 6) +#define PINMUX_GPIO107__FUNC_DBG_MON_A6 (MTK_PIN_NO(107) | 7) + +#define PINMUX_GPIO108__FUNC_GPIO108 (MTK_PIN_NO(108) | 0) +#define PINMUX_GPIO108__FUNC_URTS0 (MTK_PIN_NO(108) | 1) +#define PINMUX_GPIO108__FUNC_I2S2_BCK (MTK_PIN_NO(108) | 2) +#define PINMUX_GPIO108__FUNC_CONN_MCU_TMS (MTK_PIN_NO(108) | 4) +#define PINMUX_GPIO108__FUNC_C2K_DM_OTMS (MTK_PIN_NO(108) | 5) +#define PINMUX_GPIO108__FUNC_IO_JTAG_TMS (MTK_PIN_NO(108) | 6) +#define PINMUX_GPIO108__FUNC_DBG_MON_A7 (MTK_PIN_NO(108) | 7) + +#define PINMUX_GPIO109__FUNC_GPIO109 (MTK_PIN_NO(109) | 0) +#define PINMUX_GPIO109__FUNC_CMMCLK1 (MTK_PIN_NO(109) | 1) +#define PINMUX_GPIO109__FUNC_PWM_C (MTK_PIN_NO(109) | 2) +#define PINMUX_GPIO109__FUNC_MD_INT0 (MTK_PIN_NO(109) | 3) +#define PINMUX_GPIO109__FUNC_CONN_MCU_AICE_TCKC (MTK_PIN_NO(109) | 4) +#define PINMUX_GPIO109__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(109) | 5) +#define PINMUX_GPIO109__FUNC_CMFLASH (MTK_PIN_NO(109) | 6) +#define PINMUX_GPIO109__FUNC_DBG_MON_A9 (MTK_PIN_NO(109) | 7) + +#define PINMUX_GPIO110__FUNC_GPIO110 (MTK_PIN_NO(110) | 0) +#define PINMUX_GPIO110__FUNC_CLKM2 (MTK_PIN_NO(110) | 1) +#define PINMUX_GPIO110__FUNC_I2S2_LRCK (MTK_PIN_NO(110) | 2) +#define PINMUX_GPIO110__FUNC_CONN_MCU_TCK (MTK_PIN_NO(110) | 4) +#define PINMUX_GPIO110__FUNC_C2K_DM_OTCK (MTK_PIN_NO(110) | 5) +#define PINMUX_GPIO110__FUNC_IO_JTAG_TCK (MTK_PIN_NO(110) | 6) +#define PINMUX_GPIO110__FUNC_DBG_MON_A10 (MTK_PIN_NO(110) | 7) + +#define PINMUX_GPIO111__FUNC_GPIO111 (MTK_PIN_NO(111) | 0) +#define PINMUX_GPIO111__FUNC_CLKM1 (MTK_PIN_NO(111) | 1) +#define PINMUX_GPIO111__FUNC_I2S2_DI (MTK_PIN_NO(111) | 2) +#define PINMUX_GPIO111__FUNC_CONN_MCU_TDI (MTK_PIN_NO(111) | 4) +#define PINMUX_GPIO111__FUNC_C2K_DM_OTDI (MTK_PIN_NO(111) | 5) +#define PINMUX_GPIO111__FUNC_IO_JTAG_TDI (MTK_PIN_NO(111) | 6) +#define PINMUX_GPIO111__FUNC_DBG_MON_A11 (MTK_PIN_NO(111) | 7) + +#define PINMUX_GPIO112__FUNC_GPIO112 (MTK_PIN_NO(112) | 0) +#define PINMUX_GPIO112__FUNC_SCL2 (MTK_PIN_NO(112) | 1) + +#define PINMUX_GPIO113__FUNC_GPIO113 (MTK_PIN_NO(113) | 0) +#define PINMUX_GPIO113__FUNC_SDA2 (MTK_PIN_NO(113) | 1) + +#define PINMUX_GPIO114__FUNC_GPIO114 (MTK_PIN_NO(114) | 0) +#define PINMUX_GPIO114__FUNC_ANT_SEL0 (MTK_PIN_NO(114) | 1) +#define PINMUX_GPIO114__FUNC_PWM_A (MTK_PIN_NO(114) | 2) +#define PINMUX_GPIO114__FUNC_CLKM0 (MTK_PIN_NO(114) | 3) +#define PINMUX_GPIO114__FUNC_IRTX_OUT (MTK_PIN_NO(114) | 4) +#define PINMUX_GPIO114__FUNC_PCC_PPC_IO (MTK_PIN_NO(114) | 5) +#define PINMUX_GPIO114__FUNC_DBG_MON_A47 (MTK_PIN_NO(114) | 7) + +#define PINMUX_GPIO115__FUNC_GPIO115 (MTK_PIN_NO(115) | 0) +#define PINMUX_GPIO115__FUNC_ANT_SEL1 (MTK_PIN_NO(115) | 1) +#define PINMUX_GPIO115__FUNC_PWM_B (MTK_PIN_NO(115) | 2) +#define PINMUX_GPIO115__FUNC_CLKM1 (MTK_PIN_NO(115) | 3) +#define PINMUX_GPIO115__FUNC_USB_DRVVBUS (MTK_PIN_NO(115) | 4) +#define PINMUX_GPIO115__FUNC_DAP_SIB1_SWD (MTK_PIN_NO(115) | 5) +#define PINMUX_GPIO115__FUNC_DBG_MON_A48 (MTK_PIN_NO(115) | 7) + +#define PINMUX_GPIO116__FUNC_GPIO116 (MTK_PIN_NO(116) | 0) +#define PINMUX_GPIO116__FUNC_ANT_SEL2 (MTK_PIN_NO(116) | 1) +#define PINMUX_GPIO116__FUNC_PWM_C (MTK_PIN_NO(116) | 2) +#define PINMUX_GPIO116__FUNC_CLKM2 (MTK_PIN_NO(116) | 3) +#define PINMUX_GPIO116__FUNC_IDDIG (MTK_PIN_NO(116) | 4) +#define PINMUX_GPIO116__FUNC_DAP_SIB1_SWCK (MTK_PIN_NO(116) | 5) +#define PINMUX_GPIO116__FUNC_IRTX_OUT (MTK_PIN_NO(116) | 6) +#define PINMUX_GPIO116__FUNC_DBG_MON_A49 (MTK_PIN_NO(116) | 7) + +#define PINMUX_GPIO117__FUNC_GPIO117 (MTK_PIN_NO(117) | 0) +#define PINMUX_GPIO117__FUNC_F2W_DATA (MTK_PIN_NO(117) | 1) +#define PINMUX_GPIO117__FUNC_PTA_TXD (MTK_PIN_NO(117) | 2) +#define PINMUX_GPIO117__FUNC_PTA_RXD (MTK_PIN_NO(117) | 3) +#define PINMUX_GPIO117__FUNC_AUXIF_ST0 (MTK_PIN_NO(117) | 4) +#define PINMUX_GPIO117__FUNC_C2K_UTXD1 (MTK_PIN_NO(117) | 5) +#define PINMUX_GPIO117__FUNC_SDA0 (MTK_PIN_NO(117) | 6) +#define PINMUX_GPIO117__FUNC_DBG_MON_A50 (MTK_PIN_NO(117) | 7) + +#define PINMUX_GPIO118__FUNC_GPIO118 (MTK_PIN_NO(118) | 0) +#define PINMUX_GPIO118__FUNC_F2W_CK (MTK_PIN_NO(118) | 1) +#define PINMUX_GPIO118__FUNC_PTA_RXD (MTK_PIN_NO(118) | 2) +#define PINMUX_GPIO118__FUNC_PTA_TXD (MTK_PIN_NO(118) | 3) +#define PINMUX_GPIO118__FUNC_AUXIF_CLK0 (MTK_PIN_NO(118) | 4) +#define PINMUX_GPIO118__FUNC_C2K_URXD1 (MTK_PIN_NO(118) | 5) +#define PINMUX_GPIO118__FUNC_SCL0 (MTK_PIN_NO(118) | 6) +#define PINMUX_GPIO118__FUNC_DBG_MON_A51 (MTK_PIN_NO(118) | 7) + +#define PINMUX_GPIO119__FUNC_GPIO119 (MTK_PIN_NO(119) | 0) +#define PINMUX_GPIO119__FUNC_WB_RSTB (MTK_PIN_NO(119) | 1) +#define PINMUX_GPIO119__FUNC_URXD1 (MTK_PIN_NO(119) | 2) +#define PINMUX_GPIO119__FUNC_UTXD1 (MTK_PIN_NO(119) | 3) +#define PINMUX_GPIO119__FUNC_DBG_MON_A52 (MTK_PIN_NO(119) | 7) + +#define PINMUX_GPIO120__FUNC_GPIO120 (MTK_PIN_NO(120) | 0) +#define PINMUX_GPIO120__FUNC_WB_SCLK (MTK_PIN_NO(120) | 1) +#define PINMUX_GPIO120__FUNC_UTXD1 (MTK_PIN_NO(120) | 2) +#define PINMUX_GPIO120__FUNC_URXD1 (MTK_PIN_NO(120) | 3) + +#define PINMUX_GPIO121__FUNC_GPIO121 (MTK_PIN_NO(121) | 0) +#define PINMUX_GPIO121__FUNC_WB_SDATA (MTK_PIN_NO(121) | 1) +#define PINMUX_GPIO121__FUNC_AGPS_SYNC (MTK_PIN_NO(121) | 2) +#define PINMUX_GPIO121__FUNC_AUXIF_ST1 (MTK_PIN_NO(121) | 4) +#define PINMUX_GPIO121__FUNC_C2K_UTXD0 (MTK_PIN_NO(121) | 5) +#define PINMUX_GPIO121__FUNC_SDA1 (MTK_PIN_NO(121) | 6) + +#define PINMUX_GPIO122__FUNC_GPIO122 (MTK_PIN_NO(122) | 0) +#define PINMUX_GPIO122__FUNC_WB_SEN (MTK_PIN_NO(122) | 1) +#define PINMUX_GPIO122__FUNC_SRCLKENAI1 (MTK_PIN_NO(122) | 2) +#define PINMUX_GPIO122__FUNC_AUXIF_CLK1 (MTK_PIN_NO(122) | 4) +#define PINMUX_GPIO122__FUNC_C2K_URXD0 (MTK_PIN_NO(122) | 5) +#define PINMUX_GPIO122__FUNC_SCL1 (MTK_PIN_NO(122) | 6) + +#define PINMUX_GPIO123__FUNC_GPIO123 (MTK_PIN_NO(123) | 0) + +#define PINMUX_GPIO124__FUNC_GPIO124 (MTK_PIN_NO(124) | 0) + +#define PINMUX_GPIO125__FUNC_GPIO125 (MTK_PIN_NO(125) | 0) + +#define PINMUX_GPIO126__FUNC_GPIO126 (MTK_PIN_NO(126) | 0) + +#define PINMUX_GPIO127__FUNC_GPIO127 (MTK_PIN_NO(127) | 0) + +#define PINMUX_GPIO128__FUNC_GPIO128 (MTK_PIN_NO(128) | 0) + +#define PINMUX_GPIO129__FUNC_GPIO129 (MTK_PIN_NO(129) | 0) + +#define PINMUX_GPIO130__FUNC_GPIO130 (MTK_PIN_NO(130) | 0) + +#define PINMUX_GPIO131__FUNC_GPIO131 (MTK_PIN_NO(131) | 0) +#define PINMUX_GPIO131__FUNC_WB_CTRL0 (MTK_PIN_NO(131) | 1) +#define PINMUX_GPIO131__FUNC_MSDC2_DAT1 (MTK_PIN_NO(131) | 2) +#define PINMUX_GPIO131__FUNC_C2K_NTRST (MTK_PIN_NO(131) | 5) + +#define PINMUX_GPIO132__FUNC_GPIO132 (MTK_PIN_NO(132) | 0) +#define PINMUX_GPIO132__FUNC_WB_CTRL1 (MTK_PIN_NO(132) | 1) +#define PINMUX_GPIO132__FUNC_MSDC2_CMD (MTK_PIN_NO(132) | 2) +#define PINMUX_GPIO132__FUNC_C2K_TCK (MTK_PIN_NO(132) | 5) + +#define PINMUX_GPIO133__FUNC_GPIO133 (MTK_PIN_NO(133) | 0) +#define PINMUX_GPIO133__FUNC_WB_CTRL2 (MTK_PIN_NO(133) | 1) +#define PINMUX_GPIO133__FUNC_MSDC2_CLK (MTK_PIN_NO(133) | 2) +#define PINMUX_GPIO133__FUNC_C2K_TDI (MTK_PIN_NO(133) | 5) + +#define PINMUX_GPIO134__FUNC_GPIO134 (MTK_PIN_NO(134) | 0) +#define PINMUX_GPIO134__FUNC_WB_CTRL3 (MTK_PIN_NO(134) | 1) +#define PINMUX_GPIO134__FUNC_MSDC2_DAT3 (MTK_PIN_NO(134) | 2) +#define PINMUX_GPIO134__FUNC_C2K_TMS (MTK_PIN_NO(134) | 5) + +#define PINMUX_GPIO135__FUNC_GPIO135 (MTK_PIN_NO(135) | 0) +#define PINMUX_GPIO135__FUNC_WB_CTRL4 (MTK_PIN_NO(135) | 1) +#define PINMUX_GPIO135__FUNC_MSDC2_DAT0 (MTK_PIN_NO(135) | 2) +#define PINMUX_GPIO135__FUNC_C2K_TDO (MTK_PIN_NO(135) | 5) + +#define PINMUX_GPIO136__FUNC_GPIO136 (MTK_PIN_NO(136) | 0) +#define PINMUX_GPIO136__FUNC_WB_CTRL5 (MTK_PIN_NO(136) | 1) +#define PINMUX_GPIO136__FUNC_MSDC2_DAT2 (MTK_PIN_NO(136) | 2) +#define PINMUX_GPIO136__FUNC_C2K_RTCK (MTK_PIN_NO(136) | 5) + +#define PINMUX_GPIO137__FUNC_GPIO137 (MTK_PIN_NO(137) | 0) + +#define PINMUX_GPIO138__FUNC_GPIO138 (MTK_PIN_NO(138) | 0) + +#define PINMUX_GPIO139__FUNC_GPIO139 (MTK_PIN_NO(139) | 0) + +#define PINMUX_GPIO140__FUNC_GPIO140 (MTK_PIN_NO(140) | 0) + +#define PINMUX_GPIO141__FUNC_GPIO141 (MTK_PIN_NO(141) | 0) + +#define PINMUX_GPIO142__FUNC_GPIO142 (MTK_PIN_NO(142) | 0) + +#define PINMUX_GPIO143__FUNC_GPIO143 (MTK_PIN_NO(143) | 0) + +#define PINMUX_GPIO144__FUNC_GPIO144 (MTK_PIN_NO(144) | 0) + +#define PINMUX_GPIO145__FUNC_GPIO145 (MTK_PIN_NO(145) | 0) + +#define PINMUX_GPIO146__FUNC_GPIO146 (MTK_PIN_NO(146) | 0) + +#define PINMUX_GPIO147__FUNC_GPIO147 (MTK_PIN_NO(147) | 0) +#define PINMUX_GPIO147__FUNC_RTC32K_CK (MTK_PIN_NO(147) | 1) + +#define PINMUX_GPIO148__FUNC_GPIO148 (MTK_PIN_NO(148) | 0) +#define PINMUX_GPIO148__FUNC_WATCHDOG (MTK_PIN_NO(148) | 1) + +#define PINMUX_GPIO149__FUNC_GPIO149 (MTK_PIN_NO(149) | 0) +#define PINMUX_GPIO149__FUNC_AUD_CLK_MOSI (MTK_PIN_NO(149) | 1) +#define PINMUX_GPIO149__FUNC_I2S1_BCK (MTK_PIN_NO(149) | 3) + +#define PINMUX_GPIO150__FUNC_GPIO150 (MTK_PIN_NO(150) | 0) +#define PINMUX_GPIO150__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(150) | 1) +#define PINMUX_GPIO150__FUNC_AUD_DAT_MISO (MTK_PIN_NO(150) | 2) +#define PINMUX_GPIO150__FUNC_I2S1_LRCK (MTK_PIN_NO(150) | 3) + +#define PINMUX_GPIO151__FUNC_GPIO151 (MTK_PIN_NO(151) | 0) +#define PINMUX_GPIO151__FUNC_AUD_DAT_MISO (MTK_PIN_NO(151) | 1) +#define PINMUX_GPIO151__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(151) | 2) +#define PINMUX_GPIO151__FUNC_I2S1_DO (MTK_PIN_NO(151) | 3) + +#define PINMUX_GPIO152__FUNC_GPIO152 (MTK_PIN_NO(152) | 0) +#define PINMUX_GPIO152__FUNC_PWRAP_SPI0_MI (MTK_PIN_NO(152) | 1) +#define PINMUX_GPIO152__FUNC_PWRAP_SPI0_MO (MTK_PIN_NO(152) | 2) + +#define PINMUX_GPIO153__FUNC_GPIO153 (MTK_PIN_NO(153) | 0) +#define PINMUX_GPIO153__FUNC_PWRAP_SPI0_CSN (MTK_PIN_NO(153) | 1) + +#define PINMUX_GPIO154__FUNC_GPIO154 (MTK_PIN_NO(154) | 0) +#define PINMUX_GPIO154__FUNC_PWRAP_SPI0_MO (MTK_PIN_NO(154) | 1) +#define PINMUX_GPIO154__FUNC_PWRAP_SPI0_MI (MTK_PIN_NO(154) | 2) + +#define PINMUX_GPIO155__FUNC_GPIO155 (MTK_PIN_NO(155) | 0) +#define PINMUX_GPIO155__FUNC_PWRAP_SPI0_CK (MTK_PIN_NO(155) | 1) + +#define PINMUX_GPIO156__FUNC_GPIO156 (MTK_PIN_NO(156) | 0) +#define PINMUX_GPIO156__FUNC_SRCLKENA0 (MTK_PIN_NO(156) | 1) + +#define PINMUX_GPIO157__FUNC_GPIO157 (MTK_PIN_NO(157) | 0) +#define PINMUX_GPIO157__FUNC_DISP_PWM (MTK_PIN_NO(157) | 1) +#define PINMUX_GPIO157__FUNC_DBG_MON_A14 (MTK_PIN_NO(157) | 7) + +#define PINMUX_GPIO158__FUNC_GPIO158 (MTK_PIN_NO(158) | 0) +#define PINMUX_GPIO158__FUNC_LCM_RST (MTK_PIN_NO(158) | 1) +#define PINMUX_GPIO158__FUNC_DBG_MON_A16 (MTK_PIN_NO(158) | 7) + +#define PINMUX_GPIO159__FUNC_GPIO159 (MTK_PIN_NO(159) | 0) +#define PINMUX_GPIO159__FUNC_RFIC0_BSI_EN (MTK_PIN_NO(159) | 1) +#define PINMUX_GPIO159__FUNC_SPM_BSI_EN (MTK_PIN_NO(159) | 2) +#define PINMUX_GPIO159__FUNC_DBG_MON_B17 (MTK_PIN_NO(159) | 7) + +#define PINMUX_GPIO160__FUNC_GPIO160 (MTK_PIN_NO(160) | 0) +#define PINMUX_GPIO160__FUNC_RFIC0_BSI_CK (MTK_PIN_NO(160) | 1) +#define PINMUX_GPIO160__FUNC_SPM_BSI_CK (MTK_PIN_NO(160) | 2) +#define PINMUX_GPIO160__FUNC_DBG_MON_B18 (MTK_PIN_NO(160) | 7) + +#define PINMUX_GPIO161__FUNC_GPIO161 (MTK_PIN_NO(161) | 0) +#define PINMUX_GPIO161__FUNC_CMMCLK0 (MTK_PIN_NO(161) | 1) +#define PINMUX_GPIO161__FUNC_CONN_MCU_AICE_TMSC (MTK_PIN_NO(161) | 4) +#define PINMUX_GPIO161__FUNC_DBG_MON_A8 (MTK_PIN_NO(161) | 7) + +#define PINMUX_GPIO162__FUNC_GPIO162 (MTK_PIN_NO(162) | 0) + +#define PINMUX_GPIO163__FUNC_GPIO163 (MTK_PIN_NO(163) | 0) + +#define PINMUX_GPIO164__FUNC_GPIO164 (MTK_PIN_NO(164) | 0) + +#define PINMUX_GPIO165__FUNC_GPIO165 (MTK_PIN_NO(165) | 0) + +#define PINMUX_GPIO166__FUNC_GPIO166 (MTK_PIN_NO(166) | 0) + +#define PINMUX_GPIO167__FUNC_GPIO167 (MTK_PIN_NO(167) | 0) + +#define PINMUX_GPIO168__FUNC_GPIO168 (MTK_PIN_NO(168) | 0) + +#define PINMUX_GPIO169__FUNC_GPIO169 (MTK_PIN_NO(169) | 0) + +#define PINMUX_GPIO170__FUNC_GPIO170 (MTK_PIN_NO(170) | 0) + +#define PINMUX_GPIO171__FUNC_GPIO171 (MTK_PIN_NO(171) | 0) + +#define PINMUX_GPIO172__FUNC_GPIO172 (MTK_PIN_NO(172) | 0) +#define PINMUX_GPIO172__FUNC_CMCSD2 (MTK_PIN_NO(172) | 2) + +#define PINMUX_GPIO173__FUNC_GPIO173 (MTK_PIN_NO(173) | 0) +#define PINMUX_GPIO173__FUNC_CMCSD3 (MTK_PIN_NO(173) | 2) + +#define PINMUX_GPIO174__FUNC_GPIO174 (MTK_PIN_NO(174) | 0) +#define PINMUX_GPIO174__FUNC_CMCSK (MTK_PIN_NO(174) | 2) + +#define PINMUX_GPIO175__FUNC_GPIO175 (MTK_PIN_NO(175) | 0) + +#define PINMUX_GPIO176__FUNC_GPIO176 (MTK_PIN_NO(176) | 0) +#define PINMUX_GPIO176__FUNC_CMCSD0 (MTK_PIN_NO(176) | 2) + +#define PINMUX_GPIO177__FUNC_GPIO177 (MTK_PIN_NO(177) | 0) +#define PINMUX_GPIO177__FUNC_CMCSD1 (MTK_PIN_NO(177) | 2) + +#define PINMUX_GPIO178__FUNC_GPIO178 (MTK_PIN_NO(178) | 0) +#define PINMUX_GPIO178__FUNC_MSDC0_DAT0 (MTK_PIN_NO(178) | 1) +#define PINMUX_GPIO178__FUNC_DBG_MON_A0 (MTK_PIN_NO(178) | 7) + +#define PINMUX_GPIO179__FUNC_GPIO179 (MTK_PIN_NO(179) | 0) +#define PINMUX_GPIO179__FUNC_MSDC0_CLK (MTK_PIN_NO(179) | 1) +#define PINMUX_GPIO179__FUNC_DBG_MON_A1 (MTK_PIN_NO(179) | 7) + +#define PINMUX_GPIO180__FUNC_GPIO180 (MTK_PIN_NO(180) | 0) +#define PINMUX_GPIO180__FUNC_MSDC0_CMD (MTK_PIN_NO(180) | 1) +#define PINMUX_GPIO180__FUNC_DBG_MON_A2 (MTK_PIN_NO(180) | 7) + +#define PINMUX_GPIO181__FUNC_GPIO181 (MTK_PIN_NO(181) | 0) +#define PINMUX_GPIO181__FUNC_MSDC0_DAT1 (MTK_PIN_NO(181) | 1) +#define PINMUX_GPIO181__FUNC_DBG_MON_A3 (MTK_PIN_NO(181) | 7) + +#define PINMUX_GPIO182__FUNC_GPIO182 (MTK_PIN_NO(182) | 0) +#define PINMUX_GPIO182__FUNC_MSDC0_DAT5 (MTK_PIN_NO(182) | 1) +#define PINMUX_GPIO182__FUNC_DBG_MON_A4 (MTK_PIN_NO(182) | 7) + +#define PINMUX_GPIO183__FUNC_GPIO183 (MTK_PIN_NO(183) | 0) +#define PINMUX_GPIO183__FUNC_MSDC0_DAT6 (MTK_PIN_NO(183) | 1) +#define PINMUX_GPIO183__FUNC_DBG_MON_A5 (MTK_PIN_NO(183) | 7) + +#define PINMUX_GPIO184__FUNC_GPIO184 (MTK_PIN_NO(184) | 0) +#define PINMUX_GPIO184__FUNC_MSDC0_DAT4 (MTK_PIN_NO(184) | 1) +#define PINMUX_GPIO184__FUNC_DBG_MON_A59 (MTK_PIN_NO(184) | 7) + +#define PINMUX_GPIO185__FUNC_GPIO185 (MTK_PIN_NO(185) | 0) +#define PINMUX_GPIO185__FUNC_MSDC0_RSTB (MTK_PIN_NO(185) | 1) +#define PINMUX_GPIO185__FUNC_DBG_MON_A60 (MTK_PIN_NO(185) | 7) + +#define PINMUX_GPIO186__FUNC_GPIO186 (MTK_PIN_NO(186) | 0) +#define PINMUX_GPIO186__FUNC_MSDC0_DAT2 (MTK_PIN_NO(186) | 1) +#define PINMUX_GPIO186__FUNC_DBG_MON_A61 (MTK_PIN_NO(186) | 7) + +#define PINMUX_GPIO187__FUNC_GPIO187 (MTK_PIN_NO(187) | 0) +#define PINMUX_GPIO187__FUNC_MSDC0_DAT3 (MTK_PIN_NO(187) | 1) +#define PINMUX_GPIO187__FUNC_DBG_MON_A62 (MTK_PIN_NO(187) | 7) + +#define PINMUX_GPIO188__FUNC_GPIO188 (MTK_PIN_NO(188) | 0) +#define PINMUX_GPIO188__FUNC_MSDC0_DAT7 (MTK_PIN_NO(188) | 1) +#define PINMUX_GPIO188__FUNC_DBG_MON_A63 (MTK_PIN_NO(188) | 7) + +#define PINMUX_GPIO189__FUNC_GPIO189 (MTK_PIN_NO(189) | 0) +#define PINMUX_GPIO189__FUNC_MSDC0_DSL (MTK_PIN_NO(189) | 1) +#define PINMUX_GPIO189__FUNC_DBG_MON_A64 (MTK_PIN_NO(189) | 7) + +#endif/* __DTS_MT6755_PINFUNC_H */ + diff --git a/arch/arm/boot/dts/mt6755.dtsi b/arch/arm/boot/dts/mt6755.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..a8c472b008a9e8f5bfafbc7a6825c6c6c6e3f5fb --- /dev/null +++ b/arch/arm/boot/dts/mt6755.dtsi @@ -0,0 +1,3144 @@ +/* + * Mediatek's MT6755 SoC device tree source + * + * Copyright (c) 2013 MediaTek Co., Ltd. + * http://www.mediatek.com + * + */ + +#include +#include +#include +#include +#include "mt6755-pinfunc.h" +#include +/ { + model = "MT6755"; + compatible = "mediatek,MT6755"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4b434e loglevel=8"; + }; + + /* Do not put any bus before mtk-msdc, because it should be mtk-msdc.0 for partition device node usage */ + mtk-msdc.0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + + mmc0: msdc0@11230000 { + compatible = "mediatek,mt6755-mmc"; + reg = <0x11230000 0x10000>; + interrupts = ; + clocks = <&infrasys INFRA_MSDC0>; + clock-names = "MSDC0-CLOCK"; + }; + + mmc1: msdc1@11240000 { + compatible = "mediatek,mt6755-mmc"; + reg = <0x11240000 0x10000>; + interrupts = ; + clocks = <&infrasys INFRA_MSDC1>; + clock-names = "MSDC1-CLOCK"; + }; + + mmc2: msdc2@11250000 { + compatible = "mediatek,mt6755-mmc"; + reg = <0x11250000 0x10000>; + interrupts = ; + clocks = <&infrasys INFRA_MSDC2>; + clock-names = "MSDC2-CLOCK"; + }; + + /* + mmc3: msdc3@11260000 { + compatible = "mediatek,mt6755-mmc"; + reg = <0x11260000 0x10000>; + interrupts = ; + clocks = <&infrasys INFRA_MSDC3>; + clock-names = "MSDC3-CLOCK"; + };*/ + }; + + /* ATF logger SW IRQ number 281 = 32 + 249 */ + atf_logger { + compatible = "mediatek,atf_logger"; + interrupts = ; + }; + + psci { + compatible = "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + affinity_info = <0x84000004>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@000 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x000>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1144000000>; + }; + + cpu1: cpu@001 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x001>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1144000000>; + }; + + cpu2: cpu@002 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x002>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1144000000>; + }; + + cpu3: cpu@003 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x003>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1144000000>; + }; + + cpu4: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x100>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1950000000>; + }; + + cpu5: cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x101>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1950000000>; + }; + + cpu6: cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x102>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1950000000>; + }; + + cpu7: cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x103>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1950000000>; + + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + + cluster1 { + core0 { + cpu = <&cpu4>; + }; + core1 { + cpu = <&cpu5>; + }; + core2 { + cpu = <&cpu6>; + }; + core3 { + cpu = <&cpu7>; + }; + }; + }; + + idle-states { + entry-method = "arm,psci"; + + cpu_sleep_0_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <600>; + exit-latency-us = <600>; + min-residency-us = <1200>; + }; + + cluster_sleep_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <800>; + exit-latency-us = <1000>; + min-residency-us = <2000>; + }; + }; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x20000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* reserve 256KB at DRAM start + 70MB */ + atf-reserved-memory@44600000 { + compatible = "mediatek,mt6755-atf-reserved-memory"; + no-map; + reg = <0 0x44600000 0 0x40000>; + }; + + reserve-memory-ccci_md1 { + compatible = "mediatek,reserve-memory-ccci_md1"; + no-map; + size = <0 0xa100000>; /* md_size+smem_size */ + alignment = <0 0x2000000>; + alloc-ranges = <0 0x40000000 0 0xc0000000>; + }; + + reserve-memory-ccci_share { + compatible = "mediatek,reserve-memory-ccci_share"; + no-map; + size = <0 0x600000>; /* md_size+smem_size */ + alignment = <0 0x4000000>; + alloc-ranges = <0 0x40000000 0 0xc0000000>; + }; + + consys-reserve-memory { + compatible = "mediatek,consys-reserve-memory"; + no-map; + size = <0 0x100000>; + alignment = <0 0x200000>; + alloc-ranges = <0 0x40000000 0 0x60000000>; + }; + + spm-reserve-memory { + compatible = "mediatek,spm-reserve-memory"; + no-map; + size = <0 0xe000>; /* PCM_FIRMWARE_SIZE * DYNA_LOAD_PCM_MAX = 8K * 7 */ + alignment = <0 0x10000>; + alloc-ranges = <0 0x40000000 0 0x60000000>; + }; + + ram_console-reserved-memory@44400000 { + compatible = "mediatek,ram_console"; + reg = <0 0x44400000 0 0x10000>; + }; + + preloader-reserved-memory@44800000 { + compatible = "mediatek,preloader"; + reg = <0 0x44800000 0 0x100000>; + }; + + lk-reserved-memory@46000000 { + compatible = "mediatek,lk"; + reg = <0 0x46000000 0 0x400000>; + }; + + minirdump-reserved-memory@444f0000 { + compatible = "mediatek, minirdump"; + reg = <0 0x444f0000 0 0x10000>; + }; + + pstore-reserved-memory@44410000 { + compatible = "mediatek,pstore"; + reg = <0 0x44410000 0 0xe0000>; + }; + + }; + + gic: interrupt-controller@10230000 { + compatible = "mediatek,mt6735-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x10231000 0 0x1000>, + <0 0x10232000 0 0x1000>, + <0 0x10200620 0 0x1000>; + }; + + cpuxgpt@10200000 { + compatible = "mediatek,cpuxgpt"; + reg = <0 0x10200000 0 0x1000>; + interrupts = , + , + , + , + , + , + , + ; + }; + pmu { + compatible = "arm,cortex-a7-pmu"; + interrupts = , + , + , + , + , + , + , + ; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <13000000>; + }; + + clocks { + clk_null: clk_null { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + clk26m: clk26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + }; + + clk32k: clk32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32000>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + vcore_dvfs@0011cf80 { + compatible = "mediatek,mt6755-vcorefs"; + reg = <0x0011cf80 0x80>; + eint_spm_vcorefs_end@154 { + compatible = "mediatek,spm_vcorefs_err_eint"; + interrupt-parent = <&eintc>; + interrupts = <154 IRQ_TYPE_LEVEL_HIGH>; + debounce = <154 0>; + }; + }; + + chipid@08000000 { + compatible = "mediatek,chipid"; + reg = <0x08000000 0x0004>, + <0x08000004 0x0004>, + <0x08000008 0x0004>, + <0x0800000C 0x0004>; + }; + + topckgen: topckgen@10000000 { + compatible = "mediatek,mt6755-topckgen", "mediatek,topckgen"; + reg = <0x10000000 0x1000>; + #clock-cells = <1>; + }; + + infracfg_ao@10001000 { + compatible = "mediatek,infracfg_ao"; + reg = <0x10001000 0x1000>; + interrupts = ; + }; + + scpsys: scpsys@10001000 { + compatible = "mediatek,mt6755-scpsys"; + reg = <0x10001000 0x1000>, <0x10006000 0x1000>; + #clock-cells = <1>; + }; + + infrasys: infrasys@10001000 { + compatible = "mediatek,mt6755-infrasys"; + reg = <0x10001000 0x1000>; + #clock-cells = <1>; + }; + + btcvsd@10001000 { + compatible = "mediatek,audio_bt_cvsd"; + offset =<0xf00 0x800 0xfd0 0xfd4 0xfd8>; + /*INFRA MISC, conn_bt_cvsd_mask, cvsd_mcu_read, write, packet_indicator*/ + reg=<0x10001000 0x1000>, /*AUDIO_INFRA_BASE_PHYSICAL*/ + <0x18000000 0x10000>, /*PKV_PHYSICAL_BASE*/ + <0x18080000 0x8000>; /*SRAM_BANK2*/ + interrupts = ; + }; + + mt_soc_btcvsd_rx_pcm@10001000 { + compatible = "mediatek,mt_soc_btcvsd_rx_pcm"; + }; + + mt_soc_btcvsd_tx_pcm@10001000 { + compatible = "mediatek,mt_soc_btcvsd_tx_pcm"; + }; + + iocfg_0@10002000 { + compatible = "mediatek,iocfg_0"; + reg = <0x10002000 0x1000>; + }; + + syscfg_pctl_a: syscfg_pctl_a@10002000 { + compatible = "mediatek,mt6755-pctl-a-syscfg", "syscon"; + reg = <0x10002000 0x1000>; + }; + + iocfg_1@10002200 { + compatible = "mediatek,iocfg_1"; + reg = <0x10002200 0x200>; + }; + + iocfg_2@10002400 { + compatible = "mediatek,iocfg_2"; + reg = <0x10002400 0x200>; + }; + + iocfg_3@10002600 { + compatible = "mediatek,iocfg_3"; + reg = <0x10002600 0x200>; + }; + + iocfg_4@10002800 { + compatible = "mediatek,iocfg_4"; + reg = <0x10002800 0x200>; + }; + + iocfg_5@10002a00 { + compatible = "mediatek,iocfg_5"; + reg = <0x10002a00 0x200>; + }; + + perisys: perisys@10003000 { + compatible = "mediatek,mt6755-perisys"; + reg = <0x10003000 0x1000>; + #clock-cells = <1>; + }; + + dramc@10004000 { + compatible = "mediatek,dramc"; + reg = <0x10004000 0x1000>; + interrupts = ; + }; + + pio: pinctrl@10005000 { + compatible = "mediatek,mt6755-pinctrl"; + reg = <0x10005000 0x1000>; + mediatek,pctl-regmap = <&syscfg_pctl_a>; + pins-are-numbered; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio_usage_mapping:gpio { + compatible = "mediatek,gpio_usage_mapping"; + }; + + gpio@10005000 { + compatible = "mediatek,gpio"; + reg = <0x10005000 0x1000>; + }; + + sleep: sleep@10006000 { + compatible = "mediatek,sleep"; + reg = <0x10006000 0x1000>; + interrupts = , + , + , + , + , + , + , + ; + clocks = <&infrasys INFRA_I2C3>; + clock-names = "i2c3-main"; + clock-div = <10>; + #address-cells = <1>; + #size-cells = <0>; + eint_spm_vcorefs_start@152 { + compatible = "mediatek,spm_vcorefs_start_eint"; + interrupt-parent = <&eintc>; + interrupts = <152 IRQ_TYPE_LEVEL_HIGH>; + debounce = <152 0>; + }; + + eint_spm_vcorefs_end@153 { + compatible = "mediatek,spm_vcorefs_end_eint"; + interrupt-parent = <&eintc>; + interrupts = <153 IRQ_TYPE_LEVEL_HIGH>; + debounce = <153 0>; + }; + + }; + + toprgu@10007000 { + compatible = "mediatek,toprgu"; + reg = <0x10007000 0x1000>; + interrupts = ; + }; + + apxgpt@10008000 { + compatible = "mediatek,mt6755-timer", + "mediatek,mt6577-timer"; + reg = <0x10008000 0x1000>; + interrupts = ; + clocks = <&topckgen INFRA_CLK_13M>, + <&clk32k>; + }; + + rsvd@10009000 { + compatible = "mediatek,rsvd"; + reg = <0x10009000 0x1000>; + }; + + hacc@1000a000 { + compatible = "mediatek,hacc"; + reg = <0x1000a000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_SEJ>; + clock-names = "sej-main"; + + }; + + eintc: eintc@1000b000 { + compatible = "mediatek,mt-eic"; + reg = <0x1000b000 0x1000>; + interrupts = ; + mediatek,max_hw_deb_cnt = <16>; + mediatek,builtin_eint_hw_deb = <145 8 0x90>; + mediatek,max_deint_cnt = <4>; + mediatek,deint_possible_irq = <191 192 193 194>; + #interrupt-cells = <2>; + interrupt-controller; + mediatek,max_eint_num = <160>; + mediatek,mapping_table_entry = <0>; + mediatek,debtime_setting_entry = <10>; + mediatek,debtime_setting_array = <0 128>, + <1 256>, + <2 512>, + <3 1024>, + <4 16384>, + <5 32768>, + <6 65536>, + <7 131072>, + <8 262144>, + <9 524288>; + }; + + apmixedsys: apmixedsys@1000c000 { + compatible = "mediatek,mt6755-apmixedsys", "mediatek,apmixed"; + reg = <0x1000c000 0x1000>, <0x10006000 0x1000>; + #clock-cells = <1>; + }; + + fhctl@1000cf00 { + compatible = "mediatek,fhctl"; + reg = <0x1000cf00 0x100>; + }; + + pwrap: pwrap@1000d000 { + compatible = "mediatek,pwrap"; + reg = <0x1000d000 0x1000>; + interrupts = ; + + pmic: mt6351 { + compatible = "mediatek,mt6351-pmic", + "mediatek,mt6353-pmic"; + interrupt-parent = <&eintc>; + interrupts = <150 IRQ_TYPE_LEVEL_HIGH>; + debounce = <150 1000>; + interrupt-controller; + }; + }; + + devapc_ao@1000e000 { + compatible = "mediatek,devapc_ao"; + reg = <0x1000e000 0x1000>; + }; + + ddrphy@1000f000 { + compatible = "mediatek,ddrphy"; + reg = <0x1000f000 0x1000>; + }; + + keypad: keypad@10010000 { + compatible = "mediatek,mt6755-keypad", "mediatek,kp"; + reg = <0x10010000 0x1000>; + interrupts = ; + }; + + topmisc@10011000 { + compatible = "mediatek,topmisc"; + reg = <0x10011000 0x1000>; + }; + + mdcldma:mdcldma@10014000 { + compatible = "mediatek,mdcldma"; + reg = <0x10014000 0x1e00>, /*AP_CLDMA_AO*/ + <0x10015000 0x1e00>, /*MD_CLDMA_AO*/ + <0x1021b000 0x1e00>, /*AP_CLDMA_PDN*/ + <0x1021c000 0x1e00>, /*MD_CLDMA_PDN*/ + <0x10209000 0x1000>, /*AP_CCIF_BASE*/ + <0x1020a000 0x1000>; /*MD_CCIF_BASE*/ + interrupts = , /*IRQ_CLDMA*/ + , /*IRQ_CCIF*/ + ; /*IRQ_MDWDT*/ + mediatek,md_id = <0>; + mediatek,cldma_capability = <6>; + mediatek,md_smem_size = <0x100000>; /* md share memory size */ + clocks = <&scpsys SCP_SYS_MD1>; + clock-names = "scp-sys-md1-main"; + }; + + cpu_dbgapb: cpu_dbgapb { + compatible = "mediatek,hw_dbg"; + num = <8>; + reg = <0x10810000 0x1000 + 0x10910000 0x1000 + 0x10a10000 0x1000 + 0x10b10000 0x1000 + 0x10c10000 0x1000 + 0x10d10000 0x1000 + 0x10e10000 0x1000 + 0x10f10000 0x1000>; + }; + + aes_top0@10016000 { + compatible = "mediatek,aes_top0"; + reg = <0x10016000 0x1000>; + }; + + aes_top1@10017000 { + compatible = "mediatek,aes_top1"; + reg = <0x10017000 0x1000>; + }; + + modem_temp_share@10018000 { + compatible = "mediatek,modem_temp_share"; + reg = <0x10018000 0x1000>; + }; + + scp_sram@10020000 { + compatible = "mediatek,scp_sram"; + reg = <0x10020000 0x60000>; + }; + + dbgapb_base@1011a000{ + compatible = "mediatek,dbgapb_base"; + reg = <0x1011a000 0x100>;/* MD debug register */ + }; + + lastbus@10200000 { + compatible = "mediatek,lastbus"; + reg = <0x10200000 0x1000>, + <0x10003000 0x1000>; + }; + + mcucfg@10200000 { + compatible = "mediatek,mcucfg"; + reg = <0x10200000 0x1000>; + interrupts = ; + }; + + lastpc: lastpc@10200000 { + compatible = "mediatek,lastpc-v1"; + reg = <0x10200000 0x200>; /* mcucfg base */ + }; + + infracfg@10201000 { + compatible = "mediatek,infracfg"; + reg = <0x10201000 0x1000>; + }; + + sramrom@10202000 { + compatible = "mediatek,sramrom"; + reg = <0x10202000 0x1000>; + }; + + emi@10203000 { + compatible = "mediatek,emi"; + reg = <0x10203000 0x1000>; + interrupts = ; + }; + + met_emi: met_emi@10203000 { + compatible = "mediatek,met_emi"; + reg = <0x10203000 0x1000>; + }; + + sys_cirq: sys_cirq@10204000 { + compatible = "mediatek,mt6755-sys_cirq", "mediatek,mt6735-sys_cirq"; + reg = <0x10204000 0x1000>; + interrupts = ; + mediatek,cirq_num = <168>; + mediatek,spi_start_offset = <72>; + }; + + m4u@10205000 { + cell-index = <0>; + compatible = "mediatek,m4u"; + reg = <0x10205000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_SMI_COMMON>, + <&mmsys MM_DISP0_SMI_LARB0>, + <&vdecsys VDEC0_VDEC>, + <&vdecsys VDEC1_LARB>, + <&imgsys IMG_IMAGE_LARB2_SMI>, + <&vencsys VENC_VENC>, + <&vencsys VENC_LARB>, + <&scpsys SCP_SYS_VEN>, + <&scpsys SCP_SYS_VDE>, + <&scpsys SCP_SYS_ISP>, + <&scpsys SCP_SYS_DIS>; + clock-names = "smi_common", + "m4u_disp0_smi_larb0", + "m4u_vdec0_vdec", + "m4u_vdec1_larb", + "m4u_img_image_larb2_smi", + "m4u_venc_venc", + "m4u_venc_larb", + "m4u_mtcmos_ven", + "m4u_mtcmos_vde", + "m4u_mtcmos_isp", + "m4u_mtcmos_dis"; + }; + + efusec@10206000 { + compatible = "mediatek,efusec"; + reg = <0x10206000 0x1000>; + }; + + devapc@10207000 { + compatible = "mediatek,devapc"; + reg = <0x10207000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_DEVICE_APC>; + clock-names = "devapc-main"; + }; + + bus_dbg@10208000 { + compatible = "mediatek,bus_dbg-v2"; + reg = <0x10208000 0x1000>; + interrupts = ; + }; + + ap_ccif0@10209000 { + compatible = "mediatek,ap_ccif0"; + reg = <0x10209000 0x1000>; + interrupts = ; + }; + + md_ccif0@1020a000 { + compatible = "mediatek,md_ccif0"; + reg = <0x1020a000 0x1000>; + }; + + ap_ccif1@1020b000 { + compatible = "mediatek,ap_ccif1"; + reg = <0x1020b000 0x1000>; + interrupts = ; + }; + + ap2c2k_ccif@1020b000 { + compatible = "mediatek,ap2c2k_ccif"; + reg = <0x1020b000 0x1000>, //CCIF + <0x10211000 0x300>, // MD1 PCCIF + <0x10213000 0x300>; // MD3 PCCIF + interrupts = , // C2K_CCIF + ; // C2K_WDT + cell-index = <2>; + ccif,major = <169>; + ccif,minor_base = <0>; + ccif,capability = <2>; // tx busy stop + mediatek,md_smem_size = <0x400000>; //md share memory size + clocks = <&scpsys SCP_SYS_MD2>; + clock-names = "scp-sys-md2-main"; + }; + + md_ccif1@1020c000 { + compatible = "mediatek,md_ccif1"; + reg = <0x1020c000 0x1000>; + }; + + infra_mbist@1020d000 { + compatible = "mediatek,infra_mbist"; + reg = <0x1020d000 0x1000>; + }; + + dramc_nao@1020e000 { + compatible = "mediatek,dramc_nao"; + reg = <0x1020e000 0x1000>; + }; + + met_dramc_nao: met_dramc_nao@1020e000 { + compatible = "mediatek,met_dramc_nao"; + reg = <0x1020e000 0x1000>; + }; + + trng@1020f000 { + compatible = "mediatek,trng"; + reg = <0x1020f000 0x1000>; + interrupts = ; + }; + + gcpu@10210000 { + compatible = "mediatek,gcpu"; + reg = <0x10210000 0x1000>; + interrupts = ; + }; + + md2md_md1_ccif0@10211000 { + compatible = "mediatek,md2md_md1_ccif0"; + reg = <0x10211000 0x1000>; + }; + + gce@10212000 { + compatible = "mediatek,gce"; + reg = <0x10212000 0x1000>; + interrupts = , + ; + disp_mutex_reg = <0x14014000 0x1000>; + g3d_config_base = <0x13000000 0 0xffff0000>; + mmsys_config_base = <0x14000000 1 0xffff0000>; + disp_dither_base = <0x14010000 2 0xffff0000>; + mm_na_base = <0x14020000 3 0xffff0000>; + imgsys_base = <0x15000000 4 0xffff0000>; + vdec_gcon_base = <0x16000000 5 0xffff0000>; + venc_gcon_base = <0x17000000 6 0xffff0000>; + conn_peri_base = <0x18000000 7 0xffff0000>; + topckgen_base = <0x10000000 8 0xffff0000>; + kp_base = <0x10010000 9 0xffff0000>; + scp_sram_base = <0x10020000 10 0xffff0000>; + infra_na3_base = <0x10030000 11 0xffff0000>; + infra_na4_base = <0x10040000 12 0xffff0000>; + scp_base = <0x10050000 13 0xffff0000>; + mcucfg_base = <0x10200000 14 0xffff0000>; + gcpu_base = <0x10210000 15 0xffff0000>; + usb0_base = <0x11200000 16 0xffff0000>; + usb_sif_base = <0x11210000 17 0xffff0000>; + audio_base = <0x11220000 18 0xffff0000>; + msdc0_base = <0x11230000 19 0xffff0000>; + msdc1_base = <0x11240000 20 0xffff0000>; + msdc2_base = <0x11250000 21 0xffff0000>; + msdc3_base = <0x11260000 22 0xffff0000>; + ap_dma_base = <0x11000000 23 0xffff0000>; + mdp_rdma0_sof = <0>; + mdp_rsz0_sof = <1>; + mdp_rsz1_sof = <2>; + mdp_tdshp_sof = <3>; + mdp_wdma_sof = <4>; + mdp_wrot_sof = <5>; + mdp_color_sof = <6>; + disp_ovl0_sof = <7>; + disp_ovl1_sof = <8>; + disp_rdma0_sof = <9>; + disp_rdma1_sof = <10>; + disp_wdma0_sof = <11>; + disp_color_sof = <12>; + disp_ccorr_sof = <13>; + disp_aal_sof = <14>; + disp_gamma_sof = <15>; + disp_dither_sof = <16>; + disp_wdma1_sof = <17>; + disp_pwm0_sof = <18>; + disp_2l_ovl0_sof = <19>; + disp_2l_ovl1_sof = <20>; + mdp_rdma0_frame_done = <21>; + mdp_rsz0_frame_done = <22>; + mdp_rsz1_frame_done = <23>; + mdp_tdshp_frame_done = <24>; + mdp_wdma_frame_done = <25>; + mdp_wrot_write_frame_done = <26>; + mdp_wrot_read_frame_done = <27>; + mdp_color_frame_done = <28>; + disp_ovl0_frame_done = <29>; + disp_ovl1_frame_done = <30>; + disp_rdma0_frame_done = <31>; + disp_rdma1_frame_done = <32>; + disp_wdma0_frame_done = <33>; + disp_color_frame_done = <34>; + disp_ccorr_frame_done = <35>; + disp_aal_frame_done = <36>; + disp_gamma_frame_done = <37>; + disp_dither_frame_done = <38>; + disp_dpi0_frame_done = <39>; + disp_wdma1_frame_done = <40>; + disp_dsi0_frame_done = <41>; + disp_2l_ovl0_frame_done = <42>; + disp_2l_ovl1_frame_done = <43>; + stream_done_0 = <44>; + stream_done_1 = <45>; + stream_done_2 = <46>; + stream_done_3 = <47>; + stream_done_4 = <48>; + stream_done_5 = <49>; + stream_done_6 = <50>; + stream_done_7 = <51>; + stream_done_8 = <52>; + stream_done_9 = <53>; + buf_underrun_event_0 = <54>; + buf_underrun_event_1 = <55>; + dsi0_te_event = <56>; + isp_frame_done_p2_2 = <129>; + isp_frame_done_p2_1 = <130>; + isp_frame_done_p2_0 = <131>; + isp_frame_done_p1_1 = <132>; + isp_frame_done_p1_0 = <133>; + camsv_2_pass1_done = <134>; + camsv_1_pass1_done = <135>; + seninf_cam1_2_3_fifo_full = <136>; + seninf_cam0_fifo_full = <137>; + venc_done = <257>; + jpgenc_done = <258>; + jpgdec_done = <259>; + venc_mb_done = <260>; + venc_128byte_cnt_done = <261>; + apxgpt2_count = <0x10008028>; + clocks = <&infrasys INFRA_GCE>; + clock-names = "GCE"; + max_prefetch_cnt = <4>; + prefetch_size = <160 32 32 32>; + sram_share_cnt = <1>; + sram_share_engine = <8>; + sram_share_event = <460>; + }; + + cqdma: cqdma@10212c00 { + compatible = "mediatek,mt-cqdma-v1"; + reg = <0x10212c00 0x100>, + <0x10212d00 0x100>; + interrupts = , + ; + nr_channel = <2>; + clocks = <&infrasys INFRA_GCE>; + clock-names = "cqdma"; + }; + + md2md_md2_ccif0@10213000 { + compatible = "mediatek,md2md_md2_ccif0"; + reg = <0x10213000 0x1000>; + }; + + mipi_tx0@10215000 { + compatible = "mediatek,mipi_tx0"; + reg = <0x10215000 0x1000>; + }; + + mipi_rx_ana_csi0@10217000 { + compatible = "mediatek,mipi_rx_ana_csi0"; + reg = <0x10217000 0x1000>; + }; + + mipi_rx_ana_csi1@10218000 { + compatible = "mediatek,mipi_rx_ana_csi1"; + reg = <0x10218000 0x1000>; + }; + + gcpu_rsa@1021a000 { + compatible = "mediatek,gcpu_rsa"; + reg = <0x1021a000 0x1000>; + }; + + infra_md@1021d000 { + compatible = "mediatek,infra_md"; + reg = <0x1021d000 0x1000>; + }; + + bpi_bsi_slv0@1021e000 { + compatible = "mediatek,bpi_bsi_slv0"; + reg = <0x1021e000 0x1000>; + }; + + bpi_bsi_slv1@1021f000 { + compatible = "mediatek,bpi_bsi_slv1"; + reg = <0x1021f000 0x6000>; + }; + + bpi_bsi_slv2@10225000 { + compatible = "mediatek,bpi_bsi_slv2"; + reg = <0x10225000 0x1000>; + }; + + emi_mpu@10226000 { + compatible = "mediatek,emi_mpu"; + reg = <0x10226000 0x1000>; + interrupts = ; + }; + + dvfsp@10227000 { + compatible = "mediatek,mt6755-dvfsp"; + reg = <0x10227000 0x1000>, + <0x0011c000 0xf80>; + interrupts = ; + clocks = <&infrasys INFRA_I2C3>; + clock-names = "i2c"; + }; + + met_cci400@10390000 { + compatible = "mediatek,met_cci400"; + reg = <0x10390000 0x10000>; + }; + + dbgapb@10400000 { + compatible = "mediatek,dbgapb"; + reg = <0x10400000 0xc00000>; + interrupts = ; + }; + + ap_dma@11000000 { + compatible = "mediatek,ap_dma"; + reg = <0x11000000 0x1000>; + interrupts = ; + }; + + btif_tx: btif_tx@11000780 { + compatible = "mediatek,btif_tx"; + reg = <0x11000780 0x80>; + interrupts = ; + }; + + btif_rx: btif_rx@11000800 { + compatible = "mediatek,btif_rx"; + reg = <0x11000800 0x80>; + interrupts = ; + }; + + auxadc: adc_hw@11001000 { + compatible = "mediatek,mt6755-auxadc"; + reg = <0x11001000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_AUXADC>; + clock-names = "auxadc-main"; + }; + + apuart0: apuart0@11002000 { + cell-index = <0>; + compatible = "mediatek,mt6755-uart"; + reg = <0x11002000 0x1000>, /* UART base */ + <0x11000380 0x1000>, /* DMA Tx base */ + <0x11000400 0x80>; /* DMA Rx base */ + interrupts = , /* UART IRQ */ + , /* DMA Tx IRQ */ + ; /* DMA Rx IRQ */ + + clock-frequency = <26000000>; + clock-div = <1>; + clocks = <&infrasys INFRA_UART0>, <&infrasys INFRA_AP_DMA>; + clock-names = "uart0-main", "uart-apdma"; + }; + + apuart1: apuart1@11003000 { + cell-index = <1>; + compatible = "mediatek,mt6755-uart"; + reg = <0x11003000 0x1000>, /* UART base */ + <0x11000480 0x80>, /* DMA Tx base */ + <0x11000500 0x80>; /* DMA Rx base */ + interrupts = , /* UART IRQ */ + , /* DMA Tx IRQ */ + ; /* DMA Rx IRQ */ + + clock-frequency = <26000000>; + clock-div = <1>; + clocks = <&infrasys INFRA_UART1>; + clock-names = "uart1-main"; + }; + + pwm: pwm@11006000 { + compatible = "mediatek,pwm"; + reg = <0x11006000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_PWM1>, + <&infrasys INFRA_PWM2>, + <&infrasys INFRA_PWM3>, + <&infrasys INFRA_PWM4>, + <&infrasys INFRA_PWM_HCLK>, + <&infrasys INFRA_PWM>; + clock-names = "PWM1-main", + "PWM2-main", + "PWM3-main", + "PWM4-main", + "PWM-HCLK-main", + "PWM-main"; + }; + + i2c0: i2c@11007000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c0"; + cell-index = <0>; + reg = <0x11007000 0x1000>, + <0x11000100 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C0>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c1: i2c@11008000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c1"; + cell-index = <1>; + reg = <0x11008000 0x1000>, + <0x11000180 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C1>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2: i2c@11009000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c2"; + cell-index = <2>; + reg = <0x11009000 0x1000>, + <0x11000200 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C2>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + }; + + spi0: spi@1100a000 { + compatible = "mediatek,mt6755-spi"; + cell-index = <0>; + spi-padmacro = <0>; + reg = <0x1100a000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_SPI0>; + clock-names = "main"; + clock-frequency = <109000000>; + clock-div = <1>; + }; + + therm_ctrl@1100b000 { + compatible = "mediatek,mt6755-therm_ctrl"; + reg = <0x1100b000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_THERM>, <&infrasys INFRA_AUXADC>; + clock-names = "therm-main", "therm-auxadc"; + }; + + ptp_fsm@1100b000 { + compatible = "mediatek,mt6755-ptp_fsm"; + reg = <0x1100b000 0x1000>; + interrupts = ; + clocks = <&mfgsys MFG_BG3D>, <&scpsys SCP_SYS_MFG>, <&infrasys INFRA_THERM>; + clock-names = "mfg-main", "mtcmos-mfg", "therm-eem"; + }; + + btif: btif@1100c000 { + compatible = "mediatek,btif"; + reg = <0x1100c000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_BTIF>,<&infrasys INFRA_AP_DMA>; + clock-names = "btifc","apdmac"; + }; + + apirtx:irtx@1100d000 { + compatible = "mediatek,irtx"; + reg = <0x1100d000 0x1000>; + interrupts = ; + pwm_ch = <3>; + + clock-frequency = <26000000>; + clock-div = <1>; + clocks = <&infrasys INFRA_IRTX>; + clock-names = "clk-irtx-main"; + }; + + irtx_pwm:irtx_pwm { + compatible = "mediatek,irtx-pwm"; + pwm_ch = <2>; + pwm_data_invert = <0>; + }; + + disp_pwm@1100e000 { + compatible = "mediatek,disp_pwm"; + reg = <0x1100e000 0x1000>; + }; + + i2c4: i2c@1100f000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c3"; + cell-index = <3>; + reg = <0x1100f000 0x1000>, + <0x11000280 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C3>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + + mt6311@6b { + compatible = "mediatek,ext_buck"; + reg = <0x6b>; + }; + }; + + spi1: spi@11010000 { + compatible = "mediatek,mt6755-spi"; + cell-index = <1>; + spi-padmacro = <0>; + reg = <0x11010000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_SPI1>; + clock-names = "main"; + clock-frequency = <109000000>; + clock-div = <1>; + }; + + i2c3: i2c@11011000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c4"; + cell-index = <4>; + reg = <0x11011000 0x1000>, + <0x11000300 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C4>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + }; + + usb1p@11200000 { + compatible = "mediatek,usb1p"; + reg = <0x11200000 0x10000>; + interrupts = ; + }; + + usb1p_sif@11210000 { + compatible = "mediatek,usb1p_sif"; + reg = <0x11210000 0x10000>; + }; + + audiosys: audiosys@11220000 { + compatible = "mediatek,mt6755-audiosys"; + reg = <0x11220000 0x10000>; + #clock-cells = <1>; + }; + + audgpio: mt_soc_dl1_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1"; + reg = <0x11220000 0x1000>; + interrupts = ; + clocks = <&audiosys AUDIO_AFE>, + <&audiosys AUDIO_I2S>, + <&audiosys AUDIO_DAC>, + <&audiosys AUDIO_DAC_PREDIS>, + <&audiosys AUDIO_ADC>, + <&audiosys AUDIO_22M>, + <&audiosys AUDIO_24M>, + <&audiosys AUDIO_APLL_TUNER>, + <&audiosys AUDIO_APLL2_TUNER>, + <&audiosys AUDIO_TML>, + <&audiosys AUDIO_APLL1_DIV0>, + <&audiosys AUDIO_APLL2_DIV0>, + <&scpsys SCP_SYS_AUD>, + <&infrasys INFRA_AUDIO>, + <&infrasys INFRA_AUDIO_26M_BCLK>, + <&topckgen TOP_MUX_AUD1>, + <&topckgen TOP_MUX_AUD2>, + <&topckgen TOP_AD_APLL1_CK>, + <&topckgen TOP_AD_APLL2_CK>, + <&topckgen TOP_MUX_AUDINTBUS>, + <&topckgen TOP_SYSPLL1_D4>, + <&apmixedsys APMIXED_APLL1>, + <&apmixedsys APMIXED_APLL2>, + <&clk26m>; + clock-names = "aud_afe_clk", + "aud_i2s_clk", + "aud_dac_clk", + "aud_dac_predis_clk", + "aud_adc_clk", + "aud_apll22m_clk", + "aud_apll24m_clk", + "aud_apll1_tuner_clk", + "aud_apll2_tuner_clk", + "aud_tml_clk", + "aud_apll1_div0_clk", + "aud_apll2_div0_clk", + "scp_sys_aud", + "aud_infra_clk", + "aud_peri_26m_clk", + "aud_mux1_clk", + "aud_mux2_clk", + "top_ad_apll1_clk", + "top_ad_apll2_clk", + "top_mux_audio_int", + "top_sys_pll1_d4", + "apmixed_apll1_clk", + "apmixed_apll2_clk", + "top_clk26m_clk"; + }; + + mt_soc_ul1_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_capture"; + }; + + mt_soc_voice_md1@11220000 { + compatible = "mediatek,mt_soc_pcm_voice_md1"; + }; + + mt_soc_hdmi_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_hdmi"; + }; + + mt_soc_uldlloopback_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_uldlloopback"; + }; + + mt_soc_i2s0_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1_i2s0"; + }; + + mt_soc_mrgrx_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_mrgrx"; + }; + + mt_soc_mrgrx_awb_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_mrgrx_awb"; + }; + + mt_soc_fm_i2s_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_fm_i2s"; + }; + + mt_soc_fm_i2s_awb_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_fm_i2s_awb"; + }; + + mt_soc_i2s0dl1_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1_i2s0dl1"; + }; + + mt_soc_dl1_awb_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1_awb"; + }; + + mt_soc_voice_md1_bt@11220000 { + compatible = "mediatek,mt_soc_pcm_voice_md1_bt"; + }; + + mt_soc_voip_bt_out@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1_bt"; + }; + + mt_soc_voip_bt_in@11220000 { + compatible = "mediatek,mt_soc_pcm_bt_dai"; + }; + + mt_soc_tdmrx_pcm@11220000 { + compatible = "mediatek,mt_soc_tdm_capture"; + }; + + mt_soc_fm_mrgtx_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_fmtx"; + }; + + mt_soc_ul2_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_capture2"; + }; + + mt_soc_i2s0_awb_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_i2s0_awb"; + }; + + mt_soc_voice_md2@11220000 { + compatible = "mediatek,mt_soc_pcm_voice_md2"; + }; + + mt_soc_routing_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_routing"; + i2s1clk-gpio = <7 6>; + i2s1dat-gpio = <5 6>; + i2s1mclk-gpio = <9 6>; + i2s1ws-gpio = <6 6>; + }; + + mt_soc_voice_md2_bt@11220000 { + compatible = "mediatek,mt_soc_pcm_voice_md2_bt"; + }; + + mt_soc_hp_impedance_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_hp_impedance"; + }; + + mt_soc_codec_name@11220000 { + compatible = "mediatek,mt_soc_codec_63xx"; + use_hp_depop_flow = <0>; /* select 1: use, 0: not use */ + use_ul_260k = <0>; /* select 1: use, 0: not use */ + }; + + mt_soc_dummy_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dummy"; + }; + + mt_soc_codec_dummy_name@11220000 { + compatible = "mediatek,mt_soc_codec_dummy"; + }; + + mt_soc_routing_dai_name@11220000 { + compatible = "mediatek,mt_soc_dai_routing"; + }; + + mt_soc_dai_name@11220000 { + compatible = "mediatek,mt_soc_dai_stub"; + }; + + mt_soc_offload_gdma@11220000 { + compatible = "mediatek,mt_soc_pcm_offload_gdma"; + }; + + mt_soc_dl2_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl2"; + }; + + icusb@11270000 { + compatible = "mediatek,icusb"; + reg = <0x11270000 0x10000>; + }; + + usb0p@11270000 { + compatible = "mediatek,usb0p"; + reg = <0x11270000 0x10000>; + interrupts = ; + }; + + usbphy0:usbphy@0 { + compatible = "usb-nop-xceiv"; + }; + + usb0:usb3@11270000 { + compatible = "mediatek,usb3"; + reg = <0x11270000 0x10000>, <0x11280000 0x10000>, <0x11290000 0x10000>; + reg-names = "ssusb_base", "ssusb_sif", "ssusb_sif2"; + interrupts = , + ; + interrupt-names = "musb-hdrc", "xhci"; + }; + + usb_c_pinctrl:usb_c_pinctrl@0 { + compatible = "mediatek,usb_c_pinctrl"; + }; + + xhci0:usb3_xhci@11270000 { + compatible = "mediatek,usb3_xhci"; + reg = <0x11270000 0x10000>, <0x11280000 0x10000>, <0x11290000 0x10000>; + reg-names = "ssusb_base", "ssusb_sif", "ssusb_sif2"; + interrupts = ; + interrupt-names = "xhci"; + eint_usb_iddig@144 { + compatible = "mediatek,usb_iddig_bi_eint"; + interrupt-parent = <&eintc>; + interrupts = <144 IRQ_TYPE_LEVEL_LOW>; + debounce = <144 0>; + }; + }; + + usb0p_sif@11280000 { + compatible = "mediatek,usb0p_sif"; + reg = <0x11280000 0x10000>; + }; + + usb3_phy { + compatible = "mediatek,usb3_phy"; + clocks = <&infrasys INFRA_SSUSB_TOP>; + clock-names = "sssub_clk"; + }; + + usb3_sif@11280000 { + compatible = "mediatek,usb3_sif"; + reg = <0x11280000 0x10000>; + }; + + usb0p_sif2@11290000 { + compatible = "mediatek,usb0p_sif2"; + reg = <0x11290000 0x10000>; + }; + + usb3_sif2@11290000 { + compatible = "mediatek,usb3_sif2"; + reg = <0x11290000 0x10000>; + }; + + mfgsys: mfgsys@13000000 { + compatible = "mediatek,mt6755-mfgsys"; + reg = <0x13000000 0x1000>; + #clock-cells = <1>; + }; + + mfgcfg@13000000 { + compatible = "mediatek,mfgcfg"; + reg = <0x13000000 0x1000>; + }; + + mfg_vad@13001000 { + compatible = "mediatek,mfg_vad"; + reg = <0x13001000 0x1000>; + }; + + mfg_dfp@13020000 { + compatible = "mediatek,mfg_dfp"; + reg = <0x13020000 0x1000>; + }; + + mali:mali@13040000 { + compatible = "arm,malit860", "arm,mali-t86x", "arm,malit8xx", "arm,mali-midgard"; + reg = <0x13040000 0x4000>; + interrupts = , + , + ; + interrupt-names = "JOB", "MMU", "GPU"; + clock-frequency = <700000000>; + clocks = <&mfgsys MFG_BG3D>, <&mmsys MM_DISP0_SMI_COMMON>, + <&scpsys SCP_SYS_MFG>, <&scpsys SCP_SYS_DIS>; + clock-names = "mfg-main", "mfg-smi-common", "mtcmos-mfg", "mtcmos-display"; + }; + + + mmsys: mmsys_config@14000000 { + compatible = "mediatek,mmsys_config", "mediatek,mt6755-mmsys"; + reg = <0x14000000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_CAM_MDP>; + clock-names = "CAM_MDP"; + #clock-cells = <1>; + }; + + mdp_rdma@14001000 { + compatible = "mediatek,mdp_rdma"; + reg = <0x14001000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_RDMA>; + clock-names = "MDP_RDMA"; + }; + + mdp_rsz0@14002000 { + compatible = "mediatek,mdp_rsz0"; + reg = <0x14002000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_RSZ0>; + clock-names = "MDP_RSZ0"; + }; + + mdp_rsz1@14003000 { + compatible = "mediatek,mdp_rsz1"; + reg = <0x14003000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_RSZ1>; + clock-names = "MDP_RSZ1"; + }; + + mdp_wdma@14004000 { + compatible = "mediatek,mdp_wdma"; + reg = <0x14004000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_WDMA>; + clock-names = "MDP_WDMA"; + }; + + mdp_wrot@14005000 { + compatible = "mediatek,mdp_wrot"; + reg = <0x14005000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_WROT>; + clock-names = "MDP_WROT"; + }; + + mdp_tdshp@14006000 { + compatible = "mediatek,mdp_tdshp"; + reg = <0x14006000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_TDSHP>; + clock-names = "MDP_TDSHP"; + }; + + mdp_color@14007000 { + compatible = "mediatek,mdp_color"; + reg = <0x14007000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_COLOR>; + clock-names = "MDP_COLOR"; + }; + + dispsys@14008000 { + compatible = "mediatek,dispsys"; + reg = <0x14000000 0x1000>, /*DISP_SYS */ + <0x14008000 0x1000>, /*DISP_OVL0 */ + <0x14009000 0x1000>, /*DISP_OVL1 */ + <0x1400A000 0x1000>, /*DISP_RDMA0 */ + <0x1400B000 0x1000>, /*DISP_RDMA1 */ + <0x1400C000 0x1000>, /*DISP_WDMA0 */ + <0x1400D000 0x1000>, /*DISP_COLOR */ + <0x1400E000 0x1000>, /*DISP_CCORR */ + <0x1400F000 0x1000>, /*DISP_AAL */ + <0x14010000 0x1000>, /*DISP_GAMMA */ + <0x14011000 0x1000>, /*DISP_DITHER */ + <0x14012000 0x1000>, /*DISP_DSI0 */ + <0x14013000 0x1000>, /*DISP_DPI0 */ + <0x1100E000 0x1000>, /*DISP_PWM */ + <0x14014000 0x1000>, /*DISP_MUTEX */ + <0x14015000 0x1000>, /*DISP_SMI_LARB0 */ + <0x14016000 0x1000>, /*DISP_SMI_COMMOM*/ + <0x14017000 0x1000>, /*DISP_WDMA1*/ + <0x14018000 0x1000>, /*DISP_OVL0_2L*/ + <0x14019000 0x1000>, /*DISP_OVL1_2L*/ + <0x10215000 0x1000>; /*MIPITX0,real chip would use this:<0x14018000 0x1000>;*/ + + + interrupts = , /*DISP_SYS */ + , /*DISP_OVL0 */ + , /*DISP_OVL1 */ + , /*DISP_RDMA0 */ + , /*DISP_RDMA1 */ + , /*DISP_WDMA0 */ + , /*DISP_COLOR */ + , /*DISP_CCORR */ + , /*DISP_AAL */ + , /*DISP_GAMMA */ + , /*DISP_DITHER */ + , /*DISP_DSI0 */ + , /*DISP_DPI0 */ + , /*DISP_PWM */ + , /*DISP_MUTEX */ + , /*DISP_SMI_LARB0 */ + , /*DISP_SMI_COMMOM*/ + , /*DISP_WDMA1 */ + , /*DISP_OVL0_2L*/ + , /*DISP_OVL1_2L*/ + ; /*MIPITX0*/ + + clocks = <&mmsys MM_DISP0_SMI_COMMON>, + <&mmsys MM_DISP0_SMI_LARB0>, + <&mmsys MM_DISP0_DISP_OVL0>, + <&mmsys MM_DISP0_DISP_OVL1>, + <&mmsys MM_DISP0_DISP_RDMA0>, + <&mmsys MM_DISP0_DISP_RDMA1>, + <&mmsys MM_DISP0_DISP_WDMA0>, + <&mmsys MM_DISP0_DISP_COLOR>, + <&mmsys MM_DISP0_DISP_CCORR>, + <&mmsys MM_DISP0_DISP_AAL>, + <&mmsys MM_DISP0_DISP_GAMMA>, + <&mmsys MM_DISP0_DISP_DITHER>, + <&mmsys MM_DISP0_DISP_UFOE_MOUT>, + <&mmsys MM_DISP0_DISP_WDMA1>, + <&mmsys MM_DISP0_DISP_2L_OVL0>, + <&mmsys MM_DISP0_DISP_2L_OVL1>, + <&mmsys MM_DISP0_DISP_OVL0_MOUT>, + <&mmsys MM_DISP1_DSI_ENGINE>, + <&mmsys MM_DISP1_DSI_DIGITAL>, + <&mmsys MM_DISP1_DPI_ENGINE>, + <&mmsys MM_DISP1_DPI_PIXEL>, + <&infrasys INFRA_DISP_PWM>, + <&scpsys SCP_SYS_DIS>, + <&topckgen TOP_MUX_DPI0>, + <&topckgen TOP_TVDPLL_D2>, + <&topckgen TOP_TVDPLL_D4>, + <&topckgen TOP_TVDPLL_D8>, + <&topckgen TOP_TVDPLL_D16>, + <&topckgen TOP_DPI_CK>, + <&topckgen TOP_MUX_DISPPWM>, + <&topckgen TOP_UNIVPLL2_D4>, + <&topckgen TOP_OSC_D2>, + <&topckgen TOP_OSC_D8>, + <&topckgen TOP_MUX_MM>, + <&topckgen TOP_VENCPLL_CK>, + <&topckgen TOP_SYSPLL2_D2>; + + clock-names = "DISP0_SMI_COMMON", + "DISP0_SMI_LARB0", + "DISP0_DISP_OVL0", + "DISP0_DISP_OVL1", + "DISP0_DISP_RDMA0", + "DISP0_DISP_RDMA1", + "DISP0_DISP_WDMA0", + "DISP0_DISP_COLOR", + "DISP0_DISP_CCORR", + "DISP0_DISP_AAL", + "DISP0_DISP_GAMMA", + "DISP0_DISP_DITHER", + "DISP0_DISP_UFOE_MOUT", + "DISP0_DISP_WDMA1", + "DISP0_DISP_2L_OVL0", + "DISP0_DISP_2L_OVL1", + "DISP0_DISP_OVL0_MOUT", + "DISP1_DSI_ENGINE", + "DISP1_DSI_DIGITAL", + "DISP1_DPI_ENGINE", + "DISP1_DPI_PIXEL", + "DISP_PWM", + "DISP_MTCMOS_CLK", + "MUX_DPI0", + "TVDPLL_D2", + "TVDPLL_D4", + "TVDPLL_D8", + "TVDPLL_D16", + "DPI_CK", + "MUX_PWM", + "UNIVPLL2_D4", + "OSC_D2", + "OSC_D8", + "MUX_MM", + "MM_VENCPLL", + "SYSPLL2_D2"; + }; + + mhl:mhl@0 { + compatible = "mediatek,extd_dev"; + }; + + disp_ovl0@14008000 { + compatible = "mediatek,disp_ovl0"; + reg = <0x14008000 0x1000>; + interrupts = ; + }; + + disp_ovl1@14009000 { + compatible = "mediatek,disp_ovl1"; + reg = <0x14009000 0x1000>; + interrupts = ; + }; + + disp_rdma0@1400a000 { + compatible = "mediatek,disp_rdma0"; + reg = <0x1400a000 0x1000>; + interrupts = ; + }; + + disp_rdma1@1400b000 { + compatible = "mediatek,disp_rdma1"; + reg = <0x1400B000 0x1000>; + interrupts = ; + }; + + disp_wdma0@1400c000 { + compatible = "mediatek,disp_wdma0"; + reg = <0x1400c000 0x1000>; + interrupts = ; + }; + + disp_color@1400d000 { + compatible = "mediatek,disp_color"; + reg = <0x1400d000 0x1000>; + interrupts = ; + }; + + disp_ccorr@1400e000 { + compatible = "mediatek,disp_ccorr"; + reg = <0x1400e000 0x1000>; + interrupts = ; + }; + + disp_aal@1400f000 { + compatible = "mediatek,disp_aal"; + reg = <0x1400f000 0x1000>; + interrupts = ; + }; + + disp_gamma@14010000 { + compatible = "mediatek,disp_gamma"; + reg = <0x14010000 0x1000>; + interrupts = ; + }; + + disp_dither@14011000 { + compatible = "mediatek,disp_dither"; + reg = <0x14011000 0x1000>; + interrupts = ; + }; + + dsi0@14012000 { + compatible = "mediatek,dsi0"; + reg = <0x14012000 0x1000>; + interrupts = ; + }; + + dpi0@14013000 { + compatible = "mediatek,dpi0"; + reg = <0x14013000 0x1000>; + interrupts = ; + }; + + mm_mutex@14014000 { + compatible = "mediatek,mm_mutex"; + reg = <0x14014000 0x1000>; + interrupts = ; + }; + + + disp_wdma1@14017000 { + compatible = "mediatek,disp_wdma1"; + reg = <0x14017000 0x1000>; + }; + + disp_ovl0_2l@14018000 { + compatible = "mediatek,disp_ovl0_2l"; + reg = <0x14018000 0x1000>; + interrupts = ; + }; + + disp_ovl1_2l@14019000 { + compatible = "mediatek,disp_ovl1_2l"; + reg = <0x14019000 0x1000>; + interrupts = ; + }; + + smi_larb0@14015000 { + compatible = "mediatek,smi_larb0"; + reg = <0x14015000 0x1000>; + interrupts = ; + }; + + met_smi: met_smi@14016000 { + compatible = "mediatek,met_smi"; + reg = <0x14016000 0x1000>, /* SMI_COMMON_EXT */ + <0x14015000 0x1000>, /* LARB 0 */ + <0x16010000 0x10000>, /* LARB 1 */ + <0x15001000 0x1000>, /* LARB 2 */ + <0x17001000 0x1000>; /* LARB 3 */ + + clocks = <&mmsys MM_DISP0_SMI_COMMON>, + <&mmsys MM_DISP0_SMI_LARB0>, + <&imgsys IMG_IMAGE_LARB2_SMI>, + <&vdecsys VDEC1_LARB>, + <&vencsys VENC_VENC>, + <&vencsys VENC_LARB>, + <&scpsys SCP_SYS_VEN>, + <&scpsys SCP_SYS_VDE>, + <&scpsys SCP_SYS_ISP>, + <&scpsys SCP_SYS_DIS>; + clock-names = "smi-common", "smi-larb0", "img-larb2", "vdec1-larb", "venc-venc", "venc-larb", + "mtcmos-ven", "mtcmos-vde", "mtcmos-isp", "mtcmos-dis"; + }; + + smi_common@14016000 { + compatible = "mediatek,smi_common"; + reg = <0x14016000 0x1000>, /* SMI_COMMON */ + <0x14015000 0x1000>, /* LARB 0 */ + <0x16010000 0x10000>, /* LARB 1 */ + <0x15001000 0x1000>, /* LARB 2 */ + <0x17001000 0x1000>; /* LARB 3 */ + clocks = <&mmsys MM_DISP0_SMI_COMMON>, + <&mmsys MM_DISP0_SMI_LARB0>, + <&imgsys IMG_IMAGE_LARB2_SMI>, + <&vdecsys VDEC1_LARB>, + <&vencsys VENC_VENC>, + <&vencsys VENC_LARB>, + <&scpsys SCP_SYS_VEN>, + <&scpsys SCP_SYS_VDE>, + <&scpsys SCP_SYS_ISP>, + <&scpsys SCP_SYS_DIS>; + clock-names = "smi-common", "smi-larb0", "img-larb2", "vdec1-larb", "venc-venc", "venc-larb", + "mtcmos-ven", "mtcmos-vde", "mtcmos-isp", "mtcmos-dis"; + }; + + imgsys: imgsys@15000000 { + compatible = "mediatek,mt6755-imgsys"; + reg = <0x15000000 0x1000>; + #clock-cells = <1>; + }; + + ispsys@15004000 { + compatible = "mediatek,ispsys"; + reg = <0x15004000 0x9000>, /*ISP_ADDR */ + <0x1500d000 0x1000>, /*INNER_ISP_ADDR */ + <0x15000000 0x10000>, /*IMGSYS_CONFIG_ADDR */ + <0x10217000 0x3000>, /*MIPI_ANA_ADDR */ + <0x10002000 0x1000>; /*GPIO_ADDR */ + + interrupts = , /* CAM0 */ + , /* CAM1 */ + , /* CAM2 */ + , /* CAMSV0 */ + ; /* CAMSV1 */ + + clocks = <&scpsys SCP_SYS_DIS>, + <&scpsys SCP_SYS_ISP>, + <&mmsys MM_DISP0_SMI_COMMON>, + <&imgsys IMG_IMAGE_CAM_SMI>, + <&imgsys IMG_IMAGE_CAM_CAM>, + <&imgsys IMG_IMAGE_SEN_TG>, + <&imgsys IMG_IMAGE_SEN_CAM>, + <&imgsys IMG_IMAGE_CAM_SV>, + <&imgsys IMG_IMAGE_LARB2_SMI>; + + clock-names = "CG_SCP_SYS_DIS", + "CG_SCP_SYS_ISP", + "CG_DISP0_SMI_COMMON", + "CG_IMAGE_CAM_SMI", + "CG_IMAGE_CAM_CAM", + "CG_IMAGE_SEN_TG", + "CG_IMAGE_SEN_CAM", + "CG_IMAGE_CAM_SV", + "CG_IMAGE_LARB2_SMI"; + }; + + smi_larb2@15001000 { + compatible = "mediatek,smi_larb2"; + reg = <0x15001000 0x1000>; + interrupts = ; + }; + + cam0@15004000 { + compatible = "mediatek,cam0"; + reg = <0x15004000 0x1000>; + }; + + cam1@15005000 { + compatible = "mediatek,cam1"; + reg = <0x15005000 0x1000>; + interrupts = ; + }; + + cam2@15006000 { + compatible = "mediatek,cam2"; + reg = <0x15006000 0x1000>; + interrupts = ; + }; + + cam3@15007000 { + compatible = "mediatek,cam3"; + reg = <0x15007000 0x1000>; + interrupts = ; + }; + + kd_camera_hw1:kd_camera_hw1@15008000 { + compatible = "mediatek,camera_hw"; + reg = <0x15008000 0x1000>; /* SENINF_ADDR */ + + /* Camera Common Clock Framework (CCF) */ + clocks = <&topckgen TOP_MUX_CAMTG>, + <&topckgen TOP_MUX_SCAM>, + <&topckgen TOP_UNIVPLL_D26>, + <&topckgen TOP_UNIVPLL2_D2>; + clock-names = "TOP_CAMTG_SEL","TOP_MUX_SCAM","TOP_UNIVPLL_D26","TOP_UNIVPLL2_D2"; + vcama-supply = <&mt_pmic_vcama_ldo_reg>; + vcamd-supply = <&mt_pmic_vcamd_ldo_reg>; + vcamio-supply = <&mt_pmic_vcamio_ldo_reg>; + }; + + kd_camera_hw2:kd_camera_hw2@15008000 { + compatible = "mediatek,camera_hw2"; + reg = <0x15008000 0x1000>; /* SENINF_ADDR */ + }; + + seninf@15008000 { + compatible = "mediatek,seninf"; + reg = <0x15008000 0x1000>; + interrupts = ; + }; + + camsv@15009000 { + compatible = "mediatek,camsv"; + reg = <0x15009000 0x1000>; + interrupts = ; + }; + + fdvt@1500b000 { + compatible = "mediatek,fdvt"; + reg = <0x1500b000 0x1000>; + interrupts = ; + clocks = <&scpsys SCP_SYS_DIS>, + <&scpsys SCP_SYS_ISP>, + <&mmsys MM_DISP0_SMI_COMMON>, + <&imgsys IMG_IMAGE_FD>; + clock-names = "FD-SCP_SYS_DIS", + "FD-SCP_SYS_ISP", + "FD-MM_DISP0_SMI_COMMON", + "FD-IMG_IMAGE_FD"; + }; + + mipi_rx@1500c000 { + compatible = "mediatek,mipi_rx"; + reg = <0x1500c000 0x1000>; + }; + + cam0_inner@1500d000 { + compatible = "mediatek,cam0_inner"; + reg = <0x1500d000 0x1000>; + }; + + cam2_inner@1500e000 { + compatible = "mediatek,cam2_inner"; + reg = <0x1500e000 0x1000>; + }; + + cam3_inner@1500f000 { + compatible = "mediatek,cam3_inner"; + reg = <0x1500f000 0x1000>; + }; + + vdecsys: vdec_gcon@16000000 { + compatible = "mediatek,mt6755-vdec_gcon", "mediatek,mt6755-vdecsys"; + reg = <0x16000000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_SMI_COMMON>, <&vdecsys VDEC0_VDEC>, + <&vdecsys VDEC1_LARB>, <&vencsys VENC_VENC>, + <&vencsys VENC_LARB>, <&topckgen TOP_MUX_VDEC>, + <&topckgen TOP_SYSPLL1_D2>, <&topckgen TOP_SYSPLL1_D4>, + <&scpsys SCP_SYS_VDE>, <&scpsys SCP_SYS_VEN>, <&scpsys SCP_SYS_DIS>; + clock-names = "MT_CG_DISP0_SMI_COMMON", "MT_CG_VDEC0_VDEC", + "MT_CG_VDEC1_LARB", "MT_CG_VENC_VENC", + "MT_CG_VENC_LARB", "MT_CG_TOP_MUX_VDEC", + "MT_CG_TOP_SYSPLL1_D2", "MT_CG_TOP_SYSPLL1_D4", + "MT_SCP_SYS_VDE", "MT_SCP_SYS_VEN", "MT_SCP_SYS_DIS"; + #clock-cells = <1>; + }; + + smi_larb1@16010000 { + compatible = "mediatek,smi_larb1"; + reg = <0x16010000 0x10000>; + interrupts = ; + }; + + vdec_full_top: vdec_full_top@16020000 { + compatible = "mediatek,mt6755-vdec_full_top"; + reg = <0x16020000 0x10000>; + interrupts = ; + }; + + vencsys: venc_gcon@17000000 { + compatible = "mediatek,mt6755-venc_gcon", "mediatek,mt6755-vencsys"; + reg = <0x17000000 0x1000>; + interrupts = ; + #clock-cells = <1>; + }; + + smi_larb3@17001000 { + compatible = "mediatek,smi_larb3"; + reg = <0x17001000 0x1000>; + interrupts = ; + }; + + venc: venc@17002000 { + compatible = "mediatek,mt6755-venc"; + reg = <0x17002000 0x1000>; + interrupts = ; + }; + + jpgenc@17003000 { + compatible = "mediatek,jpgenc"; + reg = <0x17003000 0x1000>; + interrupts = ; + clocks = <&scpsys SCP_SYS_DIS>, + <&mmsys MM_DISP0_SMI_COMMON>, + <&scpsys SCP_SYS_VEN>, + <&vencsys VENC_LARB>, + <&vencsys VENC_JPGENC>; + + clock-names = "disp-mtcmos", + "disp-smi", + "venc-mtcmos", + "venc-larb", + "venc-jpgenc"; + }; + + jpgdec@17004000 { + compatible = "mediatek,jpgdec"; + reg = <0x17004000 0x1000>; + interrupts = ; + clocks = <&scpsys SCP_SYS_DIS>, + <&mmsys MM_DISP0_SMI_COMMON>, + <&scpsys SCP_SYS_VEN>, + <&vencsys VENC_LARB>, + <&vencsys VENC_JPGDEC>; + + clock-names = "disp-mtcmos", + "disp-smi", + "venc-mtcmos", + "venc-larb", + "venc-jpgdec"; + }; + + consys:consys@18070000 { + compatible = "mediatek,mt6755-consys"; + reg = <0x18070000 0x0200>, /*CONN_MCU_CONFIG_BASE */ + <0x10007000 0x0100>, /*AP_RGU_BASE */ + <0x10000000 0x2000>, /*TOPCKGEN_BASE */ + <0x10006000 0x1000>; /*SPM_BASE */ + interrupts = , /*BGF_EINT */ + ; /*WDT_EINT */ + clocks = <&scpsys SCP_SYS_CONN>; + clock-names = "conn"; + /* vcn18-supply = <&mt_pmic_vcn18_ldo_reg>; + vcn28-supply = <&mt_pmic_vcn28_ldo_reg>; + vcn33_bt-supply = <&mt_pmic_vcn33_bt_ldo_reg>; + vcn33_wifi-supply = <&mt_pmic_vcn33_wifi_ldo_reg>; */ + }; + + wifi@180f0000 { + compatible = "mediatek,wifi"; + reg = <0x180f0000 0x005c>; + interrupts = ; + clocks = <&infrasys INFRA_AP_DMA>; + clock-names = "wifi-dma"; + }; + + ccci_off@0 { + compatible = "mediatek,ccci_off"; + clocks = <&scpsys SCP_SYS_MD1>; + clock-names = "scp-sys-md1-main"; + }; + + ccci_util_cfg { + compatible = "mediatek,ccci_util_cfg"; + mediatek,md1-smem-size = <0x200000>; + mediatek,md3-smem-size = <0x200000>; + mediatek,md1md3-smem-size = <0x200000>; + mediatek,version = <0x1>; + }; + + nfc:nfcC@0 { + compatible = "mediatek,nfc-gpio-v2"; + gpio-ven = <28>; + gpio-rst = <25>; + gpio-eint = <27>; + gpio-irq = <26>; + }; + + gps { + compatible = "mediatek,gps"; + }; + + accdet: accdet@ { + compatible = "mediatek,mt6755-accdet"; + }; + + bat_notify { + compatible = "mediatek,bat_notify"; + }; + + battery { + compatible = "mediatek,battery"; + }; + + flashlight: flashlight { + compatible = "mediatek,mt6755-flashlight"; + }; + + bat_metter { + compatible = "mediatek,bat_meter"; + /* cust_charging.h */ + /* stop charging while in talking mode */ + stop_charging_in_takling = <1 >; + talking_recharge_voltage = <3800 >; + talking_sync_time = <60 >; + + /* Battery Temperature Protection */ + mtk_temperature_recharge_support = <1 >; + max_charge_temperature = <50 >; + max_charge_temperature_minus_x_degree = <47 >; + min_charge_temperature = <0 >; + min_charge_temperature_plus_x_degree = <6 >; + err_charge_temperature = <0xff >; + + /* Linear Charging Threshold */ + v_pre2cc_thres = <3400 >; /* unit: mV */ + v_cc2topoff_thres = <4050 >; + recharging_voltage = <4110 >; + charging_full_current = <100 >; /* unit: mA */ + + /* Charging Current Setting */ + config_usb_if = <0 >; + usb_charger_current_suspend = <0 >; /* Unit: 0.01 mA */ + usb_charger_current_unconfigured = <7000 >; /* Unit: 0.01 mA */ + usb_charger_current_configured = <50000 >; /* Unit: 0.01 mA */ + usb_charger_current = <50000 >; /* Unit: 0.01 mA */ + ac_charger_current = <80000 >; /* Unit: 0.01 mA */ + non_std_ac_charger_current = <50000 >; /* Unit: 0.01 mA */ + charging_host_charger_current = <65000 >; /* Unit: 0.01 mA */ + apple_0_5a_charger_current = <50000 >; /* Unit: 0.01 mA */ + apple_1_0a_charger_current = <65000 >; /* Unit: 0.01 mA */ + apple_2_1a_charger_current = <80000 >; /* Unit: 0.01 mA */ + + + /* charger error check */ + bat_low_temp_protect_enable = <0 >; + v_charger_enable = <0 >; /* 1:on , 0:off */ + v_charger_max = <6500 >; /* unit: mV */ + v_charger_min = <4400 >; + + /* Tracking TIME */ + onehundred_percent_tracking_time = <10 >; /* Unit: second */ + npercent_tracking_time = <20 >; /* Unit: second */ + sync_to_real_tracking_time = <60 >; /* Unit: second */ + v_0percent_tracking = <3450 >; /* Unit: mV */ + + /* High battery support */ + high_battery_voltage_support = <0 >; + + /* cust_battery_meter.h */ + /* ADC resistor */ + r_bat_sense = <4 >; + r_i_sense = <4 >; + r_charger_1 = <330 >; + r_charger_2 = <39 >; + temperature_t0 = <110 >; + temperature_t1 = <0 >; + temperature_t2 = <25 >; + temperature_t3 = <50 >; + temperature_t = <255 >; /* this should be fixed, never change the value */ + fg_meter_resistance = <0 >; + + /* Qmax for 0mA */ + q_max_pos_50 = <2743 >; + q_max_pos_25 = <2707 >; + q_max_pos_0 = <840 >; + q_max_neg_10 = <807 >; + /* Qmax for 400mA, said high current */ + q_max_pos_50_h_current = <2688 >; + q_max_pos_25_h_current = <2653 >; + q_max_pos_0_h_current = <823 >; + q_max_neg_10_h_current = <791 >; + /* Discharge percentage, 1: D5, 0: D2 */ + oam_d5 = <1 >; + + change_tracking_point = <1 >; + /* SW OCV tracking setting */ + cust_tracking_point = <0 >; + cust_r_sense = <56 >; + cust_hw_cc = <0 >; + aging_tuning_value = <103 >; + cust_r_fg_offset = <0 >; + ocv_board_compesate = <0 >; + r_fg_board_base = <1000 >; + r_fg_board_slope = <1000 >; + car_tune_value = <118 >; + + /* HW Fuel gague */ + current_detect_r_fg = <10 >; /* Unit: mA */ + minerroroffset = <1000 >; + fg_vbat_average_size = <18 >; + r_fg_value = <10 >; /* Unit: mOhm */ + + /* HW Fuel gague 2.0*/ + difference_hwocv_rtc = <30 >; + difference_hwocv_swocv = <10>; + difference_swocv_rtc = <10>; + max_swocv = <3>; + + difference_voltage_update = <20>; + aging1_load_soc = <70>; + aging1_update_soc = <30>; + batterypseudo100 = <95>; + batterypseudo1 = <11>; + + q_max_by_sys = <1>; /*8. qmax variant by system drop voltage.*/ + q_max_sys_voltage = <3350>; + shutdown_gauge0 = <1>; + shutdown_gauge1_xmins = <1>; + shutdown_gauge1_mins = <60>; + + shutdown_system_voltage = <3400>; + charge_tracking_time = <60>; + discharge_tracking_time = <10>; + + recharge_tolerance = <10>; + + sync_ui_soc_imm =<0>; + mtk_enable_aging_algorithm = <1>; + md_sleep_current_check = <1>; + q_max_by_current = <0>; + + /* HW Fuel gague 1.0*/ + cust_poweron_delta_capacity_tolrance = <40 >; + cust_poweron_low_capacity_tolrance = <5 >; + cust_poweron_max_vbat_tolrance = <90 >; + cust_poweron_delta_vbat_tolrance = <30 >; + cust_poweron_delta_hw_sw_ocv_capacity_tolrance = <10 >; + + /* Fixed battery temperature */ + fixed_tbat_25 = <0 >; + /* Dynamic change wake up period of battery thread when suspend */ + vbat_normal_wakeup = <3600 >; /* Unit: mV */ + vbat_low_power_wakeup = <3500 >; /* Unit: mV */ + normal_wakeup_period = <5400 >; /* Unit: second */ + low_power_wakeup_period = <300 >; /* Unit: second */ + close_poweroff_wakeup_period = <30 >; /* Unit: second */ + + rbat_pull_up_r = <24000 >; + rbat_pull_up_volt = <1800 >; + + + batt_temperature_table_num = <17 >; + batt_temperature_table = < + (-20) 68237 + (-15) 53650 + (-10) 42506 + (-5) 33892 + 0 27219 + 5 22021 + 10 17926 + 15 14674 + 20 12081 + 25 10000 30 8315 35 6948 40 5834 45 4917 50 4161 55 3535 60 3014 >; + battery_profile_t0_num = <82 >; + battery_profile_t0 = <0 4303 + 6 4281 + 13 4261 + 18 4240 + 25 4217 + 31 4194 + 38 4169 + 44 4145 + 51 4117 + 56 4088 + 62 4068 + 69 4047 + 75 4019 + 82 3997 + 87 3981 + 94 3967 + 100 3956 + 107 3942 + 113 3929 + 118 3913 + 125 3895 + 128 3880 + 135 3869 + 141 3857 + 147 3848 + 154 3839 + 159 3830 + 166 3823 + 172 3818 + 179 3811 + 185 3806 + 192 3800 + 197 3796 + 203 3791 + 210 3787 + 216 3781 + 223 3775 + 228 3770 + 235 3760 + 241 3752 + 248 3742 + 254 3731 + 259 3721 + 266 3713 + 272 3704 + 279 3698 + 285 3688 + 292 3665 + 297 3613 + 304 3526 + 307 3466 + 310 3444 + 313 3424 + 313 3404>; + battery_profile_t1_num = <82 >; + battery_profile_t1 = <0 4316 + 7 4283 + 12 4244 + 20 4210 + 22 4185 + 29 4164 + 34 4144 + 41 4128 + 49 4109 + 54 4093 + 61 4080 + 63 4069 + 71 4047 + 78 4023 + 83 4003 + 90 3989 + 95 3977 + 100 3967 + 105 3955 + 112 3940 + 120 3923 + 124 3907 + 132 3891 + 139 3877 + 141 3864 + 149 3855 + 154 3846 + 161 3837 + 166 3831 + 173 3823 + 181 3815 + 183 3811 + 190 3804 + 195 3799 + 202 3794 + 210 3790 + 215 3785 + 222 3782 + 224 3778 + 232 3773 + 237 3768 + 244 3761 + 251 3753 + 256 3742 + 261 3727 + 266 3712 + 273 3704 + 278 3701 + 285 3698 + 293 3692 + 298 3680 + 302 3625 + 307 3528 + 315 3472 + 322 3403 + 324 3323 + 324 3267 + 324 3230 + 327 3203 + 327 3180 + 327 3157 + 327 3141 + 327 3124 + 327 3109 + 327 3096 + 327 3084 + 327 3079 + 327 3067 + 327 3058 + 327 3047 + 327 3041 + 327 3032 + 327 3029 + 327 3018 + 327 3008 + 327 3002 + 327 3003 + 327 2995 + 327 2985 + 327 2983 + 327 2979 + 327 2967>; + battery_profile_t2_num = <82 >; + battery_profile_t2 = <0 4328 + 2 4303 + 4 4283 + 5 4263 + 7 4245 + 9 4227 + 11 4209 + 13 4189 + 14 4173 + 16 4155 + 19 4138 + 21 4121 + 22 4104 + 24 4087 + 26 4072 + 28 4058 + 30 4041 + 31 4025 + 33 4011 + 35 3996 + 37 3983 + 39 3972 + 40 3958 + 42 3945 + 44 3926 + 46 3907 + 48 3889 + 49 3876 + 52 3865 + 54 3854 + 56 3846 + 57 3840 + 59 3832 + 61 3824 + 63 3818 + 65 3813 + 66 3805 + 68 3801 + 70 3794 + 72 3789 + 74 3784 + 75 3778 + 77 3772 + 79 3765 + 81 3753 + 84 3745 + 85 3733 + 87 3717 + 89 3699 + 91 3692 + 92 3691 + 94 3689 + 96 3687 + 98 3668 + 100 3597 + 101 3497 + 103 3391 + 104 3157 + 105 3073 + 105 3022 + 105 2992 + 105 2969 + 105 2958 + 105 2946 + 105 2934 + 105 2925 + 105 2913 + 105 2910 + 105 2900 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891>; + battery_profile_t3_num = <82 >; + battery_profile_t3 = <0 4331 + 2 4305 + 3 4284 + 5 4265 + 7 4244 + 10 4225 + 11 4206 + 13 4188 + 15 4170 + 16 4153 + 18 4135 + 20 4119 + 22 4102 + 23 4085 + 26 4069 + 28 4054 + 29 4038 + 31 4023 + 33 4010 + 35 3996 + 36 3984 + 38 3970 + 40 3958 + 41 3947 + 44 3934 + 46 3921 + 47 3904 + 49 3884 + 51 3868 + 53 3857 + 54 3848 + 56 3838 + 59 3832 + 60 3824 + 62 3817 + 64 3811 + 66 3806 + 67 3800 + 69 3794 + 71 3790 + 72 3784 + 74 3777 + 77 3763 + 79 3758 + 80 3750 + 82 3742 + 84 3733 + 85 3723 + 87 3709 + 89 3694 + 91 3678 + 93 3676 + 95 3675 + 97 3674 + 98 3669 + 100 3625 + 102 3547 + 104 3495 + 105 3458 + 107 3331 + 109 3140 + 109 3078 + 109 3033 + 109 3001 + 109 2980 + 110 2960 + 110 2944 + 110 2932 + 110 2921 + 110 2913 + 110 2903 + 110 2899 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889>; + + r_profile_t0_num = <82 >; + r_profile_t0 = <408 4303 + 408 4281 + 415 4261 + 425 4240 + 430 4217 + 440 4194 + 463 4169 + 490 4145 + 525 4117 + 573 4088 + 615 4068 + 650 4047 + 675 4019 + 685 3997 + 705 3981 + 713 3967 + 720 3956 + 733 3942 + 728 3929 + 738 3913 + 725 3895 + 735 3880 + 745 3869 + 748 3857 + 760 3848 + 773 3839 + 783 3830 + 803 3823 + 820 3818 + 835 3811 + 863 3806 + 888 3800 + 903 3796 + 925 3791 + 955 3787 + 975 3781 + 1000 3775 + 1035 3770 + 1058 3760 + 1090 3752 + 1105 3742 + 1135 3731 + 1168 3721 + 1210 3713 + 1255 3704 + 1345 3698 + 1430 3688 + 1518 3665 + 1570 3613 + 1618 3526 + 1668 3466 + 1613 3444 + 1563 3424 + 1510 3404 + 1460 3381 + 1400 3357 + 1333 3332 + 1283 3310 + 1233 3291 + 1198 3274 + 1155 3259 + 1128 3245 + 1093 3234 + 1075 3221 + 1053 3212 + 1023 3204 + 1018 3193 + 1005 3186 + 978 3179 + 960 3168 + 940 3162 + 895 3157 + 890 3151 + 863 3143 + 925 3133 + 893 3125 + 893 3125 + 893 3125 + 893 3125 + 893 3125 + 893 3125 + 893 3125>; + r_profile_t1_num = <82 >; + r_profile_t1 = <258 4316 + 258 4283 + 278 4244 + 303 4210 + 333 4185 + 343 4164 + 350 4144 + 365 4128 + 370 4109 + 370 4093 + 380 4080 + 403 4069 + 395 4047 + 403 4023 + 403 4003 + 413 3989 + 418 3977 + 420 3967 + 423 3955 + 415 3940 + 410 3923 + 400 3907 + 393 3891 + 393 3877 + 388 3864 + 395 3855 + 403 3846 + 405 3837 + 415 3831 + 425 3823 + 430 3815 + 443 3811 + 450 3804 + 465 3799 + 475 3794 + 483 3790 + 490 3785 + 503 3782 + 520 3778 + 533 3773 + 545 3768 + 563 3761 + 588 3753 + 600 3742 + 608 3727 + 615 3712 + 635 3704 + 670 3701 + 710 3698 + 765 3692 + 840 3680 + 880 3625 + 915 3528 + 1080 3472 + 1323 3403 + 1315 3323 + 1180 3267 + 1080 3230 + 1010 3203 + 958 3180 + 925 3157 + 888 3141 + 860 3124 + 810 3109 + 788 3096 + 765 3084 + 700 3079 + 745 3067 + 680 3058 + 685 3047 + 650 3041 + 683 3032 + 615 3029 + 643 3018 + 660 3008 + 635 3002 + 530 3003 + 640 2995 + 595 2985 + 535 2983 + 463 2979 + 600 2967>; + r_profile_t2_num = <82 >; + r_profile_t2 = <155 4328 + 155 4303 + 155 4283 + 158 4263 + 158 4245 + 163 4227 + 165 4209 + 165 4189 + 170 4173 + 170 4155 + 173 4138 + 173 4121 + 173 4104 + 178 4087 + 180 4072 + 185 4058 + 188 4041 + 190 4025 + 200 4011 + 200 3996 + 205 3983 + 218 3972 + 215 3958 + 215 3945 + 200 3926 + 188 3907 + 173 3889 + 168 3876 + 163 3865 + 160 3854 + 163 3846 + 168 3840 + 170 3832 + 170 3824 + 170 3818 + 178 3813 + 175 3805 + 183 3801 + 180 3794 + 183 3789 + 185 3784 + 183 3778 + 185 3772 + 183 3765 + 173 3753 + 173 3745 + 173 3733 + 173 3717 + 173 3699 + 170 3692 + 175 3691 + 185 3689 + 198 3687 + 205 3668 + 208 3597 + 240 3497 + 273 3391 + 908 3157 + 705 3073 + 595 3022 + 513 2992 + 465 2969 + 413 2958 + 380 2946 + 368 2934 + 360 2925 + 335 2913 + 275 2910 + 315 2900 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891>; + r_profile_t3_num = <82 >; + r_profile_t3 = <123 4331 + 123 4305 + 128 4284 + 130 4265 + 130 4244 + 130 4225 + 128 4206 + 125 4188 + 130 4170 + 133 4153 + 133 4135 + 138 4119 + 138 4102 + 140 4085 + 140 4069 + 143 4054 + 140 4038 + 143 4023 + 148 4010 + 153 3996 + 155 3984 + 155 3970 + 165 3958 + 175 3947 + 175 3934 + 178 3921 + 170 3904 + 148 3884 + 135 3868 + 135 3857 + 133 3848 + 133 3838 + 135 3832 + 135 3824 + 135 3817 + 143 3811 + 145 3806 + 148 3800 + 145 3794 + 153 3790 + 150 3784 + 150 3777 + 133 3763 + 143 3758 + 140 3750 + 138 3742 + 135 3733 + 135 3723 + 133 3709 + 133 3694 + 130 3678 + 130 3676 + 138 3675 + 148 3674 + 160 3669 + 158 3625 + 170 3547 + 208 3495 + 220 3458 + 265 3331 + 855 3140 + 725 3078 + 600 3033 + 528 3001 + 460 2980 + 400 2960 + 380 2944 + 355 2932 + 315 2921 + 303 2913 + 308 2903 + 255 2899 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889>; + }; + + mt3326-gps@ffffffff { + compatible = "mediatek,mt3326-gps"; + }; + + gsensor@0 { + compatible = "mediatek,gsensor"; + /* vgsensor-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + alsps:als_ps@0 { + compatible = "mediatek,als_ps"; + /* valsps-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + gyroscope:gyroscope@0 { + compatible = "mediatek,gyroscope"; + /* vgyro-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + barometer@0 { + compatible = "mediatek,barometer"; + /* vbarometer-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + m_baro_pl@0 { + compatible = "mediatek,m_baro_pl"; + /* vbarometer-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + msensor@0 { + compatible = "mediatek,msensor"; + /* vmsensor-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + mtkfb: mtkfb { + compatible = "mediatek,mtkfb"; + }; + + touch: touch { + compatible = "mediatek,mt6755-touch"; + /* VTOUCH-supply = <&mt_pmic_vgp1_ldo_reg>; */ + }; + + psci { + compatible = "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + affinity_info = <0x84000004>; + }; + + gpufreq { + compatible = "mediatek,mt6755-gpufreq"; + clocks = + <&topckgen TOP_MUX_MFG>, + <&topckgen TOP_MMPLL_CK>, + <&topckgen TOP_SYSPLL_D3>; + clock-names = + "clk_mux", + "clk_main_parent", + "clk_sub_parent"; + }; + }; + + mobicore { + compatible = "trustonic,mobicore"; + interrupts = ; + }; + + utos { + compatible = "microtrust,utos"; + interrupts = , + , + , + , + , + , + , + ; + }; + + /* Add dummy nodes for cust.dtsi */ + als: als { + compatible = "mediatek, als-eint"; + status = "disabled"; + }; + + gse_1: gse_1 { + compatible = "mediatek, gse_1-eint"; + status = "disabled"; + }; + + ext_buck_oc: ext_buck_oc { + compatible = "mediatek, ext_buck_oc-eint"; + status = "disabled"; + }; + + msdc1_ins: msdc1_ins { + compatible = "mediatek, msdc1_ins-eint"; + status = "disabled"; + }; + + gyro: gyro { + compatible = "mediatek, gyro-eint"; + status = "disabled"; + }; + + mse: mse { + compatible = "mediatek, mse-eint"; + status = "disabled"; + }; + + mrdump_ext_rst: mrdump_ext_rst { + compatible = "mediatek, mrdump_ext_rst-eint"; + status = "disabled"; + }; + + irq_nfc: irq_nfc { + compatible = "mediatek, irq_nfc-eint"; + status = "disabled"; + }; + + eint_wpc: eint_wpc { + compatible = "mediatek, eint_wpc-eint"; + status = "disabled"; + }; + + dsi_te: dsi_te { + compatible = "mediatek, dsi_te-eint"; + status = "disabled"; + }; + + usb_typec: usb_typec { + compatible = "mediatek,fusb300-eint"; + status = "disabled"; + }; + + swtp: swtp { + compatible = "mediatek, swtp-eint"; + }; + + rf_clock_buffer_ctrl:rf_clock_buffer { + compatible = "mediatek,rf_clock_buffer"; + mediatek,clkbuf-quantity = <4>; + mediatek,clkbuf-config = <2 0 1 1>; + mediatek,clkbuf-driving-current = <2 2 2 2>; + }; + + pmic_clock_buffer_ctrl:pmic_clock_buffer { + compatible = "mediatek,pmic_clock_buffer"; + mediatek,clkbuf-quantity = <4>; + mediatek,clkbuf-config = <2 1 1 2>; + mediatek,clkbuf-driving-current = <2 2 2 2>; + }; + + ext_buck_vmd1:ext_buck_vmd1 { + compatible = "mediatek,ext_buck_vmd1"; + }; +}; +/*/include/ "cust_pmic.dtsi"*/ + +#include "cust_mt6755_msdc.dtsi" + +#include + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#include "mt6353.dtsi" +#else +#include "mt6351.dtsi" +#endif diff --git a/arch/arm/boot/dts/vz6750_35_i_n.dts b/arch/arm/boot/dts/vz6750_35_i_n.dts new file mode 100644 index 0000000000000000000000000000000000000000..8fd1dd2f8e61436de2f521b2f2817b3cd2d73961 --- /dev/null +++ b/arch/arm/boot/dts/vz6750_35_i_n.dts @@ -0,0 +1,907 @@ + +/dts-v1/; + +#include "mt6755.dtsi" +#include "cust.dtsi" + +/ { + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x3e800000>; + }; + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4B434E loglevel=8"; + + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base_h = <0x0>; + atag,videolfb-fb_base_l = <0x7E800000>; + atag,videolfb-islcmfound = <1>; + /* because no lk, so lcm is not inited */ + atag,videolfb-islcm_inited = <0>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35695_fhd_dsi_cmd_truly_nt50358_drv"; + }; + led0:led@0 { + compatible = "mediatek,red"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led1:led@1 { + compatible = "mediatek,green"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led2:led@2 { + compatible = "mediatek,blue"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led3:led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led4:led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led5:led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led6:led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <5>; + }; +/* start sensor */ + cust_accel@0 { + compatible = "mediatek,mpu6515a"; + i2c_num = <1>; + /* i2c_addr = <0x4c 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <16>; + is_batch_supported = <1>; + }; + + cust_alsps@0 { + compatible = "mediatek,cm36686"; + i2c_num = <1>; + i2c_addr = <0x60 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als = <1>; + power_id = <0xffff>; + power_vol = <0>; +/* Total has 15 level*/ + als_level = <0 257 637 1027 2297 5588 6730 11301 20449 25768 31122 45552 57937 57937 57937>; +/* Total has 16 range*/ + als_value = <0 132 304 502 1004 2003 3006 5006 8004 10000 12000 16000 20000 20000 20000 20000>; + ps_threshold_high = <70>; + ps_threshold_low = <40>; + is_batch_supported_ps = <1>; + is_batch_supported_als = <1>; + }; + + cust_mag@0 { + compatible = "mediatek,akm8963"; + i2c_num = <1>; + /* i2c_addr = <0x0F 0 0 0>; */ + direction = <8>; + power_id = <0xffff>; + power_vol = <0>; + /* is_batch_supported = <0>; */ + }; + + cust_gyro@0 { + compatible = "mediatek,mpu6515g"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + + cust_baro@0 { + compatible = "mediatek,bmp280new"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <32>; + is_batch_supported = <0>; + }; +/* end sensor */ +}; +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <6>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 80 220 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; +}; + +/* TOUCH start */ +&touch { + tpd-resolution = <1080 1920>; + use-tpd-button = <0>; + tpd-key-num = <3>; + tpd-key-local= <139 172 158 0>; + tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>; + tpd-max-touch-num = <5>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <146>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <0 0 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: eint0default { + }; + ctp_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_sub_vcamd0: cam1@4 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_sub_vcamd1: cam1@5 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + /*camera_pins_cam_ldo_vcama_0: cam@vcama0 { + }; + camera_pins_cam_ldo_vcama_1: cam@vcama1 { + };*/ + camera_pins_default: camdefault { + }; + +}; + +&kd_camera_hw1 { + pinctrl-names = "default", + "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo_sub_vcamd_0", "cam_ldo_sub_vcamd_1"; + /*"cam2_rst0", "cam2_rst1", "cam2_pnd0", "cam2_pnd1", + "cam_ldo_vcama_0", "cam_ldo_vcama_1";*/ + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_sub_vcamd0>; + pinctrl-10 = <&camera_pins_sub_vcamd1>; + /* for main2 */ + /*pinctrl-9 = <&camera_pins_cam2_rst0>; + pinctrl-10 = <&camera_pins_cam2_rst1>; + pinctrl-11 = <&camera_pins_cam2_pnd0>; + pinctrl-12 = <&camera_pins_cam2_pnd1>;*/ + /* for ldo control by gpio */ + /*pinctrl-13 = <&camera_pins_cam_ldo_vcama_0>; + pinctrl-14 = <&camera_pins_cam_ldo_vcama_1>;*/ + status = "okay"; + +}; +/* CAMERA GPIO end */ + +&pio { + alsps_intpin_cfg: alspspincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + + alsps_intpin_default: alspsdefaultcfg { + + }; + + gyro_intpin_cfg: gyropincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + + gyro_intpin_default: gyrodefaultcfg { + + }; +}; + +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; + +&gyroscope { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_lcd_bias_enp0: lcd_bias_enp0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcd_bias_enp1: lcd_bias_enp1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", "lcd_bias_enp0_gpio", "lcd_bias_enp1_gpio"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_lcd_bias_enp0>; + pinctrl-6 = <&mtkfb_pins_lcd_bias_enp1>; + status = "okay"; +};/* DISPSYS GPIO standardization end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + }; + + gpslna_pins_init: gpslna@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; +}; +/* CONSYS end */ + +/* SPM GPIO standardization */ +&pio { + spm_pins_default: default { + }; + + spm_vmd1_sel: vmd1_sel { + pins_cmd_dat { + pins = ; + }; + }; + +}; + +&sleep{ + pinctrl-names = "default", "vmd1_sel"; + pinctrl-0 = <&spm_pins_default>; + pinctrl-1 = <&spm_vmd1_sel>; + status = "okay"; +}; +/* SPM end */ + +/* AUDIO GPIO standardization */ +&audgpio { + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "audi2s1-mode0", "audi2s1-mode1", "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow", "rcvspk-pullhigh", + "rcvspk-pulllow","hpdepop-pullhigh","hpdepop-pulllow"; + pinctrl-0 = <&aud_pins_default>; + pinctrl-1 = <&aud_pins_pmicclk_mode0>; + pinctrl-2 = <&aud_pins_pmicclk_mode1>; + pinctrl-3 = <&aud_pins_i2s1_mode0>; + pinctrl-4 = <&aud_pins_i2s1_mode1>; + pinctrl-5 = <&aud_pins_extamp_high>; + pinctrl-6 = <&aud_pins_extamp_low>; + pinctrl-7 = <&aud_pins_extamp2_high>; + pinctrl-8 = <&aud_pins_extamp2_low>; + pinctrl-9 = <&aud_pins_rcvspk_high>; + pinctrl-10 = <&aud_pins_rcvspk_low>; + pinctrl-11 = <&aud_pins_hpdepop_high>; + pinctrl-12 = <&aud_pins_hpdepop_low>; + status = "okay"; +}; + +&pio { + aud_pins_default: audiodefault { + }; + + aud_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode0: audi2s1mode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode1: audi2s1mode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_extamp_high: audexamphigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_extamp_low: audexamplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_extamp2_high: audexam2phigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + aud_pins_extamp2_low: audexamp2low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_rcvspk_high: audrcvspkhigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_rcvspk_low: audrcvspklow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_hpdepop_high: audhpdepophigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_hpdepop_low: audhpdepoplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; +/* AUDIO end */ + +/* UART GPIO */ +&apuart0 { + pinctrl-names = "uart0_gpio_default", + "uart0_rx_set", + "uart0_rx_clear", + "uart0_tx_set", + "uart0_tx_clear"; + pinctrl-0 = <&uart0_gpio_def_cfg>; + pinctrl-1 = <&uart0_rx_set_cfg>; + pinctrl-2 = <&uart0_rx_clr_cfg>; + pinctrl-3 = <&uart0_tx_set_cfg>; + pinctrl-4 = <&uart0_tx_clr_cfg>; + status = "okay"; +}; + +&pio { + /* UART GPIO Settings - Start */ + /* UART0: rx set, rx clear, tx clear, tx clear*/ + uart0_gpio_def_cfg:uart0gpiodefault { + + }; + uart0_rx_set_cfg:uart0_rx_set@gpio105 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_rx_clr_cfg:uart0_rx_clear@gpio105 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + uart0_tx_set_cfg:uart0_tx_set@gpio106 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_tx_clr_cfg:uart0_tx_clear@gpio106 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +};/* UART GPIO end */ + +/* IRTX GPIO end */ +&irtx_pwm { + pinctrl-names = "irtx_gpio_led_default", + "irtx_gpio_led_set", + "irtx_gpio_en_default", + "irtx_gpio_en_set"; + + pinctrl-0 = <&irtx_gpio_led_default>; + pinctrl-1 = <&irtx_gpio_led_set>; + pinctrl-2 = <&irtx_gpio_en_default>; + pinctrl-3 = <&irtx_gpio_en_set>; + status = "okay"; +}; +&pio { + /* IRTX GPIO Settings -Start */ + /* default: GPIO0, output, high */ + irtx_gpio_led_default:irtx_gpio_led_def@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_led_set:irtx_gpio_led_set@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + irtx_gpio_en_default:irtx_gpio_en_def@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_en_set:irtx_gpio_en_set@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + +}; /* IRTX GPIO Settings -End */ + +/* NFC GPIO standardization */ +&pio { + nfc_default: default { + + }; + + nfc_ven_high: state_ven_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_ven_low: state_ven_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_rst_high: state_rst_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_rst_low: state_rst_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_eint_high: state_eint_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_eint_low: state_eint_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_irq_init: state_irq_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; +}; + +&nfc { + pinctrl-names = "default", "ven_high", "ven_low", "rst_high", "rst_low", "eint_high", "eint_low", "irq_init"; + pinctrl-0 = <&nfc_default>; + pinctrl-1 = <&nfc_ven_high>; + pinctrl-2 = <&nfc_ven_low>; + pinctrl-3 = <&nfc_rst_high>; + pinctrl-4 = <&nfc_rst_low>; + pinctrl-5 = <&nfc_eint_high>; + pinctrl-6 = <&nfc_eint_low>; + pinctrl-7 = <&nfc_irq_init>; + status = "okay"; +}; +/* NFC end */ + + + + +&pio { + iddig_default: iddig_default { + }; + + iddig_init: iddig_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio43_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + gpio43_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&iddig_init>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio43_mode1_drvvbus_low>; + pinctrl-2 = <&gpio43_mode1_drvvbus_high>; + status = "okay"; +}; + +&i2c1 { + + gyro@68 { + compatible = "mediatek,gyro"; + reg = <0x69>; + status = "okay"; + }; + + gsensor@68 { + compatible = "mediatek,gsensor"; + reg = <0x68>; + status = "okay"; + }; +}; + +&ext_buck_vmd1 { + pinctrl-names = "default", "vmd1_sel_low", "vmd1_sel_high"; + + pinctrl-0 = <&vmd1_default>; + pinctrl-1 = <&vmd1_sel_low>; + pinctrl-2 = <&vmd1_sel_high>; +}; + +&pio { + vmd1_default: vmd10default { + }; + + vmd1_sel_low: vmd1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + vmd1_sel_high: vmd1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; diff --git a/arch/arm/boot/dts/vz6750_35g_i_n.dts b/arch/arm/boot/dts/vz6750_35g_i_n.dts new file mode 100644 index 0000000000000000000000000000000000000000..8fd1dd2f8e61436de2f521b2f2817b3cd2d73961 --- /dev/null +++ b/arch/arm/boot/dts/vz6750_35g_i_n.dts @@ -0,0 +1,907 @@ + +/dts-v1/; + +#include "mt6755.dtsi" +#include "cust.dtsi" + +/ { + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x3e800000>; + }; + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4B434E loglevel=8"; + + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base_h = <0x0>; + atag,videolfb-fb_base_l = <0x7E800000>; + atag,videolfb-islcmfound = <1>; + /* because no lk, so lcm is not inited */ + atag,videolfb-islcm_inited = <0>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35695_fhd_dsi_cmd_truly_nt50358_drv"; + }; + led0:led@0 { + compatible = "mediatek,red"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led1:led@1 { + compatible = "mediatek,green"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led2:led@2 { + compatible = "mediatek,blue"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led3:led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led4:led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led5:led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led6:led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <5>; + }; +/* start sensor */ + cust_accel@0 { + compatible = "mediatek,mpu6515a"; + i2c_num = <1>; + /* i2c_addr = <0x4c 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <16>; + is_batch_supported = <1>; + }; + + cust_alsps@0 { + compatible = "mediatek,cm36686"; + i2c_num = <1>; + i2c_addr = <0x60 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als = <1>; + power_id = <0xffff>; + power_vol = <0>; +/* Total has 15 level*/ + als_level = <0 257 637 1027 2297 5588 6730 11301 20449 25768 31122 45552 57937 57937 57937>; +/* Total has 16 range*/ + als_value = <0 132 304 502 1004 2003 3006 5006 8004 10000 12000 16000 20000 20000 20000 20000>; + ps_threshold_high = <70>; + ps_threshold_low = <40>; + is_batch_supported_ps = <1>; + is_batch_supported_als = <1>; + }; + + cust_mag@0 { + compatible = "mediatek,akm8963"; + i2c_num = <1>; + /* i2c_addr = <0x0F 0 0 0>; */ + direction = <8>; + power_id = <0xffff>; + power_vol = <0>; + /* is_batch_supported = <0>; */ + }; + + cust_gyro@0 { + compatible = "mediatek,mpu6515g"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + + cust_baro@0 { + compatible = "mediatek,bmp280new"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <32>; + is_batch_supported = <0>; + }; +/* end sensor */ +}; +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <6>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 80 220 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; +}; + +/* TOUCH start */ +&touch { + tpd-resolution = <1080 1920>; + use-tpd-button = <0>; + tpd-key-num = <3>; + tpd-key-local= <139 172 158 0>; + tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>; + tpd-max-touch-num = <5>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <146>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <0 0 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: eint0default { + }; + ctp_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_sub_vcamd0: cam1@4 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_sub_vcamd1: cam1@5 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + /*camera_pins_cam_ldo_vcama_0: cam@vcama0 { + }; + camera_pins_cam_ldo_vcama_1: cam@vcama1 { + };*/ + camera_pins_default: camdefault { + }; + +}; + +&kd_camera_hw1 { + pinctrl-names = "default", + "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo_sub_vcamd_0", "cam_ldo_sub_vcamd_1"; + /*"cam2_rst0", "cam2_rst1", "cam2_pnd0", "cam2_pnd1", + "cam_ldo_vcama_0", "cam_ldo_vcama_1";*/ + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_sub_vcamd0>; + pinctrl-10 = <&camera_pins_sub_vcamd1>; + /* for main2 */ + /*pinctrl-9 = <&camera_pins_cam2_rst0>; + pinctrl-10 = <&camera_pins_cam2_rst1>; + pinctrl-11 = <&camera_pins_cam2_pnd0>; + pinctrl-12 = <&camera_pins_cam2_pnd1>;*/ + /* for ldo control by gpio */ + /*pinctrl-13 = <&camera_pins_cam_ldo_vcama_0>; + pinctrl-14 = <&camera_pins_cam_ldo_vcama_1>;*/ + status = "okay"; + +}; +/* CAMERA GPIO end */ + +&pio { + alsps_intpin_cfg: alspspincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + + alsps_intpin_default: alspsdefaultcfg { + + }; + + gyro_intpin_cfg: gyropincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + + gyro_intpin_default: gyrodefaultcfg { + + }; +}; + +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; + +&gyroscope { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_lcd_bias_enp0: lcd_bias_enp0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcd_bias_enp1: lcd_bias_enp1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", "lcd_bias_enp0_gpio", "lcd_bias_enp1_gpio"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_lcd_bias_enp0>; + pinctrl-6 = <&mtkfb_pins_lcd_bias_enp1>; + status = "okay"; +};/* DISPSYS GPIO standardization end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + }; + + gpslna_pins_init: gpslna@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; +}; +/* CONSYS end */ + +/* SPM GPIO standardization */ +&pio { + spm_pins_default: default { + }; + + spm_vmd1_sel: vmd1_sel { + pins_cmd_dat { + pins = ; + }; + }; + +}; + +&sleep{ + pinctrl-names = "default", "vmd1_sel"; + pinctrl-0 = <&spm_pins_default>; + pinctrl-1 = <&spm_vmd1_sel>; + status = "okay"; +}; +/* SPM end */ + +/* AUDIO GPIO standardization */ +&audgpio { + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "audi2s1-mode0", "audi2s1-mode1", "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow", "rcvspk-pullhigh", + "rcvspk-pulllow","hpdepop-pullhigh","hpdepop-pulllow"; + pinctrl-0 = <&aud_pins_default>; + pinctrl-1 = <&aud_pins_pmicclk_mode0>; + pinctrl-2 = <&aud_pins_pmicclk_mode1>; + pinctrl-3 = <&aud_pins_i2s1_mode0>; + pinctrl-4 = <&aud_pins_i2s1_mode1>; + pinctrl-5 = <&aud_pins_extamp_high>; + pinctrl-6 = <&aud_pins_extamp_low>; + pinctrl-7 = <&aud_pins_extamp2_high>; + pinctrl-8 = <&aud_pins_extamp2_low>; + pinctrl-9 = <&aud_pins_rcvspk_high>; + pinctrl-10 = <&aud_pins_rcvspk_low>; + pinctrl-11 = <&aud_pins_hpdepop_high>; + pinctrl-12 = <&aud_pins_hpdepop_low>; + status = "okay"; +}; + +&pio { + aud_pins_default: audiodefault { + }; + + aud_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode0: audi2s1mode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode1: audi2s1mode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_extamp_high: audexamphigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_extamp_low: audexamplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_extamp2_high: audexam2phigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + aud_pins_extamp2_low: audexamp2low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_rcvspk_high: audrcvspkhigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_rcvspk_low: audrcvspklow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_hpdepop_high: audhpdepophigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_hpdepop_low: audhpdepoplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; +/* AUDIO end */ + +/* UART GPIO */ +&apuart0 { + pinctrl-names = "uart0_gpio_default", + "uart0_rx_set", + "uart0_rx_clear", + "uart0_tx_set", + "uart0_tx_clear"; + pinctrl-0 = <&uart0_gpio_def_cfg>; + pinctrl-1 = <&uart0_rx_set_cfg>; + pinctrl-2 = <&uart0_rx_clr_cfg>; + pinctrl-3 = <&uart0_tx_set_cfg>; + pinctrl-4 = <&uart0_tx_clr_cfg>; + status = "okay"; +}; + +&pio { + /* UART GPIO Settings - Start */ + /* UART0: rx set, rx clear, tx clear, tx clear*/ + uart0_gpio_def_cfg:uart0gpiodefault { + + }; + uart0_rx_set_cfg:uart0_rx_set@gpio105 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_rx_clr_cfg:uart0_rx_clear@gpio105 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + uart0_tx_set_cfg:uart0_tx_set@gpio106 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_tx_clr_cfg:uart0_tx_clear@gpio106 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +};/* UART GPIO end */ + +/* IRTX GPIO end */ +&irtx_pwm { + pinctrl-names = "irtx_gpio_led_default", + "irtx_gpio_led_set", + "irtx_gpio_en_default", + "irtx_gpio_en_set"; + + pinctrl-0 = <&irtx_gpio_led_default>; + pinctrl-1 = <&irtx_gpio_led_set>; + pinctrl-2 = <&irtx_gpio_en_default>; + pinctrl-3 = <&irtx_gpio_en_set>; + status = "okay"; +}; +&pio { + /* IRTX GPIO Settings -Start */ + /* default: GPIO0, output, high */ + irtx_gpio_led_default:irtx_gpio_led_def@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_led_set:irtx_gpio_led_set@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + irtx_gpio_en_default:irtx_gpio_en_def@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_en_set:irtx_gpio_en_set@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + +}; /* IRTX GPIO Settings -End */ + +/* NFC GPIO standardization */ +&pio { + nfc_default: default { + + }; + + nfc_ven_high: state_ven_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_ven_low: state_ven_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_rst_high: state_rst_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_rst_low: state_rst_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_eint_high: state_eint_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_eint_low: state_eint_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_irq_init: state_irq_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; +}; + +&nfc { + pinctrl-names = "default", "ven_high", "ven_low", "rst_high", "rst_low", "eint_high", "eint_low", "irq_init"; + pinctrl-0 = <&nfc_default>; + pinctrl-1 = <&nfc_ven_high>; + pinctrl-2 = <&nfc_ven_low>; + pinctrl-3 = <&nfc_rst_high>; + pinctrl-4 = <&nfc_rst_low>; + pinctrl-5 = <&nfc_eint_high>; + pinctrl-6 = <&nfc_eint_low>; + pinctrl-7 = <&nfc_irq_init>; + status = "okay"; +}; +/* NFC end */ + + + + +&pio { + iddig_default: iddig_default { + }; + + iddig_init: iddig_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio43_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + gpio43_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&iddig_init>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio43_mode1_drvvbus_low>; + pinctrl-2 = <&gpio43_mode1_drvvbus_high>; + status = "okay"; +}; + +&i2c1 { + + gyro@68 { + compatible = "mediatek,gyro"; + reg = <0x69>; + status = "okay"; + }; + + gsensor@68 { + compatible = "mediatek,gsensor"; + reg = <0x68>; + status = "okay"; + }; +}; + +&ext_buck_vmd1 { + pinctrl-names = "default", "vmd1_sel_low", "vmd1_sel_high"; + + pinctrl-0 = <&vmd1_default>; + pinctrl-1 = <&vmd1_sel_low>; + pinctrl-2 = <&vmd1_sel_high>; +}; + +&pio { + vmd1_default: vmd10default { + }; + + vmd1_sel_low: vmd1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + vmd1_sel_high: vmd1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; diff --git a/arch/arm/boot/dts/vz6750_36_i_n.dts b/arch/arm/boot/dts/vz6750_36_i_n.dts new file mode 100644 index 0000000000000000000000000000000000000000..8fd1dd2f8e61436de2f521b2f2817b3cd2d73961 --- /dev/null +++ b/arch/arm/boot/dts/vz6750_36_i_n.dts @@ -0,0 +1,907 @@ + +/dts-v1/; + +#include "mt6755.dtsi" +#include "cust.dtsi" + +/ { + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x3e800000>; + }; + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4B434E loglevel=8"; + + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base_h = <0x0>; + atag,videolfb-fb_base_l = <0x7E800000>; + atag,videolfb-islcmfound = <1>; + /* because no lk, so lcm is not inited */ + atag,videolfb-islcm_inited = <0>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35695_fhd_dsi_cmd_truly_nt50358_drv"; + }; + led0:led@0 { + compatible = "mediatek,red"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led1:led@1 { + compatible = "mediatek,green"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led2:led@2 { + compatible = "mediatek,blue"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led3:led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led4:led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led5:led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led6:led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <5>; + }; +/* start sensor */ + cust_accel@0 { + compatible = "mediatek,mpu6515a"; + i2c_num = <1>; + /* i2c_addr = <0x4c 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <16>; + is_batch_supported = <1>; + }; + + cust_alsps@0 { + compatible = "mediatek,cm36686"; + i2c_num = <1>; + i2c_addr = <0x60 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als = <1>; + power_id = <0xffff>; + power_vol = <0>; +/* Total has 15 level*/ + als_level = <0 257 637 1027 2297 5588 6730 11301 20449 25768 31122 45552 57937 57937 57937>; +/* Total has 16 range*/ + als_value = <0 132 304 502 1004 2003 3006 5006 8004 10000 12000 16000 20000 20000 20000 20000>; + ps_threshold_high = <70>; + ps_threshold_low = <40>; + is_batch_supported_ps = <1>; + is_batch_supported_als = <1>; + }; + + cust_mag@0 { + compatible = "mediatek,akm8963"; + i2c_num = <1>; + /* i2c_addr = <0x0F 0 0 0>; */ + direction = <8>; + power_id = <0xffff>; + power_vol = <0>; + /* is_batch_supported = <0>; */ + }; + + cust_gyro@0 { + compatible = "mediatek,mpu6515g"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + + cust_baro@0 { + compatible = "mediatek,bmp280new"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <32>; + is_batch_supported = <0>; + }; +/* end sensor */ +}; +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <6>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 80 220 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; +}; + +/* TOUCH start */ +&touch { + tpd-resolution = <1080 1920>; + use-tpd-button = <0>; + tpd-key-num = <3>; + tpd-key-local= <139 172 158 0>; + tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>; + tpd-max-touch-num = <5>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <146>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <0 0 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: eint0default { + }; + ctp_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_sub_vcamd0: cam1@4 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_sub_vcamd1: cam1@5 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + /*camera_pins_cam_ldo_vcama_0: cam@vcama0 { + }; + camera_pins_cam_ldo_vcama_1: cam@vcama1 { + };*/ + camera_pins_default: camdefault { + }; + +}; + +&kd_camera_hw1 { + pinctrl-names = "default", + "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo_sub_vcamd_0", "cam_ldo_sub_vcamd_1"; + /*"cam2_rst0", "cam2_rst1", "cam2_pnd0", "cam2_pnd1", + "cam_ldo_vcama_0", "cam_ldo_vcama_1";*/ + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_sub_vcamd0>; + pinctrl-10 = <&camera_pins_sub_vcamd1>; + /* for main2 */ + /*pinctrl-9 = <&camera_pins_cam2_rst0>; + pinctrl-10 = <&camera_pins_cam2_rst1>; + pinctrl-11 = <&camera_pins_cam2_pnd0>; + pinctrl-12 = <&camera_pins_cam2_pnd1>;*/ + /* for ldo control by gpio */ + /*pinctrl-13 = <&camera_pins_cam_ldo_vcama_0>; + pinctrl-14 = <&camera_pins_cam_ldo_vcama_1>;*/ + status = "okay"; + +}; +/* CAMERA GPIO end */ + +&pio { + alsps_intpin_cfg: alspspincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + + alsps_intpin_default: alspsdefaultcfg { + + }; + + gyro_intpin_cfg: gyropincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + + gyro_intpin_default: gyrodefaultcfg { + + }; +}; + +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; + +&gyroscope { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_lcd_bias_enp0: lcd_bias_enp0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcd_bias_enp1: lcd_bias_enp1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", "lcd_bias_enp0_gpio", "lcd_bias_enp1_gpio"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_lcd_bias_enp0>; + pinctrl-6 = <&mtkfb_pins_lcd_bias_enp1>; + status = "okay"; +};/* DISPSYS GPIO standardization end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + }; + + gpslna_pins_init: gpslna@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; +}; +/* CONSYS end */ + +/* SPM GPIO standardization */ +&pio { + spm_pins_default: default { + }; + + spm_vmd1_sel: vmd1_sel { + pins_cmd_dat { + pins = ; + }; + }; + +}; + +&sleep{ + pinctrl-names = "default", "vmd1_sel"; + pinctrl-0 = <&spm_pins_default>; + pinctrl-1 = <&spm_vmd1_sel>; + status = "okay"; +}; +/* SPM end */ + +/* AUDIO GPIO standardization */ +&audgpio { + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "audi2s1-mode0", "audi2s1-mode1", "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow", "rcvspk-pullhigh", + "rcvspk-pulllow","hpdepop-pullhigh","hpdepop-pulllow"; + pinctrl-0 = <&aud_pins_default>; + pinctrl-1 = <&aud_pins_pmicclk_mode0>; + pinctrl-2 = <&aud_pins_pmicclk_mode1>; + pinctrl-3 = <&aud_pins_i2s1_mode0>; + pinctrl-4 = <&aud_pins_i2s1_mode1>; + pinctrl-5 = <&aud_pins_extamp_high>; + pinctrl-6 = <&aud_pins_extamp_low>; + pinctrl-7 = <&aud_pins_extamp2_high>; + pinctrl-8 = <&aud_pins_extamp2_low>; + pinctrl-9 = <&aud_pins_rcvspk_high>; + pinctrl-10 = <&aud_pins_rcvspk_low>; + pinctrl-11 = <&aud_pins_hpdepop_high>; + pinctrl-12 = <&aud_pins_hpdepop_low>; + status = "okay"; +}; + +&pio { + aud_pins_default: audiodefault { + }; + + aud_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode0: audi2s1mode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode1: audi2s1mode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_extamp_high: audexamphigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_extamp_low: audexamplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_extamp2_high: audexam2phigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + aud_pins_extamp2_low: audexamp2low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_rcvspk_high: audrcvspkhigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_rcvspk_low: audrcvspklow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_hpdepop_high: audhpdepophigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_hpdepop_low: audhpdepoplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; +/* AUDIO end */ + +/* UART GPIO */ +&apuart0 { + pinctrl-names = "uart0_gpio_default", + "uart0_rx_set", + "uart0_rx_clear", + "uart0_tx_set", + "uart0_tx_clear"; + pinctrl-0 = <&uart0_gpio_def_cfg>; + pinctrl-1 = <&uart0_rx_set_cfg>; + pinctrl-2 = <&uart0_rx_clr_cfg>; + pinctrl-3 = <&uart0_tx_set_cfg>; + pinctrl-4 = <&uart0_tx_clr_cfg>; + status = "okay"; +}; + +&pio { + /* UART GPIO Settings - Start */ + /* UART0: rx set, rx clear, tx clear, tx clear*/ + uart0_gpio_def_cfg:uart0gpiodefault { + + }; + uart0_rx_set_cfg:uart0_rx_set@gpio105 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_rx_clr_cfg:uart0_rx_clear@gpio105 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + uart0_tx_set_cfg:uart0_tx_set@gpio106 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_tx_clr_cfg:uart0_tx_clear@gpio106 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +};/* UART GPIO end */ + +/* IRTX GPIO end */ +&irtx_pwm { + pinctrl-names = "irtx_gpio_led_default", + "irtx_gpio_led_set", + "irtx_gpio_en_default", + "irtx_gpio_en_set"; + + pinctrl-0 = <&irtx_gpio_led_default>; + pinctrl-1 = <&irtx_gpio_led_set>; + pinctrl-2 = <&irtx_gpio_en_default>; + pinctrl-3 = <&irtx_gpio_en_set>; + status = "okay"; +}; +&pio { + /* IRTX GPIO Settings -Start */ + /* default: GPIO0, output, high */ + irtx_gpio_led_default:irtx_gpio_led_def@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_led_set:irtx_gpio_led_set@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + irtx_gpio_en_default:irtx_gpio_en_def@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_en_set:irtx_gpio_en_set@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + +}; /* IRTX GPIO Settings -End */ + +/* NFC GPIO standardization */ +&pio { + nfc_default: default { + + }; + + nfc_ven_high: state_ven_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_ven_low: state_ven_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_rst_high: state_rst_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_rst_low: state_rst_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_eint_high: state_eint_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_eint_low: state_eint_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_irq_init: state_irq_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; +}; + +&nfc { + pinctrl-names = "default", "ven_high", "ven_low", "rst_high", "rst_low", "eint_high", "eint_low", "irq_init"; + pinctrl-0 = <&nfc_default>; + pinctrl-1 = <&nfc_ven_high>; + pinctrl-2 = <&nfc_ven_low>; + pinctrl-3 = <&nfc_rst_high>; + pinctrl-4 = <&nfc_rst_low>; + pinctrl-5 = <&nfc_eint_high>; + pinctrl-6 = <&nfc_eint_low>; + pinctrl-7 = <&nfc_irq_init>; + status = "okay"; +}; +/* NFC end */ + + + + +&pio { + iddig_default: iddig_default { + }; + + iddig_init: iddig_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio43_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + gpio43_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&iddig_init>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio43_mode1_drvvbus_low>; + pinctrl-2 = <&gpio43_mode1_drvvbus_high>; + status = "okay"; +}; + +&i2c1 { + + gyro@68 { + compatible = "mediatek,gyro"; + reg = <0x69>; + status = "okay"; + }; + + gsensor@68 { + compatible = "mediatek,gsensor"; + reg = <0x68>; + status = "okay"; + }; +}; + +&ext_buck_vmd1 { + pinctrl-names = "default", "vmd1_sel_low", "vmd1_sel_high"; + + pinctrl-0 = <&vmd1_default>; + pinctrl-1 = <&vmd1_sel_low>; + pinctrl-2 = <&vmd1_sel_high>; +}; + +&pio { + vmd1_default: vmd10default { + }; + + vmd1_sel_low: vmd1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + vmd1_sel_high: vmd1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; diff --git a/arch/arm/boot/dts/vz6750_36g_i_n.dts b/arch/arm/boot/dts/vz6750_36g_i_n.dts new file mode 100644 index 0000000000000000000000000000000000000000..8fd1dd2f8e61436de2f521b2f2817b3cd2d73961 --- /dev/null +++ b/arch/arm/boot/dts/vz6750_36g_i_n.dts @@ -0,0 +1,907 @@ + +/dts-v1/; + +#include "mt6755.dtsi" +#include "cust.dtsi" + +/ { + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x3e800000>; + }; + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4B434E loglevel=8"; + + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base_h = <0x0>; + atag,videolfb-fb_base_l = <0x7E800000>; + atag,videolfb-islcmfound = <1>; + /* because no lk, so lcm is not inited */ + atag,videolfb-islcm_inited = <0>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35695_fhd_dsi_cmd_truly_nt50358_drv"; + }; + led0:led@0 { + compatible = "mediatek,red"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led1:led@1 { + compatible = "mediatek,green"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led2:led@2 { + compatible = "mediatek,blue"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led3:led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led4:led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led5:led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led6:led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <5>; + }; +/* start sensor */ + cust_accel@0 { + compatible = "mediatek,mpu6515a"; + i2c_num = <1>; + /* i2c_addr = <0x4c 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <16>; + is_batch_supported = <1>; + }; + + cust_alsps@0 { + compatible = "mediatek,cm36686"; + i2c_num = <1>; + i2c_addr = <0x60 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als = <1>; + power_id = <0xffff>; + power_vol = <0>; +/* Total has 15 level*/ + als_level = <0 257 637 1027 2297 5588 6730 11301 20449 25768 31122 45552 57937 57937 57937>; +/* Total has 16 range*/ + als_value = <0 132 304 502 1004 2003 3006 5006 8004 10000 12000 16000 20000 20000 20000 20000>; + ps_threshold_high = <70>; + ps_threshold_low = <40>; + is_batch_supported_ps = <1>; + is_batch_supported_als = <1>; + }; + + cust_mag@0 { + compatible = "mediatek,akm8963"; + i2c_num = <1>; + /* i2c_addr = <0x0F 0 0 0>; */ + direction = <8>; + power_id = <0xffff>; + power_vol = <0>; + /* is_batch_supported = <0>; */ + }; + + cust_gyro@0 { + compatible = "mediatek,mpu6515g"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + + cust_baro@0 { + compatible = "mediatek,bmp280new"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <32>; + is_batch_supported = <0>; + }; +/* end sensor */ +}; +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <6>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 80 220 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; +}; + +/* TOUCH start */ +&touch { + tpd-resolution = <1080 1920>; + use-tpd-button = <0>; + tpd-key-num = <3>; + tpd-key-local= <139 172 158 0>; + tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>; + tpd-max-touch-num = <5>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <146>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <0 0 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: eint0default { + }; + ctp_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_sub_vcamd0: cam1@4 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_sub_vcamd1: cam1@5 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + /*camera_pins_cam_ldo_vcama_0: cam@vcama0 { + }; + camera_pins_cam_ldo_vcama_1: cam@vcama1 { + };*/ + camera_pins_default: camdefault { + }; + +}; + +&kd_camera_hw1 { + pinctrl-names = "default", + "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo_sub_vcamd_0", "cam_ldo_sub_vcamd_1"; + /*"cam2_rst0", "cam2_rst1", "cam2_pnd0", "cam2_pnd1", + "cam_ldo_vcama_0", "cam_ldo_vcama_1";*/ + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_sub_vcamd0>; + pinctrl-10 = <&camera_pins_sub_vcamd1>; + /* for main2 */ + /*pinctrl-9 = <&camera_pins_cam2_rst0>; + pinctrl-10 = <&camera_pins_cam2_rst1>; + pinctrl-11 = <&camera_pins_cam2_pnd0>; + pinctrl-12 = <&camera_pins_cam2_pnd1>;*/ + /* for ldo control by gpio */ + /*pinctrl-13 = <&camera_pins_cam_ldo_vcama_0>; + pinctrl-14 = <&camera_pins_cam_ldo_vcama_1>;*/ + status = "okay"; + +}; +/* CAMERA GPIO end */ + +&pio { + alsps_intpin_cfg: alspspincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + + alsps_intpin_default: alspsdefaultcfg { + + }; + + gyro_intpin_cfg: gyropincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + + gyro_intpin_default: gyrodefaultcfg { + + }; +}; + +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; + +&gyroscope { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_lcd_bias_enp0: lcd_bias_enp0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcd_bias_enp1: lcd_bias_enp1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", "lcd_bias_enp0_gpio", "lcd_bias_enp1_gpio"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_lcd_bias_enp0>; + pinctrl-6 = <&mtkfb_pins_lcd_bias_enp1>; + status = "okay"; +};/* DISPSYS GPIO standardization end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + }; + + gpslna_pins_init: gpslna@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; +}; +/* CONSYS end */ + +/* SPM GPIO standardization */ +&pio { + spm_pins_default: default { + }; + + spm_vmd1_sel: vmd1_sel { + pins_cmd_dat { + pins = ; + }; + }; + +}; + +&sleep{ + pinctrl-names = "default", "vmd1_sel"; + pinctrl-0 = <&spm_pins_default>; + pinctrl-1 = <&spm_vmd1_sel>; + status = "okay"; +}; +/* SPM end */ + +/* AUDIO GPIO standardization */ +&audgpio { + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "audi2s1-mode0", "audi2s1-mode1", "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow", "rcvspk-pullhigh", + "rcvspk-pulllow","hpdepop-pullhigh","hpdepop-pulllow"; + pinctrl-0 = <&aud_pins_default>; + pinctrl-1 = <&aud_pins_pmicclk_mode0>; + pinctrl-2 = <&aud_pins_pmicclk_mode1>; + pinctrl-3 = <&aud_pins_i2s1_mode0>; + pinctrl-4 = <&aud_pins_i2s1_mode1>; + pinctrl-5 = <&aud_pins_extamp_high>; + pinctrl-6 = <&aud_pins_extamp_low>; + pinctrl-7 = <&aud_pins_extamp2_high>; + pinctrl-8 = <&aud_pins_extamp2_low>; + pinctrl-9 = <&aud_pins_rcvspk_high>; + pinctrl-10 = <&aud_pins_rcvspk_low>; + pinctrl-11 = <&aud_pins_hpdepop_high>; + pinctrl-12 = <&aud_pins_hpdepop_low>; + status = "okay"; +}; + +&pio { + aud_pins_default: audiodefault { + }; + + aud_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode0: audi2s1mode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode1: audi2s1mode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_extamp_high: audexamphigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_extamp_low: audexamplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_extamp2_high: audexam2phigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + aud_pins_extamp2_low: audexamp2low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_rcvspk_high: audrcvspkhigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_rcvspk_low: audrcvspklow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_hpdepop_high: audhpdepophigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_hpdepop_low: audhpdepoplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; +/* AUDIO end */ + +/* UART GPIO */ +&apuart0 { + pinctrl-names = "uart0_gpio_default", + "uart0_rx_set", + "uart0_rx_clear", + "uart0_tx_set", + "uart0_tx_clear"; + pinctrl-0 = <&uart0_gpio_def_cfg>; + pinctrl-1 = <&uart0_rx_set_cfg>; + pinctrl-2 = <&uart0_rx_clr_cfg>; + pinctrl-3 = <&uart0_tx_set_cfg>; + pinctrl-4 = <&uart0_tx_clr_cfg>; + status = "okay"; +}; + +&pio { + /* UART GPIO Settings - Start */ + /* UART0: rx set, rx clear, tx clear, tx clear*/ + uart0_gpio_def_cfg:uart0gpiodefault { + + }; + uart0_rx_set_cfg:uart0_rx_set@gpio105 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_rx_clr_cfg:uart0_rx_clear@gpio105 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + uart0_tx_set_cfg:uart0_tx_set@gpio106 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_tx_clr_cfg:uart0_tx_clear@gpio106 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +};/* UART GPIO end */ + +/* IRTX GPIO end */ +&irtx_pwm { + pinctrl-names = "irtx_gpio_led_default", + "irtx_gpio_led_set", + "irtx_gpio_en_default", + "irtx_gpio_en_set"; + + pinctrl-0 = <&irtx_gpio_led_default>; + pinctrl-1 = <&irtx_gpio_led_set>; + pinctrl-2 = <&irtx_gpio_en_default>; + pinctrl-3 = <&irtx_gpio_en_set>; + status = "okay"; +}; +&pio { + /* IRTX GPIO Settings -Start */ + /* default: GPIO0, output, high */ + irtx_gpio_led_default:irtx_gpio_led_def@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_led_set:irtx_gpio_led_set@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + irtx_gpio_en_default:irtx_gpio_en_def@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_en_set:irtx_gpio_en_set@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + +}; /* IRTX GPIO Settings -End */ + +/* NFC GPIO standardization */ +&pio { + nfc_default: default { + + }; + + nfc_ven_high: state_ven_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_ven_low: state_ven_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_rst_high: state_rst_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_rst_low: state_rst_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_eint_high: state_eint_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_eint_low: state_eint_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_irq_init: state_irq_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; +}; + +&nfc { + pinctrl-names = "default", "ven_high", "ven_low", "rst_high", "rst_low", "eint_high", "eint_low", "irq_init"; + pinctrl-0 = <&nfc_default>; + pinctrl-1 = <&nfc_ven_high>; + pinctrl-2 = <&nfc_ven_low>; + pinctrl-3 = <&nfc_rst_high>; + pinctrl-4 = <&nfc_rst_low>; + pinctrl-5 = <&nfc_eint_high>; + pinctrl-6 = <&nfc_eint_low>; + pinctrl-7 = <&nfc_irq_init>; + status = "okay"; +}; +/* NFC end */ + + + + +&pio { + iddig_default: iddig_default { + }; + + iddig_init: iddig_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio43_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + gpio43_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&iddig_init>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio43_mode1_drvvbus_low>; + pinctrl-2 = <&gpio43_mode1_drvvbus_high>; + status = "okay"; +}; + +&i2c1 { + + gyro@68 { + compatible = "mediatek,gyro"; + reg = <0x69>; + status = "okay"; + }; + + gsensor@68 { + compatible = "mediatek,gsensor"; + reg = <0x68>; + status = "okay"; + }; +}; + +&ext_buck_vmd1 { + pinctrl-names = "default", "vmd1_sel_low", "vmd1_sel_high"; + + pinctrl-0 = <&vmd1_default>; + pinctrl-1 = <&vmd1_sel_low>; + pinctrl-2 = <&vmd1_sel_high>; +}; + +&pio { + vmd1_default: vmd10default { + }; + + vmd1_sel_low: vmd1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + vmd1_sel_high: vmd1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; diff --git a/arch/arm/configs/KIICAA_POWER_defconfig b/arch/arm/configs/KIICAA_POWER_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..676742f5f2e06e9abe2bd5498161f55ae2ad137e --- /dev/null +++ b/arch/arm/configs/KIICAA_POWER_defconfig @@ -0,0 +1,480 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x80000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_LOCALVERSION="-SnowCatPDA-x5-1.N1.0.2" +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6580=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_ZNDSWAP=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_LZ4K_COMPRESS=y +CONFIG_ZRAM_DEBUG=y +CONFIG_ZSM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6580" + +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_CLKMGR=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_MTK_CMDQ=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali utgard" +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +#CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +#CONFIG_MTK_ITG1010_NEW=y +CONFIG_MTK_HWMON=y +#CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +#CONFIG_MTK_AKM09911_NEW=y +CONFIG_MTK_BTCVSD=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=3 +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6580=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +# CONFIG_MTK_CONN_LTE_IDC_SUPPORT is not set +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6580_FM" +CONFIG_MTK_CCCI_EXT=y +CONFIG_MTK_CCCI_DRIVER=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT=y +CONFIG_MTK_DEVAPC_DRIVER=y +# CONFIG_MTK_EMI_MBW is not set +CONFIG_MTK_IRQ=y +CONFIG_MTK_LEDS=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_CHIP=y +CONFIG_MTK_SEC_MODEM_NVRAM_ANTI_CLONE=y +CONFIG_MTPROF=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_DRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0x3000 +CONFIG_MTK_RAM_CONSOLE_ADDR=0xF912D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x83F00000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MTK_SYSENV=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +#CONFIG_TOUCHSCREEN_MTK_GT1151=y +#CONFIG_GT1151_FIRMWARE="firmware1" +#CONFIG_GT1151_CONFIG="config4" +#CONFIG_GTP_DRIVER_SEND_CFG=y +#CONFIG_GTP_CUSTOM_CFG=y +#CONFIG_GTP_HOTKNOT=y +#CONFIG_GTP_AUTO_UPDATE=y +#CONFIG_GTP_HEADER_FW_UPDATE=y +#CONFIG_GTP_CREATE_WR_NODE=y +#CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_RESET=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_PUMP_EXPRESS_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6580=y +#CONFIG_MTK_SPEAKER=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_MTK_GMO_RAM_OPTIMIZE=y +CONFIG_ION=y +CONFIG_MTK_ION=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x10000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x83F10000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=1 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y + +################################ +# CONFIG KIICAA_POWER 6580 +################################ + +CONFIG_LCM_HEIGHT="1280" +CONFIG_LCM_WIDTH="720" + +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="KIICAA_POWER" +CONFIG_ARCH_MTK_PROJECT="KIICAA_POWER" + +#CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k5e2ya_mipi_raw gc2355_mipi_raw" +#CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k5e2ya_mipi_raw s5k4e2gx_mipi_raw hi551_mipi_raw ov9760_mipi_raw gc2355_mipi_raw hi841_mipi_raw" + +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="ili9881_hds_hd720_5p0_h1_t592_otd" + +#CONFIG_MTK_KXTJ2_1009_NEW=y +#CONFIG_MTK_MXC400X_NEW=y +#CONFIG_MTK_EPL2182_NEW=y +#CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +#CONFIG_TOUCHSCREEN_MTK_FT5X0X=y +#CONFIG_HCT_TP_GESTRUE=y + diff --git a/arch/arm/configs/vz6750_35_i_n_debug_defconfig b/arch/arm/configs/vz6750_35_i_n_debug_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..9cce4cd18ea2430276fff7dfc455ae8c53ea563c --- /dev/null +++ b/arch/arm/configs/vz6750_35_i_n_debug_defconfig @@ -0,0 +1,527 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x40000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="vz6750_35_i_n" +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTK_NET_LOGGING=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_35_i_n" +CONFIG_MT_ENG_BUILD=y +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=10 +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_MEMCFG=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_AEE_MRDUMP=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_WQ_DEBUG=y +CONFIG_MT_SCHED_MONITOR=y +CONFIG_MT_RT_THROTTLE_MON=y +CONFIG_PREEMPT_MONITOR=y +CONFIG_MTK_PERFMGR_TOUCH_BOOST=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MT_SCHED_TRACE=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_DEBUG=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_SLUB_DEBUG_ON=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=3200 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_LOCKDEP=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_TRACE=y +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_MTK_FTRACE_DEFAULT_ENABLE=y +CONFIG_DMA_API_DEBUG=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/vz6750_35_i_n_defconfig b/arch/arm/configs/vz6750_35_i_n_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..5087c8afc1d5e98daf5e76fb4ce69d45d7820225 --- /dev/null +++ b/arch/arm/configs/vz6750_35_i_n_defconfig @@ -0,0 +1,503 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x40000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="vz6750_35_i_n" +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_35_i_n" +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=10 +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_PERFMGR_TOUCH_BOOST=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=1 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/vz6750_35g_i_n_debug_defconfig b/arch/arm/configs/vz6750_35g_i_n_debug_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..3138812cecdb64416bb6ccd938c64549dfe4dc83 --- /dev/null +++ b/arch/arm/configs/vz6750_35g_i_n_debug_defconfig @@ -0,0 +1,529 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x40000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="vz6750_35g_i_n" +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTK_NET_LOGGING=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_LZ4K_COMPRESS=y +CONFIG_ZRAM_DEBUG=y +CONFIG_ZSM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_35g_i_n" +CONFIG_MT_ENG_BUILD=y +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358_720p" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_LCM_HEIGHT="1280" +CONFIG_LCM_WIDTH="720" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=10 +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_MEMCFG=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_AEE_MRDUMP=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_WQ_DEBUG=y +CONFIG_MT_SCHED_MONITOR=y +CONFIG_MT_RT_THROTTLE_MON=y +CONFIG_PREEMPT_MONITOR=y +CONFIG_MTK_PERFMGR_TOUCH_BOOST=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MT_SCHED_TRACE=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_MTK_GMO_RAM_OPTIMIZE=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_DEBUG=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=3200 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_LOCKDEP=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_TRACE=y +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_MTK_FTRACE_DEFAULT_ENABLE=y +CONFIG_DMA_API_DEBUG=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/vz6750_35g_i_n_defconfig b/arch/arm/configs/vz6750_35g_i_n_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..8f836e6bc1d765d876cd0a547d907c8394ef5289 --- /dev/null +++ b/arch/arm/configs/vz6750_35g_i_n_defconfig @@ -0,0 +1,506 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x40000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="vz6750_35g_i_n" +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_LZ4K_COMPRESS=y +CONFIG_ZRAM_DEBUG=y +CONFIG_ZSM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_35g_i_n" +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358_720p" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_LCM_HEIGHT="1280" +CONFIG_LCM_WIDTH="720" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=10 +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_PERFMGR_TOUCH_BOOST=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_MTK_GMO_RAM_OPTIMIZE=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=1 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/vz6750_36_i_n_debug_defconfig b/arch/arm/configs/vz6750_36_i_n_debug_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..5c01d7c246f74e2498196ca01dc99c9ef431a5bb --- /dev/null +++ b/arch/arm/configs/vz6750_36_i_n_debug_defconfig @@ -0,0 +1,531 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x40000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="vz6750_36_i_n" +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTK_NET_LOGGING=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_36_i_n" +CONFIG_MT_ENG_BUILD=y +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=12 +CONFIG_MTK_MD3_SUPPORT=2 +CONFIG_MTK_C2K_LTE_MODE=2 +CONFIG_MTK_IRAT_SUPPORT=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_IRTX_PWM_SUPPORT=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_MEMCFG=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_AEE_MRDUMP=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_WQ_DEBUG=y +CONFIG_MT_SCHED_MONITOR=y +CONFIG_MT_RT_THROTTLE_MON=y +CONFIG_PREEMPT_MONITOR=y +CONFIG_MTK_PERFMGR_TOUCH_BOOST=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MT_SCHED_TRACE=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_DEBUG=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_SLUB_DEBUG_ON=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=3200 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_LOCKDEP=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_TRACE=y +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_MTK_FTRACE_DEFAULT_ENABLE=y +CONFIG_DMA_API_DEBUG=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/vz6750_36_i_n_defconfig b/arch/arm/configs/vz6750_36_i_n_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..660ca3c153617e4aaae4efb7d8f7aadd40529fbf --- /dev/null +++ b/arch/arm/configs/vz6750_36_i_n_defconfig @@ -0,0 +1,507 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x40000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="vz6750_36_i_n" +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_36_i_n" +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=12 +CONFIG_MTK_MD3_SUPPORT=2 +CONFIG_MTK_C2K_LTE_MODE=2 +CONFIG_MTK_IRAT_SUPPORT=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_IRTX_PWM_SUPPORT=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_PERFMGR_TOUCH_BOOST=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=1 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/vz6750_36g_i_n_debug_defconfig b/arch/arm/configs/vz6750_36g_i_n_debug_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..5a7147189c584c42f7329d66439030b9bd7ccc82 --- /dev/null +++ b/arch/arm/configs/vz6750_36g_i_n_debug_defconfig @@ -0,0 +1,531 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x40000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="vz6750_36g_i_n" +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTK_NET_LOGGING=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_LZ4K_COMPRESS=y +CONFIG_ZRAM_DEBUG=y +CONFIG_ZSM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_36g_i_n" +CONFIG_MT_ENG_BUILD=y +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw imx135_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358_720p" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_LCM_HEIGHT="1280" +CONFIG_LCM_WIDTH="720" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=12 +CONFIG_MTK_MD3_SUPPORT=2 +CONFIG_MTK_C2K_LTE_MODE=2 +CONFIG_MTK_IRAT_SUPPORT=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_MEMCFG=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_AEE_MRDUMP=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_WQ_DEBUG=y +CONFIG_MT_SCHED_MONITOR=y +CONFIG_MT_RT_THROTTLE_MON=y +CONFIG_PREEMPT_MONITOR=y +CONFIG_MTK_PERFMGR_TOUCH_BOOST=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MT_SCHED_TRACE=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_MTK_GMO_RAM_OPTIMIZE=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_DEBUG=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=3200 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_LOCKDEP=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_TRACE=y +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_MTK_FTRACE_DEFAULT_ENABLE=y +CONFIG_DMA_API_DEBUG=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/vz6750_36g_i_n_defconfig b/arch/arm/configs/vz6750_36g_i_n_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..680fd82cec0a3392cd7b83f63d3fdbaefaac8bfb --- /dev/null +++ b/arch/arm/configs/vz6750_36g_i_n_defconfig @@ -0,0 +1,508 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x40000000 +CONFIG_CROSS_COMPILE="arm-eabi-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_ARM_KERNMEM_PERMS=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_USE_OF=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="vz6750_36g_i_n" +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +CONFIG_AUTO_ZRELADDR=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_LZ4K_COMPRESS=y +CONFIG_ZRAM_DEBUG=y +CONFIG_ZSM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_36g_i_n" +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw imx135_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358_720p" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_LCM_HEIGHT="1280" +CONFIG_LCM_WIDTH="720" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=12 +CONFIG_MTK_MD3_SUPPORT=2 +CONFIG_MTK_C2K_LTE_MODE=2 +CONFIG_MTK_IRAT_SUPPORT=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_PERFMGR_TOUCH_BOOST=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_MTK_GMO_RAM_OPTIMIZE=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=1 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_LIBCRC32C=y diff --git a/arch/arm64/boot/dts/K6000_Plus.dts b/arch/arm64/boot/dts/K6000_Plus.dts new file mode 100644 index 0000000000000000000000000000000000000000..8fd1dd2f8e61436de2f521b2f2817b3cd2d73961 --- /dev/null +++ b/arch/arm64/boot/dts/K6000_Plus.dts @@ -0,0 +1,907 @@ + +/dts-v1/; + +#include "mt6755.dtsi" +#include "cust.dtsi" + +/ { + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x3e800000>; + }; + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4B434E loglevel=8"; + + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base_h = <0x0>; + atag,videolfb-fb_base_l = <0x7E800000>; + atag,videolfb-islcmfound = <1>; + /* because no lk, so lcm is not inited */ + atag,videolfb-islcm_inited = <0>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35695_fhd_dsi_cmd_truly_nt50358_drv"; + }; + led0:led@0 { + compatible = "mediatek,red"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led1:led@1 { + compatible = "mediatek,green"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led2:led@2 { + compatible = "mediatek,blue"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led3:led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led4:led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led5:led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led6:led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <5>; + }; +/* start sensor */ + cust_accel@0 { + compatible = "mediatek,mpu6515a"; + i2c_num = <1>; + /* i2c_addr = <0x4c 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <16>; + is_batch_supported = <1>; + }; + + cust_alsps@0 { + compatible = "mediatek,cm36686"; + i2c_num = <1>; + i2c_addr = <0x60 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als = <1>; + power_id = <0xffff>; + power_vol = <0>; +/* Total has 15 level*/ + als_level = <0 257 637 1027 2297 5588 6730 11301 20449 25768 31122 45552 57937 57937 57937>; +/* Total has 16 range*/ + als_value = <0 132 304 502 1004 2003 3006 5006 8004 10000 12000 16000 20000 20000 20000 20000>; + ps_threshold_high = <70>; + ps_threshold_low = <40>; + is_batch_supported_ps = <1>; + is_batch_supported_als = <1>; + }; + + cust_mag@0 { + compatible = "mediatek,akm8963"; + i2c_num = <1>; + /* i2c_addr = <0x0F 0 0 0>; */ + direction = <8>; + power_id = <0xffff>; + power_vol = <0>; + /* is_batch_supported = <0>; */ + }; + + cust_gyro@0 { + compatible = "mediatek,mpu6515g"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + + cust_baro@0 { + compatible = "mediatek,bmp280new"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <32>; + is_batch_supported = <0>; + }; +/* end sensor */ +}; +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <6>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 80 220 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; +}; + +/* TOUCH start */ +&touch { + tpd-resolution = <1080 1920>; + use-tpd-button = <0>; + tpd-key-num = <3>; + tpd-key-local= <139 172 158 0>; + tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>; + tpd-max-touch-num = <5>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <146>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <0 0 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: eint0default { + }; + ctp_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_sub_vcamd0: cam1@4 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_sub_vcamd1: cam1@5 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + /*camera_pins_cam_ldo_vcama_0: cam@vcama0 { + }; + camera_pins_cam_ldo_vcama_1: cam@vcama1 { + };*/ + camera_pins_default: camdefault { + }; + +}; + +&kd_camera_hw1 { + pinctrl-names = "default", + "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo_sub_vcamd_0", "cam_ldo_sub_vcamd_1"; + /*"cam2_rst0", "cam2_rst1", "cam2_pnd0", "cam2_pnd1", + "cam_ldo_vcama_0", "cam_ldo_vcama_1";*/ + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_sub_vcamd0>; + pinctrl-10 = <&camera_pins_sub_vcamd1>; + /* for main2 */ + /*pinctrl-9 = <&camera_pins_cam2_rst0>; + pinctrl-10 = <&camera_pins_cam2_rst1>; + pinctrl-11 = <&camera_pins_cam2_pnd0>; + pinctrl-12 = <&camera_pins_cam2_pnd1>;*/ + /* for ldo control by gpio */ + /*pinctrl-13 = <&camera_pins_cam_ldo_vcama_0>; + pinctrl-14 = <&camera_pins_cam_ldo_vcama_1>;*/ + status = "okay"; + +}; +/* CAMERA GPIO end */ + +&pio { + alsps_intpin_cfg: alspspincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + + alsps_intpin_default: alspsdefaultcfg { + + }; + + gyro_intpin_cfg: gyropincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + + gyro_intpin_default: gyrodefaultcfg { + + }; +}; + +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; + +&gyroscope { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_lcd_bias_enp0: lcd_bias_enp0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcd_bias_enp1: lcd_bias_enp1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", "lcd_bias_enp0_gpio", "lcd_bias_enp1_gpio"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_lcd_bias_enp0>; + pinctrl-6 = <&mtkfb_pins_lcd_bias_enp1>; + status = "okay"; +};/* DISPSYS GPIO standardization end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + }; + + gpslna_pins_init: gpslna@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; +}; +/* CONSYS end */ + +/* SPM GPIO standardization */ +&pio { + spm_pins_default: default { + }; + + spm_vmd1_sel: vmd1_sel { + pins_cmd_dat { + pins = ; + }; + }; + +}; + +&sleep{ + pinctrl-names = "default", "vmd1_sel"; + pinctrl-0 = <&spm_pins_default>; + pinctrl-1 = <&spm_vmd1_sel>; + status = "okay"; +}; +/* SPM end */ + +/* AUDIO GPIO standardization */ +&audgpio { + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "audi2s1-mode0", "audi2s1-mode1", "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow", "rcvspk-pullhigh", + "rcvspk-pulllow","hpdepop-pullhigh","hpdepop-pulllow"; + pinctrl-0 = <&aud_pins_default>; + pinctrl-1 = <&aud_pins_pmicclk_mode0>; + pinctrl-2 = <&aud_pins_pmicclk_mode1>; + pinctrl-3 = <&aud_pins_i2s1_mode0>; + pinctrl-4 = <&aud_pins_i2s1_mode1>; + pinctrl-5 = <&aud_pins_extamp_high>; + pinctrl-6 = <&aud_pins_extamp_low>; + pinctrl-7 = <&aud_pins_extamp2_high>; + pinctrl-8 = <&aud_pins_extamp2_low>; + pinctrl-9 = <&aud_pins_rcvspk_high>; + pinctrl-10 = <&aud_pins_rcvspk_low>; + pinctrl-11 = <&aud_pins_hpdepop_high>; + pinctrl-12 = <&aud_pins_hpdepop_low>; + status = "okay"; +}; + +&pio { + aud_pins_default: audiodefault { + }; + + aud_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode0: audi2s1mode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode1: audi2s1mode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_extamp_high: audexamphigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_extamp_low: audexamplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_extamp2_high: audexam2phigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + aud_pins_extamp2_low: audexamp2low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_rcvspk_high: audrcvspkhigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_rcvspk_low: audrcvspklow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_hpdepop_high: audhpdepophigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_hpdepop_low: audhpdepoplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; +/* AUDIO end */ + +/* UART GPIO */ +&apuart0 { + pinctrl-names = "uart0_gpio_default", + "uart0_rx_set", + "uart0_rx_clear", + "uart0_tx_set", + "uart0_tx_clear"; + pinctrl-0 = <&uart0_gpio_def_cfg>; + pinctrl-1 = <&uart0_rx_set_cfg>; + pinctrl-2 = <&uart0_rx_clr_cfg>; + pinctrl-3 = <&uart0_tx_set_cfg>; + pinctrl-4 = <&uart0_tx_clr_cfg>; + status = "okay"; +}; + +&pio { + /* UART GPIO Settings - Start */ + /* UART0: rx set, rx clear, tx clear, tx clear*/ + uart0_gpio_def_cfg:uart0gpiodefault { + + }; + uart0_rx_set_cfg:uart0_rx_set@gpio105 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_rx_clr_cfg:uart0_rx_clear@gpio105 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + uart0_tx_set_cfg:uart0_tx_set@gpio106 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_tx_clr_cfg:uart0_tx_clear@gpio106 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +};/* UART GPIO end */ + +/* IRTX GPIO end */ +&irtx_pwm { + pinctrl-names = "irtx_gpio_led_default", + "irtx_gpio_led_set", + "irtx_gpio_en_default", + "irtx_gpio_en_set"; + + pinctrl-0 = <&irtx_gpio_led_default>; + pinctrl-1 = <&irtx_gpio_led_set>; + pinctrl-2 = <&irtx_gpio_en_default>; + pinctrl-3 = <&irtx_gpio_en_set>; + status = "okay"; +}; +&pio { + /* IRTX GPIO Settings -Start */ + /* default: GPIO0, output, high */ + irtx_gpio_led_default:irtx_gpio_led_def@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_led_set:irtx_gpio_led_set@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + irtx_gpio_en_default:irtx_gpio_en_def@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_en_set:irtx_gpio_en_set@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + +}; /* IRTX GPIO Settings -End */ + +/* NFC GPIO standardization */ +&pio { + nfc_default: default { + + }; + + nfc_ven_high: state_ven_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_ven_low: state_ven_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_rst_high: state_rst_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_rst_low: state_rst_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_eint_high: state_eint_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_eint_low: state_eint_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_irq_init: state_irq_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; +}; + +&nfc { + pinctrl-names = "default", "ven_high", "ven_low", "rst_high", "rst_low", "eint_high", "eint_low", "irq_init"; + pinctrl-0 = <&nfc_default>; + pinctrl-1 = <&nfc_ven_high>; + pinctrl-2 = <&nfc_ven_low>; + pinctrl-3 = <&nfc_rst_high>; + pinctrl-4 = <&nfc_rst_low>; + pinctrl-5 = <&nfc_eint_high>; + pinctrl-6 = <&nfc_eint_low>; + pinctrl-7 = <&nfc_irq_init>; + status = "okay"; +}; +/* NFC end */ + + + + +&pio { + iddig_default: iddig_default { + }; + + iddig_init: iddig_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio43_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + gpio43_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&iddig_init>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio43_mode1_drvvbus_low>; + pinctrl-2 = <&gpio43_mode1_drvvbus_high>; + status = "okay"; +}; + +&i2c1 { + + gyro@68 { + compatible = "mediatek,gyro"; + reg = <0x69>; + status = "okay"; + }; + + gsensor@68 { + compatible = "mediatek,gsensor"; + reg = <0x68>; + status = "okay"; + }; +}; + +&ext_buck_vmd1 { + pinctrl-names = "default", "vmd1_sel_low", "vmd1_sel_high"; + + pinctrl-0 = <&vmd1_default>; + pinctrl-1 = <&vmd1_sel_low>; + pinctrl-2 = <&vmd1_sel_high>; +}; + +&pio { + vmd1_default: vmd10default { + }; + + vmd1_sel_low: vmd1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + vmd1_sel_high: vmd1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; diff --git a/arch/arm64/boot/dts/cust_mt6755_msdc.dtsi b/arch/arm64/boot/dts/cust_mt6755_msdc.dtsi new file mode 100755 index 0000000000000000000000000000000000000000..5f3faee65ff99ae80fc0d7a8ce6da7b02ad896fa --- /dev/null +++ b/arch/arm64/boot/dts/cust_mt6755_msdc.dtsi @@ -0,0 +1,173 @@ +/********************************************** + *MT6755 MSDC DTSI File +********************************************/ + +&mmc0 { + clk_src = /bits/ 8 ; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + msdc-sys-suspend; + /*mmc-ddr-1_8v;*/ + mmc-hs200-1_8v; + mmc-hs400-1_8v; + non-removable; + pinctl = <&mmc0_pins_default>; + register_setting = <&mmc0_register_setting_default>; + host_function = /bits/ 8 ; + bootable; + status = "okay"; + vmmc-supply = <&mt_pmic_vemc_ldo_reg>; +}; + +&mmc1 { + clk_src = /bits/ 8 ; + bus-width = <4>; + max-frequency = <200000000>; + msdc-sys-suspend; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + /*sd-uhs-ddr50;*/ + pinctl = <&mmc1_pins_default>; + pinctl_sdr104 = <&mmc1_pins_sdr104>; + pinctl_sdr50 = <&mmc1_pins_sdr50>; + pinctl_ddr50 = <&mmc1_pins_ddr50>; + register_setting = <&mmc1_register_setting_default>; + host_function = /bits/ 8 ; + cd_level = /bits/ 8 ; + cd-gpios = <&pio 83 0>; + status = "okay"; + vmmc-supply = <&mt_pmic_vmch_ldo_reg>; + vqmmc-supply = <&mt_pmic_vmc_ldo_reg>; +}; + +&mmc2 { + clk_src = /bits/ 8 ; + bus-width = <4>; + max-frequency = <200000000>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; + keep-power-in-suspend; + non-removable; + pinctl = <&mmc2_pins_default>; + register_setting = <&mmc2_register_setting_default>; + host_function = /bits/ 8 ; + status = "disable"; +}; + +&pio { + mmc0_pins_default: mmc0@default { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <2>; + }; + pins_rst { + drive-strength = /bits/ 8 <2>; + }; + pins_ds { + drive-strength = /bits/ 8 <2>; + }; + }; + + mmc0_register_setting_default: mmc0@register_default { + datrddly = /bits/ 8 <0 0 0 0 0 0 0 0>; + datwrddly = /bits/ 8 <0>; + cmdrrddly = /bits/ 8 <0>; + cmdrddly = /bits/ 8 <0>; + cmd_edge = /bits/ 8 ; + rdata_edge = /bits/ 8 ; + wdata_edge = /bits/ 8 ; + }; + + mmc1_pins_default: mmc1@default { + pins_cmd { + drive-strength = /bits/ 8 <3>; + }; + pins_dat { + drive-strength = /bits/ 8 <3>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_sdr104: mmc1@sdr104 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_sdr50: mmc1@sdr50 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_pins_ddr50: mmc1@ddr50 { + pins_cmd { + drive-strength = /bits/ 8 <2>; + }; + pins_dat { + drive-strength = /bits/ 8 <2>; + }; + pins_clk { + drive-strength = /bits/ 8 <3>; + }; + }; + + mmc1_register_setting_default: mmc1@register_default { + datrddly = /bits/ 8 <0 0 0 0 0 0 0 0>; + datwrddly = /bits/ 8 <0>; + cmdrrddly = /bits/ 8 <0>; + cmdrddly = /bits/ 8 <0>; + cmd_edge = /bits/ 8 ; + rdata_edge = /bits/ 8 ; + wdata_edge = /bits/ 8 ; + }; + + mmc2_pins_default: mmc2@default { + pins_cmd { + drive-strength = /bits/ 8 <1>; + }; + pins_dat { + drive-strength = /bits/ 8 <1>; + }; + pins_clk { + drive-strength = /bits/ 8 <1>; + }; + }; + + mmc2_register_setting_default: mmc2@register_default { + datrddly = /bits/ 8 <0 0 0 0 0 0 0 0>; + datwrddly = /bits/ 8 <0>; + cmdrrddly = /bits/ 8 <0>; + cmdrddly = /bits/ 8 <0>; + cmd_edge = /bits/ 8 ; + rdata_edge = /bits/ 8 ; + wdata_edge = /bits/ 8 ; + }; +}; diff --git a/arch/arm64/boot/dts/mt6755-pinfunc.h b/arch/arm64/boot/dts/mt6755-pinfunc.h new file mode 100644 index 0000000000000000000000000000000000000000..fed390c3c9f1a71866074f22e3e47a1986cd80e6 --- /dev/null +++ b/arch/arm64/boot/dts/mt6755-pinfunc.h @@ -0,0 +1,1033 @@ +/* + * Generated by MTK SP DrvGen Version 03.13.6 for MT6755. Copyright MediaTek Inc. (C) 2013. + * Wed Jul 22 21:04:21 2015 + * Do Not Modify the File. + */ + +/************************* + * GPIO PINFUNC File +*************************/ + +#ifndef __DTS_MT6755_PINFUNC_H +#define __DTS_MT6755_PINFUNC_H + +#include "mt65xx.h" + +#define PINMUX_GPIO0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) +#define PINMUX_GPIO0__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(0) | 2) +#define PINMUX_GPIO0__FUNC_CLKM0 (MTK_PIN_NO(0) | 3) +#define PINMUX_GPIO0__FUNC_IDDIG (MTK_PIN_NO(0) | 4) +#define PINMUX_GPIO0__FUNC_C2K_EINT0 (MTK_PIN_NO(0) | 5) +#define PINMUX_GPIO0__FUNC_I2S3_MCK (MTK_PIN_NO(0) | 6) + +#define PINMUX_GPIO1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0) +#define PINMUX_GPIO1__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(1) | 2) +#define PINMUX_GPIO1__FUNC_CLKM1 (MTK_PIN_NO(1) | 3) +#define PINMUX_GPIO1__FUNC_USB_DRVVBUS (MTK_PIN_NO(1) | 4) +#define PINMUX_GPIO1__FUNC_C2K_EINT1 (MTK_PIN_NO(1) | 5) +#define PINMUX_GPIO1__FUNC_I2S3_BCK (MTK_PIN_NO(1) | 6) + +#define PINMUX_GPIO2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0) +#define PINMUX_GPIO2__FUNC_CMFLASH (MTK_PIN_NO(2) | 1) +#define PINMUX_GPIO2__FUNC_UTXD1 (MTK_PIN_NO(2) | 2) +#define PINMUX_GPIO2__FUNC_CLKM2 (MTK_PIN_NO(2) | 3) +#define PINMUX_GPIO2__FUNC_MD_URXD2 (MTK_PIN_NO(2) | 4) +#define PINMUX_GPIO2__FUNC_C2K_UTXD1 (MTK_PIN_NO(2) | 5) +#define PINMUX_GPIO2__FUNC_I2S3_LRCK (MTK_PIN_NO(2) | 6) + +#define PINMUX_GPIO3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0) +#define PINMUX_GPIO3__FUNC_PWM_A (MTK_PIN_NO(3) | 1) +#define PINMUX_GPIO3__FUNC_URXD1 (MTK_PIN_NO(3) | 2) +#define PINMUX_GPIO3__FUNC_CLKM3 (MTK_PIN_NO(3) | 3) +#define PINMUX_GPIO3__FUNC_MD_UTXD2 (MTK_PIN_NO(3) | 4) +#define PINMUX_GPIO3__FUNC_C2K_URXD1 (MTK_PIN_NO(3) | 5) +#define PINMUX_GPIO3__FUNC_I2S3_DO (MTK_PIN_NO(3) | 6) +#define PINMUX_GPIO3__FUNC_SPI1_B_MI (MTK_PIN_NO(3) | 7) + +#define PINMUX_GPIO4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0) +#define PINMUX_GPIO4__FUNC_PWM_B (MTK_PIN_NO(4) | 1) +#define PINMUX_GPIO4__FUNC_I2S0_MCK (MTK_PIN_NO(4) | 2) +#define PINMUX_GPIO4__FUNC_UCTS0 (MTK_PIN_NO(4) | 3) +#define PINMUX_GPIO4__FUNC_MD_URXD1 (MTK_PIN_NO(4) | 4) +#define PINMUX_GPIO4__FUNC_C2K_UTXD0 (MTK_PIN_NO(4) | 5) +#define PINMUX_GPIO4__FUNC_ANT_SEL3 (MTK_PIN_NO(4) | 6) +#define PINMUX_GPIO4__FUNC_SPI1_B_MI (MTK_PIN_NO(4) | 7) + +#define PINMUX_GPIO5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0) +#define PINMUX_GPIO5__FUNC_PWM_C (MTK_PIN_NO(5) | 1) +#define PINMUX_GPIO5__FUNC_I2S0_BCK (MTK_PIN_NO(5) | 2) +#define PINMUX_GPIO5__FUNC_URTS0 (MTK_PIN_NO(5) | 3) +#define PINMUX_GPIO5__FUNC_MD_UTXD1 (MTK_PIN_NO(5) | 4) +#define PINMUX_GPIO5__FUNC_C2K_URXD0 (MTK_PIN_NO(5) | 5) +#define PINMUX_GPIO5__FUNC_ANT_SEL4 (MTK_PIN_NO(5) | 6) +#define PINMUX_GPIO5__FUNC_SPI1_B_CSB (MTK_PIN_NO(5) | 7) + +#define PINMUX_GPIO6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0) +#define PINMUX_GPIO6__FUNC_IRTX_OUT (MTK_PIN_NO(6) | 1) +#define PINMUX_GPIO6__FUNC_I2S0_LRCK (MTK_PIN_NO(6) | 2) +#define PINMUX_GPIO6__FUNC_IDDIG (MTK_PIN_NO(6) | 3) +#define PINMUX_GPIO6__FUNC_MD_URXD0 (MTK_PIN_NO(6) | 4) +#define PINMUX_GPIO6__FUNC_SDA0 (MTK_PIN_NO(6) | 5) +#define PINMUX_GPIO6__FUNC_ANT_SEL5 (MTK_PIN_NO(6) | 6) +#define PINMUX_GPIO6__FUNC_SPI1_B_MO (MTK_PIN_NO(6) | 7) + +#define PINMUX_GPIO7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0) +#define PINMUX_GPIO7__FUNC_IRTX_OUT (MTK_PIN_NO(7) | 1) +#define PINMUX_GPIO7__FUNC_I2S0_DI (MTK_PIN_NO(7) | 2) +#define PINMUX_GPIO7__FUNC_USB_DRVVBUS (MTK_PIN_NO(7) | 3) +#define PINMUX_GPIO7__FUNC_MD_UTXD0 (MTK_PIN_NO(7) | 4) +#define PINMUX_GPIO7__FUNC_SCL0 (MTK_PIN_NO(7) | 5) +#define PINMUX_GPIO7__FUNC_PCC_PPC_IO (MTK_PIN_NO(7) | 6) +#define PINMUX_GPIO7__FUNC_SPI1_B_CLK (MTK_PIN_NO(7) | 7) + +#define PINMUX_GPIO8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0) +#define PINMUX_GPIO8__FUNC_PWM_A (MTK_PIN_NO(8) | 1) +#define PINMUX_GPIO8__FUNC_PCC_PPC_IO (MTK_PIN_NO(8) | 2) +#define PINMUX_GPIO8__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(8) | 4) +#define PINMUX_GPIO8__FUNC_C2K_DM_JTINTP (MTK_PIN_NO(8) | 5) +#define PINMUX_GPIO8__FUNC_IO_JTAG_TRSTN (MTK_PIN_NO(8) | 6) +#define PINMUX_GPIO8__FUNC_DBG_MON_A44 (MTK_PIN_NO(8) | 7) + +#define PINMUX_GPIO9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0) +#define PINMUX_GPIO9__FUNC_PWM_B (MTK_PIN_NO(9) | 1) +#define PINMUX_GPIO9__FUNC_UCTS1 (MTK_PIN_NO(9) | 2) +#define PINMUX_GPIO9__FUNC_DAP_SIB1_SWD (MTK_PIN_NO(9) | 3) +#define PINMUX_GPIO9__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(9) | 4) +#define PINMUX_GPIO9__FUNC_IRTX_OUT (MTK_PIN_NO(9) | 5) +#define PINMUX_GPIO9__FUNC_DBG_MON_A45 (MTK_PIN_NO(9) | 7) + +#define PINMUX_GPIO10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0) +#define PINMUX_GPIO10__FUNC_PWM_C (MTK_PIN_NO(10) | 1) +#define PINMUX_GPIO10__FUNC_URTS1 (MTK_PIN_NO(10) | 2) +#define PINMUX_GPIO10__FUNC_DAP_SIB1_SWCK (MTK_PIN_NO(10) | 3) +#define PINMUX_GPIO10__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(10) | 4) +#define PINMUX_GPIO10__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(10) | 5) +#define PINMUX_GPIO10__FUNC_DBG_MON_A46 (MTK_PIN_NO(10) | 7) + +#define PINMUX_GPIO11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0) +#define PINMUX_GPIO11__FUNC_IRTX_OUT (MTK_PIN_NO(11) | 1) +#define PINMUX_GPIO11__FUNC_IDDIG (MTK_PIN_NO(11) | 2) +#define PINMUX_GPIO11__FUNC_I2S1_MCK (MTK_PIN_NO(11) | 3) +#define PINMUX_GPIO11__FUNC_PWM_B (MTK_PIN_NO(11) | 4) +#define PINMUX_GPIO11__FUNC_CLKM0 (MTK_PIN_NO(11) | 5) +#define PINMUX_GPIO11__FUNC_SRCLKENAI1 (MTK_PIN_NO(11) | 6) + +#define PINMUX_GPIO12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0) +#define PINMUX_GPIO12__FUNC_IRTX_OUT (MTK_PIN_NO(12) | 1) +#define PINMUX_GPIO12__FUNC_USB_DRVVBUS (MTK_PIN_NO(12) | 2) +#define PINMUX_GPIO12__FUNC_I2S2_DI (MTK_PIN_NO(12) | 3) +#define PINMUX_GPIO12__FUNC_PWM_C (MTK_PIN_NO(12) | 4) +#define PINMUX_GPIO12__FUNC_CLKM1 (MTK_PIN_NO(12) | 5) +#define PINMUX_GPIO12__FUNC_CMFLASH (MTK_PIN_NO(12) | 6) + +#define PINMUX_GPIO13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0) +#define PINMUX_GPIO13__FUNC_DPI_D0 (MTK_PIN_NO(13) | 1) +#define PINMUX_GPIO13__FUNC_MRG_SYNC (MTK_PIN_NO(13) | 2) +#define PINMUX_GPIO13__FUNC_PCM0_SYNC (MTK_PIN_NO(13) | 3) +#define PINMUX_GPIO13__FUNC_MD_URXD0 (MTK_PIN_NO(13) | 4) +#define PINMUX_GPIO13__FUNC_C2K_EINT0 (MTK_PIN_NO(13) | 5) +#define PINMUX_GPIO13__FUNC_I2S0_MCK (MTK_PIN_NO(13) | 6) +#define PINMUX_GPIO13__FUNC_DBG_MON_A19 (MTK_PIN_NO(13) | 7) + +#define PINMUX_GPIO14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0) +#define PINMUX_GPIO14__FUNC_DPI_D1 (MTK_PIN_NO(14) | 1) +#define PINMUX_GPIO14__FUNC_MRG_CLK (MTK_PIN_NO(14) | 2) +#define PINMUX_GPIO14__FUNC_PCM0_CLK (MTK_PIN_NO(14) | 3) +#define PINMUX_GPIO14__FUNC_MD_UTXD0 (MTK_PIN_NO(14) | 4) +#define PINMUX_GPIO14__FUNC_C2K_EINT1 (MTK_PIN_NO(14) | 5) +#define PINMUX_GPIO14__FUNC_I2S0_BCK (MTK_PIN_NO(14) | 6) +#define PINMUX_GPIO14__FUNC_DBG_MON_A20 (MTK_PIN_NO(14) | 7) + +#define PINMUX_GPIO15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0) +#define PINMUX_GPIO15__FUNC_DPI_D2 (MTK_PIN_NO(15) | 1) +#define PINMUX_GPIO15__FUNC_MRG_DO (MTK_PIN_NO(15) | 2) +#define PINMUX_GPIO15__FUNC_PCM0_DO (MTK_PIN_NO(15) | 3) +#define PINMUX_GPIO15__FUNC_MD_URXD1 (MTK_PIN_NO(15) | 4) +#define PINMUX_GPIO15__FUNC_C2K_DM_EINT0 (MTK_PIN_NO(15) | 5) +#define PINMUX_GPIO15__FUNC_I2S0_LRCK (MTK_PIN_NO(15) | 6) +#define PINMUX_GPIO15__FUNC_DBG_MON_A21 (MTK_PIN_NO(15) | 7) + +#define PINMUX_GPIO16__FUNC_GPIO16 (MTK_PIN_NO(16) | 0) +#define PINMUX_GPIO16__FUNC_DPI_D3 (MTK_PIN_NO(16) | 1) +#define PINMUX_GPIO16__FUNC_MRG_DI (MTK_PIN_NO(16) | 2) +#define PINMUX_GPIO16__FUNC_PCM0_DI (MTK_PIN_NO(16) | 3) +#define PINMUX_GPIO16__FUNC_MD_UTXD1 (MTK_PIN_NO(16) | 4) +#define PINMUX_GPIO16__FUNC_C2K_DM_EINT1 (MTK_PIN_NO(16) | 5) +#define PINMUX_GPIO16__FUNC_I2S0_DI (MTK_PIN_NO(16) | 6) +#define PINMUX_GPIO16__FUNC_DBG_MON_A22 (MTK_PIN_NO(16) | 7) + +#define PINMUX_GPIO17__FUNC_GPIO17 (MTK_PIN_NO(17) | 0) +#define PINMUX_GPIO17__FUNC_DPI_D4 (MTK_PIN_NO(17) | 1) +#define PINMUX_GPIO17__FUNC_UCTS1 (MTK_PIN_NO(17) | 2) +#define PINMUX_GPIO17__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(17) | 3) +#define PINMUX_GPIO17__FUNC_MD_URXD2 (MTK_PIN_NO(17) | 4) +#define PINMUX_GPIO17__FUNC_C2K_URXD0 (MTK_PIN_NO(17) | 5) +#define PINMUX_GPIO17__FUNC_I2S1_MCK (MTK_PIN_NO(17) | 6) +#define PINMUX_GPIO17__FUNC_DBG_MON_A23 (MTK_PIN_NO(17) | 7) + +#define PINMUX_GPIO18__FUNC_GPIO18 (MTK_PIN_NO(18) | 0) +#define PINMUX_GPIO18__FUNC_DPI_D5 (MTK_PIN_NO(18) | 1) +#define PINMUX_GPIO18__FUNC_URTS1 (MTK_PIN_NO(18) | 2) +#define PINMUX_GPIO18__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(18) | 3) +#define PINMUX_GPIO18__FUNC_MD_UTXD2 (MTK_PIN_NO(18) | 4) +#define PINMUX_GPIO18__FUNC_C2K_UTXD0 (MTK_PIN_NO(18) | 5) +#define PINMUX_GPIO18__FUNC_I2S1_BCK (MTK_PIN_NO(18) | 6) +#define PINMUX_GPIO18__FUNC_DBG_MON_A24 (MTK_PIN_NO(18) | 7) + +#define PINMUX_GPIO19__FUNC_GPIO19 (MTK_PIN_NO(19) | 0) +#define PINMUX_GPIO19__FUNC_DPI_D6 (MTK_PIN_NO(19) | 1) +#define PINMUX_GPIO19__FUNC_URXD1 (MTK_PIN_NO(19) | 2) +#define PINMUX_GPIO19__FUNC_CONN_MCU_TDO (MTK_PIN_NO(19) | 3) +#define PINMUX_GPIO19__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(19) | 4) +#define PINMUX_GPIO19__FUNC_I2S1_LRCK (MTK_PIN_NO(19) | 6) +#define PINMUX_GPIO19__FUNC_DBG_MON_A25 (MTK_PIN_NO(19) | 7) + +#define PINMUX_GPIO20__FUNC_GPIO20 (MTK_PIN_NO(20) | 0) +#define PINMUX_GPIO20__FUNC_DPI_D7 (MTK_PIN_NO(20) | 1) +#define PINMUX_GPIO20__FUNC_UTXD1 (MTK_PIN_NO(20) | 2) +#define PINMUX_GPIO20__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(20) | 3) +#define PINMUX_GPIO20__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(20) | 4) +#define PINMUX_GPIO20__FUNC_I2S1_DO (MTK_PIN_NO(20) | 6) +#define PINMUX_GPIO20__FUNC_DBG_MON_A26 (MTK_PIN_NO(20) | 7) + +#define PINMUX_GPIO21__FUNC_GPIO21 (MTK_PIN_NO(21) | 0) +#define PINMUX_GPIO21__FUNC_DPI_D8 (MTK_PIN_NO(21) | 1) +#define PINMUX_GPIO21__FUNC_SRCLKENAI1 (MTK_PIN_NO(21) | 2) +#define PINMUX_GPIO21__FUNC_CONN_MCU_TMS (MTK_PIN_NO(21) | 3) +#define PINMUX_GPIO21__FUNC_DAP_SIB1_SWD (MTK_PIN_NO(21) | 4) +#define PINMUX_GPIO21__FUNC_CONN_MCU_AICE_TMSC (MTK_PIN_NO(21) | 5) +#define PINMUX_GPIO21__FUNC_I2S2_MCK (MTK_PIN_NO(21) | 6) +#define PINMUX_GPIO21__FUNC_DBG_MON_A27 (MTK_PIN_NO(21) | 7) + +#define PINMUX_GPIO22__FUNC_GPIO22 (MTK_PIN_NO(22) | 0) +#define PINMUX_GPIO22__FUNC_DPI_D9 (MTK_PIN_NO(22) | 1) +#define PINMUX_GPIO22__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(22) | 2) +#define PINMUX_GPIO22__FUNC_CONN_MCU_TCK (MTK_PIN_NO(22) | 3) +#define PINMUX_GPIO22__FUNC_DAP_SIB1_SWCK (MTK_PIN_NO(22) | 4) +#define PINMUX_GPIO22__FUNC_CONN_MCU_AICE_TCKC (MTK_PIN_NO(22) | 5) +#define PINMUX_GPIO22__FUNC_I2S2_BCK (MTK_PIN_NO(22) | 6) +#define PINMUX_GPIO22__FUNC_DBG_MON_A28 (MTK_PIN_NO(22) | 7) + +#define PINMUX_GPIO23__FUNC_GPIO23 (MTK_PIN_NO(23) | 0) +#define PINMUX_GPIO23__FUNC_DPI_D10 (MTK_PIN_NO(23) | 1) +#define PINMUX_GPIO23__FUNC_IDDIG (MTK_PIN_NO(23) | 2) +#define PINMUX_GPIO23__FUNC_CONN_MCU_TDI (MTK_PIN_NO(23) | 3) +#define PINMUX_GPIO23__FUNC_PWM_B (MTK_PIN_NO(23) | 5) +#define PINMUX_GPIO23__FUNC_I2S2_LRCK (MTK_PIN_NO(23) | 6) +#define PINMUX_GPIO23__FUNC_DBG_MON_A29 (MTK_PIN_NO(23) | 7) + +#define PINMUX_GPIO24__FUNC_GPIO24 (MTK_PIN_NO(24) | 0) +#define PINMUX_GPIO24__FUNC_DPI_D11 (MTK_PIN_NO(24) | 1) +#define PINMUX_GPIO24__FUNC_USB_DRVVBUS (MTK_PIN_NO(24) | 2) +#define PINMUX_GPIO24__FUNC_CONN_DSP_JCK (MTK_PIN_NO(24) | 3) +#define PINMUX_GPIO24__FUNC_SPI1_A_MI (MTK_PIN_NO(24) | 4) +#define PINMUX_GPIO24__FUNC_PWM_C (MTK_PIN_NO(24) | 5) +#define PINMUX_GPIO24__FUNC_I2S2_DI (MTK_PIN_NO(24) | 6) +#define PINMUX_GPIO24__FUNC_DBG_MON_A30 (MTK_PIN_NO(24) | 7) + +#define PINMUX_GPIO25__FUNC_GPIO25 (MTK_PIN_NO(25) | 0) +#define PINMUX_GPIO25__FUNC_DPI_HSYNC (MTK_PIN_NO(25) | 1) +#define PINMUX_GPIO25__FUNC_SPI1_A_MI (MTK_PIN_NO(25) | 2) +#define PINMUX_GPIO25__FUNC_CONN_DSP_JMS (MTK_PIN_NO(25) | 3) +#define PINMUX_GPIO25__FUNC_CLKM0 (MTK_PIN_NO(25) | 4) +#define PINMUX_GPIO25__FUNC_C2K_UTXD1 (MTK_PIN_NO(25) | 5) +#define PINMUX_GPIO25__FUNC_I2S3_MCK (MTK_PIN_NO(25) | 6) +#define PINMUX_GPIO25__FUNC_DBG_MON_A31 (MTK_PIN_NO(25) | 7) + +#define PINMUX_GPIO26__FUNC_GPIO26 (MTK_PIN_NO(26) | 0) +#define PINMUX_GPIO26__FUNC_DPI_VSYNC (MTK_PIN_NO(26) | 1) +#define PINMUX_GPIO26__FUNC_SPI1_A_CSB (MTK_PIN_NO(26) | 2) +#define PINMUX_GPIO26__FUNC_CONN_DSP_JDI (MTK_PIN_NO(26) | 3) +#define PINMUX_GPIO26__FUNC_CLKM1 (MTK_PIN_NO(26) | 4) +#define PINMUX_GPIO26__FUNC_C2K_URXD1 (MTK_PIN_NO(26) | 5) +#define PINMUX_GPIO26__FUNC_I2S3_BCK (MTK_PIN_NO(26) | 6) +#define PINMUX_GPIO26__FUNC_DBG_MON_A32 (MTK_PIN_NO(26) | 7) + +#define PINMUX_GPIO27__FUNC_GPIO27 (MTK_PIN_NO(27) | 0) +#define PINMUX_GPIO27__FUNC_DPI_DE (MTK_PIN_NO(27) | 1) +#define PINMUX_GPIO27__FUNC_SPI1_A_MO (MTK_PIN_NO(27) | 2) +#define PINMUX_GPIO27__FUNC_CONN_DSP_JDO (MTK_PIN_NO(27) | 3) +#define PINMUX_GPIO27__FUNC_CLKM2 (MTK_PIN_NO(27) | 4) +#define PINMUX_GPIO27__FUNC_C2K_DM_EINT2 (MTK_PIN_NO(27) | 5) +#define PINMUX_GPIO27__FUNC_I2S3_LRCK (MTK_PIN_NO(27) | 6) +#define PINMUX_GPIO27__FUNC_DBG_MON_A33 (MTK_PIN_NO(27) | 7) + +#define PINMUX_GPIO28__FUNC_GPIO28 (MTK_PIN_NO(28) | 0) +#define PINMUX_GPIO28__FUNC_DPI_CK (MTK_PIN_NO(28) | 1) +#define PINMUX_GPIO28__FUNC_SPI1_A_CLK (MTK_PIN_NO(28) | 2) +#define PINMUX_GPIO28__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(28) | 3) +#define PINMUX_GPIO28__FUNC_CLKM3 (MTK_PIN_NO(28) | 4) +#define PINMUX_GPIO28__FUNC_C2K_DM_EINT3 (MTK_PIN_NO(28) | 5) +#define PINMUX_GPIO28__FUNC_I2S3_DO (MTK_PIN_NO(28) | 6) +#define PINMUX_GPIO28__FUNC_DBG_MON_A34 (MTK_PIN_NO(28) | 7) + +#define PINMUX_GPIO29__FUNC_GPIO29 (MTK_PIN_NO(29) | 0) +#define PINMUX_GPIO29__FUNC_SRCLKENA1 (MTK_PIN_NO(29) | 1) + +#define PINMUX_GPIO30__FUNC_GPIO30 (MTK_PIN_NO(30) | 0) +#define PINMUX_GPIO30__FUNC_MSDC1_CLK (MTK_PIN_NO(30) | 1) +#define PINMUX_GPIO30__FUNC_IO_JTAG_TCK (MTK_PIN_NO(30) | 2) +#define PINMUX_GPIO30__FUNC_CONN_DSP_JCK (MTK_PIN_NO(30) | 4) +#define PINMUX_GPIO30__FUNC_C2K_DM_OTCK (MTK_PIN_NO(30) | 5) +#define PINMUX_GPIO30__FUNC_C2K_TCK (MTK_PIN_NO(30) | 6) +#define PINMUX_GPIO30__FUNC_DBG_MON_A53 (MTK_PIN_NO(30) | 7) + +#define PINMUX_GPIO31__FUNC_GPIO31 (MTK_PIN_NO(31) | 0) +#define PINMUX_GPIO31__FUNC_MSDC1_DAT3 (MTK_PIN_NO(31) | 1) +#define PINMUX_GPIO31__FUNC_DAP_SIB1_SWD (MTK_PIN_NO(31) | 3) +#define PINMUX_GPIO31__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(31) | 4) +#define PINMUX_GPIO31__FUNC_C2K_DM_JTINTP (MTK_PIN_NO(31) | 5) +#define PINMUX_GPIO31__FUNC_C2K_RTCK (MTK_PIN_NO(31) | 6) +#define PINMUX_GPIO31__FUNC_DBG_MON_A54 (MTK_PIN_NO(31) | 7) + +#define PINMUX_GPIO32__FUNC_GPIO32 (MTK_PIN_NO(32) | 0) +#define PINMUX_GPIO32__FUNC_MSDC1_CMD (MTK_PIN_NO(32) | 1) +#define PINMUX_GPIO32__FUNC_IO_JTAG_TMS (MTK_PIN_NO(32) | 2) +#define PINMUX_GPIO32__FUNC_CONN_DSP_JMS (MTK_PIN_NO(32) | 4) +#define PINMUX_GPIO32__FUNC_C2K_DM_OTMS (MTK_PIN_NO(32) | 5) +#define PINMUX_GPIO32__FUNC_C2K_TMS (MTK_PIN_NO(32) | 6) +#define PINMUX_GPIO32__FUNC_DBG_MON_A55 (MTK_PIN_NO(32) | 7) + +#define PINMUX_GPIO33__FUNC_GPIO33 (MTK_PIN_NO(33) | 0) +#define PINMUX_GPIO33__FUNC_MSDC1_DAT0 (MTK_PIN_NO(33) | 1) +#define PINMUX_GPIO33__FUNC_IO_JTAG_TDI (MTK_PIN_NO(33) | 2) +#define PINMUX_GPIO33__FUNC_CONN_DSP_JDI (MTK_PIN_NO(33) | 4) +#define PINMUX_GPIO33__FUNC_C2K_DM_OTDI (MTK_PIN_NO(33) | 5) +#define PINMUX_GPIO33__FUNC_C2K_TDI (MTK_PIN_NO(33) | 6) +#define PINMUX_GPIO33__FUNC_DBG_MON_A56 (MTK_PIN_NO(33) | 7) + +#define PINMUX_GPIO34__FUNC_GPIO34 (MTK_PIN_NO(34) | 0) +#define PINMUX_GPIO34__FUNC_MSDC1_DAT2 (MTK_PIN_NO(34) | 1) +#define PINMUX_GPIO34__FUNC_IO_JTAG_TRSTN (MTK_PIN_NO(34) | 2) +#define PINMUX_GPIO34__FUNC_DAP_SIB1_SWCK (MTK_PIN_NO(34) | 5) +#define PINMUX_GPIO34__FUNC_C2K_NTRST (MTK_PIN_NO(34) | 6) +#define PINMUX_GPIO34__FUNC_DBG_MON_A57 (MTK_PIN_NO(34) | 7) + +#define PINMUX_GPIO35__FUNC_GPIO35 (MTK_PIN_NO(35) | 0) +#define PINMUX_GPIO35__FUNC_MSDC1_DAT1 (MTK_PIN_NO(35) | 1) +#define PINMUX_GPIO35__FUNC_IO_JTAG_TDO (MTK_PIN_NO(35) | 2) +#define PINMUX_GPIO35__FUNC_CONN_DSP_JDO (MTK_PIN_NO(35) | 4) +#define PINMUX_GPIO35__FUNC_C2K_DM_OTDO (MTK_PIN_NO(35) | 5) +#define PINMUX_GPIO35__FUNC_C2K_TDO (MTK_PIN_NO(35) | 6) +#define PINMUX_GPIO35__FUNC_DBG_MON_A58 (MTK_PIN_NO(35) | 7) + +#define PINMUX_GPIO36__FUNC_GPIO36 (MTK_PIN_NO(36) | 0) +#define PINMUX_GPIO36__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(36) | 1) +#define PINMUX_GPIO36__FUNC_MD1_SIM1_SIO (MTK_PIN_NO(36) | 3) +#define PINMUX_GPIO36__FUNC_C2K_UIM0_IO (MTK_PIN_NO(36) | 5) +#define PINMUX_GPIO36__FUNC_C2K_UIM1_IO (MTK_PIN_NO(36) | 6) +#define PINMUX_GPIO36__FUNC_DBG_MON_A38 (MTK_PIN_NO(36) | 7) + +#define PINMUX_GPIO37__FUNC_GPIO37 (MTK_PIN_NO(37) | 0) +#define PINMUX_GPIO37__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(37) | 1) +#define PINMUX_GPIO37__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(37) | 3) +#define PINMUX_GPIO37__FUNC_C2K_UIM0_RST (MTK_PIN_NO(37) | 5) +#define PINMUX_GPIO37__FUNC_C2K_UIM1_RST (MTK_PIN_NO(37) | 6) +#define PINMUX_GPIO37__FUNC_DBG_MON_A39 (MTK_PIN_NO(37) | 7) + +#define PINMUX_GPIO38__FUNC_GPIO38 (MTK_PIN_NO(38) | 0) +#define PINMUX_GPIO38__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(38) | 1) +#define PINMUX_GPIO38__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(38) | 3) +#define PINMUX_GPIO38__FUNC_C2K_UIM0_CLK (MTK_PIN_NO(38) | 5) +#define PINMUX_GPIO38__FUNC_C2K_UIM1_CLK (MTK_PIN_NO(38) | 6) +#define PINMUX_GPIO38__FUNC_DBG_MON_A40 (MTK_PIN_NO(38) | 7) + +#define PINMUX_GPIO39__FUNC_GPIO39 (MTK_PIN_NO(39) | 0) +#define PINMUX_GPIO39__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(39) | 1) +#define PINMUX_GPIO39__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(39) | 3) +#define PINMUX_GPIO39__FUNC_C2K_UIM0_CLK (MTK_PIN_NO(39) | 5) +#define PINMUX_GPIO39__FUNC_C2K_UIM1_CLK (MTK_PIN_NO(39) | 6) +#define PINMUX_GPIO39__FUNC_DBG_MON_A41 (MTK_PIN_NO(39) | 7) + +#define PINMUX_GPIO40__FUNC_GPIO40 (MTK_PIN_NO(40) | 0) +#define PINMUX_GPIO40__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(40) | 1) +#define PINMUX_GPIO40__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(40) | 3) +#define PINMUX_GPIO40__FUNC_C2K_UIM0_RST (MTK_PIN_NO(40) | 5) +#define PINMUX_GPIO40__FUNC_C2K_UIM1_RST (MTK_PIN_NO(40) | 6) +#define PINMUX_GPIO40__FUNC_DBG_MON_A42 (MTK_PIN_NO(40) | 7) + +#define PINMUX_GPIO41__FUNC_GPIO41 (MTK_PIN_NO(41) | 0) +#define PINMUX_GPIO41__FUNC_MD1_SIM1_SIO (MTK_PIN_NO(41) | 1) +#define PINMUX_GPIO41__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(41) | 3) +#define PINMUX_GPIO41__FUNC_C2K_UIM0_IO (MTK_PIN_NO(41) | 5) +#define PINMUX_GPIO41__FUNC_C2K_UIM1_IO (MTK_PIN_NO(41) | 6) +#define PINMUX_GPIO41__FUNC_DBG_MON_A43 (MTK_PIN_NO(41) | 7) + +#define PINMUX_GPIO42__FUNC_GPIO42 (MTK_PIN_NO(42) | 0) +#define PINMUX_GPIO42__FUNC_IDDIG (MTK_PIN_NO(42) | 1) +#define PINMUX_GPIO42__FUNC_URXD1 (MTK_PIN_NO(42) | 2) +#define PINMUX_GPIO42__FUNC_UCTS0 (MTK_PIN_NO(42) | 3) +#define PINMUX_GPIO42__FUNC_SDA1 (MTK_PIN_NO(42) | 4) +#define PINMUX_GPIO42__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(42) | 5) +#define PINMUX_GPIO42__FUNC_KPCOL2 (MTK_PIN_NO(42) | 6) +#define PINMUX_GPIO42__FUNC_DBG_MON_A12 (MTK_PIN_NO(42) | 7) + +#define PINMUX_GPIO43__FUNC_GPIO43 (MTK_PIN_NO(43) | 0) +#define PINMUX_GPIO43__FUNC_USB_DRVVBUS (MTK_PIN_NO(43) | 1) +#define PINMUX_GPIO43__FUNC_UTXD1 (MTK_PIN_NO(43) | 2) +#define PINMUX_GPIO43__FUNC_URTS0 (MTK_PIN_NO(43) | 3) +#define PINMUX_GPIO43__FUNC_SCL1 (MTK_PIN_NO(43) | 4) +#define PINMUX_GPIO43__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(43) | 5) +#define PINMUX_GPIO43__FUNC_KPROW2 (MTK_PIN_NO(43) | 6) +#define PINMUX_GPIO43__FUNC_DBG_MON_A13 (MTK_PIN_NO(43) | 7) + +#define PINMUX_GPIO44__FUNC_GPIO44 (MTK_PIN_NO(44) | 0) +#define PINMUX_GPIO44__FUNC_DSI_TE (MTK_PIN_NO(44) | 1) +#define PINMUX_GPIO44__FUNC_DBG_MON_A15 (MTK_PIN_NO(44) | 7) + +#define PINMUX_GPIO45__FUNC_GPIO45 (MTK_PIN_NO(45) | 0) +#define PINMUX_GPIO45__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(45) | 1) +#define PINMUX_GPIO45__FUNC_URXD1 (MTK_PIN_NO(45) | 2) +#define PINMUX_GPIO45__FUNC_UCTS1 (MTK_PIN_NO(45) | 3) +#define PINMUX_GPIO45__FUNC_CLKM0 (MTK_PIN_NO(45) | 4) +#define PINMUX_GPIO45__FUNC_IDDIG (MTK_PIN_NO(45) | 6) +#define PINMUX_GPIO45__FUNC_DBG_MON_A17 (MTK_PIN_NO(45) | 7) + +#define PINMUX_GPIO46__FUNC_GPIO46 (MTK_PIN_NO(46) | 0) +#define PINMUX_GPIO46__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(46) | 1) +#define PINMUX_GPIO46__FUNC_UTXD1 (MTK_PIN_NO(46) | 2) +#define PINMUX_GPIO46__FUNC_URTS1 (MTK_PIN_NO(46) | 3) +#define PINMUX_GPIO46__FUNC_PWM_B (MTK_PIN_NO(46) | 4) +#define PINMUX_GPIO46__FUNC_USB_DRVVBUS (MTK_PIN_NO(46) | 6) +#define PINMUX_GPIO46__FUNC_DBG_MON_A18 (MTK_PIN_NO(46) | 7) + +#define PINMUX_GPIO47__FUNC_GPIO47 (MTK_PIN_NO(47) | 0) +#define PINMUX_GPIO47__FUNC_SCL_APPM (MTK_PIN_NO(47) | 1) + +#define PINMUX_GPIO48__FUNC_GPIO48 (MTK_PIN_NO(48) | 0) +#define PINMUX_GPIO48__FUNC_SDA_APPM (MTK_PIN_NO(48) | 1) + +#define PINMUX_GPIO49__FUNC_GPIO49 (MTK_PIN_NO(49) | 0) +#define PINMUX_GPIO49__FUNC_SCL3 (MTK_PIN_NO(49) | 1) +#define PINMUX_GPIO49__FUNC_IDDIG (MTK_PIN_NO(49) | 2) + +#define PINMUX_GPIO50__FUNC_GPIO50 (MTK_PIN_NO(50) | 0) +#define PINMUX_GPIO50__FUNC_SDA3 (MTK_PIN_NO(50) | 1) +#define PINMUX_GPIO50__FUNC_IDDIG (MTK_PIN_NO(50) | 2) + +#define PINMUX_GPIO51__FUNC_GPIO51 (MTK_PIN_NO(51) | 0) +#define PINMUX_GPIO51__FUNC_BPI_BUS15 (MTK_PIN_NO(51) | 1) +#define PINMUX_GPIO51__FUNC_DBG_MON_B0 (MTK_PIN_NO(51) | 7) + +#define PINMUX_GPIO52__FUNC_GPIO52 (MTK_PIN_NO(52) | 0) +#define PINMUX_GPIO52__FUNC_BPI_BUS14 (MTK_PIN_NO(52) | 1) +#define PINMUX_GPIO52__FUNC_DBG_MON_B1 (MTK_PIN_NO(52) | 7) + +#define PINMUX_GPIO53__FUNC_GPIO53 (MTK_PIN_NO(53) | 0) +#define PINMUX_GPIO53__FUNC_BPI_BUS13 (MTK_PIN_NO(53) | 1) +#define PINMUX_GPIO53__FUNC_DBG_MON_B2 (MTK_PIN_NO(53) | 7) + +#define PINMUX_GPIO54__FUNC_GPIO54 (MTK_PIN_NO(54) | 0) +#define PINMUX_GPIO54__FUNC_BPI_BUS12 (MTK_PIN_NO(54) | 1) +#define PINMUX_GPIO54__FUNC_DBG_MON_B3 (MTK_PIN_NO(54) | 7) + +#define PINMUX_GPIO55__FUNC_GPIO55 (MTK_PIN_NO(55) | 0) +#define PINMUX_GPIO55__FUNC_BPI_BUS11 (MTK_PIN_NO(55) | 1) + +#define PINMUX_GPIO56__FUNC_GPIO56 (MTK_PIN_NO(56) | 0) +#define PINMUX_GPIO56__FUNC_BPI_BUS10 (MTK_PIN_NO(56) | 1) + +#define PINMUX_GPIO57__FUNC_GPIO57 (MTK_PIN_NO(57) | 0) +#define PINMUX_GPIO57__FUNC_BPI_BUS9 (MTK_PIN_NO(57) | 1) +#define PINMUX_GPIO57__FUNC_DBG_MON_B4 (MTK_PIN_NO(57) | 7) + +#define PINMUX_GPIO58__FUNC_GPIO58 (MTK_PIN_NO(58) | 0) +#define PINMUX_GPIO58__FUNC_BPI_BUS8 (MTK_PIN_NO(58) | 1) +#define PINMUX_GPIO58__FUNC_DBG_MON_B5 (MTK_PIN_NO(58) | 7) + +#define PINMUX_GPIO59__FUNC_GPIO59 (MTK_PIN_NO(59) | 0) +#define PINMUX_GPIO59__FUNC_BPI_BUS7 (MTK_PIN_NO(59) | 1) +#define PINMUX_GPIO59__FUNC_DBG_MON_B6 (MTK_PIN_NO(59) | 7) + +#define PINMUX_GPIO60__FUNC_GPIO60 (MTK_PIN_NO(60) | 0) +#define PINMUX_GPIO60__FUNC_BPI_BUS6 (MTK_PIN_NO(60) | 1) +#define PINMUX_GPIO60__FUNC_DBG_MON_B7 (MTK_PIN_NO(60) | 7) + +#define PINMUX_GPIO61__FUNC_GPIO61 (MTK_PIN_NO(61) | 0) +#define PINMUX_GPIO61__FUNC_BPI_BUS5 (MTK_PIN_NO(61) | 1) +#define PINMUX_GPIO61__FUNC_DBG_MON_B8 (MTK_PIN_NO(61) | 7) + +#define PINMUX_GPIO62__FUNC_GPIO62 (MTK_PIN_NO(62) | 0) +#define PINMUX_GPIO62__FUNC_BPI_BUS4 (MTK_PIN_NO(62) | 1) +#define PINMUX_GPIO62__FUNC_DBG_MON_B9 (MTK_PIN_NO(62) | 7) + +#define PINMUX_GPIO63__FUNC_GPIO63 (MTK_PIN_NO(63) | 0) +#define PINMUX_GPIO63__FUNC_MIPI1_SDATA (MTK_PIN_NO(63) | 1) +#define PINMUX_GPIO63__FUNC_DBG_MON_B10 (MTK_PIN_NO(63) | 7) + +#define PINMUX_GPIO64__FUNC_GPIO64 (MTK_PIN_NO(64) | 0) +#define PINMUX_GPIO64__FUNC_MIPI1_SCLK (MTK_PIN_NO(64) | 1) +#define PINMUX_GPIO64__FUNC_DBG_MON_B11 (MTK_PIN_NO(64) | 7) + +#define PINMUX_GPIO65__FUNC_GPIO65 (MTK_PIN_NO(65) | 0) +#define PINMUX_GPIO65__FUNC_MIPI0_SDATA (MTK_PIN_NO(65) | 1) +#define PINMUX_GPIO65__FUNC_DBG_MON_B12 (MTK_PIN_NO(65) | 7) + +#define PINMUX_GPIO66__FUNC_GPIO66 (MTK_PIN_NO(66) | 0) +#define PINMUX_GPIO66__FUNC_MIPI0_SCLK (MTK_PIN_NO(66) | 1) +#define PINMUX_GPIO66__FUNC_DBG_MON_B13 (MTK_PIN_NO(66) | 7) + +#define PINMUX_GPIO67__FUNC_GPIO67 (MTK_PIN_NO(67) | 0) +#define PINMUX_GPIO67__FUNC_RFIC0_BSI_D2 (MTK_PIN_NO(67) | 1) +#define PINMUX_GPIO67__FUNC_SPM_BSI_D2 (MTK_PIN_NO(67) | 2) +#define PINMUX_GPIO67__FUNC_DBG_MON_B14 (MTK_PIN_NO(67) | 7) + +#define PINMUX_GPIO68__FUNC_GPIO68 (MTK_PIN_NO(68) | 0) +#define PINMUX_GPIO68__FUNC_RFIC0_BSI_D1 (MTK_PIN_NO(68) | 1) +#define PINMUX_GPIO68__FUNC_SPM_BSI_D1 (MTK_PIN_NO(68) | 2) +#define PINMUX_GPIO68__FUNC_DBG_MON_B15 (MTK_PIN_NO(68) | 7) + +#define PINMUX_GPIO69__FUNC_GPIO69 (MTK_PIN_NO(69) | 0) +#define PINMUX_GPIO69__FUNC_RFIC0_BSI_D0 (MTK_PIN_NO(69) | 1) +#define PINMUX_GPIO69__FUNC_SPM_BSI_D0 (MTK_PIN_NO(69) | 2) +#define PINMUX_GPIO69__FUNC_DBG_MON_B16 (MTK_PIN_NO(69) | 7) + +#define PINMUX_GPIO70__FUNC_GPIO70 (MTK_PIN_NO(70) | 0) + +#define PINMUX_GPIO71__FUNC_GPIO71 (MTK_PIN_NO(71) | 0) + +#define PINMUX_GPIO72__FUNC_GPIO72 (MTK_PIN_NO(72) | 0) + +#define PINMUX_GPIO73__FUNC_GPIO73 (MTK_PIN_NO(73) | 0) + +#define PINMUX_GPIO74__FUNC_GPIO74 (MTK_PIN_NO(74) | 0) + +#define PINMUX_GPIO75__FUNC_GPIO75 (MTK_PIN_NO(75) | 0) +#define PINMUX_GPIO75__FUNC_MIPI3_SDATA (MTK_PIN_NO(75) | 1) +#define PINMUX_GPIO75__FUNC_PWM_C (MTK_PIN_NO(75) | 2) +#define PINMUX_GPIO75__FUNC_IRTX_OUT (MTK_PIN_NO(75) | 3) +#define PINMUX_GPIO75__FUNC_I2S0_DI (MTK_PIN_NO(75) | 4) +#define PINMUX_GPIO75__FUNC_I2S2_DI (MTK_PIN_NO(75) | 5) +#define PINMUX_GPIO75__FUNC_ANT_SEL5 (MTK_PIN_NO(75) | 6) +#define PINMUX_GPIO75__FUNC_DBG_MON_B19 (MTK_PIN_NO(75) | 7) + +#define PINMUX_GPIO76__FUNC_GPIO76 (MTK_PIN_NO(76) | 0) +#define PINMUX_GPIO76__FUNC_MIPI3_SCLK (MTK_PIN_NO(76) | 1) +#define PINMUX_GPIO76__FUNC_CLKM3 (MTK_PIN_NO(76) | 2) +#define PINMUX_GPIO76__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(76) | 3) +#define PINMUX_GPIO76__FUNC_I2S0_LRCK (MTK_PIN_NO(76) | 4) +#define PINMUX_GPIO76__FUNC_I2S2_LRCK (MTK_PIN_NO(76) | 5) +#define PINMUX_GPIO76__FUNC_ANT_SEL4 (MTK_PIN_NO(76) | 6) +#define PINMUX_GPIO76__FUNC_DBG_MON_B20 (MTK_PIN_NO(76) | 7) + +#define PINMUX_GPIO77__FUNC_GPIO77 (MTK_PIN_NO(77) | 0) +#define PINMUX_GPIO77__FUNC_MIPI2_SDATA (MTK_PIN_NO(77) | 1) +#define PINMUX_GPIO77__FUNC_USB_DRVVBUS (MTK_PIN_NO(77) | 2) +#define PINMUX_GPIO77__FUNC_IRTX_OUT (MTK_PIN_NO(77) | 3) +#define PINMUX_GPIO77__FUNC_I2S0_BCK (MTK_PIN_NO(77) | 4) +#define PINMUX_GPIO77__FUNC_I2S2_BCK (MTK_PIN_NO(77) | 5) +#define PINMUX_GPIO77__FUNC_ANT_SEL3 (MTK_PIN_NO(77) | 6) +#define PINMUX_GPIO77__FUNC_DBG_MON_B21 (MTK_PIN_NO(77) | 7) + +#define PINMUX_GPIO78__FUNC_GPIO78 (MTK_PIN_NO(78) | 0) +#define PINMUX_GPIO78__FUNC_MIPI2_SCLK (MTK_PIN_NO(78) | 1) +#define PINMUX_GPIO78__FUNC_IDDIG (MTK_PIN_NO(78) | 2) +#define PINMUX_GPIO78__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(78) | 3) +#define PINMUX_GPIO78__FUNC_I2S0_MCK (MTK_PIN_NO(78) | 4) +#define PINMUX_GPIO78__FUNC_I2S2_MCK (MTK_PIN_NO(78) | 5) +#define PINMUX_GPIO78__FUNC_PCM1_DO0 (MTK_PIN_NO(78) | 6) +#define PINMUX_GPIO78__FUNC_DBG_MON_B22 (MTK_PIN_NO(78) | 7) + +#define PINMUX_GPIO79__FUNC_GPIO79 (MTK_PIN_NO(79) | 0) +#define PINMUX_GPIO79__FUNC_BPI_BUS3 (MTK_PIN_NO(79) | 1) +#define PINMUX_GPIO79__FUNC_DBG_MON_B23 (MTK_PIN_NO(79) | 7) + +#define PINMUX_GPIO80__FUNC_GPIO80 (MTK_PIN_NO(80) | 0) +#define PINMUX_GPIO80__FUNC_BPI_BUS2 (MTK_PIN_NO(80) | 1) +#define PINMUX_GPIO80__FUNC_DBG_MON_B24 (MTK_PIN_NO(80) | 7) + +#define PINMUX_GPIO81__FUNC_GPIO81 (MTK_PIN_NO(81) | 0) +#define PINMUX_GPIO81__FUNC_BPI_BUS1 (MTK_PIN_NO(81) | 1) +#define PINMUX_GPIO81__FUNC_DBG_MON_B25 (MTK_PIN_NO(81) | 7) + +#define PINMUX_GPIO82__FUNC_GPIO82 (MTK_PIN_NO(82) | 0) +#define PINMUX_GPIO82__FUNC_BPI_BUS0 (MTK_PIN_NO(82) | 1) +#define PINMUX_GPIO82__FUNC_DBG_MON_B26 (MTK_PIN_NO(82) | 7) + +#define PINMUX_GPIO83__FUNC_GPIO83 (MTK_PIN_NO(83) | 0) +#define PINMUX_GPIO83__FUNC_BPI_BUS23 (MTK_PIN_NO(83) | 1) +#define PINMUX_GPIO83__FUNC_DET_BPI1 (MTK_PIN_NO(83) | 2) +#define PINMUX_GPIO83__FUNC_I2S3_DO (MTK_PIN_NO(83) | 4) +#define PINMUX_GPIO83__FUNC_I2S1_DO (MTK_PIN_NO(83) | 5) +#define PINMUX_GPIO83__FUNC_PCM1_DO1 (MTK_PIN_NO(83) | 6) +#define PINMUX_GPIO83__FUNC_DBG_MON_B27 (MTK_PIN_NO(83) | 7) + +#define PINMUX_GPIO84__FUNC_GPIO84 (MTK_PIN_NO(84) | 0) +#define PINMUX_GPIO84__FUNC_BPI_BUS22 (MTK_PIN_NO(84) | 1) +#define PINMUX_GPIO84__FUNC_DET_BPI0 (MTK_PIN_NO(84) | 2) +#define PINMUX_GPIO84__FUNC_I2S3_LRCK (MTK_PIN_NO(84) | 4) +#define PINMUX_GPIO84__FUNC_I2S1_LRCK (MTK_PIN_NO(84) | 5) +#define PINMUX_GPIO84__FUNC_PCM1_CLK (MTK_PIN_NO(84) | 6) +#define PINMUX_GPIO84__FUNC_DBG_MON_B28 (MTK_PIN_NO(84) | 7) + +#define PINMUX_GPIO85__FUNC_GPIO85 (MTK_PIN_NO(85) | 0) +#define PINMUX_GPIO85__FUNC_BPI_BUS21 (MTK_PIN_NO(85) | 1) +#define PINMUX_GPIO85__FUNC_TX_SWAP3 (MTK_PIN_NO(85) | 2) +#define PINMUX_GPIO85__FUNC_DBG_MON_B29 (MTK_PIN_NO(85) | 7) + +#define PINMUX_GPIO86__FUNC_GPIO86 (MTK_PIN_NO(86) | 0) +#define PINMUX_GPIO86__FUNC_BPI_BUS20 (MTK_PIN_NO(86) | 1) +#define PINMUX_GPIO86__FUNC_TX_SWAP2 (MTK_PIN_NO(86) | 2) +#define PINMUX_GPIO86__FUNC_DBG_MON_B30 (MTK_PIN_NO(86) | 7) + +#define PINMUX_GPIO87__FUNC_GPIO87 (MTK_PIN_NO(87) | 0) +#define PINMUX_GPIO87__FUNC_BPI_BUS19 (MTK_PIN_NO(87) | 1) +#define PINMUX_GPIO87__FUNC_TX_SWAP1 (MTK_PIN_NO(87) | 2) +#define PINMUX_GPIO87__FUNC_DBG_MON_B31 (MTK_PIN_NO(87) | 7) + +#define PINMUX_GPIO88__FUNC_GPIO88 (MTK_PIN_NO(88) | 0) +#define PINMUX_GPIO88__FUNC_BPI_BUS18 (MTK_PIN_NO(88) | 1) +#define PINMUX_GPIO88__FUNC_TX_SWAP0 (MTK_PIN_NO(88) | 2) + +#define PINMUX_GPIO89__FUNC_GPIO89 (MTK_PIN_NO(89) | 0) +#define PINMUX_GPIO89__FUNC_BPI_BUS17 (MTK_PIN_NO(89) | 1) +#define PINMUX_GPIO89__FUNC_PA_VM1 (MTK_PIN_NO(89) | 2) +#define PINMUX_GPIO89__FUNC_I2S3_BCK (MTK_PIN_NO(89) | 4) +#define PINMUX_GPIO89__FUNC_I2S1_BCK (MTK_PIN_NO(89) | 5) +#define PINMUX_GPIO89__FUNC_PCM1_SYNC (MTK_PIN_NO(89) | 6) + +#define PINMUX_GPIO90__FUNC_GPIO90 (MTK_PIN_NO(90) | 0) +#define PINMUX_GPIO90__FUNC_BPI_BUS16 (MTK_PIN_NO(90) | 1) +#define PINMUX_GPIO90__FUNC_PA_VM0 (MTK_PIN_NO(90) | 2) +#define PINMUX_GPIO90__FUNC_I2S3_MCK (MTK_PIN_NO(90) | 4) +#define PINMUX_GPIO90__FUNC_I2S1_MCK (MTK_PIN_NO(90) | 5) +#define PINMUX_GPIO90__FUNC_PCM1_DI (MTK_PIN_NO(90) | 6) + +#define PINMUX_GPIO91__FUNC_GPIO91 (MTK_PIN_NO(91) | 0) +#define PINMUX_GPIO91__FUNC_SDA1 (MTK_PIN_NO(91) | 1) +#define PINMUX_GPIO91__FUNC_IDDIG (MTK_PIN_NO(91) | 2) + +#define PINMUX_GPIO92__FUNC_GPIO92 (MTK_PIN_NO(92) | 0) +#define PINMUX_GPIO92__FUNC_SDA0 (MTK_PIN_NO(92) | 1) + +#define PINMUX_GPIO93__FUNC_GPIO93 (MTK_PIN_NO(93) | 0) +#define PINMUX_GPIO93__FUNC_SCL0 (MTK_PIN_NO(93) | 1) + +#define PINMUX_GPIO94__FUNC_GPIO94 (MTK_PIN_NO(94) | 0) +#define PINMUX_GPIO94__FUNC_SCL1 (MTK_PIN_NO(94) | 1) +#define PINMUX_GPIO94__FUNC_IDDIG (MTK_PIN_NO(94) | 2) + +#define PINMUX_GPIO95__FUNC_GPIO95 (MTK_PIN_NO(95) | 0) +#define PINMUX_GPIO95__FUNC_SPI0_MI (MTK_PIN_NO(95) | 1) +#define PINMUX_GPIO95__FUNC_MRG_SYNC (MTK_PIN_NO(95) | 2) +#define PINMUX_GPIO95__FUNC_PCM0_SYNC (MTK_PIN_NO(95) | 3) +#define PINMUX_GPIO95__FUNC_I2S1_BCK (MTK_PIN_NO(95) | 4) +#define PINMUX_GPIO95__FUNC_SPI0_MO (MTK_PIN_NO(95) | 5) +#define PINMUX_GPIO95__FUNC_DFD_TDO (MTK_PIN_NO(95) | 6) +#define PINMUX_GPIO95__FUNC_JTDO_SEL1 (MTK_PIN_NO(95) | 7) + +#define PINMUX_GPIO96__FUNC_GPIO96 (MTK_PIN_NO(96) | 0) +#define PINMUX_GPIO96__FUNC_SPI0_CSB (MTK_PIN_NO(96) | 1) +#define PINMUX_GPIO96__FUNC_MRG_DO (MTK_PIN_NO(96) | 2) +#define PINMUX_GPIO96__FUNC_PCM0_DO (MTK_PIN_NO(96) | 3) +#define PINMUX_GPIO96__FUNC_I2S1_LRCK (MTK_PIN_NO(96) | 4) +#define PINMUX_GPIO96__FUNC_SDA2 (MTK_PIN_NO(96) | 5) +#define PINMUX_GPIO96__FUNC_DFD_TMS (MTK_PIN_NO(96) | 6) +#define PINMUX_GPIO96__FUNC_JTMS_SEL1 (MTK_PIN_NO(96) | 7) + +#define PINMUX_GPIO97__FUNC_GPIO97 (MTK_PIN_NO(97) | 0) +#define PINMUX_GPIO97__FUNC_SPI0_MO (MTK_PIN_NO(97) | 1) +#define PINMUX_GPIO97__FUNC_MRG_CLK (MTK_PIN_NO(97) | 2) +#define PINMUX_GPIO97__FUNC_PCM0_CLK (MTK_PIN_NO(97) | 3) +#define PINMUX_GPIO97__FUNC_I2S1_DO (MTK_PIN_NO(97) | 4) +#define PINMUX_GPIO97__FUNC_SPI0_MI (MTK_PIN_NO(97) | 5) +#define PINMUX_GPIO97__FUNC_DFD_TDI (MTK_PIN_NO(97) | 6) +#define PINMUX_GPIO97__FUNC_JTDI_SEL1 (MTK_PIN_NO(97) | 7) + +#define PINMUX_GPIO98__FUNC_GPIO98 (MTK_PIN_NO(98) | 0) +#define PINMUX_GPIO98__FUNC_SPI0_CLK (MTK_PIN_NO(98) | 1) +#define PINMUX_GPIO98__FUNC_MRG_DI (MTK_PIN_NO(98) | 2) +#define PINMUX_GPIO98__FUNC_PCM0_DI (MTK_PIN_NO(98) | 3) +#define PINMUX_GPIO98__FUNC_I2S1_MCK (MTK_PIN_NO(98) | 4) +#define PINMUX_GPIO98__FUNC_SCL2 (MTK_PIN_NO(98) | 5) +#define PINMUX_GPIO98__FUNC_DFD_TCK_XI (MTK_PIN_NO(98) | 6) +#define PINMUX_GPIO98__FUNC_JTCK_SEL1 (MTK_PIN_NO(98) | 7) + +#define PINMUX_GPIO99__FUNC_GPIO99 (MTK_PIN_NO(99) | 0) +#define PINMUX_GPIO99__FUNC_SRCLKENAI0 (MTK_PIN_NO(99) | 1) +#define PINMUX_GPIO99__FUNC_UTXD1 (MTK_PIN_NO(99) | 2) +#define PINMUX_GPIO99__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(99) | 3) +#define PINMUX_GPIO99__FUNC_CLKM2 (MTK_PIN_NO(99) | 4) +#define PINMUX_GPIO99__FUNC_PCC_PPC_IO (MTK_PIN_NO(99) | 5) +#define PINMUX_GPIO99__FUNC_ANT_SEL3 (MTK_PIN_NO(99) | 6) +#define PINMUX_GPIO99__FUNC_SPI0_MI (MTK_PIN_NO(99) | 7) + +#define PINMUX_GPIO100__FUNC_GPIO100 (MTK_PIN_NO(100) | 0) +#define PINMUX_GPIO100__FUNC_PWM_A (MTK_PIN_NO(100) | 1) +#define PINMUX_GPIO100__FUNC_URXD1 (MTK_PIN_NO(100) | 2) +#define PINMUX_GPIO100__FUNC_MD_INT0 (MTK_PIN_NO(100) | 3) +#define PINMUX_GPIO100__FUNC_CLKM3 (MTK_PIN_NO(100) | 4) +#define PINMUX_GPIO100__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(100) | 5) +#define PINMUX_GPIO100__FUNC_ANT_SEL4 (MTK_PIN_NO(100) | 6) +#define PINMUX_GPIO100__FUNC_DBG_MON_A35 (MTK_PIN_NO(100) | 7) + +#define PINMUX_GPIO101__FUNC_GPIO101 (MTK_PIN_NO(101) | 0) +#define PINMUX_GPIO101__FUNC_KPROW1 (MTK_PIN_NO(101) | 1) +#define PINMUX_GPIO101__FUNC_IRTX_OUT (MTK_PIN_NO(101) | 2) +#define PINMUX_GPIO101__FUNC_C2K_UTXD1 (MTK_PIN_NO(101) | 3) +#define PINMUX_GPIO101__FUNC_C2K_UTXD0 (MTK_PIN_NO(101) | 4) +#define PINMUX_GPIO101__FUNC_C2K_DM_EINT2 (MTK_PIN_NO(101) | 5) +#define PINMUX_GPIO101__FUNC_ANT_SEL5 (MTK_PIN_NO(101) | 6) +#define PINMUX_GPIO101__FUNC_DBG_MON_A36 (MTK_PIN_NO(101) | 7) + +#define PINMUX_GPIO102__FUNC_GPIO102 (MTK_PIN_NO(102) | 0) +#define PINMUX_GPIO102__FUNC_KPROW0 (MTK_PIN_NO(102) | 1) +#define PINMUX_GPIO102__FUNC_C2K_DM_EINT3 (MTK_PIN_NO(102) | 5) +#define PINMUX_GPIO102__FUNC_DBG_MON_A37 (MTK_PIN_NO(102) | 7) + +#define PINMUX_GPIO103__FUNC_GPIO103 (MTK_PIN_NO(103) | 0) +#define PINMUX_GPIO103__FUNC_KPCOL0 (MTK_PIN_NO(103) | 1) +#define PINMUX_GPIO103__FUNC_C2K_DM_EINT0 (MTK_PIN_NO(103) | 5) + +#define PINMUX_GPIO104__FUNC_GPIO104 (MTK_PIN_NO(104) | 0) +#define PINMUX_GPIO104__FUNC_KPCOL1 (MTK_PIN_NO(104) | 1) +#define PINMUX_GPIO104__FUNC_C2K_URXD1 (MTK_PIN_NO(104) | 3) +#define PINMUX_GPIO104__FUNC_C2K_URXD0 (MTK_PIN_NO(104) | 4) +#define PINMUX_GPIO104__FUNC_C2K_DM_EINT1 (MTK_PIN_NO(104) | 5) + +#define PINMUX_GPIO105__FUNC_GPIO105 (MTK_PIN_NO(105) | 0) +#define PINMUX_GPIO105__FUNC_URXD0 (MTK_PIN_NO(105) | 1) +#define PINMUX_GPIO105__FUNC_UTXD0 (MTK_PIN_NO(105) | 2) +#define PINMUX_GPIO105__FUNC_MD_URXD0 (MTK_PIN_NO(105) | 3) +#define PINMUX_GPIO105__FUNC_MD_URXD1 (MTK_PIN_NO(105) | 4) +#define PINMUX_GPIO105__FUNC_C2K_URXD0 (MTK_PIN_NO(105) | 5) +#define PINMUX_GPIO105__FUNC_MD_URXD2 (MTK_PIN_NO(105) | 6) +#define PINMUX_GPIO105__FUNC_C2K_URXD1 (MTK_PIN_NO(105) | 7) + +#define PINMUX_GPIO106__FUNC_GPIO106 (MTK_PIN_NO(106) | 0) +#define PINMUX_GPIO106__FUNC_UTXD0 (MTK_PIN_NO(106) | 1) +#define PINMUX_GPIO106__FUNC_URXD0 (MTK_PIN_NO(106) | 2) +#define PINMUX_GPIO106__FUNC_MD_UTXD0 (MTK_PIN_NO(106) | 3) +#define PINMUX_GPIO106__FUNC_MD_UTXD1 (MTK_PIN_NO(106) | 4) +#define PINMUX_GPIO106__FUNC_C2K_UTXD0 (MTK_PIN_NO(106) | 5) +#define PINMUX_GPIO106__FUNC_MD_UTXD2 (MTK_PIN_NO(106) | 6) +#define PINMUX_GPIO106__FUNC_C2K_UTXD1 (MTK_PIN_NO(106) | 7) + +#define PINMUX_GPIO107__FUNC_GPIO107 (MTK_PIN_NO(107) | 0) +#define PINMUX_GPIO107__FUNC_UCTS0 (MTK_PIN_NO(107) | 1) +#define PINMUX_GPIO107__FUNC_I2S2_MCK (MTK_PIN_NO(107) | 2) +#define PINMUX_GPIO107__FUNC_CONN_MCU_TDO (MTK_PIN_NO(107) | 4) +#define PINMUX_GPIO107__FUNC_C2K_DM_OTDO (MTK_PIN_NO(107) | 5) +#define PINMUX_GPIO107__FUNC_IO_JTAG_TDO (MTK_PIN_NO(107) | 6) +#define PINMUX_GPIO107__FUNC_DBG_MON_A6 (MTK_PIN_NO(107) | 7) + +#define PINMUX_GPIO108__FUNC_GPIO108 (MTK_PIN_NO(108) | 0) +#define PINMUX_GPIO108__FUNC_URTS0 (MTK_PIN_NO(108) | 1) +#define PINMUX_GPIO108__FUNC_I2S2_BCK (MTK_PIN_NO(108) | 2) +#define PINMUX_GPIO108__FUNC_CONN_MCU_TMS (MTK_PIN_NO(108) | 4) +#define PINMUX_GPIO108__FUNC_C2K_DM_OTMS (MTK_PIN_NO(108) | 5) +#define PINMUX_GPIO108__FUNC_IO_JTAG_TMS (MTK_PIN_NO(108) | 6) +#define PINMUX_GPIO108__FUNC_DBG_MON_A7 (MTK_PIN_NO(108) | 7) + +#define PINMUX_GPIO109__FUNC_GPIO109 (MTK_PIN_NO(109) | 0) +#define PINMUX_GPIO109__FUNC_CMMCLK1 (MTK_PIN_NO(109) | 1) +#define PINMUX_GPIO109__FUNC_PWM_C (MTK_PIN_NO(109) | 2) +#define PINMUX_GPIO109__FUNC_MD_INT0 (MTK_PIN_NO(109) | 3) +#define PINMUX_GPIO109__FUNC_CONN_MCU_AICE_TCKC (MTK_PIN_NO(109) | 4) +#define PINMUX_GPIO109__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(109) | 5) +#define PINMUX_GPIO109__FUNC_CMFLASH (MTK_PIN_NO(109) | 6) +#define PINMUX_GPIO109__FUNC_DBG_MON_A9 (MTK_PIN_NO(109) | 7) + +#define PINMUX_GPIO110__FUNC_GPIO110 (MTK_PIN_NO(110) | 0) +#define PINMUX_GPIO110__FUNC_CLKM2 (MTK_PIN_NO(110) | 1) +#define PINMUX_GPIO110__FUNC_I2S2_LRCK (MTK_PIN_NO(110) | 2) +#define PINMUX_GPIO110__FUNC_CONN_MCU_TCK (MTK_PIN_NO(110) | 4) +#define PINMUX_GPIO110__FUNC_C2K_DM_OTCK (MTK_PIN_NO(110) | 5) +#define PINMUX_GPIO110__FUNC_IO_JTAG_TCK (MTK_PIN_NO(110) | 6) +#define PINMUX_GPIO110__FUNC_DBG_MON_A10 (MTK_PIN_NO(110) | 7) + +#define PINMUX_GPIO111__FUNC_GPIO111 (MTK_PIN_NO(111) | 0) +#define PINMUX_GPIO111__FUNC_CLKM1 (MTK_PIN_NO(111) | 1) +#define PINMUX_GPIO111__FUNC_I2S2_DI (MTK_PIN_NO(111) | 2) +#define PINMUX_GPIO111__FUNC_CONN_MCU_TDI (MTK_PIN_NO(111) | 4) +#define PINMUX_GPIO111__FUNC_C2K_DM_OTDI (MTK_PIN_NO(111) | 5) +#define PINMUX_GPIO111__FUNC_IO_JTAG_TDI (MTK_PIN_NO(111) | 6) +#define PINMUX_GPIO111__FUNC_DBG_MON_A11 (MTK_PIN_NO(111) | 7) + +#define PINMUX_GPIO112__FUNC_GPIO112 (MTK_PIN_NO(112) | 0) +#define PINMUX_GPIO112__FUNC_SCL2 (MTK_PIN_NO(112) | 1) + +#define PINMUX_GPIO113__FUNC_GPIO113 (MTK_PIN_NO(113) | 0) +#define PINMUX_GPIO113__FUNC_SDA2 (MTK_PIN_NO(113) | 1) + +#define PINMUX_GPIO114__FUNC_GPIO114 (MTK_PIN_NO(114) | 0) +#define PINMUX_GPIO114__FUNC_ANT_SEL0 (MTK_PIN_NO(114) | 1) +#define PINMUX_GPIO114__FUNC_PWM_A (MTK_PIN_NO(114) | 2) +#define PINMUX_GPIO114__FUNC_CLKM0 (MTK_PIN_NO(114) | 3) +#define PINMUX_GPIO114__FUNC_IRTX_OUT (MTK_PIN_NO(114) | 4) +#define PINMUX_GPIO114__FUNC_PCC_PPC_IO (MTK_PIN_NO(114) | 5) +#define PINMUX_GPIO114__FUNC_DBG_MON_A47 (MTK_PIN_NO(114) | 7) + +#define PINMUX_GPIO115__FUNC_GPIO115 (MTK_PIN_NO(115) | 0) +#define PINMUX_GPIO115__FUNC_ANT_SEL1 (MTK_PIN_NO(115) | 1) +#define PINMUX_GPIO115__FUNC_PWM_B (MTK_PIN_NO(115) | 2) +#define PINMUX_GPIO115__FUNC_CLKM1 (MTK_PIN_NO(115) | 3) +#define PINMUX_GPIO115__FUNC_USB_DRVVBUS (MTK_PIN_NO(115) | 4) +#define PINMUX_GPIO115__FUNC_DAP_SIB1_SWD (MTK_PIN_NO(115) | 5) +#define PINMUX_GPIO115__FUNC_DBG_MON_A48 (MTK_PIN_NO(115) | 7) + +#define PINMUX_GPIO116__FUNC_GPIO116 (MTK_PIN_NO(116) | 0) +#define PINMUX_GPIO116__FUNC_ANT_SEL2 (MTK_PIN_NO(116) | 1) +#define PINMUX_GPIO116__FUNC_PWM_C (MTK_PIN_NO(116) | 2) +#define PINMUX_GPIO116__FUNC_CLKM2 (MTK_PIN_NO(116) | 3) +#define PINMUX_GPIO116__FUNC_IDDIG (MTK_PIN_NO(116) | 4) +#define PINMUX_GPIO116__FUNC_DAP_SIB1_SWCK (MTK_PIN_NO(116) | 5) +#define PINMUX_GPIO116__FUNC_IRTX_OUT (MTK_PIN_NO(116) | 6) +#define PINMUX_GPIO116__FUNC_DBG_MON_A49 (MTK_PIN_NO(116) | 7) + +#define PINMUX_GPIO117__FUNC_GPIO117 (MTK_PIN_NO(117) | 0) +#define PINMUX_GPIO117__FUNC_F2W_DATA (MTK_PIN_NO(117) | 1) +#define PINMUX_GPIO117__FUNC_PTA_TXD (MTK_PIN_NO(117) | 2) +#define PINMUX_GPIO117__FUNC_PTA_RXD (MTK_PIN_NO(117) | 3) +#define PINMUX_GPIO117__FUNC_AUXIF_ST0 (MTK_PIN_NO(117) | 4) +#define PINMUX_GPIO117__FUNC_C2K_UTXD1 (MTK_PIN_NO(117) | 5) +#define PINMUX_GPIO117__FUNC_SDA0 (MTK_PIN_NO(117) | 6) +#define PINMUX_GPIO117__FUNC_DBG_MON_A50 (MTK_PIN_NO(117) | 7) + +#define PINMUX_GPIO118__FUNC_GPIO118 (MTK_PIN_NO(118) | 0) +#define PINMUX_GPIO118__FUNC_F2W_CK (MTK_PIN_NO(118) | 1) +#define PINMUX_GPIO118__FUNC_PTA_RXD (MTK_PIN_NO(118) | 2) +#define PINMUX_GPIO118__FUNC_PTA_TXD (MTK_PIN_NO(118) | 3) +#define PINMUX_GPIO118__FUNC_AUXIF_CLK0 (MTK_PIN_NO(118) | 4) +#define PINMUX_GPIO118__FUNC_C2K_URXD1 (MTK_PIN_NO(118) | 5) +#define PINMUX_GPIO118__FUNC_SCL0 (MTK_PIN_NO(118) | 6) +#define PINMUX_GPIO118__FUNC_DBG_MON_A51 (MTK_PIN_NO(118) | 7) + +#define PINMUX_GPIO119__FUNC_GPIO119 (MTK_PIN_NO(119) | 0) +#define PINMUX_GPIO119__FUNC_WB_RSTB (MTK_PIN_NO(119) | 1) +#define PINMUX_GPIO119__FUNC_URXD1 (MTK_PIN_NO(119) | 2) +#define PINMUX_GPIO119__FUNC_UTXD1 (MTK_PIN_NO(119) | 3) +#define PINMUX_GPIO119__FUNC_DBG_MON_A52 (MTK_PIN_NO(119) | 7) + +#define PINMUX_GPIO120__FUNC_GPIO120 (MTK_PIN_NO(120) | 0) +#define PINMUX_GPIO120__FUNC_WB_SCLK (MTK_PIN_NO(120) | 1) +#define PINMUX_GPIO120__FUNC_UTXD1 (MTK_PIN_NO(120) | 2) +#define PINMUX_GPIO120__FUNC_URXD1 (MTK_PIN_NO(120) | 3) + +#define PINMUX_GPIO121__FUNC_GPIO121 (MTK_PIN_NO(121) | 0) +#define PINMUX_GPIO121__FUNC_WB_SDATA (MTK_PIN_NO(121) | 1) +#define PINMUX_GPIO121__FUNC_AGPS_SYNC (MTK_PIN_NO(121) | 2) +#define PINMUX_GPIO121__FUNC_AUXIF_ST1 (MTK_PIN_NO(121) | 4) +#define PINMUX_GPIO121__FUNC_C2K_UTXD0 (MTK_PIN_NO(121) | 5) +#define PINMUX_GPIO121__FUNC_SDA1 (MTK_PIN_NO(121) | 6) + +#define PINMUX_GPIO122__FUNC_GPIO122 (MTK_PIN_NO(122) | 0) +#define PINMUX_GPIO122__FUNC_WB_SEN (MTK_PIN_NO(122) | 1) +#define PINMUX_GPIO122__FUNC_SRCLKENAI1 (MTK_PIN_NO(122) | 2) +#define PINMUX_GPIO122__FUNC_AUXIF_CLK1 (MTK_PIN_NO(122) | 4) +#define PINMUX_GPIO122__FUNC_C2K_URXD0 (MTK_PIN_NO(122) | 5) +#define PINMUX_GPIO122__FUNC_SCL1 (MTK_PIN_NO(122) | 6) + +#define PINMUX_GPIO123__FUNC_GPIO123 (MTK_PIN_NO(123) | 0) + +#define PINMUX_GPIO124__FUNC_GPIO124 (MTK_PIN_NO(124) | 0) + +#define PINMUX_GPIO125__FUNC_GPIO125 (MTK_PIN_NO(125) | 0) + +#define PINMUX_GPIO126__FUNC_GPIO126 (MTK_PIN_NO(126) | 0) + +#define PINMUX_GPIO127__FUNC_GPIO127 (MTK_PIN_NO(127) | 0) + +#define PINMUX_GPIO128__FUNC_GPIO128 (MTK_PIN_NO(128) | 0) + +#define PINMUX_GPIO129__FUNC_GPIO129 (MTK_PIN_NO(129) | 0) + +#define PINMUX_GPIO130__FUNC_GPIO130 (MTK_PIN_NO(130) | 0) + +#define PINMUX_GPIO131__FUNC_GPIO131 (MTK_PIN_NO(131) | 0) +#define PINMUX_GPIO131__FUNC_WB_CTRL0 (MTK_PIN_NO(131) | 1) +#define PINMUX_GPIO131__FUNC_MSDC2_DAT1 (MTK_PIN_NO(131) | 2) +#define PINMUX_GPIO131__FUNC_C2K_NTRST (MTK_PIN_NO(131) | 5) + +#define PINMUX_GPIO132__FUNC_GPIO132 (MTK_PIN_NO(132) | 0) +#define PINMUX_GPIO132__FUNC_WB_CTRL1 (MTK_PIN_NO(132) | 1) +#define PINMUX_GPIO132__FUNC_MSDC2_CMD (MTK_PIN_NO(132) | 2) +#define PINMUX_GPIO132__FUNC_C2K_TCK (MTK_PIN_NO(132) | 5) + +#define PINMUX_GPIO133__FUNC_GPIO133 (MTK_PIN_NO(133) | 0) +#define PINMUX_GPIO133__FUNC_WB_CTRL2 (MTK_PIN_NO(133) | 1) +#define PINMUX_GPIO133__FUNC_MSDC2_CLK (MTK_PIN_NO(133) | 2) +#define PINMUX_GPIO133__FUNC_C2K_TDI (MTK_PIN_NO(133) | 5) + +#define PINMUX_GPIO134__FUNC_GPIO134 (MTK_PIN_NO(134) | 0) +#define PINMUX_GPIO134__FUNC_WB_CTRL3 (MTK_PIN_NO(134) | 1) +#define PINMUX_GPIO134__FUNC_MSDC2_DAT3 (MTK_PIN_NO(134) | 2) +#define PINMUX_GPIO134__FUNC_C2K_TMS (MTK_PIN_NO(134) | 5) + +#define PINMUX_GPIO135__FUNC_GPIO135 (MTK_PIN_NO(135) | 0) +#define PINMUX_GPIO135__FUNC_WB_CTRL4 (MTK_PIN_NO(135) | 1) +#define PINMUX_GPIO135__FUNC_MSDC2_DAT0 (MTK_PIN_NO(135) | 2) +#define PINMUX_GPIO135__FUNC_C2K_TDO (MTK_PIN_NO(135) | 5) + +#define PINMUX_GPIO136__FUNC_GPIO136 (MTK_PIN_NO(136) | 0) +#define PINMUX_GPIO136__FUNC_WB_CTRL5 (MTK_PIN_NO(136) | 1) +#define PINMUX_GPIO136__FUNC_MSDC2_DAT2 (MTK_PIN_NO(136) | 2) +#define PINMUX_GPIO136__FUNC_C2K_RTCK (MTK_PIN_NO(136) | 5) + +#define PINMUX_GPIO137__FUNC_GPIO137 (MTK_PIN_NO(137) | 0) + +#define PINMUX_GPIO138__FUNC_GPIO138 (MTK_PIN_NO(138) | 0) + +#define PINMUX_GPIO139__FUNC_GPIO139 (MTK_PIN_NO(139) | 0) + +#define PINMUX_GPIO140__FUNC_GPIO140 (MTK_PIN_NO(140) | 0) + +#define PINMUX_GPIO141__FUNC_GPIO141 (MTK_PIN_NO(141) | 0) + +#define PINMUX_GPIO142__FUNC_GPIO142 (MTK_PIN_NO(142) | 0) + +#define PINMUX_GPIO143__FUNC_GPIO143 (MTK_PIN_NO(143) | 0) + +#define PINMUX_GPIO144__FUNC_GPIO144 (MTK_PIN_NO(144) | 0) + +#define PINMUX_GPIO145__FUNC_GPIO145 (MTK_PIN_NO(145) | 0) + +#define PINMUX_GPIO146__FUNC_GPIO146 (MTK_PIN_NO(146) | 0) + +#define PINMUX_GPIO147__FUNC_GPIO147 (MTK_PIN_NO(147) | 0) +#define PINMUX_GPIO147__FUNC_RTC32K_CK (MTK_PIN_NO(147) | 1) + +#define PINMUX_GPIO148__FUNC_GPIO148 (MTK_PIN_NO(148) | 0) +#define PINMUX_GPIO148__FUNC_WATCHDOG (MTK_PIN_NO(148) | 1) + +#define PINMUX_GPIO149__FUNC_GPIO149 (MTK_PIN_NO(149) | 0) +#define PINMUX_GPIO149__FUNC_AUD_CLK_MOSI (MTK_PIN_NO(149) | 1) +#define PINMUX_GPIO149__FUNC_I2S1_BCK (MTK_PIN_NO(149) | 3) + +#define PINMUX_GPIO150__FUNC_GPIO150 (MTK_PIN_NO(150) | 0) +#define PINMUX_GPIO150__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(150) | 1) +#define PINMUX_GPIO150__FUNC_AUD_DAT_MISO (MTK_PIN_NO(150) | 2) +#define PINMUX_GPIO150__FUNC_I2S1_LRCK (MTK_PIN_NO(150) | 3) + +#define PINMUX_GPIO151__FUNC_GPIO151 (MTK_PIN_NO(151) | 0) +#define PINMUX_GPIO151__FUNC_AUD_DAT_MISO (MTK_PIN_NO(151) | 1) +#define PINMUX_GPIO151__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(151) | 2) +#define PINMUX_GPIO151__FUNC_I2S1_DO (MTK_PIN_NO(151) | 3) + +#define PINMUX_GPIO152__FUNC_GPIO152 (MTK_PIN_NO(152) | 0) +#define PINMUX_GPIO152__FUNC_PWRAP_SPI0_MI (MTK_PIN_NO(152) | 1) +#define PINMUX_GPIO152__FUNC_PWRAP_SPI0_MO (MTK_PIN_NO(152) | 2) + +#define PINMUX_GPIO153__FUNC_GPIO153 (MTK_PIN_NO(153) | 0) +#define PINMUX_GPIO153__FUNC_PWRAP_SPI0_CSN (MTK_PIN_NO(153) | 1) + +#define PINMUX_GPIO154__FUNC_GPIO154 (MTK_PIN_NO(154) | 0) +#define PINMUX_GPIO154__FUNC_PWRAP_SPI0_MO (MTK_PIN_NO(154) | 1) +#define PINMUX_GPIO154__FUNC_PWRAP_SPI0_MI (MTK_PIN_NO(154) | 2) + +#define PINMUX_GPIO155__FUNC_GPIO155 (MTK_PIN_NO(155) | 0) +#define PINMUX_GPIO155__FUNC_PWRAP_SPI0_CK (MTK_PIN_NO(155) | 1) + +#define PINMUX_GPIO156__FUNC_GPIO156 (MTK_PIN_NO(156) | 0) +#define PINMUX_GPIO156__FUNC_SRCLKENA0 (MTK_PIN_NO(156) | 1) + +#define PINMUX_GPIO157__FUNC_GPIO157 (MTK_PIN_NO(157) | 0) +#define PINMUX_GPIO157__FUNC_DISP_PWM (MTK_PIN_NO(157) | 1) +#define PINMUX_GPIO157__FUNC_DBG_MON_A14 (MTK_PIN_NO(157) | 7) + +#define PINMUX_GPIO158__FUNC_GPIO158 (MTK_PIN_NO(158) | 0) +#define PINMUX_GPIO158__FUNC_LCM_RST (MTK_PIN_NO(158) | 1) +#define PINMUX_GPIO158__FUNC_DBG_MON_A16 (MTK_PIN_NO(158) | 7) + +#define PINMUX_GPIO159__FUNC_GPIO159 (MTK_PIN_NO(159) | 0) +#define PINMUX_GPIO159__FUNC_RFIC0_BSI_EN (MTK_PIN_NO(159) | 1) +#define PINMUX_GPIO159__FUNC_SPM_BSI_EN (MTK_PIN_NO(159) | 2) +#define PINMUX_GPIO159__FUNC_DBG_MON_B17 (MTK_PIN_NO(159) | 7) + +#define PINMUX_GPIO160__FUNC_GPIO160 (MTK_PIN_NO(160) | 0) +#define PINMUX_GPIO160__FUNC_RFIC0_BSI_CK (MTK_PIN_NO(160) | 1) +#define PINMUX_GPIO160__FUNC_SPM_BSI_CK (MTK_PIN_NO(160) | 2) +#define PINMUX_GPIO160__FUNC_DBG_MON_B18 (MTK_PIN_NO(160) | 7) + +#define PINMUX_GPIO161__FUNC_GPIO161 (MTK_PIN_NO(161) | 0) +#define PINMUX_GPIO161__FUNC_CMMCLK0 (MTK_PIN_NO(161) | 1) +#define PINMUX_GPIO161__FUNC_CONN_MCU_AICE_TMSC (MTK_PIN_NO(161) | 4) +#define PINMUX_GPIO161__FUNC_DBG_MON_A8 (MTK_PIN_NO(161) | 7) + +#define PINMUX_GPIO162__FUNC_GPIO162 (MTK_PIN_NO(162) | 0) + +#define PINMUX_GPIO163__FUNC_GPIO163 (MTK_PIN_NO(163) | 0) + +#define PINMUX_GPIO164__FUNC_GPIO164 (MTK_PIN_NO(164) | 0) + +#define PINMUX_GPIO165__FUNC_GPIO165 (MTK_PIN_NO(165) | 0) + +#define PINMUX_GPIO166__FUNC_GPIO166 (MTK_PIN_NO(166) | 0) + +#define PINMUX_GPIO167__FUNC_GPIO167 (MTK_PIN_NO(167) | 0) + +#define PINMUX_GPIO168__FUNC_GPIO168 (MTK_PIN_NO(168) | 0) + +#define PINMUX_GPIO169__FUNC_GPIO169 (MTK_PIN_NO(169) | 0) + +#define PINMUX_GPIO170__FUNC_GPIO170 (MTK_PIN_NO(170) | 0) + +#define PINMUX_GPIO171__FUNC_GPIO171 (MTK_PIN_NO(171) | 0) + +#define PINMUX_GPIO172__FUNC_GPIO172 (MTK_PIN_NO(172) | 0) +#define PINMUX_GPIO172__FUNC_CMCSD2 (MTK_PIN_NO(172) | 2) + +#define PINMUX_GPIO173__FUNC_GPIO173 (MTK_PIN_NO(173) | 0) +#define PINMUX_GPIO173__FUNC_CMCSD3 (MTK_PIN_NO(173) | 2) + +#define PINMUX_GPIO174__FUNC_GPIO174 (MTK_PIN_NO(174) | 0) +#define PINMUX_GPIO174__FUNC_CMCSK (MTK_PIN_NO(174) | 2) + +#define PINMUX_GPIO175__FUNC_GPIO175 (MTK_PIN_NO(175) | 0) + +#define PINMUX_GPIO176__FUNC_GPIO176 (MTK_PIN_NO(176) | 0) +#define PINMUX_GPIO176__FUNC_CMCSD0 (MTK_PIN_NO(176) | 2) + +#define PINMUX_GPIO177__FUNC_GPIO177 (MTK_PIN_NO(177) | 0) +#define PINMUX_GPIO177__FUNC_CMCSD1 (MTK_PIN_NO(177) | 2) + +#define PINMUX_GPIO178__FUNC_GPIO178 (MTK_PIN_NO(178) | 0) +#define PINMUX_GPIO178__FUNC_MSDC0_DAT0 (MTK_PIN_NO(178) | 1) +#define PINMUX_GPIO178__FUNC_DBG_MON_A0 (MTK_PIN_NO(178) | 7) + +#define PINMUX_GPIO179__FUNC_GPIO179 (MTK_PIN_NO(179) | 0) +#define PINMUX_GPIO179__FUNC_MSDC0_CLK (MTK_PIN_NO(179) | 1) +#define PINMUX_GPIO179__FUNC_DBG_MON_A1 (MTK_PIN_NO(179) | 7) + +#define PINMUX_GPIO180__FUNC_GPIO180 (MTK_PIN_NO(180) | 0) +#define PINMUX_GPIO180__FUNC_MSDC0_CMD (MTK_PIN_NO(180) | 1) +#define PINMUX_GPIO180__FUNC_DBG_MON_A2 (MTK_PIN_NO(180) | 7) + +#define PINMUX_GPIO181__FUNC_GPIO181 (MTK_PIN_NO(181) | 0) +#define PINMUX_GPIO181__FUNC_MSDC0_DAT1 (MTK_PIN_NO(181) | 1) +#define PINMUX_GPIO181__FUNC_DBG_MON_A3 (MTK_PIN_NO(181) | 7) + +#define PINMUX_GPIO182__FUNC_GPIO182 (MTK_PIN_NO(182) | 0) +#define PINMUX_GPIO182__FUNC_MSDC0_DAT5 (MTK_PIN_NO(182) | 1) +#define PINMUX_GPIO182__FUNC_DBG_MON_A4 (MTK_PIN_NO(182) | 7) + +#define PINMUX_GPIO183__FUNC_GPIO183 (MTK_PIN_NO(183) | 0) +#define PINMUX_GPIO183__FUNC_MSDC0_DAT6 (MTK_PIN_NO(183) | 1) +#define PINMUX_GPIO183__FUNC_DBG_MON_A5 (MTK_PIN_NO(183) | 7) + +#define PINMUX_GPIO184__FUNC_GPIO184 (MTK_PIN_NO(184) | 0) +#define PINMUX_GPIO184__FUNC_MSDC0_DAT4 (MTK_PIN_NO(184) | 1) +#define PINMUX_GPIO184__FUNC_DBG_MON_A59 (MTK_PIN_NO(184) | 7) + +#define PINMUX_GPIO185__FUNC_GPIO185 (MTK_PIN_NO(185) | 0) +#define PINMUX_GPIO185__FUNC_MSDC0_RSTB (MTK_PIN_NO(185) | 1) +#define PINMUX_GPIO185__FUNC_DBG_MON_A60 (MTK_PIN_NO(185) | 7) + +#define PINMUX_GPIO186__FUNC_GPIO186 (MTK_PIN_NO(186) | 0) +#define PINMUX_GPIO186__FUNC_MSDC0_DAT2 (MTK_PIN_NO(186) | 1) +#define PINMUX_GPIO186__FUNC_DBG_MON_A61 (MTK_PIN_NO(186) | 7) + +#define PINMUX_GPIO187__FUNC_GPIO187 (MTK_PIN_NO(187) | 0) +#define PINMUX_GPIO187__FUNC_MSDC0_DAT3 (MTK_PIN_NO(187) | 1) +#define PINMUX_GPIO187__FUNC_DBG_MON_A62 (MTK_PIN_NO(187) | 7) + +#define PINMUX_GPIO188__FUNC_GPIO188 (MTK_PIN_NO(188) | 0) +#define PINMUX_GPIO188__FUNC_MSDC0_DAT7 (MTK_PIN_NO(188) | 1) +#define PINMUX_GPIO188__FUNC_DBG_MON_A63 (MTK_PIN_NO(188) | 7) + +#define PINMUX_GPIO189__FUNC_GPIO189 (MTK_PIN_NO(189) | 0) +#define PINMUX_GPIO189__FUNC_MSDC0_DSL (MTK_PIN_NO(189) | 1) +#define PINMUX_GPIO189__FUNC_DBG_MON_A64 (MTK_PIN_NO(189) | 7) + +#endif/* __DTS_MT6755_PINFUNC_H */ + diff --git a/arch/arm64/boot/dts/mt6755.dtsi b/arch/arm64/boot/dts/mt6755.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..a00121408af6bac2a73dc6d4c78509e7ec4f342a --- /dev/null +++ b/arch/arm64/boot/dts/mt6755.dtsi @@ -0,0 +1,3177 @@ +/* + * Mediatek's MT6755 SoC device tree source + * + * Copyright (c) 2013 MediaTek Co., Ltd. + * http://www.mediatek.com + * + */ + +#include +#include +#include +#include +#include "mt6755-pinfunc.h" +#include +/ { + model = "MT6755"; + compatible = "mediatek,MT6755"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4b434e loglevel=8"; + }; + + /* Do not put any bus before mtk-msdc, because it should be mtk-msdc.0 for partition device node usage */ + mtk-msdc.0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + + mmc0: msdc0@11230000 { + compatible = "mediatek,mt6755-mmc"; + reg = <0x11230000 0x10000>; + interrupts = ; + clocks = <&infrasys INFRA_MSDC0>; + clock-names = "MSDC0-CLOCK"; + }; + + mmc1: msdc1@11240000 { + compatible = "mediatek,mt6755-mmc"; + reg = <0x11240000 0x10000>; + interrupts = ; + clocks = <&infrasys INFRA_MSDC1>; + clock-names = "MSDC1-CLOCK"; + }; + + mmc2: msdc2@11250000 { + compatible = "mediatek,mt6755-mmc"; + reg = <0x11250000 0x10000>; + interrupts = ; + clocks = <&infrasys INFRA_MSDC2>; + clock-names = "MSDC2-CLOCK"; + }; + + /* + mmc3: msdc3@11260000 { + compatible = "mediatek,mt6755-mmc"; + reg = <0x11260000 0x10000>; + interrupts = ; + clocks = <&infrasys INFRA_MSDC3>; + clock-names = "MSDC3-CLOCK"; + };*/ + }; + + /* ATF logger SW IRQ number 281 = 32 + 249 */ + atf_logger { + compatible = "mediatek,atf_logger"; + interrupts = ; + }; + + psci { + compatible = "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + affinity_info = <0x84000004>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@000 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x000>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1144000000>; + }; + + cpu1: cpu@001 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x001>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1144000000>; + }; + + cpu2: cpu@002 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x002>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1144000000>; + }; + + cpu3: cpu@003 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x003>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1144000000>; + }; + + cpu4: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x100>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1950000000>; + }; + + cpu5: cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x101>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1950000000>; + }; + + cpu6: cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x102>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1950000000>; + }; + + cpu7: cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x103>; + enable-method = "mt-boot"; + cpu-idle-states = <&cluster_sleep_0 &cluster_sleep_0 &cluster_sleep_0>, + <&cpu_sleep_0_0 &cpu_sleep_0_0 &cpu_sleep_0_0>; + cpu-release-addr = <0x0 0x40000200>; + clock-frequency = <1950000000>; + + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + + cluster1 { + core0 { + cpu = <&cpu4>; + }; + core1 { + cpu = <&cpu5>; + }; + core2 { + cpu = <&cpu6>; + }; + core3 { + cpu = <&cpu7>; + }; + }; + }; + + idle-states { + entry-method = "arm,psci"; + + cpu_sleep_0_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <600>; + exit-latency-us = <600>; + min-residency-us = <1200>; + }; + + cluster_sleep_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <800>; + exit-latency-us = <1000>; + min-residency-us = <2000>; + }; + }; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x20000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* reserve 256KB at DRAM start + 70MB */ + atf-reserved-memory@44600000 { + compatible = "mediatek,mt6755-atf-reserved-memory"; + no-map; + reg = <0 0x44600000 0 0x40000>; + }; + + reserve-memory-ccci_md1 { + compatible = "mediatek,reserve-memory-ccci_md1"; + no-map; + size = <0 0xa100000>; /* md_size+smem_size */ + alignment = <0 0x2000000>; + alloc-ranges = <0 0x40000000 0 0xc0000000>; + }; + + reserve-memory-ccci_share { + compatible = "mediatek,reserve-memory-ccci_share"; + no-map; + size = <0 0x600000>; /* md_size+smem_size */ + alignment = <0 0x4000000>; + alloc-ranges = <0 0x40000000 0 0xc0000000>; + }; + + consys-reserve-memory { + compatible = "mediatek,consys-reserve-memory"; + no-map; + size = <0 0x100000>; + alignment = <0 0x200000>; + alloc-ranges = <0 0x40000000 0 0x60000000>; + }; + + spm-reserve-memory { + compatible = "mediatek,spm-reserve-memory"; + no-map; + size = <0 0xe000>; /* PCM_FIRMWARE_SIZE * DYNA_LOAD_PCM_MAX = 8K * 7 */ + alignment = <0 0x10000>; + alloc-ranges = <0 0x40000000 0 0x60000000>; + }; + + ram_console-reserved-memory@44400000 { + compatible = "mediatek,ram_console"; + reg = <0 0x44400000 0 0x10000>; + }; + + preloader-reserved-memory@44800000 { + compatible = "mediatek,preloader"; + reg = <0 0x44800000 0 0x100000>; + }; + + lk-reserved-memory@46000000 { + compatible = "mediatek,lk"; + reg = <0 0x46000000 0 0x400000>; + }; + + minirdump-reserved-memory@444f0000 { + compatible = "mediatek, minirdump"; + reg = <0 0x444f0000 0 0x10000>; + }; + + pstore-reserved-memory@44410000 { + compatible = "mediatek,pstore"; + reg = <0 0x44410000 0 0xe0000>; + }; + + }; + + gic: interrupt-controller@10230000 { + compatible = "mediatek,mt6735-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x10231000 0 0x1000>, + <0 0x10232000 0 0x1000>, + <0 0x10200620 0 0x1000>; + }; + + cpuxgpt@10200000 { + compatible = "mediatek,cpuxgpt"; + reg = <0 0x10200000 0 0x1000>; + interrupts = , + , + , + , + , + , + , + ; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = , + , + , + , + , + , + , + ; + }; + + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <13000000>; + }; + + clocks { + clk_null: clk_null { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + clk26m: clk26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + }; + + clk32k: clk32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32000>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + vcore_dvfs@0011cf80 { + compatible = "mediatek,mt6755-vcorefs"; + reg = <0x0011cf80 0x80>; + eint_spm_vcorefs_end@154 { + compatible = "mediatek,spm_vcorefs_err_eint"; + interrupt-parent = <&eintc>; + interrupts = <154 IRQ_TYPE_LEVEL_HIGH>; + debounce = <154 0>; + }; + }; + + chipid@08000000 { + compatible = "mediatek,chipid"; + reg = <0x08000000 0x0004>, + <0x08000004 0x0004>, + <0x08000008 0x0004>, + <0x0800000C 0x0004>; + }; + + topckgen: topckgen@10000000 { + compatible = "mediatek,mt6755-topckgen", "mediatek,topckgen"; + reg = <0x10000000 0x1000>; + #clock-cells = <1>; + }; + + infracfg_ao@10001000 { + compatible = "mediatek,infracfg_ao"; + reg = <0x10001000 0x1000>; + interrupts = ; + }; + + scpsys: scpsys@10001000 { + compatible = "mediatek,mt6755-scpsys"; + reg = <0x10001000 0x1000>, <0x10006000 0x1000>; + #clock-cells = <1>; + }; + + infrasys: infrasys@10001000 { + compatible = "mediatek,mt6755-infrasys"; + reg = <0x10001000 0x1000>; + #clock-cells = <1>; + }; + + btcvsd@10001000 { + compatible = "mediatek,audio_bt_cvsd"; + offset =<0xf00 0x800 0xfd0 0xfd4 0xfd8>; + /*INFRA MISC, conn_bt_cvsd_mask, cvsd_mcu_read, write, packet_indicator*/ + reg=<0x10001000 0x1000>, /*AUDIO_INFRA_BASE_PHYSICAL*/ + <0x18000000 0x10000>, /*PKV_PHYSICAL_BASE*/ + <0x18080000 0x8000>; /*SRAM_BANK2*/ + interrupts = ; + }; + + mt_soc_btcvsd_rx_pcm@10001000 { + compatible = "mediatek,mt_soc_btcvsd_rx_pcm"; + }; + + mt_soc_btcvsd_tx_pcm@10001000 { + compatible = "mediatek,mt_soc_btcvsd_tx_pcm"; + }; + + iocfg_0@10002000 { + compatible = "mediatek,iocfg_0"; + reg = <0x10002000 0x1000>; + }; + + syscfg_pctl_a: syscfg_pctl_a@10002000 { + compatible = "mediatek,mt6755-pctl-a-syscfg", "syscon"; + reg = <0x10002000 0x1000>; + }; + + iocfg_1@10002200 { + compatible = "mediatek,iocfg_1"; + reg = <0x10002200 0x200>; + }; + + iocfg_2@10002400 { + compatible = "mediatek,iocfg_2"; + reg = <0x10002400 0x200>; + }; + + iocfg_3@10002600 { + compatible = "mediatek,iocfg_3"; + reg = <0x10002600 0x200>; + }; + + iocfg_4@10002800 { + compatible = "mediatek,iocfg_4"; + reg = <0x10002800 0x200>; + }; + + iocfg_5@10002a00 { + compatible = "mediatek,iocfg_5"; + reg = <0x10002a00 0x200>; + }; + + perisys: perisys@10003000 { + compatible = "mediatek,mt6755-perisys"; + reg = <0x10003000 0x1000>; + #clock-cells = <1>; + }; + + dramc@10004000 { + compatible = "mediatek,dramc"; + reg = <0x10004000 0x1000>; + interrupts = ; + }; + + pio: pinctrl@10005000 { + compatible = "mediatek,mt6755-pinctrl"; + reg = <0x10005000 0x1000>; + mediatek,pctl-regmap = <&syscfg_pctl_a>; + pins-are-numbered; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio_usage_mapping:gpio { + compatible = "mediatek,gpio_usage_mapping"; + }; + + gpio@10005000 { + compatible = "mediatek,gpio"; + reg = <0x10005000 0x1000>; + }; + + sleep: sleep@10006000 { + compatible = "mediatek,sleep"; + reg = <0x10006000 0x1000>; + interrupts = , + , + , + , + , + , + , + ; + clocks = <&infrasys INFRA_I2C3>; + clock-names = "i2c3-main"; + clock-div = <10>; + #address-cells = <1>; + #size-cells = <0>; + eint_spm_vcorefs_start@152 { + compatible = "mediatek,spm_vcorefs_start_eint"; + interrupt-parent = <&eintc>; + interrupts = <152 IRQ_TYPE_LEVEL_HIGH>; + debounce = <152 0>; + }; + + eint_spm_vcorefs_end@153 { + compatible = "mediatek,spm_vcorefs_end_eint"; + interrupt-parent = <&eintc>; + interrupts = <153 IRQ_TYPE_LEVEL_HIGH>; + debounce = <153 0>; + }; + + }; + + toprgu@10007000 { + compatible = "mediatek,toprgu"; + reg = <0x10007000 0x1000>; + interrupts = ; + }; + + apxgpt@10008000 { + compatible = "mediatek,mt6755-timer", + "mediatek,mt6577-timer"; + reg = <0x10008000 0x1000>; + interrupts = ; + clocks = <&topckgen INFRA_CLK_13M>, + <&clk32k>; + }; + + rsvd@10009000 { + compatible = "mediatek,rsvd"; + reg = <0x10009000 0x1000>; + }; + + hacc@1000a000 { + compatible = "mediatek,hacc"; + reg = <0x1000a000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_SEJ>; + clock-names = "sej-main"; + + }; + + eintc: eintc@1000b000 { + compatible = "mediatek,mt-eic"; + reg = <0x1000b000 0x1000>; + interrupts = ; + mediatek,max_hw_deb_cnt = <16>; + mediatek,builtin_eint_hw_deb = <145 8 0x90>; + mediatek,max_deint_cnt = <4>; + mediatek,deint_possible_irq = <191 192 193 194>; + #interrupt-cells = <2>; + interrupt-controller; + mediatek,max_eint_num = <160>; + mediatek,mapping_table_entry = <0>; + mediatek,debtime_setting_entry = <10>; + mediatek,debtime_setting_array = <0 128>, + <1 256>, + <2 512>, + <3 1024>, + <4 16384>, + <5 32768>, + <6 65536>, + <7 131072>, + <8 262144>, + <9 524288>; + }; + + apmixedsys: apmixedsys@1000c000 { + compatible = "mediatek,mt6755-apmixedsys", "mediatek,apmixed"; + reg = <0x1000c000 0x1000>, <0x10006000 0x1000>; + #clock-cells = <1>; + }; + + fhctl@1000cf00 { + compatible = "mediatek,fhctl"; + reg = <0x1000cf00 0x100>; + }; + + pwrap: pwrap@1000d000 { + compatible = "mediatek,pwrap"; + reg = <0x1000d000 0x1000>; + interrupts = ; + + pmic: mt6351 { + compatible = "mediatek,mt6351-pmic", + "mediatek,mt6353-pmic"; + interrupt-parent = <&eintc>; + interrupts = <150 IRQ_TYPE_LEVEL_HIGH>; + debounce = <150 1000>; + interrupt-controller; + }; + }; + + devapc_ao@1000e000 { + compatible = "mediatek,devapc_ao"; + reg = <0x1000e000 0x1000>; + }; + + ddrphy@1000f000 { + compatible = "mediatek,ddrphy"; + reg = <0x1000f000 0x1000>; + }; + + keypad: keypad@10010000 { + compatible = "mediatek,mt6755-keypad", "mediatek,kp"; + reg = <0x10010000 0x1000>; + interrupts = ; + }; + + topmisc@10011000 { + compatible = "mediatek,topmisc"; + reg = <0x10011000 0x1000>; + }; + + mdcldma:mdcldma@10014000 { + compatible = "mediatek,mdcldma"; + reg = <0x10014000 0x1e00>, /*AP_CLDMA_AO*/ + <0x10015000 0x1e00>, /*MD_CLDMA_AO*/ + <0x1021b000 0x1e00>, /*AP_CLDMA_PDN*/ + <0x1021c000 0x1e00>, /*MD_CLDMA_PDN*/ + <0x10209000 0x1000>, /*AP_CCIF_BASE*/ + <0x1020a000 0x1000>; /*MD_CCIF_BASE*/ + interrupts = , /*IRQ_CLDMA*/ + , /*IRQ_CCIF*/ + ; /*IRQ_MDWDT*/ + mediatek,md_id = <0>; + mediatek,cldma_capability = <6>; + mediatek,md_smem_size = <0x100000>; /* md share memory size */ + clocks = <&scpsys SCP_SYS_MD1>; + clock-names = "scp-sys-md1-main"; + }; + + cpu_dbgapb: cpu_dbgapb { + compatible = "mediatek,hw_dbg"; + num = <8>; + reg = <0x10810000 0x1000 + 0x10910000 0x1000 + 0x10a10000 0x1000 + 0x10b10000 0x1000 + 0x10c10000 0x1000 + 0x10d10000 0x1000 + 0x10e10000 0x1000 + 0x10f10000 0x1000>; + }; + + aes_top0@10016000 { + compatible = "mediatek,aes_top0"; + reg = <0x10016000 0x1000>; + }; + + aes_top1@10017000 { + compatible = "mediatek,aes_top1"; + reg = <0x10017000 0x1000>; + }; + + modem_temp_share@10018000 { + compatible = "mediatek,modem_temp_share"; + reg = <0x10018000 0x1000>; + }; + + scp_sram@10020000 { + compatible = "mediatek,scp_sram"; + reg = <0x10020000 0x60000>; + }; + + dbgapb_base@1011a000{ + compatible = "mediatek,dbgapb_base"; + reg = <0x1011a000 0x100>;/* MD debug register */ + }; + + lastbus@10200000 { + compatible = "mediatek,lastbus"; + reg = <0x10200000 0x1000>, + <0x10003000 0x1000>; + }; + + mcucfg@10200000 { + compatible = "mediatek,mcucfg"; + reg = <0x10200000 0x1000>; + interrupts = ; + }; + + lastpc: lastpc@10200000 { + compatible = "mediatek,lastpc-v1"; + reg = <0x10200000 0x200>; /* mcucfg base */ + }; + + infracfg@10201000 { + compatible = "mediatek,infracfg"; + reg = <0x10201000 0x1000>; + }; + + sramrom@10202000 { + compatible = "mediatek,sramrom"; + reg = <0x10202000 0x1000>; + }; + + emi@10203000 { + compatible = "mediatek,emi"; + reg = <0x10203000 0x1000>; + interrupts = ; + }; + + met_emi: met_emi@10203000 { + compatible = "mediatek,met_emi"; + reg = <0x10203000 0x1000>; + }; + + sys_cirq: sys_cirq@10204000 { + compatible = "mediatek,mt6755-sys_cirq", "mediatek,mt6735-sys_cirq"; + reg = <0x10204000 0x1000>; + interrupts = ; + mediatek,cirq_num = <168>; + mediatek,spi_start_offset = <72>; + }; + + m4u@10205000 { + cell-index = <0>; + compatible = "mediatek,m4u"; + reg = <0x10205000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_SMI_COMMON>, + <&mmsys MM_DISP0_SMI_LARB0>, + <&vdecsys VDEC0_VDEC>, + <&vdecsys VDEC1_LARB>, + <&imgsys IMG_IMAGE_LARB2_SMI>, + <&vencsys VENC_VENC>, + <&vencsys VENC_LARB>, + <&scpsys SCP_SYS_VEN>, + <&scpsys SCP_SYS_VDE>, + <&scpsys SCP_SYS_ISP>, + <&scpsys SCP_SYS_DIS>; + clock-names = "smi_common", + "m4u_disp0_smi_larb0", + "m4u_vdec0_vdec", + "m4u_vdec1_larb", + "m4u_img_image_larb2_smi", + "m4u_venc_venc", + "m4u_venc_larb", + "m4u_mtcmos_ven", + "m4u_mtcmos_vde", + "m4u_mtcmos_isp", + "m4u_mtcmos_dis"; + }; + + efusec@10206000 { + compatible = "mediatek,efusec"; + reg = <0x10206000 0x1000>; + }; + + devapc@10207000 { + compatible = "mediatek,devapc"; + reg = <0x10207000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_DEVICE_APC>; + clock-names = "devapc-main"; + }; + + bus_dbg@10208000 { + compatible = "mediatek,bus_dbg-v2"; + reg = <0x10208000 0x1000>; + interrupts = ; + }; + + ap_ccif0@10209000 { + compatible = "mediatek,ap_ccif0"; + reg = <0x10209000 0x1000>; + interrupts = ; + }; + + md_ccif0@1020a000 { + compatible = "mediatek,md_ccif0"; + reg = <0x1020a000 0x1000>; + }; + + ap_ccif1@1020b000 { + compatible = "mediatek,ap_ccif1"; + reg = <0x1020b000 0x1000>; + interrupts = ; + }; + + ap2c2k_ccif@1020b000 { + compatible = "mediatek,ap2c2k_ccif"; + reg = <0x1020b000 0x1000>, //CCIF + <0x10211000 0x300>, // MD1 PCCIF + <0x10213000 0x300>; // MD3 PCCIF + interrupts = , // C2K_CCIF + ; // C2K_WDT + cell-index = <2>; + ccif,major = <169>; + ccif,minor_base = <0>; + ccif,capability = <2>; // tx busy stop + mediatek,md_smem_size = <0x400000>; //md share memory size + clocks = <&scpsys SCP_SYS_MD2>; + clock-names = "scp-sys-md2-main"; + }; + + md_ccif1@1020c000 { + compatible = "mediatek,md_ccif1"; + reg = <0x1020c000 0x1000>; + }; + + infra_mbist@1020d000 { + compatible = "mediatek,infra_mbist"; + reg = <0x1020d000 0x1000>; + }; + + dramc_nao@1020e000 { + compatible = "mediatek,dramc_nao"; + reg = <0x1020e000 0x1000>; + }; + + met_dramc_nao: met_dramc_nao@1020e000 { + compatible = "mediatek,met_dramc_nao"; + reg = <0x1020e000 0x1000>; + }; + + trng@1020f000 { + compatible = "mediatek,trng"; + reg = <0x1020f000 0x1000>; + interrupts = ; + }; + + gcpu@10210000 { + compatible = "mediatek,gcpu"; + reg = <0x10210000 0x1000>; + interrupts = ; + }; + + md2md_md1_ccif0@10211000 { + compatible = "mediatek,md2md_md1_ccif0"; + reg = <0x10211000 0x1000>; + }; + + gce@10212000 { + compatible = "mediatek,gce"; + reg = <0x10212000 0x1000>; + interrupts = , + ; + disp_mutex_reg = <0x14014000 0x1000>; + g3d_config_base = <0x13000000 0 0xffff0000>; + mmsys_config_base = <0x14000000 1 0xffff0000>; + disp_dither_base = <0x14010000 2 0xffff0000>; + mm_na_base = <0x14020000 3 0xffff0000>; + imgsys_base = <0x15000000 4 0xffff0000>; + vdec_gcon_base = <0x16000000 5 0xffff0000>; + venc_gcon_base = <0x17000000 6 0xffff0000>; + conn_peri_base = <0x18000000 7 0xffff0000>; + topckgen_base = <0x10000000 8 0xffff0000>; + kp_base = <0x10010000 9 0xffff0000>; + scp_sram_base = <0x10020000 10 0xffff0000>; + infra_na3_base = <0x10030000 11 0xffff0000>; + infra_na4_base = <0x10040000 12 0xffff0000>; + scp_base = <0x10050000 13 0xffff0000>; + mcucfg_base = <0x10200000 14 0xffff0000>; + gcpu_base = <0x10210000 15 0xffff0000>; + usb0_base = <0x11200000 16 0xffff0000>; + usb_sif_base = <0x11210000 17 0xffff0000>; + audio_base = <0x11220000 18 0xffff0000>; + msdc0_base = <0x11230000 19 0xffff0000>; + msdc1_base = <0x11240000 20 0xffff0000>; + msdc2_base = <0x11250000 21 0xffff0000>; + msdc3_base = <0x11260000 22 0xffff0000>; + ap_dma_base = <0x11000000 23 0xffff0000>; + mdp_rdma0_sof = <0>; + mdp_rsz0_sof = <1>; + mdp_rsz1_sof = <2>; + mdp_tdshp_sof = <3>; + mdp_wdma_sof = <4>; + mdp_wrot_sof = <5>; + mdp_color_sof = <6>; + disp_ovl0_sof = <7>; + disp_ovl1_sof = <8>; + disp_rdma0_sof = <9>; + disp_rdma1_sof = <10>; + disp_wdma0_sof = <11>; + disp_color_sof = <12>; + disp_ccorr_sof = <13>; + disp_aal_sof = <14>; + disp_gamma_sof = <15>; + disp_dither_sof = <16>; + disp_wdma1_sof = <17>; + disp_pwm0_sof = <18>; + disp_2l_ovl0_sof = <19>; + disp_2l_ovl1_sof = <20>; + mdp_rdma0_frame_done = <21>; + mdp_rsz0_frame_done = <22>; + mdp_rsz1_frame_done = <23>; + mdp_tdshp_frame_done = <24>; + mdp_wdma_frame_done = <25>; + mdp_wrot_write_frame_done = <26>; + mdp_wrot_read_frame_done = <27>; + mdp_color_frame_done = <28>; + disp_ovl0_frame_done = <29>; + disp_ovl1_frame_done = <30>; + disp_rdma0_frame_done = <31>; + disp_rdma1_frame_done = <32>; + disp_wdma0_frame_done = <33>; + disp_color_frame_done = <34>; + disp_ccorr_frame_done = <35>; + disp_aal_frame_done = <36>; + disp_gamma_frame_done = <37>; + disp_dither_frame_done = <38>; + disp_dpi0_frame_done = <39>; + disp_wdma1_frame_done = <40>; + disp_dsi0_frame_done = <41>; + disp_2l_ovl0_frame_done = <42>; + disp_2l_ovl1_frame_done = <43>; + stream_done_0 = <44>; + stream_done_1 = <45>; + stream_done_2 = <46>; + stream_done_3 = <47>; + stream_done_4 = <48>; + stream_done_5 = <49>; + stream_done_6 = <50>; + stream_done_7 = <51>; + stream_done_8 = <52>; + stream_done_9 = <53>; + buf_underrun_event_0 = <54>; + buf_underrun_event_1 = <55>; + dsi0_te_event = <56>; + isp_frame_done_p2_2 = <129>; + isp_frame_done_p2_1 = <130>; + isp_frame_done_p2_0 = <131>; + isp_frame_done_p1_1 = <132>; + isp_frame_done_p1_0 = <133>; + camsv_2_pass1_done = <134>; + camsv_1_pass1_done = <135>; + seninf_cam1_2_3_fifo_full = <136>; + seninf_cam0_fifo_full = <137>; + venc_done = <257>; + jpgenc_done = <258>; + jpgdec_done = <259>; + venc_mb_done = <260>; + venc_128byte_cnt_done = <261>; + apxgpt2_count = <0x10008028>; + clocks = <&infrasys INFRA_GCE>; + clock-names = "GCE"; + max_prefetch_cnt = <4>; + prefetch_size = <160 32 32 32>; + sram_share_cnt = <1>; + sram_share_engine = <8>; + sram_share_event = <460>; + }; + + cqdma: cqdma@10212c00 { + compatible = "mediatek,mt-cqdma-v1"; + reg = <0x10212c00 0x100>, + <0x10212d00 0x100>; + interrupts = , + ; + nr_channel = <2>; + clocks = <&infrasys INFRA_GCE>; + clock-names = "cqdma"; + }; + + md2md_md2_ccif0@10213000 { + compatible = "mediatek,md2md_md2_ccif0"; + reg = <0x10213000 0x1000>; + }; + + mipi_tx0@10215000 { + compatible = "mediatek,mipi_tx0"; + reg = <0x10215000 0x1000>; + }; + + mipi_rx_ana_csi0@10217000 { + compatible = "mediatek,mipi_rx_ana_csi0"; + reg = <0x10217000 0x1000>; + }; + + mipi_rx_ana_csi1@10218000 { + compatible = "mediatek,mipi_rx_ana_csi1"; + reg = <0x10218000 0x1000>; + }; + + gcpu_rsa@1021a000 { + compatible = "mediatek,gcpu_rsa"; + reg = <0x1021a000 0x1000>; + }; + + infra_md@1021d000 { + compatible = "mediatek,infra_md"; + reg = <0x1021d000 0x1000>; + }; + + bpi_bsi_slv0@1021e000 { + compatible = "mediatek,bpi_bsi_slv0"; + reg = <0x1021e000 0x1000>; + }; + + bpi_bsi_slv1@1021f000 { + compatible = "mediatek,bpi_bsi_slv1"; + reg = <0x1021f000 0x6000>; + }; + + bpi_bsi_slv2@10225000 { + compatible = "mediatek,bpi_bsi_slv2"; + reg = <0x10225000 0x1000>; + }; + + emi_mpu@10226000 { + compatible = "mediatek,emi_mpu"; + reg = <0x10226000 0x1000>; + interrupts = ; + }; + + dvfsp@10227000 { + compatible = "mediatek,mt6755-dvfsp"; + reg = <0x10227000 0x1000>, + <0x0011c000 0xf80>; + interrupts = ; + clocks = <&infrasys INFRA_I2C3>; + clock-names = "i2c"; + }; + + met_cci400@10390000 { + compatible = "mediatek,met_cci400"; + reg = <0x10390000 0x10000>; + }; + + dbgapb@10400000 { + compatible = "mediatek,dbgapb"; + reg = <0x10400000 0xc00000>; + interrupts = ; + }; + + ap_dma@11000000 { + compatible = "mediatek,ap_dma"; + reg = <0x11000000 0x1000>; + interrupts = ; + }; + + btif_tx: btif_tx@11000780 { + compatible = "mediatek,btif_tx"; + reg = <0x11000780 0x80>; + interrupts = ; + }; + + btif_rx: btif_rx@11000800 { + compatible = "mediatek,btif_rx"; + reg = <0x11000800 0x80>; + interrupts = ; + }; + + auxadc: adc_hw@11001000 { + compatible = "mediatek,mt6755-auxadc"; + reg = <0x11001000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_AUXADC>; + clock-names = "auxadc-main"; + }; + + apuart0: apuart0@11002000 { + cell-index = <0>; + compatible = "mediatek,mt6755-uart"; + reg = <0x11002000 0x1000>, /* UART base */ + <0x11000380 0x1000>, /* DMA Tx base */ + <0x11000400 0x80>; /* DMA Rx base */ + interrupts = , /* UART IRQ */ + , /* DMA Tx IRQ */ + ; /* DMA Rx IRQ */ + + clock-frequency = <26000000>; + clock-div = <1>; + clocks = <&infrasys INFRA_UART0>, <&infrasys INFRA_AP_DMA>; + clock-names = "uart0-main", "uart-apdma"; + }; + + apuart1: apuart1@11003000 { + cell-index = <1>; + compatible = "mediatek,mt6755-uart"; + reg = <0x11003000 0x1000>, /* UART base */ + <0x11000480 0x80>, /* DMA Tx base */ + <0x11000500 0x80>; /* DMA Rx base */ + interrupts = , /* UART IRQ */ + , /* DMA Tx IRQ */ + ; /* DMA Rx IRQ */ + + clock-frequency = <26000000>; + clock-div = <1>; + clocks = <&infrasys INFRA_UART1>; + clock-names = "uart1-main"; + }; + + pwm: pwm@11006000 { + compatible = "mediatek,pwm"; + reg = <0x11006000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_PWM1>, + <&infrasys INFRA_PWM2>, + <&infrasys INFRA_PWM3>, + <&infrasys INFRA_PWM4>, + <&infrasys INFRA_PWM_HCLK>, + <&infrasys INFRA_PWM>; + clock-names = "PWM1-main", + "PWM2-main", + "PWM3-main", + "PWM4-main", + "PWM-HCLK-main", + "PWM-main"; + }; + + i2c0: i2c@11007000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c0"; + cell-index = <0>; + reg = <0x11007000 0x1000>, + <0x11000100 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C0>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c1: i2c@11008000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c1"; + cell-index = <1>; + reg = <0x11008000 0x1000>, + <0x11000180 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C1>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2: i2c@11009000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c2"; + cell-index = <2>; + reg = <0x11009000 0x1000>, + <0x11000200 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C2>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + }; + + spi0: spi@1100a000 { + compatible = "mediatek,mt6755-spi"; + cell-index = <0>; + spi-padmacro = <0>; + reg = <0x1100a000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_SPI0>; + clock-names = "main"; + clock-frequency = <109000000>; + clock-div = <1>; + }; + + therm_ctrl@1100b000 { + compatible = "mediatek,mt6755-therm_ctrl"; + reg = <0x1100b000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_THERM>, <&infrasys INFRA_AUXADC>; + clock-names = "therm-main", "therm-auxadc"; + }; + + ptp_fsm@1100b000 { + compatible = "mediatek,mt6755-ptp_fsm"; + reg = <0x1100b000 0x1000>; + interrupts = ; + clocks = <&mfgsys MFG_BG3D>, <&scpsys SCP_SYS_MFG>, <&infrasys INFRA_THERM>; + clock-names = "mfg-main", "mtcmos-mfg", "therm-eem"; + }; + + btif: btif@1100c000 { + compatible = "mediatek,btif"; + reg = <0x1100c000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_BTIF>,<&infrasys INFRA_AP_DMA>; + clock-names = "btifc","apdmac"; + }; + + apirtx:irtx@1100d000 { + compatible = "mediatek,irtx"; + reg = <0x1100d000 0x1000>; + interrupts = ; + pwm_ch = <3>; + + clock-frequency = <26000000>; + clock-div = <1>; + clocks = <&infrasys INFRA_IRTX>; + clock-names = "clk-irtx-main"; + }; + + irtx_pwm:irtx_pwm { + compatible = "mediatek,irtx-pwm"; + pwm_ch = <2>; + pwm_data_invert = <0>; + }; + + disp_pwm@1100e000 { + compatible = "mediatek,disp_pwm"; + reg = <0x1100e000 0x1000>; + }; + + i2c4: i2c@1100f000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c3"; + cell-index = <3>; + reg = <0x1100f000 0x1000>, + <0x11000280 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C3>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + + mt6311@6b { + compatible = "mediatek,ext_buck"; + reg = <0x6b>; + }; + }; + + spi1: spi@11010000 { + compatible = "mediatek,mt6755-spi"; + cell-index = <1>; + spi-padmacro = <0>; + reg = <0x11010000 0x1000>; + interrupts = ; + clocks = <&infrasys INFRA_SPI1>; + clock-names = "main"; + clock-frequency = <109000000>; + clock-div = <1>; + }; + + i2c3: i2c@11011000 { + compatible = "mediatek,mt6755-i2c", "mediatek,i2c4"; + cell-index = <4>; + reg = <0x11011000 0x1000>, + <0x11000300 0x80>; + interrupts = ; + clock-div = <10>; + clocks = <&infrasys INFRA_I2C4>, <&infrasys INFRA_AP_DMA>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + }; + + usb1p@11200000 { + compatible = "mediatek,usb1p"; + reg = <0x11200000 0x10000>; + interrupts = ; + }; + + usb1p_sif@11210000 { + compatible = "mediatek,usb1p_sif"; + reg = <0x11210000 0x10000>; + }; + + audiosys: audiosys@11220000 { + compatible = "mediatek,mt6755-audiosys"; + reg = <0x11220000 0x10000>; + #clock-cells = <1>; + }; + + audgpio: mt_soc_dl1_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1"; + reg = <0x11220000 0x1000>; + interrupts = ; + clocks = <&audiosys AUDIO_AFE>, + <&audiosys AUDIO_I2S>, + <&audiosys AUDIO_DAC>, + <&audiosys AUDIO_DAC_PREDIS>, + <&audiosys AUDIO_ADC>, + <&audiosys AUDIO_22M>, + <&audiosys AUDIO_24M>, + <&audiosys AUDIO_APLL_TUNER>, + <&audiosys AUDIO_APLL2_TUNER>, + <&audiosys AUDIO_TML>, + <&audiosys AUDIO_APLL1_DIV0>, + <&audiosys AUDIO_APLL2_DIV0>, + <&scpsys SCP_SYS_AUD>, + <&infrasys INFRA_AUDIO>, + <&infrasys INFRA_AUDIO_26M_BCLK>, + <&topckgen TOP_MUX_AUD1>, + <&topckgen TOP_MUX_AUD2>, + <&topckgen TOP_AD_APLL1_CK>, + <&topckgen TOP_AD_APLL2_CK>, + <&topckgen TOP_MUX_AUDINTBUS>, + <&topckgen TOP_SYSPLL1_D4>, + <&apmixedsys APMIXED_APLL1>, + <&apmixedsys APMIXED_APLL2>, + <&clk26m>; + clock-names = "aud_afe_clk", + "aud_i2s_clk", + "aud_dac_clk", + "aud_dac_predis_clk", + "aud_adc_clk", + "aud_apll22m_clk", + "aud_apll24m_clk", + "aud_apll1_tuner_clk", + "aud_apll2_tuner_clk", + "aud_tml_clk", + "aud_apll1_div0_clk", + "aud_apll2_div0_clk", + "scp_sys_aud", + "aud_infra_clk", + "aud_peri_26m_clk", + "aud_mux1_clk", + "aud_mux2_clk", + "top_ad_apll1_clk", + "top_ad_apll2_clk", + "top_mux_audio_int", + "top_sys_pll1_d4", + "apmixed_apll1_clk", + "apmixed_apll2_clk", + "top_clk26m_clk"; + }; + + mt_soc_ul1_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_capture"; + }; + + mt_soc_voice_md1@11220000 { + compatible = "mediatek,mt_soc_pcm_voice_md1"; + }; + + mt_soc_hdmi_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_hdmi"; + }; + + mt_soc_uldlloopback_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_uldlloopback"; + }; + + mt_soc_i2s0_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1_i2s0"; + }; + + mt_soc_mrgrx_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_mrgrx"; + }; + + mt_soc_mrgrx_awb_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_mrgrx_awb"; + }; + + mt_soc_fm_i2s_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_fm_i2s"; + }; + + mt_soc_fm_i2s_awb_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_fm_i2s_awb"; + }; + + mt_soc_i2s0dl1_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1_i2s0dl1"; + }; + + mt_soc_dl1_awb_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1_awb"; + }; + + mt_soc_voice_md1_bt@11220000 { + compatible = "mediatek,mt_soc_pcm_voice_md1_bt"; + }; + + mt_soc_voip_bt_out@11220000 { + compatible = "mediatek,mt_soc_pcm_dl1_bt"; + }; + + mt_soc_voip_bt_in@11220000 { + compatible = "mediatek,mt_soc_pcm_bt_dai"; + }; + + mt_soc_tdmrx_pcm@11220000 { + compatible = "mediatek,mt_soc_tdm_capture"; + }; + + mt_soc_fm_mrgtx_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_fmtx"; + }; + + mt_soc_ul2_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_capture2"; + }; + + mt_soc_i2s0_awb_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_i2s0_awb"; + }; + + mt_soc_voice_md2@11220000 { + compatible = "mediatek,mt_soc_pcm_voice_md2"; + }; + + mt_soc_routing_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_routing"; + i2s1clk-gpio = <7 6>; + i2s1dat-gpio = <5 6>; + i2s1mclk-gpio = <9 6>; + i2s1ws-gpio = <6 6>; + }; + + mt_soc_voice_md2_bt@11220000 { + compatible = "mediatek,mt_soc_pcm_voice_md2_bt"; + }; + + mt_soc_hp_impedance_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_hp_impedance"; + }; + + mt_soc_codec_name@11220000 { + compatible = "mediatek,mt_soc_codec_63xx"; + use_hp_depop_flow = <0>; /* select 1: use, 0: not use */ + use_ul_260k = <0>; /* select 1: use, 0: not use */ + }; + + mt_soc_dummy_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dummy"; + }; + + mt_soc_codec_dummy_name@11220000 { + compatible = "mediatek,mt_soc_codec_dummy"; + }; + + mt_soc_routing_dai_name@11220000 { + compatible = "mediatek,mt_soc_dai_routing"; + }; + + mt_soc_dai_name@11220000 { + compatible = "mediatek,mt_soc_dai_stub"; + }; + + mt_soc_offload_gdma@11220000 { + compatible = "mediatek,mt_soc_pcm_offload_gdma"; + }; + + mt_soc_dl2_pcm@11220000 { + compatible = "mediatek,mt_soc_pcm_dl2"; + }; + + icusb@11270000 { + compatible = "mediatek,icusb"; + reg = <0x11270000 0x10000>; + }; + + usb0p@11270000 { + compatible = "mediatek,usb0p"; + reg = <0x11270000 0x10000>; + interrupts = ; + }; + + usbphy0:usbphy@0 { + compatible = "usb-nop-xceiv"; + }; + + usb0:usb3@11270000 { + compatible = "mediatek,usb3"; + reg = <0x11270000 0x10000>, <0x11280000 0x10000>, <0x11290000 0x10000>; + reg-names = "ssusb_base", "ssusb_sif", "ssusb_sif2"; + interrupts = , + ; + interrupt-names = "musb-hdrc", "xhci"; + }; + + usb_c_pinctrl:usb_c_pinctrl@0 { + compatible = "mediatek,usb_c_pinctrl"; + }; + + xhci0:usb3_xhci@11270000 { + compatible = "mediatek,usb3_xhci"; + reg = <0x11270000 0x10000>, <0x11280000 0x10000>, <0x11290000 0x10000>; + reg-names = "ssusb_base", "ssusb_sif", "ssusb_sif2"; + interrupts = ; + interrupt-names = "xhci"; + eint_usb_iddig@28 { + compatible = "mediatek,usb_iddig_bi_eint"; + interrupt-parent = <&eintc>; + interrupts = <28 IRQ_TYPE_LEVEL_LOW>; + debounce = <28 0>; + }; + }; + + usb0p_sif@11280000 { + compatible = "mediatek,usb0p_sif"; + reg = <0x11280000 0x10000>; + }; + + usb3_phy { + compatible = "mediatek,usb3_phy"; + clocks = <&infrasys INFRA_SSUSB_TOP>; + clock-names = "sssub_clk"; + }; + + usb3_sif@11280000 { + compatible = "mediatek,usb3_sif"; + reg = <0x11280000 0x10000>; + }; + + usb0p_sif2@11290000 { + compatible = "mediatek,usb0p_sif2"; + reg = <0x11290000 0x10000>; + }; + + usb3_sif2@11290000 { + compatible = "mediatek,usb3_sif2"; + reg = <0x11290000 0x10000>; + }; + + mfgsys: mfgsys@13000000 { + compatible = "mediatek,mt6755-mfgsys"; + reg = <0x13000000 0x1000>; + #clock-cells = <1>; + }; + + mfgcfg@13000000 { + compatible = "mediatek,mfgcfg"; + reg = <0x13000000 0x1000>; + }; + + mfg_vad@13001000 { + compatible = "mediatek,mfg_vad"; + reg = <0x13001000 0x1000>; + }; + + mfg_dfp@13020000 { + compatible = "mediatek,mfg_dfp"; + reg = <0x13020000 0x1000>; + }; + + mali:mali@13040000 { + compatible = "arm,malit860", "arm,mali-t86x", "arm,malit8xx", "arm,mali-midgard"; + reg = <0x13040000 0x4000>; + interrupts = , + , + ; + interrupt-names = "JOB", "MMU", "GPU"; + clock-frequency = <700000000>; + clocks = <&mfgsys MFG_BG3D>, <&mmsys MM_DISP0_SMI_COMMON>, + <&scpsys SCP_SYS_MFG>, <&scpsys SCP_SYS_DIS>; + clock-names = "mfg-main", "mfg-smi-common", "mtcmos-mfg", "mtcmos-display"; + }; + + + mmsys: mmsys_config@14000000 { + compatible = "mediatek,mmsys_config", "mediatek,mt6755-mmsys"; + reg = <0x14000000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_CAM_MDP>; + clock-names = "CAM_MDP"; + #clock-cells = <1>; + }; + + mdp_rdma@14001000 { + compatible = "mediatek,mdp_rdma"; + reg = <0x14001000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_RDMA>; + clock-names = "MDP_RDMA"; + }; + + mdp_rsz0@14002000 { + compatible = "mediatek,mdp_rsz0"; + reg = <0x14002000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_RSZ0>; + clock-names = "MDP_RSZ0"; + }; + + mdp_rsz1@14003000 { + compatible = "mediatek,mdp_rsz1"; + reg = <0x14003000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_RSZ1>; + clock-names = "MDP_RSZ1"; + }; + + mdp_wdma@14004000 { + compatible = "mediatek,mdp_wdma"; + reg = <0x14004000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_WDMA>; + clock-names = "MDP_WDMA"; + }; + + mdp_wrot@14005000 { + compatible = "mediatek,mdp_wrot"; + reg = <0x14005000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_WROT>; + clock-names = "MDP_WROT"; + }; + + mdp_tdshp@14006000 { + compatible = "mediatek,mdp_tdshp"; + reg = <0x14006000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_TDSHP>; + clock-names = "MDP_TDSHP"; + }; + + mdp_color@14007000 { + compatible = "mediatek,mdp_color"; + reg = <0x14007000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_MDP_COLOR>; + clock-names = "MDP_COLOR"; + }; + + dispsys@14008000 { + compatible = "mediatek,dispsys"; + reg = <0x14000000 0x1000>, /*DISP_SYS */ + <0x14008000 0x1000>, /*DISP_OVL0 */ + <0x14009000 0x1000>, /*DISP_OVL1 */ + <0x1400A000 0x1000>, /*DISP_RDMA0 */ + <0x1400B000 0x1000>, /*DISP_RDMA1 */ + <0x1400C000 0x1000>, /*DISP_WDMA0 */ + <0x1400D000 0x1000>, /*DISP_COLOR */ + <0x1400E000 0x1000>, /*DISP_CCORR */ + <0x1400F000 0x1000>, /*DISP_AAL */ + <0x14010000 0x1000>, /*DISP_GAMMA */ + <0x14011000 0x1000>, /*DISP_DITHER */ + <0x14012000 0x1000>, /*DISP_DSI0 */ + <0x14013000 0x1000>, /*DISP_DPI0 */ + <0x1100E000 0x1000>, /*DISP_PWM */ + <0x14014000 0x1000>, /*DISP_MUTEX */ + <0x14015000 0x1000>, /*DISP_SMI_LARB0 */ + <0x14016000 0x1000>, /*DISP_SMI_COMMOM*/ + <0x14017000 0x1000>, /*DISP_WDMA1*/ + <0x14018000 0x1000>, /*DISP_OVL0_2L*/ + <0x14019000 0x1000>, /*DISP_OVL1_2L*/ + <0x10215000 0x1000>; /*MIPITX0,real chip would use this:<0x14018000 0x1000>;*/ + + + interrupts = , /*DISP_SYS */ + , /*DISP_OVL0 */ + , /*DISP_OVL1 */ + , /*DISP_RDMA0 */ + , /*DISP_RDMA1 */ + , /*DISP_WDMA0 */ + , /*DISP_COLOR */ + , /*DISP_CCORR */ + , /*DISP_AAL */ + , /*DISP_GAMMA */ + , /*DISP_DITHER */ + , /*DISP_DSI0 */ + , /*DISP_DPI0 */ + , /*DISP_PWM */ + , /*DISP_MUTEX */ + , /*DISP_SMI_LARB0 */ + , /*DISP_SMI_COMMOM*/ + , /*DISP_WDMA1 */ + , /*DISP_OVL0_2L*/ + , /*DISP_OVL1_2L*/ + ; /*MIPITX0*/ + + clocks = <&mmsys MM_DISP0_SMI_COMMON>, + <&mmsys MM_DISP0_SMI_LARB0>, + <&mmsys MM_DISP0_DISP_OVL0>, + <&mmsys MM_DISP0_DISP_OVL1>, + <&mmsys MM_DISP0_DISP_RDMA0>, + <&mmsys MM_DISP0_DISP_RDMA1>, + <&mmsys MM_DISP0_DISP_WDMA0>, + <&mmsys MM_DISP0_DISP_COLOR>, + <&mmsys MM_DISP0_DISP_CCORR>, + <&mmsys MM_DISP0_DISP_AAL>, + <&mmsys MM_DISP0_DISP_GAMMA>, + <&mmsys MM_DISP0_DISP_DITHER>, + <&mmsys MM_DISP0_DISP_UFOE_MOUT>, + <&mmsys MM_DISP0_DISP_WDMA1>, + <&mmsys MM_DISP0_DISP_2L_OVL0>, + <&mmsys MM_DISP0_DISP_2L_OVL1>, + <&mmsys MM_DISP0_DISP_OVL0_MOUT>, + <&mmsys MM_DISP1_DSI_ENGINE>, + <&mmsys MM_DISP1_DSI_DIGITAL>, + <&mmsys MM_DISP1_DPI_ENGINE>, + <&mmsys MM_DISP1_DPI_PIXEL>, + <&infrasys INFRA_DISP_PWM>, + <&scpsys SCP_SYS_DIS>, + <&topckgen TOP_MUX_DPI0>, + <&topckgen TOP_TVDPLL_D2>, + <&topckgen TOP_TVDPLL_D4>, + <&topckgen TOP_TVDPLL_D8>, + <&topckgen TOP_TVDPLL_D16>, + <&topckgen TOP_DPI_CK>, + <&topckgen TOP_MUX_DISPPWM>, + <&topckgen TOP_UNIVPLL2_D4>, + <&topckgen TOP_OSC_D2>, + <&topckgen TOP_OSC_D8>, + <&topckgen TOP_MUX_MM>, + <&topckgen TOP_VENCPLL_CK>, + <&topckgen TOP_SYSPLL2_D2>; + + clock-names = "DISP0_SMI_COMMON", + "DISP0_SMI_LARB0", + "DISP0_DISP_OVL0", + "DISP0_DISP_OVL1", + "DISP0_DISP_RDMA0", + "DISP0_DISP_RDMA1", + "DISP0_DISP_WDMA0", + "DISP0_DISP_COLOR", + "DISP0_DISP_CCORR", + "DISP0_DISP_AAL", + "DISP0_DISP_GAMMA", + "DISP0_DISP_DITHER", + "DISP0_DISP_UFOE_MOUT", + "DISP0_DISP_WDMA1", + "DISP0_DISP_2L_OVL0", + "DISP0_DISP_2L_OVL1", + "DISP0_DISP_OVL0_MOUT", + "DISP1_DSI_ENGINE", + "DISP1_DSI_DIGITAL", + "DISP1_DPI_ENGINE", + "DISP1_DPI_PIXEL", + "DISP_PWM", + "DISP_MTCMOS_CLK", + "MUX_DPI0", + "TVDPLL_D2", + "TVDPLL_D4", + "TVDPLL_D8", + "TVDPLL_D16", + "DPI_CK", + "MUX_PWM", + "UNIVPLL2_D4", + "OSC_D2", + "OSC_D8", + "MUX_MM", + "MM_VENCPLL", + "SYSPLL2_D2"; + }; + + mhl:mhl@0 { + compatible = "mediatek,extd_dev"; + }; + + disp_ovl0@14008000 { + compatible = "mediatek,disp_ovl0"; + reg = <0x14008000 0x1000>; + interrupts = ; + }; + + disp_ovl1@14009000 { + compatible = "mediatek,disp_ovl1"; + reg = <0x14009000 0x1000>; + interrupts = ; + }; + + disp_rdma0@1400a000 { + compatible = "mediatek,disp_rdma0"; + reg = <0x1400a000 0x1000>; + interrupts = ; + }; + + disp_rdma1@1400b000 { + compatible = "mediatek,disp_rdma1"; + reg = <0x1400B000 0x1000>; + interrupts = ; + }; + + disp_wdma0@1400c000 { + compatible = "mediatek,disp_wdma0"; + reg = <0x1400c000 0x1000>; + interrupts = ; + }; + + disp_color@1400d000 { + compatible = "mediatek,disp_color"; + reg = <0x1400d000 0x1000>; + interrupts = ; + }; + + disp_ccorr@1400e000 { + compatible = "mediatek,disp_ccorr"; + reg = <0x1400e000 0x1000>; + interrupts = ; + }; + + disp_aal@1400f000 { + compatible = "mediatek,disp_aal"; + reg = <0x1400f000 0x1000>; + interrupts = ; + }; + + disp_gamma@14010000 { + compatible = "mediatek,disp_gamma"; + reg = <0x14010000 0x1000>; + interrupts = ; + }; + + disp_dither@14011000 { + compatible = "mediatek,disp_dither"; + reg = <0x14011000 0x1000>; + interrupts = ; + }; + + dsi0@14012000 { + compatible = "mediatek,dsi0"; + reg = <0x14012000 0x1000>; + interrupts = ; + }; + + dpi0@14013000 { + compatible = "mediatek,dpi0"; + reg = <0x14013000 0x1000>; + interrupts = ; + }; + + mm_mutex@14014000 { + compatible = "mediatek,mm_mutex"; + reg = <0x14014000 0x1000>; + interrupts = ; + }; + + + disp_wdma1@14017000 { + compatible = "mediatek,disp_wdma1"; + reg = <0x14017000 0x1000>; + }; + + disp_ovl0_2l@14018000 { + compatible = "mediatek,disp_ovl0_2l"; + reg = <0x14018000 0x1000>; + interrupts = ; + }; + + disp_ovl1_2l@14019000 { + compatible = "mediatek,disp_ovl1_2l"; + reg = <0x14019000 0x1000>; + interrupts = ; + }; + + smi_larb0@14015000 { + compatible = "mediatek,smi_larb0"; + reg = <0x14015000 0x1000>; + interrupts = ; + }; + + met_smi: met_smi@14016000 { + compatible = "mediatek,met_smi"; + reg = <0x14016000 0x1000>, /* SMI_COMMON_EXT */ + <0x14015000 0x1000>, /* LARB 0 */ + <0x16010000 0x10000>, /* LARB 1 */ + <0x15001000 0x1000>, /* LARB 2 */ + <0x17001000 0x1000>; /* LARB 3 */ + + clocks = <&mmsys MM_DISP0_SMI_COMMON>, + <&mmsys MM_DISP0_SMI_LARB0>, + <&imgsys IMG_IMAGE_LARB2_SMI>, + <&vdecsys VDEC1_LARB>, + <&vencsys VENC_VENC>, + <&vencsys VENC_LARB>, + <&scpsys SCP_SYS_VEN>, + <&scpsys SCP_SYS_VDE>, + <&scpsys SCP_SYS_ISP>, + <&scpsys SCP_SYS_DIS>; + clock-names = "smi-common", "smi-larb0", "img-larb2", "vdec1-larb", "venc-venc", "venc-larb", + "mtcmos-ven", "mtcmos-vde", "mtcmos-isp", "mtcmos-dis"; + }; + + smi_common@14016000 { + compatible = "mediatek,smi_common"; + reg = <0x14016000 0x1000>, /* SMI_COMMON */ + <0x14015000 0x1000>, /* LARB 0 */ + <0x16010000 0x10000>, /* LARB 1 */ + <0x15001000 0x1000>, /* LARB 2 */ + <0x17001000 0x1000>; /* LARB 3 */ + clocks = <&mmsys MM_DISP0_SMI_COMMON>, + <&mmsys MM_DISP0_SMI_LARB0>, + <&imgsys IMG_IMAGE_LARB2_SMI>, + <&vdecsys VDEC1_LARB>, + <&vencsys VENC_VENC>, + <&vencsys VENC_LARB>, + <&scpsys SCP_SYS_VEN>, + <&scpsys SCP_SYS_VDE>, + <&scpsys SCP_SYS_ISP>, + <&scpsys SCP_SYS_DIS>; + clock-names = "smi-common", "smi-larb0", "img-larb2", "vdec1-larb", "venc-venc", "venc-larb", + "mtcmos-ven", "mtcmos-vde", "mtcmos-isp", "mtcmos-dis"; + }; + + imgsys: imgsys@15000000 { + compatible = "mediatek,mt6755-imgsys"; + reg = <0x15000000 0x1000>; + #clock-cells = <1>; + }; + + ispsys@15004000 { + compatible = "mediatek,ispsys"; + reg = <0x15004000 0x9000>, /*ISP_ADDR */ + <0x1500d000 0x1000>, /*INNER_ISP_ADDR */ + <0x15000000 0x10000>, /*IMGSYS_CONFIG_ADDR */ + <0x10217000 0x3000>, /*MIPI_ANA_ADDR */ + <0x10002000 0x1000>; /*GPIO_ADDR */ + + interrupts = , /* CAM0 */ + , /* CAM1 */ + , /* CAM2 */ + , /* CAMSV0 */ + ; /* CAMSV1 */ + + clocks = <&scpsys SCP_SYS_DIS>, + <&scpsys SCP_SYS_ISP>, + <&mmsys MM_DISP0_SMI_COMMON>, + <&imgsys IMG_IMAGE_CAM_SMI>, + <&imgsys IMG_IMAGE_CAM_CAM>, + <&imgsys IMG_IMAGE_SEN_TG>, + <&imgsys IMG_IMAGE_SEN_CAM>, + <&imgsys IMG_IMAGE_CAM_SV>, + <&imgsys IMG_IMAGE_LARB2_SMI>; + + clock-names = "CG_SCP_SYS_DIS", + "CG_SCP_SYS_ISP", + "CG_DISP0_SMI_COMMON", + "CG_IMAGE_CAM_SMI", + "CG_IMAGE_CAM_CAM", + "CG_IMAGE_SEN_TG", + "CG_IMAGE_SEN_CAM", + "CG_IMAGE_CAM_SV", + "CG_IMAGE_LARB2_SMI"; + }; + + smi_larb2@15001000 { + compatible = "mediatek,smi_larb2"; + reg = <0x15001000 0x1000>; + interrupts = ; + }; + + cam0@15004000 { + compatible = "mediatek,cam0"; + reg = <0x15004000 0x1000>; + }; + + cam1@15005000 { + compatible = "mediatek,cam1"; + reg = <0x15005000 0x1000>; + interrupts = ; + }; + + cam2@15006000 { + compatible = "mediatek,cam2"; + reg = <0x15006000 0x1000>; + interrupts = ; + }; + + cam3@15007000 { + compatible = "mediatek,cam3"; + reg = <0x15007000 0x1000>; + interrupts = ; + }; + + kd_camera_hw1:kd_camera_hw1@15008000 { + compatible = "mediatek,camera_hw"; + reg = <0x15008000 0x1000>; /* SENINF_ADDR */ + + /* Camera Common Clock Framework (CCF) */ + clocks = <&topckgen TOP_MUX_CAMTG>, + <&topckgen TOP_MUX_SCAM>, + <&topckgen TOP_UNIVPLL_D26>, + <&topckgen TOP_UNIVPLL2_D2>; + clock-names = "TOP_CAMTG_SEL","TOP_MUX_SCAM","TOP_UNIVPLL_D26","TOP_UNIVPLL2_D2"; + vcama-supply = <&mt_pmic_vcama_ldo_reg>; + vcamd-supply = <&mt_pmic_vcamd_ldo_reg>; + vcamio-supply = <&mt_pmic_vcamio_ldo_reg>; + }; + + kd_camera_hw2:kd_camera_hw2@15008000 { + compatible = "mediatek,camera_hw2"; + reg = <0x15008000 0x1000>; /* SENINF_ADDR */ + }; + + seninf@15008000 { + compatible = "mediatek,seninf"; + reg = <0x15008000 0x1000>; + interrupts = ; + }; + + camsv@15009000 { + compatible = "mediatek,camsv"; + reg = <0x15009000 0x1000>; + interrupts = ; + }; + + fdvt@1500b000 { + compatible = "mediatek,fdvt"; + reg = <0x1500b000 0x1000>; + interrupts = ; + clocks = <&scpsys SCP_SYS_DIS>, + <&scpsys SCP_SYS_ISP>, + <&mmsys MM_DISP0_SMI_COMMON>, + <&imgsys IMG_IMAGE_FD>; + clock-names = "FD-SCP_SYS_DIS", + "FD-SCP_SYS_ISP", + "FD-MM_DISP0_SMI_COMMON", + "FD-IMG_IMAGE_FD"; + }; + + mipi_rx@1500c000 { + compatible = "mediatek,mipi_rx"; + reg = <0x1500c000 0x1000>; + }; + + cam0_inner@1500d000 { + compatible = "mediatek,cam0_inner"; + reg = <0x1500d000 0x1000>; + }; + + cam2_inner@1500e000 { + compatible = "mediatek,cam2_inner"; + reg = <0x1500e000 0x1000>; + }; + + cam3_inner@1500f000 { + compatible = "mediatek,cam3_inner"; + reg = <0x1500f000 0x1000>; + }; + + vdecsys: vdec_gcon@16000000 { + compatible = "mediatek,mt6755-vdec_gcon", "mediatek,mt6755-vdecsys"; + reg = <0x16000000 0x1000>; + interrupts = ; + clocks = <&mmsys MM_DISP0_SMI_COMMON>, <&vdecsys VDEC0_VDEC>, + <&vdecsys VDEC1_LARB>, <&vencsys VENC_VENC>, + <&vencsys VENC_LARB>, <&topckgen TOP_MUX_VDEC>, + <&topckgen TOP_SYSPLL1_D2>, <&topckgen TOP_SYSPLL1_D4>, + <&scpsys SCP_SYS_VDE>, <&scpsys SCP_SYS_VEN>, <&scpsys SCP_SYS_DIS>; + clock-names = "MT_CG_DISP0_SMI_COMMON", "MT_CG_VDEC0_VDEC", + "MT_CG_VDEC1_LARB", "MT_CG_VENC_VENC", + "MT_CG_VENC_LARB", "MT_CG_TOP_MUX_VDEC", + "MT_CG_TOP_SYSPLL1_D2", "MT_CG_TOP_SYSPLL1_D4", + "MT_SCP_SYS_VDE", "MT_SCP_SYS_VEN", "MT_SCP_SYS_DIS"; + #clock-cells = <1>; + }; + + smi_larb1@16010000 { + compatible = "mediatek,smi_larb1"; + reg = <0x16010000 0x10000>; + interrupts = ; + }; + + vdec_full_top: vdec_full_top@16020000 { + compatible = "mediatek,mt6755-vdec_full_top"; + reg = <0x16020000 0x10000>; + interrupts = ; + }; + + vencsys: venc_gcon@17000000 { + compatible = "mediatek,mt6755-venc_gcon", "mediatek,mt6755-vencsys"; + reg = <0x17000000 0x1000>; + interrupts = ; + #clock-cells = <1>; + }; + + smi_larb3@17001000 { + compatible = "mediatek,smi_larb3"; + reg = <0x17001000 0x1000>; + interrupts = ; + }; + + venc: venc@17002000 { + compatible = "mediatek,mt6755-venc"; + reg = <0x17002000 0x1000>; + interrupts = ; + }; + + jpgenc@17003000 { + compatible = "mediatek,jpgenc"; + reg = <0x17003000 0x1000>; + interrupts = ; + clocks = <&scpsys SCP_SYS_DIS>, + <&mmsys MM_DISP0_SMI_COMMON>, + <&scpsys SCP_SYS_VEN>, + <&vencsys VENC_LARB>, + <&vencsys VENC_JPGENC>; + + clock-names = "disp-mtcmos", + "disp-smi", + "venc-mtcmos", + "venc-larb", + "venc-jpgenc"; + }; + + jpgdec@17004000 { + compatible = "mediatek,jpgdec"; + reg = <0x17004000 0x1000>; + interrupts = ; + clocks = <&scpsys SCP_SYS_DIS>, + <&mmsys MM_DISP0_SMI_COMMON>, + <&scpsys SCP_SYS_VEN>, + <&vencsys VENC_LARB>, + <&vencsys VENC_JPGDEC>; + + clock-names = "disp-mtcmos", + "disp-smi", + "venc-mtcmos", + "venc-larb", + "venc-jpgdec"; + }; + + consys:consys@18070000 { + compatible = "mediatek,mt6755-consys"; + reg = <0x18070000 0x0200>, /*CONN_MCU_CONFIG_BASE */ + <0x10007000 0x0100>, /*AP_RGU_BASE */ + <0x10000000 0x2000>, /*TOPCKGEN_BASE */ + <0x10006000 0x1000>; /*SPM_BASE */ + interrupts = , /*BGF_EINT */ + ; /*WDT_EINT */ + clocks = <&scpsys SCP_SYS_CONN>; + clock-names = "conn"; + /* vcn18-supply = <&mt_pmic_vcn18_ldo_reg>; + vcn28-supply = <&mt_pmic_vcn28_ldo_reg>; + vcn33_bt-supply = <&mt_pmic_vcn33_bt_ldo_reg>; + vcn33_wifi-supply = <&mt_pmic_vcn33_wifi_ldo_reg>; */ + }; + + wifi@180f0000 { + compatible = "mediatek,wifi"; + reg = <0x180f0000 0x005c>; + interrupts = ; + clocks = <&infrasys INFRA_AP_DMA>; + clock-names = "wifi-dma"; + }; + + ccci_off@0 { + compatible = "mediatek,ccci_off"; + clocks = <&scpsys SCP_SYS_MD1>; + clock-names = "scp-sys-md1-main"; + }; + + ccci_util_cfg { + compatible = "mediatek,ccci_util_cfg"; + mediatek,md1-smem-size = <0x200000>; + mediatek,md3-smem-size = <0x200000>; + mediatek,md1md3-smem-size = <0x200000>; + mediatek,version = <0x1>; + }; + + nfc:nfcC@0 { + compatible = "mediatek,nfc-gpio-v2"; + gpio-ven = <88>; + gpio-rst = <87>; + gpio-eint = <82>; + gpio-irq = <86>; + }; + + gps { + compatible = "mediatek,gps"; + }; + + accdet: accdet@ { + compatible = "mediatek,mt6755-accdet"; + }; + + bat_notify { + compatible = "mediatek,bat_notify"; + }; + + battery { + compatible = "mediatek,battery"; + }; + + flashlight: flashlight { + compatible = "mediatek,mt6755-flashlight"; + }; + + bat_metter { + compatible = "mediatek,bat_meter"; + /* cust_charging.h */ + /* stop charging while in talking mode */ + stop_charging_in_takling = <1 >; + talking_recharge_voltage = <3800 >; + talking_sync_time = <60 >; + + /* Battery Temperature Protection */ + mtk_temperature_recharge_support = <1 >; + max_charge_temperature = <50 >; + max_charge_temperature_minus_x_degree = <47 >; + min_charge_temperature = <0 >; + min_charge_temperature_plus_x_degree = <6 >; + err_charge_temperature = <0xff >; + + /* Linear Charging Threshold */ + v_pre2cc_thres = <3400 >; /* unit: mV */ + v_cc2topoff_thres = <4050 >; + recharging_voltage = <4110 >; + charging_full_current = <100 >; /* unit: mA */ + + /* Charging Current Setting */ + config_usb_if = <0 >; + usb_charger_current_suspend = <0 >; /* Unit: 0.01 mA */ + usb_charger_current_unconfigured = <7000 >; /* Unit: 0.01 mA */ + usb_charger_current_configured = <50000 >; /* Unit: 0.01 mA */ + usb_charger_current = <50000 >; /* Unit: 0.01 mA */ + ac_charger_current = <80000 >; /* Unit: 0.01 mA */ + non_std_ac_charger_current = <50000 >; /* Unit: 0.01 mA */ + charging_host_charger_current = <65000 >; /* Unit: 0.01 mA */ + apple_0_5a_charger_current = <50000 >; /* Unit: 0.01 mA */ + apple_1_0a_charger_current = <65000 >; /* Unit: 0.01 mA */ + apple_2_1a_charger_current = <80000 >; /* Unit: 0.01 mA */ + + + /* charger error check */ + bat_low_temp_protect_enable = <0 >; + v_charger_enable = <0 >; /* 1:on , 0:off */ + v_charger_max = <6500 >; /* unit: mV */ + v_charger_min = <4400 >; + + /* Tracking TIME */ + onehundred_percent_tracking_time = <10 >; /* Unit: second */ + npercent_tracking_time = <20 >; /* Unit: second */ + sync_to_real_tracking_time = <60 >; /* Unit: second */ + v_0percent_tracking = <3450 >; /* Unit: mV */ + + /* High battery support */ + high_battery_voltage_support = <0 >; + + /* cust_battery_meter.h */ + /* ADC resistor */ + r_bat_sense = <4 >; + r_i_sense = <4 >; + r_charger_1 = <330 >; + r_charger_2 = <39 >; + temperature_t0 = <110 >; + temperature_t1 = <0 >; + temperature_t2 = <25 >; + temperature_t3 = <50 >; + temperature_t = <255 >; /* this should be fixed, never change the value */ + fg_meter_resistance = <0 >; + + /* Qmax for 0mA */ + q_max_pos_50 = <2743 >; + q_max_pos_25 = <2707 >; + q_max_pos_0 = <840 >; + q_max_neg_10 = <807 >; + /* Qmax for 400mA, said high current */ + q_max_pos_50_h_current = <2688 >; + q_max_pos_25_h_current = <2653 >; + q_max_pos_0_h_current = <823 >; + q_max_neg_10_h_current = <791 >; + /* Discharge percentage, 1: D5, 0: D2 */ + oam_d5 = <1 >; + + change_tracking_point = <1 >; + /* SW OCV tracking setting */ + cust_tracking_point = <0 >; + cust_r_sense = <56 >; + cust_hw_cc = <0 >; + aging_tuning_value = <103 >; + cust_r_fg_offset = <0 >; + ocv_board_compesate = <0 >; + r_fg_board_base = <1000 >; + r_fg_board_slope = <1000 >; + car_tune_value = <118 >; + + /* HW Fuel gague */ + current_detect_r_fg = <10 >; /* Unit: mA */ + minerroroffset = <1000 >; + fg_vbat_average_size = <18 >; + r_fg_value = <10 >; /* Unit: mOhm */ + + /* HW Fuel gague 2.0*/ + difference_hwocv_rtc = <30 >; + difference_hwocv_swocv = <10>; + difference_swocv_rtc = <10>; + max_swocv = <3>; + + difference_voltage_update = <20>; + aging1_load_soc = <70>; + aging1_update_soc = <30>; + batterypseudo100 = <95>; + batterypseudo1 = <11>; + + q_max_by_sys = <1>; /*8. qmax variant by system drop voltage.*/ + q_max_sys_voltage = <3350>; + shutdown_gauge0 = <1>; + shutdown_gauge1_xmins = <1>; + shutdown_gauge1_mins = <60>; + + shutdown_system_voltage = <3400>; + charge_tracking_time = <60>; + discharge_tracking_time = <10>; + + recharge_tolerance = <10>; + + sync_ui_soc_imm =<0>; + mtk_enable_aging_algorithm = <1>; + md_sleep_current_check = <1>; + q_max_by_current = <0>; + + /* HW Fuel gague 1.0*/ + cust_poweron_delta_capacity_tolrance = <40 >; + cust_poweron_low_capacity_tolrance = <5 >; + cust_poweron_max_vbat_tolrance = <90 >; + cust_poweron_delta_vbat_tolrance = <30 >; + cust_poweron_delta_hw_sw_ocv_capacity_tolrance = <10 >; + + /* Fixed battery temperature */ + fixed_tbat_25 = <0 >; + /* Dynamic change wake up period of battery thread when suspend */ + vbat_normal_wakeup = <3600 >; /* Unit: mV */ + vbat_low_power_wakeup = <3500 >; /* Unit: mV */ + normal_wakeup_period = <5400 >; /* Unit: second */ + low_power_wakeup_period = <300 >; /* Unit: second */ + close_poweroff_wakeup_period = <30 >; /* Unit: second */ + + rbat_pull_up_r = <24000 >; + rbat_pull_up_volt = <1800 >; + + + batt_temperature_table_num = <17 >; + batt_temperature_table = < + (-20) 68237 + (-15) 53650 + (-10) 42506 + (-5) 33892 + 0 27219 + 5 22021 + 10 17926 + 15 14674 + 20 12081 + 25 10000 30 8315 35 6948 40 5834 45 4917 50 4161 55 3535 60 3014 >; + battery_profile_t0_num = <82 >; + battery_profile_t0 = <0 4303 + 6 4281 + 13 4261 + 18 4240 + 25 4217 + 31 4194 + 38 4169 + 44 4145 + 51 4117 + 56 4088 + 62 4068 + 69 4047 + 75 4019 + 82 3997 + 87 3981 + 94 3967 + 100 3956 + 107 3942 + 113 3929 + 118 3913 + 125 3895 + 128 3880 + 135 3869 + 141 3857 + 147 3848 + 154 3839 + 159 3830 + 166 3823 + 172 3818 + 179 3811 + 185 3806 + 192 3800 + 197 3796 + 203 3791 + 210 3787 + 216 3781 + 223 3775 + 228 3770 + 235 3760 + 241 3752 + 248 3742 + 254 3731 + 259 3721 + 266 3713 + 272 3704 + 279 3698 + 285 3688 + 292 3665 + 297 3613 + 304 3526 + 307 3466 + 310 3444 + 313 3424 + 313 3404>; + battery_profile_t1_num = <82 >; + battery_profile_t1 = <0 4316 + 7 4283 + 12 4244 + 20 4210 + 22 4185 + 29 4164 + 34 4144 + 41 4128 + 49 4109 + 54 4093 + 61 4080 + 63 4069 + 71 4047 + 78 4023 + 83 4003 + 90 3989 + 95 3977 + 100 3967 + 105 3955 + 112 3940 + 120 3923 + 124 3907 + 132 3891 + 139 3877 + 141 3864 + 149 3855 + 154 3846 + 161 3837 + 166 3831 + 173 3823 + 181 3815 + 183 3811 + 190 3804 + 195 3799 + 202 3794 + 210 3790 + 215 3785 + 222 3782 + 224 3778 + 232 3773 + 237 3768 + 244 3761 + 251 3753 + 256 3742 + 261 3727 + 266 3712 + 273 3704 + 278 3701 + 285 3698 + 293 3692 + 298 3680 + 302 3625 + 307 3528 + 315 3472 + 322 3403 + 324 3323 + 324 3267 + 324 3230 + 327 3203 + 327 3180 + 327 3157 + 327 3141 + 327 3124 + 327 3109 + 327 3096 + 327 3084 + 327 3079 + 327 3067 + 327 3058 + 327 3047 + 327 3041 + 327 3032 + 327 3029 + 327 3018 + 327 3008 + 327 3002 + 327 3003 + 327 2995 + 327 2985 + 327 2983 + 327 2979 + 327 2967>; + battery_profile_t2_num = <82 >; + battery_profile_t2 = <0 4328 + 2 4303 + 4 4283 + 5 4263 + 7 4245 + 9 4227 + 11 4209 + 13 4189 + 14 4173 + 16 4155 + 19 4138 + 21 4121 + 22 4104 + 24 4087 + 26 4072 + 28 4058 + 30 4041 + 31 4025 + 33 4011 + 35 3996 + 37 3983 + 39 3972 + 40 3958 + 42 3945 + 44 3926 + 46 3907 + 48 3889 + 49 3876 + 52 3865 + 54 3854 + 56 3846 + 57 3840 + 59 3832 + 61 3824 + 63 3818 + 65 3813 + 66 3805 + 68 3801 + 70 3794 + 72 3789 + 74 3784 + 75 3778 + 77 3772 + 79 3765 + 81 3753 + 84 3745 + 85 3733 + 87 3717 + 89 3699 + 91 3692 + 92 3691 + 94 3689 + 96 3687 + 98 3668 + 100 3597 + 101 3497 + 103 3391 + 104 3157 + 105 3073 + 105 3022 + 105 2992 + 105 2969 + 105 2958 + 105 2946 + 105 2934 + 105 2925 + 105 2913 + 105 2910 + 105 2900 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891 + 105 2891>; + battery_profile_t3_num = <82 >; + battery_profile_t3 = <0 4331 + 2 4305 + 3 4284 + 5 4265 + 7 4244 + 10 4225 + 11 4206 + 13 4188 + 15 4170 + 16 4153 + 18 4135 + 20 4119 + 22 4102 + 23 4085 + 26 4069 + 28 4054 + 29 4038 + 31 4023 + 33 4010 + 35 3996 + 36 3984 + 38 3970 + 40 3958 + 41 3947 + 44 3934 + 46 3921 + 47 3904 + 49 3884 + 51 3868 + 53 3857 + 54 3848 + 56 3838 + 59 3832 + 60 3824 + 62 3817 + 64 3811 + 66 3806 + 67 3800 + 69 3794 + 71 3790 + 72 3784 + 74 3777 + 77 3763 + 79 3758 + 80 3750 + 82 3742 + 84 3733 + 85 3723 + 87 3709 + 89 3694 + 91 3678 + 93 3676 + 95 3675 + 97 3674 + 98 3669 + 100 3625 + 102 3547 + 104 3495 + 105 3458 + 107 3331 + 109 3140 + 109 3078 + 109 3033 + 109 3001 + 109 2980 + 110 2960 + 110 2944 + 110 2932 + 110 2921 + 110 2913 + 110 2903 + 110 2899 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889 + 110 2889>; + + r_profile_t0_num = <82 >; + r_profile_t0 = <408 4303 + 408 4281 + 415 4261 + 425 4240 + 430 4217 + 440 4194 + 463 4169 + 490 4145 + 525 4117 + 573 4088 + 615 4068 + 650 4047 + 675 4019 + 685 3997 + 705 3981 + 713 3967 + 720 3956 + 733 3942 + 728 3929 + 738 3913 + 725 3895 + 735 3880 + 745 3869 + 748 3857 + 760 3848 + 773 3839 + 783 3830 + 803 3823 + 820 3818 + 835 3811 + 863 3806 + 888 3800 + 903 3796 + 925 3791 + 955 3787 + 975 3781 + 1000 3775 + 1035 3770 + 1058 3760 + 1090 3752 + 1105 3742 + 1135 3731 + 1168 3721 + 1210 3713 + 1255 3704 + 1345 3698 + 1430 3688 + 1518 3665 + 1570 3613 + 1618 3526 + 1668 3466 + 1613 3444 + 1563 3424 + 1510 3404 + 1460 3381 + 1400 3357 + 1333 3332 + 1283 3310 + 1233 3291 + 1198 3274 + 1155 3259 + 1128 3245 + 1093 3234 + 1075 3221 + 1053 3212 + 1023 3204 + 1018 3193 + 1005 3186 + 978 3179 + 960 3168 + 940 3162 + 895 3157 + 890 3151 + 863 3143 + 925 3133 + 893 3125 + 893 3125 + 893 3125 + 893 3125 + 893 3125 + 893 3125 + 893 3125>; + r_profile_t1_num = <82 >; + r_profile_t1 = <258 4316 + 258 4283 + 278 4244 + 303 4210 + 333 4185 + 343 4164 + 350 4144 + 365 4128 + 370 4109 + 370 4093 + 380 4080 + 403 4069 + 395 4047 + 403 4023 + 403 4003 + 413 3989 + 418 3977 + 420 3967 + 423 3955 + 415 3940 + 410 3923 + 400 3907 + 393 3891 + 393 3877 + 388 3864 + 395 3855 + 403 3846 + 405 3837 + 415 3831 + 425 3823 + 430 3815 + 443 3811 + 450 3804 + 465 3799 + 475 3794 + 483 3790 + 490 3785 + 503 3782 + 520 3778 + 533 3773 + 545 3768 + 563 3761 + 588 3753 + 600 3742 + 608 3727 + 615 3712 + 635 3704 + 670 3701 + 710 3698 + 765 3692 + 840 3680 + 880 3625 + 915 3528 + 1080 3472 + 1323 3403 + 1315 3323 + 1180 3267 + 1080 3230 + 1010 3203 + 958 3180 + 925 3157 + 888 3141 + 860 3124 + 810 3109 + 788 3096 + 765 3084 + 700 3079 + 745 3067 + 680 3058 + 685 3047 + 650 3041 + 683 3032 + 615 3029 + 643 3018 + 660 3008 + 635 3002 + 530 3003 + 640 2995 + 595 2985 + 535 2983 + 463 2979 + 600 2967>; + r_profile_t2_num = <82 >; + r_profile_t2 = <155 4328 + 155 4303 + 155 4283 + 158 4263 + 158 4245 + 163 4227 + 165 4209 + 165 4189 + 170 4173 + 170 4155 + 173 4138 + 173 4121 + 173 4104 + 178 4087 + 180 4072 + 185 4058 + 188 4041 + 190 4025 + 200 4011 + 200 3996 + 205 3983 + 218 3972 + 215 3958 + 215 3945 + 200 3926 + 188 3907 + 173 3889 + 168 3876 + 163 3865 + 160 3854 + 163 3846 + 168 3840 + 170 3832 + 170 3824 + 170 3818 + 178 3813 + 175 3805 + 183 3801 + 180 3794 + 183 3789 + 185 3784 + 183 3778 + 185 3772 + 183 3765 + 173 3753 + 173 3745 + 173 3733 + 173 3717 + 173 3699 + 170 3692 + 175 3691 + 185 3689 + 198 3687 + 205 3668 + 208 3597 + 240 3497 + 273 3391 + 908 3157 + 705 3073 + 595 3022 + 513 2992 + 465 2969 + 413 2958 + 380 2946 + 368 2934 + 360 2925 + 335 2913 + 275 2910 + 315 2900 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891 + 283 2891>; + r_profile_t3_num = <82 >; + r_profile_t3 = <123 4331 + 123 4305 + 128 4284 + 130 4265 + 130 4244 + 130 4225 + 128 4206 + 125 4188 + 130 4170 + 133 4153 + 133 4135 + 138 4119 + 138 4102 + 140 4085 + 140 4069 + 143 4054 + 140 4038 + 143 4023 + 148 4010 + 153 3996 + 155 3984 + 155 3970 + 165 3958 + 175 3947 + 175 3934 + 178 3921 + 170 3904 + 148 3884 + 135 3868 + 135 3857 + 133 3848 + 133 3838 + 135 3832 + 135 3824 + 135 3817 + 143 3811 + 145 3806 + 148 3800 + 145 3794 + 153 3790 + 150 3784 + 150 3777 + 133 3763 + 143 3758 + 140 3750 + 138 3742 + 135 3733 + 135 3723 + 133 3709 + 133 3694 + 130 3678 + 130 3676 + 138 3675 + 148 3674 + 160 3669 + 158 3625 + 170 3547 + 208 3495 + 220 3458 + 265 3331 + 855 3140 + 725 3078 + 600 3033 + 528 3001 + 460 2980 + 400 2960 + 380 2944 + 355 2932 + 315 2921 + 303 2913 + 308 2903 + 255 2899 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889 + 273 2889>; + }; + + mt3326-gps@ffffffff { + compatible = "mediatek,mt3326-gps"; + }; + + gsensor@0 { + compatible = "mediatek,gsensor"; + /* vgsensor-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + alsps:als_ps@0 { + compatible = "mediatek,als_ps"; + /* valsps-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + gyroscope:gyroscope@0 { + compatible = "mediatek,gyroscope"; + /* vgyro-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + barometer@0 { + compatible = "mediatek,barometer"; + /* vbarometer-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + m_baro_pl@0 { + compatible = "mediatek,m_baro_pl"; + /* vbarometer-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + msensor@0 { + compatible = "mediatek,msensor"; + /* vmsensor-supply = <&mt_pmic_vio28_ldo_reg>; */ + }; + + mtkfb: mtkfb { + compatible = "mediatek,mtkfb"; + }; + + touch: touch { + compatible = "mediatek,mt6755-touch"; + /* VTOUCH-supply = <&mt_pmic_vgp1_ldo_reg>; */ + }; + + psci { + compatible = "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + affinity_info = <0x84000004>; + }; + + gpufreq { + compatible = "mediatek,mt6755-gpufreq"; + clocks = + <&topckgen TOP_MUX_MFG>, + <&topckgen TOP_MMPLL_CK>, + <&topckgen TOP_SYSPLL_D3>; + clock-names = + "clk_mux", + "clk_main_parent", + "clk_sub_parent"; + }; + }; + + mobicore { + compatible = "trustonic,mobicore"; + interrupts = ; + }; + + utos { + compatible = "microtrust,utos"; + interrupts = , + , + , + , + , + , + , + ; + }; + + /* Add dummy nodes for cust.dtsi */ + als: als { + compatible = "mediatek, als-eint"; + status = "disabled"; + }; + + gse_1: gse_1 { + compatible = "mediatek, gse_1-eint"; + status = "disabled"; + }; + + ext_buck_oc: ext_buck_oc { + compatible = "mediatek, ext_buck_oc-eint"; + status = "disabled"; + }; + + msdc1_ins: msdc1_ins { + compatible = "mediatek, msdc1_ins-eint"; + status = "disabled"; + }; + + gyro: gyro { + compatible = "mediatek, gyro-eint"; + status = "disabled"; + }; + + mse: mse { + compatible = "mediatek, mse-eint"; + status = "disabled"; + }; + + mrdump_ext_rst: mrdump_ext_rst { + compatible = "mediatek, mrdump_ext_rst-eint"; + status = "disabled"; + }; + + irq_nfc: irq_nfc { + compatible = "mediatek, irq_nfc-eint"; + status = "disabled"; + }; + + eint_wpc: eint_wpc { + compatible = "mediatek, eint_wpc-eint"; + status = "disabled"; + }; + + dsi_te: dsi_te { + compatible = "mediatek, dsi_te-eint"; + status = "disabled"; + }; + + goodix_fp: fingerprint@ { + compatible = "mediatek,goodix-fp"; + }; + + fpc_finger:fpc_finger { + compatible = "mediatek,fpc_finger"; + }; + usb_typec: usb_typec { + compatible = "mediatek,fusb300-eint"; + status = "disabled"; + }; + + swtp: swtp { + compatible = "mediatek, swtp-eint"; + }; + + fingerprint: fingerprint { + compatible = "mediatek, fingerprint-eint"; + }; + vanzo_fp: vanzo_fp { + compatible = "mediatek,vanzo-fp"; + }; + + rf_clock_buffer_ctrl:rf_clock_buffer { + compatible = "mediatek,rf_clock_buffer"; + mediatek,clkbuf-quantity = <4>; + mediatek,clkbuf-config = <2 0 1 1>; + mediatek,clkbuf-driving-current = <2 2 2 2>; + }; + + pmic_clock_buffer_ctrl:pmic_clock_buffer { + compatible = "mediatek,pmic_clock_buffer"; + mediatek,clkbuf-quantity = <4>; + mediatek,clkbuf-config = <2 1 1 2>; + mediatek,clkbuf-driving-current = <2 2 2 2>; + }; + + ext_buck_vmd1:ext_buck_vmd1 { + compatible = "mediatek,ext_buck_vmd1"; + }; + + halldriver: hall_driver { + compatible = "mediatek, hall_driver"; + }; + + hall: halleint { + compatible = "mediatek, HALL-eint"; + }; + breathlight:breathlight_drv { + compatible = "mediatek,breathlight"; + }; + cam_cal_drv{ + compatible = "mediatek,cam_cal_drv"; + main_bus = <2>; + sub_bus = <1>; + }; + +}; +/*/include/ "cust_pmic.dtsi"*/ + +#include "cust_mt6755_msdc.dtsi" + +#include + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#include "mt6353.dtsi" +#else +#include "mt6351.dtsi" +#endif diff --git a/arch/arm64/boot/dts/vz6750_65_i_n.dts b/arch/arm64/boot/dts/vz6750_65_i_n.dts new file mode 100755 index 0000000000000000000000000000000000000000..d77c76d9ccf86acb4833fcef61a9fc607acc7fc2 --- /dev/null +++ b/arch/arm64/boot/dts/vz6750_65_i_n.dts @@ -0,0 +1,983 @@ + +/dts-v1/; + +#include "mt6755.dtsi" +#include "cust.dtsi" + +/ { + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x3e800000>; + }; + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4B434E loglevel=8"; + + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base_h = <0x0>; + atag,videolfb-fb_base_l = <0x7E800000>; + atag,videolfb-islcmfound = <1>; + /* because no lk, so lcm is not inited */ + atag,videolfb-islcm_inited = <0>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35695_fhd_dsi_cmd_truly_nt50358_drv"; + }; + led0:led@0 { + compatible = "mediatek,red"; + led_mode = <3>; + data = <2>; + pwm_config = <0 0 0 0 0>; + }; + led1:led@1 { + compatible = "mediatek,green"; + led_mode = <3>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led2:led@2 { + compatible = "mediatek,blue"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led3:led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led4:led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led5:led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led6:led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <5>; + }; +/* start sensor */ + cust_accel@0 { + compatible = "mediatek,mpu6515a"; + i2c_num = <1>; + /* i2c_addr = <0x4c 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <16>; + is_batch_supported = <1>; + }; + + cust_alsps@0 { + compatible = "mediatek,cm36686"; + i2c_num = <1>; + i2c_addr = <0x60 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als = <1>; + power_id = <0xffff>; + power_vol = <0>; +/* Total has 15 level*/ + als_level = <0 257 637 1027 2297 5588 6730 11301 20449 25768 31122 45552 57937 57937 57937>; +/* Total has 16 range*/ + als_value = <0 132 304 502 1004 2003 3006 5006 8004 10000 12000 16000 20000 20000 20000 20000>; + ps_threshold_high = <70>; + ps_threshold_low = <40>; + is_batch_supported_ps = <1>; + is_batch_supported_als = <1>; + }; + + cust_mag@0 { + compatible = "mediatek,akm8963"; + i2c_num = <1>; + /* i2c_addr = <0x0F 0 0 0>; */ + direction = <8>; + power_id = <0xffff>; + power_vol = <0>; + /* is_batch_supported = <0>; */ + }; + + cust_gyro@0 { + compatible = "mediatek,mpu6515g"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + + cust_baro@0 { + compatible = "mediatek,bmp280new"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <32>; + is_batch_supported = <0>; + }; +/* end sensor */ +}; +/*ACCDET start*/ +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <1>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 80 220 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; + /* ACCDET GPIO standardization ACC mode use */ + pinctrl-names = "default", "state_eint_as_int"; + pinctrl-0 = <&accdet_pins_default>; + pinctrl-1 = <&accdet_pins_eint_as_int>; + status = "okay"; +}; +&pio { + accdet_pins_default: accdetdefault { + }; + accdet_pins_eint_as_int: accdeteint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; +}; +/*ACCDET end*/ +/* TOUCH start */ +&touch { + tpd-resolution = <1080 1920>; + use-tpd-button = <0>; + tpd-key-num = <3>; + tpd-key-local= <139 172 158 0>; + tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>; + tpd-max-touch-num = <5>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <146>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <0 0 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1","state_ldoen_output0","state_ldoen_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + pinctrl-6 = <&ctp_pins_ldoen_output0>; + pinctrl-7 = <&ctp_pins_ldoen_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: eint0default { + }; + ctp_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_ldoen_output0: ldoenoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_ldoen_output1: ldoenoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_sub_vcama0: cam1@4 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_sub_vcama1: cam1@5 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam_ldo_vcama_0: cam@vcama0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam_ldo_vcama_1: cam@vcama1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_default: camdefault { + }; + +}; + +&kd_camera_hw1 { + pinctrl-names = "default", + "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo_sub_vcama_0", "cam_ldo_sub_vcama_1", + /*"cam2_rst0", "cam2_rst1", "cam2_pnd0", "cam2_pnd1",*/ + "cam_ldo_vcama_0", "cam_ldo_vcama_1"; + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_sub_vcama0>; + pinctrl-10 = <&camera_pins_sub_vcama1>; + /* for main2 */ + /*pinctrl-9 = <&camera_pins_cam2_rst0>; + pinctrl-10 = <&camera_pins_cam2_rst1>; + pinctrl-11 = <&camera_pins_cam2_pnd0>; + pinctrl-12 = <&camera_pins_cam2_pnd1>;*/ + /* for ldo control by gpio */ + pinctrl-11 = <&camera_pins_cam_ldo_vcama_0>; + pinctrl-12 = <&camera_pins_cam_ldo_vcama_1>; + status = "okay"; + +}; +/* CAMERA GPIO end */ +/* FLASHLIGHT GPIO standardization */ +&pio { + flashlight_pins_default: default { + + }; + + flashlight_pins_hwen_high: hwen_high { + + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + flashlight_pins_hwen_low: hwen_low { + + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&flashlight { + pinctrl-names = "default", "hwen_high", "hwen_low"; + pinctrl-0 = <&flashlight_pins_default>; + pinctrl-1 = <&flashlight_pins_hwen_high>; + pinctrl-2 = <&flashlight_pins_hwen_low>; + status = "okay"; +}; +/* FLASHLIGHT GPIO standardization end*/ + +&pio { + alsps_intpin_cfg: alspspincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + + alsps_intpin_default: alspsdefaultcfg { + + }; + + gyro_intpin_cfg: gyropincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + + gyro_intpin_default: gyrodefaultcfg { + + }; +}; + +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; + +&gyroscope { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_lcd_bias_enp0: lcd_bias_enp0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcd_bias_enp1: lcd_bias_enp1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", "lcd_bias_enp0_gpio", "lcd_bias_enp1_gpio"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_lcd_bias_enp0>; + pinctrl-6 = <&mtkfb_pins_lcd_bias_enp1>; + status = "okay"; +};/* DISPSYS GPIO standardization end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + }; + + gpslna_pins_init: gpslna@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; +}; +/* CONSYS end */ + +/* SPM GPIO standardization */ +&pio { + spm_pins_default: default { + }; + + spm_vmd1_sel: vmd1_sel { + pins_cmd_dat { + pins = ; + }; + }; + +}; + +&sleep{ + pinctrl-names = "default", "vmd1_sel"; + pinctrl-0 = <&spm_pins_default>; + pinctrl-1 = <&spm_vmd1_sel>; + status = "okay"; +}; +/* SPM end */ + +/* AUDIO GPIO standardization */ +&audgpio { + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "audi2s1-mode0", "audi2s1-mode1", "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow", "rcvspk-pullhigh", + "rcvspk-pulllow","hpdepop-pullhigh","hpdepop-pulllow"; + pinctrl-0 = <&aud_pins_default>; + pinctrl-1 = <&aud_pins_pmicclk_mode0>; + pinctrl-2 = <&aud_pins_pmicclk_mode1>; + pinctrl-3 = <&aud_pins_i2s1_mode0>; + pinctrl-4 = <&aud_pins_i2s1_mode1>; + pinctrl-5 = <&aud_pins_extamp_high>; + pinctrl-6 = <&aud_pins_extamp_low>; + pinctrl-7 = <&aud_pins_extamp2_high>; + pinctrl-8 = <&aud_pins_extamp2_low>; + pinctrl-9 = <&aud_pins_rcvspk_high>; + pinctrl-10 = <&aud_pins_rcvspk_low>; + pinctrl-11 = <&aud_pins_hpdepop_high>; + pinctrl-12 = <&aud_pins_hpdepop_low>; + status = "okay"; +}; + +&pio { + aud_pins_default: audiodefault { + }; + + aud_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode0: audi2s1mode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode1: audi2s1mode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_extamp_high: audexamphigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_extamp_low: audexamplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_extamp2_high: audexam2phigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + aud_pins_extamp2_low: audexamp2low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_rcvspk_high: audrcvspkhigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_rcvspk_low: audrcvspklow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_hpdepop_high: audhpdepophigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_hpdepop_low: audhpdepoplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; +/* AUDIO end */ + +/* UART GPIO */ +&apuart0 { + pinctrl-names = "uart0_gpio_default", + "uart0_rx_set", + "uart0_rx_clear", + "uart0_tx_set", + "uart0_tx_clear"; + pinctrl-0 = <&uart0_gpio_def_cfg>; + pinctrl-1 = <&uart0_rx_set_cfg>; + pinctrl-2 = <&uart0_rx_clr_cfg>; + pinctrl-3 = <&uart0_tx_set_cfg>; + pinctrl-4 = <&uart0_tx_clr_cfg>; + status = "okay"; +}; + +&pio { + /* UART GPIO Settings - Start */ + /* UART0: rx set, rx clear, tx clear, tx clear*/ + uart0_gpio_def_cfg:uart0gpiodefault { + + }; + uart0_rx_set_cfg:uart0_rx_set@gpio105 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_rx_clr_cfg:uart0_rx_clear@gpio105 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + uart0_tx_set_cfg:uart0_tx_set@gpio106 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_tx_clr_cfg:uart0_tx_clear@gpio106 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +};/* UART GPIO end */ + +/* IRTX GPIO end */ +&apirtx { + pinctrl-names = "irtx_gpio_led_default", + "irtx_gpio_led_set", + "irtx_gpio_en_default", + "irtx_gpio_en_set"; + + pinctrl-0 = <&irtx_gpio_led_default>; + pinctrl-1 = <&irtx_gpio_led_set>; + pinctrl-2 = <&irtx_gpio_en_default>; + pinctrl-3 = <&irtx_gpio_en_set>; + status = "okay"; +}; +&pio { + /* IRTX GPIO Settings -Start */ + /* default: GPIO0, output, high */ + irtx_gpio_led_default:irtx_gpio_led_def@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_led_set:irtx_gpio_led_set@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + irtx_gpio_en_default:irtx_gpio_en_def@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_en_set:irtx_gpio_en_set@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + +}; /* IRTX GPIO Settings -End */ + +/* NFC GPIO standardization */ +&pio { + nfc_default: default { + + }; + + nfc_ven_high: state_ven_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_ven_low: state_ven_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_rst_high: state_rst_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_rst_low: state_rst_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_eint_high: state_eint_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_eint_low: state_eint_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_irq_init: state_irq_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; +}; + +&nfc { + pinctrl-names = "default", "ven_high", "ven_low", "rst_high", "rst_low", "eint_high", "eint_low", "irq_init"; + pinctrl-0 = <&nfc_default>; + pinctrl-1 = <&nfc_ven_high>; + pinctrl-2 = <&nfc_ven_low>; + pinctrl-3 = <&nfc_rst_high>; + pinctrl-4 = <&nfc_rst_low>; + pinctrl-5 = <&nfc_eint_high>; + pinctrl-6 = <&nfc_eint_low>; + pinctrl-7 = <&nfc_irq_init>; + status = "okay"; +}; +/* NFC end */ + + + + +&pio { + iddig_default: iddig_default { + }; + + iddig_init: iddig_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio43_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + gpio43_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&iddig_init>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio43_mode1_drvvbus_low>; + pinctrl-2 = <&gpio43_mode1_drvvbus_high>; + status = "okay"; +}; + +&i2c1 { + + gyro@68 { + compatible = "mediatek,gyro"; + reg = <0x69>; + status = "okay"; + }; + + gsensor@68 { + compatible = "mediatek,gsensor"; + reg = <0x68>; + status = "okay"; + }; +}; + +&ext_buck_vmd1 { + pinctrl-names = "default", "vmd1_sel_low", "vmd1_sel_high"; + + pinctrl-0 = <&vmd1_default>; + pinctrl-1 = <&vmd1_sel_low>; + pinctrl-2 = <&vmd1_sel_high>; +}; + +&pio { + vmd1_default: vmd10default { + }; + + vmd1_sel_low: vmd1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + vmd1_sel_high: vmd1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; diff --git a/arch/arm64/boot/dts/vz6750_66_i_n.dts b/arch/arm64/boot/dts/vz6750_66_i_n.dts new file mode 100644 index 0000000000000000000000000000000000000000..8fd1dd2f8e61436de2f521b2f2817b3cd2d73961 --- /dev/null +++ b/arch/arm64/boot/dts/vz6750_66_i_n.dts @@ -0,0 +1,907 @@ + +/dts-v1/; + +#include "mt6755.dtsi" +#include "cust.dtsi" + +/ { + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x3e800000>; + }; + /* chosen */ + chosen { + bootargs = "console=tty0 console=ttyMT0,921600n1 root=/dev/ram initrd=0x44000000,0x4B434E loglevel=8"; + + /* fpga may has no lk, we need to specify display info here */ + /* fb buffer is reserved using this dts by memory node above */ + atag,videolfb-fb_base_h = <0x0>; + atag,videolfb-fb_base_l = <0x7E800000>; + atag,videolfb-islcmfound = <1>; + /* because no lk, so lcm is not inited */ + atag,videolfb-islcm_inited = <0>; + atag,videolfb-fps= <6000>; + atag,videolfb-vramSize= <0x01800000>; + atag,videolfb-lcmname= "nt35695_fhd_dsi_cmd_truly_nt50358_drv"; + }; + led0:led@0 { + compatible = "mediatek,red"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led1:led@1 { + compatible = "mediatek,green"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led2:led@2 { + compatible = "mediatek,blue"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led3:led@3 { + compatible = "mediatek,jogball-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led4:led@4 { + compatible = "mediatek,keyboard-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led5:led@5 { + compatible = "mediatek,button-backlight"; + led_mode = <0>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + led6:led@6 { + compatible = "mediatek,lcd-backlight"; + led_mode = <5>; + data = <1>; + pwm_config = <0 0 0 0 0>; + }; + vibrator0:vibrator@0 { + compatible = "mediatek,vibrator"; + vib_timer = <25>; + vib_limit = <9>; + vib_vol= <5>; + }; +/* start sensor */ + cust_accel@0 { + compatible = "mediatek,mpu6515a"; + i2c_num = <1>; + /* i2c_addr = <0x4c 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <16>; + is_batch_supported = <1>; + }; + + cust_alsps@0 { + compatible = "mediatek,cm36686"; + i2c_num = <1>; + i2c_addr = <0x60 0 0 0>; + polling_mode_ps = <0>; + polling_mode_als = <1>; + power_id = <0xffff>; + power_vol = <0>; +/* Total has 15 level*/ + als_level = <0 257 637 1027 2297 5588 6730 11301 20449 25768 31122 45552 57937 57937 57937>; +/* Total has 16 range*/ + als_value = <0 132 304 502 1004 2003 3006 5006 8004 10000 12000 16000 20000 20000 20000 20000>; + ps_threshold_high = <70>; + ps_threshold_low = <40>; + is_batch_supported_ps = <1>; + is_batch_supported_als = <1>; + }; + + cust_mag@0 { + compatible = "mediatek,akm8963"; + i2c_num = <1>; + /* i2c_addr = <0x0F 0 0 0>; */ + direction = <8>; + power_id = <0xffff>; + power_vol = <0>; + /* is_batch_supported = <0>; */ + }; + + cust_gyro@0 { + compatible = "mediatek,mpu6515g"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <6>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <0>; + is_batch_supported = <0>; + }; + + cust_baro@0 { + compatible = "mediatek,bmp280new"; + i2c_num = <1>; + /* i2c_addr = <0x68 0 0 0>; */ + direction = <0>; + power_id = <0xffff>; + power_vol = <0>; + firlen = <32>; + is_batch_supported = <0>; + }; +/* end sensor */ +}; +&accdet { + accdet-mic-vol = <7>; + headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>; + accdet-plugout-debounce = <20>; + /*1:ACC mode, 2:low cost without in bias, 6:low cost with in bias*/ + accdet-mic-mode = <6>; + /*0--MD_MAX--UP_MAX--DW_MAX*/ + headset-three-key-threshold = <0 80 220 500>; + /*0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX*/ + headset-four-key-threshold = <0 59 123 195 450>; +}; + +/* TOUCH start */ +&touch { + tpd-resolution = <1080 1920>; + use-tpd-button = <0>; + tpd-key-num = <3>; + tpd-key-local= <139 172 158 0>; + tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>; + tpd-max-touch-num = <5>; + tpd-filter-enable = <1>; + tpd-filter-pixel-density = <146>; + tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>; + tpd-filter-custom-speed = <0 0 0>; + pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1", + "state_rst_output0", "state_rst_output1"; + pinctrl-0 = <&ctp_pins_default>; + pinctrl-1 = <&ctp_pins_eint_as_int>; + pinctrl-2 = <&ctp_pins_eint_output0>; + pinctrl-3 = <&ctp_pins_eint_output1>; + pinctrl-4 = <&ctp_pins_rst_output0>; + pinctrl-5 = <&ctp_pins_rst_output1>; + status = "okay"; +}; +&pio { + ctp_pins_default: eint0default { + }; + ctp_pins_eint_as_int: eint@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + }; + }; + ctp_pins_eint_output0: eintoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_eint_output1: eintoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + ctp_pins_rst_output0: rstoutput0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + ctp_pins_rst_output1: rstoutput1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; +/* TOUCH end */ + +/* CAMERA GPIO standardization */ +&pio { + camera_pins_cam0_rst0: cam0@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam0_rst1: cam0@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam0_pnd0: cam0@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam0_pnd1: cam0@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_rst0: cam1@0 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; /*direction 0:in, 1:out*/ + output-low;/*direction out used only. output_low or high*/ + }; + }; + camera_pins_cam1_rst1: cam1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_cam1_pnd0: cam1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_cam1_pnd1: cam1@3 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + camera_pins_sub_vcamd0: cam1@4 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + camera_pins_sub_vcamd1: cam1@5 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + /*camera_pins_cam_ldo_vcama_0: cam@vcama0 { + }; + camera_pins_cam_ldo_vcama_1: cam@vcama1 { + };*/ + camera_pins_default: camdefault { + }; + +}; + +&kd_camera_hw1 { + pinctrl-names = "default", + "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1", + "cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1", + "cam_ldo_sub_vcamd_0", "cam_ldo_sub_vcamd_1"; + /*"cam2_rst0", "cam2_rst1", "cam2_pnd0", "cam2_pnd1", + "cam_ldo_vcama_0", "cam_ldo_vcama_1";*/ + pinctrl-0 = <&camera_pins_default>; + pinctrl-1 = <&camera_pins_cam0_rst0>; + pinctrl-2 = <&camera_pins_cam0_rst1>; + pinctrl-3 = <&camera_pins_cam0_pnd0>; + pinctrl-4 = <&camera_pins_cam0_pnd1>; + pinctrl-5 = <&camera_pins_cam1_rst0>; + pinctrl-6 = <&camera_pins_cam1_rst1>; + pinctrl-7 = <&camera_pins_cam1_pnd0>; + pinctrl-8 = <&camera_pins_cam1_pnd1>; + pinctrl-9 = <&camera_pins_sub_vcamd0>; + pinctrl-10 = <&camera_pins_sub_vcamd1>; + /* for main2 */ + /*pinctrl-9 = <&camera_pins_cam2_rst0>; + pinctrl-10 = <&camera_pins_cam2_rst1>; + pinctrl-11 = <&camera_pins_cam2_pnd0>; + pinctrl-12 = <&camera_pins_cam2_pnd1>;*/ + /* for ldo control by gpio */ + /*pinctrl-13 = <&camera_pins_cam_ldo_vcama_0>; + pinctrl-14 = <&camera_pins_cam_ldo_vcama_1>;*/ + status = "okay"; + +}; +/* CAMERA GPIO end */ + +&pio { + alsps_intpin_cfg: alspspincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; + + alsps_intpin_default: alspsdefaultcfg { + + }; + + gyro_intpin_cfg: gyropincfg { + + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; + + gyro_intpin_default: gyrodefaultcfg { + + }; +}; + +&alsps { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&alsps_intpin_default>; + pinctrl-1 = <&alsps_intpin_cfg>; + status = "okay"; +}; + +&gyroscope { + pinctrl-names = "pin_default", "pin_cfg"; + pinctrl-0 = <&gyro_intpin_default>; + pinctrl-1 = <&gyro_intpin_cfg>; + status = "okay"; +}; + +/* DISPSYS GPIO standardization */ +&pio { + + mtkfb_pins_mode_te_gpio: mode_te_gpio { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_mode_te_te: mode_te_te { + pins_cmd_dat { + pins = ; + }; + }; + + mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_lcd_bias_enp0: lcd_bias_enp0_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + mtkfb_pins_lcd_bias_enp1: lcd_bias_enp1_gpio { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + mtkfb_pins_default: default { + }; +}; + +&mtkfb { + pinctrl-names = "default", "mode_te_gpio", "mode_te_te", "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", "lcd_bias_enp0_gpio", "lcd_bias_enp1_gpio"; + pinctrl-0 = <&mtkfb_pins_default>; + pinctrl-1 = <&mtkfb_pins_mode_te_gpio>; + pinctrl-2 = <&mtkfb_pins_mode_te_te>; + pinctrl-3 = <&mtkfb_pins_lcm_reset0>; + pinctrl-4 = <&mtkfb_pins_lcm_reset1>; + pinctrl-5 = <&mtkfb_pins_lcd_bias_enp0>; + pinctrl-6 = <&mtkfb_pins_lcd_bias_enp1>; + status = "okay"; +};/* DISPSYS GPIO standardization end */ + +/* CONSYS GPIO standardization */ +&pio { + consys_pins_default: default { + }; + + gpslna_pins_init: gpslna@0 { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-disable; + output-low; + }; + }; + + gpslna_pins_oh: gpslna@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + gpslna_pins_ol: gpslna@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; + +&consys { + pinctrl-names = "default", "gps_lna_state_init", "gps_lna_state_oh", "gps_lna_state_ol"; + pinctrl-0 = <&consys_pins_default>; + pinctrl-1 = <&gpslna_pins_init>; + pinctrl-2 = <&gpslna_pins_oh>; + pinctrl-3 = <&gpslna_pins_ol>; + status = "okay"; +}; +/* CONSYS end */ + +/* SPM GPIO standardization */ +&pio { + spm_pins_default: default { + }; + + spm_vmd1_sel: vmd1_sel { + pins_cmd_dat { + pins = ; + }; + }; + +}; + +&sleep{ + pinctrl-names = "default", "vmd1_sel"; + pinctrl-0 = <&spm_pins_default>; + pinctrl-1 = <&spm_vmd1_sel>; + status = "okay"; +}; +/* SPM end */ + +/* AUDIO GPIO standardization */ +&audgpio { + pinctrl-names = "default", "audpmicclk-mode0", "audpmicclk-mode1", + "audi2s1-mode0", "audi2s1-mode1", "extamp-pullhigh", "extamp-pulllow", + "extamp2-pullhigh", "extamp2-pulllow", "rcvspk-pullhigh", + "rcvspk-pulllow","hpdepop-pullhigh","hpdepop-pulllow"; + pinctrl-0 = <&aud_pins_default>; + pinctrl-1 = <&aud_pins_pmicclk_mode0>; + pinctrl-2 = <&aud_pins_pmicclk_mode1>; + pinctrl-3 = <&aud_pins_i2s1_mode0>; + pinctrl-4 = <&aud_pins_i2s1_mode1>; + pinctrl-5 = <&aud_pins_extamp_high>; + pinctrl-6 = <&aud_pins_extamp_low>; + pinctrl-7 = <&aud_pins_extamp2_high>; + pinctrl-8 = <&aud_pins_extamp2_low>; + pinctrl-9 = <&aud_pins_rcvspk_high>; + pinctrl-10 = <&aud_pins_rcvspk_low>; + pinctrl-11 = <&aud_pins_hpdepop_high>; + pinctrl-12 = <&aud_pins_hpdepop_low>; + status = "okay"; +}; + +&pio { + aud_pins_default: audiodefault { + }; + + aud_pins_pmicclk_mode0: pmicclkmode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_pmicclk_mode1: pmicclkmode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode0: audi2s1mode0 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_i2s1_mode1: audi2s1mode1 { + pins_cmd0_dat { + pins = ; + }; + pins_cmd1_dat { + pins = ; + }; + pins_cmd2_dat { + pins = ; + }; + }; + + aud_pins_extamp_high: audexamphigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_extamp_low: audexamplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_extamp2_high: audexam2phigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + aud_pins_extamp2_low: audexamp2low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_rcvspk_high: audrcvspkhigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_rcvspk_low: audrcvspklow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + aud_pins_hpdepop_high: audhpdepophigh { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + aud_pins_hpdepop_low: audhpdepoplow { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; +}; +/* AUDIO end */ + +/* UART GPIO */ +&apuart0 { + pinctrl-names = "uart0_gpio_default", + "uart0_rx_set", + "uart0_rx_clear", + "uart0_tx_set", + "uart0_tx_clear"; + pinctrl-0 = <&uart0_gpio_def_cfg>; + pinctrl-1 = <&uart0_rx_set_cfg>; + pinctrl-2 = <&uart0_rx_clr_cfg>; + pinctrl-3 = <&uart0_tx_set_cfg>; + pinctrl-4 = <&uart0_tx_clr_cfg>; + status = "okay"; +}; + +&pio { + /* UART GPIO Settings - Start */ + /* UART0: rx set, rx clear, tx clear, tx clear*/ + uart0_gpio_def_cfg:uart0gpiodefault { + + }; + uart0_rx_set_cfg:uart0_rx_set@gpio105 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_rx_clr_cfg:uart0_rx_clear@gpio105 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + uart0_tx_set_cfg:uart0_tx_set@gpio106 { + pins_cmd_dat { + pins = ; + }; + }; + uart0_tx_clr_cfg:uart0_tx_clear@gpio106 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +};/* UART GPIO end */ + +/* IRTX GPIO end */ +&irtx_pwm { + pinctrl-names = "irtx_gpio_led_default", + "irtx_gpio_led_set", + "irtx_gpio_en_default", + "irtx_gpio_en_set"; + + pinctrl-0 = <&irtx_gpio_led_default>; + pinctrl-1 = <&irtx_gpio_led_set>; + pinctrl-2 = <&irtx_gpio_en_default>; + pinctrl-3 = <&irtx_gpio_en_set>; + status = "okay"; +}; +&pio { + /* IRTX GPIO Settings -Start */ + /* default: GPIO0, output, high */ + irtx_gpio_led_default:irtx_gpio_led_def@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_led_set:irtx_gpio_led_set@gpio116 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + irtx_gpio_en_default:irtx_gpio_en_def@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + bias-disable; + output-low; + input-schmitt-enable = <0>; + }; + }; + + irtx_gpio_en_set:irtx_gpio_en_set@gpio104 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + +}; /* IRTX GPIO Settings -End */ + +/* NFC GPIO standardization */ +&pio { + nfc_default: default { + + }; + + nfc_ven_high: state_ven_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_ven_low: state_ven_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_rst_high: state_rst_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_rst_low: state_rst_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_eint_high: state_eint_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; + + nfc_eint_low: state_eint_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + nfc_irq_init: state_irq_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-down = <00>; + }; + }; +}; + +&nfc { + pinctrl-names = "default", "ven_high", "ven_low", "rst_high", "rst_low", "eint_high", "eint_low", "irq_init"; + pinctrl-0 = <&nfc_default>; + pinctrl-1 = <&nfc_ven_high>; + pinctrl-2 = <&nfc_ven_low>; + pinctrl-3 = <&nfc_rst_high>; + pinctrl-4 = <&nfc_rst_low>; + pinctrl-5 = <&nfc_eint_high>; + pinctrl-6 = <&nfc_eint_low>; + pinctrl-7 = <&nfc_irq_init>; + status = "okay"; +}; +/* NFC end */ + + + + +&pio { + iddig_default: iddig_default { + }; + + iddig_init: iddig_init { + pins_cmd_dat { + pins = ; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio43_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + gpio43_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&iddig_init>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio43_mode1_drvvbus_low>; + pinctrl-2 = <&gpio43_mode1_drvvbus_high>; + status = "okay"; +}; + +&i2c1 { + + gyro@68 { + compatible = "mediatek,gyro"; + reg = <0x69>; + status = "okay"; + }; + + gsensor@68 { + compatible = "mediatek,gsensor"; + reg = <0x68>; + status = "okay"; + }; +}; + +&ext_buck_vmd1 { + pinctrl-names = "default", "vmd1_sel_low", "vmd1_sel_high"; + + pinctrl-0 = <&vmd1_default>; + pinctrl-1 = <&vmd1_sel_low>; + pinctrl-2 = <&vmd1_sel_high>; +}; + +&pio { + vmd1_default: vmd10default { + }; + + vmd1_sel_low: vmd1@1 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-low; + }; + }; + + vmd1_sel_high: vmd1@2 { + pins_cmd_dat { + pins = ; + slew-rate = <1>; + output-high; + }; + }; +}; diff --git a/arch/arm64/configs/K6000_Plus_debug_defconfig b/arch/arm64/configs/K6000_Plus_debug_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..8c338c2648f40fc297910b9db335f13bb626cdd5 --- /dev/null +++ b/arch/arm64/configs/K6000_Plus_debug_defconfig @@ -0,0 +1,531 @@ +CONFIG_CROSS_COMPILE="aarch64-linux-android-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_RCU_FANOUT=32 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_MTK_PSCI=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +# CONFIG_EFI is not set +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="K6000_Plus" +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTK_NET_LOGGING=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="K6000_Plus" +CONFIG_MT_ENG_BUILD=y +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=12 +CONFIG_MTK_MD3_SUPPORT=2 +CONFIG_MTK_C2K_LTE_MODE=2 +CONFIG_MTK_IRAT_SUPPORT=y +CONFIG_MTK_C2K_SLOT2_SUPPORT=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_IRTX_PWM_SUPPORT=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_MEMCFG=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_AEE_MRDUMP=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_WQ_DEBUG=y +CONFIG_MT_SCHED_MONITOR=y +CONFIG_MT_RT_THROTTLE_MON=y +CONFIG_PREEMPT_MONITOR=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MTK_COMPAT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MT_SCHED_TRACE=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_MTK_WATCHPOINT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_MTK_MRDUMP_KEY=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_MTK_EMMC_CQ_SUPPORT=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_DEBUG=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_SLUB_DEBUG_ON=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=3200 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_LOCKDEP=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_TRACE=y +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_MTK_FTRACE_DEFAULT_ENABLE=y +CONFIG_DMA_API_DEBUG=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +CONFIG_DEBUG_RODATA=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_LIBCRC32C=y diff --git a/arch/arm64/configs/K6000_Plus_defconfig b/arch/arm64/configs/K6000_Plus_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..74b356f05793a21c038c4015a3697acfd07acccb --- /dev/null +++ b/arch/arm64/configs/K6000_Plus_defconfig @@ -0,0 +1,511 @@ +CONFIG_CROSS_COMPILE="aarch64-linux-android-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_RCU_FANOUT=32 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_MTK_PSCI=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +# CONFIG_EFI is not set +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="K6000_Plus" +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="K6000_Plus" +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +#CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y + +#CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +#CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +#CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +#CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +#CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +#CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=14 +CONFIG_MTK_MD3_SUPPORT=0 +CONFIG_MTK_C2K_LTE_MODE=2 +#CONFIG_MTK_IRAT_SUPPORT=y +CONFIG_MTK_C2K_SLOT2_SUPPORT=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_IRTX_PWM_SUPPORT=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MTK_COMPAT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +#CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_MTK_WATCHPOINT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_MTK_MRDUMP_KEY=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_MTK_EMMC_CQ_SUPPORT=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=1 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_DEBUG_RODATA=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_LIBCRC32C=y + +CONFIG_MTK_LCM_PHYSICAL_ROTATION="180" +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y + diff --git a/arch/arm64/configs/vz6750_65_i_n_debug_defconfig b/arch/arm64/configs/vz6750_65_i_n_debug_defconfig new file mode 100755 index 0000000000000000000000000000000000000000..16ce235e9e0d97c897cc692a52aba94a2590a37c --- /dev/null +++ b/arch/arm64/configs/vz6750_65_i_n_debug_defconfig @@ -0,0 +1,527 @@ +CONFIG_CROSS_COMPILE="aarch64-linux-android-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_RCU_FANOUT=32 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_MTK_PSCI=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +# CONFIG_EFI is not set +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="vz6750_65_i_n" +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTK_NET_LOGGING=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_65_i_n" +CONFIG_MT_ENG_BUILD=y +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_NCP1854_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k3p3sx_mipi_raw ov8856_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35532_auo55_truly_fhd" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=10 +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_MEMCFG=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_AEE_MRDUMP=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_WQ_DEBUG=y +CONFIG_MT_SCHED_MONITOR=y +CONFIG_MT_RT_THROTTLE_MON=y +CONFIG_PREEMPT_MONITOR=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MTK_COMPAT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MT_SCHED_TRACE=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +# CONFIG_MICROTRUST_TEE_SUPPORT is not set +CONFIG_MTK_WATCHPOINT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +# CONFIG_GTP_DRIVER_SEND_CFG is not set +CONFIG_GTP_CUSTOM_CFG=y +# CONFIG_GTP_HOTKNOT is not set +CONFIG_GTP_AUTO_UPDATE=y +# CONFIG_GTP_HEADER_FW_UPDATE is not set +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_MTK_MRDUMP_KEY=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +# CONFIG_MTK_SPEAKER is not set +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_MTK_EMMC_CQ_SUPPORT=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_DEBUG=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_SLUB_DEBUG_ON=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=3200 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_LOCKDEP=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_TRACE=y +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_MTK_FTRACE_DEFAULT_ENABLE=y +CONFIG_DMA_API_DEBUG=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +CONFIG_DEBUG_RODATA=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_LIBCRC32C=y diff --git a/arch/arm64/configs/vz6750_65_i_n_defconfig b/arch/arm64/configs/vz6750_65_i_n_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..9bb5954970246b825fcc87824e4be12d93352026 --- /dev/null +++ b/arch/arm64/configs/vz6750_65_i_n_defconfig @@ -0,0 +1,503 @@ +CONFIG_CROSS_COMPILE="aarch64-linux-android-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_RCU_FANOUT=32 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_MTK_PSCI=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +# CONFIG_EFI is not set +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="vz6750_65_i_n" +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_65_i_n" +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_NCP1854_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k3p3sx_mipi_raw ov8856_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35532_auo55_truly_fhd" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=10 +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MTK_COMPAT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +# CONFIG_MICROTRUST_TEE_SUPPORT is not set +CONFIG_MTK_WATCHPOINT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +# CONFIG_GTP_DRIVER_SEND_CFG is not set +CONFIG_GTP_CUSTOM_CFG=y +# CONFIG_GTP_HOTKNOT is not set +CONFIG_GTP_AUTO_UPDATE=y +# CONFIG_GTP_HEADER_FW_UPDATE is not set +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_MTK_MRDUMP_KEY=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +# CONFIG_MTK_SPEAKER is not set +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_MTK_EMMC_CQ_SUPPORT=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=1 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_DEBUG_RODATA=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_LIBCRC32C=y diff --git a/arch/arm64/configs/vz6750_66_i_n_debug_defconfig b/arch/arm64/configs/vz6750_66_i_n_debug_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..b36c6e2941894aed142d93d9d92eca2e3b2baf0a --- /dev/null +++ b/arch/arm64/configs/vz6750_66_i_n_debug_defconfig @@ -0,0 +1,531 @@ +CONFIG_CROSS_COMPILE="aarch64-linux-android-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_RCU_FANOUT=32 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_MTK_PSCI=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +# CONFIG_EFI is not set +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="vz6750_66_i_n" +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTK_NET_LOGGING=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_66_i_n" +CONFIG_MT_ENG_BUILD=y +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=12 +CONFIG_MTK_MD3_SUPPORT=2 +CONFIG_MTK_C2K_LTE_MODE=2 +CONFIG_MTK_IRAT_SUPPORT=y +CONFIG_MTK_C2K_SLOT2_SUPPORT=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_IRTX_PWM_SUPPORT=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_MEMCFG=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_AEE_MRDUMP=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_WQ_DEBUG=y +CONFIG_MT_SCHED_MONITOR=y +CONFIG_MT_RT_THROTTLE_MON=y +CONFIG_PREEMPT_MONITOR=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MTK_COMPAT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MT_SCHED_TRACE=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_MTK_WATCHPOINT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_MTK_MRDUMP_KEY=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_MTK_EMMC_CQ_SUPPORT=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_DEBUG=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_SLUB_DEBUG_ON=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=3200 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_LOCKDEP=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_TRACE=y +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_MTK_FTRACE_DEFAULT_ENABLE=y +CONFIG_DMA_API_DEBUG=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +CONFIG_DEBUG_RODATA=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_LIBCRC32C=y diff --git a/arch/arm64/configs/vz6750_66_i_n_defconfig b/arch/arm64/configs/vz6750_66_i_n_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..4c3d03238881c663a5e16e7c87baea99f4fc1a1f --- /dev/null +++ b/arch/arm64/configs/vz6750_66_i_n_defconfig @@ -0,0 +1,507 @@ +CONFIG_CROSS_COMPILE="aarch64-linux-android-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_RCU_FANOUT=32 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MT6755=y +CONFIG_MTK_PSCI=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +# CONFIG_BOUNCE is not set +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O " +# CONFIG_EFI is not set +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="vz6750_66_i_n" +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_REALM=y +CONFIG_NETFILTER_XT_MATCH_RECENT=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_IPT=y +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND_IDS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_DEBUG=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_UID_STAT=y +CONFIG_UID_CPUTIME=y +CONFIG_MEDIATEK_SOLUTION=y +CONFIG_MTK_PLATFORM="mt6755" +CONFIG_ARCH_MTK_PROJECT="vz6750_66_i_n" +CONFIG_MTK_SHARED_SDCARD=y +CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y +CONFIG_MTK_FREQ_HOPPING=y +CONFIG_MTK_PMIC_NEW_ARCH=y +CONFIG_MTK_PMIC_CHIP_MT6353=y +CONFIG_MTK_BQ25896_SUPPORT=y +CONFIG_MTK_THERMAL_PA_VIA_ATCMD=y +CONFIG_CUSTOM_KERNEL_IMGSENSOR="s5k2p8_mipi_raw ov8858_mipi_raw" +CONFIG_MTK_CMDQ=y +CONFIG_MTK_CQDMA=y +CONFIG_MTK_FLASHLIGHT=y +CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight" +CONFIG_MTK_GPU_SUPPORT=y +CONFIG_MTK_GPU_VERSION="mali midgard r12p1" +CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT=y +CONFIG_MTK_IMGSENSOR=y +CONFIG_MTK_JPEG=y +CONFIG_MTK_LCM=y +CONFIG_CUSTOM_KERNEL_LCM="nt35695_fhd_dsi_cmd_truly_nt50358" +CONFIG_MTK_LENS=y +CONFIG_MTK_LENS_DUMMYLENS_SUPPORT=y +CONFIG_MTK_LENS_AD5820AF_SUPPORT=y +CONFIG_MTK_LENS_BU6424AF_SUPPORT=y +CONFIG_MTK_LENS_BU6429AF_SUPPORT=y +CONFIG_MTK_LENS_DW9714AF_SUPPORT=y +CONFIG_MTK_LENS_LC898212AF_SUPPORT=y +CONFIG_MTK_LENS_LC898214AF_SUPPORT=y +CONFIG_MTK_MMPROFILE_SUPPORT=y +CONFIG_MMPROFILE=y +CONFIG_MTK_SYNC=y +CONFIG_MTK_VIDEOCODEC_DRIVER=y +CONFIG_MTK_FB=y +CONFIG_MTK_VIDEOX=y +CONFIG_MTK_LCM_PHYSICAL_ROTATION="0" +CONFIG_MTK_AAL_SUPPORT=y +CONFIG_MTK_SENSOR_SUPPORT=y +CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y +CONFIG_MTK_MPU6515A=y +CONFIG_CUSTOM_KERNEL_ALSPS=y +CONFIG_MTK_CM36686_NEW=y +CONFIG_MTK_BMP280_NEW=y +CONFIG_CUSTOM_KERNEL_GYROSCOPE=y +CONFIG_MTK_MPU6515G=y +CONFIG_MTK_HWMON=y +CONFIG_CUSTOM_KERNEL_MAGNETOMETER=y +CONFIG_MTK_AKM8963_NEW=y +CONFIG_MTK_BTIF=y +CONFIG_MTK_MD1_SUPPORT=12 +CONFIG_MTK_MD3_SUPPORT=2 +CONFIG_MTK_C2K_LTE_MODE=2 +CONFIG_MTK_IRAT_SUPPORT=y +CONFIG_MTK_C2K_SLOT2_SUPPORT=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_6755=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_GPS=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_GPS_SUPPORT=y +CONFIG_MTK_FMRADIO=y +CONFIG_MTK_FM_CHIP="MT6625_FM" +CONFIG_MTK_ECCCI_DRIVER=y +CONFIG_MTK_ECCCI_C2K=y +CONFIG_MTK_NFC=y +CONFIG_NFC_MT6605=y +CONFIG_MTK_ACCDET=y +CONFIG_ACCDET_EINT_IRQ=y +CONFIG_MTK_DEBUG_LATCH=y +CONFIG_MTK_LASTPC=y +CONFIG_MTK_LASTBUS=y +CONFIG_MTK_DEVAPC_DRIVER=y +CONFIG_MTK_DRAMC=y +CONFIG_MTK_IRTX_PWM_SUPPORT=y +CONFIG_MTK_LEDS=y +CONFIG_USB_MU3D_DRV=y +CONFIG_MTK_SIB_USB_SWITCH=y +CONFIG_USB_MU3D_ONLY_U2_MODE=y +CONFIG_MU3_PHY=y +CONFIG_U3_PHY_AHB_SUPPORT=y +CONFIG_PROJECT_PHY=y +CONFIG_MTK_PWM=y +CONFIG_MTK_RTC=y +CONFIG_MTK_SMI_EXT=y +# CONFIG_USB_MTK_HDRC is not set +CONFIG_MTK_MUSB_QMU_SUPPORT=y +CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y +CONFIG_MTK_AEE_FEATURE=y +CONFIG_MTK_CHIP=y +CONFIG_MTPROF=y +CONFIG_MTK_RAM_CONSOLE=y +CONFIG_MTK_RAM_CONSOLE_USING_SRAM=y +CONFIG_MTK_RAM_CONSOLE_SIZE=0xc00 +CONFIG_MTK_RAM_CONSOLE_ADDR=0x0011D000 +CONFIG_MTK_RAM_CONSOLE_DRAM_SIZE=0x10000 +CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR=0x44400000 +CONFIG_MTK_SCHED_RQAVG_KS=y +CONFIG_MTK_SCHED_RQAVG_US=y +CONFIG_MT_CPU_AFFINITY=y +CONFIG_MT_LOAD_BALANCE_ENHANCEMENT=y +CONFIG_MTK_COMPAT=y +CONFIG_MT_SCHED_INTEROP=y +CONFIG_MTK_CPU_TOPOLOGY=y +CONFIG_MTK_SCHED_CMP=y +CONFIG_MTK_SCHED_CMP_TGS=y +CONFIG_MTK_SCHED_CMP_TGS_WAKEUP=y +CONFIG_SCHED_HMP=y +CONFIG_SCHED_HMP_PRIO_FILTER=y +CONFIG_HMP_TRACER=y +CONFIG_SCHED_HMP_PLUS=y +CONFIG_MTK_SYSENV=y +CONFIG_MICROTRUST_TEE_SUPPORT=y +CONFIG_MTK_WATCHPOINT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_IFB=y +CONFIG_TUN=y +# CONFIG_ETHERNET is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_MTK=y +CONFIG_TOUCHSCREEN_MTK_GT1151=y +CONFIG_GT1151_FIRMWARE="firmware2" +CONFIG_GT1151_CONFIG="config8" +CONFIG_GTP_DRIVER_SEND_CFG=y +CONFIG_GTP_CUSTOM_CFG=y +CONFIG_GTP_HOTKNOT=y +CONFIG_GTP_AUTO_UPDATE=y +CONFIG_GTP_HEADER_FW_UPDATE=y +CONFIG_GTP_CREATE_WR_NODE=y +CONFIG_GTP_POWER_CTRL_SLEEP=y +CONFIG_KEYBOARD_MTK=y +CONFIG_ONEKEY_REBOOT_NORMAL_MODE=y +CONFIG_ONEKEY_REBOOT_OTHER_MODE=y +CONFIG_KPD_PMIC_LPRST_TD=0 +CONFIG_KPD_PWRKEY_USE_PMIC=y +CONFIG_MTK_MRDUMP_KEY=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_MTK_SPI=y +CONFIG_MTK_SMART_BATTERY=y +CONFIG_MTK_KERNEL_POWER_OFF_CHARGING=y +CONFIG_MTK_HAFG_20=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_BACKWARD_COMPATIBLE=y +CONFIG_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_MT_SND_SOC_6750=y +CONFIG_MTK_SPEAKER=y +CONFIG_MTK_HP_ANASWITCH=y +CONFIG_MTK_BTCVSD_ALSA=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_SOUND_PRIME=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_TRANCEVIBRATOR=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_MTK=y +CONFIG_MTK_EMMC_SUPPORT=y +CONFIG_MTK_EMMC_CACHE=y +CONFIG_MTK_EMMC_CQ_SUPPORT=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_SWITCH=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_MTK_ION=y +# CONFIG_ARM_ARCH_TIMER_SUSPEND_NONSTOP is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_CONSOLE_SIZE=0x40000 +CONFIG_PSTORE_PMSG_SIZE=0x10000 +CONFIG_PSTORE_MEM_ADDR=0x44410000 +CONFIG_PSTORE_MEM_SIZE=0xe0000 +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1400 +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=1 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_FAULT_INJECTION=y +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_MTK_SCHED_TRACERS=y +CONFIG_DEBUG_RODATA=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_LIBCRC32C=y diff --git a/drivers/clk/mediatek/clk-mt6755-pg.c b/drivers/clk/mediatek/clk-mt6755-pg.c new file mode 100644 index 0000000000000000000000000000000000000000..e3628e71e4fe9155ed9cb6d6bee7a62d4ba18408 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6755-pg.c @@ -0,0 +1,2344 @@ +/* +* Copyright (c) 2014 MediaTek Inc. +* Author: James Liao +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 +#include + +#include +#include +#include +#include + +#include "clk-mtk-v1.h" +#include "clk-mt6755-pg.h" + +#include + +#define VLTE_SUPPORT +#ifdef VLTE_SUPPORT +/* #include */ +/* #include */ +#endif /* VLTE_SUPPORT */ + +/*#if !defined(MT_CCF_DEBUG) || !defined(MT_CCF_BRINGUP) +#define MT_CCF_DEBUG 0 +#define MT_CCF_BRINGUP 0 +#endif*/ +#define MT_CCF_DEBUG 0 +#define MT_CCF_BRINGUP 1 +#define CHECK_PWR_ST 1 + +#ifndef GENMASK +#define GENMASK(h, l) (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l)) +#endif + +#ifdef CONFIG_ARM64 +#define IOMEM(a) ((void __force __iomem *)((a))) +#endif + +#define clk_readl(addr) readl(addr) +#define clk_writel(val, addr) \ + do { writel(val, addr); wmb(); } while (0) /* sync_write */ +#define clk_setl(mask, addr) clk_writel(clk_readl(addr) | (mask), addr) +#define clk_clrl(mask, addr) clk_writel(clk_readl(addr) & ~(mask), addr) + +#define mt_reg_sync_writel(v, a) \ + do { \ + __raw_writel((v), IOMEM((a))); \ + mb(); /* for mt_reg_sync_writel() */ \ + } while (0) +#define spm_read(addr) __raw_readl(IOMEM(addr)) +#define spm_write(addr, val) mt_reg_sync_writel(val, addr) + +/* + * MTCMOS + */ + +#define STA_POWER_DOWN 0 +#define STA_POWER_ON 1 +#define SUBSYS_PWR_DOWN 0 +#define SUBSYS_PWR_ON 1 +#define PWR_CLK_DIS (1U << 4) +#define PWR_ON_2ND (1U << 3) +#define PWR_ON (1U << 2) +#define PWR_ISO (1U << 1) +#define PWR_RST_B (1U << 0) + +struct subsys; + +struct subsys_ops { + int (*enable)(struct subsys *sys); + int (*disable)(struct subsys *sys); + int (*get_state)(struct subsys *sys); +}; + +struct subsys { + const char *name; + uint32_t sta_mask; + void __iomem *ctl_addr; + uint32_t sram_pdn_bits; + uint32_t sram_pdn_ack_bits; + uint32_t bus_prot_mask; + struct subsys_ops *ops; +}; + +/*static struct subsys_ops general_sys_ops;*/ +static struct subsys_ops MD1_sys_ops; +static struct subsys_ops C2K_sys_ops; +static struct subsys_ops CONN_sys_ops; +static struct subsys_ops MFG_sys_ops; +static struct subsys_ops DIS_sys_ops; +static struct subsys_ops ISP_sys_ops; +static struct subsys_ops VDE_sys_ops; +static struct subsys_ops VEN_sys_ops; +static struct subsys_ops AUD_sys_ops; +/*static struct subsys_ops IFR_sys_ops;*/ +static void __iomem *infracfg_base; +static void __iomem *spm_base; +static void __iomem *infra_base; + +#define INFRACFG_REG(offset) (infracfg_base + offset) +#define SPM_REG(offset) (spm_base + offset) +#define INFRA_REG(offset) (infra_base + offset) + +/************************************** + * for non-CPU MTCMOS + **************************************/ +static DEFINE_SPINLOCK(spm_noncpu_lock); +#define spm_mtcmos_noncpu_lock(flags) spin_lock_irqsave(&spm_noncpu_lock, flags) + +#define spm_mtcmos_noncpu_unlock(flags) spin_unlock_irqrestore(&spm_noncpu_lock, flags) + +/* FIXME: set correct value: S */ +#define POWERON_CONFIG_EN SPM_REG(0x0000) +#define PWR_STATUS SPM_REG(0x0180) /* correct */ +#define PWR_STATUS_2ND SPM_REG(0x0184) /* correct */ + +#define MD1_PWR_CON SPM_REG(0x0320) /* correct */ +#define C2K_PWR_CON SPM_REG(0x0328) /* correct */ +#define CONN_PWR_CON SPM_REG(0x032c) /* correct */ +#define DIS_PWR_CON SPM_REG(0x030c) +#define MFG_PWR_CON SPM_REG(0x0338) +#define ISP_PWR_CON SPM_REG(0x0308) +#define VDE_PWR_CON SPM_REG(0x0300) +#define VEN_PWR_CON SPM_REG(0x0304) +#define PCM_IM_PTR SPM_REG(0x0020) /* correct */ +#define PCM_IM_LEN SPM_REG(0x0024) /* correct */ +#define MD_EXT_BUCK_ISO SPM_REG(0x0390) +#define AUDIO_PWR_CON SPM_REG(0x0314) /* correct */ +#define MFG_ASYNC_PWR_CON SPM_REG(0x0334) /* correct */ +#define IFR_PWR_CON SPM_REG(0x0318) /* correct */ +#define SLEEP_CPU_WAKEUP_EVENT SPM_REG(0x00B0) /* correct */ +#define PCM_PASR_DPD_3 SPM_REG(0x063C) /* correct */ +#define MDSYS_INTF_INFRA_PWR_CON SPM_REG(0x0360) + +#define INFRA_TOPAXI_PROTECTEN INFRACFG_REG(0x0220) /* correct */ +#define INFRA_TOPAXI_PROTECTSTA1 INFRACFG_REG(0x0228) /* correct */ +#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_REG(0x0250) /* correct */ +#define INFRA_TOPAXI_PROTECTSTA1_1 INFRACFG_REG(0x0258) /* correct */ +#define C2K_SPM_CTRL INFRACFG_REG(0x0368) /* correct */ + + +#define INFRA_BUS_IDLE_STA1 INFRA_REG(0x0180) +#define INFRA_BUS_IDLE_STA2 INFRA_REG(0x0184) +#define INFRA_BUS_IDLE_STA3 INFRA_REG(0x0188) +#define INFRA_BUS_IDLE_STA4 INFRA_REG(0x018c) +#define INFRA_BUS_IDLE_STA5 INFRA_REG(0x0190) + + + +#define SPM_PROJECT_CODE 0xb16 +/* MCU/CPU */ +#define PWR_RST_B_BIT BIT(0) +#define PWR_ISO_BIT BIT(1) +#define PWR_ON_BIT BIT(2) +#define PWR_ON_2ND_BIT BIT(3) +#define PWR_CLK_DIS_BIT BIT(4) + +#define MD1_PWR_STA_MASK BIT(0) +#define CONN_PWR_STA_MASK BIT(1) +#define DIS_PWR_STA_MASK BIT(3) +#define MFG_PWR_STA_MASK BIT(4) +#define ISP_PWR_STA_MASK BIT(5) +#define VDE_PWR_STA_MASK BIT(7) +#define VEN_PWR_STA_MASK BIT(21) +#define IFR_PWR_STA_MASK (0x1 << 6) +#define MFG_ASYNC_PWR_STA_MASK BIT(23) +#define AUDIO_PWR_STA_MASK BIT(24) +#define C2K_PWR_STA_MASK BIT(28) +#define MDSYS_INTF_INFRA_PWR_STA_MASK BIT(29) +/* XXX_PWR_CON */ +#define SRAM_PDN (0xf << 8) /* VDEC, VENC, ISP, DISP */ + + + +/* PDN_ACK, all 4b from 12, ref. mtcmos_ctrl2.c */ +#define VDE_SRAM_ACK (0x1 << 12) +#define VEN_SRAM_ACK (0xf << 12) +#define ISP_SRAM_ACK (0x3 << 12) +#define DIS_SRAM_ACK (0x1 << 12) +#define MFG_SRAM_ACK (0x1 << 16) /* jade */ +/* BUS Protect? ref. mtcmos_ctrl2.c, INFRA_TOPAXI_PROTECTEN */ +#define IFR_SRAM_PDN_ACK (0xF << 12) +#define DIS_PROT_MASK ((0x1<<1)) /* bit 1, 6, 16; if bit6 set, MMSYS PDN, access reg will hang, */ +#define MFG_PROT_MASK ((0x1<<21)) +#define MD1_PROT_MASK ((0x1<<16) | (0x1<<17) | (0x1<<18) | (0x1<<19) | (0x1<<20) | (0x1<<21) | (0x1<<28)) +#define MD1_PROT_CHECK_MASK ((0x1<<16) | (0x1<<17) | (0x1<<18) | (0x1<<19) | (0x1<<20) | (0x1<<21)) +#define C2K_PROT_MASK ((0x1<<22) | (0x1<<23) | (0x1<<24)) /* bit 29, 30, 31 */ +#define CONN_PROT_MASK ((0x1<<13) | (0x1<<14))/* bit 2, 8 */ + +#define MDSYS_INTF_INFRA_PROT_MASK ((0x1 << 3) \ + |(0x1 << 4)) +#define CONN_SRAM_PDN (0x1 << 8) +#define MD1_SRAM_PDN (0x1 << 8) +#define MD1_SRAM_PDN_ACK (0x0 << 12) +#define C2K_SRAM_PDN (0x1 << 8) +#define DIS_SRAM_PDN (0x1 << 8) +#define DIS_SRAM_PDN_ACK (0x1 << 12) +#define MFG_SRAM_PDN (0x1 << 8) +#define MFG_SRAM_PDN_ACK (0x1 << 16) +#define ISP_SRAM_PDN (0x3 << 8) +#define ISP_SRAM_PDN_ACK (0x3 << 12) +#define IFR_SRAM_PDN (0xF << 8) +#define IFR_SRAM_PDN_ACK (0xF << 12) +#define VDE_SRAM_PDN (0x1 << 8) +#define VDE_SRAM_PDN_ACK (0x1 << 12) +#define VEN_SRAM_PDN (0xF << 8) +#define VEN_SRAM_PDN_ACK (0xF << 12) +#define AUDIO_SRAM_PDN (0xF << 8) +#define AUDIO_SRAM_PDN_ACK (0xF << 12) +static struct subsys syss[] = /* NR_SYSS */ /* FIXME: set correct value */ +{ + [SYS_MD1] = { + .name = __stringify(SYS_MD1), + .sta_mask = MD1_PWR_STA_MASK, + /* .ctl_addr = NULL, SPM_MD_PWR_CON, */ + .sram_pdn_bits = MD1_SRAM_PDN, + .sram_pdn_ack_bits = 0, /* GENMASK(15, 12), */ + .bus_prot_mask = MD1_PROT_MASK, + .ops = &MD1_sys_ops, + }, + [SYS_MD2] = { + .name = __stringify(SYS_MD2), + .sta_mask = C2K_PWR_STA_MASK, + /*.ctl_addr = NULL, SPM_C2K_PWR_CON, */ + .sram_pdn_bits = C2K_SRAM_PDN, + .sram_pdn_ack_bits = 0, + .bus_prot_mask = C2K_PROT_MASK, + .ops = &C2K_sys_ops, + }, + [SYS_CONN] = { + .name = __stringify(SYS_CONN), + .sta_mask = CONN_PWR_STA_MASK, + /* .ctl_addr = NULL, SPM_CONN_PWR_CON, */ + .sram_pdn_bits = CONN_SRAM_PDN, + .sram_pdn_ack_bits = 0, + .bus_prot_mask = 0, + .ops = &CONN_sys_ops, + }, + [SYS_DIS] = { + .name = __stringify(SYS_DIS), + .sta_mask = DIS_PWR_STA_MASK, + /* .ctl_addr = NULL, SPM_DIS_PWR_CON, */ + .sram_pdn_bits = DIS_SRAM_PDN, + .sram_pdn_ack_bits = DIS_SRAM_ACK, + .bus_prot_mask = DIS_PROT_MASK, + .ops = &DIS_sys_ops, + }, + [SYS_MFG] = { + .name = __stringify(SYS_MFG), + .sta_mask = MFG_PWR_STA_MASK, + /* .ctl_addr = NULL, SPM_MFG_PWR_CON, */ + .sram_pdn_bits = MFG_SRAM_PDN, + .sram_pdn_ack_bits = MFG_SRAM_ACK, + .bus_prot_mask = MFG_PROT_MASK, + .ops = &MFG_sys_ops, + }, + [SYS_ISP] = { + .name = __stringify(SYS_ISP), + .sta_mask = ISP_PWR_STA_MASK, + /* .ctl_addr = NULL, SPM_ISP_PWR_CON, */ + .sram_pdn_bits = ISP_SRAM_PDN, + .sram_pdn_ack_bits = ISP_SRAM_ACK, + .bus_prot_mask = 0, + .ops = &ISP_sys_ops, + }, + [SYS_VDE] = { + .name = __stringify(SYS_VDE), + .sta_mask = VDE_PWR_STA_MASK, + /* .ctl_addr = NULL, SPM_VDE_PWR_CON, */ + .sram_pdn_bits = VDE_SRAM_PDN, + .sram_pdn_ack_bits = VDE_SRAM_ACK, + .bus_prot_mask = 0, + .ops = &VDE_sys_ops, + }, + [SYS_VEN] = { + .name = __stringify(SYS_VEN), + .sta_mask = VEN_PWR_STA_MASK, + /*.ctl_addr = 0, SPM_VEN_PWR_CON, */ + .sram_pdn_bits = VEN_SRAM_PDN, + .sram_pdn_ack_bits = VEN_SRAM_ACK, + .bus_prot_mask = 0, + .ops = &VEN_sys_ops, + }, + + [SYS_AUD] = { + .name = __stringify(SYS_AUD), + .sta_mask = AUDIO_PWR_STA_MASK, + /*.ctl_addr = 0, SPM_VEN_PWR_CON, */ + .sram_pdn_bits = AUDIO_SRAM_PDN, + .sram_pdn_ack_bits = AUDIO_SRAM_PDN_ACK, + .bus_prot_mask = 0, + .ops = &AUD_sys_ops, + }, +#if 0 + [SYS_IFR] = { + .name = __stringify(SYS_IFR), + .sta_mask = IFR_PWR_STA_MASK, + /*.ctl_addr = 0, SPM_VEN_PWR_CON, */ + .sram_pdn_bits = IFR_SRAM_PDN, + .sram_pdn_ack_bits = IFR_SRAM_PDN_ACK, + .bus_prot_mask = 0, + .ops = &IFR_sys_ops, + }, +#endif +}; + +static struct pg_callbacks *g_pgcb; + +struct pg_callbacks *register_pg_callback(struct pg_callbacks *pgcb) +{ + struct pg_callbacks *old_pgcb = g_pgcb; + + g_pgcb = pgcb; + return old_pgcb; +} + +#define _TOPAXI_TIMEOUT_CNT_ 4000 +int spm_topaxi_protect(unsigned int mask_value, int en) +{ + unsigned long flags; + int count = 0; + struct timeval tm_s, tm_e; + unsigned int tm_val = 0; + + do_gettimeofday(&tm_s); + spm_mtcmos_noncpu_lock(flags); + + if (en == 1) { + spm_write(INFRA_TOPAXI_PROTECTEN, spm_read(INFRA_TOPAXI_PROTECTEN) | (mask_value)); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1) & (mask_value)) != (mask_value)) { + count++; + if (count > _TOPAXI_TIMEOUT_CNT_) + break; + } + } else { + spm_write(INFRA_TOPAXI_PROTECTEN, spm_read(INFRA_TOPAXI_PROTECTEN) & ~(mask_value)); + while (spm_read(INFRA_TOPAXI_PROTECTSTA1) & (mask_value)) { + count++; + if (count > _TOPAXI_TIMEOUT_CNT_) + break; + } + } + + spm_mtcmos_noncpu_unlock(flags); + + if (count > _TOPAXI_TIMEOUT_CNT_) { + do_gettimeofday(&tm_e); + tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000000 + (tm_e.tv_usec - tm_s.tv_usec); + pr_err("TOPAXI Bus Protect Timeout Error (%d us)(%d) !!\n", tm_val, count); + pr_err("mask_value = 0x%x (%d)\n", mask_value, en); + pr_err("INFRA_TOPAXI_PROTECTEN = 0x%x\n", clk_readl(INFRA_TOPAXI_PROTECTEN)); + pr_err("INFRA_TOPAXI_PROTECTSTA1 = 0x%x\n", clk_readl(INFRA_TOPAXI_PROTECTSTA1)); + pr_err("INFRA_TOPAXI_PROTECTEN_1 = 0x%x\n", clk_readl(INFRA_TOPAXI_PROTECTEN_1)); + pr_err("INFRA_TOPAXI_PROTECTSTA1_1 = 0x%x\n", clk_readl(INFRA_TOPAXI_PROTECTSTA1_1)); + pr_err("INFRA_BUS_IDLE_STA1 = 0x%x\n", clk_readl(INFRA_BUS_IDLE_STA1)); + pr_err("INFRA_BUS_IDLE_STA2 = 0x%x\n", clk_readl(INFRA_BUS_IDLE_STA2)); + pr_err("INFRA_BUS_IDLE_STA3 = 0x%x\n", clk_readl(INFRA_BUS_IDLE_STA3)); + pr_err("INFRA_BUS_IDLE_STA4 = 0x%x\n", clk_readl(INFRA_BUS_IDLE_STA4)); + pr_err("INFRA_BUS_IDLE_STA5 = 0x%x\n", clk_readl(INFRA_BUS_IDLE_STA5)); + BUG(); + } + return 0; +} + +void reset_infra_md(void) +{ + unsigned long flags; + int count = 0; + u32 infra_topaxi_protecten = 0; + u32 infra_topaxi_protecten_1 = 0; + + spm_mtcmos_noncpu_lock(flags); + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); +/* step.1 */ + infra_topaxi_protecten = spm_read(INFRA_TOPAXI_PROTECTEN); + infra_topaxi_protecten_1 = spm_read(INFRA_TOPAXI_PROTECTEN_1); +/* step.2 */ + spm_write(INFRA_TOPAXI_PROTECTEN_1, + spm_read(INFRA_TOPAXI_PROTECTEN_1) | MD1_PROT_MASK); + spm_write(INFRA_TOPAXI_PROTECTEN_1, + spm_read(INFRA_TOPAXI_PROTECTEN_1) | C2K_PROT_MASK); +/* step.3 */ + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1_1) & MD1_PROT_CHECK_MASK) != + MD1_PROT_CHECK_MASK) { + count++; + if (count > 2000) { + pr_err("Check MDSYS bus protect ready TIMEOUT!\r\n"); + break; + } + } + count = 0; + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1_1) & C2K_PROT_MASK) != C2K_PROT_MASK) { + count++; + if (count > 2000) { + pr_err("Check C2K bus protect ready TIMEOUT!\r\n"); + break; + } + } +/* step.4 */ + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) | MDSYS_INTF_INFRA_PROT_MASK); +/* step.5 */ + count = 0; + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1) & MDSYS_INTF_INFRA_PROT_MASK) != + MDSYS_INTF_INFRA_PROT_MASK) { + count++; + if (count > 2000) { + pr_err("Check INFRA_MD bus protect ready TIMEOUT!\r\n"); + break; + } + } +/* step.6 */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, spm_read(MDSYS_INTF_INFRA_PWR_CON) & ~PWR_RST_B); + spm_write(MDSYS_INTF_INFRA_PWR_CON, spm_read(MDSYS_INTF_INFRA_PWR_CON) | PWR_RST_B); +/* step.7 */ + spm_write(INFRA_TOPAXI_PROTECTEN, infra_topaxi_protecten); + spm_write(INFRA_TOPAXI_PROTECTEN_1, infra_topaxi_protecten_1); + spm_mtcmos_noncpu_unlock(flags); +} + +static struct subsys *id_to_sys(unsigned int id) +{ + return id < NR_SYSS ? &syss[id] : NULL; +} + +/** sync from mt_spm_mtcmos.c for bring up */ +static int spm_mtcmos_ctrl_connsys(int state) +{ + int err = 0; + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off CONN" */ + /* TINFO="Set bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) | CONN_PROT_MASK); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1) & CONN_PROT_MASK) != CONN_PROT_MASK) { + count++; + if (count > 1000) + break; + } +#else + spm_topaxi_protect(CONN_PROT_MASK, 1); +#endif + /* TINFO="Set PWR_ISO = 1" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & CONN_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & CONN_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Finish to turn off CONN" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on CONN" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & CONN_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & CONN_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_RST_B); + /* TINFO="Release bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) & ~CONN_PROT_MASK); + while (spm_read(INFRA_TOPAXI_PROTECTSTA1) & CONN_PROT_MASK) + ; +#else + spm_topaxi_protect(CONN_PROT_MASK, 0); +#endif + /* TINFO="Finish to turn on CONN" */ + } + return err; +} + +static int spm_mtcmos_ctrl_mdsys1(int state) +{ + int err = 0; + int count = 0; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off MD1" */ + /* TINFO="Set bus protect" */ + spm_write(INFRA_TOPAXI_PROTECTEN_1, + spm_read(INFRA_TOPAXI_PROTECTEN_1) | MD1_PROT_MASK); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1_1) & MD1_PROT_CHECK_MASK) != + MD1_PROT_CHECK_MASK) { + count++; + if (count > 1000) + break; + } + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | MD1_SRAM_PDN); + /* TINFO="Set PWR_ISO = 1" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MD1_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MD1_PWR_STA_MASK)) + ; +#endif + + /* TINFO="MD_EXT_BUCK_ISO[0]=1"*/ + spm_write(MD_EXT_BUCK_ISO, spm_read(MD_EXT_BUCK_ISO) | (0x1 << 0)); + /* TINFO="Finish to turn off MD1" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on MD1" */ + /* TINFO="MD_EXT_BUCK_ISO[0]=0"*/ + spm_write(MD_EXT_BUCK_ISO, spm_read(MD_EXT_BUCK_ISO) & ~(0x1 << 0)); + /* TINFO="Set PWR_ON = 1" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MD1_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MD1_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~(0x1 << 8)); + /* TINFO="Release bus protect" */ + spm_write(INFRA_TOPAXI_PROTECTEN_1, + spm_read(INFRA_TOPAXI_PROTECTEN_1) & ~MD1_PROT_MASK); + while (spm_read(INFRA_TOPAXI_PROTECTSTA1_1) & MD1_PROT_CHECK_MASK) + ; + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MD1" */ + } + return err; +} + +static int spm_mtcmos_ctrl_mdsys2(int state) +{ + int err = 0; + int count = 0; + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off C2K" */ + /* TINFO="Set bus protect" */ + spm_write(INFRA_TOPAXI_PROTECTEN_1, + spm_read(INFRA_TOPAXI_PROTECTEN_1) | C2K_PROT_MASK); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1_1) & C2K_PROT_MASK) != C2K_PROT_MASK) { + count++; + if (count > 1000) + break; + } + /* TINFO="Set PWR_ISO = 1" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & C2K_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & C2K_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Finish to turn off C2K" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on C2K" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & C2K_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & C2K_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(C2K_PWR_CON, spm_read(C2K_PWR_CON) | PWR_RST_B); + /* TINFO="Release bus protect" */ + spm_write(INFRA_TOPAXI_PROTECTEN_1, + spm_read(INFRA_TOPAXI_PROTECTEN_1) & ~C2K_PROT_MASK); + while (spm_read(INFRA_TOPAXI_PROTECTSTA1_1) & C2K_PROT_MASK) + ; + /* TINFO="Finish to turn on C2K" */ + } + return err; +} + +int spm_mtcmos_ctrl_mdsys_intf_infra2(int state) +{ + int err = 0; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { +#if 1 + if ((spm_read(PWR_STATUS) & MD1_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MD1_PWR_STA_MASK)) + return 0; + if ((spm_read(PWR_STATUS) & C2K_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & C2K_PWR_STA_MASK)) + return 0; +#endif + /* TINFO="Start to turn off MDSYS_INTF_INFRA" */ + /* TINFO="Set bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) | MDSYS_INTF_INFRA_PROT_MASK); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1) & MDSYS_INTF_INFRA_PROT_MASK) != + MDSYS_INTF_INFRA_PROT_MASK) { + count++; + if (count > 1000) + break; + } +#else + spm_topaxi_protect(MDSYS_INTF_INFRA_PROT_MASK, 1); +#endif + /* TINFO="Set PWR_ISO = 1" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, spm_read(MDSYS_INTF_INFRA_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, + spm_read(MDSYS_INTF_INFRA_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, + spm_read(MDSYS_INTF_INFRA_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, spm_read(MDSYS_INTF_INFRA_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, + spm_read(MDSYS_INTF_INFRA_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MDSYS_INTF_INFRA_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MDSYS_INTF_INFRA_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Finish to turn off MDSYS_INTF_INFRA" */ + } else { /* STA_POWER_ON */ +#if 0 + if ((spm_read(PWR_STATUS) & MDSYS_INTF_INFRA_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MDSYS_INTF_INFRA_PWR_STA_MASK)) + return; +#endif + /* TINFO="Start to turn on MDSYS_INTF_INFRA" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, spm_read(MDSYS_INTF_INFRA_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, + spm_read(MDSYS_INTF_INFRA_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MDSYS_INTF_INFRA_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MDSYS_INTF_INFRA_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, + spm_read(MDSYS_INTF_INFRA_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, spm_read(MDSYS_INTF_INFRA_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MDSYS_INTF_INFRA_PWR_CON, spm_read(MDSYS_INTF_INFRA_PWR_CON) | PWR_RST_B); + /* TINFO="Release bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) & ~MDSYS_INTF_INFRA_PROT_MASK); + while (spm_read(INFRA_TOPAXI_PROTECTSTA1) & MDSYS_INTF_INFRA_PROT_MASK) + ; +#else + spm_topaxi_protect(MDSYS_INTF_INFRA_PROT_MASK, 0); +#endif + /* TINFO="Finish to turn on MDSYS_INTF_INFRA" */ + } + return err; +} + +int spm_mtcmos_ctrl_dis(int state) +{ + int err = 0; + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off DIS" */ + /* TINFO="Set bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, spm_read(INFRA_TOPAXI_PROTECTEN) | DIS_PROT_MASK); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1) & DIS_PROT_MASK) != DIS_PROT_MASK) + ; +#else + spm_topaxi_protect(DIS_PROT_MASK, 1); +#endif + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | DIS_SRAM_PDN); + /* TINFO="Wait until DIS_SRAM_PDN_ACK = 1" */ + while (!(spm_read(DIS_PWR_CON) & DIS_SRAM_PDN_ACK)) + ; + /* Need hf_fmm_ck for SRAM PDN delay IP. */ + /* TINFO="Set PWR_ISO = 1" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & DIS_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & DIS_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Finish to turn off DIS" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on DIS" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & DIS_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & DIS_PWR_STA_MASK)) + ; +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_RST_B); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~(0x1 << 8)); + /* TINFO="Wait until DIS_SRAM_PDN_ACK = 0" */ + while (spm_read(DIS_PWR_CON) & DIS_SRAM_PDN_ACK) + ; + /* Need hf_fmm_ck for SRAM PDN delay IP. */ + /* TINFO="Release bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) & ~DIS_PROT_MASK); + while (spm_read(INFRA_TOPAXI_PROTECTSTA1) & DIS_PROT_MASK) + ; +#else + spm_topaxi_protect(DIS_PROT_MASK, 0); +#endif + /* TINFO="Finish to turn on DIS" */ + } + return err; +} + +int spm_mtcmos_ctrl_mfg2(int state) +{ + int err = 0; + int count = 0; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off MFG" */ + /* TINFO="Set bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, spm_read(INFRA_TOPAXI_PROTECTEN) | MFG_PROT_MASK); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1) & MFG_PROT_MASK) != MFG_PROT_MASK) { + count++; + if (count > 1000) { + pr_err("mfgx: , TOPAXI = 0x%x\n", + spm_read(INFRA_TOPAXI_PROTECTSTA1)); + break; + } + } +#else + spm_topaxi_protect(MFG_PROT_MASK, 1); +#endif + /* TINFO="Set SRAM_PDN = 1" */ + count = 0; + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | MFG_SRAM_PDN); + /* TINFO="Wait until MFG_SRAM_PDN_ACK = 1" */ + while (!(spm_read(MFG_PWR_CON) & MFG_SRAM_PDN_ACK)) { + count++; + if (count > 2000) { + pr_err("mfgx: , MFG_PWR_CON = 0x%08x\n", spm_read(MFG_PWR_CON)); + BUG(); + } + + } + /* Need f_fmfg_core_ck for SRAM PDN delay IP. */ + /* TINFO="Set PWR_ISO = 1" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + count = 0; + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MFG_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MFG_PWR_STA_MASK)) { + /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ + count++; + if (count > 2000) { + pr_err("mfgx: , PWR_STATUS = 0x%08x, 0x%08x\n", + spm_read(PWR_STATUS), spm_read(PWR_STATUS_2ND)); + BUG(); + } + } +#endif + + /* TINFO="Finish to turn off MFG" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on MFG" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MFG_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MFG_PWR_STA_MASK)) { + /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ + count++; +#if 0 + if (count > 1000 && count < 1010) + check_mfg(); +#endif + if (count > 2000) { + pr_err("mfgo: , PWR_STATUS = 0x%08x, 0x%08x\n", + spm_read(PWR_STATUS), spm_read(PWR_STATUS_2ND)); + BUG(); + } + } +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_RST_B); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~(0x1 << 8)); + count = 0; + /* TINFO="Wait until MFG_SRAM_PDN_ACK = 0" */ + while (spm_read(MFG_PWR_CON) & MFG_SRAM_PDN_ACK) { + /* Need f_fmfg_core_ck for SRAM PDN delay IP. */ + count++; + if (count > 2000) { + pr_err("mfgo: , MFG_PWR_CON = 0x%08x\n", spm_read(MFG_PWR_CON)); + BUG(); + } + } + /* TINFO="Release bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) & ~MFG_PROT_MASK); + count = 0; + while (spm_read(INFRA_TOPAXI_PROTECTSTA1) & MFG_PROT_MASK) { + count++; + if (count > 2000) { + pr_err("mfgo: , TOPAXI = 0x%x\n", + spm_read(INFRA_TOPAXI_PROTECTSTA1)); + BUG(); + } + } +#else + spm_topaxi_protect(MFG_PROT_MASK, 0); +#endif + /* TINFO="Finish to turn on MFG" */ + } + + return err; +} + +int spm_mtcmos_ctrl_isp2(int state) +{ + int err = 0; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off ISP" */ + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | ISP_SRAM_PDN); + /* TINFO="Wait until ISP_SRAM_PDN_ACK = 1" */ + while (!(spm_read(ISP_PWR_CON) & ISP_SRAM_PDN_ACK)) + ; + /* Need hf_fmm_ck for SRAM PDN delay IP. */ + /* TINFO="Set PWR_ISO = 1" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & ISP_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & ISP_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Finish to turn off ISP" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on ISP" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & ISP_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & ISP_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_RST_B); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~(0x1 << 8)); + spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~(0x1 << 9)); + /* TINFO="Wait until ISP_SRAM_PDN_ACK = 0" */ + while (spm_read(ISP_PWR_CON) & ISP_SRAM_PDN_ACK) + ; + /* Need hf_fmm_ck for SRAM PDN delay IP. */ + /* TINFO="Finish to turn on ISP" */ + } + return err; +} + +int spm_mtcmos_ctrl_ifr(int state) +{ + int err = 0; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off IFR" */ + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) | IFR_SRAM_PDN); + /* TINFO="Wait until IFR_SRAM_PDN_ACK = 1" */ + while (!(spm_read(IFR_PWR_CON) & IFR_SRAM_PDN_ACK)) + ; + /* SRAM PDN delay IP clock is 26MHz. Print SRAM control and ACK for debug. */ + /* TINFO="Set PWR_ISO = 1" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & IFR_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & IFR_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Finish to turn off IFR" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on IFR" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & IFR_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & IFR_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) | PWR_RST_B); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~(0x1 << 8)); + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~(0x1 << 9)); + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~(0x1 << 10)); + spm_write(IFR_PWR_CON, spm_read(IFR_PWR_CON) & ~(0x1 << 11)); + /* TINFO="Wait until IFR_SRAM_PDN_ACK = 0" */ + while (spm_read(IFR_PWR_CON) & IFR_SRAM_PDN_ACK) + ; + /* SRAM PDN delay IP clock is 26MHz. Print SRAM control and ACK for debug. */ + /* TINFO="Finish to turn on IFR" */ + } + return err; +} + +int spm_mtcmos_ctrl_vde(int state) +{ + int err = 0; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off VDE" */ + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) | VDE_SRAM_PDN); + /* TINFO="Wait until VDE_SRAM_PDN_ACK = 1" */ + while (!(spm_read(VDE_PWR_CON) & VDE_SRAM_PDN_ACK)) + ; + /* Need hf_fmm_ck for SRAM PDN delay IP. */ + /* TINFO="Set PWR_ISO = 1" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & VDE_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & VDE_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Finish to turn off VDE" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on VDE" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & VDE_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & VDE_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) | PWR_RST_B); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(VDE_PWR_CON, spm_read(VDE_PWR_CON) & ~(0x1 << 8)); + /* TINFO="Wait until VDE_SRAM_PDN_ACK = 0" */ + while (spm_read(VDE_PWR_CON) & VDE_SRAM_PDN_ACK) + ; + /* Need hf_fmm_ck for SRAM PDN delay IP. */ + /* TINFO="Finish to turn on VDE" */ + } + return err; +} + +int spm_mtcmos_ctrl_ven(int state) +{ + int err = 0; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off VEN" */ + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) | VEN_SRAM_PDN); + /* TINFO="Wait until VEN_SRAM_PDN_ACK = 1" */ + while (!(spm_read(VEN_PWR_CON) & VEN_SRAM_PDN_ACK)) + ; + /* Need hf_fmm_ck for SRAM PDN delay IP. */ + /* TINFO="Set PWR_ISO = 1" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & VEN_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & VEN_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Finish to turn off VEN" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on VEN" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & VEN_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & VEN_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) | PWR_RST_B); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~(0x1 << 8)); + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~(0x1 << 9)); + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~(0x1 << 10)); + spm_write(VEN_PWR_CON, spm_read(VEN_PWR_CON) & ~(0x1 << 11)); + /* TINFO="Wait until VEN_SRAM_PDN_ACK = 0" */ + while (spm_read(VEN_PWR_CON) & VEN_SRAM_PDN_ACK) + ; + /* Need hf_fmm_ck for SRAM PDN delay IP. */ + /* TINFO="Finish to turn on VEN" */ + } + return err; +} + +int spm_mtcmos_ctrl_mfg_async(int state) +{ + int err = 0; + int count = 0; + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off MFG_ASYNC" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MFG_ASYNC_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MFG_ASYNC_PWR_STA_MASK)) { + /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ + count++; + if (count > 2000) { + pr_err("mfgAx: , PWR_STATUS = 0x%08x, 0x%08x\n", + spm_read(PWR_STATUS), spm_read(PWR_STATUS_2ND)); + BUG(); + } + } +#endif + + /* TINFO="Finish to turn off MFG_ASYNC" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on MFG_ASYNC" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MFG_ASYNC_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MFG_ASYNC_PWR_STA_MASK)) { + /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ + count++; + if (count > 2000) { + pr_err("mfgAo: , PWR_STATUS = 0x%08x, 0x%08x\n", + spm_read(PWR_STATUS), spm_read(PWR_STATUS_2ND)); + BUG(); + } + } +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MFG_ASYNC_PWR_CON, spm_read(MFG_ASYNC_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MFG_ASYNC" */ + } + return err; +} + +int spm_mtcmos_ctrl_audio(int state) +{ + int err = 0; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off AUDIO" */ + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) | AUDIO_SRAM_PDN); + /* TINFO="Wait until AUDIO_SRAM_PDN_ACK = 1" */ + while (!(spm_read(AUDIO_PWR_CON) & AUDIO_SRAM_PDN_ACK)) + ; + /* Need f_f26M_aud_ck for SRAM PDN delay IP. */ + /* TINFO="Set PWR_ISO = 1" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) | PWR_ISO); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_ON = 0" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & AUDIO_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & AUDIO_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ + +#endif + + /* TINFO="Finish to turn off AUDIO" */ + } else { /* STA_POWER_ON */ + /* TINFO="Start to turn on AUDIO" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & AUDIO_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & AUDIO_PWR_STA_MASK)) + ; +/* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ +#endif + + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_ISO = 0" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~PWR_ISO); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) | PWR_RST_B); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~(0x1 << 8)); + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~(0x1 << 9)); + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~(0x1 << 10)); + spm_write(AUDIO_PWR_CON, spm_read(AUDIO_PWR_CON) & ~(0x1 << 11)); + /* TINFO="Wait until AUDIO_SRAM_PDN_ACK = 0" */ + while (spm_read(AUDIO_PWR_CON) & AUDIO_SRAM_PDN_ACK) + ; + /* Need f_f26M_aud_ck for SRAM PDN delay IP. */ + /* TINFO="Finish to turn on AUDIO" */ + } + return err; +} +#if 0 +static void set_bus_protect(int en, uint32_t mask, unsigned long expired) +{ +#if MT_CCF_DEBUG + pr_debug("[CCF] %s: en=%d, mask=%u, expired=%lu: S\n", __func__, + en, mask, expired); +#endif /* MT_CCF_DEBUG */ + if (!mask) + return; + + if (en) { + clk_setl(mask, INFRA_TOPAXI_PROTECTEN); + +#if !DUMMY_REG_TEST + while ((clk_readl(INFRA_TOPAXI_PROTECTSTA1) & mask) != mask) { + if (time_after(jiffies, expired)) { + WARN_ON(1); + break; + } + } +#endif /* !DUMMY_REG_TEST */ + } else { + clk_clrl(mask, INFRA_TOPAXI_PROTECTEN); + +#if !DUMMY_REG_TEST + while (clk_readl(INFRA_TOPAXI_PROTECTSTA1) & mask) { + if (time_after(jiffies, expired)) { + WARN_ON(1); + break; + } + } +#endif /* !DUMMY_REG_TEST */ + } +} + +static int spm_mtcmos_power_off_general_locked(struct subsys *sys, + int wait_power_ack, int ext_pwr_delay) +{ + unsigned long expired = jiffies + HZ / 10; + void __iomem *ctl_addr = sys->ctl_addr; + +/* pr_debug("[CCF] %s: sys=%s, wait_power_ack=%d, ext_pwr_delay=%d\n", + __func__, sys->name, wait_power_ack, ext_pwr_delay);*/ + + /* BUS_PROTECT */ + if (sys->bus_prot_mask) + set_bus_protect(1, sys->bus_prot_mask, expired); + + /* SRAM_PDN */ + clk_setl(sys->sram_pdn_bits, ctl_addr); + + /* wait until SRAM_PDN_ACK all 1 */ +#if !DUMMY_REG_TEST + if (sys->sram_pdn_ack_bits) { + while (((clk_readl(ctl_addr) & sys->sram_pdn_ack_bits) != sys->sram_pdn_ack_bits)) { + if (time_after(jiffies, expired)) { + WARN_ON(1); + break; + } + } + } +#endif /* !DUMMY_REG_TEST */ + + clk_setl(PWR_ISO_BIT, ctl_addr); + clk_clrl(PWR_RST_B_BIT, ctl_addr); + clk_setl(PWR_CLK_DIS_BIT, ctl_addr); + + clk_clrl(PWR_ON_BIT, ctl_addr); + clk_clrl(PWR_ON_2ND_BIT, ctl_addr); + + /* extra delay after power off */ + if (ext_pwr_delay > 0) + udelay(ext_pwr_delay); + + if (wait_power_ack) { + /* wait until PWR_ACK = 0 */ +#if !DUMMY_REG_TEST + while ((clk_readl(PWR_STATUS) & sys->sta_mask) + || (clk_readl(PWR_STATUS_2ND) & sys->sta_mask)) { + if (time_after(jiffies, expired)) { + WARN_ON(1); + break; + } + } +#endif /* !DUMMY_REG_TEST */ + } + + return 0; +} + +static int spm_mtcmos_power_on_general_locked( + struct subsys *sys, int wait_power_ack, int ext_pwr_delay) +{ + unsigned long expired = jiffies + HZ / 10; + void __iomem *ctl_addr = sys->ctl_addr; + +/* pr_debug("[CCF] %s: sys=%s, wait_power_ack=%d, ext_pwr_delay=%d\n", + __func__, sys->name, wait_power_ack, ext_pwr_delay);*/ + + clk_setl(PWR_ON_BIT, ctl_addr); + clk_setl(PWR_ON_2ND_BIT, ctl_addr); + + /* extra delay after power on */ + if (ext_pwr_delay > 0) + udelay(ext_pwr_delay); + + if (wait_power_ack) { + /* wait until PWR_ACK = 1 */ +#if !DUMMY_REG_TEST + while (!(clk_readl(PWR_STATUS) & sys->sta_mask) + || !(clk_readl(PWR_STATUS_2ND) & sys->sta_mask)) { + if (time_after(jiffies, expired)) { + WARN_ON(1); + break; + } + } +#endif /* !DUMMY_REG_TEST */ + } + + clk_clrl(PWR_CLK_DIS_BIT, ctl_addr); + clk_clrl(PWR_ISO_BIT, ctl_addr); + clk_setl(PWR_RST_B_BIT, ctl_addr); + + /* SRAM_PDN */ + clk_clrl(sys->sram_pdn_bits, ctl_addr); + + /* wait until SRAM_PDN_ACK all 0 */ +#if !DUMMY_REG_TEST + if (sys->sram_pdn_ack_bits) { + while (sys->sram_pdn_ack_bits && (clk_readl(ctl_addr) & sys->sram_pdn_ack_bits)) { + if (time_after(jiffies, expired)) { + WARN_ON(1); + break; + } + } + } +#endif /* !DUMMY_REG_TEST */ + + /* BUS_PROTECT */ + if (sys->bus_prot_mask) + set_bus_protect(0, sys->bus_prot_mask, expired); + + return 0; +} +#endif +/*static int general_sys_enable_op(struct subsys *sys) +{ + return spm_mtcmos_power_on_general_locked(sys, 1, 0); +} + +static int general_sys_disable_op(struct subsys *sys) +{ + return spm_mtcmos_power_off_general_locked(sys, 1, 0); +}*/ + +static int MD1_sys_enable_op(struct subsys *sys) +{ + spm_mtcmos_ctrl_mdsys_intf_infra2(STA_POWER_ON); + return spm_mtcmos_ctrl_mdsys1(STA_POWER_ON); +} +static int C2K_sys_enable_op(struct subsys *sys) +{ + spm_mtcmos_ctrl_mdsys_intf_infra2(STA_POWER_ON); + return spm_mtcmos_ctrl_mdsys2(STA_POWER_ON); +} +static int CONN_sys_enable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_connsys(STA_POWER_ON); +} +static int MFG_sys_enable_op(struct subsys *sys) +{ + spm_mtcmos_ctrl_mfg_async(STA_POWER_ON); + return spm_mtcmos_ctrl_mfg2(STA_POWER_ON); +} +static int DIS_sys_enable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_dis(STA_POWER_ON); +} +static int ISP_sys_enable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_isp2(STA_POWER_ON); +} +static int VDE_sys_enable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_vde(STA_POWER_ON); +} +static int VEN_sys_enable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_ven(STA_POWER_ON); +} + +static int AUD_sys_enable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_audio(STA_POWER_ON); +} +#if 0 +static int IFR_sys_enable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_ifr(STA_POWER_ON); +} +#endif +static int MD1_sys_disable_op(struct subsys *sys) +{ + spm_mtcmos_ctrl_mdsys1(STA_POWER_DOWN); + return spm_mtcmos_ctrl_mdsys_intf_infra2(STA_POWER_DOWN); +} +static int C2K_sys_disable_op(struct subsys *sys) +{ + spm_mtcmos_ctrl_mdsys2(STA_POWER_DOWN); + return spm_mtcmos_ctrl_mdsys_intf_infra2(STA_POWER_DOWN); +} +static int CONN_sys_disable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_connsys(STA_POWER_DOWN); +} +static int MFG_sys_disable_op(struct subsys *sys) +{ + spm_mtcmos_ctrl_mfg2(STA_POWER_DOWN); + return spm_mtcmos_ctrl_mfg_async(STA_POWER_DOWN); + /*return 0;*/ +} +static int DIS_sys_disable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_dis(STA_POWER_DOWN); + /*return 0;*/ +} +static int ISP_sys_disable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_isp2(STA_POWER_DOWN); +} +static int VDE_sys_disable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_vde(STA_POWER_DOWN); +} +static int VEN_sys_disable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_ven(STA_POWER_DOWN); +} + +static int AUD_sys_disable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_audio(STA_POWER_DOWN); +} +#if 0 +static int IFR_sys_disable_op(struct subsys *sys) +{ + return spm_mtcmos_ctrl_ifr(STA_POWER_DOWN); +} +#endif +static int sys_get_state_op(struct subsys *sys) +{ + unsigned int sta = clk_readl(PWR_STATUS); + unsigned int sta_s = clk_readl(PWR_STATUS_2ND); + + return (sta & sys->sta_mask) && (sta_s & sys->sta_mask); +} + +/*static struct subsys_ops general_sys_ops = { + .enable = general_sys_enable_op, + .disable = general_sys_disable_op, + .get_state = sys_get_state_op, +};*/ + +static struct subsys_ops MD1_sys_ops = { + .enable = MD1_sys_enable_op, + .disable = MD1_sys_disable_op, + .get_state = sys_get_state_op, +}; + +static struct subsys_ops C2K_sys_ops = { + .enable = C2K_sys_enable_op, + .disable = C2K_sys_disable_op, + .get_state = sys_get_state_op, +}; + +static struct subsys_ops CONN_sys_ops = { + .enable = CONN_sys_enable_op, + .disable = CONN_sys_disable_op, + .get_state = sys_get_state_op, +}; + +static struct subsys_ops MFG_sys_ops = { + .enable = MFG_sys_enable_op, + .disable = MFG_sys_disable_op, + .get_state = sys_get_state_op, +}; + +static struct subsys_ops DIS_sys_ops = { + .enable = DIS_sys_enable_op, + .disable = DIS_sys_disable_op, + .get_state = sys_get_state_op, +}; + +static struct subsys_ops ISP_sys_ops = { + .enable = ISP_sys_enable_op, + .disable = ISP_sys_disable_op, + .get_state = sys_get_state_op, +}; + +static struct subsys_ops VDE_sys_ops = { + .enable = VDE_sys_enable_op, + .disable = VDE_sys_disable_op, + .get_state = sys_get_state_op, +}; + +static struct subsys_ops VEN_sys_ops = { + .enable = VEN_sys_enable_op, + .disable = VEN_sys_disable_op, + .get_state = sys_get_state_op, +}; +static struct subsys_ops AUD_sys_ops = { + .enable = AUD_sys_enable_op, + .disable = AUD_sys_disable_op, + .get_state = sys_get_state_op, +}; +/*static struct subsys_ops IFR_sys_ops = { + .enable = IFR_sys_enable_op, + .disable = IFR_sys_disable_op, + .get_state = sys_get_state_op, +};*/ + + +static int subsys_is_on(enum subsys_id id) +{ + int r; + struct subsys *sys = id_to_sys(id); + + BUG_ON(!sys); + + r = sys->ops->get_state(sys); + +#if MT_CCF_DEBUG + pr_debug("[CCF] %s:%d, sys=%s, id=%d\n", __func__, r, sys->name, id); +#endif /* MT_CCF_DEBUG */ + + return r; +} + +static int enable_subsys(enum subsys_id id) +{ + int r; + unsigned long flags; + struct subsys *sys = id_to_sys(id); + + BUG_ON(!sys); + +#if 0 /*MT_CCF_BRINGUP */ +/* pr_debug("[CCF] %s: sys=%s, id=%d\n", __func__, sys->name, id);*/ + switch (id) { + case SYS_MD1: +#ifdef VLTE_SUPPORT /* Workaround is handled by ccci */ + /* mt_set_gpio_out(GPIO_LTE_VSRAM_EXT_POWER_EN_PIN,1); + pmic_config_interface(0x04D6, 0x1, 0x1, 0); + udelay(200); */ +#endif /* VLTE_SUPPORT */ + spm_mtcmos_ctrl_mdsys_intf_infra2(STA_POWER_ON); + spm_mtcmos_ctrl_mdsys1(STA_POWER_ON); + break; + case SYS_MD2: + spm_mtcmos_ctrl_mdsys_intf_infra2(STA_POWER_ON); + spm_mtcmos_ctrl_mdsys2(STA_POWER_ON); + break; + case SYS_CONN: + spm_mtcmos_ctrl_connsys(STA_POWER_ON); + break; + default: + break; + } + return 0; +#endif /* MT_CCF_BRINGUP */ + + mtk_clk_lock(flags); + +#if CHECK_PWR_ST + if (sys->ops->get_state(sys) == SUBSYS_PWR_ON) { + mtk_clk_unlock(flags); + return 0; + } +#endif /* CHECK_PWR_ST */ + + r = sys->ops->enable(sys); + WARN_ON(r); + + mtk_clk_unlock(flags); + + if (g_pgcb && g_pgcb->after_on) + g_pgcb->after_on(id); + + return r; +} + +static int disable_subsys(enum subsys_id id) +{ + int r; + unsigned long flags; + struct subsys *sys = id_to_sys(id); + + BUG_ON(!sys); + +#if 0 /*MT_CCF_BRINGUP */ +/* pr_debug("[CCF] %s: sys=%s, id=%d\n", __func__, sys->name, id);*/ + switch (id) { + case SYS_DIS: + return 0; + default: + break; + } +#endif /* MT_CCF_BRINGUP */ + + /* TODO: check all clocks related to this subsys are off */ + /* could be power off or not */ + + if (g_pgcb && g_pgcb->before_off) + g_pgcb->before_off(id); + + mtk_clk_lock(flags); + +#if CHECK_PWR_ST + if (sys->ops->get_state(sys) == SUBSYS_PWR_DOWN) { + mtk_clk_unlock(flags); + return 0; + } +#endif /* CHECK_PWR_ST */ + + r = sys->ops->disable(sys); + WARN_ON(r); + + mtk_clk_unlock(flags); + + return r; +} + +/* + * power_gate + */ + +struct mt_power_gate { + struct clk_hw hw; + struct clk *pre_clk; + enum subsys_id pd_id; +}; + +#define to_power_gate(_hw) container_of(_hw, struct mt_power_gate, hw) + +static int pg_enable(struct clk_hw *hw) +{ + struct mt_power_gate *pg = to_power_gate(hw); + +#if MT_CCF_DEBUG + pr_debug("[CCF] %s: sys=%s, pd_id=%u\n", __func__, + __clk_get_name(hw->clk), pg->pd_id); +#endif /* MT_CCF_DEBUG */ + + return enable_subsys(pg->pd_id); +} + +static void pg_disable(struct clk_hw *hw) +{ + struct mt_power_gate *pg = to_power_gate(hw); + +#if MT_CCF_DEBUG + pr_debug("[CCF] %s: sys=%s, pd_id=%u\n", __func__, + __clk_get_name(hw->clk), pg->pd_id); +#endif /* MT_CCF_DEBUG */ + + disable_subsys(pg->pd_id); +} + +static int pg_is_enabled(struct clk_hw *hw) +{ + struct mt_power_gate *pg = to_power_gate(hw); +#if 0 /*MT_CCF_BRINGUP */ + return 1; +#endif /* MT_CCF_BRINGUP */ + + return subsys_is_on(pg->pd_id); +} + +int pg_prepare(struct clk_hw *hw) +{ + int r; + struct mt_power_gate *pg = to_power_gate(hw); + +#if MT_CCF_DEBUG + pr_debug("[CCF] %s: sys=%s, pre_sys=%s\n", __func__, + __clk_get_name(hw->clk), + pg->pre_clk ? __clk_get_name(pg->pre_clk) : ""); +#endif /* MT_CCF_DEBUG */ + + if (pg->pre_clk) { + r = clk_prepare_enable(pg->pre_clk); + if (r) + return r; + } + + return pg_enable(hw); + +} + +void pg_unprepare(struct clk_hw *hw) +{ + struct mt_power_gate *pg = to_power_gate(hw); + +#if MT_CCF_DEBUG + pr_debug("[CCF] %s: clk=%s, pre_clk=%s\n", __func__, + __clk_get_name(hw->clk), + pg->pre_clk ? __clk_get_name(pg->pre_clk) : ""); +#endif /* MT_CCF_DEBUG */ + + pg_disable(hw); + + if (pg->pre_clk) + clk_disable_unprepare(pg->pre_clk); +} + +static const struct clk_ops mt_power_gate_ops = { + .prepare = pg_prepare, + .unprepare = pg_unprepare, + .is_enabled = pg_is_enabled, +}; + +struct clk *mt_clk_register_power_gate( + const char *name, + const char *parent_name, + struct clk *pre_clk, + enum subsys_id pd_id) +{ + struct mt_power_gate *pg; + struct clk *clk; + struct clk_init_data init; + + pg = kzalloc(sizeof(*pg), GFP_KERNEL); + if (!pg) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = CLK_IGNORE_UNUSED; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.ops = &mt_power_gate_ops; + + pg->pre_clk = pre_clk; + pg->pd_id = pd_id; + pg->hw.init = &init; + + clk = clk_register(NULL, &pg->hw); + if (IS_ERR(clk)) + kfree(pg); + + return clk; +} + +#define pg_md1 "pg_md1" +#define pg_md2 "pg_md2" +#define pg_conn "pg_conn" +#define pg_dis "pg_dis" +#define pg_mfg "pg_mfg" +#define pg_isp "pg_isp" +#define pg_vde "pg_vde" +#define pg_ven "pg_ven" +#define pg_aud "pg_aud" +#define pg_ifr "pg_ifr" + +/* FIXME: set correct value: S */ +#define md_sel "md_sel" +#define conn_sel "conn_sel" +#define mm_sel "mm_sel" +#define vdec_sel "vdec_sel" +#define venc_sel "venc_sel" +#define mfg_sel "mfg_sel" +/* FIXME: set correct value: E */ + +struct mtk_power_gate { + int id; + const char *name; + const char *parent_name; + const char *pre_clk_name; + enum subsys_id pd_id; +}; + +#define PGATE(_id, _name, _parent, _pre_clk, _pd_id) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .pre_clk_name = _pre_clk, \ + .pd_id = _pd_id, \ + } + +/* FIXME: all values needed to be verified */ +struct mtk_power_gate scp_clks[] __initdata = { + PGATE(SCP_SYS_MD1, pg_md1, NULL, NULL, SYS_MD1), + PGATE(SCP_SYS_MD2, pg_md2, NULL, NULL, SYS_MD2), + PGATE(SCP_SYS_CONN, pg_conn, NULL, NULL, SYS_CONN), + PGATE(SCP_SYS_DIS, pg_dis, NULL, mm_sel, SYS_DIS), + PGATE(SCP_SYS_MFG, pg_mfg, NULL, mfg_sel, SYS_MFG), + PGATE(SCP_SYS_ISP, pg_isp, NULL, NULL, SYS_ISP), + PGATE(SCP_SYS_VDE, pg_vde, NULL, vdec_sel, SYS_VDE), + PGATE(SCP_SYS_VEN, pg_ven, NULL, NULL, SYS_VEN), + PGATE(SCP_SYS_AUD, pg_aud, NULL, NULL, SYS_AUD), +}; + +static void __init init_clk_scpsys( + void __iomem *infracfg_reg, + void __iomem *spm_reg, + void __iomem *infra_reg, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + struct clk *pre_clk; + + infracfg_base = infracfg_reg; + spm_base = spm_reg; + infra_base = infra_reg; + + syss[SYS_MD1].ctl_addr = MD1_PWR_CON; + syss[SYS_MD2].ctl_addr = C2K_PWR_CON; + syss[SYS_CONN].ctl_addr = CONN_PWR_CON; + syss[SYS_DIS].ctl_addr = DIS_PWR_CON; + syss[SYS_MFG].ctl_addr = MFG_PWR_CON; + syss[SYS_ISP].ctl_addr = ISP_PWR_CON; + syss[SYS_VDE].ctl_addr = VDE_PWR_CON; + syss[SYS_VEN].ctl_addr = VEN_PWR_CON; + + for (i = 0; i < ARRAY_SIZE(scp_clks); i++) { + struct mtk_power_gate *pg = &scp_clks[i]; + + pre_clk = pg->pre_clk_name ? + __clk_lookup(pg->pre_clk_name) : NULL; + + clk = mt_clk_register_power_gate(pg->name, pg->parent_name, + pre_clk, pg->pd_id); + + if (IS_ERR(clk)) { + pr_err("[CCF] %s: Failed to register clk %s: %ld\n", + __func__, pg->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[pg->id] = clk; + +#if MT_CCF_DEBUG + pr_debug("[CCF] %s: pgate %3d: %s\n", __func__, i, pg->name); +#endif /* MT_CCF_DEBUG */ + } +} + +/* + * device tree support + */ + +/* TODO: remove this function */ +static struct clk_onecell_data *alloc_clk_data(unsigned int clk_num) +{ + int i; + struct clk_onecell_data *clk_data; + + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return NULL; + + clk_data->clks = kcalloc(clk_num, sizeof(struct clk *), GFP_KERNEL); + if (!clk_data->clks) { + kfree(clk_data); + return NULL; + } + + clk_data->clk_num = clk_num; + + for (i = 0; i < clk_num; ++i) + clk_data->clks[i] = ERR_PTR(-ENOENT); + + return clk_data; +} + +/* TODO: remove this function */ +static void __iomem *get_reg(struct device_node *np, int index) +{ +#if DUMMY_REG_TEST + return kzalloc(PAGE_SIZE, GFP_KERNEL); +#else + return of_iomap(np, index); +#endif +} + +static void __init mt_scpsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *infracfg_reg; + void __iomem *spm_reg; + int r; + void __iomem *infra_reg; + struct device_node *node2; + + node2 = of_find_compatible_node(NULL, NULL, "mediatek,infracfg"); + if (!node2) + pr_err("[infracfg] find node failed\n"); + infra_reg = of_iomap(node, 0); + if (!infra_reg) + pr_err("[infracfg] base failed\n"); + + infracfg_reg = get_reg(node, 0); + spm_reg = get_reg(node, 1); + + if (!infracfg_reg || !spm_reg) { + pr_err("clk-pg-mt6755: missing reg\n"); + return; + } + +/* pr_debug("[CCF] %s: sys: %s, reg: 0x%p, 0x%p\n", + __func__, node->name, infracfg_reg, spm_reg);*/ + + clk_data = alloc_clk_data(SCP_NR_SYSS); + + init_clk_scpsys(infracfg_reg, spm_reg, infra_reg, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("[CCF] %s:could not register clock provide\n", __func__); + + /* subsys init: per modem owner request, disable modem power first */ + disable_subsys(SYS_MD1); + disable_subsys(SYS_MD2); + spm_mtcmos_ctrl_mfg_async(STA_POWER_ON); + spm_mtcmos_ctrl_mfg2(STA_POWER_ON); +} +CLK_OF_DECLARE(mtk_pg_regs, "mediatek,mt6755-scpsys", mt_scpsys_init); +void subsys_if_on(void) +{ + unsigned int sta = spm_read(PWR_STATUS); + unsigned int sta_s = spm_read(PWR_STATUS_2ND); + + if ((sta & (1U << 0)) && (sta_s & (1U << 0))) + pr_err("suspend warning: SYS_MD1 is on!!!\n"); + + if ((sta & (1U << 1)) && (sta_s & (1U << 1))) + pr_err("suspend warning: SYS_CONN is on!!!\n"); + + if ((sta & (1U << 3)) && (sta_s & (1U << 3))) + pr_err("suspend warning: SYS_DIS is on!!!\n"); + + if ((sta & (1U << 4)) && (sta_s & (1U << 4))) + pr_err("suspend warning: SYS_MFG is on!!!\n"); + + if ((sta & (1U << 5)) && (sta_s & (1U << 5))) + pr_err("suspend warning: SYS_ISP is on!!!\n"); + + if ((sta & (1U << 7)) && (sta_s & (1U << 7))) + pr_err("suspend warning: SYS_VDE is on!!!\n"); + + if ((sta & (1U << 21)) && (sta_s & (1U << 21))) + pr_err("suspend warning: SYS_VEN is on!!!\n"); + + if ((sta & (1U << 24)) && (sta_s & (1U << 24))) + pr_err("suspend warning: SYS_AUD is on!!!\n"); + + if ((sta & (1U << 23)) && (sta_s & (1U << 23))) + pr_err("suspend warning: SYS_MFG_ASYNC is on!!!\n"); + + if ((sta & (1U << 28)) && (sta_s & (1U << 28))) + pr_err("suspend warning: SYS_C2K is on!!!\n"); +} + +#if CLK_DEBUG + +/* + * debug / unit test + */ + +#include +#include +#include +#include + +static char last_cmd[128] = "null"; + +static int test_pg_dump_regs(struct seq_file *s, void *v) +{ + int i; + + for (i = 0; i < NR_SYSS; i++) { + if (!syss[i].ctl_addr) + continue; + + seq_printf(s, "%10s: [0x%p]: 0x%08x\n", syss[i].name, + syss[i].ctl_addr, clk_readl(syss[i].ctl_addr)); + } + + return 0; +} + +static void dump_pg_state(const char *clkname, struct seq_file *s) +{ + struct clk *c = __clk_lookup(clkname); + struct clk *p = IS_ERR_OR_NULL(c) ? NULL : __clk_get_parent(c); + + if (IS_ERR_OR_NULL(c)) { + seq_printf(s, "[%17s: NULL]\n", clkname); + return; + } + + seq_printf(s, "[%17s: %3s, %3d, %3d, %10ld, %17s]\n", + __clk_get_name(c), + __clk_is_enabled(c) ? "ON" : "off", + __clk_get_prepare_count(c), + __clk_get_enable_count(c), + __clk_get_rate(c), + p ? __clk_get_name(p) : ""); + + clk_put(c); +} + +static int test_pg_dump_state_all(struct seq_file *s, void *v) +{ + static const char * const clks[] = { + pg_md1, + pg_md2, + pg_conn, + pg_dis, + pg_mfg, + pg_isp, + pg_vde, + pg_ven, + }; + + int i; + +/* pr_debug("\n");*/ + for (i = 0; i < ARRAY_SIZE(clks); i++) + dump_pg_state(clks[i], s); + + return 0; +} + +static struct { + const char *name; + struct clk *clk; +} g_clks[] = { + {.name = pg_md1}, + {.name = pg_vde}, + {.name = pg_ven}, + {.name = pg_mfg}, +}; + +static int test_pg_1(struct seq_file *s, void *v) +{ + int i; + +/* pr_debug("\n");*/ + + for (i = 0; i < ARRAY_SIZE(g_clks); i++) { + g_clks[i].clk = __clk_lookup(g_clks[i].name); + if (IS_ERR_OR_NULL(g_clks[i].clk)) { + seq_printf(s, "clk_get(%s): NULL\n", + g_clks[i].name); + continue; + } + + clk_prepare_enable(g_clks[i].clk); + seq_printf(s, "clk_prepare_enable(%s)\n", + __clk_get_name(g_clks[i].clk)); + } + + return 0; +} + +static int test_pg_2(struct seq_file *s, void *v) +{ + int i; + +/* pr_debug("\n");*/ + + for (i = 0; i < ARRAY_SIZE(g_clks); i++) { + if (IS_ERR_OR_NULL(g_clks[i].clk)) { + seq_printf(s, "(%s).clk: NULL\n", + g_clks[i].name); + continue; + } + + seq_printf(s, "clk_disable_unprepare(%s)\n", + __clk_get_name(g_clks[i].clk)); + clk_disable_unprepare(g_clks[i].clk); + clk_put(g_clks[i].clk); + } + + return 0; +} + +static int test_pg_show(struct seq_file *s, void *v) +{ + static const struct { + int (*fn)(struct seq_file *, void *); + const char *cmd; + } cmds[] = { + {.cmd = "dump_regs", .fn = test_pg_dump_regs}, + {.cmd = "dump_state", .fn = test_pg_dump_state_all}, + {.cmd = "1", .fn = test_pg_1}, + {.cmd = "2", .fn = test_pg_2}, + }; + + int i; + +/* pr_debug("last_cmd: %s\n", last_cmd);*/ + + for (i = 0; i < ARRAY_SIZE(cmds); i++) { + if (strcmp(cmds[i].cmd, last_cmd) == 0) + return cmds[i].fn(s, v); + } + + return 0; +} + +static int test_pg_open(struct inode *inode, struct file *file) +{ + return single_open(file, test_pg_show, NULL); +} + +static ssize_t test_pg_write( + struct file *file, + const char __user *buffer, + size_t count, + loff_t *data) +{ + char desc[sizeof(last_cmd)]; + int len = 0; + +/* pr_debug("count: %zu\n", count);*/ + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + strcpy(last_cmd, desc); + if (last_cmd[len - 1] == '\n') + last_cmd[len - 1] = 0; + + return count; +} + +static const struct file_operations test_pg_fops = { + .owner = THIS_MODULE, + .open = test_pg_open, + .read = seq_read, + .write = test_pg_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init debug_init(void) +{ + static int init; + struct proc_dir_entry *entry; + +/* pr_debug("init: %d\n", init);*/ + + if (init) + return 0; + + ++init; + + entry = proc_create("test_pg", 0, 0, &test_pg_fops); + if (!entry) + return -ENOMEM; + + ++init; + return 0; +} + +static void __exit debug_exit(void) +{ + remove_proc_entry("test_pg", NULL); +} + +module_init(debug_init); +module_exit(debug_exit); + +#endif /* CLK_DEBUG */ diff --git a/drivers/clk/mediatek/clk-mt6755-pg.h b/drivers/clk/mediatek/clk-mt6755-pg.h new file mode 100644 index 0000000000000000000000000000000000000000..4755c6a4abb919c8283ec2408fed59bc0a5358ae --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6755-pg.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DRV_CLK_MT6755_PG_H +#define __DRV_CLK_MT6755_PG_H + +enum subsys_id { + SYS_MD1 = 0, + SYS_MD2 = 1, + SYS_CONN = 2, + SYS_DIS = 3, + SYS_MFG = 4, + SYS_ISP = 5, + SYS_VDE = 6, + SYS_VEN = 7, + SYS_AUD = 8, + NR_SYSS = 9, +}; + +struct pg_callbacks { + void (*before_off)(enum subsys_id sys); + void (*after_on)(enum subsys_id sys); +}; + +/* register new pg_callbacks and return previous pg_callbacks. */ +extern struct pg_callbacks *register_pg_callback(struct pg_callbacks *pgcb); +extern int spm_topaxi_protect(unsigned int mask_value, int en); +extern void reset_infra_md(void); +#endif /* __DRV_CLK_MT6755_PG_H */ diff --git a/drivers/clk/mediatek/clk-mt6755-pll.c b/drivers/clk/mediatek/clk-mt6755-pll.c new file mode 100644 index 0000000000000000000000000000000000000000..33e5ee8042d6e926bcc50a13e3a5b8540dea98a2 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6755-pll.c @@ -0,0 +1,1075 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include "clk-mtk-v1.h" +#include "clk-pll-v1.h" +#include "clk-mt6755-pll.h" + +/*#if !defined(MT_CCF_DEBUG) || !defined(MT_CCF_BRINGUP) +#define MT_CCF_DEBUG 1 +#define MT_CCF_BRINGUP 0 +#endif*/ +#define MT_CCF_DEBUG 0 +#define MT_CCF_BRINGUP 0 +#ifndef GENMASK +#define GENMASK(h, l) (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l)) +#endif + +/* + * clk_pll + */ + +#define PLL_BASE_EN BIT(0) +#define PLL_PWR_ON BIT(0) +#define PLL_ISO_EN BIT(1) +#define PLL_PCW_CHG BIT(31) +#define RST_BAR_MASK BIT(24) +#define AUDPLL_TUNER_EN BIT(31) +#define ULPOSC_EN BIT(0) +#define ULPOSC_RST BIT(1) +#define ULPOSC_CG_EN BIT(2) + + +static const u32 pll_posdiv_map[8] = { 1, 2, 4, 8, 16, 16, 16, 16 }; + +static u32 calc_pll_vco_freq( + u32 fin, + u32 pcw, + u32 vcodivsel, + u32 prediv, + u32 pcwfbits) +{ + /* vco = (fin * pcw * vcodivsel / prediv) >> pcwfbits; */ + u64 vco = fin; + u8 c = 0; + + vco = vco * pcw * vcodivsel; + do_div(vco, prediv); + + if (vco & GENMASK(pcwfbits - 1, 0)) + c = 1; + + vco >>= pcwfbits; + + if (c) + ++vco; + + return (u32)vco; +} + +static u32 freq_limit(u32 freq) +{ + static const u64 freq_max = 3000UL * 1000 * 1000; /* 3000 MHz */ + static const u32 freq_min = 1000 * 1000 * 1000 / 16; /* 62.5 MHz */ + + if (freq <= freq_min) + freq = freq_min + 16; + else if (freq > freq_max) + freq = freq_max; + + return freq; +} + +static int calc_pll_freq_cfg( + u32 *pcw, + u32 *postdiv_idx, + u32 freq, + u32 fin, + int pcwfbits) +{ + static const u64 freq_max = 3000UL * 1000 * 1000; /* 3000 MHz */ + static const u64 freq_min = 1000 * 1000 * 1000; /* 1000 MHz */ + static const u64 postdiv[] = { 1, 2, 4, 8, 16 }; + u64 n_info; + u32 idx; + +/* pr_debug("freq: %u\n", freq);*/ + + /* search suitable postdiv */ + for (idx = *postdiv_idx; + idx < ARRAY_SIZE(postdiv) && postdiv[idx] * freq <= freq_min; + idx++) + ; + + if (idx >= ARRAY_SIZE(postdiv)) + return -EINVAL; /* freq is out of range (too low) */ + else if (postdiv[idx] * freq > freq_max) + return -EINVAL; /* freq is out of range (too high) */ + + /* n_info = freq * postdiv / 26MHz * 2^pcwfbits */ + n_info = (postdiv[idx] * freq) << pcwfbits; + do_div(n_info, fin); + + *postdiv_idx = idx; + *pcw = (u32)n_info; + + return 0; +} + +static int clk_pll_is_enabled(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + int r; +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 1; +#endif /* MT_CCF_BRINGUP */ + + r = (readl_relaxed(pll->base_addr) & PLL_BASE_EN) != 0; + +#if MT_CCF_DEBUG +/* pr_debug("[CCF] %s:%d: %s\n", __func__, r, __clk_get_name(hw->clk));*/ +#endif /* MT_CCF_DEBUG */ + + return r; +} + +static int clk_pll_enable(struct clk_hw *hw) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + +#if MT_CCF_DEBUG +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ +#endif /* MT_CCF_DEBUG */ +#if MT_CCF_BRINGUP + return 0; +#endif /* MT_CCF_BRINGUP */ + + mtk_clk_lock(flags); + + r = readl_relaxed(pll->pwr_addr) | PLL_PWR_ON; + writel_relaxed(r, pll->pwr_addr); + wmb(); /* sync write before delay */ + udelay(1); + + r = readl_relaxed(pll->pwr_addr) & ~PLL_ISO_EN; + writel_relaxed(r , pll->pwr_addr); + wmb(); /* sync write before delay */ + udelay(1); + + r = readl_relaxed(pll->base_addr) | pll->en_mask; + writel_relaxed(r, pll->base_addr); + wmb(); /* sync write before delay */ + udelay(20); + + if (pll->flags & HAVE_RST_BAR) { + r = readl_relaxed(pll->base_addr) | RST_BAR_MASK; + writel_relaxed(r, pll->base_addr); + } + + mtk_clk_unlock(flags); + + return 0; +} + +static void clk_pll_disable(struct clk_hw *hw) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + +#if MT_CCF_DEBUG +/* pr_debug("[CCF] %s: %s: flags=%u, PLL_AO: %d\n", __func__, + __clk_get_name(hw->clk), pll->flags, !!(pll->flags & PLL_AO));*/ +#endif /* MT_CCF_DEBUG */ +#if MT_CCF_BRINGUP + return; +#endif /* MT_CCF_BRINGUP */ + + if (pll->flags & PLL_AO) + return; + + mtk_clk_lock(flags); + + if (pll->flags & HAVE_RST_BAR) { + r = readl_relaxed(pll->base_addr) & ~RST_BAR_MASK; + writel_relaxed(r, pll->base_addr); + } + + r = readl_relaxed(pll->base_addr) & ~PLL_BASE_EN; + writel_relaxed(r, pll->base_addr); + + r = readl_relaxed(pll->pwr_addr) | PLL_ISO_EN; + writel_relaxed(r, pll->pwr_addr); + + r = readl_relaxed(pll->pwr_addr) & ~PLL_PWR_ON; + writel_relaxed(r, pll->pwr_addr); + + mtk_clk_unlock(flags); +} + +static long clk_pll_round_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + u32 pcwfbits = 14; + u32 pcw = 0; + u32 postdiv = 0; + u32 r; + +/* pr_debug("[CCF] %s: %s: rate=%lu\n", __func__, __clk_get_name(hw->clk), + rate);*/ +#if MT_CCF_BRINGUP + return 0; +#endif /* MT_CCF_BRINGUP */ + + *prate = *prate ? *prate : 26000000; + rate = freq_limit(rate); + calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits); + + r = calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits); + r = (r + pll_posdiv_map[postdiv] - 1) / pll_posdiv_map[postdiv]; + + return r; +} + +#define SDM_PLL_POSTDIV_H 6 +#define SDM_PLL_POSTDIV_L 4 +#define SDM_PLL_POSTDIV_MASK GENMASK(SDM_PLL_POSTDIV_H, SDM_PLL_POSTDIV_L) +#define SDM_PLL_PCW_H 20 +#define SDM_PLL_PCW_L 0 +#define SDM_PLL_PCW_MASK GENMASK(SDM_PLL_PCW_H, SDM_PLL_PCW_L) + +static unsigned long clk_sdm_pll_recalc_rate( + struct clk_hw *hw, + unsigned long parent_rate) +{ + + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + u32 con0 = readl_relaxed(pll->base_addr); + u32 con1 = readl_relaxed(pll->base_addr + 4); + + u32 posdiv = (con0 & SDM_PLL_POSTDIV_MASK) >> SDM_PLL_POSTDIV_L; + u32 pcw = (con1 & SDM_PLL_PCW_MASK) >> SDM_PLL_PCW_L; + u32 pcwfbits = 14; + + u32 vco_freq; + unsigned long r; +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: parent_rate=%lu\n", __func__, + __clk_get_name(hw->clk), parent_rate);*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + parent_rate = parent_rate ? parent_rate : 26000000; + + vco_freq = calc_pll_vco_freq(parent_rate, pcw, 1, 1, pcwfbits); + r = (vco_freq + pll_posdiv_map[posdiv] - 1) / pll_posdiv_map[posdiv]; + +/* pr_debug("[CCF] %s: %lu: %s\n", __func__, r, __clk_get_name(hw->clk));*/ + + return r; +} + +static void clk_sdm_pll_set_rate_regs( + struct clk_hw *hw, + u32 pcw, + u32 postdiv_idx) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + void __iomem *con0_addr = pll->base_addr; + void __iomem *con1_addr = pll->base_addr + 4; + u32 con0; + u32 con1; + u32 pll_en; + + mtk_clk_lock(flags); + + con0 = readl_relaxed(con0_addr); + con1 = readl_relaxed(con1_addr); + + pll_en = con0 & PLL_BASE_EN; + + /* set postdiv */ + con0 &= ~SDM_PLL_POSTDIV_MASK; + con0 |= postdiv_idx << SDM_PLL_POSTDIV_L; + writel_relaxed(con0, con0_addr); + + /* set pcw */ + con1 &= ~SDM_PLL_PCW_MASK; + con1 |= pcw << SDM_PLL_PCW_L; + + if (pll_en) + con1 |= PLL_PCW_CHG; + + writel_relaxed(con1, con1_addr); + + if (pll_en) { + wmb(); /* sync write before delay */ + udelay(20); + } + + mtk_clk_unlock(flags); +} + +static int clk_sdm_pll_set_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + u32 pcwfbits = 14; + u32 pcw = 0; + u32 postdiv_idx = 0; + int r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + parent_rate = parent_rate ? parent_rate : 26000000; + r = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits); + +/* pr_debug("[CCF] %s: %s, rate: %lu, pcw: %u, postdiv_idx: %u\n", + __func__, __clk_get_name(hw->clk), rate, pcw, postdiv_idx);*/ + + if (r == 0) + clk_sdm_pll_set_rate_regs(hw, pcw, postdiv_idx); + + return r; +} + +const struct clk_ops mt_clk_sdm_pll_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_pll_enable, + .disable = clk_pll_disable, + .recalc_rate = clk_sdm_pll_recalc_rate, + .round_rate = clk_pll_round_rate, + .set_rate = clk_sdm_pll_set_rate, +}; + +#define ARM_PLL_POSTDIV_H 26 +#define ARM_PLL_POSTDIV_L 24 +#define ARM_PLL_POSTDIV_MASK GENMASK(ARM_PLL_POSTDIV_H, ARM_PLL_POSTDIV_L) +#define ARM_PLL_PCW_H 20 +#define ARM_PLL_PCW_L 0 +#define ARM_PLL_PCW_MASK GENMASK(ARM_PLL_PCW_H, ARM_PLL_PCW_L) + +static unsigned long clk_arm_pll_recalc_rate( + struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + u32 con1 = readl_relaxed(pll->base_addr + 4); + + u32 posdiv = (con1 & ARM_PLL_POSTDIV_MASK) >> ARM_PLL_POSTDIV_L; + u32 pcw = (con1 & ARM_PLL_PCW_MASK) >> ARM_PLL_PCW_L; + u32 pcwfbits = 14; + + u32 vco_freq; + unsigned long r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + parent_rate = parent_rate ? parent_rate : 26000000; + + vco_freq = calc_pll_vco_freq(parent_rate, pcw, 1, 1, pcwfbits); + r = (vco_freq + pll_posdiv_map[posdiv] - 1) / pll_posdiv_map[posdiv]; + +/* pr_debug("[CCF] %s: %lu: %s\n", __func__, r, __clk_get_name(hw->clk));*/ + + return r; +} + +static void clk_arm_pll_set_rate_regs( + struct clk_hw *hw, + u32 pcw, + u32 postdiv_idx) + +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + void __iomem *con0_addr = pll->base_addr; + void __iomem *con1_addr = pll->base_addr + 4; + u32 con0; + u32 con1; + u32 pll_en; + + mtk_clk_lock(flags); + + con0 = readl_relaxed(con0_addr); + con1 = readl_relaxed(con1_addr); + + pll_en = con0 & PLL_BASE_EN; + + /* postdiv */ + con1 &= ~ARM_PLL_POSTDIV_MASK; + con1 |= postdiv_idx << ARM_PLL_POSTDIV_L; + + /* pcw */ + con1 &= ~ARM_PLL_PCW_MASK; + con1 |= pcw << ARM_PLL_PCW_L; + + if (pll_en) + con1 |= PLL_PCW_CHG; + + writel_relaxed(con1, con1_addr); + + if (pll_en) { + wmb(); /* sync write before delay */ + udelay(20); + } + + mtk_clk_unlock(flags); +} + +static int clk_arm_pll_set_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + u32 pcwfbits = 14; + u32 pcw = 0; + u32 postdiv_idx = 0; + int r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + parent_rate = parent_rate ? parent_rate : 26000000; + r = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits); + +/* pr_debug("[CCF] %s: %s, rate: %lu, pcw: %u, postdiv_idx: %u\n", + __func__, __clk_get_name(hw->clk), rate, pcw, postdiv_idx);*/ + + if (r == 0) + clk_arm_pll_set_rate_regs(hw, pcw, postdiv_idx); + + return r; +} + +const struct clk_ops mt_clk_arm_pll_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_pll_enable, + .disable = clk_pll_disable, + .recalc_rate = clk_arm_pll_recalc_rate, + .round_rate = clk_pll_round_rate, + .set_rate = clk_arm_pll_set_rate, +}; + +static long clk_mm_pll_round_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + u32 pcwfbits = 14; + u32 pcw = 0; + u32 postdiv = 0; + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s, rate: %lu\n", __clk_get_name(hw->clk), rate);*/ + + if (rate <= 702000000) + postdiv = 2; + + *prate = *prate ? *prate : 26000000; + rate = freq_limit(rate); + calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits); + + r = calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits); + r = (r + pll_posdiv_map[postdiv] - 1) / pll_posdiv_map[postdiv]; + + return r; +} + +static int clk_mm_pll_set_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + u32 pcwfbits = 14; + u32 pcw = 0; + u32 postdiv_idx = 0; + int r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + if (rate <= 702000000) + postdiv_idx = 2; + + parent_rate = parent_rate ? parent_rate : 26000000; + r = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits); + +/* pr_debug("%s, rate: %lu, pcw: %u, postdiv_idx: %u\n", + __clk_get_name(hw->clk), rate, pcw, postdiv_idx);*/ + + if (r == 0) + clk_arm_pll_set_rate_regs(hw, pcw, postdiv_idx); + + return r; +} + +const struct clk_ops mt_clk_mm_pll_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_pll_enable, + .disable = clk_pll_disable, + .recalc_rate = clk_arm_pll_recalc_rate, + .round_rate = clk_mm_pll_round_rate, + .set_rate = clk_mm_pll_set_rate, +}; + +static int clk_univ_pll_enable(struct clk_hw *hw) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s\n", __clk_get_name(hw->clk));*/ + + mtk_clk_lock(flags); + + r = readl_relaxed(pll->base_addr) | pll->en_mask; + writel_relaxed(r, pll->base_addr); + wmb(); /* sync write before delay */ + udelay(20); + + if (pll->flags & HAVE_RST_BAR) { + r = readl_relaxed(pll->base_addr) | RST_BAR_MASK; + writel_relaxed(r, pll->base_addr); + } + + mtk_clk_unlock(flags); + + return 0; +} + +static void clk_univ_pll_disable(struct clk_hw *hw) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return; +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s: PLL_AO: %d\n", + __clk_get_name(hw->clk), !!(pll->flags & PLL_AO));*/ + + if (pll->flags & PLL_AO) + return; + + mtk_clk_lock(flags); + + if (pll->flags & HAVE_RST_BAR) { + r = readl_relaxed(pll->base_addr) & ~RST_BAR_MASK; + writel_relaxed(r, pll->base_addr); + } + + r = readl_relaxed(pll->base_addr) & ~PLL_BASE_EN; + writel_relaxed(r, pll->base_addr); + + mtk_clk_unlock(flags); +} + +#define UNIV_PLL_POSTDIV_H 6 +#define UNIV_PLL_POSTDIV_L 4 +#define UNIV_PLL_POSTDIV_MASK GENMASK(UNIV_PLL_POSTDIV_H, UNIV_PLL_POSTDIV_L) +#define UNIV_PLL_FBKDIV_H 20 +#define UNIV_PLL_FBKDIV_L 14 +#define UNIV_PLL_FBKDIV_MASK GENMASK(UNIV_PLL_FBKDIV_H, UNIV_PLL_FBKDIV_L) + +static unsigned long clk_univ_pll_recalc_rate( + struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + u32 con0 = readl_relaxed(pll->base_addr); + u32 con1 = readl_relaxed(pll->base_addr + 4); + + u32 fbkdiv = (con1 & UNIV_PLL_FBKDIV_MASK) >> UNIV_PLL_FBKDIV_L; + u32 posdiv = (con0 & UNIV_PLL_POSTDIV_MASK) >> UNIV_PLL_POSTDIV_L; + + u32 vco_freq; + unsigned long r; +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + parent_rate = parent_rate ? parent_rate : 26000000; + + vco_freq = parent_rate * fbkdiv; + r = (vco_freq + pll_posdiv_map[posdiv] - 1) / pll_posdiv_map[posdiv]; + +/* pr_debug("%lu: %s\n", r, __clk_get_name(hw->clk));*/ + + return r; +} + +static void clk_univ_pll_set_rate_regs( + struct clk_hw *hw, + u32 pcw, + u32 postdiv_idx) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + void __iomem *con0_addr = pll->base_addr; + void __iomem *con1_addr = pll->base_addr + 4; + u32 con0; + u32 con1; + u32 pll_en; + + mtk_clk_lock(flags); + + con0 = readl_relaxed(con0_addr); + con1 = readl_relaxed(con1_addr); + + pll_en = con0 & PLL_BASE_EN; + + /* postdiv */ + con0 &= ~UNIV_PLL_POSTDIV_MASK; + con0 |= postdiv_idx << UNIV_PLL_POSTDIV_L; + + /* fkbdiv */ + con1 &= ~UNIV_PLL_FBKDIV_MASK; + con1 |= pcw << UNIV_PLL_FBKDIV_L; + + writel_relaxed(con0, con0_addr); + writel_relaxed(con1, con1_addr); + + if (pll_en) { + wmb(); /* sync write before delay */ + udelay(20); + } + + mtk_clk_unlock(flags); +} + +static long clk_univ_pll_round_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + u32 pcwfbits = 0; + u32 pcw = 0; + u32 postdiv = 0; + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s, rate: %lu\n", __clk_get_name(hw->clk), rate);*/ + + *prate = *prate ? *prate : 26000000; + rate = freq_limit(rate); + calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits); + + r = *prate * pcw; + r = (r + pll_posdiv_map[postdiv] - 1) / pll_posdiv_map[postdiv]; + + return r; +} + +static int clk_univ_pll_set_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + u32 pcwfbits = 0; + u32 pcw = 0; + u32 postdiv_idx = 0; + int r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + parent_rate = parent_rate ? parent_rate : 26000000; + r = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits); + +/* pr_debug("%s, rate: %lu, pcw: %u, postdiv_idx: %u\n", + __clk_get_name(hw->clk), rate, pcw, postdiv_idx);*/ + + if (r == 0) + clk_univ_pll_set_rate_regs(hw, pcw, postdiv_idx); + + return r; +} + +const struct clk_ops mt_clk_univ_pll_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_univ_pll_enable, + .disable = clk_univ_pll_disable, + .recalc_rate = clk_univ_pll_recalc_rate, + .round_rate = clk_univ_pll_round_rate, + .set_rate = clk_univ_pll_set_rate, +}; + +static int clk_aud_pll_enable(struct clk_hw *hw) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s\n", __clk_get_name(hw->clk));*/ + + mtk_clk_lock(flags); + + r = readl_relaxed(pll->pwr_addr) | PLL_PWR_ON; + writel_relaxed(r, pll->pwr_addr); + wmb(); /* sync write before delay */ + udelay(1); + + r = readl_relaxed(pll->pwr_addr) & ~PLL_ISO_EN; + writel_relaxed(r, pll->pwr_addr); + wmb(); /* sync write before delay */ + udelay(1); + + r = readl_relaxed(pll->base_addr) | pll->en_mask; + writel_relaxed(r, pll->base_addr); + + r = readl_relaxed(pll->base_addr + 16) | AUDPLL_TUNER_EN; + writel_relaxed(r, pll->base_addr + 16); + wmb(); /* sync write before delay */ + udelay(20); + + if (pll->flags & HAVE_RST_BAR) { + r = readl_relaxed(pll->base_addr) | RST_BAR_MASK; + writel_relaxed(r, pll->base_addr); + } + + mtk_clk_unlock(flags); + + return 0; +} + +static void clk_aud_pll_disable(struct clk_hw *hw) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return; +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s: PLL_AO: %d\n", + __clk_get_name(hw->clk), !!(pll->flags & PLL_AO));*/ + + if (pll->flags & PLL_AO) + return; + + mtk_clk_lock(flags); + + if (pll->flags & HAVE_RST_BAR) { + r = readl_relaxed(pll->base_addr) & ~RST_BAR_MASK; + writel_relaxed(r, pll->base_addr); + } + + r = readl_relaxed(pll->base_addr + 8) & ~AUDPLL_TUNER_EN; + writel_relaxed(r, pll->base_addr + 8); + + r = readl_relaxed(pll->base_addr) & ~PLL_BASE_EN; + writel_relaxed(r, pll->base_addr); + + r = readl_relaxed(pll->pwr_addr) | PLL_ISO_EN; + writel_relaxed(r, pll->pwr_addr); + + r = readl_relaxed(pll->pwr_addr) & ~PLL_PWR_ON; + writel_relaxed(r, pll->pwr_addr); + + mtk_clk_unlock(flags); +} + +#define AUD_PLL_POSTDIV_H 6 +#define AUD_PLL_POSTDIV_L 4 +#define AUD_PLL_POSTDIV_MASK GENMASK(AUD_PLL_POSTDIV_H, AUD_PLL_POSTDIV_L) +#define AUD_PLL_PCW_H 30 +#define AUD_PLL_PCW_L 0 +#define AUD_PLL_PCW_MASK GENMASK(AUD_PLL_PCW_H, AUD_PLL_PCW_L) + +static unsigned long clk_aud_pll_recalc_rate( + struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + u32 con0 = readl_relaxed(pll->base_addr); + u32 con1 = readl_relaxed(pll->base_addr + 4); + + u32 posdiv = (con0 & AUD_PLL_POSTDIV_MASK) >> AUD_PLL_POSTDIV_L; + u32 pcw = (con1 & AUD_PLL_PCW_MASK) >> AUD_PLL_PCW_L; + u32 pcwfbits = 24; + + u32 vco_freq; + unsigned long r; +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + parent_rate = parent_rate ? parent_rate : 26000000; + + vco_freq = calc_pll_vco_freq(parent_rate, pcw, 1, 1, pcwfbits); + r = (vco_freq + pll_posdiv_map[posdiv] - 1) / pll_posdiv_map[posdiv]; + +/* pr_debug("%lu: %s\n", r, __clk_get_name(hw->clk));*/ + + return r; +} + +static void clk_aud_pll_set_rate_regs( + struct clk_hw *hw, + u32 pcw, + u32 postdiv_idx) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + void __iomem *con0_addr = pll->base_addr; + void __iomem *con1_addr = pll->base_addr + 4; + void __iomem *con2_addr = pll->base_addr + 8; + u32 con0; + u32 con1; + u32 pll_en; + + mtk_clk_lock(flags); + + con0 = readl_relaxed(con0_addr); + con1 = readl_relaxed(con1_addr); + + pll_en = con0 & PLL_BASE_EN; + + /* set postdiv */ + con0 &= ~AUD_PLL_POSTDIV_MASK; + con0 |= postdiv_idx << AUD_PLL_POSTDIV_L; + writel_relaxed(con0, con0_addr); + + /* set pcw */ + con1 &= ~AUD_PLL_PCW_MASK; + con1 |= pcw << AUD_PLL_PCW_L; + + if (pll_en) + con1 |= PLL_PCW_CHG; + + writel_relaxed(con1, con1_addr); + writel_relaxed(con1 + 1, con2_addr); + + if (pll_en) { + wmb(); /* sync write before delay */ + udelay(20); + } + + mtk_clk_unlock(flags); +} + +static long clk_aud_pll_round_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + u32 pcwfbits = 24; + u32 pcw = 0; + u32 postdiv = 0; + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + return 0; +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s, rate: %lu\n", __clk_get_name(hw->clk), rate);*/ + + *prate = *prate ? *prate : 26000000; + rate = freq_limit(rate); + calc_pll_freq_cfg(&pcw, &postdiv, rate, *prate, pcwfbits); + + r = calc_pll_vco_freq(*prate, pcw, 1, 1, pcwfbits); + r = (r + pll_posdiv_map[postdiv] - 1) / pll_posdiv_map[postdiv]; + + return r; +} + +static int clk_aud_pll_set_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + u32 pcwfbits = 24; + u32 pcw = 0; + u32 postdiv_idx = 0; + int r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: rate=%lu, parent_rate=%lu\n", __func__, + __clk_get_name(hw->clk), rate, parent_rate);*/ + return 0; +#endif /* MT_CCF_BRINGUP */ + parent_rate = parent_rate ? parent_rate : 26000000; + r = calc_pll_freq_cfg(&pcw, &postdiv_idx, rate, parent_rate, pcwfbits); + +/* pr_debug("%s, rate: %lu, pcw: %u, postdiv_idx: %u\n", + __clk_get_name(hw->clk), rate, pcw, postdiv_idx);*/ + + if (r == 0) + clk_aud_pll_set_rate_regs(hw, pcw, postdiv_idx); + + return r; +} + +const struct clk_ops mt_clk_aud_pll_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_aud_pll_enable, + .disable = clk_aud_pll_disable, + .recalc_rate = clk_aud_pll_recalc_rate, + .round_rate = clk_aud_pll_round_rate, + .set_rate = clk_aud_pll_set_rate, +}; + + +static int clk_spm_pll_enable(struct clk_hw *hw) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + /*return 0;*/ +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s\n", __clk_get_name(hw->clk));*/ + + mtk_clk_lock(flags); +/* OSC EN = 1 */ + r = readl_relaxed(pll->base_addr) | ULPOSC_EN; + writel_relaxed(r, pll->base_addr); + wmb(); /* sync write before delay */ + udelay(11); +/* OSC RST */ + r = readl_relaxed(pll->base_addr) | ULPOSC_RST; + writel_relaxed(r, pll->base_addr); + wmb(); /* sync write before delay */ + udelay(40); + r = readl_relaxed(pll->base_addr) & ~ULPOSC_RST; + writel_relaxed(r, pll->base_addr); + wmb(); /* sync write before delay */ + udelay(130); +/* OSC CG_EN = 1 */ + r = readl_relaxed(pll->base_addr) | ULPOSC_CG_EN; + writel_relaxed(r, pll->base_addr); + + mtk_clk_unlock(flags); + + return 0; +} + +static void clk_spm_pll_disable(struct clk_hw *hw) +{ + unsigned long flags = 0; + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + /*return;*/ +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s: PLL_AO: %d\n", + __clk_get_name(hw->clk), !!(pll->flags & PLL_AO));*/ + + if (pll->flags & PLL_AO) + return; + + mtk_clk_lock(flags); + +/* OSC CG_EN = 0 */ + r = readl_relaxed(pll->base_addr) & ~ULPOSC_CG_EN; + writel_relaxed(r, pll->base_addr); + wmb(); /* sync write before delay */ + udelay(40); +/* OSC EN = 0 */ + r = readl_relaxed(pll->base_addr) & ~ULPOSC_EN; + writel_relaxed(r, pll->base_addr); + + mtk_clk_unlock(flags); +} + + + +static unsigned long clk_spm_pll_recalc_rate( + struct clk_hw *hw, + unsigned long parent_rate) +{ +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + /*return 0;*/ +#endif /* MT_CCF_BRINGUP */ + + return 208000000; +} + + +static long clk_spm_pll_round_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: S\n", __func__, __clk_get_name(hw->clk));*/ + /*return 0;*/ +#endif /* MT_CCF_BRINGUP */ +/* pr_debug("%s, rate: %lu\n", __clk_get_name(hw->clk), rate);*/ + + return 208000000; +} + +static int clk_spm_pll_set_rate( + struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + + +#if MT_CCF_BRINGUP +/* pr_debug("[CCF] %s: %s: rate=%lu, parent_rate=%lu\n", __func__, + __clk_get_name(hw->clk), rate, parent_rate);*/ + /*return 0;*/ +#endif /* MT_CCF_BRINGUP */ + + return 208000000; +} + +const struct clk_ops mt_clk_spm_pll_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_spm_pll_enable, + .disable = clk_spm_pll_disable, + .recalc_rate = clk_spm_pll_recalc_rate, + .round_rate = clk_spm_pll_round_rate, + .set_rate = clk_spm_pll_set_rate, +}; diff --git a/drivers/clk/mediatek/clk-mt6755-pll.h b/drivers/clk/mediatek/clk-mt6755-pll.h new file mode 100644 index 0000000000000000000000000000000000000000..1966a6f0a20242daaf66ced36aab89f097cb5c35 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6755-pll.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DRV_CLK_MT6755_PLL_H +#define __DRV_CLK_MT6755_PLL_H + +/* + * This is a private header file. DO NOT include it except clk-*.c. + */ + +extern const struct clk_ops mt_clk_sdm_pll_ops; +extern const struct clk_ops mt_clk_arm_pll_ops; +extern const struct clk_ops mt_clk_mm_pll_ops; +extern const struct clk_ops mt_clk_univ_pll_ops; +extern const struct clk_ops mt_clk_aud_pll_ops; +extern const struct clk_ops mt_clk_spm_pll_ops; +#endif /* __DRV_CLK_MT6755_PLL_H */ diff --git a/drivers/clk/mediatek/clk-mt6755.c b/drivers/clk/mediatek/clk-mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..950826c2bbba6497640ea072add8169df1ceb4e1 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6755.c @@ -0,0 +1,2048 @@ +/* +* Copyright (c) 2014 MediaTek Inc. +* Author: James Liao +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 +#include +#include +#include + +#include "clk-mtk-v1.h" +#include "clk-pll-v1.h" +#include "clk-gate-v1.h" +#include "clk-mt6755-pll.h" +#define _MUX_CLR_SET_UPDS_ +#define _MUX_UPDS_ +#ifdef _MUX_UPDS_ +#include "clk-mux.h" +static DEFINE_SPINLOCK(mt6755_clk_lock); +#endif +#include +#include "../../misc/mediatek/base/power/mt6755/mt_spm_mtcmos.h" +#include "../../misc/mediatek/include/mt-plat/mt_devinfo.h" + +#if !defined(MT_CCF_DEBUG) || !defined(MT_CCF_BRINGUP) +#define MT_CCF_DEBUG 0 +#define MT_CCF_BRINGUP 0 +#endif +#ifdef CONFIG_ARM64 +#define IOMEM(a) ((void __force __iomem *)((a))) +#endif +#define mt_reg_sync_writel(v, a) \ + do { \ + __raw_writel((v), IOMEM((a))); \ + mb(); /* for mt_reg_sync_writel() */ \ + } while (0) +#define clk_readl(addr) __raw_readl(IOMEM(addr)) + +#define clk_writel(addr, val) \ + mt_reg_sync_writel(val, addr) + +#define clk_setl(addr, val) \ + mt_reg_sync_writel(clk_readl(addr) | (val), addr) + +#define clk_clrl(addr, val) \ + mt_reg_sync_writel(clk_readl(addr) & ~(val), addr) + +/* + * platform clocks + */ + +/* ROOT */ +#define clk_null "clk_null" +#define clk26m "clk26m" +#define clk32k "clk32k" +#define clk13m "clk13m" + +#define clkph_mck_o "clkph_mck_o" +#define dpi_ck "dpi_ck" + +/* PLL */ +#define armbpll "armbpll" +#define armspll "armspll" +/*#define armpll "armpll"*/ +#define mainpll "mainpll" +#define msdcpll "msdcpll" +#define univpll "univpll" +#define mmpll "mmpll" +#define vencpll "vencpll" +#define tvdpll "tvdpll" +#define apll1 "apll1" +#define apll2 "apll2" +#define oscpll "oscpll" + +/* DIV */ +#define syspll_ck "syspll_ck" +#define syspll1_ck "syspll1_ck" +#define syspll2_ck "syspll2_ck" +#define syspll3_ck "syspll3_ck" +#define syspll4_ck "syspll4_ck" +#define univpll_ck "univpll_ck" +#define univpll1_ck "univpll1_ck" +#define univpll2_ck "univpll2_ck" +#define univpll3_ck "univpll3_ck" +#define ad_apll1_ck "ad_apll1_ck" +#define ad_sys_26m_ck "ad_sys_26m_ck" +#define ad_sys_26m_d2 "ad_sys_26m_d2" +#define dmpll_ck "dmpll_ck" +#define dmpll_d2 "dmpll_d2" +#define dmpll_d4 "dmpll_d4" +#define dmpll_d8 "dmpll_d8" +#define dpi_ck "dpi_ck" +#define mmpll_ck "mmpll_ck" +#define msdcpll_ck "msdcpll_ck" +#define msdcpll_d16 "msdcpll_d16" +#define msdcpll_d2 "msdcpll_d2" +#define msdcpll_d4 "msdcpll_d4" +#define msdcpll_d8 "msdcpll_d8" +#define syspll_d2 "syspll_d2" +#define syspll_d3 "syspll_d3" +#define syspll_d5 "syspll_d5" +#define syspll1_d16 "syspll1_d16" +#define syspll1_d2 "syspll1_d2" +#define syspll1_d4 "syspll1_d4" +#define syspll1_d8 "syspll1_d8" +#define syspll2_d2 "syspll2_d2" +#define syspll2_d4 "syspll2_d4" +#define syspll3_d2 "syspll3_d2" +#define syspll3_d4 "syspll3_d4" +#define syspll4_d2 "syspll4_d2" +#define syspll4_d2_d8 "syspll4_d2_d8" +#define syspll4_d4 "syspll4_d4" +#define tvdpll_ck "tvdpll_ck" +#define tvdpll_d2 "tvdpll_d2" +#define tvdpll_d4 "tvdpll_d4" +#define univpll_d2 "univpll_d2" +#define univpll_d26 "univpll_d26" +#define univpll_d3 "univpll_d3" +#define univpll_d5 "univpll_d5" +#define univpll1_d2 "univpll1_d2" +#define univpll1_d4 "univpll1_d4" +#define univpll1_d8 "univpll1_d8" +#define univpll2_d2 "univpll2_d2" +#define univpll2_d4 "univpll2_d4" +#define univpll2_d8 "univpll2_d8" +#define univpll3_d2 "univpll3_d2" +#define univpll3_d4 "univpll3_d4" +#define vencpll_ck "vencpll_ck" +#define vencpll_d3 "vencpll_d3" +#define whpll_audio_ck "whpll_audio_ck" +/*---------------------------------------------*/ +#define osc_ck "osc_ck" +#define osc_d8 "osc_d8" +#define osc_d2 "osc_d2" +#define syspll_d7 "syspll_d7" +#define univpll_d7 "univpll_d7" +#define osc_d4 "osc_d4" +#define tvdpll_d8 "tvdpll_d8" +#define tvdpll_d16 "tvdpll_d16" +#define apll1_ck "apll1_ck" +#define apll2_ck "apll2_ck" +#define syspll_d3_d3 "syspll_d3_d3" + + + +/* TOP */ +#define axi_sel "axi_sel" +#define mem_sel "mem_sel" +#define ddrphycfg_sel "ddrphycfg_sel" +#define mm_sel "mm_sel" +#define pwm_sel "pwm_sel" +#define vdec_sel "vdec_sel" +#define mfg_sel "mfg_sel" +#define camtg_sel "camtg_sel" +#define uart_sel "uart_sel" +#define spi_sel "spi_sel" +#define usb20_sel "usb20_sel" +#define msdc50_0_sel "msdc50_0_sel" + +#define msdc30_1_sel "msdc30_1_sel" +#define msdc30_2_sel "msdc30_2_sel" +#define msdc30_3_sel "msdc30_3_sel" +#define audio_sel "audio_sel" +#define aud_intbus_sel "aud_intbus_sel" +#define pmicspi_sel "pmicspi_sel" +#define scp_sel "scp_sel" +#define atb_sel "atb_sel" +#define dpi0_sel "dpi0_sel" +#define scam_sel "scam_sel" +#define mfg13m_sel "mfg13m_sel" +#define aud_1_sel "aud_1_sel" +#define aud_2_sel "aud_2_sel" +#define irda_sel "irda_sel" +#define irtx_sel "irtx_sel" +#define disppwm_sel "disppwm_sel" +/*--------------------------------------------------------------*/ +#define ssusb_top_sys_sel "ssusb_top_sys_sel" +#define usb_top_sel "usb_top_sel" +#define i2c_sel "i2c_sel" +#define f26m_sel "f26m_sel" +#define msdc50_0_hclk_sel "msdc50_0_hclk_sel" +#define bsi_spi_sel "bsi_spi_sel" +#define spm_sel "spm_sel" +#define dvfsp_sel "dvfsp_sel" +#define i2s_sel "i2s_sel" + + + +/* INFRA */ +#define infra_pmictmr "infra_pmictmr" +#define infra_pmicap "infra_pmicap" +#define infra_pmicmd "infra_pmicmd" +#define infra_pmicconn "infra_pmicconn" +#define infra_scpsys "infra_scpsys" +#define infra_sej "infra_sej" +#define infra_apxgpt "infra_apxgpt" +#define infra_icusb "infra_icusb" +#define infra_gce "infra_gce" +#define infra_therm "infra_therm" +#define infra_i2c0 "infra_i2c0" +#define infra_i2c1 "infra_i2c1" +#define infra_i2c2 "infra_i2c2" +#define infra_i2c3 "infra_i2c3" +#define infra_pwmhclk "infra_pwmhclk" +#define infra_pwm1 "infra_pwm1" +#define infra_pwm2 "infra_pwm2" +#define infra_pwm3 "infra_pwm3" +#define infra_pwm4 "infra_pwm4" +#define infra_pwm "infra_pwm" +#define infra_uart0 "infra_uart0" +#define infra_uart1 "infra_uart1" +#define infra_uart2 "infra_uart2" +#define infra_uart3 "infra_uart3" +#define infra_md2mdccif0 "infra_md2mdccif0" +#define infra_md2mdccif1 "infra_md2mdccif1" +#define infra_md2mdccif2 "infra_md2mdccif2" +#define infra_btif "infra_btif" +#define infra_md2mdccif3 "infra_md2mdccif3" +#define infra_spi0 "infra_spi0" +#define infra_msdc0 "infra_msdc0" +#define infra_md2mdccif4 "infra_md2mdccif4" +#define infra_msdc1 "infra_msdc1" +#define infra_msdc2 "infra_msdc2" +#define infra_msdc3 "infra_msdc3" +#define infra_md2mdccif5 "infra_md2mdccif5" +#define infra_gcpu "infra_gcpu" +#define infra_trng "infra_trng" +#define infra_auxadc "infra_auxadc" +#define infra_cpum "infra_cpum" +#define infra_ccif1ap "infra_ccif1ap" +#define infra_ccif1md "infra_ccif1md" +#define infra_apdma "infra_apdma" +#define infra_xiu "infra_xiu" +#define infra_deviceapc "infra_deviceapc" +#define infra_xiu2ahb "infra_xiu2ahb" +#define infra_ccifap "infra_ccifap" +#define infra_debugsys "infra_debugsys" +#define infra_audio "infra_audio" /* confirm if for audio??*/ +#define infra_ccifmd "infra_ccifmd" +#define infra_dramcf26m "infra_dramcf26m" +#define infra_irtx "infra_irtx" +#define infra_ssusbtop "infra_ssusbtop" +#define infra_disppwm "infra_disppwm" +#define infra_cldmabclk "infra_cldmabclk" +#define infra_audio26mbclk "infra_audio26mbclk" +#define infra_mdtmp26mbclk "infra_mdtmp26mbclk" +#define infra_spi1 "infra_spi1" +#define infra_i2c4 "infra_i2c4" +#define infra_mdtmpshare "infra_mdtmpshare" + + +#if 0 +#define infra_dbgclk "infra_dbgclk" +#define infra_gce "infra_gce" +#define infra_trbg "infra_trbg" +#define infra_cpum "infra_cpum" +#define infra_devapc "infra_devapc" +#define infra_audio "infra_audio" +#define infra_gcpu "infra_gcpu" +#define infra_l2csram "infra_l2csram" +#define infra_m4u "infra_m4u" +#define infra_cldma "infra_cldma" +#define infra_connmcubus "infra_connmcubus" +#define infra_kp "infra_kp" +#define infra_apxgpt "infra_apxgpt" +#define infra_sej "infra_sej" +#define infra_ccif0ap "infra_ccif0ap" +#define infra_ccif1ap "infra_ccif1ap" +#define infra_pmicspi "infra_pmicspi" +#define infra_pmicwrap "infra_pmicwrap" + +/* PERI */ +#if 0 +#define peri_disp_pwm "peri_disp_pwm" +#define peri_therm "peri_therm" +#define peri_pwm1 "peri_pwm1" +#define peri_pwm2 "peri_pwm2" +#define peri_pwm3 "peri_pwm3" +#define peri_pwm4 "peri_pwm4" +#define peri_pwm5 "peri_pwm5" +#define peri_pwm6 "peri_pwm6" +#define peri_pwm7 "peri_pwm7" +#define peri_pwm "peri_pwm" +#define peri_usb0 "peri_usb0" +#define peri_irda "peri_irda" +#define peri_apdma "peri_apdma" +#define peri_msdc30_0 "peri_msdc30_0" +#define peri_msdc30_1 "peri_msdc30_1" +#define peri_msdc30_2 "peri_msdc30_2" +#define peri_msdc30_3 "peri_msdc30_3" +#define peri_uart0 "peri_uart0" +#define peri_uart1 "peri_uart1" +#define peri_uart2 "peri_uart2" +#define peri_uart3 "peri_uart3" +#define peri_uart4 "peri_uart4" +#define peri_btif "peri_btif" +#define peri_i2c0 "peri_i2c0" +#define peri_i2c1 "peri_i2c1" +#define peri_i2c2 "peri_i2c2" +#define peri_i2c3 "peri_i2c3" +#define peri_auxadc "peri_auxadc" +#define peri_spi0 "peri_spi0" +#define peri_irtx "peri_irtx" +#endif +#endif +/* MFG */ +#define mfg_bg3d "mfg_bg3d" + +/* IMG */ +#define img_image_larb2_smi "img_image_larb2_smi" +#define img_image_larb2_smi_m4u "img_image_larb2_smi_m4u" +#define img_image_larb2_smi_smi_common "img_image_larb2_smi_smi_common" +#define img_image_larb2_smi_met_smi_common "img_image_larb2_smi_met_smi_common" +#define img_image_larb2_smi_ispsys "img_image_larb2_smi_ispsys" +#define img_image_cam_smi "img_image_cam_smi" +#define img_image_cam_cam "img_image_cam_cam" +#define img_image_sen_tg "img_image_sen_tg" +#define img_image_sen_cam "img_image_sen_cam" +#define img_image_cam_sv "img_image_cam_sv" +#define img_image_sufod "img_image_sufod" +#define img_image_fd "img_image_fd" + +/* MM_SYS */ +#define mm_disp0_smi_common "mm_disp0_smi_common" +#define mm_disp0_smi_common_m4u "mm_disp0_smi_common_m4u" +#define mm_disp0_smi_common_mali "mm_disp0_smi_common_mali" +#define mm_disp0_smi_common_dispsys "mm_disp0_smi_common_dispsys" +#define mm_disp0_smi_common_smi_common "mm_disp0_smi_common_smi_common" +#define mm_disp0_smi_common_met_smi_common "mm_disp0_smi_common_met_smi_common" +#define mm_disp0_smi_common_ispsys "mm_disp0_smi_common_ispsys" +#define mm_disp0_smi_common_fdvt "mm_disp0_smi_common_fdvt" +#define mm_disp0_smi_common_vdec_gcon "mm_disp0_smi_common_vdec_gcon" +#define mm_disp0_smi_common_jpgenc "mm_disp0_smi_common_jpgenc" +#define mm_disp0_smi_common_jpgdec "mm_disp0_smi_common_jpgdec" + +#define mm_disp0_smi_larb0 "mm_disp0_smi_larb0" +#define mm_disp0_smi_larb0_m4u "mm_disp0_smi_larb0_m4u" +#define mm_disp0_smi_larb0_dispsys "mm_disp0_smi_larb0_dispsys" +#define mm_disp0_smi_larb0_smi_common "mm_disp0_smi_larb0_smi_common" +#define mm_disp0_smi_larb0_met_smi_common "mm_disp0_smi_larb0_met_smi_common" + + +#define mm_disp0_cam_mdp "mm_disp0_cam_mdp" +#define mm_disp0_mdp_rdma "mm_disp0_mdp_rdma" +#define mm_disp0_mdp_rsz0 "mm_disp0_mdp_rsz0" +#define mm_disp0_mdp_rsz1 "mm_disp0_mdp_rsz1" +#define mm_disp0_mdp_tdshp "mm_disp0_mdp_tdshp" +#define mm_disp0_mdp_wdma "mm_disp0_mdp_wdma" +#define mm_disp0_mdp_wrot "mm_disp0_mdp_wrot" +#define mm_disp0_fake_eng "mm_disp0_fake_eng" +#define mm_disp0_disp_ovl0 "mm_disp0_disp_ovl0" +#define mm_disp0_disp_ovl1 "mm_disp0_disp_ovl1" +#define mm_disp0_disp_rdma0 "mm_disp0_disp_rdma0" +#define mm_disp0_disp_rdma1 "mm_disp0_disp_rdma1" +#define mm_disp0_disp_wdma0 "mm_disp0_disp_wdma0" +#define mm_disp0_disp_color "mm_disp0_disp_color" +#define mm_disp0_disp_ccorr "mm_disp0_disp_ccorr" +#define mm_disp0_disp_aal "mm_disp0_disp_aal" +#define mm_disp0_disp_gamma "mm_disp0_disp_gamma" +#define mm_disp0_disp_dither "mm_disp0_disp_dither" +#define mm_disp0_mdp_color "mm_disp0_mdp_color" +#define mm_disp0_ufoe_mout "mm_disp0_ufoe_mout" +#define mm_disp0_disp_wdma1 "mm_disp0_disp_wdma1" +#define mm_disp0_disp_2lovl0 "mm_disp0_disp_2lovl0" +#define mm_disp0_disp_2lovl1 "mm_disp0_disp_2lovl1" +#define mm_disp0_disp_ovl0mout "mm_disp0_disp_ovl0mout" +#define mm_disp1_dsi_engine "mm_disp1_dsi_engine" +#define mm_disp1_dsi_digital "mm_disp1_dsi_digital" +#define mm_disp1_dpi_pixel "mm_disp1_dpi_pixel" +#define mm_disp1_dpi_engine "mm_disp1_dpi_engine" +#if 0 +#define "" +#define "" +#define "" +#define "" +#define "" +#define "" +#define "" +#define "" +#define "" +#define "" +#endif +#if 0 +#define mm_disp0_smi_common "mm_disp0_smi_common" +#define mm_disp0_smi_larb0 "mm_disp0_smi_larb0" +#define mm_disp0_cam_mdp "mm_disp0_cam_mdp" +#define mm_disp0_mdp_rdma "mm_disp0_mdp_rdma" +#define mm_disp0_mdp_rsz0 "mm_disp0_mdp_rsz0" +#define mm_disp0_mdp_rsz1 "mm_disp0_mdp_rsz1" +#define mm_disp0_mdp_tdshp "mm_disp0_mdp_tdshp" +#define mm_disp0_mdp_wdma "mm_disp0_mdp_wdma" +#define mm_disp0_mdp_wrot "mm_disp0_mdp_wrot" +#define mm_disp0_fake_eng "mm_disp0_fake_eng" +#define mm_disp0_disp_ovl0 "mm_disp0_disp_ovl0" +#define mm_disp0_disp_rdma0 "mm_disp0_disp_rdma0" +#define mm_disp0_disp_rdma1 "mm_disp0_disp_rdma1" +#define mm_disp0_disp_wdma0 "mm_disp0_disp_wdma0" +#define mm_disp0_disp_color "mm_disp0_disp_color" +#define mm_disp0_disp_ccorr "mm_disp0_disp_ccorr" +#define mm_disp0_disp_aal "mm_disp0_disp_aal" +#define mm_disp0_disp_gamma "mm_disp0_disp_gamma" +#define mm_disp0_disp_dither "mm_disp0_disp_dither" +#define mm_disp1_dsi_engine "mm_disp1_dsi_engine" +#define mm_disp1_dsi_digital "mm_disp1_dsi_digital" +#define mm_disp1_dpi_engine "mm_disp1_dpi_engine" +#define mm_disp1_dpi_pixel "mm_disp1_dpi_pixel" +#endif +/* VDEC */ +#define vdec0_vdec "vdec0_vdec" +#define vdec1_larb "vdec1_larb" +#define vdec1_larb_m4u "vdec1_larb_m4u" +#define vdec1_larb_smi_common "vdec1_larb_smi_common" +#define vdec1_larb_met_smi_common "vdec1_larb_met_smi_common" +#define vdec1_larb_vdec_gcon "vdec1_larb_vdec_gcon" + +/* VENC */ +#define venc_larb "venc_larb" +#define venc_larb_m4u "venc_larb_m4u" +#define venc_larb_smi_common "venc_larb_smi_common" +#define venc_larb_met_smi_common "venc_larb_met_smi_common" +#define venc_larb_jpgenc "venc_larb_jpgenc" +#define venc_larb_jpgdec "venc_larb_jpgdec" + +#define venc_venc "venc_venc" +#define venc_jpgenc "venc_jpgenc" +#define venc_jpgdec "venc_jpgdec" + +/* AUDIO */ +#define audio_afe "audio_afe" +#define audio_i2s "audio_i2s" +#define audio_22m "audio_22m" +#define audio_24m "audio_24m" +#define audio_apll2_tuner "audio_apll2_tuner" +#define audio_apll_tuner "audio_apll_tuner" +#define audio_adc "audio_adc" +#define audio_dac "audio_dac" +#define audio_dac_predis "audio_dac_predis" +#define audio_tml "audio_tml" +#define audio_apll1div0 "audio_apll1div0" +#define audio_apll2div0 "audio_apll2div0" + + +#ifdef CONFIG_OF +void __iomem *apmixed_base; +void __iomem *cksys_base; +void __iomem *infracfg_base; +void __iomem *audio_base; +void __iomem *mfgcfg_base; +void __iomem *mmsys_config_base; +void __iomem *img_base; +void __iomem *vdec_gcon_base; +void __iomem *venc_gcon_base; +void __iomem *scp_base; +/*PLL INIT*/ +#define ARMCA15PLL_CON0 (apmixed_base + 0x200) +#define ARMCA7PLL_CON0 (apmixed_base + 0x210) +#define MAINPLL_CON0 (apmixed_base + 0x220) +#define UNIVPLL_CON0 (apmixed_base + 0x230) +#define MMPLL_CON0 (apmixed_base + 0x240) +#define MSDCPLL_CON0 (apmixed_base + 0x250) +#define MSDCPLL_PWR_CON0 (apmixed_base + 0x25C) +#define VENCPLL_CON0 (apmixed_base + 0x260) +#define TVDPLL_CON0 (apmixed_base + 0x270) +#define TVDPLL_PWR_CON0 (apmixed_base + 0x27C) +#define APLL1_CON0 (apmixed_base + 0x2A0) +#define APLL1_PWR_CON0 (apmixed_base + 0x2B0) +#define APLL2_CON0 (apmixed_base + 0x2B4) +#define APLL2_PWR_CON0 (apmixed_base + 0x2C4) +#define INFRA_PDN_SET0 (infracfg_base + 0x0080) +#define INFRA_PDN_SET1 (infracfg_base + 0x0088) +#define INFRA_PDN_SET2 (infracfg_base + 0x00A4) +#define MFG_CG_SET (mfgcfg_base + 4) +#define IMG_CG_SET (img_base + 0x0004) +#define DISP_CG_SET0 (mmsys_config_base + 0x104) +#define VDEC_CKEN_CLR (vdec_gcon_base + 0x0004) +#define LARB_CKEN_CLR (vdec_gcon_base + 0x000C) +#define VENC_CG_CON (venc_gcon_base + 0x0) +#define AUDIO_TOP_CON0 (audio_base + 0x0000) +#define ULPOSC_CON (scp_base + 0x0458) +#endif + +#define INFRA0_CG 0x832ff910/*0: Disable ( with clock), 1: Enable ( without clock )*/ +#define INFRA1_CG 0x6f0802/*0: Disable ( with clock), 1: Enable ( without clock )*/ +#define INFRA2_CG 0xc1/*0: Disable ( with clock), 1: Enable ( without clock )*/ +#define AUD_CG 0x0F0C0344/*same as denali*/ +#define MFG_CG 0x00000001/*set*/ +#define DISP0_CG 0xfffffffc +#define DISP1_CG 0x0000003F +#define IMG_CG 0x00000FE1/*no bit10 SUFOD_CKPDN*/ +#define VDEC_CG 0x00000001/*set*/ +#define LARB_CG 0x00000001 +#define VENC_CG 0x00001111/*set*/ + +#define CG_BOOTUP_PDN 1 +#define ULPOSC_EN BIT(0) +#define ULPOSC_RST BIT(1) +#define ULPOSC_CG_EN BIT(2) + +struct mtk_fixed_factor { + int id; + const char *name; + const char *parent_name; + int mult; + int div; +}; + +#define FACTOR(_id, _name, _parent, _mult, _div) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .mult = _mult, \ + .div = _div, \ + } + +static void __init init_factors(struct mtk_fixed_factor *clks, int num, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + + for (i = 0; i < num; i++) { + struct mtk_fixed_factor *ff = &clks[i]; + + clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name, + 0, ff->mult, ff->div); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + ff->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[ff->id] = clk; + +#if MT_CCF_DEBUG + pr_debug("[CCF] factor %3d: %s\n", i, ff->name); +#endif /* MT_CCF_DEBUG */ + } +} + +static struct mtk_fixed_factor root_clk_alias[] __initdata = { + FACTOR(TOP_CLKPH_MCK_O, clkph_mck_o, clk_null, 1, 1), + FACTOR(TOP_DPI_CK, dpi_ck, clk_null, 1, 1), +}; + +static void __init init_clk_root_alias(struct clk_onecell_data *clk_data) +{ + init_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); +} + +static struct mtk_fixed_factor top_divs[] __initdata = { + FACTOR(TOP_AD_APLL1_CK, apll1_ck, apll1, 1, 1), + FACTOR(TOP_AD_APLL2_CK, apll2_ck, apll2, 1, 1), + /*FACTOR(TOP_AD_SYS_26M_CK, ad_sys_26m_ck, clk26m, 1, 1), + FACTOR(TOP_AD_SYS_26M_D2, ad_sys_26m_d2, clk26m, 1, 1),*/ + FACTOR(TOP_DMPLL_CK, dmpll_ck, clkph_mck_o, 1, 1), + /*FACTOR(TOP_DMPLL_D2, dmpll_d2, clkph_mck_o, 1, 1), + FACTOR(TOP_DMPLL_D4, dmpll_d4, clkph_mck_o, 1, 1), + FACTOR(TOP_DMPLL_D8, dmpll_d8, clkph_mck_o, 1, 1),*/ + + FACTOR(TOP_MMPLL_CK, mmpll_ck, mmpll, 1, 1), + /*FACTOR(TOP_MPLL_208M_CK, mmpll_208m_ck, mmpll, 1, 1),used for scpsys, no use*/ +#if 1 + FACTOR(TOP_OSC_CK, osc_ck, oscpll, 1, 1), + FACTOR(TOP_OSC_D2, osc_d2, oscpll, 1, 2), + FACTOR(TOP_OSC_D4, osc_d4, oscpll, 1, 4), + FACTOR(TOP_OSC_D8, osc_d8, oscpll, 1, 8), +#else + FACTOR(TOP_OSC_D2, osc_d2, clk_null, 1, 1), + FACTOR(TOP_OSC_D4, osc_d4, clk_null, 1, 1), + FACTOR(TOP_OSC_D8, osc_d8, clk_null, 1, 1), +#endif + FACTOR(TOP_MSDCPLL_CK, msdcpll_ck, msdcpll, 1, 1), + FACTOR(TOP_MSDCPLL_D16, msdcpll_d16, msdcpll, 1, 16), + FACTOR(TOP_MSDCPLL_D2, msdcpll_d2, msdcpll, 1, 2), + FACTOR(TOP_MSDCPLL_D4, msdcpll_d4, msdcpll, 1, 4), + FACTOR(TOP_MSDCPLL_D8, msdcpll_d8, msdcpll, 1, 8), + + + FACTOR(TOP_SYSPLL_CK, syspll_ck, mainpll, 1, 1), + FACTOR(TOP_SYSPLL_D3, syspll_d3, mainpll, 1, 3), + FACTOR(TOP_SYSPLL_D3_D3, syspll_d3_d3, mainpll, 1, 9), + FACTOR(TOP_SYSPLL_D5, syspll_d5, mainpll, 1, 5), + FACTOR(TOP_SYSPLL_D7, syspll_d7, mainpll, 1, 7), + + FACTOR(TOP_SYSPLL1_CK, syspll1_ck, mainpll, 1, 2), + FACTOR(TOP_SYSPLL1_D16, syspll1_d16, syspll1_ck, 1, 16), + FACTOR(TOP_SYSPLL1_D2, syspll1_d2, syspll1_ck, 1, 2), + FACTOR(TOP_SYSPLL1_D4, syspll1_d4, syspll1_ck, 1, 4), + FACTOR(TOP_SYSPLL1_D8, syspll1_d8, syspll1_ck, 1, 8), + + FACTOR(TOP_SYSPLL2_CK, syspll2_ck, mainpll, 1, 3), + FACTOR(TOP_SYSPLL2_D2, syspll2_d2, syspll2_ck, 1, 2), + FACTOR(TOP_SYSPLL2_D4, syspll2_d4, syspll2_ck, 1, 4), + + FACTOR(TOP_SYSPLL3_CK, syspll3_ck, mainpll, 1, 5), + FACTOR(TOP_SYSPLL3_D2, syspll3_d2, syspll3_ck, 1, 2), + FACTOR(TOP_SYSPLL3_D4, syspll3_d4, syspll3_ck, 1, 4), + + FACTOR(TOP_SYSPLL4_CK, syspll4_ck, mainpll, 1, 7), + FACTOR(TOP_SYSPLL4_D2, syspll4_d2, syspll4_ck, 1, 2), + FACTOR(TOP_SYSPLL4_D4, syspll4_d4, syspll4_ck, 1, 4), + + FACTOR(TOP_TVDPLL_CK, tvdpll_ck, tvdpll, 1, 1), + FACTOR(TOP_TVDPLL_D2, tvdpll_d2, tvdpll, 1, 2), + FACTOR(TOP_TVDPLL_D4, tvdpll_d4, tvdpll, 1, 4), + FACTOR(TOP_TVDPLL_D8, tvdpll_d8, tvdpll, 1, 8), + FACTOR(TOP_TVDPLL_D16, tvdpll_d16, tvdpll, 1, 16), + + + FACTOR(TOP_UNIVPLL_CK, univpll_ck, univpll, 1, 1), + FACTOR(TOP_UNIVPLL_D26, univpll_d26, univpll, 1, 26), + FACTOR(TOP_UNIVPLL_D7, univpll_d7, univpll, 1, 7), + FACTOR(TOP_UNIVPLL_D5, univpll_d5, univpll, 1, 5), + FACTOR(TOP_UNIVPLL_D3, univpll_d3, univpll, 1, 3), + FACTOR(TOP_UNIVPLL_D2, univpll_d2, univpll, 1, 2), + + FACTOR(TOP_UNIVPLL1_CK, univpll1_ck, univpll, 1, 2), + FACTOR(TOP_UNIVPLL1_D2, univpll1_d2, univpll1_ck, 1, 2), + FACTOR(TOP_UNIVPLL1_D4, univpll1_d4, univpll1_ck, 1, 4), + FACTOR(TOP_UNIVPLL1_D8, univpll1_d8, univpll1_ck, 1, 8), + + FACTOR(TOP_UNIVPLL2_CK, univpll2_ck, univpll, 1, 3), + FACTOR(TOP_UNIVPLL2_D2, univpll2_d2, univpll2_ck, 1, 2), + FACTOR(TOP_UNIVPLL2_D4, univpll2_d4, univpll2_ck, 1, 4), + FACTOR(TOP_UNIVPLL2_D8, univpll2_d8, univpll2_ck, 1, 8), + + FACTOR(TOP_UNIVPLL3_CK, univpll3_ck, univpll, 1, 5), + FACTOR(TOP_UNIVPLL3_D2, univpll3_d2, univpll3_ck, 1, 2), + FACTOR(TOP_UNIVPLL3_D4, univpll3_d4, univpll3_ck, 1, 4), + + FACTOR(TOP_VENCPLL_CK, vencpll_ck, vencpll, 1, 1), + FACTOR(INFRA_CLK_13M, clk13m, clk26m, 1, 2), + /*FACTOR(TOP_VENCPLL_D3, vencpll_d3, vencpll, 1, 1), + FACTOR(TOP_WHPLL_AUDIO_CK, whpll_audio_ck, clk_null, 1, 1),*/ +}; + +static void __init init_clk_top_div(struct clk_onecell_data *clk_data) +{ + init_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); +} + +static const char *axi_parents[] __initconst = { + clk26m, + syspll1_d4, + syspll2_d2, + osc_d8}; + +static const char *mem_parents[] __initconst = { + dmpll_ck}; + +static const char *ddrphycfg_parents[] __initconst = { + clk26m, + syspll1_d8}; + +static const char *mm_parents[] __initconst = { + clk26m, + syspll_d3, + vencpll_ck, + syspll1_d2, + syspll2_d2, + syspll_d7, + syspll2_d4, + syspll4_d2}; + +static const char *pwm_parents[] __initconst = { + clk26m, + univpll2_d2, + univpll2_d4}; + +static const char *vdec_parents[] __initconst = { + clk26m, + univpll1_d2, + vencpll_ck, + univpll_d5, + syspll1_d4}; + +static const char *mfg_parents[] __initconst = { + clk26m, + mmpll_ck, + univpll_d3, + syspll_d3 +}; + +static const char *camtg_parents[] __initconst = { + clk26m, + univpll_d26, + univpll2_d2, +}; + +static const char *uart_parents[] __initconst = { + clk26m, + univpll2_d8 +}; + +static const char *spi_parents[] __initconst = { + clk26m, + syspll3_d2, + syspll2_d4, + msdcpll_d4 +}; +/* +static const char *usb20_parents[] __initconst = { + clk26m, + univpll1_d8, + univpll3_d4 +}; +*/ + +static const char *msdc50_0_hclk_parents[] __initconst = { + clk26m, + syspll1_d2, + syspll2_d2, + syspll4_d2 +}; + +static const char *msdc50_0_parents[] __initconst = { + clk26m, + msdcpll_ck, + msdcpll_d2, + univpll1_d4, + syspll2_d2, + syspll_d7, + msdcpll_d4, + univpll_d2, + univpll1_d2 +}; + +/* +static const char *msdc30_0_parents[] __initconst = { + clk26m, + msdcpll_ck, + msdcpll_d2, + msdcpll_d4, + syspll2_d2, + syspll1_d4, + univpll1_d4, + univpll_d3, + univpll_d26, + syspll2_d4, + univpll_d2 +}; +*/ +static const char *msdc30_1_parents[] __initconst = { + clk26m, + univpll2_d2, + msdcpll_d4, + univpll1_d4, + syspll2_d2, + syspll_d7, + univpll_d7, + msdcpll_d2 +}; + +static const char *msdc30_2_parents[] __initconst = { + clk26m, + univpll2_d2, + msdcpll_d4, + univpll1_d4, + syspll2_d2, + syspll_d7, + univpll_d7, + msdcpll_d2 +}; + +static const char *msdc30_3_parents[] __initconst = { + clk26m, + msdcpll_d8, + msdcpll_d4, + univpll1_d4, + univpll_d26, + syspll_d7, + univpll_d7, + syspll3_d4, + msdcpll_d16 +}; + +static const char *audio_parents[] __initconst = { + clk26m, + syspll3_d4, + syspll4_d4, + syspll1_d16 +}; + +static const char *aud_intbus_parents[] __initconst = { + clk26m, + syspll1_d4, + syspll4_d2 +}; + +static const char *pmicspi_parents[] __initconst = { + clk26m, + syspll1_d8, + osc_d4 +}; +/* +static const char *scp_parents[] __initconst = { + clk26m, + syspll1_d8, + dmpll_d2, + dmpll_d4 +}; +*/ +static const char *atb_parents[] __initconst = { + clk26m, + syspll1_d2, + syspll_d5 +}; + +static const char *dpi0_parents[] __initconst = { + clk26m, + tvdpll_d2, + tvdpll_d4, + tvdpll_d8, + tvdpll_d16 +}; + +static const char *scam_parents[] __initconst = { + clk26m, + syspll3_d2 +}; +/* +static const char *mfg13m_parents[] __initconst = { + clk26m, + ad_sys_ +}; +*/ +static const char *aud_1_parents[] __initconst = { + clk26m, + apll1_ck +}; + +static const char *aud_2_parents[] __initconst = { + clk26m, + apll2_ck +}; +/* +static const char *irda_parents[] __initconst = { + clk26m, + univpll2_d4 +}; + +static const char *irtx_parents[] __initconst = { + clk26m, + ad_sys_26m_ck +}; +*/ +static const char *disppwm_parents[] __initconst = { + clk26m, + univpll2_d4, + osc_d2, + osc_d8 +}; +/* extra 6 */ + +static const char *ssusb_top_sys_parents[] __initconst = { + clk26m, + univpll3_d2 +}; + +static const char *usb_top_parents[] __initconst = { + clk26m, + univpll3_d4 +}; + +static const char *spm_parents[] __initconst = { + clk26m, + syspll1_d8 +}; + +static const char *bsi_spi_parents[] __initconst = { + clk26m, + syspll_d3_d3, + syspll1_d4, + syspll_d7 +}; + +static const char *i2c_parents[] __initconst = { + clk26m, + syspll1_d8, + univpll3_d4 +}; +static const char *dvfsp_parents[] __initconst = { + clk26m, + syspll1_d8 +}; + + + + +#ifndef _MUX_UPDS_ +struct mtk_mux { + int id; + const char *name; + uint32_t reg; + int shift; + int width; + int gate; + const char **parent_names; + int num_parents; +}; + +#define MUX(_id, _name, _parents, _reg, _shift, _width, _gate) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .shift = _shift, \ + .width = _width, \ + .gate = _gate, \ + .parent_names = (const char **)_parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + } + +static struct mtk_mux top_muxes[] __initdata = { + /* CLK_CFG_0 */ + MUX(TOP_MUX_AXI, axi_sel, axi_parents, 0x0040, 0, 2, INVALID_MUX_GATE_BIT), + MUX(TOP_MUX_MEM, mem_sel, mem_parents, 0x0040, 8, 2, INVALID_MUX_GATE_BIT), + /*why not 23 pdn bit*/ + MUX(TOP_MUX_DDRPHY, ddrphycfg_sel, ddrphycfg_parents, 0x0040, 16, 1, INVALID_MUX_GATE_BIT), + MUX(TOP_MUX_MM, mm_sel, mm_parents, 0x0040, 24, 3, 31), + /* CLK_CFG_1 */ + MUX(TOP_MUX_PWM, pwm_sel, pwm_parents, 0x0050, 0, 2, 7), + MUX(TOP_MUX_VDEC, vdec_sel, vdec_parents, 0x0050, 8, 3, 15), + MUX(TOP_MUX_MFG, mfg_sel, mfg_parents, 0x0050, 24, 2, 31), + /* CLK_CFG_2 */ + MUX(TOP_MUX_CAMTG, camtg_sel, camtg_parents, 0x0060, 0, 2, 7), + MUX(TOP_MUX_UART, uart_sel, uart_parents, 0x0060, 8, 1, 15), + MUX(TOP_MUX_SPI, spi_sel, spi_parents, 0x0060, 16, 2, 23), + /* CLK_CFG_3 */ + MUX(TOP_MUX_MSDC50_0_HCLK, msdc50_0_hclk_sel, msdc50_0_hclk_parents, 0x0070, 8, 2, 15), + MUX(TOP_MUX_MSDC50_0, msdc50_0_sel, msdc50_0_parents, 0x0070, 16, 4, 23), + MUX(TOP_MUX_MSDC30_1, msdc30_1_sel, msdc30_1_parents, 0x0070, 24, 4, 31), + /* CLK_CFG_4 */ + MUX(TOP_MUX_MSDC30_2, msdc30_2_sel, msdc30_2_parents, 0x0080, 0, 4, 7), + MUX(TOP_MUX_MSDC30_3, msdc30_3_sel, msdc30_3_parents, 0x0080, 8, 4, 15), + MUX(TOP_MUX_AUDIO, audio_sel, audio_parents, 0x0080, 16, 2, 23), + MUX(TOP_MUX_AUDINTBUS, aud_intbus_sel, aud_intbus_parents, 0x0080, 24, 2, 31), + /* CLK_CFG_5 */ + MUX(TOP_MUX_PMICSPI, pmicspi_sel, pmicspi_parents, 0x0090, 0, 2, INVALID_MUX_GATE_BIT), + /*MUX(TOP_MUX_SCP, scp_sel, scp_parents, 0x0090, 8, 2, 15),*/ + MUX(TOP_MUX_ATB, atb_sel, atb_parents, 0x0090, 16, 2, 23), + /*MUX(TOP_MUX_MJC, mjc_sel, mjc_parents, 0x0090, 24, 2, 31),*/ + /* CLK_CFG_6 */ + MUX(TOP_MUX_DPI0, dpi0_sel, dpi0_parents, 0x00a0, 0, 3, 7), + MUX(TOP_MUX_SCAM, scam_sel, scam_parents, 0x00a0, 8, 1, 15), + MUX(TOP_MUX_AUD1, aud_1_sel, aud_1_parents, 0x00a0, 16, 1, 23), + MUX(TOP_MUX_AUD2, aud_2_sel, aud_2_parents, 0x00a0, 24, 1, 31), +/* CLK_CFG_7 */ + MUX(TOP_MUX_DISPPWM, disppwm_sel, disppwm_parents, 0x00b0, 0, 2, 7), + MUX(TOP_MUX_SSUSBTOPSYS, ssusb_top_sys_sel, ssusb_top_sys_parents, 0x00b0, 8, 1, 15), + MUX(TOP_MUX_USBTOP, usb_top_sel, usb_top_parents, 0x00b0, 24, 1, 31), + /* CLK_CFG_8 */ + MUX(TOP_MUX_SPM, spm_sel, spm_parents, 0x00c0, 0, 1, 7), + MUX(TOP_MUX_BSISPI, bsi_spi_sel, bsi_spi_parents, 0x00c0, 8, 2, 15), + MUX(TOP_MUX_I2C, i2c_sel, i2c_parents, 0x00c0, 16, 2, INVALID_MUX_GATE_BIT), + MUX(TOP_MUX_DVFSP, dvfsp_sel, dvfsp_parents, 0x00c0, 24, 1, 31), +}; +#else + +#define _UPDATE_REG 0x04 +#define _UPDATE1_REG 0x08 +#define INVALID_UPDATE_REG 0xFFFFFFFF +#define INVALID_UPDATE_SHIFT -1 +#define INVALID_MUX_GATE -1 +#ifdef _MUX_CLR_SET_UPDS_ +static struct mtk_mux_clr_set_upd top_muxes[] __initdata = { + /* CLK_CFG_0 */ + MUX_CLR_SET_UPD(TOP_MUX_AXI, axi_sel, axi_parents, 0x0040, 0x0044, 0x0048, 0, 2, + INVALID_MUX_GATE, _UPDATE_REG, 0), + MUX_CLR_SET_UPD(TOP_MUX_MEM, mem_sel, mem_parents, 0x0040, 0x0044, 0x0048, 8, 2, + INVALID_MUX_GATE, _UPDATE_REG, 1), + /*why not 23 pdn bit*/ + MUX_CLR_SET_UPD(TOP_MUX_DDRPHY, ddrphycfg_sel, ddrphycfg_parents, 0x0040, 0x0044, 0x0048, 16, 1, + INVALID_MUX_GATE, _UPDATE_REG, 2), + MUX_CLR_SET_UPD(TOP_MUX_MM, mm_sel, mm_parents, 0x0040, 0x0044, 0x0048, 24, 3, + INVALID_MUX_GATE, _UPDATE_REG, 3), + /* CLK_CFG_1 */ + MUX_CLR_SET_UPD(TOP_MUX_PWM, pwm_sel, pwm_parents, 0x0050, 0x0054, 0x0058, 0, 2, + INVALID_MUX_GATE, _UPDATE_REG, 4), + MUX_CLR_SET_UPD(TOP_MUX_VDEC, vdec_sel, vdec_parents, 0x0050, 0x0054, 0x0058, 8, 3, + INVALID_MUX_GATE, _UPDATE_REG, 5), + MUX_CLR_SET_UPD(TOP_MUX_MFG, mfg_sel, mfg_parents, 0x0050, 0x0054, 0x0058, 24, 2, + INVALID_MUX_GATE, _UPDATE_REG, 7), + /* CLK_CFG_2 */ + MUX_CLR_SET_UPD(TOP_MUX_CAMTG, camtg_sel, camtg_parents, 0x0060, 0x0064, 0x0068, 0, 2, + INVALID_MUX_GATE, _UPDATE_REG, 8), + MUX_CLR_SET_UPD(TOP_MUX_UART, uart_sel, uart_parents, 0x0060, 0x0064, 0x0068, 8, 1, + INVALID_MUX_GATE, _UPDATE_REG, 9), + MUX_CLR_SET_UPD(TOP_MUX_SPI, spi_sel, spi_parents, 0x0060, 0x0064, 0x0068, 16, 2, + INVALID_MUX_GATE, _UPDATE_REG, 10), + /* CLK_CFG_3 */ + MUX_CLR_SET_UPD(TOP_MUX_MSDC50_0_HCLK, msdc50_0_hclk_sel, msdc50_0_hclk_parents, 0x0070, 0x0074, 0x0078, 8, 2, + INVALID_MUX_GATE, _UPDATE_REG, 12), + MUX_CLR_SET_UPD(TOP_MUX_MSDC50_0, msdc50_0_sel, msdc50_0_parents, 0x0070, 0x0074, 0x0078, 16, 4, + INVALID_MUX_GATE, _UPDATE_REG, 13), + MUX_CLR_SET_UPD(TOP_MUX_MSDC30_1, msdc30_1_sel, msdc30_1_parents, 0x0070, 0x0074, 0x0078, 24, 4, + INVALID_MUX_GATE, _UPDATE_REG, 14), + /* CLK_CFG_4 */ + MUX_CLR_SET_UPD(TOP_MUX_MSDC30_2, msdc30_2_sel, msdc30_2_parents, 0x0080, 0x0084, 0x0088, 0, 4, + INVALID_MUX_GATE, _UPDATE_REG, 15), + MUX_CLR_SET_UPD(TOP_MUX_MSDC30_3, msdc30_3_sel, msdc30_3_parents, 0x0080, 0x0084, 0x0088, 8, 4, + INVALID_MUX_GATE, _UPDATE_REG, 16), + MUX_CLR_SET_UPD(TOP_MUX_AUDIO, audio_sel, audio_parents, 0x0080, 0x0084, 0x0088, 16, 2, + INVALID_MUX_GATE, _UPDATE_REG, 17), + MUX_CLR_SET_UPD(TOP_MUX_AUDINTBUS, aud_intbus_sel, aud_intbus_parents, 0x0080, 0x0084, 0x0088, 24, 2, + INVALID_MUX_GATE, _UPDATE_REG, 18), + /* CLK_CFG_5 */ + MUX_CLR_SET_UPD(TOP_MUX_PMICSPI, pmicspi_sel, pmicspi_parents, 0x0090, 0x0094, 0x0098, 0, 2, + INVALID_MUX_GATE, _UPDATE_REG, 19), + MUX_CLR_SET_UPD(TOP_MUX_ATB, atb_sel, atb_parents, 0x0090, 0x0094, 0x0098, 16, 2, + INVALID_MUX_GATE, _UPDATE_REG, 21), + /* CLK_CFG_6 */ + MUX_CLR_SET_UPD(TOP_MUX_DPI0, dpi0_sel, dpi0_parents, 0x00a0, 0x00a4, 0x00a8, 0, 3, + INVALID_MUX_GATE, _UPDATE_REG, 23), + MUX_CLR_SET_UPD(TOP_MUX_SCAM, scam_sel, scam_parents, 0x00a0, 0x00a4, 0x00a8, 8, 1, + INVALID_MUX_GATE, _UPDATE_REG, 24), + MUX_CLR_SET_UPD(TOP_MUX_AUD1, aud_1_sel, aud_1_parents, 0x00a0, 0x00a4, 0x00a8, 16, 1, + INVALID_MUX_GATE, _UPDATE_REG, 25), + MUX_CLR_SET_UPD(TOP_MUX_AUD2, aud_2_sel, aud_2_parents, 0x00a0, 0x00a4, 0x00a8, 24, 1, + INVALID_MUX_GATE, _UPDATE_REG, 26), + /* CLK_CFG_7 */ + MUX_CLR_SET_UPD(TOP_MUX_DISPPWM, disppwm_sel, disppwm_parents, 0x00b0, 0x00b4, 0x00b8, 0, 2, + INVALID_MUX_GATE, _UPDATE_REG, 27), + MUX_CLR_SET_UPD(TOP_MUX_SSUSBTOPSYS, ssusb_top_sys_sel, ssusb_top_sys_parents, 0x00b0, 0x00b4, 0x00b8, 8, 1, + INVALID_MUX_GATE, _UPDATE_REG, 28), + MUX_CLR_SET_UPD(TOP_MUX_USBTOP, usb_top_sel, usb_top_parents, 0x00b0, 0x00b4, 0x00b8, 24, 1, + INVALID_MUX_GATE, _UPDATE_REG, 30), + /* CLK_CFG_8 */ + MUX_CLR_SET_UPD(TOP_MUX_SPM, spm_sel, spm_parents, 0x00c0, 0x00c4, 0x00c8, 0, 1, + INVALID_MUX_GATE, _UPDATE_REG, 31), + MUX_CLR_SET_UPD(TOP_MUX_BSISPI, bsi_spi_sel, bsi_spi_parents, 0x00c0, 0x00c4, 0x00c8, 8, 2, + INVALID_MUX_GATE, _UPDATE1_REG, 0), + MUX_CLR_SET_UPD(TOP_MUX_I2C, i2c_sel, i2c_parents, 0x00c0, 0x00c4, 0x00c8, 16, 2, + INVALID_MUX_GATE, _UPDATE1_REG, 1), + MUX_CLR_SET_UPD(TOP_MUX_DVFSP, dvfsp_sel, dvfsp_parents, 0x00c0, 0x00c4, 0x00c8, 24, 1, + INVALID_MUX_GATE, _UPDATE1_REG, 2), +}; +#else +static struct mtk_mux_upd top_muxes[] __initdata = { + /* CLK_CFG_0 */ + MUX_UPD(TOP_MUX_AXI, axi_sel, axi_parents, 0x0040, 0, 2, INVALID_MUX_GATE, _UPDATE_REG, 0), + MUX_UPD(TOP_MUX_MEM, mem_sel, mem_parents, 0x0040, 8, 2, INVALID_MUX_GATE, _UPDATE_REG, 1), + /*why not 23 pdn bit*/ + MUX_UPD(TOP_MUX_DDRPHY, ddrphycfg_sel, ddrphycfg_parents, 0x0040, 16, 1, INVALID_MUX_GATE, _UPDATE_REG, 2), + MUX_UPD(TOP_MUX_MM, mm_sel, mm_parents, 0x0040, 24, 3, INVALID_MUX_GATE, _UPDATE_REG, 3), + /* CLK_CFG_1 */ + MUX_UPD(TOP_MUX_PWM, pwm_sel, pwm_parents, 0x0050, 0, 2, INVALID_MUX_GATE, _UPDATE_REG, 4), + MUX_UPD(TOP_MUX_VDEC, vdec_sel, vdec_parents, 0x0050, 8, 3, INVALID_MUX_GATE, _UPDATE_REG, 5), + MUX_UPD(TOP_MUX_MFG, mfg_sel, mfg_parents, 0x0050, 24, 2, INVALID_MUX_GATE, _UPDATE_REG, 7), + /* CLK_CFG_2 */ + MUX_UPD(TOP_MUX_CAMTG, camtg_sel, camtg_parents, 0x0060, 0, 2, INVALID_MUX_GATE, _UPDATE_REG, 8), + MUX_UPD(TOP_MUX_UART, uart_sel, uart_parents, 0x0060, 8, 1, INVALID_MUX_GATE, _UPDATE_REG, 9), + MUX_UPD(TOP_MUX_SPI, spi_sel, spi_parents, 0x0060, 16, 2, INVALID_MUX_GATE, _UPDATE_REG, 10), + /* CLK_CFG_3 */ + MUX_UPD(TOP_MUX_MSDC50_0_HCLK, msdc50_0_hclk_sel, msdc50_0_hclk_parents, + 0x0070, 8, 2, INVALID_MUX_GATE, _UPDATE_REG, 12), + MUX_UPD(TOP_MUX_MSDC50_0, msdc50_0_sel, msdc50_0_parents, 0x0070, 16, 4, INVALID_MUX_GATE, _UPDATE_REG, 13), + MUX_UPD(TOP_MUX_MSDC30_1, msdc30_1_sel, msdc30_1_parents, 0x0070, 24, 4, INVALID_MUX_GATE, _UPDATE_REG, 14), + /* CLK_CFG_4 */ + MUX_UPD(TOP_MUX_MSDC30_2, msdc30_2_sel, msdc30_2_parents, 0x0080, 0, 4, INVALID_MUX_GATE, _UPDATE_REG, 15), + MUX_UPD(TOP_MUX_MSDC30_3, msdc30_3_sel, msdc30_3_parents, 0x0080, 8, 4, INVALID_MUX_GATE, _UPDATE_REG, 16), + MUX_UPD(TOP_MUX_AUDIO, audio_sel, audio_parents, 0x0080, 16, 2, INVALID_MUX_GATE, _UPDATE_REG, 17), + MUX_UPD(TOP_MUX_AUDINTBUS, aud_intbus_sel, aud_intbus_parents, + 0x0080, 24, 2, INVALID_MUX_GATE, _UPDATE_REG, 18), + /* CLK_CFG_5 */ + MUX_UPD(TOP_MUX_PMICSPI, pmicspi_sel, pmicspi_parents, 0x0090, 0, 2, INVALID_MUX_GATE, _UPDATE_REG, 19), + /*MUX(TOP_MUX_SCP, scp_sel, scp_parents, 0x0090, 8, 2, 15),*/ + MUX_UPD(TOP_MUX_ATB, atb_sel, atb_parents, 0x0090, 16, 2, INVALID_MUX_GATE, _UPDATE_REG, 21), + /*MUX(TOP_MUX_MJC, mjc_sel, mjc_parents, 0x0090, 24, 2, 31),*/ + /* CLK_CFG_6 */ + MUX_UPD(TOP_MUX_DPI0, dpi0_sel, dpi0_parents, 0x00a0, 0, 3, INVALID_MUX_GATE, _UPDATE_REG, 23), + MUX_UPD(TOP_MUX_SCAM, scam_sel, scam_parents, 0x00a0, 8, 1, INVALID_MUX_GATE, _UPDATE_REG, 24), + MUX_UPD(TOP_MUX_AUD1, aud_1_sel, aud_1_parents, 0x00a0, 16, 1, INVALID_MUX_GATE, _UPDATE_REG, 25), + MUX_UPD(TOP_MUX_AUD2, aud_2_sel, aud_2_parents, 0x00a0, 24, 1, INVALID_MUX_GATE, _UPDATE_REG, 26), + /* CLK_CFG_7 */ + MUX_UPD(TOP_MUX_DISPPWM, disppwm_sel, disppwm_parents, 0x00b0, 0, 2, INVALID_MUX_GATE, _UPDATE_REG, 27), + MUX_UPD(TOP_MUX_SSUSBTOPSYS, ssusb_top_sys_sel, ssusb_top_sys_parents, + 0x00b0, 8, 1, INVALID_MUX_GATE, _UPDATE_REG, 28), + MUX_UPD(TOP_MUX_USBTOP, usb_top_sel, usb_top_parents, 0x00b0, 24, 1, INVALID_MUX_GATE, _UPDATE_REG, 30), + /* CLK_CFG_8 */ + MUX_UPD(TOP_MUX_SPM, spm_sel, spm_parents, 0x00c0, 0, 1, INVALID_MUX_GATE, _UPDATE_REG, 31), + MUX_UPD(TOP_MUX_BSISPI, bsi_spi_sel, bsi_spi_parents, 0x00c0, 8, 2, INVALID_MUX_GATE, _UPDATE1_REG, 0), + MUX_UPD(TOP_MUX_I2C, i2c_sel, i2c_parents, 0x00c0, 16, 2, INVALID_MUX_GATE, _UPDATE1_REG, 1), + MUX_UPD(TOP_MUX_DVFSP, dvfsp_sel, dvfsp_parents, 0x00c0, 24, 1, INVALID_MUX_GATE, _UPDATE1_REG, 2), +}; +#endif +#endif + +#ifndef _MUX_UPDS_ +static void __init init_clk_topckgen(void __iomem *top_base, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + + for (i = 0; i < ARRAY_SIZE(top_muxes); i++) { + struct mtk_mux *mux = &top_muxes[i]; + + clk = mtk_clk_register_mux(mux->name, + mux->parent_names, mux->num_parents, + top_base + mux->reg, mux->shift, mux->width, mux->gate); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + mux->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[mux->id] = clk; + +#if MT_CCF_DEBUG + pr_debug("[CCF] mux %3d: %s\n", i, mux->name); +#endif /* MT_CCF_DEBUG */ + } +} +#endif +struct mtk_pll { + int id; + const char *name; + const char *parent_name; + uint32_t reg; + uint32_t pwr_reg; + uint32_t en_mask; + unsigned int flags; + const struct clk_ops *ops; +}; + +#define PLL(_id, _name, _parent, _reg, _pwr_reg, _en_mask, _flags, _ops) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .ops = _ops, \ + } +/*ten pll*/ +static struct mtk_pll plls[] __initdata = { + PLL(APMIXED_ARMBPLL, armbpll, clk26m, 0x0200, 0x020C, 0x00000001, HAVE_PLL_HP, &mt_clk_arm_pll_ops), + PLL(APMIXED_ARMSPLL, armspll, clk26m, 0x0210, 0x021C, 0x00000001, HAVE_PLL_HP, &mt_clk_arm_pll_ops), + PLL(APMIXED_MAINPLL, mainpll, clk26m, 0x0220, 0x022C, 0xF0000101, HAVE_PLL_HP, &mt_clk_sdm_pll_ops), + PLL(APMIXED_UNIVPLL, univpll, clk26m, 0x0230, 0x023C, 0xFC000001, HAVE_FIX_FRQ, &mt_clk_univ_pll_ops), + PLL(APMIXED_MMPLL, mmpll, clk26m, 0x0240, 0x024C, 0x00000001, HAVE_PLL_HP, &mt_clk_mm_pll_ops), + PLL(APMIXED_MSDCPLL, msdcpll, clk26m, 0x0250, 0x025C, 0x00000001, HAVE_PLL_HP, &mt_clk_sdm_pll_ops), + PLL(APMIXED_VENCPLL, vencpll, clk26m, 0x0260, 0x026C, 0x00000001, HAVE_PLL_HP, &mt_clk_sdm_pll_ops), + PLL(APMIXED_TVDPLL, tvdpll, clk26m, 0x0270, 0x027C, 0x00000001, HAVE_PLL_HP, &mt_clk_sdm_pll_ops), + /*No.28 JADE NO MPLL*/ + /*No.29 JADE NO VCODEPLL? not list in PLL SPEC*/ + PLL(APMIXED_APLL1, apll1, clk26m, 0x02A0, 0x02B0, 0x00000001, HAVE_FIX_FRQ, &mt_clk_aud_pll_ops), + PLL(APMIXED_APLL2, apll2, clk26m, 0x02B4, 0x02C4, 0x00000001, HAVE_FIX_FRQ, &mt_clk_aud_pll_ops), + PLL(SCP_OSCPLL, oscpll, clk26m, 0x0458, 0x0458, 0x00000001, HAVE_FIX_FRQ, &mt_clk_spm_pll_ops), + /*PLL(APMIXED_ARMPLL, armpll, clk26m, 0x0200, 0x020C, 0x00000001, HAVE_PLL_HP, &mt_clk_arm_pll_ops),*/ +}; + +static void __init init_clk_apmixedsys(void __iomem *apmixed_base, void __iomem *spm_base, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + + for (i = 0; i < ARRAY_SIZE(plls); i++) { + struct mtk_pll *pll = &plls[i]; + if (!strcmp("oscpll", pll->name)) { + clk = mtk_clk_register_pll(pll->name, pll->parent_name, + spm_base + pll->reg, + spm_base + pll->pwr_reg, + pll->en_mask, pll->flags, pll->ops); + } else { + clk = mtk_clk_register_pll(pll->name, pll->parent_name, + apmixed_base + pll->reg, + apmixed_base + pll->pwr_reg, + pll->en_mask, pll->flags, pll->ops); + } + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + pll->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[pll->id] = clk; + +#if MT_CCF_DEBUG + pr_debug("[CCF] pll %3d: %s\n", i, pll->name); +#endif /* MT_CCF_DEBUG */ + } +} + +struct mtk_gate_regs { + u32 sta_ofs; + u32 clr_ofs; + u32 set_ofs; +}; + +struct mtk_gate { + int id; + const char *name; + const char *parent_name; + struct mtk_gate_regs *regs; + int shift; + uint32_t flags; +}; + +#define GATE(_id, _name, _parent, _regs, _shift, _flags) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &_regs, \ + .shift = _shift, \ + .flags = _flags, \ + } + +static void __init init_clk_gates( + void __iomem *reg_base, + struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + + for (i = 0; i < num; i++) { + struct mtk_gate *gate = &clks[i]; + + clk = mtk_clk_register_gate(gate->name, gate->parent_name, + reg_base + gate->regs->set_ofs, + reg_base + gate->regs->clr_ofs, + reg_base + gate->regs->sta_ofs, + gate->shift, gate->flags); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + gate->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[gate->id] = clk; + +#if MT_CCF_DEBUG + pr_debug("[CCF] gate %3d: %s\n", i, gate->name); +#endif /* MT_CCF_DEBUG */ + } +} + +static struct mtk_gate_regs infra0_cg_regs = { + .set_ofs = 0x0080, + .clr_ofs = 0x0084, + .sta_ofs = 0x0090, +}; +static struct mtk_gate_regs infra1_cg_regs = { + .set_ofs = 0x0088, + .clr_ofs = 0x008c, + .sta_ofs = 0x0094, +}; +static struct mtk_gate_regs infra2_cg_regs = { + .set_ofs = 0x00a4, + .clr_ofs = 0x00a8, + .sta_ofs = 0x00ac, +}; + +static struct mtk_gate infra_clks[] __initdata = { + /* INFRA0 */ + GATE(INFRA_PMIC_TMR, infra_pmictmr, pmicspi_sel, infra0_cg_regs, 0, 0), + GATE(INFRA_PMIC_AP, infra_pmicap, pmicspi_sel, infra0_cg_regs, 1, 0), + GATE(INFRA_PMIC_MD, infra_pmicmd, pmicspi_sel, infra0_cg_regs, 2, 0), + GATE(INFRA_PMIC_CONN, infra_pmicconn, pmicspi_sel, infra0_cg_regs, 3, 0), + /*GATE(INFRA_SCPSYS, infra_scpsys, null, infra0_cg_regs, 4, 0),*/ + GATE(INFRA_SEJ, infra_sej, f26m_sel, infra0_cg_regs, 5, 0),/*?*/ + GATE(INFRA_APXGPT, infra_apxgpt, axi_sel, infra0_cg_regs, 6, 0), + GATE(INFRA_ICUSB, infra_icusb, axi_sel, infra0_cg_regs, 8, 0), + GATE(INFRA_GCE, infra_gce, axi_sel, infra0_cg_regs, 9, 0), + GATE(INFRA_THERM, infra_therm, axi_sel, infra0_cg_regs, 10, 0), + GATE(INFRA_I2C0, infra_i2c0, i2c_sel, infra0_cg_regs, 11, 0), + GATE(INFRA_I2C1, infra_i2c1, i2c_sel, infra0_cg_regs, 12, 0), + GATE(INFRA_I2C2, infra_i2c2, i2c_sel, infra0_cg_regs, 13, 0), + GATE(INFRA_I2C3, infra_i2c3, i2c_sel, infra0_cg_regs, 14, 0), + GATE(INFRA_PWM_HCLK, infra_pwmhclk, axi_sel, infra0_cg_regs, 15, 0), + GATE(INFRA_PWM1, infra_pwm1, i2c_sel, infra0_cg_regs, 16, 0), + GATE(INFRA_PWM2, infra_pwm2, i2c_sel, infra0_cg_regs, 17, 0), + GATE(INFRA_PWM3, infra_pwm3, i2c_sel, infra0_cg_regs, 18, 0), + GATE(INFRA_PWM4, infra_pwm4, i2c_sel, infra0_cg_regs, 19, 0), + GATE(INFRA_PWM, infra_pwm, i2c_sel, infra0_cg_regs, 21, 0), + GATE(INFRA_UART0, infra_uart0, uart_sel, infra0_cg_regs, 22, 0), + GATE(INFRA_UART1, infra_uart1, uart_sel, infra0_cg_regs, 23, 0), + GATE(INFRA_UART2, infra_uart2, uart_sel, infra0_cg_regs, 24, 0), + GATE(INFRA_UART3, infra_uart3, uart_sel, infra0_cg_regs, 25, 0), + GATE(INFRA_MD2MD_CCIF0, infra_md2mdccif0, axi_sel, infra0_cg_regs, 27, 0), + GATE(INFRA_MD2MD_CCIF1, infra_md2mdccif1, axi_sel, infra0_cg_regs, 28, 0), + GATE(INFRA_MD2MD_CCIF2, infra_md2mdccif2, axi_sel, infra0_cg_regs, 29, 0), + GATE(INFRA_BTIF, infra_btif, axi_sel, infra0_cg_regs, 31, 0), + /* INFRA1 */ + GATE(INFRA_MD2MD_CCIF3, infra_md2mdccif3, axi_sel, infra1_cg_regs, 0, 0), + GATE(INFRA_SPI0, infra_spi0, spi_sel, infra1_cg_regs, 1, 0), + GATE(INFRA_MSDC0, infra_msdc0, msdc50_0_sel, infra1_cg_regs, 2, 0), + GATE(INFRA_MD2MD_CCIF4, infra_md2mdccif4, axi_sel, infra1_cg_regs, 3, 0), + GATE(INFRA_MSDC1, infra_msdc1, msdc30_1_sel, infra1_cg_regs, 4, 0), + GATE(INFRA_MSDC2, infra_msdc2, msdc30_2_sel, infra1_cg_regs, 5, 0), + GATE(INFRA_MSDC3, infra_msdc3, msdc30_3_sel, infra1_cg_regs, 6, 0), + GATE(INFRA_MD2MD_CCIF5, infra_md2mdccif5, axi_sel, infra1_cg_regs, 7, 0), + GATE(INFRA_GCPU, infra_gcpu, axi_sel, infra1_cg_regs, 8, 0), + GATE(INFRA_TRNG, infra_trng, axi_sel, infra1_cg_regs, 9, 0), + GATE(INFRA_AUXADC, infra_auxadc, f26m_sel, infra1_cg_regs, 10, 0), + GATE(INFRA_CPUM, infra_cpum, axi_sel, infra1_cg_regs, 11, 0), + GATE(INFRA_CCIF1_AP, infra_ccif1ap, axi_sel, infra1_cg_regs, 12, 0), + GATE(INFRA_CCIF1_MD, infra_ccif1md, axi_sel, infra1_cg_regs, 13, 0), + /*GATE(INFRA_NFI, infra_nfi, axi_sel, infra1_cg_regs, 16, 0), + GATE(INFRA_NFI_ECC, infra_nfiecc, axi_sel, infra1_cg_regs, 17, 0),*/ + GATE(INFRA_AP_DMA, infra_apdma, axi_sel, infra1_cg_regs, 18, 0), + GATE(INFRA_XIU, infra_xiu, axi_sel, infra1_cg_regs, 19, 0), + GATE(INFRA_DEVICE_APC, infra_deviceapc, axi_sel, infra1_cg_regs, 20, 0), + GATE(INFRA_XIU2AHB, infra_xiu2ahb, axi_sel, infra1_cg_regs, 21, 0), + /*GATE(INFRA_L2C_SRAM, infra_l2csram, axi_sel, infra1_cg_regs, 22, 0),*/ + GATE(INFRA_CCIF_AP, infra_ccifap, axi_sel, infra1_cg_regs, 23, 0), + GATE(INFRA_DEBUGSYS, infra_debugsys, axi_sel, infra1_cg_regs, 24, 0), + GATE(INFRA_AUDIO, infra_audio, axi_sel, infra1_cg_regs, 25, 0), + GATE(INFRA_CCIF_MD, infra_ccifmd, axi_sel, infra1_cg_regs, 26, 0), + GATE(INFRA_DRAMC_F26M, infra_dramcf26m, f26m_sel, infra1_cg_regs, 31, 0), + + + /* INFRA2 */ + GATE(INFRA_IRTX, infra_irtx, f26m_sel, infra2_cg_regs, 0, 0), + GATE(INFRA_SSUSB_TOP, infra_ssusbtop, ssusb_top_sys_sel, infra2_cg_regs, 1, 0), + GATE(INFRA_DISP_PWM, infra_disppwm, axi_sel, infra2_cg_regs, 2, 0), + GATE(INFRA_CLDMA_BCLK, infra_cldmabclk, clk_null, infra2_cg_regs, 3, 0), + GATE(INFRA_AUDIO_26M_BCLK, infra_audio26mbclk, clk_null, infra2_cg_regs, 4, 0), + GATE(INFRA_MD_TEMP_26M_BCLK, infra_mdtmp26mbclk, clk_null, infra2_cg_regs, 5, 0), + GATE(INFRA_SPI1, infra_spi1, spi_sel, infra2_cg_regs, 6, 0), + GATE(INFRA_I2C4, infra_i2c4, i2c_sel, infra2_cg_regs, 7, 0), + GATE(INFRA_MD_TEMP_SHARE, infra_mdtmpshare, clk_null, infra2_cg_regs, 8, 0), + +#if 0 + GATE(INFRA_DBGCLK, infra_dbgclk, axi_sel, infra_cg_regs, 0, 0), + GATE(INFRA_GCE, infra_gce, axi_sel, infra_cg_regs, 1, 0), + GATE(INFRA_TRBG, infra_trbg, axi_sel, infra_cg_regs, 2, 0), + GATE(INFRA_CPUM, infra_cpum, axi_sel, infra_cg_regs, 3, 0), + GATE(INFRA_DEVAPC, infra_devapc, axi_sel, infra_cg_regs, 4, 0), + GATE(INFRA_AUDIO, infra_audio, aud_intbus_sel, infra_cg_regs, 5, 0), + GATE(INFRA_GCPU, infra_gcpu, axi_sel, infra_cg_regs, 6, 0), + GATE(INFRA_L2C_SRAM, infra_l2csram, axi_sel, infra_cg_regs, 7, 0), + GATE(INFRA_M4U, infra_m4u, axi_sel, infra_cg_regs, 8, 0), + GATE(INFRA_CLDMA, infra_cldma, axi_sel, infra_cg_regs, 12, 0), + GATE(INFRA_CONNMCU_BUS, infra_connmcubus, axi_sel, infra_cg_regs, 15, 0), + GATE(INFRA_KP, infra_kp, axi_sel, infra_cg_regs, 16, 0), + GATE(INFRA_APXGPT, infra_apxgpt, axi_sel, infra_cg_regs, 18, 0), + GATE(INFRA_SEJ, infra_sej, axi_sel, infra_cg_regs, 19, 0), + GATE(INFRA_CCIF0_AP, infra_ccif0ap, axi_sel, infra_cg_regs, 20, 0), + GATE(INFRA_CCIF1_AP, infra_ccif1ap, axi_sel, infra_cg_regs, 21, 0), + GATE(INFRA_PMIC_SPI, infra_pmicspi, pmicspi_sel, infra_cg_regs, 22, 0), + GATE(INFRA_PMIC_WRAP, infra_pmicwrap, axi_sel, infra_cg_regs, 23, 0), +#endif + +}; + +static void __init init_clk_infrasys(void __iomem *infrasys_base, + struct clk_onecell_data *clk_data) +{ + pr_debug("[CCF] init infrasys gates:\n"); + init_clk_gates(infrasys_base, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); +} + +#if 0 +static struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x0010, + .sta_ofs = 0x0018, +}; + +static struct mtk_gate peri_clks[] __initdata = { + + /*GATE(PERI_AXI, peri_axi, periaxi_sel, peri0_cg_regs, 31, 0),//not perisys, periconfig*/ +#if 0 + GATE(PERI_DISP_PWM, peri_disp_pwm, disppwm_sel, peri0_cg_regs, 0, 0), + GATE(PERI_THERM, peri_therm, axi_sel, peri0_cg_regs, 1, 0), + GATE(PERI_PWM1, peri_pwm1, axi_sel, peri0_cg_regs, 2, 0), + GATE(PERI_PWM2, peri_pwm2, axi_sel, peri0_cg_regs, 3, 0), + GATE(PERI_PWM3, peri_pwm3, axi_sel, peri0_cg_regs, 4, 0), + GATE(PERI_PWM4, peri_pwm4, axi_sel, peri0_cg_regs, 5, 0), + GATE(PERI_PWM5, peri_pwm5, axi_sel, peri0_cg_regs, 6, 0), + GATE(PERI_PWM6, peri_pwm6, axi_sel, peri0_cg_regs, 7, 0), + GATE(PERI_PWM7, peri_pwm7, axi_sel, peri0_cg_regs, 8, 0), + GATE(PERI_PWM, peri_pwm, axi_sel, peri0_cg_regs, 9, 0), + GATE(PERI_USB0, peri_usb0, usb20_sel, peri0_cg_regs, 10, 0), + GATE(PERI_IRDA, peri_irda, irda_sel, peri0_cg_regs, 11, 0), + GATE(PERI_APDMA, peri_apdma, axi_sel, peri0_cg_regs, 12, 0), + GATE(PERI_MSDC30_0, peri_msdc30_0, msdc30_0_sel, peri0_cg_regs, 13, 0), + GATE(PERI_MSDC30_1, peri_msdc30_1, msdc30_1_sel, peri0_cg_regs, 14, 0), + GATE(PERI_MSDC30_2, peri_msdc30_2, msdc30_2_sel, peri0_cg_regs, 15, 0), + GATE(PERI_MSDC30_3, peri_msdc30_3, msdc30_3_sel, peri0_cg_regs, 16, 0), + GATE(PERI_UART0, peri_uart0, uart_sel, peri0_cg_regs, 17, 0), + GATE(PERI_UART1, peri_uart1, uart_sel, peri0_cg_regs, 18, 0), + GATE(PERI_UART2, peri_uart2, uart_sel, peri0_cg_regs, 19, 0), + GATE(PERI_UART3, peri_uart3, uart_sel, peri0_cg_regs, 20, 0), + GATE(PERI_UART4, peri_uart4, uart_sel, peri0_cg_regs, 21, 0), + GATE(PERI_BTIF, peri_btif, axi_sel, peri0_cg_regs, 22, 0), + GATE(PERI_I2C0, peri_i2c0, axi_sel, peri0_cg_regs, 23, 0), + GATE(PERI_I2C1, peri_i2c1, axi_sel, peri0_cg_regs, 24, 0), + GATE(PERI_I2C2, peri_i2c2, axi_sel, peri0_cg_regs, 25, 0), + GATE(PERI_I2C3, peri_i2c3, axi_sel, peri0_cg_regs, 26, 0), + GATE(PERI_AUXADC, peri_auxadc, axi_sel, peri0_cg_regs, 27, 0), + GATE(PERI_SPI0, peri_spi0, spi_sel, peri0_cg_regs, 28, 0), + GATE(PERI_IRTX, peri_irtx, irtx_sel, peri0_cg_regs, 29, 0), +#endif +}; + +static void __init init_clk_perisys(void __iomem *perisys_base, + struct clk_onecell_data *clk_data) +{ + pr_debug("[CCF] init perisys gates:\n"); + init_clk_gates(perisys_base, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); +} +#endif +static struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +static struct mtk_gate mfg_clks[] __initdata = { + GATE(MFG_BG3D, mfg_bg3d, mfg_sel, mfg_cg_regs, 0, 0), +}; + +static void __init init_clk_mfgsys(void __iomem *mfgsys_base, + struct clk_onecell_data *clk_data) +{ + pr_debug("[CCF] init mfgsys gates:\n"); + init_clk_gates(mfgsys_base, mfg_clks, ARRAY_SIZE(mfg_clks), clk_data); +} + +static struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +static struct mtk_gate img_clks[] __initdata = { + GATE(IMG_IMAGE_LARB2_SMI, img_image_larb2_smi, mm_sel, img_cg_regs, 0, 0), + GATE(IMG_IMAGE_LARB2_SMI_M4U, img_image_larb2_smi_m4u, mm_sel, img_cg_regs, 0, 0), + + GATE(IMG_IMAGE_LARB2_SMI_SMI_COMMON, img_image_larb2_smi_smi_common, mm_sel, img_cg_regs, 0, 0), + GATE(IMG_IMAGE_LARB2_SMI_MET_SMI_COMMON, img_image_larb2_smi_met_smi_common, mm_sel, img_cg_regs, 0, 0), + GATE(IMG_IMAGE_LARB2_SMI_ISPSYS, img_image_larb2_smi_ispsys, mm_sel, img_cg_regs, 0, 0), + + GATE(IMG_IMAGE_CAM_SMI, img_image_cam_smi, mm_sel, img_cg_regs, 5, 0), + GATE(IMG_IMAGE_CAM_CAM, img_image_cam_cam, mm_sel, img_cg_regs, 6, 0), + GATE(IMG_IMAGE_SEN_TG, img_image_sen_tg, mm_sel, img_cg_regs, 7, 0), + GATE(IMG_IMAGE_SEN_CAM, img_image_sen_cam, camtg_sel, img_cg_regs, 8, 0), + GATE(IMG_IMAGE_CAM_SV, img_image_cam_sv, mm_sel, img_cg_regs, 9, 0), + GATE(IMG_IMAGE_SUFOD, img_image_sufod, mm_sel, img_cg_regs, 10, 0), + GATE(IMG_IMAGE_FD, img_image_fd, mm_sel, img_cg_regs, 11, 0), +}; + +static void __init init_clk_imgsys(void __iomem *imgsys_base, + struct clk_onecell_data *clk_data) +{ + pr_debug("[CCF] init imgsys gates:\n"); + init_clk_gates(imgsys_base, img_clks, ARRAY_SIZE(img_clks), clk_data); +} + +static struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x0104, + .clr_ofs = 0x0108, + .sta_ofs = 0x0100, +}; + +static struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x0114, + .clr_ofs = 0x0118, + .sta_ofs = 0x0110, +}; + +static struct mtk_gate mm_clks[] __initdata = { + /* MM0 */ + GATE(MM_DISP0_SMI_COMMON, mm_disp0_smi_common, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_M4U, mm_disp0_smi_common_m4u, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_MALI, mm_disp0_smi_common_mali, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_DISPSYS, mm_disp0_smi_common_dispsys, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_SMI_COMMON, mm_disp0_smi_common_smi_common, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_MET_SMI_COMMON, mm_disp0_smi_common_met_smi_common, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_ISPSYS, mm_disp0_smi_common_ispsys, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_FDVT, mm_disp0_smi_common_fdvt, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_VDEC_GCON, mm_disp0_smi_common_vdec_gcon, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_JPGENC, mm_disp0_smi_common_jpgenc, mm_sel, mm0_cg_regs, 0, 0), + GATE(MM_DISP0_SMI_COMMON_JPGDEC, mm_disp0_smi_common_jpgdec, mm_sel, mm0_cg_regs, 0, 0), + + GATE(MM_DISP0_SMI_LARB0, mm_disp0_smi_larb0, mm_sel, mm0_cg_regs, 1, 0), + GATE(MM_DISP0_SMI_LARB0_M4U, mm_disp0_smi_larb0_m4u, mm_sel, mm0_cg_regs, 1, 0), + GATE(MM_DISP0_SMI_LARB0_DISPSYS, mm_disp0_smi_larb0_dispsys, mm_sel, mm0_cg_regs, 1, 0), + GATE(MM_DISP0_SMI_LARB0_SMI_COMMON, mm_disp0_smi_larb0_smi_common, mm_sel, mm0_cg_regs, 1, 0), + GATE(MM_DISP0_SMI_LARB0_MET_SMI_COMMON, mm_disp0_smi_larb0_met_smi_common, mm_sel, mm0_cg_regs, 1, 0), + + GATE(MM_DISP0_CAM_MDP, mm_disp0_cam_mdp, mm_sel, mm0_cg_regs, 2, 0), + GATE(MM_DISP0_MDP_RDMA, mm_disp0_mdp_rdma, mm_sel, mm0_cg_regs, 3, 0), + GATE(MM_DISP0_MDP_RSZ0, mm_disp0_mdp_rsz0, mm_sel, mm0_cg_regs, 4, 0), + GATE(MM_DISP0_MDP_RSZ1, mm_disp0_mdp_rsz1, mm_sel, mm0_cg_regs, 5, 0), + GATE(MM_DISP0_MDP_TDSHP, mm_disp0_mdp_tdshp, mm_sel, mm0_cg_regs, 6, 0), + GATE(MM_DISP0_MDP_WDMA, mm_disp0_mdp_wdma, mm_sel, mm0_cg_regs, 7, 0), + GATE(MM_DISP0_MDP_WROT, mm_disp0_mdp_wrot, mm_sel, mm0_cg_regs, 8, 0), + GATE(MM_DISP0_FAKE_ENG, mm_disp0_fake_eng, mm_sel, mm0_cg_regs, 9, 0), + GATE(MM_DISP0_DISP_OVL0, mm_disp0_disp_ovl0, mm_sel, mm0_cg_regs, 10, 0), + GATE(MM_DISP0_DISP_OVL1, mm_disp0_disp_ovl1, mm_sel, mm0_cg_regs, 11, 0), + GATE(MM_DISP0_DISP_RDMA0, mm_disp0_disp_rdma0, mm_sel, mm0_cg_regs, 12, 0), + GATE(MM_DISP0_DISP_RDMA1, mm_disp0_disp_rdma1, mm_sel, mm0_cg_regs, 13, 0), + GATE(MM_DISP0_DISP_WDMA0, mm_disp0_disp_wdma0, mm_sel, mm0_cg_regs, 14, 0), + GATE(MM_DISP0_DISP_COLOR, mm_disp0_disp_color, mm_sel, mm0_cg_regs, 15, 0), + GATE(MM_DISP0_DISP_CCORR, mm_disp0_disp_ccorr, mm_sel, mm0_cg_regs, 16, 0), + GATE(MM_DISP0_DISP_AAL, mm_disp0_disp_aal, mm_sel, mm0_cg_regs, 17, 0), + GATE(MM_DISP0_DISP_GAMMA, mm_disp0_disp_gamma, mm_sel, mm0_cg_regs, 18, 0), + GATE(MM_DISP0_DISP_DITHER, mm_disp0_disp_dither, mm_sel, mm0_cg_regs, 19, 0), + GATE(MM_DISP0_MDP_COLOR, mm_disp0_mdp_color, mm_sel, mm0_cg_regs, 20, 0), + GATE(MM_DISP0_DISP_UFOE_MOUT, mm_disp0_ufoe_mout, mm_sel, mm0_cg_regs, 21, 0), + GATE(MM_DISP0_DISP_WDMA1, mm_disp0_disp_wdma1, mm_sel, mm0_cg_regs, 22, 0), + GATE(MM_DISP0_DISP_2L_OVL0, mm_disp0_disp_2lovl0, mm_sel, mm0_cg_regs, 23, 0), + GATE(MM_DISP0_DISP_2L_OVL1, mm_disp0_disp_2lovl1, mm_sel, mm0_cg_regs, 24, 0), + GATE(MM_DISP0_DISP_OVL0_MOUT, mm_disp0_disp_ovl0mout, mm_sel, mm0_cg_regs, 25, 0), + /* MM1 */ + GATE(MM_DISP1_DSI_ENGINE, mm_disp1_dsi_engine, mm_sel, mm1_cg_regs, 0, 0), + GATE(MM_DISP1_DSI_DIGITAL, mm_disp1_dsi_digital, mm_sel, mm1_cg_regs, 1, 0), + GATE(MM_DISP1_DPI_PIXEL, mm_disp1_dpi_pixel, dpi0_sel, mm1_cg_regs, 2, 0), + GATE(MM_DISP1_DPI_ENGINE, mm_disp1_dpi_engine, mm_sel, mm1_cg_regs, 3, 0), + +}; + +static void __init init_clk_mmsys(void __iomem *mmsys_base, + struct clk_onecell_data *clk_data) +{ + pr_debug("[CCF] init mmsys gates:\n"); + init_clk_gates(mmsys_base, mm_clks, ARRAY_SIZE(mm_clks), + clk_data); +} + +static struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0000, + .clr_ofs = 0x0004, + .sta_ofs = 0x0000, +}; + +static struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x000c, + .sta_ofs = 0x0008, +}; + +static struct mtk_gate vdec_clks[] __initdata = { + GATE(VDEC0_VDEC, vdec0_vdec, vdec_sel, vdec0_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VDEC1_LARB, vdec1_larb, vdec_sel, vdec1_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VDEC1_LARB_M4U, vdec1_larb_m4u, vdec_sel, vdec1_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VDEC1_LARB_SMI_COMMON, vdec1_larb_smi_common, vdec_sel, vdec1_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VDEC1_LARB_MET_SMI_COMMON, vdec1_larb_met_smi_common, vdec_sel, vdec1_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VDEC1_LARB_VDEC_GCON, vdec1_larb_vdec_gcon, vdec_sel, vdec1_cg_regs, 0, CLK_GATE_INVERSE), +}; + +static void __init init_clk_vdecsys(void __iomem *vdecsys_base, + struct clk_onecell_data *clk_data) +{ + pr_debug("[CCF] init vdecsys gates:\n"); + init_clk_gates(vdecsys_base, vdec_clks, ARRAY_SIZE(vdec_clks), + clk_data); +} + +static struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +static struct mtk_gate venc_clks[] __initdata = { + GATE(VENC_LARB, venc_larb, mm_sel, venc_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VENC_LARB_M4U, venc_larb_m4u, mm_sel, venc_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VENC_LARB_SMI_COMMON, venc_larb_smi_common, mm_sel, venc_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VENC_LARB_MET_SMI_COMMON, venc_larb_met_smi_common, mm_sel, venc_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VENC_LARB_JPGENC, venc_larb_jpgenc, mm_sel, venc_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VENC_LARB_JPGDEC, venc_larb_jpgdec, mm_sel, venc_cg_regs, 0, CLK_GATE_INVERSE), + GATE(VENC_VENC, venc_venc, mm_sel, venc_cg_regs, 4, CLK_GATE_INVERSE), + GATE(VENC_JPGENC, venc_jpgenc, mm_sel, venc_cg_regs, 8, CLK_GATE_INVERSE), + GATE(VENC_JPGDEC, venc_jpgdec, mm_sel, venc_cg_regs, 12, CLK_GATE_INVERSE), + /*note: clk inverse: 1: Clock enabled 0: Clock disabled*/ +}; + +static void __init init_clk_vencsys(void __iomem *vencsys_base, + struct clk_onecell_data *clk_data) +{ + pr_debug("[CCF] init vencsys gates:\n"); + init_clk_gates(vencsys_base, venc_clks, ARRAY_SIZE(venc_clks), + clk_data); +} + +static struct mtk_gate_regs aud_cg_regs = { + .set_ofs = 0x0000, + .clr_ofs = 0x0000, + .sta_ofs = 0x0000, +}; + +static struct mtk_gate_regs aud_div0_regs = { +/*Audio Clock Selection Register 0, 0 apll1_div0_pdn 1 apll2_div0_pdn*/ + .set_ofs = 0x05a0, + .clr_ofs = 0x05a0, + .sta_ofs = 0x05a0, +}; + +static struct mtk_gate audio_clks[] __initdata = { + + GATE(AUDIO_AFE, audio_afe, audio_sel, aud_cg_regs, 2, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_I2S, audio_i2s, i2s_sel, aud_cg_regs, 6, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_22M, audio_22m, aud_1_sel, aud_cg_regs, 8, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_24M, audio_24m, aud_2_sel, aud_cg_regs, 9, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_APLL2_TUNER, audio_apll2_tuner, aud_2_sel, aud_cg_regs, 18, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_APLL_TUNER, audio_apll_tuner, aud_1_sel, aud_cg_regs, 19, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_ADC, audio_adc, audio_sel, aud_cg_regs, 24, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_DAC, audio_dac, audio_sel, aud_cg_regs, 25, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_DAC_PREDIS, audio_dac_predis, audio_sel, aud_cg_regs, 26, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_TML, audio_tml, audio_sel, aud_cg_regs, 27, CLK_GATE_NO_SETCLR_REG), + + GATE(AUDIO_APLL1_DIV0, audio_apll1div0, clk_null, aud_div0_regs, 0, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_APLL2_DIV0, audio_apll2div0, clk_null, aud_div0_regs, 1, CLK_GATE_NO_SETCLR_REG), + + #if 0 + GATE(AUDIO_AFE, audio_afe, aud_intbus_sel, aud_cg_regs, 2, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_I2S, audio_i2s, aud_intbus_sel, aud_cg_regs, 6, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_22M, audio_22m, aud_intbus_sel, aud_cg_regs, 8, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_24M, audio_24m, aud_intbus_sel, aud_cg_regs, 9, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_APLL2_TUNER, audio_apll2_tuner, aud_intbus_sel, aud_cg_regs, 18, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_APLL_TUNER, audio_apll_tuner, aud_intbus_sel, aud_cg_regs, 19, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_ADC, audio_adc, aud_intbus_sel, aud_cg_regs, 24, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_DAC, audio_dac, aud_intbus_sel, aud_cg_regs, 25, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_DAC_PREDIS, audio_dac_predis, aud_intbus_sel, aud_cg_regs, 26, CLK_GATE_NO_SETCLR_REG), + GATE(AUDIO_TML, audio_tml, aud_intbus_sel, aud_cg_regs, 27, CLK_GATE_NO_SETCLR_REG), + #endif +}; + +static void __init init_clk_audiosys(void __iomem *audiosys_base, + struct clk_onecell_data *clk_data) +{ + pr_debug("[CCF] init audiosys gates:\n"); + init_clk_gates(audiosys_base, audio_clks, ARRAY_SIZE(audio_clks), + clk_data); +} + +/* + * device tree support + */ + +static struct clk_onecell_data *alloc_clk_data(unsigned int clk_num) +{ + int i; + struct clk_onecell_data *clk_data; + + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return NULL; + + clk_data->clks = kcalloc(clk_num, sizeof(struct clk *), GFP_KERNEL); + if (!clk_data->clks) { + kfree(clk_data); + return NULL; + } + + clk_data->clk_num = clk_num; + + for (i = 0; i < clk_num; ++i) + clk_data->clks[i] = ERR_PTR(-ENOENT); + + return clk_data; +} + +static void __iomem *get_reg(struct device_node *np, int index) +{ +#if DUMMY_REG_TEST + return kzalloc(PAGE_SIZE, GFP_KERNEL); +#else + return of_iomap(np, index); +#endif +} + +static void __init mt_topckgen_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap topckgen failed\n"); + return; + } + + clk_data = alloc_clk_data(TOP_NR_CLK); + + init_clk_root_alias(clk_data); + init_clk_top_div(clk_data); +#ifndef _MUX_UPDS_ + init_clk_topckgen(base, clk_data); +#else + #ifdef _MUX_CLR_SET_UPDS_ + mtk_clk_register_mux_clr_set_upds(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt6755_clk_lock, clk_data); + #else + mtk_clk_register_mux_upds(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt6755_clk_lock, clk_data); + #endif +#endif + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +} +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt6755-topckgen", mt_topckgen_init); + +#define PLL_PWR_ON (0x1 << 0) +#define PLL_ISO_EN (0x1 << 1) +static void __init mt_apmixedsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + void __iomem *spm_base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + spm_base = get_reg(node, 1); + if ((!base) || (!spm_base)) { + pr_err("ioremap apmixedsys/spm failed\n"); + return; + } + + clk_data = alloc_clk_data(APMIXED_NR_CLK); + + init_clk_apmixedsys(base, spm_base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); + scp_base = spm_base; +#if CG_BOOTUP_PDN + apmixed_base = base; + /*msdcpll*/ + clk_clrl(MSDCPLL_CON0, 0x1); + clk_setl(MSDCPLL_PWR_CON0, PLL_ISO_EN); + clk_clrl(MSDCPLL_PWR_CON0, PLL_PWR_ON); + +/*tvdpll*/ + clk_clrl(TVDPLL_CON0, 0x1); + clk_setl(TVDPLL_PWR_CON0, PLL_ISO_EN); + clk_clrl(TVDPLL_PWR_CON0, PLL_PWR_ON); + +/*apll1*/ + clk_clrl(APLL1_CON0, 0x1); + clk_setl(APLL1_PWR_CON0, PLL_ISO_EN); + clk_clrl(APLL1_PWR_CON0, PLL_PWR_ON); +/*apll2*/ + clk_clrl(APLL2_CON0, 0x1); + clk_setl(APLL2_PWR_CON0, PLL_ISO_EN); + clk_clrl(APLL2_PWR_CON0, PLL_PWR_ON); +/*oscpll default enable*/ + /* OSC EN = 1 */ + clk_setl(ULPOSC_CON, ULPOSC_EN); + udelay(11); + /* OSC RST */ + clk_setl(ULPOSC_CON, ULPOSC_RST); + udelay(40); + clk_clrl(ULPOSC_CON, ULPOSC_RST); + udelay(130); + /* OSC CG_EN = 1 */ + clk_setl(ULPOSC_CON, ULPOSC_CG_EN); +#endif +} +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt6755-apmixedsys", + mt_apmixedsys_init); + +static void __init mt_infrasys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap infrasys failed\n"); + return; + } + + clk_data = alloc_clk_data(INFRA_NR_CLK); + + init_clk_infrasys(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +#if CG_BOOTUP_PDN + /*INFRA CG*/ + infracfg_base = base; + clk_writel(INFRA_PDN_SET0, INFRA0_CG); + clk_writel(INFRA_PDN_SET1, INFRA1_CG); + clk_writel(INFRA_PDN_SET2, INFRA2_CG); +#endif +} +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt6755-infrasys", mt_infrasys_init); +#if 0 +static void __init mt_perisys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap perisys failed\n"); + return; + } + + clk_data = alloc_clk_data(PERI_NR_CLK); + + init_clk_perisys(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +} +CLK_OF_DECLARE(mtk_perisys, "mediatek,mt6755-perisys", mt_perisys_init); +#endif +static void __init mt_mfgsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap mfgsys failed\n"); + return; + } + + clk_data = alloc_clk_data(MFG_NR_CLK); + + init_clk_mfgsys(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +#if 0/*CG_BOOTUP_PDN*/ + /*MFG*/ + mfgcfg_base = base; + clk_writel(MFG_CG_SET, MFG_CG); +#endif +} +CLK_OF_DECLARE(mtk_mfgsys, "mediatek,mt6755-mfgsys", mt_mfgsys_init); + +static void __init mt_imgsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap imgsys failed\n"); + return; + } + + clk_data = alloc_clk_data(IMG_NR_CLK); + + init_clk_imgsys(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +#if CG_BOOTUP_PDN + /*ISP*/ + img_base = base; + clk_writel(IMG_CG_SET, IMG_CG); +#endif +} +CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt6755-imgsys", mt_imgsys_init); + +static void __init mt_mmsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap mmsys failed\n"); + return; + } + + clk_data = alloc_clk_data(MM_NR_CLK); + + init_clk_mmsys(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +#if CG_BOOTUP_PDN + /*DISP*/ + mmsys_config_base = base; + clk_writel(DISP_CG_SET0, DISP0_CG); /*DCM enable*/ +#endif +} +CLK_OF_DECLARE(mtk_mmsys, "mediatek,mt6755-mmsys", mt_mmsys_init); + +static void __init mt_vdecsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap vdecsys failed\n"); + return; + } + + clk_data = alloc_clk_data(VDEC_NR_CLK); + + init_clk_vdecsys(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +#if CG_BOOTUP_PDN + /*VDE*/ + vdec_gcon_base = base; + clk_writel(VDEC_CKEN_CLR, VDEC_CG); + clk_writel(LARB_CKEN_CLR, LARB_CG); +#endif +} +CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt6755-vdecsys", mt_vdecsys_init); + +static void __init mt_vencsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap vencsys failed\n"); + return; + } + + clk_data = alloc_clk_data(VENC_NR_CLK); + + init_clk_vencsys(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +#if CG_BOOTUP_PDN + /*VENC*/ + venc_gcon_base = base; + clk_clrl(VENC_CG_CON, VENC_CG); +#endif +} +CLK_OF_DECLARE(mtk_vencsys, "mediatek,mt6755-vencsys", mt_vencsys_init); + +static void __init mt_audiosys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + pr_debug("[CCF] %s: %s\n", __func__, node->name); + + base = get_reg(node, 0); + if (!base) { + pr_err("ioremap audiosys failed\n"); + return; + } + + clk_data = alloc_clk_data(AUDIO_NR_CLK); + + init_clk_audiosys(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("could not register clock provide\n"); +#if CG_BOOTUP_PDN + /*AUDIO*/ + audio_base = base; + clk_writel(AUDIO_TOP_CON0, AUD_CG); +#endif +} +CLK_OF_DECLARE(mtk_audiosys, "mediatek,mt6755-audiosys", mt_audiosys_init); + +void pll_if_on(void) +{ + u32 segment = get_devinfo_with_index(21) & 0xFF; + + if ((segment == 0x43) || (segment == 0x4B)) { + pr_err("segment = 6738 chip\n"); + switch_armpll_l_hwmode(1); + switch_armpll_ll_hwmode(1); + } else + pr_err("segment != 6738 chip\n"); + + if (clk_readl(UNIVPLL_CON0) & 0x1) + pr_err("suspend warning: UNIVPLL is on!!!\n"); + + if (clk_readl(MMPLL_CON0) & 0x1) + pr_err("suspend warning: MMPLL is on!!!\n"); + + if (clk_readl(MSDCPLL_CON0) & 0x1) + pr_err("suspend warning: MSDCPLL is on!!!\n"); + + if (clk_readl(VENCPLL_CON0) & 0x1) + pr_err("suspend warning: VENCPLL is on!!!\n"); + + if (clk_readl(TVDPLL_CON0) & 0x1) + pr_err("suspend warning: TVDPLL is on!!!\n"); + + if (clk_readl(APLL1_CON0) & 0x1) + pr_err("suspend warning: APLL1 is on!!!\n"); + + if (clk_readl(APLL2_CON0) & 0x1) + pr_err("suspend warning: APLL2 is on!!!\n"); +} diff --git a/drivers/clocksource/arm_arch_timer_mt6755.c b/drivers/clocksource/arm_arch_timer_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..d979120668902a231e4959ebbc19b0ac735f49b5 --- /dev/null +++ b/drivers/clocksource/arm_arch_timer_mt6755.c @@ -0,0 +1,839 @@ +/* + * linux/drivers/clocksource/arm_arch_timer.c + * + * Copyright (C) 2011 ARM Ltd. + * 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 version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define CNTTIDR 0x08 +#define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4)) + +#define CNTVCT_LO 0x08 +#define CNTVCT_HI 0x0c +#define CNTFRQ 0x10 +#define CNTP_TVAL 0x28 +#define CNTP_CTL 0x2c +#define CNTV_TVAL 0x38 +#define CNTV_CTL 0x3c + +#define ARCH_CP15_TIMER BIT(0) +#define ARCH_MEM_TIMER BIT(1) +static unsigned arch_timers_present __initdata; + +static void __iomem *arch_counter_base; + +struct arch_timer { + void __iomem *base; + struct clock_event_device evt; +}; + +#define to_arch_timer(e) container_of(e, struct arch_timer, evt) + +static u32 arch_timer_rate; + +enum ppi_nr { + PHYS_SECURE_PPI, + PHYS_NONSECURE_PPI, + VIRT_PPI, + HYP_PPI, + MAX_TIMER_PPI +}; + +static int arch_timer_ppi[MAX_TIMER_PPI]; + +static struct clock_event_device __percpu *arch_timer_evt; + +static bool arch_timer_use_virtual = true; +static bool arch_timer_c3stop; +static bool arch_timer_mem_use_virtual; + +/* + * Architected system timer support. + */ + +static __always_inline +void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, + struct clock_event_device *clk) +{ + if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + + switch (reg) { + case ARCH_TIMER_REG_CTRL: + writel_relaxed(val, timer->base + CNTP_CTL); + break; + case ARCH_TIMER_REG_TVAL: + writel_relaxed(val, timer->base + CNTP_TVAL); + break; + } + } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + + switch (reg) { + case ARCH_TIMER_REG_CTRL: + writel_relaxed(val, timer->base + CNTV_CTL); + break; + case ARCH_TIMER_REG_TVAL: + writel_relaxed(val, timer->base + CNTV_TVAL); + break; + } + } else { + arch_timer_reg_write_cp15(access, reg, val); + } +} + +static __always_inline +u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, + struct clock_event_device *clk) +{ + u32 val; + + if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + + switch (reg) { + case ARCH_TIMER_REG_CTRL: + val = readl_relaxed(timer->base + CNTP_CTL); + break; + case ARCH_TIMER_REG_TVAL: + val = readl_relaxed(timer->base + CNTP_TVAL); + break; + } + } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + + switch (reg) { + case ARCH_TIMER_REG_CTRL: + val = readl_relaxed(timer->base + CNTV_CTL); + break; + case ARCH_TIMER_REG_TVAL: + val = readl_relaxed(timer->base + CNTV_TVAL); + break; + } + } else { + val = arch_timer_reg_read_cp15(access, reg); + } + + return val; +} + +static __always_inline irqreturn_t timer_handler(const int access, + struct clock_event_device *evt) +{ + unsigned long ctrl; + + ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, evt); + if (ctrl & ARCH_TIMER_CTRL_IT_STAT) { + ctrl |= ARCH_TIMER_CTRL_IT_MASK; + arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, evt); + evt->event_handler(evt); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static irqreturn_t arch_timer_handler_virt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + return timer_handler(ARCH_TIMER_VIRT_ACCESS, evt); +} + +static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt); +} + +static irqreturn_t arch_timer_handler_phys_mem(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + return timer_handler(ARCH_TIMER_MEM_PHYS_ACCESS, evt); +} + +static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt); +} + +static __always_inline void timer_set_mode(const int access, int mode, + struct clock_event_device *clk) +{ + unsigned long ctrl; + + switch (mode) { + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); + ctrl &= ~ARCH_TIMER_CTRL_ENABLE; + arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); + break; + default: + break; + } +} + +static void arch_timer_set_mode_virt(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode, clk); +} + +static void arch_timer_set_mode_phys(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode, clk); +} + +static void arch_timer_set_mode_virt_mem(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + timer_set_mode(ARCH_TIMER_MEM_VIRT_ACCESS, mode, clk); +} + +static void arch_timer_set_mode_phys_mem(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + timer_set_mode(ARCH_TIMER_MEM_PHYS_ACCESS, mode, clk); +} + +static __always_inline void set_next_event(const int access, unsigned long evt, + struct clock_event_device *clk) +{ + unsigned long ctrl; + + ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); + ctrl |= ARCH_TIMER_CTRL_ENABLE; + ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; + arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk); + arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); +} + +static int arch_timer_set_next_event_virt(unsigned long evt, + struct clock_event_device *clk) +{ + set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); + return 0; +} + +static int arch_timer_set_next_event_phys(unsigned long evt, + struct clock_event_device *clk) +{ + set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); + return 0; +} + +static int arch_timer_set_next_event_virt_mem(unsigned long evt, + struct clock_event_device *clk) +{ + set_next_event(ARCH_TIMER_MEM_VIRT_ACCESS, evt, clk); + return 0; +} + +static int arch_timer_set_next_event_phys_mem(unsigned long evt, + struct clock_event_device *clk) +{ + set_next_event(ARCH_TIMER_MEM_PHYS_ACCESS, evt, clk); + return 0; +} + +static void __arch_timer_setup(unsigned type, + struct clock_event_device *clk) +{ + clk->features = CLOCK_EVT_FEAT_ONESHOT; + + if (type == ARCH_CP15_TIMER) { + if (arch_timer_c3stop) + clk->features |= CLOCK_EVT_FEAT_C3STOP; + clk->name = "arch_sys_timer"; + clk->rating = 450; + clk->cpumask = cpumask_of(smp_processor_id()); + if (arch_timer_use_virtual) { + clk->irq = arch_timer_ppi[VIRT_PPI]; + clk->set_mode = arch_timer_set_mode_virt; + clk->set_next_event = arch_timer_set_next_event_virt; + } else { + clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; + clk->set_mode = arch_timer_set_mode_phys; + clk->set_next_event = arch_timer_set_next_event_phys; + } + } else { + clk->features |= CLOCK_EVT_FEAT_DYNIRQ; + clk->name = "arch_mem_timer"; + clk->rating = 400; + clk->cpumask = cpu_all_mask; + if (arch_timer_mem_use_virtual) { + clk->set_mode = arch_timer_set_mode_virt_mem; + clk->set_next_event = + arch_timer_set_next_event_virt_mem; + } else { + clk->set_mode = arch_timer_set_mode_phys_mem; + clk->set_next_event = + arch_timer_set_next_event_phys_mem; + } + } + + clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, clk); + + clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); +} + +static void arch_timer_evtstrm_enable(int divider) +{ + u32 cntkctl = arch_timer_get_cntkctl(); + + cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK; + /* Set the divider and enable virtual event stream */ + cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT) + | ARCH_TIMER_VIRT_EVT_EN; + arch_timer_set_cntkctl(cntkctl); + elf_hwcap |= HWCAP_EVTSTRM; +#ifdef CONFIG_COMPAT + compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM; +#endif +} + +static void arch_timer_configure_evtstream(void) +{ + int evt_stream_div, pos; + + /* Find the closest power of two to the divisor */ + evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ; + pos = fls(evt_stream_div); + if (pos > 1 && !(evt_stream_div & (1 << (pos - 2)))) + pos--; + /* enable event stream */ + arch_timer_evtstrm_enable(min(pos, 15)); +} + +static void arch_counter_set_user_access(void) +{ + u32 cntkctl = arch_timer_get_cntkctl(); + + /* Disable user access to the timers and the physical counter */ + /* Also disable virtual event stream */ + cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN + | ARCH_TIMER_USR_VT_ACCESS_EN + | ARCH_TIMER_VIRT_EVT_EN + | ARCH_TIMER_USR_PCT_ACCESS_EN); + + /* Enable user access to the virtual counter */ + cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; + + arch_timer_set_cntkctl(cntkctl); +} + +static int arch_timer_setup(struct clock_event_device *clk) +{ + __arch_timer_setup(ARCH_CP15_TIMER, clk); + + if (arch_timer_use_virtual) + enable_percpu_irq(arch_timer_ppi[VIRT_PPI], 0); + else { + enable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], 0); + if (arch_timer_ppi[PHYS_NONSECURE_PPI]) + enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0); + } + + arch_counter_set_user_access(); + if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM)) + arch_timer_configure_evtstream(); + + return 0; +} + +static void +arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) +{ + /* Who has more than one independent system counter? */ + if (arch_timer_rate) + return; + + /* Try to determine the frequency from the device tree or CNTFRQ */ + if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { + if (cntbase) + arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); + else + arch_timer_rate = arch_timer_get_cntfrq(); + } + + /* Check the timer frequency. */ + if (arch_timer_rate == 0) + pr_warn("Architected timer frequency not available\n"); +} + +static void arch_timer_banner(unsigned type) +{ + pr_info("Architected %s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", + type & ARCH_CP15_TIMER ? "cp15" : "", + type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? " and " : "", + type & ARCH_MEM_TIMER ? "mmio" : "", + (unsigned long)arch_timer_rate / 1000000, + (unsigned long)(arch_timer_rate / 10000) % 100, + type & ARCH_CP15_TIMER ? + arch_timer_use_virtual ? "virt" : "phys" : + "", + type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", + type & ARCH_MEM_TIMER ? + arch_timer_mem_use_virtual ? "virt" : "phys" : + ""); +} + +u32 arch_timer_get_rate(void) +{ + return arch_timer_rate; +} + +static u64 arch_counter_get_cntvct_mem(void) +{ + u32 vct_lo, vct_hi, tmp_hi; + + do { + vct_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); + vct_lo = readl_relaxed(arch_counter_base + CNTVCT_LO); + tmp_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); + } while (vct_hi != tmp_hi); + + return ((u64) vct_hi << 32) | vct_lo; +} + +/* + * Default to cp15 based access because arm64 uses this function for + * sched_clock() before DT is probed and the cp15 method is guaranteed + * to exist on arm64. arm doesn't use this before DT is probed so even + * if we don't have the cp15 accessors we won't have a problem. + */ +u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntpct; /*need used pct because VCT's OFFSET counter in bootup*/ + +static cycle_t arch_counter_read(struct clocksource *cs) +{ + if (arch_timer_use_virtual) + return arch_counter_get_cntvct(); + else + return arch_counter_get_cntpct(); +} + +static cycle_t arch_counter_read_cc(const struct cyclecounter *cc) +{ + if (arch_timer_use_virtual) + return arch_counter_get_cntvct(); + else + return arch_counter_get_cntpct(); +} + +static struct clocksource clocksource_counter = { + .name = "arch_sys_counter", + .rating = 400, + .read = arch_counter_read, + .mask = CLOCKSOURCE_MASK(56), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static struct cyclecounter cyclecounter = { + .read = arch_counter_read_cc, + .mask = CLOCKSOURCE_MASK(56), +}; + +static struct timecounter timecounter; + +struct timecounter *arch_timer_get_timecounter(void) +{ + return &timecounter; +} + +static void __init arch_counter_register(unsigned type) +{ + u64 start_count; + + /* Register the CP15 based counter if we have one */ + if (type & ARCH_CP15_TIMER) { + arch_timer_read_counter = arch_counter_get_cntpct; /*same as line 427*/ + } else { + arch_timer_read_counter = arch_counter_get_cntvct_mem; + + /* If the clocksource name is "arch_sys_counter" the + * VDSO will attempt to read the CP15-based counter. + * Ensure this does not happen when CP15-based + * counter is not available. + */ + /*clocksource_counter.name = "arch_mem_counter";*/ /*used APXGPT as clocksource, no need this*/ + } +#if 1 + start_count = arch_timer_read_counter(); + clocksource_register_hz(&clocksource_counter, arch_timer_rate); + cyclecounter.mult = clocksource_counter.mult; + cyclecounter.shift = clocksource_counter.shift; + timecounter_init(&timecounter, &cyclecounter, start_count); +#endif + /* 56 bits minimum, so we assume worst case rollover */ + sched_clock_register((void *)arch_timer_read_counter, 53, (unsigned long)arch_timer_rate); +} + +static void arch_timer_stop(struct clock_event_device *clk) +{ + pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", + clk->irq, smp_processor_id()); + + if (arch_timer_use_virtual) + disable_percpu_irq(arch_timer_ppi[VIRT_PPI]); + else { + disable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI]); + if (arch_timer_ppi[PHYS_NONSECURE_PPI]) + disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); + } + + clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk); +} + +static int arch_timer_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + /* + * Grab cpu pointer in each case to avoid spurious + * preemptible warnings + */ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + arch_timer_setup(this_cpu_ptr(arch_timer_evt)); + break; + case CPU_DYING: + arch_timer_stop(this_cpu_ptr(arch_timer_evt)); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block arch_timer_cpu_nb = { + .notifier_call = arch_timer_cpu_notify, +}; + +#ifdef CONFIG_CPU_PM +static unsigned int saved_cntkctl; +static int arch_timer_cpu_pm_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + if (action == CPU_PM_ENTER) + saved_cntkctl = arch_timer_get_cntkctl(); + else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) + arch_timer_set_cntkctl(saved_cntkctl); + return NOTIFY_OK; +} + +static struct notifier_block arch_timer_cpu_pm_notifier = { + .notifier_call = arch_timer_cpu_pm_notify, +}; + +static int __init arch_timer_cpu_pm_init(void) +{ + return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier); +} +#else +static int __init arch_timer_cpu_pm_init(void) +{ + return 0; +} +#endif + +static int __init arch_timer_register(void) +{ + int err; + int ppi; + + pr_alert("%s:arch_timer_rate(0x%x),arch_timer_use_virtual=%d\n", + __func__, arch_timer_rate, arch_timer_use_virtual); + + arch_timer_evt = alloc_percpu(struct clock_event_device); + if (!arch_timer_evt) { + err = -ENOMEM; + goto out; + } + + if (arch_timer_use_virtual) { + ppi = arch_timer_ppi[VIRT_PPI]; + err = request_percpu_irq(ppi, arch_timer_handler_virt, + "arch_timer", arch_timer_evt); + } else { + ppi = arch_timer_ppi[PHYS_SECURE_PPI]; + err = request_percpu_irq(ppi, arch_timer_handler_phys, + "arch_timer", arch_timer_evt); + pr_alert("%s:request_percpu_irq PHYS_SECURE_PPI err=%d\n", __func__, err); + if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) { + ppi = arch_timer_ppi[PHYS_NONSECURE_PPI]; + err = request_percpu_irq(ppi, arch_timer_handler_phys, + "arch_timer", arch_timer_evt); + pr_alert("%s:request_percpu_irq PHYS_NONSECURE_PPI err=%d\n", __func__, err); + if (err) + free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], + arch_timer_evt); + } + } + + if (err) { + pr_err("arch_timer: can't register interrupt %d (%d)\n", + ppi, err); + goto out_free; + } + + err = register_cpu_notifier(&arch_timer_cpu_nb); + if (err) + goto out_free_irq; + + err = arch_timer_cpu_pm_init(); + if (err) + goto out_unreg_notify; + + /* Immediately configure the timer on the boot CPU */ + arch_timer_setup(this_cpu_ptr(arch_timer_evt)); + + return 0; + +out_unreg_notify: + unregister_cpu_notifier(&arch_timer_cpu_nb); +out_free_irq: + if (arch_timer_use_virtual) + free_percpu_irq(arch_timer_ppi[VIRT_PPI], arch_timer_evt); + else { + free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], + arch_timer_evt); + if (arch_timer_ppi[PHYS_NONSECURE_PPI]) + free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], + arch_timer_evt); + } + +out_free: + free_percpu(arch_timer_evt); +out: + return err; +} + +static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq) +{ + int ret; + irq_handler_t func; + struct arch_timer *t; + + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (!t) + return -ENOMEM; + + t->base = base; + t->evt.irq = irq; + __arch_timer_setup(ARCH_MEM_TIMER, &t->evt); + + if (arch_timer_mem_use_virtual) + func = arch_timer_handler_virt_mem; + else + func = arch_timer_handler_phys_mem; + + ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt); + if (ret) { + pr_err("arch_timer: Failed to request mem timer irq\n"); + kfree(t); + } + + return ret; +} + +static const struct of_device_id arch_timer_of_match[] __initconst = { + { .compatible = "arm,armv7-timer", }, + { .compatible = "arm,armv8-timer", }, + {}, +}; + +static const struct of_device_id arch_timer_mem_of_match[] __initconst = { + { .compatible = "arm,armv7-timer-mem", }, + {}, +}; + +static bool __init +arch_timer_probed(int type, const struct of_device_id *matches) +{ + struct device_node *dn; + bool probed = true; + + dn = of_find_matching_node(NULL, matches); + if (dn && of_device_is_available(dn) && !(arch_timers_present & type)) + probed = false; + of_node_put(dn); + + return probed; +} + +static void __init arch_timer_common_init(void) +{ + unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER; + + /* Wait until both nodes are probed if we have two timers */ + if ((arch_timers_present & mask) != mask) { + if (!arch_timer_probed(ARCH_MEM_TIMER, arch_timer_mem_of_match)) + return; + if (!arch_timer_probed(ARCH_CP15_TIMER, arch_timer_of_match)) + return; + } + + arch_timer_banner(arch_timers_present); + arch_counter_register(arch_timers_present); + arch_timer_arch_init(); +} + +int localtimer_set_next_event(unsigned long evt) +{ + if (arch_timer_use_virtual) + arch_timer_set_next_event_virt(evt, NULL); + else + arch_timer_set_next_event_phys(evt, NULL); + return 0; +} + +unsigned long localtimer_get_counter(void) +{ + unsigned long evt; + +if (arch_timer_use_virtual) + evt = arch_timer_reg_read(ARCH_TIMER_VIRT_ACCESS, ARCH_TIMER_REG_TVAL, NULL); + else + evt = arch_timer_reg_read(ARCH_TIMER_PHYS_ACCESS, ARCH_TIMER_REG_TVAL, NULL); + return evt; +} + +static void __init arch_timer_init(struct device_node *np) +{ + int i; + + if (arch_timers_present & ARCH_CP15_TIMER) { + pr_warn("arch_timer: multiple nodes in dt, skipping\n"); + return; + } + + arch_timers_present |= ARCH_CP15_TIMER; + for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) + arch_timer_ppi[i] = irq_of_parse_and_map(np, i); + arch_timer_detect_rate(NULL, np); + + /* + * If HYP mode is available, we know that the physical timer + * has been configured to be accessible from PL1. Use it, so + * that a guest can use the virtual timer instead. + * + * If no interrupt provided for virtual timer, we'll have to + * stick to the physical timer. It'd better be accessible... + */ + pr_alert("%s:arch_timer_rate(0x%x),PHYS_SECURE_PPI=%d,PHYS_NONSECURE_PPI=%d,VIRT_PPI=%d,HYP_PPI=%d\n", + __func__, arch_timer_rate, arch_timer_ppi[PHYS_SECURE_PPI], arch_timer_ppi[PHYS_NONSECURE_PPI], + arch_timer_ppi[VIRT_PPI], arch_timer_ppi[HYP_PPI]); +#if 1 /*MTK always use pct*/ +arch_timer_use_virtual = false; +#endif + if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) { + arch_timer_use_virtual = false; + + if (!arch_timer_ppi[PHYS_SECURE_PPI] || + !arch_timer_ppi[PHYS_NONSECURE_PPI]) { + pr_warn("arch_timer: No interrupt available, giving up\n"); + return; + } + } + + arch_timer_c3stop = !of_property_read_bool(np, "always-on"); + + pr_alert("%s:arch_timer_c3stop=%d\n", __func__, arch_timer_c3stop); + + arch_timer_register(); + arch_timer_common_init(); +} +CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init); +CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init); + +static void __init arch_timer_mem_init(struct device_node *np) +{ + struct device_node *frame, *best_frame = NULL; + void __iomem *cntctlbase, *base; + unsigned int irq; + u32 cnttidr; + + arch_timers_present |= ARCH_MEM_TIMER; + cntctlbase = of_iomap(np, 0); + if (!cntctlbase) { + pr_err("arch_timer: Can't find CNTCTLBase\n"); + return; + } + + cnttidr = readl_relaxed(cntctlbase + CNTTIDR); + iounmap(cntctlbase); + + /* + * Try to find a virtual capable frame. Otherwise fall back to a + * physical capable frame. + */ + for_each_available_child_of_node(np, frame) { + int n; + + if (of_property_read_u32(frame, "frame-number", &n)) { + pr_err("arch_timer: Missing frame-number\n"); + of_node_put(best_frame); + of_node_put(frame); + return; + } + + if (cnttidr & CNTTIDR_VIRT(n)) { + of_node_put(best_frame); + best_frame = frame; + arch_timer_mem_use_virtual = true; + break; + } + of_node_put(best_frame); + best_frame = of_node_get(frame); + } + + base = arch_counter_base = of_iomap(best_frame, 0); + if (!base) { + pr_err("arch_timer: Can't map frame's registers\n"); + of_node_put(best_frame); + return; + } + + if (arch_timer_mem_use_virtual) + irq = irq_of_parse_and_map(best_frame, 1); + else + irq = irq_of_parse_and_map(best_frame, 0); + of_node_put(best_frame); + if (!irq) { + pr_err("arch_timer: Frame missing %s irq", + arch_timer_mem_use_virtual ? "virt" : "phys"); + return; + } + + arch_timer_detect_rate(base, np); + arch_timer_mem_register(base, irq); + arch_timer_common_init(); +} +CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", + arch_timer_mem_init); diff --git a/drivers/clocksource/mtk_cpuxgpt_mt6755.c b/drivers/clocksource/mtk_cpuxgpt_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..e4446260d11bbcc50ca35cbd7a9c527da662e313 --- /dev/null +++ b/drivers/clocksource/mtk_cpuxgpt_mt6755.c @@ -0,0 +1,516 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +/* #include */ + +#include +#include + +#include +#include +#include + +#include +/*if ATF enable, MCUSYS register will be write protect*/ +#include + +#define CPUXGPT_BASE cpuxgpt_regs +#define INDEX_BASE (CPUXGPT_BASE+0x0674) +#define CTL_BASE (CPUXGPT_BASE+0x0670) + +#define CPUXGPT_BASE_PHY mt_cpuxgpt_base_phys +#define INDEX_BASE_PHY (CPUXGPT_BASE_PHY+0x0674) +#define CTL_BASE_PHY (CPUXGPT_BASE_PHY+0x0670) +static struct resource cpuxgpt_r; +static phys_addr_t mt_cpuxgpt_base_phys; + +static DEFINE_SPINLOCK(cpuxgpt_reg_lock); +static irqreturn_t(*user_handlers[CPUXGPTNUMBERS])(int irq, void *dev_id) = {0}; +static unsigned int g_ctl; + +static void __iomem *cpuxgpt_regs; +static int cpuxgpt_irq[CPUXGPTNUMBERS]; + +static irqreturn_t __cpuxgpt0_irq_handler(int irq, void *dev_id); +static irqreturn_t __cpuxgpt1_irq_handler(int irq, void *dev_id); +static irqreturn_t __cpuxgpt2_irq_handler(int irq, void *dev_id); +static irqreturn_t __cpuxgpt3_irq_handler(int irq, void *dev_id); +static irqreturn_t __cpuxgpt4_irq_handler(int irq, void *dev_id); +static irqreturn_t __cpuxgpt5_irq_handler(int irq, void *dev_id); +static irqreturn_t __cpuxgpt6_irq_handler(int irq, void *dev_id); +static irqreturn_t __cpuxgpt7_irq_handler(int irq, void *dev_id); + +static const struct of_device_id cpuxgpt_addr_ids[] __initconst = { + {.compatible = "mediatek,cpuxgpt"}, + {}, +}; + +static irqreturn_t(*cpuxgpt_irq_handler[])(int irq, void *dev_id) = { +__cpuxgpt0_irq_handler, +__cpuxgpt1_irq_handler, +__cpuxgpt2_irq_handler, +__cpuxgpt3_irq_handler, +__cpuxgpt4_irq_handler, +__cpuxgpt5_irq_handler, +__cpuxgpt6_irq_handler, +__cpuxgpt7_irq_handler, +};/* support 8 timer call back */ + +#define gpt_update_lock(flags) spin_lock_irqsave(&cpuxgpt_reg_lock, flags) + +#define gpt_update_unlock(flags) spin_unlock_irqrestore(&cpuxgpt_reg_lock, flags) + +static unsigned int __read_cpuxgpt(unsigned int reg_index) +{ + unsigned int value = 0; + #if defined(CONFIG_ARM_PSCI) || defined(CONFIG_MTK_PSCI) + /* DRV_WriteReg32(INDEX_BASE,reg_index); */ + mcusys_smc_write_phy(INDEX_BASE_PHY, reg_index); + #else +mcusys_smc_write(INDEX_BASE, reg_index); + #endif + value = __raw_readl(CTL_BASE); + return value; +} + +static void __write_cpuxgpt(unsigned int reg_index, unsigned int value) +{ + #if defined(CONFIG_ARM_PSCI) || defined(CONFIG_MTK_PSCI) + /* DRV_WriteReg32(INDEX_BASE,reg_index); */ + /* DRV_WriteReg32(CTL_BASE,value); */ + mcusys_smc_write_phy(INDEX_BASE_PHY, reg_index); + mcusys_smc_write_phy(CTL_BASE_PHY, value); + #else +mcusys_smc_write(INDEX_BASE, reg_index); + mcusys_smc_write(CTL_BASE, value); + #endif +} + +static int __get_irq_id(int id) +{ + if (id < CPUXGPTNUMBERS) + return cpuxgpt_irq[id]; + + pr_err("%s:fine irq id error\n", __func__); + return -1; +} + +static void __cpuxgpt_enable(void) +{ + unsigned int tmp = 0; + + spin_lock(&cpuxgpt_reg_lock); + tmp = __read_cpuxgpt(INDEX_CTL_REG); + tmp |= EN_CPUXGPT; + __write_cpuxgpt(INDEX_CTL_REG, tmp); + spin_unlock(&cpuxgpt_reg_lock); +} + +static void __cpuxgpt_disable(void) +{ + unsigned int tmp = 0; + + spin_lock(&cpuxgpt_reg_lock); + tmp = __read_cpuxgpt(INDEX_CTL_REG); + tmp &= (~EN_CPUXGPT); + __write_cpuxgpt(INDEX_CTL_REG, tmp); + spin_unlock(&cpuxgpt_reg_lock); +} + +static void __cpuxgpt_halt_on_debug_en(int en) +{ + unsigned int tmp = 0; + + spin_lock(&cpuxgpt_reg_lock); + tmp = __read_cpuxgpt(INDEX_CTL_REG); + if (1 == en) + tmp |= EN_AHLT_DEBUG; + if (0 == en) + tmp &= (~EN_AHLT_DEBUG); + __write_cpuxgpt(INDEX_CTL_REG, tmp); + spin_unlock(&cpuxgpt_reg_lock); +} + +static void __cpuxgpt_set_clk(unsigned int div) +{ + unsigned int tmp = 0; + + /* printk("%s fwq div is 0x%x\n",__func__, div); */ + if (div != CLK_DIV1 && div != CLK_DIV2 && div != CLK_DIV4) + pr_err("%s error: div is not right\n", __func__); + spin_lock(&cpuxgpt_reg_lock); + tmp = __read_cpuxgpt(INDEX_CTL_REG); + tmp &= CLK_DIV_MASK; + tmp |= div; + __write_cpuxgpt(INDEX_CTL_REG, tmp); + spin_unlock(&cpuxgpt_reg_lock); +} + +static void __cpuxgpt_set_init_cnt(unsigned int countH, unsigned int countL) +{ + spin_lock(&cpuxgpt_reg_lock); + __write_cpuxgpt(INDEX_CNT_H_INIT, countH); + __write_cpuxgpt(INDEX_CNT_L_INIT, countL); + spin_unlock(&cpuxgpt_reg_lock); +} + +static unsigned int __cpuxgpt_irq_en(int cpuxgpt_num) +{ +unsigned int tmp = 0; + +spin_lock(&cpuxgpt_reg_lock); +tmp = __read_cpuxgpt(INDEX_IRQ_MASK); +tmp |= (1< 7 || id < 0) { + pr_err("%s: err idnumber id=%d should be 0~7\n", __func__, id); + return -1; + } + switch (id) { + case 0: + name = "mtk_cpuxgpt0"; + break; + case 1: + name = "mtk_cpuxgpt1"; + break; + case 2: + name = "mtk_cpuxgpt2"; + break; + case 3: + name = "mtk_cpuxgpt3"; + break; + case 4: + name = "mtk_cpuxgpt4"; + break; + case 5: + name = "mtk_cpuxgpt5"; + break; + case 6: + name = "mtk_cpuxgpt6"; + break; + case 7: + name = "mtk_cpuxgpt7"; + break; + + } + if (func) + user_handlers[id] = func; + + /* sprintf(name, "mtk_cpuxgpt%d", id); */ + + irq_id = __get_irq_id(id); + + /*cpuxgpt assigne for per core*/ +/*don't trigger IRQ to CPU0 mt_gic_cfg_irq2cpu(irq_id,0,0);*/ +/*trigger IRQ to CPUx mt_gic_cfg_irq2cpu(irq_id,(irq_id - CPUXGPT_IRQID_BASE)%num_possible_cpus(),1); */ + + ret = request_irq(irq_id, (irq_handler_t)cpuxgpt_irq_handler[id], + IRQF_TRIGGER_HIGH | IRQF_PERCPU, name, NULL); + if (ret != 0) { + pr_err("%s:%s fail to register irq\n", __func__, name); + return ret; + } + + pr_debug("%s:%s register irq (%d) ok\n", __func__, name , irq_id); + + return 0; +} +EXPORT_SYMBOL(cpu_xgpt_register_timer); + +int cpu_xgpt_set_timer(int id, u64 ns) +{ + u64 count = 0; + u64 now = 0; + u64 set_count = 0; + unsigned int set_count_lo = 0; +unsigned int set_count_hi = 0; + count = ns; + now = localtimer_get_phy_count(); + do_div(count, 1000/13); + + set_count = count + now; + set_count_lo = 0x00000000FFFFFFFF & set_count; + set_count_hi = (0xFFFFFFFF00000000 & set_count)>>32; + + pr_debug("%s:set cpuxgpt(%d) count(%u,%u)\n", __func__ , id, set_count_hi, set_count_lo); + + __cpuxgpt_set_cmp(id, set_count_hi, set_count_lo); + __cpuxgpt_irq_en(id); + return 0; +} +EXPORT_SYMBOL(cpu_xgpt_set_timer); + +void enable_cpuxgpt(void) +{ + __cpuxgpt_enable(); + pr_debug("%s: reg(%x)\n", __func__, __read_cpuxgpt(INDEX_CTL_REG)); +} +EXPORT_SYMBOL(enable_cpuxgpt); + +void disable_cpuxgpt(void) +{ + __cpuxgpt_disable(); + pr_debug("%s: reg(%x)\n", __func__, __read_cpuxgpt(INDEX_CTL_REG)); +} +EXPORT_SYMBOL(disable_cpuxgpt); + +void set_cpuxgpt_clk(unsigned int div) +{ + __cpuxgpt_set_clk(div); + pr_debug("%s: reg(%x)\n", __func__, __read_cpuxgpt(INDEX_CTL_REG)); +} +EXPORT_SYMBOL(set_cpuxgpt_clk); + +void restore_cpuxgpt(void) +{ + __write_cpuxgpt(INDEX_CTL_REG, g_ctl); + pr_debug("g_ctl:0x%x, %s\n", __read_cpuxgpt(INDEX_CTL_REG), __func__); + +} +EXPORT_SYMBOL(restore_cpuxgpt); + +void save_cpuxgpt(void) +{ + g_ctl = __read_cpuxgpt(INDEX_CTL_REG); + pr_debug("g_ctl:0x%x, %s\n", g_ctl, __func__); +} +EXPORT_SYMBOL(save_cpuxgpt); + +unsigned int cpu_xgpt_irq_dis(int cpuxgpt_num) +{ + __cpuxgpt_irq_dis(cpuxgpt_num); + + return 0; +} +EXPORT_SYMBOL(cpu_xgpt_irq_dis); + +int cpu_xgpt_set_cmp(CPUXGPT_NUM cpuxgpt_num, u64 count) +{ + + unsigned int set_count_lo = 0; +unsigned int set_count_hi = 0; + + set_count_lo = 0x00000000FFFFFFFF & count; + set_count_hi = (0xFFFFFFFF00000000 & count)>>32; + + cpu_xgpt_set_cmp_HL(cpuxgpt_num, set_count_hi, set_count_lo); + return 0; +} +EXPORT_SYMBOL(cpu_xgpt_set_cmp); + +void cpu_xgpt_set_init_count(unsigned int countH, unsigned int countL) +{ + __cpuxgpt_set_init_cnt(countH, countL); + +} +EXPORT_SYMBOL(cpu_xgpt_set_init_count); + +void cpu_xgpt_halt_on_debug_en(int en) +{ + __cpuxgpt_halt_on_debug_en(en); +} +EXPORT_SYMBOL(cpu_xgpt_halt_on_debug_en); + +CLOCKSOURCE_OF_DECLARE(mtk_cpuxgpt, "mediatek,cpuxgpt", mt_cpuxgpt_init); diff --git a/drivers/clocksource/mtk_timer_mt6755.c b/drivers/clocksource/mtk_timer_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..6495506f39abee2171b51bd3c590f692deca1f7c --- /dev/null +++ b/drivers/clocksource/mtk_timer_mt6755.c @@ -0,0 +1,784 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define GPT_CLKEVT_ID (GPT1) +#define GPT_CLKSRC_ID (GPT2) + +#define AP_XGPT_BASE xgpt_timers.tmr_regs + +#define GPT_IRQEN (AP_XGPT_BASE + 0x0000) +#define GPT_IRQSTA (AP_XGPT_BASE + 0x0004) +#define GPT_IRQACK (AP_XGPT_BASE + 0x0008) +#define GPT1_BASE (AP_XGPT_BASE + 0x0010) + +#define GPT_CON (0x00) +#define GPT_CLK (0x04) +#define GPT_CNT (0x08) +#define GPT_CMP (0x0C) +#define GPT_CNTH (0x18) +#define GPT_CMPH (0x1C) + +#define GPT_CON_ENABLE (0x1 << 0) +#define GPT_CON_CLRCNT (0x1 << 1) +#define GPT_CON_OPMODE (0x3 << 4) + +#define GPT_OPMODE_MASK (0x3) +#define GPT_CLKDIV_MASK (0xf) +#define GPT_CLKSRC_MASK (0x1) + +#define GPT_OPMODE_OFFSET (4) +#define GPT_CLKSRC_OFFSET (4) + +#define GPT_FEAT_64_BIT (0x0001) +#define GPT_ISR (0x0010) +#define GPT_IN_USE (0x0100) + +/************define this for 32/64 compatible**************/ +#define GPT_BIT_MASK_L 0x00000000FFFFFFFF +#define GPT_BIT_MASK_H 0xFFFFFFFF00000000 +/****************************************************/ + + +struct mt_xgpt_timers { + int tmr_irq; + void __iomem *tmr_regs; +}; + +struct gpt_device { + unsigned int id; + unsigned int mode; + unsigned int clksrc; + unsigned int clkdiv; + unsigned int cmp[2]; + void (*func)(unsigned long); + int flags; + int features; + void __iomem *base_addr; +}; + + +static struct mt_xgpt_timers xgpt_timers; +static struct gpt_device gpt_devs[NR_GPTS]; + +static DEFINE_SPINLOCK(gpt_lock); + +/************************return GPT4 count(before init clear) to +record kernel start time between LK and kernel****************************/ +#define GPT4_1MS_TICK ((u32)(13000)) /* 1000000 / 76.92ns = 13000.520 */ +#define GPT4_BASE (AP_XGPT_BASE + 0x0040) +static unsigned int boot_time_value; + +#define mt_gpt_set_reg(val, addr) mt_reg_sync_writel(__raw_readl(addr)|(val), addr) +#define mt_gpt_clr_reg(val, addr) mt_reg_sync_writel(__raw_readl(addr)&~(val), addr) + +static unsigned int xgpt_boot_up_time(void) +{ +unsigned int tick; + + tick = __raw_readl(GPT4_BASE + GPT_CNT); + return ((tick + (GPT4_1MS_TICK - 1)) / GPT4_1MS_TICK); +} +/*********************************************************/ + +static struct gpt_device *id_to_dev(unsigned int id) +{ + return id < NR_GPTS ? gpt_devs + id : NULL; +} + +#define gpt_update_lock(flags) spin_lock_irqsave(&gpt_lock, flags) + +#define gpt_update_unlock(flags) spin_unlock_irqrestore(&gpt_lock, flags) + +static inline void noop(unsigned long data) { } +static void(*handlers[])(unsigned long) = { + noop, + noop, + noop, + noop, + noop, + noop, + noop, +}; + +static struct tasklet_struct task[NR_GPTS]; +static void task_sched(unsigned long data) +{ + unsigned int id = (unsigned int)data; + + tasklet_schedule(&task[id]); +} + +static irqreturn_t gpt_handler(int irq, void *dev_id); +static cycle_t mt_gpt_read(struct clocksource *cs); +static int mt_gpt_set_next_event(unsigned long cycles, struct clock_event_device *evt); +static void mt_gpt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt); + +static struct clocksource gpt_clocksource = { + .name = "mtk-timer", + .rating = 300, + .read = mt_gpt_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 25, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static struct clock_event_device gpt_clockevent = { + .name = "mtk_tick", + .features = CLOCK_EVT_FEAT_ONESHOT, + .shift = 32, + .rating = 300, + .set_next_event = mt_gpt_set_next_event, + .set_mode = mt_gpt_set_mode +}; + +static struct irqaction gpt_irq = { + .name = "mt-gpt", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL | IRQF_TRIGGER_LOW, + .handler = gpt_handler, + .dev_id = &gpt_clockevent, +}; + +static inline unsigned int gpt_get_and_ack_irq(void) +{ + unsigned int id; + unsigned int mask; + unsigned int status = __raw_readl(GPT_IRQSTA); + + for (id = GPT1; id < NR_GPTS; id++) { + mask = 0x1 << id; + if (status & mask) { + mt_reg_sync_writel(mask, GPT_IRQACK); + break; + } + } + return id; +} + +static irqreturn_t gpt_handler(int irq, void *dev_id) +{ + unsigned int id = gpt_get_and_ack_irq(); + struct gpt_device *dev = id_to_dev(id); + + if (likely(dev)) { + if (!(dev->flags & GPT_ISR)) + handlers[id](id); + else + handlers[id]((unsigned long)dev_id); + } else + pr_err("GPT id is %d\n", id); + + return IRQ_HANDLED; +} + +static void __gpt_enable_irq(struct gpt_device *dev) +{ + mt_gpt_set_reg(0x1 << (dev->id), GPT_IRQEN); +} + +static void __gpt_disable_irq(struct gpt_device *dev) +{ + mt_gpt_clr_reg(0x1 << (dev->id), GPT_IRQEN); +} + +static void __gpt_ack_irq(struct gpt_device *dev) +{ + mt_reg_sync_writel(0x1 << (dev->id), GPT_IRQACK); +} + +static void __gpt_reset(struct gpt_device *dev) +{ + + mt_reg_sync_writel(0x0, dev->base_addr + GPT_CON); + __gpt_disable_irq(dev); + __gpt_ack_irq(dev); + mt_reg_sync_writel(0x0, dev->base_addr + GPT_CLK); + mt_reg_sync_writel(0x2, dev->base_addr + GPT_CON); + mt_reg_sync_writel(0x0, dev->base_addr + GPT_CMP); + if (dev->features & GPT_FEAT_64_BIT) + mt_reg_sync_writel(0, dev->base_addr + GPT_CMPH); +} + +static void __gpt_get_cnt(struct gpt_device *dev, unsigned int *ptr) +{ + *ptr = __raw_readl(dev->base_addr + GPT_CNT); + if (dev->features & GPT_FEAT_64_BIT) + *(++ptr) = __raw_readl(dev->base_addr + GPT_CNTH); +} + +static void __gpt_get_cmp(struct gpt_device *dev, unsigned int *ptr) +{ + *ptr = __raw_readl(dev->base_addr + GPT_CMP); + if (dev->features & GPT_FEAT_64_BIT) + *(++ptr) = __raw_readl(dev->base_addr + GPT_CMPH); +} + +static void __gpt_set_mode(struct gpt_device *dev, unsigned int mode) +{ + unsigned int ctl = __raw_readl(dev->base_addr + GPT_CON); + + mode <<= GPT_OPMODE_OFFSET; + + ctl &= ~GPT_CON_OPMODE; + ctl |= mode; + + mt_reg_sync_writel(ctl, dev->base_addr + GPT_CON); + + dev->mode = mode; +} + +static void __gpt_set_clk(struct gpt_device *dev, unsigned int clksrc, unsigned int clkdiv) +{ + unsigned int clk = (clksrc << GPT_CLKSRC_OFFSET) | clkdiv; + + mt_reg_sync_writel(clk, dev->base_addr + GPT_CLK); + + dev->clksrc = clksrc; + dev->clkdiv = clkdiv; +} + +static void __gpt_set_cmp(struct gpt_device *dev, unsigned int cmpl, + unsigned int cmph) +{ + mt_reg_sync_writel(cmpl, dev->base_addr + GPT_CMP); + dev->cmp[0] = cmpl; + + if (dev->features & GPT_FEAT_64_BIT) { + mt_reg_sync_writel(cmph, dev->base_addr + GPT_CMPH); + dev->cmp[1] = cmpl; + } +} + +static void __gpt_clrcnt(struct gpt_device *dev) +{ + mt_gpt_set_reg(GPT_CON_CLRCNT, dev->base_addr + GPT_CON); + while (__raw_readl(dev->base_addr + GPT_CNT)) + cpu_relax(); +} + +static void __gpt_start(struct gpt_device *dev) +{ + mt_gpt_set_reg(GPT_CON_ENABLE, dev->base_addr + GPT_CON); +} + +static void __gpt_stop(struct gpt_device *dev) +{ + mt_gpt_clr_reg(GPT_CON_ENABLE, dev->base_addr + GPT_CON); +} + +static void __gpt_start_from_zero(struct gpt_device *dev) +{ + /* DRV_SetReg32(dev->base_addr + GPT_CON, GPT_CON_ENABLE | GPT_CON_CLRCNT); */ + __gpt_clrcnt(dev); + __gpt_start(dev); +} + +static void __gpt_set_flags(struct gpt_device *dev, unsigned int flags) +{ + dev->flags |= flags; +} + +static void __gpt_set_handler(struct gpt_device *dev, void (*func)(unsigned long)) +{ + if (func) { + if (dev->flags & GPT_ISR) + handlers[dev->id] = func; + else { + tasklet_init(&task[dev->id], func, 0); + handlers[dev->id] = task_sched; + } + } + dev->func = func; +} + +static void gpt_devs_init(void) +{ + int i; + + for (i = 0; i < NR_GPTS; i++) { + gpt_devs[i].id = i; + gpt_devs[i].base_addr = GPT1_BASE + 0x10 * i; + pr_alert("gpt_devs_init: base_addr=0x%lx\n", (unsigned long)gpt_devs[i].base_addr); + } + + gpt_devs[GPT6].features |= GPT_FEAT_64_BIT; +} + +static void setup_gpt_dev_locked(struct gpt_device *dev, unsigned int mode, + unsigned int clksrc, unsigned int clkdiv, unsigned int cmp, + void (*func)(unsigned long), unsigned int flags) +{ + __gpt_set_flags(dev, flags | GPT_IN_USE); + + __gpt_set_mode(dev, mode & GPT_OPMODE_MASK); + __gpt_set_clk(dev, clksrc & GPT_CLKSRC_MASK, clkdiv & GPT_CLKDIV_MASK); + + if (func) + __gpt_set_handler(dev, func); + + if (dev->mode != GPT_FREE_RUN) { + __gpt_set_cmp(dev, cmp, 0); + if (!(dev->flags & GPT_NOIRQEN)) + __gpt_enable_irq(dev); + } + + if (!(dev->flags & GPT_NOAUTOEN)) + __gpt_start(dev); +} + +static int mt_gpt_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + struct gpt_device *dev = id_to_dev(GPT_CLKEVT_ID); + + /* printk("[%s]entry, evt=%lu\n", __func__, cycles); */ + + __gpt_stop(dev); + __gpt_set_cmp(dev, cycles, 0); + __gpt_start_from_zero(dev); + return 0; +} + +static void mt_gpt_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + struct gpt_device *dev = id_to_dev(GPT_CLKEVT_ID); + + /* printk("[%s]entry, mode=%d\n", __func__, mode); */ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + __gpt_stop(dev); + __gpt_set_mode(dev, GPT_REPEAT); + __gpt_enable_irq(dev); + __gpt_start_from_zero(dev); + break; + + case CLOCK_EVT_MODE_ONESHOT: + __gpt_stop(dev); + __gpt_set_mode(dev, GPT_ONE_SHOT); + __gpt_enable_irq(dev); + __gpt_start_from_zero(dev); + break; + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + __gpt_stop(dev); + __gpt_disable_irq(dev); + __gpt_ack_irq(dev); + break; + case CLOCK_EVT_MODE_RESUME: + default: + break; + } +} + +static cycle_t mt_gpt_read(struct clocksource *cs) +{ + cycle_t cycles; + unsigned int cnt[2] = {0, 0}; + struct gpt_device *dev = id_to_dev(GPT_CLKSRC_ID); + + __gpt_get_cnt(dev, cnt); + + if (GPT_CLKSRC_ID != GPT6) { + /* + * force do mask for high 32-bit to avoid unpredicted alignment + */ + cycles = (GPT_BIT_MASK_L & (cycle_t) (cnt[0])); + } else { + cycles = (GPT_BIT_MASK_H & (((cycle_t) (cnt[1])) << 32)) | (GPT_BIT_MASK_L&((cycle_t) (cnt[0]))); + } + + return cycles; +} + +static void clkevt_handler(unsigned long data) +{ + struct clock_event_device *evt = (struct clock_event_device *)data; + + evt->event_handler(evt); +} + +static inline void setup_clksrc(u32 freq) +{ + struct clocksource *cs = &gpt_clocksource; + struct gpt_device *dev = id_to_dev(GPT_CLKSRC_ID); + + pr_alert("setup_clksrc1: dev->base_addr=0x%lx GPT2_CON=0x%x\n", + (unsigned long)dev->base_addr, __raw_readl(dev->base_addr)); + cs->mult = clocksource_hz2mult(freq, cs->shift); + + setup_gpt_dev_locked(dev, GPT_FREE_RUN, GPT_CLK_SRC_SYS, GPT_CLK_DIV_1, + 0, NULL, 0); + + clocksource_register(cs); + + pr_alert("setup_clksrc2: dev->base_addr=0x%lx GPT2_CON=0x%x\n", + (unsigned long)dev->base_addr, __raw_readl(dev->base_addr)); +} + +static inline void setup_clkevt(u32 freq) +{ + unsigned int cmp[2]; + struct clock_event_device *evt = &gpt_clockevent; + struct gpt_device *dev = id_to_dev(GPT_CLKEVT_ID); + + evt->mult = div_sc(freq, NSEC_PER_SEC, evt->shift); + evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt); + evt->min_delta_ns = clockevent_delta2ns(3, evt); + /* evt->cpumask = cpumask_of(0); */ + evt->cpumask = cpu_possible_mask; + + setup_gpt_dev_locked(dev, GPT_REPEAT, GPT_CLK_SRC_SYS, GPT_CLK_DIV_1, + freq / HZ, clkevt_handler, GPT_ISR); + + __gpt_get_cmp(dev, cmp); + pr_alert("GPT1_CMP = %d, HZ = %d\n", cmp[0], HZ); + + clockevents_register_device(evt); +} + +static void setup_syscnt(void) +{ + /* map cpuxgpt address */ + mt_cpuxgpt_map_base(); + /* set cpuxgpt free run,cpuxgpt always free run & oneshot no need to set */ + /* set cpuxgpt 13Mhz clock */ + set_cpuxgpt_clk(CLK_DIV2); + /* enable cpuxgpt */ + enable_cpuxgpt(); +} + +static void __init mt_gpt_init(struct device_node *node) +{ + int i; + u32 freq = 0; + unsigned long save_flags; + struct clk *clk; + + gpt_update_lock(save_flags); + + /* Setup IRQ numbers */ + xgpt_timers.tmr_irq = irq_of_parse_and_map(node, 0); + + /* Setup IO addresses */ + xgpt_timers.tmr_regs = of_iomap(node, 0); + + /* freq=SYS_CLK_RATE */ + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) + pr_alert("Can't get timer clock"); + + if (clk_prepare_enable(clk)) + pr_alert("Can't prepare clock"); + + freq = (u32)clk_get_rate(clk); + if (!freq) + BUG(); + + boot_time_value = xgpt_boot_up_time(); /*record the time when init GPT*/ + + pr_alert("mt_gpt_init: tmr_regs=0x%lx, tmr_irq=%d, freq=%d\n", + (unsigned long)xgpt_timers.tmr_regs, xgpt_timers.tmr_irq, freq); + + gpt_devs_init(); + for (i = 0; i < NR_GPTS; i++) + __gpt_reset(&gpt_devs[i]); + + setup_clksrc(freq); + setup_irq(xgpt_timers.tmr_irq, &gpt_irq); + setup_clkevt(freq); + + /* use cpuxgpt as syscnt */ + setup_syscnt(); + pr_alert("mt_gpt_init: get_cnt_GPT2=%lld\n", mt_gpt_read(NULL)); /* /TODO: remove */ + gpt_update_unlock(save_flags); +} + +static void release_gpt_dev_locked(struct gpt_device *dev) +{ +__gpt_reset(dev); + +handlers[dev->id] = noop; +dev->func = NULL; + +dev->flags = 0; +} + +/* gpt is counting or not */ +static int __gpt_get_status(struct gpt_device *dev) +{ + return !!(__raw_readl(dev->base_addr + GPT_CON) & GPT_CON_ENABLE); +} + +/********************** export area *********************/ +int request_gpt(unsigned int id, unsigned int mode, unsigned int clksrc, + unsigned int clkdiv, unsigned int cmp, + void (*func)(unsigned long), unsigned int flags) +{ +unsigned long save_flags; +struct gpt_device *dev = id_to_dev(id); + +if (!dev) + return -EINVAL; + +if (dev->flags & GPT_IN_USE) { + pr_err("%s: GPT%d is in use!\n", __func__, (id + 1)); + return -EBUSY; +} + +gpt_update_lock(save_flags); +setup_gpt_dev_locked(dev, mode, clksrc, clkdiv, cmp, func, flags); +gpt_update_unlock(save_flags); + +return 0; +} +EXPORT_SYMBOL(request_gpt); + +int free_gpt(unsigned int id) +{ +unsigned long save_flags; + +struct gpt_device *dev = id_to_dev(id); + +if (!dev) + return -EINVAL; + +if (!(dev->flags & GPT_IN_USE)) + return 0; + +gpt_update_lock(save_flags); +release_gpt_dev_locked(dev); +gpt_update_unlock(save_flags); +return 0; +} +EXPORT_SYMBOL(free_gpt); + +int start_gpt(unsigned int id) +{ +unsigned long save_flags; + +struct gpt_device *dev = id_to_dev(id); + +if (!dev) + return -EINVAL; + +if (!(dev->flags & GPT_IN_USE)) { + pr_err("%s: GPT%d is not in use!\n", __func__, id); + return -EBUSY; +} + +gpt_update_lock(save_flags); +__gpt_clrcnt(dev); +__gpt_start(dev); +gpt_update_unlock(save_flags); + +return 0; +} +EXPORT_SYMBOL(start_gpt); + +int stop_gpt(unsigned int id) +{ +unsigned long save_flags; +struct gpt_device *dev = id_to_dev(id); + +if (!dev) + return -EINVAL; + +if (!(dev->flags & GPT_IN_USE)) { + pr_err("%s: GPT%d is not in use!\n", __func__, id); + return -EBUSY; +} + +gpt_update_lock(save_flags); +__gpt_stop(dev); +gpt_update_unlock(save_flags); + +return 0; +} +EXPORT_SYMBOL(stop_gpt); + +int restart_gpt(unsigned int id) +{ +unsigned long save_flags; +struct gpt_device *dev = id_to_dev(id); + +if (!dev) + return -EINVAL; + +if (!(dev->flags & GPT_IN_USE)) { + pr_err("%s: GPT%d is not in use!\n", __func__, id); + return -EBUSY; +} + +gpt_update_lock(save_flags); +__gpt_start(dev); +gpt_update_unlock(save_flags); + +return 0; +} +EXPORT_SYMBOL(restart_gpt); + +int gpt_is_counting(unsigned int id) +{ +unsigned long save_flags; +int is_counting; +struct gpt_device *dev = id_to_dev(id); + +if (!dev) + return -EINVAL; + +if (!(dev->flags & GPT_IN_USE)) { + pr_err("%s: GPT%d is not in use!\n", __func__, id); + return -EBUSY; +} + +gpt_update_lock(save_flags); +is_counting = __gpt_get_status(dev); +gpt_update_unlock(save_flags); + +return is_counting; +} +EXPORT_SYMBOL(gpt_is_counting); + +int gpt_set_cmp(unsigned int id, unsigned int val) +{ +unsigned long save_flags; +struct gpt_device *dev = id_to_dev(id); + +if (!dev) + return -EINVAL; + +if (dev->mode == GPT_FREE_RUN) + return -EINVAL; + +gpt_update_lock(save_flags); +__gpt_set_cmp(dev, val, 0); +gpt_update_unlock(save_flags); + +return 0; +} +EXPORT_SYMBOL(gpt_set_cmp); + +int gpt_get_cmp(unsigned int id, unsigned int *ptr) +{ +unsigned long save_flags; +struct gpt_device *dev = id_to_dev(id); + +if (!dev || !ptr) + return -EINVAL; + +gpt_update_lock(save_flags); +__gpt_get_cmp(dev, ptr); +gpt_update_unlock(save_flags); + +return 0; +} +EXPORT_SYMBOL(gpt_get_cmp); + +int gpt_get_cnt(unsigned int id, unsigned int *ptr) +{ +unsigned long save_flags; +struct gpt_device *dev = id_to_dev(id); + +if (!dev || !ptr) + return -EINVAL; + +if (!(dev->features & GPT_FEAT_64_BIT)) { + __gpt_get_cnt(dev, ptr); +} else { + gpt_update_lock(save_flags); + __gpt_get_cnt(dev, ptr); + gpt_update_unlock(save_flags); +} + +return 0; +} +EXPORT_SYMBOL(gpt_get_cnt); + +int gpt_check_irq(unsigned int id) +{ +unsigned int mask = 0x1 << id; + unsigned int status = __raw_readl(GPT_IRQSTA); +return (status & mask) ? 1 : 0; +} +EXPORT_SYMBOL(gpt_check_irq); + + +int gpt_check_and_ack_irq(unsigned int id) +{ +unsigned int mask = 0x1 << id; +unsigned int status = __raw_readl(GPT_IRQSTA); + +if (status & mask) { + mt_reg_sync_writel(mask, GPT_IRQACK); + return 1; +} else { + return 0; +} +} +EXPORT_SYMBOL(gpt_check_and_ack_irq); + +unsigned int gpt_boot_time(void) +{ + return boot_time_value; +} +EXPORT_SYMBOL(gpt_boot_time); + +int gpt_set_clk(unsigned int id, unsigned int clksrc, unsigned int clkdiv) +{ + unsigned long save_flags; + struct gpt_device *dev = id_to_dev(id); + + if (!dev) + return -EINVAL; + + if (!(dev->flags & GPT_IN_USE)) { + pr_err("%s: GPT%d is not in use!\n", __func__, id); + return -EBUSY; + } + + gpt_update_lock(save_flags); + __gpt_stop(dev); + __gpt_set_clk(dev, clksrc, clkdiv); + __gpt_start(dev); + gpt_update_unlock(save_flags); + + return 0; +} +EXPORT_SYMBOL(gpt_set_clk); + +/************************************************************************************************/ +CLOCKSOURCE_OF_DECLARE(mtk_apxgpt, "mediatek,apxgpt", mt_gpt_init); diff --git a/drivers/input/fingerprint/sunwavecorp/mt6750_dts.c b/drivers/input/fingerprint/sunwavecorp/mt6750_dts.c new file mode 100755 index 0000000000000000000000000000000000000000..c362d6baaed64089b6bc3edb05e01f4df373318e --- /dev/null +++ b/drivers/input/fingerprint/sunwavecorp/mt6750_dts.c @@ -0,0 +1,171 @@ +#include "finger.h" +#include "config.h" +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include + +//------------------------------------------------------------------------------ + + +/** + * this function olny use thread ex.open + * + */ + +typedef enum DTS_STATE { + STATE_DEFAULT, + STATE_RST_HIGH, + STATE_RST_LOW, + STATE_IRQ_MODE, + STATE_LDO1V8_ON, + STATE_LDO1V8_OFF, + STATE_LDO3V3_ON, + STATE_LDO3V3_OFF, + STATE_MAX, /* array size */ +} dts_status_t; + +static struct pinctrl* this_pctrl; /* static pinctrl instance */ + +/* DTS state mapping name */ +static const char* dts_state_name[STATE_MAX] = { + "default", + "fp_rst_high", + "fp_rst_low", + "fp_irq_mode", + "fp_ldo1v8_on", + "fp_ldo1v8_off", + "fp_ldo3v3_on", + "fp_ldo3v3_off" +}; + +/* pinctrl implementation */ +inline static long dts_set_state(const char* name) +{ + long ret = 0; + struct pinctrl_state* pin_state = 0; + BUG_ON(!this_pctrl); + pin_state = pinctrl_lookup_state(this_pctrl, name); + + if (IS_ERR(pin_state)) { + pr_err("sunwave ----finger set state '%s' failed\n", name); + ret = PTR_ERR(pin_state); + return ret; + } + + //printk("sunwave ---- dts_set_state = %s \n", name); + /* select state! */ + ret = pinctrl_select_state(this_pctrl, pin_state); + + if ( ret < 0) { + printk("sunwave --------pinctrl_select_state %s failed\n", name); + } + + return ret; +} + + +inline static long dts_select_state(dts_status_t s) +{ + BUG_ON(!((unsigned int)(s) < (unsigned int)(STATE_MAX))); + return dts_set_state(dts_state_name[s]); +} + +int mt6750_dts_reset(struct spi_device** spi) +{ + dts_select_state(STATE_RST_HIGH); + msleep(10); + dts_select_state(STATE_RST_LOW); + msleep(20); + dts_select_state(STATE_RST_HIGH); + return 0; +} + +static int mt6750_dts_gpio_init(struct spi_device** spidev) +{ + sunwave_sensor_t* sunwave = spi_to_sunwave(spidev); + struct device_node* finger_irq_node = NULL; + struct spi_device* spi = *spidev; + /* set power pin to high */ +#ifdef CONFIG_OF + spi->dev.of_node = of_find_compatible_node(NULL, NULL, "mediatek,vanzo-fp"); + this_pctrl = devm_pinctrl_get(&spi->dev); + + if (IS_ERR(this_pctrl)) { + //int ret = PTR_ERR(this_pctrl); + dev_err(&spi->dev, "fwq Cannot find fp pctrl!\n"); + return -ENODEV; + } + + dts_select_state(STATE_LDO1V8_ON); + dts_select_state(STATE_LDO3V3_ON); + mt6750_dts_reset(&spi); + dts_select_state(STATE_IRQ_MODE); + finger_irq_node = of_find_compatible_node(NULL, NULL, "mediatek, FINGERPRINT-eint"); + + if (finger_irq_node) { + u32 ints[2] = {0}; + of_property_read_u32_array(finger_irq_node, "debounce", ints, ARRAY_SIZE(ints)); + gpio_set_debounce(ints[0], ints[1]); + sunwave->standby_irq = irq_of_parse_and_map(finger_irq_node, 0); + } else { + return -ENOMEM; + } + +#endif + return 0; +} + +static int mt6750_dts_irq_hander(struct spi_device** spi) +{ + spi_to_sunwave(spi); + return 0; +} + + +static int mt6750_dts_speed(struct spi_device** spi, unsigned int speed) +{ +#define SPI_MODULE_CLOCK (100*1000*1000) + struct mt_chip_conf* config; + unsigned int time = SPI_MODULE_CLOCK / speed; + config = (struct mt_chip_conf*)(*spi)->controller_data; + config->low_time = time / 2; + config->high_time = time / 2; + + if (time % 2) { + config->high_time = config->high_time + 1; + } + + //(chip_config->low_time + chip_config->high_time); + return 0; +} + +static finger_t finger_sensor = { + .ver = 0, +#if __SUNWAVE_SPI_DMA_MODE_EN + .attribute = DEVICE_ATTRIBUTE_NONE, +#else // SPI FIFO MODE + .attribute = DEVICE_ATTRIBUTE_SPI_FIFO, +#endif + .write_then_read = 0, + .irq_hander = mt6750_dts_irq_hander, + .irq_request = 0, + .irq_free = 0, + .init = mt6750_dts_gpio_init, + .reset = mt6750_dts_reset, + .speed = mt6750_dts_speed, +}; + +void mt6750_dts_register_finger(sunwave_sensor_t* sunwave) +{ + sunwave->finger = &finger_sensor; +} +EXPORT_SYMBOL_GPL(mt6750_dts_register_finger); diff --git a/drivers/input/fingerprint/sunwavecorp/mt6750_dts_plat.c b/drivers/input/fingerprint/sunwavecorp/mt6750_dts_plat.c new file mode 100755 index 0000000000000000000000000000000000000000..68c5baf737f74167cdbe7510371015540bb7aa2f --- /dev/null +++ b/drivers/input/fingerprint/sunwavecorp/mt6750_dts_plat.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "finger.h" +#include "config.h" +#include + + +#define SUNWAVE_NAME "sunwave_fp" +//#define SUNWAVE_NAME "spidev" + +static struct mt_chip_conf sunwave_chip_config = { + /* + .setuptime = 20, + .holdtime = 20, + .high_time = 13, + .low_time = 12, + .cs_idletime = 10, + .ulthgh_thrsh = 0, + .cpol = 0, + .cpha = 0, + .rx_mlsb = 1, + .tx_mlsb = 1, + .tx_endian = 0, + .rx_endian = 0, + #ifdef MTK_SPI_DMA_MODE + .com_mod = DMA_TRANSFER, + #else + .com_mod = FIFO_TRANSFER, + #endif + .pause = PAUSE_MODE_ENABLE, + .finish_intr = 1, + .deassert = 0, + .ulthigh = 0, + .tckdly = 0, + */ + .setuptime = 15, + .holdtime = 15, + .high_time = 50, + .low_time = 50, + .cs_idletime = 20, + .ulthgh_thrsh = 0, + .cpol = 0, + .cpha = 0, + .rx_mlsb = 1, + .tx_mlsb = 1, + .tx_endian = 0, + .rx_endian = 0, +#if __SUNWAVE_SPI_DMA_MODE_EN + .com_mod = DMA_TRANSFER, +#else // SPI FIFO MODE + .com_mod = FIFO_TRANSFER, +#endif + + .pause = 0, + .finish_intr = 1, + .deassert = 0, + .ulthigh = 0, + .tckdly = 0, +}; + +static struct spi_board_info spi_board_devs[] __initdata = { + [0] = { + .modalias = SUNWAVE_NAME, + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_0, + .controller_data = &sunwave_chip_config, + }, +}; +static int __init mt6750_dts_register_platform(void) +{ + /*NOTE: spi_register_board_info don't use modules (*.ko) + * WARNING: spi_register_board_info" [sunwave.ko] undefined! + */ + spi_register_board_info(spi_board_devs, ARRAY_SIZE(spi_board_devs)); + return 0; +} + +module_init(mt6750_dts_register_platform); + +static void __exit mt6750_dts__dev_exit(void) +{ +} +module_exit(mt6750_dts__dev_exit); + +MODULE_AUTHOR("Jone.Chen, "); +MODULE_DESCRIPTION("User mode SPI device interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:sunwave_fp"); diff --git a/drivers/input/keyboard/mediatek/mt6755/Makefile b/drivers/input/keyboard/mediatek/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f6638484f259124474adc7844f7b34bf3e25e3d4 --- /dev/null +++ b/drivers/input/keyboard/mediatek/mt6755/Makefile @@ -0,0 +1,21 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +subdir-ccflags-y += -Werror -I$(srctree)/drivers/input/keyboard/mediatek/ + +ifeq ($(CONFIG_MT_SND_SOC_6755),y) + EXTRA_CFLAGS += -I$(srctree)/sound/soc/mediatek/common_define + EXTRA_CFLAGS += -I$(srctree)/sound/soc/mediatek/mt_soc_audio_6755 +endif + +obj-$(CONFIG_KEYBOARD_MTK) := hal_kpd.o diff --git a/drivers/input/keyboard/mediatek/mt6755/hal_kpd.c b/drivers/input/keyboard/mediatek/mt6755/hal_kpd.c new file mode 100644 index 0000000000000000000000000000000000000000..fe8a5438a5370ae42b1457be0307407753eebabe --- /dev/null +++ b/drivers/input/keyboard/mediatek/mt6755/hal_kpd.c @@ -0,0 +1,490 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#ifdef CONFIG_MT_SND_SOC_6755 +#include +#endif + +#define KPD_DEBUG KPD_YES + +#define KPD_SAY "kpd: " +#if KPD_DEBUG +#define kpd_print(fmt, arg...) pr_err(KPD_SAY fmt, ##arg) +#define kpd_info(fmt, arg...) pr_warn(KPD_SAY fmt, ##arg) +#else +#define kpd_print(fmt, arg...) do {} while (0) +#define kpd_info(fmt, arg...) do {} while (0) +#endif + +#ifdef CONFIG_KPD_PWRKEY_USE_EINT +static u8 kpd_pwrkey_state = !KPD_PWRKEY_POLARITY; +#endif + +static int kpd_show_hw_keycode = 1; +static int kpd_enable_lprst = 1; +static u16 kpd_keymap_state[KPD_NUM_MEMS] = { + 0xffff, 0xffff, 0xffff, 0xffff, 0x00ff +}; + +static bool kpd_sb_enable; + +#ifdef CONFIG_MTK_SMARTBOOK_SUPPORT +static void sb_kpd_release_keys(struct input_dev *dev) +{ + int code; + + for (code = 0; code <= KEY_MAX; code++) { + if (test_bit(code, dev->keybit)) { + kpd_print("report release event for sb plug in! keycode:%d\n", code); + input_report_key(dev, code, 0); + input_sync(dev); + } + } +} + +void sb_kpd_enable(void) +{ + kpd_sb_enable = true; + kpd_print("sb_kpd_enable performed!\n"); + mt_reg_sync_writew(0x0, KP_EN); + sb_kpd_release_keys(kpd_input_dev); +} + +void sb_kpd_disable(void) +{ + kpd_sb_enable = false; + kpd_print("sb_kpd_disable performed!\n"); + mt_reg_sync_writew(0x1, KP_EN); +} +#else +void sb_kpd_enable(void) +{ + kpd_print("sb_kpd_enable empty function for HAL!\n"); +} + +void sb_kpd_disable(void) +{ + kpd_print("sb_kpd_disable empty function for HAL!\n"); +} +#endif + +static void enable_kpd(int enable) +{ + if (enable == 1) { + mt_reg_sync_writew((u16) (enable), KP_EN); + kpd_print("KEYPAD is enabled\n"); + } else if (enable == 0) { + mt_reg_sync_writew((u16) (enable), KP_EN); + kpd_print("KEYPAD is disabled\n"); + } +} + +void kpd_slide_qwerty_init(void) +{ +#if KPD_HAS_SLIDE_QWERTY + bool evdev_flag = false; + bool power_op = false; + struct input_handler *handler; + struct input_handle *handle; + + handle = rcu_dereference(dev->grab); + if (handle) { + handler = handle->handler; + if (strcmp(handler->name, "evdev") == 0) + return -1; + } else { + list_for_each_entry_rcu(handle, &dev->h_list, d_node) { + handler = handle->handler; + if (strcmp(handler->name, "evdev") == 0) { + evdev_flag = true; + break; + } + } + if (evdev_flag == false) + return -1; + } + + power_op = powerOn_slidePin_interface(); + if (!power_op) + kpd_print(KPD_SAY "Qwerty slide pin interface power on fail\n"); + else + kpd_print("Qwerty slide pin interface power on success\n"); + + mt_eint_set_sens(KPD_SLIDE_EINT, KPD_SLIDE_SENSITIVE); + mt_eint_set_hw_debounce(KPD_SLIDE_EINT, KPD_SLIDE_DEBOUNCE); + mt_eint_registration(KPD_SLIDE_EINT, true, KPD_SLIDE_POLARITY, + kpd_slide_eint_handler, false); + + power_op = powerOff_slidePin_interface(); + if (!power_op) + kpd_print(KPD_SAY "Qwerty slide pin interface power off fail\n"); + else + kpd_print("Qwerty slide pin interface power off success\n"); +#endif +} + +void kpd_get_keymap_state(u16 state[]) +{ + state[0] = *(volatile u16 *)KP_MEM1; + state[1] = *(volatile u16 *)KP_MEM2; + state[2] = *(volatile u16 *)KP_MEM3; + state[3] = *(volatile u16 *)KP_MEM4; + state[4] = *(volatile u16 *)KP_MEM5; + kpd_print(KPD_SAY "register = %x %x %x %x %x\n", state[0], state[1], state[2], state[3], state[4]); + +} + +static void kpd_factory_mode_handler(void) +{ + int i, j; + bool pressed; + u16 new_state[KPD_NUM_MEMS], change, mask; + u16 hw_keycode, linux_keycode; + + for (i = 0; i < KPD_NUM_MEMS - 1; i++) + kpd_keymap_state[i] = 0xffff; + if (!kpd_dts_data.kpd_use_extend_type) + kpd_keymap_state[KPD_NUM_MEMS - 1] = 0x00ff; + else + kpd_keymap_state[KPD_NUM_MEMS - 1] = 0xffff; + + kpd_get_keymap_state(new_state); + + for (i = 0; i < KPD_NUM_MEMS; i++) { + change = new_state[i] ^ kpd_keymap_state[i]; + if (!change) + continue; + + for (j = 0; j < 16; j++) { + mask = 1U << j; + if (!(change & mask)) + continue; + + hw_keycode = (i << 4) + j; + /* bit is 1: not pressed, 0: pressed */ + pressed = !(new_state[i] & mask); + if (kpd_show_hw_keycode) { + kpd_print(KPD_SAY "(%s) factory_mode HW keycode = %u\n", + pressed ? "pressed" : "released", hw_keycode); + } + BUG_ON(hw_keycode >= KPD_NUM_KEYS); + linux_keycode = kpd_dts_data.kpd_hw_init_map[hw_keycode]; + if (unlikely(linux_keycode == 0)) { + kpd_print("Linux keycode = 0\n"); + continue; + } + input_report_key(kpd_input_dev, linux_keycode, pressed); + input_sync(kpd_input_dev); + kpd_print("factory_mode report Linux keycode = %u\n", linux_keycode); + } + } + + memcpy(kpd_keymap_state, new_state, sizeof(new_state)); + kpd_print("save new keymap state\n"); +} + +/********************************************************************/ +void kpd_auto_test_for_factorymode(void) +{ + kpd_print("Enter kpd_auto_test_for_factorymode!\n"); + + mdelay(1000); + + kpd_factory_mode_handler(); + kpd_print("begin kpd_auto_test_for_factorymode!\n"); +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + if (pmic_get_register_value(PMIC_PWRKEY_DEB) == 1) { +#else + if (pmic_get_register_value(MT6351_PMIC_PWRKEY_DEB) == 1) { +#endif + kpd_print("power key release\n"); + /*kpd_pwrkey_pmic_handler(1);*/ + /*mdelay(time);*/ + /*kpd_pwrkey_pmic_handler(0);}*/ + } else { + kpd_print("power key press\n"); + kpd_pwrkey_pmic_handler(1); + /*mdelay(time);*/ + /*kpd_pwrkey_pmic_handler(0);*/ + } + +#ifdef KPD_PMIC_RSTKEY_MAP +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + if (pmic_get_register_value(PMIC_HOMEKEY_DEB) == 1) { +#else + if (pmic_get_register_value(MT6351_PMIC_HOMEKEY_DEB) == 1) { +#endif + /*kpd_print("home key release\n");*/ + /*kpd_pmic_rstkey_handler(1);*/ + /*mdelay(time);*/ + /*kpd_pmic_rstkey_handler(0);*/ + } else { + kpd_print("home key press\n"); + kpd_pmic_rstkey_handler(1); + /*mdelay(time);*/ + /*kpd_pmic_rstkey_handler(0);*/ + } +#endif +} + +/********************************************************************/ +void long_press_reboot_function_setting(void) +{ + if (kpd_enable_lprst && get_boot_mode() == NORMAL_BOOT) { + kpd_info("Normal Boot long press reboot selection\n"); +#ifdef CONFIG_KPD_PMIC_LPRST_TD + kpd_info("Enable normal mode LPRST\n"); +#ifdef CONFIG_ONEKEY_REBOOT_NORMAL_MODE +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN, 0x01); + pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN, 0x00); + pmic_set_register_value(PMIC_RG_PWRKEY_RST_TD, CONFIG_KPD_PMIC_LPRST_TD); +#else + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_HOMEKEY_RST_EN, 0x00); + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_TD, CONFIG_KPD_PMIC_LPRST_TD); +#endif +#endif + +#ifdef CONFIG_TWOKEY_REBOOT_NORMAL_MODE +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN, 0x01); + pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN, 0x01); + pmic_set_register_value(PMIC_RG_PWRKEY_RST_TD, CONFIG_KPD_PMIC_LPRST_TD); +#else + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_HOMEKEY_RST_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_TD, CONFIG_KPD_PMIC_LPRST_TD); +#endif +#endif +#else + kpd_info("disable normal mode LPRST\n"); +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN, 0x00); + pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN, 0x00); +#else + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_EN, 0x00); + pmic_set_register_value(MT6351_PMIC_RG_HOMEKEY_RST_EN, 0x00); +#endif + +#endif + } else { + kpd_info("Other Boot Mode long press reboot selection\n"); +#ifdef CONFIG_KPD_PMIC_LPRST_TD + kpd_info("Enable other mode LPRST\n"); +#ifdef CONFIG_ONEKEY_REBOOT_OTHER_MODE +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN, 0x01); + pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN, 0x00); + pmic_set_register_value(PMIC_RG_PWRKEY_RST_TD, CONFIG_KPD_PMIC_LPRST_TD); +#else + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_HOMEKEY_RST_EN, 0x00); + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_TD, CONFIG_KPD_PMIC_LPRST_TD); +#endif +#endif + +#ifdef CONFIG_TWOKEY_REBOOT_OTHER_MODE +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN, 0x01); + pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN, 0x01); + pmic_set_register_value(PMIC_RG_PWRKEY_RST_TD, CONFIG_KPD_PMIC_LPRST_TD); +#else + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_HOMEKEY_RST_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_TD, CONFIG_KPD_PMIC_LPRST_TD); +#endif +#endif +#else + kpd_info("disable other mode LPRST\n"); +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_RG_PWRKEY_RST_EN, 0x00); + pmic_set_register_value(PMIC_RG_HOMEKEY_RST_EN, 0x00); +#else + pmic_set_register_value(MT6351_PMIC_RG_PWRKEY_RST_EN, 0x00); + pmic_set_register_value(MT6351_PMIC_RG_HOMEKEY_RST_EN, 0x00); +#endif +#endif + } +} + +/* FM@suspend */ +bool __attribute__ ((weak)) ConditionEnterSuspend(void) +{ + return true; +} + +/********************************************************************/ +void kpd_wakeup_src_setting(int enable) +{ + int is_fm_radio_playing = 0; + + /* If FM is playing, keep keypad as wakeup source */ + if (ConditionEnterSuspend() == true) + is_fm_radio_playing = 0; + else + is_fm_radio_playing = 1; + + if (is_fm_radio_playing == 0) { + if (enable == 1) { + kpd_print("enable kpd work!\n"); + enable_kpd(1); + } else { + kpd_print("disable kpd work!\n"); + enable_kpd(0); + } + } +} + +/********************************************************************/ +void kpd_init_keymap(u16 keymap[]) +{ + int i = 0; + + if (kpd_dts_data.kpd_use_extend_type) + kpd_keymap_state[4] = 0xffff; + for (i = 0; i < KPD_NUM_KEYS; i++) { + keymap[i] = kpd_dts_data.kpd_hw_init_map[i]; + /*kpd_print(KPD_SAY "keymap[%d] = %d\n", i,keymap[i]);*/ + } +} + +void kpd_init_keymap_state(u16 keymap_state[]) +{ + int i = 0; + + for (i = 0; i < KPD_NUM_MEMS; i++) + keymap_state[i] = kpd_keymap_state[i]; + kpd_info("init_keymap_state done: %x %x %x %x %x!\n", keymap_state[0], keymap_state[1], keymap_state[2], + keymap_state[3], keymap_state[4]); +} + +/********************************************************************/ + +void kpd_set_debounce(u16 val) +{ + mt_reg_sync_writew((u16) (val & KPD_DEBOUNCE_MASK), KP_DEBOUNCE); +} + +/********************************************************************/ +void kpd_pmic_rstkey_hal(unsigned long pressed) +{ + if (kpd_dts_data.kpd_sw_rstkey != 0) { + if (!kpd_sb_enable) { + input_report_key(kpd_input_dev, kpd_dts_data.kpd_sw_rstkey, pressed); + input_sync(kpd_input_dev); + if (kpd_show_hw_keycode) { + kpd_print(KPD_SAY "(%s) HW keycode =%d using PMIC\n", + pressed ? "pressed" : "released", kpd_dts_data.kpd_sw_rstkey); + } + } + } +} + +void kpd_pmic_pwrkey_hal(unsigned long pressed) +{ +#ifdef CONFIG_KPD_PWRKEY_USE_PMIC + if (!kpd_sb_enable) { + input_report_key(kpd_input_dev, kpd_dts_data.kpd_sw_pwrkey, pressed); + input_sync(kpd_input_dev); + if (kpd_show_hw_keycode) { + kpd_print(KPD_SAY "(%s) HW keycode =%d using PMIC\n", + pressed ? "pressed" : "released", kpd_dts_data.kpd_sw_pwrkey); + } + /*aee_powerkey_notify_press(pressed);*/ + } +#endif +} + +/***********************************************************************/ +void kpd_pwrkey_handler_hal(unsigned long data) +{ +#ifdef CONFIG_KPD_PWRKEY_USE_EINT + bool pressed; + u8 old_state = kpd_pwrkey_state; + + kpd_pwrkey_state = !kpd_pwrkey_state; + pressed = (kpd_pwrkey_state == !!KPD_PWRKEY_POLARITY); + if (kpd_show_hw_keycode) + kpd_print(KPD_SAY "(%s) HW keycode = using EINT\n", pressed ? "pressed" : "released"); + input_report_key(kpd_input_dev, kpd_dts_data.kpd_sw_pwrkey, pressed); + kpd_print("report Linux keycode = %u\n", kpd_dts_data.kpd_sw_pwrkey); + input_sync(kpd_input_dev); + + /* for detecting the return to old_state */ + mt_eint_set_polarity(KPD_PWRKEY_EINT, old_state); + mt_eint_unmask(KPD_PWRKEY_EINT); +#endif +} + +#ifdef CONFIG_MTK_MRDUMP_KEY +static int mrdump_eint_state; +static int mrdump_ext_rst_irq; +static irqreturn_t mrdump_rst_eint_handler(int irq, void *data) +{ + /* bool pressed; */ + + if (mrdump_eint_state == 0) { + irq_set_irq_type(mrdump_ext_rst_irq, IRQ_TYPE_LEVEL_HIGH); + mrdump_eint_state = 1; + } else { + irq_set_irq_type(mrdump_ext_rst_irq, IRQ_TYPE_LEVEL_LOW); + mrdump_eint_state = 0; + } + + input_report_key(kpd_input_dev, KEY_RESTART, mrdump_eint_state); + input_sync(kpd_input_dev); + + return IRQ_HANDLED; +} +#endif + +/***********************************************************************/ +void mt_eint_register(void) +{ +#ifdef CONFIG_MTK_MRDUMP_KEY + int ints[2] = {0, 0}; + int ret; + struct device_node *node; + + /* register EINT handler for MRDUMP_EXT_RST key */ + node = of_find_compatible_node(NULL, NULL, "mediatek, mrdump_ext_rst-eint"); + if (!node) + kpd_print("can't find compatible node\n"); + else { + of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints)); + gpio_set_debounce(ints[0], ints[1]); + + mrdump_ext_rst_irq = irq_of_parse_and_map(node, 0); + ret = request_irq(mrdump_ext_rst_irq, mrdump_rst_eint_handler, + IRQF_TRIGGER_NONE, "mrdump_ext_rst-eint", NULL); + if (ret > 0) + kpd_print("EINT IRQ LINE NOT AVAILABLE\n"); + } +#endif + +#ifdef CONFIG_KPD_PWRKEY_USE_EINT + mt_eint_set_sens(KPD_PWRKEY_EINT, KPD_PWRKEY_SENSITIVE); + mt_eint_set_hw_debounce(KPD_PWRKEY_EINT, KPD_PWRKEY_DEBOUNCE); + mt_eint_registration(KPD_PWRKEY_EINT, true, KPD_PWRKEY_POLARITY, + kpd_pwrkey_eint_handler, false); +#endif +} + +/************************************************************************/ diff --git a/drivers/input/keyboard/mediatek/mt6755/hal_kpd.h b/drivers/input/keyboard/mediatek/mt6755/hal_kpd.h new file mode 100644 index 0000000000000000000000000000000000000000..530640e501cd309677998d5be7b4a63688c01fea --- /dev/null +++ b/drivers/input/keyboard/mediatek/mt6755/hal_kpd.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef KPD_HAL_H +#define KPD_HAL_H +#include +/* Keypad registers */ +extern void __iomem *kp_base; + +#define KP_STA (kp_base + 0x0000) +#define KP_MEM1 (kp_base + 0x0004) +#define KP_MEM2 (kp_base + 0x0008) +#define KP_MEM3 (kp_base + 0x000c) +#define KP_MEM4 (kp_base + 0x0010) +#define KP_MEM5 (kp_base + 0x0014) +#define KP_DEBOUNCE (kp_base + 0x0018) +#define KP_SCAN_TIMING (kp_base + 0x001C) +#define KP_SEL (kp_base + 0x0020) +#define KP_EN (kp_base + 0x0024) + +#define KP_COL0_SEL (1 << 10) +#define KP_COL1_SEL (1 << 11) +#define KP_COL2_SEL (1 << 12) + +#define KPD_DEBOUNCE_MASK ((1U << 14) - 1) + +/*function define*/ +void kpd_slide_qwerty_init(void); +void kpd_ldvt_test_init(void); +void long_press_reboot_function_setting(void); +void kpd_auto_test_for_factorymode(void); +void kpd_wakeup_src_setting(int enable); +void kpd_get_keymap_state(u16 state[]); +void kpd_set_debounce(u16 val); +void kpd_init_keymap(u16 keymap[]); +void kpd_init_keymap_state(u16 keymap_state[]); +void kpd_pmic_rstkey_hal(unsigned long pressed); +void kpd_pmic_pwrkey_hal(unsigned long pressed); +void kpd_pwrkey_handler_hal(unsigned long data); +void mt_eint_register(void); +extern struct input_dev *kpd_input_dev; + +#ifdef CONFIG_MTK_SMARTBOOK_SUPPORT +void sb_kpd_enable(void); +void sb_kpd_disable(void); +#else +void sb_kpd_enable(void); +void sb_kpd_disable(void); +#endif + +#define KPD_NUM_MEMS 5 +#define KPD_MEM5_BITS 8 + +#define KPD_NUM_KEYS 72 /* 4 * 16 + KPD_MEM5_BITS */ +#endif diff --git a/drivers/misc/mediatek/accdet/mt6755/Makefile b/drivers/misc/mediatek/accdet/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..34b72f4d23d164d4881991c27b0f56ce42de0084 --- /dev/null +++ b/drivers/misc/mediatek/accdet/mt6755/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + + +obj-$(CONFIG_MTK_ACCDET) := accdet.o + +obj-$(CONFIG_TS3A225E_ACCDET) += ts3a225e.o diff --git a/drivers/misc/mediatek/accdet/mt6755/accdet.c b/drivers/misc/mediatek/accdet/mt6755/accdet.c new file mode 100644 index 0000000000000000000000000000000000000000..609e22626e798e136efa7a9eabe71399151de627 --- /dev/null +++ b/drivers/misc/mediatek/accdet/mt6755/accdet.c @@ -0,0 +1,1804 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "accdet.h" +#ifdef CONFIG_ACCDET_EINT +#include +#endif +#include +#include +#include +#include + +#define DEBUG_THREAD 1 +#define GET_ADC_DIRECTLY + +/*---------------------------------------------------------------------- +static variable defination +----------------------------------------------------------------------*/ + +#define REGISTER_VALUE(x) (x - 1) + +#define ACCDET_DEBOUNCE3_PLUG_OUT (0x20*30) /* 30 msec */ +static int button_press_debounce = 0x400; +static int mic_voltage1_comp; /* only for MIC mode = 6 */ +int cur_key = 0; +struct head_dts_data accdet_dts_data; +s8 accdet_auxadc_offset; +int accdet_irq; +unsigned int gpiopin, headsetdebounce; +unsigned int accdet_eint_type; +struct headset_mode_settings *cust_headset_settings; +#define ACCDET_DEBUG(format, args...) pr_debug(format, ##args) +#define ACCDET_INFO(format, args...) pr_warn(format, ##args) +#define ACCDET_ERROR(format, args...) pr_err(format, ##args) +static struct switch_dev accdet_data; +static struct input_dev *kpd_accdet_dev; +static struct cdev *accdet_cdev; +static struct class *accdet_class; +static struct device *accdet_nor_device; +static dev_t accdet_devno; +static int pre_status; +static int pre_state_swctrl; +static int accdet_status = PLUG_OUT; +static int cable_type; +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION +/*add for new feature PIN recognition*/ +static int cable_pin_recognition; +static int show_icon_delay; +#endif +#if defined(ACCDET_TS3A225E_PIN_SWAP) +#define TS3A225E_CONNECTOR_NONE 0 +#define TS3A225E_CONNECTOR_TRS 1 +#define TS3A225E_CONNECTOR_TRRS_STANDARD 2 +#define TS3A225E_CONNECTOR_TRRS_OMTP 3 +unsigned char ts3a225e_reg_value[7] = { 0 }; +unsigned char ts3a225e_connector_type = TS3A225E_CONNECTOR_NONE; +#endif +static int eint_accdet_sync_flag; +static int g_accdet_first = 1; +static bool IRQ_CLR_FLAG; +static int call_status; +static int button_status; +struct wake_lock accdet_suspend_lock; +struct wake_lock accdet_irq_lock; +struct wake_lock accdet_key_lock; +struct wake_lock accdet_timer_lock; +static struct work_struct accdet_work; +static struct workqueue_struct *accdet_workqueue; +static DEFINE_MUTEX(accdet_eint_irq_sync_mutex); +static inline void clear_accdet_interrupt(void); +static inline void clear_accdet_eint_interrupt(void); +static void send_key_event(int keycode, int flag); +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ +static struct work_struct accdet_eint_work; +static struct workqueue_struct *accdet_eint_workqueue; +static inline void accdet_init(void); +#define MICBIAS_DISABLE_TIMER (6 * HZ) /*6 seconds*/ +struct timer_list micbias_timer; +static void disable_micbias(unsigned long a); +/* Used to let accdet know if the pin has been fully plugged-in */ +#define EINT_PIN_PLUG_IN (1) +#define EINT_PIN_PLUG_OUT (0) +int cur_eint_state = EINT_PIN_PLUG_OUT; +static struct work_struct accdet_disable_work; +static struct workqueue_struct *accdet_disable_workqueue; +#else +/*static int g_accdet_working_in_suspend =0;*/ +#endif/*end CONFIG_ACCDET_EINT*/ +#ifndef CONFIG_ACCDET_EINT_IRQ +struct pinctrl *accdet_pinctrl1; +struct pinctrl_state *pins_eint_int; +#endif +#ifdef DEBUG_THREAD +#endif +static u32 pmic_pwrap_read(u32 addr); +static void pmic_pwrap_write(u32 addr, unsigned int wdata); +char *accdet_status_string[5] = { + "Plug_out", + "Headset_plug_in", + /*"Double_check",*/ + "Hook_switch", + /*"Tvout_plug_in",*/ + "Stand_by" +}; +char *accdet_report_string[4] = { + "No_device", + "Headset_mic", + "Headset_no_mic", + /*"HEADSET_illegal",*/ + /* "Double_check"*/ +}; +/****************************************************************/ +/*** export function **/ +/****************************************************************/ + +void accdet_detect(void) +{ + int ret = 0; + + ACCDET_DEBUG("[Accdet]accdet_detect\n"); + + accdet_status = PLUG_OUT; + ret = queue_work(accdet_workqueue, &accdet_work); + if (!ret) + ACCDET_DEBUG("[Accdet]accdet_detect:accdet_work return:%d!\n", ret); +} +EXPORT_SYMBOL(accdet_detect); + +void accdet_state_reset(void) +{ + + ACCDET_DEBUG("[Accdet]accdet_state_reset\n"); + + accdet_status = PLUG_OUT; + cable_type = NO_DEVICE; +} +EXPORT_SYMBOL(accdet_state_reset); + +int accdet_get_cable_type(void) +{ + return cable_type; +} + +void accdet_auxadc_switch(int enable) +{ + if (enable) { +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_pwrap_write(ACCDET_EINT_NV, pmic_pwrap_read(ACCDET_EINT_NV) | ACCDET_BF_ON); +#else + pmic_pwrap_write(ACCDET_ADC_REG, pmic_pwrap_read(ACCDET_ADC_REG) | ACCDET_BF_ON); +#endif + /*ACCDET_DEBUG("ACCDET enable switch\n");*/ + } else { +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_pwrap_write(ACCDET_EINT_NV, pmic_pwrap_read(ACCDET_EINT_NV) & ~(ACCDET_BF_ON)); +#else + pmic_pwrap_write(ACCDET_ADC_REG, pmic_pwrap_read(ACCDET_ADC_REG) & ~(ACCDET_BF_ON)); +#endif + /*ACCDET_DEBUG("ACCDET disable switch\n");*/ + } +} + +/****************************************************************/ +/*******static function defination **/ +/****************************************************************/ +static u64 accdet_get_current_time(void) +{ + return sched_clock(); +} + +static bool accdet_timeout_ns(u64 start_time_ns, u64 timeout_time_ns) +{ + u64 cur_time = 0; + u64 elapse_time = 0; + + /*get current tick*/ + cur_time = accdet_get_current_time(); /*ns*/ + if (cur_time < start_time_ns) { + ACCDET_DEBUG("@@@@Timer overflow! start%lld cur timer%lld\n", start_time_ns, cur_time); + start_time_ns = cur_time; + timeout_time_ns = 400 * 1000; /*400us*/ + ACCDET_DEBUG("@@@@reset timer! start%lld setting%lld\n", start_time_ns, timeout_time_ns); + } + elapse_time = cur_time - start_time_ns; + + /*check if timeout*/ + if (timeout_time_ns <= elapse_time) { + /*timeout*/ + ACCDET_DEBUG("@@@@ACCDET IRQ clear Timeout\n"); + return false; + } + return true; +} + +/*pmic wrap read and write func*/ +static u32 pmic_pwrap_read(u32 addr) +{ + u32 val = 0; + + pwrap_read(addr, &val); + return val; +} + +static void pmic_pwrap_write(unsigned int addr, unsigned int wdata) +{ + pwrap_write(addr, wdata); +} + +#ifdef GET_ADC_DIRECTLY +static int Accdet_PMIC_IMM_GetOneChannelValue(int deCount) +{ + int vol_val = 0; + + pmic_pwrap_write(ACCDET_AUXADC_CTL_SET, ACCDET_CH_REQ_EN); + mdelay(3); + while ((pmic_pwrap_read(ACCDET_AUXADC_REG) & ACCDET_DATA_READY) != ACCDET_DATA_READY) + ; + /*wait AUXADC data ready*/ + vol_val = (pmic_pwrap_read(ACCDET_AUXADC_REG) & ACCDET_DATA_MASK); + vol_val = (vol_val * 1800) / 4096; /*mv*/ + vol_val -= accdet_auxadc_offset; + vol_val -= mic_voltage1_comp; + if (vol_val < 0) + vol_val = 0; + ACCDET_DEBUG("ACCDET offset: %d mv, vol: %d mv, comp: %d\n", accdet_auxadc_offset, vol_val, mic_voltage1_comp); + return vol_val; +} +#endif + +#ifdef CONFIG_ACCDET_PIN_SWAP + +static void accdet_FSA8049_enable(void) +{ + mt_set_gpio_mode(GPIO_FSA8049_PIN, GPIO_FSA8049_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_FSA8049_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_FSA8049_PIN, GPIO_OUT_ONE); +} + +static void accdet_FSA8049_disable(void) +{ + mt_set_gpio_mode(GPIO_FSA8049_PIN, GPIO_FSA8049_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_FSA8049_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_FSA8049_PIN, GPIO_OUT_ZERO); +} + +#endif +static inline void headset_plug_out(void) +{ + accdet_status = PLUG_OUT; + cable_type = NO_DEVICE; + /*update the cable_type*/ + if (cur_key != 0) { + send_key_event(cur_key, 0); + ACCDET_DEBUG(" [accdet] headset_plug_out send key = %d release\n", cur_key); + cur_key = 0; + } + switch_set_state((struct switch_dev *)&accdet_data, cable_type); + ACCDET_DEBUG(" [accdet] set state in cable_type = NO_DEVICE\n"); + +} + +/*Accdet only need this func*/ +static inline void enable_accdet(u32 state_swctrl) +{ + /*enable ACCDET unit*/ + ACCDET_DEBUG("accdet: enable_accdet\n"); + /*enable clock*/ + pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_CLK_CLR); + pmic_pwrap_write(ACCDET_STATE_SWCTRL, pmic_pwrap_read(ACCDET_STATE_SWCTRL) | state_swctrl); + pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) | ACCDET_ENABLE); + +} + +static inline void disable_accdet(void) +{ + int irq_temp = 0; + + /*sync with accdet_irq_handler set clear accdet irq bit to avoid set clear accdet irq bit after disable accdet + disable accdet irq*/ + pmic_pwrap_write(INT_CON_ACCDET_CLR, RG_ACCDET_IRQ_CLR); + clear_accdet_interrupt(); + udelay(200); + mutex_lock(&accdet_eint_irq_sync_mutex); + while (pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) { + ACCDET_DEBUG("[Accdet]check_cable_type: Clear interrupt on-going....\n"); + msleep(20); + } + irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); + irq_temp = irq_temp & (~IRQ_CLR_BIT); + pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); + mutex_unlock(&accdet_eint_irq_sync_mutex); + /*disable ACCDET unit*/ + ACCDET_DEBUG("accdet: disable_accdet\n"); + pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL); +#ifdef CONFIG_ACCDET_EINT + pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0); + pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE); + /*disable clock and Analog control*/ + /*mt6331_upmu_set_rg_audmicbias1vref(0x0);*/ + pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET); +#endif +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(ACCDET_STATE_SWCTRL, ACCDET_EINT_PWM_EN); + pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) & (~(ACCDET_ENABLE))); + /*mt_set_gpio_out(GPIO_CAMERA_2_CMRST_PIN, GPIO_OUT_ZERO);*/ +#endif + +} + +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ +static void disable_micbias(unsigned long a) +{ + int ret = 0; + + ret = queue_work(accdet_disable_workqueue, &accdet_disable_work); + if (!ret) + ACCDET_DEBUG("[Accdet]disable_micbias:accdet_work return:%d!\n", ret); +} + +static void disable_micbias_callback(struct work_struct *work) +{ + + if (cable_type == HEADSET_NO_MIC) { +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + show_icon_delay = 0; + cable_pin_recognition = 0; + ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition); + pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); + pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_thresh); +#endif + /*setting pwm idle;*/ + pmic_pwrap_write(ACCDET_STATE_SWCTRL, pmic_pwrap_read(ACCDET_STATE_SWCTRL) & ~ACCDET_SWCTRL_IDLE_EN); +#ifdef CONFIG_ACCDET_PIN_SWAP + /*accdet_FSA8049_disable(); disable GPIOxxx for PIN swap */ + /*ACCDET_DEBUG("[Accdet] FSA8049 disable!\n");*/ +#endif + disable_accdet(); + ACCDET_DEBUG("[Accdet] more than 5s MICBIAS : Disabled\n"); + } +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + else if (cable_type == HEADSET_MIC) { + pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); + pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_thresh); + ACCDET_DEBUG("[Accdet]pin recog after 5s recover micbias polling!\n"); + } +#endif +} + +static void accdet_eint_work_callback(struct work_struct *work) +{ +#ifdef CONFIG_ACCDET_EINT_IRQ + int irq_temp = 0; + + if (cur_eint_state == EINT_PIN_PLUG_IN) { + ACCDET_DEBUG("[Accdet]DCC EINT func :plug-in, cur_eint_state = %d\n", cur_eint_state); + mutex_lock(&accdet_eint_irq_sync_mutex); + eint_accdet_sync_flag = 1; + mutex_unlock(&accdet_eint_irq_sync_mutex); + wake_lock_timeout(&accdet_timer_lock, 7 * HZ); +#ifdef CONFIG_ACCDET_PIN_SWAP + /*pmic_pwrap_write(0x0400, pmic_pwrap_read(0x0400)|(1<<14)); */ + msleep(800); + accdet_FSA8049_enable(); /*enable GPIOxxx for PIN swap */ + ACCDET_DEBUG("[Accdet] FSA8049 enable!\n"); + msleep(250); /*PIN swap need ms*/ +#endif + + accdet_init(); /*do set pwm_idle on in accdet_init*/ + +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + show_icon_delay = 1; + /*micbias always on during detected PIN recognition*/ + pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); + pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width); + ACCDET_DEBUG("[Accdet]pin recog start! micbias always on!\n"); +#endif + /*set PWM IDLE on*/ + pmic_pwrap_write(ACCDET_STATE_SWCTRL, (pmic_pwrap_read(ACCDET_STATE_SWCTRL) | ACCDET_SWCTRL_IDLE_EN)); + /*enable ACCDET unit*/ + enable_accdet(ACCDET_SWCTRL_EN); + } else { +/*EINT_PIN_PLUG_OUT*/ +/*Disable ACCDET*/ + ACCDET_DEBUG("[Accdet]DCC EINT func :plug-out, cur_eint_state = %d\n", cur_eint_state); + mutex_lock(&accdet_eint_irq_sync_mutex); + eint_accdet_sync_flag = 0; + mutex_unlock(&accdet_eint_irq_sync_mutex); + del_timer_sync(&micbias_timer); +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + show_icon_delay = 0; + cable_pin_recognition = 0; +#endif +#ifdef CONFIG_ACCDET_PIN_SWAP + /*pmic_pwrap_write(0x0400, pmic_pwrap_read(0x0400)&~(1<<14)); */ + accdet_FSA8049_disable(); /*disable GPIOxxx for PIN swap */ + ACCDET_DEBUG("[Accdet] FSA8049 disable!\n"); +#endif + /*accdet_auxadc_switch(0);*/ + disable_accdet(); + headset_plug_out(); + /*recover EINT irq clear bit */ + /*TODO: need think~~~*/ + irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); + irq_temp = irq_temp & (~IRQ_EINT_CLR_BIT); + pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); + } +#else + /*KE under fastly plug in and plug out*/ + if (cur_eint_state == EINT_PIN_PLUG_IN) { + ACCDET_DEBUG("[Accdet]ACC EINT func :plug-in, cur_eint_state = %d\n", cur_eint_state); + mutex_lock(&accdet_eint_irq_sync_mutex); + eint_accdet_sync_flag = 1; + mutex_unlock(&accdet_eint_irq_sync_mutex); + wake_lock_timeout(&accdet_timer_lock, 7 * HZ); +#ifdef CONFIG_ACCDET_PIN_SWAP + /*pmic_pwrap_write(0x0400, pmic_pwrap_read(0x0400)|(1<<14)); */ + msleep(800); + accdet_FSA8049_enable(); /*enable GPIOxxx for PIN swap */ + ACCDET_DEBUG("[Accdet] FSA8049 enable!\n"); + msleep(250); /*PIN swap need ms */ +#endif +#if defined(ACCDET_TS3A225E_PIN_SWAP) + ACCDET_DEBUG("[Accdet] TS3A225E enable!\n"); + ts3a225e_write_byte(0x04, 0x01); + msleep(500); + ts3a225e_read_byte(0x02, &ts3a225e_reg_value[1]); + ts3a225e_read_byte(0x03, &ts3a225e_reg_value[2]); + ts3a225e_read_byte(0x05, &ts3a225e_reg_value[4]); + ts3a225e_read_byte(0x06, &ts3a225e_reg_value[5]); + ACCDET_DEBUG("[Accdet] TS3A225E CTRL1=%x!\n", ts3a225e_reg_value[1]); + ACCDET_DEBUG("[Accdet] TS3A225E CTRL2=%x!\n", ts3a225e_reg_value[2]); + ACCDET_DEBUG("[Accdet] TS3A225E DAT1=%x!\n", ts3a225e_reg_value[4]); + ACCDET_DEBUG("[Accdet] TS3A225E INT=%x!\n", ts3a225e_reg_value[5]); + if (ts3a225e_reg_value[5] == 0x01) { + ACCDET_DEBUG("[Accdet] TS3A225E A standard TSR headset detected, RING2 and SLEEVE shorted!\n"); + ts3a225e_connector_type = TS3A225E_CONNECTOR_TRS; + ts3a225e_write_byte(0x02, 0x07); + ts3a225e_write_byte(0x03, 0xf3); + msleep(20); + } else if (ts3a225e_reg_value[5] == 0x02) { + ACCDET_DEBUG("[Accdet] TS3A225E A microphone detected on either RING2 or SLEEVE!\n"); + if ((ts3a225e_reg_value[4] & 0x40) == 0x00) + ts3a225e_connector_type = TS3A225E_CONNECTOR_TRRS_STANDARD; + else + ts3a225e_connector_type = TS3A225E_CONNECTOR_TRRS_OMTP; + } else { + ACCDET_DEBUG("[Accdet] TS3A225E Detection sequence completed without successful!\n"); + } +#endif + + accdet_init(); /* do set pwm_idle on in accdet_init*/ + +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + show_icon_delay = 1; + /*micbias always on during detected PIN recognition*/ + pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); + pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width); + ACCDET_DEBUG("[Accdet]pin recog start! micbias always on!\n"); +#endif + /*set PWM IDLE on*/ + pmic_pwrap_write(ACCDET_STATE_SWCTRL, (pmic_pwrap_read(ACCDET_STATE_SWCTRL) | ACCDET_SWCTRL_IDLE_EN)); + /*enable ACCDET unit*/ + enable_accdet(ACCDET_SWCTRL_EN); + } else { +/*EINT_PIN_PLUG_OUT*/ +/*Disable ACCDET*/ + ACCDET_DEBUG("[Accdet]DCC EINT func :plug-out, cur_eint_state = %d\n", cur_eint_state); + mutex_lock(&accdet_eint_irq_sync_mutex); + eint_accdet_sync_flag = 0; + mutex_unlock(&accdet_eint_irq_sync_mutex); + del_timer_sync(&micbias_timer); +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + show_icon_delay = 0; + cable_pin_recognition = 0; +#endif +#ifdef CONFIG_ACCDET_PIN_SWAP + /*pmic_pwrap_write(0x0400, pmic_pwrap_read(0x0400)&~(1<<14));*/ + accdet_FSA8049_disable(); /*disable GPIOxxx for PIN swap*/ + ACCDET_DEBUG("[Accdet] FSA8049 disable!\n"); +#endif +#if defined(ACCDET_TS3A225E_PIN_SWAP) + ACCDET_DEBUG("[Accdet] TS3A225E disable!\n"); + ts3a225e_connector_type = TS3A225E_CONNECTOR_NONE; +#endif + /*accdet_auxadc_switch(0);*/ + disable_accdet(); + headset_plug_out(); + } + enable_irq(accdet_irq); + ACCDET_DEBUG("[Accdet]enable_irq !!!!!!\n"); +#endif +} + +static irqreturn_t accdet_eint_func(int irq, void *data) +{ + int ret = 0; + + ACCDET_DEBUG("[Accdet]Enter accdet_eint_func !!!!!!\n"); + if (cur_eint_state == EINT_PIN_PLUG_IN) { + /* + To trigger EINT when the headset was plugged in + We set the polarity back as we initialed. + */ +#ifndef CONFIG_ACCDET_EINT_IRQ + if (accdet_eint_type == IRQ_TYPE_LEVEL_HIGH) + irq_set_irq_type(accdet_irq, IRQ_TYPE_LEVEL_HIGH); + else + irq_set_irq_type(accdet_irq, IRQ_TYPE_LEVEL_LOW); +#endif +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) & (~(7 << 4))); + /*debounce=256ms*/ + pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) | EINT_IRQ_DE_IN); + pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3); + +#else + gpio_set_debounce(gpiopin, headsetdebounce); +#endif + + /* update the eint status */ + cur_eint_state = EINT_PIN_PLUG_OUT; + } else { + /* + To trigger EINT when the headset was plugged out + We set the opposite polarity to what we initialed. + */ +#ifndef CONFIG_ACCDET_EINT_IRQ + if (accdet_eint_type == IRQ_TYPE_LEVEL_HIGH) + irq_set_irq_type(accdet_irq, IRQ_TYPE_LEVEL_LOW); + else + irq_set_irq_type(accdet_irq, IRQ_TYPE_LEVEL_HIGH); +#endif + +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) & (~(7 << 4))); + /*debounce=16ms*/ + pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) | EINT_IRQ_DE_OUT); +#else + gpio_set_debounce(gpiopin, accdet_dts_data.accdet_plugout_debounce * 1000); +#endif + /* update the eint status */ + cur_eint_state = EINT_PIN_PLUG_IN; + + mod_timer(&micbias_timer, jiffies + MICBIAS_DISABLE_TIMER); + } +#ifndef CONFIG_ACCDET_EINT_IRQ + disable_irq_nosync(accdet_irq); +#endif + ACCDET_DEBUG("[Accdet]accdet_eint_func after cur_eint_state=%d\n", cur_eint_state); + + ret = queue_work(accdet_eint_workqueue, &accdet_eint_work); + return IRQ_HANDLED; +} +#ifndef CONFIG_ACCDET_EINT_IRQ +static inline int accdet_setup_eint(struct platform_device *accdet_device) +{ + int ret; + u32 ints[2] = { 0, 0 }; + u32 ints1[2] = { 0, 0 }; + struct device_node *node = NULL; + struct pinctrl_state *pins_default; + + /*configure to GPIO function, external interrupt */ + ACCDET_INFO("[Accdet]accdet_setup_eint\n"); + accdet_pinctrl1 = devm_pinctrl_get(&accdet_device->dev); + if (IS_ERR(accdet_pinctrl1)) { + ret = PTR_ERR(accdet_pinctrl1); + dev_err(&accdet_device->dev, "fwq Cannot find accdet accdet_pinctrl1!\n"); + return ret; + } + + pins_default = pinctrl_lookup_state(accdet_pinctrl1, "default"); + if (IS_ERR(pins_default)) { + ret = PTR_ERR(pins_default); + dev_err(&accdet_device->dev, "fwq Cannot find accdet pinctrl default!\n"); + } + + pins_eint_int = pinctrl_lookup_state(accdet_pinctrl1, "state_eint_as_int"); + if (IS_ERR(pins_eint_int)) { + ret = PTR_ERR(pins_eint_int); + dev_err(&accdet_device->dev, "fwq Cannot find accdet pinctrl state_eint_int!\n"); + return ret; + } + pinctrl_select_state(accdet_pinctrl1, pins_eint_int); + + node = of_find_matching_node(node, accdet_of_match); + if (node) { + of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints)); + of_property_read_u32_array(node, "interrupts", ints1, ARRAY_SIZE(ints1)); + gpiopin = ints[0]; + headsetdebounce = ints[1]; + accdet_eint_type = ints1[1]; + gpio_set_debounce(gpiopin, headsetdebounce); + accdet_irq = irq_of_parse_and_map(node, 0); + ret = request_irq(accdet_irq, accdet_eint_func, IRQF_TRIGGER_NONE, "accdet-eint", NULL); + if (ret != 0) { + ACCDET_ERROR("[Accdet]EINT IRQ LINE NOT AVAILABLE\n"); + } else { + ACCDET_ERROR("[Accdet]accdet set EINT finished, accdet_irq=%d, headsetdebounce=%d\n", + accdet_irq, headsetdebounce); + } + } else { + ACCDET_ERROR("[Accdet]%s can't find compatible node\n", __func__); + } + return 0; +} +#endif /*CONFIG_ACCDET_EINT_IRQ*/ +#endif /*endif CONFIG_ACCDET_EINT*/ + +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ + +#define KEY_SAMPLE_PERIOD (60) /*ms*/ +#define MULTIKEY_ADC_CHANNEL (8) + +static DEFINE_MUTEX(accdet_multikey_mutex); +#define NO_KEY (0x0) +#define UP_KEY (0x01) +#define MD_KEY (0x02) +#define DW_KEY (0x04) +#define AS_KEY (0x08) + +#ifndef CONFIG_FOUR_KEY_HEADSET +static int key_check(int b) +{ + /*ACCDET_DEBUG("adc_data: %d v\n",b);*/ + + /* 0.24V ~ */ + /*ACCDET_DEBUG("[accdet] come in key_check!!\n");*/ + if ((b < accdet_dts_data.three_key.down_key) && (b >= accdet_dts_data.three_key.up_key)) + return DW_KEY; + else if ((b < accdet_dts_data.three_key.up_key) && (b >= accdet_dts_data.three_key.mid_key)) + return UP_KEY; + else if ((b < accdet_dts_data.three_key.mid_key) && (b >= 0)) + return MD_KEY; + ACCDET_DEBUG("[accdet] leave key_check!!\n"); + return NO_KEY; +} +#else +static int key_check(int b) +{ + /* 0.24V ~ */ + /*ACCDET_DEBUG("[accdet] come in key_check!!\n");*/ + if ((b < accdet_dts_data.four_key.down_key_four) && (b >= accdet_dts_data.four_key.up_key_four)) + return DW_KEY; + else if ((b < accdet_dts_data.four_key.up_key_four) && (b >= accdet_dts_data.four_key.voice_key_four)) + return UP_KEY; + else if ((b < accdet_dts_data.four_key.voice_key_four) && (b >= accdet_dts_data.four_key.mid_key_four)) + return AS_KEY; + else if ((b < accdet_dts_data.four_key.mid_key_four) && (b >= 0)) + return MD_KEY; + ACCDET_DEBUG("[accdet] leave key_check!!\n"); + return NO_KEY; +} + +#endif +static void send_key_event(int keycode, int flag) +{ + switch (keycode) { + case DW_KEY: + input_report_key(kpd_accdet_dev, KEY_VOLUMEDOWN, flag); + input_sync(kpd_accdet_dev); + ACCDET_DEBUG("[accdet]KEY_VOLUMEDOWN %d\n", flag); + break; + case UP_KEY: + input_report_key(kpd_accdet_dev, KEY_VOLUMEUP, flag); + input_sync(kpd_accdet_dev); + ACCDET_DEBUG("[accdet]KEY_VOLUMEUP %d\n", flag); + break; + case MD_KEY: + input_report_key(kpd_accdet_dev, KEY_PLAYPAUSE, flag); + input_sync(kpd_accdet_dev); + ACCDET_DEBUG("[accdet]KEY_PLAYPAUSE %d\n", flag); + break; + case AS_KEY: + input_report_key(kpd_accdet_dev, KEY_VOICECOMMAND, flag); + input_sync(kpd_accdet_dev); + ACCDET_DEBUG("[accdet]KEY_VOICECOMMAND %d\n", flag); + break; + } +} + +static void multi_key_detection(int current_status) +{ + int m_key = 0; + int cali_voltage = 0; + + if (0 == current_status) { +#ifdef GET_ADC_DIRECTLY + cali_voltage = Accdet_PMIC_IMM_GetOneChannelValue(1); +#else + cali_voltage = PMIC_IMM_GetOneChannelValue(PMIC_AUX_VACCDET_AP, 1, 0); + cali_voltage -= accdet_auxadc_offset; + ACCDET_DEBUG("[Accdet]adc cali_voltage1 = %d mv\n", cali_voltage); +#endif + m_key = cur_key = key_check(cali_voltage); + } + mdelay(30); +#ifdef CONFIG_ACCDET_EINT_IRQ + if (((pmic_pwrap_read(ACCDET_IRQ_STS) & EINT_IRQ_STATUS_BIT) != EINT_IRQ_STATUS_BIT) || eint_accdet_sync_flag) { +#else /* ifdef CONFIG_ACCDET_EINT */ + if (((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) != IRQ_STATUS_BIT) || eint_accdet_sync_flag) { +#endif + send_key_event(cur_key, !current_status); + } else { + ACCDET_DEBUG("[Accdet]plug out side effect key press, do not report key = %d\n", cur_key); + cur_key = NO_KEY; + } + if (current_status) + cur_key = NO_KEY; +} +#endif +static void accdet_workqueue_func(void) +{ + int ret; + + ret = queue_work(accdet_workqueue, &accdet_work); + if (!ret) + ACCDET_DEBUG("[Accdet]accdet_work return:%d!\n", ret); +} + +int accdet_irq_handler(void) +{ + u64 cur_time = 0; + + cur_time = accdet_get_current_time(); + +#ifdef CONFIG_ACCDET_EINT_IRQ + ACCDET_DEBUG("[Accdet accdet_irq_handler]clear_accdet_eint_interrupt: ACCDET_IRQ_STS = 0x%x\n", + pmic_pwrap_read(ACCDET_IRQ_STS)); + if ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) + && ((pmic_pwrap_read(ACCDET_IRQ_STS) & EINT_IRQ_STATUS_BIT) != EINT_IRQ_STATUS_BIT)) { + clear_accdet_interrupt(); + if (accdet_status == MIC_BIAS) { + /*accdet_auxadc_switch(1);*/ + pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); + pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_width)); + } + accdet_workqueue_func(); + while (((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) + && (accdet_timeout_ns(cur_time, ACCDET_TIME_OUT)))) + ; + } else if ((pmic_pwrap_read(ACCDET_IRQ_STS) & EINT_IRQ_STATUS_BIT) == EINT_IRQ_STATUS_BIT) { + if (cur_eint_state == EINT_PIN_PLUG_IN) { + if (accdet_eint_type == IRQ_TYPE_LEVEL_HIGH) + pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) | EINT_IRQ_POL_HIGH); + else + pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) & ~EINT_IRQ_POL_LOW); + } else { + if (accdet_eint_type == IRQ_TYPE_LEVEL_HIGH) + pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) & ~EINT_IRQ_POL_LOW); + else + pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) | EINT_IRQ_POL_HIGH); + } + clear_accdet_eint_interrupt(); + while (((pmic_pwrap_read(ACCDET_IRQ_STS) & EINT_IRQ_STATUS_BIT) + && (accdet_timeout_ns(cur_time, ACCDET_TIME_OUT)))) + ; + accdet_eint_func(accdet_irq, NULL); + } else { + ACCDET_DEBUG("ACCDET IRQ and EINT IRQ don't be triggerred!!\n"); + } +#else + if ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT)) + clear_accdet_interrupt(); + if (accdet_status == MIC_BIAS) { + /*accdet_auxadc_switch(1);*/ + pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); + pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_width)); + } + accdet_workqueue_func(); + while (((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) + && (accdet_timeout_ns(cur_time, ACCDET_TIME_OUT)))) + ; +#endif +#ifdef ACCDET_NEGV_IRQ + cur_time = accdet_get_current_time(); + if ((pmic_pwrap_read(ACCDET_IRQ_STS) & NEGV_IRQ_STATUS_BIT) == NEGV_IRQ_STATUS_BIT) { + ACCDET_DEBUG("[ACCDET NEGV detect]plug in a error Headset\n\r"); + pmic_pwrap_write(ACCDET_IRQ_STS, (IRQ_NEGV_CLR_BIT)); + while (((pmic_pwrap_read(ACCDET_IRQ_STS) & NEGV_IRQ_STATUS_BIT) + && (accdet_timeout_ns(cur_time, ACCDET_TIME_OUT)))) + ; + pmic_pwrap_write(ACCDET_IRQ_STS, (pmic_pwrap_read(ACCDET_IRQ_STS) & (~IRQ_NEGV_CLR_BIT))); + } +#endif + + return 1; +} + +/*clear ACCDET IRQ in accdet register*/ +static inline void clear_accdet_interrupt(void) +{ + /*it is safe by using polling to adjust when to clear IRQ_CLR_BIT*/ + pmic_pwrap_write(ACCDET_IRQ_STS, ((pmic_pwrap_read(ACCDET_IRQ_STS)) & 0x8000) | (IRQ_CLR_BIT)); + ACCDET_DEBUG("[Accdet]clear_accdet_interrupt: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS)); +} + +static inline void clear_accdet_eint_interrupt(void) +{ + pmic_pwrap_write(ACCDET_IRQ_STS, (((pmic_pwrap_read(ACCDET_IRQ_STS)) & 0x8000) | IRQ_EINT_CLR_BIT)); + ACCDET_DEBUG("[Accdet]clear_accdet_eint_interrupt: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS)); +} + +static inline void check_cable_type(void) +{ + int current_status = 0; + int irq_temp = 0; /*for clear IRQ_bit*/ + int wait_clear_irq_times = 0; +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + int pin_adc_value = 0; +#define PIN_ADC_CHANNEL 5 +#endif + + current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6); /*A=bit1; B=bit0*/ + ACCDET_DEBUG("[Accdet]accdet interrupt happen:[%s]current AB = %d\n", + accdet_status_string[accdet_status], current_status); + + button_status = 0; + pre_status = accdet_status; + + /*ACCDET_DEBUG("[Accdet]check_cable_type: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS));*/ + IRQ_CLR_FLAG = false; + switch (accdet_status) { + case PLUG_OUT: +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + pmic_pwrap_write(ACCDET_DEBOUNCE1, cust_headset_settings->debounce1); +#endif + if (current_status == 0) { +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + /*micbias always on during detected PIN recognition*/ + pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); + pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width); + ACCDET_DEBUG("[Accdet]PIN recognition micbias always on!\n"); + ACCDET_DEBUG("[Accdet]before adc read, pin_adc_value = %d mv!\n", pin_adc_value); + msleep(500); + current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6); /*A=bit1; B=bit0*/ + if (current_status == 0 && show_icon_delay != 0) { + /*accdet_auxadc_switch(1);switch on when need to use auxadc read voltage*/ +#ifdef GET_ADC_DIRECTLY + pin_adc_value = Accdet_PMIC_IMM_GetOneChannelValue(1); +#else + pin_adc_value = PMIC_IMM_GetOneChannelValue(PMIC_AUX_VACCDET_AP, 1, 0); + pin_adc_value -= accdet_auxadc_offset; +#endif + ACCDET_DEBUG("[Accdet]pin_adc_value = %d mv!\n", pin_adc_value); + /*accdet_auxadc_switch(0);*/ + if (180 > pin_adc_value && pin_adc_value > 90) { /*90mv ilegal headset*/ + /*mt_set_gpio_out(GPIO_CAMERA_2_CMRST_PIN, GPIO_OUT_ONE);*/ + /*ACCDET_DEBUG("[Accdet]PIN recognition change GPIO_OUT!\n");*/ + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + cable_type = HEADSET_NO_MIC; + accdet_status = HOOK_SWITCH; + cable_pin_recognition = 1; + ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", + cable_pin_recognition); + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); + } else { + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + cable_type = HEADSET_NO_MIC; + accdet_status = HOOK_SWITCH; + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); + } + } +#else + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + cable_type = HEADSET_NO_MIC; + accdet_status = HOOK_SWITCH; + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); +#endif + } else if (current_status == 1) { + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + accdet_status = MIC_BIAS; + cable_type = HEADSET_MIC; + /*AB=11 debounce=30ms*/ + pmic_pwrap_write(ACCDET_DEBOUNCE3, ACCDET_DEBOUNCE3_PLUG_OUT); + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); + pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce); + /*recover polling set AB 00-01*/ +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); + pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); +#endif + } else if (current_status == 3) { + ACCDET_DEBUG("[Accdet]PLUG_OUT state not change!\n"); +#ifdef CONFIG_ACCDET_EINT + ACCDET_DEBUG("[Accdet] do not send plug out event in plug out\n"); +#else + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + accdet_status = PLUG_OUT; + cable_type = NO_DEVICE; + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); +#endif + } else { + ACCDET_DEBUG("[Accdet]PLUG_OUT can't change to this state!\n"); + } + break; + + case MIC_BIAS: + /*solution: resume hook switch debounce time*/ + pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0); + + if (current_status == 0) { + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + while ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) + && (wait_clear_irq_times < 3)) { + ACCDET_DEBUG("[Accdet]check_cable_type: MIC BIAS clear IRQ on-going1....\n"); + wait_clear_irq_times++; + msleep(20); + } + irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); + irq_temp = irq_temp & (~IRQ_CLR_BIT); + pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); + IRQ_CLR_FLAG = true; + accdet_status = HOOK_SWITCH; + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); + button_status = 1; + if (button_status) { + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) + multi_key_detection(current_status); + else + ACCDET_DEBUG("[Accdet] multi_key_detection: Headset has plugged out\n"); + mutex_unlock(&accdet_eint_irq_sync_mutex); + /*accdet_auxadc_switch(0);*/ + /*recover pwm frequency and duty*/ + pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); + pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); + } + } else if (current_status == 1) { + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + accdet_status = MIC_BIAS; + cable_type = HEADSET_MIC; + ACCDET_DEBUG("[Accdet]MIC_BIAS state not change!\n"); + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); + } else if (current_status == 3) { +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ + ACCDET_DEBUG("[Accdet]do not send plug ou in micbiast\n"); + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) + accdet_status = PLUG_OUT; + else + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + mutex_unlock(&accdet_eint_irq_sync_mutex); +#else + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + accdet_status = PLUG_OUT; + cable_type = NO_DEVICE; + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); +#endif + } else { + ACCDET_DEBUG("[Accdet]MIC_BIAS can't change to this state!\n"); + } + break; + + case HOOK_SWITCH: + if (current_status == 0) { + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + /*for avoid 01->00 framework of Headset will report press key info for Audio*/ + /*cable_type = HEADSET_NO_MIC;*/ + /*accdet_status = HOOK_SWITCH;*/ + ACCDET_DEBUG("[Accdet]HOOK_SWITCH state not change!\n"); + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); + } else if (current_status == 1) { + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + multi_key_detection(current_status); + accdet_status = MIC_BIAS; + cable_type = HEADSET_MIC; + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); + /*accdet_auxadc_switch(0);*/ +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + cable_pin_recognition = 0; + ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition); + pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); + pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); +#endif + /*solution: reduce hook switch debounce time to 0x400*/ + pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce); + } else if (current_status == 3) { + +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + cable_pin_recognition = 0; + ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition); + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) + accdet_status = PLUG_OUT; + else + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + mutex_unlock(&accdet_eint_irq_sync_mutex); +#endif +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ + ACCDET_DEBUG("[Accdet] do not send plug out event in hook switch\n"); + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) + accdet_status = PLUG_OUT; + else + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + mutex_unlock(&accdet_eint_irq_sync_mutex); +#else + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + accdet_status = PLUG_OUT; + cable_type = NO_DEVICE; + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); +#endif + } else { + ACCDET_DEBUG("[Accdet]HOOK_SWITCH can't change to this state!\n"); + } + break; + case STAND_BY: + if (current_status == 3) { +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ + ACCDET_DEBUG("[Accdet]accdet do not send plug out event in stand by!\n"); +#else + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + accdet_status = PLUG_OUT; + cable_type = NO_DEVICE; + } else { + ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); + } + mutex_unlock(&accdet_eint_irq_sync_mutex); +#endif + } else { + ACCDET_DEBUG("[Accdet]STAND_BY can't change to this state!\n"); + } + break; + + default: + ACCDET_DEBUG("[Accdet]check_cable_type: accdet current status error!\n"); + break; + + } + + if (!IRQ_CLR_FLAG) { + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) { + while ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) && (wait_clear_irq_times < 3)) { + ACCDET_DEBUG("[Accdet]check_cable_type: Clear interrupt on-going2....\n"); + wait_clear_irq_times++; + msleep(20); + } + } + irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); + irq_temp = irq_temp & (~IRQ_CLR_BIT); + pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); + mutex_unlock(&accdet_eint_irq_sync_mutex); + IRQ_CLR_FLAG = true; + ACCDET_DEBUG("[Accdet]check_cable_type:Clear interrupt:Done[0x%x]!\n", pmic_pwrap_read(ACCDET_IRQ_STS)); + + } else { + IRQ_CLR_FLAG = false; + } + + ACCDET_DEBUG("[Accdet]cable type:[%s], status switch:[%s]->[%s]\n", + accdet_report_string[cable_type], accdet_status_string[pre_status], + accdet_status_string[accdet_status]); +} + +static void accdet_work_callback(struct work_struct *work) +{ + + wake_lock(&accdet_irq_lock); + check_cable_type(); + +#ifdef CONFIG_ACCDET_PIN_SWAP +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + if (cable_pin_recognition == 1) { + cable_pin_recognition = 0; + accdet_FSA8049_disable(); + cable_type = HEADSET_NO_MIC; + accdet_status = PLUG_OUT; + } +#endif +#endif + mutex_lock(&accdet_eint_irq_sync_mutex); + if (1 == eint_accdet_sync_flag) + switch_set_state((struct switch_dev *)&accdet_data, cable_type); + else + ACCDET_DEBUG("[Accdet] Headset has plugged out don't set accdet state\n"); + mutex_unlock(&accdet_eint_irq_sync_mutex); + ACCDET_DEBUG(" [accdet] set state in cable_type status\n"); + + wake_unlock(&accdet_irq_lock); +} + +void accdet_get_dts_data(void) +{ + struct device_node *node = NULL; + int debounce[7]; + #ifdef CONFIG_FOUR_KEY_HEADSET + int four_key[5]; + #else + int three_key[4]; + #endif + + ACCDET_INFO("[ACCDET]Start accdet_get_dts_data"); + node = of_find_matching_node(node, accdet_of_match); + if (node) { + of_property_read_u32_array(node, "headset-mode-setting", debounce, ARRAY_SIZE(debounce)); + of_property_read_u32(node, "accdet-mic-vol", &accdet_dts_data.mic_mode_vol); + of_property_read_u32(node, "accdet-plugout-debounce", &accdet_dts_data.accdet_plugout_debounce); + of_property_read_u32(node, "accdet-mic-mode", &accdet_dts_data.accdet_mic_mode); + #ifdef CONFIG_FOUR_KEY_HEADSET + of_property_read_u32_array(node, "headset-four-key-threshold", four_key, ARRAY_SIZE(four_key)); + memcpy(&accdet_dts_data.four_key, four_key+1, sizeof(struct four_key_threshold)); + ACCDET_INFO("[Accdet]mid-Key = %d, voice = %d, up_key = %d, down_key = %d\n", + accdet_dts_data.four_key.mid_key_four, accdet_dts_data.four_key.voice_key_four, + accdet_dts_data.four_key.up_key_four, accdet_dts_data.four_key.down_key_four); + #else + of_property_read_u32_array(node, "headset-three-key-threshold", three_key, ARRAY_SIZE(three_key)); + memcpy(&accdet_dts_data.three_key, three_key+1, sizeof(struct three_key_threshold)); + ACCDET_INFO("[Accdet]mid-Key = %d, up_key = %d, down_key = %d\n", + accdet_dts_data.three_key.mid_key, accdet_dts_data.three_key.up_key, + accdet_dts_data.three_key.down_key); + #endif + + memcpy(&accdet_dts_data.headset_debounce, debounce, sizeof(debounce)); + cust_headset_settings = &accdet_dts_data.headset_debounce; + ACCDET_INFO("[Accdet]pwm_width = %x, pwm_thresh = %x\n deb0 = %x, deb1 = %x, mic_mode = %d\n", + cust_headset_settings->pwm_width, cust_headset_settings->pwm_thresh, + cust_headset_settings->debounce0, cust_headset_settings->debounce1, + accdet_dts_data.accdet_mic_mode); + } else { + ACCDET_ERROR("[Accdet]%s can't find compatible dts node\n", __func__); + } +} +void accdet_pmic_Read_Efuse_HPOffset(void) +{ + s16 efusevalue; + + efusevalue = (s16) pmic_Read_Efuse_HPOffset(RG_OTP_PA_ADDR_WORD_INDEX); + accdet_auxadc_offset = (efusevalue >> RG_OTP_PA_ACCDET_BIT_SHIFT) & 0xFF; + accdet_auxadc_offset = (accdet_auxadc_offset / 2); + ACCDET_INFO(" efusevalue = 0x%x, accdet_auxadc_offset = %d\n", efusevalue, accdet_auxadc_offset); +} + +static inline void accdet_init(void) +{ + ACCDET_DEBUG("[Accdet]accdet hardware init\n"); + /*clock*/ + pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_CLK_CLR); + /*ACCDET_DEBUG("[Accdet]accdet TOP_CKPDN=0x%x!\n", pmic_pwrap_read(TOP_CKPDN)); */ + /*reset the accdet unit*/ + /*ACCDET_DEBUG("ACCDET reset : reset start!\n\r");*/ + pmic_pwrap_write(TOP_RST_ACCDET_SET, ACCDET_RESET_SET); + /*ACCDET_DEBUG("ACCDET reset function test: reset finished!!\n\r");*/ + pmic_pwrap_write(TOP_RST_ACCDET_CLR, ACCDET_RESET_CLR); + /*init pwm frequency and duty*/ + pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); + pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); + pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0x07); + + /*rise and fall delay of PWM*/ + pmic_pwrap_write(ACCDET_EN_DELAY_NUM, + (cust_headset_settings->fall_delay << 15 | cust_headset_settings->rise_delay)); + /* init the debounce time*/ +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0); + pmic_pwrap_write(ACCDET_DEBOUNCE1, 0xFFFF); /*2.0s*/ + pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3); + pmic_pwrap_write(ACCDET_DEBOUNCE4, ACCDET_DE4); +#else + pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0); + pmic_pwrap_write(ACCDET_DEBOUNCE1, cust_headset_settings->debounce1); + pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3); + pmic_pwrap_write(ACCDET_DEBOUNCE4, ACCDET_DE4); +#endif + /*enable INT */ +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) & (~IRQ_EINT_CLR_BIT)); +#endif +#ifdef CONFIG_ACCDET_EINT + pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) & (~IRQ_CLR_BIT)); +#endif + pmic_pwrap_write(INT_CON_ACCDET_SET, RG_ACCDET_IRQ_SET); +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(INT_CON_ACCDET_SET, RG_ACCDET_EINT_IRQ_SET); +#endif +#ifdef ACCDET_NEGV_IRQ + pmic_pwrap_write(INT_CON_ACCDET_SET, RG_ACCDET_NEGV_IRQ_SET); +#endif + /*********************ACCDET Analog Setting***********************************************************/ +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#if defined(CONFIG_MTK_LEGACY) +#ifndef ACCDET_WQHD + pmic_set_register_value(PMIC_RG_AUDMICBIASVREF, ACCDET_MIC_VOL); +#else + pmic_pwrap_write(ACCDET_ADC_REG, 0x068F); /*for wqhd project*/ +#endif +#else + pmic_set_register_value(PMIC_RG_AUDMICBIASVREF, accdet_dts_data.mic_mode_vol); +#endif + pmic_pwrap_write(ACCDET_RSV, 0x1290); /*TODO: need confirm pull low,6328 bit[12]=1*/ +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(ACCDET_EINT_NV, pmic_pwrap_read(ACCDET_EINT_NV) | ACCDET_EINT_CON_EN); +#endif +#ifdef ACCDET_NEGV_IRQ + pmic_pwrap_write(ACCDET_EINT_NV, pmic_pwrap_read(ACCDET_EINT_NV) | ACCDET_NEGV_DT_EN); +#endif + if (accdet_dts_data.accdet_mic_mode == 1) { /* ACC mode*/ + mic_voltage1_comp = 0; /* The variation of the hook key */ + pmic_set_register_value(PMIC_RG_AUDMICBIAS1DCSWPEN, 0); + } else if (accdet_dts_data.accdet_mic_mode == 2) { /* Low cost mode without internal bias*/ + mic_voltage1_comp = 0; /* The variation of the hook key */ + pmic_pwrap_write(ACCDET_RSV, pmic_pwrap_read(ACCDET_RSV) | ACCDET_INPUT_MICP); + } else if (accdet_dts_data.accdet_mic_mode == 6) { /* Low cost mode with internal bias*/ + mic_voltage1_comp = 20; /* The variation of the hook key */ + pmic_pwrap_write(ACCDET_RSV, pmic_pwrap_read(ACCDET_RSV) | ACCDET_INPUT_MICP); + pmic_set_register_value(PMIC_RG_AUDMICBIAS1DCSWPEN, 1); /*switch P internal*/ + } +#else + pmic_pwrap_write(ACCDET_ADC_REG, pmic_pwrap_read(ACCDET_ADC_REG) | 0xF); + pmic_pwrap_write(ACCDET_MICBIAS_REG, pmic_pwrap_read(ACCDET_MICBIAS_REG) + | (accdet_dts_data.mic_mode_vol<<4) | 0x80); + pmic_pwrap_write(ACCDET_RSV, 0x0010); +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(ACCDET_ADC_REG, pmic_pwrap_read(ACCDET_ADC_REG) + | ACCDET_EINT_CON_EN); /*Internal connection between ACCDET and EINT*/ +#endif +#ifdef ACCDET_NEGV_IRQ + pmic_pwrap_write(ACCDET_EINT_NV, pmic_pwrap_read(ACCDET_EINT_NV) | ACCDET_NEGV_DT_EN); +#endif + if (accdet_dts_data.accdet_mic_mode == 1) /* ACC mode*/ + ; + else if (accdet_dts_data.accdet_mic_mode == 2) /* Low cost mode without internal bias*/ + pmic_pwrap_write(ACCDET_ADC_REG, pmic_pwrap_read(ACCDET_ADC_REG) | 0x08C0); + else if (accdet_dts_data.accdet_mic_mode == 6) { /* Low cost mode with internal bias*/ + pmic_pwrap_write(ACCDET_ADC_REG, pmic_pwrap_read(ACCDET_ADC_REG) | 0x08C0); + pmic_pwrap_write(ACCDET_MICBIAS_REG, pmic_pwrap_read(ACCDET_MICBIAS_REG) | 0x0104); + } +#endif + /**************************************************************************************************/ +#if defined CONFIG_ACCDET_EINT + /* disable ACCDET unit*/ + pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL); + pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE); + pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0x0); + pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET); +#elif defined CONFIG_ACCDET_EINT_IRQ + if (cur_eint_state == EINT_PIN_PLUG_OUT) + pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) | EINT_IRQ_DE_IN);/*debounce=256ms*/ + pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) | EINT_PWM_THRESH); + /* disable ACCDET unit, except CLK of ACCDET*/ + pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL); + pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) | ACCDET_DISABLE); + pmic_pwrap_write(ACCDET_STATE_SWCTRL, pmic_pwrap_read(ACCDET_STATE_SWCTRL) & (~ACCDET_SWCTRL_EN)); + pmic_pwrap_write(ACCDET_STATE_SWCTRL, pmic_pwrap_read(ACCDET_STATE_SWCTRL) | ACCDET_EINT_PWM_EN); + pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) | ACCDET_EINT_EN); +#else + /* enable ACCDET unit*/ + pmic_pwrap_write(ACCDET_CTRL, ACCDET_ENABLE); +#endif +#ifdef ACCDET_NEGV_IRQ + pmic_pwrap_write(ACCDET_EINT_PWM_DELAY, pmic_pwrap_read(ACCDET_EINT_PWM_DELAY) & (~0x1F)); + pmic_pwrap_write(ACCDET_EINT_PWM_DELAY, pmic_pwrap_read(ACCDET_EINT_PWM_DELAY) | 0x0F); + pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) | ACCDET_NEGV_EN); +#endif + /**************************************AUXADC enable auto sample****************************************/ + pmic_pwrap_write(ACCDET_AUXADC_AUTO_SPL, (pmic_pwrap_read(ACCDET_AUXADC_AUTO_SPL) | ACCDET_AUXADC_AUTO_SET)); +} + +/*-----------------------------------sysfs-----------------------------------------*/ +#if DEBUG_THREAD +static int dump_register(void) +{ + int i = 0; + + for (i = ACCDET_RSV; i <= ACCDET_RSV_CON1; i += 2) + ACCDET_DEBUG(" ACCDET_BASE + %x=%x\n", i, pmic_pwrap_read(ACCDET_BASE + i)); + + ACCDET_DEBUG(" TOP_RST_ACCDET(0x%x) =%x\n", TOP_RST_ACCDET, pmic_pwrap_read(TOP_RST_ACCDET)); + ACCDET_DEBUG(" INT_CON_ACCDET(0x%x) =%x\n", INT_CON_ACCDET, pmic_pwrap_read(INT_CON_ACCDET)); + ACCDET_DEBUG(" TOP_CKPDN(0x%x) =%x\n", TOP_CKPDN, pmic_pwrap_read(TOP_CKPDN)); +#ifndef CONFIG_MTK_PMIC_CHIP_MT6353 + ACCDET_DEBUG(" ACCDET_MICBIAS_REG(0x%x) =%x\n", ACCDET_MICBIAS_REG, pmic_pwrap_read(ACCDET_MICBIAS_REG)); +#endif + ACCDET_DEBUG(" ACCDET_ADC_REG(0x%x) =%x\n", ACCDET_ADC_REG, pmic_pwrap_read(ACCDET_ADC_REG)); +#ifdef CONFIG_ACCDET_PIN_SWAP + /*ACCDET_DEBUG(" 0x00004000 =%x\n",pmic_pwrap_read(0x00004000));*/ + /*VRF28 power for PIN swap feature*/ +#endif + return 0; +} + +#if defined(ACCDET_TS3A225E_PIN_SWAP) +static ssize_t show_TS3A225EConnectorType(struct device_driver *ddri, char *buf) +{ + ACCDET_DEBUG("[Accdet] TS3A225E ts3a225e_connector_type=%d\n", ts3a225e_connector_type); + return sprintf(buf, "%u\n", ts3a225e_connector_type); +} + +static DRIVER_ATTR(TS3A225EConnectorType, 0664, show_TS3A225EConnectorType, NULL); +#endif +static ssize_t accdet_store_call_state(struct device_driver *ddri, const char *buf, size_t count) +{ + int ret; + + ret = kstrtoint(buf, 10, &call_status); + if (ret != 0) { + ACCDET_DEBUG("accdet: Invalid values\n"); + return -EINVAL; + } + + switch (call_status) { + case CALL_IDLE: + ACCDET_DEBUG("[Accdet]accdet call: Idle state!\n"); + break; + + case CALL_RINGING: + + ACCDET_DEBUG("[Accdet]accdet call: ringing state!\n"); + break; + + case CALL_ACTIVE: + ACCDET_DEBUG("[Accdet]accdet call: active or hold state!\n"); + ACCDET_DEBUG("[Accdet]accdet_ioctl : Button_Status=%d (state:%d)\n", button_status, accdet_data.state); + /*return button_status;*/ + break; + + default: + ACCDET_DEBUG("[Accdet]accdet call : Invalid values\n"); + break; + } + return count; +} + +static ssize_t show_pin_recognition_state(struct device_driver *ddri, char *buf) +{ +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + ACCDET_DEBUG("ACCDET show_pin_recognition_state = %d\n", cable_pin_recognition); + return sprintf(buf, "%u\n", cable_pin_recognition); +#else + return sprintf(buf, "%u\n", 0); +#endif +} + +static DRIVER_ATTR(accdet_pin_recognition, 0664, show_pin_recognition_state, NULL); +static DRIVER_ATTR(accdet_call_state, 0664, NULL, accdet_store_call_state); + +static int g_start_debug_thread; +static struct task_struct *thread; +static int g_dump_register; +static int dbug_thread(void *unused) +{ + while (g_start_debug_thread) { + if (g_dump_register) { + dump_register(); + /*dump_pmic_register();*/ + } + + msleep(500); + + } + return 0; +} + +static ssize_t store_accdet_start_debug_thread(struct device_driver *ddri, const char *buf, size_t count) +{ + + int start_flag; + int error; + int ret; + + ret = kstrtoint(buf, 10, &start_flag); + if (ret != 0) { + ACCDET_DEBUG("accdet: Invalid values\n"); + return -EINVAL; + } + + ACCDET_DEBUG("[Accdet] start flag =%d\n", start_flag); + + g_start_debug_thread = start_flag; + + if (1 == start_flag) { + thread = kthread_run(dbug_thread, 0, "ACCDET"); + if (IS_ERR(thread)) { + error = PTR_ERR(thread); + ACCDET_DEBUG(" failed to create kernel thread: %d\n", error); + } + } + + return count; +} + +static ssize_t store_accdet_set_headset_mode(struct device_driver *ddri, const char *buf, size_t count) +{ + + int value; + int ret; + + ret = kstrtoint(buf, 10, &value); + if (ret != 0) { + ACCDET_DEBUG("accdet: Invalid values\n"); + return -EINVAL; + } + + ACCDET_DEBUG("[Accdet]store_accdet_set_headset_mode value =%d\n", value); + + return count; +} + +static ssize_t store_accdet_dump_register(struct device_driver *ddri, const char *buf, size_t count) +{ + int value; + int ret; + + ret = kstrtoint(buf, 10, &value); + if (ret != 0) { + ACCDET_DEBUG("accdet: Invalid values\n"); + return -EINVAL; + } + + g_dump_register = value; + + ACCDET_DEBUG("[Accdet]store_accdet_dump_register value =%d\n", value); + + return count; +} + +/*----------------------------------------------------------------------------*/ +static DRIVER_ATTR(dump_register, S_IWUSR | S_IRUGO, NULL, store_accdet_dump_register); + +static DRIVER_ATTR(set_headset_mode, S_IWUSR | S_IRUGO, NULL, store_accdet_set_headset_mode); + +static DRIVER_ATTR(start_debug, S_IWUSR | S_IRUGO, NULL, store_accdet_start_debug_thread); + +/*----------------------------------------------------------------------------*/ +static struct driver_attribute *accdet_attr_list[] = { + &driver_attr_start_debug, + &driver_attr_set_headset_mode, + &driver_attr_dump_register, + &driver_attr_accdet_call_state, + /*#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION*/ + &driver_attr_accdet_pin_recognition, + /*#endif*/ +#if defined(ACCDET_TS3A225E_PIN_SWAP) + &driver_attr_TS3A225EConnectorType, +#endif +}; + +static int accdet_create_attr(struct device_driver *driver) +{ + int idx, err = 0; + int num = (int)(sizeof(accdet_attr_list) / sizeof(accdet_attr_list[0])); + + if (driver == NULL) + return -EINVAL; + for (idx = 0; idx < num; idx++) { + err = driver_create_file(driver, accdet_attr_list[idx]); + if (err) { + ACCDET_DEBUG("driver_create_file (%s) = %d\n", accdet_attr_list[idx]->attr.name, err); + break; + } + } + return err; +} + +#endif +void accdet_int_handler(void) +{ + int ret = 0; + + ACCDET_DEBUG("[accdet_int_handler]....\n"); + ret = accdet_irq_handler(); + if (0 == ret) + ACCDET_DEBUG("[accdet_int_handler] don't finished\n"); +} + +void accdet_eint_int_handler(void) +{ + int ret = 0; + + ACCDET_DEBUG("[accdet_eint_int_handler]....\n"); + ret = accdet_irq_handler(); + if (0 == ret) + ACCDET_DEBUG("[accdet_int_handler] don't finished\n"); +} + +int mt_accdet_probe(struct platform_device *dev) +{ + int ret = 0; + +#if DEBUG_THREAD + struct platform_driver accdet_driver_hal = accdet_driver_func(); +#endif + + ACCDET_INFO("[Accdet]accdet_probe begin!\n"); + + /*-------------------------------------------------------------------- + // below register accdet as switch class + //------------------------------------------------------------------*/ + accdet_data.name = "h2w"; + accdet_data.index = 0; + accdet_data.state = NO_DEVICE; + ret = switch_dev_register(&accdet_data); + if (ret) { + ACCDET_ERROR("[Accdet]switch_dev_register returned:%d!\n", ret); + return 1; + } + /*---------------------------------------------------------------------- + // Create normal device for auido use + //--------------------------------------------------------------------*/ + ret = alloc_chrdev_region(&accdet_devno, 0, 1, ACCDET_DEVNAME); + if (ret) + ACCDET_ERROR("[Accdet]alloc_chrdev_region: Get Major number error!\n"); + + accdet_cdev = cdev_alloc(); + accdet_cdev->owner = THIS_MODULE; + accdet_cdev->ops = accdet_get_fops(); + ret = cdev_add(accdet_cdev, accdet_devno, 1); + if (ret) + ACCDET_ERROR("[Accdet]accdet error: cdev_add\n"); + + accdet_class = class_create(THIS_MODULE, ACCDET_DEVNAME); + + /* if we want auto creat device node, we must call this*/ + accdet_nor_device = device_create(accdet_class, NULL, accdet_devno, NULL, ACCDET_DEVNAME); + + /*-------------------------------------------------------------------- + // Create input device + //------------------------------------------------------------------*/ + kpd_accdet_dev = input_allocate_device(); + if (!kpd_accdet_dev) { + ACCDET_ERROR("[Accdet]kpd_accdet_dev : fail!\n"); + return -ENOMEM; + } + /*INIT the timer to disable micbias.*/ + init_timer(&micbias_timer); + micbias_timer.expires = jiffies + MICBIAS_DISABLE_TIMER; + micbias_timer.function = &disable_micbias; + micbias_timer.data = ((unsigned long)0); + + /*define multi-key keycode*/ + __set_bit(EV_KEY, kpd_accdet_dev->evbit); + __set_bit(KEY_PLAYPAUSE, kpd_accdet_dev->keybit); + __set_bit(KEY_VOLUMEDOWN, kpd_accdet_dev->keybit); + __set_bit(KEY_VOLUMEUP, kpd_accdet_dev->keybit); + __set_bit(KEY_VOICECOMMAND, kpd_accdet_dev->keybit); + + kpd_accdet_dev->id.bustype = BUS_HOST; + kpd_accdet_dev->name = "ACCDET"; + if (input_register_device(kpd_accdet_dev)) + ACCDET_ERROR("[Accdet]kpd_accdet_dev register : fail!\n"); + /*------------------------------------------------------------------ + // Create workqueue + //------------------------------------------------------------------ */ + accdet_workqueue = create_singlethread_workqueue("accdet"); + INIT_WORK(&accdet_work, accdet_work_callback); + + /*------------------------------------------------------------------ + // wake lock + //------------------------------------------------------------------*/ + wake_lock_init(&accdet_suspend_lock, WAKE_LOCK_SUSPEND, "accdet wakelock"); + wake_lock_init(&accdet_irq_lock, WAKE_LOCK_SUSPEND, "accdet irq wakelock"); + wake_lock_init(&accdet_key_lock, WAKE_LOCK_SUSPEND, "accdet key wakelock"); + wake_lock_init(&accdet_timer_lock, WAKE_LOCK_SUSPEND, "accdet timer wakelock"); +#if DEBUG_THREAD + ret = accdet_create_attr(&accdet_driver_hal.driver); + if (ret != 0) + ACCDET_ERROR("create attribute err = %d\n", ret); +#endif + pmic_register_interrupt_callback(12, accdet_int_handler); + pmic_register_interrupt_callback(13, accdet_eint_int_handler); + ACCDET_INFO("[Accdet]accdet_probe : ACCDET_INIT\n"); + if (g_accdet_first == 1) { + eint_accdet_sync_flag = 1; +#ifdef CONFIG_ACCDET_EINT_IRQ + accdet_eint_workqueue = create_singlethread_workqueue("accdet_eint"); + INIT_WORK(&accdet_eint_work, accdet_eint_work_callback); + accdet_disable_workqueue = create_singlethread_workqueue("accdet_disable"); + INIT_WORK(&accdet_disable_work, disable_micbias_callback); +#endif + /*Accdet Hardware Init*/ + accdet_get_dts_data(); + accdet_init(); + accdet_pmic_Read_Efuse_HPOffset(); + /*schedule a work for the first detection*/ + queue_work(accdet_workqueue, &accdet_work); +#ifdef CONFIG_ACCDET_EINT + accdet_disable_workqueue = create_singlethread_workqueue("accdet_disable"); + INIT_WORK(&accdet_disable_work, disable_micbias_callback); + accdet_eint_workqueue = create_singlethread_workqueue("accdet_eint"); + INIT_WORK(&accdet_eint_work, accdet_eint_work_callback); + accdet_setup_eint(dev); +#endif + g_accdet_first = 0; + } + ACCDET_INFO("[Accdet]accdet_probe done!\n"); + return 0; +} + +void mt_accdet_remove(void) +{ + ACCDET_DEBUG("[Accdet]accdet_remove begin!\n"); + + /*cancel_delayed_work(&accdet_work);*/ +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ + destroy_workqueue(accdet_eint_workqueue); +#endif + destroy_workqueue(accdet_workqueue); + switch_dev_unregister(&accdet_data); + device_del(accdet_nor_device); + class_destroy(accdet_class); + cdev_del(accdet_cdev); + unregister_chrdev_region(accdet_devno, 1); + input_unregister_device(kpd_accdet_dev); + ACCDET_DEBUG("[Accdet]accdet_remove Done!\n"); +} + +void mt_accdet_suspend(void) /*only one suspend mode*/ +{ + +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ + ACCDET_DEBUG("[Accdet] in suspend1: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS)); +#else + ACCDET_DEBUG("[Accdet]accdet_suspend: ACCDET_CTRL=[0x%x], STATE=[0x%x]->[0x%x]\n", + pmic_pwrap_read(ACCDET_CTRL), pre_state_swctrl, pmic_pwrap_read(ACCDET_STATE_SWCTRL)); +#endif +} + +void mt_accdet_resume(void) /*wake up*/ +{ +#if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ + ACCDET_DEBUG("[Accdet] in resume1: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS)); +#else + ACCDET_DEBUG("[Accdet]accdet_resume: ACCDET_CTRL=[0x%x], STATE_SWCTRL=[0x%x]\n", + pmic_pwrap_read(ACCDET_CTRL), pmic_pwrap_read(ACCDET_STATE_SWCTRL)); + +#endif + +} + +/********************************************************************** +//add for IPO-H need update headset state when resume + +***********************************************************************/ +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION +struct timer_list accdet_disable_ipoh_timer; +static void mt_accdet_pm_disable(unsigned long a) +{ + if (cable_type == NO_DEVICE && eint_accdet_sync_flag == 0) { + /*disable accdet*/ + pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL); + pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0); +#ifdef CONFIG_ACCDET_EINT + pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE); + /*disable clock*/ + pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET); +#endif +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) & (~(ACCDET_ENABLE))); +#endif + ACCDET_DEBUG("[Accdet]daccdet_pm_disable: disable!\n"); + } else { + ACCDET_DEBUG("[Accdet]daccdet_pm_disable: enable!\n"); + } +} +#endif +void mt_accdet_pm_restore_noirq(void) +{ + int current_status_restore = 0; + + ACCDET_DEBUG("[Accdet]accdet_pm_restore_noirq start!\n"); + /*enable ACCDET unit*/ + ACCDET_DEBUG("accdet: enable_accdet\n"); + /*enable clock*/ + pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_CLK_CLR); +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_EINT_IRQ_CLR); + pmic_pwrap_write(ACCDET_RSV, pmic_pwrap_read(ACCDET_RSV) | ACCDET_INPUT_MICP); +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_pwrap_write(ACCDET_EINT_NV, pmic_pwrap_read(ACCDET_EINT_NV) | ACCDET_EINT_CON_EN); +#else + pmic_pwrap_write(ACCDET_ADC_REG, pmic_pwrap_read(ACCDET_ADC_REG) | ACCDET_EINT_CON_EN); +#endif + pmic_pwrap_write(ACCDET_CTRL, ACCDET_EINT_EN); +#endif +#ifdef ACCDET_NEGV_IRQ + pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_NEGV_IRQ_CLR); + pmic_pwrap_write(ACCDET_EINT_NV, pmic_pwrap_read(ACCDET_EINT_NV) | ACCDET_NEGV_DT_EN); + pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) | ACCDET_NEGV_EN); +#endif + enable_accdet(ACCDET_SWCTRL_EN); + pmic_pwrap_write(ACCDET_STATE_SWCTRL, (pmic_pwrap_read(ACCDET_STATE_SWCTRL) | ACCDET_SWCTRL_IDLE_EN)); + + eint_accdet_sync_flag = 1; + current_status_restore = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6); /*AB*/ + + switch (current_status_restore) { + case 0: /*AB=0*/ + cable_type = HEADSET_NO_MIC; + accdet_status = HOOK_SWITCH; + break; + case 1: /*AB=1*/ + cable_type = HEADSET_MIC; + accdet_status = MIC_BIAS; + break; + case 3: /*AB=3*/ + cable_type = NO_DEVICE; + accdet_status = PLUG_OUT; + break; + default: + ACCDET_DEBUG("[Accdet]accdet_pm_restore_noirq: accdet current status error!\n"); + break; + } + switch_set_state((struct switch_dev *)&accdet_data, cable_type); + if (cable_type == NO_DEVICE) { +#ifdef CONFIG_ACCDET_PIN_RECOGNIZATION + init_timer(&accdet_disable_ipoh_timer); + accdet_disable_ipoh_timer.expires = jiffies + 3 * HZ; + accdet_disable_ipoh_timer.function = &mt_accdet_pm_disable; + accdet_disable_ipoh_timer.data = ((unsigned long)0); + add_timer(&accdet_disable_ipoh_timer); + ACCDET_DEBUG("[Accdet]enable! pm timer\n"); + +#else + /*disable accdet*/ + pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL); +#ifdef CONFIG_ACCDET_EINT + pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0); + pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE); + /*disable clock*/ + pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET); +#endif +#ifdef CONFIG_ACCDET_EINT_IRQ + pmic_pwrap_write(ACCDET_STATE_SWCTRL, ACCDET_EINT_PWM_EN); + pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) & (~(ACCDET_ENABLE))); +#endif +#endif + } +} + +/*//////////////////////////////////IPO_H end/////////////////////////////////////////////*/ +long mt_accdet_unlocked_ioctl(unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case ACCDET_INIT: + break; + case SET_CALL_STATE: + call_status = (int)arg; + ACCDET_DEBUG("[Accdet]accdet_ioctl : CALL_STATE=%d\n", call_status); + break; + case GET_BUTTON_STATUS: + ACCDET_DEBUG("[Accdet]accdet_ioctl : Button_Status=%d (state:%d)\n", button_status, accdet_data.state); + return button_status; + default: + ACCDET_DEBUG("[Accdet]accdet_ioctl : default\n"); + break; + } + return 0; +} diff --git a/drivers/misc/mediatek/accdet/mt6755/accdet.h b/drivers/misc/mediatek/accdet/mt6755/accdet.h new file mode 100644 index 0000000000000000000000000000000000000000..e3526f2532740e28a1801cf52a647e2a581aa239 --- /dev/null +++ b/drivers/misc/mediatek/accdet/mt6755/accdet.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _ACCDEH_H_ +#define _ACCDEH_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "reg_accdet.h" + +/*---------------------------------------------------------------------- +IOCTL +----------------------------------------------------------------------*/ +#define ACCDET_DEVNAME "accdet" +#define ACCDET_IOC_MAGIC 'A' +#define ACCDET_INIT _IO(ACCDET_IOC_MAGIC, 0) +#define SET_CALL_STATE _IO(ACCDET_IOC_MAGIC, 1) +#define GET_BUTTON_STATUS _IO(ACCDET_IOC_MAGIC, 2) + +/*define for phone call state*/ + +#define CALL_IDLE 0 +#define CALL_RINGING 1 +#define CALL_ACTIVE 2 +#define KEY_CALL KEY_SEND +#define KEY_ENDCALL KEY_HANGEUL + +#define ACCDET_TIME_OUT 0x61A80 /*400us*/ +extern s32 pwrap_read(u32 adr, u32 *rdata); +extern s32 pwrap_write(u32 adr, u32 wdata); +extern const struct file_operations *accdet_get_fops(void);/*from accdet_drv.c*/ +extern struct platform_driver accdet_driver_func(void); /*from accdet_drv.c*/ +extern struct headset_mode_settings *get_cust_headset_settings(void); +extern struct headset_key_custom *get_headset_key_custom_setting(void); +extern void accdet_create_attr_func(void); /*from accdet_drv.c*/ +#if defined(ACCDET_TS3A225E_PIN_SWAP) +extern int ts3a225e_read_byte(unsigned char cmd, unsigned char *returnData); +extern int ts3a225e_write_byte(unsigned char cmd, unsigned char writeData); +#endif +extern struct of_device_id accdet_of_match[]; +void mt_accdet_remove(void); +void mt_accdet_suspend(void); +void mt_accdet_resume(void); +void mt_accdet_pm_restore_noirq(void); +long mt_accdet_unlocked_ioctl(unsigned int cmd, unsigned long arg); +int mt_accdet_probe(struct platform_device *dev); +int accdet_get_cable_type(void); + +/**************************************************** +globle ACCDET variables +****************************************************/ + +enum accdet_report_state { + NO_DEVICE = 0, + HEADSET_MIC = 1, + HEADSET_NO_MIC = 2, + /*HEADSET_ILEGAL = 3,*/ + /*DOUBLE_CHECK_TV = 4*/ +}; + +enum accdet_status { + PLUG_OUT = 0, + MIC_BIAS = 1, + /*DOUBLE_CHECK = 2,*/ + HOOK_SWITCH = 2, + /*MIC_BIAS_ILLEGAL =3,*/ + /*TV_OUT = 5,*/ + STAND_BY = 4 +}; + + +enum hook_switch_result { + DO_NOTHING = 0, + ANSWER_CALL = 1, + REJECT_CALL = 2 +}; +struct headset_mode_settings { + int pwm_width; /*pwm frequence*/ + int pwm_thresh; /*pwm duty*/ + int fall_delay; /*falling stable time*/ + int rise_delay; /*rising stable time*/ + int debounce0; /*hook switch or double check debounce*/ + int debounce1; /*mic bias debounce*/ + int debounce3; /*plug out debounce*/ +}; +struct three_key_threshold { + int mid_key; + int up_key; + int down_key; +}; +struct four_key_threshold { + int mid_key_four; + int voice_key_four; + int up_key_four; + int down_key_four; +}; +struct head_dts_data { + int mic_mode_vol; + struct headset_mode_settings headset_debounce; + int accdet_plugout_debounce; + int accdet_mic_mode; + struct three_key_threshold three_key; + struct four_key_threshold four_key; +}; +#ifdef CONFIG_ACCDET_EINT +extern struct platform_device accdet_device; +#endif +#endif diff --git a/drivers/misc/mediatek/accdet/mt6755/reg_accdet.h b/drivers/misc/mediatek/accdet/mt6755/reg_accdet.h new file mode 100644 index 0000000000000000000000000000000000000000..17c8f9e118240c775d4a379e7174d494aa6d3906 --- /dev/null +++ b/drivers/misc/mediatek/accdet/mt6755/reg_accdet.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/*Register address define*/ +#include + +#ifdef CONFIG_MTK_PMIC_NEW_ARCH + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#include "reg_accdet_mt6353.h" +#endif + +#else + +#define ACCDET_BASE 0x00000000 +#define TOP_RST_ACCDET MT6351_TOP_RST_CON0 +#define TOP_RST_ACCDET_SET MT6351_TOP_RST_CON0_SET +#define TOP_RST_ACCDET_CLR MT6351_TOP_RST_CON0_CLR + +#define INT_CON_ACCDET MT6351_INT_CON0 +#define INT_CON_ACCDET_SET MT6351_INT_CON0_SET +#define INT_CON_ACCDET_CLR MT6351_INT_CON0_CLR + +#define INT_STATUS_ACCDET MT6351_INT_STATUS0 +#define INT_STATUS_1 MT6351_INT_STATUS1 + +/*clock register*/ +#define TOP_CKPDN MT6351_TOP_CKPDN_CON2 +#define TOP_CKPDN_SET MT6351_TOP_CKPDN_CON2_SET +#define TOP_CKPDN_CLR MT6351_TOP_CKPDN_CON2_CLR + +#define ACCDET_RSV MT6351_ACCDET_CON0 +#define ACCDET_CTRL MT6351_ACCDET_CON1 +#define ACCDET_STATE_SWCTRL MT6351_ACCDET_CON2 +#define ACCDET_PWM_WIDTH MT6351_ACCDET_CON3 +#define ACCDET_PWM_THRESH MT6351_ACCDET_CON4 +#define ACCDET_EN_DELAY_NUM MT6351_ACCDET_CON5 +#define ACCDET_DEBOUNCE0 MT6351_ACCDET_CON6 +#define ACCDET_DEBOUNCE1 MT6351_ACCDET_CON7 +#define ACCDET_DEBOUNCE2 MT6351_ACCDET_CON8 +#define ACCDET_DEBOUNCE3 MT6351_ACCDET_CON9 +#define ACCDET_DEBOUNCE4 MT6351_ACCDET_CON10 +#define ACCDET_DEFAULT_STATE_RG MT6351_ACCDET_CON11 +#define ACCDET_IRQ_STS MT6351_ACCDET_CON12 +#define ACCDET_CONTROL_RG MT6351_ACCDET_CON13 +#define ACCDET_STATE_RG MT6351_ACCDET_CON14 +#define ACCDET_EINT_CTL MT6351_ACCDET_CON15 +#define ACCDET_EINT_PWM_DELAY MT6351_ACCDET_CON16 +#define ACCDET_TEST_DEBUG MT6351_ACCDET_CON17 +#define ACCDET_NEGV MT6351_ACCDET_CON20 +#define ACCDET_CUR_DEB MT6351_ACCDET_CON21 +#define ACCDET_EINT_CUR_DEB MT6351_ACCDET_CON22 +#define ACCDET_RSV_CON0 MT6351_ACCDET_CON23 +#define ACCDET_RSV_CON1 MT6351_ACCDET_CON24 + +#define ACCDET_AUXADC_CTL MT6351_AUXADC_RQST0 +#define ACCDET_AUXADC_CTL_SET MT6351_AUXADC_RQST0_SET +#define ACCDET_AUXADC_REG MT6351_AUXADC_ADC5 +#define ACCDET_AUXADC_AUTO_SPL MT6351_AUXADC_ACCDET + +#define ACCDET_ADC_REG MT6351_AUDENC_ANA_CON11 +#define ACCDET_MICBIAS_REG MT6351_AUDENC_ANA_CON10 + +/*Register value define*/ + +#define ACCDET_AUXADC_AUTO_SET (1<<0) +#define ACCDET_DATA_READY (1<<15) +#define ACCDET_CH_REQ_EN (1<<5) +#define ACCDET_DATA_MASK (0x0FFF) + +#define ACCDET_POWER_MOD (1<<13) +#define ACCDET_MIC1_ON (1<<7) +#define ACCDET_BF_ON (1<<9) +#define ACCDET_BF_OFF (0<<9) +#define ACCDET_BF_MOD (1<<11) +#define ACCDET_INPUT_MICP (1<<3) +#define ACCDET_EINT_CON_EN (1<<11) +#define ACCDET_NEGV_DT_EN (1<<13) + +#define ACCDET_CTRL_EN (1<<0) +#define ACCDET_EINT_EN (1<<2) +#define ACCDET_NEGV_EN (1<<4) +#define ACCDET_EINT_PWM_IDLE (1<<7) +#define ACCDET_MIC_PWM_IDLE (1<<6) +#define ACCDET_VTH_PWM_IDLE (1<<5) +#define ACCDET_CMP_PWM_IDLE (1<<4) +#define ACCDET_EINT_PWM_EN (1<<3) +#define ACCDET_CMP_EN (1<<0) +#define ACCDET_VTH_EN (1<<1) +#define ACCDET_MICBIA_EN (1<<2) + + +#define ACCDET_ENABLE (1<<0) +#define ACCDET_DISABLE (0<<0) + +#define ACCDET_RESET_SET (1<<4) +#define ACCDET_RESET_CLR (1<<4) + +#define IRQ_CLR_BIT 0x100 +#define IRQ_EINT_CLR_BIT 0x400 +#define IRQ_NEGV_CLR_BIT 0x200 +#define IRQ_STATUS_BIT (1<<0) +#define EINT_IRQ_STATUS_BIT (1<<2) +#define NEGV_IRQ_STATUS_BIT (1<<1) +#define EINT_IRQ_DE_OUT 0x00 /* 1 msec */ +#define EINT_IRQ_DE_IN 0x60 /* 256 msec */ +#define EINT_PWM_THRESH 0x400 +#define EINT_IRQ_POL_HIGH (1<<15) +#define EINT_IRQ_POL_LOW (1<<15) + + +#define RG_ACCDET_IRQ_SET (1<<12) +#define RG_ACCDET_IRQ_CLR (1<<12) +#define RG_ACCDET_IRQ_STATUS_CLR (1<<12) + +#define RG_ACCDET_EINT_IRQ_SET (1<<13) +#define RG_ACCDET_EINT_IRQ_CLR (1<<13) +#define RG_ACCDET_EINT_IRQ_STATUS_CLR (1<<10) +#define RG_ACCDET_EINT_HIGH (1<<15) +#define RG_ACCDET_EINT_LOW (0<<15) + +#define RG_ACCDET_NEGV_IRQ_SET (1<<14) +#define RG_ACCDET_NEGV_IRQ_CLR (1<<14) +#define RG_ACCDET_NEGV_IRQ_STATUS_CLR (1<<14) + +#define RG_OTP_PA_ADDR_WORD_INDEX (0x03) +#define RG_OTP_PA_ACCDET_BIT_SHIFT (0x05) + +/*CLOCK*/ +#define RG_ACCDET_CLK_SET (1<<9) +#define RG_ACCDET_CLK_CLR (1<<9) + + +#define ACCDET_PWM_EN_SW (1<<15) +#define ACCDET_MIC_EN_SW (1<<14) +#define ACCDET_VTH_EN_SW (1<<13) +#define ACCDET_CMP_EN_SW (1<<12) + +#define ACCDET_SWCTRL_EN 0x07 + +#define ACCDET_IN_SW 0x10 + +#define ACCDET_DE4 0x42 /*2ms*/ +/* +#define ACCDET_PWM_SEL_CMP 0x00 +#define ACCDET_PWM_SEL_VTH 0x01 +#define ACCDET_PWM_SEL_MIC 0x10 +#define ACCDET_PWM_SEL_SW 0x11 + + + +#define ACCDET_TEST_MODE5_ACCDET_IN_GPI (1<<5) +#define ACCDET_TEST_MODE4_ACCDET_IN_SW (1<<4) +#define ACCDET_TEST_MODE3_MIC_SW (1<<3) +#define ACCDET_TEST_MODE2_VTH_SW (1<<2) +#define ACCDET_TEST_MODE1_CMP_SW (1<<1) +#define ACCDET_TEST_MODE0_GPI (1<<0) +//#define ACCDET_DEFVAL_SEL (1<<15) +*/ +/*power mode and auxadc switch on/off*/ +#define ACCDET_1V9_MODE_OFF 0x1A10 +#define ACCDET_2V8_MODE_OFF 0x5A10 +#define ACCDET_1V9_MODE_ON 0x1E10 +#define ACCDET_2V8_MODE_ON 0x5A20 +#define ACCDET_SWCTRL_IDLE_EN (0x07<<4) + +#endif diff --git a/drivers/misc/mediatek/accdet/mt6755/reg_accdet_mt6353.h b/drivers/misc/mediatek/accdet/mt6755/reg_accdet_mt6353.h new file mode 100644 index 0000000000000000000000000000000000000000..7ba1d9960b78cc5fa6928a36b87fd4c759aa97a1 --- /dev/null +++ b/drivers/misc/mediatek/accdet/mt6755/reg_accdet_mt6353.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/*Register address define*/ +#include + +#define ACCDET_BASE 0x00000000 +#define TOP_RST_ACCDET MT6353_TOP_RST_CON0 +#define TOP_RST_ACCDET_SET MT6353_TOP_RST_CON0_SET +#define TOP_RST_ACCDET_CLR MT6353_TOP_RST_CON0_CLR + +#define INT_CON_ACCDET MT6353_INT_CON0 +#define INT_CON_ACCDET_SET MT6353_INT_CON0_SET +#define INT_CON_ACCDET_CLR MT6353_INT_CON0_CLR + +#define INT_STATUS_ACCDET MT6353_INT_STATUS0 + +/*clock register*/ +#define TOP_CKPDN MT6353_CLK_CKPDN_CON0 +#define TOP_CKPDN_SET MT6353_CLK_CKPDN_CON0_SET +#define TOP_CKPDN_CLR MT6353_CLK_CKPDN_CON0_CLR + +#define ACCDET_RSV MT6353_ACCDET_CON0 +#define ACCDET_CTRL MT6353_ACCDET_CON1 +#define ACCDET_STATE_SWCTRL MT6353_ACCDET_CON2 +#define ACCDET_PWM_WIDTH MT6353_ACCDET_CON3 +#define ACCDET_PWM_THRESH MT6353_ACCDET_CON4 +#define ACCDET_EN_DELAY_NUM MT6353_ACCDET_CON5 +#define ACCDET_DEBOUNCE0 MT6353_ACCDET_CON6 +#define ACCDET_DEBOUNCE1 MT6353_ACCDET_CON7 +#define ACCDET_DEBOUNCE2 MT6353_ACCDET_CON8 +#define ACCDET_DEBOUNCE3 MT6353_ACCDET_CON9 +#define ACCDET_DEBOUNCE4 MT6353_ACCDET_CON10 +#define ACCDET_DEFAULT_STATE_RG MT6353_ACCDET_CON11 +#define ACCDET_IRQ_STS MT6353_ACCDET_CON12 +#define ACCDET_CONTROL_RG MT6353_ACCDET_CON13 +#define ACCDET_STATE_RG MT6353_ACCDET_CON14 +#define ACCDET_EINT_CTL MT6353_ACCDET_CON15 +#define ACCDET_EINT_PWM_DELAY MT6353_ACCDET_CON16 +#define ACCDET_TEST_DEBUG MT6353_ACCDET_CON17 +#define ACCDET_EINT_NV MT6353_ACCDET_CON18 +#define ACCDET_NEGV MT6353_ACCDET_CON20 +#define ACCDET_CUR_DEB MT6353_ACCDET_CON21 +#define ACCDET_EINT_CUR_DEB MT6353_ACCDET_CON22 +#define ACCDET_RSV_CON0 MT6353_ACCDET_CON23 +#define ACCDET_RSV_CON1 MT6353_ACCDET_CON24 + +#define ACCDET_AUXADC_CTL MT6353_AUXADC_RQST0 +#define ACCDET_AUXADC_CTL_SET MT6353_AUXADC_RQST0_SET +#define ACCDET_AUXADC_REG MT6353_AUXADC_ADC5 +#define ACCDET_AUXADC_AUTO_SPL MT6353_AUXADC_ACCDET + +#define ACCDET_ADC_REG MT6353_AUDENC_ANA_CON9 + +/*Register value define*/ +#define ACCDET_AUXADC_AUTO_SET (1<<0) +#define ACCDET_DATA_READY (1<<15) +#define ACCDET_CH_REQ_EN (1<<5) +#define ACCDET_DATA_MASK (0x0FFF) + +#define ACCDET_POWER_MOD (1<<13) +#define ACCDET_MIC1_ON (1<<7) +#define ACCDET_BF_ON (1<<10) +#define ACCDET_BF_OFF (0<<10) +#define ACCDET_BF_MOD (1<<11) +#define ACCDET_INPUT_MICP (1<<3) +#define ACCDET_EINT_CON_EN (1<<14) +#define ACCDET_NEGV_DT_EN (1<<13) + +#define ACCDET_CTRL_EN (1<<0) +#define ACCDET_EINT_EN (1<<2) +#define ACCDET_NEGV_EN (1<<4) +#define ACCDET_EINT_PWM_IDLE (1<<7) +#define ACCDET_MIC_PWM_IDLE (1<<6) +#define ACCDET_VTH_PWM_IDLE (1<<5) +#define ACCDET_CMP_PWM_IDLE (1<<4) +#define ACCDET_EINT_PWM_EN (1<<3) +#define ACCDET_CMP_EN (1<<0) +#define ACCDET_VTH_EN (1<<1) +#define ACCDET_MICBIA_EN (1<<2) + + +#define ACCDET_ENABLE (1<<0) +#define ACCDET_DISABLE (0<<0) + +#define ACCDET_RESET_SET (1<<4) +#define ACCDET_RESET_CLR (1<<4) + +#define IRQ_CLR_BIT 0x100 +#define IRQ_EINT_CLR_BIT 0x400 +#define IRQ_NEGV_CLR_BIT 0x200 +#define IRQ_STATUS_BIT (1<<0) +#define EINT_IRQ_STATUS_BIT (1<<2) +#define NEGV_IRQ_STATUS_BIT (1<<1) +#define EINT_IRQ_DE_OUT 0x50 +#define EINT_IRQ_DE_IN 0x60 +#define EINT_PWM_THRESH 0x400 +#define EINT_IRQ_POL_HIGH (1<<15) +#define EINT_IRQ_POL_LOW (1<<15) + + +#define RG_ACCDET_IRQ_SET (1<<12) +#define RG_ACCDET_IRQ_CLR (1<<12) +#define RG_ACCDET_IRQ_STATUS_CLR (1<<12) + +#define RG_ACCDET_EINT_IRQ_SET (1<<13) +#define RG_ACCDET_EINT_IRQ_CLR (1<<13) +#define RG_ACCDET_EINT_IRQ_STATUS_CLR (1<<10) +#define RG_ACCDET_EINT_HIGH (1<<15) +#define RG_ACCDET_EINT_LOW (0<<15) + +#define RG_ACCDET_NEGV_IRQ_SET (1<<14) +#define RG_ACCDET_NEGV_IRQ_CLR (1<<14) +#define RG_ACCDET_NEGV_IRQ_STATUS_CLR (1<<14) + +#define RG_OTP_PA_ADDR_WORD_INDEX (0x03) +#define RG_OTP_PA_ACCDET_BIT_SHIFT (0x05) + +/*CLOCK*/ +#define RG_ACCDET_CLK_SET (1<<3) +#define RG_ACCDET_CLK_CLR (1<<3) + + +#define ACCDET_PWM_EN_SW (1<<15) +#define ACCDET_MIC_EN_SW (1<<14) +#define ACCDET_VTH_EN_SW (1<<13) +#define ACCDET_CMP_EN_SW (1<<12) + +#define ACCDET_SWCTRL_EN 0x07 + +#define ACCDET_IN_SW 0x10 + +#define ACCDET_DE4 0x42 /*2ms*/ +/* +#define ACCDET_PWM_SEL_CMP 0x00 +#define ACCDET_PWM_SEL_VTH 0x01 +#define ACCDET_PWM_SEL_MIC 0x10 +#define ACCDET_PWM_SEL_SW 0x11 + + + +#define ACCDET_TEST_MODE5_ACCDET_IN_GPI (1<<5) +#define ACCDET_TEST_MODE4_ACCDET_IN_SW (1<<4) +#define ACCDET_TEST_MODE3_MIC_SW (1<<3) +#define ACCDET_TEST_MODE2_VTH_SW (1<<2) +#define ACCDET_TEST_MODE1_CMP_SW (1<<1) +#define ACCDET_TEST_MODE0_GPI (1<<0) +//#define ACCDET_DEFVAL_SEL (1<<15) +*/ +/*power mode and auxadc switch on/off*/ +#define ACCDET_1V9_MODE_OFF 0x1A10 +#define ACCDET_2V8_MODE_OFF 0x5A10 +#define ACCDET_1V9_MODE_ON 0x1E10 +#define ACCDET_2V8_MODE_ON 0x5A20 +#define ACCDET_SWCTRL_IDLE_EN (0x07<<4) diff --git a/drivers/misc/mediatek/accdet/mt6755/ts3a225e.c b/drivers/misc/mediatek/accdet/mt6755/ts3a225e.c new file mode 100644 index 0000000000000000000000000000000000000000..5a721f972b0ac74e54bc55f93c535dd5c13be36a --- /dev/null +++ b/drivers/misc/mediatek/accdet/mt6755/ts3a225e.c @@ -0,0 +1,222 @@ +/* drivers/hwmon/mt6516/amit/IQS128.c - IQS128/PS driver + * + * Author: MingHsien Hsieh + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "upmu_common.h" +/* +#include +#include +#include +*/ +#include +#include "ts3a225e.h" + +/****************************************************************************** + * configuration +*******************************************************************************/ +#define TS3A225E_DEV_NAME "TS3A225E" + +static struct i2c_client *ts3a225e_i2c_client; +static const struct i2c_device_id ts3a225e_i2c_id[] = { {"TS3A225E", 0}, {} }; +static struct i2c_board_info i2c_TS3A225E __initdata = { I2C_BOARD_INFO("TS3A225E", (0X76 >> 1)) }; + +static int ts3a225e_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + unsigned char devicve_id[1]; + + pr_warn("ts3a225e_i2c_probe\n"); + + ts3a225e_i2c_client = client; + + ts3a225e_read_byte(0x01, &devicve_id[0]); + pr_warn("ts3a225e_i2c_probe ID=%x\n", devicve_id[0]); + + return 0; +} + +static int ts3a225e_i2c_remove(struct i2c_client *client) +{ + pr_warn("TS3A225E_i2c_remove\n"); + + ts3a225e_i2c_client = NULL; + + return 0; +} + +static int ts3a225e_i2c_suspend(struct i2c_client *client, pm_message_t msg) +{ + pr_debug("TS3A225E_i2c_suspend\n"); + + return 0; +} + +static int ts3a225e_i2c_resume(struct i2c_client *client) +{ + pr_debug("TS3A225E_i2c_resume\n"); + + return 0; +} + +static struct i2c_driver ts3a225e_i2c_driver = { + .probe = ts3a225e_i2c_probe, + .remove = ts3a225e_i2c_remove, + .suspend = ts3a225e_i2c_suspend, + .resume = ts3a225e_i2c_resume, + .id_table = ts3a225e_i2c_id, + .driver = { + .name = TS3A225E_DEV_NAME, + }, +}; + +static DEFINE_MUTEX(ts3a225e_i2c_access); + +int ts3a225e_read_byte(unsigned char cmd, unsigned char *returnData) +{ + char cmd_buf[1] = { 0x00 }; + char readData = 0; + int ret = 0; + + mutex_lock(&ts3a225e_i2c_access); + + /*new_client->addr = ((new_client->addr) & I2C_MASK_FLAG) | I2C_WR_FLAG;*/ + ts3a225e_i2c_client->ext_flag = + ((ts3a225e_i2c_client->ext_flag) & I2C_MASK_FLAG) | I2C_WR_FLAG | I2C_DIRECTION_FLAG; + + cmd_buf[0] = cmd; + ret = i2c_master_send(ts3a225e_i2c_client, &cmd_buf[0], (1 << 8 | 1)); + if (ret < 0) { + /*new_client->addr = new_client->addr & I2C_MASK_FLAG;*/ + ts3a225e_i2c_client->ext_flag = 0; + + mutex_unlock(&ts3a225e_i2c_access); + return 0; + } + + readData = cmd_buf[0]; + *returnData = readData; + + /*new_client->addr = new_client->addr & I2C_MASK_FLAG;*/ + ts3a225e_i2c_client->ext_flag = 0; + + mutex_unlock(&ts3a225e_i2c_access); + return 1; +} + +int ts3a225e_write_byte(unsigned char cmd, unsigned char writeData) +{ + char write_data[2] = { 0 }; + int ret = 0; + + mutex_lock(&ts3a225e_i2c_access); + + write_data[0] = cmd; + write_data[1] = writeData; + + ts3a225e_i2c_client->ext_flag = ((ts3a225e_i2c_client->ext_flag) & I2C_MASK_FLAG) | I2C_DIRECTION_FLAG; + + ret = i2c_master_send(ts3a225e_i2c_client, write_data, 2); + if (ret < 0) { + ts3a225e_i2c_client->ext_flag = 0; + mutex_unlock(&ts3a225e_i2c_access); + return 0; + } + + ts3a225e_i2c_client->ext_flag = 0; + mutex_unlock(&ts3a225e_i2c_access); + return 1; +} + +/****************************************************************************** + * extern functions +*******************************************************************************/ +/*----------------------------------------------------------------------------*/ +static int ts3a225e_probe(struct platform_device *pdev) +{ + pr_warn("ts3a225e_probe\n"); + + if (i2c_add_driver(&ts3a225e_i2c_driver)) { + pr_err("ts3a225e add driver error\n"); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int ts3a225e_remove(struct platform_device *pdev) +{ + pr_warn("ts3a225e remove\n"); + + i2c_del_driver(&ts3a225e_i2c_driver); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static const struct of_device_id audio_switch_of_match[] = { + {.compatible = "mediatek,audio_switch",}, + {}, +}; + +static struct platform_driver ts3a225e_audio_switch_driver = { + .probe = ts3a225e_probe, + .remove = ts3a225e_remove, + .driver = { + .name = "audio_switch", + .of_match_table = audio_switch_of_match, + } +}; + +/*----------------------------------------------------------------------------*/ +static int __init ts3a225e_init(void) +{ + pr_warn("ts3a225e_init\n"); + + i2c_register_board_info(3, &i2c_TS3A225E, 1); + + if (platform_driver_register(&ts3a225e_audio_switch_driver)) { + pr_err("ts3a225e failed to register driver"); + return -ENODEV; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static void __exit ts3a225e_exit(void) +{ + pr_warn("ts3a225e_exit\n"); +} + +/*----------------------------------------------------------------------------*/ +module_init(ts3a225e_init); +module_exit(ts3a225e_exit); +/*----------------------------------------------------------------------------*/ +MODULE_AUTHOR("Dexiang Liu"); +MODULE_DESCRIPTION("TS3A225E driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/accdet/mt6755/ts3a225e.h b/drivers/misc/mediatek/accdet/mt6755/ts3a225e.h new file mode 100644 index 0000000000000000000000000000000000000000..9403e5fe6ddc13905c8002b05d50e86f390635b5 --- /dev/null +++ b/drivers/misc/mediatek/accdet/mt6755/ts3a225e.h @@ -0,0 +1,22 @@ +/* + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ +/* + * Definitions for TS3A225E Audio Switch chip. + */ +#ifndef __TS3A225E_H__ +#define __TS3A225E_H__ + +int ts3a225e_read_byte(unsigned char cmd, unsigned char *returnData); +int ts3a225e_write_byte(unsigned char cmd, unsigned char writeData); + +#endif diff --git a/drivers/misc/mediatek/auxadc/mt6755/mt_auxadc_hw.h b/drivers/misc/mediatek/auxadc/mt6755/mt_auxadc_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..e9043ab1f20477ec8b2b24056db37a906ada1ab5 --- /dev/null +++ b/drivers/misc/mediatek/auxadc/mt6755/mt_auxadc_hw.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MTK_ADC_HW_H +#define _MTK_ADC_HW_H + +#ifdef CONFIG_OF +extern void __iomem *auxadc_base; +extern void __iomem *auxadc_apmix_base; +extern void __iomem *auxadc_efuse_base; +#undef AUXADC_BASE +#undef APMIXED_BASE +#undef EFUSEC_BASE +#define AUXADC_BASE auxadc_base +#define APMIXED_BASE auxadc_apmix_base +#define EFUSEC_BASE auxadc_efuse_base +#else +#include +#endif + +#define AUXADC_CLOCK_BY_SPM + +#define EFUSE_CALI +#define ADC_GE_A_MASK 0xffc00 +#define ADC_GE_A_SHIFT 10 +#define ADC_OE_A_MASK 0x3ff00000 +#define ADC_OE_A_SHIFT 20 +#define ADC_CALI_EN_A_MASK 0x40000000 +#define ADC_CALI_EN_A_SHIFT 30 + + +#define ADC_CHANNEL_MAX 16 + +#define MT_PDN_PERI_AUXADC MT_CG_PERI_AUXADC +#define ADC_CALI_EN_A_REG (EFUSEC_BASE + 0x544) +#define AUXADC_NODE "mediatek,mt6755-auxadc" + +#define AUXADC_CON0 (AUXADC_BASE + 0x000) +#define AUXADC_CON1 (AUXADC_BASE + 0x004) +#define AUXADC_CON2 (AUXADC_BASE + 0x010) +#define AUXADC_DAT0 (AUXADC_BASE + 0x014) +#define AUXADC_TP_CMD (AUXADC_BASE + 0x005c) +#define AUXADC_TP_ADDR (AUXADC_BASE + 0x0060) +#define AUXADC_TP_CON0 (AUXADC_BASE + 0x0064) +#define AUXADC_TP_DATA0 (AUXADC_BASE + 0x0074) +#define AUXADC_DET_VOLT (AUXADC_BASE + 0x084) +#define AUXADC_DET_SEL (AUXADC_BASE + 0x088) +#define AUXADC_DET_PERIOD (AUXADC_BASE + 0x08C) +#define AUXADC_DET_DEBT (AUXADC_BASE + 0x090) + +#define PAD_AUX_XP 13 +#define PAD_AUX_YM 15 +#define TP_CMD_ADDR_X 0x0005 + +#define AUXADC_CON_RTP (APMIXED_BASE + 0x0404) + +#endif /*_MTK_ADC_HW_H*/ + diff --git a/drivers/misc/mediatek/base/power/include/spm_v2/mt_clk_id_mt6755.h b/drivers/misc/mediatek/base/power/include/spm_v2/mt_clk_id_mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..7baebdff507ec31b5d825d2bd3213dae7628a3cb --- /dev/null +++ b/drivers/misc/mediatek/base/power/include/spm_v2/mt_clk_id_mt6755.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_CLK_ID_MT6755_H__ +#define __MT_CLK_ID_MT6755_H__ + +/* The following is CODA name */ +enum mt_cg_clk_id { + MT_CG_INFRA0_MD2MD_CCIF_CG3_STA = 0, + MT_CG_INFRA0_SPI_CG_STA = 1, + MT_CG_INFRA0_MSDC0_CG_STA = 2, + MT_CG_INFRA0_MD2MD_CCIF_CG4_STA = 3, + MT_CG_INFRA0_MSDC1_CG_STA = 4, + MT_CG_INFRA0_MSDC2_CG_STA = 5, + MT_CG_INFRA0_MSDC3_CG_STA = 6, + MT_CG_INFRA0_MD2MD_CCIF_CG5_STA = 7, + MT_CG_INFRA0_GCPU_CG_STA = 8, + MT_CG_INFRA0_AUXADC_CG_STA = 10, + MT_CG_INFRA0_CPUM_CG_STA = 11, + MT_CG_INFRA0_NFI_CG_STA = 16, + MT_CG_INFRA0_NFI_ECC_cg_STA = 17, + MT_CG_INFRA0_AP_DMA_CG_STA = 18, + MT_CG_INFRA0_XIU_CG_sta = 19, + MT_CG_INFRA0_DEVICE_APC_CG_STA = 20, + MT_CG_INFRA0_XIU2AHB_CG_STA = 21, + MT_CG_INFRA0_I2C_SRAM_CG_STA = 22, + MT_CG_INFRA0_CCIF_AP_CG_STA = 23, + MT_CG_INFRA0_DEBUGSYS_CG_STA = 24, + MT_CG_INFRA0_AUDIO_CG_STA = 25, + MT_CG_INFRA0_CCIF_MD_CG_STA = 26, + MT_CG_INFRA0_DRAMC_F26M_CG_STA = 31, + + MT_CG_INFRA1_PMIC_CG_TMR_STA = 32 + 0, + MT_CG_INFRA1_PMIC_CG_AP_STA = 32 + 1, + MT_CG_INFRA1_PMIC_CG_MD_STA = 32 + 2, + MT_CG_INFRA1_PMIC_CG_CONN_STA = 32 + 3, + MT_CG_INFRA1_SCPSYS_CG_STA = 32 + 4, + MT_CG_INFRA1_SEJ_CG_STA = 32 + 5, + MT_CG_INFRA1_APXGPT_CG_STA = 32 + 6, + MT_CG_INFRA1_ICUSB_CG_STA = 32 + 8, + MT_CG_INFRA1_GCE_CG_STA = 32 + 9, + MT_CG_INFRA1_THERM_CG_STA = 32 + 10, + MT_CG_INFRA1_I2C0_CG_STA = 32 + 11, + MT_CG_INFRA1_I2C1_CG_STA = 32 + 12, + MT_CG_INFRA1_I2C2_CG_STA = 32 + 13, + MT_CG_INFRA1_I2C3_CG_STA = 32 + 14, + MT_CG_INFRA1_PWM_HCLK_CG_STA = 32 + 15, + MT_CG_INFRA1_PWM1_CG_STA = 32 + 16, + MT_CG_INFRA1_PWM2_CG_STA = 32 + 17, + MT_CG_INFRA1_PWM3_CG_STA = 32 + 18, + MT_CG_INFRA1_PWM4_CG_STA = 32 + 19, + MT_CG_INFRA1_PWM_CG_STA = 32 + 21, + MT_CG_INFRA1_UART0_CG_STA = 32 + 22, + MT_CG_INFRA1_UART1_CG_STA = 32 + 23, + MT_CG_INFRA1_UART2_CG_STA = 32 + 24, + MT_CG_INFRA1_UART3_CG_STA = 32 + 25, + MT_CG_INFRA1_MD2MD_CCIF_CG0_STA = 32 + 27, + MT_CG_INFRA1_MD2MD_CCIF_CG1_STA = 32 + 28, + MT_CG_INFRA1_MD2MD_CCIF_CG2_STA = 32 + 29, + MT_CG_INFRA1_FHCTL_CG_STA = 32 + 30, + MT_CG_INFRA1_BTIF_CG_STA = 32 + 31, + + MT_CG_INFRA2_INTX_CG_STA = 64 + 0, + MT_CG_INFRA2_SSUSB_TOP_CG_STA = 64 + 1, + MT_CG_INFRA2_DISP_PWM_CG_STA = 64 + 2, + MT_CG_INFRA2_CLDMA_BCLK_CG_STA = 64 + 3, + MT_CG_INFRA2_AUDIO_26M_BCLK_CG_STA = 64 + 4, + MT_CG_INFRA2_MODEM_TEMP_26M_BCLK_CG_STA = 64 + 5, + MT_CG_INFRA2_SPI1_CG_STA = 64 + 6, + MT_CG_INFRA2_I2C4_CG_STA = 64 + 7, + MT_CG_INFRA2_MODEM_TEMP_SHARE_CG_STA = 64 + 8, + + MT_CG_ID_DISP0_SMI_COMMON = 96 + 0, + MT_CG_ID_DISP0_SMI_LARB0 = 96 + 1, + MT_CG_ID_DISP0_CAM_MDP = 96 + 2, + MT_CG_ID_DISP0_MDP_RDMA = 96 + 3, + MT_CG_ID_DISP0_MDP_RSZ0 = 96 + 4, + MT_CG_ID_DISP0_MDP_RSZ1 = 96 + 5, + MT_CG_ID_DISP0_MDP_TDSHP = 96 + 6, + MT_CG_ID_DISP0_MDP_WDMA = 96 + 7, + MT_CG_ID_DISP0_MDP_WROT = 96 + 8, + MT_CG_ID_DISP0_FAKE_ENG = 96 + 9, + MT_CG_ID_DISP0_DISP_OVL0 = 96 + 10, + MT_CG_ID_DISP0_DISP_OVL1 = 96 + 11, + MT_CG_ID_DISP0_DISP_RDMA0 = 96 + 12, + MT_CG_ID_DISP0_DISP_RDMA1 = 96 + 13, + MT_CG_ID_DISP0_DISP_WDMA0 = 96 + 14, + MT_CG_ID_DISP0_DISP_COLOR = 96 + 15, + MT_CG_ID_DISP0_DISP_CCORR = 96 + 16, + MT_CG_ID_DISP0_DISP_AAL = 96 + 17, + MT_CG_ID_DISP0_DISP_GAMMA = 96 + 18, + MT_CG_ID_DISP0_DISP_DITHER = 96 + 19, + MT_CG_ID_DISP0_MDP_COLOR = 96 + 20, + MT_CG_ID_DISP0_DISP_UFOE_MOUT = 96 + 21, + MT_CG_ID_DISP0_DISP_WDMA1 = 96 + 22, + MT_CG_ID_DISP0_DISP_2L_OVL0 = 96 + 23, + MT_CG_ID_DISP0_DISP_2L_OVL1 = 96 + 24, + MT_CG_ID_DISP0_DISP_OVL0_MOUT = 96 + 25, + + MT_CG_IMAGE_ISP_PWR_RST_B = 128 + 0, + MT_CG_IMAGE_ISP_PWR_ISO = 128 + 1, + MT_CG_IMAGE_ISP_PWR_ON = 128 + 2, + MT_CG_IMAGE_ISP_PWR_ON_2ND = 128 + 3, + MT_CG_IMAGE_ISP_PWR_CLK_DIS = 128 + 4, + MT_CG_IMAGE_ISP_SRAM_PDN0 = 128 + 8, + MT_CG_IMAGE_ISP_SRAM_PDN1 = 128 + 9, + MT_CG_IMAGE_ISP_SRAM_PDN2 = 128 + 10, + MT_CG_IMAGE_ISP_SRAM_PDN3 = 128 + 11, + + MT_CG_MFG_PWR_RST_B = 160 + 0, + MT_CG_MFG_PWR_ISO = 160 + 1, + MT_CG_MFG_PWR_ON = 160 + 2, + MT_CG_MFG_PWR_ON_2ND = 160 + 3, + MT_CG_MFG_PWR_CLK_DIS = 160 + 4, + MT_CG_MFG_SRAM_PDN0 = 160 + 8, + MT_CG_MFG_SRAM_PDN1 = 160 + 9, + MT_CG_MFG_SRAM_PDN2 = 160 + 10, + MT_CG_MFG_SRAM_PDN3 = 160 + 11, + MT_CG_MFG_SRAM_PDN4 = 160 + 12, + MT_CG_MFG_SRAM_PDN5 = 160 + 13, + + MT_CG_ID_AUDIO_AFE = 192 + 2, /* PDN_AFE */ + MT_CG_ID_AUDIO_I2S = 192 + 6, /* PDN_I2S */ + MT_CG_ID_AUDIO_22M = 192 + 8, /* PDN_22M */ + MT_CG_ID_AUDIO_24M = 192 + 9, /* PDN_24M */ + MT_CG_ID_AUDIO_APLL2_TUNER = 192 + 18, /* PDN_APLL2_TUNER */ + MT_CG_ID_AUDIO_APLL_TUNER = 192 + 19, /* PDN_APLL_TUNER */ + MT_CG_ID_AUDIO_ADC = 192 + 24, + MT_CG_ID_AUDIO_DAC = 192 + 25, + MT_CG_ID_AUDIO_DAC_PREDIS = 192 + 26, + MT_CG_ID_AUDIO_TML = 192 + 27, + + MT_CG_VDE_PWR_RST_B = 224 + 0, + MT_CG_VDE_PWR_ISO = 224 + 1, + MT_CG_VDE_PWR_ON = 224 + 2, + MT_CG_VDE_PWR_ON_2ND = 224 + 3, + MT_CG_VDE_PWR_CLK_DIS = 224 + 4, + MT_CG_VDE_SRAM_PDN0 = 224 + 8, + MT_CG_VDE_SRAM_PDN1 = 224 + 9, + MT_CG_VDE_SRAM_PDN2 = 224 + 10, + MT_CG_VDE_SRAM_PDN3 = 224 + 11, + + MT_CG_VEN_PWR_RST_B = 256 + 0, + MT_CG_VEN_PWR_ISO = 256 + 1, + MT_CG_VEN_PWR_ON = 256 + 2, + MT_CG_VEN_PWR_ON_2ND = 256 + 3, + MT_CG_VEN_PWR_CLK_DIS = 256 + 4, + MT_CG_VEN_SRAM_PDN0 = 256 + 8, + MT_CG_VEN_SRAM_PDN1 = 256 + 9, + MT_CG_VEN_SRAM_PDN2 = 256 + 10, + MT_CG_VEN_SRAM_PDN3 = 256 + 11 +}; + +#endif /* __MT_CLK_ID_MT6755_H__ */ + diff --git a/drivers/misc/mediatek/base/power/include/spm_v2/mt_idle_mt6755.h b/drivers/misc/mediatek/base/power/include/spm_v2/mt_idle_mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..07230542254c584bd5d37d343ab7736dcd1ce0a8 --- /dev/null +++ b/drivers/misc/mediatek/base/power/include/spm_v2/mt_idle_mt6755.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_IDLE_MT6755__H__ +#define __MT_IDLE_MT6755__H__ + +#include "mt_idle_internal.h" + +enum { + UNIV_PLL = 0, + MM_PLL, + MSDC_PLL, + VENC_PLL, + NR_PLLS, +}; + +enum { + CG_INFRA0 = 0, + CG_INFRA1, + CG_INFRA2, + CG_DISP0, + CG_IMAGE, + CG_MFG, + CG_AUDIO, + CG_VDEC, + CG_VENC, + NR_GRPS, +}; + +extern bool soidle_by_pass_pg; +extern bool dpidle_by_pass_pg; + +extern void __iomem *infrasys_base; +extern void __iomem *mmsys_base; +extern void __iomem *sleepsys_base; +extern void __iomem *topcksys_base; +extern void __iomem *mfgsys_base; +extern void __iomem *imgsys_base; +extern void __iomem *vdecsys_base; +extern void __iomem *vencsys_base; +extern void __iomem *audiosys_base_in_idle; + +extern void __iomem *apmixed_base_in_idle; + +#define INFRA_REG(ofs) (infrasys_base + ofs) +#define MM_REG(ofs) (mmsys_base + ofs) +#define SPM_REG(ofs) (sleepsys_base + ofs) +#define TOPCKSYS_REG(ofs) (topcksys_base + ofs) +#define MFGSYS_REG(ofs) (mfgsys_base + ofs) +#define IMGSYS_REG(ofs) (imgsys_base + ofs) +#define VDECSYS_REG(ofs) (vdecsys_base + ofs) +#define VENCSYS_REG(ofs) (vencsys_base + ofs) +#define AUDIOSYS_REG(ofs) (audiosys_base_in_idle + ofs) + +#define APMIXEDSYS(ofs) (apmixed_base_in_idle + ofs) + +#ifdef SPM_PWR_STATUS +#undef SPM_PWR_STATUS +#endif + +#ifdef SPM_PWR_STATUS_2ND +#undef SPM_PWR_STATUS_2ND +#endif + +#define INFRA_SW_CG_0_STA INFRA_REG(0x0094) +#define INFRA_SW_CG_1_STA INFRA_REG(0x0090) +#define INFRA_SW_CG_2_STA INFRA_REG(0x00AC) +#define DISP_CG_CON0 MM_REG(0x100) +#define DISP_CG_CON1 MM_REG(0x110) + +#define AUDIO_TOP_CON0 AUDIOSYS_REG(0x0) + +#define SPM_PWR_STATUS SPM_REG(0x0180) +#define SPM_PWR_STATUS_2ND SPM_REG(0x0184) +#define SPM_ISP_PWR_CON SPM_REG(0x0308) +#define SPM_MFG_PWR_CON SPM_REG(0x0338) +#define SPM_VDE_PWR_CON SPM_REG(0x0300) +#define SPM_VEN_PWR_CON SPM_REG(0x0304) +#define SPM_DIS_PWR_CON SPM_REG(0x030c) +#define SPM_AUDIO_PWR_CON SPM_REG(0x0314) +#define SPM_MD1_PWR_CON SPM_REG(0x0320) +#define SPM_MD2_PWR_CON SPM_REG(0x0324) +#define SPM_C2K_PWR_CON SPM_REG(0x0328) +#define SPM_CONN_PWR_CON SPM_REG(0x032c) +#define SPM_MDSYS_INTF_INFRA_PWR_CON SPM_REG(0x0360) + +#define CLK_CFG_UPDATE TOPCKSYS_REG(0x004) +#define CLK_CFG_4 TOPCKSYS_REG(0x080) +#define CLK_CFG_7 TOPCKSYS_REG(0x0B0) + +#define ARMCA15PLL_BASE APMIXEDSYS(0x200) +#define ARMCA15PLL_CON0 APMIXEDSYS(0x0200) +#define ARMCA7PLL_CON0 APMIXEDSYS(0x0210) +#define MAINPLL_CON0 APMIXEDSYS(0x0220) +#define UNIVPLL_CON0 APMIXEDSYS(0x0230) +#define MMPLL_CON0 APMIXEDSYS(0x0240) +#define MSDCPLL_CON0 APMIXEDSYS(0x0250) +#define VENCPLL_CON0 APMIXEDSYS(0x0260) +#define TVDPLL_CON0 APMIXEDSYS(0x0270) +#define APLL1_CON0 APMIXEDSYS(0x02a0) +#define APLL2_CON0 APMIXEDSYS(0x02b4) + +#define MFG_CG_CON MFGSYS_REG(0x0) +#define IMG_CG_CON IMGSYS_REG(0x0) +#define VDEC_CG_CON_0 VDECSYS_REG(0x0) +#define VDEC_CG_CON_1 VDECSYS_REG(0x8) +#define VENCSYS_CG_CON VENCSYS_REG(0x0) + +#define DIS_PWR_STA_MASK BIT(3) +#define MFG_PWR_STA_MASK BIT(4) +#define ISP_PWR_STA_MASK BIT(5) +#define VDE_PWR_STA_MASK BIT(7) +#define VEN_PWR_STA_MASK BIT(21) +#define MFG_2D_PWR_STA_MASK BIT(22) +#define MFG_ASYNC_PWR_STA_MASK BIT(23) +#define AUDIO_PWR_STA_MASK BIT(24) + +#endif /* __MT_IDLE_MT6755__H__ */ + diff --git a/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_dpidle_mt6755.h b/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_dpidle_mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..1f5d4516e79163e623f56bb2c1e4aa7bbe57d392 --- /dev/null +++ b/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_dpidle_mt6755.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_SPM_DPIDLE_MT6755__H__ +#define __MT_SPM_DPIDLE_MT6755__H__ + +#include "mt_spm.h" + +#if defined(CONFIG_MICROTRUST_TEE_SUPPORT) +#define WAKE_SRC_FOR_DPIDLE \ + (WAKE_SRC_R12_KP_IRQ_B | \ + WAKE_SRC_R12_PCM_TIMER | \ + WAKE_SRC_R12_APXGPT1_EVENT_B | \ + WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B | \ + WAKE_SRC_R12_EINT_EVENT_B | \ + WAKE_SRC_R12_CONN_WDT_IRQ_B | \ + WAKE_SRC_R12_CCIF0_EVENT_B | \ + WAKE_SRC_R12_USB_CDSC_B | \ + WAKE_SRC_R12_USB_POWERDWN_B | \ + WAKE_SRC_R12_C2K_WDT_IRQ_B | \ + WAKE_SRC_R12_EINT_EVENT_SECURE_B | \ + WAKE_SRC_R12_CCIF1_EVENT_B | \ + WAKE_SRC_R12_AFE_IRQ_MCU_B | \ + WAKE_SRC_R12_SYS_CIRQ_IRQ_B | \ + WAKE_SRC_R12_MD1_WDT_B | \ + WAKE_SRC_R12_CLDMA_EVENT_B) +#else +#define WAKE_SRC_FOR_DPIDLE \ + (WAKE_SRC_R12_KP_IRQ_B | \ + WAKE_SRC_R12_PCM_TIMER | \ + WAKE_SRC_R12_APXGPT1_EVENT_B | \ + WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B | \ + WAKE_SRC_R12_EINT_EVENT_B | \ + WAKE_SRC_R12_CONN_WDT_IRQ_B | \ + WAKE_SRC_R12_CCIF0_EVENT_B | \ + WAKE_SRC_R12_USB_CDSC_B | \ + WAKE_SRC_R12_USB_POWERDWN_B | \ + WAKE_SRC_R12_C2K_WDT_IRQ_B | \ + WAKE_SRC_R12_EINT_EVENT_SECURE_B | \ + WAKE_SRC_R12_CCIF1_EVENT_B | \ + WAKE_SRC_R12_AFE_IRQ_MCU_B | \ + WAKE_SRC_R12_SYS_CIRQ_IRQ_B | \ + WAKE_SRC_R12_MD1_WDT_B | \ + WAKE_SRC_R12_CLDMA_EVENT_B | \ + WAKE_SRC_R12_SEJ_WDT_GPT_B) +#endif /* #if defined(CONFIG_MICROTRUST_TEE_SUPPORT) */ + +#endif /* __MT_SPM_DPIDLE_MT6755__H__ */ diff --git a/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_pmic_wrap_mt6755.h b/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_pmic_wrap_mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..997a33dec82ede6078650f0bb1a440b680905b40 --- /dev/null +++ b/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_pmic_wrap_mt6755.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_SPM_PMIC_WRAP_H__ +#define __MT_SPM_PMIC_WRAP_H__ +/* Phase */ +enum pmic_wrap_phase_id { + PMIC_WRAP_PHASE_NORMAL, /* as VCORE_DVFS */ + PMIC_WRAP_PHASE_SUSPEND, + PMIC_WRAP_PHASE_DEEPIDLE, + NR_PMIC_WRAP_PHASE, +}; + +/* IDX mapping */ +enum { + IDX_NM_RESERVE1, /* 0 *//* PMIC_WRAP_PHASE_NORMAL */ + IDX_NM_RESERVE2, /* 1 */ + IDX_NM_VCORE_HPM, /* 2 */ + IDX_NM_VCORE_TRANS2, /* 3 */ + IDX_NM_VCORE_TRANS1, /* 4 */ + IDX_NM_VCORE_LPM, /* 5 */ + NR_IDX_NM, +}; +enum { + IDX_SP_VSRAM_PWR_ON, /* 0 *//* PMIC_WRAP_PHASE_SUSPEND */ + IDX_SP_VSRAM_SHUTDOWN, /* 1 */ + IDX_SP_VCORE_HPM, /* 2 */ + IDX_SP_VCORE_TRANS2, /* 3 */ + IDX_SP_VCORE_TRANS1, /* 4 */ + IDX_SP_VCORE_LPM, /* 5 */ + IDX_SP_VPROC_PWR_ON = 12, /* 12 */ + IDX_SP_VPROC_SHUTDOWN, /* 13 */ + NR_IDX_SP, +}; +enum { + IDX_DI_VSRAM_NORMAL, /* 0 *//* PMIC_WRAP_PHASE_DEEPIDLE */ + IDX_DI_VSRAM_SLEEP, /* 1 */ + IDX_DI_VCORE_HPM, /* 2 */ + IDX_DI_VCORE_TRANS2, /* 3 */ + IDX_DI_VCORE_TRANS1, /* 4 */ + IDX_DI_VCORE_LPM, /* 5 */ + IDX_DI_SRCCLKEN_IN2_NORMAL, /* 6 */ + IDX_DI_SRCCLKEN_IN2_SLEEP, /* 7 */ + IDX_DI_VPROC_NORMAL = 12, /* 12 */ + IDX_DI_VPROC_SLEEP, /* 13 */ + NR_IDX_DI, +}; + +#endif /* __MT_SPM_PMIC_WRAP_H__ */ diff --git a/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_reg_mt6755.h b/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_reg_mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..9055cbe98b6044ae39c4a43a48e786f20d2d8699 --- /dev/null +++ b/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_reg_mt6755.h @@ -0,0 +1,1088 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/**************************************************************** +* Auto generated by DE, please DO NOT modify this file directly. +*****************************************************************/ + +#ifndef _MT_SPM_REG_ +#define _MT_SPM_REG_ + +#include "sleep_def.h" +#include "pcm_def.h" + +/************************************** + * Define and Declare + **************************************/ + +#define POWERON_CONFIG_EN (SPM_BASE + 0x000) +#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004) +#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008) +#define SPM_CLK_CON (SPM_BASE + 0x00C) +#define SPM_CLK_SETTLE (SPM_BASE + 0x010) +#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014) +#define PCM_CON0 (SPM_BASE + 0x018) +#define PCM_CON1 (SPM_BASE + 0x01C) +#define PCM_IM_PTR (SPM_BASE + 0x020) +#define PCM_IM_LEN (SPM_BASE + 0x024) +#define PCM_REG_DATA_INI (SPM_BASE + 0x028) +#define PCM_PWR_IO_EN (SPM_BASE + 0x02C) +#define PCM_TIMER_VAL (SPM_BASE + 0x030) +#define PCM_WDT_VAL (SPM_BASE + 0x034) +#define PCM_IM_HOST_RW_PTR (SPM_BASE + 0x038) +#define PCM_IM_HOST_RW_DAT (SPM_BASE + 0x03C) +#define PCM_EVENT_VECTOR0 (SPM_BASE + 0x040) +#define PCM_EVENT_VECTOR1 (SPM_BASE + 0x044) +#define PCM_EVENT_VECTOR2 (SPM_BASE + 0x048) +#define PCM_EVENT_VECTOR3 (SPM_BASE + 0x04C) +#define PCM_EVENT_VECTOR4 (SPM_BASE + 0x050) +#define PCM_EVENT_VECTOR5 (SPM_BASE + 0x054) +#define PCM_EVENT_VECTOR6 (SPM_BASE + 0x058) +#define PCM_EVENT_VECTOR7 (SPM_BASE + 0x05C) +#define PCM_EVENT_VECTOR8 (SPM_BASE + 0x060) +#define PCM_EVENT_VECTOR9 (SPM_BASE + 0x064) +#define PCM_EVENT_VECTOR10 (SPM_BASE + 0x068) +#define PCM_EVENT_VECTOR11 (SPM_BASE + 0x06C) +#define PCM_EVENT_VECTOR12 (SPM_BASE + 0x070) +#define PCM_EVENT_VECTOR13 (SPM_BASE + 0x074) +#define PCM_EVENT_VECTOR14 (SPM_BASE + 0x078) +#define PCM_EVENT_VECTOR15 (SPM_BASE + 0x07C) +#define PCM_EVENT_VECTOR_EN (SPM_BASE + 0x080) +#define SPM_SW_INT_SET (SPM_BASE + 0x090) +#define SPM_SW_INT_CLEAR (SPM_BASE + 0x094) +#define SPM_SCP_MAILBOX (SPM_BASE + 0x098) +#define SPM_SCP_IRQ (SPM_BASE + 0x09C) +#define SPM_TWAM_CON (SPM_BASE + 0x0A0) +#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x0A4) +#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x0A8) +#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x0B0) +#define SPM_IRQ_MASK (SPM_BASE + 0x0B4) +#define SPM_SRC_REQ (SPM_BASE + 0x0B8) +#define SPM_SRC_MASK (SPM_BASE + 0x0BC) +#define SPM_SRC2_MASK (SPM_BASE + 0x0C0) +#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x0C4) +#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0C8) +#define SCP_CLK_CON (SPM_BASE + 0x0D0) +#define PCM_DEBUG_CON (SPM_BASE + 0x0D4) +#define PCM_REG0_DATA (SPM_BASE + 0x100) +#define PCM_REG1_DATA (SPM_BASE + 0x104) +#define PCM_REG2_DATA (SPM_BASE + 0x108) +#define PCM_REG3_DATA (SPM_BASE + 0x10C) +#define PCM_REG4_DATA (SPM_BASE + 0x110) +#define PCM_REG5_DATA (SPM_BASE + 0x114) +#define PCM_REG6_DATA (SPM_BASE + 0x118) +#define PCM_REG7_DATA (SPM_BASE + 0x11C) +#define PCM_REG8_DATA (SPM_BASE + 0x120) +#define PCM_REG9_DATA (SPM_BASE + 0x124) +#define PCM_REG10_DATA (SPM_BASE + 0x128) +#define PCM_REG11_DATA (SPM_BASE + 0x12C) +#define PCM_REG12_DATA (SPM_BASE + 0x130) +#define PCM_REG13_DATA (SPM_BASE + 0x134) +#define PCM_REG14_DATA (SPM_BASE + 0x138) +#define PCM_REG15_DATA (SPM_BASE + 0x13C) +#define PCM_REG12_MASK_B_STA (SPM_BASE + 0x140) +#define PCM_REG12_EXT_DATA (SPM_BASE + 0x144) +#define PCM_REG12_EXT_MASK_B_STA (SPM_BASE + 0x148) +#define PCM_EVENT_REG_STA (SPM_BASE + 0x14C) +#define PCM_TIMER_OUT (SPM_BASE + 0x150) +#define PCM_WDT_OUT (SPM_BASE + 0x154) +#define SPM_IRQ_STA (SPM_BASE + 0x158) +#define SPM_WAKEUP_STA (SPM_BASE + 0x15C) +#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x160) +#define SPM_WAKEUP_MISC (SPM_BASE + 0x164) +#define BUS_PROTECT_RDY (SPM_BASE + 0x168) +#define BUS_PROTECT2_RDY (SPM_BASE + 0x16C) +#define SUBSYS_IDLE_STA (SPM_BASE + 0x170) +#define CPU_IDLE_STA (SPM_BASE + 0x174) +#define PCM_FSM_STA (SPM_BASE + 0x178) +#define PWR_STATUS (SPM_BASE + 0x180) +#define PWR_STATUS_2ND (SPM_BASE + 0x184) +#define CPU_PWR_STATUS (SPM_BASE + 0x188) +#define CPU_PWR_STATUS_2ND (SPM_BASE + 0x18C) +#define PCM_WDT_LATCH_0 (SPM_BASE + 0x190) +#define PCM_WDT_LATCH_1 (SPM_BASE + 0x194) +#define PCM_WDT_LATCH_2 (SPM_BASE + 0x198) +#define DRAMC_DBG_LATCH (SPM_BASE + 0x19C) +#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1A0) +#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1A4) +#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1A8) +#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1AC) +#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1B0) +#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1B4) +#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1B8) +#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1BC) +#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1C0) +#define PCM_WDT_LATCH_3 (SPM_BASE + 0x1C4) +#define SPM_SRC_RDY_STA (SPM_BASE + 0x1D0) +#define MCU_PWR_CON (SPM_BASE + 0x200) +#define MP0_CPUTOP_PWR_CON (SPM_BASE + 0x204) +#define MP0_CPU0_PWR_CON (SPM_BASE + 0x208) +#define MP0_CPU1_PWR_CON (SPM_BASE + 0x20C) +#define MP0_CPU2_PWR_CON (SPM_BASE + 0x210) +#define MP0_CPU3_PWR_CON (SPM_BASE + 0x214) +#define MP1_CPUTOP_PWR_CON (SPM_BASE + 0x218) +#define MP1_CPU0_PWR_CON (SPM_BASE + 0x21C) +#define MP1_CPU1_PWR_CON (SPM_BASE + 0x220) +#define MP1_CPU2_PWR_CON (SPM_BASE + 0x224) +#define MP1_CPU3_PWR_CON (SPM_BASE + 0x228) +#define MP0_CPUTOP_L2_PDN (SPM_BASE + 0x240) +#define MP0_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x244) +#define MP0_CPU0_L1_PDN (SPM_BASE + 0x248) +#define MP0_CPU1_L1_PDN (SPM_BASE + 0x24C) +#define MP0_CPU2_L1_PDN (SPM_BASE + 0x250) +#define MP0_CPU3_L1_PDN (SPM_BASE + 0x254) +#define MP1_CPUTOP_L2_PDN (SPM_BASE + 0x258) +#define MP1_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x25C) +#define MP1_CPU0_L1_PDN (SPM_BASE + 0x260) +#define MP1_CPU1_L1_PDN (SPM_BASE + 0x264) +#define MP1_CPU2_L1_PDN (SPM_BASE + 0x268) +#define MP1_CPU3_L1_PDN (SPM_BASE + 0x26C) +#define CPU_EXT_BUCK_ISO (SPM_BASE + 0x290) +#define DUMMY1_PWR_CON (SPM_BASE + 0x2B0) +#define VDE_PWR_CON (SPM_BASE + 0x300) +#define VEN_PWR_CON (SPM_BASE + 0x304) +#define ISP_PWR_CON (SPM_BASE + 0x308) +#define DIS_PWR_CON (SPM_BASE + 0x30C) +#define MJC_PWR_CON (SPM_BASE + 0x310) +#define AUDIO_PWR_CON (SPM_BASE + 0x314) +#define IFR_PWR_CON (SPM_BASE + 0x318) +#define DPY_PWR_CON (SPM_BASE + 0x31C) +#define MD1_PWR_CON (SPM_BASE + 0x320) +#define MD2_PWR_CON (SPM_BASE + 0x324) +#define C2K_PWR_CON (SPM_BASE + 0x328) +#define CONN_PWR_CON (SPM_BASE + 0x32C) +#define VCOREPDN_PWR_CON (SPM_BASE + 0x330) +#define MFG_ASYNC_PWR_CON (SPM_BASE + 0x334) +#define MFG_PWR_CON (SPM_BASE + 0x338) +#define SYSRAM_CON (SPM_BASE + 0x350) +#define SYSROM_CON (SPM_BASE + 0x354) +#define SCP_SRAM_CON (SPM_BASE + 0x358) +#define GCPU_SRAM_CON (SPM_BASE + 0x35C) +#define MDSYS_INTF_INFRA_PWR_CON (SPM_BASE + 0x360) +#define MDSYS_INTF_MD1_PWR_CON (SPM_BASE + 0x364) +#define MDSYS_INTF_C2K_PWR_CON (SPM_BASE + 0x368) +#define BSI_TOP_SRAM_CON (SPM_BASE + 0x370) +#define DVFSP_SRAM_CON (SPM_BASE + 0x374) +#define MD_EXT_BUCK_ISO (SPM_BASE + 0x390) +#define DUMMY2_PWR_CON (SPM_BASE + 0x3B0) +#define SPM_DVFS_CON (SPM_BASE + 0x400) +#define SPM_MDBSI_CON (SPM_BASE + 0x404) +#define SPM_MAS_PAUSE_MASK_B (SPM_BASE + 0x408) +#define SPM_MAS_PAUSE2_MASK_B (SPM_BASE + 0x40C) +#define SPM_BSI_GEN (SPM_BASE + 0x410) +#define SPM_BSI_EN_SR (SPM_BASE + 0x414) +#define SPM_BSI_CLK_SR (SPM_BASE + 0x418) +#define SPM_BSI_D0_SR (SPM_BASE + 0x41C) +#define SPM_BSI_D1_SR (SPM_BASE + 0x420) +#define SPM_BSI_D2_SR (SPM_BASE + 0x424) +#define SPM_AP_SEMA (SPM_BASE + 0x428) +#define SPM_SPM_SEMA (SPM_BASE + 0x42C) +#define AP2MD_CROSS_TRIGGER (SPM_BASE + 0x430) +#define AP_MDSRC_REQ (SPM_BASE + 0x434) +#define SPM2MD_DVFS_CON (SPM_BASE + 0x438) +#define MD2SPM_DVFS_CON (SPM_BASE + 0x43C) +#define DRAMC_DPY_CLK_SW_CON (SPM_BASE + 0x440) +#define DPY_LP_CON (SPM_BASE + 0x444) +#define CPU_DVFS_REQ (SPM_BASE + 0x448) +#define SPM_PLL_CON (SPM_BASE + 0x44C) +#define SPM_EMI_BW_MODE (SPM_BASE + 0x450) +#define AP2MD_PEER_WAKEUP (SPM_BASE + 0x454) +#ifdef ULPOSC_CON +#undef ULPOSC_CON +#define ULPOSC_CON (SPM_BASE + 0x458) +#endif +#define MP0_CPU0_IRQ_MASK (SPM_BASE + 0x500) +#define MP0_CPU1_IRQ_MASK (SPM_BASE + 0x504) +#define MP0_CPU2_IRQ_MASK (SPM_BASE + 0x508) +#define MP0_CPU3_IRQ_MASK (SPM_BASE + 0x50C) +#define MP1_CPU0_IRQ_MASK (SPM_BASE + 0x510) +#define MP1_CPU1_IRQ_MASK (SPM_BASE + 0x514) +#define MP1_CPU2_IRQ_MASK (SPM_BASE + 0x518) +#define MP1_CPU3_IRQ_MASK (SPM_BASE + 0x51C) +#define MP0_CPU0_WFI_EN (SPM_BASE + 0x530) +#define MP0_CPU1_WFI_EN (SPM_BASE + 0x534) +#define MP0_CPU2_WFI_EN (SPM_BASE + 0x538) +#define MP0_CPU3_WFI_EN (SPM_BASE + 0x53C) +#define MP1_CPU0_WFI_EN (SPM_BASE + 0x540) +#define MP1_CPU1_WFI_EN (SPM_BASE + 0x544) +#define MP1_CPU2_WFI_EN (SPM_BASE + 0x548) +#define MP1_CPU3_WFI_EN (SPM_BASE + 0x54C) +#define CPU_PTPOD2_CON (SPM_BASE + 0x560) +#define SPM_SW_FLAG (SPM_BASE + 0x600) +#define SPM_SW_DEBUG (SPM_BASE + 0x604) +#define SPM_SW_RSV_0 (SPM_BASE + 0x608) +#define SPM_SW_RSV_1 (SPM_BASE + 0x60C) +#define SPM_SW_RSV_2 (SPM_BASE + 0x610) +#define SPM_SW_RSV_3 (SPM_BASE + 0x614) +#define SPM_SW_RSV_4 (SPM_BASE + 0x618) +#define SPM_SW_RSV_5 (SPM_BASE + 0x61C) +#define SPM_RSV_CON (SPM_BASE + 0x620) +#define SPM_RSV_STA (SPM_BASE + 0x624) +#define SPM_PASR_DPD_0 (SPM_BASE + 0x630) +#define SPM_PASR_DPD_1 (SPM_BASE + 0x634) +#define SPM_PASR_DPD_2 (SPM_BASE + 0x638) +#define SPM_PASR_DPD_3 (SPM_BASE + 0x63C) +#define SPM_INFRA_MISC (SPM_INFRACFG_AO_BASE + 0xf0c) +#define MD_SRC_REQ_BIT 0 +/* POWERON_CONFIG_EN (0x10006000+0x000) */ +#define BCLK_CG_EN_LSB (1U << 0) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_POWER_ON_VAL0 (0x10006000+0x004) */ +#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */ +/* SPM_POWER_ON_VAL1 (0x10006000+0x008) */ +#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */ +/* SPM_CLK_CON (0x10006000+0x00C) */ +#define SYSCLK0_EN_CTRL_LSB (1U << 0) /* 2b */ +#define SYSCLK1_EN_CTRL_LSB (1U << 2) /* 2b */ +#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */ +#define SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */ +#define EXT_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */ +#define CXO32K_REMOVE_EN_MD1_LSB (1U << 9) /* 1b */ +#define CXO32K_REMOVE_EN_MD2_LSB (1U << 10) /* 1b */ +#define CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */ +#define CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */ +#define SRCLKEN0_EN_LSB (1U << 13) /* 1b */ +#define SRCLKEN1_EN_LSB (1U << 14) /* 1b */ +#define SCP_DCM_EN_LSB (1U << 15) /* 1b */ +#define SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 7b */ +#define SYSCLK1_SRC_MASK_B_LSB (1U << 23) /* 7b */ +/* SPM_CLK_SETTLE (0x10006000+0x010) */ +#define SYSCLK_SETTLE_LSB (1U << 0) /* 8b */ +/* SPM_AP_STANDBY_CON (0x10006000+0x014) */ +#define WFI_OP_LSB (1U << 0) /* 1b */ +#define MP0_CPUTOP_IDLE_MASK_LSB (1U << 1) /* 1b */ +#define MP1_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */ +#define MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */ +#define MM_MASK_B_LSB (1U << 16) /* 2b */ +#define MD_DDR_EN_DBC_EN_LSB (1U << 18) /* 1b */ +#define MD_MASK_B_LSB (1U << 19) /* 2b */ +#define SCP_MASK_B_LSB (1U << 21) /* 1b */ +#define LTE_MASK_B_LSB (1U << 22) /* 1b */ +#define SRCCLKENI_MASK_B_LSB (1U << 23) /* 1b */ +#define MD_APSRC_1_SEL_LSB (1U << 24) /* 1b */ +#define MD_APSRC_0_SEL_LSB (1U << 25) /* 1b */ +#define CONN_MASK_B_LSB (1U << 26) /* 1b */ +#define CONN_APSRC_SEL_LSB (1U << 27) /* 1b */ +/* PCM_CON0 (0x10006000+0x018) */ +#define PCM_KICK_L_LSB (1U << 0) /* 1b */ +#define IM_KICK_L_LSB (1U << 1) /* 1b */ +#define PCM_CK_EN_LSB (1U << 2) /* 1b */ +#define EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */ +#define IM_AUTO_PDN_EN_LSB (1U << 4) /* 1b */ +#define PCM_SW_RESET_LSB (1U << 15) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* PCM_CON1 (0x10006000+0x01C) */ +#define IM_SLAVE_LSB (1U << 0) /* 1b */ +#define IM_SLEEP_LSB (1U << 1) /* 1b */ +#define MIF_APBEN_LSB (1U << 3) /* 1b */ +#define IM_PDN_LSB (1U << 4) /* 1b */ +#define PCM_TIMER_EN_LSB (1U << 5) /* 1b */ +#define IM_NONRP_EN_LSB (1U << 6) /* 1b */ +#define DIS_MIF_PROT_LSB (1U << 7) /* 1b */ +#define PCM_WDT_EN_LSB (1U << 8) /* 1b */ +#define PCM_WDT_WAKE_MODE_LSB (1U << 9) /* 1b */ +#define SPM_SRAM_SLEEP_B_LSB (1U << 10) /* 1b */ +#define SPM_SRAM_ISOINT_B_LSB (1U << 11) /* 1b */ +#define EVENT_LOCK_EN_LSB (1U << 12) /* 1b */ +#define SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */ +#define SCP_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* PCM_IM_PTR (0x10006000+0x020) */ +#define PCM_IM_PTR_LSB (1U << 0) /* 32b */ +/* PCM_IM_LEN (0x10006000+0x024) */ +#define PCM_IM_LEN_LSB (1U << 0) /* 12b */ +/* PCM_REG_DATA_INI (0x10006000+0x028) */ +#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */ +/* PCM_PWR_IO_EN (0x10006000+0x02C) */ +#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */ +#define PCM_RF_SYNC_EN_LSB (1U << 16) /* 8b */ +/* PCM_TIMER_VAL (0x10006000+0x030) */ +#define PCM_TIMER_VAL_LSB (1U << 0) /* 32b */ +/* PCM_WDT_VAL (0x10006000+0x034) */ +#define PCM_WDT_VAL_LSB (1U << 0) /* 32b */ +/* PCM_IM_HOST_RW_PTR (0x10006000+0x038) */ +#define PCM_IM_HOST_RW_PTR_LSB (1U << 0) /* 11b */ +#define PCM_IM_HOST_W_EN_LSB (1U << 30) /* 1b */ +#define PCM_IM_HOST_EN_LSB (1U << 31) /* 1b */ +/* PCM_IM_HOST_RW_DAT (0x10006000+0x03C) */ +#define PCM_IM_HOST_RW_DAT_LSB (1U << 0) /* 32b */ +/* PCM_EVENT_VECTOR0 (0x10006000+0x040) */ +#define PCM_EVENT_VECTOR_0_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_0_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_0_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_0_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR1 (0x10006000+0x044) */ +#define PCM_EVENT_VECTOR_1_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_1_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_1_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_1_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR2 (0x10006000+0x048) */ +#define PCM_EVENT_VECTOR_2_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_2_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_2_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_2_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR3 (0x10006000+0x04C) */ +#define PCM_EVENT_VECTOR_3_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_3_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_3_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_3_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR4 (0x10006000+0x050) */ +#define PCM_EVENT_VECTOR_4_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_4_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_4_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_4_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR5 (0x10006000+0x054) */ +#define PCM_EVENT_VECTOR_5_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_5_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_5_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_5_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR6 (0x10006000+0x058) */ +#define PCM_EVENT_VECTOR_6_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_6_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_6_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_6_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR7 (0x10006000+0x05C) */ +#define PCM_EVENT_VECTOR_7_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_7_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_7_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_7_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR8 (0x10006000+0x060) */ +#define PCM_EVENT_VECTOR_8_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_8_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_8_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_8_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR9 (0x10006000+0x064) */ +#define PCM_EVENT_VECTOR_9_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_9_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_9_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_9_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR10 (0x10006000+0x068) */ +#define PCM_EVENT_VECTOR_10_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_10_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_10_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_10_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR11 (0x10006000+0x06C) */ +#define PCM_EVENT_VECTOR_11_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_11_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_11_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_11_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR12 (0x10006000+0x070) */ +#define PCM_EVENT_VECTOR_12_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_12_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_12_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_12_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR13 (0x10006000+0x074) */ +#define PCM_EVENT_VECTOR_13_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_13_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_13_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_13_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR14 (0x10006000+0x078) */ +#define PCM_EVENT_VECTOR_14_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_14_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_14_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_14_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR15 (0x10006000+0x07C) */ +#define PCM_EVENT_VECTOR_15_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_15_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_15_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_15_LSB (1U << 16) /* 10b */ +/* PCM_EVENT_VECTOR_EN (0x10006000+0x080) */ +#define PCM_EVENT_VECTOR_EN_LSB (1U << 0) /* 16b */ +/* SPM_SW_INT_SET (0x10006000+0x090) */ +#define SPM_SW_INT_SET_LSB (1U << 0) /* 10b */ +/* SPM_SW_INT_CLEAR (0x10006000+0x094) */ +#define SPM_SW_INT_CLEAR_LSB (1U << 0) /* 10b */ +/* SPM_SCP_MAILBOX (0x10006000+0x098) */ +#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */ +/* SPM_SCP_IRQ (0x10006000+0x09C) */ +#define SPM_SCP_IRQ_LSB (1U << 0) /* 1b */ +#define SPM_SCP_IRQ_SEL_LSB (1U << 4) /* 1b */ +/* SPM_TWAM_CON (0x10006000+0x0A0) */ +#define TWAM_ENABLE_LSB (1U << 0) /* 1b */ +#define TWAM_SPEED_MODE_ENABLE_LSB (1U << 1) /* 1b */ +#define TWAM_SW_RST_LSB (1U << 2) /* 1b */ +#define TWAM_MON_TYPE0_LSB (1U << 4) /* 2b */ +#define TWAM_MON_TYPE1_LSB (1U << 6) /* 2b */ +#define TWAM_MON_TYPE2_LSB (1U << 8) /* 2b */ +#define TWAM_MON_TYPE3_LSB (1U << 10) /* 2b */ +#define TWAM_SIGNAL_SEL0_LSB (1U << 12) /* 5b */ +#define TWAM_SIGNAL_SEL1_LSB (1U << 17) /* 5b */ +#define TWAM_SIGNAL_SEL2_LSB (1U << 22) /* 5b */ +#define TWAM_SIGNAL_SEL3_LSB (1U << 27) /* 5b */ +/* SPM_TWAM_WINDOW_LEN (0x10006000+0x0A4) */ +#define TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_IDLE_SEL (0x10006000+0x0A8) */ +#define TWAM_IDLE_SEL_LSB (1U << 0) /* 5b */ +/* SPM_CPU_WAKEUP_EVENT (0x10006000+0x0B0) */ +#define SPM_CPU_WAKEUP_EVENT_LSB (1U << 0) /* 1b */ +/* SPM_IRQ_MASK (0x10006000+0x0B4) */ +#define SPM_TWAM_IRQ_MASK_LSB (1U << 2) /* 1b */ +#define PCM_IRQ_ROOT_MASK_LSB (1U << 3) /* 1b */ +#define SPM_IRQ_MASK_LSB (1U << 8) /* 10b */ +/* SPM_SRC_REQ (0x10006000+0x0B8) */ +#define SPM_APSRC_REQ_LSB (1U << 0) /* 1b */ +#define SPM_F26M_REQ_LSB (1U << 1) /* 1b */ +#define SPM_LTE_REQ_LSB (1U << 2) /* 1b */ +#define SPM_INFRA_REQ_LSB (1U << 3) /* 1b */ +#define SPM_VRF18_REQ_LSB (1U << 4) /* 1b */ +#define SPM_DVFS_REQ_LSB (1U << 5) /* 1b */ +#define SPM_DVFS_FORCE_DOWN_LSB (1U << 6) /* 1b */ +#define SPM_DDREN_REQ_LSB (1U << 7) /* 1b */ +#define SPM_RSV_SRC_REQ_LSB (1U << 8) /* 3b */ +#define CPU_MD_DVFS_SOP_FORCE_ON_LSB (1U << 16) /* 1b */ +/* SPM_SRC_MASK (0x10006000+0x0BC) */ +#define CSYSPWREQ_MASK_LSB (1U << 0) /* 1b */ +#define CCIF0_MD_EVENT_MASK_B_LSB (1U << 1) /* 1b */ +#define CCIF0_AP_EVENT_MASK_B_LSB (1U << 2) /* 1b */ +#define CCIF1_MD_EVENT_MASK_B_LSB (1U << 3) /* 1b */ +#define CCIF1_AP_EVENT_MASK_B_LSB (1U << 4) /* 1b */ +#define CCIFMD_MD1_EVENT_MASK_B_LSB (1U << 5) /* 1b */ +#define CCIFMD_MD2_EVENT_MASK_B_LSB (1U << 6) /* 1b */ +#define DSI0_VSYNC_MASK_B_LSB (1U << 7) /* 1b */ +#define DSI1_VSYNC_MASK_B_LSB (1U << 8) /* 1b */ +#define DPI_VSYNC_MASK_B_LSB (1U << 9) /* 1b */ +#define ISP0_VSYNC_MASK_B_LSB (1U << 10) /* 1b */ +#define ISP1_VSYNC_MASK_B_LSB (1U << 11) /* 1b */ +#define MD_SRCCLKENA_0_INFRA_MASK_B_LSB (1U << 12) /* 1b */ +#define MD_SRCCLKENA_1_INFRA_MASK_B_LSB (1U << 13) /* 1b */ +#define CONN_SRCCLKENA_INFRA_MASK_B_LSB (1U << 14) /* 1b */ +#define MD32_SRCCLKENA_INFRA_MASK_B_LSB (1U << 15) /* 1b */ +#define SRCCLKENI_INFRA_MASK_B_LSB (1U << 16) /* 1b */ +#define MD_APSRC_REQ_0_INFRA_MASK_B_LSB (1U << 17) /* 1b */ +#define MD_APSRC_REQ_1_INFRA_MASK_B_LSB (1U << 18) /* 1b */ +#define CONN_APSRCREQ_INFRA_MASK_B_LSB (1U << 19) /* 1b */ +#define MD32_APSRCREQ_INFRA_MASK_B_LSB (1U << 20) /* 1b */ +#define MD_DDR_EN_0_MASK_B_LSB (1U << 21) /* 1b */ +#define MD_DDR_EN_1_MASK_B_LSB (1U << 22) /* 1b */ +#define MD_VRF18_REQ_0_MASK_B_LSB (1U << 23) /* 1b */ +#define MD_VRF18_REQ_1_MASK_B_LSB (1U << 24) /* 1b */ +#define MD1_DVFS_REQ_MASK_LSB (1U << 25) /* 2b */ +#define CPU_DVFS_REQ_MASK_LSB (1U << 27) /* 1b */ +#define EMI_BW_DVFS_REQ_MASK_LSB (1U << 28) /* 1b */ +#define MD_SRCCLKENA_0_DVFS_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define MD_SRCCLKENA_1_DVFS_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define CONN_SRCCLKENA_DVFS_REQ_MASK_B_LSB (1U << 31) /* 1b */ +/* SPM_SRC2_MASK (0x10006000+0x0C0) */ +#define DVFS_HALT_MASK_B_LSB (1U << 0) /* 5b */ +#define VDEC_REQ_MASK_B_LSB (1U << 6) /* 1b */ +#define GCE_REQ_MASK_B_LSB (1U << 7) /* 1b */ +#define CPU_MD_DVFS_REQ_MERGE_MASK_B_LSB (1U << 8) /* 1b */ +#define MD_DDR_EN_DVFS_HALT_MASK_B_LSB (1U << 9) /* 2b */ +#define DSI0_VSYNC_DVFS_HALT_MASK_B_LSB (1U << 11) /* 1b */ +#define DSI1_VSYNC_DVFS_HALT_MASK_B_LSB (1U << 12) /* 1b */ +#define DPI_VSYNC_DVFS_HALT_MASK_B_LSB (1U << 13) /* 1b */ +#define ISP0_VSYNC_DVFS_HALT_MASK_B_LSB (1U << 14) /* 1b */ +#define ISP1_VSYNC_DVFS_HALT_MASK_B_LSB (1U << 15) /* 1b */ +#define CONN_DDR_EN_MASK_B_LSB (1U << 16) /* 1b */ +#define DISP_REQ_MASK_B_LSB (1U << 17) /* 1b */ +#define DISP1_REQ_MASK_B_LSB (1U << 18) /* 1b */ +#define MFG_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define C2K_PS_RCCIF_WAKE_MASK_B_LSB (1U << 20) /* 1b */ +#define C2K_L1_RCCIF_WAKE_MASK_B_LSB (1U << 21) /* 1b */ +#define PS_C2K_RCCIF_WAKE_MASK_B_LSB (1U << 22) /* 1b */ +#define L1_C2K_RCCIF_WAKE_MASK_B_LSB (1U << 23) /* 1b */ +#define SDIO_ON_DVFS_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define EMI_BOOST_DVFS_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define CPU_MD_EMI_DVFS_REQ_PROT_DIS_LSB (1U << 26) /* 1b */ +/* SPM_WAKEUP_EVENT_MASK (0x10006000+0x0C4) */ +#define SPM_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000+0x0C8) */ +#define SPM_WAKEUP_EVENT_EXT_MASK_LSB (1U << 0) /* 32b */ +/* SCP_CLK_CON (0x10006000+0x0D0) */ +#define SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */ +/* PCM_DEBUG_CON (0x10006000+0x0D4) */ +#define PCM_DEBUG_OUT_ENABLE_LSB (1U << 0) /* 1b */ +/* PCM_REG0_DATA (0x10006000+0x100) */ +#define PCM_REG0_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG1_DATA (0x10006000+0x104) */ +#define PCM_REG1_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG2_DATA (0x10006000+0x108) */ +#define PCM_REG2_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG3_DATA (0x10006000+0x10C) */ +#define PCM_REG3_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG4_DATA (0x10006000+0x110) */ +#define PCM_REG4_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG5_DATA (0x10006000+0x114) */ +#define PCM_REG5_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG6_DATA (0x10006000+0x118) */ +#define PCM_REG6_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG7_DATA (0x10006000+0x11C) */ +#define PCM_REG7_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG8_DATA (0x10006000+0x120) */ +#define PCM_REG8_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG9_DATA (0x10006000+0x124) */ +#define PCM_REG9_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG10_DATA (0x10006000+0x128) */ +#define PCM_REG10_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG11_DATA (0x10006000+0x12C) */ +#define PCM_REG11_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG12_DATA (0x10006000+0x130) */ +#define PCM_REG12_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG13_DATA (0x10006000+0x134) */ +#define PCM_REG13_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG14_DATA (0x10006000+0x138) */ +#define PCM_REG14_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG15_DATA (0x10006000+0x13C) */ +#define PCM_REG15_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG12_MASK_B_STA (0x10006000+0x140) */ +#define PCM_REG12_MASK_B_STA_LSB (1U << 0) /* 32b */ +/* PCM_REG12_EXT_DATA (0x10006000+0x144) */ +#define PCM_REG12_EXT_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG12_EXT_MASK_B_STA (0x10006000+0x148) */ +#define PCM_REG12_EXT_MASK_B_STA_LSB (1U << 0) /* 32b */ +/* PCM_EVENT_REG_STA (0x10006000+0x14C) */ +#define PCM_EVENT_REG_STA_LSB (1U << 0) /* 32b */ +/* PCM_TIMER_OUT (0x10006000+0x150) */ +#define PCM_TIMER_OUT_LSB (1U << 0) /* 32b */ +/* PCM_WDT_OUT (0x10006000+0x154) */ +#define PCM_WDT_OUT_LSB (1U << 0) /* 32b */ +/* SPM_IRQ_STA (0x10006000+0x158) */ +#define TWAM_IRQ_LSB (1U << 2) /* 1b */ +#define PCM_IRQ_LSB (1U << 3) /* 1b */ +#define SPM_SWINT_LSB (1U << 4) /* 10b */ +/* SPM_WAKEUP_STA (0x10006000+0x15C) */ +#define SPM_WAKEUP_EVENT_STA_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_EXT_STA (0x10006000+0x160) */ +#define SPM_WAKEUP_EVENT_EXT_STA_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_MISC (0x10006000+0x164) */ +#define SPM_WAKEUP_EVENT_MISC_LSB (1U << 0) /* 30b */ +#define SPM_PWRAP_IRQ_ACK_LSB (1U << 30) /* 1b */ +#define SPM_PWRAP_IRQ_LSB (1U << 31) /* 1b */ +/* BUS_PROTECT_RDY (0x10006000+0x168) */ +#define BUS_PROTECT_RDY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT2_RDY (0x10006000+0x16C) */ +#define BUS_PROTECT2_RDY_LSB (1U << 0) /* 32b */ +/* SUBSYS_IDLE_STA (0x10006000+0x170) */ +#define SUBSYS_IDLE_STA_LSB (1U << 0) /* 32b */ +/* CPU_IDLE_STA (0x10006000+0x174) */ +#define MP0_CPU0_STANDBYWFI_AFTER_SEL_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_STANDBYWFI_AFTER_SEL_LSB (1U << 1) /* 1b */ +#define MP0_CPU2_STANDBYWFI_AFTER_SEL_LSB (1U << 2) /* 1b */ +#define MP0_CPU3_STANDBYWFI_AFTER_SEL_LSB (1U << 3) /* 1b */ +#define MP1_CPU0_STANDBYWFI_AFTER_SEL_LSB (1U << 4) /* 1b */ +#define MP1_CPU1_STANDBYWFI_AFTER_SEL_LSB (1U << 5) /* 1b */ +#define MP1_CPU2_STANDBYWFI_AFTER_SEL_LSB (1U << 6) /* 1b */ +#define MP1_CPU3_STANDBYWFI_AFTER_SEL_LSB (1U << 7) /* 1b */ +#define MP0_CPU0_STANDBYWFI_LSB (1U << 10) /* 1b */ +#define MP0_CPU1_STANDBYWFI_LSB (1U << 11) /* 1b */ +#define MP0_CPU2_STANDBYWFI_LSB (1U << 12) /* 1b */ +#define MP0_CPU3_STANDBYWFI_LSB (1U << 13) /* 1b */ +#define MP1_CPU0_STANDBYWFI_LSB (1U << 14) /* 1b */ +#define MP1_CPU1_STANDBYWFI_LSB (1U << 15) /* 1b */ +#define MP1_CPU2_STANDBYWFI_LSB (1U << 16) /* 1b */ +#define MP1_CPU3_STANDBYWFI_LSB (1U << 17) /* 1b */ +#define MP0_CPUTOP_IDLE_LSB (1U << 20) /* 1b */ +#define MP1_CPUTOP_IDLE_LSB (1U << 21) /* 1b */ +#define MCUSYS_IDLE_LSB (1U << 23) /* 1b */ +/* PCM_FSM_STA (0x10006000+0x178) */ +#define EXEC_INST_OP_LSB (1U << 0) /* 4b */ +#define PC_STATE_LSB (1U << 4) /* 3b */ +#define IM_STATE_LSB (1U << 7) /* 3b */ +#define MASTER_STATE_LSB (1U << 10) /* 5b */ +#define EVENT_FSM_LSB (1U << 15) /* 3b */ +#define PCM_CLK_SEL_STA_LSB (1U << 18) /* 3b */ +#define PCM_KICK_LSB (1U << 21) /* 1b */ +#define IM_KICK_LSB (1U << 22) /* 1b */ +#define EXT_SRCCLKEN_STA_LSB (1U << 23) /* 2b */ +#define EXT_SRCVOLTEN_STA_LSB (1U << 25) /* 1b */ +/* PWR_STATUS (0x10006000+0x180) */ +#define PWR_STATUS_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_2ND (0x10006000+0x184) */ +#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */ +/* CPU_PWR_STATUS (0x10006000+0x188) */ +#define CPU_PWR_STATUS_LSB (1U << 0) /* 32b */ +/* CPU_PWR_STATUS_2ND (0x10006000+0x18C) */ +#define CPU_PWR_STATUS_2ND_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_0 (0x10006000+0x190) */ +#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_1 (0x10006000+0x194) */ +#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_2 (0x10006000+0x198) */ +#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */ +/* DRAMC_DBG_LATCH (0x10006000+0x19C) */ +#define DRAMC_DEBUG_LATCH_STATUS_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA0 (0x10006000+0x1A0) */ +#define SPM_TWAM_LAST_STA0_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA1 (0x10006000+0x1A4) */ +#define SPM_TWAM_LAST_STA1_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA2 (0x10006000+0x1A8) */ +#define SPM_TWAM_LAST_STA2_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA3 (0x10006000+0x1AC) */ +#define SPM_TWAM_LAST_STA3_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA0 (0x10006000+0x1B0) */ +#define SPM_TWAM_CURR_STA0_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA1 (0x10006000+0x1B4) */ +#define SPM_TWAM_CURR_STA1_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA2 (0x10006000+0x1B8) */ +#define SPM_TWAM_CURR_STA2_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA3 (0x10006000+0x1BC) */ +#define SPM_TWAM_CURR_STA3_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_TIMER_OUT (0x10006000+0x1C0) */ +#define SPM_TWAM_TIMER_OUT_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_3 (0x10006000+0x1C4) */ +#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */ +/* SPM_SRC_RDY_STA (0x10006000+0x1D0) */ +#define SPM_INFRA_SRC_ACK_LSB (1U << 0) /* 1b */ +#define SPM_VRF18_SRC_ACK_LSB (1U << 1) /* 1b */ +/* MCU_PWR_CON (0x10006000+0x200) */ +#define MCU_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MCU_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MCU_PWR_ON_LSB (1U << 2) /* 1b */ +#define MCU_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MCU_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MCU_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MCU_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP0_CPUTOP_PWR_CON (0x10006000+0x204) */ +#define MP0_CPUTOP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPUTOP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPUTOP_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPUTOP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPUTOP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPUTOP_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPUTOP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP0_CPU0_PWR_CON (0x10006000+0x208) */ +#define MP0_CPU0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPU0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPU0_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPU0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPU0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPU0_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPU0_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP0_CPU1_PWR_CON (0x10006000+0x20C) */ +#define MP0_CPU1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPU1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPU1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPU1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPU1_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPU1_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP0_CPU2_PWR_CON (0x10006000+0x210) */ +#define MP0_CPU2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPU2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPU2_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPU2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPU2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPU2_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPU2_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP0_CPU3_PWR_CON (0x10006000+0x214) */ +#define MP0_CPU3_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPU3_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPU3_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPU3_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPU3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPU3_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPU3_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP1_CPUTOP_PWR_CON (0x10006000+0x218) */ +#define MP1_CPUTOP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPUTOP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPUTOP_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPUTOP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPUTOP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPUTOP_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPUTOP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP1_CPU0_PWR_CON (0x10006000+0x21C) */ +#define MP1_CPU0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPU0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPU0_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPU0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPU0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPU0_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPU0_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP1_CPU1_PWR_CON (0x10006000+0x220) */ +#define MP1_CPU1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPU1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPU1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPU1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPU1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPU1_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPU1_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP1_CPU2_PWR_CON (0x10006000+0x224) */ +#define MP1_CPU2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPU2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPU2_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPU2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPU2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPU2_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPU2_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP1_CPU3_PWR_CON (0x10006000+0x228) */ +#define MP1_CPU3_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPU3_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPU3_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPU3_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPU3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPU3_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPU3_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +/* MP0_CPUTOP_L2_PDN (0x10006000+0x240) */ +#define MP0_CPUTOP_L2_SRAM_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPUTOP_L2_SRAM_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPUTOP_L2_SLEEP_B (0x10006000+0x244) */ +#define MP0_CPUTOP_L2_SRAM_SLEEP_B_LSB (1U << 0) /* 1b */ +#define MP0_CPUTOP_L2_SRAM_SLEEP_B_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPU0_L1_PDN (0x10006000+0x248) */ +#define MP0_CPU0_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPU0_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPU1_L1_PDN (0x10006000+0x24C) */ +#define MP0_CPU1_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPU2_L1_PDN (0x10006000+0x250) */ +#define MP0_CPU2_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPU2_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPU3_L1_PDN (0x10006000+0x254) */ +#define MP0_CPU3_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPU3_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPUTOP_L2_PDN (0x10006000+0x258) */ +#define MP1_CPUTOP_L2_SRAM_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPUTOP_L2_SRAM_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPUTOP_L2_SLEEP_B (0x10006000+0x25C) */ +#define MP1_CPUTOP_L2_SRAM_SLEEP_B_LSB (1U << 0) /* 1b */ +#define MP1_CPUTOP_L2_SRAM_SLEEP_B_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPU0_L1_PDN (0x10006000+0x260) */ +#define MP1_CPU0_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPU0_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPU1_L1_PDN (0x10006000+0x264) */ +#define MP1_CPU1_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPU1_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPU2_L1_PDN (0x10006000+0x268) */ +#define MP1_CPU2_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPU2_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPU3_L1_PDN (0x10006000+0x26C) */ +#define MP1_CPU3_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPU3_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* CPU_EXT_BUCK_ISO (0x10006000+0x290) */ +#define MP0_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +#define MP1_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */ +/* DUMMY1_PWR_CON (0x10006000+0x2B0) */ +#define DUMMY1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DUMMY1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DUMMY1_PWR_ON_LSB (1U << 2) /* 1b */ +#define DUMMY1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DUMMY1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* VDE_PWR_CON (0x10006000+0x300) */ +#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VDE_PWR_ON_LSB (1U << 2) /* 1b */ +#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VDE_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* VEN_PWR_CON (0x10006000+0x304) */ +#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VEN_PWR_ON_LSB (1U << 2) /* 1b */ +#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VEN_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* ISP_PWR_CON (0x10006000+0x308) */ +#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ISP_PWR_ON_LSB (1U << 2) /* 1b */ +#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ISP_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* DIS_PWR_CON (0x10006000+0x30C) */ +#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DIS_PWR_ON_LSB (1U << 2) /* 1b */ +#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DIS_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* MJC_PWR_CON (0x10006000+0x310) */ +#define MJC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MJC_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MJC_PWR_ON_LSB (1U << 2) /* 1b */ +#define MJC_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MJC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MJC_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define MJC_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* AUDIO_PWR_CON (0x10006000+0x314) */ +#define AUD_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define AUD_PWR_ISO_LSB (1U << 1) /* 1b */ +#define AUD_PWR_ON_LSB (1U << 2) /* 1b */ +#define AUD_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define AUD_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define AUD_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define AUD_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* IFR_PWR_CON (0x10006000+0x318) */ +#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IFR_PWR_ON_LSB (1U << 2) /* 1b */ +#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IFR_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* DPY_PWR_CON (0x10006000+0x31C) */ +#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DPY_PWR_ON_LSB (1U << 2) /* 1b */ +#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* MD1_PWR_CON (0x10006000+0x320) */ +#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MD1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */ +/* MD2_PWR_CON (0x10006000+0x324) */ +#define MD2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MD2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MD2_PWR_ON_LSB (1U << 2) /* 1b */ +#define MD2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MD2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MD2_SRAM_PDN_LSB (1U << 8) /* 1b */ +/* C2K_PWR_CON (0x10006000+0x328) */ +#define C2K_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define C2K_PWR_ISO_LSB (1U << 1) /* 1b */ +#define C2K_PWR_ON_LSB (1U << 2) /* 1b */ +#define C2K_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define C2K_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* CONN_PWR_CON (0x10006000+0x32C) */ +#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CONN_PWR_ON_LSB (1U << 2) /* 1b */ +#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CONN_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define CONN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VCOREPDN_PWR_CON (0x10006000+0x330) */ +#define VCOREPDN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VCOREPDN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VCOREPDN_PWR_ON_LSB (1U << 2) /* 1b */ +#define VCOREPDN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VCOREPDN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* MFG_ASYNC_PWR_CON (0x10006000+0x334) */ +#define MFG_ASYNC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG_ASYNC_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG_ASYNC_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG_ASYNC_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG_ASYNC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG_ASYNC_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define MFG_ASYNC_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* MFG_PWR_CON (0x10006000+0x338) */ +#define MFG_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG_SRAM_PDN_LSB (1U << 8) /* 6b */ +#define MFG_SRAM_PDN_ACK_LSB (1U << 16) /* 6b */ +/* SYSRAM_CON (0x10006000+0x350) */ +#define IFR_SRAMROM_SRAM_PDN_LSB (1U << 0) /* 4b */ +#define IFR_SRAMROM_SRAM_CKISO_LSB (1U << 4) /* 4b */ +#define IFR_SRAMROM_SRAM_SLEEP_B_LSB (1U << 8) /* 4b */ +#define IFR_SRAMROM_SRAM_ISOINT_B_LSB (1U << 12) /* 4b */ +/* SYSROM_CON (0x10006000+0x354) */ +#define IFR_SRAMROM_ROM_PDN_LSB (1U << 0) /* 6b */ +/* SCP_SRAM_CON (0x10006000+0x358) */ +#define SCP_SRAM_PDN_LSB (1U << 0) /* 1b */ +#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SCP_SRAM_ISOINT_B_LSB (1U << 8) /* 1b */ +/* GCPU_SRAM_CON (0x10006000+0x35C) */ +#define GCPU_SRAM_PDN_LSB (1U << 0) /* 4b */ +#define GCPU_SRAM_CKISO_LSB (1U << 4) /* 4b */ +#define GCPU_SRAM_SLEEP_B_LSB (1U << 8) /* 4b */ +#define GCPU_SRAM_ISOINT_B_LSB (1U << 12) /* 4b */ +/* MDSYS_INTF_INFRA_PWR_CON (0x10006000+0x360) */ +#define MDSYS_INTF_INFRA_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MDSYS_INTF_INFRA_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MDSYS_INTF_INFRA_PWR_ON_LSB (1U << 2) /* 1b */ +#define MDSYS_INTF_INFRA_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MDSYS_INTF_INFRA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* MDSYS_INTF_MD1_PWR_CON (0x10006000+0x364) */ +#define MDSYS_INTF_MD1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MDSYS_INTF_MD1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MDSYS_INTF_MD1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MDSYS_INTF_MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MDSYS_INTF_MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* MDSYS_INTF_C2K_PWR_CON (0x10006000+0x368) */ +#define MDSYS_INTF_C2K_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MDSYS_INTF_C2K_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MDSYS_INTF_C2K_PWR_ON_LSB (1U << 2) /* 1b */ +#define MDSYS_INTF_C2K_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MDSYS_INTF_C2K_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* BSI_TOP_SRAM_CON (0x10006000+0x370) */ +#define BSI_TOP_SRAM_PDN_LSB (1U << 0) /* 7b */ +#define BSI_TOP_SRAM_DSLP_LSB (1U << 7) /* 7b */ +#define BSI_TOP_SRAM_SLEEP_B_LSB (1U << 14) /* 7b */ +#define BSI_TOP_SRAM_ISOINT_B_LSB (1U << 21) /* 7b */ +#define BSI_TOP_SRAM_ISO_EN_LSB (1U << 28) /* 2b */ +/* DVFSP_SRAM_CON (0x10006000+0x374) */ +#define DVFSP_SRAM_PDN_LSB (1U << 0) /* 2b */ +#define DVFSP_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */ +#define DVFSP_SRAM_ISOINT_B_LSB (1U << 8) /* 2b */ +/* MD_EXT_BUCK_ISO (0x10006000+0x390) */ +#define MD_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +/* DUMMY2_PWR_CON (0x10006000+0x3B0) */ +#define DUMMY2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DUMMY2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DUMMY2_PWR_ON_LSB (1U << 2) /* 1b */ +#define DUMMY2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DUMMY2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DUMMY2_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define DUMMY2_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* SPM_DVFS_CON (0x10006000+0x400) */ +#define SPM_DVFS_CON_LSB (1U << 0) /* 4b */ +#define SPM_DVFS_ACK_LSB (1U << 30) /* 2b */ +/* SPM_MDBSI_CON (0x10006000+0x404) */ +#define SPM_MDBSI_CON_LSB (1U << 0) /* 3b */ +/* SPM_MAS_PAUSE_MASK_B (0x10006000+0x408) */ +#define SPM_MAS_PAUSE_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_MAS_PAUSE2_MASK_B (0x10006000+0x40C) */ +#define SPM_MAS_PAUSE2_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BSI_GEN (0x10006000+0x410) */ +#define SPM_BSI_START_LSB (1U << 0) /* 1b */ +/* SPM_BSI_EN_SR (0x10006000+0x414) */ +#define SPM_BSI_EN_SR_LSB (1U << 0) /* 32b */ +/* SPM_BSI_CLK_SR (0x10006000+0x418) */ +#define SPM_BSI_CLK_SR_LSB (1U << 0) /* 32b */ +/* SPM_BSI_D0_SR (0x10006000+0x41C) */ +#define SPM_BSI_D0_SR_LSB (1U << 0) /* 32b */ +/* SPM_BSI_D1_SR (0x10006000+0x420) */ +#define SPM_BSI_D1_SR_LSB (1U << 0) /* 32b */ +/* SPM_BSI_D2_SR (0x10006000+0x424) */ +#define SPM_BSI_D2_SR_LSB (1U << 0) /* 32b */ +/* SPM_AP_SEMA (0x10006000+0x428) */ +#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */ +/* SPM_SPM_SEMA (0x10006000+0x42C) */ +#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */ +/* AP2MD_CROSS_TRIGGER (0x10006000+0x430) */ +#define AP2MD_CROSS_TRIGGER_REQ_LSB (1U << 0) /* 1b */ +#define AP2MD_CROSS_TRIGGER_ACK_LSB (1U << 1) /* 1b */ +/* AP_MDSRC_REQ (0x10006000+0x434) */ +#define AP_MD1SRC_REQ_LSB (1U << 0) /* 1b */ +#define AP_MD2SRC_REQ_LSB (1U << 1) /* 1b */ +#define AP_MD1SRC_ACK_LSB (1U << 4) /* 1b */ +#define AP_MD2SRC_ACK_LSB (1U << 5) /* 1b */ +/* SPM2MD_DVFS_CON (0x10006000+0x438) */ +#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 16b */ +/* MD2SPM_DVFS_CON (0x10006000+0x43C) */ +#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 16b */ +/* DRAMC_DPY_CLK_SW_CON (0x10006000+0x440) */ +#define SPM2DRAMC_SHUFFLE_START_LSB (1U << 0) /* 1b */ +#define SPM2DRAMC_SHUFFLE_SWITCH_LSB (1U << 1) /* 1b */ +#define SPM2DPY_DIV2_SYNC_LSB (1U << 2) /* 1b */ +#define SPM2DPY_1PLL_SWITCH_LSB (1U << 3) /* 1b */ +#define SPM2DPY_TEST_CK_MUX_LSB (1U << 4) /* 1b */ +#define SPM2DPY_ASYNC_MODE_LSB (1U << 5) /* 1b */ +#define SPM2TOP_ASYNC_MODE_LSB (1U << 6) /* 1b */ +/* DPY_LP_CON (0x10006000+0x444) */ +#define SC_DDRPHY_LP_SIGNALS_LSB (1U << 0) /* 3b */ +/* CPU_DVFS_REQ (0x10006000+0x448) */ +#define CPU_DVFS_REQ_LSB (1U << 0) /* 16b */ +#define DVFS_HALT_LSB (1U << 16) /* 1b */ +#define MD_DVFS_ERROR_STATUS_LSB (1U << 17) /* 1b */ +/* SPM_PLL_CON (0x10006000+0x44C) */ +#define SC_MPLLOUT_OFF_LSB (1U << 0) /* 1b */ +#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */ +#define SC_MPLL_OFF_LSB (1U << 4) /* 1b */ +#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */ +#define SC_MPLL_S_OFF_LSB (1U << 8) /* 1b */ +#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */ +/* SPM_EMI_BW_MODE (0x10006000+0x450) */ +#define EMI_BW_MODE_LSB (1U << 0) /* 1b */ +#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */ +/* AP2MD_PEER_WAKEUP (0x10006000+0x454) */ +#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */ +/* ULPOSC_CON (0x10006000+0x458) */ +#define ULPOSC_EN_LSB (1U << 0) /* 1b */ +#define ULPOSC_RST_LSB (1U << 1) /* 1b */ +#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */ +/* MP0_CPU0_IRQ_MASK (0x10006000+0x500) */ +#define MP0_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU0_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU1_IRQ_MASK (0x10006000+0x504) */ +#define MP0_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU2_IRQ_MASK (0x10006000+0x508) */ +#define MP0_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU2_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU3_IRQ_MASK (0x10006000+0x50C) */ +#define MP0_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU3_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU0_IRQ_MASK (0x10006000+0x510) */ +#define MP1_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU0_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU1_IRQ_MASK (0x10006000+0x514) */ +#define MP1_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU1_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU2_IRQ_MASK (0x10006000+0x518) */ +#define MP1_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU2_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU3_IRQ_MASK (0x10006000+0x51C) */ +#define MP1_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU3_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU0_WFI_EN (0x10006000+0x530) */ +#define MP0_CPU0_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU1_WFI_EN (0x10006000+0x534) */ +#define MP0_CPU1_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU2_WFI_EN (0x10006000+0x538) */ +#define MP0_CPU2_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU3_WFI_EN (0x10006000+0x53C) */ +#define MP0_CPU3_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP1_CPU0_WFI_EN (0x10006000+0x540) */ +#define MP1_CPU0_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP1_CPU1_WFI_EN (0x10006000+0x544) */ +#define MP1_CPU1_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP1_CPU2_WFI_EN (0x10006000+0x548) */ +#define MP1_CPU2_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP1_CPU3_WFI_EN (0x10006000+0x54C) */ +#define MP1_CPU3_WFI_EN_LSB (1U << 0) /* 1b */ +/* CPU_PTPOD2_CON (0x10006000+0x560) */ +#define MP0_PTPOD2_FBB_EN_LSB (1U << 0) /* 1b */ +#define MP1_PTPOD2_FBB_EN_LSB (1U << 1) /* 1b */ +#define MP0_PTPOD2_SPARK_EN_LSB (1U << 2) /* 1b */ +#define MP1_PTPOD2_SPARK_EN_LSB (1U << 3) /* 1b */ +#define MP0_PTPOD2_FBB_ACK_LSB (1U << 4) /* 1b */ +#define MP1_PTPOD2_FBB_ACK_LSB (1U << 5) /* 1b */ +/* SPM_SW_FLAG (0x10006000+0x600) */ +#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */ +/* SPM_SW_DEBUG (0x10006000+0x604) */ +#define SPM_SW_DEBUG_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_0 (0x10006000+0x608) */ +#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_1 (0x10006000+0x60C) */ +#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_2 (0x10006000+0x610) */ +#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_3 (0x10006000+0x614) */ +#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_4 (0x10006000+0x618) */ +#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_5 (0x10006000+0x61C) */ +#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */ +/* SPM_RSV_CON (0x10006000+0x620) */ +#define SPM_RSV_CON_LSB (1U << 0) /* 16b */ +/* SPM_RSV_STA (0x10006000+0x624) */ +#define SPM_RSV_STA_LSB (1U << 0) /* 16b */ +/* SPM_PASR_DPD_0 (0x10006000+0x630) */ +#define SPM_PASR_DPD_0_LSB (1U << 0) /* 32b */ +/* SPM_PASR_DPD_1 (0x10006000+0x634) */ +#define SPM_PASR_DPD_1_LSB (1U << 0) /* 32b */ +/* SPM_PASR_DPD_2 (0x10006000+0x638) */ +#define SPM_PASR_DPD_2_LSB (1U << 0) /* 32b */ +/* SPM_PASR_DPD_3 (0x10006000+0x63C) */ +#define SPM_PASR_DPD_3_LSB (1U << 0) /* 32b */ + +#define SPM_PROJECT_CODE 0xb16 +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) + +/************************************** + * Macro and Inline + **************************************/ +#define spm_read(addr) __raw_readl((void __force __iomem *)(addr)) +#define spm_write(addr, val) mt_reg_sync_writel(val, addr) + +#endif diff --git a/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_vcore_dvfs_mt6755.h b/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_vcore_dvfs_mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..e94d61906dd396370dcc03ffb29969b21e57b376 --- /dev/null +++ b/drivers/misc/mediatek/base/power/include/spm_v2/mt_spm_vcore_dvfs_mt6755.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_SPM_VCORE_DVFS_H +#define _MT_SPM_VCORE_DVFS_H + +#include +#include "mt_spm.h" +#include + +#undef VCOREFS_SPM_TAG +#define VCOREFS_SPM_TAG "[VcoreFS_SPM]" + +#define spm_vcorefs_crit(fmt, args...) \ + pr_err(VCOREFS_SPM_TAG"[CRTT]"fmt, ##args) +#define spm_vcorefs_err(fmt, args...) \ + pr_err(VCOREFS_SPM_TAG"[ERR]"fmt, ##args) +#define spm_vcorefs_warn(fmt, args...) \ + pr_warn(VCOREFS_SPM_TAG"[WARN]"fmt, ##args) +#define spm_vcorefs_info(fmt, args...) \ + pr_warn(VCOREFS_SPM_TAG""fmt, ##args) /* pr_info(TAG""fmt, ##args) */ +#define spm_vcorefs_debug(fmt, args...) \ + pr_debug(VCOREFS_SPM_TAG""fmt, ##args) + +#define spm_vcorefs_aee_warn(string, args...) do {\ + pr_err("[WARN]"string, ##args); \ + aee_kernel_warning(VCOREFS_SPM_TAG, "[WARN]"string, ##args); \ +} while (0) + +#define spm_vcorefs_aee_exception(string, args...) do {\ + pr_err("[ERR]"string, ##args); \ + aee_kernel_exception(VCOREFS_SPM_TAG, "[ERR]"string, ##args); \ +} while (0) + +/* load fw for boot up */ +extern void spm_go_to_vcore_dvfs(u32 spm_flags, u32 spm_data); + +/* vcore dvfs request */ +extern int spm_vcorefs_set_dvfs_hpm(int opp, int vcore, int ddr); +extern int spm_vcorefs_set_dvfs_hpm_force(int opp, int vcore, int ddr); +extern int spm_vcorefs_set_total_bw(int opp, int vcore, int ddr); /* OVL >3 & CA Data-Link */ + +/* debug only */ +extern int spm_vcorefs_set_dvfs_lpm_force(int opp, int vcore, int ddr); +extern void spm_vcorefs_set_pcm_flag(u32 flag, bool set); + +/* bw monitor threshold setting to spm */ +extern int spm_vcorefs_set_total_bw_threshold(u32 lpm_threshold, u32 hpm_threshold); +extern int spm_vcorefs_set_perform_bw_threshold(u32 lpm_threshold, u32 hpm_threshold); + +/* bw monitor enable/disable in spm dvfs logic */ +extern void spm_vcorefs_enable_total_bw(bool enable); +extern void spm_vcorefs_enable_perform_bw(bool enable); +extern int spm_vcorefs_get_clk_mem_pll(void); + +/* misc vcore dvfs support func */ +extern char *spm_vcorefs_dump_dvfs_regs(char *p); +extern int spm_vcorefs_set_cpu_dvfs_req(u32 screen_on, u32 mask); +extern u32 spm_vcorefs_get_MD_status(void); +extern bool spm_vcorefs_is_dvfs_in_porgress(void); + +/* SRAM debug */ +extern void aee_rr_rec_vcore_dvfs_status(u32 val); +extern u32 aee_rr_curr_vcore_dvfs_status(void); + +#endif /* _MT_SPM_VCORE_DVFS_H */ diff --git a/drivers/misc/mediatek/base/power/include/spm_v2/pcm_def_mt6755.h b/drivers/misc/mediatek/base/power/include/spm_v2/pcm_def_mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..6f8109d87b37e748c323a8011be7e56a6598c52c --- /dev/null +++ b/drivers/misc/mediatek/base/power/include/spm_v2/pcm_def_mt6755.h @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __pcm_def_h__ +#define __pcm_def_h__ + +/* + * Auto generated by DE, please DO NOT modify this file directly. + */ + +/* --- R0 Define --- */ +#define R0_SC_26M_CK_OFF (1U << 0) +#define R0_SC_ARM_CK_OFF (1U << 1) +#define R0_SC_MEM_CK_OFF (1U << 2) +#define R0_SC_AXI_CK_OFF (1U << 3) +#define R0_SC_SMI_CK_OFF (1U << 4) +#define R0_SC_MD26M_CK_OFF (1U << 5) +#define R0_SC_MD32K_CK_OFF (1U << 6) +#define R0_SPM2DRAMC_SHUFFLE_START (1U << 7) +#define R0_SC_MEMPLLOUT_OFF (1U << 8) +#define R0_SC_ARMPLLOUT_OFF (1U << 9) +#define R0_SC_MAINPOUT_OFF (1U << 10) +#define R0_SC_ARMBPLLOUT_OFF (1U << 11) +#define R0_SPM2DRAMC_SHUFFLE_SWITCH (1U << 12) +#define R0_SPM2DPY_DIV2_SYNC (1U << 13) +#define R0_SPM2DPY_1PLL_SWITCH (1U << 14) +#define R0_SPM2TOP_ASYNC_MODE (1U << 15) +#define R0_SC_MEMPLL_OFF (1U << 16) +#define R0_SC_ARMPLL_OFF (1U << 17) +#define R0_SC_MAINPLL_OFF (1U << 18) +#define R0_SC_ARMBPLL_OFF (1U << 19) +#define R0_SC_CKSQ0_OFF (1U << 20) +#define R0_SC_CKSQ1_OFF (1U << 21) +#define R0_SC_MEMPLL_S_OFF (1U << 22) +#define R0_SC_ARMPLL_S_OFF (1U << 23) +#define R0_SC_MAINPLL_S_OFF (1U << 24) +#define R0_SC_ARMBPLL_S_OFF (1U << 25) +#define R0_SC_MEMPLL_S2_OFF (1U << 26) +#define R0_SC_MEMPLL_RESET (1U << 27) +#define R0_SC_APBIAS_OFF (1U << 28) +#define R0_SC_1ST_MEMPLLOUT_OFF (1U << 29) +#define R0_SC_1ST_MEMPLL_OFF (1U << 30) +#define R0_SC_1ST_MEMPLL_S_OFF (1U << 31) +/* --- R7 Define --- */ +#define R7_PWRAP_SLEEP_REQ (1U << 0) +#define R7_EMI_CLK_OFF_REQ (1U << 1) +#define R7_TOP_MAS_PAU_REQ (1U << 2) +#define R7_SPM2CKSYS_MEM_CK_MUX_UPDATE (1U << 3) +#define R7_PCM_CK_SEL0 (1U << 4) +#define R7_PCM_CK_SEL1 (1U << 5) +#define R7_MD32_WAKEUP (1U << 6) +#define R7_FREQH_PAUSE_ARM (1U << 7) +#define R7_SC_26M_CK_SEL (1U << 8) +#define R7_PCM_TIMER_SET (1U << 9) +#define R7_PCM_TIMER_CLR (1U << 10) +#define R7_SRCVOLTEN (1U << 11) +#define R7_CSYSPWRUPACK (1U << 12) +#define R7_IM_SLEEP_ENABLE (1U << 13) +#define R7_SRCCLKENO_0 (1U << 14) +#define R7_SYSRST (1U << 15) +#define R7_MD_APSRC_ACK (1U << 16) +#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17) +#define R7_SC_AXI_DCM_DIS (1U << 18) +#define R7_FREQH_PAUSE_MAIN (1U << 19) +#define R7_FREQH_PAUSE_MEM (1U << 20) +#define R7_SRCCLKENO_1 (1U << 21) +#define R7_WDT_KICK_P (1U << 22) +#define R7_TWAM_EVENT_CLR (1U << 23) +#define R7_WAKEUP_EXT_W_SEL (1U << 24) +#define R7_WAKEUP_EXT_R_SEL (1U << 25) +#define R7_PMIC_IRQ_REQ_EN (1U << 26) +#define R7_FORCE_26M_WAKE (1U << 27) +#define R7_FORCE_APSRC_WAKE (1U << 28) +#define R7_FORCE_INFRA_WAKE (1U << 29) +#define R7_FORCE_VRF18_WAKE (1U << 30) +#define R7_SPM2DRAMC_BLOCK_ALE (1U << 31) +/* --- R12 Define --- */ +#define R12_PCM_TIMER (1U << 0) +#define R12_MD32_WDT_EVENT_B (1U << 1) +#define R12_KP_IRQ_B (1U << 2) +#define R12_APWDT_EVENT_B (1U << 3) +#define R12_APXGPT1_EVENT_B (1U << 4) +#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5) +#define R12_EINT_EVENT_B (1U << 6) +#define R12_CONN_WDT_IRQ_B (1U << 7) +#define R12_CCIF0_EVENT_B (1U << 8) +#define R12_LOWBATTERY_IRQ_B (1U << 9) +#define R12_MD32_SPM_IRQ_B (1U << 10) +#define R12_26M_WAKE (1U << 11) +#define R12_26M_SLEEP (1U << 12) +#define R12_PCM_WDT_WAKEUP_B (1U << 13) +#define R12_USB_CDSC_B (1U << 14) +#define R12_USB_POWERDWN_B (1U << 15) +#define R12_C2K_WDT_IRQ_B (1U << 16) +#define R12_EINT_EVENT_SECURE_B (1U << 17) +#define R12_CCIF1_EVENT_B (1U << 18) +#define R12_UART0_IRQ_B (1U << 19) +#define R12_AFE_IRQ_MCU_B (1U << 20) +#define R12_THERM_CTRL_EVENT_B (1U << 21) +#define R12_SYS_CIRQ_IRQ_B (1U << 22) +#define R12_MD2_WDT_B (1U << 23) +#define R12_CSYSPWREQ_B (1U << 24) +#define R12_MD1_WDT_B (1U << 25) +#define R12_CLDMA_EVENT_B (1U << 26) +#define R12_SEJ_WDT_GPT_B (1U << 27) +#define R12_ALL_MD32_WAKEUP_B (1U << 28) +#define R12_CPU_IRQ_B (1U << 29) +#define R12_APSRC_WAKE (1U << 30) +#define R12_APSRC_SLEEP (1U << 31) +/* --- R12ext Define --- */ +#define R12EXT_26M_WAKE (1U << 0) +#define R12EXT_26M_SLEEP (1U << 1) +#define R12EXT_INFRA_WAKE (1U << 2) +#define R12EXT_INFRA_SLEEP (1U << 3) +#define R12EXT_APSRC_WAKE (1U << 4) +#define R12EXT_APSRC_SLEEP (1U << 5) +#define R12EXT_VRF18_WAKE (1U << 6) +#define R12EXT_VRF18_SLEEP (1U << 7) +#define R12EXT_LTE_WAKE (1U << 8) +#define R12EXT_LTE_SLEEP (1U << 9) +#define R12EXT_DVFS_WAKE (1U << 10) +#define R12EXT_DVFS_SLEEP (1U << 11) +#define R12EXT_DDREN_WAKE (1U << 12) +#define R12EXT_DDREN_SLEEP (1U << 13) +#define R12EXT_NFC_CLK_BUF_WAKE (1U << 14) +#define R12EXT_NFC_CLK_BUF_SLEEP (1U << 15) +#define R12EXT_CONN_CLK_BUF_WAKE (1U << 16) +#define R12EXT_CONN_CLK_BUF_SLEEP (1U << 17) +#define R12EXT_MD_DVFS_ERROR_STATUS (1U << 18) +#define R12EXT_AUDIO_REQ_WAKE (1U << 19) +#define R12EXT_AUDIO_REQ_SLEEP (1U << 20) +#define R12EXT_BIT21 (1U << 21) +#define R12EXT_BIT22 (1U << 22) +#define R12EXT_BIT23 (1U << 23) +#define R12EXT_BIT24 (1U << 24) +#define R12EXT_BIT25 (1U << 25) +#define R12EXT_BIT26 (1U << 26) +#define R12EXT_BIT27 (1U << 27) +#define R12EXT_BIT28 (1U << 28) +#define R12EXT_BIT29 (1U << 29) +#define R12EXT_BIT30 (1U << 30) +#define R12EXT_BIT31 (1U << 31) +/* --- R13 Define --- */ +#define R13_EXT_SRCCLKENI_0 (1U << 0) +#define R13_EXT_SRCCLKENI_1 (1U << 1) +#define R13_MD1_SRCCLKENA (1U << 2) +#define R13_MD1_APSRC_REQ (1U << 3) +#define R13_CONN_DDR_EN (1U << 4) +#define R13_MD2_SRCCLKENA (1U << 5) +#define R13_MD32_SRCCLKENA (1U << 6) +#define R13_MD32_APSRC_REQ (1U << 7) +#define R13_MD_STATE (1U << 8) +#define R13_MD2_STATE (1U << 9) +#define R13_MM_STATE (1U << 10) +#define R13_MD32_STATE (1U << 11) +#define R13_MD_DDR_EN (1U << 12) +#define R13_CONN_STATE (1U << 13) +#define R13_CONN_SRCCLKENA (1U << 14) +#define R13_CONN_APSRC_REQ (1U << 15) +#define R13_SLEEP_EVENT_STA (1U << 16) +#define R13_WAKE_EVENT_STA (1U << 17) +#define R13_EMI_IDLE (1U << 18) +#define R13_CSYSPWRUPREQ (1U << 19) +#define R13_PWRAP_SLEEP_ACK (1U << 20) +#define R13_EMI_CLK_OFF_ACK (1U << 21) +#define R13_TOP_MAS_PAU_ACK (1U << 22) +#define R13_DRAMC2SPM_SHFFLUE_STATUS (1U << 23) +#define R13_MD2_APSRC_REQ (1U << 24) +#define R13_DRAMC2SPM_REQUEST_QUEUE_EMPTY (1U << 25) +#define R13_INFRA_AUX_IDLE (1U << 26) +#define R13_DVFS_WAKE (1U << 27) +#define R13_MD2_DDR_EN (1U << 28) +#define R13_LTE_SRCCLKENA (1U << 29) +#define R13_MD1_VRF18_REQ (1U << 30) +#define R13_C2K_VRF18_REQ (1U << 31) + +enum SPM_WAKE_SRC_LIST { + WAKE_SRC_R12_PCM_TIMER = (1U << 0), + WAKE_SRC_R12_MD32_WDT_EVENT_B = (1U << 1), + WAKE_SRC_R12_KP_IRQ_B = (1U << 2), + WAKE_SRC_R12_APWDT_EVENT_B = (1U << 3), + WAKE_SRC_R12_APXGPT1_EVENT_B = (1U << 4), + WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B = (1U << 5), + WAKE_SRC_R12_EINT_EVENT_B = (1U << 6), + WAKE_SRC_R12_CONN_WDT_IRQ_B = (1U << 7), + WAKE_SRC_R12_CCIF0_EVENT_B = (1U << 8), + WAKE_SRC_R12_LOWBATTERY_IRQ_B = (1U << 9), + WAKE_SRC_R12_MD32_SPM_IRQ_B = (1U << 10), + WAKE_SRC_R12_26M_WAKE = (1U << 11), + WAKE_SRC_R12_26M_SLEEP = (1U << 12), + WAKE_SRC_R12_PCM_WDT_WAKEUP_B = (1U << 13), + WAKE_SRC_R12_USB_CDSC_B = (1U << 14), + WAKE_SRC_R12_USB_POWERDWN_B = (1U << 15), + WAKE_SRC_R12_C2K_WDT_IRQ_B = (1U << 16), + WAKE_SRC_R12_EINT_EVENT_SECURE_B = (1U << 17), + WAKE_SRC_R12_CCIF1_EVENT_B = (1U << 18), + WAKE_SRC_R12_UART0_IRQ_B = (1U << 19), + WAKE_SRC_R12_AFE_IRQ_MCU_B = (1U << 20), + WAKE_SRC_R12_THERM_CTRL_EVENT_B = (1U << 21), + WAKE_SRC_R12_SYS_CIRQ_IRQ_B = (1U << 22), + WAKE_SRC_R12_MD2_WDT_B = (1U << 23), + WAKE_SRC_R12_CSYSPWREQ_B = (1U << 24), + WAKE_SRC_R12_MD1_WDT_B = (1U << 25), + WAKE_SRC_R12_CLDMA_EVENT_B = (1U << 26), + WAKE_SRC_R12_SEJ_WDT_GPT_B = (1U << 27), + WAKE_SRC_R12_ALL_MD32_WAKEUP_B = (1U << 28), + WAKE_SRC_R12_CPU_IRQ_B = (1U << 29), + WAKE_SRC_R12_APSRC_WAKE = (1U << 30), + WAKE_SRC_R12_APSRC_SLEEP = (1U << 31) +}; + +extern const char *wakesrc_str[32]; + +#endif /* __pcm_def_h__ */ diff --git a/drivers/misc/mediatek/base/power/include/spm_v2/sleep_def_mt6755.h b/drivers/misc/mediatek/base/power/include/spm_v2/sleep_def_mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..ec7d59c6d0fa1fd5062b84f11ed4cc0a87243053 --- /dev/null +++ b/drivers/misc/mediatek/base/power/include/spm_v2/sleep_def_mt6755.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __sleep_def_h__ +#define __sleep_def_h__ + +/* + * Auto generated by DE, please DO NOT modify this file directly. + */ + +/* --- SPM Flag Define --- */ +#define SPM_FLAG_DIS_CPU_PDN (1U << 0) +#define SPM_FLAG_DIS_INFRA_PDN (1U << 1) +#define SPM_FLAG_DIS_DDRPHY_PDN (1U << 2) +#define SPM_FLAG_DIS_VCORE_DVS (1U << 3) +#define SPM_FLAG_DIS_VCORE_DFS (1U << 4) +#define SPM_FLAG_DIS_DPD (1U << 5) +#define SPM_FLAG_DIS_BUS_CLOCK_OFF (1U << 6) +#define SPM_FLAG_DIS_MD_INFRA_PDN (1U << 7) +#define SPM_FLAG_KEEP_CSYSPWRUPACK_HIGH (1U << 8) +#define SPM_FLAG_DIS_VPROC_VSRAM_DVS (1U << 9) +#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10) +#define SPM_FLAG_EN_MET_DBG_FOR_VCORE_DVFS (1U << 11) +#define SPM_FLAG_SODI_CG_MODE (1U << 12) +#define SPM_FLAG_SODI_NO_EVENT (1U << 13) +#define SPM_FLAG_ENABLE_SODI3 (1U << 14) +#define SPM_FLAG_DIS_SRCCLKEN_LOW (1U << 15) +#define SPM_FLAG_DIS_SYSRAM_SLEEP (1U << 16) +#define SPM_FLAG_EN_HPM_SODI (1U << 17) +#define SPM_FLAG_DIS_MCDI_FLOW (1U << 18) +#define SPM_FLAG_IS_COTSX (1U << 19) +#define SPM_FLAG_EN_NFC_CLOCK_BUF_CTRL (1U << 20) +#define SPM_FLAG_EN_CONN_CLOCK_BUF_CTRL (1U << 21) +#define SPM_FLAG_EN_E2_SDIO_SOLUTION (1U << 22) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT23 (1U << 23) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT24 (1U << 24) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT25 (1U << 25) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT26 (1U << 26) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT27 (1U << 27) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT28 (1U << 28) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT29 (1U << 29) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT30 (1U << 30) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT31 (1U << 31) +/* --- SPM DEBUG Define --- */ +#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0) +#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1) +#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2) +#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3) +#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4) +#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5) +#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6) +#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7) +#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8) +#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9) +#define SPM_DBG_DEBUG_IDX_NFC_CKBUF_ON (1U << 10) +#define SPM_DBG_DEBUG_IDX_NFC_CKBUF_OFF (1U << 11) +#define SPM_DBG_DEBUG_IDX_CPU_PDN (1U << 12) +#define SPM_DBG_DEBUG_IDX_DPD (1U << 13) +#define SPM_DBG_DEBUG_IDX_CONN_CKBUF_ON (1U << 14) +#define SPM_DBG_DEBUG_IDX_CONN_CKBUF_OFF (1U << 15) +#define SPM_DBG_DEBUG_IDX_VCORE_DVFS_START (1U << 16) +#define SPM_DBG_RESERVED_BIT17 (1U << 17) +#define SPM_DBG_RESERVED_BIT18 (1U << 18) +#define SPM_DBG_RESERVED_BIT19 (1U << 19) +#define SPM_DBG_RESERVED_BIT20 (1U << 20) +#define SPM_DBG_RESERVED_BIT21 (1U << 21) +#define SPM_DBG_RESERVED_BIT22 (1U << 22) +#define SPM_DBG_RESERVED_BIT23 (1U << 23) +#define SPM_DBG_RESERVED_BIT24 (1U << 24) +#define SPM_DBG_RESERVED_BIT25 (1U << 25) +#define SPM_DBG_RESERVED_BIT26 (1U << 26) +#define SPM_DBG_RESERVED_BIT27 (1U << 27) +#define SPM_DBG_RESERVED_BIT28 (1U << 28) +#define SPM_DBG_RESERVED_BIT29 (1U << 29) +#define SPM_DBG_RESERVED_BIT30 (1U << 30) +#define SPM_DBG_RESERVED_BIT31 (1U << 31) + +/* + * Macro and Inline + */ +#define is_cpu_pdn(flags) (!((flags) & SPM_FLAG_DIS_CPU_PDN)) +#define is_infra_pdn(flags) (!((flags) & SPM_FLAG_DIS_INFRA_PDN)) +#define is_ddrphy_pdn(flags) (!((flags) & SPM_FLAG_DIS_DDRPHY_PDN)) + +#endif /* __sleep_def_h__ */ diff --git a/drivers/misc/mediatek/base/power/mt6755/Makefile b/drivers/misc/mediatek/base/power/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..62af83550b3bb26d5146f6efcfbf76b5b20a49a0 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/Makefile @@ -0,0 +1,64 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/spm_v2/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/cpuidle_v1/ + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/irq/$(MTK_PLATFORM)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/dramc/$(MTK_PLATFORM)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/thermal/fakeHeader/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/video/$(MTK_PLATFORM)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/video/$(MTK_PLATFORM)/videox/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/smi/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/ + +obj-y += mt_pm_init.o +obj-y += mt_clkbuf_ctl.o +obj-y += mt_dcm.o +#obj-y += mt_spm.o +#obj-y += mt_spm_fs.o +#obj-y += mt_spm_internal.o +obj-y += mt_spm_mtcmos.o +#obj-y += mt_pbm.o +obj-$(CONFIG_DEBUG_FS) += mt_clkdbg.o +obj-y += mt_picachu.o +obj-y += mt_static_power.o +obj-y += mt_cpufreq.o +obj-y += mt_cpufreq_hybrid.o +obj-y += mt_gpufreq.o +obj-y += mt_ptp.o +obj-$(CONFIG_MTK_MT6750TT) += mt_eem_turbo.o + +obj-y += mt_vcorefs_governor.o +obj-y += mt_vcorefs_manager.o + +ifneq ($(CONFIG_ARM64), y) + +obj-y += mt-smp.o +obj-y += hotplug.o +obj-y += mt-headsmp.o +obj-y += mt_hotplug.o + +else + +obj-$(CONFIG_MTK_PSCI) += mt_psci.o + +endif + +obj-y += mt_hotplug_strategy_main.o +obj-y += mt_hotplug_strategy_core.o +obj-y += mt_hotplug_strategy_procfs.o +obj-y += mt_hotplug_strategy_cpu.o +obj-y += mt_hotplug_strategy_api.o +obj-y += mt_hotplug_strategy_algo.o diff --git a/drivers/misc/mediatek/base/power/mt6755/hotplug.c b/drivers/misc/mediatek/base/power/mt6755/hotplug.c new file mode 100644 index 0000000000000000000000000000000000000000..d76ffdaca18831dce206ab8889653b4c327b74c4 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/hotplug.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * 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 +#include +#include +#include + +#include "mt-smp.h" +#include "smp.h" +#include "hotplug.h" + +atomic_t hotplug_cpu_count = ATOMIC_INIT(1); + +static inline void cpu_enter_lowpower(unsigned int cpu) +{ + if (((cpu == 4) && (cpu_online(5) == 0) && (cpu_online(6) == 0) + && (cpu_online(7) == 0)) || ((cpu == 5) && (cpu_online(4) == 0) + && (cpu_online(6) == 0) + && (cpu_online(7) == 0)) + || ((cpu == 6) && (cpu_online(4) == 0) && (cpu_online(5) == 0) + && (cpu_online(7) == 0)) || ((cpu == 7) && (cpu_online(4) == 0) + && (cpu_online(5) == 0) + && (cpu_online(6) == 0))) { + __disable_dcache__inner_flush_dcache_L1__inner_flush_dcache_L2 + (); + + /* Switch the processor from SMP mode to AMP mode by clearing + the ACTLR SMP bit */ + __switch_to_amp(); + + /* Execute an ISB instruction to ensure that all of the CP15 + register changes from the previous steps have been + committed */ + isb(); + + /* Execute a DSB instruction to ensure that all cache, TLB + and branch predictor maintenance operations issued by any + processor in the multiprocessor device before the SMP bit + was cleared have completed */ + mb(); + + /* Disable snoop requests and DVM message requests */ + REG_WRITE((void *)CCI400_SI3_SNOOP_CONTROL, + readl((void *)CCI400_SI3_SNOOP_CONTROL) & + ~(SNOOP_REQ | DVM_MSG_REQ)); + while (readl((void *)CCI400_STATUS) & CHANGE_PENDING) + ; + + /* Disable CA15L snoop function */ + REG_WRITE((void *)MP1_AXI_CONFIG, + readl((void *)MP1_AXI_CONFIG) | ACINACTM); + } else { + __disable_dcache__inner_flush_dcache_L1__inner_clean_dcache_L2 + (); + + /* Execute a CLREX instruction */ + __asm__ __volatile__("clrex"); + + /* Switch the processor from SMP mode to AMP mode by + clearing the ACTLR SMP bit */ + __switch_to_amp(); + } +} + +static inline void cpu_leave_lowpower(unsigned int cpu) +{ + if (((cpu == 4) && (cpu_online(5) == 0) && (cpu_online(6) == 0) + && (cpu_online(7) == 0)) || ((cpu == 5) && (cpu_online(4) == 0) + && (cpu_online(6) == 0) + && (cpu_online(7) == 0)) + || ((cpu == 6) && (cpu_online(4) == 0) && (cpu_online(5) == 0) + && (cpu_online(7) == 0)) || ((cpu == 7) && (cpu_online(4) == 0) + && (cpu_online(5) == 0) + && (cpu_online(6) == 0))) { + /* Enable CA15L snoop function */ + REG_WRITE((void *)MP1_AXI_CONFIG, + readl((void *)MP1_AXI_CONFIG) & ~ACINACTM); + + /* Enable snoop requests and DVM message requests */ + REG_WRITE((void *)CCI400_SI3_SNOOP_CONTROL, + readl((void *)CCI400_SI3_SNOOP_CONTROL) | + (SNOOP_REQ | DVM_MSG_REQ)); + while (readl((void *)CCI400_STATUS) & CHANGE_PENDING) + ; + } + + /* Set the ACTLR.SMP bit to 1 for SMP mode */ + __switch_to_smp(); + + /* Enable dcache */ + __enable_dcache(); +} + +static inline void platform_do_lowpower(unsigned int cpu, int *spurious) +{ + /* Just enter wfi for now. TODO: Properly shut off the cpu. */ + for (;;) { + + /* Execute an ISB instruction to ensure that all of the CP15 + register changes from the previous steps have been + committed */ + isb(); + + /* Execute a DSB instruction to ensure that all cache, TLB and + branch predictor maintenance operations issued by any + processor in the multiprocessor device before the SMP bit + was cleared have completed */ + mb(); + + /* + * here's the WFI + */ + __asm__ __volatile__("wfi"); + + if (pen_release == cpu) { + /* + * OK, proper wakeup, we're done + */ + break; + } + + /* + * Getting here, means that we have come out of WFI without + * having been woken up - this shouldn't happen + * + * Just note it happening - when we're woken, we can report + * its occurrence. + */ + (*spurious)++; + } +} + +/* + * mt_cpu_kill: + * @cpu: + * Return TBD. + */ +int mt_cpu_kill(unsigned int cpu) +{ + HOTPLUG_INFO("mt_cpu_kill, cpu: %d\n", cpu); + +#ifdef CONFIG_HOTPLUG_WITH_POWER_CTRL + switch (cpu) { + case 0: + spm_mtcmos_ctrl_cpu0(STA_POWER_DOWN, 1); + break; + case 1: + spm_mtcmos_ctrl_cpu1(STA_POWER_DOWN, 1); + break; + case 2: + spm_mtcmos_ctrl_cpu2(STA_POWER_DOWN, 1); + break; + case 3: + spm_mtcmos_ctrl_cpu3(STA_POWER_DOWN, 1); + break; + case 4: + spm_mtcmos_ctrl_cpu4(STA_POWER_DOWN, 1); + break; + case 5: + spm_mtcmos_ctrl_cpu5(STA_POWER_DOWN, 1); + break; + case 6: + spm_mtcmos_ctrl_cpu6(STA_POWER_DOWN, 1); + break; + case 7: + spm_mtcmos_ctrl_cpu7(STA_POWER_DOWN, 1); + break; + default: + break; + } +#endif + atomic_dec(&hotplug_cpu_count); + + return 1; +} + +/* + * mt_cpu_die: shutdown a CPU + * @cpu: + */ +void mt_cpu_die(unsigned int cpu) +{ + int spurious = 0; + + HOTPLUG_INFO("mt_cpu_die, cpu: %d\n", cpu); + /* + * we're ready for shutdown now, so do it + */ + cpu_enter_lowpower(cpu); + platform_do_lowpower(cpu, &spurious); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + cpu_leave_lowpower(cpu); + + if (spurious) + HOTPLUG_INFO( + "spurious wakeup call, cpu: %d, spurious: %d\n", + cpu, spurious); +} + +/* + * mt_cpu_disable: + * @cpu: + * Return error code. + */ +int mt_cpu_disable(unsigned int cpu) +{ + /* + * we don't allow CPU 0 to be shutdown (it is still too special + * e.g. clock tick interrupts) + */ + HOTPLUG_INFO("mt_cpu_disable, cpu: %d\n", cpu); + + return 0; +} diff --git a/drivers/misc/mediatek/base/power/mt6755/hotplug.h b/drivers/misc/mediatek/base/power/mt6755/hotplug.h new file mode 100644 index 0000000000000000000000000000000000000000..c679fe7cf862dca64a569e01c4774cd12e5d5db5 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/hotplug.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * 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. + */ +#ifndef _HOTPLUG +#define _HOTPLUG + +#include +#include + +#define BOOTROM_BASE (0x00000000) +#define BOOTSRAM_BASE (0x00100000) + +#define CCI400_BASE (0xF0390000) +#define INFRACFG_AO_BASE (0xF0001000) +#define MCUCFG_BASE (0xF0200000) + +/* log */ +#define HOTPLUG_LOG_NONE 0 +#define HOTPLUG_LOG_WITH_DEBUG 1 +#define HOTPLUG_LOG_WITH_WARN 2 + +#define HOTPLUG_LOG_PRINT HOTPLUG_LOG_WITH_WARN + +#if (HOTPLUG_LOG_PRINT == HOTPLUG_LOG_NONE) +#define HOTPLUG_INFO(fmt, args...) +#elif (HOTPLUG_LOG_PRINT == HOTPLUG_LOG_WITH_DEBUG) +#define HOTPLUG_INFO(fmt, args...) pr_debug("[Power/hotplug] "fmt, ##args) +#elif (HOTPLUG_LOG_PRINT == HOTPLUG_LOG_WITH_WARN) +#define HOTPLUG_INFO(fmt, args...) pr_warn("[Power/hotplug] "fmt, ##args) +#endif + +/* profilling */ +/* #define CONFIG_HOTPLUG_PROFILING */ +#define CONFIG_HOTPLUG_PROFILING_COUNT 100 + +/* register address - bootrom power*/ +#define BOOTROM_BOOT_ADDR (INFRACFG_AO_BASE + 0x800) +#define BOOTROM_SEC_CTRL (INFRACFG_AO_BASE + 0x804) +#define SW_ROM_PD (1U << 31) + +/* register address - CCI400 */ +#define CCI400_STATUS (CCI400_BASE + 0x000C) +#define CHANGE_PENDING (1U << 0) +#define CCI400_SI4_BASE (CCI400_BASE + 0x5000) +#define CCI400_SI4_SNOOP_CONTROL (CCI400_SI4_BASE) +#define CCI400_SI3_BASE (CCI400_BASE + 0x4000) +#define CCI400_SI3_SNOOP_CONTROL (CCI400_SI3_BASE) +#define DVM_MSG_REQ (1U << 1) +#define SNOOP_REQ (1U << 0) + +/* register address - acinactm */ +#define MP0_AXI_CONFIG (MCUCFG_BASE + 0x02C) +#define MP1_AXI_CONFIG (MCUCFG_BASE + 0x22C) +#define ACINACTM (1U << 4) + +/* register address - aa64naa32 */ +#define MP0_MISC_CONFIG3 (MCUCFG_BASE + 0x03C) +#define MP1_MISC_CONFIG3 (MCUCFG_BASE + 0x23C) + +#define REG_WRITE(addr, value) mt_reg_sync_writel(value, addr) + +/* power on/off cpu*/ +#define CONFIG_HOTPLUG_WITH_POWER_CTRL + +/* global variable */ +extern atomic_t hotplug_cpu_count; + +extern void __disable_dcache(void); +extern void __enable_dcache(void); +extern void __inner_clean_dcache_L2(void); +extern void inner_dcache_flush_L1(void); +extern void inner_dcache_flush_L2(void); +extern void __switch_to_smp(void); +extern void __switch_to_amp(void); +extern void __disable_dcache__inner_flush_dcache_L1(void); +extern void +__disable_dcache__inner_flush_dcache_L1__inner_clean_dcache_L2(void); +extern void +__disable_dcache__inner_flush_dcache_L1__inner_flush_dcache_L2(void); + +/* mt cpu hotplug callback for smp_operations */ +extern int mt_cpu_kill(unsigned int cpu); +extern void mt_cpu_die(unsigned int cpu); +extern int mt_cpu_disable(unsigned int cpu); + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt-headsmp.S b/drivers/misc/mediatek/base/power/mt6755/mt-headsmp.S new file mode 100644 index 0000000000000000000000000000000000000000..3f0179e5ec65288e052c7fc88b009416209c2646 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt-headsmp.S @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + + __CPUINIT + +CCI400_SI3_SNOOP_CONTROL: + .long 0x10394000 +CCI400_STATUS: + .long 0x1039000C +MP1_AXI_CONFIG: + .long 0x1020022C + +ENTRY(mt_secondary_startup) +/* + MRRC p15, 1, r0, r1, c15 @ read cpu extended control register + ORR r0, r0, #0x040 + MCRR p15, 1, r0, r1, c15 @ write cpu extended control register + DSB + ISB +*/ + +/* CONFIG_ARM_ERRATA_836870, prevent software livelock */ + mrc p15, 0, r9, c0, c0, 0 @ MIDR + movw r10, #0xfff0 + movt r10, #0xff0f + and r9, r10 + movw r10, #0xD030 + movt r10, #0x410F + teq r9, r10 + bne 1f + + mrrc p15, 0, r0, r1, c15 @ Read CPU Auxiliary Control Register + orr r0, r0, #0x01000000 @ set CPUACTLR[24] = 1 + mcrr p15, 0, r0, r1, c15 @ Write CPU Auxiliary Control Register + dsb + isb +1: + mrc p15, 0, r0, c0, c0, 5 @ MPIDR + ubfx r0, r0, #8, #4 @ Cluster Id + cmp r0, #0 @ Cluster 1 + beq cluster0 + ldr r2, MP1_AXI_CONFIG + ldr r1, [r2] + bic r1, r1, #0x10 + str r1, [r2] + ldr r2, CCI400_SI3_SNOOP_CONTROL + ldr r1, [r2] + orr r1, r1, #0x3 + str r1, [r2] + ldr r2, CCI400_STATUS + b 1f +0: + dsb +1: + ldr r1, [r2] + tst r1, #1 + bne 0b +cluster0: + b secondary_startup +END(mt_secondary_startup) + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt-smp.c b/drivers/misc/mediatek/base/power/mt6755/mt-smp.c new file mode 100644 index 0000000000000000000000000000000000000000..4327ed5ff2e55537e5288ce88a4d2932573c5e2e --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt-smp.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mt-smp.h" +#include "smp.h" +#include "hotplug.h" + +#define SLAVE1_MAGIC_REG (SRAMROM_BASE+0x38) +#define SLAVE2_MAGIC_REG (SRAMROM_BASE+0x38) +#define SLAVE3_MAGIC_REG (SRAMROM_BASE+0x38) +#define SLAVE4_MAGIC_REG (SRAMROM_BASE+0x3C) +#define SLAVE5_MAGIC_REG (SRAMROM_BASE+0x3C) +#define SLAVE6_MAGIC_REG (SRAMROM_BASE+0x3C) +#define SLAVE7_MAGIC_REG (SRAMROM_BASE+0x3C) + +#define SLAVE1_MAGIC_NUM 0x534C4131 +#define SLAVE2_MAGIC_NUM 0x4C415332 +#define SLAVE3_MAGIC_NUM 0x41534C33 +#define SLAVE4_MAGIC_NUM 0x534C4134 +#define SLAVE5_MAGIC_NUM 0x4C415335 +#define SLAVE6_MAGIC_NUM 0x41534C36 +#define SLAVE7_MAGIC_NUM 0x534C4137 + +#define SLAVE_JUMP_REG (SRAMROM_BASE+0x34) + +static DEFINE_SPINLOCK(boot_lock); + +/* + * Write pen_release in a way that is guaranteed to be visible to all + * observers, irrespective of whether they're taking part in coherency + * or not. This is necessary for the hotplug code to work reliably. + */ +static void __cpuinit write_pen_release(int val) +{ + pen_release = val; + /* Make sure this is visible to other CPUs */ + smp_wmb(); + /* sync_cache_w(&pen_release); */ + __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); + outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); +} + +void __cpuinit mt_smp_secondary_init(unsigned int cpu) +{ + /*pr_debug("Slave cpu init\n"); + HOTPLUG_INFO("platform_secondary_init, cpu: %d\n", cpu);*/ +#ifndef CONFIG_MTK_GIC + mt_gic_secondary_init(); +#endif + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + write_pen_release(-1); + +#if !defined(CONFIG_ARM_PSCI) + fiq_glue_resume(); +#endif + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +#define MT6735_INFRACFG_AO 0x10001000 + +static void __init smp_set_boot_addr(void) +{ + static void __iomem *infracfg_ao_base; + + infracfg_ao_base = ioremap(MT6735_INFRACFG_AO, 0x1000); + + if (!infracfg_ao_base) + pr_err("%s: Unable to map I/O memory\n", __func__); + + /* Write the address of slave startup into boot address + register for bootrom power down mode */ + + writel_relaxed(virt_to_phys(mt_secondary_startup), + infracfg_ao_base + 0x800); + + iounmap(infracfg_ao_base); +} + +int __cpuinit mt_smp_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /*pr_crit("Boot slave CPU\n");*/ + + atomic_inc(&hotplug_cpu_count); + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /*HOTPLUG_INFO("mt_smp_boot_secondary, cpu: %d\n", cpu);*/ + /* + * The secondary processor is waiting to be released from + * the holding pen - release it, then wait for it to flag + * that it has been released by resetting pen_release. + * + * Note that "pen_release" is the hardware CPU ID, whereas + * "cpu" is Linux's internal ID. + */ + /* + * This is really belt and braces; we hold unintended secondary + * CPUs in the holding pen until we're ready for them. However, + * since we haven't sent them a soft interrupt, they shouldn't + * be there. + */ + write_pen_release(cpu); + + switch (cpu) { + case 0: +#ifdef CONFIG_MTK_FPGA + mt_reg_sync_writel(SLAVE0_MAGIC_NUM, SLAVE0_MAGIC_REG); + HOTPLUG_INFO("SLAVE0_MAGIC_NUM:%x\n", SLAVE0_MAGIC_NUM); +#endif + spm_mtcmos_ctrl_cpu0(STA_POWER_ON, 1); + break; + case 1: +#ifdef CONFIG_MTK_FPGA + mt_reg_sync_writel(SLAVE1_MAGIC_NUM, SLAVE1_MAGIC_REG); + HOTPLUG_INFO("SLAVE1_MAGIC_NUM:%x\n", SLAVE1_MAGIC_NUM); +#endif + spm_mtcmos_ctrl_cpu1(STA_POWER_ON, 1); + break; + case 2: +#ifdef CONFIG_MTK_FPGA + mt_reg_sync_writel(SLAVE2_MAGIC_NUM, SLAVE2_MAGIC_REG); + HOTPLUG_INFO("SLAVE2_MAGIC_NUM:%x\n", SLAVE2_MAGIC_NUM); +#endif + spm_mtcmos_ctrl_cpu2(STA_POWER_ON, 1); + break; + case 3: +#ifdef CONFIG_MTK_FPGA + mt_reg_sync_writel(SLAVE3_MAGIC_NUM, SLAVE3_MAGIC_REG); + HOTPLUG_INFO("SLAVE3_MAGIC_NUM:%x\n", SLAVE3_MAGIC_NUM); +#endif + spm_mtcmos_ctrl_cpu3(STA_POWER_ON, 1); + break; + + case 4: + #ifdef CONFIG_MTK_FPGA + mt_reg_sync_writel(SLAVE4_MAGIC_NUM, SLAVE4_MAGIC_REG); + HOTPLUG_INFO("SLAVE4_MAGIC_NUM:%x\n", SLAVE4_MAGIC_NUM); + #endif + spm_mtcmos_ctrl_cpu4(STA_POWER_ON, 1); + break; + + case 5: + if ((cpu_online(4) == 0) && (cpu_online(6) == 0) && + (cpu_online(7) == 0)) { + HOTPLUG_INFO("up CPU%d fail, CPU4 first\n", cpu); + spin_unlock(&boot_lock); + atomic_dec(&hotplug_cpu_count); + return -ENOSYS; + } + #ifdef CONFIG_MTK_FPGA + mt_reg_sync_writel(SLAVE5_MAGIC_NUM, SLAVE5_MAGIC_REG); + HOTPLUG_INFO("SLAVE5_MAGIC_NUM:%x\n", SLAVE5_MAGIC_NUM); + #endif + spm_mtcmos_ctrl_cpu5(STA_POWER_ON, 1); + break; + + case 6: + if ((cpu_online(4) == 0) && (cpu_online(5) == 0) && + (cpu_online(7) == 0)) { + HOTPLUG_INFO("up CPU%d fail, CPU4 first\n", cpu); + spin_unlock(&boot_lock); + atomic_dec(&hotplug_cpu_count); + return -ENOSYS; + } + #ifdef CONFIG_MTK_FPGA + mt_reg_sync_writel(SLAVE6_MAGIC_NUM, SLAVE6_MAGIC_REG); + HOTPLUG_INFO("SLAVE6_MAGIC_NUM:%x\n", SLAVE6_MAGIC_NUM); + #endif + spm_mtcmos_ctrl_cpu6(STA_POWER_ON, 1); + break; + + case 7: + if ((cpu_online(4) == 0) && (cpu_online(5) == 0) && + (cpu_online(6) == 0)) { + HOTPLUG_INFO("up CPU%d fail, CPU4 first\n", cpu); + spin_unlock(&boot_lock); + atomic_dec(&hotplug_cpu_count); + return -ENOSYS; + } + #ifdef CONFIG_MTK_FPGA + mt_reg_sync_writel(SLAVE7_MAGIC_NUM, SLAVE7_MAGIC_REG); + HOTPLUG_INFO("SLAVE7_MAGIC_NUM:%x\n", SLAVE7_MAGIC_NUM); + #endif + spm_mtcmos_ctrl_cpu7(STA_POWER_ON, 1); + break; + + default: + break; + + } + + /* + * Now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + /* */ + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + if (pen_release != -1) { + on_each_cpu((smp_call_func_t) dump_stack, NULL, 0); + atomic_dec(&hotplug_cpu_count); + return -ENOSYS; + } + return 0; +} + +void __init mt_smp_init_cpus(void) +{ + /* Enable CA7 snoop function */ +#if defined(CONFIG_ARM_PSCI) || defined(CONFIG_MTK_PSCI) + mcusys_smc_write_phy(virt_to_phys((void *)MP0_AXI_CONFIG), + readl((void *)MP0_AXI_CONFIG) & ~ACINACTM); +#else + mcusys_smc_write(MP0_AXI_CONFIG, readl(MP0_AXI_CONFIG) & ~ACINACTM); +#endif + + /* Enable snoop requests and DVM message requests */ + REG_WRITE((void *)CCI400_SI4_SNOOP_CONTROL, + readl((void *)CCI400_SI4_SNOOP_CONTROL) | (SNOOP_REQ | + DVM_MSG_REQ)); + while (readl((void *)CCI400_STATUS) & CHANGE_PENDING) + ; + + pr_emerg("@@@### num_possible_cpus(): %u ###@@@\n", + num_possible_cpus()); + pr_emerg("@@@### num_present_cpus(): %u ###@@@\n", num_present_cpus()); +#ifndef CONFIG_MTK_GIC + irq_total_secondary_cpus = num_possible_cpus() - 1; +#endif +} + +void __init mt_smp_prepare_cpus(unsigned int max_cpus) +{ +#if !defined(CONFIG_ARM_PSCI) + +#ifdef CONFIG_MTK_FPGA + /* write the address of slave startup into the system-wide + flags register */ + mt_reg_sync_writel(virt_to_phys(mt_secondary_startup), SLAVE_JUMP_REG); +#endif + + /* Set all cpus into AArch32 */ + mcusys_smc_write(MP0_MISC_CONFIG3, + readl(MP0_MISC_CONFIG3) & 0xFFFF0FFF); + mcusys_smc_write(MP1_MISC_CONFIG3, + readl(MP1_MISC_CONFIG3) & 0xFFFF0FFF); + + /* enable bootrom power down mode */ + REG_WRITE(BOOTROM_SEC_CTRL, readl(BOOTROM_SEC_CTRL) | SW_ROM_PD); + + /* write the address of slave startup into boot address register + for bootrom power down mode */ + mt_reg_sync_writel(virt_to_phys(mt_secondary_startup), + BOOTROM_BOOT_ADDR); +#endif + /* set boot address */ + smp_set_boot_addr(); + + /* initial spm_mtcmos memory map */ + spm_mtcmos_cpu_init(); +} + +struct smp_operations __initdata mt_smp_ops = { + .smp_init_cpus = mt_smp_init_cpus, + .smp_prepare_cpus = mt_smp_prepare_cpus, + .smp_secondary_init = mt_smp_secondary_init, + .smp_boot_secondary = mt_smp_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_kill = mt_cpu_kill, + .cpu_die = mt_cpu_die, + .cpu_disable = mt_cpu_disable, +#endif +}; diff --git a/drivers/misc/mediatek/base/power/mt6755/mt-smp.h b/drivers/misc/mediatek/base/power/mt6755/mt-smp.h new file mode 100644 index 0000000000000000000000000000000000000000..1a3450393f41cfb6eb4a00b038bb7b1acedb0d62 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt-smp.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * 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. + */ + +extern void mt_secondary_startup(void); +extern void mt_gic_secondary_init(void); +extern unsigned int irq_total_secondary_cpus; + +extern void __init mt_smp_prepare_cpus(unsigned int max_cpus); +extern void mt_smp_secondary_init(unsigned int cpu); +extern int mt_smp_boot_secondary(unsigned int cpu, struct task_struct *idle); +extern int mt_cpu_kill(unsigned int cpu); + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_clkbuf_ctl.c b/drivers/misc/mediatek/base/power/mt6755/mt_clkbuf_ctl.c new file mode 100644 index 0000000000000000000000000000000000000000..3f0f0effd921ab61ecc0df807b32c7f11ab2d450 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_clkbuf_ctl.c @@ -0,0 +1,1102 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @file mt_clk_buf_ctl.c + * @brief Driver for RF clock buffer control + * + */ + +#define __MT_CLK_BUF_CTL_C__ + +/* + * Include files + */ + +/* system includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +/* #include */ +/* #include */ +#include "mt_clkbuf_ctl.h" +#include + +#define TAG "[Power/clkbuf]" + +#define clk_buf_err(fmt, args...) pr_err(TAG fmt, ##args) +#define clk_buf_warn(fmt, args...) pr_warn(TAG fmt, ##args) +#define clk_buf_warn_limit(fmt, args...) pr_warn_ratelimited(TAG fmt, ##args) +#define clk_buf_dbg(fmt, args...) \ + do { \ + if (clkbuf_debug) \ + pr_warn(TAG fmt, ##args); \ + } while (0) + +/* + * LOCK + */ +DEFINE_MUTEX(clk_buf_ctrl_lock); + +#define DEFINE_ATTR_RO(_name) \ +static struct kobj_attribute _name##_attr = { \ + .attr = { \ + .name = #_name, \ + .mode = 0444, \ + }, \ + .show = _name##_show, \ +} + +#define DEFINE_ATTR_RW(_name) \ +static struct kobj_attribute _name##_attr = { \ + .attr = { \ + .name = #_name, \ + .mode = 0644, \ + }, \ + .show = _name##_show, \ + .store = _name##_store, \ +} + +#define __ATTR_OF(_name) (&_name##_attr.attr) + +#define clkbuf_readl(addr) __raw_readl(addr) +#define clkbuf_writel(addr, val) mt_reg_sync_writel(val, addr) + +static void __iomem *pwrap_base; + +#define PWRAP_REG(ofs) (pwrap_base + ofs) + +#define DCXO_ENABLE PWRAP_REG(0x18C) +#define DCXO_CONN_ADR0 PWRAP_REG(0x190) +#define DCXO_CONN_WDATA0 PWRAP_REG(0x194) +#define DCXO_CONN_ADR1 PWRAP_REG(0x198) +#define DCXO_CONN_WDATA1 PWRAP_REG(0x19C) +#define DCXO_NFC_ADR0 PWRAP_REG(0x1A0) +#define DCXO_NFC_WDATA0 PWRAP_REG(0x1A4) +#define DCXO_NFC_ADR1 PWRAP_REG(0x1A8) +#define DCXO_NFC_WDATA1 PWRAP_REG(0x1AC) +#define HARB_SLEEP_GATED_CTRL PWRAP_REG(0x1F0) + +#define DCXO_CONN_ENABLE (1U << 1) +#define DCXO_NFC_ENABLE (1U << 0) +#define HARB_SLEEP_GATED_EN (1U << 0) + +#define DCXO_EXTBUF_EN_M 0 +#define DCXO_EN_BB 1 +#define DCXO_CLK_SEL 2 +#define DCXO_EN_BB_OR_CLK_SEL 3 + +#define PMIC_REG_MASK 0xFFFF +#define PMIC_REG_SHIFT 0 + +#define PMIC_CW00_ADDR 0x7000 +#define PMIC_CW00_INIT_VAL 0x4DFD +#define PMIC_CW00_XO_EXTBUF2_MODE_MASK 0x3 +#define PMIC_CW00_XO_EXTBUF2_MODE_SHIFT 3 +#define PMIC_CW00_XO_EXTBUF2_EN_M_MASK 0x1 +#define PMIC_CW00_XO_EXTBUF2_EN_M_SHIFT 5 +#define PMIC_CW00_XO_EXTBUF3_MODE_MASK 0x3 +#define PMIC_CW00_XO_EXTBUF3_MODE_SHIFT 6 +#define PMIC_CW00_XO_BB_LPM_EN_MASK 0x1 +#define PMIC_CW00_XO_BB_LPM_EN_SHIFT 12 + +/* + * 0x701A CW13 Code Word 13 + * 15:14 RG_XO_EXTBUF4_ISET XO Control Signal of Current on EXTBUF4 + * 13:12 RG_XO_EXTBUF4_HD XO Control Signal of EXTBUF4 Output driving Strength + * 11:10 RG_XO_EXTBUF3_ISET XO Control Signal of Current on EXTBUF3 + * 9:8 RG_XO_EXTBUF3_HD XO Control Signal of EXTBUF3 Output driving Strength + * 7:6 RG_XO_EXTBUF2_ISET XO Control Signal of Current on EXTBUF2 + * 5:4 RG_XO_EXTBUF2_HD XO Control Signal of EXTBUF2 Output driving Strength + * 3:2 RG_XO_EXTBUF1_ISET XO Control Signal of Current on EXTBUF1 + * 1:0 RG_XO_EXTBUF1_HD XO Control Signal of EXTBUF1 Output driving Strength + */ +#define PMIC_CW13_ADDR 0x701A +#define PMIC_CW13_SUGGEST_VAL 0x4666 +#define PMIC_CW13_DEFAULT_VAL 0x8AAA +#define PMIC_CW13_XO_EXTBUF_HD_VAL ((0x2 << 0) | (0x2 << 4) \ + | (0x2 << 8) | (0 << 12)) + +#define PMIC_CW14_ADDR 0x701C +#define PMIC_CW14_XO_EXTBUF3_EN_M_MASK 0x1 +#define PMIC_CW14_XO_EXTBUF3_EN_M_SHIFT 11 + +#define PMIC_CW15_ADDR 0x701E +#define PMIC_CW15_DCXO_STATIC_AUXOUT_EN_MASK 0x1 +#define PMIC_CW15_DCXO_STATIC_AUXOUT_EN_SHIFT 0 +#define PMIC_CW15_DCXO_STATIC_AUXOUT_SEL_MASK 0xF +#define PMIC_CW15_DCXO_STATIC_AUXOUT_SEL_SHIFT 1 + +/* FIXME: only for bring up Co-TSX before DT is ready */ +/* #define CLKBUF_COTSX_BRINGUP */ + +static bool is_clkbuf_initiated; +static bool g_is_flightmode_on; +static bool clkbuf_debug; + +struct delayed_work clkbuf_delayed_work; + +/* false: rf_clkbuf, true: pmic_clkbuf */ +static bool is_pmic_clkbuf; + +static unsigned int afcdac_val = 0x2A80008; /* afc_default=4096 */ +static bool is_clkbuf_afcdac_updated; +static unsigned int bblpm_cnt; + +static unsigned int g_pmic_cw13_rg_val = PMIC_CW13_DEFAULT_VAL; +/* FIXME: Before MP, using suggested driving current to test. */ +/* #define TEST_SUGGEST_RF_DRIVING_CURR_BEFORE_MP */ +/* #define TEST_SUGGEST_PMIC_DRIVING_CURR_BEFORE_MP */ + +#if !defined(CONFIG_MTK_LEGACY) +static unsigned int CLK_BUF1_STATUS, CLK_BUF2_STATUS, + CLK_BUF3_STATUS, CLK_BUF4_STATUS, + CLK_BUF5_STATUS_PMIC = CLOCK_BUFFER_HW_CONTROL, + CLK_BUF6_STATUS_PMIC = CLOCK_BUFFER_SW_CONTROL, + CLK_BUF7_STATUS_PMIC = CLOCK_BUFFER_SW_CONTROL, + CLK_BUF8_STATUS_PMIC = CLOCK_BUFFER_HW_CONTROL; +static unsigned int RF_CLK_BUF1_DRIVING_CURR = CLK_BUF_DRIVING_CURR_1_4MA, + RF_CLK_BUF2_DRIVING_CURR = CLK_BUF_DRIVING_CURR_1_4MA, + RF_CLK_BUF3_DRIVING_CURR = CLK_BUF_DRIVING_CURR_1_4MA, + RF_CLK_BUF4_DRIVING_CURR = CLK_BUF_DRIVING_CURR_1_4MA; +static unsigned int PMIC_CLK_BUF5_DRIVING_CURR = CLK_BUF_DRIVING_CURR_1_4MA, + PMIC_CLK_BUF6_DRIVING_CURR = CLK_BUF_DRIVING_CURR_1_4MA, + PMIC_CLK_BUF7_DRIVING_CURR = CLK_BUF_DRIVING_CURR_1_4MA, + PMIC_CLK_BUF8_DRIVING_CURR = CLK_BUF_DRIVING_CURR_1_4MA; +#else /* CONFIG_MTK_LEGACY */ +/* FIXME: can be removed after DCT tool gen is ready */ +#if !defined(RF_CLK_BUF1_DRIVING_CURR) +#define RF_CLK_BUF1_DRIVING_CURR CLK_BUF_DRIVING_CURR_1_4MA +#define RF_CLK_BUF2_DRIVING_CURR CLK_BUF_DRIVING_CURR_1_4MA +#define RF_CLK_BUF3_DRIVING_CURR CLK_BUF_DRIVING_CURR_1_4MA +#define RF_CLK_BUF4_DRIVING_CURR CLK_BUF_DRIVING_CURR_1_4MA +#endif +#if !defined(PMIC_CLK_BUF5_DRIVING_CURR) +#define PMIC_CLK_BUF5_DRIVING_CURR CLK_BUF_DRIVING_CURR_1_4MA +#define PMIC_CLK_BUF6_DRIVING_CURR CLK_BUF_DRIVING_CURR_1_4MA +#define PMIC_CLK_BUF7_DRIVING_CURR CLK_BUF_DRIVING_CURR_1_4MA +#define PMIC_CLK_BUF8_DRIVING_CURR CLK_BUF_DRIVING_CURR_1_4MA +#endif + +#ifdef CLKBUF_COTSX_BRINGUP +#undef CLK_BUF1_STATUS +#undef CLK_BUF2_STATUS +#undef CLK_BUF3_STATUS +#undef CLK_BUF4_STATUS +#undef CLK_BUF5_STATUS_PMIC +#undef CLK_BUF6_STATUS_PMIC +#undef CLK_BUF7_STATUS_PMIC +#undef CLK_BUF8_STATUS_PMIC + +#define CLK_BUF1_STATUS CLOCK_BUFFER_DISABLE +#define CLK_BUF2_STATUS CLOCK_BUFFER_DISABLE +#define CLK_BUF3_STATUS CLOCK_BUFFER_DISABLE +#define CLK_BUF4_STATUS CLOCK_BUFFER_DISABLE +#define CLK_BUF5_STATUS_PMIC CLOCK_BUFFER_HW_CONTROL +#define CLK_BUF6_STATUS_PMIC CLOCK_BUFFER_SW_CONTROL +#define CLK_BUF7_STATUS_PMIC CLOCK_BUFFER_SW_CONTROL +#define CLK_BUF8_STATUS_PMIC CLOCK_BUFFER_HW_CONTROL +#endif +#endif /* CONFIG_MTK_LEGACY */ + +#if 1 +static CLK_BUF_SWCTRL_STATUS_T clk_buf_swctrl[CLKBUF_NUM] = { +#ifdef CLKBUF_COTSX_BRINGUP + CLK_BUF_SW_DISABLE, + CLK_BUF_SW_DISABLE, + CLK_BUF_SW_DISABLE, + CLK_BUF_SW_DISABLE +#else + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_DISABLE, + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_DISABLE +#endif +}; + +static CLK_BUF_SWCTRL_STATUS_T clk_buf_swctrl_modem_on[CLKBUF_NUM] = { + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_DISABLE, + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_ENABLE +}; +#else /* For Bring-up */ +static CLK_BUF_SWCTRL_STATUS_T clk_buf_swctrl[CLKBUF_NUM] = { + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_ENABLE +}; +#endif + +static CLK_BUF_SWCTRL_STATUS_T pmic_clk_buf_swctrl[CLKBUF_NUM] = { + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_ENABLE, + CLK_BUF_SW_ENABLE +}; + +static void spm_clk_buf_ctrl(CLK_BUF_SWCTRL_STATUS_T *status) +{ + u32 spm_val; + int i; + + spm_val = spm_read(SPM_MDBSI_CON) & ~0x7; + + for (i = 1; i < CLKBUF_NUM; i++) + spm_val |= status[i] << (i - 1); + + spm_write(SPM_MDBSI_CON, spm_val); + + udelay(2); +} + +static void pmic_clk_buf_ctrl(CLK_BUF_SWCTRL_STATUS_T *status) +{ +#ifndef CONFIG_MTK_PMIC_CHIP_MT6353 /* MT6351 */ + u32 conn_conf = 0, nfc_conf = 0; + + pmic_config_interface(PMIC_CW00_ADDR, (status[PMIC_CLK_BUF_CONN] % 2), + PMIC_CW00_XO_EXTBUF2_EN_M_MASK, + PMIC_CW00_XO_EXTBUF2_EN_M_SHIFT); + pmic_config_interface(PMIC_CW14_ADDR, (status[PMIC_CLK_BUF_NFC] % 2), + PMIC_CW14_XO_EXTBUF3_EN_M_MASK, + PMIC_CW14_XO_EXTBUF3_EN_M_SHIFT); + + pmic_read_interface(PMIC_CW00_ADDR, &conn_conf, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_read_interface(PMIC_CW14_ADDR, &nfc_conf, + PMIC_REG_MASK, PMIC_REG_SHIFT); + clk_buf_dbg("%s: CW00=0x%x, CW14=0x%x, clkbuf2=%u, clkbuf3=%u\n", + __func__, conn_conf, nfc_conf, + status[PMIC_CLK_BUF_CONN], + status[PMIC_CLK_BUF_NFC]); +#else /* MT6353 */ + u32 pmic_cw00 = 0; + + if (status[PMIC_CLK_BUF_CONN] % 2) + pmic_config_interface(PMIC_DCXO_CW00_SET_ADDR, 0x1, + PMIC_XO_EXTBUF2_EN_M_MASK, + PMIC_XO_EXTBUF2_EN_M_SHIFT); + else + pmic_config_interface(PMIC_DCXO_CW00_CLR_ADDR, 0x1, + PMIC_XO_EXTBUF2_EN_M_MASK, + PMIC_XO_EXTBUF2_EN_M_SHIFT); + if (status[PMIC_CLK_BUF_NFC] % 2) + pmic_config_interface(PMIC_DCXO_CW00_SET_ADDR, 0x1, + PMIC_XO_EXTBUF3_EN_M_MASK, + PMIC_XO_EXTBUF3_EN_M_SHIFT); + else + pmic_config_interface(PMIC_DCXO_CW00_CLR_ADDR, 0x1, + PMIC_XO_EXTBUF3_EN_M_MASK, + PMIC_XO_EXTBUF3_EN_M_SHIFT); + + pmic_read_interface(MT6353_DCXO_CW00, &pmic_cw00, + PMIC_REG_MASK, PMIC_REG_SHIFT); + clk_buf_dbg("%s: CW00=0x%x, clkbuf2=%u, clkbuf3=%u\n", + __func__, pmic_cw00, status[PMIC_CLK_BUF_CONN], + status[PMIC_CLK_BUF_NFC]); +#endif +} + +/* + * Baseband Low Power Mode (BBLPM) for PMIC clkbuf + * Condition: flightmode on + conn mtcmos off + NFC clkbuf off + enter deepidle + * Caller: deep idle + */ +void clk_buf_control_bblpm(bool on) +{ + u32 cw00 = 0; + + if (!is_pmic_clkbuf || + (pmic_clk_buf_swctrl[PMIC_CLK_BUF_NFC] == CLK_BUF_SW_ENABLE)) + return; + +#ifndef CONFIG_MTK_PMIC_CHIP_MT6353 /* MT6351 */ + pmic_config_interface_nolock(PMIC_CW00_ADDR, (on ? 1 : 0), + PMIC_CW00_XO_BB_LPM_EN_MASK, + PMIC_CW00_XO_BB_LPM_EN_SHIFT); + + pmic_read_interface_nolock(PMIC_CW00_ADDR, &cw00, + PMIC_REG_MASK, PMIC_REG_SHIFT); +#else /* MT6353 */ + if (on) { /* FPM -> BBLPM */ + pmic_config_interface_nolock(MT6353_DCXO_CW02, 0x2AEA, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_config_interface_nolock(MT6353_DCXO_CW10, 0x0FD0, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_config_interface_nolock(PMIC_DCXO_CW00_SET_ADDR, 0x1, + PMIC_XO_BB_LPM_EN_MASK, + PMIC_XO_BB_LPM_EN_SHIFT); + udelay(60); + pmic_config_interface_nolock(MT6353_DCXO_CW01, 0xBD55, + PMIC_REG_MASK, PMIC_REG_SHIFT); + } else { /* BBLPM -> FPM */ + pmic_config_interface_nolock(MT6353_DCXO_CW01, 0xED55, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_config_interface_nolock(PMIC_DCXO_CW00_CLR_ADDR, 0x1, + PMIC_XO_BB_LPM_EN_MASK, + PMIC_XO_BB_LPM_EN_SHIFT); + udelay(75); + pmic_config_interface_nolock(MT6353_DCXO_CW10, 0xEF50, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_config_interface_nolock(MT6353_DCXO_CW02, 0x3AEA, + PMIC_REG_MASK, PMIC_REG_SHIFT); + } + + pmic_read_interface_nolock(MT6353_DCXO_CW00, &cw00, + PMIC_REG_MASK, PMIC_REG_SHIFT); +#endif + bblpm_cnt++; + + clk_buf_dbg("%s(%u): CW00=0x%x\n", __func__, (on ? 1 : 0), cw00); +} + +static void clkbuf_delayed_worker(struct work_struct *work) +{ + bool srcclkena_o1 = false; + + srcclkena_o1 = !!(spm_read(PCM_REG13_DATA) & R13_MD1_VRF18_REQ); + clk_buf_warn("%s: g_is_flightmode_on=%d, srcclkena_o1=%u, pcm_reg13=0x%x\n", + __func__, g_is_flightmode_on, srcclkena_o1, + spm_read(PCM_REG13_DATA)); + + BUG_ON(clkbuf_debug && g_is_flightmode_on && srcclkena_o1); + + mutex_lock(&clk_buf_ctrl_lock); + + if (g_is_flightmode_on) + spm_clk_buf_ctrl(clk_buf_swctrl); + + mutex_unlock(&clk_buf_ctrl_lock); +} + +/* for spm driver use */ +bool is_clk_buf_under_flightmode(void) +{ + return g_is_flightmode_on; +} + +/* for ccci driver to notify this */ +void clk_buf_set_by_flightmode(bool is_flightmode_on) +{ + bool srcclkena_o1 = false; + + srcclkena_o1 = !!(spm_read(PCM_REG13_DATA) & R13_MD1_VRF18_REQ); + clk_buf_warn("%s: g/is_flightmode_on=%d->%d, srcclkena_o1=%u, pcm_reg13=0x%x\n", + __func__, g_is_flightmode_on, is_flightmode_on, + srcclkena_o1, spm_read(PCM_REG13_DATA)); + + mutex_lock(&clk_buf_ctrl_lock); + + if (g_is_flightmode_on == is_flightmode_on) { + mutex_unlock(&clk_buf_ctrl_lock); + return; + } + + g_is_flightmode_on = is_flightmode_on; + + if (!is_pmic_clkbuf) { + if (g_is_flightmode_on) { + schedule_delayed_work(&clkbuf_delayed_work, + msecs_to_jiffies(2000)); + /* spm_clk_buf_ctrl(clk_buf_swctrl); */ + } else { + cancel_delayed_work(&clkbuf_delayed_work); + spm_clk_buf_ctrl(clk_buf_swctrl_modem_on); + } + } + + mutex_unlock(&clk_buf_ctrl_lock); +} + +bool clk_buf_ctrl(enum clk_buf_id id, bool onoff) +{ + if (is_pmic_clkbuf) { + mutex_lock(&clk_buf_ctrl_lock); + + /* record the status of NFC from caller for checking BBLPM */ + if (id == CLK_BUF_NFC) + pmic_clk_buf_swctrl[id] = onoff; + + mutex_unlock(&clk_buf_ctrl_lock); + + clk_buf_dbg("%s: id=%d, onoff=%d, is_flightmode_on=%d\n", + __func__, id, onoff, g_is_flightmode_on); + + return false; + } + + if (id >= CLK_BUF_INVALID) /* TODO: need check DCT tool for CLK BUF SW control */ + return false; + + if ((id == CLK_BUF_BB_MD) && (CLK_BUF1_STATUS == CLOCK_BUFFER_HW_CONTROL)) + return false; + + if ((id == CLK_BUF_CONN) && (CLK_BUF2_STATUS == CLOCK_BUFFER_HW_CONTROL)) + return false; + + if ((id == CLK_BUF_NFC) && (CLK_BUF3_STATUS == CLOCK_BUFFER_HW_CONTROL)) + return false; + + if ((id == CLK_BUF_AUDIO) && (CLK_BUF4_STATUS == CLOCK_BUFFER_HW_CONTROL)) + return false; + +#if 0 + /* for bring-up */ + clk_buf_warn("clk_buf_ctrl is disabled for bring-up\n"); + return false; +#endif + clk_buf_dbg("%s: id=%d, onoff=%d, is_flightmode_on=%d\n", __func__, + id, onoff, g_is_flightmode_on); + + mutex_lock(&clk_buf_ctrl_lock); + + clk_buf_swctrl[id] = onoff; + + if (g_is_flightmode_on) + spm_clk_buf_ctrl(clk_buf_swctrl); + + mutex_unlock(&clk_buf_ctrl_lock); + + return true; +} + +void clk_buf_get_swctrl_status(CLK_BUF_SWCTRL_STATUS_T *status) +{ + int i; + + clk_buf_warn("%s: is_flightmode_on=%d, swctrl:clkbuf3=%d/%d, clkbuf4=%d/%d\n", + __func__, g_is_flightmode_on, + clk_buf_swctrl[2], clk_buf_swctrl_modem_on[2], + clk_buf_swctrl[3], clk_buf_swctrl_modem_on[3]); + + for (i = 0; i < CLKBUF_NUM; i++) { + if (g_is_flightmode_on) + status[i] = clk_buf_swctrl[i]; + else + status[i] = clk_buf_swctrl_modem_on[i]; + } +} + +/* + * Let caller get driving current setting of RF clock buffer + * Caller: ccci & ccci will send it to modem + */ +void clk_buf_get_rf_drv_curr(void *rf_drv_curr) +{ +#ifdef TEST_SUGGEST_RF_DRIVING_CURR_BEFORE_MP + RF_CLK_BUF1_DRIVING_CURR = CLK_BUF_DRIVING_CURR_0_9MA, + RF_CLK_BUF2_DRIVING_CURR = CLK_BUF_DRIVING_CURR_0_9MA, + RF_CLK_BUF3_DRIVING_CURR = CLK_BUF_DRIVING_CURR_0_9MA, + RF_CLK_BUF4_DRIVING_CURR = CLK_BUF_DRIVING_CURR_0_9MA; +#endif + + ((MTK_CLK_BUF_DRIVING_CURR *)rf_drv_curr)[0] = RF_CLK_BUF1_DRIVING_CURR; + ((MTK_CLK_BUF_DRIVING_CURR *)rf_drv_curr)[1] = RF_CLK_BUF2_DRIVING_CURR; + ((MTK_CLK_BUF_DRIVING_CURR *)rf_drv_curr)[2] = RF_CLK_BUF3_DRIVING_CURR; + ((MTK_CLK_BUF_DRIVING_CURR *)rf_drv_curr)[3] = RF_CLK_BUF4_DRIVING_CURR; + + clk_buf_warn("%s: rf_drv_curr_vals=%d %d %d %d\n", __func__, + ((MTK_CLK_BUF_DRIVING_CURR *)rf_drv_curr)[0], + ((MTK_CLK_BUF_DRIVING_CURR *)rf_drv_curr)[1], + ((MTK_CLK_BUF_DRIVING_CURR *)rf_drv_curr)[2], + ((MTK_CLK_BUF_DRIVING_CURR *)rf_drv_curr)[3]); +} + +/* Called by ccci driver to keep afcdac value sent from modem */ +void clk_buf_save_afc_val(unsigned int afcdac) +{ + if (is_pmic_clkbuf) + return; + + afcdac_val = afcdac; + + if (!is_clkbuf_afcdac_updated) { + spm_write(SPM_BSI_EN_SR, afcdac_val); + is_clkbuf_afcdac_updated = true; + } + + clk_buf_dbg("%s: afcdac=0x%x, SPM_BSI_EN_SR=0x%x\n", __func__, + afcdac_val, spm_read(SPM_BSI_EN_SR)); +} + +/* Called by suspend driver to write afcdac into SPM register */ +void clk_buf_write_afcdac(void) +{ + if (is_pmic_clkbuf) + return; + + spm_write(SPM_BSI_EN_SR, afcdac_val); + clk_buf_dbg("%s: afcdac=0x%x, SPM_BSI_EN_SR=0x%x, afcdac_updated=%d\n", + __func__, afcdac_val, spm_read(SPM_BSI_EN_SR), + is_clkbuf_afcdac_updated); +} + +static ssize_t clk_buf_ctrl_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + /* design for BSI or PMIC wrapper command */ + u32 clk_buf_en[CLKBUF_NUM], i; + char cmd[32]; + + if (sscanf(buf, "%31s %x %x %x %x", cmd, &clk_buf_en[0], &clk_buf_en[1], + &clk_buf_en[2], &clk_buf_en[3]) != 5) + return -EPERM; + + if (!strcmp(cmd, "bsi")) { + if (is_pmic_clkbuf) + return -EINVAL; + + mutex_lock(&clk_buf_ctrl_lock); + + for (i = 0; i < CLKBUF_NUM; i++) + clk_buf_swctrl[i] = clk_buf_en[i]; + + if (g_is_flightmode_on) + spm_clk_buf_ctrl(clk_buf_swctrl); + + mutex_unlock(&clk_buf_ctrl_lock); + + return count; + } + + if (!strcmp(cmd, "pmic")) { + if (!is_pmic_clkbuf) + return -EINVAL; + + for (i = 0; i < CLKBUF_NUM; i++) + pmic_clk_buf_swctrl[i] = clk_buf_en[i]; + + pmic_clk_buf_ctrl(pmic_clk_buf_swctrl); + + return count; + } + + return -EINVAL; +} + +static ssize_t clk_buf_ctrl_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + int len = 0; + bool srcclkena_o1 = false; + + len += snprintf(buf+len, PAGE_SIZE-len, + "********** RF clock buffer state (%s) flightmode(FM)=%d **********\n", + (is_pmic_clkbuf ? "off" : "on"), g_is_flightmode_on); + len += snprintf(buf+len, PAGE_SIZE-len, + "CKBUF1_BB SW(1)/HW(2) CTL: %d, Dis(0)/En(1) of FM=1:%d, FM=0:%d\n", + CLK_BUF1_STATUS, clk_buf_swctrl[0], + clk_buf_swctrl_modem_on[0]); + len += snprintf(buf+len, PAGE_SIZE-len, + "CKBUF2_NONE SW(1)/HW(2) CTL: %d, Dis(0)/En(1) of FM=1:%d, FM=0:%d\n", + CLK_BUF2_STATUS, clk_buf_swctrl[1], + clk_buf_swctrl_modem_on[1]); + len += snprintf(buf+len, PAGE_SIZE-len, + "CKBUF3_NFC SW(1)/HW(2) CTL: %d, Dis(0)/En(1) of FM=1:%d, FM=0:%d\n", + CLK_BUF3_STATUS, clk_buf_swctrl[2], + clk_buf_swctrl_modem_on[2]); + len += snprintf(buf+len, PAGE_SIZE-len, + "CKBUF4_AUD SW(1)/HW(2) CTL: %d, Dis(0)/En(1) of FM=1:%d, FM=0:%d\n", + CLK_BUF4_STATUS, clk_buf_swctrl[3], + clk_buf_swctrl_modem_on[3]); + len += snprintf(buf+len, PAGE_SIZE-len, + "********** PMIC clock buffer state (%s) **********\n", + (is_pmic_clkbuf ? "on" : "off")); + len += snprintf(buf+len, PAGE_SIZE-len, + "CKBUF1_BB SW(1)/HW(2) CTL: %d, Dis(0)/En(1): %d\n", + CLK_BUF5_STATUS_PMIC, pmic_clk_buf_swctrl[0]); + len += snprintf(buf+len, PAGE_SIZE-len, + "CKBUF2_CONN SW(1)/HW(2) CTL: %d, Dis(0)/En(1): %d\n", + CLK_BUF6_STATUS_PMIC, pmic_clk_buf_swctrl[1]); + len += snprintf(buf+len, PAGE_SIZE-len, + "CKBUF3_NFC SW(1)/HW(2) CTL: %d, Dis(0)/En(1): %d\n", + CLK_BUF7_STATUS_PMIC, pmic_clk_buf_swctrl[2]); + len += snprintf(buf+len, PAGE_SIZE-len, + "CKBUF4_RF SW(1)/HW(2) CTL: %d, Dis(0)/En(1): %d\n", + CLK_BUF8_STATUS_PMIC, pmic_clk_buf_swctrl[3]); + len += snprintf(buf+len, PAGE_SIZE-len, + "\n********** clock buffer command help **********\n"); + len += snprintf(buf+len, PAGE_SIZE-len, + "BSI switch on/off: echo bsi en1 en2 en3 en4 > /sys/power/clk_buf/clk_buf_ctrl\n"); + len += snprintf(buf+len, PAGE_SIZE-len, + "PMIC switch on/off: echo pmic en1 en2 en3 en4 > /sys/power/clk_buf/clk_buf_ctrl\n"); + if (is_pmic_clkbuf) + len += snprintf(buf+len, PAGE_SIZE-len, + "g_pmic_cw13_rg_val=0x%x, bblpm_cnt=%u\n", + g_pmic_cw13_rg_val, bblpm_cnt); + else + len += snprintf(buf+len, PAGE_SIZE-len, + "afcdac=0x%x, is_afcdac_updated=%d\n", + afcdac_val, is_clkbuf_afcdac_updated); + len += snprintf(buf+len, PAGE_SIZE-len, + "rf_drv_curr_vals=%d %d %d %d, pmic_drv_curr_vals=%d %d %d %d\n", + RF_CLK_BUF1_DRIVING_CURR, RF_CLK_BUF2_DRIVING_CURR, + RF_CLK_BUF3_DRIVING_CURR, RF_CLK_BUF4_DRIVING_CURR, + PMIC_CLK_BUF5_DRIVING_CURR, PMIC_CLK_BUF6_DRIVING_CURR, + PMIC_CLK_BUF7_DRIVING_CURR, PMIC_CLK_BUF8_DRIVING_CURR); + srcclkena_o1 = !!(spm_read(PCM_REG13_DATA) & R13_MD1_VRF18_REQ); + len += snprintf(buf+len, PAGE_SIZE-len, + "srcclkena_o1=%u, pcm_reg13=0x%x, MD1_PWR_CON=0x%x, C2K_PWR_CON=0x%x\n", + srcclkena_o1, spm_read(PCM_REG13_DATA), + spm_read(MD1_PWR_CON), spm_read(C2K_PWR_CON)); + + return len; +} + +static ssize_t clk_buf_debug_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int debug = 0; + + if (!kstrtoint(buf, 10, &debug)) { + if (debug == 0) + clkbuf_debug = false; + else if (debug == 1) + clkbuf_debug = true; + else + clk_buf_warn("bad argument!! should be 0 or 1 [0: disable, 1: enable]\n"); + } else + return -EPERM; + + return count; +} + +static ssize_t clk_buf_debug_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + int len = 0; + + len += snprintf(buf+len, PAGE_SIZE-len, "clkbuf_debug=%d\n", clkbuf_debug); + + return len; +} + +DEFINE_ATTR_RW(clk_buf_ctrl); +DEFINE_ATTR_RW(clk_buf_debug); + +static struct attribute *clk_buf_attrs[] = { + /* for clock buffer control */ + __ATTR_OF(clk_buf_ctrl), + __ATTR_OF(clk_buf_debug), + + /* must */ + NULL, +}; + +static struct attribute_group spm_attr_group = { + .name = "clk_buf", + .attrs = clk_buf_attrs, +}; + +bool is_clk_buf_from_pmic(void) +{ + unsigned int reg = 0; + bool ret = false; + + if (is_clkbuf_initiated) + return is_pmic_clkbuf; + +#ifndef CONFIG_MTK_PMIC_CHIP_MT6353 /* MT6351 */ + /* switch to debug mode */ + pmic_config_interface_nolock(PMIC_CW15_ADDR, 0x1, + PMIC_CW15_DCXO_STATIC_AUXOUT_EN_MASK, + PMIC_CW15_DCXO_STATIC_AUXOUT_EN_SHIFT); + pmic_config_interface_nolock(PMIC_CW15_ADDR, 0x3, + PMIC_CW15_DCXO_STATIC_AUXOUT_SEL_MASK, + PMIC_CW15_DCXO_STATIC_AUXOUT_SEL_SHIFT); + /* bit 6, 7, 8, 9 => 32K Less Mode, Buffer Mode, RTC Mode, Off Mode */ + pmic_read_interface_nolock(PMIC_CW00_ADDR, ®, + PMIC_REG_MASK, PMIC_REG_SHIFT); + /* switch back from debug mode */ + pmic_config_interface_nolock(PMIC_CW15_ADDR, 0x0, + PMIC_CW15_DCXO_STATIC_AUXOUT_EN_MASK, + PMIC_CW15_DCXO_STATIC_AUXOUT_EN_SHIFT); + if ((reg & 0x200) == 0x200) { + clk_buf_warn_limit("clkbuf is from RF, CW00=0x%x\n", reg); + ret = false; + } else { + clk_buf_warn_limit("clkbuf is from PMIC, CW00=0x%x\n", reg); + ret = true; + } +#else /* MT6353 */ + pmic_config_interface_nolock(MT6353_DCXO_CW15, 0x18, + PMIC_REG_MASK, PMIC_REG_SHIFT); + /* bit 10, 11, 12, 13 => 32K Less Mode, Buffer Mode, RTC Mode, Off Mode */ + pmic_read_interface_nolock(PMIC_XO_STATIC_AUXOUT_ADDR, ®, + PMIC_XO_STATIC_AUXOUT_MASK, + PMIC_XO_STATIC_AUXOUT_SHIFT); + if ((reg & 0x2000) == 0x2000) { + clk_buf_warn_limit("clkbuf is from RF, DCXO_CW16=0x%x\n", reg); + ret = false; + } else { + clk_buf_warn_limit("clkbuf is from PMIC, DCXO_CW16=0x%x\n", reg); + ret = true; + } +#endif + return ret; +}; + +static void gen_pmic_cw13_rg_val(void) +{ +#ifdef TEST_SUGGEST_PMIC_DRIVING_CURR_BEFORE_MP + g_pmic_cw13_rg_val = PMIC_CW13_SUGGEST_VAL; +#else + g_pmic_cw13_rg_val = PMIC_CW13_XO_EXTBUF_HD_VAL | + (PMIC_CLK_BUF5_DRIVING_CURR << 2) | + (PMIC_CLK_BUF6_DRIVING_CURR << 6) | + (PMIC_CLK_BUF7_DRIVING_CURR << 10) | + (PMIC_CLK_BUF8_DRIVING_CURR << 14); +#endif + + clk_buf_warn("%s: g_pmic_cw13_rg_val=0x%x, pmic_drv_curr_vals=%d %d %d %d\n", + __func__, g_pmic_cw13_rg_val, + PMIC_CLK_BUF5_DRIVING_CURR, + PMIC_CLK_BUF6_DRIVING_CURR, + PMIC_CLK_BUF7_DRIVING_CURR, + PMIC_CLK_BUF8_DRIVING_CURR); +} + +static void clk_buf_pmic_wrap_init(void) +{ +#ifndef CONFIG_MTK_PMIC_CHIP_MT6353 /* MT6351 */ + u32 conn_conf = 0, nfc_conf = 0; +#else + u32 pmic_cw00 = 0; +#endif + u32 pmic_cw13 = 0; + + gen_pmic_cw13_rg_val(); +#ifndef CONFIG_MTK_PMIC_CHIP_MT6353 /* MT6351 */ +#if 0 /* debug only */ + /* Switch clkbuf2,3 to S/W mode control */ + pmic_config_interface(PMIC_CW00_ADDR, 0, + PMIC_CW00_XO_EXTBUF2_MODE_MASK, + PMIC_CW00_XO_EXTBUF2_MODE_SHIFT); /* XO_WCN */ + pmic_config_interface(PMIC_CW00_ADDR, 0, + PMIC_CW00_XO_EXTBUF3_MODE_MASK, + PMIC_CW00_XO_EXTBUF3_MODE_SHIFT); /* XO_NFC */ +#else + /* Setup initial PMIC clock buffer setting */ + pmic_read_interface(PMIC_CW00_ADDR, &conn_conf, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_read_interface(PMIC_CW14_ADDR, &nfc_conf, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_read_interface(PMIC_CW13_ADDR, &pmic_cw13, + PMIC_REG_MASK, PMIC_REG_SHIFT); + clk_buf_warn("%s PMIC_CW00_ADDR=0x%x, PMIC_CW14_ADDR=0x%x, PMIC_CW13_ADDR=0x%x\n", + __func__, conn_conf, nfc_conf, pmic_cw13); + pmic_config_interface(PMIC_CW00_ADDR, PMIC_CW00_INIT_VAL, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_config_interface(PMIC_CW13_ADDR, g_pmic_cw13_rg_val, + PMIC_REG_MASK, PMIC_REG_SHIFT); +#endif + + /* Check if the setting is ok */ + pmic_read_interface(PMIC_CW00_ADDR, &conn_conf, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_read_interface(PMIC_CW14_ADDR, &nfc_conf, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_read_interface(PMIC_CW13_ADDR, &pmic_cw13, + PMIC_REG_MASK, PMIC_REG_SHIFT); + clk_buf_warn("%s PMIC_CW00_ADDR=0x%x, PMIC_CW14_ADDR=0x%x, PMIC_CW13_ADDR=0x%x\n", + __func__, conn_conf, nfc_conf, pmic_cw13); + + clkbuf_writel(DCXO_CONN_ADR0, PMIC_CW00_ADDR); + clkbuf_writel(DCXO_CONN_WDATA0, conn_conf & 0xFFDF); /* bit5 = 0 */ + clkbuf_writel(DCXO_CONN_ADR1, PMIC_CW00_ADDR); + clkbuf_writel(DCXO_CONN_WDATA1, conn_conf | 0x0020); /* bit5 = 1 */ + clkbuf_writel(DCXO_NFC_ADR0, PMIC_CW14_ADDR); + clkbuf_writel(DCXO_NFC_WDATA0, nfc_conf & 0xF7FF); /* bit11 = 0 */ + clkbuf_writel(DCXO_NFC_ADR1, PMIC_CW14_ADDR); + clkbuf_writel(DCXO_NFC_WDATA1, nfc_conf | 0x0800); /* bit11 = 1 */ +#else /* MT6353 */ + /* Setup initial PMIC clock buffer setting */ + pmic_read_interface(MT6353_DCXO_CW00, &pmic_cw00, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_read_interface(MT6353_DCXO_CW13, &pmic_cw13, + PMIC_REG_MASK, PMIC_REG_SHIFT); + clk_buf_warn("%s PMIC_CW00_ADDR=0x%x, PMIC_CW13_ADDR=0x%x\n", + __func__, pmic_cw00, pmic_cw13); + pmic_config_interface(MT6353_DCXO_CW00, PMIC_CW00_INIT_VAL, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_config_interface(MT6353_DCXO_CW13, g_pmic_cw13_rg_val, + PMIC_REG_MASK, PMIC_REG_SHIFT); + + /* Check if the setting is ok */ + pmic_read_interface(MT6353_DCXO_CW00, &pmic_cw00, + PMIC_REG_MASK, PMIC_REG_SHIFT); + pmic_read_interface(MT6353_DCXO_CW13, &pmic_cw13, + PMIC_REG_MASK, PMIC_REG_SHIFT); + clk_buf_warn("%s PMIC_CW00_ADDR=0x%x, PMIC_CW13_ADDR=0x%x\n", + __func__, pmic_cw00, pmic_cw13); + + clkbuf_writel(DCXO_CONN_ADR0, PMIC_DCXO_CW00_CLR_ADDR); + clkbuf_writel(DCXO_CONN_WDATA0, + PMIC_XO_EXTBUF2_EN_M_MASK << PMIC_XO_EXTBUF2_EN_M_SHIFT); /* bit5 = 0 */ + clkbuf_writel(DCXO_CONN_ADR1, PMIC_DCXO_CW00_SET_ADDR); + clkbuf_writel(DCXO_CONN_WDATA1, + PMIC_XO_EXTBUF2_EN_M_MASK << PMIC_XO_EXTBUF2_EN_M_SHIFT); /* bit5 = 1 */ + clkbuf_writel(DCXO_NFC_ADR0, PMIC_DCXO_CW00_CLR_ADDR); + clkbuf_writel(DCXO_NFC_WDATA0, + PMIC_XO_EXTBUF3_EN_M_MASK << PMIC_XO_EXTBUF3_EN_M_SHIFT); /* bit8 = 0 */ + clkbuf_writel(DCXO_NFC_ADR1, PMIC_DCXO_CW00_SET_ADDR); + clkbuf_writel(DCXO_NFC_WDATA1, + PMIC_XO_EXTBUF3_EN_M_MASK << PMIC_XO_EXTBUF3_EN_M_SHIFT); /* bit8 = 1 */ +#endif + + /* Enable pmic_wrap sleep gated control */ + clkbuf_writel(HARB_SLEEP_GATED_CTRL, HARB_SLEEP_GATED_EN); + + clkbuf_writel(DCXO_ENABLE, DCXO_CONN_ENABLE | DCXO_NFC_ENABLE); + + clk_buf_warn("%s: DCXO_CONN_ADR0/WDATA0/ADR1/WDATA1/EN=0x%x/%x/%x/%x/%x,HSGC=%x\n", + __func__, clkbuf_readl(DCXO_CONN_ADR0), + clkbuf_readl(DCXO_CONN_WDATA0), + clkbuf_readl(DCXO_CONN_ADR1), + clkbuf_readl(DCXO_CONN_WDATA1), + clkbuf_readl(DCXO_ENABLE), + clkbuf_readl(HARB_SLEEP_GATED_CTRL)); + clk_buf_warn("%s: DCXO_NFC_ADR0/WDATA0/ADR1/WDATA1=0x%x/%x/%x/%x\n", + __func__, clkbuf_readl(DCXO_NFC_ADR0), + clkbuf_readl(DCXO_NFC_WDATA0), + clkbuf_readl(DCXO_NFC_ADR1), + clkbuf_readl(DCXO_NFC_WDATA1)); +} + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 /* only for MT6750 */ +static void rf_clk_buf_pmic_wrap_init(void) +{ + u32 ldo_vcn28_con0 = 0; + +#ifndef CONFIG_MTK_PMIC_CHIP_MT6353 /* only for MT6755 */ + /* Read original LDO_VCN28_CON0 value */ + pmic_read_interface(MT6351_LDO_VCN28_CON0, &ldo_vcn28_con0, + PMIC_REG_MASK, PMIC_REG_SHIFT); + + /* setup PMIC WRAP to control VCN28_EN by conn_srcclkena */ + clkbuf_writel(DCXO_CONN_ADR0, MT6351_LDO_VCN28_CON0); + clkbuf_writel(DCXO_CONN_WDATA0, ldo_vcn28_con0 & 0xFFFD); /* falling: bit1 = 0 */ + clkbuf_writel(DCXO_CONN_ADR1, MT6351_LDO_VCN28_CON0); + clkbuf_writel(DCXO_CONN_WDATA1, ldo_vcn28_con0 | 0x0002); /* rising: bit1 = 1 */ +#else + /* Read original LDO_VCN28_CON0 value */ + pmic_read_interface(MT6353_LDO3_VCN28_CON0, &ldo_vcn28_con0, + PMIC_REG_MASK, PMIC_REG_SHIFT); + + /* setup PMIC WRAP to control VCN28_EN by conn_srcclkena */ + clkbuf_writel(DCXO_CONN_ADR0, MT6353_LDO3_VCN28_CON0); + clkbuf_writel(DCXO_CONN_WDATA0, ldo_vcn28_con0 & 0xFFFD); /* falling: bit1 = 0 */ + clkbuf_writel(DCXO_CONN_ADR1, MT6353_LDO3_VCN28_CON0); + clkbuf_writel(DCXO_CONN_WDATA1, ldo_vcn28_con0 | 0x0002); /* rising: bit1 = 1 */ +#endif + + /* Enable pmic_wrap sleep gated control */ + clkbuf_writel(HARB_SLEEP_GATED_CTRL, HARB_SLEEP_GATED_EN); + + /* Enables DCXO conn interface */ + clkbuf_writel(DCXO_ENABLE, DCXO_CONN_ENABLE); + + clk_buf_warn("%s: ldo_vcn28_con0=0x%x,DCXO_CONN_ADR0/WDATA0/ADR1/WDATA1/EN=0x%x/%x/%x/%x/%x,HSGC=%x\n", + __func__, ldo_vcn28_con0, + clkbuf_readl(DCXO_CONN_ADR0), + clkbuf_readl(DCXO_CONN_WDATA0), + clkbuf_readl(DCXO_CONN_ADR1), + clkbuf_readl(DCXO_CONN_WDATA1), + clkbuf_readl(DCXO_ENABLE), + clkbuf_readl(HARB_SLEEP_GATED_CTRL)); +} +#endif + +static int clk_buf_fs_init(void) +{ + int r = 0; + +#if defined(CONFIG_PM) + /* create /sys/power/clk_buf/xxx */ + r = sysfs_create_group(power_kobj, &spm_attr_group); + if (r) + clk_buf_err("FAILED TO CREATE /sys/power/clk_buf (%d)\n", r); +#endif + + return r; +} + +static void clk_buf_clear_rf_setting(void) +{ + memset(clk_buf_swctrl, 0, sizeof(clk_buf_swctrl)); + memset(clk_buf_swctrl_modem_on, 0, sizeof(clk_buf_swctrl_modem_on)); + +#if !defined(CONFIG_MTK_LEGACY) + CLK_BUF1_STATUS = CLOCK_BUFFER_DISABLE; + CLK_BUF2_STATUS = CLOCK_BUFFER_DISABLE; + CLK_BUF3_STATUS = CLOCK_BUFFER_DISABLE; + CLK_BUF4_STATUS = CLOCK_BUFFER_DISABLE; + CLK_BUF5_STATUS_PMIC = CLOCK_BUFFER_HW_CONTROL; + CLK_BUF6_STATUS_PMIC = CLOCK_BUFFER_SW_CONTROL; + CLK_BUF7_STATUS_PMIC = CLOCK_BUFFER_SW_CONTROL; + CLK_BUF8_STATUS_PMIC = CLOCK_BUFFER_HW_CONTROL; + + clk_buf_warn("%s: RF_CLK_BUF?_STATUS=%d %d %d %d\n", __func__, + CLK_BUF1_STATUS, CLK_BUF2_STATUS, + CLK_BUF3_STATUS, CLK_BUF4_STATUS); + clk_buf_warn("%s: PMIC_CLK_BUF?_STATUS=%d %d %d %d\n", __func__, + CLK_BUF5_STATUS_PMIC, CLK_BUF6_STATUS_PMIC, + CLK_BUF7_STATUS_PMIC, CLK_BUF8_STATUS_PMIC); +#endif +} + +bool clk_buf_init(void) +{ + struct device_node *node; +#if !defined(CONFIG_MTK_LEGACY) + u32 vals[CLKBUF_NUM] = {0, 0, 0, 0}; + int ret = -1; + +#if 1 /* for kernel 3.18 */ + node = of_find_compatible_node(NULL, NULL, "mediatek,rf_clock_buffer"); + if (node) { + of_property_read_u32_array(node, "mediatek,clkbuf-config", + vals, CLKBUF_NUM); + CLK_BUF1_STATUS = vals[0]; + CLK_BUF2_STATUS = vals[1]; + CLK_BUF3_STATUS = vals[2]; + CLK_BUF4_STATUS = vals[3]; + ret = of_property_read_u32_array(node, "mediatek,clkbuf-driving-current", + vals, CLKBUF_NUM); + if (!ret) { + RF_CLK_BUF1_DRIVING_CURR = vals[0]; + RF_CLK_BUF2_DRIVING_CURR = vals[1]; + RF_CLK_BUF3_DRIVING_CURR = vals[2]; + RF_CLK_BUF4_DRIVING_CURR = vals[3]; + } + } else { + clk_buf_err("%s can't find compatible node for rf_clock_buffer\n", __func__); + BUG(); + } + + node = of_find_compatible_node(NULL, NULL, "mediatek,pmic_clock_buffer"); + if (node) { + ret = of_property_read_u32_array(node, "mediatek,clkbuf-config", + vals, CLKBUF_NUM); + if (!ret) { + CLK_BUF5_STATUS_PMIC = vals[0]; + CLK_BUF6_STATUS_PMIC = vals[1]; + CLK_BUF7_STATUS_PMIC = vals[2]; + CLK_BUF8_STATUS_PMIC = vals[3]; + } + ret = of_property_read_u32_array(node, "mediatek,clkbuf-driving-current", + vals, CLKBUF_NUM); + if (!ret) { + PMIC_CLK_BUF5_DRIVING_CURR = vals[0]; + PMIC_CLK_BUF6_DRIVING_CURR = vals[1]; + PMIC_CLK_BUF7_DRIVING_CURR = vals[2]; + PMIC_CLK_BUF8_DRIVING_CURR = vals[3]; + } + } else { + clk_buf_err("%s can't find compatible node for pmic_clock_buffer\n", __func__); + BUG(); + } +#else /* for kernel 3.10 */ + node = of_find_compatible_node(NULL, NULL, "mediatek, rf_clock_buffer"); + if (node) { + of_property_read_u32(node, "buffer1", (u32 *)&CLK_BUF1_STATUS); + of_property_read_u32(node, "buffer2", (u32 *)&CLK_BUF2_STATUS); + of_property_read_u32(node, "buffer3", (u32 *)&CLK_BUF3_STATUS); + of_property_read_u32(node, "buffer4", (u32 *)&CLK_BUF4_STATUS); + ret = of_property_read_u32_array(node, "mediatek,clkbuf-driving-current", + vals, CLKBUF_NUM); + if (!ret) { + RF_CLK_BUF1_DRIVING_CURR = vals[0]; + RF_CLK_BUF2_DRIVING_CURR = vals[1]; + RF_CLK_BUF3_DRIVING_CURR = vals[2]; + RF_CLK_BUF4_DRIVING_CURR = vals[3]; + } + } else { + clk_buf_err("%s can't find compatible node for rf_clock_buffer\n", __func__); + BUG_ON(1); + } + + node = of_find_compatible_node(NULL, NULL, "mediatek, pmic_clock_buffer"); + if (node) { + of_property_read_u32(node, "buffer1", (u32 *)&CLK_BUF5_STATUS_PMIC); + of_property_read_u32(node, "buffer2", (u32 *)&CLK_BUF6_STATUS_PMIC); + of_property_read_u32(node, "buffer3", (u32 *)&CLK_BUF7_STATUS_PMIC); + of_property_read_u32(node, "buffer4", (u32 *)&CLK_BUF8_STATUS_PMIC); + ret = of_property_read_u32_array(node, "mediatek,clkbuf-driving-current", vals, CLKBUF_NUM); + if (!ret) { + PMIC_CLK_BUF5_DRIVING_CURR = vals[0]; + PMIC_CLK_BUF6_DRIVING_CURR = vals[1]; + PMIC_CLK_BUF7_DRIVING_CURR = vals[2]; + PMIC_CLK_BUF8_DRIVING_CURR = vals[3]; + } + } else { + clk_buf_err("%s can't find compatible node for pmic_clock_buffer\n", __func__); + BUG_ON(1); + } +#endif +#endif + + if (is_clkbuf_initiated) + return false; + + if (clk_buf_fs_init()) + return false; + + node = of_find_compatible_node(NULL, NULL, "mediatek,pwrap"); + if (node) + pwrap_base = of_iomap(node, 0); + else { + clk_buf_err("%s can't find compatible node for pwrap\n", + __func__); + BUG(); + } + + /* Co-TSX @PMIC */ + if (is_clk_buf_from_pmic()) { + is_pmic_clkbuf = true; + + clk_buf_pmic_wrap_init(); + clk_buf_clear_rf_setting(); + } else { /* VCTCXO @RF */ +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 /* only for MT6750 */ + rf_clk_buf_pmic_wrap_init(); +#endif + + spm_write(SPM_BSI_EN_SR, afcdac_val); + clk_buf_warn("%s: afcdac=0x%x, SPM_BSI_EN_SR=0x%x\n", __func__, + afcdac_val, spm_read(SPM_BSI_EN_SR)); + } + + INIT_DELAYED_WORK(&clkbuf_delayed_work, clkbuf_delayed_worker); + + is_clkbuf_initiated = true; + + return true; +} + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_clkbuf_ctl.h b/drivers/misc/mediatek/base/power/mt6755/mt_clkbuf_ctl.h new file mode 100644 index 0000000000000000000000000000000000000000..a1ac9975bdd763b58e5c540af0df7bc7fa28ea60 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_clkbuf_ctl.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/** +* @file mt_clk_buf_ctl.c +* @brief Driver for RF clock buffer control +* +*/ +#ifndef __MT_CLK_BUF_CTL_H__ +#define __MT_CLK_BUF_CTL_H__ + +#include +#include +#if defined(CONFIG_MTK_LEGACY) +#include +#endif + +#if 1 /*TODO: need add Pad name@DCT tool */ +#ifndef GPIO_RFIC0_BSI_CS +#define GPIO_RFIC0_BSI_CS (GPIO159 | 0x80000000) /* RFIC0_BSI_CS = GPIO159 */ +#endif +#ifndef GPIO_RFIC0_BSI_CK +#define GPIO_RFIC0_BSI_CK (GPIO160 | 0x80000000) /* RFIC0_BSI_CK = GPIO160 */ +#endif +#ifndef GPIO_RFIC0_BSI_D0 +#define GPIO_RFIC0_BSI_D0 (GPIO69 | 0x80000000) /* RFIC0_BSI_D0 = GPIO69 */ +#endif +#ifndef GPIO_RFIC0_BSI_D1 +#define GPIO_RFIC0_BSI_D1 (GPIO68 | 0x80000000) /* RFIC0_BSI_D1 = GPIO68 */ +#endif +#ifndef GPIO_RFIC0_BSI_D2 +#define GPIO_RFIC0_BSI_D2 (GPIO67 | 0x80000000) /* RFIC0_BSI_D2 = GPIO67 */ +#endif +#endif + +enum clk_buf_id { + CLK_BUF_BB_MD = 0, + CLK_BUF_CONN = 1, + CLK_BUF_NFC = 2, + CLK_BUF_AUDIO = 3, + CLK_BUF_INVALID = 4, +}; + +enum pmic_clk_buf_id { + PMIC_CLK_BUF_BB_MD = 0, + PMIC_CLK_BUF_CONN = 1, + PMIC_CLK_BUF_NFC = 2, + PMIC_CLK_BUF_RF = 3, + PMIC_CLK_BUF_INVALID = 4 +}; + +#if !defined(CONFIG_MTK_LEGACY) +typedef enum { + CLOCK_BUFFER_DISABLE = 0, + CLOCK_BUFFER_SW_CONTROL = 1, + CLOCK_BUFFER_HW_CONTROL = 2, +} CLK_BUF_STATUS; + +typedef enum { + CLK_BUF_DRIVING_CURR_0_4MA, + CLK_BUF_DRIVING_CURR_0_9MA, + CLK_BUF_DRIVING_CURR_1_4MA, + CLK_BUF_DRIVING_CURR_1_9MA +} MTK_CLK_BUF_DRIVING_CURR; +#endif + +typedef enum { + CLK_BUF_SW_DISABLE = 0, + CLK_BUF_SW_ENABLE = 1, +} CLK_BUF_SWCTRL_STATUS_T; + +#define CLKBUF_NUM 4 + +#define STA_CLK_ON 1 +#define STA_CLK_OFF 0 + +bool clk_buf_ctrl(enum clk_buf_id id, bool onoff); +void clk_buf_get_swctrl_status(CLK_BUF_SWCTRL_STATUS_T *status); +void clk_buf_get_rf_drv_curr(void *rf_drv_curr); +void clk_buf_set_by_flightmode(bool is_flightmode_on); +void clk_buf_save_afc_val(unsigned int afcdac); +void clk_buf_write_afcdac(void); +void clk_buf_control_bblpm(bool on); +bool clk_buf_init(void); +bool is_clk_buf_under_flightmode(void); +bool is_clk_buf_from_pmic(void); + +extern struct mutex clk_buf_ctrl_lock; +#endif + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_clkdbg.c b/drivers/misc/mediatek/base/power/mt6755/mt_clkdbg.c new file mode 100644 index 0000000000000000000000000000000000000000..66fe27411f5def4591e2946592c55751cfc6b0eb --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_clkdbg.c @@ -0,0 +1,2332 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DUMMY_REG_TEST 0 +#define DUMP_INIT_STATE 0 +#define CLKDBG_PM_DOMAIN 0 +#define CLKDBG_6755 1 +#define CLKDBG_6755_TK 0 +#define CLKDBG_8173 0 + +#define TAG "[clkdbg] " + +#define clk_err(fmt, args...) pr_err(TAG fmt, ##args) +#define clk_warn(fmt, args...) pr_warn(TAG fmt, ##args) +#define clk_info(fmt, args...) pr_debug(TAG fmt, ##args) +#define clk_dbg(fmt, args...) pr_debug(TAG fmt, ##args) +#define clk_ver(fmt, args...) pr_debug(TAG fmt, ##args) + +/************************************************ + ********** register access ********** + ************************************************/ + +#ifndef BIT +#define BIT(_bit_) (u32)(1U << (_bit_)) +#endif + +#ifndef GENMASK +#define GENMASK(h, l) (((1U << ((h) - (l) + 1)) - 1) << (l)) +#endif + +#define ALT_BITS(o, h, l, v) \ + (((o) & ~GENMASK(h, l)) | (((v) << (l)) & GENMASK(h, l))) + +#define clk_readl(addr) readl(addr) +#define clk_writel(addr, val) \ + do { writel(val, addr); wmb(); } while (0) /* sync write */ +#define clk_setl(addr, val) clk_writel(addr, clk_readl(addr) | (val)) +#define clk_clrl(addr, val) clk_writel(addr, clk_readl(addr) & ~(val)) +#define clk_writel_mask(addr, h, l, v) \ + clk_writel(addr, (clk_readl(addr) & ~GENMASK(h, l)) | ((v) << (l))) + +#define ABS_DIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) + +/************************************************ + ********** struct definition ********** + ************************************************/ + +#if CLKDBG_6755 + +static void __iomem *topckgen_base; /* 0x10000000 */ +static void __iomem *infrasys_base; /* 0x10001000 */ +static void __iomem *perisys_base; /* 0x10003000 */ +static void __iomem *mcucfg_base; /* 0x10200000 */ +static void __iomem *apmixedsys_base; /* 0x1000C000 */ +static void __iomem *audiosys_base; /* 0x11220000 */ +static void __iomem *mfgsys_base; /* 0x13000000 */ +static void __iomem *mmsys_base; /* 0x14000000 */ +static void __iomem *imgsys_base; /* 0x15000000 */ +static void __iomem *vdecsys_base; /* 0x16000000 */ +static void __iomem *vencsys_base; /* 0x17000000 */ +static void __iomem *scpsys_base; /* 0x10006000 */ + +#define TOPCKGEN_REG(ofs) (topckgen_base + ofs) +#define INFRA_REG(ofs) (infrasys_base + ofs) +#define PREI_REG(ofs) (perisys_base + ofs) +#define MCUCFG_REG(ofs) (mcucfg_base + ofs) +#define APMIXED_REG(ofs) (apmixedsys_base + ofs) +#define AUDIO_REG(ofs) (audiosys_base + ofs) +#define MFG_REG(ofs) (mfgsys_base + ofs) +#define MM_REG(ofs) (mmsys_base + ofs) +#define IMG_REG(ofs) (imgsys_base + ofs) +#define VDEC_REG(ofs) (vdecsys_base + ofs) +#define VENC_REG(ofs) (vencsys_base + ofs) +#define SCP_REG(ofs) (scpsys_base + ofs) + +#define CLK_MISC_CFG_0 TOPCKGEN_REG(0x104) +#define CLK_MISC_CFG_1 TOPCKGEN_REG(0x108) +#define CLK_DBG_CFG TOPCKGEN_REG(0x10C) +#define CLK26CALI_0 TOPCKGEN_REG(0x220) +#define CLK26CALI_1 TOPCKGEN_REG(0x224) + +#define CLK_CFG_0 TOPCKGEN_REG(0x040) +#define CLK_CFG_1 TOPCKGEN_REG(0x050) +#define CLK_CFG_2 TOPCKGEN_REG(0x060) +#define CLK_CFG_3 TOPCKGEN_REG(0x070) +#define CLK_CFG_4 TOPCKGEN_REG(0x080) +#define CLK_CFG_5 TOPCKGEN_REG(0x090) +#define CLK_CFG_6 TOPCKGEN_REG(0x0A0) +#define CLK_CFG_7 TOPCKGEN_REG(0x0B0) +#define CLK_CFG_8 TOPCKGEN_REG(0x0C0) +#define CLK_CFG_9 TOPCKGEN_REG(0x0D0) + + +/* APMIXEDSYS Register */ + +#define ARMCA15PLL_CON0 APMIXED_REG(0x200) +#define ARMCA15PLL_CON1 APMIXED_REG(0x204) +#define ARMCA15PLL_PWR_CON0 APMIXED_REG(0x20C) + +#define ARMCA7PLL_CON0 APMIXED_REG(0x210) +#define ARMCA7PLL_CON1 APMIXED_REG(0x214) +#define ARMCA7PLL_PWR_CON0 APMIXED_REG(0x21C) + +#define MAINPLL_CON0 APMIXED_REG(0x220) +#define MAINPLL_CON1 APMIXED_REG(0x224) +#define MAINPLL_PWR_CON0 APMIXED_REG(0x22C) + +#define UNIVPLL_CON0 APMIXED_REG(0x230) +#define UNIVPLL_CON1 APMIXED_REG(0x234) +#define UNIVPLL_PWR_CON0 APMIXED_REG(0x23C) + +#define MMPLL_CON0 APMIXED_REG(0x240) +#define MMPLL_CON1 APMIXED_REG(0x244) +#define MMPLL_PWR_CON0 APMIXED_REG(0x24C) + +#define MSDCPLL_CON0 APMIXED_REG(0x250) +#define MSDCPLL_CON1 APMIXED_REG(0x254) +#define MSDCPLL_PWR_CON0 APMIXED_REG(0x25C) + +#define VENCPLL_CON0 APMIXED_REG(0x260) +#define VENCPLL_CON1 APMIXED_REG(0x264) +#define VENCPLL_PWR_CON0 APMIXED_REG(0x26C) + +#define TVDPLL_CON0 APMIXED_REG(0x270) +#define TVDPLL_CON1 APMIXED_REG(0x274) +#define TVDPLL_PWR_CON0 APMIXED_REG(0x27C) + +#define MPLL_CON0 APMIXED_REG(0x280) +#define MPLL_CON1 APMIXED_REG(0x284) +#define MPLL_PWR_CON0 APMIXED_REG(0x28C) + +#define VCODECPLL_CON0 APMIXED_REG(0x290) +#define VCODECPLL_CON1 APMIXED_REG(0x294) +#define VCODECPLL_PWR_CON0 APMIXED_REG(0x29C) + +#define APLL1_CON0 APMIXED_REG(0x2A0) +#define APLL1_CON1 APMIXED_REG(0x2A4) +#define APLL1_PWR_CON0 APMIXED_REG(0x2B0) + +#define APLL2_CON0 APMIXED_REG(0x2B4) +#define APLL2_CON1 APMIXED_REG(0x2B8) +#define APLL2_PWR_CON0 APMIXED_REG(0x2C4) + +/* INFRASYS Register */ + +#define INFRA_TOPCKGEN_DCMCTL INFRA_REG(0x0010) +/* +#define INFRA_PDN_SET INFRA_REG(0x0040) +#define INFRA_PDN_CLR INFRA_REG(0x0044) +#define INFRA_PDN_STA INFRA_REG(0x0048) +*/ +#define INFRA_PDN0_SET INFRA_REG(0x0080) +#define INFRA_PDN0_CLR INFRA_REG(0x0084) +#define INFRA_PDN0_STA INFRA_REG(0x0090) + +#define INFRA_PDN1_SET INFRA_REG(0x0088) +#define INFRA_PDN1_CLR INFRA_REG(0x008C) +#define INFRA_PDN1_STA INFRA_REG(0x0094) + +#define INFRA_PDN2_SET INFRA_REG(0x00A4) +#define INFRA_PDN2_CLR INFRA_REG(0x00A8) +#define INFRA_PDN2_STA INFRA_REG(0x00AC) + +/* Audio Register */ + +#define AUDIO_TOP_CON0 AUDIO_REG(0x0000) + +/* MFGCFG Register */ + +#define MFG_CG_CON MFG_REG(0) +#define MFG_CG_SET MFG_REG(4) +#define MFG_CG_CLR MFG_REG(8) + +/* MMSYS Register */ + +#define DISP_CG_CON0 MM_REG(0x100) +#define DISP_CG_SET0 MM_REG(0x104) +#define DISP_CG_CLR0 MM_REG(0x108) +#define DISP_CG_CON1 MM_REG(0x110) +#define DISP_CG_SET1 MM_REG(0x114) +#define DISP_CG_CLR1 MM_REG(0x118) + +/* IMGSYS Register */ +#define IMG_CG_CON IMG_REG(0x0000) +#define IMG_CG_SET IMG_REG(0x0004) +#define IMG_CG_CLR IMG_REG(0x0008) + +/* VDEC Register */ +#define VDEC_CKEN_SET VDEC_REG(0x0000) +#define VDEC_CKEN_CLR VDEC_REG(0x0004) +#define LARB_CKEN_SET VDEC_REG(0x0008)/*LARB1*/ +#define LARB_CKEN_CLR VDEC_REG(0x000C)/*LARB1*/ + +/* VENC Register */ +#define VENC_CG_CON VENC_REG(0x0) +#define VENC_CG_SET VENC_REG(0x4) +#define VENC_CG_CLR VENC_REG(0x8) + +/* SCPSYS Register */ +#define SPM_VDE_PWR_CON SCP_REG(0x300) +#define SPM_MFG_PWR_CON SCP_REG(0x338) +#define SPM_VEN_PWR_CON SCP_REG(0x304) +#define SPM_ISP_PWR_CON SCP_REG(0x308) +#define SPM_DIS_PWR_CON SCP_REG(0x30C) +#define SPM_AUDIO_PWR_CON SCP_REG(0x314) +#define SPM_MFG_ASYNC_PWR_CON SCP_REG(0x334) +#define SPM_PWR_STATUS SCP_REG(0x180) +#define SPM_PWR_STATUS_2ND SCP_REG(0x184) + +#endif /* CLKDBG_SOC */ + +static bool is_valid_reg(void __iomem *addr) +{ + #ifndef CONFIG_ARM64 + return 1; + #else + return ((u64)addr & 0xf0000000) || (((u64)addr >> 32) & 0xf0000000); + #endif +} + +enum FMETER_TYPE { + ABIST, + CKGEN +}; + +enum ABIST_CLK { + ABIST_CLK_NULL, + +#if CLKDBG_6755 + AD_CSI0_DELAY_TSTCLK = 1, + AD_CSI1_DELAY_TSTCLK = 2, + AD_PSMCUPLL_CK = 3, + AD_L1MCUPLL_CK = 4, + AD_C2KCPPLL_CK = 5, + AD_ICCPLL_CK = 6, + AD_INTFPLL_CK = 7, + AD_MD2GPLL_CK = 8, + AD_IMCPLL_CK = 9, + AD_C2KDSPPLL_CK = 10, + AD_BRPPLL_CK = 11, + AD_DFEPLL_CK = 12, + AD_EQPLL_CK = 13, + AD_CMPPLL_CK = 14, + AD_MDPLLGP_TST_CK = 15, + AD_MDPLL1_FS26M_CK = 16, + AD_MDPLL1_FS208M_CK = 17, + AD_MDPLL1_FS393P216M_CK = 18, + AD_ARMBPLL_1700M_PRO_CK = 19, + AD_ARMBPLL_1700M_CORE_CK = 20, + AD_ARMSPLL_1000M_PRO_CK = 21, + AD_ARMSPLL_1000M_CORE_CK = 22, + AD_MAINPLL_1092M_CK = 23, + AD_UNIVPLL_1248M_CK = 24, + AD_MMPLL_520M_CK = 25, + AD_MSDCPLL_416M_CK = 26, + AD_VENCPLL_286M_CK = 27, + AD_APLL1_180P6336M_CK = 28, + AD_APLL2_196P608M_CK = 29, + AD_APPLLGP_TST_CK = 30, + AD_USB20_48M_CK = 31, + AD_UNIV_48M_CK = 32, + AD_SSUSB_48M_CK = 33, + AD_TVDPLL_594M_CK = 34, + AD_DSI0_MPPLL_TST_CK = 35, + AD_DSI0_LNTC_DSICLK = 36, + AD_MEMPLL_MONCLK = 37, + AD_OSC_CK = 38, + RTC32K_CK_I = 39, + ARMPLL_HD_FARM_CK_BIG = 40, + ARMPLL_HD_FARM_CK_SML = 41, + ARMPLL_HD_FARM_CK_BUS = 42, + MSDC01_IN_CK = 43, + MSDC02_IN_CK = 44, + MSDC11_IN_CK = 45, + MSDC12_IN_CK = 46, + AD_DSI0_DPICLK = 47, +#endif /* CLKDBG_6755 */ + + ABIST_CLK_END, +}; + +static const char * const ABIST_CLK_NAME[] = { +#if CLKDBG_6755 + [AD_CSI0_DELAY_TSTCLK] = "AD_CSI0_DELAY_TSTCLK", + [AD_CSI1_DELAY_TSTCLK] = "AD_CSI1_DELAY_TSTCLK", + [AD_PSMCUPLL_CK] = "AD_PSMCUPLL_CK", + [AD_L1MCUPLL_CK] = "AD_L1MCUPLL_CK", + [AD_C2KCPPLL_CK] = "AD_C2KCPPLL_CK", + [AD_ICCPLL_CK] = "AD_ICCPLL_CK", + [AD_INTFPLL_CK] = "AD_INTFPLL_CK", + [AD_MD2GPLL_CK] = "AD_MD2GPLL_CK", + [AD_IMCPLL_CK] = "AD_IMCPLL_CK", + [AD_C2KDSPPLL_CK] = "AD_C2KDSPPLL_CK", + [AD_BRPPLL_CK] = "AD_BRPPLL_CK", + [AD_DFEPLL_CK] = "AD_DFEPLL_CK", + [AD_EQPLL_CK] = "AD_EQPLL_CK", + [AD_CMPPLL_CK] = "AD_CMPPLL_CK", + [AD_MDPLLGP_TST_CK] = "AD_MDPLLGP_TST_CK", + [AD_MDPLL1_FS26M_CK] = "AD_MDPLL1_FS26M_CK", + [AD_MDPLL1_FS208M_CK] = "AD_MDPLL1_FS208M_CK", + [AD_MDPLL1_FS393P216M_CK] = "AD_MDPLL1_FS393P216M_CK", + [AD_ARMBPLL_1700M_PRO_CK] = "AD_ARMBPLL_1700M_PRO_CK", + [AD_ARMBPLL_1700M_CORE_CK] = "AD_ARMBPLL_1700M_CORE_CK", + [AD_ARMSPLL_1000M_PRO_CK] = "AD_ARMSPLL_1000M_PRO_CK", + [AD_ARMSPLL_1000M_CORE_CK] = "AD_ARMSPLL_1000M_CORE_CK", + [AD_MAINPLL_1092M_CK] = "AD_MAINPLL_1092M_CK", + [AD_UNIVPLL_1248M_CK] = "AD_UNIVPLL_1248M_CK", + [AD_MMPLL_520M_CK] = "AD_MMPLL_520M_CK", + [AD_MSDCPLL_416M_CK] = "AD_MSDCPLL_416M_CK", + [AD_VENCPLL_286M_CK] = "AD_VENCPLL_286M_CK", + [AD_APLL1_180P6336M_CK] = "AD_APLL1_180P6336M_CK", + [AD_APLL2_196P608M_CK] = "AD_APLL2_196P608M_CK", + [AD_APPLLGP_TST_CK] = "AD_APPLLGP_TST_CK", + [AD_USB20_48M_CK] = "AD_USB20_48M_CK", + [AD_UNIV_48M_CK] = "AD_UNIV_48M_CK", + [AD_SSUSB_48M_CK] = "AD_SSUSB_48M_CK", + [AD_TVDPLL_594M_CK] = "AD_TVDPLL_594M_CK", + [AD_DSI0_MPPLL_TST_CK] = "AD_DSI0_MPPLL_TST_CK", + [AD_DSI0_LNTC_DSICLK] = "AD_DSI0_LNTC_DSICLK", + [AD_MEMPLL_MONCLK] = "AD_MEMPLL_MONCLK", + [AD_OSC_CK] = "AD_OSC_CK", + [RTC32K_CK_I] = "rtc32k_ck_i", + [ARMPLL_HD_FARM_CK_BIG] = "armpll_hd_farm_ck_big", + [ARMPLL_HD_FARM_CK_SML] = "armpll_hd_farm_ck_sml", + [ARMPLL_HD_FARM_CK_BUS] = "armpll_hd_farm_ck_bus", + [MSDC01_IN_CK] = "msdc01_in_ck", + [MSDC02_IN_CK] = "msdc02_in_ck", + [MSDC11_IN_CK] = "msdc11_in_ck", + [MSDC12_IN_CK] = "msdc12_in_ck", + [AD_DSI0_DPICLK] = "AD_DSI0_DPICLK", +#endif /* CLKDBG_6755 */ +}; + +enum CKGEN_CLK { + CKGEN_CLK_NULL, + +#if CLKDBG_6755 + HD_FAXI_CK = 1, + HF_FDDRPHYCFG_CK = 2, + HF_FMM_CK = 3, + F_FPWM_CK = 4, + HF_FVDEC_CK = 5, + HF_FMFG_CK = 6, + HF_FCAMTG_CK = 7, + F_FUART_CK = 8, + HF_FSPI_CK = 9, + HF_FMSDC50_0_HCLK_CK = 10, + HF_FMSDC50_0_CK = 11, + HF_FMSDC30_1_CK = 12, + HF_FMSDC30_2_CK = 13, + HF_FMSDC30_3_CK = 14, + HF_FAUDIO_CK = 15, + HF_FAUD_INTBUS_CK = 16, + HF_FPMICSPI_CK = 17, + HF_FATB_CK = 19, + HF_FMJC_CK = 20, + HF_FDPI0_CK = 21, + HF_FSCAM_CK = 22, + HF_FAUD_1_CK = 23, + HF_FAUD_2_CK = 24, + ECO_AO12_MEM_MUX_CK = 25, + ECO_AO12_MEM_DCM_CK = 26, + F_FDISP_PWM_CK = 27, + F_FSSUSB_TOP_SYS_CK = 28, + F_FSSUSB_TOP_XHCI_CK = 29, + F_FUSB_TOP_CK = 30, + HG_FSPM_CK = 31, + HF_FBSI_SPI_CK = 32, + F_FI2C_CK = 33, + HG_FDVFSP_CK = 34, +#endif /* CLKDBG_6755 */ + + CKGEN_CLK_END, +}; + +static const char * const CKGEN_CLK_NAME[] = { +#if CLKDBG_6755 + [HD_FAXI_CK] = "hd_faxi_ck", + [HF_FDDRPHYCFG_CK] = "hf_fddrphycfg_ck", + [HF_FMM_CK] = "hf_fmm_ck", + [F_FPWM_CK] = "f_fpwm_ck", + [HF_FVDEC_CK] = "hf_fvdec_ck", + [HF_FMFG_CK] = "hf_fmfg_ck", + [HF_FCAMTG_CK] = "hf_fcamtg_ck", + [F_FUART_CK] = "f_fuart_ck", + [HF_FSPI_CK] = "hf_fspi_ck", + [HF_FMSDC50_0_HCLK_CK] = "hf_fmsdc50_0_h_ck", + [HF_FMSDC50_0_CK] = "hf_fmsdc50_0_ck", + [HF_FMSDC30_1_CK] = "hf_fmsdc30_1_ck", + [HF_FMSDC30_2_CK] = "hf_fmsdc30_2_ck", + [HF_FMSDC30_3_CK] = "hf_fmsdc30_3_ck", + [HF_FAUDIO_CK] = "hf_faudio_ck", + [HF_FAUD_INTBUS_CK] = "hf_faud_intbus_ck", + [HF_FPMICSPI_CK] = "hf_fpmicspi_ck", + [HF_FATB_CK] = "hf_fatb_ck", + [HF_FMJC_CK] = "hf_fmjc_ck", + [HF_FDPI0_CK] = "hf_fdpi0_ck", + [HF_FSCAM_CK] = "hf_fscam_ck", + [HF_FAUD_1_CK] = "hf_faud_1_ck", + [HF_FAUD_2_CK] = "hf_faud_2_ck", + [ECO_AO12_MEM_MUX_CK] = "eco_ao12_mem_mux_ck", + [ECO_AO12_MEM_DCM_CK] = "eco_ao12_mem_dcm_ck", + [F_FDISP_PWM_CK] = "f_fdisp_pwm_ck", + [F_FSSUSB_TOP_SYS_CK] = "f_fssusb_top_sys_ck", + [F_FSSUSB_TOP_XHCI_CK] = "f_fssusb_top_xhci_ck", + [F_FUSB_TOP_CK] = "f_fusb_top_ck", + [HG_FSPM_CK] = "hg_fspm_ck", + [HF_FBSI_SPI_CK] = "hf_fbsi_spi_ck", + [F_FI2C_CK] = "f_fi2c_ck", + [HG_FDVFSP_CK] = "hg_fdvfsp_ck", +#endif /* CLKDBG_6755 */ +}; + +#if CLKDBG_8173 + +static void set_fmeter_divider_ca7(u32 k1) +{ + u32 v = clk_readl(CLK_MISC_CFG_1); + + v = ALT_BITS(v, 15, 8, k1); + clk_writel(CLK_MISC_CFG_1, v); +} + +static void set_fmeter_divider_ca15(u32 k1) +{ + u32 v = clk_readl(CLK_MISC_CFG_2); + + v = ALT_BITS(v, 7, 0, k1); + clk_writel(CLK_MISC_CFG_2, v); +} +#endif /* CLKDBG_6755 */ + + +#if CLKDBG_6755 +static void set_fmeter_divider(u32 k1) +{ + u32 v = clk_readl(CLK_MISC_CFG_0); + + v = ALT_BITS(v, 31, 24, k1); + clk_writel(CLK_MISC_CFG_0, v); +} + +static bool wait_fmeter_done(u32 tri_bit) +{ + static int max_wait_count; + int wait_count = (max_wait_count > 0) ? (max_wait_count * 2 + 2) : 100; + int i; + + /* wait fmeter */ + for (i = 0; i < wait_count && (clk_readl(CLK26CALI_0) & tri_bit); i++) + udelay(20); + + if (!(clk_readl(CLK26CALI_0) & tri_bit)) { + max_wait_count = max(max_wait_count, i); + return true; + } + + return false; +} + +#endif /* CLKDBG_6755 */ + +static u32 fmeter_freq(enum FMETER_TYPE type, int k1, int clk) +{ + void __iomem *clk_cfg_reg = CLK_DBG_CFG; + void __iomem *cnt_reg = CLK26CALI_1; + u32 cksw_ckgen[] = {13, 8, clk}; + u32 cksw_abist[] = {21, 16, clk}; + u32 *cksw_hlv = (type == CKGEN) ? cksw_ckgen : cksw_abist; + u32 en_bit = BIT(12); + u32 tri_bit = BIT(4); + u32 clk_misc_cfg_0; + u32 clk_misc_cfg_1; + u32 clk_cfg_val; + u32 freq = 0; + + if (!is_valid_reg(topckgen_base)) + return 0; + + clk_misc_cfg_0 = clk_readl(CLK_MISC_CFG_0); /* backup reg value */ + clk_misc_cfg_1 = clk_readl(CLK_MISC_CFG_1); + clk_cfg_val = clk_readl(clk_cfg_reg); + /* set meter div (0 = /1) */ + set_fmeter_divider(k1); + /* select fmeter */ + if (type == CKGEN) + clk_setl(CLK_DBG_CFG, BIT(0)); + else + clk_clrl(CLK_DBG_CFG, BIT(1)); + /* select meter clock input */ + clk_writel_mask(CLK_DBG_CFG, cksw_hlv[0], cksw_hlv[1], cksw_hlv[2]); + /* trigger fmeter */ + clk_setl(CLK26CALI_0, en_bit); /* enable fmeter_en */ + clk_clrl(CLK26CALI_0, tri_bit); /* start fmeter */ + clk_setl(CLK26CALI_0, en_bit|tri_bit); + + if (wait_fmeter_done(tri_bit)) { + u32 cnt = clk_readl(cnt_reg) & 0xFFFF; + + freq = (cnt * 26000) / 1024; + } + /* restore register settings */ + clk_writel(clk_cfg_reg, clk_cfg_val); + clk_writel(CLK_MISC_CFG_0, clk_misc_cfg_0); + clk_writel(CLK_MISC_CFG_1, clk_misc_cfg_1); + return freq; +} + +static u32 measure_stable_fmeter_freq(enum FMETER_TYPE type, int k1, int clk) +{ + u32 last_freq = 0; + u32 freq; + u32 maxfreq; + + freq = fmeter_freq(type, k1, clk); + maxfreq = max(freq, last_freq); + + while (maxfreq > 0 && ABS_DIFF(freq, last_freq) * 100 / maxfreq > 10) { + last_freq = freq; + freq = fmeter_freq(type, k1, clk); + maxfreq = max(freq, last_freq); + } + + return freq; +} + +static u32 measure_abist_freq(enum ABIST_CLK clk) +{ + return measure_stable_fmeter_freq(ABIST, 0, clk); +} + +static u32 measure_ckgen_freq(enum CKGEN_CLK clk) +{ + return measure_stable_fmeter_freq(CKGEN, 0, clk); +} + + + +static enum ABIST_CLK abist_clk[] = { + AD_CSI0_DELAY_TSTCLK, + AD_CSI1_DELAY_TSTCLK, + AD_PSMCUPLL_CK, + AD_L1MCUPLL_CK, + AD_C2KCPPLL_CK, + AD_ICCPLL_CK, + AD_INTFPLL_CK, + AD_MD2GPLL_CK, + AD_IMCPLL_CK, + AD_C2KDSPPLL_CK, + AD_BRPPLL_CK, + AD_DFEPLL_CK, + AD_EQPLL_CK, + AD_CMPPLL_CK, + AD_MDPLLGP_TST_CK, + AD_MDPLL1_FS26M_CK, + AD_MDPLL1_FS208M_CK, + AD_MDPLL1_FS393P216M_CK, + AD_ARMBPLL_1700M_PRO_CK, + AD_ARMBPLL_1700M_CORE_CK, + AD_ARMSPLL_1000M_PRO_CK, + AD_ARMSPLL_1000M_CORE_CK, + AD_MAINPLL_1092M_CK, + AD_UNIVPLL_1248M_CK, + AD_MMPLL_520M_CK, + AD_MSDCPLL_416M_CK, + AD_VENCPLL_286M_CK, + AD_APLL1_180P6336M_CK, + AD_APLL2_196P608M_CK, + AD_APPLLGP_TST_CK, + AD_USB20_48M_CK, + AD_UNIV_48M_CK, + AD_SSUSB_48M_CK, + AD_TVDPLL_594M_CK, + AD_DSI0_MPPLL_TST_CK, + AD_DSI0_LNTC_DSICLK, + AD_MEMPLL_MONCLK, + AD_OSC_CK, + RTC32K_CK_I, + ARMPLL_HD_FARM_CK_BIG, + ARMPLL_HD_FARM_CK_SML, + ARMPLL_HD_FARM_CK_BUS, + MSDC01_IN_CK, + MSDC02_IN_CK, + MSDC11_IN_CK, + MSDC12_IN_CK, + AD_DSI0_DPICLK, +}; + +static enum CKGEN_CLK ckgen_clk[] = { + HD_FAXI_CK, + HF_FDDRPHYCFG_CK, + HF_FMM_CK, + F_FPWM_CK, + HF_FVDEC_CK, + HF_FMFG_CK, + HF_FCAMTG_CK, + F_FUART_CK, + HF_FSPI_CK, + HF_FMSDC50_0_HCLK_CK, + HF_FMSDC50_0_CK, + HF_FMSDC30_1_CK, + HF_FMSDC30_2_CK, + HF_FMSDC30_3_CK, + HF_FAUDIO_CK, + HF_FAUD_INTBUS_CK, + HF_FPMICSPI_CK, + HF_FATB_CK, + HF_FMJC_CK, + HF_FDPI0_CK, + HF_FSCAM_CK, + HF_FAUD_1_CK, + HF_FAUD_2_CK, + ECO_AO12_MEM_MUX_CK, + ECO_AO12_MEM_DCM_CK, + F_FDISP_PWM_CK, + F_FSSUSB_TOP_SYS_CK, + F_FSSUSB_TOP_XHCI_CK, + F_FUSB_TOP_CK, + HG_FSPM_CK, + HF_FBSI_SPI_CK, + F_FI2C_CK, + HG_FDVFSP_CK, +}; +#if CLKDBG_8173 +static u32 measure_armpll_freq(u32 jit_ctrl) +{ +#if CLKDBG_8173 + u32 freq; + u32 mcu26c; + u32 armpll_jit_ctrl; + u32 top_dcmctl; + + if (!is_valid_reg(mcucfg_base) || !is_valid_reg(infrasys_base)) + return 0; + + mcu26c = clk_readl(MCU_26C); + armpll_jit_ctrl = clk_readl(ARMPLL_JIT_CTRL); + top_dcmctl = clk_readl(INFRA_TOPCKGEN_DCMCTL); + + clk_setl(MCU_26C, 0x8); + clk_setl(ARMPLL_JIT_CTRL, jit_ctrl); + clk_clrl(INFRA_TOPCKGEN_DCMCTL, 0x700); + + freq = measure_stable_fmeter_freq(ABIST, 1, ARMPLL_OCC_MON); + + clk_writel(INFRA_TOPCKGEN_DCMCTL, top_dcmctl); + clk_writel(ARMPLL_JIT_CTRL, armpll_jit_ctrl); + clk_writel(MCU_26C, mcu26c); + + return freq; +#else + return 0; +#endif +} + +static u32 measure_ca53_freq(void) +{ + return measure_armpll_freq(0x01); +} + +static u32 measure_ca57_freq(void) +{ + return measure_armpll_freq(0x11); +} + +#endif /* CLKDBG_8173 */ + +#if DUMP_INIT_STATE + +static void print_abist_clock(enum ABIST_CLK clk) +{ + u32 freq = measure_abist_freq(clk); + + clk_info("%2d: %-29s: %u\n", clk, ABIST_CLK_NAME[clk], freq); +} + +static void print_ckgen_clock(enum CKGEN_CLK clk) +{ + u32 freq = measure_ckgen_freq(clk); + + clk_info("%2d: %-29s: %u\n", clk, CKGEN_CLK_NAME[clk], freq); +} + +static void print_fmeter_all(void) +{ + size_t i; + u32 freq; + + if (!is_valid_reg(apmixedsys_base)) + return; + + for (i = 0; i < ARRAY_SIZE(abist_clk); i++) + print_abist_clock(abist_clk[i]); + + for (i = 0; i < ARRAY_SIZE(ckgen_clk); i++) + print_ckgen_clock(ckgen_clk[i]); +} + +#endif /* DUMP_INIT_STATE */ + +static void seq_print_abist_clock(enum ABIST_CLK clk, + struct seq_file *s, void *v) +{ + u32 freq = measure_abist_freq(clk); + + seq_printf(s, "%2d: %-29s: %u\n", clk, ABIST_CLK_NAME[clk], freq); +} + +static void seq_print_ckgen_clock(enum CKGEN_CLK clk, + struct seq_file *s, void *v) +{ + u32 freq = measure_ckgen_freq(clk); + + seq_printf(s, "%2d: %-29s: %u\n", clk, CKGEN_CLK_NAME[clk], freq); +} + +static int seq_print_fmeter_all(struct seq_file *s, void *v) +{ + size_t i; + + if (!is_valid_reg(apmixedsys_base)) + return 0; + + for (i = 0; i < ARRAY_SIZE(abist_clk); i++) + seq_print_abist_clock(abist_clk[i], s, v); + + for (i = 0; i < ARRAY_SIZE(ckgen_clk); i++) + seq_print_ckgen_clock(ckgen_clk[i], s, v); + + return 0; +} + +struct regname { + void __iomem *reg; + const char *name; +}; + +static size_t get_regnames(struct regname *regnames, size_t size) +{ + struct regname rn[] = { +#if CLKDBG_6755 + {SPM_VDE_PWR_CON, "SPM_VDE_PWR_CON"}, + {SPM_MFG_PWR_CON, "SPM_MFG_PWR_CON"}, + {SPM_VEN_PWR_CON, "SPM_VEN_PWR_CON"}, + {SPM_ISP_PWR_CON, "SPM_ISP_PWR_CON"}, + {SPM_DIS_PWR_CON, "SPM_DIS_PWR_CON"}, + {SPM_AUDIO_PWR_CON, "SPM_AUDIO_PWR_CON"}, + {SPM_MFG_ASYNC_PWR_CON, "SPM_MFG_ASYNC_PWR_CON"}, + {SPM_PWR_STATUS, "SPM_PWR_STATUS"}, + {SPM_PWR_STATUS_2ND, "SPM_PWR_STATUS_2ND"}, + {CLK_CFG_0, "CLK_CFG_0"}, + {CLK_CFG_1, "CLK_CFG_1"}, + {CLK_CFG_2, "CLK_CFG_2"}, + {CLK_CFG_3, "CLK_CFG_3"}, + {CLK_CFG_4, "CLK_CFG_4"}, + {CLK_CFG_5, "CLK_CFG_5"}, + {CLK_CFG_6, "CLK_CFG_6"}, + {CLK_CFG_7, "CLK_CFG_7"}, + {CLK_CFG_8, "CLK_CFG_8"}, + {CLK_CFG_9, "CLK_CFG_9"}, + {CLK_MISC_CFG_0, "CLK_MISC_CFG_0"}, + {CLK_MISC_CFG_1, "CLK_MISC_CFG_1"}, + {CLK26CALI_0, "CLK26CALI_0"}, + {CLK26CALI_1, "CLK26CALI_1"}, + {ARMCA15PLL_CON0, "ARMCA15PLL_CON0"}, + {ARMCA15PLL_CON1, "ARMCA15PLL_CON1"}, + {ARMCA15PLL_PWR_CON0, "ARMCA15PLL_PWR_CON0"}, + {ARMCA7PLL_CON0, "ARMCA7PLL_CON0"}, + {ARMCA7PLL_CON1, "ARMCA7PLL_CON1"}, + {ARMCA7PLL_PWR_CON0, "ARMCA7PLL_PWR_CON0"}, + {MAINPLL_CON0, "MAINPLL_CON0"}, + {MAINPLL_CON1, "MAINPLL_CON1"}, + {MAINPLL_PWR_CON0, "MAINPLL_PWR_CON0"}, + {UNIVPLL_CON0, "UNIVPLL_CON0"}, + {UNIVPLL_CON1, "UNIVPLL_CON1"}, + {UNIVPLL_PWR_CON0, "UNIVPLL_PWR_CON0"}, + {MMPLL_CON0, "MMPLL_CON0"}, + {MMPLL_CON1, "MMPLL_CON1"}, + {MMPLL_PWR_CON0, "MMPLL_PWR_CON0"}, + {MSDCPLL_CON0, "MSDCPLL_CON0"}, + {MSDCPLL_CON1, "MSDCPLL_CON1"}, + {MSDCPLL_PWR_CON0, "MSDCPLL_PWR_CON0"}, + {VENCPLL_CON0, "VENCPLL_CON0"}, + {VENCPLL_CON1, "VENCPLL_CON1"}, + {VENCPLL_PWR_CON0, "VENCPLL_PWR_CON0"}, + {TVDPLL_CON0, "TVDPLL_CON0"}, + {TVDPLL_CON1, "TVDPLL_CON1"}, + {TVDPLL_PWR_CON0, "TVDPLL_PWR_CON0"}, + {MPLL_CON0, "MPLL_CON0"}, + {MPLL_CON1, "MPLL_CON1"}, + {MPLL_PWR_CON0, "MPLL_PWR_CON0"}, + {VCODECPLL_CON0, "VCODECPLL_CON0"}, + {VCODECPLL_CON1, "VCODECPLL_CON1"}, + {VCODECPLL_PWR_CON0, "VCODECPLL_PWR_CON0"}, + {APLL1_CON0, "APLL1_CON0"}, + {APLL1_CON1, "APLL1_CON1"}, + {APLL1_PWR_CON0, "APLL1_PWR_CON0"}, + {APLL2_CON0, "APLL2_CON0"}, + {APLL2_CON1, "APLL2_CON1"}, + {APLL2_PWR_CON0, "APLL2_PWR_CON0"}, + {INFRA_PDN0_STA, "INFRA_PDN0_STA"}, + {INFRA_PDN1_STA, "INFRA_PDN1_STA"}, + {INFRA_PDN2_STA, "INFRA_PDN2_STA"}, + {DISP_CG_CON0, "DISP_CG_CON0"}, + {DISP_CG_CON1, "DISP_CG_CON1"}, + {IMG_CG_CON, "IMG_CG_CON"}, + {VDEC_CKEN_SET, "VDEC_CKEN_SET"}, + {LARB_CKEN_SET, "LARB_CKEN_SET"}, + {VENC_CG_CON, "VENC_CG_CON"}, + {AUDIO_TOP_CON0, "AUDIO_TOP_CON0"}, + {MFG_CG_CON, "MFG_CG_CON"}, +#endif /* CLKDBG_SOC */ + }; + + size_t n = min(ARRAY_SIZE(rn), size); + + memcpy(regnames, rn, sizeof(rn[0]) * n); + return n; +} + +#if DUMP_INIT_STATE + +static void print_reg(void __iomem *reg, const char *name) +{ + if (!is_valid_reg(reg)) + return; + + clk_info("%-21s: [0x%p] = 0x%08x\n", name, reg, clk_readl(reg)); +} + +static void print_regs(void) +{ + static struct regname rn[128]; + int i, n; + + n = get_regnames(rn, ARRAY_SIZE(rn)); + + for (i = 0; i < n; i++) + print_reg(rn[i].reg, rn[i].name); +} + +#endif /* DUMP_INIT_STATE */ + +static void seq_print_reg(void __iomem *reg, const char *name, + struct seq_file *s, void *v) +{ + u32 val; + + if (!is_valid_reg(reg)) + return; + + val = clk_readl(reg); + + clk_info("%-21s: [0x%p] = 0x%08x\n", name, reg, val); + seq_printf(s, "%-21s: [0x%p] = 0x%08x\n", name, reg, val); +} + +static int seq_print_regs(struct seq_file *s, void *v) +{ + static struct regname rn[128]; + int i, n; + + n = get_regnames(rn, ARRAY_SIZE(rn)); + + for (i = 0; i < n; i++) + seq_print_reg(rn[i].reg, rn[i].name, s, v); + + return 0; +} + +#if CLKDBG_6755 + +/* ROOT */ +#define clk_null "clk_null" +#define clk26m "clk26m" +#define clk32k "clk32k" + +#define clkph_mck_o "clkph_mck_o" +#define dpi_ck "dpi_ck" + +/* PLL */ +#define armbpll "armbpll" +#define armspll "armspll" +#define mainpll "mainpll" +#define msdcpll "msdcpll" +#define univpll "univpll" +#define mmpll "mmpll" +#define vencpll "vencpll" +#define tvdpll "tvdpll" +#define apll1 "apll1" +#define apll2 "apll2" +#define oscpll "oscpll" + +/* DIV */ +#define syspll_ck "syspll_ck" +#define syspll1_ck "syspll1_ck" +#define syspll2_ck "syspll2_ck" +#define syspll3_ck "syspll3_ck" +#define syspll4_ck "syspll4_ck" +#define univpll_ck "univpll_ck" +#define univpll1_ck "univpll1_ck" +#define univpll2_ck "univpll2_ck" +#define univpll3_ck "univpll3_ck" +#define ad_apll1_ck "ad_apll1_ck" +#define ad_sys_26m_ck "ad_sys_26m_ck" +#define ad_sys_26m_d2 "ad_sys_26m_d2" +#define dmpll_ck "dmpll_ck" +#define dmpll_d2 "dmpll_d2" +#define dmpll_d4 "dmpll_d4" +#define dmpll_d8 "dmpll_d8" +#define dpi_ck "dpi_ck" +#define mmpll_ck "mmpll_ck" +#define msdcpll_ck "msdcpll_ck" +#define msdcpll_d16 "msdcpll_d16" +#define msdcpll_d2 "msdcpll_d2" +#define msdcpll_d4 "msdcpll_d4" +#define msdcpll_d8 "msdcpll_d8" +#define syspll_d2 "syspll_d2" +#define syspll_d3 "syspll_d3" +#define syspll_d5 "syspll_d5" +#define syspll1_d16 "syspll1_d16" +#define syspll1_d2 "syspll1_d2" +#define syspll1_d4 "syspll1_d4" +#define syspll1_d8 "syspll1_d8" +#define syspll2_d2 "syspll2_d2" +#define syspll2_d4 "syspll2_d4" +#define syspll3_d2 "syspll3_d2" +#define syspll3_d4 "syspll3_d4" +#define syspll4_d2 "syspll4_d2" +#define syspll4_d2_d8 "syspll4_d2_d8" +#define syspll4_d4 "syspll4_d4" +#define tvdpll_ck "tvdpll_ck" +#define tvdpll_d2 "tvdpll_d2" +#define tvdpll_d4 "tvdpll_d4" +#define univpll_d2 "univpll_d2" +#define univpll_d26 "univpll_d26" +#define univpll_d3 "univpll_d3" +#define univpll_d5 "univpll_d5" +#define univpll1_d2 "univpll1_d2" +#define univpll1_d4 "univpll1_d4" +#define univpll1_d8 "univpll1_d8" +#define univpll2_d2 "univpll2_d2" +#define univpll2_d4 "univpll2_d4" +#define univpll2_d8 "univpll2_d8" +#define univpll3_d2 "univpll3_d2" +#define univpll3_d4 "univpll3_d4" +#define vencpll_ck "vencpll_ck" +#define vencpll_d3 "vencpll_d3" +#define whpll_audio_ck "whpll_audio_ck" + +#define osc_ck "osc_ck" +#define osc_d8 "osc_d8" +#define osc_d2 "osc_d2" +#define syspll_d7 "syspll_d7" +#define univpll_d7 "univpll_d7" +#define osc_d4 "osc_d4" +#define tvdpll_d8 "tvdpll_d8" +#define tvdpll_d16 "tvdpll_d16" +#define apll1_ck "apll1_ck" +#define apll2_ck "apll2_ck" +#define syspll_d3_d3 "syspll_d3_d3" + + + +/* TOP */ +#define axi_sel "axi_sel" +#define mem_sel "mem_sel" +#define ddrphycfg_sel "ddrphycfg_sel" +#define mm_sel "mm_sel" +#define pwm_sel "pwm_sel" +#define vdec_sel "vdec_sel" +#define mfg_sel "mfg_sel" +#define camtg_sel "camtg_sel" +#define uart_sel "uart_sel" +#define spi_sel "spi_sel" +#define usb20_sel "usb20_sel" +#define msdc50_0_sel "msdc50_0_sel" + +#define msdc30_1_sel "msdc30_1_sel" +#define msdc30_2_sel "msdc30_2_sel" +#define msdc30_3_sel "msdc30_3_sel" +#define audio_sel "audio_sel" +#define aud_intbus_sel "aud_intbus_sel" +#define pmicspi_sel "pmicspi_sel" +#define scp_sel "scp_sel" +#define atb_sel "atb_sel" +#define dpi0_sel "dpi0_sel" +#define scam_sel "scam_sel" +#define mfg13m_sel "mfg13m_sel" +#define aud_1_sel "aud_1_sel" +#define aud_2_sel "aud_2_sel" +#define irda_sel "irda_sel" +#define irtx_sel "irtx_sel" +#define disppwm_sel "disppwm_sel" +#define ssusb_top_sys_sel "ssusb_top_sys_sel" +#define usb_top_sel "usb_top_sel" +#define i2c_sel "i2c_sel" +#define f26m_sel "f26m_sel" +#define msdc50_0_hclk_sel "msdc50_0_hclk_sel" +#define bsi_spi_sel "bsi_spi_sel" +#define spm_sel "spm_sel" +#define dvfsp_sel "dvfsp_sel" +#define i2s_sel "i2s_sel" + + + +/* INFRA */ +#define infra_pmictmr "infra_pmictmr" +#define infra_pmicap "infra_pmicap" +#define infra_pmicmd "infra_pmicmd" +#define infra_pmicconn "infra_pmicconn" +#define infra_scpsys "infra_scpsys" +#define infra_sej "infra_sej" +#define infra_apxgpt "infra_apxgpt" +#define infra_icusb "infra_icusb" +#define infra_gce "infra_gce" +#define infra_therm "infra_therm" +#define infra_i2c0 "infra_i2c0" +#define infra_i2c1 "infra_i2c1" +#define infra_i2c2 "infra_i2c2" +#define infra_i2c3 "infra_i2c3" +#define infra_pwmhclk "infra_pwmhclk" +#define infra_pwm1 "infra_pwm1" +#define infra_pwm2 "infra_pwm2" +#define infra_pwm3 "infra_pwm3" +#define infra_pwm4 "infra_pwm4" +#define infra_pwm "infra_pwm" +#define infra_uart0 "infra_uart0" +#define infra_uart1 "infra_uart1" +#define infra_uart2 "infra_uart2" +#define infra_uart3 "infra_uart3" +#define infra_md2mdccif0 "infra_md2mdccif0" +#define infra_md2mdccif1 "infra_md2mdccif1" +#define infra_md2mdccif2 "infra_md2mdccif2" +#define infra_btif "infra_btif" +#define infra_md2mdccif3 "infra_md2mdccif3" +#define infra_spi0 "infra_spi0" +#define infra_msdc0 "infra_msdc0" +#define infra_md2mdccif4 "infra_md2mdccif4" +#define infra_msdc1 "infra_msdc1" +#define infra_msdc2 "infra_msdc2" +#define infra_msdc3 "infra_msdc3" +#define infra_md2mdccif5 "infra_md2mdccif5" +#define infra_gcpu "infra_gcpu" +#define infra_trng "infra_trng" +#define infra_auxadc "infra_auxadc" +#define infra_cpum "infra_cpum" +#define infra_ccif1ap "infra_ccif1ap" +#define infra_ccif1md "infra_ccif1md" +#define infra_apdma "infra_apdma" +#define infra_xiu "infra_xiu" +#define infra_deviceapc "infra_deviceapc" +#define infra_xiu2ahb "infra_xiu2ahb" +#define infra_ccifap "infra_ccifap" +#define infra_debugsys "infra_debugsys" +#define infra_audio "infra_audio" /* confirm if for audio??*/ +#define infra_ccifmd "infra_ccifmd" +#define infra_dramcf26m "infra_dramcf26m" +#define infra_irtx "infra_irtx" +#define infra_ssusbtop "infra_ssusbtop" +#define infra_disppwm "infra_disppwm" +#define infra_cldmabclk "infra_cldmabclk" +#define infra_audio26mbclk "infra_audio26mbclk" +#define infra_mdtmp26mbclk "infra_mdtmp26mbclk" +#define infra_spi1 "infra_spi1" +#define infra_i2c4 "infra_i2c4" +#define infra_mdtmpshare "infra_mdtmpshare" + + +/* MFG */ +#define mfg_bg3d "mfg_bg3d" + +/* IMG */ +#define img_image_larb2_smi "img_image_larb2_smi" +#define img_image_larb2_smi_m4u "img_image_larb2_smi_m4u" +#define img_image_larb2_smi_smi_common "img_image_larb2_smi_smi_common" +#define img_image_larb2_smi_met_smi_common "img_image_larb2_smi_met_smi_common" +#define img_image_larb2_smi_ispsys "img_image_larb2_smi_ispsys" +#define img_image_cam_smi "img_image_cam_smi" +#define img_image_cam_cam "img_image_cam_cam" +#define img_image_sen_tg "img_image_sen_tg" +#define img_image_sen_cam "img_image_sen_cam" +#define img_image_cam_sv "img_image_cam_sv" +#define img_image_sufod "img_image_sufod" +#define img_image_fd "img_image_fd" + +/* MM_SYS */ +#define mm_disp0_smi_common "mm_disp0_smi_common" +#define mm_disp0_smi_common_m4u "mm_disp0_smi_common_m4u" +#define mm_disp0_smi_common_mali "mm_disp0_smi_common_mali" +#define mm_disp0_smi_common_dispsys "mm_disp0_smi_common_dispsys" +#define mm_disp0_smi_common_smi_common "mm_disp0_smi_common_smi_common" +#define mm_disp0_smi_common_met_smi_common "mm_disp0_smi_common_met_smi_common" +#define mm_disp0_smi_common_ispsys "mm_disp0_smi_common_ispsys" +#define mm_disp0_smi_common_fdvt "mm_disp0_smi_common_fdvt" +#define mm_disp0_smi_common_vdec_gcon "mm_disp0_smi_common_vdec_gcon" +#define mm_disp0_smi_common_jpgenc "mm_disp0_smi_common_jpgenc" +#define mm_disp0_smi_common_jpgdec "mm_disp0_smi_common_jpgdec" + +#define mm_disp0_smi_larb0 "mm_disp0_smi_larb0" +#define mm_disp0_smi_larb0_m4u "mm_disp0_smi_larb0_m4u" +#define mm_disp0_smi_larb0_dispsys "mm_disp0_smi_larb0_dispsys" +#define mm_disp0_smi_larb0_smi_common "mm_disp0_smi_larb0_smi_common" +#define mm_disp0_smi_larb0_met_smi_common "mm_disp0_smi_larb0_met_smi_common" + + +#define mm_disp0_cam_mdp "mm_disp0_cam_mdp" +#define mm_disp0_mdp_rdma "mm_disp0_mdp_rdma" +#define mm_disp0_mdp_rsz0 "mm_disp0_mdp_rsz0" +#define mm_disp0_mdp_rsz1 "mm_disp0_mdp_rsz1" +#define mm_disp0_mdp_tdshp "mm_disp0_mdp_tdshp" +#define mm_disp0_mdp_wdma "mm_disp0_mdp_wdma" +#define mm_disp0_mdp_wrot "mm_disp0_mdp_wrot" +#define mm_disp0_fake_eng "mm_disp0_fake_eng" +#define mm_disp0_disp_ovl0 "mm_disp0_disp_ovl0" +#define mm_disp0_disp_ovl1 "mm_disp0_disp_ovl1" +#define mm_disp0_disp_rdma0 "mm_disp0_disp_rdma0" +#define mm_disp0_disp_rdma1 "mm_disp0_disp_rdma1" +#define mm_disp0_disp_wdma0 "mm_disp0_disp_wdma0" +#define mm_disp0_disp_color "mm_disp0_disp_color" +#define mm_disp0_disp_ccorr "mm_disp0_disp_ccorr" +#define mm_disp0_disp_aal "mm_disp0_disp_aal" +#define mm_disp0_disp_gamma "mm_disp0_disp_gamma" +#define mm_disp0_disp_dither "mm_disp0_disp_dither" +#define mm_disp0_mdp_color "mm_disp0_mdp_color" +#define mm_disp0_ufoe_mout "mm_disp0_ufoe_mout" +#define mm_disp0_disp_wdma1 "mm_disp0_disp_wdma1" +#define mm_disp0_disp_2lovl0 "mm_disp0_disp_2lovl0" +#define mm_disp0_disp_2lovl1 "mm_disp0_disp_2lovl1" +#define mm_disp0_disp_ovl0mout "mm_disp0_disp_ovl0mout" +#define mm_disp1_dsi_engine "mm_disp1_dsi_engine" +#define mm_disp1_dsi_digital "mm_disp1_dsi_digital" +#define mm_disp1_dpi_pixel "mm_disp1_dpi_pixel" +#define mm_disp1_dpi_engine "mm_disp1_dpi_engine" + +/* VDEC */ +#define vdec0_vdec "vdec0_vdec" +#define vdec1_larb "vdec1_larb" +#define vdec1_larb_m4u "vdec1_larb_m4u" +#define vdec1_larb_smi_common "vdec1_larb_smi_common" +#define vdec1_larb_met_smi_common "vdec1_larb_met_smi_common" +#define vdec1_larb_vdec_gcon "vdec1_larb_vdec_gcon" + +/* VENC */ +#define venc_larb "venc_larb" +#define venc_larb_m4u "venc_larb_m4u" +#define venc_larb_smi_common "venc_larb_smi_common" +#define venc_larb_met_smi_common "venc_larb_met_smi_common" +#define venc_larb_jpgenc "venc_larb_jpgenc" +#define venc_larb_jpgdec "venc_larb_jpgdec" + +#define venc_venc "venc_venc" +#define venc_jpgenc "venc_jpgenc" +#define venc_jpgdec "venc_jpgdec" + +/* AUDIO */ +#define audio_afe "audio_afe" +#define audio_i2s "audio_i2s" +#define audio_22m "audio_22m" +#define audio_24m "audio_24m" +#define audio_apll2_tuner "audio_apll2_tuner" +#define audio_apll_tuner "audio_apll_tuner" +#define audio_adc "audio_adc" +#define audio_dac "audio_dac" +#define audio_dac_predis "audio_dac_predis" +#define audio_tml "audio_tml" +#define audio_apll1div0 "audio_apll1div0" +#define audio_apll2div0 "audio_apll2div0" + +/* SCP */ +#define pg_md1 "pg_md1" +#define pg_md2 "pg_md2" +#define pg_conn "pg_conn" +#define pg_dis "pg_dis" +#define pg_mfg "pg_mfg" +#define pg_isp "pg_isp" +#define pg_vde "pg_vde" +#define pg_ven "pg_ven" +#define pg_aud "pg_aud" +/*#define pg_mfg_async "pg_mfg_async"*/ + +#endif /* CLKDBG_6755 */ + +static const char * const *get_all_clk_names(size_t *num) +{ + static const char * const clks[] = { +#if CLKDBG_6755 + /* ROOT */ + clk_null, + clk26m, + clk32k, + + clkph_mck_o, + + /* PLL */ + armbpll, + armspll, + mainpll, + msdcpll, + univpll, + mmpll, + vencpll, + tvdpll, + apll1, + apll2, + oscpll, + + /* DIV */ + syspll_ck, + syspll2_ck, + syspll3_ck, + syspll4_ck, + univpll_ck, + univpll1_ck, + univpll2_ck, + univpll3_ck, + ad_apll1_ck, + ad_sys_26m_ck, + ad_sys_26m_d2, + dmpll_ck, + dmpll_d2, + dmpll_d4, + dmpll_d8, + dpi_ck, + mmpll_ck, + msdcpll_ck, + msdcpll_d16, + msdcpll_d2, + msdcpll_d4, + msdcpll_d8, + syspll_d2, + syspll_d3, + syspll_d5, + syspll1_d16, + syspll1_d2, + syspll1_d4, + syspll1_d8, + syspll2_d2, + syspll2_d4, + syspll3_d2, + syspll3_d4, + syspll4_d2, + syspll4_d2_d8, + syspll4_d4, + tvdpll_ck, + tvdpll_d2, + tvdpll_d4, + univpll_d2, + univpll_d26, + univpll_d3, + univpll_d5, + univpll1_d2, + univpll1_d4, + univpll1_d8, + univpll2_d2, + univpll2_d4, + univpll2_d8, + univpll3_d2, + univpll3_d4, + vencpll_ck, + vencpll_d3, + whpll_audio_ck, + osc_ck, + osc_d8, + osc_d2, + syspll_d7, + univpll_d7, + osc_d4, + tvdpll_d8, + tvdpll_d16, + apll1_ck, + apll2_ck, + syspll_d3_d3, + + /* TOP */ + axi_sel, + mem_sel, + ddrphycfg_sel, + mm_sel, + pwm_sel, + vdec_sel, + mfg_sel, + camtg_sel, + uart_sel, + spi_sel, + usb20_sel, + msdc50_0_sel, + msdc30_1_sel, + msdc30_2_sel, + msdc30_3_sel, + audio_sel, + aud_intbus_sel, + pmicspi_sel, + scp_sel, + atb_sel, + dpi0_sel, + scam_sel, + mfg13m_sel, + aud_1_sel, + aud_2_sel, + irda_sel, + irtx_sel, + disppwm_sel, + ssusb_top_sys_sel, + usb_top_sel, + i2c_sel, + f26m_sel, + msdc50_0_hclk_sel, + bsi_spi_sel, + spm_sel, + dvfsp_sel, + i2s_sel, + + + /* INFRA */ + infra_pmictmr, + infra_pmicap, + infra_pmicmd, + infra_pmicconn, + infra_scpsys, + infra_sej, + infra_apxgpt, + infra_icusb, + infra_gce, + infra_therm, + infra_i2c0, + infra_i2c1, + infra_i2c2, + infra_i2c3, + infra_pwmhclk, + infra_pwm1, + infra_pwm2, + infra_pwm3, + infra_pwm4, + infra_pwm, + infra_uart0, + infra_uart1, + infra_uart2, + infra_uart3, + infra_md2mdccif0, + infra_md2mdccif1, + infra_md2mdccif2, + infra_btif, + infra_md2mdccif3, + infra_spi0, + infra_msdc0, + infra_md2mdccif4, + infra_msdc1, + infra_msdc2, + infra_msdc3, + infra_md2mdccif5, + infra_gcpu, + + /* MFG */ + mfg_bg3d, + + /* IMG */ + img_image_larb2_smi, + img_image_larb2_smi_m4u, + img_image_larb2_smi_smi_common, + img_image_larb2_smi_met_smi_common, + img_image_larb2_smi_ispsys, + img_image_cam_smi, + img_image_cam_cam, + img_image_sen_tg, + img_image_sen_cam, + img_image_cam_sv, + img_image_sufod, + img_image_fd, + + + /* MM */ + mm_disp0_smi_common, + mm_disp0_smi_common_m4u, + mm_disp0_smi_common_mali, + mm_disp0_smi_common_dispsys, + mm_disp0_smi_common_smi_common, + mm_disp0_smi_common_met_smi_common, + mm_disp0_smi_common_ispsys, + mm_disp0_smi_common_fdvt, + mm_disp0_smi_common_vdec_gcon, + mm_disp0_smi_common_jpgenc, + mm_disp0_smi_common_jpgdec, + mm_disp0_smi_larb0, + mm_disp0_smi_larb0_m4u, + mm_disp0_smi_larb0_dispsys, + mm_disp0_smi_larb0_smi_common, + mm_disp0_smi_larb0_met_smi_common, + mm_disp0_cam_mdp, + mm_disp0_mdp_rdma, + mm_disp0_mdp_rsz0, + mm_disp0_mdp_rsz1, + mm_disp0_mdp_tdshp, + mm_disp0_mdp_wdma, + mm_disp0_mdp_wrot, + mm_disp0_fake_eng, + mm_disp0_disp_ovl0, + mm_disp0_disp_ovl1, + mm_disp0_disp_rdma0, + mm_disp0_disp_rdma1, + mm_disp0_disp_wdma0, + mm_disp0_disp_color, + mm_disp0_disp_ccorr, + mm_disp0_disp_aal, + mm_disp0_disp_gamma, + mm_disp0_disp_dither, + mm_disp0_mdp_color, + mm_disp0_ufoe_mout, + mm_disp0_disp_wdma1, + mm_disp0_disp_2lovl0, + mm_disp0_disp_2lovl1, + mm_disp0_disp_ovl0mout, + mm_disp1_dsi_engine, + mm_disp1_dsi_digital, + mm_disp1_dpi_pixel, + mm_disp1_dpi_engine, + + + + + /* VDEC */ + vdec0_vdec, + vdec1_larb, + vdec1_larb_m4u, + vdec1_larb_smi_common, + vdec1_larb_met_smi_common, + vdec1_larb_vdec_gcon, + + + /* VENC */ + venc_larb, + venc_larb_m4u, + venc_larb_smi_common, + venc_larb_met_smi_common, + venc_larb_jpgenc, + venc_larb_jpgdec, + venc_venc, + venc_jpgenc, + venc_jpgdec, + + /* AUDIO */ + audio_afe, + audio_i2s, + audio_22m, + audio_24m, + audio_apll2_tuner, + audio_apll_tuner, + audio_adc, + audio_dac, + audio_dac_predis, + audio_tml, + audio_apll1div0, + audio_apll2div0, + + + pg_md1, + pg_md2, + pg_conn, + pg_dis, + pg_mfg, + pg_isp, + pg_vde, + pg_ven, + pg_aud, + /*pg_mfg_async,*/ + + +#endif /* CLKDBG_SOC */ + }; + + *num = ARRAY_SIZE(clks); + + return clks; +} + +static void dump_clk_state(const char *clkname, struct seq_file *s) +{ + struct clk *c = __clk_lookup(clkname); + struct clk *p = IS_ERR_OR_NULL(c) ? NULL : __clk_get_parent(c); + + if (IS_ERR_OR_NULL(c)) { + seq_printf(s, "[%17s: NULL]\n", clkname); + return; + } + + seq_printf(s, "[%-17s: %3s, %3d, %3d, %10ld, %17s]\n", + __clk_get_name(c), + (__clk_is_enabled(c) || __clk_is_prepared(c)) ? "ON" : "off", + __clk_is_prepared(c), + __clk_get_enable_count(c), + __clk_get_rate(c), + p ? __clk_get_name(p) : ""); +} + +static int clkdbg_dump_state_all(struct seq_file *s, void *v) +{ + int i; + size_t num; + + const char * const *clks = get_all_clk_names(&num); + + pr_debug("\n"); + for (i = 0; i < num; i++) + dump_clk_state(clks[i], s); + + return 0; +} + +static char last_cmd[128] = "null"; + +static int clkdbg_prepare_enable(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *clk_name; + struct clk *clk; + int r; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + clk_name = strsep(&c, " "); + + seq_printf(s, "clk_prepare_enable(%s): ", clk_name); + + clk = __clk_lookup(clk_name); + if (IS_ERR_OR_NULL(clk)) { + seq_printf(s, "clk_get(): 0x%p\n", clk); + return PTR_ERR(clk); + } + + r = clk_prepare_enable(clk); + seq_printf(s, "%d\n", r); + + return r; +} + +static int clkdbg_disable_unprepare(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *clk_name; + struct clk *clk; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + clk_name = strsep(&c, " "); + + seq_printf(s, "clk_disable_unprepare(%s): ", clk_name); + + clk = __clk_lookup(clk_name); + if (IS_ERR_OR_NULL(clk)) { + seq_printf(s, "clk_get(): 0x%p\n", clk); + return PTR_ERR(clk); + } + + clk_disable_unprepare(clk); + seq_puts(s, "0\n"); + + return 0; +} + +static int clkdbg_set_parent(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *clk_name; + char *parent_name; + struct clk *clk; + struct clk *parent; + int r; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + clk_name = strsep(&c, " "); + parent_name = strsep(&c, " "); + + seq_printf(s, "clk_set_parent(%s, %s): ", clk_name, parent_name); + + clk = __clk_lookup(clk_name); + if (IS_ERR_OR_NULL(clk)) { + seq_printf(s, "clk_get(): 0x%p\n", clk); + return PTR_ERR(clk); + } + + parent = __clk_lookup(parent_name); + if (IS_ERR_OR_NULL(parent)) { + seq_printf(s, "clk_get(): 0x%p\n", parent); + return PTR_ERR(parent); + } + + clk_prepare_enable(clk); + r = clk_set_parent(clk, parent); + clk_disable_unprepare(clk); + seq_printf(s, "%d\n", r); + + return r; +} + +static int clkdbg_set_rate(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *clk_name; + char *rate_str; + struct clk *clk; + unsigned long rate; + int r; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + clk_name = strsep(&c, " "); + rate_str = strsep(&c, " "); + r = kstrtoul(rate_str, 0, &rate); + + seq_printf(s, "clk_set_rate(%s, %lu): %d: ", clk_name, rate, r); + + clk = __clk_lookup(clk_name); + if (IS_ERR_OR_NULL(clk)) { + seq_printf(s, "clk_get(): 0x%p\n", clk); + return PTR_ERR(clk); + } + + r = clk_set_rate(clk, rate); + seq_printf(s, "%d\n", r); + + return r; +} + +void *reg_from_str(const char *str) +{ + if (sizeof(void *) == sizeof(unsigned long)) { + unsigned long v; + + if (kstrtoul(str, 0, &v) == 0) + return (void *)((uintptr_t)v); + } else if (sizeof(void *) == sizeof(unsigned long long)) { + unsigned long long v; + + if (kstrtoull(str, 0, &v) == 0) + return (void *)((uintptr_t)v); + } else { + unsigned long long v; + + clk_warn("unexpected pointer size: sizeof(void *): %zu\n", + sizeof(void *)); + + if (kstrtoull(str, 0, &v) == 0) + return (void *)((uintptr_t)v); + } + + clk_warn("%s(): parsing error: %s\n", __func__, str); + + return NULL; +} + +static int parse_reg_val_from_cmd(void __iomem **preg, unsigned long *pval) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *reg_str; + char *val_str; + int r = 0; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + reg_str = strsep(&c, " "); + val_str = strsep(&c, " "); + + if (preg) + *preg = reg_from_str(reg_str); + + if (pval) + r = kstrtoul(val_str, 0, pval); + + return r; +} + +static int clkdbg_reg_read(struct seq_file *s, void *v) +{ + void __iomem *reg; + unsigned long val; + + parse_reg_val_from_cmd(®, NULL); + seq_printf(s, "readl(0x%p): ", reg); + + val = clk_readl(reg); + seq_printf(s, "0x%08x\n", (u32)val); + + return 0; +} + +static int clkdbg_reg_write(struct seq_file *s, void *v) +{ + void __iomem *reg; + unsigned long val; + + parse_reg_val_from_cmd(®, &val); + seq_printf(s, "writel(0x%p, 0x%08x): ", reg, (u32)val); + + clk_writel(reg, val); + val = clk_readl(reg); + seq_printf(s, "0x%08x\n", (u32)val); + + return 0; +} + +static int clkdbg_reg_set(struct seq_file *s, void *v) +{ + void __iomem *reg; + unsigned long val; + + parse_reg_val_from_cmd(®, &val); + seq_printf(s, "writel(0x%p, 0x%08x): ", reg, (u32)val); + + clk_setl(reg, val); + val = clk_readl(reg); + seq_printf(s, "0x%08x\n", (u32)val); + + return 0; +} + +static int clkdbg_reg_clr(struct seq_file *s, void *v) +{ + void __iomem *reg; + unsigned long val; + + parse_reg_val_from_cmd(®, &val); + seq_printf(s, "writel(0x%p, 0x%08x): ", reg, (u32)val); + + clk_clrl(reg, val); + val = clk_readl(reg); + seq_printf(s, "0x%08x\n", (u32)val); + + return 0; +} + +#if CLKDBG_PM_DOMAIN + +/* + * pm_domain support + */ + +static struct generic_pm_domain **get_all_pm_domain(int *numpd) +{ + static struct generic_pm_domain *pds[10]; + const int maxpd = ARRAY_SIZE(pds); +#if CLKDBG_6755 + const char *cmp = "mediatek,mt6755-scpsys"; +#endif + + struct device_node *node; + int i; + + node = of_find_compatible_node(NULL, NULL, cmp); + + if (!node) { + clk_err("node '%s' not found!\n", cmp); + return NULL; + } + + for (i = 0; i < maxpd; i++) { + struct of_phandle_args pa; + + pa.np = node; + pa.args[0] = i; + pa.args_count = 1; + pds[i] = of_genpd_get_from_provider(&pa); + + if (IS_ERR(pds[i])) + break; + } + + if (numpd) + *numpd = i; + + return pds; +} + +static struct generic_pm_domain *genpd_from_name(const char *name) +{ + int i; + int numpd; + struct generic_pm_domain **pds = get_all_pm_domain(&numpd); + + for (i = 0; i < numpd; i++) { + struct generic_pm_domain *pd = pds[i]; + + if (IS_ERR_OR_NULL(pd)) + continue; + + if (strcmp(name, pd->name) == 0) + return pd; + } + + return NULL; +} + +static struct platform_device *pdev_from_name(const char *name) +{ + int i; + int numpd; + struct generic_pm_domain **pds = get_all_pm_domain(&numpd); + + for (i = 0; i < numpd; i++) { + struct pm_domain_data *pdd; + struct generic_pm_domain *pd = pds[i]; + + if (IS_ERR_OR_NULL(pd)) + continue; + + list_for_each_entry(pdd, &pd->dev_list, list_node) { + struct device *dev = pdd->dev; + struct platform_device *pdev = to_platform_device(dev); + + if (strcmp(name, pdev->name) == 0) + return pdev; + } + } + + return NULL; +} + +static void seq_print_all_genpd(struct seq_file *s) +{ + static const char * const gpd_status_name[] = { + "ACTIVE", + "WAIT_MASTER", + "BUSY", + "REPEAT", + "POWER_OFF", + }; + + static const char * const prm_status_name[] = { + "active", + "resuming", + "suspended", + "suspending", + }; + + int i; + int numpd; + struct generic_pm_domain **pds = get_all_pm_domain(&numpd); + + seq_puts(s, "domain_on [pmd_name status]\n"); + seq_puts(s, "\tdev_on (dev_name usage_count, disable, status)\n"); + seq_puts(s, "------------------------------------------------------\n"); + + for (i = 0; i < numpd; i++) { + struct pm_domain_data *pdd; + struct generic_pm_domain *pd = pds[i]; + + if (IS_ERR_OR_NULL(pd)) { + seq_printf(s, "pd[%d]: 0x%p\n", i, pd); + continue; + } + + seq_printf(s, "%c [%-9s %11s]\n", + (pd->status == GPD_STATE_ACTIVE) ? '+' : '-', + pd->name, gpd_status_name[pd->status]); + + list_for_each_entry(pdd, &pd->dev_list, list_node) { + struct device *dev = pdd->dev; + struct platform_device *pdev = to_platform_device(dev); + + seq_printf(s, "\t%c (%-16s %3d, %d, %10s)\n", + pm_runtime_active(dev) ? '+' : '-', + pdev->name, + atomic_read(&dev->power.usage_count), + dev->power.disable_depth, + prm_status_name[dev->power.runtime_status]); + } + } +} + +static int clkdbg_dump_genpd(struct seq_file *s, void *v) +{ + seq_print_all_genpd(s); + + return 0; +} + +static int clkdbg_pm_genpd_poweron(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *genpd_name; + struct generic_pm_domain *pd; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + genpd_name = strsep(&c, " "); + + seq_printf(s, "pm_genpd_poweron(%s): ", genpd_name); + + pd = genpd_from_name(genpd_name); + if (pd) { + int r = pm_genpd_poweron(pd); + + seq_printf(s, "%d\n", r); + } else { + seq_puts(s, "NULL\n"); + } + + return 0; +} + +static int clkdbg_pm_genpd_poweroff_unused(struct seq_file *s, void *v) +{ + seq_puts(s, "pm_genpd_poweroff_unused()\n"); + pm_genpd_poweroff_unused(); + + return 0; +} + +static int clkdbg_pm_runtime_enable(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *dev_name; + struct platform_device *pdev; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + dev_name = strsep(&c, " "); + + seq_printf(s, "pm_runtime_enable(%s): ", dev_name); + + pdev = pdev_from_name(dev_name); + if (pdev) { + pm_runtime_enable(&pdev->dev); + seq_puts(s, "\n"); + } else { + seq_puts(s, "NULL\n"); + } + + return 0; +} + +static int clkdbg_pm_runtime_disable(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *dev_name; + struct platform_device *pdev; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + dev_name = strsep(&c, " "); + + seq_printf(s, "pm_runtime_disable(%s): ", dev_name); + + pdev = pdev_from_name(dev_name); + if (pdev) { + pm_runtime_disable(&pdev->dev); + seq_puts(s, "\n"); + } else { + seq_puts(s, "NULL\n"); + } + + return 0; +} + +static int clkdbg_pm_runtime_get_sync(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *dev_name; + struct platform_device *pdev; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + dev_name = strsep(&c, " "); + + seq_printf(s, "pm_runtime_get_sync(%s): ", dev_name); + + pdev = pdev_from_name(dev_name); + if (pdev) { + int r = pm_runtime_get_sync(&pdev->dev); + + seq_printf(s, "%d\n", r); + } else { + seq_puts(s, "NULL\n"); + } + + return 0; +} + +static int clkdbg_pm_runtime_put_sync(struct seq_file *s, void *v) +{ + char cmd[sizeof(last_cmd) + 1]; + char *c = cmd; + char *ign; + char *dev_name; + struct platform_device *pdev; + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + ign = strsep(&c, " "); + dev_name = strsep(&c, " "); + + seq_printf(s, "pm_runtime_put_sync(%s): ", dev_name); + + pdev = pdev_from_name(dev_name); + if (pdev) { + int r = pm_runtime_put_sync(&pdev->dev); + + seq_printf(s, "%d\n", r); + } else { + seq_puts(s, "NULL\n"); + } + + return 0; +} + +#endif /* CLKDBG_PM_DOMAIN */ + +#define CMDFN(_cmd, _fn) { \ + .cmd = _cmd, \ + .fn = _fn, \ +} + +static int clkdbg_show(struct seq_file *s, void *v) +{ + static const struct { + const char *cmd; + int (*fn)(struct seq_file *, void *); + } cmds[] = { + CMDFN("dump_regs", seq_print_regs), + CMDFN("dump_state", clkdbg_dump_state_all), + CMDFN("fmeter", seq_print_fmeter_all), + CMDFN("prepare_enable", clkdbg_prepare_enable), + CMDFN("disable_unprepare", clkdbg_disable_unprepare), + CMDFN("set_parent", clkdbg_set_parent), + CMDFN("set_rate", clkdbg_set_rate), + CMDFN("reg_read", clkdbg_reg_read), + CMDFN("reg_write", clkdbg_reg_write), + CMDFN("reg_set", clkdbg_reg_set), + CMDFN("reg_clr", clkdbg_reg_clr), +#if CLKDBG_PM_DOMAIN + CMDFN("dump_genpd", clkdbg_dump_genpd), + CMDFN("pm_genpd_poweron", clkdbg_pm_genpd_poweron), + CMDFN("pm_genpd_poweroff_unused", + clkdbg_pm_genpd_poweroff_unused), + CMDFN("pm_runtime_enable", clkdbg_pm_runtime_enable), + CMDFN("pm_runtime_disable", clkdbg_pm_runtime_disable), + CMDFN("pm_runtime_get_sync", clkdbg_pm_runtime_get_sync), + CMDFN("pm_runtime_put_sync", clkdbg_pm_runtime_put_sync), +#endif /* CLKDBG_PM_DOMAIN */ + }; + + int i; + char cmd[sizeof(last_cmd) + 1]; + + pr_debug("last_cmd: %s\n", last_cmd); + + strncpy(cmd, last_cmd, sizeof(last_cmd)); + + for (i = 0; i < ARRAY_SIZE(cmds); i++) { + char *c = cmd; + char *token = strsep(&c, " "); + + if (strcmp(cmds[i].cmd, token) == 0) + return cmds[i].fn(s, v); + } + + return 0; +} + +static int clkdbg_open(struct inode *inode, struct file *file) +{ + return single_open(file, clkdbg_show, NULL); +} + +static ssize_t clkdbg_write( + struct file *file, + const char __user *buffer, + size_t count, + loff_t *data) +{ + char desc[sizeof(last_cmd) - 1]; + int len = 0; + + pr_debug("count: %zu\n", count); + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + strncpy(last_cmd, desc, sizeof(last_cmd)); + if (last_cmd[len - 1] == '\n') + last_cmd[len - 1] = 0; + + return count; +} + +static const struct file_operations clkdbg_fops = { + .owner = THIS_MODULE, + .open = clkdbg_open, + .read = seq_read, + .write = clkdbg_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static void __iomem *get_reg(struct device_node *np, int index) +{ +#if DUMMY_REG_TEST + return kzalloc(PAGE_SIZE, GFP_KERNEL); +#else + return of_iomap(np, index); +#endif +} + +static int __init get_base_from_node( + const char *cmp, int idx, void __iomem **pbase) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, cmp); + + if (!node) { + clk_warn("node '%s' not found!\n", cmp); + return -1; + } + + *pbase = get_reg(node, idx); + clk_info("%s base: 0x%p\n", cmp, *pbase); + + return 0; +} + +static void __init init_iomap(void) +{ +#if CLKDBG_6755 + get_base_from_node("mediatek,mt6755-topckgen", 0, &topckgen_base); + get_base_from_node("mediatek,mt6755-infrasys", 0, &infrasys_base); + get_base_from_node("mediatek,mt6755-perisys", 0, &perisys_base); + get_base_from_node("mediatek,mcucfg", 0, &mcucfg_base); + get_base_from_node("mediatek,mt6755-apmixedsys", 0, &apmixedsys_base); + get_base_from_node("mediatek,mt6755-mfgsys", 0, &mfgsys_base); + get_base_from_node("mediatek,mt6755-mmsys", 0, &mmsys_base); + get_base_from_node("mediatek,mt6755-imgsys", 0, &imgsys_base); + get_base_from_node("mediatek,mt6755-vdecsys", 0, &vdecsys_base); + get_base_from_node("mediatek,mt6755-vencsys", 0, &vencsys_base); + get_base_from_node("mediatek,mt6755-audiosys", 0, &audiosys_base); + get_base_from_node("mediatek,mt6755-scpsys", 1, &scpsys_base); +#endif /* CLKDBG_SOC */ +} + +/* + * clkdbg pm_domain support + */ + +static const struct of_device_id clkdbg_id_table[] = { + { .compatible = "mediatek,clkdbg-pd",}, + { }, +}; +MODULE_DEVICE_TABLE(of, clkdbg_id_table); + +static int clkdbg_probe(struct platform_device *pdev) +{ + clk_info("%s():%d: pdev: %s\n", __func__, __LINE__, pdev->name); + + return 0; +} + +static int clkdbg_remove(struct platform_device *pdev) +{ + clk_info("%s():%d: pdev: %s\n", __func__, __LINE__, pdev->name); + + return 0; +} + +static int clkdbg_pd_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + clk_info("%s():%d: pdev: %s\n", __func__, __LINE__, pdev->name); + + return 0; +} + +static int clkdbg_pd_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + clk_info("%s():%d: pdev: %s\n", __func__, __LINE__, pdev->name); + + return 0; +} + +static const struct dev_pm_ops clkdbg_pd_pm_ops = { + .runtime_suspend = clkdbg_pd_runtime_suspend, + .runtime_resume = clkdbg_pd_runtime_resume, +}; + +static struct platform_driver clkdbg_driver = { + .probe = clkdbg_probe, + .remove = clkdbg_remove, + .driver = { + .name = "clkdbg", + .owner = THIS_MODULE, + .of_match_table = clkdbg_id_table, + .pm = &clkdbg_pd_pm_ops, + }, +}; + +module_platform_driver(clkdbg_driver); + +/* + * pm_domain sample code + */ + +static struct platform_device *my_pdev; + +int power_on_before_work(void) +{ + return pm_runtime_get_sync(&my_pdev->dev); +} + +int power_off_after_work(void) +{ + return pm_runtime_put_sync(&my_pdev->dev); +} + +static const struct of_device_id my_id_table[] = { + { .compatible = "mediatek,my-device",}, + { }, +}; +MODULE_DEVICE_TABLE(of, my_id_table); + +static int my_probe(struct platform_device *pdev) +{ + pm_runtime_enable(&pdev->dev); + + my_pdev = pdev; + + return 0; +} + +static int my_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static struct platform_driver my_driver = { + .probe = my_probe, + .remove = my_remove, + .driver = { + .name = "my_driver", + .owner = THIS_MODULE, + .of_match_table = my_id_table, + }, +}; + +module_platform_driver(my_driver); + +/* + * init functions + */ + +int __init mt_clkdbg_init(void) +{ + init_iomap(); + +#if DUMP_INIT_STATE + print_regs(); + print_fmeter_all(); +#endif /* DUMP_INIT_STATE */ + + return 0; +} +arch_initcall(mt_clkdbg_init); + +int __init mt_clkdbg_debug_init(void) +{ + struct proc_dir_entry *entry; + + entry = proc_create("clkdbg", 0, 0, &clkdbg_fops); + if (!entry) + return -ENOMEM; + + return 0; +} +module_init(mt_clkdbg_debug_init); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_cpu_psci_ops.h b/drivers/misc/mediatek/base/power/mt6755/mt_cpu_psci_ops.h new file mode 100644 index 0000000000000000000000000000000000000000..8242a3e99db7d6cac8b0a45ab10d708bc4e650d9 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_cpu_psci_ops.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * 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. + */ + +extern const struct cpu_operations cpu_psci_ops; + +#ifdef CONFIG_MTK_PSCI +extern const struct cpu_operations mt_cpu_psci_ops; +#endif + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq.c b/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq.c new file mode 100644 index 0000000000000000000000000000000000000000..8f63c0146459fb5212dcc59f0223fdac473ab90a --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq.c @@ -0,0 +1,4492 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @file mt_cpufreq.c + * @brief Driver for CPU DVFS + * + */ + +#define __MT_CPUFREQ_C__ +#define DEBUG 1 +/* system includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#endif + +/* project includes */ +#include "mach/mt_thermal.h" +#include "mt_static_power.h" +#include "mach/mt_pmic_wrap.h" +#include "mach/mt_freqhopping.h" +#include "mach/mt_ppm_api.h" +/* #include "mach/mt_ptp.h" +#include "mach/upmu_common.h" +#include "mach/upmu_sw.h" +#include "mach/upmu_hw.h" +#include "mach/mt_hotplug_strategy.h" +#include "mach/mt_pbm.h" +#include "mt-plat/mt_devinfo.h" */ + +/* local includes */ +#include "mt_cpufreq.h" + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#include "../../../pmic/include/pmic_api.h" +#else +#include "../../../power/mt6755/mt6311.h" +#endif + +#include +#include +#include +#include "mt-plat/mt_devinfo.h" +#include "mt_cpufreq_hybrid.h" + +/*=============================================================*/ +/* Macro definition */ +/*=============================================================*/ +#if defined(CONFIG_OF) +static unsigned long infracfg_ao_base; +static unsigned long topckgen_base; +static unsigned long apmixed_base; + +#define INFRACFG_AO_NODE "mediatek,mt6755-infrasys" +#define TOPCKGEN_NODE "mediatek,topckgen" +#define APMIXED_NODE "mediatek,apmixed" + +#undef INFRACFG_AO_BASE +#undef TOPCKGEN_BASE +#undef APMIXED_BASE + +#define INFRACFG_AO_BASE (infracfg_ao_base) /* 0xF0001000 */ +#define TOPCKGEN_BASE (topckgen_base) /* 0xF0000000 */ +#define APMIXED_BASE (apmixed_base) /* 0xF000C000 */ + +#else /* #if defined (CONFIG_OF) */ +#undef INFRACFG_AO_BASE +#undef TOPCKGEN_BASE +#undef APMIXED_BASE + +#define INFRACFG_AO_BASE 0xF0001000 +#define TOPCKGEN_BASE 0xF0000000 +#define APMIXED_BASE 0xF000C000 +#endif /* #if defined (CONFIG_OF) */ + +#define ARMCA15PLL_CON0 (APMIXED_BASE + 0x200) +#define ARMCA15PLL_CON1 (APMIXED_BASE + 0x204) +#define ARMCA15PLL_CON2 (APMIXED_BASE + 0x208) +#define ARMCA7PLL_CON0 (APMIXED_BASE + 0x210) +#define ARMCA7PLL_CON1 (APMIXED_BASE + 0x214) +#define ARMCA7PLL_CON2 (APMIXED_BASE + 0x218) + +/* INFRASYS Register */ +#define TOP_CKMUXSEL (INFRACFG_AO_BASE + 0x00) +#define TOP_CKDIV1 (INFRACFG_AO_BASE + 0x08) +#define INFRA_TOPCKGEN_CKDIV1_BIG (INFRACFG_AO_BASE + 0x0024) +#define INFRA_TOPCKGEN_CKDIV1_SML (INFRACFG_AO_BASE + 0x0028) +#define INFRA_TOPCKGEN_CKDIV1_BUS (INFRACFG_AO_BASE + 0x002C) + +/* TOPCKGEN Register */ +#define CLK_MISC_CFG_0 (TOPCKGEN_BASE + 0x104) + +/* + * CONFIG + */ +#define DCM_ENABLE 1 +#define CONFIG_CPU_DVFS_SHOWLOG 1 +/* #define CONFIG_CPU_DVFS_BRINGUP 1 */ +#ifdef CONFIG_MTK_RAM_CONSOLE +#define CONFIG_CPU_DVFS_AEE_RR_REC 1 +#endif + +#ifdef CONFIG_HYBRID_CPU_DVFS +/** + * 1: get voltage from DVFSP for performance + * 2: get voltage from PMIC through I2C + */ +static u32 enable_cpuhvfs = 1; +#endif + +#include +ktime_t now[NR_SET_V_F]; +ktime_t delta[NR_SET_V_F]; +ktime_t max[NR_SET_V_F]; + +#define MAX(a, b) ((a) >= (b) ? (a) : (b)) +#define MIN(a, b) ((a) >= (b) ? (b) : (a)) + +/* used @ set_cur_volt_extBuck() */ +/* #define MIN_DIFF_VSRAM_PROC 1000 */ +#define NORMAL_DIFF_VRSAM_VPROC 10000 +#define MAX_DIFF_VSRAM_VPROC 20000 +#define MIN_VSRAM_VOLT 93000 +#define MAX_VSRAM_VOLT 115000 +#define MAX_VPROC_VOLT 115000 + +/* PMIC/PLL settle time (us) */ +#define PMIC_CMD_DELAY_TIME 5 +#define MIN_PMIC_SETTLE_TIME 25 +#define PMIC_VOLT_UP_SETTLE_TIME(old_volt, new_volt) \ + (((((new_volt) - (old_volt)) + 1250 - 1) / 1250) + PMIC_CMD_DELAY_TIME) +#define PMIC_VOLT_DOWN_SETTLE_TIME(old_volt, new_volt) \ + (((((old_volt) - (new_volt)) * 2) / 625) + PMIC_CMD_DELAY_TIME) +#define PLL_SETTLE_TIME (20) + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +/* for DVFS OPP table LL/FY */ +#define CPU_DVFS_FREQ0_LL (1001000) /* KHz */ +#define CPU_DVFS_FREQ1_LL (910000) /* KHz */ +#define CPU_DVFS_FREQ2_LL (819000) /* KHz */ +#define CPU_DVFS_FREQ3_LL (689000) /* KHz */ +#define CPU_DVFS_FREQ4_LL (598000) /* KHz */ +#define CPU_DVFS_FREQ5_LL (494000) /* KHz */ +#define CPU_DVFS_FREQ6_LL (338000) /* KHz */ +#define CPU_DVFS_FREQ7_LL (156000) /* KHz */ + +/* for DVFS OPP table L/FY */ +#define CPU_DVFS_FREQ0_L (1508000) /* KHz */ +#define CPU_DVFS_FREQ1_L (1430000) /* KHz */ +#define CPU_DVFS_FREQ2_L (1352000) /* KHz */ +#define CPU_DVFS_FREQ3_L (1196000) /* KHz */ +#define CPU_DVFS_FREQ4_L (1027000) /* KHz */ +#define CPU_DVFS_FREQ5_L (871000) /* KHz */ +#define CPU_DVFS_FREQ6_L (663000) /* KHz */ +#define CPU_DVFS_FREQ7_L (286000) /* KHz */ +#else + +/* for DVFS OPP table LL/FY */ +#define CPU_DVFS_FREQ0_LL (1001000) /* KHz */ +#define CPU_DVFS_FREQ1_LL (910000) /* KHz */ +#define CPU_DVFS_FREQ2_LL (819000) /* KHz */ +#define CPU_DVFS_FREQ3_LL (689000) /* KHz */ +#define CPU_DVFS_FREQ4_LL (598000) /* KHz */ +#define CPU_DVFS_FREQ5_LL (494000) /* KHz */ +#define CPU_DVFS_FREQ6_LL (338000) /* KHz */ +#define CPU_DVFS_FREQ7_LL (156000) /* KHz */ + +/* for DVFS OPP table L/FY */ +#define CPU_DVFS_FREQ0_L (1807000) /* KHz */ +#define CPU_DVFS_FREQ1_L (1651000) /* KHz */ +#define CPU_DVFS_FREQ2_L (1495000) /* KHz */ +#define CPU_DVFS_FREQ3_L (1196000) /* KHz */ +#define CPU_DVFS_FREQ4_L (1027000) /* KHz */ +#define CPU_DVFS_FREQ5_L (871000) /* KHz */ +#define CPU_DVFS_FREQ6_L (663000) /* KHz */ +#define CPU_DVFS_FREQ7_L (286000) /* KHz */ +#endif + +/* for DVFS OPP table LL/SB */ +#define CPU_DVFS_FREQ0_LL_SB (1144000) /* KHz */ +#define CPU_DVFS_FREQ1_LL_SB (1014000) /* KHz */ +#define CPU_DVFS_FREQ2_LL_SB (871000) /* KHz */ +#define CPU_DVFS_FREQ3_LL_SB (689000) /* KHz */ +#define CPU_DVFS_FREQ4_LL_SB (598000) /* KHz */ +#define CPU_DVFS_FREQ5_LL_SB (494000) /* KHz */ +#define CPU_DVFS_FREQ6_LL_SB (338000) /* KHz */ +#define CPU_DVFS_FREQ7_LL_SB (156000) /* KHz */ + +/* for DVFS OPP table L/SB */ +#define CPU_DVFS_FREQ0_L_SB (1950000) /* KHz */ +#define CPU_DVFS_FREQ1_L_SB (1755000) /* KHz */ +#define CPU_DVFS_FREQ2_L_SB (1573000) /* KHz */ +#define CPU_DVFS_FREQ3_L_SB (1196000) /* KHz */ +#define CPU_DVFS_FREQ4_L_SB (1027000) /* KHz */ +#define CPU_DVFS_FREQ5_L_SB (871000) /* KHz */ +#define CPU_DVFS_FREQ6_L_SB (663000) /* KHz */ +#define CPU_DVFS_FREQ7_L_SB (286000) /* KHz */ +/* for DVFS OPP table LL/P15 */ +#define CPU_DVFS_FREQ0_LL_P15 (1248000) /* KHz */ +#define CPU_DVFS_FREQ1_LL_P15 (1079000) /* KHz */ +#define CPU_DVFS_FREQ2_LL_P15 (910000) /* KHz */ +#define CPU_DVFS_FREQ3_LL_P15 (689000) /* KHz */ +#define CPU_DVFS_FREQ4_LL_P15 (598000) /* KHz */ +#define CPU_DVFS_FREQ5_LL_P15 (494000) /* KHz */ +#define CPU_DVFS_FREQ6_LL_P15 (338000) /* KHz */ +#define CPU_DVFS_FREQ7_LL_P15 (156000) /* KHz */ +/* for DVFS OPP table L/P15 */ +#define CPU_DVFS_FREQ0_L_P15 (2145000) /* KHz */ +#define CPU_DVFS_FREQ1_L_P15 (1911000) /* KHz */ +#define CPU_DVFS_FREQ2_L_P15 (1664000) /* KHz */ +#define CPU_DVFS_FREQ3_L_P15 (1196000) /* KHz */ +#define CPU_DVFS_FREQ4_L_P15 (1027000) /* KHz */ +#define CPU_DVFS_FREQ5_L_P15 (871000) /* KHz */ +#define CPU_DVFS_FREQ6_L_P15 (663000) /* KHz */ +#define CPU_DVFS_FREQ7_L_P15 (286000) /* KHz */ +#define CPUFREQ_BOUNDARY_FOR_FHCTL (CPU_DVFS_FREQ4_L) +#define CPUFREQ_LAST_FREQ_LEVEL (CPU_DVFS_FREQ7_LL) + +/* Debugging */ +#undef TAG +#define TAG "[Power/cpufreq] " + +#define cpufreq_err(fmt, args...) \ + pr_err(TAG"[ERROR]"fmt, ##args) +#define cpufreq_warn(fmt, args...) \ + pr_warn(TAG"[WARNING]"fmt, ##args) +#define cpufreq_info(fmt, args...) \ + pr_warn(TAG""fmt, ##args) +#define cpufreq_dbg(fmt, args...) \ + pr_debug(TAG""fmt, ##args) +#define cpufreq_ver(fmt, args...) \ + do { \ + if (func_lv_mask) \ + cpufreq_info(TAG""fmt, ##args); \ + } while (0) + +#define FUNC_LV_MODULE BIT(0) /* module, platform driver interface */ +#define FUNC_LV_CPUFREQ BIT(1) /* cpufreq driver interface */ +#define FUNC_LV_API BIT(2) /* mt_cpufreq driver global function */ +#define FUNC_LV_LOCAL BIT(3) /* mt_cpufreq driver local function */ +#define FUNC_LV_HELP BIT(4) /* mt_cpufreq driver help function */ +#define FUNC_ENTER(lv) \ + do { if ((lv) & func_lv_mask) cpufreq_dbg(">> %s()\n", __func__); } while (0) +#define FUNC_EXIT(lv) \ + do { if ((lv) & func_lv_mask) cpufreq_dbg("<< %s():%d\n", __func__, __LINE__); } while (0) + +#define FUNC_LV_MODULE BIT(0) /* module, platform driver interface */ +#define FUNC_LV_CPUFREQ BIT(1) /* cpufreq driver interface */ +#define FUNC_LV_API BIT(2) /* mt_cpufreq driver global function */ +#define FUNC_LV_LOCAL BIT(3) /* mt_cpufreq driver local function */ +#define FUNC_LV_HELP BIT(4) /* mt_cpufreq driver help function */ + +/* +* static unsigned int func_lv_mask = +* (FUNC_LV_MODULE | FUNC_LV_CPUFREQ | FUNC_LV_API | FUNC_LV_LOCAL | FUNC_LV_HELP); +*/ +static unsigned int func_lv_mask; +static unsigned int do_dvfs_stress_test; +static unsigned int dvfs_power_mode; + +enum ppb_power_mode { + Default = 0, + Low_power_Mode = 1, + Just_Make_Mode = 2, + Performance_Mode = 3, +}; + +#ifdef CONFIG_CPU_DVFS_SHOWLOG +#define FUNC_ENTER(lv) \ + do { if ((lv) & func_lv_mask) cpufreq_dbg(">> %s()\n", __func__); } while (0) +#define FUNC_EXIT(lv) \ + do { if ((lv) & func_lv_mask) cpufreq_dbg("<< %s():%d\n", __func__, __LINE__); } while (0) +#else +#define FUNC_ENTER(lv) +#define FUNC_EXIT(lv) +#endif /* CONFIG_CPU_DVFS_SHOWLOG */ + +/* + * BIT Operation + */ +#define _BIT_(_bit_) (unsigned)(1 << (_bit_)) +#define _BITS_(_bits_, _val_) \ + ((((unsigned) -1 >> (31 - ((1) ? _bits_))) & ~((1U << ((0) ? _bits_)) - 1)) & ((_val_)<<((0) ? _bits_))) +#define _BITMASK_(_bits_) (((unsigned) -1 >> (31 - ((1) ? _bits_))) & ~((1U << ((0) ? _bits_)) - 1)) +#define _GET_BITS_VAL_(_bits_, _val_) (((_val_) & (_BITMASK_(_bits_))) >> ((0) ? _bits_)) + +/* + * REG ACCESS + */ +#define cpufreq_read(addr) __raw_readl(IOMEM(addr)) +#define cpufreq_write(addr, val) mt_reg_sync_writel((val), ((void *)addr)) + +#define cpufreq_write_mask(addr, mask, val) \ +cpufreq_write(addr, (cpufreq_read(addr) & ~(_BITMASK_(mask))) | _BITS_(mask, val)) + +/* + * LOCK + */ +#if 0 +static DEFINE_SPINLOCK(cpufreq_lock); +#define cpufreq_lock(flags) spin_lock_irqsave(&cpufreq_lock, flags) +#define cpufreq_unlock(flags) spin_unlock_irqrestore(&cpufreq_lock, flags) +#else /* mutex */ +static DEFINE_MUTEX(cpufreq_mutex); +bool is_in_cpufreq = 0; +#define cpufreq_lock(flags) \ + do { \ + flags = (unsigned long)&flags; \ + mutex_lock(&cpufreq_mutex); \ + is_in_cpufreq = 1;\ + } while (0) + +#define cpufreq_unlock(flags) \ + do { \ + flags = (unsigned long)&flags; \ + is_in_cpufreq = 0;\ + mutex_unlock(&cpufreq_mutex); \ + } while (0) +#endif + +/* + * EFUSE + */ +#define CPUFREQ_EFUSE_INDEX (3) +#define FUNC_CODE_EFUSE_INDEX (21) +#define FUNC_CODE_EFUSE_INDEX_ENG (19) + +#define CPU_LEVEL_0 (0x0) +#define CPU_LEVEL_1 (0x1) +#define CPU_LEVEL_2 (0x2) +#define CPU_LEVEL_3 (0x3) +#define CPU_LV_TO_OPP_IDX(lv) ((lv)) /* cpu_level to opp_idx */ + +#ifdef __KERNEL__ +static unsigned int _mt_cpufreq_get_cpu_level(void) +{ + unsigned int lv = 0; + unsigned int func_code_0 = _GET_BITS_VAL_(7:0, get_devinfo_with_index(FUNC_CODE_EFUSE_INDEX)); + unsigned int func_code_1 = _GET_BITS_VAL_(31:28, get_devinfo_with_index(FUNC_CODE_EFUSE_INDEX)); + unsigned int binLevel_eng = _GET_BITS_VAL_(15:0, get_devinfo_with_index(FUNC_CODE_EFUSE_INDEX_ENG)); + + cpufreq_ver("from efuse: function code 0 = 0x%x, function code 1 = 0x%x, binLevel_eng = 0x%x\n", + func_code_0, + func_code_1, + binLevel_eng); + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + return CPU_LEVEL_0; +#endif + + /* get CPU clock-frequency from DT */ +#ifdef CONFIG_OF + { + struct device_node *node = of_find_node_by_type(NULL, "cpu"); + unsigned int cpu_speed = 0; + + if (!of_property_read_u32(node, "clock-frequency", &cpu_speed)) + cpu_speed = cpu_speed / 1000 / 1000; /* MHz */ + else { + cpufreq_err + ("@%s: missing clock-frequency property, use default CPU level\n", + __func__); + return CPU_LEVEL_1; + } + + cpufreq_ver("CPU clock-frequency from DT = %d MHz\n", cpu_speed); + + if (cpu_speed == 1001) /* FY */ + return CPU_LEVEL_0; + else { + if ((1 == func_code_0) || (3 == func_code_0)) + return CPU_LEVEL_0; + else if ((2 == func_code_0) || (4 == func_code_0)) + return CPU_LEVEL_1; +#ifdef CONFIG_ARCH_MT6755_TURBO + else if (0x22 == func_code_0) + return CPU_LEVEL_2; +#endif + else { + if ((2 == ((binLevel_eng >> 4) & 0x07)) || (2 == ((binLevel_eng >> 10) & 0x07))) + return CPU_LEVEL_0; + return CPU_LEVEL_1; + } + } + } + +#endif + + return lv; +} +#else +static unsigned int _mt_cpufreq_get_cpu_level(void) +{ + return CPU_LEVEL_0; +} +#endif + + +/* + * AEE (SRAM debug) + */ +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC +enum cpu_dvfs_state { + CPU_DVFS_LITTLE_IS_DOING_DVFS = 0, + CPU_DVFS_LITTLE_IS_TURBO, + CPU_DVFS_BIG_IS_DOING_DVFS = 0, + CPU_DVFS_BIG_IS_TURBO, +}; + +static void _mt_cpufreq_aee_init(void) +{ + aee_rr_rec_cpu_dvfs_vproc_big(0xFF); + aee_rr_rec_cpu_dvfs_vproc_little(0xFF); + aee_rr_rec_cpu_dvfs_oppidx(0xFF); + aee_rr_rec_cpu_dvfs_status(0xFC); +} +#endif + +/* + * PMIC_WRAP + */ +#define VOLT_TO_PMIC_VAL(volt) (((volt) - 60000 + 625 - 1) / 625) /* ((((volt) - 700 * 100 + 625 - 1) / 625) */ +#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + 60000) /* (((pmic) * 625) / 100 + 700) */ + +#define VOLT_TO_EXTBUCK_VAL(volt) VOLT_TO_PMIC_VAL(volt) /* (((((volt) - 300) + 9) / 10) & 0x7F) */ +#define EXTBUCK_VAL_TO_VOLT(val) PMIC_VAL_TO_VOLT(val) /* (300 + ((val) & 0x7F) * 10) */ + +/* cpu voltage sampler */ +static cpuVoltsampler_func g_pCpuVoltSampler; + +void mt_cpufreq_setvolt_registerCB(cpuVoltsampler_func pCB) +{ + g_pCpuVoltSampler = pCB; +} +EXPORT_SYMBOL(mt_cpufreq_setvolt_registerCB); + +/* + * mt_cpufreq driver + */ +#define FP(khz, pos, clk, cci) { \ + .target_f = khz, \ + .vco_dds = khz*pos*clk, \ + .pos_div = pos, \ + .clk_div = clk, \ + .cci_div = cci, \ +} +struct mt_cpu_freq_method { + const unsigned int target_f; + const unsigned int vco_dds; + const unsigned int pos_div; + const unsigned int clk_div; + const unsigned int cci_div; +}; +#define OP(khz, volt) { \ + .cpufreq_khz = khz, \ + .cpufreq_volt = volt, \ + .cpufreq_volt_org = volt, \ +} + +struct mt_cpu_freq_info { + const unsigned int cpufreq_khz; + unsigned int cpufreq_volt; + const unsigned int cpufreq_volt_org; +}; + +struct opp_idx_tbl { + struct mt_cpu_dvfs *p; + struct mt_cpu_freq_method *slot; +}; + +enum opp_idx_type { + CUR_OPP_IDX = 0, + TARGET_OPP_IDX = 1, + CUR_CCI_OPP_IDX = 2, + TARGET_CCI_OPP_IDX = 3, + BACKUP_CCI_OPP_IDX = 4, + + NR_OPP_IDX, +}; +struct opp_idx_tbl opp_tbl[NR_OPP_IDX]; + +struct mt_cpu_dvfs { + const char *name; + unsigned int cpu_id; /* for cpufreq */ + unsigned int cpu_level; + struct mt_cpu_dvfs_ops *ops; + unsigned int *armpll_addr; /* for armpll clock address */ + enum top_ckmuxsel_cci armpll_clk_src; /* for cci switch clock source */ + struct mt_cpu_freq_method *freq_tbl; /* Frequency table */ + struct mt_cpu_freq_info *opp_tbl; /* OPP table */ + int nr_opp_tbl; /* size for OPP table */ + int idx_opp_tbl; /* current OPP idx */ + int idx_opp_ppm_base; /* ppm update base */ + int idx_opp_ppm_limit; /* ppm update limit */ + int armpll_is_available; /* For CCI clock switch flag */ + int idx_normal_max_opp; /* idx for normal max OPP */ + + struct cpufreq_frequency_table *freq_tbl_for_cpufreq; /* freq table for cpufreq */ + + /* enable/disable DVFS function */ + bool dvfs_disable_by_suspend; + bool dvfs_disable_by_procfs; + + /* turbo mode */ + unsigned int turbo_mode; + +}; + +struct mt_cpu_dvfs_ops { + /* for freq change (PLL/MUX) */ + unsigned int (*get_cur_phy_freq)(struct mt_cpu_dvfs *p); /* return (physical) freq (KHz) */ + void (*set_cur_freq)(struct mt_cpu_dvfs *p, unsigned int cur_khz, unsigned int target_khz); /* set freq */ + /* for volt change (PMICWRAP/extBuck) */ + unsigned int (*get_cur_volt)(struct mt_cpu_dvfs *p); /* return volt (mV * 100) */ + int (*set_cur_volt)(struct mt_cpu_dvfs *p, unsigned int volt); /* set volt (mv * 100) */ +}; + +/* for freq change (PLL/MUX) */ +static unsigned int get_cur_phy_freq_L(struct mt_cpu_dvfs *p); +static unsigned int get_cur_phy_freq_LL(struct mt_cpu_dvfs *p); +static void set_cur_freq(struct mt_cpu_dvfs *p, unsigned int cur_khz, unsigned int target_khz); +static enum top_ckmuxsel_cci _get_cci_clock_switch(void); +static void cci_switch_from_to(enum opp_idx_type from, enum opp_idx_type to); +/* for volt change (PMICWRAP/extBuck) */ +static unsigned int get_cur_volt_extbuck(struct mt_cpu_dvfs *p); +static int set_cur_volt_extbuck(struct mt_cpu_dvfs *p, unsigned int volt); /* volt: mv * 100 */ +/* CPU callback */ +static int __cpuinit _mt_cpufreq_cpu_CB(struct notifier_block *nfb, unsigned long action, + void *hcpu); +static unsigned int max_cpu_num = 8; + +static struct mt_cpu_dvfs_ops dvfs_ops_LL = { + .get_cur_phy_freq = get_cur_phy_freq_LL, + .set_cur_freq = set_cur_freq, + .get_cur_volt = get_cur_volt_extbuck, + .set_cur_volt = set_cur_volt_extbuck, +}; + +static struct mt_cpu_dvfs_ops dvfs_ops_L = { + .get_cur_phy_freq = get_cur_phy_freq_L, + .set_cur_freq = set_cur_freq, + .get_cur_volt = get_cur_volt_extbuck, + .set_cur_volt = set_cur_volt_extbuck, +}; + +static struct mt_cpu_dvfs cpu_dvfs[] = { + [MT_CPU_DVFS_LITTLE] = { + .name = __stringify(MT_CPU_DVFS_LITTLE), + .cpu_id = MT_CPU_DVFS_LITTLE, + .cpu_level = CPU_LEVEL_0, + .idx_normal_max_opp = -1, + .idx_opp_ppm_base = -1, + .idx_opp_ppm_limit = -1, + .ops = &dvfs_ops_LL, + }, + + [MT_CPU_DVFS_BIG] = { + .name = __stringify(MT_CPU_DVFS_BIG), + .cpu_id = MT_CPU_DVFS_BIG, + .cpu_level = CPU_LEVEL_0, + .idx_normal_max_opp = -1, + .idx_opp_ppm_base = -1, + .idx_opp_ppm_limit = -1, + .ops = &dvfs_ops_L, + }, +}; + +#define for_each_cpu_dvfs(i, p) for (i = 0, p = cpu_dvfs; i < NR_MT_CPU_DVFS; i++, p = &cpu_dvfs[i]) +#define cpu_dvfs_is(p, id) (p == &cpu_dvfs[id]) +#define cpu_dvfs_is_available(p) (p->opp_tbl) +#define cpu_dvfs_get_name(p) (p->name) + +#define cpu_dvfs_get_cur_freq(p) (p->opp_tbl[p->idx_opp_tbl].cpufreq_khz) +#define cpu_dvfs_get_freq_by_idx(p, idx) (p->opp_tbl[idx].cpufreq_khz) + +#define cpu_dvfs_get_max_freq(p) (p->opp_tbl[0].cpufreq_khz) +#define cpu_dvfs_get_normal_max_freq(p) (p->opp_tbl[p->idx_normal_max_opp].cpufreq_khz) +#define cpu_dvfs_get_min_freq(p) (p->opp_tbl[p->nr_opp_tbl - 1].cpufreq_khz) + +#define cpu_dvfs_get_cur_volt(p) (p->opp_tbl[p->idx_opp_tbl].cpufreq_volt) +#define cpu_dvfs_get_volt_by_idx(p, idx) (p->opp_tbl[idx].cpufreq_volt) + +#define cpu_dvfs_is_extbuck_valid() (is_ext_buck_exist() && is_ext_buck_sw_ready()) + +static struct mt_cpu_dvfs *id_to_cpu_dvfs(enum mt_cpu_dvfs_id id) +{ + return (id < NR_MT_CPU_DVFS) ? &cpu_dvfs[id] : NULL; +} + +#ifdef CONFIG_HYBRID_CPU_DVFS +static inline unsigned int id_to_cluster(enum mt_cpu_dvfs_id id) +{ + if (id == MT_CPU_DVFS_LITTLE) + return CPU_CLUSTER_LL; + if (id == MT_CPU_DVFS_BIG) + return CPU_CLUSTER_L; + + BUG(); + return NUM_CPU_CLUSTER; +} + +static inline unsigned int cpu_dvfs_to_cluster(struct mt_cpu_dvfs *p) +{ + if (p == &cpu_dvfs[MT_CPU_DVFS_LITTLE]) + return CPU_CLUSTER_LL; + if (p == &cpu_dvfs[MT_CPU_DVFS_BIG]) + return CPU_CLUSTER_L; + + BUG(); + return NUM_CPU_CLUSTER; +} + +static inline struct mt_cpu_dvfs *cluster_to_cpu_dvfs(unsigned int cluster) +{ + if (cluster == CPU_CLUSTER_LL) + return &cpu_dvfs[MT_CPU_DVFS_LITTLE]; + if (cluster == CPU_CLUSTER_L) + return &cpu_dvfs[MT_CPU_DVFS_BIG]; + + BUG(); + return NULL; +} +#endif + +static void aee_record_cpu_volt(struct mt_cpu_dvfs *p, unsigned int volt) +{ +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + aee_rr_rec_cpu_dvfs_vproc_little(VOLT_TO_PMIC_VAL(volt)); + else + aee_rr_rec_cpu_dvfs_vproc_big(VOLT_TO_PMIC_VAL(volt)); +#endif +} + +static void notify_cpu_volt_sampler(struct mt_cpu_dvfs *p, unsigned int volt) +{ + unsigned int mv = volt / 100; + enum mt_cpu_dvfs_id id; + + if (!g_pCpuVoltSampler) + return; + + id = (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE) ? MT_CPU_DVFS_LITTLE : MT_CPU_DVFS_BIG); + g_pCpuVoltSampler(id, mv); +} + + +/* DVFS OPP table */ +/* Notice: Each table MUST has 8 element to avoid ptpod error */ + +#define NR_MAX_OPP_TBL 8 +#define NR_MAX_CPU 8 + +/* CPU LEVEL 0 of LL, FY segment */ +static struct mt_cpu_freq_info opp_tbl_little_e1_0[] = { + OP(CPU_DVFS_FREQ0_LL, 115000), + OP(CPU_DVFS_FREQ1_LL, 111250), + OP(CPU_DVFS_FREQ2_LL, 107500), + OP(CPU_DVFS_FREQ3_LL, 100000), + OP(CPU_DVFS_FREQ4_LL, 96875), + OP(CPU_DVFS_FREQ5_LL, 93750), + OP(CPU_DVFS_FREQ6_LL, 90000), + OP(CPU_DVFS_FREQ7_LL, 80000), +}; + +/* CPU LEVEL 1 of LL, SB segment */ +static struct mt_cpu_freq_info opp_tbl_little_e2_0[] = { + OP(CPU_DVFS_FREQ0_LL_SB, 115000), + OP(CPU_DVFS_FREQ1_LL_SB, 111250), + OP(CPU_DVFS_FREQ2_LL_SB, 107500), + OP(CPU_DVFS_FREQ3_LL_SB, 100000), + OP(CPU_DVFS_FREQ4_LL_SB, 96875), + OP(CPU_DVFS_FREQ5_LL_SB, 93750), + OP(CPU_DVFS_FREQ6_LL_SB, 90000), + OP(CPU_DVFS_FREQ7_LL_SB, 80000), +}; + +/* CPU LEVEL 1 of LL, P15 segment */ +static struct mt_cpu_freq_info opp_tbl_little_e3_0[] = { + OP(CPU_DVFS_FREQ0_LL_P15, 115000), + OP(CPU_DVFS_FREQ1_LL_P15, 111250), + OP(CPU_DVFS_FREQ2_LL_P15, 107500), + OP(CPU_DVFS_FREQ3_LL_P15, 100000), + OP(CPU_DVFS_FREQ4_LL_P15, 96875), + OP(CPU_DVFS_FREQ5_LL_P15, 93750), + OP(CPU_DVFS_FREQ6_LL_P15, 90000), + OP(CPU_DVFS_FREQ7_LL_P15, 80000), +}; + +/* CPU LEVEL 0 of L, FY segment */ +static struct mt_cpu_freq_info opp_tbl_big_e1_0[] = { + OP(CPU_DVFS_FREQ0_L, 115000), + OP(CPU_DVFS_FREQ1_L, 111250), + OP(CPU_DVFS_FREQ2_L, 107500), + OP(CPU_DVFS_FREQ3_L, 100000), + OP(CPU_DVFS_FREQ4_L, 96875), + OP(CPU_DVFS_FREQ5_L, 93750), + OP(CPU_DVFS_FREQ6_L, 90000), + OP(CPU_DVFS_FREQ7_L, 80000), +}; + +/* CPU LEVEL 1 of L, SB segment */ +static struct mt_cpu_freq_info opp_tbl_big_e2_0[] = { + OP(CPU_DVFS_FREQ0_L_SB, 115000), + OP(CPU_DVFS_FREQ1_L_SB, 111250), + OP(CPU_DVFS_FREQ2_L_SB, 107500), + OP(CPU_DVFS_FREQ3_L_SB, 100000), + OP(CPU_DVFS_FREQ4_L_SB, 96875), + OP(CPU_DVFS_FREQ5_L_SB, 93750), + OP(CPU_DVFS_FREQ6_L_SB, 90000), + OP(CPU_DVFS_FREQ7_L_SB, 80000), +}; + +/* CPU LEVEL 1 of L, SB segment */ +static struct mt_cpu_freq_info opp_tbl_big_e3_0[] = { + OP(CPU_DVFS_FREQ0_L_P15, 115000), + OP(CPU_DVFS_FREQ1_L_P15, 111250), + OP(CPU_DVFS_FREQ2_L_P15, 107500), + OP(CPU_DVFS_FREQ3_L_P15, 100000), + OP(CPU_DVFS_FREQ4_L_P15, 96875), + OP(CPU_DVFS_FREQ5_L_P15, 93750), + OP(CPU_DVFS_FREQ6_L_P15, 90000), + OP(CPU_DVFS_FREQ7_L_P15, 80000), +}; + +static struct mt_cpu_freq_method opp_tbl_method_L_e1[] = { + /* Target Frequency, POS, CLK, CCI */ + FP(CPU_DVFS_FREQ0_L, 1, 1, 2), + FP(CPU_DVFS_FREQ1_L, 1, 1, 2), + FP(CPU_DVFS_FREQ2_L, 1, 1, 2), + FP(CPU_DVFS_FREQ3_L, 1, 1, 2), + FP(CPU_DVFS_FREQ4_L, 2, 1, 2), + FP(CPU_DVFS_FREQ5_L, 2, 1, 2), + FP(CPU_DVFS_FREQ6_L, 2, 1, 2), + FP(CPU_DVFS_FREQ7_L, 2, 2, 4), +}; + +static struct mt_cpu_freq_method opp_tbl_method_LL_e1[] = { + /* Target Frequency, POS, CLK, CCI */ + FP(CPU_DVFS_FREQ0_LL, 2, 1, 2), + FP(CPU_DVFS_FREQ1_LL, 2, 1, 2), + FP(CPU_DVFS_FREQ2_LL, 2, 1, 2), + FP(CPU_DVFS_FREQ3_LL, 2, 1, 2), + FP(CPU_DVFS_FREQ4_LL, 2, 1, 2), + FP(CPU_DVFS_FREQ5_LL, 2, 2, 4), + FP(CPU_DVFS_FREQ6_LL, 2, 2, 4), + FP(CPU_DVFS_FREQ7_LL, 2, 4, 6), +}; + +static struct mt_cpu_freq_method opp_tbl_method_L_e2[] = { + /* Target Frequency, POS, CLK, CCI */ + FP(CPU_DVFS_FREQ0_L_SB, 1, 1, 2), + FP(CPU_DVFS_FREQ1_L_SB, 1, 1, 2), + FP(CPU_DVFS_FREQ2_L_SB, 1, 1, 2), + FP(CPU_DVFS_FREQ3_L_SB, 1, 1, 2), + FP(CPU_DVFS_FREQ4_L_SB, 2, 1, 2), + FP(CPU_DVFS_FREQ5_L_SB, 2, 1, 2), + FP(CPU_DVFS_FREQ6_L_SB, 2, 1, 2), + FP(CPU_DVFS_FREQ7_L_SB, 2, 2, 4), +}; + +static struct mt_cpu_freq_method opp_tbl_method_LL_e2[] = { + /* Target Frequency, POS, CLK, CCI */ + FP(CPU_DVFS_FREQ0_LL_SB, 2, 1, 2), + FP(CPU_DVFS_FREQ1_LL_SB, 2, 1, 2), + FP(CPU_DVFS_FREQ2_LL_SB, 2, 1, 2), + FP(CPU_DVFS_FREQ3_LL_SB, 2, 1, 2), + FP(CPU_DVFS_FREQ4_LL_SB, 2, 1, 2), + FP(CPU_DVFS_FREQ5_LL_SB, 2, 2, 4), + FP(CPU_DVFS_FREQ6_LL_SB, 2, 2, 4), + FP(CPU_DVFS_FREQ7_LL_SB, 2, 4, 6), +}; + +static struct mt_cpu_freq_method opp_tbl_method_L_e3[] = { + /* Target Frequency, POS, CLK, CCI */ + FP(CPU_DVFS_FREQ0_L_P15, 1, 1, 2), + FP(CPU_DVFS_FREQ1_L_P15, 1, 1, 2), + FP(CPU_DVFS_FREQ2_L_P15, 1, 1, 2), + FP(CPU_DVFS_FREQ3_L_P15, 1, 1, 2), + FP(CPU_DVFS_FREQ4_L_P15, 2, 1, 2), + FP(CPU_DVFS_FREQ5_L_P15, 2, 1, 2), + FP(CPU_DVFS_FREQ6_L_P15, 2, 1, 2), + FP(CPU_DVFS_FREQ7_L_P15, 2, 2, 4), +}; + +static struct mt_cpu_freq_method opp_tbl_method_LL_e3[] = { + /* Target Frequency, POS, CLK, CCI */ + FP(CPU_DVFS_FREQ0_LL_P15, 2, 1, 2), + FP(CPU_DVFS_FREQ1_LL_P15, 2, 1, 2), + FP(CPU_DVFS_FREQ2_LL_P15, 2, 1, 2), + FP(CPU_DVFS_FREQ3_LL_P15, 2, 1, 2), + FP(CPU_DVFS_FREQ4_LL_P15, 2, 1, 2), + FP(CPU_DVFS_FREQ5_LL_P15, 2, 2, 4), + FP(CPU_DVFS_FREQ6_LL_P15, 2, 2, 4), + FP(CPU_DVFS_FREQ7_LL_P15, 2, 4, 6), +}; + +struct opp_tbl_info { + struct mt_cpu_freq_info *const opp_tbl; + const int size; +}; + +static struct opp_tbl_info opp_tbls_little[2][3] = { + { + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_0)] = {opp_tbl_little_e1_0, ARRAY_SIZE(opp_tbl_little_e1_0),}, + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_1)] = {opp_tbl_little_e2_0, ARRAY_SIZE(opp_tbl_little_e2_0),}, + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_2)] = {opp_tbl_little_e3_0, ARRAY_SIZE(opp_tbl_little_e3_0),}, + }, + { + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_0)] = {opp_tbl_little_e1_0, ARRAY_SIZE(opp_tbl_little_e1_0),}, + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_1)] = {opp_tbl_little_e2_0, ARRAY_SIZE(opp_tbl_little_e2_0),}, + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_2)] = {opp_tbl_little_e3_0, ARRAY_SIZE(opp_tbl_little_e3_0),}, + }, +}; + +static struct opp_tbl_info opp_tbls_big[2][3] = { + { + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_0)] = {opp_tbl_big_e1_0, ARRAY_SIZE(opp_tbl_big_e1_0),}, + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_1)] = {opp_tbl_big_e2_0, ARRAY_SIZE(opp_tbl_big_e2_0),}, + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_2)] = {opp_tbl_big_e3_0, ARRAY_SIZE(opp_tbl_big_e3_0),}, + }, + { + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_0)] = {opp_tbl_big_e1_0, ARRAY_SIZE(opp_tbl_big_e1_0),}, + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_1)] = {opp_tbl_big_e2_0, ARRAY_SIZE(opp_tbl_big_e2_0),}, + [CPU_LV_TO_OPP_IDX(CPU_LEVEL_2)] = {opp_tbl_big_e3_0, ARRAY_SIZE(opp_tbl_big_e3_0),}, + }, +}; + +static struct notifier_block __refdata _mt_cpufreq_cpu_notifier = { + .notifier_call = _mt_cpufreq_cpu_CB, +}; + +/* for freq change (PLL/MUX) */ +#define PLL_FREQ_STEP (13000) /* KHz */ + +#define PLL_MIN_FREQ (130000) /* KHz */ +#define PLL_DIV1_FREQ (1001000) /* KHz */ +#define PLL_DIV2_FREQ (520000) /* KHz */ +#define PLL_DIV4_FREQ (260000) /* KHz */ +#define PLL_DIV8_FREQ (PLL_MIN_FREQ) /* KHz */ + +#define DDS_DIV1_FREQ (0x0009A000) /* 1001MHz */ +#define DDS_DIV2_FREQ (0x010A0000) /* 520MHz */ +#define DDS_DIV4_FREQ (0x020A0000) /* 260MHz */ +#define DDS_DIV8_FREQ (0x030A0000) /* 130MHz */ + +int get_turbo_freq(int chip_id, int freq) +{ + return freq; +} + +int get_turbo_volt(int chip_id, int volt) +{ + return volt; +} + +static int _search_available_freq_idx(struct mt_cpu_dvfs *p, unsigned int target_khz, + unsigned int relation) +{ + int new_opp_idx = -1; + int i; + + FUNC_ENTER(FUNC_LV_HELP); + + if (CPUFREQ_RELATION_L == relation) { + for (i = (signed)(p->nr_opp_tbl - 1); i >= 0; i--) { + if (cpu_dvfs_get_freq_by_idx(p, i) >= target_khz) { + new_opp_idx = i; + break; + } + } + } else { /* CPUFREQ_RELATION_H */ + for (i = 0; i < (signed)p->nr_opp_tbl; i++) { + if (cpu_dvfs_get_freq_by_idx(p, i) <= target_khz) { + new_opp_idx = i; + break; + } + } + } + + FUNC_EXIT(FUNC_LV_HELP); + + return new_opp_idx; +} + +/* for PTP-OD */ +static mt_cpufreq_set_ptbl_funcPTP mt_cpufreq_update_private_tbl; + +void mt_cpufreq_set_ptbl_registerCB(mt_cpufreq_set_ptbl_funcPTP pCB) +{ + mt_cpufreq_update_private_tbl = pCB; +} +EXPORT_SYMBOL(mt_cpufreq_set_ptbl_registerCB); + +static int _set_cur_volt_locked(struct mt_cpu_dvfs *p, unsigned int volt) /* volt: mv * 100 */ +{ + int ret = -1; + + FUNC_ENTER(FUNC_LV_HELP); + + BUG_ON(NULL == p); + + if (!cpu_dvfs_is_available(p)) { + FUNC_EXIT(FUNC_LV_HELP); + return 0; + } + + /* set volt */ + ret = p->ops->set_cur_volt(p, volt); + + FUNC_EXIT(FUNC_LV_HELP); + + return ret; +} + +static int _restore_default_volt(struct mt_cpu_dvfs *p) +{ + unsigned long flags; + int i; + int ret = -1; + unsigned int freq = 0; + unsigned int volt = 0; + int idx = 0; + + enum mt_cpu_dvfs_id id; + struct mt_cpu_dvfs *p_second; + + id = (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? MT_CPU_DVFS_BIG : MT_CPU_DVFS_LITTLE; + p_second = id_to_cpu_dvfs(id); + + FUNC_ENTER(FUNC_LV_HELP); + + BUG_ON(NULL == p); + BUG_ON(NULL == p_second); + + if (!cpu_dvfs_is_available(p) || !cpu_dvfs_is_available(p_second)) { + FUNC_EXIT(FUNC_LV_HELP); + return 0; + } + + cpufreq_lock(flags); + + /* restore to default volt */ + for (i = 0; i < p->nr_opp_tbl; i++) + p->opp_tbl[i].cpufreq_volt = p->opp_tbl[i].cpufreq_volt_org; + + if (NULL != mt_cpufreq_update_private_tbl) + mt_cpufreq_update_private_tbl(id, 1); + + freq = p->ops->get_cur_phy_freq(p); + volt = p->ops->get_cur_volt(p); + + if (freq > cpu_dvfs_get_max_freq(p)) + idx = 0; + else + idx = _search_available_freq_idx(p, freq, CPUFREQ_RELATION_L); + + /* set volt */ + if ((p->idx_opp_tbl < p_second->idx_opp_tbl) || + (get_turbo_volt(p->cpu_id, cpu_dvfs_get_volt_by_idx(p, idx)) > volt)) + ret = _set_cur_volt_locked(p, + get_turbo_volt(p->cpu_id, cpu_dvfs_get_volt_by_idx(p, idx))); + + cpufreq_unlock(flags); + + FUNC_EXIT(FUNC_LV_HELP); + + return ret; +} + +unsigned int mt_cpufreq_get_freq_by_idx(enum mt_cpu_dvfs_id id, int idx) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + + FUNC_ENTER(FUNC_LV_API); + + BUG_ON(NULL == p); + + if (!cpu_dvfs_is_available(p)) { + FUNC_EXIT(FUNC_LV_API); + return 0; + } + + BUG_ON(idx >= p->nr_opp_tbl); + + FUNC_EXIT(FUNC_LV_API); + + return cpu_dvfs_get_freq_by_idx(p, idx); +} +EXPORT_SYMBOL(mt_cpufreq_get_freq_by_idx); + +int mt_cpufreq_update_volt(enum mt_cpu_dvfs_id id, unsigned int *volt_tbl, int nr_volt_tbl) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + unsigned long flags; + int i; + int ret = -1; + unsigned int freq = 0; + unsigned int volt = 0; + int idx = 0; + + enum mt_cpu_dvfs_id id_sec; + struct mt_cpu_dvfs *p_second; + + FUNC_ENTER(FUNC_LV_API); + + id_sec = (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? MT_CPU_DVFS_BIG : MT_CPU_DVFS_LITTLE; + p_second = id_to_cpu_dvfs(id_sec); + + BUG_ON(NULL == p); + BUG_ON(NULL == p_second); + + if (!cpu_dvfs_is_available(p) || !cpu_dvfs_is_available(p_second)) { + FUNC_EXIT(FUNC_LV_API); + return 0; + } + + BUG_ON(nr_volt_tbl > p->nr_opp_tbl); + + cpufreq_lock(flags); + + /* update volt table */ + for (i = 0; i < nr_volt_tbl; i++) + p->opp_tbl[i].cpufreq_volt = PMIC_VAL_TO_VOLT(volt_tbl[i]); + + if (NULL != mt_cpufreq_update_private_tbl) + mt_cpufreq_update_private_tbl(id, 0); + + freq = p->ops->get_cur_phy_freq(p); + volt = p->ops->get_cur_volt(p); + + if (freq > cpu_dvfs_get_max_freq(p)) + idx = 0; + else + idx = _search_available_freq_idx(p, freq, CPUFREQ_RELATION_L); + + /* dump_opp_table(p); */ + /* set volt */ + if ((p->idx_opp_tbl < p_second->idx_opp_tbl) || + (get_turbo_volt(p->cpu_id, cpu_dvfs_get_volt_by_idx(p, idx)) > volt)) + ret = _set_cur_volt_locked(p, + get_turbo_volt(p->cpu_id, cpu_dvfs_get_volt_by_idx(p, idx))); + + cpufreq_unlock(flags); + + FUNC_EXIT(FUNC_LV_API); + + return ret; +} +EXPORT_SYMBOL(mt_cpufreq_update_volt); + +void mt_cpufreq_restore_default_volt(enum mt_cpu_dvfs_id id) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + + FUNC_ENTER(FUNC_LV_API); + + BUG_ON(NULL == p); + + if (!cpu_dvfs_is_available(p)) { + FUNC_EXIT(FUNC_LV_API); + return; + } + + _restore_default_volt(p); + + FUNC_EXIT(FUNC_LV_API); +} +EXPORT_SYMBOL(mt_cpufreq_restore_default_volt); +/* for PTP-OD End*/ + +/* for PBM */ +unsigned int mt_cpufreq_get_leakage_mw(enum mt_cpu_dvfs_id id) +{ +#ifndef DISABLE_PBM_FEATURE + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); +#ifdef CONFIG_THERMAL + int temp; + + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + temp = tscpu_get_temp_by_bank(THERMAL_BANK0) / 1000; + else + temp = tscpu_get_temp_by_bank(THERMAL_BANK2) / 1000; +#else + int temp = 40; +#endif + /* if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + return mt_spower_get_leakage(MT_SPOWER_CPU, p->ops->get_cur_volt(p) / 100, temp); + else */ + return mt_spower_get_leakage(MT_SPOWER_CPU, p->ops->get_cur_volt(p) / 100, temp); +#else + return 0; +#endif +} + +static void _kick_PBM_by_cpu(struct mt_cpu_dvfs *p) +{ + struct mt_cpu_dvfs *p_dvfs[NR_MT_CPU_DVFS]; + struct cpumask dvfs_cpumask[NR_MT_CPU_DVFS]; + struct cpumask cpu_online_cpumask[NR_MT_CPU_DVFS]; + struct ppm_cluster_status ppm_data[NR_MT_CPU_DVFS]; + int i; + + for (i = 0; i < NR_MT_CPU_DVFS; i++) { + arch_get_cluster_cpus(&dvfs_cpumask[i], i); + cpumask_and(&cpu_online_cpumask[i], &dvfs_cpumask[i], cpu_online_mask); + + p_dvfs[i] = id_to_cpu_dvfs(i); + ppm_data[i].core_num = cpumask_weight(&cpu_online_cpumask[i]); + ppm_data[i].freq_idx = p_dvfs[i]->idx_opp_tbl; + ppm_data[i].volt = p_dvfs[i]->ops->get_cur_volt(p_dvfs[i]) / 100; + + cpufreq_ver("%d: core = %d, idx = %d, volt = %d\n", + i, ppm_data[i].core_num, ppm_data[i].freq_idx, ppm_data[i].volt); + } + + mt_ppm_dlpt_kick_PBM(ppm_data, (unsigned int)arch_get_nr_clusters()); +} +/* for PBM End */ +static unsigned int _cpu_freq_calc(unsigned int con1, unsigned int ckdiv1) +{ + unsigned int freq = 0; + + con1 &= _BITMASK_(26:0); + + if (con1 >= DDS_DIV8_FREQ) { + freq = DDS_DIV8_FREQ; + freq = PLL_DIV8_FREQ + (((con1 - freq) / 0x2000) * PLL_FREQ_STEP / 8); + } else if (con1 >= DDS_DIV4_FREQ) { + freq = DDS_DIV4_FREQ; + freq = PLL_DIV4_FREQ + (((con1 - freq) / 0x2000) * PLL_FREQ_STEP / 4); + } else if (con1 >= DDS_DIV2_FREQ) { + freq = DDS_DIV2_FREQ; + freq = PLL_DIV2_FREQ + (((con1 - freq) / 0x2000) * PLL_FREQ_STEP / 2); + } else if (con1 >= DDS_DIV1_FREQ) { + freq = DDS_DIV1_FREQ; + freq = PLL_DIV1_FREQ + (((con1 - freq) / 0x2000) * PLL_FREQ_STEP); + } else + BUG(); + + FUNC_ENTER(FUNC_LV_HELP); + + switch (ckdiv1) { + case 9: + freq = freq * 3 / 4; + break; + + case 10: + freq = freq * 2 / 4; + break; + + case 11: + freq = freq * 1 / 4; + break; + + case 17: + freq = freq * 4 / 5; + break; + + case 18: + freq = freq * 3 / 5; + break; + + case 19: + freq = freq * 2 / 5; + break; + + case 20: + freq = freq * 1 / 5; + break; + + case 25: + freq = freq * 5 / 6; + break; + + case 26: + freq = freq * 4 / 6; + break; + + case 27: + freq = freq * 3 / 6; + break; + + case 28: + freq = freq * 2 / 6; + break; + + case 29: + freq = freq * 1 / 6; + break; + + case 8: + case 16: + case 24: + default: + break; + } + + FUNC_EXIT(FUNC_LV_HELP); + + return freq; +} + +static unsigned int get_cur_phy_freq_L(struct mt_cpu_dvfs *p) +{ + unsigned int con1; + unsigned int ckdiv1; + unsigned int cur_khz; + + FUNC_ENTER(FUNC_LV_LOCAL); + + BUG_ON(NULL == p); + +#if 0 + /* read from freq meter */ + cur_khz = mt_get_cpu_freq(); + cpufreq_ver("@%s: Meter = %d MHz\n", __func__, cur_khz); +#else + con1 = cpufreq_read(ARMCA15PLL_CON1); + ckdiv1 = cpufreq_read(INFRA_TOPCKGEN_CKDIV1_BIG); + ckdiv1 = _GET_BITS_VAL_(4:0, ckdiv1); + + cur_khz = _cpu_freq_calc(con1, ckdiv1); + + cpufreq_ver("@%s: cur_khz = %d, con1 = 0x%x, ckdiv1_val = 0x%x\n", __func__, cur_khz, con1, + ckdiv1); +#endif + + FUNC_EXIT(FUNC_LV_LOCAL); + + return cur_khz; +} + +static unsigned int get_cur_phy_freq_LL(struct mt_cpu_dvfs *p) +{ + unsigned int con1; + unsigned int ckdiv1; + unsigned int cur_khz; + + FUNC_ENTER(FUNC_LV_LOCAL); + + BUG_ON(NULL == p); + +#if 0 + /* read from freq meter */ + cur_khz = mt_get_cpu_freq(); + cpufreq_ver("@%s: Meter = %d MHz\n", __func__, cur_khz); +#else + con1 = cpufreq_read(ARMCA7PLL_CON1); + ckdiv1 = cpufreq_read(INFRA_TOPCKGEN_CKDIV1_SML); + ckdiv1 = _GET_BITS_VAL_(4:0, ckdiv1); + + cur_khz = _cpu_freq_calc(con1, ckdiv1); + + cpufreq_ver("@%s: cur_khz = %d, con1 = 0x%x, ckdiv1_val = 0x%x\n", __func__, cur_khz, con1, + ckdiv1); +#endif + + FUNC_EXIT(FUNC_LV_LOCAL); + + return cur_khz; +} + +static unsigned int get_cur_phy_freq_cci(void) +{ + unsigned int con1; + unsigned int ckdiv1; + unsigned int cur_khz; + enum top_ckmuxsel_cci cur_cci_cluster; + + FUNC_ENTER(FUNC_LV_LOCAL); + + cur_cci_cluster = _get_cci_clock_switch(); + + if (cur_cci_cluster == TOP_CKMUXSEL_ARMPLL_L) + con1 = cpufreq_read(ARMCA15PLL_CON1); + else + con1 = cpufreq_read(ARMCA7PLL_CON1); + + ckdiv1 = cpufreq_read(INFRA_TOPCKGEN_CKDIV1_BUS); + ckdiv1 = _GET_BITS_VAL_(4:0, ckdiv1); + + cur_khz = _cpu_freq_calc(con1, ckdiv1); + + cpufreq_ver("@%s: cur_khz = %d, con1 = 0x%x, ckdiv1_val = 0x%x\n", __func__, cur_khz, con1, + ckdiv1); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return cur_khz; +} + +unsigned int mt_cpufreq_get_cur_phy_freq(enum mt_cpu_dvfs_id id) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + unsigned int freq = 0; + unsigned long flags; + + FUNC_ENTER(FUNC_LV_LOCAL); + + BUG_ON(NULL == p); + + cpufreq_lock(flags); + freq = p->ops->get_cur_phy_freq(p); + cpufreq_unlock(flags); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return freq; +} + +static unsigned int _cpu_dds_calc(unsigned int khz) +{ + unsigned int dds = 0; + + FUNC_ENTER(FUNC_LV_HELP); + + if (khz >= PLL_DIV1_FREQ) + dds = DDS_DIV1_FREQ + ((khz - PLL_DIV1_FREQ) / PLL_FREQ_STEP) * 0x2000; + else if (khz >= PLL_DIV2_FREQ) + dds = DDS_DIV2_FREQ + ((khz - PLL_DIV2_FREQ) * 2 / PLL_FREQ_STEP) * 0x2000; + else if (khz >= PLL_DIV4_FREQ) + dds = DDS_DIV4_FREQ + ((khz - PLL_DIV4_FREQ) * 4 / PLL_FREQ_STEP) * 0x2000; + else if (khz >= PLL_DIV8_FREQ) + dds = DDS_DIV8_FREQ + ((khz - PLL_DIV8_FREQ) * 8 / PLL_FREQ_STEP) * 0x2000; + else + BUG(); + + FUNC_EXIT(FUNC_LV_HELP); + + return dds; +} + +static void _cpu_clock_switch(struct mt_cpu_dvfs *p, enum top_ckmuxsel sel) +{ + unsigned int mask; + + FUNC_ENTER(FUNC_LV_HELP); + + switch (sel) { + case TOP_CKMUXSEL_CLKSQ: + break; + case TOP_CKMUXSEL_ARMPLL: + break; + case TOP_CKMUXSEL_MAINPLL: + cpufreq_write_mask(CLK_MISC_CFG_0, 5 : 4, 0x3); + break; + case TOP_CKMUXSEL_UNIVPLL: + cpufreq_write_mask(CLK_MISC_CFG_0, 5 : 4, 0x3); + break; + default: + break; + }; + + mask = (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? _BITMASK_(9:8) : _BITMASK_(5:4); + BUG_ON(sel >= NR_TOP_CKMUXSEL); + + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + cpufreq_write_mask(TOP_CKMUXSEL, 9 : 8, sel); + else + cpufreq_write_mask(TOP_CKMUXSEL, 5 : 4, sel); + + if ((sel == TOP_CKMUXSEL_CLKSQ) || (sel == TOP_CKMUXSEL_ARMPLL)) + cpufreq_write_mask(CLK_MISC_CFG_0, 5 : 4, 0x0); + + FUNC_EXIT(FUNC_LV_HELP); +} + +static enum top_ckmuxsel _get_cpu_clock_switch(struct mt_cpu_dvfs *p) +{ + unsigned int val = cpufreq_read(TOP_CKMUXSEL); + unsigned int mask; + + FUNC_ENTER(FUNC_LV_HELP); + + mask = (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? _BITMASK_(9:8) : _BITMASK_(5:4); + val &= mask; /* _BITMASK_(1 : 0) */ + + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + val = val >> 8; + else + val = val >> 4; + + FUNC_EXIT(FUNC_LV_HELP); + + return val; +} + +int mt_cpufreq_clock_switch(enum mt_cpu_dvfs_id id, enum top_ckmuxsel sel) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + + if (!p) + return -1; + + _cpu_clock_switch(p, sel); + + return 0; +} + +enum top_ckmuxsel mt_cpufreq_get_clock_switch(enum mt_cpu_dvfs_id id) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + + if (!p) + return -1; + + return _get_cpu_clock_switch(p); +} + +#define POS_SETTLE_TIME (2) +#if 0 +static void adjust_armpll_dds(struct mt_cpu_dvfs *p, unsigned int dds, unsigned int pos_div) +{ + unsigned int cur_volt; + int shift; + + cur_volt = p->ops->get_cur_volt(p); + p->ops->set_cur_volt(p, cpu_dvfs_get_volt_by_idx(p, 0)); + _cpu_clock_switch(p, TOP_CKMUXSEL_MAINPLL); + cci_switch_from_to(CUR_CCI_OPP_IDX, BACKUP_CCI_OPP_IDX); + shift = (pos_div == 1) ? 0 : + (pos_div == 2) ? 1 : + (pos_div == 4) ? 2 : 0; + + dds = (dds & ~(_BITMASK_(26:24))) | (shift << 24); + cpufreq_write(p->armpll_addr, dds | _BIT_(31)); /* CHG */ + udelay(PLL_SETTLE_TIME); + _cpu_clock_switch(p, TOP_CKMUXSEL_ARMPLL); + cci_switch_from_to(BACKUP_CCI_OPP_IDX, CUR_CCI_OPP_IDX); + p->ops->set_cur_volt(p, cur_volt); + _get_cpu_clock_switch(p); +} +#endif + +static void adjust_posdiv(struct mt_cpu_dvfs *p, unsigned int pos_div) +{ + unsigned int dds; + int shift; + + BUG_ON(cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)); + + /* disable SSC */ + /* freqhopping_config(FH_ARMCA15_PLLID, 1599000, 0); */ + _cpu_clock_switch(p, TOP_CKMUXSEL_MAINPLL); + cci_switch_from_to(CUR_CCI_OPP_IDX, BACKUP_CCI_OPP_IDX); + dds = cpufreq_read(p->armpll_addr); + shift = (pos_div == 1) ? 0 : + (pos_div == 2) ? 1 : + (pos_div == 4) ? 2 : 0; + + dds = (dds & ~(_BITMASK_(26:24))) | (shift << 24); + cpufreq_write(p->armpll_addr, dds | _BIT_(31)); /* CHG */ + udelay(POS_SETTLE_TIME); + _cpu_clock_switch(p, TOP_CKMUXSEL_ARMPLL); + /* enable SSC */ + /* freqhopping_config(FH_ARMCA15_PLLID, 1599000, 1); */ + + cci_switch_from_to(BACKUP_CCI_OPP_IDX, CUR_CCI_OPP_IDX); + _get_cpu_clock_switch(p); +} + +static void adjust_clkdiv(struct mt_cpu_dvfs *p, unsigned int clk_div) +{ + unsigned int sel = 0; + unsigned int ckdiv1_val; + unsigned int ckdiv1_mask = _BITMASK_(4 : 0); + + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + ckdiv1_val = _GET_BITS_VAL_(4 : 0, cpufreq_read(INFRA_TOPCKGEN_CKDIV1_SML)); + else + ckdiv1_val = _GET_BITS_VAL_(4 : 0, cpufreq_read(INFRA_TOPCKGEN_CKDIV1_BIG)); + + sel = (clk_div == 1) ? 8 : + (clk_div == 2) ? 10 : + (clk_div == 4) ? 11 : 8; + + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + cpufreq_write(INFRA_TOPCKGEN_CKDIV1_SML, (ckdiv1_val & ~ckdiv1_mask) | sel); + else + cpufreq_write(INFRA_TOPCKGEN_CKDIV1_BIG, (ckdiv1_val & ~ckdiv1_mask) | sel); + + udelay(POS_SETTLE_TIME); +} + +static void adjust_cci_div(unsigned int cci_div) +{ + unsigned int sel = 0; + + sel = (cci_div == 1) ? 8 : + (cci_div == 2) ? 10 : + (cci_div == 4) ? 11 : + (cci_div == 6) ? 29 : 8; + + cpufreq_write_mask(INFRA_TOPCKGEN_CKDIV1_BUS, 4 : 0, sel); + udelay(POS_SETTLE_TIME); +} + +static int armpll_exist_in_both_side(void) +{ + struct mt_cpu_dvfs *p_little = id_to_cpu_dvfs(MT_CPU_DVFS_LITTLE); + struct mt_cpu_dvfs *p_big = id_to_cpu_dvfs(MT_CPU_DVFS_BIG); + +#if 0 + unsigned int con0_LL_enable = _GET_BITS_VAL_(0:0, cpufreq_read(ARMCA7PLL_CON0)); + unsigned int con0_L_enable = _GET_BITS_VAL_(0:0, cpufreq_read(ARMCA15PLL_CON0)); + + if ((con0_LL_enable && con0_L_enable) == 1) + return 1; + else + return 0; +#else + if ((p_little->armpll_is_available == 1) && (p_big->armpll_is_available == 1)) + return 1; + else + return 0; +#endif +} + +static enum top_ckmuxsel_cci _get_cci_clock_switch(void) +{ + unsigned int val = cpufreq_read(TOP_CKMUXSEL); + unsigned int mask; + + FUNC_ENTER(FUNC_LV_HELP); + + mask = _BITMASK_(13:12); + val &= mask; /* _BITMASK_(1 : 0) */ + val = val >> 12; + + switch (val) { + case TOP_CKMUXSEL_CLKSQ_CCI: + cpufreq_ver("CCI in 26M\n"); + break; + case TOP_CKMUXSEL_ARMPLL_L: + cpufreq_ver("CCI in ARMPLL_L\n"); + break; + case TOP_CKMUXSEL_ARMPLL_LL: + cpufreq_ver("CCI in ARMPLL_LL\n"); + break; + case TOP_CKMUXSEL_CLKSQ_CCI_2: + cpufreq_ver("CCI in 26M\n"); + break; + default: + break; + }; + + FUNC_EXIT(FUNC_LV_HELP); + + return val; +} + +/* fix sel */ +static void _cci_clock_switch(enum top_ckmuxsel_cci sel) +{ + FUNC_ENTER(FUNC_LV_HELP); + + cpufreq_write_mask(TOP_CKMUXSEL, 13 : 12, sel); + + FUNC_EXIT(FUNC_LV_HELP); +} + +static int search_table_idx_by_freq(struct mt_cpu_dvfs *p, unsigned int freq) +{ + int i; + int idx = -1; + + for (i = 0; i < p->nr_opp_tbl; i++) { + if (p->freq_tbl[i].target_f == freq) { + idx = i; + break; + } + } + + if (idx == -1) + idx = p->idx_opp_tbl; + + return idx; +} + +static void cci_switch_from_to(enum opp_idx_type from, enum opp_idx_type to) +{ + if (opp_tbl[from].slot == opp_tbl[to].slot) + return; + +#ifdef DCM_ENABLE + sync_dcm_set_cci_freq(0); +#endif + + /* cci_div 1 -> 2 */ + if (opp_tbl[from].slot->cci_div < opp_tbl[to].slot->cci_div) + adjust_cci_div(opp_tbl[to].slot->cci_div); + + /* switch CCI */ + _cci_clock_switch(opp_tbl[to].p->armpll_clk_src); + + /* cci_div 2 -> 1 */ + if (opp_tbl[from].slot->cci_div > opp_tbl[to].slot->cci_div) + adjust_cci_div(opp_tbl[to].slot->cci_div); +} + +static void set_cur_freq(struct mt_cpu_dvfs *p, unsigned int cur_khz, unsigned int target_khz) +{ + enum mt_cpu_dvfs_id id_second = + (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? MT_CPU_DVFS_BIG : MT_CPU_DVFS_LITTLE; + struct mt_cpu_dvfs *p_second = id_to_cpu_dvfs(id_second); + struct mt_cpu_dvfs *p_temp; + unsigned int dds; + enum top_ckmuxsel_cci cur_cci_status; +#ifdef DCM_ENABLE + unsigned int cur_cci_freq; + unsigned int target_cci_freq; +#endif + int idx; + + FUNC_ENTER(FUNC_LV_LOCAL); + + now[SET_FREQ] = ktime_get(); + cpufreq_ver("%s: cur_khz = %d, target_khz = %d\n", + __func__, cur_khz, target_khz); + + /* CUR_OPP_IDX */ + opp_tbl[CUR_OPP_IDX].p = p; + opp_tbl[CUR_OPP_IDX].slot = &p->freq_tbl[p->idx_opp_tbl]; + cpufreq_ver("[CUR_OPP_IDX][NAME][IDX][FREQ] => %s:%d:%d\n", + cpu_dvfs_get_name(p), p->idx_opp_tbl, cpu_dvfs_get_freq_by_idx(p, p->idx_opp_tbl)); + + /* TARGET_OPP_IDX */ + opp_tbl[TARGET_OPP_IDX].p = p; + idx = search_table_idx_by_freq(opp_tbl[TARGET_OPP_IDX].p, + target_khz); + opp_tbl[TARGET_OPP_IDX].slot = &p->freq_tbl[idx]; + cpufreq_ver("[TARGET_OPP_IDX][NAME][IDX][FREQ] => %s:%d:%d\n", + cpu_dvfs_get_name(p), idx, cpu_dvfs_get_freq_by_idx(p, idx)); + + /* CUR_CCI_OPP_IDX */ + cur_cci_status = _get_cci_clock_switch(); + if (cur_cci_status == TOP_CKMUXSEL_ARMPLL_LL) + p_temp = id_to_cpu_dvfs(MT_CPU_DVFS_LITTLE); + else + p_temp = id_to_cpu_dvfs(MT_CPU_DVFS_BIG); + opp_tbl[CUR_CCI_OPP_IDX].p = p_temp; + opp_tbl[CUR_CCI_OPP_IDX].slot = &p_temp->freq_tbl[p_temp->idx_opp_tbl]; + cpufreq_ver("[CUR_CCI_OPP_IDX][NAME][IDX][FREQ] => %s:%d:%d\n", + cpu_dvfs_get_name(p_temp), p_temp->idx_opp_tbl, cpu_dvfs_get_freq_by_idx(p_temp, p_temp->idx_opp_tbl)); + + /* TARGET_CCI_OPP_IDX */ + if (armpll_exist_in_both_side()) { + cpufreq_ver("ARMPLL both side\n"); + if (target_khz > p_second->ops->get_cur_phy_freq(p_second)) { + opp_tbl[TARGET_CCI_OPP_IDX].p = p; + opp_tbl[TARGET_CCI_OPP_IDX].slot = opp_tbl[TARGET_OPP_IDX].slot; + cpufreq_ver("[TARGET_CCI_OPP_IDX][NAME][IDX][FREQ] => %s:[TARGET_OPP_IDX]:%d\n", + cpu_dvfs_get_name(p), target_khz); + } else { + opp_tbl[TARGET_CCI_OPP_IDX].p = p_second; + opp_tbl[TARGET_CCI_OPP_IDX].slot = &p_second->freq_tbl[p_second->idx_opp_tbl]; + cpufreq_ver("[TARGET_CCI_OPP_IDX][NAME][IDX][FREQ] => %s:%d:%d\n", + cpu_dvfs_get_name(p_second), p_second->idx_opp_tbl, + cpu_dvfs_get_freq_by_idx(p_second, p_second->idx_opp_tbl)); + } + } else { + cpufreq_ver("ARMPLL single side\n"); + /* BUG_ON(!p->armpll_is_available); */ + if (p->armpll_is_available) { + opp_tbl[TARGET_CCI_OPP_IDX].p = p; + opp_tbl[TARGET_CCI_OPP_IDX].slot = opp_tbl[TARGET_OPP_IDX].slot; + cpufreq_ver("[TARGET_CCI_OPP_IDX][NAME][IDX][FREQ] => %s:[TARGET_OPP_IDX]:%d\n", + cpu_dvfs_get_name(p), target_khz); + } else { + opp_tbl[TARGET_CCI_OPP_IDX].p = p_second; + opp_tbl[TARGET_CCI_OPP_IDX].slot = &p_second->freq_tbl[p_second->idx_opp_tbl]; + cpufreq_ver("[TARGET_CCI_OPP_IDX][NAME][IDX][FREQ] => %s:%d:%d\n", + cpu_dvfs_get_name(p_second), p_second->idx_opp_tbl, + cpu_dvfs_get_freq_by_idx(p_second, p_second->idx_opp_tbl)); + } + } + + /* BACKUP_CCI_OPP_IDX */ + opp_tbl[BACKUP_CCI_OPP_IDX].p = p_second; + opp_tbl[BACKUP_CCI_OPP_IDX].slot = &p_second->freq_tbl[p_second->idx_opp_tbl]; + cpufreq_ver("[BACKUP_CCI_OPP_IDX][NAME][IDX][FREQ] => %s:%d:%d\n", + cpu_dvfs_get_name(p_second), p_second->idx_opp_tbl, + cpu_dvfs_get_freq_by_idx(p_second, p_second->idx_opp_tbl)); + + if (cur_khz == target_khz && p->armpll_is_available) + return; + + /* DCM (freq: high -> low) */ +#ifdef DCM_ENABLE + sync_dcm_set_cci_freq(0); + + if (cur_khz > target_khz) { + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + sync_dcm_set_mp0_freq(target_khz/1000); + else + sync_dcm_set_mp1_freq(target_khz/1000); + } +#endif + + /* post_div 1 -> 2 */ + if (opp_tbl[CUR_OPP_IDX].slot->pos_div < opp_tbl[TARGET_OPP_IDX].slot->pos_div) + adjust_posdiv(p, opp_tbl[TARGET_OPP_IDX].slot->pos_div); + + /* armpll_div 1 -> 2 */ + if (opp_tbl[CUR_OPP_IDX].slot->clk_div < opp_tbl[TARGET_OPP_IDX].slot->clk_div) + adjust_clkdiv(p, opp_tbl[TARGET_OPP_IDX].slot->clk_div); + + /* cci_div 1 -> 2 */ + if (opp_tbl[CUR_CCI_OPP_IDX].slot->cci_div < opp_tbl[TARGET_CCI_OPP_IDX].slot->cci_div) + adjust_cci_div(opp_tbl[TARGET_CCI_OPP_IDX].slot->cci_div); + + /* actual FHCTL */ + dds = _cpu_dds_calc(opp_tbl[TARGET_OPP_IDX].slot->vco_dds); + /* adjust_armpll_dds(p, dds, opp_tbl[TARGET_OPP_IDX].slot->pos_div); */ + dds &= ~(_BITMASK_(26:24)); + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + mt_dfs_armpll(FH_ARMCA7_PLLID, dds); + else + mt_dfs_armpll(FH_ARMCA15_PLLID, dds); + + /* switch CCI */ + _cci_clock_switch(opp_tbl[TARGET_CCI_OPP_IDX].p->armpll_clk_src); + + /* cci_div 2 -> 1 */ + if (opp_tbl[CUR_CCI_OPP_IDX].slot->cci_div > opp_tbl[TARGET_CCI_OPP_IDX].slot->cci_div) + adjust_cci_div(opp_tbl[TARGET_CCI_OPP_IDX].slot->cci_div); + + /* armpll_div 2 -> 1 */ + if (opp_tbl[CUR_OPP_IDX].slot->clk_div > opp_tbl[TARGET_OPP_IDX].slot->clk_div) + adjust_clkdiv(p, opp_tbl[TARGET_OPP_IDX].slot->clk_div); + + /* post_div 2 -> 1 */ + if (opp_tbl[CUR_OPP_IDX].slot->pos_div > opp_tbl[TARGET_OPP_IDX].slot->pos_div) + adjust_posdiv(p, opp_tbl[TARGET_OPP_IDX].slot->pos_div); + +#ifdef DCM_ENABLE + /* DCM (cci freq) */ + cur_cci_freq = opp_tbl[CUR_CCI_OPP_IDX].slot->target_f/opp_tbl[CUR_CCI_OPP_IDX].slot->cci_div; + target_cci_freq = opp_tbl[TARGET_CCI_OPP_IDX].slot->target_f/opp_tbl[TARGET_CCI_OPP_IDX].slot->cci_div; + sync_dcm_set_cci_freq(target_cci_freq/1000); + + /* DCM (freq: low -> high)*/ + if (cur_khz < target_khz) { + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + sync_dcm_set_mp0_freq(target_khz/1000); + else + sync_dcm_set_mp1_freq(target_khz/1000); + } +#endif + delta[SET_FREQ] = ktime_sub(ktime_get(), now[SET_FREQ]); + if (ktime_to_us(delta[SET_FREQ]) > ktime_to_us(max[SET_FREQ])) + max[SET_FREQ] = delta[SET_FREQ]; + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +#ifdef CONFIG_HYBRID_CPU_DVFS +static void set_cur_freq_hybrid(struct mt_cpu_dvfs *p, unsigned int cur_khz, unsigned int target_khz) +{ + int r, index; + unsigned int cluster, volt, volt_val; + + BUG_ON(!enable_cpuhvfs); + + cluster = cpu_dvfs_to_cluster(p); + index = search_table_idx_by_freq(p, target_khz); + volt = cpu_dvfs_get_volt_by_idx(p, index); + + cpufreq_ver("cluster%u: target_khz = %u (%u), index = %d (%u)\n", + cluster, target_khz, cur_khz, index, volt); + + aee_record_cpu_volt(p, volt); + + r = cpuhvfs_set_target_opp(cluster, index, &volt_val); + BUG_ON(r); + + notify_cpu_volt_sampler(p, EXTBUCK_VAL_TO_VOLT(volt_val)); +} +#endif + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +/* for volt change (PMICWRAP/extBuck) */ +static unsigned int get_cur_vsram(struct mt_cpu_dvfs *p) +{ + unsigned int rdata = 0; + + FUNC_ENTER(FUNC_LV_LOCAL); + + rdata = mt6353_upmu_get_da_ni_vsram_proc_vosel(); + rdata = PMIC_VAL_TO_VOLT(rdata); + /* cpufreq_ver("@%s: vsram = %d\n", __func__, rdata); */ + + FUNC_EXIT(FUNC_LV_LOCAL); + + return rdata; /* vproc: mv*100 */ +} + +static unsigned int get_cur_volt_extbuck(struct mt_cpu_dvfs *p) +{ + /* unsigned char ret_val = 0; */ + unsigned int ret_val = 0; + unsigned int ret_volt = 0; /* volt: mv * 100 */ + + FUNC_ENTER(FUNC_LV_LOCAL); + + ret_val = mt6353_upmu_get_da_ni_vproc_vosel(); + ret_volt = PMIC_VAL_TO_VOLT(ret_val); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return ret_volt; +} +#else +/* for volt change (PMICWRAP/extBuck) */ +static unsigned int get_cur_vsram(struct mt_cpu_dvfs *p) +{ + unsigned int rdata = 0; + unsigned int retry_cnt = 5; + + FUNC_ENTER(FUNC_LV_LOCAL); +#if 0 + #define PMIC_ADDR_VSRAM_EN 0x00A6 + rdata = pmic_get_register_value(PMIC_ADDR_VSRAM_EN); + rdata &= _BITMASK_(1:1); /* enable or disable (i.e. 0mv or not) */ +#else + rdata = 1; +#endif + if (rdata) { + do { + rdata = pmic_get_register_value(MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON); + } while ((rdata == 0 || rdata > 0x7F) && retry_cnt--); + + rdata = PMIC_VAL_TO_VOLT(rdata); + /* cpufreq_ver("@%s: volt = %d\n", __func__, rdata); */ + } else + cpufreq_err("@%s: read VSRAM_EN failed, rdata = 0x%x\n", __func__, rdata); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return rdata; /* vproc: mv*100 */ +} + +static unsigned int get_cur_volt_extbuck(struct mt_cpu_dvfs *p) +{ + unsigned char ret_val = 0; + unsigned int ret_volt = 0; /* volt: mv * 100 */ + unsigned int retry_cnt = 5; + + FUNC_ENTER(FUNC_LV_LOCAL); + + if (cpu_dvfs_is_extbuck_valid()) { + do { + if (!mt6311_read_byte(MT6311_VDVFS11_CON13, &ret_val)) { + cpufreq_err("%s(), fail to read ext buck volt\n", __func__); + ret_volt = 0; + } else { + ret_volt = EXTBUCK_VAL_TO_VOLT(ret_val); + /* cpufreq_ver("@%s: volt = %d\n", __func__, ret_volt); */ + } + } while (ret_volt == EXTBUCK_VAL_TO_VOLT(0) && retry_cnt--); + } else + cpufreq_err("%s(), can not use ext buck!\n", __func__); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return ret_volt; +} +#endif + +unsigned int mt_cpufreq_get_cur_volt(enum mt_cpu_dvfs_id id) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + + FUNC_ENTER(FUNC_LV_API); + + BUG_ON(NULL == p); + BUG_ON(NULL == p->ops); + + FUNC_EXIT(FUNC_LV_API); + + return p->ops->get_cur_volt(p); /* mv * 100 */ +} +EXPORT_SYMBOL(mt_cpufreq_get_cur_volt); + +static unsigned int _calc_pmic_settle_time(unsigned int old_vproc, unsigned int old_vsram, + unsigned int new_vproc, unsigned int new_vsram) +{ + unsigned delay = 100; + + if (new_vproc == old_vproc && new_vsram == old_vsram) + return 0; + + /* VPROC is UP */ + if (new_vproc >= old_vproc) { + /* VSRAM is UP too, choose larger one to calculate settle time */ + if (new_vsram >= old_vsram) + delay = MAX(PMIC_VOLT_UP_SETTLE_TIME(old_vsram, new_vsram), + PMIC_VOLT_UP_SETTLE_TIME(old_vproc, new_vproc) + ); + /* VSRAM is DOWN, it may happen at bootup stage */ + else + delay = MAX(PMIC_VOLT_DOWN_SETTLE_TIME(old_vsram, new_vsram), + PMIC_VOLT_UP_SETTLE_TIME(old_vproc, new_vproc) + ); + } + /* VPROC is DOWN */ + else { + /* VSRAM is DOWN too, choose larger one to calculate settle time */ + if (old_vsram >= new_vsram) + delay = MAX(PMIC_VOLT_DOWN_SETTLE_TIME(old_vsram, new_vsram), + PMIC_VOLT_DOWN_SETTLE_TIME(old_vproc, new_vproc) + ); + /* VSRAM is UP, it may happen at bootup stage */ + else + delay = MAX(PMIC_VOLT_UP_SETTLE_TIME(old_vsram, new_vsram), + PMIC_VOLT_DOWN_SETTLE_TIME(old_vproc, new_vproc) + ); + } + + if (delay < MIN_PMIC_SETTLE_TIME) + delay = MIN_PMIC_SETTLE_TIME; + + return delay; +} + +static void dump_opp_table(struct mt_cpu_dvfs *p) +{ + int i; + + cpufreq_dbg("[%s/%d]\n" "cpufreq_oppidx = %d\n", p->name, p->cpu_id, p->idx_opp_tbl); + + for (i = 0; i < p->nr_opp_tbl; i++) { + cpufreq_dbg("\tOP(%d, %d),\n", + cpu_dvfs_get_freq_by_idx(p, i), cpu_dvfs_get_volt_by_idx(p, i) + ); + } +} + +unsigned int debug_vsram = 0; +unsigned int debug_vproc = 0; +unsigned int last_vsram = 0; +unsigned int last_vproc = 0; +int fail_case = 0; +int fail_times = 0; + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +static int set_cur_volt_extbuck(struct mt_cpu_dvfs *p, unsigned int volt) +{ /* volt: vproc (mv*100) */ + unsigned int cur_vsram; + unsigned int cur_vproc; + unsigned int delay_us = 0; + int ret = 0; + + enum mt_cpu_dvfs_id id_sec; + struct mt_cpu_dvfs *p_second; + + FUNC_ENTER(FUNC_LV_LOCAL); + + aee_record_cpu_volt(p, volt); + + now[SET_VOLT] = ktime_get(); + + cur_vsram = get_cur_vsram(p); + cur_vproc = get_cur_volt_extbuck(p); + + id_sec = (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? MT_CPU_DVFS_BIG : MT_CPU_DVFS_LITTLE; + p_second = id_to_cpu_dvfs(id_sec); + + if (unlikely + (!((cur_vsram >= cur_vproc) && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { +#ifdef __KERNEL__ + aee_kernel_warning(TAG, "@%s():%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, cur_vsram, cur_vproc); +#endif + } + + /* UP */ + if (volt > cur_vproc) { + unsigned int target_vsram = volt + NORMAL_DIFF_VRSAM_VPROC; + unsigned int next_vsram; + + do { + unsigned int old_vproc = cur_vproc; + unsigned int old_vsram = cur_vsram; + + next_vsram = MIN(((MAX_DIFF_VSRAM_VPROC - 2500) + cur_vproc), target_vsram); + + /* update vsram */ + cur_vsram = MAX(next_vsram, MIN_VSRAM_VOLT); + + if (cur_vsram > MAX_VSRAM_VOLT) { + cur_vsram = MAX_VSRAM_VOLT; + target_vsram = MAX_VSRAM_VOLT; /* to end the loop */ + } + + if (unlikely + (!((cur_vsram >= cur_vproc) + && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + dump_opp_table(p); + cpufreq_err("@%s():%d, old_vsram=%d, old_vproc=%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, old_vsram, old_vproc, cur_vsram, cur_vproc); + BUG(); + } + now[SET_VSRAM] = ktime_get(); + last_vsram = cur_vsram; + mt6353_upmu_set_ldo_vsram_proc_vosel_ctrl(1); + mt6353_upmu_set_ldo_vsram_proc_vosel_on(VOLT_TO_PMIC_VAL(cur_vsram)); + delta[SET_VSRAM] = ktime_sub(ktime_get(), now[SET_VSRAM]); + if (ktime_to_us(delta[SET_VSRAM]) > ktime_to_us(max[SET_VSRAM])) + max[SET_VSRAM] = delta[SET_VSRAM]; + + /* update vproc */ + if (next_vsram > MAX_VSRAM_VOLT) + cur_vproc = volt; /* Vsram was limited, set to target vproc directly */ + else + cur_vproc = next_vsram - NORMAL_DIFF_VRSAM_VPROC; + + if (unlikely + (!((cur_vsram >= cur_vproc) + && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + fail_case = 2; + fail_times++; + dump_opp_table(p); + cpufreq_err("@%s():%d, old_vsram=%d, old_vproc=%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, old_vsram, old_vproc, cur_vsram, cur_vproc); + BUG(); + } + + last_vproc = cur_vproc; + now[SET_VPROC] = ktime_get(); + mt6353_upmu_set_buck_vproc_vosel_ctrl(1); + mt6353_upmu_set_buck_vproc_vosel_on(VOLT_TO_PMIC_VAL(cur_vproc)); + delta[SET_VPROC] = ktime_sub(ktime_get(), now[SET_VPROC]); + if (ktime_to_us(delta[SET_VPROC]) > ktime_to_us(max[SET_VPROC])) + max[SET_VPROC] = delta[SET_VPROC]; + + now[SET_DELAY] = ktime_get(); + delay_us = + _calc_pmic_settle_time(old_vproc, old_vsram, cur_vproc, cur_vsram); + udelay(delay_us); + delta[SET_DELAY] = ktime_sub(ktime_get(), now[SET_DELAY]); + if (ktime_to_us(delta[SET_DELAY]) > ktime_to_us(max[SET_DELAY])) + max[SET_DELAY] = delta[SET_DELAY]; + cpufreq_ver + ("@%s(): UP --> old_vsram=%d, cur_vsram=%d, old_vproc=%d, cur_vproc=%d, delay=%d\n", + __func__, old_vsram, cur_vsram, old_vproc, cur_vproc, delay_us); + } while (target_vsram > cur_vsram); + } + /* DOWN */ + else if (volt < cur_vproc) { + unsigned int next_vproc; + unsigned int next_vsram = cur_vproc + NORMAL_DIFF_VRSAM_VPROC; + + do { + unsigned int old_vproc = cur_vproc; + unsigned int old_vsram = cur_vsram; + + next_vproc = MAX((next_vsram - (MAX_DIFF_VSRAM_VPROC - 2500)), volt); + + /* update vproc */ + cur_vproc = next_vproc; + + if (unlikely + (!((cur_vsram >= cur_vproc) + && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + fail_case = 3; + fail_times++; + dump_opp_table(p); + cpufreq_err("@%s():%d, old_vsram=%d, old_vproc=%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, old_vsram, old_vproc, cur_vsram, cur_vproc); + BUG(); + } + + last_vproc = cur_vproc; + now[SET_VPROC] = ktime_get(); + mt6353_upmu_set_buck_vproc_vosel_ctrl(1); + mt6353_upmu_set_buck_vproc_vosel_on(VOLT_TO_PMIC_VAL(cur_vproc)); + delta[SET_VPROC] = ktime_sub(ktime_get(), now[SET_VPROC]); + if (ktime_to_us(delta[SET_VPROC]) > ktime_to_us(max[SET_VPROC])) + max[SET_VPROC] = delta[SET_VPROC]; + + /* update vsram */ + next_vsram = cur_vproc + NORMAL_DIFF_VRSAM_VPROC; + cur_vsram = MAX(next_vsram, MIN_VSRAM_VOLT); + cur_vsram = MIN(cur_vsram, MAX_VSRAM_VOLT); + + if (unlikely + (!((cur_vsram >= cur_vproc) + && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + fail_case = 4; + fail_times++; + dump_opp_table(p); + cpufreq_err("@%s():%d, old_vsram=%d, old_vproc=%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, old_vsram, old_vproc, cur_vsram, cur_vproc); + BUG(); + } + now[SET_VSRAM] = ktime_get(); + last_vsram = cur_vsram; + mt6353_upmu_set_ldo_vsram_proc_vosel_ctrl(1); + mt6353_upmu_set_ldo_vsram_proc_vosel_on(VOLT_TO_PMIC_VAL(cur_vsram)); + delta[SET_VSRAM] = ktime_sub(ktime_get(), now[SET_VSRAM]); + if (ktime_to_us(delta[SET_VSRAM]) > ktime_to_us(max[SET_VSRAM])) + max[SET_VSRAM] = delta[SET_VSRAM]; + + now[SET_DELAY] = ktime_get(); + delay_us = + _calc_pmic_settle_time(old_vproc, old_vsram, cur_vproc, cur_vsram); + udelay(delay_us); + delta[SET_DELAY] = ktime_sub(ktime_get(), now[SET_DELAY]); + if (ktime_to_us(delta[SET_DELAY]) > ktime_to_us(max[SET_DELAY])) + max[SET_DELAY] = delta[SET_DELAY]; + cpufreq_ver + ("@%s(): DOWN --> old_vsram=%d, cur_vsram=%d, old_vproc=%d, cur_vproc=%d, delay=%d\n", + __func__, old_vsram, cur_vsram, old_vproc, cur_vproc, delay_us); + } while (cur_vproc > volt); + } + + delta[SET_VOLT] = ktime_sub(ktime_get(), now[SET_VOLT]); + if (ktime_to_us(delta[SET_VOLT]) > ktime_to_us(max[SET_VOLT])) + max[SET_VOLT] = delta[SET_VOLT]; + + notify_cpu_volt_sampler(p, volt); + + cpufreq_ver("@%s():%d, cur_vsram = %d, cur_vproc = %d\n", __func__, __LINE__, cur_vsram, + cur_vproc); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return ret; +} +#else +static int set_cur_volt_extbuck(struct mt_cpu_dvfs *p, unsigned int volt) +{ /* volt: vproc (mv*100) */ + unsigned int cur_vsram; + unsigned int cur_vproc; + unsigned int delay_us = 0; + int ret = 0; + + enum mt_cpu_dvfs_id id_sec; + struct mt_cpu_dvfs *p_second; + + FUNC_ENTER(FUNC_LV_LOCAL); + + aee_record_cpu_volt(p, volt); + + now[SET_VOLT] = ktime_get(); + + cur_vsram = get_cur_vsram(p); + cur_vproc = get_cur_volt_extbuck(p); + + id_sec = (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? MT_CPU_DVFS_BIG : MT_CPU_DVFS_LITTLE; + p_second = id_to_cpu_dvfs(id_sec); + + if (unlikely + (!((cur_vsram >= cur_vproc) && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + unsigned int i, val, extbuck_chip_id = mt6311_get_chip_id(); + + fail_case = 1; + fail_times++; + dump_opp_table(p); + cpufreq_err("@%s():%d, cur_vsram = %d, cur_vproc = %d, extbuck_chip_id = 0x%x\n", + __func__, __LINE__, cur_vsram, cur_vproc, extbuck_chip_id); + + /* read extbuck chip id to verify I2C is still worked or not */ + for (i = 0; i < 10; i++) { + val = ((mt6311_get_cid() << 8) | (mt6311_get_swcid())); + cpufreq_err("read chip id from I2C, id: 0x%x\n", val); + } + + /* read pmic wrap chip id */ + for (i = 0; i < 10; i++) { + pwrap_read(0x200, &val); + cpufreq_err("pmic wrap CID = %x\n", val); + } + + cpufreq_info("@%s():%d, cur_vsram = %d, cur_vproc = %d, idx = (%d, %d), volt = (%d, %d)\n", + __func__, __LINE__, cur_vsram, cur_vproc, p->idx_opp_tbl, p_second->idx_opp_tbl, + debug_vsram, debug_vproc); + + /* Try to recover voltage*/ + cur_vsram = cur_vproc + NORMAL_DIFF_VRSAM_VPROC; + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON, + VOLT_TO_PMIC_VAL(cur_vsram)); + + cur_vproc = get_cur_volt_extbuck(p); + cur_vsram = get_cur_vsram(p); + + cpufreq_info("@%s():%d, dvfs voltage = (%d, %d), recovered cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, last_vsram, last_vproc, cur_vsram, cur_vproc); + } + + /* UP */ + if (volt > cur_vproc) { + unsigned int target_vsram = volt + NORMAL_DIFF_VRSAM_VPROC; + unsigned int next_vsram; + + do { + unsigned int old_vproc = cur_vproc; + unsigned int old_vsram = cur_vsram; + + next_vsram = MIN(((MAX_DIFF_VSRAM_VPROC - 2500) + cur_vproc), target_vsram); + + /* update vsram */ + cur_vsram = MAX(next_vsram, MIN_VSRAM_VOLT); + + if (cur_vsram > MAX_VSRAM_VOLT) { + cur_vsram = MAX_VSRAM_VOLT; + target_vsram = MAX_VSRAM_VOLT; /* to end the loop */ + } + + if (unlikely + (!((cur_vsram >= cur_vproc) + && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + dump_opp_table(p); + cpufreq_err("@%s():%d, old_vsram=%d, old_vproc=%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, old_vsram, old_vproc, cur_vsram, cur_vproc); + BUG(); + } + now[SET_VSRAM] = ktime_get(); + last_vsram = cur_vsram; + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON, + VOLT_TO_PMIC_VAL(cur_vsram)); + delta[SET_VSRAM] = ktime_sub(ktime_get(), now[SET_VSRAM]); + if (ktime_to_us(delta[SET_VSRAM]) > ktime_to_us(max[SET_VSRAM])) + max[SET_VSRAM] = delta[SET_VSRAM]; + + /* update vproc */ + if (next_vsram > MAX_VSRAM_VOLT) + cur_vproc = volt; /* Vsram was limited, set to target vproc directly */ + else + cur_vproc = next_vsram - NORMAL_DIFF_VRSAM_VPROC; + + if (unlikely + (!((cur_vsram >= cur_vproc) + && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + fail_case = 2; + fail_times++; + dump_opp_table(p); + cpufreq_err("@%s():%d, old_vsram=%d, old_vproc=%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, old_vsram, old_vproc, cur_vsram, cur_vproc); + BUG(); + } + + last_vproc = cur_vproc; + now[SET_VPROC] = ktime_get(); + mt6311_set_vdvfs11_vosel_on(VOLT_TO_EXTBUCK_VAL(cur_vproc)); + delta[SET_VPROC] = ktime_sub(ktime_get(), now[SET_VPROC]); + if (ktime_to_us(delta[SET_VPROC]) > ktime_to_us(max[SET_VPROC])) + max[SET_VPROC] = delta[SET_VPROC]; + + now[SET_DELAY] = ktime_get(); + delay_us = + _calc_pmic_settle_time(old_vproc, old_vsram, cur_vproc, cur_vsram); + udelay(delay_us); + delta[SET_DELAY] = ktime_sub(ktime_get(), now[SET_DELAY]); + if (ktime_to_us(delta[SET_DELAY]) > ktime_to_us(max[SET_DELAY])) + max[SET_DELAY] = delta[SET_DELAY]; + cpufreq_ver + ("@%s(): UP --> old_vsram=%d, cur_vsram=%d, old_vproc=%d, cur_vproc=%d, delay=%d\n", + __func__, old_vsram, cur_vsram, old_vproc, cur_vproc, delay_us); + } while (target_vsram > cur_vsram); + } + /* DOWN */ + else if (volt < cur_vproc) { + unsigned int next_vproc; + unsigned int next_vsram = cur_vproc + NORMAL_DIFF_VRSAM_VPROC; + + do { + unsigned int old_vproc = cur_vproc; + unsigned int old_vsram = cur_vsram; + + next_vproc = MAX((next_vsram - (MAX_DIFF_VSRAM_VPROC - 2500)), volt); + + /* update vproc */ + cur_vproc = next_vproc; + + if (unlikely + (!((cur_vsram >= cur_vproc) + && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + fail_case = 3; + fail_times++; + dump_opp_table(p); + cpufreq_err("@%s():%d, old_vsram=%d, old_vproc=%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, old_vsram, old_vproc, cur_vsram, cur_vproc); + BUG(); + } + + last_vproc = cur_vproc; + now[SET_VPROC] = ktime_get(); + mt6311_set_vdvfs11_vosel_on(VOLT_TO_EXTBUCK_VAL(cur_vproc)); + delta[SET_VPROC] = ktime_sub(ktime_get(), now[SET_VPROC]); + if (ktime_to_us(delta[SET_VPROC]) > ktime_to_us(max[SET_VPROC])) + max[SET_VPROC] = delta[SET_VPROC]; + + /* update vsram */ + next_vsram = cur_vproc + NORMAL_DIFF_VRSAM_VPROC; + cur_vsram = MAX(next_vsram, MIN_VSRAM_VOLT); + cur_vsram = MIN(cur_vsram, MAX_VSRAM_VOLT); + + if (unlikely + (!((cur_vsram >= cur_vproc) + && (MAX_DIFF_VSRAM_VPROC >= (cur_vsram - cur_vproc))))) { + fail_case = 4; + fail_times++; + dump_opp_table(p); + cpufreq_err("@%s():%d, old_vsram=%d, old_vproc=%d, cur_vsram = %d, cur_vproc = %d\n", + __func__, __LINE__, old_vsram, old_vproc, cur_vsram, cur_vproc); + BUG(); + } + now[SET_VSRAM] = ktime_get(); + last_vsram = cur_vsram; + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON, + VOLT_TO_PMIC_VAL(cur_vsram)); + delta[SET_VSRAM] = ktime_sub(ktime_get(), now[SET_VSRAM]); + if (ktime_to_us(delta[SET_VSRAM]) > ktime_to_us(max[SET_VSRAM])) + max[SET_VSRAM] = delta[SET_VSRAM]; + + now[SET_DELAY] = ktime_get(); + delay_us = + _calc_pmic_settle_time(old_vproc, old_vsram, cur_vproc, cur_vsram); + udelay(delay_us); + delta[SET_DELAY] = ktime_sub(ktime_get(), now[SET_DELAY]); + if (ktime_to_us(delta[SET_DELAY]) > ktime_to_us(max[SET_DELAY])) + max[SET_DELAY] = delta[SET_DELAY]; + cpufreq_ver + ("@%s(): DOWN --> old_vsram=%d, cur_vsram=%d, old_vproc=%d, cur_vproc=%d, delay=%d\n", + __func__, old_vsram, cur_vsram, old_vproc, cur_vproc, delay_us); + } while (cur_vproc > volt); + } + + delta[SET_VOLT] = ktime_sub(ktime_get(), now[SET_VOLT]); + if (ktime_to_us(delta[SET_VOLT]) > ktime_to_us(max[SET_VOLT])) + max[SET_VOLT] = delta[SET_VOLT]; + + notify_cpu_volt_sampler(p, volt); + + cpufreq_ver("@%s():%d, cur_vsram = %d, cur_vproc = %d\n", __func__, __LINE__, cur_vsram, + cur_vproc); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return ret; +} +#endif + +#ifdef CONFIG_HYBRID_CPU_DVFS +static int set_cur_volt_hybrid(struct mt_cpu_dvfs *p, unsigned int volt) +{ + BUG_ON(!enable_cpuhvfs); + + return 0; +} + +static unsigned int get_cur_volt_hybrid(struct mt_cpu_dvfs *p) +{ + unsigned int volt, volt_val; + + BUG_ON(!enable_cpuhvfs); + + volt_val = cpuhvfs_get_curr_volt(cpu_dvfs_to_cluster(p)); + if (volt_val != UINT_MAX) + volt = EXTBUCK_VAL_TO_VOLT(volt_val); + else + volt = get_cur_volt_extbuck(p); + + return volt; +} +#endif + +/* cpufreq set (freq & volt) */ +static unsigned int _search_available_volt(struct mt_cpu_dvfs *p, unsigned int target_khz) +{ + int i; + + FUNC_ENTER(FUNC_LV_HELP); + + BUG_ON(NULL == p); + + /* search available voltage */ + for (i = p->nr_opp_tbl - 1; i >= 0; i--) { + if (target_khz <= cpu_dvfs_get_freq_by_idx(p, i)) + break; + } + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (i < 0) + i = 0; + #else + BUG_ON(i < 0); /* i.e. target_khz > p->opp_tbl[0].cpufreq_khz */ + #endif + + FUNC_EXIT(FUNC_LV_HELP); + + return cpu_dvfs_get_volt_by_idx(p, i); /* mv * 100 */ +} + +static int _cpufreq_set_locked(struct mt_cpu_dvfs *p, unsigned int cur_khz, unsigned int target_khz, + struct cpufreq_policy *policy, unsigned int target_volt, int log) +{ + int ret = -1; + + enum mt_cpu_dvfs_id id_second = + (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? MT_CPU_DVFS_BIG : MT_CPU_DVFS_LITTLE; + struct mt_cpu_dvfs *p_second = id_to_cpu_dvfs(id_second); + unsigned int cur_volt = UINT_MAX; + +#ifdef CONFIG_CPU_FREQ + struct cpufreq_freqs freqs; + unsigned int target_khz_orig = target_khz; +#endif + FUNC_ENTER(FUNC_LV_HELP); + + if (cur_khz != get_turbo_freq(p->cpu_id, target_khz)) { + if (log) + cpufreq_dbg("@%s(), %s: (%d, %d): freq = %d (%d), volt = %d (%d), cpus = %d, cur = %d\n", + __func__, cpu_dvfs_get_name(p), p->idx_opp_ppm_base, p->idx_opp_ppm_limit, + target_khz, get_turbo_freq(p->cpu_id, target_khz), target_volt, + get_turbo_volt(p->cpu_id, target_volt), num_online_cpus(), cur_khz); + } + + target_volt = get_turbo_volt(p->cpu_id, target_volt); + target_khz = get_turbo_freq(p->cpu_id, target_khz); + + if (cur_khz == target_khz) + goto out; + +#ifdef CONFIG_HYBRID_CPU_DVFS + if (!enable_cpuhvfs) { +#endif + cur_volt = p->ops->get_cur_volt(p); + /* set volt (UP) */ + if (target_volt > cur_volt) { + ret = p->ops->set_cur_volt(p, target_volt); + + if (ret) /* set volt fail */ + goto out; + } +#ifdef CONFIG_HYBRID_CPU_DVFS + } +#endif + +#ifdef CONFIG_CPU_FREQ + freqs.old = cur_khz; + freqs.new = target_khz_orig; + if (policy) { + freqs.cpu = policy->cpu; + cpufreq_freq_transition_begin(policy, &freqs); + } +#endif + + /* set freq (UP/DOWN) */ + if (cur_khz != target_khz) + p->ops->set_cur_freq(p, cur_khz, target_khz); + +#ifdef CONFIG_CPU_FREQ + if (policy) { + freqs.cpu = policy->cpu; + cpufreq_freq_transition_end(policy, &freqs, 0); + } +#endif + +#ifdef CONFIG_HYBRID_CPU_DVFS + if (!enable_cpuhvfs) { +#endif + /* set volt (DOWN) */ + if (cur_volt > target_volt) { + ret = p->ops->set_cur_volt(p, target_volt); + + if (ret) /* set volt fail */ + goto out; + } +#ifdef CONFIG_HYBRID_CPU_DVFS + } +#endif + + cpufreq_ver("@%s(): Vproc = %dmv, Vsram = %dmv, freq(%s) = %dKHz\n", + __func__, + (p->ops->get_cur_volt(p)) / 100, + (get_cur_vsram(p) / 100), p->name, p->ops->get_cur_phy_freq(p)); + cpufreq_ver("@%s(): freq(%s) = %dKHz, freq(%s) = %dKHz, freq(cci) = %dKHz\n", + __func__, p->name, p->ops->get_cur_phy_freq(p), p_second->name + , p_second->ops->get_cur_phy_freq(p_second), get_cur_phy_freq_cci()); + + /* trigger exception if freq/volt not correct during stress */ + if (do_dvfs_stress_test) { + unsigned int volt = p->ops->get_cur_volt(p); + unsigned int freq = p->ops->get_cur_phy_freq(p); + + if (volt < target_volt || freq != target_khz) { + cpufreq_err("volt = %u, target_volt = %u, freq = %u, target_khz = %u\n", + volt, target_volt, freq, target_khz); + dump_opp_table(p); + BUG(); + } + } + + FUNC_EXIT(FUNC_LV_HELP); + + return 0; + +out: + return ret; +} + +static unsigned int _calc_new_opp_idx(struct mt_cpu_dvfs *p, int new_opp_idx); + +static unsigned int calc_new_target_volt(struct mt_cpu_dvfs *p, struct mt_cpu_dvfs *p_second, int new_opp_idx) +{ + int freq_second; + unsigned int target_voltage; + + /* freq_second = p_second->policy_online ? p_second->ops->get_cur_phy_freq(p_second) : 0; */ + freq_second = p_second->ops->get_cur_phy_freq(p_second); + target_voltage = + MAX(cpu_dvfs_get_volt_by_idx(p, new_opp_idx), + _search_available_volt(p_second, freq_second)); + + return target_voltage; +} + +static void _mt_cpufreq_set(struct cpufreq_policy *policy, enum mt_cpu_dvfs_id id, int new_opp_idx) +{ + unsigned long flags; + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + unsigned int cur_freq; + unsigned int target_freq; + int ret = 0; + + enum mt_cpu_dvfs_id id_second = + (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) ? MT_CPU_DVFS_BIG : MT_CPU_DVFS_LITTLE; + struct mt_cpu_dvfs *p_second = id_to_cpu_dvfs(id_second); + unsigned int target_volt; /* mv * 100 */ + int log = 1; + + FUNC_ENTER(FUNC_LV_LOCAL); + +#ifndef __TRIAL_RUN__ + if (!policy) +#endif + return; + + BUG_ON(NULL == p); + BUG_ON(new_opp_idx >= p->nr_opp_tbl); + + cpufreq_lock(flags); + + now[SET_DVFS] = ktime_get(); + + if (p->armpll_is_available != 1) { + cpufreq_unlock(flags); + return; + } + + /* get current idx here to avoid idx synchronization issue */ + if (new_opp_idx == -1) { + new_opp_idx = p->idx_opp_tbl; + log = 0; + } + + if (do_dvfs_stress_test) + new_opp_idx = jiffies & 0x7; /* 0~7 */ + else { +#if defined(CONFIG_CPU_DVFS_BRINGUP) + new_opp_idx = id_to_cpu_dvfs(id)->idx_normal_max_opp; +#else + new_opp_idx = _calc_new_opp_idx(id_to_cpu_dvfs(id), new_opp_idx); +#endif + } + + target_volt = calc_new_target_volt(p, p_second, new_opp_idx); + + cur_freq = p->ops->get_cur_phy_freq(p); + target_freq = cpu_dvfs_get_freq_by_idx(p, new_opp_idx); + + if (abs(new_opp_idx - p->idx_opp_tbl) < 3 && new_opp_idx != 0 && + new_opp_idx != p->nr_opp_tbl - 1) + log = 0; + +#ifdef CONFIG_CPU_FREQ + ret = _cpufreq_set_locked(p, cur_freq, target_freq, policy, target_volt, log); +#else + ret = _cpufreq_set_locked(p, cur_freq, target_freq, NULL, target_volt, log); +#endif + + p->idx_opp_tbl = new_opp_idx; + +#ifndef DISABLE_PBM_FEATURE + if (!ret && !p->dvfs_disable_by_suspend) + _kick_PBM_by_cpu(p); +#endif + delta[SET_DVFS] = ktime_sub(ktime_get(), now[SET_DVFS]); + if (ktime_to_us(delta[SET_DVFS]) > ktime_to_us(max[SET_DVFS])) + max[SET_DVFS] = delta[SET_DVFS]; + + cpufreq_unlock(flags); + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +static int _search_available_freq_idx_under_v(struct mt_cpu_dvfs *p, unsigned int volt) +{ + int i; + + FUNC_ENTER(FUNC_LV_HELP); + + BUG_ON(NULL == p); + + /* search available voltage */ + for (i = p->nr_opp_tbl - 1; i >= 0; i--) { + if (volt <= cpu_dvfs_get_volt_by_idx(p, i)) + break; + } + + if (i < 0) + return 0; /* i.e. target_khz > p->opp_tbl[0].cpufreq_khz */ + + FUNC_EXIT(FUNC_LV_HELP); + + return i; +} +#define SINGLE_CORE_BOUNDARY_CPU_NUM 1 +static unsigned int num_online_cpus_delta; +static int __cpuinit _mt_cpufreq_cpu_CB(struct notifier_block *nfb, unsigned long action, + void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + unsigned int online_cpus = num_online_cpus(); + struct device *dev; + + enum mt_cpu_dvfs_id cluster_id; + struct mt_cpu_dvfs *p; + unsigned int cur_volt; + int freq_idx; + + /* CPU mask - Get on-line cpus per-cluster */ + struct cpumask dvfs_cpumask; + struct cpumask cpu_online_cpumask; + unsigned int cpus; + unsigned long flags; + +#ifdef CONFIG_CPU_FREQ + struct cpufreq_policy *policy; + struct cpufreq_freqs freqs; +#endif + + cluster_id = arch_get_cluster_id(cpu); + arch_get_cluster_cpus(&dvfs_cpumask, cluster_id); + cpumask_and(&cpu_online_cpumask, &dvfs_cpumask, cpu_online_mask); + p = id_to_cpu_dvfs(cluster_id); + + cpufreq_ver("@%s():%d, cpu = %d, action = %lu, oppidx = %d, num_online_cpus = %d\n" + , __func__, __LINE__, cpu, action, p->idx_opp_tbl, online_cpus); + + dev = get_cpu_device(cpu); + /* Pull up frequency when single core */ + if (dev) { + if ((SINGLE_CORE_BOUNDARY_CPU_NUM == online_cpus) && cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) { + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_PREPARE_FROZEN: + num_online_cpus_delta = 1; + + case CPU_DEAD: + case CPU_DEAD_FROZEN: + /* _mt_cpufreq_set(MT_CPU_DVFS_LITTLE, -1); */ + break; + } + } else { + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + case CPU_UP_CANCELED: + case CPU_UP_CANCELED_FROZEN: + num_online_cpus_delta = 0; + break; + } + } + } + + if (dev) { + switch (action & 0xF) { + case CPU_ONLINE: + cpus = cpumask_weight(&cpu_online_cpumask); + cpufreq_ver("CPU_ONLINE -> cpus = %d\n", cpus); + if (cpus == 1) { + cpufreq_ver("CPU_ONLINE first CPU of %s\n", + cpu_dvfs_get_name(p)); + cpufreq_lock(flags); + p->armpll_is_available = 1; + if (action == CPU_ONLINE) { + cur_volt = p->ops->get_cur_volt(p); + freq_idx = _search_available_freq_idx_under_v(p, cur_volt); + freq_idx = MAX(freq_idx, _calc_new_opp_idx(p, freq_idx)); +#ifdef CONFIG_CPU_FREQ + policy = cpufreq_cpu_get(cpu); + freqs.old = cpu_dvfs_get_cur_freq(p); + freqs.new = cpu_dvfs_get_freq_by_idx(p, freq_idx); + if (policy) { + freqs.cpu = policy->cpu; + cpufreq_freq_transition_begin(policy, &freqs); + } +#endif + p->ops->set_cur_freq(p, cpu_dvfs_get_cur_freq(p) + , cpu_dvfs_get_freq_by_idx(p, freq_idx)); +#ifdef CONFIG_CPU_FREQ + if (policy) { + freqs.cpu = policy->cpu; + cpufreq_freq_transition_end(policy, &freqs, 0); + cpufreq_cpu_put(policy); + } +#endif + p->idx_opp_tbl = freq_idx; + +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + aee_rr_rec_cpu_dvfs_oppidx( + (aee_rr_curr_cpu_dvfs_oppidx() & 0xF0) | p->idx_opp_tbl); + else + aee_rr_rec_cpu_dvfs_oppidx( + (aee_rr_curr_cpu_dvfs_oppidx() & 0x0F) | (p->idx_opp_tbl << 4)); +#endif + } + cpufreq_unlock(flags); + } + break; + case CPU_DOWN_PREPARE: + cpus = cpumask_weight(&cpu_online_cpumask); + cpufreq_ver("CPU_DOWN_PREPARE -> cpus = %d\n", cpus); + if (cpus == 1) { + cpufreq_ver("CPU_DOWN_PREPARE last CPU of %s\n", + cpu_dvfs_get_name(p)); + cpufreq_lock(flags); + p->armpll_is_available = 0; +#ifdef CONFIG_HYBRID_CPU_DVFS + if (enable_cpuhvfs) + cpuhvfs_notify_cluster_off(cpu_dvfs_to_cluster(p)); + else +#endif /* take care the above code segment */ + p->ops->set_cur_freq(p, cpu_dvfs_get_cur_freq(p), cpu_dvfs_get_min_freq(p)); + + p->idx_opp_tbl = p->nr_opp_tbl - 1; + +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + aee_rr_rec_cpu_dvfs_oppidx((aee_rr_curr_cpu_dvfs_oppidx() & 0xF0) | + p->idx_opp_tbl); + else + aee_rr_rec_cpu_dvfs_oppidx((aee_rr_curr_cpu_dvfs_oppidx() & 0x0F) | + (p->idx_opp_tbl << 4)); +#endif + cpufreq_unlock(flags); + } + break; + case CPU_DOWN_FAILED: + cpus = cpumask_weight(&cpu_online_cpumask); + cpufreq_ver("CPU_DOWN_FAILED -> cpus = %d\n", cpus); + if (cpus == 1) { + cpufreq_ver("CPU_DOWN_FAILED first CPU of %s\n", + cpu_dvfs_get_name(p)); + cpufreq_lock(flags); + p->armpll_is_available = 1; +#ifdef CONFIG_HYBRID_CPU_DVFS + if (enable_cpuhvfs) + cpuhvfs_notify_cluster_on(cpu_dvfs_to_cluster(p)); +#endif + if (action == CPU_DOWN_FAILED) { + cur_volt = p->ops->get_cur_volt(p); + freq_idx = _search_available_freq_idx_under_v(p, cur_volt); + freq_idx = MAX(freq_idx, _calc_new_opp_idx(p, freq_idx)); + +#ifdef CONFIG_CPU_FREQ + policy = cpufreq_cpu_get(cpu); + freqs.old = cpu_dvfs_get_cur_freq(p); + freqs.new = cpu_dvfs_get_freq_by_idx(p, freq_idx); + if (policy) { + freqs.cpu = policy->cpu; + cpufreq_freq_transition_begin(policy, &freqs); + } +#endif + p->ops->set_cur_freq(p, cpu_dvfs_get_cur_freq(p) + , cpu_dvfs_get_freq_by_idx(p, freq_idx)); + +#ifdef CONFIG_CPU_FREQ + if (policy) { + freqs.cpu = policy->cpu; + cpufreq_freq_transition_end(policy, &freqs, 0); + cpufreq_cpu_put(policy); + } +#endif + p->idx_opp_tbl = freq_idx; + +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + aee_rr_rec_cpu_dvfs_oppidx( + (aee_rr_curr_cpu_dvfs_oppidx() & 0xF0) | p->idx_opp_tbl); + else + aee_rr_rec_cpu_dvfs_oppidx( + (aee_rr_curr_cpu_dvfs_oppidx() & 0x0F) | (p->idx_opp_tbl << 4)); +#endif + } + cpufreq_unlock(flags); + } + break; + } +#ifndef DISABLE_PBM_FEATURE + /* Notify PBM after CPU on/off */ + if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN + || action == CPU_DEAD || action == CPU_DEAD_FROZEN) { + + cpufreq_lock(flags); + + if (!p->dvfs_disable_by_suspend) + _kick_PBM_by_cpu(p); + + cpufreq_unlock(flags); + } +#endif + } + + cpufreq_ver("@%s():%d, num_online_cpus_delta = %d\n", __func__, __LINE__, + num_online_cpus_delta); + + cpufreq_ver("@%s():%d, cpu = %d, action = %lu, oppidx = %d, num_online_cpus = %d\n" + , __func__, __LINE__, cpu, action, p->idx_opp_tbl, online_cpus); + + return NOTIFY_OK; +} + +static int _sync_opp_tbl_idx(struct mt_cpu_dvfs *p) +{ + int ret = -1; + unsigned int freq; + int i; + + FUNC_ENTER(FUNC_LV_HELP); + + BUG_ON(NULL == p); + BUG_ON(NULL == p->opp_tbl); + BUG_ON(NULL == p->ops); + + freq = p->ops->get_cur_phy_freq(p); + + for (i = p->nr_opp_tbl - 1; i >= 0; i--) { + if (freq <= cpu_dvfs_get_freq_by_idx(p, i)) { + p->idx_opp_tbl = i; + break; + } + } + +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + aee_rr_rec_cpu_dvfs_oppidx((aee_rr_curr_cpu_dvfs_oppidx() & 0xF0) | p->idx_opp_tbl); + else + aee_rr_rec_cpu_dvfs_oppidx((aee_rr_curr_cpu_dvfs_oppidx() & 0x0F) | (p->idx_opp_tbl << 4)); +#endif + + if (i >= 0) { + cpufreq_ver("%s freq = %d\n", cpu_dvfs_get_name(p), cpu_dvfs_get_cur_freq(p)); + ret = 0; + } else + cpufreq_warn("%s can't find freq = %d\n", cpu_dvfs_get_name(p), freq); + + FUNC_EXIT(FUNC_LV_HELP); + + return ret; +} + +static int _mt_cpufreq_sync_opp_tbl_idx(struct mt_cpu_dvfs *p) +{ + int ret = -1; + + FUNC_ENTER(FUNC_LV_LOCAL); + + + if (cpu_dvfs_is_available(p)) + ret = _sync_opp_tbl_idx(p); + + + cpufreq_info("%s freq = %d\n", cpu_dvfs_get_name(p), cpu_dvfs_get_cur_freq(p)); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return ret; +} + +struct cpumask cpumask_big; +struct cpumask cpumask_little; + +static enum mt_cpu_dvfs_id _get_cpu_dvfs_id(unsigned int cpu_id) +{ + int cluster_id; + + cluster_id = arch_get_cluster_id(cpu_id); + + if (cluster_id == 0) + return MT_CPU_DVFS_LITTLE; + else + return MT_CPU_DVFS_BIG; +} + +static int _mt_cpufreq_setup_freqs_table(struct cpufreq_policy *policy, + struct mt_cpu_freq_info *freqs, int num) +{ + struct mt_cpu_dvfs *p; + int ret = 0; + + FUNC_ENTER(FUNC_LV_LOCAL); + + BUG_ON(NULL == policy); + BUG_ON(NULL == freqs); + + p = id_to_cpu_dvfs(_get_cpu_dvfs_id(policy->cpu)); + +#ifdef CONFIG_CPU_FREQ + ret = cpufreq_frequency_table_cpuinfo(policy, p->freq_tbl_for_cpufreq); + + if (!ret) + policy->freq_table = p->freq_tbl_for_cpufreq; + +#endif + cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); + cpumask_copy(policy->related_cpus, policy->cpus); + + FUNC_EXIT(FUNC_LV_LOCAL); + + return 0; +} + +#define SIGLE_CORE_IDX 4 +static unsigned int _calc_new_opp_idx(struct mt_cpu_dvfs *p, int new_opp_idx) +{ + unsigned int online_cpus; + + FUNC_ENTER(FUNC_LV_HELP); + + BUG_ON(NULL == p); + + cpufreq_ver("new_opp_idx = %d, idx_opp_ppm_base = %d, idx_opp_ppm_limit = %d\n", + new_opp_idx , p->idx_opp_ppm_base, p->idx_opp_ppm_limit); + + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) { + online_cpus = num_online_cpus() + num_online_cpus_delta; + + if (online_cpus == 1 && (new_opp_idx > SIGLE_CORE_IDX)) + new_opp_idx = SIGLE_CORE_IDX; + } + + if ((p->idx_opp_ppm_limit != -1) && (new_opp_idx < p->idx_opp_ppm_limit)) + new_opp_idx = p->idx_opp_ppm_limit; + + if ((p->idx_opp_ppm_base != -1) && (new_opp_idx > p->idx_opp_ppm_base)) + new_opp_idx = p->idx_opp_ppm_base; + + if ((p->idx_opp_ppm_base == p->idx_opp_ppm_limit) && p->idx_opp_ppm_base != -1) + new_opp_idx = p->idx_opp_ppm_base; + +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + if (cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE)) + aee_rr_rec_cpu_dvfs_oppidx((aee_rr_curr_cpu_dvfs_oppidx() & 0xF0) | new_opp_idx); + else + aee_rr_rec_cpu_dvfs_oppidx((aee_rr_curr_cpu_dvfs_oppidx() & 0x0F) | (new_opp_idx << 4)); +#endif + FUNC_EXIT(FUNC_LV_HELP); + + return new_opp_idx; +} + +static void ppm_limit_callback(struct ppm_client_req req) +{ + struct ppm_client_req *ppm = (struct ppm_client_req *)&req; + unsigned long flags; + + struct mt_cpu_dvfs *p; + int ignore_ppm[NR_MT_CPU_DVFS] = {0}; + unsigned int i; + struct cpufreq_policy *policy[NR_MT_CPU_DVFS]; + struct cpumask dvfs_cpumask[NR_MT_CPU_DVFS]; + struct cpumask cpu_online_cpumask; + char str1[32]; + char str2[32]; + unsigned int ret; + + for (i = 0; i < NR_MT_CPU_DVFS; i++) + arch_get_cluster_cpus(&dvfs_cpumask[i], i); + + cpufreq_ver("get feedback from PPM module\n"); + cpufreq_ver("cluster_id = %d, cpu_id = %d, min_cpufreq_idx = %d, max_cpufreq_idx = %d\n", + ppm->cpu_limit[0].cluster_id, ppm->cpu_limit[0].cpu_id, + ppm->cpu_limit[0].min_cpufreq_idx, ppm->cpu_limit[0].max_cpufreq_idx); + cpufreq_ver("has_advise_freq = %d, advise_cpufreq_idx = %d\n", + ppm->cpu_limit[0].has_advise_freq, ppm->cpu_limit[0].advise_cpufreq_idx); + cpufreq_ver("cluster_id = %d, cpu_id = %d, min_cpufreq_idx = %d, max_cpufreq_idx = %d\n", + ppm->cpu_limit[1].cluster_id, ppm->cpu_limit[1].cpu_id, ppm->cpu_limit[1].min_cpufreq_idx, + ppm->cpu_limit[1].max_cpufreq_idx); + cpufreq_ver("has_advise_freq = %d, advise_cpufreq_idx = %d\n", + ppm->cpu_limit[1].has_advise_freq, ppm->cpu_limit[1].advise_cpufreq_idx); + + cpufreq_lock(flags); + for (i = 0; i < ppm->cluster_num; i++) { + if (i == 0) + p = id_to_cpu_dvfs(MT_CPU_DVFS_LITTLE); + else + p = id_to_cpu_dvfs(MT_CPU_DVFS_BIG); + + /* make sure the idx is synced */ + /* _sync_opp_tbl_idx(p); */ + + ignore_ppm[i] = 0; + if (ppm->cpu_limit[i].has_advise_freq) { + p->idx_opp_ppm_base = ppm->cpu_limit[i].advise_cpufreq_idx; + p->idx_opp_ppm_limit = ppm->cpu_limit[i].advise_cpufreq_idx; + if (p->idx_opp_tbl == ppm->cpu_limit[i].advise_cpufreq_idx) { + cpufreq_ver("idx = %d, advise_cpufreq_idx = %d\n", p->idx_opp_tbl , + ppm->cpu_limit[i].advise_cpufreq_idx); + ignore_ppm[i] = 1; + } + } else { + p->idx_opp_ppm_base = ppm->cpu_limit[i].min_cpufreq_idx; /* ppm update base */ + p->idx_opp_ppm_limit = ppm->cpu_limit[i].max_cpufreq_idx; /* ppm update limit */ + if ((p->idx_opp_tbl >= ppm->cpu_limit[i].max_cpufreq_idx) + && (p->idx_opp_tbl <= ppm->cpu_limit[i].min_cpufreq_idx)) { + cpufreq_ver("idx = %d, idx_opp_ppm_base = %d, idx_opp_ppm_limit = %d\n", + p->idx_opp_tbl, p->idx_opp_ppm_base, p->idx_opp_ppm_limit); + ignore_ppm[i] = 1; + } + } + } + cpufreq_unlock(flags); + + get_online_cpus(); + cpumask_and(&cpu_online_cpumask, &dvfs_cpumask[MT_CPU_DVFS_LITTLE], cpu_online_mask); + cpulist_scnprintf(str1, sizeof(str1), (const struct cpumask *)cpu_online_mask); + cpulist_scnprintf(str2, sizeof(str2), (const struct cpumask *)&cpu_online_cpumask); + cpufreq_ver("cpu_online_mask = %s, cpu_online_cpumask for little = %s\n", str1, str2); + ret = -1; + for_each_cpu(i, &cpu_online_cpumask) { + policy[MT_CPU_DVFS_LITTLE] = cpufreq_cpu_get(i); + if (policy[MT_CPU_DVFS_LITTLE]) { + p = id_to_cpu_dvfs(MT_CPU_DVFS_LITTLE); + if (p->idx_opp_ppm_limit == -1) + policy[MT_CPU_DVFS_LITTLE]->max = cpu_dvfs_get_max_freq(p); + else + policy[MT_CPU_DVFS_LITTLE]->max = cpu_dvfs_get_freq_by_idx(p, + p->idx_opp_ppm_limit); + if (p->idx_opp_ppm_base == -1) + policy[MT_CPU_DVFS_LITTLE]->min = cpu_dvfs_get_min_freq(p); + else + policy[MT_CPU_DVFS_LITTLE]->min = cpu_dvfs_get_freq_by_idx(p, + p->idx_opp_ppm_base); + cpufreq_cpu_put(policy[MT_CPU_DVFS_LITTLE]); + ret = 0; + break; + } + } + put_online_cpus(); + + if (!ignore_ppm[MT_CPU_DVFS_LITTLE]) { + if (!ret) + _mt_cpufreq_set(policy[MT_CPU_DVFS_LITTLE], MT_CPU_DVFS_LITTLE, -1); + else + goto second_limit; + } +second_limit: + get_online_cpus(); + cpumask_and(&cpu_online_cpumask, &dvfs_cpumask[MT_CPU_DVFS_BIG], cpu_online_mask); + cpulist_scnprintf(str1, sizeof(str1), (const struct cpumask *)cpu_online_mask); + cpulist_scnprintf(str2, sizeof(str2), (const struct cpumask *)&cpu_online_cpumask); + cpufreq_ver("cpu_online_mask = %s, cpu_online_cpumask for big = %s\n", str1, str2); + ret = -1; + for_each_cpu(i, &cpu_online_cpumask) { + policy[MT_CPU_DVFS_BIG] = cpufreq_cpu_get(i); + if (policy[MT_CPU_DVFS_BIG]) { + p = id_to_cpu_dvfs(MT_CPU_DVFS_BIG); + if (p->idx_opp_ppm_limit == -1) + policy[MT_CPU_DVFS_BIG]->max = cpu_dvfs_get_max_freq(p); + else + policy[MT_CPU_DVFS_BIG]->max = cpu_dvfs_get_freq_by_idx(p, + p->idx_opp_ppm_limit); + if (p->idx_opp_ppm_base == -1) + policy[MT_CPU_DVFS_BIG]->min = cpu_dvfs_get_min_freq(p); + else + policy[MT_CPU_DVFS_BIG]->min = cpu_dvfs_get_freq_by_idx(p, + p->idx_opp_ppm_base); + cpufreq_cpu_put(policy[MT_CPU_DVFS_BIG]); + ret = 0; + break; + } + } + put_online_cpus(); + + if (!ignore_ppm[MT_CPU_DVFS_BIG]) { + if (!ret) + _mt_cpufreq_set(policy[MT_CPU_DVFS_BIG], MT_CPU_DVFS_BIG, -1); + else + goto no_limit; + } +no_limit: + return; +} + +/* + * cpufreq driver + */ +static int _mt_cpufreq_verify(struct cpufreq_policy *policy) +{ + struct mt_cpu_dvfs *p; + int ret = 0; /* cpufreq_frequency_table_verify() always return 0 */ + + FUNC_ENTER(FUNC_LV_MODULE); + + p = id_to_cpu_dvfs(_get_cpu_dvfs_id(policy->cpu)); + + BUG_ON(NULL == p); + +#ifdef CONFIG_CPU_FREQ + ret = cpufreq_frequency_table_verify(policy, p->freq_tbl_for_cpufreq); +#endif + + FUNC_EXIT(FUNC_LV_MODULE); + + return ret; +} +#ifdef ICORE_BRANCH +/* static int _mt_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) */ +#else +static int _mt_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, + unsigned int relation) +#endif +{ + enum mt_cpu_dvfs_id id = _get_cpu_dvfs_id(policy->cpu); + int ret = 0; + unsigned int new_opp_idx; + + FUNC_ENTER(FUNC_LV_MODULE); + +#ifdef ICORE_BRANCH + if (policy->cpu >= num_possible_cpus() + || (id_to_cpu_dvfs(id) && id_to_cpu_dvfs(id)->dvfs_disable_by_procfs) + ) + return -EINVAL; +#else + if (policy->cpu >= num_possible_cpus() + || cpufreq_frequency_table_target(policy, id_to_cpu_dvfs(id)->freq_tbl_for_cpufreq, + target_freq, relation, &new_opp_idx) + || (id_to_cpu_dvfs(id) && id_to_cpu_dvfs(id)->dvfs_disable_by_procfs) + /* || (id_to_cpu_dvfs(id) && id_to_cpu_dvfs(id)->dvfs_disable_by_suspend) */ + ) + return -EINVAL; +#endif + +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + if (id == MT_CPU_DVFS_LITTLE) + aee_rr_rec_cpu_dvfs_status(aee_rr_curr_cpu_dvfs_status() | + (1 << CPU_DVFS_LITTLE_IS_DOING_DVFS)); + else + aee_rr_rec_cpu_dvfs_status(aee_rr_curr_cpu_dvfs_status() | + (1 << CPU_DVFS_BIG_IS_DOING_DVFS)); +#endif + /* PPM => idx */ + /* _mt_cpufreq_set(policy, id, index); */ + _mt_cpufreq_set(policy, id, new_opp_idx); + +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + if (id == MT_CPU_DVFS_LITTLE) + aee_rr_rec_cpu_dvfs_status(aee_rr_curr_cpu_dvfs_status() & + ~(1 << CPU_DVFS_LITTLE_IS_DOING_DVFS)); + else + aee_rr_rec_cpu_dvfs_status(aee_rr_curr_cpu_dvfs_status() & + ~(1 << CPU_DVFS_BIG_IS_DOING_DVFS)); +#endif + + FUNC_EXIT(FUNC_LV_MODULE); + + return ret; +} + +static int _mt_cpufreq_init(struct cpufreq_policy *policy) +{ + int ret = -EINVAL; + unsigned long flags; + + FUNC_ENTER(FUNC_LV_MODULE); + + max_cpu_num = num_possible_cpus(); + + if (policy->cpu >= max_cpu_num) + return -EINVAL; + + cpufreq_ver("@%s: max_cpu_num: %d\n", __func__, max_cpu_num); + + policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; + cpumask_setall(policy->cpus); + + policy->cpuinfo.transition_latency = 1000; + + { + enum mt_cpu_dvfs_id id = _get_cpu_dvfs_id(policy->cpu); + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + unsigned int lv = _mt_cpufreq_get_cpu_level(); + struct opp_tbl_info *opp_tbl_info = + (MT_CPU_DVFS_BIG == + id) ? &opp_tbls_big[0][CPU_LV_TO_OPP_IDX(lv)] : + &opp_tbls_little[0][CPU_LV_TO_OPP_IDX(lv)]; + + BUG_ON(NULL == p); + BUG_ON(! + (lv == CPU_LEVEL_0 || lv == CPU_LEVEL_1 || lv == CPU_LEVEL_2 + || lv == CPU_LEVEL_3)); + + p->cpu_level = lv; + + ret = _mt_cpufreq_setup_freqs_table(policy, + opp_tbl_info->opp_tbl, opp_tbl_info->size); + + policy->cpuinfo.max_freq = cpu_dvfs_get_max_freq(id_to_cpu_dvfs(id)); + policy->cpuinfo.min_freq = cpu_dvfs_get_min_freq(id_to_cpu_dvfs(id)); + + policy->cur = p->ops->get_cur_phy_freq(p); /* use cur phy freq is better */ + if (p->idx_opp_ppm_limit == -1) + policy->max = cpu_dvfs_get_max_freq(id_to_cpu_dvfs(id)); + else + policy->max = cpu_dvfs_get_freq_by_idx(id_to_cpu_dvfs(id), p->idx_opp_ppm_limit); + + if (p->idx_opp_ppm_base == -1) + policy->min = cpu_dvfs_get_min_freq(id_to_cpu_dvfs(id)); + else + policy->min = cpu_dvfs_get_freq_by_idx(id_to_cpu_dvfs(id), p->idx_opp_ppm_base); + + if (_mt_cpufreq_sync_opp_tbl_idx(p) >= 0) + if (p->idx_normal_max_opp == -1) + p->idx_normal_max_opp = p->idx_opp_tbl; + + if (MT_CPU_DVFS_BIG == id) { + if (lv == CPU_LEVEL_0) + p->freq_tbl = opp_tbl_method_L_e1; + else if (lv == CPU_LEVEL_1) + p->freq_tbl = opp_tbl_method_L_e2; + else + p->freq_tbl = opp_tbl_method_L_e3; + p->armpll_addr = (unsigned int *)ARMCA15PLL_CON1; + p->armpll_clk_src = TOP_CKMUXSEL_ARMPLL_L; + } else { + if (lv == CPU_LEVEL_0) + p->freq_tbl = opp_tbl_method_LL_e1; + else if (lv == CPU_LEVEL_1) + p->freq_tbl = opp_tbl_method_LL_e2; + else + p->freq_tbl = opp_tbl_method_LL_e3; + p->armpll_addr = (unsigned int *)ARMCA7PLL_CON1; + p->armpll_clk_src = TOP_CKMUXSEL_ARMPLL_LL; + } + + cpufreq_lock(flags); + p->armpll_is_available = 1; +#ifdef CONFIG_HYBRID_CPU_DVFS + if (enable_cpuhvfs) + cpuhvfs_notify_cluster_on(cpu_dvfs_to_cluster(p)); +#endif + cpufreq_unlock(flags); + } + + if (ret) + cpufreq_err("failed to setup frequency table\n"); + + FUNC_EXIT(FUNC_LV_MODULE); + + return ret; +} + +static int _mt_cpufreq_exit(struct cpufreq_policy *policy) +{ + return 0; +} + +static unsigned int _mt_cpufreq_get(unsigned int cpu) +{ + struct mt_cpu_dvfs *p; + + FUNC_ENTER(FUNC_LV_MODULE); + + p = id_to_cpu_dvfs(_get_cpu_dvfs_id(cpu)); + + BUG_ON(NULL == p); + + FUNC_EXIT(FUNC_LV_MODULE); + + return cpu_dvfs_get_cur_freq(p); +} + +#ifdef CONFIG_HYBRID_CPU_DVFS +#include +#include + +static void __set_cpuhvfs_init_sta(struct init_sta *sta) +{ + int i, r; + unsigned int volt; + struct mt_cpu_dvfs *p; + + for (i = 0; i < NUM_CPU_CLUSTER; i++) { + p = cluster_to_cpu_dvfs(i); + + r = _sync_opp_tbl_idx(p); /* find OPP with current frequency */ + BUG_ON(r); + + volt = get_cur_volt_extbuck(p); + BUG_ON(volt < EXTBUCK_VAL_TO_VOLT(0)); + + sta->opp[i] = p->idx_opp_tbl; + sta->freq[i] = p->ops->get_cur_phy_freq(p); + sta->volt[i] = VOLT_TO_EXTBUCK_VAL(volt); + sta->is_on[i] = (p->armpll_is_available ? true : false); + } +} + +static int _mt_cpufreq_syscore_suspend(void) +{ + if (enable_cpuhvfs) + return cpuhvfs_dvfsp_suspend(); + + return 0; +} + +static void _mt_cpufreq_syscore_resume(void) +{ + if (enable_cpuhvfs) { + int i; + enum mt_cpu_dvfs_id id = _get_cpu_dvfs_id(smp_processor_id()); + struct init_sta sta; + struct mt_cpu_dvfs *p; + + for (i = 0; i < NUM_CPU_CLUSTER; i++) { + p = cluster_to_cpu_dvfs(i); + + sta.opp[i] = OPP_AT_SUSPEND; + sta.freq[i] = p->ops->get_cur_phy_freq(p); + sta.volt[i] = VOLT_AT_SUSPEND; + } + + cpuhvfs_dvfsp_resume(id_to_cluster(id), &sta); + } +} + +static struct syscore_ops _mt_cpufreq_syscore_ops = { + .suspend = _mt_cpufreq_syscore_suspend, + .resume = _mt_cpufreq_syscore_resume, +}; +#endif + +#ifdef CONFIG_CPU_FREQ +static struct freq_attr *_mt_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static struct cpufreq_driver _mt_cpufreq_driver = { + .verify = _mt_cpufreq_verify, + .target = _mt_cpufreq_target, + .init = _mt_cpufreq_init, + .exit = _mt_cpufreq_exit, + .get = _mt_cpufreq_get, + .name = "mt-cpufreq", + .attr = _mt_cpufreq_attr, +}; +#endif + +/* + * Platform driver + */ +static int +_mt_cpufreq_pm_callback(struct notifier_block *nb, + unsigned long action, void *ptr) +{ + struct mt_cpu_dvfs *p; + int i; + unsigned long flags; + + switch (action) { + + case PM_SUSPEND_PREPARE: + cpufreq_ver("PM_SUSPEND_PREPARE\n"); + cpufreq_lock(flags); + for_each_cpu_dvfs(i, p) { + if (!cpu_dvfs_is_available(p)) + continue; + p->dvfs_disable_by_suspend = true; + } + cpufreq_unlock(flags); + break; + case PM_HIBERNATION_PREPARE: + break; + + case PM_POST_SUSPEND: + cpufreq_ver("PM_POST_SUSPEND\n"); + cpufreq_lock(flags); + for_each_cpu_dvfs(i, p) { + if (!cpu_dvfs_is_available(p)) + continue; + p->dvfs_disable_by_suspend = false; + } + cpufreq_unlock(flags); + break; + case PM_POST_HIBERNATION: + break; + + default: + return NOTIFY_DONE; + } + return NOTIFY_OK; +} +static int _mt_cpufreq_suspend(struct device *dev) +{ +#if 0 + struct mt_cpu_dvfs *p; + int i; + + FUNC_ENTER(FUNC_LV_MODULE); + + for_each_cpu_dvfs(i, p) { + if (!cpu_dvfs_is_available(p)) + continue; + + p->dvfs_disable_by_suspend = true; + } + + FUNC_EXIT(FUNC_LV_MODULE); +#endif + return 0; +} + +static int _mt_cpufreq_resume(struct device *dev) +{ +#if 0 + struct mt_cpu_dvfs *p; + int i; + + FUNC_ENTER(FUNC_LV_MODULE); + + for_each_cpu_dvfs(i, p) { + if (!cpu_dvfs_is_available(p)) + continue; + + p->dvfs_disable_by_suspend = false; + } + + FUNC_EXIT(FUNC_LV_MODULE); +#endif + return 0; +} + +static int _mt_cpufreq_pdrv_probe(struct platform_device *pdev) +{ + /* For table preparing*/ + unsigned int lv = _mt_cpufreq_get_cpu_level(); + struct mt_cpu_dvfs *p; + int i, j; + struct opp_tbl_info *opp_tbl_info; + struct cpufreq_frequency_table *table; + + FUNC_ENTER(FUNC_LV_MODULE); + + BUG_ON(!(lv == CPU_LEVEL_0 || lv == CPU_LEVEL_1 || lv == CPU_LEVEL_2 || lv == CPU_LEVEL_3)); +#if 0 + /* init static power table */ + mt_spower_init(); +#endif + +#ifdef CONFIG_CPU_DVFS_AEE_RR_REC + _mt_cpufreq_aee_init(); +#endif +/* Prepare OPP table for PPM in probe to avoid nested lock */ + for_each_cpu_dvfs(j, p) { + opp_tbl_info = (MT_CPU_DVFS_BIG == j) ? + &opp_tbls_big[0][CPU_LV_TO_OPP_IDX(lv)] : &opp_tbls_little[0][CPU_LV_TO_OPP_IDX(lv)]; + if (NULL == p->freq_tbl_for_cpufreq) { + table = kzalloc((opp_tbl_info->size + 1) * sizeof(*table), GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + for (i = 0; i < opp_tbl_info->size; i++) { + table[i].driver_data = i; + table[i].frequency = opp_tbl_info->opp_tbl[i].cpufreq_khz; + } + + table[opp_tbl_info->size].driver_data = i; + table[opp_tbl_info->size].frequency = CPUFREQ_TABLE_END; + + p->opp_tbl = opp_tbl_info->opp_tbl; + p->nr_opp_tbl = opp_tbl_info->size; + p->freq_tbl_for_cpufreq = table; + } + + if (j == MT_CPU_DVFS_LITTLE) { + if (lv == CPU_LEVEL_0) + mt_ppm_set_dvfs_table(0, p->freq_tbl_for_cpufreq, + opp_tbl_info->size, DVFS_TABLE_TYPE_FY); + else + mt_ppm_set_dvfs_table(0, p->freq_tbl_for_cpufreq, + opp_tbl_info->size, DVFS_TABLE_TYPE_SB); + } else { + if (lv == CPU_LEVEL_0) + mt_ppm_set_dvfs_table(4, p->freq_tbl_for_cpufreq, + opp_tbl_info->size, DVFS_TABLE_TYPE_FY); + else + mt_ppm_set_dvfs_table(4, p->freq_tbl_for_cpufreq, + opp_tbl_info->size, DVFS_TABLE_TYPE_SB); + } + } + +#ifdef CONFIG_HYBRID_CPU_DVFS /* before cpufreq_register_driver */ + if (enable_cpuhvfs) { + int r; + struct init_sta sta; + + __set_cpuhvfs_init_sta(&sta); + + r = cpuhvfs_kick_dvfsp_to_run(&sta); + if (!r) { + for_each_cpu_dvfs(i, p) { + p->ops->set_cur_freq = set_cur_freq_hybrid; + p->ops->set_cur_volt = set_cur_volt_hybrid; + if (enable_cpuhvfs == 1) + p->ops->get_cur_volt = get_cur_volt_hybrid; + } + + register_syscore_ops(&_mt_cpufreq_syscore_ops); + } else { + enable_cpuhvfs = 0; + } + } +#endif + +#ifdef CONFIG_CPU_FREQ + cpufreq_register_driver(&_mt_cpufreq_driver); +#endif + register_hotcpu_notifier(&_mt_cpufreq_cpu_notifier); + mt_ppm_register_client(PPM_CLIENT_DVFS, &ppm_limit_callback); + pm_notifier(_mt_cpufreq_pm_callback, 0); + FUNC_EXIT(FUNC_LV_MODULE); + + return 0; +} + +static int _mt_cpufreq_pdrv_remove(struct platform_device *pdev) +{ + FUNC_ENTER(FUNC_LV_MODULE); + + unregister_hotcpu_notifier(&_mt_cpufreq_cpu_notifier); +#ifdef CONFIG_CPU_FREQ + cpufreq_unregister_driver(&_mt_cpufreq_driver); +#endif + + FUNC_EXIT(FUNC_LV_MODULE); + + return 0; +} + +static const struct dev_pm_ops _mt_cpufreq_pm_ops = { + .suspend = _mt_cpufreq_suspend, + .resume = _mt_cpufreq_resume, + .freeze = _mt_cpufreq_suspend, + .thaw = _mt_cpufreq_resume, + .restore = _mt_cpufreq_resume, +}; + +struct platform_device _mt_cpufreq_pdev = { + .name = "mt-cpufreq", + .id = -1, +}; + +static struct platform_driver _mt_cpufreq_pdrv = { + .probe = _mt_cpufreq_pdrv_probe, + .remove = _mt_cpufreq_pdrv_remove, + .driver = { + .name = "mt-cpufreq", + .pm = &_mt_cpufreq_pm_ops, + .owner = THIS_MODULE, + }, +}; + +#ifndef __KERNEL__ +/* +* For CTP +*/ +int mt_cpufreq_pdrv_probe(void) +{ + static struct cpufreq_policy policy_little; + static struct cpufreq_policy policy_big; + + _mt_cpufreq_pdrv_probe(NULL); + + policy_little.cpu = cpu_dvfs[MT_CPU_DVFS_LITTLE].cpu_id; + _mt_cpufreq_init(&policy_little); + + policy_big.cpu = cpu_dvfs[MT_CPU_DVFS_BIG].cpu_id; + _mt_cpufreq_init(&policy_big); + + return 0; +} + +int mt_cpufreq_set_opp_volt(enum mt_cpu_dvfs_id id, int idx) +{ + int ret = 0; + static struct opp_tbl_info *info; + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + + switch (id) { + case MT_CPU_DVFS_LITTLE: + info = &opp_tbls_little[CPU_LV_TO_OPP_IDX(CPU_LEVEL_0)]; + break; + + case MT_CPU_DVFS_BIG: + default: + info = &opp_tbls_big[CPU_LV_TO_OPP_IDX(CPU_LEVEL_0)]; + break; + } + + if (idx >= info->size) + return -1; + + return _set_cur_volt_locked(p, info->opp_tbl[idx].cpufreq_volt); + +} + +int mt_cpufreq_set_freq(enum mt_cpu_dvfs_id id, int idx) +{ + unsigned int cur_freq; + unsigned int target_freq; + int ret; + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + + cur_freq = p->ops->get_cur_phy_freq(p); + target_freq = cpu_dvfs_get_freq_by_idx(p, idx); + + ret = _cpufreq_set_locked(p, cur_freq, target_freq); + + if (ret < 0) + return ret; + + return target_freq; +} + +#include "dvfs.h" + +static unsigned int _mt_get_cpu_freq(void) +{ + unsigned int output = 0, i = 0; + unsigned int temp, clk26cali_0, clk_dbg_cfg, clk_misc_cfg_0, clk26cali_1; + + clk26cali_0 = DRV_Reg32(CLK26CALI_0); + + clk_dbg_cfg = DRV_Reg32(CLK_DBG_CFG); + DRV_WriteReg32(CLK_DBG_CFG, 2 << 16); /* sel abist_cksw and enable freq meter sel abist */ + + clk_misc_cfg_0 = DRV_Reg32(CLK_MISC_CFG_0); + DRV_WriteReg32(CLK_MISC_CFG_0, (clk_misc_cfg_0 & 0x0000FFFF) | (0x07 << 16)); /* select divider */ + + clk26cali_1 = DRV_Reg32(CLK26CALI_1); + DRV_WriteReg32(CLK26CALI_1, 0x00ff0000); /* */ + + /* temp = DRV_Reg32(CLK26CALI_0); */ + DRV_WriteReg32(CLK26CALI_0, 0x1000); + DRV_WriteReg32(CLK26CALI_0, 0x1010); + + /* wait frequency meter finish */ + while (DRV_Reg32(CLK26CALI_0) & 0x10) { + mdelay(10); + i++; + + if (i > 10) + break; + } + + temp = DRV_Reg32(CLK26CALI_1) & 0xFFFF; + + output = (((temp * 26000)) / 256) * 8; /* Khz */ + + DRV_WriteReg32(CLK_DBG_CFG, clk_dbg_cfg); + DRV_WriteReg32(CLK_MISC_CFG_0, clk_misc_cfg_0); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0); + DRV_WriteReg32(CLK26CALI_1, clk26cali_1); + + cpufreq_dbg("CLK26CALI_1 = 0x%x, CPU freq = %d KHz\n", temp, output); + + if (i > 10) { + cpufreq_dbg("meter not finished!\n"); + return 0; + } else + return output; +} + +unsigned int dvfs_get_cpu_freq(enum mt_cpu_dvfs_id id) +{ + return _mt_get_cpu_freq(); +} + +void dvfs_set_cpu_freq_FH(enum mt_cpu_dvfs_id id, int freq) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + int idx; + + if (!p) { + cpufreq_err("%s(%d, %d), id is wrong\n", __func__, id, freq); + return; + } + + idx = _search_available_freq_idx(p, freq, CPUFREQ_RELATION_H); + + if (-1 == idx) { + cpufreq_err("%s(%d, %d), freq is wrong\n", __func__, id, freq); + return; + } + + mt_cpufreq_set_freq(id, idx); +} + +unsigned int cpu_frequency_output_slt(enum mt_cpu_dvfs_id id) +{ + return (MT_CPU_DVFS_LITTLE == id) ? _mt_get_smallcpu_freq() : _mt_get_bigcpu_freq(); +} + +void dvfs_set_cpu_volt(enum mt_cpu_dvfs_id id, int volt) /* volt: mv * 100 */ +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(id); + + cpufreq_dbg("%s(%d, %d)\n", __func__, id, volt); + + if (!p) { + cpufreq_err("%s(%d, %d), id is wrong\n", __func__, id, volt); + return; + } + + if (_set_cur_volt_locked(p, volt)) + cpufreq_err("%s(%d, %d), set volt fail\n", __func__, id, volt); + + cpufreq_dbg("%s(%d, %d) Vproc = %d, Vsram = %d\n", + __func__, id, volt, p->ops->get_cur_volt(p), get_cur_vsram(p) + ); +} + +static unsigned int vcpu_backup; +void dvfs_disable_by_ptpod(void) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(MT_CPU_DVFS_LITTLE); + + cpufreq_dbg("%s()\n", __func__); + + vcpu_backup = cpu_dvfs_get_cur_volt(p); + + dvfs_set_cpu_volt(MT_CPU_DVFS_LITTLE, 100000); /* 1V */ +} + +void dvfs_enable_by_ptpod(void) +{ + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(MT_CPU_DVFS_LITTLE); + + cpufreq_dbg("%s()\n", __func__); + + dvfs_set_cpu_volt(MT_CPU_DVFS_LITTLE, vcpu_backup); + +} +#endif + +#ifdef CONFIG_PROC_FS +/* +* PROC +*/ + +static char *_copy_from_user_for_proc(const char __user *buffer, size_t count) +{ + char *buf = (char *)__get_free_page(GFP_USER); + + if (!buf) + return NULL; + + if (count >= PAGE_SIZE) + goto out; + + if (copy_from_user(buf, buffer, count)) + goto out; + + buf[count] = '\0'; + + return buf; + +out: + free_page((unsigned long)buf); + + return NULL; +} + +/* cpufreq_debug */ +static int cpufreq_debug_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "cpufreq debug (log level) = %d\n", func_lv_mask); + + return 0; +} + +static ssize_t cpufreq_debug_proc_write(struct file *file, const char __user *buffer, size_t count, + loff_t *pos) +{ + unsigned int dbg_lv; + int rc; + + char *buf = _copy_from_user_for_proc(buffer, count); + + if (!buf) + return -EINVAL; + + rc = kstrtoint(buf, 10, &dbg_lv); + if (rc < 0) + cpufreq_err("echo dbg_lv (dec) > /proc/cpufreq/cpufreq_debug\n"); + else + func_lv_mask = dbg_lv; + + free_page((unsigned long)buf); + return count; +} + +static int cpufreq_power_mode_proc_show(struct seq_file *m, void *v) +{ + switch (dvfs_power_mode) { + case Default: + seq_puts(m, "Default\n"); + break; + case Low_power_Mode: + seq_puts(m, "Low_power_Mode\n"); + break; + case Just_Make_Mode: + seq_puts(m, "Just_Make_Mode\n"); + break; + case Performance_Mode: + seq_puts(m, "Performance_Mode\n"); + break; + }; + + return 0; +} + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +int mt_cpufreq_get_chip_id_38(void) +{ + unsigned int chip_code = get_devinfo_with_index(21) & 0xFF; + + if (chip_code == 0x43 || chip_code == 0x4B) + return 1; + else + return 0; +} +#else +int mt_cpufreq_get_chip_id_38(void) +{ + return 0; +} +#endif + +int mt_cpufreq_get_ppb_state(void) +{ + return dvfs_power_mode; +} + +static ssize_t cpufreq_power_mode_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) +{ + unsigned int do_power_mode; + + char *buf = _copy_from_user_for_proc(buffer, count); + + if (!buf) + return -EINVAL; + + if (!kstrtoint(buf, 10, &do_power_mode)) + dvfs_power_mode = do_power_mode; + else + cpufreq_err("echo 0/1/2/3 > /proc/cpufreq/cpufreq_power_mode\n"); + + free_page((unsigned long)buf); + return count; +} + +static int cpufreq_stress_test_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%d\n", do_dvfs_stress_test); + + return 0; +} + +static ssize_t cpufreq_stress_test_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + unsigned int do_stress; + int rc; + char *buf = _copy_from_user_for_proc(buffer, count); + + if (!buf) + return -EINVAL; + rc = kstrtoint(buf, 10, &do_stress); + if (rc < 0) + cpufreq_err("echo 0/1 > /proc/cpufreq/cpufreq_stress_test\n"); + else + do_dvfs_stress_test = do_stress; + + free_page((unsigned long)buf); + return count; +} + +#ifdef CONFIG_HYBRID_CPU_DVFS +static int enable_cpuhvfs_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%u\n", enable_cpuhvfs); + + return 0; +} + +static ssize_t enable_cpuhvfs_proc_write(struct file *file, const char __user *ubuf, size_t count, + loff_t *ppos) +{ + int r, i; + unsigned int val; + unsigned long flags; + struct init_sta sta; + struct mt_cpu_dvfs *p; + + r = kstrtouint_from_user(ubuf, count, 0, &val); + if (r) + return -EINVAL; + + cpufreq_lock(flags); + if (!val && enable_cpuhvfs) { + r = cpuhvfs_stop_dvfsp_running(); + if (!r) { + for_each_cpu_dvfs(i, p) { + p->ops->set_cur_freq = set_cur_freq; + p->ops->set_cur_volt = set_cur_volt_extbuck; + p->ops->get_cur_volt = get_cur_volt_extbuck; + } + enable_cpuhvfs = 0; + } + } else if (val && !enable_cpuhvfs) { + __set_cpuhvfs_init_sta(&sta); + + r = cpuhvfs_restart_dvfsp_running(&sta); + if (!r) { + for_each_cpu_dvfs(i, p) { + p->ops->set_cur_freq = set_cur_freq_hybrid; + p->ops->set_cur_volt = set_cur_volt_hybrid; + if (val == 1) + p->ops->get_cur_volt = get_cur_volt_hybrid; + } + enable_cpuhvfs = (val == 1 ? val : 2); + } + } + cpufreq_unlock(flags); + + return count; +} +#endif + +/* cpufreq_ptpod_freq_volt */ +static int cpufreq_ptpod_freq_volt_proc_show(struct seq_file *m, void *v) +{ + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)m->private; + int j; + + for (j = 0; j < p->nr_opp_tbl; j++) { + seq_printf(m, + "[%d] = { .cpufreq_khz = %d,\t.cpufreq_volt = %d,\t.cpufreq_volt_org = %d, },\n", + j, p->opp_tbl[j].cpufreq_khz, p->opp_tbl[j].cpufreq_volt, + p->opp_tbl[j].cpufreq_volt_org); + } + + return 0; +} + +/* cpufreq_oppidx */ +static int cpufreq_oppidx_proc_show(struct seq_file *m, void *v) +{ + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)m->private; + int j; + + seq_printf(m, "[%s/%d]\n" "cpufreq_oppidx = %d\n", p->name, p->cpu_id, p->idx_opp_tbl); + + for (j = 0; j < p->nr_opp_tbl; j++) { + seq_printf(m, "\tOP(%d, %d),\n", + cpu_dvfs_get_freq_by_idx(p, j), cpu_dvfs_get_volt_by_idx(p, j) + ); + } + + return 0; +} + +static ssize_t cpufreq_oppidx_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) +{ + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)PDE_DATA(file_inode(file)); + int oppidx; + int rc; + + char *buf = _copy_from_user_for_proc(buffer, count); + + if (!buf) + return -EINVAL; + + BUG_ON(NULL == p); + rc = kstrtoint(buf, 10, &oppidx); + if (rc < 0) { + p->dvfs_disable_by_procfs = false; + cpufreq_err("echo oppidx > /proc/cpufreq/cpufreq_oppidx (0 <= %d < %d)\n", oppidx, + p->nr_opp_tbl); + } else { + if (0 <= oppidx && oppidx < p->nr_opp_tbl) { + p->dvfs_disable_by_procfs = true; + /* _mt_cpufreq_set(cpu_dvfs_is(p, MT_CPU_DVFS_LITTLE) ? MT_CPU_DVFS_LITTLE : + MT_CPU_DVFS_BIG, oppidx); */ + +#ifdef __TRIAL_RUN__ + rc = cpuhvfs_set_target_opp(cpu_dvfs_to_cluster(p), oppidx, NULL); + BUG_ON(rc); +#endif + } else { + p->dvfs_disable_by_procfs = false; + cpufreq_err("echo oppidx > /proc/cpufreq/cpufreq_oppidx (0 <= %d < %d)\n", oppidx, + p->nr_opp_tbl); + } + } + + free_page((unsigned long)buf); + + return count; +} + +/* cpufreq_freq */ +static int cpufreq_freq_proc_show(struct seq_file *m, void *v) +{ + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)m->private; + + seq_printf(m, "%d KHz\n", p->ops->get_cur_phy_freq(p)); + + return 0; +} + +static ssize_t cpufreq_freq_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) +{ + unsigned long flags; + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)PDE_DATA(file_inode(file)); + unsigned int cur_freq; + int freq, i, found; + int rc; + + char *buf = _copy_from_user_for_proc(buffer, count); + + if (!buf) + return -EINVAL; + + BUG_ON(NULL == p); + rc = kstrtoint(buf, 10, &freq); + if (rc < 0) { + p->dvfs_disable_by_procfs = false; + cpufreq_err("echo khz > /proc/cpufreq/cpufreq_freq\n"); + } else { + if (freq < CPUFREQ_LAST_FREQ_LEVEL) { + if (freq != 0) + cpufreq_err("frequency should higher than %dKHz!\n", + CPUFREQ_LAST_FREQ_LEVEL); + + p->dvfs_disable_by_procfs = false; + goto end; + } else { + for (i = 0; i < p->nr_opp_tbl; i++) { + if (freq == p->opp_tbl[i].cpufreq_khz) { + found = 1; + break; + } + } + + if (found == 1) { + p->dvfs_disable_by_procfs = true; + cpufreq_lock(flags); + cur_freq = p->ops->get_cur_phy_freq(p); + + if (freq != cur_freq) { + p->ops->set_cur_freq(p, cur_freq, freq); + p->idx_opp_tbl = i; + } +#ifndef DISABLE_PBM_FEATURE + if (!p->dvfs_disable_by_suspend) + _kick_PBM_by_cpu(p); +#endif + cpufreq_unlock(flags); + } else { + p->dvfs_disable_by_procfs = false; + cpufreq_err("frequency %dKHz! is not found in CPU opp table\n", + freq); + } + } + } + +end: + free_page((unsigned long)buf); + + return count; +} + +/* cpufreq_volt */ +static int cpufreq_volt_proc_show(struct seq_file *m, void *v) +{ + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)m->private; + unsigned long flags; + + cpufreq_lock(flags); + + seq_printf(m, "Vproc: %d mv\n", p->ops->get_cur_volt(p) / 100); /* mv */ + seq_printf(m, "Vsram: %d mv\n", get_cur_vsram(p) / 100); /* mv */ + + cpufreq_unlock(flags); + + return 0; +} + +static ssize_t cpufreq_volt_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) +{ + unsigned long flags; + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)PDE_DATA(file_inode(file)); + int mv; + int rc; + + char *buf = _copy_from_user_for_proc(buffer, count); + + if (!buf) + return -EINVAL; + rc = kstrtoint(buf, 10, &mv); + if (rc < 0) { + p->dvfs_disable_by_procfs = false; + cpufreq_err("echo mv > /proc/cpufreq/cpufreq_volt\n"); + } else { + p->dvfs_disable_by_procfs = true; + cpufreq_lock(flags); + _set_cur_volt_locked(p, mv * 100); + cpufreq_unlock(flags); + } + + free_page((unsigned long)buf); + + return count; +} + +/* cpufreq_turbo_mode */ +static int cpufreq_turbo_mode_proc_show(struct seq_file *m, void *v) +{ + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)m->private; + + seq_printf(m, "turbo_mode = %d\n", p->turbo_mode); + + return 0; +} + +static ssize_t cpufreq_turbo_mode_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) +{ + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)PDE_DATA(file_inode(file)); + unsigned int turbo_mode; + int rc; + + char *buf = _copy_from_user_for_proc(buffer, count); + + if (!buf) + return -EINVAL; + rc = kstrtoint(buf, 10, &turbo_mode); + if (rc < 0) + cpufreq_err("echo 0/1 > /proc/cpufreq/%s/cpufreq_turbo_mode\n", p->name); + else + p->turbo_mode = turbo_mode; + + free_page((unsigned long)buf); + + return count; +} + +/* cpufreq_time_profile */ +static int cpufreq_dvfs_time_profile_proc_show(struct seq_file *m, void *v) +{ + int i; + + for (i = 0; i < NR_SET_V_F; i++) + seq_printf(m, "max[%d] = %lld us\n", i, ktime_to_us(max[i])); + + seq_printf(m, "voltage fail case = %d\n", fail_case); + seq_printf(m, "fail times= %d\n", fail_times); + return 0; +} + +static ssize_t cpufreq_dvfs_time_profile_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + struct mt_cpu_dvfs *p = (struct mt_cpu_dvfs *)PDE_DATA(file_inode(file)); + unsigned int temp; + int rc; + int i; + + char *buf = _copy_from_user_for_proc(buffer, count); + + if (!buf) + return -EINVAL; + + rc = kstrtoint(buf, 10, &temp); + if (rc < 0) + cpufreq_err("echo 0/1 > /proc/cpufreq/%s/cpufreq_dvfs_time_profile\n", p->name); + else { + if (temp == 1) { + for (i = 0; i < NR_SET_V_F; i++) + max[i].tv64 = 0; + } + fail_times = 0; + fail_case = 0; + } + free_page((unsigned long)buf); + + return count; +} + +#define PROC_FOPS_RW(name) \ + static int name ## _proc_open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, name ## _proc_show, PDE_DATA(inode)); \ +} \ +static const struct file_operations name ## _proc_fops = { \ + .owner = THIS_MODULE, \ + .open = name ## _proc_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + .write = name ## _proc_write, \ +} + +#define PROC_FOPS_RO(name) \ + static int name ## _proc_open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, name ## _proc_show, PDE_DATA(inode)); \ +} \ +static const struct file_operations name ## _proc_fops = { \ + .owner = THIS_MODULE, \ + .open = name ## _proc_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + +#define PROC_ENTRY(name) {__stringify(name), &name ## _proc_fops} + +PROC_FOPS_RW(cpufreq_debug); +PROC_FOPS_RW(cpufreq_stress_test); +PROC_FOPS_RW(cpufreq_power_mode); +#ifdef CONFIG_HYBRID_CPU_DVFS +PROC_FOPS_RW(enable_cpuhvfs); +#endif +PROC_FOPS_RO(cpufreq_ptpod_freq_volt); +PROC_FOPS_RW(cpufreq_oppidx); +PROC_FOPS_RW(cpufreq_freq); +PROC_FOPS_RW(cpufreq_volt); +PROC_FOPS_RW(cpufreq_turbo_mode); +PROC_FOPS_RW(cpufreq_dvfs_time_profile); + +static int _create_procfs(void) +{ + struct proc_dir_entry *dir = NULL; + struct proc_dir_entry *cpu_dir = NULL; + struct mt_cpu_dvfs *p = id_to_cpu_dvfs(0); + int i, j; + + struct pentry { + const char *name; + const struct file_operations *fops; + }; + + const struct pentry entries[] = { + PROC_ENTRY(cpufreq_debug), + PROC_ENTRY(cpufreq_stress_test), + PROC_ENTRY(cpufreq_power_mode), +#ifdef CONFIG_HYBRID_CPU_DVFS + PROC_ENTRY(enable_cpuhvfs), +#endif + }; + + const struct pentry cpu_entries[] = { + PROC_ENTRY(cpufreq_oppidx), + PROC_ENTRY(cpufreq_freq), + PROC_ENTRY(cpufreq_volt), + PROC_ENTRY(cpufreq_turbo_mode), + PROC_ENTRY(cpufreq_dvfs_time_profile), + }; + + dir = proc_mkdir("cpufreq", NULL); + + if (!dir) { + cpufreq_err("fail to create /proc/cpufreq @ %s()\n", __func__); + return -ENOMEM; + } + + for (i = 0; i < ARRAY_SIZE(entries); i++) { + if (!proc_create + (entries[i].name, S_IRUGO | S_IWUSR | S_IWGRP, dir, entries[i].fops)) + cpufreq_err("%s(), create /proc/cpufreq/%s failed\n", __func__, + entries[i].name); + } + + for (i = 0; i < ARRAY_SIZE(cpu_entries); i++) { + if (!proc_create_data + (cpu_entries[i].name, S_IRUGO | S_IWUSR | S_IWGRP, dir, cpu_entries[i].fops, p)) + cpufreq_err("%s(), create /proc/cpufreq/%s failed\n", __func__, + cpu_entries[i].name); + } + + for_each_cpu_dvfs(j, p) { + cpu_dir = proc_mkdir(p->name, dir); + + if (!cpu_dir) { + cpufreq_err("fail to create /proc/cpufreq/%s @ %s()\n", p->name, __func__); + return -ENOMEM; + } + + for (i = 0; i < ARRAY_SIZE(cpu_entries); i++) { + if (!proc_create_data + (cpu_entries[i].name, S_IRUGO | S_IWUSR | S_IWGRP, cpu_dir, + cpu_entries[i].fops, p)) + cpufreq_err("%s(), create /proc/cpufreq/%s/%s failed\n", __func__, + p->name, cpu_entries[i].name); + } + } + + return 0; +} +#endif +#ifdef CONFIG_OF +static int mt_cpufreq_dts_map(void) +{ + struct device_node *node; + + /* topckgen */ + node = of_find_compatible_node(NULL, NULL, TOPCKGEN_NODE); + if (!node) { + cpufreq_info("error: cannot find node " TOPCKGEN_NODE); + BUG(); + } + topckgen_base = (unsigned long)of_iomap(node, 0); + if (!topckgen_base) { + cpufreq_info("error: cannot iomap " TOPCKGEN_NODE); + BUG(); + } + + /* infracfg_ao */ + node = of_find_compatible_node(NULL, NULL, INFRACFG_AO_NODE); + if (!node) { + cpufreq_info("error: cannot find node " INFRACFG_AO_NODE); + BUG(); + } + infracfg_ao_base = (unsigned long)of_iomap(node, 0); + if (!infracfg_ao_base) { + cpufreq_info("error: cannot iomap " INFRACFG_AO_NODE); + BUG(); + } + + /* apmixed */ + node = of_find_compatible_node(NULL, NULL, APMIXED_NODE); + if (!node) { + cpufreq_info("error: cannot find node " APMIXED_NODE); + BUG(); + } + apmixed_base = (unsigned long)of_iomap(node, 0); + if (!apmixed_base) { + cpufreq_info("error: cannot iomap " APMIXED_NODE); + BUG(); + } + return 0; +} +#else +static int mt_cpufreq_dts_map(void) +{ + return 0; +} +#endif +/* +* Module driver +*/ +static int __init _mt_cpufreq_pdrv_init(void) +{ + int ret = 0; + struct cpumask cpu_mask; + unsigned int cluster_num; + int i; + + FUNC_ENTER(FUNC_LV_MODULE); + + mt_cpufreq_dts_map(); + debug_vsram = get_cur_vsram(NULL); + debug_vproc = get_cur_volt_extbuck(NULL); + + cluster_num = (unsigned int)arch_get_nr_clusters(); + for (i = 0; i < cluster_num; i++) { + arch_get_cluster_cpus(&cpu_mask, i); + cpu_dvfs[i].cpu_id = cpumask_first(&cpu_mask); + cpufreq_dbg("cluster_id = %d, cluster_cpuid = %d\n", + i, cpu_dvfs[i].cpu_id); + } + +#ifdef CONFIG_HYBRID_CPU_DVFS /* before platform_driver_register */ + ret = cpuhvfs_module_init(); + if (ret) + enable_cpuhvfs = 0; +#endif + +#ifdef CONFIG_PROC_FS + + /* init proc */ + if (_create_procfs()) + goto out; + +#endif + + /* register platform device/driver */ + ret = platform_device_register(&_mt_cpufreq_pdev); + + if (ret) { + cpufreq_err("fail to register cpufreq device @ %s()\n", __func__); + goto out; + } + + ret = platform_driver_register(&_mt_cpufreq_pdrv); + + if (ret) { + cpufreq_err("fail to register cpufreq driver @ %s()\n", __func__); + platform_device_unregister(&_mt_cpufreq_pdev); + } + +out: + FUNC_EXIT(FUNC_LV_MODULE); + + return ret; +} + +static void __exit _mt_cpufreq_pdrv_exit(void) +{ + FUNC_ENTER(FUNC_LV_MODULE); + + platform_driver_unregister(&_mt_cpufreq_pdrv); + platform_device_unregister(&_mt_cpufreq_pdev); + + FUNC_EXIT(FUNC_LV_MODULE); +} + +late_initcall(_mt_cpufreq_pdrv_init); +module_exit(_mt_cpufreq_pdrv_exit); + +MODULE_DESCRIPTION("MediaTek CPU DVFS Driver v0.3"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq.h b/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq.h new file mode 100644 index 0000000000000000000000000000000000000000..21193af7e3cecd925cbf903b7924f1475b1b25e9 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @file mt_cpufreq.h + * @brief CPU DVFS driver interface + */ + +#ifndef __MT_CPUFREQ_H__ +#define __MT_CPUFREQ_H__ + +#ifdef __cplusplus +extern "C" { +#endif +struct mt_cpu_power_tbl { + unsigned int ncpu_big; + unsigned int khz_big; + unsigned int ncpu_little; + unsigned int khz_little; + unsigned int performance; + unsigned int power; +}; + +struct mt_cpu_tlp_power_info { + struct mt_cpu_power_tbl *power_tbl; + unsigned int nr_power_table; +}; + +enum mt_cpu_dvfs_id { + MT_CPU_DVFS_LITTLE, + MT_CPU_DVFS_BIG, + + NR_MT_CPU_DVFS, +}; + +enum top_ckmuxsel { + TOP_CKMUXSEL_CLKSQ = 0, + TOP_CKMUXSEL_ARMPLL = 1, + TOP_CKMUXSEL_MAINPLL = 2, + TOP_CKMUXSEL_UNIVPLL = 3, + + NR_TOP_CKMUXSEL, +}; + +enum top_ckmuxsel_cci { + TOP_CKMUXSEL_CLKSQ_CCI = 0, + TOP_CKMUXSEL_ARMPLL_L = 1, + TOP_CKMUXSEL_ARMPLL_LL = 2, + TOP_CKMUXSEL_CLKSQ_CCI_2 = 3, + + NR_TOP_CKMUXSEL_CCI, +}; + +enum dvfs_time_profile { + SET_DVFS = 0, + SET_FREQ = 1, + SET_VOLT = 2, + SET_VPROC = 3, + SET_VSRAM = 4, + SET_DELAY = 5, + + NR_SET_V_F, +}; + +typedef void (*cpuVoltsampler_func) (enum mt_cpu_dvfs_id, unsigned int mv); + +/* PMIC */ +extern int is_ext_buck_sw_ready(void); +extern int is_ext_buck_exist(void); +extern void mt6311_set_vdvfs11_vosel(unsigned char val); +extern void mt6311_set_vdvfs11_vosel_on(unsigned char val); +extern void mt6311_set_vdvfs11_vosel_ctrl(unsigned char val); +extern unsigned int mt6311_read_byte(unsigned char cmd, unsigned char *returnData); +extern unsigned int mt6311_get_chip_id(void); + +extern u32 get_devinfo_with_index(u32 index); +extern void (*cpufreq_freq_check)(enum mt_cpu_dvfs_id id); + +/* PMIC WRAP */ +#ifdef CONFIG_OF +extern void __iomem *pwrap_base; +#define PWRAP_BASE_ADDR ((unsigned long)pwrap_base) +#endif + +/* #ifdef CONFIG_CPU_DVFS_AEE_RR_REC */ +#if 1 +/* SRAM debugging*/ +extern void aee_rr_rec_cpu_dvfs_vproc_big(u8 val); +extern void aee_rr_rec_cpu_dvfs_vproc_little(u8 val); +extern void aee_rr_rec_cpu_dvfs_oppidx(u8 val); +extern u8 aee_rr_curr_cpu_dvfs_oppidx(void); +extern void aee_rr_rec_cpu_dvfs_status(u8 val); +extern u8 aee_rr_curr_cpu_dvfs_status(void); +#endif + +/* PTP-OD */ +extern unsigned int mt_cpufreq_get_freq_by_idx(enum mt_cpu_dvfs_id id, int idx); +extern int mt_cpufreq_update_volt(enum mt_cpu_dvfs_id id, unsigned int *volt_tbl, + int nr_volt_tbl); +extern void mt_cpufreq_restore_default_volt(enum mt_cpu_dvfs_id id); +extern unsigned int mt_cpufreq_get_cur_volt(enum mt_cpu_dvfs_id id); +typedef void (*mt_cpufreq_set_ptbl_funcPTP)(enum mt_cpu_dvfs_id id, int restore); +extern void mt_cpufreq_set_ptbl_registerCB(mt_cpufreq_set_ptbl_funcPTP pCB); + +/* Thermal */ +extern void mt_cpufreq_thermal_protect(unsigned int limited_power); + +/* PBM */ +extern unsigned int mt_cpufreq_get_leakage_mw(enum mt_cpu_dvfs_id id); +extern unsigned int mt_cpufreq_get_cur_phy_freq(enum mt_cpu_dvfs_id id); +extern unsigned int mt_cpufreq_get_cur_phy_volt(enum mt_cpu_dvfs_id id); + +/* PPB */ +extern int mt_cpufreq_get_ppb_state(void); + +/* L hispeed */ +extern int mt_cpufreq_get_chip_id_38(void); + +/* DCM */ +extern int sync_dcm_set_cci_freq(unsigned int cci_hz); +extern int sync_dcm_set_mp0_freq(unsigned int mp0_hz); +extern int sync_dcm_set_mp1_freq(unsigned int mp1_hz); + +/* Generic */ +extern int mt_cpufreq_state_set(int enabled); +extern int mt_cpufreq_clock_switch(enum mt_cpu_dvfs_id id, enum top_ckmuxsel sel); +extern enum top_ckmuxsel mt_cpufreq_get_clock_switch(enum mt_cpu_dvfs_id id); +extern void mt_cpufreq_setvolt_registerCB(cpuVoltsampler_func pCB); +extern bool mt_cpufreq_earlysuspend_status_get(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq_hybrid.c b/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq_hybrid.c new file mode 100644 index 0000000000000000000000000000000000000000..305ac31d9891ab9c5ab3367b1fb55fa2157119d5 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq_hybrid.c @@ -0,0 +1,1759 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "mt_cpufreq_hybrid.h" + + +/************************************** + * [Hybrid DVFS] Config + **************************************/ + + +/************************************** + * [CPU SPM] Parameter + **************************************/ +#define CSRAM_BASE 0x0011c000 +#define CSRAM_SIZE 0xf80 /* 3968 bytes */ + +#define OFFS_DATA_S 0x260 +#define OFFS_WDT_LATCH0 0x264 +#define OFFS_WDT_LATCH1 0x268 +#define OFFS_WDT_LATCH2 0x26c +#define OFFS_TIMER_OUT1 0x270 +#define OFFS_TIMER_OUT2 0x274 +#define OFFS_PCM_PC1 0x278 +#define OFFS_PCM_PC2 0x27c +#define OFFS_FW_RSV5 0x280 +#define OFFS_FW_RSV3 0x284 +#define OFFS_FW_RSV4 0x288 +#define OFFS_FW_RSV2 0x28c +#define OFFS_PAUSE_TIME 0x290 +#define OFFS_UNPAUSE_TIME 0x294 +#define OFFS_INIT_OPP 0x2b0 +#define OFFS_INIT_FREQ 0x2c0 +#define OFFS_INIT_VOLT 0x2d0 +#define OFFS_SW_RSV4 0x2e0 +#define OFFS_PAUSE_SRC 0x2e4 +#define OFFS_DVFS_WAIT 0x2e8 +#define OFFS_FUNC_ENTER 0x2ec +#define OFFS_LOG_S 0x340 +#define OFFS_LOG_E 0xf70 + +#define DVFS_TIMEOUT 6000 /* us */ +#define SEMA_GET_TIMEOUT 2000 /* us */ +#define PAUSE_TIMEOUT 2000 /* us */ + + +/************************************** + * [Hybrid DVFS] Parameter + **************************************/ +#define ENTRY_EACH_LOG 3 + + +/************************************** + * [CPU SPM] Definition + **************************************/ +#define CSPM_BASE cspm_base /* map 0x10227000 */ + +#define CSPM_POWERON_CONFIG_EN (CSPM_BASE + 0x000) +#define CSPM_POWER_ON_VAL0 (CSPM_BASE + 0x004) +#define CSPM_POWER_ON_VAL1 (CSPM_BASE + 0x008) +#define CSPM_CLK_CON (CSPM_BASE + 0x00c) +#define CSPM_CLK_SETTLE (CSPM_BASE + 0x010) +#define CSPM_AP_STANDBY_CON (CSPM_BASE + 0x014) +#define CSPM_PCM_CON0 (CSPM_BASE + 0x018) +#define CSPM_PCM_CON1 (CSPM_BASE + 0x01c) +#define CSPM_PCM_IM_PTR (CSPM_BASE + 0x020) +#define CSPM_PCM_IM_LEN (CSPM_BASE + 0x024) +#define CSPM_PCM_REG_DATA_INI (CSPM_BASE + 0x028) +#define CSPM_PCM_PWR_IO_EN (CSPM_BASE + 0x02c) +#define CSPM_PCM_TIMER_VAL (CSPM_BASE + 0x030) +#define CSPM_PCM_WDT_VAL (CSPM_BASE + 0x034) +#define CSPM_PCM_IM_HOST_RW_PTR (CSPM_BASE + 0x038) +#define CSPM_PCM_IM_HOST_RW_DAT (CSPM_BASE + 0x03c) +#define CSPM_PCM_EVENT_VECTOR0 (CSPM_BASE + 0x040) +#define CSPM_PCM_EVENT_VECTOR1 (CSPM_BASE + 0x044) +#define CSPM_PCM_EVENT_VECTOR2 (CSPM_BASE + 0x048) +#define CSPM_PCM_EVENT_VECTOR3 (CSPM_BASE + 0x04c) +#define CSPM_PCM_EVENT_VECTOR4 (CSPM_BASE + 0x050) +#define CSPM_PCM_EVENT_VECTOR5 (CSPM_BASE + 0x054) +#define CSPM_PCM_EVENT_VECTOR6 (CSPM_BASE + 0x058) +#define CSPM_PCM_EVENT_VECTOR7 (CSPM_BASE + 0x05c) +#define CSPM_PCM_EVENT_VECTOR8 (CSPM_BASE + 0x060) +#define CSPM_PCM_EVENT_VECTOR9 (CSPM_BASE + 0x064) +#define CSPM_PCM_EVENT_VECTOR10 (CSPM_BASE + 0x068) +#define CSPM_PCM_EVENT_VECTOR11 (CSPM_BASE + 0x06c) +#define CSPM_PCM_EVENT_VECTOR12 (CSPM_BASE + 0x070) +#define CSPM_PCM_EVENT_VECTOR13 (CSPM_BASE + 0x074) +#define CSPM_PCM_EVENT_VECTOR14 (CSPM_BASE + 0x078) +#define CSPM_PCM_EVENT_VECTOR15 (CSPM_BASE + 0x07c) +#define CSPM_PCM_EVENT_VECTOR_EN (CSPM_BASE + 0x080) +#define CSPM_SW_INT_SET (CSPM_BASE + 0x090) +#define CSPM_SW_INT_CLEAR (CSPM_BASE + 0x094) +#define CSPM_SCP_MAILBOX (CSPM_BASE + 0x098) +#define CSPM_SCP_IRQ (CSPM_BASE + 0x09c) +#define CSPM_TWAM_CON (CSPM_BASE + 0x0a0) +#define CSPM_TWAM_WINDOW_LEN (CSPM_BASE + 0x0a4) +#define CSPM_TWAM_IDLE_SEL (CSPM_BASE + 0x0a8) +#define CSPM_TWAM_CON1 (CSPM_BASE + 0x0ac) +#define CSPM_CPU_WAKEUP_EVENT (CSPM_BASE + 0x0b0) +#define CSPM_IRQ_MASK (CSPM_BASE + 0x0b4) +#define CSPM_SRC_REQ (CSPM_BASE + 0x0b8) +#define CSPM_SRC_MASK (CSPM_BASE + 0x0bc) +#define CSPM_SRC2_MASK (CSPM_BASE + 0x0c0) +#define CSPM_WAKEUP_EVENT_MASK (CSPM_BASE + 0x0c4) +#define CSPM_WAKEUP_EVENT_EXT_MASK (CSPM_BASE + 0x0c8) +#define CSPM_SCP_CLK_CON (CSPM_BASE + 0x0d0) +#define CSPM_PCM_DEBUG_CON (CSPM_BASE + 0x0d4) +#define CSPM_PCM_REG0_DATA (CSPM_BASE + 0x100) +#define CSPM_PCM_REG1_DATA (CSPM_BASE + 0x104) +#define CSPM_PCM_REG2_DATA (CSPM_BASE + 0x108) +#define CSPM_PCM_REG3_DATA (CSPM_BASE + 0x10c) +#define CSPM_PCM_REG4_DATA (CSPM_BASE + 0x110) +#define CSPM_PCM_REG5_DATA (CSPM_BASE + 0x114) +#define CSPM_PCM_REG6_DATA (CSPM_BASE + 0x118) +#define CSPM_PCM_REG7_DATA (CSPM_BASE + 0x11c) +#define CSPM_PCM_REG8_DATA (CSPM_BASE + 0x120) +#define CSPM_PCM_REG9_DATA (CSPM_BASE + 0x124) +#define CSPM_PCM_REG10_DATA (CSPM_BASE + 0x128) +#define CSPM_PCM_REG11_DATA (CSPM_BASE + 0x12c) +#define CSPM_PCM_REG12_DATA (CSPM_BASE + 0x130) +#define CSPM_PCM_REG13_DATA (CSPM_BASE + 0x134) +#define CSPM_PCM_REG14_DATA (CSPM_BASE + 0x138) +#define CSPM_PCM_REG15_DATA (CSPM_BASE + 0x13c) +#define CSPM_PCM_REG12_MASK_B_STA (CSPM_BASE + 0x140) +#define CSPM_PCM_REG12_EXT_DATA (CSPM_BASE + 0x144) +#define CSPM_PCM_REG12_EXT_MASK_B_STA (CSPM_BASE + 0x148) +#define CSPM_PCM_EVENT_REG_STA (CSPM_BASE + 0x14c) +#define CSPM_PCM_TIMER_OUT (CSPM_BASE + 0x150) +#define CSPM_PCM_WDT_OUT (CSPM_BASE + 0x154) +#define CSPM_IRQ_STA (CSPM_BASE + 0x158) +#define CSPM_WAKEUP_STA (CSPM_BASE + 0x15c) +#define CSPM_WAKEUP_EXT_STA (CSPM_BASE + 0x160) +#define CSPM_WAKEUP_MISC (CSPM_BASE + 0x164) +#define CSPM_BUS_PROTECT_RDY (CSPM_BASE + 0x168) +#define CSPM_BUS_PROTECT2_RDY (CSPM_BASE + 0x16c) +#define CSPM_SUBSYS_IDLE_STA (CSPM_BASE + 0x170) +#define CSPM_CPU_IDLE_STA (CSPM_BASE + 0x174) +#define CSPM_PCM_FSM_STA (CSPM_BASE + 0x178) +#define CSPM_PCM_WDT_LATCH0 (CSPM_BASE + 0x190) +#define CSPM_PCM_WDT_LATCH1 (CSPM_BASE + 0x194) +#define CSPM_PCM_WDT_LATCH2 (CSPM_BASE + 0x198) +#define CSPM_DRAMC_DBG_LATCH (CSPM_BASE + 0x19c) +#define CSPM_TWAM_LAST_STA0 (CSPM_BASE + 0x1a0) +#define CSPM_TWAM_LAST_STA1 (CSPM_BASE + 0x1a4) +#define CSPM_TWAM_LAST_STA2 (CSPM_BASE + 0x1a8) +#define CSPM_TWAM_LAST_STA3 (CSPM_BASE + 0x1ac) +#define CSPM_TWAM_LAST_STA4 (CSPM_BASE + 0x1b0) +#define CSPM_TWAM_LAST_STA5 (CSPM_BASE + 0x1b4) +#define CSPM_TWAM_LAST_STA6 (CSPM_BASE + 0x1b8) +#define CSPM_TWAM_LAST_STA7 (CSPM_BASE + 0x1bc) +#define CSPM_TWAM_CURR_STA0 (CSPM_BASE + 0x1c0) +#define CSPM_TWAM_CURR_STA1 (CSPM_BASE + 0x1c4) +#define CSPM_TWAM_CURR_STA2 (CSPM_BASE + 0x1c8) +#define CSPM_TWAM_CURR_STA3 (CSPM_BASE + 0x1cc) +#define CSPM_TWAM_CURR_STA4 (CSPM_BASE + 0x1d0) +#define CSPM_TWAM_CURR_STA5 (CSPM_BASE + 0x1d4) +#define CSPM_TWAM_CURR_STA6 (CSPM_BASE + 0x1d8) +#define CSPM_TWAM_CURR_STA7 (CSPM_BASE + 0x1dc) +#define CSPM_TWAM_TIMER_OUT (CSPM_BASE + 0x1e0) +#define CSPM_DVFS_CON (CSPM_BASE + 0x400) +#define CSPM_MDBSI_CON (CSPM_BASE + 0x404) +#define CSPM_BSI_GEN (CSPM_BASE + 0x410) +#define CSPM_BSI_EN_SR (CSPM_BASE + 0x414) +#define CSPM_BSI_CLK_SR (CSPM_BASE + 0x418) +#define CSPM_BSI_D0_SR (CSPM_BASE + 0x41c) +#define CSPM_BSI_D1_SR (CSPM_BASE + 0x420) +#define CSPM_BSI_D2_SR (CSPM_BASE + 0x424) +#define CSPM_AP_SEMA (CSPM_BASE + 0x428) +#define CSPM_SPM_SEMA (CSPM_BASE + 0x42c) +#define CSPM_MP0_CPU0_WFI_EN (CSPM_BASE + 0x530) +#define CSPM_MP0_CPU1_WFI_EN (CSPM_BASE + 0x534) +#define CSPM_MP0_CPU2_WFI_EN (CSPM_BASE + 0x538) +#define CSPM_MP0_CPU3_WFI_EN (CSPM_BASE + 0x53c) +#define CSPM_MP1_CPU0_WFI_EN (CSPM_BASE + 0x540) +#define CSPM_MP1_CPU1_WFI_EN (CSPM_BASE + 0x544) +#define CSPM_MP1_CPU2_WFI_EN (CSPM_BASE + 0x548) +#define CSPM_MP1_CPU3_WFI_EN (CSPM_BASE + 0x54c) +#define CSPM_SW_FLAG (CSPM_BASE + 0x600) +#define CSPM_SW_DEBUG (CSPM_BASE + 0x604) +#define CSPM_SW_RSV0 (CSPM_BASE + 0x608) +#define CSPM_SW_RSV1 (CSPM_BASE + 0x60c) +#define CSPM_SW_RSV2 (CSPM_BASE + 0x610) +#define CSPM_SW_RSV3 (CSPM_BASE + 0x614) +#define CSPM_SW_RSV4 (CSPM_BASE + 0x618) +#define CSPM_SW_RSV5 (CSPM_BASE + 0x61c) +#define CSPM_RSV_CON (CSPM_BASE + 0x620) +#define CSPM_RSV_STA (CSPM_BASE + 0x624) + +#define POWER_ON_VAL1_DEF 0x20 /* PCM clock is 26M */ + +#define PCM_FSM_STA_DEF 0x48490 + +#define PROJECT_CODE 0xb16 + +#define REGWR_EN (1U << 0) +#define REGWR_CFG_KEY (PROJECT_CODE << 16) + +#define CON0_PCM_KICK (1U << 0) +#define CON0_IM_KICK (1U << 1) +#define CON0_PCM_CK_EN (1U << 2) +#define CON0_PCM_SW_RESET (1U << 15) +#define CON0_CFG_KEY (PROJECT_CODE << 16) + +#define CON1_IM_SLAVE (1U << 0) +#define CON1_MIF_APBEN (1U << 3) +#define CON1_PCM_TIMER_EN (1U << 5) +#define CON1_IM_NONRP_EN (1U << 6) +#define CON1_PCM_WDT_EN (1U << 8) +#define CON1_PCM_WDT_WAKE_MODE (1U << 9) +#define CON1_SPM_SRAM_SLP_B (1U << 10) +#define CON1_SPM_SRAM_ISO_B (1U << 11) +#define CON1_EVENT_LOCK_EN (1U << 12) +#define CON1_CFG_KEY (PROJECT_CODE << 16) + +#define PCM_PWRIO_EN_R7 (1U << 7) +#define PCM_RF_SYNC_R0 (1U << 16) +#define PCM_RF_SYNC_R1 (1U << 17) +#define PCM_RF_SYNC_R7 (1U << 23) + +#define PCM_SW_INT0 (1U << 0) +#define PCM_SW_INT1 (1U << 1) +#define PCM_SW_INT_ALL (PCM_SW_INT1 | PCM_SW_INT0) + +#define TMT_RISING 0 +#define TMT_FALLING 1 +#define TMT_HIGH_LEVEL 2 +#define TMT_LOW_LEVEL 3 + +#define TWAM_ENABLE (1U << 0) +#define TWAM_SPEED_MODE_EN (1U << 1) +#define TWAM_SW_RST (1U << 2) +#define TWAM_MON_TYPE0(val) (((val) & 0x3) << 4) +#define TWAM_MON_TYPE1(val) (((val) & 0x3) << 6) +#define TWAM_MON_TYPE2(val) (((val) & 0x3) << 8) +#define TWAM_MON_TYPE3(val) (((val) & 0x3) << 10) +#define TWAM_SIG_SEL0(val) (((val) & 0x1f) << 12) +#define TWAM_SIG_SEL1(val) (((val) & 0x1f) << 17) +#define TWAM_SIG_SEL2(val) (((val) & 0x1f) << 22) +#define TWAM_SIG_SEL3(val) (((val) & 0x1f) << 27) + +#define IRQM_TWAM (1U << 2) +#define IRQM_PCM_RETURN (1U << 3) +#define IRQM_RET_IRQ0 (1U << 8) +#define IRQM_RET_IRQ1 (1U << 9) + +#define IRQM_RET_IRQ_SEC (IRQM_RET_IRQ1) +#define IRQM_ALL_EXC_RET0 (IRQM_RET_IRQ_SEC | IRQM_TWAM) +#define IRQM_ALL (IRQM_ALL_EXC_RET0 | IRQM_RET_IRQ0 | IRQM_PCM_RETURN) + +#define WAKE_SRC_CPU (1U << 0) +#define WAKE_SRC_TWAM (1U << 1) + +#define R7_PCM_TIMER_SET (1U << 9) + +#define IRQS_TWAM (1U << 2) +#define IRQS_PCM_RETURN (1U << 3) +#define IRQS_SW_INT0 (1U << 4) +#define IRQS_SW_INT1 (1U << 5) + +#define IRQC_TWAM IRQS_TWAM +#define IRQC_PCM_RETURN IRQS_PCM_RETURN +#define IRQC_ALL (IRQC_PCM_RETURN | IRQC_TWAM) + +#define FSM_PC_STA_IDLE (1U << 4) +#define FSM_PC_STA_INC (1U << 5) +#define FSM_PC_STA_STALL (1U << 6) +#define FSM_PCM_KICK (1U << 21) + +#define SW_L_F_MIN(val) (((val) & 0xf) << 0) +#define SW_L_F_MAX(val) (((val) & 0xf) << 4) +#define SW_L_F_DES(val) (((val) & 0xf) << 8) +#define SW_L_F_ASSIGN (1U << 12) +#define SW_L_PAUSE (1U << 13) +#define L_CLUSTER_EN (1U << 14) +#define BYPASS_FIT (1U << 15) +#define SW_B_F_MIN(val) (((val) & 0xf) << 16) +#define SW_B_F_MAX(val) (((val) & 0xf) << 20) +#define SW_B_F_DES(val) (((val) & 0xf) << 24) +#define SW_B_F_ASSIGN (1U << 28) +#define SW_B_PAUSE (1U << 29) +#define B_CLUSTER_EN (1U << 30) + +#define SW_L_F_MIN_MASK (0xf << 0) +#define SW_L_F_MAX_MASK (0xf << 4) +#define SW_L_F_DES_MASK (0xf << 8) +#define SW_B_F_MIN_MASK (0xf << 16) +#define SW_B_F_MAX_MASK (0xf << 20) +#define SW_B_F_DES_MASK (0xf << 24) +#define SW_ALL_PAUSE (SW_B_PAUSE | SW_L_PAUSE) + +#define L_F_CURR(val) (((val) & 0xf) << 0) +#define L_F_DES(val) (((val) & 0xf) << 4) +#define L_V_CURR(val) (((val) & 0x7f) << 8) +#define FW_L_DONE (1U << 15) +#define B_F_CURR(val) (((val) & 0xf) << 16) +#define B_F_DES(val) (((val) & 0xf) << 20) +#define B_V_CURR(val) (((val) & 0x7f) << 24) +#define FW_B_DONE (1U << 31) + +#define L_F_CURR_MASK (0xf << 0) +#define L_F_DES_MASK (0xf << 4) +#define L_V_CURR_MASK (0x7f << 8) +#define B_F_CURR_MASK (0xf << 16) +#define B_F_DES_MASK (0xf << 20) +#define B_V_CURR_MASK (0x7f << 24) +#define FW_ALL_DONE (FW_B_DONE | FW_L_DONE) + +/* pause source flag */ +#define PSF_PAUSE_INIT (1U << PAUSE_INIT) +#define PSF_PAUSE_I2CDRV (1U << PAUSE_I2CDRV) +#define PSF_PAUSE_IDLE (1U << PAUSE_IDLE) +#define PSF_PAUSE_SUSPEND (1U << PAUSE_SUSPEND) + +/* debug log flag */ +#define DLF_KICK (1U << 0) +#define DLF_CLUSTER (1U << 1) +#define DLF_DVFS (1U << 2) +#define DLF_SEMA (1U << 3) +#define DLF_PAUSE (1U << 4) +#define DLF_STOP (1U << 5) + +/* function enter flag */ +#define FEF_DVFS (1U << 0) +#define FEF_CLUSTER_OFF (1U << 1) + +struct pcm_desc; + +struct pwr_ctrl { + u8 twam_wfi_init; + u8 r7_ctrl_en; + + u32 wake_src; +}; + + +/************************************** + * [Hybrid DVFS] Definition + **************************************/ +#define DBG_REPO_S CSRAM_BASE +#define DBG_REPO_E (DBG_REPO_S + CSRAM_SIZE) +#define DBG_REPO_DATA_S (DBG_REPO_S + OFFS_DATA_S) +#define DBG_REPO_DATA_E (DBG_REPO_S + OFFS_LOG_S) +#define DBG_REPO_LOG_S (DBG_REPO_S + OFFS_LOG_S) +#define DBG_REPO_LOG_E (DBG_REPO_S + OFFS_LOG_E) + +#define DBG_REPO_SIZE (DBG_REPO_E - DBG_REPO_S) +#define DBG_REPO_NUM (DBG_REPO_SIZE / sizeof(u32)) + +#define REPO_I_DATA_S (OFFS_DATA_S / sizeof(u32)) +#define REPO_I_WDT_LATCH0 (OFFS_WDT_LATCH0 / sizeof(u32)) +#define REPO_I_WDT_LATCH1 (OFFS_WDT_LATCH1 / sizeof(u32)) +#define REPO_I_WDT_LATCH2 (OFFS_WDT_LATCH2 / sizeof(u32)) +#define REPO_I_LOG_S (OFFS_LOG_S / sizeof(u32)) + +#define REPO_GUARD0 0x55aa55aa +#define REPO_GUARD1 0xaa55aa55 + +struct cpuhvfs_dvfsp { + struct pcm_desc *pcmdesc; + struct pwr_ctrl *pwrctrl; + + void __iomem *log_repo; + + u32 init_done; /* for dvfsp and log_repo */ + + int (*init_dvfsp)(struct cpuhvfs_dvfsp *dvfsp); + int (*kick_dvfsp)(struct cpuhvfs_dvfsp *dvfsp, struct init_sta *sta); + bool (*is_kicked)(struct cpuhvfs_dvfsp *dvfsp); + + void (*cluster_on)(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster); + void (*cluster_off)(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster); + + int (*set_target)(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster, unsigned int index, + unsigned int *ret_volt); + unsigned int (*get_volt)(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster); + + int (*get_sema)(struct cpuhvfs_dvfsp *dvfsp, enum sema_user user); + void (*release_sema)(struct cpuhvfs_dvfsp *dvfsp, enum sema_user user); + + int (*pause_dvfsp)(struct cpuhvfs_dvfsp *dvfsp, enum pause_src src); + void (*unpause_dvfsp)(struct cpuhvfs_dvfsp *dvfsp, enum pause_src src); + + int (*stop_dvfsp)(struct cpuhvfs_dvfsp *dvfsp); + + void (*dump_info)(struct cpuhvfs_dvfsp *dvfsp, const char *fmt, ...); +}; + +struct cpuhvfs_data { + struct cpuhvfs_dvfsp *dvfsp; + + u32 *dbg_repo; /* => dvfsp->log_repo */ + struct dentry *dbg_fs; +}; + + +#ifdef CONFIG_HYBRID_CPU_DVFS + +/************************************** + * [CPU SPM] Declaration + **************************************/ +#include "mt_cpufreq_hybrid_fw.h" + +static struct pwr_ctrl dvfs_ctrl = { + .r7_ctrl_en = 1, + + .wake_src = WAKE_SRC_TWAM | WAKE_SRC_CPU, +}; + +static void __iomem *cspm_base; +static void __iomem *csram_base; +static void __iomem *sema_reg[NUM_SEMA_USER]; + +static struct clk *i2c_clk; + +static u32 cspm_probe_done; + +static struct init_sta suspend_sta = { + .opp = { [0 ... (NUM_CPU_CLUSTER - 1)] = UINT_MAX }, + .volt = { [0 ... (NUM_CPU_CLUSTER - 1)] = UINT_MAX }, +}; + +/** + * 1. Will not be restored after IPO-H boot + * 2. Keep PAUSE_INIT set until cluster-on notification + */ +static u32 pause_src_map __nosavedata = PSF_PAUSE_INIT; + +static u32 pause_log_en = PSF_PAUSE_SUSPEND | + /*PSF_PAUSE_IDLE |*/ + /*PSF_PAUSE_I2CDRV |*/ + PSF_PAUSE_INIT; + +/** + * dbgx_log_en[15:0] : show on UART/MobileLog + * dbgx_log_en[31:16]: show on MobileLog + */ +static u32 dbgx_log_en = /*(DLF_DVFS << 16) |*/ + DLF_STOP | + DLF_PAUSE | + /*DLF_SEMA |*/ + /*DLF_DVFS |*/ + DLF_CLUSTER | + DLF_KICK; + +static u32 dvfs_fail_ke; +static u32 sema_fail_ke; +static u32 pause_fail_ke; + +static DEFINE_SPINLOCK(cspm_lock); +static DEFINE_SPINLOCK(dvfs_lock); + +static DECLARE_WAIT_QUEUE_HEAD(dvfs_wait); + +static int cspm_module_init(struct cpuhvfs_dvfsp *dvfsp); +static int cspm_go_to_dvfs(struct cpuhvfs_dvfsp *dvfsp, struct init_sta *sta); +static bool cspm_is_pcm_kicked(struct cpuhvfs_dvfsp *dvfsp); + +static void cspm_cluster_notify_on(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster); +static void cspm_cluster_notify_off(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster); + +static int cspm_set_target_opp(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster, unsigned int index, + unsigned int *ret_volt); +static unsigned int cspm_get_curr_volt(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster); + +static int cspm_get_semaphore(struct cpuhvfs_dvfsp *dvfsp, enum sema_user user); +static void cspm_release_semaphore(struct cpuhvfs_dvfsp *dvfsp, enum sema_user user); + +static int cspm_pause_pcm_running(struct cpuhvfs_dvfsp *dvfsp, enum pause_src src); +static void cspm_unpause_pcm_to_run(struct cpuhvfs_dvfsp *dvfsp, enum pause_src src); + +static int cspm_stop_pcm_running(struct cpuhvfs_dvfsp *dvfsp); + +static void cspm_dump_debug_info(struct cpuhvfs_dvfsp *dvfsp, const char *fmt, ...); + + +/************************************** + * [Hybrid DVFS] Declaration + **************************************/ +static struct cpuhvfs_dvfsp g_dvfsp = { + .pcmdesc = &dvfs_pcm, + .pwrctrl = &dvfs_ctrl, + + .init_dvfsp = cspm_module_init, + .kick_dvfsp = cspm_go_to_dvfs, + .is_kicked = cspm_is_pcm_kicked, + + .cluster_on = cspm_cluster_notify_on, + .cluster_off = cspm_cluster_notify_off, + + .set_target = cspm_set_target_opp, + .get_volt = cspm_get_curr_volt, + + .get_sema = cspm_get_semaphore, + .release_sema = cspm_release_semaphore, + + .pause_dvfsp = cspm_pause_pcm_running, + .unpause_dvfsp = cspm_unpause_pcm_to_run, + + .stop_dvfsp = cspm_stop_pcm_running, + + .dump_info = cspm_dump_debug_info, +}; + +static struct cpuhvfs_data g_cpuhvfs = { + .dvfsp = &g_dvfsp, +}; + +static u32 dbg_repo_bak[DBG_REPO_NUM]; + + +/************************************** + * [CPU SPM] Macro / Inline + **************************************/ +#define cspm_read(addr) __raw_readl(addr) +#define cspm_write(addr, val) mt_reg_sync_writel(val, addr) + +#define csram_read(offs) __raw_readl(csram_base + (offs)) +#define csram_write(offs, val) mt_reg_sync_writel(val, csram_base + (offs)) + +#define csram_write_fw_sta() \ +do { \ + csram_write(OFFS_FW_RSV5, cspm_read(CSPM_SW_RSV5)); \ + csram_write(OFFS_FW_RSV3, cspm_read(CSPM_SW_RSV3)); \ + csram_write(OFFS_FW_RSV4, cspm_read(CSPM_SW_RSV4)); \ + csram_write(OFFS_FW_RSV2, cspm_read(CSPM_SW_RSV2)); \ +} while (0) + +#define cspm_get_timestamp() cspm_read(CSPM_PCM_TIMER_OUT) +#define cspm_get_pcmpc() cspm_read(CSPM_PCM_REG15_DATA) + +#define cspm_get_min_freq_ll() ((cspm_read(CSPM_SW_RSV4) & SW_L_F_MIN_MASK) >> 0) +#define cspm_get_min_freq_l() ((cspm_read(CSPM_SW_RSV4) & SW_B_F_MIN_MASK) >> 16) + +#define cspm_get_max_freq_ll() ((cspm_read(CSPM_SW_RSV4) & SW_L_F_MAX_MASK) >> 4) +#define cspm_get_max_freq_l() ((cspm_read(CSPM_SW_RSV4) & SW_B_F_MAX_MASK) >> 20) + +#define cspm_is_ll_paused() (!!(cspm_read(CSPM_SW_RSV4) & SW_L_PAUSE)) +#define cspm_is_l_paused() (!!(cspm_read(CSPM_SW_RSV4) & SW_B_PAUSE)) +#define cspm_is_all_paused() ((cspm_read(CSPM_SW_RSV4) & SW_ALL_PAUSE) == SW_ALL_PAUSE) + +#define cspm_get_curr_freq_ll() ((cspm_read(CSPM_SW_RSV5) & L_F_CURR_MASK) >> 0) +#define cspm_get_curr_freq_l() ((cspm_read(CSPM_SW_RSV5) & B_F_CURR_MASK) >> 16) + +#define cspm_get_curr_volt_ll() ((cspm_read(CSPM_SW_RSV5) & L_V_CURR_MASK) >> 8) +#define cspm_get_curr_volt_l() ((cspm_read(CSPM_SW_RSV5) & B_V_CURR_MASK) >> 24) + +#define cspm_is_fw_ll_done() (!!(cspm_read(CSPM_SW_RSV5) & FW_L_DONE)) +#define cspm_is_fw_l_done() (!!(cspm_read(CSPM_SW_RSV5) & FW_B_DONE)) +#define cspm_is_fw_all_done() ((cspm_read(CSPM_SW_RSV5) & FW_ALL_DONE) == FW_ALL_DONE) + +#define cspm_err(fmt, args...) pr_err("[CPUHVFS] " fmt, ##args) +#define cspm_warn(fmt, args...) pr_warn("[CPUHVFS] " fmt, ##args) +#define cspm_debug(fmt, args...) pr_debug("[CPUHVFS] " fmt, ##args) + +#define cspm_dbgx(flag, fmt, args...) \ +do { \ + if (dbgx_log_en & DLF_##flag) \ + cspm_err(fmt, ##args); \ + else if (dbgx_log_en & (DLF_##flag << 16)) \ + cspm_debug(fmt, ##args); \ + else \ + ; \ +} while (0) + +#define wait_complete_us(condition, delay, timeout) \ +({ \ + int _i = 0; \ + int _n = DIV_ROUND_UP(timeout, delay); \ + csram_write(OFFS_PCM_PC1, cspm_get_pcmpc()); \ + csram_write(OFFS_TIMER_OUT1, cspm_get_timestamp()); \ + while (!(condition)) { \ + if (_i >= _n) { \ + _i = -_i; \ + break; \ + } \ + udelay(delay); \ + _i++; \ + } \ + csram_write(OFFS_TIMER_OUT2, cspm_get_timestamp()); \ + csram_write(OFFS_PCM_PC2, cspm_get_pcmpc()); \ + _i; \ +}) + +static inline u32 base_va_to_pa(const u32 *base) +{ + phys_addr_t pa = virt_to_phys(base); + + MAPPING_DRAM_ACCESS_ADDR(pa); /* for 4GB mode */ + + return (u32)pa; +} + +static inline u32 opp_sw_to_fw(unsigned int index) +{ + return index < NUM_CPU_OPP ? (NUM_CPU_OPP - 1) - index : 0 /* lowest frequency */; +} + +static inline unsigned int opp_fw_to_sw(u32 freq) +{ + return freq < NUM_CPU_OPP ? (NUM_CPU_OPP - 1) - freq : 0 /* highest frequency */; +} + + +/************************************** + * [Hybrid DVFS] Macro / Inline + **************************************/ +#define set_dvfsp_init_done(dvfsp) ((dvfsp)->init_done = 1) +#define is_dvfsp_uninit(dvfsp) (!(dvfsp)->init_done) + +#define cpuhvfs_crit(fmt, args...) pr_err("[CPUHVFS] " fmt, ##args) +#define cpuhvfs_err(fmt, args...) pr_err("[CPUHVFS] " fmt, ##args) +#define cpuhvfs_warn(fmt, args...) pr_warn("[CPUHVFS] " fmt, ##args) +#define cpuhvfs_debug(fmt, args...) pr_debug("[CPUHVFS] " fmt, ##args) + +#define DEFINE_FOPS_RO(fname) \ +static int fname##_open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, fname##_show, inode->i_private); \ +} \ +static const struct file_operations fname##_fops = { \ + .open = fname##_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + +#define DEFINE_FOPS_RW(fname) \ +static int fname##_open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, fname##_show, inode->i_private); \ +} \ +static const struct file_operations fname##_fops = { \ + .open = fname##_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .write = fname##_write, \ + .release = single_release, \ +} + + +/************************************** + * [CPU SPM] Function + **************************************/ +static void __cspm_pcm_sw_reset(void) +{ + u32 sta; + + cspm_write(CSPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET); + cspm_write(CSPM_PCM_CON0, CON0_CFG_KEY); + + udelay(10); + + sta = cspm_read(CSPM_PCM_FSM_STA); + if (sta != PCM_FSM_STA_DEF) { + cspm_err("FAILED TO RESET PCM (0x%x)\n", sta); + BUG(); + } +} + +static void __cspm_register_init(void) +{ + /* enable register write */ + cspm_write(CSPM_POWERON_CONFIG_EN, REGWR_CFG_KEY | REGWR_EN); + + /* init power control register */ + cspm_write(CSPM_POWER_ON_VAL1, POWER_ON_VAL1_DEF | R7_PCM_TIMER_SET); + cspm_write(CSPM_PCM_PWR_IO_EN, 0); + + /* reset PCM */ + __cspm_pcm_sw_reset(); + + /* init PCM control register */ + cspm_write(CSPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_CK_EN); + cspm_write(CSPM_PCM_CON1, CON1_CFG_KEY | CON1_EVENT_LOCK_EN | + CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B | + CON1_MIF_APBEN); + cspm_write(CSPM_PCM_IM_PTR, 0); + cspm_write(CSPM_PCM_IM_LEN, 0); + + /* clean wakeup event raw status */ + cspm_write(CSPM_WAKEUP_EVENT_MASK, ~0); + + /* clean IRQ status */ + cspm_write(CSPM_IRQ_MASK, IRQM_ALL); + cspm_write(CSPM_IRQ_STA, IRQC_ALL); + cspm_write(CSPM_SW_INT_CLEAR, PCM_SW_INT_ALL); +} + +static void __cspm_reset_and_init_pcm(const struct pcm_desc *pcmdesc) +{ + /* do basic init because of Infra power-on reset */ +#if 0 + /* others will set REGWR_EN for SEMA access */ + if (!(cspm_read(CSPM_POWERON_CONFIG_EN) & REGWR_EN)) +#else + if (!(cspm_read(CSPM_PCM_CON1) & CON1_MIF_APBEN)) +#endif + __cspm_register_init(); + + /* reset PCM */ + __cspm_pcm_sw_reset(); + + /* init PCM_CON0 */ + cspm_write(CSPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_CK_EN); + + /* init PCM_CON1 (disable PCM timer and PCM WDT) */ + cspm_write(CSPM_PCM_CON1, CON1_CFG_KEY | CON1_EVENT_LOCK_EN | + CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B | + (pcmdesc->replace ? 0 : CON1_IM_NONRP_EN) | + CON1_MIF_APBEN); +} + +static void __cspm_kick_im_to_fetch(const struct pcm_desc *pcmdesc) +{ + u32 ptr, len, con0; + + /* tell IM where is PCM code (use slave mode if code existed) */ + ptr = base_va_to_pa(pcmdesc->base); + len = pcmdesc->size - 1; + if (cspm_read(CSPM_PCM_IM_PTR) != ptr || cspm_read(CSPM_PCM_IM_LEN) != len || + pcmdesc->sess > 2) { + cspm_write(CSPM_PCM_IM_PTR, ptr); + cspm_write(CSPM_PCM_IM_LEN, len); + } else { + cspm_write(CSPM_PCM_CON1, cspm_read(CSPM_PCM_CON1) | CON1_CFG_KEY | CON1_IM_SLAVE); + } + + /* kick IM to fetch (only toggle IM_KICK) */ + con0 = cspm_read(CSPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK); + cspm_write(CSPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_IM_KICK); + cspm_write(CSPM_PCM_CON0, con0 | CON0_CFG_KEY); +} + +static void __cspm_init_pcm_register(void) +{ + /* init r7 with POWER_ON_VAL1 */ + cspm_write(CSPM_PCM_REG_DATA_INI, cspm_read(CSPM_POWER_ON_VAL1)); + cspm_write(CSPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R7); + cspm_write(CSPM_PCM_PWR_IO_EN, 0); +} + +static void __cspm_init_event_vector(const struct pcm_desc *pcmdesc) +{ + /* init event vector register */ + cspm_write(CSPM_PCM_EVENT_VECTOR0, pcmdesc->vec0); + cspm_write(CSPM_PCM_EVENT_VECTOR1, pcmdesc->vec1); + + /* disable event vector (enabled by FW) */ + cspm_write(CSPM_PCM_EVENT_VECTOR_EN, 0); +} + +static void __cspm_set_wakeup_event(const struct pwr_ctrl *pwrctrl) +{ + /* start PCM timer (as free-run timer) */ + cspm_write(CSPM_PCM_TIMER_VAL, 0xffffffff); + cspm_write(CSPM_PCM_CON1, cspm_read(CSPM_PCM_CON1) | CON1_CFG_KEY | CON1_PCM_TIMER_EN); + + /* unmask PCM wakeup source */ + cspm_write(CSPM_WAKEUP_EVENT_MASK, ~pwrctrl->wake_src); + + /* unmask CSPM IRQ */ + cspm_write(CSPM_IRQ_MASK, IRQM_ALL_EXC_RET0); +} + +static void __cspm_kick_pcm_to_run(const struct pwr_ctrl *pwrctrl, const struct init_sta *sta) +{ + u32 con0; + + /* init register to match FW expectation */ + cspm_write(CSPM_SW_RSV4, SW_B_PAUSE | /* must */ + SW_B_F_MAX(NUM_CPU_OPP - 1) | + SW_B_F_MIN(0) | + SW_L_PAUSE | /* must */ + SW_L_F_MAX(NUM_CPU_OPP - 1) | + SW_L_F_MIN(0) | + BYPASS_FIT); /* must */ + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + + cspm_write(CSPM_SW_RSV5, B_F_CURR(opp_sw_to_fw(sta->opp[CPU_CLUSTER_L])) | + B_F_DES(opp_sw_to_fw(sta->opp[CPU_CLUSTER_L])) | + B_V_CURR(sta->volt[CPU_CLUSTER_L]) | + L_F_CURR(opp_sw_to_fw(sta->opp[CPU_CLUSTER_LL])) | + L_F_DES(opp_sw_to_fw(sta->opp[CPU_CLUSTER_LL])) | + L_V_CURR(sta->volt[CPU_CLUSTER_LL])); + csram_write(OFFS_FW_RSV5, cspm_read(CSPM_SW_RSV5)); + + /* init variable to match FW state */ + pause_src_map |= PSF_PAUSE_INIT; + csram_write(OFFS_PAUSE_SRC, pause_src_map); + + /* enable r7 to control power */ + cspm_write(CSPM_PCM_PWR_IO_EN, pwrctrl->r7_ctrl_en ? PCM_PWRIO_EN_R7 : 0); + + cspm_dbgx(KICK, "kick PCM to run, RSV4: 0x%x, RSV5: 0x%x\n", + cspm_read(CSPM_SW_RSV4), cspm_read(CSPM_SW_RSV5)); + + /* kick PCM to run (only toggle PCM_KICK) */ + con0 = cspm_read(CSPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK); + cspm_write(CSPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_PCM_KICK); + cspm_write(CSPM_PCM_CON0, con0 | CON0_CFG_KEY); +} + +static void __cspm_save_curr_sta(struct init_sta *sta) +{ + csram_write_fw_sta(); + + sta->opp[CPU_CLUSTER_LL] = opp_fw_to_sw(cspm_get_curr_freq_ll()); + sta->opp[CPU_CLUSTER_L] = opp_fw_to_sw(cspm_get_curr_freq_l()); + + sta->volt[CPU_CLUSTER_LL] = cspm_get_curr_volt_ll(); + sta->volt[CPU_CLUSTER_L] = cspm_get_curr_volt_l(); +} + +static void __cspm_clean_after_pause(void) +{ + /* disable TWAM timer */ + cspm_write(CSPM_TWAM_CON, cspm_read(CSPM_TWAM_CON) & ~TWAM_ENABLE); + + /* disable r7 to control power */ + cspm_write(CSPM_PCM_PWR_IO_EN, 0); + + /* clean PCM timer event */ + cspm_write(CSPM_PCM_CON1, CON1_CFG_KEY | (cspm_read(CSPM_PCM_CON1) & ~CON1_PCM_TIMER_EN)); + + /* clean wakeup event raw status */ + cspm_write(CSPM_WAKEUP_EVENT_MASK, ~0); + + /* clean IRQ status */ + cspm_write(CSPM_IRQ_MASK, IRQM_ALL); + cspm_write(CSPM_IRQ_STA, IRQC_ALL); + cspm_write(CSPM_SW_INT_CLEAR, PCM_SW_INT_ALL); +} + +static void cspm_dump_debug_info(struct cpuhvfs_dvfsp *dvfsp, const char *fmt, ...) +{ + u32 timer, reg15, ap_sema, spm_sema; + u32 rsv3, rsv4, rsv5; + char msg[320]; + va_list args; + + timer = cspm_read(CSPM_PCM_TIMER_OUT); + reg15 = cspm_read(CSPM_PCM_REG15_DATA); + ap_sema = cspm_read(CSPM_AP_SEMA); + spm_sema = cspm_read(CSPM_SPM_SEMA); + + rsv5 = cspm_read(CSPM_SW_RSV5); + rsv3 = cspm_read(CSPM_SW_RSV3); + rsv4 = cspm_read(CSPM_SW_RSV4); + + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + + cspm_err("%s\n", msg); + cspm_err("FW_VER: %s\n", dvfsp->pcmdesc->version); + + cspm_err("PCM_TIMER: %08x\n", timer); + cspm_err("PCM_REG15: %u, SEMA: 0x(%x %x)\n", reg15, ap_sema, spm_sema); + + cspm_err("SW_RSV4: 0x%x\n", rsv4); + cspm_err("SW_RSV5: 0x%x\n", rsv5); + cspm_err("SW_RSV3: 0x%x\n", rsv3); + + cspm_err("SW_RSV2 : 0x%x\n", cspm_read(CSPM_SW_RSV2)); + cspm_err("SW_DEBUG: 0x%x\n", cspm_read(CSPM_SW_DEBUG)); + cspm_err("SW_FLAG : 0x%x\n", cspm_read(CSPM_SW_FLAG)); + + cspm_err("PCM_FSM_STA: 0x%x\n", cspm_read(CSPM_PCM_FSM_STA)); +} + +static int __cspm_pause_pcm_running(struct cpuhvfs_dvfsp *dvfsp, u32 psf) +{ + int r = 0; + + /* @dvfsp may be uninitialized (PAUSE_INIT is set) */ + + if (pause_src_map == 0) { + cspm_write(CSPM_SW_RSV4, cspm_read(CSPM_SW_RSV4) | SW_ALL_PAUSE); + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + csram_write(OFFS_PAUSE_TIME, cspm_get_timestamp()); + + udelay(10); /* skip FW_DONE 1->0 transition */ + + r = wait_complete_us(cspm_is_fw_all_done(), 10, PAUSE_TIMEOUT); + csram_write_fw_sta(); + + if (r >= 0) { /* pause done */ + r = 0; + clk_disable(i2c_clk); + } + } + + if (!r) { + pause_src_map |= psf; + if (csram_base) + csram_write(OFFS_PAUSE_SRC, pause_src_map); + + if (cspm_base && psf == PSF_PAUSE_SUSPEND) + __cspm_save_curr_sta(&suspend_sta); + } else { + cspm_dump_debug_info(dvfsp, "PAUSE TIMEOUT, psf = 0x%x", psf); + BUG_ON(pause_fail_ke); + } + + return r; +} + +static void __cspm_unpause_pcm_to_run(struct cpuhvfs_dvfsp *dvfsp, u32 psf) +{ + int r; + u32 rsv4; + + /* @dvfsp may be uninitialized (PAUSE_INIT is set) */ + + pause_src_map &= ~psf; + if (csram_base) + csram_write(OFFS_PAUSE_SRC, pause_src_map); + + if (pause_src_map == 0 && csram_base /* avoid Coverity complaining */) { + r = clk_enable(i2c_clk); + if (!r) { + rsv4 = cspm_read(CSPM_SW_RSV4); + csram_write(OFFS_SW_RSV4, rsv4); + + if (rsv4 & L_CLUSTER_EN) + rsv4 &= ~SW_L_PAUSE; + if (rsv4 & B_CLUSTER_EN) + rsv4 &= ~SW_B_PAUSE; + BUG_ON((rsv4 & SW_ALL_PAUSE) == SW_ALL_PAUSE); /* no cluster on!? */ + + cspm_write(CSPM_SW_RSV4, rsv4); + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + csram_write(OFFS_UNPAUSE_TIME, cspm_get_timestamp()); + + wake_up(&dvfs_wait); /* for set_target_opp */ + csram_write(OFFS_DVFS_WAIT, 0); + } else { + cspm_err("FAILED TO ENABLE I2C CLOCK (%d)\n", r); + BUG(); + } + } +} + +static int cspm_stop_pcm_running(struct cpuhvfs_dvfsp *dvfsp) +{ + int r; + unsigned long flags; + + spin_lock(&dvfs_lock); + cspm_dbgx(STOP, "[%08x] stop pcm\n", cspm_get_timestamp()); + + r = __cspm_pause_pcm_running(dvfsp, PSF_PAUSE_INIT); + if (!r) { + spin_lock_irqsave(&cspm_lock, flags); + + __cspm_clean_after_pause(); + + __cspm_pcm_sw_reset(); + + spin_unlock_irqrestore(&cspm_lock, flags); + } + spin_unlock(&dvfs_lock); + + return r; +} + +static int cspm_pause_pcm_running(struct cpuhvfs_dvfsp *dvfsp, enum pause_src src) +{ + int r; + u32 psf = (1U << src); + + /* @dvfsp may be uninitialized (PAUSE_INIT is set) */ + + spin_lock(&dvfs_lock); + if (pause_log_en & psf) + cspm_dbgx(PAUSE, "pause pcm, src = %u, map = 0x%x\n", src, pause_src_map); + + r = __cspm_pause_pcm_running(dvfsp, psf); + spin_unlock(&dvfs_lock); + + return r; +} + +static void cspm_unpause_pcm_to_run(struct cpuhvfs_dvfsp *dvfsp, enum pause_src src) +{ + u32 psf = (1U << src); + + /* @dvfsp may be uninitialized (PAUSE_INIT is set) */ + + spin_lock(&dvfs_lock); + if (pause_log_en & psf) + cspm_dbgx(PAUSE, "unpause pcm, src = %u, map = 0x%x\n", src, pause_src_map); + + if (psf & pause_src_map) + __cspm_unpause_pcm_to_run(dvfsp, psf); + spin_unlock(&dvfs_lock); +} + +static int cspm_get_semaphore(struct cpuhvfs_dvfsp *dvfsp, enum sema_user user) +{ + int i; + int n = DIV_ROUND_UP(SEMA_GET_TIMEOUT, 10); + + if (user == SEMA_I2C_DRV) /* workaround */ + return cspm_pause_pcm_running(dvfsp, PAUSE_I2CDRV); + + if (is_dvfsp_uninit(dvfsp)) + return 0; + + cspm_dbgx(SEMA, "sema get, user = %u\n", user); + + cspm_write(CSPM_POWERON_CONFIG_EN, REGWR_CFG_KEY | REGWR_EN); /* enable register write */ + + for (i = 0; i < n; i++) { + cspm_write(sema_reg[user], 0x1); + if (cspm_read(sema_reg[user]) & 0x1) + return 0; + + udelay(10); + } + + cspm_dump_debug_info(dvfsp, "SEMA_USER%u GET TIMEOUT", user); + BUG_ON(sema_fail_ke); + + return -EBUSY; +} + +static void cspm_release_semaphore(struct cpuhvfs_dvfsp *dvfsp, enum sema_user user) +{ + if (user == SEMA_I2C_DRV) { /* workaround */ + cspm_unpause_pcm_to_run(dvfsp, PAUSE_I2CDRV); + return; + } + + if (is_dvfsp_uninit(dvfsp)) + return; + + cspm_dbgx(SEMA, "sema release, user = %u\n", user); + + cspm_write(CSPM_POWERON_CONFIG_EN, REGWR_CFG_KEY | REGWR_EN); /* enable register write */ + + if (cspm_read(sema_reg[user]) & 0x1) { + cspm_write(sema_reg[user], 0x1); + BUG_ON(cspm_read(sema_reg[user]) & 0x1); /* semaphore release failed */ + } +} + +static int cspm_set_target_opp(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster, unsigned int index, + unsigned int *ret_volt) +{ + int r = 0; + u32 f_des = opp_sw_to_fw(index); + u32 rsv4, v; + + spin_lock(&dvfs_lock); + csram_write(OFFS_FUNC_ENTER, (cluster << 24) | (index << 16) | FEF_DVFS); + + cspm_dbgx(DVFS, "cluster%u dvfs, opp = %u <%u>, pause = 0x%x\n", + cluster, index, f_des, pause_src_map); + + while (pause_src_map != 0) { + csram_write(OFFS_DVFS_WAIT, (cluster << 8) | index); + spin_unlock(&dvfs_lock); + + wait_event(dvfs_wait, pause_src_map == 0); /* wait for PCM to be unpaused */ + + spin_lock(&dvfs_lock); + } + + rsv4 = cspm_read(CSPM_SW_RSV4); + csram_write(OFFS_SW_RSV4, rsv4); + + switch (cluster) { + case CPU_CLUSTER_LL: + if (!(rsv4 & SW_L_PAUSE)) { /* cluster on */ + rsv4 &= ~SW_L_F_DES_MASK; + cspm_write(CSPM_SW_RSV4, rsv4 | SW_L_F_ASSIGN | SW_L_F_DES(f_des)); + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + + r = wait_complete_us(cspm_get_curr_freq_ll() == f_des, 10, DVFS_TIMEOUT); + csram_write_fw_sta(); + } + + v = cspm_get_curr_volt_ll(); + break; + case CPU_CLUSTER_L: + default: + if (!(rsv4 & SW_B_PAUSE)) { /* cluster on */ + rsv4 &= ~SW_B_F_DES_MASK; + cspm_write(CSPM_SW_RSV4, rsv4 | SW_B_F_ASSIGN | SW_B_F_DES(f_des)); + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + + r = wait_complete_us(cspm_get_curr_freq_l() == f_des, 10, DVFS_TIMEOUT); + csram_write_fw_sta(); + } + + v = cspm_get_curr_volt_l(); + break; + } + + if (r >= 0) { /* DVFS done */ + r = 0; + if (ret_volt) + *ret_volt = v; + } else { + cspm_dump_debug_info(dvfsp, "CLUSTER%u DVFS TIMEOUT, opp = %u <%u>", + cluster, index, f_des); + BUG_ON(dvfs_fail_ke); + } + + csram_write(OFFS_FUNC_ENTER, 0); + spin_unlock(&dvfs_lock); + + return r; +} + +static unsigned int cspm_get_curr_volt(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster) +{ + switch (cluster) { + case CPU_CLUSTER_LL: + return cspm_get_curr_volt_ll(); + case CPU_CLUSTER_L: + default: + return cspm_get_curr_volt_l(); + } + + return UINT_MAX; +} + +static void cspm_cluster_notify_on(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster) +{ + u32 time, rsv4; + + spin_lock(&dvfs_lock); + time = cspm_get_timestamp(); + rsv4 = cspm_read(CSPM_SW_RSV4); + csram_write(OFFS_SW_RSV4, rsv4); + + cspm_dbgx(CLUSTER, "[%08x] cluster%u on, pause = 0x%x, RSV4: 0x%x\n", + time, cluster, pause_src_map, rsv4); + + switch (cluster) { + case CPU_CLUSTER_LL: + BUG_ON(!(rsv4 & SW_L_PAUSE)); /* not paused at cluster off */ + + if (pause_src_map == 0) + rsv4 &= ~SW_L_PAUSE; + cspm_write(CSPM_SW_RSV4, rsv4 | L_CLUSTER_EN); + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + break; + case CPU_CLUSTER_L: + default: + BUG_ON(!(rsv4 & SW_B_PAUSE)); /* not paused at cluster off */ + + if (pause_src_map == 0) + rsv4 &= ~SW_B_PAUSE; + cspm_write(CSPM_SW_RSV4, rsv4 | B_CLUSTER_EN); + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + break; + } + + if (PSF_PAUSE_INIT & pause_src_map) { + BUG_ON(rsv4 & (B_CLUSTER_EN | L_CLUSTER_EN)); /* not right after kick */ + + __cspm_unpause_pcm_to_run(dvfsp, PSF_PAUSE_INIT); + } + spin_unlock(&dvfs_lock); +} + +static void cspm_cluster_notify_off(struct cpuhvfs_dvfsp *dvfsp, unsigned int cluster) +{ + int r; + u32 time, rsv4; + + spin_lock(&dvfs_lock); + csram_write(OFFS_FUNC_ENTER, (cluster << 24) | FEF_CLUSTER_OFF); + + time = cspm_get_timestamp(); + rsv4 = cspm_read(CSPM_SW_RSV4); + csram_write(OFFS_SW_RSV4, rsv4); + + cspm_dbgx(CLUSTER, "[%08x] cluster%u off, pause = 0x%x, RSV4: 0x%x\n", + time, cluster, pause_src_map, rsv4); + + /* DFS only to the lowest frequency (no I2C control) */ + switch (cluster) { + case CPU_CLUSTER_LL: + BUG_ON(!(rsv4 & L_CLUSTER_EN)); /* already off */ + + cspm_write(CSPM_SW_RSV4, rsv4 & ~(L_CLUSTER_EN | SW_L_PAUSE | SW_L_F_ASSIGN)); + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + + /* FW will set SW_PAUSE when done */ + r = wait_complete_us(cspm_get_curr_freq_ll() == 0 && cspm_is_ll_paused(), + 10, DVFS_TIMEOUT); + csram_write_fw_sta(); + break; + case CPU_CLUSTER_L: + default: + BUG_ON(!(rsv4 & B_CLUSTER_EN)); /* already off */ + + cspm_write(CSPM_SW_RSV4, rsv4 & ~(B_CLUSTER_EN | SW_B_PAUSE | SW_B_F_ASSIGN)); + csram_write(OFFS_SW_RSV4, cspm_read(CSPM_SW_RSV4)); + + /* FW will set SW_PAUSE when done */ + r = wait_complete_us(cspm_get_curr_freq_l() == 0 && cspm_is_l_paused(), + 10, DVFS_TIMEOUT); + csram_write_fw_sta(); + break; + } + + if (r < 0) { + cspm_dump_debug_info(dvfsp, "CLUSTER%u OFF TIMEOUT", cluster); + BUG(); + } + + csram_write(OFFS_FUNC_ENTER, 0); + spin_unlock(&dvfs_lock); +} + +static bool cspm_is_pcm_kicked(struct cpuhvfs_dvfsp *dvfsp) +{ + return !!(cspm_read(CSPM_PCM_FSM_STA) & FSM_PCM_KICK); +} + +static void __cspm_check_and_update_sta(struct init_sta *sta) +{ + int i; + + for (i = 0; i < NUM_CPU_CLUSTER; i++) { + if (sta->opp[i] == OPP_AT_SUSPEND) { + BUG_ON(suspend_sta.opp[i] == UINT_MAX); /* without suspend */ + + sta->opp[i] = suspend_sta.opp[i]; + suspend_sta.opp[i] = UINT_MAX; + } + if (sta->volt[i] == VOLT_AT_SUSPEND) { + BUG_ON(suspend_sta.volt[i] == UINT_MAX); /* without suspend */ + + sta->volt[i] = suspend_sta.volt[i]; + suspend_sta.volt[i] = UINT_MAX; + } + + csram_write(OFFS_INIT_OPP + i * sizeof(u32), sta->opp[i]); + csram_write(OFFS_INIT_FREQ + i * sizeof(u32), sta->freq[i]); + csram_write(OFFS_INIT_VOLT + i * sizeof(u32), sta->volt[i]); + + cspm_dbgx(KICK, "cluster%d: opp = %u, freq = %u, volt = 0x%x\n", + i, sta->opp[i], sta->freq[i], sta->volt[i]); + } +} + +static int cspm_go_to_dvfs(struct cpuhvfs_dvfsp *dvfsp, struct init_sta *sta) +{ + unsigned long flags; + struct pcm_desc *pcmdesc = dvfsp->pcmdesc; + struct pwr_ctrl *pwrctrl = dvfsp->pwrctrl; + + spin_lock(&dvfs_lock); + __cspm_check_and_update_sta(sta); + + spin_lock_irqsave(&cspm_lock, flags); + + __cspm_reset_and_init_pcm(pcmdesc); + + __cspm_kick_im_to_fetch(pcmdesc); + + __cspm_init_pcm_register(); + + __cspm_init_event_vector(pcmdesc); + + __cspm_set_wakeup_event(pwrctrl); + + __cspm_kick_pcm_to_run(pwrctrl, sta); + + spin_unlock_irqrestore(&cspm_lock, flags); + spin_unlock(&dvfs_lock); + + return 0; +} + +static int cspm_probe(struct platform_device *pdev) +{ + int r; + unsigned long flags; + + cspm_base = of_iomap(pdev->dev.of_node, 0); + if (!cspm_base) { + cspm_err("FAILED TO MAP CSPM REGISTER\n"); + return -ENOMEM; + } + + csram_base = of_iomap(pdev->dev.of_node, 1); + if (!csram_base) { + cspm_err("FAILED TO MAP CSRAM MEMORY\n"); + return -ENOMEM; + } + + i2c_clk = devm_clk_get(&pdev->dev, "i2c"); + if (IS_ERR(i2c_clk)) { + cspm_err("FAILED TO GET I2C CLOCK (%ld)\n", PTR_ERR(i2c_clk)); + return PTR_ERR(i2c_clk); + } + r = clk_prepare(i2c_clk); + if (r) { + cspm_err("FAILED TO PREPARE I2C CLOCK (%d)\n", r); + return r; + } + + /* build register mapping for general access */ + sema_reg[SEMA_FHCTL_DRV] = CSPM_AP_SEMA; + + spin_lock_irqsave(&cspm_lock, flags); + __cspm_register_init(); + spin_unlock_irqrestore(&cspm_lock, flags); + + cspm_probe_done = 1; + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id cspm_of_match[] = { + { .compatible = "mediatek,mt6755-dvfsp", }, + {} +}; +#endif + +static struct platform_driver cspm_driver = { + .probe = cspm_probe, + .driver = { + .name = "cspm", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(cspm_of_match), + }, +}; + +static int cspm_module_init(struct cpuhvfs_dvfsp *dvfsp) +{ + int r; + + r = platform_driver_register(&cspm_driver); + if (r) { + cspm_err("FAILED TO REGISTER CSPM DRIVER (%d)\n", r); + return r; + } + + if (!cspm_probe_done) { + cspm_err("FAILED TO PROBE CSPM DEVICE\n"); + return -ENODEV; + } + + dvfsp->log_repo = csram_base; + + return 0; +} + + +/************************************** + * [Hybrid DVFS] Function + **************************************/ +static int dvfsp_fw_show(struct seq_file *m, void *v) +{ + struct cpuhvfs_dvfsp *dvfsp = m->private; + struct pcm_desc *pcmdesc = dvfsp->pcmdesc; + + seq_printf(m, "version = %s\n" , pcmdesc->version); + seq_printf(m, "base = 0x%p -> 0x%x\n", pcmdesc->base, base_va_to_pa(pcmdesc->base)); + seq_printf(m, "size = %u\n" , pcmdesc->size); + seq_printf(m, "sess = %u\n" , pcmdesc->sess); + seq_printf(m, "replace = %u\n" , pcmdesc->replace); + seq_printf(m, "vec0 = 0x%x\n", pcmdesc->vec0); + seq_printf(m, "vec1 = 0x%x\n", pcmdesc->vec1); + + return 0; +} + +static int dvfsp_reg_show(struct seq_file *m, void *v) +{ + seq_printf(m, "PCM_TIMER : %08x\n", cspm_read(CSPM_PCM_TIMER_OUT)); + seq_printf(m, "PCM_REG15 : %u\n" , cspm_read(CSPM_PCM_REG15_DATA)); + seq_puts(m, "============\n"); + seq_printf(m, "SW_RSV4 : 0x%x\n", cspm_read(CSPM_SW_RSV4)); + seq_printf(m, "SW_RSV5 : 0x%x\n", cspm_read(CSPM_SW_RSV5)); + seq_printf(m, "SW_RSV3 : 0x%x\n", cspm_read(CSPM_SW_RSV3)); + seq_puts(m, "============\n"); + seq_printf(m, "SW_RSV2 : 0x%x\n", cspm_read(CSPM_SW_RSV2)); + seq_printf(m, "SW_DEBUG : 0x%x\n", cspm_read(CSPM_SW_DEBUG)); + seq_printf(m, "SW_FLAG : 0x%x\n", cspm_read(CSPM_SW_FLAG)); + seq_puts(m, "============\n"); + seq_printf(m, "PCM_FSM_STA: 0x%x\n", cspm_read(CSPM_PCM_FSM_STA)); + + return 0; +} + +static int dbg_repo_show(struct seq_file *m, void *v) +{ + int i; + u32 *repo = m->private; + char ch; + + /* only save current status to debug repo */ + if (repo != dbg_repo_bak) { + repo[REPO_I_WDT_LATCH0] = cspm_read(CSPM_PCM_FSM_STA); + repo[REPO_I_WDT_LATCH1] = cspm_read(CSPM_PCM_REG6_DATA); + repo[REPO_I_WDT_LATCH2] = cspm_read(CSPM_SW_RSV5); + } + + for (i = 0; i < DBG_REPO_NUM; i++) { + if (i >= REPO_I_LOG_S && (i - REPO_I_LOG_S) % ENTRY_EACH_LOG == 0) + ch = ':'; /* timestamp */ + else + ch = '.'; + + seq_printf(m, "%4d%c%08x%c", i, ch, repo[i], i % 4 == 3 ? '\n' : ' '); + } + + return 0; +} + +DEFINE_FOPS_RO(dvfsp_fw); +DEFINE_FOPS_RO(dvfsp_reg); +DEFINE_FOPS_RO(dbg_repo); + +static int create_cpuhvfs_debug_fs(struct cpuhvfs_data *cpuhvfs) +{ + struct dentry *root; + + /* create /sys/kernel/debug/cpuhvfs */ + root = debugfs_create_dir("cpuhvfs", NULL); + if (!root) + return -EPERM; + + debugfs_create_file("dvfsp_fw", 0444, root, cpuhvfs->dvfsp, &dvfsp_fw_fops); + debugfs_create_file("dvfsp_reg", 0444, root, cpuhvfs->dvfsp, &dvfsp_reg_fops); + + debugfs_create_file("dbg_repo", 0444, root, cpuhvfs->dbg_repo, &dbg_repo_fops); + debugfs_create_file("dbg_repo_bak", 0444, root, dbg_repo_bak, &dbg_repo_fops); + + debugfs_create_x32("pause_src_map", 0444, root, &pause_src_map); + debugfs_create_x32("pause_log_en", 0644, root, &pause_log_en); + + debugfs_create_x32("dbgx_log_en", 0644, root, &dbgx_log_en); + + debugfs_create_bool("dvfs_fail_ke", 0644, root, &dvfs_fail_ke); + debugfs_create_bool("sema_fail_ke", 0644, root, &sema_fail_ke); + debugfs_create_bool("pause_fail_ke", 0644, root, &pause_fail_ke); + + cpuhvfs->dbg_fs = root; + + return 0; +} + +static void init_cpuhvfs_debug_repo(struct cpuhvfs_data *cpuhvfs) +{ + u32 __iomem *dbg_repo = cpuhvfs->dvfsp->log_repo; + + /* backup debug repo for later analysis */ + memcpy_fromio(dbg_repo_bak, dbg_repo, DBG_REPO_SIZE); + dbg_repo_bak[REPO_I_WDT_LATCH0] = cspm_read(CSPM_PCM_WDT_LATCH0); + dbg_repo_bak[REPO_I_WDT_LATCH1] = cspm_read(CSPM_PCM_WDT_LATCH1); + dbg_repo_bak[REPO_I_WDT_LATCH2] = cspm_read(CSPM_PCM_WDT_LATCH2); + cpuhvfs_crit("WDT_LATCH0: 0x%x, LATCH1: 0x%x, LATCH2: 0x%x\n", + dbg_repo_bak[REPO_I_WDT_LATCH0], + dbg_repo_bak[REPO_I_WDT_LATCH1], + dbg_repo_bak[REPO_I_WDT_LATCH2]); + + dbg_repo[0] = REPO_GUARD0; + dbg_repo[1] = REPO_GUARD1; + dbg_repo[2] = REPO_GUARD0; + dbg_repo[3] = REPO_GUARD1; + + memset_io((void __iomem *)dbg_repo + DBG_REPO_DATA_S - DBG_REPO_S, + 0, + DBG_REPO_E - DBG_REPO_DATA_S); + + dbg_repo[REPO_I_DATA_S] = REPO_GUARD0; + + cpuhvfs->dbg_repo = dbg_repo; +} + + +/************************************** + * [Hybrid DVFS] API + **************************************/ +void cpuhvfs_dump_dvfsp_info(void) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (is_dvfsp_uninit(dvfsp)) + return; + + dvfsp->dump_info(dvfsp, "DVFSP INFO DUMP"); +} + +/** + * Should be called at syscore_suspend stage (1 CPU/1 cluster) + */ +int cpuhvfs_dvfsp_suspend(void) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (is_dvfsp_uninit(dvfsp)) + return 0; + + return dvfsp->pause_dvfsp(dvfsp, PAUSE_SUSPEND); +} + +/** + * Should be called at syscore_resume stage (1 CPU/1 cluster) + */ +void cpuhvfs_dvfsp_resume(unsigned int on_cluster, struct init_sta *sta) +{ + int r; + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (on_cluster >= NUM_CPU_CLUSTER || !sta) + return; + + if (is_dvfsp_uninit(dvfsp)) + return; + + if (!dvfsp->is_kicked(dvfsp)) { + r = dvfsp->kick_dvfsp(dvfsp, sta); + BUG_ON(r); + + dvfsp->cluster_on(dvfsp, on_cluster); + } + + dvfsp->unpause_dvfsp(dvfsp, PAUSE_SUSPEND); +} + +int cpuhvfs_stop_dvfsp_running(void) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (is_dvfsp_uninit(dvfsp)) + return 0; + + return dvfsp->stop_dvfsp(dvfsp); +} + +int cpuhvfs_restart_dvfsp_running(struct init_sta *sta) +{ + int r, i; + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (!sta) + return -EINVAL; + + if (is_dvfsp_uninit(dvfsp)) + return -ENODEV; + + if (dvfsp->is_kicked(dvfsp)) + return -EPERM; + + r = dvfsp->kick_dvfsp(dvfsp, sta); + if (r) + return r; + + for (i = 0; i < NUM_CPU_CLUSTER; i++) { + if (sta->is_on[i]) + dvfsp->cluster_on(dvfsp, i); + } + + return 0; +} + +int cpuhvfs_pause_dvfsp_running(enum pause_src src) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (src >= NUM_PAUSE_SRC || src == PAUSE_INIT || src == PAUSE_SUSPEND) + return -EINVAL; + + return dvfsp->pause_dvfsp(dvfsp, src); +} + +void cpuhvfs_unpause_dvfsp_to_run(enum pause_src src) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (src >= NUM_PAUSE_SRC || src == PAUSE_INIT || src == PAUSE_SUSPEND) + return; + + dvfsp->unpause_dvfsp(dvfsp, src); +} + +int cpuhvfs_get_dvfsp_semaphore(enum sema_user user) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (user >= NUM_SEMA_USER) + return -EINVAL; + + return dvfsp->get_sema(dvfsp, user); +} + +void cpuhvfs_release_dvfsp_semaphore(enum sema_user user) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (user >= NUM_SEMA_USER) + return; + + dvfsp->release_sema(dvfsp, user); +} + +/** + * Current voltage (PMIC value) will be saved in @ret_volt if succeed + */ +int cpuhvfs_set_target_opp(unsigned int cluster, unsigned int index, unsigned int *ret_volt) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (cluster >= NUM_CPU_CLUSTER || index >= NUM_CPU_OPP) + return -EINVAL; + + if (is_dvfsp_uninit(dvfsp)) + return -ENODEV; + + if (!dvfsp->is_kicked(dvfsp)) { + cpuhvfs_err("CANNOT SET OPP, DVFSP IS NOT KICKED\n"); + return -EPERM; + } + + return dvfsp->set_target(dvfsp, cluster, index, ret_volt); +} + +/** + * Get current voltage (PMIC value) from DVFSP. Return UINT_MAX if unavailable + */ +unsigned int cpuhvfs_get_curr_volt(unsigned int cluster) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (cluster >= NUM_CPU_CLUSTER) + return UINT_MAX; + + if (is_dvfsp_uninit(dvfsp)) + return UINT_MAX; + + if (!dvfsp->is_kicked(dvfsp)) + return UINT_MAX; + + return dvfsp->get_volt(dvfsp, cluster); +} + +void cpuhvfs_notify_cluster_on(unsigned int cluster) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (cluster >= NUM_CPU_CLUSTER) + return; + + if (is_dvfsp_uninit(dvfsp)) + return; + + if (!dvfsp->is_kicked(dvfsp)) + return; + + dvfsp->cluster_on(dvfsp, cluster); +} + +/** + * Require scaling to the lowest frequency for cluster off + */ +void cpuhvfs_notify_cluster_off(unsigned int cluster) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + BUG_ON(cluster >= NUM_CPU_CLUSTER); + BUG_ON(is_dvfsp_uninit(dvfsp)); + BUG_ON(!dvfsp->is_kicked(dvfsp)); + + dvfsp->cluster_off(dvfsp, cluster); +} + +int cpuhvfs_kick_dvfsp_to_run(struct init_sta *sta) +{ + struct cpuhvfs_dvfsp *dvfsp = g_cpuhvfs.dvfsp; + + if (!sta) + return -EINVAL; + + if (is_dvfsp_uninit(dvfsp)) + return -ENODEV; + + if (dvfsp->is_kicked(dvfsp)) + return 0; + + return dvfsp->kick_dvfsp(dvfsp, sta); +} + +int cpuhvfs_module_init(void) +{ + int r; + struct cpuhvfs_data *cpuhvfs = &g_cpuhvfs; + + if (!cpuhvfs->dbg_repo) { + cpuhvfs_err("FAILED TO PRE-INIT CPUHVFS\n"); + return -ENODEV; + } + + set_dvfsp_init_done(cpuhvfs->dvfsp); + + r = create_cpuhvfs_debug_fs(cpuhvfs); + if (r) { + cpuhvfs_err("FAILED TO CREATE DEBUG FILESYSTEM (%d)\n", r); + return r; + } + + return 0; +} + +static int cpuhvfs_pre_module_init(void) +{ + int r; + struct cpuhvfs_data *cpuhvfs = &g_cpuhvfs; + + r = cpuhvfs->dvfsp->init_dvfsp(cpuhvfs->dvfsp); + if (r) { + cpuhvfs_err("FAILED TO INIT DVFS PROCESSOR (%d)\n", r); + return r; + } + + init_cpuhvfs_debug_repo(cpuhvfs); + + return 0; +} +fs_initcall(cpuhvfs_pre_module_init); + +#endif /* CONFIG_HYBRID_CPU_DVFS */ + +MODULE_DESCRIPTION("Hybrid CPU DVFS Driver v0.5"); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq_hybrid_fw.h b/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq_hybrid_fw.h new file mode 100644 index 0000000000000000000000000000000000000000..c86b54dae62cd4cbffde041bc9793790b2c30bf3 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_cpufreq_hybrid_fw.h @@ -0,0 +1,695 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_CPUFREQ_HYBRID_FW_ +#define _MT_CPUFREQ_HYBRID_FW_ + +#include + + +#define EVENT_VEC(event, resume, imme, pc) \ + (((pc) << 16) | \ + (!!(imme) << 7) | \ + (!!(resume) << 6) | \ + ((event) & 0x3f)) + +struct pcm_desc { + const char *version; /* PCM code version */ + const u32 *base; /* binary array base */ + const u16 size; /* binary array size */ + const u8 sess; /* session number */ + const u8 replace; /* replace mode */ + const u16 addr_2nd; /* 2nd binary array size */ + + u32 vec0; /* event vector 0 config */ + u32 vec1; /* event vector 1 config */ +}; + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +static const u32 dvfs_binary[] = { + 0x1ad0001f, 0x1022761c, 0x8ac0000b, 0x0000000f, 0x12c02c1f, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x1022761c, 0x88400001, 0xfffffff0, 0xa0502c01, + 0x18c0001f, 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, + 0x1022761c, 0x8ac0000b, 0x000f0000, 0x12c82c1f, 0xf0000000, 0x17c07c1f, + 0x1850001f, 0x1022761c, 0x88400001, 0xfff0ffff, 0xa0582c01, 0x18c0001f, + 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, + 0x8ac0000b, 0x000000f0, 0x12c22c1f, 0xf0000000, 0x17c07c1f, 0x1850001f, + 0x1022761c, 0x88400001, 0xffffff0f, 0xa0522c01, 0x18c0001f, 0x1022761c, + 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x8ac0000b, + 0x00f00000, 0x12ca2c1f, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x1022761c, + 0x88400001, 0xff0fffff, 0xa05a2c01, 0x18c0001f, 0x1022761c, 0xe0c00001, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x8ac0000b, 0x00008000, + 0x12c7ac1f, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x1022761c, 0x88400001, + 0xffff7fff, 0xa057ac01, 0x18c0001f, 0x1022761c, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x12cfac1f, 0x8ac0000b, 0x00000001, + 0xf0000000, 0x17c07c1f, 0x1850001f, 0x1022761c, 0x88400001, 0x7fffffff, + 0xa05fac01, 0x18c0001f, 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, + 0x1ad0001f, 0x10227610, 0x8ac0000b, 0x00004000, 0x12c72c1f, 0xf0000000, + 0x17c07c1f, 0x1ad0001f, 0x10227610, 0x8ac0000b, 0x40000000, 0x12cf2c1f, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x00008000, + 0x12c7ac1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227614, 0x8ac0000b, + 0x30000000, 0x12ce2c1f, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x10227614, + 0x88400001, 0xcfffffff, 0xa05e2c01, 0x18c0001f, 0x10227614, 0xe0c00001, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227614, 0x12cf2c1f, 0x8ac0000b, + 0x00000003, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x10227614, 0x88400001, + 0x3fffffff, 0xa05f2c01, 0x18c0001f, 0x10227614, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x10200744, 0x88400001, 0xffffffbf, 0x18c0001f, + 0x10200744, 0xe0c00001, 0x88400001, 0xffffffbf, 0x1800001f, 0x00000001, + 0x1013001f, 0xa0400001, 0x10002c1f, 0x100d801f, 0x88000000, 0x0000001f, + 0x88400001, 0xffffffc1, 0x1010801f, 0xa0400001, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x10200744, 0x88400001, 0xffffbfff, 0x18c0001f, + 0x10200744, 0xe0c00001, 0x88400001, 0xffffbfff, 0x1800001f, 0x00000001, + 0x1017001f, 0xa0400001, 0x10002c1f, 0x88000000, 0x003e0000, 0x1008801f, + 0x88400001, 0xffffc1ff, 0x1014801f, 0xa0400001, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x10200744, 0x88400001, 0xffbfffff, 0x18c0001f, + 0x10200744, 0xe0c00001, 0x88400001, 0xffbfffff, 0x1800001f, 0x00000001, + 0x101b001f, 0xa0400001, 0x10002c1f, 0x88000000, 0x003e0000, 0x1008801f, + 0x88400001, 0xffc1ffff, 0x1018801f, 0xa0400001, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x10002c1f, 0x88000000, 0x07c00000, 0x100b001f, 0x18c0001f, + 0x1000102c, 0x1850001f, 0x1000102c, 0x88400001, 0xffffffe0, 0xa0400001, + 0xe0c00001, 0x1b80001f, 0x20000104, 0xf0000000, 0x17c07c1f, 0x18c0001f, + 0x10001000, 0x1850001f, 0x10001000, 0x88400001, 0xffffcfff, 0xa0562c01, + 0xe0c00001, 0x1850001f, 0x10227614, 0x88400001, 0xcfffffff, 0xa05e2c01, + 0x18c0001f, 0x10227614, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x10002c1f, + 0x88000000, 0x0001f000, 0x1006001f, 0x18c0001f, 0x10001024, 0x1850001f, + 0x10001024, 0x88400001, 0xffffffe0, 0xa0400001, 0xe0c00001, 0x1b80001f, + 0x20000104, 0xf0000000, 0x17c07c1f, 0x10002c1f, 0x88000000, 0x0001f000, + 0x1006001f, 0x18c0001f, 0x10001028, 0x1850001f, 0x10001028, 0x88400001, + 0xffffffe0, 0xa0400001, 0xe0c00001, 0x1b80001f, 0x20000104, 0xf0000000, + 0x17c07c1f, 0x18c0001f, 0x10227600, 0x1850001f, 0x10227600, 0x1052041f, + 0xa0402c01, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x10227600, + 0x1850001f, 0x10227600, 0x1054041f, 0xa0402c01, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x18c0001f, 0x10227610, 0x1850001f, 0x10227610, 0x1052041f, + 0xa0402c01, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x10227610, + 0x1850001f, 0x10227610, 0x1054041f, 0xa0402c01, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x18c0001f, 0x0011c330, 0x1850001f, 0x0011c330, 0x1052041f, + 0xa0402c01, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x0011c330, + 0x1850001f, 0x0011c330, 0x1054041f, 0xa0402c01, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x18c0001f, 0x0011c048, 0x00f1ac03, 0x08c00003, 0x00000004, + 0x1af00003, 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x0011c0d8, + 0x00f1ac03, 0x08c00003, 0x00000004, 0x1af00003, 0x17c07c1f, 0xf0000000, + 0x17c07c1f, 0xc2001180, 0x17c07c1f, 0xc2001ea0, 0x17c07c1f, 0xc2400440, + 0x17c07c1f, 0xc2402ba0, 0x17c07c1f, 0x68600008, 0x00000001, 0xd8202fe1, + 0x17c07c1f, 0xc2400660, 0x17c07c1f, 0xc2402cc0, 0x17c07c1f, 0xc24013a0, + 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0x1800001f, 0x10000104, 0x18d0001f, + 0x10000104, 0x88c00003, 0xffffffcf, 0x1840001f, 0x00000003, 0xa0d20403, + 0xe0000003, 0x1b80001f, 0x20000104, 0x1800001f, 0x10001000, 0x18d0001f, + 0x10001000, 0x88c00003, 0xffffffcf, 0x1840001f, 0x00000002, 0xa0d20403, + 0xe0000003, 0x1800001f, 0x00000002, 0x18c0001f, 0x10001000, 0x1850001f, + 0x10001000, 0x88400001, 0xffffcfff, 0xa0560001, 0xe0c00001, 0x1850001f, + 0x10227614, 0x88400001, 0xcfffffff, 0xa05e0001, 0x18c0001f, 0x10227614, + 0xe0c00001, 0x1000101f, 0x88000000, 0x00000e00, 0x1004801f, 0x18c0001f, + 0x1000c204, 0x1850001f, 0x1000c204, 0x88400001, 0xf8ffffff, 0x101c001f, + 0xa8400001, 0x80000000, 0xa0400001, 0xe0c00001, 0x1b80001f, 0x20000104, + 0x1800001f, 0x10001000, 0x18d0001f, 0x10001000, 0x88c00003, 0xffffffcf, + 0x1840001f, 0x00000001, 0xa0d20403, 0xe0000003, 0x1800001f, 0x10000104, + 0x18d0001f, 0x10000104, 0x88c00003, 0xffffffcf, 0xe0000003, 0xf0000000, + 0x17c07c1f, 0x18d0001f, 0x1000cf38, 0x82109803, 0xd8203ce8, 0x17c07c1f, + 0x1800001f, 0x1000cf38, 0x80f09803, 0xe0000003, 0x1a50001f, 0x1000cf40, + 0x8a400009, 0x001fffff, 0x18d0001f, 0x1000cf48, 0x88c00003, 0x001fffff, + 0x60600c09, 0xd8003ce1, 0x17c07c1f, 0x1b80001f, 0x20000104, 0xd0003b80, + 0x17c07c1f, 0x1800001f, 0x1000cf40, 0x18d0001f, 0x1000c204, 0x88c00003, + 0x001fffff, 0xa8c00003, 0x80000000, 0xe0000003, 0x1800001f, 0x1000cf38, + 0x18d0001f, 0x1000cf38, 0x88c00003, 0xfffffffb, 0xa8c00003, 0x00000004, + 0xe0000003, 0x1800001f, 0x1000cf38, 0x18d0001f, 0x1000cf38, 0x88c00003, + 0xfffffffe, 0xa8c00003, 0x00000001, 0xe0000003, 0xe8208000, 0x1000cf0c, + 0x06003c97, 0xe8208000, 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, + 0xd82040a3, 0x17c07c1f, 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, + 0x88c00003, 0xfffffffe, 0xa8c00003, 0x00000001, 0xe0000003, 0xe8208000, + 0x1022742c, 0x00000001, 0x1240101f, 0x8a400009, 0x000001ff, 0x1256241f, + 0x1800001f, 0x1000cf44, 0x18d0001f, 0x1000cf44, 0xa8c00009, 0x80000000, + 0xe0000003, 0x1800001f, 0x00000000, 0x18d0001f, 0x1000cf48, 0x88c00003, + 0x001fffff, 0x60600c09, 0xd80047a1, 0x17c07c1f, 0x68600000, 0x00000064, + 0xd80046c1, 0x17c07c1f, 0x08000000, 0x00000001, 0x1b80001f, 0x20000104, + 0xd00044a0, 0x17c07c1f, 0x1810001f, 0x10227604, 0xa8000000, 0x00000002, + 0x18c0001f, 0x10227604, 0xe0c00000, 0x1800001f, 0x1000c204, 0x1850001f, + 0x1000c204, 0x88400001, 0xffe00000, 0xa8400001, 0x80000000, 0x18d0001f, + 0x1000cf48, 0x88c00003, 0x001fffff, 0xa0c00403, 0xe0000003, 0xe8208000, + 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, 0xd8204963, 0x17c07c1f, + 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, 0x88c00003, 0xfffffffe, + 0xe0000003, 0xe8208000, 0x1022742c, 0x00000001, 0xd8205168, 0x17c07c1f, + 0x1800001f, 0x1000cf40, 0x18d0001f, 0x1000c204, 0x88c00003, 0x001fffff, + 0xa8c00003, 0x80000000, 0xe0000003, 0x1000101f, 0x88000000, 0x000001ff, + 0x1850001f, 0x1000c900, 0x1044041f, 0x88400001, 0x000000ff, 0x10c0341f, + 0x10c18c1f, 0x10d80c1f, 0x1800001f, 0x1000cf3c, 0xe0000003, 0xe8208000, + 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, 0xd8204ea3, 0x17c07c1f, + 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, 0xa0d01803, 0xe0000003, + 0xe8208000, 0x1022742c, 0x00000001, 0x18d0001f, 0x1000cf38, 0x1800001f, + 0x1000cf38, 0xa0d09803, 0xe0000003, 0xf0000000, 0x17c07c1f, 0x18d0001f, + 0x1000cf4c, 0x82109803, 0xd82054a8, 0x17c07c1f, 0x1800001f, 0x1000cf4c, + 0x80f09803, 0xe0000003, 0x1a50001f, 0x1000cf54, 0x8a400009, 0x001fffff, + 0x18d0001f, 0x1000cf5c, 0x88c00003, 0x001fffff, 0x60600c09, 0xd80054a1, + 0x17c07c1f, 0x1b80001f, 0x20000104, 0xd0005340, 0x17c07c1f, 0x1800001f, + 0x1000cf54, 0x18d0001f, 0x1000c214, 0x88c00003, 0x001fffff, 0xa8c00003, + 0x80000000, 0xe0000003, 0x1800001f, 0x1000cf4c, 0x18d0001f, 0x1000cf4c, + 0x88c00003, 0xfffffffb, 0xa8c00003, 0x00000004, 0xe0000003, 0x1800001f, + 0x1000cf4c, 0x18d0001f, 0x1000cf4c, 0x88c00003, 0xfffffffe, 0xa8c00003, + 0x00000001, 0xe0000003, 0xe8208000, 0x1000cf0c, 0x06003c97, 0xe8208000, + 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, 0xd8205863, 0x17c07c1f, + 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, 0xa0d09803, 0xe0000003, + 0xe8208000, 0x1022742c, 0x00000001, 0x1240101f, 0x8a400009, 0x000001ff, + 0x1256241f, 0x1800001f, 0x1000cf58, 0x18d0001f, 0x1000cf58, 0xa8c00009, + 0x80000000, 0xe0000003, 0x1800001f, 0x00000000, 0x18d0001f, 0x1000cf5c, + 0x88c00003, 0x001fffff, 0x60600c09, 0xd8005f01, 0x17c07c1f, 0x68600000, + 0x00000064, 0xd8005e21, 0x17c07c1f, 0x08000000, 0x00000001, 0x1b80001f, + 0x20000104, 0xd0005c00, 0x17c07c1f, 0x1810001f, 0x10227604, 0xa8000000, + 0x00000002, 0x18c0001f, 0x10227604, 0xe0c00000, 0x1800001f, 0x1000c214, + 0x1850001f, 0x1000c214, 0x88400001, 0xffe00000, 0xa8400001, 0x80000000, + 0x18d0001f, 0x1000cf5c, 0x88c00003, 0x001fffff, 0xa0c00403, 0xe0000003, + 0xe8208000, 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, 0xd82060c3, + 0x17c07c1f, 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, 0x80f09803, + 0xe0000003, 0xe8208000, 0x1022742c, 0x00000001, 0xd8206888, 0x17c07c1f, + 0x1800001f, 0x1000cf54, 0x18d0001f, 0x1000c214, 0x88c00003, 0x001fffff, + 0xa8c00003, 0x80000000, 0xe0000003, 0x1000101f, 0x88000000, 0x000001ff, + 0x1850001f, 0x1000c900, 0x88400001, 0x000000ff, 0x10c0341f, 0x10c18c1f, + 0x10d80c1f, 0x1800001f, 0x1000cf50, 0xe0000003, 0xe8208000, 0x1022742c, + 0x00000001, 0x18d0001f, 0x1022742c, 0xd82065c3, 0x17c07c1f, 0x1800001f, + 0x1000cf00, 0x18d0001f, 0x1000cf00, 0xa0d09803, 0xe0000003, 0xe8208000, + 0x1022742c, 0x00000001, 0x18d0001f, 0x1000cf4c, 0x1800001f, 0x1000cf4c, + 0xa0d09803, 0xe0000003, 0xf0000000, 0x17c07c1f, 0xc1400000, 0x17c07c1f, + 0xc2800440, 0x17c07c1f, 0x1080141f, 0xc0802ba0, 0x17c07c1f, 0x1100281f, + 0xc1002ba0, 0x17c07c1f, 0x12407c1f, 0xc24013a0, 0x17c07c1f, 0xc10016a0, + 0x17c07c1f, 0xc10022e0, 0x17c07c1f, 0xc1001ca0, 0x17c07c1f, 0xc10051a0, + 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0xc1400000, 0x17c07c1f, 0xc2800440, + 0x17c07c1f, 0x1080141f, 0xc0802ba0, 0x17c07c1f, 0x1100281f, 0xc1002ba0, + 0x17c07c1f, 0x12407c1f, 0xc24013a0, 0x17c07c1f, 0xc10051a0, 0x17c07c1f, + 0xc1001ca0, 0x17c07c1f, 0xc10022e0, 0x17c07c1f, 0xc10016a0, 0x17c07c1f, + 0xf0000000, 0x17c07c1f, 0xc1400220, 0x17c07c1f, 0xc2800660, 0x17c07c1f, + 0x1080141f, 0xc0802cc0, 0x17c07c1f, 0x1100281f, 0xc1002cc0, 0x17c07c1f, + 0x12407c1f, 0xc24013a0, 0x17c07c1f, 0xc10019a0, 0x17c07c1f, 0xc10020e0, + 0x17c07c1f, 0x88000004, 0x00000e00, 0x1004801f, 0x88c00002, 0x00000e00, + 0x10c48c1f, 0x20600c00, 0xd8207201, 0x17c07c1f, 0xc2003060, 0x17c07c1f, + 0xc1001ca0, 0x17c07c1f, 0xc10039e0, 0x17c07c1f, 0xf0000000, 0x17c07c1f, + 0xc1400220, 0x17c07c1f, 0xc2800660, 0x17c07c1f, 0x1080141f, 0xc0802cc0, + 0x17c07c1f, 0x1100281f, 0xc1002cc0, 0x17c07c1f, 0x12407c1f, 0xc24013a0, + 0x17c07c1f, 0xc10039e0, 0x17c07c1f, 0xc1001ca0, 0x17c07c1f, 0x88000004, + 0x00000e00, 0x1004801f, 0x1a50001f, 0x1000c204, 0x124c241f, 0x8a400009, + 0x00000007, 0x40602400, 0xd8207681, 0x17c07c1f, 0xc2003060, 0x17c07c1f, + 0xc10020e0, 0x17c07c1f, 0xc10019a0, 0x17c07c1f, 0xf0000000, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x1980001f, 0x00000001, + 0xe8208000, 0x10227608, 0x00000340, 0xe8208000, 0x1022760c, 0x00000344, + 0xe8208000, 0x10227424, 0x00000348, 0xe8208000, 0x10227418, 0x00000000, + 0xe8208000, 0x1022741c, 0x00000000, 0xc100c960, 0x17c07c1f, 0xc080c7a0, + 0x17c07c1f, 0x68600004, 0x00000001, 0xd8208361, 0x17c07c1f, 0xc0800520, + 0x17c07c1f, 0xc100ca40, 0x17c07c1f, 0xc080c880, 0x17c07c1f, 0x68600004, + 0x00000001, 0xd82084a1, 0x17c07c1f, 0xc0800740, 0x17c07c1f, 0xc100c5e0, + 0x17c07c1f, 0xc080c420, 0x17c07c1f, 0xc0c00440, 0x17c07c1f, 0x20601003, + 0xd8208601, 0x17c07c1f, 0xc1000520, 0x17c07c1f, 0x20600c02, 0xd82086a1, + 0x17c07c1f, 0xc0800520, 0x17c07c1f, 0xc100c6c0, 0x17c07c1f, 0xc080c500, + 0x17c07c1f, 0xc0c00660, 0x17c07c1f, 0x20601003, 0xd8208801, 0x17c07c1f, + 0xc1000740, 0x17c07c1f, 0x20600c02, 0xd82088a1, 0x17c07c1f, 0xc0800740, + 0x17c07c1f, 0xc100cb20, 0x17c07c1f, 0x68600004, 0x00000001, 0xd8208d21, + 0x17c07c1f, 0xc0800000, 0x17c07c1f, 0xc0800520, 0x17c07c1f, 0x1880001f, + 0x00000001, 0xc0800960, 0x17c07c1f, 0xc100cd40, 0x17c07c1f, 0x68600004, + 0x00000001, 0xd8208c61, 0x17c07c1f, 0xc0800220, 0x17c07c1f, 0xc0800740, + 0x17c07c1f, 0x1880001f, 0x00000001, 0xc0800b80, 0x17c07c1f, 0xd000c380, + 0x17c07c1f, 0x1880001f, 0x00000000, 0xc0800b80, 0x17c07c1f, 0xd0009020, + 0x17c07c1f, 0x1880001f, 0x00000000, 0xc0800960, 0x17c07c1f, 0xc100cd40, + 0x17c07c1f, 0x68600004, 0x00000001, 0xd8208fa1, 0x17c07c1f, 0xc0800220, + 0x17c07c1f, 0xc0800740, 0x17c07c1f, 0x1880001f, 0x00000001, 0xc0800b80, + 0x17c07c1f, 0xd0009020, 0x17c07c1f, 0x1880001f, 0x00000000, 0xc0800b80, + 0x17c07c1f, 0x1840001f, 0x10227610, 0x18d0001f, 0x10227618, 0xe0400003, + 0xc1000cc0, 0x17c07c1f, 0xc080cb20, 0x17c07c1f, 0xa1000804, 0x68600004, + 0x00000000, 0xd8209261, 0x17c07c1f, 0x1880001f, 0x00000000, 0xc0800520, + 0x17c07c1f, 0xc1000da0, 0x17c07c1f, 0xc080cd40, 0x17c07c1f, 0xa1000804, + 0x68600004, 0x00000000, 0xd8209401, 0x17c07c1f, 0x1880001f, 0x00000000, + 0xc0800740, 0x17c07c1f, 0xc1000da0, 0x17c07c1f, 0x68600004, 0x00000001, + 0xd8209821, 0x17c07c1f, 0xc1400440, 0x17c07c1f, 0xc1402ba0, 0x17c07c1f, + 0x89400005, 0x003e01ff, 0xc2800660, 0x17c07c1f, 0xc2802cc0, 0x17c07c1f, + 0x8a80000a, 0x003e01ff, 0x2060140a, 0xd8209761, 0x17c07c1f, 0x1880001f, + 0x00000001, 0xc0801260, 0x17c07c1f, 0xd00098a0, 0x17c07c1f, 0x1880001f, + 0x00000002, 0xc0801260, 0x17c07c1f, 0xd00098a0, 0x17c07c1f, 0x1880001f, + 0x00000002, 0xc0801260, 0x17c07c1f, 0x1840001f, 0x0011c318, 0x18d0001f, + 0x1022761c, 0xe0400003, 0x1840001f, 0x0011c31c, 0x18d0001f, 0x10227618, + 0xe0400003, 0x1840001f, 0x0011c320, 0x18d0001f, 0x10227614, 0xe0400003, + 0xc1400220, 0x17c07c1f, 0xc2800660, 0x17c07c1f, 0x6060140a, 0xd820a8a1, + 0x17c07c1f, 0xc1000da0, 0x17c07c1f, 0xd8209e44, 0x17c07c1f, 0x68600005, + 0x00000007, 0xd8209e41, 0x17c07c1f, 0x1100281f, 0xc1002cc0, 0x17c07c1f, + 0x88000004, 0x000001ff, 0x1016001f, 0x1a50001f, 0x1000c204, 0x8a400009, + 0x001ff000, 0x60602400, 0xd8009e41, 0x17c07c1f, 0xc10039e0, 0x17c07c1f, + 0xc1400000, 0x17c07c1f, 0xc2800440, 0x17c07c1f, 0x6060140a, 0xd820a481, + 0x17c07c1f, 0x18d0001f, 0x10227610, 0x821f1803, 0x120f201f, 0x805e9803, + 0x104e841f, 0xa2000408, 0x82571803, 0x1247241f, 0x80569803, 0x1046841f, + 0xa2400409, 0x80402408, 0xd820a141, 0x17c07c1f, 0xc0c0d640, 0x17c07c1f, + 0x18d0001f, 0x10227610, 0x821f1803, 0x120f201f, 0x805e9803, 0x104e841f, + 0xa2000408, 0xd800a2e8, 0x17c07c1f, 0xc0c02de0, 0x17c07c1f, 0xc180ce20, + 0x17c07c1f, 0x18d0001f, 0x10227610, 0x82171803, 0x1207201f, 0x80569803, + 0x1046841f, 0xa2000408, 0xd800a448, 0x17c07c1f, 0xc180cc00, 0x17c07c1f, + 0xd000c120, 0x17c07c1f, 0x2060140a, 0xd820a621, 0x17c07c1f, 0xc0c0d640, + 0x17c07c1f, 0xc0c06ba0, 0x17c07c1f, 0x1800001f, 0x00000001, 0xc0002960, + 0x17c07c1f, 0xd000b500, 0x17c07c1f, 0xc0c068c0, 0x17c07c1f, 0xc2400cc0, + 0x17c07c1f, 0x68600009, 0x00000001, 0xd820a7a1, 0x17c07c1f, 0xc0c0d640, + 0x17c07c1f, 0xd000a7e0, 0x17c07c1f, 0xc180cc00, 0x17c07c1f, 0x1800001f, + 0x00000002, 0xc0002960, 0x17c07c1f, 0xd000b500, 0x17c07c1f, 0x2060140a, + 0xd820ae81, 0x17c07c1f, 0xc1400000, 0x17c07c1f, 0xc2800440, 0x17c07c1f, + 0x6060140a, 0xd820ab21, 0x17c07c1f, 0xc0c0d640, 0x17c07c1f, 0xc0c072c0, + 0x17c07c1f, 0x1800001f, 0x00000003, 0xc0002960, 0x17c07c1f, 0xd000b500, + 0x17c07c1f, 0x2060140a, 0xd820ad01, 0x17c07c1f, 0xc0c0d640, 0x17c07c1f, + 0xc0c06ba0, 0x17c07c1f, 0xc0c072c0, 0x17c07c1f, 0x1800001f, 0x00000004, + 0xc0002960, 0x17c07c1f, 0xd000b500, 0x17c07c1f, 0xc0c068c0, 0x17c07c1f, + 0xc0c0d640, 0x17c07c1f, 0xc0c072c0, 0x17c07c1f, 0x1800001f, 0x00000005, + 0xc0002960, 0x17c07c1f, 0xd000b500, 0x17c07c1f, 0xc1400000, 0x17c07c1f, + 0xc2800440, 0x17c07c1f, 0x6060140a, 0xd820b1e1, 0x17c07c1f, 0xc0c06e80, + 0x17c07c1f, 0xc2400da0, 0x17c07c1f, 0x68600009, 0x00000001, 0xd820b0e1, + 0x17c07c1f, 0xc0c0d640, 0x17c07c1f, 0xd000b120, 0x17c07c1f, 0xc180ce20, + 0x17c07c1f, 0x1800001f, 0x00000006, 0xc0002960, 0x17c07c1f, 0xd000b500, + 0x17c07c1f, 0x2060140a, 0xd820b3c1, 0x17c07c1f, 0xc0c06e80, 0x17c07c1f, + 0xc0c0d640, 0x17c07c1f, 0xc0c06ba0, 0x17c07c1f, 0x1800001f, 0x00000007, + 0xc0002960, 0x17c07c1f, 0xd000b500, 0x17c07c1f, 0xc0c068c0, 0x17c07c1f, + 0xc0c06e80, 0x17c07c1f, 0xc0c0d640, 0x17c07c1f, 0x1800001f, 0x00000008, + 0xc0002960, 0x17c07c1f, 0xc0c02de0, 0x17c07c1f, 0xc2800440, 0x17c07c1f, + 0xc28000e0, 0x17c07c1f, 0xc2800660, 0x17c07c1f, 0xc2800300, 0x17c07c1f, + 0x1810001f, 0x10227150, 0x1840001f, 0x0011c000, 0x1890001f, 0x10227608, + 0x00c00801, 0xe0c00000, 0x08800002, 0x0000000c, 0x79200002, 0x00000f70, + 0xd800b844, 0x17c07c1f, 0x1880001f, 0x00000340, 0x18c0001f, 0x10227608, + 0xe0c00002, 0x1a90001f, 0x1022741c, 0x1295a81f, 0x1990001f, 0x1022761c, + 0x89800006, 0x00000070, 0x1191981f, 0xa280180a, 0x1183981f, 0x1940001f, + 0x0011c048, 0x02319805, 0x1a700008, 0x17c07c1f, 0x8a400009, 0x0000007f, + 0xa280240a, 0x1890001f, 0x1022760c, 0x00c00801, 0xe0c0000a, 0x08800002, + 0x0000000c, 0x79200002, 0x00000f74, 0xd800bc64, 0x17c07c1f, 0x1880001f, + 0x00000344, 0x18c0001f, 0x1022760c, 0xe0c00002, 0x1a90001f, 0x10227420, + 0x1295a81f, 0x1990001f, 0x1022761c, 0x89800006, 0x00700000, 0x1186981f, + 0xa280180a, 0x1183981f, 0x1940001f, 0x0011c0d8, 0x02319805, 0x1a700008, + 0x17c07c1f, 0x8a400009, 0x0000007f, 0xa280240a, 0x1890001f, 0x10227424, + 0x00c00801, 0xe0c0000a, 0x08800002, 0x0000000c, 0x79200002, 0x00000f78, + 0xd800c084, 0x17c07c1f, 0x1880001f, 0x00000348, 0x18c0001f, 0x10227424, + 0xe0c00002, 0x1980001f, 0x00000001, 0xc1800b80, 0x17c07c1f, 0xc1800960, + 0x17c07c1f, 0x1840001f, 0x0011c324, 0x18d0001f, 0x1022761c, 0xe0400003, + 0x1840001f, 0x0011c328, 0x18d0001f, 0x10227618, 0xe0400003, 0x1840001f, + 0x0011c32c, 0x18d0001f, 0x10227614, 0xe0400003, 0x1b80001f, 0x20003365, + 0xd0008220, 0x17c07c1f, 0xf0000000, 0x1ad0001f, 0x10227618, 0x8ac0000b, + 0x0000000f, 0x12c02c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, + 0x8ac0000b, 0x000f0000, 0x12c82c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, + 0x10227618, 0x8ac0000b, 0x000000f0, 0x12c22c1f, 0xf0000000, 0x17c07c1f, + 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x00f00000, 0x12ca2c1f, 0xf0000000, + 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x00000f00, 0x12c42c1f, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x0f000000, + 0x12cc2c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, + 0x00001000, 0x12c62c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, + 0x8ac0000b, 0x10000000, 0x12ce2c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, + 0x10227618, 0x8ac0000b, 0x00002000, 0x12c6ac1f, 0xf0000000, 0x17c07c1f, + 0x1850001f, 0x10227618, 0x88400001, 0xffffdfff, 0xa056ac01, 0x18c0001f, + 0x10227618, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, + 0x8ac0000b, 0x20000000, 0x12ceac1f, 0xf0000000, 0x17c07c1f, 0x1850001f, + 0x10227618, 0x88400001, 0xdfffffff, 0xa05eac01, 0x18c0001f, 0x10227618, + 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x8ac0000b, + 0x000000f0, 0x12c22c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, + 0x8ac0000b, 0x00f00000, 0x12ca2c1f, 0xf0000000, 0x17c07c1f, 0x18c0001f, + 0x0011c048, 0x00f1ac03, 0x1af00003, 0x17c07c1f, 0xf0000000, 0x17c07c1f, + 0x18c0001f, 0x0011c0d8, 0x00f1ac03, 0x1af00003, 0x17c07c1f, 0xf0000000, + 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x8ac0000b, 0x7f000000, 0x12cc2c1f, + 0xf0000000, 0x17c07c1f, 0x1850001f, 0x1022761c, 0x88400001, 0x80ffffff, + 0xa05c2c01, 0x18c0001f, 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, + 0x1850001f, 0x1022761c, 0x88400001, 0xffff80ff, 0xa0542c01, 0x18c0001f, + 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0xc200cf60, 0x17c07c1f, + 0xc200d120, 0x17c07c1f, 0x88000008, 0x00003f80, 0x1003801f, 0x8a000008, + 0x0000007f, 0xc100d040, 0x17c07c1f, 0xc100d200, 0x17c07c1f, 0x8a400004, + 0x00003f80, 0x1243a41f, 0x89000004, 0x0000007f, 0x20601008, 0xd820d921, + 0x17c07c1f, 0x1100201f, 0x1240001f, 0xc080d2e0, 0x17c07c1f, 0x28600004, + 0x00000058, 0xd820da21, 0x17c07c1f, 0x1900001f, 0x00000058, 0x48600004, + 0x00000020, 0xd820dae1, 0x17c07c1f, 0x1900001f, 0x00000020, 0x60600804, + 0xd820db81, 0x17c07c1f, 0xd000e320, 0x17c07c1f, 0x20600804, 0xd820df21, + 0x17c07c1f, 0x1200081f, 0x60602004, 0xd820dca1, 0x17c07c1f, 0xd000e320, + 0x17c07c1f, 0x0a000008, 0x0000000c, 0x20601008, 0xd820dd61, 0x17c07c1f, + 0x1200101f, 0x08000008, 0x00000010, 0x20602400, 0xd820de21, 0x17c07c1f, + 0x1000241f, 0xc000e920, 0x17c07c1f, 0xc200e420, 0x17c07c1f, 0x1b80001f, + 0x20000300, 0xd000dc00, 0x17c07c1f, 0x1200081f, 0x60602004, 0xd820dfe1, + 0x17c07c1f, 0xd000e320, 0x17c07c1f, 0x0a200008, 0x0000000c, 0x40601008, + 0xd820e0a1, 0x17c07c1f, 0x1200101f, 0xc200e420, 0x17c07c1f, 0x08000008, + 0x00000010, 0x40602400, 0xd820e1a1, 0x17c07c1f, 0x1000241f, 0x28600000, + 0x00000058, 0xd820e261, 0x17c07c1f, 0x1800001f, 0x00000058, 0xc000e920, + 0x17c07c1f, 0x1b80001f, 0x20000300, 0xd000df40, 0x17c07c1f, 0xc100d3c0, + 0x17c07c1f, 0xc100d500, 0x17c07c1f, 0x1800001f, 0x00000000, 0xf0000000, + 0x17c07c1f, 0xe8208000, 0x10006428, 0x00000001, 0x18d0001f, 0x10006428, + 0xd820e423, 0x17c07c1f, 0x1840001f, 0x1000d14c, 0xe060060c, 0x1840001f, + 0x1000d150, 0xe040000b, 0x1840001f, 0x10006400, 0xe0600008, 0x1850001f, + 0x10006400, 0x104f841f, 0xd820e621, 0x17c07c1f, 0xe8208000, 0x10006428, + 0x00000001, 0x18c0001f, 0x0011c310, 0x1850001f, 0x0011c310, 0x1054041f, + 0xa0402c01, 0xe0c00001, 0x18c0001f, 0x10227604, 0x1850001f, 0x10227604, + 0x1054041f, 0xa0402c01, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0xe8208000, + 0x10006428, 0x00000001, 0x18d0001f, 0x10006428, 0xd820e923, 0x17c07c1f, + 0x1840001f, 0x1000d14c, 0xe0600a28, 0x1840001f, 0x1000d150, 0xe040000b, + 0x1840001f, 0x10006400, 0xe0600008, 0x1850001f, 0x10006400, 0x104f841f, + 0xd820eb21, 0x17c07c1f, 0xe8208000, 0x10006428, 0x00000001, 0x18c0001f, + 0x0011c314, 0x1850001f, 0x0011c314, 0x1054041f, 0xa0402c01, 0xe0c00001, + 0x18c0001f, 0x10227600, 0x1850001f, 0x10227600, 0x1054041f, 0xa0402c01, + 0xe0c00001, 0xf0000000, 0x17c07c1f +}; +static struct pcm_desc dvfs_pcm = { + .version = "pcm_dvfs_v0.1_160210_01", + .base = dvfs_binary, + .size = 1905, + .sess = 2, + .replace = 0, + .addr_2nd = 0, +}; +#else +static const u32 dvfs_binary[] = { + 0x1ad0001f, 0x1022761c, 0x8ac0000b, 0x0000000f, 0x12c02c1f, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x1022761c, 0x88400001, 0xfffffff0, 0xa0502c01, + 0x18c0001f, 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, + 0x1022761c, 0x8ac0000b, 0x000f0000, 0x12c82c1f, 0xf0000000, 0x17c07c1f, + 0x1850001f, 0x1022761c, 0x88400001, 0xfff0ffff, 0xa0582c01, 0x18c0001f, + 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, + 0x8ac0000b, 0x000000f0, 0x12c22c1f, 0xf0000000, 0x17c07c1f, 0x1850001f, + 0x1022761c, 0x88400001, 0xffffff0f, 0xa0522c01, 0x18c0001f, 0x1022761c, + 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x8ac0000b, + 0x00f00000, 0x12ca2c1f, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x1022761c, + 0x88400001, 0xff0fffff, 0xa05a2c01, 0x18c0001f, 0x1022761c, 0xe0c00001, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x8ac0000b, 0x00008000, + 0x12c7ac1f, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x1022761c, 0x88400001, + 0xffff7fff, 0xa057ac01, 0x18c0001f, 0x1022761c, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x12cfac1f, 0x8ac0000b, 0x00000001, + 0xf0000000, 0x17c07c1f, 0x1850001f, 0x1022761c, 0x88400001, 0x7fffffff, + 0xa05fac01, 0x18c0001f, 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, + 0x1ad0001f, 0x10227610, 0x8ac0000b, 0x00004000, 0x12c72c1f, 0xf0000000, + 0x17c07c1f, 0x1ad0001f, 0x10227610, 0x8ac0000b, 0x40000000, 0x12cf2c1f, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x00008000, + 0x12c7ac1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227614, 0x8ac0000b, + 0x30000000, 0x12ce2c1f, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x10227614, + 0x88400001, 0xcfffffff, 0xa05e2c01, 0x18c0001f, 0x10227614, 0xe0c00001, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227614, 0x12cf2c1f, 0x8ac0000b, + 0x00000003, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x10227614, 0x88400001, + 0x3fffffff, 0xa05f2c01, 0x18c0001f, 0x10227614, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x10200744, 0x88400001, 0xffffffbf, 0x18c0001f, + 0x10200744, 0xe0c00001, 0x88400001, 0xffffffbf, 0x1800001f, 0x00000001, + 0x1013001f, 0xa0400001, 0x10002c1f, 0x100d801f, 0x88000000, 0x0000001f, + 0x88400001, 0xffffffc1, 0x1010801f, 0xa0400001, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x10200744, 0x88400001, 0xffffbfff, 0x18c0001f, + 0x10200744, 0xe0c00001, 0x88400001, 0xffffbfff, 0x1800001f, 0x00000001, + 0x1017001f, 0xa0400001, 0x10002c1f, 0x88000000, 0x003e0000, 0x1008801f, + 0x88400001, 0xffffc1ff, 0x1014801f, 0xa0400001, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x10200744, 0x88400001, 0xffbfffff, 0x18c0001f, + 0x10200744, 0xe0c00001, 0x88400001, 0xffbfffff, 0x1800001f, 0x00000001, + 0x101b001f, 0xa0400001, 0x10002c1f, 0x88000000, 0x003e0000, 0x1008801f, + 0x88400001, 0xffc1ffff, 0x1018801f, 0xa0400001, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x10002c1f, 0x88000000, 0x07c00000, 0x100b001f, 0x18c0001f, + 0x1000102c, 0x1850001f, 0x1000102c, 0x88400001, 0xffffffe0, 0xa0400001, + 0xe0c00001, 0x1b80001f, 0x20000104, 0xf0000000, 0x17c07c1f, 0x18c0001f, + 0x10001000, 0x1850001f, 0x10001000, 0x88400001, 0xffffcfff, 0xa0562c01, + 0xe0c00001, 0x1850001f, 0x10227614, 0x88400001, 0xcfffffff, 0xa05e2c01, + 0x18c0001f, 0x10227614, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x10002c1f, + 0x88000000, 0x0001f000, 0x1006001f, 0x18c0001f, 0x10001024, 0x1850001f, + 0x10001024, 0x88400001, 0xffffffe0, 0xa0400001, 0xe0c00001, 0x1b80001f, + 0x20000104, 0xf0000000, 0x17c07c1f, 0x10002c1f, 0x88000000, 0x0001f000, + 0x1006001f, 0x18c0001f, 0x10001028, 0x1850001f, 0x10001028, 0x88400001, + 0xffffffe0, 0xa0400001, 0xe0c00001, 0x1b80001f, 0x20000104, 0xf0000000, + 0x17c07c1f, 0x18c0001f, 0x10227600, 0x1850001f, 0x10227600, 0x1052041f, + 0xa0402c01, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x10227600, + 0x1850001f, 0x10227600, 0x1054041f, 0xa0402c01, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x18c0001f, 0x10227610, 0x1850001f, 0x10227610, 0x1052041f, + 0xa0402c01, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x10227610, + 0x1850001f, 0x10227610, 0x1054041f, 0xa0402c01, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x18c0001f, 0x0011c330, 0x1850001f, 0x0011c330, 0x1052041f, + 0xa0402c01, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x0011c330, + 0x1850001f, 0x0011c330, 0x1054041f, 0xa0402c01, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0x18c0001f, 0x0011c048, 0x00f1ac03, 0x08c00003, 0x00000004, + 0x1af00003, 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x0011c0d8, + 0x00f1ac03, 0x08c00003, 0x00000004, 0x1af00003, 0x17c07c1f, 0xf0000000, + 0x17c07c1f, 0xc2001180, 0x17c07c1f, 0xc2001ea0, 0x17c07c1f, 0xc2400440, + 0x17c07c1f, 0xc2402ba0, 0x17c07c1f, 0x68600008, 0x00000001, 0xd8202fe1, + 0x17c07c1f, 0xc2400660, 0x17c07c1f, 0xc2402cc0, 0x17c07c1f, 0xc24013a0, + 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0x1800001f, 0x10000104, 0x18d0001f, + 0x10000104, 0x88c00003, 0xffffffcf, 0x1840001f, 0x00000003, 0xa0d20403, + 0xe0000003, 0x1b80001f, 0x20000104, 0x1800001f, 0x10001000, 0x18d0001f, + 0x10001000, 0x88c00003, 0xffffffcf, 0x1840001f, 0x00000002, 0xa0d20403, + 0xe0000003, 0x1800001f, 0x00000002, 0x18c0001f, 0x10001000, 0x1850001f, + 0x10001000, 0x88400001, 0xffffcfff, 0xa0560001, 0xe0c00001, 0x1850001f, + 0x10227614, 0x88400001, 0xcfffffff, 0xa05e0001, 0x18c0001f, 0x10227614, + 0xe0c00001, 0x1000101f, 0x88000000, 0x00000e00, 0x1004801f, 0x18c0001f, + 0x1000c204, 0x1850001f, 0x1000c204, 0x88400001, 0xf8ffffff, 0x101c001f, + 0xa8400001, 0x80000000, 0xa0400001, 0xe0c00001, 0x1b80001f, 0x20000104, + 0x1800001f, 0x10001000, 0x18d0001f, 0x10001000, 0x88c00003, 0xffffffcf, + 0x1840001f, 0x00000001, 0xa0d20403, 0xe0000003, 0x1800001f, 0x10000104, + 0x18d0001f, 0x10000104, 0x88c00003, 0xffffffcf, 0xe0000003, 0xf0000000, + 0x17c07c1f, 0x18d0001f, 0x1000cf38, 0x82109803, 0xd8203ce8, 0x17c07c1f, + 0x1800001f, 0x1000cf38, 0x80f09803, 0xe0000003, 0x1a50001f, 0x1000cf40, + 0x8a400009, 0x001fffff, 0x18d0001f, 0x1000cf48, 0x88c00003, 0x001fffff, + 0x60600c09, 0xd8003ce1, 0x17c07c1f, 0x1b80001f, 0x20000104, 0xd0003b80, + 0x17c07c1f, 0x1800001f, 0x1000cf40, 0x18d0001f, 0x1000c204, 0x88c00003, + 0x001fffff, 0xa8c00003, 0x80000000, 0xe0000003, 0x1800001f, 0x1000cf38, + 0x18d0001f, 0x1000cf38, 0x88c00003, 0xfffffffb, 0xa8c00003, 0x00000004, + 0xe0000003, 0x1800001f, 0x1000cf38, 0x18d0001f, 0x1000cf38, 0x88c00003, + 0xfffffffe, 0xa8c00003, 0x00000001, 0xe0000003, 0xe8208000, 0x1000cf0c, + 0x06003c97, 0xe8208000, 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, + 0xd82040a3, 0x17c07c1f, 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, + 0x88c00003, 0xfffffffe, 0xa8c00003, 0x00000001, 0xe0000003, 0xe8208000, + 0x1022742c, 0x00000001, 0x1240101f, 0x8a400009, 0x000001ff, 0x1256241f, + 0x1800001f, 0x1000cf44, 0x18d0001f, 0x1000cf44, 0xa8c00009, 0x80000000, + 0xe0000003, 0x1800001f, 0x00000000, 0x18d0001f, 0x1000cf48, 0x88c00003, + 0x001fffff, 0x60600c09, 0xd80047a1, 0x17c07c1f, 0x68600000, 0x00000064, + 0xd80046c1, 0x17c07c1f, 0x08000000, 0x00000001, 0x1b80001f, 0x20000104, + 0xd00044a0, 0x17c07c1f, 0x1810001f, 0x10227604, 0xa8000000, 0x00000002, + 0x18c0001f, 0x10227604, 0xe0c00000, 0x1800001f, 0x1000c204, 0x1850001f, + 0x1000c204, 0x88400001, 0xffe00000, 0xa8400001, 0x80000000, 0x18d0001f, + 0x1000cf48, 0x88c00003, 0x001fffff, 0xa0c00403, 0xe0000003, 0xe8208000, + 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, 0xd8204963, 0x17c07c1f, + 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, 0x88c00003, 0xfffffffe, + 0xe0000003, 0xe8208000, 0x1022742c, 0x00000001, 0xd8205168, 0x17c07c1f, + 0x1800001f, 0x1000cf40, 0x18d0001f, 0x1000c204, 0x88c00003, 0x001fffff, + 0xa8c00003, 0x80000000, 0xe0000003, 0x1000101f, 0x88000000, 0x000001ff, + 0x1850001f, 0x1000c900, 0x1044041f, 0x88400001, 0x000000ff, 0x10c0341f, + 0x10c18c1f, 0x10d80c1f, 0x1800001f, 0x1000cf3c, 0xe0000003, 0xe8208000, + 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, 0xd8204ea3, 0x17c07c1f, + 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, 0xa0d01803, 0xe0000003, + 0xe8208000, 0x1022742c, 0x00000001, 0x18d0001f, 0x1000cf38, 0x1800001f, + 0x1000cf38, 0xa0d09803, 0xe0000003, 0xf0000000, 0x17c07c1f, 0x18d0001f, + 0x1000cf4c, 0x82109803, 0xd82054a8, 0x17c07c1f, 0x1800001f, 0x1000cf4c, + 0x80f09803, 0xe0000003, 0x1a50001f, 0x1000cf54, 0x8a400009, 0x001fffff, + 0x18d0001f, 0x1000cf5c, 0x88c00003, 0x001fffff, 0x60600c09, 0xd80054a1, + 0x17c07c1f, 0x1b80001f, 0x20000104, 0xd0005340, 0x17c07c1f, 0x1800001f, + 0x1000cf54, 0x18d0001f, 0x1000c214, 0x88c00003, 0x001fffff, 0xa8c00003, + 0x80000000, 0xe0000003, 0x1800001f, 0x1000cf4c, 0x18d0001f, 0x1000cf4c, + 0x88c00003, 0xfffffffb, 0xa8c00003, 0x00000004, 0xe0000003, 0x1800001f, + 0x1000cf4c, 0x18d0001f, 0x1000cf4c, 0x88c00003, 0xfffffffe, 0xa8c00003, + 0x00000001, 0xe0000003, 0xe8208000, 0x1000cf0c, 0x06003c97, 0xe8208000, + 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, 0xd8205863, 0x17c07c1f, + 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, 0xa0d09803, 0xe0000003, + 0xe8208000, 0x1022742c, 0x00000001, 0x1240101f, 0x8a400009, 0x000001ff, + 0x1256241f, 0x1800001f, 0x1000cf58, 0x18d0001f, 0x1000cf58, 0xa8c00009, + 0x80000000, 0xe0000003, 0x1800001f, 0x00000000, 0x18d0001f, 0x1000cf5c, + 0x88c00003, 0x001fffff, 0x60600c09, 0xd8005f01, 0x17c07c1f, 0x68600000, + 0x00000064, 0xd8005e21, 0x17c07c1f, 0x08000000, 0x00000001, 0x1b80001f, + 0x20000104, 0xd0005c00, 0x17c07c1f, 0x1810001f, 0x10227604, 0xa8000000, + 0x00000002, 0x18c0001f, 0x10227604, 0xe0c00000, 0x1800001f, 0x1000c214, + 0x1850001f, 0x1000c214, 0x88400001, 0xffe00000, 0xa8400001, 0x80000000, + 0x18d0001f, 0x1000cf5c, 0x88c00003, 0x001fffff, 0xa0c00403, 0xe0000003, + 0xe8208000, 0x1022742c, 0x00000001, 0x18d0001f, 0x1022742c, 0xd82060c3, + 0x17c07c1f, 0x1800001f, 0x1000cf00, 0x18d0001f, 0x1000cf00, 0x80f09803, + 0xe0000003, 0xe8208000, 0x1022742c, 0x00000001, 0xd8206888, 0x17c07c1f, + 0x1800001f, 0x1000cf54, 0x18d0001f, 0x1000c214, 0x88c00003, 0x001fffff, + 0xa8c00003, 0x80000000, 0xe0000003, 0x1000101f, 0x88000000, 0x000001ff, + 0x1850001f, 0x1000c900, 0x88400001, 0x000000ff, 0x10c0341f, 0x10c18c1f, + 0x10d80c1f, 0x1800001f, 0x1000cf50, 0xe0000003, 0xe8208000, 0x1022742c, + 0x00000001, 0x18d0001f, 0x1022742c, 0xd82065c3, 0x17c07c1f, 0x1800001f, + 0x1000cf00, 0x18d0001f, 0x1000cf00, 0xa0d09803, 0xe0000003, 0xe8208000, + 0x1022742c, 0x00000001, 0x18d0001f, 0x1000cf4c, 0x1800001f, 0x1000cf4c, + 0xa0d09803, 0xe0000003, 0xf0000000, 0x17c07c1f, 0xc1400000, 0x17c07c1f, + 0xc2800440, 0x17c07c1f, 0x1080141f, 0xc0802ba0, 0x17c07c1f, 0x1100281f, + 0xc1002ba0, 0x17c07c1f, 0x12407c1f, 0xc24013a0, 0x17c07c1f, 0xc10016a0, + 0x17c07c1f, 0xc10022e0, 0x17c07c1f, 0xc1001ca0, 0x17c07c1f, 0xc10051a0, + 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0xc1400000, 0x17c07c1f, 0xc2800440, + 0x17c07c1f, 0x1080141f, 0xc0802ba0, 0x17c07c1f, 0x1100281f, 0xc1002ba0, + 0x17c07c1f, 0x12407c1f, 0xc24013a0, 0x17c07c1f, 0xc10051a0, 0x17c07c1f, + 0xc1001ca0, 0x17c07c1f, 0xc10022e0, 0x17c07c1f, 0xc10016a0, 0x17c07c1f, + 0xf0000000, 0x17c07c1f, 0xc1400220, 0x17c07c1f, 0xc2800660, 0x17c07c1f, + 0x1080141f, 0xc0802cc0, 0x17c07c1f, 0x1100281f, 0xc1002cc0, 0x17c07c1f, + 0x12407c1f, 0xc24013a0, 0x17c07c1f, 0xc10019a0, 0x17c07c1f, 0xc10020e0, + 0x17c07c1f, 0x88000004, 0x00000e00, 0x1004801f, 0x88c00002, 0x00000e00, + 0x10c48c1f, 0x20600c00, 0xd8207201, 0x17c07c1f, 0xc2003060, 0x17c07c1f, + 0xc1001ca0, 0x17c07c1f, 0xc10039e0, 0x17c07c1f, 0xf0000000, 0x17c07c1f, + 0xc1400220, 0x17c07c1f, 0xc2800660, 0x17c07c1f, 0x1080141f, 0xc0802cc0, + 0x17c07c1f, 0x1100281f, 0xc1002cc0, 0x17c07c1f, 0x12407c1f, 0xc24013a0, + 0x17c07c1f, 0xc10039e0, 0x17c07c1f, 0xc1001ca0, 0x17c07c1f, 0x88000004, + 0x00000e00, 0x1004801f, 0x1a50001f, 0x1000c204, 0x124c241f, 0x8a400009, + 0x00000007, 0x40602400, 0xd8207681, 0x17c07c1f, 0xc2003060, 0x17c07c1f, + 0xc10020e0, 0x17c07c1f, 0xc10019a0, 0x17c07c1f, 0xf0000000, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x1980001f, 0x00000001, + 0xe8208000, 0x10227608, 0x00000340, 0xe8208000, 0x1022760c, 0x00000344, + 0xe8208000, 0x10227424, 0x00000348, 0xe8208000, 0x10227418, 0x00000000, + 0xe8208000, 0x1022741c, 0x00000000, 0xc100c580, 0x17c07c1f, 0xc080c3c0, + 0x17c07c1f, 0x68600004, 0x00000001, 0xd8208361, 0x17c07c1f, 0xc0800520, + 0x17c07c1f, 0xc100c660, 0x17c07c1f, 0xc080c4a0, 0x17c07c1f, 0x68600004, + 0x00000001, 0xd82084a1, 0x17c07c1f, 0xc0800740, 0x17c07c1f, 0xc100c200, + 0x17c07c1f, 0xc080c040, 0x17c07c1f, 0xc0c00440, 0x17c07c1f, 0x20601003, + 0xd8208601, 0x17c07c1f, 0xc1000520, 0x17c07c1f, 0x20600c02, 0xd82086a1, + 0x17c07c1f, 0xc0800520, 0x17c07c1f, 0xc100c2e0, 0x17c07c1f, 0xc080c120, + 0x17c07c1f, 0xc0c00660, 0x17c07c1f, 0x20601003, 0xd8208801, 0x17c07c1f, + 0xc1000740, 0x17c07c1f, 0x20600c02, 0xd82088a1, 0x17c07c1f, 0xc0800740, + 0x17c07c1f, 0xc100c740, 0x17c07c1f, 0x68600004, 0x00000001, 0xd8208d21, + 0x17c07c1f, 0xc0800000, 0x17c07c1f, 0xc0800520, 0x17c07c1f, 0x1880001f, + 0x00000001, 0xc0800960, 0x17c07c1f, 0xc100c960, 0x17c07c1f, 0x68600004, + 0x00000001, 0xd8208c61, 0x17c07c1f, 0xc0800220, 0x17c07c1f, 0xc0800740, + 0x17c07c1f, 0x1880001f, 0x00000001, 0xc0800b80, 0x17c07c1f, 0xd000bfa0, + 0x17c07c1f, 0x1880001f, 0x00000000, 0xc0800b80, 0x17c07c1f, 0xd0008fe0, + 0x17c07c1f, 0x1880001f, 0x00000000, 0xc0800960, 0x17c07c1f, 0xc100c960, + 0x17c07c1f, 0x68600004, 0x00000001, 0xd8208f61, 0x17c07c1f, 0xc0800220, + 0x17c07c1f, 0xc0800740, 0x17c07c1f, 0x1880001f, 0x00000001, 0xc0800b80, + 0x17c07c1f, 0x1880001f, 0x00000000, 0xc0800b80, 0x17c07c1f, 0x1840001f, + 0x10227610, 0x18d0001f, 0x10227618, 0xe0400003, 0xc1000cc0, 0x17c07c1f, + 0x68600004, 0x00000000, 0xd82091c1, 0x17c07c1f, 0x1880001f, 0x00000000, + 0xc0800520, 0x17c07c1f, 0xc1000da0, 0x17c07c1f, 0x68600004, 0x00000000, + 0xd8209301, 0x17c07c1f, 0x1880001f, 0x00000000, 0xc0800740, 0x17c07c1f, + 0xc1000da0, 0x17c07c1f, 0x68600004, 0x00000001, 0xd8209721, 0x17c07c1f, + 0xc1400440, 0x17c07c1f, 0xc1402ba0, 0x17c07c1f, 0x89400005, 0x003e01ff, + 0xc2800660, 0x17c07c1f, 0xc2802cc0, 0x17c07c1f, 0x8a80000a, 0x003e01ff, + 0x2060140a, 0xd8209661, 0x17c07c1f, 0x1880001f, 0x00000001, 0xc0801260, + 0x17c07c1f, 0xd00097a0, 0x17c07c1f, 0x1880001f, 0x00000002, 0xc0801260, + 0x17c07c1f, 0xd00097a0, 0x17c07c1f, 0x1880001f, 0x00000002, 0xc0801260, + 0x17c07c1f, 0x1840001f, 0x0011c318, 0x18d0001f, 0x1022761c, 0xe0400003, + 0x1840001f, 0x0011c31c, 0x18d0001f, 0x10227618, 0xe0400003, 0x1840001f, + 0x0011c320, 0x18d0001f, 0x10227614, 0xe0400003, 0xc1400220, 0x17c07c1f, + 0xc2800660, 0x17c07c1f, 0x6060140a, 0xd820a4c1, 0x17c07c1f, 0xc1400000, + 0x17c07c1f, 0xc2800440, 0x17c07c1f, 0x6060140a, 0xd820a0a1, 0x17c07c1f, + 0x18d0001f, 0x10227610, 0x821f1803, 0x120f201f, 0x805e9803, 0x104e841f, + 0xa2000408, 0x82571803, 0x1247241f, 0x80569803, 0x1046841f, 0xa2400409, + 0x80402408, 0xd8209d61, 0x17c07c1f, 0xc0c0d260, 0x17c07c1f, 0x18d0001f, + 0x10227610, 0x821f1803, 0x120f201f, 0x805e9803, 0x104e841f, 0xa2000408, + 0xd8009f08, 0x17c07c1f, 0xc0c02de0, 0x17c07c1f, 0xc180ca40, 0x17c07c1f, + 0x18d0001f, 0x10227610, 0x82171803, 0x1207201f, 0x80569803, 0x1046841f, + 0xa2000408, 0xd800a068, 0x17c07c1f, 0xc180c820, 0x17c07c1f, 0xd000bd40, + 0x17c07c1f, 0x2060140a, 0xd820a241, 0x17c07c1f, 0xc0c0d260, 0x17c07c1f, + 0xc0c06ba0, 0x17c07c1f, 0x1800001f, 0x00000001, 0xc0002960, 0x17c07c1f, + 0xd000b120, 0x17c07c1f, 0xc0c068c0, 0x17c07c1f, 0xc2400cc0, 0x17c07c1f, + 0x68600009, 0x00000001, 0xd820a3c1, 0x17c07c1f, 0xc0c0d260, 0x17c07c1f, + 0xd000a400, 0x17c07c1f, 0xc180c820, 0x17c07c1f, 0x1800001f, 0x00000002, + 0xc0002960, 0x17c07c1f, 0xd000b120, 0x17c07c1f, 0x2060140a, 0xd820aaa1, + 0x17c07c1f, 0xc1400000, 0x17c07c1f, 0xc2800440, 0x17c07c1f, 0x6060140a, + 0xd820a741, 0x17c07c1f, 0xc0c0d260, 0x17c07c1f, 0xc0c072c0, 0x17c07c1f, + 0x1800001f, 0x00000003, 0xc0002960, 0x17c07c1f, 0xd000b120, 0x17c07c1f, + 0x2060140a, 0xd820a921, 0x17c07c1f, 0xc0c0d260, 0x17c07c1f, 0xc0c06ba0, + 0x17c07c1f, 0xc0c072c0, 0x17c07c1f, 0x1800001f, 0x00000004, 0xc0002960, + 0x17c07c1f, 0xd000b120, 0x17c07c1f, 0xc0c068c0, 0x17c07c1f, 0xc0c0d260, + 0x17c07c1f, 0xc0c072c0, 0x17c07c1f, 0x1800001f, 0x00000005, 0xc0002960, + 0x17c07c1f, 0xd000b120, 0x17c07c1f, 0xc1400000, 0x17c07c1f, 0xc2800440, + 0x17c07c1f, 0x6060140a, 0xd820ae01, 0x17c07c1f, 0xc0c06e80, 0x17c07c1f, + 0xc2400da0, 0x17c07c1f, 0x68600009, 0x00000001, 0xd820ad01, 0x17c07c1f, + 0xc0c0d260, 0x17c07c1f, 0xd000ad40, 0x17c07c1f, 0xc180ca40, 0x17c07c1f, + 0x1800001f, 0x00000006, 0xc0002960, 0x17c07c1f, 0xd000b120, 0x17c07c1f, + 0x2060140a, 0xd820afe1, 0x17c07c1f, 0xc0c06e80, 0x17c07c1f, 0xc0c0d260, + 0x17c07c1f, 0xc0c06ba0, 0x17c07c1f, 0x1800001f, 0x00000007, 0xc0002960, + 0x17c07c1f, 0xd000b120, 0x17c07c1f, 0xc0c068c0, 0x17c07c1f, 0xc0c06e80, + 0x17c07c1f, 0xc0c0d260, 0x17c07c1f, 0x1800001f, 0x00000008, 0xc0002960, + 0x17c07c1f, 0xc0c02de0, 0x17c07c1f, 0xc2800440, 0x17c07c1f, 0xc28000e0, + 0x17c07c1f, 0xc2800660, 0x17c07c1f, 0xc2800300, 0x17c07c1f, 0x1810001f, + 0x10227150, 0x1840001f, 0x0011c000, 0x1890001f, 0x10227608, 0x00c00801, + 0xe0c00000, 0x08800002, 0x0000000c, 0x79200002, 0x00000f70, 0xd800b464, + 0x17c07c1f, 0x1880001f, 0x00000340, 0x18c0001f, 0x10227608, 0xe0c00002, + 0x1a90001f, 0x1022741c, 0x1295a81f, 0x1990001f, 0x1022761c, 0x89800006, + 0x00000070, 0x1191981f, 0xa280180a, 0x1183981f, 0x1940001f, 0x0011c048, + 0x02319805, 0x1a700008, 0x17c07c1f, 0x8a400009, 0x0000007f, 0xa280240a, + 0x1890001f, 0x1022760c, 0x00c00801, 0xe0c0000a, 0x08800002, 0x0000000c, + 0x79200002, 0x00000f74, 0xd800b884, 0x17c07c1f, 0x1880001f, 0x00000344, + 0x18c0001f, 0x1022760c, 0xe0c00002, 0x1a90001f, 0x10227420, 0x1295a81f, + 0x1990001f, 0x1022761c, 0x89800006, 0x00700000, 0x1186981f, 0xa280180a, + 0x1183981f, 0x1940001f, 0x0011c0d8, 0x02319805, 0x1a700008, 0x17c07c1f, + 0x8a400009, 0x0000007f, 0xa280240a, 0x1890001f, 0x10227424, 0x00c00801, + 0xe0c0000a, 0x08800002, 0x0000000c, 0x79200002, 0x00000f78, 0xd800bca4, + 0x17c07c1f, 0x1880001f, 0x00000348, 0x18c0001f, 0x10227424, 0xe0c00002, + 0x1980001f, 0x00000001, 0xc1800b80, 0x17c07c1f, 0xc1800960, 0x17c07c1f, + 0x1840001f, 0x0011c324, 0x18d0001f, 0x1022761c, 0xe0400003, 0x1840001f, + 0x0011c328, 0x18d0001f, 0x10227618, 0xe0400003, 0x1840001f, 0x0011c32c, + 0x18d0001f, 0x10227614, 0xe0400003, 0x1b80001f, 0x20003365, 0xd0008220, + 0x17c07c1f, 0xf0000000, 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x0000000f, + 0x12c02c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, + 0x000f0000, 0x12c82c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, + 0x8ac0000b, 0x000000f0, 0x12c22c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, + 0x10227618, 0x8ac0000b, 0x00f00000, 0x12ca2c1f, 0xf0000000, 0x17c07c1f, + 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x00000f00, 0x12c42c1f, 0xf0000000, + 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x0f000000, 0x12cc2c1f, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, 0x00001000, + 0x12c62c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, + 0x10000000, 0x12ce2c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, + 0x8ac0000b, 0x00002000, 0x12c6ac1f, 0xf0000000, 0x17c07c1f, 0x1850001f, + 0x10227618, 0x88400001, 0xffffdfff, 0xa056ac01, 0x18c0001f, 0x10227618, + 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x10227618, 0x8ac0000b, + 0x20000000, 0x12ceac1f, 0xf0000000, 0x17c07c1f, 0x1850001f, 0x10227618, + 0x88400001, 0xdfffffff, 0xa05eac01, 0x18c0001f, 0x10227618, 0xe0c00001, + 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x8ac0000b, 0x000000f0, + 0x12c22c1f, 0xf0000000, 0x17c07c1f, 0x1ad0001f, 0x1022761c, 0x8ac0000b, + 0x00f00000, 0x12ca2c1f, 0xf0000000, 0x17c07c1f, 0x18c0001f, 0x0011c048, + 0x00f1ac03, 0x1af00003, 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0x18c0001f, + 0x0011c0d8, 0x00f1ac03, 0x1af00003, 0x17c07c1f, 0xf0000000, 0x17c07c1f, + 0x1ad0001f, 0x1022761c, 0x8ac0000b, 0x7f000000, 0x12cc2c1f, 0xf0000000, + 0x17c07c1f, 0x1850001f, 0x1022761c, 0x88400001, 0x80ffffff, 0xa05c2c01, + 0x18c0001f, 0x1022761c, 0xe0c00001, 0xf0000000, 0x17c07c1f, 0x1850001f, + 0x1022761c, 0x88400001, 0xffff80ff, 0xa0542c01, 0x18c0001f, 0x1022761c, + 0xe0c00001, 0xf0000000, 0x17c07c1f, 0xc200cb80, 0x17c07c1f, 0xc200cd40, + 0x17c07c1f, 0x88000008, 0x00003f80, 0x1003801f, 0x8a000008, 0x0000007f, + 0xc100cc60, 0x17c07c1f, 0xc100ce20, 0x17c07c1f, 0x8a400004, 0x00003f80, + 0x1243a41f, 0x89000004, 0x0000007f, 0x20601008, 0xd820d541, 0x17c07c1f, + 0x1100201f, 0x1240001f, 0xc080cf00, 0x17c07c1f, 0x28600004, 0x00000058, + 0xd820d641, 0x17c07c1f, 0x1900001f, 0x00000058, 0x48600004, 0x00000020, + 0xd820d701, 0x17c07c1f, 0x1900001f, 0x00000020, 0x60600804, 0xd820d7a1, + 0x17c07c1f, 0xd000df40, 0x17c07c1f, 0x20600804, 0xd820db41, 0x17c07c1f, + 0x1200081f, 0x60602004, 0xd820d8c1, 0x17c07c1f, 0xd000df40, 0x17c07c1f, + 0x0a000008, 0x0000000c, 0x20601008, 0xd820d981, 0x17c07c1f, 0x1200101f, + 0x08000008, 0x00000010, 0x20602400, 0xd820da41, 0x17c07c1f, 0x1000241f, + 0xc000e7e0, 0x17c07c1f, 0xc200e040, 0x17c07c1f, 0x1b80001f, 0x20000300, + 0xd000d820, 0x17c07c1f, 0x1200081f, 0x60602004, 0xd820dc01, 0x17c07c1f, + 0xd000df40, 0x17c07c1f, 0x0a200008, 0x0000000c, 0x40601008, 0xd820dcc1, + 0x17c07c1f, 0x1200101f, 0xc200e040, 0x17c07c1f, 0x08000008, 0x00000010, + 0x40602400, 0xd820ddc1, 0x17c07c1f, 0x1000241f, 0x28600000, 0x00000058, + 0xd820de81, 0x17c07c1f, 0x1800001f, 0x00000058, 0xc000e7e0, 0x17c07c1f, + 0x1b80001f, 0x20000300, 0xd000db60, 0x17c07c1f, 0xc100cfe0, 0x17c07c1f, + 0xc100d120, 0x17c07c1f, 0x1800001f, 0x00000000, 0xf0000000, 0x17c07c1f, + 0xe8208000, 0x1100f004, 0x000000d6, 0xe8208000, 0x1100f008, 0x000000f8, + 0xe8208000, 0x1100f010, 0x00000028, 0xe8208000, 0x1100f014, 0x00000002, + 0xe8208000, 0x1100f018, 0x00000001, 0xe8208000, 0x1100f01c, 0x00000002, + 0xe8208000, 0x1100f020, 0x00001001, 0xe8208000, 0x1100f028, 0x00001800, + 0xe8208000, 0x1100f040, 0x00000000, 0xe8208000, 0x1100f048, 0x00000102, + 0xe8208000, 0x1100f054, 0x00000000, 0xe8208000, 0x1100f06c, 0x00000000, + 0x1840001f, 0x1100f000, 0xe060008e, 0xe040000b, 0xe8208000, 0x1100f024, + 0x00000001, 0x18d0001f, 0x1100f00c, 0x88c00003, 0x00000007, 0xd820e5a3, + 0x17c07c1f, 0x1840001f, 0x1100f00c, 0xe0400003, 0x18c0001f, 0x0011c310, + 0x1850001f, 0x0011c310, 0x1054041f, 0xa0402c01, 0xe0c00001, 0xf0000000, + 0x17c07c1f, 0xe8208000, 0x10006428, 0x00000001, 0x18d0001f, 0x10006428, + 0xd820e7e3, 0x17c07c1f, 0x1840001f, 0x1000d14c, 0xe06006aa, 0x1840001f, + 0x1000d150, 0xe040000b, 0x1840001f, 0x10006400, 0xe0600008, 0x1850001f, + 0x10006400, 0x104f841f, 0xd820e9e1, 0x17c07c1f, 0xe8208000, 0x10006428, + 0x00000001, 0x18c0001f, 0x0011c314, 0x1850001f, 0x0011c314, 0x1054041f, + 0xa0402c01, 0xe0c00001, 0xf0000000, 0x17c07c1f +}; +static struct pcm_desc dvfs_pcm = { + .version = "pcm_dvfs_v0.1_150806_09", + .base = dvfs_binary, + .size = 1888, + .sess = 2, + .replace = 0, + .addr_2nd = 0, +}; +#endif + +#endif /* _MT_CPUFREQ_HYBRID_FW_ */ diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_dcm.c b/drivers/misc/mediatek/base/power/mt6755/mt_dcm.c new file mode 100644 index 0000000000000000000000000000000000000000..f4ea39bfba9b0317de3103f9e52f87d528dc5d76 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_dcm.c @@ -0,0 +1,1945 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt_dcm.h" +#include +#include +#include +#include + +/* #define DCM_DEFAULT_ALL_OFF */ + +#if defined(CONFIG_OF) +static unsigned long topckgen_base; +static unsigned long mcucfg_base; +static unsigned long mcucfg_phys_base; +static unsigned long dramc_ao_base; +static unsigned long emi_reg_base; +static unsigned long infracfg_ao_base; +/* static unsigned long pericfg_base; */ +/* static unsigned long apmixed_base; */ +static unsigned long ddrphy_base; + +#define MCUCFG_NODE "mediatek,mcucfg" +#define INFRACFG_AO_NODE "mediatek,infracfg_ao" +#define TOPCKGEN_NODE "mediatek,topckgen" +#define EMI_REG_NODE "mediatek,emi" + +#undef INFRACFG_AO_BASE +#undef MCUCFG_BASE +#undef TOPCKGEN_BASE +#define INFRACFG_AO_BASE (infracfg_ao_base) /* 0xF0000000 */ +#define MCUCFG_BASE (mcucfg_base) /* 0xF0200000 */ +#define TOPCKGEN_BASE (topckgen_base) /* 0xF0210000 */ +#if 0 +#define PERICFG_BASE (pericfg_base) /* 0xF0002000 */ +#endif +#define DRAMC_AO_BASE (dramc_ao_base) /* 0xF0214000 */ +#define EMI_REG_BASE (emi_reg_base) /* 0xF0203000 */ +/* #define APMIXED_BASE (apmixed_base) //0x10209000 */ +#define DDRPHY_BASE (ddrphy_base) /* 0xF0213000 */ + +#else /* !defined(CONFIG_OF) */ +#undef INFRACFG_AO_BASE +#undef MCUCFG_BASE +#undef TOPCKGEN_BASE +#define INFRACFG_AO_BASE 0xF0000000 +#define MCUCFG_BASE 0xF0200000 +#define TOPCKGEN_BASE 0xF0210000 +/* #define PERICFG_BASE 0xF0002000 */ +#define DRAMC_AO_BASE 0xF0214000 +#define EMI_REG_BASE 0xF0203000 +/* #define APMIXED_BASE 0xF0209000 */ +#define DDRPHY_BASE 0xF0213000 +#endif /* #if defined(CONFIG_OF) */ + +/* MCUCFG registers */ +#define MCUCFG_L2C_SRAM_CTRL (MCUCFG_BASE + 0x648) /* 0x10200648 */ +#define MCUCFG_CCI_CLK_CTRL (MCUCFG_BASE + 0x660) /* 0x10200660 */ +#define MCUCFG_BUS_FABRIC_DCM_CTRL (MCUCFG_BASE + 0x668) /* 0x10200668 */ +#define MCUCFG_CCI_ADB400_DCM_CONFIG (MCUCFG_BASE + 0x740) /* 0x10200740 */ +#define MCUCFG_SYNC_DCM_CONFIG (MCUCFG_BASE + 0x744) /* 0x10200744 */ +#define MCUCFG_SYNC_DCM_CLUSTER_CONFIG (MCUCFG_BASE + 0x74C) /* 0x1020074C */ + +#define MCUCFG_L2C_SRAM_CTRL_PHYS (mcucfg_phys_base + 0x648) /* 0x10200648 */ +#define MCUCFG_CCI_CLK_CTRL_PHYS (mcucfg_phys_base + 0x660) /* 0x10200660 */ +#define MCUCFG_BUS_FABRIC_DCM_CTRL_PHYS (mcucfg_phys_base + 0x668) /* 0x10200668 */ +#define MCUCFG_CCI_ADB400_DCM_CONFIG_PHYS (mcucfg_phys_base + 0x740) /* 0x10200740 */ +#define MCUCFG_SYNC_DCM_CONFIG_PHYS (mcucfg_phys_base + 0x744) /* 0x10200744 */ +#define MCUCFG_SYNC_DCM_CLUSTER_CONFIG_PHYS (mcucfg_phys_base + 0x74C) /* 0x1020074C */ + +/* INFRASYS_AO */ +#define TOP_CKMUXSEL (INFRACFG_AO_BASE + 0x000) /* 0x10001000 */ +#define INFRA_TOPCKGEN_CKDIV1_BIG (INFRACFG_AO_BASE + 0x024) /* 0x10001024 */ +#define INFRA_TOPCKGEN_CKDIV1_SML (INFRACFG_AO_BASE + 0x028) /* 0x10001028 */ +#define INFRA_TOPCKGEN_CKDIV1_BUS (INFRACFG_AO_BASE + 0x02C) /* 0x1000102C */ +#define TOP_DCMCTL (INFRACFG_AO_BASE + 0x010) /* 0x10001010 */ +#define INFRA_BUS_DCM_CTRL (INFRACFG_AO_BASE + 0x070) /* 0x10001070 */ +#define PERI_BUS_DCM_CTRL (INFRACFG_AO_BASE + 0x074) /* 0x10001074 */ +#define P2P_RX_CLK_ON (INFRACFG_AO_BASE + 0x0a0) /* 0x100010a0 */ +#define INFRA_MISC (INFRACFG_AO_BASE + 0xf00) /* 0x10001f00 */ +#define INFRA_MISC_1 (INFRACFG_AO_BASE + 0xf0c) /* 0x10001f0c */ + +/* TOPCKGEN */ +#define TOPCKG_CLK_MISC_CFG_0 (TOPCKGEN_BASE + 0x104) /* 0x10000104 */ + +#if 0 +/* perisys */ +#define PERI_GLOBALCON_DCMCTL (PERICFG_BASE + 0x050) /* 0x10002050 */ +#define PERI_GLOBALCON_DCMDBC (PERICFG_BASE + 0x054) /* 0x10002054 */ +#define PERI_GLOBALCON_DCMFSEL (PERICFG_BASE + 0x058) /* 0x10002058 */ +#endif /* 0 */ + +/* DRAMC_AO */ +#define DRAMC_GDDR3CTL1 (DRAMC_AO_BASE + 0x0f4) /* 0x100040f4 */ +#define DRAMC_CLKCTRL (DRAMC_AO_BASE + 0x130) /* 0x10004130 */ +#define DRAMC_PD_CTRL (DRAMC_AO_BASE + 0x1dc) /* 0x100041dc */ +#define DRAMC_PERFCTL0 (DRAMC_AO_BASE + 0x1ec) /* 0x100041ec */ + +/* ddrphy */ +#define DDRPHY_CG_CTRL (DDRPHY_BASE + 0x63c) /* 0x1000f63c */ + +/* EMI */ +#define EMI_CONM (EMI_REG_BASE + 0x060) /* 0x10203060 */ + +#define TAG "[Power/dcm] " +/* #define DCM_ENABLE_DCM_CFG */ +#define dcm_err(fmt, args...) pr_err(TAG fmt, ##args) +#define dcm_warn(fmt, args...) pr_warn(TAG fmt, ##args) +#define dcm_info(fmt, args...) pr_warn(TAG fmt, ##args) +#define dcm_dbg(fmt, args...) pr_debug(TAG fmt, ##args) +#define dcm_ver(fmt, args...) pr_debug(TAG fmt, ##args) + +/** macro **/ +#define and(v, a) ((v) & (a)) +#define or(v, o) ((v) | (o)) +#define aor(v, a, o) (((v) & (a)) | (o)) + +#define reg_read(addr) __raw_readl(IOMEM(addr)) +#define reg_write(addr, val) mt_reg_sync_writel((val), ((void *)addr)) + +#if defined(CONFIG_ARM_PSCI) || defined(CONFIG_MTK_PSCI) +#define MCUSYS_SMC_WRITE(addr, val) mcusys_smc_write_phy(addr##_PHYS, val) +#else +#define MCUSYS_SMC_WRITE(addr, val) mcusys_smc_write(addr, val) +#endif + +#define REG_DUMP(addr) dcm_info("%-30s(0x%08lx): 0x%08x\n", #addr, addr, reg_read(addr)) + +#define DCM_OFF (0) +#define DCM_ON (1) + +/* #define DCM_DEBUG */ + +/** global **/ +static DEFINE_MUTEX(dcm_lock); +static unsigned int dcm_initiated; + +/***************************************** + * following is implementation per DCM module. + * 1. per-DCM function is 1-argu with ON/OFF/MODE option. + *****************************************/ +typedef int (*DCM_FUNC)(int); +typedef void (*DCM_PRESET_FUNC)(void); + +/* + * INFRACFG_AO DCM golden setting --------------------------------------------- + */ +/* + * 0x10001010 TOP_DCMCTL "0: Disable,1: Enable" + * 0 0 infra_dcm_enable + * 1 1 armpll_dcm_enable_big + * 2 2 armpll_dcm_enable_sml + * 3 3 armpll_dcm_enable_bus + * 12 12 armpll_dcm_wfi_enable_big + * 13 13 armpll_dcm_wfi_enable_sml + * 14 14 armpll_dcm_wfi_enable_bus + * 16 16 armpll_dcm_wfe_enable_big + * 17 17 armpll_dcm_wfe_enable_sml + * 18 18 armpll_dcm_wfe_enable_bus + */ +#define INFRA_TOP_DCMCTL_MODE1_MASK ((0x1 << 1) | (0x1 << 2) | (0x1 << 3)) +#define INFRA_TOP_DCMCTL_MODE1_ON ((0x1 << 1) | (0x1 << 2) | (0x1 << 3)) +#define INFRA_TOP_DCMCTL_MODE1_OFF ((0x0 << 1) | (0x0 << 2) | (0x0 << 3)) +#define INFRA_TOP_DCMCTL_MODE2_MASK ((0x1 << 12) | (0x1 << 13) | \ + (0x1 << 14) | (0x1 << 16) | \ + (0x1 << 17) | (0x1 << 18)) +#define INFRA_TOP_DCMCTL_MODE2_ON ((0x1 << 12) | (0x1 << 13) | \ + (0x1 << 14) | (0x1 << 16) | \ + (0x1 << 17) | (0x1 << 18)) +#define INFRA_TOP_DCMCTL_MODE2_OFF ((0x0 << 12) | (0x0 << 13) | \ + (0x0 << 14) | (0x0 << 16) | \ + (0x0 << 17) | (0x0 << 18)) + +typedef enum { + ARMCORE_DCM_OFF = DCM_OFF, + ARMCORE_DCM_MODE1 = DCM_ON, + ARMCORE_DCM_MODE2 = DCM_ON+1, +} ENUM_ARMCORE_DCM; + +int dcm_armcore(ENUM_ARMCORE_DCM mode) +{ + if (mode == ARMCORE_DCM_OFF) { + reg_write(TOP_DCMCTL, + aor(reg_read(TOP_DCMCTL), + ~(INFRA_TOP_DCMCTL_MODE1_MASK | + INFRA_TOP_DCMCTL_MODE2_MASK), + (INFRA_TOP_DCMCTL_MODE1_OFF | + INFRA_TOP_DCMCTL_MODE2_OFF))); + + return 0; + } + + if (mode == ARMCORE_DCM_MODE2) { + reg_write(TOP_DCMCTL, + aor(reg_read(TOP_DCMCTL), + ~(INFRA_TOP_DCMCTL_MODE1_MASK | + INFRA_TOP_DCMCTL_MODE2_MASK), + (INFRA_TOP_DCMCTL_MODE1_OFF | + INFRA_TOP_DCMCTL_MODE2_ON))); + } else if (mode == ARMCORE_DCM_MODE1) { + reg_write(TOP_DCMCTL, + aor(reg_read(TOP_DCMCTL), + ~(INFRA_TOP_DCMCTL_MODE1_MASK | + INFRA_TOP_DCMCTL_MODE2_MASK), + (INFRA_TOP_DCMCTL_MODE1_ON | + INFRA_TOP_DCMCTL_MODE2_OFF))); + } + + return 0; +} + +/* + * 0x0000 TOP_CKMUXSEL: Switch clock source for ARMPLL + * 5 4 armpll_mux1_sel_big 4'b0 Sel Big cluster ARMBPLL clk MUX 1 + * "00: CLKSQ(26M),01: ARMBPLL_1700M,10: MAINPLL_1092M,11: UNIVPLL_624M" + * 9 8 armpll_mux1_sel_sml 4'b0 Sel Small cluster ARMSPLL clk MUX 1 + * "00: CLKSQ(26M),01: ARMSPLL_1000M,10: MAINPLL_1092M,11: UNIVPLL_624M" + * 13 12 armpll_mux1_sel_bus 4'b0 Sel CCI clock MUX 1 + * "00: CLKSQ(26M),01: ARMBPLL_1700M,10: ARMSPLL_1000M,11: CLKSQ (26M)" + */ +#define INFRA_TOP_CKMUXSEL_MASK ((0x2 << 4) | (0x2 << 8) | (0x2 << 12)) + +/* + * 0x0024 INFRA_TOPCKGEN_CKDIV1_BIG: Big cluster ARMBPLL clock divider 1 + * 4 0 ckdiv1_divsel_big 5'b0 (5'b00000~5'b11111) + */ +/* + * 0x0028 INFRA_TOPCKGEN_CKDIV1_SML: Small cluster ARMSPLL clock divider 1 + * 4 0 ckdiv1_divsel_sml 5'b0 (5'b00000~5'b11111) + */ +/* + * 0x002C INFRA_TOPCKGEN_CKDIV1_BUS: CCI clock divider 1 + * 4 0 ckdiv1_divsel_bus 5'b0 (5'b00000~5'b11111) + */ +#define INFRA_TOPCKGEN_CKDIV1_MASK (0x1F << 0) +/* + * 0x10000104 CLK_MISC_CFG_0 32 miscellanenous control (TOPCKGEN) + * 4 4 armpll_divider_pll1_ck_en RW PUBLIC 0 1: Enable clock (MAINPLL) + * 5 5 armpll_divider_pll2_ck_en RW PUBLIC 0 1: Enable clock (UNIVPLL) + */ +#define TOPCKG_CLK_MISC_CFG_0_MAINPLL_MASK (0x1 << 4) +#define TOPCKG_CLK_MISC_CFG_0_MAINPLL_EN TOPCKG_CLK_MISC_CFG_0_MAINPLL_MASK +#define TOPCKG_CLK_MISC_CFG_0_MAINPLL_DIS (0x0 << 4) +#define TOPCKG_CLK_MISC_CFG_0_UNIVPLL_MASK (0x1 << 5) +#define TOPCKG_CLK_MISC_CFG_0_UNIVPLL_EN TOPCKG_CLK_MISC_CFG_0_UNIVPLL_MASK +#define TOPCKG_CLK_MISC_CFG_0_UNIVPLL_DIS (0x0 << 5) + +int dcm_armcore_pll_big_clkdiv(int pll, int div) +{ + if (pll < 0 || pll > 3 || div < 0 || div > 31) + BUG_ON(1); + + if (pll == 2) + reg_write(TOPCKG_CLK_MISC_CFG_0, + aor(reg_read(TOPCKG_CLK_MISC_CFG_0), + ~TOPCKG_CLK_MISC_CFG_0_MAINPLL_MASK, + TOPCKG_CLK_MISC_CFG_0_MAINPLL_EN)); + else if (pll == 3) + reg_write(TOPCKG_CLK_MISC_CFG_0, + aor(reg_read(TOPCKG_CLK_MISC_CFG_0), + ~TOPCKG_CLK_MISC_CFG_0_UNIVPLL_MASK, + TOPCKG_CLK_MISC_CFG_0_UNIVPLL_EN)); + else + reg_write(TOPCKG_CLK_MISC_CFG_0, + aor(reg_read(TOPCKG_CLK_MISC_CFG_0), + ~(TOPCKG_CLK_MISC_CFG_0_MAINPLL_MASK | + TOPCKG_CLK_MISC_CFG_0_UNIVPLL_MASK), + (TOPCKG_CLK_MISC_CFG_0_MAINPLL_DIS | + TOPCKG_CLK_MISC_CFG_0_UNIVPLL_DIS))); + reg_write(TOP_CKMUXSEL, + aor(reg_read(TOP_CKMUXSEL), + ~INFRA_TOP_CKMUXSEL_MASK, + (pll << 4))); + reg_write(INFRA_TOPCKGEN_CKDIV1_BIG, + aor(reg_read(INFRA_TOPCKGEN_CKDIV1_BIG), + ~INFRA_TOPCKGEN_CKDIV1_MASK, div << 0)); + + return 0; +} + +int dcm_armcore_pll_sml_clkdiv(int pll, int div) +{ + if (pll < 0 || pll > 3 || div < 0 || div > 31) + BUG_ON(1); + + if (pll == 2) + reg_write(TOPCKG_CLK_MISC_CFG_0, + aor(reg_read(TOPCKG_CLK_MISC_CFG_0), + ~TOPCKG_CLK_MISC_CFG_0_MAINPLL_MASK, + TOPCKG_CLK_MISC_CFG_0_MAINPLL_EN)); + else if (pll == 3) + reg_write(TOPCKG_CLK_MISC_CFG_0, + aor(reg_read(TOPCKG_CLK_MISC_CFG_0), + ~TOPCKG_CLK_MISC_CFG_0_UNIVPLL_MASK, + TOPCKG_CLK_MISC_CFG_0_UNIVPLL_EN)); + else + reg_write(TOPCKG_CLK_MISC_CFG_0, + aor(reg_read(TOPCKG_CLK_MISC_CFG_0), + ~(TOPCKG_CLK_MISC_CFG_0_MAINPLL_MASK | + TOPCKG_CLK_MISC_CFG_0_UNIVPLL_MASK), + (TOPCKG_CLK_MISC_CFG_0_MAINPLL_DIS | + TOPCKG_CLK_MISC_CFG_0_UNIVPLL_DIS))); + reg_write(TOP_CKMUXSEL, + aor(reg_read(TOP_CKMUXSEL), + ~INFRA_TOP_CKMUXSEL_MASK, + (pll << 8))); + reg_write(INFRA_TOPCKGEN_CKDIV1_SML, + aor(reg_read(INFRA_TOPCKGEN_CKDIV1_SML), + ~INFRA_TOPCKGEN_CKDIV1_MASK, div << 0)); + + return 0; +} + +int dcm_armcore_pll_bus_clkdiv(int pll, int div) +{ + if (pll < 0 || pll > 3 || div < 0 || div > 31) + BUG_ON(1); + + reg_write(TOP_CKMUXSEL, + aor(reg_read(TOP_CKMUXSEL), + ~INFRA_TOP_CKMUXSEL_MASK, + (pll << 12))); + reg_write(INFRA_TOPCKGEN_CKDIV1_BUS, + aor(reg_read(INFRA_TOPCKGEN_CKDIV1_BUS), + ~INFRA_TOPCKGEN_CKDIV1_MASK, div << 0)); + + return 0; +} + +/* + * 0x10001010 TOP_DCMCTL + * 0 0 infra_dcm_enable + * this field actually is to activate clock ratio between infra/fast_peri/slow_peri. + * and need to set when bus clock switch from CLKSQ to PLL. + * do ASSERT, for each time infra/peri bus dcm setting. + */ +#define ASSERT_INFRA_DCMCTL() \ + do { \ + volatile unsigned int dcmctl; \ + dcmctl = reg_read(TOP_DCMCTL); \ + BUG_ON(!(dcmctl & 1)); \ + } while (0) + +/* + * 0x10001070 INFRA_BUS_DCM_CTRL + * 0 0 infra_dcm_rg_clkoff_en + * 1 1 infra_dcm_rg_clkslow_en + * 2 2 infra_dcm_rg_force_clkoff + * 3 3 infra_dcm_rg_force_clkslow + * 4 4 infra_dcm_rg_force_on + * 9 5 infra_dcm_rg_fsel 5'h1f off:0x10,on:0x10 Selects Infra DCM active divide + * 14 10 infra_dcm_rg_sfsel 5'h1f off:0x10,on:0 Selecs Infra DCM idle divide + * 19 15 infra_dcm_dbc_rg_dbc_num 5'h10 Infra DCM de-bounce number + * 20 20 infra_dcm_dbc_rg_dbc_en + * 21 21 rg_axi_dcm_dis_en 1'b0 keep default + * 22 22 rg_pllck_sel_no_spm 1'b0 keep default + */ +#define INFRA_BUS_DCM_CTRL_MASK ((0x3 << 0) | (0x7 << 2) | (0x1 << 20)) +#define INFRA_BUS_DCM_CTRL_EN ((0x3 << 0) | (0x0 << 2) | (0x1 << 20)) +#define INFRA_BUS_DCM_CTRL_DIS ((0x0 << 0) | (0x0 << 2) | (0x0 << 20)) +#define INFRA_BUS_DCM_CTRL_SEL_MASK ((0x1F << 5) | (0x1F << 10)) +#define INFRA_BUS_DCM_CTRL_SEL_EN ((0x10 << 5) | (0x0 << 10)) + +/* + * 0x100010a0 P2P_RX_CLK_ON + * 3 0 p2p_rx_clk_force_on 4'b1111 "0: Dies not force, 1: Force" + */ +#define P2P_RX_CLK_ON_MASK (0xF<<0) +#define P2P_RX_CLK_ON_EN (0<<0) +#define P2P_RX_CLK_ON_DIS (0xF<<0) + +/* + * 0x10001f00 INFRA_MISC 32 + * 28 28 infra_md_fmem_dcm_en 1'b0 "0: disable INFRA_MD DCM, 1: Enable it" + */ +#define INFRA_MISC_MASK (1<<28) +#define INFRA_MISC_EN (1<<28) +#define INFRA_MISC_DIS (0<<28) + +/* + * 0x10001F0C INFRA_MISC_1 32 Infrasys Miscellaneous Control Register + * 24 24 topaxi_second_level_dcm_mask_reg 1'b1 "0: enable fine-grained DCM, 1: mask it" + */ +#define INFRA_MISC_1_MASK (1<<24) +#define INFRA_MISC_1_EN (0<<24) +#define INFRA_MISC_1_DIS (1<<24) + +typedef enum { + INFRA_DCM_OFF = DCM_OFF, + INFRA_DCM_ON = DCM_ON, +} ENUM_INFRA_DCM; + +int dcm_infra(ENUM_INFRA_DCM on) +{ + /* ASSERT_INFRA_DCMCTL(); */ + + if (on) { + reg_write(INFRA_BUS_DCM_CTRL, aor(reg_read(INFRA_BUS_DCM_CTRL), + ~INFRA_BUS_DCM_CTRL_MASK, + INFRA_BUS_DCM_CTRL_EN)); + reg_write(P2P_RX_CLK_ON, aor(reg_read(P2P_RX_CLK_ON), + ~P2P_RX_CLK_ON_MASK, + P2P_RX_CLK_ON_EN)); + reg_write(INFRA_MISC, aor(reg_read(INFRA_MISC), + ~INFRA_MISC_MASK, + INFRA_MISC_EN)); + reg_write(INFRA_MISC_1, aor(reg_read(INFRA_MISC_1), + ~INFRA_MISC_1_MASK, + INFRA_MISC_1_EN)); + } else { + reg_write(INFRA_BUS_DCM_CTRL, aor(reg_read(INFRA_BUS_DCM_CTRL), + ~INFRA_BUS_DCM_CTRL_MASK, + INFRA_BUS_DCM_CTRL_DIS)); + reg_write(P2P_RX_CLK_ON, aor(reg_read(P2P_RX_CLK_ON), + ~P2P_RX_CLK_ON_MASK, + P2P_RX_CLK_ON_DIS)); + reg_write(INFRA_MISC, aor(reg_read(INFRA_MISC), + ~INFRA_MISC_MASK, + INFRA_MISC_DIS)); + reg_write(INFRA_MISC_1, aor(reg_read(INFRA_MISC_1), + ~INFRA_MISC_1_MASK, + INFRA_MISC_1_DIS)); + } + + return 0; +} + +int dcm_infra_dbc(int cnt) +{ + reg_write(INFRA_BUS_DCM_CTRL, aor(reg_read(INFRA_BUS_DCM_CTRL), + ~(0x1f << 15), (cnt << 15))); + + return 0; +} + +/* + * input argument + * 0: 1/1 + * 1: 1/2 + * 2: 1/4 + * 3: 1/8 + * 4: 1/16 + * 5: 1/32 + * default: 0, 0 + */ +int dcm_infra_rate(unsigned int fsel, unsigned int sfsel) +{ + BUG_ON(fsel > 5 || sfsel > 5); + + fsel = 0x10 >> fsel; + sfsel = 0x10 >> sfsel; + + reg_write(INFRA_BUS_DCM_CTRL, aor(reg_read(INFRA_BUS_DCM_CTRL), + ~INFRA_BUS_DCM_CTRL_SEL_MASK, + ((fsel << 5) | (sfsel << 10)))); + + return 0; +} + +void dcm_infra_preset(void) +{ + reg_write(INFRA_BUS_DCM_CTRL, aor(reg_read(INFRA_BUS_DCM_CTRL), + ~INFRA_BUS_DCM_CTRL_SEL_MASK, + INFRA_BUS_DCM_CTRL_SEL_EN)); +} + +/* + * 0x10001074 PERI_BUS_DCM_CTRL + * 0 0 peri_dcm_rg_clkoff_en 1'b1 off: 0 on: 1 + * 1 1 peri_dcm_rg_clkslow_en 1'b0 off: 0 on: 1 + * 3 3 peri_dcm_rg_force_clkslow 1'b0 off: 0 on: 0 + * 4 4 peri_dcm_rg_force_on 1'b0 off: 0 on: 0 + * 9 5 peri_dcm_rg_fsel 5'h1f off: 0x1F on: 0x1F + * 14 10 peri_dcm_rg_sfsel 5'h1f off: 0x1F on: 0 + * 19 15 peri_dcm_dbc_rg_dbc_num 5'h10 off: 0 on: 0x1F + * 20 20 peri_dcm_dbc_rg_dbc_en 1'b1 off: 0 on: 1 + * 21 21 re_usb_dcm_en 1'b1 off: 0 on: 1 + * 22 22 re_pmic_dcm_en 1'b1 off: 0 on: 1 + * 27 23 pmic_cnt_mst_rg_sfsel 5'h08 off: 0 on: 0 + * 28 28 re_icusb_dcm_en 1'b0 off: 0 on: 1 + * 29 29 rg_audio_dcm_en 1'b0 off: 0 on: 1 + * 31 31 rg_ssusb_top_dcm_en 1'b0 off: 0 on: 1 + */ +#define PERI_DCM_MASK ((1<<0) | (1<<1) | (0x1F<<15) | (1<<20)) +#define PERI_DCM_EN ((1<<0) | (1<<1) | (0x1F<<15) | (1<<20)) +#define PERI_DCM_DIS ((0<<0) | (0<<1) | (0<<15) | (0<<20)) +#define PERI_DCM_SEL_MASK ((0x1F<<5) | (0x1F<<10)) +#define PERI_DCM_SEL_EN ((0x1F<<5) | (0<<10)) + +typedef enum { + PERI_DCM_OFF = DCM_OFF, + PERI_DCM_ON = DCM_ON, +} ENUM_PERI_DCM; + +int dcm_peri(ENUM_PERI_DCM on) +{ + if (on == PERI_DCM_ON) + reg_write(PERI_BUS_DCM_CTRL, aor(reg_read(PERI_BUS_DCM_CTRL), + ~PERI_DCM_MASK, + PERI_DCM_EN)); + else + reg_write(PERI_BUS_DCM_CTRL, aor(reg_read(PERI_BUS_DCM_CTRL), + ~PERI_DCM_MASK, + PERI_DCM_DIS)); + + return 0; +} + + +int dcm_peri_dbc(int cnt) +{ + reg_write(PERI_BUS_DCM_CTRL, aor(reg_read(PERI_BUS_DCM_CTRL), + ~(0x1f << 15), + (cnt << 15))); + + return 0; +} + +/* + * input argument + * 0: 1/1 + * 1: 1/2 + * 2: 1/4 + * 3: 1/8 + * 4: 1/16 + * 5: 1/32 + * default: 0, 0 + */ +int dcm_peri_rate(unsigned int fsel, unsigned int sfsel) +{ + BUG_ON(fsel > 5 || sfsel > 5); + + fsel = 0x10 >> fsel; + sfsel = 0x10 >> sfsel; + + reg_write(PERI_BUS_DCM_CTRL, aor(reg_read(PERI_BUS_DCM_CTRL), + ~PERI_DCM_SEL_MASK, + ((fsel << 5) | (sfsel << 10)))); + + return 0; +} + +void dcm_peri_preset(void) +{ + reg_write(PERI_BUS_DCM_CTRL, aor(reg_read(PERI_BUS_DCM_CTRL), + ~PERI_DCM_SEL_MASK, + PERI_DCM_SEL_EN)); +} + +/* + * 0x10001074 PERI_BUS_DCM_CTRL + * ... + * 21 21 re_usb_dcm_en 1'b1 off: 0 on: 1 + * 22 22 re_pmic_dcm_en 1'b1 off: 0 on: 1 + * 27 23 pmic_cnt_mst_rg_sfsel 5'h08 off: 0 on: 0 + * 28 28 re_icusb_dcm_en 1'b0 off: 0 on: 1 + * 29 29 rg_audio_dcm_en 1'b0 off: 0 on: 1 + * 31 31 rg_ssusb_top_dcm_en 1'b0 off: 0 on: 1 + */ +#define MISC_DCM_DEFAULT_MASK ((1<<21) | (1<<22) | (1<<28) | (1<<29) | (1<<31)) +#define MISC_USB_DCM_EN (1<<21) +#define MISC_PMIC_DCM_MASK ((1<<22) | (0x1F<<23)) +#define MISC_PMIC_DCM_EN ((1<<22) | (0<<23)) +#define MISC_PMIC_DCM_DIS ((0<<22) | (0<<23)) +#define MISC_ICUSB_DCM_EN (1<<28) +#define MISC_AUDIO_DCM_EN (1<<29) +#define MISC_SSUSB_DCM_EN (1<<31) + +typedef enum { + MISC_DCM_OFF = DCM_OFF, + PMIC_DCM_OFF = DCM_OFF, + USB_DCM_OFF = DCM_OFF, + ICUSB_DCM_OFF = DCM_OFF, + AUDIO_DCM_OFF = DCM_OFF, + SSUSB_DCM_OFF = DCM_OFF, + + MISC_DCM_ON = DCM_ON, + PMIC_DCM_ON = DCM_ON, + USB_DCM_ON = DCM_ON, + ICUSB_DCM_ON = DCM_ON, + AUDIO_DCM_ON = DCM_ON, + SSUSB_DCM_ON = DCM_ON, +} ENUM_MISC_DCM; + +/** argu REG, is 1-bit hot value **/ +int _dcm_peri_misc(unsigned int reg, int on) +{ + reg_write(PERI_BUS_DCM_CTRL, aor(reg_read(PERI_BUS_DCM_CTRL), + ~reg, (on) ? reg : 0)); + + return 0; +} + +int dcm_pmic(ENUM_MISC_DCM on) +{ + if (on == PMIC_DCM_ON) + reg_write(PERI_BUS_DCM_CTRL, aor(reg_read(PERI_BUS_DCM_CTRL), + ~MISC_PMIC_DCM_MASK, + MISC_PMIC_DCM_EN)); + else + reg_write(PERI_BUS_DCM_CTRL, aor(reg_read(PERI_BUS_DCM_CTRL), + ~MISC_PMIC_DCM_MASK, + MISC_PMIC_DCM_DIS)); + + return 0; +} + +int dcm_usb(ENUM_MISC_DCM on) +{ + _dcm_peri_misc(MISC_USB_DCM_EN, on); + + return 0; +} + +int dcm_icusb(ENUM_MISC_DCM on) +{ + _dcm_peri_misc(MISC_ICUSB_DCM_EN, on); + + return 0; +} + +int dcm_audio(ENUM_MISC_DCM on) +{ + _dcm_peri_misc(MISC_AUDIO_DCM_EN, on); + + return 0; +} + +int dcm_ssusb(ENUM_MISC_DCM on) +{ + _dcm_peri_misc(MISC_SSUSB_DCM_EN, on); + + return 0; +} + +/* + * MCUSYS DCM golden setting -------------------------------------------------- + */ +/* + * 0x0648 L2C_SRAM_CTRL + * 0 0 l2c_sram_dcm_en, L2C SRAM DCM enable, "0: Disable, 1: Enable" + */ +#define MCUCFG_L2C_SRAM_CTRL_MASK (0x1 << 0) +#define MCUCFG_L2C_SRAM_CTRL_ON (0x1 << 0) +#define MCUCFG_L2C_SRAM_CTRL_OFF (0x0 << 0) + +/* + * 0x0660 CCI_CLK_CTRL + * 8 8 MCU_BUS_DCM_EN "0: Disable, 1: Enable" + */ +#define MCUCFG_CCI_CLK_CTRL_MASK (0x1 << 8) +#define MCUCFG_CCI_CLK_CTRL_ON (0x1 << 8) +#define MCUCFG_CCI_CLK_CTRL_OFF (0x0 << 8) + +/* + * 0x0668 BUS_FABRIC_DCM_CTRL + * 0 0 ACLK_INFRA_dynamic_CG_en "0: disable, 1: enable" + * 1 1 EMI2_ADB400_S_DCM_CTRL "0: disable, 1: enable" + * 4 4 MP0_ADB400_S_DCM_CTRL "0: disable, 1: enable" + * 5 5 MP0_ADB400_M_DCM_CTRL "0: disable, 1: enable" + * 6 6 MP1_ADB400_S_DCM_CTRL "0: disable, 1: enable" + * 7 7 MP0_ADB400_M_DCM_CTRL "0: disable, 1: enable" + * 8 8 InfraCLK_INFRA_dynamic_CG_en "0: disable, 1: enable" + * 9 9 EMICLK_EMI_dynamic_CG_en "0: disable, 1: enable" + * 21 21 L2_Share_ADB400_DCM_CTRL "0: disable, 1: enable" + */ +#define MCUCFG_BUS_FABRIC_DCM_CTRL_MASK ((0x3 << 0) | (0x3F << 4) | (0x1 << 21)) +#define MCUCFG_BUS_FABRIC_DCM_CTRL_ON ((0x3 << 0) | (0x3F << 4) | (0x1 << 21)) +#define MCUCFG_BUS_FABRIC_DCM_CTRL_OFF ((0x0 << 0) | (0x0 << 4) | (0x0 << 21)) + +/* + * 0x0740 CCI_ADB400_DCM_CONFIG + * 0 0 cci_m0_adb400_dcm_en "0: disable, 1: enable" + * 2 2 cci_m2_adb400_dcm_en "0: disable, 1: enable" + * 5 5 cci_s3_adb400_dcm_en "0: disable, 1: enable" + * 6 6 cci_s4_adb400_dcm_en "0: disable, 1: enable" + * 7 7 l2c_adb400_dcm_en "0: disable, 1: enable" + * 16 16 cci_mst_dcm_en "0: disable, 1: enable" + * 17 17 cci_slv_dcm_en "0: disable, 1: enable" + * 18 18 cci400_mst_rw_dcm_en "0: disable, 1: enable" + * 19 19 cci400_slv_rw_dcm_en "0: disable, 1: enable" + * 24 24 cci400_top_stall_dcm_en "0: disable, 1: enable" + * 28 25 cci400_top_dbnc_cycle "default:4'hF, Debounce Value must >= 8" + */ +#define MCUCFG_CCI_ADB400_DCM_CONFIG_MASK ((0x1 << 0) | (0x1 << 2) | \ + (0x7 << 5) | (0xF << 16) | \ + (0x1 << 24) | (0xF << 25)) +#define MCUCFG_CCI_ADB400_DCM_CONFIG_ON ((0x1 << 0) | (0x1 << 2) | \ + (0x7 << 5) | (0xF << 16) | \ + (0x1 << 24) | (0xF << 25)) +#define MCUCFG_CCI_ADB400_DCM_CONFIG_OFF ((0x0 << 0) | (0x0 << 2) | \ + (0x0 << 5) | (0x0 << 16) | \ + (0x0 << 24) | (0xF << 25)) + +/* + * 0x0744 SYNC_DCM_CONFIG + * 0 0 cci_sync_dcm_div_en "0: disable, 1: enable" + * 5 1 cci_sync_dcm_div_sel "Floor(CPU_Freq/(4*system_timer_Freq))" + * 6 6 cci_sync_dcm_update_tog "change value will update the divider value" + * 8 8 mp0_sync_dcm_div_en "0: disable, 1: enable" + * 13 9 mp0_sync_dcm_div_sel "Floor(CPU_Freq/(4*system_timer_Freq))" + * 14 14 mp0_sync_dcm_update_tog "change value will update the divider value" + * 16 16 mp1_sync_dcm_div_en "0: disable, 1: enable" + * 21 17 mp1_sync_dcm_div_sel "Floor(CPU_Freq/(4*system_timer_Freq))" + * 22 22 mp1_sync_dcm_update_tog "change value will update the divider value" + */ +#define MCUCFG_SYNC_DCM_MASK ((0x1 << 0) | (0x1F << 1) | (0x1 << 6) | \ + (0x1 << 8) | (0x1F << 9) | (0x1 << 14) | \ + (0x1 << 16) | (0x1F << 17) | (0x1 << 22)) +#define MCUCFG_SYNC_DCM_CCI_MASK ((0x1 << 0) | (0x1F << 1) | (0x1 << 6)) +#define MCUCFG_SYNC_DCM_MP0_MASK ((0x1 << 8) | (0x1F << 9) | (0x1 << 14)) +#define MCUCFG_SYNC_DCM_MP1_MASK ((0x1 << 16) | (0x1F << 17) | (0x1 << 22)) +#define MCUCFG_SYNC_DCM_ON ((0x1 << 0) | (0x1 << 8) | (0x1 << 16)) +#define MCUCFG_SYNC_DCM_OFF ((0x0 << 0) | (0x0 << 8) | (0x0 << 16)) +#define MCUCFG_SYNC_DCM_SEL0 ((0x0 << 1) | (0x0 << 9) | (0x0 << 17)) +#define MCUCFG_SYNC_DCM_SEL2 ((0x2 << 1) | (0x2 << 9) | (0x2 << 17)) +#define MCUCFG_SYNC_DCM_TOGMASK ((0x1 << 6) | (0x1 << 14) | (0x1 << 22)) +#define MCUCFG_SYNC_DCM_CCI_TOGMASK (0x1 << 6) +#define MCUCFG_SYNC_DCM_MP0_TOGMASK (0x1 << 14) +#define MCUCFG_SYNC_DCM_MP1_TOGMASK (0x1 << 22) +#define MCUCFG_SYNC_DCM_TOG1 ((0x1 << 6) | (0x1 << 14) | (0x1 << 22)) +#define MCUCFG_SYNC_DCM_CCI_TOG1 MCUCFG_SYNC_DCM_CCI_TOGMASK +#define MCUCFG_SYNC_DCM_MP0_TOG1 MCUCFG_SYNC_DCM_MP0_TOGMASK +#define MCUCFG_SYNC_DCM_MP1_TOG1 MCUCFG_SYNC_DCM_MP1_TOGMASK +#define MCUCFG_SYNC_DCM_TOG0 ((0x0 << 6) | (0x0 << 14) | (0x0 << 22)) +#define MCUCFG_SYNC_DCM_CCI_TOG0 (0x0 << 6) +#define MCUCFG_SYNC_DCM_MP0_TOG0 (0x0 << 14) +#define MCUCFG_SYNC_DCM_MP1_TOG0 (0x0 << 22) +#define MCUCFG_SYNC_DCM_SELTOG_MASK ((0x1F << 1) | (0x1 << 6) | \ + (0x1F << 9) | (0x1 << 14) | \ + (0x1F << 17) | (0x1 << 22)) +#define MCUCFG_SYNC_DCM_SELTOG_CCI_MASK ((0x1F << 1) | (0x1 << 6)) +#define MCUCFG_SYNC_DCM_SELTOG_MP0_MASK ((0x1F << 9) | (0x1 << 14)) +#define MCUCFG_SYNC_DCM_SELTOG_MP1_MASK ((0x1F << 17) | (0x1 << 22)) + +/* + * 0x074C SYNC_DCM_CLUSTER_CONFIG + * 4 0 mp0_sync_dcm_stall_wr_del_sel Debounce Value must >= 16 + * 7 7 mp0_sync_dcm_stall_wr_en + */ +#define MCUCFG_SYNC_DCM_CLUSTER_MASK ((0x1F << 0) | (0x1 << 7)) +#define MCUCFG_SYNC_DCM_CLUSTER_EN ((0x1F << 0) | (0x1 << 7)) +#define MCUCFG_SYNC_DCM_CLUSTER_DIS ((0x0F << 0) | (0x0 << 7)) + +/* Do not enable it since it will impact the performance */ +/* #define ENABLE_SYNC_DCM_CLUSTER */ + +typedef enum { + MCUSYS_DCM_OFF = DCM_OFF, + MCUSYS_DCM_ON = DCM_ON, +} ENUM_MCUSYS_DCM; +int dcm_mcusys(ENUM_MCUSYS_DCM on) +{ + if (on == MCUSYS_DCM_OFF) { + MCUSYS_SMC_WRITE(MCUCFG_L2C_SRAM_CTRL, + aor(reg_read(MCUCFG_L2C_SRAM_CTRL), + ~MCUCFG_L2C_SRAM_CTRL_MASK, + MCUCFG_L2C_SRAM_CTRL_OFF)); + MCUSYS_SMC_WRITE(MCUCFG_CCI_CLK_CTRL, + aor(reg_read(MCUCFG_CCI_CLK_CTRL), + ~MCUCFG_CCI_CLK_CTRL_MASK, + MCUCFG_CCI_CLK_CTRL_OFF)); + MCUSYS_SMC_WRITE(MCUCFG_BUS_FABRIC_DCM_CTRL, + aor(reg_read(MCUCFG_BUS_FABRIC_DCM_CTRL), + ~MCUCFG_BUS_FABRIC_DCM_CTRL_MASK, + MCUCFG_BUS_FABRIC_DCM_CTRL_OFF)); + MCUSYS_SMC_WRITE(MCUCFG_CCI_ADB400_DCM_CONFIG, + aor(reg_read(MCUCFG_CCI_ADB400_DCM_CONFIG), + ~MCUCFG_CCI_ADB400_DCM_CONFIG_MASK, + MCUCFG_CCI_ADB400_DCM_CONFIG_OFF)); + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_MASK, + (MCUCFG_SYNC_DCM_OFF | + MCUCFG_SYNC_DCM_SEL0 | + MCUCFG_SYNC_DCM_TOG0))); +#ifdef ENABLE_SYNC_DCM_CLUSTER + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CLUSTER_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CLUSTER_CONFIG), + ~MCUCFG_SYNC_DCM_CLUSTER_MASK, + MCUCFG_SYNC_DCM_CLUSTER_DIS)); +#endif + } else { + MCUSYS_SMC_WRITE(MCUCFG_L2C_SRAM_CTRL, + aor(reg_read(MCUCFG_L2C_SRAM_CTRL), + ~MCUCFG_L2C_SRAM_CTRL_MASK, + MCUCFG_L2C_SRAM_CTRL_ON)); + MCUSYS_SMC_WRITE(MCUCFG_CCI_CLK_CTRL, + aor(reg_read(MCUCFG_CCI_CLK_CTRL), + ~MCUCFG_CCI_CLK_CTRL_MASK, + MCUCFG_CCI_CLK_CTRL_ON)); + MCUSYS_SMC_WRITE(MCUCFG_BUS_FABRIC_DCM_CTRL, + aor(reg_read(MCUCFG_BUS_FABRIC_DCM_CTRL), + ~MCUCFG_BUS_FABRIC_DCM_CTRL_MASK, + MCUCFG_BUS_FABRIC_DCM_CTRL_ON)); + MCUSYS_SMC_WRITE(MCUCFG_CCI_ADB400_DCM_CONFIG, + aor(reg_read(MCUCFG_CCI_ADB400_DCM_CONFIG), + ~MCUCFG_CCI_ADB400_DCM_CONFIG_MASK, + MCUCFG_CCI_ADB400_DCM_CONFIG_ON)); + /* set xxx_sync_dcm_tog as 0 first */ + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_TOGMASK, + MCUCFG_SYNC_DCM_TOG0)); + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_MASK, + (MCUCFG_SYNC_DCM_ON | + MCUCFG_SYNC_DCM_SEL0 | + MCUCFG_SYNC_DCM_TOG1))); +#ifdef ENABLE_SYNC_DCM_CLUSTER + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CLUSTER_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CLUSTER_CONFIG), + ~MCUCFG_SYNC_DCM_CLUSTER_MASK, + MCUCFG_SYNC_DCM_CLUSTER_EN)); +#endif + } + + return 0; +} + +int dcm_mcusys_cci_stall(ENUM_MCUSYS_DCM on) +{ + if (on == MCUSYS_DCM_OFF) { + MCUSYS_SMC_WRITE(MCUCFG_CCI_ADB400_DCM_CONFIG, + aor(reg_read(MCUCFG_CCI_ADB400_DCM_CONFIG), + ~MCUCFG_CCI_ADB400_DCM_CONFIG_MASK, + MCUCFG_CCI_ADB400_DCM_CONFIG_OFF)); + } else { + MCUSYS_SMC_WRITE(MCUCFG_CCI_ADB400_DCM_CONFIG, + aor(reg_read(MCUCFG_CCI_ADB400_DCM_CONFIG), + ~MCUCFG_CCI_ADB400_DCM_CONFIG_MASK, + MCUCFG_CCI_ADB400_DCM_CONFIG_ON)); + } + + return 0; +} + +int dcm_mcusys_sync_dcm(ENUM_MCUSYS_DCM on) +{ + if (on == MCUSYS_DCM_OFF) { + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_MASK, + (MCUCFG_SYNC_DCM_OFF | + MCUCFG_SYNC_DCM_SEL2 | + MCUCFG_SYNC_DCM_TOG0))); +#ifdef ENABLE_SYNC_DCM_CLUSTER + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CLUSTER_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CLUSTER_CONFIG), + ~MCUCFG_SYNC_DCM_CLUSTER_MASK, + MCUCFG_SYNC_DCM_CLUSTER_DIS)); +#endif + } else { + /* set xxx_sync_dcm_tog as 0 first */ + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_TOGMASK, + MCUCFG_SYNC_DCM_TOG0)); + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_MASK, + (MCUCFG_SYNC_DCM_ON | + MCUCFG_SYNC_DCM_SEL2 | + MCUCFG_SYNC_DCM_TOG1))); +#ifdef ENABLE_SYNC_DCM_CLUSTER + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CLUSTER_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CLUSTER_CONFIG), + ~MCUCFG_SYNC_DCM_CLUSTER_MASK, + MCUCFG_SYNC_DCM_CLUSTER_EN)); +#endif + } + + return 0; +} + +#if 0 +/* + * TOPCKGEN DCM golden setting ------------------------------------------------ + */ +/* + * 0x10000004 DCM_CFG + * 4 0 dcm_full_fsel (axi bus dcm full fsel) + * 7 7 dcm_enable + * 14 8 dcm_dbc_cnt + * 15 15 dcm_dbc_enable + * 20 16 mem_dcm_full_fsel ("1xxxx:1/1, 01xxx:1/2, 001xx: 1/4, 0001x: 1/8, 00001: 1/16, 00000: 1/32") + * 21 21 mem_dcm_cfg_latch + * 22 22 mem_dcm_idle_align + * 23 23 mem_dcm_enable + * 30 24 mem_dcm_dbc_cnt + * 31 31 mem_dcm_dbc_enable + */ +#define TOPCKG_DCM_CFG_MASK ((0x1f<<0) | (1<<7) | (0x7f<<8) | (1<<15)) +#define TOPCKG_DCM_CFG_ON ((0<<0) | (1<<7) | (0<<8) | (0<<15)) +#define TOPCKG_DCM_CFG_OFF (0<<7) +/* Used for slow idle to enable or disable TOPCK DCM */ +#define TOPCKG_DCM_CFG_QMASK (1<<7) +#define TOPCKG_DCM_CFG_QON (1<<7) +#define TOPCKG_DCM_CFG_QOFF (0<<7) + +#define TOPCKG_DCM_CFG_FMEM_MASK ((0x1f<<16) | (1<<21) | (1<<22) \ + | (1<<23) | (0x7f<<24) | (1<<31)) +#define TOPCKG_DCM_CFG_FMEM_ON ((0<<16) | (1<<21) | (0x1<<22) \ + | (1<<23) | (0<<24) | (0<<31)) +#define TOPCKG_DCM_CFG_FMEM_OFF ((1<<21) | (0<<23)) +/* toggle mem_dcm_cfg_latch since it's triggered by rising edge */ +#define TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK (1<<21) +#define TOPCKG_DCM_CFG_FMEM_TOGGLE_CLEAR (0<<21) +#define TOPCKG_DCM_CFG_FMEM_TOGGLE_ON (1<<21) + +/* + * TOPCKG_CLK_MISC_CFG_2 + * 7 0 mem_dcm_force_idle (0: does not force idle, 1: force idle to high) + */ +#define TOPCKG_CLK_MISC_CFG_2_MASK (0xf<<0) +#define TOPCKG_CLK_MISC_CFG_2_ON (0xf<<0) +#define TOPCKG_CLK_MISC_CFG_2_OFF (0x0<<0) + +typedef enum { + TOPCKG_DCM_OFF = DCM_OFF, + TOPCKG_DCM_ON = DCM_ON, +} ENUM_TOPCKG_DCM; + +int dcm_topckg_dbc(int on, int cnt) +{ + int value; + + cnt &= 0x7f; + on = (on != 0) ? 1 : 0; + value = (cnt << 8) | (cnt << 24) | (on << 15) | (on << 31); + + reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG), + ~((0xff << 8) | (0xff << 24)), value)); + + return 0; +} + +/** input argument + * 0: 1/1 + * 1: 1/2 + * 2: 1/4 + * 3: 1/8 + * 4: 1/16 + * 5: 1/32 + **/ +int dcm_topckg_rate(unsigned int fmem, unsigned int faxi) +{ + + fmem = 0x10 >> fmem; + faxi = 0x10 >> faxi; + + reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG), + ~((0x1f << 0) | (0x1f << 16)), (fmem << 16) | (faxi << 0))); + + return 0; +} + +/** FMEM DCM enable or disable (separate fmem DCM setting from TOPCK) + * For writing reg successfully, we need to toggle mem_dcm_cfg_latch first. + **/ +int dcm_fmem(ENUM_TOPCKG_DCM on) +{ + if (on) { + /* write reverse value of 21th bit */ + reg_write(TOPCKG_DCM_CFG, + aor(reg_read(TOPCKG_DCM_CFG), + ~TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK, + and(~reg_read(TOPCKG_DCM_CFG), TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK))); + reg_write(TOPCKG_DCM_CFG, + aor(reg_read(TOPCKG_DCM_CFG), + ~TOPCKG_DCM_CFG_FMEM_MASK, TOPCKG_DCM_CFG_FMEM_ON)); + /* Debug only: force fmem enter idle */ +/* reg_write(TOPCKG_CLK_MISC_CFG_2, TOPCKG_CLK_MISC_CFG_2_ON); */ + } else { + /* write reverse value of 21th bit */ + reg_write(TOPCKG_DCM_CFG, + aor(reg_read(TOPCKG_DCM_CFG), + ~TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK, + and(~reg_read(TOPCKG_DCM_CFG), TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK))); + reg_write(TOPCKG_DCM_CFG, + aor(reg_read(TOPCKG_DCM_CFG), + ~TOPCKG_DCM_CFG_FMEM_MASK, TOPCKG_DCM_CFG_FMEM_OFF)); + /* Debug only: force fmem enter idle */ +/* reg_write(TOPCKG_CLK_MISC_CFG_2, TOPCKG_CLK_MISC_CFG_2_OFF); */ + } + + return 0; +} + +int dcm_topckg(ENUM_TOPCKG_DCM on) +{ + if (on) { + dcm_fmem(on); + /* please be noticed, here TOPCKG_DCM_CFG_ON will overrid dbc/fsel setting !! */ + reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG), + ~TOPCKG_DCM_CFG_MASK, TOPCKG_DCM_CFG_ON)); + } else { + dcm_fmem(on); + reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG), + ~TOPCKG_DCM_CFG_MASK, TOPCKG_DCM_CFG_OFF)); + } + + return 0; +} +#endif /* 0 */ + +/* + * DRAMC DCM golden setting --------------------------------------------------- + */ +/* + * 0x100040f4 DRAMC_GDDR3CTL1 + * 21 21 CKE1FIXOFF RW PUBLIC 1'b0 off: 0, on: 0 + * "CKE1 always off, 0: CKE1 hardware control,1: CKE1 always off" + * 20 20 CKE1FIXON RW PUBLIC 1'b0 off: 0, on: 0 + * "CKE1 always on, 0: CKE1 hardware control, 1: CKE1 always on" + */ +#define DRAMC_GDDR3CTL1_MASK ((1<<21) | (1<<20)) +#define DRAMC_GDDR3CTL1_EN ((0<<21) | (0<<20)) +#define DRAMC_GDDR3CTL1_DIS ((0<<21) | (0<<20)) + +/* + * 0x10004130 DRAMC_CLKCTRL + * 29 29 CLK_EN_1 RW PUBLIC 1'b0 off: 0, on: 1 + * "Clock pad 1 enable, 0: disable, 1: enable" + * 28 28 CLK_EN_0 RW PUBLIC 1'b1 off: 0, on: 1 + * "Clock pad 0 enable, 0: disable, 1: enable" + */ +#define DRAMC_CLKCTRL_MASK ((1<<29) | (1<<28)) +#define DRAMC_CLKCTRL_EN ((1<<29) | (1<<28)) +#define DRAMC_CLKCTRL_DIS ((0<<29) | (0<<28)) + +/* + * 0x100041dc DRAMC_PD_CTRL + * 31 31 COMBCLKCTRL RW PUBLIC 1'b1 off: 0, on: 1 + * "MACRO_COMB clock dynamic gating control + * 1'b0: disable, MACRO_COMB clock is not gated. + * 1'b1: enable" + * 30 30 PHYCLKDYNGEN RW PUBLIC 1'b0 off: 0, on: 1 + * "DDRPHY clock dynamic gating control + * 1 : controlled by dramc + * 0 : always no gating" + * 26 26 MIOCKCTRLOFF RW PUBLIC 1'b0 off: 1, on: 0 + * "dram clk gating parameter + * 1 : always no gating + * 0 : controlled by dramc" + * 25 25 DCMEN RW PUBLIC 1'b0 off: 0, on: 1 + * "DRAMC non-freerun clock gating function + * 0: disable + * 1: enable" + * 24 24 REFFRERUN RW PUBLIC 1'b0 off: 0, on: 1 + * Using FREE-RUN CLK to count refresh period + * 3 3 COMBPHY_CLKENSAME RW PUBLIC 1'b0 off: 0, on: 1 + * "MACRO_COMB clock dynamic gating control is the same as DDRPHY + * 1'b0: disable, MACRO_COMB clock is gated by COMBCLKCTRL option. + * 1'b1: enable" + */ +#define DRAMC_PD_CTRL_MASK ((1<<31) | (1<<30) | (1<<26) | (1<<25) | \ + (1<<24) | (1<<3)) +#define DRAMC_PD_CTRL_EN ((1<<31) | (1<<30) | (0<<26) | (1<<25) | \ + (1<<24) | (1<<3)) +#define DRAMC_PD_CTRL_DIS ((0<<31) | (0<<30) | (1<<26) | (0<<25) | \ + (0<<24) | (0<<3)) + +/* + * 0x100041ec DRAMC_PERFCTL0 + * 16 16 DISDMOEDIS RW PUBLIC 1'b0 off: 1, on: 0 + * "For power saving, the self-refresh may disable the IO output enable + * 0: enable the power saving function + * 1: disable the power saving function" + */ +#define DRAMC_PERFCTL0_MASK (1<<16) +#define DRAMC_PERFCTL0_EN (0<<16) +#define DRAMC_PERFCTL0_DIS (1<<16) + +typedef enum { + DRAMC_AO_DCM_OFF = DCM_OFF, + DRAMC_AO_DCM_ON = DCM_ON, +} ENUM_DRAMC_AO_DCM; + +int dcm_dramc_ao(ENUM_DRAMC_AO_DCM on) +{ + if (on) { +#if 0 + reg_write(DRAMC_GDDR3CTL1, aor(reg_read(DRAMC_GDDR3CTL1), + ~DRAMC_GDDR3CTL1_MASK, + DRAMC_GDDR3CTL1_EN)); + reg_write(DRAMC_CLKCTRL, aor(reg_read(DRAMC_CLKCTRL), + ~DRAMC_CLKCTRL_MASK, + DRAMC_CLKCTRL_EN)); +#endif + reg_write(DRAMC_PD_CTRL, aor(reg_read(DRAMC_PD_CTRL), + ~DRAMC_PD_CTRL_MASK, + DRAMC_PD_CTRL_EN)); + reg_write(DRAMC_PERFCTL0, aor(reg_read(DRAMC_PERFCTL0), + ~DRAMC_PERFCTL0_MASK, + DRAMC_PERFCTL0_EN)); + } else { +#if 0 + reg_write(DRAMC_GDDR3CTL1, aor(reg_read(DRAMC_GDDR3CTL1), + ~DRAMC_GDDR3CTL1_MASK, + DRAMC_GDDR3CTL1_DIS)); + reg_write(DRAMC_CLKCTRL, aor(reg_read(DRAMC_CLKCTRL), + ~DRAMC_CLKCTRL_MASK, + DRAMC_CLKCTRL_DIS)); +#endif + reg_write(DRAMC_PD_CTRL, aor(reg_read(DRAMC_PD_CTRL), + ~DRAMC_PD_CTRL_MASK, + DRAMC_PD_CTRL_DIS)); + reg_write(DRAMC_PERFCTL0, aor(reg_read(DRAMC_PERFCTL0), + ~DRAMC_PERFCTL0_MASK, + DRAMC_PERFCTL0_DIS)); + } + + return 0; +} + +/* + * DDRPHY DCM golden setting -------------------------------------------------- + */ +/* + * 0x1000f63c DDRPHY_CG_CTRL + * 2 2 RG_M_CK_DYN_CG_EN RW PUBLIC "1'b0 off: 0, on: 1 + * "DDRPHY C/A M_CK clock gating function enable + * 1'b0: disable + * 1'b1: enable" + * 1 1 RG_M_CK_DYN_CG_EN_COMB RW PUBLIC 1'b0 off: 0, on: 1 + * "DDRPHY DQ M_CK clock gating function enable + * 1'b0: disable + * 1'b1: enable" + */ +#define DDRPHY_CG_CTRL_MASK ((1<<2) | (1<<1)) +#define DDRPHY_CG_CTRL_EN ((1<<2) | (1<<1)) +#define DDRPHY_CG_CTRL_DIS ((0<<2) | (0<<1)) + +typedef enum { + DDRPHY_DCM_OFF = DCM_OFF, + DDRPHY_DCM_ON = DCM_ON, +} ENUM_DDRPHY_DCM; + +int dcm_ddrphy(ENUM_DDRPHY_DCM on) +{ + if (on) { + reg_write(DDRPHY_CG_CTRL, + aor(reg_read(DDRPHY_CG_CTRL), + ~DDRPHY_CG_CTRL_MASK, DDRPHY_CG_CTRL_EN)); + } else { + reg_write(DDRPHY_CG_CTRL, + aor(reg_read(DDRPHY_CG_CTRL), + ~DDRPHY_CG_CTRL_MASK, DDRPHY_CG_CTRL_DIS)); + } + + return 0; +} + +/* + * EMI DCM golden setting ----------------------------------------------------- + */ +/** 0x10203060 EMI_CONM + * 31 24 EMI_DCM_DIS 8'h0 off: FF, on: 0 + **/ +#define EMI_CONM_MASK (0xFF<<24) +#define EMI_CONM_EN (0<<24) +#define EMI_CONM_DIS (0xFF<<24) + +typedef enum { + EMI_DCM_OFF = DCM_OFF, + EMI_DCM_ON = DCM_ON, +} ENUM_EMI_DCM; + +int dcm_emi(ENUM_EMI_DCM on) +{ + if (on) + reg_write(EMI_CONM, aor(reg_read(EMI_CONM), ~EMI_CONM_MASK, + EMI_CONM_EN)); + else + reg_write(EMI_CONM, aor(reg_read(EMI_CONM), ~EMI_CONM_MASK, + EMI_CONM_DIS)); + + return 0; +} + +/*****************************************************/ +enum { + ARMCORE_DCM = 0, + MCUSYS_DCM, + INFRA_DCM, + PERI_DCM, + EMI_DCM, + DRAMC_DCM, + DDRPHY_DCM, + PMIC_DCM, + USB_DCM, + ICUSB_DCM, + AUDIO_DCM, + SSUSB_DCM, + + NR_DCM = 12, +}; + +enum { + ARMCORE_DCM_TYPE = (1U << 0), + MCUSYS_DCM_TYPE = (1U << 1), + INFRA_DCM_TYPE = (1U << 2), + PERI_DCM_TYPE = (1U << 3), + EMI_DCM_TYPE = (1U << 4), + DRAMC_DCM_TYPE = (1U << 5), + DDRPHY_DCM_TYPE = (1U << 6), + PMIC_DCM_TYPE = (1U << 7), + USB_DCM_TYPE = (1U << 8), + ICUSB_DCM_TYPE = (1U << 9), + AUDIO_DCM_TYPE = (1U << 10), + SSUSB_DCM_TYPE = (1U << 11), + + NR_DCM_TYPE = 12, +}; + +#define ALL_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE | INFRA_DCM_TYPE | \ + PERI_DCM_TYPE | EMI_DCM_TYPE | DRAMC_DCM_TYPE | \ + DDRPHY_DCM_TYPE | PMIC_DCM_TYPE | USB_DCM_TYPE | \ + ICUSB_DCM_TYPE | AUDIO_DCM_TYPE | SSUSB_DCM_TYPE) + +#define INIT_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE | INFRA_DCM_TYPE | \ + PERI_DCM_TYPE | /* EMI_DCM_TYPE | DRAMC_DCM_TYPE |*/ \ + /*| DDRPHY_DCM_TYPE */ PMIC_DCM_TYPE | USB_DCM_TYPE | \ + ICUSB_DCM_TYPE | AUDIO_DCM_TYPE | SSUSB_DCM_TYPE) + +typedef struct _dcm { + int current_state; + int saved_state; + int disable_refcnt; + int default_state; + DCM_FUNC func; + DCM_PRESET_FUNC preset_func; + int typeid; + char *name; +} DCM; + +static DCM dcm_array[NR_DCM_TYPE] = { + { + .typeid = ARMCORE_DCM_TYPE, + .name = "ARMCORE_DCM", + .func = (DCM_FUNC) dcm_armcore, + .current_state = ARMCORE_DCM_MODE1, + .default_state = ARMCORE_DCM_MODE1, + .disable_refcnt = 0, + }, + { + .typeid = MCUSYS_DCM_TYPE, + .name = "MCUSYS_DCM", + .func = (DCM_FUNC) dcm_mcusys, + .current_state = MCUSYS_DCM_ON, + .default_state = MCUSYS_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = INFRA_DCM_TYPE, + .name = "INFRA_DCM", + .func = (DCM_FUNC) dcm_infra, + .preset_func = (DCM_PRESET_FUNC) dcm_infra_preset, + .current_state = INFRA_DCM_ON, + .default_state = INFRA_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = PERI_DCM_TYPE, + .name = "PERI_DCM", + .func = (DCM_FUNC) dcm_peri, + .preset_func = (DCM_PRESET_FUNC) dcm_peri_preset, + .current_state = PERI_DCM_ON, + .default_state = PERI_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = EMI_DCM_TYPE, + .name = "EMI_DCM", + .func = (DCM_FUNC) dcm_emi, + .current_state = EMI_DCM_ON, + .default_state = EMI_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = DRAMC_DCM_TYPE, + .name = "DRAMC_DCM", + .func = (DCM_FUNC) dcm_dramc_ao, + .current_state = DRAMC_AO_DCM_ON, + .default_state = DRAMC_AO_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = DDRPHY_DCM_TYPE, + .name = "DDRPHY_DCM", + .func = (DCM_FUNC) dcm_ddrphy, + .current_state = DDRPHY_DCM_ON, + .default_state = DDRPHY_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = PMIC_DCM_TYPE, + .name = "PMIC_DCM", + .func = (DCM_FUNC) dcm_pmic, + .current_state = PMIC_DCM_ON, + .default_state = PMIC_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = USB_DCM_TYPE, + .name = "USB_DCM", + .func = (DCM_FUNC) dcm_usb, + .current_state = USB_DCM_ON, + .default_state = USB_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = ICUSB_DCM_TYPE, + .name = "ICUSB_DCM", + .func = (DCM_FUNC) dcm_icusb, + .current_state = ICUSB_DCM_ON, + .default_state = ICUSB_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = AUDIO_DCM_TYPE, + .name = "AUDIO_DCM", + .func = (DCM_FUNC) dcm_audio, + .current_state = AUDIO_DCM_ON, + .default_state = AUDIO_DCM_ON, + .disable_refcnt = 0, + }, + { + .typeid = SSUSB_DCM_TYPE, + .name = "SSUSB_DCM", + .func = (DCM_FUNC) dcm_ssusb, + .current_state = SSUSB_DCM_ON, + .default_state = SSUSB_DCM_ON, + .disable_refcnt = 0, + }, +}; + +/***************************************** + * DCM driver will provide regular APIs : + * 1. dcm_restore(type) to recovery CURRENT_STATE before any power-off reset. + * 2. dcm_set_default(type) to reset as cold-power-on init state. + * 3. dcm_disable(type) to disable all dcm. + * 4. dcm_set_state(type) to set dcm state. + * 5. dcm_dump_state(type) to show CURRENT_STATE. + * 6. /sys/power/dcm_state interface: 'restore', 'disable', 'dump', 'set'. 4 commands. + * + * spsecified APIs for workaround: + * 1. (definitely no workaround now) + *****************************************/ +void dcm_set_default(unsigned int type) +{ + int i; + DCM *dcm; + + dcm_info("[%s]type:0x%08x\n", __func__, type); + + mutex_lock(&dcm_lock); + + for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) { + if (type & dcm->typeid) { + dcm->saved_state = dcm->default_state; + dcm->current_state = dcm->default_state; + dcm->disable_refcnt = 0; + if (dcm->preset_func) + dcm->preset_func(); + dcm->func(dcm->current_state); + + dcm_info("[%16s 0x%08x] current state:%d (%d)\n", + dcm->name, dcm->typeid, dcm->current_state, + dcm->disable_refcnt); + } + } + + mutex_unlock(&dcm_lock); +} + +void dcm_set_state(unsigned int type, int state) +{ + int i; + DCM *dcm; + + dcm_info("[%s]type:0x%08x, set:%d\n", __func__, type, state); + + mutex_lock(&dcm_lock); + + for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) { + if (type & dcm->typeid) { + type &= ~(dcm->typeid); + + dcm->saved_state = state; + if (dcm->disable_refcnt == 0) { + dcm->current_state = state; + dcm->func(dcm->current_state); + } + + dcm_info("[%16s 0x%08x] current state:%d (%d)\n", + dcm->name, dcm->typeid, dcm->current_state, + dcm->disable_refcnt); + } + } + + mutex_unlock(&dcm_lock); +} + + +void dcm_disable(unsigned int type) +{ + int i; + DCM *dcm; + + dcm_info("[%s]type:0x%08x\n", __func__, type); + + mutex_lock(&dcm_lock); + + for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) { + if (type & dcm->typeid) { + type &= ~(dcm->typeid); + + dcm->current_state = DCM_OFF; + dcm->disable_refcnt++; + dcm->func(dcm->current_state); + + dcm_info("[%16s 0x%08x] current state:%d (%d)\n", + dcm->name, dcm->typeid, dcm->current_state, + dcm->disable_refcnt); + } + } + + mutex_unlock(&dcm_lock); + +} + +void dcm_restore(unsigned int type) +{ + int i; + DCM *dcm; + + dcm_info("[%s]type:0x%08x\n", __func__, type); + + mutex_lock(&dcm_lock); + + for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) { + if (type & dcm->typeid) { + type &= ~(dcm->typeid); + + if (dcm->disable_refcnt > 0) + dcm->disable_refcnt--; + if (dcm->disable_refcnt == 0) { + dcm->current_state = dcm->saved_state; + dcm->func(dcm->current_state); + } + + dcm_info("[%16s 0x%08x] current state:%d (%d)\n", + dcm->name, dcm->typeid, dcm->current_state, + dcm->disable_refcnt); + } + } + + mutex_unlock(&dcm_lock); +} + + +void dcm_dump_state(int type) +{ + int i; + DCM *dcm; + + dcm_info("\n******** dcm dump state *********\n"); + for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) { + if (type & dcm->typeid) { + dcm_info("[%-16s 0x%08x] current state:%d (%d)\n", + dcm->name, dcm->typeid, dcm->current_state, + dcm->disable_refcnt); + } + } +} + +void dcm_dump_regs(void) +{ + dcm_info("\n******** dcm dump register *********\n"); + REG_DUMP(MCUCFG_L2C_SRAM_CTRL); + REG_DUMP(MCUCFG_CCI_CLK_CTRL); + REG_DUMP(MCUCFG_BUS_FABRIC_DCM_CTRL); + REG_DUMP(MCUCFG_CCI_ADB400_DCM_CONFIG); + REG_DUMP(MCUCFG_SYNC_DCM_CONFIG); +#ifdef ENABLE_SYNC_DCM_CLUSTER + REG_DUMP(MCUCFG_SYNC_DCM_CLUSTER_CONFIG); +#endif + REG_DUMP(TOP_CKMUXSEL); + REG_DUMP(INFRA_TOPCKGEN_CKDIV1_BIG); + REG_DUMP(INFRA_TOPCKGEN_CKDIV1_SML); + REG_DUMP(INFRA_TOPCKGEN_CKDIV1_BUS); + REG_DUMP(TOPCKG_CLK_MISC_CFG_0); + REG_DUMP(TOP_DCMCTL); + REG_DUMP(INFRA_BUS_DCM_CTRL); + REG_DUMP(PERI_BUS_DCM_CTRL); + REG_DUMP(P2P_RX_CLK_ON); + REG_DUMP(INFRA_MISC); + REG_DUMP(INFRA_MISC_1); +#if 0 + REG_DUMP(DRAMC_GDDR3CTL1); + REG_DUMP(DRAMC_CLKCTRL); +#endif + REG_DUMP(DRAMC_PD_CTRL); + REG_DUMP(DRAMC_PERFCTL0); + REG_DUMP(DDRPHY_CG_CTRL); + REG_DUMP(EMI_CONM); +} + + +#if defined(CONFIG_PM) +static ssize_t dcm_state_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + int len = 0; + int i; + DCM *dcm; + + /* dcm_dump_state(ALL_DCM_TYPE); */ + len += snprintf(buf+len, PAGE_SIZE-len, + "\n******** dcm dump state *********\n"); + for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) + len += snprintf(buf+len, PAGE_SIZE-len, + "[%-16s 0x%08x] current state:%d (%d)\n", + dcm->name, dcm->typeid, dcm->current_state, + dcm->disable_refcnt); + + len += snprintf(buf+len, PAGE_SIZE-len, + "\n********** dcm_state help *********\n"); + len += snprintf(buf+len, PAGE_SIZE-len, + "set: echo set [mask] [mode] > /sys/power/dcm_state\n"); + len += snprintf(buf+len, PAGE_SIZE-len, + "disable: echo disable [mask] > /sys/power/dcm_state\n"); + len += snprintf(buf+len, PAGE_SIZE-len, + "restore: echo restore [mask] > /sys/power/dcm_state\n"); + len += snprintf(buf+len, PAGE_SIZE-len, + "dump: echo dump [mask] > /sys/power/dcm_state\n"); + len += snprintf(buf+len, PAGE_SIZE-len, + "***** [mask] is hexl bit mask of dcm;\n"); + len += snprintf(buf+len, PAGE_SIZE-len, + "***** [mode] is type of DCM to set and retained\n"); + + return len; +} + +static ssize_t dcm_state_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, + size_t n) +{ + char cmd[16]; + unsigned int mask; + int ret, mode; + + if (sscanf(buf, "%15s %x", cmd, &mask) == 2) { + mask &= ALL_DCM_TYPE; + + if (!strcmp(cmd, "restore")) { + /* dcm_dump_regs(); */ + dcm_restore(mask); + /* dcm_dump_regs(); */ + } else if (!strcmp(cmd, "disable")) { + /* dcm_dump_regs(); */ + dcm_disable(mask); + /* dcm_dump_regs(); */ + } else if (!strcmp(cmd, "dump")) { + dcm_dump_state(mask); + dcm_dump_regs(); + } else if (!strcmp(cmd, "set")) { + if (sscanf(buf, "%15s %x %d", cmd, &mask, &mode) == 3) { + mask &= ALL_DCM_TYPE; + + dcm_set_state(mask, mode); + } + } else { + dcm_info("SORRY, do not support your command: %s\n", cmd); + } + ret = n; + } else { + dcm_info("SORRY, do not support your command.\n"); + ret = -EINVAL; + } + + return ret; +} + +static struct kobj_attribute dcm_state_attr = { + .attr = { + .name = "dcm_state", + .mode = 0644, + }, + .show = dcm_state_show, + .store = dcm_state_store, +}; +#endif /* #if defined (CONFIG_PM) */ + +#if defined(CONFIG_OF) +static int mt_dcm_dts_map(void) +{ + struct device_node *node; + struct resource r; + + /* topckgen */ + node = of_find_compatible_node(NULL, NULL, TOPCKGEN_NODE); + if (!node) { + dcm_info("error: cannot find node " TOPCKGEN_NODE); + BUG(); + } + topckgen_base = (unsigned long)of_iomap(node, 0); + if (!topckgen_base) { + dcm_info("error: cannot iomap " TOPCKGEN_NODE); + BUG(); + } + + /* mcucfg */ + node = of_find_compatible_node(NULL, NULL, MCUCFG_NODE); + if (!node) { + dcm_info("error: cannot find node " MCUCFG_NODE); + BUG(); + } + if (of_address_to_resource(node, 0, &r)) { + dcm_info("error: cannot get phys addr" MCUCFG_NODE); + BUG(); + } + mcucfg_phys_base = r.start; + + mcucfg_base = (unsigned long)of_iomap(node, 0); + if (!mcucfg_base) { + dcm_info("error: cannot iomap " MCUCFG_NODE); + BUG(); + } + + /* dramc */ + dramc_ao_base = (unsigned long)mt_dramc_base_get(); + if (!dramc_ao_base) { + dcm_info("error: cannot get dramc_ao_base from dram api"); + BUG(); + } + + /* emi_reg */ + node = of_find_compatible_node(NULL, NULL, EMI_REG_NODE); + if (!node) { + dcm_info("error: cannot find node " EMI_REG_NODE); + BUG(); + } + emi_reg_base = (unsigned long)of_iomap(node, 0); + if (!emi_reg_base) { + dcm_info("error: cannot iomap " EMI_REG_NODE); + BUG(); + } + + /* ddrphy */ + ddrphy_base = (unsigned long)mt_ddrphy_base_get(); + if (!ddrphy_base) { + dcm_info("error: cannot get ddrphy_base from dram api"); + BUG(); + } + + /* infracfg_ao */ + node = of_find_compatible_node(NULL, NULL, INFRACFG_AO_NODE); + if (!node) { + dcm_info("error: cannot find node " INFRACFG_AO_NODE); + BUG(); + } + infracfg_ao_base = (unsigned long)of_iomap(node, 0); + if (!infracfg_ao_base) { + dcm_info("error: cannot iomap " INFRACFG_AO_NODE); + BUG(); + } + + return 0; +} +#else +static int mt_dcm_dts_map(void) +{ + return 0; +} +#endif + +int mt_dcm_init(void) +{ + if (dcm_initiated) + return 0; + + mt_dcm_dts_map(); + +#if !defined(DCM_DEFAULT_ALL_OFF) + /** enable all dcm **/ + dcm_set_default(INIT_DCM_TYPE); +#else /* #if !defined (DCM_DEFAULT_ALL_OFF) */ + dcm_set_state(ALL_DCM_TYPE, DCM_OFF); +#endif /* #if !defined (DCM_DEFAULT_ALL_OFF) */ + + dcm_dump_regs(); + +#if defined(CONFIG_PM) + { + int err = 0; + + err = sysfs_create_file(power_kobj, &dcm_state_attr.attr); + if (err) + dcm_err("[%s]: fail to create sysfs\n", __func__); + } + +#if defined(DCM_DEBUG_MON) + { + int err = 0; + + err = sysfs_create_file(power_kobj, &dcm_debug_mon_attr.attr); + if (err) + dcm_err("[%s]: fail to create sysfs\n", __func__); + } +#endif /* #if defined (DCM_DEBUG_MON) */ +#endif /* #if defined (CONFIG_PM) */ + + dcm_initiated = 1; + + return 0; +} +late_initcall(mt_dcm_init); + +/**** public APIs *****/ +void mt_dcm_disable(void) +{ + mt_dcm_init(); + dcm_disable(ALL_DCM_TYPE); +} + +void mt_dcm_restore(void) +{ + mt_dcm_init(); + dcm_restore(ALL_DCM_TYPE); +} + +unsigned int sync_dcm_convert_freq2div(unsigned int freq) +{ + unsigned int div = 0; + + if (freq < 52) + return 0; + + /* max divided ratio = Floor (CPU Frequency / 4* system timer Frequency) */ + div = freq / 52; + if (div > 31) + return 31; + + return div; +} + +/* unit of frequency is MHz */ +int sync_dcm_set_cpu_freq(unsigned int cci, unsigned int mp0, unsigned int mp1) +{ + mt_dcm_init(); + /* set xxx_sync_dcm_tog as 0 first */ + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_TOGMASK, + MCUCFG_SYNC_DCM_TOG0)); + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_SELTOG_MASK, + (MCUCFG_SYNC_DCM_TOG1 | + (sync_dcm_convert_freq2div(cci) << 1) | + (sync_dcm_convert_freq2div(mp0) << 9) | + (sync_dcm_convert_freq2div(mp1) << 17)))); +#ifdef DCM_DEBUG + dcm_info("%s: SYNC_DCM_CONFIG=0x%08x, cci=%u/%u,%u, mp0=%u/%u,%u, mp1=%u/%u,%u\n", + __func__, reg_read(MCUCFG_SYNC_DCM_CONFIG), cci, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 1)) >> 1), + sync_dcm_convert_freq2div(cci), mp0, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 9)) >> 9), + sync_dcm_convert_freq2div(mp0), mp1, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 17)) >> 17), + sync_dcm_convert_freq2div(mp1)); +#endif + + return 0; +} + +int sync_dcm_set_cpu_div(unsigned int cci, unsigned int mp0, unsigned int mp1) +{ + if (cci > 31 || mp0 > 31 || mp1 > 31) + return -1; + + mt_dcm_init(); + /* set xxx_sync_dcm_tog as 0 first */ + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_TOGMASK, + MCUCFG_SYNC_DCM_TOG0)); + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_SELTOG_MASK, + (MCUCFG_SYNC_DCM_TOG1 | + (cci << 1) | + (mp0 << 9) | + (mp1 << 17)))); +#ifdef DCM_DEBUG + dcm_info("%s: SYNC_DCM_CONFIG=0x%08x, cci=%u/%u, mp0=%u/%u, mp1=%u/%u\n", + __func__, reg_read(MCUCFG_SYNC_DCM_CONFIG), cci, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 1)) >> 1), mp0, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 9)) >> 9), mp1, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 17)) >> 17)); +#endif + + return 0; +} + +int sync_dcm_set_cci_freq(unsigned int cci) +{ + mt_dcm_init(); + /* set xxx_sync_dcm_tog as 0 first */ + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_CCI_TOGMASK, + MCUCFG_SYNC_DCM_CCI_TOG0)); + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_SELTOG_CCI_MASK, + (MCUCFG_SYNC_DCM_CCI_TOG1 | + (sync_dcm_convert_freq2div(cci) << 1)))); +#ifdef DCM_DEBUG + dcm_info("%s: SYNC_DCM_CONFIG=0x%08x, cci=%u, cci_div_sel=%u,%u\n", + __func__, reg_read(MCUCFG_SYNC_DCM_CONFIG), cci, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 1)) >> 1), + sync_dcm_convert_freq2div(cci)); +#endif + + return 0; +} + +int sync_dcm_set_mp0_freq(unsigned int mp0) +{ + mt_dcm_init(); + /* set xxx_sync_dcm_tog as 0 first */ + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_MP0_TOGMASK, + MCUCFG_SYNC_DCM_MP0_TOG0)); + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_SELTOG_MP0_MASK, + (MCUCFG_SYNC_DCM_MP0_TOG1 | + (sync_dcm_convert_freq2div(mp0) << 9)))); +#ifdef DCM_DEBUG + dcm_info("%s: SYNC_DCM_CONFIG=0x%08x, mp0=%u, mp0_div_sel=%u,%u\n", + __func__, reg_read(MCUCFG_SYNC_DCM_CONFIG), mp0, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 9)) >> 9), + sync_dcm_convert_freq2div(mp0)); +#endif + + return 0; +} + +int sync_dcm_set_mp1_freq(unsigned int mp1) +{ + mt_dcm_init(); + /* set xxx_sync_dcm_tog as 0 first */ + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_MP1_TOGMASK, + MCUCFG_SYNC_DCM_MP1_TOG0)); + MCUSYS_SMC_WRITE(MCUCFG_SYNC_DCM_CONFIG, + aor(reg_read(MCUCFG_SYNC_DCM_CONFIG), + ~MCUCFG_SYNC_DCM_SELTOG_MP1_MASK, + (MCUCFG_SYNC_DCM_MP1_TOG1 | + (sync_dcm_convert_freq2div(mp1) << 17)))); +#ifdef DCM_DEBUG + dcm_info("%s: SYNC_DCM_CONFIG=0x%08x, mp1=%u, mp1_div_sel=%u,%u\n", + __func__, reg_read(MCUCFG_SYNC_DCM_CONFIG), mp1, + (and(reg_read(MCUCFG_SYNC_DCM_CONFIG), (0x1F << 17)) >> 17), + sync_dcm_convert_freq2div(mp1)); +#endif + + return 0; +} + +/* mt_dcm_topckg_disable/enable is used for slow idle */ +void mt_dcm_topckg_disable(void) +{ +#if 0 +#if !defined(DCM_DEFAULT_ALL_OFF) + reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG), + ~TOPCKG_DCM_CFG_QMASK, TOPCKG_DCM_CFG_QOFF)); +#endif /* #if !defined (DCM_DEFAULT_ALL_OFF) */ +#endif /* 0 */ +} + +/* mt_dcm_topckg_disable/enable is used for slow idle */ +void mt_dcm_topckg_enable(void) +{ +#if 0 +#if !defined(DCM_DEFAULT_ALL_OFF) + if (dcm_array[TOPCKG_DCM].current_state != DCM_OFF) { + reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG), + ~TOPCKG_DCM_CFG_QMASK, TOPCKG_DCM_CFG_QON)); + } +#endif /* #if !defined (DCM_DEFAULT_ALL_OFF) */ +#endif /* 0 */ +} + +void mt_dcm_topck_off(void) +{ +#if 0 + mt_dcm_init(); + dcm_set_state(TOPCKG_DCM_TYPE, DCM_OFF); +#endif /* 0 */ +} + +void mt_dcm_topck_on(void) +{ +#if 0 + mt_dcm_init(); + dcm_set_state(TOPCKG_DCM_TYPE, DCM_ON); +#endif /* 0 */ +} + +void mt_dcm_peri_off(void) +{ +} + +void mt_dcm_peri_on(void) +{ +} + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_dcm.h b/drivers/misc/mediatek/base/power/mt6755/mt_dcm.h new file mode 100644 index 0000000000000000000000000000000000000000..df28b6adaa75bd4ba2b7abce26216a6402dafa10 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_dcm.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_DCM_H__ +#define __MT_DCM_H__ + +void mt_dcm_emi_1pll_mode(void); +void mt_dcm_emi_off(void); +void mt_dcm_emi_3pll_mode(void); + +void mt_dcm_disable(void); +void mt_dcm_restore(void); +void mt_dcm_topckg_disable(void); +void mt_dcm_topckg_enable(void); +void mt_dcm_topck_off(void); +void mt_dcm_topck_on(void); +void mt_dcm_peri_off(void); +void mt_dcm_peri_on(void); + +int sync_dcm_set_cci_freq(unsigned int cci); +int sync_dcm_set_mp0_freq(unsigned int mp0); +int sync_dcm_set_mp1_freq(unsigned int mp1); + +#endif /* #ifndef __MT_DCM_H__ */ + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_defptp.h b/drivers/misc/mediatek/base/power/mt6755/mt_defptp.h new file mode 100644 index 0000000000000000000000000000000000000000..ec34329fa0ec131bc4b0e3211e71bd225f783f07 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_defptp.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_DEFEEM_ +#define _MT_DEFEEM_ + +#ifdef __KERNEL__ + #include +#endif + +#ifdef __KERNEL__ + #define EEMCONF_S 0x0011c010 + #define EEMCONF_E 0x0011c210 + #define EEMCONF_SIZE (EEMCONF_E - EEMCONF_S) + + extern void __iomem *eem_base; + #define EEM_BASEADDR eem_base + + #ifdef CONFIG_OF + struct devinfo_ptp_tag { + u32 size; + u32 tag; + u32 volt0; + u32 volt1; + u32 volt2; + u32 have_550; + }; + #endif +#else + typedef unsigned char bool; + #define EEM_BASEADDR (0x1100B000) + #define eem_base EEM_BASEADDR +#endif + +#define EEM_TEMPMONCTL0 (EEM_BASEADDR + 0x000) +#define EEM_TEMPMONCTL1 (EEM_BASEADDR + 0x004) +#define EEM_TEMPMONCTL2 (EEM_BASEADDR + 0x008) +#define EEM_TEMPMONINT (EEM_BASEADDR + 0x00C) +#define EEM_TEMPMONINTSTS (EEM_BASEADDR + 0x010) +#define EEM_TEMPMONIDET0 (EEM_BASEADDR + 0x014) +#define EEM_TEMPMONIDET1 (EEM_BASEADDR + 0x018) +#define EEM_TEMPMONIDET2 (EEM_BASEADDR + 0x01C) +#define EEM_TEMPH2NTHRE (EEM_BASEADDR + 0x024) +#define EEM_TEMPHTHRE (EEM_BASEADDR + 0x028) +#define EEM_TEMPCTHRE (EEM_BASEADDR + 0x02C) +#define EEM_TEMPOFFSETH (EEM_BASEADDR + 0x030) +#define EEM_TEMPOFFSETL (EEM_BASEADDR + 0x034) +#define EEM_TEMPMSRCTL0 (EEM_BASEADDR + 0x038) +#define EEM_TEMPMSRCTL1 (EEM_BASEADDR + 0x03C) +#define EEM_TEMPAHBPOLL (EEM_BASEADDR + 0x040) +#define EEM_TEMPAHBTO (EEM_BASEADDR + 0x044) +#define EEM_TEMPADCPNP0 (EEM_BASEADDR + 0x048) +#define EEM_TEMPADCPNP1 (EEM_BASEADDR + 0x04C) +#define EEM_TEMPADCPNP2 (EEM_BASEADDR + 0x050) +#define EEM_TEMPADCMUX (EEM_BASEADDR + 0x054) +#define EEM_TEMPADCEXT (EEM_BASEADDR + 0x058) +#define EEM_TEMPADCEXT1 (EEM_BASEADDR + 0x05C) +#define EEM_TEMPADCEN (EEM_BASEADDR + 0x060) +#define EEM_TEMPPNPMUXADDR (EEM_BASEADDR + 0x064) +#define EEM_TEMPADCMUXADDR (EEM_BASEADDR + 0x068) +#define EEM_TEMPADCEXTADDR (EEM_BASEADDR + 0x06C) +#define EEM_TEMPADCEXT1ADDR (EEM_BASEADDR + 0x070) +#define EEM_TEMPADCENADDR (EEM_BASEADDR + 0x074) +#define EEM_TEMPADCVALIDADDR (EEM_BASEADDR + 0x078) +#define EEM_TEMPADCVOLTADDR (EEM_BASEADDR + 0x07C) +#define EEM_TEMPRDCTRL (EEM_BASEADDR + 0x080) +#define EEM_TEMPADCVALIDMASK (EEM_BASEADDR + 0x084) +#define EEM_TEMPADCVOLTAGESHIFT (EEM_BASEADDR + 0x088) +#define EEM_TEMPADCWRITECTRL (EEM_BASEADDR + 0x08C) +#define EEM_TEMPMSR0 (EEM_BASEADDR + 0x090) +#define EEM_TEMPMSR1 (EEM_BASEADDR + 0x094) +#define EEM_TEMPMSR2 (EEM_BASEADDR + 0x098) +#define EEM_TEMPIMMD0 (EEM_BASEADDR + 0x0A0) +#define EEM_TEMPIMMD1 (EEM_BASEADDR + 0x0A4) +#define EEM_TEMPIMMD2 (EEM_BASEADDR + 0x0A8) +#define EEM_TEMPMONIDET3 (EEM_BASEADDR + 0x0B0) +#define EEM_TEMPADCPNP3 (EEM_BASEADDR + 0x0B4) +#define EEM_TEMPMSR3 (EEM_BASEADDR + 0x0B8) +#define EEM_TEMPIMMD3 (EEM_BASEADDR + 0x0BC) +#define EEM_TEMPPROTCTL (EEM_BASEADDR + 0x0C0) +#define EEM_TEMPPROTTA (EEM_BASEADDR + 0x0C4) +#define EEM_TEMPPROTTB (EEM_BASEADDR + 0x0C8) +#define EEM_TEMPPROTTC (EEM_BASEADDR + 0x0CC) +#define EEM_TEMPSPARE0 (EEM_BASEADDR + 0x0F0) +#define EEM_TEMPSPARE1 (EEM_BASEADDR + 0x0F4) +#define EEM_TEMPSPARE2 (EEM_BASEADDR + 0x0F8) +#define EEM_REVISIONID (EEM_BASEADDR + 0x0FC) +#define DESCHAR (EEM_BASEADDR + 0x200) +#define TEMPCHAR (EEM_BASEADDR + 0x204) +#define DETCHAR (EEM_BASEADDR + 0x208) +#define AGECHAR (EEM_BASEADDR + 0x20C) +#define EEM_DCCONFIG (EEM_BASEADDR + 0x210) +#define EEM_AGECONFIG (EEM_BASEADDR + 0x214) +#define FREQPCT30 (EEM_BASEADDR + 0x218) +#define FREQPCT74 (EEM_BASEADDR + 0x21C) +#define LIMITVALS (EEM_BASEADDR + 0x220) +#define EEM_VBOOT (EEM_BASEADDR + 0x224) +#define EEM_DETWINDOW (EEM_BASEADDR + 0x228) +#define EEMCONFIG (EEM_BASEADDR + 0x22C) +#define TSCALCS (EEM_BASEADDR + 0x230) +#define RUNCONFIG (EEM_BASEADDR + 0x234) +#define EEMEN (EEM_BASEADDR + 0x238) +#define INIT2VALS (EEM_BASEADDR + 0x23C) +#define DCVALUES (EEM_BASEADDR + 0x240) +#define AGEVALUES (EEM_BASEADDR + 0x244) +#define VOP30 (EEM_BASEADDR + 0x248) +#define VOP74 (EEM_BASEADDR + 0x24C) +#define TEMP (EEM_BASEADDR + 0x250) +#define EEMINTSTS (EEM_BASEADDR + 0x254) +#define EEMINTSTSRAW (EEM_BASEADDR + 0x258) +#define EEMINTEN (EEM_BASEADDR + 0x25C) +#define VDESIGN30 (EEM_BASEADDR + 0x26C) +#define VDESIGN74 (EEM_BASEADDR + 0x270) +#define AGECOUNT (EEM_BASEADDR + 0x27C) +#define SMSTATE0 (EEM_BASEADDR + 0x280) +#define SMSTATE1 (EEM_BASEADDR + 0x284) +#define EEMCORESEL (EEM_BASEADDR + 0x400) +/* +#define EEMODCORE3EN 19:19 +#define EEMODCORE2EN 18:18 +#define EEMODCORE1EN 17:17 +#define EEMODCORE0EN 16:16 +#define APBSEL 3:0 +#define APBSEL 2:0 +*/ +#define EEM_THERMINTST (EEM_BASEADDR + 0x404) +#define EEMODINTST (EEM_BASEADDR + 0x408) +/* +#define EEMODINT3 3:3 +#define EEMODINT2 2:2 +#define EEMODINT1 1:1 +#define EEMODINT0 0:0 +*/ +#define EEM_THSTAGE0ST (EEM_BASEADDR + 0x40C) +#define EEM_THSTAGE1ST (EEM_BASEADDR + 0x410) +#define EEM_THSTAGE2ST (EEM_BASEADDR + 0x414) +#define EEM_THAHBST0 (EEM_BASEADDR + 0x418) +#define EEM_THAHBST1 (EEM_BASEADDR + 0x41C) +#define EEMSPARE0 (EEM_BASEADDR + 0x420) +#define EEMSPARE1 (EEM_BASEADDR + 0x424) +#define EEMSPARE2 (EEM_BASEADDR + 0x428) +#define EEMSPARE3 (EEM_BASEADDR + 0x42C) +#define EEM_THSLPEVEB (EEM_BASEADDR + 0x430) + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_eem_turbo.c b/drivers/misc/mediatek/base/power/mt6755/mt_eem_turbo.c new file mode 100644 index 0000000000000000000000000000000000000000..14305d8d83ef339fc4633406f552dfb35dfcf219 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_eem_turbo.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) && defined(CONFIG_MTK_MT6750TT) +unsigned int tFyTbl[6] = {0x0e, 0xa, 0x1d, 0x8, 0x0, 0x116};/* 1.807 */ +unsigned int tSbTbl[6] = {0x0e, 0xa, 0x1d, 0x8, 0x0, 0x12c};/* 1.95 */ +unsigned int *tbl; +unsigned int *get_turbo(unsigned int binLevel, unsigned int binLevelEng) +{ + if ((1 == binLevel) || (3 == binLevel)) { + tbl = tFyTbl; + } else if ((2 == binLevel) || (4 == binLevel)) { + tbl = tFyTbl; + } else { + if ((2 == ((binLevelEng >> 4) & 0x07)) || (2 == ((binLevelEng >> 10) & 0x07))) + tbl = tFyTbl; + else + tbl = tFyTbl; + } + return tbl; +} +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_eem_turbo.h b/drivers/misc/mediatek/base/power/mt6755/mt_eem_turbo.h new file mode 100644 index 0000000000000000000000000000000000000000..5b0af7a7215a976be673d6c10cdd78774a9e5446 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_eem_turbo.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_EEM_TURBO_ +#define _MT_EEM_TURBO_ + +#ifdef __KERNEL__ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) && defined(CONFIG_MTK_MT6750TT) + extern unsigned int *get_turbo(unsigned int binLevel, unsigned int binLevelEng); +#endif +#endif +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq.c b/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq.c new file mode 100644 index 0000000000000000000000000000000000000000..4c655739f821a38e86bbec7d349cb031dfa28960 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq.c @@ -0,0 +1,3820 @@ +/* + * Copyright (C) 2015-2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#endif + +/* #include */ +#include + +/* #include "mach/mt_clkmgr.h" */ +#include "mt_cpufreq.h" +#include "mt_gpufreq.h" +#include "mt-plat/upmu_common.h" +#include "mt-plat/sync_write.h" +#include "mach/mt_pmic_wrap.h" + +#include "mach/mt_freqhopping.h" + +#define STATIC_PWR_READY2USE +#ifdef STATIC_PWR_READY2USE +#include "mt_static_power.h" +#endif + +#include "mach/mt_thermal.h" + +/* DLPT */ +#include "mach/mt_pbm.h" + +#include + +/* + * CONFIG + */ +/************************************************** + * Define low battery voltage support + ***************************************************/ +#define MT_GPUFREQ_LOW_BATT_VOLT_PROTECT + +/************************************************** + * Define low battery volume support + ***************************************************/ +#define MT_GPUFREQ_LOW_BATT_VOLUME_PROTECT + +/************************************************** + * Define oc support + ***************************************************/ +/* #define MT_GPUFREQ_OC_PROTECT */ + +/************************************************** + * GPU DVFS input boost feature + ***************************************************/ +#define MT_GPUFREQ_INPUT_BOOST + +/*************************** + * Define for dynamic power table update + ****************************/ +#define MT_GPUFREQ_DYNAMIC_POWER_TABLE_UPDATE + +/*************************** + * Define for random test + ****************************/ +/* #define MT_GPU_DVFS_RANDOM_TEST */ + +/*************************** + * Define for SRAM debugging + ****************************/ +#ifdef CONFIG_MTK_RAM_CONSOLE +#define MT_GPUFREQ_AEE_RR_REC +#endif + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#include "mt_vcorefs_manager.h" + +#define MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +#endif + +/* + * Define how to set up VGPU by + * PMIC_WRAP + * PMIC + */ +/* #define VGPU_SET_BY_PMIC_WRAP */ +#define VGPU_SET_BY_PMIC + +/************************************************** + * Define register write function + ***************************************************/ +#define mt_gpufreq_reg_write(val, addr) mt_reg_sync_writel((val), ((void *)addr)) + +/*************************** + * Operate Point Definition + ****************************/ +#define GPUOP(khz, volt, idx) \ +{ \ + .gpufreq_khz = khz, \ + .gpufreq_volt = volt, \ + .gpufreq_idx = idx, \ +} + +/************************** + * GPU DVFS OPP table setting + ***************************/ +#define GPU_DVFS_FREQT (806000) /* KHz */ +#define GPU_DVFS_FREQ0 (728000) /* KHz */ +#define GPU_DVFS_FREQ0_1 (676000) /* KHz */ +#define GPU_DVFS_FREQ1 (650000) /* KHz */ +#define GPU_DVFS_FREQ2 (598000) /* KHz */ +#define GPU_DVFS_FREQ3 (546000) /* KHz */ +#define GPU_DVFS_FREQ4 (520000) /* KHz */ +#define GPU_DVFS_FREQ5 (468000) /* KHz */ +#define GPU_DVFS_FREQ6 (429000) /* KHz */ +#define GPU_DVFS_FREQ7 (390000) /* KHz */ +#define GPU_DVFS_FREQ8 (351000) /* KHz */ +#define GPUFREQ_LAST_FREQ_LEVEL (GPU_DVFS_FREQ8) + +#define GPU_DVFS_VOLT0 (112500) /* mV x 100 */ +#define GPU_DVFS_VOLT1 (100000) /* mV x 100 */ +#define GPU_DVFS_VOLT2 (93125) /* mV x 100 */ +#define GPU_DVFS_VOLT3 (90000) /* mV x 100 */ + +#define GPU_DVFS_CTRL_VOLT (2) + +#define GPU_DVFS_PTPOD_DISABLE_VOLT GPU_DVFS_VOLT1 + +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +/***************************************** + * PMIC settle time (us), should not be changed + ******************************************/ +#define PMIC_CMD_DELAY_TIME 5 +#define MIN_PMIC_SETTLE_TIME 25 +#define PMIC_VOLT_UP_SETTLE_TIME(old_volt, new_volt) \ + (((((new_volt) - (old_volt)) + 1250 - 1) / 1250) + PMIC_CMD_DELAY_TIME) +#define PMIC_VOLT_DOWN_SETTLE_TIME(old_volt, new_volt) \ + (((((old_volt) - (new_volt)) * 2) / 625) + PMIC_CMD_DELAY_TIME) +#define PMIC_VOLT_ON_OFF_DELAY_US (400) +/* #define GPU_DVFS_PMIC_SETTLE_TIME (40) // us */ + +#define PMIC_BUCK_VGPU_VOSEL_ON MT6351_PMIC_BUCK_VGPU_VOSEL_ON +#define PMIC_ADDR_VGPU_VOSEL_ON MT6351_PMIC_BUCK_VGPU_VOSEL_ON_ADDR +#define PMIC_ADDR_VGPU_VOSEL_ON_MASK MT6351_PMIC_BUCK_VGPU_VOSEL_ON_MASK +#define PMIC_ADDR_VGPU_VOSEL_ON_SHIFT MT6351_PMIC_BUCK_VGPU_VOSEL_ON_SHIFT +#define PMIC_ADDR_VGPU_VOSEL_CTRL MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_ADDR +#define PMIC_ADDR_VGPU_VOSEL_CTRL_MASK MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_MASK +#define PMIC_ADDR_VGPU_VOSEL_CTRL_SHIFT MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_SHIFT +#define PMIC_ADDR_VGPU_EN MT6351_PMIC_BUCK_VGPU_EN_ADDR +#define PMIC_ADDR_VGPU_EN_MASK MT6351_PMIC_BUCK_VGPU_EN_MASK +#define PMIC_ADDR_VGPU_EN_SHIFT MT6351_PMIC_BUCK_VGPU_EN_SHIFT +#define PMIC_ADDR_VGPU_EN_CTRL MT6351_PMIC_BUCK_VGPU_EN_CTRL_ADDR +#define PMIC_ADDR_VGPU_EN_CTRL_MASK MT6351_PMIC_BUCK_VGPU_EN_CTRL_MASK +#define PMIC_ADDR_VGPU_EN_CTRL_SHIFT MT6351_PMIC_BUCK_VGPU_EN_CTRL_SHIFT +#endif + +/* efuse */ +#define GPUFREQ_EFUSE_INDEX (4) +#define EFUSE_MFG_SPD_BOND_SHIFT (27) +#define EFUSE_MFG_SPD_BOND_MASK (0xF) + +#define MFG_PWR_STA_MASK BIT(4) + +/* + * LOG + */ +#define TAG "[gpufreq] " + +#define gpufreq_err(fmt, args...) \ + pr_err(TAG"[ERROR]"fmt, ##args) +#define gpufreq_warn(fmt, args...) \ + pr_warn(TAG"[WARNING]"fmt, ##args) +#define gpufreq_info(fmt, args...) \ + pr_warn(TAG""fmt, ##args) +#define gpufreq_dbg(fmt, args...) \ + do { \ + if (mt_gpufreq_debug) \ + pr_warn(TAG""fmt, ##args); \ + } while (0) +#define gpufreq_ver(fmt, args...) \ + do { \ + if (mt_gpufreq_debug) \ + pr_debug(TAG""fmt, ##args); \ + } while (0) + + +static sampler_func g_pFreqSampler; +static sampler_func g_pVoltSampler; + +static gpufreq_power_limit_notify g_pGpufreq_power_limit_notify; +#ifdef MT_GPUFREQ_INPUT_BOOST +static gpufreq_input_boost_notify g_pGpufreq_input_boost_notify; +#endif + +#if defined(CONFIG_OF) +static unsigned long apmixed_base; + +#define APMIXED_NODE "mediatek,apmixed" +#define APMIXED_BASE (apmixed_base) /* 0x1000C000 */ + +#define GPUFREQ_NODE "mediatek,mt6755-gpufreq" +static const struct of_device_id mt_gpufreq_of_match[] = { + {.compatible = GPUFREQ_NODE,}, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mt_gpufreq_of_match); +#else /* !defined(CONFIG_OF) */ +#define APMIXED_BASE 0x1000C000 +#endif + +#define APMIXED_MMPLL_CON1 (APMIXED_BASE + 0x244) /* 0x1000C244 */ + +/*************************** + * GPU DVFS OPP Table + ****************************/ +/* Segment1: Free */ +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +static struct mt_gpufreq_table_info mt_gpufreq_opp_tbl_e1_0[] = { + GPUOP(GPU_DVFS_FREQ0, GPU_DVFS_VOLT0, 0), + GPUOP(GPU_DVFS_FREQ1, GPU_DVFS_VOLT0, 1), + GPUOP(GPU_DVFS_FREQ2, GPU_DVFS_VOLT0, 2), + GPUOP(GPU_DVFS_FREQ4, GPU_DVFS_VOLT1, 3), + GPUOP(GPU_DVFS_FREQ5, GPU_DVFS_VOLT1, 4), + GPUOP(GPU_DVFS_FREQ6, GPU_DVFS_VOLT1, 5), + GPUOP(GPU_DVFS_FREQ7, GPU_DVFS_VOLT1, 6), + GPUOP(GPU_DVFS_FREQ8, GPU_DVFS_VOLT2, 7), +}; + +/* Segment2: 550M */ +static struct mt_gpufreq_table_info mt_gpufreq_opp_tbl_e1_1[] = { + GPUOP(GPU_DVFS_FREQ3, GPU_DVFS_VOLT0, 0), + GPUOP(GPU_DVFS_FREQ4, GPU_DVFS_VOLT1, 1), + GPUOP(GPU_DVFS_FREQ5, GPU_DVFS_VOLT1, 2), + GPUOP(GPU_DVFS_FREQ6, GPU_DVFS_VOLT1, 3), + GPUOP(GPU_DVFS_FREQ7, GPU_DVFS_VOLT1, 4), + GPUOP(GPU_DVFS_FREQ8, GPU_DVFS_VOLT2, 5), +}; + +/* MT6755T: 800M Turbo */ +static struct mt_gpufreq_table_info mt_gpufreq_opp_tbl_e1_t[] = { + GPUOP(GPU_DVFS_FREQT, GPU_DVFS_VOLT0, 0), + GPUOP(GPU_DVFS_FREQ0, GPU_DVFS_VOLT0, 1), + GPUOP(GPU_DVFS_FREQ1, GPU_DVFS_VOLT0, 2), + GPUOP(GPU_DVFS_FREQ2, GPU_DVFS_VOLT0, 3), + GPUOP(GPU_DVFS_FREQ4, GPU_DVFS_VOLT1, 4), + GPUOP(GPU_DVFS_FREQ5, GPU_DVFS_VOLT1, 5), + GPUOP(GPU_DVFS_FREQ7, GPU_DVFS_VOLT1, 6), + GPUOP(GPU_DVFS_FREQ8, GPU_DVFS_VOLT2, 7), +}; +#else +/* For E2 segment, GPU is sourced from Vcore */ +/* E2 Segment1: 680M */ +static struct mt_gpufreq_table_info mt_gpufreq_opp_tbl_e2_0[] = { + GPUOP(GPU_DVFS_FREQ0_1, GPU_DVFS_VOLT1, 0), + GPUOP(GPU_DVFS_FREQ4, GPU_DVFS_VOLT1, 1), + GPUOP(GPU_DVFS_FREQ8, GPU_DVFS_VOLT3, 2), +}; + +/* Segment2: 520M */ +static struct mt_gpufreq_table_info mt_gpufreq_opp_tbl_e2_1[] = { + GPUOP(GPU_DVFS_FREQ4, GPU_DVFS_VOLT1, 0), + GPUOP(GPU_DVFS_FREQ8, GPU_DVFS_VOLT1, 1), +}; + +/* Segment3: 350M */ +static struct mt_gpufreq_table_info mt_gpufreq_opp_tbl_e2_2[] = { + GPUOP(GPU_DVFS_FREQ8, GPU_DVFS_VOLT1, 0), +}; + +/* fake Segment2: 520M */ +static struct mt_gpufreq_table_info mt_gpufreq_opp_tbl_e2_3[] = { + GPUOP(GPU_DVFS_FREQ4, GPU_DVFS_VOLT1, 0), + GPUOP(GPU_DVFS_FREQ8, GPU_DVFS_VOLT3, 1), +}; + +/* fake Segment3: 350M */ +static struct mt_gpufreq_table_info mt_gpufreq_opp_tbl_e2_4[] = { + GPUOP(GPU_DVFS_FREQ8, GPU_DVFS_VOLT3, 0), +}; +#endif + +/* + * AEE (SRAM debug) + */ +#ifdef MT_GPUFREQ_AEE_RR_REC +enum gpu_dvfs_state { + GPU_DVFS_IS_DOING_DVFS = 0, + GPU_DVFS_IS_VGPU_ENABLED, +}; + +static void _mt_gpufreq_aee_init(void) +{ + aee_rr_rec_gpu_dvfs_vgpu(0xFF); + aee_rr_rec_gpu_dvfs_oppidx(0xFF); + aee_rr_rec_gpu_dvfs_status(0xFC); +} +#endif + +/************************** + * enable GPU DVFS count + ***************************/ +static int g_gpufreq_dvfs_disable_count; + +static unsigned int g_cur_gpu_freq = 520000; /* initial value */ +static unsigned int g_cur_gpu_volt = 100000; /* initial value */ +static unsigned int g_cur_gpu_idx = 0xFF; +static unsigned int g_cur_gpu_OPPidx = 0xFF; + +static unsigned int g_cur_freq_init_keep; + +static bool mt_gpufreq_ready; + +/* In default settiing, freq_table[0] is max frequency, freq_table[num-1] is min frequency,*/ +static unsigned int g_gpufreq_max_id; + +/* If not limited, it should be set to freq_table[0] (MAX frequency) */ +static unsigned int g_limited_max_id; +static unsigned int g_limited_min_id; + +static bool mt_gpufreq_debug; +static bool mt_gpufreq_pause; +static bool mt_gpufreq_keep_max_frequency_state; +static bool mt_gpufreq_keep_opp_frequency_state; +static unsigned int mt_gpufreq_keep_opp_frequency; +static unsigned int mt_gpufreq_keep_opp_index; +static bool mt_gpufreq_fixed_freq_volt_state; +static unsigned int mt_gpufreq_fixed_frequency; +static unsigned int mt_gpufreq_fixed_voltage; + +static unsigned int mt_gpufreq_volt_enable; +static unsigned int mt_gpufreq_volt_enable_state; +static bool mt_gpufreq_keep_volt_enable; +#ifdef MT_GPUFREQ_INPUT_BOOST +static unsigned int mt_gpufreq_input_boost_state = 1; +#endif +/* static bool g_limited_power_ignore_state = false; */ +static bool g_limited_thermal_ignore_state; +#ifdef MT_GPUFREQ_LOW_BATT_VOLT_PROTECT +static bool g_limited_low_batt_volt_ignore_state; +#endif +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_PROTECT +static bool g_limited_low_batt_volume_ignore_state; +#endif +#ifdef MT_GPUFREQ_OC_PROTECT +static bool g_limited_oc_ignore_state; +#endif + +static bool mt_gpufreq_opp_max_frequency_state; +static unsigned int mt_gpufreq_opp_max_frequency; +static unsigned int mt_gpufreq_opp_max_index; + +static unsigned int mt_gpufreq_dvfs_table_type; +static unsigned int mt_gpufreq_dvfs_mmpll_spd_bond; + +/* static DEFINE_SPINLOCK(mt_gpufreq_lock); */ +static DEFINE_MUTEX(mt_gpufreq_lock); +static DEFINE_MUTEX(mt_gpufreq_power_lock); + +static unsigned int mt_gpufreqs_num; +static struct mt_gpufreq_table_info *mt_gpufreqs; +static struct mt_gpufreq_table_info *mt_gpufreqs_default; +static struct mt_gpufreq_power_table_info *mt_gpufreqs_power; +static struct mt_gpufreq_clk_t *mt_gpufreq_clk; +/* static struct mt_gpufreq_power_table_info *mt_gpufreqs_default_power; */ + +static bool mt_gpufreq_ptpod_disable; + +static int mt_gpufreq_ptpod_disable_idx; + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_POLLING_TIMER +static int mt_gpufreq_low_batt_volume_timer_flag; +static DECLARE_WAIT_QUEUE_HEAD(mt_gpufreq_low_batt_volume_timer_waiter); +static struct hrtimer mt_gpufreq_low_batt_volume_timer; +static int mt_gpufreq_low_batt_volume_period_s = 1; +static int mt_gpufreq_low_batt_volume_period_ns; +struct task_struct *mt_gpufreq_low_batt_volume_thread = NULL; +#endif + +static void mt_gpufreq_clock_switch(unsigned int freq_new); +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +static int mt_gpufreq_volt_switch(unsigned int new_oppidx); +static int mt_gpufreq_set(unsigned int freq_old, unsigned int freq_new, + unsigned int new_oppidx); +#else +static void mt_gpufreq_volt_switch(unsigned int volt_old, unsigned int volt_new); +static void mt_gpufreq_set(unsigned int freq_old, unsigned int freq_new, + unsigned int volt_old, unsigned int volt_new); +#endif +static unsigned int _mt_gpufreq_get_cur_volt(void); +static unsigned int _mt_gpufreq_get_cur_freq(void); +static void _mt_gpufreq_kick_pbm(int enable); + +#ifndef DISABLE_PBM_FEATURE +static bool g_limited_pbm_ignore_state; +static unsigned int mt_gpufreq_pbm_limited_gpu_power; /* PBM limit power */ +static unsigned int mt_gpufreq_pbm_limited_index; /* Limited frequency index for PBM */ +#define GPU_OFF_SETTLE_TIME_MS (100) +struct delayed_work notify_pbm_gpuoff_work; +#endif + +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +static int g_last_gpu_dvs_result = 0x7F; +static unsigned int fake_segment; +#endif + +/* weak function declaration */ +int __attribute__((weak)) get_immediate_gpu_wrap(void) +{ + return 40000; +} + +int __attribute__((weak)) mtk_gpufreq_register(struct mt_gpufreq_power_table_info *freqs, int num) +{ + return 0; +} + +void __attribute__((weak)) kicker_pbm_by_gpu(bool status, unsigned int loading, int voltage) +{ +} + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_POLLING_TIMER +enum hrtimer_restart mt_gpufreq_low_batt_volume_timer_func(struct hrtimer *timer) +{ + mt_gpufreq_low_batt_volume_timer_flag = 1; + wake_up_interruptible(&mt_gpufreq_low_batt_volume_timer_waiter); + return HRTIMER_NORESTART; +} + +int mt_gpufreq_low_batt_volume_thread_handler(void *unused) +{ + do { + ktime_t ktime = + ktime_set(mt_gpufreq_low_batt_volume_period_s, + mt_gpufreq_low_batt_volume_period_ns); + + wait_event_interruptible(mt_gpufreq_low_batt_volume_timer_waiter, + mt_gpufreq_low_batt_volume_timer_flag != 0); + mt_gpufreq_low_batt_volume_timer_flag = 0; + + gpufreq_dbg("@%s: begin\n", __func__); + mt_gpufreq_low_batt_volume_check(); + + hrtimer_start(&mt_gpufreq_low_batt_volume_timer, ktime, HRTIMER_MODE_REL); + + } while (!kthread_should_stop()); + + return 0; +} + +void mt_gpufreq_cancel_low_batt_volume_timer(void) +{ + hrtimer_cancel(&mt_gpufreq_low_batt_volume_timer); +} +EXPORT_SYMBOL(mt_gpufreq_cancel_low_batt_volume_timer); + +void mt_gpufreq_start_low_batt_volume_timer(void) +{ + ktime_t ktime = + ktime_set(mt_gpufreq_low_batt_volume_period_s, mt_gpufreq_low_batt_volume_period_ns); + hrtimer_start(&mt_gpufreq_low_batt_volume_timer, ktime, HRTIMER_MODE_REL); +} +EXPORT_SYMBOL(mt_gpufreq_start_low_batt_volume_timer); +#endif + + +/************************************************************************************* + * Check GPU DVFS Efuse + **************************************************************************************/ +static unsigned int mt_gpufreq_get_dvfs_table_type(void) +{ + unsigned int type = 0; + unsigned int segment = get_devinfo_with_index(21) & 0xFF; +#ifdef CONFIG_OF + static const struct of_device_id gpu_ids[] = { + {.compatible = "arm,malit6xx"}, + {.compatible = "arm,mali-midgard"}, + { /* sentinel */ } + }; + struct device_node *node; +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + unsigned int gpu_speed = 0; +#endif +#endif + +#ifdef CONFIG_ARCH_MT6755_TURBO + gpufreq_info("check if GPU freq can be turbo by segment=0x%x\n", segment); + if (segment == 0x22) + return 3; +#endif + +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +#ifdef CONFIG_OF + node = of_find_matching_node(NULL, gpu_ids); + if (!node) + gpufreq_info("@%s: no GPU node found\n", __func__); + else { + if (!of_property_read_u32(node, "fake-segment", &fake_segment)) + gpufreq_info("@%s: fake_segment=%d\n", __func__, fake_segment); + else + gpufreq_info("@%s: no fake-segment property\n", __func__); + } +#endif + + gpufreq_info("Segment code = 0x%x\n", segment); + + switch (segment) { + case 0x42: + case 0x46: + type = 1; + break; + case 0x43: + case 0x4B: + type = 2; + break; + case 0x41: + case 0x45: + default: + type = 0; + break; + } + + return type; +#else /* !MT_GPUFREQ_GPU_SOURCE_FROM_VCORE */ + + mt_gpufreq_dvfs_mmpll_spd_bond = (get_devinfo_with_index(GPUFREQ_EFUSE_INDEX) >> + EFUSE_MFG_SPD_BOND_SHIFT) & EFUSE_MFG_SPD_BOND_MASK; + gpufreq_info("GPU frequency bounding from efuse = 0x%x\n", mt_gpufreq_dvfs_mmpll_spd_bond); + + /* No efuse or free run? use clock-frequency from device tree to determine GPU table type! */ + if (mt_gpufreq_dvfs_mmpll_spd_bond == 0) { + /* Check segment_code if no efuse */ + if ((segment == 0x1) || (segment == 0x3) || (segment == 0x5) || + (segment == 0x7)) { + gpufreq_info("Set as 6755M since segment=0x%x\n", segment); + return 1; /* Segment2: 550M */ + } + +#ifdef CONFIG_OF + node = of_find_matching_node(NULL, gpu_ids); + if (!node) { + gpufreq_err("@%s: find GPU node failed\n", __func__); + gpu_speed = 700; /* default speed */ + } else { + if (!of_property_read_u32(node, "clock-frequency", &gpu_speed)) { + gpu_speed = gpu_speed / 1000 / 1000; /* MHz */ + } else { + gpufreq_err + ("@%s: missing clock-frequency property, use default GPU level\n", + __func__); + gpu_speed = 700; /* default speed */ + } + } + gpufreq_info("GPU clock-frequency from DT = %d MHz\n", gpu_speed); + + if (gpu_speed >= 700) + type = 0; /* Segment1: Free */ + else if (gpu_speed >= 550) + type = 1; /* Segment2: 550M */ +#else + gpufreq_err("@%s: Cannot get GPU speed from DT!\n", __func__); + type = 0; +#endif + return type; + } + + switch (mt_gpufreq_dvfs_mmpll_spd_bond) { + case 1: + case 2: + type = 0; /* Segment1: Free */ + break; + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + default: + type = 1; /* Segment2: 550M */ + break; + } + + return type; +#endif +} + +#ifdef MT_GPUFREQ_INPUT_BOOST +static struct task_struct *mt_gpufreq_up_task; + +static int mt_gpufreq_input_boost_task(void *data) +{ + while (1) { + gpufreq_dbg("@%s: begin\n", __func__); + + if (NULL != g_pGpufreq_input_boost_notify) { + gpufreq_dbg("@%s: g_pGpufreq_input_boost_notify\n", __func__); + g_pGpufreq_input_boost_notify(g_gpufreq_max_id); + } + + gpufreq_dbg("@%s: end\n", __func__); + + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + + if (kthread_should_stop()) + break; + } + + return 0; +} + +static void mt_gpufreq_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + return; + } + + if ((type == EV_KEY) && (code == BTN_TOUCH) && (value == 1) + && (mt_gpufreq_input_boost_state == 1)) { + gpufreq_dbg("@%s: accept.\n", __func__); + + /* if ((g_cur_gpu_freq < mt_gpufreqs[g_gpufreq_max_id].gpufreq_khz) && + * (g_cur_gpu_freq < mt_gpufreqs[g_limited_max_id].gpufreq_khz)) */ + /* { */ + wake_up_process(mt_gpufreq_up_task); + /* } */ + } +} + +static int mt_gpufreq_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "gpufreq_ib"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + + return 0; +err1: + input_unregister_handle(handle); +err2: + kfree(handle); + return error; +} + +static void mt_gpufreq_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id mt_gpufreq_ids[] = { + {.driver_info = 1}, + {}, +}; + +static struct input_handler mt_gpufreq_input_handler = { + .event = mt_gpufreq_input_event, + .connect = mt_gpufreq_input_connect, + .disconnect = mt_gpufreq_input_disconnect, + .name = "gpufreq_ib", + .id_table = mt_gpufreq_ids, +}; +#endif + +/* + * Power table calculation + */ +static void mt_gpufreq_power_calculation(unsigned int idx, unsigned int freq, + unsigned int volt, unsigned int temp) +{ +#define GPU_ACT_REF_POWER 1025 /* mW */ +#define GPU_ACT_REF_FREQ 728000 /* KHz */ +#define GPU_ACT_REF_VOLT 100000 /* mV x 100 */ + + unsigned int p_total = 0, p_dynamic = 0, p_leakage = 0, ref_freq = 0, ref_volt = 0; + + p_dynamic = GPU_ACT_REF_POWER; + ref_freq = GPU_ACT_REF_FREQ; + ref_volt = GPU_ACT_REF_VOLT; + + p_dynamic = p_dynamic * + ((freq * 100) / ref_freq) * + ((volt * 100) / ref_volt) * ((volt * 100) / ref_volt) / (100 * 100 * 100); + +#ifdef STATIC_PWR_READY2USE + p_leakage = + mt_spower_get_leakage(MT_SPOWER_GPU, (volt / 100), temp); +#else + p_leakage = 130; +#endif + + p_total = p_dynamic + p_leakage; + + gpufreq_ver("%d: p_dynamic = %d, p_leakage = %d, p_total = %d\n", + idx, p_dynamic, p_leakage, p_total); + + mt_gpufreqs_power[idx].gpufreq_power = p_total; +} + +/************************************** + * Random seed generated for test + ***************************************/ +#ifdef MT_GPU_DVFS_RANDOM_TEST +static int mt_gpufreq_idx_get(int num) +{ + int random = 0, mult = 0, idx; + + random = jiffies & 0xF; + + while (1) { + if ((mult * num) >= random) { + idx = (mult * num) - random; + break; + } + mult++; + } + return idx; +} +#endif + +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +/************************************** + * Convert pmic wrap register to voltage + ***************************************/ +static unsigned int mt_gpufreq_pmic_wrap_to_volt(unsigned int pmic_wrap_value) +{ + unsigned int volt = 0; + + volt = (pmic_wrap_value * 625) + 60000; + + gpufreq_dbg("@%s: volt = %d\n", __func__, volt); + + /* 1.39375V */ + if (volt > 139375) { + gpufreq_err("@%s: volt > 1.39375v!\n", __func__); + return 139375; + } + + return volt; +} +#endif + +/************************************** + * Convert voltage to pmic wrap register + ***************************************/ +static unsigned int mt_gpufreq_volt_to_pmic_wrap(unsigned int volt) +{ + unsigned int reg_val = 0; + + reg_val = (volt - 60000) / 625; + + gpufreq_dbg("@%s: reg_val = %d\n", __func__, reg_val); + + if (reg_val > 0x7F) { + gpufreq_err("@%s: reg_val > 0x7F!\n", __func__); + return 0x7F; + } + + return reg_val; +} + +/* Set frequency and voltage at driver probe function */ +static void mt_gpufreq_set_initial(void) +{ + unsigned int cur_volt = 0, cur_freq = 0; + int i = 0; + + mutex_lock(&mt_gpufreq_lock); + +#ifdef MT_GPUFREQ_AEE_RR_REC + aee_rr_rec_gpu_dvfs_status(aee_rr_curr_gpu_dvfs_status() | (1 << GPU_DVFS_IS_DOING_DVFS)); +#endif + + cur_volt = _mt_gpufreq_get_cur_volt(); + cur_freq = _mt_gpufreq_get_cur_freq(); + +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + /* slow down gpu freq for MT6738 since default freq is 520MHz */ + if (cur_freq > mt_gpufreqs[g_gpufreq_max_id].gpufreq_khz) + mt_gpufreq_clock_switch(mt_gpufreqs[g_gpufreq_max_id].gpufreq_khz); + + /* keep in default freq since Vcore DVFS is not ready yet */ + for (i = 0; i < mt_gpufreqs_num; i++) { + if (cur_freq == mt_gpufreqs[i].gpufreq_khz) { + g_cur_gpu_OPPidx = i; + gpufreq_dbg("init_idx = %d\n", g_cur_gpu_OPPidx); + _mt_gpufreq_kick_pbm(1); + break; + } + } +#else + for (i = 0; i < mt_gpufreqs_num; i++) { + if (cur_volt == mt_gpufreqs[i].gpufreq_volt) { + mt_gpufreq_clock_switch(mt_gpufreqs[i].gpufreq_khz); + g_cur_gpu_OPPidx = i; + gpufreq_dbg("init_idx = %d\n", g_cur_gpu_OPPidx); + _mt_gpufreq_kick_pbm(1); + break; + } + } + + /* Not found, set to LPM */ + if (i == mt_gpufreqs_num) { + gpufreq_err + ("Set to LPM since GPU idx not found according to current Vcore = %d mV\n", + cur_volt / 100); + g_cur_gpu_OPPidx = mt_gpufreqs_num - 1; + mt_gpufreq_set(cur_freq, mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_khz, + cur_volt, mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt); + } +#endif + + g_cur_gpu_freq = mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_khz; + g_cur_gpu_volt = mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt; + g_cur_gpu_idx = mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_idx; + +#ifdef MT_GPUFREQ_AEE_RR_REC + aee_rr_rec_gpu_dvfs_oppidx(g_cur_gpu_OPPidx); + aee_rr_rec_gpu_dvfs_status(aee_rr_curr_gpu_dvfs_status() & ~(1 << GPU_DVFS_IS_DOING_DVFS)); +#endif + + mutex_unlock(&mt_gpufreq_lock); +} + +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +static unsigned int mt_gpufreq_calc_pmic_settle_time(unsigned int volt_old, unsigned int volt_new) +{ + unsigned int delay = 100; + + if (volt_new == volt_old) + return 0; + else if (volt_new > volt_old) + delay = PMIC_VOLT_UP_SETTLE_TIME(volt_old, volt_new); + else + delay = PMIC_VOLT_DOWN_SETTLE_TIME(volt_old, volt_new); + + if (delay < MIN_PMIC_SETTLE_TIME) + delay = MIN_PMIC_SETTLE_TIME; + + return delay; +} +#endif + +#ifndef DISABLE_PBM_FEATURE +static void mt_gpufreq_notify_pbm_gpuoff(struct work_struct *work) +{ + mutex_lock(&mt_gpufreq_lock); + if (!mt_gpufreq_volt_enable_state) + _mt_gpufreq_kick_pbm(0); + + mutex_unlock(&mt_gpufreq_lock); +} +#endif + +/* Set VGPU enable/disable when GPU clock be switched on/off */ +unsigned int mt_gpufreq_voltage_enable_set(unsigned int enable) +{ + int ret = 0; + + if (enable == 0) + if ((DRV_Reg32(PWR_STATUS) & MFG_PWR_STA_MASK) || + (DRV_Reg32(PWR_STATUS_2ND) & MFG_PWR_STA_MASK)) { + gpufreq_dbg("@%s, VGPU should keep on since MTCMOS cannot be turned off!\n", + __func__); + return -ENOSYS; + } + + mutex_lock(&mt_gpufreq_lock); + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + ret = -ENOSYS; + goto exit; + } + + if (enable == mt_gpufreq_volt_enable_state) { + ret = 0; + goto exit; + } + + if (enable == 0) { + if (mt_gpufreq_ptpod_disable) { + gpufreq_info("mt_gpufreq_ptpod_disable is true\n"); + ret = -ENOSYS; + goto exit; + } + if (mt_gpufreq_keep_volt_enable) { + gpufreq_dbg("mt_gpufreq_keep_volt_enable is true\n"); + ret = -ENOSYS; + goto exit; + } + } + +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + if ((is_vcorefs_can_work() < 0) || + (mt_gpufreq_dvfs_table_type == 1 && fake_segment != 2) || + (mt_gpufreq_dvfs_table_type == 2)) + goto end; + + if (enable == 0) { + /* no need to unreq if current freq is not over GPU_DVFS_FREQ8 */ + if (mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_khz > GPU_DVFS_FREQ8) + vcorefs_request_dvfs_opp(KIR_GPU, OPPI_UNREQ); + } else { + unsigned int cur_volt = _mt_gpufreq_get_cur_volt(); + int need_kick_pbm = 0; + + /* Vcore changed, need to kick PBM */ + if (cur_volt != mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt) + need_kick_pbm = 1; + + /* Check need to raise Vcore or not */ + if (cur_volt >= mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt) + goto done; + + ret = mt_gpufreq_volt_switch(g_cur_gpu_OPPidx); + + if (ret) { + unsigned int cur_freq = _mt_gpufreq_get_cur_freq(); + + gpufreq_err("@%s: Set Vcore to %dmV failed! ret = %d, cur_freq = %d\n", + __func__, + mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt / 100, + ret, + cur_freq + ); + + /* Raise Vcore failed, set GPU freq to corresponding LV */ + if (cur_volt < mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt) { + unsigned int i; + + for (i = 0; i < mt_gpufreqs_num; i++) { + if (cur_volt == mt_gpufreqs[i].gpufreq_volt) { + mt_gpufreq_clock_switch(mt_gpufreqs[i].gpufreq_khz); + g_cur_gpu_OPPidx = i; + } + } + + if (i == mt_gpufreqs_num) { + gpufreq_err("@%s: Volt not found, set to lowest freq!\n", + __func__); + mt_gpufreq_clock_switch( + mt_gpufreqs[mt_gpufreqs_num - 1].gpufreq_khz); + g_cur_gpu_OPPidx = mt_gpufreqs_num - 1; + } + } + } + +done: + if (need_kick_pbm) + _mt_gpufreq_kick_pbm(1); + } + +end: +#else /* MT_GPUFREQ_GPU_SOURCE_FROM_VCORE */ + { + unsigned int delay = 0; + unsigned short rg_buck_gpu_en = 0, rg_da_qi_gpu_en = 0; + + if (enable == 1) + pmic_config_interface(PMIC_ADDR_VGPU_EN, 0x1, + PMIC_ADDR_VGPU_EN_MASK, + PMIC_ADDR_VGPU_EN_SHIFT); /* Set VGPU_EN[0] to 1 */ + else + pmic_config_interface(PMIC_ADDR_VGPU_EN, 0x0, + PMIC_ADDR_VGPU_EN_MASK, + PMIC_ADDR_VGPU_EN_SHIFT); /* Set VGPU_EN[0] to 0 */ + + /* (g_cur_gpu_volt / 1250) + 26; */ + /* delay = mt_gpufreq_calc_pmic_settle_time(0, g_cur_gpu_volt); */ + delay = PMIC_VOLT_ON_OFF_DELAY_US; + gpufreq_dbg("@%s: enable = %x, delay = %d\n", __func__, enable, delay); + udelay(delay); + +#ifdef MT_GPUFREQ_AEE_RR_REC + if (enable == 1) + aee_rr_rec_gpu_dvfs_status(aee_rr_curr_gpu_dvfs_status() | + (1 << GPU_DVFS_IS_VGPU_ENABLED)); + else + aee_rr_rec_gpu_dvfs_status(aee_rr_curr_gpu_dvfs_status() & + ~(1 << GPU_DVFS_IS_VGPU_ENABLED)); +#endif + + rg_buck_gpu_en = pmic_get_register_value(PMIC_BUCK_VGPU_EN); + rg_da_qi_gpu_en = pmic_get_register_value(PMIC_DA_QI_VGPU_EN); + + /* Error checking */ + if (enable == 1 && (rg_buck_gpu_en == 0 || rg_da_qi_gpu_en == 0)) { + /* VGPU enable fail, dump info and trigger BUG() */ + int i = 0; + + gpufreq_err("@%s: enable=%x, delay=%d, buck_gpu_en=%u, da_qi_gpu_en=%u\n", + __func__, enable, delay, rg_buck_gpu_en, + rg_da_qi_gpu_en); + + /* read PMIC chip id via PMIC wrapper */ + for (i = 0; i < 10; i++) { + gpufreq_err("@%s: PMIC_HWCID=0x%x\n", __func__, + pmic_get_register_value(PMIC_HWCID)); + } + + BUG(); + } + +#ifndef DISABLE_PBM_FEATURE + if (enable == 1) { + if (delayed_work_pending(¬ify_pbm_gpuoff_work)) + cancel_delayed_work(¬ify_pbm_gpuoff_work); + else + _mt_gpufreq_kick_pbm(1); + } else { + schedule_delayed_work(¬ify_pbm_gpuoff_work, + msecs_to_jiffies(GPU_OFF_SETTLE_TIME_MS)); + } +#endif + } +#endif /* MT_GPUFREQ_GPU_SOURCE_FROM_VCORE */ + + mt_gpufreq_volt_enable_state = enable; +exit: + mutex_unlock(&mt_gpufreq_lock); + + return ret; +} +EXPORT_SYMBOL(mt_gpufreq_voltage_enable_set); + +/************************************************ + * DVFS enable API for PTPOD + *************************************************/ +void mt_gpufreq_enable_by_ptpod(void) +{ +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + mt_gpufreq_ptpod_disable = false; + gpufreq_info("mt_gpufreq enabled by ptpod\n"); +#endif +} +EXPORT_SYMBOL(mt_gpufreq_enable_by_ptpod); + +/************************************************ + * DVFS disable API for PTPOD + *************************************************/ +void mt_gpufreq_disable_by_ptpod(void) +{ +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + int i = 0, volt_level_reached = 0, target_idx = 0; + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + return; + } + + mt_gpufreq_ptpod_disable = true; + gpufreq_info("mt_gpufreq disabled by ptpod\n"); + + for (i = 0; i < mt_gpufreqs_num; i++) { + /* VBoot = 1v for PTPOD */ + if (mt_gpufreqs_default[i].gpufreq_volt == GPU_DVFS_PTPOD_DISABLE_VOLT) { + volt_level_reached = 1; + if (i == (mt_gpufreqs_num - 1)) { + target_idx = i; + break; + } + } else { + if (volt_level_reached == 1) { + target_idx = i - 1; + break; + } + } + } + + mt_gpufreq_ptpod_disable_idx = target_idx; + + mt_gpufreq_voltage_enable_set(1); + mt_gpufreq_target(target_idx); +#endif +} +EXPORT_SYMBOL(mt_gpufreq_disable_by_ptpod); + +/************************************************ + * API to switch back default voltage setting for GPU PTPOD disabled + *************************************************/ +void mt_gpufreq_restore_default_volt(void) +{ +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + int i; + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + return; + } + + mutex_lock(&mt_gpufreq_lock); + + for (i = 0; i < mt_gpufreqs_num; i++) { + mt_gpufreqs[i].gpufreq_volt = mt_gpufreqs_default[i].gpufreq_volt; + gpufreq_dbg("@%s: mt_gpufreqs[%d].gpufreq_volt = %x\n", __func__, i, + mt_gpufreqs[i].gpufreq_volt); + } + + mt_gpufreq_volt_switch(g_cur_gpu_volt, mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt); + + g_cur_gpu_volt = mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt; + + mutex_unlock(&mt_gpufreq_lock); +#endif +} +EXPORT_SYMBOL(mt_gpufreq_restore_default_volt); + +/* Set voltage because PTP-OD modified voltage table by PMIC wrapper */ +unsigned int mt_gpufreq_update_volt(unsigned int pmic_volt[], unsigned int array_size) +{ +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + return 0; +#else + int i; /* , idx; */ + /* unsigned long flags; */ + unsigned volt = 0; + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + return -ENOSYS; + } + + mutex_lock(&mt_gpufreq_lock); + + for (i = 0; i < array_size; i++) { + volt = mt_gpufreq_pmic_wrap_to_volt(pmic_volt[i]); + mt_gpufreqs[i].gpufreq_volt = volt; + gpufreq_dbg("@%s: mt_gpufreqs[%d].gpufreq_volt = %x\n", __func__, i, + mt_gpufreqs[i].gpufreq_volt); + } + + mt_gpufreq_volt_switch(g_cur_gpu_volt, mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt); + + g_cur_gpu_volt = mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt; + + mutex_unlock(&mt_gpufreq_lock); + + return 0; +#endif +} +EXPORT_SYMBOL(mt_gpufreq_update_volt); + +unsigned int mt_gpufreq_get_dvfs_table_num(void) +{ + return mt_gpufreqs_num; +} +EXPORT_SYMBOL(mt_gpufreq_get_dvfs_table_num); + +unsigned int mt_gpufreq_get_freq_by_idx(unsigned int idx) +{ + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + return -ENOSYS; + } + + if (idx < mt_gpufreqs_num) { + gpufreq_dbg("@%s: idx = %d, frequency= %d\n", __func__, idx, + mt_gpufreqs[idx].gpufreq_khz); + return mt_gpufreqs[idx].gpufreq_khz; + } + + gpufreq_dbg("@%s: idx = %d, NOT found! return 0!\n", __func__, idx); + return 0; +} +EXPORT_SYMBOL(mt_gpufreq_get_freq_by_idx); + + +#ifdef MT_GPUFREQ_DYNAMIC_POWER_TABLE_UPDATE +static void mt_update_gpufreqs_power_table(void) +{ + int i = 0, temp = 0; + unsigned int freq = 0, volt = 0; + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready\n", __func__); + return; + } + +#ifdef CONFIG_THERMAL + temp = get_immediate_gpu_wrap() / 1000; +#else + temp = 40; +#endif + + gpufreq_dbg("@%s, temp = %d\n", __func__, temp); + + mutex_lock(&mt_gpufreq_lock); + + if ((temp > 0) && (temp < 125)) { + for (i = 0; i < mt_gpufreqs_num; i++) { + freq = mt_gpufreqs_power[i].gpufreq_khz; + volt = mt_gpufreqs_power[i].gpufreq_volt; + + mt_gpufreq_power_calculation(i, freq, volt, temp); + + gpufreq_ver("update gpufreqs_power[%d]: khz=%u, volt=%u, power=%u\n", + i, mt_gpufreqs_power[i].gpufreq_khz, + mt_gpufreqs_power[i].gpufreq_volt, + mt_gpufreqs_power[i].gpufreq_power); + } + } else + gpufreq_err("@%s: temp < 0 or temp > 125, NOT update power table!\n", __func__); + + mutex_unlock(&mt_gpufreq_lock); +} +#endif + +static void mt_setup_gpufreqs_power_table(int num) +{ + int i = 0, temp = 0; + + mt_gpufreqs_power = kzalloc((num) * sizeof(struct mt_gpufreq_power_table_info), GFP_KERNEL); + if (mt_gpufreqs_power == NULL) + return; + +#ifdef CONFIG_THERMAL + temp = get_immediate_gpu_wrap() / 1000; +#else + temp = 40; +#endif + + gpufreq_dbg("@%s: temp = %d\n", __func__, temp); + + if ((temp < 0) || (temp > 125)) { + gpufreq_dbg("@%s: temp < 0 or temp > 125!\n", __func__); + temp = 65; + } + + for (i = 0; i < num; i++) { + /* fill-in freq and volt in power table */ + mt_gpufreqs_power[i].gpufreq_khz = mt_gpufreqs[i].gpufreq_khz; + mt_gpufreqs_power[i].gpufreq_volt = mt_gpufreqs[i].gpufreq_volt; + + mt_gpufreq_power_calculation(i, + mt_gpufreqs_power[i].gpufreq_khz, + mt_gpufreqs_power[i].gpufreq_volt, + temp); + + gpufreq_info("gpufreqs_power[%d]: khz=%u, volt=%u, power=%u\n", + i, mt_gpufreqs_power[i].gpufreq_khz, + mt_gpufreqs_power[i].gpufreq_volt, + mt_gpufreqs_power[i].gpufreq_power); + } + +#ifdef CONFIG_THERMAL + mtk_gpufreq_register(mt_gpufreqs_power, num); +#endif +} + +/*********************************************** + * register frequency table to gpufreq subsystem + ************************************************/ +static int mt_setup_gpufreqs_table(struct mt_gpufreq_table_info *freqs, int num) +{ + int i = 0; + + mt_gpufreqs = kzalloc((num) * sizeof(*freqs), GFP_KERNEL); + mt_gpufreqs_default = kzalloc((num) * sizeof(*freqs), GFP_KERNEL); + if (mt_gpufreqs == NULL) + return -ENOMEM; + + for (i = 0; i < num; i++) { + mt_gpufreqs[i].gpufreq_khz = freqs[i].gpufreq_khz; + mt_gpufreqs[i].gpufreq_volt = freqs[i].gpufreq_volt; + mt_gpufreqs[i].gpufreq_idx = freqs[i].gpufreq_idx; + + mt_gpufreqs_default[i].gpufreq_khz = freqs[i].gpufreq_khz; + mt_gpufreqs_default[i].gpufreq_volt = freqs[i].gpufreq_volt; + mt_gpufreqs_default[i].gpufreq_idx = freqs[i].gpufreq_idx; + + gpufreq_dbg("freqs[%d]:khz=%u, volt=%u, idx=%u\n", i, + freqs[i].gpufreq_khz, freqs[i].gpufreq_volt, + freqs[i].gpufreq_idx); + } + + mt_gpufreqs_num = num; + + g_limited_max_id = 0; + g_limited_min_id = mt_gpufreqs_num - 1; + + mt_setup_gpufreqs_power_table(num); + + return 0; +} + +/************************************** + * check if maximum frequency is needed + ***************************************/ +static int mt_gpufreq_keep_max_freq(unsigned int freq_old, unsigned int freq_new) +{ + if (mt_gpufreq_keep_max_frequency_state == true) + return 1; + + return 0; +} + +#if 1 +/***************************** + * set GPU DVFS status + ******************************/ +int mt_gpufreq_state_set(int enabled) +{ + if (enabled) { + if (!mt_gpufreq_pause) { + gpufreq_dbg("gpufreq already enabled\n"); + return 0; + } + + /***************** + * enable GPU DVFS + ******************/ + g_gpufreq_dvfs_disable_count--; + gpufreq_dbg("enable GPU DVFS: g_gpufreq_dvfs_disable_count = %d\n", + g_gpufreq_dvfs_disable_count); + + /*********************************************** + * enable DVFS if no any module still disable it + ************************************************/ + if (g_gpufreq_dvfs_disable_count <= 0) + mt_gpufreq_pause = false; + else + gpufreq_warn("someone still disable gpufreq, cannot enable it\n"); + } else { + /****************** + * disable GPU DVFS + *******************/ + g_gpufreq_dvfs_disable_count++; + gpufreq_dbg("disable GPU DVFS: g_gpufreq_dvfs_disable_count = %d\n", + g_gpufreq_dvfs_disable_count); + + if (mt_gpufreq_pause) { + gpufreq_dbg("gpufreq already disabled\n"); + return 0; + } + + mt_gpufreq_pause = true; + } + + return 0; +} +EXPORT_SYMBOL(mt_gpufreq_state_set); +#endif + +static unsigned int mt_gpufreq_dds_calc(unsigned int khz, enum post_div_enum post_div) +{ + unsigned int dds = 0; + + gpufreq_dbg("@%s: request freq = %d, div = %d\n", __func__, khz, post_div); + + if ((khz >= 125000) && (khz <= 3000000)) { + dds = (((khz / 100 * post_div*2) * 16384) / 26 + 5) / 10; + } else { + gpufreq_err("@%s: target khz(%d) out of range!\n", __func__, khz); + BUG(); + } + + return dds; +} + +static void gpu_dvfs_switch_to_syspll(bool on) +{ + clk_prepare_enable(mt_gpufreq_clk->clk_mux); + if (on) { + clk_set_parent(mt_gpufreq_clk->clk_mux, mt_gpufreq_clk->clk_sub_parent); + clk_disable_unprepare(mt_gpufreq_clk->clk_mux); + } else { + clk_set_parent(mt_gpufreq_clk->clk_mux, mt_gpufreq_clk->clk_main_parent); + clk_disable_unprepare(mt_gpufreq_clk->clk_mux); + } + + /* gpufreq_dbg("@%s: on = %d, CLK_CFG_1 = 0x%x, CLK_CFG_UPDATE = 0x%x\n", + __func__, on, DRV_Reg32(CLK_CFG_1), DRV_Reg32(CLK_CFG_UPDATE)); */ +} + +static void mt_gpufreq_clock_switch_transient(unsigned int freq_new, enum post_div_enum post_div) +{ +#define SYSPLL_D3_FREQ (364000) + + unsigned int cur_volt, cur_freq, dds, i, found = 0; + unsigned int new_oppidx = g_cur_gpu_OPPidx; + unsigned int tmp_idx = g_cur_gpu_OPPidx; + unsigned int syspll_volt = mt_gpufreqs[0].gpufreq_volt; + + cur_volt = _mt_gpufreq_get_cur_volt(); + cur_freq = _mt_gpufreq_get_cur_freq(); + for (i = 0; i < mt_gpufreqs_num; i++) { + if (freq_new == mt_gpufreqs[i].gpufreq_khz) { + new_oppidx = i; + break; + } + } + dds = mt_gpufreq_dds_calc(freq_new, 1 << post_div); + gpufreq_dbg("@%s: request GPU dds=0x%x, cur_volt=%u, cur_freq=%u, new_oppidx=%u\n", + __func__, dds, cur_volt, cur_freq, new_oppidx); + gpufreq_dbg("@%s: request APMIXED_MMPLL_CON1 = 0x%x\n", + __func__, DRV_Reg32(APMIXED_MMPLL_CON1)); + if ((DRV_Reg32(APMIXED_MMPLL_CON1) & (0x7 << 24)) != ((post_div+1) << 24)) { + gpufreq_dbg("@%s: switch to syspll\n", __func__); + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs[i].gpufreq_khz < SYSPLL_D3_FREQ) { + /* record idx since current voltage may not in DVFS table */ + if (i >= 1) + tmp_idx = i - 1; + else + break; + syspll_volt = mt_gpufreqs[tmp_idx].gpufreq_volt; + found = 1; + gpufreq_dbg("@%s: request GPU syspll_volt = %d\n", + __func__, syspll_volt); + break; + } + } + + if (found == 1) { + /* ramp up volt for SYSPLL */ + if (cur_volt < syspll_volt) +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + mt_gpufreq_volt_switch(cur_volt, syspll_volt); +#else + mt_gpufreq_volt_switch(tmp_idx); +#endif + + /* Step1. Select to SYSPLL_D3 364MHz */ + gpu_dvfs_switch_to_syspll(true); + /* Step2. Modify APMIXED_MMPLL_CON1 */ + DRV_WriteReg32(APMIXED_MMPLL_CON1, (0x80000000) | ((post_div+1) << 24) | dds); + /* Step3. Select back to MMPLL */ + gpu_dvfs_switch_to_syspll(false); + DRV_SetReg32(APMIXED_MMPLL_CON1, 0x80000000); + + /* restore to cur_volt */ + if (cur_volt < syspll_volt) +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + mt_gpufreq_volt_switch(syspll_volt, cur_volt); +#else + mt_gpufreq_volt_switch(new_oppidx); +#endif + } else { + gpufreq_dbg("@%s: request GPU syspll_volt not found, khz = %d, volt = %d\n", + __func__, mt_gpufreqs[mt_gpufreqs_num - 1].gpufreq_khz, + mt_gpufreqs[mt_gpufreqs_num - 1].gpufreq_volt); + BUG(); + } + } else { + gpufreq_dbg("@%s: no need to switch to SYSPLL\n", __func__); + DRV_WriteReg32(APMIXED_MMPLL_CON1, 0x80000000 | ((post_div+1) << 24) | dds); + } +} + +static void mt_gpufreq_clock_switch(unsigned int freq_new) +{ + unsigned int dds; + + /* need clk switch if max freq is over 750M */ + if (mt_gpufreqs[g_gpufreq_max_id].gpufreq_khz > 750000) { + if (freq_new > 750000) + mt_gpufreq_clock_switch_transient(freq_new, POST_DIV2); + else if (freq_new < 250000) + mt_gpufreq_clock_switch_transient(freq_new, POST_DIV8); + else + mt_gpufreq_clock_switch_transient(freq_new, POST_DIV4); + } else { + dds = mt_gpufreq_dds_calc(freq_new, 1 << POST_DIV4); + mt_dfs_mmpll(dds); + gpufreq_dbg("@%s: freq_new = %d, dds = 0x%x\n", __func__, freq_new, dds); + } + + if (NULL != g_pFreqSampler) + g_pFreqSampler(freq_new); + +} + +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +static int mt_gpufreq_volt_switch(unsigned int new_oppidx) +{ + gpufreq_dbg("@%s: new_oppidx = %d\n", __func__, new_oppidx); + + if ((is_vcorefs_can_work() < 0) || + (mt_gpufreq_dvfs_table_type == 1 && fake_segment != 2) || + (mt_gpufreq_dvfs_table_type == 2)) /* Segment2 & 3: use Vcore2 */ + return 0; + + BUG_ON(new_oppidx >= mt_gpufreqs_num); + + switch (mt_gpufreqs[new_oppidx].gpufreq_khz) { + case GPU_DVFS_FREQ0_1: + case GPU_DVFS_FREQ4: + g_last_gpu_dvs_result = vcorefs_request_dvfs_opp(KIR_GPU, OPPI_PERF); + break; + case GPU_DVFS_FREQ8: + g_last_gpu_dvs_result = vcorefs_request_dvfs_opp(KIR_GPU, OPPI_UNREQ); + break; + default: + gpufreq_err("@%s: freq not found\n", __func__); + g_last_gpu_dvs_result = 0x7F; + break; + } + + if (g_last_gpu_dvs_result == 0) { + unsigned int volt_new = mt_gpufreq_get_cur_volt(); + +#ifdef MT_GPUFREQ_AEE_RR_REC + aee_rr_rec_gpu_dvfs_vgpu(mt_gpufreq_volt_to_pmic_wrap(volt_new)); +#endif + + if (NULL != g_pVoltSampler) + g_pVoltSampler(volt_new); + } else + gpufreq_warn("@%s: GPU DVS failed, ret = %d\n", __func__, g_last_gpu_dvs_result); + + return g_last_gpu_dvs_result; +} +#else /* MT_GPUFREQ_GPU_SOURCE_FROM_VCORE */ +static void mt_gpufreq_volt_switch(unsigned int volt_old, unsigned int volt_new) +{ + unsigned int reg_val = 0; + unsigned int delay = 0; + /* unsigned int RegValGet = 0; */ + + gpufreq_dbg("@%s: volt_new = %d\n", __func__, volt_new); + + /* mt_gpufreq_reg_write(0x02B0, PMIC_WRAP_DVFS_ADR2); */ + + reg_val = mt_gpufreq_volt_to_pmic_wrap(volt_new); + +#ifdef MT_GPUFREQ_AEE_RR_REC + aee_rr_rec_gpu_dvfs_vgpu(reg_val); +#endif + +#ifdef VGPU_SET_BY_PMIC + /* Set VGPU_VOSEL_CTRL[1] to HW control */ + pmic_config_interface(PMIC_ADDR_VGPU_VOSEL_ON, reg_val, + PMIC_ADDR_VGPU_VOSEL_ON_MASK, + PMIC_ADDR_VGPU_VOSEL_ON_SHIFT); +#elif defined(VGPU_SET_BY_PMIC_WRAP) +#if 1 + mt_cpufreq_set_pmic_cmd(PMIC_WRAP_PHASE_NORMAL, IDX_NM_VGPU, reg_val); + mt_cpufreq_apply_pmic_cmd(IDX_NM_VGPU); + + /* pmic_read_interface(0x02B0, &RegValGet, 0x7F, 0x0); // Get VDVFS13_EN[0] */ + /* gpufreq_dbg("0x02B0 = %d\n", RegValGet); */ +#else + mt_gpufreq_reg_write(reg_val, PMIC_WRAP_DVFS_WDATA2); + + spm_dvfs_ctrl_volt(GPU_DVFS_CTRL_VOLT); +#endif +#endif + + if (volt_new > volt_old) { + delay = mt_gpufreq_calc_pmic_settle_time(volt_old, volt_new); + gpufreq_dbg("@%s: delay = %d\n", __func__, delay); + udelay(delay); + } + + if (NULL != g_pVoltSampler) + g_pVoltSampler(volt_new); +} +#endif + +static unsigned int _mt_gpufreq_get_cur_freq(void) +{ +#if 1 + unsigned int mmpll = 0; + unsigned int freq = 0; + unsigned int div = 0; + unsigned int n_info = 0; + + mmpll = DRV_Reg32(APMIXED_MMPLL_CON1) & ~0x80000000; + div = 1 << ((mmpll & (0x7 << 24)) >> 24); + n_info = (mmpll & 0x1fffff) >> 14; + freq = n_info * 26000 / div; + + gpufreq_dbg("mmpll = 0x%x, freq = %d\n", mmpll, freq); + + return freq; /* KHz */ +#else + unsigned int gpu_freq = mt_get_mfgclk_freq(); + /* check freq meter */ + gpufreq_dbg("g_cur_gpu_freq = %d KHz, Meter = %d KHz\n", g_cur_gpu_freq, gpu_freq); + return gpu_freq; +#endif +} + +static unsigned int _mt_gpufreq_get_cur_volt(void) +{ +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + if ((mt_gpufreq_dvfs_table_type == 0) || /* Segment1: 680M use Vcore1 */ + (fake_segment != 0)) + return vcorefs_get_curr_vcore() / 10; + else /* Segment2 & 3: use Vcore2 */ + return GPU_DVFS_VOLT1; +#else + return mt_gpufreq_pmic_wrap_to_volt(pmic_get_register_value(PMIC_BUCK_VGPU_VOSEL_ON)); +#endif +} + +static void _mt_gpufreq_kick_pbm(int enable) +{ +#ifndef DISABLE_PBM_FEATURE + int i; + int tmp_idx = -1; + unsigned int found = 0; + unsigned int power; + unsigned int cur_volt = _mt_gpufreq_get_cur_volt(); + unsigned int cur_freq = _mt_gpufreq_get_cur_freq(); + + if (enable) { + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs_power[i].gpufreq_khz == cur_freq) { + /* record idx since current voltage may not in DVFS table */ + tmp_idx = i; + + if (mt_gpufreqs_power[i].gpufreq_volt == cur_volt) { + power = mt_gpufreqs_power[i].gpufreq_power; + found = 1; + kicker_pbm_by_gpu(true, power, cur_volt / 100); + gpufreq_dbg + ("@%s: request GPU power = %d, cur_volt = %d, cur_freq = %d\n", + __func__, power, cur_volt / 100, cur_freq); + return; + } + } + } + + if (!found) { + gpufreq_dbg("@%s: tmp_idx = %d\n", __func__, tmp_idx); + + if (tmp_idx != -1 && tmp_idx < mt_gpufreqs_num) { + /* use freq to found corresponding power budget */ + power = mt_gpufreqs_power[tmp_idx].gpufreq_power; + kicker_pbm_by_gpu(true, power, cur_volt / 100); + gpufreq_dbg + ("@%s: request GPU power = %d, cur_volt = %d, cur_freq = %d\n", + __func__, power, cur_volt / 100, cur_freq); + } else { + gpufreq_warn("@%s: Cannot found request power in power table!\n", + __func__); + gpufreq_warn("cur_freq = %dKHz, cur_volt = %dmV\n", cur_freq, + cur_volt / 100); + } + } + } else { + kicker_pbm_by_gpu(false, 0, cur_volt / 100); + } +#endif +} + +/***************************************** + * frequency ramp up and ramp down handler + ******************************************/ +/*********************************************************** + * [note] + * 1. frequency ramp up need to wait voltage settle + * 2. frequency ramp down do not need to wait voltage settle + ************************************************************/ +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE +static int mt_gpufreq_set(unsigned int freq_old, unsigned int freq_new, unsigned int new_oppidx) +{ + int ret = 0; + + if (freq_new > freq_old) { + if (is_vcorefs_can_work() >= 0) { + ret = mt_gpufreq_volt_switch(new_oppidx); + + /* Do DFS only when Vcore was set to HPM successfully */ + if (ret) + return ret; + } + mt_gpufreq_clock_switch(freq_new); + } else { + mt_gpufreq_clock_switch(freq_new); + if (is_vcorefs_can_work() >= 0) + mt_gpufreq_volt_switch(new_oppidx); + } + + _mt_gpufreq_kick_pbm(1); + + return 0; +} +#else /* MT_GPUFREQ_GPU_SOURCE_FROM_VCORE */ +static void mt_gpufreq_set(unsigned int freq_old, unsigned int freq_new, + unsigned int volt_old, unsigned int volt_new) +{ + if (freq_new > freq_old) { + /* if(volt_old != volt_new) // ??? */ + /* { */ + mt_gpufreq_volt_switch(volt_old, volt_new); + /* } */ + + mt_gpufreq_clock_switch(freq_new); + } else { + mt_gpufreq_clock_switch(freq_new); + + /* if(volt_old != volt_new) */ + /* { */ + mt_gpufreq_volt_switch(volt_old, volt_new); + /* } */ + } + + g_cur_gpu_freq = freq_new; + g_cur_gpu_volt = volt_new; + + _mt_gpufreq_kick_pbm(1); +} +#endif + +/********************************** + * gpufreq target callback function + ***********************************/ +/************************************************* + * [note] + * 1. handle frequency change request + * 2. call mt_gpufreq_set to set target frequency + **************************************************/ +unsigned int mt_gpufreq_target(unsigned int idx) +{ + /* unsigned long flags; */ + unsigned int target_freq, target_volt, target_idx, target_OPPidx; + + mutex_lock(&mt_gpufreq_lock); + + if (mt_gpufreq_ready == false) { + gpufreq_warn("GPU DVFS not ready!\n"); + mutex_unlock(&mt_gpufreq_lock); + return -ENOSYS; + } + + if (mt_gpufreq_volt_enable_state == 0) { + gpufreq_dbg("mt_gpufreq_volt_enable_state == 0! return\n"); + mutex_unlock(&mt_gpufreq_lock); + return -ENOSYS; + } +#ifdef MT_GPU_DVFS_RANDOM_TEST + idx = mt_gpufreq_idx_get(5); + gpufreq_dbg("@%s: random test index is %d !\n", __func__, idx); +#endif + + if (idx > (mt_gpufreqs_num - 1)) { + mutex_unlock(&mt_gpufreq_lock); + gpufreq_err("@%s: idx out of range! idx = %d\n", __func__, idx); + return -1; + } + +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + /* only 1 OPP, no need to DVFS */ + if ((mt_gpufreq_dvfs_table_type == 2) || (fake_segment == 3)) { + mutex_unlock(&mt_gpufreq_lock); + return 0; + } +#endif + + /********************************** + * look up for the target GPU OPP + ***********************************/ + target_freq = mt_gpufreqs[idx].gpufreq_khz; + target_volt = mt_gpufreqs[idx].gpufreq_volt; + target_idx = mt_gpufreqs[idx].gpufreq_idx; + target_OPPidx = idx; + + gpufreq_dbg("@%s: begin, receive freq: %d, OPPidx: %d\n", __func__, target_freq, + target_OPPidx); + + /********************************** + * Check if need to keep max frequency + ***********************************/ + if (mt_gpufreq_keep_max_freq(g_cur_gpu_freq, target_freq)) { + target_freq = mt_gpufreqs[g_gpufreq_max_id].gpufreq_khz; + target_volt = mt_gpufreqs[g_gpufreq_max_id].gpufreq_volt; + target_idx = mt_gpufreqs[g_gpufreq_max_id].gpufreq_idx; + target_OPPidx = g_gpufreq_max_id; + gpufreq_dbg("Keep MAX frequency %d !\n", target_freq); + } +#if 0 + /**************************************************** + * If need to raise frequency, raise to max frequency + *****************************************************/ + if (target_freq > g_cur_freq) { + target_freq = mt_gpufreqs[g_gpufreq_max_id].gpufreq_khz; + target_volt = mt_gpufreqs[g_gpufreq_max_id].gpufreq_volt; + gpufreq_dbg("Need to raise frequency, raise to MAX frequency %d !\n", target_freq); + } +#endif + + /************************************************ + * If /proc command keep opp frequency. + *************************************************/ + if (mt_gpufreq_keep_opp_frequency_state == true) { + target_freq = mt_gpufreqs[mt_gpufreq_keep_opp_index].gpufreq_khz; + target_volt = mt_gpufreqs[mt_gpufreq_keep_opp_index].gpufreq_volt; + target_idx = mt_gpufreqs[mt_gpufreq_keep_opp_index].gpufreq_idx; + target_OPPidx = mt_gpufreq_keep_opp_index; + gpufreq_dbg("Keep opp! opp frequency %d, opp voltage %d, opp idx %d\n", target_freq, + target_volt, target_OPPidx); + } + + /************************************************ + * If /proc command fix the frequency. + *************************************************/ + if (mt_gpufreq_fixed_freq_volt_state == true) { + target_freq = mt_gpufreq_fixed_frequency; + target_volt = mt_gpufreq_fixed_voltage; + target_idx = 0; + target_OPPidx = 0; + gpufreq_dbg("Fixed! fixed frequency %d, fixed voltage %d\n", target_freq, + target_volt); + } + + /************************************************ + * If /proc command keep opp max frequency. + *************************************************/ + if (mt_gpufreq_opp_max_frequency_state == true) { + if (target_freq > mt_gpufreq_opp_max_frequency) { + target_freq = mt_gpufreqs[mt_gpufreq_opp_max_index].gpufreq_khz; + target_volt = mt_gpufreqs[mt_gpufreq_opp_max_index].gpufreq_volt; + target_idx = mt_gpufreqs[mt_gpufreq_opp_max_index].gpufreq_idx; + target_OPPidx = mt_gpufreq_opp_max_index; + + gpufreq_dbg + ("opp max freq! opp max frequency %d, opp max voltage %d, opp max idx %d\n", + target_freq, target_volt, target_OPPidx); + } + } + + /************************************************ + * PBM limit + *************************************************/ +#ifndef DISABLE_PBM_FEATURE + if (mt_gpufreq_pbm_limited_index != 0) { + if (target_freq > mt_gpufreqs[mt_gpufreq_pbm_limited_index].gpufreq_khz) { + /********************************************* + * target_freq > limited_freq, need to adjust + **********************************************/ + target_freq = mt_gpufreqs[mt_gpufreq_pbm_limited_index].gpufreq_khz; + target_volt = mt_gpufreqs[mt_gpufreq_pbm_limited_index].gpufreq_volt; + target_OPPidx = mt_gpufreq_pbm_limited_index; + gpufreq_dbg("Limit! Thermal/Power limit gpu frequency %d\n", + mt_gpufreqs[mt_gpufreq_pbm_limited_index].gpufreq_khz); + } + } +#endif + + /************************************************ + * Thermal/Power limit + *************************************************/ + if (g_limited_max_id != 0) { + if (target_freq > mt_gpufreqs[g_limited_max_id].gpufreq_khz) { + /********************************************* + * target_freq > limited_freq, need to adjust + **********************************************/ + target_freq = mt_gpufreqs[g_limited_max_id].gpufreq_khz; + target_volt = mt_gpufreqs[g_limited_max_id].gpufreq_volt; + target_idx = mt_gpufreqs[g_limited_max_id].gpufreq_idx; + target_OPPidx = g_limited_max_id; + gpufreq_info("Limit! Thermal/Power limit gpu frequency %d\n", + mt_gpufreqs[g_limited_max_id].gpufreq_khz); + } + } + + /************************************************ + * DVFS keep at max freq when PTPOD initial + *************************************************/ + if (mt_gpufreq_ptpod_disable == true) { +#if 1 + target_freq = mt_gpufreqs[mt_gpufreq_ptpod_disable_idx].gpufreq_khz; + target_volt = mt_gpufreqs[mt_gpufreq_ptpod_disable_idx].gpufreq_volt; + target_idx = mt_gpufreqs[mt_gpufreq_ptpod_disable_idx].gpufreq_idx; + target_OPPidx = mt_gpufreq_ptpod_disable_idx; + gpufreq_dbg("PTPOD disable dvfs, mt_gpufreq_ptpod_disable_idx = %d\n", + mt_gpufreq_ptpod_disable_idx); +#else + mutex_unlock(&mt_gpufreq_lock); + gpufreq_dbg("PTPOD disable dvfs, return\n"); + return 0; +#endif + } + + /************************************************ + * target frequency == current frequency, skip it + *************************************************/ + if (g_cur_gpu_freq == target_freq) { + mutex_unlock(&mt_gpufreq_lock); + gpufreq_dbg("GPU frequency from %d KHz to %d KHz (skipped) due to same frequency\n", + g_cur_gpu_freq, target_freq); + return 0; + } + + gpufreq_dbg("GPU current frequency %d KHz, target frequency %d KHz\n", g_cur_gpu_freq, + target_freq); + +#ifdef MT_GPUFREQ_AEE_RR_REC + aee_rr_rec_gpu_dvfs_status(aee_rr_curr_gpu_dvfs_status() | (1 << GPU_DVFS_IS_DOING_DVFS)); + aee_rr_rec_gpu_dvfs_oppidx(target_OPPidx); +#endif + + /****************************** + * set to the target frequency + *******************************/ +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + if (!mt_gpufreq_set(g_cur_gpu_freq, target_freq, target_OPPidx)) { + g_cur_gpu_idx = target_idx; + g_cur_gpu_OPPidx = target_OPPidx; + g_cur_gpu_freq = target_freq; + g_cur_gpu_volt = mt_gpufreqs[g_cur_gpu_OPPidx].gpufreq_volt; + } +#else + mt_gpufreq_set(g_cur_gpu_freq, target_freq, g_cur_gpu_volt, target_volt); + + g_cur_gpu_idx = target_idx; + g_cur_gpu_OPPidx = target_OPPidx; +#endif + +#ifdef MT_GPUFREQ_AEE_RR_REC + aee_rr_rec_gpu_dvfs_status(aee_rr_curr_gpu_dvfs_status() & ~(1 << GPU_DVFS_IS_DOING_DVFS)); +#endif + + mutex_unlock(&mt_gpufreq_lock); + + return 0; +} +EXPORT_SYMBOL(mt_gpufreq_target); + + +/******************************************** + * POWER LIMIT RELATED + ********************************************/ +enum { + IDX_THERMAL_LIMITED, + IDX_LOW_BATT_VOLT_LIMITED, + IDX_LOW_BATT_VOLUME_LIMITED, + IDX_OC_LIMITED, + + NR_IDX_POWER_LIMITED, +}; + +/* NO need to throttle when OC */ +#ifdef MT_GPUFREQ_OC_PROTECT +static unsigned int mt_gpufreq_oc_level; + +#define MT_GPUFREQ_OC_LIMIT_FREQ_1 GPU_DVFS_FREQ0 /* no need to throttle when OC */ +static unsigned int mt_gpufreq_oc_limited_index_0; /* unlimit frequency, index = 0. */ +static unsigned int mt_gpufreq_oc_limited_index_1; +static unsigned int mt_gpufreq_oc_limited_index; /* Limited frequency index for oc */ +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_PROTECT +static unsigned int mt_gpufreq_low_battery_volume; + +#define MT_GPUFREQ_LOW_BATT_VOLUME_LIMIT_FREQ_1 GPU_DVFS_FREQ7 +static unsigned int mt_gpufreq_low_bat_volume_limited_index_0; /* unlimit frequency, index = 0. */ +static unsigned int mt_gpufreq_low_bat_volume_limited_index_1; +static unsigned int mt_gpufreq_low_batt_volume_limited_index; /* Limited frequency index for low battery volume */ +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLT_PROTECT +static unsigned int mt_gpufreq_low_battery_level; + +#define MT_GPUFREQ_LOW_BATT_VOLT_LIMIT_FREQ_1 GPU_DVFS_FREQ0 /* no need to throttle when LV1 */ +#define MT_GPUFREQ_LOW_BATT_VOLT_LIMIT_FREQ_2 GPU_DVFS_FREQ7 +static unsigned int mt_gpufreq_low_bat_volt_limited_index_0; /* unlimit frequency, index = 0. */ +static unsigned int mt_gpufreq_low_bat_volt_limited_index_1; +static unsigned int mt_gpufreq_low_bat_volt_limited_index_2; +static unsigned int mt_gpufreq_low_batt_volt_limited_index; /* Limited frequency index for low battery voltage */ +#endif + +static unsigned int mt_gpufreq_thermal_limited_gpu_power; /* thermal limit power */ +/* limit frequency index array */ +static unsigned int mt_gpufreq_power_limited_index_array[NR_IDX_POWER_LIMITED] = { 0 }; + +/************************************************ + * frequency adjust interface for thermal protect + *************************************************/ +/****************************************************** + * parameter: target power + *******************************************************/ +static int mt_gpufreq_power_throttle_protect(void) +{ + int ret = 0; + int i = 0; + unsigned int limited_index = 0; + + /* Check lowest frequency in all limitation */ + for (i = 0; i < NR_IDX_POWER_LIMITED; i++) { + if (mt_gpufreq_power_limited_index_array[i] != 0 && limited_index == 0) + limited_index = mt_gpufreq_power_limited_index_array[i]; + else if (mt_gpufreq_power_limited_index_array[i] != 0 && limited_index != 0) { + if (mt_gpufreq_power_limited_index_array[i] > limited_index) + limited_index = mt_gpufreq_power_limited_index_array[i]; + } + + gpufreq_dbg("mt_gpufreq_power_limited_index_array[%d] = %d\n", i, + mt_gpufreq_power_limited_index_array[i]); + } + + g_limited_max_id = limited_index; + gpufreq_dbg("Final limit frequency upper bound to id = %d, frequency = %d\n", + g_limited_max_id, mt_gpufreqs[g_limited_max_id].gpufreq_khz); + + if (NULL != g_pGpufreq_power_limit_notify) + g_pGpufreq_power_limit_notify(g_limited_max_id); + + return ret; +} + +#ifdef MT_GPUFREQ_OC_PROTECT +/************************************************ + * GPU frequency adjust interface for oc protect + *************************************************/ +static void mt_gpufreq_oc_protect(unsigned int limited_index) +{ + mutex_lock(&mt_gpufreq_power_lock); + + gpufreq_dbg("@%s: limited_index = %d\n", __func__, limited_index); + + mt_gpufreq_power_limited_index_array[IDX_OC_LIMITED] = limited_index; + mt_gpufreq_power_throttle_protect(); + + mutex_unlock(&mt_gpufreq_power_lock); +} + +void mt_gpufreq_oc_callback(BATTERY_OC_LEVEL oc_level) +{ + gpufreq_dbg("@%s: oc_level = %d\n", __func__, oc_level); + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + return; + } + + if (g_limited_oc_ignore_state == true) { + gpufreq_info("@%s: g_limited_oc_ignore_state == true!\n", __func__); + return; + } + + mt_gpufreq_oc_level = oc_level; + + /* BATTERY_OC_LEVEL_1: >= 7A, BATTERY_OC_LEVEL_0: < 7A */ + if (oc_level == BATTERY_OC_LEVEL_1) { + if (mt_gpufreq_oc_limited_index != mt_gpufreq_oc_limited_index_1) { + mt_gpufreq_oc_limited_index = mt_gpufreq_oc_limited_index_1; + mt_gpufreq_oc_protect(mt_gpufreq_oc_limited_index_1); /* Limit GPU 396.5Mhz */ + } + } + /* unlimit gpu */ + else { + if (mt_gpufreq_oc_limited_index != mt_gpufreq_oc_limited_index_0) { + mt_gpufreq_oc_limited_index = mt_gpufreq_oc_limited_index_0; + mt_gpufreq_oc_protect(mt_gpufreq_oc_limited_index_0); /* Unlimit */ + } + } +} +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_PROTECT +/************************************************ + * GPU frequency adjust interface for low bat_volume protect + *************************************************/ +static void mt_gpufreq_low_batt_volume_protect(unsigned int limited_index) +{ + mutex_lock(&mt_gpufreq_power_lock); + + gpufreq_dbg("@%s: limited_index = %d\n", __func__, limited_index); + + mt_gpufreq_power_limited_index_array[IDX_LOW_BATT_VOLUME_LIMITED] = limited_index; + mt_gpufreq_power_throttle_protect(); + + mutex_unlock(&mt_gpufreq_power_lock); +} + +void mt_gpufreq_low_batt_volume_callback(BATTERY_PERCENT_LEVEL low_battery_volume) +{ + gpufreq_dbg("@%s: low_battery_volume = %d\n", __func__, low_battery_volume); + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + return; + } + + if (g_limited_low_batt_volume_ignore_state == true) { + gpufreq_info("@%s: g_limited_low_batt_volume_ignore_state == true!\n", __func__); + return; + } + + mt_gpufreq_low_battery_volume = low_battery_volume; + + /* LOW_BATTERY_VOLUME_1: <= 15%, LOW_BATTERY_VOLUME_0: >15% */ + if (low_battery_volume == BATTERY_PERCENT_LEVEL_1) { + if (mt_gpufreq_low_batt_volume_limited_index != + mt_gpufreq_low_bat_volume_limited_index_1) { + mt_gpufreq_low_batt_volume_limited_index = + mt_gpufreq_low_bat_volume_limited_index_1; + /* Limit GPU 400Mhz */ + mt_gpufreq_low_batt_volume_protect(mt_gpufreq_low_bat_volume_limited_index_1); + } + } + /* unlimit gpu */ + else { + if (mt_gpufreq_low_batt_volume_limited_index != + mt_gpufreq_low_bat_volume_limited_index_0) { + mt_gpufreq_low_batt_volume_limited_index = + mt_gpufreq_low_bat_volume_limited_index_0; + mt_gpufreq_low_batt_volume_protect(mt_gpufreq_low_bat_volume_limited_index_0); /* Unlimit */ + } + } +} +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLT_PROTECT +/************************************************ + * GPU frequency adjust interface for low bat_volt protect + *************************************************/ +static void mt_gpufreq_low_batt_volt_protect(unsigned int limited_index) +{ + mutex_lock(&mt_gpufreq_power_lock); + + gpufreq_dbg("@%s: limited_index = %d\n", __func__, limited_index); + mt_gpufreq_power_limited_index_array[IDX_LOW_BATT_VOLT_LIMITED] = limited_index; + mt_gpufreq_power_throttle_protect(); + + mutex_unlock(&mt_gpufreq_power_lock); +} + +/****************************************************** + * parameter: low_battery_level + *******************************************************/ +void mt_gpufreq_low_batt_volt_callback(LOW_BATTERY_LEVEL low_battery_level) +{ + gpufreq_dbg("@%s: low_battery_level = %d\n", __func__, low_battery_level); + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + return; + } + + if (g_limited_low_batt_volt_ignore_state == true) { + gpufreq_info("@%s: g_limited_low_batt_volt_ignore_state == true!\n", __func__); + return; + } + + mt_gpufreq_low_battery_level = low_battery_level; + + /* is_low_battery=1:need limit HW, is_low_battery=0:no limit */ + /* 3.25V HW issue int and is_low_battery=1, + * 3.0V HW issue int and is_low_battery=2, + * 3.5V HW issue int and is_low_battery=0 */ +#if 0 /* no need to throttle when LV1 */ + if (low_battery_level == LOW_BATTERY_LEVEL_1) { + if (mt_gpufreq_low_batt_volt_limited_index != + mt_gpufreq_low_bat_volt_limited_index_1) { + mt_gpufreq_low_batt_volt_limited_index = + mt_gpufreq_low_bat_volt_limited_index_1; + /* Limit GPU 416Mhz */ + mt_gpufreq_low_batt_volt_protect(mt_gpufreq_low_bat_volt_limited_index_1); + } + } else +#endif + if (low_battery_level == LOW_BATTERY_LEVEL_2) { + if (mt_gpufreq_low_batt_volt_limited_index != + mt_gpufreq_low_bat_volt_limited_index_2) { + mt_gpufreq_low_batt_volt_limited_index = + mt_gpufreq_low_bat_volt_limited_index_2; + /* Limit GPU 400Mhz */ + mt_gpufreq_low_batt_volt_protect(mt_gpufreq_low_bat_volt_limited_index_2); + } + } else { /* unlimit gpu */ + if (mt_gpufreq_low_batt_volt_limited_index != + mt_gpufreq_low_bat_volt_limited_index_0) { + mt_gpufreq_low_batt_volt_limited_index = + mt_gpufreq_low_bat_volt_limited_index_0; + /* Unlimit */ + mt_gpufreq_low_batt_volt_protect(mt_gpufreq_low_bat_volt_limited_index_0); + } + } +} +#endif + +/************************************************ + * frequency adjust interface for thermal protect + *************************************************/ +/****************************************************** + * parameter: target power + *******************************************************/ +static unsigned int _mt_gpufreq_get_limited_freq(unsigned int limited_power) +{ + int i = 0; + unsigned int limited_freq = 0; + unsigned int found = 0; + + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs_power[i].gpufreq_power <= limited_power) { + limited_freq = mt_gpufreqs_power[i].gpufreq_khz; + found = 1; + break; + } + } + + /* not found */ + if (!found) + limited_freq = mt_gpufreqs_power[mt_gpufreqs_num - 1].gpufreq_khz; + + gpufreq_dbg("@%s: limited_freq = %d\n", __func__, limited_freq); + + return limited_freq; +} + +void mt_gpufreq_thermal_protect(unsigned int limited_power) +{ + int i = 0; + unsigned int limited_freq = 0; + + mutex_lock(&mt_gpufreq_power_lock); + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + mutex_unlock(&mt_gpufreq_power_lock); + return; + } + + if (mt_gpufreqs_num == 0) { + gpufreq_warn("@%s: mt_gpufreqs_num == 0!\n", __func__); + mutex_unlock(&mt_gpufreq_power_lock); + return; + } + + if (g_limited_thermal_ignore_state == true) { + gpufreq_info("@%s: g_limited_thermal_ignore_state == true!\n", __func__); + mutex_unlock(&mt_gpufreq_power_lock); + return; + } + + mt_gpufreq_thermal_limited_gpu_power = limited_power; + +#ifdef MT_GPUFREQ_DYNAMIC_POWER_TABLE_UPDATE + mt_update_gpufreqs_power_table(); +#endif + + if (limited_power == 0) + mt_gpufreq_power_limited_index_array[IDX_THERMAL_LIMITED] = 0; + else { + limited_freq = _mt_gpufreq_get_limited_freq(limited_power); + + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs[i].gpufreq_khz <= limited_freq) { + mt_gpufreq_power_limited_index_array[IDX_THERMAL_LIMITED] = i; + break; + } + } + } + + gpufreq_dbg("Thermal limit frequency upper bound to id=%d, limited_power=%d\n", + mt_gpufreq_power_limited_index_array[IDX_THERMAL_LIMITED], + limited_power); + + mt_gpufreq_power_throttle_protect(); + + mutex_unlock(&mt_gpufreq_power_lock); +} +EXPORT_SYMBOL(mt_gpufreq_thermal_protect); + +/* for thermal to update power budget */ +unsigned int mt_gpufreq_get_max_power(void) +{ + if (!mt_gpufreqs_power) + return 0; + else + return mt_gpufreqs_power[0].gpufreq_power; +} + +/* for thermal to update power budget */ +unsigned int mt_gpufreq_get_min_power(void) +{ + if (!mt_gpufreqs_power) + return 0; + else + return mt_gpufreqs_power[mt_gpufreqs_num - 1].gpufreq_power; +} + +void mt_gpufreq_set_power_limit_by_pbm(unsigned int limited_power) +{ +#ifndef DISABLE_PBM_FEATURE + int i = 0; + unsigned int limited_freq = 0; + + mutex_lock(&mt_gpufreq_power_lock); + + if (mt_gpufreq_ready == false) { + gpufreq_warn("@%s: GPU DVFS not ready!\n", __func__); + mutex_unlock(&mt_gpufreq_power_lock); + return; + } + + if (mt_gpufreqs_num == 0) { + gpufreq_warn("@%s: mt_gpufreqs_num == 0!\n", __func__); + mutex_unlock(&mt_gpufreq_power_lock); + return; + } + + if (g_limited_pbm_ignore_state == true) { + gpufreq_info("@%s: g_limited_pbm_ignore_state == true!\n", __func__); + mutex_unlock(&mt_gpufreq_power_lock); + return; + } + + if (limited_power == mt_gpufreq_pbm_limited_gpu_power) { + gpufreq_dbg("@%s: limited_power(%d mW) not changed, skip it!\n", + __func__, limited_power); + mutex_unlock(&mt_gpufreq_power_lock); + return; + } + + mt_gpufreq_pbm_limited_gpu_power = limited_power; + + gpufreq_dbg("@%s: limited_power = %d\n", __func__, limited_power); + +#ifdef MT_GPUFREQ_DYNAMIC_POWER_TABLE_UPDATE + mt_update_gpufreqs_power_table(); /* TODO: need to check overhead? */ +#endif + + if (limited_power == 0) + mt_gpufreq_pbm_limited_index = 0; + else { + limited_freq = _mt_gpufreq_get_limited_freq(limited_power); + + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs[i].gpufreq_khz <= limited_freq) { + mt_gpufreq_pbm_limited_index = i; + break; + } + } + } + + gpufreq_dbg("PBM limit frequency upper bound to id = %d\n", mt_gpufreq_pbm_limited_index); + + if (NULL != g_pGpufreq_power_limit_notify) + g_pGpufreq_power_limit_notify(mt_gpufreq_pbm_limited_index); + + mutex_unlock(&mt_gpufreq_power_lock); +#endif +} + +unsigned int mt_gpufreq_get_leakage_mw(void) +{ +#ifndef DISABLE_PBM_FEATURE + int temp = 0; +#ifdef STATIC_PWR_READY2USE + unsigned int cur_vcore = _mt_gpufreq_get_cur_volt() / 100; +#endif + +#ifdef CONFIG_THERMAL + temp = get_immediate_gpu_wrap() / 1000; +#else + temp = 40; +#endif + +#ifdef STATIC_PWR_READY2USE + return mt_spower_get_leakage(MT_SPOWER_GPU, cur_vcore, temp); +#else + return 130; +#endif + +#else /* DISABLE_PBM_FEATURE */ + return 0; +#endif +} + +/************************************************ + * return current GPU thermal limit index + *************************************************/ +unsigned int mt_gpufreq_get_thermal_limit_index(void) +{ + gpufreq_dbg("current GPU thermal limit index is %d\n", g_limited_max_id); + return g_limited_max_id; +} +EXPORT_SYMBOL(mt_gpufreq_get_thermal_limit_index); + +/************************************************ + * return current GPU thermal limit frequency + *************************************************/ +unsigned int mt_gpufreq_get_thermal_limit_freq(void) +{ + gpufreq_dbg("current GPU thermal limit freq is %d MHz\n", + mt_gpufreqs[g_limited_max_id].gpufreq_khz / 1000); + return mt_gpufreqs[g_limited_max_id].gpufreq_khz; +} +EXPORT_SYMBOL(mt_gpufreq_get_thermal_limit_freq); + +/************************************************ + * return current GPU frequency index + *************************************************/ +unsigned int mt_gpufreq_get_cur_freq_index(void) +{ + gpufreq_dbg("current GPU frequency OPP index is %d\n", g_cur_gpu_OPPidx); + return g_cur_gpu_OPPidx; +} +EXPORT_SYMBOL(mt_gpufreq_get_cur_freq_index); + +/************************************************ + * return current GPU frequency + *************************************************/ +unsigned int mt_gpufreq_get_cur_freq(void) +{ + gpufreq_dbg("current GPU frequency is %d MHz\n", g_cur_gpu_freq / 1000); + return g_cur_gpu_freq; +} +EXPORT_SYMBOL(mt_gpufreq_get_cur_freq); + +/************************************************ + * return current GPU voltage + *************************************************/ +unsigned int mt_gpufreq_get_cur_volt(void) +{ + return g_cur_gpu_volt; +} +EXPORT_SYMBOL(mt_gpufreq_get_cur_volt); + +/************************************************ + * register / unregister GPU input boost notifiction CB + *************************************************/ +void mt_gpufreq_input_boost_notify_registerCB(gpufreq_input_boost_notify pCB) +{ +#ifdef MT_GPUFREQ_INPUT_BOOST + g_pGpufreq_input_boost_notify = pCB; +#endif +} +EXPORT_SYMBOL(mt_gpufreq_input_boost_notify_registerCB); + +/************************************************ + * register / unregister GPU power limit notifiction CB + *************************************************/ +void mt_gpufreq_power_limit_notify_registerCB(gpufreq_power_limit_notify pCB) +{ + g_pGpufreq_power_limit_notify = pCB; +} +EXPORT_SYMBOL(mt_gpufreq_power_limit_notify_registerCB); + +/************************************************ + * register / unregister set GPU freq CB + *************************************************/ +void mt_gpufreq_setfreq_registerCB(sampler_func pCB) +{ + g_pFreqSampler = pCB; +} +EXPORT_SYMBOL(mt_gpufreq_setfreq_registerCB); + +/************************************************ + * register / unregister set GPU volt CB + *************************************************/ +void mt_gpufreq_setvolt_registerCB(sampler_func pCB) +{ + g_pVoltSampler = pCB; +} +EXPORT_SYMBOL(mt_gpufreq_setvolt_registerCB); + +static int mt_gpufreq_pm_restore_early(struct device *dev) +{ + int i = 0; + int found = 0; + + g_cur_gpu_freq = _mt_gpufreq_get_cur_freq(); + + for (i = 0; i < mt_gpufreqs_num; i++) { + if (g_cur_gpu_freq == mt_gpufreqs[i].gpufreq_khz) { + g_cur_gpu_idx = mt_gpufreqs[i].gpufreq_idx; + g_cur_gpu_volt = mt_gpufreqs[i].gpufreq_volt; + g_cur_gpu_OPPidx = i; + found = 1; + gpufreq_dbg("match g_cur_gpu_OPPidx: %d\n", g_cur_gpu_OPPidx); + break; + } + } + + if (found == 0) { + g_cur_gpu_idx = mt_gpufreqs[0].gpufreq_idx; + g_cur_gpu_volt = mt_gpufreqs[0].gpufreq_volt; + g_cur_gpu_OPPidx = 0; + gpufreq_err("gpu freq not found, set parameter to max freq\n"); + } + + gpufreq_dbg("GPU freq SW/HW: %u/%u, g_cur_gpu_OPPidx: %d\n", + g_cur_gpu_freq, _mt_gpufreq_get_cur_freq(), + g_cur_gpu_OPPidx); + + return 0; +} + +#if defined(CONFIG_OF) +static int mt_gpufreq_dts_map(struct platform_device *pdev) +{ + struct device_node *node; + + /* MFGCLK */ + node = of_find_matching_node(NULL, mt_gpufreq_of_match); + if (!node) { + gpufreq_err("@%s: find GPUFREQ node failed\n", __func__); + BUG(); + } + mt_gpufreq_clk = kzalloc(sizeof(struct mt_gpufreq_clk_t), GFP_KERNEL); + if (NULL == mt_gpufreq_clk) + return -ENOMEM; + mt_gpufreq_clk->clk_mux = devm_clk_get(&pdev->dev, "clk_mux"); + if (IS_ERR(mt_gpufreq_clk->clk_mux)) { + gpufreq_err("cannot get clock mux\n"); + return PTR_ERR(mt_gpufreq_clk->clk_mux); + } + mt_gpufreq_clk->clk_main_parent = devm_clk_get(&pdev->dev, "clk_main_parent"); + if (IS_ERR(mt_gpufreq_clk->clk_main_parent)) { + gpufreq_err("cannot get main clock parent\n"); + return PTR_ERR(mt_gpufreq_clk->clk_main_parent); + } + mt_gpufreq_clk->clk_sub_parent = devm_clk_get(&pdev->dev, "clk_sub_parent"); + if (IS_ERR(mt_gpufreq_clk->clk_sub_parent)) { + gpufreq_err("cannot get sub clock parent\n"); + return PTR_ERR(mt_gpufreq_clk->clk_sub_parent); + } + + /* apmixed */ + node = of_find_compatible_node(NULL, NULL, APMIXED_NODE); + if (!node) { + gpufreq_err("error: cannot find node " APMIXED_NODE); + BUG(); + } + apmixed_base = (unsigned long)of_iomap(node, 0); + if (!apmixed_base) { + gpufreq_err("error: cannot iomap " APMIXED_NODE); + BUG(); + } + + return 0; +} +#else +static int mt_gpufreq_dts_map(struct platform_device *pdev) +{ + return 0; +} +#endif + +static int mt_gpufreq_pdrv_probe(struct platform_device *pdev) +{ + unsigned int reg_val = 0; + int i = 0; +#ifdef MT_GPUFREQ_INPUT_BOOST + int rc; + struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 }; +#endif + + mt_gpufreq_dts_map(pdev); + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_POLLING_TIMER + ktime_t ktime = + ktime_set(mt_gpufreq_low_batt_volume_period_s, mt_gpufreq_low_batt_volume_period_ns); + hrtimer_init(&mt_gpufreq_low_batt_volume_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + mt_gpufreq_low_batt_volume_timer.function = mt_gpufreq_low_batt_volume_timer_func; +#endif + + mt_gpufreq_dvfs_table_type = mt_gpufreq_get_dvfs_table_type(); + +#ifdef VGPU_SET_BY_PMIC_WRAP + /********************** + * setup PMIC wrap setting + ***********************/ + mt_cpufreq_set_pmic_phase(PMIC_WRAP_PHASE_NORMAL); +#endif + + /********************** + * Initial leackage power usage + ***********************/ +#ifdef STATIC_PWR_READY2USE + mt_spower_init(); +#endif + + /********************** + * Initial SRAM debugging ptr + ***********************/ +#ifdef MT_GPUFREQ_AEE_RR_REC + _mt_gpufreq_aee_init(); +#endif + + /********************** + * setup gpufreq table + ***********************/ +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + if (mt_gpufreq_dvfs_table_type == 0) /* Segment1: 680M */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e2_0, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e2_0)); + else if (mt_gpufreq_dvfs_table_type == 1) { + if (fake_segment == 0) /* Segment2: 520M */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e2_1, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e2_1)); + else if (fake_segment == 2) /* fake Segment2: max 520M, flavor:_50 */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e2_3, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e2_3)); + else /* fake Segment2: max 350M, flavor:_50_k2_720p */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e2_4, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e2_4)); + } else if (mt_gpufreq_dvfs_table_type == 2) + if (fake_segment == 0) /* Segment3: 350M */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e2_2, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e2_2)); + else /* fake Segment3: max 350M, flavor:_38 */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e2_4, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e2_4)); + else + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e2_0, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e2_0)); +#else /* MT_GPUFREQ_GPU_SOURCE_FROM_VCORE */ + if (mt_gpufreq_dvfs_table_type == 0) /* Segment1: Free */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e1_0, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e1_0)); + else if (mt_gpufreq_dvfs_table_type == 1) /* Segment2: 550M */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e1_1, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e1_1)); + else if (mt_gpufreq_dvfs_table_type == 3) /* 800M for turbo segment */ + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e1_t, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e1_t)); + else + mt_setup_gpufreqs_table(mt_gpufreq_opp_tbl_e1_0, + ARRAY_SIZE(mt_gpufreq_opp_tbl_e1_0)); +#endif + + /********************** + * setup PMIC init value + ***********************/ +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + /* Set VGPU_VOSEL_CTRL[1] to HW control */ + pmic_config_interface(PMIC_ADDR_VGPU_VOSEL_CTRL, 0x1, + PMIC_ADDR_VGPU_VOSEL_CTRL_MASK, + PMIC_ADDR_VGPU_VOSEL_CTRL_SHIFT); + /* Set VGPU_EN_CTRL[0] SW control to 0 */ + pmic_config_interface(PMIC_ADDR_VGPU_EN_CTRL, 0x0, + PMIC_ADDR_VGPU_EN_CTRL_MASK, + PMIC_ADDR_VGPU_EN_CTRL_SHIFT); + /* Set VGPU_EN[0] to 1 */ + pmic_config_interface(PMIC_ADDR_VGPU_EN, 0x1, + PMIC_ADDR_VGPU_EN_MASK, + PMIC_ADDR_VGPU_EN_SHIFT); +#endif + +#ifdef MT_GPUFREQ_AEE_RR_REC + aee_rr_rec_gpu_dvfs_status(aee_rr_curr_gpu_dvfs_status() | (1 << GPU_DVFS_IS_VGPU_ENABLED)); +#endif + + mt_gpufreq_volt_enable_state = 1; + +#ifndef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + /* Get VGPU_VOSEL_CTRL[1] */ + pmic_read_interface(PMIC_ADDR_VGPU_VOSEL_CTRL, ®_val, + PMIC_ADDR_VGPU_VOSEL_CTRL_MASK, + PMIC_ADDR_VGPU_VOSEL_CTRL_SHIFT); + gpufreq_dbg("VGPU_VOSEL_CTRL[1] = %d\n", reg_val); + /* Get VGPU_EN_CTRL[0] */ + pmic_read_interface(PMIC_ADDR_VGPU_EN_CTRL, ®_val, + PMIC_ADDR_VGPU_EN_CTRL_MASK, + PMIC_ADDR_VGPU_EN_CTRL_SHIFT); + gpufreq_dbg("VGPU_EN_CTRL[0] = %d\n", reg_val); + /* Get VGPU_EN[0] */ + pmic_read_interface(PMIC_ADDR_VGPU_EN, ®_val, + PMIC_ADDR_VGPU_EN_MASK, + PMIC_ADDR_VGPU_EN_SHIFT); + gpufreq_dbg("VGPU_EN[0] = %d\n", reg_val); +#else + reg_val = 0; +#endif + + g_cur_freq_init_keep = g_cur_gpu_freq; + +#ifdef VGPU_SET_BY_PMIC_WRAP +#if 1 + /********************** + * PMIC wrap setting for gpu default volt value + ***********************/ + reg_val = mt_gpufreq_volt_to_pmic_wrap(mt_gpufreqs[0].gpufreq_volt); + mt_cpufreq_set_pmic_cmd(PMIC_WRAP_PHASE_NORMAL, IDX_NM_VGPU, reg_val); +#else + mt_gpufreq_reg_write(0x02B0, PMIC_WRAP_DVFS_ADR2); + + reg_val = mt_gpufreq_volt_to_pmic_wrap(mt_gpufreqs[0].gpufreq_volt); + mt_gpufreq_reg_write(reg_val, PMIC_WRAP_DVFS_WDATA2); /* 1.125V */ +#endif +#endif + + /********************** + * setup initial frequency + ***********************/ + mt_gpufreq_set_initial(); + + gpufreq_info("GPU current F=%u/%uKHz, V=%d/%dmV, cur_idx=%d, cur_OPPidx=%d\n", + _mt_gpufreq_get_cur_freq(), g_cur_gpu_freq, + _mt_gpufreq_get_cur_volt() / 100, g_cur_gpu_volt / 100, + g_cur_gpu_idx, g_cur_gpu_OPPidx); + + mt_gpufreq_ready = true; + +#ifdef MT_GPUFREQ_INPUT_BOOST + mt_gpufreq_up_task = + kthread_create(mt_gpufreq_input_boost_task, NULL, "mt_gpufreq_input_boost_task"); + if (IS_ERR(mt_gpufreq_up_task)) + return PTR_ERR(mt_gpufreq_up_task); + + sched_setscheduler_nocheck(mt_gpufreq_up_task, SCHED_FIFO, ¶m); + get_task_struct(mt_gpufreq_up_task); + + rc = input_register_handler(&mt_gpufreq_input_handler); +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLT_PROTECT + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs[i].gpufreq_khz <= MT_GPUFREQ_LOW_BATT_VOLT_LIMIT_FREQ_1) { + mt_gpufreq_low_bat_volt_limited_index_1 = i; + break; + } + } + + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs[i].gpufreq_khz <= MT_GPUFREQ_LOW_BATT_VOLT_LIMIT_FREQ_2) { + mt_gpufreq_low_bat_volt_limited_index_2 = i; + break; + } + } + + register_low_battery_notify(&mt_gpufreq_low_batt_volt_callback, LOW_BATTERY_PRIO_GPU); +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_PROTECT + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs[i].gpufreq_khz <= MT_GPUFREQ_LOW_BATT_VOLUME_LIMIT_FREQ_1) { + mt_gpufreq_low_bat_volume_limited_index_1 = i; + break; + } + } + + register_battery_percent_notify(&mt_gpufreq_low_batt_volume_callback, + BATTERY_PERCENT_PRIO_GPU); +#endif + +#ifdef MT_GPUFREQ_OC_PROTECT + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs[i].gpufreq_khz <= MT_GPUFREQ_OC_LIMIT_FREQ_1) { + mt_gpufreq_oc_limited_index_1 = i; + break; + } + } + + register_battery_oc_notify(&mt_gpufreq_oc_callback, BATTERY_OC_PRIO_GPU); +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_POLLING_TIMER + mt_gpufreq_low_batt_volume_thread = kthread_run(mt_gpufreq_low_batt_volume_thread_handler, + 0, "gpufreq low batt volume"); + if (IS_ERR(mt_gpufreq_low_batt_volume_thread)) + gpufreq_err("failed to create gpufreq_low_batt_volume thread\n"); + + hrtimer_start(&mt_gpufreq_low_batt_volume_timer, ktime, HRTIMER_MODE_REL); +#endif + +#ifndef DISABLE_PBM_FEATURE + INIT_DEFERRABLE_WORK(¬ify_pbm_gpuoff_work, mt_gpufreq_notify_pbm_gpuoff); +#endif + + return 0; +} + +/*************************************** + * this function should never be called + ****************************************/ +static int mt_gpufreq_pdrv_remove(struct platform_device *pdev) +{ +#ifdef MT_GPUFREQ_INPUT_BOOST + input_unregister_handler(&mt_gpufreq_input_handler); + + kthread_stop(mt_gpufreq_up_task); + put_task_struct(mt_gpufreq_up_task); +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_POLLING_TIMER + kthread_stop(mt_gpufreq_low_batt_volume_thread); + hrtimer_cancel(&mt_gpufreq_low_batt_volume_timer); +#endif + + return 0; +} + + +static const struct dev_pm_ops mt_gpufreq_pm_ops = { + .suspend = NULL, + .resume = NULL, + .restore_early = mt_gpufreq_pm_restore_early, +}; + +struct platform_device mt_gpufreq_pdev = { + .name = "mt-gpufreq", + .id = -1, +}; + +static struct platform_driver mt_gpufreq_pdrv = { + .probe = mt_gpufreq_pdrv_probe, + .remove = mt_gpufreq_pdrv_remove, + .driver = { + .name = "mt-gpufreq", + .pm = &mt_gpufreq_pm_ops, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = mt_gpufreq_of_match, +#endif + }, +}; + + +#ifdef CONFIG_PROC_FS +/* + * PROC + */ + +/*************************** + * show current debug status + ****************************/ +static int mt_gpufreq_debug_proc_show(struct seq_file *m, void *v) +{ + if (mt_gpufreq_debug) + seq_puts(m, "gpufreq debug enabled\n"); + else + seq_puts(m, "gpufreq debug disabled\n"); + + return 0; +} + +/*********************** + * enable debug message + ************************/ +static ssize_t mt_gpufreq_debug_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + int debug = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtoint(desc, 10, &debug)) { + if (debug == 0) + mt_gpufreq_debug = 0; + else if (debug == 1) + mt_gpufreq_debug = 1; + else + gpufreq_warn("bad argument!! should be 0 or 1 [0: disable, 1: enable]\n"); + } else + gpufreq_warn("bad argument!! should be 0 or 1 [0: disable, 1: enable]\n"); + + return count; +} + +#ifdef MT_GPUFREQ_OC_PROTECT +/**************************** + * show current limited by low batt volume + *****************************/ +static int mt_gpufreq_limited_oc_ignore_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "g_limited_max_id = %d, g_limited_oc_ignore_state = %d\n", g_limited_max_id, + g_limited_oc_ignore_state); + + return 0; +} + +/********************************** + * limited for low batt volume protect + ***********************************/ +static ssize_t mt_gpufreq_limited_oc_ignore_proc_write(struct file *file, + const char __user *buffer, size_t count, + loff_t *data) +{ + char desc[32]; + int len = 0; + + unsigned int ignore = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtouint(desc, 10, &ignore)) { + if (ignore == 1) + g_limited_oc_ignore_state = true; + else if (ignore == 0) + g_limited_oc_ignore_state = false; + else + gpufreq_warn + ("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + } else + gpufreq_warn("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + + return count; +} +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_PROTECT +/**************************** + * show current limited by low batt volume + *****************************/ +static int mt_gpufreq_limited_low_batt_volume_ignore_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "g_limited_max_id = %d, g_limited_low_batt_volume_ignore_state = %d\n", + g_limited_max_id, g_limited_low_batt_volume_ignore_state); + + return 0; +} + +/********************************** + * limited for low batt volume protect + ***********************************/ +static ssize_t mt_gpufreq_limited_low_batt_volume_ignore_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + unsigned int ignore = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtouint(desc, 10, &ignore)) { + if (ignore == 1) + g_limited_low_batt_volume_ignore_state = true; + else if (ignore == 0) + g_limited_low_batt_volume_ignore_state = false; + else + gpufreq_warn + ("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + } else + gpufreq_warn("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + + return count; +} +#endif + +#ifdef MT_GPUFREQ_LOW_BATT_VOLT_PROTECT +/**************************** + * show current limited by low batt volt + *****************************/ +static int mt_gpufreq_limited_low_batt_volt_ignore_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "g_limited_max_id = %d, g_limited_low_batt_volt_ignore_state = %d\n", + g_limited_max_id, g_limited_low_batt_volt_ignore_state); + + return 0; +} + +/********************************** + * limited for low batt volt protect + ***********************************/ +static ssize_t mt_gpufreq_limited_low_batt_volt_ignore_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + unsigned int ignore = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtouint(desc, 10, &ignore)) { + if (ignore == 1) + g_limited_low_batt_volt_ignore_state = true; + else if (ignore == 0) + g_limited_low_batt_volt_ignore_state = false; + else + gpufreq_warn + ("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + } else + gpufreq_warn("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + + return count; +} +#endif + +/**************************** + * show current limited by thermal + *****************************/ +static int mt_gpufreq_limited_thermal_ignore_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "g_limited_max_id = %d, g_limited_thermal_ignore_state = %d\n", + g_limited_max_id, g_limited_thermal_ignore_state); + + return 0; +} + +/********************************** + * limited for thermal protect + ***********************************/ +static ssize_t mt_gpufreq_limited_thermal_ignore_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + unsigned int ignore = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtouint(desc, 10, &ignore)) { + if (ignore == 1) + g_limited_thermal_ignore_state = true; + else if (ignore == 0) + g_limited_thermal_ignore_state = false; + else + gpufreq_warn + ("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + } else + gpufreq_warn("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + + return count; +} + +#ifndef DISABLE_PBM_FEATURE +/**************************** + * show current limited by PBM + *****************************/ +static int mt_gpufreq_limited_pbm_ignore_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "g_limited_max_id = %d, g_limited_oc_ignore_state = %d\n", g_limited_max_id, + g_limited_pbm_ignore_state); + + return 0; +} + +/********************************** + * limited for low batt volume protect + ***********************************/ +static ssize_t mt_gpufreq_limited_pbm_ignore_proc_write(struct file *file, + const char __user *buffer, size_t count, + loff_t *data) +{ + char desc[32]; + int len = 0; + + unsigned int ignore = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtouint(desc, 10, &ignore)) { + if (ignore == 1) + g_limited_pbm_ignore_state = true; + else if (ignore == 0) + g_limited_pbm_ignore_state = false; + else + gpufreq_warn + ("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + } else + gpufreq_warn("bad argument!! should be 0 or 1 [0: not ignore, 1: ignore]\n"); + + return count; +} +#endif + +/**************************** + * show current limited power + *****************************/ +static int mt_gpufreq_limited_power_proc_show(struct seq_file *m, void *v) +{ + + seq_printf(m, "g_limited_max_id = %d, limit frequency = %d\n", + g_limited_max_id, mt_gpufreqs[g_limited_max_id].gpufreq_khz); + + return 0; +} + +/********************************** + * limited power for thermal protect + ***********************************/ +static ssize_t mt_gpufreq_limited_power_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + unsigned int power = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtouint(desc, 10, &power)) + mt_gpufreq_thermal_protect(power); + else + gpufreq_warn("bad argument!! please provide the maximum limited power\n"); + + return count; +} + +/**************************** + * show current limited power by PBM + *****************************/ +#ifndef DISABLE_PBM_FEATURE +static int mt_gpufreq_limited_by_pbm_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "pbm_limited_power = %d, limit index = %d\n", + mt_gpufreq_pbm_limited_gpu_power, mt_gpufreq_pbm_limited_index); + + return 0; +} + +/********************************** + * limited power for thermal protect + ***********************************/ +static ssize_t mt_gpufreq_limited_by_pbm_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + unsigned int power = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtouint(desc, 10, &power)) + mt_gpufreq_set_power_limit_by_pbm(power); + else + gpufreq_warn("bad argument!! please provide the maximum limited power\n"); + + return count; +} +#endif + +/****************************** + * show current GPU DVFS stauts + *******************************/ +static int mt_gpufreq_state_proc_show(struct seq_file *m, void *v) +{ + if (!mt_gpufreq_pause) + seq_puts(m, "GPU DVFS enabled\n"); + else + seq_puts(m, "GPU DVFS disabled\n"); + + return 0; +} + +/**************************************** + * set GPU DVFS stauts by sysfs interface + *****************************************/ +static ssize_t mt_gpufreq_state_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + int enabled = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtoint(desc, 10, &enabled)) { + if (enabled == 1) { + mt_gpufreq_keep_max_frequency_state = false; + mt_gpufreq_state_set(1); + } else if (enabled == 0) { + /* Keep MAX frequency when GPU DVFS disabled. */ + mt_gpufreq_keep_max_frequency_state = true; + mt_gpufreq_voltage_enable_set(1); + mt_gpufreq_target(g_gpufreq_max_id); + mt_gpufreq_state_set(0); + } else + gpufreq_warn("bad argument!! argument should be \"1\" or \"0\"\n"); + } else + gpufreq_warn("bad argument!! argument should be \"1\" or \"0\"\n"); + + return count; +} + +/******************** + * show GPU OPP table + *********************/ +static int mt_gpufreq_opp_dump_proc_show(struct seq_file *m, void *v) +{ + int i = 0; + + for (i = 0; i < mt_gpufreqs_num; i++) { + seq_printf(m, "[%d] ", i); + seq_printf(m, "freq = %d, ", mt_gpufreqs[i].gpufreq_khz); + seq_printf(m, "volt = %d, ", mt_gpufreqs[i].gpufreq_volt); + seq_printf(m, "idx = %d\n", mt_gpufreqs[i].gpufreq_idx); + +#if 0 + for (j = 0; j < ARRAY_SIZE(mt_gpufreqs_golden_power); j++) { + if (mt_gpufreqs_golden_power[j].gpufreq_khz == mt_gpufreqs[i].gpufreq_khz) { + p += sprintf(p, "power = %d\n", + mt_gpufreqs_golden_power[j].gpufreq_power); + break; + } + } +#endif + } + + return 0; +} + +/******************** + * show GPU power table + *********************/ +static int mt_gpufreq_power_dump_proc_show(struct seq_file *m, void *v) +{ + int i = 0; + + for (i = 0; i < mt_gpufreqs_num; i++) { + seq_printf(m, "mt_gpufreqs_power[%d].gpufreq_khz = %d\n", i, + mt_gpufreqs_power[i].gpufreq_khz); + seq_printf(m, "mt_gpufreqs_power[%d].gpufreq_volt = %d\n", i, + mt_gpufreqs_power[i].gpufreq_volt); + seq_printf(m, "mt_gpufreqs_power[%d].gpufreq_power = %d\n", i, + mt_gpufreqs_power[i].gpufreq_power); + } + + return 0; +} + +/*************************** + * show current specific frequency status + ****************************/ +static int mt_gpufreq_opp_freq_proc_show(struct seq_file *m, void *v) +{ + if (mt_gpufreq_keep_opp_frequency_state) { + seq_puts(m, "gpufreq keep opp frequency enabled\n"); + seq_printf(m, "freq = %d\n", mt_gpufreqs[mt_gpufreq_keep_opp_index].gpufreq_khz); + seq_printf(m, "volt = %d\n", mt_gpufreqs[mt_gpufreq_keep_opp_index].gpufreq_volt); + } else + seq_puts(m, "gpufreq keep opp frequency disabled\n"); + + return 0; +} + +/*********************** + * enable specific frequency + ************************/ +static ssize_t mt_gpufreq_opp_freq_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + int i = 0; + int fixed_freq = 0; + int found = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtoint(desc, 10, &fixed_freq)) { + if (fixed_freq == 0) { + mt_gpufreq_keep_opp_frequency_state = false; + } else { + for (i = 0; i < mt_gpufreqs_num; i++) { + if (fixed_freq == mt_gpufreqs[i].gpufreq_khz) { + mt_gpufreq_keep_opp_index = i; + found = 1; + break; + } + } + + if (found == 1) { + mt_gpufreq_keep_opp_frequency_state = true; + mt_gpufreq_keep_opp_frequency = fixed_freq; + + mt_gpufreq_voltage_enable_set(1); + mt_gpufreq_target(mt_gpufreq_keep_opp_index); + } + + } + } else + gpufreq_warn("bad argument!! please provide the fixed frequency\n"); + + return count; +} + +/*************************** + * show current specific frequency status + ****************************/ +static int mt_gpufreq_opp_max_freq_proc_show(struct seq_file *m, void *v) +{ + if (mt_gpufreq_opp_max_frequency_state) { + seq_puts(m, "gpufreq opp max frequency enabled\n"); + seq_printf(m, "freq = %d\n", mt_gpufreqs[mt_gpufreq_opp_max_index].gpufreq_khz); + seq_printf(m, "volt = %d\n", mt_gpufreqs[mt_gpufreq_opp_max_index].gpufreq_volt); + } else + seq_puts(m, "gpufreq opp max frequency disabled\n"); + + return 0; +} + +/*********************** + * enable specific frequency + ************************/ +static ssize_t mt_gpufreq_opp_max_freq_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + int i = 0; + int max_freq = 0; + int found = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtoint(desc, 10, &max_freq)) { + if (max_freq == 0) { + mt_gpufreq_opp_max_frequency_state = false; + } else { + for (i = 0; i < mt_gpufreqs_num; i++) { + if (mt_gpufreqs[i].gpufreq_khz <= max_freq) { + mt_gpufreq_opp_max_index = i; + found = 1; + break; + } + } + + if (found == 1) { + mt_gpufreq_opp_max_frequency_state = true; + mt_gpufreq_opp_max_frequency = + mt_gpufreqs[mt_gpufreq_opp_max_index].gpufreq_khz; + + mt_gpufreq_voltage_enable_set(1); + mt_gpufreq_target(mt_gpufreq_opp_max_index); + } + } + } else + gpufreq_warn("bad argument!! please provide the maximum limited frequency\n"); + + return count; +} + +/******************** + * show variable dump + *********************/ +static int mt_gpufreq_var_dump_proc_show(struct seq_file *m, void *v) +{ + int i = 0; + + seq_printf(m, "g_cur_gpu_freq = %d, g_cur_gpu_volt = %d\n", mt_gpufreq_get_cur_freq(), + mt_gpufreq_get_cur_volt()); + seq_printf(m, "g_cur_gpu_idx = %d, g_cur_gpu_OPPidx = %d\n", g_cur_gpu_idx, + g_cur_gpu_OPPidx); + seq_printf(m, "g_limited_max_id = %d\n", g_limited_max_id); + + for (i = 0; i < NR_IDX_POWER_LIMITED; i++) + seq_printf(m, "mt_gpufreq_power_limited_index_array[%d] = %d\n", i, + mt_gpufreq_power_limited_index_array[i]); + + seq_printf(m, "_mt_gpufreq_get_cur_freq = %u KHz\n", _mt_gpufreq_get_cur_freq()); + seq_printf(m, "_mt_gpufreq_get_cur_volt = %u mV\n", _mt_gpufreq_get_cur_volt() / 100); + seq_printf(m, "mt_gpufreq_volt_enable_state = %d\n", mt_gpufreq_volt_enable_state); + seq_printf(m, "dvfs_table_type=%d, mmpll_spd_bond=%d, segment_code=0x%x\n", + mt_gpufreq_dvfs_table_type, mt_gpufreq_dvfs_mmpll_spd_bond, + (get_devinfo_with_index(21) & 0xFF)); + seq_printf(m, "mt_gpufreq_ptpod_disable_idx = %d\n", mt_gpufreq_ptpod_disable_idx); +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + seq_printf(m, "fake_segment=%u, is_vcorefs_can_work=%d\n", + fake_segment, is_vcorefs_can_work()); +#endif + + return 0; +} + +/*************************** + * show current voltage enable status + ****************************/ +static int mt_gpufreq_volt_enable_proc_show(struct seq_file *m, void *v) +{ + if (mt_gpufreq_volt_enable == 1) + seq_puts(m, "gpufreq voltage is enabled\n"); + else if (mt_gpufreq_volt_enable == 2) + seq_puts(m, "gpufreq voltage is always enabled\n"); + else + seq_puts(m, "gpufreq voltage is disabled\n"); + + return 0; +} + +/* + * control current vgpu buck + */ +static ssize_t mt_gpufreq_volt_enable_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + int enable = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtoint(desc, 10, &enable)) { + if (enable == 0) { + mt_gpufreq_volt_enable = 0; + mt_gpufreq_keep_volt_enable = false; + mt_gpufreq_voltage_enable_set(0); + } else if (enable == 1) { + mt_gpufreq_volt_enable = 1; + mt_gpufreq_keep_volt_enable = false; + mt_gpufreq_voltage_enable_set(1); + } else if (enable == 2) { + mt_gpufreq_volt_enable = 2; + mt_gpufreq_keep_volt_enable = true; + mt_gpufreq_voltage_enable_set(1); + } else + gpufreq_warn("bad argument! should be 0/1/2 [0: disable, 1: enable, 2: always on]\n"); + } else + gpufreq_warn("bad argument! should be 0/1/2 [0: disable, 1: enable, 2: always on]\n"); + + return count; +} + +/*************************** + * show current specific frequency status + ****************************/ +static int mt_gpufreq_fixed_freq_volt_proc_show(struct seq_file *m, void *v) +{ + if (mt_gpufreq_fixed_freq_volt_state) { + seq_puts(m, "gpufreq fixed frequency enabled\n"); + seq_printf(m, "fixed frequency = %d\n", mt_gpufreq_fixed_frequency); + seq_printf(m, "fixed voltage = %d\n", mt_gpufreq_fixed_voltage); + } else + seq_puts(m, "gpufreq fixed frequency disabled\n"); + + return 0; +} + +/*********************** + * enable specific frequency + ************************/ +static ssize_t mt_gpufreq_fixed_freq_volt_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + +#ifdef MT_GPUFREQ_GPU_SOURCE_FROM_VCORE + gpufreq_warn("not support fix volt since GPU is sourced from Vcore!\n"); +#else + { + int fixed_freq = 0; + int fixed_volt = 0; + + if (sscanf(desc, "%d %d", &fixed_freq, &fixed_volt) == 2) { + if ((fixed_freq == 0) && (fixed_volt == 0)) { + mt_gpufreq_fixed_freq_volt_state = false; + mt_gpufreq_fixed_frequency = 0; + mt_gpufreq_fixed_voltage = 0; + } else { + /* freq (KHz) */ + if ((fixed_freq >= GPUFREQ_LAST_FREQ_LEVEL) + && (fixed_freq <= GPU_DVFS_FREQT)) { + mt_gpufreq_fixed_freq_volt_state = true; + mt_gpufreq_fixed_frequency = fixed_freq; + mt_gpufreq_fixed_voltage = g_cur_gpu_volt; + mt_gpufreq_voltage_enable_set(1); + mt_gpufreq_clock_switch(mt_gpufreq_fixed_frequency); + g_cur_gpu_freq = mt_gpufreq_fixed_frequency; + } + /* volt (mV) */ + if (fixed_volt >= (mt_gpufreq_pmic_wrap_to_volt(0x0) / 100) && + fixed_volt <= (mt_gpufreq_pmic_wrap_to_volt(0x7F) / 100)) { + mt_gpufreq_fixed_freq_volt_state = true; + mt_gpufreq_fixed_frequency = g_cur_gpu_freq; + mt_gpufreq_fixed_voltage = fixed_volt * 100; + mt_gpufreq_voltage_enable_set(1); + mt_gpufreq_volt_switch(g_cur_gpu_volt, mt_gpufreq_fixed_voltage); + g_cur_gpu_volt = mt_gpufreq_fixed_voltage; + } + } + } else + gpufreq_warn("bad argument!! should be [enable fixed_freq fixed_volt]\n"); + + } +#endif + return count; +} + +#ifdef MT_GPUFREQ_INPUT_BOOST +/***************************** + * show current input boost status + ******************************/ +static int mt_gpufreq_input_boost_proc_show(struct seq_file *m, void *v) +{ + if (mt_gpufreq_input_boost_state == 1) + seq_puts(m, "gpufreq input boost is enabled\n"); + else + seq_puts(m, "gpufreq input boost is disabled\n"); + + return 0; +} + +/*************************** + * enable/disable input boost + ****************************/ +static ssize_t mt_gpufreq_input_boost_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + int debug = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtoint(desc, 10, &debug)) { + if (debug == 0) + mt_gpufreq_input_boost_state = 0; + else if (debug == 1) + mt_gpufreq_input_boost_state = 1; + else + gpufreq_warn("bad argument!! should be 0 or 1 [0: disable, 1: enable]\n"); + } else + gpufreq_warn("bad argument!! should be 0 or 1 [0: disable, 1: enable]\n"); + + return count; +} +#endif + +#define PROC_FOPS_RW(name) \ + static int mt_ ## name ## _proc_open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, mt_ ## name ## _proc_show, PDE_DATA(inode)); \ +} \ +static const struct file_operations mt_ ## name ## _proc_fops = { \ + .owner = THIS_MODULE, \ + .open = mt_ ## name ## _proc_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + .write = mt_ ## name ## _proc_write, \ +} + +#define PROC_FOPS_RO(name) \ + static int mt_ ## name ## _proc_open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, mt_ ## name ## _proc_show, PDE_DATA(inode)); \ +} \ +static const struct file_operations mt_ ## name ## _proc_fops = { \ + .owner = THIS_MODULE, \ + .open = mt_ ## name ## _proc_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + +#define PROC_ENTRY(name) {__stringify(name), &mt_ ## name ## _proc_fops} + +PROC_FOPS_RW(gpufreq_debug); +PROC_FOPS_RW(gpufreq_limited_power); +#ifdef MT_GPUFREQ_OC_PROTECT +PROC_FOPS_RW(gpufreq_limited_oc_ignore); +#endif +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_PROTECT +PROC_FOPS_RW(gpufreq_limited_low_batt_volume_ignore); +#endif +#ifdef MT_GPUFREQ_LOW_BATT_VOLT_PROTECT +PROC_FOPS_RW(gpufreq_limited_low_batt_volt_ignore); +#endif +PROC_FOPS_RW(gpufreq_limited_thermal_ignore); +#ifndef DISABLE_PBM_FEATURE +PROC_FOPS_RW(gpufreq_limited_pbm_ignore); +PROC_FOPS_RW(gpufreq_limited_by_pbm); +#endif +PROC_FOPS_RW(gpufreq_state); +PROC_FOPS_RO(gpufreq_opp_dump); +PROC_FOPS_RO(gpufreq_power_dump); +PROC_FOPS_RW(gpufreq_opp_freq); +PROC_FOPS_RW(gpufreq_opp_max_freq); +PROC_FOPS_RO(gpufreq_var_dump); +PROC_FOPS_RW(gpufreq_volt_enable); +PROC_FOPS_RW(gpufreq_fixed_freq_volt); +#ifdef MT_GPUFREQ_INPUT_BOOST +PROC_FOPS_RW(gpufreq_input_boost); +#endif + +static int mt_gpufreq_create_procfs(void) +{ + struct proc_dir_entry *dir = NULL; + int i; + + struct pentry { + const char *name; + const struct file_operations *fops; + }; + + const struct pentry entries[] = { + PROC_ENTRY(gpufreq_debug), + PROC_ENTRY(gpufreq_limited_power), +#ifdef MT_GPUFREQ_OC_PROTECT + PROC_ENTRY(gpufreq_limited_oc_ignore), +#endif +#ifdef MT_GPUFREQ_LOW_BATT_VOLUME_PROTECT + PROC_ENTRY(gpufreq_limited_low_batt_volume_ignore), +#endif +#ifdef MT_GPUFREQ_LOW_BATT_VOLT_PROTECT + PROC_ENTRY(gpufreq_limited_low_batt_volt_ignore), +#endif + PROC_ENTRY(gpufreq_limited_thermal_ignore), +#ifndef DISABLE_PBM_FEATURE + PROC_ENTRY(gpufreq_limited_pbm_ignore), + PROC_ENTRY(gpufreq_limited_by_pbm), +#endif + PROC_ENTRY(gpufreq_state), + PROC_ENTRY(gpufreq_opp_dump), + PROC_ENTRY(gpufreq_power_dump), + PROC_ENTRY(gpufreq_opp_freq), + PROC_ENTRY(gpufreq_opp_max_freq), + PROC_ENTRY(gpufreq_var_dump), + PROC_ENTRY(gpufreq_volt_enable), + PROC_ENTRY(gpufreq_fixed_freq_volt), +#ifdef MT_GPUFREQ_INPUT_BOOST + PROC_ENTRY(gpufreq_input_boost), +#endif + }; + + + dir = proc_mkdir("gpufreq", NULL); + + if (!dir) { + gpufreq_err("fail to create /proc/gpufreq @ %s()\n", __func__); + return -ENOMEM; + } + + for (i = 0; i < ARRAY_SIZE(entries); i++) { + if (!proc_create + (entries[i].name, S_IRUGO | S_IWUSR | S_IWGRP, dir, entries[i].fops)) + gpufreq_err("@%s: create /proc/gpufreq/%s failed\n", __func__, + entries[i].name); + } + + return 0; +} +#endif /* CONFIG_PROC_FS */ + + +/********************************** + * mediatek gpufreq initialization + ***********************************/ +static int __init mt_gpufreq_init(void) +{ + int ret = 0; + + gpufreq_info("@%s\n", __func__); + +#ifdef CONFIG_PROC_FS + + /* init proc */ + if (mt_gpufreq_create_procfs()) + goto out; + +#endif /* CONFIG_PROC_FS */ + +#if 0 + clk_cfg_0 = DRV_Reg32(CLK_CFG_0); + clk_cfg_0 = (clk_cfg_0 & 0x00070000) >> 16; + + gpufreq_dbg("clk_cfg_0 = %d\n", clk_cfg_0); + + switch (clk_cfg_0) { + case 0x5: /* 476Mhz */ + g_cur_freq = GPU_MMPLL_D3; + break; + case 0x2: /* 403Mhz */ + g_cur_freq = GPU_SYSPLL_D2; + break; + case 0x6: /* 357Mhz */ + g_cur_freq = GPU_MMPLL_D4; + break; + case 0x4: /* 312Mhz */ + g_cur_freq = GPU_UNIVPLL1_D2; + break; + case 0x7: /* 286Mhz */ + g_cur_freq = GPU_MMPLL_D5; + break; + case 0x3: /* 268Mhz */ + g_cur_freq = GPU_SYSPLL_D3; + break; + case 0x1: /* 238Mhz */ + g_cur_freq = GPU_MMPLL_D6; + break; + case 0x0: /* 156Mhz */ + g_cur_freq = GPU_UNIVPLL1_D4; + break; + default: + break; + } + + + g_cur_freq_init_keep = g_cur_gpu_freq; + gpufreq_dbg("g_cur_freq_init_keep = %d\n", g_cur_freq_init_keep); +#endif + + /* register platform device/driver */ +#if !defined(CONFIG_OF) + ret = platform_device_register(&mt_gpufreq_pdev); + if (ret) { + gpufreq_err("fail to register gpufreq device @ %s()\n", __func__); + goto out; + } +#endif + + ret = platform_driver_register(&mt_gpufreq_pdrv); + if (ret) { + gpufreq_err("fail to register gpufreq driver @ %s()\n", __func__); +#if !defined(CONFIG_OF) + platform_device_unregister(&mt_gpufreq_pdev); +#endif + } + +out: + return ret; + +} + +static void __exit mt_gpufreq_exit(void) +{ + platform_driver_unregister(&mt_gpufreq_pdrv); +#if !defined(CONFIG_OF) + platform_device_unregister(&mt_gpufreq_pdev); +#endif +} +module_init(mt_gpufreq_init); +module_exit(mt_gpufreq_exit); + +MODULE_DESCRIPTION("MediaTek GPU Frequency Scaling driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq.h b/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq.h new file mode 100644 index 0000000000000000000000000000000000000000..0b99467ea639f4967d0278e6453788bbff3af312 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_GPUFREQ_H +#define _MT_GPUFREQ_H + +#include + +/* + * Clock Mux Register + */ +/*#define CLK26CALI (0xF00001C0) // FIX ME, No this register +#define CLK_MISC_CFG_0 (0xF0000210) +#define CLK_MISC_CFG_1 (0xF0000214) +#define CLK26CALI_0 (0xF0000220) +#define CLK26CALI_1 (0xF0000224) +#define CLK26CALI_2 (0xF0000228) +#define MBIST_CFG_0 (0xF0000308) +#define MBIST_CFG_1 (0xF000030C) +#define MBIST_CFG_2 (0xF0000310) +#define MBIST_CFG_3 (0xF0000314) +*/ + + +#if 0 +/* + * PMIC Wrapper DVFS Register + */ +#define PWRAP_BASE (0xF000D000) +#define PMIC_WRAP_DVFS_ADR0 (PWRAP_BASE + 0xE8) /**/ +#define PMIC_WRAP_DVFS_WDATA0 (PWRAP_BASE + 0xEC) /**/ +#define PMIC_WRAP_DVFS_ADR1 (PWRAP_BASE + 0xF0) /**/ +#define PMIC_WRAP_DVFS_WDATA1 (PWRAP_BASE + 0xF4) /**/ +#define PMIC_WRAP_DVFS_ADR2 (PWRAP_BASE + 0xF8) /**/ +#define PMIC_WRAP_DVFS_WDATA2 (PWRAP_BASE + 0xFC) /**/ +#define PMIC_WRAP_DVFS_ADR3 (PWRAP_BASE + 0x100) /**/ +#define PMIC_WRAP_DVFS_WDATA3 (PWRAP_BASE + 0x104) /**/ +#define PMIC_WRAP_DVFS_ADR4 (PWRAP_BASE + 0x108) /**/ +#define PMIC_WRAP_DVFS_WDATA4 (PWRAP_BASE + 0x10C) /**/ +#define PMIC_WRAP_DVFS_ADR5 (PWRAP_BASE + 0x110) /**/ +#define PMIC_WRAP_DVFS_WDATA5 (PWRAP_BASE + 0x114) /**/ +#define PMIC_WRAP_DVFS_ADR6 (PWRAP_BASE + 0x118) /**/ +#define PMIC_WRAP_DVFS_WDATA6 (PWRAP_BASE + 0x11C) /**/ +#define PMIC_WRAP_DVFS_ADR7 (PWRAP_BASE + 0x120) /**/ +#define PMIC_WRAP_DVFS_WDATA7 (PWRAP_BASE + 0x124) /**/ +#endif + +enum post_div_enum { + POST_DIV2 = 0, + POST_DIV4, + POST_DIV8, +}; + +struct mt_gpufreq_table_info { + unsigned int gpufreq_khz; + unsigned int gpufreq_volt; + unsigned int gpufreq_idx; +}; + +struct mt_gpufreq_power_table_info { + unsigned int gpufreq_khz; + unsigned int gpufreq_volt; + unsigned int gpufreq_power; +}; + +struct mt_gpufreq_clk_t { + struct clk *clk_mux; /* main clock for mfg setting */ + struct clk *clk_main_parent; /* substitution clock for mfg transient mux setting */ + struct clk *clk_sub_parent; /* substitution clock for mfg transient parent setting */ +}; + + +/* + * extern function + */ +extern int mt_gpufreq_state_set(int enabled); +extern void mt_gpufreq_thermal_protect(unsigned int limited_power); +extern unsigned int mt_gpufreq_get_max_power(void); +extern unsigned int mt_gpufreq_get_min_power(void); +extern unsigned int mt_gpufreq_get_cur_freq_index(void); +extern unsigned int mt_gpufreq_get_cur_freq(void); +extern unsigned int mt_gpufreq_get_cur_volt(void); +extern unsigned int mt_gpufreq_get_dvfs_table_num(void); +extern unsigned int mt_gpufreq_target(unsigned int idx); +extern unsigned int mt_gpufreq_voltage_enable_set(unsigned int enable); +extern unsigned int mt_gpufreq_update_volt(unsigned int pmic_volt[], unsigned int array_size); +extern unsigned int mt_gpufreq_get_freq_by_idx(unsigned int idx); +extern void mt_gpufreq_restore_default_volt(void); +extern void mt_gpufreq_enable_by_ptpod(void); +extern void mt_gpufreq_disable_by_ptpod(void); +extern unsigned int mt_gpufreq_get_thermal_limit_index(void); +extern unsigned int mt_gpufreq_get_thermal_limit_freq(void); +extern void mt_gpufreq_set_power_limit_by_pbm(unsigned int limited_power); +extern unsigned int mt_gpufreq_get_leakage_mw(void); + +extern unsigned int mt_get_mfgclk_freq(void); /* Freq Meter API */ +extern u32 get_devinfo_with_index(u32 index); + +/* #ifdef MT_GPUFREQ_AEE_RR_REC */ +extern void aee_rr_rec_gpu_dvfs_vgpu(u8 val); +extern void aee_rr_rec_gpu_dvfs_oppidx(u8 val); +extern void aee_rr_rec_gpu_dvfs_status(u8 val); +extern u8 aee_rr_curr_gpu_dvfs_status(void); +/* #endif */ + +/* + * power limit notification + */ +typedef void (*gpufreq_power_limit_notify)(unsigned int); +extern void mt_gpufreq_power_limit_notify_registerCB(gpufreq_power_limit_notify pCB); + +/* + * input boost notification + */ +typedef void (*gpufreq_input_boost_notify)(unsigned int); +extern void mt_gpufreq_input_boost_notify_registerCB(gpufreq_input_boost_notify pCB); + +/* + * profiling purpose + */ +typedef void (*sampler_func)(unsigned int); +extern void mt_gpufreq_setfreq_registerCB(sampler_func pCB); +extern void mt_gpufreq_setvolt_registerCB(sampler_func pCB); + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq_bringup.c b/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq_bringup.c new file mode 100644 index 0000000000000000000000000000000000000000..2389999b9b2bbd2dc4a281fe01054da6abf2d633 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_gpufreq_bringup.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2015-2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +unsigned int mt_gpufreq_voltage_enable_set(unsigned int enable) +{ + return 0; +} + +void mt_gpufreq_enable_by_ptpod(void) +{ +} + +void mt_gpufreq_disable_by_ptpod(void) +{ +} + +void mt_gpufreq_restore_default_volt(void) +{ +} + +unsigned int mt_gpufreq_update_volt(unsigned int pmic_volt[], + unsigned int array_size) +{ + return 0; +} + +unsigned int mt_gpufreq_get_dvfs_table_num(void) +{ + return 0; +} + +unsigned int mt_gpufreq_get_freq_by_idx(unsigned int idx) +{ + return 0; +} + +int mt_gpufreq_state_set(int enabled) +{ + return 0; +} + +unsigned int mt_gpufreq_target(unsigned int idx) +{ + return 0; +} + +void mt_gpufreq_thermal_protect(unsigned int limited_power) +{ +} + +unsigned int mt_gpufreq_get_max_power(void) +{ + return 0; +} + +unsigned int mt_gpufreq_get_min_power(void) +{ + return 0; +} + +unsigned int mt_gpufreq_get_thermal_limit_index(void) +{ + return 0; +} + +unsigned int mt_gpufreq_get_thermal_limit_freq(void) +{ + return 0; +} + +unsigned int mt_gpufreq_get_cur_freq_index(void) +{ + return 0; +} + +unsigned int mt_gpufreq_get_cur_freq(void) +{ + return 0; +} + +unsigned int mt_gpufreq_get_cur_volt(void) +{ + return 0; +} + +void mt_gpufreq_set_power_limit_by_pbm(unsigned int limited_power) +{ +} + +unsigned int mt_gpufreq_get_leakage_mw(void) +{ + return 0; +} + +typedef void (*gpufreq_input_boost_notify)(unsigned int); +void mt_gpufreq_input_boost_notify_registerCB(gpufreq_input_boost_notify pCB) +{ +} + +typedef void (*gpufreq_power_limit_notify)(unsigned int); +void mt_gpufreq_power_limit_notify_registerCB(gpufreq_power_limit_notify pCB) +{ +} + +typedef void (*sampler_func)(unsigned int); +void mt_gpufreq_setfreq_registerCB(sampler_func pCB) +{ +} + +void mt_gpufreq_setvolt_registerCB(sampler_func pCB) +{ +} + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug.S b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug.S new file mode 100644 index 0000000000000000000000000000000000000000..e740e072989f1e8d433cf02dcd430ffc7776cc19 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug.S @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + + .text + + .global __switch_to_smp + .global __switch_to_amp + +.equ ACTLR_SMP_BIT ,0x00000040 + +__switch_to_smp: + MRRC p15,1,r0,r1,c15 + ORR r0,r0,#ACTLR_SMP_BIT + MCRR p15,1,r0,r1,c15 + BX lr + +__switch_to_amp: + MRRC p15,1,r0,r1,c15 + BIC r0,r0,#ACTLR_SMP_BIT + MCRR p15,1,r0,r1,c15 + BX lr diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy.h b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy.h new file mode 100644 index 0000000000000000000000000000000000000000..22488f4b59e83c91c6bfb7371a5c458661872d68 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy.h @@ -0,0 +1,70 @@ +/** +* @file mt_hotplug_strategy.h +* @brief hotplug strategy(hps) - external header file +*/ + +#ifndef __MT_HOTPLUG_STRATEGY_H__ +#define __MT_HOTPLUG_STRATEGY_H__ + + +/*=============================================================*/ +/* Include files */ +/*=============================================================*/ + +/* system includes */ + +/* project includes */ + +/* local includes */ + +/* forward references */ + +/*=============================================================*/ +/* Macro definition */ +/*=============================================================*/ +typedef enum { + BASE_PERF_SERV = 0, + BASE_PPM_SERV, + BASE_COUNT +} hps_base_type_e; + +typedef enum { + LIMIT_THERMAL = 0, + LIMIT_PPM_SERV, + LIMIT_LOW_BATTERY, + LIMIT_ULTRA_POWER_SAVING, + LIMIT_POWER_SERV, + LIMIT_COUNT +} hps_limit_type_e; + +/*=============================================================*/ +/* Type definition */ +/*=============================================================*/ + +/*=============================================================*/ +/* Global variable declaration */ +/*=============================================================*/ + +/*=============================================================*/ +/* Global function declaration */ +/*=============================================================*/ +extern int hps_get_enabled(unsigned int *enabled_ptr); +extern int hps_set_enabled(unsigned int enabled); +extern int hps_get_cpu_num_base(hps_base_type_e type, unsigned int *little_cpu_ptr, + unsigned int *big_cpu_ptr); +extern int hps_set_cpu_num_base(hps_base_type_e type, unsigned int little_cpu, + unsigned int big_cpu); +extern int hps_get_cpu_num_limit(hps_limit_type_e type, unsigned int *little_cpu_ptr, + unsigned int *big_cpu_ptr); +extern int hps_set_cpu_num_limit(hps_limit_type_e type, unsigned int little_cpu, + unsigned int big_cpu); +extern int hps_get_tlp(unsigned int *tlp_ptr); +extern int hps_get_num_possible_cpus(unsigned int *little_cpu_ptr, unsigned int *big_cpu_ptr); +extern int hps_get_num_online_cpus(unsigned int *little_cpu_ptr, unsigned int *big_cpu_ptr); +extern int hps_set_PPM_request(unsigned int little_min, unsigned int little_max, + unsigned int big_min, unsigned int big_max); +/*=============================================================*/ +/* End */ +/*=============================================================*/ + +#endif /* __MT_HOTPLUG_STRATEGY_H__ */ diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_algo.c b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_algo.c new file mode 100644 index 0000000000000000000000000000000000000000..1e653bad7156aedc858d246bfb720bb041283c29 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_algo.c @@ -0,0 +1,563 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/** +* @file mt_hotplug_strategy_algo.c +* @brief hotplug strategy(hps) - algo +*/ + +/*============================================================================*/ +/* Include files */ +/*============================================================================*/ +/* system includes */ +#include /* printk */ +#include /* MODULE_DESCRIPTION, MODULE_LICENSE */ +#include /* module_init, module_exit */ +#include /* cpu_up */ +#include /* kthread_create */ +#include /* wake_lock_init */ +#include /* msleep */ +#include /* BUG_ON */ + +/* local includes */ +#include "mt_hotplug_strategy_internal.h" + +/* forward references */ + +/*============================================================================*/ +/* Macro definition */ +/*============================================================================*/ +/* + * static + */ +#define STATIC +/* #define STATIC static */ + +/* + * config + */ + +/*============================================================================*/ +/* Local type definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local function declarition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local variable definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Global variable definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local function definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Gobal function definition */ +/*============================================================================*/ + +/* power on_off cpus of cluster*/ +/*Use for Fast hotplug.*/ +#ifdef CONFIG_CPU_ISOLATION +void hps_algo_cpu_cluster_action(unsigned int online_cores, unsigned int target_cores, + unsigned int cpu_id_min, unsigned int cpu_id_max, + unsigned int cluster) +{ + unsigned int cpu; + struct cpumask target_cpu_up_cpumask, target_cpu_down_cpumask, target_cpu_isolate_mask; + + cpumask_clear(&target_cpu_up_cpumask); + cpumask_clear(&target_cpu_down_cpumask); + cpumask_copy(&target_cpu_isolate_mask, cpu_isolate_mask); + + if (target_cores > online_cores) { /*Power upcpus */ + for (cpu = cpu_id_min; cpu <= cpu_id_max; ++cpu) { + if (!cpumask_test_cpu(cpu, cpu_online_mask)) { /* For CPU offline */ + cpumask_set_cpu(cpu, &target_cpu_up_cpumask); + ++online_cores; + } else if (cpumask_test_cpu(cpu, cpu_isolate_mask)) { + cpumask_clear_cpu(cpu, &target_cpu_isolate_mask); + ++online_cores; + } + if (target_cores == online_cores) + break; + } + cpu_up_by_mask(&target_cpu_up_cpumask); + cpu_isolate_set(&target_cpu_isolate_mask); + + } else { /*Power downcpus */ + + for (cpu = cpu_id_max; cpu >= cpu_id_min; --cpu) { + if (cpumask_test_cpu(cpu, cpu_online_mask)) { + if (!cpumask_test_cpu(cpu, cpu_isolate_mask)) + cpumask_set_cpu(cpu, &target_cpu_isolate_mask); + else + continue; + --online_cores; + } + if (target_cores == online_cores) + break; + } + cpu_isolate_set(&target_cpu_isolate_mask); + } +} +#else +/* +*power on/off cpus of cluster +*For legacy hotplug use +*/ +static void hps_algo_cpu_cluster_action(unsigned int online_cores, unsigned int target_cores, + unsigned int cpu_id_min, unsigned int cpu_id_max, + unsigned int cluster) +{ + unsigned int cpu; + + if (target_cores > online_cores) { /*Power upcpus */ + for (cpu = cpu_id_min; cpu <= cpu_id_max; ++cpu) { + if (!cpu_online(cpu)) { /* For CPU offline */ + cpu_up(cpu); + ++online_cores; + } + if (target_cores == online_cores) + break; + } + + } else { /*Power downcpus */ + + for (cpu = cpu_id_max; cpu >= cpu_id_min; --cpu) { + if (cpu_online(cpu)) { + cpu_down(cpu); + --online_cores; + } + if (target_cores == online_cores) + break; + } + } +} +#endif + +/* =============================================================================================== */ +/* +* New hotpug strategy +*/ + +void hps_cal_cores(struct hps_func_data *hps_func) +{ + int cpu; + + switch (hps_func->target_root_cpu) { + case 0: + for (cpu = hps_func->base_LL; + cpu < hps_func->limit_LL; cpu++, hps_func->target_LL++, hps_func->cores--) { + if (hps_func->cores <= 0) + break; + } + if (hps_func->cores > 0) { + for (cpu = hps_func->base_L; cpu < hps_func->limit_L; cpu++) { + hps_func->target_L++; + hps_func->cores--; + } + } + set_bit(hps_func->action_LL, (unsigned long *)&hps_ctxt.action); + break; + + case 4: + for (cpu = hps_func->base_L; + cpu < hps_func->limit_L; cpu++, hps_func->target_L++, hps_func->cores--) { + if (hps_func->cores <= 0) + break; + } + if (hps_func->cores > 0) { + for (cpu = hps_func->base_LL; cpu < hps_func->limit_LL; cpu++) { + hps_func->target_LL++; + hps_func->cores--; + } + } + set_bit(hps_func->action_L, (unsigned long *)&hps_ctxt.action); + break; + default: + break; + } +} + +void hps_algo_amp(void) +{ + int val, base_val, target_little_cores, target_big_cores; + struct cpumask little_online_cpumask; + struct cpumask big_online_cpumask; + int little_num_base, little_num_limit, little_num_online; + int big_num_base, big_num_limit, big_num_online; + int target_root_cpu, state_tran_active; + struct hps_func_data hps_func; + /* + * run algo or not by hps_ctxt.enabled + */ + if (!hps_ctxt.enabled) { + atomic_set(&hps_ctxt.is_ondemand, 0); + return; + } + + /* + * algo - begin + */ + mutex_lock(&hps_ctxt.lock); + hps_ctxt.action = ACTION_NONE; + atomic_set(&hps_ctxt.is_ondemand, 0); + + /* + * algo - get boundary + */ + little_num_limit = hps_ctxt.little_num_limit_power_serv; + little_num_base = hps_ctxt.little_num_base_perf_serv; + cpumask_and(&little_online_cpumask, &hps_ctxt.little_cpumask, cpu_online_mask); + +#ifdef CONFIG_CPU_ISOLATION + cpumask_andnot(&little_online_cpumask, &little_online_cpumask, cpu_isolate_mask); +#endif + little_num_online = cpumask_weight(&little_online_cpumask); + + big_num_limit = hps_ctxt.big_num_limit_power_serv; + big_num_base = hps_ctxt.big_num_base_perf_serv; + + cpumask_and(&big_online_cpumask, &hps_ctxt.big_cpumask, cpu_online_mask); + +#ifdef CONFIG_CPU_ISOLATION + cpumask_andnot(&big_online_cpumask, &big_online_cpumask, cpu_isolate_mask); +#endif + big_num_online = cpumask_weight(&big_online_cpumask); + + base_val = little_num_base + big_num_base; + target_little_cores = little_num_online; + target_big_cores = big_num_online; + + if (hps_ctxt.cur_dump_enabled) { + hps_debug( + "loads(%u), hvy_tsk(%u), tlp(%u), iowait(%u), limit_t(%u)(%u), limit_lb(%u)(%u), limit_ups(%u)(%u), limit_pos(%u)(%u), base_pes(%u)(%u)\n", + hps_ctxt.cur_loads, hps_ctxt.cur_nr_heavy_task, hps_ctxt.cur_tlp, + hps_ctxt.cur_iowait, hps_ctxt.little_num_limit_thermal, + hps_ctxt.big_num_limit_thermal, hps_ctxt.little_num_limit_low_battery, + hps_ctxt.big_num_limit_low_battery, + hps_ctxt.little_num_limit_ultra_power_saving, + hps_ctxt.big_num_limit_ultra_power_saving, + hps_ctxt.little_num_limit_power_serv, hps_ctxt.big_num_limit_power_serv, + hps_ctxt.little_num_base_perf_serv, hps_ctxt.big_num_base_perf_serv); + } + /* Determine target_root_cpu */ + target_root_cpu = hps_ctxt.root_cpu; + state_tran_active = 0; + if ((hps_ctxt.root_cpu == 0) && (little_num_base == 0) && (big_num_base > 0)) + target_root_cpu = 4; + if ((hps_ctxt.root_cpu == 4) && (big_num_base == 0) && (little_num_base > 0)) + target_root_cpu = 0; + + if ((hps_ctxt.root_cpu == 0) && (little_num_base == 0) && (little_num_limit == 0)) + target_root_cpu = 4; + if ((hps_ctxt.root_cpu == 4) && (big_num_base == 0) && (big_num_limit == 0)) + target_root_cpu = 0; + if (hps_ctxt.root_cpu != target_root_cpu) + state_tran_active = 1; + /* + * update history - tlp + */ + val = hps_ctxt.tlp_history[hps_ctxt.tlp_history_index]; + hps_ctxt.tlp_history[hps_ctxt.tlp_history_index] = hps_ctxt.cur_tlp; + hps_ctxt.tlp_sum += hps_ctxt.cur_tlp; + hps_ctxt.tlp_history_index = + (hps_ctxt.tlp_history_index + 1 == + hps_ctxt.tlp_times) ? 0 : hps_ctxt.tlp_history_index + 1; + ++hps_ctxt.tlp_count; + if (hps_ctxt.tlp_count > hps_ctxt.tlp_times) { + BUG_ON(hps_ctxt.tlp_sum < val); + hps_ctxt.tlp_sum -= val; + hps_ctxt.tlp_avg = hps_ctxt.tlp_sum / hps_ctxt.tlp_times; + } else { + hps_ctxt.tlp_avg = hps_ctxt.tlp_sum / hps_ctxt.tlp_count; + } + if (hps_ctxt.stats_dump_enabled) + hps_ctxt_print_algo_stats_tlp(0); + + hps_func.limit_LL = hps_ctxt.little_num_limit_power_serv; + hps_func.limit_L = hps_ctxt.big_num_limit_power_serv; + hps_func.base_LL = hps_ctxt.little_num_base_perf_serv; + hps_func.base_L = hps_ctxt.big_num_base_perf_serv; + hps_func.target_root_cpu = target_root_cpu; +/* ALGO_RUSH_BOOST: */ + /* + * algo - rush boost + */ + if (hps_ctxt.rush_boost_enabled) { + if (hps_ctxt.cur_loads > + hps_ctxt.rush_boost_threshold * (little_num_online + big_num_online)) + ++hps_ctxt.rush_count; + else + hps_ctxt.rush_count = 0; + if (hps_ctxt.rush_boost_times == 1) + hps_ctxt.tlp_avg = hps_ctxt.cur_tlp; + if ((hps_ctxt.rush_count >= hps_ctxt.rush_boost_times) && + ((little_num_online + big_num_online) * 100 < hps_ctxt.tlp_avg)) { + val = hps_ctxt.tlp_avg / 100 + (hps_ctxt.tlp_avg % 100 ? 1 : 0); + + BUG_ON(!(val > little_num_online + big_num_online)); + if (val > num_possible_cpus()) + val = num_possible_cpus(); + target_little_cores = target_big_cores = 0; + val -= base_val; + + hps_func.cores = val; + hps_func.action_LL = ACTION_RUSH_BOOST_LITTLE; + hps_func.action_L = ACTION_RUSH_BOOST_BIG; + hps_func.target_LL = hps_func.target_L = 0; + hps_cal_cores(&hps_func); + target_little_cores = hps_func.target_LL; + target_big_cores = hps_func.target_L; + } + } /* if (hps_ctxt.rush_boost_enabled) */ + if (hps_ctxt.action) { + target_little_cores += hps_ctxt.little_num_base_perf_serv; + target_big_cores += hps_ctxt.big_num_base_perf_serv; + if (!((little_num_online == target_little_cores) + && (big_num_online == target_big_cores))) + goto ALGO_END_WITH_ACTION; + else + hps_ctxt.action = ACTION_NONE; + } + +/* ALGO_UP: */ + /* + * algo - cpu up + */ + if ((little_num_online + big_num_online) < num_possible_cpus()) { + + /* + * update history - up + */ + val = hps_ctxt.up_loads_history[hps_ctxt.up_loads_history_index]; + hps_ctxt.up_loads_history[hps_ctxt.up_loads_history_index] = hps_ctxt.cur_loads; + hps_ctxt.up_loads_sum += hps_ctxt.cur_loads; + hps_ctxt.up_loads_history_index = + (hps_ctxt.up_loads_history_index + 1 == + hps_ctxt.up_times) ? 0 : hps_ctxt.up_loads_history_index + 1; + ++hps_ctxt.up_loads_count; + /* XXX: use >= or >, which is benifit? use > */ + if (hps_ctxt.up_loads_count > hps_ctxt.up_times) { + BUG_ON(hps_ctxt.up_loads_sum < val); + hps_ctxt.up_loads_sum -= val; + } + if (hps_ctxt.stats_dump_enabled) + hps_ctxt_print_algo_stats_up(0); + if (hps_ctxt.up_times == 1) + hps_ctxt.up_loads_sum = hps_ctxt.cur_loads; + if (hps_ctxt.up_loads_count >= hps_ctxt.up_times) { + target_little_cores = target_big_cores = 0; + if (hps_ctxt.up_loads_sum > + hps_ctxt.up_threshold * hps_ctxt.up_times * (little_num_online + + big_num_online)) { + val = little_num_online + big_num_online + 1; + target_little_cores = target_big_cores = 0; + val -= base_val; + + hps_func.cores = val; + hps_func.action_LL = ACTION_UP_LITTLE; + hps_func.action_L = ACTION_UP_BIG; + hps_func.target_LL = hps_func.target_L = 0; + hps_cal_cores(&hps_func); + target_little_cores = hps_func.target_LL; + target_big_cores = hps_func.target_L; + } + } /* if (hps_ctxt.up_loads_count >= hps_ctxt.up_times) */ + } + /* if ((little_num_online + big_num_online) < num_possible_cpus()) */ + if (hps_ctxt.action) { + target_little_cores += hps_ctxt.little_num_base_perf_serv; + target_big_cores += hps_ctxt.big_num_base_perf_serv; + if (!((little_num_online == target_little_cores) + && (big_num_online == target_big_cores))) + goto ALGO_END_WITH_ACTION; + else + hps_ctxt.action = ACTION_NONE; + } +/* ALGO_DOWN: */ + /* + * algo - cpu down (inc. quick landing) + */ + if (little_num_online + big_num_online > 1) { + /* + * update history - down + */ + val = hps_ctxt.down_loads_history[hps_ctxt.down_loads_history_index]; + hps_ctxt.down_loads_history[hps_ctxt.down_loads_history_index] = hps_ctxt.cur_loads; + hps_ctxt.down_loads_sum += hps_ctxt.cur_loads; + hps_ctxt.down_loads_history_index = + (hps_ctxt.down_loads_history_index + 1 == + hps_ctxt.down_times) ? 0 : hps_ctxt.down_loads_history_index + 1; + ++hps_ctxt.down_loads_count; + /* XXX: use >= or >, which is benifit? use > */ + if (hps_ctxt.down_loads_count > hps_ctxt.down_times) { + BUG_ON(hps_ctxt.down_loads_sum < val); + hps_ctxt.down_loads_sum -= val; + } + if (hps_ctxt.stats_dump_enabled) + hps_ctxt_print_algo_stats_down(0); + if (hps_ctxt.up_times == 1) + hps_ctxt.down_loads_sum = hps_ctxt.cur_loads; + if (hps_ctxt.down_loads_count >= hps_ctxt.down_times) { + unsigned int down_threshold = hps_ctxt.down_threshold * hps_ctxt.down_times; + + val = little_num_online + big_num_online; + while (hps_ctxt.down_loads_sum < down_threshold * (val - 1)) + --val; + BUG_ON(val < 0); + target_little_cores = target_big_cores = 0; + val -= base_val; + + hps_func.cores = val; + hps_func.action_LL = ACTION_DOWN_LITTLE; + hps_func.action_L = ACTION_DOWN_BIG; + hps_func.target_LL = hps_func.target_L = 0; + hps_cal_cores(&hps_func); + target_little_cores = hps_func.target_LL; + target_big_cores = hps_func.target_L; + + } /* if (hps_ctxt.down_loads_count >= hps_ctxt.down_times) */ + } + + /* if (little_num_online + big_num_online > 1) */ + if (hps_ctxt.action) { + target_little_cores += hps_ctxt.little_num_base_perf_serv; + target_big_cores += hps_ctxt.big_num_base_perf_serv; + if (!((little_num_online == target_little_cores) + && (big_num_online == target_big_cores))) + goto ALGO_END_WITH_ACTION; + else + hps_ctxt.action = ACTION_NONE; + } +/*ACTION_ROOT_TRAN: */ + /* Process "ONLY" root cpu transition */ + if (state_tran_active) { + target_little_cores = target_big_cores = 0; + val = little_num_online + big_num_online; + val -= base_val; + + hps_func.cores = val; + hps_func.action_LL = ACTION_ROOT_2_LITTLE; + hps_func.action_L = ACTION_ROOT_2_BIG; + hps_func.target_LL = hps_func.target_L = 0; + hps_cal_cores(&hps_func); + target_little_cores = hps_func.target_LL; + target_big_cores = hps_func.target_L; + state_tran_active = 0; + } + + if (hps_ctxt.action) { + target_little_cores += hps_ctxt.little_num_base_perf_serv; + target_big_cores += hps_ctxt.big_num_base_perf_serv; + if (!((little_num_online == target_little_cores) + && (big_num_online == target_big_cores))) + goto ALGO_END_WITH_ACTION; + else + hps_ctxt.action = ACTION_NONE; + } + +/*Base and limit check*/ + if (target_little_cores < hps_ctxt.little_num_base_perf_serv) + target_little_cores = hps_ctxt.little_num_base_perf_serv; + if (target_little_cores > hps_ctxt.little_num_limit_power_serv) + target_little_cores = hps_ctxt.little_num_limit_power_serv; + + if (target_big_cores < hps_ctxt.big_num_base_perf_serv) + target_big_cores = hps_ctxt.big_num_base_perf_serv; + if (target_big_cores > hps_ctxt.big_num_limit_power_serv) + target_big_cores = hps_ctxt.big_num_limit_power_serv; + + if (!((little_num_online == target_little_cores) && (big_num_online == target_big_cores))) + goto ALGO_END_WITH_ACTION; + else + hps_ctxt.action = ACTION_NONE; + + + if (!hps_ctxt.action) + goto ALGO_END_WO_ACTION; + + + /* + * algo - end + */ +ALGO_END_WITH_ACTION: + +/*Base and limit check*/ + if (target_little_cores < hps_ctxt.little_num_base_perf_serv) + target_little_cores = hps_ctxt.little_num_base_perf_serv; + if (target_little_cores > hps_ctxt.little_num_limit_power_serv) + target_little_cores = hps_ctxt.little_num_limit_power_serv; + + if (target_big_cores < hps_ctxt.big_num_base_perf_serv) + target_big_cores = hps_ctxt.big_num_base_perf_serv; + if (target_big_cores > hps_ctxt.big_num_limit_power_serv) + target_big_cores = hps_ctxt.big_num_limit_power_serv; + + + if (target_root_cpu == 4) { + if (target_big_cores == 0) + target_big_cores++; /*Root cpu must alive!! */ + /*Process big cluster */ + if (big_num_online != target_big_cores) + hps_algo_cpu_cluster_action(big_num_online, target_big_cores, + hps_ctxt.big_cpu_id_min, + hps_ctxt.big_cpu_id_max, 1); + + /*process little cluster */ + if (little_num_online != target_little_cores) + hps_algo_cpu_cluster_action(little_num_online, target_little_cores, + hps_ctxt.little_cpu_id_min, + hps_ctxt.little_cpu_id_max, 0); + } else if (target_root_cpu == 0) { + if (target_little_cores == 0) + target_little_cores++; /*Root cpu must alive!! */ + + /*Process little cluster */ + if (little_num_online != target_little_cores) + hps_algo_cpu_cluster_action(little_num_online, target_little_cores, + hps_ctxt.little_cpu_id_min, + hps_ctxt.little_cpu_id_max, 0); + + /*process big cluster */ + if (big_num_online != target_big_cores) + hps_algo_cpu_cluster_action(big_num_online, target_big_cores, + hps_ctxt.big_cpu_id_min, + hps_ctxt.big_cpu_id_max, 1); + } else + hps_warn("ERROR! root cpu %d\n", target_root_cpu); + if (!get_suspend_status()) { + if (!((little_num_online == target_little_cores) && (big_num_online == target_big_cores))) { + hps_warn( + "END :(%04lx)(%u)(%u) action end(%u)(%u)(%u)(%u) (%u)(%u)(%u)(%u) (%u)(%u)(%u) (%u)(%u)(%u) (%u)(%u)(%u)(%u)(%u) (%u)(%u)(%u)\n", + hps_ctxt.action, little_num_online, big_num_online, hps_ctxt.cur_loads, hps_ctxt.cur_tlp, + hps_ctxt.cur_iowait, hps_ctxt.cur_nr_heavy_task, hps_ctxt.little_num_limit_power_serv, + hps_ctxt.big_num_limit_power_serv, hps_ctxt.little_num_base_perf_serv, hps_ctxt.big_num_base_perf_serv, + hps_ctxt.up_loads_sum, hps_ctxt.up_loads_count, hps_ctxt.up_loads_history_index, + hps_ctxt.down_loads_sum, hps_ctxt.down_loads_count, hps_ctxt.down_loads_history_index, + hps_ctxt.rush_count, hps_ctxt.tlp_sum, hps_ctxt.tlp_count, hps_ctxt.tlp_history_index, + hps_ctxt.tlp_avg, target_root_cpu, target_little_cores, target_big_cores); + } + } + hps_ctxt_reset_stas_nolock(); + +ALGO_END_WO_ACTION: + + mutex_unlock(&hps_ctxt.lock); +} diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_api.c b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_api.c new file mode 100644 index 0000000000000000000000000000000000000000..c2915102ac499f409b319d97e2e03a4b6ca4ff3b --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_api.c @@ -0,0 +1,454 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/** +* @file mt_hotplug_strategy_api.c +* @brief hotplug strategy(hps) - api +*/ + +/*============================================================================*/ +/* Include files */ +/*============================================================================*/ +/* system includes */ +#include /* printk */ +#include /* MODULE_DESCRIPTION, MODULE_LICENSE */ +#include /* module_init, module_exit */ +#include /* sched_get_percpu_load, sched_get_nr_heavy_task */ + +/* local includes */ +#include "mt_hotplug_strategy_internal.h" +#include "mt_hotplug_strategy.h" + +/* forward references */ + +/*============================================================================*/ +/* Macro definition */ +/*============================================================================*/ +/* + * static + */ +#define STATIC +/* #define STATIC static */ + +/* + * config + */ + +/*============================================================================*/ +/* Local type definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local function declarition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local variable definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Global variable definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local function definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Gobal function definition */ +/*============================================================================*/ +/* + * hps set PPM request + */ + +int hps_set_PPM_request(unsigned int little_min, unsigned int little_max, unsigned int big_min, + unsigned int big_max) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + if ((little_min > num_possible_little_cpus()) || (little_max > num_possible_little_cpus())) + return -1; + if ((big_min > num_possible_big_cpus()) || (big_max > num_possible_big_cpus())) + return -1; + + mutex_lock(&hps_ctxt.lock); + hps_ctxt.little_num_base_perf_serv = little_min; + hps_ctxt.little_num_limit_power_serv = little_max; + hps_ctxt.big_num_base_perf_serv = big_min; + hps_ctxt.big_num_limit_power_serv = big_max; + + /* hps_task_wakeup_nolock(); */ + mutex_unlock(&hps_ctxt.lock); + return 0; +} + +/* + * hps cpu num base + */ +int hps_set_cpu_num_base(hps_base_type_e type, unsigned int little_cpu, unsigned int big_cpu) +{ + unsigned int num_online; + + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if ((type < 0) || (type >= BASE_COUNT)) + return -1; + if (hps_ctxt.is_amp) { + if (little_cpu > num_possible_little_cpus()) + return -1; + } else { + if ((little_cpu > num_possible_little_cpus()) || (little_cpu < 1)) + return -1; + } + if ((hps_ctxt.is_hmp || hps_ctxt.is_amp) && (big_cpu > num_possible_big_cpus())) + return -1; + + /* XXX: check mutex lock or not? use hps_ctxt.lock! */ + mutex_lock(&hps_ctxt.lock); + + switch (type) { + case BASE_PERF_SERV: + hps_ctxt.little_num_base_perf_serv = little_cpu; + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + hps_ctxt.big_num_base_perf_serv = big_cpu; + break; + case BASE_PPM_SERV: + hps_ctxt.little_num_base_perf_serv = little_cpu; + hps_ctxt.big_num_base_perf_serv = big_cpu; + break; + default: + break; + } + + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) { + num_online = num_online_big_cpus(); + if ((num_online < big_cpu) && + (num_online < + min(hps_ctxt.big_num_limit_thermal, hps_ctxt.big_num_limit_low_battery)) + && (num_online < + min(hps_ctxt.big_num_limit_ultra_power_saving, + hps_ctxt.big_num_limit_power_serv))) { + hps_task_wakeup_nolock(); + } else { + num_online = num_online_little_cpus(); + if ((num_online < little_cpu) && + (num_online < + min(hps_ctxt.little_num_limit_thermal, + hps_ctxt.little_num_limit_low_battery)) + && (num_online < + min(hps_ctxt.little_num_limit_ultra_power_saving, + hps_ctxt.little_num_limit_power_serv)) + && (num_online_cpus() < (little_cpu + big_cpu))) + hps_task_wakeup_nolock(); + } + } else { + num_online = num_online_little_cpus(); + if ((num_online < little_cpu) && + (num_online < + min(hps_ctxt.little_num_limit_thermal, hps_ctxt.little_num_limit_low_battery)) + && (num_online < + min(hps_ctxt.little_num_limit_ultra_power_saving, + hps_ctxt.little_num_limit_power_serv))) { + hps_task_wakeup_nolock(); + } + } + + mutex_unlock(&hps_ctxt.lock); + + return 0; +} + +int hps_get_cpu_num_base(hps_base_type_e type, unsigned int *little_cpu_ptr, + unsigned int *big_cpu_ptr) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if ((little_cpu_ptr == NULL) || (big_cpu_ptr == NULL)) + return -1; + + if ((type < 0) || (type >= BASE_COUNT)) + return -1; + + switch (type) { + case BASE_PERF_SERV: + *little_cpu_ptr = hps_ctxt.little_num_base_perf_serv; + *big_cpu_ptr = hps_ctxt.big_num_base_perf_serv; + break; + case BASE_PPM_SERV: + *little_cpu_ptr = hps_ctxt.little_num_base_perf_serv; + *big_cpu_ptr = hps_ctxt.big_num_base_perf_serv; + break; + default: + break; + } + + return 0; +} + +/* + * hps cpu num limit + */ +int hps_set_cpu_num_limit(hps_limit_type_e type, unsigned int little_cpu, unsigned int big_cpu) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if ((type < 0) || (type >= LIMIT_COUNT)) + return -1; + if (hps_ctxt.is_amp) { + if (little_cpu > num_possible_little_cpus()) + return -1; + } else { + if ((little_cpu > num_possible_little_cpus()) || (little_cpu < 1)) + return -1; + } + + if ((hps_ctxt.is_hmp || hps_ctxt.is_amp) && (big_cpu > num_possible_big_cpus())) + return -1; + + mutex_lock(&hps_ctxt.lock); + + switch (type) { + case LIMIT_PPM_SERV: + hps_ctxt.little_num_limit_power_serv = little_cpu; + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + hps_ctxt.big_num_limit_power_serv = big_cpu; + break; + case LIMIT_THERMAL: + hps_ctxt.little_num_limit_thermal = little_cpu; + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + hps_ctxt.big_num_limit_thermal = big_cpu; + break; + case LIMIT_LOW_BATTERY: + hps_ctxt.little_num_limit_low_battery = little_cpu; + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + hps_ctxt.big_num_limit_low_battery = big_cpu; + break; + case LIMIT_ULTRA_POWER_SAVING: + hps_ctxt.little_num_limit_ultra_power_saving = little_cpu; + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + hps_ctxt.big_num_limit_ultra_power_saving = big_cpu; + break; + case LIMIT_POWER_SERV: + hps_ctxt.little_num_limit_power_serv = little_cpu; + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + hps_ctxt.big_num_limit_power_serv = big_cpu; + break; + default: + break; + } + + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) { + if (num_online_big_cpus() > big_cpu) + hps_task_wakeup_nolock(); + else if (num_online_little_cpus() > little_cpu) + hps_task_wakeup_nolock(); + } else { + if (num_online_little_cpus() > little_cpu) + hps_task_wakeup_nolock(); + } + + mutex_unlock(&hps_ctxt.lock); + + return 0; +} + +int hps_get_cpu_num_limit(hps_limit_type_e type, unsigned int *little_cpu_ptr, + unsigned int *big_cpu_ptr) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if ((little_cpu_ptr == NULL) || (big_cpu_ptr == NULL)) + return -1; + + if ((type < 0) || (type >= LIMIT_COUNT)) + return -1; + + switch (type) { + case LIMIT_PPM_SERV: + *little_cpu_ptr = hps_ctxt.little_num_limit_thermal; + *big_cpu_ptr = hps_ctxt.big_num_limit_thermal; + break; + case LIMIT_THERMAL: + *little_cpu_ptr = hps_ctxt.little_num_limit_thermal; + *big_cpu_ptr = hps_ctxt.big_num_limit_thermal; + break; + case LIMIT_LOW_BATTERY: + *little_cpu_ptr = hps_ctxt.little_num_limit_low_battery; + *big_cpu_ptr = hps_ctxt.big_num_limit_low_battery; + break; + case LIMIT_ULTRA_POWER_SAVING: + *little_cpu_ptr = hps_ctxt.little_num_limit_ultra_power_saving; + *big_cpu_ptr = hps_ctxt.big_num_limit_ultra_power_saving; + break; + case LIMIT_POWER_SERV: + *little_cpu_ptr = hps_ctxt.little_num_limit_power_serv; + *big_cpu_ptr = hps_ctxt.big_num_limit_power_serv; + break; + default: + break; + } + + return 0; +} + +/* + * hps tlp + */ +int hps_get_tlp(unsigned int *tlp_ptr) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if (tlp_ptr == NULL) + return -1; + + *tlp_ptr = hps_ctxt.tlp_avg; + + return 0; +} + +/* + * hps num_possible_cpus + */ +int hps_get_num_possible_cpus(unsigned int *little_cpu_ptr, unsigned int *big_cpu_ptr) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if ((little_cpu_ptr == NULL) || (big_cpu_ptr == NULL)) + return -1; + + *little_cpu_ptr = num_possible_little_cpus(); + *big_cpu_ptr = num_possible_big_cpus(); + + return 0; +} + +/* + * hps num_online_cpus + */ +int hps_get_num_online_cpus(unsigned int *little_cpu_ptr, unsigned int *big_cpu_ptr) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if ((little_cpu_ptr == NULL) || (big_cpu_ptr == NULL)) + return -1; + + *little_cpu_ptr = num_online_little_cpus(); + *big_cpu_ptr = num_online_big_cpus(); + + return 0; +} + +/* + * hps cpu num base + */ +int hps_get_enabled(unsigned int *enabled_ptr) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if (enabled_ptr == NULL) + return -1; + + *enabled_ptr = hps_ctxt.enabled; + + return 0; +} + +int hps_set_enabled(unsigned int enabled) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if (enabled > 1) + return -1; + + /* XXX: check mutex lock or not? use hps_ctxt.lock! */ + mutex_lock(&hps_ctxt.lock); + + if (!hps_ctxt.enabled && enabled) + hps_ctxt_reset_stas_nolock(); + hps_ctxt.enabled = enabled; + + mutex_unlock(&hps_ctxt.lock); + + return 0; +} + +/* + * hps get/set power mode + */ +int hps_get_powmode_status(unsigned int *pwrmode_ptr) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if (pwrmode_ptr == NULL) + return -1; + + *pwrmode_ptr = hps_ctxt.power_mode; + + return 0; +} + +int hps_set_powmode_status(unsigned int pwrmode) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + /* XXX: check mutex lock or not? use hps_ctxt.lock! */ + mutex_lock(&hps_ctxt.lock); + hps_ctxt_reset_stas_nolock(); + hps_ctxt.power_mode = pwrmode; + + mutex_unlock(&hps_ctxt.lock); + + return 0; +} + +/* + * hps get/set PPM_power mode + */ +int hps_get_ppm_powmode_status(unsigned int *pwrmode_ptr) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + if (pwrmode_ptr == NULL) + return -1; + + *pwrmode_ptr = hps_ctxt.ppm_power_mode; + + return 0; +} + +int hps_set_ppm_powmode_status(unsigned int pwrmode) +{ + if (hps_ctxt.init_state != INIT_STATE_DONE) + return -1; + + /* XXX: check mutex lock or not? use hps_ctxt.lock! */ + mutex_lock(&hps_ctxt.lock); + hps_ctxt_reset_stas_nolock(); + hps_ctxt.ppm_power_mode = pwrmode; + + mutex_unlock(&hps_ctxt.lock); + + return 0; +} diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_core.c b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_core.c new file mode 100644 index 0000000000000000000000000000000000000000..830972f992bb6c652944e05fa3db14193cdd2cdd --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_core.c @@ -0,0 +1,440 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/** +* @file mt_hotplug_strategy_core.c +* @brief hotplug strategy(hps) - core +*/ + +/*============================================================================*/ +/* Include files */ +/*============================================================================*/ +/* system includes */ +#include +#include /* MODULE_DESCRIPTION, MODULE_LICENSE */ +#include /* module_init, module_exit */ +#include /* cpu_up */ +#include /* kthread_create */ +#include /* wake_lock_init */ +#include /* BUG_ON */ + +/* local includes */ +#include "mt_hotplug_strategy_internal.h" +#include "mt_hotplug_strategy.h" + +/* forward references */ + +/*============================================================================*/ +/* Macro definition */ +/*============================================================================*/ +/* + * static + */ +#define STATIC +/* #define STATIC static */ +#define MS_TO_NS(x) (x * 1E6L) +/* + * config + */ + +/*============================================================================*/ +/* Local type definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local function declarition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local variable definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Global variable definition */ +/*============================================================================*/ +static unsigned long long hps_cancel_time; +static ktime_t ktime; +static DEFINE_SPINLOCK(idle_nb_lock); +/*============================================================================*/ +/* Local function definition */ +/*============================================================================*/ +/* + * hps timer callback + */ +static int _hps_timer_callback(unsigned long data) +{ +/* hps_warn("_hps_timer_callback\n");*/ + if (hps_ctxt.tsk_struct_ptr) + wake_up_process(hps_ctxt.tsk_struct_ptr); + return HRTIMER_NORESTART; +} + +static long int hps_get_current_time_ms(void) +{ + struct timeval t; + + do_gettimeofday(&t); + return ((t.tv_sec & 0xFFF) * 1000000 + t.tv_usec) / 1000; +} + +#if 1 +/*Add idle callback function*/ +static int cpu_hotplug_idle_notifier(struct notifier_block *nb, + unsigned long val, + void *data) +{ + if ((val == IDLE_END) && (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_TIMER)) { + spin_lock(&idle_nb_lock); + if ((hps_get_current_time_ms() - hps_cancel_time) >= HPS_TIMER_INTERVAL_MS) { + hps_task_wakeup_nolock(); + hps_cancel_time = hps_get_current_time_ms(); + /* hps_warn("[AT]CPU hotplug idle notifier[Timeout]!!!\n");*/ + } + spin_unlock(&idle_nb_lock); + } +/* hps_warn("[AT]CPU hotplug idle notifier!!![0x%x]\n",IDLE_END);*/ + return 0; +} + +static struct notifier_block cpu_hotplug_idle_nb = { + .notifier_call = cpu_hotplug_idle_notifier, +}; +#endif + +static void hps_get_sysinfo(void) +{ + unsigned int cpu; + char str1[64]; + char str2[64]; + int i, j; + char *str1_ptr = str1; + char *str2_ptr = str2; + /* + * calculate cpu loading + */ + hps_ctxt.cur_loads = 0; + str1_ptr = str1; + str2_ptr = str2; + + for_each_possible_cpu(cpu) { + per_cpu(hps_percpu_ctxt, cpu).load = hps_cpu_get_percpu_load(cpu); + hps_ctxt.cur_loads += per_cpu(hps_percpu_ctxt, cpu).load; + + if (hps_ctxt.cur_dump_enabled) { + if (cpu_online(cpu)) + i = sprintf(str1_ptr, "%4u", 1); + else + i = sprintf(str1_ptr, "%4u", 0); + str1_ptr += i; + j = sprintf(str2_ptr, "%4u", per_cpu(hps_percpu_ctxt, cpu).load); + str2_ptr += j; + } + } + + /*Get heavy task information */ + hps_ctxt.cur_nr_heavy_task = hps_cpu_get_nr_heavy_task(); + + /*Get sys TLP information */ + hps_cpu_get_tlp(&hps_ctxt.cur_tlp, &hps_ctxt.cur_iowait); + +#if 0 + ppm_lock(&ppm_main_info.lock); + ppm_hps_algo_data.ppm_cur_loads = hps_ctxt.cur_loads; + ppm_hps_algo_data.ppm_cur_nr_heavy_task = hps_ctxt.cur_nr_heavy_task; + ppm_hps_algo_data.ppm_cur_tlp = hps_ctxt.cur_tlp; + ppm_unlock(&ppm_main_info.lock); +#endif +} + +/* + * hps task main loop + */ +static int _hps_task_main(void *data) +{ + int cnt = 0; + void (*algo_func_ptr)(void); + + hps_ctxt_print_basic(1); +#if 0 + if (hps_ctxt.is_hmp) + algo_func_ptr = hps_algo_hmp; + else if (hps_ctxt.is_amp) + algo_func_ptr = hps_algo_amp; + else + algo_func_ptr = hps_algo_smp; +#else + algo_func_ptr = hps_algo_amp; +#endif + while (1) { + /* TODO: showld we do dvfs? */ + /* struct cpufreq_policy *policy; */ + /* policy = cpufreq_cpu_get(0); */ + /* dbs_freq_increase(policy, policy->max); */ + /* cpufreq_cpu_put(policy); */ + + /*Add for update time value of deferrable timer*/ + spin_lock(&idle_nb_lock); + hps_cancel_time = hps_get_current_time_ms(); + spin_unlock(&idle_nb_lock); + +#ifdef CONFIG_CPU_ISOLATION + if (hps_ctxt.wake_up_by_fasthotplug) { + + mutex_lock(&hps_ctxt.lock); + struct cpumask cpu_down_cpumask; + + cpumask_setall(&cpu_down_cpumask); + cpumask_clear_cpu(hps_ctxt.root_cpu, &cpu_down_cpumask); + cpu_down_by_mask(&cpu_down_cpumask); + + hps_ctxt.wake_up_by_fasthotplug = 0; + mutex_unlock(&hps_ctxt.lock); + goto HPS_WAIT_EVENT; + } +#endif + + /*Get sys status */ + hps_get_sysinfo(); + + mt_ppm_hica_update_algo_data(hps_ctxt.cur_loads, hps_ctxt.cur_nr_heavy_task, + hps_ctxt.cur_tlp); + + /*Execute PPM main function */ + mt_ppm_main(); + + + /*execute hotplug algorithm */ + (*algo_func_ptr) (); + +#ifdef CONFIG_CPU_ISOLATION +HPS_WAIT_EVENT: +#endif + if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_WAIT_QUEUE) { + wait_event_timeout(hps_ctxt.wait_queue, + atomic_read(&hps_ctxt.is_ondemand) != 0, + msecs_to_jiffies(HPS_TIMER_INTERVAL_MS)); + } else if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_TIMER) { + hps_cancel_time = hps_get_current_time_ms(); + if (atomic_read(&hps_ctxt.is_ondemand) == 0) { + mod_timer(&hps_ctxt.tmr_list, + (jiffies + msecs_to_jiffies(HPS_TIMER_INTERVAL_MS))); + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + } else if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_HR_TIMER) { + hrtimer_cancel(&hps_ctxt.hr_timer); + hrtimer_start(&hps_ctxt.hr_timer, ktime, HRTIMER_MODE_REL); + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + + if (kthread_should_stop()) + break; + + } /* while(1) */ + + hps_warn("leave _hps_task_main, cnt:%08d\n", cnt++); + return 0; +} + +/*============================================================================*/ +/* Gobal function definition */ +/*============================================================================*/ +/* + * hps task control interface + */ +int hps_task_start(void) +{ + if (hps_ctxt.tsk_struct_ptr == NULL) { + /*struct sched_param param = {.sched_priority = HPS_TASK_PRIORITY };*/ + hps_ctxt.tsk_struct_ptr = kthread_create(_hps_task_main, NULL, "hps_main"); + if (IS_ERR(hps_ctxt.tsk_struct_ptr)) + return PTR_ERR(hps_ctxt.tsk_struct_ptr); + + /* sched_setscheduler_nocheck(hps_ctxt.tsk_struct_ptr, SCHED_FIFO, ¶m);*/ + set_user_nice(hps_ctxt.tsk_struct_ptr, HPS_TASK_NORMAL_PRIORITY); + get_task_struct(hps_ctxt.tsk_struct_ptr); + wake_up_process(hps_ctxt.tsk_struct_ptr); + hps_warn("hps_task_start success, ptr: %p, pid: %d\n", hps_ctxt.tsk_struct_ptr, + hps_ctxt.tsk_struct_ptr->pid); + } else { + hps_warn("hps task already exist, ptr: %p, pid: %d\n", hps_ctxt.tsk_struct_ptr, + hps_ctxt.tsk_struct_ptr->pid); + } + return 0; +} + +void hps_task_stop(void) +{ + if (hps_ctxt.tsk_struct_ptr) { + kthread_stop(hps_ctxt.tsk_struct_ptr); + put_task_struct(hps_ctxt.tsk_struct_ptr); + hps_ctxt.tsk_struct_ptr = NULL; + } +} + +void hps_task_wakeup_nolock(void) +{ + if (hps_ctxt.tsk_struct_ptr) { + atomic_set(&hps_ctxt.is_ondemand, 1); + if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_WAIT_QUEUE) + wake_up(&hps_ctxt.wait_queue); + else if ((hps_ctxt.periodical_by == HPS_PERIODICAL_BY_TIMER) + || (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_HR_TIMER)) + wake_up_process(hps_ctxt.tsk_struct_ptr); + } +} + +void hps_task_wakeup(void) +{ + mutex_lock(&hps_ctxt.lock); + + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); +} + +int little_min = -1; +int little_max = -1; +int big_min = -1; +int big_max = -1; + +static void ppm_limit_callback(struct ppm_client_req req) +{ + struct ppm_client_req *p = (struct ppm_client_req *)&req; + void (*algo_func_ptr)(void); + + if (!p->cpu_limit[0].has_advise_core) { + little_min = p->cpu_limit[0].min_cpu_core; + little_max = p->cpu_limit[0].max_cpu_core; + } else { + little_min = little_max = p->cpu_limit[0].advise_cpu_core; + } + if (!p->cpu_limit[1].has_advise_core) { + big_min = p->cpu_limit[1].min_cpu_core; + big_max = p->cpu_limit[1].max_cpu_core; + } else { + big_min = big_max = p->cpu_limit[1].advise_cpu_core; + } + hps_set_PPM_request(little_min, little_max, big_min, big_max); +#if 0 + if (hps_ctxt.is_hmp) + algo_func_ptr = hps_algo_hmp; + else if (hps_ctxt.is_amp) + algo_func_ptr = hps_algo_amp; + else + algo_func_ptr = hps_algo_smp; +#else + algo_func_ptr = hps_algo_amp; +#endif + /*execute hotplug algorithm */ + (*algo_func_ptr) (); +} + +/* + * init + */ +int hps_core_init(void) +{ + int r = 0; + + hps_warn("hps_core_init\n"); + if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_TIMER) { + idle_notifier_register(&cpu_hotplug_idle_nb); + hps_warn("hps_core_init: register idle nb done\n"); + /*init timer */ + /*init_timer(&hps_ctxt.tmr_list);*/ + init_timer_deferrable(&hps_ctxt.tmr_list); + /*init_timer_deferrable(&hps_ctxt.tmr_list); */ + hps_ctxt.tmr_list.function = (void *)&_hps_timer_callback; + hps_ctxt.tmr_list.data = (unsigned long)&hps_ctxt; + hps_ctxt.tmr_list.expires = jiffies + msecs_to_jiffies(HPS_TIMER_INTERVAL_MS); + add_timer(&hps_ctxt.tmr_list); + } else if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_HR_TIMER) { + ktime = ktime_set(0, MS_TO_NS(HPS_TIMER_INTERVAL_MS)); + /*init Hrtimer */ + hrtimer_init(&hps_ctxt.hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hps_ctxt.hr_timer.function = (void *)&_hps_timer_callback; + hrtimer_start(&hps_ctxt.hr_timer, ktime, HRTIMER_MODE_REL); + + } + /* init and start task */ + r = hps_task_start(); + if (r) { + hps_error("hps_task_start fail(%d)\n", r); + return r; + } + + mt_ppm_register_client(PPM_CLIENT_HOTPLUG, &ppm_limit_callback); /* register PPM callback */ + return r; +} + +/* + * deinit + */ +int hps_core_deinit(void) +{ + int r = 0; + + hps_warn("hps_core_deinit\n"); + if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_TIMER) { + /*deinit timer */ + del_timer_sync(&hps_ctxt.tmr_list); + } else if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_HR_TIMER) { + /*deinit timer */ + r = hrtimer_cancel(&hps_ctxt.hr_timer); + if (r) + hps_error("hps hr timer delete error!\n"); + } + + hps_task_stop(); + return r; +} + +int hps_del_timer(void) +{ +#if 1 + if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_TIMER) { + /*deinit timer */ + /*del_timer_sync(&hps_ctxt.tmr_list);*/ + } else if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_HR_TIMER) { + if (!hps_cancel_time) + hps_cancel_time = hps_get_current_time_ms(); + hrtimer_cancel(&hps_ctxt.hr_timer); + } +#endif + return 0; +} + +int hps_restart_timer(void) +{ + if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_TIMER) { + unsigned long long cancel_time; + + spin_lock(&idle_nb_lock); + cancel_time = hps_cancel_time; + spin_unlock(&idle_nb_lock); + if ((hps_get_current_time_ms() - cancel_time) >= HPS_TIMER_INTERVAL_MS) + hps_task_wakeup_nolock(); + } else if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_HR_TIMER) { + hrtimer_start(&hps_ctxt.hr_timer, ktime, HRTIMER_MODE_REL); + if ((hps_get_current_time_ms() - hps_cancel_time) >= HPS_TIMER_INTERVAL_MS) { + hrtimer_start(&hps_ctxt.hr_timer, ktime, HRTIMER_MODE_REL); + hps_task_wakeup_nolock(); + hps_cancel_time = hps_get_current_time_ms(); + } + } + return 0; +} + + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_cpu.c b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..af7b95b16809c73178b5eb5f86f21883b07161b9 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_cpu.c @@ -0,0 +1,249 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/** +* @file mt_hotplug_strategy_cpu.c +* @brief hotplug strategy(hps) - cpu +*/ + +/*============================================================================*/ +/* Include files */ +/*============================================================================*/ +/* system includes */ +#include /* printk */ +#include /* MODULE_DESCRIPTION, MODULE_LICENSE */ +#include /* module_init, module_exit */ +#include /* sched_get_percpu_load, sched_get_nr_heavy_task */ + +/* local includes */ +#include "mt_hotplug_strategy_internal.h" + +/*============================================================================*/ +/* Macro definition */ +/*============================================================================*/ +/* + * static + */ +#define STATIC +/* #define STATIC static */ + +/* + * config + */ + +/*============================================================================*/ +/* Local type definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local function declarition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local variable definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Global variable definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local function definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Gobal function definition */ +/*============================================================================*/ +/* + * hps cpu interface - cpumask + */ +int hps_cpu_is_cpu_big(int cpu) +{ + if (!cpumask_empty(&hps_ctxt.big_cpumask)) { + if (cpumask_test_cpu(cpu, &hps_ctxt.big_cpumask)) + return 1; + else + return 0; + } else { + return 0; + } +} + +int hps_cpu_is_cpu_little(int cpu) +{ + if (!cpumask_empty(&hps_ctxt.little_cpumask)) { + if (cpumask_test_cpu(cpu, &hps_ctxt.little_cpumask)) + return 1; + else + return 0; + } else { + return 0; + } +} + +unsigned int num_online_little_cpus(void) +{ + struct cpumask dst_cpumask; + + cpumask_and(&dst_cpumask, &hps_ctxt.little_cpumask, cpu_online_mask); + return cpumask_weight(&dst_cpumask); +} + +unsigned int num_online_big_cpus(void) +{ + struct cpumask dst_cpumask; + + cpumask_and(&dst_cpumask, &hps_ctxt.big_cpumask, cpu_online_mask); + return cpumask_weight(&dst_cpumask); +} + +/* int hps_cpu_get_arch_type(void) */ +/* { */ +/* if(!cluster_numbers) */ +/* return ARCH_TYPE_NO_CLUSTER; */ +/* if(cpumask_empty(&hps_ctxt.little_cpumask) && cpumask_empty(&hps_ctxt.big_cpumask) ) */ +/* return ARCH_TYPE_NOT_READY; */ +/* if(!cpumask_empty(&hps_ctxt.little_cpumask) && !cpumask_empty(&hps_ctxt.big_cpumask)) */ +/* return ARCH_TYPE_big_LITTLE; */ +/* if(!cpumask_empty(&hps_ctxt.little_cpumask) && cpumask_empty(&hps_ctxt.big_cpumask)) */ +/* return ARCH_TYPE_LITTLE_LITTLE; */ +/* return ARCH_TYPE_NOT_READY; */ +/* } */ + +/* + * hps cpu interface - scheduler + */ +unsigned int hps_cpu_get_percpu_load(int cpu) +{ +#ifdef CONFIG_MTK_SCHED_RQAVG_US + return sched_get_percpu_load(cpu, 1, 0); +#else + return 100; +#endif +} + +unsigned int hps_cpu_get_nr_heavy_task(void) +{ +#ifdef CONFIG_MTK_SCHED_RQAVG_US + return sched_get_nr_heavy_task(); +#else + return 0; +#endif +} + +void hps_cpu_get_tlp(unsigned int *avg, unsigned int *iowait_avg) +{ +#ifdef CONFIG_MTK_SCHED_RQAVG_KS + sched_get_nr_running_avg((int *)avg, (int *)iowait_avg); +#else + *avg = 0; + *iowait_avg = 0; +#endif +} + + +/* + * init + */ +int hps_cpu_init(void) +{ + int r = 0; + char str1[32]; + + hps_warn("hps_cpu_init\n"); + + /* init cpu arch in hps_ctxt */ + /* init cpumask */ + cpumask_clear(&hps_ctxt.little_cpumask); + cpumask_clear(&hps_ctxt.big_cpumask); + + /* a. call api */ + arch_get_cluster_cpus(&hps_ctxt.little_cpumask, 0); + arch_get_cluster_cpus(&hps_ctxt.big_cpumask, 1); + /* b. fix 2L2b */ + /* cpulist_parse("0-1", &hps_ctxt.little_cpumask); */ + /* cpulist_parse("2-3", &hps_ctxt.big_cpumask); */ + /* c. 4L */ + /* cpulist_parse("0-3", &hps_ctxt.little_cpumask); */ + + cpulist_parse("0-3", &hps_ctxt.little_cpumask); + cpulist_parse("4-7", &hps_ctxt.big_cpumask); + if (cpumask_weight(&hps_ctxt.little_cpumask) == 0) { + cpumask_copy(&hps_ctxt.little_cpumask, &hps_ctxt.big_cpumask); + cpumask_clear(&hps_ctxt.big_cpumask); + } + /* for(i=0;i<4;i++) */ + /* cpumask_set_cpu(i,&hps_ctxt.little_cpumask); */ + /* for(i=4;i<8;i++); */ + /* cpumask_set_cpu(i,&hps_ctxt.big_cpumask); */ + cpulist_scnprintf(str1, sizeof(str1), &hps_ctxt.little_cpumask); + hps_warn("hps_ctxt.little_cpumask: %s\n", str1); + cpulist_scnprintf(str1, sizeof(str1), &hps_ctxt.big_cpumask); + hps_warn("hps_ctxt.big_cpumask: %s\n", str1); + + /* verify arch is hmp or amp or smp */ + if (!cpumask_empty(&hps_ctxt.little_cpumask) && !cpumask_empty(&hps_ctxt.big_cpumask)) { + unsigned int cpu; + + hps_ctxt.is_amp = 1; + + for_each_cpu((cpu), &hps_ctxt.little_cpumask) { + if (cpu < hps_ctxt.little_cpu_id_min) + hps_ctxt.little_cpu_id_min = cpu; + if (cpu > hps_ctxt.little_cpu_id_max) + hps_ctxt.little_cpu_id_max = cpu; + } + for_each_cpu((cpu), &hps_ctxt.big_cpumask) { + if (cpu < hps_ctxt.big_cpu_id_min) + hps_ctxt.big_cpu_id_min = cpu; + if (cpu > hps_ctxt.big_cpu_id_max) + hps_ctxt.big_cpu_id_max = cpu; + } + } else { + hps_ctxt.is_hmp = 0; + hps_ctxt.is_amp = 0; + hps_ctxt.little_cpu_id_min = 0; + hps_ctxt.little_cpu_id_max = num_possible_little_cpus() - 1; + } + + /* init bound in hps_ctxt */ + hps_ctxt.little_num_base_perf_serv = 1; + hps_ctxt.little_num_limit_thermal = cpumask_weight(&hps_ctxt.little_cpumask); + hps_ctxt.little_num_limit_low_battery = cpumask_weight(&hps_ctxt.little_cpumask); + hps_ctxt.little_num_limit_ultra_power_saving = cpumask_weight(&hps_ctxt.little_cpumask); + hps_ctxt.little_num_limit_power_serv = cpumask_weight(&hps_ctxt.little_cpumask); + hps_ctxt.big_num_base_perf_serv = 0; + hps_ctxt.big_num_limit_thermal = cpumask_weight(&hps_ctxt.big_cpumask); + hps_ctxt.big_num_limit_low_battery = cpumask_weight(&hps_ctxt.big_cpumask); + hps_ctxt.big_num_limit_ultra_power_saving = cpumask_weight(&hps_ctxt.big_cpumask); + hps_ctxt.big_num_limit_power_serv = cpumask_weight(&hps_ctxt.big_cpumask); + + hps_warn + ("%s: little_cpu_id_min: %u, little_cpu_id_max: %u, big_cpu_id_min: %u, big_cpu_id_max: %u\n", + __func__, hps_ctxt.little_cpu_id_min, hps_ctxt.little_cpu_id_max, + hps_ctxt.big_cpu_id_min, hps_ctxt.big_cpu_id_max); + + return r; +} + +/* + * deinit + */ +int hps_cpu_deinit(void) +{ + int r = 0; + + hps_warn("hps_cpu_deinit\n"); + + return r; +} diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_internal.h b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..99201d7edf2226cf99d7262910eb369d07e1dd64 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_internal.h @@ -0,0 +1,335 @@ +/** +* @file mt_hotplug_strategy_internal.h +* @brief hotplug strategy(hps) - internal header file +*/ + +#ifndef __MT_HOTPLUG_STRATEGY_INTERNAL_H__ +#define __MT_HOTPLUG_STRATEGY_INTERNAL_H__ + + +/*=============================================================*/ +/* Include files */ +/*=============================================================*/ +/* system includes */ +#include +#include /* __raw_readl */ +#include /* struct platform_driver */ +#include /* struct task_struct */ +#include /* struct timer_list */ +#include /* MAX_RT_PRIO */ + +/* project includes */ + +/* local includes */ +#include +/* forward references */ + +/*=============================================================*/ +/* Macro definition */ +/*=============================================================*/ +/* + * CONFIG - compile time + */ +#define HPS_TASK_RT_PRIORITY (MAX_RT_PRIO - 3) +#define HPS_TASK_NORMAL_PRIORITY (MIN_NICE) +#define HPS_TIMER_INTERVAL_MS (40) + +#define HPS_PERIODICAL_BY_WAIT_QUEUE (1) +#define HPS_PERIODICAL_BY_TIMER (2) +#define HPS_PERIODICAL_BY_HR_TIMER (3) + +#define MAX_CPU_UP_TIMES (10) +#define MAX_CPU_DOWN_TIMES (100) +#define MAX_TLP_TIMES (10) +/* cpu capability of big / little = 1.7, aka 170, 170 - 100 = 70 */ +#define CPU_DMIPS_BIG_LITTLE_DIFF (70) + +/* + * CONFIG - runtime + */ +#define DEF_CPU_UP_THRESHOLD (95) +#define DEF_CPU_UP_TIMES (3) +#define DEF_CPU_DOWN_THRESHOLD (85) +#define DEF_CPU_DOWN_TIMES (1) +#define DEF_TLP_TIMES (1) + +#define EN_CPU_INPUT_BOOST (1) +#define DEF_CPU_INPUT_BOOST_CPU_NUM (2) + +#define EN_CPU_RUSH_BOOST (1) +#define DEF_CPU_RUSH_BOOST_THRESHOLD (98) +#define DEF_CPU_RUSH_BOOST_TIMES (1) + +#define EN_HPS_LOG (1) +#define EN_ISR_LOG (0) + +/* + * LOG + */ +#define hps_emerg(fmt, args...) pr_emerg("[HPS] " fmt, ##args) +#define hps_alert(fmt, args...) pr_alert("[HPS] " fmt, ##args) +#define hps_crit(fmt, args...) pr_crit("[HPS] " fmt, ##args) +#define hps_error(fmt, args...) pr_err("[HPS] " fmt, ##args) +#define hps_warn(fmt, args...) pr_warn("[HPS] " fmt, ##args) +/* #define hps_warn(fmt, args...) printk(KERN_DEBUG "[HPS] " fmt, ##args) */ +/* #define hps_warn(fmt, args...) pr_emerg("[HPS] " fmt, ##args) */ +#define hps_notice(fmt, args...) pr_notice("[HPS] " fmt, ##args) +#define hps_info(fmt, args...) pr_info("[HPS] " fmt, ##args) +/* #define hps_debug(fmt, args...) pr_debug("[HPS] " fmt, ##args) */ +#define hps_debug(fmt, args...) pr_debug("[HPS] " fmt, ##args) +/* #define hps_debug(fmt, args...) pr_emerg("[HPS] " fmt, ##args) */ + +#if EN_ISR_LOG +#define hps_isr_info(fmt, args...) hps_notice(fmt, ##args) +#else +#define hps_isr_info(fmt, args...) hps_debug(fmt, ##args) +#endif + +/* + * REG ACCESS + */ +#define hps_read(addr) __raw_readl(IOMEM(addr)) +#define hps_write(addr, val) mt_reg_sync_writel(val, addr) + +/* +* hps_cpu_get_arch_type() return value */ +/* #define ARCH_TYPE_NOT_READY -1 */ +/* #define ARCH_TYPE_NO_CLUSTER 0 */ +/* #define ARCH_TYPE_big_LITTLE 1 */ +/* #define ARCH_TYPE_LITTLE_LITTLE 2 */ + +/* + * debug + */ +/* #define STEP_BY_STEP_DEBUG + hps_debug("@@@### file:%s, func:%s, line:%d ###@@@\n", __FILE__, __func__, __LINE__) */ + +/*=============================================================*/ +/* Type definition */ +/*=============================================================*/ +typedef enum { + INIT_STATE_NOT_READY = 0, + INIT_STATE_DONE +} hps_init_state_e; + +typedef enum { + STATE_LATE_RESUME = 0, + STATE_EARLY_SUSPEND, + STATE_SUSPEND, + STATE_COUNT +} hps_ctxt_state_e; + + +/* TODO: verify do you need action? no use now */ +typedef enum { + ACTION_NONE = 0, + ACTION_BASE_LITTLE, /* bit 1, 0x0002 */ + ACTION_BASE_BIG, /* bit 2, 0x0004 */ + ACTION_LIMIT_LITTLE, /* bit 3, 0x0008 */ + ACTION_LIMIT_BIG, /* bit 4, 0x0010 */ + ACTION_RUSH_BOOST_LITTLE, /* bit 5, 0x0020 */ + ACTION_RUSH_BOOST_BIG, /* bit 6, 0x0040 */ + ACTION_UP_LITTLE, /* bit 7, 0x0080 */ + ACTION_UP_BIG, /* bit 8, 0x0100 */ + ACTION_DOWN_LITTLE, /* bit 9, 0x0200 */ + ACTION_DOWN_BIG, /* bit 10, 0x0400 */ + ACTION_BIG_TO_LITTLE, /* bit 11, 0x0800 */ + ACTION_INPUT, /* bit 12 */ + ACTION_ROOT_2_LITTLE, /*bit 13, 0x2000 */ + ACTION_ROOT_2_BIG, /*bit 14, 0x4000 */ + ACTION_COUNT +} hps_ctxt_action_e; +typedef struct hps_func_data { + int cores; + unsigned int target_root_cpu; + unsigned int action_LL; + unsigned int action_L; + unsigned int target_LL; + unsigned int target_L; + unsigned int limit_LL; + unsigned int limit_L; + unsigned int base_LL; + unsigned int base_L; +} hps_func_data_t; +typedef struct hps_ctxt_struct { + /* state */ + unsigned int init_state; + unsigned int state; + + /* enabled */ + unsigned int enabled; + unsigned int early_suspend_enabled; + /* default 1, disable all big cores if is_hmp after early suspend stage (aka screen off) */ + unsigned int suspend_enabled; /* default 1, disable hotplug strategy in suspend flow */ + unsigned int cur_dump_enabled; + unsigned int stats_dump_enabled; + unsigned int power_mode; + unsigned int ppm_power_mode; + + + /* core */ + struct mutex lock; /* Synchronizes accesses */ + struct task_struct *tsk_struct_ptr; + wait_queue_head_t wait_queue; + struct timer_list tmr_list; + unsigned int periodical_by; + struct hrtimer hr_timer; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend es_handler; +#endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */ + struct platform_driver pdrv; + + /* backup */ + unsigned int enabled_backup; + unsigned int rush_boost_enabled_backup; + + /* cpu arch */ + unsigned int is_hmp; + unsigned int is_amp; + struct cpumask little_cpumask; + struct cpumask big_cpumask; + unsigned int little_cpu_id_min; + unsigned int little_cpu_id_max; + unsigned int big_cpu_id_min; + unsigned int big_cpu_id_max; + + /* algo config */ + unsigned int up_threshold; + unsigned int up_times; + unsigned int down_threshold; + unsigned int down_times; + unsigned int input_boost_enabled; + unsigned int input_boost_cpu_num; + unsigned int rush_boost_enabled; + unsigned int rush_boost_threshold; + unsigned int rush_boost_times; + unsigned int tlp_times; + + /* algo bound */ + unsigned int little_num_base_perf_serv; + unsigned int little_num_limit_thermal; + unsigned int little_num_limit_low_battery; + unsigned int little_num_limit_ultra_power_saving; + unsigned int little_num_limit_power_serv; + unsigned int big_num_base_perf_serv; + unsigned int big_num_limit_thermal; + unsigned int big_num_limit_low_battery; + unsigned int big_num_limit_ultra_power_saving; + unsigned int big_num_limit_power_serv; + + /* algo statistics */ + unsigned int cur_loads; + unsigned int cur_tlp; + unsigned int cur_iowait; + unsigned int cur_nr_heavy_task; + unsigned int up_loads_sum; + unsigned int up_loads_count; + unsigned int up_loads_history[MAX_CPU_UP_TIMES]; + unsigned int up_loads_history_index; + unsigned int down_loads_sum; + unsigned int down_loads_count; + unsigned int down_loads_history[MAX_CPU_DOWN_TIMES]; + unsigned int down_loads_history_index; + unsigned int rush_count; + unsigned int tlp_sum; + unsigned int tlp_count; + unsigned int tlp_history[MAX_TLP_TIMES]; + unsigned int tlp_history_index; + unsigned int tlp_avg; + + /* For fast hotplug integration */ + unsigned int wake_up_by_fasthotplug; + unsigned int root_cpu; + + /* algo action */ + unsigned long action; + atomic_t is_ondemand; + + /* misc */ + unsigned int test0; + unsigned int test1; +} hps_ctxt_t; + +typedef struct hps_cpu_ctxt_struct { + unsigned int load; +} hps_cpu_ctxt_t; + +/*=============================================================*/ +/* Global variable declaration */ +/*=============================================================*/ +extern hps_ctxt_t hps_ctxt; +DECLARE_PER_CPU(hps_cpu_ctxt_t, hps_percpu_ctxt); +/* forward references */ +extern struct cpumask cpu_domain_big_mask; /* definition in kernel-3.10/arch/arm/kernel/topology.c */ +extern struct cpumask cpu_domain_little_mask; /* definition in kernel-3.10/arch/arm/kernel/topology.c */ + +extern void sched_get_nr_running_avg(int *avg, int *iowait_avg); + /* definition in mediatek/kernel/kernel/sched/rq_stats.c */ + +/*=============================================================*/ +/* Global function declaration */ +/*=============================================================*/ +/* + * mt_hotplug_strategy_main.c + */ +extern void hps_ctxt_reset_stas_nolock(void); +extern void hps_ctxt_reset_stas(void); +extern void hps_ctxt_print_basic(int toUart); +extern void hps_ctxt_print_algo_config(int toUart); +extern void hps_ctxt_print_algo_bound(int toUart); +extern void hps_ctxt_print_algo_stats_cur(int toUart); +extern void hps_ctxt_print_algo_stats_up(int toUart); +extern void hps_ctxt_print_algo_stats_down(int toUart); +extern void hps_ctxt_print_algo_stats_tlp(int toUart); +extern int hps_restart_timer(void); +extern int hps_del_timer(void); +extern int hps_core_deinit(void); +/* + * mt_hotplug_strategy_core.c + */ +extern int hps_core_init(void); +extern int hps_core_deinit(void); +extern int hps_task_start(void); +extern void hps_task_stop(void); +extern void hps_task_wakeup_nolock(void); +extern void hps_task_wakeup(void); + +/* + * mt_hotplug_strategy_algo.c + */ +extern void hps_algo_hmp(void); +extern void hps_algo_smp(void); +extern void hps_algo_amp(void); +/* + * mt_hotplug_strategy_procfs.c + */ +extern int hps_procfs_init(void); + +/* + * mt_hotplug_strategy_cpu.c + */ +#define num_possible_little_cpus() cpumask_weight(&hps_ctxt.little_cpumask) +#define num_possible_big_cpus() cpumask_weight(&hps_ctxt.big_cpumask) + +extern int hps_cpu_init(void); +extern int hps_cpu_deinit(void); +/* extern int hps_cpu_get_arch_type(void); */ +extern unsigned int num_online_little_cpus(void); +extern unsigned int num_online_big_cpus(void); +extern int hps_cpu_is_cpu_big(int cpu); +extern int hps_cpu_is_cpu_little(int cpu); +extern unsigned int hps_cpu_get_percpu_load(int cpu); +extern unsigned int hps_cpu_get_nr_heavy_task(void); +extern void hps_cpu_get_tlp(unsigned int *avg, unsigned int *iowait_avg); +int get_suspend_status(void); +/*=============================================================*/ +/* End */ +/*=============================================================*/ +extern struct cpumask cpu_domain_big_mask; +extern struct cpumask cpu_domain_little_mask; +extern void sched_get_nr_running_avg(int *avg, int *iowait_avg); + +extern unsigned int sched_get_percpu_load(int cpu, bool reset, bool use_maxfreq); +extern unsigned int sched_get_nr_heavy_task(void); + +#endif /* __MT_HOTPLUG_STRATEGY_INTERNAL_H__ */ diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_main.c b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_main.c new file mode 100644 index 0000000000000000000000000000000000000000..0bcbfdaeabb8b6b55c984cdcdf4bb8dffb0f89bb --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_main.c @@ -0,0 +1,624 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/** +* @file mt_hotplug_strategy_main.c +* @brief hotplug strategy(hps) - main +*/ + +/*============================================================================*/ +/* Include files */ +/*============================================================================*/ +/* system includes */ +#include /* printk */ +#include /* MODULE_DESCRIPTION, MODULE_LICENSE */ +#include /* module_init, module_exit */ +#include /* cpu_up */ +#include /* platform_driver_register */ +#include /* wake_lock_init */ +#include +/* local includes */ +#include "mt_hotplug_strategy_internal.h" + +/* forward references */ + +/*============================================================================*/ +/* Macro definition */ +/*============================================================================*/ +/* + * static + */ +#define STATIC +/* #define STATIC static */ + +/* + * config + */ +#define HPS_TASK_PRIORITY (MAX_RT_PRIO - 3) +static int is_suspend; + +/*============================================================================*/ +/* Local type definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Local function declarition */ +/*============================================================================*/ +static int hps_probe(struct platform_device *pdev); +static int hps_suspend(struct device *dev); +static int hps_resume(struct device *dev); +static int hps_freeze(struct device *dev); +static int hps_restore(struct device *dev); + +/*============================================================================*/ +/* Local variable definition */ +/*============================================================================*/ +/* XXX: may be moved into device tree in the future */ +struct platform_device hotplug_strategy_pdev = { + .name = "hps", + .id = -1, +}; + +const struct dev_pm_ops hps_dev_pm_ops = { + .suspend = hps_suspend, + .resume = hps_resume, + .freeze = hps_freeze, + .restore = hps_restore, + .thaw = hps_restore, +}; + +#ifndef CONFIG_MTK_FPGA +int get_suspend_status(void) +{ + return is_suspend; +} +static int hps_pm_event(struct notifier_block *notifier, unsigned long pm_event, void *unused) +{ + switch (pm_event) { + case PM_SUSPEND_PREPARE: + is_suspend = 1; + break; + case PM_POST_SUSPEND: + is_suspend = 0; + break; + default: + is_suspend = 0; + break; + } + return NOTIFY_OK; +} + +static struct notifier_block hps_pm_notifier_func = { + .notifier_call = hps_pm_event, + .priority = 0, +}; +#endif /* CONFIG_MTK_FPGA */ + +/*============================================================================*/ +/* Global variable definition */ +/*============================================================================*/ +hps_ctxt_t hps_ctxt = { + /* state */ + .init_state = INIT_STATE_NOT_READY, + .state = STATE_LATE_RESUME, + + /* enabled */ + .enabled = 1, + .suspend_enabled = 1, + .cur_dump_enabled = 0, + .stats_dump_enabled = 0, + + /* core */ + .lock = __MUTEX_INITIALIZER(hps_ctxt.lock), /* Synchronizes accesses to loads statistics */ + .tsk_struct_ptr = NULL, + .wait_queue = __WAIT_QUEUE_HEAD_INITIALIZER(hps_ctxt.wait_queue), + /*.periodical_by = HPS_PERIODICAL_BY_WAIT_QUEUE, */ + /*.periodical_by = HPS_PERIODICAL_BY_HR_TIMER,*/ + .periodical_by = HPS_PERIODICAL_BY_TIMER, + .pdrv = { + .remove = NULL, + .shutdown = NULL, + .probe = hps_probe, + .driver = { + .name = "hps", + .pm = &hps_dev_pm_ops, + }, + }, + + /* cpu arch */ + /* unsigned int is_hmp; */ + /* struct cpumask little_cpumask; */ + /* struct cpumask big_cpumask; */ + .little_cpu_id_min = 0, + .little_cpu_id_max = 3, + .big_cpu_id_min = 4, + .big_cpu_id_max = 7, + + /* algo config */ + .up_threshold = DEF_CPU_UP_THRESHOLD, + .up_times = DEF_CPU_UP_TIMES, + .down_threshold = DEF_CPU_DOWN_THRESHOLD, + .down_times = DEF_CPU_DOWN_TIMES, + .input_boost_enabled = EN_CPU_INPUT_BOOST, + .input_boost_cpu_num = DEF_CPU_INPUT_BOOST_CPU_NUM, + .rush_boost_enabled = EN_CPU_RUSH_BOOST, + .rush_boost_threshold = DEF_CPU_RUSH_BOOST_THRESHOLD, + .rush_boost_times = DEF_CPU_RUSH_BOOST_TIMES, + .tlp_times = DEF_TLP_TIMES, + + /* algo bound */ + /* .little_num_base_perf_serv = 1, */ + /* .little_num_limit_thermal = NR_CPUS, */ + /* .little_num_limit_low_battery = NR_CPUS, */ + /* .little_num_limit_ultra_power_saving = NR_CPUS, */ + /* .little_num_limit_power_serv = NR_CPUS, */ + /* .big_num_base_perf_serv = 1, */ + /* .big_num_limit_thermal = NR_CPUS, */ + /* .big_num_limit_low_battery = NR_CPUS, */ + /* .big_num_limit_ultra_power_saving = NR_CPUS, */ + /* .big_num_limit_power_serv = NR_CPUS, */ + + /* algo statistics */ + .up_loads_sum = 0, + .up_loads_count = 0, + .up_loads_history = {0}, + .up_loads_history_index = 0, + .down_loads_sum = 0, + .down_loads_count = 0, + .down_loads_history = {0}, + .down_loads_history_index = 0, + .rush_count = 0, + .tlp_sum = 0, + .tlp_count = 0, + .tlp_history = {0}, + .tlp_history_index = 0, + + /* for fast hotplug setting */ + .wake_up_by_fasthotplug = 0, + .root_cpu = 0, + /* algo action */ + .action = ACTION_NONE, + .is_ondemand = ATOMIC_INIT(0), + + .test0 = 0, + .test1 = 0, +}; + +DEFINE_PER_CPU(hps_cpu_ctxt_t, hps_percpu_ctxt); + +/*============================================================================*/ +/* Local function definition */ +/*============================================================================*/ + +/*============================================================================*/ +/* Gobal function definition */ +/*============================================================================*/ +/*********************************************************** +* hps_ctxt +***********************************************************/ +/* + * hps hps_ctxt_t control interface + */ +void hps_ctxt_reset_stas_nolock(void) +{ + hps_ctxt.up_loads_sum = 0; + hps_ctxt.up_loads_count = 0; + hps_ctxt.up_loads_history_index = 0; + hps_ctxt.up_loads_history[hps_ctxt.up_times - 1] = 0; + /* memset(hps_ctxt.up_loads_history, 0, sizeof(hps_ctxt.up_loads_history)); */ + + hps_ctxt.down_loads_sum = 0; + hps_ctxt.down_loads_count = 0; + hps_ctxt.down_loads_history_index = 0; + hps_ctxt.down_loads_history[hps_ctxt.down_times - 1] = 0; + /* memset(hps_ctxt.down_loads_history, 0, sizeof(hps_ctxt.down_loads_history)); */ + + hps_ctxt.rush_count = 0; + hps_ctxt.tlp_sum = 0; + hps_ctxt.tlp_count = 0; + hps_ctxt.tlp_history_index = 0; + hps_ctxt.tlp_history[hps_ctxt.tlp_times - 1] = 0; + /* memset(hps_ctxt.tlp_history, 0, sizeof(hps_ctxt.tlp_history)); */ + switch (hps_ctxt.power_mode) { + case 1: /*Low power mode */ + hps_ctxt.down_times = 1; + hps_ctxt.up_times = 5; + hps_ctxt.down_threshold = 85; + hps_ctxt.up_threshold = 95; + hps_ctxt.rush_boost_enabled = 0; + break; + case 2: /*Just make mode */ + case 3: /*Performance mode */ + hps_ctxt.down_times = 1; + hps_ctxt.up_times = 3; + hps_ctxt.down_threshold = 85; + hps_ctxt.up_threshold = 95; + hps_ctxt.rush_boost_enabled = 1; + break; + default: + break; + } +} + +void hps_ctxt_reset_stas(void) +{ + mutex_lock(&hps_ctxt.lock); + + hps_ctxt_reset_stas_nolock(); + + mutex_unlock(&hps_ctxt.lock); +} + +/* + * hps hps_ctxt_t print interface + */ +void hps_ctxt_print_basic(int toUart) +{ + if (toUart) { + hps_warn("hps_ctxt.init_state: %u\n", hps_ctxt.init_state); + hps_warn("hps_ctxt.state: %u\n", hps_ctxt.state); + hps_warn("hps_ctxt.enabled: %u\n", hps_ctxt.enabled); + hps_warn("hps_ctxt.suspend_enabled: %u\n", hps_ctxt.suspend_enabled); + hps_warn("hps_ctxt.is_hmp: %u\n", hps_ctxt.is_hmp); + hps_warn("hps_ctxt.little_cpu_id_min: %u\n", hps_ctxt.little_cpu_id_min); + hps_warn("hps_ctxt.little_cpu_id_max: %u\n", hps_ctxt.little_cpu_id_max); + hps_warn("hps_ctxt.big_cpu_id_min: %u\n", hps_ctxt.big_cpu_id_min); + hps_warn("hps_ctxt.big_cpu_id_max: %u\n", hps_ctxt.big_cpu_id_max); + } else { + hps_debug("hps_ctxt.init_state: %u\n", hps_ctxt.init_state); + hps_debug("hps_ctxt.state: %u\n", hps_ctxt.state); + hps_debug("hps_ctxt.enabled: %u\n", hps_ctxt.enabled); + hps_debug("hps_ctxt.suspend_enabled: %u\n", hps_ctxt.suspend_enabled); + hps_debug("hps_ctxt.is_hmp: %u\n", hps_ctxt.is_hmp); + hps_debug("hps_ctxt.little_cpu_id_min: %u\n", hps_ctxt.little_cpu_id_min); + hps_debug("hps_ctxt.little_cpu_id_max: %u\n", hps_ctxt.little_cpu_id_max); + hps_debug("hps_ctxt.big_cpu_id_min: %u\n", hps_ctxt.big_cpu_id_min); + hps_debug("hps_ctxt.big_cpu_id_max: %u\n", hps_ctxt.big_cpu_id_max); + } +} + +void hps_ctxt_print_algo_config(int toUart) +{ + if (toUart) { + hps_warn("hps_ctxt.up_threshold: %u\n", hps_ctxt.up_threshold); + hps_warn("hps_ctxt.up_times: %u\n", hps_ctxt.up_times); + hps_warn("hps_ctxt.down_threshold: %u\n", hps_ctxt.down_threshold); + hps_warn("hps_ctxt.down_times: %u\n", hps_ctxt.down_times); + hps_warn("hps_ctxt.input_boost_enabled: %u\n", hps_ctxt.input_boost_enabled); + hps_warn("hps_ctxt.input_boost_cpu_num: %u\n", hps_ctxt.input_boost_cpu_num); + hps_warn("hps_ctxt.rush_boost_enabled: %u\n", hps_ctxt.rush_boost_enabled); + hps_warn("hps_ctxt.rush_boost_threshold: %u\n", hps_ctxt.rush_boost_threshold); + hps_warn("hps_ctxt.rush_boost_times: %u\n", hps_ctxt.rush_boost_times); + hps_warn("hps_ctxt.tlp_times: %u\n", hps_ctxt.tlp_times); + } else { + hps_debug("hps_ctxt.up_threshold: %u\n", hps_ctxt.up_threshold); + hps_debug("hps_ctxt.up_times: %u\n", hps_ctxt.up_times); + hps_debug("hps_ctxt.down_threshold: %u\n", hps_ctxt.down_threshold); + hps_debug("hps_ctxt.down_times: %u\n", hps_ctxt.down_times); + hps_debug("hps_ctxt.input_boost_enabled: %u\n", hps_ctxt.input_boost_enabled); + hps_debug("hps_ctxt.input_boost_cpu_num: %u\n", hps_ctxt.input_boost_cpu_num); + hps_debug("hps_ctxt.rush_boost_enabled: %u\n", hps_ctxt.rush_boost_enabled); + hps_debug("hps_ctxt.rush_boost_threshold: %u\n", hps_ctxt.rush_boost_threshold); + hps_debug("hps_ctxt.rush_boost_times: %u\n", hps_ctxt.rush_boost_times); + hps_debug("hps_ctxt.tlp_times: %u\n", hps_ctxt.tlp_times); + } +} + +void hps_ctxt_print_algo_bound(int toUart) +{ + if (toUart) { + hps_warn("hps_ctxt.little_num_base_perf_serv: %u\n", + hps_ctxt.little_num_base_perf_serv); + hps_warn("hps_ctxt.little_num_limit_thermal: %u\n", + hps_ctxt.little_num_limit_thermal); + hps_warn("hps_ctxt.little_num_limit_low_battery: %u\n", + hps_ctxt.little_num_limit_low_battery); + hps_warn("hps_ctxt.little_num_limit_ultra_power_saving: %u\n", + hps_ctxt.little_num_limit_ultra_power_saving); + hps_warn("hps_ctxt.little_num_limit_power_serv: %u\n", + hps_ctxt.little_num_limit_power_serv); + hps_warn("hps_ctxt.big_num_base_perf_serv: %u\n", hps_ctxt.big_num_base_perf_serv); + hps_warn("hps_ctxt.big_num_limit_thermal: %u\n", hps_ctxt.big_num_limit_thermal); + hps_warn("hps_ctxt.big_num_limit_low_battery: %u\n", + hps_ctxt.big_num_limit_low_battery); + hps_warn("hps_ctxt.big_num_limit_ultra_power_saving: %u\n", + hps_ctxt.big_num_limit_ultra_power_saving); + hps_warn("hps_ctxt.big_num_limit_power_serv: %u\n", + hps_ctxt.big_num_limit_power_serv); + } else { + hps_debug("hps_ctxt.little_num_base_perf_serv: %u\n", + hps_ctxt.little_num_base_perf_serv); + hps_debug("hps_ctxt.little_num_limit_thermal: %u\n", + hps_ctxt.little_num_limit_thermal); + hps_debug("hps_ctxt.little_num_limit_low_battery: %u\n", + hps_ctxt.little_num_limit_low_battery); + hps_debug("hps_ctxt.little_num_limit_ultra_power_saving: %u\n", + hps_ctxt.little_num_limit_ultra_power_saving); + hps_debug("hps_ctxt.little_num_limit_power_serv: %u\n", + hps_ctxt.little_num_limit_power_serv); + hps_debug("hps_ctxt.big_num_base_perf_serv: %u\n", hps_ctxt.big_num_base_perf_serv); + hps_debug("hps_ctxt.big_num_limit_thermal: %u\n", hps_ctxt.big_num_limit_thermal); + hps_debug("hps_ctxt.big_num_limit_low_battery: %u\n", + hps_ctxt.big_num_limit_low_battery); + hps_debug("hps_ctxt.big_num_limit_ultra_power_saving: %u\n", + hps_ctxt.big_num_limit_ultra_power_saving); + hps_debug("hps_ctxt.big_num_limit_power_serv: %u\n", + hps_ctxt.big_num_limit_power_serv); + } +} + +void hps_ctxt_print_algo_stats_cur(int toUart) +{ + if (toUart) { + hps_warn("hps_ctxt.cur_loads: %u\n", hps_ctxt.cur_loads); + hps_warn("hps_ctxt.cur_tlp: %u\n", hps_ctxt.cur_tlp); + hps_warn("hps_ctxt.cur_iowait: %u\n", hps_ctxt.cur_iowait); + hps_warn("hps_ctxt.cur_nr_heavy_task: %u\n", hps_ctxt.cur_nr_heavy_task); + } else { + hps_debug("hps_ctxt.cur_loads: %u\n", hps_ctxt.cur_loads); + hps_debug("hps_ctxt.cur_tlp: %u\n", hps_ctxt.cur_tlp); + hps_debug("hps_ctxt.cur_iowait: %u\n", hps_ctxt.cur_iowait); + hps_debug("hps_ctxt.cur_nr_heavy_task: %u\n", hps_ctxt.cur_nr_heavy_task); + } +} + +void hps_ctxt_print_algo_stats_up(int toUart) +{ + if (toUart) { + hps_warn("hps_ctxt.up_loads_sum: %u\n", hps_ctxt.up_loads_sum); + hps_warn("hps_ctxt.up_loads_count: %u\n", hps_ctxt.up_loads_count); + hps_warn("hps_ctxt.up_loads_history_index: %u\n", hps_ctxt.up_loads_history_index); + } else { + hps_debug("hps_ctxt.up_loads_sum: %u\n", hps_ctxt.up_loads_sum); + hps_debug("hps_ctxt.up_loads_count: %u\n", hps_ctxt.up_loads_count); + hps_debug("hps_ctxt.up_loads_history_index: %u\n", hps_ctxt.up_loads_history_index); + } +} + +void hps_ctxt_print_algo_stats_down(int toUart) +{ + if (toUart) { + hps_warn("hps_ctxt.down_loads_sum: %u\n", hps_ctxt.down_loads_sum); + hps_warn("hps_ctxt.down_loads_count: %u\n", hps_ctxt.down_loads_count); + hps_warn("hps_ctxt.down_loads_history_index: %u\n", + hps_ctxt.down_loads_history_index); + } else { + hps_debug("hps_ctxt.down_loads_sum: %u\n", hps_ctxt.down_loads_sum); + hps_debug("hps_ctxt.down_loads_count: %u\n", hps_ctxt.down_loads_count); + hps_debug("hps_ctxt.down_loads_history_index: %u\n", + hps_ctxt.down_loads_history_index); + } +} + +void hps_ctxt_print_algo_stats_tlp(int toUart) +{ + if (toUart) { + hps_warn("hps_ctxt.tlp_sum: %u\n", hps_ctxt.tlp_sum); + hps_warn("hps_ctxt.tlp_count: %u\n", hps_ctxt.tlp_count); + hps_warn("hps_ctxt.tlp_history_index: %u\n", hps_ctxt.tlp_history_index); + hps_warn("hps_ctxt.tlp_avg: %u\n", hps_ctxt.tlp_avg); + hps_warn("hps_ctxt.rush_count: %u\n", hps_ctxt.rush_count); + } else { + hps_debug("hps_ctxt.tlp_sum: %u\n", hps_ctxt.tlp_sum); + hps_debug("hps_ctxt.tlp_count: %u\n", hps_ctxt.tlp_count); + hps_debug("hps_ctxt.tlp_history_index: %u\n", hps_ctxt.tlp_history_index); + hps_debug("hps_ctxt.tlp_avg: %u\n", hps_ctxt.tlp_avg); + hps_debug("hps_ctxt.rush_count: %u\n", hps_ctxt.rush_count); + } +} + +/*********************************************************** +* device driver +***********************************************************/ +/* + * probe callback + */ +static int hps_probe(struct platform_device *pdev) +{ + hps_warn("hps_probe\n"); + + return 0; +} + +/* + * suspend callback + */ +static int hps_suspend(struct device *dev) +{ + hps_warn("%s\n", __func__); + + if (!hps_ctxt.suspend_enabled) + goto suspend_end; + + mutex_lock(&hps_ctxt.lock); + hps_ctxt.enabled_backup = hps_ctxt.enabled; + hps_ctxt.enabled = 0; + mutex_unlock(&hps_ctxt.lock); + +suspend_end: + hps_ctxt.state = STATE_SUSPEND; + if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_HR_TIMER) + hps_del_timer(); + hps_warn("state: %u, enabled: %u, suspend_enabled: %u, rush_boost_enabled: %u\n", + hps_ctxt.state, hps_ctxt.enabled, + hps_ctxt.suspend_enabled, hps_ctxt.rush_boost_enabled); + + return 0; +} + +/* + * resume callback + */ +static int hps_resume(struct device *dev) +{ + hps_warn("%s\n", __func__); + + if (!hps_ctxt.suspend_enabled) + goto resume_end; + + mutex_lock(&hps_ctxt.lock); + hps_ctxt.enabled = hps_ctxt.enabled_backup; + mutex_unlock(&hps_ctxt.lock); +#if 0 + /*In order to fast screen on, power on extra little CPU to serve system resume. */ + for (cpu = hps_ctxt.little_cpu_id_min; cpu <= hps_ctxt.little_cpu_id_max; cpu++) { + if (!cpu_online(cpu)) + cpu_up(cpu); + } +#endif +resume_end: + hps_ctxt.state = STATE_EARLY_SUSPEND; + if (hps_ctxt.periodical_by == HPS_PERIODICAL_BY_HR_TIMER) { + hps_task_wakeup(); + hps_restart_timer(); + } + hps_warn("state: %u, enabled: %u, suspend_enabled: %u, rush_boost_enabled: %u\n", + hps_ctxt.state, hps_ctxt.enabled, + hps_ctxt.suspend_enabled, hps_ctxt.rush_boost_enabled); + + + return 0; +} + +/* + * freeze callback + */ +static int hps_freeze(struct device *dev) +{ + int cpu; + + hps_warn("%s\n", __func__); + + if (!hps_ctxt.suspend_enabled) + goto freeze_end; + + mutex_lock(&hps_ctxt.lock); + hps_ctxt.enabled_backup = hps_ctxt.enabled; + hps_ctxt.enabled = 0; + /* Force fix cpu0 at IPOH stage */ + if (!cpu_online(0)) + cpu_up(0); + for (cpu = hps_ctxt.big_cpu_id_max; cpu > hps_ctxt.little_cpu_id_min; cpu--) { + if (cpu_online(cpu)) + cpu_down(cpu); + } + mutex_unlock(&hps_ctxt.lock); + +freeze_end: + hps_ctxt.state = STATE_SUSPEND; + hps_warn("state: %u, enabled: %u, suspend_enabled: %u, rush_boost_enabled: %u\n", + hps_ctxt.state, hps_ctxt.enabled, + hps_ctxt.suspend_enabled, hps_ctxt.rush_boost_enabled); + + + return 0; +} + +/* + * restore callback + */ +static int hps_restore(struct device *dev) +{ + hps_warn("%s\n", __func__); + + if (!hps_ctxt.suspend_enabled) + goto restore_end; + + mutex_lock(&hps_ctxt.lock); + hps_ctxt.enabled = hps_ctxt.enabled_backup; + mutex_unlock(&hps_ctxt.lock); + +restore_end: + hps_ctxt.state = STATE_EARLY_SUSPEND; + hps_warn("state: %u, enabled: %u, suspend_enabled: %u, rush_boost_enabled: %u\n", + hps_ctxt.state, hps_ctxt.enabled, + hps_ctxt.suspend_enabled, hps_ctxt.rush_boost_enabled); + + + return 0; +} + +/*********************************************************** +* kernel module +***********************************************************/ +/* + * module init function + */ +static int __init hps_init(void) +{ + int r = 0; + + hps_warn("hps_init\n"); + + /* hps_cpu_init() must before hps_core_init() */ + r = hps_cpu_init(); + if (r) + hps_error("hps_cpu_init fail(%d)\n", r); + + r = hps_procfs_init(); + if (r) + hps_error("hps_procfs_init fail(%d)\n", r); + + + r = platform_device_register(&hotplug_strategy_pdev); + if (r) + hps_error("platform_device_register fail(%d)\n", r); + + r = platform_driver_register(&hps_ctxt.pdrv); + if (r) + hps_error("platform_driver_register fail(%d)\n", r); + + r = register_pm_notifier(&hps_pm_notifier_func); + if (r) + hps_error("pm_notifier_register fail(%d)\n", r); + + r = hps_core_init(); + if (r) + hps_error("hps_core_init fail(%d)\n", r); + + hps_ctxt.init_state = INIT_STATE_DONE; + + is_suspend = 0; + + return r; +} +module_init(hps_init); + +/* + * module exit function + */ +static void __exit hps_exit(void) +{ + int r = 0; + + hps_warn("hps_exit\n"); + + hps_ctxt.init_state = INIT_STATE_NOT_READY; + + r = hps_core_deinit(); + if (r) + hps_error("hps_core_deinit fail(%d)\n", r); +} +module_exit(hps_exit); + +/* + * module parameters + */ +/* module_param(g_enable, int, 0644); */ +/* #ifdef CONFIG_HAS_EARLYSUSPEND */ +/* module_param(g_enable_cpu_rush_boost, int, 0644); */ +/* #endif //#ifdef CONFIG_HAS_EARLYSUSPEND */ +/* module_param(g_enable_dynamic_hps_at_suspend, int, 0644); */ + +MODULE_DESCRIPTION("MediaTek CPU Hotplug Stragegy Core v0.1"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_procfs.c b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_procfs.c new file mode 100644 index 0000000000000000000000000000000000000000..f890bd738e9f968b3f616357a3181e52023c3e17 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_hotplug_strategy_procfs.c @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * 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 +#include +#include +#include +#include +#include + +#include "mt_hotplug_strategy_internal.h" + +typedef void (*func_void) (void); + +static int hps_proc_uint_show(struct seq_file *m, void *v) +{ + unsigned int *pv = (unsigned int *)m->private; + + seq_printf(m, "%u\n", *pv); + return 0; +} + +static ssize_t hps_proc_uint_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, + func_void before_write, func_void after_write) +{ + int len = 0; + char desc[32]; + unsigned int var; + unsigned int *pv; + + desc[31] = '\0'; + pv = (unsigned int *)((struct seq_file *)file->private_data)->private; + len = min(count, sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + desc[len] = '\0'; + + if (!kstrtouint(desc, 0, &var)) { + if (before_write) + before_write(); + + *pv = var; + + if (after_write) + after_write(); + + return count; + } + + hps_warn("%s(): bad argument\n", __func__); + + return -EINVAL; +} + +static void lock_hps_ctxt(void) +{ + mutex_lock(&hps_ctxt.lock); +} + +static void unlock_hps_ctxt(void) +{ + mutex_unlock(&hps_ctxt.lock); +} + +static void reset_unlock_hps_ctxt(void) +{ + hps_ctxt_reset_stas_nolock(); + mutex_unlock(&hps_ctxt.lock); +} + +static ssize_t hps_proc_uint_write_with_lock(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + return hps_proc_uint_write(file, buffer, count, pos, lock_hps_ctxt, unlock_hps_ctxt); +} + +static ssize_t hps_proc_uint_write_with_lock_reset(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + return hps_proc_uint_write(file, buffer, count, pos, lock_hps_ctxt, reset_unlock_hps_ctxt); +} + +#define RPOC_FOPS_OPEN_WRITE(_name, _open, _write) \ + static const struct file_operations _name = { \ + .owner = THIS_MODULE, \ + .open = _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + .write = _write, \ + } + +#define PROC_FOPS_RW_UINT(name, var, _write) \ + static int hps_##name##_proc_open( \ + struct inode *inode, struct file *file) \ + { \ + return single_open(file, hps_proc_uint_show, &(var)); \ + } \ + RPOC_FOPS_OPEN_WRITE( \ + hps_##name##_proc_fops, hps_##name##_proc_open, _write) + +#define PROC_FOPS_RO_UINT(name, var) PROC_FOPS_RW_UINT(name, var, NULL) + +#define PROC_FOPS_RW(name) \ + static int hps_##name##_proc_open( \ + struct inode *inode, struct file *file) \ + { \ + return single_open(file, hps_##name##_proc_show, \ + PDE_DATA(inode)); \ + } \ + RPOC_FOPS_OPEN_WRITE( \ + hps_##name##_proc_fops, \ + hps_##name##_proc_open, \ + hps_##name##_proc_write) + +#define PROC_ENTRY(name) {__stringify(name), &hps_##name##_proc_fops} + +/*********************************************************** +* procfs callback - state series +* - init_state +* - state +***********************************************************/ +PROC_FOPS_RO_UINT(init_state, hps_ctxt.init_state); +PROC_FOPS_RO_UINT(state, hps_ctxt.state); + +/*********************************************************** +* procfs callback - enabled series +* - enabled +* - suspend_enabled +* - cur_dump_enabled +* - stats_dump_enabled +***********************************************************/ +PROC_FOPS_RW_UINT(enabled, hps_ctxt.enabled, hps_proc_uint_write_with_lock_reset); +PROC_FOPS_RW_UINT(suspend_enabled, hps_ctxt.suspend_enabled, hps_proc_uint_write_with_lock); +PROC_FOPS_RW_UINT(cur_dump_enabled, hps_ctxt.cur_dump_enabled, hps_proc_uint_write_with_lock); +PROC_FOPS_RW_UINT(stats_dump_enabled, hps_ctxt.stats_dump_enabled, hps_proc_uint_write_with_lock); + +/*********************************************************** +* procfs callback - algo config series +* - up_threshold +* - up_times +* - down_threshold +* - down_times +* - input_boost_enabled +* - input_boost_cpu_num +* - rush_boost_enabled +* - rush_boost_threshold +* - rush_boost_times +* - tlp_times +***********************************************************/ +PROC_FOPS_RW_UINT(up_threshold, hps_ctxt.up_threshold, hps_proc_uint_write_with_lock_reset); +PROC_FOPS_RW_UINT(up_times, hps_ctxt.up_times, hps_proc_uint_write_with_lock_reset); +PROC_FOPS_RW_UINT(down_threshold, hps_ctxt.down_threshold, hps_proc_uint_write_with_lock_reset); +PROC_FOPS_RW_UINT(down_times, hps_ctxt.down_times, hps_proc_uint_write_with_lock_reset); +PROC_FOPS_RW_UINT(input_boost_enabled, hps_ctxt.input_boost_enabled, hps_proc_uint_write_with_lock); +PROC_FOPS_RW_UINT(input_boost_cpu_num, hps_ctxt.input_boost_cpu_num, hps_proc_uint_write_with_lock); +PROC_FOPS_RW_UINT(rush_boost_enabled, hps_ctxt.rush_boost_enabled, hps_proc_uint_write_with_lock); +PROC_FOPS_RW_UINT(rush_boost_threshold, + hps_ctxt.rush_boost_threshold, hps_proc_uint_write_with_lock_reset); +PROC_FOPS_RW_UINT(rush_boost_times, hps_ctxt.rush_boost_times, hps_proc_uint_write_with_lock_reset); +PROC_FOPS_RW_UINT(tlp_times, hps_ctxt.tlp_times, hps_proc_uint_write_with_lock_reset); + +/*********************************************************** +* procfs callback - algo bound series +* - little_num_base_perf_serv +* - big_num_base_perf_serv +***********************************************************/ +static int hps_num_base_perf_serv_proc_show(struct seq_file *m, void *v) +{ + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + seq_printf(m, "%u %u\n", hps_ctxt.little_num_base_perf_serv, + hps_ctxt.big_num_base_perf_serv); + else + seq_printf(m, "%u\n", hps_ctxt.little_num_base_perf_serv); + return 0; +} + +static ssize_t hps_num_base_perf_serv_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *pos) +{ + int len = 0, little_num_base_perf_serv = 0, big_num_base_perf_serv = 0; + char desc[32]; + unsigned int num_online; + + desc[31] = '\0'; + len = min(count, sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + + if ((hps_ctxt.is_hmp || hps_ctxt.is_amp) + && (sscanf(desc, "%u %u", &little_num_base_perf_serv, &big_num_base_perf_serv) == 2)) { + if (little_num_base_perf_serv > num_possible_little_cpus() + || little_num_base_perf_serv < 1) { + hps_warn("hps_num_base_perf_serv_proc_write, bad argument(%u, %u)\n", + little_num_base_perf_serv, big_num_base_perf_serv); + return -EINVAL; + } + + if (big_num_base_perf_serv > num_possible_big_cpus()) { + hps_warn("hps_num_base_perf_serv_proc_write, bad argument(%u, %u)\n", + little_num_base_perf_serv, big_num_base_perf_serv); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_base_perf_serv = little_num_base_perf_serv; + hps_ctxt.big_num_base_perf_serv = big_num_base_perf_serv; + num_online = num_online_big_cpus(); + if ((num_online < big_num_base_perf_serv) && + (num_online < + min(hps_ctxt.big_num_limit_thermal, + hps_ctxt.big_num_limit_low_battery)) && + (num_online < + min(hps_ctxt.big_num_limit_ultra_power_saving, + hps_ctxt.big_num_limit_power_serv))) + hps_task_wakeup_nolock(); + else { + num_online = num_online_little_cpus(); + if ((num_online < little_num_base_perf_serv) && + (num_online < + min(hps_ctxt.little_num_limit_thermal, + hps_ctxt.little_num_limit_low_battery)) && + (num_online < + min(hps_ctxt.little_num_limit_ultra_power_saving, + hps_ctxt.little_num_limit_power_serv)) && + (num_online_cpus() < + (little_num_base_perf_serv + big_num_base_perf_serv))) + hps_task_wakeup_nolock(); + } + + /* XXX: should we move mutex_unlock(&hps_ctxt.lock) to + earlier stage? no! */ + mutex_unlock(&hps_ctxt.lock); + + return count; + } else if ((!hps_ctxt.is_hmp || !hps_ctxt.is_amp) + && !kstrtouint(desc, 0, &little_num_base_perf_serv)) { + if (little_num_base_perf_serv > num_possible_little_cpus() + || little_num_base_perf_serv < 1) { + hps_warn("hps_num_base_perf_serv_proc_write, bad argument(%u)\n", + little_num_base_perf_serv); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_base_perf_serv = little_num_base_perf_serv; + num_online = num_online_little_cpus(); + if ((num_online < little_num_base_perf_serv) && + (num_online < + min(hps_ctxt.little_num_limit_thermal, + hps_ctxt.little_num_limit_low_battery)) && + (num_online < + min(hps_ctxt.little_num_limit_ultra_power_saving, + hps_ctxt.little_num_limit_power_serv))) + hps_task_wakeup_nolock(); + + /* XXX: should we move mutex_unlock(&hps_ctxt.lock) + to earlier stage? no! */ + mutex_unlock(&hps_ctxt.lock); + + return count; + } + + hps_warn("hps_num_base_perf_serv_proc_write, bad argument\n"); + + return -EINVAL; +} + +PROC_FOPS_RW(num_base_perf_serv); + +/*********************************************************** +* procfs callback - algo bound series +* - little_num_limit_thermal +* - big_num_limit_thermal +***********************************************************/ +static int hps_num_limit_thermal_proc_show(struct seq_file *m, void *v) +{ + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + seq_printf(m, "%u %u\n", hps_ctxt.little_num_limit_thermal, + hps_ctxt.big_num_limit_thermal); + else + seq_printf(m, "%u\n", hps_ctxt.little_num_limit_thermal); + return 0; +} + +static ssize_t hps_num_limit_thermal_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *pos) +{ + int len = 0, little_num_limit_thermal = 0, big_num_limit_thermal = 0; + char desc[32]; + + desc[31] = '\0'; + len = min(count, sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + + if ((hps_ctxt.is_hmp || hps_ctxt.is_amp) + && (sscanf(desc, "%u %u", &little_num_limit_thermal, &big_num_limit_thermal) == 2)) { + if (little_num_limit_thermal > num_possible_little_cpus() + || little_num_limit_thermal < 1) { + hps_warn("hps_num_limit_thermal_proc_write, bad argument(%u, %u)\n", + little_num_limit_thermal, big_num_limit_thermal); + return -EINVAL; + } + + if (big_num_limit_thermal > num_possible_big_cpus()) { + hps_warn("hps_num_limit_thermal_proc_write, bad argument(%u, %u)\n", + little_num_limit_thermal, big_num_limit_thermal); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_limit_thermal = little_num_limit_thermal; + hps_ctxt.big_num_limit_thermal = big_num_limit_thermal; + if (num_online_big_cpus() > big_num_limit_thermal) + hps_task_wakeup_nolock(); + else if (num_online_little_cpus() > little_num_limit_thermal) + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); + + return count; + } else if ((!hps_ctxt.is_hmp || !hps_ctxt.is_amp) + && !kstrtouint(desc, 0, &little_num_limit_thermal)) { + if (little_num_limit_thermal > num_possible_little_cpus() + || little_num_limit_thermal < 1) { + hps_warn("hps_num_limit_thermal_proc_write, bad argument(%u)\n", + little_num_limit_thermal); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_limit_thermal = little_num_limit_thermal; + if (num_online_little_cpus() > little_num_limit_thermal) + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); + + return count; + } + + hps_warn("hps_num_limit_thermal_proc_write, bad argument\n"); + + return -EINVAL; +} + +PROC_FOPS_RW(num_limit_thermal); + +/*********************************************************** +* procfs callback - algo bound series +* - little_num_limit_low_battery +* - big_num_limit_low_battery +***********************************************************/ +static int hps_num_limit_low_battery_proc_show(struct seq_file *m, void *v) +{ + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + seq_printf(m, "%u %u\n", hps_ctxt.little_num_limit_low_battery, + hps_ctxt.big_num_limit_low_battery); + else + seq_printf(m, "%u\n", hps_ctxt.little_num_limit_low_battery); + return 0; +} + +static ssize_t hps_num_limit_low_battery_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *pos) +{ + int len = 0; + int little_num_limit_low_battery = 0, big_num_limit_low_battery = 0; + char desc[32]; + + desc[31] = '\0'; + len = min(count, sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + + if ((hps_ctxt.is_hmp || hps_ctxt.is_amp) + && (sscanf(desc, "%u %u", &little_num_limit_low_battery, + &big_num_limit_low_battery) == 2)) { + if (little_num_limit_low_battery > num_possible_little_cpus() + || little_num_limit_low_battery < 1) { + hps_warn("hps_num_limit_low_battery_proc_write, bad argument(%u, %u)\n", + little_num_limit_low_battery, big_num_limit_low_battery); + return -EINVAL; + } + + if (big_num_limit_low_battery > num_possible_big_cpus()) { + hps_warn("hps_num_limit_low_battery_proc_write, bad argument(%u, %u)\n", + little_num_limit_low_battery, big_num_limit_low_battery); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_limit_low_battery = little_num_limit_low_battery; + hps_ctxt.big_num_limit_low_battery = big_num_limit_low_battery; + if (num_online_big_cpus() > big_num_limit_low_battery) + hps_task_wakeup_nolock(); + else if (num_online_little_cpus() > little_num_limit_low_battery) + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); + + return count; + } else if ((!hps_ctxt.is_hmp || !hps_ctxt.is_amp) + && !kstrtouint(desc, 0, &little_num_limit_low_battery)) { + if (little_num_limit_low_battery > num_possible_little_cpus() + || little_num_limit_low_battery < 1) { + hps_warn("hps_num_limit_low_battery_proc_write, bad argument(%u)\n", + little_num_limit_low_battery); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_limit_low_battery = little_num_limit_low_battery; + if (num_online_little_cpus() > little_num_limit_low_battery) + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); + + return count; + } + + hps_warn("hps_num_limit_low_battery_proc_write, bad argument\n"); + + return -EINVAL; +} + +PROC_FOPS_RW(num_limit_low_battery); + +/*********************************************************** +* procfs callback - algo bound series +* - little_num_limit_ultra_power_saving +* - big_num_limit_ultra_power_saving +***********************************************************/ +static int hps_num_limit_ultra_power_saving_proc_show(struct seq_file *m, void *v) +{ + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + seq_printf(m, "%u %u\n", + hps_ctxt.little_num_limit_ultra_power_saving, + hps_ctxt.big_num_limit_ultra_power_saving); + else + seq_printf(m, "%u\n", hps_ctxt.little_num_limit_ultra_power_saving); + return 0; +} + +static ssize_t hps_num_limit_ultra_power_saving_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *pos) +{ + int len = 0; + int little_num_limit_ultra_power_saving = 0; + int big_num_limit_ultra_power_saving = 0; + char desc[32]; + + desc[31] = '\0'; + len = min(count, sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + + if ((hps_ctxt.is_hmp || hps_ctxt.is_amp) + && + (sscanf(desc, "%u %u", + &little_num_limit_ultra_power_saving, + &big_num_limit_ultra_power_saving) == 2)) { + if (little_num_limit_ultra_power_saving > + num_possible_little_cpus() || little_num_limit_ultra_power_saving < 1) { + hps_warn + ("hps_num_limit_ultra_power_saving_proc_write, bad argument(%u, %u)\n", + little_num_limit_ultra_power_saving, big_num_limit_ultra_power_saving); + return -EINVAL; + } + + if (big_num_limit_ultra_power_saving > num_possible_big_cpus()) { + hps_warn + ("hps_num_limit_ultra_power_saving_proc_write, bad argument(%u, %u)\n", + little_num_limit_ultra_power_saving, big_num_limit_ultra_power_saving); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_limit_ultra_power_saving = little_num_limit_ultra_power_saving; + hps_ctxt.big_num_limit_ultra_power_saving = big_num_limit_ultra_power_saving; + if (num_online_big_cpus() > big_num_limit_ultra_power_saving) + hps_task_wakeup_nolock(); + else if (num_online_little_cpus() > little_num_limit_ultra_power_saving) + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); + + return count; + } else if ((!hps_ctxt.is_hmp || !hps_ctxt.is_amp) + && !kstrtouint(desc, 0, &little_num_limit_ultra_power_saving)) { + if (little_num_limit_ultra_power_saving > num_possible_little_cpus() + || little_num_limit_ultra_power_saving < 1) { + hps_warn("hps_num_limit_ultra_power_saving_proc_write, bad argument(%u)\n", + little_num_limit_ultra_power_saving); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_limit_ultra_power_saving = little_num_limit_ultra_power_saving; + if (num_online_little_cpus() > little_num_limit_ultra_power_saving) + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); + + return count; + } + + hps_warn("hps_num_limit_ultra_power_saving_proc_write, bad argument\n"); + + return -EINVAL; +} + +PROC_FOPS_RW(num_limit_ultra_power_saving); + +/*********************************************************** +* procfs callback - algo bound series +* - little_num_limit_power_serv +* - big_num_limit_power_serv +***********************************************************/ +static int hps_num_limit_power_serv_proc_show(struct seq_file *m, void *v) +{ + if (hps_ctxt.is_hmp || hps_ctxt.is_amp) + seq_printf(m, "%u %u\n", hps_ctxt.little_num_limit_power_serv, + hps_ctxt.big_num_limit_power_serv); + else + seq_printf(m, "%u\n", hps_ctxt.little_num_limit_power_serv); + return 0; +} + +static ssize_t hps_num_limit_power_serv_proc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *pos) +{ + int len = 0; + int little_num_limit_power_serv = 0, big_num_limit_power_serv = 0; + char desc[32]; + + desc[31] = '\0'; + len = min(count, sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + + if ((hps_ctxt.is_hmp || hps_ctxt.is_amp) + && + (sscanf(desc, "%u %u", &little_num_limit_power_serv, &big_num_limit_power_serv) == 2)) { + if (little_num_limit_power_serv > num_possible_little_cpus() + || little_num_limit_power_serv < 1) { + hps_warn("hps_num_limit_power_serv_proc_write, bad argument(%u, %u)\n", + little_num_limit_power_serv, big_num_limit_power_serv); + return -EINVAL; + } + + if (big_num_limit_power_serv > num_possible_big_cpus()) { + hps_warn("hps_num_limit_power_serv_proc_write, bad argument(%u, %u)\n", + little_num_limit_power_serv, big_num_limit_power_serv); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_limit_power_serv = little_num_limit_power_serv; + hps_ctxt.big_num_limit_power_serv = big_num_limit_power_serv; + if (num_online_big_cpus() > big_num_limit_power_serv) + hps_task_wakeup_nolock(); + else if (num_online_little_cpus() > little_num_limit_power_serv) + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); + + return count; + } else if ((!hps_ctxt.is_hmp || !hps_ctxt.is_amp) + && !kstrtouint(desc, 0, &little_num_limit_power_serv)) { + if (little_num_limit_power_serv > num_possible_little_cpus() + || little_num_limit_power_serv < 1) { + hps_warn("hps_num_limit_power_serv_proc_write, bad argument(%u)\n", + little_num_limit_power_serv); + return -EINVAL; + } + + mutex_lock(&hps_ctxt.lock); + + hps_ctxt.little_num_limit_power_serv = little_num_limit_power_serv; + if (num_online_little_cpus() > little_num_limit_power_serv) + hps_task_wakeup_nolock(); + + mutex_unlock(&hps_ctxt.lock); + + return count; + } + + hps_warn("hps_num_limit_power_serv_proc_write, bad argument\n"); + + + return -EINVAL; +} + +PROC_FOPS_RW(num_limit_power_serv); + +/* + * init + */ +int hps_procfs_init(void) +{ + /* struct proc_dir_entry *entry = NULL; */ + struct proc_dir_entry *hps_dir = NULL; + int r = 0; + int i; + + struct pentry { + const char *name; + const struct file_operations *fops; + }; + + const struct pentry entries[] = { + PROC_ENTRY(init_state), + PROC_ENTRY(state), + PROC_ENTRY(enabled), + PROC_ENTRY(suspend_enabled), + PROC_ENTRY(cur_dump_enabled), + PROC_ENTRY(stats_dump_enabled), + PROC_ENTRY(up_threshold), + PROC_ENTRY(up_times), + PROC_ENTRY(down_threshold), + PROC_ENTRY(down_times), + PROC_ENTRY(input_boost_enabled), + PROC_ENTRY(input_boost_cpu_num), + PROC_ENTRY(rush_boost_enabled), + PROC_ENTRY(rush_boost_threshold), + PROC_ENTRY(rush_boost_times), + PROC_ENTRY(tlp_times), + PROC_ENTRY(num_base_perf_serv), + PROC_ENTRY(num_limit_thermal), + PROC_ENTRY(num_limit_low_battery), + PROC_ENTRY(num_limit_ultra_power_saving), + PROC_ENTRY(num_limit_power_serv), + }; + + hps_warn("hps_procfs_init\n"); + + hps_dir = proc_mkdir("hps", NULL); + if (hps_dir == NULL) { + hps_emerg("mkdir /proc/hps fail\n"); + return -1; + } + + for (i = 0; i < ARRAY_SIZE(entries); i++) { + if (!proc_create(entries[i].name, + S_IRUGO | S_IWUSR | S_IWGRP, hps_dir, entries[i].fops)) + hps_emerg("create /proc/hps/%s failed\n", entries[i].name); + } + + return r; +} diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_picachu.c b/drivers/misc/mediatek/base/power/mt6755/mt_picachu.c new file mode 100644 index 0000000000000000000000000000000000000000..09d915c6d8143bff986206dad9f0a2942505de9b --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_picachu.c @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#include +#include +#endif + +#include "mt_ptp.h" + +#define PICACHU_BASE 0x0011C210 +#define PICACHU_SIZE 0x40 + +#define PICACHU_BARRIER_START 0x0011C250 +#define PICACHU_BARRIER_END 0x0011C260 +#define PICACHU_BARRIER_SIZE (PICACHU_BARRIER_END - PICACHU_BARRIER_START) + +#define PARA_PATH "/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/para" +#define CFG_ENV_SIZE 0x1000 +#define CFG_ENV_OFFSET 0x40000 + +#define NR_OPPS 1 + + +#undef TAG +#define TAG "[Picachu] " + +#define picachu_err(fmt, args...) \ + pr_err(TAG"[ERROR]"fmt, ##args) +#define picachu_warn(fmt, args...) \ + pr_warn(TAG"[WARNING]"fmt, ##args) +#define picachu_info(fmt, args...) \ + pr_warn(TAG""fmt, ##args) +#define picachu_dbg(fmt, args...) \ + do { \ + if (picachu_debug) \ + picachu_info(fmt, ##args); \ + else \ + pr_debug(TAG""fmt, ##args); \ + } while (0) +#define picachu_ver(fmt, args...) \ + do { \ + if (picachu_debug == 1) \ + picachu_info(fmt, ##args); \ + } while (0) +#define picachu_cont(fmt, args...) \ + pr_cont(fmt, ##args) + + +struct picachu_info { + unsigned int magic; + int vmin[NR_OPPS]; + int offset; + unsigned int timestamp; + unsigned int checksum; + int enable; +}; + +static struct picachu_info *picachu_data; +static unsigned int picachu_debug; + +#if defined(CONFIG_MTK_DISABLE_PICACHU) +static int picachu_enable; +#else +static int picachu_enable = 1; +#endif + +static void dump_picachu_info(struct seq_file *m, struct picachu_info *info) +{ + int i; + + seq_printf(m, "0x%X\n", info->magic); + for (i = 0; i < NR_OPPS; i++) + seq_printf(m, "0x%X\n", info->vmin[i]); + + seq_printf(m, "0x%X\n", info->offset); + seq_printf(m, "0x%X\n", info->timestamp); + seq_printf(m, "0x%X\n", info->checksum); + seq_printf(m, "0x%X\n", info->enable); +} + +static void read_picachu_emmc(char *pi_data) +{ + int result = 0; + int ret = 0; + loff_t pos = 0; + struct file *read_fp; + + read_fp = filp_open(PARA_PATH, O_RDONLY, 0); + if (IS_ERR(read_fp)) { + result = PTR_ERR(read_fp); + picachu_err("File open return fail,result=%d,file=%p\n", result, read_fp); + + return; + } + + pos += CFG_ENV_OFFSET; + ret = kernel_read(read_fp, pos, (char *)pi_data, CFG_ENV_SIZE); + if (ret < 0) + picachu_err("Kernel read env fail\n"); + + filp_close(read_fp, 0); +} + +static int reset_picachu_emmc(void) +{ + int result = 0; + int ret = 0; + loff_t pos = 0; + struct file *write_fp; + mm_segment_t old_fs; + char *pi_data; + + pi_data = kzalloc(CFG_ENV_SIZE, GFP_KERNEL); + if (pi_data == NULL) + return -ENOMEM; + + write_fp = filp_open(PARA_PATH, O_RDWR, 0); + if (IS_ERR(write_fp)) { + result = PTR_ERR(write_fp); + picachu_err("File open return fail,result=%d,file=%p\n", + result, write_fp); + kfree(pi_data); + return -ENOENT; + } + + pos += CFG_ENV_OFFSET; + ret = kernel_write(write_fp, (char *)pi_data, CFG_ENV_SIZE, pos); + if (ret < 0) + picachu_err("Kernel write env fail\n"); + + old_fs = get_fs(); + set_fs(get_ds()); + ret = vfs_fsync(write_fp, 0); + if (ret < 0) + picachu_warn("Kernel write env sync fail\n"); + + set_fs(old_fs); + + filp_close(write_fp, 0); + kfree(pi_data); + + return 0; +} + +static int picachu_enable_proc_show(struct seq_file *m, void *v) +{ + if (picachu_data != NULL) + seq_printf(m, "0x%X\n", picachu_data->enable); + + return 0; +} + +static ssize_t picachu_enable_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + char *buf = (char *) __get_free_page(GFP_USER); + int enable = 0; + int ret; + + if (!buf) + return -ENOMEM; + + ret = -EINVAL; + + if (count >= PAGE_SIZE) + goto out; + + ret = -EFAULT; + + if (copy_from_user(buf, buffer, count)) + goto out; + + buf[count] = '\0'; + + if (kstrtoint(buf, 10, &enable)) { + ret = -EINVAL; + picachu_dbg("bad argument_1!! argument should be 0/1\n"); + } else { + ret = 0; + if (picachu_data != NULL) + picachu_data->enable = enable; + } + +out: + free_page((unsigned long)buf); + + return (ret < 0) ? ret : count; +} + +static int picachu_offset_proc_show(struct seq_file *m, void *v) +{ + if (picachu_data != NULL) + seq_printf(m, "0x%X\n", picachu_data->offset); + + return 0; +} + +static ssize_t picachu_offset_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + char *buf = (char *) __get_free_page(GFP_USER); + int offset = 0; + int ret; + + if (!buf) + return -ENOMEM; + + ret = -EINVAL; + + if (count >= PAGE_SIZE) + goto out; + + ret = -EFAULT; + + if (copy_from_user(buf, buffer, count)) + goto out; + + buf[count] = '\0'; + + if (kstrtoint(buf, 10, &offset)) { + ret = -EINVAL; + picachu_dbg("bad argument_1!! argument should be 0/1\n"); + } else { + ret = 0; + if (picachu_data != NULL) { + picachu_data->offset = offset; + eem_set_pi_offset(EEM_CTRL_LITTLE, offset); + eem_set_pi_offset(EEM_CTRL_BIG, offset); + } + } + +out: + free_page((unsigned long)buf); + + return (ret < 0) ? ret : count; +} + +static int picachu_emmc_proc_show(struct seq_file *m, void *v) +{ + char *pi_data = NULL; + + pi_data = kzalloc(CFG_ENV_SIZE, GFP_KERNEL); + if (pi_data == NULL) + return -ENOMEM; + + if (pi_data) { + read_picachu_emmc(pi_data); + dump_picachu_info(m, (struct picachu_info *)pi_data); + kfree(pi_data); + } + + return 0; +} + +static ssize_t picachu_emmc_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + int ret; + char *buf = (char *) __get_free_page(GFP_USER); + int offset = 0; + + if (!buf) + return -ENOMEM; + + ret = -EINVAL; + + if (count >= PAGE_SIZE) + goto out; + + ret = -EFAULT; + + if (copy_from_user(buf, buffer, count)) + goto out; + + buf[count] = '\0'; + + if (kstrtoint(buf, 10, &offset)) + ret = -EINVAL; + else + ret = (offset == -1) ? reset_picachu_emmc() : -EINVAL; + +out: + free_page((unsigned long)buf); + + return (ret < 0) ? ret : count; +} + +static int picachu_dump_proc_show(struct seq_file *m, void *v) +{ + if (picachu_data != NULL) + dump_picachu_info(m, picachu_data); + + return 0; +} + +#define PROC_FOPS_RW(name) \ + static int name ## _proc_open(struct inode *inode, \ + struct file *file) \ + { \ + return single_open(file, name ## _proc_show, \ + PDE_DATA(inode)); \ + } \ + static const struct file_operations name ## _proc_fops = { \ + .owner = THIS_MODULE, \ + .open = name ## _proc_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + .write = name ## _proc_write, \ + } + +#define PROC_FOPS_RO(name) \ + static int name ## _proc_open(struct inode *inode, \ + struct file *file) \ + { \ + return single_open(file, name ## _proc_show, \ + PDE_DATA(inode)); \ + } \ + static const struct file_operations name ## _proc_fops = { \ + .owner = THIS_MODULE, \ + .open = name ## _proc_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } + +#define PROC_ENTRY(name) {__stringify(name), &name ## _proc_fops} + +PROC_FOPS_RW(picachu_enable); +PROC_FOPS_RW(picachu_offset); +PROC_FOPS_RW(picachu_emmc); +PROC_FOPS_RO(picachu_dump); + +static int create_procfs(void) +{ + int i; + struct proc_dir_entry *dir = NULL; + struct pentry { + const char *name; + const struct file_operations *fops; + }; + + struct pentry entries[] = { + PROC_ENTRY(picachu_enable), + PROC_ENTRY(picachu_offset), + PROC_ENTRY(picachu_emmc), + PROC_ENTRY(picachu_dump), + }; + + dir = proc_mkdir("picachu", NULL); + + if (!dir) { + picachu_dbg("[%s]: mkdir /proc/picachu failed\n", __func__); + return -1; + } + + for (i = 0; i < ARRAY_SIZE(entries); i++) { + if (!proc_create(entries[i].name, S_IRUGO | S_IWUSR | S_IWGRP, dir, entries[i].fops)) { + picachu_dbg("[%s]: create /proc/picachu/%s failed\n", __func__, entries[i].name); + return -3; + } + } + + return 0; +} + +static int __init picachu_init(void) +{ + int offset = 0; + u32 *barrier; + + barrier = ioremap_nocache(PICACHU_BARRIER_START, PICACHU_BARRIER_SIZE); + memset_io((u8 *)barrier, 0x00, PICACHU_BARRIER_SIZE); + + picachu_data = (struct picachu_info *)ioremap_nocache(PICACHU_BASE, PICACHU_SIZE); + + if (picachu_data != NULL) { + picachu_data->enable = picachu_enable; + + if (picachu_enable == 1) { + offset = picachu_data->offset; + picachu_info("pi_off = %d\n", picachu_data->offset); + } + eem_set_pi_offset(EEM_CTRL_LITTLE, offset); + eem_set_pi_offset(EEM_CTRL_BIG, offset); + } + + create_procfs(); + + if (barrier) + iounmap(barrier); + + return 0; +} + +static void __exit picachu_exit(void) +{ + picachu_dbg("Picachu de-initialization\n"); + + if (picachu_data) + iounmap(picachu_data); + +} + +late_initcall(picachu_init); + +MODULE_DESCRIPTION("MediaTek Picachu Driver v0.1"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_pm_init.c b/drivers/misc/mediatek/base/power/mt6755/mt_pm_init.c new file mode 100644 index 0000000000000000000000000000000000000000..8b93010a724460cfb28e1e9c1035654fdb61102f --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_pm_init.c @@ -0,0 +1,569 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ + +#include +#include + +/* #include "mach/irqs.h" */ +#include +/* #include "mach/mt_reg_base.h" */ +/* #include "mach/mt_typedefs.h" */ +#include "mt_spm.h" +#include "mt_sleep.h" +#include "mt_dcm.h" +#include "mt_cpufreq.h" +#include "mt_gpufreq.h" +/* #include "mach/mt_sleep.h" */ +/* #include "mach/mt_dcm.h" */ +#include +#include +/* #include "mach/mt_cpufreq.h" */ +/* #include "mach/mt_gpufreq.h" */ +/* #include "mach/mt_dormant.h" */ +#include "mt_cpuidle.h" +#include "mt_clkbuf_ctl.h" +/* #include "mach/mt_chip.h" */ +#include + +#define pminit_write(addr, val) mt_reg_sync_writel((val), ((void *)(addr))) +#define pminit_read(addr) __raw_readl(IOMEM(addr)) +#ifndef DRV_WriteReg32 +#define DRV_WriteReg32(addr, val) \ + mt_reg_sync_writel(val, addr) +#endif + +int __attribute__ ((weak)) mt_cpu_dormant_init(void) { return MT_CPU_DORMANT_BYPASS; } +void __attribute__ ((weak)) slp_module_init(void) +{ + +} + + +#define TOPCK_LDVT +#ifdef TOPCK_LDVT +/*************************** +*For TOPCKGen Meter LDVT Test +****************************/ +static unsigned int ckgen_meter(int val) +{ +#if 0 + int output = 0; + int i = 0; + unsigned int temp, clk26cali_0, clk_cfg_9, clk_misc_cfg_1; + + clk26cali_0 = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */ + + clk_misc_cfg_1 = readl(CLK_MISC_CFG_1); + DRV_WriteReg32(CLK_MISC_CFG_1, 0x00FFFFFF); /* select divider */ + + clk_cfg_9 = readl(CLK_CFG_9); + DRV_WriteReg32(CLK_CFG_9, (val << 16)); /* select ckgen_cksw */ + + temp = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, temp | 0x10); /* start fmeter */ + + /* wait frequency meter finish */ + while (readl(CLK26CALI_0) & 0x10) { + mdelay(10); + i++; + if (i > 10) + break; + } + + temp = readl(CLK26CALI_2) & 0xFFFF; + + output = (temp * 26000) / 1024; /* Khz */ + + DRV_WriteReg32(CLK_CFG_9, clk_cfg_9); + DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0); + + if (i > 10) + return 0; + else + return output; +#else + return 0; +#endif +} + +static unsigned int abist_meter(int val) +{ +#if 0 + int output = 0; + int i = 0; + unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1; + + clk26cali_0 = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */ + + clk_misc_cfg_1 = readl(CLK_MISC_CFG_1); + DRV_WriteReg32(CLK_MISC_CFG_1, 0xFFFFFF00); /* select divider */ + + clk_cfg_8 = readl(CLK_CFG_8); + DRV_WriteReg32(CLK_CFG_8, (val << 8)); /* select abist_cksw */ + + temp = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, temp | 0x1); /* start fmeter */ + + /* wait frequency meter finish */ + while (readl(CLK26CALI_0) & 0x1) { + mdelay(10); + i++; + if (i > 10) + break; + } + + temp = readl(CLK26CALI_1) & 0xFFFF; + + output = (temp * 26000) / 1024; /* Khz */ + + DRV_WriteReg32(CLK_CFG_8, clk_cfg_8); + DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0); + + if (i > 10) + return 0; + else + return output; +#else + return 0; +#endif +} + + +#if defined(CONFIG_ARCH_MT6753) +const char *ckgen_array[] = { + "hf_faxi_ck", "hd_faxi_ck", "hf_fdpi0_ck", "hf_fddrphycfg_ck", "hf_fmm_ck", + "f_fpwm_ck", "hf_fvdec_ck", "hf_fmfg_ck", "hf_fcamtg_ck", "f_fuart_ck", + "hf_fspi_ck", "f_fusb20_ck", "hf_fmsdc30_0_ck", "hf_fmsdc30_1_ck", "hf_fmsdc30_2_ck", + "hf_faudio_ck", "hf_faud_intbus_ck", "hf_fpmicspi_ck", "f_frtc_ck", "f_f26m_ck", + "f_f32k_md1_ck", "f_frtc_conn_ck", "hf_fmsdc30_3_ck", "hg_fmipicfg_ck", "NULL", + "hd_qaxidcm_ck", "NULL", "hf_fscam_ck", "f_fckbus_scan", " f_fckrtc_scan", + "hf_fatb_ck", "hf_faud_1_ck", "hf_faud_2_ck", "hf_fmsdc50_0_ck", "hf_firda_ck", + " hf_firtx_ck", "hf_fdisppwm_ck", "hs_fmfg13m_ck" +}; +#else +const char *ckgen_array[] = { + "hf_faxi_ck", "hd_faxi_ck", "hf_fdpi0_ck", "hf_fddrphycfg_ck", "hf_fmm_ck", + "f_fpwm_ck", "hf_fvdec_ck", "hf_fmfg_ck", "hf_fcamtg_ck", "f_fuart_ck", + "hf_fspi_ck", "f_fusb20_ck", "hf_fmsdc30_0_ck", "hf_fmsdc30_1_ck", "hf_fmsdc30_2_ck", + "hf_faudio_ck", "hf_faud_intbus_ck", "hf_fpmicspi_ck", "f_frtc_ck", "f_f26m_ck", + "f_f32k_md1_ck", "f_frtc_conn_ck", "f_fusb20p1_ck", "hg_fmipicfg_ck", "NULL", + "hd_qaxidcm_ck", "NULL", "hf_fscam_ck", "f_fckbus_scan", " f_fckrtc_scan", + "hf_fatb_ck", "hf_faud_1_ck", "hf_faud_2_ck", "hf_fmsdc50_0_ck", "hf_firda_ck", + " hf_firtx_ck", "hf_fdisppwm_ck", "hs_fmfg13m_ck" +}; +#endif + +static int ckgen_meter_read(struct seq_file *m, void *v) +{ + int i; + + for (i = 1; i < 39; i++) + seq_printf(m, "%s: %d\n", ckgen_array[i - 1], ckgen_meter(i)); + + return 0; +} + +static ssize_t ckgen_meter_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[128]; + int len = 0; + /*int val; */ + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + + /*if (sscanf(desc, "%d", &val) == 1) */ + /*if (kstrtoint(desc, "%d", &val) == 1) + pr_debug("ckgen_meter %d is %d\n", val, ckgen_meter(val)); */ + + return count; +} + + +static int abist_meter_read(struct seq_file *m, void *v) +{ + int i; + + for (i = 1; i < 59; i++) + seq_printf(m, "%d\n", abist_meter(i)); + + return 0; +} + +static ssize_t abist_meter_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[128]; + int len = 0; + /*int val; */ + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return 0; + + desc[len] = '\0'; + + /*if (sscanf(desc, "%d", &val) == 1) */ + /*if (kstrtoint(desc, "%d", &val) == 1) + pr_debug("abist_meter %d is %d\n", val, abist_meter(val)); */ + + return count; +} + +static int proc_abist_meter_open(struct inode *inode, struct file *file) +{ + return single_open(file, abist_meter_read, NULL); +} + +static const struct file_operations abist_meter_fops = { + .owner = THIS_MODULE, + .open = proc_abist_meter_open, + .read = seq_read, + .write = abist_meter_write, +}; + +static int proc_ckgen_meter_open(struct inode *inode, struct file *file) +{ + return single_open(file, ckgen_meter_read, NULL); +} + +static const struct file_operations ckgen_meter_fops = { + .owner = THIS_MODULE, + .open = proc_ckgen_meter_open, + .read = seq_read, + .write = ckgen_meter_write, +}; + +#endif + +/********************************************************************* + * FUNCTION DEFINATIONS + ********************************************************************/ + +static unsigned int mt_get_emi_freq(void) +{ +#if 0 + int output = 0; + int i = 0; + unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1; + + clk26cali_0 = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */ + + clk_misc_cfg_1 = readl(CLK_MISC_CFG_1); + DRV_WriteReg32(CLK_MISC_CFG_1, 0xFFFFFF00); /* select divider */ + + clk_cfg_8 = readl(CLK_CFG_8); + DRV_WriteReg32(CLK_CFG_8, (14 << 8)); /* select abist_cksw */ + + temp = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, temp | 0x1); /* start fmeter */ + + /* wait frequency meter finish */ + while (readl(CLK26CALI_0) & 0x1) { + mdelay(10); + i++; + if (i > 10) + break; + } + + temp = readl(CLK26CALI_1) & 0xFFFF; + + output = (temp * 26000) / 1024; /* Khz */ + + DRV_WriteReg32(CLK_CFG_8, clk_cfg_8); + DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0); + + if (i > 10) + return 0; + else + return output; +#else + return 0; +#endif +} +EXPORT_SYMBOL(mt_get_emi_freq); + +unsigned int mt_get_bus_freq(void) +{ +#if 0 + int output = 0; + int i = 0; + unsigned int temp, clk26cali_0, clk_cfg_9, clk_misc_cfg_1; + + clk26cali_0 = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */ + + clk_misc_cfg_1 = readl(CLK_MISC_CFG_1); + DRV_WriteReg32(CLK_MISC_CFG_1, 0x00FFFFFF); /* select divider */ + + clk_cfg_9 = readl(CLK_CFG_9); + DRV_WriteReg32(CLK_CFG_9, (1 << 16)); /* select ckgen_cksw */ + + temp = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, temp | 0x10); /* start fmeter */ + + /* wait frequency meter finish */ + while (readl(CLK26CALI_0) & 0x10) { + udelay(10); + i++; + if (i > 1000) + break; + } + + temp = readl(CLK26CALI_2) & 0xFFFF; + + output = (temp * 26000) / 1024; /* Khz */ + + DRV_WriteReg32(CLK_CFG_9, clk_cfg_9); + DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0); + + if (i > 1000) + return 0; + else + return output; +#else + return 0; +#endif +} +EXPORT_SYMBOL(mt_get_bus_freq); + +static unsigned int mt_get_cpu_freq(void) +{ +#if 0 + int output = 0; + int i = 0; + unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1; + + clk26cali_0 = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */ + + clk_misc_cfg_1 = readl(CLK_MISC_CFG_1); + DRV_WriteReg32(CLK_MISC_CFG_1, 0xFFFF0300); /* select divider */ + + clk_cfg_8 = readl(CLK_CFG_8); + DRV_WriteReg32(CLK_CFG_8, (39 << 8)); /* select abist_cksw */ + + temp = readl(CLK26CALI_0); + DRV_WriteReg32(CLK26CALI_0, temp | 0x1); /* start fmeter */ + + /* wait frequency meter finish */ + while (readl(CLK26CALI_0) & 0x1) { + mdelay(10); + i++; + if (i > 10) + break; + } + + temp = readl(CLK26CALI_1) & 0xFFFF; + + output = ((temp * 26000) / 1024) * 4; /* Khz */ + + DRV_WriteReg32(CLK_CFG_8, clk_cfg_8); + DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1); + DRV_WriteReg32(CLK26CALI_0, clk26cali_0); + + if (i > 10) + return 0; + else + return output; +#else + return 0; +#endif +} +EXPORT_SYMBOL(mt_get_cpu_freq); + +static int cpu_speed_dump_read(struct seq_file *m, void *v) +{ + seq_printf(m, "%d\n", mt_get_cpu_freq()); + return 0; +} + +static int emi_speed_dump_read(struct seq_file *m, void *v) +{ + seq_printf(m, "%d\n", mt_get_emi_freq()); + return 0; +} + +static int bus_speed_dump_read(struct seq_file *m, void *v) +{ + seq_printf(m, "%d\n", mt_get_bus_freq()); + return 0; +} + +#if 0 +static int mmclk_speed_dump_read(struct seq_file *m, void *v) +{ + seq_printf(m, "%d\n", mt_get_mmclk_freq()); + return 0; +} + +static int mfgclk_speed_dump_read(struct seq_file *m, void *v) +{ + seq_printf(m, "%d\n", mt_get_mfgclk_freq()); + return 0; +} +#endif + +static int proc_cpu_open(struct inode *inode, struct file *file) +{ + return single_open(file, cpu_speed_dump_read, NULL); +} + +static const struct file_operations cpu_fops = { + .owner = THIS_MODULE, + .open = proc_cpu_open, + .read = seq_read, +}; + + +static int proc_emi_open(struct inode *inode, struct file *file) +{ + return single_open(file, emi_speed_dump_read, NULL); +} + +static const struct file_operations emi_fops = { + .owner = THIS_MODULE, + .open = proc_emi_open, + .read = seq_read, +}; + +static int proc_bus_open(struct inode *inode, struct file *file) +{ + return single_open(file, bus_speed_dump_read, NULL); +} + +static const struct file_operations bus_fops = { + .owner = THIS_MODULE, + .open = proc_bus_open, + .read = seq_read, +}; + +#if 0 +static int proc_mmclk_open(struct inode *inode, struct file *file) +{ + return single_open(file, mmclk_speed_dump_read, NULL); +} + +static const struct file_operations mmclk_fops = { + .owner = THIS_MODULE, + .open = proc_mmclk_open, + .read = seq_read, +}; + +static int proc_mfgclk_open(struct inode *inode, struct file *file) +{ + return single_open(file, mfgclk_speed_dump_read, NULL); +} + +static const struct file_operations mfgclk_fops = { + .owner = THIS_MODULE, + .open = proc_mfgclk_open, + .read = seq_read, +}; +#endif + + +static int __init mt_power_management_init(void) +{ + struct proc_dir_entry *entry = NULL; + struct proc_dir_entry *pm_init_dir = NULL; + /* unsigned int code = mt_get_chip_hw_code(); */ + + pm_power_off = mt_power_off; + +#if !defined(CONFIG_MTK_FPGA) + /* cpu dormant driver init */ + mt_cpu_dormant_init(); + + spm_module_init(); + slp_module_init(); + mt_freqhopping_init(); + /* mt_clkmgr_init(); */ + + /* mt_pm_log_init(); // power management log init */ + + /* mt_dcm_init(); // dynamic clock management init */ + + + pm_init_dir = proc_mkdir("pm_init", NULL); + /* pm_init_dir = proc_mkdir("pm_init", NULL); */ + if (!pm_init_dir) { + pr_debug("[%s]: mkdir /proc/pm_init failed\n", __func__); + } else { + entry = proc_create("cpu_speed_dump", S_IRUGO, pm_init_dir, &cpu_fops); + + /* entry = proc_create("bigcpu_speed_dump", S_IRUGO, pm_init_dir, &bigcpu_fops); */ + + entry = proc_create("emi_speed_dump", S_IRUGO, pm_init_dir, &emi_fops); + + entry = proc_create("bus_speed_dump", S_IRUGO, pm_init_dir, &bus_fops); + + /* entry = proc_create("mmclk_speed_dump", S_IRUGO, pm_init_dir, &mmclk_fops); */ + + /* entry = proc_create("mfgclk_speed_dump", S_IRUGO, pm_init_dir, &mfgclk_fops); */ +#ifdef TOPCK_LDVT + entry = + proc_create("abist_meter_test", S_IRUGO | S_IWUSR, pm_init_dir, + &abist_meter_fops); + entry = + proc_create("ckgen_meter_test", S_IRUGO | S_IWUSR, pm_init_dir, + &ckgen_meter_fops); +#endif + } + +#endif + + return 0; +} +arch_initcall(mt_power_management_init); + + +#if !defined(MT_DORMANT_UT) +static int __init mt_pm_late_init(void) +{ +#ifndef CONFIG_MTK_FPGA +/* mt_idle_init(); */ + clk_buf_init(); +#endif + return 0; +} +late_initcall(mt_pm_late_init); +#endif /* #if !defined (MT_DORMANT_UT) */ + + +MODULE_DESCRIPTION("MTK Power Management Init Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_psci.c b/drivers/misc/mediatek/base/power/mt6755/mt_psci.c new file mode 100644 index 0000000000000000000000000000000000000000..ec244b9c8a8ee5b1ad04d67ed80d9708a4153b32 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_psci.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * 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 +#include +#include +#include +#include +#include + +#include "mt_cpu_psci_ops.h" + +#ifdef CONFIG_SMP + +static int __init mt_psci_cpu_init(struct device_node *dn, unsigned int cpu) +{ + return 0; +} + +static int __init mt_psci_cpu_prepare(unsigned int cpu) +{ + if (cpu == 1) + spm_mtcmos_cpu_init(); + return cpu_psci_ops.cpu_prepare(cpu); +} + +static int mt_psci_cpu_boot(unsigned int cpu) +{ + int ret; + + ret = cpu_psci_ops.cpu_boot(cpu); + if (ret < 0) + return ret; + + return spm_mtcmos_ctrl_cpu(cpu, STA_POWER_ON, 1); +} + +#ifdef CONFIG_HOTPLUG_CPU +static int mt_psci_cpu_disable(unsigned int cpu) +{ + return cpu_psci_ops.cpu_disable(cpu); +} + +static void mt_psci_cpu_die(unsigned int cpu) +{ + cpu_psci_ops.cpu_die(cpu); +} + +static int mt_psci_cpu_kill(unsigned int cpu) +{ + int ret; + + ret = cpu_psci_ops.cpu_kill(cpu); + if (!ret) + pr_warn("CPU%d may not have shut down cleanly\n", cpu); + + return !spm_mtcmos_ctrl_cpu(cpu, STA_POWER_DOWN, 1); +} + +#endif + +#ifdef CONFIG_CPU_IDLE + +static int mt_psci_cpu_init_idle(struct device_node *cpu_node, + unsigned int cpu) +{ + return cpu_psci_ops.cpu_init_idle(cpu_node, cpu); +} + +static int mt_psci_cpu_suspend(unsigned long index) +{ +#ifdef CONFIG_MTK_HIBERNATION + if (index == POWERMODE_HIBERNATE) { + pr_warn("[%s] hibernating\n", __func__); + return swsusp_arch_save_image(0); + } +#endif + return cpu_psci_ops.cpu_suspend(index); +} + +#endif + +const struct cpu_operations mt_cpu_psci_ops = { + .name = "mt-boot", +#ifdef CONFIG_CPU_IDLE + .cpu_init_idle = mt_psci_cpu_init_idle, + .cpu_suspend = mt_psci_cpu_suspend, +#endif + .cpu_init = mt_psci_cpu_init, + .cpu_prepare = mt_psci_cpu_prepare, + .cpu_boot = mt_psci_cpu_boot, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = mt_psci_cpu_disable, + .cpu_die = mt_psci_cpu_die, + .cpu_kill = mt_psci_cpu_kill, +#endif +}; + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_ptp.c b/drivers/misc/mediatek/base/power/mt6755/mt_ptp.c new file mode 100644 index 0000000000000000000000000000000000000000..10edc54215f8ab67cda60e3fae06c5b6d18e9dd5 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_ptp.c @@ -0,0 +1,4912 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +unsigned int reg_dump_addr_off[] = { + 0x0000, + 0x0004, + 0x0008, + 0x000C, + 0x0010, + 0x0014, + 0x0018, + 0x001c, + 0x0024, + 0x0028, + 0x002c, + 0x0030, + 0x0034, + 0x0038, + 0x003c, + 0x0040, + 0x0044, + 0x0048, + 0x004c, + 0x0050, + 0x0054, + 0x0058, + 0x005c, + 0x0060, + 0x0064, + 0x0068, + 0x006c, + 0x0070, + 0x0074, + 0x0078, + 0x007c, + 0x0080, + 0x0084, + 0x0088, + 0x008c, + 0x0090, + 0x0094, + 0x0098, + 0x00a0, + 0x00a4, + 0x00a8, + 0x00B0, + 0x00B4, + 0x00B8, + 0x00BC, + 0x00C0, + 0x00C4, + 0x00C8, + 0x00CC, + 0x00F0, + 0x00F4, + 0x00F8, + 0x00FC, + 0x0200, + 0x0204, + 0x0208, + 0x020C, + 0x0210, + 0x0214, + 0x0218, + 0x021C, + 0x0220, + 0x0224, + 0x0228, + 0x022C, + 0x0230, + 0x0234, + 0x0238, + 0x023C, + 0x0240, + 0x0244, + 0x0248, + 0x024C, + 0x0250, + 0x0254, + 0x0258, + 0x025C, + 0x0260, + 0x0264, + 0x0268, + 0x026C, + 0x0270, + 0x0274, + 0x0278, + 0x027C, + 0x0280, + 0x0284, + 0x0400, + 0x0404, + 0x0408, + 0x040C, + 0x0410, + 0x0414, + 0x0418, + 0x041C, + 0x0420, + 0x0424, + 0x0428, + 0x042C, + 0x0430, +}; + +unsigned int littleFreq_FY[8] = {1001000, 910000, 819000, 689000, 598000, 494000, 338000, 156000}; + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + #if defined(CONFIG_MTK_MT6750TT) + unsigned int bigFreq_FY[8] = {1807000, 1430000, 1352000, 1196000, 1027000, 871000, 663000, 286000}; + #else + unsigned int bigFreq_FY[8] = {1508000, 1430000, 1352000, 1196000, 1027000, 871000, 663000, 286000}; + #endif +#else +unsigned int bigFreq_FY[8] = {1807000, 1651000, 1495000, 1196000, 1027000, 871000, 663000, 286000}; +unsigned int bigFreq_FY_M[8] = {1807000, 1651000, 1495000, 1196000, 1098000, 871000, 663000, 286000}; +#endif + +unsigned int littleFreq_SB[8] = {1144000, 1014000, 871000, 689000, 598000, 494000, 338000, 156000}; +unsigned int bigFreq_SB[8] = {1950000, 1755000, 1573000, 1196000, 1027000, 871000, 663000, 286000}; + +unsigned int littleFreq_P15[8] = {1248000, 1079000, 910000, 689000, 598000, 494000, 338000, 156000}; +unsigned int bigFreq_P15[8] = {2145000, 1911000, 1664000, 1196000, 1027000, 871000, 663000, 286000}; + +unsigned int gpuFreq[8] = {728000, 650000, 598000, 520000, 468000, 429000, 390000, 351000}; + + +/* +[31:27] CCI dcmdiv +[26:22] CCI div +[21:17] dcm div +[16:12] clkdiv; ARM PLL Divider +[11:9] post dif +[8:0] DDS[20:12] + +[13:7] Vsram pmic value +[6:0] Vproc pmic value +*/ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + +unsigned int fyTbl[][9] = { +/* CCI dcmdiv, CCI_div, dcm_div, clk_div, post_div, DDS, Vsram, Vproc */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x134, 0x0, 0x58, 0x58},/* 1001 (LL) */ + {0x08, 0xa, 0x11, 0x8, 0x1, 0x118, 0x0, 0x58, 0x52},/* 910 */ + {0x07, 0xa, 0x0f, 0x8, 0x1, 0x0fc, 0x0, 0x58, 0x4c},/* 819 */ + {0x06, 0xa, 0x0D, 0x8, 0x1, 0x0d4, 0x0, 0x50, 0x40},/* 689 */ + {0x05, 0xa, 0x0B, 0x8, 0x1, 0x0b8, 0x0, 0x4b, 0x3b},/* 598 */ + {0x04, 0xb, 0x09, 0xa, 0x1, 0x130, 0x0, 0x46, 0x36},/* 494 */ + {0x03, 0xb, 0x06, 0xa, 0x1, 0x0d0, 0x0, 0x40, 0x30},/* 338 */ + {0x01, 0x1d, 0x03, 0xb, 0x1, 0x0c0, 0x0, 0x35, 0x20},/* 156 */ + {0x0e, 0xa, 0x1d, 0x8, 0x0, 0x0e8, 0x0, 0x58, 0x58},/* 1508 (L) */ + {0x0d, 0xa, 0x1b, 0x8, 0x0, 0x0dc, 0x0, 0x58, 0x52},/* 1430 */ + {0x0d, 0xa, 0x1a, 0x8, 0x0, 0x0d0, 0x0, 0x58, 0x4c},/* 1352 */ + {0x0b, 0xa, 0x17, 0x8, 0x0, 0x0b8, 0x0, 0x50, 0x40},/* 1196 */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x13c, 0x0, 0x4b, 0x3b},/* 1027 */ + {0x08, 0xa, 0x10, 0x8, 0x1, 0x10c, 0x0, 0x46, 0x36},/* 871 */ + {0x06, 0xa, 0x0c, 0x8, 0x1, 0x0cc, 0x0, 0x40, 0x30},/* 663 */ + {0x02, 0xb, 0x05, 0xa, 0x1, 0x0B0, 0x0, 0x35, 0x20},/* 286 */ +}; + +unsigned int sbTbl[][9] = { + {0x0b, 0xa, 0x16, 0x8, 0x1, 0x160, 0x0, 0x58, 0x58},/* 1144 (LL) */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x138, 0x0, 0x58, 0x52},/* 1014 */ + {0x08, 0xa, 0x10, 0x8, 0x1, 0x10c, 0x0, 0x58, 0x4c},/* 871 */ + {0x06, 0xa, 0x0D, 0x8, 0x1, 0x0d4, 0x0, 0x50, 0x40},/* 689 */ + {0x05, 0xa, 0x0B, 0x8, 0x1, 0x0b8, 0x0, 0x4b, 0x3b},/* 598 */ + {0x04, 0xb, 0x09, 0xa, 0x1, 0x130, 0x0, 0x46, 0x36},/* 494 */ + {0x03, 0xb, 0x06, 0xa, 0x1, 0x0d0, 0x0, 0x40, 0x30},/* 338 */ + {0x01, 0x1d, 0x03, 0xb, 0x1, 0x0c0, 0x0, 0x35, 0x20},/* 156 */ + {0x12, 0xa, 0x1f, 0x8, 0x0, 0x12c, 0x0, 0x58, 0x58},/* 1950 (L) */ + {0x10, 0xa, 0x1f, 0x8, 0x0, 0x10e, 0x0, 0x58, 0x52},/* 1755 */ + {0x0f, 0xa, 0x1e, 0x8, 0x0, 0x0f2, 0x0, 0x58, 0x4c},/* 1573 */ + {0x0b, 0xa, 0x17, 0x8, 0x0, 0x0b8, 0x0, 0x50, 0x40},/* 1196 */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x13c, 0x0, 0x4b, 0x3b},/* 1027 */ + {0x08, 0xa, 0x10, 0x8, 0x1, 0x10c, 0x0, 0x46, 0x36},/* 871 */ + {0x06, 0xa, 0x0c, 0x8, 0x1, 0x0cc, 0x0, 0x40, 0x30},/* 663 */ + {0x02, 0xb, 0x05, 0xa, 0x1, 0x0B0, 0x0, 0x35, 0x20},/* 286 */ +}; +static unsigned int *tTbl; + +#else +unsigned int fyTbl[][9] = { +/* CCI dcmdiv, CCI_div, dcm_div, clk_div, post_div, DDS, Vsram, Vproc */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x134, 0xc51, 0x58, 0x58},/* 1001 (LL) */ + {0x08, 0xa, 0x11, 0x8, 0x1, 0x118, 0xb33, 0x58, 0x52},/* 910 */ + {0x07, 0xa, 0x0f, 0x8, 0x1, 0x0fc, 0xa14, 0x58, 0x4c},/* 819 */ + {0x06, 0xa, 0x0D, 0x8, 0x1, 0x0d4, 0x87a, 0x50, 0x40},/* 689 */ + {0x05, 0xa, 0x0B, 0x8, 0x1, 0x0b8, 0x75c, 0x4b, 0x3b},/* 598 */ + {0x02, 0xb, 0x09, 0xa, 0x1, 0x130, 0xc28, 0x46, 0x36},/* 494 */ + {0x01, 0xb, 0x06, 0xa, 0x1, 0x0d0, 0x851, 0x40, 0x30},/* 338 */ + {0x00, 0x1d, 0x03, 0xb, 0x1, 0x0c0, 0x7ae, 0x35, 0x20},/* 156 */ + {0x11, 0xa, 0x1f, 0x8, 0x0, 0x116, 0xb1e, 0x58, 0x58},/* 1807 (L) */ + {0x0f, 0xa, 0x1f, 0x8, 0x0, 0x0fe, 0xA28, 0x58, 0x52},/* 1651 */ + {0x0e, 0xa, 0x1c, 0x8, 0x0, 0x0e6, 0x933, 0x58, 0x4c},/* 1495 */ + {0x0b, 0xa, 0x17, 0x8, 0x0, 0x0b8, 0x75c, 0x50, 0x40},/* 1196 */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x13c, 0xca3, 0x4b, 0x3b},/* 1027 */ + {0x08, 0xa, 0x10, 0x8, 0x1, 0x10c, 0xab8, 0x46, 0x36},/* 871 */ + {0x06, 0xa, 0x0c, 0x8, 0x1, 0x0cc, 0x828, 0x40, 0x30},/* 663 */ + {0x02, 0xb, 0x05, 0xa, 0x1, 0x0B0, 0x70a, 0x35, 0x20},/* 286 */ +}; + +unsigned int fyTbl_M[][9] = { +/* CCI dcmdiv, CCI_div, dcm_div, clk_div, post_div, DDS, Vsram, Vproc */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x134, 0xc51, 0x58, 0x58},/* 1001 (LL) */ + {0x08, 0xa, 0x11, 0x8, 0x1, 0x118, 0xb33, 0x58, 0x52},/* 910 */ + {0x07, 0xa, 0x0f, 0x8, 0x1, 0x0fc, 0xa14, 0x58, 0x4c},/* 819 */ + {0x06, 0xa, 0x0D, 0x8, 0x1, 0x0d4, 0x87a, 0x50, 0x40},/* 689 */ + {0x05, 0xa, 0x0B, 0x8, 0x1, 0x0b8, 0x75c, 0x4b, 0x3b},/* 598 */ + {0x02, 0xb, 0x09, 0xa, 0x1, 0x130, 0xc28, 0x46, 0x36},/* 494 */ + {0x01, 0xb, 0x06, 0xa, 0x1, 0x0d0, 0x851, 0x40, 0x30},/* 338 */ + {0x00, 0x1d, 0x03, 0xb, 0x1, 0x0c0, 0x7ae, 0x35, 0x20},/* 156 */ + {0x11, 0xa, 0x1f, 0x8, 0x0, 0x116, 0xb1e, 0x58, 0x58},/* 1807 (L) */ + {0x0f, 0xa, 0x1f, 0x8, 0x0, 0x0fe, 0xA28, 0x58, 0x52},/* 1651 */ + {0x0e, 0xa, 0x1c, 0x8, 0x0, 0x0e6, 0x933, 0x58, 0x4c},/* 1495 */ + {0x0b, 0xa, 0x17, 0x8, 0x0, 0x0b8, 0x75c, 0x50, 0x40},/* 1196 */ + {0x09, 0xa, 0x13, 0x8, 0x0, 0x09e, 0xca3, 0x4b, 0x3b},/* 1027 */ + {0x08, 0xa, 0x10, 0x8, 0x1, 0x10c, 0xab8, 0x46, 0x36},/* 871 */ + {0x06, 0xa, 0x0c, 0x8, 0x1, 0x0cc, 0x828, 0x40, 0x30},/* 663 */ + {0x02, 0xb, 0x05, 0xa, 0x1, 0x0B0, 0x70a, 0x35, 0x20},/* 286 */ +}; + +unsigned int sbTbl[][9] = { + {0x0b, 0xa, 0x16, 0x8, 0x1, 0x160, 0xe14, 0x58, 0x58},/* 1144 (LL) */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x138, 0xc7a, 0x58, 0x52},/* 1014 */ + {0x08, 0xa, 0x10, 0x8, 0x1, 0x10c, 0xab8, 0x58, 0x4c},/* 871 */ + {0x06, 0xa, 0x0D, 0x8, 0x1, 0x0d4, 0x87a, 0x50, 0x40},/* 689 */ + {0x05, 0xa, 0x0B, 0x8, 0x1, 0x0b8, 0x75c, 0x4b, 0x3b},/* 598 */ + {0x02, 0xb, 0x09, 0xa, 0x1, 0x130, 0xc28, 0x46, 0x36},/* 494 */ + {0x01, 0xb, 0x06, 0xa, 0x1, 0x0d0, 0x851, 0x40, 0x30},/* 338 */ + {0x00, 0x1d, 0x03, 0xb, 0x1, 0x0c0, 0x7ae, 0x35, 0x20},/* 156 */ + {0x12, 0xa, 0x1f, 0x8, 0x0, 0x12c, 0xc00, 0x58, 0x58},/* 1950 (L) */ + {0x10, 0xa, 0x1f, 0x8, 0x0, 0x10e, 0xacc, 0x58, 0x52},/* 1755 */ + {0x0f, 0xa, 0x1e, 0x8, 0x0, 0x0f2, 0x9ae, 0x58, 0x4c},/* 1573 */ + {0x0b, 0xa, 0x17, 0x8, 0x0, 0x0b8, 0x75c, 0x50, 0x40},/* 1196 */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x13c, 0xca3, 0x4b, 0x3b},/* 1027 */ + {0x08, 0xa, 0x10, 0x8, 0x1, 0x10c, 0xab8, 0x46, 0x36},/* 871 */ + {0x06, 0xa, 0x0c, 0x8, 0x1, 0x0cc, 0x828, 0x40, 0x30},/* 663 */ + {0x02, 0xb, 0x05, 0xa, 0x1, 0x0B0, 0x70a, 0x35, 0x20},/* 286 */ +}; + +unsigned int p15Tbl[][9] = { + {0x0c, 0xa, 0x18, 0x8, 0x1, 0x180, 0xe14, 0x58, 0x58},/* 1248 (LL) */ + {0x0a, 0xa, 0x14, 0x8, 0x1, 0x14c, 0xc7a, 0x58, 0x52},/* 1079 */ + {0x08, 0xa, 0x11, 0x8, 0x1, 0x118, 0xab8, 0x58, 0x4c},/* 910 */ + {0x06, 0xa, 0x0D, 0x8, 0x1, 0x0d4, 0x87a, 0x50, 0x40},/* 689 */ + {0x05, 0xa, 0x0B, 0x8, 0x1, 0x0b8, 0x75c, 0x4b, 0x3b},/* 598 */ + {0x02, 0xb, 0x09, 0xa, 0x1, 0x130, 0xc28, 0x46, 0x36},/* 494 */ + {0x01, 0xb, 0x06, 0xa, 0x1, 0x0d0, 0x851, 0x40, 0x30},/* 338 */ + {0x00, 0x1d, 0x03, 0xb, 0x1, 0x0c0, 0x7ae, 0x35, 0x20},/* 156 */ + {0x14, 0xa, 0x1f, 0x8, 0x0, 0x14A, 0xc00, 0x58, 0x58},/* 2145 (L) */ + {0x12, 0xa, 0x1f, 0x8, 0x0, 0x126, 0xacc, 0x58, 0x52},/* 1911 */ + {0x10, 0xa, 0x1e, 0x8, 0x0, 0x100, 0x9ae, 0x58, 0x4c},/* 1664 */ + {0x0b, 0xa, 0x17, 0x8, 0x0, 0x0b8, 0x75c, 0x50, 0x40},/* 1196 */ + {0x09, 0xa, 0x13, 0x8, 0x1, 0x13c, 0xca3, 0x4b, 0x3b},/* 1027 */ + {0x08, 0xa, 0x10, 0x8, 0x1, 0x10c, 0xab8, 0x46, 0x36},/* 871 */ + {0x06, 0xa, 0x0c, 0x8, 0x1, 0x0cc, 0x828, 0x40, 0x30},/* 663 */ + {0x02, 0xb, 0x05, 0xa, 0x1, 0x0B0, 0x70a, 0x35, 0x20},/* 286 */ +}; + +unsigned int gpuSb[8] = {0x54, 0x54, 0x54, 0x40, 0x40, 0x40, 0x40, 0x35}; +unsigned int gpuFy[8] = {0x54, 0x40, 0x40, 0x40, 0x40, 0x35, 0x00, 0x00}; +#endif +static unsigned int record_tbl_locked[8]; +static unsigned int *recordTbl; +static unsigned int cpu_speed; + +/** + * @file mt_ptp.c + * @brief Driver for EEM + * + */ + +#define __MT_EEM_C__ + +/* Early porting use that avoid to cause compiler error */ +/* #define EARLY_PORTING */ + +/*============================================================= + * Include files + *=============================================================*/ + +/* system includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* project includes */ +/* #include "mach/mt_reg_base.h" */ +/* #include "mach/mt_typedefs.h" */ + +#include "mach/irqs.h" +/* #include "mach/mt_irq.h" */ +#include "mt_ptp.h" +#include "mt_cpufreq.h" +/* #include "mach/mt_spm_idle.h" +#include "mach/mt_pmic_wrap.h" +#include "mach/mt_clkmgr.h" */ +#include "mach/mt_freqhopping.h" +#include "mach/mtk_rtc_hal.h" +#include "mach/mt_rtc_hw.h" + +#ifdef CONFIG_OF + #include + #include + #include + #include + #include + #if defined(CONFIG_MTK_CLKMGR) + #include + #else + #include + #endif +#endif + +/* local includes */ +#include "mt_defptp.h" +#ifdef __KERNEL__ + #include + #include + #include "mt-plat/upmu_common.h" + #include "mach/mt_thermal.h" + #include "mach/mt_ppm_api.h" + #include "mt_gpufreq.h" + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) && defined(CONFIG_MTK_MT6750TT) + #include "mt_eem_turbo.h" + #else + #include "../../../power/mt6755/mt6311.h" + /* #include "mach/mt6311.h" */ + #endif + +#else + #include "mach/mt_ptpslt.h" + #include "kernel2ctp.h" + #include "ptp.h" + #include "upmu_common.h" + #include "mt6311.h" + #ifndef EARLY_PORTING + #include "gpu_dvfs.h" + #include "thermal.h" + /* #include "gpio_const.h" */ + #endif +#endif + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +static unsigned int ctrl_ITurbo = 0, ITurboRun, fab, segment; +unsigned int cpuBinLevel, cpuBinLevel_eng; +#endif +static int eem_log_en; + +/* Global variable for slow idle*/ +volatile unsigned int ptp_data[3] = {0, 0, 0}; + + +struct eem_det; +struct eem_ctrl; +u32 *recordRef; + +static void eem_set_eem_volt(struct eem_det *det); +static void eem_restore_eem_volt(struct eem_det *det); + +#if 0 +static void eem_init01_prepare(struct eem_det *det); +static void eem_init01_finish(struct eem_det *det); +#endif + +/*============================================================= + * Macro definition + *=============================================================*/ + +/* + * CONFIG (SW related) + */ +/* #define CONFIG_EEM_SHOWLOG */ + +#define EN_ISR_LOG (0) + +#define EEM_GET_REAL_VAL (1) /* get val from efuse */ +#define SET_PMIC_VOLT (1) /* apply PMIC voltage */ + +#define DUMP_DATA_TO_DE (1) + +#define LOG_INTERVAL (2LL * NSEC_PER_SEC) +#define NR_FREQ 8 + + +/* + * 100 us, This is the EEM Detector sampling time as represented in + * cycles of bclk_ck during INIT. 52 MHz + */ +#define DETWINDOW_VAL 0x514 + +/* + * mili Volt to config value. voltage = 600mV + val * 6.25mV + * val = (voltage - 600) / 6.25 + * @mV: mili volt + */ +#if 1 +/* from Brian Yang,1mV=>10uV */ +#define EEM_VOLT_TO_PMIC_VAL(volt) (((volt) - 70000 + 625 - 1) / 625) /* ((((volt) - 700 * 100 + 625 - 1) / 625) */ + +/* pmic value from EEM already add 16 steps(16*6.25=100mV) for real voltage transfer */ +#define EEM_PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + 60000) /* (((pmic) * 625) / 100 + 600) */ +#else +#define MV_TO_VAL(MV) ((((MV) - 600) * 100 + 625 - 1) / 625) /* TODO: FIXME, refer to VOLT_TO_PMIC_VAL() */ +#define VAL_TO_MV(VAL) (((VAL) * 625) / 100 + 600) /* TODO: FIXME, refer to PMIC_VAL_TO_VOLT() */ +#endif +/* offset 0x10(16 steps) for CPU/GPU DVFS */ +#define EEM_PMIC_OFFSET (0x10) + +/* I-Chang */ +#define VMAX_VAL EEM_VOLT_TO_PMIC_VAL(115000) +#define VMIN_VAL EEM_VOLT_TO_PMIC_VAL(80000) +#define VMIN_SRAM EEM_VOLT_TO_PMIC_VAL(93000) +#define VMAX_VAL_GPU EEM_VOLT_TO_PMIC_VAL(112500) +#define VMIN_VAL_GPU EEM_VOLT_TO_PMIC_VAL(90000) +#if 0 +#define VMAX_VAL_SOC EEM_VOLT_TO_PMIC_VAL(125000) +#define VMIN_VAL_SOC EEM_VOLT_TO_PMIC_VAL(115000) +#define VMAX_VAL_LTE EEM_VOLT_TO_PMIC_VAL(105000) +#define VMIN_VAL_LTE EEM_VOLT_TO_PMIC_VAL(93000) +#endif + +#define DTHI_VAL 0x01 /* positive */ +#define DTLO_VAL 0xfe /* negative (2's compliment) */ +#define DETMAX_VAL 0xffff /* This timeout value is in cycles of bclk_ck. */ +#define AGECONFIG_VAL 0x555555 +#define AGEM_VAL 0x0 +#define DVTFIXED_VAL 0x6 +#define DVTFIXED_VAL_GPU 0x4 +#define DVTFIXED_VAL_SOC 0x4 +#define DVTFIXED_VAL_LTE 0x4 +#define VCO_VAL 0x10 +#define VCO_VAL_GPU 0x20 +#define VCO_VAL_SOC 0x28 +#define VCO_VAL_LTE 0x25 +#define DCCONFIG_VAL 0x555555 + +#if defined(CONFIG_EEM_AEE_RR_REC) && !defined(EARLY_PORTING) +static void _mt_eem_aee_init(void) +{ + aee_rr_rec_ptp_cpu_little_volt(0xFFFFFFFFFFFFFFFF); + aee_rr_rec_ptp_cpu_big_volt(0xFFFFFFFFFFFFFFFF); + aee_rr_rec_ptp_gpu_volt(0xFFFFFFFFFFFFFFFF); + aee_rr_rec_ptp_temp(0xFFFFFFFFFFFFFFFF); + aee_rr_rec_ptp_status(0xFF); +} +#endif + +/* + * bit operation + */ +#undef BIT +#define BIT(bit) (1U << (bit)) + +#define MSB(range) (1 ? range) +#define LSB(range) (0 ? range) +/** + * Genearte a mask wher MSB to LSB are all 0b1 + * @r: Range in the form of MSB:LSB + */ +#define BITMASK(r) \ + (((unsigned) -1 >> (31 - MSB(r))) & ~((1U << LSB(r)) - 1)) + +/** + * Set value at MSB:LSB. For example, BITS(7:3, 0x5A) + * will return a value where bit 3 to bit 7 is 0x5A + * @r: Range in the form of MSB:LSB + */ +/* BITS(MSB:LSB, value) => Set value at MSB:LSB */ +#define BITS(r, val) ((val << LSB(r)) & BITMASK(r)) + +#define GET_BITS_VAL(_bits_, _val_) (((_val_) & (BITMASK(_bits_))) >> ((0) ? _bits_)) +/* + * LOG + */ +#ifdef __KERNEL__ +#define EEM_TAG "[xxxx1] " +#ifdef USING_XLOG + #include + #define eem_emerg(fmt, args...) pr_err(ANDROID_LOG_ERROR, EEM_TAG, fmt, ##args) + #define eem_alert(fmt, args...) pr_err(ANDROID_LOG_ERROR, EEM_TAG, fmt, ##args) + #define eem_crit(fmt, args...) pr_err(ANDROID_LOG_ERROR, EEM_TAG, fmt, ##args) + #define eem_error(fmt, args...) pr_err(ANDROID_LOG_ERROR, EEM_TAG, fmt, ##args) + #define eem_warning(fmt, args...) pr_warn(ANDROID_LOG_WARN, EEM_TAG, fmt, ##args) + #define eem_notice(fmt, args...) pr_info(ANDROID_LOG_INFO, EEM_TAG, fmt, ##args) + #define eem_info(fmt, args...) pr_info(ANDROID_LOG_INFO, EEM_TAG, fmt, ##args) + #define eem_debug(fmt, args...) pr_debug(ANDROID_LOG_DEBUG, EEM_TAG, fmt, ##args) +#else + #define eem_emerg(fmt, args...) pr_emerg(EEM_TAG fmt, ##args) + #define eem_alert(fmt, args...) pr_alert(EEM_TAG fmt, ##args) + #define eem_crit(fmt, args...) pr_crit(EEM_TAG fmt, ##args) + #define eem_error(fmt, args...) pr_err(EEM_TAG fmt, ##args) + #define eem_warning(fmt, args...) pr_warn(EEM_TAG fmt, ##args) + #define eem_notice(fmt, args...) pr_notice(EEM_TAG fmt, ##args) + #define eem_info(fmt, args...) pr_info(EEM_TAG fmt, ##args) + #define eem_debug(fmt, args...) /* pr_debug(EEM_TAG fmt, ##args) */ +#endif + + #if EN_ISR_LOG /* For Interrupt use */ + #define eem_isr_info(fmt, args...) eem_debug(fmt, ##args) + #else + #define eem_isr_info(fmt, args...) + #endif +#endif + +#define FUNC_LV_MODULE BIT(0) /* module, platform driver interface */ +#define FUNC_LV_CPUFREQ BIT(1) /* cpufreq driver interface */ +#define FUNC_LV_API BIT(2) /* mt_cpufreq driver global function */ +#define FUNC_LV_LOCAL BIT(3) /* mt_cpufreq driver lcaol function */ +#define FUNC_LV_HELP BIT(4) /* mt_cpufreq driver help function */ + + +#if defined(CONFIG_EEM_SHOWLOG) + static unsigned int func_lv_mask = + (FUNC_LV_MODULE | FUNC_LV_CPUFREQ | FUNC_LV_API | FUNC_LV_LOCAL | FUNC_LV_HELP); + #define FUNC_ENTER(lv) \ + do { if ((lv) & func_lv_mask) eem_debug(">> %s()\n", __func__); } while (0) + #define FUNC_EXIT(lv) \ + do { if ((lv) & func_lv_mask) eem_debug("<< %s():%d\n", __func__, __LINE__); } while (0) +#else + #define FUNC_ENTER(lv) + #define FUNC_EXIT(lv) +#endif /* CONFIG_CPU_DVFS_SHOWLOG */ + +/* + * REG ACCESS + */ +#ifdef __KERNEL__ + #define eem_read(addr) DRV_Reg32(addr) + #define eem_read_field(addr, range) \ + ((eem_read(addr) & BITMASK(range)) >> LSB(range)) + #define eem_write(addr, val) mt_reg_sync_writel(val, addr) +#endif +/** + * Write a field of a register. + * @addr: Address of the register + * @range: The field bit range in the form of MSB:LSB + * @val: The value to be written to the field + */ +#define eem_write_field(addr, range, val) \ + eem_write(addr, (eem_read(addr) & ~BITMASK(range)) | BITS(range, val)) + +/** + * Helper macros + */ + +/* EEM detector is disabled by who */ +enum { + BY_PROCFS = BIT(0), + BY_INIT_ERROR = BIT(1), + BY_MON_ERROR = BIT(2), + BY_PROCFS_INIT2 = BIT(3), + BY_VOLT_SET = BIT(4), + BY_FREQ_SET = BIT(5) +}; + +#ifdef CONFIG_OF +void __iomem *eem_base; +static u32 eem_irq_number; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +void __iomem *eem_apmixed_base; +#endif +#endif + +/** + * iterate over list of detectors + * @det: the detector * to use as a loop cursor. + */ +#define for_each_det(det) for (det = eem_detectors; det < (eem_detectors + ARRAY_SIZE(eem_detectors)); det++) + +/** + * iterate over list of detectors and its controller + * @det: the detector * to use as a loop cursor. + * @ctrl: the eem_ctrl * to use as ctrl pointer of current det. + */ +#define for_each_det_ctrl(det, ctrl) \ + for (det = eem_detectors, \ + ctrl = id_to_eem_ctrl(det->ctrl_id); \ + det < (eem_detectors + ARRAY_SIZE(eem_detectors)); \ + det++, \ + ctrl = id_to_eem_ctrl(det->ctrl_id)) + +/** + * iterate over list of controllers + * @pos: the eem_ctrl * to use as a loop cursor. + */ +#define for_each_ctrl(ctrl) for (ctrl = eem_ctrls; ctrl < (eem_ctrls + ARRAY_SIZE(eem_ctrls)); ctrl++) + +/** + * Given a eem_det * in eem_detectors. Return the id. + * @det: pointer to a eem_det in eem_detectors + */ +#define det_to_id(det) ((det) - &eem_detectors[0]) + +/** + * Given a eem_ctrl * in eem_ctrls. Return the id. + * @det: pointer to a eem_ctrl in eem_ctrls + */ +#define ctrl_to_id(ctrl) ((ctrl) - &eem_ctrls[0]) + +/** + * Check if a detector has a feature + * @det: pointer to a eem_det to be check + * @feature: enum eem_features to be checked + */ +#define HAS_FEATURE(det, feature) ((det)->features & feature) + +#define PERCENT(numerator, denominator) \ + (unsigned char)(((numerator) * 100 + (denominator) - 1) / (denominator)) + +/*============================================================= + * Local type definition + *=============================================================*/ + +/* + * CONFIG (CHIP related) + * EEMCORESEL.APBSEL + */ + +enum eem_phase { + EEM_PHASE_INIT01, + EEM_PHASE_INIT02, + EEM_PHASE_MON, + + NR_EEM_PHASE, +}; + +enum { + EEM_VOLT_NONE = 0, + EEM_VOLT_UPDATE = BIT(0), + EEM_VOLT_RESTORE = BIT(1), +}; + +struct eem_ctrl { + const char *name; + enum eem_det_id det_id; + /* struct completion init_done; */ + /* atomic_t in_init; */ +#ifdef __KERNEL__ + /* for voltage setting thread */ + wait_queue_head_t wq; +#endif + int volt_update; + struct task_struct *thread; +}; + +struct eem_det_ops { + /* interface to EEM */ + void (*enable)(struct eem_det *det, int reason); + void (*disable)(struct eem_det *det, int reason); + void (*disable_locked)(struct eem_det *det, int reason); + void (*switch_bank)(struct eem_det *det); + + int (*init01)(struct eem_det *det); + int (*init02)(struct eem_det *det); + int (*mon_mode)(struct eem_det *det); + + int (*get_status)(struct eem_det *det); + void (*dump_status)(struct eem_det *det); + + void (*set_phase)(struct eem_det *det, enum eem_phase phase); + + /* interface to thermal */ + int (*get_temp)(struct eem_det *det); + + /* interface to DVFS */ + int (*get_volt)(struct eem_det *det); + int (*set_volt)(struct eem_det *det); + void (*restore_default_volt)(struct eem_det *det); + void (*get_freq_table)(struct eem_det *det); +}; + +enum eem_features { + FEA_INIT01 = BIT(EEM_PHASE_INIT01), + FEA_INIT02 = BIT(EEM_PHASE_INIT02), + FEA_MON = BIT(EEM_PHASE_MON), +}; + +struct eem_det { + const char *name; + struct eem_det_ops *ops; + int status; /* TODO: enable/disable */ + int features; /* enum eem_features */ + enum eem_ctrl_id ctrl_id; + + /* devinfo */ + unsigned int EEMINITEN; + unsigned int EEMMONEN; + unsigned int MDES; + unsigned int BDES; + unsigned int DCMDET; + unsigned int DCBDET; + unsigned int AGEDELTA; + unsigned int MTDES; + + /* constant */ + unsigned int DETWINDOW; + unsigned int VMAX; + unsigned int VMIN; + unsigned int DTHI; + unsigned int DTLO; + unsigned int VBOOT; + unsigned int DETMAX; + unsigned int AGECONFIG; + unsigned int AGEM; + unsigned int DVTFIXED; + unsigned int VCO; + unsigned int DCCONFIG; + + /* Generated by EEM init01. Used in EEM init02 */ + unsigned int DCVOFFSETIN; + unsigned int AGEVOFFSETIN; + + /* for debug */ + unsigned int dcvalues[NR_EEM_PHASE]; + + unsigned int eem_freqpct30[NR_EEM_PHASE]; + unsigned int eem_26c[NR_EEM_PHASE]; + unsigned int eem_vop30[NR_EEM_PHASE]; + unsigned int eem_eemen[NR_EEM_PHASE]; + u32 *recordRef; +#if DUMP_DATA_TO_DE + unsigned int reg_dump_data[ARRAY_SIZE(reg_dump_addr_off)][NR_EEM_PHASE]; +#endif + /* slope */ + unsigned int MTS; + unsigned int BTS; + unsigned int t250; + /* dvfs */ + unsigned int num_freq_tbl; /* could be got @ the same time + with freq_tbl[] */ + unsigned int max_freq_khz; /* maximum frequency used to + calculate percentage */ + unsigned char freq_tbl[NR_FREQ]; /* percentage to maximum freq */ + + unsigned int volt_tbl[NR_FREQ]; /* pmic value */ + unsigned int volt_tbl_init2[NR_FREQ]; /* pmic value */ + unsigned int volt_tbl_pmic[NR_FREQ]; /* pmic value */ + unsigned int volt_tbl_bin[NR_FREQ]; /* pmic value */ + int volt_offset; + int pi_offset; + + unsigned int disabled; /* Disabled by error or sysfs */ +}; + + +struct eem_devinfo { + /* EEM0 0x10206660 */ + unsigned int CPU0_BDES:8; + unsigned int CPU0_MDES:8; + unsigned int CPU0_DCBDET:8; + unsigned int CPU0_DCMDET:8; + + /* EEM1 0x10206664 */ + unsigned int CPU1_MTDES:8; + unsigned int CPU1_AGEDELTA:8; + unsigned int CPU0_MTDES:8; + unsigned int CPU0_AGEDELTA:8; + + /* EEM2 0x10206668 */ + unsigned int CPU1_BDES:8; + unsigned int CPU1_MDES:8; + unsigned int CPU1_DCBDET:8; + unsigned int CPU1_DCMDET:8; + + /* EEM3 0x1020666C */ + unsigned int GPU_BDES:8; + unsigned int GPU_MDES:8; + unsigned int GPU_DCBDET:8; + unsigned int GPU_DCMDET:8; + + /* EEM4 0x10206670 */ + unsigned int OD4_RESERVED:16; + unsigned int GPU_MTDES:8; + unsigned int GPU_AGEDELTA:8; + + /* M_SRM_RP5 0x10206274 */ + unsigned int RP5_RESERVED:8; + unsigned int GPU_LEAKAGE:8; + unsigned int CPU1_LEAKAGE:8; + unsigned int CPU0_LEAKAGE:8; + + /* M_SRM_RP6 0x10206278 */ + unsigned int FT_PGM:4; + unsigned int CPU0_SPEC:3; + unsigned int CPU0_TURBO:1; + unsigned int CPU0_DVFS:2; + unsigned int CPU1_SPEC:3; + unsigned int CPU1_DVFS:2; + unsigned int CPU1_TURBO:1; + unsigned int PR6_RESERVED:16; + + unsigned int EEMINITEN:8; + unsigned int EEMMONEN:8; + unsigned int RESERVED:16; +#if 0 + /* M_SRM_RP5 */ + unsigned int SOC_MTDES:8; + unsigned int SOC_AGEDELTA:8; + + /* M_SRM_RP6 */ + unsigned int SOC_BDES:8; + unsigned int SOC_MDES:8; + unsigned int SOC_DCBDET:8; + unsigned int SOC_DCMDET:8; +#endif +}; + +/*============================================================= + *Local variable definition + *=============================================================*/ + +#ifdef __KERNEL__ +/* + * lock + */ +static DEFINE_SPINLOCK(eem_spinlock); +static DEFINE_MUTEX(record_mutex); + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* CPU callback */ + static int __cpuinit _mt_eem_cpu_CB(struct notifier_block *nfb, + unsigned long action, void *hcpu); + static struct notifier_block __refdata _mt_eem_cpu_notifier = { + .notifier_call = _mt_eem_cpu_CB, + }; + #endif +#endif +/** + * EEM controllers + */ +struct eem_ctrl eem_ctrls[NR_EEM_CTRL] = { + [EEM_CTRL_LITTLE] = { + .name = __stringify(EEM_CTRL_LITTLE), + .det_id = EEM_DET_LITTLE, + }, + + [EEM_CTRL_GPU] = { + .name = __stringify(EEM_CTRL_GPU), + .det_id = EEM_DET_GPU, + }, + + [EEM_CTRL_BIG] = { + .name = __stringify(EEM_CTRL_BIG), + .det_id = EEM_DET_BIG, + }, + #if 0 + [EEM_CTRL_SOC] = { + .name = __stringify(EEM_CTRL_SOC), + .det_id = EEM_DET_SOC, + }, + #endif +}; + +/* + * EEM detectors + */ +static void base_ops_enable(struct eem_det *det, int reason); +static void base_ops_disable(struct eem_det *det, int reason); +static void base_ops_disable_locked(struct eem_det *det, int reason); +static void base_ops_switch_bank(struct eem_det *det); + +static int base_ops_init01(struct eem_det *det); +static int base_ops_init02(struct eem_det *det); +static int base_ops_mon_mode(struct eem_det *det); + +static int base_ops_get_status(struct eem_det *det); +static void base_ops_dump_status(struct eem_det *det); + +static void base_ops_set_phase(struct eem_det *det, enum eem_phase phase); +static int base_ops_get_temp(struct eem_det *det); +static int base_ops_get_volt(struct eem_det *det); +static int base_ops_set_volt(struct eem_det *det); +static void base_ops_restore_default_volt(struct eem_det *det); +static void base_ops_get_freq_table(struct eem_det *det); + +static int get_volt_cpu(struct eem_det *det); +static int set_volt_cpu(struct eem_det *det); +static void restore_default_volt_cpu(struct eem_det *det); +static void get_freq_table_cpu(struct eem_det *det); + +static int get_volt_gpu(struct eem_det *det); +static int set_volt_gpu(struct eem_det *det); +static void restore_default_volt_gpu(struct eem_det *det); +static void get_freq_table_gpu(struct eem_det *det); + +#if 0 +static int get_volt_lte(struct eem_det *det); +static int set_volt_lte(struct eem_det *det); +static void restore_default_volt_lte(struct eem_det *det); + +static int get_volt_vcore(struct eem_det *det); +#ifndef __KERNEL__ +static int set_volt_vcore(struct eem_det *det); +#endif + +static void switch_to_vcore_ao(struct eem_det *det); +static void switch_to_vcore_pdn(struct eem_det *det); +#endif + +#define BASE_OP(fn) .fn = base_ops_ ## fn +static struct eem_det_ops eem_det_base_ops = { + BASE_OP(enable), + BASE_OP(disable), + BASE_OP(disable_locked), + BASE_OP(switch_bank), + + BASE_OP(init01), + BASE_OP(init02), + BASE_OP(mon_mode), + + BASE_OP(get_status), + BASE_OP(dump_status), + + BASE_OP(set_phase), + + BASE_OP(get_temp), + + BASE_OP(get_volt), + BASE_OP(set_volt), + BASE_OP(restore_default_volt), + BASE_OP(get_freq_table), +}; + +static struct eem_det_ops little_det_ops = { /* I-Chang */ + .get_volt = get_volt_cpu, + .set_volt = set_volt_cpu, + .restore_default_volt = restore_default_volt_cpu, + .get_freq_table = get_freq_table_cpu, +}; + +static struct eem_det_ops gpu_det_ops = { + .get_volt = get_volt_gpu, + .set_volt = set_volt_gpu, /* <-@@@ */ + .restore_default_volt = restore_default_volt_gpu, + .get_freq_table = get_freq_table_gpu, +}; + +static struct eem_det_ops big_det_ops = { /* I-Chang */ + .get_volt = get_volt_cpu, + .set_volt = set_volt_cpu, /* <-@@@ */ + .restore_default_volt = restore_default_volt_cpu, + .get_freq_table = get_freq_table_cpu, +}; +#if 0 +static struct eem_det_ops lte_det_ops = { + .get_volt = get_volt_lte, + .set_volt = set_volt_lte, + .restore_default_volt = restore_default_volt_lte, + .get_freq_table = NULL, +}; + +static struct eem_det_ops soc_det_ops = { + .get_volt = get_volt_vcore, /* <-@@@@@@@@@@@@ */ +#ifndef __KERNEL__ + .set_volt = set_volt_vcore, /* <-@@@@@@@@@@@@ */ +#else + .set_volt = NULL, +#endif + .restore_default_volt = NULL, /* <-@@@@@@@@@@@@ */ + .get_freq_table = NULL, +}; +#endif + +static struct eem_det eem_detectors[NR_EEM_DET] = { + [EEM_DET_LITTLE] = { + .name = __stringify(EEM_DET_LITTLE), + .ops = &little_det_ops, + .ctrl_id = EEM_CTRL_LITTLE, + .features = FEA_INIT01 | FEA_INIT02 | FEA_MON, + .max_freq_khz = 1144000,/* 1144 MHz */ + .VBOOT = EEM_VOLT_TO_PMIC_VAL(100000), /* 1.0v: 0x30 */ + .volt_offset = 0, + }, + + [EEM_DET_GPU] = { + .name = __stringify(EEM_DET_GPU), + .ops = &gpu_det_ops, + .ctrl_id = EEM_CTRL_GPU, + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + .features = 0, + #else + .features = FEA_INIT01 | FEA_INIT02 | FEA_MON, + #endif + .max_freq_khz = 728000,/* 728 MHz */ + .VBOOT = EEM_VOLT_TO_PMIC_VAL(100000), /* 1.0v: 0x30 */ + .volt_offset = 0, + }, + + [EEM_DET_BIG] = { + .name = __stringify(EEM_DET_BIG), + .ops = &big_det_ops, + .ctrl_id = EEM_CTRL_BIG, + .features = FEA_INIT01 | FEA_INIT02 | FEA_MON, + .max_freq_khz = 1950000,/* 1950Mhz */ + .VBOOT = EEM_VOLT_TO_PMIC_VAL(100000), /* 1.0v: 0x30 */ + .volt_offset = 0, + }, + #if 0 + [EEM_DET_SOC] = { + .name = __stringify(EEM_DET_SOC), + .ops = &soc_det_ops, + .ctrl_id = EEM_CTRL_SOC, + #if !defined(__MTK_SLT_) + .features = FEA_INIT01 | FEA_INIT02 | FEA_MON, + #else + .features = FEA_INIT01 | FEA_INIT02, + #endif + .max_freq_khz = 1866000, + .VBOOT = EEM_VOLT_TO_PMIC_VAL(100000), /* 1.0v: 0x30 */ + .volt_offset = 0, + }, + + [EEM_DET_LTE] = { + .name = __stringify(EEM_DET_LTE), + .ops = <e_det_ops, + .ctrl_id = EEM_CTRL_LTE, + #if !defined(__MTK_SLT_) + .features = FEA_INIT01 | FEA_INIT02 | FEA_MON, + #else + .features = FEA_INIT01 | FEA_INIT02, + #endif + .max_freq_khz = 300000, + .VBOOT = EEM_VOLT_TO_PMIC_VAL(105000), /* 1.0v: 0x30 */ + .volt_offset = 0, + }, + #endif +}; + +static struct eem_devinfo eem_devinfo; +/* static unsigned int eem_level; debug info */ + +#ifdef __KERNEL__ +/** + * timer for log + */ +static struct hrtimer eem_log_timer; +#endif + +/*============================================================= + * Local function definition + *=============================================================*/ + +static struct eem_det *id_to_eem_det(enum eem_det_id id) +{ + if (likely(id < NR_EEM_DET)) + return &eem_detectors[id]; + else + return NULL; +} + +static struct eem_ctrl *id_to_eem_ctrl(enum eem_ctrl_id id) +{ + if (likely(id < NR_EEM_CTRL)) + return &eem_ctrls[id]; + else + return NULL; +} + +static void base_ops_enable(struct eem_det *det, int reason) +{ + /* FIXME: UNDER CONSTRUCTION */ + FUNC_ENTER(FUNC_LV_HELP); + det->disabled &= ~reason; + FUNC_EXIT(FUNC_LV_HELP); +} + +static void base_ops_switch_bank(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + eem_write_field(EEMCORESEL, 2:0, det->ctrl_id); + FUNC_EXIT(FUNC_LV_HELP); +} + +static void base_ops_disable_locked(struct eem_det *det, int reason) +{ + FUNC_ENTER(FUNC_LV_HELP); + + switch (reason) { + case BY_MON_ERROR: + /* disable EEM */ + eem_write(EEMEN, 0x0); + + /* Clear EEM interrupt EEMINTSTS */ + eem_write(EEMINTSTS, 0x00ffffff); + /* fall through */ + + case BY_PROCFS_INIT2: + /* set init2 value to DVFS table (PMIC) */ + memcpy(det->volt_tbl, det->volt_tbl_init2, sizeof(det->volt_tbl_init2)); + eem_set_eem_volt(det); + det->disabled |= reason; + break; + + case BY_INIT_ERROR: + /* disable EEM */ + eem_write(EEMEN, 0x0); + + /* Clear EEM interrupt EEMINTSTS */ + eem_write(EEMINTSTS, 0x00ffffff); + /* fall through */ + + case BY_PROCFS: + det->disabled |= reason; + /* restore default DVFS table (PMIC) */ + eem_restore_eem_volt(det); + break; + + default: + det->disabled &= ~BY_PROCFS; + det->disabled &= ~BY_PROCFS_INIT2; + eem_set_eem_volt(det); + break; + } + + eem_debug("Disable EEM[%s] done. reason=[%d]\n", det->name, det->disabled); + + FUNC_EXIT(FUNC_LV_HELP); +} + +static void base_ops_disable(struct eem_det *det, int reason) +{ + unsigned long flags; + + FUNC_ENTER(FUNC_LV_HELP); + + mt_ptp_lock(&flags); + det->ops->switch_bank(det); + det->ops->disable_locked(det, reason); + mt_ptp_unlock(&flags); + + FUNC_EXIT(FUNC_LV_HELP); +} + +static int base_ops_init01(struct eem_det *det) +{ + /* struct eem_ctrl *ctrl = id_to_eem_ctrl(det->ctrl_id); */ + + FUNC_ENTER(FUNC_LV_HELP); + + if (unlikely(!HAS_FEATURE(det, FEA_INIT01))) { + eem_debug("det %s has no INIT01\n", det->name); + FUNC_EXIT(FUNC_LV_HELP); + return -1; + } + + /* + if (det->disabled & BY_PROCFS) { + eem_debug("[%s] Disabled by PROCFS\n", __func__); + FUNC_EXIT(FUNC_LV_HELP); + return -2; + } + */ + + /* eem_debug("%s(%s) start (eem_level = 0x%08X).\n", __func__, det->name, eem_level); */ + /* atomic_inc(&ctrl->in_init); */ + /* eem_init01_prepare(det); */ + /* det->ops->dump_status(det); */ + det->ops->set_phase(det, EEM_PHASE_INIT01); + + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +static int base_ops_init02(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + + if (unlikely(!HAS_FEATURE(det, FEA_INIT02))) { + eem_debug("det %s has no INIT02\n", det->name); + FUNC_EXIT(FUNC_LV_HELP); + return -1; + } + + /* + if (det->disabled & BY_PROCFS) { + eem_debug("[%s] Disabled by PROCFS\n", __func__); + FUNC_EXIT(FUNC_LV_HELP); + return -2; + } + eem_debug("%s(%s) start (eem_level = 0x%08X).\n", __func__, det->name, eem_level); + eem_debug("DCV = 0x%08X, AGEV = 0x%08X\n", det->DCVOFFSETIN, det->AGEVOFFSETIN); + */ + + /* det->ops->dump_status(det); */ + det->ops->set_phase(det, EEM_PHASE_INIT02); + + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +static int base_ops_mon_mode(struct eem_det *det) +{ + #ifndef EARLY_PORTING + struct TS_PTPOD ts_info; + thermal_bank_name ts_bank; + #endif + + FUNC_ENTER(FUNC_LV_HELP); + + if (!HAS_FEATURE(det, FEA_MON)) { + eem_debug("det %s has no MON mode\n", det->name); + FUNC_EXIT(FUNC_LV_HELP); + return -1; + } + + /* + if (det->disabled & BY_PROCFS) { + eem_debug("[%s] Disabled by PROCFS\n", __func__); + FUNC_EXIT(FUNC_LV_HELP); + return -2; + } + eem_debug("%s(%s) start (eem_level = 0x%08X).\n", __func__, det->name, eem_level); + */ + +#if !defined(EARLY_PORTING) + ts_bank = det->ctrl_id; + get_thermal_slope_intercept(&ts_info, ts_bank);/* I-Chang */ + det->MTS = ts_info.ts_MTS;/* I-Chang */ + det->BTS = ts_info.ts_BTS;/* I-Chang */ +#else + det->MTS = 0x2cf; /* (2048 * TS_SLOPE) + 2048; */ + det->BTS = 0x80E; /* 4 * TS_INTERCEPT; */ +#endif + eem_debug("MTS = %d, BTS = %d\n", det->MTS, det->BTS); + if ((det->EEMINITEN == 0x0) || (det->EEMMONEN == 0x0)) { + eem_debug("EEMINITEN = 0x%08X, EEMMONEN = 0x%08X\n", det->EEMINITEN, det->EEMMONEN); + FUNC_EXIT(FUNC_LV_HELP); + return 1; + } + + /* det->ops->dump_status(det); */ + det->ops->set_phase(det, EEM_PHASE_MON); + + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +static int base_ops_get_status(struct eem_det *det) +{ + int status; + unsigned long flags; + + FUNC_ENTER(FUNC_LV_HELP); + + mt_ptp_lock(&flags); + det->ops->switch_bank(det); + status = (eem_read(EEMEN) != 0) ? 1 : 0; + mt_ptp_unlock(&flags); + + FUNC_EXIT(FUNC_LV_HELP); + + return status; +} + +static void base_ops_dump_status(struct eem_det *det) +{ + unsigned int i; + + FUNC_ENTER(FUNC_LV_HELP); + + eem_isr_info("[%s]\n", det->name); + + eem_isr_info("EEMINITEN = 0x%08X\n", det->EEMINITEN); + eem_isr_info("EEMMONEN = 0x%08X\n", det->EEMMONEN); + eem_isr_info("MDES = 0x%08X\n", det->MDES); + eem_isr_info("BDES = 0x%08X\n", det->BDES); + eem_isr_info("DCMDET = 0x%08X\n", det->DCMDET); + + eem_isr_info("DCCONFIG = 0x%08X\n", det->DCCONFIG); + eem_isr_info("DCBDET = 0x%08X\n", det->DCBDET); + + eem_isr_info("AGECONFIG = 0x%08X\n", det->AGECONFIG); + eem_isr_info("AGEM = 0x%08X\n", det->AGEM); + + eem_isr_info("AGEDELTA = 0x%08X\n", det->AGEDELTA); + eem_isr_info("DVTFIXED = 0x%08X\n", det->DVTFIXED); + eem_isr_info("MTDES = 0x%08X\n", det->MTDES); + eem_isr_info("VCO = 0x%08X\n", det->VCO); + + eem_isr_info("DETWINDOW = 0x%08X\n", det->DETWINDOW); + eem_isr_info("VMAX = 0x%08X\n", det->VMAX); + eem_isr_info("VMIN = 0x%08X\n", det->VMIN); + eem_isr_info("DTHI = 0x%08X\n", det->DTHI); + eem_isr_info("DTLO = 0x%08X\n", det->DTLO); + eem_isr_info("VBOOT = 0x%08X\n", det->VBOOT); + eem_isr_info("DETMAX = 0x%08X\n", det->DETMAX); + + eem_isr_info("DCVOFFSETIN = 0x%08X\n", det->DCVOFFSETIN); + eem_isr_info("AGEVOFFSETIN = 0x%08X\n", det->AGEVOFFSETIN); + + eem_isr_info("MTS = 0x%08X\n", det->MTS); + eem_isr_info("BTS = 0x%08X\n", det->BTS); + + eem_isr_info("num_freq_tbl = %d\n", det->num_freq_tbl); + + for (i = 0; i < det->num_freq_tbl; i++) + eem_isr_info("freq_tbl[%d] = %d\n", i, det->freq_tbl[i]); + + for (i = 0; i < det->num_freq_tbl; i++) + eem_isr_info("volt_tbl[%d] = %d\n", i, det->volt_tbl[i]); + + for (i = 0; i < det->num_freq_tbl; i++) + eem_isr_info("volt_tbl_init2[%d] = %d\n", i, det->volt_tbl_init2[i]); + + for (i = 0; i < det->num_freq_tbl; i++) + eem_isr_info("volt_tbl_pmic[%d] = %d\n", i, det->volt_tbl_pmic[i]); + + FUNC_EXIT(FUNC_LV_HELP); +} + +static void base_ops_set_phase(struct eem_det *det, enum eem_phase phase) +{ + unsigned int i, filter, val; + /* unsigned long flags; */ + + FUNC_ENTER(FUNC_LV_HELP); + + /* mt_ptp_lock(&flags); */ + + det->ops->switch_bank(det); + /* config EEM register */ + eem_write(DESCHAR, + ((det->BDES << 8) & 0xff00) | (det->MDES & 0xff)); + eem_write(TEMPCHAR, + (((det->VCO << 16) & 0xff0000) | + ((det->MTDES << 8) & 0xff00) | (det->DVTFIXED & 0xff))); + eem_write(DETCHAR, + ((det->DCBDET << 8) & 0xff00) | (det->DCMDET & 0xff)); + eem_write(AGECHAR, + ((det->AGEDELTA << 8) & 0xff00) | (det->AGEM & 0xff)); + eem_write(EEM_DCCONFIG, det->DCCONFIG); + eem_write(EEM_AGECONFIG, det->AGECONFIG); + + if (EEM_PHASE_MON == phase) + eem_write(TSCALCS, + ((det->BTS << 12) & 0xfff000) | (det->MTS & 0xfff)); + + if (det->AGEM == 0x0) + eem_write(RUNCONFIG, 0x80000000); + else { + val = 0x0; + + for (i = 0; i < 24; i += 2) { + filter = 0x3 << i; + + if (((det->AGECONFIG) & filter) == 0x0) + val |= (0x1 << i); + else + val |= ((det->AGECONFIG) & filter); + } + + eem_write(RUNCONFIG, val); + } + + eem_write(FREQPCT30, + ((det->freq_tbl[3] << 24) & 0xff000000) | + ((det->freq_tbl[2] << 16) & 0xff0000) | + ((det->freq_tbl[1] << 8) & 0xff00) | + (det->freq_tbl[0] & 0xff)); + eem_write(FREQPCT74, + ((det->freq_tbl[7] << 24) & 0xff000000) | + ((det->freq_tbl[6] << 16) & 0xff0000) | + ((det->freq_tbl[5] << 8) & 0xff00) | + ((det->freq_tbl[4]) & 0xff)); + eem_write(LIMITVALS, + ((det->VMAX << 24) & 0xff000000) | + ((det->VMIN << 16) & 0xff0000) | + ((det->DTHI << 8) & 0xff00) | + (det->DTLO & 0xff)); + /* eem_write(LIMITVALS, 0xFF0001FE); */ + eem_write(EEM_VBOOT, (((det->VBOOT) & 0xff))); + eem_write(EEM_DETWINDOW, (((det->DETWINDOW) & 0xffff))); + eem_write(EEMCONFIG, (((det->DETMAX) & 0xffff))); + + /* clear all pending EEM interrupt & config EEMINTEN */ + eem_write(EEMINTSTS, 0xffffffff); + + eem_debug("%s phase = %d\n", ((char *)(det->name) + 8), phase); + switch (phase) { + case EEM_PHASE_INIT01: + eem_write(EEMINTEN, 0x00005f01); + /* enable EEM INIT measurement */ + eem_write(EEMEN, 0x00000001); + break; + + case EEM_PHASE_INIT02: + eem_write(EEMINTEN, 0x00005f01); + eem_write(INIT2VALS, + ((det->AGEVOFFSETIN << 16) & 0xffff0000) | + (det->DCVOFFSETIN & 0xffff)); + /* enable EEM INIT measurement */ + eem_write(EEMEN, 0x00000005); + break; + + case EEM_PHASE_MON: + eem_write(EEMINTEN, 0x00FF0000); + /* enable EEM monitor mode */ + eem_write(EEMEN, 0x00000002); + break; + + default: + BUG(); + break; + } + + /* mt_ptp_unlock(&flags); */ + + FUNC_EXIT(FUNC_LV_HELP); +} + +static int base_ops_get_temp(struct eem_det *det) +{ + thermal_bank_name ts_bank; +#if 1 /* TODO: FIXME */ + FUNC_ENTER(FUNC_LV_HELP); + /* THERMAL_BANK0 = 0, */ /* CPU0 */ + /* THERMAL_BANK2 = 1, */ /* GPU/SOC */ + /* THERMAL_BANK1 = 2, */ /* CPU1 */ + + ts_bank = (det_to_id(det) == EEM_DET_LITTLE) ? THERMAL_BANK0 : + (det_to_id(det) == EEM_DET_BIG) ? THERMAL_BANK2 : + THERMAL_BANK1; + + FUNC_EXIT(FUNC_LV_HELP); +#endif + +#if !defined(EARLY_PORTING) + #ifdef __KERNEL__ + return tscpu_get_temp_by_bank(ts_bank); + #else + thermal_init(); + udelay(1000); + return mtktscpu_get_hw_temp(); + #endif +#else + return 0; +#endif +} + +static int base_ops_get_volt(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + eem_debug("[%s] default func\n", __func__); + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +static int base_ops_set_volt(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + eem_debug("[%s] default func\n", __func__); + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +static void base_ops_restore_default_volt(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + eem_debug("[%s] default func\n", __func__); + FUNC_EXIT(FUNC_LV_HELP); +} + +static void base_ops_get_freq_table(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + + det->freq_tbl[0] = 100; + det->num_freq_tbl = 1; + + FUNC_EXIT(FUNC_LV_HELP); +} + +static void record(struct eem_det *det) +{ + int i; + unsigned int vSram; + + det->recordRef[NR_FREQ * 2] = 0x00000000; + mb(); /* SRAM writing */ + for (i = 0; i < NR_FREQ; i++) { + vSram = clamp((unsigned int)(record_tbl_locked[i] + 0x10), + (unsigned int)(VMIN_SRAM + EEM_PMIC_OFFSET), + (unsigned int)(det->VMAX + EEM_PMIC_OFFSET)); + + det->recordRef[i*2] = (det->recordRef[i*2] & (~0x3FFF)) | + ((((vSram & 0x7F) << 7) | (record_tbl_locked[i] & 0x7F)) & 0x3fff); + } + det->recordRef[NR_FREQ * 2] = 0xFFFFFFFF; + mb(); /* SRAM writing */ +} + +static void restore_record(struct eem_det *det) +{ + int i; + + det->recordRef[NR_FREQ * 2] = 0x00000000; + mb(); /* SRAM writing */ + for (i = 0; i < NR_FREQ; i++) { + if (det_to_id(det) == EEM_DET_LITTLE) + det->recordRef[i*2] = (det->recordRef[i*2] & (~0x3FFF)) | + (((*(recordTbl + (i * 9) + 7) & 0x7F) << 7) | + (*(recordTbl + (i * 9) + 8) & 0x7F)); + else if (det_to_id(det) == EEM_DET_BIG) + det->recordRef[i*2] = (det->recordRef[i*2] & (~0x3FFF)) | + (((*(recordTbl + (i + 8) * 9 + 7) & 0x7F) << 7) | + (*(recordTbl + (i + 8) * 9 + 8) & 0x7F)); + } + det->recordRef[NR_FREQ * 2] = 0xFFFFFFFF; + mb(); /* SRAM writing */ +} + +static void mt_cpufreq_set_ptbl_funcEEM(enum mt_cpu_dvfs_id id, int restore) +{ + struct eem_det *det = id_to_eem_det((id == MT_CPU_DVFS_LITTLE) ? EEM_CTRL_LITTLE : EEM_CTRL_BIG); + if (restore) + restore_record(det); + else + record(det); +} + +/* Will return 10uV */ +static int get_volt_cpu(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + FUNC_EXIT(FUNC_LV_HELP); + #ifdef EARLY_PORTING + return 0; + #else + /* unit mv * 100 = 10uv */ /* I-Chang */ + return mt_cpufreq_get_cur_volt( + (det_to_id(det) == EEM_DET_LITTLE) ? + MT_CPU_DVFS_LITTLE : MT_CPU_DVFS_BIG); + #endif +} + +#if defined(__MTK_SLT_) && (defined(SLT_VMAX) || defined(SLT_VMIN)) + #define EEM_PMIC_LV_HV_OFFSET (0x3) + #define EEM_PMIC_NV_OFFSET (0xB) +#endif +/* volt_tbl_pmic is convert from 10uV */ +static int set_volt_cpu(struct eem_det *det) +{ + int value = 0; + + FUNC_ENTER(FUNC_LV_HELP); + FUNC_EXIT(FUNC_LV_HELP); +#if defined(__MTK_SLT_) + #if defined(SLT_VMAX) + det->volt_tbl_pmic[0] = det->volt_tbl_pmic[0] - EEM_PMIC_NV_OFFSET + EEM_PMIC_LV_HV_OFFSET; + eem_debug("VPROC voltage EEM to 0x%X\n", det->volt_tbl_pmic[0]); + #elif defined(SLT_VMIN) + det->volt_tbl_pmic[0] = det->volt_tbl_pmic[0] - EEM_PMIC_NV_OFFSET - EEM_PMIC_LV_HV_OFFSET; + eem_debug("VPROC voltage EEM to 0x%X\n", det->volt_tbl_pmic[0]); + #else + /* det->volt_tbl_pmic[0] = det->volt_tbl_pmic[0] - EEM_PMIC_NV_OFFSET; */ + eem_debug("NV VPROC voltage EEM to 0x%X\n", det->volt_tbl_pmic[0]); + #endif +#endif + eem_debug("init02_vop_30 = 0x%x\n", det->eem_vop30[EEM_PHASE_INIT02]); + + #ifdef EARLY_PORTING + return value; + #else + #ifdef __KERNEL__ + /* record(det); */ + mutex_lock(&record_mutex); + #endif + + for (value = 0; value < NR_FREQ; value++) + record_tbl_locked[value] = det->volt_tbl_pmic[value]; + + value = mt_cpufreq_update_volt( + (det_to_id(det) == EEM_DET_LITTLE) ? + MT_CPU_DVFS_LITTLE : MT_CPU_DVFS_BIG, + record_tbl_locked, det->num_freq_tbl); + + #ifdef __KERNEL__ + mutex_unlock(&record_mutex); + #endif + + return value; + #endif +} + +static void restore_default_volt_cpu(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + + #ifndef EARLY_PORTING + /* I-Chang */ + #ifdef __KERNEL__ + /* restore_record(det); */ + #endif + mt_cpufreq_restore_default_volt( + (det_to_id(det) == EEM_DET_LITTLE) ? + MT_CPU_DVFS_LITTLE : MT_CPU_DVFS_BIG); + #endif + + FUNC_EXIT(FUNC_LV_HELP); +} + + +static void get_freq_table_cpu(struct eem_det *det) +{ + int i; + unsigned int binLevel, binLevel_eng; + #if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + unsigned int freq_bound; + #endif + #ifndef EARLY_PORTING + enum mt_cpu_dvfs_id cpu; + + FUNC_ENTER(FUNC_LV_HELP); + cpu = (det_to_id(det) == EEM_DET_LITTLE) ? + MT_CPU_DVFS_LITTLE : MT_CPU_DVFS_BIG; + #endif + + /* det->max_freq_khz = mt_cpufreq_get_freq_by_idx(cpu, 0); */ + #ifdef __KERNEL__ + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + binLevel = 1; + cpuBinLevel = binLevel; + cpuBinLevel_eng = 0x20; + #else + binLevel = GET_BITS_VAL(7:0, get_devinfo_with_index(21)); + binLevel_eng = GET_BITS_VAL(15:0, get_devinfo_with_index(19)); + freq_bound = GET_BITS_VAL(25:23, get_devinfo_with_index(4)); + #endif + #else + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + binLevel = 1; + #else + binLevel = GET_BITS_VAL(7:0, eem_read(0x1020627C)); + binLevel_eng = GET_BITS_VAL(15:0, eem_read(0x10206278)); + freq_bound = GET_BITS_VAL(25:23, eem_read(0x10206044)); + #endif + #endif + + for (i = 0; i < NR_FREQ; i++) { + #ifdef EARLY_PORTING + det->freq_tbl[i] = + PERCENT((det_to_id(det) == EEM_DET_LITTLE) ? littleFreq_SB[i] : bigFreq_SB[i], + det->max_freq_khz); + #else + /* I-Chang */ + /* det->freq_tbl[i] = PERCENT(mt_cpufreq_get_freq_by_idx(cpu, i), det->max_freq_khz); */ + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (0) { + #else + if (1001 == cpu_speed) { + #endif + det->freq_tbl[i] = + PERCENT((det_to_id(det) == EEM_DET_LITTLE) ? littleFreq_FY[i] : + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + bigFreq_FY[i], + #else + ((freq_bound == 5) ? bigFreq_FY_M[i] : bigFreq_FY[i]), + #endif + det->max_freq_khz); + /* eem_error("2--->Get cpu speed from Device tree = %d\n", cpu_speed); */ + } else { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (1 == binLevel) { + #else + if ((1 == binLevel) || (3 == binLevel)) { + #endif + det->freq_tbl[i] = + PERCENT((det_to_id(det) == EEM_DET_LITTLE) ? littleFreq_FY[i] : + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + bigFreq_FY[i], + #else + ((freq_bound == 5) ? bigFreq_FY_M[i] : bigFreq_FY[i]), + #endif + det->max_freq_khz); + } else if ((2 == binLevel) || (4 == binLevel)) { + det->freq_tbl[i] = + PERCENT((det_to_id(det) == EEM_DET_LITTLE) ? littleFreq_SB[i] : bigFreq_SB[i], + det->max_freq_khz); +#ifdef CONFIG_ARCH_MT6755_TURBO + } else if (0x22 == binLevel) { + det->freq_tbl[i] = + PERCENT((det_to_id(det) == EEM_DET_LITTLE) ? littleFreq_P15[i] : bigFreq_P15[i], + det->max_freq_khz); +#endif + } else { + if ((2 == ((binLevel_eng >> 4) & 0x07)) || + (2 == ((binLevel_eng >> 10) & 0x07))) { + det->freq_tbl[i] = + PERCENT( + (det_to_id(det) == EEM_DET_LITTLE) ? + littleFreq_FY[i] : + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + bigFreq_FY[i], + #else + ((freq_bound == 5) ? bigFreq_FY_M[i] : bigFreq_FY[i]), + #endif + det->max_freq_khz); + } else { + det->freq_tbl[i] = + PERCENT( + (det_to_id(det) == EEM_DET_LITTLE) ? + littleFreq_SB[i] : + bigFreq_SB[i], + det->max_freq_khz); + } + } + } + #endif + if (0 == det->freq_tbl[i]) + break; + } + + det->num_freq_tbl = i; + + FUNC_EXIT(FUNC_LV_HELP); +} + +static int get_volt_gpu(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + FUNC_EXIT(FUNC_LV_HELP); + + /* eem_debug("get_volt_gpu=%d\n",mt_gpufreq_get_cur_volt()); */ + #ifdef EARLY_PORTING + return 0; /* gpu_dvfs_get_cur_volt(); Ask gpu owner */ + #else + #if defined(__MTK_SLT_) + return gpu_dvfs_get_cur_volt(); + #else + return mt_gpufreq_get_cur_volt(); /* unit mv * 100 = 10uv */ + #endif + #endif +} + +static int set_volt_gpu(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + FUNC_EXIT(FUNC_LV_HELP); + /* + eem_debug("set_volt_gpu=%x %x %x %x\n", + det->volt_tbl_pmic[0], + det->volt_tbl_pmic[1], + det->volt_tbl_pmic[2], + det->volt_tbl_pmic[3]); + */ + #ifdef EARLY_PORTING + return 0; + #else + return mt_gpufreq_update_volt(det->volt_tbl_pmic, det->num_freq_tbl); + #endif +} + +static void restore_default_volt_gpu(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + #if !defined(EARLY_PORTING) + mt_gpufreq_restore_default_volt(); + #endif + FUNC_EXIT(FUNC_LV_HELP); +} + +static void get_freq_table_gpu(struct eem_det *det) +{ + int i; + + FUNC_ENTER(FUNC_LV_HELP); + + for (i = 0; i < NR_FREQ; i++) { + #ifdef EARLY_PORTING + det->freq_tbl[i] = PERCENT(gpuFreq[i], det->max_freq_khz); + #else + det->freq_tbl[i] = PERCENT(mt_gpufreq_get_freq_by_idx(i), det->max_freq_khz); + #endif + if (0 == det->freq_tbl[i]) + break; + } + + FUNC_EXIT(FUNC_LV_HELP); + + det->num_freq_tbl = i; +} + +#if 0 +static int set_volt_lte(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); +#ifdef __KERNEL__ + return mt_cpufreq_set_lte_volt(det->volt_tbl_init2[0]); +#else + return 0; + /* return dvfs_set_vlte(det->volt_tbl_bin[0]); */ + /* return dvfs_set_vlte(det->volt_tbl_init2[0]); */ +#endif + FUNC_EXIT(FUNC_LV_HELP); +} + +static int get_volt_lte(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + return mt_get_cur_volt_lte(); /* unit mv * 100 = 10uv */ + FUNC_EXIT(FUNC_LV_HELP); +} + +static void restore_default_volt_lte(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); +#ifdef __KERNEL__ + if (0x337 == mt_get_chip_hw_code()) + mt_cpufreq_set_lte_volt(EEM_VOLT_TO_PMIC_VAL(105000) + + EEM_PMIC_OFFSET); /*-700+100 */ +#else + /* dvfs_set_vlte(EEM_VOLT_TO_PMIC_VAL(105000)+EEM_PMIC_OFFSET); */ +#endif + FUNC_EXIT(FUNC_LV_HELP); +} + + +static void switch_to_vcore_ao(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + + eem_write_field(PERI_VCORE_EEM_CON0, VCORE_EEMODSEL, SEL_VCORE_AO); + eem_write_field(EEMCORESEL, APBSEL, det->ctrl_id); + eem_ctrls[EEM_CTRL_VCORE].det_id = det_to_id(det); + + FUNC_EXIT(FUNC_LV_HELP); +} + +static void switch_to_vcore_pdn(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + + eem_write_field(PERI_VCORE_EEM_CON0, VCORE_EEMODSEL, SEL_VCORE_PDN); + eem_write_field(EEMCORESEL, APBSEL, det->ctrl_id); + eem_ctrls[EEM_CTRL_SOC].det_id = det_to_id(det); + + FUNC_EXIT(FUNC_LV_HELP); +} + +#ifndef __KERNEL__ +static int set_volt_vcore(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + FUNC_EXIT(FUNC_LV_HELP); + #if defined(__MTK_SLT_) + #if defined(SLT_VMAX) + det->volt_tbl_init2[0] = EEM_VOLT_TO_PMIC_VAL(131000) + EEM_PMIC_OFFSET; + eem_debug("HV VCORE voltage EEM to 0x%X\n", det->volt_tbl_init2[0]); + #elif defined(SLT_VMIN) + det->volt_tbl_init2[0] = clamp(det->volt_tbl_init2[0] - 0xB, + det->VMIN + EEM_PMIC_OFFSET, det->VMAX + EEM_PMIC_OFFSET); + eem_debug("LV VCORE voltage EEM to 0x%X\n", det->volt_tbl_init2[0]); + #else + eem_debug("NV VCORE voltage EEM to 0x%x\n", det->volt_tbl_init2[0]); + #endif + #else + eem_debug("VCORE EEM voltage to 0x%x\n", det->volt_tbl_init2[0]); + #endif + + /* return mt_set_cur_volt_vcore_pdn(det->volt_tbl_pmic[0]); */ /* unit = 10 uv */ + #ifdef EARLY_PORTING + return 0; + #else + return dvfs_set_vcore(det->volt_tbl_init2[0]); + #endif +} +#endif + +static int get_volt_vcore(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_HELP); + FUNC_EXIT(FUNC_LV_HELP); + + /* eem_debug("get_volt_vcore=%d\n",mt_get_cur_volt_vcore_ao()); */ + #ifdef EARLY_PORTING + return 0; + #else + return mt_get_cur_volt_vcore_ao(); /* unit = 10 uv */ + #endif +} +#endif + +/*============================================================= + * Global function definition + *=============================================================*/ +#if 0 +unsigned int mt_eem_get_level(void) +{ + unsigned int spd_bin_resv = 0, ret = 0; + + FUNC_ENTER(FUNC_LV_HELP); + + spd_bin_resv = (get_devinfo_with_index(15) >> 28) & 0x7; + + switch (spd_bin_resv) { + case 1: + ret = 1; /* 2.0G */ + break; + + case 2: + ret = 2; /* 1.3G */ + break; + + case 4: + ret = 2; /* 1.3G */ + break; + + default: + ret = 0; /* 1.7G */ + break; + } + + FUNC_EXIT(FUNC_LV_HELP); + + return ret; +} +#endif + +void mt_ptp_lock(unsigned long *flags) +{ + /* FUNC_ENTER(FUNC_LV_HELP); */ + /* FIXME: lock with MD32 */ + /* get_md32_semaphore(SEMAPHORE_PTP); */ +#ifdef __KERNEL__ + spin_lock_irqsave(&eem_spinlock, *flags); +#endif + /* FUNC_EXIT(FUNC_LV_HELP); */ +} +#ifdef __KERNEL__ +EXPORT_SYMBOL(mt_ptp_lock); +#endif + +void mt_ptp_unlock(unsigned long *flags) +{ + /* FUNC_ENTER(FUNC_LV_HELP); */ +#ifdef __KERNEL__ + spin_unlock_irqrestore(&eem_spinlock, *flags); + /* FIXME: lock with MD32 */ + /* release_md32_semaphore(SEMAPHORE_PTP); */ +#endif + /* FUNC_EXIT(FUNC_LV_HELP); */ +} +#ifdef __KERNEL__ +EXPORT_SYMBOL(mt_ptp_unlock); +#endif + +#if 0 +int mt_eem_idle_can_enter(void) +{ + struct eem_ctrl *ctrl; + + FUNC_ENTER(FUNC_LV_HELP); + + for_each_ctrl(ctrl) { + if (atomic_read(&ctrl->in_init)) { + FUNC_EXIT(FUNC_LV_HELP); + return 0; + } + } + + FUNC_EXIT(FUNC_LV_HELP); + + return 1; +} +EXPORT_SYMBOL(mt_eem_idle_can_enter); +#endif + +#ifdef __KERNEL__ +/* + * timer for log + */ +static enum hrtimer_restart eem_log_timer_func(struct hrtimer *timer) +{ + struct eem_det *det; + + FUNC_ENTER(FUNC_LV_HELP); + + for_each_det(det) { + eem_error("Timer Bank=%d - (%d) - (%d, %d, %d, %d, %d, %d, %d, %d) - (0x%x), sts(%d)\n" + /* + "(%d, %d, %d, %d, %d, %d, %d, %d) -" + "(%d, %d, %d, %d)\n"*/, + det->ctrl_id, det->ops->get_temp(det), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[0]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[1]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[2]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[3]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[4]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[5]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[6]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[7]), + det->t250, + det->ops->get_status(det) + /* + det->freq_tbl[0], + det->freq_tbl[1], + det->freq_tbl[2], + det->freq_tbl[3], + det->freq_tbl[4], + det->freq_tbl[5], + det->freq_tbl[6], + det->freq_tbl[7], + det->dcvalues[3], + det->eem_freqpct30[3], + det->eem_26c[3], + det->eem_vop30[3]*/); + } + + hrtimer_forward_now(timer, ns_to_ktime(LOG_INTERVAL)); + FUNC_EXIT(FUNC_LV_HELP); + + return HRTIMER_RESTART; +} +#endif +/* + * Thread for voltage setting + */ +static int eem_volt_thread_handler(void *data) +{ + struct eem_ctrl *ctrl = (struct eem_ctrl *)data; + struct eem_det *det = id_to_eem_det(ctrl->det_id); + + FUNC_ENTER(FUNC_LV_HELP); +#ifdef __KERNEL__ + + do { + wait_event_interruptible(ctrl->wq, ctrl->volt_update); + + if ((ctrl->volt_update & EEM_VOLT_UPDATE) && det->ops->set_volt) { +#ifdef CONFIG_EEM_AEE_RR_REC + int temp = -1; + #if !defined(EARLY_PORTING) /* I-Chang */ + switch (det->ctrl_id) { + case EEM_CTRL_LITTLE: + aee_rr_rec_ptp_status(aee_rr_curr_ptp_status() | + (1 << EEM_CPU_LITTLE_IS_SET_VOLT)); + temp = EEM_CPU_LITTLE_IS_SET_VOLT; + break; + + case EEM_CTRL_GPU: + aee_rr_rec_ptp_status(aee_rr_curr_ptp_status() | + (1 << EEM_GPU_IS_SET_VOLT)); + temp = EEM_GPU_IS_SET_VOLT; + break; + + case EEM_CTRL_BIG: + aee_rr_rec_ptp_status(aee_rr_curr_ptp_status() | + (1 << EEM_CPU_BIG_IS_SET_VOLT)); + temp = EEM_CPU_BIG_IS_SET_VOLT; + break; + + default: + break; + } + #endif +#endif + det->ops->set_volt(det); + +#if (defined(CONFIG_EEM_AEE_RR_REC) && !defined(EARLY_PORTING)) + if (temp >= EEM_CPU_LITTLE_IS_SET_VOLT) + aee_rr_rec_ptp_status(aee_rr_curr_ptp_status() & ~(1 << temp)); +#endif + + } + if ((ctrl->volt_update & EEM_VOLT_RESTORE) && det->ops->restore_default_volt) + det->ops->restore_default_volt(det); + + ctrl->volt_update = EEM_VOLT_NONE; + + } while (!kthread_should_stop()); + +#endif + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +static void inherit_base_det(struct eem_det *det) +{ + /* + * Inherit ops from eem_det_base_ops if ops in det is NULL + */ + FUNC_ENTER(FUNC_LV_HELP); + + #define INIT_OP(ops, func) \ + do { \ + if (ops->func == NULL) \ + ops->func = eem_det_base_ops.func; \ + } while (0) + + INIT_OP(det->ops, disable); + INIT_OP(det->ops, disable_locked); + INIT_OP(det->ops, switch_bank); + INIT_OP(det->ops, init01); + INIT_OP(det->ops, init02); + INIT_OP(det->ops, mon_mode); + INIT_OP(det->ops, get_status); + INIT_OP(det->ops, dump_status); + INIT_OP(det->ops, set_phase); + INIT_OP(det->ops, get_temp); + INIT_OP(det->ops, get_volt); + INIT_OP(det->ops, set_volt); + INIT_OP(det->ops, restore_default_volt); + INIT_OP(det->ops, get_freq_table); + + FUNC_EXIT(FUNC_LV_HELP); +} + +static void eem_init_ctrl(struct eem_ctrl *ctrl) +{ + FUNC_ENTER(FUNC_LV_HELP); + + /* init_completion(&ctrl->init_done); */ + /* atomic_set(&ctrl->in_init, 0); */ +#ifdef __KERNEL__ + + if (1) { + /* HAS_FEATURE(id_to_eem_det(ctrl->det_id), FEA_MON)) { + TODO: FIXME, why doesn't work <-XXX */ + init_waitqueue_head(&ctrl->wq); + ctrl->thread = kthread_run(eem_volt_thread_handler, ctrl, ctrl->name); + + if (IS_ERR(ctrl->thread)) + eem_debug("Create %s thread failed: %ld\n", ctrl->name, PTR_ERR(ctrl->thread)); + } + +#endif + FUNC_EXIT(FUNC_LV_HELP); +} + +static void eem_init_det(struct eem_det *det, struct eem_devinfo *devinfo) +{ + enum eem_det_id det_id = det_to_id(det); + + FUNC_ENTER(FUNC_LV_HELP); + eem_debug("det=%s, id=%d\n", ((char *)(det->name) + 8), det_id); + + inherit_base_det(det); + + /* init with devinfo */ + det->EEMINITEN = devinfo->EEMINITEN; + det->EEMMONEN = devinfo->EEMMONEN; + + /* init with constant */ + det->DETWINDOW = DETWINDOW_VAL; + det->VMAX = VMAX_VAL; + det->VMIN = VMIN_VAL; + det->VBOOT = EEM_VOLT_TO_PMIC_VAL(100000); + + det->DTHI = DTHI_VAL; + det->DTLO = DTLO_VAL; + det->DETMAX = DETMAX_VAL; + + det->AGECONFIG = AGECONFIG_VAL; + det->AGEM = AGEM_VAL; + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if ((get_devinfo_with_index(38) & 0x100) && (get_devinfo_with_index(28) & 0x40000000)) { + /* for Jade- UMC */ + det->DVTFIXED = 0; + eem_error("Apply HT settings FEA(%d)\n", det->features); + } else + det->DVTFIXED = DVTFIXED_VAL; + #else + det->DVTFIXED = DVTFIXED_VAL; + #endif + det->VCO = VCO_VAL; + det->DCCONFIG = DCCONFIG_VAL; + + if (NULL != det->ops->get_volt) { + det->VBOOT = EEM_VOLT_TO_PMIC_VAL(det->ops->get_volt(det)); + eem_debug("@%s, %s-VBOOT = %d(%d)\n", + __func__, ((char *)(det->name) + 8), det->VBOOT, det->ops->get_volt(det)); + } + + switch (det_id) { + case EEM_DET_LITTLE: + det->MDES = devinfo->CPU0_MDES; + det->BDES = devinfo->CPU0_BDES; + det->DCMDET = devinfo->CPU0_DCMDET; + det->DCBDET = devinfo->CPU0_DCBDET; + det->recordRef = recordRef; + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* For Jade- UMC use */ + if (get_devinfo_with_index(28) & 0x40000000) + det->max_freq_khz = 1001000; + #endif + #if 0 + int i; + + for (int i = 0; i < NR_FREQ; i++) + eem_debug("@(Record)%s----->(%s), = 0x%08x\n", + __func__, + det->name, + *(recordRef + i)); + #endif + break; + + case EEM_DET_BIG: + det->MDES = devinfo->CPU1_MDES; + det->BDES = devinfo->CPU1_BDES; + det->DCMDET = devinfo->CPU1_DCMDET; + det->DCBDET = devinfo->CPU1_DCBDET; + det->recordRef = recordRef + 36; + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* For Jade- UMC use */ + if (get_devinfo_with_index(28) & 0x40000000) + det->max_freq_khz = 1508000; + #endif + + #if 0 + int i; + + for (int i = 0; i < NR_FREQ; i++) + eem_debug("@(SRAM)%s----->(%s), = 0x%08x\n", + __func__, + det->name, + *(recordRef + i)); + #endif + break; + + case EEM_DET_GPU: + det->MDES = devinfo->GPU_MDES; + det->BDES = devinfo->GPU_BDES; + det->DCMDET = devinfo->GPU_DCMDET; + det->DCBDET = devinfo->GPU_DCBDET; + det->VMAX = VMAX_VAL_GPU; + det->VMIN = VMIN_VAL_GPU; /* override default setting */ + det->DVTFIXED = DVTFIXED_VAL_GPU; + det->VCO = VCO_VAL_GPU; + break; + + #if 0 + case EEM_DET_SOC: + det->MDES = devinfo->SOC_MDES; + det->BDES = devinfo->SOC_BDES; + det->DCMDET = devinfo->SOC_DCMDET; + det->DCBDET = devinfo->SOC_DCBDET; + det->VMAX = VMAX_VAL_SOC; /* override default setting */ + det->VMIN = VMIN_VAL_SOC; /* override default setting */ + det->DVTFIXED = DVTFIXED_VAL_SOC; + det->VBOOT = EEM_VOLT_TO_PMIC_VAL(125000); /* TODO: FIXME, unit = 10us */ + det->num_freq_tbl = 2; + det->freq_tbl[0] = 1600 * 100 / 1600; /* XXX: percentage, 800/800, dedicated for VCORE only */ + det->freq_tbl[1] = 1333 * 100 / 1600; /* XXX: percentage, 600/800, dedicated for VCORE only */ + break; + + case EEM_DET_LTE: + det->MDES = devinfo->LTE_MDES; + det->BDES = devinfo->LTE_BDES; + det->DCMDET = devinfo->LTE_DCMDET; + det->DCBDET = devinfo->LTE_DCBDET; + det->DVTFIXED = DVTFIXED_VAL_LTE; + /* det->VBOOT = EEM_VOLT_TO_PMIC_VAL(105000); */ /* TODO: FIXME, unit = 10us */ + det->VMAX = VMAX_VAL_LTE; /* override default setting */ + det->VMIN = VMIN_VAL_LTE; /* override default setting */ + det->num_freq_tbl = 1; + det->freq_tbl[0] = 300 * 100 / 300; /* XXX: percentage, 300/300, dedicated for LTE only */ + break; + #endif + + default: + eem_debug("[%s]: Unknown det_id %d\n", __func__, det_id); + break; + } + + switch (det->ctrl_id) { + case EEM_CTRL_LITTLE: + det->AGEDELTA = devinfo->CPU0_AGEDELTA; + det->MTDES = devinfo->CPU0_MTDES; + break; + + case EEM_CTRL_GPU: + det->AGEDELTA = devinfo->GPU_AGEDELTA; + det->MTDES = devinfo->GPU_MTDES; + break; + + case EEM_CTRL_BIG: + det->AGEDELTA = devinfo->CPU1_AGEDELTA; + det->MTDES = devinfo->CPU1_MTDES; + break; + + #if 0 + case EEM_CTRL_SOC: + det->AGEDELTA = devinfo->SOC_AGEDELTA; + det->MTDES = devinfo->SOC_MTDES; + break; + + case EEM_CTRL_LTE: + det->AGEDELTA = devinfo->LTE_AGEDELTA; + det->MTDES = devinfo->LTE_MTDES; + break; + #endif + + default: + eem_debug("[%s]: Unknown ctrl_id %d\n", __func__, det->ctrl_id); + break; + } + + /* get DVFS frequency table */ + det->ops->get_freq_table(det); + + FUNC_EXIT(FUNC_LV_HELP); +} + + +static void eem_set_eem_volt(struct eem_det *det) +{ +#if SET_PMIC_VOLT + unsigned i; + int cur_temp, low_temp_offset; + struct eem_ctrl *ctrl = id_to_eem_ctrl(det->ctrl_id); + + cur_temp = det->ops->get_temp(det); + /* eem_debug("eem_set_eem_volt cur_temp = %d\n", cur_temp); */ + if (cur_temp <= 33000) { + low_temp_offset = 10; + ctrl->volt_update |= EEM_VOLT_UPDATE; + } else { + low_temp_offset = 0; + ctrl->volt_update |= EEM_VOLT_UPDATE; + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if ((get_devinfo_with_index(38) & 0x100) && (get_devinfo_with_index(28) & 0x40000000)) + memcpy(det->volt_tbl, det->volt_tbl_init2, sizeof(det->volt_tbl_init2)); + #endif + } + /* eem_debug("ctrl->volt_update |= EEM_VOLT_UPDATE\n"); */ + + /* all scale of volt_tbl_pmic, volt_tbl, volt_offset are pmic value */ + /* scale of det->volt_offset must equal 10uV */ + for (i = 0; i < det->num_freq_tbl; i++) { + det->volt_tbl_pmic[i] = clamp(det->volt_tbl[i] + det->volt_offset + low_temp_offset + det->pi_offset, + det->VMIN + EEM_PMIC_OFFSET, + det->VMAX + EEM_PMIC_OFFSET); + if (det_to_id(det) == EEM_DET_LITTLE) + det->volt_tbl_pmic[i] = min(det->volt_tbl_pmic[i], (*(recordTbl + (i * 9) + 8) & 0x7F)); + else if (det_to_id(det) == EEM_DET_BIG) + det->volt_tbl_pmic[i] = min(det->volt_tbl_pmic[i], (*(recordTbl + (i + 8) * 9 + 8) & 0x7F)); + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + #else + else { + if (8 == det->num_freq_tbl) + det->volt_tbl_pmic[i] = min(det->volt_tbl_pmic[i], gpuSb[i]); + else { + if (0 == gpuFy[i]) + break; + det->volt_tbl_pmic[i] = min(det->volt_tbl_pmic[i], gpuFy[i]); + } + } + #endif + } + +#ifdef __KERNEL__ + if ((0 == (det->disabled % 2)) && (0 == (det->disabled & BY_PROCFS_INIT2))) + wake_up_interruptible(&ctrl->wq); + else + eem_error("Disabled by [%d]\n", det->disabled); +#else + #if defined(__MTK_SLT_) + if ((ctrl->volt_update & EEM_VOLT_UPDATE) && det->ops->set_volt) + det->ops->set_volt(det); + + if ((ctrl->volt_update & EEM_VOLT_RESTORE) && det->ops->restore_default_volt) + det->ops->restore_default_volt(det); + + ctrl->volt_update = EEM_VOLT_NONE; + #endif +#endif +#endif + + FUNC_ENTER(FUNC_LV_HELP); + FUNC_EXIT(FUNC_LV_HELP); +} + +static void eem_restore_eem_volt(struct eem_det *det) +{ +#if SET_PMIC_VOLT + struct eem_ctrl *ctrl = id_to_eem_ctrl(det->ctrl_id); + + ctrl->volt_update |= EEM_VOLT_RESTORE; +#ifdef __KERNEL__ + wake_up_interruptible(&ctrl->wq); +#else +#if defined(__MTK_SLT_) + if ((ctrl->volt_update & EEM_VOLT_UPDATE) && det->ops->set_volt) + det->ops->set_volt(det); + + if ((ctrl->volt_update & EEM_VOLT_RESTORE) && det->ops->restore_default_volt) + det->ops->restore_default_volt(det); + + ctrl->volt_update = EEM_VOLT_NONE; +#endif +#endif +#endif + + FUNC_ENTER(FUNC_LV_HELP); + FUNC_EXIT(FUNC_LV_HELP); +} + +#if 0 +static void mt_eem_reg_dump_locked(void) +{ +#ifndef CONFIG_ARM64 + unsigned int addr; + + for (addr = (unsigned int)DESCHAR; addr <= (unsigned int)SMSTATE1; addr += 4) + eem_isr_info("0x%08X = 0x%08X\n", addr, *(volatile unsigned int *)addr); + + addr = (unsigned int)EEMCORESEL; + eem_isr_info("0x%08X = 0x%08X\n", addr, *(volatile unsigned int *)addr); +#else + unsigned long addr; + + for (addr = (unsigned long)DESCHAR; addr <= (unsigned long)SMSTATE1; addr += 4) + eem_isr_info("0x%lu = 0x%lu\n", addr, *(volatile unsigned long *)addr); + + addr = (unsigned long)EEMCORESEL; + eem_isr_info("0x%lu = 0x%lu\n", addr, *(volatile unsigned long *)addr); +#endif +} +#endif + +static inline void handle_init01_isr(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_LOCAL); + + eem_isr_info("mode = init1 %s-isr\n", ((char *)(det->name) + 8)); + + det->dcvalues[EEM_PHASE_INIT01] = eem_read(DCVALUES); + det->eem_freqpct30[EEM_PHASE_INIT01] = eem_read(FREQPCT30); + det->eem_26c[EEM_PHASE_INIT01] = eem_read(EEMINTEN + 0x10); + det->eem_vop30[EEM_PHASE_INIT01] = eem_read(VOP30); + det->eem_eemen[EEM_PHASE_INIT01] = eem_read(EEMEN); + + /* + #if defined(__MTK_SLT_) + eem_debug("CTP - dcvalues 240 = 0x%x\n", det->dcvalues[EEM_PHASE_INIT01]); + eem_debug("CTP - eem_freqpct30 218 = 0x%x\n", det->eem_freqpct30[EEM_PHASE_INIT01]); + eem_debug("CTP - eem_26c 26c = 0x%x\n", det->eem_26c[EEM_PHASE_INIT01]); + eem_debug("CTP - eem_vop30 248 = 0x%x\n", det->eem_vop30[EEM_PHASE_INIT01]); + eem_debug("CTP - eem_eemen 238 = 0x%x\n", det->eem_eemen[EEM_PHASE_INIT01]);i + #endif + */ +#if DUMP_DATA_TO_DE + { + unsigned int i; + for (i = 0; i < ARRAY_SIZE(reg_dump_addr_off); i++) { + det->reg_dump_data[i][EEM_PHASE_INIT01] = eem_read(EEM_BASEADDR + reg_dump_addr_off[i]); + #ifdef __KERNEL__ + eem_isr_info("0x%lx = 0x%08x\n", + #else + eem_isr_info("0x%X = 0x%X\n", + #endif + (unsigned long)EEM_BASEADDR + reg_dump_addr_off[i], + det->reg_dump_data[i][EEM_PHASE_INIT01] + ); + } + } +#endif + /* + * Read & store 16 bit values DCVALUES.DCVOFFSET and + * AGEVALUES.AGEVOFFSET for later use in INIT2 procedure + */ + det->DCVOFFSETIN = ~(eem_read(DCVALUES) & 0xffff) + 1; /* hw bug, workaround */ + det->AGEVOFFSETIN = eem_read(AGEVALUES) & 0xffff; + + /* + * Set EEMEN.EEMINITEN/EEMEN.EEMINIT2EN = 0x0 & + * Clear EEM INIT interrupt EEMINTSTS = 0x00000001 + */ + eem_write(EEMEN, 0x0); + eem_write(EEMINTSTS, 0x1); + /* eem_init01_finish(det); */ + /* det->ops->init02(det); */ + + FUNC_EXIT(FUNC_LV_LOCAL); +} +#if defined(__MTK_SLT_) +int cpu_in_mon; +#endif +static inline void handle_init02_isr(struct eem_det *det) +{ + unsigned int temp, i; + /* struct eem_ctrl *ctrl = id_to_eem_ctrl(det->ctrl_id); */ + + FUNC_ENTER(FUNC_LV_LOCAL); + + eem_isr_info("mode = init2 %s-isr\n", ((char *)(det->name) + 8)); + + det->dcvalues[EEM_PHASE_INIT02] = eem_read(DCVALUES); + det->eem_freqpct30[EEM_PHASE_INIT02] = eem_read(FREQPCT30); + det->eem_26c[EEM_PHASE_INIT02] = eem_read(EEMINTEN + 0x10); + det->eem_vop30[EEM_PHASE_INIT02] = eem_read(VOP30); + det->eem_eemen[EEM_PHASE_INIT02] = eem_read(EEMEN); + + /* + #if defined(__MTK_SLT_) + eem_debug("CTP - dcvalues 240 = 0x%x\n", det->dcvalues[EEM_PHASE_INIT02]); + eem_debug("CTP - eem_freqpct30 218 = 0x%x\n", det->eem_freqpct30[EEM_PHASE_INIT02]); + eem_debug("CTP - eem_26c 26c = 0x%x\n", det->eem_26c[EEM_PHASE_INIT02]); + eem_debug("CTP - eem_vop30 248 = 0x%x\n", det->eem_vop30[EEM_PHASE_INIT02]); + eem_debug("CTP - eem_eemen 238 = 0x%x\n", det->eem_eemen[EEM_PHASE_INIT02]); + #endif + */ + +#if DUMP_DATA_TO_DE + for (i = 0; i < ARRAY_SIZE(reg_dump_addr_off); i++) { + det->reg_dump_data[i][EEM_PHASE_INIT02] = eem_read(EEM_BASEADDR + reg_dump_addr_off[i]); + #ifdef __KERNEL__ + eem_isr_info("0x%lx = 0x%08x\n", + #else + eem_isr_info("0x%X = 0x%X\n", + #endif + (unsigned long)EEM_BASEADDR + reg_dump_addr_off[i], + det->reg_dump_data[i][EEM_PHASE_INIT02] + ); + } +#endif + temp = eem_read(VOP30); + /* eem_isr_info("init02 read(VOP30) = 0x%08X\n", temp); */ + /* VOP30=>pmic value */ + det->volt_tbl[0] = (temp & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[1] = ((temp >> 8) & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[2] = ((temp >> 16) & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[3] = ((temp >> 24) & 0xff) + EEM_PMIC_OFFSET; + + temp = eem_read(VOP74); + /* eem_isr_info("init02 read(VOP74) = 0x%08X\n", temp); */ + /* VOP74=>pmic value */ + det->volt_tbl[4] = (temp & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[5] = ((temp >> 8) & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[6] = ((temp >> 16) & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[7] = ((temp >> 24) & 0xff) + EEM_PMIC_OFFSET; + + /* backup to volt_tbl_init2 */ + memcpy(det->volt_tbl_init2, det->volt_tbl, sizeof(det->volt_tbl_init2)); + + for (i = 0; i < NR_FREQ; i++) { +#if defined(CONFIG_EEM_AEE_RR_REC) && !defined(EARLY_PORTING) /* I-Chang */ + switch (det->ctrl_id) { + case EEM_CTRL_LITTLE: + aee_rr_rec_ptp_cpu_little_volt(((unsigned long long)(det->volt_tbl[i]) << (8 * i)) | + (aee_rr_curr_ptp_cpu_little_volt() & ~((unsigned long long)(0xFF) << (8 * i)))); + break; + case EEM_CTRL_GPU: + aee_rr_rec_ptp_gpu_volt(((unsigned long long)(det->volt_tbl[i]) << (8 * i)) | + (aee_rr_curr_ptp_gpu_volt() & ~((unsigned long long)(0xFF) << (8 * i)))); + break; + case EEM_CTRL_BIG: + aee_rr_rec_ptp_cpu_big_volt(((unsigned long long)(det->volt_tbl[i]) << (8 * i)) | + (aee_rr_curr_ptp_cpu_big_volt() & ~((unsigned long long)(0xFF) << (8 * i)))); + break; + default: + break; + } +#endif + /* + eem_isr_info("init02_[%s].volt_tbl[%d] = 0x%08X (%d)\n", + det->name, i, det->volt_tbl[i], EEM_PMIC_VAL_TO_VOLT(det->volt_tbl[i])); + */ + } + #if defined(__MTK_SLT_) + if (det->ctrl_id <= EEM_CTRL_BIG) + cpu_in_mon = 0; + #endif + eem_set_eem_volt(det); + + /* + * Set EEMEN.EEMINITEN/EEMEN.EEMINIT2EN = 0x0 & + * Clear EEM INIT interrupt EEMINTSTS = 0x00000001 + */ + eem_write(EEMEN, 0x0); + eem_write(EEMINTSTS, 0x1); + + /* atomic_dec(&ctrl->in_init); */ + /* complete(&ctrl->init_done); */ + det->ops->mon_mode(det); + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +static inline void handle_init_err_isr(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_LOCAL); + eem_isr_info("====================================================\n"); + eem_isr_info("EEM init err: EEMEN(%p) = 0x%08X, EEMINTSTS(%p) = 0x%08X\n", + EEMEN, eem_read(EEMEN), + EEMINTSTS, eem_read(EEMINTSTS)); + eem_isr_info("SMSTATE0 (%p) = 0x%08X\n", + SMSTATE0, eem_read(SMSTATE0)); + eem_isr_info("SMSTATE1 (%p) = 0x%08X\n", + SMSTATE1, eem_read(SMSTATE1)); + eem_isr_info("====================================================\n"); + + /* + TODO: FIXME + { + struct eem_ctrl *ctrl = id_to_eem_ctrl(det->ctrl_id); + atomic_dec(&ctrl->in_init); + complete(&ctrl->init_done); + } + TODO: FIXME + */ + +#ifdef __KERNEL__ + aee_kernel_warning("mt_eem", "@%s():%d, get_volt(%s) = 0x%08X\n", + __func__, + __LINE__, + det->name, + det->VBOOT); +#endif + det->ops->disable_locked(det, BY_INIT_ERROR); + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +static inline void handle_mon_mode_isr(struct eem_det *det) +{ + unsigned int temp, i; + + FUNC_ENTER(FUNC_LV_LOCAL); + + eem_isr_info("mode = mon %s-isr\n", ((char *)(det->name) + 8)); + +#if defined(CONFIG_THERMAL) && !defined(EARLY_PORTING) + eem_isr_info("C0_temp=%d, C1_temp=%d GPU_temp=%d\n", + tscpu_get_temp_by_bank(THERMAL_BANK0), + tscpu_get_temp_by_bank(THERMAL_BANK2), + tscpu_get_temp_by_bank(THERMAL_BANK1)); +#endif + +#if defined(CONFIG_EEM_AEE_RR_REC) && !defined(EARLY_PORTING) + switch (det->ctrl_id) { + case EEM_CTRL_LITTLE: + #ifdef CONFIG_THERMAL + if (tscpu_get_temp_by_bank(THERMAL_BANK0) != 0) { + aee_rr_rec_ptp_temp( + (tscpu_get_temp_by_bank(THERMAL_BANK0) / 1000) << (8 * EEM_CPU_LITTLE_IS_SET_VOLT) | + (aee_rr_curr_ptp_temp() & ~(0xFF << (8 * EEM_CPU_LITTLE_IS_SET_VOLT)))); + } + #endif + break; + + case EEM_CTRL_GPU: + #ifdef CONFIG_THERMAL + if (tscpu_get_temp_by_bank(THERMAL_BANK1) != 0) { + aee_rr_rec_ptp_temp( + (tscpu_get_temp_by_bank(THERMAL_BANK1) / 1000) << (8 * EEM_GPU_IS_SET_VOLT) | + (aee_rr_curr_ptp_temp() & ~(0xFF << (8 * EEM_GPU_IS_SET_VOLT)))); + } + #endif + break; + + case EEM_CTRL_BIG: + #ifdef CONFIG_THERMAL + if (tscpu_get_temp_by_bank(THERMAL_BANK2) != 0) { + aee_rr_rec_ptp_temp( + (tscpu_get_temp_by_bank(THERMAL_BANK2) / 1000) << (8 * EEM_CPU_BIG_IS_SET_VOLT) | + (aee_rr_curr_ptp_temp() & ~(0xFF << (8 * EEM_CPU_BIG_IS_SET_VOLT)))); + } + #endif + break; + + default: + break; + } +#endif + + det->dcvalues[EEM_PHASE_MON] = eem_read(DCVALUES); + det->eem_freqpct30[EEM_PHASE_MON] = eem_read(FREQPCT30); + det->eem_26c[EEM_PHASE_MON] = eem_read(EEMINTEN + 0x10); + det->eem_vop30[EEM_PHASE_MON] = eem_read(VOP30); + det->eem_eemen[EEM_PHASE_MON] = eem_read(EEMEN); + + /* + #if defined(__MTK_SLT_) + eem_debug("CTP - dcvalues 240 = 0x%x\n", det->dcvalues[EEM_PHASE_MON]); + eem_debug("CTP - eem_freqpct30 218 = 0x%x\n", det->eem_freqpct30[EEM_PHASE_MON]); + eem_debug("CTP - eem_26c 26c = 0x%x\n", det->eem_26c[EEM_PHASE_MON]); + eem_debug("CTP - eem_vop30 248 = 0x%x\n", det->eem_vop30[EEM_PHASE_MON]); + eem_debug("CTP - eem_eemen 238 = 0x%x\n", det->eem_eemen[EEM_PHASE_MON]); + #endif + */ + +#if DUMP_DATA_TO_DE + for (i = 0; i < ARRAY_SIZE(reg_dump_addr_off); i++) { + det->reg_dump_data[i][EEM_PHASE_MON] = eem_read(EEM_BASEADDR + reg_dump_addr_off[i]); + + #ifdef __KERNEL__ + eem_isr_info("0x%lx = 0x%08x\n", + #else + eem_isr_info("0x%X = 0x%X\n", + #endif + (unsigned long)EEM_BASEADDR + reg_dump_addr_off[i], + det->reg_dump_data[i][EEM_PHASE_MON] + ); + } +#endif + /* check if thermal sensor init completed? */ + det->t250 = eem_read(TEMP); + + if (((det->t250 & 0xff) > 0x4b) && ((det->t250 & 0xff) < 0xd3)) { + eem_isr_info("thermal sensor init has not been completed.(temp = 0x%08X)\n", det->t250); + goto out; + } + + temp = eem_read(VOP30); + /* eem_debug("mon eem_read(VOP30) = 0x%08X\n", temp); */ + /* VOP30=>pmic value */ + det->volt_tbl[0] = (temp & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[1] = ((temp >> 8) & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[2] = ((temp >> 16) & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[3] = ((temp >> 24) & 0xff) + EEM_PMIC_OFFSET; + + temp = eem_read(VOP74); + /* eem_debug("mon eem_read(VOP74) = 0x%08X\n", temp); */ + /* VOP74=>pmic value */ + det->volt_tbl[4] = (temp & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[5] = ((temp >> 8) & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[6] = ((temp >> 16) & 0xff) + EEM_PMIC_OFFSET; + det->volt_tbl[7] = ((temp >> 24) & 0xff) + EEM_PMIC_OFFSET; + + for (i = 0; i < NR_FREQ; i++) { + #if defined(CONFIG_EEM_AEE_RR_REC) && !defined(EARLY_PORTING) /* I-Chang */ + switch (det->ctrl_id) { + case EEM_CTRL_LITTLE: + aee_rr_rec_ptp_cpu_little_volt(((unsigned long long)(det->volt_tbl[i]) << (8 * i)) | + (aee_rr_curr_ptp_cpu_little_volt() & ~((unsigned long long)(0xFF) << (8 * i)))); + break; + + case EEM_CTRL_GPU: + aee_rr_rec_ptp_gpu_volt(((unsigned long long)(det->volt_tbl[i]) << (8 * i)) | + (aee_rr_curr_ptp_gpu_volt() & ~((unsigned long long)(0xFF) << (8 * i)))); + break; + + case EEM_CTRL_BIG: + aee_rr_rec_ptp_cpu_big_volt(((unsigned long long)(det->volt_tbl[i]) << (8 * i)) | + (aee_rr_curr_ptp_cpu_big_volt() & ~((unsigned long long)(0xFF) << (8 * i)))); + break; + + default: + break; + } + #endif + eem_isr_info("mon_[%s].volt_tbl[%d] = 0x%08X (%d)\n", + det->name, i, det->volt_tbl[i], EEM_PMIC_VAL_TO_VOLT(det->volt_tbl[i])); + } + eem_isr_info("ISR : EEM_TEMPSPARE1 = 0x%08X\n", eem_read(EEM_TEMPSPARE1)); + + #if defined(__MTK_SLT_) + if ((cpu_in_mon == 1) && (det->ctrl_id <= EEM_CTRL_BIG)) + eem_isr_info("Won't do CPU eem_set_eem_volt\n"); + else{ + if (det->ctrl_id <= EEM_CTRL_BIG) { + eem_isr_info("Do CPU eem_set_eem_volt\n"); + cpu_in_mon = 1; + } + eem_set_eem_volt(det); + } + #else + eem_set_eem_volt(det); + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (EEM_CTRL_BIG == det->ctrl_id) { + ctrl_ITurbo = (0 == ctrl_ITurbo) ? 0 : 2; + eem_isr_info("Finished BIG monitor mode!!\n"); + } + #endif + #endif + +out: + /* Clear EEM INIT interrupt EEMINTSTS = 0x00ff0000 */ + eem_write(EEMINTSTS, 0x00ff0000); + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +static inline void handle_mon_err_isr(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_LOCAL); + + /* EEM Monitor mode error handler */ + eem_isr_info("====================================================\n"); + eem_isr_info("EEM mon err: EEMEN(%p) = 0x%08X, EEMINTSTS(%p) = 0x%08X\n", + EEMEN, eem_read(EEMEN), + EEMINTSTS, eem_read(EEMINTSTS)); + eem_isr_info("SMSTATE0 (%p) = 0x%08X\n", + SMSTATE0, eem_read(SMSTATE0)); + eem_isr_info("SMSTATE1 (%p) = 0x%08X\n", + SMSTATE1, eem_read(SMSTATE1)); + eem_isr_info("TEMP (%p) = 0x%08X\n", + TEMP, eem_read(TEMP)); + eem_isr_info("EEM_TEMPMSR0 (%p) = 0x%08X\n", + EEM_TEMPMSR0, eem_read(EEM_TEMPMSR0)); + eem_isr_info("EEM_TEMPMSR1 (%p) = 0x%08X\n", + EEM_TEMPMSR1, eem_read(EEM_TEMPMSR1)); + eem_isr_info("EEM_TEMPMSR2 (%p) = 0x%08X\n", + EEM_TEMPMSR2, eem_read(EEM_TEMPMSR2)); + eem_isr_info("EEM_TEMPMONCTL0 (%p) = 0x%08X\n", + EEM_TEMPMONCTL0, eem_read(EEM_TEMPMONCTL0)); + eem_isr_info("EEM_TEMPMSRCTL1 (%p) = 0x%08X\n", + EEM_TEMPMSRCTL1, eem_read(EEM_TEMPMSRCTL1)); + eem_isr_info("====================================================\n"); + +#ifdef __KERNEL__ + aee_kernel_warning("mt_eem", "@%s():%d, get_volt(%s) = 0x%08X\n", __func__, __LINE__, det->name, det->VBOOT); +#endif + det->ops->disable_locked(det, BY_MON_ERROR); + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +static inline void eem_isr_handler(struct eem_det *det) +{ + unsigned int eemintsts, eemen; + + FUNC_ENTER(FUNC_LV_LOCAL); + + eemintsts = eem_read(EEMINTSTS); + eemen = eem_read(EEMEN); + + eem_isr_info("Bank_number = %d %s-isr, 0x%X, 0x%X\n", + det->ctrl_id, ((char *)(det->name) + 8), eemintsts, eemen); + + if (eemintsts == 0x1) { /* EEM init1 or init2 */ + if ((eemen & 0x7) == 0x1) /* EEM init1 */ + handle_init01_isr(det); + else if ((eemen & 0x7) == 0x5) /* EEM init2 */ + handle_init02_isr(det); + else { + /* error : init1 or init2 */ + handle_init_err_isr(det); + } + } else if ((eemintsts & 0x00ff0000) != 0x0) + handle_mon_mode_isr(det); + else { /* EEM error handler */ + /* init 1 || init 2 error handler */ + if (((eemen & 0x7) == 0x1) || ((eemen & 0x7) == 0x5)) + handle_init_err_isr(det); + else /* EEM Monitor mode error handler */ + handle_mon_err_isr(det); + } + + FUNC_EXIT(FUNC_LV_LOCAL); +} +#ifdef __KERNEL__ +static irqreturn_t eem_isr(int irq, void *dev_id) +#else +int ptp_isr(void) +#endif +{ + unsigned long flags; + struct eem_det *det = NULL; + int i; + + FUNC_ENTER(FUNC_LV_MODULE); + + mt_ptp_lock(&flags); + +#if 0 + if (!(BIT(EEM_CTRL_VCORE) & eem_read(EEMODINTST))) { + switch (eem_read_field(PERI_VCORE_EEM_CON0, VCORE_EEMODSEL)) { + case SEL_VCORE_AO: + det = &eem_detectors[PTP_DET_VCORE_AO]; + break; + + case SEL_VCORE_PDN: + det = &eem_detectors[PTP_DET_VCORE_PDN]; + break; + } + + if (likely(det)) { + det->ops->switch_bank(det); + eem_isr_handler(det); + } + } +#endif + + for (i = 0; i < NR_EEM_CTRL; i++) { + /* + if (i == EEM_CTRL_VCORE) + continue; + */ + /* TODO: FIXME, it is better to link i @ struct eem_det */ + if ((BIT(i) & eem_read(EEMODINTST))) + continue; + + det = &eem_detectors[i]; + + det->ops->switch_bank(det); + + /*mt_eem_reg_dump_locked(); */ + + eem_isr_handler(det); + } + + mt_ptp_unlock(&flags); + + FUNC_EXIT(FUNC_LV_MODULE); +#ifdef __KERNEL__ + return IRQ_HANDLED; +#else + return 0; +#endif +} + +#if 0 +static atomic_t eem_init01_cnt; +static void eem_init01_prepare(struct eem_det *det) +{ + FUNC_ENTER(FUNC_LV_LOCAL); + + atomic_inc(&eem_init01_cnt); + + if (atomic_read(&eem_init01_cnt) == 1) { + enum mt_cpu_dvfs_id cpu; + + switch (det_to_id(det)) { + case EEM_DET_LITTLE: + cpu = MT_CPU_DVFS_LITTLE; + break; + + case EEM_DET_BIG: + cpu = MT_CPU_DVFS_BIG; + break; + + default: + return; + } + } + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +static void eem_init01_finish(struct eem_det *det) +{ + atomic_dec(&eem_init01_cnt); + + FUNC_ENTER(FUNC_LV_LOCAL); + + if (atomic_read(&eem_init01_cnt) < 0) + BUG(); + + if (atomic_read(&eem_init01_cnt) == 0) { +#if 0 + enum mt_cpu_dvfs_id cpu; + + switch (det_to_id(det)) { + case EEM_DET_LITTLE: + cpu = MT_CPU_DVFS_LITTLE; + break; + + case EEM_DET_BIG: + cpu = MT_CPU_DVFS_BIG; + break; + + default: + return; + } +#endif + } + + FUNC_EXIT(FUNC_LV_LOCAL); +} +#endif + +#if defined(__KERNEL__) && defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#define ITURBO_CPU_NUM 2 +static int __cpuinit _mt_eem_cpu_CB(struct notifier_block *nfb, unsigned long action, void *hcpu) +{ +#if defined(CONFIG_MTK_MT6750TT) + unsigned long flags; + unsigned int cpu = (unsigned long)hcpu; + unsigned int online_cpus = num_online_cpus(); + struct device *dev; + struct eem_det *det; + enum mt_eem_cpu_id cluster_id; + + /* CPU mask - Get on-line cpus per-cluster */ + struct cpumask eem_cpumask; + struct cpumask cpu_online_cpumask; + unsigned int cpus, big_cpus, timeout; + + if (ctrl_ITurbo < 2) { + eem_debug("Default Turbo off (%d) !!", ctrl_ITurbo); + return NOTIFY_OK; + } + /* eem_debug("Turbo start to run (%d) !!", ctrl_ITurbo); */ + tTbl = get_turbo(cpuBinLevel, cpuBinLevel_eng); + + /* Current active CPU is belong which cluster */ + cluster_id = arch_get_cluster_id(cpu); + + /* How many active CPU in this cluster, present by bit mask + ex: BIG LITTLE + 1111 0000 */ + arch_get_cluster_cpus(&eem_cpumask, cluster_id); + + /* How many active CPU online in this cluster, present by number */ + cpumask_and(&cpu_online_cpumask, &eem_cpumask, cpu_online_mask); + cpus = cpumask_weight(&cpu_online_cpumask); + + if (eem_log_en) + eem_error("@%s():%d, cpu = %d, act = %lu, on_cpus = %d, clst = %d, clst_cpu = %d\n" + , __func__, __LINE__, cpu, action, online_cpus, cluster_id, cpus); + + dev = get_cpu_device(cpu); + if (dev) { + det = id_to_eem_det(EEM_DET_BIG); + arch_get_cluster_cpus(&eem_cpumask, MT_EEM_CPU_BIG); + cpumask_and(&cpu_online_cpumask, &eem_cpumask, cpu_online_mask); + big_cpus = cpumask_weight(&cpu_online_cpumask); + + switch (action) { + case CPU_POST_DEAD: + if ((0 == ITurboRun) && + (0 < big_cpus) && + (ITURBO_CPU_NUM >= big_cpus) && + (MT_EEM_CPU_BIG == cluster_id)) { + if (eem_log_en) + eem_error("Turbo(1) POST_DEAD (%d) BIG_cc(%d)\n", online_cpus, big_cpus); + mt_ptp_lock(&flags); + ITurboRun = 1; + /* Revise BIG private table */ + /* CCI dcmdiv, CCI_div, dcm_div, clk_div, post_div, DDS */ + det->recordRef[1] = + ((tTbl[0] & 0x1F) << 27) | + ((tTbl[1] & 0x1F) << 22) | + ((tTbl[2] & 0x1F) << 17) | + ((tTbl[3] & 0x1F) << 12) | + ((tTbl[4] & 0x07) << 9) | + (tTbl[5] & 0x1FF); + mb(); /* SRAM writing */ + mt_ptp_unlock(&flags); + } else { + if (eem_log_en) + eem_error("Turbo(%d)ed !! POST_DEAD (%d), BIG_cc(%d)\n", + ITurboRun, online_cpus, big_cpus); + } + break; + + case CPU_DOWN_PREPARE: + if ((1 == ITurboRun) && (1 == big_cpus) && (MT_EEM_CPU_BIG == cluster_id)) { + if (eem_log_en) + eem_error("Turbo(0) DP (%d) BIG_cc(%d)\n", online_cpus, big_cpus); + mt_ptp_lock(&flags); + ITurboRun = 0; + /* Restore BIG private table */ + /* CCI dcmdiv, CCI_div, dcm_div, clk_div, post_div, DDS */ + det->recordRef[1] = + ((*(recordTbl + (8 * 9) + 0) & 0x1F) << 27) | + ((*(recordTbl + (8 * 9) + 1) & 0x1F) << 22) | + ((*(recordTbl + (8 * 9) + 2) & 0x1F) << 17) | + ((*(recordTbl + (8 * 9) + 3) & 0x1F) << 12) | + ((*(recordTbl + (8 * 9) + 4) & 0x07) << 9) | + (*(recordTbl + (8 * 9) + 5) & 0x1FF); + mb(); /* SRAM writing */ + mt_ptp_unlock(&flags); + } else { + if (eem_log_en) + eem_error("Turbo(%d)ed !! DP (%d), BIG_cc(%d)\n", + ITurboRun, online_cpus, big_cpus); + } + break; + + case CPU_UP_PREPARE: + if ((0 == ITurboRun) && (0 == big_cpus) && (MT_EEM_CPU_BIG == cluster_id)) { + if (eem_log_en) + eem_error("Turbo(1) UP (%d), BIG_cc(%d)\n", online_cpus, big_cpus); + mt_ptp_lock(&flags); + ITurboRun = 1; + /* Revise BIG private table */ + /* CCI dcmdiv, CCI_div, dcm_div, clk_div, post_div, DDS */ + det->recordRef[1] = + ((tTbl[0] & 0x1F) << 27) | + ((tTbl[1] & 0x1F) << 22) | + ((tTbl[2] & 0x1F) << 17) | + ((tTbl[3] & 0x1F) << 12) | + ((tTbl[4] & 0x07) << 9) | + (tTbl[5] & 0x1FF); + mb(); /* SRAM writing */ + mt_ptp_unlock(&flags); + } else if ((1 == ITurboRun) && + ((ITURBO_CPU_NUM == big_cpus) /* || (5 < cpu) */) && + (MT_EEM_CPU_BIG == cluster_id)) { + if (eem_log_en) + eem_error("Turbo(0) UP c(%d), on_c(%d), BIG_cc(%d)\n", + cpu, online_cpus, big_cpus); + mt_ptp_lock(&flags); + ITurboRun = 0; + /* Restore BIG private table */ + det->recordRef[1] = + ((*(recordTbl + (8 * 9) + 0) & 0x1F) << 27) | + ((*(recordTbl + (8 * 9) + 1) & 0x1F) << 22) | + ((*(recordTbl + (8 * 9) + 2) & 0x1F) << 17) | + ((*(recordTbl + (8 * 9) + 3) & 0x1F) << 12) | + ((*(recordTbl + (8 * 9) + 4) & 0x07) << 9) | + (*(recordTbl + (8 * 9) + 5) & 0x1FF); + mb(); /* SRAM writing */ + mt_ptp_unlock(&flags); + timeout = 0; + while (((eem_read(eem_apmixed_base + 0x204) >> 12) & 0x1FF) > + *(recordTbl + (8 * 9) + 5)) { + udelay(120); + if (timeout == 100) { + eem_error("DDS = %x, %x\n", + (eem_read(eem_apmixed_base + 0x204) >> 12) & 0x1FF, + *(recordTbl + (8 * 9) + 5)); + break; + } + timeout++; + } + udelay(120); + } else { + if (eem_log_en) + eem_error("Turbo(%d)ed !! UP (%d), BIG_cc(%d)\n", + ITurboRun, online_cpus, big_cpus); + } + break; + } + } + return NOTIFY_OK; +#else + tTbl = NULL; + return NOTIFY_OK; +#endif +} + +unsigned int get_turbo_status(void) +{ + return ITurboRun; +} +#endif + +void eem_init02(const char *str) +{ + struct eem_det *det; + struct eem_ctrl *ctrl; + + FUNC_ENTER(FUNC_LV_LOCAL); + eem_error("eem_init02 called by [%s]\n", str); + for_each_det_ctrl(det, ctrl) { + if (HAS_FEATURE(det, FEA_INIT02)) { + unsigned long flag; + + mt_ptp_lock(&flag); + det->ops->init02(det); + #if defined(__MTK_SLT_) + mdelay(5); + #endif + mt_ptp_unlock(&flag); + } + } + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +void eem_init01(void) +{ + struct eem_det *det; + struct eem_ctrl *ctrl; + unsigned int out = 0, timeout = 0; + + FUNC_ENTER(FUNC_LV_LOCAL); + + for_each_det_ctrl(det, ctrl) { + { + unsigned long flag; + unsigned int vboot = 0; + + if (NULL != det->ops->get_volt) + vboot = EEM_VOLT_TO_PMIC_VAL(det->ops->get_volt(det)); + + eem_debug("%s, vboot = %d, VBOOT = %d\n", + ((char *)(det->name) + 8), vboot, det->VBOOT); +#ifdef __KERNEL__ + + if (vboot != det->VBOOT) { + eem_error("@%s():%d, get_volt(%s) = 0x%08X, VBOOT = 0x%08X\n", + __func__, __LINE__, det->name, vboot, det->VBOOT); + aee_kernel_warning("mt_eem", "@%s():%d, get_volt(%s) = 0x%08X, VBOOT = 0x%08X\n", + __func__, __LINE__, det->name, vboot, det->VBOOT); + } + + BUG_ON(EEM_VOLT_TO_PMIC_VAL(det->ops->get_volt(det)) != det->VBOOT); +#endif + mt_ptp_lock(&flag); /* <-XXX */ + det->ops->init01(det); + mt_ptp_unlock(&flag); /* <-XXX */ + } + + /* + * VCORE_AO and VCORE_PDN use the same controller. + * Wait until VCORE_AO init01 and init02 done + */ + + /* + if (atomic_read(&ctrl->in_init)) { + TODO: Use workqueue to avoid blocking + wait_for_completion(&ctrl->init_done); + } + */ + } + + /* This patch is waiting for whole bank finish the init01 then go + * next. Due to LL/L use same bulk PMIC, LL voltage table change + * will impact L to process init01 stage, because L require a + * stable 1V for init01. + */ + while (1) { + for_each_det_ctrl(det, ctrl) { + if ((EEM_CTRL_LITTLE == det->ctrl_id) && (1 == det->eem_eemen[EEM_PHASE_INIT01])) + out |= BIT(EEM_CTRL_LITTLE); + else if ((EEM_CTRL_GPU == det->ctrl_id) && (1 == det->eem_eemen[EEM_PHASE_INIT01])) + out |= BIT(EEM_CTRL_GPU); + else if ((EEM_CTRL_BIG == det->ctrl_id) && (1 == det->eem_eemen[EEM_PHASE_INIT01])) + out |= BIT(EEM_CTRL_BIG); + } + if ((0x07 == out) || (30 == timeout)) { + eem_debug("init01 finish time is %d\n", timeout); + break; + } + udelay(100); + timeout++; + } + eem_init02(__func__); + FUNC_EXIT(FUNC_LV_LOCAL); +} + +#if EN_EEM_OD +#if 0 +static char *readline(struct file *fp) +{ +#define BUFSIZE 1024 + static char buf[BUFSIZE]; /* TODO: FIXME, dynamic alloc */ + static int buf_end; + static int line_start; + static int line_end; + char *ret; + + FUNC_ENTER(FUNC_LV_HELP); +empty: + + if (line_start >= buf_end) { + line_start = 0; + buf_end = fp->f_op->read(fp, &buf[line_end], sizeof(buf) - line_end, &fp->f_pos); + + if (0 == buf_end) { + line_end = 0; + return NULL; + } + + buf_end += line_end; + } + + while (buf[line_end] != '\n') { + line_end++; + + if (line_end >= buf_end) { + memcpy(&buf[0], &buf[line_start], buf_end - line_start); + line_end = buf_end - line_start; + line_start = buf_end; + goto empty; + } + } + + buf[line_end] = '\0'; + ret = &buf[line_start]; + line_start = line_end + 1; + + FUNC_EXIT(FUNC_LV_HELP); + + return ret; +} +#endif +/* leakage */ +unsigned int leakage_core; +unsigned int leakage_gpu; +unsigned int leakage_sram2; +unsigned int leakage_sram1; + + +void get_devinfo(struct eem_devinfo *p) +{ + int *val = (int *)p; + + FUNC_ENTER(FUNC_LV_HELP); + +#ifndef EARLY_PORTING + #if defined(__KERNEL__) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if ((get_devinfo_with_index(38) & 0x200) && (get_devinfo_with_index(28) & 0x40000000)) { + /* for Jade- UMC */ + val[0] = get_devinfo_with_index(37); + val[1] = get_devinfo_with_index(38); + val[2] = get_devinfo_with_index(39); + } else { + val[0] = get_devinfo_with_index(34); + val[1] = get_devinfo_with_index(35); + val[2] = get_devinfo_with_index(36); + } + #else + val[0] = get_devinfo_with_index(34); + val[1] = get_devinfo_with_index(35); + val[2] = get_devinfo_with_index(36); + #endif + val[3] = get_devinfo_with_index(37); + val[4] = get_devinfo_with_index(38); + val[5] = get_devinfo_with_index(18); + val[6] = get_devinfo_with_index(19); + #else + if ((eem_read(0x10206670) & 0x200) && (eem_read(0x10206540) & 0x40000000)) { + /* for Jade- UMC */ + val[0] = eem_read(0x1020666C); + val[1] = eem_read(0x10206670); + val[2] = eem_read(0x10206674); + } else { + val[0] = eem_read(0x10206660); /* EEM0 */ + val[1] = eem_read(0x10206664); /* EEM1 */ + val[2] = eem_read(0x10206668); /* EEM2 */ + } + val[3] = eem_read(0x1020666C); /* EEM3 */ + val[4] = eem_read(0x10206670); /* EEM4 */ + val[5] = eem_read(0x10206274); /* EEM_SRM_RP5 */ + val[6] = eem_read(0x10206278); /* EEM_SRM_RP6 */ + #endif +#else + /* test pattern */ + val[0] = 0x071769F7; + val[1] = 0x00260026; + val[2] = 0x071769F7; + val[3] = 0x071769F7; + val[4] = 0x00260000; + val[5] = 0x00000000; + val[6] = 0x00000000; +#endif + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if ((p->CPU0_BDES != 0) && (p->CPU1_BDES != 0)) + val[7] = 0x01; + if ((p->CPU0_MTDES != 0) && (p->CPU1_MTDES != 0)) + val[7] = val[7] | (0x01<<8); + #else + if ((p->CPU0_BDES != 0) && (p->CPU1_BDES != 0) && (p->GPU_BDES != 0)) + val[7] = 0x01; + if ((p->CPU0_MTDES != 0) && (p->CPU1_MTDES != 0) && (p->GPU_MTDES != 0)) + val[7] = val[7] | (0x01<<8); + #endif + + eem_debug("M_HW_RES0 = 0x%X\n", val[0]); + eem_debug("M_HW_RES1 = 0x%X\n", val[1]); + eem_debug("M_HW_RES2 = 0x%X\n", val[2]); + eem_debug("M_HW_RES3 = 0x%X\n", val[3]); + eem_debug("M_HW_RES4 = 0x%X\n", val[4]); + eem_debug("M_HW_RES5 = 0x%X\n", val[5]); + eem_debug("M_HW_RES6 = 0x%X\n", val[6]); + eem_debug("M_HW_RES7 = 0x%X\n", val[7]); + eem_debug("p->EEMINITEN=0x%x\n", p->EEMINITEN); + eem_debug("p->EEMMONEN=0x%x\n", p->EEMMONEN); + /* p->EEMINITEN = 0; */ /* TODO: FIXME */ + /* p->EEMMONEN = 0; */ /* TODO: FIXME */ + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + fab = get_devinfo_with_index(28) & 0x40000000; + segment = get_devinfo_with_index(21) & 0xFF; + if (((segment == 0x41) || (segment == 0x45) || (segment == 0x40)) && !(fab)) + #if defined(CONFIG_MTK_MT6750TT) + ctrl_ITurbo = 1; /* t */ + #else + ctrl_ITurbo = 0; /* u */ + #endif + #endif + + FUNC_EXIT(FUNC_LV_HELP); +} + +static int eem_probe(struct platform_device *pdev) +{ + int ret; + struct eem_det *det; + struct eem_ctrl *ctrl; + #if (defined(__KERNEL__) && !defined(CONFIG_MTK_CLKMGR)) + struct clk *clk_thermal; + struct clk *clk_mfg, *clk_mfg_scp; /* for gpu clock use */ + #endif + /* unsigned int code = mt_get_chip_hw_code(); */ + + FUNC_ENTER(FUNC_LV_MODULE); + + #ifdef __KERNEL__ + #if !defined(CONFIG_MTK_CLKMGR) + /* enable thermal CG */ + clk_thermal = devm_clk_get(&pdev->dev, "therm-eem"); + if (IS_ERR(clk_thermal)) { + eem_error("cannot get thermal clock\n"); + return PTR_ERR(clk_thermal); + } + + /* get GPU clock */ + clk_mfg = devm_clk_get(&pdev->dev, "mfg-main"); + if (IS_ERR(clk_mfg)) { + eem_error("cannot get mfg main clock\n"); + return PTR_ERR(clk_mfg); + } + + /* get GPU mtcomose */ + clk_mfg_scp = devm_clk_get(&pdev->dev, "mtcmos-mfg"); + if (IS_ERR(clk_mfg_scp)) { + eem_error("cannot get mtcmos mfg\n"); + return PTR_ERR(clk_mfg_scp); + } + eem_debug("thmal=%p, gpu_clk=%p, gpu_mtcmos=%p", + clk_thermal, + clk_mfg, + clk_mfg_scp); + #else + enable_clock(MT_CG_INFRA_THERM, "PTPOD"); + enable_clock(MT_CG_MFG_BG3D, "PTPOD"); + #endif + + /* set EEM IRQ */ + ret = request_irq(eem_irq_number, eem_isr, IRQF_TRIGGER_LOW, "ptp", NULL); + + if (ret) { + eem_debug("EEM IRQ register failed (%d)\n", ret); + WARN_ON(1); + } + eem_debug("Set EEM IRQ OK.\n"); + #endif + + /* eem_level = mt_eem_get_level(); */ + eem_debug("In eem_probe\n"); + /* atomic_set(&eem_init01_cnt, 0); */ + + #if (defined(CONFIG_EEM_AEE_RR_REC) && !defined(EARLY_PORTING)) + _mt_eem_aee_init(); + #endif + + for_each_ctrl(ctrl) { + eem_init_ctrl(ctrl); + } + #ifdef __KERNEL__ + #ifndef EARLY_PORTING + /* disable frequency hopping (main PLL) */ + mt_fh_popod_save();/* I-Chang */ + + /* disable DVFS and set vproc = 1v (LITTLE = 689 MHz)(BIG = 1196 MHz) */ + mt_ppm_ptpod_policy_activate(); + mt_gpufreq_disable_by_ptpod(); /* GPU bulk enable*/ + + #if !defined(CONFIG_MTK_CLKMGR) + ret = clk_prepare_enable(clk_thermal); /* Thermal clock enable */ + if (ret) + eem_error("clk_prepare_enable failed when enabling THERMAL\n"); + + ret = clk_prepare_enable(clk_mfg_scp); /* GPU MTCMOS enable*/ + if (ret) + eem_error("clk_prepare_enable failed when enabling mfg MTCMOS\n"); + + ret = clk_prepare_enable(clk_mfg); /* GPU CLOCK */ + if (ret) + eem_error("clk_prepare_enable failed when enabling mfg clock\n"); + #endif + #endif + #else + dvfs_disable_by_ptpod(); + gpu_dvfs_disable_by_ptpod(); + #endif + + #if (defined(__KERNEL__) && !defined(EARLY_PORTING)) + { + /* + extern unsigned int ckgen_meter(int val); + eem_debug("@%s(), hf_faxi_ck = %d, hd_faxi_ck = %d\n", + __func__, ckgen_meter(1), ckgen_meter(2)); + */ + } + #endif + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* for Jade-(MT6353) */ + pmic_set_register_value(PMIC_RG_VPROC_MODESET, 1); + pmic_set_register_value(PMIC_RG_VCORE_MODESET, 1); + pmic_set_register_value(PMIC_RG_VCORE2_MODESET, 1); + #else + /* for Jade/Everest/Olympus(MT6351) */ + pmic_config_interface(0x44E, 0x1, 0x1, 1); /* set PWM mode for MT6351 */ + mt6311_config_interface(0x7C, 0x1, 0x1, 6); /* set PWM mode for MT6311 */ + #endif + + /* for slow idle */ + ptp_data[0] = 0xffffffff; + + for_each_det(det) + eem_init_det(det, &eem_devinfo); + + #ifdef __KERNEL__ + mt_cpufreq_set_ptbl_registerCB(mt_cpufreq_set_ptbl_funcEEM); + eem_init01(); + #endif + ptp_data[0] = 0; + + #if (defined(__KERNEL__) && !defined(EARLY_PORTING)) + /* + unsigned int ckgen_meter(int val); + eem_debug("@%s(), hf_faxi_ck = %d, hd_faxi_ck = %d\n", + __func__, + ckgen_meter(1), + ckgen_meter(2)); + */ + #endif + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* for Jade-(MT6353) */ + pmic_set_register_value(PMIC_RG_VPROC_MODESET, 0); + pmic_set_register_value(PMIC_RG_VCORE_MODESET, 0); + pmic_set_register_value(PMIC_RG_VCORE2_MODESET, 0); + #else + /* for Jade/Everest/Olympus(MT6351) */ + mt6311_config_interface(0x7C, 0x0, 0x1, 6); /* set non-PWM mode for MT6311 */ + pmic_config_interface(0x44E, 0x0, 0x1, 1); /* set non-PWM mode for MT6351 */ + #endif + + #ifdef __KERNEL__ + #ifndef EARLY_PORTING + #if !defined(CONFIG_MTK_CLKMGR) + clk_disable_unprepare(clk_mfg); /* Disable GPU clock */ + clk_disable_unprepare(clk_mfg_scp); /* Disable GPU MTCMOSE */ + clk_disable_unprepare(clk_thermal); /* Disable Thermal clock */ + #endif + mt_gpufreq_enable_by_ptpod();/* Disable GPU bulk */ + mt_ppm_ptpod_policy_deactivate(); + /* enable frequency hopping (main PLL) */ + mt_fh_popod_restore();/* I-Chang */ + #endif + #else + gpu_dvfs_enable_by_ptpod(); + dvfs_enable_by_ptpod(); + #endif + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + register_hotcpu_notifier(&_mt_eem_cpu_notifier); + #endif + + eem_debug("eem_probe ok\n"); + FUNC_EXIT(FUNC_LV_MODULE); + + return 0; +} + +static int eem_suspend(struct platform_device *pdev, pm_message_t state) +{ + /* + kthread_stop(eem_volt_thread); + */ + FUNC_ENTER(FUNC_LV_MODULE); + FUNC_EXIT(FUNC_LV_MODULE); + + return 0; +} + +static int eem_resume(struct platform_device *pdev) +{ + /* + eem_volt_thread = kthread_run(eem_volt_thread_handler, 0, "eem volt"); + if (IS_ERR(eem_volt_thread)) + { + eem_debug("[%s]: failed to create eem volt thread\n", __func__); + } + */ + FUNC_ENTER(FUNC_LV_MODULE); + eem_init02(__func__); + FUNC_EXIT(FUNC_LV_MODULE); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id mt_eem_of_match[] = { + { .compatible = "mediatek,mt6755-ptp_fsm", }, + {}, +}; +#endif + +static struct platform_driver eem_driver = { + .remove = NULL, + .shutdown = NULL, + .probe = eem_probe, + .suspend = eem_suspend, + .resume = eem_resume, + .driver = { + .name = "mt-eem", +#ifdef CONFIG_OF + .of_match_table = mt_eem_of_match, +#endif + }, +}; + +#ifndef __KERNEL__ +/* + * For CTP + */ +int no_efuse; + +int can_not_read_efuse(void) +{ + return no_efuse; +} + +int mt_ptp_probe(void) +{ + eem_debug("CTP - In mt_ptp_probe\n"); + no_efuse = eem_init(); + +#if defined(__MTK_SLT_) + if (no_efuse == -1) + return 0; +#endif + eem_probe(NULL); + return 0; +} + +void eem_init01_ctp(unsigned int id) +{ + struct eem_det *det; + struct eem_ctrl *ctrl; + unsigned int out = 0, timeout = 0; + + FUNC_ENTER(FUNC_LV_LOCAL); + + for_each_det_ctrl(det, ctrl) { + unsigned long flag; /* <-XXX */ + + eem_debug("CTP - (%d:%d)\n", + EEM_VOLT_TO_PMIC_VAL(det->ops->get_volt(det)), + det->VBOOT); + + mt_ptp_lock(&flag); /* <-XXX */ + det->ops->init01(det); + mt_ptp_unlock(&flag); /* <-XXX */ + } + + while (1) { + for_each_det_ctrl(det, ctrl) { + if ((EEM_CTRL_LITTLE == det->ctrl_id) && (1 == det->eem_eemen[EEM_PHASE_INIT01])) + out |= BIT(EEM_CTRL_LITTLE); + else if ((EEM_CTRL_GPU == det->ctrl_id) && (1 == det->eem_eemen[EEM_PHASE_INIT01])) + out |= BIT(EEM_CTRL_GPU); + else if ((EEM_CTRL_BIG == det->ctrl_id) && (1 == det->eem_eemen[EEM_PHASE_INIT01])) + out |= BIT(EEM_CTRL_BIG); + } + if ((0x07 == out) || (300 == timeout)) { + eem_error("init01 finish time is %d\n", timeout); + break; + } + udelay(100); + timeout++; + } + + thermal_init(); + udelay(500); + eem_init02(__func__); + + FUNC_EXIT(FUNC_LV_LOCAL); +} + +void ptp_init01_ptp(int id) +{ + eem_init01_ctp(id); +} + +#endif + +#ifdef CONFIG_PROC_FS +int mt_eem_opp_num(enum eem_det_id id) +{ + struct eem_det *det = id_to_eem_det(id); + + FUNC_ENTER(FUNC_LV_API); + FUNC_EXIT(FUNC_LV_API); + + return det->num_freq_tbl; +} +EXPORT_SYMBOL(mt_eem_opp_num); + +void mt_eem_opp_freq(enum eem_det_id id, unsigned int *freq) +{ + struct eem_det *det = id_to_eem_det(id); + int i = 0; + + FUNC_ENTER(FUNC_LV_API); + + for (i = 0; i < det->num_freq_tbl; i++) + freq[i] = det->freq_tbl[i]; + + FUNC_EXIT(FUNC_LV_API); +} +EXPORT_SYMBOL(mt_eem_opp_freq); + +void mt_eem_opp_status(enum eem_det_id id, unsigned int *temp, unsigned int *volt) +{ + struct eem_det *det = id_to_eem_det(id); + int i = 0; + + FUNC_ENTER(FUNC_LV_API); + +#if defined(__KERNEL__) && defined(CONFIG_THERMAL) && !defined(EARLY_PORTING) + *temp = tscpu_get_temp_by_bank( + (id == EEM_DET_LITTLE) ? THERMAL_BANK0 : + (id == EEM_DET_BIG) ? THERMAL_BANK2 : THERMAL_BANK1); /* I-Chang */ +#else + *temp = 0; +#endif + + for (i = 0; i < det->num_freq_tbl; i++) + volt[i] = EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[i]); + + FUNC_EXIT(FUNC_LV_API); +} +EXPORT_SYMBOL(mt_eem_opp_status); + +/*************************** +* return current EEM stauts +****************************/ +int mt_eem_status(enum eem_det_id id) +{ + struct eem_det *det = id_to_eem_det(id); + + FUNC_ENTER(FUNC_LV_API); + + BUG_ON(!det); + BUG_ON(!det->ops); + BUG_ON(!det->ops->get_status); + + FUNC_EXIT(FUNC_LV_API); + + return det->ops->get_status(det); +} + +/** + * =============================================== + * PROCFS interface for debugging + * =============================================== + */ + +/* + * show current EEM stauts + */ +static int eem_debug_proc_show(struct seq_file *m, void *v) +{ + struct eem_det *det = (struct eem_det *)m->private; + + FUNC_ENTER(FUNC_LV_HELP); + + /* FIXME: EEMEN sometimes is disabled temp */ + seq_printf(m, "[%s] (%s, %d) (%d)\n", + ((char *)(det->name) + 8), + det->disabled ? "disabled" : "enable", + det->disabled, + det->ops->get_status(det) + ); + + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +/* + * set EEM status by procfs interface + */ +static ssize_t eem_debug_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + int ret; + int enabled = 0; + char *buf = (char *) __get_free_page(GFP_USER); + struct eem_det *det = (struct eem_det *)PDE_DATA(file_inode(file)); + + FUNC_ENTER(FUNC_LV_HELP); + + if (!buf) { + FUNC_EXIT(FUNC_LV_HELP); + return -ENOMEM; + } + + ret = -EINVAL; + + if (count >= PAGE_SIZE) + goto out; + + ret = -EFAULT; + + if (copy_from_user(buf, buffer, count)) + goto out; + + buf[count] = '\0'; + + if (!kstrtoint(buf, 10, &enabled)) { + ret = 0; + + if (0 == enabled) + /* det->ops->enable(det, BY_PROCFS); */ + det->ops->disable(det, 0); + else if (1 == enabled) + det->ops->disable(det, BY_PROCFS); + else if (2 == enabled) + det->ops->disable(det, BY_PROCFS_INIT2); + } else + ret = -EINVAL; + +out: + free_page((unsigned long)buf); + FUNC_EXIT(FUNC_LV_HELP); + + return (ret < 0) ? ret : count; +} + +/* + * show current EEM data + */ +static int eem_dump_proc_show(struct seq_file *m, void *v) +{ + struct eem_det *det; + int *val = (int *)&eem_devinfo; + int i; + #if DUMP_DATA_TO_DE + int j; + #endif + + + FUNC_ENTER(FUNC_LV_HELP); + /* + eem_detectors[EEM_DET_BIG].ops->dump_status(&eem_detectors[EEM_DET_BIG]); + eem_detectors[EEM_DET_LITTLE].ops->dump_status(&eem_detectors[EEM_DET_LITTLE]); + seq_printf(m, "det->EEMMONEN= 0x%08X,det->EEMINITEN= 0x%08X\n", det->EEMMONEN, det->EEMINITEN); + seq_printf(m, "leakage_core\t= %d\n" + "leakage_gpu\t= %d\n" + "leakage_little\t= %d\n" + "leakage_big\t= %d\n", + leakage_core, + leakage_gpu, + leakage_sram2, + leakage_sram1 + ); + */ + + + for (i = 0; i < sizeof(struct eem_devinfo)/sizeof(unsigned int); i++) + seq_printf(m, "M_HW_RES%d\t= 0x%08X\n", i, val[i]); + + for_each_det(det) { + for (i = EEM_PHASE_INIT01; i < NR_EEM_PHASE; i++) { + seq_printf(m, "Bank_number = %d\n", det->ctrl_id); + if (i < EEM_PHASE_MON) + seq_printf(m, "mode = init%d\n", i); + else + seq_puts(m, "mode = mon"); + if (eem_log_en) { + seq_printf(m, "0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n", + det->dcvalues[i], + det->eem_freqpct30[i], + det->eem_26c[i], + det->eem_vop30[i], + det->eem_eemen[i] + ); + + /* if (det->eem_eemen[i] == 0x5) */ + { + seq_printf(m, "EEM_LOG: Bank_number = [%d] (%d)\n", + det->ctrl_id, det->ops->get_temp(det)); + + seq_printf(m, "p(%d, %d, %d, %d, %d, %d, %d, %d)\n", + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[0]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[1]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[2]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[3]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[4]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[5]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[6]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[7])); + + seq_printf(m, "2(%d, %d, %d, %d, %d, %d, %d, %d)\n", + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_init2[0]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_init2[1]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_init2[2]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_init2[3]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_init2[4]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_init2[5]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_init2[6]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_init2[7])); + + seq_printf(m, "f(%d, %d, %d, %d, %d, %d, %d, %d)\n", + det->freq_tbl[0], + det->freq_tbl[1], + det->freq_tbl[2], + det->freq_tbl[3], + det->freq_tbl[4], + det->freq_tbl[5], + det->freq_tbl[6], + det->freq_tbl[7]); + } + } + #if DUMP_DATA_TO_DE + for (j = 0; j < ARRAY_SIZE(reg_dump_addr_off); j++) + seq_printf(m, "0x%08lx = 0x%08x\n", + (unsigned long)EEM_BASEADDR + reg_dump_addr_off[j], + det->reg_dump_data[j][i] + ); + #endif + } + } + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +/* + * show current voltage + */ +static int eem_cur_volt_proc_show(struct seq_file *m, void *v) +{ + struct eem_det *det = (struct eem_det *)m->private; + u32 rdata = 0, i; + + FUNC_ENTER(FUNC_LV_HELP); + + rdata = det->ops->get_volt(det); + + if (rdata != 0) + seq_printf(m, "%d\n", rdata); + else + seq_printf(m, "EEM[%s] read current voltage fail\n", det->name); + + if (EEM_CTRL_GPU != det->ctrl_id) { + for (i = 0; i < NR_FREQ; i++) { + seq_printf(m, "(SSC, 0x%x) (Vs, 0x%x) (Vp, 0x%x)\n", + det->recordRef[i*2] >> 16 & 0xFFF, + det->recordRef[i*2] >> 7 & 0x7F, + det->recordRef[i*2] & 0x7F + ); + + seq_printf(m, "(F_Setting)(%x, %x, %x, %x, %x, %x)\n", + (det->recordRef[i*2+1] >> 27) & 0x1F, + (det->recordRef[i*2+1] >> 22) & 0x1F, + (det->recordRef[i*2+1] >> 17) & 0x1F, + (det->recordRef[i*2+1] >> 12) & 0x1F, + (det->recordRef[i*2+1] >> 9) & 0x07, + det->recordRef[i*2+1] & 0x1ff + ); + } + } + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +/* + * update record message + */ +static ssize_t eem_cur_volt_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + int ret; + char *buf = (char *) __get_free_page(GFP_USER); + unsigned int voltValue = 0, voltProc = 0, voltSram = 0, voltPmic = 0, index = 0; + struct eem_det *det = (struct eem_det *)PDE_DATA(file_inode(file)); + + FUNC_ENTER(FUNC_LV_HELP); + + if (!buf) { + FUNC_EXIT(FUNC_LV_HELP); + return -ENOMEM; + } + + ret = -EINVAL; + + if (count >= PAGE_SIZE) + goto out; + + ret = -EFAULT; + + if (copy_from_user(buf, buffer, count)) + goto out; + + buf[count] = '\0'; + + if (EEM_CTRL_GPU != det->ctrl_id) { + /* if (sscanf(buf, "%d", &voltValue) == 1) { */ + if (2 == sscanf(buf, "%u %u", &voltValue, &index)) { + ret = 0; + det->recordRef[NR_FREQ * 2] = 0x00000000; + mb(); /* SRAM writing */ + voltPmic = EEM_VOLT_TO_PMIC_VAL(voltValue) + EEM_PMIC_OFFSET; + voltProc = clamp(voltPmic, + det->VMIN + EEM_PMIC_OFFSET, + det->VMAX + EEM_PMIC_OFFSET); + + voltSram = clamp((unsigned int)(voltProc + 0x10), + (unsigned int)(VMIN_SRAM + EEM_PMIC_OFFSET), + (unsigned int)(det->VMAX + EEM_PMIC_OFFSET)); + + /* for (i = 0; i < NR_FREQ; i++) */ + if ((index >= 0) && (index < 8)) + det->recordRef[index*2] = (det->recordRef[index*2] & (~0x3FFF)) | + (((voltSram & 0x7F) << 7) | (voltProc & 0x7F)); + + det->recordRef[NR_FREQ * 2] = 0xFFFFFFFF; + mb(); /* SRAM writing */ + } else { + ret = -EINVAL; + eem_debug("bad argument_1!! argument should be 80000 ~ 115500, index = (0 ~ 8)\n"); + } + } +out: + free_page((unsigned long)buf); + FUNC_EXIT(FUNC_LV_HELP); + + return (ret < 0) ? ret : count; +} + +#ifdef __KERNEL__ +#define VPROC_MAX 125000 +#define CPU_TURBO_VOLT_DIFF_1 4375 +#define CPU_TURBO_VOLT_DIFF_2 2500 +#define NUM_OF_CPU_FREQ_TABLE 8 +#define NUM_OF_GPU_FREQ_TABLE 8 + +static int volt_to_buck_volt(u32 cur_volt, int need) +{ + if (need) { + if (cur_volt >= VPROC_MAX) + return VPROC_MAX; + else { + if (cur_volt % 625 == 0) + return cur_volt; + else + return (cur_volt + 625) / 1000 * 1000; + } + } + return cur_volt; +} + +static int eem_not_work(u32 cur_volt, unsigned int *volt_tbl_pmic, int num) +{ + int i; + int need = 0; + + if (num == NUM_OF_CPU_FREQ_TABLE) { + need = 1; + eem_isr_info("CPU: In eem_not_work, cur_volt = %d -> %d\n", + cur_volt, + EEM_VOLT_TO_PMIC_VAL(cur_volt)); + } else + eem_isr_info("GPU: In eem_not_work, cur_volt = %d -> %d\n", + cur_volt, + EEM_VOLT_TO_PMIC_VAL(cur_volt)); + + for (i = 0; i < num; i++) { + eem_isr_info("volt_tbl_pmic[%d] = %d => %d\n", + i, + volt_tbl_pmic[i], + volt_to_buck_volt(EEM_PMIC_VAL_TO_VOLT(volt_tbl_pmic[i]), need)); + + if (cur_volt == volt_to_buck_volt(EEM_PMIC_VAL_TO_VOLT(volt_tbl_pmic[i]), need)) + return 0; + } + + if ((cur_volt == (EEM_PMIC_VAL_TO_VOLT(volt_tbl_pmic[0]) + CPU_TURBO_VOLT_DIFF_1)) || + (cur_volt == (EEM_PMIC_VAL_TO_VOLT(volt_tbl_pmic[0]) + CPU_TURBO_VOLT_DIFF_2))) { + eem_isr_info("%d, %d, %d\n", + cur_volt, + EEM_PMIC_VAL_TO_VOLT(volt_tbl_pmic[0]) + CPU_TURBO_VOLT_DIFF_1, + EEM_PMIC_VAL_TO_VOLT(volt_tbl_pmic[0]) + CPU_TURBO_VOLT_DIFF_2); + return 0; + } + return 1; +} + +static int eem_stress_result_proc_show(struct seq_file *m, void *v) +{ + unsigned int result = 0; + struct eem_det *det; + u32 rdata = 0; + + FUNC_ENTER(FUNC_LV_HELP); + + for_each_det(det) { + rdata = det->ops->get_volt(det); + switch (det->ctrl_id) { + case EEM_CTRL_LITTLE: /* I-Chang */ + result |= (eem_not_work(rdata, det->volt_tbl_pmic, + NUM_OF_CPU_FREQ_TABLE) << EEM_CTRL_LITTLE); + if ((result & (1 << EEM_CTRL_LITTLE)) != 0) + eem_isr_info("BANK0 EEM fail\n"); + break; + + case EEM_CTRL_BIG: /* I-Chang */ + result |= (eem_not_work(rdata, det->volt_tbl_pmic, + NUM_OF_CPU_FREQ_TABLE) << EEM_CTRL_BIG); + if ((result & (1 << EEM_CTRL_BIG)) != 0) + eem_isr_info("BANK2 EEM fail\n"); + break; + + case EEM_CTRL_GPU: /* I-Chang */ + result |= (eem_not_work(rdata, det->volt_tbl_pmic, + NUM_OF_GPU_FREQ_TABLE) << EEM_CTRL_GPU); + if ((result & (1 << EEM_CTRL_GPU)) != 0) + eem_isr_info("GPU EEM fail\n"); + break; + + default: + break; + } + } + seq_printf(m, "0x%X\n", result); + return 0; +} +#endif +/* + * show current EEM status + */ +static int eem_status_proc_show(struct seq_file *m, void *v) +{ + struct eem_det *det = (struct eem_det *)m->private; + + FUNC_ENTER(FUNC_LV_HELP); + + seq_printf(m, "bank = %d, (%d) - p(%d, %d, %d, %d, %d, %d, %d, %d) - (%d, %d, %d, %d, %d, %d, %d, %d)\n", + det->ctrl_id, det->ops->get_temp(det), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[0]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[1]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[2]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[3]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[4]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[5]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[6]), + EEM_PMIC_VAL_TO_VOLT(det->volt_tbl_pmic[7]), + + det->freq_tbl[0], + det->freq_tbl[1], + det->freq_tbl[2], + det->freq_tbl[3], + det->freq_tbl[4], + det->freq_tbl[5], + det->freq_tbl[6], + det->freq_tbl[7]); + + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +/* + * set EEM log enable by procfs interface + */ + +static int eem_log_en_proc_show(struct seq_file *m, void *v) +{ + FUNC_ENTER(FUNC_LV_HELP); + seq_printf(m, "%d\n", eem_log_en); + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +static ssize_t eem_log_en_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + int ret; + char *buf = (char *) __get_free_page(GFP_USER); + + FUNC_ENTER(FUNC_LV_HELP); + + if (!buf) { + FUNC_EXIT(FUNC_LV_HELP); + return -ENOMEM; + } + + ret = -EINVAL; + + if (count >= PAGE_SIZE) + goto out; + + ret = -EFAULT; + + if (copy_from_user(buf, buffer, count)) + goto out; + + buf[count] = '\0'; + + ret = -EINVAL; + + if (kstrtoint(buf, 10, &eem_log_en)) { + eem_debug("bad argument!! Should be \"0\" or \"1\"\n"); + goto out; + } + + ret = 0; + + switch (eem_log_en) { + case 0: + eem_debug("EEM log disabled.\n"); + hrtimer_cancel(&eem_log_timer); + break; + + case 1: + eem_debug("EEM log enabled.\n"); + hrtimer_start(&eem_log_timer, ns_to_ktime(LOG_INTERVAL), HRTIMER_MODE_REL); + break; + + default: + eem_debug("bad argument!! Should be \"0\" or \"1\"\n"); + ret = -EINVAL; + } + +out: + free_page((unsigned long)buf); + FUNC_EXIT(FUNC_LV_HELP); + + return (ret < 0) ? ret : count; +} + + +/* + * show EEM offset + */ +static int eem_offset_proc_show(struct seq_file *m, void *v) +{ + struct eem_det *det = (struct eem_det *)m->private; + + FUNC_ENTER(FUNC_LV_HELP); + + seq_printf(m, "%d\n", det->volt_offset); + + FUNC_EXIT(FUNC_LV_HELP); + + return 0; +} + +/* + * set EEM offset by procfs + */ +static ssize_t eem_offset_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + int ret; + char *buf = (char *) __get_free_page(GFP_USER); + int offset = 0; + struct eem_det *det = (struct eem_det *)PDE_DATA(file_inode(file)); + + FUNC_ENTER(FUNC_LV_HELP); + + if (!buf) { + FUNC_EXIT(FUNC_LV_HELP); + return -ENOMEM; + } + + ret = -EINVAL; + + if (count >= PAGE_SIZE) + goto out; + + ret = -EFAULT; + + if (copy_from_user(buf, buffer, count)) + goto out; + + buf[count] = '\0'; + + if (!kstrtoint(buf, 10, &offset)) { + ret = 0; + det->volt_offset = offset; + eem_set_eem_volt(det); + } else { + ret = -EINVAL; + eem_debug("bad argument_1!! argument should be \"0\"\n"); + } + +out: + free_page((unsigned long)buf); + FUNC_EXIT(FUNC_LV_HELP); + + return (ret < 0) ? ret : count; +} + +#define PROC_FOPS_RW(name) \ + static int name ## _proc_open(struct inode *inode, \ + struct file *file) \ + { \ + return single_open(file, name ## _proc_show, \ + PDE_DATA(inode)); \ + } \ + static const struct file_operations name ## _proc_fops = { \ + .owner = THIS_MODULE, \ + .open = name ## _proc_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + .write = name ## _proc_write, \ + } + +#define PROC_FOPS_RO(name) \ + static int name ## _proc_open(struct inode *inode, \ + struct file *file) \ + { \ + return single_open(file, name ## _proc_show, \ + PDE_DATA(inode)); \ + } \ + static const struct file_operations name ## _proc_fops = { \ + .owner = THIS_MODULE, \ + .open = name ## _proc_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } + +#define PROC_ENTRY(name) {__stringify(name), &name ## _proc_fops} + +PROC_FOPS_RW(eem_debug); +PROC_FOPS_RO(eem_dump); +PROC_FOPS_RO(eem_stress_result); +PROC_FOPS_RW(eem_log_en); +PROC_FOPS_RO(eem_status); +PROC_FOPS_RW(eem_cur_volt); +PROC_FOPS_RW(eem_offset); + +static int create_procfs(void) +{ + struct proc_dir_entry *eem_dir = NULL; + struct proc_dir_entry *det_dir = NULL; + int i; + struct eem_det *det; + + struct pentry { + const char *name; + const struct file_operations *fops; + }; + + struct pentry det_entries[] = { + PROC_ENTRY(eem_debug), + PROC_ENTRY(eem_status), + PROC_ENTRY(eem_cur_volt), + PROC_ENTRY(eem_offset), + }; + + struct pentry eem_entries[] = { + PROC_ENTRY(eem_dump), + PROC_ENTRY(eem_log_en), + PROC_ENTRY(eem_stress_result), + }; + + FUNC_ENTER(FUNC_LV_HELP); + + eem_dir = proc_mkdir("eem", NULL); + + if (!eem_dir) { + eem_debug("[%s]: mkdir /proc/eem failed\n", __func__); + FUNC_EXIT(FUNC_LV_HELP); + return -1; + } + + for (i = 0; i < ARRAY_SIZE(eem_entries); i++) { + if (!proc_create(eem_entries[i].name, S_IRUGO | S_IWUSR | S_IWGRP, eem_dir, eem_entries[i].fops)) { + eem_debug("[%s]: create /proc/eem/%s failed\n", __func__, eem_entries[i].name); + FUNC_EXIT(FUNC_LV_HELP); + return -3; + } + } + + for_each_det(det) { + det_dir = proc_mkdir(det->name, eem_dir); + + if (!det_dir) { + eem_debug("[%s]: mkdir /proc/eem/%s failed\n", __func__, det->name); + FUNC_EXIT(FUNC_LV_HELP); + return -2; + } + + for (i = 0; i < ARRAY_SIZE(det_entries); i++) { + if (!proc_create_data(det_entries[i].name, + S_IRUGO | S_IWUSR | S_IWGRP, + det_dir, det_entries[i].fops, det)) { + eem_debug("[%s]: create /proc/eem/%s/%s failed\n", __func__, + det->name, det_entries[i].name); + FUNC_EXIT(FUNC_LV_HELP); + return -3; + } + } + } + + FUNC_EXIT(FUNC_LV_HELP); + return 0; +} + +int get_ptpod_status(void) +{ + get_devinfo(&eem_devinfo); + + return eem_devinfo.EEMINITEN; + +} +EXPORT_SYMBOL(get_ptpod_status); +#endif + +#if 0 +#define VLTE_BIN0_VMAX (121000) +#define VLTE_BIN0_VMIN (104500) +#define VLTE_BIN0_VNRL (110625) + +#define VLTE_BIN1_VMAX (121000) +#define VLTE_BIN1_VMIN (102500) +#define VLTE_BIN1_VNRL (105000) + +#define VLTE_BIN2_VMAX (121000) +#define VLTE_BIN2_VMIN (97500) +#define VLTE_BIN2_VNRL (100000) + +#define VSOC_BIN0_VMAX (126500) +#define VSOC_BIN0_VMIN (109000) +#define VSOC_BIN0_VNRL (115000) + +#define VSOC_BIN1_VMAX (126500) +#define VSOC_BIN1_VMIN (107500) +#define VSOC_BIN1_VNRL (110000) + +#define VSOC_BIN2_VMAX (126500) +#define VSOC_BIN2_VMIN (102500) +#define VSOC_BIN2_VNRL (105000) + +#if defined(SLT_VMAX) +#define VLTE_BIN(x) VLTE_BIN##x##_VMAX +#define VSOC_BIN(x) VSOC_BIN##x##_VMAX +#elif defined(SLT_VMIN) +#define VLTE_BIN(x) VLTE_BIN##x##_VMIN +#define VSOC_BIN(x) VSOC_BIN##x##_VMIN +#else +#define VLTE_BIN(x) VLTE_BIN##x##_VNRL +#define VSOC_BIN(x) VSOC_BIN##x##_VNRL +#endif + +void process_voltage_bin(struct eem_devinfo *devinfo) +{ + switch (devinfo->LTE_VOLTBIN) { + case 0: + #ifndef EARLY_PORTING + #ifdef __KERNEL__ + /* det->volt_tbl_bin[0] = EEM_VOLT_TO_PMIC_VAL(VLTE_BIN(0)) + EEM_PMIC_OFFSET; */ + mt_cpufreq_set_lte_volt(EEM_VOLT_TO_PMIC_VAL(VLTE_BIN(0)) + EEM_PMIC_OFFSET); + #else + dvfs_set_vlte(EEM_VOLT_TO_PMIC_VAL(VLTE_BIN(0)) + EEM_PMIC_OFFSET); + #endif + #endif + eem_debug("VLTE voltage bin to %dmV\n", (VLTE_BIN(0)/100)); + break; + case 1: + #ifndef EARLY_PORTING + #ifdef __KERNEL__ + /* det->volt_tbl_bin[0] = EEM_VOLT_TO_PMIC_VAL(105000) + EEM_PMIC_OFFSET; */ + mt_cpufreq_set_lte_volt(EEM_VOLT_TO_PMIC_VAL(105000) + EEM_PMIC_OFFSET); + #else + dvfs_set_vlte(EEM_VOLT_TO_PMIC_VAL(VLTE_BIN(1)) + EEM_PMIC_OFFSET); + #endif + #endif + eem_debug("VLTE voltage bin to %dmV\n", (VLTE_BIN(1)/100)); + break; + case 2: + #ifndef EARLY_PORTING + #ifdef __KERNEL__ + /* det->volt_tbl_bin[0] = EEM_VOLT_TO_PMIC_VAL(100000) + EEM_PMIC_OFFSET; */ + mt_cpufreq_set_lte_volt(EEM_VOLT_TO_PMIC_VAL(100000) + EEM_PMIC_OFFSET); + #else + dvfs_set_vlte(EEM_VOLT_TO_PMIC_VAL(VLTE_BIN(2)) + EEM_PMIC_OFFSET); + #endif + #endif + eem_debug("VLTE voltage bin to %dmV\n", (VLTE_BIN(2)/100)); + break; + default: + #ifndef EARLY_PORTING + #ifdef __KERNEL__ + mt_cpufreq_set_lte_volt(EEM_VOLT_TO_PMIC_VAL(110625) + EEM_PMIC_OFFSET); + #else + dvfs_set_vlte(EEM_VOLT_TO_PMIC_VAL(110625) + EEM_PMIC_OFFSET); + #endif + #endif + eem_debug("VLTE voltage bin to 1.10625V\n"); + break; + }; + /* mt_cpufreq_set_lte_volt(det->volt_tbl_bin[0]); */ + + switch (devinfo->SOC_VOLTBIN) { + case 0: +#ifdef __MTK_SLT_ + if (!slt_is_low_vcore()) { + dvfs_set_vcore(EEM_VOLT_TO_PMIC_VAL(VSOC_BIN(0)) + EEM_PMIC_OFFSET); + eem_debug("VCORE voltage bin to %dmV\n", (VSOC_BIN(0)/100)); + } else { + dvfs_set_vcore(EEM_VOLT_TO_PMIC_VAL(105000) + EEM_PMIC_OFFSET); + eem_debug("VCORE voltage bin to %dmV\n", (105000/100)); + } +#else + dvfs_set_vcore(EEM_VOLT_TO_PMIC_VAL(VSOC_BIN(0)) + EEM_PMIC_OFFSET); + eem_debug("VCORE voltage bin to %dmV\n", (VSOC_BIN(0)/100)); +#endif + break; + case 1: + dvfs_set_vcore(EEM_VOLT_TO_PMIC_VAL(VSOC_BIN(1)) + EEM_PMIC_OFFSET); + eem_debug("VCORE voltage bin to %dmV\n", (VSOC_BIN(1)/100)); + break; + case 2: + dvfs_set_vcore(EEM_VOLT_TO_PMIC_VAL(VSOC_BIN(2)) + EEM_PMIC_OFFSET); + eem_debug("VCORE voltage bin to %dmV\n", (VSOC_BIN(2)/100)); + break; + default: + dvfs_set_vcore(EEM_VOLT_TO_PMIC_VAL(105000) + EEM_PMIC_OFFSET); + eem_debug("VCORE voltage bin to 1.05V\n"); + break; + }; +} +#endif + +#define VCORE_VOLT_0 1000000 +#define VCORE_VOLT_1 900000 +#define VCORE_VOLT_2 900000 + +unsigned int vcore0; +unsigned int vcore1; +unsigned int vcore2; +unsigned int have_550; + +int is_have_550(void) +{ + return have_550; +} + +unsigned int get_vcore_ptp_volt(int uv) +{ + unsigned int ret; + + switch (uv) { + case VCORE_VOLT_0: + /* ret = vcore0; */ + ret = EEM_VOLT_TO_PMIC_VAL(VCORE_VOLT_0 / 10) + EEM_PMIC_OFFSET; + break; + + case VCORE_VOLT_1: + /* ret = vcore1; */ + ret = EEM_VOLT_TO_PMIC_VAL(VCORE_VOLT_1 / 10) + EEM_PMIC_OFFSET; + break; + + /* Jade only use 2 level voltage + case VCORE_VOLT_2: + ret = vcore2; + break; + */ + default: + ret = EEM_VOLT_TO_PMIC_VAL(uv / 10) + EEM_PMIC_OFFSET; + break; + } + + if (ret == 0) + ret = EEM_VOLT_TO_PMIC_VAL(uv / 10) + EEM_PMIC_OFFSET; + + return ret; +} + +void eem_set_pi_offset(enum eem_ctrl_id id, int step) +{ + struct eem_det *det = id_to_eem_det(id); + + det->pi_offset = step; + +#ifdef CONFIG_EEM_AEE_RR_REC + aee_rr_rec_eem_pi_offset(step); +#endif +} + +#ifdef __KERNEL__ +static int __init dt_get_ptp_devinfo(unsigned long node, const char *uname, int depth, void *data) +{ + struct devinfo_ptp_tag *tags; + unsigned int size = 0; + + if (depth != 1 || (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; + + tags = (struct devinfo_ptp_tag *) of_get_flat_dt_prop(node, "atag,ptp", &size); + + if (tags) { + vcore0 = tags->volt0; + vcore1 = tags->volt1; + vcore2 = tags->volt2; + have_550 = tags->have_550; + eem_debug("[PTP][VCORE] - Kernel Got from DT (0x%0X, 0x%0X, 0x%0X, 0x%0X)\n", + vcore0, vcore1, vcore2, have_550); + } + return 1; +} + +static int __init vcore_ptp_init(void) +{ + of_scan_flat_dt(dt_get_ptp_devinfo, NULL); + + return 0; +} + +/* + * Module driver + */ + +static int __init eem_conf(void) +{ + int i; + unsigned int binLevel; + #if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + unsigned int freq_bound, binLevel_eng; + #endif + struct device_node *cpuSpeedNode = NULL; + + recordRef = ioremap_nocache(EEMCONF_S, EEMCONF_SIZE); + eem_debug("@(Record)%s----->(%p)\n", __func__, recordRef); + memset_io((u8 *)recordRef, 0x00, EEMCONF_SIZE); + if (!recordRef) + return -ENOMEM; + + cpuSpeedNode = of_find_node_by_type(NULL, "cpu"); + cpu_speed = 0; + + if (!of_property_read_u32(cpuSpeedNode, "clock-frequency", &cpu_speed)) + cpu_speed = cpu_speed / 1000 / 1000; /* MHz */ + else { + eem_error("missing clock-frequency property, use EFUSE to get FY/SB\n"); + cpu_speed = 0; + } + eem_error("0--->The cpu_speed = %d\n", cpu_speed); + + /* read E-fuse for segment selection */ + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + binLevel = 1; + if (0) { + #else + binLevel = GET_BITS_VAL(7:0, get_devinfo_with_index(21)); + binLevel_eng = GET_BITS_VAL(15:0, get_devinfo_with_index(19)); + freq_bound = GET_BITS_VAL(25:23, get_devinfo_with_index(4)); + if (1001 == cpu_speed) { + #endif + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (0) { + #else + if (freq_bound == 5) { + recordTbl = &fyTbl_M[0][0]; + eem_debug("1--->The table ----->(fyTbl_M), cpu_speed = %d\n", cpu_speed); + #endif + } else { + recordTbl = &fyTbl[0][0]; + eem_debug("1--->The table ----->(fyTbl), cpu_speed = %d\n", cpu_speed); + } + } else { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (1 == binLevel) { + #else + if ((1 == binLevel) || (3 == binLevel)) { + #endif + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (0) { + #else + if (freq_bound == 5) { + recordTbl = &fyTbl_M[0][0]; + eem_error("@The table ----->(fyTbl_M)\n"); + #endif + } else { + recordTbl = &fyTbl[0][0]; + eem_error("@The table ----->(fyTbl)\n"); + } + #if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + } else if ((2 == binLevel) || (4 == binLevel)) { + recordTbl = &sbTbl[0][0]; + eem_error("@The table ----->(sbTbl)\n"); + #endif + #ifdef CONFIG_ARCH_MT6755_TURBO + } else if (0x22 == binLevel) { + recordTbl = &p15Tbl[0][0]; + eem_error("@The table ----->(p15Tbl)\n"); + #endif + } else { + #if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if ((2 == ((binLevel_eng >> 4) & 0x07)) || (2 == ((binLevel_eng >> 10) & 0x07))) { + if (freq_bound == 5) { + recordTbl = &fyTbl_M[0][0]; + eem_error("@The table ----->(ENG fyTbl_M)\n"); + } else { + recordTbl = &fyTbl[0][0]; + eem_error("@The table ----->(ENG fyTbl)\n"); + } + } else { + recordTbl = &sbTbl[0][0]; + eem_error("@The table ----->(ENG sbTbl)\n"); + } + #else + recordTbl = &fyTbl[0][0]; + #endif + } + } + + /* [13:7] = Vsram pmic value, [6:0] = Vproc pmic value */ + for (i = 0; i < NR_FREQ; i++) { + /* LL */ + recordRef[i * 2] = + ((*(recordTbl + (i * 9) + 6) & 0xFFF)<<16) | + ((*(recordTbl + (i * 9) + 7) & 0x7F) << 7) | + (*(recordTbl + (i * 9) + 8) & 0x7F); + recordRef[i * 2 + 1] = + ((*(recordTbl + (i * 9) + 0) & 0x1F) << 27) | + ((*(recordTbl + (i * 9) + 1) & 0x1F) << 22) | + ((*(recordTbl + (i * 9) + 2) & 0x1F) << 17) | + ((*(recordTbl + (i * 9) + 3) & 0x1F) << 12) | + ((*(recordTbl + (i * 9) + 4) & 0x07) << 9) | + (*(recordTbl + (i * 9) + 5) & 0x1FF); + + /* L */ + recordRef[i * 2 + 36] = + ((*(recordTbl + ((i + 8) * 9) + 6) & 0xFFF)<<16) | + ((*(recordTbl + ((i + 8) * 9) + 7) & 0x7F) << 7) | + (*(recordTbl + ((i + 8) * 9) + 8) & 0x7F); + recordRef[i * 2 + 36 + 1] = + ((*(recordTbl + ((i + 8) * 9) + 0) & 0x1F) << 27) | + ((*(recordTbl + ((i + 8) * 9) + 1) & 0x1F) << 22) | + ((*(recordTbl + ((i + 8) * 9) + 2) & 0x1F) << 17) | + ((*(recordTbl + ((i + 8) * 9) + 3) & 0x1F) << 12) | + ((*(recordTbl + ((i + 8) * 9) + 4) & 0x07) << 9) | + (*(recordTbl + ((i + 8) * 9) + 5) & 0x1FF); + } + recordRef[i*2] = 0xffffffff; + recordRef[i*2+36] = 0xffffffff; + mb(); /* SRAM writing */ + for (i = 0; i < NR_FREQ; i++) { + eem_debug("LL (SSC, 0x%x) (Vs, 0x%x) (Vp, 0x%x)\n", + ((*(recordRef + (i * 2))) >> 16) & 0xFFF, + ((*(recordRef + (i * 2))) >> 7) & 0x7F, + (*(recordRef + (i * 2))) & 0x7F + ); + + eem_debug("LL(F_Setting)(%x, %x, %x, %x, %x, %x)\n", + ((*(recordRef + (i * 2) + 1)) >> 27) & 0x1F, + ((*(recordRef + (i * 2) + 1)) >> 22) & 0x1F, + ((*(recordRef + (i * 2) + 1)) >> 17) & 0x1F, + ((*(recordRef + (i * 2) + 1)) >> 12) & 0x1F, + ((*(recordRef + (i * 2) + 1)) >> 9) & 0x07, + ((*(recordRef + (i * 2) + 1)) & 0x1ff) + ); + + eem_debug("L (SSC, 0x%x) (Vs, 0x%x) (Vp, 0x%x),\n", + ((*(recordRef + 36 + (i * 2))) >> 16) & 0xFFF, + ((*(recordRef + 36 + (i * 2))) >> 7) & 0x7F, + (*(recordRef + 36 + (i * 2))) & 0x7F + ); + + eem_debug("L(F_Setting)(%x, %x, %x, %x, %x, %x)\n", + ((*(recordRef + 36 + (i * 2) + 1)) >> 27) & 0x1F, + ((*(recordRef + 36 + (i * 2) + 1)) >> 22) & 0x1F, + ((*(recordRef + 36 + (i * 2) + 1)) >> 17) & 0x1F, + ((*(recordRef + 36 + (i * 2) + 1)) >> 12) & 0x1F, + ((*(recordRef + 36 + (i * 2) + 1)) >> 9) & 0x07, + ((*(recordRef + 36 + (i * 2) + 1)) & 0x1ff) + ); + } + return 0; +} + +static int new_eem_val = 1; /* default no change */ +static int __init fn_change_eem_status(char *str) +{ + int new_set_val; + + eem_debug("fn_change_eem_status\n"); + if (get_option(&str, &new_set_val)) { + new_eem_val = new_set_val; + eem_debug("new_eem_val = %d\n", new_eem_val); + return 0; + } + return -EINVAL; +} +early_param("eemen", fn_change_eem_status); + +static int __init eem_init(void) +#else +int __init eem_init(void) +#endif +{ + int err = 0; +#ifdef __KERNEL__ + struct device_node *node = NULL; +#endif + FUNC_ENTER(FUNC_LV_MODULE); + +#ifdef __KERNEL__ + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-ptp_fsm"); + + if (node) { + /* Setup IO addresses */ + eem_base = of_iomap(node, 0); + eem_debug("[EEM] eem_base = 0x%p\n", eem_base); + } + + /*get eem irq num*/ + eem_irq_number = irq_of_parse_and_map(node, 0); + eem_debug("[THERM_CTRL] eem_irq_number=%d\n", eem_irq_number); + if (!eem_irq_number) { + eem_debug("[EEM] get irqnr failed=0x%x\n", eem_irq_number); + return 0; + } + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* apmixed */ + node = of_find_compatible_node(NULL, NULL, "mediatek,apmixed"); + if (node) { + eem_apmixed_base = of_iomap(node, 0); + eem_debug("[EEM] eem_apmixed_base = 0x%p\n", eem_apmixed_base); + } + #endif + +#endif + get_devinfo(&eem_devinfo); +#ifdef __KERNEL__ + if (new_eem_val == 0) { + eem_devinfo.EEMINITEN = 0; + eem_debug("Disable EEM by kernel config\n"); + } +#endif + /* process_voltage_bin(&eem_devinfo); */ /* LTE voltage bin use I-Chang */ + /* eem_devinfo.EEMINITEN = 0; DISABLE_EEM!!! */ + if (0 == eem_devinfo.EEMINITEN) { + eem_error("EEMINITEN = 0x%08X\n", eem_devinfo.EEMINITEN); + FUNC_EXIT(FUNC_LV_MODULE); + return 0; + } + +#ifdef __KERNEL__ + /* + * init timer for log / volt + */ + hrtimer_init(&eem_log_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + eem_log_timer.function = eem_log_timer_func; + + create_procfs(); +#endif + + /* + * reg platform device driver + */ + err = platform_driver_register(&eem_driver); + + if (err) { + eem_debug("EEM driver callback register failed..\n"); + FUNC_EXIT(FUNC_LV_MODULE); + return err; + } + + FUNC_EXIT(FUNC_LV_MODULE); + + return 0; +} + +static void __exit eem_exit(void) +{ + FUNC_ENTER(FUNC_LV_MODULE); + eem_debug("EEM de-initialization\n"); + FUNC_EXIT(FUNC_LV_MODULE); +} + +#ifdef __KERNEL__ +module_init(eem_conf); +arch_initcall(vcore_ptp_init); /* I-Chang */ +late_initcall(eem_init); +#endif +#endif + +MODULE_DESCRIPTION("MediaTek EEM Driver v0.3"); +MODULE_LICENSE("GPL"); +#ifdef EARLY_PORTING + #undef EARLY_PORTING +#endif +#undef __MT_EEM_C__ + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_ptp.h b/drivers/misc/mediatek/base/power/mt6755/mt_ptp.h new file mode 100644 index 0000000000000000000000000000000000000000..7123d7fc294f9a16d4dfa8766c500dd2a19f58e2 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_ptp.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_PTP_ +#define _MT_PTP_ + +#ifdef __KERNEL__ +#include +#include +#endif + +#define EN_EEM_OD (1) /* enable/disable EEM-OD (SW) */ + +/** + * 1: Select VCORE_AO ptpod detector + * 0: Select VCORE_PDN ptpod detector + */ + +/* +#define PERI_VCORE_EEM_CON0 (PERICFG_BASE + 0x408) +#define VCORE_PTPODSEL 0:0 +#define SEL_VCORE_AO 1 +#define SEL_VCORE_PDN 0 +*/ + +/* Thermal Register Definition */ + +/* EEM Structure */ +typedef struct { + unsigned int ADC_CALI_EN; + unsigned int PTPINITEN; + unsigned int PTPMONEN; + + unsigned int MDES; + unsigned int BDES; + unsigned int DCCONFIG; + unsigned int DCMDET; + unsigned int DCBDET; + unsigned int AGECONFIG; + unsigned int AGEM; + unsigned int AGEDELTA; + unsigned int DVTFIXED; + unsigned int VCO; + unsigned int MTDES; + unsigned int MTS; + unsigned int BTS; + + unsigned char FREQPCT0; + unsigned char FREQPCT1; + unsigned char FREQPCT2; + unsigned char FREQPCT3; + unsigned char FREQPCT4; + unsigned char FREQPCT5; + unsigned char FREQPCT6; + unsigned char FREQPCT7; + + unsigned int DETWINDOW; + unsigned int VMAX; + unsigned int VMIN; + unsigned int DTHI; + unsigned int DTLO; + unsigned int VBOOT; + unsigned int DETMAX; + + unsigned int DCVOFFSETIN; + unsigned int AGEVOFFSETIN; +} PTP_INIT_T; + + +enum eem_ctrl_id { + EEM_CTRL_LITTLE = 0, + EEM_CTRL_GPU = 1, + EEM_CTRL_BIG = 2, + /* EEM_CTRL_SOC = 3, */ + NR_EEM_CTRL, +}; + +enum eem_det_id { + EEM_DET_LITTLE = EEM_CTRL_LITTLE, + EEM_DET_GPU = EEM_CTRL_GPU, + EEM_DET_BIG = EEM_CTRL_BIG, + /* EEM_DET_SOC = EEM_CTRL_SOC, */ + NR_EEM_DET, /* 3 */ +}; + +enum mt_eem_cpu_id { + MT_EEM_CPU_LITTLE, + MT_EEM_CPU_BIG, + + NR_MT_EEM_CPU, +}; + + +/* Global variable for SW EFUSE*/ +/* TODO: FIXME #include "devinfo.h" */ +extern u32 get_devinfo_with_index(u32 index); + +#ifdef CONFIG_MTK_RAM_CONSOLE +#define CONFIG_EEM_AEE_RR_REC 1 +#endif + +#ifdef CONFIG_EEM_AEE_RR_REC +enum eem_state { + EEM_CPU_LITTLE_IS_SET_VOLT = 0, /* L */ + EEM_GPU_IS_SET_VOLT, /* G */ + EEM_CPU_BIG_IS_SET_VOLT, /* B */ +}; + +extern void aee_rr_rec_ptp_cpu_little_volt(u64 val); +extern void aee_rr_rec_ptp_gpu_volt(u64 val); +extern void aee_rr_rec_ptp_cpu_big_volt(u64 val); +extern void aee_rr_rec_ptp_temp(u64 val); +extern void aee_rr_rec_ptp_status(u8 val); +extern void aee_rr_rec_eem_pi_offset(u8 val); + +extern u64 aee_rr_curr_ptp_cpu_little_volt(void); +extern u64 aee_rr_curr_ptp_gpu_volt(void); +extern u64 aee_rr_curr_ptp_cpu_big_volt(void); +extern u64 aee_rr_curr_ptp_temp(void); +extern u8 aee_rr_curr_ptp_status(void); +extern u8 aee_rr_curr_eem_pi_offset(void); +#endif + + +/* EEM Extern Function */ +/* extern unsigned int mt_eem_get_level(void); */ +extern void mt_ptp_lock(unsigned long *flags); +extern void mt_ptp_unlock(unsigned long *flags); +extern void eem_init02(const char *str); +extern int mt_eem_status(enum eem_det_id id); +extern int get_ptpod_status(void); +extern int is_have_550(void); +extern unsigned int get_vcore_ptp_volt(int uv); +extern void eem_set_pi_offset(enum eem_ctrl_id id, int step); +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +extern unsigned int get_turbo_status(void); +#endif + +#if defined(__MTK_SLT_) +/* extern int mt_ptp_idle_can_enter(void); */ +extern void ptp_init01_ptp(int id); +extern int ptp_isr(void); +#endif + + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_spm_cpu.h b/drivers/misc/mediatek/base/power/mt6755/mt_spm_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..725c4c977e0b610a6a20c20f1b720a14aed7e5f9 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_spm_cpu.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_SPM_CPU +#define _MT_SPM_CPU + +#include +#include + +#ifdef CONFIG_OF +extern void __iomem *spm_cpu_base; +extern void __iomem *scp_i2c0_base; +extern void __iomem *scp_i2c1_base; +extern void __iomem *scp_i2c2_base; +extern u32 spm_irq_0; +extern u32 spm_irq_1; +extern u32 spm_irq_2; +extern u32 spm_irq_3; +extern u32 spm_irq_4; +extern u32 spm_irq_5; +extern u32 spm_irq_6; +extern u32 spm_irq_7; + +#undef SPM_BASE +#define SPM_BASE spm_cpu_base +#else +#include +#endif + +/* #include */ +#include + +/************************************** + * Config and Parameter + **************************************/ + +/* FIXME: for bring up */ +#ifdef CONFIG_OF +#undef SPM_I2C0_BASE +#undef SPM_I2C1_BASE +#undef SPM_I2C2_BASE +#define SPM_I2C0_BASE scp_i2c0_base +#define SPM_I2C1_BASE scp_i2c1_base +#define SPM_I2C2_BASE scp_i2c2_base + +#define SPM_IRQ0_ID spm_irq_0 +#define SPM_IRQ1_ID spm_irq_1 +#define SPM_IRQ2_ID spm_irq_2 +#define SPM_IRQ3_ID spm_irq_3 +#define SPM_IRQ4_ID spm_irq_4 +#define SPM_IRQ5_ID spm_irq_5 +#define SPM_IRQ6_ID spm_irq_6 +#define SPM_IRQ7_ID spm_irq_7 +#else +#define SPM_BASE SLEEP_BASE + +#define SPM_I2C0_BASE 0xF0059C00 /* SCP_I2C0_BASE */ +#define SPM_I2C1_BASE 0xF0059C00 /* SCP_I2C1_BASE */ +#define SPM_I2C2_BASE 0xF0059C00 /* SCP_I2C2_BASE */ + +#define SPM_IRQ0_ID 195 /* SLEEP_IRQ_BIT0_ID */ +#define SPM_IRQ1_ID 196 /* SLEEP_IRQ_BIT1_ID */ +#define SPM_IRQ2_ID 197 /* SLEEP_IRQ_BIT2_ID */ +#define SPM_IRQ3_ID 198 /* SLEEP_IRQ_BIT3_ID */ +#define SPM_IRQ4_ID 199 /* SLEEP_IRQ_BIT4_ID */ +#define SPM_IRQ5_ID 200 /* SLEEP_IRQ_BIT5_ID */ +#define SPM_IRQ6_ID 201 /* SLEEP_IRQ_BIT6_ID */ +#define SPM_IRQ7_ID 202 /* SLEEP_IRQ_BIT7_ID */ +#endif + +#include "mt_spm_reg.h" + +enum SPM_WAKE_SRC_LIST; + +typedef enum { + WR_NONE = 0, + WR_UART_BUSY = 1, + WR_PCM_ASSERT = 2, + WR_PCM_TIMER = 3, + WR_WAKE_SRC = 4, + WR_UNKNOWN = 5, +} wake_reason_t; + +struct twam_sig { + u32 sig0; /* signal 0: config or status */ + u32 sig1; /* signal 1: config or status */ + u32 sig2; /* signal 2: config or status */ + u32 sig3; /* signal 3: config or status */ +}; + +typedef void (*twam_handler_t) (struct twam_sig *twamsig); + +/* for power management init */ +extern int spm_module_init(void); + +/* for ANC in talking */ +extern void spm_mainpll_on_request(const char *drv_name); +extern void spm_mainpll_on_unrequest(const char *drv_name); + +/* for TWAM in MET */ +extern void spm_twam_register_handler(twam_handler_t handler); +extern void spm_twam_enable_monitor(const struct twam_sig *twamsig, bool speed_mode); +extern void spm_twam_disable_monitor(void); + +/* for Vcore DVFS */ +extern int spm_go_to_ddrdfs(u32 spm_flags, u32 spm_data); + + +/************************************** + * Macro and Inline + **************************************/ +#define get_high_cnt(sigsta) ((sigsta) & 0x3ff) +#define get_high_percent(sigsta) ((get_high_cnt(sigsta) * 100 + 511) / 1023) + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_spm_mtcmos.c b/drivers/misc/mediatek/base/power/mt6755/mt_spm_mtcmos.c new file mode 100644 index 0000000000000000000000000000000000000000..ddf119f45767953c9c934778471c6fa28d6de959 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_spm_mtcmos.c @@ -0,0 +1,1401 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include /* udelay */ +#ifdef CONFIG_OF +#include +#include +#include +#endif + +/*#include */ +/*#include */ +/*#include */ +#include "mt_spm_mtcmos.h" +#include +#include + +#include +#define BUILDERROR + +#include "mt_spm_cpu.h" +/*#include "hotplug.h"*/ +/************************************** + * extern + **************************************/ + +/************************************** + * for CPU MTCMOS + **************************************/ +static DEFINE_SPINLOCK(spm_cpu_lock); +#ifdef CONFIG_OF +void __iomem *spm_cpu_base; +void __iomem *clk_apmixed_base; +#define ARMCA15PLL_CON0 (clk_apmixed_base + 0x200) +#define ARMCA15PLL_CON1 (clk_apmixed_base + 0x204) +#define ARMCA15PLL_PWR_CON0 (clk_apmixed_base + 0x20C) +#define AP_PLL_CON3 (clk_apmixed_base + 0x0C) +#define AP_PLL_CON4 (clk_apmixed_base + 0x10) + +#endif /* #ifdef CONFIG_OF */ + +int spm_mtcmos_cpu_init(void) +{ +#ifdef CONFIG_OF + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "mediatek,SLEEP"); + if (!node) { + pr_err("find SLEEP node failed\n"); + return -EINVAL; + } + spm_cpu_base = of_iomap(node, 0); + if (!spm_cpu_base) { + pr_err("base spm_cpu_base failed\n"); + return -EINVAL; + } + iomap(); /*for clk function */ + return 0; +#else /* #ifdef CONFIG_OF */ + return -EINVAL; +#endif /* #ifdef CONFIG_OF */ +} + +void spm_mtcmos_cpu_lock(unsigned long *flags) +{ + spin_lock_irqsave(&spm_cpu_lock, *flags); +} + +void spm_mtcmos_cpu_unlock(unsigned long *flags) +{ + spin_unlock_irqrestore(&spm_cpu_lock, *flags); +} + +/* Define MTCMOS Bus Protect Mask */ +#define MD1_PROT_MASK ((0x1 << 16) \ + |(0x1 << 17) \ + |(0x1 << 18) \ + |(0x1 << 19) \ + |(0x1 << 20) \ + |(0x1 << 21)) +#define CONN_PROT_MASK ((0x1 << 13) \ + |(0x1 << 14)) +#define DIS_PROT_MASK ((0x1 << 1)) +#define MFG_PROT_MASK ((0x1 << 21)) +#define MP0_CPUTOP_PROT_MASK ((0x1 << 26) \ + |(0x1 << 29)) +#define MP1_CPUTOP_PROT_MASK ((0x1 << 30)) +#define C2K_PROT_MASK ((0x1 << 22) \ + |(0x1 << 23) \ + |(0x1 << 24)) +#define MDSYS_INTF_INFRA_PROT_MASK ((0x1 << 3) \ + |(0x1 << 4)) + + /* Define MTCMOS Power Status Mask */ + +#define MD1_PWR_STA_MASK (0x1 << 0) +#define CONN_PWR_STA_MASK (0x1 << 1) +#define DPY_PWR_STA_MASK (0x1 << 2) +#define DIS_PWR_STA_MASK (0x1 << 3) +#define MFG_PWR_STA_MASK (0x1 << 4) +#define ISP_PWR_STA_MASK (0x1 << 5) +#define IFR_PWR_STA_MASK (0x1 << 6) +#define VDE_PWR_STA_MASK (0x1 << 7) +#define MP0_CPUTOP_PWR_STA_MASK (0x1 << 8) +#define MP0_CPU0_PWR_STA_MASK (0x1 << 9) +#define MP0_CPU1_PWR_STA_MASK (0x1 << 10) +#define MP0_CPU2_PWR_STA_MASK (0x1 << 11) +#define MP0_CPU3_PWR_STA_MASK (0x1 << 12) +#define MCU_PWR_STA_MASK (0x1 << 14) +#define MP1_CPUTOP_PWR_STA_MASK (0x1 << 15) +#define MP1_CPU0_PWR_STA_MASK (0x1 << 16) +#define MP1_CPU1_PWR_STA_MASK (0x1 << 17) +#define MP1_CPU2_PWR_STA_MASK (0x1 << 18) +#define MP1_CPU3_PWR_STA_MASK (0x1 << 19) +#define VEN_PWR_STA_MASK (0x1 << 21) +#define MFG_ASYNC_PWR_STA_MASK (0x1 << 23) +#define AUDIO_PWR_STA_MASK (0x1 << 24) +#define C2K_PWR_STA_MASK (0x1 << 28) +#define MDSYS_INTF_INFRA_PWR_STA_MASK (0x1 << 29) +/* Define Non-CPU SRAM Mask */ +#define MD1_SRAM_PDN (0x1 << 8) +#define MD1_SRAM_PDN_ACK (0x0 << 12) +#define DIS_SRAM_PDN (0x1 << 8) +#define DIS_SRAM_PDN_ACK (0x1 << 12) +#define MFG_SRAM_PDN (0x1 << 8) +#define MFG_SRAM_PDN_ACK (0x1 << 16) +#define ISP_SRAM_PDN (0x3 << 8) +#define ISP_SRAM_PDN_ACK (0x3 << 12) +#define IFR_SRAM_PDN (0xF << 8) +#define IFR_SRAM_PDN_ACK (0xF << 12) +#define VDE_SRAM_PDN (0x1 << 8) +#define VDE_SRAM_PDN_ACK (0x1 << 12) +#define VEN_SRAM_PDN (0xF << 8) +#define VEN_SRAM_PDN_ACK (0xF << 12) +#define AUDIO_SRAM_PDN (0xF << 8) +#define AUDIO_SRAM_PDN_ACK (0xF << 12) +/* Define CPU SRAM Mask */ +#define MP0_CPUTOP_SRAM_PDN (0x1 << 0) +#define MP0_CPUTOP_SRAM_PDN_ACK (0x1 << 8) +#define MP0_CPUTOP_SRAM_SLEEP_B (0x1 << 0) +#define MP0_CPUTOP_SRAM_SLEEP_B_ACK (0x1 << 8) +#define MP0_CPU0_SRAM_PDN (0x1 << 0) +#define MP0_CPU0_SRAM_PDN_ACK (0x1 << 8) +#define MP0_CPU1_SRAM_PDN (0x1 << 0) +#define MP0_CPU1_SRAM_PDN_ACK (0x1 << 8) +#define MP0_CPU2_SRAM_PDN (0x1 << 0) +#define MP0_CPU2_SRAM_PDN_ACK (0x1 << 8) +#define MP0_CPU3_SRAM_PDN (0x1 << 0) +#define MP0_CPU3_SRAM_PDN_ACK (0x1 << 8) +#define MP1_CPUTOP_SRAM_PDN (0x1 << 0) +#define MP1_CPUTOP_SRAM_PDN_ACK (0x1 << 8) +#define MP1_CPUTOP_SRAM_SLEEP_B (0x1 << 0) +#define MP1_CPUTOP_SRAM_SLEEP_B_ACK (0x1 << 8) +#define MP1_CPU0_SRAM_PDN (0x1 << 0) +#define MP1_CPU0_SRAM_PDN_ACK (0x1 << 8) +#define MP1_CPU1_SRAM_PDN (0x1 << 0) +#define MP1_CPU1_SRAM_PDN_ACK (0x1 << 8) +#define MP1_CPU2_SRAM_PDN (0x1 << 0) +#define MP1_CPU2_SRAM_PDN_ACK (0x1 << 8) +#define MP1_CPU3_SRAM_PDN (0x1 << 0) +#define MP1_CPU3_SRAM_PDN_ACK (0x1 << 8) + +typedef int (*spm_cpu_mtcmos_ctrl_func) (int state, int chkWfiBeforePdn); +static spm_cpu_mtcmos_ctrl_func spm_cpu_mtcmos_ctrl_funcs[] = { + spm_mtcmos_ctrl_cpu0, + spm_mtcmos_ctrl_cpu1, + spm_mtcmos_ctrl_cpu2, + spm_mtcmos_ctrl_cpu3, + spm_mtcmos_ctrl_cpu4, + spm_mtcmos_ctrl_cpu5, + spm_mtcmos_ctrl_cpu6, + spm_mtcmos_ctrl_cpu7 +}; + +int spm_mtcmos_ctrl_cpu(unsigned int cpu, int state, int chkWfiBeforePdn) +{ + return (*spm_cpu_mtcmos_ctrl_funcs[cpu]) (state, chkWfiBeforePdn); +} + +int spm_mtcmos_ctrl_cpu0(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + if (chkWfiBeforePdn) { + while ((spm_read(CPU_IDLE_STA) & MP0_CPU0_STANDBYWFI_LSB) == 0) { + /* no ops */ + ; + } + } + /* TINFO="Start to turn off MP0_CPU0" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_mtcmos_cpu_lock(&flags); + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP0_CPU0_L1_PDN, spm_read(MP0_CPU0_L1_PDN) | MP0_CPU0_SRAM_PDN); + /* TINFO="Wait until MP0_CPU0_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP0_CPU0_L1_PDN) & MP0_CPU0_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP0_CPU0_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP0_CPU0_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn off MP0_CPU0" */ + if (! + (spm_read(PWR_STATUS) & + (MP0_CPU1_PWR_STA_MASK | MP0_CPU2_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP0_CPU1_PWR_STA_MASK | MP0_CPU2_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK))) { +#ifdef CONFIG_MTK_L2C_SHARE + if (!IS_L2_BORROWED()) +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + spm_mtcmos_ctrl_cpusys0(state, chkWfiBeforePdn); + } + + /* TINFO="Finish to turn off MP0_CPU0" */ + } else { /* STA_POWER_ON */ + if (!(spm_read(PWR_STATUS) & MP0_CPUTOP_PWR_STA_MASK) && + !(spm_read(PWR_STATUS_2ND) & MP0_CPUTOP_PWR_STA_MASK)) + spm_mtcmos_ctrl_cpusys0(state, chkWfiBeforePdn); + spm_mtcmos_cpu_lock(&flags); + /* TINFO="Start to turn on MP0_CPU0" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP0_CPU0_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP0_CPU0_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP0_CPU0_L1_PDN, spm_read(MP0_CPU0_L1_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP0_CPU0_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP0_CPU0_L1_PDN) & MP0_CPU0_SRAM_PDN_ACK) { + /* no ops */ + ; + }; +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP0_CPU0_PWR_CON, spm_read(MP0_CPU0_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MP0_CPU0" */ + spm_mtcmos_cpu_unlock(&flags); + } + return 0; +} + +int spm_mtcmos_ctrl_cpu1(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP0_CPU1_STANDBYWFI_LSB) == 0) { + /* no ops */ + ; + } + /* TINFO="Start to turn off MP0_CPU1" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_mtcmos_cpu_lock(&flags); + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP0_CPU1_L1_PDN, spm_read(MP0_CPU1_L1_PDN) | MP0_CPU1_SRAM_PDN); + /* TINFO="Wait until MP0_CPU1_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP0_CPU1_L1_PDN) & MP0_CPU1_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP0_CPU1_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP0_CPU1_PWR_STA_MASK)) { + /*no ops*/ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn off MP0_CPU0" */ + if (! + (spm_read(PWR_STATUS) & + (MP0_CPU0_PWR_STA_MASK | MP0_CPU2_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP0_CPU0_PWR_STA_MASK | MP0_CPU2_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK))) { +#ifdef CONFIG_MTK_L2C_SHARE + if (!IS_L2_BORROWED()) +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + spm_mtcmos_ctrl_cpusys0(state, chkWfiBeforePdn); + } + + /* TINFO="Finish to turn off MP0_CPU1" */ + } else { /* STA_POWER_ON */ + if (!(spm_read(PWR_STATUS) & MP0_CPUTOP_PWR_STA_MASK) && + !(spm_read(PWR_STATUS_2ND) & MP0_CPUTOP_PWR_STA_MASK)) + spm_mtcmos_ctrl_cpusys0(state, chkWfiBeforePdn); + spm_mtcmos_cpu_lock(&flags); + /* TINFO="Start to turn on MP0_CPU1" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP0_CPU1_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP0_CPU1_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP0_CPU1_L1_PDN, spm_read(MP0_CPU1_L1_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP0_CPU1_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP0_CPU1_L1_PDN) & MP0_CPU1_SRAM_PDN_ACK) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP0_CPU1_PWR_CON, spm_read(MP0_CPU1_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MP0_CPU1" */ + spm_mtcmos_cpu_unlock(&flags); + } + return 0; +} + +int spm_mtcmos_ctrl_cpu2(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP0_CPU2_STANDBYWFI_LSB) == 0) { + /* no ops */ + ; + } + /* TINFO="Start to turn off MP0_CPU2" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_mtcmos_cpu_lock(&flags); + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP0_CPU2_L1_PDN, spm_read(MP0_CPU2_L1_PDN) | MP0_CPU2_SRAM_PDN); + /* TINFO="Wait until MP0_CPU2_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP0_CPU2_L1_PDN) & MP0_CPU2_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP0_CPU2_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP0_CPU2_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn off MP0_CPU0" */ + if (! + (spm_read(PWR_STATUS) & + (MP0_CPU0_PWR_STA_MASK | MP0_CPU1_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP0_CPU0_PWR_STA_MASK | MP0_CPU1_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK))) { +#ifdef CONFIG_MTK_L2C_SHARE + if (!IS_L2_BORROWED()) +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + spm_mtcmos_ctrl_cpusys0(state, chkWfiBeforePdn); + } + + /* TINFO="Finish to turn off MP0_CPU2" */ + } else { /* STA_POWER_ON */ + if (!(spm_read(PWR_STATUS) & MP0_CPUTOP_PWR_STA_MASK) && + !(spm_read(PWR_STATUS_2ND) & MP0_CPUTOP_PWR_STA_MASK)) + spm_mtcmos_ctrl_cpusys0(state, chkWfiBeforePdn); + spm_mtcmos_cpu_lock(&flags); + /* TINFO="Start to turn on MP0_CPU2" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP0_CPU2_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP0_CPU2_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP0_CPU2_L1_PDN, spm_read(MP0_CPU2_L1_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP0_CPU2_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP0_CPU2_L1_PDN) & MP0_CPU2_SRAM_PDN_ACK) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP0_CPU2_PWR_CON, spm_read(MP0_CPU2_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MP0_CPU2" */ + spm_mtcmos_cpu_unlock(&flags); + } + return 0; +} + +int spm_mtcmos_ctrl_cpu3(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP0_CPU3_STANDBYWFI_LSB) == 0) { + /* no ops */ + ; + } + /* TINFO="Start to turn off MP0_CPU3" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_mtcmos_cpu_lock(&flags); + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP0_CPU3_L1_PDN, spm_read(MP0_CPU3_L1_PDN) | MP0_CPU3_SRAM_PDN); + /* TINFO="Wait until MP0_CPU3_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP0_CPU3_L1_PDN) & MP0_CPU3_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP0_CPU3_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP0_CPU3_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn off MP0_CPU0" */ + if (! + (spm_read(PWR_STATUS) & + (MP0_CPU0_PWR_STA_MASK | MP0_CPU1_PWR_STA_MASK | MP0_CPU2_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP0_CPU0_PWR_STA_MASK | MP0_CPU1_PWR_STA_MASK | MP0_CPU2_PWR_STA_MASK))) { +#ifdef CONFIG_MTK_L2C_SHARE + if (!IS_L2_BORROWED()) +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + spm_mtcmos_ctrl_cpusys0(state, chkWfiBeforePdn); + } + + /* TINFO="Finish to turn off MP0_CPU3" */ + } else { /* STA_POWER_ON */ + if (!(spm_read(PWR_STATUS) & MP0_CPUTOP_PWR_STA_MASK) && + !(spm_read(PWR_STATUS_2ND) & MP0_CPUTOP_PWR_STA_MASK)) + spm_mtcmos_ctrl_cpusys0(state, chkWfiBeforePdn); + spm_mtcmos_cpu_lock(&flags); + /* TINFO="Start to turn on MP0_CPU3" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP0_CPU3_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP0_CPU3_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP0_CPU3_L1_PDN, spm_read(MP0_CPU3_L1_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP0_CPU3_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP0_CPU3_L1_PDN) & MP0_CPU3_SRAM_PDN_ACK) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP0_CPU3_PWR_CON, spm_read(MP0_CPU3_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MP0_CPU3" */ + spm_mtcmos_cpu_unlock(&flags); + } + return 0; +} + +int spm_mtcmos_ctrl_cpu4(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP1_CPU0_STANDBYWFI_LSB) == 0) { + /* no ops */ + ; + } + /* TINFO="Start to turn off MP1_CPU0" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_mtcmos_cpu_lock(&flags); + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP1_CPU0_L1_PDN, spm_read(MP1_CPU0_L1_PDN) | MP1_CPU0_SRAM_PDN); + /* TINFO="Wait until MP1_CPU0_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP1_CPU0_L1_PDN) & MP1_CPU0_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP1_CPU0_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP1_CPU0_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + spm_mtcmos_cpu_unlock(&flags); + + /* TINFO="Finish to turn off MP1_CPU0" */ + if (! + (spm_read(PWR_STATUS) & + (MP1_CPU1_PWR_STA_MASK | MP1_CPU2_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP1_CPU1_PWR_STA_MASK | MP1_CPU2_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK))) { +#ifdef CONFIG_MTK_L2C_SHARE + if (!IS_L2_BORROWED()) +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn); + } + } else { /* STA_POWER_ON */ + if (!(spm_read(PWR_STATUS) & MP1_CPUTOP_PWR_STA_MASK) && + !(spm_read(PWR_STATUS_2ND) & MP1_CPUTOP_PWR_STA_MASK)) + spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn); + spm_mtcmos_cpu_lock(&flags); + /* TINFO="Start to turn on MP1_CPU0" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP1_CPU0_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP1_CPU0_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP1_CPU0_L1_PDN, spm_read(MP1_CPU0_L1_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP1_CPU0_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP1_CPU0_L1_PDN) & MP1_CPU0_SRAM_PDN_ACK) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP1_CPU0_PWR_CON, spm_read(MP1_CPU0_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MP1_CPU0" */ + spm_mtcmos_cpu_unlock(&flags); + } + return 0; +} + +int spm_mtcmos_ctrl_cpu5(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP1_CPU1_STANDBYWFI_LSB) == 0) { + /* no ops */ + ; + } + /* TINFO="Start to turn off MP1_CPU1" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_mtcmos_cpu_lock(&flags); + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP1_CPU1_L1_PDN, spm_read(MP1_CPU1_L1_PDN) | MP1_CPU1_SRAM_PDN); + /* TINFO="Wait until MP1_CPU1_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP1_CPU1_L1_PDN) & MP1_CPU1_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP1_CPU1_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP1_CPU1_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn off MP1_CPU1" */ + if (! + (spm_read(PWR_STATUS) & + (MP1_CPU0_PWR_STA_MASK | MP1_CPU2_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP1_CPU0_PWR_STA_MASK | MP1_CPU2_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK))) { +#ifdef CONFIG_MTK_L2C_SHARE + if (!IS_L2_BORROWED()) +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn); + } + } else { /* STA_POWER_ON */ + if (!(spm_read(PWR_STATUS) & CA15_CPUTOP) && + !(spm_read(PWR_STATUS_2ND) & CA15_CPUTOP)) + spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn); + spm_mtcmos_cpu_lock(&flags); + /* TINFO="Start to turn on MP1_CPU1" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP1_CPU1_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP1_CPU1_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP1_CPU1_L1_PDN, spm_read(MP1_CPU1_L1_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP1_CPU1_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP1_CPU1_L1_PDN) & MP1_CPU1_SRAM_PDN_ACK) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP1_CPU1_PWR_CON, spm_read(MP1_CPU1_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MP1_CPU1" */ + spm_mtcmos_cpu_unlock(&flags); + } + return 0; +} + +int spm_mtcmos_ctrl_cpu6(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP1_CPU2_STANDBYWFI_LSB) == 0) { + /* no ops */ + ; + } + /* TINFO="Start to turn off MP1_CPU2" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_mtcmos_cpu_lock(&flags); + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP1_CPU2_L1_PDN, spm_read(MP1_CPU2_L1_PDN) | MP1_CPU2_SRAM_PDN); + /* TINFO="Wait until MP1_CPU2_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP1_CPU2_L1_PDN) & MP1_CPU2_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP1_CPU2_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP1_CPU2_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn off MP1_CPU2" */ + if (! + (spm_read(PWR_STATUS) & + (MP1_CPU0_PWR_STA_MASK | MP1_CPU1_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP1_CPU0_PWR_STA_MASK | MP1_CPU1_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK))) { +#ifdef CONFIG_MTK_L2C_SHARE + if (!IS_L2_BORROWED()) +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn); + } + } else { /* STA_POWER_ON */ + if (!(spm_read(PWR_STATUS) & CA15_CPUTOP) && + !(spm_read(PWR_STATUS_2ND) & CA15_CPUTOP)) + spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn); + spm_mtcmos_cpu_lock(&flags); + /* TINFO="Start to turn on MP1_CPU2" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP1_CPU2_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP1_CPU2_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP1_CPU2_L1_PDN, spm_read(MP1_CPU2_L1_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP1_CPU2_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP1_CPU2_L1_PDN) & MP1_CPU2_SRAM_PDN_ACK) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP1_CPU2_PWR_CON, spm_read(MP1_CPU2_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MP1_CPU2" */ + spm_mtcmos_cpu_unlock(&flags); + } + return 0; +} + +int spm_mtcmos_ctrl_cpu7(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP1_CPU3_STANDBYWFI_LSB) == 0) { + /* no ops */ + ; + } + /* TINFO="Start to turn off MP1_CPU3" */ + /* TINFO="Set PWR_ISO = 1" */ + spm_mtcmos_cpu_lock(&flags); + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP1_CPU3_L1_PDN, spm_read(MP1_CPU3_L1_PDN) | MP1_CPU3_SRAM_PDN); + /* TINFO="Wait until MP1_CPU3_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP1_CPU3_L1_PDN) & MP1_CPU3_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP1_CPU3_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP1_CPU3_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn off MP1_CPU3" */ + if (! + (spm_read(PWR_STATUS) & + (MP1_CPU0_PWR_STA_MASK | MP1_CPU1_PWR_STA_MASK | MP1_CPU2_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP1_CPU0_PWR_STA_MASK | MP1_CPU1_PWR_STA_MASK | MP1_CPU2_PWR_STA_MASK))) { +#ifdef CONFIG_MTK_L2C_SHARE + if (!IS_L2_BORROWED()) +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn); + } + } else { /* STA_POWER_ON */ + if (!(spm_read(PWR_STATUS) & CA15_CPUTOP) && + !(spm_read(PWR_STATUS_2ND) & CA15_CPUTOP)) + spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn); + + spm_mtcmos_cpu_lock(&flags); + /* TINFO="Start to turn on MP1_CPU3" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP1_CPU3_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP1_CPU3_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP1_CPU3_L1_PDN, spm_read(MP1_CPU3_L1_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP1_CPU3_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP1_CPU3_L1_PDN) & MP1_CPU3_SRAM_PDN_ACK) { + /* no ops */ + ; + } +#endif + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP1_CPU3_PWR_CON, spm_read(MP1_CPU3_PWR_CON) | PWR_RST_B); + /* TINFO="Finish to turn on MP1_CPU3" */ + spm_mtcmos_cpu_unlock(&flags); + } + return 0; +} + +int spm_mtcmos_ctrl_cpusys0(int state, int chkWfiBeforePdn) +{ + int err = 0; + unsigned long flags; + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off MP1_CPUTOP" */ + /* TINFO="Set bus protect" */ + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP0_CPUTOP_IDLE_LSB) == 0) { + /* no ops */ + ; + } + spm_mtcmos_cpu_lock(&flags); +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) | MP0_CPUTOP_PROT_MASK); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1) & + MP0_CPUTOP_PROT_MASK) != MP0_CPUTOP_PROT_MASK) { + /* no ops */ + ; + } +#else + spm_topaxi_protect(MP0_CPUTOP_PROT_MASK, 1); +#endif + /* TINFO="Set PWR_ISO = 1" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP0_CPUTOP_L2_PDN, spm_read(MP0_CPUTOP_L2_PDN) | MP0_CPUTOP_SRAM_PDN); + /* TINFO="Wait until MP1_CPUTOP_SRAM_PDN_ACK = 1" */ + while (!(spm_read(MP0_CPUTOP_L2_PDN) & MP0_CPUTOP_SRAM_PDN_ACK)) { + /* no ops */ + ; + } + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) & ~PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP0_CPUTOP_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP0_CPUTOP_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif + + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn off MP1_CPUTOP" */ + } else { + spm_mtcmos_cpu_lock(&flags); + /* STA_POWER_ON */ + /* TINFO="Start to turn on MP1_CPUTOP" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) | PWR_ON_2ND); + +#ifndef IGNORE_PWR_ACK + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP0_CPUTOP_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP0_CPUTOP_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP0_CPUTOP_L2_PDN, spm_read(MP0_CPUTOP_L2_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP1_CPUTOP_SRAM_PDN_ACK = 0" */ + while (spm_read(MP0_CPUTOP_L2_PDN) & MP0_CPUTOP_SRAM_PDN_ACK) { + /* no ops */ + ; + } + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP0_CPUTOP_PWR_CON, spm_read(MP0_CPUTOP_PWR_CON) | PWR_RST_B); + /* TINFO="Release bus protect" */ +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) & ~MP0_CPUTOP_PROT_MASK); + while (spm_read(INFRA_TOPAXI_PROTECTSTA1) & MP0_CPUTOP_PROT_MASK) { + /* no ops */ + ; + } +#else + spm_topaxi_protect(MP0_CPUTOP_PROT_MASK, 0); +#endif + spm_mtcmos_cpu_unlock(&flags); + + /* TINFO="Finish to turn on MP1_CPUTOP" */ + } + return err; +} + +int spm_mtcmos_ctrl_cpusys1(int state, int chkWfiBeforePdn) +{ + unsigned long flags; + + /* TINFO="enable SPM register control" */ + spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | (0x1 << 0)); + + if (state == STA_POWER_DOWN) { + /* TINFO="Start to turn off MP1_CPUTOP" */ + /* TINFO="Set bus protect" */ + if (chkWfiBeforePdn) + while ((spm_read(CPU_IDLE_STA) & MP1_CPUTOP_IDLE_LSB) == 0) + ; /* no ops */ + + spm_mtcmos_cpu_lock(&flags); +#if 0 + spm_write(INFRA_TOPAXI_PROTECTEN, + spm_read(INFRA_TOPAXI_PROTECTEN) | MP1_CPUTOP_PROT_MASK); + while ((spm_read(INFRA_TOPAXI_PROTECTSTA1) & + MP1_CPUTOP_PROT_MASK) != MP1_CPUTOP_PROT_MASK) { + /* no ops */ + ; + } +#else + spm_topaxi_protect(MP1_CPUTOP_PROT_MASK, 1); +#endif + /* TINFO="Set PWR_ISO = 1" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) | PWR_ISO); + /* TINFO="Set SRAM_CKISO = 1" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) | SRAM_CKISO); + /* TINFO="Set SRAM_ISOINT_B = 0" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) & ~SRAM_ISOINT_B); + /* TINFO="Set SRAM_PDN = 1" */ + spm_write(MP1_CPUTOP_L2_PDN, spm_read(MP1_CPUTOP_L2_PDN) | MP1_CPUTOP_SRAM_PDN); + /* TINFO="Wait until MP1_CPUTOP_SRAM_PDN_ACK = 1" */ +#ifndef CFG_FPGA_PLATFORM + while (!(spm_read(MP1_CPUTOP_L2_PDN) & MP1_CPUTOP_SRAM_PDN_ACK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Set PWR_RST_B = 0" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) & ~PWR_RST_B); + /* TINFO="Set PWR_CLK_DIS = 1" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) | PWR_CLK_DIS); + /* TINFO="Set PWR_ON = 0" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) & ~PWR_ON); + /* TINFO="Set PWR_ON_2ND = 0" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) & ~PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ + while ((spm_read(PWR_STATUS) & MP1_CPUTOP_PWR_STA_MASK) + || (spm_read(PWR_STATUS_2ND) & MP1_CPUTOP_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ +#if 1 + switch_armpll_l_hwmode(0); /*Switch to SW mode */ + mt_pause_armpll(FH_ARMCA15_PLLID, 1); /*Pause FQHP function */ + disable_armpll_l(); /*Turn off arm pll */ +#endif + spm_mtcmos_cpu_unlock(&flags); + + /* TINFO="Finish to turn off MP1_CPUTOP" */ + } else { /* STA_POWER_ON */ + + spm_mtcmos_cpu_lock(&flags); +#if 1 + enable_armpll_l(); /*Turn on arm pll */ + mt_pause_armpll(FH_ARMCA15_PLLID, 0); + /*Non-pause FQHP function */ + switch_armpll_l_hwmode(1); /*Switch to HW mode */ +#endif + + /* TINFO="Start to turn on MP1_CPUTOP" */ + /* TINFO="Set PWR_ON = 1" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) | PWR_ON); + /* TINFO="Set PWR_ON_2ND = 1" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) | PWR_ON_2ND); + +#ifndef CFG_FPGA_PLATFORM + /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ + while (!(spm_read(PWR_STATUS) & MP1_CPUTOP_PWR_STA_MASK) + || !(spm_read(PWR_STATUS_2ND) & MP1_CPUTOP_PWR_STA_MASK)) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + + /* TINFO="Set PWR_ISO = 0" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) & ~PWR_ISO); + /* TINFO="Set SRAM_PDN = 0" */ + spm_write(MP1_CPUTOP_L2_PDN, spm_read(MP1_CPUTOP_L2_PDN) & ~(0x1 << 0)); + /* TINFO="Wait until MP1_CPUTOP_SRAM_PDN_ACK = 0" */ +#ifndef CFG_FPGA_PLATFORM + while (spm_read(MP1_CPUTOP_L2_PDN) & MP1_CPUTOP_SRAM_PDN_ACK) { + /* no ops */ + ; + } +#endif /* #ifndef CFG_FPGA_PLATFORM */ + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_ISOINT_B = 1" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) | SRAM_ISOINT_B); + /* TINFO="Delay 1us" */ + udelay(1); + /* TINFO="Set SRAM_CKISO = 0" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) & ~SRAM_CKISO); + /* TINFO="Set PWR_CLK_DIS = 0" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) & ~PWR_CLK_DIS); + /* TINFO="Set PWR_RST_B = 1" */ + spm_write(MP1_CPUTOP_PWR_CON, spm_read(MP1_CPUTOP_PWR_CON) | PWR_RST_B); + /* TINFO="Release bus protect" */ +#if 1 + /* #ifndef CFG_FPGA_PLATFORM */ + + spm_topaxi_protect(MP1_CPUTOP_PROT_MASK, 0); +#endif + spm_mtcmos_cpu_unlock(&flags); + /* TINFO="Finish to turn on MP1_CPUTOP" */ + } + return 0; +} + +void spm_mtcmos_ctrl_cpusys1_init_1st_bring_up(int state) +{ + + if (state == STA_POWER_DOWN) { + spm_mtcmos_ctrl_cpu7(STA_POWER_DOWN, 0); + spm_mtcmos_ctrl_cpu6(STA_POWER_DOWN, 0); + spm_mtcmos_ctrl_cpu5(STA_POWER_DOWN, 0); + spm_mtcmos_ctrl_cpu4(STA_POWER_DOWN, 0); + } else { /* STA_POWER_ON */ + + spm_mtcmos_ctrl_cpu4(STA_POWER_ON, 1); + spm_mtcmos_ctrl_cpu5(STA_POWER_ON, 1); + spm_mtcmos_ctrl_cpu6(STA_POWER_ON, 1); + spm_mtcmos_ctrl_cpu7(STA_POWER_ON, 1); + } +} + +bool spm_cpusys0_can_power_down(void) +{ + return !(spm_read(PWR_STATUS) & + (MP1_CPU0_PWR_STA_MASK | MP1_CPU1_PWR_STA_MASK | + MP1_CPU2_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK | + MP1_CPUTOP_PWR_STA_MASK | MP0_CPU1_PWR_STA_MASK | + MP0_CPU2_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP1_CPU0_PWR_STA_MASK | MP1_CPU1_PWR_STA_MASK | + MP1_CPU2_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK | + MP1_CPUTOP_PWR_STA_MASK | MP0_CPU1_PWR_STA_MASK | + MP0_CPU2_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK)); +} + +bool spm_cpusys1_can_power_down(void) +{ + return !(spm_read(PWR_STATUS) & + (MP0_CPU0_PWR_STA_MASK | MP0_CPU1_PWR_STA_MASK | + MP0_CPU2_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK | + MP0_CPUTOP_PWR_STA_MASK | MP1_CPU1_PWR_STA_MASK | + MP1_CPU2_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK)) + && !(spm_read(PWR_STATUS_2ND) & + (MP0_CPU0_PWR_STA_MASK | MP0_CPU1_PWR_STA_MASK | + MP0_CPU2_PWR_STA_MASK | MP0_CPU3_PWR_STA_MASK | + MP0_CPUTOP_PWR_STA_MASK | MP1_CPU1_PWR_STA_MASK | + MP1_CPU2_PWR_STA_MASK | MP1_CPU3_PWR_STA_MASK)); +} + +#ifdef CONFIG_OF +void iomap(void) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-apmixedsys"); + if (!node) + pr_debug("[CLK_APMIXED] find node failed\n"); + clk_apmixed_base = of_iomap(node, 0); + if (!clk_apmixed_base) + pr_debug("[CLK_APMIXED] base failed\n"); +} + +void enable_armpll_l(void) +{ + spm_write(ARMCA15PLL_PWR_CON0, (spm_read(ARMCA15PLL_PWR_CON0) | 0x01)); + udelay(2); + spm_write(ARMCA15PLL_PWR_CON0, (spm_read(ARMCA15PLL_PWR_CON0) & 0xfffffffd)); + spm_write(ARMCA15PLL_CON1, (spm_read(ARMCA15PLL_CON1) | 0x80000000)); + spm_write(ARMCA15PLL_CON0, (spm_read(ARMCA15PLL_CON0) | 0x01)); + udelay(100); +} + +void disable_armpll_l(void) +{ + spm_write(ARMCA15PLL_CON0, (spm_read(ARMCA15PLL_CON0) & 0xfffffffe)); + spm_write(ARMCA15PLL_PWR_CON0, (spm_read(ARMCA15PLL_PWR_CON0) | 0x00000002)); + spm_write(ARMCA15PLL_PWR_CON0, (spm_read(ARMCA15PLL_PWR_CON0) & 0xfffffffe)); +} + +void switch_armpll_l_hwmode(int enable) +{ + /* ARM CA15 */ + if (enable == 1) { + spm_write(AP_PLL_CON3, (spm_read(AP_PLL_CON3) & 0xff87ffff)); + spm_write(AP_PLL_CON4, (spm_read(AP_PLL_CON4) & 0xffffcfff)); + } else { + spm_write(AP_PLL_CON3, (spm_read(AP_PLL_CON3) | 0x00780000)); + spm_write(AP_PLL_CON4, (spm_read(AP_PLL_CON4) | 0x00003000)); + } +} + +void switch_armpll_ll_hwmode(int enable) +{ + /* ARM CA7 */ + if (enable == 1) { + spm_write(AP_PLL_CON3, (spm_read(AP_PLL_CON3) & 0xfffeeeef)); + spm_write(AP_PLL_CON4, (spm_read(AP_PLL_CON4) & 0xfffffefe)); + } else { + spm_write(AP_PLL_CON3, (spm_read(AP_PLL_CON3) | 0x00011110)); + spm_write(AP_PLL_CON4, (spm_read(AP_PLL_CON4) | 0x00000101)); + } +} +#endif + + +static int mt_spm_mtcmos_init(void) +{ + return 0; +} +module_init(mt_spm_mtcmos_init); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_spm_mtcmos.h b/drivers/misc/mediatek/base/power/mt6755/mt_spm_mtcmos.h new file mode 100644 index 0000000000000000000000000000000000000000..842f48090b53885a712c36dd899e540f987df7b0 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_spm_mtcmos.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_SPM_MTCMOS_ +#define _MT_SPM_MTCMOS_ + +#include + +#define STA_POWER_DOWN 0 +#define STA_POWER_ON 1 + +/* + * 1. for CPU MTCMOS: CPU0, CPU1, CPU2, CPU3, DBG0, CPU4, CPU5, CPU6, CPU7, DBG1, CPUSYS1 + * 2. call spm_mtcmos_cpu_lock/unlock() before/after any operations + */ +extern int spm_mtcmos_cpu_init(void); +extern void spm_mtcmos_cpu_lock(unsigned long *flags); +extern void spm_mtcmos_cpu_unlock(unsigned long *flags); +extern int spm_topaxi_protect(unsigned int mask_value, int en); + +extern int spm_mtcmos_ctrl_cpu(unsigned int cpu, int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu0(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu1(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu2(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu3(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu4(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu5(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu6(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu7(int state, int chkWfiBeforePdn); + +extern int spm_mtcmos_ctrl_dbg0(int state); + +extern int spm_mtcmos_ctrl_cpusys0(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpusys1(int state, int chkWfiBeforePdn); + +extern bool spm_cpusys0_can_power_down(void); +extern bool spm_cpusys1_can_power_down(void); + +extern void spm_mtcmos_ctrl_cpusys1_init_1st_bring_up(int state); +extern void switch_armpll_ll_hwmode(int enable); +extern void switch_armpll_l_hwmode(int enable); +extern void disable_armpll_l(void); +extern void enable_armpll_l(void); +extern void iomap(void); + +#ifdef CONFIG_MTK_L2C_SHARE +extern int IS_L2_BORROWED(void); +#endif /* #ifdef CONFIG_MTK_L2C_SHARE */ + +/* + * 1. for non-CPU MTCMOS: VDEC, VENC, ISP, DISP, MFG, INFRA, DDRPHY, MDSYS1, MDSYS2 + * 2. call spm_mtcmos_noncpu_lock/unlock() before/after any operations + */ + +#if 0 +extern int spm_mtcmos_ctrl_vdec(int state); +extern int spm_mtcmos_ctrl_venc(int state); +extern int spm_mtcmos_ctrl_isp(int state); +extern int spm_mtcmos_ctrl_disp(int state); +extern int spm_mtcmos_ctrl_mfg(int state); +extern int spm_mtcmos_ctrl_mfg_ASYNC(int state); +extern int spm_mtcmos_ctrl_mjc(int state); +extern int spm_mtcmos_ctrl_aud(int state); +extern int spm_mtcmos_ctrl_mdsys_intf_infra(int state); + +extern int spm_mtcmos_ctrl_mdsys1(int state); +extern int spm_mtcmos_ctrl_mdsys2(int state); +extern int spm_mtcmos_ctrl_connsys(int state); + +extern int spm_topaxi_protect(int bit, int en); +#endif + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_spower_data.h b/drivers/misc/mediatek/base/power/mt6755/mt_spower_data.h new file mode 100644 index 0000000000000000000000000000000000000000..d902b538b5699ade3695a21150f60baac9eeeea4 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_spower_data.h @@ -0,0 +1,703 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef MT_SPOWER_CPU_H +#define MT_SPOWER_CPU_H + + + +#define VSIZE 11 +#define TSIZE 26 +#define MAX_TABLE_SIZE 3 + +/** PLEASE MAKE SURE the following things for table interpolation: + * 1. table order: FF,TT,SS; such that,the order is necessarily obey as following: + * the power at (1150,30) should be descent absoultely. + **/ + +/* "(WAT 12.6%) Leakage Power" */ +#define CPU_TABLE_0 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 9, 12, 16, 21, 29, 38, 50, 66, 88, 117, 157,\ + 5, 11, 15, 20, 26, 35, 46, 61, 80, 107, 142, 190,\ + 10, 14, 19, 25, 32, 43, 57, 75, 98, 130, 173, 230,\ + 15, 17, 23, 30, 40, 53, 69, 91, 120, 159, 210, 278,\ + 20, 22, 28, 37, 49, 64, 84, 111, 146, 192, 254, 335,\ + 25, 26, 35, 45, 59, 78, 102, 134, 176, 232, 305, 403,\ + 30, 32, 42, 55, 72, 94, 124, 162, 213, 280, 367, 483,\ + 35, 40, 52, 67, 88, 114, 149, 195, 256, 336, 438, 577,\ + 40, 48, 63, 82, 106, 138, 180, 235, 307, 402, 523, 688,\ + 45, 59, 76, 99, 128, 167, 216, 282, 367, 480, 625, 817,\ + 50, 71, 92, 119, 154, 200, 260, 337, 438, 571, 745, 967,\ + 55, 86, 112, 144, 186, 240, 310, 402, 522, 678, 882, 1143,\ + 60, 104, 134, 173, 223, 287, 370, 479, 620, 804, 1046, 1355,\ + 65, 125, 161, 206, 266, 342, 441, 568, 734, 949, 1232, 1592,\ + 70, 149, 192, 246, 317, 407, 523, 673, 867, 1119, 1448, 1863,\ + 75, 179, 229, 295, 378, 486, 623, 801, 1031, 1328, 1714, 2208,\ + 80, 213, 273, 350, 449, 576, 737, 944, 1211, 1558, 2006, 2588,\ + 85, 254, 323, 414, 532, 680, 869, 1111, 1420, 1821, 2343, 3015,\ + 90, 303, 384, 490, 627, 800, 1020, 1301, 1661, 2122, 2723, 3500,\ + 95, 360, 455, 578, 739, 939, 1194, 1520, 1937, 2466, 3153, 4044,\ + 100, 425, 537, 681, 867, 1098, 1392, 1770, 2251, 2860, 3640, 4658,\ + 105, 500, 632, 797, 1015, 1282, 1619, 2049, 2606, 3309, 4200, 5349,\ + 110, 586, 740, 932, 1181, 1492, 1882, 2383, 3016, 3822, 4851, 6132,\ + 115, 685, 863, 1086, 1370, 1727, 2189, 2756, 3471, 4381, 5552, 7040,\ + 120, 796, 1007, 1265, 1586, 1994, 2523, 3174, 3993, 5013, 6321, 8004,\ + 125, 924, 1162, 1469, 1835, 2309, 2900, 3635, 4564, 5736, 7192, 9083 } + +/* "(WAT 4.2%) Leakage Power" */ +#define CPU_TABLE_1 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 7, 9, 11, 15, 19, 25, 32, 42, 54, 71, 92, \ + 5, 8, 11, 14, 18, 23, 30, 39, 50, 66, 86, 112, \ + 10, 10, 13, 17, 22, 28, 36, 47, 61, 79, 104, 136, \ + 15, 12, 16, 20, 26, 34, 43, 57, 74, 95, 125, 164, \ + 20, 15, 19, 24, 31, 40, 52, 68, 89, 115, 151, 197, \ + 25, 17, 22, 29, 38, 49, 63, 82, 106, 138, 182, 238, \ + 30, 21, 27, 34, 45, 58, 75, 98, 127, 166, 219, 286, \ + 35, 25, 32, 41, 54, 69, 90, 117, 152, 200, 263, 345, \ + 40, 30, 38, 49, 64, 83, 108, 140, 182, 240, 317, 414, \ + 45, 36, 45, 59, 77, 99, 129, 168, 218, 288, 381, 498, \ + 50, 42, 54, 70, 91, 118, 154, 200, 261, 344, 456, 595, \ + 55, 50, 64, 83, 108, 141, 183, 238, 311, 410, 544, 712, \ + 60, 59, 76, 99, 128, 167, 217, 283, 371, 490, 648, 857, \ + 65, 70, 91, 118, 152, 198, 258, 337, 441, 582, 772, 1026, \ + 70, 82, 107, 139, 180, 234, 305, 399, 524, 691, 918, 1218, \ + 75, 98, 126, 164, 213, 277, 361, 473, 622, 821, 1087, 1449, \ + 80, 115, 149, 193, 251, 327, 427, 558, 735, 972, 1287, 1720, \ + 85, 134, 176, 227, 295, 385, 502, 659, 865, 1143, 1523, 2029, \ + 90, 158, 206, 266, 346, 452, 591, 774, 1022, 1353, 1800, 2396, \ + 95, 186, 241, 311, 406, 531, 694, 911, 1205, 1593, 2110, 2813, \ + 100, 217, 281, 364, 476, 621, 813, 1071, 1413, 1870, 2483, 3316, \ + 105, 254, 329, 428, 556, 727, 950, 1253, 1655, 2187, 2923, 3899, \ + 110, 297, 384, 499, 652, 852, 1112, 1465, 1936, 2568, 3417, 4542, \ + 115, 348, 452, 583, 761, 996, 1301, 1715, 2255, 2999, 3977, 5289, \ + 120, 405, 527, 683, 890, 1157, 1514, 1997, 2626, 3484, 4638, 6189, \ + 125, 470, 608, 794, 1035, 1349, 1765, 2316, 3054, 4072, 5412, 7264 } + +/* "(WAT -8%) Leakage Power" */ +#define CPU_TABLE_2 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 4, 5, 7, 8, 11, 13, 17, 22, 28, 36, 47, \ + 5, 5, 6, 7, 9, 12, 15, 19, 24, 31, 40, 52, \ + 10, 5, 6, 8, 10, 13, 16, 21, 27, 34, 44, 58, \ + 15, 6, 7, 9, 11, 14, 18, 23, 30, 39, 50, 66, \ + 20, 6, 8, 10, 13, 16, 20, 26, 34, 44, 57, 75, \ + 25, 7, 9, 11, 14, 18, 23, 29, 38, 50, 65, 86, \ + 30, 8, 10, 13, 16, 21, 27, 34, 44, 58, 76, 100, \ + 35, 9, 12, 15, 19, 24, 31, 40, 52, 67, 88, 116, \ + 40, 11, 14, 17, 22, 28, 36, 47, 61, 79, 104, 138, \ + 45, 13, 16, 20, 26, 33, 43, 56, 72, 95, 125, 165, \ + 50, 15, 19, 24, 31, 40, 52, 67, 87, 114, 151, 199, \ + 55, 18, 23, 29, 37, 48, 62, 81, 106, 139, 184, 243, \ + 60, 22, 28, 35, 45, 58, 76, 99, 130, 171, 225, 298, \ + 65, 27, 34, 43, 56, 72, 94, 122, 160, 211, 277, 371, \ + 70, 33, 42, 54, 69, 89, 117, 153, 200, 262, 348, 467, \ + 75, 40, 52, 67, 87, 113, 147, 191, 250, 332, 443, 595, \ + 80, 51, 65, 85, 110, 143, 186, 244, 324, 431, 575, 772, \ + 85, 65, 84, 108, 141, 185, 242, 317, 420, 558, 746, 1002, \ + 90, 84, 109, 141, 182, 238, 313, 413, 543, 726, 967, 1301, \ + 95, 109, 140, 183, 238, 313, 411, 539, 713, 954, 1272, 1711, \ + 100, 144, 186, 242, 313, 411, 540, 711, 939, 1256, 1685, 2276, \ + 105, 190, 246, 319, 417, 545, 715, 944, 1252, 1676, 2247, 3032, \ + 110, 251, 325, 424, 554, 726, 951, 1255, 1669, 2235, 3012, 4077, \ + 115, 336, 436, 566, 743, 972, 1276, 1700, 2262, 3031, 4057, 5515, \ + 120, 445, 585, 766, 1012, 1318, 1741, 2300, 3066, 4118, 5552, 7582, \ + 125, 610, 796, 1039, 1366, 1792, 2346, 3124, 4209, 5628, 7739, 10561 } + +/* "(WAT 12.6%) Leakage Power" */ +#define VCORE_TABLE_0 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 2, 2, 3, 5, 6, 9, 12, 17, 24, 34, 48,\ + 5, 2, 3, 4, 6, 8, 11, 15, 20, 28, 39, 55,\ + 10, 3, 4, 5, 7, 9, 12, 17, 23, 32, 45, 62,\ + 15, 3, 5, 6, 8, 11, 15, 20, 27, 37, 51, 71,\ + 20, 4, 6, 7, 10, 13, 18, 24, 32, 43, 59, 81,\ + 25, 5, 7, 9, 12, 16, 21, 28, 37, 50, 68, 92,\ + 30, 6, 8, 11, 14, 19, 24, 33, 43, 58, 78, 105,\ + 35, 8, 10, 13, 17, 22, 29, 38, 50, 67, 89, 120,\ + 40, 9, 12, 16, 20, 26, 34, 45, 59, 77, 102, 135,\ + 45, 12, 15, 19, 25, 31, 41, 52, 68, 89, 117, 154,\ + 50, 14, 18, 23, 30, 38, 48, 62, 80, 103, 135, 176,\ + 55, 18, 22, 28, 36, 45, 57, 73, 93, 120, 154, 200,\ + 60, 22, 27, 34, 43, 54, 68, 86, 108, 138, 177, 228,\ + 65, 27, 33, 41, 51, 64, 81, 101, 126, 161, 203, 259,\ + 70, 33, 40, 50, 62, 77, 95, 118, 147, 185, 233, 294,\ + 75, 41, 49, 60, 74, 91, 113, 139, 171, 214, 267, 335,\ + 80, 50, 60, 72, 88, 108, 132, 162, 199, 246, 306, 379,\ + 85, 62, 74, 88, 106, 128, 157, 191, 232, 283, 348, 427,\ + 90, 77, 91, 108, 128, 153, 184, 223, 269, 326, 397, 484,\ + 95, 94, 112, 131, 154, 183, 218, 260, 312, 373, 452, 549,\ + 100, 116, 137, 160, 187, 219, 258, 306, 361, 429, 516, 626,\ + 105, 143, 167, 195, 225, 263, 305, 359, 422, 496, 594, 709,\ + 110, 176, 203, 235, 271, 313, 364, 421, 493, 576, 682, 803,\ + 115, 217, 247, 283, 327, 375, 430, 495, 574, 670, 782, 920,\ + 120, 267, 302, 345, 392, 448, 511, 584, 667, 775, 899, 1048,\ + 125, 328, 368, 418, 471, 536, 608, 690, 781, 888, 1027, 1190 } + +/* "(WAT 4.2%) Leakage Power" */ +#define VCORE_TABLE_1 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 2, 3, 4, 5, 7, 9, 13, 18, 25, 35, 49, \ + 5, 2, 3, 4, 6, 8, 11, 14, 20, 27, 38, 53, \ + 10, 3, 4, 5, 7, 9, 12, 16, 22, 30, 41, 57, \ + 15, 3, 4, 6, 8, 10, 13, 18, 24, 33, 45, 62, \ + 20, 4, 5, 7, 9, 12, 15, 20, 27, 37, 50, 68, \ + 25, 5, 6, 8, 10, 13, 17, 23, 31, 41, 55, 75, \ + 30, 5, 7, 9, 12, 15, 20, 26, 35, 46, 62, 83, \ + 35, 6, 8, 11, 14, 18, 23, 30, 39, 52, 69, 93, \ + 40, 8, 10, 12, 16, 21, 27, 34, 45, 60, 78, 104, \ + 45, 9, 12, 15, 19, 24, 31, 40, 52, 68, 89, 117, \ + 50, 11, 14, 17, 22, 28, 36, 46, 60, 78, 101, 133, \ + 55, 13, 17, 21, 26, 33, 42, 54, 69, 90, 117, 151, \ + 60, 16, 20, 25, 32, 40, 50, 64, 81, 104, 134, 174, \ + 65, 20, 25, 31, 38, 47, 59, 75, 95, 121, 155, 199, \ + 70, 25, 30, 37, 46, 57, 71, 89, 113, 142, 181, 232, \ + 75, 31, 37, 46, 56, 69, 85, 106, 133, 168, 212, 269, \ + 80, 38, 46, 56, 68, 84, 103, 127, 158, 198, 249, 315, \ + 85, 48, 57, 69, 84, 102, 125, 153, 190, 235, 294, 370, \ + 90, 60, 72, 85, 103, 124, 151, 185, 227, 280, 349, 436, \ + 95, 76, 90, 106, 127, 152, 185, 224, 274, 338, 418, 519, \ + 100, 96, 113, 133, 158, 189, 228, 274, 333, 407, 499, 616, \ + 105, 123, 143, 168, 198, 236, 282, 338, 407, 490, 597, 731, \ + 110, 158, 183, 213, 249, 295, 350, 415, 495, 597, 720, 879, \ + 115, 203, 234, 271, 315, 368, 432, 512, 605, 726, 870, 1062, \ + 120, 262, 300, 346, 399, 465, 541, 634, 748, 892, 1061, 1292, \ + 125, 341, 387, 442, 513, 591, 685, 798, 929, 1101, 1293, 1565 } + +/*"(WAT -8%) Leakage Power" */ +#define VCORE_TABLE_2 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 2, 3, 4, 5, 7, 10, 14, 20, 28, 39, 55, \ + 5, 2, 3, 4, 6, 8, 11, 15, 21, 29, 40, 56, \ + 10, 3, 3, 5, 6, 8, 11, 16, 22, 30, 41, 58, \ + 15, 3, 4, 5, 7, 9, 12, 17, 23, 31, 43, 60, \ + 20, 3, 4, 5, 7, 10, 13, 18, 24, 33, 45, 62, \ + 25, 3, 5, 6, 8, 11, 14, 19, 26, 35, 48, 66, \ + 30, 4, 5, 7, 9, 12, 16, 21, 28, 38, 51, 70, \ + 35, 4, 6, 7, 10, 13, 17, 23, 30, 41, 55, 74, \ + 40, 5, 7, 8, 11, 14, 19, 25, 33, 44, 59, 80, \ + 45, 6, 7, 10, 12, 16, 21, 28, 37, 48, 64, 86, \ + 50, 7, 9, 11, 14, 18, 24, 31, 41, 53, 70, 93, \ + 55, 8, 10, 13, 16, 21, 27, 35, 45, 59, 77, 102, \ + 60, 9, 12, 15, 19, 24, 30, 39, 50, 65, 86, 112, \ + 65, 11, 14, 17, 22, 27, 35, 44, 57, 73, 96, 125, \ + 70, 13, 16, 20, 25, 32, 40, 51, 65, 83, 107, 139, \ + 75, 15, 19, 24, 30, 37, 47, 59, 74, 94, 121, 157, \ + 80, 19, 23, 28, 35, 43, 54, 68, 85, 108, 137, 176, \ + 85, 22, 27, 34, 41, 51, 63, 79, 99, 124, 156, 200, \ + 90, 27, 33, 41, 49, 61, 75, 93, 115, 143, 180, 227, \ + 95, 34, 41, 49, 60, 73, 89, 109, 136, 167, 208, 262, \ + 100, 42, 50, 60, 72, 88, 107, 131, 161, 197, 244, 305, \ + 105, 52, 62, 74, 88, 107, 129, 157, 191, 234, 288, 356, \ + 110, 65, 77, 91, 109, 130, 156, 189, 228, 278, 340, 418, \ + 115, 82, 96, 114, 135, 160, 191, 229, 276, 334, 405, 497, \ + 120, 104, 122, 143, 168, 198, 235, 281, 335, 404, 486, 592, \ + 125, 133, 155, 180, 211, 247, 292, 346, 410, 490, 587, 716 } + +/* "(WAT 12.6%) Leakage Power" */ +#define GPU_TABLE_0 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 1, 2, 2, 3, 4, 5, 7, 10, 14, 19,\ + 5, 1, 1, 2, 2, 3, 4, 6, 8, 11, 15, 21,\ + 10, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, 22,\ + 15, 1, 2, 2, 3, 4, 6, 8, 10, 13, 18, 24,\ + 20, 2, 2, 3, 4, 5, 7, 9, 12, 15, 20, 27,\ + 25, 2, 3, 3, 4, 6, 8, 10, 13, 17, 23, 30,\ + 30, 2, 3, 4, 5, 7, 9, 12, 15, 20, 26, 34,\ + 35, 3, 4, 5, 6, 8, 11, 14, 18, 23, 30, 38,\ + 40, 4, 5, 6, 8, 10, 13, 16, 20, 26, 34, 44,\ + 45, 5, 6, 7, 9, 12, 15, 19, 24, 31, 39, 50,\ + 50, 6, 7, 9, 11, 14, 18, 23, 29, 36, 46, 58,\ + 55, 7, 9, 11, 14, 17, 22, 27, 34, 43, 53, 67,\ + 60, 9, 11, 14, 17, 21, 26, 32, 40, 50, 63, 78,\ + 65, 11, 14, 17, 21, 25, 32, 39, 47, 59, 73, 91,\ + 70, 14, 17, 21, 26, 32, 38, 47, 58, 71, 87, 107,\ + 75, 18, 22, 27, 32, 39, 47, 56, 69, 85, 104, 127,\ + 80, 23, 28, 34, 40, 48, 58, 70, 84, 102, 124, 152,\ + 85, 30, 36, 43, 51, 60, 72, 86, 103, 124, 149, 182,\ + 90, 39, 46, 55, 64, 76, 91, 108, 129, 152, 183, 219,\ + 95, 51, 60, 71, 83, 98, 114, 135, 160, 190, 226, 269,\ + 100, 67, 78, 93, 109, 128, 147, 172, 202, 239, 282, 332,\ + 105, 90, 104, 122, 143, 165, 191, 221, 259, 302, 354, 415,\ + 110, 121, 140, 162, 186, 215, 248, 281, 329, 383, 447, 517,\ + 115, 165, 191, 216, 245, 279, 318, 362, 417, 477, 552, 639,\ + 120, 224, 256, 291, 326, 369, 415, 473, 534, 604, 692, 793,\ + 125, 308, 350, 395, 443, 495, 550, 621, 689, 777, 883, 995 } + +/* "(WAT 4.2%) Leakage Power" */ +#define GPU_TABLE_1 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 1, 1, 2, 3, 3, 4, 6, 8, 11, 15, \ + 5, 1, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, \ + 10, 1, 1, 2, 2, 3, 4, 6, 7, 10, 13, 18, \ + 15, 1, 2, 2, 3, 4, 5, 6, 8, 11, 15, 20, \ + 20, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, 22, \ + 25, 2, 2, 3, 4, 5, 6, 8, 10, 14, 18, 24, \ + 30, 2, 2, 3, 4, 5, 7, 9, 12, 15, 20, 27, \ + 35, 2, 3, 4, 5, 6, 8, 10, 13, 17, 23, 30, \ + 40, 3, 4, 4, 6, 7, 9, 12, 15, 20, 26, 34, \ + 45, 3, 4, 5, 7, 8, 11, 14, 18, 23, 29, 38, \ + 50, 4, 5, 6, 8, 10, 13, 16, 20, 26, 33, 43, \ + 55, 5, 6, 8, 10, 12, 15, 19, 24, 30, 39, 49, \ + 60, 6, 8, 9, 12, 15, 18, 23, 28, 36, 45, 57, \ + 65, 8, 10, 12, 14, 18, 22, 27, 34, 42, 52, 65, \ + 70, 10, 12, 15, 18, 22, 27, 33, 40, 50, 62, 77, \ + 75, 13, 15, 18, 22, 27, 32, 40, 49, 60, 74, 92, \ + 80, 16, 19, 23, 28, 33, 40, 49, 59, 72, 89, 110, \ + 85, 21, 25, 29, 35, 42, 50, 60, 73, 88, 108, 132, \ + 90, 27, 32, 38, 44, 53, 63, 75, 90, 108, 131, 160, \ + 95, 35, 41, 49, 57, 67, 79, 93, 110, 132, 160, 194, \ + 100, 47, 54, 64, 74, 86, 100, 118, 139, 164, 197, 238, \ + 105, 63, 73, 83, 95, 110, 127, 149, 174, 206, 244, 290, \ + 110, 86, 96, 110, 124, 143, 164, 191, 220, 262, 309, 366, \ + 115, 114, 128, 145, 163, 186, 215, 246, 285, 335, 392, 461, \ + 120, 152, 172, 192, 218, 248, 281, 323, 373, 430, 503, 586, \ + 125, 207, 233, 260, 295, 330, 368, 423, 488, 560, 651, 750 } + +/* "(WAT -8%) Leakage Power" */ +#define GPU_TABLE_2 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 1, 2, 2, 3, 4, 6, 8, 10, 14, 20, \ + 5, 1, 1, 2, 2, 3, 4, 6, 8, 11, 15, 20, \ + 10, 1, 1, 2, 3, 3, 5, 6, 8, 11, 15, 21, \ + 15, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, 21, \ + 20, 1, 2, 2, 3, 4, 5, 7, 9, 13, 17, 22, \ + 25, 1, 2, 3, 3, 4, 6, 8, 10, 13, 18, 23, \ + 30, 2, 2, 3, 4, 5, 6, 8, 11, 14, 19, 25, \ + 35, 2, 2, 3, 4, 5, 7, 9, 12, 16, 20, 26, \ + 40, 2, 3, 4, 5, 6, 8, 10, 13, 17, 22, 28, \ + 45, 3, 3, 4, 5, 7, 9, 11, 14, 18, 24, 30, \ + 50, 3, 4, 5, 6, 8, 10, 13, 16, 20, 26, 33, \ + 55, 3, 4, 6, 7, 9, 11, 14, 18, 23, 29, 37, \ + 60, 4, 5, 6, 8, 10, 13, 16, 20, 26, 32, 41, \ + 65, 5, 6, 8, 9, 12, 15, 18, 23, 29, 36, 46, \ + 70, 6, 7, 9, 11, 14, 17, 21, 26, 33, 41, 52, \ + 75, 7, 9, 11, 13, 16, 20, 25, 31, 38, 47, 59, \ + 80, 9, 10, 13, 16, 19, 24, 29, 36, 44, 54, 67, \ + 85, 10, 13, 15, 19, 23, 28, 34, 42, 51, 63, 77, \ + 90, 13, 15, 19, 23, 28, 34, 41, 49, 60, 74, 90, \ + 95, 16, 19, 23, 28, 33, 40, 48, 59, 72, 87, 105, \ + 100, 20, 24, 28, 34, 41, 49, 58, 71, 85, 103, 124, \ + 105, 25, 30, 36, 42, 51, 60, 72, 85, 102, 122, 146, \ + 110, 32, 37, 44, 53, 64, 74, 87, 104, 124, 147, 176, \ + 115, 40, 47, 56, 67, 79, 93, 108, 127, 151, 179, 213, \ + 120, 52, 60, 72, 85, 99, 115, 134, 158, 187, 218, 258, \ + 125, 69, 79, 92, 108, 127, 144, 168, 197, 231, 270, 315 } + +/* "(WAT 12.6%) Leakage Power" */ +#define VMD1_TABLE_0 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 2, 2, 3, 5, 6, 8, 11, 15, 21, 29,\ + 5, 2, 2, 3, 4, 5, 7, 10, 13, 18, 25, 33,\ + 10, 2, 3, 4, 5, 7, 9, 12, 16, 21, 28, 38,\ + 15, 2, 3, 4, 6, 8, 10, 14, 18, 24, 33, 44,\ + 20, 3, 4, 5, 7, 9, 12, 16, 22, 29, 38, 50,\ + 25, 4, 5, 6, 8, 11, 15, 19, 25, 33, 44, 58,\ + 30, 5, 6, 8, 10, 13, 17, 23, 29, 39, 51, 67,\ + 35, 6, 7, 9, 12, 16, 20, 27, 34, 45, 58, 76,\ + 40, 7, 9, 11, 15, 19, 24, 31, 40, 52, 67, 88,\ + 45, 8, 11, 14, 18, 22, 29, 37, 47, 60, 78, 100,\ + 50, 10, 13, 17, 21, 27, 34, 43, 55, 70, 90, 115,\ + 55, 13, 16, 20, 25, 32, 40, 51, 64, 81, 103, 131,\ + 60, 15, 19, 24, 30, 38, 48, 60, 75, 94, 119, 150,\ + 65, 19, 23, 29, 36, 45, 56, 70, 87, 109, 137, 172,\ + 70, 23, 28, 35, 43, 54, 66, 82, 102, 126, 157, 196,\ + 75, 28, 34, 42, 52, 64, 78, 96, 118, 146, 180, 224,\ + 80, 34, 42, 51, 62, 76, 92, 112, 137, 168, 207, 255,\ + 85, 42, 50, 61, 74, 90, 108, 131, 160, 194, 237, 290,\ + 90, 51, 61, 73, 89, 106, 128, 154, 186, 225, 272, 331,\ + 95, 62, 74, 88, 105, 126, 151, 181, 216, 260, 312, 376,\ + 100, 75, 89, 106, 125, 149, 178, 211, 252, 300, 359, 428,\ + 105, 92, 108, 127, 149, 175, 207, 246, 292, 346, 410, 487,\ + 110, 112, 131, 152, 178, 208, 243, 285, 335, 396, 468, 553,\ + 115, 136, 159, 183, 212, 245, 285, 332, 388, 454, 533, 626,\ + 120, 166, 191, 220, 253, 292, 335, 387, 449, 521, 606, 706,\ + 125, 202, 231, 264, 302, 345, 394, 452, 520, 600, 693, 802 } + +/* "(WAT 4.2%) Leakage Power" */ +#define VMD1_TABLE_1 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 1, 2, 3, 3, 5, 6, 9, 12, 16, 22, \ + 5, 1, 2, 2, 3, 4, 5, 7, 10, 13, 18, 25, \ + 10, 1, 2, 3, 4, 5, 6, 9, 11, 15, 21, 28, \ + 15, 2, 2, 3, 4, 6, 7, 10, 13, 18, 23, 32, \ + 20, 2, 3, 4, 5, 7, 9, 11, 15, 20, 27, 36, \ + 25, 3, 3, 4, 6, 8, 10, 13, 18, 23, 31, 41, \ + 30, 3, 4, 5, 7, 9, 12, 16, 20, 27, 35, 46, \ + 35, 4, 5, 6, 8, 11, 14, 18, 24, 31, 40, 52, \ + 40, 5, 6, 8, 10, 13, 16, 21, 28, 36, 46, 60, \ + 45, 6, 7, 9, 12, 15, 19, 25, 32, 41, 53, 68, \ + 50, 7, 9, 11, 14, 18, 23, 29, 37, 48, 61, 78, \ + 55, 8, 11, 13, 17, 22, 27, 35, 44, 55, 71, 90, \ + 60, 10, 13, 16, 20, 26, 32, 41, 51, 65, 82, 103, \ + 65, 13, 16, 20, 25, 31, 38, 48, 60, 76, 95, 119, \ + 70, 16, 19, 24, 30, 37, 46, 57, 71, 88, 110, 137, \ + 75, 19, 24, 29, 36, 44, 55, 68, 84, 103, 128, 158, \ + 80, 24, 29, 36, 44, 53, 65, 80, 98, 121, 149, 184, \ + 85, 30, 36, 44, 53, 64, 78, 95, 116, 142, 174, 213, \ + 90, 37, 44, 53, 64, 78, 94, 113, 137, 167, 203, 249, \ + 95, 46, 55, 66, 78, 94, 113, 135, 163, 196, 238, 288, \ + 100, 57, 68, 81, 96, 114, 136, 162, 194, 232, 279, 336, \ + 105, 71, 84, 99, 117, 138, 163, 194, 231, 275, 328, 392, \ + 110, 89, 104, 122, 143, 168, 197, 233, 275, 325, 386, 458, \ + 115, 111, 129, 150, 175, 204, 239, 280, 328, 386, 454, 537, \ + 120, 139, 160, 185, 214, 248, 288, 334, 390, 456, 534, 629, \ + 125, 173, 199, 228, 262, 302, 349, 404, 468, 543, 633, 739 } + +/* "(WAT -8%) Leakage Power" */ +#define VMD1_TABLE_2 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 1, 2, 3, 4, 5, 7, 9, 13, 17, 24, \ + 5, 1, 2, 2, 3, 4, 5, 7, 10, 13, 18, 25, \ + 10, 1, 2, 2, 3, 4, 6, 8, 10, 14, 19, 26, \ + 15, 1, 2, 3, 3, 5, 6, 8, 11, 15, 20, 27, \ + 20, 2, 2, 3, 4, 5, 7, 9, 12, 16, 22, 29, \ + 25, 2, 2, 3, 4, 6, 7, 10, 13, 17, 23, 31, \ + 30, 2, 3, 4, 5, 6, 8, 11, 14, 19, 25, 33, \ + 35, 2, 3, 4, 5, 7, 9, 12, 16, 21, 27, 36, \ + 40, 3, 4, 5, 6, 8, 10, 13, 17, 23, 30, 39, \ + 45, 3, 4, 5, 7, 9, 12, 15, 19, 25, 33, 43, \ + 50, 4, 5, 6, 8, 10, 13, 17, 22, 28, 36, 47, \ + 55, 5, 6, 7, 9, 12, 15, 19, 24, 31, 40, 52, \ + 60, 5, 7, 8, 11, 14, 17, 22, 28, 35, 45, 58, \ + 65, 6, 8, 10, 13, 16, 20, 25, 32, 40, 51, 65, \ + 70, 8, 9, 12, 15, 18, 23, 29, 36, 46, 58, 73, \ + 75, 9, 11, 14, 17, 22, 27, 34, 42, 52, 66, 83, \ + 80, 11, 14, 17, 21, 26, 32, 39, 49, 61, 76, 95, \ + 85, 14, 17, 20, 25, 31, 38, 46, 57, 71, 88, 109, \ + 90, 17, 20, 25, 30, 37, 45, 55, 67, 83, 102, 126, \ + 95, 20, 25, 30, 36, 44, 53, 65, 80, 97, 119, 146, \ + 100, 25, 30, 37, 44, 53, 65, 78, 95, 115, 140, 171, \ + 105, 32, 38, 45, 55, 65, 79, 95, 114, 137, 165, 201, \ + 110, 40, 48, 56, 67, 80, 96, 115, 137, 165, 198, 239, \ + 115, 51, 60, 71, 84, 99, 118, 140, 167, 199, 237, 285, \ + 120, 65, 77, 90, 105, 124, 146, 172, 205, 242, 288, 342, \ + 125, 84, 97, 114, 133, 155, 182, 214, 251, 296, 351, 413 } + +/* "(WAT 12.6%) Leakage Power" */ +#define MODEM_TABLE_0 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 2, 3, 4, 5, 6, 9, 12, 16, 21, 28,\ + 5, 2, 2, 3, 4, 6, 8, 10, 14, 18, 24, 32,\ + 10, 2, 3, 4, 5, 7, 9, 12, 16, 21, 28, 37,\ + 15, 3, 4, 5, 6, 8, 11, 14, 19, 25, 32, 42,\ + 20, 3, 4, 6, 7, 10, 13, 17, 22, 28, 37, 48,\ + 25, 4, 5, 7, 9, 12, 15, 20, 25, 33, 42, 55,\ + 30, 5, 6, 8, 11, 14, 18, 23, 30, 38, 49, 63,\ + 35, 6, 8, 10, 13, 17, 21, 27, 35, 45, 57, 73,\ + 40, 7, 9, 12, 15, 20, 25, 32, 41, 52, 66, 84,\ + 45, 9, 11, 15, 19, 24, 30, 38, 48, 61, 77, 96,\ + 50, 11, 14, 18, 22, 28, 36, 45, 56, 71, 89, 111,\ + 55, 13, 17, 22, 27, 34, 43, 53, 66, 83, 103, 128,\ + 60, 17, 21, 26, 33, 41, 51, 63, 78, 97, 120, 148,\ + 65, 21, 26, 32, 40, 49, 61, 75, 92, 113, 139, 170,\ + 70, 25, 32, 39, 48, 59, 72, 89, 109, 133, 162, 197,\ + 75, 31, 39, 48, 59, 71, 87, 105, 128, 155, 188, 229,\ + 80, 39, 48, 58, 71, 86, 104, 125, 151, 182, 220, 265,\ + 85, 48, 58, 71, 86, 104, 125, 150, 179, 215, 256, 306,\ + 90, 60, 72, 87, 104, 125, 150, 179, 212, 252, 300, 355,\ + 95, 74, 89, 106, 127, 151, 180, 214, 252, 297, 350, 412,\ + 100, 93, 110, 131, 155, 183, 216, 255, 299, 350, 410, 479,\ + 105, 116, 137, 161, 189, 222, 260, 304, 355, 413, 480, 557,\ + 110, 144, 169, 199, 231, 269, 313, 364, 422, 487, 563, 649,\ + 115, 181, 210, 244, 284, 327, 377, 436, 502, 575, 659, 756,\ + 120, 226, 262, 301, 347, 398, 457, 522, 596, 681, 775, 881,\ + 125, 281, 324, 372, 425, 483, 550, 625, 709, 804, 911, 1031 } + +/* "(WAT 4.2%) Leakage Power" */ +#define MODEM_TABLE_1 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 1, 2, 3, 4, 5, 7, 9, 12, 16, 22, \ + 5, 1, 2, 2, 3, 4, 6, 7, 10, 14, 18, 24, \ + 10, 1, 2, 3, 4, 5, 6, 9, 11, 15, 20, 27, \ + 15, 2, 2, 3, 4, 6, 7, 10, 13, 17, 23, 30, \ + 20, 2, 3, 4, 5, 7, 9, 11, 15, 20, 26, 34, \ + 25, 3, 3, 4, 6, 8, 10, 13, 17, 22, 29, 38, \ + 30, 3, 4, 5, 7, 9, 12, 15, 20, 26, 33, 43, \ + 35, 4, 5, 6, 8, 11, 14, 18, 23, 30, 38, 49, \ + 40, 5, 6, 8, 10, 13, 16, 21, 27, 34, 44, 55, \ + 45, 6, 7, 9, 12, 15, 19, 25, 31, 40, 50, 63, \ + 50, 7, 9, 11, 14, 18, 23, 29, 37, 46, 58, 73, \ + 55, 9, 11, 14, 17, 22, 28, 35, 43, 54, 68, 84, \ + 60, 11, 13, 17, 21, 27, 33, 41, 51, 64, 79, 98, \ + 65, 13, 17, 21, 26, 32, 40, 49, 61, 75, 93, 114, \ + 70, 17, 21, 26, 32, 40, 49, 60, 73, 89, 109, 133, \ + 75, 21, 26, 32, 40, 49, 59, 72, 88, 106, 130, 157, \ + 80, 27, 33, 40, 50, 60, 73, 87, 106, 128, 154, 185, \ + 85, 34, 42, 51, 62, 74, 89, 107, 129, 154, 184, 220, \ + 90, 44, 53, 64, 77, 92, 110, 131, 156, 186, 221, 262, \ + 95, 56, 68, 81, 96, 114, 135, 161, 191, 225, 266, 314, \ + 100, 72, 86, 102, 121, 142, 168, 198, 233, 273, 320, 376, \ + 105, 94, 110, 129, 152, 178, 208, 244, 285, 333, 388, 452, \ + 110, 122, 142, 165, 192, 223, 260, 302, 350, 406, 471, 546, \ + 115, 158, 183, 212, 245, 282, 325, 376, 432, 497, 573, 660, \ + 120, 207, 237, 272, 312, 358, 411, 470, 537, 614, 702, 802, \ + 125, 271, 310, 352, 401, 456, 519, 590, 669, 759, 862, 980 } + +/* "(WAT -8%) Leakage Power" */ +#define MODEM_TABLE_2 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 1, 2, 2, 3, 4, 5, 7, 10, 13, 18, 24, \ + 5, 1, 2, 2, 3, 4, 6, 8, 10, 14, 19, 25, \ + 10, 1, 2, 3, 3, 5, 6, 8, 11, 14, 19, 26, \ + 15, 2, 2, 3, 4, 5, 7, 9, 12, 15, 20, 27, \ + 20, 2, 2, 3, 4, 5, 7, 9, 12, 16, 22, 29, \ + 25, 2, 3, 3, 4, 6, 8, 10, 13, 18, 23, 30, \ + 30, 2, 3, 4, 5, 7, 9, 11, 15, 19, 25, 33, \ + 35, 3, 3, 4, 6, 7, 10, 12, 16, 21, 27, 35, \ + 40, 3, 4, 5, 6, 8, 11, 14, 18, 23, 29, 38, \ + 45, 3, 4, 6, 7, 9, 12, 15, 20, 25, 32, 41, \ + 50, 4, 5, 7, 8, 11, 14, 18, 22, 28, 36, 46, \ + 55, 5, 6, 8, 10, 12, 16, 20, 25, 32, 40, 51, \ + 60, 6, 7, 9, 12, 15, 18, 23, 29, 36, 45, 57, \ + 65, 7, 9, 11, 14, 17, 21, 27, 33, 41, 52, 64, \ + 70, 8, 10, 13, 16, 20, 25, 31, 38, 48, 59, 73, \ + 75, 10, 13, 16, 19, 24, 30, 36, 45, 55, 68, 84, \ + 80, 12, 15, 19, 23, 29, 35, 43, 53, 65, 79, 97, \ + 85, 15, 19, 23, 28, 35, 42, 52, 63, 77, 93, 114, \ + 90, 19, 24, 29, 35, 42, 51, 62, 75, 91, 110, 133, \ + 95, 24, 29, 36, 43, 52, 63, 76, 91, 109, 132, 158, \ + 100, 31, 37, 45, 54, 65, 77, 93, 110, 132, 158, 188, \ + 105, 39, 47, 57, 67, 81, 96, 114, 136, 161, 191, 227, \ + 110, 51, 61, 72, 86, 101, 120, 142, 168, 198, 234, 276, \ + 115, 67, 78, 93, 109, 129, 151, 177, 208, 245, 288, 337, \ + 120, 87, 102, 120, 141, 165, 192, 224, 261, 305, 355, 416, \ + 125, 115, 135, 157, 182, 211, 246, 286, 332, 384, 445, 516 } + +/* "(WAT 12.6%) Leakage Power" */ +#define VMODEM_SRAM_TABLE_0 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 2, 2, 3, 5, 7, 9, 12, 17, 23, 32, 44,\ + 5, 2, 3, 4, 5, 7, 10, 13, 18, 25, 34, 46,\ + 10, 2, 3, 4, 6, 8, 11, 14, 19, 26, 35, 48,\ + 15, 3, 4, 5, 6, 9, 12, 16, 21, 28, 38, 51,\ + 20, 3, 4, 5, 7, 10, 13, 17, 23, 31, 41, 55,\ + 25, 3, 5, 6, 8, 11, 15, 19, 26, 34, 45, 59,\ + 30, 4, 5, 7, 9, 12, 16, 22, 28, 37, 49, 64,\ + 35, 5, 6, 8, 11, 14, 18, 24, 32, 41, 54, 70,\ + 40, 5, 7, 9, 12, 16, 21, 27, 36, 46, 60, 77,\ + 45, 6, 8, 11, 14, 19, 24, 31, 40, 52, 67, 86,\ + 50, 8, 10, 13, 17, 22, 28, 36, 46, 59, 75, 96,\ + 55, 9, 12, 15, 20, 25, 32, 41, 52, 67, 85, 108,\ + 60, 11, 14, 18, 23, 29, 37, 48, 60, 76, 97, 122,\ + 65, 13, 17, 22, 28, 35, 44, 56, 70, 88, 110, 138,\ + 70, 16, 21, 26, 33, 42, 52, 65, 82, 102, 127, 158,\ + 75, 20, 26, 32, 40, 50, 62, 78, 96, 119, 148, 182,\ + 80, 25, 31, 39, 49, 61, 75, 92, 114, 140, 172, 211,\ + 85, 31, 39, 48, 59, 73, 90, 110, 136, 166, 203, 247,\ + 90, 39, 49, 59, 73, 88, 108, 132, 161, 197, 240, 290,\ + 95, 49, 61, 74, 90, 109, 132, 162, 196, 236, 285, 343,\ + 100, 62, 76, 93, 113, 136, 164, 197, 237, 284, 341, 408,\ + 105, 79, 97, 117, 141, 170, 203, 243, 290, 346, 412, 489,\ + 110, 102, 124, 149, 179, 214, 254, 302, 357, 422, 498, 587,\ + 115, 132, 159, 189, 227, 269, 317, 374, 438, 515, 605, 710,\ + 120, 171, 203, 242, 286, 336, 397, 466, 546, 637, 743, 868,\ + 125, 222, 263, 308, 361, 424, 497, 578, 676, 788, 916, 1061 } + +/* "(WAT 4.2%) Leakage Power" */ +#define VMODEM_SRAM_TABLE_1 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 4, 5, 6, 8, 10, 13, 17, 22, 28, 36, 46, \ + 5, 4, 5, 7, 9, 11, 14, 18, 23, 29, 37, 49, \ + 10, 5, 6, 7, 9, 12, 15, 19, 24, 31, 40, 52, \ + 15, 5, 6, 8, 10, 12, 16, 20, 26, 33, 42, 55, \ + 20, 5, 7, 8, 11, 13, 17, 21, 27, 35, 45, 59, \ + 25, 6, 7, 9, 12, 14, 18, 23, 30, 38, 49, 63, \ + 30, 6, 8, 10, 13, 16, 20, 25, 32, 42, 53, 69, \ + 35, 7, 9, 11, 14, 17, 22, 28, 35, 45, 58, 75, \ + 40, 8, 10, 12, 15, 19, 24, 31, 39, 50, 64, 83, \ + 45, 9, 11, 13, 17, 21, 27, 34, 44, 56, 72, 92, \ + 50, 10, 12, 15, 19, 24, 30, 38, 49, 62, 80, 103, \ + 55, 11, 14, 17, 22, 27, 34, 43, 55, 70, 90, 116, \ + 60, 13, 16, 20, 25, 31, 39, 49, 63, 80, 102, 132, \ + 65, 15, 18, 23, 28, 36, 45, 57, 72, 92, 118, 151, \ + 70, 17, 21, 26, 33, 41, 52, 66, 84, 106, 135, 174, \ + 75, 20, 25, 31, 39, 48, 61, 77, 97, 123, 156, 201, \ + 80, 23, 29, 36, 45, 56, 71, 90, 113, 144, 184, 235, \ + 85, 28, 34, 43, 53, 66, 83, 105, 133, 169, 216, 277, \ + 90, 33, 41, 51, 63, 79, 99, 124, 158, 201, 257, 328, \ + 95, 39, 49, 61, 76, 95, 118, 149, 188, 239, 305, 391, \ + 100, 47, 59, 73, 91, 113, 142, 178, 225, 286, 365, 466, \ + 105, 57, 71, 88, 110, 137, 171, 214, 271, 344, 440, 564, \ + 110, 70, 87, 108, 134, 166, 208, 261, 330, 419, 536, 687, \ + 115, 86, 106, 132, 164, 205, 256, 320, 403, 511, 653, 837, \ + 120, 107, 131, 162, 202, 251, 315, 393, 495, 627, 801, 1035, \ + 125, 133, 163, 202, 249, 310, 388, 486, 610, 774, 988, 1272 } + +/* "(WAT -8%) Leakage Power" */ +#define VMODEM_SRAM_TABLE_2 \ + { 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200,\ + 0, 2, 3, 4, 5, 7, 9, 12, 16, 22, 29, 39, \ + 5, 3, 3, 4, 6, 7, 10, 13, 17, 22, 30, 40, \ + 10, 3, 4, 5, 6, 8, 10, 13, 17, 23, 31, 42, \ + 15, 3, 4, 5, 6, 8, 11, 14, 18, 24, 32, 43, \ + 20, 3, 4, 5, 7, 9, 11, 15, 19, 25, 34, 45, \ + 25, 3, 4, 5, 7, 9, 12, 15, 20, 27, 35, 47, \ + 30, 4, 5, 6, 8, 10, 13, 16, 22, 28, 37, 49, \ + 35, 4, 5, 6, 8, 10, 14, 18, 23, 30, 40, 52, \ + 40, 4, 5, 7, 9, 11, 15, 19, 25, 32, 42, 56, \ + 45, 5, 6, 8, 10, 12, 16, 21, 27, 35, 46, 60, \ + 50, 5, 7, 8, 11, 14, 18, 23, 29, 38, 50, 65, \ + 55, 6, 7, 9, 12, 15, 19, 25, 32, 42, 54, 71, \ + 60, 7, 8, 10, 13, 17, 22, 28, 36, 46, 60, 78, \ + 65, 8, 9, 12, 15, 19, 24, 31, 39, 51, 66, 85, \ + 70, 9, 11, 13, 17, 21, 27, 34, 44, 57, 73, 95, \ + 75, 10, 12, 15, 19, 24, 31, 39, 50, 64, 82, 106, \ + 80, 11, 14, 17, 22, 28, 35, 44, 56, 72, 92, 119, \ + 85, 13, 16, 20, 25, 32, 40, 50, 64, 81, 104, 135, \ + 90, 15, 19, 23, 29, 36, 46, 58, 73, 92, 118, 152, \ + 95, 18, 22, 27, 34, 42, 53, 67, 85, 106, 136, 175, \ + 100, 21, 26, 32, 39, 49, 61, 77, 97, 123, 157, 202, \ + 105, 25, 30, 37, 46, 57, 72, 90, 112, 142, 181, 232, \ + 110, 29, 36, 44, 54, 67, 84, 104, 130, 165, 210, 268, \ + 115, 35, 42, 52, 64, 79, 98, 121, 153, 193, 244, 311, \ + 120, 41, 50, 61, 76, 93, 115, 143, 179, 224, 284, 361, \ + 125, 49, 60, 74, 90, 111, 137, 168, 211, 264, 332, 423 } + +typedef struct spower_raw_s { + int vsize; + int tsize; + int table_size; + int *table[]; +} spower_raw_t; + + +/** table order: ff,tt,ss **/ + +int cpu_leakage_data[][VSIZE*TSIZE+VSIZE+TSIZE] = { + CPU_TABLE_0, + CPU_TABLE_1, + CPU_TABLE_2, +}; + +int vcore_leakage_data[][VSIZE*TSIZE+VSIZE+TSIZE] = { + VCORE_TABLE_0, + VCORE_TABLE_1, + VCORE_TABLE_2, +}; + +int gpu_leakage_data[][VSIZE*TSIZE+VSIZE+TSIZE] = { + GPU_TABLE_0, + GPU_TABLE_1, + GPU_TABLE_2, +}; + +int vmd1_leakage_data[][VSIZE*TSIZE+VSIZE+TSIZE] = { + VMD1_TABLE_0, + VMD1_TABLE_1, + VMD1_TABLE_2, +}; + +int modem_leakage_data[][VSIZE*TSIZE+VSIZE+TSIZE] = { + MODEM_TABLE_0, + MODEM_TABLE_1, + MODEM_TABLE_2, +}; + +int vmodem_sram_leakage_data[][VSIZE*TSIZE+VSIZE+TSIZE] = { + VMODEM_SRAM_TABLE_0, + VMODEM_SRAM_TABLE_1, + VMODEM_SRAM_TABLE_2, +}; + +spower_raw_t cpu_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = MAX_TABLE_SIZE, + .table = { (int *)&cpu_leakage_data[0], (int *)&cpu_leakage_data[1], (int *)&cpu_leakage_data[2] }, +}; + +spower_raw_t vcore_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = MAX_TABLE_SIZE, + .table = { (int *)&vcore_leakage_data[0], (int *)&vcore_leakage_data[1], (int *)&vcore_leakage_data[2] }, +}; + +spower_raw_t gpu_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = MAX_TABLE_SIZE, + .table = { (int *)&gpu_leakage_data[0], (int *)&gpu_leakage_data[1], (int *)&gpu_leakage_data[2] }, +}; + +spower_raw_t vmd1_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = MAX_TABLE_SIZE, + .table = { (int *)&vmd1_leakage_data[0], (int *)&vmd1_leakage_data[1], (int *)&vmd1_leakage_data[2] }, +}; + +spower_raw_t modem_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = MAX_TABLE_SIZE, + .table = { (int *)&modem_leakage_data[0], (int *)&modem_leakage_data[1], (int *)&modem_leakage_data[2] }, +}; + +spower_raw_t vmodem_sram_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = MAX_TABLE_SIZE, + .table = { (int *)&vmodem_sram_leakage_data[0], (int *)&vmodem_sram_leakage_data[1], + (int *)&vmodem_sram_leakage_data[2] }, +}; + + +typedef struct voltage_row_s { + int mV[VSIZE]; +} vrow_t; + +typedef struct temperature_row_s { + int deg; + int mA[VSIZE]; +} trow_t; + + +typedef struct sptab_s { + int vsize; + int tsize; + int *data; /* array[VSIZE + TSIZE + (VSIZE*TSIZE)] */ + vrow_t *vrow; /* pointer to voltage row of data */ + trow_t *trow; /* pointer to temperature row of data */ +} sptbl_t; + +#define trow(tab, ti) ((tab)->trow[ti]) +#define mA(tab, vi, ti) ((tab)->trow[ti].mA[vi]) +#define mV(tab, vi) ((tab)->vrow[0].mV[vi]) +#define deg(tab, ti) ((tab)->trow[ti].deg) +#define vsize(tab) ((tab)->vsize) +#define tsize(tab) ((tab)->tsize) +#define tab_validate(tab) (!!(tab) && (tab)->data != NULL) + +static inline void spower_tab_construct(sptbl_t (*tab)[], spower_raw_t *raw) +{ + int i; + sptbl_t *ptab = (sptbl_t *)tab; + + for (i = 0; i < raw->table_size; i++) { + ptab->vsize = raw->vsize; + ptab->tsize = raw->tsize; + ptab->data = raw->table[i]; + ptab->vrow = (vrow_t *)ptab->data; + ptab->trow = (trow_t *)(ptab->data + ptab->vsize); + ptab++; + } +} + + + +#endif + + diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_spower_data_d2.h b/drivers/misc/mediatek/base/power/mt6755/mt_spower_data_d2.h new file mode 100644 index 0000000000000000000000000000000000000000..2765cf17d1bbc932ef9e118b3b2a05bfe42784a2 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_spower_data_d2.h @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef MT_SPOWER_CPU_H +#define MT_SPOWER_CPU_H + + + +#define VSIZE 10 +#define TSIZE 20 +#define MAX_TABLE_SIZE 3 + +#define CPU_TABLE_0 \ + /* "(WAT 8.62%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 14, 17, 21, 26, 33, 41, 51, 65, 81, 102,\ + 30, 16, 20, 24, 30, 38, 47, 59, 73, 92, 115,\ + 35, 18, 22, 28, 35, 43, 53, 67, 83, 104, 130,\ + 40, 21, 26, 32, 40, 49, 61, 76, 94, 118, 146,\ + 45, 24, 29, 36, 45, 56, 69, 86, 107, 132, 165,\ + 50, 27, 34, 42, 51, 64, 79, 97, 120, 149, 185,\ + 55, 31, 39, 47, 58, 72, 89, 110, 136, 168, 208,\ + 60, 36, 44, 54, 66, 82, 101, 124, 153, 189, 233,\ + 65, 41, 50, 61, 75, 93, 114, 140, 172, 212, 262,\ + 70, 47, 57, 70, 85, 105, 128, 157, 193, 238, 293,\ + 75, 53, 65, 79, 97, 118, 144, 177, 217, 266, 327,\ + 80, 60, 74, 90, 109, 133, 163, 199, 243, 297, 364,\ + 85, 69, 83, 101, 123, 150, 183, 223, 272, 332, 406,\ + 90, 78, 94, 114, 139, 168, 205, 249, 303, 370, 452,\ + 95, 88, 107, 129, 156, 189, 229, 278, 339, 413, 502,\ + 100, 99, 120, 145, 175, 212, 257, 311, 378, 459, 558,\ + 105, 112, 135, 163, 197, 237, 287, 347, 420, 510, 619,\ + 110, 126, 152, 183, 220, 266, 320, 386, 467, 565, 684,\ + 115, 142, 171, 205, 247, 297, 357, 430, 517, 624, 755,\ + 120, 160, 192, 230, 276, 330, 397, 476, 572, 690, 833}, + +#define CPU_TABLE_1 \ + /* "(WAT 1.72%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 8, 10, 13, 16, 20, 25, 31, 39, 49, 62,\ + 30, 10, 12, 15, 18, 23, 29, 36, 45, 56, 71,\ + 35, 11, 14, 17, 21, 26, 33, 41, 51, 64, 80,\ + 40, 13, 16, 20, 24, 30, 37, 47, 58, 72, 90,\ + 45, 15, 18, 23, 28, 35, 43, 53, 66, 82, 102,\ + 50, 17, 21, 26, 32, 39, 49, 60, 74, 92, 115,\ + 55, 20, 24, 30, 36, 45, 55, 68, 84, 104, 129,\ + 60, 22, 27, 34, 41, 51, 62, 77, 95, 117, 145,\ + 65, 26, 31, 38, 47, 57, 70, 86, 106, 131, 162,\ + 70, 29, 36, 43, 53, 65, 79, 97, 119, 147, 181,\ + 75, 33, 40, 49, 60, 73, 89, 109, 134, 164, 201,\ + 80, 38, 46, 56, 68, 82, 100, 122, 149, 182, 224,\ + 85, 43, 52, 63, 76, 92, 112, 136, 166, 203, 248,\ + 90, 48, 58, 70, 85, 103, 125, 152, 185, 225, 274,\ + 95, 54, 66, 79, 95, 115, 139, 169, 205, 249, 303,\ + 100, 61, 74, 89, 107, 128, 155, 187, 226, 275, 333,\ + 105, 69, 83, 99, 119, 143, 172, 207, 249, 302, 365,\ + 110, 77, 93, 111, 133, 159, 190, 229, 275, 331, 400,\ + 115, 86, 103, 123, 147, 176, 210, 252, 302, 363, 438,\ + 120, 97, 115, 137, 163, 194, 232, 277, 331, 398, 477}, + +#define CPU_TABLE_2 \ + /*"(WAT -11.35%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 4, 4, 5, 7, 8, 10, 13, 16, 21, 26,\ + 30, 4, 5, 6, 8, 9, 12, 15, 18, 23, 29,\ + 35, 5, 6, 7, 9, 11, 13, 17, 21, 26, 33,\ + 40, 5, 6, 8, 10, 12, 15, 19, 23, 29, 36,\ + 45, 6, 7, 9, 11, 14, 17, 21, 26, 33, 41,\ + 50, 7, 9, 10, 13, 16, 19, 24, 29, 37, 46,\ + 55, 8, 10, 12, 14, 18, 22, 27, 33, 41, 51,\ + 60, 9, 11, 14, 17, 20, 25, 30, 37, 46, 57,\ + 65, 11, 13, 16, 19, 23, 28, 34, 42, 52, 63,\ + 70, 12, 15, 18, 21, 26, 32, 39, 47, 58, 71,\ + 75, 14, 17, 20, 24, 30, 36, 44, 53, 65, 79,\ + 80, 16, 19, 23, 28, 34, 41, 49, 60, 72, 89,\ + 85, 19, 22, 27, 32, 38, 46, 55, 67, 81, 99,\ + 90, 22, 26, 31, 36, 44, 52, 63, 76, 92, 111,\ + 95, 25, 30, 35, 42, 50, 59, 71, 86, 103, 125,\ + 100, 29, 34, 40, 48, 57, 67, 81, 97, 116, 141,\ + 105, 33, 39, 46, 55, 64, 77, 91, 109, 131, 158,\ + 110, 38, 45, 53, 62, 73, 87, 103, 123, 147, 176,\ + 115, 44, 52, 61, 71, 84, 99, 117, 139, 165, 198,\ + 120, 51, 60, 70, 82, 96, 113, 133, 157, 186, 222}, + +#define LTE_TABLE_0 \ + /* "(WAT 11.57%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 8, 9, 12, 14, 18, 22, 27, 33, 41, 52,\ + 30, 9, 11, 14, 17, 20, 25, 31, 38, 48, 59,\ + 35, 11, 13, 16, 19, 24, 29, 36, 44, 55, 68,\ + 40, 13, 15, 18, 23, 28, 34, 42, 51, 63, 78,\ + 45, 15, 18, 22, 26, 32, 39, 48, 59, 73, 90,\ + 50, 17, 21, 26, 31, 38, 46, 56, 68, 84, 103,\ + 55, 21, 25, 30, 36, 44, 53, 65, 79, 97, 119,\ + 60, 24, 29, 35, 42, 51, 62, 75, 91, 112, 137,\ + 65, 29, 34, 41, 50, 60, 72, 87, 106, 129, 157,\ + 70, 34, 40, 48, 58, 70, 84, 101, 122, 148, 180,\ + 75, 40, 48, 57, 68, 81, 98, 117, 142, 171, 207,\ + 80, 47, 56, 67, 80, 95, 114, 136, 164, 197, 238,\ + 85, 56, 66, 78, 93, 111, 133, 158, 189, 227, 274,\ + 90, 66, 78, 92, 109, 130, 154, 184, 219, 262, 315,\ + 95, 78, 92, 108, 128, 152, 180, 213, 254, 303, 362,\ + 100, 92, 108, 127, 150, 177, 209, 247, 294, 351, 417,\ + 105, 110, 128, 150, 176, 206, 244, 288, 341, 405, 483,\ + 110, 129, 151, 176, 206, 241, 284, 335, 395, 469, 557,\ + 115, 153, 178, 207, 242, 283, 331, 389, 458, 541, 641,\ + 120, 182, 211, 245, 284, 331, 386, 452, 531, 625, 738}, + + +#define LTE_TABLE_1 \ + /* "(WAT 0.78%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 5, 6, 7, 9, 12, 15, 18, 23, 29, 37,\ + 30, 6, 7, 9, 11, 13, 16, 21, 26, 33, 42,\ + 35, 7, 8, 10, 12, 15, 19, 23, 29, 37, 47,\ + 40, 8, 9, 11, 14, 17, 22, 27, 33, 42, 53,\ + 45, 9, 11, 13, 16, 20, 25, 31, 38, 47, 59,\ + 50, 10, 13, 15, 19, 23, 28, 35, 43, 54, 67,\ + 55, 12, 15, 18, 22, 27, 33, 40, 50, 61, 76,\ + 60, 15, 18, 21, 26, 31, 38, 46, 57, 70, 86,\ + 65, 17, 21, 25, 30, 36, 44, 53, 65, 80, 98,\ + 70, 20, 24, 29, 35, 42, 51, 62, 75, 91, 112,\ + 75, 24, 29, 34, 41, 49, 59, 71, 87, 105, 128,\ + 80, 29, 34, 41, 49, 58, 69, 83, 100, 121, 147,\ + 85, 35, 41, 48, 57, 68, 81, 97, 116, 140, 169,\ + 90, 42, 49, 57, 68, 80, 95, 113, 135, 162, 196,\ + 95, 50, 58, 68, 80, 95, 112, 133, 158, 188, 226,\ + 100, 61, 70, 82, 96, 113, 132, 156, 185, 220, 263,\ + 105, 73, 84, 98, 114, 133, 157, 184, 217, 258, 306,\ + 110, 88, 102, 117, 137, 159, 185, 217, 255, 301, 356,\ + 115, 108, 124, 142, 164, 190, 221, 258, 301, 353, 418,\ + 120, 131, 149, 171, 197, 228, 263, 306, 356, 416, 488}, + + +#define LTE_TABLE_2 \ + /* "(WAT -8.16%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 3, 4, 5, 6, 8, 10, 13, 17, 22, 30,\ + 30, 3, 4, 5, 7, 8, 11, 14, 18, 24, 32,\ + 35, 4, 5, 6, 7, 9, 12, 15, 20, 26, 34,\ + 40, 4, 5, 7, 8, 10, 13, 17, 22, 28, 37,\ + 45, 5, 6, 7, 9, 12, 15, 19, 24, 31, 40,\ + 50, 6, 7, 8, 11, 13, 17, 21, 26, 34, 43,\ + 55, 6, 8, 10, 12, 15, 19, 23, 29, 37, 48,\ + 60, 8, 9, 11, 14, 17, 21, 26, 33, 41, 53,\ + 65, 9, 11, 13, 16, 19, 24, 29, 37, 46, 58,\ + 70, 10, 13, 15, 18, 22, 27, 34, 41, 52, 65,\ + 75, 12, 15, 18, 21, 26, 32, 38, 47, 58, 73,\ + 80, 15, 17, 21, 25, 30, 36, 44, 54, 66, 82,\ + 85, 18, 21, 25, 29, 35, 42, 51, 62, 76, 94,\ + 90, 21, 25, 29, 35, 41, 49, 59, 72, 88, 107,\ + 95, 26, 30, 36, 42, 49, 58, 70, 84, 101, 123,\ + 100, 32, 37, 43, 50, 58, 69, 82, 98, 118, 143,\ + 105, 39, 45, 52, 60, 70, 83, 97, 115, 138, 166,\ + 110, 48, 55, 63, 73, 84, 99, 116, 136, 162, 193,\ + 115, 60, 68, 78, 89, 102, 118, 138, 162, 192, 227,\ + 120, 75, 84, 96, 109, 124, 142, 165, 193, 228, 268}, + +#define VCORE_TABLE_0 \ + /* "(WAT 11.57%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 8, 10, 12, 15, 18, 22, 28, 34, 42, 53,\ + 30, 9, 11, 14, 17, 21, 26, 32, 39, 48, 60,\ + 35, 11, 13, 16, 20, 24, 30, 36, 45, 55, 69,\ + 40, 13, 16, 19, 23, 28, 34, 42, 51, 63, 78,\ + 45, 15, 18, 22, 27, 32, 39, 48, 59, 72, 89,\ + 50, 18, 21, 26, 31, 37, 45, 55, 68, 83, 102,\ + 55, 21, 25, 30, 36, 43, 52, 64, 78, 95, 116,\ + 60, 24, 29, 35, 42, 50, 60, 73, 89, 109, 133,\ + 65, 28, 34, 40, 48, 58, 70, 84, 102, 124, 152,\ + 70, 33, 39, 47, 56, 67, 81, 97, 118, 142, 173,\ + 75, 38, 46, 54, 65, 78, 93, 112, 135, 163, 198,\ + 80, 45, 53, 63, 75, 90, 107, 129, 154, 186, 225,\ + 85, 52, 62, 73, 87, 104, 123, 148, 177, 213, 257,\ + 90, 61, 72, 85, 101, 120, 142, 169, 203, 243, 293,\ + 95, 72, 84, 99, 117, 138, 164, 195, 232, 278, 335,\ + 100, 84, 98, 115, 135, 160, 189, 224, 266, 318, 382,\ + 105, 98, 114, 134, 156, 184, 218, 257, 305, 363, 434,\ + 110, 114, 133, 155, 182, 213, 250, 295, 350, 415, 494,\ + 115, 133, 155, 180, 211, 246, 288, 339, 401, 474, 564,\ + 120, 155, 180, 210, 244, 284, 332, 389, 459, 542, 642}, + +#define VCORE_TABLE_1 \ + /* "(WAT 0.78%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 5, 6, 8, 10, 12, 15, 19, 23, 30, 38,\ + 30, 6, 7, 9, 11, 14, 17, 21, 27, 33, 42,\ + 35, 7, 9, 10, 13, 16, 19, 24, 30, 38, 48,\ + 40, 8, 10, 12, 15, 18, 22, 28, 34, 43, 54,\ + 45, 10, 12, 14, 17, 21, 25, 31, 39, 48, 60,\ + 50, 11, 13, 16, 20, 24, 29, 36, 44, 55, 68,\ + 55, 13, 16, 19, 23, 27, 34, 41, 50, 62, 77,\ + 60, 15, 18, 22, 26, 32, 38, 47, 58, 71, 87,\ + 65, 18, 21, 25, 30, 37, 44, 54, 66, 80, 99,\ + 70, 21, 25, 30, 35, 42, 51, 62, 75, 91, 112,\ + 75, 25, 29, 34, 41, 49, 59, 71, 86, 104, 127,\ + 80, 29, 34, 40, 48, 57, 68, 81, 98, 119, 145,\ + 85, 34, 40, 47, 55, 66, 78, 94, 112, 136, 165,\ + 90, 40, 47, 55, 65, 76, 90, 108, 129, 156, 188,\ + 95, 47, 55, 64, 75, 88, 104, 124, 148, 178, 214,\ + 100, 56, 65, 75, 88, 103, 121, 143, 170, 204, 245,\ + 105, 65, 76, 88, 102, 119, 140, 165, 196, 234, 280,\ + 110, 77, 89, 103, 120, 139, 163, 192, 227, 270, 321,\ + 115, 92, 105, 121, 141, 163, 191, 223, 263, 310, 368,\ + 120, 109, 125, 143, 165, 191, 222, 259, 303, 357, 421}, + +#define VCORE_TABLE_2 \ + /* "(WAT 11.57%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 3, 4, 5, 6, 7, 9, 12, 15, 20, 27,\ + 30, 3, 4, 5, 6, 8, 10, 13, 17, 22, 29,\ + 35, 4, 5, 6, 7, 9, 11, 14, 18, 24, 31,\ + 40, 4, 5, 6, 8, 10, 13, 16, 20, 26, 34,\ + 45, 5, 6, 7, 9, 11, 14, 18, 22, 29, 37,\ + 50, 6, 7, 8, 10, 13, 16, 20, 25, 32, 41,\ + 55, 7, 8, 10, 12, 14, 18, 22, 28, 35, 45,\ + 60, 8, 9, 11, 13, 16, 20, 25, 31, 39, 49,\ + 65, 9, 11, 13, 15, 19, 23, 28, 35, 43, 54,\ + 70, 11, 12, 15, 18, 21, 26, 32, 39, 49, 61,\ + 75, 12, 15, 17, 20, 24, 30, 36, 44, 55, 68,\ + 80, 15, 17, 20, 24, 28, 34, 41, 50, 62, 77,\ + 85, 18, 20, 24, 28, 33, 40, 47, 58, 71, 87,\ + 90, 21, 24, 28, 33, 38, 46, 55, 66, 81, 99,\ + 95, 25, 29, 33, 38, 45, 54, 64, 77, 93, 113,\ + 100, 30, 34, 39, 46, 53, 63, 74, 89, 107, 129,\ + 105, 36, 41, 47, 55, 63, 74, 87, 103, 123, 148,\ + 110, 44, 50, 57, 65, 75, 87, 102, 120, 143, 171,\ + 115, 54, 60, 68, 78, 89, 103, 120, 140, 165, 198,\ + 120, 66, 73, 82, 93, 106, 122, 142, 164, 194, 229}, + +typedef struct spower_raw_s { + int vsize; + int tsize; + int table_size; + int *table[]; +} spower_raw_t; + + +/** table order: ff, tt, ss **/ + +int cpu_leakage_data[][VSIZE * TSIZE + VSIZE + TSIZE] = { + CPU_TABLE_0 + CPU_TABLE_1 + CPU_TABLE_2 +}; + +int lte_leakage_data[][VSIZE * TSIZE + VSIZE + TSIZE] = { + LTE_TABLE_0 + LTE_TABLE_1 + LTE_TABLE_2 +}; + +int vcore_leakage_data[][VSIZE * TSIZE + VSIZE + TSIZE] = { + VCORE_TABLE_0 + VCORE_TABLE_1 + VCORE_TABLE_2 +}; + +spower_raw_t cpu_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = 3, + .table = { + (int *)&cpu_leakage_data[0], (int *)&cpu_leakage_data[1], (int *)&cpu_leakage_data[2]}, +}; + +spower_raw_t lte_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = 3, + .table = { + (int *)<e_leakage_data[0], (int *)<e_leakage_data[1], (int *)<e_leakage_data[2]}, +}; + +spower_raw_t vcore_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = 3, + .table = { + (int *)&vcore_leakage_data[0], (int *)&vcore_leakage_data[1], + (int *)&vcore_leakage_data[2]}, +}; + + + +typedef struct voltage_row_s { + int mV[VSIZE]; +} vrow_t; + +typedef struct temperature_row_s { + int deg; + int mA[VSIZE]; +} trow_t; + + +typedef struct sptab_s { + int vsize; + int tsize; + int *data; /* array[VSIZE + TSIZE + (VSIZE*TSIZE)]; */ + vrow_t *vrow; /* pointer to voltage row of data */ + trow_t *trow; /* pointer to temperature row of data */ +} sptbl_t; + +#define trow(tab, ti) ((tab)->trow[ti]) +#define mA(tab, vi, ti) ((tab)->trow[ti].mA[vi]) +#define mV(tab, vi) ((tab)->vrow[0].mV[vi]) +#define deg(tab, ti) ((tab)->trow[ti].deg) +#define vsize(tab) ((tab)->vsize) +#define tsize(tab) ((tab)->tsize) +#define tab_validate(tab) (!!(tab) && (tab)->data != NULL) + +static inline void spower_tab_construct(sptbl_t(*tab)[], spower_raw_t *raw) +{ + int i; + sptbl_t *ptab = (sptbl_t *) tab; + + for (i = 0; i < raw->table_size; i++) { + ptab->vsize = raw->vsize; + ptab->tsize = raw->tsize; + ptab->data = raw->table[i]; + ptab->vrow = (vrow_t *) ptab->data; + ptab->trow = (trow_t *) (ptab->data + ptab->vsize); + ptab++; + } +} + + + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_spower_data_d3.h b/drivers/misc/mediatek/base/power/mt6755/mt_spower_data_d3.h new file mode 100644 index 0000000000000000000000000000000000000000..07be0cbe99311103b9f96c2d20bf57a60e040091 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_spower_data_d3.h @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef MT_SPOWER_CPU_H +#define MT_SPOWER_CPU_H + + + +#define VSIZE 10 +#define TSIZE 20 +#define MAX_TABLE_SIZE 3 + +#define CPU_TABLE_0 \ + /* "(WAT 8.62%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 29, 37, 47, 59, 74, 93, 116, 145, 180, 224, \ + 30, 34, 43, 54, 68, 86, 107, 134, 167, 208, 257, \ + 35, 39, 50, 63, 79, 99, 124, 155, 192, 238, 294, \ + 40, 46, 58, 73, 92, 115, 143, 178, 220, 273, 337, \ + 45, 53, 67, 84, 106, 132, 164, 204, 252, 312, 384, \ + 50, 62, 78, 97, 122, 152, 188, 233, 288, 355, 437, \ + 55, 71, 89, 112, 140, 174, 215, 266, 328, 404, 497, \ + 60, 82, 103, 129, 160, 199, 246, 303, 374, 459, 563, \ + 65, 94, 118, 148, 184, 227, 280, 344, 424, 522, 639, \ + 70, 108, 136, 169, 209, 258, 319, 392, 481, 591, 722, \ + 75, 124, 155, 193, 239, 294, 362, 445, 545, 666, 813, \ + 80, 143, 177, 220, 272, 334, 411, 505, 617, 753, 917, \ + 85, 163, 202, 250, 309, 380, 466, 570, 696, 846, 1028, \ + 90, 185, 230, 284, 350, 430, 526, 642, 782, 949, 1149, \ + 95, 211, 261, 322, 396, 485, 592, 721, 876, 1061, 1283, \ + 100, 239, 296, 364, 447, 547, 666, 808, 980, 1184, 1430, \ + 105, 271, 334, 410, 502, 613, 745, 904, 1094, 1320, 1590, \ + 110, 306, 376, 461, 563, 684, 831, 1005, 1215, 1464, 1760, \ + 115, 344, 423, 517, 629, 764, 925, 1118, 1348, 1621, 1946, \ + 120, 386, 473, 577, 702, 851, 1029, 1241, 1494, 1793, 2148}, + +#define CPU_TABLE_1 \ + /* "(WAT 1.72%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 13, 16, 20, 24, 30, 37, 46, 57, 70, 85, \ + 30, 15, 18, 23, 28, 35, 43, 53, 65, 80, 98, \ + 35, 17, 21, 26, 33, 40, 49, 61, 74, 91, 111, \ + 40, 20, 24, 30, 37, 46, 57, 70, 85, 104, 127, \ + 45, 23, 28, 35, 43, 53, 65, 80, 98, 119, 145, \ + 50, 26, 33, 40, 50, 61, 75, 92, 111, 135, 165, \ + 55, 30, 38, 46, 57, 70, 86, 104, 127, 154, 188, \ + 60, 35, 43, 53, 66, 80, 98, 119, 145, 176, 213, \ + 65, 40, 50, 61, 75, 92, 112, 136, 165, 200, 242, \ + 70, 47, 57, 70, 86, 105, 128, 155, 188, 228, 276, \ + 75, 54, 66, 81, 99, 120, 146, 177, 214, 259, 314, \ + 80, 62, 75, 92, 113, 137, 167, 202, 245, 295, 356, \ + 85, 71, 87, 106, 129, 157, 190, 230, 278, 335, 403, \ + 90, 81, 99, 121, 148, 179, 217, 261, 315, 378, 454, \ + 95, 93, 113, 139, 168, 204, 246, 297, 356, 427, 511, \ + 100, 106, 130, 158, 192, 232, 279, 336, 403, 482, 576, \ + 105, 122, 148, 180, 218, 263, 317, 380, 455, 543, 648, \ + 110, 139, 169, 206, 248, 298, 358, 428, 511, 610, 729, \ + 115, 158, 192, 233, 280, 336, 402, 480, 573, 687, 817, \ + 120, 180, 218, 263, 316, 380, 455, 544, 648, 772, 916}, + +#define CPU_TABLE_2 \ + /*"(WAT -11.35%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 6, 8, 10, 13, 16, 21, 26, 32, 39, 47, \ + 30, 7, 9, 12, 15, 19, 24, 29, 36, 44, 53, \ + 35, 8, 10, 13, 17, 22, 27, 33, 41, 50, 60, \ + 40, 9, 12, 15, 20, 25, 31, 38, 46, 56, 68, \ + 45, 11, 14, 18, 22, 28, 35, 43, 52, 64, 76, \ + 50, 12, 16, 20, 26, 32, 40, 49, 59, 72, 86, \ + 55, 14, 18, 23, 29, 37, 45, 56, 68, 82, 98, \ + 60, 17, 21, 27, 34, 42, 52, 63, 77, 92, 110, \ + 65, 19, 24, 31, 39, 48, 59, 72, 87, 105, 125, \ + 70, 22, 28, 36, 44, 55, 67, 82, 99, 119, 141, \ + 75, 26, 33, 41, 51, 63, 77, 94, 113, 135, 161, \ + 80, 30, 38, 47, 59, 72, 88, 107, 129, 154, 182, \ + 85, 34, 43, 54, 67, 83, 101, 122, 146, 174, 206, \ + 90, 40, 50, 62, 77, 95, 115, 139, 166, 198, 233, \ + 95, 46, 58, 72, 89, 109, 132, 159, 190, 224, 264, \ + 100, 53, 67, 83, 102, 125, 151, 182, 216, 256, 300, \ + 105, 61, 77, 95, 117, 143, 173, 208, 247, 291, 341, \ + 110, 71, 89, 110, 135, 164, 198, 237, 282, 331, 387, \ + 115, 83, 103, 127, 156, 189, 228, 272, 322, 377, 439, \ + 120, 96, 120, 147, 180, 218, 262, 311, 367, 428, 497}, + +#define LTE_TABLE_0 \ + /* "(WAT 11.57%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 15, 18, 22, 26, 32, 38, 45, 54, 65, 77, \ + 30, 17, 20, 24, 29, 35, 42, 50, 60, 72, 86, \ + 35, 19, 23, 27, 33, 39, 47, 56, 67, 80, 95, \ + 40, 21, 25, 30, 36, 43, 52, 62, 74, 89, 106, \ + 45, 23, 28, 34, 40, 48, 58, 69, 83, 99, 118, \ + 50, 26, 31, 38, 45, 54, 64, 77, 92, 110, 131, \ + 55, 29, 35, 42, 50, 60, 72, 86, 103, 122, 146, \ + 60, 32, 39, 47, 56, 67, 80, 96, 115, 137, 163, \ + 65, 36, 44, 52, 63, 75, 90, 107, 128, 153, 182, \ + 70, 41, 49, 59, 70, 84, 100, 120, 143, 171, 204, \ + 75, 46, 55, 66, 79, 94, 113, 134, 160, 191, 228, \ + 80, 51, 62, 74, 88, 106, 126, 151, 180, 214, 255, \ + 85, 58, 69, 83, 99, 119, 142, 169, 202, 241, 287, \ + 90, 65, 78, 93, 112, 134, 160, 191, 227, 271, 323, \ + 95, 73, 88, 105, 126, 151, 180, 215, 256, 305, 364, \ + 100, 82, 99, 119, 142, 170, 203, 242, 289, 345, 411, \ + 105, 93, 112, 134, 161, 192, 230, 274, 327, 389, 464, \ + 110, 105, 126, 152, 182, 217, 259, 309, 369, 439, 524, \ + 115, 119, 143, 172, 205, 246, 293, 350, 418, 497, 592, \ + 120, 135, 162, 194, 232, 278, 332, 396, 472, 563, 670}, + + +#define LTE_TABLE_1 \ + /* "(WAT 0.78%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 11, 13, 16, 19, 22, 26, 30, 35, 42, 49, \ + 30, 12, 14, 17, 20, 23, 27, 32, 38, 45, 53, \ + 35, 13, 15, 18, 21, 25, 29, 34, 41, 48, 56, \ + 40, 14, 16, 19, 23, 27, 31, 37, 44, 52, 61, \ + 45, 15, 18, 21, 25, 29, 34, 40, 47, 56, 66, \ + 50, 16, 19, 23, 27, 31, 37, 43, 51, 60, 71, \ + 55, 18, 21, 24, 29, 34, 40, 47, 56, 66, 78, \ + 60, 19, 23, 27, 31, 37, 44, 52, 61, 72, 85, \ + 65, 21, 25, 29, 34, 41, 48, 57, 67, 79, 93, \ + 70, 23, 27, 32, 38, 45, 53, 62, 74, 87, 103, \ + 75, 25, 30, 35, 42, 49, 58, 69, 81, 96, 114, \ + 80, 28, 33, 39, 46, 55, 65, 76, 90, 107, 126, \ + 85, 31, 37, 44, 51, 61, 72, 85, 100, 119, 141, \ + 90, 35, 41, 49, 57, 68, 80, 95, 112, 133, 158, \ + 95, 39, 46, 54, 64, 76, 90, 107, 126, 150, 177, \ + 100, 44, 52, 61, 72, 86, 101, 120, 142, 169, 200, \ + 105, 49, 58, 69, 82, 97, 114, 135, 160, 190, 226, \ + 110, 56, 66, 78, 93, 110, 129, 153, 181, 216, 257, \ + 115, 63, 75, 89, 105, 124, 147, 174, 207, 246, 293, \ + 120, 72, 86, 101, 120, 142, 168, 200, 238, 282, 335}, + + +#define LTE_TABLE_2 \ + /* "(WAT -8.16%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 10, 12, 14, 16, 19, 23, 27, 31, 37, 44, \ + 30, 11, 13, 15, 17, 20, 23, 28, 33, 39, 46, \ + 35, 11, 13, 15, 18, 21, 24, 29, 34, 40, 48, \ + 40, 12, 14, 16, 18, 22, 25, 30, 35, 42, 50, \ + 45, 12, 14, 17, 19, 23, 27, 31, 37, 44, 52, \ + 50, 13, 15, 17, 20, 24, 28, 33, 39, 46, 55, \ + 55, 13, 16, 18, 22, 25, 30, 35, 41, 49, 59, \ + 60, 14, 17, 19, 23, 27, 32, 37, 44, 52, 62, \ + 65, 15, 18, 21, 24, 29, 34, 40, 47, 56, 67, \ + 70, 16, 19, 22, 26, 31, 36, 43, 51, 60, 72, \ + 75, 17, 20, 24, 28, 33, 39, 46, 55, 65, 77, \ + 80, 19, 22, 26, 30, 36, 42, 50, 59, 70, 84, \ + 85, 20, 24, 28, 33, 39, 46, 54, 64, 77, 92, \ + 90, 22, 26, 31, 36, 43, 50, 59, 70, 84, 100, \ + 95, 24, 29, 34, 40, 47, 55, 65, 77, 92, 110, \ + 100, 27, 32, 37, 44, 51, 61, 72, 85, 102, 122, \ + 105, 30, 35, 41, 48, 57, 67, 80, 95, 113, 135, \ + 110, 33, 39, 46, 54, 63, 75, 89, 106, 126, 151, \ + 115, 37, 43, 51, 60, 71, 84, 99, 118, 141, 169, \ + 120, 41, 49, 57, 67, 80, 94, 112, 133, 159, 190}, + +#define VCORE_TABLE_0 \ + /* "(WAT 11.57%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 19, 23, 28, 34, 42, 51, 62, 75, 91, 111, \ + 30, 21, 26, 32, 39, 48, 58, 70, 85, 103, 125, \ + 35, 24, 30, 37, 45, 54, 66, 80, 97, 117, 141, \ + 40, 28, 34, 42, 51, 62, 75, 91, 110, 133, 160, \ + 45, 32, 39, 48, 58, 71, 85, 103, 125, 151, 182, \ + 50, 37, 45, 55, 66, 81, 97, 118, 142, 171, 206, \ + 55, 42, 51, 63, 76, 92, 111, 134, 161, 194, 233, \ + 60, 49, 59, 72, 87, 105, 126, 152, 183, 220, 264, \ + 65, 56, 68, 82, 99, 120, 144, 173, 208, 250, 299, \ + 70, 64, 78, 94, 113, 137, 164, 198, 237, 284, 340, \ + 75, 74, 89, 108, 130, 156, 188, 225, 270, 323, 386, \ + 80, 85, 103, 124, 149, 180, 215, 258, 308, 368, 440, \ + 85, 98, 118, 142, 171, 206, 247, 295, 352, 420, 500, \ + 90, 113, 136, 164, 197, 236, 282, 336, 401, 477, 568, \ + 95, 130, 156, 188, 225, 269, 322, 383, 457, 544, 645, \ + 100, 149, 180, 215, 258, 308, 368, 438, 522, 619, 735, \ + 105, 172, 207, 248, 297, 354, 422, 502, 596, 707, 839, \ + 110, 199, 238, 285, 340, 405, 482, 573, 680, 806, 954, \ + 115, 230, 275, 329, 392, 466, 554, 657, 778, 921, 1087, \ + 120, 265, 317, 378, 450, 535, 635, 752, 890, 1052, 1241}, + +#define VCORE_TABLE_1 \ + /* "(WAT 0.78%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 12, 15, 18, 21, 25, 30, 36, 44, 52, 63, \ + 30, 13, 16, 19, 23, 28, 33, 40, 48, 57, 69, \ + 35, 15, 18, 21, 26, 31, 37, 44, 53, 63, 76, \ + 40, 16, 20, 24, 28, 34, 41, 49, 58, 70, 83, \ + 45, 18, 22, 26, 32, 38, 45, 54, 65, 77, 92, \ + 50, 21, 25, 29, 35, 42, 50, 60, 72, 86, 103, \ + 55, 23, 28, 33, 39, 47, 56, 67, 80, 96, 115, \ + 60, 26, 31, 37, 44, 53, 63, 75, 90, 107, 128, \ + 65, 29, 35, 42, 50, 60, 71, 85, 101, 120, 144, \ + 70, 33, 40, 47, 57, 67, 80, 96, 114, 136, 162, \ + 75, 38, 45, 54, 64, 77, 91, 109, 129, 154, 184, \ + 80, 44, 52, 62, 74, 88, 104, 124, 147, 176, 209, \ + 85, 50, 60, 71, 85, 101, 120, 142, 169, 201, 239, \ + 90, 58, 69, 82, 97, 116, 138, 163, 194, 231, 274, \ + 95, 67, 80, 95, 113, 134, 159, 189, 224, 267, 317, \ + 100, 78, 93, 110, 131, 155, 184, 219, 260, 309, 367, \ + 105, 91, 108, 128, 152, 180, 214, 254, 301, 358, 424, \ + 110, 107, 127, 150, 178, 210, 249, 295, 349, 415, 493, \ + 115, 125, 149, 176, 208, 246, 291, 345, 409, 484, 573, \ + 120, 148, 176, 208, 246, 291, 344, 407, 481, 568, 672}, + +#define VCORE_TABLE_2 \ + /* "(WAT 11.57%) Leakage Power" */ \ + {800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, \ + 25, 6, 8, 11, 15, 20, 26, 32, 38, 44, 49, \ + 30, 6, 8, 12, 16, 21, 27, 34, 40, 46, 52, \ + 35, 6, 9, 13, 17, 23, 29, 36, 43, 49, 55, \ + 40, 6, 9, 13, 18, 24, 31, 38, 46, 53, 59, \ + 45, 7, 10, 14, 20, 26, 33, 41, 49, 57, 64, \ + 50, 7, 11, 15, 21, 28, 36, 44, 53, 61, 69, \ + 55, 8, 12, 16, 23, 30, 39, 48, 57, 67, 75, \ + 60, 8, 13, 18, 25, 33, 42, 52, 63, 73, 82, \ + 65, 9, 14, 19, 27, 36, 46, 57, 69, 80, 91, \ + 70, 10, 15, 21, 29, 39, 50, 63, 76, 89, 101, \ + 75, 11, 16, 23, 32, 43, 56, 70, 85, 99, 112, \ + 80, 12, 18, 26, 36, 48, 62, 78, 95, 111, 126, \ + 85, 13, 20, 29, 40, 54, 70, 87, 106, 125, 142, \ + 90, 15, 22, 32, 45, 60, 78, 98, 120, 141, 161, \ + 95, 17, 25, 36, 50, 68, 88, 111, 136, 160, 183, \ + 100, 19, 28, 41, 57, 77, 100, 127, 155, 183, 209, \ + 105, 21, 32, 46, 65, 88, 115, 145, 177, 209, 240, \ + 110, 24, 37, 53, 74, 101, 132, 167, 205, 242, 278, \ + 115, 28, 42, 61, 85, 116, 152, 194, 238, 282, 324, \ + 120, 32, 49, 70, 99, 135, 177, 225, 277, 329, 378}, + +typedef struct spower_raw_s { + int vsize; + int tsize; + int table_size; + int *table[]; +} spower_raw_t; + + +/** table order: ff, tt, ss **/ + +int cpu_leakage_data[][VSIZE * TSIZE + VSIZE + TSIZE] = { + CPU_TABLE_0 + CPU_TABLE_1 + CPU_TABLE_2 +}; + +int lte_leakage_data[][VSIZE * TSIZE + VSIZE + TSIZE] = { + LTE_TABLE_0 + LTE_TABLE_1 + LTE_TABLE_2 +}; + +int vcore_leakage_data[][VSIZE * TSIZE + VSIZE + TSIZE] = { + VCORE_TABLE_0 + VCORE_TABLE_1 + VCORE_TABLE_2 +}; + +spower_raw_t cpu_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = 3, + .table = { + (int *)&cpu_leakage_data[0], (int *)&cpu_leakage_data[1], + (int *)&cpu_leakage_data[2]}, +}; + +spower_raw_t lte_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = 3, + .table = { + (int *)<e_leakage_data[0], (int *)<e_leakage_data[1], + (int *)<e_leakage_data[2]}, +}; + +spower_raw_t vcore_spower_raw = { + .vsize = VSIZE, + .tsize = TSIZE, + .table_size = 3, + .table = { + (int *)&vcore_leakage_data[0], (int *)&vcore_leakage_data[1], + (int *)&vcore_leakage_data[2]}, +}; + + + +typedef struct voltage_row_s { + int mV[VSIZE]; +} vrow_t; + +typedef struct temperature_row_s { + int deg; + int mA[VSIZE]; +} trow_t; + + +typedef struct sptab_s { + int vsize; + int tsize; + int *data; /* array[VSIZE + TSIZE + (VSIZE*TSIZE)]; */ + vrow_t *vrow; /* pointer to voltage row of data */ + trow_t *trow; /* pointer to temperature row of data */ +} sptbl_t; + +#define trow(tab, ti) ((tab)->trow[ti]) +#define mA(tab, vi, ti) ((tab)->trow[ti].mA[vi]) +#define mV(tab, vi) ((tab)->vrow[0].mV[vi]) +#define deg(tab, ti) ((tab)->trow[ti].deg) +#define vsize(tab) ((tab)->vsize) +#define tsize(tab) ((tab)->tsize) +#define tab_validate(tab) (!!(tab) && (tab)->data != NULL) + +static inline void spower_tab_construct(sptbl_t(*tab)[], spower_raw_t *raw) +{ + int i; + sptbl_t *ptab = (sptbl_t *) tab; + + for (i = 0; i < raw->table_size; i++) { + ptab->vsize = raw->vsize; + ptab->tsize = raw->tsize; + ptab->data = raw->table[i]; + ptab->vrow = (vrow_t *) ptab->data; + ptab->trow = (trow_t *) (ptab->data + ptab->vsize); + ptab++; + } +} + + + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_static_power.c b/drivers/misc/mediatek/base/power/mt6755/mt_static_power.c new file mode 100644 index 0000000000000000000000000000000000000000..91ec0601bdbd69ffbb4a32550eb97430c35f9da8 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_static_power.c @@ -0,0 +1,534 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#if defined(__KERNEL__) /* || !defined(__CTP__) */ + #include + #include +#endif /* #if !defined(__CTP__) */ + +/* #include */ +#include "mt_spower_data.h" +#include "mt_static_power.h" + +/********************************* + * macro for log + **********************************/ +#define SP_TAG "[Power/spower] " +#define SPOWER_LOG_NONE 0 +#define SPOWER_LOG_WITH_PRINTK 1 + +/* #define SPOWER_LOG_PRINT SPOWER_LOG_WITH_PRINTK */ +#define SPOWER_LOG_PRINT SPOWER_LOG_NONE + +#if (SPOWER_LOG_PRINT == SPOWER_LOG_NONE) +#define SPOWER_INFO(fmt, args...) +#elif (SPOWER_LOG_PRINT == SPOWER_LOG_WITH_PRINTK) +/* printk("[Power/spower] "fmt, ##args) */ +#define SPOWER_INFO(fmt, args...) pr_err(SP_TAG fmt, ##args) +#endif + + + +static sptbl_t sptab[MT_SPOWER_MAX]; /* CPU, VCORE, GPU, VMD1, MODEM, VMODEM_SRAM */ + +/**************************************************************** + * this table is generated by scramble function. * + * (plz refer to DE team.) * + ****************************************************************/ +int devinfo_table[] = { + 3539, 492, 1038, 106, 231, 17, 46, 2179, + 4, 481, 1014, 103, 225, 17, 45, 2129, + 3, 516, 1087, 111, 242, 19, 49, 2282, + 4, 504, 1063, 108, 236, 18, 47, 2230, + 4, 448, 946, 96, 210, 15, 41, 1986, + 2, 438, 924, 93, 205, 14, 40, 1941, + 2, 470, 991, 101, 220, 16, 43, 2080, + 3, 459, 968, 98, 215, 16, 42, 2033, + 3, 594, 1250, 129, 279, 23, 57, 2621, + 6, 580, 1221, 126, 273, 22, 56, 2561, + 6, 622, 1309, 136, 293, 24, 60, 2745, + 7, 608, 1279, 132, 286, 23, 59, 2683, + 6, 541, 1139, 117, 254, 20, 51, 2390, + 5, 528, 1113, 114, 248, 19, 50, 2335, + 4, 566, 1193, 123, 266, 21, 54, 2503, + 5, 553, 1166, 120, 260, 21, 53, 2446, + 5, 338, 715, 70, 157, 9, 29, 1505, + 3153, 330, 699, 69, 153, 9, 28, 1470, + 3081, 354, 750, 74, 165, 10, 31, 1576, + 3302, 346, 732, 72, 161, 10, 30, 1540, + 3227, 307, 652, 63, 142, 8, 26, 1371, + 2875, 300, 637, 62, 139, 7, 25, 1340, + 2809, 322, 683, 67, 149, 8, 27, 1436, + 3011, 315, 667, 65, 146, 8, 26, 1404, + 2942, 408, 862, 86, 191, 13, 37, 1811, + 1, 398, 842, 84, 186, 12, 36, 1769, + 1, 428, 903, 91, 200, 14, 39, 1896, + 2, 418, 882, 89, 195, 13, 38, 1853, + 2, 371, 785, 78, 173, 11, 33, 1651, + 3458, 363, 767, 76, 169, 10, 32, 1613, + 3379, 389, 823, 82, 182, 12, 35, 1729, + 1, 380, 804, 80, 177, 11, 34, 1689, +}; + + +int interpolate(int x1, int x2, int x3, int y1, int y2) +{ + /* BUG_ON(x1 == x2); */ + if (x1 == x2) + return (y1+y2)/2; + + return (x3-x1) * (y2-y1) / (x2 - x1) + y1; +} + +int interpolate_2d(sptbl_t *tab, int v1, int v2, int t1, int t2, int voltage, int degree) +{ + int c1, c2, p1, p2, p; + + if ((v1 == v2) && (t1 == t2)) { + p = mA(tab, v1, t1); + return p; + } else if (v1 == v2) { + c1 = mA(tab, v1, t1); + c2 = mA(tab, v1, t2); + p = interpolate(deg(tab, t1), deg(tab, t2), degree, c1, c2); + return p; + } else if (t1 == t2) { + c1 = mA(tab, v1, t1); + c2 = mA(tab, v2, t1); + p = interpolate(mV(tab, v1), mV(tab, v2), voltage, c1, c2); + return p; + } else { + c1 = mA(tab, v1, t1); + c2 = mA(tab, v1, t2); + p1 = interpolate(deg(tab, t1), deg(tab, t2), degree, c1, c2); + + c1 = mA(tab, v2, t1); + c2 = mA(tab, v2, t2); + p2 = interpolate(deg(tab, t1), deg(tab, t2), degree, c1, c2); + + p = interpolate(mV(tab, v1), mV(tab, v2), voltage, p1, p2); + return p; + } +} +/* c1, c2, c3(EFUSE) => make sptab 239, 53, 100 */ +void interpolate_table(sptbl_t *spt, int c1, int c2, int c3, sptbl_t *tab1, sptbl_t *tab2) +{ + int v, t; + + /* avoid divid error, if we have bad raw data table */ + if (unlikely(c1 == c2)) { + *spt = *tab1; + SPOWER_INFO("sptab equal to tab1:%d/%d\n", c1, c3); + return; + } + + SPOWER_INFO("make sptab %d, %d, %d\n", c1, c2, c3); + for (t = 0; t < tsize(spt); t++) { + for (v = 0; v < vsize(spt); v++) { + int *p = &mA(spt, v, t); + p[0] = interpolate(c1, c2, c3, + mA(tab1, v, t), + mA(tab2, v, t)); + + SPOWER_INFO("%d ", p[0]); + } + SPOWER_INFO("\n"); + } + SPOWER_INFO("make sptab done!\n"); + + return; +} + + +int sptab_lookup(sptbl_t *tab, int voltage, int degree) +{ + int x1, x2, y1, y2, i; + int mamper; + + /** lookup voltage **/ + for (i = 0; i < vsize(tab); i++) { + if (voltage <= mV(tab, i)) + break; + } + + if (unlikely(voltage == mV(tab, i))) { + x1 = x2 = i; + } else if (unlikely(i == vsize(tab))) { + x1 = vsize(tab)-2; + x2 = vsize(tab)-1; + } else if (i == 0) { + x1 = 0; + x2 = 1; + } else { + x1 = i-1; + x2 = i; + } + + + /** lookup degree **/ + for (i = 0; i < tsize(tab); i++) { + if (degree <= deg(tab, i)) + break; + } + + if (unlikely(degree == deg(tab, i))) { + y1 = y2 = i; + } else if (unlikely(i == tsize(tab))) { + y1 = tsize(tab)-2; + y2 = tsize(tab)-1; + } else if (i == 0) { + y1 = 0; + y2 = 1; + } else { + y1 = i-1; + y2 = i; + } + + mamper = interpolate_2d(tab, x1, x2, y1, y2, voltage, degree); + + return mamper; +} + + +int mt_spower_make_table(sptbl_t *spt, spower_raw_t *spower_raw, int wat, int voltage, int degree) +{ + int i; + int c1, c2, c = -1; + sptbl_t tab[MAX_TABLE_SIZE], *tab1, *tab2, *tspt; + + /** FIXME, test only; please read efuse to assign. **/ + /* wat = 80; */ + /* voltage = 1150; */ + /* degree = 30; */ + + BUG_ON(spower_raw->table_size < MAX_TABLE_SIZE); + + /** structurize the raw data **/ + spower_tab_construct(&tab, spower_raw); + + /** lookup tables which the chip type locates to **/ + for (i = 0; i < spower_raw->table_size; i++) { + c = sptab_lookup(&tab[i], voltage, degree); + /** table order: ff, tt, ss **/ + if (wat >= c) + break; + } + + /** FIXME, + * There are only 2 tables are used to interpolate to form SPTAB. + * Thus, sptab takes use of the container which raw data is not used anymore. + **/ + if (wat == c) { + /** just match **/ + tab1 = tab2 = &tab[i]; + /** pointer duplicate **/ + tspt = tab1; + SPOWER_INFO("sptab equal to tab:%d/%d\n", wat, c); + } else if (i == spower_raw->table_size) { + /** above all **/ + #if defined(EXTER_POLATION) + tab1 = &tab[spower_raw->table_size-2]; + tab2 = &tab[spower_raw->table_size-1]; + + /** occupy the free container**/ + tspt = &tab[spower_raw->table_size-3]; + #else /* #if defined(EXTER_POLATION) */ + tspt = tab1 = tab2 = &tab[spower_raw->table_size-1]; + #endif /* #if defined(EXTER_POLATION) */ + + SPOWER_INFO("sptab max tab:%d/%d\n", wat, c); + } else if (i == 0) { +#if defined(EXTER_POLATION) + /** below all **/ + tab1 = &tab[0]; + tab2 = &tab[1]; + + /** occupy the free container**/ + tspt = &tab[2]; +#else /* #if defined(EXTER_POLATION) */ + tspt = tab1 = tab2 = &tab[0]; +#endif /* #if defined(EXTER_POLATION) */ + + SPOWER_INFO("sptab min tab:%d/%d\n", wat, c); + } else { + /** anyone **/ + tab1 = &tab[i-1]; + tab2 = &tab[i]; + + /** occupy the free container**/ + tspt = &tab[(i+1)%spower_raw->table_size]; + + SPOWER_INFO("sptab interpolate tab:%d/%d\n", wat, c); + } + + + /** sptab needs to interpolate 2 tables. **/ + if (tab1 != tab2) { + c1 = sptab_lookup(tab1, voltage, degree); + c2 = sptab_lookup(tab2, voltage, degree); + + interpolate_table(tspt, c1, c2, wat, tab1, tab2); + } + + /** update to global data **/ + *spt = *tspt; + + return 0; +} + + + + +/* #define MT_SPOWER_UT 0 */ + +#if defined(MT_SPOWER_UT) +void mt_spower_ut(void) +{ + int v, t, p, i; + + for (i = 0; i < MT_SPOWER_MAX; i++) { + sptbl_t *spt = &sptab[i]; + switch (i) { + case MT_SPOWER_CPU: + SPOWER_INFO("[SPOWER] - This is MT_SPOWER_CPU\n"); + break; + case MT_SPOWER_VCORE: + SPOWER_INFO("[SPOWER] - This is MT_SPOWER_VCORE\n"); + break; + case MT_SPOWER_GPU: + SPOWER_INFO("[SPOWER] - This is MT_SPOWER_GPU\n"); + break; + case MT_SPOWER_VMD1: + SPOWER_INFO("[SPOWER] - This is MT_SPOWER_VMD1\n"); + break; + case MT_SPOWER_MODEM: + SPOWER_INFO("[SPOWER] - This is MT_SPOWER_MODEM\n"); + break; + case MT_SPOWER_VMODEM_SRAM: + SPOWER_INFO("[SPOWER] - This is MT_SPOWER_VMODEM_SRAM\n"); + break; + default: + break; + } + + v = 750; + t = 22; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 750; + t = 25; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 750; + t = 28; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 750; + t = 82; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 750; + t = 120; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 820; + t = 22; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 820; + t = 25; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 820; + t = 28; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 820; + t = 82; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 820; + t = 120; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 1200; + t = 22; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 1200; + t = 25; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 1200; + t = 28; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 1200; + t = 82; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + + v = 1200; + t = 120; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + + v = 950; + t = 80; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + v = 1000; + t = 85; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + + + v = 1150; + t = 105; + p = sptab_lookup(spt, v, t); + SPOWER_INFO("v/t/p: %d/%d/%d\n", v, t, p); + switch (i) { + case MT_SPOWER_CPU: + SPOWER_INFO("[SPOWER] - MT_SPOWER_CPU Done\n"); + break; + case MT_SPOWER_VCORE: + SPOWER_INFO("[SPOWER] - MT_SPOWER_VCORE Done\n"); + break; + case MT_SPOWER_GPU: + SPOWER_INFO("[SPOWER] - MT_SPOWER_GPU Done\n"); + break; + case MT_SPOWER_VMD1: + SPOWER_INFO("[SPOWER] - MT_SPOWER_VMD1 Done\n"); + break; + case MT_SPOWER_MODEM: + SPOWER_INFO("[SPOWER] - MT_SPOWER_MODEM Done\n"); + break; + case MT_SPOWER_VMODEM_SRAM: + SPOWER_INFO("[SPOWER] - MT_SPOWER_VMODEM_SRAM Done\n"); + break; + default: + break; + } + } +} +#endif /* #if defined(MT_SPOWER_UT) */ +static unsigned int mtSpowerInited; +int mt_spower_init(void) +{ + #define DEVINFO_IDX0 (18) + #define DEVINFO_IDX1 (19) + + int devinfo = 0, devinfo_1 = 0; + int cpu, vcore, gpu, vmd1, modem, vmodem_sram; + + if (1 == mtSpowerInited) + return 0; + + /* avoid side effect from multiple invocation */ + if (tab_validate(&sptab[MT_SPOWER_CPU])) + return 0; + + devinfo = (int)get_devinfo_with_index(DEVINFO_IDX0); /* ptp_read(0xF0206274); M_SRM_RP5 */ + cpu = (devinfo >> 24) & 0x0ff; + vcore = (devinfo >> 16) & 0x0ff; + gpu = (devinfo >> 8) & 0x0ff; + vmd1 = (devinfo) & 0x0ff; + devinfo_1 = (int)get_devinfo_with_index(DEVINFO_IDX1); /* ptp_read(0xF0206278); M_SRM_RP6 */ + modem = (devinfo >> 24) & 0x0ff; + vmodem_sram = (devinfo >> 16) & 0x0ff; + SPOWER_INFO("[SPOWER] - cpu/vcore/gpu/vmd1/modem/vmodem_sram => 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n", + cpu, vcore, gpu, vmd1, modem, vmodem_sram); + + if ((devinfo != 0) && (devinfo_1 != 0)) { + cpu = (int)devinfo_table[cpu]; + vcore = (int)devinfo_table[vcore]; + gpu = (int)devinfo_table[gpu]; + vmd1 = (int)devinfo_table[vmd1]; + modem = (int)devinfo_table[modem]; + vmodem_sram = (int)devinfo_table[vmodem_sram]; + SPOWER_INFO("[SPOWER] - cpu/vcore/gpu/vmd1/modem/vmodem_sram => 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n", + cpu, vcore, gpu, vmd1, modem, vmodem_sram); + + cpu = (int)(cpu*1150/1000); + vcore = (int)(vcore*1150/1000); + gpu = (int)(gpu*1150/1000); + vmd1 = (int)(vmd1*1150/1000); + modem = (int)(modem*1150/1000); + vmodem_sram = (int)(vmodem_sram*1150/1000); + } else { + cpu = 100; + vcore = 100; + gpu = 100; + vmd1 = 162; + modem = 300; + vmodem_sram = 300; + } + + SPOWER_INFO("[SPOWER] - cpu/vcore/gpu/vmd1/modem/vmodem_sram => %d/%d/%d/%d/%d/%d\n", + cpu, vcore, gpu, vmd1, modem, vmodem_sram); + SPOWER_INFO("[SPOWER] - MT_SPOWER_CPU\n"); + mt_spower_make_table(&sptab[MT_SPOWER_CPU], &cpu_spower_raw, cpu, 1150, 30); + SPOWER_INFO("[SPOWER] - MT_SPOWER_VCORE\n"); + mt_spower_make_table(&sptab[MT_SPOWER_VCORE], &vcore_spower_raw, vcore, 1150, 30); + SPOWER_INFO("[SPOWER] - MT_SPOWER_GPU\n"); + mt_spower_make_table(&sptab[MT_SPOWER_GPU], &gpu_spower_raw, gpu, 1150, 30); + SPOWER_INFO("[SPOWER] - MT_SPOWER_VMD1\n"); + mt_spower_make_table(&sptab[MT_SPOWER_VMD1], &vmd1_spower_raw, vmd1, 1150, 30); + SPOWER_INFO("[SPOWER] - MT_SPOWER_MODEM\n"); + mt_spower_make_table(&sptab[MT_SPOWER_MODEM], &modem_spower_raw, modem, 1150, 30); + SPOWER_INFO("[SPOWER] - MT_SPOWER_VMODEM_SRAM\n"); + mt_spower_make_table(&sptab[MT_SPOWER_VMODEM_SRAM], &vmodem_sram_spower_raw, vmodem_sram, 1150, 30); + /* mt_spower_make_table(&sptab[MT_SPOWER_VCORE], &vcore_spower_raw, vcore, 1150, 30); */ + + SPOWER_INFO("[SPOWER] - Start SPOWER UT!\n"); + #if defined(MT_SPOWER_UT) + mt_spower_ut(); + #endif + SPOWER_INFO("[SPOWER] - End SPOWER UT!\n"); + + mtSpowerInited = 1; + return 0; +} + +late_initcall(mt_spower_init); + + +/** return 0, means sptab is not yet ready. **/ +int mt_spower_get_leakage(int dev, int vol, int deg) +{ + BUG_ON(!(dev < MT_SPOWER_MAX)); + + if (!tab_validate(&sptab[dev])) + return 0; + + return sptab_lookup(&sptab[dev], vol, deg); +} +EXPORT_SYMBOL(mt_spower_get_leakage); diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_static_power.h b/drivers/misc/mediatek/base/power/mt6755/mt_static_power.h new file mode 100644 index 0000000000000000000000000000000000000000..d3fa232aa25a395e6bfc919460ba2a3196a46683 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_static_power.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef MT_STATIC_POWER_H +#define MT_STATIC_POWER_H + + +enum { + MT_SPOWER_CPU = 0, + MT_SPOWER_VCORE, + MT_SPOWER_GPU, + MT_SPOWER_VMD1, + MT_SPOWER_MODEM, + MT_SPOWER_VMODEM_SRAM, + MT_SPOWER_MAX, +}; + +extern u32 get_devinfo_with_index(u32 index); + +/** + * @argument + * dev: the enum of MT_SPOWER_xxx + * voltage: the operating voltage, mV. + * degree: the Tj. (degree C) + * @return + * -1, means sptab is not yet ready. + * other value: the mW of leakage value. + **/ +extern int mt_spower_get_leakage(int dev, int voltage, int degree); +extern int mt_spower_init(void); + + +#endif diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_governor.c b/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_governor.c new file mode 100644 index 0000000000000000000000000000000000000000..4fa730aa68272684a859e1b8e1650d65b9891599 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_governor.c @@ -0,0 +1,1544 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include "mt_vcorefs_manager.h" +#include "mt_spm_vcore_dvfs.h" +#include "mt_spm_pmic_wrap.h" + +#include "mt_ptp.h" +#include "mt_dramc.h" +#include "mt-plat/upmu_common.h" +#include "mt-plat/mt_pmic_wrap.h" +#include "mt_spm.h" +#include "mmdvfs_mgr.h" +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "mt-plat/aee.h" + +__weak int emmc_autok(void) +{ + return 0; +} + +__weak int sd_autok(void) +{ + return 0; +} + +__weak int sdio_autok(void) +{ + return 0; +} + +__weak void mmdvfs_enable(int enable) +{ + +} + +/* + * PMIC + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#define PMIC_VCORE_ADDR PMIC_BUCK_VCORE_VOSEL_ON_ADDR +#else +#define PMIC_VCORE_ADDR MT6351_PMIC_BUCK_VCORE_VOSEL_ON_ADDR +#endif +#define VCORE_BASE_UV 600000 +#define VCORE_STEP_UV 6250 + +#define VCORE_INVALID 0x80 + +#define vcore_uv_to_pmic(uv) /* pmic >= uv */ \ + ((((uv) - VCORE_BASE_UV) + (VCORE_STEP_UV - 1)) / VCORE_STEP_UV) + +#define vcore_pmic_to_uv(pmic) \ + (((pmic) * VCORE_STEP_UV) + VCORE_BASE_UV) + +/* + * sram debug info + */ +void __iomem *vcorefs_sram_base; +u32 spm_vcorefs_err_irq = 154; +/* unsigned int vcorefs_log_mask = ~((0xFFFFFFFF << LAST_KICKER)); */ +/* default filter-out GPU message */ +unsigned int vcorefs_log_mask = ~((0xFFFFFFFF << LAST_KICKER) | (1U << KIR_GPU)); +/* + * HD segment size + */ +#define DISP_LCM_HD_SIZE (1280 * 800) + +#define VCOREFS_SEGMENT_HPM_LPM 1 +#define VCOREFS_SEGMENT_LPM 2 +#define VCOREFS_SEGMENT_LPM_EXCEPT_OVL 3 + +/* + * product segment + */ +#define MT6750_TURBO_SEGMENT 0x41 +#define MT6750_NORMAL_SEGMENT 0x42 +#define MT6738_SEGMENT 0x43 +#define MT6750_TURBO_5M_SEGMENT 0x45 +#define MT6750_NORMAL_5M_SEGMENT 0x46 +#define MT6738_5M_SEGMENT 0x4B + +/* + * struct define + */ +static DEFINE_MUTEX(governor_mutex); + +struct governor_profile { + bool vcore_dvfs_en; + bool vcore_dvs; + bool ddr_dfs; + bool isr_debug; + + bool is_fhd_segment; + + int boot_up_opp; + int late_init_opp; + + int curr_vcore_uv; + int curr_ddr_khz; + + u32 autok_kir_group; + u32 active_autok_kir; + + u32 cpu_dvfs_req; + + u32 log_mask; + u32 segment_code; + u32 segment_policy; + + u32 total_bw_lpm_threshold; + u32 total_bw_hpm_threshold; + u32 perform_bw_lpm_threshold; + u32 perform_bw_hpm_threshold; + bool total_bw_enable; + bool perform_bw_enable; +}; + +static struct governor_profile governor_ctrl = { + .vcore_dvfs_en = 1, /* vcore dvfs feature enable */ + .vcore_dvs = 1, + .ddr_dfs = 1, + .isr_debug = 0, + + .is_fhd_segment = true, + .cpu_dvfs_req = (1 << MD_CAT6_CA_DATALINK | (1 << MD_Position)), + .boot_up_opp = OPPI_PERF, /* boot up with HPM */ + .late_init_opp = OPPI_LOW_PWR, /* late init change to LPM mode */ + + .autok_kir_group = ((1 << KIR_AUTOK_EMMC) | (1 << KIR_AUTOK_SDIO) | (1 << KIR_AUTOK_SD)), + .active_autok_kir = 0, + + .curr_vcore_uv = VCORE_1_P_00_UV, + .curr_ddr_khz = FDDR_S1_KHZ, + + .total_bw_enable = false, + .perform_bw_enable = false, +}; + +static struct opp_profile opp_table[] __nosavedata = { + /* performance mode */ + [OPP_0] = { + .vcore_uv = VCORE_1_P_00_UV, + .ddr_khz = FDDR_S0_KHZ, + }, + /* low power mode */ + [OPP_1] = { + .vcore_uv = VCORE_0_P_90_UV, + .ddr_khz = FDDR_S1_KHZ, + } +}; + +int kicker_table[LAST_KICKER]; + +int gpu_kicker_init_opp = OPPI_LOW_PWR; + +int vcorefs_gpu_get_init_opp(void) +{ + return gpu_kicker_init_opp; +} + +void vcorefs_gpu_set_init_opp(int opp) +{ + vcorefs_info("gpu_set_init_opp(%d)\n", opp); + gpu_kicker_init_opp = opp; +} + +bool vcorefs_request_init_opp(int kicker, int opp) +{ + bool accept = false; + + mutex_lock(&governor_mutex); + if (kicker == KIR_GPU) { + gpu_kicker_init_opp = opp; + vcorefs_debug_mask(kicker, "init_opp request(kr:%d, opp:%d)\n", kicker, opp); + accept = true; + } + mutex_unlock(&governor_mutex); + return accept; +} + +static char *kicker_name[] = { + "KIR_MM_16MCAM", + "KIR_MM_WFD", + "KIR_MM_MHL", + "KIR_OVL", + "KIR_SDIO", + "KIR_PERF", + "KIR_SYSFS", + "KIR_SYSFS_N", + "KIR_GPU", + "NUM_KICKER", + "KIR_LATE_INIT", + "KIR_SYSFSX", + "KIR_AUTOK_EMMC", + "KIR_AUTOK_SDIO", + "KIR_AUTOK_SD", + "LAST_KICKER", +}; + +static unsigned int trans[NUM_TRANS] __nosavedata; + +struct timing_debug_profile { + u32 dvfs_latency_spec; + u32 long_hpm_latency_count; + u32 long_lpm_latency_count; + u32 long_emi_block_time_count; + u32 max_hpm_latency; + u32 max_lpm_latency; + u32 max_emi_block_time; +}; + +static struct timing_debug_profile timing_debug_ctrl = { + .dvfs_latency_spec = 32, /* 1T@32K, about 210us for hpm,lpm latency, max allow 1ms */ + .long_hpm_latency_count = 0, + .long_lpm_latency_count = 0, + .long_emi_block_time_count = 0, /* 1T@26M */ + .max_hpm_latency = 0, + .max_lpm_latency = 0, + .max_emi_block_time = 0, +}; + +void vcorefs_set_log_mask(u32 value) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + gvrctrl->log_mask = value; + vcorefs_log_mask = value; +} +/* + * Unit Test API + */ +void vcorefs_set_cpu_dvfs_req(u32 value) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + u32 mask = 0xFFFF; + + mutex_lock(&governor_mutex); + gvrctrl->cpu_dvfs_req = (value & mask); + spm_vcorefs_set_cpu_dvfs_req(value, mask); + mutex_unlock(&governor_mutex); +} + +unsigned int vcorefs_get_cpu_dvfs_req(void) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + return gvrctrl->cpu_dvfs_req; +} + +static void update_vcore_pwrap_cmd(struct opp_profile *opp_ctrl_table) +{ + u32 diff; + + diff = opp_ctrl_table[OPPI_PERF].vcore_uv - opp_ctrl_table[OPPI_LOW_PWR].vcore_uv; + trans[TRANS1] = opp_ctrl_table[OPPI_LOW_PWR].vcore_uv + (diff / 3) * 1; + trans[TRANS2] = opp_ctrl_table[OPPI_LOW_PWR].vcore_uv + (diff / 3) * 2; + + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_NORMAL, IDX_NM_VCORE_HPM, + vcore_uv_to_pmic(opp_ctrl_table[OPPI_PERF].vcore_uv)); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_NORMAL, IDX_NM_VCORE_TRANS2, + vcore_uv_to_pmic(trans[TRANS2])); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_NORMAL, IDX_NM_VCORE_TRANS1, + vcore_uv_to_pmic(trans[TRANS1])); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_NORMAL, IDX_NM_VCORE_LPM, + vcore_uv_to_pmic(opp_ctrl_table[OPPI_LOW_PWR].vcore_uv)); + + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_SUSPEND, IDX_SP_VCORE_HPM, + vcore_uv_to_pmic(opp_ctrl_table[OPPI_PERF].vcore_uv)); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_SUSPEND, IDX_SP_VCORE_TRANS2, + vcore_uv_to_pmic(trans[TRANS2])); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_SUSPEND, IDX_SP_VCORE_TRANS1, + vcore_uv_to_pmic(trans[TRANS1])); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_SUSPEND, IDX_SP_VCORE_LPM, + vcore_uv_to_pmic(opp_ctrl_table[OPPI_LOW_PWR].vcore_uv)); + + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, IDX_DI_VCORE_HPM, + vcore_uv_to_pmic(opp_ctrl_table[OPPI_PERF].vcore_uv)); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, IDX_DI_VCORE_TRANS2, + vcore_uv_to_pmic(trans[TRANS2])); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, IDX_DI_VCORE_TRANS1, + vcore_uv_to_pmic(trans[TRANS1])); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, IDX_DI_VCORE_LPM, + vcore_uv_to_pmic(opp_ctrl_table[OPPI_LOW_PWR].vcore_uv)); + + vcorefs_info("HPM : %u (0x%x)\n", opp_ctrl_table[OPPI_PERF].vcore_uv, + vcore_uv_to_pmic(opp_ctrl_table[OPPI_PERF].vcore_uv)); + vcorefs_info("TRANS2: %u (0x%x)\n", trans[TRANS2], vcore_uv_to_pmic(trans[TRANS2])); + vcorefs_info("TRANS1: %u (0x%x)\n", trans[TRANS1], vcore_uv_to_pmic(trans[TRANS1])); + vcorefs_info("LPM : %u (0x%x)\n", opp_ctrl_table[OPPI_LOW_PWR].vcore_uv, + vcore_uv_to_pmic(opp_ctrl_table[OPPI_LOW_PWR].vcore_uv)); +} + +static int is_fhd_segment(void) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + return gvrctrl->is_fhd_segment; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void vcorefs_early_suspend_cb(struct early_suspend *h) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + if (gvrctrl->cpu_dvfs_req & MD_DISABLE_SCREEN_CHANGE) + return; + + if (is_fhd_segment()) + spm_vcorefs_set_cpu_dvfs_req(0, gvrctrl->cpu_dvfs_req); /* set screen OFF state */ +} + +static void vcorefs_late_resume_cb(struct early_suspend *h) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + if (gvrctrl->cpu_dvfs_req & MD_DISABLE_SCREEN_CHANGE) + return; + + if (is_fhd_segment()) + spm_vcorefs_set_cpu_dvfs_req(0xFFFF, gvrctrl->cpu_dvfs_req); /* set screen ON state */ +} + +static struct early_suspend vcorefs_earlysuspend_desc = { + .level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 50, + .suspend = vcorefs_early_suspend_cb, /* after mtkfb_early_suspend */ + .resume = vcorefs_late_resume_cb, /* before mtkfb_late_resume */ +}; +#else +static struct notifier_block vcorefs_fb_notif; +static int +vcorefs_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *fb_evdata) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + struct fb_event *evdata = fb_evdata; + int blank; + + if (gvrctrl->cpu_dvfs_req & MD_DISABLE_SCREEN_CHANGE) + return 0; + + /* skip if not fhd segment */ + if (is_fhd_segment() == false) + return 0; + + /* skip non-interested event immediately */ + if (event != FB_EVENT_BLANK && event != FB_EARLY_EVENT_BLANK) + return 0; + + blank = *(int *)evdata->data; + vcorefs_debug("fb_notify event=%lu blank=%d\n", event, blank); + if ((blank == FB_BLANK_POWERDOWN) && (event == FB_EVENT_BLANK)) { + vcorefs_info("Switch to Screen-OFF\n"); + spm_vcorefs_set_cpu_dvfs_req(0, gvrctrl->cpu_dvfs_req); /* set screen OFF state */ + } else if ((blank == FB_BLANK_UNBLANK) && (event == FB_EARLY_EVENT_BLANK)) { + vcorefs_info("Switch to Screen-ON\n"); + spm_vcorefs_set_cpu_dvfs_req(0xFFFF, gvrctrl->cpu_dvfs_req); /* set screen ON state */ + } + return 0; +} + +#endif +/* + * sram debug info + */ +static u32 sram_debug_info[7]; +char *vcorefs_get_sram_debug_info(char *p) +{ + if (p) { + p += sprintf(p, "dvs/dfs up_count : 0x%x / 0x%x\n", + spm_read(VCOREFS_SRAM_DVS_UP_COUNT), + spm_read(VCOREFS_SRAM_DFS_UP_COUNT)); + p += sprintf(p, "dvs/dfs down_count: 0x%x / 0x%x\n", + spm_read(VCOREFS_SRAM_DVS_DOWN_COUNT), + spm_read(VCOREFS_SRAM_DFS_DOWN_COUNT)); + p += sprintf(p, "dvfs_up_latency : 0x%x\n", + spm_read(VCOREFS_SRAM_DVFS_UP_LATENCY)); + p += sprintf(p, "dvfs_down_latency : 0x%x\n", + spm_read(VCOREFS_SRAM_DVFS_DOWN_LATENCY)); + p += sprintf(p, "dvfs_latency_spec : 0x%x\n", + spm_read(VCOREFS_SRAM_DVFS_LATENCY_SPEC)); + p += sprintf(p, "\n"); + } else { + sram_debug_info[0] = spm_read(VCOREFS_SRAM_DVS_UP_COUNT); + sram_debug_info[1] = spm_read(VCOREFS_SRAM_DFS_UP_COUNT); + sram_debug_info[2] = spm_read(VCOREFS_SRAM_DVS_DOWN_COUNT); + sram_debug_info[3] = spm_read(VCOREFS_SRAM_DFS_DOWN_COUNT); + sram_debug_info[4] = spm_read(VCOREFS_SRAM_DVFS_UP_LATENCY); + sram_debug_info[5] = spm_read(VCOREFS_SRAM_DVFS_DOWN_LATENCY); + sram_debug_info[6] = spm_read(VCOREFS_SRAM_DVFS_LATENCY_SPEC); + vcorefs_info("dvs_up_count : 0x%x\n", sram_debug_info[0]); + vcorefs_info("dfs_up_count : 0x%x\n", sram_debug_info[1]); + vcorefs_info("dvs_down_count : 0x%x\n", sram_debug_info[2]); + vcorefs_info("dfs_down_count : 0x%x\n", sram_debug_info[3]); + vcorefs_info("dvfs_up_latency : 0x%x\n", sram_debug_info[4]); + vcorefs_info("dvfs_down_latency: 0x%x\n", sram_debug_info[5]); + vcorefs_info("dvfs_latency spec: 0x%x\n", sram_debug_info[6]); + } + + return p; +} + +static void vcorefs_init_sram_debug(void) +{ + int i; + struct timing_debug_profile *dbg_ctrl = &timing_debug_ctrl; + + if (!vcorefs_sram_base) { + vcorefs_err("vcorefs_sram_base is not valid\n"); + return; + } + + for (i = 0; i < 21; i++) + vcorefs_set_sram_data(i, 0); + +#if 1 + vcorefs_get_sram_debug_info(NULL); +#endif + vcorefs_info("clean debug sram info\n"); + spm_write(VCOREFS_SRAM_DVS_UP_COUNT, 0); + spm_write(VCOREFS_SRAM_DFS_UP_COUNT, 0); + spm_write(VCOREFS_SRAM_DVS_DOWN_COUNT, 0); + spm_write(VCOREFS_SRAM_DFS_DOWN_COUNT, 0); + spm_write(VCOREFS_SRAM_DVFS_UP_LATENCY, 0); + spm_write(VCOREFS_SRAM_DVFS_DOWN_LATENCY, 0); + spm_write(VCOREFS_SRAM_DVFS_LATENCY_SPEC, dbg_ctrl->dvfs_latency_spec); + vcorefs_info("dvfs_latency spec set to 0x%x\n", spm_read(VCOREFS_SRAM_DVFS_LATENCY_SPEC)); +} + +void vcorefs_set_sram_data(int index, u32 data) +{ + spm_write(VCOREFS_SRAM_BASE + index * 4, data); +} + +u32 vcorefs_get_sram_data(int index) +{ + return spm_read(VCOREFS_SRAM_BASE + index * 4); +} + +void vcorefs_set_dvfs_latency_spec(u32 value) +{ + struct timing_debug_profile *dbg_ctrl = &timing_debug_ctrl; + + dbg_ctrl->dvfs_latency_spec = value; + spm_write(VCOREFS_SRAM_DVFS_LATENCY_SPEC, value); +} + +static irqreturn_t spm_vcorefs_err_handler(int irq, void *dev_id) +{ + u32 hpm_latency, lpm_latency; + int pll_mode; + struct timing_debug_profile *dbg_ctrl = &timing_debug_ctrl; + + hpm_latency = spm_read(VCOREFS_SRAM_DVFS_UP_LATENCY); + lpm_latency = spm_read(VCOREFS_SRAM_DVFS_DOWN_LATENCY); + pll_mode = spm_vcorefs_get_clk_mem_pll(); + +#if 0 + u32 assert_pc, block_time; + /* debug only with special FW */ + assert_pc = spm_read(PCM_REG_DATA_INI); + block_time = spm_read(SPM_SW_RSV_0); + vcorefs_err("r6: 0x%x r15:0x%x\n", spm_read(PCM_REG6_DATA), spm_read(PCM_REG15_DATA)); + if ((assert_pc != 0) && (block_time != 0)) { + dbg_ctrl->long_emi_block_time_count++; + if (block_time > dbg_ctrl->max_emi_block_time) + dbg_ctrl->max_emi_block_time = block_time; + vcorefs_err("see long emi block time: %d (cnt=%d)\n", block_time, + dbg_ctrl->long_emi_block_time_count); + } +#endif + + if (pll_mode == 0) { + if (((lpm_latency & 0xffff0000) == 0) + && (lpm_latency > dbg_ctrl->dvfs_latency_spec)) { + dbg_ctrl->long_lpm_latency_count++; + if (lpm_latency > dbg_ctrl->max_lpm_latency) + dbg_ctrl->max_lpm_latency = lpm_latency; + vcorefs_err("see long lpm latency: %d (cnt=%d)\n", lpm_latency, + dbg_ctrl->long_lpm_latency_count); + } else if ((hpm_latency & 0xffff0000) == 0) { + dbg_ctrl->long_hpm_latency_count++; + if (hpm_latency > dbg_ctrl->max_hpm_latency) + dbg_ctrl->max_hpm_latency = hpm_latency; + vcorefs_err("see long* hpm latency: %d (cnt=%d)\n", hpm_latency, + dbg_ctrl->long_hpm_latency_count); + } + } else if (pll_mode == 1) { + if (((hpm_latency & 0xffff0000) == 0) + && (hpm_latency > dbg_ctrl->dvfs_latency_spec)) { + dbg_ctrl->long_hpm_latency_count++; + if (hpm_latency > dbg_ctrl->max_hpm_latency) + dbg_ctrl->max_hpm_latency = hpm_latency; + vcorefs_err("see long hpm latency: %d (cnt=%d)\n", hpm_latency, + dbg_ctrl->long_hpm_latency_count); + } else if ((lpm_latency & 0xffff0000) == 0) { + dbg_ctrl->long_lpm_latency_count++; + if (lpm_latency > dbg_ctrl->max_lpm_latency) + dbg_ctrl->max_lpm_latency = lpm_latency; + vcorefs_err("see long* lpm latency: %d (cnt=%d)\n", lpm_latency, + dbg_ctrl->long_lpm_latency_count); + } + } + mt_eint_virq_soft_clr(irq); + + return IRQ_HANDLED; +} + +uint32_t get_vcore_dvfs_sram_debug_regs(uint32_t index) +{ + uint32_t value = 0; + + switch (index) { + case 0: + value = 7; + vcorefs_err("get vcore dvfs sram debug regs count = 0x%.8x\n", value); + break; + case 1: + value = sram_debug_info[0]; + vcorefs_err("DVS UP COUNT(0x%x) = 0x%x\n", index, value); + break; + case 2: + value = sram_debug_info[1]; + vcorefs_err("VFS UP COUNT(0x%x) = 0x%x\n", index, value); + break; + case 3: + value = sram_debug_info[2]; + vcorefs_err("DVS DOWN COUNT(0x%x) = 0x%x\n", index, value); + break; + case 4: + value = sram_debug_info[3]; + vcorefs_err("DFS DOWN COUNT(0x%x) = 0x%x\n", index, value); + break; + case 5: + value = sram_debug_info[4]; + vcorefs_err("DVFS UP LATENCY(0x%x) = 0x%x\n", index, value); + break; + case 6: + value = sram_debug_info[5]; + vcorefs_err("DVFS DOWN LATENCY(0x%x) = 0x%x\n", index, value); + break; + case 7: + value = sram_debug_info[6]; + vcorefs_err("DVFS DOWN LATENCY(0x%x) = 0x%x\n", index, value); + break; + } + + return value; +} +EXPORT_SYMBOL(get_vcore_dvfs_sram_debug_regs); + +/* + * Governor extern API + */ +bool is_vcorefs_feature_enable(void) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + if (!dram_can_support_fh()) { + gvrctrl->vcore_dvfs_en = false; + vcorefs_err("DISABLE DVFS DUE TO NOT SUPPORT DRAM FH\n"); + } + + return gvrctrl->vcore_dvfs_en; +} + +int vcorefs_get_num_opp(void) +{ + return NUM_OPP; /* for ATE script */ +} + +int vcorefs_get_curr_vcore(void) +{ + int vcore = VCORE_INVALID; + + pwrap_read(PMIC_VCORE_ADDR, &vcore); + if (vcore >= VCORE_INVALID) + pwrap_read(PMIC_VCORE_ADDR, &vcore); + + return vcore < VCORE_INVALID ? vcore_pmic_to_uv(vcore) : 0; +} + +int vcorefs_get_curr_ddr(void) +{ + int ddr_khz; + + ddr_khz = get_dram_data_rate() * 1000; + + return ddr_khz; +} + +int vcorefs_get_vcore_by_steps(u32 steps) +{ + int uv = 0; + + switch (steps) { + case OPP_0: + uv = vcore_pmic_to_uv(get_vcore_ptp_volt(VCORE_1_P_00_UV)); + break; + case OPP_1: + uv = vcore_pmic_to_uv(get_vcore_ptp_volt(VCORE_0_P_90_UV)); + break; + default: + break; + } + + return uv; +} + +int vcorefs_get_ddr_by_steps(u32 steps) +{ + int ddr_khz; + /*FIXME: wait dram_steps_freq */ + ddr_khz = dram_steps_freq(steps) * 1000; + + BUG_ON(ddr_khz < 0); + + return ddr_khz; +} + +char *vcorefs_get_dvfs_info(char *p) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + struct timing_debug_profile *dbg_ctrl = &timing_debug_ctrl; + + int uv = vcorefs_get_curr_vcore(); + + p += sprintf(p, "[vcore_dvfs ]: %d\n", gvrctrl->vcore_dvfs_en); + p += sprintf(p, "[vcore_dvs ]: %d\n", gvrctrl->vcore_dvs); + p += sprintf(p, "[ddr_dfs ]: %d\n", gvrctrl->ddr_dfs); + p += sprintf(p, "[isr_debug ]: %d\n", gvrctrl->isr_debug); + p += sprintf(p, "[fhd_segment ]: %d\n", gvrctrl->is_fhd_segment); + p += sprintf(p, "[cpu_dvfs_req]: 0x%x\n", vcorefs_get_cpu_dvfs_req()); + p += sprintf(p, "[log_mask ]: 0x%x\n", gvrctrl->log_mask); + p += sprintf(p, "[segment_code]: 0x%x\n", gvrctrl->segment_code); + p += sprintf(p, "[segment_policy]: 0x%x\n", gvrctrl->segment_policy); + p += sprintf(p, "\n"); + + p += sprintf(p, "[vcore] uv : %u (0x%x)\n", uv, vcore_uv_to_pmic(uv)); + p += sprintf(p, "[ddr ] khz: %u\n", vcorefs_get_curr_ddr()); + p += sprintf(p, "\n"); + + p += sprintf(p, "[perform_bw ]: en = %d, lpm_thres = 0x%x, hpm_thres =0x%x\n", + gvrctrl->perform_bw_enable, gvrctrl->perform_bw_lpm_threshold, + gvrctrl->perform_bw_hpm_threshold); + p += sprintf(p, "[total_bw ]: en = %d, lpm_thres = 0x%x, hpm_thres =0x%x\n", + gvrctrl->total_bw_enable, gvrctrl->total_bw_lpm_threshold, + gvrctrl->total_bw_hpm_threshold); + p += sprintf(p, "\n"); + p = vcorefs_get_sram_debug_info(p); + p += sprintf(p, "[dvfs_latency_spec]: count=%d\n", dbg_ctrl->dvfs_latency_spec); + p += sprintf(p, "[hpm_latency* ]: count=0x%x ,max=%d\n", + dbg_ctrl->long_hpm_latency_count, dbg_ctrl->max_hpm_latency); + p += sprintf(p, "[lpm_latency* ]: count=0x%x ,max=%d\n", + dbg_ctrl->long_lpm_latency_count, dbg_ctrl->max_lpm_latency); + /* + p += sprintf(p, "[emi_block_time* ]: count=0x%x ,max=%d\n", + dbg_ctrl->long_emi_block_time_count, dbg_ctrl->max_emi_block_time); + */ + return p; +} + +char *get_kicker_name(int id) +{ + return kicker_name[id]; +} + +char *vcorefs_get_opp_table_info(char *p) +{ + struct opp_profile *opp_ctrl_table = opp_table; + struct governor_profile *gvrctrl = &governor_ctrl; + int i; + + if (gvrctrl->segment_policy == VCOREFS_SEGMENT_LPM) { + i = OPPI_LOW_PWR; + p += sprintf(p, "[OPP_%d] vcore_uv: %u (0x%x)\n", i, opp_ctrl_table[i].vcore_uv, + vcore_uv_to_pmic(opp_ctrl_table[i].vcore_uv)); + p += sprintf(p, "[OPP_%d] ddr_khz: %u\n", i, opp_ctrl_table[i].ddr_khz); + p += sprintf(p, "\n"); + } else { + for (i = 0; i < NUM_OPP; i++) { + p += sprintf(p, "[OPP_%d] vcore_uv: %u (0x%x)\n", i, opp_ctrl_table[i].vcore_uv, + vcore_uv_to_pmic(opp_ctrl_table[i].vcore_uv)); + p += sprintf(p, "[OPP_%d] ddr_khz: %u\n", i, opp_ctrl_table[i].ddr_khz); + p += sprintf(p, "\n"); + } + + for (i = 0; i < NUM_TRANS; i++) + p += sprintf(p, "[TRANS%d] vcore_uv: %u (0x%x)\n", i + 1, trans[i], + vcore_uv_to_pmic(trans[i])); + } + return p; +} + +/* set opp_table vcore */ +void vcorefs_update_opp_table(char *cmd, int val) +{ + struct opp_profile *opp_ctrl_table = opp_table; + struct governor_profile *gvrctrl = &governor_ctrl; + int uv = vcore_pmic_to_uv(val); + + if (gvrctrl->segment_policy == VCOREFS_SEGMENT_LPM) { + vcorefs_err("segment policy is LPM only not allow opp_table cmd\n"); + return; + } + + if (!strcmp(cmd, "HPM") && val < VCORE_INVALID) { + if (uv >= opp_ctrl_table[OPPI_LOW_PWR].vcore_uv) { + opp_ctrl_table[OPPI_PERF].vcore_uv = uv; + update_vcore_pwrap_cmd(opp_ctrl_table); + } + } else if (!strcmp(cmd, "LPM") && val < VCORE_INVALID) { + if (uv <= opp_ctrl_table[OPPI_PERF].vcore_uv) { + opp_ctrl_table[OPPI_LOW_PWR].vcore_uv = uv; + update_vcore_pwrap_cmd(opp_ctrl_table); + } + } +} + +int vcorefs_output_kicker_id(char *name) +{ + int i; + + for (i = 0; i < NUM_KICKER; i++) { + if (!strcmp(kicker_name[i], name)) + return i; + } + return -1; +} + +int vcorefs_set_total_bw_threshold(u32 lpm_threshold, u32 hpm_threshold) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + if ((lpm_threshold < 1) | (lpm_threshold > 127) + || (hpm_threshold < 1) | (lpm_threshold > 127)) + return -1; + + gvrctrl->total_bw_lpm_threshold = lpm_threshold; + gvrctrl->total_bw_hpm_threshold = hpm_threshold; + + mutex_lock(&governor_mutex); + + spm_vcorefs_set_total_bw_threshold(lpm_threshold, hpm_threshold); + + mutex_unlock(&governor_mutex); + return 0; +} + +int vcorefs_set_perform_bw_threshold(u32 lpm_threshold, u32 hpm_threshold) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + if ((lpm_threshold < 1) | (lpm_threshold > 127) + || (hpm_threshold < 1) | (hpm_threshold > 127)) + return -1; + + gvrctrl->perform_bw_lpm_threshold = lpm_threshold; + gvrctrl->perform_bw_hpm_threshold = hpm_threshold; + + mutex_lock(&governor_mutex); + + spm_vcorefs_set_perform_bw_threshold(lpm_threshold, hpm_threshold); + + mutex_unlock(&governor_mutex); + return 0; +} + +int vcorefs_release_hpm(int opp, int vcore, int ddr) +{ + int r = -1; + + if (opp == OPPI_LOW_PWR) { + r = spm_vcorefs_set_dvfs_hpm_force(OPPI_LOW_PWR, vcore, ddr); + r = spm_vcorefs_set_dvfs_hpm(OPPI_LOW_PWR, vcore, ddr); + } else { + /* FIXME: */ + /* r = spm_vcorefs_set_dvfs_hpm_force(OPPI_LOW_PWR, 0); */ + BUG(); + } + return r; +} + +int vcorefs_handle_kir_sysfsx_req(int opp, int vcore, int ddr) +{ + int r = -1; + + vcorefs_info("hh: vcorefs_handle_kir_sysfsx_req(%d, v:%d, f:%d)\n", opp, vcore, ddr); + if (opp == OPPI_PERF) + r = spm_vcorefs_set_dvfs_hpm_force(OPPI_PERF, vcore, ddr); + else if (opp == OPPI_LOW_PWR) + r = spm_vcorefs_set_dvfs_lpm_force(OPPI_LOW_PWR, vcore, ddr); + else if (opp == OPPI_UNREQ) { + r = spm_vcorefs_set_dvfs_hpm_force(OPPI_LOW_PWR, vcore, ddr); + r = spm_vcorefs_set_dvfs_lpm_force(OPPI_PERF, vcore, ddr); + } + return r; +} + +void vcorefs_reload_spm_firmware(int flag) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + mutex_lock(&governor_mutex); + + if ((flag & SPM_FLAG_DIS_VCORE_DVS) != 0) + gvrctrl->vcore_dvs = 0; + else + gvrctrl->vcore_dvs = 1; + + if ((flag & SPM_FLAG_DIS_VCORE_DFS) != 0) + gvrctrl->ddr_dfs = 0; + else + gvrctrl->ddr_dfs = 1; + vcorefs_info(" re-kick vcore dvfs FW (vcore_dvs=%d ddr_dfs=%d)\n", gvrctrl->vcore_dvs, + gvrctrl->ddr_dfs); + spm_go_to_vcore_dvfs(flag, 0); + + mutex_unlock(&governor_mutex); +} + +int governor_debug_store(const char *buf) +{ + int val, val2, r = 0; + char cmd[32]; + struct governor_profile *gvrctrl = &governor_ctrl; + + if (sscanf(buf, "%31s 0x%x 0x%x", cmd, &val, &val2) == 3 || + sscanf(buf, "%31s %d %d", cmd, &val, &val2) == 3) { + vcorefs_info("governor_debug: cmd: %s, val: %d(0x%x), val2: %d(0x%x)\n", cmd, val, + val, val2, val2); + + if (!strcmp(cmd, "perform_bw_threshold")) { + /* val1: lpm_threshold, + val2: hpm_threshold */ + vcorefs_set_perform_bw_threshold(val, val2); + } + if (!strcmp(cmd, "total_bw_threshold")) { + /* val1: lpm_threshold, + val2: hpm_threshold */ + vcorefs_set_total_bw_threshold(val, val2); + } else { + r = -EPERM; + } + } else if (sscanf(buf, "%31s 0x%x", cmd, &val) == 2 || + sscanf(buf, "%31s %d", cmd, &val) == 2) { + vcorefs_info("governor_debug: cmd: %s, val: %d(0x%x)\n", cmd, val, val); + if (gvrctrl->segment_policy == VCOREFS_SEGMENT_LPM) + vcorefs_err("segment policy is LPM only not allow vcore_debug cmd\n"); + else if (!strcmp(cmd, "vcore_dvs")) + vcorefs_enable_dvs(val); + else if (!strcmp(cmd, "ddr_dfs")) + vcorefs_enable_dfs(val); + else if (!strcmp(cmd, "isr_debug")) + vcorefs_enable_debug_isr(val); + else if (!strcmp(cmd, "cpu_dvfs_req")) + vcorefs_set_cpu_dvfs_req(val); + else if (!strcmp(cmd, "load_spm")) + vcorefs_reload_spm_firmware(val); + else if (!strcmp(cmd, "dvfs_latency_spec")) + vcorefs_set_dvfs_latency_spec(val); + else if (!strcmp(cmd, "log_mask")) + vcorefs_set_log_mask(val); + else + r = -EPERM; + } else { + r = -EPERM; + } + + return r; +} + +/* + * sub-main function + */ +struct dvfs_func { + int (*do_dvfs)(int, int, int); /* requested opp, vcore, ddr */ + u32 kicker_mask; + char *purpose; +}; + +static struct dvfs_func spm_dvfs_func_list[] = { + {spm_vcorefs_set_dvfs_hpm_force, + (1 << KIR_MM_16MCAM | 1 << KIR_SDIO | 1 << KIR_SYSFS | 1 << KIR_PERF | 1 << KIR_OVL | 1 << KIR_GPU), + "set hpm_force"}, + {spm_vcorefs_set_dvfs_hpm, (1 << KIR_MM_WFD | 1 << KIR_MM_MHL | 1 << KIR_SYSFS_N), + "set hpm"}, + {vcorefs_release_hpm, (1 << KIR_LATE_INIT), "clear hpm_lpm_forced"}, + {vcorefs_handle_kir_sysfsx_req, + (1 << KIR_SYSFSX | (1 << KIR_AUTOK_EMMC | 1 << KIR_AUTOK_SDIO | 1 << KIR_AUTOK_SD)), + "set hpm_lpm_force"}, +}; + +int find_spm_dvfs_func_group(int kicker) +{ + int i; + int id = -1; + int total = sizeof(spm_dvfs_func_list) / sizeof(spm_dvfs_func_list[0]); + + for (i = 0; i < total; i++) { + if (spm_dvfs_func_list[i].kicker_mask & (1 << kicker)) { + id = i; + break; + } + } + return id; +} + +int get_kicker_group_opp(int kicker, int group_id) +{ + u32 group_kickers; + int id = -1; + int i, result_opp = (NUM_OPP - 1); /* the lowest power mode, OPP_1 */ + int total = sizeof(spm_dvfs_func_list) / sizeof(spm_dvfs_func_list[0]); + + if (group_id < 0) + id = find_spm_dvfs_func_group(kicker); + else + id = group_id; + + if (id < 0 || id >= total) { + vcorefs_err("Invalid group id(%d), return default opp(%d)\n", id, result_opp); + return result_opp; + } + + group_kickers = spm_dvfs_func_list[id].kicker_mask; + for (i = 0; i < NUM_KICKER; i++) { + if ((group_kickers & 1 << i) != 0) { + if (kicker_table[i] < 0) + continue; + if (kicker_table[i] < result_opp) + result_opp = kicker_table[i]; + } + } + return result_opp; +} + + +static int set_dvfs_with_opp(struct governor_profile *gvrctrl, struct kicker_config *krconf, + struct opp_profile *opp_ctrl_table) +{ + int ret = 0; + int group_id = -1; + int expect_vcore_uv; + int expect_ddr_khz; + int opp_idx; + + /* find spm func group by kicker type */ + group_id = find_spm_dvfs_func_group(krconf->kicker); + + if (group_id < 0) { + vcorefs_err("not find spm func for %s kicker\n", get_kicker_name(krconf->kicker)); + return -1; + } + if (krconf->kicker < NUM_KICKER) { + /* check with history_opp_table to decide the real request opp (dvfs_opp) */ + krconf->dvfs_opp = get_kicker_group_opp(krconf->kicker, group_id); + } + + /* struct opp_profile *opp_ctrl_table = opp_table; */ + gvrctrl->curr_vcore_uv = vcorefs_get_curr_vcore(); + gvrctrl->curr_ddr_khz = vcorefs_get_curr_ddr(); + + if (krconf->dvfs_opp < 0) + opp_idx = (NUM_OPP - 1); + else + opp_idx = krconf->dvfs_opp; + + if (gvrctrl->vcore_dvs == 1) + expect_vcore_uv = opp_ctrl_table[opp_idx].vcore_uv; + else + expect_vcore_uv = gvrctrl->curr_vcore_uv; + + if (gvrctrl->ddr_dfs == 1) + expect_ddr_khz = opp_ctrl_table[opp_idx].ddr_khz; + else + expect_ddr_khz = gvrctrl->curr_ddr_khz; + + vcorefs_debug_mask(krconf->kicker, "opp: %d, vcore: %d(%d), fddr: %d(%d)\n", + krconf->dvfs_opp, + expect_vcore_uv, gvrctrl->curr_vcore_uv, + expect_ddr_khz, gvrctrl->curr_ddr_khz); + + vcorefs_debug_mask(krconf->kicker, "[%d]%s, opp: %d\n", group_id, spm_dvfs_func_list[group_id].purpose, + krconf->dvfs_opp); + + /* call spm with dvfs_opp */ + ret = + spm_dvfs_func_list[group_id].do_dvfs(krconf->dvfs_opp, + opp_ctrl_table[opp_idx].vcore_uv, + opp_ctrl_table[opp_idx].ddr_khz); + + /* update curr_vcore_uv and curr_ddr_khz */ + gvrctrl->curr_vcore_uv = opp_ctrl_table[opp_idx].vcore_uv; + gvrctrl->curr_ddr_khz = opp_ctrl_table[opp_idx].ddr_khz; + + return ret; + +} + +static int do_dvfs_for_performance(struct kicker_config *krconf) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + struct opp_profile *opp_ctrl_table = opp_table; + + return set_dvfs_with_opp(gvrctrl, krconf, opp_ctrl_table); +} + +static int do_dvfs_for_low_power(struct kicker_config *krconf) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + struct opp_profile *opp_ctrl_table = opp_table; + + return set_dvfs_with_opp(gvrctrl, krconf, opp_ctrl_table); +} + +/* + * main function + */ +int kick_dvfs_by_opp_index(struct kicker_config *krconf) +{ + int r = 0; + + if (krconf->opp == OPPI_PERF) + r = do_dvfs_for_performance(krconf); + else + r = do_dvfs_for_low_power(krconf); + + vcorefs_debug_mask(krconf->kicker, "kick_dvfs_by_opp_index done, r: %d\n", r); + + return r; +} + +/* + * init vcorefs function + */ +int vcorefs_late_init_dvfs(void) +{ + struct kicker_config krconf; + struct governor_profile *gvrctrl = &governor_ctrl; + struct opp_profile *opp_ctrl_table = opp_table; + bool plat_init_done = true; + int plat_init_opp; + int disp_w, disp_h; + int uv; + u32 mask = 0; + + vcorefs_info("disp_virtual(w:%d, h:%d) disp(w:%d, h:%d)\n", + primary_display_get_virtual_width(), primary_display_get_virtual_height(), + primary_display_get_width(), primary_display_get_height()); + + disp_w = primary_display_get_virtual_width(); + disp_h = primary_display_get_virtual_height(); + if (disp_w == 0) + disp_w = primary_display_get_width(); + if (disp_h == 0) + disp_h = primary_display_get_height(); + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (disp_w * disp_h <= DISP_LCM_HD_SIZE) { + gvrctrl->is_fhd_segment = false; + gvrctrl->cpu_dvfs_req = 0; + } +#else +#if 0 /* apply FHD policy for MD-CA */ + if (disp_w * disp_h <= DISP_LCM_HD_SIZE) { + gvrctrl->is_fhd_segment = false; + gvrctrl->cpu_dvfs_req = 0; + } else { + gvrctrl->is_fhd_segment = true; + gvrctrl->cpu_dvfs_req = (1 << MD_CAT6_CA_DATALINK | (1 << MD_Position)); + } +#endif +#endif + + /* update boot_up_opp */ + uv = vcorefs_get_curr_vcore(); + if (opp_ctrl_table[OPPI_PERF].vcore_uv == uv) + gvrctrl->boot_up_opp = OPPI_PERF; + else + gvrctrl->boot_up_opp = OPPI_LOW_PWR; + vcorefs_info("curr uv=%d boot_up_opp=%d\n", uv, gvrctrl->boot_up_opp); + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* mt6750 series */ + if (gvrctrl->segment_code == MT6750_NORMAL_SEGMENT || + gvrctrl->segment_code == MT6750_NORMAL_5M_SEGMENT || + gvrctrl->segment_code == MT6738_5M_SEGMENT || + gvrctrl->segment_code == MT6738_SEGMENT) { + if (gvrctrl->is_fhd_segment == true) { + if (spm_read(SPM_POWER_ON_VAL0) & (1 << 14)) { + gvrctrl->segment_policy = VCOREFS_SEGMENT_LPM; + gvrctrl->vcore_dvfs_en = false; + vcorefs_err("disable vcore_dvfs for DRAMC only K LPM(reg=0x%x) by seg=0x%x\n", + spm_read(SPM_POWER_ON_VAL0), gvrctrl->segment_code); + } else { + gvrctrl->segment_policy = VCOREFS_SEGMENT_LPM_EXCEPT_OVL; + } + } else { + gvrctrl->segment_policy = VCOREFS_SEGMENT_LPM; + gvrctrl->vcore_dvfs_en = false; + } + } else { + gvrctrl->segment_policy = VCOREFS_SEGMENT_HPM_LPM; + } +#else + gvrctrl->segment_policy = VCOREFS_SEGMENT_HPM_LPM; + +#endif + vcorefs_info("segment=0x%x policy=%d vcore_dvfs_en=%d\n", + gvrctrl->segment_code, gvrctrl->segment_policy, gvrctrl->vcore_dvfs_en); + if (gvrctrl->segment_policy == VCOREFS_SEGMENT_LPM) { + gvrctrl->vcore_dvfs_en = false; + vcorefs_info("vcore dvfs disable. segment(0x%x) boot_up_opp=%d\n", + gvrctrl->segment_code, gvrctrl->boot_up_opp); + if (!(spm_read(SPM_POWER_ON_VAL0) & (1 << 14))) { + vcorefs_err("boot ddr freq is not expected as LPM (seg=0x%x)\n", gvrctrl->segment_code); + aee_kernel_exception_api(__FILE__, __LINE__, + DB_OPT_DEFAULT, "BOOT_DRAMC", "BOOT DDR Freq Not Expected"); + } + if (gvrctrl->boot_up_opp != OPPI_LOW_PWR) { + vcorefs_err("boot vcore is not expected as LPM (seg=0x%x)\n", gvrctrl->segment_code); + aee_kernel_exception_api(__FILE__, __LINE__, + DB_OPT_DEFAULT, "BOOT_PMIC", "BOOT VCORE Not Expected"); + } + } else if (gvrctrl->segment_policy == VCOREFS_SEGMENT_LPM_EXCEPT_OVL) { + disable_cg_fliper(); /* disable c+g fliper */ + mmdvfs_enable(0); /* disable mm dvfs */ + gvrctrl->cpu_dvfs_req = 0; /* disable MD request */ + /* only allow OVL kicker and GPU kicker */ + mask = (1U << NUM_KICKER) - 1 - (1U << KIR_OVL) - (1U << KIR_GPU); + vcorefs_info("fake HD segment, adjust kr_mask=0x%x\n", mask); + vcorefs_set_kr_req_mask(mask); + } + + spm_vcorefs_set_cpu_dvfs_req(gvrctrl->cpu_dvfs_req, 0xFFFF); + + vcorefs_init_sram_debug(); + + if (!is_vcorefs_feature_enable()) + vcorefs_info("vcore_dvfs_en=%d\n", gvrctrl->vcore_dvfs_en); + + /* SPM_SW_RSV_5[0] init in spm module init */ + /* spm_vcorefs_set_opp_state(gvrctrl->boot_up_opp); */ + if (gvrctrl->vcore_dvfs_en == true) + spm_go_to_vcore_dvfs(SPM_FLAG_RUN_COMMON_SCENARIO, gvrctrl->boot_up_opp); + else + spm_go_to_vcore_dvfs(SPM_FLAG_RUN_COMMON_SCENARIO | SPM_FLAG_DIS_VCORE_DVS | + SPM_FLAG_DIS_VCORE_DFS, gvrctrl->boot_up_opp); + + mutex_lock(&governor_mutex); + + /* SPM_SW_RSV_5[0] need init first time */ + /* spm_vcorefs_set_opp_state(gvrctrl->boot_up_opp); */ + /* spm_go_to_vcore_dvfs(SPM_FLAG_RUN_COMMON_SCENARIO, 0); */ + plat_init_opp = gvrctrl->late_init_opp; + if (is_vcorefs_feature_enable()) { + if (gpu_kicker_init_opp == OPPI_PERF) { + kicker_table[KIR_GPU] = OPPI_PERF; + gvrctrl->late_init_opp = OPPI_PERF; + plat_init_opp = OPPI_PERF; + } + if (plat_init_opp != gvrctrl->boot_up_opp) { + krconf.kicker = KIR_LATE_INIT; + krconf.opp = plat_init_opp; + krconf.dvfs_opp = plat_init_opp; + kick_dvfs_by_opp_index(&krconf); + } else { + vcorefs_info("skip late_init kick(opp=%d)\n", gvrctrl->late_init_opp); + } + } + + mutex_unlock(&governor_mutex); + /* inform manager for governor init down */ + vcorefs_drv_init(plat_init_done, gvrctrl->vcore_dvfs_en, plat_init_opp); + + vcorefs_info("[%s] plat_feature_en: %d, plat_init_opp: %d\n", __func__, + gvrctrl->vcore_dvfs_en, plat_init_opp); + + /* mutex_unlock(&governor_mutex); */ + + return 0; +} + +static int init_vcorefs_config(void) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + struct opp_profile *opp_ctrl_table = opp_table; + int opp; + + mutex_lock(&governor_mutex); + gvrctrl->curr_vcore_uv = vcorefs_get_curr_vcore(); + BUG_ON(gvrctrl->curr_vcore_uv == 0); + gvrctrl->curr_ddr_khz = vcorefs_get_curr_ddr(); + + for (opp = 0; opp < NUM_OPP; opp++) { + opp_ctrl_table[opp].vcore_uv = vcorefs_get_vcore_by_steps(opp); + opp_ctrl_table[opp].ddr_khz = vcorefs_get_ddr_by_steps(opp); + vcorefs_info("OPP %d: vcore_uv: %d, ddr_khz: %d\n", opp, + opp_ctrl_table[opp].vcore_uv, opp_ctrl_table[opp].ddr_khz); + } + + vcorefs_info("curr_vcore_uv: %d, curr_ddr_khz: %d\n", gvrctrl->curr_vcore_uv, + gvrctrl->curr_ddr_khz); + + update_vcore_pwrap_cmd(opp_ctrl_table); + mutex_unlock(&governor_mutex); + + return 0; +} + +static int vcorefs_governor_pm_callback(struct notifier_block *nb, unsigned long action, void *ptr) +{ + /* vcorefs_info("governor_pm_callback(action=%lu)", action); */ + switch (action) { + case PM_POST_HIBERNATION: + { + vcorefs_info + ("restore sram debug info(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + sram_debug_info[0], sram_debug_info[1], sram_debug_info[2], + sram_debug_info[3], sram_debug_info[4], sram_debug_info[5], + sram_debug_info[6]); + vcorefs_info("sram count and latency clear to zero\n"); + spm_write(VCOREFS_SRAM_DVS_UP_COUNT, 0); + spm_write(VCOREFS_SRAM_DFS_UP_COUNT, 0); + spm_write(VCOREFS_SRAM_DVS_DOWN_COUNT, 0); + spm_write(VCOREFS_SRAM_DFS_DOWN_COUNT, 0); + spm_write(VCOREFS_SRAM_DVFS_UP_LATENCY, 0); + spm_write(VCOREFS_SRAM_DVFS_DOWN_LATENCY, 0); + spm_write(VCOREFS_SRAM_DVFS_LATENCY_SPEC, sram_debug_info[6]); + } + break; + case PM_HIBERNATION_PREPARE: + { + struct kicker_config krconf; + + sram_debug_info[0] = spm_read(VCOREFS_SRAM_DVS_UP_COUNT); + sram_debug_info[1] = spm_read(VCOREFS_SRAM_DFS_UP_COUNT); + sram_debug_info[2] = spm_read(VCOREFS_SRAM_DVS_DOWN_COUNT); + sram_debug_info[3] = spm_read(VCOREFS_SRAM_DFS_DOWN_COUNT); + sram_debug_info[4] = spm_read(VCOREFS_SRAM_DVFS_UP_LATENCY); + sram_debug_info[5] = spm_read(VCOREFS_SRAM_DVFS_DOWN_LATENCY); + sram_debug_info[6] = spm_read(VCOREFS_SRAM_DVFS_LATENCY_SPEC); + vcorefs_info + ("backup sram debug info(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + sram_debug_info[0], sram_debug_info[1], sram_debug_info[2], + sram_debug_info[3], sram_debug_info[4], sram_debug_info[5], + sram_debug_info[6]); + if (is_vcorefs_feature_enable()) { + krconf.kicker = KIR_SYSFS; + krconf.opp = OPPI_PERF; + krconf.dvfs_opp = OPPI_PERF; + kick_dvfs_by_opp_index(&krconf); + } + vcorefs_set_feature_en(false); + } + break; + case PM_RESTORE_PREPARE: + case PM_SUSPEND_PREPARE: + case PM_POST_SUSPEND: + case PM_POST_RESTORE: + default: + return NOTIFY_DONE; + } + return NOTIFY_OK; +} + +static int __init vcorefs_module_init(void) +{ + int r; + struct governor_profile *gvrctrl = &governor_ctrl; + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-vcorefs"); + if (!node) + vcorefs_err("find VCORE_DVFS node failed\n"); + + vcorefs_sram_base = of_iomap(node, 0); + if (!vcorefs_sram_base) { + vcorefs_err("FAILED TO MAP SRAM MEMORY OF VCORE DVFS\n"); + return -ENOMEM; + } + + node = of_find_compatible_node(NULL, NULL, "mediatek,spm_vcorefs_err_eint"); + if (!node) { + vcorefs_err("find spm_vcorefs_err_eint failed\n"); + } else { + int ret; + u32 ints[2]; + + of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints)); + mt_gpio_set_debounce(ints[0], ints[1]); + spm_vcorefs_err_irq = irq_of_parse_and_map(node, 0); + ret = + request_irq(spm_vcorefs_err_irq, spm_vcorefs_err_handler, + IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, "spm_vcorefs_err_eint", NULL); + } + + gvrctrl->segment_code = get_devinfo_with_index(21) & 0xff; + vcorefs_info("efuse segment code = 0x%x\n", gvrctrl->segment_code); + + pm_notifier(vcorefs_governor_pm_callback, 0); + + r = init_vcorefs_config(); + if (r) { + vcorefs_err("FAILED TO INIT CONFIG (%d)\n", r); + return r; + } + + r = init_vcorefs_sysfs(); + if (r) { + vcorefs_err("FAILED TO CREATE /sys/power/vcorefs (%d)\n", r); + return r; + } +#ifdef CONFIG_HAS_EARLYSUSPEND + register_early_suspend(&vcorefs_earlysuspend_desc); /* set Screen ON/OFF state to SPM for MD DVFS control */ +#else + memset(&vcorefs_fb_notif, 0, sizeof(vcorefs_fb_notif)); + vcorefs_fb_notif.notifier_call = vcorefs_fb_notifier_callback; + r = fb_register_client(&vcorefs_fb_notif); +#endif + vcorefs_set_log_mask(vcorefs_log_mask); + vcorefs_info("vcorefs_sram_base = %p, spm_vcorefs_err_irq = %d\n", vcorefs_sram_base, + spm_vcorefs_err_irq); + return r; +} +module_init(vcorefs_module_init); + +/*late_init is called after dyna_load_fw ready */ +/* late_initcall_sync(vcorefs_late_init_dvfs); */ + +void vcorefs_set_feature_enable(bool enable) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + mutex_lock(&governor_mutex); + gvrctrl->vcore_dvfs_en = enable; + vcorefs_info("%s DVFS feature\n", enable ? "Enable" : "Disable"); + mutex_unlock(&governor_mutex); +} + +/* + * pcm_flag control ( dvs / dfs / isr_debug_on) + */ +int vcorefs_enable_dvs(bool enable) +{ + struct opp_profile *opp_ctrl_table = opp_table; + + mutex_lock(&governor_mutex); + + /* dvs disabled: only adjust freq, voltage should be HPM */ + if (enable == false) { + /* set force_HPM before disable dvs */ + spm_vcorefs_set_dvfs_hpm_force(OPPI_PERF, opp_ctrl_table[OPPI_PERF].vcore_uv, + opp_ctrl_table[OPPI_PERF].ddr_khz); + + spm_go_to_vcore_dvfs(SPM_FLAG_RUN_COMMON_SCENARIO | SPM_FLAG_DIS_VCORE_DVS, 0); + /* release force_HPM */ + spm_vcorefs_set_dvfs_hpm_force(OPPI_LOW_PWR, opp_ctrl_table[OPPI_LOW_PWR].vcore_uv, + opp_ctrl_table[OPPI_LOW_PWR].ddr_khz); + } else { + spm_go_to_vcore_dvfs(SPM_FLAG_RUN_COMMON_SCENARIO, 0); + } + + mutex_unlock(&governor_mutex); + return 0; +} + +int vcorefs_enable_dfs(bool enable) +{ + struct opp_profile *opp_ctrl_table = opp_table; + + mutex_lock(&governor_mutex); + + /* dfs disabled: only adjust voltage, freq should be LPM */ + if (enable == false) { + /*set force_LPM before disable dfs */ + spm_vcorefs_set_dvfs_lpm_force(OPPI_LOW_PWR, opp_ctrl_table[OPPI_LOW_PWR].vcore_uv, + opp_ctrl_table[OPPI_LOW_PWR].ddr_khz); + spm_go_to_vcore_dvfs(SPM_FLAG_RUN_COMMON_SCENARIO | SPM_FLAG_DIS_VCORE_DFS, 0); + /* release force_LPM */ + spm_vcorefs_set_dvfs_lpm_force(OPPI_PERF, opp_ctrl_table[OPPI_PERF].vcore_uv, + opp_ctrl_table[OPPI_PERF].ddr_khz); + } else { + spm_go_to_vcore_dvfs(SPM_FLAG_RUN_COMMON_SCENARIO, 0); + } + + mutex_unlock(&governor_mutex); + return 0; +} + +int vcorefs_enable_debug_isr(bool enable) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + int flag = SPM_FLAG_RUN_COMMON_SCENARIO; + + vcorefs_info("enable_debug_isr(%d)\n", enable); + mutex_lock(&governor_mutex); + + if (gvrctrl->vcore_dvs == false) + flag |= SPM_FLAG_DIS_VCORE_DVS; + if (gvrctrl->ddr_dfs == false) + flag |= SPM_FLAG_DIS_VCORE_DFS; + + if (enable == true) + flag |= SPM_FLAG_EN_MET_DBG_FOR_VCORE_DVFS; + + spm_go_to_vcore_dvfs(flag, 0); + + mutex_unlock(&governor_mutex); + return 0; +} + +int vcorefs_enable_perform_bw(bool enable) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + mutex_lock(&governor_mutex); + gvrctrl->perform_bw_enable = enable; + spm_vcorefs_enable_perform_bw(enable); + mutex_unlock(&governor_mutex); + return 0; +} + +int vcorefs_enable_total_bw(bool enable) +{ + struct governor_profile *gvrctrl = &governor_ctrl; + + mutex_lock(&governor_mutex); + gvrctrl->total_bw_enable = enable; + spm_vcorefs_enable_total_bw(enable); + mutex_unlock(&governor_mutex); + return 0; +} + +/* + * AutoK related API + */ +void governor_apply_E2_SDIO_DVFS(void) +{ + vcorefs_info("check SRAM AUTOK REMARK=0x%x\n", spm_read(VCOREFS_SRAM_AUTOK_REMARK)); +#if 0 + if (spm_read(VCOREFS_SRAM_AUTOK_REMARK) == VALID_AUTOK_REMARK_VAL) { + int flag = (SPM_FLAG_RUN_COMMON_SCENARIO | SPM_FLAG_EN_E2_SDIO_SOLUTION); + vcorefs_crit("reload FW with flag=0x%x for E2-SDIO_ECO\n", flag); + vcorefs_reload_spm_firmware(flag); + } +#endif +} + +void governor_autok_manager(void) +{ + int r; + + vcorefs_info("autok flow start\n"); + /* autok callback */ + r = emmc_autok(); + vcorefs_info("emmc_autok r: %d\n", r); + r = sd_autok(); + vcorefs_info("sd_autok r: %d\n", r); + r = sdio_autok(); + vcorefs_info("sdio_autok r: %d\n", r); + + governor_apply_E2_SDIO_DVFS(); + + vcorefs_info("autok flow end\n"); + +} + +bool governor_autok_check(int kicker, int opp) +{ + int is_autok = true; + struct governor_profile *gvrctrl = &governor_ctrl; + + mutex_lock(&governor_mutex); + if (!((1 << kicker) & gvrctrl->autok_kir_group)) { + is_autok = false; + } else if (gvrctrl->active_autok_kir != 0 && gvrctrl->active_autok_kir != kicker) { + vcorefs_err("Not allow kir:%d autok ( other kir:%d on-going)\n", kicker, + gvrctrl->active_autok_kir); + is_autok = false; + } else { + is_autok = true; + } + mutex_unlock(&governor_mutex); + + return is_autok; +} + +bool governor_autok_lock_check(int kicker, int opp) +{ + bool lock_r = true; + struct governor_profile *gvrctrl = &governor_ctrl; + + mutex_lock(&governor_mutex); + + if (gvrctrl->active_autok_kir == 0) { + gvrctrl->active_autok_kir = kicker; /* start autok */ + lock_r = true; + } else if (kicker == gvrctrl->active_autok_kir) { + lock_r = true; /* continue autok */ + } else { + BUG(); + } + + if (opp == OPPI_UNREQ) { + gvrctrl->active_autok_kir = 0; + lock_r = false; + } + mutex_unlock(&governor_mutex); + return lock_r; +} diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_governor.h b/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_governor.h new file mode 100644 index 0000000000000000000000000000000000000000..5d6358a486bdb68e7779810cdfbfb009eb36a1bc --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_governor.h @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_VCOREFS_GOVERNOR_H +#define _MT_VCOREFS_GOVERNOR_H + +#undef VCPREFS_TAG +#define VCPREFS_TAG "[VcoreFS]" + +#define vcorefs_crit(fmt, args...) \ + pr_err(VCPREFS_TAG"[CRTT]"fmt, ##args) +#define vcorefs_err(fmt, args...) \ + pr_err(VCPREFS_TAG"[ERR]"fmt, ##args) +#define vcorefs_warn(fmt, args...) \ + pr_warn(VCPREFS_TAG"[WARN]"fmt, ##args) +#define vcorefs_info(fmt, args...) \ + pr_warn(VCPREFS_TAG""fmt, ##args) +#define vcorefs_debug(fmt, args...) \ + pr_debug(VCPREFS_TAG""fmt, ##args) + +#define DBG_MSG_ENABLE (1U << 31) +#define vcorefs_debug_mask(type, fmt, args...) \ + do { \ + if (vcorefs_log_mask & DBG_MSG_ENABLE) \ + vcorefs_info(fmt, ##args); \ + else if (vcorefs_log_mask & (1U << type)) \ + vcorefs_info(fmt, ##args); \ + } while (0) + +struct kicker_config { + int kicker; + int opp; + int dvfs_opp; +}; + + +#define VCORE_1_P_00_UV 1000000 +#define VCORE_0_P_90_UV 900000 + +#define FDDR_S0_KHZ 1866000 +#define FDDR_S1_KHZ 1333000 + +/* Vcore 1.0 <=> trans1 <=> trans2 <=> Vcore 0.9 (SPM control) */ +enum vcore_trans { + TRANS1, + TRANS2, + NUM_TRANS +}; + +enum dvfs_kicker { + KIR_MM_16MCAM, + KIR_MM_WFD, + KIR_MM_MHL, + KIR_OVL, + KIR_SDIO, + KIR_PERF, + KIR_SYSFS, + KIR_SYSFS_N, + KIR_GPU, + NUM_KICKER, + + /* internal kicker */ + KIR_LATE_INIT, + KIR_SYSFSX, + KIR_AUTOK_EMMC, + KIR_AUTOK_SDIO, + KIR_AUTOK_SD, + LAST_KICKER, +}; + +#define KIR_AUTOK KIR_AUTOK_SDIO + +enum dvfs_opp { + OPP_OFF = -1, + OPP_0 = 0, + OPP_1, + NUM_OPP +}; + +#define OPPI_PERF OPP_0 +#define OPPI_LOW_PWR OPP_1 +#define OPPI_UNREQ OPP_OFF + +enum md_status { + MD_CAT6_CA_DATALINK = 0, + MD_NON_CA_DATALINK, + MD_Paging, + MD_Position, + MD_Cell_Search, + MD_Cell_Manage, + MD_DISABLE_SCREEN_CHANGE = 16, +}; + +struct opp_profile { + int vcore_uv; + int ddr_khz; +}; + +extern unsigned int vcorefs_log_mask; + +extern int kicker_table[LAST_KICKER]; + +extern void __iomem *vcorefs_sram_base; + +#define VCOREFS_SRAM_BASE vcorefs_sram_base /* map 0x0011cf80 */ +/* SDIO parameters */ +#define VCOREFS_SRAM_AUTOK_REMARK (VCOREFS_SRAM_BASE) +#define VCOREFS_SRAM_SDIO_HPM_PARA (VCOREFS_SRAM_BASE + 0x04) +#define VCOREFS_SRAM_SDIO_LPM_PARA (VCOREFS_SRAM_BASE + 0x2C) +/* VcoreFS debug */ +#define VCOREFS_SRAM_DVS_UP_COUNT (VCOREFS_SRAM_BASE + 0x54) +#define VCOREFS_SRAM_DFS_UP_COUNT (VCOREFS_SRAM_BASE + 0x58) +#define VCOREFS_SRAM_DVS_DOWN_COUNT (VCOREFS_SRAM_BASE + 0x5c) +#define VCOREFS_SRAM_DFS_DOWN_COUNT (VCOREFS_SRAM_BASE + 0x60) +#define VCOREFS_SRAM_DVFS_UP_LATENCY (VCOREFS_SRAM_BASE + 0x64) +#define VCOREFS_SRAM_DVFS_DOWN_LATENCY (VCOREFS_SRAM_BASE + 0x68) +#define VCOREFS_SRAM_DVFS_LATENCY_SPEC (VCOREFS_SRAM_BASE + 0x6c) + +#define VALID_AUTOK_REMARK_VAL 0x55AA55AA + +/* 1T@32K = 30.5us, 1ms is about 32 T */ +#define DVFS_LATENCY_MAX 32 /* about 1 msc */ + + + +/* + * User API + */ +extern void vcorefs_set_cpu_dvfs_req(u32 value); + +/* + * Framework API + */ +extern int vcorefs_late_init_dvfs(void); +extern int kick_dvfs_by_opp_index(struct kicker_config *krconf); +extern bool is_vcorefs_feature_enable(void); +extern int vcorefs_get_num_opp(void); +extern int vcorefs_get_curr_vcore(void); +extern int vcorefs_get_curr_ddr(void); +extern int vcorefs_get_vcore_by_steps(u32); +extern int vcorefs_get_ddr_by_steps(unsigned int steps); +extern char *vcorefs_get_dvfs_info(char *p); +extern char *vcorefs_get_opp_table_info(char *p); +extern void vcorefs_update_opp_table(char *cmd, int val); +extern int vcorefs_output_kicker_id(char *name); + +/* Manager extern API */ +extern int governor_debug_store(const char *); + +extern int vcorefs_enable_dvs(bool enable); +extern int vcorefs_enable_dfs(bool enable); +extern int vcorefs_enable_debug_isr(bool enable); + +extern int get_kicker_group_opp(int kicker, int group_id); +extern char *get_kicker_name(int id); + +/* EMIBW API */ +extern int vcorefs_set_perform_bw_threshold(u32 lpm_threshold, u32 hpm_threshold); +extern int vcorefs_set_total_bw_threshold(u32 lpm_threshold, u32 hpm_threshold); +extern int vcorefs_enable_perform_bw(bool enable); +extern int vcorefs_enable_total_bw(bool enable); + +/* screen size */ +extern int primary_display_get_width(void); +extern int primary_display_get_height(void); +extern int primary_display_get_virtual_width(void); +extern int primary_display_get_virtual_height(void); + +/* AutoK related API */ +extern void governor_autok_manager(void); +extern bool governor_autok_check(int kicker, int opp); +extern bool governor_autok_lock_check(int kicker, int opp); + +extern void vcorefs_set_sram_data(int index, u32 data); +extern u32 vcorefs_get_sram_data(int index); + +extern void aee_rr_rec_vcore_dvfs_opp(u32 val); +extern u32 aee_rr_curr_vcore_dvfs_opp(void); +extern void aee_rr_rec_vcore_dvfs_status(u32 val); +extern u32 aee_rr_curr_vcore_dvfs_status(void); + +/* GPU kicker init opp API */ +extern int vcorefs_gpu_get_init_opp(void); +extern void vcorefs_gpu_set_init_opp(int opp); +extern bool vcorefs_request_init_opp(int kicker, int opp); + +#endif /* _MT_VCOREFS_GOVERNOR_H */ diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_manager.c b/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_manager.c new file mode 100644 index 0000000000000000000000000000000000000000..ed5118bebaf881cbf911e7d011d0151f84b9baaf --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_manager.c @@ -0,0 +1,593 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include + +#include "mt_vcorefs_manager.h" +#include "mt_spm_vcore_dvfs.h" +#include "mt_spm.h" + +static DEFINE_MUTEX(vcorefs_mutex); + +#define DEFINE_ATTR_RO(_name) \ +static struct kobj_attribute _name##_attr = { \ + .attr = { \ + .name = #_name, \ + .mode = 0444, \ + }, \ + .show = _name##_show, \ +} + +#define DEFINE_ATTR_RW(_name) \ +static struct kobj_attribute _name##_attr = { \ + .attr = { \ + .name = #_name, \ + .mode = 0644, \ + }, \ + .show = _name##_show, \ + .store = _name##_store, \ +} + +#define __ATTR_OF(_name) (&_name##_attr.attr) + +#ifdef CONFIG_MTK_RAM_CONSOLE +#define SPM_AEE_RR_REC 1 +#else +#define SPM_AEE_RR_REC 0 +#endif + +struct vcorefs_profile { + int plat_init_opp; + bool init_done; + bool autok_lock; + u32 kr_req_mask; +}; + +static struct vcorefs_profile vcorefs_ctrl = { + .plat_init_opp = 0, + .init_done = 0, + .autok_lock = 0, + .kr_req_mask = 0, +}; + +/* + * __nosavedata will not be restored after IPO-H boot + */ +static bool feature_en __nosavedata; + +static int vcorefs_curr_opp __nosavedata = OPPI_PERF; +static int vcorefs_prev_opp __nosavedata = OPPI_PERF; + +static int vcorefs_autok_lock_dvfs(int kicker, bool lock); +static int vcorefs_autok_set_vcore(int kicker, enum dvfs_opp opp); + +static vcorefs_req_handler_t vcorefs_req_handler; + +void vcorefs_register_req_notify(vcorefs_req_handler_t handler) +{ + vcorefs_req_handler = handler; +} +EXPORT_SYMBOL(spm_vcorefs_register_handler); + +/* + * Manager extern API + */ +int is_vcorefs_can_work(void) +{ + struct vcorefs_profile *pwrctrl = &vcorefs_ctrl; + int r = 0; + + mutex_lock(&vcorefs_mutex); + if (pwrctrl->init_done && feature_en) + r = 1; /* ready to use vcorefs */ + else if (!is_vcorefs_feature_enable()) + r = -1; /* not support vcorefs */ + else + r = 0; /* init not finish, please wait */ + mutex_unlock(&vcorefs_mutex); + + return r; +} + +int vcorefs_get_curr_opp(void) +{ + int opp; + + mutex_lock(&vcorefs_mutex); + opp = vcorefs_curr_opp; + mutex_unlock(&vcorefs_mutex); + + return opp; +} + +/* + * Sub-main function + */ +static int _get_dvfs_opp(int kicker, struct vcorefs_profile *pwrctrl) +{ + unsigned int opp = UINT_MAX; + int i; + char table[NUM_KICKER * 4 + 1]; + char *p = table; + + for (i = 0; i < NUM_KICKER; i++) + p += sprintf(p, " %d,", kicker_table[i]); + + vcorefs_debug_mask(kicker, "kr opp: %s\n", table); + + for (i = 0; i < NUM_KICKER; i++) { + if (kicker_table[i] < 0) + continue; + + if (kicker_table[i] < opp) + opp = kicker_table[i]; + } + + /* if have no request, set to init OPP */ + if (opp == UINT_MAX) + opp = pwrctrl->plat_init_opp; + + return opp; +} + +static int kicker_request_compare(enum dvfs_kicker kicker, enum dvfs_opp opp) +{ + /* compare kicker table opp with request opp (except SYSFS) */ + if (opp == kicker_table[kicker] && kicker != KIR_SYSFS) { + /* try again since previous change is partial success */ + if (vcorefs_curr_opp == vcorefs_prev_opp) { + vcorefs_debug_mask(LAST_KICKER, "opp no change, kr_tb: %d, kr: %d, opp: %d\n", + kicker_table[kicker], kicker, opp); + return -1; + } + } + + kicker_table[kicker] = opp; + + return 0; +} + +static int kicker_request_mask(struct vcorefs_profile *pwrctrl, enum dvfs_kicker kicker, + enum dvfs_opp opp) +{ + if (pwrctrl->kr_req_mask & (1U << kicker)) { + if (opp < 0) + kicker_table[kicker] = opp; + + vcorefs_debug_mask(LAST_KICKER, "mask request, mask: 0x%x, kr: %d, opp: %d\n", + pwrctrl->kr_req_mask, kicker, opp); + return -1; + } + + return 0; +} + +static void record_kicker_opp_in_aee(int kicker, int opp) +{ +#if SPM_AEE_RR_REC + u32 val; + /* record opp table */ + val = aee_rr_curr_vcore_dvfs_opp(); + val = (opp == OPP_0) ? (val & ~(1 << kicker)) : (val | (1 << kicker)); + aee_rr_rec_vcore_dvfs_opp(val); + + /* record last kicker and opp */ + val = aee_rr_curr_vcore_dvfs_status(); + val &= ~(0xFF000000); + val |= ((opp << 30) | (kicker << 24)); + aee_rr_rec_vcore_dvfs_status(val); +#endif +} + +/* + * Main function API (Called by kicker request for DVFS) + * PASS: return 0 + * FAIL: return less than 0 + */ +int vcorefs_request_dvfs_opp(enum dvfs_kicker kicker, enum dvfs_opp opp) +{ + struct vcorefs_profile *pwrctrl = &vcorefs_ctrl; + struct kicker_config krconf; + int r; + int autok_r, autok_lock; + + if (is_vcorefs_feature_enable() && !pwrctrl->init_done) { + vcorefs_debug_mask(kicker, "request before init done(kr:%d opp:%d)\n", kicker, opp); + if (vcorefs_request_init_opp(kicker, opp)) + return 0; + } + + if (!feature_en || !pwrctrl->init_done) { + vcorefs_err("feature_en: %d, init_done: %d\n", feature_en, pwrctrl->init_done); + return -1; + } + + autok_r = governor_autok_check(kicker, opp); + if (autok_r == true) { + autok_lock = governor_autok_lock_check(kicker, opp); + + if (autok_lock) { + vcorefs_autok_lock_dvfs(kicker, true); + vcorefs_autok_set_vcore(kicker, opp); + } else { + vcorefs_autok_set_vcore(kicker, opp); + if (OPPI_PERF == get_kicker_group_opp(KIR_SYSFS, -1)) + vcorefs_autok_set_vcore(KIR_SYSFS, OPPI_PERF); + vcorefs_autok_lock_dvfs(kicker, false); + } + return 0; + } + + if (pwrctrl->autok_lock) { + vcorefs_err("autoK lock: %d, Not allow kr: %d, opp: %d\n", pwrctrl->autok_lock, + kicker, opp); + return -1; + } + + if (kicker_request_mask(pwrctrl, kicker, opp)) + return -1; + + if (kicker_request_compare(kicker, opp)) + return 0; /* already request, return OK */ + + mutex_lock(&vcorefs_mutex); + + krconf.kicker = kicker; + krconf.opp = opp; + krconf.dvfs_opp = _get_dvfs_opp(kicker, pwrctrl); + + vcorefs_debug_mask(kicker, "kicker: %d, opp: %d, dvfs_opp: %d, curr_opp: %d\n", + krconf.kicker, krconf.opp, krconf.dvfs_opp, vcorefs_curr_opp); + + record_kicker_opp_in_aee(kicker, opp); + if (vcorefs_req_handler) + vcorefs_req_handler(kicker, opp); + + /* + * r = 0: DVFS completed + * + * LPM to HPM: + * r = -1: step1 DVS fail + * r = -2: step2 DFS fail + */ + r = kick_dvfs_by_opp_index(&krconf); + + if (r == 0) { + vcorefs_prev_opp = krconf.dvfs_opp; + vcorefs_curr_opp = krconf.dvfs_opp; + } else if (r < 0) { + vcorefs_err("kicker: %d, Vcore DVFS Fail, r: %d\n", kicker, r); + + /* if (r == -2) no change */ + if (r == -3) { + vcorefs_prev_opp = vcorefs_curr_opp; + vcorefs_curr_opp = krconf.dvfs_opp; + } + } else { + vcorefs_err("kicker: %d, unknown error handling, r: %d\n", kicker, r); + BUG(); + } + mutex_unlock(&vcorefs_mutex); + + return r; +} + +/* + * SDIO AutoK related API + */ +int vcorefs_autok_lock_dvfs(int kicker, bool lock) +{ + struct vcorefs_profile *pwrctrl = &vcorefs_ctrl; + int r = 0; + + mutex_lock(&vcorefs_mutex); + vcorefs_crit("autok kicker %d set lock: %d\n", kicker, lock); + pwrctrl->autok_lock = lock; + mutex_unlock(&vcorefs_mutex); + + return r; +} + +int vcorefs_autok_set_vcore(int kicker, enum dvfs_opp opp) +{ + struct vcorefs_profile *pwrctrl = &vcorefs_ctrl; + struct kicker_config krconf; + int r = 0; + + if (opp >= NUM_OPP || !pwrctrl->autok_lock) { + vcorefs_err("set vcore fail, opp: %d, autok_lock: %d\n", opp, pwrctrl->autok_lock); + return -1; + } + + if (vcorefs_gpu_get_init_opp() == OPPI_PERF && opp == OPPI_LOW_PWR) { + vcorefs_err("autok kicker:%d set vcore fail due to init_opp request OPPI_PERF\n", kicker); + return -1; + } + + mutex_lock(&vcorefs_mutex); + krconf.kicker = kicker; + krconf.opp = opp; + krconf.dvfs_opp = opp; + + vcorefs_crit("autok kicker: %d, opp: %d, dvfs_opp: %d, curr_opp: %d\n", + krconf.kicker, krconf.opp, krconf.dvfs_opp, vcorefs_curr_opp); + + /* + * r = 0: DVFS completed + * + * LPM to HPM: + * r = -1: step1 DVS fail + * r = -2: step2 DFS fail + */ + r = kick_dvfs_by_opp_index(&krconf); + mutex_unlock(&vcorefs_mutex); + + return r; +} + +/* + * Called by governor for init flow + */ +void vcorefs_drv_init(bool plat_init_done, bool plat_feature_en, int plat_init_opp) +{ + struct vcorefs_profile *pwrctrl = &vcorefs_ctrl; + int i; + + mutex_lock(&vcorefs_mutex); + if (!plat_feature_en) + feature_en = 0; + else + feature_en = 1; + + for (i = 0; i < NUM_KICKER; i++) + kicker_table[i] = -1; + aee_rr_rec_vcore_dvfs_opp(0xffffffff); + + if (vcorefs_gpu_get_init_opp() == OPPI_PERF) { + /* GPU kicker already request HPM in init */ + kicker_table[KIR_GPU] = OPPI_PERF; + aee_rr_rec_vcore_dvfs_opp(0xfffffeff); + } + + vcorefs_curr_opp = plat_init_opp; + pwrctrl->plat_init_opp = plat_init_opp; + pwrctrl->init_done = plat_init_done; + mutex_unlock(&vcorefs_mutex); + + governor_autok_manager(); + vcorefs_gpu_set_init_opp(OPPI_UNREQ); +} + +void vcorefs_set_feature_en(bool enable) +{ + feature_en = enable; +} + +void vcorefs_set_kr_req_mask(unsigned int mask) +{ + struct vcorefs_profile *pwrctrl = &vcorefs_ctrl; + + pwrctrl->kr_req_mask = mask; +} +/* + * Vcorefs debug sysfs + */ +static char *vcorefs_get_kicker_info(char *p) +{ + int i; + + for (i = 0; i < NUM_KICKER; i++) + p += sprintf(p, "[%s] opp: %d\n", get_kicker_name(i), kicker_table[i]); + + return p; +} + +static ssize_t vcore_debug_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct vcorefs_profile *pwrctrl = &vcorefs_ctrl; + char *p = buf; + + p += sprintf(p, "\n"); + + p += sprintf(p, "[feature_en ]: %d\n", feature_en); + p += sprintf(p, "[plat_init_opp]: %d\n", pwrctrl->plat_init_opp); + p += sprintf(p, "[init_done ]: %d\n", pwrctrl->init_done); + p += sprintf(p, "[autok_lock ]: %d\n", pwrctrl->autok_lock); + p += sprintf(p, "[kr_req_mask ]: 0x%x\n", pwrctrl->kr_req_mask); + p += sprintf(p, "\n"); + + p += sprintf(p, "curr_opp: %d\n", vcorefs_curr_opp); + p += sprintf(p, "prev_opp: %d\n", vcorefs_prev_opp); + p += sprintf(p, "\n"); + + p = vcorefs_get_dvfs_info(p); + p += sprintf(p, "\n"); + + p = vcorefs_get_kicker_info(p); + p += sprintf(p, "\n"); + + p += sprintf(p, " [aee] vcore_dvfs_opp = 0x%x\n", aee_rr_curr_vcore_dvfs_opp()); + p += sprintf(p, " [aee] vcore_dvfs_status = 0x%x\n", aee_rr_curr_vcore_dvfs_status()); + p += sprintf(p, "\n"); + +#ifndef CONFIG_MTK_FPGA + p = spm_vcorefs_dump_dvfs_regs(p); +#endif + + return p - buf; +} + +static ssize_t vcore_debug_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct vcorefs_profile *pwrctrl = &vcorefs_ctrl; + struct kicker_config krconf; + int kicker, val, r, opp; + char cmd[32]; + int change = 0; + + /* governor debug sysfs */ + r = governor_debug_store(buf); + if (!r) + return count; + + if (!(sscanf(buf, "%31s 0x%x", cmd, &val) == 2 || + sscanf(buf, "%31s %d", cmd, &val) == 2)) { + return -EPERM; + } + + /* manager debug sysfs */ + vcorefs_crit("vcore_debug: cmd: %s, val: %d\n", cmd, val); + + if (!strcmp(cmd, "feature_en")) { + mutex_lock(&vcorefs_mutex); + + if (val && (!feature_en)) { + kicker_table[KIR_SYSFS] = OPP_OFF; + opp = get_kicker_group_opp(KIR_SYSFS, -1); + change = 1; + } else if ((!val) && feature_en) { + kicker_table[KIR_SYSFS] = OPP_0; + opp = OPP_0; + change = 1; + } else { + change = 0; + } + + if (change == 1) { + krconf.kicker = KIR_SYSFS; + krconf.opp = opp; + krconf.dvfs_opp = opp; + + vcorefs_crit("kicker: %d, opp: %d, dvfs_opp: %d, curr_opp: %d\n", + krconf.kicker, krconf.opp, krconf.dvfs_opp, vcorefs_curr_opp); + + /* + * r = 0: DVFS completed + * + * LPM to HPM: + * r = -1: step1 DVS fail + * r = -2: step2 DFS fail + */ + r = kick_dvfs_by_opp_index(&krconf); + + vcorefs_curr_opp = krconf.dvfs_opp; + feature_en = !!(val); + } + mutex_unlock(&vcorefs_mutex); + } else if (!strcmp(cmd, "kr_req_mask")) { + mutex_lock(&vcorefs_mutex); + pwrctrl->kr_req_mask = val; + mutex_unlock(&vcorefs_mutex); + } else if (!strcmp(cmd, "KIR_SYSFSX") && (val >= OPP_OFF && val < NUM_OPP)) { + mutex_lock(&vcorefs_mutex); + if (val != OPP_OFF) + pwrctrl->kr_req_mask = (1U << NUM_KICKER) - 1; + else + pwrctrl->kr_req_mask = 0; + + krconf.kicker = KIR_SYSFSX; + krconf.opp = val; + krconf.dvfs_opp = val; + + vcorefs_crit("kicker: %d, opp: %d, dvfs_opp: %d, curr_opp: %d\n", + krconf.kicker, krconf.opp, krconf.dvfs_opp, vcorefs_curr_opp); + + /* + * r = 0: DVFS completed + * + * LPM to HPM: + * r = -1: step1 DVS fail + * r = -2: step2 DFS fail + */ + r = kick_dvfs_by_opp_index(&krconf); + mutex_unlock(&vcorefs_mutex); + } else if (!strcmp(cmd, "KIR_AUTOK_SDIO")) { + kicker = KIR_AUTOK_SDIO; + vcorefs_request_dvfs_opp(kicker, val); + } else { + /* set kicker opp and do DVFS */ + kicker = vcorefs_output_kicker_id(cmd); + if (kicker != -1) + vcorefs_request_dvfs_opp(kicker, val); + } + + return count; +} + +static ssize_t opp_table_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + char *p = buf; + + p = vcorefs_get_opp_table_info(p); + + return p - buf; +} + +static ssize_t opp_table_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int val; + char cmd[32]; + + if (sscanf(buf, "%31s %u", cmd, &val) != 2) + return -EPERM; + + vcorefs_crit("opp_table: cmd: %s, val: %d (0x%x)\n", cmd, val, val); + + mutex_lock(&vcorefs_mutex); + if (!feature_en) + vcorefs_update_opp_table(cmd, val); + mutex_unlock(&vcorefs_mutex); + + return count; +} + +static ssize_t opp_num_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + char *p = buf; + int num = vcorefs_get_num_opp(); + + p += sprintf(p, "%d\n", num); + + return p - buf; +} + +DEFINE_ATTR_RW(vcore_debug); +DEFINE_ATTR_RW(opp_table); +DEFINE_ATTR_RO(opp_num); + +static struct attribute *vcorefs_attrs[] = { + __ATTR_OF(opp_table), + __ATTR_OF(vcore_debug), + __ATTR_OF(opp_num), + NULL, +}; + +static struct attribute_group vcorefs_attr_group = { + .name = "vcorefs", + .attrs = vcorefs_attrs, +}; + +int init_vcorefs_sysfs(void) +{ + int r; + + r = sysfs_create_group(power_kobj, &vcorefs_attr_group); + + return 0; +} diff --git a/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_manager.h b/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..83ca4b39fb517a969f2d0b1671a0ab1fd3506690 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/mt_vcorefs_manager.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_VCOREFS_MANAGER_H +#define _MT_VCOREFS_MANAGER_H + +#include "mt_vcorefs_governor.h" + +/* Manager extern API */ +extern int is_vcorefs_can_work(void); +extern int vcorefs_get_curr_opp(void); + +/* Main function API (Called by kicker request for DVFS) */ +extern int vcorefs_request_dvfs_opp(enum dvfs_kicker, enum dvfs_opp); + +/* Called by governor for init flow */ +extern void vcorefs_drv_init(bool, bool, int); +extern int init_vcorefs_sysfs(void); +extern void vcorefs_set_feature_en(bool enable); +extern void vcorefs_set_kr_req_mask(unsigned int mask); + +/* Called by MET */ +typedef void (*vcorefs_req_handler_t) (enum dvfs_kicker kicker, enum dvfs_opp opp); +extern void vcorefs_register_req_notify(vcorefs_req_handler_t handler); + +#endif /* _MT_VCOREFS_MANAGER_H */ diff --git a/drivers/misc/mediatek/base/power/mt6755/smp.h b/drivers/misc/mediatek/base/power/mt6755/smp.h new file mode 100644 index 0000000000000000000000000000000000000000..40507200121ddbbe8dd9b9dc82cfb1c261c93721 --- /dev/null +++ b/drivers/misc/mediatek/base/power/mt6755/smp.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * 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. + */ +#ifndef __MT_SMP_H +#define __MT_SMP_H + +#include +#include +#include + +#include + +#include "hotplug.h" + +extern void irq_raise_softirq(const struct cpumask *mask, unsigned int irq); + +/* use Soft IRQ1 as the IPI */ +static inline void smp_cross_call(const struct cpumask *mask) +{ + irq_raise_softirq(mask, CPU_BRINGUP_SGI); +} + +#ifdef CONFIG_ARM64 +static inline int get_HW_cpuid(void) +{ + u64 mpidr; + u32 id; + + mpidr = read_cpuid_mpidr(); + id = (mpidr & 0xff) + ((mpidr & 0xff00) >> 6); + + return id; +} +#else +static inline int get_HW_cpuid(void) +{ + int id; + + asm("mrc p15, 0, %0, c0, c0, 5 @ Get CPUID\n":"=r"(id)); + return (id & 0x3) + ((id & 0xF00) >> 6); +} +#endif + +static inline void mt_smp_set_boot_addr(u32 addr, int cpu) +{ + mt_reg_sync_writel(addr, BOOTROM_BOOT_ADDR); +} + +#endif diff --git a/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/Makefile b/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7d73f8c082e8d2e073372d4b864f1d89b630c8b2 --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/Makefile @@ -0,0 +1,19 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += \ + -I$(PPM_ROOT_DIR)/inc \ + -I$(srctree)/drivers/misc/mediatek/base/power/$(CONFIG_MTK_PLATFORM)/ + +# power state settings +obj-y += mt_ppm_power_state.o diff --git a/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_platform.h b/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..6f46e5f41b9c9d16772881fd9e328b763d546dfa --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_platform.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#ifndef __MT_PPM_PLATFORM_H__ +#define __MT_PPM_PLATFORM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mach/mt_ppm_api.h" + +/*==============================================================*/ +/* Macros */ +/*==============================================================*/ +/* ppm driver update state to MET directly 0: turn off */ +#define PPM_UPDATE_STATE_DIRECT_TO_MET (1) + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#define PPM_IC_SEGMENT_CHECK (1) +#define PPM_VPROC_5A_LIMIT_CHECK (1) +#define PPM_5A_LIMIT_FREQ_IDX (1) +#endif + +#define PPM_HW_OCP_SUPPORT (0) +#define PPM_DLPT_ENHANCEMENT (0) + +/* DLPT */ +#define PPM_DLPT_DEFAULT_MODE (SW_MODE) +#define DLPT_MAX_REAL_POWER_FY (3890) +#define DLPT_MAX_REAL_POWER_SB (4992) +#define LCMOFF_MIN_FREQ (598000) +#define PTPOD_FREQ_IDX (3) +#define SUSPEND_FREQ_LL (689000) +#define SUSPEND_FREQ_L (871000) +#define PWRTHRO_BAT_PER_MW (610) +#define PWRTHRO_BAT_OC_MW (610) +#define PWRTHRO_LOW_BAT_LV1_MW (610) +#define PWRTHRO_LOW_BAT_LV2_MW (610) + +#define NR_CLUSTERS (2) +#define DVFS_OPP_NUM (8) + +#define PPM_DEFAULT_HOLD_TIME (4) +#define PPM_DEFAULT_FREQ_HOLD_TIME (4) +#define PPM_DEFAULT_DELTA (20) +#define PPM_LOADING_UPPER (400) +#define PPM_TLP_CRITERIA (400) + +#define get_cluster_lcmoff_min_freq(id) LCMOFF_MIN_FREQ /* the same for each cluster */ +#define get_cluster_ptpod_fix_freq_idx(id) PTPOD_FREQ_IDX /* the same for each cluster */ +#define get_cluster_suspend_fix_freq(id) \ + ((id == 0) ? SUSPEND_FREQ_LL : SUSPEND_FREQ_L) +#define get_max_real_power_by_segment(seg) \ + ((ppm_main_info.dvfs_tbl_type == DVFS_TABLE_TYPE_SB) ? DLPT_MAX_REAL_POWER_SB \ + : DLPT_MAX_REAL_POWER_FY) + +/*==============================================================*/ +/* Enum */ +/*==============================================================*/ +enum ppm_power_state { + PPM_POWER_STATE_LL_ONLY = 0, + PPM_POWER_STATE_L_ONLY, + PPM_POWER_STATE_4LL_L, + PPM_POWER_STATE_4L_LL, /* Need this? */ + + PPM_POWER_STATE_NONE, /* HICA disabled */ + NR_PPM_POWER_STATE = PPM_POWER_STATE_NONE, +}; + +/*==============================================================*/ +/* Data Structures */ +/*==============================================================*/ +struct ppm_power_tbl { + const unsigned int index; + struct { + int opp_lv; + unsigned int core_num; + } const cluster_cfg[NR_CLUSTERS]; + const unsigned int perf_idx; + const unsigned int power_idx; +}; + +struct ppm_power_tbl_data { + const struct ppm_power_tbl *power_tbl; + const unsigned int nr_power_tbl; +}; + +/*==============================================================*/ +/* Global Variables */ +/*==============================================================*/ + +/*==============================================================*/ +/* APIs */ +/*==============================================================*/ +#ifdef PPM_IC_SEGMENT_CHECK +extern enum ppm_power_state ppm_check_fix_state_by_segment(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + + + diff --git a/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_power_state.c b/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_power_state.c new file mode 100644 index 0000000000000000000000000000000000000000..3415baee9dd2d371bf85b58420b97c5431cce20b --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_power_state.c @@ -0,0 +1,837 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include "mt_cpufreq.h" +#include "mt_ppm_platform.h" +#include "mt_ppm_internal.h" + +/*==============================================================*/ +/* Macros */ +/*==============================================================*/ +#define PWR_STATE_TBLS(name, type) \ + .cluster_limit = &cluster_limit_##name, \ + .pwr_sorted_tbl = &pwr_sorted_tbl_##name##_##type, \ + .perf_sorted_tbl = &perf_sorted_tbl_##name##_##type, \ + .transfer_by_pwr = &transfer_by_pwr_##name, \ + .transfer_by_perf = &transfer_by_perf_##name, + +#define LIMIT(fmin, fmax, cmin, cmax) { \ + .min_cpufreq_idx = fmin, \ + .max_cpufreq_idx = fmax, \ + .min_cpu_core = cmin, \ + .max_cpu_core = cmax, \ +} + +#define STATE_LIMIT(name) \ +const struct ppm_state_cluster_limit_data cluster_limit_##name = { \ + .state_limit = state_limit_##name, \ + .size = ARRAY_SIZE(state_limit_##name), \ +} + +#define SORT_TBL_ELEMENT(idx, val, advise) { \ + .index = idx, \ + .value = val, \ + .advise_index = advise, \ +} + +#define STATE_PWR_TBL(name, type) \ +const struct ppm_state_sorted_pwr_tbl_data pwr_sorted_tbl_##name##_##type = { \ + .sorted_tbl = state_pwr_tbl_##name##_##type, \ + .size = ARRAY_SIZE(state_pwr_tbl_##name##_##type), \ +} + +#define STATE_PERF_TBL(name, type) \ +const struct ppm_state_sorted_pwr_tbl_data perf_sorted_tbl_##name##_##type = { \ + .sorted_tbl = state_perf_tbl_##name##_##type, \ + .size = ARRAY_SIZE(state_perf_tbl_##name##_##type), \ +} + +#define TRANS_DATA(state, mask, rule, delta, hold, bond, f_hold, tlp) { \ + .next_state = PPM_POWER_STATE_##state, \ + .mode_mask = mask, \ + .transition_rule = rule, \ + .loading_delta = delta, \ + .loading_hold_time = hold, \ + .loading_hold_cnt = 0, \ + .loading_bond = bond, \ + .freq_hold_time = f_hold, \ + .freq_hold_cnt = 0, \ + .tlp_bond = tlp, \ +} + +#define STATE_TRANSFER_DATA_PWR(name) \ +struct ppm_state_transfer_data transfer_by_pwr_##name = { \ + .transition_data = state_pwr_transfer_##name, \ + .size = ARRAY_SIZE(state_pwr_transfer_##name), \ +} + +#define STATE_TRANSFER_DATA_PERF(name) \ +struct ppm_state_transfer_data transfer_by_perf_##name = { \ + .transition_data = state_perf_transfer_##name, \ + .size = ARRAY_SIZE(state_perf_transfer_##name), \ +} + +/*==============================================================*/ +/* Local Functions */ +/*==============================================================*/ +static bool ppm_trans_rule_LL_ONLY_to_L_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_LL_ONLY_to_4LL_L( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_L_ONLY_to_LL_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_L_ONLY_to_4L_LL( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_4LL_L_to_LL_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_4L_LL_to_L_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); + +/*==============================================================*/ +/* Local Variables */ +/*==============================================================*/ +/* cluster limit for each power state */ +static const struct ppm_cluster_limit state_limit_LL_ONLY[] = { + [0] = LIMIT(7, 0, 1, 4), + [1] = LIMIT(7, 0, 0, 0), +}; +STATE_LIMIT(LL_ONLY); + +static const struct ppm_cluster_limit state_limit_L_ONLY[] = { + [0] = LIMIT(7, 0, 0, 0), + [1] = LIMIT(5, 0, 1, 4), +}; +STATE_LIMIT(L_ONLY); + +static const struct ppm_cluster_limit state_limit_4LL_L[] = { + [0] = LIMIT(7, 0, 4, 4), + [1] = LIMIT(7, 0, 1, 4), +}; +STATE_LIMIT(4LL_L); + +static const struct ppm_cluster_limit state_limit_4L_LL[] = { + [0] = LIMIT(7, 0, 1, 4), + [1] = LIMIT(7, 0, 4, 4), +}; +STATE_LIMIT(4L_LL); + +/* state transfer data by power/performance for each state */ +static struct ppm_state_transfer state_pwr_transfer_LL_ONLY[] = { + TRANS_DATA(NONE, 0, NULL, 0, 0, 0, 0, 0), +}; +STATE_TRANSFER_DATA_PWR(LL_ONLY); + +static struct ppm_state_transfer state_perf_transfer_LL_ONLY[] = { + TRANS_DATA( + 4LL_L, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_LL_ONLY_to_4LL_L, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + 0, + PPM_TLP_CRITERIA + ), + TRANS_DATA( + L_ONLY, + PPM_MODE_MASK_JUST_MAKE_ONLY | PPM_MODE_MASK_PERFORMANCE_ONLY, + ppm_trans_rule_LL_ONLY_to_L_ONLY, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + /* PPM_DEFAULT_FREQ_HOLD_TIME, */ + 8, + PPM_TLP_CRITERIA + ), +}; +STATE_TRANSFER_DATA_PERF(LL_ONLY); + +static struct ppm_state_transfer state_pwr_transfer_L_ONLY[] = { + TRANS_DATA( + LL_ONLY, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_L_ONLY_to_LL_ONLY, + 0, + 0, + 0, + PPM_DEFAULT_FREQ_HOLD_TIME, + 0 + ), +}; +STATE_TRANSFER_DATA_PWR(L_ONLY); + +static struct ppm_state_transfer state_perf_transfer_L_ONLY[] = { + TRANS_DATA( + 4L_LL, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_L_ONLY_to_4L_LL, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + 0, + 0 + ), +}; +STATE_TRANSFER_DATA_PERF(L_ONLY); + +static struct ppm_state_transfer state_pwr_transfer_4LL_L[] = { + TRANS_DATA( + LL_ONLY, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_4LL_L_to_LL_ONLY, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + 0, + 0 + ), +}; +STATE_TRANSFER_DATA_PWR(4LL_L); + +static struct ppm_state_transfer state_perf_transfer_4LL_L[] = { + TRANS_DATA(NONE, 0, NULL, 0, 0, 0, 0, 0), +}; +STATE_TRANSFER_DATA_PERF(4LL_L); + +static struct ppm_state_transfer state_pwr_transfer_4L_LL[] = { + TRANS_DATA( + L_ONLY, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_4L_LL_to_L_ONLY, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + 0, + 0 + ), +}; +STATE_TRANSFER_DATA_PWR(4L_LL); + +static struct ppm_state_transfer state_perf_transfer_4L_LL[] = { + TRANS_DATA(NONE, 0, NULL, 0, 0, 0, 0, 0), +}; +STATE_TRANSFER_DATA_PERF(4L_LL); + +/*==============================================================*/ +/* Power Table auto-generated by script begin */ +/* Note: DO NOT modify it manually!! */ +/*==============================================================*/ +#include "mt_ppm_power_table.h" +/*==============================================================*/ +/* Power Table auto-generated by script end */ +/*==============================================================*/ + +/* default use FY table, may change to SB if needed */ +const struct ppm_power_tbl_data power_table_FY = { + .power_tbl = cpu_tlp_power_tbl_FY, + .nr_power_tbl = ARRAY_SIZE(cpu_tlp_power_tbl_FY), +}; + +const struct ppm_power_tbl_data power_table_SB = { + .power_tbl = cpu_tlp_power_tbl_SB, + .nr_power_tbl = ARRAY_SIZE(cpu_tlp_power_tbl_SB), +}; + +/* PPM power state static data */ +struct ppm_power_state_data pwr_state_info_FY[NR_PPM_POWER_STATE] = { + [0] = { + .name = __stringify(LL_ONLY), + .state = PPM_POWER_STATE_LL_ONLY, + PWR_STATE_TBLS(LL_ONLY, FY) + }, + [1] = { + .name = __stringify(L_ONLY), + .state = PPM_POWER_STATE_L_ONLY, + PWR_STATE_TBLS(L_ONLY, FY) + }, + [2] = { + .name = __stringify(4LL_L), + .state = PPM_POWER_STATE_4LL_L, + PWR_STATE_TBLS(4LL_L, FY) + }, + [3] = { + .name = __stringify(4L_LL), + .state = PPM_POWER_STATE_4L_LL, + PWR_STATE_TBLS(4L_LL, FY) + }, +}; + +struct ppm_power_state_data pwr_state_info_SB[NR_PPM_POWER_STATE] = { + [0] = { + .name = __stringify(LL_ONLY), + .state = PPM_POWER_STATE_LL_ONLY, + PWR_STATE_TBLS(LL_ONLY, SB) + }, + [1] = { + .name = __stringify(L_ONLY), + .state = PPM_POWER_STATE_L_ONLY, + PWR_STATE_TBLS(L_ONLY, SB) + }, + [2] = { + .name = __stringify(4LL_L), + .state = PPM_POWER_STATE_4LL_L, + PWR_STATE_TBLS(4LL_L, SB) + }, + [3] = { + .name = __stringify(4L_LL), + .state = PPM_POWER_STATE_4L_LL, + PWR_STATE_TBLS(4L_LL, SB) + }, +}; + +const unsigned int pwr_idx_search_prio[NR_PPM_POWER_STATE][NR_PPM_POWER_STATE] = { + [PPM_POWER_STATE_LL_ONLY] = {PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_L_ONLY] = {PPM_POWER_STATE_LL_ONLY, PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_4LL_L] = {PPM_POWER_STATE_LL_ONLY, PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_4L_LL] = {PPM_POWER_STATE_L_ONLY, PPM_POWER_STATE_LL_ONLY, PPM_POWER_STATE_NONE,}, +}; + +const unsigned int perf_idx_search_prio[NR_PPM_POWER_STATE][NR_PPM_POWER_STATE] = { + [PPM_POWER_STATE_LL_ONLY] = {PPM_POWER_STATE_L_ONLY, PPM_POWER_STATE_4LL_L, PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_L_ONLY] = {PPM_POWER_STATE_4L_LL, PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_4LL_L] = {PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_4L_LL] = {PPM_POWER_STATE_NONE,}, +}; + +/*==============================================================*/ +/* Local Function Implementation */ +/*==============================================================*/ +/* transition rules */ +static bool ppm_trans_rule_LL_ONLY_to_L_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + unsigned int cur_freq_LL; + + /* keep in LL_ONLY state if root cluster is fixed at cluster 0 */ + if (ppm_main_info.fixed_root_cluster == 0) + return false; + + /* keep in LL ONLY state if LCM is off */ + if (ppm_lcmoff_is_policy_activated()) + return false; + + /* check loading */ + if (data.ppm_cur_loads > (settings->loading_bond - settings->loading_delta) + && data.ppm_cur_tlp <= settings->tlp_bond) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + /* check freq */ + cur_freq_LL = mt_cpufreq_get_cur_phy_freq(MT_CPU_DVFS_LITTLE); /* FIXME */ + ppm_dbg(HICA, "LL cur freq = %d\n", cur_freq_LL); + + if (cur_freq_LL >= get_cluster_max_cpufreq(0)) { + settings->freq_hold_cnt++; + if (settings->freq_hold_cnt >= settings->freq_hold_time) + return true; + } else + settings->freq_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_LL_ONLY_to_4LL_L( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check loading only */ + if (data.ppm_cur_loads > (settings->loading_bond - settings->loading_delta) + && data.ppm_cur_tlp > settings->tlp_bond) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_L_ONLY_to_LL_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check freq only */ + unsigned int cur_freq_L; + + /* keep in L_ONLY state if root cluster is fixed at cluster 1 */ + if (ppm_main_info.fixed_root_cluster == 1) + return false; + + cur_freq_L = mt_cpufreq_get_cur_phy_freq(MT_CPU_DVFS_BIG); /* FIXME */ + ppm_dbg(HICA, "L cur freq = %d\n", cur_freq_L); + + if (cur_freq_L < get_cluster_max_cpufreq(0)) { + settings->freq_hold_cnt++; + if (settings->freq_hold_cnt >= settings->freq_hold_time) + return true; + } else + settings->freq_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_L_ONLY_to_4L_LL( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check loading only */ + if (data.ppm_cur_loads > (settings->loading_bond - settings->loading_delta)) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_4LL_L_to_LL_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check loading only */ + if (data.ppm_cur_loads <= (settings->loading_bond - settings->loading_delta)) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_4L_LL_to_L_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check loading only */ + if (data.ppm_cur_loads <= (settings->loading_bond - settings->loading_delta)) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + return false; +} + + +/*==============================================================*/ +/* Global Function Implementation */ +/*==============================================================*/ +struct ppm_power_state_data *ppm_get_power_state_info(void) +{ + return (ppm_main_info.dvfs_tbl_type == DVFS_TABLE_TYPE_FY) + ? pwr_state_info_FY : pwr_state_info_SB; +} + +const struct ppm_power_tbl_data ppm_get_power_table(void) +{ + return (ppm_main_info.dvfs_tbl_type == DVFS_TABLE_TYPE_FY) + ? power_table_FY : power_table_SB; +} + +const char *ppm_get_power_state_name(enum ppm_power_state state) +{ + if (state >= NR_PPM_POWER_STATE) + return "NONE"; + + /* the state name is the same between FY and SB */ + return pwr_state_info_FY[state].name; +} + +enum ppm_power_state ppm_change_state_with_fix_root_cluster(enum ppm_power_state cur_state, int cluster) +{ + enum ppm_power_state new_state = cur_state; + + switch (cluster) { + case 0: + if (cur_state == PPM_POWER_STATE_L_ONLY) + new_state = PPM_POWER_STATE_LL_ONLY; + else if (cur_state == PPM_POWER_STATE_4L_LL) + new_state = PPM_POWER_STATE_4LL_L; + break; + case 1: + if (cur_state == PPM_POWER_STATE_LL_ONLY) + new_state = PPM_POWER_STATE_L_ONLY; + else if (cur_state == PPM_POWER_STATE_4LL_L) + new_state = PPM_POWER_STATE_4L_LL; + break; + default: + break; + } + + return new_state; +} + +int ppm_get_table_idx_by_perf(enum ppm_power_state state, unsigned int perf_idx) +{ + int i; + struct ppm_power_state_data *state_info; + const struct ppm_state_sorted_pwr_tbl_data *tbl; + struct ppm_power_tbl_data power_table = ppm_get_power_table(); + + if (state > NR_PPM_POWER_STATE || (perf_idx == -1)) { + ppm_warn("Invalid argument: state = %d, pwr_idx = %d\n", state, perf_idx); + return -1; + } + + /* search whole tlp table */ + if (state == PPM_POWER_STATE_NONE) { + for (i = 1; i < power_table.nr_power_tbl; i++) { + if (power_table.power_tbl[i].perf_idx < perf_idx) + return power_table.power_tbl[i-1].index; + } + } else { + state_info = ppm_get_power_state_info(); + tbl = state_info[state].perf_sorted_tbl; + + /* return -1 (not found) if input is larger than max perf_idx in table */ + if (tbl->sorted_tbl[0].value < perf_idx) + return -1; + + for (i = 1; i < tbl->size; i++) { + if (tbl->sorted_tbl[i].value < perf_idx) + return tbl->sorted_tbl[i-1].index; + } + } + + /* not found */ + return -1; +} + +int ppm_get_table_idx_by_pwr(enum ppm_power_state state, unsigned int pwr_idx) +{ + int i; + struct ppm_power_state_data *state_info; + const struct ppm_state_sorted_pwr_tbl_data *tbl; + struct ppm_power_tbl_data power_table = ppm_get_power_table(); + + if (state > NR_PPM_POWER_STATE || (pwr_idx == ~0)) { + ppm_warn("Invalid argument: state = %d, pwr_idx = %d\n", state, pwr_idx); + return -1; + } + + /* search whole tlp table */ + if (state == PPM_POWER_STATE_NONE) { + for_each_pwr_tbl_entry(i, power_table) { + if (power_table.power_tbl[i].power_idx <= pwr_idx) + return i; + } + } else { + state_info = ppm_get_power_state_info(); + tbl = state_info[state].pwr_sorted_tbl; + + for (i = 0; i < tbl->size; i++) { + if (tbl->sorted_tbl[i].value <= pwr_idx) + return tbl->sorted_tbl[i].advise_index; + } + } + + /* not found */ + return -1; +} + +enum ppm_power_state ppm_find_next_state(enum ppm_power_state state, + unsigned int *level, enum power_state_search_policy policy) +{ + const unsigned int *tbl; + enum ppm_power_state new_state; + int keep_going; + + ppm_ver("@%s: state = %s, lv = %d\n", __func__, ppm_get_power_state_name(state), *level); + + if (state >= NR_PPM_POWER_STATE || *level >= NR_PPM_POWER_STATE) + return PPM_POWER_STATE_NONE; + + tbl = (policy == PERFORMANCE) ? perf_idx_search_prio[state] : pwr_idx_search_prio[state]; + + do { + keep_going = 0; + + new_state = tbl[*level]; + + ppm_ver("@%s: new_state = %s, lv = %d\n", __func__, ppm_get_power_state_name(new_state), *level); + + if (new_state == PPM_POWER_STATE_NONE) + break; + + /* check fix root cluster setting */ + switch (ppm_main_info.fixed_root_cluster) { + case 0: + if (new_state == PPM_POWER_STATE_L_ONLY || new_state == PPM_POWER_STATE_4L_LL) { + (*level)++; + keep_going = 1; + } + break; + case 1: + if (new_state == PPM_POWER_STATE_LL_ONLY || new_state == PPM_POWER_STATE_4LL_L) { + (*level)++; + keep_going = 1; + } + break; + default: + break; + } + } while (keep_going); + + return new_state; +} + +int ppm_find_pwr_idx(struct ppm_cluster_status *cluster_status) +{ + int i; + struct ppm_power_tbl_data power_table = ppm_get_power_table(); + int core_1 = cluster_status[0].core_num; + int opp_1 = cluster_status[0].freq_idx; + int core_2 = cluster_status[1].core_num; + int opp_2 = cluster_status[1].freq_idx; + + ppm_dbg(DLPT, "@%s: core_1 = %d, opp_1 = %d, core_2 = %d, opp_2 = %d, volt_1 = %d, volt_2 = %d\n", + __func__, core_1, opp_1, core_2, opp_2, cluster_status[0].volt, cluster_status[1].volt); + + opp_1 = (!core_1) ? -1 : opp_1; + opp_2 = (!core_2) ? -1 : opp_2; + + /* sync opp to little one due to shared bulk*/ + if (opp_1 != -1 && opp_2 != -1) { + opp_1 = MIN(opp_1, opp_2); + opp_2 = MIN(opp_1, opp_2); + } + + for_each_pwr_tbl_entry(i, power_table) { + if (power_table.power_tbl[i].cluster_cfg[0].core_num == core_1 + && power_table.power_tbl[i].cluster_cfg[0].opp_lv == opp_1 + && power_table.power_tbl[i].cluster_cfg[1].core_num == core_2 + && power_table.power_tbl[i].cluster_cfg[1].opp_lv == opp_2 + ) { + ppm_dbg(DLPT, "[index][power] = [%d][%d]\n", + i, power_table.power_tbl[i].power_idx); + return power_table.power_tbl[i].power_idx; + } + } + + ppm_dbg(DLPT, "@%s: power_idx not found!\n", __func__); + + /* return -1 if not found */ + return -1; +} + +enum ppm_power_state ppm_judge_state_by_user_limit(enum ppm_power_state cur_state, + struct ppm_userlimit_data user_limit) +{ + enum ppm_power_state new_state = PPM_POWER_STATE_NONE; + int LL_core_min = user_limit.limit[0].min_core_num; + int LL_core_max = user_limit.limit[0].max_core_num; + int L_core_min = user_limit.limit[1].min_core_num; + int L_core_max = user_limit.limit[1].max_core_num; + int LL_freq_min = user_limit.limit[0].min_freq_idx; + int L_freq_max = user_limit.limit[1].max_freq_idx; + int sum = LL_core_min + L_core_min; + + ppm_ver("Judge: input --> [%s] (%d)(%d)(%d)(%d) [(%d)(%d)]\n", + ppm_get_power_state_name(cur_state), + LL_core_min, LL_core_max, L_core_min, L_core_max, LL_freq_min, L_freq_max); + + LL_core_max = (LL_core_max == -1) ? 4 : LL_core_max; + L_core_max = (L_core_max == -1) ? 4 : L_core_max; + + /* need to check freq limit for cluster move/merge */ + if (cur_state == PPM_POWER_STATE_LL_ONLY || cur_state == PPM_POWER_STATE_L_ONLY) { + struct ppm_power_state_data *state_info = ppm_get_power_state_info(); + + LL_freq_min = (LL_freq_min == -1) + ? state_info[cur_state].cluster_limit->state_limit[0].min_cpufreq_idx + : LL_freq_min; + L_freq_max = (L_freq_max == -1) + ? state_info[cur_state].cluster_limit->state_limit[1].max_cpufreq_idx + : L_freq_max; + /* idx -> freq */ + LL_freq_min = (ppm_main_info.cluster_info[0].dvfs_tbl) + ? ppm_main_info.cluster_info[0].dvfs_tbl[LL_freq_min].frequency + : get_cluster_min_cpufreq_idx(0); + L_freq_max = (ppm_main_info.cluster_info[1].dvfs_tbl) + ? ppm_main_info.cluster_info[1].dvfs_tbl[L_freq_max].frequency + : get_cluster_max_cpufreq_idx(1); + } + + /* min_core <= 0: don't care */ + /* min_core > 0: turn on this cluster */ + /* max_core == 0: turn off this cluster */ + switch (cur_state) { + case PPM_POWER_STATE_LL_ONLY: + new_state = (LL_core_max == 0) ? PPM_POWER_STATE_L_ONLY + : (L_core_min <= 0 || L_core_max == 0) ? cur_state + /* should not go to L only due to root cluster is fixed at LL */ + : (L_core_min > 0 && ppm_main_info.fixed_root_cluster == 0) ? PPM_POWER_STATE_4LL_L + : (LL_core_min <= 0) ? PPM_POWER_STATE_L_ONLY + : (LL_core_min == 4) ? PPM_POWER_STATE_4LL_L + : (L_core_min == 4) ? PPM_POWER_STATE_4L_LL + /* merge to L cluster */ + : (sum <= L_core_max && L_freq_max >= LL_freq_min) ? PPM_POWER_STATE_L_ONLY + : PPM_POWER_STATE_NONE; + break; + case PPM_POWER_STATE_L_ONLY: + new_state = (L_core_max == 0) ? PPM_POWER_STATE_LL_ONLY + : (LL_core_min <= 0 || LL_core_max == 0) ? cur_state + /* keep current if for only LL min is set */ + : (LL_core_min > 0 && L_core_min == -1 && L_freq_max >= LL_freq_min) ? cur_state + /* will return NONE if LL min is set but L min is not */ + : (L_core_min == 4) ? PPM_POWER_STATE_4L_LL + : (LL_core_min == 4) ? PPM_POWER_STATE_4LL_L + /* merge to L cluster */ + : (sum <= L_core_max && L_freq_max >= LL_freq_min) ? cur_state + : PPM_POWER_STATE_NONE; + break; + case PPM_POWER_STATE_4LL_L: + new_state = (L_core_max == 0) ? PPM_POWER_STATE_LL_ONLY + : (LL_core_max == 0) ? PPM_POWER_STATE_L_ONLY + : (L_core_min == 4) ? PPM_POWER_STATE_4L_LL + : (LL_core_max == 4) ? cur_state + : PPM_POWER_STATE_NONE; + break; + case PPM_POWER_STATE_4L_LL: + new_state = (LL_core_max == 0) ? PPM_POWER_STATE_L_ONLY + : (L_core_max == 0) ? PPM_POWER_STATE_LL_ONLY + : (L_core_max == 4) ? cur_state + : (L_core_max < 4 && LL_core_min == 4) ? PPM_POWER_STATE_4LL_L + : PPM_POWER_STATE_NONE; + break; + default: + break; + } + + /* check root cluster is fixed or not */ + switch (ppm_main_info.fixed_root_cluster) { + case 0: + new_state = (new_state == PPM_POWER_STATE_L_ONLY) ? PPM_POWER_STATE_NONE + : (new_state == PPM_POWER_STATE_4L_LL) ? PPM_POWER_STATE_4LL_L + : new_state; + break; + case 1: + new_state = (new_state == PPM_POWER_STATE_LL_ONLY) ? PPM_POWER_STATE_NONE + : (new_state == PPM_POWER_STATE_4LL_L) ? PPM_POWER_STATE_4L_LL + : new_state; + break; + default: + break; + } + + ppm_ver("Judge: output --> [%s]\n", ppm_get_power_state_name(new_state)); + + return new_state; +} + +/* modify request to fit cur_state */ +void ppm_limit_check_for_user_limit(enum ppm_power_state cur_state, struct ppm_policy_req *req, + struct ppm_userlimit_data user_limit) +{ + if (req && cur_state == PPM_POWER_STATE_L_ONLY) { + unsigned int LL_min_core = req->limit[0].min_cpu_core; + unsigned int L_min_core = req->limit[1].min_cpu_core; + unsigned int sum = LL_min_core + L_min_core; + unsigned int LL_min_freq, L_min_freq, L_max_freq; + + LL_min_freq = (ppm_main_info.cluster_info[0].dvfs_tbl) + ? ppm_main_info.cluster_info[0].dvfs_tbl[req->limit[0].min_cpufreq_idx].frequency + : get_cluster_min_cpufreq_idx(0); + L_min_freq = (ppm_main_info.cluster_info[1].dvfs_tbl) + ? ppm_main_info.cluster_info[1].dvfs_tbl[req->limit[1].min_cpufreq_idx].frequency + : get_cluster_min_cpufreq_idx(1); + L_max_freq = (ppm_main_info.cluster_info[1].dvfs_tbl) + ? ppm_main_info.cluster_info[1].dvfs_tbl[req->limit[1].max_cpufreq_idx].frequency + : get_cluster_max_cpufreq_idx(1); + + if (LL_min_core > 0 && L_max_freq >= LL_min_freq) { + /* user do not set L min so we just move LL core to L */ + if (user_limit.limit[1].min_core_num <= 0) { + req->limit[0].min_cpu_core = 0; + req->limit[1].min_cpu_core = LL_min_core; + ppm_ver("Judge: move LL min core to L = %d\n", LL_min_core); + } else if (sum <= 4) { + req->limit[0].min_cpu_core = 0; + req->limit[1].min_cpu_core = sum; + ppm_ver("Judge: merge LL and L min core = %d\n", sum); +#ifdef PPM_IC_SEGMENT_CHECK + } else if (ppm_main_info.fix_state_by_segment == PPM_POWER_STATE_L_ONLY) { + req->limit[0].min_cpu_core = 0; + req->limit[1].min_cpu_core = min(sum, get_cluster_max_cpu_core(1)); + ppm_ver("Judge: merge LL and L min core = %d(sum = %d)\n", + req->limit[1].min_cpu_core, sum); +#endif + } else { + ppm_ver("Judge: cannot merge to L! LL min = %d, L min = %d\n", + LL_min_core, L_min_core); + /* check LL max core */ + if (req->limit[0].max_cpu_core < LL_min_core) + req->limit[0].max_cpu_core = LL_min_core; + + return; + } + + if (LL_min_freq > L_min_freq) { + req->limit[1].min_cpufreq_idx = + ppm_main_freq_to_idx(1, LL_min_freq, CPUFREQ_RELATION_L); + ppm_ver("Judge: change L min freq idx to %d due to LL min freq = %d\n", + req->limit[1].min_cpufreq_idx, LL_min_freq); + } + } + } +} + +unsigned int ppm_get_root_cluster_by_state(enum ppm_power_state cur_state) +{ + unsigned int root_cluster = 0; + + switch (cur_state) { + case PPM_POWER_STATE_L_ONLY: + case PPM_POWER_STATE_4L_LL: + root_cluster = 1; + break; + case PPM_POWER_STATE_NONE: + root_cluster = (ppm_main_info.fixed_root_cluster == -1) ? 0 + : (unsigned int)ppm_main_info.fixed_root_cluster; + break; + case PPM_POWER_STATE_LL_ONLY: + case PPM_POWER_STATE_4LL_L: + default: + break; + } + + return root_cluster; +} + +#ifdef PPM_IC_SEGMENT_CHECK +enum ppm_power_state ppm_check_fix_state_by_segment(void) +{ + unsigned int segment = get_devinfo_with_index(21) & 0xFF; + enum ppm_power_state fix_state = PPM_POWER_STATE_NONE; + + switch (segment) { + case 0x43: /* fix L only */ + case 0x4B: + fix_state = PPM_POWER_STATE_L_ONLY; + break; + default: + break; + } + + ppm_info("segment = 0x%x, fix_state = %s\n", segment, ppm_get_power_state_name(fix_state)); + + return fix_state; +} +#endif + diff --git a/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_power_table.h b/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_power_table.h new file mode 100644 index 0000000000000000000000000000000000000000..8b8e80a4e9b54e0e6c63060f8e088d7521f4eff3 --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v1/src/mach/mt6755/mt_ppm_power_table.h @@ -0,0 +1,835 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +static const struct ppm_sorted_pwr_tbl state_pwr_tbl_LL_ONLY_FY[] = { + SORT_TBL_ELEMENT(50, 613, 50), + SORT_TBL_ELEMENT(56, 520, 56), + SORT_TBL_ELEMENT(61, 468, 67), + SORT_TBL_ELEMENT(67, 436, 67), + SORT_TBL_ELEMENT(69, 397, 77), + SORT_TBL_ELEMENT(74, 333, 77), + SORT_TBL_ELEMENT(75, 323, 77), + SORT_TBL_ELEMENT(77, 314, 77), + SORT_TBL_ELEMENT(79, 274, 83), + SORT_TBL_ELEMENT(83, 256, 83), + SORT_TBL_ELEMENT(86, 239, 86), + SORT_TBL_ELEMENT(87, 230, 93), + SORT_TBL_ELEMENT(93, 201, 93), + SORT_TBL_ELEMENT(94, 196, 94), + SORT_TBL_ELEMENT(96, 178, 100), + SORT_TBL_ELEMENT(98, 165, 100), + SORT_TBL_ELEMENT(100, 153, 100), + SORT_TBL_ELEMENT(101, 151, 104), + SORT_TBL_ELEMENT(102, 135, 104), + SORT_TBL_ELEMENT(104, 132, 104), + SORT_TBL_ELEMENT(106, 126, 109), + SORT_TBL_ELEMENT(108, 106, 109), + SORT_TBL_ELEMENT(109, 101, 109), + SORT_TBL_ELEMENT(110, 91, 110), + SORT_TBL_ELEMENT(111, 74, 112), + SORT_TBL_ELEMENT(112, 70, 112), + SORT_TBL_ELEMENT(114, 66, 114), + SORT_TBL_ELEMENT(115, 58, 115), + SORT_TBL_ELEMENT(116, 51, 116), + SORT_TBL_ELEMENT(117, 39, 117), + SORT_TBL_ELEMENT(118, 35, 118), + SORT_TBL_ELEMENT(119, 20, 119), +}; +STATE_PWR_TBL(LL_ONLY, FY); + +static const struct ppm_sorted_pwr_tbl state_perf_tbl_LL_ONLY_FY[] = { + SORT_TBL_ELEMENT(50, 2002, 0xFF), + SORT_TBL_ELEMENT(56, 1820, 0xFF), + SORT_TBL_ELEMENT(67, 1638, 0xFF), + SORT_TBL_ELEMENT(61, 1501, 0xFF), + SORT_TBL_ELEMENT(77, 1378, 0xFF), + SORT_TBL_ELEMENT(69, 1365, 0xFF), + SORT_TBL_ELEMENT(74, 1229, 0xFF), + SORT_TBL_ELEMENT(83, 1196, 0xFF), + SORT_TBL_ELEMENT(86, 1034, 0xFF), + SORT_TBL_ELEMENT(75, 1001, 0xFF), + SORT_TBL_ELEMENT(93, 988, 0xFF), + SORT_TBL_ELEMENT(79, 910, 0xFF), + SORT_TBL_ELEMENT(94, 897, 0xFF), + SORT_TBL_ELEMENT(87, 819, 0xFF), + SORT_TBL_ELEMENT(100, 741, 0xFF), + SORT_TBL_ELEMENT(98, 689, 0xFF), + SORT_TBL_ELEMENT(104, 676, 0xFF), + SORT_TBL_ELEMENT(102, 598, 0xFF), + SORT_TBL_ELEMENT(109, 507, 0xFF), + SORT_TBL_ELEMENT(96, 500, 0xFF), + SORT_TBL_ELEMENT(108, 494, 0xFF), + SORT_TBL_ELEMENT(101, 455, 0xFF), + SORT_TBL_ELEMENT(106, 410, 0xFF), + SORT_TBL_ELEMENT(110, 345, 0xFF), + SORT_TBL_ELEMENT(112, 338, 0xFF), + SORT_TBL_ELEMENT(114, 312, 0xFF), + SORT_TBL_ELEMENT(111, 299, 0xFF), + SORT_TBL_ELEMENT(115, 247, 0xFF), + SORT_TBL_ELEMENT(116, 234, 0xFF), + SORT_TBL_ELEMENT(117, 169, 0xFF), + SORT_TBL_ELEMENT(118, 156, 0xFF), + SORT_TBL_ELEMENT(119, 78, 0xFF), +}; +STATE_PERF_TBL(LL_ONLY, FY); + +static const struct ppm_sorted_pwr_tbl state_pwr_tbl_L_ONLY_FY[] = { + SORT_TBL_ELEMENT(8, 1758, 8), + SORT_TBL_ELEMENT(14, 1498, 14), + SORT_TBL_ELEMENT(18, 1349, 20), + SORT_TBL_ELEMENT(20, 1263, 20), + SORT_TBL_ELEMENT(22, 1150, 22), + SORT_TBL_ELEMENT(29, 970, 34), + SORT_TBL_ELEMENT(32, 941, 34), + SORT_TBL_ELEMENT(34, 871, 34), + SORT_TBL_ELEMENT(37, 802, 43), + SORT_TBL_ELEMENT(43, 709, 43), + SORT_TBL_ELEMENT(44, 676, 46), + SORT_TBL_ELEMENT(46, 669, 46), + SORT_TBL_ELEMENT(52, 569, 52), + SORT_TBL_ELEMENT(53, 544, 53), + SORT_TBL_ELEMENT(55, 532, 68), + SORT_TBL_ELEMENT(62, 467, 68), + SORT_TBL_ELEMENT(63, 454, 68), + SORT_TBL_ELEMENT(66, 438, 68), + SORT_TBL_ELEMENT(68, 412, 68), + SORT_TBL_ELEMENT(70, 383, 71), + SORT_TBL_ELEMENT(71, 380, 71), + SORT_TBL_ELEMENT(76, 317, 76), + SORT_TBL_ELEMENT(78, 306, 78), + SORT_TBL_ELEMENT(81, 264, 90), + SORT_TBL_ELEMENT(90, 222, 90), + SORT_TBL_ELEMENT(91, 216, 92), + SORT_TBL_ELEMENT(92, 205, 92), + SORT_TBL_ELEMENT(97, 174, 97), + SORT_TBL_ELEMENT(99, 159, 99), + SORT_TBL_ELEMENT(105, 128, 105), + SORT_TBL_ELEMENT(107, 113, 107), + SORT_TBL_ELEMENT(113, 67, 113), +}; +STATE_PWR_TBL(L_ONLY, FY); + +static const struct ppm_sorted_pwr_tbl state_perf_tbl_L_ONLY_FY[] = { + SORT_TBL_ELEMENT(8, 3614, 0xFF), + SORT_TBL_ELEMENT(14, 3302, 0xFF), + SORT_TBL_ELEMENT(20, 2990, 0xFF), + SORT_TBL_ELEMENT(18, 2711, 0xFF), + SORT_TBL_ELEMENT(22, 2477, 0xFF), + SORT_TBL_ELEMENT(34, 2392, 0xFF), + SORT_TBL_ELEMENT(29, 2243, 0xFF), + SORT_TBL_ELEMENT(43, 2054, 0xFF), + SORT_TBL_ELEMENT(32, 1807, 0xFF), + SORT_TBL_ELEMENT(46, 1794, 0xFF), + SORT_TBL_ELEMENT(52, 1742, 0xFF), + SORT_TBL_ELEMENT(37, 1651, 0xFF), + SORT_TBL_ELEMENT(53, 1541, 0xFF), + SORT_TBL_ELEMENT(44, 1495, 0xFF), + SORT_TBL_ELEMENT(68, 1326, 0xFF), + SORT_TBL_ELEMENT(66, 1307, 0xFF), + SORT_TBL_ELEMENT(62, 1196, 0xFF), + SORT_TBL_ELEMENT(71, 1027, 0xFF), + SORT_TBL_ELEMENT(76, 995, 0xFF), + SORT_TBL_ELEMENT(55, 904, 0xFF), + SORT_TBL_ELEMENT(78, 871, 0xFF), + SORT_TBL_ELEMENT(63, 826, 0xFF), + SORT_TBL_ELEMENT(70, 748, 0xFF), + SORT_TBL_ELEMENT(90, 663, 0xFF), + SORT_TBL_ELEMENT(81, 598, 0xFF), + SORT_TBL_ELEMENT(92, 572, 0xFF), + SORT_TBL_ELEMENT(91, 514, 0xFF), + SORT_TBL_ELEMENT(97, 436, 0xFF), + SORT_TBL_ELEMENT(99, 429, 0xFF), + SORT_TBL_ELEMENT(105, 332, 0xFF), + SORT_TBL_ELEMENT(107, 286, 0xFF), + SORT_TBL_ELEMENT(113, 143, 0xFF), +}; +STATE_PERF_TBL(L_ONLY, FY); + +static const struct ppm_sorted_pwr_tbl state_pwr_tbl_4LL_L_FY[] = { + SORT_TBL_ELEMENT(0, 2371, 0), + SORT_TBL_ELEMENT(3, 2018, 3), + SORT_TBL_ELEMENT(4, 1962, 4), + SORT_TBL_ELEMENT(9, 1699, 9), + SORT_TBL_ELEMENT(10, 1670, 10), + SORT_TBL_ELEMENT(13, 1554, 16), + SORT_TBL_ELEMENT(16, 1406, 16), + SORT_TBL_ELEMENT(19, 1322, 21), + SORT_TBL_ELEMENT(21, 1185, 21), + SORT_TBL_ELEMENT(23, 1145, 30), + SORT_TBL_ELEMENT(24, 1112, 30), + SORT_TBL_ELEMENT(27, 983, 30), + SORT_TBL_ELEMENT(28, 974, 30), + SORT_TBL_ELEMENT(30, 965, 30), + SORT_TBL_ELEMENT(36, 819, 38), + SORT_TBL_ELEMENT(38, 801, 38), + SORT_TBL_ELEMENT(40, 780, 41), + SORT_TBL_ELEMENT(41, 770, 41), + SORT_TBL_ELEMENT(47, 638, 47), + SORT_TBL_ELEMENT(48, 637, 48), + SORT_TBL_ELEMENT(51, 578, 54), + SORT_TBL_ELEMENT(54, 544, 54), + SORT_TBL_ELEMENT(58, 507, 58), + SORT_TBL_ELEMENT(60, 472, 60), + SORT_TBL_ELEMENT(65, 449, 65), + SORT_TBL_ELEMENT(72, 375, 72), + SORT_TBL_ELEMENT(73, 354, 73), + SORT_TBL_ELEMENT(80, 271, 82), + SORT_TBL_ELEMENT(82, 260, 82), + SORT_TBL_ELEMENT(88, 225, 88), + SORT_TBL_ELEMENT(95, 179, 95), + SORT_TBL_ELEMENT(103, 133, 103), +}; +STATE_PWR_TBL(4LL_L, FY); + +static const struct ppm_sorted_pwr_tbl state_perf_tbl_4LL_L_FY[] = { + SORT_TBL_ELEMENT(0, 5616, 0xFF), + SORT_TBL_ELEMENT(3, 5122, 0xFF), + SORT_TBL_ELEMENT(4, 4713, 0xFF), + SORT_TBL_ELEMENT(9, 4628, 0xFF), + SORT_TBL_ELEMENT(10, 4297, 0xFF), + SORT_TBL_ELEMENT(16, 3881, 0xFF), + SORT_TBL_ELEMENT(13, 3809, 0xFF), + SORT_TBL_ELEMENT(21, 3770, 0xFF), + SORT_TBL_ELEMENT(19, 3471, 0xFF), + SORT_TBL_ELEMENT(30, 3250, 0xFF), + SORT_TBL_ELEMENT(27, 3172, 0xFF), + SORT_TBL_ELEMENT(24, 3133, 0xFF), + SORT_TBL_ELEMENT(23, 2906, 0xFF), + SORT_TBL_ELEMENT(38, 2737, 0xFF), + SORT_TBL_ELEMENT(41, 2730, 0xFF), + SORT_TBL_ELEMENT(28, 2646, 0xFF), + SORT_TBL_ELEMENT(40, 2574, 0xFF), + SORT_TBL_ELEMENT(36, 2386, 0xFF), + SORT_TBL_ELEMENT(47, 2295, 0xFF), + SORT_TBL_ELEMENT(48, 2223, 0xFF), + SORT_TBL_ELEMENT(54, 2002, 0xFF), + SORT_TBL_ELEMENT(51, 1976, 0xFF), + SORT_TBL_ELEMENT(58, 1859, 0xFF), + SORT_TBL_ELEMENT(60, 1710, 0xFF), + SORT_TBL_ELEMENT(65, 1671, 0xFF), + SORT_TBL_ELEMENT(72, 1424, 0xFF), + SORT_TBL_ELEMENT(73, 1339, 0xFF), + SORT_TBL_ELEMENT(82, 1008, 0xFF), + SORT_TBL_ELEMENT(80, 884, 0xFF), + SORT_TBL_ELEMENT(88, 741, 0xFF), + SORT_TBL_ELEMENT(95, 598, 0xFF), + SORT_TBL_ELEMENT(103, 455, 0xFF), +}; +STATE_PERF_TBL(4LL_L, FY); + +static const struct ppm_sorted_pwr_tbl state_pwr_tbl_4L_LL_FY[] = { + SORT_TBL_ELEMENT(0, 2371, 0), + SORT_TBL_ELEMENT(1, 2226, 3), + SORT_TBL_ELEMENT(2, 2081, 3), + SORT_TBL_ELEMENT(3, 2018, 3), + SORT_TBL_ELEMENT(5, 1936, 6), + SORT_TBL_ELEMENT(6, 1895, 6), + SORT_TBL_ELEMENT(7, 1772, 9), + SORT_TBL_ELEMENT(9, 1699, 9), + SORT_TBL_ELEMENT(11, 1649, 12), + SORT_TBL_ELEMENT(12, 1596, 12), + SORT_TBL_ELEMENT(15, 1493, 15), + SORT_TBL_ELEMENT(17, 1390, 21), + SORT_TBL_ELEMENT(21, 1185, 21), + SORT_TBL_ELEMENT(25, 1111, 25), + SORT_TBL_ELEMENT(26, 1037, 30), + SORT_TBL_ELEMENT(30, 965, 30), + SORT_TBL_ELEMENT(31, 962, 33), + SORT_TBL_ELEMENT(33, 904, 33), + SORT_TBL_ELEMENT(35, 844, 41), + SORT_TBL_ELEMENT(39, 783, 41), + SORT_TBL_ELEMENT(41, 770, 41), + SORT_TBL_ELEMENT(42, 722, 42), + SORT_TBL_ELEMENT(45, 675, 45), + SORT_TBL_ELEMENT(49, 628, 54), + SORT_TBL_ELEMENT(54, 544, 54), + SORT_TBL_ELEMENT(57, 513, 57), + SORT_TBL_ELEMENT(59, 482, 59), + SORT_TBL_ELEMENT(64, 451, 64), + SORT_TBL_ELEMENT(80, 271, 80), + SORT_TBL_ELEMENT(84, 255, 84), + SORT_TBL_ELEMENT(85, 240, 85), + SORT_TBL_ELEMENT(89, 224, 89), +}; +STATE_PWR_TBL(4L_LL, FY); + +static const struct ppm_sorted_pwr_tbl state_perf_tbl_4L_LL_FY[] = { + SORT_TBL_ELEMENT(0, 5616, 0xFF), + SORT_TBL_ELEMENT(3, 5122, 0xFF), + SORT_TBL_ELEMENT(1, 5116, 0xFF), + SORT_TBL_ELEMENT(6, 4667, 0xFF), + SORT_TBL_ELEMENT(9, 4628, 0xFF), + SORT_TBL_ELEMENT(2, 4615, 0xFF), + SORT_TBL_ELEMENT(12, 4219, 0xFF), + SORT_TBL_ELEMENT(7, 4212, 0xFF), + SORT_TBL_ELEMENT(5, 4115, 0xFF), + SORT_TBL_ELEMENT(15, 3809, 0xFF), + SORT_TBL_ELEMENT(21, 3770, 0xFF), + SORT_TBL_ELEMENT(11, 3757, 0xFF), + SORT_TBL_ELEMENT(25, 3426, 0xFF), + SORT_TBL_ELEMENT(17, 3400, 0xFF), + SORT_TBL_ELEMENT(30, 3250, 0xFF), + SORT_TBL_ELEMENT(26, 3081, 0xFF), + SORT_TBL_ELEMENT(33, 2951, 0xFF), + SORT_TBL_ELEMENT(31, 2737, 0xFF), + SORT_TBL_ELEMENT(41, 2730, 0xFF), + SORT_TBL_ELEMENT(35, 2652, 0xFF), + SORT_TBL_ELEMENT(42, 2483, 0xFF), + SORT_TBL_ELEMENT(39, 2353, 0xFF), + SORT_TBL_ELEMENT(45, 2236, 0xFF), + SORT_TBL_ELEMENT(54, 2002, 0xFF), + SORT_TBL_ELEMENT(49, 1989, 0xFF), + SORT_TBL_ELEMENT(57, 1833, 0xFF), + SORT_TBL_ELEMENT(59, 1664, 0xFF), + SORT_TBL_ELEMENT(64, 1495, 0xFF), + SORT_TBL_ELEMENT(80, 884, 0xFF), + SORT_TBL_ELEMENT(84, 806, 0xFF), + SORT_TBL_ELEMENT(85, 728, 0xFF), + SORT_TBL_ELEMENT(89, 650, 0xFF), +}; +STATE_PERF_TBL(4L_LL, FY); + +static const struct ppm_power_tbl cpu_tlp_power_tbl_FY[] = { + {0, {{0, 4}, {0, 4},}, 5616, 2371}, + {1, {{0, 3}, {0, 4},}, 5116, 2226}, + {2, {{0, 2}, {0, 4},}, 4615, 2081}, + {3, {{1, 4}, {1, 4},}, 5122, 2018}, + {4, {{0, 4}, {0, 3},}, 4713, 1962}, + {5, {{0, 1}, {0, 4},}, 4115, 1936}, + {6, {{1, 3}, {1, 4},}, 4667, 1895}, + {7, {{1, 2}, {1, 4},}, 4212, 1772}, + {8, {{-1, 0}, {0, 4},}, 3614, 1758}, + {9, {{2, 4}, {2, 4},}, 4628, 1699}, + {10, {{1, 4}, {1, 3},}, 4297, 1670}, + {11, {{1, 1}, {1, 4},}, 3757, 1649}, + {12, {{2, 3}, {2, 4},}, 4219, 1596}, + {13, {{0, 4}, {0, 2},}, 3809, 1554}, + {14, {{-1, 0}, {1, 4},}, 3302, 1498}, + {15, {{2, 2}, {2, 4},}, 3809, 1493}, + {16, {{2, 4}, {2, 3},}, 3881, 1406}, + {17, {{2, 1}, {2, 4},}, 3400, 1390}, + {18, {{-1, 0}, {0, 3},}, 2711, 1349}, + {19, {{1, 4}, {1, 2},}, 3471, 1322}, + {20, {{-1, 0}, {2, 4},}, 2990, 1263}, + {21, {{3, 4}, {3, 4},}, 3770, 1185}, + {22, {{-1, 0}, {1, 3},}, 2477, 1150}, + {23, {{0, 4}, {0, 1},}, 2906, 1145}, + {24, {{2, 4}, {2, 2},}, 3133, 1112}, + {25, {{3, 3}, {3, 4},}, 3426, 1111}, + {26, {{3, 2}, {3, 4},}, 3081, 1037}, + {27, {{3, 4}, {3, 3},}, 3172, 983}, + {28, {{1, 4}, {1, 1},}, 2646, 974}, + {29, {{-1, 0}, {2, 3},}, 2243, 970}, + {30, {{4, 4}, {4, 4},}, 3250, 965}, + {31, {{3, 1}, {3, 4},}, 2737, 962}, + {32, {{-1, 0}, {0, 2},}, 1807, 941}, + {33, {{4, 3}, {4, 4},}, 2951, 904}, + {34, {{-1, 0}, {3, 4},}, 2392, 871}, + {35, {{4, 2}, {4, 4},}, 2652, 844}, + {36, {{2, 4}, {2, 1},}, 2386, 819}, + {37, {{-1, 0}, {1, 2},}, 1651, 802}, + {38, {{4, 4}, {4, 3},}, 2737, 801}, + {39, {{4, 1}, {4, 4},}, 2353, 783}, + {40, {{3, 4}, {3, 2},}, 2574, 780}, + {41, {{5, 4}, {5, 4},}, 2730, 770}, + {42, {{5, 3}, {5, 4},}, 2483, 722}, + {43, {{-1, 0}, {4, 4},}, 2054, 709}, + {44, {{-1, 0}, {2, 2},}, 1495, 676}, + {45, {{5, 2}, {5, 4},}, 2236, 675}, + {46, {{-1, 0}, {3, 3},}, 1794, 669}, + {47, {{5, 4}, {5, 3},}, 2295, 638}, + {48, {{4, 4}, {4, 2},}, 2223, 637}, + {49, {{5, 1}, {5, 4},}, 1989, 628}, + {50, {{0, 4}, {-1, 0},}, 2002, 613}, + {51, {{3, 4}, {3, 1},}, 1976, 578}, + {52, {{-1, 0}, {5, 4},}, 1742, 569}, + {53, {{-1, 0}, {4, 3},}, 1541, 544}, + {54, {{6, 4}, {6, 4},}, 2002, 544}, + {55, {{-1, 0}, {0, 1},}, 904, 532}, + {56, {{1, 4}, {-1, 0},}, 1820, 520}, + {57, {{6, 3}, {6, 4},}, 1833, 513}, + {58, {{5, 4}, {5, 2},}, 1859, 507}, + {59, {{6, 2}, {6, 4},}, 1664, 482}, + {60, {{4, 4}, {4, 1},}, 1710, 472}, + {61, {{0, 3}, {-1, 0},}, 1501, 468}, + {62, {{-1, 0}, {3, 2},}, 1196, 467}, + {63, {{-1, 0}, {1, 1},}, 826, 454}, + {64, {{6, 1}, {6, 4},}, 1495, 451}, + {65, {{6, 4}, {6, 3},}, 1671, 449}, + {66, {{-1, 0}, {5, 3},}, 1307, 438}, + {67, {{2, 4}, {-1, 0},}, 1638, 436}, + {68, {{-1, 0}, {6, 4},}, 1326, 412}, + {69, {{1, 3}, {-1, 0},}, 1365, 397}, + {70, {{-1, 0}, {2, 1},}, 748, 383}, + {71, {{-1, 0}, {4, 2},}, 1027, 380}, + {72, {{5, 4}, {5, 1},}, 1424, 375}, + {73, {{6, 4}, {6, 2},}, 1339, 354}, + {74, {{2, 3}, {-1, 0},}, 1229, 333}, + {75, {{0, 2}, {-1, 0},}, 1001, 323}, + {76, {{-1, 0}, {6, 3},}, 995, 317}, + {77, {{3, 4}, {-1, 0},}, 1378, 314}, + {78, {{-1, 0}, {5, 2},}, 871, 306}, + {79, {{1, 2}, {-1, 0},}, 910, 274}, + {80, {{7, 4}, {7, 4},}, 884, 271}, + {81, {{-1, 0}, {3, 1},}, 598, 264}, + {82, {{6, 4}, {6, 1},}, 1008, 260}, + {83, {{4, 4}, {-1, 0},}, 1196, 256}, + {84, {{7, 3}, {7, 4},}, 806, 255}, + {85, {{7, 2}, {7, 4},}, 728, 240}, + {86, {{3, 3}, {-1, 0},}, 1034, 239}, + {87, {{2, 2}, {-1, 0},}, 819, 230}, + {88, {{7, 4}, {7, 3},}, 741, 225}, + {89, {{7, 1}, {7, 4},}, 650, 224}, + {90, {{-1, 0}, {6, 2},}, 663, 222}, + {91, {{-1, 0}, {4, 1},}, 514, 216}, + {92, {{-1, 0}, {7, 4},}, 572, 205}, + {93, {{5, 4}, {-1, 0},}, 988, 201}, + {94, {{4, 3}, {-1, 0},}, 897, 196}, + {95, {{7, 4}, {7, 2},}, 598, 179}, + {96, {{0, 1}, {-1, 0},}, 500, 178}, + {97, {{-1, 0}, {5, 1},}, 436, 174}, + {98, {{3, 2}, {-1, 0},}, 689, 165}, + {99, {{-1, 0}, {7, 3},}, 429, 159}, + {100, {{5, 3}, {-1, 0},}, 741, 153}, + {101, {{1, 1}, {-1, 0},}, 455, 151}, + {102, {{4, 2}, {-1, 0},}, 598, 135}, + {103, {{7, 4}, {7, 1},}, 455, 133}, + {104, {{6, 4}, {-1, 0},}, 676, 132}, + {105, {{-1, 0}, {6, 1},}, 332, 128}, + {106, {{2, 1}, {-1, 0},}, 410, 126}, + {107, {{-1, 0}, {7, 2},}, 286, 113}, + {108, {{5, 2}, {-1, 0},}, 494, 106}, + {109, {{6, 3}, {-1, 0},}, 507, 101}, + {110, {{3, 1}, {-1, 0},}, 345, 91}, + {111, {{4, 1}, {-1, 0},}, 299, 74}, + {112, {{6, 2}, {-1, 0},}, 338, 70}, + {113, {{-1, 0}, {7, 1},}, 143, 67}, + {114, {{7, 4}, {-1, 0},}, 312, 66}, + {115, {{5, 1}, {-1, 0},}, 247, 58}, + {116, {{7, 3}, {-1, 0},}, 234, 51}, + {117, {{6, 1}, {-1, 0},}, 169, 39}, + {118, {{7, 2}, {-1, 0},}, 156, 35}, + {119, {{7, 1}, {-1, 0},}, 78, 20}, +}; + +static const struct ppm_sorted_pwr_tbl state_pwr_tbl_LL_ONLY_SB[] = { + SORT_TBL_ELEMENT(47, 785, 47), + SORT_TBL_ELEMENT(54, 655, 54), + SORT_TBL_ELEMENT(59, 599, 66), + SORT_TBL_ELEMENT(66, 530, 66), + SORT_TBL_ELEMENT(68, 500, 68), + SORT_TBL_ELEMENT(74, 413, 78), + SORT_TBL_ELEMENT(75, 405, 78), + SORT_TBL_ELEMENT(78, 366, 78), + SORT_TBL_ELEMENT(79, 345, 82), + SORT_TBL_ELEMENT(82, 301, 82), + SORT_TBL_ELEMENT(83, 280, 83), + SORT_TBL_ELEMENT(84, 279, 90), + SORT_TBL_ELEMENT(90, 238, 90), + SORT_TBL_ELEMENT(91, 230, 91), + SORT_TBL_ELEMENT(92, 228, 99), + SORT_TBL_ELEMENT(97, 193, 99), + SORT_TBL_ELEMENT(98, 190, 99), + SORT_TBL_ELEMENT(99, 182, 99), + SORT_TBL_ELEMENT(101, 159, 101), + SORT_TBL_ELEMENT(102, 159, 102), + SORT_TBL_ELEMENT(105, 154, 108), + SORT_TBL_ELEMENT(107, 125, 108), + SORT_TBL_ELEMENT(108, 121, 108), + SORT_TBL_ELEMENT(110, 106, 110), + SORT_TBL_ELEMENT(111, 88, 112), + SORT_TBL_ELEMENT(112, 84, 112), + SORT_TBL_ELEMENT(113, 69, 115), + SORT_TBL_ELEMENT(115, 66, 115), + SORT_TBL_ELEMENT(116, 51, 116), + SORT_TBL_ELEMENT(117, 47, 117), + SORT_TBL_ELEMENT(118, 35, 118), + SORT_TBL_ELEMENT(119, 20, 119), +}; +STATE_PWR_TBL(LL_ONLY, SB); + +static const struct ppm_sorted_pwr_tbl state_perf_tbl_LL_ONLY_SB[] = { + SORT_TBL_ELEMENT(47, 2288, 0xFF), + SORT_TBL_ELEMENT(54, 2028, 0xFF), + SORT_TBL_ELEMENT(66, 1742, 0xFF), + SORT_TBL_ELEMENT(59, 1716, 0xFF), + SORT_TBL_ELEMENT(68, 1521, 0xFF), + SORT_TBL_ELEMENT(78, 1378, 0xFF), + SORT_TBL_ELEMENT(75, 1307, 0xFF), + SORT_TBL_ELEMENT(82, 1196, 0xFF), + SORT_TBL_ELEMENT(74, 1144, 0xFF), + SORT_TBL_ELEMENT(83, 1034, 0xFF), + SORT_TBL_ELEMENT(79, 1014, 0xFF), + SORT_TBL_ELEMENT(90, 988, 0xFF), + SORT_TBL_ELEMENT(91, 897, 0xFF), + SORT_TBL_ELEMENT(84, 871, 0xFF), + SORT_TBL_ELEMENT(99, 741, 0xFF), + SORT_TBL_ELEMENT(97, 689, 0xFF), + SORT_TBL_ELEMENT(101, 676, 0xFF), + SORT_TBL_ELEMENT(102, 598, 0xFF), + SORT_TBL_ELEMENT(92, 572, 0xFF), + SORT_TBL_ELEMENT(98, 507, 0xFF), + SORT_TBL_ELEMENT(108, 507, 0xFF), + SORT_TBL_ELEMENT(107, 494, 0xFF), + SORT_TBL_ELEMENT(105, 436, 0xFF), + SORT_TBL_ELEMENT(110, 345, 0xFF), + SORT_TBL_ELEMENT(112, 338, 0xFF), + SORT_TBL_ELEMENT(115, 312, 0xFF), + SORT_TBL_ELEMENT(111, 299, 0xFF), + SORT_TBL_ELEMENT(113, 247, 0xFF), + SORT_TBL_ELEMENT(116, 234, 0xFF), + SORT_TBL_ELEMENT(117, 169, 0xFF), + SORT_TBL_ELEMENT(118, 156, 0xFF), + SORT_TBL_ELEMENT(119, 78, 0xFF), +}; +STATE_PERF_TBL(LL_ONLY, SB); + +static const struct ppm_sorted_pwr_tbl state_pwr_tbl_L_ONLY_SB[] = { + SORT_TBL_ELEMENT(8, 2150, 8), + SORT_TBL_ELEMENT(14, 1819, 14), + SORT_TBL_ELEMENT(18, 1651, 20), + SORT_TBL_ELEMENT(20, 1529, 20), + SORT_TBL_ELEMENT(22, 1397, 22), + SORT_TBL_ELEMENT(28, 1175, 34), + SORT_TBL_ELEMENT(30, 1152, 34), + SORT_TBL_ELEMENT(34, 1026, 34), + SORT_TBL_ELEMENT(37, 975, 43), + SORT_TBL_ELEMENT(43, 840, 43), + SORT_TBL_ELEMENT(44, 820, 46), + SORT_TBL_ELEMENT(46, 789, 46), + SORT_TBL_ELEMENT(52, 681, 52), + SORT_TBL_ELEMENT(55, 653, 56), + SORT_TBL_ELEMENT(56, 647, 56), + SORT_TBL_ELEMENT(62, 553, 69), + SORT_TBL_ELEMENT(63, 552, 69), + SORT_TBL_ELEMENT(67, 524, 69), + SORT_TBL_ELEMENT(69, 499, 69), + SORT_TBL_ELEMENT(70, 466, 71), + SORT_TBL_ELEMENT(71, 453, 71), + SORT_TBL_ELEMENT(76, 385, 76), + SORT_TBL_ELEMENT(77, 368, 77), + SORT_TBL_ELEMENT(81, 315, 86), + SORT_TBL_ELEMENT(86, 271, 86), + SORT_TBL_ELEMENT(87, 259, 96), + SORT_TBL_ELEMENT(95, 211, 96), + SORT_TBL_ELEMENT(96, 205, 96), + SORT_TBL_ELEMENT(103, 159, 103), + SORT_TBL_ELEMENT(104, 157, 104), + SORT_TBL_ELEMENT(109, 113, 109), + SORT_TBL_ELEMENT(114, 67, 114), +}; +STATE_PWR_TBL(L_ONLY, SB); + +static const struct ppm_sorted_pwr_tbl state_perf_tbl_L_ONLY_SB[] = { + SORT_TBL_ELEMENT(8, 3900, 0xFF), + SORT_TBL_ELEMENT(14, 3510, 0xFF), + SORT_TBL_ELEMENT(20, 3146, 0xFF), + SORT_TBL_ELEMENT(18, 2925, 0xFF), + SORT_TBL_ELEMENT(22, 2633, 0xFF), + SORT_TBL_ELEMENT(34, 2392, 0xFF), + SORT_TBL_ELEMENT(28, 2360, 0xFF), + SORT_TBL_ELEMENT(43, 2054, 0xFF), + SORT_TBL_ELEMENT(30, 1950, 0xFF), + SORT_TBL_ELEMENT(46, 1794, 0xFF), + SORT_TBL_ELEMENT(37, 1755, 0xFF), + SORT_TBL_ELEMENT(52, 1742, 0xFF), + SORT_TBL_ELEMENT(44, 1573, 0xFF), + SORT_TBL_ELEMENT(56, 1541, 0xFF), + SORT_TBL_ELEMENT(69, 1326, 0xFF), + SORT_TBL_ELEMENT(67, 1307, 0xFF), + SORT_TBL_ELEMENT(63, 1196, 0xFF), + SORT_TBL_ELEMENT(71, 1027, 0xFF), + SORT_TBL_ELEMENT(76, 995, 0xFF), + SORT_TBL_ELEMENT(55, 975, 0xFF), + SORT_TBL_ELEMENT(62, 878, 0xFF), + SORT_TBL_ELEMENT(77, 871, 0xFF), + SORT_TBL_ELEMENT(70, 787, 0xFF), + SORT_TBL_ELEMENT(86, 663, 0xFF), + SORT_TBL_ELEMENT(81, 598, 0xFF), + SORT_TBL_ELEMENT(96, 572, 0xFF), + SORT_TBL_ELEMENT(87, 514, 0xFF), + SORT_TBL_ELEMENT(95, 436, 0xFF), + SORT_TBL_ELEMENT(103, 429, 0xFF), + SORT_TBL_ELEMENT(104, 332, 0xFF), + SORT_TBL_ELEMENT(109, 286, 0xFF), + SORT_TBL_ELEMENT(114, 143, 0xFF), +}; +STATE_PERF_TBL(L_ONLY, SB); + +static const struct ppm_sorted_pwr_tbl state_pwr_tbl_4LL_L_SB[] = { + SORT_TBL_ELEMENT(0, 2935, 0), + SORT_TBL_ELEMENT(3, 2473, 3), + SORT_TBL_ELEMENT(4, 2436, 4), + SORT_TBL_ELEMENT(9, 2060, 9), + SORT_TBL_ELEMENT(10, 2052, 10), + SORT_TBL_ELEMENT(12, 1937, 12), + SORT_TBL_ELEMENT(16, 1705, 16), + SORT_TBL_ELEMENT(19, 1630, 19), + SORT_TBL_ELEMENT(21, 1438, 23), + SORT_TBL_ELEMENT(23, 1392, 23), + SORT_TBL_ELEMENT(24, 1351, 24), + SORT_TBL_ELEMENT(27, 1208, 31), + SORT_TBL_ELEMENT(29, 1155, 31), + SORT_TBL_ELEMENT(31, 1142, 31), + SORT_TBL_ELEMENT(36, 996, 38), + SORT_TBL_ELEMENT(38, 948, 38), + SORT_TBL_ELEMENT(40, 919, 40), + SORT_TBL_ELEMENT(41, 918, 41), + SORT_TBL_ELEMENT(48, 762, 48), + SORT_TBL_ELEMENT(49, 754, 49), + SORT_TBL_ELEMENT(51, 681, 53), + SORT_TBL_ELEMENT(53, 658, 53), + SORT_TBL_ELEMENT(58, 605, 58), + SORT_TBL_ELEMENT(61, 560, 61), + SORT_TBL_ELEMENT(65, 544, 65), + SORT_TBL_ELEMENT(72, 449, 72), + SORT_TBL_ELEMENT(73, 430, 73), + SORT_TBL_ELEMENT(80, 315, 80), + SORT_TBL_ELEMENT(85, 271, 85), + SORT_TBL_ELEMENT(93, 225, 93), + SORT_TBL_ELEMENT(100, 179, 100), + SORT_TBL_ELEMENT(106, 133, 106), +}; +STATE_PWR_TBL(4LL_L, SB); + +static const struct ppm_sorted_pwr_tbl state_perf_tbl_4LL_L_SB[] = { + SORT_TBL_ELEMENT(0, 6188, 0xFF), + SORT_TBL_ELEMENT(3, 5538, 0xFF), + SORT_TBL_ELEMENT(4, 5213, 0xFF), + SORT_TBL_ELEMENT(9, 4888, 0xFF), + SORT_TBL_ELEMENT(10, 4661, 0xFF), + SORT_TBL_ELEMENT(12, 4238, 0xFF), + SORT_TBL_ELEMENT(16, 4102, 0xFF), + SORT_TBL_ELEMENT(19, 3783, 0xFF), + SORT_TBL_ELEMENT(23, 3770, 0xFF), + SORT_TBL_ELEMENT(24, 3315, 0xFF), + SORT_TBL_ELEMENT(21, 3263, 0xFF), + SORT_TBL_ELEMENT(31, 3250, 0xFF), + SORT_TBL_ELEMENT(29, 3172, 0xFF), + SORT_TBL_ELEMENT(27, 2906, 0xFF), + SORT_TBL_ELEMENT(38, 2737, 0xFF), + SORT_TBL_ELEMENT(40, 2730, 0xFF), + SORT_TBL_ELEMENT(41, 2574, 0xFF), + SORT_TBL_ELEMENT(36, 2529, 0xFF), + SORT_TBL_ELEMENT(48, 2295, 0xFF), + SORT_TBL_ELEMENT(49, 2223, 0xFF), + SORT_TBL_ELEMENT(53, 2002, 0xFF), + SORT_TBL_ELEMENT(51, 1976, 0xFF), + SORT_TBL_ELEMENT(58, 1859, 0xFF), + SORT_TBL_ELEMENT(61, 1710, 0xFF), + SORT_TBL_ELEMENT(65, 1671, 0xFF), + SORT_TBL_ELEMENT(72, 1424, 0xFF), + SORT_TBL_ELEMENT(73, 1339, 0xFF), + SORT_TBL_ELEMENT(80, 1008, 0xFF), + SORT_TBL_ELEMENT(85, 884, 0xFF), + SORT_TBL_ELEMENT(93, 741, 0xFF), + SORT_TBL_ELEMENT(100, 598, 0xFF), + SORT_TBL_ELEMENT(106, 455, 0xFF), +}; +STATE_PERF_TBL(4LL_L, SB); + +static const struct ppm_sorted_pwr_tbl state_pwr_tbl_4L_LL_SB[] = { + SORT_TBL_ELEMENT(0, 2935, 0), + SORT_TBL_ELEMENT(1, 2749, 1), + SORT_TBL_ELEMENT(2, 2563, 3), + SORT_TBL_ELEMENT(3, 2473, 3), + SORT_TBL_ELEMENT(5, 2377, 6), + SORT_TBL_ELEMENT(6, 2318, 6), + SORT_TBL_ELEMENT(7, 2164, 9), + SORT_TBL_ELEMENT(9, 2060, 9), + SORT_TBL_ELEMENT(11, 2009, 13), + SORT_TBL_ELEMENT(13, 1934, 13), + SORT_TBL_ELEMENT(15, 1809, 15), + SORT_TBL_ELEMENT(17, 1683, 23), + SORT_TBL_ELEMENT(23, 1392, 23), + SORT_TBL_ELEMENT(25, 1306, 25), + SORT_TBL_ELEMENT(26, 1219, 31), + SORT_TBL_ELEMENT(31, 1142, 31), + SORT_TBL_ELEMENT(32, 1132, 33), + SORT_TBL_ELEMENT(33, 1071, 33), + SORT_TBL_ELEMENT(35, 999, 40), + SORT_TBL_ELEMENT(39, 928, 40), + SORT_TBL_ELEMENT(40, 919, 40), + SORT_TBL_ELEMENT(42, 862, 42), + SORT_TBL_ELEMENT(45, 806, 45), + SORT_TBL_ELEMENT(50, 750, 53), + SORT_TBL_ELEMENT(53, 658, 53), + SORT_TBL_ELEMENT(57, 621, 57), + SORT_TBL_ELEMENT(60, 583, 60), + SORT_TBL_ELEMENT(64, 546, 64), + SORT_TBL_ELEMENT(85, 271, 85), + SORT_TBL_ELEMENT(88, 255, 88), + SORT_TBL_ELEMENT(89, 240, 89), + SORT_TBL_ELEMENT(94, 224, 94), +}; +STATE_PWR_TBL(4L_LL, SB); + +static const struct ppm_sorted_pwr_tbl state_perf_tbl_4L_LL_SB[] = { + SORT_TBL_ELEMENT(0, 6188, 0xFF), + SORT_TBL_ELEMENT(1, 5616, 0xFF), + SORT_TBL_ELEMENT(3, 5538, 0xFF), + SORT_TBL_ELEMENT(2, 5044, 0xFF), + SORT_TBL_ELEMENT(6, 5031, 0xFF), + SORT_TBL_ELEMENT(9, 4888, 0xFF), + SORT_TBL_ELEMENT(7, 4524, 0xFF), + SORT_TBL_ELEMENT(5, 4472, 0xFF), + SORT_TBL_ELEMENT(13, 4453, 0xFF), + SORT_TBL_ELEMENT(11, 4017, 0xFF), + SORT_TBL_ELEMENT(15, 4017, 0xFF), + SORT_TBL_ELEMENT(23, 3770, 0xFF), + SORT_TBL_ELEMENT(17, 3582, 0xFF), + SORT_TBL_ELEMENT(25, 3426, 0xFF), + SORT_TBL_ELEMENT(31, 3250, 0xFF), + SORT_TBL_ELEMENT(26, 3081, 0xFF), + SORT_TBL_ELEMENT(33, 2951, 0xFF), + SORT_TBL_ELEMENT(32, 2737, 0xFF), + SORT_TBL_ELEMENT(40, 2730, 0xFF), + SORT_TBL_ELEMENT(35, 2652, 0xFF), + SORT_TBL_ELEMENT(42, 2483, 0xFF), + SORT_TBL_ELEMENT(39, 2353, 0xFF), + SORT_TBL_ELEMENT(45, 2236, 0xFF), + SORT_TBL_ELEMENT(53, 2002, 0xFF), + SORT_TBL_ELEMENT(50, 1989, 0xFF), + SORT_TBL_ELEMENT(57, 1833, 0xFF), + SORT_TBL_ELEMENT(60, 1664, 0xFF), + SORT_TBL_ELEMENT(64, 1495, 0xFF), + SORT_TBL_ELEMENT(85, 884, 0xFF), + SORT_TBL_ELEMENT(88, 806, 0xFF), + SORT_TBL_ELEMENT(89, 728, 0xFF), + SORT_TBL_ELEMENT(94, 650, 0xFF), +}; +STATE_PERF_TBL(4L_LL, SB); + +static const struct ppm_power_tbl cpu_tlp_power_tbl_SB[] = { + {0, {{0, 4}, {0, 4},}, 6188, 2935}, + {1, {{0, 3}, {0, 4},}, 5616, 2749}, + {2, {{0, 2}, {0, 4},}, 5044, 2563}, + {3, {{1, 4}, {1, 4},}, 5538, 2473}, + {4, {{0, 4}, {0, 3},}, 5213, 2436}, + {5, {{0, 1}, {0, 4},}, 4472, 2377}, + {6, {{1, 3}, {1, 4},}, 5031, 2318}, + {7, {{1, 2}, {1, 4},}, 4524, 2164}, + {8, {{-1, 0}, {0, 4},}, 3900, 2150}, + {9, {{2, 4}, {2, 4},}, 4888, 2060}, + {10, {{1, 4}, {1, 3},}, 4661, 2052}, + {11, {{1, 1}, {1, 4},}, 4017, 2009}, + {12, {{0, 4}, {0, 2},}, 4238, 1937}, + {13, {{2, 3}, {2, 4},}, 4453, 1934}, + {14, {{-1, 0}, {1, 4},}, 3510, 1819}, + {15, {{2, 2}, {2, 4},}, 4017, 1809}, + {16, {{2, 4}, {2, 3},}, 4102, 1705}, + {17, {{2, 1}, {2, 4},}, 3582, 1683}, + {18, {{-1, 0}, {0, 3},}, 2925, 1651}, + {19, {{1, 4}, {1, 2},}, 3783, 1630}, + {20, {{-1, 0}, {2, 4},}, 3146, 1529}, + {21, {{0, 4}, {0, 1},}, 3263, 1438}, + {22, {{-1, 0}, {1, 3},}, 2633, 1397}, + {23, {{3, 4}, {3, 4},}, 3770, 1392}, + {24, {{2, 4}, {2, 2},}, 3315, 1351}, + {25, {{3, 3}, {3, 4},}, 3426, 1306}, + {26, {{3, 2}, {3, 4},}, 3081, 1219}, + {27, {{1, 4}, {1, 1},}, 2906, 1208}, + {28, {{-1, 0}, {2, 3},}, 2360, 1175}, + {29, {{3, 4}, {3, 3},}, 3172, 1155}, + {30, {{-1, 0}, {0, 2},}, 1950, 1152}, + {31, {{4, 4}, {4, 4},}, 3250, 1142}, + {32, {{3, 1}, {3, 4},}, 2737, 1132}, + {33, {{4, 3}, {4, 4},}, 2951, 1071}, + {34, {{-1, 0}, {3, 4},}, 2392, 1026}, + {35, {{4, 2}, {4, 4},}, 2652, 999}, + {36, {{2, 4}, {2, 1},}, 2529, 996}, + {37, {{-1, 0}, {1, 2},}, 1755, 975}, + {38, {{4, 4}, {4, 3},}, 2737, 948}, + {39, {{4, 1}, {4, 4},}, 2353, 928}, + {40, {{5, 4}, {5, 4},}, 2730, 919}, + {41, {{3, 4}, {3, 2},}, 2574, 918}, + {42, {{5, 3}, {5, 4},}, 2483, 862}, + {43, {{-1, 0}, {4, 4},}, 2054, 840}, + {44, {{-1, 0}, {2, 2},}, 1573, 820}, + {45, {{5, 2}, {5, 4},}, 2236, 806}, + {46, {{-1, 0}, {3, 3},}, 1794, 789}, + {47, {{0, 4}, {-1, 0},}, 2288, 785}, + {48, {{5, 4}, {5, 3},}, 2295, 762}, + {49, {{4, 4}, {4, 2},}, 2223, 754}, + {50, {{5, 1}, {5, 4},}, 1989, 750}, + {51, {{3, 4}, {3, 1},}, 1976, 681}, + {52, {{-1, 0}, {5, 4},}, 1742, 681}, + {53, {{6, 4}, {6, 4},}, 2002, 658}, + {54, {{1, 4}, {-1, 0},}, 2028, 655}, + {55, {{-1, 0}, {0, 1},}, 975, 653}, + {56, {{-1, 0}, {4, 3},}, 1541, 647}, + {57, {{6, 3}, {6, 4},}, 1833, 621}, + {58, {{5, 4}, {5, 2},}, 1859, 605}, + {59, {{0, 3}, {-1, 0},}, 1716, 599}, + {60, {{6, 2}, {6, 4},}, 1664, 583}, + {61, {{4, 4}, {4, 1},}, 1710, 560}, + {62, {{-1, 0}, {1, 1},}, 878, 553}, + {63, {{-1, 0}, {3, 2},}, 1196, 552}, + {64, {{6, 1}, {6, 4},}, 1495, 546}, + {65, {{6, 4}, {6, 3},}, 1671, 544}, + {66, {{2, 4}, {-1, 0},}, 1742, 530}, + {67, {{-1, 0}, {5, 3},}, 1307, 524}, + {68, {{1, 3}, {-1, 0},}, 1521, 500}, + {69, {{-1, 0}, {6, 4},}, 1326, 499}, + {70, {{-1, 0}, {2, 1},}, 787, 466}, + {71, {{-1, 0}, {4, 2},}, 1027, 453}, + {72, {{5, 4}, {5, 1},}, 1424, 449}, + {73, {{6, 4}, {6, 2},}, 1339, 430}, + {74, {{0, 2}, {-1, 0},}, 1144, 413}, + {75, {{2, 3}, {-1, 0},}, 1307, 405}, + {76, {{-1, 0}, {6, 3},}, 995, 385}, + {77, {{-1, 0}, {5, 2},}, 871, 368}, + {78, {{3, 4}, {-1, 0},}, 1378, 366}, + {79, {{1, 2}, {-1, 0},}, 1014, 345}, + {80, {{6, 4}, {6, 1},}, 1008, 315}, + {81, {{-1, 0}, {3, 1},}, 598, 315}, + {82, {{4, 4}, {-1, 0},}, 1196, 301}, + {83, {{3, 3}, {-1, 0},}, 1034, 280}, + {84, {{2, 2}, {-1, 0},}, 871, 279}, + {85, {{7, 4}, {7, 4},}, 884, 271}, + {86, {{-1, 0}, {6, 2},}, 663, 271}, + {87, {{-1, 0}, {4, 1},}, 514, 259}, + {88, {{7, 3}, {7, 4},}, 806, 255}, + {89, {{7, 2}, {7, 4},}, 728, 240}, + {90, {{5, 4}, {-1, 0},}, 988, 238}, + {91, {{4, 3}, {-1, 0},}, 897, 230}, + {92, {{0, 1}, {-1, 0},}, 572, 228}, + {93, {{7, 4}, {7, 3},}, 741, 225}, + {94, {{7, 1}, {7, 4},}, 650, 224}, + {95, {{-1, 0}, {5, 1},}, 436, 211}, + {96, {{-1, 0}, {7, 4},}, 572, 205}, + {97, {{3, 2}, {-1, 0},}, 689, 193}, + {98, {{1, 1}, {-1, 0},}, 507, 190}, + {99, {{5, 3}, {-1, 0},}, 741, 182}, + {100, {{7, 4}, {7, 2},}, 598, 179}, + {101, {{6, 4}, {-1, 0},}, 676, 159}, + {102, {{4, 2}, {-1, 0},}, 598, 159}, + {103, {{-1, 0}, {7, 3},}, 429, 159}, + {104, {{-1, 0}, {6, 1},}, 332, 157}, + {105, {{2, 1}, {-1, 0},}, 436, 154}, + {106, {{7, 4}, {7, 1},}, 455, 133}, + {107, {{5, 2}, {-1, 0},}, 494, 125}, + {108, {{6, 3}, {-1, 0},}, 507, 121}, + {109, {{-1, 0}, {7, 2},}, 286, 113}, + {110, {{3, 1}, {-1, 0},}, 345, 106}, + {111, {{4, 1}, {-1, 0},}, 299, 88}, + {112, {{6, 2}, {-1, 0},}, 338, 84}, + {113, {{5, 1}, {-1, 0},}, 247, 69}, + {114, {{-1, 0}, {7, 1},}, 143, 67}, + {115, {{7, 4}, {-1, 0},}, 312, 66}, + {116, {{7, 3}, {-1, 0},}, 234, 51}, + {117, {{6, 1}, {-1, 0},}, 169, 47}, + {118, {{7, 2}, {-1, 0},}, 156, 35}, + {119, {{7, 1}, {-1, 0},}, 78, 20}, +}; + diff --git a/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/Makefile b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..bba7fabe39da0e039629f307eccd20be70a37953 --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/Makefile @@ -0,0 +1,25 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += \ + -I$(PPM_ROOT_DIR)/inc \ + -I$(srctree)/drivers/misc/mediatek/base/power/$(CONFIG_MTK_PLATFORM)/ + +# platform dependent functions +obj-y += mt_ppm_platform.o +# power state settings +obj-y += mt_ppm_power_state.o +# power data related +obj-y += mt_ppm_power_data.o +# limit calculation algorithm +obj-y += mt_ppm_cobra_algo.o diff --git a/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_cobra_algo.c b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_cobra_algo.c new file mode 100644 index 0000000000000000000000000000000000000000..655634550b6cea2c8218955950fbe4bb14d9f2d5 --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_cobra_algo.c @@ -0,0 +1,524 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include + +#include "mt_ppm_platform.h" +#include "mt_ppm_internal.h" + + +struct ppm_cobra_data cobra_tbl; + +static int Core_limit[NR_PPM_CLUSTERS] = {CORE_NUM_LL, CORE_NUM_L}; +#if PPM_COBRA_NEED_OPP_MAPPING +static int freq_idx_mapping_tbl_fy[COBRA_OPP_NUM] = {0, 3, 5, 7, 9, 10, 12, 14}; +static int freq_idx_mapping_tbl_fy_r[DVFS_OPP_NUM] = {0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 7}; +static int freq_idx_mapping_tbl_sb[COBRA_OPP_NUM] = {0, 3, 6, 8, 9, 11, 12, 14}; +static int freq_idx_mapping_tbl_sb_r[DVFS_OPP_NUM] = {0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 7}; + +int *freq_idx_mapping_tbl; +int *freq_idx_mapping_tbl_r; +int *freq_idx_mapping_tbl_big; +int *freq_idx_mapping_tbl_big_r; +#endif + +#define ACT_CORE(cluster) (active_core[PPM_CLUSTER_##cluster]) +#define CORE_LIMIT(cluster) (core_limit_tmp[PPM_CLUSTER_##cluster]) + + +static int get_delta_pwr_LxLL(unsigned int L_core, unsigned int LL_core, unsigned int opp) +{ +#if PPM_COBRA_RUNTIME_CALC_DELTA + unsigned int idx_L = get_cluster_max_cpu_core(PPM_CLUSTER_LL); + unsigned int idx_LL = 0; + unsigned int cur_opp, cur_pwr, prev_pwr; + int delta_pwr; +#endif + + if (L_core > get_cluster_max_cpu_core(PPM_CLUSTER_L) + || LL_core > get_cluster_max_cpu_core(PPM_CLUSTER_LL) + || opp > get_cluster_min_cpufreq_idx(PPM_CLUSTER_L)) { + ppm_err("%s: Invalid input: L_core=%d, LL_core=%d, opp=%d\n", + __func__, L_core, LL_core, opp); + BUG(); + } + +#if PPM_COBRA_RUNTIME_CALC_DELTA + if (L_core == 0 && LL_core == 0) + return 0; + +#if PPM_COBRA_NEED_OPP_MAPPING + cur_opp = freq_idx_mapping_tbl[opp]; +#else + cur_opp = opp; +#endif + cur_pwr = (L_core) ? cobra_tbl.basic_pwr_tbl[idx_L+L_core-1][cur_opp].power_idx : 0; /* L */ + cur_pwr += (LL_core) ? cobra_tbl.basic_pwr_tbl[idx_LL+LL_core-1][cur_opp].power_idx : 0; /* L+LL */ + + if (opp == COBRA_OPP_NUM - 1) { + prev_pwr = (L_core) ? ((L_core > 1) ? (cobra_tbl.basic_pwr_tbl[idx_L+L_core-2][cur_opp].power_idx + + ((LL_core) ? cobra_tbl.basic_pwr_tbl[idx_LL+LL_core-1][cur_opp].power_idx : 0)) + : ((LL_core) ? cobra_tbl.basic_pwr_tbl[idx_LL+LL_core-1][cur_opp].power_idx : 0)) + : ((LL_core > 1) ? cobra_tbl.basic_pwr_tbl[idx_LL+LL_core-2][cur_opp].power_idx : 0); + } else { +#if PPM_COBRA_NEED_OPP_MAPPING + unsigned int prev_opp = freq_idx_mapping_tbl[opp+1]; +#else + unsigned int prev_opp = opp + 1; +#endif + prev_pwr = (L_core) ? cobra_tbl.basic_pwr_tbl[idx_L+L_core-1][prev_opp].power_idx : 0; + prev_pwr += (LL_core) ? cobra_tbl.basic_pwr_tbl[idx_LL+LL_core-1][prev_opp].power_idx : 0; + } + + delta_pwr = cur_pwr - prev_pwr; + + return delta_pwr; +#else + return cobra_tbl.delta_tbl_LxLL[L_core][LL_core][opp].delta_pwr; +#endif +} + +void ppm_cobra_update_core_limit(unsigned int cluster, int limit) +{ + if (cluster >= NR_PPM_CLUSTERS) { + ppm_err("%s: Invalid cluster id = %d\n", __func__, cluster); + BUG(); + } + + if (limit < 0 || limit > get_cluster_max_cpu_core(cluster)) { + ppm_err("%s: Invalid core limit for cluster%d = %d\n", __func__, cluster, limit); + BUG(); + } + + Core_limit[cluster] = limit; +} + +void ppm_cobra_update_freq_limit(unsigned int cluster, int limit) +{ + /* NO NEED */ +} + +void ppm_cobra_update_limit(enum ppm_power_state new_state, void *user_req) +{ + struct ppm_policy_req *req; + int power_budget; + int opp[NR_PPM_CLUSTERS]; + int active_core[NR_PPM_CLUSTERS]; +#if PPM_COBRA_USE_CORE_LIMIT + int core_limit_tmp[NR_PPM_CLUSTERS]; +#endif + int i; + struct cpumask cluster_cpu, online_cpu; + int delta_power; + int LxLL; + /* Get power index of current OPP */ + int curr_power = 0; + struct ppm_cluster_status cl_status[NR_PPM_CLUSTERS]; + + /* skip if DVFS is not ready (we cannot get current freq...) */ + if (!ppm_main_info.client_info[PPM_CLIENT_DVFS].limit_cb) + return; + + if (!user_req) + return; + + req = (struct ppm_policy_req *)user_req; + power_budget = req->power_budget; + + if (power_budget >= ppm_get_max_pwr_idx()) + return; + + ppm_dbg(COBRA_ALGO, "[PREV]Core_Limit=%d%d, policy_limit=%d%d, state=%s\n", + Core_limit[PPM_CLUSTER_LL], + Core_limit[PPM_CLUSTER_L], + req->limit[PPM_CLUSTER_LL].max_cpu_core, + req->limit[PPM_CLUSTER_L].max_cpu_core, + ppm_get_power_state_name(new_state)); + + for_each_ppm_clusters(i) { + arch_get_cluster_cpus(&cluster_cpu, i); + cpumask_and(&online_cpu, &cluster_cpu, cpu_online_mask); + + cl_status[i].core_num = cpumask_weight(&online_cpu); + cl_status[i].volt = 0; /* don't care */ + if (!cl_status[i].core_num) + cl_status[i].freq_idx = -1; + else + cl_status[i].freq_idx = ppm_main_freq_to_idx(i, + mt_cpufreq_get_cur_phy_freq_no_lock(i), CPUFREQ_RELATION_L); + + ppm_ver("[%d] core = %d, freq_idx = %d\n", + i, cl_status[i].core_num, cl_status[i].freq_idx); + } + +#if PPM_COBRA_USE_CORE_LIMIT + for_each_ppm_clusters(i) { + if (cl_status[i].core_num > Core_limit[i]) + cl_status[i].core_num = Core_limit[i]; + if (req->limit[i].max_cpu_core < Core_limit[i]) + Core_limit[i] = req->limit[i].max_cpu_core; + } +#endif + + if (cl_status[PPM_CLUSTER_LL].core_num == 0 && cl_status[PPM_CLUSTER_L].core_num == 0) { + if (Core_limit[PPM_CLUSTER_LL] > 0) { + cl_status[PPM_CLUSTER_LL].core_num = 1; + cl_status[PPM_CLUSTER_LL].freq_idx = get_cluster_max_cpufreq_idx(PPM_CLUSTER_LL); + } else { + cl_status[PPM_CLUSTER_L].core_num = 1; + cl_status[PPM_CLUSTER_L].freq_idx = get_cluster_max_cpufreq_idx(PPM_CLUSTER_L); + } + } + + + /* use L cluster frequency */ + if (cl_status[PPM_CLUSTER_L].core_num > 0) + cl_status[PPM_CLUSTER_LL].freq_idx = cl_status[PPM_CLUSTER_L].freq_idx; + + curr_power = ppm_find_pwr_idx(cl_status); + if (curr_power < 0) + curr_power = mt_ppm_thermal_get_max_power(); + delta_power = power_budget - curr_power; + + for_each_ppm_clusters(i) { +#if PPM_COBRA_NEED_OPP_MAPPING + /* convert current OPP(frequency only) from 16 to 8 */ + opp[i] = (cl_status[i].freq_idx >= 0) + ? freq_idx_mapping_tbl_r[cl_status[i].freq_idx] : -1; +#else + opp[i] = cl_status[i].freq_idx; +#endif + /* Get Active Core number of each cluster */ + active_core[i] = (cl_status[i].core_num >= 0) ? cl_status[i].core_num : 0; + +#if PPM_COBRA_USE_CORE_LIMIT + core_limit_tmp[i] = Core_limit[i]; + req->limit[i].max_cpu_core = core_limit_tmp[i]; +#endif + } + + /* Which Cluster in L and LL is active (1: L is on, 0: LL is on) */ + LxLL = (ACT_CORE(L) > 0) ? 1 : 0; + + ppm_dbg(COBRA_ALGO, "[IN](bgt/delta/cur)=(%d/%d/%d), (opp/act/c_lmt)=(%d,%d/%d%d/%d%d)\n", + power_budget, delta_power, curr_power, + opp[PPM_CLUSTER_LL], opp[PPM_CLUSTER_L], + ACT_CORE(LL), ACT_CORE(L), + CORE_LIMIT(LL), CORE_LIMIT(L)); + + + /* increase ferquency limit */ + if (delta_power >= 0) { + while (1) { + int ChoosenCl = -1, ChoosenPwr = 0; + int target_delta_pwr; + + /* LxLL Cluster */ + if (opp[LxLL] > 0) { + target_delta_pwr = get_delta_pwr_LxLL(ACT_CORE(L), ACT_CORE(LL), opp[LxLL]-1); + if (delta_power >= target_delta_pwr) { + ChoosenCl = 1; + ChoosenPwr = target_delta_pwr; + + if (ACT_CORE(L) > 0) + opp[PPM_CLUSTER_L] -= 1; + if (ACT_CORE(LL) > 0) + opp[PPM_CLUSTER_LL] -= 1; + } + } + + if (ChoosenCl != -1) + goto prepare_next_round; + +#if PPM_COBRA_USE_CORE_LIMIT + /* no enough budget */ + if (opp[LxLL] != 0) + goto end; + + /* PPM state L_ONLY --> LL core remain turned off */ + if (new_state != PPM_POWER_STATE_L_ONLY) { + while (CORE_LIMIT(LL) < get_cluster_max_cpu_core(PPM_CLUSTER_LL)) { + target_delta_pwr = get_delta_pwr_LxLL(ACT_CORE(L), + CORE_LIMIT(LL)+1, COBRA_OPP_NUM-1); + if (delta_power < target_delta_pwr) + break; + + delta_power -= target_delta_pwr; + req->limit[PPM_CLUSTER_LL].max_cpu_core = ++CORE_LIMIT(LL); + } + } + /* PPM state LL_ONLY --> L core remain turned off */ + if (new_state != PPM_POWER_STATE_LL_ONLY) { + while (CORE_LIMIT(L) < get_cluster_max_cpu_core(PPM_CLUSTER_L)) { + target_delta_pwr = get_delta_pwr_LxLL(CORE_LIMIT(L)+1, + ACT_CORE(LL), COBRA_OPP_NUM-1); + if (delta_power < target_delta_pwr) + break; + + delta_power -= target_delta_pwr; + req->limit[PPM_CLUSTER_L].max_cpu_core = ++CORE_LIMIT(L); + } + } +end: +#endif + ppm_dbg(COBRA_ALGO, "[+]ChoosenCl=-1! delta=%d, (opp/c_lmt)=(%d,%d/%d%d)\n", + delta_power, opp[PPM_CLUSTER_LL], opp[PPM_CLUSTER_L], + CORE_LIMIT(LL), CORE_LIMIT(L)); + + break; + +prepare_next_round: + delta_power -= ChoosenPwr; + + ppm_dbg(COBRA_ALGO, "[+](delta/Cl/Pwr)=(%d,%d,%d), opp=%d,%d\n", + delta_power, ChoosenCl, ChoosenPwr, + opp[PPM_CLUSTER_LL], opp[PPM_CLUSTER_L]); + } + } else { + while (delta_power < 0) { + int ChoosenCl = -1; + int ChoosenPwr = 0; + + /* LxLL */ + if (opp[LxLL] >= 0 && opp[LxLL] < PPM_COBRA_MAX_FREQ_IDX) { + ChoosenCl = 1; + ChoosenPwr = get_delta_pwr_LxLL(ACT_CORE(L), ACT_CORE(LL), opp[LxLL]); + + if (ACT_CORE(L) > 0) + opp[PPM_CLUSTER_L] += 1; + if (ACT_CORE(LL) > 0) + opp[PPM_CLUSTER_LL] += 1; + } + + if (ChoosenCl == -1) { + ppm_err("No lower OPP!(bgt/delta/cur)=(%d/%d/%d),(opp/act)=(%d,%d/%d%d)\n", + power_budget, delta_power, curr_power, + opp[PPM_CLUSTER_LL], opp[PPM_CLUSTER_L], ACT_CORE(LL), ACT_CORE(L)); + break; + } + +#if PPM_COBRA_USE_CORE_LIMIT + /* Turned off core */ + if (opp[LxLL] == PPM_COBRA_MAX_FREQ_IDX) { + if (ACT_CORE(L) > 1 || (ACT_CORE(LL) > 0 && ACT_CORE(L) > 0)) + req->limit[PPM_CLUSTER_L].max_cpu_core = --ACT_CORE(L); + else if (ACT_CORE(LL) > 1) + req->limit[PPM_CLUSTER_LL].max_cpu_core = --ACT_CORE(LL); + if (ACT_CORE(L) > 0) + opp[PPM_CLUSTER_L] = PPM_COBRA_MAX_FREQ_IDX - 1; + else + LxLL = 0; + if (ACT_CORE(LL) > 0) + opp[PPM_CLUSTER_LL] = PPM_COBRA_MAX_FREQ_IDX - 1; + } +#endif + + delta_power += ChoosenPwr; + curr_power -= ChoosenPwr; + + ppm_dbg(COBRA_ALGO, "[-](delta/Cl/Pwr)=(%d,%d,%d), (opp/act)=(%d,%d/%d%d)\n", + delta_power, ChoosenCl, ChoosenPwr, + opp[PPM_CLUSTER_LL], opp[PPM_CLUSTER_L], + ACT_CORE(LL), ACT_CORE(L)); + } + } + + /* Set frequency limit */ + /* For non share buck */ +#if 0 + if (opp[PPM_CLUSTER_LL] >= 0 && ACT_CORE(LL) > 0) + req->limit[PPM_CLUSTER_LL].max_cpufreq_idx = freq_idx_mapping_tbl[opp[PPM_CLUSTER_LL]]; + if (opp[PPM_CLUSTER_L] >= 0 && ACT_CORE(L) > 0) + req->limit[PPM_CLUSTER_L].max_cpufreq_idx = freq_idx_mapping_tbl[opp[PPM_CLUSTER_L]]; +#endif + + /* Set all frequency limit of the cluster */ + /* Set OPP of Cluser n to opp[n] */ + for_each_ppm_clusters(i) { +#if PPM_COBRA_NEED_OPP_MAPPING + req->limit[i].max_cpufreq_idx = freq_idx_mapping_tbl[opp[LxLL]]; +#else + req->limit[i].max_cpufreq_idx = opp[LxLL]; +#endif + } + + ppm_dbg(COBRA_ALGO, "[OUT]delta=%d, (opp/act/c_lmt/f_lmt)=(%d,%d/%d%d/%d%d/%d,%d)\n", + delta_power, + opp[PPM_CLUSTER_LL], opp[PPM_CLUSTER_L], + ACT_CORE(LL), ACT_CORE(L), + req->limit[PPM_CLUSTER_LL].max_cpu_core, + req->limit[PPM_CLUSTER_L].max_cpu_core, + req->limit[PPM_CLUSTER_LL].max_cpufreq_idx, + req->limit[PPM_CLUSTER_L].max_cpufreq_idx); + + /* error check */ + for_each_ppm_clusters(i) { + if (req->limit[i].max_cpufreq_idx > req->limit[i].min_cpufreq_idx) + req->limit[i].min_cpufreq_idx = req->limit[i].max_cpufreq_idx; + if (req->limit[i].max_cpu_core < req->limit[i].min_cpu_core) + req->limit[i].min_cpu_core = req->limit[i].max_cpu_core; + } +} + +void ppm_cobra_init(void) +{ + int i, j; +#if !PPM_COBRA_RUNTIME_CALC_DELTA + int k; +#endif + struct ppm_pwr_idx_ref_tbl_data pwr_ref_tbl = ppm_get_pwr_idx_ref_tbl(); + struct ppm_power_state_data *state_info = ppm_get_power_state_info(); + +#if PPM_COBRA_NEED_OPP_MAPPING + if (ppm_main_info.dvfs_tbl_type == DVFS_TABLE_TYPE_SB) { + freq_idx_mapping_tbl = freq_idx_mapping_tbl_sb; + freq_idx_mapping_tbl_r = freq_idx_mapping_tbl_sb_r; + freq_idx_mapping_tbl_big = freq_idx_mapping_tbl_sb_big; + freq_idx_mapping_tbl_big_r = freq_idx_mapping_tbl_sb_big_r; + } else { + freq_idx_mapping_tbl = freq_idx_mapping_tbl_fy; + freq_idx_mapping_tbl_r = freq_idx_mapping_tbl_fy_r; + freq_idx_mapping_tbl_big = freq_idx_mapping_tbl_fy_big; + freq_idx_mapping_tbl_big_r = freq_idx_mapping_tbl_fy_big_r; + } +#endif + + /* generate basic power table for EAS */ + ppm_info("basic power table:\n"); + for (i = 0; i < TOTAL_CORE_NUM; i++) { + for (j = 0; j < DVFS_OPP_NUM; j++) { + int *perf_ref_tbl = ppm_get_perf_idx_ref_tbl(i/4); + unsigned char core = (i % 4) + 1; + + if (!perf_ref_tbl) + BUG(); + + cobra_tbl.basic_pwr_tbl[i][j].power_idx = + pwr_ref_tbl.pwr_idx_ref_tbl[i/4].core_total_power[j] * core + + pwr_ref_tbl.pwr_idx_ref_tbl[i/4].l2_power[j]; + cobra_tbl.basic_pwr_tbl[i][j].perf_idx = perf_ref_tbl[j] * core; + + ppm_info("[%d][%d] = (%d, %d)\n", i, j, + cobra_tbl.basic_pwr_tbl[i][j].power_idx, + cobra_tbl.basic_pwr_tbl[i][j].perf_idx); + } + } + + /* decide min_pwr_idx and max_perf_idx for each state */ + for_each_ppm_power_state(i) { + for_each_ppm_clusters(j) { + int max_core = state_info[i].cluster_limit->state_limit[j].max_cpu_core; + int min_core = state_info[i].cluster_limit->state_limit[j].min_cpu_core; + int idx = 4 * j; + + if (max_core > get_cluster_max_cpu_core(j) || min_core < get_cluster_min_cpu_core(j)) + continue; + + state_info[i].min_pwr_idx += (min_core) + ? cobra_tbl.basic_pwr_tbl[idx+min_core-1][DVFS_OPP_NUM-1].power_idx : 0; + state_info[i].max_perf_idx += (max_core) + ? cobra_tbl.basic_pwr_tbl[idx+max_core-1][0].perf_idx : 0; + } + ppm_info("%s: min_pwr_idx = %d, max_perf_idx = %d\n", state_info[i].name, + state_info[i].min_pwr_idx, state_info[i].max_perf_idx); + } + +#if !PPM_COBRA_RUNTIME_CALC_DELTA + /* generate delta power and delta perf table for LxLL */ + ppm_info("LxLL delta table:\n"); + for (i = 0; i <= get_cluster_max_cpu_core(PPM_CLUSTER_L); i++) { + for (j = 0; j <= get_cluster_max_cpu_core(PPM_CLUSTER_LL); j++) { + for (k = 0; k < COBRA_OPP_NUM; k++) { + int idx_L = get_cluster_max_cpu_core(PPM_CLUSTER_LL); + int idx_LL = 0; +#if PPM_COBRA_NEED_OPP_MAPPING + int opp = freq_idx_mapping_tbl[k]; +#else + int opp = k; +#endif + int cur_pwr, prev_pwr, prev_opp; + + if (i == 0 && j == 0) { + cobra_tbl.delta_tbl_LxLL[i][j][k].delta_pwr = 0; + + ppm_info("[%d][%d][%d] = (0)\n", i, j, k); + continue; + } + + cur_pwr = (i) ? cobra_tbl.basic_pwr_tbl[idx_L+i-1][opp].power_idx : 0; /* L */ + cur_pwr += (j) ? cobra_tbl.basic_pwr_tbl[idx_LL+j-1][opp].power_idx : 0; /* L+LL */ + + if (k == COBRA_OPP_NUM - 1) { + prev_pwr = (i) ? + ((i > 1) ? (cobra_tbl.basic_pwr_tbl[idx_L+i-2][opp].power_idx + + ((j) ? cobra_tbl.basic_pwr_tbl[idx_LL+j-1][opp].power_idx : 0)) + : ((j) ? cobra_tbl.basic_pwr_tbl[idx_LL+j-1][opp].power_idx : 0)) + : ((j > 1) ? cobra_tbl.basic_pwr_tbl[idx_LL+j-2][opp].power_idx : 0); + + cobra_tbl.delta_tbl_LxLL[i][j][k].delta_pwr = cur_pwr - prev_pwr; + } else { +#if PPM_COBRA_NEED_OPP_MAPPING + prev_opp = freq_idx_mapping_tbl[k+1]; +#else + prev_opp = k+1; +#endif + prev_pwr = (i) ? cobra_tbl.basic_pwr_tbl[idx_L+i-1][prev_opp].power_idx : 0; + prev_pwr += (j) ? cobra_tbl.basic_pwr_tbl[idx_LL+j-1][prev_opp].power_idx : 0; + + cobra_tbl.delta_tbl_LxLL[i][j][k].delta_pwr = cur_pwr - prev_pwr; + } + + ppm_info("[%d][%d][%d] = (%d)\n", i, j, k, + cobra_tbl.delta_tbl_LxLL[i][j][k].delta_pwr); + } + } + } +#endif + + ppm_info("ET init done!\n"); +} + + +void ppm_cobra_dump_tbl(struct seq_file *m) +{ + int i, j, k; + + seq_puts(m, "\n==========================================\n"); + seq_puts(m, "basic power table (pwr, perf)"); + seq_puts(m, "\n==========================================\n"); + for (i = 0; i < TOTAL_CORE_NUM; i++) { + for (j = 0; j < DVFS_OPP_NUM; j++) { + seq_printf(m, "[%d][%d] = (%d, %d)\n", i, j, + cobra_tbl.basic_pwr_tbl[i][j].power_idx, + cobra_tbl.basic_pwr_tbl[i][j].perf_idx); + } + } + + if (ppm_debug > 0) { + seq_puts(m, "\n==================================================\n"); + seq_puts(m, "LxLL delta table (delta_pwr)"); + seq_puts(m, "\n==================================================\n"); + for (i = 0; i <= get_cluster_max_cpu_core(PPM_CLUSTER_L); i++) { + for (j = 0; j <= get_cluster_max_cpu_core(PPM_CLUSTER_LL); j++) { + for (k = 0; k < COBRA_OPP_NUM; k++) { + seq_printf(m, "[%d][%d][%d] = (%d)\n", i, j, k, + get_delta_pwr_LxLL(i, j, k)); + } + } + } + } +} diff --git a/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_platform.c b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..92db3aaeee667cbdeb647b2b117f840c2bb525ee --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_platform.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include "mt_ppm_platform.h" +#include "mt_ppm_internal.h" + + +void ppm_update_req_by_pwr(enum ppm_power_state new_state, struct ppm_policy_req *req) +{ + ppm_cobra_update_limit(new_state, req); +} + +int ppm_find_pwr_idx(struct ppm_cluster_status *cluster_status) +{ + struct ppm_pwr_idx_ref_tbl_data ref_tbl = ppm_get_pwr_idx_ref_tbl(); + unsigned int pwr_idx = 0; + int i; + + for_each_ppm_clusters(i) { + int core = cluster_status[i].core_num; + int opp = cluster_status[i].freq_idx; + + if (core != 0 && opp >= 0 && opp < DVFS_OPP_NUM) { + pwr_idx += (ref_tbl.pwr_idx_ref_tbl[i].core_total_power[opp] * core) + + ref_tbl.pwr_idx_ref_tbl[i].l2_power[opp]; + } + + ppm_ver("[%d] core = %d, opp = %d\n", i, core, opp); + } + + if (!pwr_idx) { + ppm_warn("@%s: pwr_idx is 0!\n", __func__); + return -1; /* not found */ + } + + ppm_ver("@%s: pwr_idx = %d\n", __func__, pwr_idx); + + return pwr_idx; +} + +int ppm_get_max_pwr_idx(void) +{ + struct ppm_cluster_status status[NR_PPM_CLUSTERS]; + int i; + + for_each_ppm_clusters(i) { + status[i].core_num = get_cluster_max_cpu_core(i); + status[i].freq_idx = get_cluster_max_cpufreq_idx(i); + } + + return ppm_find_pwr_idx(status); +} + +enum ppm_power_state ppm_judge_state_by_user_limit(enum ppm_power_state cur_state, + struct ppm_userlimit_data user_limit) +{ + enum ppm_power_state new_state = PPM_POWER_STATE_NONE; + int LL_core_min = user_limit.limit[0].min_core_num; + int LL_core_max = user_limit.limit[0].max_core_num; + int L_core_min = user_limit.limit[1].min_core_num; + int L_core_max = user_limit.limit[1].max_core_num; + int LL_freq_min = user_limit.limit[0].min_freq_idx; + int L_freq_max = user_limit.limit[1].max_freq_idx; + int sum = LL_core_min + L_core_min; + + ppm_ver("Judge: input --> [%s] (%d)(%d)(%d)(%d) [(%d)(%d)]\n", + ppm_get_power_state_name(cur_state), + LL_core_min, LL_core_max, L_core_min, L_core_max, LL_freq_min, L_freq_max); + + LL_core_max = (LL_core_max == -1) ? 4 : LL_core_max; + L_core_max = (L_core_max == -1) ? 4 : L_core_max; + + /* need to check freq limit for cluster move/merge */ + if (cur_state == PPM_POWER_STATE_LL_ONLY || cur_state == PPM_POWER_STATE_L_ONLY) { + struct ppm_power_state_data *state_info = ppm_get_power_state_info(); + + LL_freq_min = (LL_freq_min == -1) + ? state_info[cur_state].cluster_limit->state_limit[0].min_cpufreq_idx + : LL_freq_min; + L_freq_max = (L_freq_max == -1) + ? state_info[cur_state].cluster_limit->state_limit[1].max_cpufreq_idx + : L_freq_max; + /* idx -> freq */ + LL_freq_min = (ppm_main_info.cluster_info[0].dvfs_tbl) + ? ppm_main_info.cluster_info[0].dvfs_tbl[LL_freq_min].frequency + : get_cluster_min_cpufreq_idx(0); + L_freq_max = (ppm_main_info.cluster_info[1].dvfs_tbl) + ? ppm_main_info.cluster_info[1].dvfs_tbl[L_freq_max].frequency + : get_cluster_max_cpufreq_idx(1); + } + + /* min_core <= 0: don't care */ + /* min_core > 0: turn on this cluster */ + /* max_core == 0: turn off this cluster */ + switch (cur_state) { + case PPM_POWER_STATE_LL_ONLY: + new_state = (LL_core_max == 0) ? PPM_POWER_STATE_L_ONLY + : (L_core_min <= 0 || L_core_max == 0) ? cur_state + /* should not go to L only due to root cluster is fixed at LL */ + : (L_core_min > 0 && ppm_main_info.fixed_root_cluster == 0) ? PPM_POWER_STATE_4LL_L + : (LL_core_min <= 0) ? PPM_POWER_STATE_L_ONLY + : (LL_core_min == 4) ? PPM_POWER_STATE_4LL_L + : (L_core_min == 4) ? PPM_POWER_STATE_4L_LL + /* merge to L cluster */ + : (sum <= L_core_max && L_freq_max >= LL_freq_min) ? PPM_POWER_STATE_L_ONLY + : PPM_POWER_STATE_NONE; + break; + case PPM_POWER_STATE_L_ONLY: + new_state = (L_core_max == 0) ? PPM_POWER_STATE_LL_ONLY + : (LL_core_min <= 0 || LL_core_max == 0) ? cur_state + /* keep current if for only LL min is set */ + : (LL_core_min > 0 && L_core_min == -1 && L_freq_max >= LL_freq_min) ? cur_state + /* will return NONE if LL min is set but L min is not */ + : (L_core_min == 4) ? PPM_POWER_STATE_4L_LL + : (LL_core_min == 4) ? PPM_POWER_STATE_4LL_L + /* merge to L cluster */ + : (sum <= L_core_max && L_freq_max >= LL_freq_min) ? cur_state + : PPM_POWER_STATE_NONE; + break; + case PPM_POWER_STATE_4LL_L: + new_state = (L_core_max == 0) ? PPM_POWER_STATE_LL_ONLY + : (LL_core_max == 0) ? PPM_POWER_STATE_L_ONLY + : (L_core_min == 4) ? PPM_POWER_STATE_4L_LL + : (LL_core_max == 4) ? cur_state + : PPM_POWER_STATE_NONE; + break; + case PPM_POWER_STATE_4L_LL: + new_state = (LL_core_max == 0) ? PPM_POWER_STATE_L_ONLY + : (L_core_max == 0) ? PPM_POWER_STATE_LL_ONLY + : (L_core_max == 4) ? cur_state + : (L_core_max < 4 && LL_core_min == 4) ? PPM_POWER_STATE_4LL_L + : PPM_POWER_STATE_NONE; + break; + default: + break; + } + + /* check root cluster is fixed or not */ + switch (ppm_main_info.fixed_root_cluster) { + case 0: + new_state = (new_state == PPM_POWER_STATE_L_ONLY) ? PPM_POWER_STATE_NONE + : (new_state == PPM_POWER_STATE_4L_LL) ? PPM_POWER_STATE_4LL_L + : new_state; + break; + case 1: + new_state = (new_state == PPM_POWER_STATE_LL_ONLY) ? PPM_POWER_STATE_NONE + : (new_state == PPM_POWER_STATE_4LL_L) ? PPM_POWER_STATE_4L_LL + : new_state; + break; + default: + break; + } + + ppm_ver("Judge: output --> [%s]\n", ppm_get_power_state_name(new_state)); + + return new_state; +} + +/* modify request to fit cur_state */ +void ppm_limit_check_for_user_limit(enum ppm_power_state cur_state, struct ppm_policy_req *req, + struct ppm_userlimit_data user_limit) +{ + if (req && cur_state == PPM_POWER_STATE_L_ONLY) { + unsigned int LL_min_core = req->limit[0].min_cpu_core; + unsigned int L_min_core = req->limit[1].min_cpu_core; + unsigned int sum = LL_min_core + L_min_core; + unsigned int LL_min_freq, L_min_freq, L_max_freq; + + LL_min_freq = (ppm_main_info.cluster_info[0].dvfs_tbl) + ? ppm_main_info.cluster_info[0].dvfs_tbl[req->limit[0].min_cpufreq_idx].frequency + : get_cluster_min_cpufreq_idx(0); + L_min_freq = (ppm_main_info.cluster_info[1].dvfs_tbl) + ? ppm_main_info.cluster_info[1].dvfs_tbl[req->limit[1].min_cpufreq_idx].frequency + : get_cluster_min_cpufreq_idx(1); + L_max_freq = (ppm_main_info.cluster_info[1].dvfs_tbl) + ? ppm_main_info.cluster_info[1].dvfs_tbl[req->limit[1].max_cpufreq_idx].frequency + : get_cluster_max_cpufreq_idx(1); + + if (LL_min_core > 0 && L_max_freq >= LL_min_freq) { + /* user do not set L min so we just move LL core to L */ + if (user_limit.limit[1].min_core_num <= 0) { + req->limit[0].min_cpu_core = 0; + req->limit[1].min_cpu_core = LL_min_core; + ppm_ver("Judge: move LL min core to L = %d\n", LL_min_core); + } else if (sum <= 4) { + req->limit[0].min_cpu_core = 0; + req->limit[1].min_cpu_core = sum; + ppm_ver("Judge: merge LL and L min core = %d\n", sum); +#ifdef PPM_IC_SEGMENT_CHECK + } else if (ppm_main_info.fix_state_by_segment == PPM_POWER_STATE_L_ONLY) { + req->limit[0].min_cpu_core = 0; + req->limit[1].min_cpu_core = min(sum, get_cluster_max_cpu_core(1)); + ppm_ver("Judge: merge LL and L min core = %d(sum = %d)\n", + req->limit[1].min_cpu_core, sum); +#endif + } else { + ppm_ver("Judge: cannot merge to L! LL min = %d, L min = %d\n", + LL_min_core, L_min_core); + /* check LL max core */ + if (req->limit[0].max_cpu_core < LL_min_core) + req->limit[0].max_cpu_core = LL_min_core; + + return; + } + + if (LL_min_freq > L_min_freq) { + req->limit[1].min_cpufreq_idx = + ppm_main_freq_to_idx(1, LL_min_freq, CPUFREQ_RELATION_L); + ppm_ver("Judge: change L min freq idx to %d due to LL min freq = %d\n", + req->limit[1].min_cpufreq_idx, LL_min_freq); + } + } + } +} + +/* to avoid build error since cpufreq does not provide no lock API for MT6755 */ +#include "mt_cpufreq.h" +unsigned int mt_cpufreq_get_cur_phy_freq_no_lock(unsigned int cluster) +{ + return mt_cpufreq_get_cur_phy_freq(cluster); +} diff --git a/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_platform.h b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..39152224901f0d263c0856be5f184fe0811fe7c9 --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_platform.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#ifndef __MT_PPM_PLATFORM_H__ +#define __MT_PPM_PLATFORM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mach/mt_ppm_api.h" + +/*==============================================================*/ +/* Macros */ +/*==============================================================*/ +/* ppm driver update state to MET directly 0: turn off */ +#define PPM_UPDATE_STATE_DIRECT_TO_MET (1) + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#define PPM_IC_SEGMENT_CHECK (1) +#define PPM_VPROC_5A_LIMIT_CHECK (1) +#define PPM_5A_LIMIT_FREQ_IDX (1) +#endif + +#define PPM_HW_OCP_SUPPORT (0) +#define PPM_DLPT_ENHANCEMENT (0) + +/* for COBRA algo */ +#define PPM_COBRA_USE_CORE_LIMIT (1) +#define PPM_COBRA_NEED_OPP_MAPPING (0) +#define PPM_COBRA_RUNTIME_CALC_DELTA (0) +#ifdef PPM_COBRA_USE_CORE_LIMIT +#define PPM_COBRA_MAX_FREQ_IDX (COBRA_OPP_NUM) +#else +#define PPM_COBRA_MAX_FREQ_IDX (COBRA_OPP_NUM-1) +#endif +#define COBRA_OPP_NUM (8) +#define TOTAL_CORE_NUM (CORE_NUM_LL+CORE_NUM_L) +#define CORE_NUM_LL (4) +#define CORE_NUM_L (4) + +/* DLPT */ +#define PPM_DLPT_DEFAULT_MODE (SW_MODE) +#define DLPT_MAX_REAL_POWER_FY (3890) +#define DLPT_MAX_REAL_POWER_SB (4992) + +/* other policy settings */ +#define LCMOFF_MIN_FREQ (598000) +#define PTPOD_FREQ_IDX (3) +#define SUSPEND_FREQ_LL (689000) +#define SUSPEND_FREQ_L (871000) +#define PWRTHRO_BAT_PER_MW (610) +#define PWRTHRO_BAT_OC_MW (610) +#define PWRTHRO_LOW_BAT_LV1_MW (610) +#define PWRTHRO_LOW_BAT_LV2_MW (610) + +#define FREQ_LIMIT_FOR_KE (800000) + +#define NR_CLUSTERS (2) +#define DVFS_OPP_NUM (8) + +#define PPM_DEFAULT_HOLD_TIME (4) +#define PPM_DEFAULT_FREQ_HOLD_TIME (4) +#define PPM_DEFAULT_DELTA (20) +#define PPM_LOADING_UPPER (400) +#define PPM_TLP_CRITERIA (400) + +#define get_cluster_lcmoff_min_freq(id) LCMOFF_MIN_FREQ /* the same for each cluster */ +#define get_cluster_ptpod_fix_freq_idx(id) PTPOD_FREQ_IDX /* the same for each cluster */ +#define get_cluster_suspend_fix_freq(id) \ + ((id == 0) ? SUSPEND_FREQ_LL : SUSPEND_FREQ_L) +#define get_max_real_power_by_segment(seg) \ + ((ppm_main_info.dvfs_tbl_type == DVFS_TABLE_TYPE_SB) ? DLPT_MAX_REAL_POWER_SB \ + : DLPT_MAX_REAL_POWER_FY) + +/*==============================================================*/ +/* Enum */ +/*==============================================================*/ +enum ppm_power_state { + PPM_POWER_STATE_LL_ONLY = 0, + PPM_POWER_STATE_L_ONLY, + PPM_POWER_STATE_4LL_L, + PPM_POWER_STATE_4L_LL, /* Need this? */ + + PPM_POWER_STATE_NONE, /* HICA disabled */ + NR_PPM_POWER_STATE = PPM_POWER_STATE_NONE, +}; + +enum ppm_cluster { + PPM_CLUSTER_LL = 0, + PPM_CLUSTER_L, + + NR_PPM_CLUSTERS, +}; + +/*==============================================================*/ +/* Data Structures */ +/*==============================================================*/ +struct ppm_pwr_idx_ref_tbl { + const unsigned int core_dynamic_power_TT[DVFS_OPP_NUM]; + const unsigned int core_dynamic_power_FF[DVFS_OPP_NUM]; + unsigned int core_dynamic_power[DVFS_OPP_NUM]; + const unsigned int core_total_power_TT[DVFS_OPP_NUM]; + const unsigned int core_total_power_FF[DVFS_OPP_NUM]; + unsigned int core_total_power[DVFS_OPP_NUM]; + const unsigned int l2_power_TT[DVFS_OPP_NUM]; + const unsigned int l2_power_FF[DVFS_OPP_NUM]; + unsigned int l2_power[DVFS_OPP_NUM]; +}; + +struct ppm_pwr_idx_ref_tbl_data { + struct ppm_pwr_idx_ref_tbl *pwr_idx_ref_tbl; + const unsigned int nr_pwr_idx_ref_tbl; +}; + +struct ppm_cobra_basic_pwr_data { + unsigned int perf_idx; + unsigned int power_idx; +}; + +struct ppm_cobra_delta_data { + unsigned int delta_pwr; +#if 0 + unsigned int delta_perf; + unsigned int delta_eff; +#endif +}; + +struct ppm_cobra_data { + struct ppm_cobra_basic_pwr_data basic_pwr_tbl[TOTAL_CORE_NUM][DVFS_OPP_NUM]; +#if !PPM_COBRA_RUNTIME_CALC_DELTA + struct ppm_cobra_delta_data delta_tbl_LxLL[CORE_NUM_L+1][CORE_NUM_LL+1][COBRA_OPP_NUM]; +#endif +}; + +/*==============================================================*/ +/* Global Variables */ +/*==============================================================*/ +extern struct ppm_cobra_data cobra_tbl; + +/*==============================================================*/ +/* APIs */ +/*==============================================================*/ +#ifdef PPM_IC_SEGMENT_CHECK +extern enum ppm_power_state ppm_check_fix_state_by_segment(void); +#endif + +/* to avoid build error */ +extern unsigned int mt_cpufreq_get_cur_phy_freq_no_lock(unsigned int cluster); + + +extern struct ppm_pwr_idx_ref_tbl_data ppm_get_pwr_idx_ref_tbl(void); +extern int *ppm_get_perf_idx_ref_tbl(enum ppm_cluster cluster); +extern void ppm_power_data_init(void); + +/* COBRA algo */ +extern void ppm_cobra_update_core_limit(unsigned int cluster, int limit); +extern void ppm_cobra_update_freq_limit(unsigned int cluster, int limit); +extern void ppm_cobra_update_limit(enum ppm_power_state new_state, void *user_req); +extern void ppm_cobra_init(void); +extern void ppm_cobra_dump_tbl(struct seq_file *m); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_data.c b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_data.c new file mode 100644 index 0000000000000000000000000000000000000000..7cd8f703107199a628a9ca6ce0b619a61ea43c01 --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_data.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include "mt_ppm_platform.h" +#include "mt_ppm_internal.h" + + +/*==============================================================*/ +/* Power data auto-generated by script */ +/* Note: DO NOT modify it manually!! */ +/*==============================================================*/ +#include "mt_ppm_power_data.h" +/*==============================================================*/ +/* Power Table auto-generated by script end */ +/*==============================================================*/ + + +/* default use FY table, may change to SB/MB if needed */ +#define PWR_IDX_REF_TABLE(name) \ +static struct ppm_pwr_idx_ref_tbl_data pwr_idx_ref_tbl_##name = { \ + .pwr_idx_ref_tbl = cpu_pwr_idx_ref_tbl_##name, \ + .nr_pwr_idx_ref_tbl = ARRAY_SIZE(cpu_pwr_idx_ref_tbl_##name), \ +} + +PWR_IDX_REF_TABLE(FY); +PWR_IDX_REF_TABLE(SB); + + +struct ppm_pwr_idx_ref_tbl_data ppm_get_pwr_idx_ref_tbl(void) +{ + return (ppm_main_info.dvfs_tbl_type == DVFS_TABLE_TYPE_SB) + ? pwr_idx_ref_tbl_SB : pwr_idx_ref_tbl_FY; +} + +int *ppm_get_perf_idx_ref_tbl(enum ppm_cluster cluster) +{ + if (cluster >= NR_PPM_CLUSTERS) + return NULL; + + return (ppm_main_info.dvfs_tbl_type == DVFS_TABLE_TYPE_SB) + ? cpu_perf_idx_ref_tbl_SB[cluster] : cpu_perf_idx_ref_tbl_FY[cluster]; +} + +void ppm_power_data_init(void) +{ + int i, j; + struct ppm_pwr_idx_ref_tbl_data ref_tbl = ppm_get_pwr_idx_ref_tbl(); + + /* calibrate pwr_idx ref table */ + ppm_info("PPM pwr_idx ref table:\n"); + for_each_ppm_clusters(i) { + for (j = 0; j < DVFS_OPP_NUM; j++) { + /* TODO: HOW to interpolate power_idx? */ +#if 1 + ref_tbl.pwr_idx_ref_tbl[i].core_dynamic_power[j] = + ref_tbl.pwr_idx_ref_tbl[i].core_dynamic_power_TT[j]; + ref_tbl.pwr_idx_ref_tbl[i].core_total_power[j] = + ref_tbl.pwr_idx_ref_tbl[i].core_total_power_TT[j]; + ref_tbl.pwr_idx_ref_tbl[i].l2_power[j] = + ref_tbl.pwr_idx_ref_tbl[i].l2_power_TT[j]; +#else + /* calculate actual dynamic power */ + p_FF = ref_tbl.pwr_idx_ref_tbl[i].core_dynamic_power_FF[j]; + p_TT = ref_tbl.pwr_idx_ref_tbl[i].core_dynamic_power_TT[j]; + ref_tbl.pwr_idx_ref_tbl[i].core_dynamic_power[j] = (big_lkg_efuse >= BIG_LKG_EFUSE_TT) + ? p_TT - (abs(p_FF - p_TT) * lkg_ratio + (100 - 1)) / 100 + : p_TT + (abs(p_FF - p_TT) * lkg_ratio + (100 - 1)) / 100; + + + /* calculate actual total power */ + p_FF = ref_tbl.pwr_idx_ref_tbl[i].core_total_power_FF[j]; + p_TT = ref_tbl.pwr_idx_ref_tbl[i].core_total_power_TT[j]; + ref_tbl.pwr_idx_ref_tbl[i].core_total_power[j] = (big_lkg_efuse >= BIG_LKG_EFUSE_TT) + ? p_TT + (abs(p_FF - p_TT) * lkg_ratio + (100 - 1)) / 100 + : p_TT - (abs(p_FF - p_TT) * lkg_ratio + (100 - 1)) / 100; + + /* calculate actual L2 power */ + p_FF = ref_tbl.pwr_idx_ref_tbl[i].l2_power_FF[j]; + p_TT = ref_tbl.pwr_idx_ref_tbl[i].l2_power_TT[j]; + ref_tbl.pwr_idx_ref_tbl[i].l2_power[j] = (big_lkg_efuse >= BIG_LKG_EFUSE_TT) + ? p_TT + (abs(p_FF - p_TT) * lkg_ratio + (100 - 1)) / 100 + : p_TT - (abs(p_FF - p_TT) * lkg_ratio + (100 - 1)) / 100; +#endif + ppm_info("cluster %d(%d): (%d, %d, %d)\n", i, j, + ref_tbl.pwr_idx_ref_tbl[i].core_dynamic_power[j], + ref_tbl.pwr_idx_ref_tbl[i].core_total_power[j], + ref_tbl.pwr_idx_ref_tbl[i].l2_power[j] + ); + } + } + + ppm_cobra_init(); + + ppm_info("power data init done!\n"); +} + + diff --git a/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_data.h b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_data.h new file mode 100644 index 0000000000000000000000000000000000000000..667041a08868eab8ba3d058f6504a1deb782dc41 --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_data.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +static int cpu_perf_idx_ref_tbl_FY[NR_PPM_CLUSTERS][DVFS_OPP_NUM] = { + {501, 455, 410, 345, 299, 247, 169, 78}, + {904, 826, 748, 598, 514, 436, 332, 143}, +}; + +static int cpu_perf_idx_ref_tbl_SB[NR_PPM_CLUSTERS][DVFS_OPP_NUM] = { + {572, 507, 436, 345, 299, 247, 169, 78}, + {975, 878, 787, 598, 514, 436, 332, 143}, +}; + +static struct ppm_pwr_idx_ref_tbl cpu_pwr_idx_ref_tbl_FY[] = { + [0] = { + {145, 123, 103, 74, 61, 47, 31, 16}, + {145, 123, 103, 74, 61, 47, 31, 16}, + {145, 123, 103, 74, 61, 47, 31, 16}, + {145, 123, 103, 74, 61, 47, 31, 16}, + {145, 123, 103, 74, 61, 47, 31, 16}, + {145, 123, 103, 74, 61, 47, 31, 16}, + {33, 28, 23, 17, 14, 11, 7, 4}, + {33, 28, 23, 17, 14, 11, 7, 4}, + {33, 28, 23, 17, 14, 11, 7, 4}, + }, + [1] = { + {409, 348, 294, 202, 164, 132, 95, 46}, + {409, 348, 294, 202, 164, 132, 95, 46}, + {409, 348, 294, 202, 164, 132, 95, 46}, + {409, 348, 294, 202, 164, 132, 95, 46}, + {409, 348, 294, 202, 164, 132, 95, 46}, + {409, 348, 294, 202, 164, 132, 95, 46}, + {124, 106, 89, 62, 52, 43, 33, 21}, + {124, 106, 89, 62, 52, 43, 33, 21}, + {124, 106, 89, 62, 52, 43, 33, 21}, + }, +}; + +static struct ppm_pwr_idx_ref_tbl cpu_pwr_idx_ref_tbl_SB[] = { + [0] = { + {186, 155, 125, 87, 71, 56, 37, 16}, + {186, 155, 125, 87, 71, 56, 37, 16}, + {186, 155, 125, 87, 71, 56, 37, 16}, + {186, 155, 125, 87, 71, 56, 37, 16}, + {186, 155, 125, 87, 71, 56, 37, 16}, + {186, 155, 125, 87, 71, 56, 37, 16}, + {42, 35, 29, 20, 16, 13, 9, 4}, + {42, 35, 29, 20, 16, 13, 9, 4}, + {42, 35, 29, 20, 16, 13, 9, 4}, + }, + [1] = { + {499, 422, 354, 237, 194, 157, 114, 46}, + {499, 422, 354, 237, 194, 157, 114, 46}, + {499, 422, 354, 237, 194, 157, 114, 46}, + {499, 422, 354, 237, 194, 157, 114, 46}, + {499, 422, 354, 237, 194, 157, 114, 46}, + {499, 422, 354, 237, 194, 157, 114, 46}, + {155, 132, 112, 77, 65, 54, 42, 21}, + {155, 132, 112, 77, 65, 54, 42, 21}, + {155, 132, 112, 77, 65, 54, 42, 21}, + }, +}; + diff --git a/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_state.c b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_state.c new file mode 100644 index 0000000000000000000000000000000000000000..be702956ad11a273cdb8895abe2c880783020ae1 --- /dev/null +++ b/drivers/misc/mediatek/base/power/ppm_v2/src/mach/mt6755/mt_ppm_power_state.c @@ -0,0 +1,523 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include "mt_ppm_platform.h" +#include "mt_ppm_internal.h" + +/*==============================================================*/ +/* Macros */ +/*==============================================================*/ +#define PWR_STATE_INFO(name, type) \ + .min_pwr_idx = 0, \ + .max_perf_idx = ~0, \ + .cluster_limit = &cluster_limit_##name, \ + .transfer_by_pwr = &transfer_by_pwr_##name, \ + .transfer_by_perf = &transfer_by_perf_##name, + +#define LIMIT(fmin, fmax, cmin, cmax) { \ + .min_cpufreq_idx = fmin, \ + .max_cpufreq_idx = fmax, \ + .min_cpu_core = cmin, \ + .max_cpu_core = cmax, \ +} + +#define STATE_LIMIT(name) \ +const struct ppm_state_cluster_limit_data cluster_limit_##name = { \ + .state_limit = state_limit_##name, \ + .size = ARRAY_SIZE(state_limit_##name), \ +} + +#define TRANS_DATA(state, mask, rule, delta, hold, bond, f_hold, tlp) { \ + .next_state = PPM_POWER_STATE_##state, \ + .mode_mask = mask, \ + .transition_rule = rule, \ + .loading_delta = delta, \ + .loading_hold_time = hold, \ + .loading_hold_cnt = 0, \ + .loading_bond = bond, \ + .freq_hold_time = f_hold, \ + .freq_hold_cnt = 0, \ + .tlp_bond = tlp, \ +} + +#define STATE_TRANSFER_DATA_PWR(name) \ +struct ppm_state_transfer_data transfer_by_pwr_##name = { \ + .transition_data = state_pwr_transfer_##name, \ + .size = ARRAY_SIZE(state_pwr_transfer_##name), \ +} + +#define STATE_TRANSFER_DATA_PERF(name) \ +struct ppm_state_transfer_data transfer_by_perf_##name = { \ + .transition_data = state_perf_transfer_##name, \ + .size = ARRAY_SIZE(state_perf_transfer_##name), \ +} + +/*==============================================================*/ +/* Local Functions */ +/*==============================================================*/ +static bool ppm_trans_rule_LL_ONLY_to_L_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_LL_ONLY_to_4LL_L( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_L_ONLY_to_LL_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_L_ONLY_to_4L_LL( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_4LL_L_to_LL_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); +static bool ppm_trans_rule_4L_LL_to_L_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings); + +/*==============================================================*/ +/* Local Variables */ +/*==============================================================*/ +/* cluster limit for each power state */ +static const struct ppm_cluster_limit state_limit_LL_ONLY[] = { + [0] = LIMIT(7, 0, 1, 4), + [1] = LIMIT(7, 0, 0, 0), +}; +STATE_LIMIT(LL_ONLY); + +static const struct ppm_cluster_limit state_limit_L_ONLY[] = { + [0] = LIMIT(7, 0, 0, 0), + [1] = LIMIT(5, 0, 1, 4), +}; +STATE_LIMIT(L_ONLY); + +static const struct ppm_cluster_limit state_limit_4LL_L[] = { + [0] = LIMIT(7, 0, 4, 4), + [1] = LIMIT(7, 0, 1, 4), +}; +STATE_LIMIT(4LL_L); + +static const struct ppm_cluster_limit state_limit_4L_LL[] = { + [0] = LIMIT(7, 0, 1, 4), + [1] = LIMIT(7, 0, 4, 4), +}; +STATE_LIMIT(4L_LL); + +/* state transfer data by power/performance for each state */ +static struct ppm_state_transfer state_pwr_transfer_LL_ONLY[] = { + TRANS_DATA(NONE, 0, NULL, 0, 0, 0, 0, 0), +}; +STATE_TRANSFER_DATA_PWR(LL_ONLY); + +static struct ppm_state_transfer state_perf_transfer_LL_ONLY[] = { + TRANS_DATA( + 4LL_L, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_LL_ONLY_to_4LL_L, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + 0, + PPM_TLP_CRITERIA + ), + TRANS_DATA( + L_ONLY, + PPM_MODE_MASK_JUST_MAKE_ONLY | PPM_MODE_MASK_PERFORMANCE_ONLY, + ppm_trans_rule_LL_ONLY_to_L_ONLY, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + /* PPM_DEFAULT_FREQ_HOLD_TIME, */ + 8, + PPM_TLP_CRITERIA + ), +}; +STATE_TRANSFER_DATA_PERF(LL_ONLY); + +static struct ppm_state_transfer state_pwr_transfer_L_ONLY[] = { + TRANS_DATA( + LL_ONLY, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_L_ONLY_to_LL_ONLY, + 0, + 0, + 0, + PPM_DEFAULT_FREQ_HOLD_TIME, + 0 + ), +}; +STATE_TRANSFER_DATA_PWR(L_ONLY); + +static struct ppm_state_transfer state_perf_transfer_L_ONLY[] = { + TRANS_DATA( + 4L_LL, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_L_ONLY_to_4L_LL, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + 0, + 0 + ), +}; +STATE_TRANSFER_DATA_PERF(L_ONLY); + +static struct ppm_state_transfer state_pwr_transfer_4LL_L[] = { + TRANS_DATA( + LL_ONLY, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_4LL_L_to_LL_ONLY, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + 0, + 0 + ), +}; +STATE_TRANSFER_DATA_PWR(4LL_L); + +static struct ppm_state_transfer state_perf_transfer_4LL_L[] = { + TRANS_DATA(NONE, 0, NULL, 0, 0, 0, 0, 0), +}; +STATE_TRANSFER_DATA_PERF(4LL_L); + +static struct ppm_state_transfer state_pwr_transfer_4L_LL[] = { + TRANS_DATA( + L_ONLY, + PPM_MODE_MASK_ALL_MODE, + ppm_trans_rule_4L_LL_to_L_ONLY, + PPM_DEFAULT_DELTA, + PPM_DEFAULT_HOLD_TIME, + PPM_LOADING_UPPER, + 0, + 0 + ), +}; +STATE_TRANSFER_DATA_PWR(4L_LL); + +static struct ppm_state_transfer state_perf_transfer_4L_LL[] = { + TRANS_DATA(NONE, 0, NULL, 0, 0, 0, 0, 0), +}; +STATE_TRANSFER_DATA_PERF(4L_LL); + + +/* PPM power state static data */ +struct ppm_power_state_data pwr_state_info_FY[NR_PPM_POWER_STATE] = { + [0] = { + .name = __stringify(LL_ONLY), + .state = PPM_POWER_STATE_LL_ONLY, + PWR_STATE_INFO(LL_ONLY, FY) + }, + [1] = { + .name = __stringify(L_ONLY), + .state = PPM_POWER_STATE_L_ONLY, + PWR_STATE_INFO(L_ONLY, FY) + }, + [2] = { + .name = __stringify(4LL_L), + .state = PPM_POWER_STATE_4LL_L, + PWR_STATE_INFO(4LL_L, FY) + }, + [3] = { + .name = __stringify(4L_LL), + .state = PPM_POWER_STATE_4L_LL, + PWR_STATE_INFO(4L_LL, FY) + }, +}; + +struct ppm_power_state_data pwr_state_info_SB[NR_PPM_POWER_STATE] = { + [0] = { + .name = __stringify(LL_ONLY), + .state = PPM_POWER_STATE_LL_ONLY, + PWR_STATE_INFO(LL_ONLY, SB) + }, + [1] = { + .name = __stringify(L_ONLY), + .state = PPM_POWER_STATE_L_ONLY, + PWR_STATE_INFO(L_ONLY, SB) + }, + [2] = { + .name = __stringify(4LL_L), + .state = PPM_POWER_STATE_4LL_L, + PWR_STATE_INFO(4LL_L, SB) + }, + [3] = { + .name = __stringify(4L_LL), + .state = PPM_POWER_STATE_4L_LL, + PWR_STATE_INFO(4L_LL, SB) + }, +}; + +const unsigned int pwr_idx_search_prio[NR_PPM_POWER_STATE][NR_PPM_POWER_STATE] = { + [PPM_POWER_STATE_LL_ONLY] = {PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_L_ONLY] = {PPM_POWER_STATE_LL_ONLY, PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_4LL_L] = {PPM_POWER_STATE_LL_ONLY, PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_4L_LL] = {PPM_POWER_STATE_L_ONLY, PPM_POWER_STATE_LL_ONLY, PPM_POWER_STATE_NONE,}, +}; + +const unsigned int perf_idx_search_prio[NR_PPM_POWER_STATE][NR_PPM_POWER_STATE] = { + [PPM_POWER_STATE_LL_ONLY] = {PPM_POWER_STATE_L_ONLY, PPM_POWER_STATE_4LL_L, PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_L_ONLY] = {PPM_POWER_STATE_4L_LL, PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_4LL_L] = {PPM_POWER_STATE_NONE,}, + [PPM_POWER_STATE_4L_LL] = {PPM_POWER_STATE_NONE,}, +}; + +/*==============================================================*/ +/* Local Function Implementation */ +/*==============================================================*/ +/* transition rules */ +static bool ppm_trans_rule_LL_ONLY_to_L_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + unsigned int cur_freq_LL; + + /* keep in LL_ONLY state if root cluster is fixed at cluster 0 */ + if (ppm_main_info.fixed_root_cluster == 0) + return false; + + /* keep in LL ONLY state if LCM is off */ + if (ppm_lcmoff_is_policy_activated()) + return false; + + /* check loading */ + if (data.ppm_cur_loads > (settings->loading_bond - settings->loading_delta) + && data.ppm_cur_tlp <= settings->tlp_bond) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + /* check freq */ + cur_freq_LL = mt_cpufreq_get_cur_phy_freq(MT_CPU_DVFS_LITTLE); /* FIXME */ + ppm_dbg(HICA, "LL cur freq = %d\n", cur_freq_LL); + + if (cur_freq_LL >= get_cluster_max_cpufreq(0)) { + settings->freq_hold_cnt++; + if (settings->freq_hold_cnt >= settings->freq_hold_time) + return true; + } else + settings->freq_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_LL_ONLY_to_4LL_L( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check loading only */ + if (data.ppm_cur_loads > (settings->loading_bond - settings->loading_delta) + && data.ppm_cur_tlp > settings->tlp_bond) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_L_ONLY_to_LL_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check freq only */ + unsigned int cur_freq_L; + + /* keep in L_ONLY state if root cluster is fixed at cluster 1 */ + if (ppm_main_info.fixed_root_cluster == 1) + return false; + + cur_freq_L = mt_cpufreq_get_cur_phy_freq(MT_CPU_DVFS_BIG); /* FIXME */ + ppm_dbg(HICA, "L cur freq = %d\n", cur_freq_L); + + if (cur_freq_L < get_cluster_max_cpufreq(0)) { + settings->freq_hold_cnt++; + if (settings->freq_hold_cnt >= settings->freq_hold_time) + return true; + } else + settings->freq_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_L_ONLY_to_4L_LL( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check loading only */ + if (data.ppm_cur_loads > (settings->loading_bond - settings->loading_delta)) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_4LL_L_to_LL_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check loading only */ + if (data.ppm_cur_loads <= (settings->loading_bond - settings->loading_delta)) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + return false; +} + +static bool ppm_trans_rule_4L_LL_to_L_ONLY( + struct ppm_hica_algo_data data, struct ppm_state_transfer *settings) +{ + /* check loading only */ + if (data.ppm_cur_loads <= (settings->loading_bond - settings->loading_delta)) { + settings->loading_hold_cnt++; + if (settings->loading_hold_cnt >= settings->loading_hold_time) + return true; + } else + settings->loading_hold_cnt = 0; + + return false; +} + + +/*==============================================================*/ +/* Global Function Implementation */ +/*==============================================================*/ +struct ppm_power_state_data *ppm_get_power_state_info(void) +{ + return (ppm_main_info.dvfs_tbl_type == DVFS_TABLE_TYPE_FY) + ? pwr_state_info_FY : pwr_state_info_SB; +} + +const char *ppm_get_power_state_name(enum ppm_power_state state) +{ + if (state >= NR_PPM_POWER_STATE) + return "NONE"; + + /* the state name is the same between FY and SB */ + return pwr_state_info_FY[state].name; +} + +enum ppm_power_state ppm_change_state_with_fix_root_cluster(enum ppm_power_state cur_state, int cluster) +{ + enum ppm_power_state new_state = cur_state; + + switch (cluster) { + case 0: + if (cur_state == PPM_POWER_STATE_L_ONLY) + new_state = PPM_POWER_STATE_LL_ONLY; + else if (cur_state == PPM_POWER_STATE_4L_LL) + new_state = PPM_POWER_STATE_4LL_L; + break; + case 1: + if (cur_state == PPM_POWER_STATE_LL_ONLY) + new_state = PPM_POWER_STATE_L_ONLY; + else if (cur_state == PPM_POWER_STATE_4LL_L) + new_state = PPM_POWER_STATE_4L_LL; + break; + default: + break; + } + + return new_state; +} + +unsigned int ppm_get_root_cluster_by_state(enum ppm_power_state cur_state) +{ + unsigned int root_cluster = 0; + + switch (cur_state) { + case PPM_POWER_STATE_L_ONLY: + case PPM_POWER_STATE_4L_LL: + root_cluster = 1; + break; + case PPM_POWER_STATE_NONE: + root_cluster = (ppm_main_info.fixed_root_cluster == -1) ? 0 + : (unsigned int)ppm_main_info.fixed_root_cluster; + break; + case PPM_POWER_STATE_LL_ONLY: + case PPM_POWER_STATE_4LL_L: + default: + break; + } + + return root_cluster; +} + +enum ppm_power_state ppm_find_next_state(enum ppm_power_state state, + unsigned int *level, enum power_state_search_policy policy) +{ + const unsigned int *tbl; + enum ppm_power_state new_state; + int keep_going; + + ppm_ver("@%s: state = %s, lv = %d\n", __func__, ppm_get_power_state_name(state), *level); + + if (state >= NR_PPM_POWER_STATE || *level >= NR_PPM_POWER_STATE) + return PPM_POWER_STATE_NONE; + + tbl = (policy == PERFORMANCE) ? perf_idx_search_prio[state] : pwr_idx_search_prio[state]; + + do { + keep_going = 0; + + new_state = tbl[*level]; + + ppm_ver("@%s: new_state = %s, lv = %d\n", __func__, ppm_get_power_state_name(new_state), *level); + + if (new_state == PPM_POWER_STATE_NONE) + break; + + /* check fix root cluster setting */ + switch (ppm_main_info.fixed_root_cluster) { + case 0: + if (new_state == PPM_POWER_STATE_L_ONLY || new_state == PPM_POWER_STATE_4L_LL) { + (*level)++; + keep_going = 1; + } + break; + case 1: + if (new_state == PPM_POWER_STATE_LL_ONLY || new_state == PPM_POWER_STATE_4LL_L) { + (*level)++; + keep_going = 1; + } + break; + default: + break; + } + } while (keep_going); + + return new_state; +} + +#ifdef PPM_IC_SEGMENT_CHECK +enum ppm_power_state ppm_check_fix_state_by_segment(void) +{ + unsigned int segment = get_devinfo_with_index(21) & 0xFF; + enum ppm_power_state fix_state = PPM_POWER_STATE_NONE; + + switch (segment) { + case 0x43: /* fix L only */ + fix_state = PPM_POWER_STATE_L_ONLY; + break; + default: + break; + } + + ppm_info("segment = 0x%x, fix_state = %s\n", segment, ppm_get_power_state_name(fix_state)); + + return fix_state; +} +#endif + diff --git a/drivers/misc/mediatek/base/power/spm_v2/mt_idle_mt6755.c b/drivers/misc/mediatek/base/power/spm_v2/mt_idle_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..fb67d5c2353a99615b4407c98bfc3e1dc14b296c --- /dev/null +++ b/drivers/misc/mediatek/base/power/spm_v2/mt_idle_mt6755.c @@ -0,0 +1,428 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + +#include + +#include "mt_idle_internal.h" + +#define IDLE_TAG "Power/swap" +#define idle_err(fmt, args...) pr_err(IDLE_TAG fmt, ##args) + +enum subsys_id { + SYS_VDE, + SYS_MFG, + SYS_VEN, + SYS_ISP, + SYS_DIS, + SYS_AUDIO, + SYS_MFG_2D, + SYS_MFG_ASYNC, + NR_SYSS__, +}; + +/* + * Variable Declarations + */ +void __iomem *infrasys_base; +void __iomem *mmsys_base; +void __iomem *sleepsys_base; +void __iomem *topcksys_base; +void __iomem *mfgsys_base; +void __iomem *imgsys_base; +void __iomem *vdecsys_base; +void __iomem *vencsys_base; +void __iomem *audiosys_base_in_idle; + +void __iomem *apmixed_base_in_idle; + +/* Idle handler on/off */ +int idle_switch[NR_TYPES] = { + 1, /* dpidle switch */ +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + 1, /* soidle3 switch */ +#else + 0, /* soidle3 switch */ +#endif + 1, /* soidle switch */ +#ifdef CONFIG_CPU_ISOLATION + 1, /* mcidle switch */ +#else + 0, /* mcidle switch */ +#endif + 0, /* slidle switch */ + 1, /* rgidle switch */ +}; + +unsigned int dpidle_blocking_stat[NR_GRPS][32]; + +unsigned int dpidle_condition_mask[NR_GRPS] = { + 0x00640802, /* INFRA0: */ + 0x03AFB900, /* INFRA1: separate I2C-appm CG check */ + 0x000000C7, /* INFRA2: */ + 0x03FFFFFF, /* DISP0: */ + 0x00000312, /* IMAGE, use SPM MTCMOS off as condition: */ + 0x00000112, /* MFG, use SPM MTCMOS off as condition: */ + 0x00000000, /* AUDIO */ + 0x00000112, /* VDEC, use SPM MTCMOS off as condition: */ + 0x00000F12, /* VENC, use SPM MTCMOS off as condition: */ +}; + +unsigned int soidle3_pll_condition_mask[NR_PLLS] = { + 1, /* UNIVPLL */ + 0, /* MMPLL */ + 1, /* MSDCPLL */ + 0, /* VENCPLL */ +}; + +unsigned int soidle3_condition_mask[NR_GRPS] = { + 0x026C0802, /* INFRA0: separate AUXADC CG check */ + 0x03AFB900, /* INFRA1: separate I2C-appm CG check */ + 0x000000D3, /* INFRA2: */ + 0x005023FC, /* DISP0: */ + 0x00000312, /* IMAGE, use SPM MTCMOS off as condition: */ + 0x00000112, /* MFG, use SPM MTCMOS off as condition: */ + 0x00000000, /* AUDIO */ + 0x00000112, /* VDEC, use SPM MTCMOS off as condition: */ + 0x00000F12, /* VENC, use SPM MTCMOS off as condition: */ +}; + +unsigned int soidle_condition_mask[NR_GRPS] = { + 0x00640802, /* INFRA0: */ + 0x03AFB900, /* INFRA1: separate I2C-appm CG check */ + 0x000000C3, /* INFRA2: */ + 0x005023FC, /* DISP0: */ + 0x00000312, /* IMAGE, use SPM MTCMOS off as condition: */ + 0x00000112, /* MFG, use SPM MTCMOS off as condition: */ + 0x00000000, /* AUDIO */ + 0x00000112, /* VDEC, use SPM MTCMOS off as condition: */ + 0x00000F12, /* VENC, use SPM MTCMOS off as condition: */ +}; + +unsigned int slidle_condition_mask[NR_GRPS] = { + 0x00000000, /* INFRA0: */ + 0x00000000, /* INFRA1: */ + 0x00000000, /* INFRA2: */ + 0x00000000, /* DISP0: */ + 0x00000000, /* IMAGE, use SPM MTCMOS off as condition: */ + 0x00000000, /* MFG, use SPM MTCMOS off as condition: */ + 0x00000000, /* AUDIO */ + 0x00000000, /* VDEC, use SPM MTCMOS off as condition: */ + 0x00000000, /* VENC, use SPM MTCMOS off as condition: */ +}; + +const char *idle_name[NR_TYPES] = { + "dpidle", + "soidle3", + "soidle", + "mcidle", + "slidle", + "rgidle", +}; + +const char *reason_name[NR_REASONS] = { + "by_cpu", + "by_clk", + "by_tmr", + "by_oth", + "by_vtg", + "by_frm", + "by_pll", + "by_pwm", +#ifdef CONFIG_CPU_ISOLATION + "by_iso", +#endif + "by_dvfsp", + "by_conn", +}; + +static char cg_group_name[NR_GRPS][10] = { + "INFRA0", + "INFRA1", + "INFRA2", + "DISP0", + "IMAGE", + "MFG", + "AUDIO", + "VDEC", + "VENC", +}; + +/* + * Weak functions + */ +void __attribute__((weak)) msdc_clk_status(int *status) +{ + *status = 0; +} + +/* + * Function Definitions + */ +static int sys_is_on(enum subsys_id id) +{ + u32 pwr_sta_mask[] = { + VDE_PWR_STA_MASK, + MFG_PWR_STA_MASK, + VEN_PWR_STA_MASK, + ISP_PWR_STA_MASK, + DIS_PWR_STA_MASK, + AUDIO_PWR_STA_MASK, + MFG_2D_PWR_STA_MASK, + MFG_ASYNC_PWR_STA_MASK, + }; + + u32 mask = pwr_sta_mask[id]; + u32 sta = idle_readl(SPM_PWR_STATUS); + u32 sta_s = idle_readl(SPM_PWR_STATUS_2ND); + + if (id >= NR_SYSS__) + BUG(); + + return (sta & mask) && (sta_s & mask); +} + +static void get_all_clock_state(u32 clks[NR_GRPS]) +{ + int i; + + for (i = 0; i < NR_GRPS; i++) + clks[i] = 0; + + clks[CG_INFRA0] = ~idle_readl(INFRA_SW_CG_0_STA); /* INFRA0 */ + clks[CG_INFRA1] = ~idle_readl(INFRA_SW_CG_1_STA); /* INFRA1 */ + clks[CG_INFRA2] = ~idle_readl(INFRA_SW_CG_2_STA); /* INFRA2 */ + + if (sys_is_on(SYS_DIS)) + clks[CG_DISP0] = ~idle_readl(DISP_CG_CON0); /* DISP */ + + if (sys_is_on(SYS_ISP)) + clks[CG_IMAGE] = ~idle_readl(SPM_ISP_PWR_CON); /* IMAGE */ + + if (sys_is_on(SYS_MFG)) + clks[CG_MFG] = ~idle_readl(SPM_MFG_PWR_CON); /* MFG */ + + if (sys_is_on(SYS_VDE)) + clks[CG_VDEC] = ~idle_readl(SPM_VDE_PWR_CON); /* VDEC */ + + if (sys_is_on(SYS_VEN)) + clks[CG_VENC] = ~idle_readl(SPM_VEN_PWR_CON); /* VENC */ + + if (sys_is_on(SYS_AUDIO)) + clks[CG_AUDIO] = ~idle_readl(AUDIO_TOP_CON0); /* AUDIO */ +} + +bool cg_check_idle_can_enter( + unsigned int *condition_mask, unsigned int *block_mask, enum mt_idle_mode mode) +{ + int i; + unsigned int sd_mask = 0; + u32 clks[NR_GRPS]; + u32 r = 0; + unsigned int sta; + bool ret = true; + int k; + + /* SD status */ + msdc_clk_status(&sd_mask); + if (sd_mask) { + block_mask[CG_INFRA0] |= sd_mask; + ret = false; + } + + /* CG status */ + get_all_clock_state(clks); + + for (i = 0; i < NR_GRPS; i++) { + block_mask[i] = condition_mask[i] & clks[i]; + r |= block_mask[i]; + } + + if (!(r == 0)) + ret = false; + + if (mode == MT_DPIDLE) { + for (i = 0; i < NR_GRPS; i++) { + for (k = 0; k < 32; k++) { + if (block_mask[i] & (1 << k)) + dpidle_blocking_stat[i][k] += 1; + } + } + } + + /* MTCMOS status */ + sta = idle_readl(SPM_PWR_STATUS); + if (mode == MT_DPIDLE) { + if (!dpidle_by_pass_pg) { + if (sta & (MFG_PWR_STA_MASK | + ISP_PWR_STA_MASK | + VDE_PWR_STA_MASK | + VEN_PWR_STA_MASK | + DIS_PWR_STA_MASK)) + return false; + } + } else if (mode == MT_SOIDLE) { + if (!soidle_by_pass_pg) { + if (sta & (MFG_PWR_STA_MASK | + ISP_PWR_STA_MASK | + VDE_PWR_STA_MASK | + VEN_PWR_STA_MASK)) + return false; + } + } + + return ret; +} + +bool cg_i2c_appm_check_idle_can_enter(unsigned int *block_mask) +{ + u32 clk_stat = ~idle_readl(INFRA_SW_CG_1_STA); /* INFRA1 */ + + if ((clk_stat & 0x00004000) == 0x00004000) { + block_mask[CG_INFRA1] |= 0x00004000; + return false; + } + + return true; +} + +char pll_name[NR_PLLS][10] = { + "UNIVPLL", + "MMPLL", + "MSDCPLL", + "VENCPLL", +}; + +const char *pll_grp_get_name(int id) +{ + return pll_name[id]; +} + +int is_pll_on(int id) +{ + return idle_readl(APMIXEDSYS(0x230 + id * 0x10)) & 0x1; +} + +bool pll_check_idle_can_enter(unsigned int *condition_mask, unsigned int *block_mask) +{ + int i, j; + unsigned int pll_mask; + + memset(block_mask, 0, NR_PLLS * sizeof(unsigned int)); + + for (i = 0; i < NR_PLLS; i++) { + pll_mask = is_pll_on(i) & condition_mask[i]; + if (pll_mask) { + for (j = 0; j < NR_PLLS; j++) + block_mask[j] = is_pll_on(j) & condition_mask[j]; + + return false; + } + } + + return true; +} + +static int __init get_base_from_matching_node( + const struct of_device_id *ids, void __iomem **pbase, int idx, const char *cmp) +{ + struct device_node *node; + + node = of_find_matching_node(NULL, ids); + if (!node) { + idle_err("node '%s' not found!\n", cmp); + /* TODO: BUG() */ + } + + *pbase = of_iomap(node, idx); + if (!(*pbase)) { + idle_err("node '%s' cannot iomap!\n", cmp); + /* TODO: BUG() */ + } + + return 0; +} + +static int __init get_base_from_node( + const char *cmp, void __iomem **pbase, int idx) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, cmp); + + if (!node) { + idle_err("node '%s' not found!\n", cmp); + /* TODO: BUG() */ + } + + *pbase = of_iomap(node, idx); + if (!(*pbase)) { + idle_err("node '%s' cannot iomap!\n", cmp); + /* TODO: BUG() */ + } + + return 0; +} + +void __init iomap_init(void) +{ + static const struct of_device_id audiosys_ids[] = { + {.compatible = "mediatek,audio"}, + {.compatible = "mediatek,mt6755-audiosys"}, + { /* sentinel */ } + }; + + get_base_from_node("mediatek,infracfg_ao", &infrasys_base, 0); + get_base_from_node("mediatek,mmsys_config", &mmsys_base, 0); + get_base_from_node("mediatek,sleep", &sleepsys_base, 0); + get_base_from_node("mediatek,topckgen", &topcksys_base, 0); + get_base_from_node("mediatek,apmixed", &apmixed_base_in_idle, 0); + get_base_from_node("mediatek,mt6755-mfgsys", &mfgsys_base, 0); + get_base_from_node("mediatek,mt6755-imgsys", &imgsys_base, 0); + get_base_from_node("mediatek,mt6755-vdecsys", &vdecsys_base, 0); + get_base_from_node("mediatek,mt6755-vencsys", &vencsys_base, 0); + + get_base_from_matching_node(audiosys_ids, &audiosys_base_in_idle, 0, "audio"); +} + +const char *cg_grp_get_name(int id) +{ + BUG_ON(INVALID_GRP_ID(id)); + return cg_group_name[id]; +} + +bool is_disp_pwm_rosc(void) +{ + u32 sta = idle_readl(CLK_CFG_7) & 0x3; + + return (sta == 2) || (sta == 3); +} + +bool is_auxadc_released(void) +{ +#if 0 + if ((~idle_readl(INFRA_SW_CG_0_STA) & 0x400) == 0x400) { + idle_err("AUXADC CG does not be released\n"); + return false; + } +#endif + + return true; +} + +bool vcore_dvfs_is_progressing(void) +{ + return false; +} diff --git a/drivers/misc/mediatek/base/power/spm_v2/mt_spm_dpidle_mt6755.c b/drivers/misc/mediatek/base/power/spm_v2/mt_spm_dpidle_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..529518ab740b3d1fbaa07b261299d827857f4d65 --- /dev/null +++ b/drivers/misc/mediatek/base/power/spm_v2/mt_spm_dpidle_mt6755.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + +#include + +#include "mt_spm.h" +#include "mt_spm_internal.h" +#include "mt_spm_pmic_wrap.h" +#include + +static u32 ap_pll_con0_val; +static void __iomem *apmixedsys_base_in_dpidle; + +#define APMIXED_REG(ofs) (apmixedsys_base_in_dpidle + ofs) + +#define AP_PLL_CON0 APMIXED_REG(0x0) + +/* #define PMIC_CLK_SRC_BY_SRCCLKEN_IN1 */ + +void spm_dpidle_pre_process(void) +{ + u32 value = 0; + + __spm_pmic_pg_force_on(); + + spm_pmic_power_mode(PMIC_PWR_DEEPIDLE, 0, 0); + + spm_bypass_boost_gpio_set(); + + /* Update PMIC wrap table: deepidle */ + value = 0; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_read_interface_nolock(PMIC_LDO_VSRAM_PROC_VOSEL_ON_ADDR, + &value, + PMIC_LDO_VSRAM_PROC_VOSEL_ON_MASK, + PMIC_LDO_VSRAM_PROC_VOSEL_ON_SHIFT); +#else + pmic_read_interface_nolock(MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_ADDR, + &value, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_SHIFT); +#endif + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, IDX_DI_VSRAM_NORMAL, value); + + value = 0; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_read_interface_nolock(PMIC_RG_SRCLKEN_IN2_EN_ADDR, &value, 0x037F, 0); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, + IDX_DI_SRCCLKEN_IN2_NORMAL, + value | (1 << PMIC_RG_SRCLKEN_IN2_EN_SHIFT)); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, + IDX_DI_SRCCLKEN_IN2_SLEEP, + value & ~(1 << PMIC_RG_SRCLKEN_IN2_EN_SHIFT)); +#else + pmic_read_interface_nolock(MT6351_TOP_CON, &value, 0x037F, 0); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, + IDX_DI_SRCCLKEN_IN2_NORMAL, + value | (1 << MT6351_PMIC_RG_SRCLKEN_IN2_EN_SHIFT)); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, + IDX_DI_SRCCLKEN_IN2_SLEEP, + value & ~(1 << MT6351_PMIC_RG_SRCLKEN_IN2_EN_SHIFT)); +#endif + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_read_interface_nolock(PMIC_BUCK_VPROC_VOSEL_ON_ADDR, + &value, + PMIC_BUCK_VPROC_VOSEL_ON_MASK, + PMIC_BUCK_VPROC_VOSEL_ON_SHIFT); + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_DEEPIDLE, IDX_DI_VPROC_NORMAL, value); +#else + /* nothing */ +#endif + + /* set PMIC WRAP table for deepidle power control */ + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_DEEPIDLE); + + /* Do more low power setting when MD1/C2K/CONN off */ + if (is_md_c2k_conn_power_off()) { + __spm_bsi_top_init_setting(); + + __spm_backup_pmic_ck_pdn(); + + /* disable 26M clks: MIPID, MIPIC1, MIPIC0, MDPLLGP, SSUSB */ + ap_pll_con0_val = spm_read(AP_PLL_CON0); + spm_write(AP_PLL_CON0, ap_pll_con0_val & (~0x18D0)); +#if defined(PMIC_CLK_SRC_BY_SRCCLKEN_IN1) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_config_interface_nolock(MT6353_BUCK_ALL_CON2, 0x111, 0x3FF, 0); +#else + pmic_config_interface_nolock(MT6351_BUCK_ALL_CON2, 0x111, 0x3FF, 0); +#endif +#endif + clk_buf_control_bblpm(true); + } +} + +void spm_dpidle_post_process(void) +{ + /* Do more low power setting when MD1/C2K/CONN off */ + if (is_md_c2k_conn_power_off()) { + clk_buf_control_bblpm(false); + +#if defined(PMIC_CLK_SRC_BY_SRCCLKEN_IN1) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_config_interface_nolock(MT6353_BUCK_ALL_CON2, 0x0, 0x3FF, 0); +#else + pmic_config_interface_nolock(MT6351_BUCK_ALL_CON2, 0x0, 0x3FF, 0); +#endif +#endif + /* Enable 26M clks: MIPID, MIPIC1, MIPIC0, MDPLLGP, SSUSB */ + spm_write(AP_PLL_CON0, ap_pll_con0_val); + + __spm_restore_pmic_ck_pdn(); + } + + /* set PMIC WRAP table for normal power control */ + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_NORMAL); + + __spm_pmic_pg_force_off(); +} + +static int __init get_base_from_node( + const char *cmp, void __iomem **pbase, int idx) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, cmp); + + if (!node) { + pr_err("node '%s' not found!\n", cmp); + /* TODO: BUG() */ + } + + *pbase = of_iomap(node, idx); + if (!(*pbase)) { + pr_err("node '%s' cannot iomap!\n", cmp); + /* TODO: BUG() */ + } + + return 0; +} + +void spm_deepidle_chip_init(void) +{ + get_base_from_node("mediatek,apmixed", &apmixedsys_base_in_dpidle, 0); +} + diff --git a/drivers/misc/mediatek/base/power/spm_v2/mt_spm_vcorefs_mt6755.c b/drivers/misc/mediatek/base/power/spm_v2/mt_spm_vcorefs_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..68b57cc5be33a60a322783c33b35476224bbd376 --- /dev/null +++ b/drivers/misc/mediatek/base/power/spm_v2/mt_spm_vcorefs_mt6755.c @@ -0,0 +1,766 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include "mt_spm_vcore_dvfs.h" +#include "mt_vcorefs_governor.h" + +#include "upmu_common.h" + +#include +#include +#include + +#include "mt_spm_internal.h" +#include "mt_spm_pmic_wrap.h" + +/* + * Define and Declare + */ +#define SPM_DVFS_TIMEOUT 2000 +#define SPM_DVFS_HPM 1 +#define SPM_DVFS_LPM 0 + +#define SPM_CHK_GUARD_TIME 10 +#define SPM_HPM_HOLD_TIME 1000 +/* PCM_REG6_DATA */ +#define SPM_FLAG_DVFS_ACTIVE (1<<23) /* bit 23 */ +#define SPM_FLAG_DVFS_STATE (1<<24) +/* bw threshold for SPM_SW_RSV_5, SPM_SW_RSV_4 */ +#define HPM_THRES_OFFSET 16 +#define LPM_THRES_OFFSET 24 + + +/* r6[31] = 1 for DVFS UP, 0 for DVFS DOWN */ +#define is_dvfs_in_progress() (spm_read(PCM_REG6_DATA) & SPM_FLAG_DVFS_ACTIVE) + +#ifdef CONFIG_MTK_RAM_CONSOLE +#define VCOREFS_AEE_RR_REC 1 +#else +#define VCOREFS_AEE_RR_REC 0 +#endif + +#if VCOREFS_AEE_RR_REC +enum spm_vcorefs_step { + SPM_VCOREFS_ENTER = 0, + SPM_VCOREFS_DVFS_START, + SPM_VCOREFS_DVFS_END, + SPM_VCOREFS_LEAVE, +}; + +void set_aee_vcore_dvfs_status(int state) +{ + u32 value = aee_rr_curr_vcore_dvfs_status(); + + value &= ~(0x000000FF); + value |= (state & 0x000000FF); + aee_rr_rec_vcore_dvfs_status(value); +} +#else +void set_aee_vcore_dvfs_status(int state) +{ + /* nothing */ +} +#endif + +/* FW is loaded by dyna_load_fw from binary */ +#if 0 +static const u32 vcore_dvfs_binary[] = { +}; + +static struct pcm_desc vcore_dvfs_pcm = { + .version = "pcm_vcore_dvfs_v0.1.2_20150323", + .base = vcore_dvfs_binary, + .size = 295, + .sess = 1, + .replace = 1, + .vec0 = EVENT_VEC(23, 1, 0, 78), /* FUNC_MD_VRF18_WAKEUP */ + .vec1 = EVENT_VEC(28, 1, 0, 101), /* FUNC_MD_VRF18_SLEEP */ + .vec2 = EVENT_VEC(11, 1, 0, 124), /* FUNC_VCORE_HIGH */ + .vec3 = EVENT_VEC(12, 1, 0, 159), /* FUNC_VCORE_LOW */ +}; +#endif + +static struct pwr_ctrl vcore_dvfs_ctrl = { +#if 1 + /* default VCORE DVFS is disabled */ + .pcm_flags = (SPM_FLAG_DIS_VCORE_DVS | SPM_FLAG_DIS_VCORE_DFS), +#endif + .wake_src = WAKE_SRC_R12_PCM_TIMER, + /* SPM general */ + .r0_ctrl_en = 1, + .r7_ctrl_en = 1, + + /* VCORE DVFS Logic pwr_ctrl */ + .dvfs_halt_mask_b = 0x07, /* 5 bit *//* todo: enable for isp/disp, disable gce */ + .sdio_on_dvfs_req_mask_b = 0, + + .cpu_md_dvfs_erq_merge_mask_b = 1, /* HPM request by WFD/MHL/MD */ + + .md1_ddr_en_dvfs_halt_mask_b = 0, + .md2_ddr_en_dvfs_halt_mask_b = 0, + + .md_srcclkena_0_dvfs_req_mask_b = 0, + .md_srcclkena_1_dvfs_req_mask_b = 0, + .conn_srcclkena_dvfs_req_mask_b = 0, + + .vsync_dvfs_halt_mask_b = 0x0, /* 5 bit */ + .emi_boost_dvfs_req_mask_b = 0, + .cpu_md_emi_dvfs_req_prot_dis = 1, /* todo: enable by MD if need check MD_SRCCLKEMA_0 */ + + .spm_dvfs_req = 1, /* set to 1 for keep high after fw loading */ + .spm_dvfs_force_down = 1, + .cpu_md_dvfs_sop_force_on = 0, + + .emi_bw_dvfs_req_mask = 1, /* default disable, enable by fliper */ + .emi_boost_dvfs_req_mask_b = 0, /* default disable, enable by fliper */ + + .dvfs_halt_src_chk = 1, + + /* +450 SPM_EMI_BW_MODE */ + /* [0]EMI_BW_MODE, [1]EMI_BOOST_MODE default is 0 */ + +}; + +struct spm_lp_scen __spm_vcore_dvfs = { + /*.pcmdesc = &vcore_dvfs_pcm, */ + .pwrctrl = &vcore_dvfs_ctrl, +}; + +/* + * Macro and Inline + */ +inline int _wait_spm_dvfs_idle(int timeout) +{ + int i = 0; + u32 val = spm_read(PCM_REG6_DATA); + + while (!((val & SPM_FLAG_DVFS_ACTIVE) == 0)) { + if (i >= timeout) { + i = -EBUSY; + break; + } + udelay(1); + val = spm_read(PCM_REG6_DATA); + i++; + } + return i; +} + + +static inline int _wait_spm_dvfs_complete(int opp, int timeout) +{ + int i = 0; + int target = (opp == OPPI_PERF) ? SPM_DVFS_HPM : SPM_DVFS_LPM; + u32 val; + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + bool partial = ((pwrctrl->pcm_flags & SPM_FLAG_DIS_VCORE_DFS) != 0); + + /* wait 10 usec before check status */ + udelay(SPM_CHK_GUARD_TIME); + + val = spm_read(PCM_REG6_DATA); + if (partial == true) { + udelay(SPM_CHK_GUARD_TIME*10); + spm_vcorefs_info("hh: skip chk idle instead of comp (flags=0x%x) udelay(%d)\n", + pwrctrl->pcm_flags, SPM_CHK_GUARD_TIME*10); + while (!((val & SPM_FLAG_DVFS_ACTIVE) == 0)) { + if (i >= timeout) { + i = -EBUSY; + break; + } + udelay(1); + val = spm_read(PCM_REG6_DATA); + i++; + } + } else { + while (!(((val & SPM_FLAG_DVFS_ACTIVE) == 0) + && ((val & SPM_FLAG_DVFS_STATE) == (target << 24)))) { + if (i >= timeout) { + i = -EBUSY; + break; + } + udelay(1); + val = spm_read(PCM_REG6_DATA); + i++; + } + } + return i; +} + +/************************************** + * Static function + **************************************/ +bool _get_total_bw_enable(void) +{ + bool enabled = true; + + if ((spm_read(SPM_SRC_MASK) & EMI_BW_DVFS_REQ_MASK_LSB) != 0) + enabled = false; + else + enabled = true; + + return enabled; +} + +/* get SPM DVFS Logic output */ +int _find_spm_dvfs_result(int opp) +{ + int expect_opp; + u32 val = spm_read(SPM_SRC_REQ); + bool is_forced_hpm = (val & SPM_DVFS_REQ_LSB) ? true : false; + bool is_forced_lpm = (val & SPM_DVFS_FORCE_DOWN_LSB) ? true : false; + bool is_cpu_md_dvfs_sop_force_on = (val & CPU_MD_DVFS_SOP_FORCE_ON_LSB) ? true : false; + u32 CPU_val = spm_read(CPU_DVFS_REQ) & 0xFFFF; + u32 MD2SPM_val = spm_read(MD2SPM_DVFS_CON) & 0xFFFF; + + if (is_forced_lpm == true) + expect_opp = OPPI_LOW_PWR; + else if (is_forced_hpm == true) + expect_opp = OPPI_PERF; + else if (is_cpu_md_dvfs_sop_force_on == true) + expect_opp = OPPI_PERF; + else { + if ((CPU_val & MD2SPM_val) != 0) + expect_opp = OPPI_PERF; + else + expect_opp = OPPI_LOW_PWR; + } + + return expect_opp; + +} + +static void dump_pmic_info(void) +{ + u32 ret, reg_val; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + ret = pmic_read_interface_nolock(MT6353_WDTDBG_CON1, ®_val, 0xffff, 0); + spm_notice("[PMIC]wdtdbg_con1=0x%x\n", reg_val); + ret = pmic_read_interface_nolock(MT6353_BUCK_VCORE_HWM_CON0, ®_val, 0xffff, 0); + spm_notice("[PMIC]vcore vosel_ctrl=0x%x\n", reg_val); + ret = pmic_read_interface_nolock(MT6353_BUCK_VCORE_VOL_CON1, ®_val, 0xffff, 0); + spm_notice("[PMIC]vcore vosel=0x%x\n", reg_val); + ret = pmic_read_interface_nolock(MT6353_BUCK_VCORE_VOL_CON2, ®_val, 0xffff, 0); + spm_notice("[PMIC]vcore vosel_on=0x%x\n", reg_val); +#else + ret = pmic_read_interface_nolock(MT6351_WDTDBG_CON1, ®_val, 0xffff, 0); + spm_notice("[PMIC]wdtdbg_con1=0x%x\n", reg_val); + + ret = pmic_read_interface_nolock(MT6351_BUCK_VCORE_CON0, ®_val, 0xffff, 0); + spm_notice("[PMIC]vcore vosel_ctrl=0x%x\n", reg_val); + + ret = pmic_read_interface_nolock(MT6351_BUCK_VCORE_CON4, ®_val, 0xffff, 0); + spm_notice("[PMIC]vcore vosel=0x%x\n", reg_val); + + ret = pmic_read_interface_nolock(MT6351_BUCK_VCORE_CON5, ®_val, 0xffff, 0); + spm_notice("[PMIC]vcore vosel_on=0x%x\n", reg_val); +#endif +} + +static int _check_dvfs_result(int vcore, int ddr) +{ + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + int vcore_val = 0; + int ddr_val = 0; + int r = 0; + + bool dvs_en = ((pwrctrl->pcm_flags & SPM_FLAG_DIS_VCORE_DVS) == 0); + bool dfs_en = ((pwrctrl->pcm_flags & SPM_FLAG_DIS_VCORE_DFS) == 0); + + if (dvs_en == true) { + vcore_val = vcorefs_get_curr_vcore(); + if (vcore_val != vcore) { + spm_vcorefs_err("VCORE FAIL: %d(%d)\n", vcore_val, vcore); + spm_vcorefs_dump_dvfs_regs(NULL); + pwrap_dump_all_register(); /* pwrap debug msg */ + dump_pmic_info(); + spm_vcorefs_aee_exception("VCORE FAIL: %d(%d)\n", + vcore_val, vcorefs_get_curr_vcore()); + r = -1; + } + } + + if (dfs_en == true) { + ddr_val = vcorefs_get_curr_ddr(); + if (ddr_val != ddr) { + spm_vcorefs_err("DDR FAIL: %d(%d)\n", ddr_val, ddr); + spm_vcorefs_dump_dvfs_regs(NULL); + spm_vcorefs_aee_exception("DDR FAIL: %d(%d)\n", + ddr_val, vcorefs_get_curr_ddr()); + r = -1; + } + } + return r; +} + + +static void __go_to_vcore_dvfs(u32 spm_flags, u32 spm_data) +{ + struct pcm_desc *pcmdesc = __spm_sodi.pcmdesc; + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + + if (!dyna_load_pcm[DYNA_LOAD_PCM_SODI].ready) { + spm_vcorefs_err("LOAD FIRMWARE FAIL\n"); + BUG(); + } + pcmdesc = &(dyna_load_pcm[DYNA_LOAD_PCM_SODI].desc); + + set_pwrctrl_pcm_flags(pwrctrl, spm_flags); + + __spm_reset_and_init_pcm(pcmdesc); + + __spm_kick_im_to_fetch(pcmdesc); + + __spm_init_pcm_register(); + + __spm_init_event_vector(pcmdesc); + + __spm_set_power_control(pwrctrl); + + __spm_set_wakeup_event(pwrctrl); + + __spm_kick_pcm_to_run(pwrctrl); +} + + +void _spm_vcorefs_init_reg(void) +{ + u32 mask; + + /* set en_spm2cksys_mem_ck_mux_update for SPM control */ + spm_write((spm_cksys_base + 0x40), (spm_read(spm_cksys_base + 0x40) | (0x1 << 13))); + + /* SPM_EMI_BW_MODE[0]&[1] set to 0 */ + mask = (EMI_BW_MODE_LSB | EMI_BOOST_MODE_LSB); + spm_write(SPM_EMI_BW_MODE, spm_read(SPM_EMI_BW_MODE) & ~(mask)); + + /* Set dummy read address */ + /* This task is done in spm_module_init */ + + /* SPM_SW_RSV5[0] init is moved to caller, only need first time */ + + /* other setting is set by __spm_set_power_control */ + + spm_vcorefs_info("EMI_BW_MODE=0x%8x\n", spm_read(SPM_EMI_BW_MODE)); + spm_vcorefs_info("SPM_SW_RSV_4=0x%8x\n", spm_read(SPM_SW_RSV_4)); + spm_vcorefs_info("SPM_SW_RSV_5=0x%8x\n", spm_read(SPM_SW_RSV_5)); + spm_vcorefs_info("SPM_PASR_DPD_1=0x%8x\n", spm_read(SPM_PASR_DPD_1)); + spm_vcorefs_info("SPM_PASR_DPD_2=0x%8x\n", spm_read(SPM_PASR_DPD_2)); + spm_vcorefs_info("SPM_SRC2_MASK=0x%8x\n", spm_read(SPM_SW_RSV_4)); + spm_vcorefs_info("SPM_SRC_MASK=0x%8x\n", spm_read(SPM_SW_RSV_5)); + spm_vcorefs_info("CLK_CFG_0=0x%8x\n", spm_read(spm_cksys_base + 0x40)); +} + +/* + * External Function + */ +char *spm_vcorefs_dump_dvfs_regs(char *p) +{ + if (p) { + p += sprintf(p, "MD2SPM_DVFS_CON : 0x%x\n", spm_read(MD2SPM_DVFS_CON)); + p += sprintf(p, "CPU_DVFS_REQ: 0x%x\n", spm_read(CPU_DVFS_REQ)); + p += sprintf(p, "SPM_SRC_REQ: 0x%x\n", spm_read(SPM_SRC_REQ)); + p += sprintf(p, "SPM_SRC_MASK: 0x%x\n", spm_read(SPM_SRC_MASK)); + p += sprintf(p, "SPM_SRC2_MASK : 0x%x\n", spm_read(SPM_SRC2_MASK)); + p += sprintf(p, "SPM_SW_RSV_4 : 0x%x\n", spm_read(SPM_SW_RSV_4)); + p += sprintf(p, "SPM_SW_RSV_5 : 0x%x\n", spm_read(SPM_SW_RSV_5)); + p += sprintf(p, "PCM_IM_PTR : 0x%x (%u)\n", spm_read(PCM_IM_PTR), + spm_read(PCM_IM_LEN)); + p += sprintf(p, "PCM_REG6_DATA : 0x%x\n", spm_read(PCM_REG6_DATA)); + p += sprintf(p, "PCM_REG15_DATA : 0x%x\n", spm_read(PCM_REG15_DATA)); + } else { + dump_pmic_info(); + spm_vcorefs_info("MD2SPM_DVFS_CON : 0x%x\n", spm_read(MD2SPM_DVFS_CON)); + spm_vcorefs_info("CPU_DVFS_REQ: 0x%x\n", spm_read(CPU_DVFS_REQ)); + spm_vcorefs_info("SPM_SRC_REQ: 0x%x\n", spm_read(SPM_SRC_REQ)); + spm_vcorefs_info("SPM_SRC_MASK: 0x%x\n", spm_read(SPM_SRC_MASK)); + spm_vcorefs_info("SPM_SRC2_MASK: 0x%x\n", spm_read(SPM_SRC2_MASK)); + spm_vcorefs_info("SPM_SW_RSV_4 : 0x%x\n", spm_read(SPM_SW_RSV_4)); + spm_vcorefs_info("SPM_SW_RSV_5 : 0x%x\n", spm_read(SPM_SW_RSV_5)); + spm_vcorefs_info("PCM_IM_PTR : 0x%x (%u)\n", spm_read(PCM_IM_PTR), + spm_read(PCM_IM_LEN)); + spm_vcorefs_info("PCM_REG6_DATA : 0x%x\n", spm_read(PCM_REG6_DATA)); + spm_vcorefs_info("PCM_REG0_DATA : 0x%x\n", spm_read(PCM_REG0_DATA)); + spm_vcorefs_info("PCM_REG1_DATA : 0x%x\n", spm_read(PCM_REG1_DATA)); + spm_vcorefs_info("PCM_REG2_DATA : 0x%x\n", spm_read(PCM_REG2_DATA)); + spm_vcorefs_info("PCM_REG3_DATA : 0x%x\n", spm_read(PCM_REG3_DATA)); + spm_vcorefs_info("PCM_REG4_DATA : 0x%x\n", spm_read(PCM_REG4_DATA)); + spm_vcorefs_info("PCM_REG5_DATA : 0x%x\n", spm_read(PCM_REG5_DATA)); + spm_vcorefs_info("PCM_REG7_DATA : 0x%x\n", spm_read(PCM_REG7_DATA)); + spm_vcorefs_info("PCM_REG8_DATA : 0x%x\n", spm_read(PCM_REG8_DATA)); + spm_vcorefs_info("PCM_REG9_DATA : 0x%x\n", spm_read(PCM_REG9_DATA)); + spm_vcorefs_info("PCM_REG10_DATA: 0x%x\n", spm_read(PCM_REG10_DATA)); + spm_vcorefs_info("PCM_REG11_DATA: 0x%x\n", spm_read(PCM_REG11_DATA)); + spm_vcorefs_info("PCM_REG12_DATA: 0x%x\n", spm_read(PCM_REG12_DATA)); + spm_vcorefs_info("PCM_REG13_DATA: 0x%x\n", spm_read(PCM_REG13_DATA)); + spm_vcorefs_info("PCM_REG14_DATA: 0x%x\n", spm_read(PCM_REG14_DATA)); + spm_vcorefs_info("PCM_REG15_DATA: %u\n", spm_read(PCM_REG15_DATA)); + spm_vcorefs_info("PCM_REG12_MASK_B_STA: 0x%x\n", spm_read(PCM_REG12_MASK_B_STA)); + spm_vcorefs_info("PCM_REG12_EXT_DATA: 0x%x\n", spm_read(PCM_REG12_EXT_DATA)); + spm_vcorefs_info("PCM_REG12_EXT_MASK_B_STA: 0x%x\n", spm_read(PCM_REG12_EXT_MASK_B_STA)); + } + + return p; +} + +int spm_vcorefs_get_clk_mem_pll(void) +{ + int r; +/* + -1 : dvfs in progress + 0 : MEMPLL1PLL + 1 : MEMPLL3PLL +*/ + if ((spm_read(PCM_REG6_DATA) & SPM_FLAG_DVFS_ACTIVE)) + r = -1; + else if ((spm_read(SPM_SW_RSV_5) & 0x1)) + r = 1; + else + r = 0; + + return r; +} + +/* first time kick SPM FW for vcore dvfs */ +void spm_go_to_vcore_dvfs(u32 spm_flags, u32 spm_data) +{ + unsigned long flags; + + spin_lock_irqsave(&__spm_lock, flags); + spm_write((spm_cksys_base + 0x40), (spm_read(spm_cksys_base + 0x40) | (0x1 << 13))); + + _spm_vcorefs_init_reg(); + + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_NORMAL); + + __go_to_vcore_dvfs(spm_flags, spm_data); + + spm_vcorefs_dump_dvfs_regs(NULL); + + spin_unlock_irqrestore(&__spm_lock, flags); +} + +int spm_vcorefs_set_total_bw_threshold(u32 lpm_threshold, u32 hpm_threshold) +{ + u32 value; + unsigned long flags; + + if (((hpm_threshold & (~0xFF)) != 0) || ((lpm_threshold & (~0xFF)) != 0)) { + spm_vcorefs_err("total bw threshold out-of-range !\n"); + spm_vcorefs_err("hpm:%d lpm:%d\n", hpm_threshold, lpm_threshold); + return -1; + } + + spin_lock_irqsave(&__spm_lock, flags); + + value = spm_read(SPM_SW_RSV_5) & (~(0xFF << HPM_THRES_OFFSET | 0xFF << LPM_THRES_OFFSET)); + spm_write(SPM_SW_RSV_5, + value | (hpm_threshold << HPM_THRES_OFFSET) | (lpm_threshold << + LPM_THRES_OFFSET)); + + spin_unlock_irqrestore(&__spm_lock, flags); + + return 0; +} + +int spm_vcorefs_set_perform_bw_threshold(u32 lpm_threshold, u32 hpm_threshold) +{ + u32 value; + unsigned long flags; + + if (((hpm_threshold & (~0x7F)) != 0) || ((lpm_threshold & (~0x7F)) != 0)) { + spm_vcorefs_err("perform bw threshold out-of-range !\n"); + spm_vcorefs_err("hpm:%d lpm:%d\n", hpm_threshold, lpm_threshold); + return -1; + } + spin_lock_irqsave(&__spm_lock, flags); + + value = spm_read(SPM_SW_RSV_4) & (~(0xFF << HPM_THRES_OFFSET | 0xFF << LPM_THRES_OFFSET)); + spm_write(SPM_SW_RSV_4, + value | (hpm_threshold << HPM_THRES_OFFSET) | (lpm_threshold << + LPM_THRES_OFFSET)); + + spin_unlock_irqrestore(&__spm_lock, flags); + + return 0; +} + +void spm_vcorefs_enable_total_bw(bool enable) +{ + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + unsigned long flags; + + spin_lock_irqsave(&__spm_lock, flags); + + if (enable == true) { + pwrctrl->emi_bw_dvfs_req_mask = 0; + spm_write(SPM_SRC_MASK, spm_read(SPM_SRC_MASK) & (~EMI_BW_DVFS_REQ_MASK_LSB)); + } else { + pwrctrl->emi_bw_dvfs_req_mask = 1; + spm_write(SPM_SRC_MASK, spm_read(SPM_SRC_MASK) | EMI_BW_DVFS_REQ_MASK_LSB); + } + + spin_unlock_irqrestore(&__spm_lock, flags); +} + +void spm_vcorefs_enable_perform_bw(bool enable) +{ + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + unsigned long flags; + + spin_lock_irqsave(&__spm_lock, flags); + + if (enable == true) { + pwrctrl->emi_boost_dvfs_req_mask_b = 1; + spm_write(SPM_SRC2_MASK, spm_read(SPM_SRC2_MASK) | EMI_BOOST_DVFS_REQ_MASK_B_LSB); + } else { + pwrctrl->emi_boost_dvfs_req_mask_b = 0; + spm_write(SPM_SRC2_MASK, + spm_read(SPM_SRC2_MASK) & (~EMI_BOOST_DVFS_REQ_MASK_B_LSB)); + } + + spin_unlock_irqrestore(&__spm_lock, flags); +} + + +int spm_vcorefs_set_dvfs_hpm_force(int opp, int vcore, int ddr) +{ + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + int r = 0; + unsigned long flags; + int timeout = SPM_DVFS_TIMEOUT; + + set_aee_vcore_dvfs_status(SPM_VCOREFS_ENTER); + + spin_lock_irqsave(&__spm_lock, flags); + + r = _wait_spm_dvfs_idle(timeout); + if (r < 0) { + spm_vcorefs_err("wait idle timeout(opp:%d)\n", opp); + spm_vcorefs_dump_dvfs_regs(NULL); + } + + set_aee_vcore_dvfs_status(SPM_VCOREFS_DVFS_START); + + /* MAIN: "DVFS_FORCE_ON" */ + if (opp == OPPI_PERF) { + pwrctrl->spm_dvfs_force_down = 1; + pwrctrl->spm_dvfs_req = 1; + spm_write(SPM_SRC_REQ, + spm_read(SPM_SRC_REQ) | (SPM_DVFS_FORCE_DOWN_LSB | SPM_DVFS_REQ_LSB)); + } else { + pwrctrl->spm_dvfs_req = 0; + spm_write(SPM_SRC_REQ, spm_read(SPM_SRC_REQ) & (~SPM_DVFS_REQ_LSB)); + } + + /* check spm task done status for HPM */ + if (opp == OPPI_PERF) { + r = _wait_spm_dvfs_complete(opp, timeout); + if (r < 0) { + spm_vcorefs_err("wait complete timeout(opp:%d)\n", opp); + spm_vcorefs_dump_dvfs_regs(NULL); + spm_vcorefs_aee_warn("set_hpm_force_complete_timeout(opp:%d)\n", opp); + __check_dvfs_halt_source(pwrctrl->dvfs_halt_src_chk); + } + } + + set_aee_vcore_dvfs_status(SPM_VCOREFS_DVFS_END); + + /* check vcore and ddr for HPM */ + if (opp == OPPI_PERF) + r = _check_dvfs_result(vcore, ddr); + + set_aee_vcore_dvfs_status(SPM_VCOREFS_LEAVE); + + spin_unlock_irqrestore(&__spm_lock, flags); + + return (r > 0) ? 0 : r; +} + +int spm_vcorefs_set_dvfs_hpm(int opp, int vcore, int ddr) +{ + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + int r = 0; + unsigned long flags; + int timeout = SPM_DVFS_TIMEOUT; + + bool is_total_bw_enabled = false; + + set_aee_vcore_dvfs_status(SPM_VCOREFS_ENTER); + + if (opp == OPPI_PERF) { + /* disable total bw for dvfs result check */ + is_total_bw_enabled = _get_total_bw_enable(); + spm_vcorefs_enable_total_bw(false); + } + + spin_lock_irqsave(&__spm_lock, flags); + + r = _wait_spm_dvfs_idle(timeout); + if (r < 0) { + spm_vcorefs_err("wait idle timeout(opp:%d)\n", opp); + spm_vcorefs_dump_dvfs_regs(NULL); + } + + set_aee_vcore_dvfs_status(SPM_VCOREFS_DVFS_START); + + /* MAIN: "CPU_MD_DVFS_SOP_FORCE_ON" */ + if (opp == OPPI_PERF) { + pwrctrl->cpu_md_dvfs_sop_force_on = 1; + pwrctrl->cpu_md_emi_dvfs_req_prot_dis = 1; + spm_write(SPM_SRC_REQ, spm_read(SPM_SRC_REQ) | CPU_MD_DVFS_SOP_FORCE_ON_LSB); + spm_write(SPM_SRC2_MASK, + spm_read(SPM_SRC2_MASK) | CPU_MD_EMI_DVFS_REQ_PROT_DIS_LSB); + } else { + pwrctrl->cpu_md_dvfs_sop_force_on = 0; + pwrctrl->cpu_md_emi_dvfs_req_prot_dis = 0; + spm_write(SPM_SRC2_MASK, + spm_read(SPM_SRC2_MASK) & (~CPU_MD_EMI_DVFS_REQ_PROT_DIS_LSB)); + spm_write(SPM_SRC_REQ, spm_read(SPM_SRC_REQ) & (~CPU_MD_DVFS_SOP_FORCE_ON_LSB)); + } + + /* check spm task done status for HPM */ + if (opp == OPPI_PERF) { + r = _wait_spm_dvfs_complete(opp, timeout); + if (r < 0) { + spm_vcorefs_err("wait complete timeout(opp:%d)\n", opp); + spm_vcorefs_dump_dvfs_regs(NULL); + spm_vcorefs_aee_warn("set_hpm_complete_timeout(opp:%d)\n", opp); + __check_dvfs_halt_source(pwrctrl->dvfs_halt_src_chk); + } + } + + set_aee_vcore_dvfs_status(SPM_VCOREFS_DVFS_END); + + /* check vcore and ddr for HPM */ + if (opp == OPPI_PERF) + r = _check_dvfs_result(vcore, ddr); + + set_aee_vcore_dvfs_status(SPM_VCOREFS_LEAVE); + + spin_unlock_irqrestore(&__spm_lock, flags); + + if (opp == OPPI_PERF) { + /* keep hpm at least 1ms */ + udelay(SPM_HPM_HOLD_TIME); + /* restore to orignal total bw setting */ + spm_vcorefs_enable_total_bw(is_total_bw_enabled); + } + + return (r > 0) ? 0 : r; +} + +int spm_vcorefs_set_dvfs_lpm_force(int opp, int vcore, int ddr) +{ + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + int r = 0; + unsigned long flags; + int timeout = SPM_DVFS_TIMEOUT; + + set_aee_vcore_dvfs_status(SPM_VCOREFS_ENTER); + + spin_lock_irqsave(&__spm_lock, flags); + + r = _wait_spm_dvfs_idle(timeout); + if (r < 0) { + spm_vcorefs_err("wait idle timeout(opp:%d)\n", opp); + spm_vcorefs_dump_dvfs_regs(NULL); + } + + set_aee_vcore_dvfs_status(SPM_VCOREFS_DVFS_START); + + /* spm setting for "DVFS_FORCE_DOWN" */ + if (opp == OPPI_LOW_PWR) { + pwrctrl->spm_dvfs_force_down = 0; + spm_write(SPM_SRC_REQ, spm_read(SPM_SRC_REQ) & (~SPM_DVFS_FORCE_DOWN_LSB)); + } else { + pwrctrl->spm_dvfs_force_down = 1; + spm_write(SPM_SRC_REQ, spm_read(SPM_SRC_REQ) | (SPM_DVFS_FORCE_DOWN_LSB)); + } + + /* check spm task done status for LPM */ + if (opp == OPPI_LOW_PWR) { + r = _wait_spm_dvfs_complete(opp, timeout); + if (r < 0) { + spm_vcorefs_err("wait complete timeout(opp:%d)\n", opp); + spm_vcorefs_dump_dvfs_regs(NULL); + spm_vcorefs_aee_warn("set_lpm_force_complete_timeout(opp:%d)\n", opp); + __check_dvfs_halt_source(pwrctrl->dvfs_halt_src_chk); + } + } + + set_aee_vcore_dvfs_status(SPM_VCOREFS_DVFS_END); + + /* check vcore and ddr for LPM */ + if (opp == OPPI_LOW_PWR) + r = _check_dvfs_result(vcore, ddr); + + set_aee_vcore_dvfs_status(SPM_VCOREFS_LEAVE); + + spin_unlock_irqrestore(&__spm_lock, flags); + + return r; +} + +int spm_vcorefs_set_total_bw(int opp, int vcore, int ddr) +{ + /* HPM means to disable total bw, + avoid trigger LPM event */ + + if (opp == OPPI_LOW_PWR) + spm_vcorefs_enable_total_bw(true); + else + spm_vcorefs_enable_total_bw(false); + + return 0; +} + +u32 spm_vcorefs_get_MD_status(void) +{ + return spm_read(MD2SPM_DVFS_CON); +} + +int spm_vcorefs_set_cpu_dvfs_req(u32 val, u32 mask) +{ + u32 value = (spm_read(CPU_DVFS_REQ) & ~mask) | (val & mask); + + spm_write(CPU_DVFS_REQ, value); + return 0; +} + +bool spm_vcorefs_is_dvfs_in_porgress(void) +{ + if (is_dvfs_in_progress() != 0) + return true; + else + return false; +} + +void spm_vcorefs_set_pcm_flag(u32 flag, bool set) +{ + struct pwr_ctrl *pwrctrl = __spm_vcore_dvfs.pwrctrl; + + if (set == true) + pwrctrl->pcm_flags |= flag; + else + pwrctrl->pcm_flags &= (~flag); + + spm_write(SPM_SW_FLAG, pwrctrl->pcm_flags); +} + +MODULE_DESCRIPTION("SPM-VCORE_DVFS Driver v0.2"); diff --git a/drivers/misc/mediatek/base/power/spm_v3/mt_idle_mt6755.c b/drivers/misc/mediatek/base/power/spm_v3/mt_idle_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..5f55cc7c83c1b50d4acc9ea8f1b0259ef6a85bc6 --- /dev/null +++ b/drivers/misc/mediatek/base/power/spm_v3/mt_idle_mt6755.c @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + +#include + +#include "mt_idle_internal.h" + +#define IDLE_TAG "Power/swap" +#define idle_err(fmt, args...) pr_err(IDLE_TAG fmt, ##args) + +enum subsys_id { + SYS_VDE, + SYS_MFG, + SYS_VEN, + SYS_ISP, + SYS_DIS, + SYS_AUDIO, + SYS_MFG_2D, + SYS_MFG_ASYNC, + NR_SYSS__, +}; + +/* + * Variable Declarations + */ +void __iomem *infrasys_base; +void __iomem *mmsys_base; +void __iomem *sleepsys_base; +void __iomem *topcksys_base; +void __iomem *mfgsys_base; +void __iomem *imgsys_base; +void __iomem *vdecsys_base; +void __iomem *vencsys_base; +void __iomem *audiosys_base_in_idle; + +void __iomem *apmixed_base_in_idle; + +/* Idle handler on/off */ +int idle_switch[NR_TYPES] = { + 0, /* dpidle switch */ + 0, /* soidle3 switch */ + 0, /* soidle switch */ +#ifdef CONFIG_CPU_ISOLATION + 1, /* mcidle switch */ +#else + 0, /* mcidle switch */ +#endif + 0, /* slidle switch */ + 1, /* rgidle switch */ +}; + +unsigned int dpidle_blocking_stat[NR_GRPS][32]; + +unsigned int idle_condition_mask[NR_TYPES][NR_GRPS] = { + /* dpidle_condition_mask */ + [IDLE_TYPE_DP] = { + 0x00640802, /* INFRA0: */ + 0x03AFB900, /* INFRA1: separate I2C-appm CG check */ + 0x000000C7, /* INFRA2: */ + 0x03FFFFFF, /* DISP0: */ + 0x00000312, /* IMAGE, use SPM MTCMOS off as condition: */ + 0x00000112, /* MFG, use SPM MTCMOS off as condition: */ + 0x00000000, /* AUDIO */ + 0x00000112, /* VDEC, use SPM MTCMOS off as condition: */ + 0x00000F12, /* VENC, use SPM MTCMOS off as condition: */ + }, + /* soidle3_condition_mask */ + [IDLE_TYPE_SO3] = { + 0x026C0802, /* INFRA0: separate AUXADC CG check */ + 0x03AFB900, /* INFRA1: separate I2C-appm CG check */ + 0x000000D3, /* INFRA2: */ + 0x005023FC, /* DISP0: */ + 0x00000312, /* IMAGE, use SPM MTCMOS off as condition: */ + 0x00000112, /* MFG, use SPM MTCMOS off as condition: */ + 0x00000000, /* AUDIO */ + 0x00000112, /* VDEC, use SPM MTCMOS off as condition: */ + 0x00000F12, /* VENC, use SPM MTCMOS off as condition: */ + }, + /* soidle_condition_mask */ + [IDLE_TYPE_SO] = { + 0x00640802, /* INFRA0: */ + 0x03AFB900, /* INFRA1: separate I2C-appm CG check */ + 0x000000C3, /* INFRA2: */ + 0x005023FC, /* DISP0: */ + 0x00000312, /* IMAGE, use SPM MTCMOS off as condition: */ + 0x00000112, /* MFG, use SPM MTCMOS off as condition: */ + 0x00000000, /* AUDIO */ + 0x00000112, /* VDEC, use SPM MTCMOS off as condition: */ + 0x00000F12, /* VENC, use SPM MTCMOS off as condition: */ + }, + /* mcidle_condition_mask */ + [IDLE_TYPE_MC] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* slidle_condition_mask */ + [IDLE_TYPE_SL] = { + 0x00000000, /* INFRA0: */ + 0x00000000, /* INFRA1: */ + 0x00000000, /* INFRA2: */ + 0x00000000, /* DISP0: */ + 0x00000000, /* IMAGE, use SPM MTCMOS off as condition: */ + 0x00000000, /* MFG, use SPM MTCMOS off as condition: */ + 0x00000000, /* AUDIO */ + 0x00000000, /* VDEC, use SPM MTCMOS off as condition: */ + 0x00000000, /* VENC, use SPM MTCMOS off as condition: */ + }, + /* rgidle_condition_mask */ + [IDLE_TYPE_RG] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +}; + +unsigned int soidle3_pll_condition_mask[NR_PLLS] = { + 1, /* UNIVPLL */ + 0, /* MMPLL */ + 1, /* MSDCPLL */ + 0, /* VENCPLL */ +}; + +static const char *idle_name[NR_TYPES] = { + "dpidle", + "soidle3", + "soidle", + "mcidle", + "slidle", + "rgidle", +}; + +static const char *reason_name[NR_REASONS] = { + "by_cpu", + "by_clk", + "by_tmr", + "by_oth", + "by_vtg", + "by_frm", + "by_pll", + "by_pwm", +#ifdef CONFIG_CPU_ISOLATION + "by_iso", +#endif + "by_dvfsp", +}; + +static const char *cg_group_name[NR_GRPS] = { + "INFRA0", + "INFRA1", + "INFRA2", + "DISP0", + "IMAGE", + "MFG", + "AUDIO", + "VDEC", + "VENC", +}; + +/* + * Weak functions + */ +void __attribute__((weak)) msdc_clk_status(int *status) +{ + *status = 0; +} + +/* + * Function Definitions + */ +const char *mt_get_idle_name(int id) +{ + BUG_ON(INVALID_IDLE_ID(id)); + return idle_name[id]; +} + +const char *mt_get_reason_name(int id) +{ + BUG_ON(INVALID_REASON_ID(id)); + return reason_name[id]; +} + +const char *mt_get_cg_group_name(int id) +{ + BUG_ON(INVALID_GRP_ID(id)); + return cg_group_name[id]; +} + +static int sys_is_on(enum subsys_id id) +{ + u32 pwr_sta_mask[] = { + VDE_PWR_STA_MASK, + MFG_PWR_STA_MASK, + VEN_PWR_STA_MASK, + ISP_PWR_STA_MASK, + DIS_PWR_STA_MASK, + AUDIO_PWR_STA_MASK, + MFG_2D_PWR_STA_MASK, + MFG_ASYNC_PWR_STA_MASK, + }; + + u32 mask = pwr_sta_mask[id]; + u32 sta = idle_readl(SPM_PWR_STATUS); + u32 sta_s = idle_readl(SPM_PWR_STATUS_2ND); + + if (id >= NR_SYSS__) + BUG(); + + return (sta & mask) && (sta_s & mask); +} + +static void get_all_clock_state(u32 clks[NR_GRPS]) +{ + int i; + + for (i = 0; i < NR_GRPS; i++) + clks[i] = 0; + + clks[CG_INFRA0] = ~idle_readl(INFRA_SW_CG_0_STA); /* INFRA0 */ + clks[CG_INFRA1] = ~idle_readl(INFRA_SW_CG_1_STA); /* INFRA1 */ + clks[CG_INFRA2] = ~idle_readl(INFRA_SW_CG_2_STA); /* INFRA2 */ + + if (sys_is_on(SYS_DIS)) + clks[CG_DISP0] = ~idle_readl(DISP_CG_CON0); /* DISP */ + + if (sys_is_on(SYS_ISP)) + clks[CG_IMAGE] = ~idle_readl(SPM_ISP_PWR_CON); /* IMAGE */ + + if (sys_is_on(SYS_MFG)) + clks[CG_MFG] = ~idle_readl(SPM_MFG_PWR_CON); /* MFG */ + + if (sys_is_on(SYS_VDE)) + clks[CG_VDEC] = ~idle_readl(SPM_VDE_PWR_CON); /* VDEC */ + + if (sys_is_on(SYS_VEN)) + clks[CG_VENC] = ~idle_readl(SPM_VEN_PWR_CON); /* VENC */ + + if (sys_is_on(SYS_AUDIO)) + clks[CG_AUDIO] = ~idle_readl(AUDIO_TOP_CON0); /* AUDIO */ +} + +static inline void mt_idle_check_cg_internal(unsigned int block_mask[NR_TYPES][NR_GRPS+1], int idle_type) +{ + int a, b; + + for (a = 0; a < NR_GRPS; a++) { + for (b = 0; b < 32; b++) { + if (block_mask[idle_type][a] & (1 << b)) + dpidle_blocking_stat[a][b] += 1; + } + } +} + +bool mt_idle_check_cg(unsigned int block_mask[NR_TYPES][NR_GRPS+1]) +{ + bool ret = true; + int i, j; + unsigned int sd_mask = 0, sta; + u32 clks[NR_GRPS]; + + msdc_clk_status(&sd_mask); + + get_all_clock_state(clks); + + sta = idle_readl(SPM_PWR_STATUS); + + for (i = 0; i < NR_TYPES; i++) { + if (idle_switch[i]) { + /* SD status */ + if (sd_mask) { + block_mask[i][CG_INFRA0] |= sd_mask; + block_mask[i][NR_GRPS] |= 0x1; + } + /* CG status */ + for (j = 0; j < NR_GRPS; j++) { + block_mask[i][j] = idle_condition_mask[i][j] & clks[j]; + if (block_mask[i][j]) + block_mask[i][NR_GRPS] |= 0x2; + } + if (i == IDLE_TYPE_DP) + mt_idle_check_cg_internal(block_mask, IDLE_TYPE_DP); + + /* mtcmos */ + if (i == IDLE_TYPE_DP && !dpidle_by_pass_pg) { + unsigned int flag = + MFG_PWR_STA_MASK | + ISP_PWR_STA_MASK | + VDE_PWR_STA_MASK | + VEN_PWR_STA_MASK | + DIS_PWR_STA_MASK; + if (sta & flag) + block_mask[i][NR_GRPS] |= 0x4; + } + if ((i == IDLE_TYPE_SO || i == IDLE_TYPE_SO3) && !soidle_by_pass_pg) { + unsigned int flag = + MFG_PWR_STA_MASK | + ISP_PWR_STA_MASK | + VDE_PWR_STA_MASK | + VEN_PWR_STA_MASK; + if (sta & flag) + block_mask[i][NR_GRPS] |= 0x4; + } + if (block_mask[i][NR_GRPS]) + ret = false; + } + } + + return ret; +} + +bool mt_idle_check_cg_i2c_appm(unsigned int *block_mask) +{ + u32 clk_stat = ~idle_readl(INFRA_SW_CG_1_STA); /* INFRA1 */ + + if ((clk_stat & 0x00004000) == 0x00004000) { + block_mask[CG_INFRA1] |= 0x00004000; + return false; + } + + return true; +} + +static const char *pll_name[NR_PLLS] = { + "UNIVPLL", + "MMPLL", + "MSDCPLL", + "VENCPLL", +}; + +const char *mt_get_pll_group_name(int id) +{ + return pll_name[id]; +} + +static int is_pll_on(int id) +{ + return idle_readl(APMIXEDSYS(0x230 + id * 0x10)) & 0x1; +} + +bool mt_idle_check_pll(unsigned int *condition_mask, unsigned int *block_mask) +{ + int i, j; + + memset(block_mask, 0, NR_PLLS * sizeof(unsigned int)); + + for (i = 0; i < NR_PLLS; i++) { + if (is_pll_on(i) & condition_mask[i]) { + for (j = 0; j < NR_PLLS; j++) + block_mask[j] = is_pll_on(j) & condition_mask[j]; + return false; + } + } + + return true; +} + +static int __init get_base_from_matching_node( + const struct of_device_id *ids, void __iomem **pbase, int idx, const char *cmp) +{ + struct device_node *node; + + node = of_find_matching_node(NULL, ids); + if (!node) { + idle_err("node '%s' not found!\n", cmp); + /* TODO: BUG() */ + } + + *pbase = of_iomap(node, idx); + if (!(*pbase)) { + idle_err("node '%s' cannot iomap!\n", cmp); + /* TODO: BUG() */ + } + + return 0; +} + +static int __init get_base_from_node( + const char *cmp, void __iomem **pbase, int idx) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, cmp); + + if (!node) { + idle_err("node '%s' not found!\n", cmp); + /* TODO: BUG() */ + } + + *pbase = of_iomap(node, idx); + if (!(*pbase)) { + idle_err("node '%s' cannot iomap!\n", cmp); + /* TODO: BUG() */ + } + + return 0; +} + +void __init iomap_init(void) +{ + static const struct of_device_id audiosys_ids[] = { + {.compatible = "mediatek,audio"}, + {.compatible = "mediatek,mt6755-audiosys"}, + { /* sentinel */ } + }; + + get_base_from_node("mediatek,infracfg_ao", &infrasys_base, 0); + get_base_from_node("mediatek,mmsys_config", &mmsys_base, 0); + get_base_from_node("mediatek,sleep", &sleepsys_base, 0); + get_base_from_node("mediatek,topckgen", &topcksys_base, 0); + get_base_from_node("mediatek,apmixed", &apmixed_base_in_idle, 0); + get_base_from_node("mediatek,mt6755-mfgsys", &mfgsys_base, 0); + get_base_from_node("mediatek,mt6755-imgsys", &imgsys_base, 0); + get_base_from_node("mediatek,mt6755-vdecsys", &vdecsys_base, 0); + get_base_from_node("mediatek,mt6755-vencsys", &vencsys_base, 0); + + get_base_from_matching_node(audiosys_ids, &audiosys_base_in_idle, 0, "audio"); +} + +bool mt_idle_disp_is_pwm_rosc(void) +{ + u32 sta = idle_readl(CLK_CFG_7) & 0x3; + + return (sta == 2) || (sta == 3); +} + +bool mt_idle_auxadc_is_released(void) +{ + if ((~idle_readl(INFRA_SW_CG_0_STA) & 0x400) == 0x400) { + idle_err("AUXADC CG does not be released\n"); + return false; + } + + return true; +} diff --git a/drivers/misc/mediatek/base/power/spm_v3/mt_spm_dpidle_mt6755.c b/drivers/misc/mediatek/base/power/spm_v3/mt_spm_dpidle_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..47feab84982d17a208b3918b2dc26e3ab22fbb73 --- /dev/null +++ b/drivers/misc/mediatek/base/power/spm_v3/mt_spm_dpidle_mt6755.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + +#include + +#include "mt_spm.h" +#include "mt_spm_internal.h" +#include "mt_spm_pmic_wrap.h" + +void spm_dpidle_pre_process(void) +{ +#if 0 + spm_pmic_power_mode(PMIC_PWR_DEEPIDLE, 0, 0); + + /* set PMIC WRAP table for deepidle power control */ + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_DEEPIDLE); +#endif +} + +void spm_dpidle_post_process(void) +{ +#if 0 + /* set PMIC WRAP table for normal power control */ + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_NORMAL); +#endif +} + +#if 0 +static int __init get_base_from_node( + const char *cmp, void __iomem **pbase, int idx) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, cmp); + + if (!node) { + pr_err("node '%s' not found!\n", cmp); + BUG(); + } + + *pbase = of_iomap(node, idx); + if (!(*pbase)) { + pr_err("node '%s' cannot iomap!\n", cmp); + BUG(); + } + + return 0; +} +#endif + +void spm_deepidle_chip_init(void) +{ +} + diff --git a/drivers/misc/mediatek/btcvsd/inc/mt6755/AudDrv_BTCVSD.h b/drivers/misc/mediatek/btcvsd/inc/mt6755/AudDrv_BTCVSD.h new file mode 100644 index 0000000000000000000000000000000000000000..17f85f1a92428dc9044d5375753c443b1311a10c --- /dev/null +++ b/drivers/misc/mediatek/btcvsd/inc/mt6755/AudDrv_BTCVSD.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef AUDDRV_BTCVSD_H +#define AUDDRV_BTCVSD_H + +#include +#include "AudioBTCVSDDef.h" + +#undef DEBUG_AUDDRV +#ifdef DEBUG_AUDDRV +#define PRINTK_AUDDRV(format, args...) pr_debug(format, ##args) +#else +#define PRINTK_AUDDRV(format, args...) +#endif + +/***************************************************************************** + * C O M P I L E R F L A G S + *****************************************************************************/ + + +/***************************************************************************** + * E X T E R N A L R E F E R E N C E S + *****************************************************************************/ + + +/***************************************************************************** + * D A T A T Y P E S + *****************************************************************************/ +typedef uint8_t kal_uint8; +typedef int8_t kal_int8; +typedef uint16_t kal_uint16; +typedef uint32_t kal_uint32; +typedef int32_t kal_int32; +typedef uint64_t kal_uint64; +typedef int64_t kal_int64; +typedef bool kal_bool; + +typedef enum { + BT_SCO_TXSTATE_IDLE = 0x0, + BT_SCO_TXSTATE_INIT, + BT_SCO_TXSTATE_READY, + BT_SCO_TXSTATE_RUNNING, + BT_SCO_TXSTATE_ENDING, + BT_SCO_RXSTATE_IDLE = 0x10, + BT_SCO_RXSTATE_INIT, + BT_SCO_RXSTATE_READY, + BT_SCO_RXSTATE_RUNNING, + BT_SCO_RXSTATE_ENDING, + BT_SCO_TXSTATE_DIRECT_LOOPBACK +} CVSD_STATE; + +typedef enum { + BT_SCO_DIRECT_BT2ARM, + BT_SCO_DIRECT_ARM2BT +} BT_SCO_DIRECT; + + +typedef enum { + BT_SCO_CVSD_30 = 0, + BT_SCO_CVSD_60 = 1, + BT_SCO_CVSD_90 = 2, + BT_SCO_CVSD_120 = 3, + BT_SCO_CVSD_10 = 4, + BT_SCO_CVSD_20 = 5, + BT_SCO_CVSD_MAX = 6 +} BT_SCO_PACKET_LEN; + + +typedef struct { + dma_addr_t pucTXPhysBufAddr; + dma_addr_t pucRXPhysBufAddr; + kal_uint8 *pucTXVirtBufAddr; + kal_uint8 *pucRXVirtBufAddr; + kal_int32 u4TXBufferSize; + kal_int32 u4RXBufferSize; +} CVSD_MEMBLOCK_T; + + +typedef struct { + kal_uint8 PacketBuf[SCO_RX_PACKER_BUF_NUM][SCO_RX_PLC_SIZE + BTSCO_CVSD_PACKET_VALID_SIZE]; + kal_bool PacketValid[SCO_RX_PACKER_BUF_NUM]; + int iPacket_w; + int iPacket_r; + kal_uint8 TempPacketBuf[BT_SCO_PACKET_180]; + kal_bool fOverflow; + kal_uint32 u4BufferSize; /*RX packetbuf size*/ +} BT_SCO_RX_T; + + +typedef struct { + kal_uint8 PacketBuf[SCO_TX_PACKER_BUF_NUM][SCO_TX_ENCODE_SIZE]; + kal_int32 iPacket_w; + kal_int32 iPacket_r; + kal_uint8 TempPacketBuf[BT_SCO_PACKET_180]; + kal_bool fUnderflow; + kal_uint32 u4BufferSize; /*TX packetbuf size*/ +} BT_SCO_TX_T; + +CVSD_MEMBLOCK_T BT_CVSD_Mem; + +/* here is temp address for ioremap BT hardware register */ +void *BTSYS_PKV_BASE_ADDRESS = 0; +void *BTSYS_SRAM_BANK2_BASE_ADDRESS = 0; +void *AUDIO_INFRA_BASE_VIRTUAL = 0; + +#ifdef CONFIG_OF +unsigned long btsys_pkv_physical_base = 0; +unsigned long btsys_sram_bank2_physical_base = 0; +unsigned long infra_base = 0; +/* INFRA_MISC address=AUDIO_INFRA_BASE_PHYSICAL + INFRA_MISC_OFFSET */ +unsigned long infra_misc_offset = 0; +/* bit 11 of INFRA_MISC */ +unsigned long conn_bt_cvsd_mask = 0; +/* BTSYS_PKV_BASE_ADDRESS+cvsd_mcu_read_offset */ +unsigned long cvsd_mcu_read_offset = 0; +/* BTSYS_PKV_BASE_ADDRESS+cvsd_mcu_write_offset */ +unsigned long cvsd_mcu_write_offset = 0; +/* BTSYS_PKV_BASE_ADDRESS+cvsd_packet_indicator */ +unsigned long cvsd_packet_indicator = 0; +#else +#define AUDIO_BTSYS_PKV_PHYSICAL_BASE (0x18000000) +#define AUDIO_BTSYS_SRAM_BANK2_PHYSICAL_BASE (0x18080000) +#define AUDIO_INFRA_BASE_PHYSICAL (0x10001000) +/* INFRA_MISC address=AUDIO_INFRA_BASE_PHYSICAL + INFRA_MISC_OFFSET */ +#define INFRA_MISC_OFFSET (0x0F00) +/* bit 11 of INFRA_MISC */ +#define conn_bt_cvsd_mask (0x00000800) +#define CVSD_MCU_READ_OFFSET (0xFD0) +#define CVSD_MCU_WRITE_OFFSET (0xFD4) +#define CVSD_PACKET_INDICATOR (0xFD8) +#endif +#define AP_BT_CVSD_IRQ_LINE (268) +u32 btcvsd_irq_number = AP_BT_CVSD_IRQ_LINE; + +#endif diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/GT24c32a.c b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/GT24c32a.c new file mode 100644 index 0000000000000000000000000000000000000000..41d73f047775b708e04e0fc596d8acd87bddf991 --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/GT24c32a.c @@ -0,0 +1,902 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_hw.h" +#include "eeprom.h" +#include "eeprom_define.h" +#include "GT24c32a.h" +#include /* for SMP */ +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_hw.h" +#include "cam_cal.h" +#include "cam_cal_define.h" + +#include "GT24c32a.h" +#include /* for SMP */ +#endif +/* #define EEPROMGETDLT_DEBUG */ +#define EEPROM_DEBUG +#ifdef EEPROM_DEBUG +#define EEPROMDB pr_debug +#else +#define EEPROMDB(x, ...) +#endif + + +static DEFINE_SPINLOCK(g_EEPROMLock); /* for SMP */ +#define EEPROM_I2C_BUSNUM 1 +static struct i2c_board_info kd_eeprom_dev __initdata = { I2C_BOARD_INFO("CAM_CAL_DRV", 0xAA >> 1)}; + +/******************************************************************************* +* +********************************************************************************/ +#define EEPROM_ICS_REVISION 1 /* seanlin111208 */ +/******************************************************************************* +* +********************************************************************************/ +#define EEPROM_DRVNAME "CAM_CAL_DRV" +#define EEPROM_I2C_GROUP_ID 0 + +/******************************************************************************* +* +********************************************************************************/ +/* #define FM50AF_EEPROM_I2C_ID 0x28 */ +#define FM50AF_EEPROM_I2C_ID 0xA1 + +/* EEPROM READ/WRITE ID */ +#define S24CS64A_DEVICE_ID 0xAA +#define EEPROM_DEV_MAJOR_NUMBER 226 + +/******************************************************************************* +/* define LSC data for M24C08F EEPROM on L10 project */ +/********************************************************************************/ +#define SampleNum 221 +#define Read_NUMofEEPROM 2 +#define Boundary_Address 256 +#define EEPROM_Address_Offset 0xC + + +/******************************************************************************* +* +********************************************************************************/ +static struct i2c_client *g_pstI2Cclient; + +/* 81 is used for V4L driver */ +static dev_t g_EEPROMdevno = MKDEV(EEPROM_DEV_MAJOR_NUMBER, 0); +static struct cdev *g_pEEPROM_CharDrv; +/* static spinlock_t g_EEPROMLock; */ +/* spin_lock(&g_EEPROMLock); */ +/* spin_unlock(&g_EEPROMLock); */ + +static struct class *EEPROM_class; +static atomic_t g_EEPROMatomic; +/* static DEFINE_SPINLOCK(kdeeprom_drv_lock); */ +/* spin_lock(&kdeeprom_drv_lock); */ +/* spin_unlock(&kdeeprom_drv_lock); */ + +/******************************************************************************* +* +********************************************************************************/ +/* +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, +u16 a_sizeRecvData, u16 i2cId); +extern int iBurstReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, +u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern int iReadReg(u16 a_u2Addr , u8 *a_puBuff , u16 i2cId); +*/ +/******************************************************************************* +* +********************************************************************************/ +/* maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt6516.c which is 8 bytes */ +int iWriteEEPROM(u16 a_u2Addr , u32 a_u4Bytes, u8 *puDataInBytes) +{ + u32 u4Index; + int i4RetValue; + char puSendCmd[8] = { + (char)(a_u2Addr >> 8) , + (char)(a_u2Addr & 0xFF) , + 0, 0, 0, 0, 0, 0 + }; + if (a_u4Bytes + 2 > 8) { + EEPROMDB("[S24EEPROM] exceed I2c-mt65xx.c 8 bytes limitation (include address 2 Byte)\n"); + return -1; + } + + for (u4Index = 0; u4Index < a_u4Bytes; u4Index += 1) + puSendCmd[(u4Index + 2)] = puDataInBytes[u4Index]; + + i4RetValue = i2c_master_send(g_pstI2Cclient, puSendCmd, (a_u4Bytes + 2)); + if (i4RetValue != (a_u4Bytes + 2)) { + EEPROMDB("[S24EEPROM] I2C write failed!!\n"); + return -1; + } + mdelay(10); /* for tWR singnal --> write data form buffer to memory. */ + + /* EEPROMDB("[EEPROM] iWriteEEPROM done!!\n"); */ + return 0; +} + + +/* maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt65xx.c which is 8 bytes */ +int iReadEEPROM(u16 a_u2Addr, u32 ui4_length, u8 *a_puBuff) +{ + int i4RetValue = 0; + char puReadCmd[2] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF)}; + + /* EEPROMDB("[EEPROM] iReadEEPROM!!\n"); */ + + if (ui4_length > 8) { + EEPROMDB("[S24EEPROM] exceed I2c-mt65xx.c 8 bytes limitation\n"); + return -1; + } + spin_lock(&g_EEPROMLock); /* for SMP */ + g_pstI2Cclient->addr = g_pstI2Cclient->addr & (I2C_MASK_FLAG | I2C_WR_FLAG); + spin_unlock(&g_EEPROMLock); /* for SMP */ + + /* EEPROMDB("[EEPROM] i2c_master_send\n"); */ + i4RetValue = i2c_master_send(g_pstI2Cclient, puReadCmd, 2); + if (i4RetValue != 2) { + EEPROMDB("[EEPROM] I2C send read address failed!!\n"); + return -1; + } + + /* EEPROMDB("[EEPROM] i2c_master_recv\n"); */ + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_puBuff, ui4_length); + if (i4RetValue != ui4_length) { + EEPROMDB("[EEPROM] I2C read data failed!!\n"); + return -1; + } + spin_lock(&g_EEPROMLock); /* for SMP */ + g_pstI2Cclient->addr = g_pstI2Cclient->addr & I2C_MASK_FLAG; + spin_unlock(&g_EEPROMLock); /* for SMP */ + + /* EEPROMDB("[EEPROM] iReadEEPROM done!!\n"); */ + return 0; +} + + +int iWriteData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char *pinputdata) +{ + int i4RetValue = 0; + int i4ResidueDataLength; + u32 u4IncOffset = 0; + u32 u4CurrentOffset; + u8 *pBuff; + + EEPROMDB("[S24EEPROM] iWriteData\n"); + +#if 0 + if (ui4_offset + ui4_length >= 0x2000) { + EEPROMDB("[S24EEPROM] Write Error!! S-24CS64A not supprt address >= 0x2000!!\n"); + return -1; + } + + i4ResidueDataLength = (int)ui4_length; + u4CurrentOffset = ui4_offset; + pBuff = pinputdata; + + EEPROMDB("[S24EEPROM] iWriteData u4CurrentOffset is %d\n", u4CurrentOffset); + + do { + if (i4ResidueDataLength >= 6) { + /* i4RetValue = iWriteEEPROM((u16)u4CurrentOffset, 6, pBuff); */ + if (i4RetValue != 0) { + EEPROMDB("[EEPROM] I2C iWriteData failed!!\n"); + return -1; + } + u4IncOffset += 6; + i4ResidueDataLength -= 6; + u4CurrentOffset = ui4_offset + u4IncOffset; + pBuff = pinputdata + u4IncOffset; + } else { + /* i4RetValue = iWriteEEPROM((u16)u4CurrentOffset, i4ResidueDataLength, pBuff); */ + if (i4RetValue != 0) { + EEPROMDB("[EEPROM] I2C iWriteData failed!!\n"); + return -1; + } + u4IncOffset += 6; + i4ResidueDataLength -= 6; + u4CurrentOffset = ui4_offset + u4IncOffset; + pBuff = pinputdata + u4IncOffset; + /* break; */ + } + } while (i4ResidueDataLength > 0); +#endif + EEPROMDB("[S24EEPROM] iWriteData done\n"); + + return 0; +} + + + +int iReadDataFromGT24c32a(unsigned int ui4_offset, unsigned int ui4_length, +unsigned char *pinputdata) +{ + + char puSendCmd[2];/* = {(char)(ui4_offset & 0xFF) }; */ + unsigned short SampleOffset = (unsigned short)((ui4_offset) & (0x0000FFFF)); + unsigned short EEPROM_Address[2] = {0xA0, 0xA0}; + /* unsigned char address_offset = ((SampleNum *SampleOffset) + + EEPROM_Address_Offset+ ui4_length) / Boundary_Address; */ + short loop[2], loopCount; + unsigned short SampleCount; + u8 *pBuff; + u32 u4IncOffset = 0; + int i4RetValue = 0; + + + pBuff = pinputdata; + + EEPROMDB("[EEPROM] ui4_offset=%x ui4_offset(80)=%x ui4_offset(8)=%x\n", ui4_offset, + (unsigned short)((ui4_offset >> 8) & 0x0000FFFF), SampleOffset); + + /* ui4_offset = (char)( (ui4_offset>>8) & 0xFF); */ + +#if 0 + EEPROM_Address[0] = ((0 < address_offset) ? (EEPROM_Address[0] | (address_offset - 1)) + : EEPROM_Address[0]); + EEPROM_Address[1] = ((EEPROM_Address[0] & 0xF0) | (address_offset)); + + EEPROM_Address[0] = EEPROM_Address[0] << 1; + EEPROM_Address[1] = EEPROM_Address[1] << 1; +#endif + + EEPROMDB("[EEPROM] EEPROM_Address[0]=%x EEPROM_Address[1]=%x\n", (EEPROM_Address[0] >> 1), + (EEPROM_Address[1] >> 1)); + + /* loop[0] = (Boundary_Address * address_offset) - ((SampleNum *SampleOffset) + + EEPROM_Address_Offset); */ + loop[0] = ((ui4_length >> 4) << 4); + + loop[1] = ui4_length - loop[0]; + + + EEPROMDB("[EEPROM] loop[0]=%d loop[1]=%d\n", (loop[0]) , (loop[1])); + + puSendCmd[0] = (char)(((SampleOffset + u4IncOffset) >> 8) & 0xFF); + puSendCmd[1] = (char)((SampleOffset + u4IncOffset) & 0xFF); + + for (loopCount = 0; loopCount < Read_NUMofEEPROM; loopCount++) { + do { + if (16 <= loop[loopCount]) { + + EEPROMDB("[EEPROM]1 loopCount=%d loop[loopCount]=%d puSendCmd[0]=%x puSendCmd[1]=%x, + EEPROM(%x)\n", loopCount , loop[loopCount], puSendCmd[0], puSendCmd[1], + EEPROM_Address[loopCount]); + /* iReadRegI2C(puSendCmd , 2, (u8*)pBuff,16,EEPROM_Address[loopCount]); */ + i4RetValue = iBurstReadRegI2C(puSendCmd , 2, (u8 *)pBuff, 16, + EEPROM_Address[loopCount]); + if (i4RetValue != 0) { + EEPROMDB("[EEPROM] I2C iReadData failed!!\n"); + return -1; + } + u4IncOffset += 16; + loop[loopCount] -= 16; + /* puSendCmd[0] = (char)( (ui4_offset+u4IncOffset) & 0xFF) ; */ + puSendCmd[0] = (char)(((SampleOffset + u4IncOffset) >> 8) & 0xFF); + puSendCmd[1] = (char)((SampleOffset + u4IncOffset) & 0xFF); + pBuff = pinputdata + u4IncOffset; + } else if (0 < loop[loopCount]) { + EEPROMDB("[EEPROM]2 loopCount=%d loop[loopCount]=%d puSendCmd[0]=%x puSendCmd[1]=%x\n", + loopCount , loop[loopCount], puSendCmd[0], puSendCmd[1]); + /* iReadRegI2C(puSendCmd , 2, (u8*)pBuff,loop[loopCount],EEPROM_Address[loopCount]); */ + i4RetValue = iBurstReadRegI2C(puSendCmd , 2, (u8 *)pBuff, 16, + EEPROM_Address[loopCount]); + if (i4RetValue != 0) { + EEPROMDB("[EEPROM] I2C iReadData failed!!\n"); + return -1; + } + u4IncOffset += loop[loopCount]; + loop[loopCount] -= loop[loopCount]; + /* puSendCmd[0] = (char)( (ui4_offset+u4IncOffset) & 0xFF) ; */ + puSendCmd[0] = (char)(((SampleOffset + u4IncOffset) >> 8) & 0xFF); + puSendCmd[1] = (char)((SampleOffset + u4IncOffset) & 0xFF); + pBuff = pinputdata + u4IncOffset; + } + } while (loop[loopCount] > 0); + } + + return 0; +} + +int iReadData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char *pinputdata) +{ + int i4RetValue = 0; + int i4ResidueDataLength; + u32 u4IncOffset = 0; + u32 u4CurrentOffset; + u8 *pBuff; + /* EEPROMDB("[S24EEPORM] iReadData\n" ); */ + + if (ui4_offset + ui4_length >= 0x2000) { + EEPROMDB("[S24EEPROM] Read Error!! S-24CS64A not supprt address >= 0x2000!!\n"); + return -1; + } + + i4ResidueDataLength = (int)ui4_length; + u4CurrentOffset = ui4_offset; + pBuff = pinputdata; + do { + if (i4ResidueDataLength >= 8) { + i4RetValue = iReadEEPROM((u16)u4CurrentOffset, 8, pBuff); + if (i4RetValue != 0) { + EEPROMDB("[EEPROM] I2C iReadData failed!!\n"); + return -1; + } + u4IncOffset += 8; + i4ResidueDataLength -= 8; + u4CurrentOffset = ui4_offset + u4IncOffset; + pBuff = pinputdata + u4IncOffset; + } else { + i4RetValue = iReadEEPROM((u16)u4CurrentOffset, i4ResidueDataLength, pBuff); + if (i4RetValue != 0) { + EEPROMDB("[EEPROM] I2C iReadData failed!!\n"); + return -1; + } + u4IncOffset += 8; + i4ResidueDataLength -= 8; + u4CurrentOffset = ui4_offset + u4IncOffset; + pBuff = pinputdata + u4IncOffset; + /* break; */ + } + } while (i4ResidueDataLength > 0); + /* EEPROMDB("[S24EEPORM] iReadData finial address is %d length is %d buffer address is + 0x%x\n",u4CurrentOffset, i4ResidueDataLength, pBuff); */ + /* EEPROMDB("[S24EEPORM] iReadData done\n" ); */ + return 0; +} + + +/******************************************************************************* +* +********************************************************************************/ +#define NEW_UNLOCK_IOCTL +#ifndef NEW_UNLOCK_IOCTL +static int EEPROM_Ioctl(struct inode *a_pstInode, + struct file *a_pstFile, + unsigned int a_u4Command, + unsigned long a_u4Param) +#else +static long EEPROM_Ioctl( + struct file *file, + unsigned int a_u4Command, + unsigned long a_u4Param +) +#endif +{ + int i4RetValue = 0; + u8 *pBuff = NULL; + u8 *pWorkingBuff = NULL; + stCAM_CAL_INFO_STRUCT *ptempbuf; + ssize_t writeSize; + u8 readTryagain = 0; + +#ifdef EEPROMGETDLT_DEBUG + struct timeval ktv1, ktv2; + unsigned long TimeIntervalUS; +#endif +/* + if (_IOC_NONE == _IOC_DIR(a_u4Command)) { + } else { +*/ + if (_IOC_NONE != _IOC_DIR(a_u4Command)) { + pBuff = kmalloc(sizeof(stCAM_CAL_INFO_STRUCT), GFP_KERNEL); + + if (NULL == pBuff) { + EEPROMDB("[S24EEPROM] ioctl allocate mem failed\n"); + return -ENOMEM; + } + + if (_IOC_WRITE & _IOC_DIR(a_u4Command)) { + if (copy_from_user((u8 *) pBuff , (u8 *) a_u4Param, sizeof(stCAM_CAL_INFO_STRUCT))) { + /* get input structure address */ + kfree(pBuff); + EEPROMDB("[S24EEPROM] ioctl copy from user failed\n"); + return -EFAULT; + } + } + } + + ptempbuf = (stCAM_CAL_INFO_STRUCT *)pBuff; + pWorkingBuff = kmalloc(ptempbuf->u4Length, GFP_KERNEL); + if (NULL == pWorkingBuff) { + kfree(pBuff); + EEPROMDB("[S24EEPROM] ioctl allocate mem failed\n"); + return -ENOMEM; + } + EEPROMDB("[S24EEPROM] init Working buffer address 0x%8x command is 0x%8x\n", + (u32)pWorkingBuff, (u32)a_u4Command); + + + if (copy_from_user((u8 *)pWorkingBuff , (u8 *)ptempbuf->pu1Params, ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pWorkingBuff); + EEPROMDB("[S24EEPROM] ioctl copy from user failed\n"); + return -EFAULT; + } + + switch (a_u4Command) { + case CAM_CALIOC_S_WRITE: + EEPROMDB("[S24EEPROM] Write CMD\n"); +#ifdef EEPROMGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + i4RetValue = iWriteData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff); +#ifdef EEPROMGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + EEPROMDB("Write data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + break; + case CAM_CALIOC_G_READ: + EEPROMDB("[S24EEPROM] Read CMD\n"); +#ifdef EEPROMGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + EEPROMDB("[EEPROM] offset %x\n", ptempbuf->u4Offset); + EEPROMDB("[EEPROM] length %x\n", ptempbuf->u4Length); + EEPROMDB("[EEPROM] Before read Working buffer address 0x%8x\n", (u32)pWorkingBuff); + +#if 0 + /* iReadReg(0x0770 , u8 * a_puBuff , u16 i2cId); */ + /* iWriteRegI2C(0xFF ,1,0xA6); */ + if (0) { + unsigned short addr; + unsigned short get_byte = 0, loop = 0; +#if 0 + for (loop = 0xc; loop <= 0x06fd; loop++) { + addr = 0x72; + iReadReg(loop , (u8 *)&get_byte, addr); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", loop, loop, get_byte); + get_byte = 0; + } +#endif + for (addr = 0; addr < 256; addr++) { + for (loop = 0x07FC; loop <= 0x07FF; loop++) { + /* addr = 0x72; */ + get_byte = 0; + iReadReg(loop , (u8 *)&get_byte, addr); + + EEPROMDB("[EEPROM]enter EEPROM_test function addr(%x) (%x)%x\n", + addr, loop, get_byte); + + } + } + } +#endif + +#if 0 + if (1) { + unsigned short addr; + unsigned short get_byte = 0, loop = 0; + + iReadReg(0x0000 , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x0000, get_byte); + + get_byte = 0; + + iReadReg(0x0001 , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x0001, get_byte); + + + get_byte = 0; + + iReadReg(0x0380 , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x0380, get_byte); + + get_byte = 0; + + iReadReg(0x0381 , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x0381, get_byte); + + + get_byte = 0; + + iReadReg(0x0703 , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x0703, get_byte); + + get_byte = 0; + + iReadReg(0x0704 , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x0704, get_byte); + + get_byte = 0; + + iReadReg(0x0705 , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x0705, get_byte); + + get_byte = 0; + + iReadReg(0x0706 , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x0706, get_byte); + +#if 0 + get_byte = 0; + + iReadReg(0x07fc , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x07fc, get_byte); + + get_byte = 0; + + iReadReg(0x07fd , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x05, get_byte); + + get_byte = 0; + + iReadReg(0x07fe , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x05, get_byte); + + get_byte = 0; + + iReadReg(0x07ff , (u8 *)&get_byte, 0xA6); + + EEPROMDB("[EEPROM]enter EEPROM_test function%d (%x)%x\n", ++loop, 0x05, get_byte); + + get_byte = 0; +#endif + + } +#endif + +#if 0 + if (ptempbuf->u4Offset == 0x800) { + *(u16 *)pWorkingBuff = 0x3; + + } + + else if (ptempbuf->u4Offset == 0x0024C32a) { + *(u32 *)pWorkingBuff = 0x0124C32a; + } else if (ptempbuf->u4Offset == 0xFFFFFFFF) { + char puSendCmd[1] = {0, }; + + puSendCmd[0] = 0x7E; + /* iReadRegI2C(puSendCmd , 1, pWorkingBuff,2, (0x53<<1) ); */ + EEPROMDB("[S24EEPORM] Shading CheckSum MSB=> %x %x\n", pWorkingBuff[0], pWorkingBuff[1]); + } else { + /* i4RetValue = iReadData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff); */ + + i4RetValue = iReadDataFromM24C08F((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff); + + } + EEPROMDB("[S24EEPROM] After read Working buffer data 0x%4x\n", *pWorkingBuff); +#else + if (ptempbuf->u4Offset == 0x0024C32a) { + *(u32 *)pWorkingBuff = 0x0124C32a; + } else { + readTryagain = 3; + while (0 < readTryagain) { + i4RetValue = iReadDataFromGT24c32a((u16)ptempbuf->u4Offset, ptempbuf->u4Length, + pWorkingBuff); + EEPROMDB("[S24EEPROM] error (%d) Read retry (%d)\n", i4RetValue, readTryagain); + if (i4RetValue != 0) + readTryagain--; + else + readTryagain = 0; + } + + + } + EEPROMDB("[S24EEPROM] After read Working buffer data 0x%4x\n", *pWorkingBuff); + +#endif + +#ifdef EEPROMGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + EEPROMDB("Read data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + + break; + default: + EEPROMDB("[S24EEPROM] No CMD\n"); + i4RetValue = -EPERM; + break; + } + + if (_IOC_READ & _IOC_DIR(a_u4Command)) { + /* copy data to user space buffer, keep other input paremeter unchange. */ + EEPROMDB("[S24EEPROM] to user length %d\n", ptempbuf->u4Length); + EEPROMDB("[S24EEPROM] to user Working buffer address 0x%8x\n", (u32)pWorkingBuff); + if (copy_to_user((u8 __user *) ptempbuf->pu1Params , (u8 *)pWorkingBuff , ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pWorkingBuff); + EEPROMDB("[S24EEPROM] ioctl copy to user failed\n"); + return -EFAULT; + } + } + + kfree(pBuff); + kfree(pWorkingBuff); + return i4RetValue; +} + + +static u32 g_u4Opened; +/* #define */ +/* Main jobs: */ +/* 1.check for device-specified errors, device not ready. */ +/* 2.Initialize the device if it is opened for the first time. */ +static int EEPROM_Open(struct inode *a_pstInode, struct file *a_pstFile) +{ + EEPROMDB("[S24EEPROM] EEPROM_Open\n"); + spin_lock(&g_EEPROMLock); + if (g_u4Opened) { + spin_unlock(&g_EEPROMLock); + return -EBUSY; + } /*else {*//*LukeHu--150720=For check fo*/ + if (!g_u4Opened) {/*LukeHu++150720=For check fo*/ + g_u4Opened = 1; + atomic_set(&g_EEPROMatomic, 0); + } + spin_unlock(&g_EEPROMLock); + + return 0; +} + +/* Main jobs: */ +/* 1.Deallocate anything that "open" allocated in private_data. */ +/* 2.Shut down the device on last close. */ +/* 3.Only called once on last time. */ +/* Q1 : Try release multiple times. */ +static int EEPROM_Release(struct inode *a_pstInode, struct file *a_pstFile) +{ + spin_lock(&g_EEPROMLock); + + g_u4Opened = 0; + + atomic_set(&g_EEPROMatomic, 0); + + spin_unlock(&g_EEPROMLock); + + return 0; +} + +static const struct file_operations g_stEEPROM_fops = { + .owner = THIS_MODULE, + .open = EEPROM_Open, + .release = EEPROM_Release, + /* .ioctl = EEPROM_Ioctl */ + .unlocked_ioctl = EEPROM_Ioctl +}; + +#define EEPROM_DYNAMIC_ALLOCATE_DEVNO 1 +static inline int RegisterEEPROMCharDrv(void) +{ + struct device *EEPROM_device = NULL; + +#if EEPROM_DYNAMIC_ALLOCATE_DEVNO + if (alloc_chrdev_region(&g_EEPROMdevno, 0, 1, EEPROM_DRVNAME)) { + EEPROMDB("[S24EEPROM] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if (register_chrdev_region(g_EEPROMdevno , 1 , EEPROM_DRVNAME)) { + EEPROMDB("[S24EEPROM] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + /* Allocate driver */ + g_pEEPROM_CharDrv = cdev_alloc(); + + if (NULL == g_pEEPROM_CharDrv) { + unregister_chrdev_region(g_EEPROMdevno, 1); + + EEPROMDB("[S24EEPROM] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + /* Attatch file operation. */ + cdev_init(g_pEEPROM_CharDrv, &g_stEEPROM_fops); + + g_pEEPROM_CharDrv->owner = THIS_MODULE; + + /* Add to system */ + if (cdev_add(g_pEEPROM_CharDrv, g_EEPROMdevno, 1)) { + EEPROMDB("[S24EEPROM] Attatch file operation failed\n"); + + unregister_chrdev_region(g_EEPROMdevno, 1); + + return -EAGAIN; + } + + EEPROM_class = class_create(THIS_MODULE, "EEPROMdrv"); + if (IS_ERR(EEPROM_class)) { + int ret = PTR_ERR(EEPROM_class); + + EEPROMDB("Unable to create class, err = %d\n", ret); + return ret; + } + EEPROM_device = device_create(EEPROM_class, NULL, g_EEPROMdevno, NULL, EEPROM_DRVNAME); + + return 0; +} + +static inline void UnregisterEEPROMCharDrv(void) +{ + /* Release char driver */ + cdev_del(g_pEEPROM_CharDrv); + + unregister_chrdev_region(g_EEPROMdevno, 1); + + device_destroy(EEPROM_class, g_EEPROMdevno); + class_destroy(EEPROM_class); +} + + +/* //////////////////////////////////////////////////////////////////// */ +#ifndef EEPROM_ICS_REVISION +static int EEPROM_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); +#elif 0 +static int EEPROM_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); +#else +#endif +static int EEPROM_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int EEPROM_i2c_remove(struct i2c_client *); + +static const struct i2c_device_id EEPROM_i2c_id[] = {{EEPROM_DRVNAME, 0}, {} }; +#if 0 /* test110314 Please use the same I2C Group ID as Sensor */ +static unsigned short force[] = {EEPROM_I2C_GROUP_ID, S24CS64A_DEVICE_ID, I2C_CLIENT_END, + I2C_CLIENT_END}; +#else +/* static unsigned short force[] = {IMG_SENSOR_I2C_GROUP_ID, S24CS64A_DEVICE_ID, I2C_CLIENT_END, I2C_CLIENT_END}; */ +#endif +/* static const unsigned short * const forces[] = { force, NULL }; */ +/* static struct i2c_client_address_data addr_data = { .forces = forces,}; */ + + +static struct i2c_driver EEPROM_i2c_driver = { + .probe = EEPROM_i2c_probe, + .remove = EEPROM_i2c_remove, + /* .detect = EEPROM_i2c_detect, */ + .driver.name = EEPROM_DRVNAME, + .id_table = EEPROM_i2c_id, +}; + +#ifndef EEPROM_ICS_REVISION +static int EEPROM_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) +{ + strcpy(info->type, EEPROM_DRVNAME); + return 0; +} +#endif +static int EEPROM_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i4RetValue = 0; + + EEPROMDB("[S24EEPROM] Attach I2C\n"); + /* spin_lock_init(&g_EEPROMLock); */ + + /* get sensor i2c client */ + spin_lock(&g_EEPROMLock); /* for SMP */ + g_pstI2Cclient = client; + g_pstI2Cclient->addr = S24CS64A_DEVICE_ID >> 1; + spin_unlock(&g_EEPROMLock); /* for SMP */ + + EEPROMDB("[EEPROM] g_pstI2Cclient->addr = 0x%8x\n", g_pstI2Cclient->addr); + /* Register char driver */ + i4RetValue = RegisterEEPROMCharDrv(); + + if (i4RetValue) { + EEPROMDB("[S24EEPROM] register char device failed!\n"); + return i4RetValue; + } + + + EEPROMDB("[S24EEPROM] Attached!!\n"); + return 0; +} + +static int EEPROM_i2c_remove(struct i2c_client *client) +{ + return 0; +} + +static int EEPROM_probe(struct platform_device *pdev) +{ + return i2c_add_driver(&EEPROM_i2c_driver); +} + +static int EEPROM_remove(struct platform_device *pdev) +{ + i2c_del_driver(&EEPROM_i2c_driver); + return 0; +} + +/* platform structure */ +static struct platform_driver g_stEEPROM_Driver = { + .probe = EEPROM_probe, + .remove = EEPROM_remove, + .driver = { + .name = EEPROM_DRVNAME, + .owner = THIS_MODULE, + } +}; + + +static struct platform_device g_stEEPROM_Device = { + .name = EEPROM_DRVNAME, + .id = 0, + .dev = { + } +}; + +static int __init EEPROM_i2C_init(void) +{ + i2c_register_board_info(EEPROM_I2C_BUSNUM, &kd_eeprom_dev, 1); + if (platform_driver_register(&g_stEEPROM_Driver)) { + EEPROMDB("failed to register S24EEPROM driver\n"); + return -ENODEV; + } + + if (platform_device_register(&g_stEEPROM_Device)) { + EEPROMDB("failed to register S24EEPROM driver, 2nd time\n"); + return -ENODEV; + } + + return 0; +} + +static void __exit EEPROM_i2C_exit(void) +{ + platform_driver_unregister(&g_stEEPROM_Driver); +} + +module_init(EEPROM_i2C_init); +module_exit(EEPROM_i2C_exit); + +MODULE_DESCRIPTION("EEPROM driver"); +MODULE_AUTHOR("Sean Lin "); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/GT24c32a.h b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/GT24c32a.h new file mode 100644 index 0000000000000000000000000000000000000000..e15ff31a4e2d8643d6e9bf0cb8c94aeab22b5d98 --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/GT24c32a.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/***************************************************************************** + * + * Filename: + * --------- + * S-24CS64A.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Header file of EEPROM driver + * + * + * Author: + * ------- + * Ronnie Lai (MTK01420) + * + *============================================================================*/ +#ifndef __GT24C32A_H +#define __GT24C32A_H + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iBurstReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern int iReadReg(u16 a_u2Addr , u8 *a_puBuff , u16 i2cId); + +#endif /* __EEPROM_H */ + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/Makefile b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..40ac19f10714b0b512e6ceea0035e3ee07692614 --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/GT24c32a_eeprom/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MTK_CAM_CAL_GT24C32A_SUPPORT) += GT24c32a.o diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/Makefile b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..591d3c21e071f29b5b1a470cf2fec356c41eae7b --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/Makefile @@ -0,0 +1,5 @@ +custom_cam_cal := $(addsuffix /, $(shell echo $(CONFIG_CUSTOM_KERNEL_CAM_CAL_DRV))) +obj-y += $(custom_cam_cal) + + + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/Makefile b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..fafeed23a373b3f7d4829834ee5f6726f4387c26 --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/Makefile @@ -0,0 +1 @@ +obj-y += cat24c16.o diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/cat24c16.c b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/cat24c16.c new file mode 100644 index 0000000000000000000000000000000000000000..d0dfcc188b0d5b7de3edb64510b39fad04e5be5c --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/cat24c16.c @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_hw.h" +#include "cam_cal.h" +#include "cam_cal_define.h" +#include "cat24c16.h" +/* #include // for SMP */ +#include +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + + +/* #define CAM_CALGETDLT_DEBUG */ +#define CAM_CAL_DEBUG +#ifdef CAM_CAL_DEBUG +#define PFX "cat2416c" + +#define CAM_CALINF(fmt, arg...) pr_debug("[%s] " fmt, __func__, ##arg) +#define CAM_CALDB(fmt, arg...) pr_debug("[%s] " fmt, __func__, ##arg) +#define CAM_CALERR(fmt, arg...) pr_err("[%s] " fmt, __func__, ##arg) +#else +#define CAM_CALDB(x, ...) +#endif +#define PAGE_SIZE_ 256 +#define BUFF_SIZE 8 + +static DEFINE_SPINLOCK(g_CAM_CALLock); /* for SMP */ +#define CAM_CAL_I2C_BUSNUM 2 + +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_ICS_REVISION 1 /* seanlin111208 */ +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_DRVNAME "CAM_CAL_DRV" +#define CAM_CAL_I2C_GROUP_ID 0 +#define CATC24C16_DEVICE_ID 0xA0 +#define CAM_CAL_DEV_MAJOR_NUMBER 226 + +/******************************************************************************* +* +********************************************************************************/ +static struct i2c_board_info kd_cam_cal_dev __initdata = { + I2C_BOARD_INFO(CAM_CAL_DRVNAME, 0xA0 >> 1) +}; +/* A0 for page0 A2 for page 2 and so on for 8 pages */ + +static struct i2c_client *g_pstI2Cclient; + +/* 81 is used for V4L driver */ +static dev_t g_CAM_CALdevno = MKDEV(CAM_CAL_DEV_MAJOR_NUMBER, 0); +static struct cdev *g_pCAM_CAL_CharDrv; +/* static spinlock_t g_CAM_CALLock; */ +/* spin_lock(&g_CAM_CALLock); */ +/* spin_unlock(&g_CAM_CALLock); */ + +static struct class *CAM_CAL_class; +static atomic_t g_CAM_CALatomic; +/* static DEFINE_SPINLOCK(kdcam_cal_drv_lock); */ +/* spin_lock(&kdcam_cal_drv_lock); */ +/* spin_unlock(&kdcam_cal_drv_lock); */ + + + + +#define EEPROM_I2C_SPEED 100 +/* #define LSCOTPDATASIZE 0x03c4 //964 */ +/* static kal_uint8 lscotpdata[LSCOTPDATASIZE]; */ + +static void kdSetI2CSpeed(u32 i2cSpeed) +{ + spin_lock(&g_CAM_CALLock); + g_pstI2Cclient->timing = i2cSpeed; + spin_unlock(&g_CAM_CALLock); + +} + +static int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData, u16 i2cId) +{ + int i4RetValue = 0; + + spin_lock(&g_CAM_CALLock); + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG); + + spin_unlock(&g_CAM_CALLock); + i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData); + if (i4RetValue != a_sizeSendData) { + CAM_CALERR(" I2C send failed!!, Addr = 0x%x\n", a_pSendData[0]); + return -1; + } + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_pRecvData, a_sizeRecvData); + if (i4RetValue != a_sizeRecvData) { + CAM_CALERR(" I2C read failed!!\n"); + return -1; + } + return 0; +} + + +/******************************************************************************* +* iWriteReg +********************************************************************************/ +#if 0 +static int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId) +{ + int i4RetValue = 0; + int u4Index = 0; + u8 *puDataInBytes = (u8 *)&a_u4Data; + int retry = 3; + + char puSendCmd[6] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF) , + 0 , 0 , 0 , 0 + }; + + spin_lock(&g_CAM_CALLock); + + + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG); + + spin_unlock(&g_CAM_CALLock); + + + if (a_u4Bytes > 2) { + CAM_CALERR(" exceed 2 bytes\n"); + return -1; + } + + if (a_u4Data >> (a_u4Bytes << 3)) + CAM_CALERR(" warning!! some data is not sent!!\n"); + + for (u4Index = 0; u4Index < a_u4Bytes; u4Index += 1) + puSendCmd[(u4Index + 2)] = puDataInBytes[(a_u4Bytes - u4Index - 1)]; + do { + i4RetValue = i2c_master_send(g_pstI2Cclient, puSendCmd, (a_u4Bytes + 2)); + + if (i4RetValue != (a_u4Bytes + 2)) + CAM_CALERR(" I2C send failed addr = 0x%x, data = 0x%x !!\n", a_u2Addr, a_u4Data); + else + break; + mdelay(5); + } while ((retry--) > 0); + return 0; +} +#endif + +bool selective_read_byte(u32 addr, BYTE *data, u16 i2c_id) +{ + /* CAM_CALDB("selective_read_byte\n"); */ + + u8 page = addr / PAGE_SIZE_; /* size of page was 256 */ + u8 offset = addr % PAGE_SIZE_; + + kdSetI2CSpeed(EEPROM_I2C_SPEED); + + if (iReadRegI2C(&offset, 1, (u8 *)data, 1, i2c_id + (page << 1)) < 0) { + CAM_CALERR("fail selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", + addr, *data, page, offset); + return false; + } + /* CAM_CALDB("selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", addr, + *data,page,offset); */ + return true; +} + +int selective_read_region(u32 addr, BYTE *data, u16 i2c_id, u32 size) +{ + /* u32 page = addr/PAGE_SIZE; //size of page was 256 */ + /* u32 offset = addr%PAGE_SIZE; */ + BYTE *buff = data; + u32 size_to_read = size; + /* kdSetI2CSpeed(EEPROM_I2C_SPEED); */ + int ret = 0; + + while (size_to_read > 0) { + if (selective_read_byte(addr, (u8 *)buff, CATC24C16_DEVICE_ID)) { + addr += 1; + buff += 1; + size_to_read -= 1; + ret += 1; + } else { + break; + + } +#if 0 + if (size_to_read > BUFF_SIZE) { + CAM_CALDB("offset =%x size %d\n", offset, BUFF_SIZE); + if (iReadRegI2C(&offset, 1, (u8 *)buff, BUFF_SIZE, i2c_id + (page << 1)) < 0) + break; + ret += BUFF_SIZE; + buff += BUFF_SIZE; + offset += BUFF_SIZE; + size_to_read -= BUFF_SIZE; + page += offset / PAGE_SIZE_; + + } else { + CAM_CALDB("offset =%x size %d\n", offset, size_to_read); + if (iReadRegI2C(&offset, 1, (u8 *)buff, (u16) size_to_read, i2c_id + (page << 1)) < 0) + break; + ret += size_to_read; + size_to_read = 0; + } +#endif + } + CAM_CALDB("selective_read_region addr =%x size %d data read = %d\n", addr, size, ret); + return ret; +} + + + + +/* Burst Write Data */ +static int iWriteData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char *pinputdata) +{ + CAM_CALDB("not implemented!"); + return 0; +} + + + + +#ifdef CONFIG_COMPAT +static int compat_put_cal_info_struct( + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32, + stCAM_CAL_INFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data->u4Offset); + err |= put_user(i, &data32->u4Offset); + err |= get_user(i, &data->u4Length); + err |= put_user(i, &data32->u4Length); + /* Assume pointer is not change */ +#if 1 + err |= get_user(p, (compat_uptr_t *)&data->pu1Params); + err |= put_user(p, &data32->pu1Params); +#endif + return err; +} +static int compat_get_cal_info_struct( + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32, + stCAM_CAL_INFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data32->u4Offset); + err |= put_user(i, &data->u4Offset); + err |= get_user(i, &data32->u4Length); + err |= put_user(i, &data->u4Length); + err |= get_user(p, &data32->pu1Params); + err |= put_user(compat_ptr(p), &data->pu1Params); + + return err; +} + +static long cat24c16_Ioctl_Compat(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + int err; + + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32; + stCAM_CAL_INFO_STRUCT __user *data; + + CAM_CALDB("[CAMERA SENSOR] cat24c16_Ioctl_Compat,%p %p %x ioc size %d\n", + filp->f_op , filp->f_op->unlocked_ioctl, cmd, _IOC_SIZE(cmd)); + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + + case COMPAT_CAM_CALIOC_G_READ: { + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_cal_info_struct(data32, data); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, CAM_CALIOC_G_READ, (unsigned long)data); + err = compat_put_cal_info_struct(data32, data); + + + if (err != 0) + CAM_CALERR("[CAMERA SENSOR] compat_put_acdk_sensor_getinfo_struct failed\n"); + return ret; + } + default: + return -ENOIOCTLCMD; + } +} + + +#endif + + +/******************************************************************************* +* +********************************************************************************/ +#define NEW_UNLOCK_IOCTL +#ifndef NEW_UNLOCK_IOCTL +static int CAM_CAL_Ioctl(struct inode *a_pstInode, + struct file *a_pstFile, + unsigned int a_u4Command, + unsigned long a_u4Param) +#else +static long CAM_CAL_Ioctl( + struct file *file, + unsigned int a_u4Command, + unsigned long a_u4Param +) +#endif +{ + int i4RetValue = 0; + u8 *pBuff = NULL; + u8 *pu1Params = NULL; + stCAM_CAL_INFO_STRUCT *ptempbuf; + + CAM_CALDB("[S24CAM_CAL] ioctl\n"); + +#ifdef CAM_CALGETDLT_DEBUG + struct timeval ktv1, ktv2; + unsigned long TimeIntervalUS; +#endif + + if (_IOC_NONE != _IOC_DIR(a_u4Command)) { + pBuff = kmalloc(sizeof(stCAM_CAL_INFO_STRUCT), GFP_KERNEL); + + if (NULL == pBuff) { + CAM_CALDB(" ioctl allocate mem failed\n"); + return -ENOMEM; + } + + if (_IOC_WRITE & _IOC_DIR(a_u4Command)) { + if (copy_from_user((u8 *) pBuff , (u8 *) a_u4Param, sizeof(stCAM_CAL_INFO_STRUCT))) { + /* get input structure address */ + kfree(pBuff); + CAM_CALDB("[S24CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + } + } + + ptempbuf = (stCAM_CAL_INFO_STRUCT *)pBuff; + pu1Params = kmalloc(ptempbuf->u4Length, GFP_KERNEL); + if (NULL == pu1Params) { + kfree(pBuff); + CAM_CALDB("ioctl allocate mem failed\n"); + return -ENOMEM; + } + CAM_CALDB(" init Working buffer address 0x%p command is 0x%x\n", pu1Params, a_u4Command); + + + if (copy_from_user((u8 *)pu1Params , (u8 *)ptempbuf->pu1Params, ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[S24CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + + switch (a_u4Command) { + case CAM_CALIOC_S_WRITE: + CAM_CALDB("[S24CAM_CAL] Write CMD\n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + i4RetValue = iWriteData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pu1Params); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + CAM_CALDB("Write data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + break; + case CAM_CALIOC_G_READ: + CAM_CALDB("[S24CAM_CAL] Read CMD\n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + CAM_CALDB("[CAM_CAL] offset %d\n", ptempbuf->u4Offset); + CAM_CALDB("[CAM_CAL] length %d\n", ptempbuf->u4Length); + /* CAM_CALDB("[CAM_CAL] Before read Working buffer address 0x%p\n", pu1Params); */ + + i4RetValue = selective_read_region(ptempbuf->u4Offset, pu1Params, + CATC24C16_DEVICE_ID, ptempbuf->u4Length); + CAM_CALDB("[S24CAM_CAL] After read Working buffer data 0x%x\n", *pu1Params); + + +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + CAM_CALDB("Read data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + + break; + default: + CAM_CALDB("[S24CAM_CAL] No CMD\n"); + i4RetValue = -EPERM; + break; + } + + if (_IOC_READ & _IOC_DIR(a_u4Command)) { + /* copy data to user space buffer, keep other input paremeter unchange. */ + CAM_CALDB("[S24CAM_CAL] to user length %d\n", ptempbuf->u4Length); + CAM_CALDB("[S24CAM_CAL] to user Working buffer address 0x%p\n", pu1Params); + if (copy_to_user((u8 __user *) ptempbuf->pu1Params , (u8 *)pu1Params , ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[S24CAM_CAL] ioctl copy to user failed\n"); + return -EFAULT; + } + } + + kfree(pBuff); + kfree(pu1Params); + return i4RetValue; +} + + +static u32 g_u4Opened; +/* #define */ +/* Main jobs: */ +/* 1.check for device-specified errors, device not ready. */ +/* 2.Initialize the device if it is opened for the first time. */ +static int CAM_CAL_Open(struct inode *a_pstInode, struct file *a_pstFile) +{ + CAM_CALDB("[S24CAM_CAL] CAM_CAL_Open\n"); + spin_lock(&g_CAM_CALLock); + if (g_u4Opened) { + spin_unlock(&g_CAM_CALLock); + CAM_CALDB("[S24CAM_CAL] Opened, return -EBUSY\n"); + return -EBUSY; + } /*else {*//*LukeHu--150720=For check patch*/ + if (!g_u4Opened) {/*LukeHu--150720=For check patch*/ + g_u4Opened = 1; + atomic_set(&g_CAM_CALatomic, 0); + } + spin_unlock(&g_CAM_CALLock); + mdelay(2); + return 0; +} + +/* Main jobs: */ +/* 1.Deallocate anything that "open" allocated in private_data. */ +/* 2.Shut down the device on last close. */ +/* 3.Only called once on last time. */ +/* Q1 : Try release multiple times. */ +static int CAM_CAL_Release(struct inode *a_pstInode, struct file *a_pstFile) +{ + spin_lock(&g_CAM_CALLock); + + g_u4Opened = 0; + + atomic_set(&g_CAM_CALatomic, 0); + + spin_unlock(&g_CAM_CALLock); + + return 0; +} + +static const struct file_operations g_stCAM_CAL_fops = { + .owner = THIS_MODULE, + .open = CAM_CAL_Open, + .release = CAM_CAL_Release, + /* .ioctl = CAM_CAL_Ioctl */ +#ifdef CONFIG_COMPAT + .compat_ioctl = cat24c16_Ioctl_Compat, +#endif + .unlocked_ioctl = CAM_CAL_Ioctl +}; + +#define CAM_CAL_DYNAMIC_ALLOCATE_DEVNO 1 +static inline int RegisterCAM_CALCharDrv(void) +{ + struct device *CAM_CAL_device = NULL; + +#if CAM_CAL_DYNAMIC_ALLOCATE_DEVNO + if (alloc_chrdev_region(&g_CAM_CALdevno, 0, 1, CAM_CAL_DRVNAME)) { + CAM_CALDB("[S24CAM_CAL] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if (register_chrdev_region(g_CAM_CALdevno , 1 , CAM_CAL_DRVNAME)) { + CAM_CALDB("[S24CAM_CAL] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + /* Allocate driver */ + g_pCAM_CAL_CharDrv = cdev_alloc(); + + if (NULL == g_pCAM_CAL_CharDrv) { + unregister_chrdev_region(g_CAM_CALdevno, 1); + + CAM_CALDB("[S24CAM_CAL] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + /* Attatch file operation. */ + cdev_init(g_pCAM_CAL_CharDrv, &g_stCAM_CAL_fops); + + g_pCAM_CAL_CharDrv->owner = THIS_MODULE; + + /* Add to system */ + if (cdev_add(g_pCAM_CAL_CharDrv, g_CAM_CALdevno, 1)) { + CAM_CALDB("[S24CAM_CAL] Attatch file operation failed\n"); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + return -EAGAIN; + } + + CAM_CAL_class = class_create(THIS_MODULE, "CAM_CALdrv"); + if (IS_ERR(CAM_CAL_class)) { + int ret = PTR_ERR(CAM_CAL_class); + + CAM_CALDB("Unable to create class, err = %d\n", ret); + return ret; + } + CAM_CAL_device = device_create(CAM_CAL_class, NULL, g_CAM_CALdevno, NULL, CAM_CAL_DRVNAME); + + return 0; +} + +static inline void UnregisterCAM_CALCharDrv(void) +{ + /* Release char driver */ + cdev_del(g_pCAM_CAL_CharDrv); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + device_destroy(CAM_CAL_class, g_CAM_CALdevno); + class_destroy(CAM_CAL_class); +} + + +/* //////////////////////////////////////////////////////////////////// */ +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); +#elif 0 +static int CAM_CAL_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); +#else +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int CAM_CAL_i2c_remove(struct i2c_client *); + +static const struct i2c_device_id CAM_CAL_i2c_id[] = {{CAM_CAL_DRVNAME, 0}, {} }; + + + +static struct i2c_driver CAM_CAL_i2c_driver = { + .probe = CAM_CAL_i2c_probe, + .remove = CAM_CAL_i2c_remove, + /* .detect = CAM_CAL_i2c_detect, */ + .driver.name = CAM_CAL_DRVNAME, + .id_table = CAM_CAL_i2c_id, +}; + +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) +{ + strcpy(info->type, CAM_CAL_DRVNAME); + return 0; +} +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i4RetValue = 0; + + CAM_CALDB("[S24CAM_CAL] Attach I2C\n"); + /* spin_lock_init(&g_CAM_CALLock); */ + + /* get sensor i2c client */ + spin_lock(&g_CAM_CALLock); /* for SMP */ + g_pstI2Cclient = client; + g_pstI2Cclient->addr = CATC24C16_DEVICE_ID >> 1; + spin_unlock(&g_CAM_CALLock); /* for SMP */ + + CAM_CALDB("[CAM_CAL] g_pstI2Cclient->addr = 0x%x\n", g_pstI2Cclient->addr); + /* Register char driver */ + i4RetValue = RegisterCAM_CALCharDrv(); + + if (i4RetValue) { + CAM_CALDB("[S24CAM_CAL] register char device failed!\n"); + return i4RetValue; + } + + + CAM_CALDB("[S24CAM_CAL] Attached!!\n"); + return 0; +} + +static int CAM_CAL_i2c_remove(struct i2c_client *client) +{ + return 0; +} + +static int CAM_CAL_probe(struct platform_device *pdev) +{ + return i2c_add_driver(&CAM_CAL_i2c_driver); +} + +static int CAM_CAL_remove(struct platform_device *pdev) +{ + i2c_del_driver(&CAM_CAL_i2c_driver); + return 0; +} + +/* platform structure */ +static struct platform_driver g_stCAM_CAL_Driver = { + .probe = CAM_CAL_probe, + .remove = CAM_CAL_remove, + .driver = { + .name = CAM_CAL_DRVNAME, + .owner = THIS_MODULE, + } +}; + + +static struct platform_device g_stCAM_CAL_Device = { + .name = CAM_CAL_DRVNAME, + .id = 0, + .dev = { + } +}; + +static int __init CAM_CAL_i2C_init(void) +{ + i2c_register_board_info(CAM_CAL_I2C_BUSNUM, &kd_cam_cal_dev, 1); + if (platform_driver_register(&g_stCAM_CAL_Driver)) { + CAM_CALDB("failed to register S24CAM_CAL driver\n"); + return -ENODEV; + } + + if (platform_device_register(&g_stCAM_CAL_Device)) { + CAM_CALDB("failed to register S24CAM_CAL driver, 2nd time\n"); + return -ENODEV; + } + + return 0; +} + +static void __exit CAM_CAL_i2C_exit(void) +{ + platform_driver_unregister(&g_stCAM_CAL_Driver); +} + +module_init(CAM_CAL_i2C_init); +module_exit(CAM_CAL_i2C_exit); + +MODULE_DESCRIPTION("CAM_CAL driver"); +MODULE_AUTHOR("Sean Lin "); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/cat24c16.h b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/cat24c16.h new file mode 100644 index 0000000000000000000000000000000000000000..818eb222698b21fa399d92066d242ff58ef664fb --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/cat24c16/cat24c16.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef __CAT24C16_H +#define __CAT24C16_H + +#endif/* __CAM_CAL_H */ + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/Makefile b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c3bd738a1faa03dfa55fefff7171da73155b9bb5 --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/Makefile @@ -0,0 +1,2 @@ + +obj-y += dummy_cam_cal.o diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/dummy_cam_cal.c b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/dummy_cam_cal.c new file mode 100644 index 0000000000000000000000000000000000000000..be76d706cbc0fe4f4af99b79b40f6c9c7ce5d65c --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/dummy_cam_cal.c @@ -0,0 +1,632 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_hw.h" +#include "cam_cal.h" +#include "cam_cal_define.h" + +#include "dummy_cam_cal.h" +/* #include // for SMP */ + +/* #define CAM_CALGETDLT_DEBUG //test */ +/* #define CAM_CAL_DEBUG //test */ +#ifdef CAM_CAL_DEBUG +#define CAM_CALDB pr_debug +#else +#define CAM_CALDB(x, ...) +#endif + + +static DEFINE_SPINLOCK(g_CAM_CALLock); /* for SMP */ + +#define CAM_CAL_I2C_BUSNUM 1 +static struct i2c_board_info kd_cam_cal_dev __initdata = { + I2C_BOARD_INFO("dummy_cam_cal", 0xAB >> 1) +};/* make dummy_eeprom co-exist */ + +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_ICS_REVISION 1 /* seanlin111208 */ +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_DRVNAME "dummy_cam_cal" +#define CAM_CAL_I2C_GROUP_ID 0 +#define CAM_CAL_DEV_MAJOR_NUMBER 226 +/* CAM_CAL READ/WRITE ID */ +#define S24CS64A_DEVICE_ID 0xAB /*0xFE */ + +/******************************************************************************* +* +********************************************************************************/ +/* fix warning MSG +static unsigned short g_pu2Normal_i2c[] = {S24CS64A_DEVICE_ID , I2C_CLIENT_END}; +static unsigned short g_u2Ignore = I2C_CLIENT_END; +static struct i2c_client_address_data g_stCAM_CAL_Addr_data = { + .normal_i2c = g_pu2Normal_i2c, + .probe = &g_u2Ignore, + .ignore = &g_u2Ignore +}; */ +static struct i2c_client *g_pstI2Cclient; + +/* 81 is used for V4L driver */ +static dev_t g_CAM_CALdevno = MKDEV(CAM_CAL_DEV_MAJOR_NUMBER, 0); +static struct cdev *g_pCAM_CAL_CharDrv; +/* static spinlock_t g_CAM_CALLock; */ +static struct class *CAM_CAL_class; +static atomic_t g_CAM_CALatomic; +/******************************************************************************* +* +********************************************************************************/ +/* maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt65xx.c which is 8 bytes */ +int iWriteCAM_CAL(u16 a_u2Addr , u32 a_u4Bytes, u8 *puDataInBytes) +{ + int i4RetValue = 0; + u32 u4Index = 0; + char puSendCmd[8] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF) , + 0, 0, 0, 0, 0, 0 + }; + if (a_u4Bytes + 2 > 8) { + CAM_CALDB("[CAM_CAL] exceed I2c-mt65xx.c 8 bytes limitation (include address 2 Byte)\n"); + return -1; + } + + for (u4Index = 0; u4Index < a_u4Bytes; u4Index += 1) + puSendCmd[(u4Index + 2)] = puDataInBytes[u4Index]; + + i4RetValue = i2c_master_send(g_pstI2Cclient, puSendCmd, (a_u4Bytes + 2)); + if (i4RetValue != (a_u4Bytes + 2)) { + CAM_CALDB("[CAM_CAL] I2C write failed!!\n"); + return -1; + } + mdelay(10); /* for tWR singnal --> write data form buffer to memory. */ + + /* CAM_CALDB("[CAM_CAL] iWriteCAM_CAL done!!\n"); */ + return 0; +} + + +/* maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt65xx.c which is 8 bytes */ +int iReadCAM_CAL(u16 a_u2Addr, u32 ui4_length, u8 *a_puBuff) +{ + int i4RetValue = 0; + char puReadCmd[2] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF)}; + + /* CAM_CALDB("[CAM_CAL] iReadCAM_CAL!!\n"); */ + + if (ui4_length > 8) { + CAM_CALDB("[CAM_CAL] exceed I2c-mt65xx.c 8 bytes limitation\n"); + return -1; + } + spin_lock(&g_CAM_CALLock); /* for SMP */ + g_pstI2Cclient->addr = g_pstI2Cclient->addr & (I2C_MASK_FLAG | I2C_WR_FLAG); + spin_unlock(&g_CAM_CALLock); /* for SMP */ + + /* CAM_CALDB("[EERPOM] i2c_master_send\n"); */ + i4RetValue = i2c_master_send(g_pstI2Cclient, puReadCmd, 2); + if (i4RetValue != 2) { + CAM_CALDB("[CAM_CAL] I2C send read address failed!!\n"); + return -1; + } + + /* CAM_CALDB("[EERPOM] i2c_master_recv\n"); */ + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_puBuff, ui4_length); + if (i4RetValue != ui4_length) { + CAM_CALDB("[CAM_CAL] I2C read data failed!!\n"); + return -1; + } + spin_lock(&g_CAM_CALLock); /* for SMP */ + g_pstI2Cclient->addr = g_pstI2Cclient->addr & I2C_MASK_FLAG; + spin_unlock(&g_CAM_CALLock); /* for SMP */ + + /* CAM_CALDB("[CAM_CAL] iReadCAM_CAL done!!\n"); */ + return 0; +} + + +static int iWriteData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char *pinputdata) +{ + int i4RetValue = 0; + int i4ResidueDataLength; + u32 u4IncOffset = 0; + u32 u4CurrentOffset; + u8 *pBuff; + + CAM_CALDB("[CAM_CAL] iWriteData\n"); + + + if (ui4_offset + ui4_length >= 0x2000) { + CAM_CALDB("[CAM_CAL] Write Error!! S-24CS64A not supprt address >= 0x2000!!\n"); + return -1; + } + + i4ResidueDataLength = (int)ui4_length; + u4CurrentOffset = ui4_offset; + pBuff = pinputdata; + CAM_CALDB("[CAM_CAL] iWriteData u4CurrentOffset is %d\n", u4CurrentOffset); + do { + if (i4ResidueDataLength >= 6) { + i4RetValue = iWriteCAM_CAL((u16)u4CurrentOffset, 6, pBuff); + if (i4RetValue != 0) { + CAM_CALDB("[CAM_CAL] I2C iWriteData failed!!\n"); + return -1; + } + u4IncOffset += 6; + i4ResidueDataLength -= 6; + u4CurrentOffset = ui4_offset + u4IncOffset; + pBuff = pinputdata + u4IncOffset; + } else { + i4RetValue = iWriteCAM_CAL((u16)u4CurrentOffset, i4ResidueDataLength, pBuff); + if (i4RetValue != 0) { + CAM_CALDB("[CAM_CAL] I2C iWriteData failed!!\n"); + return -1; + } + u4IncOffset += 6; + i4ResidueDataLength -= 6; + u4CurrentOffset = ui4_offset + u4IncOffset; + pBuff = pinputdata + u4IncOffset; + /* break; */ + } + } while (i4ResidueDataLength > 0); + CAM_CALDB("[CAM_CAL] iWriteData done\n"); + + return 0; +} + +/* int iReadData(stCAM_CAL_INFO_STRUCT * st_pOutputBuffer) */ +static int iReadData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char *pinputdata) +{ + int i4RetValue = 0; + int i4ResidueDataLength; + u32 u4IncOffset = 0; + u32 u4CurrentOffset; + u8 *pBuff; + + CAM_CALDB("[CAM_CAL] iReadData\n"); + + if (ui4_offset + ui4_length >= 0x2000) { + CAM_CALDB("[CAM_CAL] Read Error!! S-24CS64A not supprt address >= 0x2000!!\n"); + return -1; + } + + i4ResidueDataLength = (int)ui4_length; + u4CurrentOffset = ui4_offset; + pBuff = pinputdata; + do { + if (i4ResidueDataLength >= 8) { + i4RetValue = iReadCAM_CAL((u16)u4CurrentOffset, 8, pBuff); + if (i4RetValue != 0) { + CAM_CALDB("[CAM_CAL] I2C iReadData failed!!\n"); + return -1; + } + u4IncOffset += 8; + i4ResidueDataLength -= 8; + u4CurrentOffset = ui4_offset + u4IncOffset; + pBuff = pinputdata + u4IncOffset; + } else { + i4RetValue = iReadCAM_CAL((u16)u4CurrentOffset, i4ResidueDataLength, pBuff); + if (i4RetValue != 0) { + CAM_CALDB("[CAM_CAL] I2C iReadData failed!!\n"); + return -1; + } + u4IncOffset += 8; + i4ResidueDataLength -= 8; + u4CurrentOffset = ui4_offset + u4IncOffset; + pBuff = pinputdata + u4IncOffset; + /* break; */ + } + } while (i4ResidueDataLength > 0); + /* fix warning MSG CAM_CALDB("[CAM_CAL] iReadData finial address is %d length is %d + buffer address is 0x%x\n",u4CurrentOffset, i4ResidueDataLength, pBuff); */ + CAM_CALDB("[CAM_CAL] iReadData done\n"); + return 0; +} + + +/******************************************************************************* +* +********************************************************************************/ +#define NEW_UNLOCK_IOCTL +#ifndef NEW_UNLOCK_IOCTL +static int CAM_CAL_Ioctl(struct inode *a_pstInode, + struct file *a_pstFile, + unsigned int a_u4Command, + unsigned long a_u4Param) +#else +static long CAM_CAL_Ioctl( + struct file *file, + unsigned int a_u4Command, + unsigned long a_u4Param +) +#endif +{ + int i4RetValue = 0; + u8 *pBuff = NULL; + u8 *pWorkingBuff = NULL; + stCAM_CAL_INFO_STRUCT *ptempbuf; + +#ifdef CAM_CALGETDLT_DEBUG + struct timeval ktv1, ktv2; + unsigned long TimeIntervalUS; +#endif +/* + if (_IOC_NONE == _IOC_DIR(a_u4Command)) { + } else { +*/ + if (_IOC_NONE != _IOC_DIR(a_u4Command)) { + pBuff = kmalloc(sizeof(stCAM_CAL_INFO_STRUCT), GFP_KERNEL); + + if (NULL == pBuff) { + CAM_CALDB("[CAM_CAL] ioctl allocate mem failed\n"); + return -ENOMEM; + } + + if (_IOC_WRITE & _IOC_DIR(a_u4Command)) { + if (copy_from_user((u8 *) pBuff , (u8 *) a_u4Param, sizeof(stCAM_CAL_INFO_STRUCT))) { + /* get input structure address */ + kfree(pBuff); + CAM_CALDB("[CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + } + } + + ptempbuf = (stCAM_CAL_INFO_STRUCT *)pBuff; + pWorkingBuff = kmalloc(ptempbuf->u4Length, GFP_KERNEL); + if (NULL == pWorkingBuff) { + kfree(pBuff); + CAM_CALDB("[CAM_CAL] ioctl allocate mem failed\n"); + return -ENOMEM; + } + /* fix warning MSG CAM_CALDB("[CAM_CAL] init Working buffer address 0x%x command is + 0x%08x\n", pWorkingBuff, a_u4Command); */ + + + if (copy_from_user((u8 *)pWorkingBuff , (u8 *)ptempbuf->pu1Params, ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pWorkingBuff); + CAM_CALDB("[CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + + switch (a_u4Command) { + case CAM_CALIOC_S_WRITE: + CAM_CALDB("[CAM_CAL] Write CMD\n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + i4RetValue = iWriteData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + CAM_CALDB("Write data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + break; + case CAM_CALIOC_G_READ: + CAM_CALDB("[CAM_CAL] Read CMD\n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + CAM_CALDB("[CAM_CAL] offset %d\n", ptempbuf->u4Offset); + CAM_CALDB("[CAM_CAL] length %d\n", ptempbuf->u4Length); + /* fix warning MSG CAM_CALDB("[CAM_CAL] Before read Working buffer address + 0x%x\n", pWorkingBuff); */ + + i4RetValue = iReadData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff); + /* fix warning MSG CAM_CALDB("[CAM_CAL] After read Working buffer address + 0x%x\n", pWorkingBuff); */ + + +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + CAM_CALDB("Read data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + + break; + default: + CAM_CALDB("[CAM_CAL] No CMD\n"); + i4RetValue = -EPERM; + break; + } + + if (_IOC_READ & _IOC_DIR(a_u4Command)) { + /* copy data to user space buffer, keep other input paremeter unchange. */ + CAM_CALDB("[CAM_CAL] to user length %d\n", ptempbuf->u4Length); + /* fix warning MSG CAM_CALDB("[CAM_CAL] to user Working buffer address 0x%x\n", + pWorkingBuff); */ + if (copy_to_user((u8 __user *) ptempbuf->pu1Params , (u8 *)pWorkingBuff , ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pWorkingBuff); + CAM_CALDB("[CAM_CAL] ioctl copy to user failed\n"); + return -EFAULT; + } + } + + kfree(pBuff); + kfree(pWorkingBuff); + return i4RetValue; +} + + +static u32 g_u4Opened; +/* #define */ +/* Main jobs: */ +/* 1.check for device-specified errors, device not ready. */ +/* 2.Initialize the device if it is opened for the first time. */ +static int CAM_CAL_Open(struct inode *a_pstInode, struct file *a_pstFile) +{ + CAM_CALDB("[S24CAM_CAL] CAM_CAL_Open\n"); + spin_lock(&g_CAM_CALLock); + if (g_u4Opened) { + spin_unlock(&g_CAM_CALLock); + return -EBUSY; + } /*else {*//*LukeHu--150720=For check fo*/ + + if (!g_u4Opened) {/*LukeHu++150720=For check fo*/ + g_u4Opened = 1; + atomic_set(&g_CAM_CALatomic, 0); + } + spin_unlock(&g_CAM_CALLock); + + /* #if defined(MT6572) */ + /* do nothing */ + /* #else */ + /* if(TRUE != hwPowerOn(MT65XX_POWER_LDO_VCAMA, VOL_2800, "S24CS64A")) */ + /* { */ + /* CAM_CALDB("[CAM_CAL] Fail to enable analog gain\n"); */ + /* return -EIO; */ + /* } */ + /* #endif */ + + return 0; +} + +/* Main jobs: */ +/* 1.Deallocate anything that "open" allocated in private_data. */ +/* 2.Shut down the device on last close. */ +/* 3.Only called once on last time. */ +/* Q1 : Try release multiple times. */ +static int CAM_CAL_Release(struct inode *a_pstInode, struct file *a_pstFile) +{ + spin_lock(&g_CAM_CALLock); + + g_u4Opened = 0; + + atomic_set(&g_CAM_CALatomic, 0); + + spin_unlock(&g_CAM_CALLock); + + return 0; +} + +static const struct file_operations g_stCAM_CAL_fops = { + .owner = THIS_MODULE, + .open = CAM_CAL_Open, + .release = CAM_CAL_Release, + /* .ioctl = CAM_CAL_Ioctl */ + .unlocked_ioctl = CAM_CAL_Ioctl +}; + +#define CAM_CAL_DYNAMIC_ALLOCATE_DEVNO 1 +static inline int RegisterCAM_CALCharDrv(void) +{ + struct device *CAM_CAL_device = NULL; + +#if CAM_CAL_DYNAMIC_ALLOCATE_DEVNO + if (alloc_chrdev_region(&g_CAM_CALdevno, 0, 1, CAM_CAL_DRVNAME)) { + CAM_CALDB("[CAM_CAL] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if (register_chrdev_region(g_CAM_CALdevno , 1 , CAM_CAL_DRVNAME)) { + CAM_CALDB("[CAM_CAL] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + /* Allocate driver */ + g_pCAM_CAL_CharDrv = cdev_alloc(); + + if (NULL == g_pCAM_CAL_CharDrv) { + unregister_chrdev_region(g_CAM_CALdevno, 1); + + CAM_CALDB("[CAM_CAL] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + /* Attatch file operation. */ + cdev_init(g_pCAM_CAL_CharDrv, &g_stCAM_CAL_fops); + + g_pCAM_CAL_CharDrv->owner = THIS_MODULE; + + /* Add to system */ + if (cdev_add(g_pCAM_CAL_CharDrv, g_CAM_CALdevno, 1)) { + CAM_CALDB("[CAM_CAL] Attatch file operation failed\n"); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + return -EAGAIN; + } + + CAM_CAL_class = class_create(THIS_MODULE, "CAM_CALdrv"); + if (IS_ERR(CAM_CAL_class)) { + int ret = PTR_ERR(CAM_CAL_class); + + CAM_CALDB("Unable to create class, err = %d\n", ret); + return ret; + } + CAM_CAL_device = device_create(CAM_CAL_class, NULL, g_CAM_CALdevno, NULL, CAM_CAL_DRVNAME); + + return 0; +} + +static inline void UnregisterCAM_CALCharDrv(void) +{ + /* Release char driver */ + cdev_del(g_pCAM_CAL_CharDrv); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + device_destroy(CAM_CAL_class, g_CAM_CALdevno); + class_destroy(CAM_CAL_class); +} + + +/* //////////////////////////////////////////////////////////////////// */ +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); +#elif 0 +static int CAM_CAL_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); +#else +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int CAM_CAL_i2c_remove(struct i2c_client *); + +static const struct i2c_device_id CAM_CAL_i2c_id[] = {{CAM_CAL_DRVNAME, 0}, {} }; +#if 0 /* test110314 Please use the same I2C Group ID as Sensor */ +static unsigned short force[] = {CAM_CAL_I2C_GROUP_ID, S24CS64A_DEVICE_ID, I2C_CLIENT_END, + I2C_CLIENT_END}; +#else +/* static unsigned short force[] = {CAM_CAL_I2C_GROUP_ID, S24CS64A_DEVICE_ID, I2C_CLIENT_END, +I2C_CLIENT_END}; */ +#endif +/* static const unsigned short * const forces[] = { force, NULL }; */ +/* static struct i2c_client_address_data addr_data = { .forces = forces,}; */ + + +static struct i2c_driver CAM_CAL_i2c_driver = { + .probe = CAM_CAL_i2c_probe, + .remove = CAM_CAL_i2c_remove, + /* .detect = CAM_CAL_i2c_detect, */ + .driver.name = CAM_CAL_DRVNAME, + .id_table = CAM_CAL_i2c_id, +}; + +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) +{ + strcpy(info->type, CAM_CAL_DRVNAME); + return 0; +} +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i4RetValue = 0; + + CAM_CALDB("[CAM_CAL] Attach I2C\n"); + /* spin_lock_init(&g_CAM_CALLock); */ + + /* get sensor i2c client */ + spin_lock(&g_CAM_CALLock); /* for SMP */ + g_pstI2Cclient = client; + g_pstI2Cclient->addr = S24CS64A_DEVICE_ID >> 1; + spin_unlock(&g_CAM_CALLock); /* for SMP */ + + CAM_CALDB("[CAM_CAL] g_pstI2Cclient->addr = 0x%8x\n", g_pstI2Cclient->addr); + /* Register char driver */ + i4RetValue = RegisterCAM_CALCharDrv(); + + if (i4RetValue) { + CAM_CALDB("[CAM_CAL] register char device failed!\n"); + return i4RetValue; + } + + + CAM_CALDB("[CAM_CAL] Attached!!\n"); + return 0; +} + +static int CAM_CAL_i2c_remove(struct i2c_client *client) +{ + return 0; +} + +static int CAM_CAL_probe(struct platform_device *pdev) +{ + return i2c_add_driver(&CAM_CAL_i2c_driver); +} + +static int CAM_CAL_remove(struct platform_device *pdev) +{ + i2c_del_driver(&CAM_CAL_i2c_driver); + return 0; +} + +/* platform structure */ +static struct platform_driver g_stCAM_CAL_Driver = { + .probe = CAM_CAL_probe, + .remove = CAM_CAL_remove, + .driver = { + .name = CAM_CAL_DRVNAME, + .owner = THIS_MODULE, + } +}; + + +static struct platform_device g_stCAM_CAL_Device = { + .name = CAM_CAL_DRVNAME, + .id = 0, + .dev = { + } +}; + +static int __init CAM_CAL_i2C_init(void) +{ + i2c_register_board_info(CAM_CAL_I2C_BUSNUM, &kd_cam_cal_dev, 1); + if (platform_driver_register(&g_stCAM_CAL_Driver)) { + CAM_CALDB("failed to register CAM_CAL driver\n"); + return -ENODEV; + } + + if (platform_device_register(&g_stCAM_CAL_Device)) { + CAM_CALDB("failed to register CAM_CAL driver\n"); + return -ENODEV; + } + + return 0; +} + +static void __exit CAM_CAL_i2C_exit(void) +{ + platform_driver_unregister(&g_stCAM_CAL_Driver); +} + +module_init(CAM_CAL_i2C_init); +module_exit(CAM_CAL_i2C_exit); + +MODULE_DESCRIPTION("CAM_CAL driver"); +MODULE_AUTHOR("Sean Lin "); +MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/dummy_cam_cal.h b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/dummy_cam_cal.h new file mode 100644 index 0000000000000000000000000000000000000000..fee0ffc7482d557e67ac68524b6e14a7de0bc48e --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/dummy_eeprom/dummy_cam_cal.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/***************************************************************************** + * + * Filename: + * --------- + * S-24CS64A.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Header file of CAM_CAL driver + * + * + * Author: + * ------- + * Ronnie Lai (MTK01420) + * + *============================================================================*/ +#ifndef __DUMMY_CAM_CAL_H +#define __DUMMY_CAM_CAL_H + + +#endif /* __CAM_CAL_H */ + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/Makefile b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d7db6a488f0134e2d7f24124f2d38e515d038c22 --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/Makefile @@ -0,0 +1,4 @@ +$(info add imx258_eeprom.o) +obj-y += imx258_eeprom.o + + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/imx258_eeprom.c b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/imx258_eeprom.c new file mode 100644 index 0000000000000000000000000000000000000000..dc3312741d8cc7dcb10b0b662b1ef8dd59beeeb2 --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/imx258_eeprom.c @@ -0,0 +1,833 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_hw.h" +#include "cam_cal.h" +#include "cam_cal_define.h" +#include "imx258_eeprom.h" +/*#include // for SM*/ +#include +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + + +/*#define CAM_CALGETDLT_DEBUG*/ +#define CAM_CAL_DEBUG +#ifdef CAM_CAL_DEBUG +#include +#include + +#define PFX "imx258_eeprom" +/*pr_err("[%s] " fmt, __FUNCTION__, ##arg)*/ + +#define CAM_CALINF(format, args...) pr_info(PFX "[%s] " format, __func__, ##args) +#define CAM_CALDB(format, args...) pr_info(PFX "[%s] " format, __func__, ##args) +#define CAM_CALERR(format, args...) printk(KERN_ERR format, ##args) +#else +#define CAM_CALINF(x, ...) +#define CAM_CALDB(x, ...) +#define CAM_CALERR(x, ...) +#endif + +#define PAGE_SIZE_ 32 +#define BUFF_SIZE 8 + +static DEFINE_SPINLOCK(g_CAM_CALLock); /* for SMP*/ +#define CAM_CAL_I2C_BUSNUM 2 + +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_ICS_REVISION 1 /*seanlin111208*/ +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_DRVNAME "CAM_CAL_DRV" +#define CAM_CAL_I2C_GROUP_ID 0 + +#define CAM_CAL_DEV_MAJOR_NUMBER 226 + +/* CAM_CAL READ/WRITE ID */ +#define IMX258_DEVICE_ID 0xA0 + +/******************************************************************************* +* +********************************************************************************/ +static struct i2c_board_info kd_cam_cal_dev __initdata = { I2C_BOARD_INFO(CAM_CAL_DRVNAME, 0xA2 >> 1)}; + +static struct i2c_client *g_pstI2Cclient; + +/*81 is used for V4L driver*/ +static dev_t g_CAM_CALdevno = MKDEV(CAM_CAL_DEV_MAJOR_NUMBER, 0); +static struct cdev *g_pCAM_CAL_CharDrv; +/*static spinlock_t g_CAM_CALLock;*/ +/*spin_lock(&g_CAM_CALLock);*/ +/*spin_unlock(&g_CAM_CALLock);*/ + +static struct class *CAM_CAL_class; +static atomic_t g_CAM_CALatomic; +/*static DEFINE_SPINLOCK(kdcam_cal_drv_lock);*/ +/*spin_lock(&kdcam_cal_drv_lock);*/ +/*spin_unlock(&kdcam_cal_drv_lock);*/ + +static int selective_read_region(u32 addr, u8 *data, u16 i2c_id, u32 size); + + +#define EEPROM_I2C_SPEED 100 +/*#define LSCOTPDATASIZE 0x03c4 //964*/ +/*static kal_uint8 lscotpdata[LSCOTPDATASIZE];*/ + +static void kdSetI2CSpeed(u32 i2cSpeed) +{ + spin_lock(&g_CAM_CALLock); + g_pstI2Cclient->timing = i2cSpeed; + spin_unlock(&g_CAM_CALLock); + +} + + +/******************************************************************************* +* iWriteRegI2C +********************************************************************************/ +/* +int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId) +{ + int i4RetValue = 0; + int retry = 3; + +// PK_DBG("Addr : 0x%x,Val : 0x%x\n",a_u2Addr,a_u4Data); + + //KD_IMGSENSOR_PROFILE_INIT(); + spin_lock(&g_CAM_CALLock); + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_DMA_FLAG); + spin_unlock(&g_CAM_CALLock); + // + + do { + i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData); + if (i4RetValue != a_sizeSendData) { + CAM_CALERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x, Data = 0x%x\n", + a_pSendData[0], a_pSendData[1] ); + } + else { + break; + } + udelay(50); + } while ((retry--) > 0); + //KD_IMGSENSOR_PROFILE("iWriteRegI2C"); + return 0; +} +*/ + + +/******************************************************************************* +* iWriteReg +********************************************************************************/ +#if 0 +static int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId) +{ + int i4RetValue = 0; + int u4Index = 0; + u8 *puDataInBytes = (u8 *)&a_u4Data; + int retry = 3; + + char puSendCmd[6] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF) , + 0 , 0 , 0 , 0 + }; + + spin_lock(&g_CAM_CALLock); + + + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG); + + spin_unlock(&g_CAM_CALLock); + + + if (a_u4Bytes > 2) { + CAM_CALERR(" exceed 2 bytes\n"); + return -1; + } + + if (a_u4Data >> (a_u4Bytes << 3)) + CAM_CALERR(" warning!! some data is not sent!!\n"); + + for (u4Index = 0; u4Index < a_u4Bytes; u4Index += 1) + puSendCmd[(u4Index + 2)] = puDataInBytes[(a_u4Bytes - u4Index - 1)]; + do { + i4RetValue = i2c_master_send(g_pstI2Cclient, puSendCmd, (a_u4Bytes + 2)); + + if (i4RetValue != (a_u4Bytes + 2)) + CAM_CALERR(" I2C send failed addr = 0x%x, data = 0x%x !!\n", a_u2Addr, a_u4Data); + else + break; + mdelay(5); + } while ((retry--) > 0); + return 0; +} +#endif + +/* +static bool selective_read_byte(u32 addr, BYTE* data,u16 i2c_id) +{ +// CAM_CALDB("selective_read_byte\n"); + + u8 page = addr/PAGE_SIZE_; size of page was 256 + u8 offset = addr%PAGE_SIZE_; + kdSetI2CSpeed(EEPROM_I2C_SPEED); + + if(iReadRegI2C(&offset, 1, (u8*)data, 1, i2c_id+(page<<1))<0) { + CAM_CALERR("[CAM_CAL] fail selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", + addr, *data,page,offset); + return false; + } + //CAM_CALDB("selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", addr, *data,page, + offset); + return true; +} +*/ +static bool byteread_cmos_sensor(unsigned char SLAVEID, unsigned short addr, unsigned char *data) +{ + /* To call your IIC function here*/ + /*char puSendCmd[1] = {(char)(addr & 0xFF) };*/ + /*if(iReadRegI2C(puSendCmd , sizeof(puSendCmd), data, 1, SLAVEID)<0) {*/ + char puSendCmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + + kdSetI2CSpeed(EEPROM_I2C_SPEED); + if (iReadRegI2C(puSendCmd , 2, data, 1, SLAVEID) < 0) { + CAM_CALERR("[CAM_CAL] fail imx258_byteread_cmos_sensor addr =0x%x, data = 0x%x", addr, *data); + return false; + } + /*CAM_CALDB("selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", addr, + *data,page,offset);*/ + CAM_CALDB("[CAM_CAL] imx258_cmos_sensor addr =0x%x, data = 0x%x", addr, *data); + return true; + +} + + +static int selective_read_region(u32 addr, u8 *data, u16 i2c_id, u32 size) +{ + /*u32 page = addr/PAGE_SIZE;//size of page was 256 */ + /*u32 offset = addr%PAGE_SIZE;*/ + unsigned short curAddr = (unsigned short)addr; + u8 *buff = data; + u32 size_to_read = size; + /*kdSetI2CSpeed(EEPROM_I2C_SPEED);*/ + int ret = 0; + + CAM_CALDB("Before byteread_cmos_sensor curAddr =%x count=%d buffData=%x\n", curAddr, + size - size_to_read, *buff); + while (size_to_read > 0) { + /*if(selective_read_byte(addr,(u8*)buff,S5K2P8_DEVICE_ID)){*/ + if (byteread_cmos_sensor(0xA0, curAddr, buff)) { + CAM_CALDB("after byteread_cmos_sensor curAddr =%x count=%d buffData=%x\n", curAddr, + size - size_to_read, *buff); + curAddr += 1; + buff += 1; + size_to_read -= 1; + ret += 1; + } else { + break; + + } +#if 0 + if (size_to_read > BUFF_SIZE) { + CAM_CALDB("offset =%x size %d\n", offset, BUFF_SIZE); + if (iReadRegI2C(&offset, 1, (u8 *)buff, BUFF_SIZE, i2c_id + (page << 1)) < 0) + break; + ret += BUFF_SIZE; + buff += BUFF_SIZE; + offset += BUFF_SIZE; + size_to_read -= BUFF_SIZE; + page += offset / PAGE_SIZE_; + + } else { + CAM_CALDB("offset =%x size %d\n", offset, size_to_read); + if (iReadRegI2C(&offset, 1, (u8 *)buff, (u16) size_to_read, i2c_id + (page << 1)) < 0) + break; + ret += size_to_read; + size_to_read = 0; + } +#endif + } + CAM_CALDB("selective_read_region addr =%x size %d readSize = %d\n", addr, size, ret); + return ret; +} + +/* +static int iReadRegI2C2(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, +u16 a_sizeRecvData, u16 i2cId) +{ + int i4RetValue = 0; + + spin_lock(&g_CAM_CALLock); + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_DMA_FLAG); + + spin_unlock(&g_CAM_CALLock); + i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData); + if (i4RetValue != a_sizeSendData) { + CAM_CALERR(" I2C send failed!!, Addr = 0x%x\n", a_pSendData[0]); + return -1; + } + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_pRecvData, a_sizeRecvData); + if (i4RetValue != a_sizeRecvData) { + CAM_CALERR(" I2C read failed!!\n"); + return -1; + } + return 0; +} +*/ +/* +static int lm75_read_value(struct i2c_client *client) +{ + struct i2c_msg msgs[2]; + int status; + char buf1[2]; + char buf2[2]; + msgs[0].len = 1; + msgs[0].addr = client->addr; // lm75 ???? + msgs[0].flags = 0;//write + msgs[0].buf = buf1; + msgs[0].buf[0] = LM75_REG_TEMP[0]; + msgs[1].len = 2;//????? + msgs[1].addr = client->addr;// lm75 ???? + msgs[1].flags = I2C_M_RD;//read + msgs[1].buf = buf2;//????????? + status = i2c_transfer(client->adapter, msgs, 2); + if(status < 0) + return status; + //printk("1 = %2x %2x\n", buf2[0], buf2[1]); + return (buf2[0] << 8) | buf2[1]; +} + +// maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt65xx.c which is 8 bytes +int iReadEEPROM(u16 a_u2Addr, u32 ui4_length, u8 * a_puBuff) +{ + int i4RetValue = 0; + char puReadCmd[2] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF)}; + + //EEPROMDB("[EEPROM] iReadEEPROM!!\n"); + + if(ui4_length > 8) + { + EEPROMDB("[BRCC064GWZ_3_eeprom] exceed I2c-mt65xx.c 8 bytes limitation\n"); + return -1; + } + spin_lock(&g_EEPROMLock); //for SMP + g_pstI2Cclient->addr = g_pstI2Cclient->addr & (I2C_MASK_FLAG | I2C_WR_FLAG); + spin_unlock(&g_EEPROMLock); // for SMP + + //EEPROMDB("[EEPROM] i2c_master_send\n"); + i4RetValue = i2c_master_send(g_pstI2Cclient, puReadCmd, 2); + if (i4RetValue != 2) + { + EEPROMDB("[BRCC064GWZ_3_eeprom] I2C send read address failed!!\n"); + return -1; + } + + //EEPROMDB("[EEPROM] i2c_master_recv\n"); + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_puBuff, ui4_length); + if (i4RetValue != ui4_length) + { + EEPROMDB("[BRCC064GWZ_3_eeprom] I2C read data failed!!\n"); + return -1; + } + spin_lock(&g_EEPROMLock); //for SMP + g_pstI2Cclient->addr = g_pstI2Cclient->addr & I2C_MASK_FLAG; + spin_unlock(&g_EEPROMLock); // for SMP + + //EEPROMDB("[EEPROM] iReadEEPROM done!!\n"); + return 0; +} +*/ + + +/* Burst Write Data */ +static int iWriteData(unsigned int ui4_offset, unsigned int ui4_length, +unsigned char *pinputdata) +{ + CAM_CALDB("[CAM_CAL] not implemented!"); + return 0; +} + + + + +#ifdef CONFIG_COMPAT +static int compat_put_cal_info_struct( + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32, + stCAM_CAL_INFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data->u4Offset); + err |= put_user(i, &data32->u4Offset); + err |= get_user(i, &data->u4Length); + err |= put_user(i, &data32->u4Length); + /* Assume pointer is not change */ +#if 1 + err |= get_user(p, (compat_uptr_t *)&data->pu1Params); + err |= put_user(p, &data32->pu1Params); +#endif + return err; +} +static int compat_get_cal_info_struct( + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32, + stCAM_CAL_INFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data32->u4Offset); + err |= put_user(i, &data->u4Offset); + err |= get_user(i, &data32->u4Length); + err |= put_user(i, &data->u4Length); + err |= get_user(p, &data32->pu1Params); + err |= put_user(compat_ptr(p), &data->pu1Params); + + return err; +} + +static long imx258_Ioctl_Compat(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32; + stCAM_CAL_INFO_STRUCT __user *data; + int err; + + CAM_CALDB("[CAMERA SENSOR] imx258_Ioctl_Compat,%p %p %x ioc size %d\n", filp->f_op , + filp->f_op->unlocked_ioctl, cmd, _IOC_SIZE(cmd)); + + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + + case COMPAT_CAM_CALIOC_G_READ: { + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_cal_info_struct(data32, data); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, CAM_CALIOC_G_READ, + (unsigned long)data); + err = compat_put_cal_info_struct(data32, data); + + + if (err != 0) + CAM_CALERR("[CAM_CAL] compat_put_acdk_sensor_getinfo_struct failed\n"); + return ret; + } + default: + return -ENOIOCTLCMD; + } +} + + +#endif + + +/******************************************************************************* +* +********************************************************************************/ +#define NEW_UNLOCK_IOCTL +#ifndef NEW_UNLOCK_IOCTL +static int CAM_CAL_Ioctl(struct inode *a_pstInode, + struct file *a_pstFile, + unsigned int a_u4Command, + unsigned long a_u4Param) +#else +static long CAM_CAL_Ioctl( + struct file *file, + unsigned int a_u4Command, + unsigned long a_u4Param +) +#endif +{ + int i4RetValue = 0; + u8 *pBuff = NULL; + u8 *pu1Params = NULL; + stCAM_CAL_INFO_STRUCT *ptempbuf; + + CAM_CALDB("[CAM_CAL] ioctl\n"); + +#ifdef CAM_CALGETDLT_DEBUG + struct timeval ktv1, ktv2; + unsigned long TimeIntervalUS; +#endif + + /*if (_IOC_NONE == _IOC_DIR(a_u4Command)) { + } else {*/ + if (_IOC_NONE != _IOC_DIR(a_u4Command)) { + pBuff = kmalloc(sizeof(stCAM_CAL_INFO_STRUCT), GFP_KERNEL); + + if (NULL == pBuff) { + CAM_CALDB(" ioctl allocate mem failed\n"); + return -ENOMEM; + } + + if (_IOC_WRITE & _IOC_DIR(a_u4Command)) { + if (copy_from_user((u8 *) pBuff , (u8 *) a_u4Param, sizeof(stCAM_CAL_INFO_STRUCT))) { + /*get input structure address*/ + kfree(pBuff); + CAM_CALDB("[CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + } + } + + ptempbuf = (stCAM_CAL_INFO_STRUCT *)pBuff; + pu1Params = kmalloc(ptempbuf->u4Length, GFP_KERNEL); + if (NULL == pu1Params) { + kfree(pBuff); + CAM_CALDB("[CAM_CAL] ioctl allocate mem failed\n"); + return -ENOMEM; + } + CAM_CALDB(" init Working buffer address 0x%p command is 0x%x\n", pu1Params, a_u4Command); + + + if (copy_from_user((u8 *)pu1Params, (u8 *)ptempbuf->pu1Params, ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + + switch (a_u4Command) { + case CAM_CALIOC_S_WRITE: + CAM_CALDB("[CAM_CAL] Write CMD\n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + i4RetValue = iWriteData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pu1Params); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + CAM_CALDB("Write data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + break; + case CAM_CALIOC_G_READ: + CAM_CALDB("[CAM_CAL] Read CMD\n"); + +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + CAM_CALDB("[CAM_CAL] offset %d\n", ptempbuf->u4Offset); + CAM_CALDB("[CAM_CAL] length %d\n", ptempbuf->u4Length); + /**pu1Params = 0;*/ + i4RetValue = selective_read_region(ptempbuf->u4Offset, pu1Params, IMX258_DEVICE_ID, ptempbuf->u4Length); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + CAM_CALDB("Read data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + + break; + default: + CAM_CALDB("[CAM_CAL] No CMD\n"); + i4RetValue = -EPERM; + break; + } + + if (_IOC_READ & _IOC_DIR(a_u4Command)) { + /*copy data to user space buffer, keep other input paremeter unchange.*/ + CAM_CALDB("[CAM_CAL] to user length %d\n", ptempbuf->u4Length); + CAM_CALDB("[CAM_CAL] to user Working buffer address 0x%p\n", pu1Params); + if (copy_to_user((u8 __user *) ptempbuf->pu1Params , (u8 *)pu1Params , ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[CAM_CAL] ioctl copy to user failed\n"); + return -EFAULT; + } + } + + kfree(pBuff); + kfree(pu1Params); + return i4RetValue; +} + + +static u32 g_u4Opened; +/*#define +//Main jobs: +// 1.check for device-specified errors, device not ready. +// 2.Initialize the device if it is opened for the first time.*/ +static int CAM_CAL_Open(struct inode *a_pstInode, struct file *a_pstFile) +{ + CAM_CALDB("[CAM_CAL] CAM_CAL_Open\n"); + spin_lock(&g_CAM_CALLock); + if (g_u4Opened) { + spin_unlock(&g_CAM_CALLock); + CAM_CALDB("[CAM_CAL] Opened, return -EBUSY\n"); + return -EBUSY; + } else { + g_u4Opened = 1; + atomic_set(&g_CAM_CALatomic, 0); + } + spin_unlock(&g_CAM_CALLock); + mdelay(2); + return 0; +} + +/*Main jobs: +// 1.Deallocate anything that "open" allocated in private_data. +// 2.Shut down the device on last close. +// 3.Only called once on last time. +// Q1 : Try release multiple times.*/ +static int CAM_CAL_Release(struct inode *a_pstInode, struct file *a_pstFile) +{ + spin_lock(&g_CAM_CALLock); + + g_u4Opened = 0; + + atomic_set(&g_CAM_CALatomic, 0); + + spin_unlock(&g_CAM_CALLock); + + return 0; +} + +static const struct file_operations g_stCAM_CAL_fops = { + .owner = THIS_MODULE, + .open = CAM_CAL_Open, + .release = CAM_CAL_Release, + /*.ioctl = CAM_CAL_Ioctl*/ +#ifdef CONFIG_COMPAT + .compat_ioctl = imx258_Ioctl_Compat, +#endif + .unlocked_ioctl = CAM_CAL_Ioctl +}; + +#define CAM_CAL_DYNAMIC_ALLOCATE_DEVNO 1 +static inline int RegisterCAM_CALCharDrv(void) +{ + CAM_CALDB("[CAM_CAL] RegisterCAM_CALCharDrv Start\n"); + + struct device *CAM_CAL_device = NULL; + +#if CAM_CAL_DYNAMIC_ALLOCATE_DEVNO + if (alloc_chrdev_region(&g_CAM_CALdevno, 0, 1, CAM_CAL_DRVNAME)) { + CAM_CALDB("[CAM_CAL] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if (register_chrdev_region(g_CAM_CALdevno , 1 , CAM_CAL_DRVNAME)) { + CAM_CALDB("[CAM_CAL] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + /*Allocate driver*/ + g_pCAM_CAL_CharDrv = cdev_alloc(); + + if (NULL == g_pCAM_CAL_CharDrv) { + unregister_chrdev_region(g_CAM_CALdevno, 1); + + CAM_CALDB("[CAM_CAL] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + /*Attatch file operation.*/ + cdev_init(g_pCAM_CAL_CharDrv, &g_stCAM_CAL_fops); + + g_pCAM_CAL_CharDrv->owner = THIS_MODULE; + + /*Add to system*/ + if (cdev_add(g_pCAM_CAL_CharDrv, g_CAM_CALdevno, 1)) { + CAM_CALDB("[CAM_CAL] Attatch file operation failed\n"); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + return -EAGAIN; + } + + CAM_CAL_class = class_create(THIS_MODULE, "CAM_CALdrv1"); + + if (IS_ERR(CAM_CAL_class)) { + int ret = PTR_ERR(CAM_CAL_class); + + CAM_CALDB("[CAM_CAL] Unable to create class, err = %d\n", ret); + return ret; + } + CAM_CAL_device = device_create(CAM_CAL_class, NULL, g_CAM_CALdevno, NULL, CAM_CAL_DRVNAME); + CAM_CALDB("[CAM_CAL] RegisterCAM_CALCharDrv End\n"); + + return 0; +} + +static inline void UnregisterCAM_CALCharDrv(void) +{ + /*Release char driver*/ + cdev_del(g_pCAM_CAL_CharDrv); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + device_destroy(CAM_CAL_class, g_CAM_CALdevno); + class_destroy(CAM_CAL_class); +} + + +/* //////////////////////////////////////////////////////////////////// */ +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); +#elif 0 +static int CAM_CAL_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); +#else +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int CAM_CAL_i2c_remove(struct i2c_client *); + +static const struct i2c_device_id CAM_CAL_i2c_id[] = {{CAM_CAL_DRVNAME, 0}, {} }; + + + +static struct i2c_driver CAM_CAL_i2c_driver = { + .probe = CAM_CAL_i2c_probe, + .remove = CAM_CAL_i2c_remove, + /* .detect = CAM_CAL_i2c_detect,*/ + .driver.name = CAM_CAL_DRVNAME, + .id_table = CAM_CAL_i2c_id, +}; + +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) +{ + strcpy(info->type, CAM_CAL_DRVNAME); + return 0; +} +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i4RetValue = 0; + + CAM_CALDB("[CAM_CAL] CAM_CAL_i2c_probe Start!\n"); + /* spin_lock_init(&g_CAM_CALLock);*/ + + /*get sensor i2c client*/ + spin_lock(&g_CAM_CALLock); /*for SMP*/ + g_pstI2Cclient = client; + g_pstI2Cclient->addr = IMX258_DEVICE_ID >> 1; + spin_unlock(&g_CAM_CALLock); /* for SMP*/ + + CAM_CALDB("[CAM_CAL] g_pstI2Cclient->addr = 0x%x\n", g_pstI2Cclient->addr); + /*Register char driver*/ + i4RetValue = RegisterCAM_CALCharDrv(); + + if (i4RetValue) { + CAM_CALDB("[CAM_CAL] register char device failed!\n"); + return i4RetValue; + } + + CAM_CALDB("[CAM_CAL] CAM_CAL_i2c_probe End!\n"); + return 0; +} + +static int CAM_CAL_i2c_remove(struct i2c_client *client) +{ + return 0; +} + +static int CAM_CAL_probe(struct platform_device *pdev) +{ + CAM_CALDB("[CAM_CAL] CAM_CAL_probe start!\n"); + return i2c_add_driver(&CAM_CAL_i2c_driver); +} + +static int CAM_CAL_remove(struct platform_device *pdev) +{ + i2c_del_driver(&CAM_CAL_i2c_driver); + return 0; +} + +/*platform structure*/ +static struct platform_driver g_stCAM_CAL_Driver = { + .probe = CAM_CAL_probe, + .remove = CAM_CAL_remove, + .driver = { + .name = CAM_CAL_DRVNAME, + .owner = THIS_MODULE, + } +}; + + +static struct platform_device g_stCAM_CAL_Device = { + .name = CAM_CAL_DRVNAME, + .id = 0, + .dev = { + } +}; + +static int __init CAM_CAL_i2C_init(void) +{ + CAM_CALDB("[CAM_CAL] CAM_CAL_i2C_init Start!\n"); + i2c_register_board_info(CAM_CAL_I2C_BUSNUM, &kd_cam_cal_dev, 1); + if (platform_driver_register(&g_stCAM_CAL_Driver)) { + CAM_CALDB("[CAM_CAL] failed to register CAM_CAL driver\n"); + return -ENODEV; + } + + if (platform_device_register(&g_stCAM_CAL_Device)) { + CAM_CALDB("[CAM_CAL] failed to register CAM_CAL driver, 2nd time\n"); + return -ENODEV; + } + CAM_CALDB("[CAM_CAL] CAM_CAL_i2C_init End!\n"); + return 0; +} + +static void __exit CAM_CAL_i2C_exit(void) +{ + platform_driver_unregister(&g_stCAM_CAL_Driver); +} + +module_init(CAM_CAL_i2C_init); +module_exit(CAM_CAL_i2C_exit); + +MODULE_DESCRIPTION("IMX258 CAM_CAL driver"); +MODULE_AUTHOR("LukeHu "); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/imx258_eeprom.h b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/imx258_eeprom.h new file mode 100644 index 0000000000000000000000000000000000000000..9b80d56cee27ddbef5bb6446ba13015b94ccf7ad --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/imx258_eeprom/imx258_eeprom.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef __IMX258_EEPROM_H +#define __IMX258_EEPROM_H + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, +u16 a_sizeRecvData, u16 i2cId); + + + +#endif /* __CAM_CAL_H */ + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/Makefile b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..df3bb0994aea432fbdbb435ffd5862027bbf320e --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/Makefile @@ -0,0 +1,4 @@ +$(info add ov8858_eeprom.o) +obj-y += ov8858_eeprom.o + + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/ov8858_eeprom.c b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/ov8858_eeprom.c new file mode 100644 index 0000000000000000000000000000000000000000..b5dbae8ac6c11a5751cf9a1a3b5cc07ed088412c --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/ov8858_eeprom.c @@ -0,0 +1,761 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +/* + * Driver for CAM_CAL + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_hw.h" +#include "cam_cal.h" +#include "cam_cal_define.h" +#include "ov8858_eeprom.h" +/*#include // for SM*/ +#include +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + + +/*#define CAM_CALGETDLT_DEBUG*/ +/*#define CAM_CAL_DEBUG*/ +#ifdef CAM_CAL_DEBUG +#include +#include + +#define PFX "ov8858_eeprom" +/*pr_err("[%s] " fmt, __FUNCTION__, ##arg)*/ + +#define CAM_CALINF(format, args...) pr_info(PFX "[%s] " format, __func__, ##args) +#define CAM_CALDB(format, args...) pr_debug(PFX "[%s] " format, __func__, ##args) +#define CAM_CALERR(format, args...) printk(KERN_ERR format, ##args) +#else +#define CAM_CALINF(x, ...) +#define CAM_CALDB(x, ...) +#define CAM_CALERR(x, ...) +#endif + +#define PAGE_SIZE_ 32 +#define BUFF_SIZE 8 + +static DEFINE_SPINLOCK(g_CAM_CALLock); /* for SMP*/ +#define CAM_CAL_I2C_BUSNUM 0 + +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_ICS_REVISION 1 /*seanlin111208*/ +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_DRVNAME "CAM_CAL_DRV2" +#define CAM_CAL_I2C_GROUP_ID 0 +#define CAM_CAL_DEV_MAJOR_NUMBER 226 +#define OV8858_DEVICE_ID 0xA2 + +/******************************************************************************* +* +********************************************************************************/ +static struct i2c_board_info kd_cam_cal_dev __initdata = { I2C_BOARD_INFO(CAM_CAL_DRVNAME, 0xA2 >> 1)}; + +static struct i2c_client *g_pstI2Cclient; + +/*81 is used for V4L driver*/ +static dev_t g_CAM_CALdevno = MKDEV(CAM_CAL_DEV_MAJOR_NUMBER, 0); +static struct cdev *g_pCAM_CAL_CharDrv; +/*static spinlock_t g_CAM_CALLock;*/ +/*spin_lock(&g_CAM_CALLock);*/ +/*spin_unlock(&g_CAM_CALLock);*/ + +static struct class *CAM_CAL_class; +static atomic_t g_CAM_CALatomic; +/*static DEFINE_SPINLOCK(kdcam_cal_drv_lock);*/ +/*spin_lock(&kdcam_cal_drv_lock);*/ +/*spin_unlock(&kdcam_cal_drv_lock);*/ + +static int selective_read_region(u32 addr, u8 *data, u16 i2c_id, u32 size); + + +#define EEPROM_I2C_SPEED 100 + + +static void kdSetI2CSpeed(u32 i2cSpeed) +{ + spin_lock(&g_CAM_CALLock); + g_pstI2Cclient->timing = i2cSpeed; + spin_unlock(&g_CAM_CALLock); + +} + + +/******************************************************************************* +* iWriteRegI2C +********************************************************************************/ +/* +int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId) +{ + int i4RetValue = 0; + int retry = 3; + +// PK_DBG("Addr : 0x%x,Val : 0x%x\n",a_u2Addr,a_u4Data); + + //KD_IMGSENSOR_PROFILE_INIT(); + spin_lock(&g_CAM_CALLock); + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_DMA_FLAG); + spin_unlock(&g_CAM_CALLock); + // + + do { + i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData); + if (i4RetValue != a_sizeSendData) { + CAM_CALERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x, Data = 0x%x\n", + a_pSendData[0], a_pSendData[1] ); + } + else { + break; + } + udelay(50); + } while ((retry--) > 0); + //KD_IMGSENSOR_PROFILE("iWriteRegI2C"); + return 0; +} +*/ + + +/******************************************************************************* +* iWriteReg +********************************************************************************/ +#if 0 +static int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId) +{ + int i4RetValue = 0; + int u4Index = 0; + u8 *puDataInBytes = (u8 *)&a_u4Data; + int retry = 3; + + char puSendCmd[6] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF) , + 0 , 0 , 0 , 0 + }; + + spin_lock(&g_CAM_CALLock); + + + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG); + + spin_unlock(&g_CAM_CALLock); + + + if (a_u4Bytes > 2) { + CAM_CALERR(" exceed 2 bytes\n"); + return -1; + } + + if (a_u4Data >> (a_u4Bytes << 3)) + CAM_CALERR(" warning!! some data is not sent!!\n"); + + for (u4Index = 0; u4Index < a_u4Bytes; u4Index += 1) + puSendCmd[(u4Index + 2)] = puDataInBytes[(a_u4Bytes - u4Index - 1)]; + do { + i4RetValue = i2c_master_send(g_pstI2Cclient, puSendCmd, (a_u4Bytes + 2)); + + if (i4RetValue != (a_u4Bytes + 2)) + CAM_CALERR(" I2C send failed addr = 0x%x, data = 0x%x !!\n", a_u2Addr, a_u4Data); + else + break; + mdelay(5); + } while ((retry--) > 0); + return 0; +} +#endif + +/* +static bool selective_read_byte(u32 addr, BYTE* data,u16 i2c_id) +{ +// CAM_CALDB("selective_read_byte\n"); + + u8 page = addr/PAGE_SIZE_; size of page was 256 + u8 offset = addr%PAGE_SIZE_; + kdSetI2CSpeed(EEPROM_I2C_SPEED); + + if(iReadRegI2C(&offset, 1, (u8*)data, 1, i2c_id+(page<<1))<0) { + CAM_CALERR("[CAM_CAL] fail selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", + addr, *data,page,offset); + return false; + } + //CAM_CALDB("selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", addr, *data,page, + offset); + return true; +} +*/ +static bool byteread_cmos_sensor(unsigned char SLAVEID, unsigned short addr, unsigned char *data) +{ + /* To call your IIC function here*/ + /*char puSendCmd[1] = {(char)(addr & 0xFF) };*/ + /*if(iReadRegI2C(puSendCmd , sizeof(puSendCmd), data, 1, SLAVEID)<0) {*/ + char puSendCmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + + kdSetI2CSpeed(EEPROM_I2C_SPEED); + + if (iReadRegI2C(puSendCmd , 2, data, 1, SLAVEID) < 0) { + CAM_CALERR("[CAM_CAL2] fail ov8858_byteread_cmos_sensor addr =0x%x, data = 0x%x", addr, *data); + return false; + } + /*CAM_CALDB("selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", addr, + *data,page,offset);*/ + CAM_CALDB("[CAM_CAL2] ov8858_cmos_sensor addr =0x%x, data = 0x%x", addr, *data); + return true; + +} + + +static int selective_read_region(u32 addr, u8 *data, u16 i2c_id, u32 size) +{ + /*u32 page = addr/PAGE_SIZE; // size of page was 256 */ + /*u32 offset = addr%PAGE_SIZE;*/ + unsigned short curAddr = (unsigned short)addr; + u8 *buff = data; + u32 size_to_read = size; + /*kdSetI2CSpeed(EEPROM_I2C_SPEED);*/ + int ret = 0; + + CAM_CALDB("Before byteread_cmos_sensor curAddr =%x count=%d buffData=%x\n", curAddr, + size - size_to_read, *buff); + while (size_to_read > 0) { + /*if(selective_read_byte(addr,(u8*)buff,OV8858_DEVICE_ID)){*/ + if (byteread_cmos_sensor(0xA2, curAddr, buff)) { + CAM_CALDB("after byteread_cmos_sensor curAddr =%x count=%d buffData=%x\n", curAddr, + size - size_to_read, *buff); + curAddr += 1; + buff += 1; + size_to_read -= 1; + ret += 1; + } else { + break; + + } +#if 0 + if (size_to_read > BUFF_SIZE) { + CAM_CALDB("offset =%x size %d\n", offset, BUFF_SIZE); + if (iReadRegI2C(&offset, 1, (u8 *)buff, BUFF_SIZE, i2c_id + (page << 1)) < 0) + break; + ret += BUFF_SIZE; + buff += BUFF_SIZE; + offset += BUFF_SIZE; + size_to_read -= BUFF_SIZE; + page += offset / PAGE_SIZE_; + + } else { + CAM_CALDB("offset =%x size %d\n", offset, size_to_read); + if (iReadRegI2C(&offset, 1, (u8 *)buff, (u16) size_to_read, i2c_id + (page << 1)) < 0) + break; + ret += size_to_read; + size_to_read = 0; + } +#endif + } + CAM_CALDB("selective_read_region addr =%x size %d readSize = %d\n", addr, size, ret); + return ret; +} + + +/* Burst Write Data */ +static int iWriteData(unsigned int ui4_offset, unsigned int ui4_length, +unsigned char *pinputdata) +{ + CAM_CALDB("[CAM_CAL2] not implemented!"); + return 0; +} + + + + +#ifdef CONFIG_COMPAT +static int compat_put_cal_info_struct( + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32, + stCAM_CAL_INFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data->u4Offset); + err |= put_user(i, &data32->u4Offset); + err |= get_user(i, &data->u4Length); + err |= put_user(i, &data32->u4Length); + /* Assume pointer is not change */ +#if 1 + err |= get_user(p, (compat_uptr_t *)&data->pu1Params); + err |= put_user(p, &data32->pu1Params); +#endif + return err; +} +static int compat_get_cal_info_struct( + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32, + stCAM_CAL_INFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data32->u4Offset); + err |= put_user(i, &data->u4Offset); + err |= get_user(i, &data32->u4Length); + err |= put_user(i, &data->u4Length); + err |= get_user(p, &data32->pu1Params); + err |= put_user(compat_ptr(p), &data->pu1Params); + + return err; +} + +static long ov8858_Ioctl_Compat(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32; + stCAM_CAL_INFO_STRUCT __user *data; + int err; + + CAM_CALDB("[CAMERA SENSOR] ov8858_Ioctl_Compat,%p %p %x ioc size %d\n", filp->f_op , + filp->f_op->unlocked_ioctl, cmd, _IOC_SIZE(cmd)); + + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + + case COMPAT_CAM_CALIOC_G_READ: { + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_cal_info_struct(data32, data); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, CAM_CALIOC_G_READ, + (unsigned long)data); + err = compat_put_cal_info_struct(data32, data); + + + if (err != 0) + CAM_CALERR("[CAM_CAL2] compat_put_acdk_sensor_getinfo_struct failed\n"); + return ret; + } + default: + return -ENOIOCTLCMD; + } +} + + +#endif + + +/******************************************************************************* +* +********************************************************************************/ +#define NEW_UNLOCK_IOCTL +#ifndef NEW_UNLOCK_IOCTL +static int CAM_CAL_Ioctl(struct inode *a_pstInode, + struct file *a_pstFile, + unsigned int a_u4Command, + unsigned long a_u4Param) +#else +static long CAM_CAL_Ioctl( + struct file *file, + unsigned int a_u4Command, + unsigned long a_u4Param +) +#endif +{ + int i4RetValue = 0; + u8 *pBuff = NULL; + u8 *pu1Params = NULL; + stCAM_CAL_INFO_STRUCT *ptempbuf = NULL;/*LukeHu++160201=Fix Code Defect.*/ + + CAM_CALDB("[CAM_CAL2] ioctl\n"); + +#ifdef CAM_CALGETDLT_DEBUG + struct timeval ktv1, ktv2; + unsigned long TimeIntervalUS; +#endif + + /*if (_IOC_NONE == _IOC_DIR(a_u4Command)) { + } else {*/ + if (_IOC_NONE != _IOC_DIR(a_u4Command)) { + pBuff = kmalloc(sizeof(stCAM_CAL_INFO_STRUCT), GFP_KERNEL); + + if (NULL == pBuff) { + CAM_CALDB(" ioctl allocate mem failed\n"); + return -ENOMEM; + } + + if (_IOC_WRITE & _IOC_DIR(a_u4Command)) { + if (copy_from_user((u8 *) pBuff , (u8 *) a_u4Param, sizeof(stCAM_CAL_INFO_STRUCT))) { + /*get input structure address*/ + kfree(pBuff); + CAM_CALDB("[CAM_CAL2] ioctl copy from user failed\n"); + return -EFAULT; + } + } + } + + ptempbuf = (stCAM_CAL_INFO_STRUCT *)pBuff; + if (NULL == pBuff) /* Dream add for non-null at 2016.02.29 */ + return -ENOMEM; + if (ptempbuf->u4Length <= 0 || ptempbuf->u4Length > 65535) { + kfree(pBuff); + CAM_CALDB("ptempbuf->u4Length range is failed\n"); + return -ENOMEM; + } + pu1Params = kmalloc(ptempbuf->u4Length, GFP_KERNEL); + if (NULL == pu1Params) { + kfree(pBuff); + CAM_CALDB("[CAM_CAL2] ioctl allocate mem failed\n"); + return -ENOMEM; + } + CAM_CALDB(" init Working buffer address 0x%p command is 0x%x\n", pu1Params, a_u4Command); + + if (ptempbuf->u4Length > 65535) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("ptempbuf->u4Length is large\n"); + return -EFAULT; + } + + if (copy_from_user((u8 *)pu1Params, (u8 *)ptempbuf->pu1Params, ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[CAM_CAL2] ioctl copy from user failed\n"); + return -EFAULT; + } + + switch (a_u4Command) { + case CAM_CALIOC_S_WRITE: + CAM_CALDB("[CAM_CAL2] Write CMD\n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + i4RetValue = iWriteData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pu1Params); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + CAM_CALDB("Write data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + break; + case CAM_CALIOC_G_READ: + CAM_CALDB("[CAM_CAL2] Read CMD\n"); + +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + CAM_CALDB("[CAM_CAL2] offset %d\n", ptempbuf->u4Offset); + CAM_CALDB("[CAM_CAL2] length %d\n", ptempbuf->u4Length); + /**pu1Params = 0;*/ + i4RetValue = selective_read_region(ptempbuf->u4Offset, pu1Params, OV8858_DEVICE_ID, ptempbuf->u4Length); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + CAM_CALDB("Read data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + + break; + default: + CAM_CALDB("[CAM_CAL2] No CMD\n"); + i4RetValue = -EPERM; + break; + } + if (_IOC_READ & _IOC_DIR(a_u4Command)) { + /*copy data to user space buffer, keep other input paremeter unchange.*/ + CAM_CALDB("[CAM_CAL2] to user length %d\n", ptempbuf->u4Length); + if (ptempbuf->u4Length > 65535) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("ptempbuf->u4Length is large!\n"); + return -EFAULT; + } + + if (copy_to_user((u8 __user *) ptempbuf->pu1Params , (u8 *)pu1Params , ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[CAM_CAL2] ioctl copy to user failed\n"); + return -EFAULT; + } + } + + kfree(pBuff); + kfree(pu1Params); + return i4RetValue; +} + + +static u32 g_u4Opened; +/*#define +//Main jobs: +// 1.check for device-specified errors, device not ready. +// 2.Initialize the device if it is opened for the first time.*/ +static int CAM_CAL_Open(struct inode *a_pstInode, struct file *a_pstFile) +{ + CAM_CALDB("[CAM_CAL2] CAM_CAL_Open\n"); + spin_lock(&g_CAM_CALLock); + if (g_u4Opened) { + spin_unlock(&g_CAM_CALLock); + CAM_CALDB("[CAM_CAL2] Opened, return -EBUSY\n"); + return -EBUSY; + } else { + g_u4Opened = 1; + atomic_set(&g_CAM_CALatomic, 0); + } + spin_unlock(&g_CAM_CALLock); + mdelay(2); + return 0; +} + +/*Main jobs: +// 1.Deallocate anything that "open" allocated in private_data. +// 2.Shut down the device on last close. +// 3.Only called once on last time. +// Q1 : Try release multiple times.*/ +static int CAM_CAL_Release(struct inode *a_pstInode, struct file *a_pstFile) +{ + spin_lock(&g_CAM_CALLock); + + g_u4Opened = 0; + + atomic_set(&g_CAM_CALatomic, 0); + + spin_unlock(&g_CAM_CALLock); + + return 0; +} + +static const struct file_operations g_stCAM_CAL_fops = { + .owner = THIS_MODULE, + .open = CAM_CAL_Open, + .release = CAM_CAL_Release, + /*.ioctl = CAM_CAL_Ioctl*/ +#ifdef CONFIG_COMPAT + .compat_ioctl = ov8858_Ioctl_Compat, +#endif + .unlocked_ioctl = CAM_CAL_Ioctl +}; + +#define CAM_CAL_DYNAMIC_ALLOCATE_DEVNO 1 +static inline int RegisterCAM_CALCharDrv(void) +{ + struct device *CAM_CAL_device = NULL; + + CAM_CALDB("[CAM_CAL2] RegisterCAM_CALCharDrv Start\n"); + +#if CAM_CAL_DYNAMIC_ALLOCATE_DEVNO + if (alloc_chrdev_region(&g_CAM_CALdevno, 0, 1, CAM_CAL_DRVNAME)) { + CAM_CALDB("[CAM_CAL2] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if (register_chrdev_region(g_CAM_CALdevno , 1 , CAM_CAL_DRVNAME)) { + CAM_CALDB("[CAM_CAL2] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + /*Allocate driver*/ + g_pCAM_CAL_CharDrv = cdev_alloc(); + + if (NULL == g_pCAM_CAL_CharDrv) { + unregister_chrdev_region(g_CAM_CALdevno, 1); + + CAM_CALDB("[CAM_CAL2] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + /*Attatch file operation.*/ + cdev_init(g_pCAM_CAL_CharDrv, &g_stCAM_CAL_fops); + + g_pCAM_CAL_CharDrv->owner = THIS_MODULE; + + /*Add to system*/ + if (cdev_add(g_pCAM_CAL_CharDrv, g_CAM_CALdevno, 1)) { + CAM_CALDB("[CAM_CAL2] Attatch file operation failed\n"); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + return -EAGAIN; + } + + CAM_CAL_class = class_create(THIS_MODULE, "CAM_CALdrv2"); + if (IS_ERR(CAM_CAL_class)) { + int ret = PTR_ERR(CAM_CAL_class); + + CAM_CALDB("[CAM_CAL2] Unable to create class, err = %d\n", ret); + return ret; + } + CAM_CAL_device = device_create(CAM_CAL_class, NULL, g_CAM_CALdevno, NULL, CAM_CAL_DRVNAME); + CAM_CALDB("[CAM_CAL2] RegisterCAM_CALCharDrv End\n"); + + return 0; +} + +static inline void UnregisterCAM_CALCharDrv(void) +{ + /*Release char driver*/ + cdev_del(g_pCAM_CAL_CharDrv); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + device_destroy(CAM_CAL_class, g_CAM_CALdevno); + class_destroy(CAM_CAL_class); +} + + +/* //////////////////////////////////////////////////////////////////// */ +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); +#elif 0 +static int CAM_CAL_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); +#else +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int CAM_CAL_i2c_remove(struct i2c_client *); + +static const struct i2c_device_id CAM_CAL_i2c_id[] = {{CAM_CAL_DRVNAME, 0}, {} }; + + + +static struct i2c_driver CAM_CAL_i2c_driver = { + .probe = CAM_CAL_i2c_probe, + .remove = CAM_CAL_i2c_remove, + /* .detect = CAM_CAL_i2c_detect,*/ + .driver.name = CAM_CAL_DRVNAME, + .id_table = CAM_CAL_i2c_id, +}; + +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) +{ + strcpy(info->type, CAM_CAL_DRVNAME); + return 0; +} +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i4RetValue = 0; + + CAM_CALDB("[CAM_CAL2] CAM_CAL_i2c_probe Start!\n"); + /* spin_lock_init(&g_CAM_CALLock);*/ + + /*get sensor i2c client*/ + spin_lock(&g_CAM_CALLock); /*for SMP*/ + g_pstI2Cclient = client; + g_pstI2Cclient->addr = OV8858_DEVICE_ID >> 1; + spin_unlock(&g_CAM_CALLock); /* for SMP*/ + + CAM_CALDB("[CAM_CAL2] g_pstI2Cclient->addr = 0x%x\n", g_pstI2Cclient->addr); + /*Register char driver*/ + i4RetValue = RegisterCAM_CALCharDrv(); + + if (i4RetValue) { + CAM_CALDB("[CAM_CAL2] register char device failed!\n"); + return i4RetValue; + } + + CAM_CALDB("[CAM_CAL2] CAM_CAL_i2c_probe End!\n"); + return 0; +} + +static int CAM_CAL_i2c_remove(struct i2c_client *client) +{ + return 0; +} + +static int CAM_CAL_probe(struct platform_device *pdev) +{ + CAM_CALDB("[CAM_CAL2] CAM_CAL_probe start!\n"); + return i2c_add_driver(&CAM_CAL_i2c_driver); +} + +static int CAM_CAL_remove(struct platform_device *pdev) +{ + i2c_del_driver(&CAM_CAL_i2c_driver); + return 0; +} + +/*platform structure*/ +static struct platform_driver g_stCAM_CAL_Driver = { + .probe = CAM_CAL_probe, + .remove = CAM_CAL_remove, + .driver = { + .name = CAM_CAL_DRVNAME, + .owner = THIS_MODULE, + } +}; + + +static struct platform_device g_stCAM_CAL_Device = { + .name = CAM_CAL_DRVNAME, + .id = 0, + .dev = { + } +}; + +static int __init CAM_CAL2_i2C_init(void) +{ + CAM_CALDB("[CAM_CAL2] CAM_CAL2_i2C_init Start!\n"); + i2c_register_board_info(CAM_CAL_I2C_BUSNUM, &kd_cam_cal_dev, 1); + if (platform_driver_register(&g_stCAM_CAL_Driver)) { + CAM_CALDB("[CAM_CAL] failed to register CAM_CAL driver\n"); + return -ENODEV; + } + + if (platform_device_register(&g_stCAM_CAL_Device)) { + CAM_CALDB("[CAM_CAL2] failed to register CAM_CAL driver, 2nd time\n"); + return -ENODEV; + } + CAM_CALDB("[CAM_CAL2] CAM_CAL2_i2C_init End!\n"); + return 0; +} + +static void __exit CAM_CAL2_i2C_exit(void) +{ + platform_driver_unregister(&g_stCAM_CAL_Driver); +} + +module_init(CAM_CAL2_i2C_init); +module_exit(CAM_CAL2_i2C_exit); + +MODULE_DESCRIPTION("ov8858 CAM_CAL2 driver"); +MODULE_AUTHOR("DreamYeh "); diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/ov8858_eeprom.h b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/ov8858_eeprom.h new file mode 100644 index 0000000000000000000000000000000000000000..9b0a43437492f5b43e57857e383a93d614c24d0d --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/ov8858_eeprom/ov8858_eeprom.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef __OV8858_EEPROM_H +#define __OV8858_EEPROM_H + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, +u16 a_sizeRecvData, u16 i2cId); + +#endif /* __CAM_CAL_H */ + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/Makefile b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f92e928b29f3ad2aa4012c8c0eb0bc0caafde91d --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/Makefile @@ -0,0 +1,4 @@ +$(info add s5k2p8_eeprom.o) +obj-y += s5k2p8_eeprom.o + + diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/s5k2p8_eeprom.c b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/s5k2p8_eeprom.c new file mode 100644 index 0000000000000000000000000000000000000000..44a5b46fce0e71d65c3075f2e65530b12d5f74a4 --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/s5k2p8_eeprom.c @@ -0,0 +1,665 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/* + * Driver for CAM_CAL + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_hw.h" +#include "cam_cal.h" +#include "cam_cal_define.h" +#include "s5k2p8_eeprom.h" +/*#include // for SM*/ +#include +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + + +/*#define CAM_CALGETDLT_DEBUG*/ +/*#define CAM_CAL_DEBUG*/ +#ifdef CAM_CAL_DEBUG +#include +#include + +#define PFX "s5k2p8_eeprom" +/*pr_err("[%s] " fmt, __FUNCTION__, ##arg)*/ + +#define CAM_CALINF(format, args...) pr_info(PFX "[%s] " format, __func__, ##args) +#define CAM_CALDB(format, args...) pr_debug(PFX "[%s] " format, __func__, ##args) +#define CAM_CALERR(format, args...) printk(KERN_ERR format, ##args) +#else +#define CAM_CALINF(x, ...) +#define CAM_CALDB(x, ...) +#define CAM_CALERR(x, ...) +#endif + +#define PAGE_SIZE_ 32 +#define BUFF_SIZE 8 + +static DEFINE_SPINLOCK(g_CAM_CALLock); /* for SMP*/ +#define CAM_CAL_I2C_BUSNUM 2 + +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_ICS_REVISION 1 /*seanlin111208*/ +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_DRVNAME "CAM_CAL_DRV1" +#define CAM_CAL_I2C_GROUP_ID 0 +#define CAM_CAL_DEV_MAJOR_NUMBER 226 + +/* CAM_CAL READ/WRITE ID */ +#define S5K2P8_DEVICE_ID 0xA2 + +/******************************************************************************* +* +********************************************************************************/ +static struct i2c_board_info kd_cam_cal_dev __initdata = { I2C_BOARD_INFO(CAM_CAL_DRVNAME, 0xA2 >> 1)}; + +static struct i2c_client *g_pstI2Cclient; + +/*81 is used for V4L driver*/ +static dev_t g_CAM_CALdevno = MKDEV(CAM_CAL_DEV_MAJOR_NUMBER, 0); +static struct cdev *g_pCAM_CAL_CharDrv; +/*static spinlock_t g_CAM_CALLock;*/ +/*spin_lock(&g_CAM_CALLock);*/ +/*spin_unlock(&g_CAM_CALLock);*/ + +static struct class *CAM_CAL_class; +static atomic_t g_CAM_CALatomic; +/*static DEFINE_SPINLOCK(kdcam_cal_drv_lock);*/ +/*spin_lock(&kdcam_cal_drv_lock);*/ +/*spin_unlock(&kdcam_cal_drv_lock);*/ + +static int selective_read_region(u32 addr, u8 *data, u16 i2c_id, u32 size); + + +#define EEPROM_I2C_SPEED 100 +/*#define LSCOTPDATASIZE 0x03c4 //964*/ +/*static kal_uint8 lscotpdata[LSCOTPDATASIZE];*/ + +static void kdSetI2CSpeed(u32 i2cSpeed) +{ + spin_lock(&g_CAM_CALLock); + g_pstI2Cclient->timing = i2cSpeed; + spin_unlock(&g_CAM_CALLock); + +} + +/******************************************************************************* +* iWriteReg +********************************************************************************/ + +static bool byteread_cmos_sensor(unsigned char SLAVEID, unsigned short addr, unsigned char *data) +{ + /* To call your IIC function here*/ + /*char puSendCmd[1] = {(char)(addr & 0xFF) };*/ + /*if(iReadRegI2C(puSendCmd , sizeof(puSendCmd), data, 1, SLAVEID)<0) {*/ + char puSendCmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + + kdSetI2CSpeed(EEPROM_I2C_SPEED); + if (iReadRegI2C(puSendCmd , 2, data, 1, SLAVEID) < 0) { + CAM_CALERR("[CAM_CAL] fail s5k2p8_byteread_cmos_sensor addr =0x%x, data = 0x%x", addr, *data); + return false; + } + /*CAM_CALDB("selective_read_byte addr =0x%x data = 0x%x,page %d, offset 0x%x", addr, + *data,page,offset);*/ + CAM_CALDB("[CAM_CAL] s5k2p8_cmos_sensor addr =0x%x, data = 0x%x", addr, *data); + return true; + +} + +static int selective_read_region(u32 addr, u8 *data, u16 i2c_id, u32 size) +{ + /*u32 page = addr/PAGE_SIZE;//size of page was 256 */ + /*u32 offset = addr%PAGE_SIZE;*/ + unsigned short curAddr = (unsigned short)addr; + u8 *buff = data; + u32 size_to_read = size; + /*kdSetI2CSpeed(EEPROM_I2C_SPEED);*/ + int ret = 0; + + CAM_CALDB("Before byteread_cmos_sensor curAddr =%x count=%d buffData=%x\n", curAddr, + size - size_to_read, *buff); + while (size_to_read > 0) { + /*if(selective_read_byte(addr,(u8*)buff,S5K2P8_DEVICE_ID)){*/ + if (byteread_cmos_sensor(0xA2, curAddr, buff)) { + CAM_CALDB("after byteread_cmos_sensor curAddr =%x count=%d buffData=%x\n", curAddr, + size - size_to_read, *buff); + curAddr += 1; + buff += 1; + size_to_read -= 1; + ret += 1; + } else { + break; + + } +#if 0 + if (size_to_read > BUFF_SIZE) { + CAM_CALDB("offset =%x size %d\n", offset, BUFF_SIZE); + if (iReadRegI2C(&offset, 1, (u8 *)buff, BUFF_SIZE, i2c_id + (page << 1)) < 0) + break; + ret += BUFF_SIZE; + buff += BUFF_SIZE; + offset += BUFF_SIZE; + size_to_read -= BUFF_SIZE; + page += offset / PAGE_SIZE_; + + } else { + CAM_CALDB("offset =%x size %d\n", offset, size_to_read); + if (iReadRegI2C(&offset, 1, (u8 *)buff, (u16) size_to_read, i2c_id + (page << 1)) < 0) + break; + ret += size_to_read; + size_to_read = 0; + } +#endif + } + CAM_CALDB("selective_read_region addr =%x size %d readSize = %d\n", addr, size, ret); + return ret; +} + + +/* Burst Write Data */ +static int iWriteData(unsigned int ui4_offset, unsigned int ui4_length, +unsigned char *pinputdata) +{ + CAM_CALDB("[CAM_CAL] not implemented!"); + return 0; +} + + + + +#ifdef CONFIG_COMPAT +static int compat_put_cal_info_struct( + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32, + stCAM_CAL_INFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data->u4Offset); + err |= put_user(i, &data32->u4Offset); + err |= get_user(i, &data->u4Length); + err |= put_user(i, &data32->u4Length); + /* Assume pointer is not change */ +#if 1 + err |= get_user(p, (compat_uptr_t *)&data->pu1Params); + err |= put_user(p, &data32->pu1Params); +#endif + return err; +} +static int compat_get_cal_info_struct( + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32, + stCAM_CAL_INFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data32->u4Offset); + err |= put_user(i, &data->u4Offset); + err |= get_user(i, &data32->u4Length); + err |= put_user(i, &data->u4Length); + err |= get_user(p, &data32->pu1Params); + err |= put_user(compat_ptr(p), &data->pu1Params); + + return err; +} + +static long s5k2p8_Ioctl_Compat(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + COMPAT_stCAM_CAL_INFO_STRUCT __user *data32; + stCAM_CAL_INFO_STRUCT __user *data; + int err; + + CAM_CALDB("[CAMERA SENSOR] s5k2p8_Ioctl_Compat,%p %p %x ioc size %d\n", filp->f_op , + filp->f_op->unlocked_ioctl, cmd, _IOC_SIZE(cmd)); + + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + + case COMPAT_CAM_CALIOC_G_READ: { + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_cal_info_struct(data32, data); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, CAM_CALIOC_G_READ, + (unsigned long)data); + err = compat_put_cal_info_struct(data32, data); + + + if (err != 0) + CAM_CALERR("[CAM_CAL] compat_put_acdk_sensor_getinfo_struct failed\n"); + return ret; + } + default: + return -ENOIOCTLCMD; + } +} + + +#endif + + +/******************************************************************************* +* +********************************************************************************/ +#define NEW_UNLOCK_IOCTL +#ifndef NEW_UNLOCK_IOCTL +static int CAM_CAL_Ioctl(struct inode *a_pstInode, + struct file *a_pstFile, + unsigned int a_u4Command, + unsigned long a_u4Param) +#else +static long CAM_CAL_Ioctl( + struct file *file, + unsigned int a_u4Command, + unsigned long a_u4Param +) +#endif +{ + int i4RetValue = 0; + u8 *pBuff = NULL; + u8 *pu1Params = NULL; + stCAM_CAL_INFO_STRUCT *ptempbuf = NULL;/*LukeHu++160201=Fix Code Defect.*/ + + CAM_CALDB("[CAM_CAL] ioctl\n"); + +#ifdef CAM_CALGETDLT_DEBUG + struct timeval ktv1, ktv2; + unsigned long TimeIntervalUS; +#endif + + /*if (_IOC_NONE == _IOC_DIR(a_u4Command)) { + } else {*/ + if (_IOC_NONE != _IOC_DIR(a_u4Command)) { + pBuff = kmalloc(sizeof(stCAM_CAL_INFO_STRUCT), GFP_KERNEL); + + if (NULL == pBuff) { + CAM_CALDB(" ioctl allocate mem failed\n"); + return -ENOMEM; + } + + if (_IOC_WRITE & _IOC_DIR(a_u4Command)) { + if (copy_from_user((u8 *) pBuff , (u8 *) a_u4Param, sizeof(stCAM_CAL_INFO_STRUCT))) { + /*get input structure address*/ + kfree(pBuff); + CAM_CALDB("[CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + } + } + + ptempbuf = (stCAM_CAL_INFO_STRUCT *)pBuff; + if(NULL == pBuff) + return -ENOMEM; + else + pu1Params = kmalloc(ptempbuf->u4Length, GFP_KERNEL); + if (NULL == pu1Params) { + kfree(pBuff); + CAM_CALDB("[CAM_CAL] ioctl allocate mem failed\n"); + return -ENOMEM; + } + CAM_CALDB(" init Working buffer address 0x%p command is 0x%x\n", pu1Params, a_u4Command); + + if (ptempbuf->u4Length > 65535) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[CAM_CAL] ptempbuf->u4Length=%d is so large!\n", ptempbuf->u4Length); + return -EFAULT; + } + + if (copy_from_user((u8 *)pu1Params, (u8 *)ptempbuf->pu1Params, ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + + switch (a_u4Command) { + case CAM_CALIOC_S_WRITE: + CAM_CALDB("[CAM_CAL] Write CMD\n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + i4RetValue = iWriteData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pu1Params); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + CAM_CALDB("Write data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + break; + case CAM_CALIOC_G_READ: + CAM_CALDB("[CAM_CAL] Read CMD\n"); + +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + /*CAM_CALDB("[CAM_CAL] offset %d\n", ptempbuf->u4Offset);70681*/ + CAM_CALDB("[CAM_CAL] length %d\n", ptempbuf->u4Length); + /**pu1Params = 0;*/ + i4RetValue = selective_read_region(ptempbuf->u4Offset, pu1Params, S5K2P8_DEVICE_ID, ptempbuf->u4Length); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if (ktv2.tv_sec > ktv1.tv_sec) + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + else + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + + CAM_CALDB("Read data %d bytes take %lu us\n", ptempbuf->u4Length, TimeIntervalUS); +#endif + + break; + default: + CAM_CALDB("[CAM_CAL] No CMD\n"); + i4RetValue = -EPERM; + break; + } + + if (_IOC_READ & _IOC_DIR(a_u4Command)) { + /*copy data to user space buffer, keep other input paremeter unchange.*/ + CAM_CALDB("[CAM_CAL] to user length %d\n", ptempbuf->u4Length); + CAM_CALDB("[CAM_CAL] to user Working buffer address 0x%p\n", pu1Params); + + if (ptempbuf->u4Length > 65535) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[CAM_CAL] ptempbuf->u4Length is so large\n"); + return -EFAULT; + } + + if (copy_to_user((u8 __user *) ptempbuf->pu1Params , (u8 *)pu1Params , ptempbuf->u4Length)) { + kfree(pBuff); + kfree(pu1Params); + CAM_CALDB("[CAM_CAL] ioctl copy to user failed\n"); + return -EFAULT; + } + } + + kfree(pBuff); + kfree(pu1Params); + return i4RetValue; +} + + +static u32 g_u4Opened; +/*#define +//Main jobs: +// 1.check for device-specified errors, device not ready. +// 2.Initialize the device if it is opened for the first time.*/ +static int CAM_CAL_Open(struct inode *a_pstInode, struct file *a_pstFile) +{ + CAM_CALDB("[CAM_CAL] CAM_CAL_Open\n"); + spin_lock(&g_CAM_CALLock); + if (g_u4Opened) { + spin_unlock(&g_CAM_CALLock); + CAM_CALDB("[CAM_CAL] Opened, return -EBUSY\n"); + return -EBUSY; + } else { + g_u4Opened = 1; + atomic_set(&g_CAM_CALatomic, 0); + } + spin_unlock(&g_CAM_CALLock); + mdelay(2); + return 0; +} + +/*Main jobs: +// 1.Deallocate anything that "open" allocated in private_data. +// 2.Shut down the device on last close. +// 3.Only called once on last time. +// Q1 : Try release multiple times.*/ +static int CAM_CAL_Release(struct inode *a_pstInode, struct file *a_pstFile) +{ + spin_lock(&g_CAM_CALLock); + + g_u4Opened = 0; + + atomic_set(&g_CAM_CALatomic, 0); + + spin_unlock(&g_CAM_CALLock); + + return 0; +} + +static const struct file_operations g_stCAM_CAL_fops = { + .owner = THIS_MODULE, + .open = CAM_CAL_Open, + .release = CAM_CAL_Release, + /*.ioctl = CAM_CAL_Ioctl*/ +#ifdef CONFIG_COMPAT + .compat_ioctl = s5k2p8_Ioctl_Compat, +#endif + .unlocked_ioctl = CAM_CAL_Ioctl +}; + +#define CAM_CAL_DYNAMIC_ALLOCATE_DEVNO 1 +static inline int RegisterCAM_CALCharDrv(void) +{ + struct device *CAM_CAL_device = NULL; + + CAM_CALDB("[CAM_CAL] RegisterCAM_CALCharDrv Start\n"); + +#if CAM_CAL_DYNAMIC_ALLOCATE_DEVNO + if (alloc_chrdev_region(&g_CAM_CALdevno, 0, 1, CAM_CAL_DRVNAME)) { + CAM_CALDB("[CAM_CAL] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if (register_chrdev_region(g_CAM_CALdevno , 1 , CAM_CAL_DRVNAME)) { + CAM_CALDB("[CAM_CAL] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + /*Allocate driver*/ + g_pCAM_CAL_CharDrv = cdev_alloc(); + + if (NULL == g_pCAM_CAL_CharDrv) { + unregister_chrdev_region(g_CAM_CALdevno, 1); + + CAM_CALDB("[CAM_CAL] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + /*Attatch file operation.*/ + cdev_init(g_pCAM_CAL_CharDrv, &g_stCAM_CAL_fops); + + g_pCAM_CAL_CharDrv->owner = THIS_MODULE; + + /*Add to system*/ + if (cdev_add(g_pCAM_CAL_CharDrv, g_CAM_CALdevno, 1)) { + CAM_CALDB("[CAM_CAL] Attatch file operation failed\n"); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + return -EAGAIN; + } + + CAM_CAL_class = class_create(THIS_MODULE, "CAM_CALdrv1"); + + if (IS_ERR(CAM_CAL_class)) { + int ret = PTR_ERR(CAM_CAL_class); + + CAM_CALDB("[CAM_CAL] Unable to create class, err = %d\n", ret); + return ret; + } + CAM_CAL_device = device_create(CAM_CAL_class, NULL, g_CAM_CALdevno, NULL, CAM_CAL_DRVNAME); + CAM_CALDB("[CAM_CAL] RegisterCAM_CALCharDrv End\n"); + + return 0; +} + +static inline void UnregisterCAM_CALCharDrv(void) +{ + /*Release char driver*/ + cdev_del(g_pCAM_CAL_CharDrv); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + device_destroy(CAM_CAL_class, g_CAM_CALdevno); + class_destroy(CAM_CAL_class); +} + + +/* //////////////////////////////////////////////////////////////////// */ +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); +#elif 0 +static int CAM_CAL_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); +#else +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int CAM_CAL_i2c_remove(struct i2c_client *); + +static const struct i2c_device_id CAM_CAL_i2c_id[] = {{CAM_CAL_DRVNAME, 0}, {} }; + + + +static struct i2c_driver CAM_CAL_i2c_driver = { + .probe = CAM_CAL_i2c_probe, + .remove = CAM_CAL_i2c_remove, + /* .detect = CAM_CAL_i2c_detect,*/ + .driver.name = CAM_CAL_DRVNAME, + .id_table = CAM_CAL_i2c_id, +}; + +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) +{ + strcpy(info->type, CAM_CAL_DRVNAME); + return 0; +} +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i4RetValue = 0; + + CAM_CALDB("[CAM_CAL] CAM_CAL_i2c_probe Start!\n"); + /* spin_lock_init(&g_CAM_CALLock);*/ + + /*get sensor i2c client*/ + spin_lock(&g_CAM_CALLock); /*for SMP*/ + g_pstI2Cclient = client; + g_pstI2Cclient->addr = S5K2P8_DEVICE_ID >> 1; + spin_unlock(&g_CAM_CALLock); /* for SMP*/ + + CAM_CALDB("[CAM_CAL] g_pstI2Cclient->addr = 0x%x\n", g_pstI2Cclient->addr); + /*Register char driver*/ + i4RetValue = RegisterCAM_CALCharDrv(); + + if (i4RetValue) { + CAM_CALDB("[CAM_CAL] register char device failed!\n"); + return i4RetValue; + } + + CAM_CALDB("[CAM_CAL] CAM_CAL_i2c_probe End!\n"); + return 0; +} + +static int CAM_CAL_i2c_remove(struct i2c_client *client) +{ + return 0; +} + +static int CAM_CAL_probe(struct platform_device *pdev) +{ + CAM_CALDB("[CAM_CAL] CAM_CAL_probe start!\n"); + return i2c_add_driver(&CAM_CAL_i2c_driver); +} + +static int CAM_CAL_remove(struct platform_device *pdev) +{ + i2c_del_driver(&CAM_CAL_i2c_driver); + return 0; +} + +/*platform structure*/ +static struct platform_driver g_stCAM_CAL_Driver = { + .probe = CAM_CAL_probe, + .remove = CAM_CAL_remove, + .driver = { + .name = CAM_CAL_DRVNAME, + .owner = THIS_MODULE, + } +}; + + +static struct platform_device g_stCAM_CAL_Device = { + .name = CAM_CAL_DRVNAME, + .id = 0, + .dev = { + } +}; + +static int __init CAM_CAL_i2C_init(void) +{ + CAM_CALDB("[CAM_CAL] CAM_CAL_i2C_init Start!\n"); + i2c_register_board_info(CAM_CAL_I2C_BUSNUM, &kd_cam_cal_dev, 1); + if (platform_driver_register(&g_stCAM_CAL_Driver)) { + CAM_CALDB("[CAM_CAL] failed to register CAM_CAL driver\n"); + return -ENODEV; + } + + if (platform_device_register(&g_stCAM_CAL_Device)) { + CAM_CALDB("[CAM_CAL] failed to register CAM_CAL driver, 2nd time\n"); + return -ENODEV; + } + CAM_CALDB("[CAM_CAL] CAM_CAL_i2C_init End!\n"); + return 0; +} + +static void __exit CAM_CAL_i2C_exit(void) +{ + platform_driver_unregister(&g_stCAM_CAL_Driver); +} + +module_init(CAM_CAL_i2C_init); +module_exit(CAM_CAL_i2C_exit); + +MODULE_DESCRIPTION("S5K2P8 CAM_CAL driver"); +MODULE_AUTHOR("DreamYeh "); diff --git a/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/s5k2p8_eeprom.h b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/s5k2p8_eeprom.h new file mode 100644 index 0000000000000000000000000000000000000000..886fcde171387d3521dfc55d5b948e51afdf310d --- /dev/null +++ b/drivers/misc/mediatek/cam_cal/src/legacy/mt6755/s5k2p8_eeprom/s5k2p8_eeprom.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +#ifndef __S5K2P8_EEPROM_H +#define __S5K2P8_EEPROM_H + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, +u16 a_sizeRecvData, u16 i2cId); + + +#endif /* __CAM_CAL_H */ + diff --git a/drivers/misc/mediatek/cameraisp/src/mt6755/Makefile b/drivers/misc/mediatek/cameraisp/src/mt6755/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..262bfc94e97ed68b7e0c924863ea0f8b08f1f4df --- /dev/null +++ b/drivers/misc/mediatek/cameraisp/src/mt6755/Makefile @@ -0,0 +1,36 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +# +# Makefile for misc devices that really don't fit anywhere else. +# + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/m4u/$(MTK_PLATFORM)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/cmdq/v2/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/cmdq/v2/$(MTK_PLATFORM)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/smi/ + +ifneq ($(CONFIG_ARM64), y) +# For arm32 + obj-y += camera_isp.o + #obj-y += camera_sysram.o + obj-y += camera_fdvt.o + #obj-y += camera_eis.o +else +# For arm64 + obj-y += camera_isp.o + #obj-y += camera_sysram.o + obj-y += camera_fdvt.o + #obj-y += camera_eis.o +endif +$(info cameraisp drv by platform $(platform_drv)) diff --git a/drivers/misc/mediatek/cameraisp/src/mt6755/camera_fdvt.c b/drivers/misc/mediatek/cameraisp/src/mt6755/camera_fdvt.c new file mode 100755 index 0000000000000000000000000000000000000000..6ac453156fa6e5162975d8c6270751717352b3da --- /dev/null +++ b/drivers/misc/mediatek/cameraisp/src/mt6755/camera_fdvt.c @@ -0,0 +1,1137 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "inc/mt_typedefs.h" +#include "inc/camera_fdvt.h" + +#include + +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + +#ifndef CONFIG_MTK_CLKMGR +#include +#endif + +#ifdef CONFIG_MTK_CLKMGR +#include +#endif + + +#define FDVT_DEVNAME "camera-fdvt" + +/* +#define MT6573FDVT_DEBUG +#ifdef MT6573FDVT_DEBUG +#define LOG_DBG(fmt, arg...) printk( "[CAMERAFDVT] " fmt, ##arg) +#else +#define LOG_DBG(x,...) +#endif + +#define MT6573FDVT_PARM +#ifdef MT6573FDVT_PARM +#define LOG_DBG(fmt,arg...) printk("[CAMERAFDVT]" "%s() - " fmt, __FUNCTION__ ,##arg) +#else +#define LOG_DBG(fmt,arg...) +#endif +*/ + +#define LOG_VRB(format, args...) pr_debug("FDVT" "[%s] " format, __func__, ##args) +#define LOG_DBG(format, args...) pr_debug("FDVT" "[%s] " format, __func__, ##args) +#define LOG_INF(format, args...) pr_debug("FDVT" "[%s] " format, __func__, ##args) +/* pr_info has been forbidden after kernel standard */ +#define LOG_WRN(format, args...) pr_warn("FDVT" "[%s] WARNING: " format, __func__, ##args) +#define LOG_ERR(format, args...) pr_err("FDVT" "[%s, line%04d] ERROR: " format, __func__, __LINE__, ##args) +#define LOG_AST(format, args...) pr_err("FDVT" "[%s, line%04d] ASSERT: " format, __func__, __LINE__, ##args) + + +static dev_t FDVT_devno; +static struct cdev *FDVT_cdev; +static struct class *FDVT_class; +static wait_queue_head_t g_MT6573FDVTWQ; +static u32 g_u4MT6573FDVTIRQ = 0 , g_u4MT6573FDVTIRQMSK = 0x00000001; + +static u8 *pBuff; +static u8 *pread_buf; +static u32 buf_size = 1024; + +#define MT6573FDVT_DBUFFREGCNT 208 + +#define FDVT_WR32(data, addr) mt_reg_sync_writel(data, addr) + +typedef struct { + UINT32 u4Addr[MT6573FDVT_DBUFFREGCNT]; + UINT32 u4Data[MT6573FDVT_DBUFFREGCNT]; + UINT32 u4Counter; +} MT6573FDVTDBuffRegMap; + +#ifdef CONFIG_OF + +typedef enum { + FDVT_IRQ_IDX = 0, + FDVT_IRQ_IDX_NUM +} FDVT_IRQ_ENUM; + +typedef enum { + FDVT_BASE_ADDR = 0, + FDVT_BASEADDR_NUM +} FDVT_BASEADDR_ENUM; + +static unsigned long gFDVT_Irq[FDVT_IRQ_IDX_NUM]; +static unsigned long gFDVT_Reg[FDVT_BASEADDR_NUM]; + +/* static void __iomem *g_isp_base_dase; */ +/* static void __iomem *g_isp_inner_base_dase; */ +/* static void __iomem *g_imgsys_config_base_dase; */ + + +#define FDVT_ADDR (gFDVT_Reg[FDVT_BASE_ADDR]) + +#else +#define FDVT_ADDR FDVT_BASE +#endif + +static MT6573FDVTDBuffRegMap pMT6573FDVTRDBuff; +static MT6573FDVTDBuffRegMap pMT6573FDVTWRBuff; + +/* register map */ +#define FDVT_START (FDVT_ADDR+0x0) +#define FDVT_ENABLE (FDVT_ADDR+0x4) +#define FDVT_RS (FDVT_ADDR+0x8) +#define FDVT_RSCON_ADR (FDVT_ADDR+0xC) +#define FDVT_RGB2Y0 (FDVT_ADDR+0x10) +#define FDVT_RGB2Y1 (FDVT_ADDR+0x14) +#define FDVT_INVG0 (FDVT_ADDR+0x18) +#define FDVT_INVG1 (FDVT_ADDR+0x1C) +#define FDVT_INVG2 (FDVT_ADDR+0x20) +#define FD_FNUM_0 (FDVT_ADDR+0x24) +#define FD_FNUM_1 (FDVT_ADDR+0x28) +#define FD_FNUM_2 (FDVT_ADDR+0x2C) +#define FD_FNUM_3 (FDVT_ADDR+0x30) +#define VT_FNUM_0 (FDVT_ADDR+0x34) +#define VT_FNUM_1 (FDVT_ADDR+0x38) +#define VT_FNUM_2 (FDVT_ADDR+0x3C) +#define VT_FNUM_3 (FDVT_ADDR+0x40) +#define FE_FNUM_0 (FDVT_ADDR+0x44) +#define FE_FNUM_1 (FDVT_ADDR+0x48) +#define FE_FNUM_2 (FDVT_ADDR+0x4C) +#define FE_FNUM_3 (FDVT_ADDR+0x50) +#define LD_BADR_0 (FDVT_ADDR+0x54) +#define LD_BADR_1 (FDVT_ADDR+0x58) +#define LD_BADR_2 (FDVT_ADDR+0x5C) +#define LD_BADR_3 (FDVT_ADDR+0x60) +#define LD_BADR_4 (FDVT_ADDR+0x64) +#define LD_BADR_5 (FDVT_ADDR+0x68) +#define LD_BADR_6 (FDVT_ADDR+0x6C) +#define LD_BADR_7 (FDVT_ADDR+0x70) +#define FDVT_RMAP_0 (FDVT_ADDR+0x74) +#define FDVT_RMAP_1 (FDVT_ADDR+0x78) +#define FDVT_FD_SET (FDVT_ADDR+0x7C) +#define FDVT_FD_CON_BASE_ADR (FDVT_ADDR+0x80) +#define FDVT_GFD_SKIP (FDVT_ADDR+0x84) +#define FDVT_LFD (FDVT_ADDR+0x88) +#define FDVT_GFD_POSITION_0 (FDVT_ADDR+0x8C) +#define FDVT_GFD_POSITION_1 (FDVT_ADDR+0x90) +#define FDVT_GFD_DET0 (FDVT_ADDR+0x94) +#define FDVT_GFD_DET1 (FDVT_ADDR+0x98) +#define FDVT_FD_RLT_BASE_ADR (FDVT_ADDR+0x9C) + +#define LFD_CTRL_0 (FDVT_ADDR+0xA4) +#define LFD_TL_0 (FDVT_ADDR+0xA8) +#define LFD_BR_0 (FDVT_ADDR+0xAC) +#define LFD_CTRL_1 (FDVT_ADDR+0xB0) +#define LFD_TL_1 (FDVT_ADDR+0xB4) +#define LFD_BR_1 (FDVT_ADDR+0xB8) +#define LFD_CTRL_2 (FDVT_ADDR+0xBC) +#define LFD_TL_2 (FDVT_ADDR+0xC0) +#define LFD_BR_2 (FDVT_ADDR+0xC4) +#define LFD_CTRL_3 (FDVT_ADDR+0xC8) +#define LFD_TL_3 (FDVT_ADDR+0xCC) +#define LFD_BR_3 (FDVT_ADDR+0xD0) +#define LFD_CTRL_4 (FDVT_ADDR+0xD4) +#define LFD_TL_4 (FDVT_ADDR+0xD8) +#define LFD_BR_4 (FDVT_ADDR+0xDC) +#define LFD_CTRL_5 (FDVT_ADDR+0xE0) +#define LFD_TL_5 (FDVT_ADDR+0xE4) +#define LFD_BR_5 (FDVT_ADDR+0xE8) +#define LFD_CTRL_6 (FDVT_ADDR+0xEC) +#define LFD_TL_6 (FDVT_ADDR+0xF0) +#define LFD_BR_6 (FDVT_ADDR+0xF4) +#define LFD_CTRL_7 (FDVT_ADDR+0xF8) +#define LFD_TL_7 (FDVT_ADDR+0xFC) +#define LFD_BR_7 (FDVT_ADDR+0x100) +#define LFD_CTRL_8 (FDVT_ADDR+0x104) +#define LFD_TL_8 (FDVT_ADDR+0x108) +#define LFD_BR_8 (FDVT_ADDR+0x10C) +#define LFD_CTRL_9 (FDVT_ADDR+0x110) +#define LFD_TL_9 (FDVT_ADDR+0x114) +#define LFD_BR_9 (FDVT_ADDR+0x118) +#define LFD_CTRL_10 (FDVT_ADDR+0x11C) +#define LFD_TL_10 (FDVT_ADDR+0x120) +#define LFD_BR_10 (FDVT_ADDR+0x124) +#define LFD_CTRL_11 (FDVT_ADDR+0x128) +#define LFD_TL_11 (FDVT_ADDR+0x12C) +#define LFD_BR_11 (FDVT_ADDR+0x130) +#define LFD_CTRL_12 (FDVT_ADDR+0x134) +#define LFD_TL_12 (FDVT_ADDR+0x138) +#define LFD_BR_12 (FDVT_ADDR+0x13C) +#define LFD_CTRL_13 (FDVT_ADDR+0x140) +#define LFD_TL_13 (FDVT_ADDR+0x144) +#define LFD_BR_13 (FDVT_ADDR+0x148) +#define LFD_CTRL_14 (FDVT_ADDR+0x14C) +#define LFD_TL_14 (FDVT_ADDR+0x150) +#define LFD_BR_14 (FDVT_ADDR+0x154) +#define FDVT_RESULT (FDVT_ADDR+0x158) +#define FDVT_INT_EN (FDVT_ADDR+0x15C) +#define FDVT_SRC_WD_HT (FDVT_ADDR+0x160) +/* #define FDVT_SRC_IMG_BASE_ADDR (FDVT_ADDR+0x164) */ +#define FDVT_INT (FDVT_ADDR+0x168) +#define DEBUG_INFO_1 (FDVT_ADDR+0x16C) +#define DEBUG_INFO_2 (FDVT_ADDR+0x170) +#define DEBUG_INFO_3 (FDVT_ADDR+0x174) +#define FDVT_RESULTNUM (FDVT_ADDR+0x178) +#define FDVT_MAX_OFFSET 0x178 + +#ifdef CONFIG_OF +struct fdvt_device { + void __iomem *regs[FDVT_BASEADDR_NUM]; + struct device *dev; + int irq[FDVT_IRQ_IDX_NUM]; +#ifndef CONFIG_MTK_CLKMGR /* CCF */ + struct clk *clk_SCP_SYS_DIS; + struct clk *clk_SCP_SYS_ISP; + struct clk *clk_SMI_COMMON; + struct clk *clk_FD; +#endif +}; + +static struct fdvt_device *fdvt_devs; +static int nr_fdvt_devs; +#endif + +void FDVT_basic_config(void) +{ + FDVT_WR32(0x00000111, FDVT_ENABLE); + FDVT_WR32(0x0000040B, FDVT_RS); + FDVT_WR32(0x00000000, FDVT_RSCON_ADR); + FDVT_WR32(0x02590132, FDVT_RGB2Y0); + FDVT_WR32(0x00000075, FDVT_RGB2Y1); + FDVT_WR32(0x66553520, FDVT_INVG0); + FDVT_WR32(0xB8A28D79, FDVT_INVG1); + FDVT_WR32(0xFFF4E7CF, FDVT_INVG2); + FDVT_WR32(0x01D10203, FD_FNUM_0); + FDVT_WR32(0x02A10213, FD_FNUM_1); + FDVT_WR32(0x03F102B1, FD_FNUM_2); + FDVT_WR32(0x046103C1, FD_FNUM_3); + FDVT_WR32(0x01450168, VT_FNUM_0); + FDVT_WR32(0x01D70173, VT_FNUM_1); + FDVT_WR32(0x02C201E2, VT_FNUM_2); + FDVT_WR32(0x031002A0, VT_FNUM_3); + FDVT_WR32(0x00600060, FE_FNUM_0); + FDVT_WR32(0x00000000, FE_FNUM_1); + FDVT_WR32(0x00000000, FE_FNUM_2); + FDVT_WR32(0x00000000, FE_FNUM_3); + FDVT_WR32(0x00000000, LD_BADR_0); + FDVT_WR32(0x00000000, LD_BADR_1); + FDVT_WR32(0x00000000, LD_BADR_2); + FDVT_WR32(0x00000000, LD_BADR_3); + FDVT_WR32(0x00000000, LD_BADR_4); + FDVT_WR32(0x00000000, LD_BADR_5); + FDVT_WR32(0x00000000, LD_BADR_6); + FDVT_WR32(0x00000000, LD_BADR_7); + FDVT_WR32(0x3F000000, FDVT_RMAP_0); + FDVT_WR32(0x01230101, FDVT_RMAP_1); + FDVT_WR32(0x000F010B, FDVT_FD_SET); + FDVT_WR32(0x00000000, FDVT_FD_CON_BASE_ADR); + FDVT_WR32(0x00000011, FDVT_GFD_SKIP); + FDVT_WR32(0x01130000, FDVT_LFD); + FDVT_WR32(0x00000000, FDVT_GFD_POSITION_0); + FDVT_WR32(0x00F00140, FDVT_GFD_POSITION_1); + FDVT_WR32(0x00000001, FDVT_GFD_DET0); + FDVT_WR32(0x00000000, FDVT_GFD_DET1); + FDVT_WR32(0x00000000, FDVT_FD_RLT_BASE_ADR); + FDVT_WR32(0x00000000, LFD_CTRL_0); + FDVT_WR32(0x00000000, LFD_TL_0); + FDVT_WR32(0x00000000, LFD_BR_0); + FDVT_WR32(0x00000000, LFD_CTRL_1); + FDVT_WR32(0x00000000, LFD_TL_1); + FDVT_WR32(0x00000000, LFD_BR_1); + FDVT_WR32(0x00000000, LFD_CTRL_2); + FDVT_WR32(0x00000000, LFD_TL_2); + FDVT_WR32(0x00000000, LFD_BR_2); + FDVT_WR32(0x00000000, LFD_CTRL_3); + FDVT_WR32(0x00000000, LFD_TL_3); + FDVT_WR32(0x00000000, LFD_BR_3); + FDVT_WR32(0x00000000, LFD_CTRL_4); + FDVT_WR32(0x00000000, LFD_TL_4); + FDVT_WR32(0x00000000, LFD_BR_4); + FDVT_WR32(0x00000000, LFD_CTRL_5); + FDVT_WR32(0x00000000, LFD_TL_5); + FDVT_WR32(0x00000000, LFD_BR_5); + FDVT_WR32(0x00000000, LFD_CTRL_6); + FDVT_WR32(0x00000000, LFD_TL_6); + FDVT_WR32(0x00000000, LFD_BR_6); + FDVT_WR32(0x00000000, LFD_CTRL_7); + FDVT_WR32(0x00000000, LFD_TL_7); + FDVT_WR32(0x00000000, LFD_BR_7); + FDVT_WR32(0x00000000, LFD_CTRL_8); + FDVT_WR32(0x00000000, LFD_TL_8); + FDVT_WR32(0x00000000, LFD_BR_8); + FDVT_WR32(0x00000000, LFD_CTRL_9); + FDVT_WR32(0x00000000, LFD_TL_9); + FDVT_WR32(0x00000000, LFD_BR_9); + FDVT_WR32(0x00000000, LFD_CTRL_10); + FDVT_WR32(0x00000000, LFD_TL_10); + FDVT_WR32(0x00000000, LFD_BR_10); + FDVT_WR32(0x00000000, LFD_CTRL_11); + FDVT_WR32(0x00000000, LFD_TL_11); + FDVT_WR32(0x00000000, LFD_BR_11); + FDVT_WR32(0x00000000, LFD_CTRL_12); + FDVT_WR32(0x00000000, LFD_TL_12); + FDVT_WR32(0x00000000, LFD_BR_12); + FDVT_WR32(0x00000000, LFD_CTRL_13); + FDVT_WR32(0x00000000, LFD_TL_13); + FDVT_WR32(0x00000000, LFD_BR_13); + FDVT_WR32(0x00000000, LFD_CTRL_14); + FDVT_WR32(0x00000000, LFD_TL_14); + FDVT_WR32(0x00000000, LFD_BR_14); + FDVT_WR32(0x00000000, FDVT_INT_EN); + FDVT_WR32(0x014000F0, FDVT_SRC_WD_HT); +} + +/******************************************************************************* +// Clock to ms +********************************************************************************/ +static unsigned long ms_to_jiffies(unsigned long ms) +{ + return (ms * HZ + 512) >> 10; +} +/*=======================================================================*/ +/* MT6573FDVT Clock control Registers */ +/*=======================================================================*/ +static int mt_fdvt_clk_ctrl(int en) +{ + UINT32 err = 0; +#ifdef CONFIG_MTK_CLKMGR + if (en) { + enable_clock(MT_CG_DISP0_SMI_COMMON, "CAMERA"); + enable_clock(MT_CG_IMAGE_FD, "FDVT"); + } else { + disable_clock(MT_CG_IMAGE_FD, "FDVT"); + disable_clock(MT_CG_DISP0_SMI_COMMON, "CAMERA"); + } +#else + if (en) { + err = clk_prepare_enable(fdvt_devs->clk_SCP_SYS_DIS); + if (err) + LOG_ERR("clk_prepare_enable(clk_SCP_SYS_DIS) FAIL! ERR CODE: %x\n", err); + err = clk_prepare_enable(fdvt_devs->clk_SMI_COMMON); + if (err) + LOG_ERR("clk_prepare_enable(clk_SMI_COMMON) FAIL! ERR CODE: %x\n", err); + err = clk_prepare_enable(fdvt_devs->clk_SCP_SYS_ISP); + if (err) + LOG_ERR("clk_prepare_enable(clk_SCP_SYS_ISP) FAIL! ERR CODE: %x\n", err); + err = clk_prepare_enable(fdvt_devs->clk_FD); + if (err) + LOG_ERR("clk_prepare_enable(clk_FD) FAIL! ERR CODE: %x\n", err); + } else { + clk_disable_unprepare(fdvt_devs->clk_FD); + clk_disable_unprepare(fdvt_devs->clk_SCP_SYS_ISP); + clk_disable_unprepare(fdvt_devs->clk_SMI_COMMON); + clk_disable_unprepare(fdvt_devs->clk_SCP_SYS_DIS); + } +#endif + return 0; +} + +/*=======================================================================*/ +/* MT6573FDVT FD Config Registers */ +/*=======================================================================*/ + +void FaceDetecteConfig(void) +{ + FDVT_WR32(0x01D10203, FD_FNUM_0); + FDVT_WR32(0x02A10213, FD_FNUM_1); + FDVT_WR32(0x03F102B1, FD_FNUM_2); + FDVT_WR32(0x046103C1, FD_FNUM_3); + FDVT_WR32(0x01450168, VT_FNUM_0); + FDVT_WR32(0x01D70173, VT_FNUM_1); + FDVT_WR32(0x02C201E2, VT_FNUM_2); + FDVT_WR32(0x031002A0, VT_FNUM_3); + FDVT_WR32(0x00600060, FE_FNUM_0); + FDVT_WR32(0x00000000, FE_FNUM_1); + FDVT_WR32(0x00000000, FE_FNUM_2); + FDVT_WR32(0x00000000, FE_FNUM_3); + /* FDVT_WR32(0x000F010B,FDVT_FD_SET); //LDVT Disable */ +} +/*=======================================================================*/ +/* MT6573FDVT SD Config Registers */ +/*=======================================================================*/ +void SmileDetecteConfig(void) +{ + FDVT_WR32(0x01210171, FD_FNUM_0); + FDVT_WR32(0x00D10081, FD_FNUM_1); + FDVT_WR32(0x00F100D1, FD_FNUM_2); + FDVT_WR32(0x00F100D1, FD_FNUM_3); + FDVT_WR32(0x00E70127, VT_FNUM_0); + FDVT_WR32(0x00A70067, VT_FNUM_1); + FDVT_WR32(0x00C000A7, VT_FNUM_2); + FDVT_WR32(0x00C000A7, VT_FNUM_3); + FDVT_WR32(0x00180018, FE_FNUM_0); + FDVT_WR32(0x00180018, FE_FNUM_1); + FDVT_WR32(0x00180018, FE_FNUM_2); + FDVT_WR32(0x00180018, FE_FNUM_3); + FDVT_WR32(0x000F010B, FDVT_FD_SET); +} + +/*=======================================================================*/ +/* MT6573FDVT Dump Registers */ +/*=======================================================================*/ +void MT6573FDVT_DUMPREG(void) +{ + UINT32 u4RegValue = 0; + UINT32 u4Index = 0; + + LOG_DBG("FDVT REG:\n ********************\n"); + + /* for(u4Index = 0; u4Index < 0x180; u4Index += 4) { */ + for (u4Index = 0x158; u4Index < 0x180; u4Index += 4) { + u4RegValue = ioread32((void *)(FDVT_ADDR + u4Index)); + LOG_DBG("+0x%x 0x%x\n", u4Index, u4RegValue); + } +} + +/*=======================================================================*/ +/* MT6573 FDVT set reg to HW buffer */ +/*=======================================================================*/ +static int MT6573FDVT_SetRegHW(MT6573FDVTRegIO *a_pstCfg) +{ + MT6573FDVTRegIO *pREGIO = NULL; + u32 i = 0; + if (NULL == a_pstCfg) { + LOG_DBG("Null input argrment\n"); + return -EINVAL; + } + + pREGIO = (MT6573FDVTRegIO *)a_pstCfg; + + if (copy_from_user((void *)pMT6573FDVTWRBuff.u4Addr, (void *) pREGIO->pAddr, pREGIO->u4Count * sizeof(u32))) { + LOG_DBG("ioctl copy from user failed\n"); + return -EFAULT; + } + + if (copy_from_user((void *)pMT6573FDVTWRBuff.u4Data, (void *) pREGIO->pData, pREGIO->u4Count * sizeof(u32))) { + LOG_DBG("ioctl copy from user failed\n"); + return -EFAULT; + } + + /* pMT6573FDVTWRBuff.u4Counter=pREGIO->u4Count; */ + /* LOG_DBG("Count = %d\n", pREGIO->u4Count); */ + + for (i = 0; i < pREGIO->u4Count; i++) { + if ((FDVT_ADDR + pMT6573FDVTWRBuff.u4Addr[i]) >= FDVT_ADDR && (FDVT_ADDR + pMT6573FDVTWRBuff.u4Addr[i]) <= (FDVT_ADDR + FDVT_MAX_OFFSET)) { + /* LOG_DBG("write addr = 0x%08x, data = 0x%08x\n", FDVT_ADDR + pMT6573FDVTWRBuff.u4Addr[i], pMT6573FDVTWRBuff.u4Data[i]); */ + FDVT_WR32(pMT6573FDVTWRBuff.u4Data[i], FDVT_ADDR + pMT6573FDVTWRBuff.u4Addr[i]); + } else { + LOG_ERR("ERROR: Writing Memory(0x%lx) Excess FDVT Range!\n", FDVT_ADDR + pMT6573FDVTWRBuff.u4Addr[i]); + } + } + + return 0; +} + +/******************************************************************************* +// +********************************************************************************/ +static int MT6573FDVT_ReadRegHW(MT6573FDVTRegIO *a_pstCfg) +{ + int ret = 0; + int size = a_pstCfg->u4Count * 4; + int i; + + if (size > buf_size) + LOG_DBG("size too big\n"); + + if (copy_from_user(pMT6573FDVTRDBuff.u4Addr, a_pstCfg->pAddr, size) != 0) { + LOG_DBG("copy_from_user failed\n"); + ret = -EFAULT; + goto mt_FDVT_read_reg_exit; + } + + for (i = 0; i < a_pstCfg->u4Count; i++) { + if ((FDVT_ADDR + pMT6573FDVTRDBuff.u4Addr[i]) >= FDVT_ADDR && (FDVT_ADDR + pMT6573FDVTRDBuff.u4Addr[i]) <= (FDVT_ADDR + FDVT_MAX_OFFSET)) { + pMT6573FDVTRDBuff.u4Data[i] = ioread32((void *)(FDVT_ADDR + pMT6573FDVTRDBuff.u4Addr[i])); + /* LOG_DBG("AFTER addr/val: 0x%08x/0x%08x\n", (u32) (FDVT_ADDR + pMT6573FDVTRDBuff.u4Addr[i]), (u32) pMT6573FDVTRDBuff.u4Data[i]); */ + } else { + LOG_ERR("ERROR: Reading Memory(0x%lx) Excess FDVT Range!\n", FDVT_ADDR + pMT6573FDVTRDBuff.u4Addr[i]); + ret = -EFAULT; + goto mt_FDVT_read_reg_exit; + } + } + if (copy_to_user(a_pstCfg->pData, pMT6573FDVTRDBuff.u4Data, size) != 0) { + LOG_DBG("copy_to_user failed\n"); + ret = -EFAULT; + goto mt_FDVT_read_reg_exit; + } +mt_FDVT_read_reg_exit: + + return ret; +} + +/*=======================================================================*/ +/* MT6573 Wait IRQ, for user space program to wait interrupt */ +/* wait for timeout 500ms */ +/*=======================================================================*/ +static int MT6573FDVT_WaitIRQ(u32 *u4IRQMask) +{ + int timeout; + timeout = wait_event_interruptible_timeout(g_MT6573FDVTWQ, (g_u4MT6573FDVTIRQMSK & g_u4MT6573FDVTIRQ), ms_to_jiffies(500)); + + if (timeout == 0) { + LOG_DBG("wait_event_interruptible_timeout timeout, %d, %d\n", g_u4MT6573FDVTIRQMSK, g_u4MT6573FDVTIRQ); + FDVT_WR32(0x00030000, FDVT_START); /* LDVT Disable */ + FDVT_WR32(0x00000000, FDVT_START); /* LDVT Disable */ + return -EAGAIN; + } + + *u4IRQMask = g_u4MT6573FDVTIRQ; + /* LOG_DBG("[FDVT] IRQ : 0x%8x\n",g_u4MT6573FDVTIRQ); */ + + if (!(g_u4MT6573FDVTIRQMSK & g_u4MT6573FDVTIRQ)) { + LOG_DBG("wait_event_interruptible Not FDVT, %d, %d\n", g_u4MT6573FDVTIRQMSK, g_u4MT6573FDVTIRQ); + MT6573FDVT_DUMPREG(); + return -1; + } + + g_u4MT6573FDVTIRQ = 0; + + return 0; +} + +static irqreturn_t MT6573FDVT_irq(int irq, void *dev_id) +{ + /* g_FDVT_interrupt_handler = VAL_TRUE; */ + /* FDVT_ISR(); */ + g_u4MT6573FDVTIRQ = ioread32((void *)FDVT_INT); + wake_up_interruptible(&g_MT6573FDVTWQ); + + return IRQ_HANDLED; +} + +static long FDVT_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + if (_IOC_NONE != _IOC_DIR(cmd)) { + /* IO write */ + if (_IOC_WRITE & _IOC_DIR(cmd)) { + if (copy_from_user(pBuff , (void *) arg, _IOC_SIZE(cmd))) { + LOG_DBG(" ioctl copy from user failed\n"); + return -EFAULT; + } + } + /* else */ + /* LOG_DBG(" ioctlnot write command\n"); */ + } + /* else */ + /* LOG_DBG(" ioctl command = NONE\n"); */ + + switch (cmd) { + case MT6573FDVT_INIT_SETPARA_CMD: + LOG_DBG("[FDVT] FDVT_INIT_CMD\n"); + FDVT_basic_config(); + break; + case MT6573FDVTIOC_STARTFD_CMD: + /* LOG_DBG("[FDVT] MT6573FDVTIOC_STARTFD_CMD\n"); */ + FDVT_WR32(0x00000001, FDVT_INT_EN); + FDVT_WR32(0x00000000, FDVT_START); + FDVT_WR32(0x00000001, FDVT_START); + FDVT_WR32(0x00000000, FDVT_START); + /* MT6573FDVT_DUMPREG(); */ + break; + case MT6573FDVTIOC_G_WAITIRQ: + /* LOG_DBG("[FDVT] MT6573FDVT_WaitIRQ\n"); */ + ret = MT6573FDVT_WaitIRQ((UINT32 *)pBuff); + FDVT_WR32(0x00000000, FDVT_INT_EN); /* BinChang 20120516 Close Interrupt */ + break; + case MT6573FDVTIOC_T_SET_FDCONF_CMD: + /* LOG_DBG("[FDVT] MT6573FDVT set FD config\n"); */ + FaceDetecteConfig(); /* LDVT Disable, Due to the different feature number between FD/SD/BD/REC */ + MT6573FDVT_SetRegHW((MT6573FDVTRegIO *)pBuff); + break; + case MT6573FDVTIOC_T_SET_SDCONF_CMD: + /* LOG_DBG("[FDVT] MT6573FDVT set SD config\n"); */ + SmileDetecteConfig(); + MT6573FDVT_SetRegHW((MT6573FDVTRegIO *)pBuff); + break; + case MT6573FDVTIOC_G_READ_FDREG_CMD: + /* LOG_DBG("[FDVT] MT6573FDVT read FD config\n"); */ + MT6573FDVT_ReadRegHW((MT6573FDVTRegIO *)pBuff); + break; + case MT6573FDVTIOC_T_DUMPREG: + LOG_DBG("[FDVT] FDVT_DUMPREG\n"); + MT6573FDVT_DUMPREG(); + break; + default: + LOG_DBG("[FDVT][ERROR] FDVT_ioctl default case\n"); + break; + } + /* NOT_REFERENCED(ret); */ + /* LOG_DBG("[FDVT] MT6573FDVT IOCtrol out\n"); */ + if (_IOC_READ & _IOC_DIR(cmd)) { + if (copy_to_user((void __user *) arg, pBuff , _IOC_SIZE(cmd)) != 0) { + LOG_DBG("copy_to_user failed\n"); + return -EFAULT; + } + } + + return ret; +} + +#ifdef CONFIG_COMPAT + +/******************************************************************************* +* +********************************************************************************/ + +static int compat_FD_get_register_data( + compat_MT6573FDVTRegIO __user *data32, + MT6573FDVTRegIO __user *data) +{ + compat_uint_t count; + compat_uptr_t uptr_Addr; + compat_uptr_t uptr_Data; + int err; + + err = get_user(uptr_Addr, &data32->pAddr); + err |= put_user(compat_ptr(uptr_Addr), &data->pAddr); + err |= get_user(uptr_Data, &data32->pData); + err |= put_user(compat_ptr(uptr_Data), &data->pData); + err |= get_user(count, &data32->u4Count); + err |= put_user(count, &data->u4Count); + + return err; +} + +static int compat_FD_put_register_data( + compat_MT6573FDVTRegIO __user *data32, + MT6573FDVTRegIO __user *data) +{ + compat_uint_t count; + /*compat_uptr_t uptr_Addr;*/ + /*compat_uptr_t uptr_Data;*/ + int err; + + /* Assume data pointer is unchanged. */ + /* err = get_user(uptr_Addr, &data->pAddr); */ + /* err |= put_user(compat_ptr(uptr_Addr), data32->pAddr); */ + /* err |= get_user(uptr_Data, &data->pData); */ + /* err |= put_user(compat_ptr(uptr_Data), &data32->pData); */ + err = get_user(count, &data->u4Count); + err |= put_user(count, &data32->u4Count); + + return err; +} + +static long compat_FD_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + + if (!file->f_op || !file->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + case COMPAT_MT6573FDVT_INIT_SETPARA_CMD: + { + return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); + } + case COMPAT_MT6573FDVTIOC_STARTFD_CMD: + { + return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); + } + case COMPAT_MT6573FDVTIOC_G_WAITIRQ: + { + compat_MT6573FDVTRegIO __user *data32; + MT6573FDVTRegIO __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_FD_get_register_data(data32, data); + if (err) + return err; + ret = file->f_op->unlocked_ioctl(file, MT6573FDVTIOC_G_WAITIRQ, (unsigned long)data); + err = compat_FD_put_register_data(data32, data); + return ret ? ret : err; + } + case COMPAT_MT6573FDVTIOC_T_SET_FDCONF_CMD: + { + compat_MT6573FDVTRegIO __user *data32; + MT6573FDVTRegIO __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_FD_get_register_data(data32, data); + if (err) + return err; + ret = file->f_op->unlocked_ioctl(file, MT6573FDVTIOC_T_SET_FDCONF_CMD, (unsigned long)data); + return ret ? ret : err; + } + case COMPAT_MT6573FDVTIOC_G_READ_FDREG_CMD: + { + compat_MT6573FDVTRegIO __user *data32; + MT6573FDVTRegIO __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_FD_get_register_data(data32, data); + if (err) + return err; + ret = file->f_op->unlocked_ioctl(file, MT6573FDVTIOC_G_READ_FDREG_CMD, (unsigned long)data); + err = compat_FD_put_register_data(data32, data); + return ret ? ret : err; + } + case COMPAT_MT6573FDVTIOC_T_SET_SDCONF_CMD: + { + compat_MT6573FDVTRegIO __user *data32; + MT6573FDVTRegIO __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_FD_get_register_data(data32, data); + if (err) + return err; + ret = file->f_op->unlocked_ioctl(file, MT6573FDVTIOC_T_SET_SDCONF_CMD, (unsigned long)data); + return ret ? ret : err; + } + case COMPAT_MT6573FDVTIOC_T_DUMPREG: + { + return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); + } + default: + return -ENOIOCTLCMD; + /* return ISP_ioctl(filep, cmd, arg); */ + } +} + +#endif + + +static int FDVT_open(struct inode *inode, struct file *file) +{ + /* VAL_BOOL_T flag; */ + INT32 ret = 0; + + LOG_DBG("[FDVT_DEBUG] FDVT_open\n"); + mt_fdvt_clk_ctrl(1); /* ISP help enable */ + if (pBuff != NULL) + LOG_DBG("pBuff is not null\n"); + if (pread_buf != NULL) + LOG_DBG("pread_buf is not null\n"); + + pBuff = kmalloc(buf_size, GFP_KERNEL); + if (NULL == pBuff) { + LOG_DBG(" ioctl allocate mem failed\n"); + ret = -ENOMEM; + } else { + LOG_DBG(" ioctl allocate mem ok\n"); + } + + pread_buf = kmalloc(buf_size, GFP_KERNEL); + if (pread_buf == NULL) { + LOG_DBG(" ioctl allocate mem failed\n"); + ret = -ENOMEM; + } else { + LOG_DBG(" ioctl allocate mem ok\n"); + } + + if (ret < 0) { + /*if (pBuff) {*/ + kfree(pBuff); + pBuff = NULL; + /*}*/ + /*if (pread_buf) {*/ + kfree(pread_buf); + pread_buf = NULL; + /*}*/ + } + + return 0; +} +/* +static int FDVT_flush(struct file *file, fl_owner_t id) +{ + LOG_DBG("[FDVT_DEBUG] FDVT_flush\n"); + + return 0; +} +*/ +static int FDVT_release(struct inode *inode, struct file *file) +{ + LOG_DBG("[FDVT_DEBUG] FDVT_release\n"); + /*if (pBuff) {*/ + kfree(pBuff); + pBuff = NULL; + /*}*/ + /*if (pread_buf) {*/ + kfree(pread_buf); + pread_buf = NULL; + /*}*/ + + FDVT_WR32(0x00000000, FDVT_INT_EN); /* BinChang 20120517 Close Interrupt */ + mb(); + g_u4MT6573FDVTIRQ = ioread32((void *)FDVT_INT); + mb(); + mt_fdvt_clk_ctrl(0); /* ISP help disable */ + return 0; +} + +static const struct file_operations FDVT_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = FDVT_ioctl, + .open = FDVT_open, + .release = FDVT_release, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_FD_ioctl, +#endif + +}; + +static int FDVT_probe(struct platform_device *dev) +{ + struct class_device; +#ifdef CONFIG_OF + struct fdvt_device *fdvt_dev; +#endif + int ret; + int i = 0; + int new_count; + struct class_device *class_dev = NULL; + nr_fdvt_devs = 0; + +#ifdef CONFIG_OF + + LOG_DBG("[FDVT_DEBUG] FDVT_probe\n"); + + if (dev == NULL) { + dev_err(&dev->dev, "dev is NULL"); + return -ENXIO; + } + + new_count = nr_fdvt_devs + 1; + fdvt_devs = krealloc(fdvt_devs, sizeof(struct fdvt_device) * new_count, GFP_KERNEL); + if (!fdvt_devs) { + dev_err(&dev->dev, "Unable to allocate fdvt_devs\n"); + return -ENOMEM; + } + + fdvt_dev = &(fdvt_devs[nr_fdvt_devs]); + fdvt_dev->dev = &dev->dev; + + /* iomap registers and irq*/ + for (i = 0; i < FDVT_BASEADDR_NUM; i++) { + fdvt_dev->regs[i] = of_iomap(dev->dev.of_node, i); + if (!fdvt_dev->regs[i]) { + dev_err(&dev->dev, "Unable to ioremap registers, of_iomap fail, i=%d\n", i); + return -ENOMEM; + } + gFDVT_Reg[i] = (unsigned long)fdvt_dev->regs[i]; + LOG_INF("DT, i=%d, map_addr=0x%lx\n", i, gFDVT_Reg[i]); + } + +#ifdef CONFIG_MTK_CLKMGR +#else + /*of_property_read_u32(pdev->dev.of_node, "clock-frequency", &speed_hz);*/ + /*of_property_read_u32(pdev->dev.of_node, "clock-div", &clk_src_div);*/ + fdvt_devs->clk_SCP_SYS_DIS = devm_clk_get(fdvt_dev->dev, "FD-SCP_SYS_DIS"); + if (!fdvt_devs->clk_SCP_SYS_DIS) { + LOG_ERR("cannot get clock: FD-SCP_SYS_DIS\n"); + return -ENOMEM; + } + fdvt_devs->clk_SCP_SYS_ISP = devm_clk_get(fdvt_dev->dev, "FD-SCP_SYS_ISP"); + if (!fdvt_devs->clk_SCP_SYS_ISP) { + LOG_ERR("cannot get clock: FD-SCP_SYS_ISP\n"); + return -ENOMEM; + } + fdvt_devs->clk_SMI_COMMON = devm_clk_get(fdvt_dev->dev, "FD-MM_DISP0_SMI_COMMON"); + if (!fdvt_devs->clk_SMI_COMMON) { + LOG_ERR("cannot get clock: FD-MM_DISP0_SMI_COMMON\n"); + return -ENOMEM; + } + fdvt_devs->clk_FD = devm_clk_get(fdvt_dev->dev, "FD-IMG_IMAGE_FD"); + if (!fdvt_devs->clk_FD) { + LOG_ERR("cannot get clock: FD-IMG_IMAGE_FD\n"); + return -ENOMEM; + } +#endif + + + /* get IRQ ID and request IRQ */ + for (i = 0; i < FDVT_IRQ_IDX_NUM; i++) { + fdvt_dev->irq[i] = irq_of_parse_and_map(dev->dev.of_node, i); + gFDVT_Irq[i] = fdvt_dev->irq[i]; + if (FDVT_IRQ_IDX == i) { + /* IRQF_TRIGGER_NONE dose not take effect here, real trigger mode set in dts file */ + ret = request_irq(fdvt_dev->irq[i], (irq_handler_t)MT6573FDVT_irq, IRQF_TRIGGER_NONE, FDVT_DEVNAME, NULL); + /* request_irq(FD_IRQ_BIT_ID, (irq_handler_t)MT6573FDVT_irq, IRQF_TRIGGER_LOW, FDVT_DEVNAME, NULL) */ + } + if (ret) { + dev_err(&dev->dev, "Unable to request IRQ, request_irq fail, i=%d, irq=%d\n", i, fdvt_dev->irq[i]); + return ret; + } + LOG_INF("DT, i=%d, map_irq=%d\n", i, fdvt_dev->irq[i]); + } + + nr_fdvt_devs = new_count; + if (dev == NULL) { + dev_err(&dev->dev, "dev is NULL"); + return -ENXIO; + } +#endif + + ret = alloc_chrdev_region(&FDVT_devno, 0, 1, FDVT_DEVNAME); + + if (ret) + LOG_DBG("[FDVT_DEBUG][ERROR] Can't Get Major number for FDVT Device\n"); + + FDVT_cdev = cdev_alloc(); + + FDVT_cdev->owner = THIS_MODULE; + FDVT_cdev->ops = &FDVT_fops; + + cdev_init(FDVT_cdev, &FDVT_fops); + + ret = cdev_add(FDVT_cdev, FDVT_devno, 1); + if (ret < 0) { + LOG_DBG("[FDVT_DEBUG] Attatch file operation failed\n"); + return -EFAULT; + } + +#ifndef CONFIG_OF + /* Register Interrupt */ + + /* if (request_irq(MT6573_FDVT_IRQ_LINE, (irq_handler_t)MT6573FDVT_irq, 0, FDVT_DEVNAME, NULL) < 0) */ + /* if (request_irq(MT_SMI_LARB1_VAMAU_IRQ_ID, (irq_handler_t)MT6573FDVT_irq, 0, FDVT_DEVNAME, NULL) < 0) */ + if (request_irq(FD_IRQ_BIT_ID, (irq_handler_t)MT6573FDVT_irq, IRQF_TRIGGER_LOW, FDVT_DEVNAME, NULL) < 0) + LOG_DBG("[FDVT_DEBUG][ERROR] error to request FDVT irq\n"); + else + LOG_DBG("[FDVT_DEBUG] success to request FDVT irq\n"); + /* For Linux 3.0 migration, replace mt65xx_irq_unmask() to enable_irq() */ + /* and mark it, due to request_irq() will call enable_irq. */ + /* mt65xx_irq_unmask(MT_SMI_LARB1_VAMAU_IRQ_ID); */ + /* enable_irq(MT_SMI_LARB1_VAMAU_IRQ_ID); */ +#endif + + + FDVT_class = class_create(THIS_MODULE, FDVT_DEVNAME); + class_dev = (struct class_device *)device_create(FDVT_class, + NULL, + FDVT_devno, + NULL, + FDVT_DEVNAME + ); + /* Initialize waitqueue */ + init_waitqueue_head(&g_MT6573FDVTWQ); + + + /* NOT_REFERENCED(class_dev); */ + /* NOT_REFERENCED(ret); */ + + + LOG_DBG("[FDVT_DEBUG] FDVT_probe Done\n"); + + return 0; +} + +static int FDVT_remove(struct platform_device *dev) +{ + int i4IRQ = 0; + LOG_DBG("[FDVT_DEBUG] FDVT_driver_exit\n"); + FDVT_WR32(0x00000000, FDVT_INT_EN); /* BinChang 20120517 Close Interrupt */ + g_u4MT6573FDVTIRQ = ioread32((void *)FDVT_INT); + mt_fdvt_clk_ctrl(0); /* ISP help disable */ + device_destroy(FDVT_class, FDVT_devno); + class_destroy(FDVT_class); + + cdev_del(FDVT_cdev); + unregister_chrdev_region(FDVT_devno, 1); + + i4IRQ = platform_get_irq(dev, 0); + free_irq(i4IRQ , NULL); + + /*if (pBuff) {*/ + kfree(pBuff); + pBuff = NULL; + /*}*/ + /*if (pread_buf) {*/ + kfree(pread_buf); + pread_buf = NULL; + /*}*/ + + + /* platform_driver_unregister(&FDVT_driver); */ + /* platform_device_unregister(&FDVT_device); */ + return 0; +} + +static int FDVT_suspend(struct platform_device *dev, pm_message_t state) +{ + /* BOOL flag; */ + /* LOG_DBG("[FDVT_DEBUG] FDVT_suspend\n"); */ + /* mt_fdvt_clk_ctrl(0); */ + /* + if (bMP4HWClockUsed == TRUE) + { + flag = hwDisableClock(MT6516_PDN_MM_MP4,"MPEG4_DEC"); + flag = hwDisableClock(MT6516_PDN_MM_DCT,"MPEG4_DEC"); + } + */ + /* NOT_REFERENCED(flag); */ + return 0; +} + +static int FDVT_resume(struct platform_device *dev) +{ + /* BOOL flag; */ + /* LOG_DBG("[FDVT_DEBUG] FDVT_resume\n"); */ + /* mt_fdvt_clk_ctrl(1); */ + /* + if (bMP4HWClockUsed == TRUE) + { + flag = hwEnableClock(MT6516_PDN_MM_MP4,"MPEG4_DEC"); + } + */ + /* NOT_REFERENCED(flag); */ + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id fdvt_of_ids[] = { + { .compatible = "mediatek,fdvt", }, + {} +}; +#endif + +static struct platform_driver FDVT_driver = { + .driver = { + .name = FDVT_DEVNAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = fdvt_of_ids, +#endif + }, + .probe = FDVT_probe, + .remove = FDVT_remove, + .suspend = FDVT_suspend, + .resume = FDVT_resume, +}; + +/* Device Tree Architecture Don't Use This Struct +static struct platform_device FDVT_device = { + .name = FDVT_DEVNAME, + .id = 0, +}; +*/ + +static int __init FDVT_driver_init(void) +{ + int ret; + + LOG_DBG("[FDVT_DEBUG] FDVT_driver_init\n"); + + /* + if (platform_device_register(&FDVT_device)){ + LOG_DBG("[FDVT_DEBUG][ERROR] failed to register FDVT Device\n"); + ret = -ENODEV; + return ret; + } + */ + + if (platform_driver_register(&FDVT_driver)) { + LOG_DBG("[FDVT_DEBUG][ERROR] failed to register FDVT Driver\n"); + /* platform_device_unregister(&FDVT_device); */ + ret = -ENODEV; + return ret; + } + LOG_DBG("[FDVT_DEBUG] FDVT_driver_init Done\n"); + + return 0; +} + +static void __exit FDVT_driver_exit(void) +{ + LOG_DBG("[FDVT_DEBUG] FDVT_driver_exit\n"); + + device_destroy(FDVT_class, FDVT_devno); + class_destroy(FDVT_class); + + cdev_del(FDVT_cdev); + unregister_chrdev_region(FDVT_devno, 1); + + platform_driver_unregister(&FDVT_driver); + /* platform_device_unregister(&FDVT_device); */ + +} + + +module_init(FDVT_driver_init); +module_exit(FDVT_driver_exit); +MODULE_AUTHOR("WCD/OSS9/ME3"); +MODULE_DESCRIPTION("FDVT Driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/mediatek/cameraisp/src/mt6755/camera_isp.c b/drivers/misc/mediatek/cameraisp/src/mt6755/camera_isp.c new file mode 100644 index 0000000000000000000000000000000000000000..af705ec16c33062e092ffff542c569e4ae6d2b20 --- /dev/null +++ b/drivers/misc/mediatek/cameraisp/src/mt6755/camera_isp.c @@ -0,0 +1,13764 @@ +/****************************************************************************** + * mt6593_isp.c - MT6593 Linux ISP Device Driver + * + * Copyright 2008-2009 MediaTek Co.,Ltd. + * + * DESCRIPTION: + * This file provid the other drivers ISP relative functions + * + ******************************************************************************/ +#include +#include +#include +#include +#include +/* #include */ +/* #include */ +#include /* proc file use */ +/* */ +#include +#include +/* #include */ +#include +#include +#include +#include +#include +/* #include */ +#include "inc/camera_isp.h" +#include +#include /* For clock mgr APIS. enable_clock()/disable_clock(). */ +#include /* For mt65xx_reg_sync_writel(). */ +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + +/* */ +#ifdef CONFIG_PM_WAKELOCKS +#include +#else +#include +#endif + +/*for kernel log reduction*/ +#include + +/* #define ISP_DEBUG */ + +#define CAMSV_DBG +#ifdef CAMSV_DBG +#define CAM_TAG "CAM:" +#define CAMSV_TAG "SV1:" +#define CAMSV2_TAG "SV2:" +#else +#define CAMSV_TAG "" +#define CAMSV2_TAG "" +#define CAM_TAG "" +#endif + +typedef unsigned char MUINT8; +typedef unsigned int MUINT32; +typedef signed char MINT8; +typedef signed int MINT32; +typedef bool MBOOL; +typedef unsigned char BOOL; + + +#ifndef MTRUE +#define MTRUE 1 +#endif +#ifndef MFALSE +#define MFALSE 0 +#endif +/* ---------------------------------------------------------------------------- */ + +#define MyTag "[ISP]" +#define IRQTag "KEEPER" + +#define LOG_VRB(format, args...) pr_debug(MyTag "[%s] " format, __func__, ##args) + +#ifdef ISP_DEBUG +#define LOG_DBG(format, args...) pr_debug(MyTag "[%s] " format, __func__, ##args) +#else +#define LOG_DBG(format, args...) +#endif + +#define LOG_INF(format, args...) pr_debug(MyTag "[%s] " format, __func__, ##args) +#define LOG_NOTICE(format, args...) pr_notice(MyTag "[%s] " format, __func__, ##args) +#define LOG_WRN(format, args...) pr_warn(MyTag "[%s] " format, __func__, ##args) +#define LOG_ERR(format, args...) pr_err(MyTag "[%s] " format, __func__, ##args) +#define LOG_AST(format, args...) pr_alert(MyTag "[%s] " format, __func__, ##args) + +/******************************************************************************* +* +********************************************************************************/ +/* #define ISP_WR32(addr, data) iowrite32(data, addr) // For other projects. */ +#define ISP_WR32(addr, data) mt_reg_sync_writel(data, addr) /* For 89 Only. NEED_TUNING_BY_PROJECT */ +#define ISP_RD32(addr) ioread32((void *)addr) +#define ISP_SET_BIT(reg, bit) ((*(volatile MUINT32*)(reg)) |= (MUINT32)(1 << (bit))) +#define ISP_CLR_BIT(reg, bit) ((*(volatile MUINT32*)(reg)) &= ~((MUINT32)(1 << (bit)))) +/******************************************************************************* +* +********************************************************************************/ +#define ISP_DEV_NAME "camera-isp" + +struct dentry *cisp_dbgTrigfs; +static /*volatile*/ wait_queue_head_t WaitQueueHead_ImemDbgDump; +typedef struct{ + volatile MUINT32 processID; /* process ID */ + volatile bool bImemDbgDump; /* */ + volatile bool bImemDbgDumpDone;/* */ +} ISP_IMEM_DUMP; +#define PROCESS_MAX 5 +static volatile ISP_IMEM_DUMP P2_IMEM_DBGList[PROCESS_MAX]; + +static /*volatile*/ wait_queue_head_t WaitQueueHead_ImemDbgDumpDone; +/* ///////////////////////////////////////////////////////////////// */ +/* for restricting range in mmap function */ +/* isp driver */ +#define ISP_RTBUF_REG_RANGE 0x10000 +#define IMGSYS_BASE_ADDR 0x15000000 +#define ISP_REG_RANGE (0x10000) /* 0x10000,the same with the value in isp_reg.h and page-aligned */ +/* seninf driver */ +#define SENINF_BASE_ADDR 0x15008000 /* the same with the value in seninf_drv.cpp(chip-dependent) */ +#define SENINF_REG_RANGE (0x4000) /* 0x4000,the same with the value in seninf_reg.h and page-aligned */ +#define PLL_BASE_ADDR 0x10000000 /* the same with the value in seninf_drv.cpp(chip-dependent) */ +#define PLL_RANGE (0x1000) /* 0x200,the same with the value in seninf_drv.cpp and page-aligned */ +#define MIPIRX_CONFIG_ADDR 0x1500C000 /* the same with the value in seninf_drv.cpp(chip-dependent) */ +#define MIPIRX_CONFIG_RANGE (0x1000) /* 0x100,the same with the value in seninf_drv.cpp and page-aligned */ +#define MIPIRX_ANALOG_ADDR 0x10217000 /* the same with the value in seninf_drv.cpp(chip-dependent) */ +#define MIPIRX_ANALOG_RANGE (0x3000) +#define GPIO_BASE_ADDR 0x10002000 /* the same with the value in seninf_drv.cpp(chip-dependent) */ +#define GPIO_RANGE (0x1000) +/* security concern */ +#define ISP_RANGE (0x10000) +/* ///////////////////////////////////////////////////////////////// */ + +/******************************************************************************* +* +********************************************************************************/ +#define ISP_DBG_INT (0x00000001) +#define ISP_DBG_HOLD_REG (0x00000002) +#define ISP_DBG_READ_REG (0x00000004) +#define ISP_DBG_WRITE_REG (0x00000008) +#define ISP_DBG_CLK (0x00000010) +#define ISP_DBG_TASKLET (0x00000020) +#define ISP_DBG_SCHEDULE_WORK (0x00000040) +#define ISP_DBG_BUF_WRITE (0x00000080) +#define ISP_DBG_BUF_CTRL (0x00000100) +#define ISP_DBG_REF_CNT_CTRL (0x00000200) +#define ISP_DBG_INT_2 (0x00000400) +#define ISP_DBG_INT_3 (0x00000800) + +/******************************************************************************* +* +********************************************************************************/ + + +#ifdef CONFIG_OF + +typedef enum { + ISP_CAM0_IRQ_IDX = 0, + ISP_CAM1_IRQ_IDX, + ISP_CAM2_IRQ_IDX, + ISP_CAMSV0_IRQ_IDX, + ISP_CAMSV1_IRQ_IDX, + ISP_CAM_IRQ_IDX_NUM +} ISP_CAM_IRQ_ENUM; + +typedef enum { + ISP_BASE_ADDR = 0, + ISP_INNER_BASE_ADDR, + ISP_IMGSYS_CONFIG_BASE_ADDR, + ISP_MIPI_ANA_BASE_ADDR, + ISP_GPIO_BASE_ADDR, + ISP_CAM_BASEADDR_NUM +} ISP_CAM_BASEADDR_ENUM; + +#ifndef CONFIG_MTK_CLKMGR /*CCF*/ +#include +typedef struct { + struct clk *CG_SCP_SYS_DIS; + struct clk *CG_SCP_SYS_ISP; + struct clk *CG_DISP0_SMI_COMMON; + struct clk *CG_IMAGE_CAM_SMI; + struct clk *CG_IMAGE_CAM_CAM; + struct clk *CG_IMAGE_SEN_TG; + struct clk *CG_IMAGE_SEN_CAM; + struct clk *CG_IMAGE_CAM_SV; + struct clk *CG_IMAGE_LARB2_SMI; +} ISP_CLK_STRUCT; +ISP_CLK_STRUCT isp_clk; +#endif + +static unsigned long gISPSYS_Irq[ISP_CAM_IRQ_IDX_NUM]; +static unsigned long gISPSYS_Reg[ISP_CAM_BASEADDR_NUM]; + +#ifdef CONFIG_PM_WAKELOCKS +struct wakeup_source isp_wake_lock; +#else +struct wake_lock isp_wake_lock; +#endif + +static volatile int g_bWaitLock; +/* static void __iomem *g_isp_base_dase; */ +/* static void __iomem *g_isp_inner_base_dase; */ +/* static void __iomem *g_imgsys_config_base_dase; */ + + +#define ISP_ADDR (gISPSYS_Reg[ISP_BASE_ADDR]) +#define ISP_IMGSYS_BASE (gISPSYS_Reg[ISP_IMGSYS_CONFIG_BASE_ADDR]) +#define ISP_ADDR_CAMINF (gISPSYS_Reg[ISP_IMGSYS_CONFIG_BASE_ADDR]) + +#define ISP_MIPI_ANA_ADDR (gISPSYS_Reg[ISP_MIPI_ANA_BASE_ADDR]) +#define ISP_GPIO_ADDR (gISPSYS_Reg[ISP_GPIO_BASE_ADDR]) + +#define ISP_IMGSYS_BASE_PHY 0x15000000 + +#else +#define ISP_ADDR (IMGSYS_BASE + 0x4000) +#define ISP_IMGSYS_BASE IMGSYS_BASE +#define ISP_ADDR_CAMINF IMGSYS_BASE +#define ISP_MIPI_ANA_ADDR 0x10215000 +#define ISP_GPIO_ADDR GPIO_BASE + +#endif + + +#define ISP_REG_ADDR_EN1 (ISP_ADDR + 0x4) +#define ISP_REG_ADDR_INT_P1_ST (ISP_ADDR + 0x4C) +#define ISP_REG_ADDR_INT_P1_ST2 (ISP_ADDR + 0x54) +#define ISP_REG_ADDR_INT_P1_ST_D (ISP_ADDR + 0x5C) +#define ISP_REG_ADDR_INT_P1_ST2_D (ISP_ADDR + 0x64) +#define ISP_REG_ADDR_INT_P2_ST (ISP_ADDR + 0x6C) +#define ISP_REG_ADDR_INT_STATUSX (ISP_ADDR + 0x70) +#define ISP_REG_ADDR_INT_STATUS2X (ISP_ADDR + 0x74) +#define ISP_REG_ADDR_INT_STATUS3X (ISP_ADDR + 0x78) +#define ISP_REG_ADDR_CAM_SW_CTL (ISP_ADDR + 0x8C) +#define ISP_REG_ADDR_IMGO_FBC (ISP_ADDR + 0xF0) +#define ISP_REG_ADDR_RRZO_FBC (ISP_ADDR + 0xF4) +#define ISP_REG_ADDR_IMGO_D_FBC (ISP_ADDR + 0xF8) +#define ISP_REG_ADDR_RRZO_D_FBC (ISP_ADDR + 0xFC) +#define ISP_REG_ADDR_TG_VF_CON (ISP_ADDR + 0x414) +#define ISP_REG_ADDR_TG_INTER_ST (ISP_ADDR + 0x44C) +#define ISP_REG_ADDR_TG2_VF_CON (ISP_ADDR + 0x2414) +#define ISP_REG_ADDR_TG2_INTER_ST (ISP_ADDR + 0x244C) +#define ISP_REG_ADDR_IMGO_BASE_ADDR (ISP_ADDR + 0x3300) +#define ISP_REG_ADDR_RRZO_BASE_ADDR (ISP_ADDR + 0x3320) +#define ISP_REG_ADDR_IMGO_D_BASE_ADDR (ISP_ADDR + 0x34D4) +#define ISP_REG_ADDR_RRZO_D_BASE_ADDR (ISP_ADDR + 0x34F4) +#define ISP_REG_ADDR_SENINF1_INT (ISP_ADDR + 0x4128) +#define ISP_REG_ADDR_SENINF2_INT (ISP_ADDR + 0x4528) +#define ISP_REG_ADDR_SENINF3_INT (ISP_ADDR + 0x4928) +#define ISP_REG_ADDR_SENINF4_INT (ISP_ADDR + 0x4D28) +#define ISP_REG_ADDR_CAMSV_FMT_SEL (ISP_ADDR + 0x5004) +#define ISP_REG_ADDR_CAMSV_INT (ISP_ADDR + 0x500C) +#define ISP_REG_ADDR_CAMSV_SW_CTL (ISP_ADDR + 0x5010) +#define ISP_REG_ADDR_CAMSV_TG_INTER_ST (ISP_ADDR + 0x544C) +#define ISP_REG_ADDR_CAMSV2_FMT_SEL (ISP_ADDR + 0x5804) +#define ISP_REG_ADDR_CAMSV2_INT (ISP_ADDR + 0x580C) +#define ISP_REG_ADDR_CAMSV2_SW_CTL (ISP_ADDR + 0x5810) +#define ISP_REG_ADDR_CAMSV_TG2_INTER_ST (ISP_ADDR + 0x5C4C) +#define ISP_REG_ADDR_CAMSV_IMGO_FBC (ISP_ADDR + 0x501C) +#define ISP_REG_ADDR_CAMSV2_IMGO_FBC (ISP_ADDR + 0x581C) +#define ISP_REG_ADDR_IMGO_SV_BASE_ADDR (ISP_ADDR + 0x5208) +#define ISP_REG_ADDR_IMGO_SV_XSIZE (ISP_ADDR + 0x5210) +#define ISP_REG_ADDR_IMGO_SV_YSIZE (ISP_ADDR + 0x5214) +#define ISP_REG_ADDR_IMGO_SV_STRIDE (ISP_ADDR + 0x5218) +#define ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR (ISP_ADDR + 0x5228) +#define ISP_REG_ADDR_IMGO_SV_D_XSIZE (ISP_ADDR + 0x5230) +#define ISP_REG_ADDR_IMGO_SV_D_YSIZE (ISP_ADDR + 0x5234) +#define ISP_REG_ADDR_IMGO_SV_D_STRIDE (ISP_ADDR + 0x5238) +#define TG_REG_ADDR_GRAB_W (ISP_ADDR + 0x418) +#define TG2_REG_ADDR_GRAB_W (ISP_ADDR + 0x2418) +#define TG_REG_ADDR_GRAB_H (ISP_ADDR + 0x41C) +#define TG2_REG_ADDR_GRAB_H (ISP_ADDR + 0x241C) + +#define ISP_REG_ADDR_CAMSV_TG_VF_CON (ISP_ADDR + 0x5414) +#define ISP_REG_ADDR_CAMSV_TG2_VF_CON (ISP_ADDR + 0x5C14) +/* spare register */ +/* #define ISP_REG_ADDR_TG_MAGIC_0 (ISP_ADDR + 0x94) */ +/* #define ISP_REG_ADDR_TG_MAGIC_1 (ISP_ADDR + 0x9C) */ +/* New define by 20131114 */ +#define ISP_REG_ADDR_TG_MAGIC_0 (ISP_IMGSYS_BASE + 0x75DC) /* 0088 */ + +#define ISP_REG_ADDR_TG2_MAGIC_0 (ISP_IMGSYS_BASE + 0x75E4) /* 0090 */ + +/* for rrz input crop size */ +#define ISP_REG_ADDR_TG_RRZ_CROP_IN (ISP_IMGSYS_BASE + 0x75E0) +#define ISP_REG_ADDR_TG_RRZ_CROP_IN_D (ISP_IMGSYS_BASE + 0x75E8) + +/* for rrz destination width (in twin mode, ISP_INNER_REG_ADDR_RRZO_XSIZE < RRZO width) */ +#define ISP_REG_ADDR_RRZ_W (ISP_ADDR_CAMINF + 0x4094) /* /// */ +#define ISP_REG_ADDR_RRZ_W_D (ISP_ADDR_CAMINF + 0x409C) /* /// */ +/* +CAM_REG_CTL_SPARE1 CAM_CTL_SPARE1; //4094 +CAM_REG_CTL_SPARE2 CAM_CTL_SPARE2; //409C +CAM_REG_CTL_SPARE3 CAM_CTL_SPARE3; //4100 +CAM_REG_AE_SPARE CAM_AE_SPARE; //4694 +CAM_REG_DM_O_SPARE CAM_DM_O_SPARE; //48F0 +CAM_REG_MIX1_SPARE CAM_MIX1_SPARE; //4C98 +CAM_REG_MIX2_SPARE CAM_MIX2_SPARE; //4CA8 +CAM_REG_MIX3_SPARE CAM_MIX3_SPARE; //4CB8 +CAM_REG_NR3D_SPARE0 CAM_NR3D_SPARE0; //4D04 +CAM_REG_AWB_D_SPARE CAM_AWB_D_SPARE; //663C +CAM_REG_AE_D_SPARE CAM_AE_D_SPARE; //6694 +CAMSV_REG_CAMSV_SPARE0 CAMSV_CAMSV_SPARE0; //9014 +CAMSV_REG_CAMSV_SPARE1 CAMSV_CAMSV_SPARE1; //9018 +CAMSV_REG_CAMSV2_SPARE0 CAMSV_CAMSV2_SPARE0; //9814 +CAMSV_REG_CAMSV2_SPARE1 CAMSV_CAMSV2_SPARE1; //9818 +*/ + +/* inner register */ +/* 1500_d000 ==> 1500_4000 */ +/* 1500_e000 ==> 1500_6000 */ +/* 1500_f000 ==> 1500_7000 */ +#define ISP_INNER_REG_ADDR_FMT_SEL_P1 (ISP_ADDR + 0x0028) +#define ISP_INNER_REG_ADDR_FMT_SEL_P1_D (ISP_ADDR + 0x002C) +/* #define ISP_INNER_REG_ADDR_FMT_SEL_P1 (ISP_ADDR_CAMINF + 0xD028) */ +/* #define ISP_INNER_REG_ADDR_FMT_SEL_P1_D (ISP_ADDR_CAMINF + 0xD02C) */ +#define ISP_INNER_REG_ADDR_CAM_CTRL_SEL_P1 (ISP_ADDR + 0x0034) +#define ISP_INNER_REG_ADDR_CAM_CTRL_SEL_P1_D (ISP_ADDR + 0x0038) +#define ISP_INNER_REG_ADDR_IMGO_XSIZE (ISP_ADDR_CAMINF + 0xF308) +#define ISP_INNER_REG_ADDR_IMGO_YSIZE (ISP_ADDR_CAMINF + 0xF30C) +#define ISP_INNER_REG_ADDR_IMGO_STRIDE (ISP_ADDR_CAMINF + 0xF310) +#define ISP_INNER_REG_ADDR_IMGO_CROP (ISP_ADDR_CAMINF + 0xF31C) +#define ISP_INNER_REG_ADDR_RRZO_XSIZE (ISP_ADDR_CAMINF + 0xF328) +#define ISP_INNER_REG_ADDR_RRZO_YSIZE (ISP_ADDR_CAMINF + 0xF32C) +#define ISP_INNER_REG_ADDR_RRZO_STRIDE (ISP_ADDR_CAMINF + 0xF330) +#define ISP_INNER_REG_ADDR_RRZO_CROP (ISP_ADDR_CAMINF + 0xF33C) +#define ISP_INNER_REG_ADDR_IMGO_D_XSIZE (ISP_ADDR_CAMINF + 0xF4DC) +#define ISP_INNER_REG_ADDR_IMGO_D_YSIZE (ISP_ADDR_CAMINF + 0xF4E0) +#define ISP_INNER_REG_ADDR_IMGO_D_STRIDE (ISP_ADDR_CAMINF + 0xF4E4) +#define ISP_INNER_REG_ADDR_IMGO_D_CROP (ISP_ADDR_CAMINF + 0xF4F0) +#define ISP_INNER_REG_ADDR_RRZO_D_XSIZE (ISP_ADDR_CAMINF + 0xF4FC) +#define ISP_INNER_REG_ADDR_RRZO_D_YSIZE (ISP_ADDR_CAMINF + 0xF500) +#define ISP_INNER_REG_ADDR_RRZO_D_STRIDE (ISP_ADDR_CAMINF + 0xF504) +#define ISP_INNER_REG_ADDR_RRZO_D_CROP (ISP_ADDR_CAMINF + 0xF510) + +#define ISP_INNER_REG_ADDR_RRZ_HORI_INT_OFST (ISP_ADDR_CAMINF + 0xD7B4) +#define ISP_INNER_REG_ADDR_RRZ_VERT_INT_OFST (ISP_ADDR_CAMINF + 0xD7BC) +#define ISP_INNER_REG_ADDR_RRZ_IN_IMG (ISP_ADDR_CAMINF + 0xD7A4) +#define ISP_INNER_REG_ADDR_RRZ_OUT_IMG (ISP_ADDR_CAMINF + 0xD7A8) + +#define ISP_INNER_REG_ADDR_RRZ_D_HORI_INT_OFST (ISP_ADDR_CAMINF + 0xE7B4) +#define ISP_INNER_REG_ADDR_RRZ_D_VERT_INT_OFST (ISP_ADDR_CAMINF + 0xE7BC) +#define ISP_INNER_REG_ADDR_RRZ_D_IN_IMG (ISP_ADDR_CAMINF + 0xE7A4) +#define ISP_INNER_REG_ADDR_RRZ_D_OUT_IMG (ISP_ADDR_CAMINF + 0xE7A8) + + +/* camsv hw no inner address to read */ +/* #define ISP_INNER_REG_ADDR_IMGO_SV_XSIZE (0) */ +/* #define ISP_INNER_REG_ADDR_IMGO_SV_YSIZE (0) */ +/* #define ISP_INNER_REG_ADDR_IMGO_SV_STRIDE (0) */ +/* #define ISP_INNER_REG_ADDR_IMGO_SV_D_XSIZE (0) */ +/* #define ISP_INNER_REG_ADDR_IMGO_SV_D_YSIZE (0) */ +/* #define ISP_INNER_REG_ADDR_IMGO_SV_D_STRIDE (0) */ +/* #define ISP_INNER_REG_ADDR_CAMSV_FMT_SEL (0) */ +/* #define ISP_INNER_REG_ADDR_CAMSV2_FMT_SEL (0) */ + +#define ISP_TPIPE_ADDR (0x15004000) + +/* CAM_CTL_SW_CTL */ +#define ISP_REG_SW_CTL_SW_RST_P1_MASK (0x00000007) +#define ISP_REG_SW_CTL_SW_RST_TRIG (0x00000001) +#define ISP_REG_SW_CTL_SW_RST_STATUS (0x00000002) +#define ISP_REG_SW_CTL_HW_RST (0x00000004) +#define ISP_REG_SW_CTL_SW_RST_P2_MASK (0x00000070) +#define ISP_REG_SW_CTL_SW_RST_P2_TRIG (0x00000010) +#define ISP_REG_SW_CTL_SW_RST_P2_STATUS (0x00000020) +#define ISP_REG_SW_CTL_HW_RST_P2 (0x00000040) +#define ISP_REG_SW_CTL_RST_CAM_P1 (1) +#define ISP_REG_SW_CTL_RST_CAM_P2 (2) +#define ISP_REG_SW_CTL_RST_CAMSV (3) +#define ISP_REG_SW_CTL_RST_CAMSV2 (4) + +/* CAM_CTL_INT_P1_STATUS */ +/* IRQ Mask */ +#define ISP_REG_MASK_INT_P1_ST (ISP_IRQ_P1_STATUS_VS1_INT_ST |\ + ISP_IRQ_P1_STATUS_TG1_INT1_ST |\ + ISP_IRQ_P1_STATUS_TG1_INT2_ST |\ + ISP_IRQ_P1_STATUS_EXPDON1_ST |\ + ISP_IRQ_P1_STATUS_PASS1_DON_ST |\ + ISP_IRQ_P1_STATUS_SOF1_INT_ST |\ + ISP_IRQ_P1_STATUS_AF_DON_ST |\ + ISP_IRQ_P1_STATUS_FLK_DON_ST |\ + ISP_IRQ_P1_STATUS_FBC_RRZO_DON_ST |\ + ISP_IRQ_P1_STATUS_FBC_IMGO_DON_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_INT_P1_ST_ERR (ISP_IRQ_P1_STATUS_TG1_ERR_ST |\ + ISP_IRQ_P1_STATUS_TG1_GBERR |\ + ISP_IRQ_P1_STATUS_CQ0_ERR |\ + ISP_IRQ_P1_STATUS_CQ0_VS_ERR_ST |\ + ISP_IRQ_P1_STATUS_IMGO_DROP_FRAME_ST |\ + ISP_IRQ_P1_STATUS_RRZO_DROP_FRAME_ST |\ + ISP_IRQ_P1_STATUS_IMGO_ERR_ST |\ + ISP_IRQ_P1_STATUS_AAO_ERR_ST |\ + ISP_IRQ_P1_STATUS_LCSO_ERR_ST |\ + ISP_IRQ_P1_STATUS_RRZO_ERR_ST |\ + ISP_IRQ_P1_STATUS_ESFKO_ERR_ST |\ + ISP_IRQ_P1_STATUS_FLK_ERR_ST |\ + ISP_IRQ_P1_STATUS_LSC_ERR_ST |\ + ISP_IRQ_P1_STATUS_DMA_ERR_ST) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_P1_ST_WAITQ (ISP_IRQ_P1_STATUS_VS1_INT_ST |\ + ISP_IRQ_P1_STATUS_PASS1_DON_ST |\ + ISP_IRQ_P1_STATUS_SOF1_INT_ST|\ + ISP_IRQ_P1_STATUS_AF_DON_ST) + +/* CAM_CTL_INT_P1_STATUS2 */ +/* IRQ Mask */ +#define ISP_REG_MASK_INT_P1_ST2 (ISP_IRQ_P1_STATUS2_IMGO_DONE_ST |\ + ISP_IRQ_P1_STATUS2_UFEO_DONE_ST |\ + ISP_IRQ_P1_STATUS2_RRZO_DONE_ST |\ + ISP_IRQ_P1_STATUS2_ESFKO_DONE_ST |\ + ISP_IRQ_P1_STATUS2_LCSO_DONE_ST |\ + ISP_IRQ_P1_STATUS2_AAO_DONE_ST |\ + ISP_IRQ_P1_STATUS2_BPCI_DONE_ST |\ + ISP_IRQ_P1_STATUS2_LSCI_DONE_ST |\ + ISP_IRQ_P1_STATUS2_AF_TAR_DONE_ST |\ + ISP_IRQ_P1_STATUS2_AF_FLO1_DONE_ST |\ + ISP_IRQ_P1_STATUS2_AF_FLO2_DONE_ST |\ + ISP_IRQ_P1_STATUS2_AF_FLO3_DONE_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_INT_P1_ST2_ERR (0x0) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_P1_ST2_WAITQ (0x0) + + +/* CAM_CTL_INT_P1_STATUS_D */ +/* IRQ Mask */ +#define ISP_REG_MASK_INT_P1_ST_D (ISP_IRQ_P1_STATUS_D_VS1_INT_ST |\ + ISP_IRQ_P1_STATUS_D_TG1_INT1_ST |\ + ISP_IRQ_P1_STATUS_D_TG1_INT2_ST |\ + ISP_IRQ_P1_STATUS_D_EXPDON1_ST |\ + ISP_IRQ_P1_STATUS_D_PASS1_DON_ST |\ + ISP_IRQ_P1_STATUS_D_SOF1_INT_ST |\ + ISP_IRQ_P1_STATUS_D_AF_DON_ST |\ + ISP_IRQ_P1_STATUS_D_FBC_RRZO_DON_ST |\ + ISP_IRQ_P1_STATUS_D_FBC_IMGO_DON_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_INT_P1_ST_D_ERR (ISP_IRQ_P1_STATUS_D_TG1_ERR_ST |\ + ISP_IRQ_P1_STATUS_D_TG1_GBERR |\ + ISP_IRQ_P1_STATUS_D_CQ0_ERR |\ + ISP_IRQ_P1_STATUS_D_CQ0_VS_ERR_ST |\ + ISP_IRQ_P1_STATUS_D_IMGO_DROP_FRAME_ST |\ + ISP_IRQ_P1_STATUS_D_RRZO_DROP_FRAME_ST |\ + ISP_IRQ_P1_STATUS_D_IMGO_ERR_ST |\ + ISP_IRQ_P1_STATUS_D_AAO_ERR_ST |\ + ISP_IRQ_P1_STATUS_D_LCSO_ERR_ST |\ + ISP_IRQ_P1_STATUS_D_RRZO_ERR_ST |\ + ISP_IRQ_P1_STATUS_D_AFO_ERR_ST |\ + ISP_IRQ_P1_STATUS_D_LSC_ERR_ST |\ + ISP_IRQ_P1_STATUS_D_DMA_ERR_ST) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_P1_ST_D_WAITQ (ISP_IRQ_P1_STATUS_D_VS1_INT_ST |\ + ISP_IRQ_P1_STATUS_D_PASS1_DON_ST |\ + ISP_IRQ_P1_STATUS_D_SOF1_INT_ST|\ + ISP_IRQ_P1_STATUS_D_AF_DON_ST) + +/* CAM_CTL_INT_P1_STATUS2_D */ +/* IRQ Mask */ +#define ISP_REG_MASK_INT_P1_ST2_D (ISP_IRQ_P1_STATUS2_D_IMGO_D_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_RRZO_D_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_AFO_D_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_LCSO_D_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_AAO_D_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_BPCI_D_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_LSCI_D_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_AF_TAR_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_AF_FLO1_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_AF_FLO2_DONE_ST |\ + ISP_IRQ_P1_STATUS2_D_AF_FLO3_DONE_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_INT_P1_ST2_D_ERR (0x0) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_P1_ST2_D_WAITQ (0x0) + +/* CAM_CTL_INT_P2_STATUS */ +/* IRQ Mask */ +#define ISP_REG_MASK_INT_P2_ST (ISP_IRQ_P2_STATUS_PASS2_DON_ST |\ + ISP_IRQ_P2_STATUS_TILE_DON_ST |\ + ISP_IRQ_P2_STATUS_CQ_DON_ST |\ + ISP_IRQ_P2_STATUS_PASS2A_DON_ST |\ + ISP_IRQ_P2_STATUS_PASS2B_DON_ST |\ + ISP_IRQ_P2_STATUS_PASS2C_DON_ST |\ + ISP_IRQ_P2_STATUS_CQ1_DONE_ST |\ + ISP_IRQ_P2_STATUS_CQ2_DONE_ST |\ + ISP_IRQ_P2_STATUS_CQ3_DONE_ST |\ + ISP_IRQ_P2_STATUS_IMGI_DONE_ST |\ + ISP_IRQ_P2_STATUS_UFDI_DONE_ST |\ + ISP_IRQ_P2_STATUS_VIPI_DONE_ST |\ + ISP_IRQ_P2_STATUS_VIP2I_DONE_ST |\ + ISP_IRQ_P2_STATUS_VIP3I_DONE_ST |\ + ISP_IRQ_P2_STATUS_LCEI_DONE_ST |\ + ISP_IRQ_P2_STATUS_MFBO_DONE_ST |\ + ISP_IRQ_P2_STATUS_IMG2O_DONE_ST |\ + ISP_IRQ_P2_STATUS_IMG3O_DONE_ST |\ + ISP_IRQ_P2_STATUS_IMG3BO_DONE_ST |\ + ISP_IRQ_P2_STATUS_IMG3CO_DONE_ST |\ + ISP_IRQ_P2_STATUS_FEO_DONE_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_INT_P2_ST_ERR (ISP_IRQ_P2_STATUS_CQ_ERR_ST |\ + ISP_IRQ_P2_STATUS_TDR_ERR_ST |\ + ISP_IRQ_P2_STATUS_PASS2A_ERR_TRIG_ST |\ + ISP_IRQ_P2_STATUS_PASS2B_ERR_TRIG_ST |\ + ISP_IRQ_P2_STATUS_PASS2C_ERR_TRIG_ST) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_P2_ST_WAITQ (ISP_IRQ_P2_STATUS_PASS2_DON_ST |\ + ISP_IRQ_P2_STATUS_PASS2A_DON_ST |\ + ISP_IRQ_P2_STATUS_PASS2B_DON_ST |\ + ISP_IRQ_P2_STATUS_PASS2C_DON_ST) +/* CAM_CTL_INT_STATUSX */ +/* IRQ Mask */ +#define ISP_REG_MASK_INT_STATUSX (ISP_IRQ_STATUSX_VS1_INT_ST |\ + ISP_IRQ_STATUSX_TG1_INT1_ST |\ + ISP_IRQ_STATUSX_TG1_INT2_ST |\ + ISP_IRQ_STATUSX_EXPDON1_ST |\ + ISP_IRQ_STATUSX_PASS1_DON_ST |\ + ISP_IRQ_STATUSX_SOF1_INT_ST |\ + ISP_IRQ_STATUSX_PASS2_DON_ST |\ + ISP_IRQ_STATUSX_TILE_DON_ST |\ + ISP_IRQ_STATUSX_AF_DON_ST |\ + ISP_IRQ_STATUSX_FLK_DON_ST |\ + ISP_IRQ_STATUSX_CQ_DON_ST |\ + ISP_IRQ_STATUSX_FBC_RRZO_DON_ST |\ + ISP_IRQ_STATUSX_FBC_IMGO_DON_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_INT_STATUSX_ERR (ISP_IRQ_STATUSX_TG1_ERR_ST |\ + ISP_IRQ_STATUSX_TG1_GBERR |\ + ISP_IRQ_STATUSX_CQ0_ERR |\ + ISP_IRQ_STATUSX_CQ0_VS_ERR_ST |\ + ISP_IRQ_STATUSX_IMGO_DROP_FRAME_ST |\ + ISP_IRQ_STATUSX_RRZO_DROP_FRAME_ST |\ + ISP_IRQ_STATUSX_CQ_ERR_ST |\ + ISP_IRQ_STATUSX_IMGO_ERR_ST |\ + ISP_IRQ_STATUSX_AAO_ERR_ST |\ + ISP_IRQ_STATUSX_LCSO_ERR_ST |\ + ISP_IRQ_STATUSX_RRZO_ERR_ST |\ + ISP_IRQ_STATUSX_ESFKO_ERR_ST |\ + ISP_IRQ_STATUSX_FLK_ERR_ST |\ + ISP_IRQ_STATUSX_LSC_ERR_ST |\ + ISP_IRQ_STATUSX_DMA_ERR_ST) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_STATUSX_WAITQ (0x0) + +/* CAM_CTL_INT_STATUS2X */ +/* IRQ Mask */ +#define ISP_REG_MASK_INT_STATUS2X (ISP_IRQ_STATUS2X_VS1_INT_ST |\ + ISP_IRQ_STATUS2X_TG1_INT1_ST |\ + ISP_IRQ_STATUS2X_TG1_INT2_ST |\ + ISP_IRQ_STATUS2X_EXPDON1_ST |\ + ISP_IRQ_STATUS2X_PASS1_DON_ST |\ + ISP_IRQ_STATUS2X_SOF1_INT_ST |\ + ISP_IRQ_STATUS2X_AF_DON_ST |\ + ISP_IRQ_STATUS2X_FBC_RRZO_DON_ST |\ + ISP_IRQ_STATUS2X_FBC_IMGO_DON_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_INT_STATUS2X_ERR (ISP_IRQ_STATUS2X_TG1_ERR_ST |\ + ISP_IRQ_STATUS2X_TG1_GBERR |\ + ISP_IRQ_STATUS2X_CQ0_ERR |\ + ISP_IRQ_STATUS2X_CQ0_VS_ERR_ST |\ + ISP_IRQ_STATUS2X_IMGO_DROP_FRAME_ST |\ + ISP_IRQ_STATUS2X_RRZO_DROP_FRAME_ST |\ + ISP_IRQ_STATUS2X_IMGO_ERR_ST |\ + ISP_IRQ_STATUS2X_AAO_ERR_ST |\ + ISP_IRQ_STATUS2X_LCSO_ERR_ST |\ + ISP_IRQ_STATUS2X_RRZO_ERR_ST |\ + ISP_IRQ_STATUS2X_AFO_ERR_ST |\ + ISP_IRQ_STATUS2X_LSC_ERR_ST |\ + ISP_IRQ_STATUS2X_DMA_ERR_ST) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_STATUS2X_WAITQ (0x0) + +/* CAM_CTL_INT_STATUS3X */ +/* IRQ Mask */ +#define ISP_REG_MASK_INT_STATUS3X (ISP_IRQ_STATUS3X_IMGO_DONE_ST |\ + ISP_IRQ_STATUS3X_UFEO_DONE_ST |\ + ISP_IRQ_STATUS3X_RRZO_DONE_ST |\ + ISP_IRQ_STATUS3X_ESFKO_DONE_ST |\ + ISP_IRQ_STATUS3X_LCSO_DONE_ST |\ + ISP_IRQ_STATUS3X_AAO_DONE_ST |\ + ISP_IRQ_STATUS3X_BPCI_DONE_ST |\ + ISP_IRQ_STATUS3X_LSCI_DONE_ST |\ + ISP_IRQ_STATUS3X_IMGO_D_DONE_ST |\ + ISP_IRQ_STATUS3X_RRZO_D_DONE_ST |\ + ISP_IRQ_STATUS3X_AFO_D_DONE_ST |\ + ISP_IRQ_STATUS3X_LCSO_D_DONE_ST |\ + ISP_IRQ_STATUS3X_AAO_D_DONE_ST |\ + ISP_IRQ_STATUS3X_BPCI_D_DONE_ST |\ + ISP_IRQ_STATUS3X_LCSI_D_DONE_ST |\ + ISP_IRQ_STATUS3X_IMGI_DONE_ST |\ + ISP_IRQ_STATUS3X_UFDI_DONE_ST |\ + ISP_IRQ_STATUS3X_VIPI_DONE_ST |\ + ISP_IRQ_STATUS3X_VIP2I_DONE_ST |\ + ISP_IRQ_STATUS3X_VIP3I_DONE_ST |\ + ISP_IRQ_STATUS3X_LCEI_DONE_ST |\ + ISP_IRQ_STATUS3X_MFBO_DONE_ST |\ + ISP_IRQ_STATUS3X_IMG2O_DONE_ST |\ + ISP_IRQ_STATUS3X_IMG3O_DONE_ST |\ + ISP_IRQ_STATUS3X_IMG3BO_DONE_ST |\ + ISP_IRQ_STATUS3X_IMG3CO_DONE_ST |\ + ISP_IRQ_STATUS3X_FEO_DONE_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_INT_STATUS3X_ERR (0X0) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_STATUS3X_WAITQ (0x0) + + +/* SENINF1_IRQ_INTSTA */ +#define ISP_REG_MASK_INT_SENINF1 (0X0) +#define ISP_REG_MASK_INT_SENINF1_ERR (SENINF1_IRQ_OVERRUN_IRQ_STA |\ + SENINF1_IRQ_CRCERR_IRQ_STA |\ + SENINF1_IRQ_FSMERR_IRQ_STA |\ + SENINF1_IRQ_VSIZEERR_IRQ_STA |\ + SENINF1_IRQ_HSIZEERR_IRQ_STA |\ + SENINF1_IRQ_SENSOR_VSIZEERR_IRQ_STA |\ + SENINF1_IRQ_SENSOR_HSIZEERR_IRQ_STA) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_SENINF1_WAITQ (0x0) + +/* SENINF2_IRQ_INTSTA */ +#define ISP_REG_MASK_INT_SENINF2 (0X0) +#define ISP_REG_MASK_INT_SENINF2_ERR (SENINF2_IRQ_OVERRUN_IRQ_STA |\ + SENINF1_IRQ_CRCERR_IRQ_STA |\ + SENINF2_IRQ_FSMERR_IRQ_STA |\ + SENINF2_IRQ_VSIZEERR_IRQ_STA |\ + SENINF2_IRQ_HSIZEERR_IRQ_STA |\ + SENINF2_IRQ_SENSOR_VSIZEERR_IRQ_STA |\ + SENINF2_IRQ_SENSOR_HSIZEERR_IRQ_STA) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_SENINF2_WAITQ (0x0) + +/* SENINF3_IRQ_INTSTA */ +#define ISP_REG_MASK_INT_SENINF3 (0X0) +#define ISP_REG_MASK_INT_SENINF3_ERR (SENINF3_IRQ_OVERRUN_IRQ_STA |\ + SENINF3_IRQ_CRCERR_IRQ_STA |\ + SENINF3_IRQ_FSMERR_IRQ_STA |\ + SENINF3_IRQ_VSIZEERR_IRQ_STA |\ + SENINF3_IRQ_HSIZEERR_IRQ_STA |\ + SENINF3_IRQ_SENSOR_VSIZEERR_IRQ_STA |\ + SENINF3_IRQ_SENSOR_HSIZEERR_IRQ_STA) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_SENINF3_WAITQ (0x0) + +/* SENINF4_IRQ_INTSTA */ +#define ISP_REG_MASK_INT_SENINF4 (0X0) +#define ISP_REG_MASK_INT_SENINF4_ERR (SENINF4_IRQ_OVERRUN_IRQ_STA |\ + SENINF4_IRQ_CRCERR_IRQ_STA |\ + SENINF4_IRQ_FSMERR_IRQ_STA |\ + SENINF4_IRQ_VSIZEERR_IRQ_STA |\ + SENINF4_IRQ_HSIZEERR_IRQ_STA |\ + SENINF4_IRQ_SENSOR_VSIZEERR_IRQ_STA |\ + SENINF4_IRQ_SENSOR_HSIZEERR_IRQ_STA) +/* if we service wait queue or not */ +#define ISP_REG_MASK_INT_SENINF4_WAITQ (0x0) + +#define ISP_REG_MASK_CAMSV_ST (ISP_IRQ_CAMSV_STATUS_VS1_ST |\ + ISP_IRQ_CAMSV_STATUS_TG_ST1 |\ + ISP_IRQ_CAMSV_STATUS_TG_ST2 |\ + ISP_IRQ_CAMSV_STATUS_EXPDON1_ST |\ + ISP_IRQ_CAMSV_STATUS_TG_SOF1_ST |\ + ISP_IRQ_CAMSV_STATUS_PASS1_DON_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_CAMSV_ST_ERR (ISP_IRQ_CAMSV_STATUS_TG_ERR_ST |\ + ISP_IRQ_CAMSV_STATUS_TG_GBERR_ST |\ + ISP_IRQ_CAMSV_STATUS_TG_DROP_ST |\ + ISP_IRQ_CAMSV_STATUS_IMGO_ERR_ST |\ + ISP_IRQ_CAMSV_STATUS_IMGO_OVERR_ST |\ + ISP_IRQ_CAMSV_STATUS_IMGO_DROP_ST) +/* if we service wait queue or not */ +#define ISP_REG_MASK_CAMSV_ST_WAITQ (ISP_IRQ_CAMSV_STATUS_VS1_ST |\ + ISP_IRQ_CAMSV_STATUS_TG_SOF1_ST |\ + ISP_IRQ_CAMSV_STATUS_PASS1_DON_ST) + +#define ISP_REG_MASK_CAMSV2_ST (ISP_IRQ_CAMSV2_STATUS_VS1_ST |\ + ISP_IRQ_CAMSV2_STATUS_TG_ST1 |\ + ISP_IRQ_CAMSV2_STATUS_TG_ST2 |\ + ISP_IRQ_CAMSV2_STATUS_EXPDON1_ST |\ + ISP_IRQ_CAMSV2_STATUS_TG_SOF1_ST |\ + ISP_IRQ_CAMSV2_STATUS_PASS1_DON_ST) +/* IRQ Error Mask */ +#define ISP_REG_MASK_CAMSV2_ST_ERR (ISP_IRQ_CAMSV2_STATUS_TG_ERR_ST |\ + ISP_IRQ_CAMSV2_STATUS_TG_GBERR_ST |\ + ISP_IRQ_CAMSV2_STATUS_TG_DROP_ST |\ + ISP_IRQ_CAMSV2_STATUS_IMGO_ERR_ST |\ + ISP_IRQ_CAMSV2_STATUS_IMGO_OVERR_ST |\ + ISP_IRQ_CAMSV2_STATUS_IMGO_DROP_ST) +/* if we service wait queue or not */ +#define ISP_REG_MASK_CAMSV2_ST_WAITQ (ISP_IRQ_CAMSV2_STATUS_VS1_ST |\ + ISP_IRQ_CAMSV2_STATUS_TG_SOF1_ST |\ + ISP_IRQ_CAMSV2_STATUS_PASS1_DON_ST) + +static volatile MINT32 gEismetaRIdx; +static volatile MINT32 gEismetaWIdx; +static volatile MINT32 gEismetaInSOF; +static volatile MINT32 gEismetaRIdx_D; +static volatile MINT32 gEismetaWIdx_D; +static volatile MINT32 gEismetaInSOF_D; +#define EISMETA_RINGSIZE 4 + +static spinlock_t SpinLockImemDump; +/* record remain node count(success/fail) excludes head when enque/deque control */ +static volatile MINT32 EDBufQueRemainNodeCnt; + +static /*volatile*/ wait_queue_head_t WaitQueueHead_EDBuf_WaitDeque; +static /*volatile*/ wait_queue_head_t WaitQueueHead_EDBuf_WaitFrame; +static spinlock_t SpinLockEDBufQueList; +#define _MAX_SUPPORT_P2_FRAME_NUM_ 512 +#define _MAX_SUPPORT_P2_BURSTQ_NUM_ 4 +static volatile MINT32 P2_Support_BurstQNum = 1; +#define _MAX_SUPPORT_P2_PACKAGE_NUM_ (_MAX_SUPPORT_P2_FRAME_NUM_/_MAX_SUPPORT_P2_BURSTQ_NUM_) +#define P2_EDBUF_MLIST_TAG 1 +#define P2_EDBUF_RLIST_TAG 2 +typedef struct { + volatile MUINT32 processID; /* caller process ID */ + volatile MUINT32 callerID; /* caller thread ID */ + volatile MINT32 p2dupCQIdx; /* p2 duplicate CQ index(for recognize belong to which package) */ + volatile ISP_ED_BUF_STATE_ENUM bufSts; /* buffer status */ +} ISP_EDBUF_STRUCT; +static volatile MINT32 P2_EDBUF_RList_FirstBufIdx; +static volatile MINT32 P2_EDBUF_RList_CurBufIdx; +static volatile MINT32 P2_EDBUF_RList_LastBufIdx; +static volatile ISP_EDBUF_STRUCT P2_EDBUF_RingList[_MAX_SUPPORT_P2_FRAME_NUM_]; + +typedef struct { + volatile MUINT32 processID; /* caller process ID */ + volatile MUINT32 callerID; /* caller thread ID */ + volatile MINT32 p2dupCQIdx; /* p2 duplicate CQ index(for recognize belong to which package) */ + volatile MINT32 frameNum; + volatile MINT32 dequedNum; /* number of dequed buffer no matter deque success or fail */ +} ISP_EDBUF_MGR_STRUCT; +static volatile MINT32 P2_EDBUF_MList_FirstBufIdx; +/* static volatile MINT32 P2_EDBUF_MList_CurBufIdx=0;*/ +static volatile MINT32 P2_EDBUF_MList_LastBufIdx; +static volatile ISP_EDBUF_MGR_STRUCT P2_EDBUF_MgrList[_MAX_SUPPORT_P2_PACKAGE_NUM_]; + +static volatile MUINT32 g_regScen = 0xa5a5a5a5; +static volatile spinlock_t SpinLockRegScen; + +/* maximum number for supporting user to do interrupt operation */ +/* index 0 is for all the user that do not do register irq first */ +#define IRQ_USER_NUM_MAX 32 +static volatile spinlock_t SpinLock_UserKey; + +/*m4u_callback_ret_t ISP_M4U_TranslationFault_callback(int port, unsigned int mva, void *data);*/ + +/******************************************************************************* +* +********************************************************************************/ +/* internal data */ +/* pointer to the kmalloc'd area, rounded up to a page boundary */ +static int *pTbl_RTBuf; +/* original pointer for kmalloc'd area as returned by kmalloc */ +static void *pBuf_kmalloc; +/* */ +static volatile ISP_RT_BUF_STRUCT *pstRTBuf; + +/* static ISP_DEQUE_BUF_INFO_STRUCT g_deque_buf = {0,{}}; // Marked to remove build warning. */ + +unsigned long g_Flash_SpinLock; + + +static volatile unsigned int G_u4EnableClockCount; + +int pr_detect_count; +/******************************************************************************* +* +********************************************************************************/ +typedef struct { + pid_t Pid; + pid_t Tid; +} ISP_USER_INFO_STRUCT; + +/******************************************************************************* +* +********************************************************************************/ +#define ISP_BUF_SIZE (4096) +#define ISP_BUF_SIZE_WRITE 1024 +#define ISP_BUF_WRITE_AMOUNT 6 + +typedef enum { + ISP_BUF_STATUS_EMPTY, + ISP_BUF_STATUS_HOLD, + ISP_BUF_STATUS_READY +} ISP_BUF_STATUS_ENUM; + +typedef struct { + volatile ISP_BUF_STATUS_ENUM Status; + volatile MUINT32 Size; + MUINT8 *pData; +} ISP_BUF_STRUCT; + +typedef struct { + ISP_BUF_STRUCT Read; + ISP_BUF_STRUCT Write[ISP_BUF_WRITE_AMOUNT]; +} ISP_BUF_INFO_STRUCT; + + +/******************************************************************************* +* +********************************************************************************/ +typedef struct { + atomic_t HoldEnable; + atomic_t WriteEnable; + ISP_HOLD_TIME_ENUM Time; +} ISP_HOLD_INFO_STRUCT; + +static volatile MINT32 FirstUnusedIrqUserKey = 1; +#define USERKEY_STR_LEN 128 + +typedef struct { + char userName[USERKEY_STR_LEN]; /* name for the user that register a userKey */ + int userKey; /* the user key for that user */ +} UserKeyInfo; +/* array for recording the user name for a specific user key */ +static volatile UserKeyInfo IrqUserKey_UserInfo[IRQ_USER_NUM_MAX]; + +static volatile MUINT32 IrqFlush[ISP_IRQ_USER_MAX]; +static volatile MUINT32 IrqFlush_v3[IRQ_USER_NUM_MAX]; + + +typedef struct { + volatile MUINT32 Status[IRQ_USER_NUM_MAX][ISP_IRQ_TYPE_AMOUNT]; + MUINT32 Mask[ISP_IRQ_TYPE_AMOUNT]; + MUINT32 ErrMask[ISP_IRQ_TYPE_AMOUNT]; + + /* flag for indicating that user do mark for a interrupt or not */ + volatile MUINT32 MarkedFlag[IRQ_USER_NUM_MAX][ISP_IRQ_TYPE_AMOUNT]; + /* time for marking a specific interrupt */ + volatile MUINT32 MarkedTime_sec[IRQ_USER_NUM_MAX][ISP_IRQ_TYPE_AMOUNT][32]; + /* time for marking a specific interrupt */ + volatile MUINT32 MarkedTime_usec[IRQ_USER_NUM_MAX][ISP_IRQ_TYPE_AMOUNT][32]; + /* number of a specific signal that passed by */ + volatile MINT32 PassedBySigCnt[IRQ_USER_NUM_MAX][ISP_IRQ_TYPE_AMOUNT][32]; + /* latest occuring time for each interrupt */ + volatile MUINT32 LastestSigTime_sec[ISP_IRQ_TYPE_AMOUNT][32]; + /* latest occuring time for each interrupt */ + volatile MUINT32 LastestSigTime_usec[ISP_IRQ_TYPE_AMOUNT][32]; + /* eis meta only for p1 and p1_d */ + volatile ISP_EIS_META_STRUCT Eismeta[ISP_IRQ_TYPE_INT_STATUSX][EISMETA_RINGSIZE]; +} ISP_IRQ_INFO_STRUCT; + +typedef struct { + MUINT32 Vd; + MUINT32 Expdone; + MUINT32 WorkQueueVd; + MUINT32 WorkQueueExpdone; + MUINT32 TaskletVd; + MUINT32 TaskletExpdone; +} ISP_TIME_LOG_STRUCT; + +typedef enum _eChannel { + _PASS1 = 0, + _PASS1_D = 1, + _CAMSV = 2, + _CAMSV_D = 3, + _PASS2 = 4, + _ChannelMax = 5, +} eChannel; + +/**********************************************************************/ +#define my_get_pow_idx(value)\ +({\ + int i = 0, cnt = 0;\ + for (i = 0; i < 32; i++) {\ + if ((value>>i) & (0x00000001)) {\ + break;\ + } else{\ + cnt++;\ + } \ + } \ + cnt;\ +}) + + +#define DMA_TRANS(dma, Out) \ +do { \ + if (dma == _imgo_ || dma == _rrzo_) {\ + Out = _PASS1;\ + } else if (dma == _imgo_d_ || dma == _rrzo_d_) { \ + Out = _PASS1_D;\ + } else if (dma == _camsv_imgo_) {\ + Out = _CAMSV;\ + } else if (dma == _camsv2_imgo_) {\ + Out = _CAMSV_D;\ + } else {\ + } \ +} while (0) + +/* basically , should separate into p1/p1_d/p2/camsv/camsv_d, */ +/* currently, only use camsv/camsv_d/others */ +typedef enum _eISPIrq { + _IRQ = 0, + _IRQ_D = 1, + _CAMSV_IRQ = 2, + _CAMSV_D_IRQ = 3, + _IRQ_MAX = 4, +} eISPIrq; + +typedef enum _eLOG_TYPE { + _LOG_DBG = 0, /* currently, only used at ipl_buf_ctrl. to protect critical section */ + _LOG_INF = 1, + _LOG_ERR = 2, + _LOG_MAX = 3, +} eLOG_TYPE; + +typedef enum _eLOG_OP { + _LOG_INIT = 0, + _LOG_RST = 1, + _LOG_ADD = 2, + _LOG_PRT = 3, + _LOG_GETCNT = 4, + _LOG_OP_MAX = 5 +} eLOG_OP; + +#define NORMAL_STR_LEN (512) +#define ERR_PAGE 2 +#define DBG_PAGE 2 +#define INF_PAGE 4 +/* #define SV_LOG_STR_LEN NORMAL_STR_LEN */ + +#define LOG_PPNUM 2 +/*volatile static MUINT32 m_CurrentPPB;*/ /* ERROR */ +static volatile MUINT32 m_CurrentPPB; +typedef struct _SV_LOG_STR { + MUINT32 _cnt[LOG_PPNUM][_LOG_MAX]; + /* char _str[_LOG_MAX][SV_LOG_STR_LEN]; */ + char *_str[LOG_PPNUM][_LOG_MAX]; +} SV_LOG_STR, *PSV_LOG_STR; + +static void *pLog_kmalloc; +static SV_LOG_STR gSvLog[_IRQ_MAX]; +/* static SV_LOG_STR gSvLog_IRQ = {0};*/ +/* static SV_LOG_STR gSvLog_CAMSV_IRQ= {0};*/ +/* static SV_LOG_STR gSvLog_CAMSV_D_IRQ= {0};*/ +static volatile MBOOL g_bDmaERR_p1 = MFALSE; +static volatile MBOOL g_bDmaERR_p1_d = MFALSE; +static volatile MBOOL g_bDmaERR_p2 = MFALSE; +static volatile MBOOL g_bDmaERR_deepDump = MFALSE; +static volatile MUINT32 g_ISPIntErr[_IRQ_MAX] = { 0 }; + +#define nDMA_ERR_P1 (11) +#define nDMA_ERR_P1_D (7) +#define nDMA_ERR (nDMA_ERR_P1 + nDMA_ERR_P1_D) +static MUINT32 g_DmaErr_p1[nDMA_ERR] = { 0 }; + +/** + for irq used,keep log until IRQ_LOG_PRINTER being involked, + limited: + each log must shorter than 512 bytes + total log length in each irq/logtype can't over 1024 bytes +*/ +#define IRQ_LOG_KEEPER_T(sec, usec) {\ + ktime_t time; \ + time = ktime_get(); \ + sec = time.tv64; \ + do_div(sec, 1000); \ + usec = do_div(sec, 1000000);\ +} +#if 1 +/* snprintf: avaLen, 1 for null termination*/ +#define IRQ_LOG_KEEPER(irq, ppb, logT, fmt, ...) do {\ + char *ptr;\ + char *pDes;\ + MINT32 avaLen;\ + MUINT32 *ptr2 = &gSvLog[irq]._cnt[ppb][logT];\ + unsigned int str_leng;\ + if (_LOG_ERR == logT) {\ + str_leng = NORMAL_STR_LEN*ERR_PAGE;\ + } else if (_LOG_DBG == logT) {\ + str_leng = NORMAL_STR_LEN*DBG_PAGE;\ + } else if (_LOG_INF == logT) {\ + str_leng = NORMAL_STR_LEN*INF_PAGE;\ + } else {\ + str_leng = 0;\ + } \ + ptr = pDes = (char *)&(gSvLog[irq]._str[ppb][logT][gSvLog[irq]._cnt[ppb][logT]]);\ + avaLen = str_leng - 1 - gSvLog[irq]._cnt[ppb][logT];\ + if (avaLen > 1) {\ + snprintf((char *)(pDes), avaLen, fmt, ##__VA_ARGS__); \ + if ('\0' != gSvLog[irq]._str[ppb][logT][str_leng - 1]) { \ + LOG_ERR("(%d)(%d)log str over flow", irq, logT);\ + } \ + while (*ptr++ != '\0') {\ + (*ptr2)++;\ + } \ + } else { \ + LOG_ERR("(%d)(%d)log str avalible=0", irq, logT);\ + } \ +} while (0) +#else +#define IRQ_LOG_KEEPER(irq, ppb, logT, fmt, args...) pr_warn(IRQTag fmt, ##args) +#endif + +#if 1 +#define IRQ_LOG_PRINTER(irq, ppb_in, logT_in) do {\ + SV_LOG_STR *pSrc = &gSvLog[irq];\ + char *ptr;\ + MUINT32 i;\ + MINT32 ppb = 0;\ + MINT32 logT = 0;\ + if (ppb_in > 1) {\ + ppb = 1;\ + } else{\ + ppb = ppb_in;\ + } \ + if (logT_in > _LOG_ERR) {\ + logT = _LOG_ERR;\ + } else{\ + logT = logT_in;\ + } \ + ptr = pSrc->_str[ppb][logT];\ + if (0 != pSrc->_cnt[ppb][logT]) {\ + if (_LOG_DBG == logT) {\ + for (i = 0; i < DBG_PAGE; i++) {\ + if (ptr[NORMAL_STR_LEN*(i+1) - 1] != '\0') {\ + ptr[NORMAL_STR_LEN*(i+1) - 1] = '\0';\ + LOG_INF("%s", &ptr[NORMAL_STR_LEN*i]);\ + } else{\ + LOG_INF("%s", &ptr[NORMAL_STR_LEN*i]);\ + break;\ + } \ + } \ + } \ + else if (_LOG_INF == logT) {\ + for (i = 0; i < INF_PAGE; i++) {\ + if (ptr[NORMAL_STR_LEN*(i+1) - 1] != '\0') {\ + ptr[NORMAL_STR_LEN*(i+1) - 1] = '\0';\ + LOG_INF("%s", &ptr[NORMAL_STR_LEN*i]);\ + } else{\ + LOG_INF("%s", &ptr[NORMAL_STR_LEN*i]);\ + break;\ + } \ + } \ + } \ + else if (_LOG_ERR == logT) {\ + for (i = 0; i < ERR_PAGE; i++) {\ + if (ptr[NORMAL_STR_LEN*(i+1) - 1] != '\0') {\ + ptr[NORMAL_STR_LEN*(i+1) - 1] = '\0';\ + LOG_ERR("%s", &ptr[NORMAL_STR_LEN*i]);\ + } else{\ + LOG_ERR("%s", &ptr[NORMAL_STR_LEN*i]);\ + break;\ + } \ + } \ + } \ + else {\ + LOG_ERR("N.S.%d", logT);\ + } \ + ptr[0] = '\0';\ + pSrc->_cnt[ppb][logT] = 0;\ + } \ +} while (0); + + +#else +#define IRQ_LOG_PRINTER(irq, ppb, logT) +#endif + +#define SUPPORT_MAX_IRQ 32 +typedef struct { + spinlock_t SpinLockIspRef; + spinlock_t SpinLockIsp; + /* currently, IRQ and IRQ_D share the same ISR , so share the same key,IRQ. */ + spinlock_t SpinLockIrq[_IRQ_MAX]; + spinlock_t SpinLockHold; + spinlock_t SpinLockRTBC; + spinlock_t SpinLockClock; + wait_queue_head_t WaitQueueHead; + /* wait_queue_head_t* WaitQHeadList; */ + volatile wait_queue_head_t WaitQHeadList[SUPPORT_MAX_IRQ]; + struct work_struct ScheduleWorkVD; + struct work_struct ScheduleWorkEXPDONE; + MUINT32 UserCount; + MUINT32 DebugMask; + MINT32 IrqNum; + ISP_IRQ_INFO_STRUCT IrqInfo; + ISP_HOLD_INFO_STRUCT HoldInfo; + ISP_BUF_INFO_STRUCT BufInfo; + ISP_TIME_LOG_STRUCT TimeLog; + ISP_CALLBACK_STRUCT Callback[ISP_CALLBACK_AMOUNT]; +} ISP_INFO_STRUCT; + +static struct tasklet_struct isp_tasklet; + +static volatile MBOOL bSlowMotion = MFALSE; +static volatile MBOOL bRawEn = MFALSE; +static volatile MBOOL bRawDEn = MFALSE; + + +static ISP_INFO_STRUCT IspInfo; + +volatile MUINT32 PrvAddr[_ChannelMax] = { 0 }; + +/*MCLK counter*/ +static MINT32 mMclk1User; +static MINT32 mMclk2User; +static MINT32 mMclk3User; +/********************************************** +************************************************/ +#ifdef T_STAMP_2_0 +#define SlowMotion 100 +typedef struct { + volatile unsigned long long T_ns; /* 1st frame start time, accurency in us,unit in ns */ + unsigned long interval_us; /* unit in us */ + unsigned long compensation_us; + MUINT32 fps; + MUINT32 fcnt; +} T_STAMP; + +static T_STAMP m_T_STAMP = { 0 }; +#endif + +/******************************************************************************* +* +********************************************************************************/ +/* test flag */ +#define ISP_KERNEL_MOTIFY_SINGAL_TEST +#ifdef ISP_KERNEL_MOTIFY_SINGAL_TEST +/*** Linux signal test ***/ +#include +#include +#include +#include /* siginfo */ +#include /* rcu_read_lock */ +#include /* find_task_by_pid_type */ +#include +#include + +/* js_test */ +#define __tcmfunc + + +#define SIG_TEST 44 /* we choose 44 as our signal number (real-time signals are in the range of 33 to 64) */ + +struct siginfo info; +struct task_struct *t; + + +int getTaskInfo(pid_t pid) +{ + /* send the signal */ + memset(&info, 0, sizeof(struct siginfo)); + info.si_signo = SIG_TEST; + info.si_code = SI_QUEUE; /* this is bit of a trickery: SI_QUEUE is normally used by */ + /* sigqueue from user space, */ + /* and kernel space should use SI_KERNEL. But if SI_KERNEL is used the real_time data */ + /* is not delivered to the user space signal handler function. */ + info.si_int = 1234; /* real time signals may have 32 bits of data. */ + + rcu_read_lock(); + + t = find_task_by_vpid(pid); + /* t = find_task_by_pid_type(PIDTYPE_PID, g_pid); //find the task_struct associated with this pid */ + if (t == NULL) { + LOG_DBG("no such pid"); + rcu_read_unlock(); + return -ENODEV; + } + rcu_read_unlock(); + + return 0; +} + +int sendSignal(void) +{ + int ret = 0; + + ret = send_sig_info(SIG_TEST, &info, t); /* send the signal */ + if (ret < 0) { + LOG_DBG("error sending signal"); + return ret; + } + return ret; +} + +/*** Linux signal test ***/ + +#endif /* ISP_KERNEL_MOTIFY_SINGAL_TEST */ + +/******************************************************************************* +* +********************************************************************************/ +static inline MUINT32 ISP_MsToJiffies(MUINT32 Ms) +{ + MUINT32 ret; + + ret = (Ms * HZ + 512) >> 10; + return ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static inline MUINT32 ISP_UsToJiffies(MUINT32 Us) +{ + MUINT32 ret; + + ret = ((Us / 1000) * HZ + 512) >> 10; + return ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static inline MUINT32 ISP_GetIRQState(eISPIrq eIrq, MUINT32 type, MUINT32 userNumber, MUINT32 stus) +{ + MUINT32 ret; + unsigned long flags; /* old: MUINT32 flags;*//* FIX to avoid build warning */ + + /* */ + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + ret = (IspInfo.IrqInfo.Status[userNumber][type] & stus); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* */ + return ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static inline MUINT32 ISP_GetEDBufQueWaitDequeState(MINT32 idx) +{ + MUINT32 ret = MFALSE; + /* */ + spin_lock(&(SpinLockEDBufQueList)); + if (P2_EDBUF_RingList[idx].bufSts == ISP_ED_BUF_STATE_RUNNING) + ret = MTRUE; + + spin_unlock(&(SpinLockEDBufQueList)); + /* */ + return ret; +} + +static inline MUINT32 ISP_GetEDBufQueWaitFrameState(MINT32 idx) +{ + MUINT32 ret = MFALSE; + /* */ + spin_lock(&(SpinLockEDBufQueList)); + if (P2_EDBUF_MgrList[idx].dequedNum == P2_EDBUF_MgrList[idx].frameNum) + ret = MTRUE; + + spin_unlock(&(SpinLockEDBufQueList)); + /* */ + return ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static inline MUINT32 ISP_JiffiesToMs(MUINT32 Jiffies) +{ + MUINT32 ret; + + ret = (Jiffies * 1000) / HZ; + return ret; +} + + +/******************************************************************************* +* +********************************************************************************/ +static MUINT32 ISP_DumpDmaDeepDbg(void) +{ + if (g_bDmaERR_p1) { + g_DmaErr_p1[0] = (MUINT32) ISP_RD32(ISP_ADDR + 0x356c); + g_DmaErr_p1[1] = (MUINT32) ISP_RD32(ISP_ADDR + 0x3570); + g_DmaErr_p1[2] = (MUINT32) ISP_RD32(ISP_ADDR + 0x3574); + g_DmaErr_p1[3] = (MUINT32) ISP_RD32(ISP_ADDR + 0x3578); + g_DmaErr_p1[4] = (MUINT32) ISP_RD32(ISP_ADDR + 0x357C); + g_DmaErr_p1[5] = (MUINT32) ISP_RD32(ISP_ADDR + 0x358c); + g_DmaErr_p1[6] = (MUINT32) ISP_RD32(ISP_ADDR + 0x3590); + g_DmaErr_p1[7] = (MUINT32) ISP_RD32(ISP_ADDR + 0x3594); + g_DmaErr_p1[8] = (MUINT32) ISP_RD32(ISP_ADDR + 0x3598); + g_DmaErr_p1[9] = (MUINT32) ISP_RD32(ISP_ADDR + 0x359c); + g_DmaErr_p1[10] = (MUINT32) ISP_RD32(ISP_ADDR + 0x35a0); + LOG_ERR + ("IMGI:0x%x,BPCI:0x%x,LSCI=0x%x,UFDI=0x%x,LCEI=0x%x,imgo=0x%x,rrzo:0x%x,lcso:0x%x,esfko:0x%x,aao:0x%x,ufeo:0x%x", + g_DmaErr_p1[0], g_DmaErr_p1[1], g_DmaErr_p1[2], g_DmaErr_p1[3], g_DmaErr_p1[4], + g_DmaErr_p1[5], g_DmaErr_p1[6], g_DmaErr_p1[7], g_DmaErr_p1[8], g_DmaErr_p1[9], + g_DmaErr_p1[10]); + g_bDmaERR_p1 = MFALSE; + } + if (g_bDmaERR_p1_d) { + g_DmaErr_p1[11] = (MUINT32) ISP_RD32(ISP_ADDR + 0x35bc); + g_DmaErr_p1[12] = (MUINT32) ISP_RD32(ISP_ADDR + 0x35c0); + g_DmaErr_p1[13] = (MUINT32) ISP_RD32(ISP_ADDR + 0x35c4); + g_DmaErr_p1[14] = (MUINT32) ISP_RD32(ISP_ADDR + 0x35c8); + g_DmaErr_p1[15] = (MUINT32) ISP_RD32(ISP_ADDR + 0x35cc); + g_DmaErr_p1[16] = (MUINT32) ISP_RD32(ISP_ADDR + 0x35d0); + g_DmaErr_p1[17] = (MUINT32) ISP_RD32(ISP_ADDR + 0x35d4); + LOG_ERR + ("BPCI_D:0x%x,LSCI_D:0x%x,IMGO_D=0x%x,RRZO_D=0x%x,LSCO_D=0x%x,AFO_D=0x%x,AAO_D:0x%x", + g_DmaErr_p1[11], g_DmaErr_p1[12], g_DmaErr_p1[13], g_DmaErr_p1[14], + g_DmaErr_p1[15], g_DmaErr_p1[16], g_DmaErr_p1[17]); + g_bDmaERR_p1_d = MFALSE; + } +#if 0 + if (g_bDmaERR_p2) { + LOG_ERR + ("vipi:0x%x,VIPI:0x%x,VIP2I=0x%x,VIP3I=0x%x,MFBO=0x%x,IMG3BO=0x%x,IMG3CO:0x%x,IMG2O:0x%x,IMG3O:0x%x,FEO:0x%x", + ISP_RD32(ISP_ADDR + 0x3574), + ISP_RD32(ISP_ADDR + 0x3580), + ISP_RD32(ISP_ADDR + 0x3584), + ISP_RD32(ISP_ADDR + 0x3588), + ISP_RD32(ISP_ADDR + 0x35a4), + ISP_RD32(ISP_ADDR + 0x35a8), + ISP_RD32(ISP_ADDR + 0x35ac), + ISP_RD32(ISP_ADDR + 0x35b0), + ISP_RD32(ISP_ADDR + 0x35b4), + ISP_RD32(ISP_ADDR + 0x35b8)); + g_bDmaERR_p2 = MFALSE; + } + + if (g_bDmaERR_deepDump) { + ISP_WR32((ISP_ADDR + 0x160), 0x0); + ISP_WR32((ISP_ADDR + 0x35f4), 0x1E); + LOG_ERR("imgi_debug_0 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x11E); + LOG_ERR("imgi_debug_1 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x21E); + LOG_ERR("imgi_debug_2 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x31E); + LOG_ERR("imgi_debug_3 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + /* vipi */ + ISP_WR32((ISP_ADDR + 0x35f4), 0x41E); + LOG_ERR("vipi_debug_0 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x51E); + LOG_ERR("vipi_debug_1 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x61E); + LOG_ERR("vipi_debug_2 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x71E); + LOG_ERR("vipi_debug_3 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + /* imgo */ + ISP_WR32((ISP_ADDR + 0x35f4), 0x81E); + LOG_ERR("imgo_debug_0 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x91E); + LOG_ERR("imgo_debug_1 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0xa1E); + LOG_ERR("imgo_debug_2 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0xb1E); + LOG_ERR("imgo_debug_3 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + /* imgo_d */ + ISP_WR32((ISP_ADDR + 0x35f4), 0xc1E); + LOG_ERR("imgo_d_debug_0 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0xd1E); + LOG_ERR("imgo_d_debug_1 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0xe1E); + LOG_ERR("imgo_d_debug_2 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0xf1E); + LOG_ERR("imgo_d_debug_3 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + /* rrzo */ + ISP_WR32((ISP_ADDR + 0x35f4), 0x101E); + LOG_ERR("rrzo_debug_0 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x111E); + LOG_ERR("rrzo_debug_1 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x121E); + LOG_ERR("rrzo_debug_2 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x131E); + LOG_ERR("rrzo_debug_3 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + /* rrzo_d */ + ISP_WR32((ISP_ADDR + 0x35f4), 0x151E); + LOG_ERR("rrzo_d_debug_0 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x161E); + LOG_ERR("rrzo_d_debug_1 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x171E); + LOG_ERR("rrzo_d_debug_2 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x181E); + LOG_ERR("rrzo_d_debug_3 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + /* img3o */ + ISP_WR32((ISP_ADDR + 0x35f4), 0x181E); + LOG_ERR("img3o_debug_0 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x191E); + LOG_ERR("img3o_debug_1 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x1a1E); + LOG_ERR("img3o_debug_2 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x1b1E); + LOG_ERR("img3o_debug_3 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + /* img2o */ + ISP_WR32((ISP_ADDR + 0x35f4), 0x1c1E); + LOG_ERR("img3o_debug_0 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x1d1E); + LOG_ERR("img3o_debug_1 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x1e1E); + LOG_ERR("img3o_debug_2 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + ISP_WR32((ISP_ADDR + 0x35f4), 0x1f1E); + LOG_ERR("img3o_debug_3 = 0x%x\n", ISP_RD32(ISP_ADDR + 0x164)); + g_bDmaERR_deepDump = MFALSE; + } +#endif + + return 0; +} + +#define RegDump(start, end) {\ + MUINT32 i;\ + for (i = start; i <= end; i += 0x10) {\ + LOG_ERR("[0x%08X %08X],[0x%08X %08X],[0x%08X %08X],[0x%08X %08X]",\ + (unsigned int)(ISP_TPIPE_ADDR + i), (unsigned int)ISP_RD32(ISP_ADDR + i),\ + (unsigned int)(ISP_TPIPE_ADDR + i+0x4), (unsigned int)ISP_RD32(ISP_ADDR + i+0x4),\ + (unsigned int)(ISP_TPIPE_ADDR + i+0x8), (unsigned int)ISP_RD32(ISP_ADDR + i+0x8),\ + (unsigned int)(ISP_TPIPE_ADDR + i+0xc), (unsigned int)ISP_RD32(ISP_ADDR + i+0xc));\ + } \ +} + +MBOOL ISP_chkModuleSetting(void) +{ + /*check the setting; */ + MUINT32 cam_ctrl_en_p1; /*4004 */ + MUINT32 cam_ctrl_sel_pl; /*4034 */ + MUINT32 cam_bmx_crop; /*4E14 */ + MUINT32 cam_bmx_vsize; /*4E18 */ + + MUINT32 cam_tg1_vf_con; /*4414 */ + MUINT32 cam_tg2_vf_con; /*6414 */ + + MUINT32 grab_width; + MUINT32 grab_height; + + MUINT32 cam_tg1_sen_grab_pxl; /*4418 */ + MUINT32 cam_tg1_sen_grab_lin; /*441C */ + + MUINT32 cam_tg2_sen_grab_pxl; /*6418 */ + MUINT32 cam_tg2_sen_grab_lin; /*641C */ + + + MUINT32 bmx_width; + MUINT32 bmx_height; + + MUINT32 sgg_sel; + MUINT32 eis_sel; + + MBOOL bmx_enable; + MUINT32 i; + + cam_ctrl_en_p1 = ISP_RD32(ISP_ADDR + 0x4); + bmx_enable = (cam_ctrl_en_p1 >> 11) & 0x01; + cam_ctrl_sel_pl = ISP_RD32(ISP_ADDR + 0x34); + sgg_sel = (cam_ctrl_sel_pl >> 1) & 0x03; + eis_sel = (cam_ctrl_sel_pl >> 10) & 0x03; + + cam_bmx_crop = ISP_RD32(ISP_ADDR + 0xE14); + cam_bmx_vsize = ISP_RD32(ISP_ADDR + 0xE18); + bmx_width = ((cam_bmx_crop >> 16) & 0x1fff) - (cam_bmx_crop & 0x1fff); + bmx_height = (cam_bmx_vsize & 0x1fff); + + cam_tg1_sen_grab_pxl = ISP_RD32(ISP_ADDR + 0x418); + cam_tg1_sen_grab_lin = ISP_RD32(ISP_ADDR + 0x41C); + + cam_tg2_sen_grab_pxl = ISP_RD32(ISP_ADDR + 0x2418); + cam_tg2_sen_grab_lin = ISP_RD32(ISP_ADDR + 0x241C); + cam_tg1_vf_con = ISP_RD32(ISP_ADDR + 0x414); + cam_tg2_vf_con = ISP_RD32(ISP_ADDR + 0x2414); + + + if (cam_tg1_vf_con & 0x01) { + /*Check FLK setting */ + MUINT32 cam_flk_con; /*4770 */ + MUINT32 cam_flk_ofst; /*4774 */ + MUINT32 cam_flk_size; /*4778 */ + MUINT32 cam_flk_num; /*477C */ + + MUINT32 cam_esfko_xsize; /*7370 */ + + MUINT32 FLK_OFST_X; + MUINT32 FLK_OFST_Y; + MUINT32 FLK_SIZE_X; + MUINT32 FLK_SIZE_Y; + MUINT32 FLK_NUM_X; + MUINT32 FLK_NUM_Y; + MUINT32 sggmux_h_size; + MUINT32 sggmux_v_size; + + MUINT32 esfko_xsize; + + /*Check AF setting */ + MUINT32 cam_af_con; /*46B0 */ + MUINT32 cam_af_winx_1; /*46B4 */ + MUINT32 cam_af_winx_2; /*46B8 */ + MUINT32 cam_af_winx_3; /*46BC */ + MUINT32 cam_af_winy_1; /*46C0 */ + MUINT32 cam_af_winy_2; /*46C4 */ + MUINT32 cam_af_winy_3; /*46C8 */ + MUINT32 cam_af_size; /*46CC */ + + MUINT32 cam_af_flt_1; /*46D4 */ + MUINT32 cam_af_flt_2; /*46D8 */ + MUINT32 cam_af_flt_3; /*46DC */ + MUINT32 cam_af_th; /*46E0 */ + MUINT32 cam_af_flo_win_1; /*46E4 */ + MUINT32 cam_af_flo_size_1; /*46E8 */ + MUINT32 cam_af_flo_win_2; /*46EC */ + MUINT32 cam_af_flo_size_2; /*46F0 */ + MUINT32 cam_af_flo_win_3; /*46F4 */ + MUINT32 cam_af_flo_size_3; /*46F8 */ + MUINT32 cam_af_flo_th; /*46FC */ + MUINT32 cam_af_image_size; /*4700 */ + + + MUINT32 AF_WIN_WD; + MUINT32 AF_WIN_HT; + MUINT32 AF_WINX_0; + MUINT32 AF_WINX_1; + MUINT32 AF_WINX_2; + MUINT32 AF_WINX_3; + MUINT32 AF_WINX_4; + MUINT32 AF_WINX_5; +/* MUINT32 AF_WINX_6;*/ + + MUINT32 AF_WINY_0; + MUINT32 AF_WINY_1; + MUINT32 AF_WINY_2; + MUINT32 AF_WINY_3; + MUINT32 AF_WINY_4; + MUINT32 AF_WINY_5; +/* MUINT32 AF_WINY_6;*/ + + MUINT32 AF_FLO_WINX_1; + MUINT32 AF_FLO_WINY_1; + MUINT32 AF_FLO_WINX_2; + MUINT32 AF_FLO_WINY_2; + MUINT32 AF_FLO_WINX_3; + MUINT32 AF_FLO_WINY_3; + + MUINT32 AF_FLO_WD_1; + MUINT32 AF_FLO_HT_1; + MUINT32 AF_FLO_WD_2; + MUINT32 AF_FLO_HT_2; + MUINT32 AF_FLO_WD_3; + MUINT32 AF_FLO_HT_3; + + MUINT32 AF_IMAGE_WD; + MUINT32 AF_Img_WD; + MUINT32 AF_DECI; + MUINT32 AF_InputWidth; + + MUINT32 AF_LeftOverWidth; + + MUINT32 cam_aao_xsize; /*7390 */ + MUINT32 cam_aao_ysize; /*7394 */ + MUINT32 cam_awb_win_num; /*45BC */ + MUINT32 cam_ae_hst_ctl; /*4650 */ + + MUINT32 AAO_XSIZE; + MUINT32 AWB_W_HNUM; + MUINT32 AWB_W_VNUM; + MUINT32 histogramen_num; + + MUINT32 cam_awb_win_org; /*45B0 */ + MUINT32 cam_awb_win_pit; /*45B8 */ + + MUINT32 AAO_InWidth; + MUINT32 AAO_InHeight; + MUINT32 AWB_W_HPIT; + MUINT32 AWB_W_VPIT; + MUINT32 AWB_W_HORG; + MUINT32 AWB_W_VORG; + + MUINT32 rrz_out_width; + MUINT32 rrz_out_height; + MUINT32 scenario; + + MUINT32 cam_rrz_out_img; /*47A8 */ + MUINT32 cam_ctl_scenario; /*4024 */ + + MUINT32 EIS_RP_VOFST; + MUINT32 EIS_RP_HOFST; + MUINT32 EIS_WIN_VSIZE; + MUINT32 EIS_WIN_HSIZE; + + MUINT32 EIS_OP_HORI; + MUINT32 EIS_OP_VERT; + + MUINT32 EIS_NUM_HRP; + MUINT32 EIS_NUM_VRP; + MUINT32 EIS_NUM_HWIN; + MUINT32 EIS_NUM_VWIN; + + MUINT32 EIS_IMG_WIDTH; + MUINT32 EIS_IMG_HEIGHT; + MUINT32 EISO_XSIZE; + + MBOOL bError; + + MUINT32 CAM_EIS_PREP_ME_CTRL1; /*4DC0 */ + MUINT32 CAM_EIS_MB_OFFSET; /*4DD0 */ + MUINT32 CAM_EIS_MB_INTERVAL; /*4DD4 */ + MUINT32 CAM_EIS_IMAGE_CTRL; /*4DE0 */ + + LOG_INF("ISP chk TG1"); + + grab_width = + ((cam_tg1_sen_grab_pxl >> 16) & 0x7fff) - (cam_tg1_sen_grab_pxl & 0x7fff); + grab_height = + ((cam_tg1_sen_grab_lin >> 16) & 0x1fff) - (cam_tg1_sen_grab_lin & 0x1fff); + + cam_esfko_xsize = ISP_RD32(ISP_ADDR + 0x3370); + esfko_xsize = cam_esfko_xsize & 0xffff; + + cam_flk_con = ISP_RD32(ISP_ADDR + 0x770); + cam_flk_ofst = ISP_RD32(ISP_ADDR + 0x774); + cam_flk_size = ISP_RD32(ISP_ADDR + 0x778); + cam_flk_num = ISP_RD32(ISP_ADDR + 0x77C); + FLK_OFST_X = cam_flk_ofst & 0xFFF; + FLK_OFST_Y = (cam_flk_ofst >> 16) & 0xFFF; + FLK_SIZE_X = cam_flk_size & 0xFFF; + FLK_SIZE_Y = (cam_flk_size >> 16) & 0xFFF; + FLK_NUM_X = cam_flk_num & 0x7; + FLK_NUM_Y = (cam_flk_num >> 4) & 0x7; + /*1. The window size must be multiples of */ + /*2. horizontally and vertically */ + /*5. CAM_FLK_SIZE.FLK_SIZE_X.value can't be 0 */ + /*6. CAM_FLK_SIZE.FLK_SIZE_Y.value can't be 0 */ + if ((FLK_SIZE_X % 2 != 0) || (FLK_SIZE_Y % 2 != 0) + || (FLK_SIZE_X == 0) || (FLK_SIZE_Y == 0)) { + /* Error */ + LOG_INF + ("HwRWCtrl:: Flicker Error: The window size must be multiples of 2. horizontally and vertically!!"); + LOG_INF + ("HwRWCtrl:: Flicker Error: CAM_FLK_SIZE.FLK_SIZE_X(%d) and CAM_FLK_SIZE.FLK_SIZE_Y(%d) value can't be 0!!", + FLK_SIZE_X, FLK_SIZE_Y); + } + if (MTRUE == bmx_enable) { + sggmux_h_size = bmx_width; + sggmux_v_size = bmx_height; + } else { + sggmux_h_size = grab_width; + sggmux_v_size = grab_height; + } + /*(CAM_FLK_NUM.FLK_NUM_X.value * CAM_FLK_SIZE.FLK_SIZE_X.value) + CAM_FLK_OFST.FLK_OFST_X.value <= sggmux_h_size.value */ + /*(CAM_FLK_NUM.FLK_NUM_Y.value * CAM_FLK_SIZE.FLK_SIZE_Y.value) + CAM_FLK_OFST.FLK_OFST_Y.value <= sggmux_v_size.value */ + if ((((FLK_NUM_X * FLK_SIZE_X) + FLK_OFST_X) > sggmux_h_size) || + (((FLK_NUM_Y * FLK_SIZE_Y) + FLK_OFST_Y) > sggmux_v_size)) { + /*Error */ + LOG_INF + ("HwRWCtrl:: Flicker Error: bmx_enable(%d), sgg_sel(%d), grab_width(%d), grab_height(%d), bmx_width(%d), bmx_height(%d)!!", + bmx_enable, sgg_sel, grab_width, grab_height, bmx_width, bmx_height); + LOG_INF + ("HwRWCtrl:: Flicker Error: (CAM_FLK_NUM.FLK_NUM_X.value(%d) * CAM_FLK_SIZE.FLK_SIZE_X.value(%d)) + CAM_FLK_OFST.FLK_OFST_X.value(%d) <= sggmux_h_size.value(%d)!!", + FLK_NUM_X, FLK_SIZE_X, FLK_OFST_X, sggmux_h_size); + LOG_INF + ("HwRWCtrl:: Flicker Error: (CAM_FLK_NUM.FLK_NUM_Y.value(%d) * CAM_FLK_SIZE.FLK_SIZE_Y.value(%d)) + CAM_FLK_OFST.FLK_OFST_Y.value(%d) <= sggmux_v_size.value(%d)!!", + FLK_NUM_Y, FLK_SIZE_Y, FLK_OFST_Y, sggmux_v_size); + } + + /*4. flko_xs == ((CAM_FLK_NUM.FLK_NUM_X.value * CAM_FLK_NUM.FLK_NUM_Y.value * CAM_FLK_SIZE.FLK_SIZE_Y.value * 2) - 1) */ + if (esfko_xsize != ((FLK_NUM_X * FLK_NUM_Y * FLK_SIZE_Y * 2) - 1)) { + /*Error */ + LOG_INF + ("HwRWCtrl:: Flicker Error: flko_xs(%d) must be equal ((CAM_FLK_NUM.FLK_NUM_X.value(%d) * CAM_FLK_NUM.FLK_NUM_Y.value(%d) * CAM_FLK_SIZE.FLK_SIZE_Y.value(%d) * 2) - 1)!!", + esfko_xsize, FLK_NUM_X, FLK_NUM_Y, FLK_SIZE_Y); + } +#if 0 + /*Check AF setting */ + MUINT32 cam_af_con; /*46B0 */ + MUINT32 cam_af_winx_1; /*46B4 */ + MUINT32 cam_af_winx_2; /*46B8 */ + MUINT32 cam_af_winx_3; /*46BC */ + MUINT32 cam_af_winy_1; /*46C0 */ + MUINT32 cam_af_winy_2; /*46C4 */ + MUINT32 cam_af_winy_3; /*46C8 */ + MUINT32 cam_af_size; /*46CC */ + + MUINT32 cam_af_flt_1; /*46D4 */ + MUINT32 cam_af_flt_2; /*46D8 */ + MUINT32 cam_af_flt_3; /*46DC */ + MUINT32 cam_af_th; /*46E0 */ + MUINT32 cam_af_flo_win_1; /*46E4 */ + MUINT32 cam_af_flo_size_1; /*46E8 */ + MUINT32 cam_af_flo_win_2; /*46EC */ + MUINT32 cam_af_flo_size_2; /*46F0 */ + MUINT32 cam_af_flo_win_3; /*46F4 */ + MUINT32 cam_af_flo_size_3; /*46F8 */ + MUINT32 cam_af_flo_th; /*46FC */ + MUINT32 cam_af_image_size; /*4700 */ + + + MUINT32 AF_WIN_WD; + MUINT32 AF_WIN_HT; + MUINT32 AF_WINX_0; + MUINT32 AF_WINX_1; + MUINT32 AF_WINX_2; + MUINT32 AF_WINX_3; + MUINT32 AF_WINX_4; + MUINT32 AF_WINX_5; +/* MUINT32 AF_WINX_6;*/ + + MUINT32 AF_WINY_0; + MUINT32 AF_WINY_1; + MUINT32 AF_WINY_2; + MUINT32 AF_WINY_3; + MUINT32 AF_WINY_4; + MUINT32 AF_WINY_5; +/* MUINT32 AF_WINY_6;*/ + + MUINT32 AF_FLO_WINX_1; + MUINT32 AF_FLO_WINY_1; + MUINT32 AF_FLO_WINX_2; + MUINT32 AF_FLO_WINY_2; + MUINT32 AF_FLO_WINX_3; + MUINT32 AF_FLO_WINY_3; + + MUINT32 AF_FLO_WD_1; + MUINT32 AF_FLO_HT_1; + MUINT32 AF_FLO_WD_2; + MUINT32 AF_FLO_HT_2; + MUINT32 AF_FLO_WD_3; + MUINT32 AF_FLO_HT_3; + + MUINT32 AF_IMAGE_WD; + MUINT32 AF_DECI; + MUINT32 AF_InputWidth; + + MUINT32 AF_LeftOverWidth; + + MUINT32 cam_aao_xsize; /*7390 */ + MUINT32 cam_aao_ysize; /*7394 */ + MUINT32 cam_awb_win_num; /*45BC */ + MUINT32 cam_ae_hst_ctl; /*4650 */ + + MUINT32 AAO_XSIZE; + MUINT32 AWB_W_HNUM; + MUINT32 AWB_W_VNUM; + MUINT32 histogramen_num; + + MUINT32 cam_awb_win_org; /*45B0 */ + MUINT32 cam_awb_win_pit; /*45B8 */ + + MUINT32 AAO_InWidth; + MUINT32 AAO_InHeight; + MUINT32 AWB_W_HPIT; + MUINT32 AWB_W_VPIT; + MUINT32 AWB_W_HORG; + MUINT32 AWB_W_VORG; + + MUINT32 rrz_out_width; + MUINT32 rrz_out_height; + MUINT32 scenario; + + MUINT32 cam_rrz_out_img; /*47A8 */ + MUINT32 cam_ctl_scenario; /*4024 */ + + MUINT32 EIS_RP_VOFST; + MUINT32 EIS_RP_HOFST; + MUINT32 EIS_WIN_VSIZE; + MUINT32 EIS_WIN_HSIZE; + + MUINT32 EIS_OP_HORI; + MUINT32 EIS_OP_VERT; + + MUINT32 EIS_NUM_HRP; + MUINT32 EIS_NUM_VRP; + MUINT32 EIS_NUM_HWIN; + MUINT32 EIS_NUM_VWIN; + + MUINT32 EIS_IMG_WIDTH; + MUINT32 EIS_IMG_HEIGHT; + MUINT32 EISO_XSIZE; + + MBOOL bError; + + MUINT32 CAM_EIS_PREP_ME_CTRL1; /*4DC0 */ + MUINT32 CAM_EIS_MB_OFFSET; /*4DD0 */ + MUINT32 CAM_EIS_MB_INTERVAL; /*4DD4 */ + MUINT32 CAM_EIS_IMAGE_CTRL; /*4DE0 */ +#endif + cam_af_con = ISP_RD32(ISP_ADDR + 0x6B0); + cam_af_winx_1 = ISP_RD32(ISP_ADDR + 0x6B4); + cam_af_winx_2 = ISP_RD32(ISP_ADDR + 0x6B8); + cam_af_winx_3 = ISP_RD32(ISP_ADDR + 0x6BC); + cam_af_winy_1 = ISP_RD32(ISP_ADDR + 0x6c0); + cam_af_winy_2 = ISP_RD32(ISP_ADDR + 0x6c4); + cam_af_winy_3 = ISP_RD32(ISP_ADDR + 0x6c8); + cam_af_size = ISP_RD32(ISP_ADDR + 0x6cc); + + cam_af_flt_1 = ISP_RD32(ISP_ADDR + 0x6D4); /*46D4 */ + cam_af_flt_2 = ISP_RD32(ISP_ADDR + 0x6D8); /*46D8 */ + cam_af_flt_3 = ISP_RD32(ISP_ADDR + 0x6DC); /*46DC */ + cam_af_th = ISP_RD32(ISP_ADDR + 0x6E0); /*46E0 */ + cam_af_flo_win_1 = ISP_RD32(ISP_ADDR + 0x6E4); /*46E4 */ + cam_af_flo_size_1 = ISP_RD32(ISP_ADDR + 0x6E8); /*46E8 */ + cam_af_flo_win_2 = ISP_RD32(ISP_ADDR + 0x6EC); /*46EC */ + cam_af_flo_size_2 = ISP_RD32(ISP_ADDR + 0x6F0); /*46F0 */ + cam_af_flo_win_3 = ISP_RD32(ISP_ADDR + 0x6F4); /*46F4 */ + cam_af_flo_size_3 = ISP_RD32(ISP_ADDR + 0x6F8); /*46F8 */ + cam_af_flo_th = ISP_RD32(ISP_ADDR + 0x6FC); /*46FC */ + cam_af_image_size = ISP_RD32(ISP_ADDR + 0x700); /*4700 */ + + AF_WINX_0 = (cam_af_winx_1 & 0x1fff); + AF_WINX_1 = ((cam_af_winx_1 >> 16) & 0x1fff); + AF_WINX_2 = (cam_af_winx_2 & 0x1fff); + AF_WINX_3 = ((cam_af_winx_2 >> 16) & 0x1fff); + AF_WINX_4 = (cam_af_winx_3 & 0x1fff); + AF_WINX_5 = ((cam_af_winx_3 >> 16) & 0x1fff); + + AF_WINY_0 = (cam_af_winy_1 & 0x1fff); + AF_WINY_1 = ((cam_af_winy_1 >> 16) & 0x1fff); + AF_WINY_2 = (cam_af_winy_2 & 0x1fff); + AF_WINY_3 = ((cam_af_winy_2 >> 16) & 0x1fff); + AF_WINY_4 = (cam_af_winy_3 & 0x1fff); + AF_WINY_5 = ((cam_af_winy_3 >> 16) & 0x1fff); + + AF_FLO_WINX_1 = (cam_af_flo_win_1 & 0x1fff); + AF_FLO_WINY_1 = ((cam_af_flo_win_1 >> 16) & 0x1fff); + AF_FLO_WINX_2 = (cam_af_flo_win_2 & 0x1fff); + AF_FLO_WINY_2 = ((cam_af_flo_win_2 >> 16) & 0x1fff); + AF_FLO_WINX_3 = (cam_af_flo_win_3 & 0x1fff); + AF_FLO_WINY_3 = ((cam_af_flo_win_3 >> 16) & 0x1fff); + + AF_FLO_WD_1 = (cam_af_flo_size_1 & 0xfff); + AF_FLO_HT_1 = ((cam_af_flo_size_1 >> 16) & 0xfff); + AF_FLO_WD_2 = (cam_af_flo_size_2 & 0xfff); + AF_FLO_HT_2 = ((cam_af_flo_size_2 >> 16) & 0xfff); + AF_FLO_WD_3 = (cam_af_flo_size_3 & 0xfff); + AF_FLO_HT_3 = ((cam_af_flo_size_3 >> 16) & 0xfff); + + AF_IMAGE_WD = cam_af_image_size & 0x1fff; + AF_Img_WD = AF_IMAGE_WD; + AF_DECI = cam_af_con & 0x03; + + /*1. The min horizontal window size is 8. (AF_WIN_WD/AF_FLO_WD_x) */ + /*2. The min vertical window size is 4. (AF_WIN_HT/AF_FLO_HT_x) */ + AF_WIN_WD = (cam_af_size & 0x7ff); + AF_WIN_HT = ((cam_af_size >> 16) & 0x7ff); + if ((AF_WIN_WD < 8) || (AF_FLO_WD_1 < 8) || (AF_FLO_WD_2 < 8) || (AF_FLO_WD_3 < 8) + || (AF_WIN_HT < 4) || (AF_FLO_HT_1 < 4) || (AF_FLO_HT_2 < 4) + || (AF_FLO_HT_3 < 4)) { + LOG_INF + ("HwRWCtrl:: AF Error: The min horizontal window size is 8. (AF_WIN_WD(%d), AF_FLO_WD_1(%d), AF_FLO_WD_2(%d), AF_FLO_WD_3(%d))!!", + AF_WIN_WD, AF_FLO_WD_1, AF_FLO_WD_2, AF_FLO_WD_3); + LOG_INF + ("HwRWCtrl:: AF Error: The min vertical window size is 4. (AF_WIN_HT(%d), AF_FLO_HT_1(%d), AF_FLO_HT_2(%d), AF_FLO_HT_3(%d))!!", + AF_WIN_HT, AF_FLO_HT_1, AF_FLO_HT_2, AF_FLO_HT_3); + } + /*3. The horizontal window start point and size must be multiples of 2 (AF_WINX_x/AF_FLO_WINX_x/AF_WIN_WD/AF_FLO_WD_x) */ + if (((AF_WINX_0 % 2) != 0) || ((AF_WINX_1 % 2) != 0) || ((AF_WINX_2 % 2) != 0) + || ((AF_WINX_3 % 2) != 0) || ((AF_WINX_4 % 2) != 0) || ((AF_WINX_5 % 2) != 0) + || ((AF_WINY_0 % 2) != 0) || ((AF_WINY_1 % 2) != 0) || ((AF_WINY_2 % 2) != 0) + || ((AF_WINY_3 % 2) != 0) || ((AF_WINY_4 % 2) != 0) || ((AF_WINY_5 % 2) != 0)) { + LOG_INF + ("HwRWCtrl:: AF Error: The horizontal window start point and size must be multiples of 2 !!"); + LOG_INF + ("HwRWCtrl:: AF Error: AF_WINX_0(%d)/AF_WINX_1(%d)/AF_WINX_2(%d)/AF_WINX_3(%d)/AF_WINX_4(%d)/AF_WINX_5(%d)!!", + AF_WINX_0, AF_WINX_1, AF_WINX_2, AF_WINX_3, AF_WINX_4, AF_WINX_5); + LOG_INF + ("HwRWCtrl:: AF Error: AF_WINY_0(%d)/AF_WINY_1(%d)/AF_WINY_2(%d)/AF_WINY_3(%d)/AF_WINY_4(%d)/AF_WINY_5(%d)!!", + AF_WINY_0, AF_WINY_1, AF_WINY_2, AF_WINY_3, AF_WINY_4, AF_WINY_5); + + } + /*10. Horizontal start position of floating window must be multiples of 2 */ + /*11. Horizontal size of floating window must be multiples of 2 */ + if (((AF_FLO_WINX_1 % 2) != 0) || ((AF_FLO_WINX_2 % 2) != 0) + || ((AF_FLO_WINX_3 % 2) != 0) + || ((AF_FLO_WINY_1 % 2) != 0) || ((AF_FLO_WINY_2 % 2) != 0) + || ((AF_FLO_WINY_3 % 2) != 0) + || ((AF_FLO_WD_1 % 2) != 0) || ((AF_FLO_WD_2 % 2) != 0) + || ((AF_FLO_WD_3 % 2) != 0) + || ((AF_FLO_HT_1 % 2) != 0) || ((AF_FLO_HT_2 % 2) != 0) + || ((AF_FLO_HT_3 % 2) != 0)) { + LOG_INF + ("HwRWCtrl:: AF Error: Horizontal start position of floating window must be multiples of 2!!"); + LOG_INF + ("HwRWCtrl:: AF Error: Horizontal size of floating window must be multiples of 2!!"); + LOG_INF + ("HwRWCtrl:: AF Error: AF_FLO_WINX_1(%d)/AF_FLO_WINX_2(%d)/AF_FLO_WINX_3(%d)!!", + AF_FLO_WINX_1, AF_FLO_WINX_2, AF_FLO_WINX_3); + LOG_INF + ("HwRWCtrl:: AF Error: AF_FLO_WD_1(%d)/AF_FLO_WD_2(%d)/AF_FLO_WD_3(%d)!!", + AF_FLO_WD_1, AF_FLO_WD_2, AF_FLO_WD_3); + LOG_INF + ("HwRWCtrl:: AF Error: AF_FLO_HT_1(%d)/AF_FLO_HT_2(%d)/AF_FLO_HT_3(%d)!!", + AF_FLO_HT_1, AF_FLO_HT_2, AF_FLO_HT_3); + } + /*5. Horizontal size of each normal window is limited to 510*2 (AF_WIN_WD) */ + /*6. Vertical size of each normal window is limited to 511*2 (AF_WIN_HT) */ + if ((AF_WIN_WD > 1020) || (AF_WIN_HT > 1022)) { + LOG_INF + ("HwRWCtrl:: AF Error: Horizontal size of each normal window is limited to 510*2 (AF_WIN_WD(%d))!!", + AF_WIN_WD); + LOG_INF + ("HwRWCtrl:: AF Error: Vertical size of each normal window is limited to 511*2 (AF_WIN_HT(%d))!!", + AF_WIN_HT); + } + + /*12. Maximum floating widow size is 4094x4095 */ + if ((AF_FLO_WD_1 > 4094) || (AF_FLO_WD_2 > 4094) || (AF_FLO_WD_3 > 4094) || + (AF_FLO_HT_1 > 4095) || (AF_FLO_HT_2 > 4095) || (AF_FLO_HT_3 > 4095)) + LOG_INF("HwRWCtrl:: AF Error: Maximum floating widow size is 4094x4095!!"); + + if (MTRUE == bmx_enable) { + if (sgg_sel == 1) + AF_InputWidth = bmx_width; + else { + AF_InputWidth = grab_width; + AF_Img_WD = (AF_IMAGE_WD << 1); + } + + /*18. If two_pixel mode, AF_DECI >= 1 */ + if (AF_DECI != 0) + LOG_INF("HwRWCtrl:: AF Error: If two_pixel mode, AF_DECI >= 1!!"); + /*Error */ + } else { + AF_InputWidth = grab_width; + } + + /*15. AF_IMAGE_WD must be the same as input frame width */ + if (AF_Img_WD != AF_InputWidth) { + LOG_INF + ("HwRWCtrl:: AF Error: bmx_enable(%d), sgg_sel(%d), bmx_width(%d), grab_width(%d)!!", + bmx_enable, sgg_sel, bmx_width, grab_width); + LOG_INF + ("HwRWCtrl:: AF Error: AF_IMAGE_WD(%d) must be the same as input frame width(%d)!!", + AF_Img_WD, AF_InputWidth); + } + /*16. "CAM_AF_WINX_x.AF_WINX_x + CAM_AF_SIZE.AF_WIN_WD <= input frame width" for a valid window */ + /*17. "CAM_AF_WINY_x.AF_WINY_x + CAM_AF_SIZE.AF_WIN_HT <= input frame height" for a valid window */ + + /*14. If AF window is aligned to image left/right boundary, minimum horizontal size should be larger than 24*(1<> 16) & 0xff; + histogramen_num = 0; + for (i = 0; i < 4; i++) { + if ((cam_ae_hst_ctl >> i) & 0x1) + histogramen_num += 1; + } + + if ((cam_aao_ysize + 1) != 1) + LOG_INF("Error HwRWCtrl::AAO_YSIZE(%d) must be equal 1 !!", + cam_aao_ysize); + if ((AAO_XSIZE + 1) != + (AWB_W_HNUM * AWB_W_VNUM * 5 + (histogramen_num << 8))) + LOG_INF + ("Error HwRWCtrl::AAO_XSIZE(%d) = AWB_W_HNUM(%d)*AWB_W_VNUM(%d)*5 + (how many histogram enable(%d)(AE_HST0/1/2/3_EN))*2*128 !!", + AAO_XSIZE, AWB_W_HNUM, AWB_W_VNUM, histogramen_num); + } +#if 0 + /*Check AWB setting */ + MUINT32 cam_awb_win_org; /*45B0 */ + MUINT32 cam_awb_win_pit; /*45B8 */ + + MUINT32 AAO_InWidth; + MUINT32 AAO_InHeight; + MUINT32 AWB_W_HPIT; + MUINT32 AWB_W_VPIT; + MUINT32 AWB_W_HORG; + MUINT32 AWB_W_VORG; +#endif + cam_awb_win_num = ISP_RD32(ISP_ADDR + 0x5BC); + cam_awb_win_pit = ISP_RD32(ISP_ADDR + 0x5B8); + cam_awb_win_org = ISP_RD32(ISP_ADDR + 0x5B0); + + if (MTRUE == bmx_enable) { + /*hbin_enable should be true under Twin mode. */ + AAO_InWidth = bmx_width / 2; + AAO_InHeight = bmx_height; + } else { + AAO_InWidth = grab_width; + AAO_InHeight = grab_height; + } + AWB_W_HNUM = (cam_awb_win_num & 0xff); + AWB_W_VNUM = ((cam_awb_win_num >> 16) & 0xff); + + AWB_W_HPIT = (cam_awb_win_pit & 0x1fff); + AWB_W_VPIT = ((cam_awb_win_pit >> 16) & 0x1fff); + + AWB_W_HORG = (cam_awb_win_org & 0x1fff); + AWB_W_VORG = ((cam_awb_win_org >> 16) & 0x1fff); + if (AAO_InWidth < (AWB_W_HNUM * AWB_W_HPIT + AWB_W_HORG)) { + /*Error */ + LOG_INF + ("Error HwRWCtrl:: bmx_enable(%d), bmx_width(%d), bmx_height(%d), grab_width(%d), grab_height(%d)!!", + bmx_enable, bmx_width, bmx_height, grab_width, grab_height); + LOG_INF + ("Error HwRWCtrl:: input frame width(%d) >= AWB_W_HNUM(%d) * AWB_W_HPIT(%d) + AWB_W_HORG(%d) !!", + AAO_InWidth, AWB_W_HNUM, AWB_W_HPIT, AWB_W_HORG); + } + if (AAO_InHeight < (AWB_W_VNUM * AWB_W_VPIT + AWB_W_VORG)) { + /*Error */ + LOG_INF + ("Error HwRWCtrl:: bmx_enable(%d), bmx_width(%d), bmx_height(%d), grab_width(%d), grab_height(%d)!!", + bmx_enable, bmx_width, bmx_height, grab_width, grab_height); + LOG_INF + ("Error HwRWCtrl:: input frame height(%d) >= AWB_W_VNUM(%d) * AWB_W_VPIT(%d) + AWB_W_VORG(%d) !!", + AAO_InHeight, AWB_W_VNUM, AWB_W_VPIT, AWB_W_VORG); + } + + /*Check EIS Setting */ +#if 0 + MUINT32 rrz_out_width; + MUINT32 rrz_out_height; + MUINT32 scenario; + + MUINT32 cam_rrz_out_img; /*47A8 */ + MUINT32 cam_ctl_scenario; /*4024 */ + + MUINT32 EIS_RP_VOFST; + MUINT32 EIS_RP_HOFST; + MUINT32 EIS_WIN_VSIZE; + MUINT32 EIS_WIN_HSIZE; + + MUINT32 EIS_OP_HORI; + MUINT32 EIS_OP_VERT; + + MUINT32 EIS_NUM_HRP; + MUINT32 EIS_NUM_VRP; + MUINT32 EIS_NUM_HWIN; + MUINT32 EIS_NUM_VWIN; + + MUINT32 EIS_IMG_WIDTH; + MUINT32 EIS_IMG_HEIGHT; + MUINT32 EISO_XSIZE; + + MBOOL bError = MFALSE; +#else + bError = MFALSE; +#endif + cam_ctl_scenario = ISP_RD32(ISP_ADDR + 0x24); + scenario = cam_ctl_scenario & 0x7; + + cam_rrz_out_img = ISP_RD32(ISP_ADDR + 0x7A8); + rrz_out_width = cam_rrz_out_img & 0x1fff; + rrz_out_height = (cam_rrz_out_img >> 16) & 0x1fff; + + EISO_XSIZE = (ISP_RD32(ISP_ADDR + 0x3360)) & 0x3ff; + +#if 0 + MUINT32 CAM_EIS_PREP_ME_CTRL1; /*4DC0 */ + MUINT32 CAM_EIS_MB_OFFSET; /*4DD0 */ + MUINT32 CAM_EIS_MB_INTERVAL; /*4DD4 */ + MUINT32 CAM_EIS_IMAGE_CTRL; /*4DE0 */ +#endif + CAM_EIS_PREP_ME_CTRL1 = ISP_RD32(ISP_ADDR + 0xDC0); + CAM_EIS_MB_OFFSET = ISP_RD32(ISP_ADDR + 0xDD0); + CAM_EIS_MB_INTERVAL = ISP_RD32(ISP_ADDR + 0xDD4); + CAM_EIS_IMAGE_CTRL = ISP_RD32(ISP_ADDR + 0xDE0); + + EIS_RP_VOFST = (CAM_EIS_MB_OFFSET) & 0xfff; + EIS_RP_HOFST = (CAM_EIS_MB_OFFSET >> 16) & 0xfff; + EIS_WIN_VSIZE = (CAM_EIS_MB_INTERVAL) & 0xfff; + EIS_WIN_HSIZE = (CAM_EIS_MB_INTERVAL >> 16) & 0xfff; + + EIS_OP_HORI = CAM_EIS_PREP_ME_CTRL1 & 0x7; + EIS_OP_VERT = (CAM_EIS_PREP_ME_CTRL1 >> 3) & 0x7; + + EIS_NUM_HRP = (CAM_EIS_PREP_ME_CTRL1 >> 8) & 0x1f; + EIS_NUM_VRP = (CAM_EIS_PREP_ME_CTRL1 >> 21) & 0xf; + EIS_NUM_HWIN = (CAM_EIS_PREP_ME_CTRL1 >> 25) & 0x7; + EIS_NUM_VWIN = (CAM_EIS_PREP_ME_CTRL1 >> 28) & 0xf; + + EIS_IMG_WIDTH = (CAM_EIS_IMAGE_CTRL >> 16) & 0x1fff; + EIS_IMG_HEIGHT = CAM_EIS_IMAGE_CTRL & 0x1fff; + + if (EISO_XSIZE != 255) + LOG_INF("EIS Error, EISO_XISZE must be 255 !!!"); + + /*1. The max horizontal window size is 4 */ + /*2. The max vertical window size is 8 */ + /*3. EIS_MF_OFFSET.EIS_RP_VOFST/EIS_RP_HOFST > 16 */ + /*6. EIS_PREP_ME_CTRL1.EIS_NUM_HRP <= 16 */ + /*7. EIS_PREP_ME_CTRL1.EIS_NUM_VRP <= 8 */ + if ((EIS_NUM_VWIN > 8) || (EIS_NUM_HWIN > 4) || + (EIS_NUM_VRP > 8) || (EIS_NUM_HRP > 16) || (EIS_RP_VOFST < 16) + || (EIS_RP_HOFST <= 16)) { + /*Error */ + LOG_INF + ("EIS Error, 1. The max horizontal window size is 4, EIS_NUM_HWIN(%d)!!", + EIS_NUM_HWIN); + LOG_INF + ("EIS Error, 2. The max vertical window size is 8, EIS_NUM_VWIN(%d)!!", + EIS_NUM_VWIN); + LOG_INF + ("EIS Error, 3. EIS_MF_OFFSET.EIS_RP_VOFST or EIS_RP_HOFST > 16!!, EIS_RP_VOFST(%d), EIS_RP_HOFST(%d)", + EIS_RP_VOFST, EIS_RP_HOFST); + LOG_INF + ("EIS Error, 6. EIS_PREP_ME_CTRL1.EIS_NUM_HRP <= 16, EIS_NUM_HRP(%d)!!", + EIS_NUM_HRP); + LOG_INF + ("EIS Error, 7. EIS_PREP_ME_CTRL1.EIS_NUM_VRP <= 8, EIS_NUM_VRP(%d)!!", + EIS_NUM_VRP); + } + + /*8. EIS_MB_INTERVAL.EIS_WIN_HSIZE >= (EIS_PREP_ME_CTRL1.EIS_NUM_HRP+1)*16+1 */ + /*9. EIS_MB_INTERVAL.EIS_WIN_VSIZE >= (EIS_PREP_ME_CTRL1.EIS_NUM_VRP+1)*16+1 */ + if ((EIS_WIN_HSIZE < (((EIS_NUM_HRP + 1) << 4) + 1)) || + (EIS_WIN_VSIZE < (((EIS_NUM_VRP + 1) << 4) + 1))) { + /*Error */ + LOG_INF + ("EIS Error, 8. EIS_WIN_HSIZE(%d) >= (EIS_NUM_HRP(%d)+1)*16+1!!", + EIS_WIN_HSIZE, EIS_NUM_HRP); + LOG_INF + ("EIS Error, 9. EIS_WIN_VSIZE(%d) >= (EIS_NUM_VRP(%d)+1)*16+1!!", + EIS_WIN_VSIZE, EIS_NUM_VRP); + } + /*10. (EIS_MB_OFFSET.EIS_RP_HOFST + ((EIS_MB_INTERVAL.EIS_WIN_HSIZE-1)*EIS_PREP_ME_CTRL1.EIS_NUM_HWIN)+EIS_PREP_ME_CTRL1.EIS_NUM_HRP*16)*EIS_PREP_ME_CTRL1.EIS_OP_HORI < EIS_IMAGE_CTRL.WIDTH */ + /*10.( EIS_MB_OFFSET.EIS_RP_VOFST + ((EIS_MB_INTERVAL.EIS_WIN_VSIZE-1)*EIS_PREP_ME_CTRL1.EIS_NUM_VWIN)+EIS_PREP_ME_CTRL1.EIS_NUM_VRP*16)*EIS_PREP_ME_CTRL1.EIS_OP_VERT < EIS_IMAGE_CTRL.HEIGHT */ + if ((((EIS_RP_HOFST + ((EIS_WIN_HSIZE - 1) * (EIS_NUM_HWIN - 1)) + + (EIS_NUM_HRP << 4)) * EIS_OP_HORI) >= EIS_IMG_WIDTH) + || + (((EIS_RP_VOFST + ((EIS_WIN_VSIZE - 1) * (EIS_NUM_VWIN - 1)) + + (EIS_NUM_VRP << 4)) * EIS_OP_VERT) >= EIS_IMG_HEIGHT)) { + /*Error */ + LOG_INF + ("EIS Error, 10. (EIS_MB_OFFSET.EIS_RP_HOFST(%d) + ((EIS_MB_INTERVAL.EIS_WIN_HSIZE(%d)-1)*(EIS_PREP_ME_CTRL1.EIS_NUM_HWIN(%d)-1))+EIS_PREP_ME_CTRL1.EIS_NUM_HRP(%d)*16)*EIS_PREP_ME_CTRL1.EIS_OP_HORI(%d) < EIS_IMAGE_CTRL.WIDTH(%d)!!", + EIS_RP_HOFST, EIS_WIN_HSIZE, EIS_NUM_HWIN, EIS_NUM_HRP, EIS_OP_HORI, + EIS_IMG_WIDTH); + LOG_INF + ("EIS Error, 10. (EIS_MB_OFFSET.EIS_RP_VOFST(%d) + ((EIS_MB_INTERVAL.EIS_WIN_VSIZE(%d)-1)*(EIS_PREP_ME_CTRL1.EIS_NUM_VWIN(%d)-1))+EIS_PREP_ME_CTRL1.EIS_NUM_VRP(%d)*16)*EIS_PREP_ME_CTRL1.EIS_OP_VERT(%d) < EIS_IMG_HEIGHT.WIDTH(%d)!!", + EIS_RP_VOFST, EIS_WIN_VSIZE, EIS_NUM_VWIN, EIS_NUM_VRP, EIS_OP_VERT, + EIS_IMG_HEIGHT); + } + + /*11. EISO_XISZE = 255 (after 82, EISO_XISZE = 407 in 89) */ + /*4. EIS_IMAGE_CTRL.WIDTH = EIS input image width but if */ + /* (two_pix mode) EIS_IMAGE_CTRL.WIDTH = input image width/2 */ + /*5. EIS_IMAGE_CTRL.HEIGHT = EIS input image height */ + switch (eis_sel) { + case 0: + if ((scenario == 1) && (0x0 == sgg_sel)) { + if ((grab_width != EIS_IMG_WIDTH) + || (grab_height != EIS_IMG_HEIGHT)) + bError = MTRUE; + /*Error */ + } else { + /*Error in non-yuv sensor */ + LOG_INF("EIS Error, Non-Yuv Sensor!!"); + } + break; + case 1: + if (MTRUE == bmx_enable) { + /*bmx_width */ + if ((bmx_width / 2 != EIS_IMG_WIDTH) + || (bmx_height != EIS_IMG_HEIGHT)) + bError = MTRUE; + /*Error */ + } else { + if ((grab_width != EIS_IMG_WIDTH) + || (grab_height != EIS_IMG_HEIGHT)) + bError = MTRUE; + /*Error */ + } + break; + case 2: + if (MTRUE == bmx_enable) { + if ((EIS_IMG_WIDTH != rrz_out_width / 2) + || (EIS_IMG_HEIGHT != rrz_out_height)) + bError = MTRUE; + /*Error */ + + } else { + if ((EIS_IMG_WIDTH != rrz_out_width) + || (EIS_IMG_HEIGHT != rrz_out_height)) + bError = MTRUE; + /*Error */ + } + break; + default: + /*Error */ + break; + } + if (MTRUE == bError) { + LOG_INF + ("EIS Error, 4. EIS_IMAGE_CTRL.WIDTH = EIS input image width but if (two_pix mode) EIS_IMAGE_CTRL.WIDTH = input image width/2!!\n"); + LOG_INF + ("EIS Error, 5. EIS_IMAGE_CTRL.HEIGHT != EIS input image height!!\n"); + LOG_INF("eis_sel:%d, scenario:%d, sgg_sel:%d, twin_mode:%d", eis_sel, + scenario, sgg_sel, bmx_enable); + LOG_INF + ("EIS_IMG_WIDTH:%d, EIS_IMG_HEIGHT:%d, rrz_out_width:%d, rrz_out_height:%d", + EIS_IMG_WIDTH, EIS_IMG_HEIGHT, rrz_out_width, rrz_out_height); + LOG_INF("grab_width:%d, grab_height:%d, bmx_width:%d, bmx_height:%d", + grab_width, grab_height, bmx_width, bmx_height); + } + + + } + + if (cam_tg2_vf_con & 0x01) { + MUINT32 cam_af_con; /*46B0 */ + MUINT32 cam_af_winx_1; /*46B4 */ + MUINT32 cam_af_winx_2; /*46B8 */ + MUINT32 cam_af_winx_3; /*46BC */ + MUINT32 cam_af_winy_1; /*46C0 */ + MUINT32 cam_af_winy_2; /*46C4 */ + MUINT32 cam_af_winy_3; /*46C8 */ + MUINT32 cam_af_size; /*46CC */ + MUINT32 cam_af_flt_1; /*46D4 */ + MUINT32 cam_af_flt_2; /*46D8 */ + MUINT32 cam_af_flt_3; /*46DC */ + MUINT32 cam_af_th; /*46E0 */ + MUINT32 cam_af_flo_win_1; /*46E4 */ + MUINT32 cam_af_flo_size_1; /*46E8 */ + MUINT32 cam_af_flo_win_2; /*46EC */ + MUINT32 cam_af_flo_size_2; /*46F0 */ + MUINT32 cam_af_flo_win_3; /*46F4 */ + MUINT32 cam_af_flo_size_3; /*46F8 */ + MUINT32 cam_af_flo_th; /*46FC */ + MUINT32 cam_af_image_size; /*4700 */ + MUINT32 AF_WIN_WD; + MUINT32 AF_WIN_HT; + MUINT32 AF_WINX_0; + MUINT32 AF_WINX_1; + MUINT32 AF_WINX_2; + MUINT32 AF_WINX_3; + MUINT32 AF_WINX_4; + MUINT32 AF_WINX_5; +/* MUINT32 AF_WINX_6;*/ + + MUINT32 AF_WINY_0; + MUINT32 AF_WINY_1; + MUINT32 AF_WINY_2; + MUINT32 AF_WINY_3; + MUINT32 AF_WINY_4; + MUINT32 AF_WINY_5; +/* MUINT32 AF_WINY_6;*/ + + MUINT32 AF_FLO_WINX_1; + MUINT32 AF_FLO_WINY_1; + MUINT32 AF_FLO_WINX_2; + MUINT32 AF_FLO_WINY_2; + MUINT32 AF_FLO_WINX_3; + MUINT32 AF_FLO_WINY_3; + + MUINT32 AF_FLO_WD_1; + MUINT32 AF_FLO_HT_1; + MUINT32 AF_FLO_WD_2; + MUINT32 AF_FLO_HT_2; + MUINT32 AF_FLO_WD_3; + MUINT32 AF_FLO_HT_3; + + MUINT32 AF_IMAGE_WD; + MUINT32 AF_DECI; + MUINT32 AF_InputWidth; + + MUINT32 AF_LeftOverWidth; + + MUINT32 cam_aao_xsize; /*7554 */ + MUINT32 cam_aao_ysize; /*7558 */ + MUINT32 cam_awb_win_num; /*65BC */ + MUINT32 cam_ae_hst_ctl; /*6650 */ + + MUINT32 AAO_XSIZE; + MUINT32 AWB_W_HNUM; + MUINT32 AWB_W_VNUM; + MUINT32 histogramen_num; + + MUINT32 cam_awb_win_org; /*65B0 */ + MUINT32 cam_awb_win_pit; /*65B8 */ + + MUINT32 AAO_InWidth; + MUINT32 AAO_InHeight; + MUINT32 AWB_W_HPIT; + MUINT32 AWB_W_VPIT; + MUINT32 AWB_W_HORG; + MUINT32 AWB_W_VORG; + /*Check ISP_D AF_D. */ + LOG_INF("ISP chk TG2"); + + grab_width = + ((cam_tg2_sen_grab_pxl >> 16) & 0x7fff) - (cam_tg2_sen_grab_pxl & 0x7fff); + grab_height = + ((cam_tg2_sen_grab_lin >> 16) & 0x1fff) - (cam_tg2_sen_grab_lin & 0x1fff); + + cam_af_con = ISP_RD32(ISP_ADDR + 0x6B0); + cam_af_winx_1 = ISP_RD32(ISP_ADDR + 0x6B4); + cam_af_winx_2 = ISP_RD32(ISP_ADDR + 0x6B8); + cam_af_winx_3 = ISP_RD32(ISP_ADDR + 0x6BC); + cam_af_winy_1 = ISP_RD32(ISP_ADDR + 0x6C0); + cam_af_winy_2 = ISP_RD32(ISP_ADDR + 0x6C4); + cam_af_winy_3 = ISP_RD32(ISP_ADDR + 0x6C8); + cam_af_size = ISP_RD32(ISP_ADDR + 0x6CC); + + cam_af_flt_1 = ISP_RD32(ISP_ADDR + 0x26D4); /*66D4 */ + cam_af_flt_2 = ISP_RD32(ISP_ADDR + 0x26D8); /*66D8 */ + cam_af_flt_3 = ISP_RD32(ISP_ADDR + 0x26DC); /*66DC */ + cam_af_th = ISP_RD32(ISP_ADDR + 0x26E0); /*66E0 */ + cam_af_flo_win_1 = ISP_RD32(ISP_ADDR + 0x26E4); /*66E4 */ + cam_af_flo_size_1 = ISP_RD32(ISP_ADDR + 0x26E8); /*66E8 */ + cam_af_flo_win_2 = ISP_RD32(ISP_ADDR + 0x26EC); /*66EC */ + cam_af_flo_size_2 = ISP_RD32(ISP_ADDR + 0x26F0); /*66F0 */ + cam_af_flo_win_3 = ISP_RD32(ISP_ADDR + 0x26F4); /*66F4 */ + cam_af_flo_size_3 = ISP_RD32(ISP_ADDR + 0x26F8); /*66F8 */ + cam_af_flo_th = ISP_RD32(ISP_ADDR + 0x26FC); /*66FC */ + cam_af_image_size = ISP_RD32(ISP_ADDR + 0x2700); /*6700 */ + + AF_WINX_0 = (cam_af_winx_1 & 0x1fff); + AF_WINX_1 = ((cam_af_winx_1 >> 16) & 0x1fff); + AF_WINX_2 = (cam_af_winx_2 & 0x1fff); + AF_WINX_3 = ((cam_af_winx_2 >> 16) & 0x1fff); + AF_WINX_4 = (cam_af_winx_3 & 0x1fff); + AF_WINX_5 = ((cam_af_winx_3 >> 16) & 0x1fff); + + AF_WINY_0 = (cam_af_winy_1 & 0x1fff); + AF_WINY_1 = ((cam_af_winy_1 >> 16) & 0x1fff); + AF_WINY_2 = (cam_af_winy_2 & 0x1fff); + AF_WINY_3 = ((cam_af_winy_2 >> 16) & 0x1fff); + AF_WINY_4 = (cam_af_winy_3 & 0x1fff); + AF_WINY_5 = ((cam_af_winy_3 >> 16) & 0x1fff); + + AF_FLO_WINX_1 = (cam_af_flo_win_1 & 0x1fff); + AF_FLO_WINY_1 = ((cam_af_flo_win_1 >> 16) & 0x1fff); + AF_FLO_WINX_2 = (cam_af_flo_win_2 & 0x1fff); + AF_FLO_WINY_2 = ((cam_af_flo_win_2 >> 16) & 0x1fff); + AF_FLO_WINX_3 = (cam_af_flo_win_3 & 0x1fff); + AF_FLO_WINY_3 = ((cam_af_flo_win_3 >> 16) & 0x1fff); + + AF_FLO_WD_1 = (cam_af_flo_size_1 & 0xfff); + AF_FLO_HT_1 = ((cam_af_flo_size_1 >> 16) & 0xfff); + AF_FLO_WD_2 = (cam_af_flo_size_2 & 0xfff); + AF_FLO_HT_2 = ((cam_af_flo_size_2 >> 16) & 0xfff); + AF_FLO_WD_3 = (cam_af_flo_size_3 & 0xfff); + AF_FLO_HT_3 = ((cam_af_flo_size_3 >> 16) & 0xfff); + + AF_IMAGE_WD = cam_af_image_size & 0x1fff; + + AF_DECI = cam_af_con & 0x03; + + /*1. The min horizontal window size is 8. (AF_WIN_WD/AF_FLO_WD_x) */ + /*2. The min vertical window size is 4. (AF_WIN_HT/AF_FLO_HT_x) */ + AF_WIN_WD = (cam_af_size & 0x7ff); + AF_WIN_HT = ((cam_af_size >> 16) & 0x7ff); + if ((AF_WIN_WD < 8) || (AF_FLO_WD_1 < 8) || (AF_FLO_WD_2 < 8) || (AF_FLO_WD_3 < 8) + || (AF_WIN_HT < 4) || (AF_FLO_HT_1 < 4) || (AF_FLO_HT_2 < 4) + || (AF_FLO_HT_3 < 4)) { + LOG_INF + ("HwRWCtrl:: AF_D Error: The min horizontal window size is 8. (AF_WIN_WD(%d), AF_FLO_WD_1(%d), AF_FLO_WD_2(%d), AF_FLO_WD_3(%d))!!", + AF_WIN_WD, AF_FLO_WD_1, AF_FLO_WD_2, AF_FLO_WD_3); + LOG_INF + ("HwRWCtrl:: AF_D Error: The min vertical window size is 4. (AF_WIN_HT(%d), AF_FLO_HT_1(%d), AF_FLO_HT_2(%d), AF_FLO_HT_3(%d))!!", + AF_WIN_HT, AF_FLO_HT_1, AF_FLO_HT_2, AF_FLO_HT_3); + } + /*3. The horizontal window start point and size must be multiples of 2 (AF_WINX_x/AF_FLO_WINX_x/AF_WIN_WD/AF_FLO_WD_x) */ + if (((AF_WINX_0 % 2) != 0) || ((AF_WINX_1 % 2) != 0) || ((AF_WINX_2 % 2) != 0) + || ((AF_WINX_3 % 2) != 0) || ((AF_WINX_4 % 2) != 0) || ((AF_WINX_5 % 2) != 0) + || ((AF_WINY_0 % 2) != 0) || ((AF_WINY_1 % 2) != 0) || ((AF_WINY_2 % 2) != 0) + || ((AF_WINY_3 % 2) != 0) || ((AF_WINY_4 % 2) != 0) || ((AF_WINY_5 % 2) != 0)) { + LOG_INF + ("HwRWCtrl:: AF_D Error: The horizontal window start point and size must be multiples of 2 !!"); + LOG_INF + ("HwRWCtrl:: AF_D Error: AF_WINX_0(%d)/AF_WINX_1(%d)/AF_WINX_2(%d)/AF_WINX_3(%d)/AF_WINX_4(%d)/AF_WINX_5(%d)!!", + AF_WINX_0, AF_WINX_1, AF_WINX_2, AF_WINX_3, AF_WINX_4, AF_WINX_5); + LOG_INF + ("HwRWCtrl:: AF_D Error: AF_WINY_0(%d)/AF_WINY_1(%d)/AF_WINY_2(%d)/AF_WINY_3(%d)/AF_WINY_4(%d)/AF_WINY_5(%d)!!", + AF_WINY_0, AF_WINY_1, AF_WINY_2, AF_WINY_3, AF_WINY_4, AF_WINY_5); + + } + /*10. Horizontal start position of floating window must be multiples of 2 */ + /*11. Horizontal size of floating window must be multiples of 2 */ + if (((AF_FLO_WINX_1 % 2) != 0) || ((AF_FLO_WINX_2 % 2) != 0) + || ((AF_FLO_WINX_3 % 2) != 0) + || ((AF_FLO_WINY_1 % 2) != 0) || ((AF_FLO_WINY_2 % 2) != 0) + || ((AF_FLO_WINY_3 % 2) != 0) + || ((AF_FLO_WD_1 % 2) != 0) || ((AF_FLO_WD_2 % 2) != 0) + || ((AF_FLO_WD_3 % 2) != 0) + || ((AF_FLO_HT_1 % 2) != 0) || ((AF_FLO_HT_2 % 2) != 0) + || ((AF_FLO_HT_3 % 2) != 0)) { + LOG_INF + ("HwRWCtrl:: AF_D Error: Horizontal start position of floating window must be multiples of 2!!"); + LOG_INF + ("HwRWCtrl:: AF_D Error: Horizontal size of floating window must be multiples of 2!!"); + LOG_INF + ("HwRWCtrl:: AF_D Error: AF_FLO_WINX_1(%d)/AF_FLO_WINX_2(%d)/AF_FLO_WINX_3(%d)!!", + AF_FLO_WINX_1, AF_FLO_WINX_2, AF_FLO_WINX_3); + LOG_INF + ("HwRWCtrl:: AF_D Error: AF_FLO_WD_1(%d)/AF_FLO_WD_2(%d)/AF_FLO_WD_3(%d)!!", + AF_FLO_WD_1, AF_FLO_WD_2, AF_FLO_WD_3); + LOG_INF + ("HwRWCtrl:: AF_D Error: AF_FLO_HT_1(%d)/AF_FLO_HT_2(%d)/AF_FLO_HT_3(%d)!!", + AF_FLO_HT_1, AF_FLO_HT_2, AF_FLO_HT_3); + } + /*5. Horizontal size of each normal window is limited to 510*2 (AF_WIN_WD) */ + /*6. Vertical size of each normal window is limited to 511*2 (AF_WIN_HT) */ + if ((AF_WIN_WD > 1020) || (AF_WIN_HT > 1022)) { + LOG_INF + ("HwRWCtrl:: AF_D Error: Horizontal size of each normal window is limited to 510*2 (AF_WIN_WD(%d))!!", + AF_WIN_WD); + LOG_INF + ("HwRWCtrl:: AF_D Error: Vertical size of each normal window is limited to 511*2 (AF_WIN_HT(%d))!!", + AF_WIN_HT); + } + + /*12. Maximum floating widow size is 4094x4095 */ + if ((AF_FLO_WD_1 > 4094) || (AF_FLO_WD_2 > 4094) || (AF_FLO_WD_3 > 4094) || + (AF_FLO_HT_1 > 4095) || (AF_FLO_HT_2 > 4095) || (AF_FLO_HT_3 > 4095)) + LOG_INF + ("HwRWCtrl:: AF_D Error: Maximum floating widow size is 4094x4095!!"); + + if (MTRUE == bmx_enable) { + if (sgg_sel == 1) + AF_InputWidth = bmx_width; + else + AF_InputWidth = grab_width; + /*18. If two_pixel mode, AF_DECI >= 1 */ + if (AF_DECI != 0) + LOG_INF("HwRWCtrl:: AF_D Error: If two_pixel mode, AF_DECI >= 1!!"); + /*Error */ + } else { + AF_InputWidth = grab_width; + } + + /*15. AF_IMAGE_WD must be the same as input frame width */ + if (AF_IMAGE_WD != AF_InputWidth) { + /*Error */ + LOG_INF + ("HwRWCtrl:: AF_D Error: bmx_enable(%d), sgg_sel(%d), bmx_width(%d), grab_width(%d)!!", + bmx_enable, sgg_sel, bmx_width, grab_width); + LOG_INF + ("HwRWCtrl:: AF_D Error: AF_IMAGE_WD(%d) must be the same as input frame width(%d)!!", + AF_IMAGE_WD, AF_InputWidth); + } + /*16. "CAM_AF_WINX_x.AF_WINX_x + CAM_AF_SIZE.AF_WIN_WD <= input frame width" for a valid window */ + /*17. "CAM_AF_WINY_x.AF_WINY_x + CAM_AF_SIZE.AF_WIN_HT <= input frame height" for a valid window */ + + /*14. If AF window is aligned to image left/right boundary, minimum horizontal size should be larger than 24*(1<> 16) & 0xff; + histogramen_num = 0; + for (i = 0; i < 4; i++) { + if ((cam_ae_hst_ctl >> i) & 0x1) + histogramen_num += 1; + } + + if ((cam_aao_ysize + 1) != 1) + LOG_INF("Error HwRWCtrl::AAO_D_YSIZE(%d) must be equal 1 !!", + cam_aao_ysize); + if ((AAO_XSIZE + 1) != + (AWB_W_HNUM * AWB_W_VNUM * 5 + (histogramen_num << 8))) + LOG_INF + ("Error HwRWCtrl::AAO_D_XSIZE(%d) = AWB_W_HNUM(%d)*AWB_W_VNUM(%d)*5 + (how many histogram enable(%d)(AE_HST0/1/2/3_EN))*2*128 !!", + AAO_XSIZE, AWB_W_HNUM, AWB_W_VNUM, histogramen_num); + } + /*Chek AWB_D setting */ +#if 0 + MUINT32 cam_awb_win_org; /*65B0 */ + MUINT32 cam_awb_win_pit; /*65B8 */ + + MUINT32 AAO_InWidth; + MUINT32 AAO_InHeight; + MUINT32 AWB_W_HPIT; + MUINT32 AWB_W_VPIT; + MUINT32 AWB_W_HORG; + MUINT32 AWB_W_VORG; +#endif + cam_awb_win_num = ISP_RD32(ISP_ADDR + 0x25BC); + cam_awb_win_pit = ISP_RD32(ISP_ADDR + 0x25B8); + cam_awb_win_org = ISP_RD32(ISP_ADDR + 0x25B0); + + if (MTRUE == bmx_enable) { /*hbin_enable should be true under Twin mode. */ + AAO_InWidth = bmx_width / 2; + AAO_InHeight = bmx_height; + } else { + AAO_InWidth = grab_width; + AAO_InHeight = grab_height; + } + AWB_W_HNUM = (cam_awb_win_num & 0xff); + AWB_W_VNUM = ((cam_awb_win_num >> 16) & 0xff); + + AWB_W_HPIT = (cam_awb_win_pit & 0x1fff); + AWB_W_VPIT = ((cam_awb_win_pit >> 16) & 0x1fff); + + AWB_W_HORG = (cam_awb_win_org & 0x1fff); + AWB_W_VORG = ((cam_awb_win_org >> 16) & 0x1fff); + if (AAO_InWidth < (AWB_W_HNUM * AWB_W_HPIT + AWB_W_HORG)) { + /*Error */ + LOG_INF + ("Error HwRWCtrl:: AWB_D bmx_enable(%d), bmx_width(%d), bmx_height(%d), grab_width(%d), grab_height(%d)!!", + bmx_enable, bmx_width, bmx_height, grab_width, grab_height); + LOG_INF + ("Error HwRWCtrl:: AWB_D input frame width(%d) >= AWB_W_HNUM(%d) * AWB_W_HPIT(%d) + AWB_W_HORG(%d) !!", + AAO_InWidth, AWB_W_HNUM, AWB_W_HPIT, AWB_W_HORG); + } + if (AAO_InHeight < (AWB_W_VNUM * AWB_W_VPIT + AWB_W_VORG)) { + /*Error */ + LOG_INF + ("Error HwRWCtrl:: AWB_D bmx_enable(%d), bmx_width(%d), bmx_height(%d), grab_width(%d), grab_height(%d)!!", + bmx_enable, bmx_width, bmx_height, grab_width, grab_height); + LOG_INF + ("Error HwRWCtrl:: AWB_D input frame height(%d) >= AWB_W_VNUM(%d) * AWB_W_VPIT(%d) + AWB_W_VORG(%d) !!", + AAO_InHeight, AWB_W_VNUM, AWB_W_VPIT, AWB_W_VORG); + } + } + + return MTRUE; +} + +static MINT32 ISP_DumpReg(void) +{ + MINT32 Ret = 0; + /* */ + LOG_ERR(" E."); + /* */ + /* spin_lock_irqsave(&(IspInfo.SpinLock), flags); */ + + /* tile tool parse range */ + /* Joseph Hung (xa)#define ISP_ADDR_START 0x15004000 */ + /* #define ISP_ADDR_END 0x15006000 */ + /* */ + /* N3D control */ + ISP_WR32((ISP_ADDR + 0x40c0), 0x746); + LOG_ERR("[0x%08X %08X] [0x%08X %08X]", + (unsigned int)(ISP_TPIPE_ADDR + 0x40c0), (unsigned int)ISP_RD32(ISP_ADDR + 0x40c0), + (unsigned int)(ISP_TPIPE_ADDR + 0x40d8), (unsigned int)ISP_RD32(ISP_ADDR + 0x40d8)); + ISP_WR32((ISP_ADDR + 0x40c0), 0x946); + LOG_ERR("[0x%08X %08X] [0x%08X %08X]", + (unsigned int)(ISP_TPIPE_ADDR + 0x40c0), (unsigned int)ISP_RD32(ISP_ADDR + 0x40c0), + (unsigned int)(ISP_TPIPE_ADDR + 0x40d8), (unsigned int)ISP_RD32(ISP_ADDR + 0x40d8)); + + /* isp top */ + RegDump(0x0, 0x200); + /* dump p1 dma reg */ + RegDump(0x3200, 0x3570); + /* dump all isp dma reg */ + RegDump(0x3300, 0x3400); + /* dump all isp dma err reg */ + RegDump(0x3560, 0x35e0); +#if 0 + g_bDmaERR_p1 = g_bDmaERR_p1_d = g_bDmaERR_p2 = g_bDmaERR_deepDump = MTRUE; + ISP_DumpDmaDeepDbg(); +#endif + /* TG1 */ + RegDump(0x410, 0x4a0); + /* TG2 */ + RegDump(0x2410, 0x2450); + /* hbin */ + LOG_ERR("[0x%08X %08X],[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x4f0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x534), (unsigned int)(ISP_TPIPE_ADDR + 0x4f4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x538)); + /* LSC */ + RegDump(0x530, 0x550); + /* awb win */ + RegDump(0x5b0, 0x5d0); + /* ae win */ + RegDump(0x650, 0x690); + /* af win */ + RegDump(0x6b0, 0x700); + /* flk */ + RegDump(0x770, 0x780); + /* rrz */ + RegDump(0x7a0, 0x7d0); + /* eis */ + RegDump(0xdc0, 0xdf0); + /* dmx/rmx/bmx */ + RegDump(0xe00, 0xe30); + /* serial cam */ + RegDump(0x4E20, 0x4E60); + /* Mipi source */ + LOG_ERR("[0x%08X %08X],[0x%08X %08X]", (unsigned int)(0x10215830), + (unsigned int)ISP_RD32(ISP_MIPI_ANA_ADDR + 0x830), (unsigned int)(0x10215830), + (unsigned int)ISP_RD32(ISP_MIPI_ANA_ADDR + 0x830)); + LOG_ERR("[0x%08X %08X],[0x%08X %08X]", (unsigned int)(0x10215c30), + (unsigned int)ISP_RD32(ISP_MIPI_ANA_ADDR + 0xc30), (unsigned int)(0x10215c30), + (unsigned int)ISP_RD32(ISP_MIPI_ANA_ADDR + 0xc30)); + + /* NSCI2 1 debug */ + ISP_WR32((ISP_ADDR + 0x43B8), 0x02); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x43B8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x43B8)); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x43BC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x43BC)); + ISP_WR32((ISP_ADDR + 0x43B8), 0x12); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x43B8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x43B8)); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x43BC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x43BC)); + + /* NSCI2 2 debug */ + ISP_WR32((ISP_ADDR + 0x47B8), 0x02); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x47B8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x47B8)); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x47BC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x47BC)); + ISP_WR32((ISP_ADDR + 0x47B8), 0x12); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x47B8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x47B8)); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x47BC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x47BC)); + + /* NSCI2 3 debug */ + ISP_WR32((ISP_ADDR + 0x4BB8), 0x02); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x4BB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BB8)); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x4BBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BBC)); + ISP_WR32((ISP_ADDR + 0x4BB8), 0x12); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x4BB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BB8)); + LOG_ERR("[0x%08X %08X]", (unsigned int)(ISP_TPIPE_ADDR + 0x4BBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BBC)); + + /* seninf1 */ + LOG_ERR("[0x%08X %08X],[0x%08X %08X]", + (unsigned int)(ISP_TPIPE_ADDR + 0x4008), (unsigned int)ISP_RD32(ISP_ADDR + 0x4008), + (unsigned int)(ISP_TPIPE_ADDR + 0x4100), (unsigned int)ISP_RD32(ISP_ADDR + 0x4100)); + RegDump(0x4120, 0x4160); + RegDump(0x4360, 0x43f0) + + /* seninf2 */ + LOG_ERR("[0x%08X %08X],[0x%08X %08X]", + (unsigned int)(ISP_TPIPE_ADDR + 0x4008), (unsigned int)ISP_RD32(ISP_ADDR + 0x4008), + (unsigned int)(ISP_TPIPE_ADDR + 0x4100), (unsigned int)ISP_RD32(ISP_ADDR + 0x4100)); + RegDump(0x4520, 0x4560); + RegDump(0x4600, 0x4610); + RegDump(0x4760, 0x47f0); + /* LSC_D */ + RegDump(0x2530, 0x2550); + /* awb_d */ + RegDump(0x25b0, 0x25d0); + /* ae_d */ + RegDump(0x2650, 0x2690); + /* af_d */ + RegDump(0x26b0, 0x2700); + /* rrz_d */ + RegDump(0x27a0, 0x27d0); + /* rmx_d/bmx_d/dmx_d */ + RegDump(0x2e00, 0x2e30); + + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x800), + (unsigned int)ISP_RD32(ISP_ADDR + 0x800)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x880), + (unsigned int)ISP_RD32(ISP_ADDR + 0x880)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x884), + (unsigned int)ISP_RD32(ISP_ADDR + 0x884)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x888), + (unsigned int)ISP_RD32(ISP_ADDR + 0x888)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x8A0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x8A0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x920), + (unsigned int)ISP_RD32(ISP_ADDR + 0x920)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x924), + (unsigned int)ISP_RD32(ISP_ADDR + 0x924)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x928), + (unsigned int)ISP_RD32(ISP_ADDR + 0x928)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x92C), + (unsigned int)ISP_RD32(ISP_ADDR + 0x92C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x930), + (unsigned int)ISP_RD32(ISP_ADDR + 0x930)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x934), + (unsigned int)ISP_RD32(ISP_ADDR + 0x934)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x938), + (unsigned int)ISP_RD32(ISP_ADDR + 0x938)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x93C), + (unsigned int)ISP_RD32(ISP_ADDR + 0x93C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x960), + (unsigned int)ISP_RD32(ISP_ADDR + 0x960)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x9C4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x9C4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x9E4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x9E4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x9E8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x9E8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x9EC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x9EC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xA00), + (unsigned int)ISP_RD32(ISP_ADDR + 0xA00)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xA04), + (unsigned int)ISP_RD32(ISP_ADDR + 0xA04)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xA08), + (unsigned int)ISP_RD32(ISP_ADDR + 0xA08)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xA0C), + (unsigned int)ISP_RD32(ISP_ADDR + 0xA0C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xA10), + (unsigned int)ISP_RD32(ISP_ADDR + 0xA10)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xA14), + (unsigned int)ISP_RD32(ISP_ADDR + 0xA14)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xA20), + (unsigned int)ISP_RD32(ISP_ADDR + 0xA20)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xAA0), + (unsigned int)ISP_RD32(ISP_ADDR + 0xAA0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xACC), + (unsigned int)ISP_RD32(ISP_ADDR + 0xACC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB00), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB00)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB04), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB04)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB08), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB08)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB0C), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB0C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB10), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB10)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB14), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB14)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB18), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB18)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB1C), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB1C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB20), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB20)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB44), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB44)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB48), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB48)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB4C), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB4C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB50), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB50)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB54), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB54)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB58), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB58)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB5C), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB5C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xB60), + (unsigned int)ISP_RD32(ISP_ADDR + 0xB60)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBA0), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBA0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBA4), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBA4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBA8), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBA8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBAC), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBAC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBB0), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBB0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBB4), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBB4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBB8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBBC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xBC0), + (unsigned int)ISP_RD32(ISP_ADDR + 0xBC0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xC20), + (unsigned int)ISP_RD32(ISP_ADDR + 0xC20)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xCC0), + (unsigned int)ISP_RD32(ISP_ADDR + 0xCC0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xCE4), + (unsigned int)ISP_RD32(ISP_ADDR + 0xCE4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xCE8), + (unsigned int)ISP_RD32(ISP_ADDR + 0xCE8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xCEC), + (unsigned int)ISP_RD32(ISP_ADDR + 0xCEC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xCF0), + (unsigned int)ISP_RD32(ISP_ADDR + 0xCF0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xCF4), + (unsigned int)ISP_RD32(ISP_ADDR + 0xCF4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xCF8), + (unsigned int)ISP_RD32(ISP_ADDR + 0xCF8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xCFC), + (unsigned int)ISP_RD32(ISP_ADDR + 0xCFC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD24), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD24)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD28), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD28)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD2C), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD2c)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD40), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD40)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD64), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD64)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD68), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD68)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD6C), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD6c)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD70), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD70)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD74), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD74)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD78), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD78)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xD7C), + (unsigned int)ISP_RD32(ISP_ADDR + 0xD7C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xDA4), + (unsigned int)ISP_RD32(ISP_ADDR + 0xDA4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xDA8), + (unsigned int)ISP_RD32(ISP_ADDR + 0xDA8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0xDAC), + (unsigned int)ISP_RD32(ISP_ADDR + 0xDAC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x2410), + (unsigned int)ISP_RD32(ISP_ADDR + 0x2410)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x2414), + (unsigned int)ISP_RD32(ISP_ADDR + 0x2414)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x2418), + (unsigned int)ISP_RD32(ISP_ADDR + 0x2418)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x241C), + (unsigned int)ISP_RD32(ISP_ADDR + 0x241C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x2420), + (unsigned int)ISP_RD32(ISP_ADDR + 0x2420)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x243C), + (unsigned int)ISP_RD32(ISP_ADDR + 0x243C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x2440), + (unsigned int)ISP_RD32(ISP_ADDR + 0x2440)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x2444), + (unsigned int)ISP_RD32(ISP_ADDR + 0x2444)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x2448), + (unsigned int)ISP_RD32(ISP_ADDR + 0x2448)); + + /* seninf3 */ + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4900), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4900)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4920), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4920)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4924), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4924)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4928), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4928)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x492C), + (unsigned int)ISP_RD32(ISP_ADDR + 0x492C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4930), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4930)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4934), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4934)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4938), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4938)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BA0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BA0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BA4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BA4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BA8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BA8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BAC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BAC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BB0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BB0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BB4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BB4)); + ISP_WR32((ISP_ADDR + 0x4BB8), 0x10); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BB8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BBC)); + ISP_WR32((ISP_ADDR + 0x4BB8), 0x11); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BB8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BBC)); + ISP_WR32((ISP_ADDR + 0x4BB8), 0x12); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BB8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4BBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4BBC)); + /* seninf4 */ + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4D00), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4D00)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4D20), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4D20)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4D24), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4D24)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4D28), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4D28)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4D2C), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4D2C)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4D30), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4D30)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4D34), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4D34)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4D38), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4D38)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FA0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FA0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FA4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FA4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FA8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FA8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FAC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FAC)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FB0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FB0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FB4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FB4)); + ISP_WR32((ISP_ADDR + 0x4FB8), 0x10); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FB8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FBC)); + ISP_WR32((ISP_ADDR + 0x4FB8), 0x11); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FB8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FBC)); + ISP_WR32((ISP_ADDR + 0x4FB8), 0x12); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FB8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FB8)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x4FBC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x4FBC)); + + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x35FC), + (unsigned int)ISP_RD32(ISP_ADDR + 0x35FC)); + LOG_ERR("end MT6593"); + + /* */ + LOG_ERR("0x%08X %08X ", (unsigned int)ISP_ADDR_CAMINF, + (unsigned int)ISP_RD32(ISP_ADDR_CAMINF)); + LOG_ERR("0x%08X %08X ", (unsigned int)(ISP_TPIPE_ADDR + 0x150), + (unsigned int)ISP_RD32(ISP_ADDR + 0x150)); + /* */ + /* debug msg for direct link */ + + + /* mdp crop */ + LOG_ERR("MDPCROP Related"); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_ADDR + 0xd10), + (unsigned int)ISP_RD32(ISP_ADDR + 0xd10)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_ADDR + 0xd20), + (unsigned int)ISP_RD32(ISP_ADDR + 0xd20)); + /* cq */ + LOG_ERR("CQ Related"); + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x6000); + LOG_ERR("0x%08X %08X (0x15004160=6000)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x7000); + LOG_ERR("0x%08X %08X (0x15004160=7000)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x8000); + LOG_ERR("0x%08X %08X (0x15004160=8000)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + /* imgi_debug */ + LOG_ERR("IMGI_DEBUG Related"); + ISP_WR32(ISP_IMGSYS_BASE + 0x75f4, 0x001e); + LOG_ERR("0x%08X %08X (0x150075f4=001e)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + ISP_WR32(ISP_IMGSYS_BASE + 0x75f4, 0x011e); + LOG_ERR("0x%08X %08X (0x150075f4=011e)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + ISP_WR32(ISP_IMGSYS_BASE + 0x75f4, 0x021e); + LOG_ERR("0x%08X %08X (0x150075f4=021e)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + ISP_WR32(ISP_IMGSYS_BASE + 0x75f4, 0x031e); + LOG_ERR("0x%08X %08X (0x150075f4=031e)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + /* yuv */ + LOG_ERR("yuv-mdp crop Related"); + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x3014); + LOG_ERR("0x%08X %08X (0x15004160=3014)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + LOG_ERR("yuv-c24b out Related"); + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x301e); + LOG_ERR("0x%08X %08X (0x15004160=301e)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x301f); + LOG_ERR("0x%08X %08X (0x15004160=301f)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x3020); + LOG_ERR("0x%08X %08X (0x15004160=3020)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x3021); + LOG_ERR("0x%08X %08X (0x15004160=3021)", (unsigned int)(ISP_IMGSYS_BASE + 0x4164), + (unsigned int)ISP_RD32(ISP_IMGSYS_BASE + 0x4164)); + + ISP_chkModuleSetting(); + + LOG_INF("dump MMDVFS info\n"); + dump_mmdvfs_info(); + +#if 0 /* _mt6593fpga_dvt_use_ */ + { + int tpipePA = ISP_RD32(ISP_ADDR + 0x204); + int ctlStart = ISP_RD32(ISP_ADDR + 0x000); + int ctlTcm = ISP_RD32(ISP_ADDR + 0x054); + int map_va = 0, map_size; + int i; + int *pMapVa; +#define TPIPE_DUMP_SIZE 200 + + if ((ctlStart & 0x01) && (tpipePA) && (ctlTcm & 0x80000000)) { + map_va = 0; + m4u_mva_map_kernel(tpipePA, TPIPE_DUMP_SIZE, 0, &map_va, &map_size); + pMapVa = map_va; + LOG_DBG("pMapVa(0x%x),map_size(0x%x)", pMapVa, map_size); + LOG_DBG("ctlStart(0x%x),tpipePA(0x%x),ctlTcm(0x%x)", ctlStart, tpipePA, + ctlTcm); + if (pMapVa) { + for (i = 0; i < TPIPE_DUMP_SIZE; i += 10) { + LOG_DBG + ("[idx(%d)]%08X-%08X-%08X-%08X-%08X-%08X-%08X-%08X-%08X-%08X", + i, pMapVa[i], pMapVa[i + 1], pMapVa[i + 2], + pMapVa[i + 3], pMapVa[i + 4], pMapVa[i + 5], + pMapVa[i + 6], pMapVa[i + 7], pMapVa[i + 8], + pMapVa[i + 9]); + } + } + m4u_mva_unmap_kernel(tpipePA, map_size, map_va); + } + } +#endif + + /* spin_unlock_irqrestore(&(IspInfo.SpinLock), flags); */ + /* */ + LOG_ERR("- X."); + /* */ + return Ret; +} + +#ifndef CONFIG_MTK_CLKMGR /*CCF*/ +static inline void Prepare_ccf_clock(void) +{ + int ret; + /* must keep this clk open order: CG_SCP_SYS_DIS-> CG_DISP0_SMI_COMMON -> CG_SCP_SYS_ISP -> ISP clk */ + ret = clk_prepare(isp_clk.CG_SCP_SYS_DIS); + if (ret) + LOG_ERR("cannot prepare CG_SCP_SYS_DIS clock\n"); + + ret = clk_prepare(isp_clk.CG_DISP0_SMI_COMMON); + if (ret) + LOG_ERR("cannot prepare CG_DISP0_SMI_COMMON clock\n"); + + ret = clk_prepare(isp_clk.CG_SCP_SYS_ISP); + if (ret) + LOG_ERR("cannot prepare CG_SCP_SYS_ISP clock\n"); + + ret = clk_prepare(isp_clk.CG_IMAGE_CAM_SMI); + if (ret) + LOG_ERR("cannot prepare CG_IMAGE_CAM_SMI clock\n"); + + ret = clk_prepare(isp_clk.CG_IMAGE_CAM_CAM); + if (ret) + LOG_ERR("cannot prepare CG_IMAGE_CAM_CAM clock\n"); + + ret = clk_prepare(isp_clk.CG_IMAGE_SEN_TG); + if (ret) + LOG_ERR("cannot prepare CG_IMAGE_SEN_TG clock\n"); + + ret = clk_prepare(isp_clk.CG_IMAGE_SEN_CAM); + if (ret) + LOG_ERR("cannot prepare CG_IMAGE_SEN_CAM clock\n"); + + ret = clk_prepare(isp_clk.CG_IMAGE_CAM_SV); + if (ret) + LOG_ERR("cannot prepare CG_IMAGE_CAM_SV clock\n"); + + ret = clk_prepare(isp_clk.CG_IMAGE_LARB2_SMI); + if (ret) + LOG_ERR("cannot prepare CG_IMAGE_LARB2_SMI clock\n"); +} + +static inline void Prepare_Enable_ccf_clock(void) +{ + int ret; + /* must keep this clk open order: CG_SCP_SYS_DIS-> CG_DISP0_SMI_COMMON -> CG_SCP_SYS_ISP -> ISP clk */ + ret = clk_prepare_enable(isp_clk.CG_SCP_SYS_DIS); + if (ret) + LOG_ERR("cannot get CG_SCP_SYS_DIS clock\n"); + + ret = clk_prepare_enable(isp_clk.CG_DISP0_SMI_COMMON); + if (ret) + LOG_ERR("cannot get CG_DISP0_SMI_COMMON clock\n"); + + ret = clk_prepare_enable(isp_clk.CG_SCP_SYS_ISP); + if (ret) + LOG_ERR("cannot get CG_SCP_SYS_ISP clock\n"); + + ret = clk_prepare_enable(isp_clk.CG_IMAGE_CAM_SMI); + if (ret) + LOG_ERR("cannot get CG_IMAGE_CAM_SMI clock\n"); + + ret = clk_prepare_enable(isp_clk.CG_IMAGE_CAM_CAM); + if (ret) + LOG_ERR("cannot get CG_IMAGE_CAM_CAM clock\n"); + + ret = clk_prepare_enable(isp_clk.CG_IMAGE_SEN_TG); + if (ret) + LOG_ERR("cannot get CG_IMAGE_SEN_TG clock\n"); + + ret = clk_prepare_enable(isp_clk.CG_IMAGE_SEN_CAM); + if (ret) + LOG_ERR("cannot get CG_IMAGE_SEN_CAM clock\n"); + + ret = clk_prepare_enable(isp_clk.CG_IMAGE_CAM_SV); + if (ret) + LOG_ERR("cannot get CG_IMAGE_CAM_SV clock\n"); + + ret = clk_prepare_enable(isp_clk.CG_IMAGE_LARB2_SMI); + if (ret) + LOG_ERR("cannot get CG_IMAGE_LARB2_SMI clock\n"); +} + +static inline void Enable_ccf_clock(void) +{ + int ret; + /* must keep this clk open order: CG_SCP_SYS_DIS-> CG_DISP0_SMI_COMMON -> CG_SCP_SYS_ISP -> ISP clk */ + ret = clk_enable(isp_clk.CG_SCP_SYS_DIS); + if (ret) + LOG_ERR("cannot get CG_SCP_SYS_DIS clock\n"); + + ret = clk_enable(isp_clk.CG_DISP0_SMI_COMMON); + if (ret) + LOG_ERR("cannot get CG_DISP0_SMI_COMMON clock\n"); + + ret = clk_enable(isp_clk.CG_SCP_SYS_ISP); + if (ret) + LOG_ERR("cannot get CG_SCP_SYS_ISP clock\n"); + + ret = clk_enable(isp_clk.CG_IMAGE_CAM_SMI); + if (ret) + LOG_ERR("cannot get CG_IMAGE_CAM_SMI clock\n"); + + ret = clk_enable(isp_clk.CG_IMAGE_CAM_CAM); + if (ret) + LOG_ERR("cannot get CG_IMAGE_CAM_CAM clock\n"); + + ret = clk_enable(isp_clk.CG_IMAGE_SEN_TG); + if (ret) + LOG_ERR("cannot get CG_IMAGE_SEN_TG clock\n"); + + ret = clk_enable(isp_clk.CG_IMAGE_SEN_CAM); + if (ret) + LOG_ERR("cannot get CG_IMAGE_SEN_CAM clock\n"); + + ret = clk_enable(isp_clk.CG_IMAGE_CAM_SV); + if (ret) + LOG_ERR("cannot get CG_IMAGE_CAM_SV clock\n"); + + ret = clk_enable(isp_clk.CG_IMAGE_LARB2_SMI); + if (ret) + LOG_ERR("cannot get CG_IMAGE_LARB2_SMI clock\n"); +} + +static inline void Disable_ccf_clock(void) +{ + /* must keep this clk close order: ISP clk -> CG_SCP_SYS_ISP -> CG_DISP0_SMI_COMMON -> CG_SCP_SYS_DIS */ + clk_disable(isp_clk.CG_IMAGE_CAM_SMI); + clk_disable(isp_clk.CG_IMAGE_CAM_CAM); + clk_disable(isp_clk.CG_IMAGE_SEN_TG); + clk_disable(isp_clk.CG_IMAGE_SEN_CAM); + clk_disable(isp_clk.CG_IMAGE_CAM_SV); + clk_disable(isp_clk.CG_IMAGE_LARB2_SMI); + clk_disable(isp_clk.CG_SCP_SYS_ISP); + clk_disable(isp_clk.CG_DISP0_SMI_COMMON); + clk_disable(isp_clk.CG_SCP_SYS_DIS); +} + +static inline void Unprepare_ccf_clock(void) +{ + /* must keep this clk close order: ISP clk -> CG_SCP_SYS_ISP -> CG_DISP0_SMI_COMMON -> CG_SCP_SYS_DIS */ + clk_unprepare(isp_clk.CG_IMAGE_CAM_SMI); + clk_unprepare(isp_clk.CG_IMAGE_CAM_CAM); + clk_unprepare(isp_clk.CG_IMAGE_SEN_TG); + clk_unprepare(isp_clk.CG_IMAGE_SEN_CAM); + clk_unprepare(isp_clk.CG_IMAGE_CAM_SV); + clk_unprepare(isp_clk.CG_IMAGE_LARB2_SMI); + clk_unprepare(isp_clk.CG_SCP_SYS_ISP); + clk_unprepare(isp_clk.CG_DISP0_SMI_COMMON); + clk_unprepare(isp_clk.CG_SCP_SYS_DIS); +} + +static inline void Disable_Unprepare_ccf_clock(void) +{ + /* must keep this clk close order: ISP clk -> CG_SCP_SYS_ISP -> CG_DISP0_SMI_COMMON -> CG_SCP_SYS_DIS */ + clk_disable_unprepare(isp_clk.CG_IMAGE_CAM_SMI); + clk_disable_unprepare(isp_clk.CG_IMAGE_CAM_CAM); + clk_disable_unprepare(isp_clk.CG_IMAGE_SEN_TG); + clk_disable_unprepare(isp_clk.CG_IMAGE_SEN_CAM); + clk_disable_unprepare(isp_clk.CG_IMAGE_CAM_SV); + clk_disable_unprepare(isp_clk.CG_IMAGE_LARB2_SMI); + clk_disable_unprepare(isp_clk.CG_SCP_SYS_ISP); + clk_disable_unprepare(isp_clk.CG_DISP0_SMI_COMMON); + clk_disable_unprepare(isp_clk.CG_SCP_SYS_DIS); +} + +#endif +/******************************************************************************* +* +********************************************************************************/ +static void ISP_EnableClock(MBOOL En) +{ + /* + if (G_u4EnableClockCount == 1) { + LOG_DBG("- E. En: %d. G_u4EnableClockCount: %d.", En, G_u4EnableClockCount); + } + */ + if (En) { + /* from SY yang,,*IMG_CG_CLR = 0xffffffff; + *MMSYS_CG_CLR0 = 0x00000003;*CLK_CFG_7 = *CLK_CFG_7 | 0x02000000;*CAM_CTL_CLK_EN = 0x00000009; */ + /* address map, MMSYS_CG_CLR0:0x14000108,CLK_CFG_7:0x100000b0 */ +#ifdef CONFIG_MTK_CLKMGR + spin_lock(&(IspInfo.SpinLockClock)); + /* LOG_DBG("Camera clock enbled. G_u4EnableClockCount: %d.", G_u4EnableClockCount); */ + switch (G_u4EnableClockCount) { + case 0: + /* LOG_INF("MTK_LEGACY:enable clk"); */ + enable_clock(MT_CG_DISP0_SMI_COMMON, "CAMERA"); + enable_clock(MT_CG_IMAGE_CAM_SMI, "CAMERA"); + enable_clock(MT_CG_IMAGE_CAM_CAM, "CAMERA"); + enable_clock(MT_CG_IMAGE_SEN_TG, "CAMERA"); + enable_clock(MT_CG_IMAGE_SEN_CAM, "CAMERA"); + enable_clock(MT_CG_IMAGE_CAM_SV, "CAMERA"); + /* enable_clock(MT_CG_IMAGE_FD, "CAMERA"); */ + enable_clock(MT_CG_IMAGE_LARB2_SMI, "CAMERA"); + break; + default: + break; + } + G_u4EnableClockCount++; + spin_unlock(&(IspInfo.SpinLockClock)); +#else + /*LOG_INF("CCF:prepare_enable clk cnt %d\n", G_u4EnableClockCount);*/ + spin_lock(&(IspInfo.SpinLockClock)); + G_u4EnableClockCount++; + spin_unlock(&(IspInfo.SpinLockClock)); + Prepare_Enable_ccf_clock(); +#endif + } else { /* Disable clock. */ +#ifdef CONFIG_MTK_CLKMGR + spin_lock(&(IspInfo.SpinLockClock)); + /* LOG_DBG("Camera clock disabled. G_u4EnableClockCount: %d.", G_u4EnableClockCount); */ + G_u4EnableClockCount--; + switch (G_u4EnableClockCount) { + case 0: + /*LOG_INF("MTK_LEGACY:disable clk"); */ + /* do disable clock */ + disable_clock(MT_CG_IMAGE_CAM_SMI, "CAMERA"); + disable_clock(MT_CG_IMAGE_CAM_CAM, "CAMERA"); + disable_clock(MT_CG_IMAGE_SEN_TG, "CAMERA"); + disable_clock(MT_CG_IMAGE_SEN_CAM, "CAMERA"); + disable_clock(MT_CG_IMAGE_CAM_SV, "CAMERA"); + /* disable_clock(MT_CG_IMAGE_FD, "CAMERA"); */ + disable_clock(MT_CG_IMAGE_LARB2_SMI, "CAMERA"); + disable_clock(MT_CG_DISP0_SMI_COMMON, "CAMERA"); + break; + default: + break; + } + spin_unlock(&(IspInfo.SpinLockClock)); +#else + /*LOG_INF("CCF:disable_unprepare cnt %d\n", G_u4EnableClockCount);*/ + spin_lock(&(IspInfo.SpinLockClock)); + G_u4EnableClockCount--; + spin_unlock(&(IspInfo.SpinLockClock)); + Disable_Unprepare_ccf_clock(); +#endif + } +} + +/******************************************************************************* +* +********************************************************************************/ +static inline void ISP_Reset(MINT32 rst_path) +{ + /* ensure the view finder is disabe. 0: take_picture */ + /* ISP_CLR_BIT(ISP_REG_ADDR_EN1, 0); */ + MUINT32 Reg; + MUINT32 setReg; + MUINT32 LoopCnt = 5, i; + /* MUINT32 i, flags; */ + /* */ + LOG_DBG("- E."); + + LOG_DBG("isp gate clk(0x%x),rst_path(%d)", ISP_RD32(ISP_ADDR_CAMINF), rst_path); + + + if (rst_path == ISP_REG_SW_CTL_RST_CAM_P1) { + /* ISP Soft SW reset process */ +#if 1 + Reg = ISP_RD32(ISP_REG_ADDR_CAM_SW_CTL); + setReg = + (Reg & (~ISP_REG_SW_CTL_SW_RST_P1_MASK)) | (ISP_REG_SW_CTL_SW_RST_TRIG & + ISP_REG_SW_CTL_SW_RST_P1_MASK); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, setReg); + /* ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, 0); */ + i = LoopCnt; + do { + Reg = ISP_RD32(ISP_REG_ADDR_CAM_SW_CTL); + if (Reg & ISP_REG_SW_CTL_SW_RST_STATUS) + break; + udelay(100); + } while (--i); + + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, ISP_REG_SW_CTL_HW_RST); + + setReg = + (Reg & (~ISP_REG_SW_CTL_SW_RST_P1_MASK)) | (0x00 & + ISP_REG_SW_CTL_SW_RST_P1_MASK); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, setReg); +#else + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, ISP_REG_SW_CTL_SW_RST_TRIG); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, 0); + do { + Reg = ISP_RD32(ISP_REG_ADDR_CAM_SW_CTL); + } while ((!Reg) & ISP_REG_SW_CTL_SW_RST_STATUS); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, ISP_REG_SW_CTL_HW_RST); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, 0); +#endif + } else if (rst_path == ISP_REG_SW_CTL_RST_CAM_P2) { +#if 1 + Reg = ISP_RD32(ISP_REG_ADDR_CAM_SW_CTL); + setReg = + (Reg & (~ISP_REG_SW_CTL_SW_RST_P2_MASK)) | (ISP_REG_SW_CTL_SW_RST_P2_TRIG & + ISP_REG_SW_CTL_SW_RST_P2_MASK); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, setReg); + /* ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, 0); */ + i = LoopCnt; + do { + Reg = ISP_RD32(ISP_REG_ADDR_CAM_SW_CTL); + if (Reg & ISP_REG_SW_CTL_SW_RST_P2_STATUS) + break; + udelay(100); + } while (--i); + + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, ISP_REG_SW_CTL_HW_RST_P2); + + setReg = + (Reg & (~ISP_REG_SW_CTL_SW_RST_P2_MASK)) | (0x00 & + ISP_REG_SW_CTL_SW_RST_P2_MASK); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, setReg); + +#else + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, ISP_REG_SW_CTL_SW_RST_P2_TRIG); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, 0); + do { + Reg = ISP_RD32(ISP_REG_ADDR_CAM_SW_CTL); + } while ((!Reg) & ISP_REG_SW_CTL_SW_RST_P2_STATUS); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, ISP_REG_SW_CTL_HW_RST_P2); + ISP_WR32(ISP_REG_ADDR_CAM_SW_CTL, 0); +#endif + } else if (rst_path == ISP_REG_SW_CTL_RST_CAMSV) { + ISP_WR32(ISP_REG_ADDR_CAMSV_SW_CTL, ISP_REG_SW_CTL_SW_RST_TRIG); + ISP_WR32(ISP_REG_ADDR_CAMSV_SW_CTL, 0); + i = LoopCnt; + do { + Reg = ISP_RD32(ISP_REG_ADDR_CAMSV_SW_CTL); + if (Reg & ISP_REG_SW_CTL_SW_RST_STATUS) + break; + udelay(100); + } while (--i); + + ISP_WR32(ISP_REG_ADDR_CAMSV_SW_CTL, ISP_REG_SW_CTL_HW_RST); + ISP_WR32(ISP_REG_ADDR_CAMSV_SW_CTL, 0); + } else if (rst_path == ISP_REG_SW_CTL_RST_CAMSV2) { + ISP_WR32(ISP_REG_ADDR_CAMSV2_SW_CTL, ISP_REG_SW_CTL_SW_RST_TRIG); + ISP_WR32(ISP_REG_ADDR_CAMSV2_SW_CTL, 0); + i = LoopCnt; + do { + Reg = ISP_RD32(ISP_REG_ADDR_CAMSV2_SW_CTL); + if (Reg & ISP_REG_SW_CTL_SW_RST_STATUS) + break; + udelay(100); + } while (--i); + ISP_WR32(ISP_REG_ADDR_CAMSV2_SW_CTL, ISP_REG_SW_CTL_HW_RST); + ISP_WR32(ISP_REG_ADDR_CAMSV2_SW_CTL, 0); + } +#if 0 + /* need modify here */ + for (i = 0; i < _IRQ_MAX; i++) + spin_lock_irqsave(&(IspInfo.SpinLockIrq[i]), flags); + +#endif +#if 0 + spin_lock_irqsave(&(IspInfo.SpinLockIrq[_IRQ]), flags); + spin_lock_irqsave(&(IspInfo.SpinLockIrq[_IRQ_D]), flags); + spin_lock_irqsave(&(IspInfo.SpinLockIrq[_CAMSV_IRQ]), flags); + spin_lock_irqsave(&(IspInfo.SpinLockIrq[_CAMSV_D_IRQ]), flags); + for (i = 0; i < ISP_IRQ_TYPE_AMOUNT; i++) + IspInfo.IrqInfo.Status[i] = 0; + + for (i = 0; i < _ChannelMax; i++) + PrvAddr[i] = 0; + +#if 0 + for (i = 0; i < _IRQ_MAX; i++) + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[i]), flags); + +#endif + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[_CAMSV_D_IRQ]), flags); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[_CAMSV_IRQ]), flags); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[_IRQ_D]), flags); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[_IRQ]), flags); +/* */ +#endif + + + /* */ + LOG_DBG("- X."); +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_ReadReg(ISP_REG_IO_STRUCT *pRegIo) +{ + MUINT32 i; + MINT32 Ret = 0; + /* */ + ISP_REG_STRUCT reg; + /* MUINT32 * pData = (MUINT32*)pRegIo->Data; */ + ISP_REG_STRUCT *pData = (ISP_REG_STRUCT *) pRegIo->pData; + + for (i = 0; i < pRegIo->Count; i++) { + if (0 != get_user(reg.Addr, (MUINT32 *) pData)) { + LOG_ERR("get_user failed"); + Ret = -EFAULT; + goto EXIT; + } + /* pData++; */ + /* */ + if ((ISP_ADDR_CAMINF + reg.Addr >= ISP_ADDR) + && (ISP_ADDR_CAMINF + reg.Addr < (ISP_ADDR_CAMINF + ISP_RANGE))) { + reg.Val = ISP_RD32(ISP_ADDR_CAMINF + reg.Addr); + } else { + LOG_ERR("Wrong address(0x%x)", (unsigned int)(ISP_ADDR_CAMINF + reg.Addr)); + reg.Val = 0; + } + /* */ + + if (0 != put_user(reg.Val, (MUINT32 *) &(pData->Val))) { + LOG_ERR("put_user failed"); + Ret = -EFAULT; + goto EXIT; + } + pData++; + /* */ + } + /* */ +EXIT: + return Ret; +} + + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_WriteRegToHw(ISP_REG_STRUCT *pReg, MUINT32 Count) +{ + MINT32 Ret = 0; + MUINT32 i; + /* */ + if (IspInfo.DebugMask & ISP_DBG_WRITE_REG) + LOG_DBG("- E."); + + /* */ + spin_lock(&(IspInfo.SpinLockIsp)); + for (i = 0; i < Count; i++) { + if (IspInfo.DebugMask & ISP_DBG_WRITE_REG) + LOG_DBG("Addr(0x%08X), Val(0x%08X)", + (MUINT32) (ISP_ADDR_CAMINF + pReg[i].Addr), + (MUINT32) (pReg[i].Val)); + + if (((ISP_ADDR_CAMINF + pReg[i].Addr) >= ISP_ADDR) + && ((ISP_ADDR_CAMINF + pReg[i].Addr) < (ISP_ADDR_CAMINF + ISP_RANGE))) + ISP_WR32(ISP_ADDR_CAMINF + pReg[i].Addr, pReg[i].Val); + else + LOG_ERR("wrong address(0x%x)", + (unsigned int)(ISP_ADDR_CAMINF + pReg[i].Addr)); + + } + spin_unlock(&(IspInfo.SpinLockIsp)); + /* */ + return Ret; +} + +/******************************************************************************* +* +******************************************************************************** +static void ISP_BufWrite_Init(void) //Vent@20121106: Marked to remove build warning: 'ISP_BufWrite_Init' defined but not used [-Wunused-function] +{ + MUINT32 i; + // + if(IspInfo.DebugMask & ISP_DBG_BUF_WRITE) { + LOG_DBG("- E."); + } + // + for(i=0; i ISP_BUF_SIZE_WRITE) { + LOG_ERR("i = %d, BufWriteSize(%d)+Size(%d) > %d", i, + IspInfo.BufInfo.Write[i].Size, Size, ISP_BUF_SIZE_WRITE); + return false; + } + /* */ + if (copy_from_user + ((MUINT8 *) (IspInfo.BufInfo.Write[i].pData + + IspInfo.BufInfo.Write[i].Size), (MUINT8 *) pData, + Size) != 0) { + LOG_ERR("copy_from_user failed"); + return false; + } + /* */ + if (IspInfo.DebugMask & ISP_DBG_BUF_WRITE) + LOG_DBG("i = %d, BufSize = %d, Size = %d", i, + IspInfo.BufInfo.Write[i].Size, Size); + /* */ + IspInfo.BufInfo.Write[i].Size += Size; + return true; + } + } + /* */ + for (i = 0; i < ISP_BUF_WRITE_AMOUNT; i++) { + if (IspInfo.BufInfo.Write[i].Status == ISP_BUF_STATUS_EMPTY) { + if (Size > ISP_BUF_SIZE_WRITE) { + LOG_ERR("i = %d, Size(%d) > %d", i, Size, ISP_BUF_SIZE_WRITE); + return false; + } + /* */ + if (copy_from_user + ((MUINT8 *) (IspInfo.BufInfo.Write[i].pData), (MUINT8 *) pData, + Size) != 0) { + LOG_ERR("copy_from_user failed"); + return false; + } + /* */ + if (IspInfo.DebugMask & ISP_DBG_BUF_WRITE) + LOG_DBG("i = %d, Size = %d", i, Size); + /* */ + IspInfo.BufInfo.Write[i].Size = Size; + /* */ + IspInfo.BufInfo.Write[i].Status = ISP_BUF_STATUS_HOLD; + return true; + } + } + + /* */ + LOG_ERR("All write buffer are full of data!"); + return false; + +} + +/******************************************************************************* +* +********************************************************************************/ +static void ISP_BufWrite_SetReady(void) +{ + MUINT32 i; + /* */ + /* LOG_DBG("- E."); */ + /* */ + for (i = 0; i < ISP_BUF_WRITE_AMOUNT; i++) { + if (IspInfo.BufInfo.Write[i].Status == ISP_BUF_STATUS_HOLD) { + if (IspInfo.DebugMask & ISP_DBG_BUF_WRITE) + LOG_DBG("i = %d, Size = %d", i, IspInfo.BufInfo.Write[i].Size); + IspInfo.BufInfo.Write[i].Status = ISP_BUF_STATUS_READY; + } + } +} + +/******************************************************************************* +* +********************************************************************************/ +static MBOOL ISP_BufWrite_Get(MUINT32 *pIndex, MUINT32 *pSize, MUINT8 **ppData) +{ + MUINT32 i; + /* */ + /* LOG_DBG("- E."); */ + /* */ + for (i = 0; i < ISP_BUF_WRITE_AMOUNT; i++) { + if (IspInfo.BufInfo.Write[i].Status == ISP_BUF_STATUS_READY) { + if (IspInfo.DebugMask & ISP_DBG_BUF_WRITE) + LOG_DBG("i = %d, Size = %d", i, IspInfo.BufInfo.Write[i].Size); + + *pIndex = i; + *pSize = IspInfo.BufInfo.Write[i].Size; + *ppData = IspInfo.BufInfo.Write[i].pData; + return true; + } + } + /* */ + if (IspInfo.DebugMask & ISP_DBG_BUF_WRITE) + LOG_DBG("No buf is ready!"); + return false; +} + +/******************************************************************************* +* +********************************************************************************/ +static MBOOL ISP_BufWrite_Clear(MUINT32 Index) +{ + /* */ + /* LOG_DBG("- E."); */ + /* */ + if (IspInfo.BufInfo.Write[Index].Status == ISP_BUF_STATUS_READY) { + if (IspInfo.DebugMask & ISP_DBG_BUF_WRITE) + LOG_DBG("Index = %d, Size = %d", Index, IspInfo.BufInfo.Write[Index].Size); + + IspInfo.BufInfo.Write[Index].Size = 0; + IspInfo.BufInfo.Write[Index].Status = ISP_BUF_STATUS_EMPTY; + return true; + } else { + LOG_DBG("WARNING: Index(%d) is not ready! Status = %d", Index, + IspInfo.BufInfo.Write[Index].Status); + return false; + } +} + +/******************************************************************************* +* +********************************************************************************/ +static void ISP_BufWrite_WriteToHw(void) +{ + MUINT8 *pBuf; + MUINT32 Index, BufSize; + /* */ + spin_lock(&(IspInfo.SpinLockHold)); + /* */ + LOG_DBG("- E."); + /* */ + while (ISP_BufWrite_Get(&Index, &BufSize, &pBuf)) { + + if (IspInfo.DebugMask & ISP_DBG_TASKLET) + LOG_DBG("Index = %d, BufSize = %d ", Index, BufSize); + + ISP_WriteRegToHw((ISP_REG_STRUCT *) pBuf, BufSize / sizeof(ISP_REG_STRUCT)); + ISP_BufWrite_Clear(Index); + } + /* LOG_DBG("No more buf."); */ + atomic_set(&(IspInfo.HoldInfo.WriteEnable), 0); + wake_up_interruptible_all((wait_queue_head_t *)&(IspInfo.WaitQueueHead)); + /* */ + spin_unlock(&(IspInfo.SpinLockHold)); +} + + +/******************************************************************************* +* +********************************************************************************/ +void ISP_ScheduleWork_VD(struct work_struct *data) +{ + if (IspInfo.DebugMask & ISP_DBG_SCHEDULE_WORK) + LOG_DBG("- E."); + /* */ + IspInfo.TimeLog.WorkQueueVd = ISP_JiffiesToMs(jiffies); + /* */ + if (IspInfo.Callback[ISP_CALLBACK_WORKQUEUE_VD].Func != NULL) + IspInfo.Callback[ISP_CALLBACK_WORKQUEUE_VD].Func(); +} + +/******************************************************************************* +* +********************************************************************************/ +void ISP_ScheduleWork_EXPDONE(struct work_struct *data) +{ + if (IspInfo.DebugMask & ISP_DBG_SCHEDULE_WORK) + LOG_DBG("- E."); + /* */ + IspInfo.TimeLog.WorkQueueExpdone = ISP_JiffiesToMs(jiffies); + /* */ + if (IspInfo.Callback[ISP_CALLBACK_WORKQUEUE_EXPDONE].Func != NULL) + IspInfo.Callback[ISP_CALLBACK_WORKQUEUE_EXPDONE].Func(); +} + +/******************************************************************************* +* +********************************************************************************/ +void ISP_Tasklet_VD(unsigned long Param) +{ + if (IspInfo.DebugMask & ISP_DBG_TASKLET) + LOG_DBG("- E."); + /* */ + IspInfo.TimeLog.TaskletVd = ISP_JiffiesToMs(jiffies); + /* */ + if (IspInfo.Callback[ISP_CALLBACK_TASKLET_VD].Func != NULL) + IspInfo.Callback[ISP_CALLBACK_TASKLET_VD].Func(); + /* */ + if (IspInfo.HoldInfo.Time == ISP_HOLD_TIME_VD) + ISP_BufWrite_WriteToHw(); +} + +DECLARE_TASKLET(IspTaskletVD, ISP_Tasklet_VD, 0); + +/******************************************************************************* +* +********************************************************************************/ +void ISP_Tasklet_EXPDONE(unsigned long Param) +{ + if (IspInfo.DebugMask & ISP_DBG_TASKLET) + LOG_DBG("- E."); + /* */ + IspInfo.TimeLog.TaskletExpdone = ISP_JiffiesToMs(jiffies); + /* */ + if (IspInfo.Callback[ISP_CALLBACK_TASKLET_EXPDONE].Func != NULL) + IspInfo.Callback[ISP_CALLBACK_TASKLET_EXPDONE].Func(); + + /* */ + if (IspInfo.HoldInfo.Time == ISP_HOLD_TIME_EXPDONE) + ISP_BufWrite_WriteToHw(); + +} + +DECLARE_TASKLET(IspTaskletEXPDONE, ISP_Tasklet_EXPDONE, 0); + + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_WriteReg(ISP_REG_IO_STRUCT *pRegIo) +{ + MINT32 Ret = 0; + MINT32 TimeVd = 0; + MINT32 TimeExpdone = 0; + MINT32 TimeTasklet = 0; + /* MUINT8* pData = NULL; */ + ISP_REG_STRUCT *pData = NULL; + + if (pRegIo->Count > (PAGE_SIZE/sizeof(MUINT32))) { + LOG_ERR("pRegIo->Count error"); + Ret = -EFAULT; + goto EXIT; + } + /* */ + if (IspInfo.DebugMask & ISP_DBG_WRITE_REG) { + /* LOG_DBG("Data(0x%08X), Count(%d)", (MUINT32)(pRegIo->pData), (MUINT32)(pRegIo->Count)); */ + LOG_DBG("Data(0x%p), Count(%d)", (pRegIo->pData), (pRegIo->Count)); + } + /* */ + if (atomic_read(&(IspInfo.HoldInfo.HoldEnable))) { + /* if(ISP_BufWrite_Add((pRegIo->Count)*sizeof(ISP_REG_STRUCT), (MUINT8*)(pRegIo->Data))) */ + if (ISP_BufWrite_Add((pRegIo->Count) * sizeof(ISP_REG_STRUCT), pRegIo->pData)) { + /* LOG_DBG("Add write buffer OK"); */ + } else { + LOG_ERR("Add write buffer fail"); + TimeVd = ISP_JiffiesToMs(jiffies) - IspInfo.TimeLog.Vd; + TimeExpdone = ISP_JiffiesToMs(jiffies) - IspInfo.TimeLog.Expdone; + TimeTasklet = ISP_JiffiesToMs(jiffies) - IspInfo.TimeLog.TaskletExpdone; + LOG_ERR("HoldTime(%d), VD(%d ms), Expdone(%d ms), Tasklet(%d ms)", + IspInfo.HoldInfo.Time, TimeVd, TimeExpdone, TimeTasklet); + ISP_BufWrite_Dump(); + ISP_DumpReg(); + Ret = -EFAULT; + goto EXIT; + } + } else { + /* pData = (MUINT8*)kmalloc((pRegIo->Count)*sizeof(ISP_REG_STRUCT), GFP_ATOMIC); */ + pData = + (ISP_REG_STRUCT *) kmalloc((pRegIo->Count) * sizeof(ISP_REG_STRUCT), + GFP_ATOMIC); + if (pData == NULL) { + LOG_DBG("ERROR: kmalloc failed, (process, pid, tgid)=(%s, %d, %d)", + current->comm, current->pid, current->tgid); + Ret = -ENOMEM; + goto EXIT; + } + /* */ + if (copy_from_user + (pData, (void __user *)(pRegIo->pData), + pRegIo->Count * sizeof(ISP_REG_STRUCT)) != 0) { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + goto EXIT; + } + /* */ + Ret = ISP_WriteRegToHw( + /* (ISP_REG_STRUCT*)pData, */ + pData, pRegIo->Count); + } + /* */ +EXIT: + if (pData != NULL) { + kfree(pData); + pData = NULL; + } + return Ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_SetHoldTime(ISP_HOLD_TIME_ENUM HoldTime) +{ + LOG_DBG("HoldTime(%d)", HoldTime); + IspInfo.HoldInfo.Time = HoldTime; + /* */ + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_ResetBuf(void) +{ + LOG_DBG("- E. hold_reg(%d), BufAmount(%d)", atomic_read(&(IspInfo.HoldInfo.HoldEnable)), + ISP_BufWrite_GetAmount()); + /* */ + ISP_BufWrite_Reset(); + atomic_set(&(IspInfo.HoldInfo.HoldEnable), 0); + atomic_set(&(IspInfo.HoldInfo.WriteEnable), 0); + LOG_DBG("- X."); + return 0; +} + + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_EnableHoldReg(MBOOL En) +{ + MINT32 Ret = 0; + MUINT32 BufAmount = 0; + /* */ + if (IspInfo.DebugMask & ISP_DBG_HOLD_REG) + LOG_DBG("En(%d), HoldEnable(%d)", En, atomic_read(&(IspInfo.HoldInfo.HoldEnable))); + + /* */ + if (!spin_trylock_bh(&(IspInfo.SpinLockHold))) { + /* Should wait until tasklet done. */ + MINT32 Timeout; + MINT32 IsLock = 0; + /* */ + if (IspInfo.DebugMask & ISP_DBG_TASKLET) + LOG_DBG("Start wait ... "); + + /* */ + Timeout = wait_event_interruptible_timeout(IspInfo.WaitQueueHead, + (IsLock = + spin_trylock_bh(& + (IspInfo. + SpinLockHold))), + ISP_MsToJiffies(500)); + /* */ + if (IspInfo.DebugMask & ISP_DBG_TASKLET) + LOG_DBG("End wait "); + + /* */ + if (IsLock == 0) { + LOG_ERR("Should not happen, Timeout & IsLock is 0"); + Ret = -EFAULT; + goto EXIT; + } + } + /* Here we get the lock. */ + if (En == MFALSE) { + ISP_BufWrite_SetReady(); + BufAmount = ISP_BufWrite_GetAmount(); + /* */ + if (BufAmount) + atomic_set(&(IspInfo.HoldInfo.WriteEnable), 1); + + } + /* */ + if (IspInfo.DebugMask & ISP_DBG_HOLD_REG) + LOG_DBG("En(%d), HoldEnable(%d), BufAmount(%d)", En, + atomic_read(&(IspInfo.HoldInfo.HoldEnable)), BufAmount); + + /* */ + atomic_set(&(IspInfo.HoldInfo.HoldEnable), En); + /* */ + spin_unlock_bh(&(IspInfo.SpinLockHold)); + /* */ +EXIT: + return Ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static atomic_t g_imem_ref_cnt[ISP_REF_CNT_ID_MAX]; +/* */ +/* static long ISP_REF_CNT_CTRL_FUNC(MUINT32 Param) */ +static long ISP_REF_CNT_CTRL_FUNC(unsigned long Param) +{ + MINT32 Ret = 0; + ISP_REF_CNT_CTRL_STRUCT ref_cnt_ctrl; + MINT32 imem_ref_cnt = 0; + + LOG_DBG("[rc]+ QQ"); /* for memory corruption check */ + + + /* //////////////////---add lock here */ +/* spin_lock_irq(&(IspInfo.SpinLock));*/ + /* ////////////////// */ + /* */ + if (IspInfo.DebugMask & ISP_DBG_REF_CNT_CTRL) + LOG_DBG("[rc]+"); + + /* */ + if (NULL == (void __user *)Param) { + LOG_ERR("[rc]NULL Param"); + /* //////////////////---add unlock here */ + /* spin_unlock_irqrestore(&(IspInfo.SpinLock), flags); */ + /* ////////////////// */ + return -EFAULT; + } + /* */ + if (copy_from_user(&ref_cnt_ctrl, (void __user *)Param, sizeof(ISP_REF_CNT_CTRL_STRUCT)) == + 0) { + + if (IspInfo.DebugMask & ISP_DBG_REF_CNT_CTRL) + LOG_DBG("[rc]ctrl(%d),id(%d)", ref_cnt_ctrl.ctrl, ref_cnt_ctrl.id); + + /* */ + if (ISP_REF_CNT_ID_MAX > ref_cnt_ctrl.id) { + /* //////////////////---add lock here */ + spin_lock(&(IspInfo.SpinLockIspRef)); + /* ////////////////// */ + /* */ + switch (ref_cnt_ctrl.ctrl) { + case ISP_REF_CNT_GET: + break; + case ISP_REF_CNT_INC: + atomic_inc(&g_imem_ref_cnt[ref_cnt_ctrl.id]); + /* g_imem_ref_cnt++; */ + break; + case ISP_REF_CNT_DEC: + case ISP_REF_CNT_DEC_AND_RESET_P1_P2_IF_LAST_ONE: + case ISP_REF_CNT_DEC_AND_RESET_P1_IF_LAST_ONE: + case ISP_REF_CNT_DEC_AND_RESET_P2_IF_LAST_ONE: + atomic_dec(&g_imem_ref_cnt[ref_cnt_ctrl.id]); + /* g_imem_ref_cnt--; */ + break; + default: + case ISP_REF_CNT_MAX: + /* Add this to remove build warning. */ + /* Do nothing. */ + break; + } + /* */ + imem_ref_cnt = (MINT32) atomic_read(&g_imem_ref_cnt[ref_cnt_ctrl.id]); + + if (imem_ref_cnt == 0) { + /* No user left and ctrl is RESET_IF_LAST_ONE, do ISP reset. */ + if (ref_cnt_ctrl.ctrl == ISP_REF_CNT_DEC_AND_RESET_P1_P2_IF_LAST_ONE + || ref_cnt_ctrl.ctrl == + ISP_REF_CNT_DEC_AND_RESET_P1_IF_LAST_ONE) { + ISP_Reset(ISP_REG_SW_CTL_RST_CAM_P1); + LOG_DBG("Reset P1\n"); + } + + if (ref_cnt_ctrl.ctrl == ISP_REF_CNT_DEC_AND_RESET_P1_P2_IF_LAST_ONE + || ref_cnt_ctrl.ctrl == + ISP_REF_CNT_DEC_AND_RESET_P2_IF_LAST_ONE) + ISP_Reset(ISP_REG_SW_CTL_RST_CAM_P2); + + } + /* //////////////////---add unlock here */ + spin_unlock(&(IspInfo.SpinLockIspRef)); + /* ////////////////// */ + + /* */ + if (IspInfo.DebugMask & ISP_DBG_REF_CNT_CTRL) + LOG_DBG("[rc]ref_cnt(%d)", imem_ref_cnt); + + /* */ + if (copy_to_user + ((void *)ref_cnt_ctrl.data_ptr, &imem_ref_cnt, sizeof(MINT32)) != 0) { + LOG_ERR("[rc][GET]:copy_to_user failed"); + Ret = -EFAULT; + } + } else { + LOG_ERR("[rc]:id(%d) exceed", ref_cnt_ctrl.id); + Ret = -EFAULT; + } + + } else { + LOG_ERR("[rc]copy_from_user failed"); + Ret = -EFAULT; + } + + /* */ + if (IspInfo.DebugMask & ISP_DBG_REF_CNT_CTRL) + LOG_DBG("[rc]-"); + + + LOG_DBG("[rc]QQ return value:(%d)", Ret); + /* */ + /* //////////////////---add unlock here */ +/* spin_unlock_irqrestore(&(IspInfo.SpinLock), flags);*/ + /* ////////////////// */ + return Ret; +} + +/******************************************************************************* +* +********************************************************************************/ +/* js_test */ +/* */ +#ifndef _rtbc_use_cq0c_ +static MUINT32 bEnqBuf; +static MUINT32 bDeqBuf; +static MINT32 rtbc_enq_dma = _rt_dma_max_; +static MINT32 rtbc_deq_dma = _rt_dma_max_; +#endif + +static MUINT32 prv_tstamp_s[_rt_dma_max_] = { 0 }; +static MUINT32 prv_tstamp_us[_rt_dma_max_] = { 0 }; + +static volatile MUINT32 sof_count[_ChannelMax] = { 0, 0, 0, 0 }; +static MUINT32 start_time[_ChannelMax] = { 0, 0, 0, 0 }; +static MUINT32 avg_frame_time[_ChannelMax] = { 0, 0, 0, 0 }; + + +/* record lost p1_done or not, 1 for lost p1_done. 0 for normal , 2 for last working buffer. */ +static volatile int sof_pass1done[2] = { 0, 0 }; + +static volatile MUINT32 lost_pass1_done_cnt; +static volatile MUINT32 lost_pass1_d_done_cnt; +/* record lost p1_done or not, 1 for lost p1_done. 0 for normal , 2 for last working buffer. */ +static volatile MUINT32 gSof_camsvdone[2] = { 0, 0 }; + +static volatile MBOOL g1stSof[4] = { MTRUE, MTRUE }; + +#ifdef _rtbc_buf_que_2_0_ +typedef struct _FW_RCNT_CTRL { + MUINT32 INC[_IRQ_MAX][ISP_RT_BUF_SIZE]; /* rcnt_in */ + MUINT32 DMA_IDX[_rt_dma_max_]; /* enque cnt */ + MUINT32 rdIdx[_IRQ_MAX]; /* enque read cnt */ + MUINT32 curIdx[_IRQ_MAX]; /* record avail rcnt pair */ + MUINT32 bLoadBaseAddr[_IRQ_MAX]; +} FW_RCNT_CTRL; +static volatile FW_RCNT_CTRL mFwRcnt = { {{0} }, {0}, {0}, {0}, {0} }; +static MUINT8 dma_en_recorder[_rt_dma_max_][ISP_RT_BUF_SIZE] = { {0} }; +#endif +/* */ +static MINT32 ISP_RTBC_ENQUE(MINT32 dma, ISP_RT_BUF_INFO_STRUCT *prt_buf_info) +{ + MINT32 Ret = 0; + MINT32 rt_dma = dma; + MUINT32 buffer_exist = 0; + MUINT32 i = 0; + MUINT32 index = 0; + + /* check max */ + if (ISP_RT_BUF_SIZE == pstRTBuf->ring_buf[rt_dma].total_count) { + LOG_ERR("[rtbc][ENQUE]:real time buffer number FULL:rt_dma(%d)", rt_dma); + Ret = -EFAULT; + /* break; */ + } + + /* */ + /* spin_lock_irqsave(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + /* check if buffer exist */ + for (i = 0; i < ISP_RT_BUF_SIZE; i++) { + if (pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr == prt_buf_info->base_pAddr) { + buffer_exist = 1; + break; + } + /* */ + if (pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr == 0) + break; + + } + /* */ + if (buffer_exist) { + /* */ + if (ISP_RTBC_BUF_EMPTY != pstRTBuf->ring_buf[rt_dma].data[i].bFilled) { + pstRTBuf->ring_buf[rt_dma].data[i].bFilled = ISP_RTBC_BUF_EMPTY; + pstRTBuf->ring_buf[rt_dma].empty_count++; + index = i; + } + /* */ + /* if(IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { */ + LOG_DBG("[rtbc][ENQUE]::buffer_exist(%d)/i(%d)/PA(0x%x)/bFilled(%d)/empty(%d)", + buffer_exist, + i, + prt_buf_info->base_pAddr, + pstRTBuf->ring_buf[rt_dma].data[i].bFilled, + pstRTBuf->ring_buf[rt_dma].empty_count); + /* } */ + + } else { + /* overwrite oldest element if buffer is full */ + if (pstRTBuf->ring_buf[rt_dma].total_count == ISP_RT_BUF_SIZE) { + LOG_ERR("[ENQUE]:[rtbc]:buffer full(%d)", + pstRTBuf->ring_buf[rt_dma].total_count); + } else { + /* first time add */ + index = pstRTBuf->ring_buf[rt_dma].total_count % ISP_RT_BUF_SIZE; + /* */ + pstRTBuf->ring_buf[rt_dma].data[index].memID = prt_buf_info->memID; + pstRTBuf->ring_buf[rt_dma].data[index].size = prt_buf_info->size; + pstRTBuf->ring_buf[rt_dma].data[index].base_vAddr = + prt_buf_info->base_vAddr; + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr = + prt_buf_info->base_pAddr; + pstRTBuf->ring_buf[rt_dma].data[index].bFilled = ISP_RTBC_BUF_EMPTY; + pstRTBuf->ring_buf[rt_dma].data[index].bufIdx = prt_buf_info->bufIdx; + /* */ + pstRTBuf->ring_buf[rt_dma].total_count++; + pstRTBuf->ring_buf[rt_dma].empty_count++; + /* */ + /* if(IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { */ + LOG_DBG + ("[rtbc][ENQUE]:dma(%d),index(%d),bufIdx(0x%x),PA(0x%x)/empty(%d)/total(%d)", + rt_dma, index, prt_buf_info->bufIdx, + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr, + pstRTBuf->ring_buf[rt_dma].empty_count, + pstRTBuf->ring_buf[rt_dma].total_count); + /* } */ + } + } + /* */ + + /* count ==1 means DMA stalled already or NOT start yet */ + if (1 == pstRTBuf->ring_buf[rt_dma].empty_count) { + if (_imgo_ == rt_dma) { + /* set base_addr at beginning before VF_EN */ + ISP_WR32(ISP_REG_ADDR_IMGO_BASE_ADDR, + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr); + } else if (_rrzo_ == rt_dma) { + /* set base_addr at beginning before VF_EN */ + ISP_WR32(ISP_REG_ADDR_RRZO_BASE_ADDR, + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr); + } else if (_imgo_d_ == rt_dma) { + /* set base_addr at beginning before VF_EN */ + ISP_WR32(ISP_REG_ADDR_IMGO_D_BASE_ADDR, + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr); + } else if (_rrzo_d_ == rt_dma) { + /* set base_addr at beginning before VF_EN */ + ISP_WR32(ISP_REG_ADDR_RRZO_D_BASE_ADDR, + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr); + } else if (_camsv_imgo_ == rt_dma) { + /*ISP_WR32(ISP_REG_ADDR_IMGO_SV_BASE_ADDR, + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr);*/ + LOG_INF("[rtbc][ENQUE]IMGO_SV:addr should write by MVHDR"); + } else if (_camsv2_imgo_ == rt_dma) { + /*ISP_WR32(ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR, + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr);*/ + LOG_INF("[rtbc][ENQUE]IMGO_SV_D:addr should write by PD"); + } + + /* if(IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { */ + LOG_DBG + ("[rtbc][ENQUE]:dma(%d),base_pAddr(0x%x)/imgo(0x%x)/rrzo(0x%x)/imgo_d(0x%x)/rrzo_d(0x%x)/empty_count(%d) ", + rt_dma, pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr, + ISP_RD32(ISP_REG_ADDR_IMGO_BASE_ADDR), ISP_RD32(ISP_REG_ADDR_RRZO_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_IMGO_D_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_RRZO_D_BASE_ADDR), + pstRTBuf->ring_buf[rt_dma].empty_count); + + + /* } */ + +#if defined(_rtbc_use_cq0c_) + /* Do nothing */ +#else + MUINT32 reg_val = 0; + + /* disable FBC control to go on download */ + if (_imgo_ == rt_dma) { + reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_FBC); + reg_val &= ~0x4000; + ISP_WR32(ISP_REG_ADDR_IMGO_FBC, reg_val); + } else { + reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_D_FBC); + reg_val &= ~0x4000; + ISP_WR32(ISP_REG_ADDR_IMGO_D_FBC, reg_val); + } + + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) + LOG_DBG("[rtbc][ENQUE]:dma(%d),disable fbc:IMGO(0x%x),IMG2O(0x%x)", rt_dma, + ISP_RD32(ISP_REG_ADDR_IMGO_FBC), ISP_RD32(ISP_REG_ADDR_IMGO_D_FBC)); + +#endif + pstRTBuf->ring_buf[rt_dma].pre_empty_count = pstRTBuf->ring_buf[rt_dma].empty_count; + + } + + /* */ + /* spin_unlock_irqrestore(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + /* */ + /* if(IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { */ + LOG_DBG("[rtbc][ENQUE]:dma:(%d),start(%d),index(%d),empty_count(%d),base_pAddr(0x%x)", + rt_dma, + pstRTBuf->ring_buf[rt_dma].start, + index, + pstRTBuf->ring_buf[rt_dma].empty_count, + pstRTBuf->ring_buf[rt_dma].data[index].base_pAddr); + /* } */ + /* */ + return Ret; +} + +static void ISP_FBC_DUMP(MUINT32 dma_id, MUINT32 VF_1, MUINT32 VF_2, MUINT32 VF_3, MUINT32 VF_4) +{ + MUINT32 z; + char str[128]; + MINT32 strLeng = sizeof(str)-1; + char str2[_rt_dma_max_]; + MUINT32 dma; + + LOG_INF("================================\n"); + LOG_INF("pass1 timeout log(timeout port:%d)", dma_id); + LOG_INF("================================\n"); + str[0] = '\0'; + LOG_INF("current activated dmaport"); + for (z = 0; z < _rt_dma_max_; z++) { + sprintf(str2, "%d_", pstRTBuf->ring_buf[z].active); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + if (VF_1) { + LOG_INF("imgo:"); + dma = _imgo_; + str[0] = '\0'; + LOG_INF("current fillled buffer(%d):\n", pstRTBuf->ring_buf[dma].total_count); + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", pstRTBuf->ring_buf[dma].data[z].bFilled); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("cur_start_idx:%d", pstRTBuf->ring_buf[dma].start); + LOG_INF("cur_read_idx=%d", pstRTBuf->ring_buf[dma].read_idx); + LOG_INF("cur_empty_cnt:%d", pstRTBuf->ring_buf[dma].empty_count); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:cur dma_en_recorder\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", dma_en_recorder[dma][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:inc record\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", mFwRcnt.INC[_IRQ][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("RCNT_RECORD: dma idx = %d\n", mFwRcnt.DMA_IDX[dma]); + LOG_INF("RCNT_RECORD: read idx = %d\n", mFwRcnt.rdIdx[_IRQ]); + LOG_INF("RCNT_RECORD: cur idx = %d\n", mFwRcnt.curIdx[_IRQ]); + LOG_INF("RCNT_RECORD: bLoad = %d\n", mFwRcnt.bLoadBaseAddr[_IRQ]); + LOG_INF("================================\n"); + LOG_INF("rrzo:"); + dma = _rrzo_; + str[0] = '\0'; + LOG_INF("current fillled buffer(%d):\n", pstRTBuf->ring_buf[dma].total_count); + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", pstRTBuf->ring_buf[dma].data[z].bFilled); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("cur_start_idx:%d", pstRTBuf->ring_buf[dma].start); + LOG_INF("cur_read_idx=%d", pstRTBuf->ring_buf[dma].read_idx); + LOG_INF("cur_empty_cnt:%d", pstRTBuf->ring_buf[dma].empty_count); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:cur dma_en_recorder\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", dma_en_recorder[dma][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:inc record\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", mFwRcnt.INC[_IRQ][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("RCNT_RECORD: dma idx = %d\n", mFwRcnt.DMA_IDX[dma]); + LOG_INF("RCNT_RECORD: read idx = %d\n", mFwRcnt.rdIdx[_IRQ]); + LOG_INF("RCNT_RECORD: cur idx = %d\n", mFwRcnt.curIdx[_IRQ]); + LOG_INF("RCNT_RECORD: bLoad = %d\n", mFwRcnt.bLoadBaseAddr[_IRQ]); + LOG_INF("================================\n"); + } + + if (VF_2) { + LOG_INF("imgo_d:"); + dma = _imgo_d_; + str[0] = '\0'; + LOG_INF("current fillled buffer(%d):\n", pstRTBuf->ring_buf[dma].total_count); + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", pstRTBuf->ring_buf[dma].data[z].bFilled); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("cur_start_idx:%d", pstRTBuf->ring_buf[dma].start); + LOG_INF("cur_read_idx=%d", pstRTBuf->ring_buf[dma].read_idx); + LOG_INF("cur_empty_cnt:%d", pstRTBuf->ring_buf[dma].empty_count); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:cur dma_en_recorder\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", dma_en_recorder[dma][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:inc record\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", mFwRcnt.INC[_IRQ_D][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("RCNT_RECORD: dma idx = %d\n", mFwRcnt.DMA_IDX[dma]); + LOG_INF("RCNT_RECORD: read idx = %d\n", mFwRcnt.rdIdx[_IRQ_D]); + LOG_INF("RCNT_RECORD: cur idx = %d\n", mFwRcnt.curIdx[_IRQ_D]); + LOG_INF("RCNT_RECORD: bLoad = %d\n", mFwRcnt.bLoadBaseAddr[_IRQ_D]); + LOG_INF("================================\n"); + LOG_INF("rrzo_d:"); + dma = _rrzo_d_; + str[0] = '\0'; + LOG_INF("current fillled buffer(%d):\n", pstRTBuf->ring_buf[dma].total_count); + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", pstRTBuf->ring_buf[dma].data[z].bFilled); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("cur_start_idx:%d", pstRTBuf->ring_buf[dma].start); + LOG_INF("cur_read_idx=%d", pstRTBuf->ring_buf[dma].read_idx); + LOG_INF("cur_empty_cnt:%d", pstRTBuf->ring_buf[dma].empty_count); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:cur dma_en_recorder\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", dma_en_recorder[dma][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:inc record\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", mFwRcnt.INC[_IRQ_D][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("RCNT_RECORD: dma idx = %d\n", mFwRcnt.DMA_IDX[dma]); + LOG_INF("RCNT_RECORD: read idx = %d\n", mFwRcnt.rdIdx[_IRQ_D]); + LOG_INF("RCNT_RECORD: cur idx = %d\n", mFwRcnt.curIdx[_IRQ_D]); + LOG_INF("RCNT_RECORD: bLoad = %d\n", mFwRcnt.bLoadBaseAddr[_IRQ_D]); + LOG_INF("================================\n"); + } + + if (VF_3) { + LOG_INF("camsv_imgo:"); + dma = _camsv_imgo_; + { + str[0] = '\0'; + LOG_INF("current fillled buffer(%d):\n", + pstRTBuf->ring_buf[dma].total_count); + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", pstRTBuf->ring_buf[dma].data[z].bFilled); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("cur_start_idx:%d", pstRTBuf->ring_buf[dma].start); + LOG_INF("cur_read_idx=%d", pstRTBuf->ring_buf[dma].read_idx); + LOG_INF("cur_empty_cnt:%d", pstRTBuf->ring_buf[dma].empty_count); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:cur dma_en_recorder\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", dma_en_recorder[dma][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:inc record\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", mFwRcnt.INC[_CAMSV_IRQ][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("RCNT_RECORD: dma idx = %d\n", mFwRcnt.DMA_IDX[dma]); + LOG_INF("RCNT_RECORD: read idx = %d\n", mFwRcnt.rdIdx[_CAMSV_IRQ]); + LOG_INF("RCNT_RECORD: cur idx = %d\n", mFwRcnt.curIdx[_CAMSV_IRQ]); + LOG_INF("RCNT_RECORD: bLoad = %d\n", mFwRcnt.bLoadBaseAddr[_CAMSV_IRQ]); + LOG_INF("================================\n"); + } + } + + if (VF_4) { + LOG_INF("camsv2_imgo:"); + dma = _camsv2_imgo_; + str[0] = '\0'; + LOG_INF("current fillled buffer(%d):\n", pstRTBuf->ring_buf[dma].total_count); + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", pstRTBuf->ring_buf[dma].data[z].bFilled); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("cur_start_idx:%d", pstRTBuf->ring_buf[dma].start); + LOG_INF("cur_read_idx=%d", pstRTBuf->ring_buf[dma].read_idx); + LOG_INF("cur_empty_cnt:%d", pstRTBuf->ring_buf[dma].empty_count); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:cur dma_en_recorder\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", dma_en_recorder[dma][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("================================\n"); + LOG_INF("RCNT_RECORD:inc record\n"); + str[0] = '\0'; + for (z = 0; z < ISP_RT_BUF_SIZE; z++) { + sprintf(str2, "%d_", mFwRcnt.INC[_CAMSV_D_IRQ][z]); + strncat(str, str2, strLeng-strlen(str)); + } + LOG_INF("%s", str); + LOG_INF("RCNT_RECORD: dma idx = %d\n", mFwRcnt.DMA_IDX[dma]); + LOG_INF("RCNT_RECORD: read idx = %d\n", mFwRcnt.rdIdx[_CAMSV_D_IRQ]); + LOG_INF("RCNT_RECORD: cur idx = %d\n", mFwRcnt.curIdx[_CAMSV_D_IRQ]); + LOG_INF("RCNT_RECORD: bLoad = %d\n", mFwRcnt.bLoadBaseAddr[_CAMSV_D_IRQ]); + LOG_INF("================================\n"); + } +} + +static MINT32 ISP_RTBC_DEQUE(MINT32 dma, ISP_DEQUE_BUF_INFO_STRUCT *pdeque_buf) +{ + MINT32 Ret = 0; + MINT32 rt_dma = dma; + MUINT32 i = 0; + MUINT32 index = 0; + /* MUINT32 z; */ + /* spin_lock_irqsave(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + /* */ + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) + LOG_DBG("[rtbc][DEQUE]+"); + + /* */ + pdeque_buf->count = 0; + /* in SOF, "start" is next buffer index */ + for (i = 0; i < pstRTBuf->ring_buf[rt_dma].total_count; i++) { + index = + (pstRTBuf->ring_buf[rt_dma].start + i) % pstRTBuf->ring_buf[rt_dma].total_count; + + if (ISP_RTBC_BUF_FILLED == pstRTBuf->ring_buf[rt_dma].data[index].bFilled) { + pstRTBuf->ring_buf[rt_dma].data[index].bFilled = ISP_RTBC_BUF_LOCKED; + pdeque_buf->count = P1_DEQUE_CNT; + break; + } + } + /* */ + if (0 == pdeque_buf->count) { + /* queue buffer status */ + LOG_DBG + ("[rtbc][DEQUE]:dma(%d),start(%d),total(%d),empty(%d), pdeque_buf->count(%d) ", + rt_dma, pstRTBuf->ring_buf[rt_dma].start, + pstRTBuf->ring_buf[rt_dma].total_count, + pstRTBuf->ring_buf[rt_dma].empty_count, pdeque_buf->count); + /* */ + for (i = 0; i <= pstRTBuf->ring_buf[rt_dma].total_count - 1; i++) { + LOG_DBG("[rtbc][DEQUE]Buf List:%d/%d/0x%x/0x%llx/0x%x/%d/ ", + i, + pstRTBuf->ring_buf[rt_dma].data[i].memID, + pstRTBuf->ring_buf[rt_dma].data[i].size, + pstRTBuf->ring_buf[rt_dma].data[i].base_vAddr, + pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr, + pstRTBuf->ring_buf[rt_dma].data[i].bFilled); + } + } + /* */ + if (pdeque_buf->count) { + /* Fill buffer head */ + /* "start" is current working index */ + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { + LOG_DBG("[rtbc][DEQUE]:rt_dma(%d)/index(%d)/empty(%d)/total(%d)", + rt_dma, + index, + pstRTBuf->ring_buf[rt_dma].empty_count, + pstRTBuf->ring_buf[rt_dma].total_count); + } + /* */ + for (i = 0; i < pdeque_buf->count; i++) { + pdeque_buf->data[i].memID = + pstRTBuf->ring_buf[rt_dma].data[index + i].memID; + pdeque_buf->data[i].size = pstRTBuf->ring_buf[rt_dma].data[index + i].size; + pdeque_buf->data[i].base_vAddr = + pstRTBuf->ring_buf[rt_dma].data[index + i].base_vAddr; + pdeque_buf->data[i].base_pAddr = + pstRTBuf->ring_buf[rt_dma].data[index + i].base_pAddr; + pdeque_buf->data[i].timeStampS = + pstRTBuf->ring_buf[rt_dma].data[index + i].timeStampS; + pdeque_buf->data[i].timeStampUs = + pstRTBuf->ring_buf[rt_dma].data[index + i].timeStampUs; + /* */ + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { + LOG_DBG + ("[rtbc][DEQUE]:index(%d)/PA(0x%x)/memID(%d)/size(0x%x)/VA(0x%llx)", + index + i, pdeque_buf->data[i].base_pAddr, + pdeque_buf->data[i].memID, pdeque_buf->data[i].size, + pdeque_buf->data[i].base_vAddr); + } + } + /* */ + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) + LOG_DBG("[rtbc][DEQUE]-"); + + /* */ + /* spin_unlock_irqrestore(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + /* */ + } else { + /* */ + /* spin_unlock_irqrestore(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + LOG_ERR("[rtbc][DEQUE]:no filled buffer"); + Ret = -EFAULT; + } + + return Ret; +} + +#ifdef _MAGIC_NUM_ERR_HANDLING_ +#define _INVALID_FRM_CNT_ 0xFFFF +#define _MAX_FRM_CNT_ 0xFF + +#define _UNCERTAIN_MAGIC_NUM_FLAG_ 0x40000000 +#define _DUMMY_MAGIC_ 0x20000000 +static MUINT32 m_LastMNum[_rt_dma_max_] = { 0 }; /* imgo/rrzo */ + +#endif +/* static long ISP_Buf_CTRL_FUNC(MUINT32 Param) */ +static long ISP_Buf_CTRL_FUNC(unsigned long Param) +{ + MINT32 Ret = 0; + MINT32 rt_dma; + MUINT32 reg_val = 0; + MUINT32 reg_val2 = 0; + MUINT32 camsv_reg_cal[2] = { 0, 0 }; + MUINT32 i = 0; + MUINT32 x = 0; + MUINT32 z = 0; + MUINT32 iBuf = 0; + MUINT32 size = 0; + MUINT32 bWaitBufRdy = 0; + ISP_BUFFER_CTRL_STRUCT rt_buf_ctrl; + MBOOL _bFlag = MTRUE; + /* MUINT32 buffer_exist = 0; */ + CQ_RTBC_FBC *p1_fbc; + /* MUINT32 p1_fbc_reg[_rt_dma_max_]; */ + unsigned long *p1_fbc_reg; + /* MUINT32 p1_dma_addr_reg[_rt_dma_max_]; */ + unsigned long *p1_dma_addr_reg; + unsigned long flags; + ISP_RT_BUF_INFO_STRUCT *rt_buf_info; + ISP_DEQUE_BUF_INFO_STRUCT *deque_buf; + eISPIrq irqT = _IRQ_MAX; + eISPIrq irqT_Lock = _IRQ_MAX; + MBOOL CurVF_En = MFALSE; + /* */ + if (NULL == pstRTBuf) { + LOG_ERR("[rtbc]NULL pstRTBuf"); + return -EFAULT; + } + /* */ + if (copy_from_user(&rt_buf_ctrl, (void __user *)Param, sizeof(ISP_BUFFER_CTRL_STRUCT)) == 0) { + p1_fbc = kcalloc(_rt_dma_max_, sizeof(CQ_RTBC_FBC), GFP_KERNEL); + p1_fbc_reg = kcalloc(_rt_dma_max_, sizeof(unsigned long), GFP_KERNEL); + p1_dma_addr_reg = kcalloc(_rt_dma_max_, sizeof(unsigned long), GFP_KERNEL); + rt_buf_info = kmalloc(sizeof(ISP_RT_BUF_INFO_STRUCT), GFP_KERNEL); + deque_buf = kmalloc(sizeof(ISP_DEQUE_BUF_INFO_STRUCT), GFP_KERNEL); + if ((NULL == p1_fbc) || (NULL == p1_fbc_reg) || (NULL == p1_dma_addr_reg) || + (NULL == rt_buf_info) || (NULL == deque_buf)) { + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -ENOMEM; + } + rt_dma = rt_buf_ctrl.buf_id; + /* */ + /* if(IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { */ + /* LOG_DBG("[rtbc]ctrl(0x%x)/buf_id(0x%x)/data_ptr(0x%x)/ex_data_ptr(0x%x)\n", */ + /* rt_buf_ctrl.ctrl, \ */ + /* rt_buf_ctrl.buf_id, \ */ + /* rt_buf_ctrl.data_ptr, \ */ + /* rt_buf_ctrl.ex_data_ptr); */ + /* } */ + /* */ + if (_imgo_ == rt_dma || _rrzo_ == rt_dma || _imgo_d_ == rt_dma || _rrzo_d_ == rt_dma + || _camsv_imgo_ == rt_dma || _camsv2_imgo_ == rt_dma) { + +#if defined(_rtbc_use_cq0c_) + /* do nothing */ +#else /* for camsv */ + if ((_camsv_imgo_ == rt_dma) || (_camsv2_imgo_ == rt_dma)) + _bFlag = MTRUE; + else + _bFlag = MFALSE; +#endif + + if (MTRUE == _bFlag) { + if ((ISP_RT_BUF_CTRL_ENQUE == rt_buf_ctrl.ctrl) || + (ISP_RT_BUF_CTRL_DEQUE == rt_buf_ctrl.ctrl) || + (ISP_RT_BUF_CTRL_IS_RDY == rt_buf_ctrl.ctrl) || + (ISP_RT_BUF_CTRL_ENQUE_IMD == rt_buf_ctrl.ctrl)) { + /* */ + p1_fbc[_imgo_].Reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_FBC); + p1_fbc[_rrzo_].Reg_val = ISP_RD32(ISP_REG_ADDR_RRZO_FBC); + p1_fbc[_imgo_d_].Reg_val = + ISP_RD32(ISP_REG_ADDR_IMGO_D_FBC); + p1_fbc[_rrzo_d_].Reg_val = + ISP_RD32(ISP_REG_ADDR_RRZO_D_FBC); + + p1_fbc_reg[_imgo_] = ISP_REG_ADDR_IMGO_FBC; + p1_fbc_reg[_rrzo_] = ISP_REG_ADDR_RRZO_FBC; + p1_fbc_reg[_imgo_d_] = ISP_REG_ADDR_IMGO_D_FBC; + p1_fbc_reg[_rrzo_d_] = ISP_REG_ADDR_RRZO_D_FBC; + + p1_dma_addr_reg[_imgo_] = ISP_REG_ADDR_IMGO_BASE_ADDR; + p1_dma_addr_reg[_rrzo_] = ISP_REG_ADDR_RRZO_BASE_ADDR; + p1_dma_addr_reg[_imgo_d_] = ISP_REG_ADDR_IMGO_D_BASE_ADDR; + p1_dma_addr_reg[_rrzo_d_] = ISP_REG_ADDR_RRZO_D_BASE_ADDR; + + + p1_fbc[_camsv_imgo_].Reg_val = + ISP_RD32(ISP_REG_ADDR_CAMSV_IMGO_FBC); + p1_fbc[_camsv2_imgo_].Reg_val = + ISP_RD32(ISP_REG_ADDR_CAMSV2_IMGO_FBC); + + p1_fbc_reg[_camsv_imgo_] = ISP_REG_ADDR_CAMSV_IMGO_FBC; + p1_fbc_reg[_camsv2_imgo_] = ISP_REG_ADDR_CAMSV2_IMGO_FBC; + + p1_dma_addr_reg[_camsv_imgo_] = + ISP_REG_ADDR_IMGO_SV_BASE_ADDR; + p1_dma_addr_reg[_camsv2_imgo_] = + ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR; + /* */ +#if 0 + /**/ if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { + LOG_DBG + ("[rtbc]:ctrl(%d),o(0x%x),zo(0x%x),camsv(0x%x/0x%x)", + rt_buf_ctrl.ctrl, p1_fbc[_imgo_].Reg_val, + p1_fbc[_rrzo_].Reg_val, + p1_fbc[_camsv_imgo_].Reg_val, + p1_fbc[_camsv2_imgo_].Reg_val); + } +#endif + } + } + } else { +#ifdef _rtbc_buf_que_2_0_ + if (rt_buf_ctrl.ctrl != ISP_RT_BUF_CTRL_DMA_EN) +#endif + { + LOG_ERR("[rtbc]invalid dma channel(%d)", rt_dma); + + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EFAULT; + } + } + /* */ + switch (rt_buf_ctrl.ctrl) { + /* make sure rct_inc will be pulled at the same vd. */ + case ISP_RT_BUF_CTRL_EXCHANGE_ENQUE: + break; + case ISP_RT_BUF_CTRL_ENQUE: + case ISP_RT_BUF_CTRL_ENQUE_IMD: + /* case ISP_RT_BUF_CTRL_EXCHANGE_ENQUE: */ + /* */ + if (copy_from_user(rt_buf_info, (void __user *)rt_buf_ctrl.data_ptr, + sizeof(ISP_RT_BUF_INFO_STRUCT)) == 0) { + /* */ + reg_val = ISP_RD32(ISP_REG_ADDR_TG_VF_CON); + reg_val2 = ISP_RD32(ISP_REG_ADDR_TG2_VF_CON); + camsv_reg_cal[0] = ISP_RD32(ISP_REG_ADDR_CAMSV_TG_VF_CON); + camsv_reg_cal[1] = ISP_RD32(ISP_REG_ADDR_CAMSV_TG2_VF_CON); + /* VF start already */ + /* MBOOL CurVF_En = MFALSE; */ + if ((_imgo_ == rt_dma) || (_rrzo_ == rt_dma)) { + if (reg_val & 0x1) + CurVF_En = MTRUE; + else + CurVF_En = MFALSE; + } else if ((_imgo_d_ == rt_dma) || (_rrzo_d_ == rt_dma)) { + if (reg_val2 & 0x1) + CurVF_En = MTRUE; + else + CurVF_En = MFALSE; + } else if (_camsv_imgo_ == rt_dma) { + if (camsv_reg_cal[0] & 0x1) + CurVF_En = MTRUE; + else + CurVF_En = MFALSE; + } else if (_camsv2_imgo_ == rt_dma) { + if (camsv_reg_cal[1] & 0x1) + CurVF_En = MTRUE; + else + CurVF_En = MFALSE; + } + + if (CurVF_En) { + if (_bFlag == MTRUE) { + MUINT32 ch_imgo = 0, ch_rrzo = 0; + /* */ + /**/ switch (rt_dma) { + /**/ case _imgo_: + /**/ case _rrzo_: + irqT = _IRQ; + ch_imgo = _imgo_; + ch_rrzo = _rrzo_; + irqT_Lock = _IRQ; + break; + /**/ case _imgo_d_: + /**/ case _rrzo_d_: + irqT = _IRQ_D; + ch_imgo = _imgo_d_; + ch_rrzo = _rrzo_d_; + irqT_Lock = _IRQ; + break; + /**/ case _camsv_imgo_: + irqT_Lock = _CAMSV_IRQ; + irqT = _CAMSV_IRQ; + break; + /**/ case _camsv2_imgo_: + irqT_Lock = _CAMSV_D_IRQ; + irqT = _CAMSV_D_IRQ; + break; + /**/ default: + irqT_Lock = _IRQ; + irqT = _IRQ; + LOG_ERR("[rtbc]N.S.(%d)\n", rt_dma); + break; + } +#if 0 + static MUINT32 RTBC_DBG_test; + + /**/ if (RTBC_DBG_test++ > 3) { + RTBC_DBG_test -= 3; + ISP_FBC_DUMP(rt_dma, 1, 0, 0, 0); + } +#endif + /* copy_from_user()/copy_to_user() might sleep when page fault, + it can't use in atomic context, e.g. spin_lock_irqsave() */ + /* spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); */ + if (0 != rt_buf_ctrl.ex_data_ptr) { + /* borrow deque_buf->data memory, + in order to shirnk memory required,avoid compile err */ + /**/ if (copy_from_user(&deque_buf->data[0], (void __user *)rt_buf_ctrl.ex_data_ptr, + sizeof(ISP_RT_BUF_INFO_STRUCT)) == 0) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); + /* */ + i = 0; + /**/ if (deque_buf->data[0].bufIdx != 0xFFFF) { + /* replace the specific buffer with the same bufIdx */ + /* LOG_ERR("[rtbc][replace2]Search By Idx");*/ + /**/ for (i = 0; i < ISP_RT_BUF_SIZE; i++) { + /**/ if (pstRTBuf->ring_buf[rt_dma].data[i].bufIdx == + /**/ deque_buf->data[0].bufIdx) + break; + } + } else { + /* */ + /* LOG_ERR("[rtbc][replace2]Search By Addr+");*/ + /**/ for (i = 0; i < ISP_RT_BUF_SIZE; i++) { + /**/ if (pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr == + /**/ rt_buf_info->base_pAddr) { + /* LOG_ERR("[rtbc][replace2]Search By Addr i[%d]", i);*/ + break; + } + } + } + + if (i == ISP_RT_BUF_SIZE) { + /* error: can't search the buffer... */ + /**/ LOG_ERR( + "[rtbc][replace2]error Can't get the idx-(0x%x)/Addr(0x%x) buf\n", + deque_buf->data[0].bufIdx, + rt_buf_info->base_pAddr); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); + IRQ_LOG_PRINTER(irqT, 0, _LOG_DBG); + + for (i = 0; i < ISP_RT_BUF_SIZE; i += 4) { + LOG_ERR("[rtbc][replace2]error idx-(0x%x/0x%x/0x%x/0x%x)\n", + pstRTBuf->ring_buf[rt_dma].data[i+0].bufIdx, + pstRTBuf->ring_buf[rt_dma].data[i+1].bufIdx, + pstRTBuf->ring_buf[rt_dma].data[i+2].bufIdx, + pstRTBuf->ring_buf[rt_dma].data[i+3].bufIdx); + } + + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EFAULT; + } + LOG_DBG("[rtbc][replace2]dma(%d),idx(%d) PA(0x%x_0x%x)", + rt_dma, i, pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr, pstRTBuf->ring_buf[rt_dma].data[i].base_vAddr); + /* IRQ_LOG_KEEPER(irqT, 0, _LOG_DBG, "[rtbc][replace2]dma(%d),idx(%d) PA(0x%x_0x%x)\n", + rt_dma, i, + pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr, + deque_buf->data[0].base_pAddr);*/ + /* spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT]), flags);*/ + pstRTBuf->ring_buf[rt_dma].data[i].memID = + deque_buf->data[0].memID; + pstRTBuf->ring_buf[rt_dma].data[i].size = + deque_buf->data[0].size; + pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr = + deque_buf->data[0].base_pAddr; + pstRTBuf->ring_buf[rt_dma].data[i].base_vAddr = + deque_buf->data[0].base_vAddr; + pstRTBuf->ring_buf[rt_dma].data[i].bFilled = ISP_RTBC_BUF_EMPTY; + pstRTBuf->ring_buf[rt_dma].data[i].image.frm_cnt = _INVALID_FRM_CNT_; + +#ifdef _rtbc_buf_que_2_0_ + /**/ /**/ if (pstRTBuf->ring_buf[rt_dma]. + empty_count < + pstRTBuf->ring_buf[rt_dma]. + total_count) + pstRTBuf->ring_buf[rt_dma]. + empty_count++; + /**/ /**/ else { + spin_unlock_irqrestore(& + (IspInfo. + SpinLockIrq + [irqT_Lock]), + flags); + IRQ_LOG_PRINTER(irqT, 0, + _LOG_DBG); + LOG_ERR + ("[rtbc]dma(%d),PA(0x%x),over enque_1", + rt_dma, + pstRTBuf-> + ring_buf[rt_dma]. + data[i].base_pAddr); + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EFAULT; + } + /* LOG_INF("RTBC_DBG7 e_dma_%d:%d %d %d\n", + rt_dma,pstRTBuf->ring_buf[rt_dma].data[0].bFilled, + pstRTBuf->ring_buf[rt_dma].data[1].bFilled, + pstRTBuf->ring_buf[rt_dma].data[2].bFilled); */ +#else + pstRTBuf->ring_buf[rt_dma]. + empty_count++; +#endif + /* spin_unlock_irqrestore( + &(IspInfo.SpinLockIrq[irqT]), flags); */ + /**/ /**/ } else { + /* spin_unlock_irqrestore( + &(IspInfo.SpinLockIrq[irqT_Lock]), flags); */ + LOG_ERR + ("[rtbc][ENQUE_ext]:copy_from_user fail"); + /* LOG_ERR("[rtbc][ENQUE_ext]:copy_from_user fail, + dst_buf(0x%lx), user_buf(0x%lx)", + &deque_buf.data[0], rt_buf_ctrl.ex_data_ptr); */ + + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EAGAIN; + } + /**/ /**/ } else { /* this case for camsv & pass1 fw rtbc */ + spin_lock_irqsave(& + (IspInfo. + SpinLockIrq[irqT_Lock]), + flags); + /**/ /**/ for (i = 0; i < ISP_RT_BUF_SIZE; i++) { + /* */ + /**/ /**/ if (pstRTBuf->ring_buf[rt_dma]. + data[i].base_pAddr == + rt_buf_info->base_pAddr) { + /* LOG_DBG("[rtbc]dma(%d),old(%d) PA(0x%x) + VA(0x%x)", + rt_dma,i,pstRTBuf->ring_buf[rt_dma]. + data[i].base_pAddr, + pstRTBuf->ring_buf[rt_dma].data[i]. + base_vAddr); */ + /* spin_lock_irqsave( + &(IspInfo.SpinLockIrq[irqT]), flags); */ + pstRTBuf->ring_buf[rt_dma]. + data[i].bFilled = + ISP_RTBC_BUF_EMPTY; + pstRTBuf->ring_buf[rt_dma]. + data[i].image.frm_cnt = + _INVALID_FRM_CNT_; +#ifdef _rtbc_buf_que_2_0_ + /**/ /**/ if (pstRTBuf-> + ring_buf[rt_dma]. + empty_count < + pstRTBuf-> + ring_buf[rt_dma]. + total_count) + pstRTBuf-> + ring_buf + [rt_dma]. + empty_count++; + /**/ /**/ else { + spin_unlock_irqrestore + (& + (IspInfo. + SpinLockIrq + [irqT_Lock]), + flags); + IRQ_LOG_PRINTER + (irqT, 0, + _LOG_DBG); + LOG_ERR + ("[rtbc]error:dma(%d),PA(0x%x),over enque_2", + rt_dma, + pstRTBuf-> + ring_buf + [rt_dma]. + data[i]. + base_pAddr); + + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EFAULT; + } + + /* double check */ + /**/ /**/ if (1) { + /**/ /**/ if (rt_buf_info-> + bufIdx != + pstRTBuf-> + ring_buf + [rt_dma]. + data[i].bufIdx) + LOG_ERR + ("[rtbc][replace2]error: BufIdx MisMatch. 0x%x/0x%x", + rt_buf_info-> + bufIdx, + pstRTBuf-> + ring_buf + [rt_dma]. + data + [i]. + bufIdx); + + } +#else + pstRTBuf->ring_buf[rt_dma]. + empty_count++; +#endif + /* spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[irqT]), flags); */ + /* LOG_DBG("[rtbc]dma(%d),new(%d) PA(0x%x) VA(0x%x)", + rt_dma,i,pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr,pstRTBuf->ring_buf[rt_dma].data[i].base_vAddr); */ + break; + } + } + /**/ /**/ if (i == ISP_RT_BUF_SIZE) { + + /**/ /**/ for (x = 0; x < ISP_RT_BUF_SIZE; + x++) + LOG_DBG + ("[rtbc]dma(%d),idx(%d) PA(0x%x) VA(0x%llx)", + rt_dma, x, + pstRTBuf-> + ring_buf[rt_dma]. + data[x].base_pAddr, + pstRTBuf-> + ring_buf[rt_dma]. + data[x].base_vAddr); + + LOG_ERR + ("[rtbc][replace3]can't find thespecified Addr(0x%x)\n", + rt_buf_info->base_pAddr); + } + } + /* set RCN_INC = 1; */ + /* RCNT++ */ + /* FBC_CNT-- */ + + + /* RCNT_INC++ */ +#ifdef _rtbc_buf_que_2_0_ + + /**/ if (rt_buf_ctrl.ctrl == ISP_RT_BUF_CTRL_ENQUE) { + /* make sure rct_inc will be pulled at the same vd. */ + /**/ /**/ if ((_IRQ == irqT) || (_IRQ_D == irqT)) { + /**/ /**/ if ((MTRUE == + pstRTBuf->ring_buf[ch_imgo]. + active) + && (MTRUE == + pstRTBuf->ring_buf[ch_rrzo]. + active)) { + /**/ /**/ /**/ if (0 != + rt_buf_ctrl. + ex_data_ptr) { + /**/ /**/ /**/ if ((p1_fbc[rt_dma]. + Bits.FB_NUM == + p1_fbc[rt_dma]. + Bits.FBC_CNT) + || + ((p1_fbc + [rt_dma].Bits. + FB_NUM - 1) == + p1_fbc[rt_dma]. + Bits. + FBC_CNT)) { + mFwRcnt. + bLoadBaseAddr + [irqT] = + MTRUE; + } + } + dma_en_recorder[rt_dma] + [mFwRcnt. + DMA_IDX[rt_dma]] = + MTRUE; + mFwRcnt.DMA_IDX[rt_dma] = + (++mFwRcnt. + DMA_IDX[rt_dma] >= + ISP_RT_BUF_SIZE) + ? (mFwRcnt. + DMA_IDX[rt_dma] - + ISP_RT_BUF_SIZE) + : (mFwRcnt. + DMA_IDX[rt_dma]); + /* LOG_INF("RTBC_DBG1:%d %d %d\n", + rt_dma,dma_en_recorder[rt_dma][mFwRcnt.DMA_IDX[rt_dma]],mFwRcnt.DMA_IDX[rt_dma]); */ + /**/ /**/ for (z = 0; + z < ISP_RT_BUF_SIZE; + z++) { + /**/ /**/ if (dma_en_recorder + [ch_imgo] + [mFwRcnt. + rdIdx[irqT]] + && + dma_en_recorder + [ch_rrzo] + [mFwRcnt. + rdIdx[irqT]]) { + mFwRcnt. + INC + [irqT] + [mFwRcnt. + curIdx + [irqT]++] + = 1; + dma_en_recorder + [ch_imgo] + [mFwRcnt. + rdIdx + [irqT]] + = + dma_en_recorder + [ch_rrzo] + [mFwRcnt. + rdIdx + [irqT]] + = + MFALSE; + mFwRcnt. + rdIdx + [irqT] = + (++mFwRcnt. + rdIdx + [irqT] + >= + ISP_RT_BUF_SIZE) + ? + (mFwRcnt. + rdIdx + [irqT] + - + ISP_RT_BUF_SIZE) + : + (mFwRcnt. + rdIdx + [irqT]); + /* LOG_INF("RTBC_DBG2:%d %d\n",mFwRcnt.rdIdx[irqT],mFwRcnt.curIdx[irqT]); */ + /**/ /**/ } else { + break; + } + } + /**/ /**/ } else { + /* rcnt_sync only work when multi-dma ch enabled. but in order to support multi-enque, these mech. also to be */ + /* worked under 1 dma ch enabled */ + /**/ /**/ if (MTRUE == + pstRTBuf-> + ring_buf[rt_dma]. + active) { + /**/ /**/ /**/ if (0 != + rt_buf_ctrl. + ex_data_ptr) { + /**/ /**/ /**/ if ((p1_fbc + [rt_dma]. + Bits. + FB_NUM + == + p1_fbc + [rt_dma]. + Bits. + FBC_CNT) + || + ((p1_fbc + [rt_dma]. + Bits. + FB_NUM + - + 1) == + p1_fbc + [rt_dma]. + Bits. + FBC_CNT)) { + mFwRcnt. + bLoadBaseAddr + [irqT] + = + MTRUE; + } + } + dma_en_recorder + [rt_dma] + [mFwRcnt. + DMA_IDX + [rt_dma]] = + MTRUE; + mFwRcnt. + DMA_IDX[rt_dma] + = + (++mFwRcnt. + DMA_IDX[rt_dma] + >= + ISP_RT_BUF_SIZE) + ? (mFwRcnt. + DMA_IDX + [rt_dma] - + ISP_RT_BUF_SIZE) + : (mFwRcnt. + DMA_IDX + [rt_dma]); + + /**/ /**/ for (z = 0; + z < + ISP_RT_BUF_SIZE; + z++) { + /**/ /**/ /**/ if (dma_en_recorder[rt_dma][mFwRcnt.rdIdx[irqT]]) { + mFwRcnt. + INC + [irqT] + [mFwRcnt. + curIdx + [irqT]++] + = + 1; + dma_en_recorder + [rt_dma] + [mFwRcnt. + rdIdx + [irqT]] + = + MFALSE; + mFwRcnt. + rdIdx + [irqT] + = + (++mFwRcnt. + rdIdx + [irqT] + >= + ISP_RT_BUF_SIZE) + ? + (mFwRcnt. + rdIdx + [irqT] + - + ISP_RT_BUF_SIZE) + : + (mFwRcnt. + rdIdx + [irqT]); + /**/ } else { + break; + } + } + /**/ } else { + spin_unlock_irqrestore + (& + (IspInfo. + SpinLockIrq + [irqT_Lock]), + flags); + LOG_ERR + ("[rtbc]error:dma(%d) r not being activated(%d)", + rt_dma, + pstRTBuf-> + ring_buf + [rt_dma]. + active); + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EFAULT; + } + } + + /**/ } else { /* camsv case */ + /**/ if (MTRUE == + pstRTBuf->ring_buf[rt_dma]. + active) { + /**/ if (0 != + rt_buf_ctrl. + ex_data_ptr) { + /**/ if ((p1_fbc[rt_dma]. + Bits.FB_NUM == + p1_fbc[rt_dma]. + Bits.FBC_CNT) + || + ((p1_fbc + [rt_dma].Bits. + FB_NUM - 1) == + p1_fbc[rt_dma]. + Bits. + FBC_CNT)) { + mFwRcnt. + bLoadBaseAddr + [irqT] = + MTRUE; + } + } + dma_en_recorder[rt_dma] + [mFwRcnt. + DMA_IDX[rt_dma]] = + MTRUE; + mFwRcnt.DMA_IDX[rt_dma] = + (++mFwRcnt. + DMA_IDX[rt_dma] >= + ISP_RT_BUF_SIZE) + ? (mFwRcnt. + DMA_IDX[rt_dma] - + ISP_RT_BUF_SIZE) + : (mFwRcnt. + DMA_IDX[rt_dma]); + + /**/ for (z = 0; + z < ISP_RT_BUF_SIZE; + z++) { + /**/ if (dma_en_recorder + [rt_dma] + [mFwRcnt. + rdIdx[irqT]]) { + mFwRcnt. + INC + [irqT] + [mFwRcnt. + curIdx + [irqT]++] + = 1; + dma_en_recorder + [rt_dma] + [mFwRcnt. + rdIdx + [irqT]] + = + MFALSE; + mFwRcnt. + rdIdx + [irqT] = + (++mFwRcnt. + rdIdx + [irqT] + >= + ISP_RT_BUF_SIZE) + ? + (mFwRcnt. + rdIdx + [irqT] + - + ISP_RT_BUF_SIZE) + : + (mFwRcnt. + rdIdx + [irqT]); + /**/ } else { + break; + } + } + /**/ } else { + spin_unlock_irqrestore(& + (IspInfo. + SpinLockIrq + [irqT_Lock]), + flags); + LOG_ERR + ("[rtbc]error:dma(%d) r not being activated(%d)", + rt_dma, + pstRTBuf-> + ring_buf[rt_dma]. + active); + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EFAULT; + } + } + /**/ } else { /* immediate enque mode */ + MUINT32 _openedDma = 1; + MBOOL _bypass = MFALSE; + + /**/ if ((MTRUE == + pstRTBuf->ring_buf[ch_imgo].active) + && (MTRUE == + pstRTBuf->ring_buf[ch_rrzo]. + active)) { + /* record wheather all enabled dma r alredy enqued, */ + /* rcnt_inc will only be pulled + to high once all enabled dma r enqued. */ + /* inorder to reduce the probability of + crossing vsync.*/ + /* this global par. r no use under immediate mode, */ + /* borrow this to shirk memory */ + dma_en_recorder[rt_dma][0] = MTRUE; + _openedDma = 2; + /**/ if ((dma_en_recorder[ch_imgo][0] == + MTRUE) + && (dma_en_recorder[ch_rrzo][0] + == MTRUE)) + dma_en_recorder[ch_imgo][0] + = + dma_en_recorder[ch_rrzo] + [0] = MFALSE; + /**/ else + _bypass = MTRUE; + + } + /**/ if (_bypass == MFALSE) { + /**/ if ((p1_fbc[rt_dma].Bits.FB_NUM == + p1_fbc[rt_dma].Bits.FBC_CNT) + || + ((p1_fbc[rt_dma].Bits.FB_NUM - + 1) == + p1_fbc[rt_dma].Bits.FBC_CNT)) { + /* write to phy register */ + /**/ LOG_DBG( + /**/ "[rtbc_%d][ENQUE] write2Phy directly(%d,%d)", + /**/ rt_dma, + /**/ p1_fbc[rt_dma].Bits.FB_NUM, + /**/ p1_fbc[rt_dma].Bits.FBC_CNT); + /*IRQ_LOG_KEEPER(irqT, 0, + _LOG_DBG, + "[rtbc_%d][ENQUE] write2Phy directly(%d,%d) ", + rt_dma, + p1_fbc + [rt_dma]. + Bits.FB_NUM, + p1_fbc + [rt_dma]. + Bits. + FBC_CNT);*/ + ISP_WR32(p1_dma_addr_reg + [rt_dma], + pstRTBuf-> + ring_buf[rt_dma]. + data[i]. + base_pAddr); + /* for openedDma=2, + it must update 2 dma's based address, + or it will occur tearing */ + /**/ if (pstRTBuf->ring_buf[ch_imgo].active == MTRUE) + ISP_WR32( + /**/ p1_dma_addr_reg[ch_imgo], + /**/ pstRTBuf->ring_buf[ch_imgo].data[i].base_pAddr); + /**/ if (pstRTBuf->ring_buf[ch_rrzo].active == MTRUE) + ISP_WR32( + /**/ p1_dma_addr_reg[ch_rrzo], + /**/ pstRTBuf->ring_buf[ch_rrzo].data[i].base_pAddr); + } + /**/ if ((_camsv_imgo_ == rt_dma) + /**/ || (_camsv2_imgo_ == rt_dma)) { + p1_fbc[rt_dma].Bits. + RCNT_INC = 1; + ISP_WR32(p1_fbc_reg[rt_dma], + p1_fbc[rt_dma]. + Reg_val); + p1_fbc[rt_dma].Bits. + RCNT_INC = 0; + ISP_WR32(p1_fbc_reg[rt_dma], + p1_fbc[rt_dma]. + Reg_val); + /**/ } else { + /**/ if (_openedDma == 1) { + p1_fbc[rt_dma].Bits. + RCNT_INC = 1; + ISP_WR32(p1_fbc_reg + [rt_dma], + p1_fbc + [rt_dma]. + Reg_val); + IRQ_LOG_KEEPER(irqT, + 0, + _LOG_DBG, + " RCNT_INC(dma:0x%x)\n", + rt_dma); + /**/ } else { + p1_fbc[ch_imgo]. + Bits.RCNT_INC = + 1; + ISP_WR32(p1_fbc_reg + [ch_imgo], + p1_fbc + [ch_imgo]. + Reg_val); + p1_fbc[ch_rrzo]. + Bits.RCNT_INC = + 1; + ISP_WR32(p1_fbc_reg + [ch_rrzo], + p1_fbc + [ch_rrzo]. + Reg_val); + IRQ_LOG_KEEPER(irqT, + 0, + _LOG_DBG, + " RCNT_INC(dma:0x%x)", + ch_imgo); + IRQ_LOG_KEEPER(irqT, + 0, + _LOG_DBG, + " RCNT_INC(dma:0x%x)\n", + ch_rrzo); + } + } + } + } + +#else /* for rtbc 1.0 case */ + /* if ( FB_NUM==FBC_CNT || (FB_NUM-1)==FBC_CNT ) */ + /**/ if ((p1_fbc[rt_dma].Bits.FB_NUM == + p1_fbc[rt_dma].Bits.FBC_CNT) + || ((p1_fbc[rt_dma].Bits.FB_NUM - 1) == + p1_fbc[rt_dma].Bits.FBC_CNT)) { + /* write to phy register */ + /* LOG_INF("[rtbc_%d][ENQUE] write2Phy directly(%d,%d)", + rt_dma,p1_fbc[rt_dma].Bits.FB_NUM, + p1_fbc[rt_dma].Bits.FBC_CNT); */ + IRQ_LOG_KEEPER(irqT, 0, _LOG_DBG, + "[rtbc_%d][ENQUE] write2Phy directly(%d,%d)\n", + rt_dma, + p1_fbc[rt_dma].Bits. + FB_NUM, + p1_fbc[rt_dma].Bits.FBC_CNT); + ISP_WR32(p1_dma_addr_reg[rt_dma], + pstRTBuf->ring_buf[rt_dma].data[i]. + base_pAddr); + } + + /* patch camsv hw bug */ + /**/ if ((_camsv_imgo_ == rt_dma) + || (_camsv2_imgo_ == rt_dma)) { + p1_fbc[rt_dma].Bits.RCNT_INC = 1; + ISP_WR32(p1_fbc_reg[rt_dma], + p1_fbc[rt_dma].Reg_val); + p1_fbc[rt_dma].Bits.RCNT_INC = 0; + ISP_WR32(p1_fbc_reg[rt_dma], + p1_fbc[rt_dma].Reg_val); + /**/ } else { + p1_fbc[rt_dma].Bits.RCNT_INC = 1; + ISP_WR32(p1_fbc_reg[rt_dma], + p1_fbc[rt_dma].Reg_val); + } +#endif + spin_unlock_irqrestore(& + (IspInfo. + SpinLockIrq[irqT_Lock]), + flags); + IRQ_LOG_PRINTER(irqT, 0, _LOG_DBG); + /* */ + /**/ if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { + /* LOG_DBG("[rtbc][ENQUE]:dma(%d),PA(0x%x),O(0x%x), + ZO(0x%x),O_D(0x%x),ZO_D(0x%x),camsv(0x%x/0x%x) + fps(%d/%d/%d/%d)us", */ + LOG_DBG + ("[rtbc][ENQUE]:dma(%d),PA(0x%x),O(0x%x),ZO(0x%x),O_D(0x%x),ZO_D(0x%x),camsv(0x%x/0x%x)fps(%d/%d/%d/%d)us,rtctrl_%d\n", + rt_dma, rt_buf_info->base_pAddr, + ISP_RD32(ISP_REG_ADDR_IMGO_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_RRZO_BASE_ADDR), + ISP_RD32 + (ISP_REG_ADDR_IMGO_D_BASE_ADDR), + ISP_RD32 + (ISP_REG_ADDR_RRZO_D_BASE_ADDR), + ISP_RD32 + (ISP_REG_ADDR_IMGO_SV_BASE_ADDR), + ISP_RD32 + (ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR), + avg_frame_time[_PASS1], + avg_frame_time[_PASS1_D], + avg_frame_time[_CAMSV], + avg_frame_time[_CAMSV_D], + rt_buf_ctrl.ctrl); + } + } + } else { + ISP_RTBC_ENQUE(rt_dma, rt_buf_info); + } + + } else { + LOG_ERR("[rtbc][ENQUE]:copy_from_user fail"); + + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EFAULT; + } + break; + + case ISP_RT_BUF_CTRL_DEQUE: + switch (rt_dma) { + case _camsv_imgo_: + irqT_Lock = _CAMSV_IRQ; + irqT = _CAMSV_IRQ; + break; + case _camsv2_imgo_: + irqT_Lock = _CAMSV_D_IRQ; + irqT = _CAMSV_D_IRQ; + break; + default: + irqT_Lock = _IRQ; + irqT = _IRQ; + break; + } + /* */ + reg_val = ISP_RD32(ISP_REG_ADDR_TG_VF_CON); + reg_val2 = ISP_RD32(ISP_REG_ADDR_TG2_VF_CON); + camsv_reg_cal[0] = ISP_RD32(ISP_REG_ADDR_CAMSV_TG_VF_CON); + camsv_reg_cal[1] = ISP_RD32(ISP_REG_ADDR_CAMSV_TG2_VF_CON); + /* VF start already */ + /* spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); */ + if ((reg_val & 0x01) || (reg_val2 & 0x01) || (camsv_reg_cal[0] & 0x01) + || (camsv_reg_cal[1] & 0x01)) { + if (MTRUE == _bFlag) { + MUINT32 out = 0; + MUINT32 _magic; + + deque_buf->count = P1_DEQUE_CNT; + spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); +#ifdef _rtbc_buf_que_2_0_ + /* p1_fbc[rt_dma].Bits.WCNT - 1; //WCNT = [1,2,..] */ + iBuf = pstRTBuf->ring_buf[rt_dma].read_idx; + pstRTBuf->ring_buf[rt_dma].read_idx = + (pstRTBuf->ring_buf[rt_dma].read_idx + + 1) % pstRTBuf->ring_buf[rt_dma].total_count; + if (deque_buf->count != P1_DEQUE_CNT) { + LOG_ERR("support only deque 1 buf at 1 time\n"); + deque_buf->count = P1_DEQUE_CNT; + } +#else + iBuf = p1_fbc[rt_dma].Bits.RCNT - 1; /* RCNT = [1,2,3,...] */ +#endif + i = 0; + + if (ISP_RTBC_BUF_LOCKED == + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].bFilled) + LOG_ERR("the same buffer deque twice\n"); + + /* for (i=0; icount; i++) { */ + /* MUINT32 out; */ + + deque_buf->data[i].memID = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].memID; + deque_buf->data[i].size = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].size; + deque_buf->data[i].base_vAddr = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].base_vAddr; + deque_buf->data[i].base_pAddr = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].base_pAddr; + deque_buf->data[i].timeStampS = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].timeStampS; + deque_buf->data[i].timeStampUs = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].timeStampUs; + deque_buf->data[i].image.w = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.w; + deque_buf->data[i].image.h = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.h; + deque_buf->data[i].image.xsize = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.xsize; + deque_buf->data[i].image.stride = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.stride; + deque_buf->data[i].image.bus_size = + pstRTBuf->ring_buf[rt_dma].data[iBuf + + i].image.bus_size; + deque_buf->data[i].image.fmt = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.fmt; + deque_buf->data[i].image.pxl_id = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.pxl_id; + deque_buf->data[i].image.wbn = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.wbn; + deque_buf->data[i].image.ob = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.ob; + deque_buf->data[i].image.lsc = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.lsc; + deque_buf->data[i].image.rpg = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.rpg; + deque_buf->data[i].image.m_num_0 = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.m_num_0; + deque_buf->data[i].image.frm_cnt = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].image.frm_cnt; + deque_buf->data[i].bProcessRaw = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].bProcessRaw; + deque_buf->data[i].rrzInfo.srcX = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].rrzInfo.srcX; + deque_buf->data[i].rrzInfo.srcY = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].rrzInfo.srcY; + deque_buf->data[i].rrzInfo.srcW = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].rrzInfo.srcW; + deque_buf->data[i].rrzInfo.srcH = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].rrzInfo.srcH; + deque_buf->data[i].rrzInfo.dstW = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].rrzInfo.dstW; + deque_buf->data[i].rrzInfo.dstH = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].rrzInfo.dstH; + deque_buf->data[i].dmaoCrop.x = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].dmaoCrop.x; + deque_buf->data[i].dmaoCrop.y = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].dmaoCrop.y; + deque_buf->data[i].dmaoCrop.w = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].dmaoCrop.w; + deque_buf->data[i].dmaoCrop.h = + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].dmaoCrop.h; + +#ifdef _MAGIC_NUM_ERR_HANDLING_ + + /*LOG_ERR("[rtbc][deque][m_num]:d(%d),fc(0x%x),lfc0x%x,m0(0x%x),lm#(0x%x)\n", + rt_dma, \ + deque_buf->data[i].image.frm_cnt, \ + m_LastFrmCnt[rt_dma] \ + ,deque_buf->data[i].image.m_num_0, \ + m_LastMNum[rt_dma]); + */ + + _magic = deque_buf->data[i].image.m_num_0; + + if (_DUMMY_MAGIC_ & deque_buf->data[i].image.m_num_0) + _magic = + (deque_buf->data[i].image. + m_num_0 & (~_DUMMY_MAGIC_)); + + + if ((_INVALID_FRM_CNT_ == deque_buf->data[i].image.frm_cnt) + || (m_LastMNum[rt_dma] > _magic)) { + /**/ if ((_DUMMY_MAGIC_ & deque_buf->data[i].image. + m_num_0) == 0) + deque_buf->data[i].image.m_num_0 |= + _UNCERTAIN_MAGIC_NUM_FLAG_; + /* */ + IRQ_LOG_KEEPER(irqT, 0, _LOG_DBG, + "m# uncertain:dma(%d),m0(0x%x),fcnt(0x%x),Lm#(0x%x)", + rt_dma, + deque_buf->data[i].image.m_num_0, + deque_buf->data[i].image.frm_cnt, + m_LastMNum[rt_dma]); +#ifdef T_STAMP_2_0 + /**/ if (m_T_STAMP.fps > SlowMotion) { + /* patch here is because of that uncertain should happen only in missing SOF. And because of FBC, image still can be deque. + That's why timestamp still need to be increased here. */ + m_T_STAMP.T_ns += + ((unsigned long long)m_T_STAMP. + interval_us * 1000); + /**/ if (++m_T_STAMP.fcnt == m_T_STAMP.fps) { + m_T_STAMP.fcnt = 0; + m_T_STAMP.T_ns += + ((unsigned long long)m_T_STAMP. + compensation_us * 1000); + } + } +#endif + } else { + m_LastMNum[rt_dma] = _magic; + } + +#endif + + DMA_TRANS(rt_dma, out); + pstRTBuf->ring_buf[rt_dma].data[iBuf + i].bFilled = + ISP_RTBC_BUF_LOCKED; + deque_buf->sof_cnt = sof_count[out]; + deque_buf->img_cnt = pstRTBuf->ring_buf[rt_dma].img_cnt; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[irqT_Lock]), + flags); + /* LOG_INF("RTBC_DBG7 d_dma_%d:%d %d %d\n", + rt_dma,pstRTBuf->ring_buf[rt_dma].data[0].bFilled,pstRTBuf->ring_buf[rt_dma].data[1].bFilled,pstRTBuf->ring_buf[rt_dma].data[2].bFilled); */ + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { + /*LOG_DBG("[rtbc][DEQUE](%d):d(%d)/id(0x%x)/bs(0x%x)/va(0x%llx)/pa(0x%x)/t(%d.%d)/img(%d,%d,%d,%d,%d,%d,%d,%d,%d)/m(0x%x)/fc(%d)/rrz(%d,%d,%d,%d,%d,%d),dmao(%d,%d,%d,%d),lm#(0x%x)",*/ + IRQ_LOG_KEEPER(irqT, 0, _LOG_DBG, "[rtbc][DEQUE](%d):d(%d)/id(0x%x)/bs(0x%x)/va(0x%llx)/pa(0x%x)/t(%d.%d)/img(%d,%d,%d,%d,%d,%d,%d,%d,%d)/m(0x%x)/fc(%d)/rrz(%d,%d,%d,%d,%d,%d),dmao(%d,%d,%d,%d),lm#(0x%x)", + iBuf+i, + rt_dma, + deque_buf->data[i].memID, + deque_buf->data[i].size, + deque_buf->data[i].base_vAddr, + deque_buf->data[i].base_pAddr, + deque_buf->data[i].timeStampS, + deque_buf->data[i].timeStampUs, + deque_buf->data[i].image.w, + deque_buf->data[i].image.h, + deque_buf->data[i].image.stride, + deque_buf->data[i].image.bus_size, + deque_buf->data[i].image.fmt, + deque_buf->data[i].image.wbn, + deque_buf->data[i].image.ob, + deque_buf->data[i].image.lsc, + deque_buf->data[i].image.rpg, + deque_buf->data[i].image.m_num_0, + deque_buf->data[i].image.frm_cnt, + deque_buf->data[i].rrzInfo.srcX, + deque_buf->data[i].rrzInfo.srcY, + deque_buf->data[i].rrzInfo.srcW, + deque_buf->data[i].rrzInfo.srcH, + deque_buf->data[i].rrzInfo.dstW, + deque_buf->data[i].rrzInfo.dstH, + deque_buf->data[i].dmaoCrop.x, + deque_buf->data[i].dmaoCrop.y, + deque_buf->data[i].dmaoCrop.w, + deque_buf->data[i].dmaoCrop.h, + m_LastMNum[rt_dma]); + } + IRQ_LOG_PRINTER(irqT, 0, _LOG_DBG); + /* */ + /* tstamp = deque_buf->data[i].timeStampS*1000000+deque_buf->data[i].timeStampUs;*/ + /* if ( (0 != prv_tstamp) && (prv_tstamp >= tstamp) ) { */ + if (0 != prv_tstamp_s[rt_dma]) { + if ((prv_tstamp_s[rt_dma] > deque_buf->data[i].timeStampS) || + ((prv_tstamp_s[rt_dma] == deque_buf->data[i].timeStampS) && + (prv_tstamp_us[rt_dma] >= deque_buf->data[i].timeStampUs))) { + LOG_ERR("[rtbc]TS rollback,D(%d),prv\"%d.%06d\",cur\"%d.%06d\"", + rt_dma, + prv_tstamp_s[rt_dma], + prv_tstamp_us[rt_dma], + deque_buf->data[i].timeStampS, + deque_buf->data[i].timeStampUs); + } + } + prv_tstamp_s[rt_dma] = deque_buf->data[i].timeStampS; + prv_tstamp_us[rt_dma] = deque_buf->data[i].timeStampUs; + /* } , mark for for (i=0; icount; i++) { */ + } + } else { + ISP_RTBC_DEQUE(rt_dma, deque_buf); + } + + if (deque_buf->count) { + /* */ + /* if(copy_to_user((void __user*)rt_buf_ctrl.data_ptr, + &deque_buf, sizeof(ISP_DEQUE_BUF_INFO_STRUCT)) != 0) */ + if (copy_to_user + ((void __user *)rt_buf_ctrl.pExtend, deque_buf, + sizeof(ISP_DEQUE_BUF_INFO_STRUCT)) != 0) { + LOG_ERR("[rtbc][DEQUE]:copy_to_user failed"); + Ret = -EFAULT; + } + + } else { + /* */ + /* spin_unlock_irqrestore(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + LOG_ERR("[rtbc][DEQUE]:no filled buffer"); + Ret = -EFAULT; + } + + break; + case ISP_RT_BUF_CTRL_CUR_STATUS: + reg_val = ISP_RD32(ISP_REG_ADDR_TG_VF_CON) & 0x1; + reg_val2 = ISP_RD32(ISP_REG_ADDR_TG2_VF_CON) & 0x1; + camsv_reg_cal[0] = ISP_RD32(ISP_REG_ADDR_CAMSV_TG_VF_CON) & 0x1; + camsv_reg_cal[1] = ISP_RD32(ISP_REG_ADDR_CAMSV_TG2_VF_CON) & 0x1; + ISP_FBC_DUMP(rt_buf_ctrl.buf_id, reg_val, reg_val2, camsv_reg_cal[0], + camsv_reg_cal[1]); + break; + case ISP_RT_BUF_CTRL_IS_RDY: + /* */ + /* spin_lock_irqsave(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + /* */ + bWaitBufRdy = 1; +#ifdef _rtbc_buf_que_2_0_ + switch (rt_dma) { + case _imgo_: + case _rrzo_: + irqT_Lock = _IRQ; + irqT = _IRQ; + break; + case _imgo_d_: + case _rrzo_d_: + irqT = _IRQ_D; + irqT_Lock = _IRQ; + break; + case _camsv_imgo_: + irqT_Lock = _CAMSV_IRQ; + irqT = _CAMSV_IRQ; + break; + case _camsv2_imgo_: + irqT_Lock = _CAMSV_D_IRQ; + irqT = _CAMSV_D_IRQ; + break; + default: + LOG_ERR("[rtbc]N.S.(%d)\n", rt_dma); + irqT_Lock = _IRQ; + irqT = _IRQ; + break; + } + + spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); + + if (ISP_RTBC_BUF_FILLED == + pstRTBuf->ring_buf[rt_dma].data[pstRTBuf->ring_buf[rt_dma].read_idx]. + bFilled) + bWaitBufRdy = 0; + + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { + + IRQ_LOG_KEEPER(irqT, 0, _LOG_DBG, + "cur dma:%d,read idx = %d,total cnt = %d,bWaitBufRdy= %d ,", + rt_dma, pstRTBuf->ring_buf[rt_dma].read_idx, + pstRTBuf->ring_buf[rt_dma].total_count, bWaitBufRdy); + + for (z = 0; z < pstRTBuf->ring_buf[rt_dma].total_count; z++) + IRQ_LOG_KEEPER(irqT, 0, _LOG_DBG, "%d_", + pstRTBuf->ring_buf[rt_dma].data[z].bFilled); + + IRQ_LOG_KEEPER(irqT, 0, _LOG_DBG, "\n"); + } + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); + IRQ_LOG_PRINTER(irqT, 0, _LOG_DBG); +#else +#if defined(_rtbc_use_cq0c_) + bWaitBufRdy = p1_fbc[rt_dma].Bits.FBC_CNT ? 0 : 1; +#else + bWaitBufRdy = MTRUE; +#endif +#endif + + /* */ + /* spin_unlock_irqrestore(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + /* */ + /* if(copy_to_user((void __user*)rt_buf_ctrl.data_ptr, &bWaitBufRdy, sizeof(MUINT32)) != 0) */ + if (copy_to_user + ((void __user *)rt_buf_ctrl.pExtend, &bWaitBufRdy, + sizeof(MUINT32)) != 0) { + LOG_ERR("[rtbc][IS_RDY]:copy_to_user failed"); + Ret = -EFAULT; + } + /* */ + /* spin_unlock_irqrestore(&(IspInfo.SpinLockRTBC), flags); */ + /* */ + break; + case ISP_RT_BUF_CTRL_GET_SIZE: + /* */ + size = pstRTBuf->ring_buf[rt_dma].total_count; + /* */ + /* if(IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { */ + /* LOG_DBG("[rtbc][GET_SIZE]:rt_dma(%d)/size(%d)",rt_dma,size); */ + /* } */ + /* if(copy_to_user((void __user*)rt_buf_ctrl.data_ptr, &size, sizeof(MUINT32)) != 0) */ + if (copy_to_user((void __user *)rt_buf_ctrl.pExtend, &size, sizeof(MUINT32)) + != 0) { + LOG_ERR("[rtbc][GET_SIZE]:copy_to_user failed"); + Ret = -EFAULT; + } + break; + case ISP_RT_BUF_CTRL_CLEAR: + /* */ + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) + LOG_INF("[rtbc][CLEAR]:rt_dma(%d)", rt_dma); + + /* */ + switch (rt_dma) { + case _imgo_: + case _rrzo_: + memset((void *)IspInfo.IrqInfo.LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST], + 0, sizeof(MUINT32) * 32); + memset((void *)IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST], + 0, sizeof(MUINT32) * 32); + memset((void *)IspInfo.IrqInfo.Eismeta[ISP_IRQ_TYPE_INT_P1_ST], 0, + sizeof(MUINT32) * EISMETA_RINGSIZE); + gEismetaRIdx = 0; + gEismetaWIdx = 0; + gEismetaInSOF = 0; + memset(&g_DmaErr_p1[0], 0, sizeof(MUINT32) * nDMA_ERR_P1); + break; + case _imgo_d_: + case _rrzo_d_: + memset((void *)IspInfo.IrqInfo. + LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST_D], 0, + sizeof(MUINT32) * 32); + memset((void *)IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST_D], + 0, sizeof(MUINT32) * 32); + memset((void *)IspInfo.IrqInfo.Eismeta[ISP_IRQ_TYPE_INT_P1_ST_D], 0, + sizeof(MUINT32) * EISMETA_RINGSIZE); + gEismetaRIdx_D = 0; + gEismetaWIdx_D = 0; + gEismetaInSOF_D = 0; + memset(&g_DmaErr_p1[nDMA_ERR_P1], 0, + sizeof(MUINT32) * (nDMA_ERR - nDMA_ERR_P1)); + break; + case _camsv_imgo_: + break; + case _camsv2_imgo_: + break; + default: + LOG_ERR("[rtbc][CLEAR]N.S.(%d)\n", rt_dma); + + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -EFAULT; + } + /* remove, cause clear will be involked only when current module r totally stopped */ + /* spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); */ + +#if 0 + pstRTBuf->ring_buf[rt_dma].total_count = 0; + pstRTBuf->ring_buf[rt_dma].start = 0; + pstRTBuf->ring_buf[rt_dma].empty_count = 0; + pstRTBuf->ring_buf[rt_dma].active = 0; + + for (i = 0; i < ISP_RT_BUF_SIZE; i++) { + if (pstRTBuf->ring_buf[rt_dma].data[i]->base_pAddr == + rt_buf_info->base_pAddr) { + buffer_exist = 1; + break; + } + /* */ + if (pstRTBuf->ring_buf[rt_dma].data[i].base_pAddr == 0) + break; + + } +#else + /* if ((_imgo_ == rt_dma)||(_rrzo_ == rt_dma)||(_imgo_d_ == rt_dma)||(_rrzo_d_ == rt_dma)) */ + /* active */ + pstRTBuf->ring_buf[rt_dma].active = MFALSE; + memset((char *)&pstRTBuf->ring_buf[rt_dma], 0x00, + sizeof(ISP_RT_RING_BUF_INFO_STRUCT)); + + /* init. frmcnt before vf_en */ + for (i = 0; i < ISP_RT_BUF_SIZE; i++) + pstRTBuf->ring_buf[rt_dma].data[i].image.frm_cnt = + _INVALID_FRM_CNT_; + + + memset((char *)&prv_tstamp_s[rt_dma], 0x0, sizeof(MUINT32)); + memset((char *)&prv_tstamp_us[rt_dma], 0x0, sizeof(MUINT32)); +#ifdef _rtbc_buf_que_2_0_ + memset((void *)dma_en_recorder[rt_dma], 0, + sizeof(MUINT8) * ISP_RT_BUF_SIZE); + mFwRcnt.DMA_IDX[rt_dma] = 0; +#endif + + { + unsigned int ii = 0; + MUINT32 out[4] = { _IRQ_MAX, _IRQ_MAX, _IRQ_MAX, _IRQ_MAX }; + + if ((pstRTBuf->ring_buf[_imgo_].active == MFALSE) + && (pstRTBuf->ring_buf[_rrzo_].active == MFALSE)) + out[0] = _IRQ; + if ((pstRTBuf->ring_buf[_imgo_d_].active == MFALSE) + && (pstRTBuf->ring_buf[_rrzo_d_].active == MFALSE)) + out[1] = _IRQ_D; + if (pstRTBuf->ring_buf[_camsv_imgo_].active == MFALSE) + out[2] = _CAMSV_IRQ; + if (pstRTBuf->ring_buf[_camsv2_imgo_].active == MFALSE) + out[3] = _CAMSV_D_IRQ; + + for (ii = 0; ii < 4; ii++) { + if (out[ii] != _IRQ_MAX) { + sof_count[out[ii]] = 0; + start_time[out[ii]] = 0; + avg_frame_time[out[ii]] = 0; + g1stSof[out[ii]] = MTRUE; + PrvAddr[out[ii]] = 0; + g_ISPIntErr[out[ii]] = 0; +#ifdef _rtbc_buf_que_2_0_ + mFwRcnt.bLoadBaseAddr[out[ii]] = 0; + mFwRcnt.curIdx[out[ii]] = 0; + memset((void *)mFwRcnt.INC[out[ii]], 0, + sizeof(MUINT32) * ISP_RT_BUF_SIZE); + mFwRcnt.rdIdx[out[ii]] = 0; +#endif +#ifdef T_STAMP_2_0 + /**/ if (out[ii] == _IRQ) { + memset((char *)&m_T_STAMP, 0x0, + sizeof(T_STAMP)); + bSlowMotion = MFALSE; + } +#endif + } + } + for (ii = 0; ii < _rt_dma_max_; ii++) { + if (pstRTBuf->ring_buf[ii].active) + break; + + } + + if (ii == _rt_dma_max_) { + pstRTBuf->dropCnt = 0; + pstRTBuf->state = 0; + } + } + +#ifdef _MAGIC_NUM_ERR_HANDLING_ + m_LastMNum[rt_dma] = 0; +#endif + +#endif + /* spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[irqT_Lock]), flags); */ + + break; +#ifdef _rtbc_buf_que_2_0_ + case ISP_RT_BUF_CTRL_DMA_EN: + { + /*MUINT8 array[_rt_dma_max_];*/ + MUINT8 *array; + + array = kcalloc(_rt_dma_max_, sizeof(MUINT8), GFP_KERNEL); + if (NULL == array) { + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + return -ENOMEM; + } + + /* if(copy_from_user(array, (void __user*)rt_buf_ctrl.data_ptr, + sizeof(MUINT8)*_rt_dma_max_) == 0) { */ + if (copy_from_user + (array, (void __user *)rt_buf_ctrl.pExtend, + sizeof(MUINT8) * _rt_dma_max_) == 0) { + + bRawEn = MFALSE; + bRawDEn = MFALSE; + for (z = 0; z < _rt_dma_max_; z++) { + pstRTBuf->ring_buf[z].active = array[z]; + if (0 == array[z]) + continue; + /**/ if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) + LOG_INF("[rtbc][DMA_EN]:dma_%d:%d", z, + array[z]); + + } + if ((MTRUE == pstRTBuf->ring_buf[_imgo_].active) || + (MTRUE == pstRTBuf->ring_buf[_rrzo_].active)) { + bRawEn = MTRUE; + } + if ((MTRUE == pstRTBuf->ring_buf[_imgo_d_].active) || + (MTRUE == pstRTBuf->ring_buf[_rrzo_d_].active)) { + bRawDEn = MTRUE; + } + } else { + LOG_ERR("[rtbc][DMA_EN]:copy_from_user failed"); + Ret = -EFAULT; + } + kfree(array); + } + break; +#endif + case ISP_RT_BUF_CTRL_MAX: + /* Add this to remove build warning. */ + /* Do nothing. */ + break; + + } + /*free*/ + kfree((unsigned int *)p1_fbc); + kfree(p1_fbc_reg); + kfree(p1_dma_addr_reg); + kfree(rt_buf_info); + kfree(deque_buf); + /* */ + } else { + LOG_ERR("[rtbc]copy_from_user failed"); + Ret = -EFAULT; + } + + return Ret; +} + + + +#if 0 +/** + rrzo/imgo/rrzo_d/imgo_d have hw cq, + if lost p1 done, need to add start index inorder to match HW CQ + camsv have no hw cq, it will refer to WCNT at SOF. + WCNT have no change when no p1_done, so start index no need to change. +*/ +static MINT32 ISP_LostP1Done_ErrHandle(MUINT32 dma) +{ + switch (dma) { + case _imgo_: + case _rrzo_: + case _imgo_d_: + case _rrzo_d_: + pstRTBuf->ring_buf[dma].start++; + pstRTBuf->ring_buf[dma].start = + pstRTBuf->ring_buf[dma].start % pstRTBuf->ring_buf[dma].total_count; + break; + default: + break; + } +} +#endif +/* mark the behavior of reading FBC at local. to prevent hw interruptting duing sw isr flow. */ +/* above behavior will make FBC write-buffer-patch fail at p1_done */ +/* curr_pa also have this prob. too */ +static MINT32 ISP_SOF_Buf_Get(eISPIrq irqT, CQ_RTBC_FBC *pFbc, MUINT32 *pCurr_pa, + unsigned long long sec, unsigned long usec, MBOOL bDrop) +{ +#if defined(_rtbc_use_cq0c_) + + CQ_RTBC_FBC imgo_fbc; + CQ_RTBC_FBC rrzo_fbc; + MUINT32 imgo_idx = 0; /* (imgo_fbc.Bits.WCNT+imgo_fbc.Bits.FB_NUM-1)%imgo_fbc.Bits.FB_NUM;//[0,1,2,...] */ + MUINT32 rrzo_idx = 0; /* (img2o_fbc.Bits.WCNT+img2o_fbc.Bits.FB_NUM-1)%img2o_fbc.Bits.FB_NUM;//[0,1,2,...] */ + MUINT32 curr_pa = 0; + MUINT32 ch_imgo, ch_rrzo; + MUINT32 i = 0; + MUINT32 _dma_cur_fw_idx = 0; + MUINT32 _dma_cur_hw_idx = 0; + MUINT32 _working_dma = 0; + MUINT32 out = 0; + + if (_IRQ == irqT) { + imgo_fbc.Reg_val = pFbc[0].Reg_val; + rrzo_fbc.Reg_val = pFbc[1].Reg_val; + ch_imgo = _imgo_; + ch_rrzo = _rrzo_; + + if (pstRTBuf->ring_buf[ch_imgo].active) + curr_pa = pCurr_pa[0]; + else + curr_pa = pCurr_pa[1]; + + i = _PASS1; + } else { /* _IRQ_D */ + imgo_fbc.Reg_val = pFbc[2].Reg_val; + rrzo_fbc.Reg_val = pFbc[3].Reg_val; + ch_imgo = _imgo_d_; + ch_rrzo = _rrzo_d_; + + if (pstRTBuf->ring_buf[ch_imgo].active) + curr_pa = pCurr_pa[2]; + else + curr_pa = pCurr_pa[3]; + + i = _PASS1_D; + } + + if (MTRUE == g1stSof[irqT]) { /* 1st frame of streaming */ + pstRTBuf->ring_buf[ch_imgo].start = imgo_fbc.Bits.WCNT - 1; + pstRTBuf->ring_buf[ch_rrzo].start = rrzo_fbc.Bits.WCNT - 1; + /* move to below because of 1st sof&done errhandle */ + g1stSof[irqT] = MFALSE; + } + + /* */ +#if 0 /* this can't be trusted , because rcnt_in is pull high at sof */ + /* No drop */ + if (imgo_fbc.Bits.FB_NUM != imgo_fbc.Bits.FBC_CNT) { + pstRTBuf->dropCnt = 0; + } else { + /* dropped */ + pstRTBuf->dropCnt = 1; + } +#else + pstRTBuf->dropCnt = bDrop; +#endif + /* */ + /* if(IspInfo.DebugMask & ISP_DBG_INT_2) { */ + /* IRQ_LOG_KEEPER(irqT,m_CurrentPPB,_LOG_INF,"[rtbc]dropCnt(%d)\n",pstRTBuf->dropCnt); */ + /* } */ + /* No drop */ + if (0 == pstRTBuf->dropCnt) { + + /* verify write buffer */ + + /* if(PrvAddr[i] == curr_pa) */ + /* { */ + /* IRQ_LOG_KEEPER(irqT,m_CurrentPPB,_LOG_INF,"PrvAddr:Last(0x%x) == Cur(0x%x)\n",PrvAddr[i],curr_pa); */ + /* ISP_DumpReg(); */ + /* } */ + PrvAddr[i] = curr_pa; +#ifdef _rtbc_buf_que_2_0_ + imgo_idx = pstRTBuf->ring_buf[ch_imgo].start; + rrzo_idx = pstRTBuf->ring_buf[ch_rrzo].start; + /* dynamic dma port ctrl */ + if (pstRTBuf->ring_buf[ch_imgo].active) { + _dma_cur_fw_idx = imgo_idx; + _dma_cur_hw_idx = imgo_fbc.Bits.WCNT - 1; + _working_dma = ch_imgo; + } else if (pstRTBuf->ring_buf[ch_rrzo].active) { + _dma_cur_fw_idx = rrzo_idx; + _dma_cur_hw_idx = rrzo_fbc.Bits.WCNT - 1; + _working_dma = ch_rrzo; + } + + if (_dma_cur_fw_idx != _dma_cur_hw_idx) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "dma sof after done %d_%d\n", _dma_cur_fw_idx, + _dma_cur_hw_idx); + +#else + /* last update buffer index */ + rrzo_idx = rrzo_fbc.Bits.WCNT - 1; /* [0,1,2,...] */ + /* curr_img2o = img2o_fbc.Bits.WCNT - 1;//[0,1,2,...] */ + imgo_idx = rrzo_idx; +#endif + /* verify write buffer,once pass1_done lost, WCNT is untrustful. */ + if (ISP_RT_CQ0C_BUF_SIZE < pstRTBuf->ring_buf[_working_dma].total_count) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_ERR, "buf cnt(%d)\n", + pstRTBuf->ring_buf[_working_dma].total_count); + pstRTBuf->ring_buf[_working_dma].total_count = ISP_RT_CQ0C_BUF_SIZE; + } + /* */ + if (curr_pa != pstRTBuf->ring_buf[_working_dma].data[_dma_cur_fw_idx].base_pAddr) { + /* */ + /* LOG_INF("RTBC_DBG6:0x%x_0x%x\n", + curr_pa,pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].base_pAddr); */ + for (i = 0; i < pstRTBuf->ring_buf[_working_dma].total_count; i++) { + /* */ + if (curr_pa == pstRTBuf->ring_buf[_working_dma].data[i].base_pAddr) { + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "[rtbc]curr:old/new(%d/%d)\n", + _dma_cur_fw_idx, i); + + /* mark */ + /* indx can't be chged if enque by immediate mode, write baseaddress timing issue. */ + /* even if not in immediate mode, this case also should no be happened */ + /* imgo_idx = i; */ + /* rrzo_idx = i; */ + /* ignor this log if enque in immediate mode */ + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "img header err: PA(%x):0x%x_0x%x, idx:0x%x_0x%x\n", + _working_dma, curr_pa, + pstRTBuf->ring_buf[_working_dma]. + data[_dma_cur_fw_idx].base_pAddr, + _dma_cur_fw_idx, i); + break; + } + } + } + /* LOG_INF("RTBC_DBG3:%d_%d\n",imgo_idx,rrzo_idx); */ + /* LOG_INF("RTBC_DBG7 imgo:%d %d %d\n", + pstRTBuf->ring_buf[_imgo_].data[0].bFilled, + pstRTBuf->ring_buf[_imgo_].data[1].bFilled, + pstRTBuf->ring_buf[_imgo_].data[2].bFilled); */ + /* LOG_INF("RTBC_DBG7 rrzo:%d %d %d\n", + pstRTBuf->ring_buf[_rrzo_].data[0].bFilled, + pstRTBuf->ring_buf[_rrzo_].data[1].bFilled, + pstRTBuf->ring_buf[_rrzo_].data[2].bFilled); */ + /* */ + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].timeStampS = sec; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].timeStampUs = usec; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].timeStampS = sec; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].timeStampUs = usec; + /* if (IspInfo.DebugMask & ISP_DBG_INT_3) { + static MUINT32 m_sec = 0, m_usec; + MUINT32 _tmp = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].timeStampS * 1000000 + + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].timeStampUs; + + if (g1stSof[irqT]) { + m_sec = 0; + m_usec = 0; + } else { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, " timestamp:%d\n", + (_tmp - (1000000 * m_sec + m_usec))); + } + m_sec = pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].timeStampS; + m_usec = pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].timeStampUs; + } */ + if (_IRQ == irqT) { + MUINT32 _tmp = ISP_RD32(TG_REG_ADDR_GRAB_W); + MUINT32 _p1_sel = ISP_RD32(ISP_INNER_REG_ADDR_CAM_CTRL_SEL_P1); + + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.xsize = + ISP_RD32(ISP_INNER_REG_ADDR_IMGO_XSIZE) & 0x3FFF; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.w = + ((_tmp >> 16) & 0x7FFF) - (_tmp & 0x7FFF); + _tmp = ISP_RD32(TG_REG_ADDR_GRAB_H); + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.h = + ((_tmp >> 16) & 0x1FFF) - (_tmp & 0x1FFF); + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.stride = + ISP_RD32(ISP_INNER_REG_ADDR_IMGO_STRIDE) & 0x3FFF; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.bus_size = + (ISP_RD32(ISP_INNER_REG_ADDR_IMGO_STRIDE) >> 16) & 0x03; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.fmt = + (ISP_RD32(ISP_INNER_REG_ADDR_FMT_SEL_P1) & 0xF000) >> 12; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.pxl_id = + (ISP_RD32(ISP_INNER_REG_ADDR_FMT_SEL_P1) & 0x03); + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.m_num_0 = + ISP_RD32(ISP_REG_ADDR_TG_MAGIC_0); + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.frm_cnt = + (ISP_RD32(ISP_REG_ADDR_TG_INTER_ST) & 0x00FF0000) >> 16; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].dmaoCrop.x = + ISP_RD32(ISP_INNER_REG_ADDR_IMGO_CROP) & 0x3fff; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].dmaoCrop.y = + (ISP_RD32(ISP_INNER_REG_ADDR_IMGO_CROP) >> 16) & 0x1fff; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].dmaoCrop.w = + (ISP_RD32(ISP_INNER_REG_ADDR_IMGO_XSIZE) & 0x3FFF) + 1; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].dmaoCrop.h = + (ISP_RD32(ISP_INNER_REG_ADDR_IMGO_YSIZE) & 0x1FFF) + 1; + + if (_p1_sel & ISP_CAM_CTL_SEL_P1_IMGO_SEL) + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].bProcessRaw = + ISP_PURE_RAW; + else + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].bProcessRaw = + ISP_RROCESSED_RAW; + + /* pstRTBuf->ring_buf[_imgo_].data[imgo_idx].image.wbn; */ + /* pstRTBuf->ring_buf[_imgo_].data[imgo_idx].image.ob; */ + /* pstRTBuf->ring_buf[_imgo_].data[imgo_idx].image.lsc; */ + /* pstRTBuf->ring_buf[_imgo_].data[imgo_idx].image.rpg; */ + /* */ + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.xsize = + ISP_RD32(ISP_INNER_REG_ADDR_RRZO_XSIZE) & 0x3FFF; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.w = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.w; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.h = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.h; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.stride = + ISP_RD32(ISP_INNER_REG_ADDR_RRZO_STRIDE) & 0x3FFF; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.bus_size = + (ISP_RD32(ISP_INNER_REG_ADDR_RRZO_STRIDE) >> 16) & 0x03; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.fmt = + (ISP_RD32(ISP_INNER_REG_ADDR_FMT_SEL_P1) & 0x30) >> 4; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.pxl_id = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.pxl_id; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.m_num_0 = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.m_num_0; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.frm_cnt = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.frm_cnt; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].bProcessRaw = ISP_RROCESSED_RAW; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcX = + ISP_RD32(ISP_INNER_REG_ADDR_RRZ_HORI_INT_OFST) & 0x1FFF; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcY = + ISP_RD32(ISP_INNER_REG_ADDR_RRZ_VERT_INT_OFST) & 0x1FFF; + _tmp = ISP_RD32(ISP_INNER_REG_ADDR_RRZ_IN_IMG); + /* pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcW =*/ + /* ((_tmp&0x1FFF)-pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcX*2)&0x1FFF; */ + /* pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcH =*/ + /* (((_tmp>>16)&0x1FFF)-pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcY*2)&0x1FFF; */ + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcW = + (ISP_RD32(ISP_REG_ADDR_TG_RRZ_CROP_IN) & 0XFFFF); + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcH = + (ISP_RD32(ISP_REG_ADDR_TG_RRZ_CROP_IN) >> 16); + + _tmp = ISP_RD32(ISP_INNER_REG_ADDR_RRZ_OUT_IMG); + /* pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.dstW = _tmp&0x1FFF; */ + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.dstW = + ISP_RD32(ISP_REG_ADDR_RRZ_W); + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.dstH = + (_tmp >> 16) & 0x1FFF; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].dmaoCrop.x = + ISP_RD32(ISP_INNER_REG_ADDR_RRZO_CROP) & 0x3fff; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].dmaoCrop.y = + (ISP_RD32(ISP_INNER_REG_ADDR_RRZO_CROP) >> 16) & 0x1fff; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].dmaoCrop.w = + (ISP_RD32(ISP_INNER_REG_ADDR_RRZO_XSIZE) & 0x3FFF) + 1; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].dmaoCrop.h = + (ISP_RD32(ISP_INNER_REG_ADDR_RRZO_YSIZE) & 0x1FFF) + 1; + + + +#if 0 +#ifdef _MAGIC_NUM_ERR_HANDLING_ + LOG_ERR("[rtbc][sof0][m_num]:fc(0x%x),m0(0x%x),rrz_src(%d,%d)", + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.frm_cnt, + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.m_num_0, + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcW, + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcH); +#endif + + if (IspInfo.DebugMask & ISP_DBG_INT_2) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "[rtbc]TStamp(%d.%06d),curr(%d),pa(0x%x/0x%x),cq0c(0x%x)\n", + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx]. + timeStampS, + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx]. + timeStampUs, imgo_idx, + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx]. + base_pAddr, + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx]. + base_pAddr, ISP_RD32(ISP_ADDR + 0xB4)); + } +#endif + } else { + MUINT32 _tmp = ISP_RD32(TG2_REG_ADDR_GRAB_W); + MUINT32 _p1_sel = ISP_RD32(ISP_INNER_REG_ADDR_CAM_CTRL_SEL_P1_D); + + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.xsize = + ISP_RD32(ISP_INNER_REG_ADDR_IMGO_D_XSIZE) & 0x3FFF; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.w = + ((_tmp >> 16) & 0x7FFF) - (_tmp & 0x7FFF); + _tmp = ISP_RD32(TG2_REG_ADDR_GRAB_H); + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.h = + ((_tmp >> 16) & 0x1FFF) - (_tmp & 0x1FFF); + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.stride = + ISP_RD32(ISP_INNER_REG_ADDR_IMGO_D_STRIDE) & 0x3FFF; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.bus_size = + (ISP_RD32(ISP_INNER_REG_ADDR_IMGO_D_STRIDE) >> 16) & 0x03; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.fmt = + (ISP_RD32(ISP_INNER_REG_ADDR_FMT_SEL_P1_D) & 0xF000) >> 12; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.pxl_id = + (ISP_RD32(ISP_INNER_REG_ADDR_FMT_SEL_P1_D) & 0x03); + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.m_num_0 = + ISP_RD32(ISP_REG_ADDR_TG2_MAGIC_0); + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.frm_cnt = + (ISP_RD32(ISP_REG_ADDR_TG2_INTER_ST) & 0x00FF0000) >> 16; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].dmaoCrop.x = + ISP_RD32(ISP_INNER_REG_ADDR_IMGO_D_CROP) & 0x3fff; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].dmaoCrop.y = + (ISP_RD32(ISP_INNER_REG_ADDR_IMGO_D_CROP) >> 16) & 0x1fff; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].dmaoCrop.w = + (ISP_RD32(ISP_INNER_REG_ADDR_IMGO_D_XSIZE) & 0x3FFF) + 1; + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].dmaoCrop.h = + (ISP_RD32(ISP_INNER_REG_ADDR_IMGO_D_YSIZE) & 0x1FFF) + 1; + + if (_p1_sel & ISP_CAM_CTL_SEL_P1_D_IMGO_SEL) + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].bProcessRaw = + ISP_PURE_RAW; + else + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].bProcessRaw = + ISP_RROCESSED_RAW; + + + /* */ + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.xsize = + ISP_RD32(ISP_INNER_REG_ADDR_RRZO_D_XSIZE) & 0x3FFF; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.w = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.w; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.h = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.h; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.stride = + ISP_RD32(ISP_INNER_REG_ADDR_RRZO_D_STRIDE) & 0x3FFF; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.bus_size = + (ISP_RD32(ISP_INNER_REG_ADDR_RRZO_D_STRIDE) >> 16) & 0x03; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.fmt = + (ISP_RD32(ISP_INNER_REG_ADDR_FMT_SEL_P1_D) & 0x30) >> 4; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.pxl_id = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.pxl_id; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.m_num_0 = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.m_num_0; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.frm_cnt = + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx].image.frm_cnt; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].bProcessRaw = ISP_RROCESSED_RAW; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcX = + ISP_RD32(ISP_INNER_REG_ADDR_RRZ_D_HORI_INT_OFST) & 0x1FFF; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcY = + ISP_RD32(ISP_INNER_REG_ADDR_RRZ_D_VERT_INT_OFST) & 0x1FFF; + _tmp = ISP_RD32(ISP_INNER_REG_ADDR_RRZ_D_IN_IMG); + /* pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcW =*/ + /* ((_tmp&0x1FFF)-(pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcX)*2)&0x1FFF; */ + /* pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcH =*/ + /* ((((_tmp>>16)&0x1FFF))-pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcY*2)&0x1FFF; */ + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcW = + (ISP_RD32(ISP_REG_ADDR_TG_RRZ_CROP_IN_D) & 0XFFFF); + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcH = + (ISP_RD32(ISP_REG_ADDR_TG_RRZ_CROP_IN_D) >> 16); + + _tmp = ISP_RD32(ISP_INNER_REG_ADDR_RRZ_D_OUT_IMG); + /* pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.dstW = _tmp&0x1FFF; */ + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.dstW = + ISP_RD32(ISP_REG_ADDR_RRZ_W_D); + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.dstH = + (_tmp >> 16) & 0x1FFF; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].dmaoCrop.x = + ISP_RD32(ISP_INNER_REG_ADDR_RRZO_D_CROP) & 0x3fff; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].dmaoCrop.y = + (ISP_RD32(ISP_INNER_REG_ADDR_RRZO_D_CROP) >> 16) & 0x1fff; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].dmaoCrop.w = + (ISP_RD32(ISP_INNER_REG_ADDR_RRZO_D_XSIZE) & 0x3FFF) + 1; + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].dmaoCrop.h = + (ISP_RD32(ISP_INNER_REG_ADDR_RRZO_D_YSIZE) & 0x1FFF) + 1; + /* */ + + +#if 0 +#ifdef _MAGIC_NUM_ERR_HANDLING_ + LOG_ERR("[rtbc][sof0][m_num]:fc(0x%x),m0(0x%x),rrz_src(%d,%d)", + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.frm_cnt, + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].image.m_num_0, + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcW, + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx].rrzInfo.srcH); +#endif + + if (IspInfo.DebugMask & ISP_DBG_INT_2) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "[rtbc]TStamp(%d.%06d),curr(%d),pa(0x%x/0x%x),cq0c(0x%x)\n", + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx]. + timeStampS, + pstRTBuf->ring_buf[ch_imgo].data[imgo_idx]. + timeStampUs, imgo_idx, + pstRTBuf->ring_buf[ch_imgo].data[rrzo_idx]. + base_pAddr, + pstRTBuf->ring_buf[ch_rrzo].data[rrzo_idx]. + base_pAddr, ISP_RD32(ISP_ADDR + 0xB4)); + } +#endif + } + /* */ + } + + /* frame time profile */ + DMA_TRANS(ch_imgo, out); + if (0 == start_time[out]) { + start_time[out] = sec * 1000000 + usec; + } else { /* calc once per senond */ + if (avg_frame_time[out]) { + avg_frame_time[out] += (sec * 1000000 + usec) - avg_frame_time[out]; + avg_frame_time[out] = avg_frame_time[out] >> 1; + } else { + avg_frame_time[out] = (sec * 1000000 + usec) - start_time[out]; + } + } + + sof_count[out]++; + if (sof_count[out] > 255) { /* for match vsync cnt */ + sof_count[out] -= 256; + } + pstRTBuf->state = ISP_RTBC_STATE_SOF; +#else +#ifdef _rtbc_buf_que_2_0_ +#error "isp kernel define condition is conflicted" +#endif +#endif + + return 0; +} /* */ + +/* mark the behavior of reading FBC at local. to prevent hw interruptting duing sw isr flow. */ +/* above behavior will make FBC write-buffer-patch fail at p1_done */ +/* curr_pa also have this prob. too */ +static MINT32 ISP_CAMSV_SOF_Buf_Get(unsigned int dma, CQ_RTBC_FBC camsv_fbc, MUINT32 curr_pa, + unsigned long long sec, unsigned long usec, MBOOL bDrop) +{ + MUINT32 camsv_imgo_idx = 0; + eISPIrq irqT; + MUINT32 out; + + DMA_TRANS(dma, out); + + if (_camsv_imgo_ == dma) + irqT = _CAMSV_IRQ; + else + irqT = _CAMSV_D_IRQ; + + + if (MTRUE == g1stSof[irqT]) { /* 1st frame of streaming */ + pstRTBuf->ring_buf[dma].start = camsv_fbc.Bits.WCNT - 1; + g1stSof[irqT] = MFALSE; + } +#if 0 /* this can't be trusted , because rcnt_in is pull high at sof */ + if (camsv_fbc.Bits.FB_NUM != camsv_fbc.Bits.FBC_CNT) + pstRTBuf->dropCnt = 0; + else + pstRTBuf->dropCnt = 1; + +#else + pstRTBuf->dropCnt = bDrop; +#endif + + if (IspInfo.DebugMask & ISP_DBG_INT_2) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, "sv%d dropCnt(%ld)\n", dma, + pstRTBuf->dropCnt); + + + /* No drop */ + if (0 == pstRTBuf->dropCnt) { + if (PrvAddr[out] == curr_pa) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_ERR, + "sv%d overlap prv(0x%x) = Cur(0x%x)\n", dma, PrvAddr[out], + curr_pa); + /* ISP_DumpReg(); */ + + PrvAddr[out] = curr_pa; + + /* last update buffer index */ + camsv_imgo_idx = (camsv_fbc.Bits.WCNT % camsv_fbc.Bits.FB_NUM); /* nest frame */ + + /* mark this: CAMSV_IMGO_* might be changed here, but it should be changed by MVHDR or PDAF*/ + /*if (_camsv_imgo_ == dma) + ISP_WR32(ISP_REG_ADDR_IMGO_SV_BASE_ADDR, + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].base_pAddr); + LOG_INF("[SOF]IMGO_SV:addr should write by MVHDR"); + else + ISP_WR32(ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR, + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].base_pAddr); + LOG_INF("[SOF]IMGO_SV_D:addr should write by PD");*/ + + + /* */ + camsv_imgo_idx = + (camsv_imgo_idx > 0) ? (camsv_imgo_idx - 1) : (camsv_fbc.Bits.FB_NUM - 1); + if (camsv_imgo_idx != pstRTBuf->ring_buf[dma].start) { + /* theoretically, it shout not be happened( wcnt is inc. at p1_done) */ + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_ERR, "sv%d WCNT%d != start%d\n", + dma, camsv_fbc.Bits.WCNT, pstRTBuf->ring_buf[dma].start); + } + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].timeStampS = sec; + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].timeStampUs = usec; + /* camsv support no inner address, these informations r truely untrustful, but */ + /* because of no resize in camsv, so these r also ok. */ + if (dma == _camsv_imgo_) { + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].image.w = + (ISP_RD32(ISP_REG_ADDR_IMGO_SV_XSIZE) & 0x3FFF); + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].image.h = + (ISP_RD32(ISP_REG_ADDR_IMGO_SV_YSIZE) & 0x1FFF); + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].image.stride = + (ISP_RD32(ISP_REG_ADDR_IMGO_SV_STRIDE) & 0x3FFF); + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].image.fmt = + (ISP_RD32(ISP_REG_ADDR_CAMSV_FMT_SEL) & 0x30000); + } else { + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].image.w = + (ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_XSIZE) & 0x3FFF); + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].image.h = + (ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_YSIZE) & 0x1FFF); + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].image.stride = + (ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_STRIDE) & 0x3FFF); + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].image.fmt = + (ISP_RD32(ISP_REG_ADDR_CAMSV2_FMT_SEL) & 0x30000); + } + + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "sv%d T(%d.%06d),cur(%d),addr(0x%x),prv(0x%x),fbc(0x%08x)\n", + dma, pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].timeStampS, + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].timeStampUs, + camsv_imgo_idx, + pstRTBuf->ring_buf[dma].data[camsv_imgo_idx].base_pAddr, + PrvAddr[out], camsv_fbc.Reg_val); + } + /* */ + } + + if (0 == start_time[out]) { + start_time[out] = sec * 1000000 + usec; + } else { /* calc once per senond */ + if (avg_frame_time[out]) { + avg_frame_time[out] += (sec * 1000000 + usec) - avg_frame_time[out]; + avg_frame_time[out] = avg_frame_time[out] >> 1; + } else { + avg_frame_time[out] = (sec * 1000000 + usec) - start_time[out]; + } + } + + sof_count[out]++; + + pstRTBuf->state = ISP_RTBC_STATE_SOF; + return 0; +} + +/* mark the behavior of reading FBC at local. to prevent hw interruptting duing sw isr flow. */ +/* above behavior will make FBC write-buffer-patch fail at p1_done */ +/* curr_pa also have this prob. too */ +static MINT32 ISP_CAMSV_DONE_Buf_Time(unsigned int dma, CQ_RTBC_FBC fbc, unsigned long long sec, + unsigned long usec) +{ + unsigned int curr; + eISPIrq irqT; + /* MUINT32 loopCount = 0; */ + MUINT32 _tmp; + MUINT32 out = 0; + + /* */ + if (_camsv_imgo_ == dma) + irqT = _CAMSV_IRQ; + else + irqT = _CAMSV_D_IRQ; + + /* */ + if (0 == pstRTBuf->ring_buf[dma].empty_count) { + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, "sv%d RTB empty,start(%d)\n", + dma, pstRTBuf->ring_buf[dma].start); + + /* TODO: err handle */ + return -1; + } + + curr = pstRTBuf->ring_buf[dma].start; + + { /* wcnt start at idx1, and +1 at p1_done by hw */ + _tmp = fbc.Bits.WCNT - 1; + _tmp = (_tmp > 0) ? (_tmp - 1) : (fbc.Bits.FB_NUM - 1); + } + if (curr != _tmp) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_ERR, "sv%d:RTBC_%d != FBC cnt_%d\n", dma, + curr, _tmp); + + + DMA_TRANS(dma, out); + while (1) { /* search next start buf, basically loop 1 time only */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, "sv%d,cur(%d),bFilled(%d)\n", + dma, curr, pstRTBuf->ring_buf[dma].data[curr].bFilled); + } + /* this buf shoud be empty.If it's non-empty , maybe err in start index(timing shift) */ + if (pstRTBuf->ring_buf[dma].data[curr].bFilled == ISP_RTBC_BUF_EMPTY) { + pstRTBuf->ring_buf[dma].data[curr].bFilled = ISP_RTBC_BUF_FILLED; + /* start + 1 */ + pstRTBuf->ring_buf[dma].start = + (curr + 1) % pstRTBuf->ring_buf[dma].total_count; + pstRTBuf->ring_buf[dma].empty_count--; + pstRTBuf->ring_buf[dma].img_cnt = sof_count[out]; + + if (g1stSof[irqT] == MTRUE) + LOG_ERR("Done&&Sof recieve at the same time in 1st f\n"); + + break; + } else { + if (IspInfo.DebugMask & ISP_DBG_INT_2) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_ERR, + "sv%d:curr(%d),bFilled(%d) != EMPTY\n", dma, curr, + pstRTBuf->ring_buf[dma].data[curr].bFilled); + } + /* start + 1 */ + /* curr = (curr+1)%pstRTBuf->ring_buf[dma].total_count; */ + break; + } +#if 0 + if (++loopCount > pstRTBuf->ring_buf[dma].total_count) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_ERR, + "sv%d:find no empty buf in total_count(%d)\n", dma, + pstRTBuf->ring_buf[dma].total_count); + break; + } else { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "sv%d:buf is not empty for current p1_done\n", dma); + } +#endif + } + + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, "sv%d:start(%d),empty(%d)\n", + dma, + pstRTBuf->ring_buf[dma].start, pstRTBuf->ring_buf[dma].empty_count); + } + + /* */ + /* if(IspInfo.DebugMask & ISP_DBG_INT_2) { */ + /* IRQ_LOG_KEEPER(irqT,m_CurrentPPB,_LOG_INF,"sv%d:curr(%d),sec(%lld),usec(%ld)\n",*/ + /* dma, curr, sec, usec); */ + /* } */ + + + /* */ + pstRTBuf->state = ISP_RTBC_STATE_DONE; + + return 0; +} + +/* mark the behavior of reading FBC at local. to prevent hw interruptting duing sw isr flow. */ +/* above behavior will make FBC write-buffer-patch fail at p1_done */ +static MINT32 ISP_DONE_Buf_Time(eISPIrq irqT, CQ_RTBC_FBC *pFbc, unsigned long long sec, + unsigned long usec) +{ + int i, k, m; + int i_dma; + unsigned int curr; + /* unsigned int reg_fbc; */ + /* MUINT32 reg_val = 0; */ + MUINT32 ch_imgo, ch_rrzo; + CQ_RTBC_FBC imgo_fbc; + CQ_RTBC_FBC rrzo_fbc; + CQ_RTBC_FBC _dma_cur_fbc; + MUINT32 _working_dma = 0; +#ifdef _rtbc_buf_que_2_0_ + /* for isr cb timing shift err hanlde */ + MUINT32 shiftT = 0; + MUINT32 out = 0; +#endif + if (_IRQ == irqT) { + ch_imgo = _imgo_; + ch_rrzo = _rrzo_; + imgo_fbc.Reg_val = pFbc[0].Reg_val; + rrzo_fbc.Reg_val = pFbc[1].Reg_val; + } else { + ch_imgo = _imgo_d_; + ch_rrzo = _rrzo_d_; + imgo_fbc.Reg_val = pFbc[2].Reg_val; + rrzo_fbc.Reg_val = pFbc[3].Reg_val; + } + +#ifdef _rtbc_buf_que_2_0_ + + /* dynamic dma port ctrl */ + if (pstRTBuf->ring_buf[ch_imgo].active && pstRTBuf->ring_buf[ch_rrzo].active) { + /* if P1_DON ISR is coming at output 2 imgo frames, but 1 rrzo frame (another rrzo frame is slowly), + we should refer to smaller WCNT, avoid patch too many times*/ + if (rrzo_fbc.Bits.WCNT < imgo_fbc.Bits.WCNT) { + _dma_cur_fbc = rrzo_fbc; + _working_dma = ch_rrzo; + } else { + _dma_cur_fbc = imgo_fbc; + _working_dma = ch_imgo; + } + } else if (pstRTBuf->ring_buf[ch_imgo].active) { + _dma_cur_fbc = imgo_fbc; + _working_dma = ch_imgo; + } else if (pstRTBuf->ring_buf[ch_rrzo].active) { + _dma_cur_fbc = rrzo_fbc; + _working_dma = ch_rrzo; + } else { + LOG_ERR("non-supported dma port(%d/%d)\n", pstRTBuf->ring_buf[ch_imgo].active, + pstRTBuf->ring_buf[ch_rrzo].active); + return 0; + } + /* isr cb timing shift err handle */ + if (_dma_cur_fbc.Bits.WCNT > 0) { + if (_dma_cur_fbc.Bits.WCNT > (pstRTBuf->ring_buf[_working_dma].start + 2)) { + shiftT = + _dma_cur_fbc.Bits.WCNT - pstRTBuf->ring_buf[_working_dma].start - 2; + if (shiftT > 0) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "[rtbc%d]:alert(%d,%d)\n", irqT, + pstRTBuf->ring_buf[_working_dma].start, + _dma_cur_fbc.Bits.WCNT); + } else if (_dma_cur_fbc.Bits.WCNT < (pstRTBuf->ring_buf[_working_dma].start + 2)) { + shiftT = + _dma_cur_fbc.Bits.WCNT + _dma_cur_fbc.Bits.FB_NUM - + (pstRTBuf->ring_buf[_working_dma].start + 2); + if (shiftT >= _dma_cur_fbc.Bits.FB_NUM) { + LOG_ERR("err shiftT = (%d,%d ,%d)\n", _dma_cur_fbc.Bits.WCNT, + _dma_cur_fbc.Bits.FB_NUM, + pstRTBuf->ring_buf[_working_dma].start); + shiftT = + (_dma_cur_fbc.Bits. + FB_NUM ? (_dma_cur_fbc.Bits.FB_NUM - + 1) : (_dma_cur_fbc.Bits.FB_NUM)); + } + } else { + } /* _dma_cur_fbc.Bits.WCNT == (pstRTBuf->ring_buf[_working_dma].start + 2) */ + } +#endif + + +#ifdef _rtbc_buf_que_2_0_ + for (k = 0; k < shiftT + 1; k++) +#endif + { + for (i = 0; i <= 1; i++) { + /* */ + if (0 == i) { + i_dma = ch_imgo; + /* reg_fbc = ch_imgo_fbc; */ + } else { + i_dma = ch_rrzo; + /* reg_fbc = ch_rrzo_fbc; */ + } + /* */ + if (0 == pstRTBuf->ring_buf[i_dma].empty_count) { + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "[rtbc][DONE]:dma(%d)buf num empty,start(%d)\n", + i_dma, pstRTBuf->ring_buf[i_dma].start); + + /* */ + continue; + } +#if 0 + /* once if buffer put into queue between SOF and ISP_DONE. */ + if (MFALSE == pstRTBuf->ring_buf[i_dma].active) { + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) + LOG_DBG("[rtbc][DONE] ERROR: missing SOF "); + + /* */ + continue; + } +#endif + curr = pstRTBuf->ring_buf[i_dma].start; + /* MUINT32 loopCount = 0; */ + while (1) { + if (IspInfo.DebugMask & ISP_DBG_INT_2) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "i_dma(%d),curr(%d),bFilled(%d)\n", i_dma, + curr, + pstRTBuf->ring_buf[i_dma].data[curr]. + bFilled); + } + /* */ + if (pstRTBuf->ring_buf[i_dma].data[curr].bFilled == + ISP_RTBC_BUF_EMPTY) { + if (IspInfo.DebugMask & ISP_DBG_INT_2) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "[rtbc][DONE]:dma_%d,fill buffer,cur_%d\n", + i_dma, curr); + pstRTBuf->ring_buf[i_dma].data[curr].bFilled = + ISP_RTBC_BUF_FILLED; + /* start + 1 */ + pstRTBuf->ring_buf[i_dma].start = + (curr + 1) % pstRTBuf->ring_buf[i_dma].total_count; + pstRTBuf->ring_buf[i_dma].empty_count--; + /* */ + if (g1stSof[irqT] == MTRUE) + LOG_ERR + ("Done&&Sof recieve at the same time in 1st f(%d)\n", + i_dma); + + break; + } else { + if (1) { /* (IspInfo.DebugMask & ISP_DBG_INT_2) { */ + /**/ for (m = 0; m < ISP_RT_BUF_SIZE;) { + LOG_ERR + ("dma_%d,cur_%d,bFilled_%d != EMPTY(%d %d %d %d)\n", + i_dma, curr, + pstRTBuf->ring_buf[i_dma]. + data[curr].bFilled, + pstRTBuf->ring_buf[i_dma].data[m]. + bFilled, + pstRTBuf->ring_buf[i_dma].data[m + + 1]. + bFilled, + pstRTBuf->ring_buf[i_dma].data[m + + 2]. + bFilled, + pstRTBuf->ring_buf[i_dma].data[m + + 3]. + bFilled); + m = m + 4; + } + } + /* start + 1 */ + /* pstRTBuf->ring_buf[i_dma].start = */ + /* (curr+1)%pstRTBuf->ring_buf[i_dma].total_count; */ + break; + } +#if 0 + loopCount++; + if (loopCount > pstRTBuf->ring_buf[i_dma].total_count) { + LOG_ERR + ("Can't find empty dma(%d) buf in total_count(%d)", + i_dma, pstRTBuf->ring_buf[i_dma].total_count); + break; + } +#endif + } +#if 0 + /* enable fbc to stall DMA */ + if (0 == pstRTBuf->ring_buf[i_dma].empty_count) { + if (_imgo_ == i_dma) { + reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_FBC); + reg_val |= 0x4000; + /* ISP_WR32(ISP_REG_ADDR_IMGO_FBC,reg_val); */ + } else { + reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_D_FBC); + reg_val |= 0x4000; + /* ISP_WR32(ISP_REG_ADDR_IMGO_D_FBC,reg_val); */ + } + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "[rtbc][DONE]:dma(%d),en fbc(0x%x) stalled DMA out", + i_dma, ISP_RD32(reg_fbc)); + + } +#endif + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) { + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, + "[rtbc][DONE]:dma(%d),start(%d),empty(%d)\n", i_dma, + pstRTBuf->ring_buf[i_dma].start, + pstRTBuf->ring_buf[i_dma].empty_count); + } +#if 0 /* time stamp move to sof */ + /* */ + pstRTBuf->ring_buf[i_dma].data[curr].timeStampS = sec; + pstRTBuf->ring_buf[i_dma].data[curr].timeStampUs = usec; + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT_2) + LOG_DBG("[rtbc][DONE]:dma(%d),curr(%d),sec(%lld),usec(%ld) ", i_dma, + curr, sec, usec); + +#endif + /* */ + DMA_TRANS(i_dma, out); + pstRTBuf->ring_buf[i_dma].img_cnt = sof_count[out]; + } + } + + if (pstRTBuf->ring_buf[ch_imgo].active && pstRTBuf->ring_buf[ch_rrzo].active) { + if (pstRTBuf->ring_buf[ch_imgo].start != pstRTBuf->ring_buf[ch_rrzo].start) { + LOG_ERR("start idx mismatch %d_%d(%d %d %d,%d %d %d)", + pstRTBuf->ring_buf[ch_imgo].start, + pstRTBuf->ring_buf[ch_rrzo].start, + pstRTBuf->ring_buf[ch_imgo].data[0].bFilled, + pstRTBuf->ring_buf[ch_imgo].data[1].bFilled, + pstRTBuf->ring_buf[ch_imgo].data[2].bFilled, + pstRTBuf->ring_buf[ch_rrzo].data[0].bFilled, + pstRTBuf->ring_buf[ch_rrzo].data[1].bFilled, + pstRTBuf->ring_buf[ch_rrzo].data[2].bFilled); + } + } + /* LOG_INF("RTBC_DBG7 imgo(buf cnt): %d %d %d\n", + pstRTBuf->ring_buf[_imgo_].data[0].bFilled, + pstRTBuf->ring_buf[_imgo_].data[1].bFilled, + pstRTBuf->ring_buf[_imgo_].data[2].bFilled); */ + /* LOG_INF("RTBC_DBG7 rrzo(buf cnt): %d %d %d\n", + pstRTBuf->ring_buf[_rrzo_].data[0].bFilled, + pstRTBuf->ring_buf[_rrzo_].data[1].bFilled, + pstRTBuf->ring_buf[_rrzo_].data[2].bFilled); */ +#if 0 + if (IspInfo.DebugMask & ISP_DBG_INT_2) + IRQ_LOG_KEEPER(irqT, m_CurrentPPB, _LOG_INF, "-:[rtbc]"); + +#endif + /* */ + pstRTBuf->state = ISP_RTBC_STATE_DONE; + /* spin_unlock_irqrestore(&(IspInfo.SpinLockRTBC),g_Flash_SpinLock); */ + + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_ED_BufQue_Update_GPtr(int listTag) +{ + MINT32 ret = 0; + MINT32 tmpIdx = 0; + MINT32 cnt = 0; + bool stop = false; + int i = 0; + ISP_ED_BUF_STATE_ENUM gPtrSts = ISP_ED_BUF_STATE_NONE; + + switch (listTag) { + case P2_EDBUF_RLIST_TAG: + /* [1] check global pointer current sts */ + gPtrSts = P2_EDBUF_RingList[P2_EDBUF_RList_CurBufIdx].bufSts; + + /* ////////////////////////////////////////////////////////////////////// */ + /* Assume we have the buffer list in the following situation */ + /* ++++++ ++++++ ++++++ */ + /* + vss + + prv + + prv + */ + /* ++++++ ++++++ ++++++ */ + /* not deque erased enqued */ + /* done */ + /* */ + /* if the vss deque is done, we should update the CurBufIdx */ + /* to the next "enqued" buffer node instead of just moving to the next buffer node */ + /* ////////////////////////////////////////////////////////////////////// */ + /* [2]calculate traverse count needed */ + if (P2_EDBUF_RList_FirstBufIdx <= P2_EDBUF_RList_LastBufIdx) { + cnt = P2_EDBUF_RList_LastBufIdx - P2_EDBUF_RList_FirstBufIdx; + } else { + cnt = _MAX_SUPPORT_P2_FRAME_NUM_ - P2_EDBUF_RList_FirstBufIdx; + cnt += P2_EDBUF_RList_LastBufIdx; + } + + /* [3] update */ + tmpIdx = P2_EDBUF_RList_CurBufIdx; + switch (gPtrSts) { + case ISP_ED_BUF_STATE_ENQUE: + P2_EDBUF_RingList[P2_EDBUF_RList_CurBufIdx].bufSts = + ISP_ED_BUF_STATE_RUNNING; + break; + case ISP_ED_BUF_STATE_WAIT_DEQUE_FAIL: + case ISP_ED_BUF_STATE_DEQUE_SUCCESS: + case ISP_ED_BUF_STATE_DEQUE_FAIL: + do { /* to find the newest cur index */ + tmpIdx = (tmpIdx + 1) % _MAX_SUPPORT_P2_FRAME_NUM_; + switch (P2_EDBUF_RingList[tmpIdx].bufSts) { + case ISP_ED_BUF_STATE_ENQUE: + case ISP_ED_BUF_STATE_RUNNING: + P2_EDBUF_RingList[tmpIdx].bufSts = ISP_ED_BUF_STATE_RUNNING; + P2_EDBUF_RList_CurBufIdx = tmpIdx; + stop = true; + break; + case ISP_ED_BUF_STATE_WAIT_DEQUE_FAIL: + case ISP_ED_BUF_STATE_DEQUE_SUCCESS: + case ISP_ED_BUF_STATE_DEQUE_FAIL: + case ISP_ED_BUF_STATE_NONE: + default: + break; + } + i++; + } while ((i < cnt) && (!stop)); + /* ////////////////////////////////////////////////////////////////////// */ + /* Assume we have the buffer list in the following situation */ + /* ++++++ ++++++ ++++++ */ + /* + vss + + prv + + prv + */ + /* ++++++ ++++++ ++++++ */ + /* not deque erased erased */ + /* done */ + /* */ + /* all the buffer node are deque done in the current moment, should */ + /* update current index to the last node */ + /* if the vss deque is done, we should update the CurBufIdx */ + /* to the last buffer node */ + /* ////////////////////////////////////////////////////////////////////// */ + if ((!stop) && (i == (cnt))) + P2_EDBUF_RList_CurBufIdx = P2_EDBUF_RList_LastBufIdx; + + break; + case ISP_ED_BUF_STATE_NONE: + case ISP_ED_BUF_STATE_RUNNING: + default: + break; + } + break; + case P2_EDBUF_MLIST_TAG: + default: + LOG_ERR("Wrong List tag(%d)\n", listTag); + break; + } + return ret; +} + +/******************************************************************************* +* +********************************************************************************/ +#if 0 /* disable it to avoid build warning */ +static MINT32 ISP_ED_BufQue_Set_FailNode(ISP_ED_BUF_STATE_ENUM failType, MINT32 idx) +{ + MINT32 ret = 0; + + spin_lock(&(SpinLockEDBufQueList)); + /* [1]set fail type */ + P2_EDBUF_RingList[idx].bufSts = failType; + + /* [2]update global pointer */ + ISP_ED_BufQue_Update_GPtr(P2_EDBUF_RLIST_TAG); + spin_unlock(&(SpinLockEDBufQueList)); + return ret; +} +#endif + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_ED_BufQue_Erase(MINT32 idx, int listTag) +{ + MINT32 ret = -1; + bool stop = false; + int i = 0; + MINT32 cnt = 0; + int tmpIdx = 0; + + switch (listTag) { + case P2_EDBUF_MLIST_TAG: + tmpIdx = P2_EDBUF_MList_FirstBufIdx; + /* [1] clear buffer status */ + P2_EDBUF_MgrList[idx].processID = 0x0; + P2_EDBUF_MgrList[idx].callerID = 0x0; + P2_EDBUF_MgrList[idx].p2dupCQIdx = -1; + P2_EDBUF_MgrList[idx].frameNum = 0; + P2_EDBUF_MgrList[idx].dequedNum = 0; + /* [2] update first index */ + if (P2_EDBUF_MgrList[tmpIdx].p2dupCQIdx == -1) { + /* traverse count needed, cuz user may erase the element */ + /* but not the one at first idx(pip or vss scenario) */ + if (P2_EDBUF_MList_FirstBufIdx <= P2_EDBUF_MList_LastBufIdx) { + cnt = P2_EDBUF_MList_LastBufIdx - P2_EDBUF_MList_FirstBufIdx; + } else { + cnt = _MAX_SUPPORT_P2_PACKAGE_NUM_ - P2_EDBUF_MList_FirstBufIdx; + cnt += P2_EDBUF_MList_LastBufIdx; + } + do { /* to find the newest first lindex */ + tmpIdx = (tmpIdx + 1) % _MAX_SUPPORT_P2_PACKAGE_NUM_; + switch (P2_EDBUF_MgrList[tmpIdx].p2dupCQIdx) { + case (-1): + break; + default: + stop = true; + P2_EDBUF_MList_FirstBufIdx = tmpIdx; + break; + } + i++; + } while ((i < cnt) && (!stop)); + /* current last erased element in list is the one firstBufindex point at */ + /* and all the buffer node are deque done in the current moment, */ + /* should update first index to the last node */ + if ((!stop) && (i == cnt)) + P2_EDBUF_MList_FirstBufIdx = P2_EDBUF_MList_LastBufIdx; + + } + break; + case P2_EDBUF_RLIST_TAG: + tmpIdx = P2_EDBUF_RList_FirstBufIdx; + /* [1] clear buffer status */ + P2_EDBUF_RingList[idx].processID = 0x0; + P2_EDBUF_RingList[idx].callerID = 0x0; + P2_EDBUF_RingList[idx].p2dupCQIdx = -1; + P2_EDBUF_RingList[idx].bufSts = ISP_ED_BUF_STATE_NONE; + EDBufQueRemainNodeCnt--; + /* [2]update first index */ + if (P2_EDBUF_RingList[tmpIdx].bufSts == ISP_ED_BUF_STATE_NONE) { + /* traverse count needed, cuz user may erase the element but not the one at first idx */ + if (P2_EDBUF_RList_FirstBufIdx <= P2_EDBUF_RList_LastBufIdx) { + cnt = P2_EDBUF_RList_LastBufIdx - P2_EDBUF_RList_FirstBufIdx; + } else { + cnt = _MAX_SUPPORT_P2_FRAME_NUM_ - P2_EDBUF_RList_FirstBufIdx; + cnt += P2_EDBUF_RList_LastBufIdx; + } + /* to find the newest first lindex */ + do { + tmpIdx = (tmpIdx + 1) % _MAX_SUPPORT_P2_FRAME_NUM_; + switch (P2_EDBUF_RingList[tmpIdx].bufSts) { + case ISP_ED_BUF_STATE_ENQUE: + case ISP_ED_BUF_STATE_RUNNING: + case ISP_ED_BUF_STATE_WAIT_DEQUE_FAIL: + case ISP_ED_BUF_STATE_DEQUE_SUCCESS: + case ISP_ED_BUF_STATE_DEQUE_FAIL: + stop = true; + P2_EDBUF_RList_FirstBufIdx = tmpIdx; + break; + case ISP_ED_BUF_STATE_NONE: + default: + break; + } + i++; + } while ((i < cnt) && (!stop)); + /* current last erased element in list is the one firstBufindex point at */ + /* and all the buffer node are deque done in the current moment, */ + /* should update first index to the last node */ + if ((!stop) && (i == (cnt))) + P2_EDBUF_RList_FirstBufIdx = P2_EDBUF_RList_LastBufIdx; + + } + break; + default: + break; + } + return ret; +} + +/******************************************************************************* +* get first matched buffer +********************************************************************************/ +static MINT32 ISP_ED_BufQue_Get_FirstMatBuf(ISP_ED_BUFQUE_STRUCT param, int ListTag, int type) +{ + MINT32 idx = -1; + MINT32 i = 0; + + switch (ListTag) { + case P2_EDBUF_MLIST_TAG: + if (type == 0) { /* for user wait frame, do not care p2 dupCq index, first enqued p2 dupCQ first out */ + if (P2_EDBUF_MList_FirstBufIdx <= P2_EDBUF_MList_LastBufIdx) { + for (i = P2_EDBUF_MList_FirstBufIdx; i <= P2_EDBUF_MList_LastBufIdx; + i++) { + if ((P2_EDBUF_MgrList[i].processID == param.processID) + && (P2_EDBUF_MgrList[i].callerID == param.callerID)) { + idx = i; + break; + } + } + } else { + for (i = P2_EDBUF_MList_FirstBufIdx; + i < _MAX_SUPPORT_P2_PACKAGE_NUM_; i++) { + if ((P2_EDBUF_MgrList[i].processID == param.processID) + && (P2_EDBUF_MgrList[i].callerID == param.callerID)) { + idx = i; + break; + } + } + if (idx != -1) { /*get in the first for loop */ + } else { + for (i = 0; i <= P2_EDBUF_MList_LastBufIdx; i++) { + /**/ if ((P2_EDBUF_MgrList[i].processID == + param.processID) + && (P2_EDBUF_MgrList[i].callerID == + param.callerID)) { + idx = i; + break; + } + } + } + } + } else { /* for buffer node deque done notify */ + if (P2_EDBUF_MList_FirstBufIdx <= P2_EDBUF_MList_LastBufIdx) { + for (i = P2_EDBUF_MList_FirstBufIdx; i <= P2_EDBUF_MList_LastBufIdx; + i++) { + if ((P2_EDBUF_MgrList[i].processID == param.processID) + && (P2_EDBUF_MgrList[i].callerID == param.callerID) + && (P2_EDBUF_MgrList[i].p2dupCQIdx == param.p2dupCQIdx) + && (P2_EDBUF_MgrList[i].dequedNum < + P2_EDBUF_MgrList[i].frameNum)) { + /* avoid race that dupCQ_1 of buffer2 enqued while dupCQ_1 of buffer1 have beend deque done but not been erased yet */ + idx = i; + break; + } + } + } else { + for (i = P2_EDBUF_MList_FirstBufIdx; + i < _MAX_SUPPORT_P2_PACKAGE_NUM_; i++) { + if ((P2_EDBUF_MgrList[i].processID == param.processID) + && (P2_EDBUF_MgrList[i].callerID == param.callerID) + && (P2_EDBUF_MgrList[i].p2dupCQIdx == param.p2dupCQIdx) + && (P2_EDBUF_MgrList[i].dequedNum < + P2_EDBUF_MgrList[i].frameNum)) { + idx = i; + break; + } + } + if (idx != -1) { /*get in the first for loop */ + } else { + for (i = 0; i <= P2_EDBUF_MList_LastBufIdx; i++) { + /**/ if ((P2_EDBUF_MgrList[i].processID == + param.processID) + && (P2_EDBUF_MgrList[i].callerID == + param.callerID) + && (P2_EDBUF_MgrList[i].p2dupCQIdx == + param.p2dupCQIdx) + && (P2_EDBUF_MgrList[i].dequedNum < + P2_EDBUF_MgrList[i].frameNum)) { + idx = i; + break; + } + } + } + } + } + break; + case P2_EDBUF_RLIST_TAG: + if (P2_EDBUF_RList_FirstBufIdx <= P2_EDBUF_RList_LastBufIdx) { + for (i = P2_EDBUF_RList_FirstBufIdx; i <= P2_EDBUF_RList_LastBufIdx; i++) { + if ((P2_EDBUF_RingList[i].processID == param.processID) + && (P2_EDBUF_RingList[i].callerID == param.callerID)) { + idx = i; + break; + } + } + } else { + for (i = P2_EDBUF_RList_FirstBufIdx; i < _MAX_SUPPORT_P2_FRAME_NUM_; i++) { + if ((P2_EDBUF_RingList[i].processID == param.processID) + && (P2_EDBUF_RingList[i].callerID == param.callerID)) { + idx = i; + break; + } + } + if (idx != -1) { /*get in the first for loop */ + } else { + for (i = 0; i <= P2_EDBUF_RList_LastBufIdx; i++) { + if ((P2_EDBUF_RingList[i].processID == param.processID) + && (P2_EDBUF_RingList[i].callerID == param.callerID)) { + idx = i; + break; + } + } + } + } + break; + default: + break; + } + if (idx == -1) + LOG_ERR("Could not find match buffer tag(%d) pid/cid/p2dupCQidx(%d/0x%x/%d)", + ListTag, param.processID, param.callerID, param.p2dupCQIdx); + + return idx; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_ED_BufQue_CTRL_FUNC(ISP_ED_BUFQUE_STRUCT param) +{ + MINT32 ret = 0; + int i = 0; + int idx = -1, idx2 = -1; + MINT32 restTime = 0; + + switch (param.ctrl) { + case ISP_ED_BUFQUE_CTRL_ENQUE_FRAME: /* signal that a specific buffer is enqueued */ + /* [1] check the ring buffer list is full or not */ + spin_lock(&(SpinLockEDBufQueList)); + if (((P2_EDBUF_MList_LastBufIdx + 1) % _MAX_SUPPORT_P2_PACKAGE_NUM_) == + P2_EDBUF_MList_FirstBufIdx && (P2_EDBUF_MList_LastBufIdx != -1)) { + LOG_ERR("F/L(%d,%d),(%d_%d,%d), RF/C/L(%d,%d,%d),(%d,%d,%d)", + P2_EDBUF_MList_FirstBufIdx, P2_EDBUF_MList_LastBufIdx, param.frameNum, + P2_EDBUF_MgrList[P2_EDBUF_MList_FirstBufIdx].p2dupCQIdx, + P2_EDBUF_MgrList[P2_EDBUF_MList_LastBufIdx].p2dupCQIdx, + P2_EDBUF_RList_FirstBufIdx, P2_EDBUF_RList_CurBufIdx, + P2_EDBUF_RList_LastBufIdx, + P2_EDBUF_RingList[P2_EDBUF_RList_FirstBufIdx].bufSts, + P2_EDBUF_RingList[P2_EDBUF_RList_CurBufIdx].bufSts, + P2_EDBUF_RingList[P2_EDBUF_RList_LastBufIdx].bufSts); + spin_unlock(&(SpinLockEDBufQueList)); + LOG_ERR("p2 ring buffer list is full, enque Fail."); + ret = -EFAULT; + return ret; + } else { + if (P2_EDBUF_MList_LastBufIdx != -1) { + + IRQ_LOG_KEEPER(_CAMSV_D_IRQ, 0, _LOG_DBG, + "pD(%d_0x%x) MF/L(%d_%d,%d),(%d,%d), RF/C/L(%d,%d,%d),(%d,%d,%d),dCq(%d)/Bq(%d)\n", + param.processID, param.callerID, param.frameNum, + P2_EDBUF_MList_FirstBufIdx, P2_EDBUF_MList_LastBufIdx, + P2_EDBUF_MgrList[P2_EDBUF_MList_FirstBufIdx].p2dupCQIdx, + P2_EDBUF_MgrList[P2_EDBUF_MList_LastBufIdx].p2dupCQIdx, + P2_EDBUF_RList_FirstBufIdx, P2_EDBUF_RList_CurBufIdx, + P2_EDBUF_RList_LastBufIdx, + P2_EDBUF_RingList[P2_EDBUF_RList_FirstBufIdx].bufSts, + P2_EDBUF_RingList[P2_EDBUF_RList_CurBufIdx].bufSts, + P2_EDBUF_RingList[P2_EDBUF_RList_LastBufIdx].bufSts, + param.p2dupCQIdx, param.p2burstQIdx); + } + /* [2] add new element to the last of the list */ + if (P2_EDBUF_RList_FirstBufIdx == P2_EDBUF_RList_LastBufIdx + && P2_EDBUF_RingList[P2_EDBUF_RList_FirstBufIdx].bufSts == + ISP_ED_BUF_STATE_NONE) { + /* all buffer node is empty */ + P2_EDBUF_RList_LastBufIdx = + (P2_EDBUF_RList_LastBufIdx + 1) % _MAX_SUPPORT_P2_FRAME_NUM_; + P2_EDBUF_RList_FirstBufIdx = P2_EDBUF_RList_LastBufIdx; + P2_EDBUF_RList_CurBufIdx = P2_EDBUF_RList_LastBufIdx; + } else if (P2_EDBUF_RList_CurBufIdx == P2_EDBUF_RList_LastBufIdx + && P2_EDBUF_RingList[P2_EDBUF_RList_CurBufIdx].bufSts == + ISP_ED_BUF_STATE_NONE) { + /* first node is not empty, but current/last is empty */ + P2_EDBUF_RList_LastBufIdx = + (P2_EDBUF_RList_LastBufIdx + 1) % _MAX_SUPPORT_P2_FRAME_NUM_; + P2_EDBUF_RList_CurBufIdx = P2_EDBUF_RList_LastBufIdx; + } else { + P2_EDBUF_RList_LastBufIdx = + (P2_EDBUF_RList_LastBufIdx + 1) % _MAX_SUPPORT_P2_FRAME_NUM_; + } + P2_EDBUF_RingList[P2_EDBUF_RList_LastBufIdx].processID = param.processID; + P2_EDBUF_RingList[P2_EDBUF_RList_LastBufIdx].callerID = param.callerID; + P2_EDBUF_RingList[P2_EDBUF_RList_LastBufIdx].p2dupCQIdx = param.p2dupCQIdx; + P2_EDBUF_RingList[P2_EDBUF_RList_LastBufIdx].bufSts = + ISP_ED_BUF_STATE_ENQUE; + EDBufQueRemainNodeCnt++; + + /* [3] add new buffer package in manager list */ + if (param.p2burstQIdx == 0) { + if (P2_EDBUF_MList_FirstBufIdx == P2_EDBUF_MList_LastBufIdx + && P2_EDBUF_MgrList[P2_EDBUF_MList_FirstBufIdx].p2dupCQIdx == + -1) { + /* all managed buffer node is empty */ + P2_EDBUF_MList_LastBufIdx = + (P2_EDBUF_MList_LastBufIdx + + 1) % _MAX_SUPPORT_P2_PACKAGE_NUM_; + P2_EDBUF_MList_FirstBufIdx = P2_EDBUF_MList_LastBufIdx; + } else { + P2_EDBUF_MList_LastBufIdx = + (P2_EDBUF_MList_LastBufIdx + + 1) % _MAX_SUPPORT_P2_PACKAGE_NUM_; + } + P2_EDBUF_MgrList[P2_EDBUF_MList_LastBufIdx].processID = + param.processID; + P2_EDBUF_MgrList[P2_EDBUF_MList_LastBufIdx].callerID = + param.callerID; + P2_EDBUF_MgrList[P2_EDBUF_MList_LastBufIdx].p2dupCQIdx = + param.p2dupCQIdx; + P2_EDBUF_MgrList[P2_EDBUF_MList_LastBufIdx].frameNum = + param.frameNum; + P2_EDBUF_MgrList[P2_EDBUF_MList_LastBufIdx].dequedNum = 0; + } + } + /* [4]update global index */ + ISP_ED_BufQue_Update_GPtr(P2_EDBUF_RLIST_TAG); + spin_unlock(&(SpinLockEDBufQueList)); + IRQ_LOG_PRINTER(_CAMSV_D_IRQ, 0, _LOG_DBG); + /* [5] wake up thread that wait for deque */ + wake_up_interruptible_all((wait_queue_head_t *)&WaitQueueHead_EDBuf_WaitDeque); + break; + case ISP_ED_BUFQUE_CTRL_WAIT_DEQUE: + /* a dequeue thread is waiting to do dequeue */ + /* [1]traverse for finding the buffer which had not beed dequeued of the process */ + spin_lock(&(SpinLockEDBufQueList)); + if (P2_EDBUF_RList_FirstBufIdx <= P2_EDBUF_RList_LastBufIdx) { + for (i = P2_EDBUF_RList_FirstBufIdx; i <= P2_EDBUF_RList_LastBufIdx; i++) { + if ((P2_EDBUF_RingList[i].processID == param.processID) + && ((P2_EDBUF_RingList[i].bufSts == ISP_ED_BUF_STATE_ENQUE) + || (P2_EDBUF_RingList[i].bufSts == + ISP_ED_BUF_STATE_RUNNING))) { + idx = i; + break; + } + } + } else { + for (i = P2_EDBUF_RList_FirstBufIdx; i < _MAX_SUPPORT_P2_FRAME_NUM_; i++) { + if ((P2_EDBUF_RingList[i].processID == param.processID) + && ((P2_EDBUF_RingList[i].bufSts == ISP_ED_BUF_STATE_ENQUE) + || (P2_EDBUF_RingList[i].bufSts == + ISP_ED_BUF_STATE_RUNNING))) { + idx = i; + break; + } + } + if (idx != -1) { /*get in the first for loop */ + } else { + for (i = 0; i <= P2_EDBUF_RList_LastBufIdx; i++) { + if ((P2_EDBUF_RingList[i].processID == param.processID) + && + ((P2_EDBUF_RingList[i].bufSts == ISP_ED_BUF_STATE_ENQUE) + || (P2_EDBUF_RingList[i].bufSts == + ISP_ED_BUF_STATE_RUNNING))) { + idx = i; + break; + } + } + } + } + spin_unlock(&(SpinLockEDBufQueList)); + if (idx == -1) { + LOG_ERR("Do not find match buffer (pid/cid %d/0x%x) to deque!", + param.processID, param.callerID); + ret = -EFAULT; + return ret; + } else { + restTime = wait_event_interruptible_timeout(WaitQueueHead_EDBuf_WaitDeque, + ISP_GetEDBufQueWaitDequeState(idx), ISP_UsToJiffies(5000000)); /* 5s */ + if (restTime == 0) { + LOG_ERR("Wait Deque fail, idx(%d) pID(%d),cID(0x%x)", idx, + param.processID, param.callerID); + ret = -EFAULT; + } else { + /* LOG_INF("wakeup and goto deque,rTime(%d), pID(%d)",restTime,param.processID); */ + } + } + break; + case ISP_ED_BUFQUE_CTRL_DEQUE_SUCCESS: + /* signal that a buffer is dequeued(success) */ + case ISP_ED_BUFQUE_CTRL_DEQUE_FAIL: + /* signal that a buffer is dequeued(fail) */ + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) + LOG_DBG("dq cm(%d),pID(%d),cID(0x%x)\n", param.ctrl, param.processID, + param.callerID); + + spin_lock(&(SpinLockEDBufQueList)); + /* [1]update buffer status for the current buffer */ + /* ////////////////////////////////////////////////////////////////////// */ + /* Assume we have the buffer list in the following situation */ + /* ++++++ ++++++ */ + /* + vss + + prv + */ + /* ++++++ ++++++ */ + /* */ + /* if the vss deque is not done(not blocking deque), dequeThread in */ + /* userspace would change to deque prv buffer(block deque) immediately */ + /* to decrease ioctrl count. */ + /* -> vss buffer would be deque at next turn, so curBuf is still at vss buffer node */ + /* -> we should use param to find the current buffer index in Rlikst to */ + /* update the buffer status cuz deque success/fail may not be the first buffer in Rlist */ + /* ////////////////////////////////////////////////////////////////////// */ + idx2 = ISP_ED_BufQue_Get_FirstMatBuf(param, P2_EDBUF_RLIST_TAG, 1); + if (idx2 == -1) { + spin_unlock(&(SpinLockEDBufQueList)); + LOG_ERR("ERRRRRRRRRRR findmatch index fail"); + ret = -EFAULT; + return ret; + } + if (param.ctrl == ISP_ED_BUFQUE_CTRL_DEQUE_SUCCESS) + P2_EDBUF_RingList[idx2].bufSts = ISP_ED_BUF_STATE_DEQUE_SUCCESS; + else + P2_EDBUF_RingList[idx2].bufSts = ISP_ED_BUF_STATE_DEQUE_FAIL; + + /* [2]update dequeued num in managed buffer list */ + idx = ISP_ED_BufQue_Get_FirstMatBuf(param, P2_EDBUF_MLIST_TAG, 1); + if (idx == -1) { + spin_unlock(&(SpinLockEDBufQueList)); + LOG_ERR("ERRRRRRRRRRR findmatch index fail"); + ret = -EFAULT; + return ret; + } + P2_EDBUF_MgrList[idx].dequedNum++; + /* [3]update global pointer */ + ISP_ED_BufQue_Update_GPtr(P2_EDBUF_RLIST_TAG); + /* [4]erase node in ring buffer list */ + ISP_ED_BufQue_Erase(idx2, P2_EDBUF_RLIST_TAG); + spin_unlock(&(SpinLockEDBufQueList)); + /* [5]wake up thread user that wait for a specific buffer and the thread that wait for deque */ + wake_up_interruptible_all((wait_queue_head_t *)&WaitQueueHead_EDBuf_WaitFrame); + wake_up_interruptible_all((wait_queue_head_t *)&WaitQueueHead_EDBuf_WaitDeque); + break; + case ISP_ED_BUFQUE_CTRL_WAIT_FRAME: + /* wait for a specific buffer */ + spin_lock(&(SpinLockEDBufQueList)); + /* [1]find first match buffer */ + idx = ISP_ED_BufQue_Get_FirstMatBuf(param, P2_EDBUF_MLIST_TAG, 0); + if (idx == -1) { + spin_unlock(&(SpinLockEDBufQueList)); + LOG_ERR("could not find match buffer pID/cID (%d/0x%x)", param.processID, + param.callerID); + ret = -EFAULT; + return ret; + } + /* [2]check the buffer is dequeued or not */ + if (P2_EDBUF_MgrList[idx].dequedNum == P2_EDBUF_MgrList[idx].frameNum) { + ISP_ED_BufQue_Erase(idx, P2_EDBUF_MLIST_TAG); + spin_unlock(&(SpinLockEDBufQueList)); + ret = 0; + LOG_DBG("Frame is alreay dequeued, return user, pd(%d/0x%x),idx(%d)", + param.processID, param.callerID, idx); + return ret; + } else { + spin_unlock(&(SpinLockEDBufQueList)); + + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) + LOG_DBG("=pd(%d/0x%x_%d)wait(%d us)=\n", param.processID, + param.callerID, idx, param.timeoutUs); + + /* [3]if not, goto wait event and wait for a signal to check */ + restTime = wait_event_interruptible_timeout(WaitQueueHead_EDBuf_WaitFrame, + ISP_GetEDBufQueWaitFrameState + (idx), + ISP_UsToJiffies(param. + timeoutUs)); + if (restTime == 0) { + LOG_ERR + ("Dequeue Buffer fail, rT(%d),idx(%d) pID(%d),cID(0x%x),p2SupportBNum(%d)\n", + restTime, idx, param.processID, param.callerID, + P2_Support_BurstQNum); + ret = -EFAULT; + break; + } else { + spin_lock(&(SpinLockEDBufQueList)); + ISP_ED_BufQue_Erase(idx, P2_EDBUF_MLIST_TAG); + spin_unlock(&(SpinLockEDBufQueList)); + } + } + break; + case ISP_ED_BUFQUE_CTRL_WAKE_WAITFRAME: + /* wake all sleeped users to check buffer is dequeued or not */ + wake_up_interruptible_all((wait_queue_head_t *)&WaitQueueHead_EDBuf_WaitFrame); + break; + case ISP_ED_BUFQUE_CTRL_CLAER_ALL: + /* free all recored dequeued buffer */ + spin_lock(&(SpinLockEDBufQueList)); + for (i = 0; i < _MAX_SUPPORT_P2_FRAME_NUM_; i++) { + P2_EDBUF_RingList[i].processID = 0x0; + P2_EDBUF_RingList[i].callerID = 0x0; + P2_EDBUF_RingList[i].bufSts = ISP_ED_BUF_STATE_NONE; + } + P2_EDBUF_RList_FirstBufIdx = 0; + P2_EDBUF_RList_CurBufIdx = 0; + P2_EDBUF_RList_LastBufIdx = -1; + /* */ + for (i = 0; i < _MAX_SUPPORT_P2_PACKAGE_NUM_; i++) { + P2_EDBUF_MgrList[i].processID = 0x0; + P2_EDBUF_MgrList[i].callerID = 0x0; + P2_EDBUF_MgrList[i].p2dupCQIdx = -1; + P2_EDBUF_MgrList[i].frameNum = 0; + P2_EDBUF_MgrList[i].dequedNum = 0; + } + P2_EDBUF_MList_FirstBufIdx = 0; + P2_EDBUF_MList_LastBufIdx = -1; + spin_unlock(&(SpinLockEDBufQueList)); + break; + default: + LOG_ERR("do not support this ctrl cmd(%d)", param.ctrl); + break; + } + return ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_REGISTER_IRQ_USERKEY(char *userName) +{ + int key = -1; /* -1 means there is no any un-locked user key */ + int i = 0; + int length = 0; + char m_UserName[USERKEY_STR_LEN]; /* local veriable for saving Username from user space */ + MBOOL bCopyFromUser = MTRUE; + + if (NULL == userName) { + LOG_ERR(" [regUser] userName is NULL\n"); + } else { + /*get UserName from user space */ + length = strnlen_user(userName, USERKEY_STR_LEN); + if (length == 0) { + LOG_ERR(" [regUser] userName address is not valid\n"); + return key; + } + + if (length > USERKEY_STR_LEN) + length = USERKEY_STR_LEN; + + if (copy_from_user(m_UserName, (void *)(userName), length * sizeof(char)) != 0) + bCopyFromUser = MFALSE; + + if (MTRUE == bCopyFromUser) { + spin_lock((spinlock_t *)(&SpinLock_UserKey)); + /*check String length, add end */ + if (length == USERKEY_STR_LEN) { + /*string length too long */ + m_UserName[length - 1] = '\0'; + if (IspInfo.DebugMask & ISP_DBG_INT) + LOG_INF(" [regUser] userName(%s) is too long (>%d)\n", + m_UserName, USERKEY_STR_LEN); + } + + if (IspInfo.DebugMask & ISP_DBG_INT) + LOG_INF(" [regUser] UserName (%s)\n", m_UserName); + + /* 1. check the current users is full or not */ + if (FirstUnusedIrqUserKey >= IRQ_USER_NUM_MAX || FirstUnusedIrqUserKey < 0) { + key = -1; + } else { + /* 2. check the user had registered or not */ + for (i = 1; i < FirstUnusedIrqUserKey; i++) { /*index 0 is for all the users that do not register irq first */ + if (strcmp((const char *)IrqUserKey_UserInfo[i].userName, m_UserName) == + 0) { + key = IrqUserKey_UserInfo[i].userKey; + break; + } + } + + /* 3.return new userkey for user if the user had not registered before */ + if (key > 0) { + } else { + memset((void *)IrqUserKey_UserInfo[i].userName, 0, USERKEY_STR_LEN); + strncpy((char *)IrqUserKey_UserInfo[i].userName, m_UserName, USERKEY_STR_LEN-1); + IrqUserKey_UserInfo[i].userKey = FirstUnusedIrqUserKey; + key = FirstUnusedIrqUserKey; + FirstUnusedIrqUserKey++; + /* cam3 for flush */ + if (strcmp((const char *)IrqUserKey_UserInfo[i].userName, "VSIrq") == 0) + IrqFlush_v3[key] = + (ISP_IRQ_P1_STATUS_VS1_INT_ST | + ISP_IRQ_P1_STATUS_D_VS1_INT_ST); + if (strcmp((const char *)IrqUserKey_UserInfo[i].userName, "AFIrq") == 0) + IrqFlush_v3[key] = + (ISP_IRQ_P1_STATUS_AF_DON_ST | + ISP_IRQ_P1_STATUS_D_AF_DON_ST); + + if (strcmp((const char *)IrqUserKey_UserInfo[i].userName, "EIS") == 0) { + IrqFlush_v3[key] = + (ISP_IRQ_P1_STATUS_VS1_INT_ST | + ISP_IRQ_P1_STATUS_D_VS1_INT_ST | + ISP_IRQ_P1_STATUS_PASS1_DON_ST | + ISP_IRQ_P1_STATUS_D_PASS1_DON_ST); + } + if (strcmp((const char *)IrqUserKey_UserInfo[i].userName, "VHDR") == 0) { + IrqFlush_v3[key] = + (ISP_IRQ_P1_STATUS_VS1_INT_ST | + ISP_IRQ_P1_STATUS_D_VS1_INT_ST | + ISP_IRQ_P1_STATUS_PASS1_DON_ST | + ISP_IRQ_P1_STATUS_D_PASS1_DON_ST); + } + } + } + spin_unlock((spinlock_t *)(&SpinLock_UserKey)); + } else { + LOG_ERR(" [regUser] copy_from_user failed (%d)\n", i); + } + } + + LOG_INF("User(%s)key(%d)\n", userName, key); + return key; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_MARK_IRQ(ISP_WAIT_IRQ_STRUCT irqinfo) +{ + eISPIrq eIrq = _IRQ; + int idx; + unsigned long long sec = 0; + unsigned long usec = 0; + unsigned long flags; /* old: MUINT32 flags;*//* FIX to avoid build warning */ + + switch (irqinfo.UserInfo.Type) { + case ISP_IRQ_TYPE_INT_CAMSV: + eIrq = _CAMSV_IRQ; + break; + case ISP_IRQ_TYPE_INT_CAMSV2: + eIrq = _CAMSV_D_IRQ; + break; + case ISP_IRQ_TYPE_INT_P1_ST_D: + case ISP_IRQ_TYPE_INT_P1_ST2_D: + default: + eIrq = _IRQ; + break; + } + + /* 1. enable marked flag */ + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + IspInfo.IrqInfo.MarkedFlag[irqinfo.UserInfo.UserKey][irqinfo.UserInfo.Type] |= + irqinfo.UserInfo.Status; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + + /* 2. record mark time */ + idx = my_get_pow_idx(irqinfo.UserInfo.Status); + + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + IspInfo.IrqInfo.MarkedTime_usec[irqinfo.UserInfo.UserKey][irqinfo.UserInfo.Type][idx] = + (unsigned int)usec; + IspInfo.IrqInfo.MarkedTime_sec[irqinfo.UserInfo.UserKey][irqinfo.UserInfo.Type][idx] = + (unsigned int)sec; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + + /* 3. clear passed by signal count */ + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + IspInfo.IrqInfo.PassedBySigCnt[irqinfo.UserInfo.UserKey][irqinfo.UserInfo.Type][idx] = 0; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + + LOG_VRB("[MARK] key/type/sts/idx (%d/%d/0x%x/%d), t(%d/%d)\n", + irqinfo.UserInfo.UserKey, irqinfo.UserInfo.Type, irqinfo.UserInfo.Status, idx, + (int)sec, (int)usec); + + return 0; +} + + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_GET_MARKtoQEURY_TIME(ISP_WAIT_IRQ_STRUCT *irqinfo) +{ + MINT32 Ret = 0; + unsigned long flags; /* old: MUINT32 flags;*//* FIX to avoid build warning */ +/* struct timeval time_getrequest;*/ + struct timeval time_ready2return; + + unsigned long long sec = 0; + unsigned long usec = 0; + int idx; + + eISPIrq eIrq = _IRQ; + +/* do_gettimeofday(&time_ready2return);*/ + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + time_ready2return.tv_usec = usec; + time_ready2return.tv_sec = sec; + + idx = my_get_pow_idx(irqinfo->UserInfo.Status); + + switch (irqinfo->UserInfo.Type) { + case ISP_IRQ_TYPE_INT_CAMSV: + eIrq = _CAMSV_IRQ; + break; + case ISP_IRQ_TYPE_INT_CAMSV2: + eIrq = _CAMSV_D_IRQ; + break; + case ISP_IRQ_TYPE_INT_P1_ST_D: + case ISP_IRQ_TYPE_INT_P1_ST2_D: + default: + eIrq = _IRQ; + break; + } + + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + if (irqinfo->UserInfo.Status & IspInfo.IrqInfo. + MarkedFlag[irqinfo->UserInfo.UserKey][irqinfo->UserInfo.Type]) { + /* */ + irqinfo->TimeInfo.passedbySigcnt = + IspInfo.IrqInfo.PassedBySigCnt[irqinfo->UserInfo.UserKey][irqinfo->UserInfo. + Type][idx]; + /* */ + irqinfo->TimeInfo.tMark2WaitSig_usec = + (time_ready2return.tv_usec - + IspInfo.IrqInfo.MarkedTime_usec[irqinfo->UserInfo.UserKey][irqinfo->UserInfo. + Type][idx]); + irqinfo->TimeInfo.tMark2WaitSig_sec = + (time_ready2return.tv_sec - + IspInfo.IrqInfo.MarkedTime_sec[irqinfo->UserInfo.UserKey][irqinfo->UserInfo. + Type][idx]); + if ((int)(irqinfo->TimeInfo.tMark2WaitSig_usec) < 0) { + irqinfo->TimeInfo.tMark2WaitSig_sec = + irqinfo->TimeInfo.tMark2WaitSig_sec - 1; + + if ((int)(irqinfo->TimeInfo.tMark2WaitSig_sec) < 0) + irqinfo->TimeInfo.tMark2WaitSig_sec = 0; + + irqinfo->TimeInfo.tMark2WaitSig_usec = + 1 * 1000000 + irqinfo->TimeInfo.tMark2WaitSig_usec; + } + /* */ + if (irqinfo->TimeInfo.passedbySigcnt > 0) { + irqinfo->TimeInfo.tLastSig2GetSig_usec = + (time_ready2return.tv_usec - + IspInfo.IrqInfo.LastestSigTime_usec[irqinfo->UserInfo.Type][idx]); + irqinfo->TimeInfo.tLastSig2GetSig_sec = + (time_ready2return.tv_sec - + IspInfo.IrqInfo.LastestSigTime_sec[irqinfo->UserInfo.Type][idx]); + if ((int)(irqinfo->TimeInfo.tLastSig2GetSig_usec) < 0) { + irqinfo->TimeInfo.tLastSig2GetSig_sec = + irqinfo->TimeInfo.tLastSig2GetSig_sec - 1; + + if ((int)(irqinfo->TimeInfo.tLastSig2GetSig_sec) < 0) + irqinfo->TimeInfo.tLastSig2GetSig_sec = 0; + + irqinfo->TimeInfo.tLastSig2GetSig_usec = + 1 * 1000000 + irqinfo->TimeInfo.tLastSig2GetSig_usec; + } + + } else { + irqinfo->TimeInfo.tLastSig2GetSig_usec = 0; + irqinfo->TimeInfo.tLastSig2GetSig_sec = 0; + } + } else { + LOG_WRN("plz mark irq first, userKey/Type/Status (%d/%d/0x%x)", + irqinfo->UserInfo.UserKey, irqinfo->UserInfo.Type, + irqinfo->UserInfo.Status); + Ret = -EFAULT; + } + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + LOG_VRB + (" [ISP_GET_MARKtoQEURY_TIME] user/type/idx(%d/%d/%d),mark sec/usec (%d/%d), irq sec/usec (%d/%d),query sec/usec(%d/%d),sig(%d)\n", + irqinfo->UserInfo.UserKey, irqinfo->UserInfo.Type, idx, + IspInfo.IrqInfo.MarkedTime_sec[irqinfo->UserInfo.UserKey][irqinfo->UserInfo. + Type][idx], + IspInfo.IrqInfo.MarkedTime_usec[irqinfo->UserInfo.UserKey][irqinfo->UserInfo. + Type][idx], + IspInfo.IrqInfo.LastestSigTime_sec[irqinfo->UserInfo.Type][idx], + IspInfo.IrqInfo.LastestSigTime_usec[irqinfo->UserInfo.Type][idx], + (int)time_ready2return.tv_sec, (int)time_ready2return.tv_usec, + IspInfo.IrqInfo.PassedBySigCnt[irqinfo->UserInfo.UserKey][irqinfo->UserInfo. + Type][idx]); + return Ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_FLUSH_IRQ(ISP_WAIT_IRQ_STRUCT irqinfo) +{ + eISPIrq eIrq = _IRQ; + unsigned long flags; /* old: MUINT32 flags;*//* FIX to avoid build warning */ + + switch (irqinfo.Type) { + case ISP_IRQ_TYPE_INT_CAMSV: + eIrq = _CAMSV_IRQ; + break; + case ISP_IRQ_TYPE_INT_CAMSV2: + eIrq = _CAMSV_D_IRQ; + break; + case ISP_IRQ_TYPE_INT_P1_ST_D: + case ISP_IRQ_TYPE_INT_P1_ST2_D: + default: + eIrq = _IRQ; + break; + } + + + /* 1. enable signal */ + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + IspInfo.IrqInfo.Status[irqinfo.UserNumber][irqinfo.Type] |= irqinfo.Status; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + + /* 2. force to wake up the user that are waiting for that signal */ + wake_up_interruptible_all((wait_queue_head_t *)&IspInfo.WaitQueueHead); + + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_FLUSH_IRQ_V3(ISP_WAIT_IRQ_STRUCT irqinfo) +{ + eISPIrq eIrq = _IRQ; + unsigned long flags; /* old: MUINT32 flags;*//* FIX to avoid build warning */ + + switch (irqinfo.UserInfo.Type) { + case ISP_IRQ_TYPE_INT_CAMSV: + eIrq = _CAMSV_IRQ; + break; + case ISP_IRQ_TYPE_INT_CAMSV2: + eIrq = _CAMSV_D_IRQ; + break; + case ISP_IRQ_TYPE_INT_P1_ST_D: + case ISP_IRQ_TYPE_INT_P1_ST2_D: + default: + eIrq = _IRQ; + break; + } + + /* 1. enable signal */ + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + IspInfo.IrqInfo.Status[irqinfo.UserInfo.UserKey][irqinfo.UserInfo.Type] |= + irqinfo.UserInfo.Status; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + + /* 2. force to wake up the user that are waiting for that signal */ + wake_up_interruptible_all((wait_queue_head_t *)&IspInfo.WaitQueueHead); + + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_WaitIrq(ISP_WAIT_IRQ_STRUCT *WaitIrq) +{ + MINT32 Ret = 0, Timeout = WaitIrq->Timeout; +/* MUINT32 i;*/ + unsigned long flags; /* old: MUINT32 flags;*//* FIX to avoid build warning */ + eISPIrq eIrq = _IRQ; +/* int cnt = 0;*/ + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT) { + if (WaitIrq-> + Status & (ISP_IRQ_P1_STATUS_SOF1_INT_ST | ISP_IRQ_P1_STATUS_PASS1_DON_ST | + ISP_IRQ_P1_STATUS_D_SOF1_INT_ST | ISP_IRQ_P1_STATUS_D_PASS1_DON_ST)) { + LOG_DBG + ("+WaitIrq Clear(%d), Type(%d), Status(0x%08X), Timeout(%d),user(%d)\n", + WaitIrq->Clear, WaitIrq->Type, WaitIrq->Status, WaitIrq->Timeout, + WaitIrq->UserNumber); + } + } + /* */ + + switch (WaitIrq->Type) { + case ISP_IRQ_TYPE_INT_CAMSV: + eIrq = _CAMSV_IRQ; + break; + case ISP_IRQ_TYPE_INT_CAMSV2: + eIrq = _CAMSV_D_IRQ; + break; + case ISP_IRQ_TYPE_INT_P1_ST_D: + case ISP_IRQ_TYPE_INT_P1_ST2_D: + default: + eIrq = _IRQ; + break; + } + + if (WaitIrq->Clear == ISP_IRQ_CLEAR_WAIT) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + if (IspInfo.IrqInfo.Status[WaitIrq->UserNumber][WaitIrq->Type] & WaitIrq->Status) { + /* LOG_DBG("WARNING: Clear(%d), Type(%d): IrqStatus(0x%08X) has been cleared", + WaitIrq->Clear,WaitIrq->Type,IspInfo.IrqInfo.Status[WaitIrq->Type] & WaitIrq->Status); */ + IspInfo.IrqInfo.Status[WaitIrq->UserNumber][WaitIrq->Type] &= + (~WaitIrq->Status); + } + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + } else if (WaitIrq->Clear == ISP_IRQ_CLEAR_ALL) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* LOG_DBG("WARNING: Clear(%d), Type(%d): IrqStatus(0x%08X) has been cleared", + WaitIrq->Clear,WaitIrq->Type,IspInfo.IrqInfo.Status[WaitIrq->Type]); */ + IspInfo.IrqInfo.Status[WaitIrq->UserNumber][WaitIrq->Type] = 0; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + } else if (WaitIrq->Clear == ISP_IRQ_CLEAR_STATUS) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* LOG_DBG("WARNING: Clear(%d), Type(%d): IrqStatus(0x%08X) has been cleared", + WaitIrq->Clear,WaitIrq->Type,IspInfo.IrqInfo.Status[WaitIrq->Type]); */ + IspInfo.IrqInfo.Status[WaitIrq->UserNumber][WaitIrq->Type] &= (~WaitIrq->Status); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + return Ret; + } + /* */ + Timeout = wait_event_interruptible_timeout(IspInfo.WaitQueueHead, + ISP_GetIRQState(eIrq, WaitIrq->Type, + WaitIrq->UserNumber, + WaitIrq->Status), + ISP_MsToJiffies(WaitIrq->Timeout)); + /* check if user is interrupted by system signal */ + if ((Timeout != 0) + && (!ISP_GetIRQState(eIrq, WaitIrq->Type, WaitIrq->UserNumber, WaitIrq->Status))) { + LOG_WRN + ("interrupted by system signal,return value(%d),irq Type/User/Sts(0x%x/%d/0x%x)", + Timeout, WaitIrq->Type, WaitIrq->UserNumber, WaitIrq->Status); + Ret = -ERESTARTSYS; /* actually it should be -ERESTARTSYS */ + goto EXIT; + } + + /* timeout */ + if (Timeout == 0) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + LOG_ERR + ("v1 ERR WaitIrq Timeout Clear(%d), Type(%d), IrqStatus(0x%08X), WaitStatus(0x%08X), Timeout(%d),user(%d)", + WaitIrq->Clear, WaitIrq->Type, + IspInfo.IrqInfo.Status[WaitIrq->UserNumber][WaitIrq->Type], + WaitIrq->Status, WaitIrq->Timeout, WaitIrq->UserNumber); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + + if (WaitIrq->bDumpReg || (WaitIrq->UserNumber == ISP_IRQ_USER_3A) + || (WaitIrq->UserNumber == ISP_IRQ_USER_MW)) + ISP_DumpReg(); + + Ret = -EFAULT; + goto EXIT; + } + + + /* */ + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT) { + /* + for (i = 0; i < ISP_IRQ_TYPE_AMOUNT; i++) { + LOG_DBG("Type(%d), IrqStatus(0x%08X)",i,IspInfo.IrqInfo.Status[i]); + } + */ + } + /* */ + /* eis meta */ + if (WaitIrq->Type < ISP_IRQ_TYPE_INT_STATUSX + && WaitIrq->SpecUser == ISP_IRQ_WAITIRQ_SPEUSER_EIS) { + if (WaitIrq->Type == ISP_IRQ_TYPE_INT_P1_ST) { + if (gEismetaWIdx == 0) { + if (gEismetaInSOF == 0) + gEismetaRIdx = (EISMETA_RINGSIZE - 1); + else + gEismetaRIdx = (EISMETA_RINGSIZE - 2); + + } else if (gEismetaWIdx == 1) { + if (gEismetaInSOF == 0) + gEismetaRIdx = 0; + else + gEismetaRIdx = (EISMETA_RINGSIZE - 1); + + } else { + gEismetaRIdx = (gEismetaWIdx - gEismetaInSOF - 1); + } + + if ((gEismetaRIdx < 0) || (gEismetaRIdx >= EISMETA_RINGSIZE)) + /* BUG_ON(1); */ + gEismetaRIdx = 0; + /* TBD WARNING */ + + /* eis meta */ + WaitIrq->EisMeta.tLastSOF2P1done_sec = + IspInfo.IrqInfo.Eismeta[WaitIrq->Type][gEismetaRIdx]. + tLastSOF2P1done_sec; + WaitIrq->EisMeta.tLastSOF2P1done_usec = + IspInfo.IrqInfo.Eismeta[WaitIrq->Type][gEismetaRIdx]. + tLastSOF2P1done_usec; + } else if (WaitIrq->Type == ISP_IRQ_TYPE_INT_P1_ST_D) { + if (gEismetaWIdx_D == 0) { + if (gEismetaInSOF_D == 0) + gEismetaRIdx_D = (EISMETA_RINGSIZE - 1); + else + gEismetaRIdx_D = (EISMETA_RINGSIZE - 2); + + } else if (gEismetaWIdx_D == 1) { + if (gEismetaInSOF_D == 0) + gEismetaRIdx_D = 0; + else + gEismetaRIdx_D = (EISMETA_RINGSIZE - 1); + + } else { + gEismetaRIdx_D = (gEismetaWIdx_D - gEismetaInSOF_D - 1); + } + + if ((gEismetaRIdx_D < 0) || (gEismetaRIdx_D >= EISMETA_RINGSIZE)) { + /* BUG_ON(1); */ + gEismetaRIdx_D = 0; + /* TBD WARNING */ + } + /* eis meta */ + WaitIrq->EisMeta.tLastSOF2P1done_sec = + IspInfo.IrqInfo.Eismeta[WaitIrq->Type][gEismetaRIdx_D]. + tLastSOF2P1done_sec; + WaitIrq->EisMeta.tLastSOF2P1done_usec = + IspInfo.IrqInfo.Eismeta[WaitIrq->Type][gEismetaRIdx_D]. + tLastSOF2P1done_usec; + } + } + /* */ + IspInfo.IrqInfo.Status[WaitIrq->UserNumber][WaitIrq->Type] &= (~WaitIrq->Status); /* clear the status if someone get the irq */ + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* */ + /* check CQ status, when pass2, pass2b, pass2c done */ + if (WaitIrq->Type == ISP_IRQ_TYPE_INT_P2_ST) { + MUINT32 CQ_status; + + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x6000); + CQ_status = ISP_RD32(ISP_IMGSYS_BASE + 0x4164); + switch (WaitIrq->Status) { + case ISP_IRQ_P2_STATUS_PASS2A_DON_ST: + if ((CQ_status & 0x0000000F) != 0x001) { + LOG_ERR("CQ1 not idle dbg(0x%08x 0x%08x)", + ISP_RD32(ISP_IMGSYS_BASE + 0x4160), CQ_status); + } + break; + case ISP_IRQ_P2_STATUS_PASS2B_DON_ST: + if ((CQ_status & 0x000000F0) != 0x010) { + LOG_ERR("CQ2 not idle dbg(0x%08x 0x%08x)", + ISP_RD32(ISP_IMGSYS_BASE + 0x4160), CQ_status); + } + break; + case ISP_IRQ_P2_STATUS_PASS2C_DON_ST: + if ((CQ_status & 0x00000F00) != 0x100) { + LOG_ERR("CQ3 not idle dbg(0x%08x 0x%08x)", + ISP_RD32(ISP_IMGSYS_BASE + 0x4160), CQ_status); + } + break; + default: + break; + } + } + +EXIT: + return Ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_WaitIrq_v3(ISP_WAIT_IRQ_STRUCT *WaitIrq) +{ + MINT32 Ret = 0, Timeout = WaitIrq->Timeout; +/* MUINT32 i;*/ + unsigned long flags; /* old: MUINT32 flags;*//* FIX to avoid build warning */ + eISPIrq eIrq = _IRQ; +/* int cnt = 0;*/ + int idx = my_get_pow_idx(WaitIrq->UserInfo.Status); + struct timeval time_getrequest; + struct timeval time_ready2return; + bool freeze_passbysigcnt = false; + unsigned long long sec = 0; + unsigned long usec = 0; + + + /* do_gettimeofday(&time_getrequest); */ + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + time_getrequest.tv_usec = usec; + time_getrequest.tv_sec = sec; + + /* */ + if (IspInfo.DebugMask & ISP_DBG_INT) { + if (WaitIrq->UserInfo. + Status & (ISP_IRQ_P1_STATUS_SOF1_INT_ST | ISP_IRQ_P1_STATUS_PASS1_DON_ST | + ISP_IRQ_P1_STATUS_D_SOF1_INT_ST | ISP_IRQ_P1_STATUS_D_PASS1_DON_ST)) { + if (WaitIrq->UserInfo.UserKey > 0) { + LOG_DBG + ("+WaitIrq Clear(%d), Type(%d), Status(0x%08X), Timeout(%d/%d),user(%d)\n", + WaitIrq->Clear, WaitIrq->UserInfo.Type, + WaitIrq->UserInfo.Status, Timeout, WaitIrq->Timeout, + WaitIrq->UserInfo.UserKey); + } + } + } + /* */ + + switch (WaitIrq->UserInfo.Type) { + case ISP_IRQ_TYPE_INT_CAMSV: + eIrq = _CAMSV_IRQ; + break; + case ISP_IRQ_TYPE_INT_CAMSV2: + eIrq = _CAMSV_D_IRQ; + break; + case ISP_IRQ_TYPE_INT_P1_ST_D: + case ISP_IRQ_TYPE_INT_P1_ST2_D: + default: + eIrq = _IRQ; + break; + } + /* 1. wait type update */ + if (WaitIrq->Clear == ISP_IRQ_CLEAR_STATUS) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* LOG_DBG("WARNING: Clear(%d), Type(%d): IrqStatus(0x%08X) has been cleared",WaitIrq->Clear,WaitIrq->UserInfo.Type,IspInfo.IrqInfo.Status[WaitIrq->UserInfo.Type]); */ + IspInfo.IrqInfo.Status[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo.Type] &= + (~WaitIrq->UserInfo.Status); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + return Ret; + } else { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + if (WaitIrq->UserInfo.Status & IspInfo.IrqInfo. + MarkedFlag[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo.Type]) { + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* force to be non_clear wait if marked before, and check the request wait timing */ + /* if the entry time of wait request after mark is before signal occuring, we freese the counting for passby signal */ + + /* */ + /* v : kernel receive mark request */ + /* o : kernel receive wait request */ + /* ¡ô: return to user */ + /* */ + /* case: freeze is true, and passby signal count = 0 */ + /* */ + /* | | */ + /* | (wait) | */ + /* | v-------------o++++++ |¡ô */ + /* | | */ + /* Sig Sig */ + /* */ + /* case: freeze is false, and passby signal count = 1 */ + /* */ + /* | | */ + /* | | */ + /* | v---------------------- |-o ¡ô(return) */ + /* | | */ + /* Sig Sig */ + /* */ + + freeze_passbysigcnt = + !(ISP_GetIRQState + (eIrq, WaitIrq->UserInfo.Type, WaitIrq->UserInfo.UserKey, + WaitIrq->UserInfo.Status)); + } else { + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + + if (WaitIrq->Clear == ISP_IRQ_CLEAR_WAIT) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + if (IspInfo.IrqInfo. + Status[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo. + Type] & WaitIrq->UserInfo. + Status) { + /* LOG_DBG("WARNING: Clear(%d), Type(%d): + IrqStatus(0x%08X) has been cleared", + WaitIrq->Clear,WaitIrq->UserInfo.Type, + IspInfo_FrmB.IrqInfo.Status[WaitIrq->UserInfo.Type] & WaitIrq->Status); */ + IspInfo.IrqInfo.Status[WaitIrq->UserInfo.UserKey][WaitIrq-> + UserInfo. + Type] &= + (~WaitIrq->UserInfo.Status); + } + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + } else if (WaitIrq->Clear == ISP_IRQ_CLEAR_ALL) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* LOG_DBG("WARNING: Clear(%d), Type(%d): + IrqStatus(0x%08X) has been cleared", + WaitIrq->Clear,WaitIrq->UserInfo.Type, + IspInfo_FrmB.IrqInfo.Status[WaitIrq->UserInfo.Type]); */ + IspInfo.IrqInfo.Status[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo. + Type] = 0; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + } + } + } + /* 2. start to wait signal */ + Timeout = wait_event_interruptible_timeout(IspInfo.WaitQueueHead, + ISP_GetIRQState(eIrq, WaitIrq->UserInfo.Type, + WaitIrq->UserInfo.UserKey, + WaitIrq->UserInfo.Status), + ISP_MsToJiffies(WaitIrq->Timeout)); + /* check if user is interrupted by system signal */ + if ((Timeout != 0) + && + (!ISP_GetIRQState + (eIrq, WaitIrq->UserInfo.Type, WaitIrq->UserInfo.UserKey, WaitIrq->UserInfo.Status))) { + LOG_WRN + ("interrupted by system signal,return value(%d),irq Type/User/Sts(0x%x/%d/0x%x)", + Timeout, WaitIrq->UserInfo.Type, WaitIrq->UserInfo.UserKey, + WaitIrq->UserInfo.Status); + Ret = -ERESTARTSYS; /* actually it should be -ERESTARTSYS */ + goto EXIT; + } + /* timeout */ + if (Timeout == 0) { + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + LOG_ERR( + "v3 ERRRR WaitIrq Timeout(%d)Clear(%d)Type(%d)IrqSts(0x%08X)WaitSts(0x%08X)UserKey(%d)\n", + WaitIrq->Timeout, WaitIrq->Clear, WaitIrq->UserInfo.Type, + IspInfo.IrqInfo.Status[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo.Type], + WaitIrq->UserInfo.Status, WaitIrq->UserInfo.UserKey); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* TODO: AF */ + if (WaitIrq->bDumpReg + || (strcmp((const char *)IrqUserKey_UserInfo[WaitIrq->UserInfo.UserKey].userName, "HwIRQ3A") + == 0)) + ISP_DumpReg(); + + Ret = -EFAULT; + goto EXIT; + } + + /* 3. get interrupt and update time related information that would be return to user */ + /* do_gettimeofday(&time_ready2return); */ + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + time_ready2return.tv_usec = usec; + time_ready2return.tv_sec = sec; + + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + /* eis meta */ + if (WaitIrq->UserInfo.Type < ISP_IRQ_TYPE_INT_STATUSX + && WaitIrq->SpecUser == ISP_IRQ_WAITIRQ_SPEUSER_EIS) { + if (WaitIrq->UserInfo.Type == ISP_IRQ_TYPE_INT_P1_ST) { + if (gEismetaWIdx == 0) { + if (gEismetaInSOF == 0) + gEismetaRIdx = (EISMETA_RINGSIZE - 1); + else + gEismetaRIdx = (EISMETA_RINGSIZE - 2); + + } else if (gEismetaWIdx == 1) { + if (gEismetaInSOF == 0) + gEismetaRIdx = 0; + else + gEismetaRIdx = (EISMETA_RINGSIZE - 1); + + } else { + gEismetaRIdx = (gEismetaWIdx - gEismetaInSOF - 1); + } + + if ((gEismetaRIdx < 0) || (gEismetaRIdx >= EISMETA_RINGSIZE)) { + /* BUG_ON(1); */ + gEismetaRIdx = 0; + /* TBD WARNING */ + } + /* eis meta */ + WaitIrq->EisMeta.tLastSOF2P1done_sec = + IspInfo.IrqInfo.Eismeta[WaitIrq->UserInfo.Type][gEismetaRIdx]. + tLastSOF2P1done_sec; + WaitIrq->EisMeta.tLastSOF2P1done_usec = + IspInfo.IrqInfo.Eismeta[WaitIrq->UserInfo.Type][gEismetaRIdx]. + tLastSOF2P1done_usec; + } else if (WaitIrq->UserInfo.Type == ISP_IRQ_TYPE_INT_P1_ST_D) { + if (gEismetaWIdx_D == 0) { + if (gEismetaInSOF_D == 0) + gEismetaRIdx_D = (EISMETA_RINGSIZE - 1); + else + gEismetaRIdx_D = (EISMETA_RINGSIZE - 2); + + } else if (gEismetaWIdx_D == 1) { + if (gEismetaInSOF_D == 0) + gEismetaRIdx_D = 0; + else + gEismetaRIdx_D = (EISMETA_RINGSIZE - 1); + + } else { + gEismetaRIdx_D = (gEismetaWIdx_D - gEismetaInSOF_D - 1); + } + + if ((gEismetaRIdx_D < 0) || (gEismetaRIdx_D >= EISMETA_RINGSIZE)) { + /* BUG_ON(1); */ + gEismetaRIdx_D = 0; + /* TBD WARNING */ + } + /* eis meta */ + WaitIrq->EisMeta.tLastSOF2P1done_sec = + IspInfo.IrqInfo.Eismeta[WaitIrq->UserInfo.Type][gEismetaRIdx_D]. + tLastSOF2P1done_sec; + WaitIrq->EisMeta.tLastSOF2P1done_usec = + IspInfo.IrqInfo.Eismeta[WaitIrq->UserInfo.Type][gEismetaRIdx_D]. + tLastSOF2P1done_usec; + } + LOG_DBG(" [WAITIRQv3](%d) EisMeta.tLastSOF2P1done_sec(%d)\n", + WaitIrq->UserInfo.Type, WaitIrq->EisMeta.tLastSOF2P1done_sec); + } + /* time period for 3A */ + if (WaitIrq->UserInfo.Status & IspInfo.IrqInfo. + MarkedFlag[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo.Type]) { + WaitIrq->TimeInfo.tMark2WaitSig_usec = + (time_getrequest.tv_usec - + IspInfo.IrqInfo.MarkedTime_usec[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo. + Type][idx]); + WaitIrq->TimeInfo.tMark2WaitSig_sec = + (time_getrequest.tv_sec - + IspInfo.IrqInfo.MarkedTime_sec[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo. + Type][idx]); + if ((int)(WaitIrq->TimeInfo.tMark2WaitSig_usec) < 0) { + WaitIrq->TimeInfo.tMark2WaitSig_sec = + WaitIrq->TimeInfo.tMark2WaitSig_sec - 1; + + if ((int)(WaitIrq->TimeInfo.tMark2WaitSig_sec) < 0) + WaitIrq->TimeInfo.tMark2WaitSig_sec = 0; + + WaitIrq->TimeInfo.tMark2WaitSig_usec = + 1 * 1000000 + WaitIrq->TimeInfo.tMark2WaitSig_usec; + } + /* */ + WaitIrq->TimeInfo.tLastSig2GetSig_usec = + (time_ready2return.tv_usec - + IspInfo.IrqInfo.LastestSigTime_usec[WaitIrq->UserInfo.Type][idx]); + WaitIrq->TimeInfo.tLastSig2GetSig_sec = + (time_ready2return.tv_sec - + IspInfo.IrqInfo.LastestSigTime_sec[WaitIrq->UserInfo.Type][idx]); + if ((int)(WaitIrq->TimeInfo.tLastSig2GetSig_usec) < 0) { + WaitIrq->TimeInfo.tLastSig2GetSig_sec = + WaitIrq->TimeInfo.tLastSig2GetSig_sec - 1; + + if ((int)(WaitIrq->TimeInfo.tLastSig2GetSig_sec) < 0) + WaitIrq->TimeInfo.tLastSig2GetSig_sec = 0; + + WaitIrq->TimeInfo.tLastSig2GetSig_usec = + 1 * 1000000 + WaitIrq->TimeInfo.tLastSig2GetSig_usec; + } + /* */ + if (freeze_passbysigcnt) + WaitIrq->TimeInfo.passedbySigcnt = + IspInfo.IrqInfo.PassedBySigCnt[WaitIrq->UserInfo.UserKey][WaitIrq-> + UserInfo. + Type][idx] - + 1; + else + WaitIrq->TimeInfo.passedbySigcnt = + IspInfo.IrqInfo.PassedBySigCnt[WaitIrq->UserInfo.UserKey][WaitIrq-> + UserInfo. + Type][idx]; + + } + IspInfo.IrqInfo.Status[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo.Type] &= + (~WaitIrq->UserInfo.Status); + /* clear the status if someone get the irq */ + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + if (WaitIrq->UserInfo.UserKey > 0) { + LOG_DBG + (" [WAITIRQv3]user(%d) mark sec/usec (%d/%d), last irq sec/usec (%d/%d),enterwait(%d/%d),getIRQ(%d/%d)\n", + WaitIrq->UserInfo.UserKey, + IspInfo.IrqInfo.MarkedTime_sec[WaitIrq->UserInfo.UserKey][WaitIrq-> + UserInfo. + Type][idx], + IspInfo.IrqInfo.MarkedTime_usec[WaitIrq->UserInfo.UserKey][WaitIrq-> + UserInfo. + Type][idx], + IspInfo.IrqInfo.LastestSigTime_sec[WaitIrq->UserInfo.Type][idx], + IspInfo.IrqInfo.LastestSigTime_usec[WaitIrq->UserInfo.Type][idx], + (int)(time_getrequest.tv_sec), (int)(time_getrequest.tv_usec), + (int)(time_ready2return.tv_sec), (int)(time_ready2return.tv_usec)); + LOG_DBG + (" [WAITIRQv3]user(%d) sigNum(%d/%d), mark sec/usec (%d/%d), irq sec/usec (%d/%d),user(0x%x)\n", + WaitIrq->UserInfo.UserKey, + IspInfo.IrqInfo.PassedBySigCnt[WaitIrq->UserInfo.UserKey][WaitIrq-> + UserInfo. + Type][idx], + WaitIrq->TimeInfo.passedbySigcnt, WaitIrq->TimeInfo.tMark2WaitSig_sec, + WaitIrq->TimeInfo.tMark2WaitSig_usec, + WaitIrq->TimeInfo.tLastSig2GetSig_sec, + WaitIrq->TimeInfo.tLastSig2GetSig_usec, WaitIrq->UserInfo.UserKey); + } + /* */ + /* check CQ status, when pass2, pass2b, pass2c done */ + if (WaitIrq->UserInfo.Type == ISP_IRQ_TYPE_INT_P2_ST) { + MUINT32 CQ_status; + + ISP_WR32(ISP_IMGSYS_BASE + 0x4160, 0x6000); + CQ_status = ISP_RD32(ISP_IMGSYS_BASE + 0x4164); + + switch (WaitIrq->UserInfo.Status) { + case ISP_IRQ_P2_STATUS_PASS2A_DON_ST: + if ((CQ_status & 0x0000000F) != 0x001) { + LOG_ERR("CQ1 not idle dbg(0x%08x 0x%08x)", + ISP_RD32(ISP_IMGSYS_BASE + 0x4160), CQ_status); + } + break; + case ISP_IRQ_P2_STATUS_PASS2B_DON_ST: + if ((CQ_status & 0x000000F0) != 0x010) { + LOG_ERR("CQ2 not idle dbg(0x%08x 0x%08x)", + ISP_RD32(ISP_IMGSYS_BASE + 0x4160), CQ_status); + } + break; + case ISP_IRQ_P2_STATUS_PASS2C_DON_ST: + if ((CQ_status & 0x00000F00) != 0x100) { + LOG_ERR("CQ3 not idle dbg(0x%08x 0x%08x)", + ISP_RD32(ISP_IMGSYS_BASE + 0x4160), CQ_status); + } + break; + default: + break; + } + } + +EXIT: + /* 4. clear mark flag / reset marked time / reset time related infor and passedby signal count */ + spin_lock_irqsave(&(IspInfo.SpinLockIrq[eIrq]), flags); + if (WaitIrq->UserInfo.Status & IspInfo.IrqInfo. + MarkedFlag[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo.Type]) { + IspInfo.IrqInfo.MarkedFlag[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo.Type] &= + (~WaitIrq->UserInfo.Status); + IspInfo.IrqInfo.MarkedTime_usec[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo. + Type][idx] = 0; + IspInfo.IrqInfo.MarkedTime_sec[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo. + Type][idx] = 0; + IspInfo.IrqInfo.PassedBySigCnt[WaitIrq->UserInfo.UserKey][WaitIrq->UserInfo. + Type][idx] = 0; + } + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[eIrq]), flags); + + return Ret; +} + + +/* #define _debug_dma_err_ */ +#if defined(_debug_dma_err_) +#define bit(x) (0x1<<(x)) + +MUINT32 DMA_ERR[3 * 12] = { + bit(1), 0xF50043A8, 0x00000011, /* IMGI */ + bit(2), 0xF50043AC, 0x00000021, /* IMGCI */ + bit(4), 0xF50043B0, 0x00000031, /* LSCI */ + bit(5), 0xF50043B4, 0x00000051, /* FLKI */ + bit(6), 0xF50043B8, 0x00000061, /* LCEI */ + bit(7), 0xF50043BC, 0x00000071, /* VIPI */ + bit(8), 0xF50043C0, 0x00000081, /* VIP2I */ + bit(9), 0xF50043C4, 0x00000194, /* IMGO */ + bit(10), 0xF50043C8, 0x000001a4, /* IMG2O */ + bit(11), 0xF50043CC, 0x000001b4, /* LCSO */ + bit(12), 0xF50043D0, 0x000001c4, /* ESFKO */ + bit(13), 0xF50043D4, 0x000001d4, /* AAO */ +}; + +static MINT32 DMAErrHandler(void) +{ + MUINT32 err_ctrl = ISP_RD32(0xF50043A4); + + LOG_DBG("err_ctrl(0x%08x)", err_ctrl); + + MUINT32 i = 0; + + MUINT32 *pErr = DMA_ERR; + + for (i = 0; i < 12; i++) { + MUINT32 addr = 0; +#if 1 + if (err_ctrl & (*pErr)) { + ISP_WR32(0xF5004160, pErr[2]); + addr = pErr[1]; + + LOG_DBG("(0x%08x, 0x%08x), dbg(0x%08x, 0x%08x)", + addr, ISP_RD32(addr), ISP_RD32(0xF5004160), ISP_RD32(0xF5004164)); + } +#else + addr = pErr[1]; + MUINT32 status = ISP_RD32(addr); + + if (status & 0x0000FFFF) { + ISP_WR32(0xF5004160, pErr[2]); + addr = pErr[1]; + + LOG_DBG("(0x%08x, 0x%08x), dbg(0x%08x, 0x%08x)", + addr, status, ISP_RD32(0xF5004160), ISP_RD32(0xF5004164)); + } +#endif + pErr = pErr + 3; + } + +} +#endif + +/* ///////////////////////////////////////////////////////////////////////////// */ +/* for CAMSV */ +static __tcmfunc irqreturn_t ISP_Irq_CAMSV(MINT32 Irq, void *DeviceId) +{ + /* MUINT32 result=0x0; */ + MUINT32 i = 0; + /* MINT32 idx=0; */ + MUINT32 IrqStatus_CAMSV; + volatile CQ_RTBC_FBC fbc; + + volatile MUINT32 curr_pa; + struct timeval time_frmb; + MUINT32 idx = 0, k = 0; + unsigned long long sec = 0; + unsigned long usec = 0; + +/* do_gettimeofday(&time_frmb);*/ + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + time_frmb.tv_usec = usec; + time_frmb.tv_sec = sec; + + fbc.Reg_val = ISP_RD32(ISP_REG_ADDR_CAMSV_IMGO_FBC); + curr_pa = ISP_RD32(ISP_REG_ADDR_IMGO_SV_BASE_ADDR); + spin_lock(&(IspInfo.SpinLockIrq[_CAMSV_IRQ])); + IrqStatus_CAMSV = + (ISP_RD32(ISP_REG_ADDR_CAMSV_INT) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_CAMSV] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_CAMSV])); + + for (i = 0; i < IRQ_USER_NUM_MAX; i++) { + /* 1. update interrupt status to all users */ + IspInfo.IrqInfo.Status[i][ISP_IRQ_TYPE_INT_CAMSV] |= + (IrqStatus_CAMSV & IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_CAMSV]); + + /* 2. update signal occuring time and passed by signal count */ + if (IspInfo.IrqInfo.MarkedFlag[i][ISP_IRQ_TYPE_INT_CAMSV] & IspInfo.IrqInfo. + Mask[ISP_IRQ_TYPE_INT_CAMSV]) { + for (k = 0; k < 32; k++) { + if ((IrqStatus_CAMSV & IspInfo.IrqInfo. + Mask[ISP_IRQ_TYPE_INT_CAMSV]) & (1 << k)) { + idx = my_get_pow_idx(1 << k); + IspInfo.IrqInfo. + LastestSigTime_usec[ISP_IRQ_TYPE_INT_CAMSV][idx] = + (unsigned int)time_frmb.tv_usec; + IspInfo.IrqInfo. + LastestSigTime_sec[ISP_IRQ_TYPE_INT_CAMSV][idx] = + (unsigned int)time_frmb.tv_sec; + IspInfo.IrqInfo. + PassedBySigCnt[i][ISP_IRQ_TYPE_INT_CAMSV][k]++; + } + } + } else { /* no any interrupt is not marked and in read mask in this irq type */ + } + } + + if (IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_CAMSV] & IrqStatus_CAMSV) + IRQ_LOG_KEEPER(_CAMSV_IRQ, m_CurrentPPB, _LOG_ERR, + CAMSV_TAG "Err IRQ, Type(%d), Status(0x%x)\n", + ISP_IRQ_TYPE_INT_CAMSV, + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_CAMSV] & IrqStatus_CAMSV); + + if (IspInfo.DebugMask & ISP_DBG_INT) + IRQ_LOG_KEEPER(_CAMSV_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV_TAG "Type(%d), IrqStatus(0x%x | 0x%x)\n", + ISP_IRQ_TYPE_INT_CAMSV, + IspInfo.IrqInfo. + Status[ISP_IRQ_USER_ISPDRV][ISP_IRQ_TYPE_INT_CAMSV], + IrqStatus_CAMSV); + + + if (IrqStatus_CAMSV & ISP_IRQ_CAMSV_STATUS_PASS1_DON_ST) { + if (IspInfo.DebugMask & ISP_DBG_BUF_CTRL) { + IRQ_LOG_KEEPER(_CAMSV_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV_TAG "DONE_%d_%d(0x%x,0x%x,0x%x,0x%x)\n", + (sof_count[_CAMSV]) ? (sof_count[_CAMSV] - + 1) : (sof_count[_CAMSV]), + ((ISP_RD32(ISP_REG_ADDR_CAMSV_TG_INTER_ST) & 0x00FF0000) >> + 16), (unsigned int)(fbc.Reg_val), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_XSIZE), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_YSIZE)); + } +#if 0 /* time stamp move to sof */ + unsigned long long sec = 0; + unsigned long usec = 0; + + if (IspInfo.DebugMask & ISP_DBG_INT) { + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + } + ISP_CAMSV_DONE_Buf_Time(_camsv_imgo_, sec, usec); +#else + ISP_CAMSV_DONE_Buf_Time(_camsv_imgo_, fbc, 0, 0); +#endif + } + if (IrqStatus_CAMSV & ISP_IRQ_CAMSV_STATUS_TG_SOF1_ST) { + unsigned long long sec; + unsigned long usec; + ktime_t time; + MUINT32 z; + /* chk this frame have EOF or not */ + if (fbc.Bits.FB_NUM == fbc.Bits.FBC_CNT) { + gSof_camsvdone[0] = 1; + IRQ_LOG_KEEPER(_CAMSV_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV_TAG "Lost done_%d\n", sof_count[_CAMSV]); + + } else { + gSof_camsvdone[0] = 0; + } +#ifdef _rtbc_buf_que_2_0_ +/* MUINT32 z;*/ + + if (1 == mFwRcnt.bLoadBaseAddr[_CAMSV_IRQ]) { + if (pstRTBuf->ring_buf[_camsv_imgo_].active) { + /*IRQ_LOG_KEEPER(_CAMSV_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV_TAG "wr2Phy,"); + ISP_WR32(ISP_REG_ADDR_IMGO_SV_BASE_ADDR, + pstRTBuf->ring_buf[_camsv_imgo_].data[pstRTBuf-> + ring_buf[_camsv_imgo_].start].base_pAddr);*/ + LOG_INF("[no wr2Phy]IMGO_SV:addr should write by MVHDR"); + } + mFwRcnt.bLoadBaseAddr[_CAMSV_IRQ] = 0; + } + /* equal case is for clear curidx */ + for (z = 0; z <= mFwRcnt.curIdx[_CAMSV_IRQ]; z++) { + if (1 == mFwRcnt.INC[_CAMSV_IRQ][z]) { + mFwRcnt.INC[_CAMSV_IRQ][z] = 0; + /* patch hw bug */ + fbc.Bits.RCNT_INC = 1; + ISP_WR32(ISP_REG_ADDR_CAMSV_IMGO_FBC, fbc.Reg_val); + fbc.Bits.RCNT_INC = 0; + ISP_WR32(ISP_REG_ADDR_CAMSV_IMGO_FBC, fbc.Reg_val); + IRQ_LOG_KEEPER(_CAMSV_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV_TAG "RCNT_INC\n"); + } else { + mFwRcnt.curIdx[_CAMSV_IRQ] = 0; + break; + } + } +#endif + if (IspInfo.DebugMask & ISP_DBG_INT) { + CQ_RTBC_FBC _fbc_chk; + + /* in order to log newest fbc condition */ + _fbc_chk.Reg_val = ISP_RD32(ISP_REG_ADDR_CAMSV_IMGO_FBC); + IRQ_LOG_KEEPER(_CAMSV_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV_TAG "SOF_%d_%d(0x%x,0x%x,0x%x,0x%x)\n", + sof_count[_CAMSV], + ((ISP_RD32(ISP_REG_ADDR_CAMSV_TG_INTER_ST) & 0x00FF0000) >> + 16), _fbc_chk.Reg_val, + ISP_RD32(ISP_REG_ADDR_IMGO_SV_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_XSIZE), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_YSIZE)); + + if (_fbc_chk.Bits.WCNT != fbc.Bits.WCNT) + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "sv1:SW ISR right on next hw p1_done(0x%x_0x%x)\n", + _fbc_chk.Reg_val, fbc.Reg_val); + } +/* + unsigned long long sec; + unsigned long usec; + ktime_t time; +*/ + time = ktime_get(); /* ns */ + sec = time.tv64; + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + + ISP_CAMSV_SOF_Buf_Get(_camsv_imgo_, fbc, curr_pa, sec, usec, gSof_camsvdone[0]); + } + spin_unlock(&(IspInfo.SpinLockIrq[_CAMSV_IRQ])); +#ifdef ISR_LOG_ON + IRQ_LOG_PRINTER(_CAMSV_IRQ, m_CurrentPPB, _LOG_INF); + IRQ_LOG_PRINTER(_CAMSV_IRQ, m_CurrentPPB, _LOG_ERR); +#endif + wake_up_interruptible_all((wait_queue_head_t *)&IspInfo.WaitQueueHead); + + return IRQ_HANDLED; +} + +static __tcmfunc irqreturn_t ISP_Irq_CAMSV2(MINT32 Irq, void *DeviceId) +{ + /* MUINT32 result=0x0; */ + MUINT32 i = 0; + /* MINT32 idx=0; */ + MUINT32 IrqStatus_CAMSV2; + volatile CQ_RTBC_FBC fbc; + + volatile MUINT32 curr_pa; + struct timeval time_frmb; + MUINT32 idx = 0, k = 0; + unsigned long long sec = 0; + unsigned long usec = 0; + +/* do_gettimeofday(&time_frmb);*/ + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + time_frmb.tv_usec = usec; + time_frmb.tv_sec = sec; + + fbc.Reg_val = ISP_RD32(ISP_REG_ADDR_CAMSV2_IMGO_FBC); + curr_pa = ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR); + spin_lock(&(IspInfo.SpinLockIrq[_CAMSV_D_IRQ])); + IrqStatus_CAMSV2 = + (ISP_RD32(ISP_REG_ADDR_CAMSV2_INT) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_CAMSV2] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_CAMSV2])); + + for (i = 0; i < IRQ_USER_NUM_MAX; i++) { + /* 1. update interrupt status to all users */ + IspInfo.IrqInfo.Status[i][ISP_IRQ_TYPE_INT_CAMSV2] |= + (IrqStatus_CAMSV2 & IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_CAMSV2]); + + /* 2. update signal occuring time and passed by signal count */ + if (IspInfo.IrqInfo.MarkedFlag[i][ISP_IRQ_TYPE_INT_CAMSV2] & IspInfo.IrqInfo. + Mask[ISP_IRQ_TYPE_INT_CAMSV2]) { + for (k = 0; k < 32; k++) { + if ((IrqStatus_CAMSV2 & IspInfo.IrqInfo. + Mask[ISP_IRQ_TYPE_INT_CAMSV2]) & (1 << k)) { + idx = my_get_pow_idx(1 << k); + IspInfo.IrqInfo. + LastestSigTime_usec[ISP_IRQ_TYPE_INT_CAMSV2][idx] = + (unsigned int)time_frmb.tv_usec; + IspInfo.IrqInfo. + LastestSigTime_sec[ISP_IRQ_TYPE_INT_CAMSV2][idx] = + (unsigned int)time_frmb.tv_sec; + IspInfo.IrqInfo. + PassedBySigCnt[i][ISP_IRQ_TYPE_INT_CAMSV2][k]++; + } + } + } else { /* no any interrupt is not marked and in read mask in this irq type */ + } + } + + if (IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_CAMSV2] & IrqStatus_CAMSV2) + IRQ_LOG_KEEPER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_ERR, + CAMSV2_TAG "Error IRQ, Type(%d), Status(0x%08x)\n", + ISP_IRQ_TYPE_INT_CAMSV2, + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_CAMSV2] & IrqStatus_CAMSV2); + + if (IspInfo.DebugMask & ISP_DBG_INT) + IRQ_LOG_KEEPER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV2_TAG "Type(%d), IrqStatus(0x%x | 0x%08x)\n", + ISP_IRQ_TYPE_INT_CAMSV2, + IspInfo.IrqInfo.Status[ISP_IRQ_USER_ISPDRV][ISP_IRQ_TYPE_INT_CAMSV2], + (unsigned int)(IrqStatus_CAMSV2)); + + if (IrqStatus_CAMSV2 & ISP_IRQ_CAMSV2_STATUS_PASS1_DON_ST) { + if (IspInfo.DebugMask & ISP_DBG_INT) { + IRQ_LOG_KEEPER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_INF, CAMSV2_TAG "fbc(0x%x)", + (unsigned int)(fbc.Reg_val)); + + IRQ_LOG_KEEPER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV2_TAG + "DONE_%d_%d(0x%x,0x%x,0x%x,0x%x,camsv support no inner addr)\n", + (sof_count[_CAMSV_D]) ? (sof_count[_CAMSV_D] - + 1) : (sof_count[_CAMSV_D]), + ((ISP_RD32(ISP_REG_ADDR_CAMSV_TG2_INTER_ST) & + 0x00FF0000) >> 16), (unsigned int)(fbc.Reg_val), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_XSIZE), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_YSIZE)); + } +#if 0 /* time stamp move to sof */ + unsigned long long sec; + unsigned long usec; + + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + + ISP_CAMSV_DONE_Buf_Time(_camsv2_imgo_, sec, usec); +#else + ISP_CAMSV_DONE_Buf_Time(_camsv2_imgo_, fbc, 0, 0); +#endif + } + if (IrqStatus_CAMSV2 & ISP_IRQ_CAMSV2_STATUS_TG_SOF1_ST) { + unsigned long long sec; + unsigned long usec; + ktime_t time; + MUINT32 z; + /* chk this frame have EOF or not */ + if (fbc.Bits.FB_NUM == fbc.Bits.FBC_CNT) { + gSof_camsvdone[1] = 1; + IRQ_LOG_KEEPER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV2_TAG "Lost done %d", sof_count[_CAMSV_D]); + + } else { + gSof_camsvdone[1] = 0; + } +#ifdef _rtbc_buf_que_2_0_ + + if (1 == mFwRcnt.bLoadBaseAddr[_CAMSV_D_IRQ]) { + if (pstRTBuf->ring_buf[_camsv2_imgo_].active) { + /*IRQ_LOG_KEEPER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV2_TAG "wr2Phy,"); + ISP_WR32(ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR, + pstRTBuf->ring_buf[_camsv2_imgo_].data[pstRTBuf-> + ring_buf[_camsv2_imgo_].start].base_pAddr);*/ + LOG_INF("[no wr2Phy]IMGO_SV_D:addr should write by PD"); + } + mFwRcnt.bLoadBaseAddr[_CAMSV_D_IRQ] = 0; + } + /* equal case is for clear curidx */ + for (z = 0; z <= mFwRcnt.curIdx[_CAMSV_D_IRQ]; z++) { + if (1 == mFwRcnt.INC[_CAMSV_D_IRQ][z]) { + mFwRcnt.INC[_CAMSV_D_IRQ][z] = 0; + /* path hw bug */ + fbc.Bits.RCNT_INC = 1; + ISP_WR32(ISP_REG_ADDR_CAMSV2_IMGO_FBC, fbc.Reg_val); + fbc.Bits.RCNT_INC = 0; + ISP_WR32(ISP_REG_ADDR_CAMSV2_IMGO_FBC, fbc.Reg_val); + IRQ_LOG_KEEPER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV2_TAG "RCNT_INC\n"); + } else { + mFwRcnt.curIdx[_CAMSV_D_IRQ] = 0; + break; + } + } +#endif + + if (IspInfo.DebugMask & ISP_DBG_INT) { + CQ_RTBC_FBC _fbc_chk; + _fbc_chk.Reg_val = ISP_RD32(ISP_REG_ADDR_CAMSV2_IMGO_FBC);/* in order to log newest fbc condition */ + + /* in order to log newest fbc condition */ + _fbc_chk.Reg_val = ISP_RD32(ISP_REG_ADDR_CAMSV2_IMGO_FBC); + + IRQ_LOG_KEEPER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_INF, + CAMSV2_TAG + "SOF_%d_%d(0x%x,0x%x,0x%x,0x%x,camsv support no inner addr)\n", + sof_count[_CAMSV_D], + ((ISP_RD32(ISP_REG_ADDR_CAMSV_TG2_INTER_ST) & 0x00FF0000) + >> 16), _fbc_chk.Reg_val, + ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_XSIZE), + ISP_RD32(ISP_REG_ADDR_IMGO_SV_D_YSIZE)); + + if (_fbc_chk.Bits.WCNT != fbc.Bits.WCNT) + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "sv2:SW ISR right on next hw p1_done(0x%x_0x%x)\n", + _fbc_chk.Reg_val, fbc.Reg_val); + } + /* unsigned long long sec; */ + /* unsigned long usec; */ + /* ktime_t time; */ + + time = ktime_get(); /* ns */ + sec = time.tv64; + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + + ISP_CAMSV_SOF_Buf_Get(_camsv2_imgo_, fbc, curr_pa, sec, usec, gSof_camsvdone[1]); + } + spin_unlock(&(IspInfo.SpinLockIrq[_CAMSV_D_IRQ])); + /* dump log during spin lock */ +#ifdef ISR_LOG_ON + IRQ_LOG_PRINTER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_INF); + IRQ_LOG_PRINTER(_CAMSV_D_IRQ, m_CurrentPPB, _LOG_ERR); +#endif + wake_up_interruptible_all((wait_queue_head_t *)&IspInfo.WaitQueueHead); + return IRQ_HANDLED; +} + +/* ///////////////////////////////////////////////////////////////////////////// */ + +/******************************************************************************* +* +********************************************************************************/ +static __tcmfunc irqreturn_t ISP_Irq_CAM(MINT32 Irq, void *DeviceId) +{ + +/* LOG_DBG("- E.");*/ + MUINT32 i; + + volatile MUINT32 IrqStatus[ISP_IRQ_TYPE_AMOUNT]; + /* MUINT32 IrqStatus_fbc_int; */ + volatile CQ_RTBC_FBC p1_fbc[4]; + + volatile MUINT32 curr_pa[4]; /* debug only at sof */ + MUINT32 cur_v_cnt = 0; + MUINT32 d_cur_v_cnt = 0; + MUINT32 j = 0, idx = 0, k = 0; + struct timeval time_frmb; + unsigned long long sec = 0; + unsigned long usec = 0; +#if 0 + if ((ISP_RD32(ISP_REG_ADDR_TG_VF_CON) & 0x1) == 0x0) { + LOG_INF("before vf:0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n", + ISP_RD32(ISP_REG_ADDR_INT_P1_ST), ISP_RD32(ISP_REG_ADDR_INT_P1_ST2), + ISP_RD32(ISP_REG_ADDR_INT_P1_ST_D), ISP_RD32(ISP_REG_ADDR_INT_P1_ST2_D), + ISP_RD32(ISP_REG_ADDR_INT_P2_ST), ISP_RD32(ISP_REG_ADDR_INT_STATUSX), + ISP_RD32(ISP_REG_ADDR_INT_STATUS2X), ISP_RD32(ISP_REG_ADDR_INT_STATUS3X)); + } +#endif + /* */ +/* do_gettimeofday(&time_frmb);*/ + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + time_frmb.tv_usec = usec; + time_frmb.tv_sec = sec; + + /* Read irq status */ + /* spin_lock(&(IspInfo.SpinLockIrq[_IRQ])); */ + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] = + (ISP_RD32(ISP_REG_ADDR_INT_P1_ST) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P1_ST] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_P1_ST])); + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST2] = (ISP_RD32(ISP_REG_ADDR_INT_P1_ST2)); + /* & (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P1_ST2]|IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_P1_ST2])); */ + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] = + (ISP_RD32(ISP_REG_ADDR_INT_P1_ST_D) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P1_ST_D] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_P1_ST_D])); + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST2_D] = + (ISP_RD32(ISP_REG_ADDR_INT_P1_ST2_D) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P1_ST2_D] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_P1_ST2_D])); +#ifdef __debugused__ + IrqStatus[ISP_IRQ_TYPE_INT_P2_ST] = + (ISP_RD32(ISP_REG_ADDR_INT_P2_ST) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P2_ST] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_P2_ST])); +#endif + /* below may need to read elsewhere */ + IrqStatus[ISP_IRQ_TYPE_INT_STATUSX] = + (ISP_RD32(ISP_REG_ADDR_INT_STATUSX) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_STATUSX] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_STATUSX])); + IrqStatus[ISP_IRQ_TYPE_INT_STATUS2X] = + (ISP_RD32(ISP_REG_ADDR_INT_STATUS2X) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_STATUS2X] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_STATUS2X])); + IrqStatus[ISP_IRQ_TYPE_INT_STATUS3X] = + (ISP_RD32(ISP_REG_ADDR_INT_STATUS3X) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_STATUS3X] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_STATUS3X])); + /* spin_unlock(&(IspInfo.SpinLockIrq[_IRQ])); */ + /* IrqStatus_fbc_int = ISP_RD32(ISP_ADDR + 0xFC); */ + + p1_fbc[0].Reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_FBC); + p1_fbc[1].Reg_val = ISP_RD32(ISP_REG_ADDR_RRZO_FBC); + p1_fbc[2].Reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_D_FBC); + p1_fbc[3].Reg_val = ISP_RD32(ISP_REG_ADDR_RRZO_D_FBC); + curr_pa[0] = ISP_RD32(ISP_REG_ADDR_IMGO_BASE_ADDR); + curr_pa[1] = ISP_RD32(ISP_REG_ADDR_RRZO_BASE_ADDR); + curr_pa[2] = ISP_RD32(ISP_REG_ADDR_IMGO_D_BASE_ADDR); + curr_pa[3] = ISP_RD32(ISP_REG_ADDR_RRZO_D_BASE_ADDR); +#ifdef __debugused__ + LOG_INF("irq status:0x%x,0x%x,0x%x,0x%x,0x%x\n", + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST], + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST2], + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D], + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST2_D], IrqStatus[ISP_IRQ_TYPE_INT_P2_ST]); +#endif + +#if 1 /* err status mechanism */ +#define STATUSX_WARNING (ISP_IRQ_STATUSX_ESFKO_ERR_ST| \ + ISP_IRQ_STATUSX_RRZO_ERR_ST| \ + ISP_IRQ_STATUSX_LCSO_ERR_ST| \ + ISP_IRQ_STATUSX_AAO_ERR_ST| \ + ISP_IRQ_STATUSX_IMGO_ERR_ST| \ + ISP_IRQ_STATUSX_RRZO_ERR_ST) + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_STATUSX] = + IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_STATUSX] & + (~(ISP_IRQ_STATUSX_IMGO_DROP_FRAME_ST | ISP_IRQ_STATUSX_RRZO_DROP_FRAME_ST)); + /* p1 && p1_d share the same interrupt status */ + if (IrqStatus[ISP_IRQ_TYPE_INT_STATUSX] & IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_STATUSX]) { + if ((IrqStatus[ISP_IRQ_TYPE_INT_STATUSX] & ISP_IRQ_STATUSX_DMA_ERR_ST) + || (IrqStatus[ISP_IRQ_TYPE_INT_STATUS2X] & ISP_IRQ_STATUSX_DMA_ERR_ST)) { + g_bDmaERR_p1_d = MTRUE; + g_bDmaERR_p1 = MTRUE; + g_bDmaERR_deepDump = MFALSE; + ISP_DumpDmaDeepDbg(); + } + + /* if(IrqStatus[ISP_IRQ_TYPE_INT_STATUSX] & ISP_IRQ_STATUSX_AAO_ERR_ST) { */ + /* ISP_DumpReg(); */ + /* } */ + /* mark, can ignor fifo may overrun if dma_err isn't pulled. */ + /* if(IrqStatus[ISP_IRQ_TYPE_INT_STATUSX] & STATUSX_WARNING) { */ + /* LOG_INF("warning: fifo may overrun"); */ + /* } */ + if (IrqStatus[ISP_IRQ_TYPE_INT_STATUSX] & (~STATUSX_WARNING)) { + LOG_ERR("ISP INT ERR_P1 0x%x\n", IrqStatus[ISP_IRQ_TYPE_INT_STATUSX]); + g_ISPIntErr[_IRQ] |= IrqStatus[ISP_IRQ_TYPE_INT_STATUSX]; + } + if (IrqStatus[ISP_IRQ_TYPE_INT_STATUS2X] & (~STATUSX_WARNING)) { + LOG_ERR("ISP INT ERR_P1_D 0x%x\n", IrqStatus[ISP_IRQ_TYPE_INT_STATUS2X]); + g_ISPIntErr[_IRQ_D] |= IrqStatus[ISP_IRQ_TYPE_INT_STATUS2X]; + } + } + /* LOG_INF("isp irq status:0x%x_0x%x", + IrqStatus[ISP_IRQ_TYPE_INT_P1_ST],IrqStatus[ISP_IRQ_TYPE_INT_STATUSX]); */ + /* LOG_INF("imgo fill:%d %d %d\n", + pstRTBuf->ring_buf[_imgo_].data[0].bFilled,pstRTBuf->ring_buf[_imgo_].data[1].bFilled, + pstRTBuf->ring_buf[_imgo_].data[2].bFilled); */ + /* LOG_INF("rrzo fill:%d %d %d\n", + pstRTBuf->ring_buf[_rrzo_].data[0].bFilled,pstRTBuf->ring_buf[_rrzo_].data[1].bFilled, + pstRTBuf->ring_buf[_rrzo_].data[2].bFilled); */ + if ((IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_PASS1_DON_ST) + || (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_SOF1_INT_ST)) + cur_v_cnt = ((ISP_RD32(ISP_REG_ADDR_TG_INTER_ST) & 0x00FF0000) >> 16); + if ((IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_D_PASS1_DON_ST) + || (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_D_SOF1_INT_ST)) + d_cur_v_cnt = ((ISP_RD32(ISP_REG_ADDR_TG2_INTER_ST) & 0x00FF0000) >> 16); + if ((IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_PASS1_DON_ST) + && (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_SOF1_INT_ST)) { + if (cur_v_cnt != sof_count[_PASS1]) + LOG_ERR("isp sof_don block, %d_%d\n", cur_v_cnt, sof_count[_PASS1]); + } +#endif + +#if 0 + /sensor interface would use another isr id + /* sensor interface related irq */ + IrqStatus[ISP_IRQ_TYPE_INT_SENINF1] = + (ISP_RD32(ISP_REG_ADDR_SENINF1_INT) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_SENINF1] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_SENINF1])); + IrqStatus[ISP_IRQ_TYPE_INT_SENINF2] = + (ISP_RD32(ISP_REG_ADDR_SENINF2_INT) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_SENINF2] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_SENINF2])); + IrqStatus[ISP_IRQ_TYPE_INT_SENINF3] = + (ISP_RD32(ISP_REG_ADDR_SENINF3_INT) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_SENINF3] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_SENINF3])); + IrqStatus[ISP_IRQ_TYPE_INT_SENINF4] = + (ISP_RD32(ISP_REG_ADDR_SENINF4_INT) & + (IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_SENINF4] | IspInfo.IrqInfo. + ErrMask[ISP_IRQ_TYPE_INT_SENINF4])); +#endif + + + /* service pass1_done first once if SOF/PASS1_DONE are coming together. */ + /* get time stamp */ + /* push hw filled buffer to sw list */ + /* LOG_INF("RTBC_DBG %x_%x\n",IrqStatus[ISP_IRQ_TYPE_INT_P1_ST],IrqStatus[ISP_IRQ_TYPE_INT_STATUSX]); */ + spin_lock(&(IspInfo.SpinLockIrq[_IRQ])); + if (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_PASS1_DON_ST) { +#ifdef _rtbc_buf_que_2_0_ + unsigned long long sec; + unsigned long usec; + + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + /* update pass1 done time stamp for eis user(need match with the time stamp in image header) */ + IspInfo.IrqInfo.LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST][10] = + (unsigned int)(usec); + IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST][10] = + (unsigned int)(sec); + gEismetaInSOF = 0; + ISP_DONE_Buf_Time(_IRQ, p1_fbc, 0, 0); + if (IspInfo.DebugMask & ISP_DBG_INT) { + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, "P1_DON_%d(0x%x,0x%x)\n", + (sof_count[_PASS1]) ? (sof_count[_PASS1] - + 1) : (sof_count[_PASS1]), + (unsigned int)(p1_fbc[0].Reg_val), + (unsigned int)(p1_fbc[1].Reg_val)); + } + lost_pass1_done_cnt = 0; +#else +#if defined(_rtbc_use_cq0c_) + if (IspInfo.DebugMask & ISP_DBG_INT) { + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, "P1_DON_%d(0x%x,0x%x)\n", + (sof_count[_PASS1]) ? (sof_count[_PASS1] - + 1) : (sof_count[_PASS1]), + (unsigned int)(p1_fbc[0].Reg_val), + (unsigned int)(p1_fbc[1].Reg_val)); + } +#else + /* LOG_DBG("[k_js_test]Pass1_done(0x%x)",IrqStatus[ISP_IRQ_TYPE_INT]); */ + unsigned long long sec; + unsigned long usec; + + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + /* update pass1 done time stamp for eis user(need match with the time stamp in image header) */ + IspInfo.IrqInfo.LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST][10] = + (unsigned int)(sec); + IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST][10] = + (unsigned int)(usec); + gEismetaInSOF = 0; + ISP_DONE_Buf_Time(p1_fbc, sec, usec); + /*Check Timesamp reverse */ + /* what's this? */ + /* */ +#endif +#endif + } + + /* switch pass1 WDMA buffer */ + /* fill time stamp for cq0c */ + if (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_SOF1_INT_ST) { + MUINT32 _dmaport = 0; + MUINT32 rt_dma = 0; + unsigned long long sec; + unsigned long usec; + ktime_t time; + MUINT32 z; + static MUINT32 m_sec, m_usec; + + time = ktime_get();/* ns */ + sec = time.tv64; + do_div(sec, 1000);/* usec */ + usec = do_div(sec, 1000000);/* sec and usec */ + + if (pstRTBuf->ring_buf[_imgo_].active) { + _dmaport = 0; + rt_dma = _imgo_; + } else if (pstRTBuf->ring_buf[_rrzo_].active) { + _dmaport = 1; + rt_dma = _rrzo_; + } else + LOG_ERR("no main dma port opened at SOF\n"); + /* chk this frame have EOF or not, dynimic dma port chk */ + if (p1_fbc[_dmaport].Bits.FB_NUM == p1_fbc[_dmaport].Bits.FBC_CNT) { + sof_pass1done[0] = 1; +#ifdef _rtbc_buf_que_2_0_ + /* ISP_LostP1Done_ErrHandle(_imgo_); */ + /* ISP_LostP1Done_ErrHandle(_rrzo_); */ + /* IRQ_LOG_KEEPER(_IRQ,m_CurrentPPB,_LOG_INF,"lost p1Done ErrHandle\n"); */ +#endif + lost_pass1_done_cnt++; + if (2 == lost_pass1_done_cnt) { + /*check any buffer is ready? */ + for (k = 0; k < pstRTBuf->ring_buf[rt_dma].total_count; k++) { + if (ISP_RTBC_BUF_FILLED == pstRTBuf->ring_buf[rt_dma].data[k].bFilled) { + /**/ for (j = 0; j < ISP_IRQ_USER_MAX; j++) + IspInfo.IrqInfo.Status[j][ISP_IRQ_TYPE_INT_P1_ST] |= + ISP_IRQ_P1_STATUS_PASS1_DON_ST; + + lost_pass1_done_cnt = 0; + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "raw buf rdy but lost pass1 done, wakeup by sof!!"); + break; + } + } + } + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, "Lost p1 done_%d (0x%x): ", + sof_count[_PASS1], cur_v_cnt); + } else { + sof_pass1done[0] = 0; + if (p1_fbc[_dmaport].Bits.FB_NUM == (p1_fbc[_dmaport].Bits.FBC_CNT + 1)) + sof_pass1done[0] = 2; + + } +#ifdef _rtbc_buf_que_2_0_ + + if (1 == mFwRcnt.bLoadBaseAddr[_IRQ]) { + if (pstRTBuf->ring_buf[_imgo_].active) { + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, " p1_%d:wr2Phy_0x%x: ", + _imgo_, + pstRTBuf->ring_buf[_imgo_].data[pstRTBuf-> + ring_buf[_imgo_]. + start].base_pAddr); + ISP_WR32(ISP_REG_ADDR_IMGO_BASE_ADDR, + pstRTBuf->ring_buf[_imgo_].data[pstRTBuf->ring_buf[_imgo_]. + start].base_pAddr); + } + if (pstRTBuf->ring_buf[_rrzo_].active) { + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, " p1_%d:wr2Phy_0x%x: ", + _rrzo_, + pstRTBuf->ring_buf[_rrzo_].data[pstRTBuf-> + ring_buf[_rrzo_]. + start].base_pAddr); + ISP_WR32(ISP_REG_ADDR_RRZO_BASE_ADDR, + pstRTBuf->ring_buf[_rrzo_].data[pstRTBuf->ring_buf[_rrzo_]. + start].base_pAddr); + } + mFwRcnt.bLoadBaseAddr[_IRQ] = 0; + } + /* equal case is for clear curidx */ + for (z = 0; z <= mFwRcnt.curIdx[_IRQ]; z++) { + /* LOG_INF("curidx:%d\n",mFwRcnt.curIdx[_IRQ]); */ + if (1 == mFwRcnt.INC[_IRQ][z]) { + mFwRcnt.INC[_IRQ][z] = 0; + p1_fbc[0].Bits.RCNT_INC = 1; + ISP_WR32(ISP_REG_ADDR_IMGO_FBC, p1_fbc[0].Reg_val); + p1_fbc[1].Bits.RCNT_INC = 1; + ISP_WR32(ISP_REG_ADDR_RRZO_FBC, p1_fbc[1].Reg_val); + if (IspInfo.DebugMask & ISP_DBG_INT) + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + " p1:RCNT_INC: "); + } else { + /* LOG_INF("RTBC_DBG:%d %d %d %d %d %d %d %d %d %d", + mFwRcnt.INC[_IRQ][0],mFwRcnt.INC[_IRQ][1],mFwRcnt.INC[_IRQ][2],mFwRcnt.INC[_IRQ][3],mFwRcnt.INC[_IRQ][4],\ */ + /* mFwRcnt.INC[_IRQ][5],mFwRcnt.INC[_IRQ][6],mFwRcnt.INC[_IRQ][7],mFwRcnt.INC[_IRQ][8],mFwRcnt.INC[_IRQ][9]); */ + mFwRcnt.curIdx[_IRQ] = 0; + break; + } + } +#endif + if (IspInfo.DebugMask & ISP_DBG_INT) { + CQ_RTBC_FBC _fbc_chk[2]; /* can chk fbc status compare to p1_fbc. (the difference is the timing of reading) */ + + _fbc_chk[0].Reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_FBC); /* in order to log newest fbc condition */ + _fbc_chk[1].Reg_val = ISP_RD32(ISP_REG_ADDR_RRZO_FBC); + + + if (g1stSof[_IRQ]) { + m_sec = sec; + m_usec = usec; + } + + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "P1_SOF_%d_%d(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x)_int_us:%d\n", + sof_count[_PASS1], cur_v_cnt, + (unsigned int)(_fbc_chk[0].Reg_val), + (unsigned int)(_fbc_chk[1].Reg_val), + ISP_RD32(ISP_REG_ADDR_IMGO_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_RRZO_BASE_ADDR), + ISP_RD32(ISP_INNER_REG_ADDR_IMGO_YSIZE), + ISP_RD32(ISP_INNER_REG_ADDR_RRZO_YSIZE), + ISP_RD32(ISP_REG_ADDR_TG_MAGIC_0), + (MUINT32)((sec*1000000 + usec) - (1000000*m_sec+m_usec))); + + /* keep current time */ + m_sec = sec; + m_usec = usec; + /* 1 port is enough */ + if (pstRTBuf->ring_buf[_imgo_].active) { + if (_fbc_chk[0].Bits.WCNT != p1_fbc[0].Bits.WCNT) + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "imgo:SW ISR right on next hw p1_done(0x%x_0x%x)\n", + _fbc_chk[0].Reg_val, p1_fbc[0].Reg_val); + } else if (pstRTBuf->ring_buf[_rrzo_].active) { + if (_fbc_chk[1].Bits.WCNT != p1_fbc[1].Bits.WCNT) + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "rrzo:SW ISR right on next hw p1_done(0x%x_0x%x)\n", + _fbc_chk[1].Reg_val, p1_fbc[1].Reg_val); + } + } +/* unsigned long long sec;*/ +/* unsigned long usec;*/ +/* ktime_t time;*/ + + time = ktime_get(); /* ns */ + sec = time.tv64; +#ifdef T_STAMP_2_0 + if (g1stSof[_IRQ] == MTRUE) + m_T_STAMP.T_ns = sec; + + if (m_T_STAMP.fps > SlowMotion) { + m_T_STAMP.fcnt++; + if (g1stSof[_IRQ] == MFALSE) { + m_T_STAMP.T_ns += + ((unsigned long long)m_T_STAMP.interval_us * 1000); + if (m_T_STAMP.fcnt == m_T_STAMP.fps) { + m_T_STAMP.fcnt = 0; + m_T_STAMP.T_ns += + ((unsigned long long)m_T_STAMP.compensation_us * 1000); + } + } + sec = m_T_STAMP.T_ns; + } +#endif + do_div(sec, 1000);/*usec*/ + usec = do_div(sec, 1000000);/*sec and usec*/ + /* update SOF time stamp for eis user(need match with the time stamp in image header) */ + IspInfo.IrqInfo.LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST][12] = + (unsigned int)(sec); + IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST][12] = + (unsigned int)(usec); + IspInfo.IrqInfo.LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST][0] = + (unsigned int)(sec); + IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST][0] = + (unsigned int)(usec); + IspInfo.IrqInfo.Eismeta[ISP_IRQ_TYPE_INT_P1_ST][gEismetaWIdx].tLastSOF2P1done_sec = + (unsigned int)(sec); + IspInfo.IrqInfo.Eismeta[ISP_IRQ_TYPE_INT_P1_ST][gEismetaWIdx].tLastSOF2P1done_usec = + (unsigned int)(usec); + gEismetaInSOF = 1; + gEismetaWIdx = ((gEismetaWIdx + 1) % EISMETA_RINGSIZE); + if (sof_pass1done[0] == 1) + ISP_SOF_Buf_Get(_IRQ, p1_fbc, (MUINT32 *)curr_pa, sec, usec, MTRUE); + else + ISP_SOF_Buf_Get(_IRQ, p1_fbc, (MUINT32 *)curr_pa, sec, usec, MFALSE); + } + spin_unlock(&(IspInfo.SpinLockIrq[_IRQ])); +#if 0 /* in order to keep the isr stability. */ + if (MFALSE == bSlowMotion) { + if (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_PASS1_DON_ST) + LOG_INF("1D_%d\n", + (sof_count[_PASS1]) ? (sof_count[_PASS1] - + 1) : (sof_count[_PASS1])); + + if (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & ISP_IRQ_P1_STATUS_SOF1_INT_ST) + LOG_INF("1S_%d\n", + (sof_count[_PASS1]) ? (sof_count[_PASS1] - + 1) : (sof_count[_PASS1])); + + } +#endif + spin_lock(&(IspInfo.SpinLockIrq[_IRQ])); + /* TG_D Done */ + if (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] & ISP_IRQ_P1_STATUS_D_PASS1_DON_ST) { + unsigned long long sec; + unsigned long usec; + if (IspInfo.DebugMask & ISP_DBG_INT) { + IRQ_LOG_KEEPER(_IRQ_D, m_CurrentPPB, _LOG_INF, + "P1_D_DON_%d_%d(0x%x,0x%x)\n", + (sof_count[_PASS1_D]) ? (sof_count[_PASS1_D] - + 1) : (sof_count[_PASS1_D]), + d_cur_v_cnt, (unsigned int)(p1_fbc[2].Reg_val), + (unsigned int)(p1_fbc[3].Reg_val)); + } +#ifdef _rtbc_buf_que_2_0_ + + sec = cpu_clock(0); /* ns */ + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + /* update pass1 done time stamp for eis user(need match with the time stamp in image header) */ + IspInfo.IrqInfo.LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST_D][10] = + (unsigned int)(usec); + IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST_D][10] = + (unsigned int)(sec); + gEismetaInSOF_D = 0; + ISP_DONE_Buf_Time(_IRQ_D, p1_fbc, 0, 0); +#endif + lost_pass1_d_done_cnt = 0; + } + + /* TG_D SOF */ + if (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] & ISP_IRQ_P1_STATUS_D_SOF1_INT_ST) { + MUINT32 _dmaport = 0; + MUINT32 rt_dma = 0; + MUINT32 z; + unsigned long long sec; + unsigned long usec; + static MUINT32 m_sec_d, m_usec_d; + ktime_t time; + time = ktime_get();/* ns */ + sec = time.tv64; + do_div(sec, 1000);/* usec */ + usec = do_div(sec, 1000000);/* sec and usec */ + + + if (pstRTBuf->ring_buf[_imgo_d_].active) { + _dmaport = 2; + rt_dma = _imgo_d_; + } else if (pstRTBuf->ring_buf[_rrzo_d_].active) { + _dmaport = 3; + rt_dma = _rrzo_d_; + } else + LOG_ERR("no main dma port opened at SOF_D\n"); + + /* chk this frame have EOF or not,dynamic dma port chk */ + if (p1_fbc[_dmaport].Bits.FB_NUM == p1_fbc[_dmaport].Bits.FBC_CNT) { + sof_pass1done[1] = 1; +#ifdef _rtbc_buf_que_2_0_ + /* ISP_LostP1Done_ErrHandle(_imgo_d_); */ + /* ISP_LostP1Done_ErrHandle(_rrzo_d_); */ + /* IRQ_LOG_KEEPER(_IRQ_D,m_CurrentPPB,_LOG_INF,"lost p1d_Done ErrHandle\n"); */ +#endif + lost_pass1_d_done_cnt++; + if (2 == lost_pass1_d_done_cnt) { + /* check any buffer is ready? */ + for (k = 0; k < pstRTBuf->ring_buf[rt_dma].total_count; k++) { + if (ISP_RTBC_BUF_FILLED == pstRTBuf->ring_buf[rt_dma].data[k].bFilled) { + /**/ for (j = 0; j < ISP_IRQ_USER_MAX; j++) + IspInfo.IrqInfo.Status[j][ISP_IRQ_TYPE_INT_P1_ST_D] |= + ISP_IRQ_P1_STATUS_D_PASS1_DON_ST; + + lost_pass1_d_done_cnt = 0; + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "raw-D buf rdy but lost pass1 done, wakeup by sof!!"); + break; + } + } + } + IRQ_LOG_KEEPER(_IRQ_D, m_CurrentPPB, _LOG_INF, "Lost p1_d done_%d (0x%x): ", + sof_count[_PASS1_D], d_cur_v_cnt); + } else { + sof_pass1done[1] = 0; + if (p1_fbc[_dmaport].Bits.FB_NUM == (p1_fbc[_dmaport].Bits.FBC_CNT - 1)) + sof_pass1done[1] = 2; + } +#ifdef _rtbc_buf_que_2_0_ + + if (1 == mFwRcnt.bLoadBaseAddr[_IRQ_D]) { + if (pstRTBuf->ring_buf[_imgo_d_].active) { + IRQ_LOG_KEEPER(_IRQ_D, m_CurrentPPB, _LOG_INF, "p1_d_%d:wr2Phy: ", + _imgo_d_); + ISP_WR32(ISP_REG_ADDR_IMGO_D_BASE_ADDR, + pstRTBuf->ring_buf[_imgo_d_].data[pstRTBuf-> + ring_buf[_imgo_d_]. + start].base_pAddr); + } + if (pstRTBuf->ring_buf[_rrzo_d_].active) { + IRQ_LOG_KEEPER(_IRQ_D, m_CurrentPPB, _LOG_INF, "p1_d_%d:wr2Phy: ", + _rrzo_d_); + ISP_WR32(ISP_REG_ADDR_RRZO_D_BASE_ADDR, + pstRTBuf->ring_buf[_rrzo_d_].data[pstRTBuf-> + ring_buf[_rrzo_d_]. + start].base_pAddr); + } + mFwRcnt.bLoadBaseAddr[_IRQ_D] = 0; + } + /* equal case is for clear curidx */ + for (z = 0; z <= mFwRcnt.curIdx[_IRQ_D]; z++) { + if (1 == mFwRcnt.INC[_IRQ_D][z]) { + mFwRcnt.INC[_IRQ_D][z] = 0; + p1_fbc[2].Bits.RCNT_INC = 1; + ISP_WR32(ISP_REG_ADDR_IMGO_D_FBC, p1_fbc[2].Reg_val); + p1_fbc[3].Bits.RCNT_INC = 1; + ISP_WR32(ISP_REG_ADDR_RRZO_D_FBC, p1_fbc[3].Reg_val); + if (IspInfo.DebugMask & ISP_DBG_INT) + IRQ_LOG_KEEPER(_IRQ_D, m_CurrentPPB, _LOG_INF, + "p1_d:RCNT_INC: "); + } else { + mFwRcnt.curIdx[_IRQ_D] = 0; + break; + } + } +#endif + + if (IspInfo.DebugMask & ISP_DBG_INT) { + CQ_RTBC_FBC _fbc_chk[2]; /* can chk fbc status compare to p1_fbc. */ + /* (the difference is the timing of reading) */ + + _fbc_chk[0].Reg_val = ISP_RD32(ISP_REG_ADDR_IMGO_D_FBC); + _fbc_chk[1].Reg_val = ISP_RD32(ISP_REG_ADDR_RRZO_D_FBC); + + + if (g1stSof[_IRQ_D]) { + m_sec_d = sec; + m_usec_d = usec; + } + + IRQ_LOG_KEEPER(_IRQ_D, m_CurrentPPB, _LOG_INF, + "P1_D_SOF_%d_%d(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x)_int_us:%d\n", + sof_count[_PASS1_D], d_cur_v_cnt, + (unsigned int)(_fbc_chk[0].Reg_val), + (unsigned int)(_fbc_chk[1].Reg_val), + ISP_RD32(ISP_REG_ADDR_IMGO_D_BASE_ADDR), + ISP_RD32(ISP_REG_ADDR_RRZO_D_BASE_ADDR), + ISP_RD32(ISP_INNER_REG_ADDR_IMGO_D_YSIZE), + ISP_RD32(ISP_INNER_REG_ADDR_RRZO_D_YSIZE), + ISP_RD32(ISP_REG_ADDR_TG2_MAGIC_0), + (MUINT32)((sec*1000000 + usec) - (1000000*m_sec_d+m_usec_d))); + + /* keep current time */ + m_sec_d = sec; + m_usec_d = usec; + + /* 1 port is enough */ + if (pstRTBuf->ring_buf[_imgo_d_].active) { + if (_fbc_chk[0].Bits.WCNT != p1_fbc[2].Bits.WCNT) + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "imgo_d:SW ISR right on next hw p1_done(0x%x_0x%x)\n", + _fbc_chk[0].Reg_val, p1_fbc[0].Reg_val); + } else if (pstRTBuf->ring_buf[_rrzo_d_].active) { + if (_fbc_chk[1].Bits.WCNT != p1_fbc[3].Bits.WCNT) + IRQ_LOG_KEEPER(_IRQ, m_CurrentPPB, _LOG_INF, + "rrzo_d:SW ISR right on next hw p1_done(0x%x_0x%x)\n", + _fbc_chk[1].Reg_val, p1_fbc[1].Reg_val); + } + } +/*-- get time at sof beginning for shrink log --*/ +/* unsigned long long sec;*/ +/* unsigned long usec;*/ +/* ktime_t time;*/ + /* */ + time = ktime_get(); /* ns */ + sec = time.tv64; + do_div(sec, 1000); /* usec */ + usec = do_div(sec, 1000000); /* sec and usec */ + /* update SOF time stamp for eis user(need match with the time stamp in image header) */ + IspInfo.IrqInfo.LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST_D][12] = + (unsigned int)(sec); + IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST_D][12] = + (unsigned int)(usec); + IspInfo.IrqInfo.LastestSigTime_usec[ISP_IRQ_TYPE_INT_P1_ST_D][0] = + (unsigned int)(sec); + IspInfo.IrqInfo.LastestSigTime_sec[ISP_IRQ_TYPE_INT_P1_ST_D][0] = + (unsigned int)(usec); + IspInfo.IrqInfo.Eismeta[ISP_IRQ_TYPE_INT_P1_ST_D][gEismetaWIdx_D]. + tLastSOF2P1done_sec = (unsigned int)(sec); + IspInfo.IrqInfo.Eismeta[ISP_IRQ_TYPE_INT_P1_ST_D][gEismetaWIdx_D]. + tLastSOF2P1done_usec = (unsigned int)(usec); + gEismetaInSOF_D = 1; + gEismetaWIdx_D = ((gEismetaWIdx_D + 1) % EISMETA_RINGSIZE); + /* */ + if (sof_pass1done[1] == 1) + ISP_SOF_Buf_Get(_IRQ_D, p1_fbc, (MUINT32 *)curr_pa, sec, usec, MTRUE); + else + ISP_SOF_Buf_Get(_IRQ_D, p1_fbc, (MUINT32 *)curr_pa, sec, usec, MFALSE); + } + /* */ + /* make sure isr sequence r all done after this status switch */ + + for (j = 0; j < ISP_IRQ_TYPE_AMOUNT; j++) { + for (i = 0; i < IRQ_USER_NUM_MAX; i++) { + /* 1. update interrupt status to all users */ + IspInfo.IrqInfo.Status[i][j] |= (IrqStatus[j] & IspInfo.IrqInfo.Mask[j]); + + /* 2. update signal occuring time and passed by signal count */ + if (IspInfo.IrqInfo.MarkedFlag[i][j] & IspInfo.IrqInfo.Mask[j]) { + for (k = 0; k < 32; k++) { + if ((IrqStatus[j] & IspInfo.IrqInfo.Mask[j]) & (1 << k)) { + idx = my_get_pow_idx(1 << k); + IspInfo.IrqInfo.LastestSigTime_usec[j][idx] = + (unsigned int)time_frmb.tv_usec; + IspInfo.IrqInfo.LastestSigTime_sec[j][idx] = + (unsigned int)time_frmb.tv_sec; + IspInfo.IrqInfo.PassedBySigCnt[i][j][k]++; + } + } + } else { /* no any interrupt is not marked and in read mask in this irq type */ + } + + } + } + spin_unlock(&(IspInfo.SpinLockIrq[_IRQ])); +#if 0 /* in order to keep the isr stability. */ + if (MFALSE == bSlowMotion) { + if (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] & ISP_IRQ_P1_STATUS_D_PASS1_DON_ST) + LOG_INF("2D_%d\n", + (sof_count[_PASS1]) ? (sof_count[_PASS1] - + 1) : (sof_count[_PASS1])); + + if (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] & ISP_IRQ_P1_STATUS_D_SOF1_INT_ST) + LOG_INF("2S_%d\n", + (sof_count[_PASS1]) ? (sof_count[_PASS1] - + 1) : (sof_count[_PASS1])); + + } +#endif + /* dump log during spin lock */ +#ifdef ISR_LOG_ON + /* IRQ_LOG_PRINTER(_IRQ,m_CurrentPPB,_LOG_INF); */ + /* IRQ_LOG_PRINTER(_IRQ,m_CurrentPPB,_LOG_ERR); */ + + /* IRQ_LOG_PRINTER(_IRQ_D,m_CurrentPPB,_LOG_INF); */ + /* IRQ_LOG_PRINTER(_IRQ_D,m_CurrentPPB,_LOG_ERR); */ +#endif + /* */ + wake_up_interruptible_all((wait_queue_head_t *)&IspInfo.WaitQueueHead); + + if ((IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & (ISP_IRQ_P1_STATUS_PASS1_DON_ST)) || + (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & (ISP_IRQ_P1_STATUS_SOF1_INT_ST)) || + (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] & (ISP_IRQ_P1_STATUS_D_PASS1_DON_ST)) || + (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] & (ISP_IRQ_P1_STATUS_D_SOF1_INT_ST))) { + tasklet_schedule(&isp_tasklet); + } + /* Work queue. It is interruptible, so there can be "Sleep" in work queue function. */ + if ((IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & (ISP_IRQ_P1_STATUS_VS1_INT_ST)) & + (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] & (ISP_IRQ_P1_STATUS_D_VS1_INT_ST))) { + IspInfo.TimeLog.Vd = ISP_JiffiesToMs(jiffies); + schedule_work(&IspInfo.ScheduleWorkVD); + tasklet_schedule(&IspTaskletVD); + } + /* Tasklet. It is uninterrupted, so there can NOT be "Sleep" in tasklet function. */ + if ((IrqStatus[ISP_IRQ_TYPE_INT_P1_ST] & (ISP_IRQ_P1_STATUS_EXPDON1_ST)) & + (IrqStatus[ISP_IRQ_TYPE_INT_P1_ST_D] & (ISP_IRQ_P1_STATUS_D_EXPDON1_ST))) { + IspInfo.TimeLog.Expdone = ISP_JiffiesToMs(jiffies); + schedule_work(&IspInfo.ScheduleWorkEXPDONE); + tasklet_schedule(&IspTaskletEXPDONE); + } + + /* LOG_DBG("- X."); */ + /* */ + return IRQ_HANDLED; +} + + +static void ISP_TaskletFunc(unsigned long data) +{ + if (MFALSE == bSlowMotion) { + IRQ_LOG_PRINTER(_IRQ, m_CurrentPPB, _LOG_INF); + IRQ_LOG_PRINTER(_IRQ, m_CurrentPPB, _LOG_ERR); + + IRQ_LOG_PRINTER(_IRQ_D, m_CurrentPPB, _LOG_INF); + IRQ_LOG_PRINTER(_IRQ_D, m_CurrentPPB, _LOG_ERR); + } else { + IRQ_LOG_PRINTER(_IRQ, m_CurrentPPB, _LOG_INF); + IRQ_LOG_PRINTER(_IRQ, m_CurrentPPB, _LOG_ERR); + + IRQ_LOG_PRINTER(_IRQ_D, m_CurrentPPB, _LOG_INF); + IRQ_LOG_PRINTER(_IRQ_D, m_CurrentPPB, _LOG_ERR); + } +} +/******************************************************************************* +* +********************************************************************************/ +static inline MUINT32 IMEMdbg_GetState(unsigned int userpid) +{ + MUINT32 ret = 0; + int i = 0; + /* */ + spin_lock(&(SpinLockImemDump)); + for (i = 0; i < PROCESS_MAX; i++) { + if (P2_IMEM_DBGList[i].processID == userpid) { + ret = P2_IMEM_DBGList[i].bImemDbgDump; + break; + } + } + spin_unlock(&(SpinLockImemDump)); + /* */ + return ret; +} +static MINT32 ISP_WaitImemDump(unsigned int userpid) +{ + MINT32 Ret = 0; + int i = 0, retWait; + int find = -1; + + /*check*/ + spin_lock(&(SpinLockImemDump)); + for (i = 0; i < PROCESS_MAX; i++) { + if (P2_IMEM_DBGList[i].processID == 0x0) { + P2_IMEM_DBGList[i].processID = userpid; + find = i; + break; + } + } + spin_unlock(&(SpinLockImemDump)); + if (find == -1) { + LOG_ERR("too many process (0x%x)", userpid); + return 0; + } + LOG_DBG("enter ISP_WaitImemDump,(0x%x)", userpid); + + retWait = wait_event_interruptible( + WaitQueueHead_ImemDbgDump, + IMEMdbg_GetState(userpid)); + + spin_lock(&(SpinLockImemDump)); + P2_IMEM_DBGList[i].bImemDbgDump = false; + /*reset for that process from imem uninit*/ + P2_IMEM_DBGList[i].processID = 0x0; + P2_IMEM_DBGList[i].bImemDbgDumpDone = false; + spin_unlock(&(SpinLockImemDump)); + LOG_DBG("leave ISP_WaitImemDump,(0x%x)", userpid); + + return Ret; +} + + +static MINT32 ISP_WriteImemDump(unsigned int userpid, int type) +{ + MINT32 Ret = 0; + int i = 0; + int find = -1; + + LOG_DBG("enter ISP_WriteImemDump,(%d)", type); + spin_lock(&(SpinLockImemDump)); + for (i = 0; i < PROCESS_MAX; i++) { + if (P2_IMEM_DBGList[i].processID == userpid) { + find = i; + break; + } + } + spin_unlock(&(SpinLockImemDump)); + if (find == -1) { + /*the same process will enter twice, it could do nothing at 2nd*/ + /*LOG_ERR("too many process (0x%x)", userpid);*/ + LOG_DBG("leave ISP_WriteImemDump -(%d)", type); + return 0; + } + switch (type) { + case 0: + /* trigger for information dump */ + spin_lock(&(SpinLockImemDump)); + P2_IMEM_DBGList[i].bImemDbgDump = true; + spin_unlock(&(SpinLockImemDump)); + wake_up_interruptible_all((wait_queue_head_t *)&WaitQueueHead_ImemDbgDump); + break; + case 1: + /* information dump done */ + spin_lock(&(SpinLockImemDump)); + P2_IMEM_DBGList[i].bImemDbgDumpDone = true; + spin_unlock(&(SpinLockImemDump)); + wake_up_interruptible_all((wait_queue_head_t *)&WaitQueueHead_ImemDbgDumpDone); + break; + default: + break; + } + LOG_DBG("leave ISP_WriteImemDump,(%d)", type); + return Ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static long ISP_ioctl(struct file *pFile, unsigned int Cmd, unsigned long Param) +{ + MINT32 Ret = 0; + /* */ + MBOOL HoldEnable = MFALSE; + MUINT32 DebugFlag[2] = { 0 }, pid = 0; + ISP_REG_IO_STRUCT RegIo; + ISP_HOLD_TIME_ENUM HoldTime; + ISP_WAIT_IRQ_STRUCT IrqInfo; + ISP_READ_IRQ_STRUCT ReadIrq; + ISP_CLEAR_IRQ_STRUCT ClearIrq; + ISP_USER_INFO_STRUCT *pUserInfo; + ISP_ED_BUFQUE_STRUCT edQueBuf; + MUINT32 regScenInfo_value = 0xa5a5a5a5; + MINT32 burstQNum; + MUINT32 wakelock_ctrl; + unsigned long flags; /* old: MUINT32 flags;*//* FIX to avoid build warning */ + int userKey = -1; + int type = 0; + ISP_REGISTER_USERKEY_STRUCT RegUserKey; + /* */ + if (pFile->private_data == NULL) { + LOG_WRN("private_data is NULL,(process, pid, tgid)=(%s, %d, %d)", current->comm, + current->pid, current->tgid); + return -EFAULT; + } + /* */ + pUserInfo = (ISP_USER_INFO_STRUCT *) (pFile->private_data); + /* */ + switch (Cmd) { + case ISP_WAKELOCK_CTRL: + { + if (copy_from_user(&wakelock_ctrl, (void *)Param, sizeof(MUINT32)) != 0) { + LOG_ERR("get ISP_WAKELOCK_CTRL from user fail"); + Ret = -EFAULT; + } else { + if (wakelock_ctrl == 1) { /* Enable wakelock */ + if (g_bWaitLock == 0) { +#ifdef CONFIG_PM_WAKELOCKS + __pm_stay_awake(&isp_wake_lock); +#else + wake_lock(&isp_wake_lock); +#endif + g_bWaitLock = 1; + LOG_DBG("wakelock enable!!\n"); + } + } else { /* Disable wakelock */ + if (g_bWaitLock == 1) { +#ifdef CONFIG_PM_WAKELOCKS + __pm_relax(&isp_wake_lock); +#else + wake_unlock(&isp_wake_lock); +#endif + g_bWaitLock = 0; + LOG_DBG("wakelock diable!!\n"); + } + } + } + + } + break; + case ISP_GET_DROP_FRAME: + if (copy_from_user(&DebugFlag[0], (void *)Param, sizeof(MUINT32)) != 0) { + LOG_ERR("get irq from user fail"); + Ret = -EFAULT; + } else { + switch (DebugFlag[0]) { + case _IRQ: + spin_lock_irqsave(&(IspInfo.SpinLockIrq[_IRQ]), flags); + DebugFlag[1] = sof_pass1done[0]; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[_IRQ]), flags); + break; + case _IRQ_D: + spin_lock_irqsave(&(IspInfo.SpinLockIrq[_IRQ]), flags); + DebugFlag[1] = sof_pass1done[1]; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[_IRQ]), flags); + break; + case _CAMSV_IRQ: + spin_lock_irqsave(&(IspInfo.SpinLockIrq[_CAMSV_IRQ]), flags); + DebugFlag[1] = gSof_camsvdone[0]; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[_CAMSV_IRQ]), flags); + break; + case _CAMSV_D_IRQ: + spin_lock_irqsave(&(IspInfo.SpinLockIrq[_CAMSV_D_IRQ]), flags); + DebugFlag[1] = gSof_camsvdone[1]; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[_CAMSV_D_IRQ]), flags); + break; + default: + LOG_ERR("err TG(0x%x)\n", DebugFlag[0]); + Ret = -EFAULT; + break; + } + if (copy_to_user((void *)Param, &DebugFlag[1], sizeof(MUINT32)) != 0) { + LOG_ERR("copy to user fail"); + Ret = -EFAULT; + } + } + break; + case ISP_GET_INT_ERR: + if (copy_to_user((void *)Param, (void *)g_ISPIntErr, sizeof(MUINT32) * _IRQ_MAX) != 0) + LOG_ERR("get int err fail\n"); + + break; + case ISP_GET_DMA_ERR: + if (copy_to_user((void *)Param, &g_DmaErr_p1[0], sizeof(MUINT32) * nDMA_ERR) != 0) + LOG_ERR("get dma_err fail\n"); + + break; + case ISP_GET_CUR_SOF: + if (copy_from_user(&DebugFlag[0], (void *)Param, sizeof(MUINT32)) != 0) { + LOG_ERR("get cur sof from user fail"); + Ret = -EFAULT; + } else { + /* TG sof update at expo_done, causes potential timing issue, using sw sof */ + switch (DebugFlag[0]) { + case _IRQ: + /* DebugFlag[1] = ((ISP_RD32(ISP_REG_ADDR_TG_INTER_ST)&0x00FF0000)>>16); */ + DebugFlag[1] = sof_count[_PASS1]; + break; + case _IRQ_D: + /* DebugFlag[1] = ((ISP_RD32(ISP_REG_ADDR_TG2_INTER_ST)&0x00FF0000)>>16); */ + DebugFlag[1] = sof_count[_PASS1_D]; + break; + case _CAMSV_IRQ: + /* DebugFlag[1] = ((ISP_RD32(ISP_REG_ADDR_CAMSV_TG_INTER_ST)&0x00FF0000)>>16); */ + DebugFlag[1] = sof_count[_CAMSV]; + break; + case _CAMSV_D_IRQ: + /* DebugFlag[1] = ((ISP_RD32(ISP_REG_ADDR_CAMSV_TG2_INTER_ST)&0x00FF0000)>>16); */ + DebugFlag[1] = sof_count[_CAMSV_D]; + break; + default: + LOG_ERR("err TG(0x%x)\n", DebugFlag[0]); + Ret = -EFAULT; + break; + } + } + if (copy_to_user((void *)Param, &DebugFlag[1], sizeof(MUINT32)) != 0) { + LOG_ERR("copy to user fail"); + Ret = -EFAULT; + } + break; + case ISP_RESET_CAM_P1: + spin_lock(&(IspInfo.SpinLockIsp)); + ISP_Reset(ISP_REG_SW_CTL_RST_CAM_P1); + spin_unlock(&(IspInfo.SpinLockIsp)); + break; + case ISP_RESET_CAM_P2: + spin_lock(&(IspInfo.SpinLockIsp)); + ISP_Reset(ISP_REG_SW_CTL_RST_CAM_P2); + spin_unlock(&(IspInfo.SpinLockIsp)); + break; + case ISP_RESET_CAMSV: + spin_lock(&(IspInfo.SpinLockIsp)); + ISP_Reset(ISP_REG_SW_CTL_RST_CAMSV); + spin_unlock(&(IspInfo.SpinLockIsp)); + break; + case ISP_RESET_CAMSV2: + spin_lock(&(IspInfo.SpinLockIsp)); + ISP_Reset(ISP_REG_SW_CTL_RST_CAMSV2); + spin_unlock(&(IspInfo.SpinLockIsp)); + break; + case ISP_RESET_BUF: + spin_lock_bh(&(IspInfo.SpinLockHold)); + ISP_ResetBuf(); + spin_unlock_bh(&(IspInfo.SpinLockHold)); + break; + case ISP_READ_REGISTER: + if (copy_from_user(&RegIo, (void *)Param, sizeof(ISP_REG_IO_STRUCT)) == 0) { + Ret = ISP_ReadReg(&RegIo); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + case ISP_WRITE_REGISTER: + if (copy_from_user(&RegIo, (void *)Param, sizeof(ISP_REG_IO_STRUCT)) == 0) { + Ret = ISP_WriteReg(&RegIo); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + case ISP_HOLD_REG_TIME: + if (copy_from_user(&HoldTime, (void *)Param, sizeof(ISP_HOLD_TIME_ENUM)) == 0) { + spin_lock(&(IspInfo.SpinLockIsp)); + Ret = ISP_SetHoldTime(HoldTime); + spin_unlock(&(IspInfo.SpinLockIsp)); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + case ISP_HOLD_REG: + if (copy_from_user(&HoldEnable, (void *)Param, sizeof(MBOOL)) == 0) { + Ret = ISP_EnableHoldReg(HoldEnable); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + case ISP_WAIT_IRQ: + if (copy_from_user(&IrqInfo, (void *)Param, sizeof(ISP_WAIT_IRQ_STRUCT)) == 0) { + /* */ + if ((IrqInfo.Type >= ISP_IRQ_TYPE_AMOUNT) || (IrqInfo.Type < 0)) { + Ret = -EFAULT; + LOG_ERR("invalid type(%d)", IrqInfo.Type); + goto EXIT; + } + if ((IrqInfo.UserNumber >= ISP_IRQ_USER_MAX) || (IrqInfo.UserNumber < 0)) { + LOG_ERR("errUserEnum(%d)", IrqInfo.UserNumber); + Ret = -EFAULT; + goto EXIT; + } + + /* check v1/v3 */ + if (IrqInfo.UserNumber > 0) { /* v1 flow */ + Ret = ISP_WaitIrq(&IrqInfo); + } +#if 1 + else { /* isp driver related operation in v1 is redirected */ + /* to v3 flow cuz userNumer and default UserKey are 0 */ + /* v3 */ + if ((IrqInfo.UserInfo.Type >= ISP_IRQ_TYPE_AMOUNT) + || (IrqInfo.UserInfo.Type < 0)) { + Ret = -EFAULT; + LOG_ERR("invalid type(%d)", IrqInfo.UserInfo.Type); + goto EXIT; + } + if ((IrqInfo.UserInfo.UserKey >= IRQ_USER_NUM_MAX) + || ((IrqInfo.UserInfo.UserKey <= 0) + && (IrqInfo.UserNumber == 0))) { + /* LOG_ERR("invalid userKey(%d), max(%d)", */ + /* WaitIrq_FrmB.UserInfo.UserKey,IRQ_USER_NUM_MAX); */ + userKey = 0; + } + if ((IrqInfo.UserInfo.UserKey > 0) + && (IrqInfo.UserInfo.UserKey < IRQ_USER_NUM_MAX)) { + /* avoid other users in v3 do not set UserNumber and */ + /* UserNumber is set as 0 in isp driver */ + userKey = IrqInfo.UserInfo.UserKey; + } + IrqInfo.UserInfo.UserKey = userKey; + Ret = ISP_WaitIrq_v3(&IrqInfo); + } +#endif + if (copy_to_user((void *)Param, &IrqInfo, sizeof(ISP_WAIT_IRQ_STRUCT)) != 0) { + LOG_ERR("copy_to_user failed\n"); + Ret = -EFAULT; + } + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + case ISP_READ_IRQ: + if (copy_from_user(&ReadIrq, (void *)Param, sizeof(ISP_READ_IRQ_STRUCT)) == 0) { + eISPIrq irqT = _IRQ; + LOG_DBG("ISP_READ_IRQ Type(%d)", ReadIrq.Type); + if ((ReadIrq.Type >= ISP_IRQ_TYPE_AMOUNT) || (ReadIrq.Type < 0)) { + Ret = -EFAULT; + LOG_ERR("invalid type(%d)", ReadIrq.Type); + goto EXIT; + } + /* */ + if ((ReadIrq.UserNumber >= ISP_IRQ_USER_MAX) || (ReadIrq.UserNumber < 0)) { + LOG_ERR("errUserEnum(%d)", ReadIrq.UserNumber); + Ret = -EFAULT; + goto EXIT; + } + /* */ + switch (ReadIrq.Type) { + case ISP_IRQ_TYPE_INT_CAMSV: + irqT = _CAMSV_IRQ; + break; + case ISP_IRQ_TYPE_INT_CAMSV2: + irqT = _CAMSV_D_IRQ; + break; + default: + irqT = _IRQ; + break; + } + spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT]), flags); + ReadIrq.Status = IspInfo.IrqInfo.Status[ReadIrq.UserNumber][ReadIrq.Type]; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[irqT]), flags); + /* */ + if (copy_to_user((void *)Param, &ReadIrq, sizeof(ISP_READ_IRQ_STRUCT)) != 0) { + LOG_ERR("copy_to_user failed"); + Ret = -EFAULT; + } + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + case ISP_CLEAR_IRQ: + if (copy_from_user(&ClearIrq, (void *)Param, sizeof(ISP_CLEAR_IRQ_STRUCT)) == 0) { + eISPIrq irqT; + LOG_DBG("ISP_CLEAR_IRQ Type(%d)", ClearIrq.Type); + + if ((ClearIrq.Type >= ISP_IRQ_TYPE_AMOUNT) || (ClearIrq.Type < 0)) { + Ret = -EFAULT; + LOG_ERR("invalid type(%d)", ClearIrq.Type); + goto EXIT; + } + /* */ + if ((ClearIrq.UserNumber >= ISP_IRQ_USER_MAX) || (ClearIrq.UserNumber < 0)) { + LOG_ERR("errUserEnum(%d)", ClearIrq.UserNumber); + Ret = -EFAULT; + goto EXIT; + } + /* */ + switch (ClearIrq.Type) { + case ISP_IRQ_TYPE_INT_CAMSV: + irqT = _CAMSV_IRQ; + break; + case ISP_IRQ_TYPE_INT_CAMSV2: + irqT = _CAMSV_D_IRQ; + break; + default: + irqT = _IRQ; + break; + } + LOG_DBG("ISP_CLEAR_IRQ:Type(%d),Status(0x%08X),IrqStatus(0x%08X)", + ClearIrq.Type, ClearIrq.Status, + IspInfo.IrqInfo.Status[ClearIrq.UserNumber][ClearIrq.Type]); + spin_lock_irqsave(&(IspInfo.SpinLockIrq[irqT]), flags); + IspInfo.IrqInfo.Status[ClearIrq.UserNumber][ClearIrq.Type] &= + (~ClearIrq.Status); + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[irqT]), flags); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + /* */ + case ISP_REGISTER_IRQ_USER_KEY: + if (copy_from_user(&RegUserKey, (void *)Param, sizeof(ISP_REGISTER_USERKEY_STRUCT)) + == 0) { + userKey = ISP_REGISTER_IRQ_USERKEY(RegUserKey.userName); + RegUserKey.userKey = userKey; + if (copy_to_user + ((void *)Param, &RegUserKey, sizeof(ISP_REGISTER_USERKEY_STRUCT)) != 0) + LOG_ERR("copy_to_user failed\n"); + + if (RegUserKey.userKey < 0) { + LOG_ERR("query irq user key fail\n"); + Ret = -1; + } + } + break; + /* */ + case ISP_MARK_IRQ_REQUEST: + if (copy_from_user(&IrqInfo, (void *)Param, sizeof(ISP_WAIT_IRQ_STRUCT)) == 0) { + if ((IrqInfo.UserInfo.UserKey >= IRQ_USER_NUM_MAX) + || (IrqInfo.UserInfo.UserKey < 1)) { + LOG_ERR("invalid userKey(%d), max(%d)", IrqInfo.UserInfo.UserKey, + IRQ_USER_NUM_MAX); + Ret = -EFAULT; + break; + } + if ((IrqInfo.UserInfo.Type >= ISP_IRQ_TYPE_AMOUNT) + || (IrqInfo.UserInfo.Type < 0)) { + LOG_ERR("invalid type(%d), max(%d)", IrqInfo.UserInfo.Type, + ISP_IRQ_TYPE_AMOUNT); + Ret = -EFAULT; + break; + } + Ret = ISP_MARK_IRQ(IrqInfo); + } else { + LOG_ERR("ISP_MARK_IRQ, copy_from_user failed"); + Ret = -EFAULT; + } + break; + /* */ + case ISP_GET_MARK2QUERY_TIME: + if (copy_from_user(&IrqInfo, (void *)Param, sizeof(ISP_WAIT_IRQ_STRUCT)) == 0) { + if ((IrqInfo.UserInfo.UserKey >= IRQ_USER_NUM_MAX) + || (IrqInfo.UserInfo.UserKey < 1)) { + LOG_ERR("invalid userKey(%d), max(%d)", IrqInfo.UserInfo.UserKey, + IRQ_USER_NUM_MAX); + Ret = -EFAULT; + break; + } + if ((IrqInfo.UserInfo.Type >= ISP_IRQ_TYPE_AMOUNT) + || (IrqInfo.UserInfo.Type < 0)) { + LOG_ERR("invalid type(%d), max(%d)", IrqInfo.UserInfo.Type, + ISP_IRQ_TYPE_AMOUNT); + Ret = -EFAULT; + break; + } + Ret = ISP_GET_MARKtoQEURY_TIME(&IrqInfo); + /* */ + if (copy_to_user((void *)Param, &IrqInfo, sizeof(ISP_WAIT_IRQ_STRUCT)) != 0) { + LOG_ERR("copy_to_user failed"); + Ret = -EFAULT; + } + } else { + LOG_ERR("ISP_GET_MARK2QUERY_TIME, copy_from_user failed"); + Ret = -EFAULT; + } + break; + /* */ + case ISP_FLUSH_IRQ_REQUEST: + if (copy_from_user(&IrqInfo, (void *)Param, sizeof(ISP_WAIT_IRQ_STRUCT)) == 0) { + if (IrqInfo.UserNumber > 0) { /* v1 flow / v1 ISP_IRQ_USER_MAX */ + if ((IrqInfo.UserNumber >= ISP_IRQ_USER_MAX) + || (IrqInfo.UserNumber < 1)) { + LOG_ERR("invalid userNumber(%d), max(%d)", + IrqInfo.UserNumber, ISP_IRQ_USER_MAX); + Ret = -EFAULT; + break; + } + if ((IrqInfo.Type >= ISP_IRQ_TYPE_AMOUNT) || (IrqInfo.Type < 0)) { + LOG_ERR("invalid type(%d), max(%d)\n", IrqInfo.Type, + ISP_IRQ_TYPE_AMOUNT); + Ret = -EFAULT; + break; + } + /* check UserNumber */ + if ((IrqInfo.UserNumber != ISP_IRQ_USER_3A) && + (IrqInfo.UserNumber != ISP_IRQ_USER_EIS) && + (IrqInfo.UserNumber != ISP_IRQ_USER_VHDR)) { + LOG_ERR("invalid userNumber(%d)\n", IrqInfo.UserNumber); + Ret = -EFAULT; + break; + } + if (0 == (IrqInfo.Type | IrqFlush[IrqInfo.UserNumber])) { + LOG_ERR("UserNumber(%d), invalid type(%d)\n", + IrqInfo.UserNumber, IrqInfo.Type); + Ret = -EFAULT; + break; + } + LOG_INF("[FlushIrq]UserNumber(%d), type(%d), status(0x08%X)\n", + IrqInfo.UserNumber, IrqInfo.Type, IrqInfo.Status); + Ret = ISP_FLUSH_IRQ(IrqInfo); + } else { /* v3 flow /v3 IRQ_USER_NUM_MAX */ + if ((IrqInfo.UserInfo.UserKey >= IRQ_USER_NUM_MAX) + || (IrqInfo.UserInfo.UserKey < 1)) { + LOG_ERR("invalid userKey(%d), max(%d)\n", + IrqInfo.UserInfo.UserKey, IRQ_USER_NUM_MAX); + Ret = -EFAULT; + break; + } + if ((IrqInfo.UserInfo.Type >= ISP_IRQ_TYPE_AMOUNT) + || (IrqInfo.UserInfo.Type < 0)) { + LOG_ERR("invalid type(%d), max(%d)\n", + IrqInfo.UserInfo.Type, ISP_IRQ_TYPE_AMOUNT); + Ret = -EFAULT; + break; + } + if (0 == + (IrqInfo.UserInfo. + Type | IrqFlush_v3[IrqInfo.UserInfo.UserKey])) { + LOG_ERR("User_%s(%d), invalid type(%d)", + IrqUserKey_UserInfo[IrqInfo.UserInfo.UserKey]. + userName, IrqInfo.UserInfo.UserKey, + IrqInfo.UserInfo.Type); + Ret = -EFAULT; + break; + } + LOG_INF("User_%s(%d), type(%d)", + IrqUserKey_UserInfo[IrqInfo.UserInfo.UserKey].userName, + IrqInfo.UserInfo.UserKey, IrqInfo.UserInfo.Type); + Ret = ISP_FLUSH_IRQ_V3(IrqInfo); + } + } + break; + /* */ + case ISP_ED_QUEBUF_CTRL: + if (copy_from_user(&edQueBuf, (void *)Param, sizeof(ISP_ED_BUFQUE_STRUCT)) == 0) { + edQueBuf.processID = pUserInfo->Pid; + Ret = ISP_ED_BufQue_CTRL_FUNC(edQueBuf); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + /* */ + case ISP_UPDATE_REGSCEN: + if (copy_from_user(®ScenInfo_value, (void *)Param, sizeof(MUINT32)) == 0) { + spin_lock((spinlock_t *)(&SpinLockRegScen)); + g_regScen = regScenInfo_value; + spin_unlock((spinlock_t *)(&SpinLockRegScen)); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + case ISP_QUERY_REGSCEN: + spin_lock((spinlock_t *)(&SpinLockRegScen)); + regScenInfo_value = g_regScen; + spin_unlock((spinlock_t *)(&SpinLockRegScen)); + /* */ + if (copy_to_user((void *)Param, ®ScenInfo_value, sizeof(MUINT32)) != 0) { + LOG_ERR("copy_to_user failed"); + Ret = -EFAULT; + } + break; + /* */ + case ISP_UPDATE_BURSTQNUM: + if (copy_from_user(&burstQNum, (void *)Param, sizeof(MINT32)) == 0) { + spin_lock((spinlock_t *)(&SpinLockRegScen)); + P2_Support_BurstQNum = burstQNum; + spin_unlock((spinlock_t *)(&SpinLockRegScen)); + LOG_DBG("new BurstQNum(%d)", P2_Support_BurstQNum); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + case ISP_QUERY_BURSTQNUM: + spin_lock((spinlock_t *)(&SpinLockRegScen)); + burstQNum = P2_Support_BurstQNum; + spin_unlock((spinlock_t *)(&SpinLockRegScen)); + /* */ + if (copy_to_user((void *)Param, &burstQNum, sizeof(MUINT32)) != 0) { + LOG_ERR("copy_to_user failed"); + Ret = -EFAULT; + } + break; + /* */ + case ISP_DUMP_REG: + Ret = ISP_DumpReg(); + break; + case ISP_DEBUG_FLAG: + if (copy_from_user(DebugFlag, (void *)Param, sizeof(MUINT32) * 2) == 0) { + MUINT32 lock_key = _IRQ_MAX; + + if (DebugFlag[1] >= _IRQ_MAX) { + LOG_ERR("unsupported module:0x%x\n", DebugFlag[1]); + Ret = -EFAULT; + break; + } + if (DebugFlag[1] == _IRQ_D) + lock_key = _IRQ; + else + lock_key = DebugFlag[1]; + spin_lock_irqsave(&(IspInfo.SpinLockIrq[lock_key]), flags); + IspInfo.DebugMask = DebugFlag[0]; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[lock_key]), flags); + /* LOG_DBG("FBC kernel debug level = %x\n",IspInfo.DebugMask); */ + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; +#ifdef ISP_KERNEL_MOTIFY_SINGAL_TEST + case ISP_SET_USER_PID: + if (copy_from_user(&pid, (void *)Param, sizeof(MUINT32)) == 0) { + spin_lock(&(IspInfo.SpinLockIsp)); + getTaskInfo((pid_t) pid); + + sendSignal(); + + LOG_DBG("[ISP_KERNEL_MOTIFY_SINGAL_TEST]:0x08%x ", pid); + spin_unlock(&(IspInfo.SpinLockIsp)); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; +#endif + case ISP_BUFFER_CTRL: + Ret = ISP_Buf_CTRL_FUNC(Param); + break; + case ISP_REF_CNT_CTRL: + Ret = ISP_REF_CNT_CTRL_FUNC(Param); + break; + case ISP_DUMP_ISR_LOG: + if (copy_from_user(DebugFlag, (void *)Param, sizeof(MUINT32)) == 0) { + MUINT32 currentPPB = m_CurrentPPB; + MUINT32 lock_key = _IRQ_MAX; + + if (DebugFlag[0] >= _IRQ_MAX) { + LOG_ERR("unsupported module:0x%x\n", DebugFlag[0]); + Ret = -EFAULT; + break; + } + if (DebugFlag[0] == _IRQ_D) + lock_key = _IRQ; + else + lock_key = DebugFlag[0]; + spin_lock_irqsave(&(IspInfo.SpinLockIrq[lock_key]), flags); + m_CurrentPPB = (m_CurrentPPB + 1) % LOG_PPNUM; + spin_unlock_irqrestore(&(IspInfo.SpinLockIrq[lock_key]), flags); + + IRQ_LOG_PRINTER(DebugFlag[0], currentPPB, _LOG_INF); + IRQ_LOG_PRINTER(DebugFlag[0], currentPPB, _LOG_ERR); + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; +#ifdef T_STAMP_2_0 + case ISP_SET_FPS: + if (copy_from_user(DebugFlag, (void *)Param, sizeof(MUINT32)) == 0) { + if (m_T_STAMP.fps == 0) { + m_T_STAMP.fps = DebugFlag[0]; + m_T_STAMP.interval_us = 1000000 / m_T_STAMP.fps; + m_T_STAMP.compensation_us = + 1000000 - (m_T_STAMP.interval_us * m_T_STAMP.fps); + if (m_T_STAMP.fps > 90) { + bSlowMotion = MTRUE; + LOG_INF("slow motion enable:%d", m_T_STAMP.fps); + } + } + } else { + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; +#endif + case ISP_WAIT_DUMPIMEM: + Ret = ISP_WaitImemDump(pUserInfo->Pid); + break; + case ISP_WRITE_DUMPIMEM: + if (copy_from_user(&type, (void *)Param, sizeof(MINT32)) == 0) { + Ret = ISP_WriteImemDump(pUserInfo->Pid, type); + } else{ + LOG_ERR("copy_from_user failed"); + Ret = -EFAULT; + } + break; + default: + LOG_ERR("Unknown Cmd(%d)", Cmd); + Ret = -EPERM; + break; + } + /* */ +EXIT: + if (Ret != 0) + LOG_ERR("Fail, Cmd(%d), Pid(%d), (process, pid, tgid)=(%s, %d, %d)", Cmd, + pUserInfo->Pid, current->comm, current->pid, current->tgid); + + /* */ + return Ret; +} + +#ifdef CONFIG_COMPAT + +/******************************************************************************* +* +********************************************************************************/ +static int compat_get_isp_read_register_data(compat_ISP_REG_IO_STRUCT __user *data32, + ISP_REG_IO_STRUCT __user *data) +{ + compat_uint_t count; + compat_uptr_t uptr; + int err; + + err = get_user(uptr, &data32->pData); + err |= put_user(compat_ptr(uptr), &data->pData); + err |= get_user(count, &data32->Count); + err |= put_user(count, &data->Count); + return err; +} + +static int compat_put_isp_read_register_data(compat_ISP_REG_IO_STRUCT __user *data32, + ISP_REG_IO_STRUCT __user *data) +{ + compat_uint_t count; +/* compat_uptr_t uptr;*/ + int err = 0; + /* Assume data pointer is unchanged. */ + /* err = get_user(compat_ptr(uptr), &data->pData); */ + /* err |= put_user(uptr, &data32->pData); */ + err |= get_user(count, &data->Count); + err |= put_user(count, &data32->Count); + return err; +} + +static int compat_get_isp_waitirq_data(compat_ISP_WAIT_IRQ_STRUCT __user *data32, + ISP_WAIT_IRQ_STRUCT __user *data) +{ + compat_uint_t tmp; + compat_uptr_t uptr; + ISP_IRQ_USER_STRUCT isp_irq_user_tmp; + ISP_IRQ_TIME_STRUCT isp_irq_time_tmp; + ISP_EIS_META_STRUCT isp_eis_meta_tmp; + int err; + + err = get_user(tmp, &data32->Clear); + err |= put_user(tmp, &data->Clear); + err |= get_user(tmp, &data32->Type); + err |= put_user(tmp, &data->Type); + err |= get_user(tmp, &data32->Status); + err |= put_user(tmp, &data->Status); + err |= get_user(tmp, &data32->UserNumber); + err |= put_user(tmp, &data->UserNumber); + err |= get_user(tmp, &data32->Timeout); + err |= put_user(tmp, &data->Timeout); + err |= get_user(uptr, &data32->UserName); + err |= put_user(compat_ptr(uptr), &data->UserName); + err |= get_user(tmp, &data32->irq_TStamp); + err |= put_user(tmp, &data->irq_TStamp); + err |= get_user(tmp, &data32->bDumpReg); + err |= put_user(tmp, &data->bDumpReg); + /* structure copy */ + err |= copy_from_user(&isp_irq_user_tmp, &data32->UserInfo, sizeof(ISP_IRQ_USER_STRUCT)); + err |= + copy_to_user((void *)&data->UserInfo, &isp_irq_user_tmp, sizeof(ISP_IRQ_USER_STRUCT)); + err |= copy_from_user(&isp_irq_time_tmp, &data32->TimeInfo, sizeof(ISP_IRQ_TIME_STRUCT)); + err |= + copy_to_user((void *)&data->TimeInfo, &isp_irq_time_tmp, sizeof(ISP_IRQ_TIME_STRUCT)); + err |= copy_from_user(&isp_eis_meta_tmp, &data32->EisMeta, sizeof(ISP_EIS_META_STRUCT)); + err |= copy_to_user((void *)&data->EisMeta, &isp_eis_meta_tmp, sizeof(ISP_EIS_META_STRUCT)); + err |= get_user(tmp, &data32->SpecUser); + err |= put_user(tmp, &data->SpecUser); + return err; +} + +static int compat_put_isp_waitirq_data(compat_ISP_WAIT_IRQ_STRUCT __user *data32, + ISP_WAIT_IRQ_STRUCT __user *data) +{ + compat_uint_t tmp; +/* compat_uptr_t uptr;*/ + ISP_IRQ_USER_STRUCT isp_irq_user_tmp; + ISP_IRQ_TIME_STRUCT isp_irq_time_tmp; + ISP_EIS_META_STRUCT isp_eis_meta_tmp; + int err; + + err = get_user(tmp, &data->Clear); + err |= put_user(tmp, &data32->Clear); + err |= get_user(tmp, &data->Type); + err |= put_user(tmp, &data32->Type); + err |= get_user(tmp, &data->Status); + err |= put_user(tmp, &data32->Status); + err |= get_user(tmp, &data->UserNumber); + err |= put_user(tmp, &data32->UserNumber); + err |= get_user(tmp, &data->Timeout); + err |= put_user(tmp, &data32->Timeout); + /* Assume data pointer is unchanged. */ + /* err |= get_user(uptr, &data->UserName); */ + /* err |= put_user(uptr, &data32->UserName); */ + err |= get_user(tmp, &data->irq_TStamp); + err |= put_user(tmp, &data32->irq_TStamp); + err |= get_user(tmp, &data->bDumpReg); + err |= put_user(tmp, &data32->bDumpReg); + + /* structure copy */ + err |= copy_from_user(&isp_irq_user_tmp, &data->UserInfo, sizeof(ISP_IRQ_USER_STRUCT)); + err |= + copy_to_user((void *)&data32->UserInfo, &isp_irq_user_tmp, sizeof(ISP_IRQ_USER_STRUCT)); + err |= copy_from_user(&isp_irq_time_tmp, &data->TimeInfo, sizeof(ISP_IRQ_TIME_STRUCT)); + err |= + copy_to_user((void *)&data32->TimeInfo, &isp_irq_time_tmp, sizeof(ISP_IRQ_TIME_STRUCT)); + err |= copy_from_user(&isp_eis_meta_tmp, &data->EisMeta, sizeof(ISP_EIS_META_STRUCT)); + err |= + copy_to_user((void *)&data32->EisMeta, &isp_eis_meta_tmp, sizeof(ISP_EIS_META_STRUCT)); + err |= get_user(tmp, &data->SpecUser); + err |= put_user(tmp, &data32->SpecUser); + return err; +} + +static int compat_get_isp_readirq_data(compat_ISP_READ_IRQ_STRUCT __user *data32, + ISP_READ_IRQ_STRUCT __user *data) +{ + compat_uint_t tmp; + int err; + + err = get_user(tmp, &data32->Type); + err |= put_user(tmp, &data->Type); + err |= get_user(tmp, &data32->UserNumber); + err |= put_user(tmp, &data->UserNumber); + err |= get_user(tmp, &data32->Status); + err |= put_user(tmp, &data->Status); + return err; +} + + +static int compat_put_isp_readirq_data(compat_ISP_READ_IRQ_STRUCT __user *data32, + ISP_READ_IRQ_STRUCT __user *data) +{ + compat_uint_t tmp; + int err; + + err = get_user(tmp, &data->Type); + err |= put_user(tmp, &data32->Type); + err |= get_user(tmp, &data->UserNumber); + err |= put_user(tmp, &data32->UserNumber); + err |= get_user(tmp, &data->Status); + err |= put_user(tmp, &data32->Status); + return err; +} + +static int compat_get_isp_buf_ctrl_struct_data(compat_ISP_BUFFER_CTRL_STRUCT __user *data32, + ISP_BUFFER_CTRL_STRUCT __user *data) +{ + compat_uint_t tmp; + compat_uptr_t uptr; + int err; + + err = get_user(tmp, &data32->ctrl); + err |= put_user(tmp, &data->ctrl); + err |= get_user(tmp, &data32->buf_id); + err |= put_user(tmp, &data->buf_id); + err |= get_user(uptr, &data32->data_ptr); + err |= put_user(compat_ptr(uptr), &data->data_ptr); + err |= get_user(uptr, &data32->ex_data_ptr); + err |= put_user(compat_ptr(uptr), &data->ex_data_ptr); + err |= get_user(uptr, &data32->pExtend); + err |= put_user(compat_ptr(uptr), &data->pExtend); + + return err; +} + +static int compat_put_isp_buf_ctrl_struct_data(compat_ISP_BUFFER_CTRL_STRUCT __user *data32, + ISP_BUFFER_CTRL_STRUCT __user *data) +{ + compat_uint_t tmp; +/* compat_uptr_t uptr;*/ + int err; + + err = get_user(tmp, &data->ctrl); + err |= put_user(tmp, &data32->ctrl); + err |= get_user(tmp, &data->buf_id); + err |= put_user(tmp, &data32->buf_id); + /* Assume data pointer is unchanged. */ + /* err |= get_user(compat_ptr(uptr), &data->data_ptr); */ + /* err |= put_user(uptr, &data32->data_ptr); */ + /* err |= get_user(compat_ptr(uptr), &data->ex_data_ptr); */ + /* err |= put_user(uptr, &data32->ex_data_ptr); */ + /* err |= get_user(compat_ptr(uptr), &data->pExtend); */ + /* err |= put_user(uptr, &data32->pExtend); */ + + return err; +} + +static int compat_get_isp_ref_cnt_ctrl_struct_data(compat_ISP_REF_CNT_CTRL_STRUCT __user *data32, + ISP_REF_CNT_CTRL_STRUCT __user *data) +{ + compat_uint_t tmp; + compat_uptr_t uptr; + int err; + + err = get_user(tmp, &data32->ctrl); + err |= put_user(tmp, &data->ctrl); + err |= get_user(tmp, &data32->id); + err |= put_user(tmp, &data->id); + err |= get_user(uptr, &data32->data_ptr); + err |= put_user(compat_ptr(uptr), &data->data_ptr); + + return err; +} + +static int compat_put_isp_ref_cnt_ctrl_struct_data(compat_ISP_REF_CNT_CTRL_STRUCT __user *data32, + ISP_REF_CNT_CTRL_STRUCT __user *data) +{ + compat_uint_t tmp; +/* compat_uptr_t uptr;*/ + int err; + + err = get_user(tmp, &data->ctrl); + err |= put_user(tmp, &data32->ctrl); + err |= get_user(tmp, &data->id); + err |= put_user(tmp, &data32->id); + /* Assume data pointer is unchanged. */ + /* err |= get_user(compat_ptr(uptr), &data->data_ptr); */ + /* err |= put_user(uptr, &data32->data_ptr); */ + + return err; +} + + +static int compat_get_isp_register_userkey_struct_data(compat_ISP_REGISTER_USERKEY_STRUCT __user * + data32, + ISP_REGISTER_USERKEY_STRUCT __user *data) +{ + compat_uint_t tmp; + compat_uptr_t uptr; + int err; + + err = get_user(tmp, &data32->userKey); + err |= put_user(tmp, &data->userKey); + err |= get_user(uptr, &data32->userName); + err |= put_user(compat_ptr(uptr), &data->userName); + + return err; +} + +static int compat_put_isp_register_userkey_struct_data(compat_ISP_REGISTER_USERKEY_STRUCT __user * + data32, + ISP_REGISTER_USERKEY_STRUCT __user *data) +{ + compat_uint_t tmp; +/* compat_uptr_t uptr;*/ + int err; + + err = get_user(tmp, &data->userKey); + err |= put_user(tmp, &data32->userKey); + /* Assume data pointer is unchanged. */ + /* err |= get_user(uptr, &data->userName); */ + /* err |= put_user(uptr, &data32->userName); */ + + return err; +} + +static long ISP_ioctl_compat(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + case COMPAT_ISP_READ_REGISTER: + { + compat_ISP_REG_IO_STRUCT __user *data32; + ISP_REG_IO_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_read_register_data(data32, data); + if (err) { + LOG_INF("compat_get_isp_read_register_data error!!!\n"); + return err; + } + ret = + filp->f_op->unlocked_ioctl(filp, ISP_READ_REGISTER, + (unsigned long)data); + err = compat_put_isp_read_register_data(data32, data); + if (err) { + LOG_INF("compat_put_isp_read_register_data error!!!\n"); + return err; + } + return ret; + } + case COMPAT_ISP_WRITE_REGISTER: + { + compat_ISP_REG_IO_STRUCT __user *data32; + ISP_REG_IO_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_read_register_data(data32, data); + if (err) { + LOG_INF("COMPAT_ISP_WRITE_REGISTER error!!!\n"); + return err; + } + ret = + filp->f_op->unlocked_ioctl(filp, ISP_WRITE_REGISTER, + (unsigned long)data); + return ret; + } + case COMPAT_ISP_WAIT_IRQ: + { + compat_ISP_WAIT_IRQ_STRUCT __user *data32; + ISP_WAIT_IRQ_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_waitirq_data(data32, data); + if (err) { + LOG_INF("compat_get_isp_waitirq_data error!!!\n"); + return err; + } + ret = filp->f_op->unlocked_ioctl(filp, ISP_WAIT_IRQ, (unsigned long)data); + err = compat_put_isp_waitirq_data(data32, data); + if (err) { + LOG_INF("compat_put_isp_waitirq_data error!!!\n"); + return err; + } + return ret; + } + case COMPAT_ISP_MARK_IRQ_REQUEST: + { + compat_ISP_WAIT_IRQ_STRUCT __user *data32; + ISP_WAIT_IRQ_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_waitirq_data(data32, data); + if (err) { + LOG_INF("compat_get_ISP_MARK_IRQ_REQUEST error!!!\n"); + return err; + } + ret = + filp->f_op->unlocked_ioctl(filp, ISP_MARK_IRQ_REQUEST, + (unsigned long)data); + err = compat_put_isp_waitirq_data(data32, data); + if (err) { + LOG_INF("compat_put_ISP_MARK_IRQ_REQUEST error!!!\n"); + return err; + } + return ret; + } + case COMPAT_ISP_GET_MARK2QUERY_TIME: + { + compat_ISP_WAIT_IRQ_STRUCT __user *data32; + ISP_WAIT_IRQ_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_waitirq_data(data32, data); + if (err) { + LOG_INF("compat_get_ISP_GET_MARK2QUERY_TIME error!!!\n"); + return err; + } + ret = + filp->f_op->unlocked_ioctl(filp, ISP_GET_MARK2QUERY_TIME, + (unsigned long)data); + err = compat_put_isp_waitirq_data(data32, data); + if (err) { + LOG_INF("compat_put_ISP_GET_MARK2QUERY_TIME error!!!\n"); + return err; + } + return ret; + } + case COMPAT_ISP_FLUSH_IRQ_REQUEST: + { + compat_ISP_WAIT_IRQ_STRUCT __user *data32; + ISP_WAIT_IRQ_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_waitirq_data(data32, data); + if (err) { + LOG_INF("compat_get_ISP_FLUSH_IRQ_REQUEST error!!!\n"); + return err; + } + ret = + filp->f_op->unlocked_ioctl(filp, ISP_FLUSH_IRQ_REQUEST, + (unsigned long)data); + err = compat_put_isp_waitirq_data(data32, data); + if (err) { + LOG_INF("compat_put_ISP_FLUSH_IRQ_REQUEST error!!!\n"); + return err; + } + return ret; + } + case COMPAT_ISP_READ_IRQ: + { + compat_ISP_READ_IRQ_STRUCT __user *data32; + ISP_READ_IRQ_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_readirq_data(data32, data); + if (err) { + LOG_INF("compat_get_isp_readirq_data error!!!\n"); + return err; + } + ret = filp->f_op->unlocked_ioctl(filp, ISP_READ_IRQ, (unsigned long)data); + err = compat_put_isp_readirq_data(data32, data); + if (err) { + LOG_INF("compat_put_isp_readirq_data error!!!\n"); + return err; + } + + return ret; + } + case COMPAT_ISP_BUFFER_CTRL: + { + compat_ISP_BUFFER_CTRL_STRUCT __user *data32; + ISP_BUFFER_CTRL_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_buf_ctrl_struct_data(data32, data); + if (err) + return err; + if (err) { + LOG_INF("compat_get_isp_buf_ctrl_struct_data error!!!\n"); + return err; + } + ret = + filp->f_op->unlocked_ioctl(filp, ISP_BUFFER_CTRL, (unsigned long)data); + err = compat_put_isp_buf_ctrl_struct_data(data32, data); + + if (err) { + LOG_INF("compat_put_isp_buf_ctrl_struct_data error!!!\n"); + return err; + } + return ret; + } + case COMPAT_ISP_REF_CNT_CTRL: + { + compat_ISP_REF_CNT_CTRL_STRUCT __user *data32; + ISP_REF_CNT_CTRL_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_ref_cnt_ctrl_struct_data(data32, data); + if (err) { + LOG_INF("compat_get_isp_ref_cnt_ctrl_struct_data error!!!\n"); + return err; + } + ret = + filp->f_op->unlocked_ioctl(filp, ISP_REF_CNT_CTRL, (unsigned long)data); + err = compat_put_isp_ref_cnt_ctrl_struct_data(data32, data); + if (err) { + LOG_INF("compat_put_isp_ref_cnt_ctrl_struct_data error!!!\n"); + return err; + } + return ret; + } + case COMPAT_ISP_REGISTER_IRQ_USER_KEY: + { + compat_ISP_REGISTER_USERKEY_STRUCT __user *data32; + ISP_REGISTER_USERKEY_STRUCT __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_isp_register_userkey_struct_data(data32, data); + if (err) { + LOG_INF("compat_get_isp_register_userkey_struct_data error!!!\n"); + return err; + } + ret = + filp->f_op->unlocked_ioctl(filp, ISP_REGISTER_IRQ_USER_KEY, + (unsigned long)data); + err = compat_put_isp_register_userkey_struct_data(data32, data); + if (err) { + LOG_INF("compat_put_isp_register_userkey_struct_data error!!!\n"); + return err; + } + return ret; + } + case COMPAT_ISP_DEBUG_FLAG: + { + /* compat_ptr(arg) will convert the arg */ + ret = + filp->f_op->unlocked_ioctl(filp, ISP_DEBUG_FLAG, + (unsigned long)compat_ptr(arg)); + return ret; + } + case COMPAT_ISP_GET_INT_ERR: + { + /* compat_ptr(arg) will convert the arg */ + ret = + filp->f_op->unlocked_ioctl(filp, ISP_GET_INT_ERR, + (unsigned long)compat_ptr(arg)); + return ret; + } + case COMPAT_ISP_GET_DMA_ERR: + { + /* compat_ptr(arg) will convert the arg */ + ret = + filp->f_op->unlocked_ioctl(filp, ISP_GET_DMA_ERR, + (unsigned long)compat_ptr(arg)); + return ret; + } + case ISP_GET_CUR_SOF: + case ISP_GET_DROP_FRAME: + case ISP_RESET_CAM_P1: + case ISP_RESET_CAM_P2: + case ISP_RESET_CAMSV: + case ISP_RESET_CAMSV2: + case ISP_RESET_BUF: + case ISP_HOLD_REG_TIME: + /* enum must check. */ + case ISP_HOLD_REG: + /* mbool value must check. */ + case ISP_CLEAR_IRQ: + /* structure (no pointer) */ + case ISP_REGISTER_IRQ: + case ISP_UNREGISTER_IRQ: + case ISP_ED_QUEBUF_CTRL: + /* structure (no pointer) */ + case ISP_UPDATE_REGSCEN: + case ISP_QUERY_REGSCEN: + case ISP_UPDATE_BURSTQNUM: + case ISP_QUERY_BURSTQNUM: + case ISP_DUMP_REG: + case ISP_SET_USER_PID: + /* structure use unsigned long , but the code is unsigned int */ + case ISP_SET_FPS: + case ISP_DUMP_ISR_LOG: + case ISP_WAKELOCK_CTRL: + case ISP_WAIT_DUMPIMEM: + case ISP_WRITE_DUMPIMEM: + return filp->f_op->unlocked_ioctl(filp, cmd, arg); + default: + return -ENOIOCTLCMD; + /* return ISP_ioctl(filep, cmd, arg); */ + } +} + +#endif + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_open(struct inode *pInode, struct file *pFile) +{ + MINT32 Ret = 0; + MUINT32 i; + int q = 0, p = 0; + ISP_USER_INFO_STRUCT *pUserInfo; + + LOG_INF("- E. UserCount: %d.", IspInfo.UserCount); + /* */ + spin_lock(&(IspInfo.SpinLockIspRef)); + /* */ + /* LOG_DBG("UserCount(%d)",IspInfo.UserCount); */ + /* */ + pFile->private_data = NULL; + pFile->private_data = kmalloc(sizeof(ISP_USER_INFO_STRUCT), GFP_ATOMIC); + if (pFile->private_data == NULL) { + LOG_DBG("ERROR: kmalloc failed, (process, pid, tgid)=(%s, %d, %d)", current->comm, + current->pid, current->tgid); + Ret = -ENOMEM; + } else { + pUserInfo = (ISP_USER_INFO_STRUCT *) pFile->private_data; + pUserInfo->Pid = current->pid; + pUserInfo->Tid = current->tgid; + } + /* */ + if (IspInfo.UserCount > 0) { + IspInfo.UserCount++; + spin_unlock(&(IspInfo.SpinLockIspRef)); + LOG_DBG("Curr UserCount(%d), (process, pid, tgid)=(%s, %d, %d), users exist", + IspInfo.UserCount, current->comm, current->pid, current->tgid); + goto EXIT; + } else { + IspInfo.UserCount++; + /*Move P2_IMEM_DBGList here to fix re-setting after other initializations*/ + for (i = 0; i < PROCESS_MAX; i++) { + spin_lock(&(SpinLockImemDump)); + P2_IMEM_DBGList[i].processID = 0x0; + P2_IMEM_DBGList[i].bImemDbgDump = false; + P2_IMEM_DBGList[i].bImemDbgDumpDone = false; + spin_unlock(&(SpinLockImemDump)); + } + for (i = 0; i < ISP_REF_CNT_ID_MAX; i++) + atomic_set(&g_imem_ref_cnt[i], 0); + spin_unlock(&(IspInfo.SpinLockIspRef)); + + LOG_DBG("Curr UserCount(%d), (process, pid, tgid)=(%s, %d, %d), first user, %d", + IspInfo.UserCount, current->comm, current->pid, current->tgid, i); + } + + /* do wait queue head init when re-enter in camera */ + EDBufQueRemainNodeCnt = 0; + spin_lock((spinlock_t *)(&SpinLockRegScen)); + P2_Support_BurstQNum = 1; + spin_unlock((spinlock_t *)(&SpinLockRegScen)); + /* */ + for (i = 0; i < IRQ_USER_NUM_MAX; i++) { + FirstUnusedIrqUserKey = 1; + memset((void *)IrqUserKey_UserInfo[i].userName, '\0', USERKEY_STR_LEN); + IrqUserKey_UserInfo[i].userKey = -1; + /* flushIRQ v3 */ + IrqFlush_v3[i] = 0x0; + } + + /* flushIRQ v1 */ + for (i = 0; i < ISP_IRQ_USER_MAX; i++) + IrqFlush[i] = 0x0; + + IrqFlush[ISP_IRQ_USER_3A] = + (ISP_IRQ_P1_STATUS_VS1_INT_ST | ISP_IRQ_P1_STATUS_D_VS1_INT_ST | + ISP_IRQ_P1_STATUS_AF_DON_ST | ISP_IRQ_P1_STATUS_D_AF_DON_ST); + IrqFlush[ISP_IRQ_USER_EIS] = + (ISP_IRQ_P1_STATUS_VS1_INT_ST | ISP_IRQ_P1_STATUS_D_VS1_INT_ST | + ISP_IRQ_P1_STATUS_PASS1_DON_ST | ISP_IRQ_P1_STATUS_D_PASS1_DON_ST); + IrqFlush[ISP_IRQ_USER_VHDR] = + (ISP_IRQ_P1_STATUS_VS1_INT_ST | ISP_IRQ_P1_STATUS_D_VS1_INT_ST | + ISP_IRQ_P1_STATUS_PASS1_DON_ST | ISP_IRQ_P1_STATUS_D_PASS1_DON_ST); + /* */ + spin_lock(&(SpinLockEDBufQueList)); + for (i = 0; i < _MAX_SUPPORT_P2_FRAME_NUM_; i++) { + P2_EDBUF_RingList[i].processID = 0x0; + P2_EDBUF_RingList[i].callerID = 0x0; + P2_EDBUF_RingList[i].p2dupCQIdx = -1; + P2_EDBUF_RingList[i].bufSts = ISP_ED_BUF_STATE_NONE; + } + P2_EDBUF_RList_FirstBufIdx = 0; + P2_EDBUF_RList_CurBufIdx = 0; + P2_EDBUF_RList_LastBufIdx = -1; + /* */ + for (i = 0; i < _MAX_SUPPORT_P2_PACKAGE_NUM_; i++) { + P2_EDBUF_MgrList[i].processID = 0x0; + P2_EDBUF_MgrList[i].callerID = 0x0; + P2_EDBUF_MgrList[i].p2dupCQIdx = -1; + P2_EDBUF_MgrList[i].dequedNum = 0; + } + P2_EDBUF_MList_FirstBufIdx = 0; + P2_EDBUF_MList_LastBufIdx = -1; + spin_unlock(&(SpinLockEDBufQueList)); + /* */ + spin_lock((spinlock_t *)(&SpinLockRegScen)); + g_regScen = 0xa5a5a5a5; + spin_unlock((spinlock_t *)(&SpinLockRegScen)); + /* */ + IspInfo.BufInfo.Read.pData = (MUINT8 *) kmalloc(ISP_BUF_SIZE, GFP_ATOMIC); + IspInfo.BufInfo.Read.Size = ISP_BUF_SIZE; + IspInfo.BufInfo.Read.Status = ISP_BUF_STATUS_EMPTY; + if (IspInfo.BufInfo.Read.pData == NULL) { + LOG_DBG("ERROR: BufRead kmalloc failed"); + Ret = -ENOMEM; + goto EXIT; + } + /* */ + if (!ISP_BufWrite_Alloc()) { + LOG_DBG("ERROR: BufWrite kmalloc failed"); + Ret = -ENOMEM; + goto EXIT; + } + /* */ + atomic_set(&(IspInfo.HoldInfo.HoldEnable), 0); + atomic_set(&(IspInfo.HoldInfo.WriteEnable), 0); + + /* */ + for (q = 0; q < IRQ_USER_NUM_MAX; q++) { + for (i = 0; i < ISP_IRQ_TYPE_AMOUNT; i++) { + IspInfo.IrqInfo.Status[q][i] = 0; + IspInfo.IrqInfo.MarkedFlag[q][i] = 0; + for (p = 0; p < 32; p++) { + IspInfo.IrqInfo.MarkedTime_sec[q][i][p] = 0; + IspInfo.IrqInfo.MarkedTime_usec[q][i][p] = 0; + IspInfo.IrqInfo.PassedBySigCnt[q][i][p] = 0; + IspInfo.IrqInfo.LastestSigTime_sec[i][p] = 0; + IspInfo.IrqInfo.LastestSigTime_usec[i][p] = 0; + } + if (i < ISP_IRQ_TYPE_INT_STATUSX) { + for (p = 0; p < EISMETA_RINGSIZE; p++) { + IspInfo.IrqInfo.Eismeta[i][p].tLastSOF2P1done_sec = 0; + IspInfo.IrqInfo.Eismeta[i][p].tLastSOF2P1done_usec = 0; + } + } + } + } + gEismetaRIdx = 0; + gEismetaWIdx = 0; + gEismetaInSOF = 0; + gEismetaRIdx_D = 0; + gEismetaWIdx_D = 0; + gEismetaInSOF_D = 0; + /* */ + /* */ + for (i = 0; i < ISP_CALLBACK_AMOUNT; i++) + IspInfo.Callback[i].Func = NULL; + + /* */ +#ifdef KERNEL_LOG + IspInfo.DebugMask = (ISP_DBG_INT | ISP_DBG_BUF_CTRL); +#endif + /* kernellog limit to (current+150) lines per second */ + pr_detect_count = get_detect_count(); + i = pr_detect_count + 150; + set_detect_count(i); +EXIT: + if (Ret < 0) { + if (IspInfo.BufInfo.Read.pData != NULL) { + kfree(IspInfo.BufInfo.Read.pData); + IspInfo.BufInfo.Read.pData = NULL; + } + ISP_BufWrite_Free(); + } else { + /* Enable clock. + * 1. clkmgr: G_u4EnableClockCount=0, call clk_enable/disable + * 2. CCF: call clk_enable/disable every time + */ + ISP_EnableClock(MTRUE); + LOG_DBG("isp open G_u4EnableClockCount: %d", G_u4EnableClockCount); + + /* DVFS HALT ENABLE + HRT engine DMA port: imgo/rrzo/aao/lcso/esfko/imgo_s/bpci/bpci_d + */ + ISP_WR32(ISP_IMGSYS_BASE + 0x120, 0x33F); + ISP_WR32(ISP_IMGSYS_BASE + 0x124, 0x0); + } + + /* LOG_DBG("Before spm_disable_sodi()."); */ + /* Disable sodi (Multi-Core Deep Idle). */ + + +#if 0 /* _mt6593fpga_dvt_use_ */ + spm_disable_sodi(); +#endif + + LOG_INF("- X. Ret: %d. UserCount: %d.", Ret, IspInfo.UserCount); + return Ret; + +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_release(struct inode *pInode, struct file *pFile) +{ + ISP_USER_INFO_STRUCT *pUserInfo; + MUINT32 Reg; + MUINT32 i = 0; + LOG_INF("- E. UserCount: %d.", IspInfo.UserCount); + /* */ + + /* */ + /* LOG_DBG("UserCount(%d)",IspInfo.UserCount); */ + /* */ + if (pFile->private_data != NULL) { + pUserInfo = (ISP_USER_INFO_STRUCT *) pFile->private_data; + kfree(pFile->private_data); + pFile->private_data = NULL; + } + /* */ + spin_lock(&(IspInfo.SpinLockIspRef)); + IspInfo.UserCount--; + if (IspInfo.UserCount > 0) { + spin_unlock(&(IspInfo.SpinLockIspRef)); + LOG_DBG("Curr UserCount(%d), (process, pid, tgid)=(%s, %d, %d), users exist", + IspInfo.UserCount, current->comm, current->pid, current->tgid); + goto EXIT; + } else { + spin_unlock(&(IspInfo.SpinLockIspRef)); + } + /* */ + LOG_DBG("Curr UserCount(%d), (process, pid, tgid)=(%s, %d, %d), last user", + IspInfo.UserCount, current->comm, current->pid, current->tgid); + /* kernel log limit back to default */ + set_detect_count(pr_detect_count); + /* reason of close vf is to make sure camera can serve regular after previous abnormal exit */ + Reg = ISP_RD32(ISP_REG_ADDR_TG_VF_CON); + Reg &= 0xfffffffE; /* close Vfinder */ + ISP_WR32(ISP_REG_ADDR_TG_VF_CON, Reg); + + Reg = ISP_RD32(ISP_REG_ADDR_TG2_VF_CON); + Reg &= 0xfffffffE; /* close Vfinder */ + ISP_WR32(ISP_REG_ADDR_TG2_VF_CON, Reg); + + /* why i add this wake_unlock here, because the Ap is not expected to be dead. */ + /* The driver must releae the wakelock, otherwise the system will not enter */ + /* the power-saving mode */ + if (g_bWaitLock == 1) { +#ifdef CONFIG_PM_WAKELOCKS + __pm_relax(&isp_wake_lock); +#else + wake_unlock(&isp_wake_lock); +#endif + g_bWaitLock = 0; + } + /* reset */ + /* */ + for (i = 0; i < IRQ_USER_NUM_MAX; i++) { + FirstUnusedIrqUserKey = 1; + memset((void *)IrqUserKey_UserInfo[i].userName, '\0', USERKEY_STR_LEN); + IrqUserKey_UserInfo[i].userKey = -1; + } + if (IspInfo.BufInfo.Read.pData != NULL) { + kfree(IspInfo.BufInfo.Read.pData); + IspInfo.BufInfo.Read.pData = NULL; + IspInfo.BufInfo.Read.Size = 0; + IspInfo.BufInfo.Read.Status = ISP_BUF_STATUS_EMPTY; + } + /* Reset MCLK */ + mMclk1User = 0; + mMclk2User = 0; + mMclk3User = 0; + ISP_WR32(ISP_ADDR + 0x4200, 0x00000001); + ISP_WR32(ISP_ADDR + 0x4600, 0x00000001); + ISP_WR32(ISP_ADDR + 0x4a00, 0x00000001); + LOG_DBG("ISP_MCLK1_EN Release"); + ISP_BufWrite_Free(); + /* */ +EXIT: + + /* */ + /* LOG_DBG("Before spm_enable_sodi()."); */ + /* Enable sodi (Multi-Core Deep Idle). */ + +#if 0 /* _mt6593fpga_dvt_use_ */ + spm_enable_sodi(); +#endif + + /* Disable clock. + * 1. clkmgr: G_u4EnableClockCount=0, call clk_enable/disable + * 2. CCF: call clk_enable/disable every time + */ + ISP_EnableClock(MFALSE); + LOG_DBG("isp release G_u4EnableClockCount: %d", G_u4EnableClockCount); + /* */ + LOG_INF("- X. UserCount: %d.", IspInfo.UserCount); + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +/* helper function, mmap's the kmalloc'd area which is physically contiguous */ +static MINT32 mmap_kmem(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + unsigned long length = 0; + + length = (vma->vm_end - vma->vm_start); + + /* check length - do not allow larger mappings than the number of + pages allocated */ + if (length > RT_BUF_TBL_NPAGES * PAGE_SIZE) + return -EIO; + + /* map the whole physically contiguous area in one piece */ + LOG_DBG("Vma->vm_pgoff(0x%lx),Vma->vm_start(0x%lx),Vma->vm_end(0x%lx),length(0x%lx)", + vma->vm_pgoff, vma->vm_start, vma->vm_end, length); + if (length > ISP_RTBUF_REG_RANGE) { + LOG_ERR("mmap range error! : length(0x%lx),ISP_RTBUF_REG_RANGE(0x%x)!", length, + ISP_RTBUF_REG_RANGE); + return -EAGAIN; + } + ret = + remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)pTbl_RTBuf) >> PAGE_SHIFT, + length, vma->vm_page_prot); + if (ret < 0) + return ret; + + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_mmap(struct file *pFile, struct vm_area_struct *pVma) +{ + unsigned long length = 0; + MUINT32 pfn = 0x0; + + LOG_DBG("- E."); + length = (pVma->vm_end - pVma->vm_start); + /* at offset RT_BUF_TBL_NPAGES we map the kmalloc'd area */ + if (pVma->vm_pgoff == RT_BUF_TBL_NPAGES) { + return mmap_kmem(pFile, pVma); + } else { + /* */ + pVma->vm_page_prot = pgprot_noncached(pVma->vm_page_prot); + LOG_DBG + ("pVma->vm_pgoff(0x%lx),phy(0x%lx),pVmapVma->vm_start(0x%lx),pVma->vm_end(0x%lx),length(0x%lx)", + pVma->vm_pgoff, pVma->vm_pgoff << PAGE_SHIFT, pVma->vm_start, pVma->vm_end, + length); + pfn = pVma->vm_pgoff << PAGE_SHIFT; + switch (pfn) { + case IMGSYS_BASE_ADDR: /* imgsys */ + if (length > ISP_REG_RANGE) { + LOG_ERR("mmap range error : length(0x%lx),ISP_REG_RANGE(0x%x)!", + length, ISP_REG_RANGE); + return -EAGAIN; + } + break; + case SENINF_BASE_ADDR: + if (length > SENINF_REG_RANGE) { + LOG_ERR + ("mmap range error : length(0x%lx),SENINF_REG_RANGE(0x%x)!", + length, SENINF_REG_RANGE); + return -EAGAIN; + } + break; + case PLL_BASE_ADDR: + if (length > PLL_RANGE) { + LOG_ERR("mmap range error : length(0x%lx),PLL_RANGE(0x%x)!", + length, PLL_RANGE); + return -EAGAIN; + } + break; + case MIPIRX_CONFIG_ADDR: + if (length > MIPIRX_CONFIG_RANGE) { + LOG_ERR + ("mmap range error : length(0x%lx),MIPIRX_CONFIG_RANGE(0x%x)!", + length, MIPIRX_CONFIG_RANGE); + return -EAGAIN; + } + break; + case MIPIRX_ANALOG_ADDR: + if (length > MIPIRX_ANALOG_RANGE) { + LOG_ERR + ("mmap range error : length(0x%lx),MIPIRX_ANALOG_RANGE(0x%x)!", + length, MIPIRX_ANALOG_RANGE); + return -EAGAIN; + } + break; + case GPIO_BASE_ADDR: + if (length > GPIO_RANGE) { + LOG_ERR("mmap range error : length(0x%lx),GPIO_RANGE(0x%x)!", + length, GPIO_RANGE); + return -EAGAIN; + } + break; + default: + LOG_ERR("Illegal starting HW addr for mmap!"); + return -EAGAIN; + break; + } + + if (remap_pfn_range + (pVma, pVma->vm_start, pVma->vm_pgoff, pVma->vm_end - pVma->vm_start, + pVma->vm_page_prot)) + return -EAGAIN; + + } + /* */ + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +#ifdef CONFIG_OF +struct cam_isp_device { + void __iomem *regs[ISP_CAM_BASEADDR_NUM]; + struct device *dev; + int irq[ISP_CAM_IRQ_IDX_NUM]; +}; + +static struct cam_isp_device *cam_isp_devs; +static int nr_camisp_devs; +#endif +static dev_t IspDevNo; +static struct cdev *pIspCharDrv; +static struct class *pIspClass; + +static const struct file_operations IspFileOper = { + .owner = THIS_MODULE, + .open = ISP_open, + .release = ISP_release, + /* .flush = mt_isp_flush, */ + .mmap = ISP_mmap, + .unlocked_ioctl = ISP_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ISP_ioctl_compat, +#endif +}; + +/******************************************************************************* +* +********************************************************************************/ +static inline void ISP_UnregCharDev(void) +{ + LOG_DBG("- E."); + /* */ + /* Release char driver */ + if (pIspCharDrv != NULL) { + cdev_del(pIspCharDrv); + pIspCharDrv = NULL; + } + /* */ + unregister_chrdev_region(IspDevNo, 1); +} + +/******************************************************************************* +* +********************************************************************************/ +static inline MINT32 ISP_RegCharDev(void) +{ + MINT32 Ret = 0; + /* */ + LOG_DBG("- E."); + /* */ + Ret = alloc_chrdev_region(&IspDevNo, 0, 1, ISP_DEV_NAME); + if (Ret < 0) { + LOG_ERR("alloc_chrdev_region failed, %d", Ret); + return Ret; + } + /* Allocate driver */ + pIspCharDrv = cdev_alloc(); + if (pIspCharDrv == NULL) { + LOG_ERR("cdev_alloc failed"); + Ret = -ENOMEM; + goto EXIT; + } + /* Attatch file operation. */ + cdev_init(pIspCharDrv, &IspFileOper); + /* */ + pIspCharDrv->owner = THIS_MODULE; + /* Add to system */ + Ret = cdev_add(pIspCharDrv, IspDevNo, 1); + if (Ret < 0) { + LOG_ERR("Attatch file operation failed, %d", Ret); + goto EXIT; + } + /* */ +EXIT: + if (Ret < 0) + ISP_UnregCharDev(); + + /* */ + + LOG_DBG("- X."); + return Ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_probe(struct platform_device *pDev) +{ + MINT32 Ret = 0; +/* + struct resource *pRes = NULL; +*/ + MINT32 i = 0; + MUINT8 n; + int new_count; +#ifdef CONFIG_OF + struct cam_isp_device *cam_isp_dev; +#endif + /* MINT32 j=0; */ + /* */ + LOG_INF("kk:+ ISP_probe\n"); + + LOG_DBG("- E."); + LOG_INF("ISP driver proble."); + /* Check platform_device parameters */ +#ifdef CONFIG_OF + + if (pDev == NULL) { + dev_err(&pDev->dev, "pDev is NULL"); + return -ENXIO; + } + + new_count = nr_camisp_devs + 1; + cam_isp_devs = + krealloc(cam_isp_devs, sizeof(struct cam_isp_device) * new_count, GFP_KERNEL); + if (!cam_isp_devs) { + dev_err(&pDev->dev, "Unable to allocate cam_isp_devs\n"); + return -ENOMEM; + } + + cam_isp_dev = &(cam_isp_devs[nr_camisp_devs]); + cam_isp_dev->dev = &pDev->dev; + + /* iomap registers and irq */ + for (i = 0; i < ISP_CAM_BASEADDR_NUM; i++) { + cam_isp_dev->regs[i] = of_iomap(pDev->dev.of_node, i); + if (!cam_isp_dev->regs[i]) { + dev_err(&pDev->dev, "Unable to ioremap registers, of_iomap fail, i=%d\n", + i); + return -ENOMEM; + } + + gISPSYS_Reg[i] = (unsigned long)(cam_isp_dev->regs[i]); + LOG_INF("DT, i=%d, map_addr=0x%lx\n", i, (unsigned long)cam_isp_dev->regs[i]); + } + + /* get IRQ ID and request IRQ */ + for (i = 0; i < ISP_CAM_IRQ_IDX_NUM; i++) { + cam_isp_dev->irq[i] = irq_of_parse_and_map(pDev->dev.of_node, i); + gISPSYS_Irq[i] = cam_isp_dev->irq[i]; + if (ISP_CAM0_IRQ_IDX == i) { + Ret = request_irq(cam_isp_dev->irq[i], (irq_handler_t) ISP_Irq_CAM, IRQF_TRIGGER_NONE, "ISP", NULL); + /* IRQF_TRIGGER_NONE dose not take effect here, real trigger mode set in dts file */ + } else if (ISP_CAMSV0_IRQ_IDX == i) { + Ret = request_irq(cam_isp_dev->irq[i], (irq_handler_t) ISP_Irq_CAMSV, IRQF_TRIGGER_NONE, "ISP", NULL); + /* IRQF_TRIGGER_NONE dose not take effect here, real trigger mode set in dts file */ + } else if (ISP_CAMSV1_IRQ_IDX == i) { + Ret = request_irq(cam_isp_dev->irq[i], (irq_handler_t) ISP_Irq_CAMSV2, IRQF_TRIGGER_NONE, "ISP", NULL); + /* IRQF_TRIGGER_NONE dose not take effect here, real trigger mode set in dts file */ + } + + if (Ret) { + dev_err(&pDev->dev, + "Unable to request IRQ, request_irq fail, i=%d, irq=%d\n", i, + cam_isp_dev->irq[i]); + return Ret; + } + LOG_INF("DT, i=%d, map_irq=%d\n", i, cam_isp_dev->irq[i]); + } + nr_camisp_devs = new_count; + + /* Register char driver */ + Ret = ISP_RegCharDev(); + if (Ret) { + dev_err(&pDev->dev, "register char failed"); + return Ret; + } + /* Mapping CAM_REGISTERS */ +#if 0 + for (i = 0; i < 1; i++) { /* NEED_TUNING_BY_CHIP. 1: Only one IORESOURCE_MEM type resource */ + /* in kernel\mt_devs.c\mt_resource_isp[]. */ + LOG_DBG("Mapping CAM_REGISTERS. i: %d.", i); + pRes = platform_get_resource(pDev, IORESOURCE_MEM, i); + if (pRes == NULL) { + dev_err(&pDev->dev, "platform_get_resource failed"); + Ret = -ENOMEM; + goto EXIT; + } + pRes = request_mem_region(pRes->start, pRes->end - pRes->start + 1, pDev->name); + if (pRes == NULL) { + dev_err(&pDev->dev, "request_mem_region failed"); + Ret = -ENOMEM; + goto EXIT; + } + } +#endif + +#ifdef CONFIG_MTK_CLKMGR +#else + /*CCF: Grab clock pointer (struct clk*) */ + isp_clk.CG_SCP_SYS_DIS = devm_clk_get(&pDev->dev, "CG_SCP_SYS_DIS"); + isp_clk.CG_DISP0_SMI_COMMON = devm_clk_get(&pDev->dev, "CG_DISP0_SMI_COMMON"); + isp_clk.CG_SCP_SYS_ISP = devm_clk_get(&pDev->dev, "CG_SCP_SYS_ISP"); + isp_clk.CG_IMAGE_CAM_SMI = devm_clk_get(&pDev->dev, "CG_IMAGE_CAM_SMI"); + isp_clk.CG_IMAGE_CAM_CAM = devm_clk_get(&pDev->dev, "CG_IMAGE_CAM_CAM"); + isp_clk.CG_IMAGE_SEN_TG = devm_clk_get(&pDev->dev, "CG_IMAGE_SEN_TG"); + isp_clk.CG_IMAGE_SEN_CAM = devm_clk_get(&pDev->dev, "CG_IMAGE_SEN_CAM"); + isp_clk.CG_IMAGE_CAM_SV = devm_clk_get(&pDev->dev, "CG_IMAGE_CAM_SV"); + isp_clk.CG_IMAGE_LARB2_SMI = devm_clk_get(&pDev->dev, "CG_IMAGE_LARB2_SMI"); + + if (IS_ERR(isp_clk.CG_SCP_SYS_DIS)) { + LOG_ERR("cannot get CG_SCP_SYS_DIS clock\n"); + return PTR_ERR(isp_clk.CG_SCP_SYS_DIS); + } + if (IS_ERR(isp_clk.CG_DISP0_SMI_COMMON)) { + LOG_ERR("cannot get CG_DISP0_SMI_COMMON clock\n"); + return PTR_ERR(isp_clk.CG_DISP0_SMI_COMMON); + } + if (IS_ERR(isp_clk.CG_SCP_SYS_ISP)) { + LOG_ERR("cannot get CG_SCP_SYS_ISP clock\n"); + return PTR_ERR(isp_clk.CG_SCP_SYS_ISP); + } + if (IS_ERR(isp_clk.CG_IMAGE_CAM_SMI)) { + LOG_ERR("cannot get CG_IMAGE_CAM_SMI clock\n"); + return PTR_ERR(isp_clk.CG_IMAGE_CAM_SMI); + } + if (IS_ERR(isp_clk.CG_IMAGE_CAM_CAM)) { + LOG_ERR("cannot get CG_IMAGE_CAM_CAM clock\n"); + return PTR_ERR(isp_clk.CG_IMAGE_CAM_CAM); + } + if (IS_ERR(isp_clk.CG_IMAGE_SEN_TG)) { + LOG_ERR("cannot get CG_IMAGE_SEN_TG clock\n"); + return PTR_ERR(isp_clk.CG_IMAGE_SEN_TG); + } + if (IS_ERR(isp_clk.CG_IMAGE_SEN_CAM)) { + LOG_ERR("cannot get CG_IMAGE_SEN_CAM clock\n"); + return PTR_ERR(isp_clk.CG_IMAGE_SEN_CAM); + } + if (IS_ERR(isp_clk.CG_IMAGE_CAM_SV)) { + LOG_ERR("cannot get CG_IMAGE_CAM_SV clock\n"); + return PTR_ERR(isp_clk.CG_IMAGE_CAM_SV); + } + if (IS_ERR(isp_clk.CG_IMAGE_LARB2_SMI)) { + LOG_ERR("cannot get CG_IMAGE_LARB2_SMI clock\n"); + return PTR_ERR(isp_clk.CG_IMAGE_LARB2_SMI); + } +#endif + + /* Create class register */ + pIspClass = class_create(THIS_MODULE, "ispdrv"); + if (IS_ERR(pIspClass)) { + Ret = PTR_ERR(pIspClass); + LOG_ERR("Unable to create class, err = %d", Ret); + return Ret; + } + /* FIXME: error handling */ + device_create(pIspClass, NULL, IspDevNo, NULL, ISP_DEV_NAME); + +#endif + /* */ + init_waitqueue_head((wait_queue_head_t *)&IspInfo.WaitQueueHead); + tasklet_init(&isp_tasklet, ISP_TaskletFunc, 0); + +#ifdef CONFIG_PM_WAKELOCKS + wakeup_source_init(&isp_wake_lock, "isp_lock_wakelock"); +#else + wake_lock_init(&isp_wake_lock, WAKE_LOCK_SUSPEND, "isp_lock_wakelock"); +#endif + + /* */ + INIT_WORK(&IspInfo.ScheduleWorkVD, ISP_ScheduleWork_VD); + INIT_WORK(&IspInfo.ScheduleWorkEXPDONE, ISP_ScheduleWork_EXPDONE); + /* */ + spin_lock_init(&(IspInfo.SpinLockIspRef)); + spin_lock_init(&(IspInfo.SpinLockIsp)); + + for (n = 0; n < _IRQ_MAX; n++) + spin_lock_init(&(IspInfo.SpinLockIrq[n])); + + spin_lock_init(&(IspInfo.SpinLockHold)); + spin_lock_init(&(IspInfo.SpinLockRTBC)); + spin_lock_init(&(IspInfo.SpinLockClock)); + /* */ + IspInfo.UserCount = 0; + IspInfo.HoldInfo.Time = ISP_HOLD_TIME_EXPDONE; + /* */ + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P1_ST] = ISP_REG_MASK_INT_P1_ST; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P1_ST2] = ISP_REG_MASK_INT_P1_ST2; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P1_ST_D] = ISP_REG_MASK_INT_P1_ST_D; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P1_ST2_D] = ISP_REG_MASK_INT_P1_ST2_D; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_P2_ST] = ISP_REG_MASK_INT_P2_ST; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_STATUSX] = ISP_REG_MASK_INT_STATUSX; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_STATUS2X] = ISP_REG_MASK_INT_STATUS2X; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_STATUS3X] = ISP_REG_MASK_INT_STATUS3X; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_SENINF1] = ISP_REG_MASK_INT_SENINF1; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_SENINF2] = ISP_REG_MASK_INT_SENINF2; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_SENINF3] = ISP_REG_MASK_INT_SENINF3; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_SENINF4] = ISP_REG_MASK_INT_SENINF4; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_CAMSV] = ISP_REG_MASK_CAMSV_ST; + IspInfo.IrqInfo.Mask[ISP_IRQ_TYPE_INT_CAMSV2] = ISP_REG_MASK_CAMSV2_ST; + /* */ + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_P1_ST] = ISP_REG_MASK_INT_P1_ST_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_P1_ST2] = ISP_REG_MASK_INT_P1_ST2_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_P1_ST_D] = ISP_REG_MASK_INT_P1_ST_D_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_P1_ST2_D] = ISP_REG_MASK_INT_P1_ST2_D_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_P2_ST] = ISP_REG_MASK_INT_P2_ST_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_STATUSX] = ISP_REG_MASK_INT_STATUSX_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_STATUS2X] = ISP_REG_MASK_INT_STATUS2X_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_STATUS3X] = ISP_REG_MASK_INT_STATUS3X_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_SENINF1] = ISP_REG_MASK_INT_SENINF1_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_SENINF2] = ISP_REG_MASK_INT_SENINF2_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_SENINF3] = ISP_REG_MASK_INT_SENINF3_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_SENINF4] = ISP_REG_MASK_INT_SENINF4_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_CAMSV] = ISP_REG_MASK_CAMSV_ST_ERR; + IspInfo.IrqInfo.ErrMask[ISP_IRQ_TYPE_INT_CAMSV2] = ISP_REG_MASK_CAMSV2_ST_ERR; + + /* enqueue/dequeue control in ihalpipe wrapper */ + init_waitqueue_head((wait_queue_head_t *)&WaitQueueHead_EDBuf_WaitDeque); + init_waitqueue_head((wait_queue_head_t *)&WaitQueueHead_EDBuf_WaitFrame); + init_waitqueue_head((wait_queue_head_t *)&WaitQueueHead_ImemDbgDump); + init_waitqueue_head((wait_queue_head_t *)&WaitQueueHead_ImemDbgDumpDone); + spin_lock_init((spinlock_t *)&(SpinLockImemDump)); + spin_lock_init((spinlock_t *)&(SpinLockEDBufQueList)); + spin_lock_init((spinlock_t *)&(SpinLockRegScen)); + spin_lock_init((spinlock_t *)&(SpinLock_UserKey)); + + /* Request CAM_ISP IRQ */ +#ifndef CONFIG_OF + /* FIXME */ + + /* if (request_irq(CAMERA_ISP_IRQ0_ID, (irq_handler_t)ISP_Irq, IRQF_TRIGGER_HIGH, "isp", NULL)) */ + + if (request_irq + (CAM0_IRQ_BIT_ID, (irq_handler_t) ISP_Irq_CAM, IRQF_TRIGGER_LOW, "ISP", NULL)) { + LOG_ERR("MT6593_CAM_IRQ_LINE IRQ LINE NOT AVAILABLE!!"); + goto EXIT; + } + /* mt_irq_unmask(CAMERA_ISP_IRQ0_ID); */ + /* request CAM_SV IRQ */ + if (request_irq + (CAM_SV0_IRQ_BIT_ID, (irq_handler_t) ISP_Irq_CAMSV, IRQF_TRIGGER_LOW, "ISP", NULL)) { + LOG_ERR("MT6593_CAMSV1_IRQ_LINE IRQ LINE NOT AVAILABLE!!"); + goto EXIT; + } + /* request CAM_SV2 IRQ */ + if (request_irq + (CAM_SV1_IRQ_BIT_ID, (irq_handler_t) ISP_Irq_CAMSV2, IRQF_TRIGGER_LOW, "ISP", NULL)) { + LOG_ERR("MT6593_CAMSV2_IRQ_LINE IRQ LINE NOT AVAILABLE!!"); + goto EXIT; + } + #endif + +#if 0 +EXIT: +#endif + /*if (Ret < 0)//note: Ret won't < 0 at here + ISP_UnregCharDev();*/ + + /* */ + LOG_DBG("- X."); + /* */ + LOG_INF("kk:- ISP_probe, ret=%d\n", Ret); + /* */ + return Ret; +} + +/******************************************************************************* +* Called when the device is being detached from the driver +********************************************************************************/ +static MINT32 ISP_remove(struct platform_device *pDev) +{ +/* + struct resource *pRes; + MINT32 i; +*/ + MINT32 IrqNum; + /* */ + LOG_DBG("- E."); + /* unregister char driver. */ + ISP_UnregCharDev(); + /* unmaping ISP CAM_REGISTER registers */ +#if 0 + for (i = 0; i < 2; i++) { + pRes = platform_get_resource(pDev, IORESOURCE_MEM, 0); + release_mem_region(pRes->start, (pRes->end - pRes->start + 1)); + } +#endif + /* Release IRQ */ + disable_irq(IspInfo.IrqNum); + IrqNum = platform_get_irq(pDev, 0); + free_irq(IrqNum, NULL); + + /* kill tasklet */ + tasklet_kill(&isp_tasklet); +#if 0 + /* free all registered irq(child nodes) */ + ISP_UnRegister_AllregIrq(); + /* free father nodes of irq user list */ + struct my_list_head *head; + struct my_list_head *father; + + head = ((struct my_list_head *)(&SupIrqUserListHead.list)); + while (1) { + father = head; + if (father->nextirq != father) { + father = father->nextirq; + REG_IRQ_NODE *accessNode; + typeof(((REG_IRQ_NODE *)0)->list) * __mptr = (father); + accessNode = + ((REG_IRQ_NODE *)((char *)__mptr - offsetof(REG_IRQ_NODE, list))); + LOG_INF("free father,reg_T(%d)\n", accessNode->reg_T); + if (father->nextirq != father) { + head->nextirq = father->nextirq; + father->nextirq = father; + } else { /* last father node */ + head->nextirq = head; + LOG_INF("break\n"); + break; + } + kfree(accessNode); + } + } +#endif + /* */ + device_destroy(pIspClass, IspDevNo); + /* */ + class_destroy(pIspClass); + pIspClass = NULL; + /* */ + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 bPass1_On_In_Resume_TG1; +static MINT32 bPass1_On_In_Resume_TG2; +static MINT32 ISP_suspend(struct platform_device *pDev, pm_message_t Mesg) +{ + MUINT32 regTG1Val, regTG2Val; + + if (IspInfo.UserCount == 0) { + LOG_DBG("ISP UserCount=0"); + return 0; + } + + /* TG_VF_CON[0] (0x15004414[0]): VFDATA_EN. TG1 Take Picture Request. */ + regTG1Val = ISP_RD32(ISP_ADDR + 0x414); + /* TG2_VF_CON[0] (0x150044B4[0]): VFDATA_EN. TG2 Take Picture Request. */ + regTG2Val = ISP_RD32(ISP_ADDR + 0x4B4); + + LOG_DBG + ("bPass1_On_In_Resume_TG1(%d). bPass1_On_In_Resume_TG2(%d). regTG1Val(0x%08x). regTG2Val(0x%08x)\n", + bPass1_On_In_Resume_TG1, bPass1_On_In_Resume_TG2, regTG1Val, regTG2Val); + + bPass1_On_In_Resume_TG1 = 0; + if (regTG1Val & 0x01) { /* For TG1 Main sensor. */ + bPass1_On_In_Resume_TG1 = 1; + ISP_WR32(ISP_ADDR + 0x414, (regTG1Val & (~0x01))); + } + + bPass1_On_In_Resume_TG2 = 0; + if (regTG2Val & 0x01) { /* For TG2 Sub sensor. */ + bPass1_On_In_Resume_TG2 = 1; + ISP_WR32(ISP_ADDR + 0x4B4, (regTG2Val & (~0x01))); + } + + return 0; +} + +/******************************************************************************* +* +********************************************************************************/ +static MINT32 ISP_resume(struct platform_device *pDev) +{ + MUINT32 regTG1Val, regTG2Val; + + if (IspInfo.UserCount == 0) { + LOG_DBG("ISP UserCount=0"); + return 0; + } + + /* TG_VF_CON[0] (0x15004414[0]): VFDATA_EN. TG1 Take Picture Request. */ + regTG1Val = ISP_RD32(ISP_ADDR + 0x414); + /* TG2_VF_CON[0] (0x150044B4[0]): VFDATA_EN. TG2 Take Picture Request. */ + regTG2Val = ISP_RD32(ISP_ADDR + 0x4B4); + + LOG_DBG + ("bPass1_On_In_Resume_TG1(%d). bPass1_On_In_Resume_TG2(%d). regTG1Val(0x%x) regTG2Val(0x%x)\n", + bPass1_On_In_Resume_TG1, bPass1_On_In_Resume_TG2, regTG1Val, regTG2Val); + + if (bPass1_On_In_Resume_TG1) { + bPass1_On_In_Resume_TG1 = 0; + ISP_WR32(ISP_ADDR + 0x414, (regTG1Val|0x01)); /* For TG1 Main sensor. */ + } + + if (bPass1_On_In_Resume_TG2) { + bPass1_On_In_Resume_TG2 = 0; + ISP_WR32(ISP_ADDR + 0x4B4, (regTG2Val|0x01)); /* For TG2 Sub sensor. */ + } + + return 0; +} + +/*---------------------------------------------------------------------------*/ +#ifdef CONFIG_PM +/*---------------------------------------------------------------------------*/ +int ISP_pm_suspend(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + + BUG_ON(pdev == NULL); + + pr_debug("calling %s()\n", __func__); + + return ISP_suspend(pdev, PMSG_SUSPEND); +} + +int ISP_pm_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + + BUG_ON(pdev == NULL); + + pr_debug("calling %s()\n", __func__); + + return ISP_resume(pdev); +} + +/* move to camera_isp.h */ +/* extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); */ +/* extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity); */ +int ISP_pm_restore_noirq(struct device *device) +{ + pr_debug("calling %s()\n", __func__); +#ifndef CONFIG_OF + /* Originally CAM0_IRQ_BIT_ID was define in mt_irq.h and x_define_irq.h */ + /* #define X_DEFINE_IRQ(__name, __num, __pol, __sens) __name = __num, */ + /* X_DEFINE_IRQ(CAM0_IRQ_BIT_ID, 215, L, level) */ + /* 32+183=215 */ + #define CAM0_IRQ_BIT_ID 215 + mt_irq_set_sens(CAM0_IRQ_BIT_ID, MT_LEVEL_SENSITIVE); + mt_irq_set_polarity(CAM0_IRQ_BIT_ID, MT_POLARITY_LOW); +#else + mt_irq_set_sens(gISPSYS_Irq[0]+32, MT_LEVEL_SENSITIVE); + mt_irq_set_polarity(gISPSYS_Irq[0]+32, MT_POLARITY_LOW); +#endif + return 0; + +} + +/*---------------------------------------------------------------------------*/ +#else /*CONFIG_PM*/ +/*---------------------------------------------------------------------------*/ +#define ISP_pm_suspend NULL +#define ISP_pm_resume NULL +#define ISP_pm_restore_noirq NULL +/*---------------------------------------------------------------------------*/ +#endif /*CONFIG_PM*/ +/*---------------------------------------------------------------------------*/ + +#ifdef CONFIG_OF +static const struct of_device_id isp_of_ids[] = { + { .compatible = "mediatek,ISPSYS", }, + {} +}; +#endif + +const struct dev_pm_ops ISP_pm_ops = { + .suspend = ISP_pm_suspend, + .resume = ISP_pm_resume, + .freeze = ISP_pm_suspend, + .thaw = ISP_pm_resume, + .poweroff = ISP_pm_suspend, + .restore = ISP_pm_resume, + .restore_noirq = ISP_pm_restore_noirq, +}; + + +/******************************************************************************* +* +********************************************************************************/ +static struct platform_driver IspDriver = { + .probe = ISP_probe, + .remove = ISP_remove, + .suspend = ISP_suspend, + .resume = ISP_resume, + .driver = { + .name = ISP_DEV_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = isp_of_ids, +#endif +#ifdef CONFIG_PM + .pm = &ISP_pm_ops, +#endif + } +}; +/******************************************************************************* +* +********************************************************************************/ +/* +ssize_t (*read) (struct file *, char __user *, size_t, loff_t *) +*/ +#define USE_OLD_STYPE_11897 0 +#if USE_OLD_STYPE_11897 +static MINT32 ISP_DumpRegToProc( + char *pPage, + char **ppStart, + off_t off, + MINT32 Count, + MINT32 *pEof, + void *pData) +#else /* new file_operations style */ +static ssize_t ISP_DumpRegToProc( + struct file *pFile, + char *pStart, + size_t off, + loff_t *Count) +#endif +{ +#if USE_OLD_STYPE_11897 + char *p = pPage; + MINT32 Length = 0; + MUINT32 i = 0; + MINT32 ret = 0; + /* */ + LOG_INF("- E. pPage: %p. off: %d. Count: %d.", pPage, (unsigned int)off, Count); + /* */ + p += sprintf(p, " MT6593 ISP Register\n"); + p += sprintf(p, "====== top ====\n"); + for (i = 0x0; i <= 0x1AC; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + p += sprintf(p, "====== dma ====\n"); + for (i = 0x200; i <= 0x3D8; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n\r", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + p += sprintf(p, "====== tg ====\n"); + for (i = 0x400; i <= 0x4EC; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + p += sprintf(p, "====== cdp (including EIS) ====\n"); + for (i = 0xB00; i <= 0xDE0; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + p += sprintf(p, "====== seninf ====\n"); + for (i = 0x4000; i <= 0x40C0; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + for (i = 0x4100; i <= 0x41BC; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + for (i = 0x4200; i <= 0x4208; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + for (i = 0x4300; i <= 0x4310; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + for (i = 0x43A0; i <= 0x43B0; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + for (i = 0x4400; i <= 0x4424; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + for (i = 0x4500; i <= 0x4520; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + for (i = 0x4600; i <= 0x4608; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + for (i = 0x4A00; i <= 0x4A08; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + + p += sprintf(p, "====== 3DNR ====\n"); + + for (i = 0x4F00; i <= 0x4F38; i += 4) + p += sprintf(p, "+0x%08x 0x%08x\n", (unsigned int)(ISP_ADDR + i), + (unsigned int)ISP_RD32(ISP_ADDR + i)); + /* */ + *ppStart = pPage + off; + /* */ + Length = p - pPage; + if (Length > off) + Length -= off; + else + Length = 0; + + /* */ + ret = Length < Count ? Length : Count; + LOG_INF("- X. ret: %d.", ret); + + return ret; +#else /* new file_operations style */ + LOG_ERR("ISP_DumpRegToProc: Not implement"); + return 0; +#endif +} + +/******************************************************************************* +* +********************************************************************************/ +/* +ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *) +*/ +#define USE_OLD_STYPE_12011 0 +#if USE_OLD_STYPE_12011 +static MINT32 ISP_RegDebug( + struct file *pFile, + const char *pBuffer, + unsigned long Count, + void *pData) +#else /* new file_operations style */ +static ssize_t ISP_RegDebug( + struct file *pFile, + const char *pBuffer, + size_t Count, + loff_t *pData) +#endif +{ +#if USE_OLD_STYPE_12011 + char RegBuf[64]; + MUINT32 CopyBufSize = (Count < (sizeof(RegBuf) - 1)) ? (Count) : (sizeof(RegBuf) - 1); + MUINT32 Addr = 0; + MUINT32 Data = 0; + + LOG_INF("- E. pFile: %p. pBuffer: %p. Count: %d.", pFile, pBuffer, (int)Count); + /* */ + if (copy_from_user(RegBuf, pBuffer, CopyBufSize)) { + LOG_ERR("copy_from_user() fail."); + return -EFAULT; + } + + /* */ + if (sscanf(RegBuf, "%x %x", &Addr, &Data) == 2) { + ISP_WR32(ISP_ADDR_CAMINF + Addr, Data); + LOG_INF("Write => Addr: 0x%08X, Write Data: 0x%08X. Read Data: 0x%08X.", + (int)(ISP_ADDR_CAMINF + Addr), (int)Data, + (int)ioread32((void *)(ISP_ADDR_CAMINF + Addr))); + } else if (sscanf(RegBuf, "%x", &Addr) == 1) { + LOG_INF("Read => Addr: 0x%08X, Read Data: 0x%08X.", + (int)(ISP_ADDR_CAMINF + Addr), (int)ioread32((void *)(ISP_ADDR_CAMINF + Addr))); + } + /* */ + LOG_INF("- X. Count: %d.", (int)Count); + return Count; +#else /* new file_operations style */ + LOG_ERR("ISP_RegDebug: Not implement"); + return 0; +#endif +} + +/* +ssize_t (*read) (struct file *, char __user *, size_t, loff_t *) +*/ +#define USE_OLD_STYPE_12061 0 +#if USE_OLD_STYPE_12061 +static MUINT32 proc_regOfst; +static MINT32 CAMIO_DumpRegToProc( + char *pPage, + char **ppStart, + off_t off, + MINT32 Count, + MINT32 *pEof, + void *pData) +#else /* new file_operations style */ +static ssize_t CAMIO_DumpRegToProc( + struct file *pFile, + char *pStart, + size_t off, + loff_t *Count) +#endif +{ +#if USE_OLD_STYPE_12061 + char *p = pPage; + MINT32 Length = 0; + MINT32 ret = 0; + /* */ + LOG_INF("- E. pPage: %p. off: %d. Count: %d.", pPage, (int)off, Count); + p += sprintf(p, "reg_0x%lx = 0x%08x \n", ISP_ADDR_CAMINF+proc_regOfst, + ioread32((void *)(ISP_ADDR_CAMINF + proc_regOfst))); + + *ppStart = pPage + off; + /* */ + Length = p - pPage; + if (Length > off) + Length -= off; + else + Length = 0; + ret = Length < Count ? Length : Count; + LOG_INF("- X. ret: %d.", ret); + + return ret; +#else /* new file_operations style */ + LOG_ERR("CAMIO_DumpRegToProc: Not implement"); + return 0; +#endif +} + + +/******************************************************************************* +* +********************************************************************************/ +/* +ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *) +*/ +#define USE_OLD_STYPE_12112 0 +#if USE_OLD_STYPE_12112 +static MINT32 CAMIO_RegDebug( + struct file *pFile, + const char *pBuffer, + unsigned long Count, + void *pData) +#else /* new file_operations style */ +static ssize_t CAMIO_RegDebug( + struct file *pFile, + const char *pBuffer, + size_t Count, + loff_t *pData) +#endif +{ +#if USE_OLD_STYPE_12112 + char RegBuf[64]; + MUINT32 CopyBufSize = (Count < (sizeof(RegBuf) - 1)) ? (Count) : (sizeof(RegBuf) - 1); + MUINT32 Addr = 0; + MUINT32 Data = 0; + + LOG_INF("- E. pFile: %p. pBuffer: %p. Count: %d.", pFile, pBuffer, (int)Count); + + /* */ + if (copy_from_user(RegBuf, pBuffer, CopyBufSize)) { + LOG_ERR("copy_from_user() fail."); + return -EFAULT; + } + + /* */ + if (sscanf(RegBuf, "%x %x", &Addr, &Data) == 2) { + proc_regOfst = Addr; + ISP_WR32(ISP_GPIO_ADDR + Addr, Data); + LOG_INF("Write => Addr: 0x%08X, Write Data: 0x%08X. Read Data: 0x%08X.", + (int)(ISP_GPIO_ADDR + Addr), (int)Data, + (int)ioread32((void *)(ISP_GPIO_ADDR + Addr))); + } else if (sscanf(RegBuf, "%x", &Addr) == 1) { + proc_regOfst = Addr; + LOG_INF("Read => Addr: 0x%08X, Read Data: 0x%08X.", (int)(ISP_GPIO_ADDR + Addr), + (int)ioread32((void *)(ISP_GPIO_ADDR + Addr))); + } + /* */ + LOG_INF("- X. Count: %d.", (int)Count); + return Count; +#else /* new file_operations style */ + LOG_ERR("CAMIO_RegDebug: Not implement"); + return 0; +#endif +} + +/******************************************************************************* +* +********************************************************************************/ +static inline MUINT32 ANRdbg_GetState(void) +{ + MUINT32 ret = 1; + int i = 0; + + spin_lock(&(SpinLockImemDump)); + for (i = 0; i < PROCESS_MAX; i++) { + if ((P2_IMEM_DBGList[i].processID != 0x0) && (P2_IMEM_DBGList[i].bImemDbgDumpDone == false)) { + ret = 0; + break; + } + } + spin_unlock(&(SpinLockImemDump)); + return ret; +} +static ssize_t imem_debug_trigger(struct file *pFile, + char *pStart, + size_t off, + loff_t *Count) +{ + int i = 0, timeout; + + LOG_INF("enter imem_debug_trigger"); + /* trigger for information dump */ + spin_lock((spinlock_t *)&(SpinLockImemDump)); + for (i = 0; i < PROCESS_MAX; i++) { + if (P2_IMEM_DBGList[i].processID != 0x0) { + P2_IMEM_DBGList[i].bImemDbgDump = true; + break; + } + } + spin_unlock((spinlock_t *)&(SpinLockImemDump)); + wake_up_interruptible_all((wait_queue_head_t *)&WaitQueueHead_ImemDbgDump); + + /*wait for dump done, then AEE would collect the dbg file to db */ + timeout = wait_event_interruptible_timeout( + WaitQueueHead_ImemDbgDumpDone, + ANRdbg_GetState(), + ISP_MsToJiffies(100)); + spin_lock((spinlock_t *)&(SpinLockImemDump)); + #if 0 + for (int i = 0; i < PROCESS_MAX; i++) { + if (P2_IMEM_DBGList[i].processID != 0x0) { + P2_IMEM_DBGList[i].bImemDbgDumpDone = false; + break; + } + } + #else + for (i = 0; i < PROCESS_MAX; i++) { + P2_IMEM_DBGList[i].processID = 0x0; + P2_IMEM_DBGList[i].bImemDbgDump = false; + P2_IMEM_DBGList[i].bImemDbgDumpDone = false; + } + #endif + spin_unlock((spinlock_t *)&(SpinLockImemDump)); + LOG_INF("leave imem_debug_trigger"); + return 0; + +} + + +static const struct file_operations imem_debugtrigger_fops = { + .read = imem_debug_trigger, +}; + + +void DBGfs_Init(void) +{ + /* for AEE */ + cisp_dbgTrigfs = debugfs_create_file("cisp_dbgtrig", + S_IFREG|S_IRUGO, NULL, (void *)0, &imem_debugtrigger_fops); +} + +void DBGfs_UnInit(void) +{ + debugfs_remove(cisp_dbgTrigfs); +} +/******************************************************************************* +* +********************************************************************************/ +static const struct file_operations fcameraisp_proc_fops = { + .read = ISP_DumpRegToProc, + .write = ISP_RegDebug, +}; + +static const struct file_operations fcameraio_proc_fops = { + .read = CAMIO_DumpRegToProc, + .write = CAMIO_RegDebug, +}; + +/******************************************************************************* +* +********************************************************************************/ +m4u_callback_ret_t ISP_M4U_TranslationFault_callback(int port, unsigned int mva, void *data) +{ + LOG_ERR("[ISP_M4U]fault call port=%d, mva=0x%x", port, mva); + + switch (port) { + case M4U_PORT_IMGO: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3204), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3204)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3300), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3300)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3304), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3304)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3308), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3308)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x330c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x330c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3310), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3310)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3314), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3314)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3318), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3318)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x331c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x331c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3320), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3320)); + break; + case M4U_PORT_RRZO: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3204), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3204)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3320), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3320)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3324), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3324)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3328), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3328)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x332c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x332c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3330), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3330)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3334), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3334)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3338), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3338)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x333c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x333c)); + break; + case M4U_PORT_AAO: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3364), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3364)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3368), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3368)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3388), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3388)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x338c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x338c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3390), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3390)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3394), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3394)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3398), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3398)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x339c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x339c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33a0)); + break; +#if 0 + case M4U_PORT_LCSO: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3340), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3340)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3344), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3344)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3348), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3348)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x334c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x334c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3350), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3350)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3354), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3354)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3358), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3358)); + break; +#endif + case M4U_PORT_ESFKO: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x335c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x335c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3360), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3360)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x336c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x336c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3370), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3370)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3374), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3374)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3378), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3378)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x337c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x337c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3380), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3380)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3384), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3384)); + break; + case M4U_PORT_IMGO_S: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00cc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00cc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00d0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00d0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00d4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00d4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00d8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00d8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34d4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34d4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34d8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34d8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34dc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34dc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34e0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34e0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34e4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34e4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34e8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34e8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34ec), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34ec)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34f0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34f0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34f4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34f4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34f8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34f8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34fc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34fc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3500), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3500)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3504), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3504)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3508), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3508)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x350c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x350c)); + break; + case M4U_PORT_LSCI: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x326c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x326c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3270), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3270)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3274), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3274)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3278), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3278)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x327c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x327c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3280), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3280)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3284), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3284)); + break; + case M4U_PORT_LSCI_D: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34c4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34c4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34c8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34c8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34cc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34cc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x34d0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x34d0)); + break; + case M4U_PORT_BPCI: + case M4U_PORT_BPCI_D: + break; + case M4U_PORT_IMGI: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0018), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0018)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x001c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x001c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3204), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3204)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3230), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3230)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3230), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3230)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3234), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3234)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3238), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3238)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x323c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x323c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3240), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3240)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3248), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3248)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x324c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x324c)); + break; + case M4U_PORT_LCEI: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0018), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0018)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x001c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x001c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3204), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3204)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32a4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32a8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32bc)); + break; + case M4U_PORT_UFDI: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0018), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0018)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x001c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x001c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3204), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3204)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3288), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3288)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x328c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x328c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3290), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3290)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3294), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3294)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3298), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3298)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x329c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x329c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32a0)); + break; + case M4U_PORT_IMG2O: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0018), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0018)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x001c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x001c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3440), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3440)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3444), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3444)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3448), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3448)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x344c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x344c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3450), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3450)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3454), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3454)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3458), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3458)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x345c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x345c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3480), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3480)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3484), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3484)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3488), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3488)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x348c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x348c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3490), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3490)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3494), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3494)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3498), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3498)); + break; + case M4U_PORT_IMG3O: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0018), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0018)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x001c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x001c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3460), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3460)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3464), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3464)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3468), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3468)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x346c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x346c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3470), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3470)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3474), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3474)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3478), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3478)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x347c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x347c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3400), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3400)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3404), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3404)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3408), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3408)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x340c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x340c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3410), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3410)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3414), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3414)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3418), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3418)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x341c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x341c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3420), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3420)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3424), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3424)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3428), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3428)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x342c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x342c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3430), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3430)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3434), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3434)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3438), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3438)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x343c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x343c)); + break; + case M4U_PORT_VIPI: + case M4U_PORT_VIP2I: + case M4U_PORT_VIP3I: + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x0018), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0018)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x001c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x001c)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x00a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3204), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3204)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x3230), + (unsigned int)ISP_RD32(ISP_ADDR + 0x3230)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32c0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32c4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32c4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32c8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32c8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32cc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32cc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32d0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32d0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32d4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32d4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32d8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32d8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32dc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32dc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32e0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32e0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32e4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32e4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32e8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32e8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32ec), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32ec)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32f0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32f0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32f4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32f4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32f8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32f8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x32fc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x32fc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33a4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33a8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33ac), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33ac)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33b0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33b0)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33b4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33b4)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33b8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33b8)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33bc), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33bc)); + LOG_ERR("[TF_%d]0x%08X %08X", port, (unsigned int)(ISP_TPIPE_ADDR + 0x33c0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x33c0)); + break; + default: + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x0000), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0000)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x0004), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0004)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x0008), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0008)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x0010), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0010)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x0014), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0014)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x0018), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0018)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x001c), + (unsigned int)ISP_RD32(ISP_ADDR + 0x001c)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x0020), + (unsigned int)ISP_RD32(ISP_ADDR + 0x0020)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x00a0), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a0)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x00a4), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a4)); + LOG_ERR("0x%08X %08X", (unsigned int)(ISP_TPIPE_ADDR + 0x00a8), + (unsigned int)ISP_RD32(ISP_ADDR + 0x00a8)); + break; + } + + return M4U_CALLBACK_HANDLED; +} + +/******************************************************************************* +* +********************************************************************************/ + +static MINT32 __init ISP_Init(void) +{ + MINT32 Ret = 0, j; + void *tmp; +#if 0 + struct proc_dir_entry *pEntry; +#endif + int i; + cisp_dbgTrigfs = NULL; + /* */ + LOG_DBG("- E."); + /* */ + Ret = platform_driver_register(&IspDriver); + if (Ret < 0) { + LOG_ERR("platform_driver_register fail"); + return Ret; + } + /* */ +/* FIX-ME: linux-3.10 procfs API changed */ +#if 1 + proc_create("driver/isp_reg", 0, NULL, &fcameraisp_proc_fops); + proc_create("driver/camio_reg", 0, NULL, &fcameraio_proc_fops); +#else + pEntry = create_proc_entry("driver/isp_reg", 0, NULL); + if (pEntry) { + pEntry->read_proc = ISP_DumpRegToProc; + pEntry->write_proc = ISP_RegDebug; + } else{ + LOG_ERR("add /proc/driver/isp_reg entry fail"); + } + + pEntry = create_proc_entry("driver/camio_reg", 0, NULL); + if (pEntry) { + pEntry->read_proc = CAMIO_DumpRegToProc; + pEntry->write_proc = CAMIO_RegDebug; + } else{ + LOG_ERR("add /proc/driver/camio_reg entry fail"); + } +#endif + /* */ + /* allocate a memory area with kmalloc. Will be rounded up to a page boundary */ + /* RT_BUF_TBL_NPAGES*4096(1page) = 64k Bytes */ + + if (sizeof(ISP_RT_BUF_STRUCT) > ((RT_BUF_TBL_NPAGES) * PAGE_SIZE)) { + i = 0; + + while (i < sizeof(ISP_RT_BUF_STRUCT)) + i += PAGE_SIZE; + pBuf_kmalloc = kmalloc(i+2*PAGE_SIZE, GFP_KERNEL); + if (pBuf_kmalloc == NULL) { + LOG_ERR("mem not enough\n"); + return -ENOMEM; + } + memset(pBuf_kmalloc, 0x00, i); + } else{ + pBuf_kmalloc = kmalloc((RT_BUF_TBL_NPAGES + 2) * PAGE_SIZE, GFP_KERNEL); + if (pBuf_kmalloc == NULL) { + LOG_ERR("mem not enough\n"); + return -ENOMEM; + } + memset(pBuf_kmalloc, 0x00, RT_BUF_TBL_NPAGES * PAGE_SIZE); + } + /* round it up to the page bondary */ + pTbl_RTBuf = (int *)((((unsigned long)pBuf_kmalloc) + PAGE_SIZE - 1) & PAGE_MASK); + pstRTBuf = (ISP_RT_BUF_STRUCT *)pTbl_RTBuf; + pstRTBuf->state = ISP_RTBC_STATE_INIT; + /* isr log */ + if (PAGE_SIZE < + ((_IRQ_MAX * NORMAL_STR_LEN * ((DBG_PAGE + INF_PAGE + ERR_PAGE) + 1)) * LOG_PPNUM)) { + i = 0; + while (i < + ((_IRQ_MAX * NORMAL_STR_LEN * ((DBG_PAGE + INF_PAGE + ERR_PAGE) + 1)) * + LOG_PPNUM)) + i += PAGE_SIZE; + } else{ + i = PAGE_SIZE; + } + pLog_kmalloc = kmalloc(i, GFP_KERNEL); + if (pLog_kmalloc == NULL) { + LOG_ERR("mem not enough\n"); + return -ENOMEM; + } + memset(pLog_kmalloc, 0x00, i); + tmp = pLog_kmalloc; + for (i = 0; i < LOG_PPNUM; i++) { + for (j = 0; j < _IRQ_MAX; j++) { + gSvLog[j]._str[i][_LOG_DBG] = (char *)tmp; + /* tmp = (void *) ((unsigned int)tmp + (NORMAL_STR_LEN*DBG_PAGE));*/ + tmp = (void *) ((char *)tmp + (NORMAL_STR_LEN*DBG_PAGE)); + gSvLog[j]._str[i][_LOG_INF] = (char *)tmp; + /* tmp = (void *) ((unsigned int)tmp + (NORMAL_STR_LEN*INF_PAGE));*/ + tmp = (void *) ((char *)tmp + (NORMAL_STR_LEN*INF_PAGE)); + gSvLog[j]._str[i][_LOG_ERR] = (char *)tmp; + /* tmp = (void *) ((unsigned int)tmp + (NORMAL_STR_LEN*ERR_PAGE));*/ + tmp = (void *) ((char *)tmp + (NORMAL_STR_LEN*ERR_PAGE)); + } + /* tmp = (void *) ((unsigned int)tmp + NORMAL_STR_LEN);//log buffer ,in case of overflow */ + tmp = (void *) ((char *)tmp + NORMAL_STR_LEN);/* log buffer ,in case of overflow */ + } + /* mark the pages reserved , FOR MMAP*/ + for (i = 0; i < RT_BUF_TBL_NPAGES * PAGE_SIZE; i += PAGE_SIZE) + SetPageReserved(virt_to_page(((unsigned long)pTbl_RTBuf) + i)); + /* */ + /* Register ISP callback */ + LOG_DBG("register isp callback for MDP"); + cmdqCoreRegisterCB(CMDQ_GROUP_ISP, ISP_MDPClockOnCallback, ISP_MDPDumpCallback, ISP_MDPResetCallback, ISP_MDPClockOffCallback); + /* Register GCE callback for dumping ISP register */ + LOG_DBG("register isp callback for GCE"); + cmdqCoreRegisterDebugRegDumpCB(ISP_BeginGCECallback, ISP_EndGCECallback); + + /* Register M4U callback dump */ + LOG_DBG("register M4U callback dump"); + m4u_register_fault_callback(M4U_PORT_IMGI, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_IMGO, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_RRZO, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_AAO, ISP_M4U_TranslationFault_callback, NULL); + /* m4u_register_fault_callback(M4U_PORT_LCSO, ISP_M4U_TranslationFault_callback, NULL);*/ + m4u_register_fault_callback(M4U_PORT_ESFKO, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_IMGO_S, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_LSCI, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_LSCI_D, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_BPCI, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_BPCI_D, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_UFDI, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_IMG2O, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_IMG3O, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_VIPI, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_VIP2I, ISP_M4U_TranslationFault_callback, NULL); + m4u_register_fault_callback(M4U_PORT_VIP3I, ISP_M4U_TranslationFault_callback, NULL); + + +#ifdef _MAGIC_NUM_ERR_HANDLING_ + LOG_DBG("init m_LastMNum"); + for (i = 0; i < _rt_dma_max_; i++) + m_LastMNum[i] = 0; +#endif + + DBGfs_Init(); + + LOG_DBG("- X. Ret: %d.", Ret); + return Ret; +} + +/******************************************************************************* +* +********************************************************************************/ +static void __exit ISP_Exit(void) +{ + int i; + LOG_DBG("- E."); + /* */ + platform_driver_unregister(&IspDriver); + /* */ + /* Unregister ISP callback */ + cmdqCoreRegisterCB(CMDQ_GROUP_ISP, NULL, NULL, NULL, NULL); + /* Un-Register GCE callback */ + LOG_DBG("Un-register isp callback for GCE"); + cmdqCoreRegisterDebugRegDumpCB(NULL, NULL); + /* */ + /* Un-Register M4U callback dump */ + LOG_DBG("Un-Register M4U callback dump"); + m4u_unregister_fault_callback(M4U_PORT_IMGI); + + + /* unreserve the pages */ + for (i = 0; i < RT_BUF_TBL_NPAGES * PAGE_SIZE; i += PAGE_SIZE) + ClearPageReserved(virt_to_page(((unsigned long)pTbl_RTBuf) + i)); + + /* free the memory areas */ + kfree(pBuf_kmalloc); + kfree(pLog_kmalloc); + + DBGfs_UnInit(); + /* */ +} + +/******************************************************************************* +* +********************************************************************************/ +MBOOL ISP_RegCallback(ISP_CALLBACK_STRUCT * pCallback) +{ + /* */ + if (pCallback == NULL) { + LOG_ERR("pCallback is null"); + return MFALSE; + } + /* */ + if (pCallback->Func == NULL) { + LOG_ERR("Func is null"); + return MFALSE; + } + /* */ + LOG_DBG("Type(%d)", pCallback->Type); + IspInfo.Callback[pCallback->Type].Func = pCallback->Func; + /* */ + return MTRUE; +} +EXPORT_SYMBOL(ISP_RegCallback); + +/******************************************************************************* +* +********************************************************************************/ +MBOOL ISP_UnregCallback(ISP_CALLBACK_ENUM Type) +{ + if (Type >= ISP_CALLBACK_AMOUNT) { + LOG_ERR("Type(%d) must smaller than %d", Type, ISP_CALLBACK_AMOUNT); + return MFALSE; + } + /* */ + LOG_DBG("Type(%d)", Type); + IspInfo.Callback[Type].Func = NULL; + /* */ + return MTRUE; +} +EXPORT_SYMBOL(ISP_UnregCallback); + + +void ISP_MCLK1_EN(BOOL En) +{ + MUINT32 temp = 0; + + if (1 == En) + mMclk1User++; + else { + mMclk1User--; + if (mMclk1User <= 0) + mMclk1User = 0; + } + + + temp = ISP_RD32(ISP_ADDR + 0x4200); + if (En) { + if (mMclk1User > 0) { + temp |= 0x20000000; + ISP_WR32(ISP_ADDR + 0x4200, temp); + } + } else { + if (mMclk1User == 0) { + temp &= 0xDFFFFFFF; + ISP_WR32(ISP_ADDR + 0x4200, temp); + } + } + temp = ISP_RD32(ISP_ADDR + 0x4200); + LOG_INF("ISP_MCLK1_EN(%d), mMclk1User(%d)", temp, mMclk1User); + +} +EXPORT_SYMBOL(ISP_MCLK1_EN); + + + + +void ISP_MCLK2_EN(BOOL En) +{ + MUINT32 temp = 0; + if (1 == En) + mMclk2User++; + else { + mMclk2User--; + if (mMclk2User <= 0) + mMclk2User = 0; + } + + + temp = ISP_RD32(ISP_ADDR + 0x4600); + if (En) { + if (mMclk2User > 0) { + temp |= 0x20000000; + ISP_WR32(ISP_ADDR + 0x4600, temp); + } + } else { + if (mMclk2User == 0) { + temp &= 0xDFFFFFFF; + ISP_WR32(ISP_ADDR + 0x4600, temp); + } + } + LOG_INF("ISP_MCLK2_EN(%d), mMclk2User(%d)", temp, mMclk2User); +} +EXPORT_SYMBOL(ISP_MCLK2_EN); + + + +void ISP_MCLK3_EN(BOOL En) +{ + MUINT32 temp = 0; + if (1 == En) + mMclk3User++; + else { + mMclk3User--; + if (mMclk3User <= 0) + mMclk3User = 0; + } + + + temp = ISP_RD32(ISP_ADDR + 0x4A00); + if (En) { + if (mMclk3User > 0) { + temp |= 0x20000000; + ISP_WR32(ISP_ADDR + 0x4A00, temp); + } + } else{ + if (mMclk3User == 0) { + temp &= 0xDFFFFFFF; + ISP_WR32(ISP_ADDR + 0x4A00, temp); + } + } + LOG_INF("ISP_MCLK3_EN(%d), mMclk3User(%d)", temp, mMclk3User); +} +EXPORT_SYMBOL(ISP_MCLK3_EN); + +int32_t ISP_MDPClockOnCallback(uint64_t engineFlag) +{ + /* LOG_DBG("ISP_MDPClockOnCallback");*/ + LOG_DBG("+MDPEn:%d", G_u4EnableClockCount); + ISP_EnableClock(MTRUE); + + return 0; +} + +int32_t ISP_MDPDumpCallback(uint64_t engineFlag, + int level) +{ + LOG_DBG("ISP_MDPDumpCallback"); + + ISP_DumpReg(); + + return 0; +} + +int32_t ISP_MDPResetCallback(uint64_t engineFlag) +{ + /* LOG_DBG("ISP_MDPResetCallback");*/ + + ISP_Reset(ISP_REG_SW_CTL_RST_CAM_P2); + + return 0; +} + +int32_t ISP_MDPClockOffCallback(uint64_t engineFlag) +{ + /* LOG_DBG("ISP_MDPClockOffCallback");*/ + ISP_EnableClock(MFALSE); + LOG_DBG("-MDPEn:%d", G_u4EnableClockCount); + return 0; +} + + +static uint32_t *addressToDump[] = { + +#if 0 /* QQ */ +#if CONFIG_OF + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4018), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x401C), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4024), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4030), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x403C), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4040), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4080), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4084), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4088), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x40A0), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x40A4), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x40A8), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48A0), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48A4), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48A8), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48AC), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48B0), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48B4), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48B8), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48BC), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48C0), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48C4), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48C8), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48CC), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48D0), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48D4), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48D8), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48DC), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48E0), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48E4), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x48E8), + /* */ + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4948), + /* */ + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B00), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B04), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B08), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B0C), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B10), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B14), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B18), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B1C), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B20), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B24), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B28), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B2C), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B30), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B34), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x4B38), + /* */ + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7204), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7208), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x720C), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7230), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7240), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7288), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x72a4), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7300), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7320), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7440), + (uint32_t *)(ISP_IMGSYS_BASE_PHY + 0x7460) + +#else + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4018), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x401C), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4024), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4030), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x403C), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4040), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4080), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4084), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4088), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x40A0), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x40A4), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x40A8), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48A0), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48A4), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48A8), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48AC), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48B0), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48B4), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48B8), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48BC), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48C0), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48C4), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48C8), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48CC), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48D0), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48D4), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48D8), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48DC), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48E0), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48E4), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x48E8), + /* */ + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4948), + /* */ + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B00), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B04), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B08), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B0C), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B10), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B14), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B18), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B1C), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B20), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B24), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B28), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B2C), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B30), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B34), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x4B38), + /* */ + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7204), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7208), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x720C), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7230), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7240), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7288), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x72a4), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7300), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7320), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7440), + (uint32_t *)IO_VIRT_TO_PHYS(ISP_IMGSYS_BASE + 0x7460) +#endif +#endif + }; + +int32_t ISP_BeginGCECallback(uint32_t taskID, uint32_t *regCount, uint32_t **regAddress) +{ + LOG_DBG("+,taskID(%d)", taskID); + + *regCount = sizeof(addressToDump)/sizeof(uint32_t); + *regAddress = (uint32_t *)addressToDump; + + LOG_DBG("-,*regCount(%d)", *regCount); + + return 0; +} + +int32_t ISP_EndGCECallback(uint32_t taskID, uint32_t regCount, uint32_t *regValues) +{ +#define PER_LINE_LOG_SIZE 10 + int32_t i, j, pos; + /* uint32_t add[PER_LINE_LOG_SIZE];*/ + uint32_t *add[PER_LINE_LOG_SIZE]; + uint32_t val[PER_LINE_LOG_SIZE]; + + LOG_DBG("End taskID(%d),regCount(%d)", taskID, regCount); + + for (i = 0; i < regCount; i += PER_LINE_LOG_SIZE) { + for (j = 0; j < PER_LINE_LOG_SIZE; j++) { + pos = i + j; + if (pos < regCount) { + /* addr[j] = (uint32_t)addressToDump[pos]&0xffff;*/ + add[j] = addressToDump[pos]; + val[j] = regValues[pos]; + } + } + /* LOG_DBG("[0x%04x,0x%08x][0x%04x,0x%08x][0x%04x,0x%08x][0x%04x,0x%08x][0x%04x,0x%08x][0x%04x,0x%08x][0x%04x,0x%08x][0x%04x,0x%08x][0x%04x,0x%08x][0x%04x,0x%08x]\n", */ + /* add[0],val[0],add[1],val[1],add[2],val[2],add[3],val[3],add[4],val[4],add[5],val[5],add[6],val[6],add[7],val[7],add[8],val[8],add[9],val[9]);*/ + LOG_DBG("[0x%p,0x%08x][0x%p,0x%08x][0x%p,0x%08x][0x%p,0x%08x][0x%p,0x%08x][0x%p,0x%08x][0x%p,0x%08x][0x%p,0x%08x][0x%p,0x%08x][0x%p,0x%08x]\n", + add[0], val[0], add[1], val[1], add[2], val[2], add[3], val[3], add[4], val[4], add[5], val[5], add[6], val[6], add[7], val[7], add[8], val[8], add[9], val[9]); + } + return 0; +} + + + +/******************************************************************************* +* +********************************************************************************/ +module_init(ISP_Init); +module_exit(ISP_Exit); +MODULE_DESCRIPTION("Camera ISP driver"); +MODULE_AUTHOR("ME3"); +MODULE_LICENSE("GPL"); + + + + + + diff --git a/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_fdvt.h b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_fdvt.h new file mode 100755 index 0000000000000000000000000000000000000000..d1f4bb49c5f2cc1a9155c8b5c330db517211680d --- /dev/null +++ b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_fdvt.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __CAMERA_FDVT_H__ +#define __CAMERA_FDVT_H__ + +#include +#define FDVT_IOC_MAGIC 'N' + +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + +typedef struct { + unsigned int *pAddr; + unsigned int *pData; + unsigned int u4Count; +} MT6573FDVTRegIO; + +#ifdef CONFIG_COMPAT + +typedef struct { + compat_uptr_t pAddr; + compat_uptr_t pData; + unsigned int u4Count; +} compat_MT6573FDVTRegIO; + + +#endif + + +/* below is control message */ +#define MT6573FDVT_INIT_SETPARA_CMD _IO(FDVT_IOC_MAGIC, 0x00) +#define MT6573FDVTIOC_STARTFD_CMD _IO(FDVT_IOC_MAGIC, 0x01) +#define MT6573FDVTIOC_G_WAITIRQ _IOR(FDVT_IOC_MAGIC, 0x02, unsigned int) +#define MT6573FDVTIOC_T_SET_FDCONF_CMD _IOW(FDVT_IOC_MAGIC, 0x03, MT6573FDVTRegIO) +#define MT6573FDVTIOC_G_READ_FDREG_CMD _IOWR(FDVT_IOC_MAGIC, 0x04, MT6573FDVTRegIO) +#define MT6573FDVTIOC_T_SET_SDCONF_CMD _IOW(FDVT_IOC_MAGIC, 0x05, MT6573FDVTRegIO) +/* #define FDVT_DESTROY_CMD _IO(FDVT_IOC_MAGIC, 0x10) */ + +#define MT6573FDVTIOC_T_DUMPREG _IO(FDVT_IOC_MAGIC, 0x80) + +/* +#define FDVT_SET_CMD_CMD _IOW(FDVT_IOC_MAGIC, 0x03, unsigned int) +#define FDVT_SET_PWR_CMD _IOW(FDVT_IOC_MAGIC, 0x04, unsigned int) +#define FDVT_SET_ISR_CMD _IOW(FDVT_IOC_MAGIC, 0x05, unsigned int) +#define FDVT_GET_CACHECTRLADDR_CMD _IOR(FDVT_IOC_MAGIC, 0x06, int) +*/ + +#ifdef CONFIG_COMPAT + +#define COMPAT_MT6573FDVT_INIT_SETPARA_CMD _IO(FDVT_IOC_MAGIC, 0x00) +#define COMPAT_MT6573FDVTIOC_STARTFD_CMD _IO(FDVT_IOC_MAGIC, 0x01) +#define COMPAT_MT6573FDVTIOC_G_WAITIRQ _IOR(FDVT_IOC_MAGIC, 0x02, unsigned int) +#define COMPAT_MT6573FDVTIOC_T_SET_FDCONF_CMD _IOW(FDVT_IOC_MAGIC, 0x03, compat_MT6573FDVTRegIO) +#define COMPAT_MT6573FDVTIOC_G_READ_FDREG_CMD _IOWR(FDVT_IOC_MAGIC, 0x04, compat_MT6573FDVTRegIO) +#define COMPAT_MT6573FDVTIOC_T_SET_SDCONF_CMD _IOW(FDVT_IOC_MAGIC, 0x05, compat_MT6573FDVTRegIO) +#define COMPAT_MT6573FDVTIOC_T_DUMPREG _IO(FDVT_IOC_MAGIC, 0x80) + +#endif + + +#endif /* __CAMERA_FDVT_H__ */ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_isp.h b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_isp.h new file mode 100755 index 0000000000000000000000000000000000000000..f3b703842e8e96f05851415bb8e94ea98380ba65 --- /dev/null +++ b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_isp.h @@ -0,0 +1,981 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_ISP_H +#define _MT_ISP_H + +#include + +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + +/** + external function declaration +*/ +extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); +extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity); +/** + enforce kernel log enable +*/ +/* #define KERNEL_LOG //enable debug log flag if defined */ +#define ISR_LOG_ON /* turn on log print at isr if defined */ + +#define T_STAMP_2_0 /* time stamp workaround method. (increase timestamp baseon fix fps, not read at each isr) */ + +#define SIG_ERESTARTSYS 512 /* ERESTARTSYS */ +/******************************************************************************* +* +********************************************************************************/ +#define ISP_DEV_MAJOR_NUMBER 251 +#define ISP_MAGIC 'k' +/******************************************************************************* +* +********************************************************************************/ +/* CAM_CTL_INT_P1_STATUS */ +#define ISP_IRQ_P1_STATUS_VS1_INT_ST ((unsigned int)1<<0) +#define ISP_IRQ_P1_STATUS_TG1_INT1_ST ((unsigned int)1<<1) +#define ISP_IRQ_P1_STATUS_TG1_INT2_ST ((unsigned int)1<<2) +#define ISP_IRQ_P1_STATUS_EXPDON1_ST ((unsigned int)1<<3) +#define ISP_IRQ_P1_STATUS_TG1_ERR_ST ((unsigned int)1<<4) +#define ISP_IRQ_P1_STATUS_TG1_GBERR ((unsigned int)1<<5) +#define ISP_IRQ_P1_STATUS_CQ0_ERR ((unsigned int)1<<6) +#define ISP_IRQ_P1_STATUS_CQ0_VS_ERR_ST ((unsigned int)1<<7) +#define ISP_IRQ_P1_STATUS_IMGO_DROP_FRAME_ST ((unsigned int)1<<8) +#define ISP_IRQ_P1_STATUS_RRZO_DROP_FRAME_ST ((unsigned int)1<<9) +#define ISP_IRQ_P1_STATUS_PASS1_DON_ST ((unsigned int)1<<10) +#define ISP_IRQ_P1_STATUS_rsv_11 ((unsigned int)1<<11) +#define ISP_IRQ_P1_STATUS_SOF1_INT_ST ((unsigned int)1<<12) +#define ISP_IRQ_P1_STATUS_rsv_13 ((unsigned int)1<<13) +#define ISP_IRQ_P1_STATUS_PESUDO_P1_DON_ST ((unsigned int)1<<15) +#define ISP_IRQ_P1_STATUS_AF_DON_ST ((unsigned int)1<<16) +#define ISP_IRQ_P1_STATUS_FLK_DON_ST ((unsigned int)1<<17) +#define ISP_IRQ_P1_STATUS_rsv_18 ((unsigned int)1<<18) +#define ISP_IRQ_P1_STATUS_IMGO_ERR_ST ((unsigned int)1<<20) +#define ISP_IRQ_P1_STATUS_AAO_ERR_ST ((unsigned int)1<<21) +#define ISP_IRQ_P1_STATUS_LCSO_ERR_ST ((unsigned int)1<<22) +#define ISP_IRQ_P1_STATUS_RRZO_ERR_ST ((unsigned int)1<<23) +#define ISP_IRQ_P1_STATUS_ESFKO_ERR_ST ((unsigned int)1<<24) +#define ISP_IRQ_P1_STATUS_FLK_ERR_ST ((unsigned int)1<<25) +#define ISP_IRQ_P1_STATUS_LSC_ERR_ST ((unsigned int)1<<26) +#define ISP_IRQ_P1_STATUS_FBC_RRZO_DON_ST ((unsigned int)1<<27) +#define ISP_IRQ_P1_STATUS_FBC_IMGO_DON_ST ((unsigned int)1<<28) +#define ISP_IRQ_P1_STATUS_rsv_29 ((unsigned int)1<<29) +#define ISP_IRQ_P1_STATUS_DMA_ERR_ST ((unsigned int)1<<30) +#define ISP_IRQ_P1_STATUS_rsv_31 ((unsigned int)1<<31) +/* CAM_CTL_INT_P1_STATUS2 */ +#define ISP_IRQ_P1_STATUS2_IMGO_DONE_ST ((unsigned int)1<<0) +#define ISP_IRQ_P1_STATUS2_UFEO_DONE_ST ((unsigned int)1<<1) +#define ISP_IRQ_P1_STATUS2_RRZO_DONE_ST ((unsigned int)1<<2) +#define ISP_IRQ_P1_STATUS2_ESFKO_DONE_ST ((unsigned int)1<<3) +#define ISP_IRQ_P1_STATUS2_LCSO_DONE_ST ((unsigned int)1<<4) +#define ISP_IRQ_P1_STATUS2_AAO_DONE_ST ((unsigned int)1<<5) +#define ISP_IRQ_P1_STATUS2_BPCI_DONE_ST ((unsigned int)1<<6) +#define ISP_IRQ_P1_STATUS2_LSCI_DONE_ST ((unsigned int)1<<7) +#define ISP_IRQ_P1_STATUS2_AF_TAR_DONE_ST ((unsigned int)1<<8) +#define ISP_IRQ_P1_STATUS2_AF_FLO1_DONE_ST ((unsigned int)1<<9) +#define ISP_IRQ_P1_STATUS2_AF_FLO2_DONE_ST ((unsigned int)1<<10) +#define ISP_IRQ_P1_STATUS2_AF_FLO3_DONE_ST ((unsigned int)1<<11) +#define ISP_IRQ_P1_STATUS2_rsv_12 ((unsigned int)1<<12) +/* CAM_CTL_INT_P1_STATUS_D */ +#define ISP_IRQ_P1_STATUS_D_VS1_INT_ST ((unsigned int)1<<0) +#define ISP_IRQ_P1_STATUS_D_TG1_INT1_ST ((unsigned int)1<<1) +#define ISP_IRQ_P1_STATUS_D_TG1_INT2_ST ((unsigned int)1<<2) +#define ISP_IRQ_P1_STATUS_D_EXPDON1_ST ((unsigned int)1<<3) +#define ISP_IRQ_P1_STATUS_D_TG1_ERR_ST ((unsigned int)1<<4) +#define ISP_IRQ_P1_STATUS_D_TG1_GBERR ((unsigned int)1<<5) +#define ISP_IRQ_P1_STATUS_D_CQ0_ERR ((unsigned int)1<<6) +#define ISP_IRQ_P1_STATUS_D_CQ0_VS_ERR_ST ((unsigned int)1<<7) +#define ISP_IRQ_P1_STATUS_D_IMGO_DROP_FRAME_ST ((unsigned int)1<<8) +#define ISP_IRQ_P1_STATUS_D_RRZO_DROP_FRAME_ST ((unsigned int)1<<9) +#define ISP_IRQ_P1_STATUS_D_PASS1_DON_ST ((unsigned int)1<<10) +#define ISP_IRQ_P1_STATUS_D_rsv_11 ((unsigned int)1<<11) +#define ISP_IRQ_P1_STATUS_D_SOF1_INT_ST ((unsigned int)1<<12) +#define ISP_IRQ_P1_STATUS_D_rsv_13 ((unsigned int)1<<13) +#define ISP_IRQ_P1_STATUS_D_PESUDO_P1_DON_ST ((unsigned int)1<<15) +#define ISP_IRQ_P1_STATUS_D_AF_DON_ST ((unsigned int)1<<16) +#define ISP_IRQ_P1_STATUS_D_rsv_17 ((unsigned int)1<<17) +#define ISP_IRQ_P1_STATUS_D_IMGO_ERR_ST ((unsigned int)1<<20) +#define ISP_IRQ_P1_STATUS_D_AAO_ERR_ST ((unsigned int)1<<21) +#define ISP_IRQ_P1_STATUS_D_LCSO_ERR_ST ((unsigned int)1<<22) +#define ISP_IRQ_P1_STATUS_D_RRZO_ERR_ST ((unsigned int)1<<23) +#define ISP_IRQ_P1_STATUS_D_AFO_ERR_ST ((unsigned int)1<<24) +#define ISP_IRQ_P1_STATUS_D_rsv_25 ((unsigned int)1<<25) +#define ISP_IRQ_P1_STATUS_D_LSC_ERR_ST ((unsigned int)1<<26) +#define ISP_IRQ_P1_STATUS_D_FBC_RRZO_DON_ST ((unsigned int)1<<27) +#define ISP_IRQ_P1_STATUS_D_FBC_IMGO_DON_ST ((unsigned int)1<<28) +#define ISP_IRQ_P1_STATUS_D_rsv_29 ((unsigned int)1<<29) +#define ISP_IRQ_P1_STATUS_D_DMA_ERR_ST ((unsigned int)1<<30) +#define ISP_IRQ_P1_STATUS_D_rsv_31 ((unsigned int)1<<31) +/* CAM_CTL_INT_P1_STATUS2_D */ +#define ISP_IRQ_P1_STATUS2_D_IMGO_D_DONE_ST ((unsigned int)1<<0) +#define ISP_IRQ_P1_STATUS2_D_rsv_1 ((unsigned int)1<<1) +#define ISP_IRQ_P1_STATUS2_D_RRZO_D_DONE_ST ((unsigned int)1<<2) +#define ISP_IRQ_P1_STATUS2_D_AFO_D_DONE_ST ((unsigned int)1<<3) +#define ISP_IRQ_P1_STATUS2_D_LCSO_D_DONE_ST ((unsigned int)1<<4) +#define ISP_IRQ_P1_STATUS2_D_AAO_D_DONE_ST ((unsigned int)1<<5) +#define ISP_IRQ_P1_STATUS2_D_BPCI_D_DONE_ST ((unsigned int)1<<6) +#define ISP_IRQ_P1_STATUS2_D_LSCI_D_DONE_ST ((unsigned int)1<<7) +#define ISP_IRQ_P1_STATUS2_D_AF_TAR_DONE_ST ((unsigned int)1<<8) +#define ISP_IRQ_P1_STATUS2_D_AF_FLO1_DONE_ST ((unsigned int)1<<9) +#define ISP_IRQ_P1_STATUS2_D_AF_FLO2_DONE_ST ((unsigned int)1<<10) +#define ISP_IRQ_P1_STATUS2_D_AF_FLO3_DONE_ST ((unsigned int)1<<11) +#define ISP_IRQ_P1_STATUS2_D_rsv_12 ((unsigned int)1<<12) +/* CAM_CTL_SEL_P1 */ +#define ISP_CAM_CTL_SEL_P1_IMGO_SEL ((unsigned int)1<<6) +/* CAM_CTL_SEL_P1_D */ +#define ISP_CAM_CTL_SEL_P1_D_IMGO_SEL ((unsigned int)1<<6) +/* CAM_CTL_INT_P2_STATUS */ +#define ISP_IRQ_P2_STATUS_CQ_ERR_ST ((unsigned int)1<<0) +#define ISP_IRQ_P2_STATUS_PASS2_DON_ST ((unsigned int)1<<1) +#define ISP_IRQ_P2_STATUS_TILE_DON_ST ((unsigned int)1<<2) +#define ISP_IRQ_P2_STATUS_CQ_DON_ST ((unsigned int)1<<3) +#define ISP_IRQ_P2_STATUS_TDR_ERR_ST ((unsigned int)1<<4) +#define ISP_IRQ_P2_STATUS_PASS2A_DON_ST ((unsigned int)1<<5) +#define ISP_IRQ_P2_STATUS_PASS2B_DON_ST ((unsigned int)1<<6) +#define ISP_IRQ_P2_STATUS_PASS2C_DON_ST ((unsigned int)1<<7) +#define ISP_IRQ_P2_STATUS_CQ1_DONE_ST ((unsigned int)1<<8) +#define ISP_IRQ_P2_STATUS_CQ2_DONE_ST ((unsigned int)1<<9) +#define ISP_IRQ_P2_STATUS_CQ3_DONE_ST ((unsigned int)1<<10) +#define ISP_IRQ_P2_STATUS_PASS2A_ERR_TRIG_ST ((unsigned int)1<<11) +#define ISP_IRQ_P2_STATUS_PASS2B_ERR_TRIG_ST ((unsigned int)1<<12) +#define ISP_IRQ_P2_STATUS_PASS2C_ERR_TRIG_ST ((unsigned int)1<<13) +#define ISP_IRQ_P2_STATUS_IMGI_DONE_ST ((unsigned int)1<<15) +#define ISP_IRQ_P2_STATUS_UFDI_DONE_ST ((unsigned int)1<<16) +#define ISP_IRQ_P2_STATUS_VIPI_DONE_ST ((unsigned int)1<<17) +#define ISP_IRQ_P2_STATUS_VIP2I_DONE_ST ((unsigned int)1<<18) +#define ISP_IRQ_P2_STATUS_VIP3I_DONE_ST ((unsigned int)1<<19) +#define ISP_IRQ_P2_STATUS_LCEI_DONE_ST ((unsigned int)1<<20) +#define ISP_IRQ_P2_STATUS_MFBO_DONE_ST ((unsigned int)1<<21) +#define ISP_IRQ_P2_STATUS_IMG2O_DONE_ST ((unsigned int)1<<22) +#define ISP_IRQ_P2_STATUS_IMG3O_DONE_ST ((unsigned int)1<<23) +#define ISP_IRQ_P2_STATUS_IMG3BO_DONE_ST ((unsigned int)1<<24) +#define ISP_IRQ_P2_STATUS_IMG3CO_DONE_ST ((unsigned int)1<<25) +#define ISP_IRQ_P2_STATUS_FEO_DONE_ST ((unsigned int)1<<26) +#define ISP_IRQ_P2_STATUS_rsv_27 ((unsigned int)1<<27) +/* CAM_CTL_INT_STATUSX //P1 AND P2 */ +#define ISP_IRQ_STATUSX_VS1_INT_ST ((unsigned int)1<<0) +#define ISP_IRQ_STATUSX_TG1_INT1_ST ((unsigned int)1<<1) +#define ISP_IRQ_STATUSX_TG1_INT2_ST ((unsigned int)1<<2) +#define ISP_IRQ_STATUSX_EXPDON1_ST ((unsigned int)1<<3) +#define ISP_IRQ_STATUSX_TG1_ERR_ST ((unsigned int)1<<4) +#define ISP_IRQ_STATUSX_TG1_GBERR ((unsigned int)1<<5) +#define ISP_IRQ_STATUSX_CQ0_ERR ((unsigned int)1<<6) +#define ISP_IRQ_STATUSX_CQ0_VS_ERR_ST ((unsigned int)1<<7) +#define ISP_IRQ_STATUSX_IMGO_DROP_FRAME_ST ((unsigned int)1<<8) +#define ISP_IRQ_STATUSX_RRZO_DROP_FRAME_ST ((unsigned int)1<<9) +#define ISP_IRQ_STATUSX_PASS1_DON_ST ((unsigned int)1<<10) +#define ISP_IRQ_STATUSX_rsv_11 ((unsigned int)1<<11) +#define ISP_IRQ_STATUSX_SOF1_INT_ST ((unsigned int)1<<12) +#define ISP_IRQ_STATUSX_CQ_ERR_ST ((unsigned int)1<<13) +#define ISP_IRQ_STATUSX_PASS2_DON_ST ((unsigned int)1<<14) +#define ISP_IRQ_STATUSX_TILE_DON_ST ((unsigned int)1<<15) +#define ISP_IRQ_STATUSX_AF_DON_ST ((unsigned int)1<<16) +#define ISP_IRQ_STATUSX_FLK_DON_ST ((unsigned int)1<<17) +#define ISP_IRQ_STATUSX_rsv_18 ((unsigned int)1<<18) +#define ISP_IRQ_STATUSX_CQ_DON_ST ((unsigned int)1<<19) +#define ISP_IRQ_STATUSX_IMGO_ERR_ST ((unsigned int)1<<20) +#define ISP_IRQ_STATUSX_AAO_ERR_ST ((unsigned int)1<<21) +#define ISP_IRQ_STATUSX_LCSO_ERR_ST ((unsigned int)1<<22) +#define ISP_IRQ_STATUSX_RRZO_ERR_ST ((unsigned int)1<<23) +#define ISP_IRQ_STATUSX_ESFKO_ERR_ST ((unsigned int)1<<24) +#define ISP_IRQ_STATUSX_FLK_ERR_ST ((unsigned int)1<<25) +#define ISP_IRQ_STATUSX_LSC_ERR_ST ((unsigned int)1<<26) +#define ISP_IRQ_STATUSX_FBC_RRZO_DON_ST ((unsigned int)1<<27) +#define ISP_IRQ_STATUSX_FBC_IMGO_DON_ST ((unsigned int)1<<28) +#define ISP_IRQ_STATUSX_rsv_29 ((unsigned int)1<<29) +#define ISP_IRQ_STATUSX_DMA_ERR_ST ((unsigned int)1<<30) +#define ISP_IRQ_STATUSX_rsv_31 ((unsigned int)1<<31) +/* CAM_CTL_INT_STATUS2X //P1_D */ +#define ISP_IRQ_STATUS2X_VS1_INT_ST ((unsigned int)1<<0) +#define ISP_IRQ_STATUS2X_TG1_INT1_ST ((unsigned int)1<<1) +#define ISP_IRQ_STATUS2X_TG1_INT2_ST ((unsigned int)1<<2) +#define ISP_IRQ_STATUS2X_EXPDON1_ST ((unsigned int)1<<3) +#define ISP_IRQ_STATUS2X_TG1_ERR_ST ((unsigned int)1<<4) +#define ISP_IRQ_STATUS2X_TG1_GBERR ((unsigned int)1<<5) +#define ISP_IRQ_STATUS2X_CQ0_ERR ((unsigned int)1<<6) +#define ISP_IRQ_STATUS2X_CQ0_VS_ERR_ST ((unsigned int)1<<7) +#define ISP_IRQ_STATUS2X_IMGO_DROP_FRAME_ST ((unsigned int)1<<8) +#define ISP_IRQ_STATUS2X_RRZO_DROP_FRAME_ST ((unsigned int)1<<9) +#define ISP_IRQ_STATUS2X_PASS1_DON_ST ((unsigned int)1<<10) +#define ISP_IRQ_STATUS2X_rsv_11 ((unsigned int)1<<11) +#define ISP_IRQ_STATUS2X_SOF1_INT_ST ((unsigned int)1<<12) +#define ISP_IRQ_STATUS2X_rsv_13 ((unsigned int)1<<13) +#define ISP_IRQ_STATUS2X_rsv_14 ((unsigned int)1<<14) +#define ISP_IRQ_STATUS2X_rsv_15 ((unsigned int)1<<15) +#define ISP_IRQ_STATUS2X_AF_DON_ST ((unsigned int)1<<16) +#define ISP_IRQ_STATUS2X_rsv_17 ((unsigned int)1<<17) +#define ISP_IRQ_STATUS2X_rsv_18 ((unsigned int)1<<18) +#define ISP_IRQ_STATUS2X_rsv_19 ((unsigned int)1<<19) +#define ISP_IRQ_STATUS2X_IMGO_ERR_ST ((unsigned int)1<<20) +#define ISP_IRQ_STATUS2X_AAO_ERR_ST ((unsigned int)1<<21) +#define ISP_IRQ_STATUS2X_LCSO_ERR_ST ((unsigned int)1<<22) +#define ISP_IRQ_STATUS2X_RRZO_ERR_ST ((unsigned int)1<<23) +#define ISP_IRQ_STATUS2X_AFO_ERR_ST ((unsigned int)1<<24) +#define ISP_IRQ_STATUS2X_rsv_25 ((unsigned int)1<<25) +#define ISP_IRQ_STATUS2X_LSC_ERR_ST ((unsigned int)1<<26) +#define ISP_IRQ_STATUS2X_FBC_RRZO_DON_ST ((unsigned int)1<<27) +#define ISP_IRQ_STATUS2X_FBC_IMGO_DON_ST ((unsigned int)1<<28) +#define ISP_IRQ_STATUS2X_rsv_29 ((unsigned int)1<<29) +#define ISP_IRQ_STATUS2X_DMA_ERR_ST ((unsigned int)1<<30) +#define ISP_IRQ_STATUS2X_rsv_31 ((unsigned int)1<<31) +/* ISP_IRQ_STATUS3X //ALL DMA */ +#define ISP_IRQ_STATUS3X_IMGO_DONE_ST ((unsigned int)1<<0) +#define ISP_IRQ_STATUS3X_UFEO_DONE_ST ((unsigned int)1<<1) +#define ISP_IRQ_STATUS3X_RRZO_DONE_ST ((unsigned int)1<<2) +#define ISP_IRQ_STATUS3X_ESFKO_DONE_ST ((unsigned int)1<<3) +#define ISP_IRQ_STATUS3X_LCSO_DONE_ST ((unsigned int)1<<4) +#define ISP_IRQ_STATUS3X_AAO_DONE_ST ((unsigned int)1<<5) +#define ISP_IRQ_STATUS3X_BPCI_DONE_ST ((unsigned int)1<<6) +#define ISP_IRQ_STATUS3X_LSCI_DONE_ST ((unsigned int)1<<7) +#define ISP_IRQ_STATUS3X_IMGO_D_DONE_ST ((unsigned int)1<<8) +#define ISP_IRQ_STATUS3X_RRZO_D_DONE_ST ((unsigned int)1<<9) +#define ISP_IRQ_STATUS3X_AFO_D_DONE_ST ((unsigned int)1<<10) +#define ISP_IRQ_STATUS3X_LCSO_D_DONE_ST ((unsigned int)1<<11) +#define ISP_IRQ_STATUS3X_AAO_D_DONE_ST ((unsigned int)1<<12) +#define ISP_IRQ_STATUS3X_BPCI_D_DONE_ST ((unsigned int)1<<13) +#define ISP_IRQ_STATUS3X_LCSI_D_DONE_ST ((unsigned int)1<<14) +#define ISP_IRQ_STATUS3X_IMGI_DONE_ST ((unsigned int)1<<15) +#define ISP_IRQ_STATUS3X_UFDI_DONE_ST ((unsigned int)1<<16) +#define ISP_IRQ_STATUS3X_VIPI_DONE_ST ((unsigned int)1<<17) +#define ISP_IRQ_STATUS3X_VIP2I_DONE_ST ((unsigned int)1<<18) +#define ISP_IRQ_STATUS3X_VIP3I_DONE_ST ((unsigned int)1<<19) +#define ISP_IRQ_STATUS3X_LCEI_DONE_ST ((unsigned int)1<<20) +#define ISP_IRQ_STATUS3X_MFBO_DONE_ST ((unsigned int)1<<21) +#define ISP_IRQ_STATUS3X_IMG2O_DONE_ST ((unsigned int)1<<22) +#define ISP_IRQ_STATUS3X_IMG3O_DONE_ST ((unsigned int)1<<23) +#define ISP_IRQ_STATUS3X_IMG3BO_DONE_ST ((unsigned int)1<<24) +#define ISP_IRQ_STATUS3X_IMG3CO_DONE_ST ((unsigned int)1<<25) +#define ISP_IRQ_STATUS3X_FEO_DONE_ST ((unsigned int)1<<26) +#define ISP_IRQ_STATUS3X_rsv_27 ((unsigned int)1<<27) +#define ISP_IRQ_STATUS3X_rsv_28 ((unsigned int)1<<28) +#define ISP_IRQ_STATUS3X_rsv_29 ((unsigned int)1<<29) +#define ISP_IRQ_STATUS3X_rsv_30 ((unsigned int)1<<30) +#define ISP_IRQ_STATUS3X_rsv_31 ((unsigned int)1<<31) +/* SENINF1_IRQ_INTSTA */ +#define SENINF1_IRQ_OVERRUN_IRQ_STA ((unsigned int)1<<0) +#define SENINF1_IRQ_CRCERR_IRQ_STA ((unsigned int)1<<1) +#define SENINF1_IRQ_FSMERR_IRQ_STA ((unsigned int)1<<2) +#define SENINF1_IRQ_VSIZEERR_IRQ_STA ((unsigned int)1<<3) +#define SENINF1_IRQ_HSIZEERR_IRQ_STA ((unsigned int)1<<4) +#define SENINF1_IRQ_SENSOR_VSIZEERR_IRQ_STA ((unsigned int)1<<5) +#define SENINF1_IRQ_SENSOR_HSIZEERR_IRQ_STA ((unsigned int)1<<6) +/* SENINF2_IRQ_INTSTA */ +#define SENINF2_IRQ_OVERRUN_IRQ_STA ((unsigned int)1<<0) +#define SENINF2_IRQ_CRCERR_IRQ_STA ((unsigned int)1<<1) +#define SENINF2_IRQ_FSMERR_IRQ_STA ((unsigned int)1<<2) +#define SENINF2_IRQ_VSIZEERR_IRQ_STA ((unsigned int)1<<3) +#define SENINF2_IRQ_HSIZEERR_IRQ_STA ((unsigned int)1<<4) +#define SENINF2_IRQ_SENSOR_VSIZEERR_IRQ_STA ((unsigned int)1<<5) +#define SENINF2_IRQ_SENSOR_HSIZEERR_IRQ_STA ((unsigned int)1<<6) +/* SENINF3_IRQ_INTSTA */ +#define SENINF3_IRQ_OVERRUN_IRQ_STA ((unsigned int)1<<0) +#define SENINF3_IRQ_CRCERR_IRQ_STA ((unsigned int)1<<1) +#define SENINF3_IRQ_FSMERR_IRQ_STA ((unsigned int)1<<2) +#define SENINF3_IRQ_VSIZEERR_IRQ_STA ((unsigned int)1<<3) +#define SENINF3_IRQ_HSIZEERR_IRQ_STA ((unsigned int)1<<4) +#define SENINF3_IRQ_SENSOR_VSIZEERR_IRQ_STA ((unsigned int)1<<5) +#define SENINF3_IRQ_SENSOR_HSIZEERR_IRQ_STA ((unsigned int)1<<6) +/* SENINF4_IRQ_INTSTA */ +#define SENINF4_IRQ_OVERRUN_IRQ_STA ((unsigned int)1<<0) +#define SENINF4_IRQ_CRCERR_IRQ_STA ((unsigned int)1<<1) +#define SENINF4_IRQ_FSMERR_IRQ_STA ((unsigned int)1<<2) +#define SENINF4_IRQ_VSIZEERR_IRQ_STA ((unsigned int)1<<3) +#define SENINF4_IRQ_HSIZEERR_IRQ_STA ((unsigned int)1<<4) +#define SENINF4_IRQ_SENSOR_VSIZEERR_IRQ_STA ((unsigned int)1<<5) +#define SENINF4_IRQ_SENSOR_HSIZEERR_IRQ_STA ((unsigned int)1<<6) +/* REG_CAMSV_INT_STATUS */ +#define ISP_IRQ_CAMSV_STATUS_VS1_ST ((unsigned int)1<<0) +#define ISP_IRQ_CAMSV_STATUS_TG_ST1 ((unsigned int)1<<1) +#define ISP_IRQ_CAMSV_STATUS_TG_ST2 ((unsigned int)1<<2) +#define ISP_IRQ_CAMSV_STATUS_EXPDON1_ST ((unsigned int)1<<3) +#define ISP_IRQ_CAMSV_STATUS_TG_ERR_ST ((unsigned int)1<<4) +#define ISP_IRQ_CAMSV_STATUS_TG_GBERR_ST ((unsigned int)1<<5) +#define ISP_IRQ_CAMSV_STATUS_TG_DROP_ST ((unsigned int)1<<6) +#define ISP_IRQ_CAMSV_STATUS_TG_SOF1_ST ((unsigned int)1<<7) +#define ISP_IRQ_CAMSV_STATUS_rsv_8 ((unsigned int)1<<8) +#define ISP_IRQ_CAMSV_STATUS_rsv_9 ((unsigned int)1<<9) +#define ISP_IRQ_CAMSV_STATUS_PASS1_DON_ST ((unsigned int)1<<10) +#define ISP_IRQ_CAMSV_STATUS_rsv_11 ((unsigned int)1<<11) +#define ISP_IRQ_CAMSV_STATUS_rsv_12 ((unsigned int)1<<12) +#define ISP_IRQ_CAMSV_STATUS_rsv_13 ((unsigned int)1<<13) +#define ISP_IRQ_CAMSV_STATUS_rsv_14 ((unsigned int)1<<14) +#define ISP_IRQ_CAMSV_STATUS_rsv_15 ((unsigned int)1<<15) +#define ISP_IRQ_CAMSV_STATUS_IMGO_ERR_ST ((unsigned int)1<<16) +#define ISP_IRQ_CAMSV_STATUS_IMGO_OVERR_ST ((unsigned int)1<<17) +#define ISP_IRQ_CAMSV_STATUS_rsv_18 ((unsigned int)1<<18) +#define ISP_IRQ_CAMSV_STATUS_IMGO_DROP_ST ((unsigned int)1<<19) +/* REG_ISP_IRQ_CAMSV2_STATUS */ +#define ISP_IRQ_CAMSV2_STATUS_VS1_ST ((unsigned int)1<<0) +#define ISP_IRQ_CAMSV2_STATUS_TG_ST1 ((unsigned int)1<<1) +#define ISP_IRQ_CAMSV2_STATUS_TG_ST2 ((unsigned int)1<<2) +#define ISP_IRQ_CAMSV2_STATUS_EXPDON1_ST ((unsigned int)1<<3) +#define ISP_IRQ_CAMSV2_STATUS_TG_ERR_ST ((unsigned int)1<<4) +#define ISP_IRQ_CAMSV2_STATUS_TG_GBERR_ST ((unsigned int)1<<5) +#define ISP_IRQ_CAMSV2_STATUS_TG_DROP_ST ((unsigned int)1<<6) +#define ISP_IRQ_CAMSV2_STATUS_TG_SOF1_ST ((unsigned int)1<<7) +#define ISP_IRQ_CAMSV2_STATUS_rsv_8 ((unsigned int)1<<8) +#define ISP_IRQ_CAMSV2_STATUS_rsv_9 ((unsigned int)1<<9) +#define ISP_IRQ_CAMSV2_STATUS_PASS1_DON_ST ((unsigned int)1<<10) +#define ISP_IRQ_CAMSV2_STATUS_rsv_11 ((unsigned int)1<<11) +#define ISP_IRQ_CAMSV2_STATUS_rsv_12 ((unsigned int)1<<12) +#define ISP_IRQ_CAMSV2_STATUS_rsv_13 ((unsigned int)1<<13) +#define ISP_IRQ_CAMSV2_STATUS_rsv_14 ((unsigned int)1<<14) +#define ISP_IRQ_CAMSV2_STATUS_rsv_15 ((unsigned int)1<<15) +#define ISP_IRQ_CAMSV2_STATUS_IMGO_ERR_ST ((unsigned int)1<<16) +#define ISP_IRQ_CAMSV2_STATUS_IMGO_OVERR_ST ((unsigned int)1<<17) +#define ISP_IRQ_CAMSV2_STATUS_rsv_18 ((unsigned int)1<<18) +#define ISP_IRQ_CAMSV2_STATUS_IMGO_DROP_ST ((unsigned int)1<<19) + +/******************************************************************************* +* +********************************************************************************/ + +/* defined if want to support multiple dequne and enque or camera 3.0 */ +/** + support multiple deque and enque if defined. + note: still en/de que 1 buffer each time only + e.g: + deque(); + deque(); + enque(); + enque(); +*/ +#define _rtbc_buf_que_2_0_ + + +typedef enum { + ISP_IRQ_CLEAR_NONE, + ISP_IRQ_CLEAR_WAIT, + ISP_IRQ_CLEAR_STATUS, + ISP_IRQ_CLEAR_ALL +} ISP_IRQ_CLEAR_ENUM; + +typedef enum { + ISP_IRQ_TYPE_INT_P1_ST, /* P1 */ + ISP_IRQ_TYPE_INT_P1_ST2, /* P1_DMA */ + ISP_IRQ_TYPE_INT_P1_ST_D, /* P1_D */ + ISP_IRQ_TYPE_INT_P1_ST2_D, /* P1_DMA_D */ + ISP_IRQ_TYPE_INT_P2_ST, /* P2 */ + ISP_IRQ_TYPE_INT_STATUSX, /* STATUSX, P1 AND P2 */ + ISP_IRQ_TYPE_INT_STATUS2X, /* STATUS2X, P1_D */ + ISP_IRQ_TYPE_INT_STATUS3X, /* STATUS3X, ALL DMA */ + ISP_IRQ_TYPE_ISP_AMOUNT, + ISP_IRQ_TYPE_INT_SENINF1 = ISP_IRQ_TYPE_ISP_AMOUNT, + ISP_IRQ_TYPE_INT_SENINF2, + ISP_IRQ_TYPE_INT_SENINF3, + ISP_IRQ_TYPE_INT_SENINF4, + ISP_IRQ_TYPE_SENINF_AMOUNT, + ISP_IRQ_TYPE_INT_CAMSV = ISP_IRQ_TYPE_SENINF_AMOUNT, + ISP_IRQ_TYPE_INT_CAMSV2, + ISP_IRQ_TYPE_AMOUNT +} ISP_IRQ_TYPE_ENUM; + + +typedef enum { + ISP_IRQ_USER_ISPDRV = 0, + ISP_IRQ_USER_MW = 1, + ISP_IRQ_USER_3A = 2, + ISP_IRQ_USER_HWSYNC = 3, + ISP_IRQ_USER_ACDK = 4, + ISP_IRQ_USER_EIS = 5, + ISP_IRQ_USER_VHDR = 6, + ISP_IRQ_USER_MAX +} ISP_IRQ_USER_ENUM; + +typedef struct { + ISP_IRQ_TYPE_ENUM Type; + unsigned int Status; + int UserKey; /* user key for doing interrupt operation */ +} ISP_IRQ_USER_STRUCT; + +typedef enum { /* special user for specific operation */ + ISP_IRQ_WAITIRQ_SPEUSER_NONE = 0, + ISP_IRQ_WAITIRQ_SPEUSER_EIS = 1, + ISP_IRQ_WAITIRQ_SPEUSER_NUM +} ISP_IRQ_WAITIRQ_SPEUSER_ENUM; + +typedef struct { + unsigned int tLastSig_sec; /* time stamp of the latest occuring signal */ + unsigned int tLastSig_usec; /* time stamp of the latest occuring signal */ + unsigned int tMark2WaitSig_sec; /* time period from marking a signal to user try to wait and get the signal */ + unsigned int tMark2WaitSig_usec; /* time period from marking a signal to user try to wait and get the signal */ + unsigned int tLastSig2GetSig_sec; /* time period from latest occuring signal to user try to wait and get the signal */ + unsigned int tLastSig2GetSig_usec; /* time period from latest occuring signal to user try to wait and get the signal */ + int passedbySigcnt; /* the count for the signal passed by */ +} ISP_IRQ_TIME_STRUCT; + +typedef struct { + unsigned int tLastSOF2P1done_sec; /* time stamp of the last closest occuring sof signal for pass1 done */ + unsigned int tLastSOF2P1done_usec; /* time stamp of the last closest occuring sof signal for pass1 done */ +} ISP_EIS_META_STRUCT; + + +typedef struct { + ISP_IRQ_CLEAR_ENUM Clear; /* v1 & v3 */ + ISP_IRQ_TYPE_ENUM Type; /* v1 only */ + unsigned int Status; /* v1 only */ + int UserNumber; /* v1 only */ + unsigned int Timeout; /* v1 & v3 */ + char *UserName; /* no use */ + unsigned int irq_TStamp; /* v1 & v3 */ + unsigned int bDumpReg; /* v1 & v3 */ + ISP_IRQ_USER_STRUCT UserInfo; /* v3 only */ + ISP_IRQ_TIME_STRUCT TimeInfo; /* v3 only */ + ISP_EIS_META_STRUCT EisMeta; /* v1&v3 */ + ISP_IRQ_WAITIRQ_SPEUSER_ENUM SpecUser; +} ISP_WAIT_IRQ_STRUCT; + +typedef struct { + int userKey; + char *userName; +} ISP_REGISTER_USERKEY_STRUCT; + +typedef struct { + ISP_IRQ_TYPE_ENUM Type; + ISP_IRQ_USER_ENUM UserNumber; + unsigned int Status; +} ISP_READ_IRQ_STRUCT; + +typedef struct { + ISP_IRQ_TYPE_ENUM Type; + ISP_IRQ_USER_ENUM UserNumber; + unsigned int Status; +} ISP_CLEAR_IRQ_STRUCT; + +typedef enum { + ISP_HOLD_TIME_VD, + ISP_HOLD_TIME_EXPDONE +} ISP_HOLD_TIME_ENUM; + +typedef struct { + unsigned int Addr; /* register's addr */ + unsigned int Val; /* register's value */ +} ISP_REG_STRUCT; + +typedef struct { + /* unsigned int Data; // pointer to ISP_REG_STRUCT */ + ISP_REG_STRUCT *pData; + unsigned int Count; /* count */ +} ISP_REG_IO_STRUCT; + +typedef void (*pIspCallback) (void); + +typedef enum { + /* Work queue. It is interruptible, so there can be "Sleep" in work queue function. */ + ISP_CALLBACK_WORKQUEUE_VD, + ISP_CALLBACK_WORKQUEUE_EXPDONE, + /* Tasklet. It is uninterrupted, so there can NOT be "Sleep" in tasklet function. */ + ISP_CALLBACK_TASKLET_VD, + ISP_CALLBACK_TASKLET_EXPDONE, + ISP_CALLBACK_AMOUNT +} ISP_CALLBACK_ENUM; + +typedef struct { + ISP_CALLBACK_ENUM Type; + pIspCallback Func; +} ISP_CALLBACK_STRUCT; + +/* */ +/* length of the two memory areas */ +#define P1_DEQUE_CNT 1 +#define RT_BUF_TBL_NPAGES 16 +#define ISP_RT_BUF_SIZE 16 +#define ISP_RT_CQ0C_BUF_SIZE (ISP_RT_BUF_SIZE) /* (ISP_RT_BUF_SIZE>>1) */ +/* pass1 setting sync index */ +#define ISP_REG_P1_CFG_IDX 0x4090 +/* */ +typedef enum { + _cam_tg_ = 0, + _cam_tg2_, /* 1 */ + _camsv_tg_, /* 2 */ + _camsv2_tg_, /* 3 */ + _cam_tg_max_ +} _isp_tg_enum_; + +/* */ +typedef enum { + _imgi_ = 0, + _vipi_, /* 1 */ + _vip2i_, /* 2 */ + _vip3i_, /* 3 */ + _imgo_, /* 4 */ + _ufdi_, /* 5 */ + _lcei_, /* 6 */ + _ufeo_, /* 7 */ + _rrzo_, /* 8 */ + _imgo_d_, /* 9 */ + _rrzo_d_, /* 10 */ + _img2o_, /* 11 */ + _img3o_, /* 12 */ + _img3bo_, /* 13 */ + _img3co_, /* 14 */ + _camsv_imgo_, /* 15 */ + _camsv2_imgo_, /* 16 */ + _mfbo_, /* 17 */ + _feo_, /* 18 */ + _wrot_, /* 19 */ + _wdma_, /* 20 */ + _jpeg_, /* 21 */ + _venc_stream_, /* 21 */ + _rt_dma_max_ +} _isp_dma_enum_; +/* */ +typedef struct { + unsigned int w; /* tg size */ + unsigned int h; + unsigned int xsize; /* dmao xsize */ + unsigned int stride; + unsigned int fmt; + unsigned int pxl_id; + unsigned int wbn; + unsigned int ob; + unsigned int lsc; + unsigned int rpg; + unsigned int m_num_0; + unsigned int frm_cnt; + unsigned int bus_size; +} ISP_RT_IMAGE_INFO_STRUCT; + +typedef struct { + unsigned int srcX; /* crop window start point */ + unsigned int srcY; + unsigned int srcW; /* crop window size */ + unsigned int srcH; + unsigned int dstW; /* rrz out size */ + unsigned int dstH; +} ISP_RT_RRZ_INFO_STRUCT; + +typedef struct { + unsigned int x; /* in pix */ + unsigned int y; /* in pix */ + unsigned int w; /* in byte */ + unsigned int h; /* in byte */ +} ISP_RT_DMAO_CROPPING_STRUCT; + +typedef struct { + unsigned int memID; + unsigned int size; + long long base_vAddr; + unsigned int base_pAddr; + unsigned int timeStampS; + unsigned int timeStampUs; + unsigned int bFilled; + unsigned int bProcessRaw; + ISP_RT_IMAGE_INFO_STRUCT image; + ISP_RT_RRZ_INFO_STRUCT rrzInfo; + ISP_RT_DMAO_CROPPING_STRUCT dmaoCrop; /* imgo */ + unsigned int bDequeued; + signed int bufIdx; /* used for replace buffer */ +} ISP_RT_BUF_INFO_STRUCT; +/* */ +typedef struct { + unsigned int count; + unsigned int sof_cnt; /* cnt for current sof */ + unsigned int img_cnt; /* cnt for mapping to which sof */ + /* rome support only deque 1 image at a time */ + /* ISP_RT_BUF_INFO_STRUCT data[ISP_RT_BUF_SIZE]; */ + ISP_RT_BUF_INFO_STRUCT data[P1_DEQUE_CNT]; +} ISP_DEQUE_BUF_INFO_STRUCT; +/* */ +typedef struct { + unsigned int start; /* current DMA accessing buffer */ + unsigned int total_count; /* total buffer number.Include Filled and empty */ + unsigned int empty_count; /* total empty buffer number include current DMA accessing buffer */ + unsigned int pre_empty_count; /* previous total empty buffer number include current DMA accessing buffer */ + unsigned int active; + unsigned int read_idx; + unsigned int img_cnt; /* cnt for mapping to which sof */ + ISP_RT_BUF_INFO_STRUCT data[ISP_RT_BUF_SIZE]; +} ISP_RT_RING_BUF_INFO_STRUCT; +/* */ +typedef enum { + ISP_RT_BUF_CTRL_ENQUE, /* 0 */ +#ifdef _rtbc_buf_que_2_0_ + ISP_RT_BUF_CTRL_ENQUE_IMD, /* for directly enque */ +#else + ISP_RT_BUF_CTRL_ENQUE_IMD = ISP_RT_BUF_CTRL_ENQUE, +#endif + ISP_RT_BUF_CTRL_EXCHANGE_ENQUE, /* 1 */ + ISP_RT_BUF_CTRL_DEQUE, /* 2 */ + ISP_RT_BUF_CTRL_IS_RDY, /* 3 */ +#ifdef _rtbc_buf_que_2_0_ + ISP_RT_BUF_CTRL_DMA_EN, /* 4 */ +#endif + ISP_RT_BUF_CTRL_GET_SIZE, /* 5 */ + ISP_RT_BUF_CTRL_CLEAR, /* 6 */ + ISP_RT_BUF_CTRL_CUR_STATUS, /* 7 */ + ISP_RT_BUF_CTRL_MAX +} ISP_RT_BUF_CTRL_ENUM; +/* */ +typedef enum { + ISP_RTBC_STATE_INIT, /* 0 */ + ISP_RTBC_STATE_SOF, + ISP_RTBC_STATE_DONE, + ISP_RTBC_STATE_MAX +} ISP_RTBC_STATE_ENUM; +/* */ +typedef enum { + ISP_RTBC_BUF_EMPTY, /* 0 */ + ISP_RTBC_BUF_FILLED, /* 1 */ + ISP_RTBC_BUF_LOCKED, /* 2 */ +} ISP_RTBC_BUF_STATE_ENUM; +/* */ +typedef enum { + ISP_RROCESSED_RAW, /* 0 */ + ISP_PURE_RAW, /* 1 */ +} ISP_RAW_TYPE_ENUM; +/* */ +typedef struct { + ISP_RTBC_STATE_ENUM state; + unsigned long dropCnt; + ISP_RT_RING_BUF_INFO_STRUCT ring_buf[_rt_dma_max_]; +} ISP_RT_BUF_STRUCT; +/* */ +typedef struct { + ISP_RT_BUF_CTRL_ENUM ctrl; + _isp_dma_enum_ buf_id; + /* unsigned int data_ptr; */ + /* unsigned int ex_data_ptr; //exchanged buffer */ + ISP_RT_BUF_INFO_STRUCT *data_ptr; + ISP_RT_BUF_INFO_STRUCT *ex_data_ptr; /* exchanged buffer */ + unsigned char *pExtend; +} ISP_BUFFER_CTRL_STRUCT; +/* */ +/* reference count */ +#define _use_kernel_ref_cnt_ +/* */ +typedef enum { + ISP_REF_CNT_GET, /* 0 */ + ISP_REF_CNT_INC, /* 1 */ + ISP_REF_CNT_DEC, /* 2 */ + ISP_REF_CNT_DEC_AND_RESET_P1_P2_IF_LAST_ONE, /* 3 */ + ISP_REF_CNT_DEC_AND_RESET_P1_IF_LAST_ONE, /* 4 */ + ISP_REF_CNT_DEC_AND_RESET_P2_IF_LAST_ONE, /* 5 */ + ISP_REF_CNT_MAX +} ISP_REF_CNT_CTRL_ENUM; +/* */ +typedef enum { + ISP_REF_CNT_ID_IMEM, /* 0 */ + ISP_REF_CNT_ID_ISP_FUNC, /* 1 */ + ISP_REF_CNT_ID_GLOBAL_PIPE, /* 2 */ + ISP_REF_CNT_ID_P1_PIPE, /* 3 */ + ISP_REF_CNT_ID_P2_PIPE, /* 4 */ + ISP_REF_CNT_ID_MAX, +} ISP_REF_CNT_ID_ENUM; +/* */ +typedef struct { + ISP_REF_CNT_CTRL_ENUM ctrl; + ISP_REF_CNT_ID_ENUM id; + signed int *data_ptr; +} ISP_REF_CNT_CTRL_STRUCT; + +/* struct for enqueue/dequeue control in ihalpipe wrapper */ +typedef enum { + ISP_ED_BUFQUE_CTRL_ENQUE_FRAME = 0, + ISP_ED_BUFQUE_CTRL_WAIT_DEQUE, /* 1,a dequeue thread is waiting to do dequeue */ + ISP_ED_BUFQUE_CTRL_DEQUE_SUCCESS, /* 2,signal that a buffer is dequeued (success) */ + ISP_ED_BUFQUE_CTRL_DEQUE_FAIL, /* 3,signal that a buffer is dequeued (fail) */ + ISP_ED_BUFQUE_CTRL_WAIT_FRAME, /* 4,wait for a specific buffer */ + ISP_ED_BUFQUE_CTRL_WAKE_WAITFRAME, /* 5,wake all sleeped users to check buffer is dequeued or not */ + ISP_ED_BUFQUE_CTRL_CLAER_ALL, /* 6,free all recored dequeued buffer */ + ISP_ED_BUFQUE_CTRL_MAX +} ISP_ED_BUFQUE_CTRL_ENUM; + +typedef struct { + ISP_ED_BUFQUE_CTRL_ENUM ctrl; + unsigned int processID; + unsigned int callerID; + int p2burstQIdx; + int p2dupCQIdx; + int frameNum; + unsigned int timeoutUs; +} ISP_ED_BUFQUE_STRUCT; + +typedef enum { + ISP_ED_BUF_STATE_NONE = -1, + ISP_ED_BUF_STATE_ENQUE = 0, + ISP_ED_BUF_STATE_RUNNING, + ISP_ED_BUF_STATE_WAIT_DEQUE_FAIL, + ISP_ED_BUF_STATE_DEQUE_SUCCESS, + ISP_ED_BUF_STATE_DEQUE_FAIL +} ISP_ED_BUF_STATE_ENUM; +/******************************************************************************************** + pass1 real time buffer control use cq0c +********************************************************************************************/ +/* */ +#define _rtbc_use_cq0c_ + +#define _MAGIC_NUM_ERR_HANDLING_ + + +#if defined(_rtbc_use_cq0c_) +/* */ +typedef struct _cq_cmd_st_ { + unsigned int inst; + unsigned int data_ptr_pa; +} CQ_CMD_ST; +/* +typedef struct _cq_cmd_rtbc_st_ +{ + CQ_CMD_ST imgo; + CQ_CMD_ST img2o; + CQ_CMD_ST cq0ci; + CQ_CMD_ST end; +}CQ_CMD_RTBC_ST; +*/ +typedef struct _cq_info_rtbc_st_ { + CQ_CMD_ST imgo; + CQ_CMD_ST rrzo; + CQ_CMD_ST next_cq0ci; + CQ_CMD_ST end; + unsigned int imgo_base_pAddr; + unsigned int rrzo_base_pAddr; + signed int imgo_buf_idx; /* used for replace buffer */ + signed int rrzo_buf_idx; /* used for replace buffer */ +} CQ_INFO_RTBC_ST; +typedef struct _cq_ring_cmd_st_ { + CQ_INFO_RTBC_ST cq_rtbc; + unsigned long next_pa; + struct _cq_ring_cmd_st_ *pNext; +} CQ_RING_CMD_ST; +typedef struct _cq_rtbc_ring_st_ { + CQ_RING_CMD_ST rtbc_ring[ISP_RT_CQ0C_BUF_SIZE]; + unsigned int imgo_ring_size; + unsigned int rrzo_ring_size; +} CQ_RTBC_RING_ST; +#endif + +/* CQ0B for AE smoothing, set obc_gain0~3 */ +typedef struct _cq0b_info_rtbc_st_ { + CQ_CMD_ST ob; + CQ_CMD_ST end; +} CQ0B_INFO_RTBC_ST; + +typedef struct _cq0b_ring_cmd_st_ { + CQ0B_INFO_RTBC_ST cq0b_rtbc; + unsigned long next_pa; + struct _cq0b_ring_cmd_st_ *pNext; +} CQ0B_RING_CMD_ST; + +typedef struct _cq0b_rtbc_ring_st_ { + CQ0B_RING_CMD_ST rtbc_ring; +} CQ0B_RTBC_RING_ST; +/* */ + +typedef volatile union _CQ_RTBC_FBC_ { + volatile struct { + unsigned int FBC_CNT:4; + unsigned int rsv_4:7; + unsigned int RCNT_INC:1; + unsigned int rsv_12:2; + unsigned int FBC_EN:1; + unsigned int LOCK_EN:1; + unsigned int FB_NUM:4; + unsigned int RCNT:4; + unsigned int WCNT:4; + unsigned int DROP_CNT:4; + } Bits; + unsigned int Reg_val; +} CQ_RTBC_FBC; + + +#ifdef CONFIG_COMPAT + +typedef struct { + ISP_IRQ_CLEAR_ENUM Clear; /* remove this */ + ISP_IRQ_TYPE_ENUM Type; + unsigned int Status; + int UserNumber; + unsigned int Timeout; + compat_uptr_t UserName; + unsigned int irq_TStamp; + unsigned int bDumpReg; + ISP_IRQ_USER_STRUCT UserInfo; /* v3 only */ + ISP_IRQ_TIME_STRUCT TimeInfo; /* v3 only */ + ISP_EIS_META_STRUCT EisMeta; /* v1&v3 */ + ISP_IRQ_WAITIRQ_SPEUSER_ENUM SpecUser; +} compat_ISP_WAIT_IRQ_STRUCT; + +typedef struct { + ISP_IRQ_TYPE_ENUM Type; + ISP_IRQ_USER_ENUM UserNumber; + unsigned int Status; +} compat_ISP_READ_IRQ_STRUCT; + +typedef struct { + ISP_IRQ_TYPE_ENUM Type; + ISP_IRQ_USER_ENUM UserNumber; + unsigned int Status; +} compat_ISP_CLEAR_IRQ_STRUCT; + + +typedef struct { + compat_uptr_t pData; + unsigned int Count; /* count */ +} compat_ISP_REG_IO_STRUCT; + +/* */ +typedef struct { + ISP_RT_BUF_CTRL_ENUM ctrl; + _isp_dma_enum_ buf_id; + compat_uptr_t data_ptr; + compat_uptr_t ex_data_ptr; /* exchanged buffer */ + compat_uptr_t pExtend; +} compat_ISP_BUFFER_CTRL_STRUCT; + + +typedef struct { + ISP_REF_CNT_CTRL_ENUM ctrl; + ISP_REF_CNT_ID_ENUM id; + compat_uptr_t data_ptr; +} compat_ISP_REF_CNT_CTRL_STRUCT; + +typedef struct { + int userKey; + compat_uptr_t userName; +} compat_ISP_REGISTER_USERKEY_STRUCT; + +#endif + + +/* */ +/******************************************************************************************** + +********************************************************************************************/ + + +/******************************************************************************* +* +********************************************************************************/ +typedef enum { + ISP_CMD_RESET_CAM_P1, /* Reset */ + ISP_CMD_RESET_CAM_P2, + ISP_CMD_RESET_CAMSV, + ISP_CMD_RESET_CAMSV2, + ISP_CMD_RESET_BUF, + ISP_CMD_READ_REG, /* Read register from driver */ + ISP_CMD_WRITE_REG, /* Write register to driver */ + ISP_CMD_HOLD_TIME, + ISP_CMD_HOLD_REG, /* Hold reg write to hw, on/off */ + ISP_CMD_WAIT_IRQ, /* Wait IRQ */ + ISP_CMD_READ_IRQ, /* Read IRQ */ + ISP_CMD_CLEAR_IRQ, /* Clear IRQ */ + ISP_CMD_DUMP_REG, /* Dump ISP registers , for debug usage */ + ISP_CMD_SET_USER_PID, /* for signal */ + ISP_CMD_RT_BUF_CTRL, /* for pass buffer control */ + ISP_CMD_REF_CNT, /* get imem reference count */ + ISP_CMD_DEBUG_FLAG, /* Dump message level */ + ISP_CMD_REGISTER_IRQ, /* register for a specific irq */ + ISP_CMD_UNREGISTER_IRQ, /* unregister for a specific irq */ + ISP_CMD_ED_QUEBUF_CTRL, + ISP_CMD_UPDATE_REGSCEN, + ISP_CMD_QUERY_REGSCEN, + ISP_CMD_UPDATE_BURSTQNUM, + ISP_CMD_QUERY_BURSTQNUM, + ISP_CMD_DUMP_ISR_LOG, /* dump isr log */ + ISP_CMD_GET_CUR_SOF, + ISP_CMD_GET_DMA_ERR, + ISP_CMD_GET_INT_ERR, + ISP_CMD_GET_DROP_FRAME, /* dump current frame informaiton, 1 for drop frmae, 2 for last working frame */ +#ifdef T_STAMP_2_0 + ISP_CMD_SET_FPS, +#endif + ISP_CMD_WAKELOCK_CTRL, + ISP_CMD_REGISTER_IRQ_USER_KEY, /* register for a user key to do irq operation */ + ISP_CMD_MARK_IRQ_REQUEST, /* mark for a specific register befor wait for the interrupt if needed */ + ISP_CMD_GET_MARK2QUERY_TIME, /* query time information between read and mark */ + ISP_CMD_FLUSH_IRQ_REQUEST, /* flush signal */ + ISP_CMD_WAIT_DUMPIMEM, /* wait for dumping imem dbg msg */ + ISP_CMD_WRITE_DUMPIMEM, /* write type for dump imem dbg msg */ +} ISP_CMD_ENUM; +/* */ +#define ISP_RESET_CAM_P1 _IO(ISP_MAGIC, ISP_CMD_RESET_CAM_P1) +#define ISP_RESET_CAM_P2 _IO(ISP_MAGIC, ISP_CMD_RESET_CAM_P2) +#define ISP_RESET_CAMSV _IO(ISP_MAGIC, ISP_CMD_RESET_CAMSV) +#define ISP_RESET_CAMSV2 _IO(ISP_MAGIC, ISP_CMD_RESET_CAMSV2) +#define ISP_RESET_BUF _IO(ISP_MAGIC, ISP_CMD_RESET_BUF) +#define ISP_READ_REGISTER _IOWR(ISP_MAGIC, ISP_CMD_READ_REG, ISP_REG_IO_STRUCT) +#define ISP_WRITE_REGISTER _IOWR(ISP_MAGIC, ISP_CMD_WRITE_REG, ISP_REG_IO_STRUCT) +#define ISP_HOLD_REG_TIME _IOW(ISP_MAGIC, ISP_CMD_HOLD_TIME, ISP_HOLD_TIME_ENUM) +#define ISP_HOLD_REG _IOW(ISP_MAGIC, ISP_CMD_HOLD_REG, bool) +#define ISP_WAIT_IRQ _IOW(ISP_MAGIC, ISP_CMD_WAIT_IRQ, ISP_WAIT_IRQ_STRUCT) +#define ISP_READ_IRQ _IOR(ISP_MAGIC, ISP_CMD_READ_IRQ, ISP_READ_IRQ_STRUCT) +#define ISP_CLEAR_IRQ _IOW(ISP_MAGIC, ISP_CMD_CLEAR_IRQ, ISP_CLEAR_IRQ_STRUCT) +#define ISP_DUMP_REG _IO(ISP_MAGIC, ISP_CMD_DUMP_REG) +#define ISP_SET_USER_PID _IOW(ISP_MAGIC, ISP_CMD_SET_USER_PID, unsigned int) +#define ISP_BUFFER_CTRL _IOWR(ISP_MAGIC, ISP_CMD_RT_BUF_CTRL, ISP_BUFFER_CTRL_STRUCT) +#define ISP_REF_CNT_CTRL _IOWR(ISP_MAGIC, ISP_CMD_REF_CNT, ISP_REF_CNT_CTRL_STRUCT) +#define ISP_DEBUG_FLAG _IOW(ISP_MAGIC, ISP_CMD_DEBUG_FLAG, unsigned char*) +#define ISP_REGISTER_IRQ _IOW(ISP_MAGIC, ISP_CMD_REGISTER_IRQ, ISP_WAIT_IRQ_STRUCT) +#define ISP_UNREGISTER_IRQ _IOW(ISP_MAGIC, ISP_CMD_UNREGISTER_IRQ, ISP_WAIT_IRQ_STRUCT) +#define ISP_ED_QUEBUF_CTRL _IOWR(ISP_MAGIC, ISP_CMD_ED_QUEBUF_CTRL, ISP_ED_BUFQUE_STRUCT) +#define ISP_UPDATE_REGSCEN _IOWR(ISP_MAGIC, ISP_CMD_UPDATE_REGSCEN, unsigned int) +#define ISP_QUERY_REGSCEN _IOR(ISP_MAGIC, ISP_CMD_QUERY_REGSCEN, unsigned int) +#define ISP_UPDATE_BURSTQNUM _IOW(ISP_MAGIC, ISP_CMD_UPDATE_BURSTQNUM, int) +#define ISP_QUERY_BURSTQNUM _IOR(ISP_MAGIC, ISP_CMD_QUERY_BURSTQNUM, int) +#define ISP_DUMP_ISR_LOG _IO(ISP_MAGIC, ISP_CMD_DUMP_ISR_LOG) +#define ISP_GET_CUR_SOF _IOR(ISP_MAGIC, ISP_CMD_GET_CUR_SOF, unsigned int) +#define ISP_GET_DMA_ERR _IOWR(ISP_MAGIC, ISP_CMD_GET_DMA_ERR, unsigned char*) +#define ISP_GET_INT_ERR _IOR(ISP_MAGIC, ISP_CMD_GET_INT_ERR, unsigned char*) +#define ISP_GET_DROP_FRAME _IOWR(ISP_MAGIC, ISP_CMD_GET_DROP_FRAME, unsigned int) +#ifdef T_STAMP_2_0 +#define ISP_SET_FPS _IOW(ISP_MAGIC, ISP_CMD_SET_FPS, unsigned int) +#endif +#define ISP_REGISTER_IRQ_USER_KEY _IOR(ISP_MAGIC, ISP_CMD_REGISTER_IRQ_USER_KEY, ISP_REGISTER_USERKEY_STRUCT) +#define ISP_MARK_IRQ_REQUEST _IOWR(ISP_MAGIC, ISP_CMD_MARK_IRQ_REQUEST, ISP_WAIT_IRQ_STRUCT) +#define ISP_GET_MARK2QUERY_TIME _IOWR(ISP_MAGIC, ISP_CMD_GET_MARK2QUERY_TIME, ISP_WAIT_IRQ_STRUCT) +#define ISP_FLUSH_IRQ_REQUEST _IOW(ISP_MAGIC, ISP_CMD_FLUSH_IRQ_REQUEST, ISP_WAIT_IRQ_STRUCT) +#define ISP_WAIT_DUMPIMEM _IO(ISP_MAGIC, ISP_CMD_WAIT_DUMPIMEM) +#define ISP_WRITE_DUMPIMEM _IOW(ISP_MAGIC, ISP_CMD_WRITE_DUMPIMEM, int) + +#define ISP_WAKELOCK_CTRL _IOWR(ISP_MAGIC, ISP_CMD_WAKELOCK_CTRL, unsigned int) + +#ifdef CONFIG_COMPAT + +#define COMPAT_ISP_READ_REGISTER _IOWR(ISP_MAGIC, ISP_CMD_READ_REG, compat_ISP_REG_IO_STRUCT) +#define COMPAT_ISP_WRITE_REGISTER _IOWR(ISP_MAGIC, ISP_CMD_WRITE_REG, compat_ISP_REG_IO_STRUCT) +#define COMPAT_ISP_DEBUG_FLAG _IOW(ISP_MAGIC, ISP_CMD_DEBUG_FLAG, compat_uptr_t) +#define COMPAT_ISP_GET_DMA_ERR _IOWR(ISP_MAGIC, ISP_CMD_GET_DMA_ERR, compat_uptr_t) +#define COMPAT_ISP_GET_INT_ERR _IOR(ISP_MAGIC, ISP_CMD_GET_INT_ERR, compat_uptr_t) + + +#define COMPAT_ISP_WAIT_IRQ _IOW(ISP_MAGIC, ISP_CMD_WAIT_IRQ, compat_ISP_WAIT_IRQ_STRUCT) +#define COMPAT_ISP_MARK_IRQ_REQUEST _IOWR(ISP_MAGIC, ISP_CMD_MARK_IRQ_REQUEST, compat_ISP_WAIT_IRQ_STRUCT) +#define COMPAT_ISP_GET_MARK2QUERY_TIME _IOWR(ISP_MAGIC, ISP_CMD_GET_MARK2QUERY_TIME, compat_ISP_WAIT_IRQ_STRUCT) +#define COMPAT_ISP_FLUSH_IRQ_REQUEST _IOW(ISP_MAGIC, ISP_CMD_FLUSH_IRQ_REQUEST, compat_ISP_WAIT_IRQ_STRUCT) + + +#define COMPAT_ISP_READ_IRQ _IOR(ISP_MAGIC, ISP_CMD_READ_IRQ, compat_ISP_READ_IRQ_STRUCT) +#define COMPAT_ISP_BUFFER_CTRL _IOWR(ISP_MAGIC, ISP_CMD_RT_BUF_CTRL, compat_ISP_BUFFER_CTRL_STRUCT) +#define COMPAT_ISP_REF_CNT_CTRL _IOWR(ISP_MAGIC, ISP_CMD_REF_CNT, compat_ISP_REF_CNT_CTRL_STRUCT) +#define COMPAT_ISP_REGISTER_IRQ_USER_KEY _IOR(ISP_MAGIC, ISP_CMD_REGISTER_IRQ_USER_KEY, compat_ISP_REGISTER_USERKEY_STRUCT) + +#endif + +/* */ +bool ISP_RegCallback(ISP_CALLBACK_STRUCT *pCallback); +bool ISP_UnregCallback(ISP_CALLBACK_ENUM Type); +int32_t ISP_MDPClockOnCallback(uint64_t engineFlag); +int32_t ISP_MDPDumpCallback(uint64_t engineFlag, int level); +int32_t ISP_MDPResetCallback(uint64_t engineFlag); + +int32_t ISP_MDPClockOffCallback(uint64_t engineFlag); + +int32_t ISP_BeginGCECallback(uint32_t taskID, uint32_t *regCount, uint32_t **regAddress); +int32_t ISP_EndGCECallback(uint32_t taskID, uint32_t regCount, uint32_t *regValues); + +/* */ +#endif diff --git a/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_sysram.h b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_sysram.h new file mode 100755 index 0000000000000000000000000000000000000000..88188b0b748d7cea87c9fe4c260e01f1558af9de --- /dev/null +++ b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_sysram.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef CAMERA_SYSRAM_H +#define CAMERA_SYSRAM_H +/* ----------------------------------------------------------------------------- */ +#define SYSRAM_DEV_NAME "camera-sysram" +#define SYSRAM_MAGIC_NO 'p' +/* ----------------------------------------------------------------------------- */ +typedef enum { + SYSRAM_USER_VIDO, + SYSRAM_USER_GDMA, + SYSRAM_USER_SW_FD, + SYSRAM_USER_AMOUNT, + SYSRAM_USER_NONE +} SYSRAM_USER_ENUM; +/* */ +typedef struct { + unsigned long Alignment; + unsigned long Size; + SYSRAM_USER_ENUM User; + unsigned long Addr; /* In/Out : address */ + unsigned long TimeoutMS; /* In : millisecond */ +} SYSRAM_ALLOC_STRUCT; +/* */ +typedef enum { + SYSRAM_CMD_ALLOC, + SYSRAM_CMD_FREE, + SYSRAM_CMD_DUMP +} SYSRAM_CMD_ENUM; +/* ----------------------------------------------------------------------------- */ +#define SYSRAM_ALLOC _IOWR(SYSRAM_MAGIC_NO, SYSRAM_CMD_ALLOC, SYSRAM_ALLOC_STRUCT) +#define SYSRAM_FREE _IOWR(SYSRAM_MAGIC_NO, SYSRAM_CMD_FREE, SYSRAM_USER_ENUM) +#define SYSRAM_DUMP _IO(SYSRAM_MAGIC_NO, SYSRAM_CMD_DUMP) +/* ----------------------------------------------------------------------------- */ +#endif diff --git a/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_sysram_imp.h b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_sysram_imp.h new file mode 100755 index 0000000000000000000000000000000000000000..fdc72ca58ab345ce7a68c1c96c7d9252def3c459 --- /dev/null +++ b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/camera_sysram_imp.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef CAMERA_SYSRAM_IMP_H +#define CAMERA_SYSRAM_IMP_H +/* ----------------------------------------------------------------------------- */ +typedef unsigned long long MUINT64; +typedef long long MINT64; +typedef unsigned long MUINT32; +typedef long MINT32; +typedef unsigned char MUINT8; +typedef char MINT8; +typedef bool MBOOL; +#define MTRUE true +#define MFALSE false +/* ----------------------------------------------------------------------------- */ +#define MyTag "SYSRAM" + +#define LOG_MSG(format, args...) pr_debug(MyTag format, ##args) +#define LOG_WRN(format, args...) pr_warn(MyTag format, ##args) +#define LOG_ERR(format, args...) pr_err(MyTag format, ##args) +#define LOG_DMP(format, args...) pr_err(MyTag format, ##args) +/* ----------------------------------------------------------------------------- */ +#define SYSRAM_DEBUG_DEFAULT (0xFFFFFFFF) +#define SYSRAM_JIFFIES_MAX (0xFFFFFFFF) +#define SYSRAM_PROC_NAME "Default" +/* ----------------------------------------------------------------------------- */ +/* originally define in mt_reg_base.h */ +#define SYSRAM_BASE (0xF9000000) +/* ----------------------------------------------------------------------------- */ +#define SYSRAM_BASE_PHY_ADDR ((SYSRAM_BASE&0x0FFFFFFF)|0x10000000) +#define SYSRAM_BASE_SIZE (81920) /* 32K+48K */ +#define SYSRAM_BASE_ADDR_BANK_0 (SYSRAM_BASE_PHY_ADDR) +#define SYSRAM_BASE_SIZE_BANK_0 (SYSRAM_BASE_SIZE) +/* */ +#define SYSRAM_USER_SIZE_VIDO (SYSRAM_BASE_SIZE) /* (78408)//(74496) // Always allocate max SYSRAM size because there is no other user. //78408: Max size used when format is RGB565. */ +#define SYSRAM_USER_SIZE_GDMA (46080) +#define SYSRAM_USER_SIZE_SW_FD (0) /* TBD */ +/* */ +#define SYSRAM_MEM_NODE_AMOUNT_PER_POOL (SYSRAM_USER_AMOUNT*2 + 2) +/* ----------------------------------------------------------------------------- */ +typedef struct { + pid_t pid; /* thread id */ + pid_t tgid; /* process id */ + char ProcName[TASK_COMM_LEN]; /* executable name */ + MUINT64 Time64; + MUINT32 TimeS; + MUINT32 TimeUS; +} SYSRAM_USER_STRUCT; +/* */ +typedef struct { + spinlock_t SpinLock; + MUINT32 TotalUserCount; + MUINT32 AllocatedTbl; + MUINT32 AllocatedSize[SYSRAM_USER_AMOUNT]; + SYSRAM_USER_STRUCT UserInfo[SYSRAM_USER_AMOUNT]; + wait_queue_head_t WaitQueueHead; + MBOOL EnableClk; + MUINT32 DebugFlag; + dev_t DevNo; + struct cdev *pCharDrv; + struct class *pClass; +} SYSRAM_STRUCT; +/* */ +typedef struct { + pid_t Pid; + pid_t Tgid; + char ProcName[TASK_COMM_LEN]; + MUINT32 Table; + MUINT64 Time64; + MUINT32 TimeS; + MUINT32 TimeUS; +} SYSRAM_PROC_STRUCT; + +/* */ +typedef enum { + SYSRAM_MEM_BANK_0, + SYSRAM_MEM_BANK_AMOUNT, + SYSRAM_MEM_BANK_BAD +} SYSRAM_MEM_BANK_ENUM; +/* */ +typedef struct SYSRAM_MEM_NODE { + SYSRAM_USER_ENUM User; + MUINT32 Offset; + MUINT32 Length; + MUINT32 Index; + struct SYSRAM_MEM_NODE *pNext; + struct SYSRAM_MEM_NODE *pPrev; +} SYSRAM_MEM_NODE_STRUCT; +/* */ +typedef struct { + SYSRAM_MEM_NODE_STRUCT * const pMemNode; + MUINT32 const UserAmount; + MUINT32 const Addr; + MUINT32 const Size; + MUINT32 IndexTbl; + MUINT32 UserCount; +} SYSRAM_MEM_POOL_STRUCT; +/* ------------------------------------------------------------------------------ */ +static SYSRAM_MEM_NODE_STRUCT SysramMemNodeBank0Tbl[SYSRAM_MEM_NODE_AMOUNT_PER_POOL]; +static SYSRAM_MEM_POOL_STRUCT SysramMemPoolInfo[SYSRAM_MEM_BANK_AMOUNT] = { + + [SYSRAM_MEM_BANK_0] = { + + .pMemNode = &SysramMemNodeBank0Tbl[0], + .UserAmount = SYSRAM_MEM_NODE_AMOUNT_PER_POOL, + .Addr = SYSRAM_BASE_ADDR_BANK_0, + .Size = SYSRAM_BASE_SIZE_BANK_0, + .IndexTbl = (~0x1), + .UserCount = 0, + } +}; + +/* */ +static inline SYSRAM_MEM_POOL_STRUCT *SYSRAM_GetMemPoolInfo(SYSRAM_MEM_BANK_ENUM const MemBankNo) +{ + if (SYSRAM_MEM_BANK_AMOUNT > MemBankNo) { + return &SysramMemPoolInfo[MemBankNo]; + } + return NULL; +} + +/* */ +enum { + SysramMemBank0UserMask = (1 << SYSRAM_USER_VIDO) + | (1 << SYSRAM_USER_GDMA) + | (1 << SYSRAM_USER_SW_FD) + , + SysramLogUserMask = (1 << SYSRAM_USER_VIDO) + | (1 << SYSRAM_USER_GDMA) + | (1 << SYSRAM_USER_SW_FD) +}; +/* */ +static SYSRAM_MEM_BANK_ENUM SYSRAM_GetMemBankNo(SYSRAM_USER_ENUM const User) +{ + MUINT32 const UserMask = (1 << User); + /* */ + if (UserMask & SysramMemBank0UserMask) { + return SYSRAM_MEM_BANK_0; + } + /* */ + return SYSRAM_MEM_BANK_BAD; +} + +/* */ +static char const *const SysramUserName[SYSRAM_USER_AMOUNT] = { + + [SYSRAM_USER_VIDO] = "VIDO", + [SYSRAM_USER_GDMA] = "GDMA", + [SYSRAM_USER_SW_FD] = "SW FD" +}; + +/* */ +static MUINT32 const SysramUserSize[SYSRAM_USER_AMOUNT] = { + + [SYSRAM_USER_VIDO] = (3 + SYSRAM_USER_SIZE_VIDO) / 4 * 4, + [SYSRAM_USER_GDMA] = (3 + SYSRAM_USER_SIZE_GDMA) / 4 * 4, + [SYSRAM_USER_SW_FD] = (3 + SYSRAM_USER_SIZE_SW_FD) / 4 * 4 +}; + +/* ------------------------------------------------------------------------------ */ +#endif diff --git a/drivers/misc/mediatek/cameraisp/src/mt6755/inc/mt_typedefs.h b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/mt_typedefs.h new file mode 100755 index 0000000000000000000000000000000000000000..61f67b86bbcb7baa079718e715476fa30b36eb64 --- /dev/null +++ b/drivers/misc/mediatek/cameraisp/src/mt6755/inc/mt_typedefs.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _TYPEDEFS_H +#define _TYPEDEFS_H + +#ifndef BOOL +typedef unsigned char BOOL; +#endif + +typedef unsigned char UINT8; +typedef unsigned int UINT32; +typedef signed int INT32; + +#if 0 +typedef unsigned short UINT16; +typedef unsigned short USHORT; +typedef signed char INT8; +typedef signed short INT16; +typedef unsigned int DWORD; +typedef void VOID; +typedef unsigned char BYTE; +typedef float FLOAT; +#endif + +#endif diff --git a/drivers/misc/mediatek/ccci_util/mt6755/Makefile b/drivers/misc/mediatek/ccci_util/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6f01c898c06be62697184b9005c9086ff6914375 --- /dev/null +++ b/drivers/misc/mediatek/ccci_util/mt6755/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += -I$(srctree)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/ccci_util/$(MTK_PLATFORM) +ifeq ($(CONFIG_MTK_PMIC_CHIP_MT6353), y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/pmic/ +endif +# always build-in parts +obj-$(CONFIG_MTK_CCCI_DEVICES) += ccci_off.o diff --git a/drivers/misc/mediatek/ccci_util/mt6755/ccci_off.c b/drivers/misc/mediatek/ccci_util/mt6755/ccci_off.c new file mode 100644 index 0000000000000000000000000000000000000000..dc5d5aa483d2918aee527da5fffa1e9553d8a258 --- /dev/null +++ b/drivers/misc/mediatek/ccci_util/mt6755/ccci_off.c @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif /*CONFIG_MTK_CLKMGR */ + +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#include +#endif +#include "ccci_off.h" +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#include "include/pmic_api_buck.h" +#endif +#if !defined(CONFIG_MTK_CLKMGR) +static struct clk *clk_scp_sys_md1_main; +#endif + +#if !defined(CONFIG_MTK_ECCCI_DRIVER) || defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) + +#define sync_write32(v, a) mt_reg_sync_writel(v, a) +#define sync_write16(v, a) mt_reg_sync_writew(v, a) +#define sync_write8(v, a) mt_reg_sync_writeb(v, a) + +/* */ +#define MD_P_TOPSM_BASE (0x200D0000) +#define REG_MD_P_TOPSM_RM_PWR0_CON(base) ((base)+0x0800) +#define REG_MD_P_TOPSM_RM_PWR1_CON(base) ((base)+0x0804) +#define REG_MD_P_TOPSM_RM_PWR2_CON(base) ((base)+0x0808) +#define REG_MD_P_TOPSM_RM_PWR3_CON(base) ((base)+0x080C) +#define REG_MD_P_TOPSM_RM_PWR4_CON(base) ((base)+0x0810) +#define REG_MD_P_TOPSM_RM_TMR_PWR0(base) ((base)+0x0018) +#define REG_MD_P_TOPSM_RM_TMR_PWR1(base) ((base)+0x001C) + +#define MD_L1_TOPSM_BASE (0x26070000) +#define REG_MD_L1_TOPSM_SM_TMR_PWR0(base) ((base)+0x0140) +#define REG_MD_L1_TOPSM_SM_TMR_PWR1(base) ((base)+0x0144) +#define REG_MD_L1_TOPSM_SM_TMR_PWR2(base) ((base)+0x0148) +#define REG_MD_L1_TOPSM_SM_TMR_PWR3(base) ((base)+0x014C) +#define REG_MD_L1_TOPSM_SM_TMR_PWR4(base) ((base)+0x0150) + +static void internal_md_power_down(void) +{ + int ret = 0; + void __iomem *md_p_topsm_base, *md_l1_topsm_base; + + pr_debug("[ccci-off]shutdown MDSYS1 !!!\n"); +#if defined(CONFIG_MTK_CLKMGR) + pr_debug("[ccci-off]Call start md_power_on()\n"); + ret = md_power_on(SYS_MD1); + pr_debug("[ccci-off]Call end md_power_on() ret=%d\n", ret); +#else + pr_debug("[ccci-off]Call start clk_prepare_enable()\n"); + clk_prepare_enable(clk_scp_sys_md1_main); + pr_debug("[ccci-off]Call end clk_prepare_enable()\n"); +#endif + pr_debug("[ccci-off]0.power on MD_INFRA/MODEM_TOP ret=%d\n", ret); + if (ret) + return; + + md_p_topsm_base = ioremap_nocache(MD_P_TOPSM_BASE, 0x830); + md_l1_topsm_base = ioremap_nocache(MD_L1_TOPSM_BASE, 0x200); + /* 1. Shutting off ARM7, HSPAL2, LTEL2 power domains */ + /* Shutting off ARM7 through software */ + sync_write32(ioread32(REG_MD_P_TOPSM_RM_PWR1_CON(md_p_topsm_base))&(~0xE6045), + REG_MD_P_TOPSM_RM_PWR1_CON(md_p_topsm_base)); + sync_write32(ioread32(REG_MD_P_TOPSM_RM_PWR1_CON(md_p_topsm_base))|(0xB8), + REG_MD_P_TOPSM_RM_PWR1_CON(md_p_topsm_base)); + /* Masking control of ostimer on ARM7,HSPAL2,LTEL2 */ + sync_write32(0x01, REG_MD_P_TOPSM_RM_TMR_PWR0(md_p_topsm_base)); + /* De-asserting software power req */ + sync_write32(ioread32(REG_MD_P_TOPSM_RM_PWR0_CON(md_p_topsm_base))&(~0x44), + REG_MD_P_TOPSM_RM_PWR0_CON(md_p_topsm_base));/* PSMCU */ + sync_write32(ioread32(REG_MD_P_TOPSM_RM_PWR2_CON(md_p_topsm_base))&(~0x44), + REG_MD_P_TOPSM_RM_PWR2_CON(md_p_topsm_base));/* HSPAL2 */ + sync_write32(ioread32(REG_MD_P_TOPSM_RM_PWR3_CON(md_p_topsm_base))&(~0x44), + REG_MD_P_TOPSM_RM_PWR3_CON(md_p_topsm_base));/* LTEL2 */ + sync_write32(ioread32(REG_MD_P_TOPSM_RM_PWR4_CON(md_p_topsm_base))&(~0x44), + REG_MD_P_TOPSM_RM_PWR4_CON(md_p_topsm_base));/* INFRA */ + + /* 2. PSMCU and INFRA power domains should be shut off at the end, + after complete register sequence has been executed: */ + sync_write32(0x00, REG_MD_P_TOPSM_RM_TMR_PWR0(md_p_topsm_base));/* PSMCU into sleep */ + sync_write32(0x00, REG_MD_P_TOPSM_RM_TMR_PWR1(md_p_topsm_base));/* INFRA into sleep */ + + /* 3. Shutting off power domains except L1MCU by masking all ostimers control + on mtcmos power domain: */ + sync_write32(ioread32(REG_MD_L1_TOPSM_SM_TMR_PWR0(md_l1_topsm_base))|~(0x1), + REG_MD_L1_TOPSM_SM_TMR_PWR0(md_l1_topsm_base)); + sync_write32(0xFFFFFFFF, REG_MD_L1_TOPSM_SM_TMR_PWR1(md_l1_topsm_base)); + sync_write32(0xFFFFFFFF, REG_MD_L1_TOPSM_SM_TMR_PWR2(md_l1_topsm_base)); + sync_write32(0xFFFFFFFF, REG_MD_L1_TOPSM_SM_TMR_PWR3(md_l1_topsm_base)); + sync_write32(0xFFFFFFFF, REG_MD_L1_TOPSM_SM_TMR_PWR4(md_l1_topsm_base)); + + /* 4. L1MCU power domain is shut off in the end + after all register sequence has been executed: */ + sync_write32(0xFFFFFFFF, REG_MD_L1_TOPSM_SM_TMR_PWR0(md_l1_topsm_base)); + + pr_notice("[ccci-off]8.power off ARM7, HSPAL2, LTEL2\n"); + /* no need to poll, as MD SW didn't run and enter sleep mode, polling will not get result */ +#if defined(CONFIG_MTK_CLKMGR) + ret = md_power_off(SYS_MD1, 0); +#else + clk_disable_unprepare(clk_scp_sys_md1_main); +#endif +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + vmd1_pmic_setting_off(); +#else + /* VMODEM off */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN, 0); /* 0x063A[8]=0, 0:SW control, 1:HW control */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_EN, 0); /* 0x062C[0]=0, 0:Disable, 1:Enable */ + /* VMD1 off */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_VSLEEP_EN, 0); /* 0x064E[8]=0, 0:SW control, 1:HW control */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_EN, 0); /* 0x0640[0]=0, 0:Disable, 1:Enable */ + /* VSRAM_MD off */ + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN, 0); /* 0x0662[8]=0, 0:SW control, 1:HW control */ + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_EN, 0); /* 0x0654[0]=0, 0:Disable, 1:Enable */ +#endif + iounmap(md_p_topsm_base); + iounmap(md_l1_topsm_base); + +} + +static int modem_power_down_worker(void *data) +{ + unsigned int val; + + val = get_devinfo_with_index(4); + if ((val & (0x1 << 1)) == 0) + internal_md_power_down(); + else + pr_debug("[ccci-off]md1 effused,no need power off\n"); + return 0; +} + +static void modem_power_down(void) +{ + /* start kthread to power down modem */ + struct task_struct *md_power_kthread; + + md_power_kthread = kthread_run(modem_power_down_worker, NULL, "md_power_off_kthread"); + if (IS_ERR(md_power_kthread)) { + pr_debug("[ccci-off] create kthread for power off md fail, only direct call API\n"); + modem_power_down_worker(NULL); + } else { + pr_debug("[ccci-off] create kthread for power off md ok\n"); + } +} +#endif + +int ccci_md_off(void) +{ +#ifndef CONFIG_MTK_ECCCI_DRIVER + modem_power_down(); +#else +#ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING + if ((get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT) || (get_boot_mode() == LOW_POWER_OFF_CHARGING_BOOT)) { + pr_debug("[ccci-off]power off MD in charging mode %d\n", get_boot_mode()); + modem_power_down(); + } +#endif +#endif + return 0; +} + +#if !defined(CONFIG_MTK_CLKMGR) +static int ccci_off_probe(struct platform_device *pdev) +{ + clk_scp_sys_md1_main = devm_clk_get(&pdev->dev, "scp-sys-md1-main"); + if (IS_ERR(clk_scp_sys_md1_main)) { + pr_debug("[ccci-off]modem %d get scp-sys-md1-main failed\n", 1); + return -1; + } + pr_debug("[ccci-off][CCF]clk_scp_sys_md1_main=%p\n", clk_scp_sys_md1_main); + + ccci_md_off(); + + return 0; +} + +static int ccci_off_remove(struct platform_device *pdev) +{ + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id ccci_off_of_ids[] = { + {.compatible = "mediatek,ccci_off",}, + {} +}; +#endif +static struct platform_driver ccci_off_dev_drv = { + .probe = ccci_off_probe, + .remove = ccci_off_remove, + .driver = { + .name = "ccci_off", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = ccci_off_of_ids, +#endif + }, +}; +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + +static int __init ccci_off_init(void) +{ + int ret; +#if defined(CONFIG_MTK_CLKMGR) + pr_debug("ccci_off_init 1\n"); + ret = ccci_md_off(); +#else + ret = platform_driver_register(&ccci_off_dev_drv); + if (ret) + pr_debug("[ccci-off] platform driver registered failed(%d)\n", ret); + else + pr_debug("[ccci-off]platform driver registered OK\n"); +#endif + return 0; +} +module_init(ccci_off_init); diff --git a/drivers/misc/mediatek/ccci_util/mt6755/ccci_off.h b/drivers/misc/mediatek/ccci_util/mt6755/ccci_off.h new file mode 100644 index 0000000000000000000000000000000000000000..29c09937aed35db8be9579be5e8c18f0f8fa083f --- /dev/null +++ b/drivers/misc/mediatek/ccci_util/mt6755/ccci_off.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +extern unsigned int get_devinfo_with_index(unsigned int index); diff --git a/drivers/misc/mediatek/chip/mt6755/Makefile b/drivers/misc/mediatek/chip/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5cb633b5b0f493a952e5af831bdf3a7329c08c07 --- /dev/null +++ b/drivers/misc/mediatek/chip/mt6755/Makefile @@ -0,0 +1,15 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += CHIP.o +CHIP-y := mt_chip.o diff --git a/drivers/misc/mediatek/chip/mt6755/mt_chip.c b/drivers/misc/mediatek/chip/mt6755/mt_chip.c new file mode 100644 index 0000000000000000000000000000000000000000..46e59e43ad6cbdd9005c1b188ba4711ba6c76b19 --- /dev/null +++ b/drivers/misc/mediatek/chip/mt6755/mt_chip.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define pr_fmt(fmt) "["KBUILD_MODNAME"] " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt_chip_common.h" + +extern u32 __attribute__((weak)) get_devinfo_with_index(u32); + +void __iomem *APHW_CODE = NULL; +void __iomem *APHW_SUBCODE = NULL; +void __iomem *APHW_VER = NULL; +void __iomem *APSW_VER = NULL; + +enum { + CID_UNINIT = 0, + CID_INITIALIZING = 1, + CID_INITIALIZED = 2, +} CID_INIT_STATE; + +static atomic_t g_cid_init = ATOMIC_INIT(CID_UNINIT); + +static void init_chip_id(unsigned int line) +{ + if (CID_INITIALIZED == atomic_read(&g_cid_init)) + return; + + if (CID_INITIALIZING == atomic_read(&g_cid_init)) { + pr_warn("%s (%d) state(%d)\n", __func__, line, atomic_read(&g_cid_init)); + return; + } + + atomic_set(&g_cid_init, CID_INITIALIZING); +#ifdef CONFIG_OF + { + struct device_node *node = of_find_compatible_node(NULL, NULL, "mediatek,chipid"); + + if (node) { + APHW_CODE = of_iomap(node, 0); + WARN(!APHW_CODE, "unable to map APHW_CODE registers\n"); + APHW_SUBCODE = of_iomap(node, 1); + WARN(!APHW_SUBCODE, "unable to map APHW_SUBCODE registers\n"); + APHW_VER = of_iomap(node, 2); + WARN(!APHW_VER, "unable to map APHW_VER registers\n"); + APSW_VER = of_iomap(node, 3); + WARN(!APSW_VER, "unable to map APSW_VER registers\n"); + atomic_set(&g_cid_init, CID_INITIALIZED); + } else { + atomic_set(&g_cid_init, CID_UNINIT); + pr_warn("node not found\n"); + } + } +#endif +} + +/* return hardware version */ +unsigned int __chip_hw_code(void) +{ + init_chip_id(__LINE__); + return (APHW_CODE) ? readl(IOMEM(APHW_CODE)) : (C_UNKNOWN_CHIP_ID); +} + +unsigned int __chip_hw_ver(void) +{ + init_chip_id(__LINE__); + return (APHW_VER) ? readl(IOMEM(APHW_VER)) : (C_UNKNOWN_CHIP_ID); +} + +unsigned int __chip_sw_ver(void) +{ + init_chip_id(__LINE__); + return (APSW_VER) ? readl(IOMEM(APSW_VER)) : (C_UNKNOWN_CHIP_ID); +} +EXPORT_SYMBOL(mt_get_chip_sw_ver); + +unsigned int __chip_hw_subcode(void) +{ + init_chip_id(__LINE__); + return (APHW_SUBCODE) ? readl(IOMEM(APHW_SUBCODE)) : (C_UNKNOWN_CHIP_ID); +} + +unsigned int __chip_func_code(void) +{ + unsigned int val = get_devinfo_with_index(21) & 0x000000FF; /*[7:0]*/ + return val; +} + +unsigned int __chip_date_code(void) +{ + return 0; /*not support*/ +} + +unsigned int __chip_proj_code(void) +{ + return 0; /*not support*/ +} + +unsigned int __chip_fab_code(void) +{ + return 0; /*not support*/ +} + +unsigned int mt_get_chip_id(void) +{ + unsigned int chip_id = __chip_hw_code(); + /*convert id if necessary */ + return chip_id; +} +EXPORT_SYMBOL(mt_get_chip_id); + +unsigned int mt_get_chip_hw_code(void) +{ + return __chip_hw_code(); +} +EXPORT_SYMBOL(mt_get_chip_hw_code); + +unsigned int mt_get_chip_hw_ver(void) +{ + return __chip_hw_ver(); +} + +unsigned int mt_get_chip_hw_subcode(void) +{ + return __chip_hw_subcode(); +} + +unsigned int mt_get_chip_sw_ver(void) +{ + return __chip_sw_ver(); +} + +static chip_info_cb g_cbs[CHIP_INFO_MAX] = { + NULL, + mt_get_chip_hw_code, + mt_get_chip_hw_subcode, + mt_get_chip_hw_ver, + (chip_info_cb) mt_get_chip_sw_ver, + + __chip_hw_code, + __chip_hw_subcode, + __chip_hw_ver, + __chip_sw_ver, + + __chip_func_code, + NULL, + NULL, + NULL, + NULL, +}; + +unsigned int mt_get_chip_info(unsigned int id) +{ + if ((id <= CHIP_INFO_NONE) || (id >= CHIP_INFO_MAX)) + return 0; + else if (NULL == g_cbs[id]) + return 0; + return g_cbs[id] (); +} +EXPORT_SYMBOL(mt_get_chip_info); + + +int __init chip_mod_init(void) +{ + struct mt_chip_drv *p_drv = get_mt_chip_drv(); + + pr_debug("CODE = %04x %04x %04x %04x, %04x %04x %04x %04x, %04X %04X\n", + __chip_hw_code(), __chip_hw_subcode(), __chip_hw_ver(), + __chip_sw_ver(), __chip_func_code(), __chip_proj_code(), + __chip_date_code(), __chip_fab_code(), mt_get_chip_hw_ver(), mt_get_chip_sw_ver()); + + p_drv->info_bit_mask |= CHIP_INFO_BIT(CHIP_INFO_HW_CODE) | + CHIP_INFO_BIT(CHIP_INFO_HW_SUBCODE) | + CHIP_INFO_BIT(CHIP_INFO_HW_VER) | + CHIP_INFO_BIT(CHIP_INFO_SW_VER) | CHIP_INFO_BIT(CHIP_INFO_FUNCTION_CODE); + + p_drv->get_chip_info = mt_get_chip_info; + + pr_debug("CODE = %08X %p", p_drv->info_bit_mask, p_drv->get_chip_info); + + return 0; +} + +core_initcall(chip_mod_init); +MODULE_DESCRIPTION("MTK Chip Information"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/cmdq/v2/mt6755/Makefile b/drivers/misc/mediatek/cmdq/v2/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3a1a48044d7588bf78ba591a65cc52391abb4a0b --- /dev/null +++ b/drivers/misc/mediatek/cmdq/v2/mt6755/Makefile @@ -0,0 +1,27 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +# drivers/cmdq + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/cmdq/v2 \ + -I$(srctree)/drivers/misc/mediatek/m4u/$(MTK_PLATFORM) + +# Enable MET +ccflags-y += -DMET_USER_EVENT_SUPPORT + +# Common Clock Framework +ifneq ($(CONFIG_MTK_CLKMGR),y) +ccflags-y += -DCMDQ_USE_CCF +endif + +obj-y += cmdq_mdp.o \ No newline at end of file diff --git a/drivers/misc/mediatek/cmdq/v2/mt6755/cmdq_engine.h b/drivers/misc/mediatek/cmdq/v2/mt6755/cmdq_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..f6c607d3c840fad5646a467e8f4b22dc7a1632d6 --- /dev/null +++ b/drivers/misc/mediatek/cmdq/v2/mt6755/cmdq_engine.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __CMDQ_ENGINE_H__ +#define __CMDQ_ENGINE_H__ + +typedef enum CMDQ_ENG_ENUM { + /* ISP */ + CMDQ_ENG_ISP_IMGI = 0, + CMDQ_ENG_ISP_IMGO, /* 1 */ + CMDQ_ENG_ISP_IMG2O, /* 2 */ + + /* MDP */ + CMDQ_ENG_MDP_CAMIN, /* 3 */ + CMDQ_ENG_MDP_RDMA0, /* 4 */ + CMDQ_ENG_MDP_RSZ0, /* 5 */ + CMDQ_ENG_MDP_RSZ1, /* 6 */ + CMDQ_ENG_MDP_TDSHP0, /* 7 */ + CMDQ_ENG_MDP_WROT0, /* 8 */ + CMDQ_ENG_MDP_WDMA, /* 9 */ + CMDQ_ENG_MDP_COLOR0, /* 10 */ + + /* JPEG & VENC */ + CMDQ_ENG_JPEG_ENC, /* 11 */ + CMDQ_ENG_VIDEO_ENC, /* 12 */ + CMDQ_ENG_JPEG_DEC, /* 13 */ + CMDQ_ENG_JPEG_REMDC, /* 14 */ + + /* DISP */ + CMDQ_ENG_DISP_AAL, /* 15 */ + CMDQ_ENG_DISP_COLOR0, /* 16 */ + CMDQ_ENG_DISP_RDMA0, /* 17 */ + CMDQ_ENG_DISP_RDMA1, /* 18 */ + CMDQ_ENG_DISP_WDMA0, /* 19 */ + CMDQ_ENG_DISP_WDMA1, /* 20 */ + CMDQ_ENG_DISP_OVL0, /* 21 */ + CMDQ_ENG_DISP_OVL1, /* 22 */ + CMDQ_ENG_DISP_GAMMA, /* 23 */ + CMDQ_ENG_DISP_DSI0_VDO, /* 24 */ + CMDQ_ENG_DISP_DSI0_CMD, /* 25 */ + CMDQ_ENG_DISP_DSI0, /* 26 */ + CMDQ_ENG_DISP_DPI, /* 27 */ + CMDQ_ENG_DISP_2L_OVL0, /* 28 */ + CMDQ_ENG_DISP_2L_OVL1, /* 29 */ + + /* temp: CMDQ internal usage */ + CMDQ_ENG_CMDQ, + CMDQ_ENG_DISP_MUTEX, + CMDQ_ENG_MMSYS_CONFIG, + + /* Dummy Engine */ + CMDQ_ENG_MDP_RDMA1, + CMDQ_ENG_MDP_RSZ2, + CMDQ_ENG_MDP_TDSHP1, + CMDQ_ENG_MDP_MOUT0, + CMDQ_ENG_MDP_MOUT1, + CMDQ_ENG_MDP_WROT1, + + CMDQ_ENG_DISP_UFOE, + CMDQ_ENG_DISP_COLOR1, + CMDQ_ENG_DISP_RDMA2, + CMDQ_ENG_DISP_OVL2, + CMDQ_ENG_DISP_2L_OVL2, + CMDQ_ENG_DISP_MERGE, + CMDQ_ENG_DISP_SPLIT0, + CMDQ_ENG_DISP_SPLIT1, + CMDQ_ENG_DISP_DSI1_VDO, + CMDQ_ENG_DISP_DSI1_CMD, + CMDQ_ENG_DISP_DSI1, + + CMDQ_ENG_DPE, + + CMDQ_MAX_ENGINE_COUNT /* ALWAYS keep at the end */ +} CMDQ_ENG_ENUM; + +#define CMDQ_ENG_MDP_COLOR (CMDQ_ENG_MDP_COLOR0) + +#endif /* __CMDQ_ENGINE_H__ */ diff --git a/drivers/misc/mediatek/cmdq/v2/mt6755/cmdq_mdp.c b/drivers/misc/mediatek/cmdq/v2/mt6755/cmdq_mdp.c new file mode 100644 index 0000000000000000000000000000000000000000..d7f1137f2b464cdfbbe18d51c5ac14c333235177 --- /dev/null +++ b/drivers/misc/mediatek/cmdq/v2/mt6755/cmdq_mdp.c @@ -0,0 +1,809 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "cmdq_core.h" +#include "cmdq_reg.h" +#include "cmdq_mdp_common.h" +#ifdef CMDQ_MET_READY +#include +#endif +#ifndef CMDQ_USE_CCF +#include +#endif /* !defined(CMDQ_USE_CCF) */ +#include "m4u.h" +#include + +#include "cmdq_device.h" + +typedef struct CmdqMdpModuleBaseVA { + long MDP_RDMA; + long MDP_RSZ0; + long MDP_RSZ1; + long MDP_WDMA; + long MDP_WROT; + long MDP_TDSHP; + long MDP_COLOR; + long VENC; +} CmdqMdpModuleBaseVA; +static CmdqMdpModuleBaseVA gCmdqMdpModuleBaseVA; + +#ifndef CMDQ_USE_CCF +#define IMP_ENABLE_MDP_HW_CLOCK(FN_NAME, HW_NAME) \ +uint32_t cmdq_mdp_enable_clock_##FN_NAME(bool enable) \ +{ \ + return cmdq_dev_enable_mtk_clock(enable, MT_CG_DISP0_##HW_NAME, "CMDQ_MDP_"#HW_NAME); \ +} +#define IMP_MDP_HW_CLOCK_IS_ENABLE(FN_NAME, HW_NAME) \ +bool cmdq_mdp_clock_is_enable_##FN_NAME(void) \ +{ \ + return cmdq_dev_mtk_clock_is_enable(MT_CG_DISP0_##HW_NAME); \ +} +#else +typedef struct CmdqMdpModuleClock { + struct clk *clk_CAM_MDP; + struct clk *clk_MDP_RDMA; + struct clk *clk_MDP_RSZ0; + struct clk *clk_MDP_RSZ1; + struct clk *clk_MDP_WDMA; + struct clk *clk_MDP_WROT; + struct clk *clk_MDP_TDSHP; + struct clk *clk_MDP_COLOR; +} CmdqMdpModuleClock; + +static CmdqMdpModuleClock gCmdqMdpModuleClock; + +#define IMP_ENABLE_MDP_HW_CLOCK(FN_NAME, HW_NAME) \ +uint32_t cmdq_mdp_enable_clock_##FN_NAME(bool enable) \ +{ \ + return cmdq_dev_enable_device_clock(enable, gCmdqMdpModuleClock.clk_##HW_NAME, #HW_NAME "-clk"); \ +} +#define IMP_MDP_HW_CLOCK_IS_ENABLE(FN_NAME, HW_NAME) \ +bool cmdq_mdp_clock_is_enable_##FN_NAME(void) \ +{ \ + return cmdq_dev_device_clock_is_enable(gCmdqMdpModuleClock.clk_##HW_NAME); \ +} +#endif /* !defined(CMDQ_USE_CCF) */ + +IMP_ENABLE_MDP_HW_CLOCK(CAM_MDP, CAM_MDP); +IMP_ENABLE_MDP_HW_CLOCK(MDP_RDMA0, MDP_RDMA); +IMP_ENABLE_MDP_HW_CLOCK(MDP_RSZ0, MDP_RSZ0); +IMP_ENABLE_MDP_HW_CLOCK(MDP_RSZ1, MDP_RSZ1); +IMP_ENABLE_MDP_HW_CLOCK(MDP_WDMA, MDP_WDMA); +IMP_ENABLE_MDP_HW_CLOCK(MDP_WROT0, MDP_WROT); +IMP_ENABLE_MDP_HW_CLOCK(MDP_TDSHP0, MDP_TDSHP); +IMP_ENABLE_MDP_HW_CLOCK(MDP_COLOR, MDP_COLOR); +IMP_MDP_HW_CLOCK_IS_ENABLE(CAM_MDP, CAM_MDP); +IMP_MDP_HW_CLOCK_IS_ENABLE(MDP_RDMA0, MDP_RDMA); +IMP_MDP_HW_CLOCK_IS_ENABLE(MDP_RSZ0, MDP_RSZ0); +IMP_MDP_HW_CLOCK_IS_ENABLE(MDP_RSZ1, MDP_RSZ1); +IMP_MDP_HW_CLOCK_IS_ENABLE(MDP_WDMA, MDP_WDMA); +IMP_MDP_HW_CLOCK_IS_ENABLE(MDP_WROT0, MDP_WROT); +IMP_MDP_HW_CLOCK_IS_ENABLE(MDP_TDSHP0, MDP_TDSHP); +IMP_MDP_HW_CLOCK_IS_ENABLE(MDP_COLOR, MDP_COLOR); +#undef IMP_ENABLE_MDP_HW_CLOCK +#undef IMP_MDP_HW_CLOCK_IS_ENABLE + +long cmdq_mdp_get_module_base_VA_MDP_RDMA(void) +{ + return gCmdqMdpModuleBaseVA.MDP_RDMA; +} + +long cmdq_mdp_get_module_base_VA_MDP_RSZ0(void) +{ + return gCmdqMdpModuleBaseVA.MDP_RSZ0; +} + +long cmdq_mdp_get_module_base_VA_MDP_RSZ1(void) +{ + return gCmdqMdpModuleBaseVA.MDP_RSZ1; +} + +long cmdq_mdp_get_module_base_VA_MDP_WDMA(void) +{ + return gCmdqMdpModuleBaseVA.MDP_WDMA; +} + +long cmdq_mdp_get_module_base_VA_MDP_WROT(void) +{ + return gCmdqMdpModuleBaseVA.MDP_WROT; +} + +long cmdq_mdp_get_module_base_VA_MDP_TDSHP(void) +{ + return gCmdqMdpModuleBaseVA.MDP_TDSHP; +} + +long cmdq_mdp_get_module_base_VA_VENC(void) +{ + return gCmdqMdpModuleBaseVA.VENC; +} + +long cmdq_mdp_get_module_base_VA_MDP_COLOR(void) +{ + return gCmdqMdpModuleBaseVA.MDP_COLOR; +} + +#ifdef CMDQ_OF_SUPPORT +#define MDP_RDMA_BASE cmdq_mdp_get_module_base_VA_MDP_RDMA() +#define MDP_RSZ0_BASE cmdq_mdp_get_module_base_VA_MDP_RSZ0() +#define MDP_RSZ1_BASE cmdq_mdp_get_module_base_VA_MDP_RSZ1() +#define MDP_TDSHP_BASE cmdq_mdp_get_module_base_VA_MDP_TDSHP() +#define MDP_WROT_BASE cmdq_mdp_get_module_base_VA_MDP_WROT() +#define MDP_WDMA_BASE cmdq_mdp_get_module_base_VA_MDP_WDMA() +#define MDP_COLOR_BASE cmdq_mdp_get_module_base_VA_MDP_COLOR() +#define VENC_BASE cmdq_mdp_get_module_base_VA_VENC() +#else +#include +#endif + +int32_t cmdq_mdp_reset_with_mmsys(const uint64_t engineToResetAgain) +{ + long MMSYS_SW0_RST_B_REG = MMSYS_CONFIG_BASE + (0x140); + int i = 0; + uint32_t reset_bits = 0L; + static const int engineResetBit[32] = { + -1, /* bit 0 : SMI COMMON */ + -1, /* bit 1 : SMI LARB0 */ + CMDQ_ENG_MDP_CAMIN, /* bit 2 : CAM_MDP */ + CMDQ_ENG_MDP_RDMA0, /* bit 3 : MDP_RDMA0 */ + CMDQ_ENG_MDP_RSZ0, /* bit 4 : MDP_RSZ0 */ + CMDQ_ENG_MDP_RSZ1, /* bit 5 : MDP_RSZ1 */ + CMDQ_ENG_MDP_TDSHP0, /* bit 6 : MDP_TDSHP0 */ + CMDQ_ENG_MDP_WDMA, /* bit 7 : MDP_WDMA */ + CMDQ_ENG_MDP_WROT0, /* bit 8 : MDP_WROT0 */ + [9 ... 31] = -1 + }; + + for (i = 0; i < 32; ++i) { + if (0 > engineResetBit[i]) + continue; + + if (engineToResetAgain & (1LL << engineResetBit[i])) + reset_bits |= (1 << i); + } + + if (0 != reset_bits) { + /* 0: reset */ + /* 1: not reset */ + /* so we need to reverse the bits */ + reset_bits = ~reset_bits; + + CMDQ_REG_SET32(MMSYS_SW0_RST_B_REG, reset_bits); + CMDQ_REG_SET32(MMSYS_SW0_RST_B_REG, ~0); + /* This takes effect immediately, no need to poll state */ + } + + return 0; +} + +m4u_callback_ret_t cmdq_M4U_TranslationFault_callback(int port, unsigned int mva, void *data) +{ + char dispatchModel[MDP_DISPATCH_KEY_STR_LEN] = "MDP"; + + CMDQ_ERR("================= [MDP M4U] Dump Begin ================\n"); + CMDQ_ERR("[MDP M4U]fault call port=%d, mva=0x%x", port, mva); + + cmdq_core_dump_tasks_info(); + + switch (port) { + case M4U_PORT_MDP_RDMA: + cmdq_mdp_dump_rdma(MDP_RDMA_BASE, "RDMA"); + break; + case M4U_PORT_MDP_WDMA: + cmdq_mdp_dump_wdma(MDP_WDMA_BASE, "WDMA"); + break; + case M4U_PORT_MDP_WROT: + cmdq_mdp_dump_rot(MDP_WROT_BASE, "WROT"); + break; + default: + CMDQ_ERR("[MDP M4U]fault callback function"); + break; + } + + CMDQ_ERR("=============== [MDP] Frame Information Begin ====================================\n"); + /* find dispatch module and assign dispatch key */ + cmdq_mdp_check_TF_address(mva, dispatchModel); + memcpy(data, dispatchModel, sizeof(dispatchModel)); + CMDQ_ERR("=============== [MDP] Frame Information End ====================================\n"); + CMDQ_ERR("================= [MDP M4U] Dump End ================\n"); + + return M4U_CALLBACK_HANDLED; +} + +int32_t cmdqVEncDumpInfo(uint64_t engineFlag, int logLevel) +{ + if (engineFlag & (1LL << CMDQ_ENG_VIDEO_ENC)) + cmdq_mdp_dump_venc(VENC_BASE, "VENC"); + + return 0; +} + +void cmdq_mdp_init_module_base_VA(void) +{ + memset(&gCmdqMdpModuleBaseVA, 0, sizeof(CmdqMdpModuleBaseVA)); + +#ifdef CMDQ_OF_SUPPORT + gCmdqMdpModuleBaseVA.MDP_RDMA = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mdp_rdma"); + gCmdqMdpModuleBaseVA.MDP_RSZ0 = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mdp_rsz0"); + gCmdqMdpModuleBaseVA.MDP_RSZ1 = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mdp_rsz1"); + gCmdqMdpModuleBaseVA.MDP_WDMA = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mdp_wdma"); + gCmdqMdpModuleBaseVA.MDP_WROT = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mdp_wrot"); + gCmdqMdpModuleBaseVA.MDP_TDSHP = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mdp_tdshp"); + gCmdqMdpModuleBaseVA.MDP_COLOR = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mdp_color"); + gCmdqMdpModuleBaseVA.VENC = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mt6755-venc"); +#endif +} + +void cmdq_mdp_deinit_module_base_VA(void) +{ +#ifdef CMDQ_OF_SUPPORT + cmdq_dev_free_module_base_VA(cmdq_mdp_get_module_base_VA_MDP_RDMA()); + cmdq_dev_free_module_base_VA(cmdq_mdp_get_module_base_VA_MDP_RSZ0()); + cmdq_dev_free_module_base_VA(cmdq_mdp_get_module_base_VA_MDP_RSZ1()); + cmdq_dev_free_module_base_VA(cmdq_mdp_get_module_base_VA_MDP_WDMA()); + cmdq_dev_free_module_base_VA(cmdq_mdp_get_module_base_VA_MDP_WROT()); + cmdq_dev_free_module_base_VA(cmdq_mdp_get_module_base_VA_MDP_TDSHP()); + cmdq_dev_free_module_base_VA(cmdq_mdp_get_module_base_VA_MDP_COLOR()); + cmdq_dev_free_module_base_VA(cmdq_mdp_get_module_base_VA_VENC()); + + memset(&gCmdqMdpModuleBaseVA, 0, sizeof(CmdqMdpModuleBaseVA)); +#else + /* do nothing, registers' IOMAP will be destroyed by platform */ +#endif +} + +bool cmdq_mdp_clock_is_on(CMDQ_ENG_ENUM engine) +{ + switch (engine) { + case CMDQ_ENG_MDP_CAMIN: + return cmdq_mdp_clock_is_enable_CAM_MDP(); + case CMDQ_ENG_MDP_RDMA0: + return cmdq_mdp_clock_is_enable_MDP_RDMA0(); + case CMDQ_ENG_MDP_RSZ0: + return cmdq_mdp_clock_is_enable_MDP_RSZ0(); + case CMDQ_ENG_MDP_RSZ1: + return cmdq_mdp_clock_is_enable_MDP_RSZ1(); + case CMDQ_ENG_MDP_WDMA: + return cmdq_mdp_clock_is_enable_MDP_WDMA(); + case CMDQ_ENG_MDP_WROT0: + return cmdq_mdp_clock_is_enable_MDP_WROT0(); + case CMDQ_ENG_MDP_TDSHP0: + return cmdq_mdp_clock_is_enable_MDP_TDSHP0(); + case CMDQ_ENG_MDP_COLOR0: + return cmdq_mdp_clock_is_enable_MDP_COLOR(); + default: + CMDQ_ERR("try to query unknown mdp clock"); + return false; + } +} + +void cmdq_mdp_enable_clock(bool enable, CMDQ_ENG_ENUM engine) +{ + unsigned long register_address; + uint32_t register_value; + + switch (engine) { + case CMDQ_ENG_MDP_CAMIN: + cmdq_mdp_enable_clock_CAM_MDP(enable); + break; + case CMDQ_ENG_MDP_RDMA0: + cmdq_mdp_enable_clock_MDP_RDMA0(enable); + /* Set MDP_RDMA0 DCM enable */ + register_address = MDP_RDMA_BASE + 0x0; + register_value = CMDQ_REG_GET32(register_address); + /* DCM_EN is bit 4 */ + register_value |= (0x1 << 4); + CMDQ_REG_SET32(register_address, register_value); + break; + case CMDQ_ENG_MDP_RSZ0: + cmdq_mdp_enable_clock_MDP_RSZ0(enable); + break; + case CMDQ_ENG_MDP_RSZ1: + cmdq_mdp_enable_clock_MDP_RSZ1(enable); + break; + case CMDQ_ENG_MDP_WDMA: + cmdq_mdp_enable_clock_MDP_WDMA(enable); + /* Set MDP_WDMA DCM enable */ + register_address = MDP_WDMA_BASE + 0x8; + register_value = CMDQ_REG_GET32(register_address); + /* DCM_EN is bit 31 */ + register_value |= (0x1 << 31); + CMDQ_REG_SET32(register_address, register_value); + break; + case CMDQ_ENG_MDP_WROT0: + cmdq_mdp_enable_clock_MDP_WROT0(enable); + /* Set MDP_WROT0 DCM enable */ + register_address = MDP_WROT_BASE + 0x7C; + register_value = CMDQ_REG_GET32(register_address); + /* DCM_EN is bit 16 */ + register_value |= (0x1 << 16); + CMDQ_REG_SET32(register_address, register_value); + break; + case CMDQ_ENG_MDP_TDSHP0: + cmdq_mdp_enable_clock_MDP_TDSHP0(enable); + break; + case CMDQ_ENG_MDP_COLOR0: + cmdq_mdp_enable_clock_MDP_COLOR(enable); + break; + default: + CMDQ_ERR("try to enable unknown mdp clock"); + break; + } +} + +/* Common Clock Framework */ +void cmdq_mdp_init_module_clk(void) +{ +#if defined(CMDQ_OF_SUPPORT) && defined(CMDQ_USE_CCF) + cmdq_dev_get_module_clock_by_name("mediatek,mmsys_config", "CAM_MDP", + &gCmdqMdpModuleClock.clk_CAM_MDP); + cmdq_dev_get_module_clock_by_name("mediatek,mdp_rdma", "MDP_RDMA", + &gCmdqMdpModuleClock.clk_MDP_RDMA); + cmdq_dev_get_module_clock_by_name("mediatek,mdp_rsz0", "MDP_RSZ0", + &gCmdqMdpModuleClock.clk_MDP_RSZ0); + cmdq_dev_get_module_clock_by_name("mediatek,mdp_rsz1", "MDP_RSZ1", + &gCmdqMdpModuleClock.clk_MDP_RSZ1); + cmdq_dev_get_module_clock_by_name("mediatek,mdp_wdma", "MDP_WDMA", + &gCmdqMdpModuleClock.clk_MDP_WDMA); + cmdq_dev_get_module_clock_by_name("mediatek,mdp_wrot", "MDP_WROT", + &gCmdqMdpModuleClock.clk_MDP_WROT); + cmdq_dev_get_module_clock_by_name("mediatek,mdp_tdshp", "MDP_TDSHP", + &gCmdqMdpModuleClock.clk_MDP_TDSHP); + cmdq_dev_get_module_clock_by_name("mediatek,mdp_color", "MDP_COLOR", + &gCmdqMdpModuleClock.clk_MDP_COLOR); +#endif +} + +int32_t cmdqMdpClockOn(uint64_t engineFlag) +{ + CMDQ_MSG("Enable MDP(0x%llx) clock begin\n", engineFlag); + +#ifdef CMDQ_PWR_AWARE + cmdq_mdp_enable(engineFlag, CMDQ_ENG_MDP_CAMIN); + cmdq_mdp_enable(engineFlag, CMDQ_ENG_MDP_RDMA0); + cmdq_mdp_enable(engineFlag, CMDQ_ENG_MDP_RSZ0); + cmdq_mdp_enable(engineFlag, CMDQ_ENG_MDP_RSZ1); + cmdq_mdp_enable(engineFlag, CMDQ_ENG_MDP_TDSHP0); + cmdq_mdp_enable(engineFlag, CMDQ_ENG_MDP_WROT0); + cmdq_mdp_enable(engineFlag, CMDQ_ENG_MDP_WDMA); + cmdq_mdp_enable(engineFlag, CMDQ_ENG_MDP_COLOR0); +#else + CMDQ_MSG("Force MDP clock all on\n"); + + /* enable all bits in MMSYS_CG_CLR0 and MMSYS_CG_CLR1 */ + CMDQ_REG_SET32(MMSYS_CONFIG_BASE + 0x108, 0xFFFFFFFF); + CMDQ_REG_SET32(MMSYS_CONFIG_BASE + 0x118, 0xFFFFFFFF); + +#endif /* #ifdef CMDQ_PWR_AWARE */ + + CMDQ_MSG("Enable MDP(0x%llx) clock end\n", engineFlag); + + return 0; +} + +typedef struct MODULE_BASE { + uint64_t engine; + long base; /* considering 64 bit kernel, use long type to store base addr */ + const char *name; +} MODULE_BASE; + +#define DEFINE_MODULE(eng, base) {eng, base, #eng} + +int32_t cmdqMdpDumpInfo(uint64_t engineFlag, int logLevel) +{ + if (engineFlag & (1LL << CMDQ_ENG_MDP_RDMA0)) + cmdq_mdp_dump_rdma(MDP_RDMA_BASE, "RDMA"); + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ0)) + cmdq_mdp_get_func()->mdpDumpRsz(MDP_RSZ0_BASE, "RSZ0"); + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ1)) + cmdq_mdp_get_func()->mdpDumpRsz(MDP_RSZ1_BASE, "RSZ1"); + + if (engineFlag & (1LL << CMDQ_ENG_MDP_TDSHP0)) + cmdq_mdp_get_func()->mdpDumpTdshp(MDP_TDSHP_BASE, "TDSHP"); + + if (engineFlag & (1LL << CMDQ_ENG_MDP_WROT0)) + cmdq_mdp_dump_rot(MDP_WROT_BASE, "WROT"); + + if (engineFlag & (1LL << CMDQ_ENG_MDP_WDMA)) + cmdq_mdp_dump_wdma(MDP_WDMA_BASE, "WDMA"); + + if (engineFlag & (1LL << CMDQ_ENG_MDP_COLOR0)) + cmdq_mdp_dump_color(MDP_COLOR_BASE, "COLOR0"); + + /* verbose case, dump entire 1KB HW register region */ + /* for each enabled HW module. */ + if (logLevel >= 1) { + int inner = 0; + + const MODULE_BASE bases[] = { + DEFINE_MODULE(CMDQ_ENG_MDP_RDMA0, MDP_RDMA_BASE), + + DEFINE_MODULE(CMDQ_ENG_MDP_RSZ0, MDP_RSZ0_BASE), + DEFINE_MODULE(CMDQ_ENG_MDP_RSZ1, MDP_RSZ1_BASE), + + DEFINE_MODULE(CMDQ_ENG_MDP_TDSHP0, MDP_TDSHP_BASE), + DEFINE_MODULE(CMDQ_ENG_MDP_COLOR0, MDP_COLOR_BASE), + DEFINE_MODULE(CMDQ_ENG_MDP_WROT0, MDP_WROT_BASE), + + DEFINE_MODULE(CMDQ_ENG_MDP_WDMA, MDP_WDMA_BASE), + }; + + for (inner = 0; inner < (sizeof(bases) / sizeof(bases[0])); ++inner) { + if (engineFlag & (1LL << bases[inner].engine)) { + CMDQ_ERR("========= [CMDQ] %s dump base 0x%lx ========\n", + bases[inner].name, bases[inner].base); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, + (void *)bases[inner].base, 1024, false); + } + } + } + + return 0; +} + +typedef enum MOUT_BITS { + MOUT_BITS_ISP_MDP = 0, /* bit 0: ISP_MDP multiple outupt reset */ + MOUT_BITS_MDP_RDMA0 = 1, /* bit 1: MDP_RDMA0 multiple outupt reset */ + MOUT_BITS_MDP_PRZ0 = 2, /* bit 2: MDP_PRZ0 multiple outupt reset */ + MOUT_BITS_MDP_PRZ1 = 3, /* bit 3: MDP_PRZ1 multiple outupt reset */ + MOUT_BITS_MDP_TDSHP0 = 4, /* bit 4: MDP_TDSHP0 multiple outupt reset */ +} MOUT_BITS; + +int32_t cmdqMdpResetEng(uint64_t engineFlag) +{ +#ifndef CMDQ_PWR_AWARE + return 0; +#else + int status = 0; + int64_t engineToResetAgain = 0LL; + uint32_t mout_bits_old = 0L; + uint32_t mout_bits = 0L; + + long MMSYS_MOUT_RST_REG = MMSYS_CONFIG_BASE + (0x040); + + CMDQ_PROF_START(0, "MDP_Rst"); + CMDQ_VERBOSE("Reset MDP(0x%llx) begin\n", engineFlag); + + /* After resetting each component, */ + /* we need also reset corresponding MOUT config. */ + mout_bits_old = CMDQ_REG_GET32(MMSYS_MOUT_RST_REG); + mout_bits = 0; + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RDMA0)) { + mout_bits |= (1 << MOUT_BITS_MDP_RDMA0); + + status = cmdq_mdp_loop_reset(CMDQ_ENG_MDP_RDMA0, + MDP_RDMA_BASE + 0x8, + MDP_RDMA_BASE + 0x408, 0x7FF00, 0x100, false); + if (0 != status) + engineToResetAgain |= (1LL << CMDQ_ENG_MDP_RDMA0); + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ0)) { + mout_bits |= (1 << MOUT_BITS_MDP_PRZ0); + if (cmdq_mdp_get_func()->mdpClockIsOn(CMDQ_ENG_MDP_RSZ0)) { + CMDQ_REG_SET32(MDP_RSZ0_BASE, 0x0); + CMDQ_REG_SET32(MDP_RSZ0_BASE, 0x10000); + CMDQ_REG_SET32(MDP_RSZ0_BASE, 0x0); + } + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ1)) { + mout_bits |= (1 << MOUT_BITS_MDP_PRZ1); + if (cmdq_mdp_get_func()->mdpClockIsOn(CMDQ_ENG_MDP_RSZ1)) { + CMDQ_REG_SET32(MDP_RSZ1_BASE, 0x0); + CMDQ_REG_SET32(MDP_RSZ1_BASE, 0x10000); + CMDQ_REG_SET32(MDP_RSZ1_BASE, 0x0); + } + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_TDSHP0)) { + mout_bits |= (1 << MOUT_BITS_MDP_TDSHP0); + if (cmdq_mdp_get_func()->mdpClockIsOn(CMDQ_ENG_MDP_TDSHP0)) { + CMDQ_REG_SET32(MDP_TDSHP_BASE + 0x100, 0x0); + CMDQ_REG_SET32(MDP_TDSHP_BASE + 0x100, 0x2); + CMDQ_REG_SET32(MDP_TDSHP_BASE + 0x100, 0x0); + } + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_WROT0)) { + status = cmdq_mdp_loop_reset(CMDQ_ENG_MDP_WROT0, + MDP_WROT_BASE + 0x010, + MDP_WROT_BASE + 0x014, 0x1, 0x1, true); + if (0 != status) + engineToResetAgain |= (1LL << CMDQ_ENG_MDP_WROT0); + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_WDMA)) { + status = cmdq_mdp_loop_reset(CMDQ_ENG_MDP_WDMA, + MDP_WDMA_BASE + 0x00C, + MDP_WDMA_BASE + 0x0A0, 0x3FF, 0x1, false); + if (0 != status) + engineToResetAgain |= (1LL << CMDQ_ENG_MDP_WDMA); + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_CAMIN)) { + /* MDP_CAMIN can only reset by mmsys, */ + /* so this is not a "error" */ + cmdq_mdp_reset_with_mmsys((1LL << CMDQ_ENG_MDP_CAMIN)); + } + + /* + when MDP engines fail to reset, + 1. print SMI debug log + 2. try resetting from MMSYS to restore system state + 3. report to QA by raising AEE warning + this reset will reset all registers to power on state. + but DpFramework always reconfigures register values, + so there is no need to backup registers. + */ + if (0 != engineToResetAgain) { + /* check SMI state immediately */ + /* if (1 == is_smi_larb_busy(0)) */ + /* { */ + /* smi_hanging_debug(5); */ + /* } */ + + CMDQ_ERR("Reset failed MDP engines(0x%llx), reset again with MMSYS_SW0_RST_B\n", + engineToResetAgain); + + cmdq_mdp_reset_with_mmsys(engineToResetAgain); + + /* finally, raise AEE warning to report normal reset fail. */ + /* we hope that reset MMSYS. */ + CMDQ_AEE("MDP", "Disable 0x%llx engine failed\n", engineToResetAgain); + + status = -EFAULT; + } + /* MOUT configuration reset */ + CMDQ_REG_SET32(MMSYS_MOUT_RST_REG, (mout_bits_old & (~mout_bits))); + CMDQ_REG_SET32(MMSYS_MOUT_RST_REG, (mout_bits_old | mout_bits)); + CMDQ_REG_SET32(MMSYS_MOUT_RST_REG, (mout_bits_old & (~mout_bits))); + + CMDQ_MSG("Reset MDP(0x%llx) end\n", engineFlag); + CMDQ_PROF_END(0, "MDP_Rst"); + + return status; + +#endif /* #ifdef CMDQ_PWR_AWARE */ + +} + +int32_t cmdqMdpClockOff(uint64_t engineFlag) +{ +#ifdef CMDQ_PWR_AWARE + CMDQ_MSG("Disable MDP(0x%llx) clock begin\n", engineFlag); + + if (engineFlag & (1LL << CMDQ_ENG_MDP_WDMA)) { + cmdq_mdp_loop_off(CMDQ_ENG_MDP_WDMA, + MDP_WDMA_BASE + 0x00C, MDP_WDMA_BASE + 0X0A0, 0x3FF, 0x1, false); + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_WROT0)) { + cmdq_mdp_loop_off(CMDQ_ENG_MDP_WROT0, + MDP_WROT_BASE + 0X010, MDP_WROT_BASE + 0X014, 0x1, 0x1, true); + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_TDSHP0)) { + if (cmdq_mdp_get_func()->mdpClockIsOn(CMDQ_ENG_MDP_TDSHP0)) { + CMDQ_REG_SET32(MDP_TDSHP_BASE + 0x100, 0x0); + CMDQ_REG_SET32(MDP_TDSHP_BASE + 0x100, 0x2); + CMDQ_REG_SET32(MDP_TDSHP_BASE + 0x100, 0x0); + CMDQ_MSG("Disable MDP_TDSHP0 clock\n"); + cmdq_mdp_get_func()->enableMdpClock(false, CMDQ_ENG_MDP_TDSHP0); + } + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ1)) { + if (cmdq_mdp_get_func()->mdpClockIsOn(CMDQ_ENG_MDP_RSZ1)) { + CMDQ_REG_SET32(MDP_RSZ1_BASE, 0x0); + CMDQ_REG_SET32(MDP_RSZ1_BASE, 0x10000); + CMDQ_REG_SET32(MDP_RSZ1_BASE, 0x0); + + CMDQ_MSG("Disable MDP_RSZ1 clock\n"); + + cmdq_mdp_get_func()->enableMdpClock(false, CMDQ_ENG_MDP_RSZ1); + } + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ0)) { + if (cmdq_mdp_get_func()->mdpClockIsOn(CMDQ_ENG_MDP_RSZ0)) { + CMDQ_REG_SET32(MDP_RSZ0_BASE, 0x0); + CMDQ_REG_SET32(MDP_RSZ0_BASE, 0x10000); + CMDQ_REG_SET32(MDP_RSZ0_BASE, 0x0); + + CMDQ_MSG("Disable MDP_RSZ0 clock\n"); + + cmdq_mdp_get_func()->enableMdpClock(false, CMDQ_ENG_MDP_RSZ0); + } + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RDMA0)) { + cmdq_mdp_loop_off(CMDQ_ENG_MDP_RDMA0, + MDP_RDMA_BASE + 0x008, + MDP_RDMA_BASE + 0x408, 0x7FF00, 0x100, false); + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_CAMIN)) { + if (cmdq_mdp_get_func()->mdpClockIsOn(CMDQ_ENG_MDP_CAMIN)) { + cmdq_mdp_reset_with_mmsys((1LL << CMDQ_ENG_MDP_CAMIN)); + + CMDQ_MSG("Disable MDP_CAMIN clock\n"); + cmdq_mdp_get_func()->enableMdpClock(false, CMDQ_ENG_MDP_CAMIN); + } + } + + if (engineFlag & (1LL << CMDQ_ENG_MDP_COLOR0)) { + if (cmdq_mdp_get_func()->mdpClockIsOn(CMDQ_ENG_MDP_COLOR0)) { + CMDQ_MSG("Disable MDP_COLOR0 clock\n"); + cmdq_mdp_get_func()->enableMdpClock(false, CMDQ_ENG_MDP_COLOR0); + } + } + + CMDQ_MSG("Disable MDP(0x%llx) clock end\n", engineFlag); +#endif /* #ifdef CMDQ_PWR_AWARE */ + + return 0; +} + +void cmdqMdpInitialSetting(void) +{ + char *data = kzalloc(MDP_DISPATCH_KEY_STR_LEN, GFP_KERNEL); + + /* Register M4U Translation Fault function */ + m4u_register_fault_callback(M4U_PORT_MDP_RDMA, cmdq_M4U_TranslationFault_callback, (void *)data); + m4u_register_fault_callback(M4U_PORT_MDP_WDMA, cmdq_M4U_TranslationFault_callback, (void *)data); + m4u_register_fault_callback(M4U_PORT_MDP_WROT, cmdq_M4U_TranslationFault_callback, (void *)data); +} + +uint32_t cmdq_mdp_rdma_get_reg_offset_src_addr(void) +{ + return 0xF00; +} + +uint32_t cmdq_mdp_wrot_get_reg_offset_dst_addr(void) +{ + return 0xF00; +} + +uint32_t cmdq_mdp_wdma_get_reg_offset_dst_addr(void) +{ + return 0xF00; +} + +void testcase_clkmgr_mdp(void) +{ +#if defined(CMDQ_PWR_AWARE) && defined(CMDQ_USE_CCF) + /* RDMA clk test with src buffer addr */ + testcase_clkmgr_impl(CMDQ_ENG_MDP_RDMA0, + "CMDQ_TEST_MDP_RDMA0", + MDP_RDMA_BASE + cmdq_mdp_rdma_get_reg_offset_src_addr(), + 0xAACCBBDD, + MDP_RDMA_BASE + cmdq_mdp_rdma_get_reg_offset_src_addr(), true); + + /* WDMA clk test with dst buffer addr */ + testcase_clkmgr_impl(CMDQ_ENG_MDP_WDMA, + "CMDQ_TEST_MDP_WDMA", + MDP_WDMA_BASE + cmdq_mdp_wdma_get_reg_offset_dst_addr(), + 0xAACCBBDD, + MDP_WDMA_BASE + cmdq_mdp_wdma_get_reg_offset_dst_addr(), true); + + /* WROT clk test with dst buffer addr */ + testcase_clkmgr_impl(CMDQ_ENG_MDP_WROT0, + "CMDQ_TEST_MDP_WROT0", + MDP_WROT_BASE + cmdq_mdp_wrot_get_reg_offset_dst_addr(), + 0xAACCBBDD, + MDP_WROT_BASE + cmdq_mdp_wrot_get_reg_offset_dst_addr(), true); + + /* TDSHP clk test with input size */ + testcase_clkmgr_impl(CMDQ_ENG_MDP_TDSHP0, + "CMDQ_TEST_MDP_TDSHP", + MDP_TDSHP_BASE + 0x244, 0xAACCBBDD, MDP_TDSHP_BASE + 0x244, true); + + /* RSZ clk test with debug port */ + testcase_clkmgr_impl(CMDQ_ENG_MDP_RSZ0, + "CMDQ_TEST_MDP_RSZ0", + MDP_RSZ0_BASE + 0x040, 0x00000001, MDP_RSZ0_BASE + 0x044, false); + + testcase_clkmgr_impl(CMDQ_ENG_MDP_RSZ1, + "CMDQ_TEST_MDP_RSZ1", + MDP_RSZ1_BASE + 0x040, 0x00000001, MDP_RSZ1_BASE + 0x044, false); + + /* COLOR clk test with debug port */ + testcase_clkmgr_impl(CMDQ_ENG_MDP_COLOR0, + "CMDQ_TEST_MDP_COLOR", + MDP_COLOR_BASE + 0x438, 0x000001AB, MDP_COLOR_BASE + 0x438, true); +#endif /* defined(CMDQ_USE_CCF) */ +} + +const char *cmdq_mdp_dispatch(uint64_t engineFlag) +{ + uint32_t state[2] = { 0 }; + struct TaskStruct task; + const uint32_t debug_str_len = 1024; + int32_t status = 0; + const char *module = "MDP"; + + task.userDebugStr = kzalloc(debug_str_len, GFP_KERNEL); + + status = cmdq_core_get_running_task_by_engine(engineFlag, debug_str_len, &task); + if (status < 0) { + CMDQ_ERR("Failed: get task by engine flag: 0x%016llx, task flag: 0x%016llx\n", + engineFlag, task.engineFlag); + } + + CMDQ_ERR("MDP frame info: %s\n", task.userDebugStr); + + kfree(task.userDebugStr); + task.userDebugStr = NULL; + + if (engineFlag & (1LL << CMDQ_ENG_MDP_RDMA0)) { + module = "MDP"; + } else { + if ((engineFlag & (1LL << CMDQ_ENG_MDP_RSZ0)) + && (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ1))) {/* 1-in 2-out */ + CMDQ_REG_SET32(MDP_RSZ0_BASE + 0x040, 0x00000002); + state[0] = CMDQ_REG_GET32(MDP_RSZ0_BASE + 0x044) & 0xF; + CMDQ_REG_SET32(MDP_RSZ1_BASE + 0x040, 0x00000002); + state[1] = CMDQ_REG_GET32(MDP_RSZ1_BASE + 0x044) & 0xF; + if ((state[0] == 0xa) && (state[1] == 0xa)) + module = "ISP (caused mdp upstream hang)"; /* 1,0,1,0 */ + } else {/* 1-in 1-out */ + if (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ0)) { + CMDQ_REG_SET32(MDP_RSZ0_BASE + 0x040, 0x00000002); + state[0] = CMDQ_REG_GET32(MDP_RSZ0_BASE + 0x044) & 0xF; + } + if (engineFlag & (1LL << CMDQ_ENG_MDP_RSZ1)) { + CMDQ_REG_SET32(MDP_RSZ1_BASE + 0x040, 0x00000002); + state[1] = CMDQ_REG_GET32(MDP_RSZ1_BASE + 0x044) & 0xF; + } + if ((state[0] == 0xa) || (state[1] == 0xa)) + module = "ISP (caused mdp upstream hang)"; /* 1,0,1,0 */ + } + } + + return module; +} + +void cmdq_mdp_platform_function_setting(void) +{ + cmdqMDPFuncStruct *pFunc; + + pFunc = cmdq_mdp_get_func(); + + pFunc->vEncDumpInfo = cmdqVEncDumpInfo; + + pFunc->initModuleBaseVA = cmdq_mdp_init_module_base_VA; + pFunc->deinitModuleBaseVA = cmdq_mdp_deinit_module_base_VA; + + pFunc->mdpClockIsOn = cmdq_mdp_clock_is_on; + pFunc->enableMdpClock = cmdq_mdp_enable_clock; + pFunc->initModuleCLK = cmdq_mdp_init_module_clk; + + pFunc->mdpClockOn = cmdqMdpClockOn; + pFunc->mdpDumpInfo = cmdqMdpDumpInfo; + pFunc->mdpResetEng = cmdqMdpResetEng; + pFunc->mdpClockOff = cmdqMdpClockOff; + + pFunc->mdpInitialSet = cmdqMdpInitialSetting; + + pFunc->rdmaGetRegOffsetSrcAddr = cmdq_mdp_rdma_get_reg_offset_src_addr; + pFunc->wrotGetRegOffsetDstAddr = cmdq_mdp_wrot_get_reg_offset_dst_addr; + pFunc->wdmaGetRegOffsetDstAddr = cmdq_mdp_wdma_get_reg_offset_dst_addr; + pFunc->testcaseClkmgrMdp = testcase_clkmgr_mdp; + + pFunc->dispatchModule = cmdq_mdp_dispatch; + +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/mt6755/Makefile b/drivers/misc/mediatek/connectivity/common/common_main/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8dbf788bdaa9c6a8d453ba8607749ff842c62aa3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/mt6755/Makefile @@ -0,0 +1,21 @@ +# WMT HAL driver for MT6755 + +ccflags-y += \ + -I$(src)/include \ + -I$(src)/../linux/include \ + -I$(src)/../include \ + -I$(src)/../../common_detect + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach + +subdir-ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + subdir-ccflags-y += -DWMT_IDC_SUPPORT=1 +else + subdir-ccflags-y += -DWMT_IDC_SUPPORT=0 +endif + +obj-y += mtk_wcn_consys_hw.o +obj-y += wmt_plat_alps.o diff --git a/drivers/misc/mediatek/connectivity/common/common_main/mt6755/include/mtk_wcn_consys_hw.h b/drivers/misc/mediatek/connectivity/common/common_main/mt6755/include/mtk_wcn_consys_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..5548d22a598ac4981c0f99eb2ea0072995da4b9e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/mt6755/include/mtk_wcn_consys_hw.h @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _MTK_WCN_CONSYS_HW_H_ +#define _MTK_WCN_CONSYS_HW_H_ + +#include +/* #include */ +#include "wmt_plat.h" + +/*device tree mode*/ +#if CONFIG_OF +/* #if 1 */ +#include +#include +#include +#include + +struct CONSYS_BASE_ADDRESS { + SIZE_T mcu_base; + SIZE_T ap_rgu_base; + SIZE_T topckgen_base; + SIZE_T spm_base; +}; + +/*TOPCKGEN_BASE*/ +#define CONSYS_TOP_CLKCG_CLR_OFFSET 0x00000084 +#define CONSYS_TOP_CLKCG_SET_OFFSET 0x00000054 +#define CONSYS_WD_SYS_RST_OFFSET 0x00000018 +#define CONSYS_AP2CONN_OSC_EN_OFFSET 0x00001f00 +#define CONSYS_EMI_MAPPING_OFFSET 0x00001340 +/*AP_RGU_BASE*/ +#define CONSYS_CPU_SW_RST_OFFSET 0x00000018 +/*SPM_BASE*/ +#define CONSYS_PWRON_CONFG_EN_OFFSET 0x00000000 +#define CONSYS_TOP1_PWR_CTRL_OFFSET 0x0000032c +#define CONSYS_PWR_CONN_ACK_OFFSET 0x00000180 +#define CONSYS_PWR_CONN_ACK_S_OFFSET 0x00000184 +/*CONN_MCU_CONFIG_BASE*/ +#define CONSYS_CHIP_ID_OFFSET 0x00000008 +#define CONSYS_ROM_RAM_DELSEL_OFFSET 0x00000114 +#define CONSYS_MCU_CFG_ACR_OFFSET 0x00000110 +#define CONSYS_CPUPCR_OFFSET 0x00000160 +#endif +/*AXI bus*/ +#define CONSYS_TOPAXI_PROT_EN_OFFSET 0x1220 +#define CONSYS_TOPAXI_PROT_STA1_OFFSET 0x1228 +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/*tag start:new platform need to make sure these define */ +#define PLATFORM_SOC_CHIP 0x6755 +#define CONSYS_BT_WIFI_SHARE_V33 0 + +#define CONSYS_PMIC_CTRL_ENABLE 1 +#define CONSYS_EMI_MPU_SETTING 1 +#define CONSYS_AHB_CLK_MAGEMENT 1 +#define CONSYS_USE_PLATFORM_WRITE 1 +#define CONSYS_PWR_ON_OFF_API_AVAILABLE 1 +#define CONSYS_CLOCK_BUF_CTRL 1 +/*tag end*/ + +#define CONSYS_SET_BIT(REG, BITVAL) (*((volatile UINT32 *)(REG)) |= ((UINT32)(BITVAL))) +#define CONSYS_CLR_BIT(REG, BITVAL) ((*(volatile UINT32 *)(REG)) &= ~((UINT32)(BITVAL))) +#define CONSYS_CLR_BIT_WITH_KEY(REG, BITVAL, KEY) {\ + UINT32 val = (*(volatile UINT32 *)(REG)); \ + val &= ~((UINT32)(BITVAL)); \ + val |= ((UINT32)(KEY)); \ + (*(volatile UINT32 *)(REG)) = val;\ +} +#define CONSYS_REG_READ(addr) (*((volatile UINT32 *)(addr))) +#if CONSYS_USE_PLATFORM_WRITE +#define CONSYS_REG_WRITE(addr, data) mt_reg_sync_writel(data, addr) +#else +#define CONSYS_REG_WRITE(addr, data) (*((volatile UINT32 *)(addr)) = (UINT32)(data)) +#endif + +/*tag start: connsys register base address (hard code, no use) */ +#define AP_RGU_BASE 0xF0007000 +#define TOPCKGEN_BASE 0xF0000000 +#define SPM_BASE 0xF0006000 +#define CONN_MCU_CONFIG_BASE 0xF8070000 +/*GIC Interrupt ID*/ +#define MT_CONN2AP_BTIF_WAKEUP_IRQ_ID 270 +/*tag end*/ + +/*connsys register offset define(hard code mode)*/ +#if 1 + /*top clock gating control register */ +#define CONSYS_TOP_CLKCG_CLR_REG (TOPCKGEN_BASE + 0x00000084) +#define CONSYS_TOP_CLKCG_SET_REG (TOPCKGEN_BASE + 0x00000054) +#define CONSYS_TOP_CLKCG_BIT (0x1 << 26) + + /*SPM clock gating control register */ +#define CONSYS_PWRON_CONFG_EN_REG (SPM_BASE + 0x00000000) +#define CONSYS_PWRON_CONFG_EN_VALUE (0x0b160001) +#define CONSYS_PWRON_CONFG_DIS_VALUE (0x0b160000) +#endif + +#define CONSYS_CPU_SW_RST_REG (AP_RGU_BASE + 0x00000018) +#define CONSYS_TOP1_PWR_CTRL_REG (SPM_BASE + 0x0000032c) +#define CONSYS_PWR_CONN_ACK_REG (SPM_BASE + 0x00000180) +#define CONSYS_PWR_CONN_ACK_S_REG (SPM_BASE + 0x00000184) + +#define CONSYS_WD_SYS_RST_REG (TOPCKGEN_BASE + 0x00000018) +#define CONSYS_CHIP_ID_REG (CONN_MCU_CONFIG_BASE + 0x00000008) +#define CONSYS_ROM_RAM_DELSEL_REG (CONN_MCU_CONFIG_BASE + 0x00000114) +#define CONSYS_MCU_CFG_ACR_REG (CONN_MCU_CONFIG_BASE + 0x00000110) +#define CONSYS_AFE_REG (CONN_TOP_CR_BASE + 0x00002000) +#define CONSYS_AFE_REG_DIG_RCK_01 (CONSYS_AFE_REG + 0x00000010) +#define CONSYS_AFE_REG_WBG_PLL_02 (CONSYS_AFE_REG + 0x00000028) +#define CONSYS_AFE_REG_WBG_WB_TX_01 (CONSYS_AFE_REG + 0x0000003c) +#define CONSYS_AFE_REG_DIG_RCK_01_VALUE (0x174b0160) +#define CONSYS_AFE_REG_WBG_PLL_02_VALUE (0x844083fe) +#define CONSYS_AFE_REG_WBG_WB_TX_01_VALUE (0x7fc39a20) + +#define CONSYS_TOPAXI_PROT_EN (TOPCKGEN_BASE + 0x1220) +#define CONSYS_TOPAXI_PROT_STA1 (TOPCKGEN_BASE + 0x1228) +#define CONSYS_PROT_MASK ((0x1<<13) | (0x1<<14)) /* bit 13, 14 */ +/*CONSYS_CPU_SW_RST_REG*/ +#define CONSYS_CPU_SW_RST_BIT (0x1 << 12) +#define CONSYS_CPU_SW_RST_CTRL_KEY (0x88 << 24) + +/*CONSYS_TOP1_PWR_CTRL_REG*/ +#define CONSYS_SPM_PWR_RST_BIT (0x1 << 0) +#define CONSYS_SPM_PWR_ISO_S_BIT (0x1 << 1) +#define CONSYS_SPM_PWR_ON_BIT (0x1 << 2) +#define CONSYS_SPM_PWR_ON_S_BIT (0x1 << 3) +#define CONSYS_CLK_CTRL_BIT (0x1 << 4) +#define CONSYS_SRAM_CONN_PD_BIT (0x1 << 8) + +/*CONSYS_PWR_CONN_ACK_REG*/ +#define CONSYS_PWR_ON_ACK_BIT (0x1 << 1) + +/*CONSYS_PWR_CONN_ACK_S_REG*/ +#define CONSYS_PWR_CONN_ACK_S_BIT (0x1 << 1) + +/*CONSYS_WD_SYS_RST_REG*/ +#define CONSYS_WD_SYS_RST_CTRL_KEY (0x88 << 24) +#define CONSYS_WD_SYS_RST_BIT (0x1 << 9) + +/*CONSYS_MCU_CFG_ACR_REG*/ +#define CONSYS_MCU_CFG_ACR_MBIST_BIT (0x1 << 18) + +/* EMI part mapping & ctrl*/ +#define KBYTE (1024*sizeof(char)) +#define CONSYS_EMI_AP_PHY_OFFSET (0x80000) +#define CONSYS_EMI_AP_PHY_BASE (0x80080000) +#define CONSYS_EMI_FW_PHY_BASE (0xf0080000) +#define CONSYS_EMI_MEM_SIZE (343*KBYTE) /*coredump space , 343K is enough */ +#define CONSYS_EMI_PAGED_TRACE_OFFSET (0x400) +#define CONSYS_EMI_PAGED_DUMP_OFFSET (0x8400) +#define CONSYS_EMI_FULL_DUMP_OFFSET (0x10400) + +/*cpupcr*/ +#define CONSYS_CPUPCR_REG (CONN_MCU_CONFIG_BASE + 0x00000160) +/*emi mapping*/ +#define CONSYS_EMI_MAPPING (TOPCKGEN_BASE + CONSYS_EMI_MAPPING_OFFSET) + +/*control app2cnn_osc_en*/ +#define CONSYS_AP2CONN_OSC_EN_REG (TOPCKGEN_BASE + 0x00001800) +#define CONSYS_AP2CONN_OSC_EN_BIT (0x1 << 10) +#define CONSYS_AP2CONN_WAKEUP_BIT (0x1 << 9) + +/*paged dump address start*/ +#define CONSYS_PAGED_DUMP_START_ADDR (0xf0088400) +#define CONSYS_PAGED_DUMP_SIZE (32*KBYTE) + +/*full dump address start*/ +#define CONSYS_FULL_DUMP_START_ADDR (0xf0090400) +#define CONSYS_FULL_DUMP_DLM_LEN (0x1f000) +#define CONSYS_FULL_DUMP_SYSB2_START (CONSYS_FULL_DUMP_START_ADDR + CONSYS_FULL_DUMP_DLM_LEN) +#define CONSYS_FULL_DUMP_SYSB2_LEN (0x6800) +#define CONSYS_FULL_DUMP_SYSB3_START (CONSYS_FULL_DUMP_SYSB2_START + CONSYS_FULL_DUMP_SYSB2_LEN) +#define CONSYS_FULL_DUMP_SYSB3_LEN (0x16800) + +/*force fw assert pattern*/ +#define EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1 (0x19b30bb1) + +/*clock type auto detection for jade and jade minus*/ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#define PMIC_DCXO_CW15 0x0D46 +#define PMIC_DCXO_CW16 0x0D48 +#define PMIC_DCXO_CW15_VAL 0x18 +#define AP_CONSYS_NOCO_CLOCK_BITA (0x1 << 11) +#define AP_CONSYS_NOCO_CLOCK_BITB (0x1 << 13) +#define AP_CONSYS_CO_CLOCK_BITA (0x1 << 10) +#define AP_CONSYS_CO_CLOCK_BITB (0x1 << 12) +#else +#define PMIC_DCXO_CW15 0x701E +#define PMIC_DCXO_CW16 0x7000 +#define PMIC_DCXO_CW15_VAL 0x7 +#define AP_CONSYS_NOCO_CLOCK_BITA (0x1 << 7) +#define AP_CONSYS_NOCO_CLOCK_BITB (0x1 << 9) +#define AP_CONSYS_CO_CLOCK_BITA (0x1 << 6) +#define AP_CONSYS_CO_CLOCK_BITB (0x1 << 8) +#endif +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_EMI_CTRL_STATE_OFFSET_ { + EXP_APMEM_CTRL_STATE = 0x0, + EXP_APMEM_CTRL_HOST_SYNC_STATE = 0x4, + EXP_APMEM_CTRL_HOST_SYNC_NUM = 0x8, + EXP_APMEM_CTRL_CHIP_SYNC_STATE = 0xc, + EXP_APMEM_CTRL_CHIP_SYNC_NUM = 0x10, + EXP_APMEM_CTRL_CHIP_SYNC_ADDR = 0x14, + EXP_APMEM_CTRL_CHIP_SYNC_LEN = 0x18, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_START = 0x1c, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_LEN = 0x20, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_IDX = 0x24, + EXP_APMEM_CTRL_CHIP_INT_STATUS = 0x28, + EXP_APMEM_CTRL_CHIP_PAGED_DUMP_END = 0x2c, + EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1 = 0x30, + EXP_APMEM_CTRL_CHIP_PAGE_DUMP_NUM = 0x44, + EXP_APMEM_CTRL_CHIP_FW_DBGLOG_MODE = 0x40, + EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP = 0x48, + EXP_APMEM_CTRL_MAX +} ENUM_EMI_CTRL_STATE_OFFSET, *P_ENUM_EMI_CTRL_STATE_OFFSET; +extern struct CONSYS_BASE_ADDRESS conn_reg; +#ifdef CONSYS_BT_WIFI_SHARE_V33 +typedef struct _BT_WIFI_V33_STATUS_ { + UINT32 counter; + UINT32 flags; + spinlock_t lock; +} BT_WIFI_V33_STATUS; + +#endif +#if CONSYS_BT_WIFI_SHARE_V33 +extern BT_WIFI_V33_STATUS gBtWifiV33; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +extern INT32 mtk_wcn_consys_hw_init(VOID); +extern INT32 mtk_wcn_consys_hw_deinit(VOID); +extern INT32 mtk_wcn_consys_hw_pwr_off(UINT32 co_clock_en); +extern INT32 mtk_wcn_consys_hw_pwr_on(UINT32 co_clock_en); +extern INT32 mtk_wcn_consys_hw_rst(UINT32 co_clock_en); +extern INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable); +extern INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable); +extern INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable); +extern INT32 mtk_wcn_consys_hw_state_show(VOID); +extern UINT8 *mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset); +#if CONSYS_ENALBE_SET_JTAG +extern UINT32 mtk_wcn_consys_jtag_flag_ctrl(UINT32 en); +#endif +extern UINT32 mtk_wcn_consys_soc_chipid(VOID); +#if !defined(CONFIG_MTK_LEGACY) +extern struct pinctrl *mtk_wcn_consys_get_pinctrl(VOID); +#endif +extern INT32 mtk_wcn_consys_co_clock_type(VOID); +extern INT32 mtk_wcn_consys_set_dbg_mode(UINT32 flag); +extern INT32 mtk_wcn_consys_set_dynamic_dump(PUINT32 buf); +#endif /* _MTK_WCN_CMB_HW_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/common_main/mt6755/mtk_wcn_consys_hw.c b/drivers/misc/mediatek/connectivity/common/common_main/mt6755/mtk_wcn_consys_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..80d6022fc08177d6608758c1110dbe46f84614d8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/mt6755/mtk_wcn_consys_hw.c @@ -0,0 +1,1339 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CONSYS-HW]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif /* defined(CONFIG_MTK_LEGACY) */ +#include +#include +#include "osal_typedef.h" +#include "mtk_wcn_consys_hw.h" +#include + +#if CONSYS_EMI_MPU_SETTING +#include +#endif + +#if CONSYS_PMIC_CTRL_ENABLE +#include +#include +#endif + +#ifdef CONFIG_MTK_HIBERNATION +#include +#endif + +#include + +#if CONSYS_CLOCK_BUF_CTRL +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static INT32 mtk_wmt_probe(struct platform_device *pdev); +static INT32 mtk_wmt_remove(struct platform_device *pdev); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +UINT8 __iomem *pEmibaseaddr = NULL; +phys_addr_t gConEmiPhyBase; +struct CONSYS_BASE_ADDRESS conn_reg; + +/* CCF part */ +#if !defined(CONFIG_MTK_CLKMGR) +struct clk *clk_scp_conn_main; /*ctrl conn_power_on/off */ +/* struct clk *clk_infra_conn_main; */ /*ctrl infra_connmcu_bus clk */ +#endif /* !defined(CONFIG_MTK_LEGACY) */ + +#ifdef CONFIG_OF +static const struct of_device_id apwmt_of_ids[] = { + {.compatible = "mediatek,mt6755-consys",}, + {} +}; +#endif + +static struct platform_driver mtk_wmt_dev_drv = { + .probe = mtk_wmt_probe, + .remove = mtk_wmt_remove, + .driver = { + .name = "mtk_wmt", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = apwmt_of_ids, +#endif + }, +}; + +/* PMIC part */ +#if CONSYS_PMIC_CTRL_ENABLE +#if !defined(CONFIG_MTK_LEGACY) +struct regulator *reg_VCN18; +struct regulator *reg_VCN28; +struct regulator *reg_VCN33_BT; +struct regulator *reg_VCN33_WIFI; +#endif +#endif + +/* GPIO part */ +#if !defined(CONFIG_MTK_LEGACY) +struct pinctrl *consys_pinctrl = NULL; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#define DYNAMIC_DUMP_GROUP_NUM 5 +#if CONSYS_ENALBE_SET_JTAG +UINT32 gJtagCtrl = 0; + +#define JTAG_ADDR1_BASE 0x10002000 + +char *jtag_addr1 = (char *)JTAG_ADDR1_BASE; + +#define JTAG1_REG_WRITE(addr, value) \ +writel(value, ((PUINT32)(jtag_addr1+(addr-JTAG_ADDR1_BASE)))) +#define JTAG1_REG_READ(addr) \ +readl(((PUINT32)(jtag_addr1+(addr-JTAG_ADDR1_BASE)))) + +static INT32 mtk_wcn_consys_jtag_set_for_mcu(VOID) +{ +#if 0 + int iRet = -1; + + WMT_PLAT_INFO_FUNC("WCN jtag_set_for_mcu start...\n"); + jtag_addr1 = ioremap(JTAG_ADDR1_BASE, 0x5000); + if (jtag_addr1 == 0) { + WMT_PLAT_ERR_FUNC("remap jtag_addr1 fail!\n"); + return iRet; + } + WMT_PLAT_INFO_FUNC("jtag_addr1 = 0x%p\n", jtag_addr1); + + JTAG1_REG_WRITE(0x100053c4, 0x11111100); + JTAG1_REG_WRITE(0x100053d4, 0x00111111); + + /*Enable IES of all pins */ + JTAG1_REG_WRITE(0x10002014, 0x00000003); + JTAG1_REG_WRITE(0x10005334, 0x55000000); + JTAG1_REG_WRITE(0x10005344, 0x00555555); + JTAG1_REG_WRITE(0x10005008, 0xc0000000); + JTAG1_REG_WRITE(0x10005018, 0x0000000d); + JTAG1_REG_WRITE(0x10005014, 0x00000032); + JTAG1_REG_WRITE(0x100020a4, 0x000000ff); + JTAG1_REG_WRITE(0x100020d4, 0x000000b4); + JTAG1_REG_WRITE(0x100020d8, 0x0000004b); + + WMT_PLAT_INFO_FUNC("WCN jtag set for mcu start...\n"); + kal_int32 iRet = 0; + kal_uint32 tmp = 0; + kal_int32 addr = 0; + kal_int32 remap_addr1 = 0; + kal_int32 remap_addr2 = 0; + + remap_addr1 = ioremap(JTAG_ADDR1_BASE, 0x1000); + if (remap_addr1 == 0) { + WMT_PLAT_ERR_FUNC("remap jtag_addr1 fail!\n"); + return -1; + } + + remap_addr2 = ioremap(JTAG_ADDR2_BASE, 0x100); + if (remap_addr2 == 0) { + WMT_PLAT_ERR_FUNC("remap jtag_addr2 fail!\n"); + return -1; + } + + /*Pinmux setting for MT6625 I/F */ + addr = remap_addr1 + 0x03C0; + tmp = DRV_Reg32(addr); + tmp = tmp & 0xff; + tmp = tmp | 0x11111100; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + + addr = remap_addr1 + 0x03D0; + tmp = DRV_Reg32(addr); + tmp = tmp & 0xff000000; + tmp = tmp | 0x00111111; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + + /*AP GPIO Setting 1 */ + /*Enable IES */ + /* addr = 0x10002014; */ + addr = remap_addr2 + 0x0014; + tmp = 0x00000003; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + /*GPIO mode setting */ + /* addr = 0x10005334; */ + addr = remap_addr1 + 0x0334; + tmp = 0x55000000; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + + /* addr = 0x10005344; */ + addr = remap_addr1 + 0x0344; + tmp = 0x00555555; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + /*GPIO direction control */ + /* addr = 0x10005008; */ + addr = remap_addr1 + 0x0008; + tmp = 0xc0000000; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + + /* addr = 0x10005018; */ + addr = remap_addr1 + 0x0018; + tmp = 0x0000000d; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + + /* addr = 0x10005014; */ + addr = remap_addr1 + 0x0014; + tmp = 0x00000032; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + + /*PULL Enable */ + /* addr = 0x100020a4; */ + addr = remap_addr2 + 0x00a4; + tmp = 0x000000ff; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + + /*PULL select enable */ + /* addr = 0x100020d4; */ + addr = remap_addr2 + 0x00d4; + tmp = 0x000000b4; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); + + /* addr = 0x100020d8; */ + addr = remap_addr2 + 0x00d8; + tmp = 0x0000004b; + DRV_WriteReg32(addr, tmp); + WMT_PLAT_INFO_FUNC("(RegAddr, RegVal):(0x%08x, 0x%08x)", addr, DRV_Reg32(addr)); +#endif + + return 0; +} + +UINT32 mtk_wcn_consys_jtag_flag_ctrl(UINT32 en) +{ + WMT_PLAT_INFO_FUNC("%s jtag set for MCU\n", en ? "enable" : "disable"); + gJtagCtrl = en; + return 0; +} + +#endif + +static INT32 mtk_wmt_probe(struct platform_device *pdev) +{ +#if !defined(CONFIG_MTK_CLKMGR) + clk_scp_conn_main = devm_clk_get(&pdev->dev, "conn"); + if (IS_ERR(clk_scp_conn_main)) { + WMT_PLAT_ERR_FUNC("[CCF]cannot get clk_scp_conn_main clock.\n"); + return PTR_ERR(clk_scp_conn_main); + } + WMT_PLAT_DBG_FUNC("[CCF]clk_scp_conn_main=%p\n", clk_scp_conn_main); +#if 0 + clk_infra_conn_main = devm_clk_get(&pdev->dev, "infra-sys-conn-main"); + if (IS_ERR(clk_infra_conn_main)) { + WMT_PLAT_ERR_FUNC("[CCF]cannot get clk_infra_conn_main clock.\n"); + return PTR_ERR(clk_infra_conn_main); + } + WMT_PLAT_DBG_FUNC("[CCF]clk_infra_conn_main=%p\n", clk_infra_conn_main); +#endif +#endif /* !defined(CONFIG_MTK_LEGACY) */ + +#if CONSYS_PMIC_CTRL_ENABLE +#if !defined(CONFIG_MTK_LEGACY) + reg_VCN18 = regulator_get(&pdev->dev, "vcn18"); + if (!reg_VCN18) + WMT_PLAT_ERR_FUNC("Regulator_get VCN_1V8 fail\n"); + reg_VCN28 = regulator_get(&pdev->dev, "vcn28"); + if (!reg_VCN28) + WMT_PLAT_ERR_FUNC("Regulator_get VCN_2V8 fail\n"); + reg_VCN33_BT = regulator_get(&pdev->dev, "vcn33_bt"); + if (!reg_VCN33_BT) + WMT_PLAT_ERR_FUNC("Regulator_get VCN33_BT fail\n"); + reg_VCN33_WIFI = regulator_get(&pdev->dev, "vcn33_wifi"); + if (!reg_VCN33_WIFI) + WMT_PLAT_ERR_FUNC("Regulator_get VCN33_WIFI fail\n"); +#endif +#endif + +#if !defined(CONFIG_MTK_LEGACY) + consys_pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(consys_pinctrl)) { + WMT_PLAT_ERR_FUNC("cannot find consys pinctrl.\n"); + return PTR_ERR(consys_pinctrl); + } +#endif /* !defined(CONFIG_MTK_LEGACY) */ + + return 0; +} + +static INT32 mtk_wmt_remove(struct platform_device *pdev) +{ + return 0; +} + +INT32 mtk_wcn_consys_co_clock_type(VOID) +{ + UINT32 retval = 0; + UINT32 back_up = 0; + UINT32 co_clock_type = 0; + + /* co-clock auto detection:backup cw15,write cw15,read cw16,restore cw15, */ + pmic_read_interface(PMIC_DCXO_CW15, &retval, 0xFFFF, 0); + back_up = retval; + pmic_config_interface(PMIC_DCXO_CW15, PMIC_DCXO_CW15_VAL, 0xFFFF, 0); + pmic_read_interface(PMIC_DCXO_CW16, &retval, 0xFFFF, 0); + pmic_config_interface(PMIC_DCXO_CW15, back_up, 0xFFFF, 0); + if ((retval & AP_CONSYS_NOCO_CLOCK_BITA) || (retval & AP_CONSYS_NOCO_CLOCK_BITB)) { + co_clock_type = 0; + WMT_PLAT_WARN_FUNC("pmic_register_val = 0x%x, co_clock_type = %d,TCXO mode\n", retval, co_clock_type); + } else if ((retval & AP_CONSYS_CO_CLOCK_BITA) || (retval & AP_CONSYS_CO_CLOCK_BITB)) { + co_clock_type = 1; + WMT_PLAT_WARN_FUNC("pmic_register_val = 0x%x, co_clock_type = %d,co-TSX mode\n", retval, co_clock_type); + } + return co_clock_type; +} +INT32 mtk_wcn_consys_hw_reg_ctrl(UINT32 on, UINT32 co_clock_type) +{ + +#if CONSYS_PWR_ON_OFF_API_AVAILABLE + INT32 iRet = -1; +#endif + + UINT32 retry = 10; + UINT32 consysHwChipId = 0; + + WMT_PLAT_DBG_FUNC("CONSYS-HW-REG-CTRL(0x%08x),start\n", on); + WMT_PLAT_DBG_FUNC("CONSYS_EMI_MAPPING dump before power on/off(0x%08x)\n", CONSYS_REG_READ(CONSYS_EMI_MAPPING)); + + if (on) { + WMT_PLAT_DBG_FUNC("++\n"); +/*step1.PMIC ctrl*/ +#if CONSYS_PMIC_CTRL_ENABLE + /*need PMIC driver provide new API protocol */ + /*1.AP power on VCN_1V8 LDO (with PMIC_WRAP API) VCN_1V8 */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_LDO_VCN18_EN_CTRL, 0); + /* VOL_DEFAULT, VOL_1200, VOL_1300, VOL_1500, VOL_1800... */ +#if defined(CONFIG_MTK_LEGACY) + hwPowerOn(MT6353_POWER_LDO_VCN18, VOL_1800 * 1000, "wcn_drv"); +#else + if (reg_VCN18) { + regulator_set_voltage(reg_VCN18, VOL_1800 * 1000, VOL_1800 * 1000); + if (regulator_enable(reg_VCN18)) + WMT_PLAT_ERR_FUNC("enable VCN18 fail\n"); + else + WMT_PLAT_DBG_FUNC("enable VCN18 ok\n"); + } +#endif +#else + pmic_set_register_value(MT6351_PMIC_RG_VCN18_ON_CTRL, 0); + /* VOL_DEFAULT, VOL_1200, VOL_1300, VOL_1500, VOL_1800... */ +#if defined(CONFIG_MTK_LEGACY) + hwPowerOn(MT6351_POWER_LDO_VCN18, VOL_1800 * 1000, "wcn_drv"); +#else + if (reg_VCN18) { + regulator_set_voltage(reg_VCN18, VOL_1800 * 1000, VOL_1800 * 1000); + if (regulator_enable(reg_VCN18)) + WMT_PLAT_ERR_FUNC("enable VCN18 fail\n"); + else + WMT_PLAT_DBG_FUNC("enable VCN18 ok\n"); + } +#endif +#endif + udelay(150); + + if (co_clock_type) { + /*step0,clk buf ctrl */ + WMT_PLAT_INFO_FUNC("co clock type(%d),turn on clk buf\n", co_clock_type); +#if CONSYS_CLOCK_BUF_CTRL + clk_buf_ctrl(CLK_BUF_CONN, 1); +#endif + /*if co-clock mode: */ + /*2.set VCN28 to SW control mode (with PMIC_WRAP API) */ + /*turn on VCN28 LDO only when FMSYS is activated" */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_LDO_VCN28_EN_CTRL, 0); +#else + pmic_set_register_value(MT6351_PMIC_RG_VCN28_ON_CTRL, 0); +#endif + } else { + /*if NOT co-clock: */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* 2.1.for jade minus:switch VCN28 to SW control mode (with PMIC_WRAP API) */ + pmic_set_register_value(PMIC_LDO_VCN28_EN_CTRL, 0); +#else + /*2.1.for jade:switch VCN28 to HW control mode (with PMIC_WRAP API) */ + pmic_set_register_value(MT6351_PMIC_RG_VCN28_ON_CTRL, 1); +#endif + /*2.2.turn on VCN28 LDO (with PMIC_WRAP API)" */ +#if defined(CONFIG_MTK_LEGACY) + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + hwPowerOn(MT6353_POWER_LDO_VCN28, VOL_2800 * 1000, "wcn_drv"); +#else + /*fix vcn28 not balance warning */ + hwPowerOn(MT6351_POWER_LDO_VCN28, VOL_2800 * 1000, "wcn_drv"); +#endif +#else + if (reg_VCN28) { + regulator_set_voltage(reg_VCN28, VOL_2800 * 1000, VOL_2800 * 1000); + if (regulator_enable(reg_VCN28)) + WMT_PLAT_ERR_FUNC("enable VCN_2V8 fail!\n"); + else + WMT_PLAT_DBG_FUNC("enable VCN_2V8 ok\n"); + } +#endif + } +#endif + +/*step2.MTCMOS ctrl*/ + +#ifdef CONFIG_OF /*use DT */ + /*3.assert CONNSYS CPU SW reset 0x10007018 "[12]=1'b1 [31:24]=8'h88 (key)" */ + CONSYS_REG_WRITE((conn_reg.ap_rgu_base + CONSYS_CPU_SW_RST_OFFSET), + CONSYS_REG_READ(conn_reg.ap_rgu_base + CONSYS_CPU_SW_RST_OFFSET) | + CONSYS_CPU_SW_RST_BIT | CONSYS_CPU_SW_RST_CTRL_KEY); + /*turn on SPM clock gating enable PWRON_CONFG_EN 0x10006000 32'h0b160001 */ + CONSYS_REG_WRITE((conn_reg.spm_base + CONSYS_PWRON_CONFG_EN_OFFSET), CONSYS_PWRON_CONFG_EN_VALUE); + +#if CONSYS_PWR_ON_OFF_API_AVAILABLE +#if defined(CONFIG_MTK_CLKMGR) + iRet = conn_power_on(); /* consult clkmgr owner. */ + if (iRet) + WMT_PLAT_ERR_FUNC("conn_power_on fail(%d)\n", iRet); + WMT_PLAT_DBG_FUNC("conn_power_on ok\n"); +#else + iRet = clk_prepare_enable(clk_scp_conn_main); + if (iRet) + WMT_PLAT_ERR_FUNC("clk_prepare_enable(clk_scp_conn_main) fail(%d)\n", iRet); + WMT_PLAT_DBG_FUNC("clk_prepare_enable(clk_scp_conn_main) ok\n"); +#endif /* defined(CONFIG_MTK_LEGACY) */ +#else + /*2.write conn_top1_pwr_on=1, power on conn_top1 0x1000632c [2] 1'b1 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) | + CONSYS_SPM_PWR_ON_BIT); + /*3.read conn_top1_pwr_on_ack =1, power on ack ready 0x10006180 [1] */ + while (0 == (CONSYS_PWR_ON_ACK_BIT & CONSYS_REG_READ(conn_reg.spm_base + CONSYS_PWR_CONN_ACK_OFFSET))) + NULL; + /*5.write conn_top1_pwr_on_s=1, power on conn_top1 0x1000632c [3] 1'b1 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) | + CONSYS_SPM_PWR_ON_S_BIT); + /*6.write conn_clk_dis=0, enable connsys clock 0x1000632c [4] 1'b0 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) & + ~CONSYS_CLK_CTRL_BIT); + /*7.wait 1us */ + udelay(1); + /*8.read conn_top1_pwr_on_ack_s =1, power on ack ready 0x10006184 [1] */ + while (0 == (CONSYS_PWR_CONN_ACK_S_BIT & + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_PWR_CONN_ACK_S_OFFSET))) + NULL; + /*9.release connsys ISO, conn_top1_iso_en=0 0x1000632c [1] 1'b0 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) & + ~CONSYS_SPM_PWR_ISO_S_BIT); + /*10.release SW reset of connsys, conn_ap_sw_rst_b=1 0x1000632c[0] 1'b1 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) | + CONSYS_SPM_PWR_RST_BIT); + /*disable AXI BUS protect 0x10001220[13] [14] */ + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_TOPAXI_PROT_EN_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_TOPAXI_PROT_EN_OFFSET) & + ~CONSYS_PROT_MASK); + while (CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_TOPAXI_PROT_STA1_OFFSET) & CONSYS_PROT_MASK) + NULL; +#endif + /*11.26M is ready now, delay 10us for mem_pd de-assert */ + udelay(10); + /*enable AP bus clock : connmcu_bus_pd API: enable_clock() ++?? */ + + /*12.poll CONNSYS CHIP ID until chipid is returned 0x18070008 */ + while (retry-- > 0) { + consysHwChipId = CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_CHIP_ID_OFFSET); + if (consysHwChipId == 0x0326) { + WMT_PLAT_INFO_FUNC("retry(%d)consys chipId(0x%08x)\n", retry, consysHwChipId); + break; + } + WMT_PLAT_ERR_FUNC("Read CONSYS chipId(0x%08x)", consysHwChipId); + msleep(20); + } + + if ((0 == retry) || (0 == consysHwChipId)) { + WMT_PLAT_ERR_FUNC("Maybe has a consys power on issue,(0x%08x)\n", consysHwChipId); + WMT_PLAT_ERR_FUNC("reg dump:CONSYS_CPU_SW_RST_REG(0x%x)\n", + CONSYS_REG_READ(conn_reg.ap_rgu_base + CONSYS_CPU_SW_RST_OFFSET)); + WMT_PLAT_ERR_FUNC("reg dump:CONSYS_PWR_CONN_ACK_REG(0x%x)\n", + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_PWR_CONN_ACK_OFFSET)); + WMT_PLAT_ERR_FUNC("reg dump:CONSYS_PWR_CONN_ACK_S_REG(0x%x)\n", + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_PWR_CONN_ACK_S_OFFSET)); + WMT_PLAT_ERR_FUNC("reg dump:CONSYS_TOP1_PWR_CTRL_REG(0x%x)\n", + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET)); + } + + /*13.{default no need}update ROMDEL/PATCH RAM DELSEL if needed 0x18070114 */ + + /* + *14.write 1 to conn_mcu_confg ACR[1] if real speed MBIST + *(default write "1") ACR 0x18070110[18] 1'b1 + *if this bit is 0, HW will do memory auto test under low CPU frequence (26M Hz) + *if this bit is 0, HW will do memory auto test under high CPU frequence(138M Hz) + *inclulding low CPU frequence + */ + CONSYS_REG_WRITE(conn_reg.mcu_base + CONSYS_MCU_CFG_ACR_OFFSET, + CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_MCU_CFG_ACR_OFFSET) | + CONSYS_MCU_CFG_ACR_MBIST_BIT); + +#if 0 + /*15.default no need,update ANA_WBG(AFE) CR if needed, CONSYS_AFE_REG */ + CONSYS_REG_WRITE(CONSYS_AFE_REG_DIG_RCK_01, CONSYS_AFE_REG_DIG_RCK_01_VALUE); + CONSYS_REG_WRITE(CONSYS_AFE_REG_WBG_PLL_02, CONSYS_AFE_REG_WBG_PLL_02_VALUE); + CONSYS_REG_WRITE(CONSYS_AFE_REG_WBG_WB_TX_01, CONSYS_AFE_REG_WBG_WB_TX_01_VALUE); +#endif + /*16.deassert CONNSYS CPU SW reset 0x10007018 "[12]=1'b0 [31:24] =8'h88 (key)" */ + CONSYS_REG_WRITE(conn_reg.ap_rgu_base + CONSYS_CPU_SW_RST_OFFSET, + (CONSYS_REG_READ(conn_reg.ap_rgu_base + CONSYS_CPU_SW_RST_OFFSET) & + ~CONSYS_CPU_SW_RST_BIT) | CONSYS_CPU_SW_RST_CTRL_KEY); + +#else /*use HADRCODE, maybe no use.. */ + /*3.assert CONNSYS CPU SW reset 0x10007018 "[12]=1'b1 [31:24]=8'h88 (key)" */ + CONSYS_REG_WRITE(CONSYS_CPU_SW_RST_REG, + (CONSYS_REG_READ(CONSYS_CPU_SW_RST_REG) | CONSYS_CPU_SW_RST_BIT | + CONSYS_CPU_SW_RST_CTRL_KEY)); + /*turn on SPM clock gating enable PWRON_CONFG_EN 0x10006000 32'h0b160001 */ + CONSYS_REG_WRITE(CONSYS_PWRON_CONFG_EN_REG, CONSYS_PWRON_CONFG_EN_VALUE); + +#if CONSYS_PWR_ON_OFF_API_AVAILABLE +#if defined(CONFIG_MTK_CLKMGR) + iRet = conn_power_on(); /* consult clkmgr owner */ + if (iRet) + WMT_PLAT_ERR_FUNC("conn_power_on fail(%d)\n", iRet); + WMT_PLAT_DBG_FUNC("conn_power_on ok\n"); +#else + iRet = clk_prepare_enable(clk_scp_conn_main); + if (iRet) + WMT_PLAT_ERR_FUNC("clk_prepare_enable(clk_scp_conn_main) fail(%d)\n", iRet); + WMT_PLAT_DBG_FUNC("clk_prepare_enable(clk_scp_conn_main) ok\n"); +#endif /* defined(CONFIG_MTK_LEGACY) */ +#else + /*2.write conn_top1_pwr_on=1, power on conn_top1 0x10006280 [2] 1'b1 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) | CONSYS_SPM_PWR_ON_BIT); + /*3.read conn_top1_pwr_on_ack =1, power on ack ready 0x1000660C [1] */ + while (0 == (CONSYS_PWR_ON_ACK_BIT & CONSYS_REG_READ(CONSYS_PWR_CONN_ACK_REG))) + NULL; + /*5.write conn_top1_pwr_on_s=1, power on conn_top1 0x10006280 [3] 1'b1 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) | CONSYS_SPM_PWR_ON_S_BIT); + /*6.write conn_clk_dis=0, enable connsys clock 0x10006280 [4] 1'b0 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) & ~CONSYS_CLK_CTRL_BIT); + /*7.wait 1us */ + udelay(1); + /*8.read conn_top1_pwr_on_ack_s =1, power on ack ready 0x10006610 [1] */ + while (0 == (CONSYS_PWR_CONN_ACK_S_BIT & CONSYS_REG_READ(CONSYS_PWR_CONN_ACK_S_REG))) + NULL; + /*9.release connsys ISO, conn_top1_iso_en=0 0x10006280 [1] 1'b0 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) & ~CONSYS_SPM_PWR_ISO_S_BIT); + /*10.release SW reset of connsys, conn_ap_sw_rst_b=1 0x10006280[0] 1'b1 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) | CONSYS_SPM_PWR_RST_BIT); + /*disable AXI BUS protect */ + CONSYS_REG_WRITE(CONSYS_TOPAXI_PROT_EN, CONSYS_REG_READ(CONSYS_TOPAXI_PROT_EN) & ~CONSYS_PROT_MASK); + while (CONSYS_REG_READ(CONSYS_TOPAXI_PROT_STA1) & CONSYS_PROT_MASK) + NULL; +#endif + /*11.26M is ready now, delay 10us for mem_pd de-assert */ + udelay(10); + /*enable AP bus clock : connmcu_bus_pd API: enable_clock() ++?? */ + + /*12.poll CONNSYS CHIP ID until 6755 is returned 0x18070008 32'h6755 */ + while (retry-- > 0) { + WMT_PLAT_DBG_FUNC("CONSYS_CHIP_ID_REG(0x%08x)", CONSYS_REG_READ(CONSYS_CHIP_ID_REG)); + consysHwChipId = CONSYS_REG_READ(CONSYS_CHIP_ID_REG); + if (consysHwChipId == 0x0326) { + WMT_PLAT_INFO_FUNC("retry(%d)consys chipId(0x%08x)\n", retry, consysHwChipId); + break; + } + msleep(20); + } + + if ((0 == retry) || (0 == consysHwChipId)) { + WMT_PLAT_ERR_FUNC("Maybe has a consys power on issue,(0x%08x)\n", consysHwChipId); + WMT_PLAT_INFO_FUNC("reg dump:CONSYS_CPU_SW_RST_REG(0x%x)\n", + CONSYS_REG_READ(CONSYS_CPU_SW_RST_REG)); + WMT_PLAT_INFO_FUNC("reg dump:CONSYS_PWR_CONN_ACK_REG(0x%x)\n", + CONSYS_REG_READ(CONSYS_PWR_CONN_ACK_REG)); + WMT_PLAT_INFO_FUNC("reg dump:CONSYS_PWR_CONN_ACK_S_REG(0x%x)\n", + CONSYS_REG_READ(CONSYS_PWR_CONN_ACK_S_REG)); + WMT_PLAT_INFO_FUNC("reg dump:CONSYS_TOP1_PWR_CTRL_REG(0x%x)\n", + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG)); + } + + /*13.{default no need}update ROMDEL/PATCH RAM DELSEL if needed 0x18070114 */ + + /* + *14.write 1 to conn_mcu_confg ACR[1] if real speed MBIST + *(default write "1") ACR 0x18070110[18] 1'b1 + *if this bit is 0, HW will do memory auto test under low CPU frequence (26M Hz) + *if this bit is 0, HW will do memory auto test under high CPU frequence(138M Hz) + *inclulding low CPU frequence + */ + CONSYS_REG_WRITE(CONSYS_MCU_CFG_ACR_REG, + CONSYS_REG_READ(CONSYS_MCU_CFG_ACR_REG) | CONSYS_MCU_CFG_ACR_MBIST_BIT); + + /*update ANA_WBG(AFE) CR. AFE setting file: AP Offset = 0x180B2000 */ + +#if 0 + /*15.default no need,update ANA_WBG(AFE) CR if needed, CONSYS_AFE_REG */ + CONSYS_REG_WRITE(CONSYS_AFE_REG_DIG_RCK_01, CONSYS_AFE_REG_DIG_RCK_01_VALUE); + CONSYS_REG_WRITE(CONSYS_AFE_REG_WBG_PLL_02, CONSYS_AFE_REG_WBG_PLL_02_VALUE); + CONSYS_REG_WRITE(CONSYS_AFE_REG_WBG_WB_TX_01, CONSYS_AFE_REG_WBG_WB_TX_01_VALUE); +#endif + /*16.deassert CONNSYS CPU SW reset 0x10007018 "[12]=1'b0 [31:24] =8'h88(key)" */ + CONSYS_REG_WRITE(CONSYS_CPU_SW_RST_REG, + (CONSYS_REG_READ(CONSYS_CPU_SW_RST_REG) & ~CONSYS_CPU_SW_RST_BIT) | + CONSYS_CPU_SW_RST_CTRL_KEY); + +#endif + msleep(20); /* msleep < 20ms can sleep for up to 20ms */ + + } else { + +#ifdef CONFIG_OF + + + +#if CONSYS_PWR_ON_OFF_API_AVAILABLE +#if defined(CONFIG_MTK_CLKMGR) + /*power off connsys by API (MT6582, MT6572 are different) API: conn_power_off() */ + iRet = conn_power_off(); /* consult clkmgr owner */ + if (iRet) + WMT_PLAT_ERR_FUNC("conn_power_off fail(%d)\n", iRet); + WMT_PLAT_DBG_FUNC("conn_power_off ok\n"); +#else + clk_disable_unprepare(clk_scp_conn_main); + WMT_PLAT_DBG_FUNC("clk_disable_unprepare(clk_scp_conn_main) calling\n"); +#endif /* defined(CONFIG_MTK_LEGACY) */ +#else + { + INT32 count = 0; + + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_TOPAXI_PROT_EN_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_TOPAXI_PROT_EN_OFFSET) | + CONSYS_PROT_MASK); + while ((CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_TOPAXI_PROT_STA1_OFFSET) & + CONSYS_PROT_MASK) != CONSYS_PROT_MASK) { + count++; + if (count > 1000) + break; + } + } + /*release connsys ISO, conn_top1_iso_en=1 0x1000632c [1] 1'b1 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) | + CONSYS_SPM_PWR_ISO_S_BIT); + /*assert SW reset of connsys, conn_ap_sw_rst_b=0 0x1000632c[0] 1'b0 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) & + ~CONSYS_SPM_PWR_RST_BIT); + /*write conn_clk_dis=1, disable connsys clock 0x1000632c [4] 1'b1 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) | + CONSYS_CLK_CTRL_BIT); + /*wait 1us */ + udelay(1); + /*write conn_top1_pwr_on=0, power off conn_top1 0x1000632c [3:2] 2'b00 */ + CONSYS_REG_WRITE(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET, + CONSYS_REG_READ(conn_reg.spm_base + CONSYS_TOP1_PWR_CTRL_OFFSET) & + ~(CONSYS_SPM_PWR_ON_BIT | CONSYS_SPM_PWR_ON_S_BIT)); + +#endif + +#else + +#if CONSYS_PWR_ON_OFF_API_AVAILABLE + + +#if defined(CONFIG_MTK_CLKMGR) + /*power off connsys by API: conn_power_off() */ + iRet = conn_power_off(); /* consult clkmgr owner */ + if (iRet) + WMT_PLAT_ERR_FUNC("conn_power_off fail(%d)\n", iRet); + WMT_PLAT_DBG_FUNC("conn_power_off ok\n"); +#else + clk_disable_unprepare(clk_scp_conn_main); + WMT_PLAT_DBG_FUNC("clk_disable_unprepare(clk_scp_conn_main) calling\n"); +#endif /* defined(CONFIG_MTK_LEGACY) */ +#else + { + INT32 count = 0; + + CONSYS_REG_WRITE(CONSYS_TOPAXI_PROT_EN, + CONSYS_REG_READ(CONSYS_TOPAXI_PROT_EN) | CONSYS_PROT_MASK); + while ((CONSYS_REG_READ(CONSYS_TOPAXI_PROT_STA1) & CONSYS_PROT_MASK) != CONSYS_PROT_MASK) { + count++; + if (count > 1000) + break; + } + + } + /*release connsys ISO, conn_top1_iso_en=1 0x1000632c [1] 1'b1 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) | CONSYS_SPM_PWR_ISO_S_BIT); + /*assert SW reset of connsys, conn_ap_sw_rst_b=0 0x1000632c[0] 1'b0 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) & ~CONSYS_SPM_PWR_RST_BIT); + /*write conn_clk_dis=1, disable connsys clock 0x1000632c [4] 1'b1 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, + CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) | CONSYS_CLK_CTRL_BIT); + /*wait 1us */ + udelay(1); + /*write conn_top1_pwr_on=0, power off conn_top1 0x1000632c [3:2] 2'b00 */ + CONSYS_REG_WRITE(CONSYS_TOP1_PWR_CTRL_REG, CONSYS_REG_READ(CONSYS_TOP1_PWR_CTRL_REG) & + ~(CONSYS_SPM_PWR_ON_BIT | CONSYS_SPM_PWR_ON_S_BIT)); +#endif + +#endif + +#if CONSYS_PMIC_CTRL_ENABLE + if (co_clock_type) { + /*VCN28 has been turned off by GPS OR FM */ +#if CONSYS_CLOCK_BUF_CTRL + clk_buf_ctrl(CLK_BUF_CONN, 0); +#endif + } else { +#if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(MT6351_PMIC_RG_VCN28_ON_CTRL, 0); +#endif +#if defined(CONFIG_MTK_LEGACY) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + hwPowerDown(MT6353_POWER_LDO_VCN28, "wcn_drv"); +#else + hwPowerDown(MT6351_POWER_LDO_VCN28, "wcn_drv"); +#endif +#else + if (reg_VCN28) { + if (regulator_disable(reg_VCN28)) + WMT_PLAT_ERR_FUNC("disable VCN_2V8 fail!\n"); + else + WMT_PLAT_DBG_FUNC("disable VCN_2V8 ok\n"); + } +#endif + } +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /*AP power off MT6351L VCN_1V8 LDO */ + pmic_set_register_value(PMIC_LDO_VCN18_EN_CTRL, 0); +#if defined(CONFIG_MTK_LEGACY) + hwPowerDown(MT6353_POWER_LDO_VCN18, "wcn_drv"); +#else + if (reg_VCN18) { + if (regulator_disable(reg_VCN18)) + WMT_PLAT_ERR_FUNC("disable VCN_1V8 fail!\n"); + else + WMT_PLAT_DBG_FUNC("disable VCN_1V8 ok\n"); + } +#endif +/*for jade MT6351_PMIC*/ +#else + /*AP power off MT6351L VCN_1V8 LDO */ + pmic_set_register_value(MT6351_PMIC_RG_VCN18_ON_CTRL, 0); +#if defined(CONFIG_MTK_LEGACY) + hwPowerDown(MT6351_POWER_LDO_VCN18, "wcn_drv"); +#else + if (reg_VCN18) { + if (regulator_disable(reg_VCN18)) + WMT_PLAT_ERR_FUNC("disable VCN_1V8 fail!\n"); + else + WMT_PLAT_DBG_FUNC("disable VCN_1V8 ok\n"); + } +#endif +#endif + +#endif + + } + WMT_PLAT_WARN_FUNC("CONSYS-HW-REG-CTRL(0x%08x),finish\n", on); + return 0; +} + +INT32 mtk_wcn_consys_hw_gpio_ctrl(UINT32 on) +{ + INT32 iRet = 0; + + WMT_PLAT_DBG_FUNC("CONSYS-HW-GPIO-CTRL(0x%08x), start\n", on); + + if (on) { + + /*if external modem used,GPS_SYNC still needed to control */ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_INIT); + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_INIT); + + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + + /* TODO: [FixMe][GeorgeKuo] double check if BGF_INT is implemented ok */ + /* iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_MUX); */ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_INIT); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + WMT_PLAT_DBG_FUNC("CONSYS-HW, BGF IRQ registered and disabled\n"); + + } else { + + /* set bgf eint/all eint to deinit state, namely input low state */ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); + WMT_PLAT_DBG_FUNC("CONSYS-HW, BGF IRQ unregistered and disabled\n"); + /* iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); */ + + /*if external modem used,GPS_SYNC still needed to control */ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_DEINIT); + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + /* deinit gps_lna */ + iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_DEINIT); + + } + WMT_PLAT_INFO_FUNC("CONSYS-HW-GPIO-CTRL(0x%08x), finish\n", on); + return iRet; + +} + +INT32 mtk_wcn_consys_hw_pwr_on(UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-ON, start\n"); + + iRet += mtk_wcn_consys_hw_reg_ctrl(1, co_clock_type); + iRet += mtk_wcn_consys_hw_gpio_ctrl(1); +#if CONSYS_ENALBE_SET_JTAG + if (gJtagCtrl) + mtk_wcn_consys_jtag_set_for_mcu(); +#endif + WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-ON, finish(%d)\n", iRet); + return iRet; +} + +INT32 mtk_wcn_consys_hw_pwr_off(UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-OFF, start\n"); + + iRet += mtk_wcn_consys_hw_reg_ctrl(0, co_clock_type); + iRet += mtk_wcn_consys_hw_gpio_ctrl(0); + + WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-OFF, finish(%d)\n", iRet); + return iRet; +} + +INT32 mtk_wcn_consys_hw_rst(UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_INFO_FUNC("CONSYS-HW, hw_rst start, eirq should be disabled before this step\n"); + + /*1. do whole hw power off flow */ + iRet += mtk_wcn_consys_hw_reg_ctrl(0, co_clock_type); + + /*2. do whole hw power on flow */ + iRet += mtk_wcn_consys_hw_reg_ctrl(1, co_clock_type); + + WMT_PLAT_INFO_FUNC("CONSYS-HW, hw_rst finish, eirq should be enabled after this step\n"); + return iRet; +} + +#if CONSYS_BT_WIFI_SHARE_V33 +INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable) +{ + /* spin_lock_irqsave(&gBtWifiV33.lock,gBtWifiV33.flags); */ + if (enable) { + if (1 == gBtWifiV33.counter) { + gBtWifiV33.counter++; + WMT_PLAT_DBG_FUNC("V33 has been enabled,counter(%d)\n", gBtWifiV33.counter); + } else if (2 == gBtWifiV33.counter) { + WMT_PLAT_DBG_FUNC("V33 has been enabled,counter(%d)\n", gBtWifiV33.counter); + } else { +#if CONSYS_PMIC_CTRL_ENABLE + /*do BT PMIC on,depenency PMIC API ready */ + /*switch BT PALDO control from SW mode to HW mode:0x416[5]-->0x1 */ + /* VOL_DEFAULT, VOL_3300, VOL_3400, VOL_3500, VOL_3600 */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + hwPowerOn(MT6353_POWER_LDO_VCN33_BT, VOL_3300 * 1000, "wcn_drv"); + mt6353_upmu_set_ldo_vcn33_en_ctrl_bt(1); +#else + hwPowerOn(MT6351_POWER_LDO_VCN33_BT, VOL_3300 * 1000, "wcn_drv"); + mt6351_upmu_set_rg_vcn33_on_ctrl(1); +#endif +#endif + WMT_PLAT_INFO_FUNC("WMT do BT/WIFI v3.3 on\n"); + gBtWifiV33.counter++; + } + + } else { + if (1 == gBtWifiV33.counter) { + /*do BT PMIC off */ + /*switch BT PALDO control from HW mode to SW mode:0x416[5]-->0x0 */ +#if CONSYS_PMIC_CTRL_ENABLE +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + mt6353_upmu_set_ldo_vcn33_en_ctrl_bt(0); + hwPowerDown(MT6353_POWER_LDO_VCN33_BT, "wcn_drv"); +#else + mt6351_upmu_set_rg_vcn33_on_ctrl(0); + hwPowerDown(MT6351_POWER_LDO_VCN33_BT, "wcn_drv"); +#endif +#endif + WMT_PLAT_INFO_FUNC("WMT do BT/WIFI v3.3 off\n"); + gBtWifiV33.counter--; + } else if (2 == gBtWifiV33.counter) { + gBtWifiV33.counter--; + WMT_PLAT_DBG_FUNC("V33 no need disabled,counter(%d)\n", gBtWifiV33.counter); + } else { + WMT_PLAT_DBG_FUNC("V33 has been disabled,counter(%d)\n", gBtWifiV33.counter); + } + + } + /* spin_unlock_irqrestore(&gBtWifiV33.lock,gBtWifiV33.flags); */ + return 0; +} + +INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable) +{ + mtk_wcn_consys_hw_bt_paldo_ctrl(enable); + return 0; +} + +#else +INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable) +{ + + if (enable) { + /*do BT PMIC on,depenency PMIC API ready */ + /*switch BT PALDO control from SW mode to HW mode:0x416[5]-->0x1 */ +#if CONSYS_PMIC_CTRL_ENABLE + /* VOL_DEFAULT, VOL_3300, VOL_3400, VOL_3500, VOL_3600 */ +#if defined(CONFIG_MTK_LEGACY) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + hwPowerOn(MT6353_POWER_LDO_VCN33_BT, VOL_3300 * 1000, "wcn_drv"); +#else + hwPowerOn(MT6351_POWER_LDO_VCN33_BT, VOL_3300 * 1000, "wcn_drv"); +#endif +#else + if (reg_VCN33_BT) { + regulator_set_voltage(reg_VCN33_BT, VOL_3300 * 1000, VOL_3300 * 1000); + if (regulator_enable(reg_VCN33_BT)) + WMT_PLAT_ERR_FUNC("WMT do BT PMIC on fail!\n"); + } +#endif +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_LDO_VCN33_EN_CTRL_BT, 1); +#else + pmic_set_register_value(MT6351_PMIC_RG_VCN33_ON_CTRL_BT, 1); +#endif + +#endif + WMT_PLAT_DBG_FUNC("WMT do BT PMIC on\n"); + } else { + /*do BT PMIC off */ + /*switch BT PALDO control from HW mode to SW mode:0x416[5]-->0x0 */ +#if CONSYS_PMIC_CTRL_ENABLE +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_LDO_VCN33_EN_CTRL_BT, 0); +#else + pmic_set_register_value(MT6351_PMIC_RG_VCN33_ON_CTRL_BT, 0); +#endif +#if defined(CONFIG_MTK_LEGACY) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + hwPowerDown(MT6353_POWER_LDO_VCN33_BT, "wcn_drv"); +#else + hwPowerDown(MT6351_POWER_LDO_VCN33_BT, "wcn_drv"); +#endif +#else + if (reg_VCN33_BT) + regulator_disable(reg_VCN33_BT); +#endif +#endif + WMT_PLAT_DBG_FUNC("WMT do BT PMIC off\n"); + } + + return 0; + +} + +INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable) +{ + + if (enable) { + /*do WIFI PMIC on,depenency PMIC API ready */ + /*switch WIFI PALDO control from SW mode to HW mode:0x418[14]-->0x1 */ +#if CONSYS_PMIC_CTRL_ENABLE +#if defined(CONFIG_MTK_LEGACY) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + hwPowerOn(MT6353_POWER_LDO_VCN33_WIFI, VOL_3300 * 1000, "wcn_drv"); +#else + hwPowerOn(MT6351_POWER_LDO_VCN33_WIFI, VOL_3300 * 1000, "wcn_drv"); +#endif +#else + if (reg_VCN33_WIFI) { + regulator_set_voltage(reg_VCN33_WIFI, VOL_3300 * 1000, VOL_3300 * 1000); + if (regulator_enable(reg_VCN33_WIFI)) + WMT_PLAT_ERR_FUNC("WMT do WIFI PMIC on fail!\n"); + } +#endif +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_LDO_VCN33_EN_CTRL_WIFI, 1); +#else + pmic_set_register_value(MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI, 1); +#endif +#endif + WMT_PLAT_DBG_FUNC("WMT do WIFI PMIC on\n"); + } else { + /*do WIFI PMIC off */ + /*switch WIFI PALDO control from HW mode to SW mode:0x418[14]-->0x0 */ +#if CONSYS_PMIC_CTRL_ENABLE +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_LDO_VCN33_EN_CTRL_WIFI, 0); +#if defined(CONFIG_MTK_LEGACY) + hwPowerDown(MT6353_POWER_LDO_VCN33_WIFI, "wcn_drv"); +#else + if (reg_VCN33_WIFI) + regulator_disable(reg_VCN33_WIFI); +#endif +#else + pmic_set_register_value(MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI, 0); +#if defined(CONFIG_MTK_LEGACY) + hwPowerDown(MT6351_POWER_LDO_VCN33_WIFI, "wcn_drv"); +#else + if (reg_VCN33_WIFI) + regulator_disable(reg_VCN33_WIFI); +#endif +#endif + +#endif + WMT_PLAT_DBG_FUNC("WMT do WIFI PMIC off\n"); + } + + return 0; + +} + +#endif +INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable) +{ + if (enable) { + /*in co-clock mode,need to turn on vcn28 when fm on */ +#if CONSYS_PMIC_CTRL_ENABLE +#if defined(CONFIG_MTK_LEGACY) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + hwPowerOn(MT6353_POWER_LDO_VCN28, VOL_2800 * 1000, "wcn_drv"); +#else + hwPowerOn(MT6351_POWER_LDO_VCN28, VOL_2800 * 1000, "wcn_drv"); +#endif +#else + if (reg_VCN28) { + regulator_set_voltage(reg_VCN28, VOL_2800 * 1000, VOL_2800 * 1000); + if (regulator_enable(reg_VCN28)) + WMT_PLAT_ERR_FUNC("WMT do VCN28 PMIC on fail!\n"); + } +#endif +#endif + WMT_PLAT_INFO_FUNC("turn on vcn28 for fm/gps usage in co-clock mode\n"); + } else { + /*in co-clock mode,need to turn off vcn28 when fm off */ +#if CONSYS_PMIC_CTRL_ENABLE +#if defined(CONFIG_MTK_LEGACY) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + hwPowerDown(MT6353_POWER_LDO_VCN28, "wcn_drv"); +#else + hwPowerDown(MT6351_POWER_LDO_VCN28, "wcn_drv"); +#endif +#else + if (reg_VCN28) + regulator_disable(reg_VCN28); +#endif +#endif + WMT_PLAT_INFO_FUNC("turn off vcn28 for fm/gps usage in co-clock mode\n"); + } + return 0; +} + +INT32 mtk_wcn_consys_hw_state_show(VOID) +{ + return 0; +} + +INT32 mtk_wcn_consys_hw_restore(struct device *device) +{ + UINT32 addrPhy = 0; + + if (gConEmiPhyBase) { + +#if CONSYS_EMI_MPU_SETTING + /*set MPU for EMI share Memory */ + WMT_PLAT_INFO_FUNC("setting MPU for EMI share memory\n"); + + emi_mpu_set_region_protection(gConEmiPhyBase + SZ_1M / 2, + gConEmiPhyBase + SZ_1M - 1, + 13, + SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, NO_PROTECTION, FORBIDDEN, NO_PROTECTION)); + +#endif + /*consys to ap emi remapping register:10000320, cal remapping address */ + addrPhy = (gConEmiPhyBase & 0xFFF00000) >> 20; + + /*enable consys to ap emi remapping bit12 */ + addrPhy = addrPhy | 0x1000; + + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET) | addrPhy); + + WMT_PLAT_INFO_FUNC("CONSYS_EMI_MAPPING dump in restore cb(0x%08x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET)); + +#if 1 + pEmibaseaddr = ioremap_nocache(gConEmiPhyBase + SZ_1M / 2, CONSYS_EMI_MEM_SIZE); +#else + pEmibaseaddr = ioremap_nocache(CONSYS_EMI_AP_PHY_BASE, CONSYS_EMI_MEM_SIZE); +#endif + if (pEmibaseaddr) { + WMT_PLAT_WARN_FUNC("EMI mapping OK(0x%p)\n", pEmibaseaddr); + memset_io(pEmibaseaddr, 0, CONSYS_EMI_MEM_SIZE); + } else { + WMT_PLAT_ERR_FUNC("EMI mapping fail\n"); + } + } else { + WMT_PLAT_ERR_FUNC("consys emi memory address gConEmiPhyBase invalid\n"); + } + + return 0; +} + +/*Reserved memory by device tree!*/ +int reserve_memory_consys_fn(struct reserved_mem *rmem) +{ + WMT_PLAT_WARN_FUNC(" name: %s, base: 0x%llx, size: 0x%llx\n", rmem->name, + (unsigned long long)rmem->base, (unsigned long long)rmem->size); + gConEmiPhyBase = rmem->base; + return 0; +} + +RESERVEDMEM_OF_DECLARE(reserve_memory_test, "mediatek,consys-reserve-memory", reserve_memory_consys_fn); + + +INT32 mtk_wcn_consys_hw_init(void) +{ + + INT32 iRet = -1; + UINT32 addrPhy = 0; + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-consys"); + if (node) { + /* registers base address */ + conn_reg.mcu_base = (SIZE_T) of_iomap(node, 0); + WMT_PLAT_DBG_FUNC("Get mcu register base(0x%zx)\n", conn_reg.mcu_base); + conn_reg.ap_rgu_base = (SIZE_T) of_iomap(node, 1); + WMT_PLAT_DBG_FUNC("Get ap_rgu register base(0x%zx)\n", conn_reg.ap_rgu_base); + conn_reg.topckgen_base = (SIZE_T) of_iomap(node, 2); + WMT_PLAT_DBG_FUNC("Get topckgen register base(0x%zx)\n", conn_reg.topckgen_base); + conn_reg.spm_base = (SIZE_T) of_iomap(node, 3); + WMT_PLAT_DBG_FUNC("Get spm register base(0x%zx)\n", conn_reg.spm_base); + } else { + WMT_PLAT_ERR_FUNC("[%s] can't find CONSYS compatible node\n", __func__); + return iRet; + } + + if (gConEmiPhyBase) { +#if CONSYS_EMI_MPU_SETTING + /*set MPU for EMI share Memory */ + WMT_PLAT_INFO_FUNC("setting MPU for EMI share memory\n"); + + emi_mpu_set_region_protection(gConEmiPhyBase + SZ_1M / 2, + gConEmiPhyBase + SZ_1M - 1, + 13, + SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, NO_PROTECTION, FORBIDDEN, NO_PROTECTION)); + + +#endif + WMT_PLAT_DBG_FUNC("get consys start phy address(0x%zx)\n", (SIZE_T) gConEmiPhyBase); + + /*consys to ap emi remapping register:10000320, cal remapping address */ + addrPhy = (gConEmiPhyBase & 0xFFF00000) >> 20; + + /*enable consys to ap emi remapping bit12 */ + addrPhy = addrPhy | 0x1000; + + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET) | addrPhy); + + WMT_PLAT_INFO_FUNC("CONSYS_EMI_MAPPING dump(0x%08x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET)); + +#if 1 + pEmibaseaddr = ioremap_nocache(gConEmiPhyBase + SZ_1M / 2, CONSYS_EMI_MEM_SIZE); +#else + pEmibaseaddr = ioremap_nocache(CONSYS_EMI_AP_PHY_BASE, CONSYS_EMI_MEM_SIZE); +#endif + /* pEmibaseaddr = ioremap_nocache(0x80090400,270*KBYTE); */ + if (pEmibaseaddr) { + WMT_PLAT_INFO_FUNC("EMI mapping OK(0x%p)\n", pEmibaseaddr); + memset_io(pEmibaseaddr, 0, CONSYS_EMI_MEM_SIZE); + iRet = 0; + } else { + WMT_PLAT_ERR_FUNC("EMI mapping fail\n"); + } + } else { + WMT_PLAT_ERR_FUNC("consys emi memory address gConEmiPhyBase invalid\n"); + } +#ifdef CONFIG_MTK_HIBERNATION + WMT_PLAT_INFO_FUNC("register connsys restore cb for complying with IPOH function\n"); + register_swsusp_restore_noirq_func(ID_M_CONNSYS, mtk_wcn_consys_hw_restore, NULL); +#endif + + iRet = platform_driver_register(&mtk_wmt_dev_drv); + if (iRet) + WMT_PLAT_ERR_FUNC("WMT platform driver registered failed(%d)\n", iRet); + + return iRet; + +} + +INT32 mtk_wcn_consys_hw_deinit(void) +{ + if (pEmibaseaddr) { + iounmap(pEmibaseaddr); + pEmibaseaddr = NULL; + } +#ifdef CONFIG_MTK_HIBERNATION + unregister_swsusp_restore_noirq_func(ID_M_CONNSYS); +#endif + + platform_driver_unregister(&mtk_wmt_dev_drv); + return 0; +} + +UINT8 *mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset) +{ + UINT8 *p_virtual_addr = NULL; + + if (!pEmibaseaddr) { + WMT_PLAT_ERR_FUNC("EMI base address is NULL\n"); + return NULL; + } + WMT_PLAT_DBG_FUNC("ctrl_state_offset(%08x)\n", ctrl_state_offset); + p_virtual_addr = pEmibaseaddr + ctrl_state_offset; + + return p_virtual_addr; +} + +UINT32 mtk_wcn_consys_soc_chipid(void) +{ + return PLATFORM_SOC_CHIP; +} + +#if !defined(CONFIG_MTK_LEGACY) +struct pinctrl *mtk_wcn_consys_get_pinctrl() +{ + return consys_pinctrl; +} +#endif +INT32 mtk_wcn_consys_set_dbg_mode(UINT32 flag) +{ + INT32 ret = -1; + PUINT8 vir_addr = NULL; + + vir_addr = mtk_wcn_consys_emi_virt_addr_get(EXP_APMEM_CTRL_CHIP_FW_DBGLOG_MODE); + if (!vir_addr) { + WMT_PLAT_ERR_FUNC("get vir address fail\n"); + return -2; + } + if (flag) { + ret = 0; + CONSYS_REG_WRITE(vir_addr, 0x1); + } else { + CONSYS_REG_WRITE(vir_addr, 0x0); + } + WMT_PLAT_ERR_FUNC("fw dbg mode register value(0x%08x)\n", CONSYS_REG_READ(vir_addr)); + return ret; +} +INT32 mtk_wcn_consys_set_dynamic_dump(PUINT32 str_buf) +{ + PUINT8 vir_addr = NULL; + + vir_addr = mtk_wcn_consys_emi_virt_addr_get(EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP); + if (!vir_addr) { + WMT_PLAT_ERR_FUNC("get vir address fail\n"); + return -2; + } + memcpy(vir_addr, str_buf, DYNAMIC_DUMP_GROUP_NUM*8); + WMT_PLAT_INFO_FUNC("dynamic dump register value(0x%08x)\n", CONSYS_REG_READ(vir_addr)); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_main/mt6755/wmt_plat_alps.c b/drivers/misc/mediatek/connectivity/common/common_main/mt6755/wmt_plat_alps.c new file mode 100644 index 0000000000000000000000000000000000000000..94a0dbb41df2fe767fc68490fed5cdc44ecfa7c5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_main/mt6755/wmt_plat_alps.c @@ -0,0 +1,1074 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ +/*! \file +* \brief Declaration of library functions +* +* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-PLAT]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include + +/* ALPS header files */ +/* #include */ +/* #include */ +#if defined(CONFIG_MTK_LEGACY) +#include +#endif +#include + +/* MTK_WCN_COMBO header files */ +#include "osal_typedef.h" +#include "mtk_wcn_consys_hw.h" +#include "stp_dbg.h" + +#define CFG_WMT_WAKELOCK_SUPPORT 1 + +#ifdef CONFIG_MTK_MT6306_SUPPORT +#define MTK_WCN_MT6306_IS_READY 1 +#else +#define MTK_WCN_MT6306_IS_READY 0 +#endif + +#if MTK_WCN_MT6306_IS_READY +#include + +#ifdef GPIO_GPS_LNA_PIN +#undef GPIO_GPS_LNA_PIN +#endif + +#define GPIO_GPS_LNA_PIN GPIO7 +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +EMI_CTRL_STATE_OFFSET mtk_wcn_emi_state_off = { + .emi_apmem_ctrl_state = EXP_APMEM_CTRL_STATE, + .emi_apmem_ctrl_host_sync_state = EXP_APMEM_CTRL_HOST_SYNC_STATE, + .emi_apmem_ctrl_host_sync_num = EXP_APMEM_CTRL_HOST_SYNC_NUM, + .emi_apmem_ctrl_chip_sync_state = EXP_APMEM_CTRL_CHIP_SYNC_STATE, + .emi_apmem_ctrl_chip_sync_num = EXP_APMEM_CTRL_CHIP_SYNC_NUM, + .emi_apmem_ctrl_chip_sync_addr = EXP_APMEM_CTRL_CHIP_SYNC_ADDR, + .emi_apmem_ctrl_chip_sync_len = EXP_APMEM_CTRL_CHIP_SYNC_LEN, + .emi_apmem_ctrl_chip_print_buff_start = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_START, + .emi_apmem_ctrl_chip_print_buff_len = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_LEN, + .emi_apmem_ctrl_chip_print_buff_idx = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_IDX, + .emi_apmem_ctrl_chip_int_status = EXP_APMEM_CTRL_CHIP_INT_STATUS, + .emi_apmem_ctrl_chip_paded_dump_end = EXP_APMEM_CTRL_CHIP_PAGED_DUMP_END, + .emi_apmem_ctrl_host_outband_assert_w1 = EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1, + .emi_apmem_ctrl_chip_page_dump_num = EXP_APMEM_CTRL_CHIP_PAGE_DUMP_NUM, +}; + +CONSYS_EMI_ADDR_INFO mtk_wcn_emi_addr_info = { + .emi_phy_addr = CONSYS_EMI_FW_PHY_BASE, + .paged_trace_off = CONSYS_EMI_PAGED_TRACE_OFFSET, + .paged_dump_off = CONSYS_EMI_PAGED_DUMP_OFFSET, + .full_dump_off = CONSYS_EMI_FULL_DUMP_OFFSET, + .p_ecso = &mtk_wcn_emi_state_off, +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if CFG_WMT_PS_SUPPORT +static VOID wmt_plat_bgf_eirq_cb(VOID); +#endif +static INT32 wmt_plat_bgf_eint_ctrl(ENUM_PIN_STATE state); +static INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state); +static INT32 wmt_plat_gps_sync_ctrl(ENUM_PIN_STATE state); +static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state); + +static INT32 wmt_plat_dump_pin_conf(VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +UINT32 gCoClockFlag = 0; +BGF_IRQ_BALANCE gbgfIrqBle; +UINT32 wmtPlatLogLvl = WMT_PLAT_LOG_INFO; +#if CONSYS_BT_WIFI_SHARE_V33 +BT_WIFI_V33_STATUS gBtWifiV33; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if CFG_WMT_WAKELOCK_SUPPORT +static struct mutex gOsSLock; +#ifdef CONFIG_PM_WAKELOCKS +static struct wakeup_source wmtWakeLock; +#else +static struct wake_lock wmtWakeLock; +#endif +#endif + +irq_cb wmt_plat_bgf_irq_cb = NULL; +device_audio_if_cb wmt_plat_audio_if_cb = NULL; +func_ctrl_cb wmt_plat_func_ctrl_cb = NULL; +thermal_query_ctrl_cb wmt_plat_thermal_query_ctrl_cb = NULL; +deep_idle_ctrl_cb wmt_plat_deep_idle_ctrl_cb = NULL; + +static const fp_set_pin gfp_set_pin_table[] = { + [PIN_BGF_EINT] = wmt_plat_bgf_eint_ctrl, + [PIN_I2S_GRP] = wmt_plat_i2s_ctrl, + [PIN_GPS_SYNC] = wmt_plat_gps_sync_ctrl, + [PIN_GPS_LNA] = wmt_plat_gps_lna_ctrl, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*! + * \brief audio control callback function for CMB_STUB on ALPS + * + * A platform function required for dynamic binding with CMB_STUB on ALPS. + * + * \param state desired audio interface state to use + * \param flag audio interface control options + * + * \retval 0 operation success + * \retval -1 invalid parameters + * \retval < 0 error for operation fail + */ +INT32 wmt_plat_audio_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) +{ + INT32 iRet = 0; + UINT32 pinShare = 0; + + /* input sanity check */ + if ((CMB_STUB_AIF_MAX <= state) + || (CMB_STUB_AIF_CTRL_MAX <= ctrl)) { + return -1; + } + + iRet = 0; + + /* set host side first */ + switch (state) { + case CMB_STUB_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + break; + + case CMB_STUB_AIF_1: + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + break; + + case CMB_STUB_AIF_2: + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + break; + + case CMB_STUB_AIF_3: + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + break; + + default: + /* FIXME: move to cust folder? */ + WMT_PLAT_ERR_FUNC("invalid state [%d]\n", state); + iRet = -1; + break; + } + + if (CMB_STUB_AIF_CTRL_EN == ctrl) { + WMT_PLAT_INFO_FUNC("call chip aif setting\n"); + /* need to control chip side GPIO */ + if (NULL != wmt_plat_audio_if_cb) { + iRet += (*wmt_plat_audio_if_cb) (state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); + } else { + WMT_PLAT_WARN_FUNC("wmt_plat_audio_if_cb is not registered\n"); + iRet -= 1; + } + + } else { + WMT_PLAT_INFO_FUNC("skip chip aif setting\n"); + } + + return iRet; + +} + +static VOID wmt_plat_func_ctrl(UINT32 type, UINT32 on) +{ + if (wmt_plat_func_ctrl_cb) + (*wmt_plat_func_ctrl_cb) (on, type); +} + +static long wmt_plat_thermal_ctrl(VOID) +{ + long temp = 0; + + if (wmt_plat_thermal_query_ctrl_cb) + temp = (*wmt_plat_thermal_query_ctrl_cb) (); + + return temp; +} + +static INT32 wmt_plat_deep_idle_ctrl(UINT32 dpilde_ctrl) +{ + INT32 iRet = -1; + + if (wmt_plat_deep_idle_ctrl_cb) + iRet = (*wmt_plat_deep_idle_ctrl_cb) (dpilde_ctrl); + + return iRet; +} +#if CFG_WMT_PS_SUPPORT +static VOID wmt_plat_bgf_eirq_cb(VOID) +{ +/* #error "need to disable EINT here" */ + /* wmt_lib_ps_irq_cb(); */ + if (NULL != wmt_plat_bgf_irq_cb) + (*(wmt_plat_bgf_irq_cb)) (); + else + WMT_PLAT_WARN_FUNC("WMT-PLAT: wmt_plat_bgf_irq_cb not registered\n"); + return; + +} +#endif +irqreturn_t wmt_plat_bgf_irq_isr(INT32 i, VOID *arg) +{ +#if CFG_WMT_PS_SUPPORT + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + wmt_plat_bgf_eirq_cb(); +#else + WMT_PLAT_INFO_FUNC("skip irq handing because psm is disable"); +#endif + return IRQ_HANDLED; +} + +VOID wmt_plat_irq_cb_reg(irq_cb bgf_irq_cb) +{ + wmt_plat_bgf_irq_cb = bgf_irq_cb; +} +EXPORT_SYMBOL(wmt_plat_irq_cb_reg); + +VOID wmt_plat_aif_cb_reg(device_audio_if_cb aif_ctrl_cb) +{ + wmt_plat_audio_if_cb = aif_ctrl_cb; +} +EXPORT_SYMBOL(wmt_plat_aif_cb_reg); + +VOID wmt_plat_func_ctrl_cb_reg(func_ctrl_cb subsys_func_ctrl) +{ + wmt_plat_func_ctrl_cb = subsys_func_ctrl; +} +EXPORT_SYMBOL(wmt_plat_func_ctrl_cb_reg); + +VOID wmt_plat_thermal_ctrl_cb_reg(thermal_query_ctrl_cb thermal_query_ctrl) +{ + wmt_plat_thermal_query_ctrl_cb = thermal_query_ctrl; +} +EXPORT_SYMBOL(wmt_plat_thermal_ctrl_cb_reg); + +VOID wmt_plat_deep_idle_ctrl_cb_reg(deep_idle_ctrl_cb deep_idle_ctrl) +{ + wmt_plat_deep_idle_ctrl_cb = deep_idle_ctrl; +} +EXPORT_SYMBOL(wmt_plat_deep_idle_ctrl_cb_reg); + +UINT32 wmt_plat_soc_co_clock_flag_get(VOID) +{ + return gCoClockFlag; +} + +static UINT32 wmt_plat_soc_co_clock_flag_set(UINT32 flag) +{ + gCoClockFlag = flag; + return 0; +} + +INT32 wmt_plat_soc_init(UINT32 co_clock_type) +{ + CMB_STUB_CB stub_cb; + INT32 iret; + /*init wmt function ctrl wakelock if wake lock is supported by host platform */ + co_clock_type = mtk_wcn_consys_co_clock_type(); + wmt_plat_soc_co_clock_flag_set(co_clock_type); + + stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; + stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; + stub_cb.thermal_query_cb = wmt_plat_thermal_ctrl; + stub_cb.deep_idle_ctrl_cb = wmt_plat_deep_idle_ctrl; + stub_cb.size = sizeof(stub_cb); + + /* register to cmb_stub */ + iret = mtk_wcn_cmb_stub_reg(&stub_cb); +#ifdef CFG_WMT_WAKELOCK_SUPPORT +#ifdef CONFIG_PM_WAKELOCKS + wakeup_source_init(&wmtWakeLock, "wmtFuncCtrl"); +#else + wake_lock_init(&wmtWakeLock, WAKE_LOCK_SUSPEND, "wmtFuncCtrl"); +#endif + mutex_init(&gOsSLock); +#endif + +#if CONSYS_BT_WIFI_SHARE_V33 + gBtWifiV33.counter = 0; + spin_lock_init(&gBtWifiV33.lock); +#endif + + iret += mtk_wcn_consys_hw_init(); + + spin_lock_init(&gbgfIrqBle.lock); + WMT_PLAT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} +EXPORT_SYMBOL(wmt_plat_init); + +INT32 wmt_plat_deinit(VOID) +{ + INT32 iret = 0; + /* 2. unreg to cmb_stub */ + iret = mtk_wcn_cmb_stub_unreg(); + + /*3. wmt wakelock deinit */ +#ifdef CFG_WMT_WAKELOCK_SUPPORT +#ifdef CONFIG_PM_WAKELOCKS + wakeup_source_trash(&wmtWakeLock); +#else + wake_lock_destroy(&wmtWakeLock); +#endif + mutex_destroy(&gOsSLock); + WMT_PLAT_DBG_FUNC("destroy wmtWakeLock\n"); +#endif + + iret += mtk_wcn_consys_hw_deinit(); + + WMT_PLAT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} +EXPORT_SYMBOL(wmt_plat_deinit); + +static INT32 wmt_plat_dump_pin_conf(VOID) +{ + WMT_PLAT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration start<=\n"); +#if defined(CONFIG_MTK_LEGACY) + +#ifdef GPIO_COMBO_BGF_EINT_PIN + WMT_PLAT_DBG_FUNC("BGF_EINT(GPIO%d)\n", GPIO_COMBO_BGF_EINT_PIN); +#else + WMT_PLAT_DBG_FUNC("BGF_EINT(not defined)\n"); +#endif + +#ifdef CUST_EINT_COMBO_BGF_NUM + WMT_PLAT_DBG_FUNC("BGF_EINT_NUM(%d)\n", CUST_EINT_COMBO_BGF_NUM); +#else + WMT_PLAT_DBG_FUNC("BGF_EINT_NUM(not defined)\n"); +#endif + +#ifdef GPIO_COMBO_URXD_PIN + WMT_PLAT_DBG_FUNC("UART_RX(GPIO%d)\n", GPIO_COMBO_URXD_PIN); +#else + WMT_PLAT_DBG_FUNC("UART_RX(not defined)\n"); +#endif +#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) +#ifdef GPIO_COMBO_I2S_CK_PIN + WMT_PLAT_DBG_FUNC("I2S_CK(GPIO%d)\n", GPIO_COMBO_I2S_CK_PIN); +#else + WMT_PLAT_DBG_FUNC("I2S_CK(not defined)\n"); +#endif +#ifdef GPIO_COMBO_I2S_WS_PIN + WMT_PLAT_DBG_FUNC("I2S_WS(GPIO%d)\n", GPIO_COMBO_I2S_WS_PIN); +#else + WMT_PLAT_DBG_FUNC("I2S_WS(not defined)\n"); +#endif +#ifdef GPIO_COMBO_I2S_DAT_PIN + WMT_PLAT_DBG_FUNC("I2S_DAT(GPIO%d)\n", GPIO_COMBO_I2S_DAT_PIN); +#else + WMT_PLAT_DBG_FUNC("I2S_DAT(not defined)\n"); +#endif +#else /* FM_ANALOG_INPUT || FM_ANALOG_OUTPUT */ + WMT_PLAT_DBG_FUNC("FM digital mode is not set, no need for I2S GPIOs\n"); +#endif +#ifdef GPIO_GPS_SYNC_PIN + WMT_PLAT_DBG_FUNC("GPS_SYNC(GPIO%d)\n", GPIO_GPS_SYNC_PIN); +#else + WMT_PLAT_DBG_FUNC("GPS_SYNC(not defined)\n"); +#endif + +#ifdef GPIO_GPS_LNA_PIN + WMT_PLAT_INFO_FUNC("GPS_LNA(GPIO%d)\n", GPIO_GPS_LNA_PIN); +#else + WMT_PLAT_INFO_FUNC("GPS_LNA(not defined)\n"); +#endif + +#else /* #if defined(CONFIG_MTK_LEGACY) */ +#endif + WMT_PLAT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration emds<=\n"); + return 0; +} + +INT32 wmt_plat_pwr_ctrl(ENUM_FUNC_STATE state) +{ + INT32 ret = -1; + + switch (state) { + case FUNC_ON: + /* TODO:[ChangeFeature][George] always output this or by request throuth /proc or sysfs? */ + wmt_plat_dump_pin_conf(); + ret = mtk_wcn_consys_hw_pwr_on(gCoClockFlag); + break; + + case FUNC_OFF: + ret = mtk_wcn_consys_hw_pwr_off(gCoClockFlag); + break; + + case FUNC_RST: + ret = mtk_wcn_consys_hw_rst(gCoClockFlag); + break; + case FUNC_STAT: + ret = mtk_wcn_consys_hw_state_show(); + break; + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) in pwr_ctrl\n", state); + break; + } + + return ret; +} +EXPORT_SYMBOL(wmt_plat_pwr_ctrl); + +INT32 wmt_plat_eirq_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state) +{ +#ifdef CONFIG_OF + struct device_node *node; + unsigned int irq_info[3] = { 0, 0, 0 }; +#endif + INT32 iret = -EINVAL; + static INT32 bgf_irq_num = -1; + static UINT32 bgf_irq_flag; + /* TODO: [ChangeFeature][GeorgeKuo]: use another function to handle this, as done in gpio_ctrls */ + + if ((PIN_STA_INIT != state) + && (PIN_STA_DEINIT != state) + && (PIN_STA_EINT_EN != state) + && (PIN_STA_EINT_DIS != state)) { + WMT_PLAT_WARN_FUNC("WMT-PLAT:invalid PIN_STATE(%d) in eirq_ctrl for PIN(%d)\n", state, id); + return -1; + } + + switch (id) { + case PIN_BGF_EINT: + + if (PIN_STA_INIT == state) { +#ifdef CONFIG_OF + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-consys"); + if (node) { + bgf_irq_num = irq_of_parse_and_map(node, 0); + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + WMT_PLAT_ERR_FUNC("get irq flags from DTS fail!!\n"); + return iret; + } + bgf_irq_flag = irq_info[2]; + WMT_PLAT_INFO_FUNC("get irq id(%d) and irq trigger flag(%d) from DT\n", bgf_irq_num, + bgf_irq_flag); + } else { + WMT_PLAT_ERR_FUNC("[%s] can't find CONSYS compatible node\n", __func__); + return iret; + } +#else + bgf_irq_num = MT_CONN2AP_BTIF_WAKEUP_IRQ_ID; + bgf_irq_flag = IRQF_TRIGGER_LOW; +#endif + iret = request_irq(bgf_irq_num, wmt_plat_bgf_irq_isr, bgf_irq_flag, "BTIF_WAKEUP_IRQ", NULL); + if (iret) { + WMT_PLAT_ERR_FUNC("request_irq fail,irq_no(%d),iret(%d)\n", bgf_irq_num, iret); + return iret; + } + gbgfIrqBle.counter = 1; + + } else if (PIN_STA_EINT_EN == state) { + + spin_lock_irqsave(&gbgfIrqBle.lock, gbgfIrqBle.flags); + if (gbgfIrqBle.counter) { + WMT_PLAT_DBG_FUNC("BGF INT has been enabled,counter(%d)\n", gbgfIrqBle.counter); + } else { + enable_irq(bgf_irq_num); + gbgfIrqBle.counter++; + } + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt (en)\n"); + spin_unlock_irqrestore(&gbgfIrqBle.lock, gbgfIrqBle.flags); + } else if (PIN_STA_EINT_DIS == state) { + spin_lock_irqsave(&gbgfIrqBle.lock, gbgfIrqBle.flags); + if (!gbgfIrqBle.counter) { + WMT_PLAT_DBG_FUNC("BGF INT has been disabled,counter(%d)\n", gbgfIrqBle.counter); + } else { + disable_irq_nosync(bgf_irq_num); + gbgfIrqBle.counter--; + } + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt (dis)\n"); + spin_unlock_irqrestore(&gbgfIrqBle.lock, gbgfIrqBle.flags); + } else { + free_irq(bgf_irq_num, NULL); + /* de-init: nothing to do in ALPS, such as un-registration... */ + } + iret = 0; + break; + + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:unsupported EIRQ(PIN_ID:%d) in eirq_ctrl\n", id); + iret = -1; + break; + } + + return iret; +} +EXPORT_SYMBOL(wmt_plat_eirq_ctrl); + +INT32 wmt_plat_gpio_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state) +{ + if ((PIN_ID_MAX > id) + && (PIN_STA_MAX > state)) { + + /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ + if (gfp_set_pin_table[id]) + return (*(gfp_set_pin_table[id])) (state); /* .handler */ + WMT_PLAT_WARN_FUNC("WMT-PLAT: null fp for gpio_ctrl(%d)\n", id); + return -2; + } + return -1; +} +EXPORT_SYMBOL(wmt_plat_gpio_ctrl); + +INT32 wmt_plat_bgf_eint_ctrl(ENUM_PIN_STATE state) +{ +#if defined(CONFIG_MTK_LEGACY) +#ifdef GPIO_COMBO_BGF_EINT_PIN + switch (state) { + case PIN_STA_INIT: + /*set to gpio input low, pull down enable */ + mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_BGF_EINT_PIN, GPIO_DIR_IN); + mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_DOWN); + mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt init(in pd)\n"); + break; + + case PIN_STA_MUX: + mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); + mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_UP); + mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_EINT); + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt mux (eint)\n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable */ + mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_BGF_EINT_PIN, GPIO_DIR_IN); + mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_DOWN); + mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt deinit(in pd)\n"); + break; + + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on BGF EINT\n", state); + break; + } +#else + WMT_PLAT_INFO_FUNC("WMT-PLAT:BGF EINT not defined\n"); +#endif +#else /* #if defined(CONFIG_MTK_LEGACY) */ +#endif + return 0; +} + +static INT32 wmt_plat_gps_sync_ctrl(ENUM_PIN_STATE state) +{ +#if defined(CONFIG_MTK_LEGACY) + +#ifdef GPIO_GPS_SYNC_PIN +#ifndef GPIO_GPS_SYNC_PIN_M_GPS_SYNC +#ifdef GPIO_GPS_SYNC_PIN_M_MD1_GPS_SYNC +#define GPIO_GPS_SYNC_PIN_M_GPS_SYNC GPIO_GPS_SYNC_PIN_M_MD1_GPS_SYNC +#else +#ifdef GPIO_GPS_SYNC_PIN_M_MD2_GPS_SYNC +#define GPIO_GPS_SYNC_PIN_M_GPS_SYNC GPIO_GPS_SYNC_PIN_M_MD2_GPS_SYNC +#endif +#endif +#endif + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + mt_set_gpio_mode(GPIO_GPS_SYNC_PIN, GPIO_GPS_SYNC_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_GPS_SYNC_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_GPS_SYNC_PIN, GPIO_OUT_ZERO); + break; + + case PIN_STA_MUX: + mt_set_gpio_mode(GPIO_GPS_SYNC_PIN, GPIO_GPS_SYNC_PIN_M_GPS_SYNC); + break; + + default: + break; + } +#endif + +#else /* #if defined(CONFIG_MTK_LEGACY) */ +#endif + return 0; +} + +#if MTK_WCN_MT6306_IS_READY +/* MT6306 GPIO7 is GPIO_GPS_LNA_EN, for K2 common phone pin modification */ +static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state) +{ +#ifdef GPIO_GPS_LNA_PIN + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + WMT_PLAT_ERR_FUNC("Gps LNA pin ctrl %d!\n", state); + mt6306_set_gpio_dir(GPIO_GPS_LNA_PIN, GPIO_DIR_OUT); + mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); + break; + case PIN_STA_OUT_H: + WMT_PLAT_ERR_FUNC("Gps LNA pin output high!\n"); + mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ONE); + break; + case PIN_STA_OUT_L: + WMT_PLAT_ERR_FUNC("Gps LNA pin output low!\n"); + mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); + break; + default: + WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + return 0; +#else + WMT_PLAT_WARN_FUNC("host gps lna pin not defined!!!\n"); + return 0; +#endif +} +#else + +static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state) +{ +#if !defined(CONFIG_MTK_LEGACY) + static struct pinctrl_state *gps_lna_init; + static struct pinctrl_state *gps_lna_oh; + static struct pinctrl_state *gps_lna_ol; + static struct pinctrl *consys_pinctrl; + + WMT_PLAT_DBG_FUNC("ENTER++\n"); + consys_pinctrl = mtk_wcn_consys_get_pinctrl(); + if (NULL == consys_pinctrl) { + WMT_PLAT_ERR_FUNC("get consys pinctrl fail\n"); + return -1; + } + + gps_lna_init = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_init"); + if (NULL == gps_lna_init) { + WMT_PLAT_ERR_FUNC("Cannot find gps lna pin init state!\n"); + return -2; + } + + gps_lna_oh = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_oh"); + if (NULL == gps_lna_oh) { + WMT_PLAT_ERR_FUNC("Cannot find gps lna pin oh state!\n"); + return -3; + } + + gps_lna_ol = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_ol"); + if (NULL == gps_lna_ol) { + WMT_PLAT_ERR_FUNC("Cannot find gps lna pin ol state!\n"); + return -4; + } + + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + pinctrl_select_state(consys_pinctrl, gps_lna_init); + WMT_PLAT_DBG_FUNC("set gps lna to init\n"); + break; + case PIN_STA_OUT_H: + pinctrl_select_state(consys_pinctrl, gps_lna_oh); + WMT_PLAT_DBG_FUNC("set gps lna to oh\n"); + break; + case PIN_STA_OUT_L: + pinctrl_select_state(consys_pinctrl, gps_lna_ol); + WMT_PLAT_DBG_FUNC("set gps lna to ol\n"); + break; + + default: + WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + return 0; +#else +#ifdef GPIO_GPS_LNA_PIN + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + mt_set_gpio_pull_enable(GPIO_GPS_LNA_PIN, GPIO_PULL_DISABLE); + mt_set_gpio_dir(GPIO_GPS_LNA_PIN, GPIO_DIR_OUT); + mt_set_gpio_mode(GPIO_GPS_LNA_PIN, GPIO_GPS_LNA_PIN_M_GPIO); + mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); + break; + case PIN_STA_OUT_H: + mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ONE); + break; + case PIN_STA_OUT_L: + mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); + break; + + default: + WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + return 0; +#else + WMT_PLAT_WARN_FUNC("host gps lna pin not defined!!!\n"); + return 0; +#endif +#endif /* !defined(CONFIG_MTK_LEGACY) */ +} +#endif + +INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state) +{ + /* TODO: [NewFeature][GeorgeKuo]: GPIO_I2Sx is changed according to different project. */ + /* TODO: provide a translation table in board_custom.h for different ALPS project customization. */ +#if defined(CONFIG_MTK_LEGACY) + +#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) +#if defined(GPIO_COMBO_I2S_CK_PIN) + switch (state) { + case PIN_STA_INIT: + case PIN_STA_MUX: + mt_set_gpio_mode(GPIO_COMBO_I2S_CK_PIN, GPIO_COMBO_I2S_CK_PIN_M_I2S0_CK); + mt_set_gpio_mode(GPIO_COMBO_I2S_WS_PIN, GPIO_COMBO_I2S_WS_PIN_M_I2S0_WS); + mt_set_gpio_mode(GPIO_COMBO_I2S_DAT_PIN, GPIO_COMBO_I2S_DAT_PIN_M_I2S0_DAT); + WMT_PLAT_DBG_FUNC("WMT-PLAT:I2S init (I2S0 system)\n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + mt_set_gpio_mode(GPIO_COMBO_I2S_CK_PIN, GPIO_COMBO_I2S_CK_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_I2S_CK_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_COMBO_I2S_CK_PIN, GPIO_OUT_ZERO); + + mt_set_gpio_mode(GPIO_COMBO_I2S_WS_PIN, GPIO_COMBO_I2S_WS_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_I2S_WS_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_COMBO_I2S_WS_PIN, GPIO_OUT_ZERO); + + mt_set_gpio_mode(GPIO_COMBO_I2S_DAT_PIN, GPIO_COMBO_I2S_DAT_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_I2S_DAT_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_COMBO_I2S_DAT_PIN, GPIO_OUT_ZERO); + WMT_PLAT_DBG_FUNC("WMT-PLAT:I2S deinit (out 0)\n"); + break; + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on I2S Group\n", state); + break; + } +#else + WMT_PLAT_ERR_FUNC("[MT6620]Error:FM digital mode set, but no I2S GPIOs defined\n"); +#endif +#else + WMT_PLAT_INFO_FUNC + ("[MT6620]warnning:FM digital mode is not set, no I2S GPIO settings should be modified by combo driver\n"); +#endif + +#else /* #if defined(CONFIG_MTK_LEGACY) */ +#endif + return 0; +} + +INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId) +{ +#ifdef CFG_WMT_WAKELOCK_SUPPORT + static INT32 counter; + INT32 status; + INT32 ret = 0; + + ret = mutex_lock_killable(&gOsSLock); + if (ret) { + WMT_PLAT_ERR_FUNC("--->lock gOsSLock failed, ret=%d\n", ret); + return ret; + } + + if (WL_OP_GET == opId) + ++counter; + else if (WL_OP_PUT == opId) + --counter; + + mutex_unlock(&gOsSLock); + if (WL_OP_GET == opId && counter == 1) { + #ifdef CONFIG_PM_WAKELOCKS + __pm_stay_awake(&wmtWakeLock); + status = wmtWakeLock.active; + #else + wake_lock(&wmtWakeLock); + status = wake_lock_active(&wmtWakeLock); + #endif + WMT_PLAT_DBG_FUNC("WMT-PLAT: after wake_lock(%d), counter(%d)\n", status, counter); + + } else if (WL_OP_PUT == opId && counter == 0) { + #ifdef CONFIG_PM_WAKELOCKS + __pm_relax(&wmtWakeLock); + status = wmtWakeLock.active; + #else + wake_unlock(&wmtWakeLock); + status = wake_lock_active(&wmtWakeLock); + #endif + WMT_PLAT_DBG_FUNC("WMT-PLAT: after wake_unlock(%d), counter(%d)\n", status, counter); + } else { + #ifdef CONFIG_PM_WAKELOCKS + status = wmtWakeLock.active; + #else + status = wake_lock_active(&wmtWakeLock); + #endif + WMT_PLAT_WARN_FUNC("WMT-PLAT: wakelock status(%d), counter(%d)\n", status, counter); + } + return 0; +#else + WMT_PLAT_WARN_FUNC("WMT-PLAT: host awake function is not supported.\n"); + return 0; + +#endif +} +EXPORT_SYMBOL(wmt_plat_wake_lock_ctrl); + +INT32 wmt_plat_soc_paldo_ctrl(ENUM_PALDO_TYPE ePt, ENUM_PALDO_OP ePo) +{ + INT32 iRet = 0; + + switch (ePt) { + + case BT_PALDO: + iRet = mtk_wcn_consys_hw_bt_paldo_ctrl(ePo); + break; + case WIFI_PALDO: + iRet = mtk_wcn_consys_hw_wifi_paldo_ctrl(ePo); + break; + case FM_PALDO: + case GPS_PALDO: + iRet = mtk_wcn_consys_hw_vcn28_ctrl(ePo); + break; + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid type(%d) in palod_ctrl\n", ePt); + break; + } + return iRet; +} +EXPORT_SYMBOL(wmt_plat_soc_paldo_ctrl); + +UINT8 *wmt_plat_get_emi_virt_add(UINT32 offset) +{ + return mtk_wcn_consys_emi_virt_addr_get(offset); +} +EXPORT_SYMBOL(wmt_plat_get_emi_virt_add); + +P_CONSYS_EMI_ADDR_INFO wmt_plat_get_emi_phy_add(VOID) +{ + return &mtk_wcn_emi_addr_info; +} +EXPORT_SYMBOL(wmt_plat_get_emi_phy_add); + +#if CONSYS_ENALBE_SET_JTAG +UINT32 wmt_plat_jtag_flag_ctrl(UINT32 en) +{ + return mtk_wcn_consys_jtag_flag_ctrl(en); +} +EXPORT_SYMBOL(wmt_plat_jtag_flag_ctrl); +#endif + +#if CFG_WMT_DUMP_INT_STATUS +VOID wmt_plat_BGF_irq_dump_status(VOID) +{ + WMT_PLAT_INFO_FUNC("this function is null in MT6735\n"); +} +EXPORT_SYMBOL(wmt_plat_BGF_irq_dump_status); + +MTK_WCN_BOOL wmt_plat_dump_BGF_irq_status(VOID) +{ + return MTK_WCN_BOOL_FALSE; +} +EXPORT_SYMBOL(wmt_plat_dump_BGF_irq_status); +#endif + +UINT32 wmt_plat_read_cpupcr(void) +{ + return CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_CPUPCR_OFFSET); +} +EXPORT_SYMBOL(wmt_plat_read_cpupcr); + +UINT32 wmt_plat_read_dmaregs(UINT32 type) +{ + return 0; +#if 0 + switch (type) { + case CONNSYS_CLK_GATE_STATUS: + return CONSYS_REG_READ(CONNSYS_CLK_GATE_STATUS_REG); + case CONSYS_EMI_STATUS: + return CONSYS_REG_READ(CONSYS_EMI_STATUS_REG); + case SYSRAM1: + return CONSYS_REG_READ(SYSRAM1_REG); + case SYSRAM2: + return CONSYS_REG_READ(SYSRAM2_REG); + case SYSRAM3: + return CONSYS_REG_READ(SYSRAM3_REG); + default: + return 0; + } +#endif +} + +INT32 wmt_plat_set_host_dump_state(ENUM_HOST_DUMP_STATE state) +{ + PUINT8 p_virtual_addr = NULL; + + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_SYNC_STATE); + if (!p_virtual_addr) { + WMT_PLAT_ERR_FUNC("get virtual address fail\n"); + return -1; + } + + CONSYS_REG_WRITE(p_virtual_addr, state); + + return 0; +} +EXPORT_SYMBOL(wmt_plat_set_host_dump_state); + +UINT32 wmt_plat_force_trigger_assert(ENUM_FORCE_TRG_ASSERT_T type) +{ + PUINT8 p_virtual_addr = NULL; + + switch (type) { + case STP_FORCE_TRG_ASSERT_EMI: + + WMT_PLAT_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi -->\n"); + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1); + if (!p_virtual_addr) { + WMT_PLAT_ERR_FUNC("get virtual address fail\n"); + return -1; + } + + CONSYS_REG_WRITE(p_virtual_addr, EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1); + WMT_PLAT_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi <--\n"); + break; + case STP_FORCE_TRG_ASSERT_DEBUG_PIN: + + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + + CONSYS_AP2CONN_OSC_EN_OFFSET) & ~CONSYS_AP2CONN_WAKEUP_BIT); + WMT_PLAT_INFO_FUNC("enable:dump CONSYS_AP2CONN_OSC_EN_REG(0x%x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET)); + usleep_range(64, 96); + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + + CONSYS_AP2CONN_OSC_EN_OFFSET) | CONSYS_AP2CONN_WAKEUP_BIT); + WMT_PLAT_INFO_FUNC("disable:dump CONSYS_AP2CONN_OSC_EN_REG(0x%x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET)); + + break; + default: + WMT_PLAT_ERR_FUNC("unknown force trigger assert type\n"); + break; + } + + return 0; +} +EXPORT_SYMBOL(wmt_plat_force_trigger_assert); + +INT32 wmt_plat_update_host_sync_num(VOID) +{ + PUINT8 p_virtual_addr = NULL; + UINT32 sync_num = 0; + + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_SYNC_NUM); + if (!p_virtual_addr) { + WMT_PLAT_ERR_FUNC("get virtual address fail\n"); + return -1; + } + + sync_num = CONSYS_REG_READ(p_virtual_addr); + CONSYS_REG_WRITE(p_virtual_addr, sync_num + 1); + + return 0; +} +EXPORT_SYMBOL(wmt_plat_update_host_sync_num); + +INT32 wmt_plat_get_dump_info(UINT32 offset) +{ + PUINT8 p_virtual_addr = NULL; + + p_virtual_addr = wmt_plat_get_emi_virt_add(offset); + if (!p_virtual_addr) { + WMT_PLAT_ERR_FUNC("get virtual address fail\n"); + return -1; + } + WMT_PLAT_WARN_FUNC("connsys_reg_read (0x%x), (0x%p), (0x%x)\n", CONSYS_REG_READ(p_virtual_addr), p_virtual_addr, + offset); + return CONSYS_REG_READ(p_virtual_addr); +} +EXPORT_SYMBOL(wmt_plat_get_dump_info); + +UINT32 wmt_plat_get_soc_chipid(void) +{ + UINT32 chipId = mtk_wcn_consys_soc_chipid(); + + WMT_PLAT_INFO_FUNC("current SOC chip:0x%x\n", chipId); + return chipId; +} +EXPORT_SYMBOL(wmt_plat_get_soc_chipid); + +#if CFG_WMT_LTE_COEX_HANDLING +INT32 wmt_plat_get_tdm_antsel_index(VOID) +{ + WMT_PLAT_INFO_FUNC("not support LTE in this platform\n"); + return 0; +} +EXPORT_SYMBOL(wmt_plat_get_tdm_antsel_index); +#endif +INT32 wmt_plat_set_dbg_mode(UINT32 flag) +{ + return mtk_wcn_consys_set_dbg_mode(flag); +} +VOID wmt_plat_set_dynamic_dumpmem(UINT32 *buf) +{ + mtk_wcn_consys_set_dynamic_dump(buf); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt6755/ahb_pdma.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt6755/ahb_pdma.c new file mode 100644 index 0000000000000000000000000000000000000000..b40085fe057e6d79320da356edeb1a4bc18c28f7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt6755/ahb_pdma.c @@ -0,0 +1,527 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#define MODULE_AHB_DMA + +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#if CONFIG_ANDROID +#include +#endif + +#include /* IRQT_FALLING */ + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ + +#include + +#include /* readw and writew */ + +#include + +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif /* defined(CONFIG_MTK_CLKMGR) */ + +#include "hif.h" +#include "hif_pdma.h" +#include "gl_os.h" + +#include + +/* #if (CONF_MTK_AHB_DMA == 1) */ + +/* #define PDMA_DEBUG_SUP */ + +#ifdef PDMA_DEBUG_SUP +#define PDMA_DBG pr_debug +#else +#define PDMA_DBG(_fmt, ...) +#endif /* PDMA_DEBUG_SUP */ + +static UINT32 gDmaReg[AP_DMA_HIF_0_LENGTH / 4 + 1]; +#if !defined(CONFIG_MTK_CLKMGR) +struct clk *g_clk_wifi_pdma; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID HifPdmaConfig(IN void *HifInfoSrc, IN void *Conf); + +static VOID HifPdmaStart(IN void *HifInfoSrc); + +static VOID HifPdmaStop(IN void *HifInfoSrc); + +static MTK_WCN_BOOL HifPdmaPollStart(IN void *HifInfoSrc); + +static MTK_WCN_BOOL HifPdmaPollIntr(IN void *HifInfoSrc); + +static VOID HifPdmaAckIntr(IN void *HifInfoSrc); + +static VOID HifPdmaClockCtrl(IN UINT_32 FlgIsEnabled); + +static VOID HifPdmaRegDump(IN void *HifInfoSrc); + +static VOID HifPdmaReset(IN void *HifInfoSrc); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +GL_HIF_DMA_OPS_T HifPdmaOps = { + .DmaConfig = HifPdmaConfig, + .DmaStart = HifPdmaStart, + .DmaStop = HifPdmaStop, + .DmaPollStart = HifPdmaPollStart, + .DmaPollIntr = HifPdmaPollIntr, + .DmaAckIntr = HifPdmaAckIntr, + .DmaClockCtrl = HifPdmaClockCtrl, + .DmaRegDump = HifPdmaRegDump, + .DmaReset = HifPdmaReset +}; + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config PDMA TX/RX. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] Conf Pointer to the settings. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID HifPdmaInit(GL_HIF_INFO_T *HifInfo) +{ + /* IO remap PDMA register memory */ + HifInfo->DmaRegBaseAddr = ioremap(AP_DMA_HIF_BASE, AP_DMA_HIF_0_LENGTH); + + /* assign PDMA operators */ + HifInfo->DmaOps = &HifPdmaOps; + + /* enable PDMA mode */ + HifInfo->fgDmaEnable = TRUE; + +#if 1 /* MPU Setting */ + /* WIFI using TOP 512KB */ + DBGLOG(INIT, INFO, "[wlan] MPU region 12, 0x%08x - 0x%08x\n", (UINT_32) gConEmiPhyBase, + (UINT_32) (gConEmiPhyBase + 512 * 1024)); + emi_mpu_set_region_protection(gConEmiPhyBase, gConEmiPhyBase + 512 * 1024 - 1, 12, + SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + NO_PROTECTION, FORBIDDEN, FORBIDDEN)); +#endif + +#if !defined(CONFIG_MTK_CLKMGR) + g_clk_wifi_pdma = HifInfo->clk_wifi_dma; +#endif + + PDMA_DBG("PDMA> HifPdmaInit ok!\n"); +} + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* \param[in] Param Pointer to the settings. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaConfig(IN void *HifInfoSrc, IN void *Param) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + MTK_WCN_HIF_DMA_CONF *Conf = (MTK_WCN_HIF_DMA_CONF *) Param; + UINT_32 RegVal; + + /* Assign fixed value */ + Conf->Burst = HIF_PDMA_BURST_4_4; /* vs. HIF_BURST_4DW */ + Conf->Fix_en = FALSE; + + /* AP_P_DMA_G_DMA_2_CON */ + PDMA_DBG("PDMA> Conf->Dir = %d\n", Conf->Dir); + + /* AP_DMA_HIF_0_CON */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_CON); + RegVal &= ~(ADH_CR_BURST_LEN | ADH_CR_FIX_EN | ADH_CR_DIR); + RegVal |= (((Conf->Burst << ADH_CR_BURST_LEN_OFFSET) & ADH_CR_BURST_LEN) | + (Conf->Fix_en << ADH_CR_FIX_EN_OFFSET) | (Conf->Dir)); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_CON, RegVal); + PDMA_DBG("PDMA> AP_DMA_HIF_0_CON = 0x%08x\n", RegVal); + + /* AP_DMA_HIF_0_SRC_ADDR */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_SRC_ADDR, Conf->Src); + PDMA_DBG("PDMA> AP_DMA_HIF_0_SRC_ADDR = 0x%08lx\n", Conf->Src); + + /* AP_DMA_HIF_0_DST_ADDR */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_DST_ADDR, Conf->Dst); + PDMA_DBG("PDMA> AP_DMA_HIF_0_DST_ADDR = 0x%08lx\n", Conf->Dst); + + /* AP_DMA_HIF_0_LEN */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_LEN, (Conf->Count & ADH_CR_LEN)); + PDMA_DBG("PDMA> AP_DMA_HIF_0_LEN = %u\n", (UINT_32)(Conf->Count & ADH_CR_LEN)); + +} /* End of HifPdmaConfig */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Start PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaStart(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT_32 RegVal, RegId, RegIdx; + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_SRC_ADDR2); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_SRC_ADDR2, (RegVal | ADH_CR_SRC_ADDR2)); + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_DST_ADDR2); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_DST_ADDR2, (RegVal | ADH_CR_DST_ADDR2)); + + /* Enable interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_EN, (RegVal | ADH_CR_INTEN_FLAG_0)); + + /* keep old register settings */ + RegIdx = 0; + for (RegId = 0; RegId < AP_DMA_HIF_0_LENGTH; RegId += 4) + gDmaReg[RegIdx++] = HIF_DMAR_READL(HifInfo, RegId); + + /* Start DMA */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_EN, (RegVal | ADH_CR_EN)); + + PDMA_DBG("PDMA> HifPdmaStart...\n"); + +} /* End of HifPdmaStart */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaStop(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT_32 RegVal; +/* UINT32 pollcnt; */ + + /* Disable interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_EN, (RegVal & ~(ADH_CR_INTEN_FLAG_0))); + +#if 0 /* DE says we donot need to do it */ + /* Stop DMA */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_STOP); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_STOP, (RegVal | ADH_CR_STOP)); + + /* Polling START bit turn to 0 */ + pollcnt = 0; + do { + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); + if (pollcnt++ > 100000) + ; /* TODO: warm reset PDMA */ + } while (RegVal & ADH_CR_EN); +#endif + +} /* End of HifPdmaStop */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Enable PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static MTK_WCN_BOOL HifPdmaPollStart(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT_32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); + return ((RegVal & ADH_CR_EN) != 0) ? TRUE : FALSE; + +} /* End of HifPdmaPollStart */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Poll PDMA TX/RX done. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static MTK_WCN_BOOL HifPdmaPollIntr(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT_32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_FLAG); + return ((RegVal & ADH_CR_FLAG_0) != 0) ? TRUE : FALSE; + +} /* End of HifPdmaPollIntr */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Acknowledge PDMA TX/RX done. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaAckIntr(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT_32 RegVal; + + /* Write 0 to clear interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_FLAG); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_FLAG, (RegVal & ~ADH_CR_FLAG_0)); + +} /* End of HifPdmaAckIntr */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Acknowledge PDMA TX/RX done. +* +* \param[in] FlgIsEnabled TRUE: enable; FALSE: disable +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaClockCtrl(IN UINT_32 FlgIsEnabled) +{ +#if !defined(CONFIG_MTK_CLKMGR) + int ret = 0; +#endif +#if defined(CONFIG_MTK_CLKMGR) + if (FlgIsEnabled == TRUE) + enable_clock(MT_CG_INFRA_APDMA, "WLAN"); + else + disable_clock(MT_CG_INFRA_APDMA, "WLAN"); +#else + if (FlgIsEnabled == TRUE) { + ret = clk_prepare_enable(g_clk_wifi_pdma); + if (ret) + DBGLOG(INIT, TRACE, "[CCF]clk_prepare_enable ret= %d\n", ret); + } else { + clk_disable_unprepare(g_clk_wifi_pdma); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dump PDMA related registers. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaRegDump(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + INT_8 *pucIoAddr; + UINT_32 RegId, RegVal, RegIdx; + UINT_32 RegNum = 0; + + DBGLOG(INIT, INFO, "PDMA> Register content before start 0x%x=\n\t", AP_DMA_HIF_BASE); + for (RegId = 0, RegIdx = 0; RegId < AP_DMA_HIF_0_LENGTH; RegId += 4) { + RegVal = gDmaReg[RegIdx++]; + DBGLOG(INIT, INFO, "0x%08x ", RegVal); + + if (RegNum++ >= 3) { + DBGLOG(INIT, INFO, "\n"); + DBGLOG(INIT, INFO, "PDMA> Register content 0x%x=\n\t", AP_DMA_HIF_BASE + RegId + 4); + RegNum = 0; + } + } + + DBGLOG(INIT, INFO, "PDMA> Register content after start 0x%x=\n\t", AP_DMA_HIF_BASE); + for (RegId = 0; RegId < AP_DMA_HIF_0_LENGTH; RegId += 4) { + RegVal = HIF_DMAR_READL(HifInfo, RegId); + DBGLOG(INIT, INFO, "0x%08x ", RegVal); + + if (RegNum++ >= 3) { + DBGLOG(INIT, INFO, "\n"); + DBGLOG(INIT, INFO, "PDMA> Register content 0x%x=\n\t", AP_DMA_HIF_BASE + RegId + 4); + RegNum = 0; + } + } + + pucIoAddr = ioremap(0x10001000, 0x100); + if (pucIoAddr != 0) { + DBGLOG(INIT, INFO, "\nPDMA> clock status = 0x%x\n\n", *(volatile unsigned int *)(pucIoAddr + 0x94)); + iounmap(pucIoAddr); + } + pucIoAddr = ioremap(0x10201180, 0x10); + if (pucIoAddr) { /* DMA bus status */ + DBGLOG(INIT, INFO, "0x10201180~0x10201090: 0x%x, 0x%x, 0x%x, 0x%x", + *(volatile unsigned int *)pucIoAddr, *(volatile unsigned int *)(pucIoAddr + 4), + *(volatile unsigned int *)(pucIoAddr + 8), *(volatile unsigned int *)(pucIoAddr + 12)); + iounmap(pucIoAddr); + } + pucIoAddr = ioremap(0x1000320c, 0x8); + if (pucIoAddr) { + DBGLOG(INIT, INFO, "0x1000320C~0x10003214: 0x%x, 0x%x", + *(volatile unsigned int *)pucIoAddr, *(volatile unsigned int *)(pucIoAddr + 4)); + iounmap(pucIoAddr); + } + pucIoAddr = ioremap(0x11000008, 0x4); + if (pucIoAddr) { /* DMA global register status, to observe the channel status of all channels */ + UINT_16 chnlStatus = 0; + UINT_8 i = 1; + PUINT_8 pucChnlStatus = NULL; + + chnlStatus = (*(volatile PUINT_32)pucIoAddr) & 0xffff; + DBGLOG(INIT, INFO, "0x11000008: 0x%x", *(volatile unsigned int *)pucIoAddr); + iounmap(pucIoAddr); + for (; i < 16; i++) { + if ((chnlStatus >> i & 0x1) == 0) + continue; + pucChnlStatus = (PUINT_8) ioremap(AP_DMA_HIF_BASE + i * 0x80, 0x70); + if (!pucChnlStatus) { + DBGLOG(INIT, INFO, "AP_DMA_BASE+%x, ioremap fail\n", i * 0x80); + continue; + } + DBGLOG(INIT, INFO, "AP_DMA_BASE+%x status:\n", i * 0x80); + DBGLOG(INIT, INFO, "channel enabled: %u\n", *(volatile PUINT_32)(pucChnlStatus + 0x8)); + DBGLOG(INIT, INFO, "channel direction: %u\n", *(volatile PUINT_32)(pucChnlStatus + 0x18)); + DBGLOG(INIT, INFO, "channel debug status: %u\n", *(volatile PUINT_32)(pucChnlStatus + 0x50)); + iounmap(pucChnlStatus); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reset DMA. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaReset(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT_32 LoopCnt; + + /* do warm reset: DMA will wait for current traction finished */ + DBGLOG(INIT, INFO, "\nDMA> do warm reset...\n"); + + /* normally, we need to sure that bit0 of AP_P_DMA_G_DMA_2_EN is 1 here */ + + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x01); + + for (LoopCnt = 0; LoopCnt < 10000; LoopCnt++) { + if (!HifPdmaPollStart(HifInfo)) + break; /* reset ok */ + } + + if (HifPdmaPollStart(HifInfo)) { + /* do hard reset because warm reset fails */ + DBGLOG(INIT, INFO, "\nDMA> do hard reset...\n"); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x02); + mdelay(1); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x00); + } +} + +/* #endif */ /* CONF_MTK_AHB_DMA */ + +/* End of ahb_pdma.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/plat/mt6755/plat_priv.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/plat/mt6755/plat_priv.c new file mode 100644 index 0000000000000000000000000000000000000000..6f410d8de309c9530618f1f3134950ac79d9d384 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/plat/mt6755/plat_priv.c @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include "mach/mt_ppm_api.h" +#include "mt_idle.h" + +#define MAX_CPU_CORE_NUM 8 +#define MAX_CPU_FREQ 1500000000 + +static unsigned int g_force_core_num; +static unsigned int g_force_core_freq; + +int kalBoostCpu(unsigned int core_num) +{ + unsigned long freq = MAX_CPU_FREQ; + + if (core_num >= 2) + idle_lock_by_conn(1);/* Disable deepidle/SODI when throughput > 40Mbps */ + else + idle_lock_by_conn(0);/* Enable deepidle/SODI */ + + if (g_force_core_num || g_force_core_freq) { + core_num = g_force_core_num; + freq = g_force_core_freq; + } else { + if (core_num == 1) + core_num++; + freq = core_num == 0 ? 0 : freq; + } + + if (core_num > MAX_CPU_CORE_NUM) + core_num = MAX_CPU_CORE_NUM; + pr_warn("enter kalBoostCpu, core_num:%d, freq:%ld\n", core_num, freq); + + mt_ppm_sysboost_core(BOOST_BY_WIFI, core_num); + mt_ppm_sysboost_freq(BOOST_BY_WIFI, freq); + + return 0; +} + +int kalSetCpuNumFreq(unsigned int core_num, unsigned int freq) +{ + pr_warn("enter kalSetCpuNumFreq, core_num:%d, freq:%d\n", core_num, freq); + + g_force_core_num = core_num; + g_force_core_freq = freq; + + kalBoostCpu(g_force_core_num); + + return 0; +} + diff --git a/drivers/misc/mediatek/debug_latch/lastpc/mt6755/Makefile b/drivers/misc/mediatek/debug_latch/lastpc/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5914d42bc149ec3cb56785dc1e55c349cbee861e --- /dev/null +++ b/drivers/misc/mediatek/debug_latch/lastpc/mt6755/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += lastpc_plt.o + +ifeq ($(CONFIG_MT_ENG_BUILD),y) +CFLAGS_lastpc_plt.o := -DDEBUG +endif diff --git a/drivers/misc/mediatek/debug_latch/lastpc/mt6755/lastpc_plt.c b/drivers/misc/mediatek/debug_latch/lastpc/mt6755/lastpc_plt.c new file mode 100644 index 0000000000000000000000000000000000000000..b77b9e94ae9b0b5e14502d251fdd20b32a2646a6 --- /dev/null +++ b/drivers/misc/mediatek/debug_latch/lastpc/mt6755/lastpc_plt.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include + +#include "../lastpc.h" + +struct lastpc_imp { + struct lastpc_plt plt; + void __iomem *toprgu_reg; +}; + +#define to_lastpc_imp(p) container_of((p), struct lastpc_imp, plt) +/* +#define LASTPC 0X20 +#define LASTSP 0X24 +#define LASTFP 0X28 +#define MUX_CONTOL_C0_REG (base + 0x140) +#define MUX_READ_C0_REG (base + 0x144) +#define MUX_CONTOL_C1_REG (base + 0x21C) +#define MUX_READ_C1_REG (base + 0x25C) + +static unsigned int LASTPC_MAGIC_NUM[] = {0x3, 0xB, 0x33, 0x43}; +*/ + +static int lastpc_plt_start(struct lastpc_plt *plt) +{ + return 0; +} + +static int lastpc_plt_dump(struct lastpc_plt *plt, char *buf, int len) +{ + void __iomem *mcu_base = plt->common->base + 0x410; + int ret = -1, cnt = num_possible_cpus(); + char *ptr = buf; + char *ptr_end = buf + len; + unsigned long pc_value; + unsigned long fp_value; + unsigned long sp_value; +#ifdef CONFIG_ARM64 + unsigned long pc_value_h; + unsigned long fp_value_h; + unsigned long sp_value_h; +#endif + unsigned long size = 0; + unsigned long offset = 0; + char str[KSYM_SYMBOL_LEN]; + int i; + int cluster, cpu_in_cluster; + int strlen = 0; + + if (cnt < 0) + return ret; + +#ifdef CONFIG_ARM64 + /* Get PC, FP, SP and save to buf */ + for (i = 0; i < cnt; i++) { + cluster = i / 4; + cpu_in_cluster = i % 4; + pc_value_h = + readl(IOMEM((mcu_base + 0x4) + (cpu_in_cluster << 5) + (0x100 * cluster))); + pc_value = + (pc_value_h << 32) | + readl(IOMEM((mcu_base + 0x0) + (cpu_in_cluster << 5) + (0x100 * cluster))); + fp_value_h = + readl(IOMEM((mcu_base + 0x14) + (cpu_in_cluster << 5) + (0x100 * cluster))); + fp_value = + (fp_value_h << 32) | + readl(IOMEM((mcu_base + 0x10) + (cpu_in_cluster << 5) + (0x100 * cluster))); + sp_value_h = + readl(IOMEM((mcu_base + 0x1c) + (cpu_in_cluster << 5) + (0x100 * cluster))); + sp_value = + (sp_value_h << 32) | + readl(IOMEM((mcu_base + 0x18) + (cpu_in_cluster << 5) + (0x100 * cluster))); + kallsyms_lookup(pc_value, &size, &offset, NULL, str); + + strlen = snprintf(ptr, ptr_end - ptr, + "[LAST PC] CORE_%d PC = 0x%lx(%s + 0x%lx), ", + i, pc_value, str, offset); + if (strlen < 0) + goto overflow; + + ptr += strlen; + strlen = snprintf(ptr, ptr_end - ptr, + "FP = 0x%lx, SP = 0x%lx\n", + fp_value, sp_value); + if (strlen < 0) + goto overflow; + + ptr += strlen; + pr_err("[LAST PC] CORE_%d PC = 0x%lx(%s), FP = 0x%lx, SP = 0x%lx\n", i, pc_value, + str, fp_value, sp_value); + } +#else + /* Get PC, FP, SP and save to buf */ + for (i = 0; i < cnt; i++) { + cluster = i / 4; + cpu_in_cluster = i % 4; + pc_value = + readl(IOMEM((mcu_base + 0x0) + (cpu_in_cluster << 5) + (0x100 * cluster))); + fp_value = + readl(IOMEM((mcu_base + 0x8) + (cpu_in_cluster << 5) + (0x100 * cluster))); + sp_value = + readl(IOMEM((mcu_base + 0xc) + (cpu_in_cluster << 5) + (0x100 * cluster))); + kallsyms_lookup((unsigned long)pc_value, &size, &offset, NULL, str); + + strlen = snprintf(ptr, ptr_end - ptr, + "[LAST PC] CORE_%d PC = 0x%lx(%s + 0x%lx), ", + i, pc_value, str, offset); + + if (strlen < 0) + goto overflow; + ptr += strlen; + strlen = snprintf(ptr, ptr_end - ptr, + "FP = 0x%lx, SP = 0x%lx\n", + fp_value, sp_value); + if (strlen < 0) + goto overflow; + ptr += strlen; + pr_err("[LAST PC] CORE_%d PC = 0x%lx(%s), FP = 0x%lx, SP = 0x%lx\n", i, pc_value, + str, fp_value, sp_value); + } +#endif + return 0; + +overflow: + pr_err("[LAST PC] string buffer overflow\n"); + return -1; +} + +static int reboot_test(struct lastpc_plt *plt) +{ + return 0; +} + +static struct lastpc_plt_operations lastpc_ops = { + .start = lastpc_plt_start, + .dump = lastpc_plt_dump, + .reboot_test = reboot_test, +}; + +static int __init lastpc_init(void) +{ + struct lastpc_imp *drv = NULL; + int ret = 0; + + drv = kzalloc(sizeof(struct lastpc_imp), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + drv->plt.ops = &lastpc_ops; + drv->plt.chip_code = 0x6755; + drv->plt.min_buf_len = 2048; /* TODO: can calculate the len by how many levels of bt we want */ + + ret = lastpc_register(&drv->plt); + if (ret) { + pr_err("%s:%d: lastpc_register failed\n", __func__, __LINE__); + goto register_lastpc_err; + } + + return 0; + +register_lastpc_err: + kfree(drv); + return ret; +} + +arch_initcall(lastpc_init); diff --git a/drivers/misc/mediatek/devapc/mt6755/Makefile b/drivers/misc/mediatek/devapc/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5b6b76852cf5b2f9d098a7b17c9d0503b5d3a402 --- /dev/null +++ b/drivers/misc/mediatek/devapc/mt6755/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += devapc.o \ No newline at end of file diff --git a/drivers/misc/mediatek/devapc/mt6755/devapc.c b/drivers/misc/mediatek/devapc/mt6755/devapc.c new file mode 100644 index 0000000000000000000000000000000000000000..cb92a21a3a70fdee1819b47fc0147f5efbfff958 --- /dev/null +++ b/drivers/misc/mediatek/devapc/mt6755/devapc.c @@ -0,0 +1,869 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MTK_HIBERNATION +#include +#endif + +#ifdef CONFIG_MTK_CLKMGR +/* mt_clkmgr */ +#include +#else +/* CCF */ +#include +#endif + +#include "mt_device_apc.h" +#include "mt_io.h" +#include "sync_write.h" +#include "mach/irqs.h" +#include "devapc.h" + +#if defined(CONFIG_MTK_AEE_FEATURE) && defined(DEVAPC_ENABLE_AEE) +#include +#endif + +/* Debug message event */ +#define DEVAPC_LOG_NONE 0x00000000 +#define DEVAPC_LOG_ERR 0x00000001 +#define DEVAPC_LOG_WARN 0x00000002 +#define DEVAPC_LOG_INFO 0x00000004 +#define DEVAPC_LOG_DBG 0x00000008 + +#define DEVAPC_LOG_LEVEL (DEVAPC_LOG_DBG) + +#define DEVAPC_MSG(fmt, args...) \ + do { \ + if (DEVAPC_LOG_LEVEL & DEVAPC_LOG_DBG) { \ + pr_debug(fmt, ##args); \ + } else if (DEVAPC_LOG_LEVEL & DEVAPC_LOG_INFO) { \ + pr_info(fmt, ##args); \ + } else if (DEVAPC_LOG_LEVEL & DEVAPC_LOG_WARN) { \ + pr_warn(fmt, ##args); \ + } else if (DEVAPC_LOG_LEVEL & DEVAPC_LOG_ERR) { \ + pr_err(fmt, ##args); \ + } \ + } while (0) + + +#define DEVAPC_VIO_LEVEL (DEVAPC_LOG_ERR) + +#define DEVAPC_VIO_MSG(fmt, args...) \ + do { \ + if (DEVAPC_VIO_LEVEL & DEVAPC_LOG_DBG) { \ + pr_debug(fmt, ##args); \ + } else if (DEVAPC_VIO_LEVEL & DEVAPC_LOG_INFO) { \ + pr_info(fmt, ##args); \ + } else if (DEVAPC_VIO_LEVEL & DEVAPC_LOG_WARN) { \ + pr_warn(fmt, ##args); \ + } else if (DEVAPC_VIO_LEVEL & DEVAPC_LOG_ERR) { \ + pr_err(fmt, ##args); \ + } \ + } while (0) + + + +#ifndef CONFIG_MTK_CLKMGR + +#if 0 +/* bypass clock! */ +static struct clk *dapc_clk; +#endif + +#endif + +static struct cdev *g_devapc_ctrl; +static unsigned int devapc_irq; +static void __iomem *devapc_pd_base; + +static unsigned int enable_dynamic_one_core_violation_debug; + +#if defined(CONFIG_MTK_AEE_FEATURE) && defined(DEVAPC_ENABLE_AEE) +static unsigned long long devapc_vio_first_trigger_time[DEVAPC_TOTAL_SLAVES]; + +/* violation times */ +static unsigned int devapc_vio_count[DEVAPC_TOTAL_SLAVES]; + +/* show the status of whether AEE warning has been populated */ +static unsigned int devapc_vio_aee_shown[DEVAPC_TOTAL_SLAVES]; +static unsigned int devapc_vio_current_aee_trigger_times; +#endif + +static struct DEVICE_INFO devapc_devices[] = { + /*device name enable_vio_irq */ + /*0 */ + {"INFRA_AO_TOP_LEVEL_CLOCK_GENERATOR", true}, + {"INFRA_AO_INFRASYS_CONFIG_REGS", true}, + {"INFRA_AO_IO_CFG", true}, + {"INFRA_AO_PERICFG", true}, + {"INFRA_AO_DRAM_CONTROLLER", true}, + {"INFRA_AO_GPIO", true}, + {"INFRA_AO_TOP_LEVEL_SLP_MANAGER", true}, + {"INFRA_AO_TOP_RGU", true}, + {"INFRA_AO_APXGPT", true}, + {"INFRA_AO_RESERVE_REGION", true}, + + /*10 */ + {"INFRA_AO_SEJ", true}, + {"INFRA_AO_AP_CIRQ_EINT", true}, + {"INFRA_AO_APMIXEDSYS_ FHCTL", true}, + {"INFRA_AO_PMIC_WRAP", true}, + {"INFRA_AO_DEVICE_APC_AO", true}, + {"INFRA_AO_DDRPHY", true}, + {"INFRA_AO_KEYPAD", true}, + {"INFRA_AO_TOP_MISC", true}, + {"INFRA_AO_RESERVE_REGION", true}, + {"INFRA_AO_RESERVE_REGION", true}, + + /*20 */ + {"INFRA_AO_CLDMA_AO_TOP_AP", true}, + {"INFRA_AO_CLDMA_AO_TOP_MD", true}, + {"INFRA_AO_AES_TOP0", true}, + {"INFRA_AO_AES_TOP1", true}, + {"INFRA_AO_MDEM_TEMP_SHARE", true}, + {"INFRA_AO_SLEEP_CONTROL_PROCESSOR", true}, + {"INFRASYS_MCUSYS_CONFIG_REG", true}, + {"INFRASYS_CONTROL_REG", true}, + {"INFRASYS_BOOTROM/SRAM", true}, + {"INFRASYS_EMI_BUS_INTERFACE", true}, + + /*30 */ + {"INFRASYS_SYSTEM_CIRQ", true}, + {"INFRASYS_MM_IOMMU_CONFIGURATION", true}, + {"INFRASYS_EFUSEC", true}, + {"INFRASYS_DEVICE_APC_MONITOR", true}, + {"INFRASYS_DEBUG_TRACKER", true}, + {"INFRASYS_CCI0_AP", true}, + {"INFRASYS_CCI0_MD", true}, + {"INFRASYS_CCI1_AP", true}, + {"INFRASYS_CCI1_MD", true}, + {"INFRASYS_MBIST_CONTROL_REG", true}, + + /*40 */ + {"INFRASYS_DRAM_CONTROLLER", true}, + {"INFRASYS_TRNG", true}, + {"INFRASYS_GCPU", true}, + {"INFRASYS_MD_CCIF_MD1", true}, + {"INFRASYS_GCE", true}, + {"INFRASYS_MD_CCIF_MD2", true}, + {"INFRASYS_RESERVE", true}, + {"INFRASYS_ANA_MIPI_DSI0", true}, + {"INFRASYS_ANA_MIPI_DSI1", true}, + {"INFRASYS_ANA_MIPI_CSI0", true}, + + /*50 */ + {"INFRASYS_ANA_MIPI_CSI1", true}, + {"INFRASYS_ANA_MIPI_CSI2", true}, + {"INFRASYS_GPU_RSA", true}, + {"INFRASYS_CLDMA_PDN_AP", true}, + {"INFRASYS_CLDMA_PDN_MD", true}, + {"INFRASYS_MDSYS_INTF", true}, + {"INFRASYS_BPI_BIS_SLV0", true}, + {"INFRASYS_BPI_BIS_SLV1", true}, + {"INFRASYS_BPI_BIS_SLV2", true}, + {"INFRAYS_EMI_MPU_REG", true}, + + /*60 */ + {"INFRAYS_DVFS_PROC", true}, + {"INFRASYS_DEBUGTOP", true}, + {"DMA", true}, + {"AUXADC", true}, + {"UART0", true}, + {"UART1", true}, + {"UART2", true}, + {"UART3", true}, + {"PWM", true}, + {"I2C0", false}, + + /*70 */ + {"I2C1", false}, + {"I2C2", false}, + {"SPI0", true}, + {"PTP_THERMAL_CTL", true}, + {"BTIF", true}, + {"IRTX", true}, + {"DISP_PWM", true}, + {"I2C3", false}, + {"SPI1", true}, + {"I2C4", false}, + + /*80 */ + {"RESERVE", true}, + {"RESERVE", true}, + {"USB2.0", true}, + {"USB2.0 SIF", true}, + {"MSDC0", true}, + {"MSDC1", true}, + {"MSDC2", true}, + {"MSDC3", true}, + {"USB3.0", true}, + {"USB3.0 SIF", true}, + + /*90 */ + {"USB3.0 SIF2", true}, + {"AUDIO", true}, + {"WCN AHB SLAVE", true}, + {"MD_PERIPHERALS", true}, + {"MD2_PERIPHERALS", true}, + {"RESERVE", true}, + {"RESERVE", true}, + {"RESERVE", true}, + {"G3D_CONFIG_0", true}, + {"G3D_CONFIG_1", true}, + + /*100 */ + {"G3D_CONFIG_2", true}, + {"G3D_CONFIG_3", true}, + {"G3D_CONFIG_4", true}, + {"G3D_POWER_CONTROL", true}, + {"MALI_CONFIG", true}, + {"MMSYS_CONFIG", true}, + {"MDP_RDMA", true}, + {"MDP_RSZ0", true}, + {"MDP_RSZ1", true}, + {"MDP_WDMA", true}, + + /*110 */ + {"MDP_WROT", true}, + {"MDP_TDSHP", true}, + {"MDP_COLOR", true}, + {"DISP_OVL0", true}, + {"DISP_OVL1", true}, + {"DISP_RDMA0", true}, + {"DISP_RDMA1", true}, + {"DISP_WDMA0", true}, + {"DISP_COLOR", true}, + {"DISP_CCORR", true}, + + /*120 */ + {"DISP_AAL", true}, + {"DISP_GAMMA", true}, + {"DISP_DITHER", true}, + {"DSI", true}, + {"DPI", true}, + {"MM_MUTEX", true}, + {"SMI_LARB0", true}, + {"SMI_COMMON", true}, + {"DISP_WDMA1", true}, + {"DISP_OVL0_2L", true}, + + /*130 */ + {"DISP_OVL1_2L", true}, + {"RESERVE", true}, + {"RESERVE", true}, + {"IMGSYS_CONFIG", true}, + {"SMI_LARB2", true}, + {"RESERVE", true}, + {"RESERVE", true}, + {"CAM0", true}, + {"CAM1", true}, + {"CAM2", true}, + + /*140 */ + {"CAM3", true}, + {"SENINF", true}, + {"CAMSV", true}, + {"RESERVE", true}, + {"FD", true}, + {"MIPI_RX", true}, + {"CAM0", true}, + {"CAM2", true}, + {"CAM3", true}, + {"VDEC_GLOBAL_CON", true}, + + /*150 */ + {"SMI_LARB1", true}, + {"VDEC_FULL_TOP", true}, + {"VENC_GLOBAL_CON", true}, + {"SMI_LARB3", true}, + {"VENC", true}, + {"JPEGENC", true}, + {"JPEGDEC", true}, + +}; + +/***************************************************************************** +*FUNCTION DEFINITION +*****************************************************************************/ +static int clear_vio_status(unsigned int module); +static int devapc_ioremap(void); + +/************************************************************************** +*EXTERN FUNCTION +**************************************************************************/ +int mt_devapc_emi_initial(void) +{ + devapc_ioremap(); + + if (NULL != devapc_pd_base) { + mt_reg_sync_writel(readl(IOMEM(DEVAPC0_PD_APC_CON)) & (0xFFFFFFFF ^ (1 << 2)), + DEVAPC0_PD_APC_CON); + mt_reg_sync_writel(ABORT_EMI, DEVAPC0_D0_VIO_STA_5); + mt_reg_sync_writel(ABORT_EMI_MPU, DEVAPC0_D0_VIO_STA_5); + + /* Notice: You cannot unmask Type B slave (e.g. EMI, EMI_MPU) unless unregistering IRQ */ + + pr_err("[DEVAPC] EMI_MPU Init done\n"); + return 0; + } + + return -1; +} + +int mt_devapc_check_emi_violation(void) +{ + if ((readl(IOMEM(DEVAPC0_D0_VIO_STA_5)) & ABORT_EMI) == 0) + return -1; + + DEVAPC_VIO_MSG("EMI violation...\n"); + return 0; +} + +int mt_devapc_check_emi_mpu_violation(void) +{ + if ((readl(IOMEM(DEVAPC0_D0_VIO_STA_5)) & ABORT_EMI_MPU) == 0) + return -1; + + DEVAPC_VIO_MSG("EMI_MPU violation...\n"); + return 0; +} + +int mt_devapc_clear_emi_violation(void) +{ + if ((readl(IOMEM(DEVAPC0_D0_VIO_STA_5)) & ABORT_EMI) != 0) + mt_reg_sync_writel(ABORT_EMI, DEVAPC0_D0_VIO_STA_5); + + return 0; +} + +int mt_devapc_clear_emi_mpu_violation(void) +{ + if ((readl(IOMEM(DEVAPC0_D0_VIO_STA_5)) & ABORT_EMI_MPU) != 0) + mt_reg_sync_writel(ABORT_EMI_MPU, DEVAPC0_D0_VIO_STA_5); + + return 0; +} + +/************************************************************************** +*STATIC FUNCTION +**************************************************************************/ + +static int devapc_ioremap(void) +{ + if (NULL == devapc_pd_base) { + struct device_node *node = NULL; + /*IO remap */ + + node = of_find_compatible_node(NULL, NULL, "mediatek,devapc"); + if (node) { + devapc_pd_base = of_iomap(node, 0); + devapc_irq = irq_of_parse_and_map(node, 0); + DEVAPC_MSG("[DEVAPC] PD_ADDRESS %p, IRD: %d\n", devapc_pd_base, devapc_irq); + } else { + pr_err("[DEVAPC] can't find DAPC_PD compatible node\n"); + return -1; + } + } + + return 0; +} + +#ifdef CONFIG_MTK_HIBERNATION +static int devapc_pm_restore_noirq(struct device *device) +{ + if (devapc_irq != 0) { + mt_irq_set_sens(devapc_irq, MT_LEVEL_SENSITIVE); + mt_irq_set_polarity(devapc_irq, MT_POLARITY_LOW); + } + + return 0; +} +#endif + +static void unmask_module_irq(unsigned int module) +{ + unsigned int apc_index = 0; + unsigned int apc_bit_index = 0; + + apc_index = module / (MOD_NO_IN_1_DEVAPC*2); + apc_bit_index = module % (MOD_NO_IN_1_DEVAPC*2); + + switch (apc_index) { + case 0: + *DEVAPC0_D0_VIO_MASK_0 &= ~(0x1 << apc_bit_index); + break; + case 1: + *DEVAPC0_D0_VIO_MASK_1 &= ~(0x1 << apc_bit_index); + break; + case 2: + *DEVAPC0_D0_VIO_MASK_2 &= ~(0x1 << apc_bit_index); + break; + case 3: + *DEVAPC0_D0_VIO_MASK_3 &= ~(0x1 << apc_bit_index); + break; + case 4: + *DEVAPC0_D0_VIO_MASK_4 &= ~(0x1 << apc_bit_index); + break; + case 5: + *DEVAPC0_D0_VIO_MASK_5 &= ~(0x1 << apc_bit_index); + break; + default: + pr_err("[DEVAPC] unmask_module_irq: check if domain master setting is correct or not!\n"); + break; + } +} + +static void start_devapc(void) +{ + unsigned int i; + + mt_reg_sync_writel(readl(DEVAPC0_PD_APC_CON) & (0xFFFFFFFF ^ (1 << 2)), DEVAPC0_PD_APC_CON); + + /* SMC call is called in LK instead */ + + for (i = 0; i < (ARRAY_SIZE(devapc_devices)); i++) { + if (true == devapc_devices[i].enable_vio_irq) + unmask_module_irq(i); + } + + pr_err("[DEVAPC] start_devapc: Current VIO_STA 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x, 4:0x%x, 5:0x%x\n", + readl(DEVAPC0_D0_VIO_STA_0), readl(DEVAPC0_D0_VIO_STA_1), + readl(DEVAPC0_D0_VIO_STA_2), readl(DEVAPC0_D0_VIO_STA_3), + readl(DEVAPC0_D0_VIO_STA_4), readl(DEVAPC0_D0_VIO_STA_5)); + + pr_err("[DEVAPC] start_devapc: Current VIO_MASK 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x, 4:0x%x, 5:0x%x\n", + readl(DEVAPC0_D0_VIO_MASK_0), readl(DEVAPC0_D0_VIO_MASK_1), + readl(DEVAPC0_D0_VIO_MASK_2), readl(DEVAPC0_D0_VIO_MASK_3), + readl(DEVAPC0_D0_VIO_MASK_4), readl(DEVAPC0_D0_VIO_MASK_5)); +} + +static int clear_vio_status(unsigned int module) +{ + + unsigned int apc_index = 0; + unsigned int apc_bit_index = 0; + + apc_index = module / (MOD_NO_IN_1_DEVAPC * 2); + apc_bit_index = module % (MOD_NO_IN_1_DEVAPC * 2); + + switch (apc_index) { + case 0: + *DEVAPC0_D0_VIO_STA_0 = (0x1 << apc_bit_index); + break; + case 1: + *DEVAPC0_D0_VIO_STA_1 = (0x1 << apc_bit_index); + break; + case 2: + *DEVAPC0_D0_VIO_STA_2 = (0x1 << apc_bit_index); + break; + case 3: + *DEVAPC0_D0_VIO_STA_3 = (0x1 << apc_bit_index); + break; + case 4: + *DEVAPC0_D0_VIO_STA_4 = (0x1 << apc_bit_index); + break; + case 5: + *DEVAPC0_D0_VIO_STA_5 = (0x1 << apc_bit_index); + break; + default: + break; + } + + return 0; +} + +static int check_vio_status(unsigned int module) +{ + unsigned int apc_index = 0; + unsigned int apc_bit_index = 0; + unsigned int vio_status = 0; + + apc_index = module / (MOD_NO_IN_1_DEVAPC * 2); + apc_bit_index = module % (MOD_NO_IN_1_DEVAPC * 2); + + switch (apc_index) { + case 0: + vio_status = (*DEVAPC0_D0_VIO_STA_0 & (0x1 << apc_bit_index)); + break; + case 1: + vio_status = (*DEVAPC0_D0_VIO_STA_1 & (0x1 << apc_bit_index)); + break; + case 2: + vio_status = (*DEVAPC0_D0_VIO_STA_2 & (0x1 << apc_bit_index)); + break; + case 3: + vio_status = (*DEVAPC0_D0_VIO_STA_3 & (0x1 << apc_bit_index)); + break; + case 4: + vio_status = (*DEVAPC0_D0_VIO_STA_4 & (0x1 << apc_bit_index)); + break; + case 5: + vio_status = (*DEVAPC0_D0_VIO_STA_5 & (0x1 << apc_bit_index)); + break; + default: + break; + } + + if (vio_status) + return 1; + + return 0; +} + +#if defined(CONFIG_MTK_AEE_FEATURE) && defined(DEVAPC_ENABLE_AEE) +static void evaluate_aee_warning(unsigned int i, unsigned int dbg1) +{ + char aee_str[256]; + unsigned long long current_time; + + if (devapc_vio_aee_shown[i] == 0) { + if (devapc_vio_count[i] < DEVAPC_VIO_AEE_TRIGGER_TIMES) { + devapc_vio_count[i]++; + + if (devapc_vio_count[i] == 1) { + /* violation for this slave is triggered the first time */ + + /* get current time from start-up in ns */ + devapc_vio_first_trigger_time[i] = sched_clock(); +#if 0 + DEVAPC_VIO_MSG("[DEVAPC] devapc_vio_first_trigger_time: %llu\n", + devapc_vio_first_trigger_time[i] / 1000000); /* ms */ +#endif + } + } + + if (devapc_vio_count[i] >= DEVAPC_VIO_AEE_TRIGGER_TIMES) { + current_time = sched_clock(); /* get current time from start-up in ns */ +#if 0 + DEVAPC_VIO_MSG("[DEVAPC] current_time: %llu\n", + current_time / 1000000); /* ms */ + DEVAPC_VIO_MSG("[DEVAPC] devapc_vio_count[%d]: %d\n", + i, devapc_vio_count[i]); +#endif + if (((current_time - devapc_vio_first_trigger_time[i]) / 1000000) <= + (unsigned long long)DEVAPC_VIO_AEE_TRIGGER_FREQUENCY) { /* diff time by ms */ + /* Mark the flag for showing AEE (AEE should be shown only once) */ + devapc_vio_aee_shown[i] = 1; + + DEVAPC_VIO_MSG("[DEVAPC] Populating AEE Warning...\n"); + + if (devapc_vio_current_aee_trigger_times < + DEVAPC_VIO_MAX_TOTAL_MODULE_AEE_TRIGGER_TIMES) { + devapc_vio_current_aee_trigger_times++; + + sprintf(aee_str, "[DEVAPC] Access Violation Slave: %s (index=%d)\n", + devapc_devices[i].device, i); + + aee_kernel_warning(aee_str, + "%s\nAccess Violation Slave: %s\nVio Addr: 0x%x\n%s%s\n", + "Device APC Violation", + devapc_devices[i].device, + dbg1, + "CRDISPATCH_KEY:Device APC Violation Issue/", + devapc_devices[i].device + ); + } + } + + devapc_vio_count[i] = 0; + } + } +} +#endif + +static irqreturn_t devapc_violation_irq(int irq, void *dev_id) +{ + unsigned int dbg0 = 0, dbg1 = 0; + unsigned int master_id; + unsigned int domain_id; + unsigned int r_w_violation; + unsigned int device_count; + unsigned int i; + struct pt_regs *regs; + + dbg0 = readl(DEVAPC0_VIO_DBG0); + dbg1 = readl(DEVAPC0_VIO_DBG1); + master_id = (dbg0 & VIO_DBG_MSTID) >> 0; + domain_id = (dbg0 & VIO_DBG_DMNID) >> 13; + r_w_violation = (dbg0 & VIO_DBG_W) >> 28; + + /* violation information improvement */ + if (1 == r_w_violation) { + DEVAPC_VIO_MSG + ("[DEVAPC] Violation(W) - Process:%s, PID:%i, Vio Addr:0x%x, Bus ID:0x%x, Dom ID:0x%x, DBG0:0x%x\n", + current->comm, current->pid, dbg1, master_id, domain_id, (*DEVAPC0_VIO_DBG0)); + } else { + DEVAPC_VIO_MSG + ("[DEVAPC] Violation(R) - Process:%s, PID:%i, Vio Addr:0x%x, Bus ID:0x%x, Dom ID:0x%x, DBG0:0x%x\n", + current->comm, current->pid, dbg1, master_id, domain_id, (*DEVAPC0_VIO_DBG0)); + } + + DEVAPC_VIO_MSG("[DEVAPC] VIO_STA 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x, 4:0x%x, 5:0x%x\n", + readl(DEVAPC0_D0_VIO_STA_0), readl(DEVAPC0_D0_VIO_STA_1), + readl(DEVAPC0_D0_VIO_STA_2), readl(DEVAPC0_D0_VIO_STA_3), + readl(DEVAPC0_D0_VIO_STA_4), readl(DEVAPC0_D0_VIO_STA_5)); + + device_count = (sizeof(devapc_devices) / sizeof(devapc_devices[0])); + + /* checking and showing violation EMI & EMI MPU slaves */ + if (check_vio_status(INDEX_EMI)) + DEVAPC_VIO_MSG("[DEVAPC] Access Violation Slave: EMI (index=%d)\n", INDEX_EMI); + + if (check_vio_status(INDEX_EMI_MPU)) + DEVAPC_VIO_MSG("[DEVAPC] Access Violation Slave: EMI_MPU (index=%d)\n", INDEX_EMI_MPU); + + /* checking and showing violation normal slaves */ + for (i = 0; i < device_count; i++) { + /* violation information improvement */ + + if ((check_vio_status(i)) && (devapc_devices[i].enable_vio_irq == true)) { + DEVAPC_VIO_MSG("[DEVAPC] Access Violation Slave: %s (index=%d)\n", + devapc_devices[i].device, i); + +#if defined(CONFIG_MTK_AEE_FEATURE) && defined(DEVAPC_ENABLE_AEE) + /* Frequency-based Violation AEE Warning (Under the condition that the violation + * for the module is not shown, it will trigger the AEE if "x" violations in "y" ms) */ + evaluate_aee_warning(i, dbg1); +#endif + } + + clear_vio_status(i); + } + + if ((DEVAPC_ENABLE_ONE_CORE_VIOLATION_DEBUG) || (enable_dynamic_one_core_violation_debug)) { + DEVAPC_VIO_MSG("[DEVAPC] ====== Start dumping Device APC violation tracing ======\n"); + + DEVAPC_VIO_MSG("[DEVAPC] **************** [All IRQ Registers] ****************\n"); + regs = get_irq_regs(); + show_regs(regs); + + DEVAPC_VIO_MSG("[DEVAPC] **************** [All Current Task Stack] ****************\n"); + show_stack(current, NULL); + + DEVAPC_VIO_MSG("[DEVAPC] ====== End of dumping Device APC violation tracing ======\n"); + } + + mt_reg_sync_writel(VIO_DBG_CLR, DEVAPC0_VIO_DBG0); + dbg0 = readl(DEVAPC0_VIO_DBG0); + dbg1 = readl(DEVAPC0_VIO_DBG1); + + if ((dbg0 != 0) || (dbg1 != 0)) { + DEVAPC_VIO_MSG("[DEVAPC] Multi-violation!\n"); + DEVAPC_VIO_MSG("[DEVAPC] DBG0 = %x, DBG1 = %x\n", dbg0, dbg1); + } + + return IRQ_HANDLED; +} + +static int devapc_probe(struct platform_device *dev) +{ + int ret; + + DEVAPC_MSG("[DEVAPC] module probe.\n"); + + /*IO remap */ + devapc_ioremap(); + + /*Temporarily disable Device APC kernel driver for bring-up */ + /* + * Interrupts of vilation (including SPC in SMI, or EMI MPU) are triggered by the device APC. + * need to share the interrupt with the SPC driver. + */ + ret = request_irq(devapc_irq, (irq_handler_t) devapc_violation_irq, + IRQF_TRIGGER_LOW | IRQF_SHARED, "devapc", &g_devapc_ctrl); + if (ret) { + pr_err("[DEVAPC] Failed to request irq! (%d)\n", ret); + return ret; + } + +#ifdef CONFIG_MTK_CLKMGR +/* mt_clkmgr */ + enable_clock(MT_CG_INFRA_DEVAPC, "DEVAPC"); +#else +/* CCF */ +#if 0 +/* bypass clock! */ + dapc_clk = devm_clk_get(&dev->dev, "devapc-main"); + if (IS_ERR(dapc_clk)) { + pr_err("[DEVAPC] cannot get dapc clock.\n"); + return PTR_ERR(dapc_clk); + } + clk_prepare_enable(dapc_clk); +#endif + +#endif + +#ifdef CONFIG_MTK_HIBERNATION + register_swsusp_restore_noirq_func(ID_M_DEVAPC, devapc_pm_restore_noirq, NULL); +#endif + + start_devapc(); + + return 0; +} + +static int devapc_remove(struct platform_device *dev) +{ + return 0; +} + +static int devapc_suspend(struct platform_device *dev, pm_message_t state) +{ + return 0; +} + +static int devapc_resume(struct platform_device *dev) +{ + DEVAPC_MSG("[DEVAPC] module resume.\n"); + + return 0; +} + +static int check_debug_input_type(const char *str) +{ + if (sysfs_streq(str, "1")) + return DAPC_INPUT_TYPE_DEBUG_ON; + else if (sysfs_streq(str, "0")) + return DAPC_INPUT_TYPE_DEBUG_OFF; + else + return 0; +} + +static ssize_t devapc_dbg_write(struct file *file, const char __user *buffer, size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + int input_type; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) + return -EFAULT; + + desc[len] = '\0'; + + input_type = check_debug_input_type(desc); + if (!input_type) + return -EFAULT; + + if (input_type == DAPC_INPUT_TYPE_DEBUG_ON) { + enable_dynamic_one_core_violation_debug = 1; + pr_err("[DEVAPC] One-Core Debugging: Enabled\n"); + } else if (input_type == DAPC_INPUT_TYPE_DEBUG_OFF) { + enable_dynamic_one_core_violation_debug = 0; + pr_err("[DEVAPC] One-Core Debugging: Disabled\n"); + } + + return count; +} + +static int devapc_dbg_open(struct inode *inode, struct file *file) +{ + return 0; +} + +struct platform_device devapc_device = { + .name = "devapc", + .id = -1, +}; + +static const struct file_operations devapc_dbg_fops = { + .owner = THIS_MODULE, + .open = devapc_dbg_open, + .write = devapc_dbg_write, + .read = NULL, +}; + +static struct platform_driver devapc_driver = { + .probe = devapc_probe, + .remove = devapc_remove, + .suspend = devapc_suspend, + .resume = devapc_resume, + .driver = { + .name = "devapc", + .owner = THIS_MODULE, + }, +}; + +/* + * devapc_init: module init function. + */ +static int __init devapc_init(void) +{ + int ret; + + DEVAPC_MSG("[DEVAPC] module init.\n"); + + ret = platform_device_register(&devapc_device); + if (ret) { + pr_err("[DEVAPC] Unable to do device register(%d)\n", ret); + return ret; + } + + ret = platform_driver_register(&devapc_driver); + if (ret) { + pr_err("[DEVAPC] Unable to register driver (%d)\n", ret); + platform_device_unregister(&devapc_device); + return ret; + } + + g_devapc_ctrl = cdev_alloc(); + if (!g_devapc_ctrl) { + pr_err("[DEVAPC] Failed to add devapc device! (%d)\n", ret); + platform_driver_unregister(&devapc_driver); + platform_device_unregister(&devapc_device); + return ret; + } + g_devapc_ctrl->owner = THIS_MODULE; + + proc_create("devapc_dbg", (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH), NULL, + &devapc_dbg_fops); + + return 0; +} + +/* + * devapc_exit: module exit function. + */ +static void __exit devapc_exit(void) +{ + DEVAPC_MSG("[DEVAPC] DEVAPC module exit\n"); +#ifdef CONFIG_MTK_HIBERNATION + unregister_swsusp_restore_noirq_func(ID_M_DEVAPC); +#endif +} + +late_initcall(devapc_init); +module_exit(devapc_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/devapc/mt6755/devapc.h b/drivers/misc/mediatek/devapc/mt6755/devapc.h new file mode 100644 index 0000000000000000000000000000000000000000..8fba3469a0104f5edc3348610a0d34eb40018657 --- /dev/null +++ b/drivers/misc/mediatek/devapc/mt6755/devapc.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _DAPC_H +#define _DAPC_H +#include +#define MOD_NO_IN_1_DEVAPC 16 +#define DEVAPC_TAG "DEVAPC" + +/* 1: Force to enable enhanced one-core violation debugging + * 0: Enhanced one-core violation debugging can be enabled dynamically + * Notice: You should only use one core to debug + * (Please note it may trigger PRINTK too much) */ +#define DEVAPC_ENABLE_ONE_CORE_VIOLATION_DEBUG 0 + +/* Uncomment to enable AEE */ +/* #define DEVAPC_ENABLE_AEE */ + +#if defined(CONFIG_MTK_AEE_FEATURE) && defined(DEVAPC_ENABLE_AEE) + +/* This is necessary for AEE */ +#define DEVAPC_TOTAL_SLAVES 157 + +/* AEE trigger threshold for each module. + * Remember: NEVER set it to 1 + */ +#define DEVAPC_VIO_AEE_TRIGGER_TIMES 10 + +/* AEE trigger frequency for each module (ms) */ +#define DEVAPC_VIO_AEE_TRIGGER_FREQUENCY 1000 + +/* Maximum populating AEE times for all the modules */ +#define DEVAPC_VIO_MAX_TOTAL_MODULE_AEE_TRIGGER_TIMES 3 + +#endif + +/*For EMI API(DRAM violation) DEVAPC0_D0_VIO_STA_5, idx:164*/ +#define ABORT_EMI 0x00000010 +#define INDEX_EMI 164 + +/*For EMI_MPU(APB violation) API DEVAPC0_D0_VIO_STA_5, idx:166*/ +#define ABORT_EMI_MPU 0x00000040 +#define INDEX_EMI_MPU 166 + +#define DAPC_INPUT_TYPE_DEBUG_ON 200 +#define DAPC_INPUT_TYPE_DEBUG_OFF 100 + +/*Define constants*/ + +#define VIO_DBG_MSTID 0x00001FFF +#define VIO_DBG_DMNID 0x0001E000 +#define VIO_DBG_W 0x10000000 +#define VIO_DBG_CLR 0x80000000 + +/****************************************************************************** +*REGISTER ADDRESS DEFINATION +******************************************************************************/ + +/* Device APC PD */ +#define DEVAPC0_PD_APC_CON ((unsigned int *)(devapc_pd_base+0x0F00)) + +#define DEVAPC0_D0_VIO_MASK_0 ((unsigned int *)(devapc_pd_base+0x0000)) +#define DEVAPC0_D0_VIO_MASK_1 ((unsigned int *)(devapc_pd_base+0x0004)) +#define DEVAPC0_D0_VIO_MASK_2 ((unsigned int *)(devapc_pd_base+0x0008)) +#define DEVAPC0_D0_VIO_MASK_3 ((unsigned int *)(devapc_pd_base+0x000C)) +#define DEVAPC0_D0_VIO_MASK_4 ((unsigned int *)(devapc_pd_base+0x0010)) +#define DEVAPC0_D0_VIO_MASK_5 ((unsigned int *)(devapc_pd_base+0x0014)) + + +#define DEVAPC0_D0_VIO_STA_0 ((unsigned int *)(devapc_pd_base+0x0400)) +#define DEVAPC0_D0_VIO_STA_1 ((unsigned int *)(devapc_pd_base+0x0404)) +#define DEVAPC0_D0_VIO_STA_2 ((unsigned int *)(devapc_pd_base+0x0408)) +#define DEVAPC0_D0_VIO_STA_3 ((unsigned int *)(devapc_pd_base+0x040C)) +#define DEVAPC0_D0_VIO_STA_4 ((unsigned int *)(devapc_pd_base+0x0410)) +#define DEVAPC0_D0_VIO_STA_5 ((unsigned int *)(devapc_pd_base+0x0414)) + + +#define DEVAPC0_VIO_DBG0 ((unsigned int *)(devapc_pd_base+0x0900)) +#define DEVAPC0_VIO_DBG1 ((unsigned int *)(devapc_pd_base+0x0904)) +#define DEVAPC0_DEC_ERR_CON ((unsigned int *)(devapc_pd_base+0x0F80)) +#define DEVAPC0_DEC_ERR_ADDR ((unsigned int *)(devapc_pd_base+0x0F84)) +#define DEVAPC0_DEC_ERR_ID ((unsigned int *)(devapc_pd_base+0x0F88)) + +struct DEVICE_INFO { + const char *device; + bool enable_vio_irq; +}; + +#ifdef CONFIG_MTK_HIBERNATION +extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); +extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity); +#endif + +#endif + diff --git a/drivers/misc/mediatek/dramc/mt6755/Makefile b/drivers/misc/mediatek/dramc/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..fa509176234b56fbb79c4f955de1adf64869b185 --- /dev/null +++ b/drivers/misc/mediatek/dramc/mt6755/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/ + +obj-$(CONFIG_MTK_DRAMC) := mt_dramc.o +ccflags-$(CONFIG_MTK_DRAMC) += -DDEBUG diff --git a/drivers/misc/mediatek/dramc/mt6755/mt_dramc.c b/drivers/misc/mediatek/dramc/mt6755/mt_dramc.c new file mode 100644 index 0000000000000000000000000000000000000000..4d78ef526dff2231a6105d6a7066a5002941f58f --- /dev/null +++ b/drivers/misc/mediatek/dramc/mt6755/mt_dramc.c @@ -0,0 +1,1478 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mt_dramc.h" + +void __iomem *DRAMCAO_BASE_ADDR; +void __iomem *DDRPHY_BASE_ADDR; +void __iomem *DRAMCNAO_BASE_ADDR; +void __iomem *TOPCKGEN_BASE_ADDR; + +volatile unsigned int dst_dummy_read_addr[2]; +volatile unsigned int src_dummy_read_addr[2]; +int get_addr_done = 0; +volatile unsigned char *dst_array_v; +volatile unsigned char *src_array_v; +volatile unsigned int dst_array_p; +volatile unsigned int src_array_p; +int init_done = 0; +static char dfs_dummy_buffer[BUFF_LEN] __aligned(PAGE_SIZE); +static DEFINE_MUTEX(dram_dfs_mutex); +int org_dram_data_rate = 0; +static unsigned int enter_pdp_cnt; +/*extern bool spm_vcorefs_is_dvfs_in_porgress(void);*/ +#define Reg_Sync_Writel(addr, val) writel(val, IOMEM(addr)) +#define Reg_Readl(addr) readl(IOMEM(addr)) + + +const struct dram_info *g_dram_info_dummy_read = NULL; + +static int __init dt_scan_dram_info(unsigned long node, const char *uname, int depth, void *data) +{ + char *type = (char *)of_get_flat_dt_prop(node, "device_type", NULL); + const __be32 *reg, *endp; + unsigned long l; + + /* We are scanning "memory" nodes only */ + if (type == NULL) { + /* + * The longtrail doesn't have a device_type on the + * /memory node, so look for the node called /memory@0. + */ + if (depth != 1 || strcmp(uname, "memory@0") != 0) + return 0; + } else if (strcmp(type, "memory") != 0) + return 0; + + reg = (const __be32 *)of_get_flat_dt_prop(node, (const char *)"reg", (int *)&l); + if (reg == NULL) + return 0; + + endp = reg + (l / sizeof(__be32)); + if (node) { + /* orig_dram_info */ + g_dram_info_dummy_read = (const struct dram_info *)of_get_flat_dt_prop(node, "orig_dram_info", NULL); + } + + pr_debug("[DRAMC] dram info dram rank number = %d\n", g_dram_info_dummy_read->rank_num); + pr_debug("[DRAMC] dram info dram rank0 base = 0x%llx\n", g_dram_info_dummy_read->rank_info[0].start); + pr_debug("[DRAMC] dram info dram rank1 base = 0x%llx\n", + g_dram_info_dummy_read->rank_info[0].start + g_dram_info_dummy_read->rank_info[0].size); + + return node; +} + +static int check_dramc_base_addr(void) +{ + if ((!DRAMCAO_BASE_ADDR) || (!DDRPHY_BASE_ADDR) || (!DRAMCNAO_BASE_ADDR)) + return -1; + else + return 0; +} + +void *mt_dramc_base_get(void) +{ + return DRAMCAO_BASE_ADDR; +} +EXPORT_SYMBOL(mt_dramc_base_get); + +void *mt_dramc_nao_base_get(void) +{ + return DRAMCNAO_BASE_ADDR; +} +EXPORT_SYMBOL(mt_dramc_nao_base_get); + +void *mt_ddrphy_base_get(void) +{ + return DDRPHY_BASE_ADDR; +} +EXPORT_SYMBOL(mt_ddrphy_base_get); + +unsigned int support_4GB_mode(void) +{ + int ret = 0; + phys_addr_t max_dram_size = get_max_DRAM_size(); + + if (max_dram_size >= 0x100000000ULL) /*dram size = 4GB*/ + ret = 1; + + return ret; +} + +#ifdef DRAM_HQA +void dram_HQA_adjust_voltage(void) +{ +#ifdef HVcore1 /*Vcore1=1.10V, Vdram=1.30V, Vio18=1.8*/ + pmic_config_interface(MT6351_BUCK_VCORE_CON4, Vcore1_HV, 0x7F, 0); + pmic_config_interface(MT6351_BUCK_VCORE_CON5, Vcore1_HV, 0x7F, 0); + pmic_config_interface(MT6351_VDRAM_ANA_CON0, Vdram_HV, 0x7F, 0); + pr_err("[HQA]Set HVcore1 setting: Vcore1=1.10V(SW_Ctrl=0x%x, HW_Ctrl=0x%x, should be 0x%x), Vdram=1.30V(0x%x, should be 0x%x)\n", + upmu_get_reg_value(MT6351_BUCK_VCORE_CON4), upmu_get_reg_value(MT6351_BUCK_VCORE_CON5), + Vcore1_HV, upmu_get_reg_value(MT6351_VDRAM_ANA_CON0), Vdram_HV); +#endif + +#ifdef NV /*Vcore1=1.00V, Vdram=1.22V, Vio18=1.8*/ + pmic_config_interface(MT6351_BUCK_VCORE_CON4, Vcore1_NV, 0x7F, 0); + pmic_config_interface(MT6351_BUCK_VCORE_CON5, Vcore1_NV, 0x7F, 0); + pmic_config_interface(MT6351_VDRAM_ANA_CON0, Vdram_NV, 0x7F, 0); + pr_err("[HQA]Set NV setting: Vcore1=1.00V(SW_Ctrl=0x%x, HW_Ctrl=0x%x, should be 0x%x), Vdram=1.22V(0x%x, should be 0x%x)\n", + upmu_get_reg_value(MT6351_BUCK_VCORE_CON4), upmu_get_reg_value(MT6351_BUCK_VCORE_CON5), + Vcore1_NV, upmu_get_reg_value(MT6351_VDRAM_ANA_CON0), Vdram_NV); +#endif + +#ifdef LVcore1 /*Vcore1=0.90V, Vdram=1.16V, Vio18=1.8*/ + pmic_config_interface(MT6351_BUCK_VCORE_CON4, Vcore1_LV, 0x7F, 0); + pmic_config_interface(MT6351_BUCK_VCORE_CON5, Vcore1_LV, 0x7F, 0); + pmic_config_interface(MT6351_VDRAM_ANA_CON0, Vdram_LV, 0x7F, 0); + pr_err("[HQA]Set LVcore1 setting: Vcore1=0.90V(SW_Ctrl=0x%x, HW_Ctrl=0x%x, should be 0x%x), Vdram=1.16V(0x%x, should be 0x%x)\n", + upmu_get_reg_value(MT6351_BUCK_VCORE_CON4), upmu_get_reg_value(MT6351_BUCK_VCORE_CON5), + Vcore1_LV, upmu_get_reg_value(MT6351_VDRAM_ANA_CON0), Vdram_LV); +#endif + +#ifdef HVcore1_LVdram /*Vcore1=1.10V, Vdram=1.16V, Vio18=1.8*/ + pmic_config_interface(MT6351_BUCK_VCORE_CON4, Vcore1_HV, 0x7F, 0); + pmic_config_interface(MT6351_BUCK_VCORE_CON5, Vcore1_HV, 0x7F, 0); + pmic_config_interface(MT6351_VDRAM_ANA_CON0, Vdram_LV, 0x7F, 0); + pr_err("[HQA]Set HVcore1_LVdram setting: Vcore1=1.10V(SW_Ctrl=0x%x, HW_Ctrl=0x%x, should be 0x%x), Vdram=1.16V(0x%x, should be 0x%x)\n", + upmu_get_reg_value(MT6351_BUCK_VCORE_CON4), upmu_get_reg_value(MT6351_BUCK_VCORE_CON5), + Vcore1_HV, upmu_get_reg_value(MT6351_VDRAM_ANA_CON0), Vdram_LV); +#endif + +#ifdef LVcore1_HVdram /*Vcore1=0.90V, Vdram=1.30V, Vio18=1.8*/ + pmic_config_interface(MT6351_BUCK_VCORE_CON4, Vcore1_LV, 0x7F, 0); + pmic_config_interface(MT6351_BUCK_VCORE_CON5, Vcore1_LV, 0x7F, 0); + pmic_config_interface(MT6351_VDRAM_ANA_CON0, Vdram_HV, 0x7F, 0); + pr_err("[HQA]Set LVcore1_HVdram setting: Vcore1=0.90V(SW_Ctrl=0x%x, HW_Ctrl=0x%x, should be 0x%x), Vdram=1.30V(0x%x, should be 0x%x)\n", + upmu_get_reg_value(MT6351_BUCK_VCORE_CON4), upmu_get_reg_value(MT6351_BUCK_VCORE_CON5), + Vcore1_LV, upmu_get_reg_value(MT6351_VDRAM_ANA_CON0), Vdram_HV); +#endif +} +#endif + +void spm_dpd_init(void) +{ + /* backup mr4, zqcs config for future restore*/ + unsigned int recover7_0; + unsigned int recover8; + unsigned int recover; + + recover7_0 = readl(PDEF_DRAMC0_REG_1E4) & 0x00ff0000; + recover8 = readl(PDEF_DRAMC0_REG_1DC) & 0x00000001; + recover = recover7_0 | recover8; + + spm_set_register(SPM_PASR_DPD_0, recover); + + /*-----try, disable MR4(0x1E8[26]=1)*/ + writel(readl(PDEF_DRAMC0_REG_1E8) | 0x04000000, PDEF_DRAMC0_REG_1E8); + + /*Set ZQCSCNT7~0(0x1e4[23:16]) = 0: disable ZQCS*/ + /*When doing ZQCS, special_command_enable will wakeup RANK1's CKE. This is wrong.*/ + writel(readl(PDEF_DRAMC0_REG_1E4) & 0xff00ffff, PDEF_DRAMC0_REG_1E4); + + /*20150402 add, ZQCSCNT8 is added in Jade*/ + /* set R_DMZQCSCNT8(0x1DC[0])=0*/ + writel(readl(PDEF_DRAMC0_REG_1DC) & 0xfffffffe, PDEF_DRAMC0_REG_1DC); + /* + *MDM_TM_WAIT_US = 2; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(2); + + /*20150319 add, set MIOCKCTRLOFF(0x1dc[26])=1: not stop to DRAM clock!*/ + writel(readl(PDEF_DRAMC0_REG_1DC) | 0x04000000, PDEF_DRAMC0_REG_1DC); + + /*20150319 add, wait 100ns*/ + /* + *MDM_TM_WAIT_US = 1; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(1); + + /*Set CKE2RANK(0x1ec[20])=0: let CKE1 and CKE0 independent*/ + writel(readl(PDEF_DRAMC0_REG_1EC) & 0xffefffff, PDEF_DRAMC0_REG_1EC); + + /*20150319 add, set R_DMCKE1FIXON(0xF4[20])=1*/ + writel(readl(PDEF_DRAMC0_REG_0F4) | 0x00100000, PDEF_DRAMC0_REG_0F4); + + /*SW set RK1SRF(0x110[21])=0: RK1 can not enter SRF*/ + writel(readl(PDEF_DRAMC0_REG_110) & 0xffdfffff, PDEF_DRAMC0_REG_110); + + /*Set DISDMOEDIS(0x1ec[16])=1: CA can not be floating because RK1 want to DPD after RK0 enter SRF.*/ + writel(readl(PDEF_DRAMC0_REG_1EC) | 0x00010000, PDEF_DRAMC0_REG_1EC); + +} + +void spm_dpd_dram_init(void) /*void spm_dpd_dram_init_1(void)*/ +{ + unsigned int recover7_0; + unsigned int recover8; + + /*20150319 add, recover, set R_DMCKE1FIXOFF(0xF4[21])=0*/ + writel(readl(PDEF_DRAMC0_REG_0F4) & 0xffdfffff, PDEF_DRAMC0_REG_0F4); + + /* DPD DRAM initialization first part - Exit PDP*/ + + /*SW set RK1DPDX(0x110[31])=1*/ + writel(readl(PDEF_DRAMC0_REG_110) | 0x80000000, PDEF_DRAMC0_REG_110); + + /*20150325 */ + /*wait100ns*/ + /* + *MDM_TM_WAIT_US = 1; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(1); + + /*SW set RK1SRF(0x110[21])=1*/ + writel(readl(PDEF_DRAMC0_REG_110) | 0x00200000, PDEF_DRAMC0_REG_110); + + /* 5. wait 220us*/ + /*SW delay 220us*/ + /* + *MDM_TM_WAIT_US = 220; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(220); + + /* 6.execute spm_dpd_init_2()*/ + + /*fix CKE, R_DMCKEFIXON*/ + writel(readl(PDEF_DRAMC0_REG_0E4) | 0x00000004, PDEF_DRAMC0_REG_0E4); + + /*move here*/ + /*SW recover CKE2RANK(0x1EC[20]) -> CKE1 is the same as CKE0*/ + writel(readl(PDEF_DRAMC0_REG_1EC) | 0x00100000, PDEF_DRAMC0_REG_1EC); + + /*20150325 add*/ + /*set R_DMCKE1FIXON(0xF4[20])=1*/ + writel(readl(PDEF_DRAMC0_REG_0F4) | 0x00100000, PDEF_DRAMC0_REG_0F4); + + /*set R_DMPREALL_OPTION(0x138[15])=0*/ + writel(readl(PDEF_DRAMC0_REG_138) & 0xffff7fff, PDEF_DRAMC0_REG_138); + + /*set R_DMDCMEN2(0x1DC[1])=0*/ + writel(readl(PDEF_DRAMC0_REG_1DC) & 0xfffffffd, PDEF_DRAMC0_REG_1DC); + + /*Set MRS value - for rank1, Reset(0x3F)*/ + writel(0x1000003f, PDEF_DRAMC0_REG_088); + /*Set MRWEN=1 (0x1E4[0]) -> Mode register write command enable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) | 0x00000001, PDEF_DRAMC0_REG_1E4); + /*SW delay 10us*/ + /* + *MDM_TM_WAIT_US = 10; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(10); + /*Set MRWEN=0 (0x1E4[0]) -> Mode register write command disable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) & 0xfffffffe, PDEF_DRAMC0_REG_1E4); + + /*Set MRS value - for rank1, Calibration command after initialization (0x0A)*/ + writel(0x10ff000a, PDEF_DRAMC0_REG_088); + /*Set MRWEN=1 (0x1E4[0]) -> Mode register write command enable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) | 0x00000001, PDEF_DRAMC0_REG_1E4); + /*SW delay 1.2us*/ + /* + *MDM_TM_WAIT_US = 1; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(2); + + /*Set MRWEN=0 (0x1E4[0]) -> Mode register write command disable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) & 0xfffffffe, PDEF_DRAMC0_REG_1E4); + + /*Set MRS value - for rank1, I/O Config-1(0x03) - 40-Ohm typical pull-down/pull-up*/ + writel(0x10010003, PDEF_DRAMC0_REG_088); + /*Set MRWEN=1 (0x1E4[0]) -> Mode register write command enable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) | 0x00000001, PDEF_DRAMC0_REG_1E4); + /*SW delay 1.2us*/ + /* + *MDM_TM_WAIT_US = 1; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(2); + + /*Set MRWEN=0 (0x1E4[0]) -> Mode register write command disable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) & 0xfffffffe, PDEF_DRAMC0_REG_1E4); + + /*Set MRS value - for rank1, Device Feature1(0x01) - BL=8, nWR=8*/ + writel(0x10830001, PDEF_DRAMC0_REG_088); + /*Set MRWEN=1 (0x1E4[0]) -> Mode register write command enable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) | 0x00000001, PDEF_DRAMC0_REG_1E4); + /*SW delay 1.2us*/ + /* + *MDM_TM_WAIT_US = 1; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(2); + + /*Set MRWEN=0 (0x1E4[0]) -> Mode register write command disable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) & 0xfffffffe, PDEF_DRAMC0_REG_1E4); + + /*Set MRS value - for rank1, Device Feature 2(0x02) - RL=12 / WL=9 (<= 800 MHz)*/ + writel(0x101c0002, PDEF_DRAMC0_REG_088); + /*Set MRWEN=1 (0x1E4[0]) -> Mode register write command enable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) | 0x00000001, PDEF_DRAMC0_REG_1E4); + /*SW delay 1.2us*/ + /* + *MDM_TM_WAIT_US = 1; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(2); + + /*Set MRWEN=0 (0x1E4[0]) -> Mode register write command disable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) & 0xfffffffe, PDEF_DRAMC0_REG_1E4); + + /*Set MRS value - for rank1, Device Feature11(0x0b) - disable ODT*/ + writel(0x1000000b, PDEF_DRAMC0_REG_088); + /*Set MRWEN=1 (0x1E4[0]) -> Mode register write command enable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) | 0x00000001, PDEF_DRAMC0_REG_1E4); + /*SW delay 1.2us*/ + /* + *MDM_TM_WAIT_US = 1; + while (*MDM_TM_WAIT_US > 0) + ; + */ + mb(); + udelay(2); + + /*Set MRWEN=0 (0x1E4[0]) -> Mode register write command disable*/ + writel(readl(PDEF_DRAMC0_REG_1E4) & 0xfffffffe, PDEF_DRAMC0_REG_1E4); + + /*20150325 add*/ + /* set R_DMDCMEN2(0x1DC[1])=1*/ + writel(readl(PDEF_DRAMC0_REG_1DC) | 0x00000002, PDEF_DRAMC0_REG_1DC); + + /* set R_DMPREALL_OPTION(0x138[15])=1*/ /*recover*/ + writel(readl(PDEF_DRAMC0_REG_138) | 0x00008000, PDEF_DRAMC0_REG_138); + + /* set R_DMCKE1FIXON(0xF4[20])=0*/ + writel(readl(PDEF_DRAMC0_REG_0F4) & 0xffefffff, PDEF_DRAMC0_REG_0F4); + + /*SW set RK1DPDX(0x110[31])=0*/ + writel(readl(PDEF_DRAMC0_REG_110) & 0x7fffffff, PDEF_DRAMC0_REG_110); + + /*release fix CKE*/ + writel(readl(PDEF_DRAMC0_REG_0E4) & 0xfffffffb, PDEF_DRAMC0_REG_0E4); + + recover7_0 = spm_get_register(SPM_PASR_DPD_0) & 0x00ff0000; + recover8 = spm_get_register(SPM_PASR_DPD_0) & 0x00000001; + + /*SW recover ZQCSCNT7~0(0x1E4[23:16]) to allow ZQCS*/ + writel(readl(PDEF_DRAMC0_REG_1DC) | recover8, PDEF_DRAMC0_REG_1DC); + /*20150402 add, ZQCSCNT8 is added in Jade*/ + /* set R_DMZQCSCNT8(0x1DC[0])=? */ /*recover the original value*/ + writel(readl(PDEF_DRAMC0_REG_1E4) | recover7_0, PDEF_DRAMC0_REG_1E4); + + /*-----try, release disable MR4(0x1E8[26]=0)*/ + writel(readl(PDEF_DRAMC0_REG_1E8) & 0xfbffffff, PDEF_DRAMC0_REG_1E8); + + /*Recover MRSRK(0x88[28])=0, MRRRK(0x88[26])=0*/ + writel(0x00000000, PDEF_DRAMC0_REG_088); +} + +int enter_pasr_dpd_config(unsigned char segment_rank0, + unsigned char segment_rank1) +{ + /* for D-3, support run time MRW */ + unsigned int rank_pasr_segment[2]; + unsigned int dramc0_spcmd, dramc0_pd_ctrl, dramc0_pd_ctrl_2, dramc0_padctl4, dramc0_1E8; + unsigned int i, cnt = 1000; + + rank_pasr_segment[0] = segment_rank0 & 0xFF; /* for rank0 */ + rank_pasr_segment[1] = segment_rank1 & 0xFF; /* for rank1 */ + pr_warn("[DRAMC0] PASR r0 = 0x%x r1 = 0x%x\n", rank_pasr_segment[0], rank_pasr_segment[1]); + + /* backup original data */ + dramc0_spcmd = readl(PDEF_DRAMC0_REG_1E4); + dramc0_pd_ctrl = readl(PDEF_DRAMC0_REG_1DC); + dramc0_padctl4 = readl(PDEF_DRAMC0_REG_0E4); + dramc0_1E8 = readl(PDEF_DRAMC0_REG_1E8); + + /* disable MR4(0x1E8[26]=1) */ + writel(dramc0_1E8 | 0x04000000, PDEF_DRAMC0_REG_1E8); + + /* Set ZQCSCNT7~0(0x1e4[23:16]) = 0 ZQCSCNT8(0x1DC[0]) = 0: disable ZQCS */ + writel(dramc0_spcmd & 0xff00ffff, PDEF_DRAMC0_REG_1E4); + writel(dramc0_pd_ctrl & 0xfffffffe, PDEF_DRAMC0_REG_1DC); + + /* Set MIOCKCTRLOFF(0x1dc[26])=1: not stop to DRAM clock! */ + dramc0_pd_ctrl_2 = readl(PDEF_DRAMC0_REG_1DC); + writel(dramc0_pd_ctrl_2 | 0x04000000, PDEF_DRAMC0_REG_1DC); + + /* fix CKE */ + writel(dramc0_padctl4 | 0x00000004, PDEF_DRAMC0_REG_0E4); + + udelay(1); + + for (i = 0; i < 2; i++) { + + if ((i == 1) && (rank_pasr_segment[i] == 0xFF)) + continue; + + /* set MRS settings include rank number, segment information and MRR17 */ + writel(((i << 28) | (rank_pasr_segment[i] << 16) | 0x00000011), PDEF_DRAMC0_REG_088); + /* Mode register write command enable */ + writel(0x00000001, PDEF_DRAMC0_REG_1E4); + + /* wait MRW command response */ + /* wait >1us */ + /* gpt_busy_wait_us(1); */ + do { + if (cnt-- == 0) { + pr_warn("[DRAMC0] PASR MRW fail!\n"); + return -1; + } + udelay(1); + } while ((readl(PDEF_DRAMC0_REG_3B8) & 0x00000001) == 0x0); + mb(); + + /* Mode register write command disable */ + writel(0x0, PDEF_DRAMC0_REG_1E4); + } + + /* release MR4 */ + writel(dramc0_1E8, PDEF_DRAMC0_REG_1E8); + + /* release fix CKE */ + writel(dramc0_padctl4, PDEF_DRAMC0_REG_0E4); + + /* recover Set MIOCKCTRLOFF(0x1dc[26]) */ + /* Set MIOCKCTRLOFF(0x1DC[26])=0: stop to DRAM clock */ + writel(dramc0_pd_ctrl, PDEF_DRAMC0_REG_1DC); + + /* writel(0x00000004, PDEF_DRAMC0_REG_088); */ + pr_warn("[DRAMC0] PASR offset 0x88 = 0x%x\n", readl(PDEF_DRAMC0_REG_088)); + writel(dramc0_spcmd, PDEF_DRAMC0_REG_1E4); + + if (segment_rank1 == 0xFF) { /*all segments of rank1 are not reserved -> rank1 enter DPD*/ + enter_pdp_cnt++; + spm_dpd_init(); + } + + return 0; + + /*slp_pasr_en(1, segment_rank0 | (segment_rank1 << 8));*/ +} + +int exit_pasr_dpd_config(void) +{ + int ret; + unsigned char rk1 = 0; + + /*slp_dpd_en(0);*/ + /*slp_pasr_en(0, 0);*/ + if (enter_pdp_cnt == 1) { + enter_pdp_cnt--; + spm_dpd_dram_init(); + rk1 = 0xFF; + } + + ret = enter_pasr_dpd_config(0, rk1); + + return ret; +} + +#define MEM_TEST_SIZE 0x2000 +#define PATTERN1 0x5A5A5A5A +#define PATTERN2 0xA5A5A5A5 +int Binning_DRAM_complex_mem_test(void) +{ + unsigned char *MEM8_BASE; + unsigned short *MEM16_BASE; + unsigned int *MEM32_BASE; + unsigned int *MEM_BASE; + unsigned long mem_ptr; + unsigned char pattern8; + unsigned short pattern16; + unsigned int i, j, size, pattern32; + unsigned int value; + unsigned int len = MEM_TEST_SIZE; + void *ptr; + int ret = 1; + + ptr = vmalloc(MEM_TEST_SIZE); + + if (!ptr) { + /*pr_err("fail to vmalloc\n");*/ + /*ASSERT(0);*/ + ret = -24; + goto fail; + } + + MEM8_BASE = (unsigned char *)ptr; + MEM16_BASE = (unsigned short *)ptr; + MEM32_BASE = (unsigned int *)ptr; + MEM_BASE = (unsigned int *)ptr; + /*pr_warn("Test DRAM start address 0x%lx\n", (unsigned long)ptr);*/ + pr_warn("Test DRAM start address %p\n", ptr); + pr_warn("Test DRAM SIZE 0x%x\n", MEM_TEST_SIZE); + size = len >> 2; + + /* === Verify the tied bits (tied high) === */ + for (i = 0; i < size; i++) + MEM32_BASE[i] = 0; + + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0) { + vfree(ptr); + /* return -1; */ + ret = -1; + goto fail; + } else + MEM32_BASE[i] = 0xffffffff; + } + + /* === Verify the tied bits (tied low) === */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0xffffffff) { + vfree(ptr); + /* return -2; */ + ret = -2; + goto fail; + } else + MEM32_BASE[i] = 0x00; + } + + /* === Verify pattern 1 (0x00~0xff) === */ + pattern8 = 0x00; + for (i = 0; i < len; i++) + MEM8_BASE[i] = pattern8++; + pattern8 = 0x00; + for (i = 0; i < len; i++) { + if (MEM8_BASE[i] != pattern8++) { + vfree(ptr); + /* return -3; */ + ret = -3; + goto fail; + } + } + + /* === Verify pattern 2 (0x00~0xff) === */ + pattern8 = 0x00; + for (i = j = 0; i < len; i += 2, j++) { + if (MEM8_BASE[i] == pattern8) + MEM16_BASE[j] = pattern8; + if (MEM16_BASE[j] != pattern8) { + vfree(ptr); + /* return -4; */ + ret = -4; + goto fail; + } + pattern8 += 2; + } + + /* === Verify pattern 3 (0x00~0xffff) === */ + pattern16 = 0x00; + for (i = 0; i < (len >> 1); i++) + MEM16_BASE[i] = pattern16++; + pattern16 = 0x00; + for (i = 0; i < (len >> 1); i++) { + if (MEM16_BASE[i] != pattern16++) { + vfree(ptr); + /* return -5; */ + ret = -5; + goto fail; + } + } + + /* === Verify pattern 4 (0x00~0xffffffff) === */ + pattern32 = 0x00; + for (i = 0; i < (len >> 2); i++) + MEM32_BASE[i] = pattern32++; + pattern32 = 0x00; + for (i = 0; i < (len >> 2); i++) { + if (MEM32_BASE[i] != pattern32++) { + vfree(ptr); + /* return -6; */ + ret = -6; + goto fail; + } + } + + /* === Pattern 5: Filling memory range with 0x44332211 === */ + for (i = 0; i < size; i++) + MEM32_BASE[i] = 0x44332211; + + /* === Read Check then Fill Memory with a5a5a5a5 Pattern === */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0x44332211) { + vfree(ptr); + /* return -7; */ + ret = -7; + goto fail; + } else { + MEM32_BASE[i] = 0xa5a5a5a5; + } + } + + /* === Read Check then Fill Memory with 00 Byte Pattern at offset 0h === */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0xa5a5a5a5) { + vfree(ptr); + /* return -8; */ + ret = -8; + goto fail; + } else { + MEM8_BASE[i * 4] = 0x00; + } + } + + /* === Read Check then Fill Memory with 00 Byte Pattern at offset 2h === */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0xa5a5a500) { + vfree(ptr); + /* return -9; */ + ret = -9; + goto fail; + } else { + MEM8_BASE[i * 4 + 2] = 0x00; + } + } + + /* === Read Check then Fill Memory with 00 Byte Pattern at offset 1h === */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0xa500a500) { + vfree(ptr); + /* return -10; */ + ret = -10; + goto fail; + } else { + MEM8_BASE[i * 4 + 1] = 0x00; + } + } + + /* === Read Check then Fill Memory with 00 Byte Pattern at offset 3h === */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0xa5000000) { + vfree(ptr); + /* return -11; */ + ret = -11; + goto fail; + } else { + MEM8_BASE[i * 4 + 3] = 0x00; + } + } + + /* === Read Check then Fill Memory with ffff Word Pattern at offset 1h == */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0x00000000) { + vfree(ptr); + /* return -12; */ + ret = -12; + goto fail; + } else { + MEM16_BASE[i * 2 + 1] = 0xffff; + } + } + + /* === Read Check then Fill Memory with ffff Word Pattern at offset 0h == */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0xffff0000) { + vfree(ptr); + /* return -13; */ + ret = -13; + goto fail; + } else { + MEM16_BASE[i * 2] = 0xffff; + } + } + /*=== Read Check === */ + for (i = 0; i < size; i++) { + if (MEM32_BASE[i] != 0xffffffff) { + vfree(ptr); + /* return -14; */ + ret = -14; + goto fail; + } + } + + /************************************************ + * Additional verification + ************************************************/ + /* === stage 1 => write 0 === */ + + for (i = 0; i < size; i++) + MEM_BASE[i] = PATTERN1; + + /* === stage 2 => read 0, write 0xF === */ + for (i = 0; i < size; i++) { + value = MEM_BASE[i]; + + if (value != PATTERN1) { + vfree(ptr); + /* return -15; */ + ret = -15; + goto fail; + } + MEM_BASE[i] = PATTERN2; + } + + /* === stage 3 => read 0xF, write 0 === */ + for (i = 0; i < size; i++) { + value = MEM_BASE[i]; + if (value != PATTERN2) { + vfree(ptr); + /* return -16; */ + ret = -16; + goto fail; + } + MEM_BASE[i] = PATTERN1; + } + + /* === stage 4 => read 0, write 0xF === */ + for (i = 0; i < size; i++) { + value = MEM_BASE[i]; + if (value != PATTERN1) { + vfree(ptr); + /* return -17; */ + ret = -17; + goto fail; + } + MEM_BASE[i] = PATTERN2; + } + + /* === stage 5 => read 0xF, write 0 === */ + for (i = 0; i < size; i++) { + value = MEM_BASE[i]; + if (value != PATTERN2) { + vfree(ptr); + /* return -18; */ + ret = -18; + goto fail; + } + MEM_BASE[i] = PATTERN1; + } + + /* === stage 6 => read 0 === */ + for (i = 0; i < size; i++) { + value = MEM_BASE[i]; + if (value != PATTERN1) { + vfree(ptr); + /* return -19; */ + ret = -19; + goto fail; + } + } + + /* === 1/2/4-byte combination test === */ + mem_ptr = (unsigned long)MEM_BASE; + while (mem_ptr < ((unsigned long)MEM_BASE + (size << 2))) { + *((unsigned char *)mem_ptr) = 0x78; + mem_ptr += 1; + *((unsigned char *)mem_ptr) = 0x56; + mem_ptr += 1; + *((unsigned short *)mem_ptr) = 0x1234; + mem_ptr += 2; + *((unsigned int *)mem_ptr) = 0x12345678; + mem_ptr += 4; + *((unsigned short *)mem_ptr) = 0x5678; + mem_ptr += 2; + *((unsigned char *)mem_ptr) = 0x34; + mem_ptr += 1; + *((unsigned char *)mem_ptr) = 0x12; + mem_ptr += 1; + *((unsigned int *)mem_ptr) = 0x12345678; + mem_ptr += 4; + *((unsigned char *)mem_ptr) = 0x78; + mem_ptr += 1; + *((unsigned char *)mem_ptr) = 0x56; + mem_ptr += 1; + *((unsigned short *)mem_ptr) = 0x1234; + mem_ptr += 2; + *((unsigned int *)mem_ptr) = 0x12345678; + mem_ptr += 4; + *((unsigned short *)mem_ptr) = 0x5678; + mem_ptr += 2; + *((unsigned char *)mem_ptr) = 0x34; + mem_ptr += 1; + *((unsigned char *)mem_ptr) = 0x12; + mem_ptr += 1; + *((unsigned int *)mem_ptr) = 0x12345678; + mem_ptr += 4; + } + for (i = 0; i < size; i++) { + value = MEM_BASE[i]; + if (value != 0x12345678) { + vfree(ptr); + /* return -20; */ + ret = -20; + goto fail; + } + } + + /* === Verify pattern 1 (0x00~0xff) === */ + pattern8 = 0x00; + MEM8_BASE[0] = pattern8; + for (i = 0; i < size * 4; i++) { + unsigned char waddr8, raddr8; + + waddr8 = i + 1; + raddr8 = i; + if (i < size * 4 - 1) + MEM8_BASE[waddr8] = pattern8 + 1; + if (MEM8_BASE[raddr8] != pattern8) { + vfree(ptr); + /* return -21; */ + ret = -21; + goto fail; + } + pattern8++; + } + + /* === Verify pattern 2 (0x00~0xffff) === */ + pattern16 = 0x00; + MEM16_BASE[0] = pattern16; + for (i = 0; i < size * 2; i++) { + if (i < size * 2 - 1) + MEM16_BASE[i + 1] = pattern16 + 1; + if (MEM16_BASE[i] != pattern16) { + vfree(ptr); + /* return -22; */ + ret = -22; + goto fail; + } + pattern16++; + } + /* === Verify pattern 3 (0x00~0xffffffff) === */ + pattern32 = 0x00; + MEM32_BASE[0] = pattern32; + for (i = 0; i < size; i++) { + if (i < size - 1) + MEM32_BASE[i + 1] = pattern32 + 1; + if (MEM32_BASE[i] != pattern32) { + vfree(ptr); + /* return -23; */ + ret = -23; + goto fail; + } + pattern32++; + } + pr_warn("complex R/W mem test pass\n"); + +fail: + vfree(ptr); + return ret; +} + +unsigned int ucDram_Register_Read(unsigned int u4reg_addr) +{ + unsigned int pu4reg_value; + + if (check_dramc_base_addr() == -1) { + pr_err("[DRAMC] Access-R DRAMC base address is NULL!!!\n"); + /* ASSERT(0); */ /* need porting*/ + } + + pu4reg_value = (readl(IOMEM(DRAMCAO_BASE_ADDR + u4reg_addr)) | + readl(IOMEM(DDRPHY_BASE_ADDR + u4reg_addr)) | + readl(IOMEM(DRAMCNAO_BASE_ADDR + u4reg_addr))); + + return pu4reg_value; +} + +void ucDram_Register_Write(unsigned int u4reg_addr, unsigned int u4reg_value) +{ + if (check_dramc_base_addr() == -1) { + pr_err("[DRAMC] Access-W DRAMC base address is NULL!!!\n"); + /* ASSERT(0); */ /* need porting*/ + } + + writel(u4reg_value, IOMEM(DRAMCAO_BASE_ADDR + u4reg_addr)); + writel(u4reg_value, IOMEM(DDRPHY_BASE_ADDR + u4reg_addr)); + writel(u4reg_value, IOMEM(DRAMCNAO_BASE_ADDR + u4reg_addr)); + mb(); +} + +bool pasr_is_valid(void) +{ + return true; +} + +/*------------------------------------------------------------------------- +** Round_Operation + * Round operation of A/B + * @param A + * @param B + * @retval round(A/B) + * +-------------------------------------------------------------------------*/ +unsigned int Round_Operation(unsigned int A, unsigned int B) +{ + unsigned int temp; + + if (B == 0) + return 0xffffffff; + + temp = A/B; + if ((A - temp*B) >= ((temp + 1)*B - A)) + return temp+1; + else + return temp; +} + + +unsigned int get_dram_data_rate_from_reg(void) +{ + unsigned int u4value1; + unsigned int MEMPLL_N_INFO, MEMPLL_DIV; + unsigned int MEMPLLx_FBDIV, MEMPLLx_M4PDIV; + unsigned int onepll_fout, threepll_fout; + + u4value1 = ucDram_Register_Read(0x600); + MEMPLL_N_INFO = (u4value1 & 0x7fffffff) >> 0; + + u4value1 = ucDram_Register_Read(0x610); + MEMPLL_DIV = (u4value1 & 0x00fe0000) >> 17; + + u4value1 = ucDram_Register_Read(0x62C); + MEMPLLx_FBDIV = (u4value1 & 0x007f0000) >> 16; + + u4value1 = ucDram_Register_Read(0x630); + MEMPLLx_M4PDIV = (u4value1 & 0x30000000) >> 28; + + if (MEMPLLx_M4PDIV == 0) + MEMPLLx_M4PDIV = 2; + else if (MEMPLLx_M4PDIV == 1) + MEMPLLx_M4PDIV = 4; + else if (MEMPLLx_M4PDIV == 2) + MEMPLLx_M4PDIV = 8; + + onepll_fout = ((26*(MEMPLL_N_INFO>>24))+(26*(MEMPLL_N_INFO&0x00ffffff)>>24))/4; + threepll_fout = (onepll_fout*4*MEMPLLx_M4PDIV*(MEMPLLx_FBDIV+1))/MEMPLL_DIV; + + if ((onepll_fout < (DUAL_FREQ_LOW + DATA_RATE_THRESHOLD)) && + (onepll_fout > (DUAL_FREQ_LOW - DATA_RATE_THRESHOLD))) + onepll_fout = DUAL_FREQ_LOW; + + /* for threepll calculation result would not be exactly 1800, but we should return exactly 1800 to DVFS driver*/ + if ((threepll_fout < (DUAL_FREQ_HIGH + DATA_RATE_THRESHOLD)) && + (threepll_fout > (DUAL_FREQ_HIGH - DATA_RATE_THRESHOLD))) + threepll_fout = DUAL_FREQ_HIGH; + + /*pr_err("[DRAMC] onepll_fout=%d, threepll_fout=%d\n", onepll_fout, threepll_fout);*/ + u4value1 = (readl(_CLK_CFG_0_SET) >> 8) & 0x00000003; + + if (u4value1 == 1) + return threepll_fout; + else + return onepll_fout; +} + +unsigned int get_dram_data_rate(void) +{ + unsigned int SPM_ACTIVE = 0; + unsigned int MEMPLL_FOUT = 0; + + /*6755 TBD*/ + /*SPM_ACTIVE = spm_vcorefs_is_dvfs_in_porgress()*/ + while (SPM_ACTIVE == 1) + ; + MEMPLL_FOUT = get_dram_data_rate_from_reg() << 1; + return MEMPLL_FOUT; +} + +#if 0 +unsigned int DRAM_MRR(int MRR_num) +{ + unsigned int MRR_value = 0x0; + unsigned int u4value; + + /* set DQ bit 0, 1, 2, 3, 4, 5, 6, 7 pinmux for LPDDR3*/ + /*ucDram_Register_Write(DRAMC_REG_RRRATE_CTL, 0x13121110); + ucDram_Register_Write(DRAMC_REG_MRR_CTL, 0x17161514);*/ + ucDram_Register_Write(DRAMC_REG_RRRATE_CTL, 0x15111012); + ucDram_Register_Write(DRAMC_REG_MRR_CTL, 0x16231314); + + ucDram_Register_Write(DRAMC_REG_MRS, MRR_num); + ucDram_Register_Write(DRAMC_REG_SPCMD, 0x00000002); + udelay(1); + ucDram_Register_Write(DRAMC_REG_SPCMD, 0x00000000); + udelay(1); + + u4value = ucDram_Register_Read(DRAMC_REG_SPCMDRESP); + MRR_value = (u4value >> 20) & 0xFF; + + return MRR_value; +} + + +unsigned int read_dram_temperature(void) +{ + unsigned int value; + + value = DRAM_MRR(4) & 0x7; + return value; +} +#endif + +int get_ddr_type(void) +{ + unsigned int value; + int DRAM_TYPE = -1; +#if 0 + value = ucDram_Register_Read(DRAMC_LPDDR2); + if ((value >> 28) & 0x1) { /*check LPDDR2_EN*/ + DRAM_TYPE = TYPE_LPDDR2; + } + + value = ucDram_Register_Read(DRAMC_PADCTL4); + if ((value >> 7) & 0x1) { /*check DDR3_EN*/ + DRAM_TYPE = TYPE_PCDDR3; + } +#endif + /* Jade support LPDDR3 only*/ + value = ucDram_Register_Read(DRAMC_ACTIM1); + if ((value >> 28) & 0x1) { /*check LPDDR3_EN*/ + DRAM_TYPE = TYPE_LPDDR3; + } + + return DRAM_TYPE; + +} +int dram_steps_freq(unsigned int step) +{ + int freq; + + switch (step) { + case 0: + freq = 1664;/*freq = 1800;*/ + break; + case 1: + freq = 1300; + break; + default: + return -1; + } + return freq; +} + +/*dram_can_support_fh() : need revise after HQA , +and need to check if there a empty bit in dramc_reg (0xf4)*/ +int dram_can_support_fh(void) +{ + unsigned int value; + + /*need to check if there empty bit in reg(0xf4) */ + /*value = ucDram_Register_Read(0xf4);*/ + value = (0x1 << 15);/*this is a temp value*/ + /*pr_debug("dummy regs 0x%x\n", value); + pr_debug("check 0x%x\n",(0x1 <<15));*/ + + if (value & (0x1 << 15)) + return 1; + else + return 0; +} + +int dram_get_dummy_read_addr(void) +{ + +#if 1/* get addr by ori method */ + DFS_APDMA_early_init(); + src_dummy_read_addr[0] = src_array_p; + dst_dummy_read_addr[0] = dst_array_p; + src_dummy_read_addr[1] = 0; + dst_dummy_read_addr[1] = 0; +#else/*get addr by new method from dts tree ,which is generated by LK */ + + + + +#endif + return 1; + +} +int DFS_APDMA_early_init(void) +{ + phys_addr_t max_dram_size = get_max_DRAM_size(); + phys_addr_t dummy_read_center_address = 0; + + if (init_done == 0) { + if (max_dram_size == 0x100000000ULL)/*dram size = 4GB*/ + dummy_read_center_address = 0x80000000ULL; + else if (max_dram_size <= 0xC0000000)/*dram size <= 3GB*/ + dummy_read_center_address = DRAM_BASE+(max_dram_size >> 1); + else { + pr_err("[DRAMC] DRAM max size incorrect!!!\n"); + /*ASSERT(0);*/ + } + + src_array_p = (volatile unsigned int)(dummy_read_center_address - (BUFF_LEN >> 1)); + dst_array_p = __pa(dfs_dummy_buffer); + init_done = 1; + } + + return 1; +} +#if 0 +int DFS_APDMA_Init(void) +{ + writel(((~DMA_GSEC_EN_BIT)&readl(DMA_GSEC_EN)), DMA_GSEC_EN); + return 1; +} + +int DFS_APDMA_Enable(void) +{ +#ifdef APDMAREG_DUMP + int i; +#endif + + while (readl(DMA_START) & 0x1) + ; + writel(src_array_p, DMA_SRC); + writel(dst_array_p, DMA_DST); + writel(BUFF_LEN , DMA_LEN1); + writel(DMA_CON_BURST_8BEAT, DMA_CON); + +#ifdef APDMAREG_DUMP + pr_debug("src_p=0x%x, dst_p=0x%x, src_v=0x%x, dst_v=0x%x, len=%d\n", + src_array_p, dst_array_p, (unsigned int)src_array_v, (unsigned int)dst_array_v, BUFF_LEN); + for (i = 0; i < 0x60; i += 4) + pr_debug("[Before]addr:0x%x, value:%x\n", (unsigned int)(DMA_BASE+i), *((volatile int *)(DMA_BASE+i))); + +#ifdef APDMA_TEST + for (i = 0; i < BUFF_LEN/sizeof(unsigned int); i++) { + dst_array_v[i] = 0; + src_array_v[i] = i; + } +#endif +#endif + + mt_reg_sync_writel(0x1 , DMA_START); + +#ifdef APDMAREG_DUMP + for (i = 0; i < 0x60; i += 4) + pr_debug("[AFTER]addr:0x%x, value:%x\n", (unsigned int)(DMA_BASE+i), *((volatile int *)(DMA_BASE+i))); + +#ifdef APDMA_TEST + for (i = 0; i < BUFF_LEN/sizeof(unsigned int); i++) { + if (dst_array_v[i] != src_array_v[i]) { + pr_debug("DMA ERROR at Address %x\n ", (unsigned int)&dst_array_v[i]); + pr_debug("(i=%d, value=0x%x(should be 0x%x))", i, dst_array_v[i], src_array_v[i]); + ASSERT(0); + } + } + pr_debug("Channe0 DFS DMA TEST PASS\n"); +#endif +#endif + return 1; +} + +int DFS_APDMA_END(void) +{ + while (readl(DMA_START)) + ; + return 1; +} + + +void dma_dummy_read_for_vcorefs(int loops) +{ + int i, count; + unsigned long long start_time, end_time, duration; + + DFS_APDMA_early_init(); + enable_clock(MT_CG_INFRA_GCE, "CQDMA"); + for (i = 0; i < loops; i++) { + count = 0; + start_time = sched_clock(); + do { + DFS_APDMA_Enable(); + DFS_APDMA_END(); + end_time = sched_clock(); + duration = end_time - start_time; + count++; + } while (duration < 4000L); + /*pr_debug("[DMA_dummy_read[%d], duration=%lld, count = %d\n", duration, count);*/ + } + disable_clock(MT_CG_INFRA_GCE, "CQDMA"); +} + +#endif +static ssize_t complex_mem_test_show(struct device_driver *driver, char *buf) +{ + int ret; + ret = Binning_DRAM_complex_mem_test(); + if (ret > 0) + return snprintf(buf, PAGE_SIZE, "MEM Test all pass\n"); + else + return snprintf(buf, PAGE_SIZE, "MEM TEST failed %d\n", ret); +} + +static ssize_t complex_mem_test_store(struct device_driver *driver, const char *buf, size_t count) +{ + /*snprintf(buf, "do nothing\n");*/ + return count; +} +#if 0 +#ifdef APDMA_TEST +static ssize_t DFS_APDMA_TEST_show(struct device_driver *driver, char *buf) +{ + dma_dummy_read_for_vcorefs(7); + return snprintf(buf, PAGE_SIZE, "DFS APDMA Dummy Read Address 0x%x\n", (unsigned int)src_array_p); +} +static ssize_t DFS_APDMA_TEST_store(struct device_driver *driver, const char *buf, size_t count) +{ + return count; +} +#endif +#endif + +#if 0 +#ifdef READ_DRAM_TEMP_TEST +static ssize_t read_dram_temp_show(struct device_driver *driver, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "DRAM MR4 = 0x%x\n", read_dram_temperature()); +} +static ssize_t read_dram_temp_store(struct device_driver *driver, const char *buf, size_t count) +{ + return count; +} +#endif +#endif +static ssize_t read_dram_data_rate_show(struct device_driver *driver, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "DRAM data rate = %d\n", get_dram_data_rate()); +} + +static ssize_t read_dram_data_rate_store(struct device_driver *driver, const char *buf, size_t count) +{ + return count; +} + + +DRIVER_ATTR(emi_clk_mem_test, 0664, complex_mem_test_show, complex_mem_test_store); + +#if 0 +#ifdef APDMA_TEST +DRIVER_ATTR(dram_dummy_read_test, 0664, DFS_APDMA_TEST_show, DFS_APDMA_TEST_store); +#endif +#endif + +#ifdef READ_DRAM_TEMP_TEST +DRIVER_ATTR(read_dram_temp_test, 0664, read_dram_temp_show, read_dram_temp_store); +#endif + +DRIVER_ATTR(read_dram_data_rate, 0664, read_dram_data_rate_show, read_dram_data_rate_store); + +/*DRIVER_ATTR(dram_dfs, 0664, dram_dfs_show, dram_dfs_store);*/ + +static int dram_probe(struct platform_device *pdev) +{ + int ret = 0; + + pr_debug("[DRAMC0] module probe.\n"); + + return ret; +} + +static int dram_remove(struct platform_device *dev) +{ + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id dram_of_ids[] = { + {.compatible = "mediatek,dramc",}, + {} +}; +#endif + +static struct platform_driver dram_test_drv = { + .probe = dram_probe, + .remove = dram_remove, + .driver = { + .name = "emi_clk_test", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = dram_of_ids, +#endif + }, +}; + +static int dram_dt_init(void) +{ + int ret = 0; + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,dramc"); + if (node) { + DRAMCAO_BASE_ADDR = of_iomap(node, 0); + pr_warn("[DRAMC]get DRAMCAO_BASE_ADDR @ %p\n", DRAMCAO_BASE_ADDR); + } else { + pr_err("[DRAMC]can't find DRAMC0 compatible node\n"); + return -1; + } + + node = of_find_compatible_node(NULL, NULL, "mediatek,ddrphy"); + if (node) { + DDRPHY_BASE_ADDR = of_iomap(node, 0); + pr_warn("[DRAMC]get DDRPHY_BASE_ADDR @ %p\n", DDRPHY_BASE_ADDR); + } else { + pr_err("[DRAMC]can't find DDRPHY compatible node\n"); + return -1; + } + + node = of_find_compatible_node(NULL, NULL, "mediatek,dramc_nao"); + if (node) { + DRAMCNAO_BASE_ADDR = of_iomap(node, 0); + pr_warn("[DRAMC]get DRAMCNAO_BASE_ADDR @ %p\n", DRAMCNAO_BASE_ADDR); + } else { + pr_err("[DRAMC]can't find DRAMCNAO compatible node\n"); + return -1; + } + + node = of_find_compatible_node(NULL, NULL, "mediatek,topckgen"); + if (node) { + TOPCKGEN_BASE_ADDR = of_iomap(node, 0); + pr_warn("[DRAMC]get TOPCKGEN_BASE_ADDR @ %p\n", TOPCKGEN_BASE_ADDR); + } else { + pr_err("[DRAMC]can't find TOPCKGEN compatible node\n"); + return -1; + } + + if (of_scan_flat_dt(dt_scan_dram_info, NULL) > 0) { + pr_warn("[DRAMC]find dt_scan_dram_info\n"); + } else { + pr_err("[DRAMC]can't find dt_scan_dram_info\n"); + return -1; + } + + return ret; +} + +/* int __init dram_test_init(void) */ +static int __init dram_test_init(void) +{ + int ret = 0; + + ret = dram_dt_init(); + if (ret) { + pr_warn("[DRAMC] Device Tree Init Fail\n"); + return ret; + } + + ret = platform_driver_register(&dram_test_drv); + if (ret) { + pr_warn("fail to create dram_test platform driver\n"); + return ret; + } + + ret = driver_create_file(&dram_test_drv.driver, &driver_attr_emi_clk_mem_test); + if (ret) { + pr_warn("fail to create the emi_clk_mem_test sysfs files\n"); + return ret; + } + + /* get dummy read address once only*/ + dram_get_dummy_read_addr(); + +#if 0 +#ifdef APDMA_TEST + ret = driver_create_file(&dram_test_drv.driver, &driver_attr_dram_dummy_read_test); + if (ret) { + pr_warn("fail to create the DFS sysfs files\n"); + return ret; + } +#endif + +#ifdef READ_DRAM_TEMP_TEST + ret = driver_create_file(&dram_test_drv.driver, &driver_attr_read_dram_temp_test); + if (ret) { + pr_warn("fail to create the read dram temp sysfs files\n"); + return ret; + } +#endif +#endif + + ret = driver_create_file(&dram_test_drv.driver, &driver_attr_read_dram_data_rate); + if (ret) { + pr_warn("fail to create the read dram data rate sysfs files\n"); + return ret; + } + + org_dram_data_rate = get_dram_data_rate(); + pr_warn("[DRAMC Driver] Dram Data Rate = %d\n", org_dram_data_rate); + + if (dram_can_support_fh()) + pr_warn("[DRAMC Driver] dram can support Frequency Hopping\n"); + else + pr_warn("[DRAMC Driver] dram can not support Frequency Hopping\n"); + + return ret; +} + +static void __exit dram_test_exit(void) +{ + platform_driver_unregister(&dram_test_drv); +} + +postcore_initcall(dram_test_init); +module_exit(dram_test_exit); + +MODULE_DESCRIPTION("MediaTek DRAMC Driver v0.1"); diff --git a/drivers/misc/mediatek/dramc/mt6755/mt_dramc.h b/drivers/misc/mediatek/dramc/mt6755/mt_dramc.h new file mode 100644 index 0000000000000000000000000000000000000000..64929937e7c5f1cdc1e3d755f7080585b66450a9 --- /dev/null +++ b/drivers/misc/mediatek/dramc/mt6755/mt_dramc.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DRAMC_H__ +#define __DRAMC_H__ + +/*========================= +Registers define +=========================*/ +#define PDEF_DRAMC0_REG_088 IOMEM((DRAMCAO_BASE_ADDR + 0x0088)) +#define PDEF_DRAMC0_REG_0E4 IOMEM((DRAMCAO_BASE_ADDR + 0x00e4)) +#define PDEF_DRAMC0_REG_0F4 IOMEM((DRAMCAO_BASE_ADDR + 0x00f4)) +#define PDEF_DRAMC0_REG_110 IOMEM((DRAMCAO_BASE_ADDR + 0x0110)) +#define PDEF_DRAMC0_REG_138 IOMEM((DRAMCAO_BASE_ADDR + 0x0138)) +#define PDEF_DRAMC0_REG_1DC IOMEM((DRAMCAO_BASE_ADDR + 0x01dc)) +#define PDEF_DRAMC0_REG_1E4 IOMEM((DRAMCAO_BASE_ADDR + 0x01e4)) +#define PDEF_DRAMC0_REG_1E8 IOMEM((DRAMCAO_BASE_ADDR + 0x01e8)) +#define PDEF_DRAMC0_REG_1EC IOMEM((DRAMCAO_BASE_ADDR + 0x01ec)) +#define PDEF_DRAMC0_REG_3B8 IOMEM((DRAMCNAO_BASE_ADDR + 0x03B8)) +#define _CLK_CFG_0_SET IOMEM((TOPCKGEN_BASE_ADDR + 0x0040)) + +/*========================= +Define +=========================*/ +#define DUAL_FREQ_HIGH 832 +#define DUAL_FREQ_LOW 650 +#define DATA_RATE_THRESHOLD 15 +#define MPLL_CON0_OFFSET 0x280 +#define MPLL_CON1_OFFSET 0x284 +#define MEMPLL5_OFFSET 0x614 +#define DRAMC_ACTIM1 (0x1e8) +#define TB_DRAM_SPEED +#define DUAL_FREQ_DIFF_RLWL /* If defined, need to set MR2 in dramcinit.*/ +#define DMA_GDMA_LEN_MAX_MASK (0x000FFFFF) +#define DMA_GSEC_EN_BIT (0x00000001) +#define DMA_INT_EN_BIT (0x00000001) +#define DMA_INT_FLAG_CLR_BIT (0x00000000) +#define LPDDR3_MODE_REG_2_LOW 0x00140002 /*RL6 WL3.*/ +#define LPDDR2_MODE_REG_2_LOW 0x00040002 /*RL6 WL3.*/ + +#ifdef DDR_1866 +#define LPDDR3_MODE_REG_2 0x001C0002 +#else +#define LPDDR3_MODE_REG_2 0x001A0002 +#endif +#define LPDDR2_MODE_REG_2 0x00060002 + +#define DRAMC_REG_MRS 0x088 +#define DRAMC_REG_PADCTL4 0x0e4 +#define DRAMC_REG_LPDDR2_3 0x1e0 +#define DRAMC_REG_SPCMD 0x1e4 +#define DRAMC_REG_ACTIM1 0x1e8 +#define DRAMC_REG_RRRATE_CTL 0x1f4 +#define DRAMC_REG_MRR_CTL 0x1fc +#define DRAMC_REG_SPCMDRESP 0x3b8 +#define PATTERN1 0x5A5A5A5A +#define PATTERN2 0xA5A5A5A5 + +/*========================= +Sysfs config +=========================*/ +#define APDMA_TEST +/*#define READ_DRAM_TEMP_TEST*/ +/*#define APDMAREG_DUMP*/ +#define PHASE_NUMBER 3 +#define DRAM_BASE (0x40000000ULL) +#define BUFF_LEN 0x100 +#define IOREMAP_ALIGMENT 0x1000 +#define Delay_magic_num 0x295 +/*We use GPT to measurement how many clk pass in 100us*/ + +/*========================= +DRAM HQA Config +=========================*/ +/*#define DRAM_HQA*/ + +#ifdef DRAM_HQA +/*#define HVcore1*/ /*Vcore1=1.10, Vdram=1.3, Vio18=1.8*/ +/*#define NV*/ /*Vcore1=1.00, Vdram=1.22, Vio18=1.8*/ +/*#define LVcore1*/ /*Vcore1=0.90, Vdram=1.16, Vio18=1.8*/ +#define HVcore1_LVdram /*Vcore1=1.10, Vdram=1.16, Vio18=1.8*/ +/*#define LVcore1_HVdram*/ /*Vcore1=0.90, Vdram=1.3, Vio18=1.8*/ + +#define RG_VDRAM_VOSEL_1p2V (0x5 << 8) /*1.2V*/ +#define VDRAM_ANA_CON0_SUB40mV 0x4 +#define VDRAM_ANA_CON0_ADD20mV 0x1e +#define VDRAM_ANA_CON0_ADD100mV 0X16 + +#define Vdram_HV (RG_VDRAM_VOSEL_1p2V | VDRAM_ANA_CON0_ADD100mV) /*1.30V*/ +#define Vdram_NV (RG_VDRAM_VOSEL_1p2V | VDRAM_ANA_CON0_ADD20mV) /*1.22V*/ +#define Vdram_LV (RG_VDRAM_VOSEL_1p2V | VDRAM_ANA_CON0_SUB40mV) /*1.16V*/ + +#define Vcore1_HV 0x48 /*1.05V*/ +#define Vcore1_NV 0x40 /*1.00V*/ +#define Vcore1_LV 0x38 /*0.95V*/ + +#define Vio18_HV 0x28 /*1.9V*/ +#define Vio18_NV 0x20 /*1.8V*/ +#define Vio18_LV 0x18 /*1.7V*/ + +#endif + +/*========================= +DRAMC API config +=========================*/ +extern unsigned int DMA_TIMES_RECORDER; +extern phys_addr_t get_max_DRAM_size(void); +/*int DFS_APDMA_Enable(void);*/ +/*int DFS_APDMA_Init(void);*/ +int DFS_APDMA_early_init(void); +void dma_dummy_read_for_vcorefs(int loops); +/*void get_mempll_table_info(u32 *high_addr, u32 *low_addr, u32 *num);*/ +unsigned int get_dram_data_rate(void); +/*unsigned int read_dram_temperature(void);*/ +/*void sync_hw_gating_value(void);*/ +/*unsigned int is_one_pll_mode(void);*/ +int dram_steps_freq(unsigned int step); +int dram_can_support_fh(void); +void spm_dpd_init(void); +void spm_dpd_dram_init(void); +unsigned int support_4GB_mode(void); +extern void *mt_dramc_base_get(void); +extern void *mt_dramc_nao_base_get(void); +extern void *mt_ddrphy_base_get(void); +unsigned int ucDram_Register_Read(unsigned int u4reg_addr); +void ucDram_Register_Write(unsigned int u4reg_addr, unsigned int u4reg_value); +void dram_HQA_adjust_voltage(void); +int enter_pasr_dpd_config(unsigned char segment_rank0, unsigned char segment_rank1); +int exit_pasr_dpd_config(void); + +enum DDRTYPE { + TYPE_DDR1 = 1, + TYPE_LPDDR2, + TYPE_LPDDR3, + TYPE_PCDDR3 +}; + +/************************** Common Macro *********************/ +#define delay_a_while(count) \ + do { \ + register unsigned int delay; \ + asm volatile ("mov %0, %1\n\t"\ + "1:\n\t" \ + "subs %0, %0, #1\n\t" \ + "bne 1b\n\t" \ + : "+r" (delay) \ + : "r" (count) \ + : "cc"); \ + } while (0) + +#define mcDELAY_US(x) delay_a_while((U32) (x*1000*10)) + +#endif /*__WDT_HW_H__*/ diff --git a/drivers/misc/mediatek/dws/mt6580/KIICAA_POWER.dws b/drivers/misc/mediatek/dws/mt6580/KIICAA_POWER.dws new file mode 100644 index 0000000000000000000000000000000000000000..7c24164c6d3d8f49170319b75d4e1fcecd4bb674 Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6580/KIICAA_POWER.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/K6000_Plus.dws b/drivers/misc/mediatek/dws/mt6755/K6000_Plus.dws new file mode 100644 index 0000000000000000000000000000000000000000..51bb858f747f3dc1703beeabde11a1bdf8c027de Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/K6000_Plus.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/p382.dws b/drivers/misc/mediatek/dws/mt6755/p382.dws new file mode 100755 index 0000000000000000000000000000000000000000..2c8df147b3d5c694bc7ea3f0326d8e9412ecdac3 Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/p382.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/p383.dws b/drivers/misc/mediatek/dws/mt6755/p383.dws new file mode 100755 index 0000000000000000000000000000000000000000..2604354557550788fdb324ea6f4c9a3ea5b2018e Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/p383.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/p386.dws b/drivers/misc/mediatek/dws/mt6755/p386.dws new file mode 100755 index 0000000000000000000000000000000000000000..b4f4ffa7923d329e50bb2e9648897459175aa203 Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/p386.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/p389bf.dws b/drivers/misc/mediatek/dws/mt6755/p389bf.dws new file mode 100755 index 0000000000000000000000000000000000000000..75a8aa5f3e7ee67be23c48162d7dc057c6df659e Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/p389bf.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/vz6750_35_i_n.dws b/drivers/misc/mediatek/dws/mt6755/vz6750_35_i_n.dws new file mode 100644 index 0000000000000000000000000000000000000000..51bb858f747f3dc1703beeabde11a1bdf8c027de Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/vz6750_35_i_n.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/vz6750_35g_i_n.dws b/drivers/misc/mediatek/dws/mt6755/vz6750_35g_i_n.dws new file mode 100644 index 0000000000000000000000000000000000000000..51bb858f747f3dc1703beeabde11a1bdf8c027de Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/vz6750_35g_i_n.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/vz6750_36_i_n.dws b/drivers/misc/mediatek/dws/mt6755/vz6750_36_i_n.dws new file mode 100644 index 0000000000000000000000000000000000000000..51bb858f747f3dc1703beeabde11a1bdf8c027de Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/vz6750_36_i_n.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/vz6750_36g_i_n.dws b/drivers/misc/mediatek/dws/mt6755/vz6750_36g_i_n.dws new file mode 100644 index 0000000000000000000000000000000000000000..51bb858f747f3dc1703beeabde11a1bdf8c027de Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/vz6750_36g_i_n.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/vz6750_65_i_n.dws b/drivers/misc/mediatek/dws/mt6755/vz6750_65_i_n.dws new file mode 100755 index 0000000000000000000000000000000000000000..d30d24ce639654958db3b852b47eb0beac996bbb Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/vz6750_65_i_n.dws differ diff --git a/drivers/misc/mediatek/dws/mt6755/vz6750_66_i_n.dws b/drivers/misc/mediatek/dws/mt6755/vz6750_66_i_n.dws new file mode 100644 index 0000000000000000000000000000000000000000..51bb858f747f3dc1703beeabde11a1bdf8c027de Binary files /dev/null and b/drivers/misc/mediatek/dws/mt6755/vz6750_66_i_n.dws differ diff --git a/drivers/misc/mediatek/eccci/mt6755/Makefile b/drivers/misc/mediatek/eccci/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8e762dbe8ea6386fdc67e2f6d958ed0bf327a5c7 --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/Makefile @@ -0,0 +1,63 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ifeq ($(CONFIG_MTK_ECCCI_DRIVER), y) + +ccflags-y += -I$(srctree)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include +ifeq ($(CONFIG_MTK_PMIC_CHIP_MT6353), y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/pmic/ +endif +# security objects +MASP_CORE_DRIVER_DIR := $(srctree)/drivers/misc/mediatek/drivers/masp + +ifeq ($(CONFIG_MTK_SECURITY_SW_SUPPORT), y) +ifeq ($(CONFIG_CUSTOM_SEC_AUTH_SUPPORT), y) +clean-files += $(CCCI_CUSTOM_DRIVER_DIR)/cust_auth.o +else +clean-files += $(patsubst $(obj)/%,%,$(wildcard auth/*.o)) +endif +endif + +ifeq ($(CONFIG_MTK_SECURITY_SW_SUPPORT), y) +ifeq ($(CONFIG_CUSTOM_SEC_AUTH_SUPPORT), y) +CCCI_CUSTOM_DRIVER_DIR := $(MTK_PATH_CUSTOM)/$(call lc,$(MTK_PROJECT))/kernel/ccci +ccci_plat-y += $(CCCI_CUSTOM_DRIVER_DIR)/cust_auth.o +endif +endif + +ifeq ($(CONFIG_MTK_SECURITY_SW_SUPPORT), y) +ccflags-y += -DENABLE_MD_IMG_SECURITY_FEATURE +endif +ifeq ($(CONFIG_MTK_SEC_MODEM_NVRAM_ANTI_CLONE), y) +ccflags-y += -DMTK_SEC_MODEM_NVRAM_ANTI_CLONE +endif + +# CCCI objects +obj-$(CONFIG_MTK_ECCCI_DRIVER) := ccci.o + +# platform dependent parts +ccci-y := ccci_platform.o $(core_obj) $(mach_obj) $(sec_obj) +ifeq ($(CONFIG_MTK_ECCCI_CLDMA), y) +ccci-y += cldma_platform.o +endif +ifeq ($(CONFIG_MTK_ECCCI_C2K), y) +ccci-y += ccif_c2k_platform.o +endif + +else +obj- := dummy.o # avoid build error +endif diff --git a/drivers/misc/mediatek/eccci/mt6755/ccci_config.h b/drivers/misc/mediatek/eccci/mt6755/ccci_config.h new file mode 100644 index 0000000000000000000000000000000000000000..85daee73e6ebe038ebefb2c2fd1b8f2722390879 --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/ccci_config.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef ECCCI_INTERNAL_OPTION +#define ECCCI_INTERNAL_OPTION +/*================================================ */ +/*Bool option part*/ +/*================================================*/ +/*#define CCCI_STATISTIC*/ +#define FEATURE_GET_MD_GPIO_NUM +#define FEATURE_GET_MD_GPIO_VAL +#define FEATURE_GET_MD_ADC_NUM +#define FEATURE_GET_MD_ADC_VAL +#define FEATURE_GET_MD_EINT_ATTR +#if defined(FEATURE_GET_MD_EINT_ATTR) && !defined(CONFIG_MTK_LEGACY) +#define FEATURE_GET_MD_EINT_ATTR_DTS +#endif + +#define FEATURE_GET_MD_BAT_VOL +#define FEATURE_PM_IPO_H +/*#define FEATURE_DFO_EN*/ +#define FEATURE_SEQ_CHECK_EN +#define FEATURE_POLL_MD_EN + +#define FEATURE_SMART_LOGGING +#define FEATURE_MD1MD3_SHARE_MEM + +#if 0 /*DEPRECATED */ +#define FEATURE_GET_TD_EINT_NUM +#define FEATURE_GET_DRAM_TYPE_CLK +#endif + +#define ENABLE_DRAM_API +#define ENABLE_MEM_REMAP_HW +/*#define ENABLE_CHIP_VER_CHECK*/ +/*#define ENABLE_2G_3G_CHECK*/ +/*#define ENABLE_MD_WDT_DBG*/ +#define ENABLE_CLDMA_AP_SIDE +#define ENABLE_MD_POWER_OFF_CHECK + +#ifdef CONFIG_MTK_CONN_MD +#define FEATURE_CONN_MD_EXP_EN +#endif + +/*#define FEATURE_USING_4G_MEMORY_API*/ +/*#define FEATURE_LOW_BATTERY_SUPPORT disable for customer complaint*/ +#ifdef CONFIG_MTK_FPGA +#define FEATURE_FPGA_PORTING +#else +#define FEATURE_RF_CLK_BUF +#define ENABLE_32K_CLK_LESS +#define FEATURE_MD_GET_CLIB_TIME +#define FEATURE_C2K_ALWAYS_ON +#define FEATURE_DBM_SUPPORT + +#define ENABLE_EMI_PROTECTION +#ifdef ENABLE_EMI_PROTECTION +#define SET_EMI_STEP_BY_STAGE +/* #define SET_AP_MPU_REGION */ /*no need set ap region */ +#endif + +#endif +/* #define DISABLE_MD_WDT_PROCESS */ /* enable wdt after bringup */ +#define NO_POWER_OFF_ON_STARTMD +#define NO_START_ON_SUSPEND_RESUME +#define MD_UMOLY_EE_SUPPORT +#define TEST_MESSAGE_FOR_BRINGUP + +#define FEATURE_MTK_SWITCH_TX_POWER +#ifdef FEATURE_MTK_SWITCH_TX_POWER +#define SWTP_COMPATIBLE_DEVICE_ID "mediatek, swtp-eint" +#endif + +#define FEATURE_FORCE_ASSERT_CHECK_EN + +/*================================================ */ +/* misc size description */ +#define CCCI_SMEM_DUMP_SIZE 4096 /* smem size we dump when EE */ +#define CCCC_SMEM_CCIF_SRAM_SIZE 16 /* SRAM size we dump into smem */ +#define CCCI_SMEM_SLEEP_MODE_DBG_DUMP 512 /* only dump first 512bytes in sleep mode info */ +#define CCCI_SMEM_DBM_GUARD_SIZE 8 +#define CCCI_SMEM_DBM_SIZE 40 +#define CCCI_SMEM_SIZE_RUNTIME_AP 0x800 /* AP runtime data size */ +#define CCCI_SMEM_SIZE_RUNTIME_MD 0x800 /* MD runtime data size */ +/*================================================*/ +/* share memory region description */ +#define CCCI_SMEM_OFFSET_EXCEPTION 0 /* offset in whole share memory region */ +#define CCCI_SMEM_SIZE_EXCEPTION (64*1024) /* exception smem total size */ +/*== subset of exception region begains ==*/ +#define CCCI_SMEM_OFFSET_CCCI_DEBUG CCCI_SMEM_OFFSET_EXCEPTION /* MD CCCI debug info */ +#define CCCI_SMEM_SIZE_CCCI_DEBUG 2048 +#define CCCI_SMEM_OFFSET_MDSS_DEBUG (CCCI_SMEM_OFFSET_EXCEPTION+CCCI_SMEM_SIZE_CCCI_DEBUG) /* MD SS debug info */ +#define CCCI_SMEM_OFFSET_CCIF_SRAM (CCCI_SMEM_OFFSET_MDSS_DEBUG+1024-CCCC_SMEM_CCIF_SRAM_SIZE) +#define CCCI_SMEM_OFFSET_EPON (CCCI_SMEM_OFFSET_EXCEPTION+0xC64) +#define CCCI_SMEM_OFFSET_EPON_UMOLY (CCCI_SMEM_OFFSET_EXCEPTION+0x1830) +#define CCCI_SMEM_OFFSET_EPOF (CCCI_SMEM_OFFSET_EXCEPTION+8*1024+31*4) +#define CCCI_SMEM_OFFSET_SEQERR (CCCI_SMEM_OFFSET_EXCEPTION+0x34) +#define CCCI_SMEM_SIZE_MDSS_DEBUG_UMOLY 8192 /* MD SS debug info size for MD1 after UMOLY */ +#define CCCI_SMEM_SIZE_MDSS_DEBUG 2048 /* MD SS debug info size except MD1 */ +#define CCCI_SMEM_SIZE_SLEEP_MODE_DBG 1024 /* MD sleep mode debug info section in exception region tail */ +#define CCCI_SMEM_OFFSET_SLEEP_MODE_DBG (CCCI_SMEM_OFFSET_EXCEPTION+CCCI_SMEM_SIZE_EXCEPTION \ + -CCCI_SMEM_SIZE_SLEEP_MODE_DBG) + +#ifdef FEATURE_FORCE_ASSERT_CHECK_EN +/* MD CCCI force assert debug info */ +#define CCCI_SMEM_FORCE_ASSERT_SIZE 1024 +#define CCCI_SMEM_OFFSET_FORCE_ASSERT (CCCI_SMEM_OFFSET_EXCEPTION + CCCI_SMEM_SIZE_EXCEPTION \ + - CCCI_SMEM_FORCE_ASSERT_SIZE - CCCI_SMEM_SIZE_SLEEP_MODE_DBG) +#endif +#define CCCI_SMEM_OFFSET_DBM_DEBUG (CCCI_SMEM_OFFSET_EXCEPTION + CCCI_SMEM_SIZE_EXCEPTION \ + - CCCI_SMEM_DBM_SIZE - CCCI_SMEM_DBM_GUARD_SIZE*2) +/*== subset of exception region ends ==*/ +#define CCCI_SMEM_OFFSET_RUNTIME (CCCI_SMEM_OFFSET_EXCEPTION+CCCI_SMEM_SIZE_EXCEPTION) +#define CCCI_SMEM_SIZE_RUNTIME (CCCI_SMEM_SIZE_RUNTIME_AP+CCCI_SMEM_SIZE_RUNTIME_MD) + +#define CCCI_SMEM_OFFSET_SMART_LOGGING (CCCI_SMEM_OFFSET_RUNTIME+CCCI_SMEM_SIZE_RUNTIME) /*APM->MD1*/ +#define CCCI_SMEM_SIZE_SMART_LOGGING 0 /* variable, so it should be the last region for MD1 */ + +#define CCCI_SMEM_OFFSET_CCIF_SMEM (CCCI_SMEM_OFFSET_RUNTIME+CCCI_SMEM_SIZE_RUNTIME) /*AP<->MD3*/ +#define CCCI_SMEM_SIZE_CCIF_SMEM 0 /* variable, so it should be the last region for MD3 */ +/*================================================ */ + +/*================================================ */ +/*Configure value option part*/ +/*================================================*/ +#define AP_PLATFORM_INFO "MT6755E1" +#define CCCI_MTU (3584-128) +#define CCCI_NET_MTU (1500) +#define SKB_POOL_SIZE_4K (256) /*2*MD */ +#define SKB_POOL_SIZE_1_5K (256) /*2*MD */ +#define SKB_POOL_SIZE_16 (64) /*2*MD */ +#define BM_POOL_SIZE (SKB_POOL_SIZE_4K+SKB_POOL_SIZE_1_5K+SKB_POOL_SIZE_16) +#define RELOAD_TH 3 /*reload pool if pool size dropped below 1/RELOAD_TH */ +#define MD_HEADER_VER_NO (3) +#define MEM_LAY_OUT_VER (1) +#define AP_MD_HS_V2 2 /*handshake version*/ + +#define CCCI_MEM_ALIGN (SZ_32M) +#define CCCI_SMEM_ALIGN_MD1 (0x200000) /*2M */ +#define CCCI_SMEM_ALIGN_MD2 (0x200000) /*2M */ + +#define CURR_SEC_CCCI_SYNC_VER (1) /*Note: must sync with sec lib, if ccci and sec has dependency change */ +#define CCCI_DRIVER_VER 0x20110118 + +#define IPC_L4C_MSG_ID_LEN (0x40) + +#define CCCI_LOG_LEVEL (4) +#endif diff --git a/drivers/misc/mediatek/eccci/mt6755/ccci_platform.c b/drivers/misc/mediatek/eccci/mt6755/ccci_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..efb57e400a974461f6c49d3883fe9abfae4245dd --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/ccci_platform.c @@ -0,0 +1,1082 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#include +#endif +#include +#include "ccci_config.h" +#include "ccci_modem.h" +#include "ccci_debug.h" +#include "ccci_bm.h" +#include "ccci_platform.h" +#ifdef FEATURE_USING_4G_MEMORY_API +#include +#endif + +#ifdef ENABLE_EMI_PROTECTION +#include +#endif +#define TAG "plat" + +static int is_4g_memory_size_support(void) +{ +#ifdef FEATURE_USING_4G_MEMORY_API + return enable_4G(); +#else + return 0; +#endif +} +int Is_MD_EMI_voilation(void) +{ +#ifdef ENABLE_EMI_PROTECTION + int violation_port = MASTER_MDMCU; + + violation_port = emi_mpu_get_violation_port(); + if ((violation_port == MASTER_MDMCU) || (violation_port == MASTER_MDHW)) + return 1; + return 0; +#else + return 1; +#endif +} +/* =================================================== */ +/* MPU Region defination */ +/* =================================================== */ +#define MPU_REGION_ID_SEC_OS 0 +#define MPU_REGION_ID_ATF 1 +/* #define MPU_REGION_ID_MD32_SMEM 2 */ +#define MPU_REGION_ID_TRUSTED_UI 3 +#define MPU_REGION_ID_MD1_SEC_SMEM 4 + +#define MPU_REGION_ID_MD1_SMEM 5 +#define MPU_REGION_ID_MD3_SMEM 6 +#define MPU_REGION_ID_MD1MD3_SMEM 7 +#define MPU_REGION_ID_MD1_MCURW_HWRW 8 +#define MPU_REGION_ID_MD1_ROM 9 /* contain DSP */ +#define MPU_REGION_ID_MD1_MCURW_HWRO 10 +#define MPU_REGION_ID_MD1_MCURO_HWRW 11 +#define MPU_REGION_ID_WIFI_EMI_FW 12 +#define MPU_REGION_ID_WMT 13 +#define MPU_REGION_ID_MD1_RW 14 +#define MPU_REGION_ID_MD3_ROM 15 +#define MPU_REGION_ID_MD3_RW 16 +#define MPU_REGION_ID_AP 17 +#define MPU_REGION_ID_TOTAL_NUM (MPU_REGION_ID_AP + 1) + +#ifdef ENABLE_EMI_PROTECTION +/* ////////////////////////////////////////////////////////////// (D7(MDHW), D6(MFG), \ + D5(MD3), D4(MM), D3(Resv), D2(CONN), D1(MD1), D0(AP)) */ +#define MPU_ACCESS_PERMISSON_CLEAR SET_ACCESS_PERMISSON(NO_PROTECTION, NO_PROTECTION, \ + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION) +/* maybe no use */ +#define MPU_ACCESS_PERMISSON_AP_MD1_RO_ATTR SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, \ + FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION) +/* #define MPU_REGION_ID_AP 17 */ +#define MPU_ACCESS_PERMISSON_AP_ATTR SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, \ + FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION) +/* #define MPU_REGION_ID_MD1_ROM_DSP 9 */ +#define MPU_ACCESS_PERMISSON_MD1_ROM_ATTR SET_ACCESS_PERMISSON(SEC_R_NSEC_R, FORBIDDEN, \ + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_R_NSEC_R, SEC_R_NSEC_R) +/* #define MPU_REGION_ID_MD1_RW 14 */ +#define MPU_ACCESS_PERMISSON_MD1_RW_ATTR SET_ACCESS_PERMISSON(SEC_R_NSEC_R, FORBIDDEN, \ + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, FORBIDDEN) +/* #define MPU_REGION_ID_MD1_SMEM 5 */ +#define MPU_ACCESS_PERMISSON_MD1_SMEM_ATTR SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, \ + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, NO_PROTECTION) +/* #define MPU_REGION_ID_MD3_ROM 15 */ +#define MPU_ACCESS_PERMISSON_MD3_ROM_ATTR SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, \ + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_R_NSEC_R) +/* #define MPU_REGION_ID_MD3_RW 16 */ +#define MPU_ACCESS_PERMISSON_MD3_RW_ATTR SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, \ + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_R_NSEC_R) +/* #define MPU_REGION_ID_MD3_SMEM 6 */ +#define MPU_ACCESS_PERMISSON_MD3_SMEM_ATTR SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, \ + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION) +/* #define MPU_REGION_ID_MD1MD3_SMEM 7 */ +#define MPU_ACCESS_PERMISSON_MD1MD3_SMEM_ATTR SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, \ + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, NO_PROTECTION) +/* #define MPU_REGION_ID_MD1_MCURO_HWRW 11 */ +#define MPU_ACCESS_PERMISSON_MD1RO_HWRW_ATTR SET_ACCESS_PERMISSON(NO_PROTECTION, FORBIDDEN, \ + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, SEC_R_NSEC_R) + +static const unsigned int MPU_ATTR_DEFAULT[MPU_REGION_ID_TOTAL_NUM][MPU_DOMAIN_ID_TOTAL_NUM] = { +/*===================================================================================================================*/ +/* No | | D0(AP) | D1(MD1) | D2(CONN) | D3(Res) | D4(MM) | D5(MD3 ) | D6(MFG) | D7(MDHW) |*/ +/*--------------+----------------------------------------------------------------------------------------------------*/ +/* 0*/{ SEC_RW , FORBIDDEN , FORBIDDEN , FORBIDDEN, SEC_RW , FORBIDDEN , FORBIDDEN , FORBIDDEN}, +/* 1*/{ SEC_RW , FORBIDDEN , FORBIDDEN , FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN , FORBIDDEN}, +/* 2*/{ SEC_RW , FORBIDDEN , FORBIDDEN , FORBIDDEN, SEC_RW , FORBIDDEN , FORBIDDEN , FORBIDDEN}, +/* 3*/{ SEC_RW , FORBIDDEN , FORBIDDEN , FORBIDDEN, SEC_RW , FORBIDDEN , FORBIDDEN , FORBIDDEN}, +/* 4*/{ SEC_R_NSEC_R , NO_PROTECTION, FORBIDDEN , FORBIDDEN, FORBIDDEN , NO_PROTECTION, FORBIDDEN , FORBIDDEN}, +/* 5*/{ NO_PROTECTION, NO_PROTECTION, FORBIDDEN , FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN , FORBIDDEN}, +/* 6*/{ NO_PROTECTION, FORBIDDEN , FORBIDDEN , FORBIDDEN, FORBIDDEN , NO_PROTECTION, FORBIDDEN , FORBIDDEN}, +/* 7*/{ SEC_R_NSEC_R , NO_PROTECTION, FORBIDDEN , FORBIDDEN, FORBIDDEN , NO_PROTECTION, FORBIDDEN , FORBIDDEN}, +/* 8*/{ SEC_R_NSEC_R , NO_PROTECTION, FORBIDDEN , FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN, NO_PROTECTION}, +/* 9*/{ SEC_R_NSEC_R , SEC_R_NSEC_R , FORBIDDEN , FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN, SEC_R_NSEC_R }, +/*10*/{ SEC_R_NSEC_R , NO_PROTECTION, FORBIDDEN , FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN, SEC_R_NSEC_R }, +/*11*/{ SEC_R_NSEC_R , SEC_R_NSEC_R , FORBIDDEN , FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN, NO_PROTECTION}, +/*12*/{ FORBIDDEN , FORBIDDEN , NO_PROTECTION, FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN , FORBIDDEN}, +/*13*/{ NO_PROTECTION, FORBIDDEN , NO_PROTECTION, FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN , FORBIDDEN}, +/*14*/{ SEC_R_NSEC_R , NO_PROTECTION, FORBIDDEN , FORBIDDEN, FORBIDDEN , FORBIDDEN , FORBIDDEN, SEC_R_NSEC_R }, +/*15*/{ SEC_R_NSEC_R , FORBIDDEN , FORBIDDEN , FORBIDDEN, FORBIDDEN , SEC_R_NSEC_R , FORBIDDEN , FORBIDDEN}, +/*16*/{ SEC_R_NSEC_R , FORBIDDEN , FORBIDDEN , FORBIDDEN, FORBIDDEN , NO_PROTECTION, FORBIDDEN , FORBIDDEN}, +/*17*/{ NO_PROTECTION, FORBIDDEN , FORBIDDEN , FORBIDDEN, NO_PROTECTION, FORBIDDEN , NO_PROTECTION, FORBIDDEN}, +}; /*=================================================================================================================*/ +#endif + +#define MPU_REGION_INFO_ID0 MPU_REGION_ID_MD1_ROM +#define MPU_REGION_INFO_ID1 MPU_REGION_ID_MD1_MCURW_HWRO +#define MPU_REGION_INFO_ID2 MPU_REGION_ID_MD1_MCURO_HWRW +#define MPU_REGION_INFO_ID3 MPU_REGION_ID_MD1_MCURW_HWRW +#define MPU_REGION_INFO_ID4 MPU_REGION_ID_MD1_RW +#define MPU_REGION_INFO_ID5 0 +#define MPU_REGION_INFO_ID6 0 +#define MPU_REGION_INFO_ID7 0 +#define MPU_REGION_INFO_ID(X) MPU_REGION_INFO_ID##X + +static const unsigned int MPU_REGION_INFO_ID[] = { +MPU_REGION_INFO_ID0, MPU_REGION_INFO_ID1, MPU_REGION_INFO_ID2, MPU_REGION_INFO_ID3, +MPU_REGION_INFO_ID4, MPU_REGION_INFO_ID5, MPU_REGION_INFO_ID6, MPU_REGION_INFO_ID7}; + +#define CHEAD_MPU_DOMAIN_0 MPU_DOMAIN_ID_AP +#define CHEAD_MPU_DOMAIN_1 MPU_DOMAIN_ID_MD +#define CHEAD_MPU_DOMAIN_2 MPU_DOMAIN_ID_MDHW +#define CHEAD_MPU_DOMAIN_3 0xFF +#define CHEAD_MPU_DOMAIN_LAST CHEAD_MPU_DOMAIN_2 +#define MPU_DOMAIN_NUM_OF_ID(X) MPU_DOMAIN_NUM_OF_ID##X +/* domain_attr */ +static const unsigned int CHEAD_MPU_DOMAIN_ID[] = { +CHEAD_MPU_DOMAIN_0, CHEAD_MPU_DOMAIN_1, CHEAD_MPU_DOMAIN_2, CHEAD_MPU_DOMAIN_3}; + +unsigned long infra_ao_base; +unsigned long dbgapb_base; +/* -- MD1 Bank 0 */ +#define MD1_BANK0_MAP0 ((unsigned int *)(infra_ao_base+0x300)) +#define MD1_BANK0_MAP1 ((unsigned int *)(infra_ao_base+0x304)) +/* -- MD1 Bank 4 */ +#define MD1_BANK4_MAP0 ((unsigned int *)(infra_ao_base+0x310)) +#define MD1_BANK4_MAP1 ((unsigned int *)(infra_ao_base+0x314)) + +/* -- MD2 Bank 0 */ +#define MD2_BANK0_MAP0 ((unsigned int *)(infra_ao_base+0x310)) +#define MD2_BANK0_MAP1 ((unsigned int *)(infra_ao_base+0x314)) +/* -- MD2 Bank 4 */ +#define MD2_BANK4_MAP0 ((unsigned int *)(infra_ao_base+0x318)) +#define MD2_BANK4_MAP1 ((unsigned int *)(infra_ao_base+0x31C)) + +/*-- MD3 Bank 0 */ +#define MD3_BANK0_MAP0 ((unsigned int *)(infra_ao_base+0x320)) +#define MD3_BANK0_MAP1 ((unsigned int *)(infra_ao_base+0x324)) +/*-- MD3 Bank 4 */ +#define MD3_BANK4_MAP0 ((unsigned int *)(infra_ao_base+0x330)) +#define MD3_BANK4_MAP1 ((unsigned int *)(infra_ao_base+0x334)) + +void ccci_clear_md_region_protection(struct ccci_modem *md) +{ +#ifdef ENABLE_EMI_PROTECTION + unsigned int rom_mem_mpu_id, rw_mem_mpu_id; + mpu_cfg_t *mpu_cfg_inf; + + if (modem_run_env_ready(md->index)) { /* LK has did it, bypass this step */ + CCCI_BOOTUP_LOG(md->index, TAG, "Ignore Clear MPU for md%d\n", md->index+1); + return; + } + switch (md->index) { + case MD_SYS1: + rom_mem_mpu_id = MPU_REGION_ID_MD1_ROM; + rw_mem_mpu_id = MPU_REGION_ID_MD1_RW; + break; + case MD_SYS3: + rom_mem_mpu_id = MPU_REGION_ID_MD3_ROM; + rw_mem_mpu_id = MPU_REGION_ID_MD3_RW; + break; + default: + CCCI_BOOTUP_LOG(md->index, TAG, "[error]MD ID invalid when clear MPU protect\n"); + return; + } + + CCCI_BOOTUP_LOG(md->index, TAG, "Clear MPU protect MD ROM region<%d>\n", rom_mem_mpu_id); + emi_mpu_set_region_protection(0, /*START_ADDR */ + 0, /*END_ADDR */ + rom_mem_mpu_id, /*region */ + MPU_ACCESS_PERMISSON_CLEAR); + + CCCI_BOOTUP_LOG(md->index, TAG, "Clear MPU protect MD R/W region<%d>\n", rw_mem_mpu_id); + emi_mpu_set_region_protection(0, /*START_ADDR */ + 0, /*END_ADDR */ + rw_mem_mpu_id, /*region */ + MPU_ACCESS_PERMISSON_CLEAR); +#ifdef SET_EMI_STEP_BY_STAGE +/*=======================================*/ +/* - Clear HW-related region protection -*/ +/*---------------------------------------*/ + if (md->index == MD_SYS1) { + /*---------------------------------------------------------------------------*/ + CCCI_BOOTUP_LOG(md->index, TAG, "Clear MPU protect HWRW R/W region<%d>\n", + MPU_REGION_ID_MD1_MCURW_HWRW); + emi_mpu_set_region_protection(0, /*START_ADDR*/ + 0, /*END_ADDR*/ + MPU_REGION_ID_MD1_MCURW_HWRW, /*region*/ + MPU_ACCESS_PERMISSON_CLEAR); + mpu_cfg_inf = get_mpu_region_cfg_info(MPU_REGION_ID_MD1_MCURW_HWRW); + if (mpu_cfg_inf && (mpu_cfg_inf->relate_region != 0)) { /*Region 0 used by security, it is safe */ + emi_mpu_set_region_protection(0, /*START_ADDR*/ + 0, /*END_ADDR*/ + mpu_cfg_inf->relate_region, /*region*/ + MPU_ACCESS_PERMISSON_CLEAR); + CCCI_BOOTUP_LOG(md->index, TAG, "Relate region<%d> using same setting\n", + mpu_cfg_inf->relate_region); + } else + CCCI_BOOTUP_LOG(md->index, TAG, "No relate region for region<%d>\n", + MPU_REGION_ID_MD1_MCURW_HWRW); + + /*---------------------------------------------------------------------------*/ + CCCI_BOOTUP_LOG(md->index, TAG, "Clear MPU protect HWRW ROM region<%d>\n", + MPU_REGION_ID_MD1_MCURW_HWRO); + emi_mpu_set_region_protection(0, /*START_ADDR*/ + 0, /*END_ADDR*/ + MPU_REGION_ID_MD1_MCURW_HWRO, /*region*/ + MPU_ACCESS_PERMISSON_CLEAR); + mpu_cfg_inf = get_mpu_region_cfg_info(MPU_REGION_ID_MD1_MCURW_HWRO); + if (mpu_cfg_inf && (mpu_cfg_inf->relate_region != 0)) { /*Region 0 used by security, it is safe */ + emi_mpu_set_region_protection(0, /*START_ADDR*/ + 0, /*END_ADDR*/ + mpu_cfg_inf->relate_region, /*region*/ + MPU_ACCESS_PERMISSON_CLEAR); + CCCI_BOOTUP_LOG(md->index, TAG, "Relate region<%d> using same setting\n", + mpu_cfg_inf->relate_region); + } else + CCCI_BOOTUP_LOG(md->index, TAG, "No relate region for region<%d>\n", + MPU_REGION_ID_MD1_MCURW_HWRO); + + /*---------------------------------------------------------------------------*/ + CCCI_BOOTUP_LOG(md->index, TAG, "Clear MPU protect HWRO R/W region<%d>\n", + MPU_REGION_ID_MD1_MCURO_HWRW); + emi_mpu_set_region_protection(0, /*START_ADDR*/ + 0, /*END_ADDR*/ + MPU_REGION_ID_MD1_MCURO_HWRW, /*region*/ + MPU_ACCESS_PERMISSON_CLEAR); + mpu_cfg_inf = get_mpu_region_cfg_info(MPU_REGION_ID_MD1_MCURO_HWRW); + if (mpu_cfg_inf && (mpu_cfg_inf->relate_region != 0)) { /*Region 0 used by security, it is safe */ + emi_mpu_set_region_protection(0, /*START_ADDR*/ + 0, /*END_ADDR*/ + mpu_cfg_inf->relate_region, /*region*/ + MPU_ACCESS_PERMISSON_CLEAR); + CCCI_BOOTUP_LOG(md->index, TAG, "Relate region<%d> using same setting\n", + mpu_cfg_inf->relate_region); + } else + CCCI_BOOTUP_LOG(md->index, TAG, "No relate region for region<%d>\n", + MPU_REGION_ID_MD1_MCURO_HWRW); + } + +#endif + +#endif +} + +void ccci_clear_dsp_region_protection(struct ccci_modem *md) +{ +#ifdef ENABLE_EMI_PROTECTION +#endif +} + +/* + * for some unkonw reason on 6582 and 6572, MD will read AP's memory during boot up, so we + * set AP region as MD read-only at first, and re-set it to portected after MD boot up. + * this function should be called right before sending runtime data. + */ +void ccci_set_ap_region_protection(struct ccci_modem *md) +{ +#ifdef ENABLE_EMI_PROTECTION +#ifdef SET_AP_MPU_REGION + unsigned int ap_mem_mpu_id, ap_mem_mpu_attr; + unsigned int kernel_base; + unsigned int dram_size; + + if (is_4g_memory_size_support()) + kernel_base = 0; + else + kernel_base = get_phys_offset(); +#ifdef ENABLE_DRAM_API + dram_size = get_max_DRAM_size(); +#else + dram_size = 256*1024*1024; +#endif + ap_mem_mpu_id = MPU_REGION_ID_AP; + ap_mem_mpu_attr = MPU_ACCESS_PERMISSON_AP_ATTR; + + CCCI_NORMAL_LOG(md->index, TAG, "MPU Start protect AP region<%d:%08x:%08x> %x\n", + ap_mem_mpu_id, kernel_base, (kernel_base+dram_size-1), ap_mem_mpu_attr); + emi_mpu_set_region_protection(kernel_base, + (kernel_base+dram_size-1), + ap_mem_mpu_id, + ap_mem_mpu_attr); +#endif +#endif +} + +void ccci_set_dsp_region_protection(struct ccci_modem *md, int loaded) +{ +#ifdef ENABLE_EMI_PROTECTION +#endif +} +#ifdef ENABLE_EMI_PROTECTION +inline unsigned int EXTRACT_REGION_VALUE(unsigned int domain_set, int region_num) +{ + unsigned int ret; + unsigned int shift = 4 * region_num; + + ret = (domain_set&(0x0000000F<>shift; + + return ret; +} + +/* region_id: 0~7 0=MPU_DOMAIN_INFO_ID_MD1 ->CHEAD_MPU_DOMAIN_ID[MPU_DOMAIN_INFO_ID_MD1]-- domain 1 MD1*/ +unsigned int CheckHeader_region_attr_paser(struct ccci_modem *md, unsigned region_id) +{ + unsigned int domain_id; + unsigned int region_attr, region_dom[8], temp_attr, extract_value; + unsigned int domain_attr_id[] = { + [CHEAD_MPU_DOMAIN_0] = MPU_DOMAIN_INFO_ID_MD1, + [CHEAD_MPU_DOMAIN_1] = MPU_DOMAIN_INFO_ID_MD3, + [CHEAD_MPU_DOMAIN_2] = MPU_DOMAIN_INFO_ID_MDHW, + }; + for (domain_id = 0; domain_id < 8; domain_id++) { + switch (domain_id) { + case CHEAD_MPU_DOMAIN_0: + case CHEAD_MPU_DOMAIN_1: + case CHEAD_MPU_DOMAIN_2: + case CHEAD_MPU_DOMAIN_3: + /* different domain attr value is in different domain_attr[] */ + temp_attr = md->img_info[IMG_MD].rmpu_info.domain_attr[domain_attr_id[domain_id]]; + extract_value = EXTRACT_REGION_VALUE(temp_attr, region_id); + CCCI_DEBUG_LOG(md->index, TAG, "%d, temp_attr = %X, extract_value= %X\n", + domain_attr_id[domain_id], temp_attr, extract_value); + if ((extract_value >= NO_PROTECTION) && (extract_value <= FORBIDDEN)) + region_dom[domain_id] = extract_value; + else + region_dom[domain_id] = MPU_ATTR_DEFAULT[MPU_REGION_INFO_ID[region_id]][domain_id]; + CCCI_DEBUG_LOG(md->index, TAG, "1. region_dom[%d] = %X\n", domain_id, region_dom[domain_id]); + break; + default: + region_dom[domain_id] = MPU_ATTR_DEFAULT[MPU_REGION_INFO_ID[region_id]][domain_id]; + CCCI_DEBUG_LOG(md->index, TAG, "2. region_dom[%d] = %X\n", domain_id, region_dom[domain_id]); + break; + } + } + region_attr = SET_ACCESS_PERMISSON(region_dom[7], region_dom[6], region_dom[5], region_dom[4], + region_dom[3], region_dom[2], region_dom[1], region_dom[0]); + return region_attr; +} +#endif +void ccci_set_mem_access_protection(struct ccci_modem *md) +{ +#ifdef ENABLE_EMI_PROTECTION + unsigned int shr_mem_phy_start, shr_mem_phy_end, shr_mem_mpu_id, shr_mem_mpu_attr; + unsigned int rom_mem_phy_start, rom_mem_phy_end, rom_mem_mpu_id, rom_mem_mpu_attr; + unsigned int rw_mem_phy_start, rw_mem_phy_end, rw_mem_mpu_id, rw_mem_mpu_attr; +#ifdef SET_AP_MPU_REGION + unsigned int ap_mem_mpu_id, ap_mem_mpu_attr; +#endif + unsigned int shr_mem13_phy_start, shr_mem13_phy_end, shr_mem13_mpu_id, shr_mem13_mpu_attr; + unsigned int region_id; + struct ccci_image_info *img_info; + struct ccci_mem_layout *md_layout; +#ifdef SET_AP_MPU_REGION + unsigned int kernel_base; + unsigned int dram_size; +#endif + unsigned int by_pass_setting = 0; + /* check header version is newer than v4 */ + CCCI_BOOTUP_LOG(md->index, TAG, "CCCI Image header version = %d\n", md->img_info[IMG_MD].img_info.header_verno); + if (md->index == MD_SYS1 && md->img_info[IMG_MD].img_info.header_verno < 4) { + CCCI_BOOTUP_LOG(md->index, TAG, "CCCI Image header version is %d ,RMPU Only support after v4\n", + md->img_info[IMG_MD].img_info.header_verno); + return; + } + + if (modem_run_env_ready(md->index)) { + CCCI_BOOTUP_LOG(md->index, TAG, "Has protected, bypass\n"); + by_pass_setting = 1; + } + switch (md->index) { + case MD_SYS1: + img_info = &md->img_info[IMG_MD]; + md_layout = &md->mem_layout; + /* region 9 */ + region_id = MD_SET_REGION_MD1_ROM_DSP; + rom_mem_mpu_id = MPU_REGION_ID_MD1_ROM; /*MPU_REGION_INFO_ID[region_id]; */ + rom_mem_mpu_attr = CheckHeader_region_attr_paser(md, region_id); + rom_mem_phy_start = (unsigned int)md_layout->md_region_phy + + img_info->rmpu_info.region_info[region_id].region_offset; + rom_mem_phy_end = + ((rom_mem_phy_start + img_info->rmpu_info.region_info[region_id].region_size + 0xFFFF)&(~0xFFFF)) + - 0x1; + if (by_pass_setting == 0) { + CCCI_BOOTUP_LOG(md->index, TAG, "Start MPU protect region <%d:%08X:%08X> %X\n", + rom_mem_mpu_id, rom_mem_phy_start, rom_mem_phy_end, rom_mem_mpu_attr); + emi_mpu_set_region_protection(rom_mem_phy_start, /*START_ADDR */ + rom_mem_phy_end, /*END_ADDR */ + rom_mem_mpu_id, /*region */ + rom_mem_mpu_attr); + } + shr_mem_mpu_id = MPU_REGION_ID_MD1_SMEM;/* 5 */ + shr_mem_mpu_attr = MPU_ACCESS_PERMISSON_MD1_SMEM_ATTR;/* 5 */ + break; + case MD_SYS3: + img_info = &md->img_info[IMG_MD]; + md_layout = &md->mem_layout; + rom_mem_mpu_id = MPU_REGION_ID_MD3_ROM; + rw_mem_mpu_id = MPU_REGION_ID_MD3_RW; + shr_mem_mpu_id = MPU_REGION_ID_MD3_SMEM; + shr_mem13_mpu_id = MPU_REGION_ID_MD1MD3_SMEM; + rom_mem_mpu_attr = MPU_ACCESS_PERMISSON_MD3_ROM_ATTR; + rw_mem_mpu_attr = MPU_ACCESS_PERMISSON_MD3_RW_ATTR; + shr_mem_mpu_attr = MPU_ACCESS_PERMISSON_MD3_SMEM_ATTR; + shr_mem13_mpu_attr = MPU_ACCESS_PERMISSON_MD1MD3_SMEM_ATTR; + /* + * if set start=0x0, end=0x10000, the actural protected area will be 0x0-0x1FFFF, + * here we use 64KB align, MPU actually request 32KB align since MT6582, but this works... + * we assume emi_mpu_set_region_protection will round end address down to 64KB align. + */ + rom_mem_phy_start = (unsigned int)md_layout->md_region_phy; + rom_mem_phy_end = ((rom_mem_phy_start + img_info->size + 0xFFFF) & (~0xFFFF)) - 0x1; + rw_mem_phy_start = rom_mem_phy_end + 0x1; + rw_mem_phy_end = rom_mem_phy_start + md_layout->md_region_size - 0x1; +#ifdef ENABLE_DSP_SMEM_SHARE_MPU_REGION + rw_mem_phy_end += md_layout->smem_region_size; +#endif + /* MD1 MD3 share memory */ + shr_mem13_phy_start = (unsigned int)md_layout->md1_md3_smem_phy; + shr_mem13_phy_end = ((shr_mem13_phy_start + md_layout->md1_md3_smem_size + 0xFFFF) & (~0xFFFF)) - 0x1; + + if (by_pass_setting == 0) { + CCCI_BOOTUP_LOG(md->index, TAG, + "MPU protect MD ROM region<%d:%08x:%08x> %x,invalid_map=0x%llx\n", + rom_mem_mpu_id, rom_mem_phy_start, rom_mem_phy_end, rom_mem_mpu_attr, + (unsigned long long)md->invalid_remap_base); + emi_mpu_set_region_protection(rom_mem_phy_start, /*START_ADDR */ + rom_mem_phy_end, /*END_ADDR */ + rom_mem_mpu_id, /*region */ + rom_mem_mpu_attr); + + CCCI_BOOTUP_LOG(md->index, TAG, "MPU protect MD R/W region<%d:%08x:%08x> %x\n", + rw_mem_mpu_id, rw_mem_phy_start, rw_mem_phy_end, rw_mem_mpu_attr); + emi_mpu_set_region_protection(rw_mem_phy_start, /*START_ADDR */ + rw_mem_phy_end, /*END_ADDR */ + rw_mem_mpu_id, /*region */ + rw_mem_mpu_attr); + } + + CCCI_BOOTUP_LOG(md->index, TAG, "MPU protect MD1&3 Share region<%d:%08x:%08x> %x\n", + shr_mem13_mpu_id, shr_mem13_phy_start, shr_mem13_phy_end, shr_mem13_mpu_attr); + emi_mpu_set_region_protection(shr_mem13_phy_start, /*START_ADDR */ + shr_mem13_phy_end, /*END_ADDR */ + shr_mem13_mpu_id, /*region */ + shr_mem13_mpu_attr); + + break; + default: + CCCI_BOOTUP_LOG(md->index, CORE, "[error]invalid when MPU protect\n"); + return; + } +#ifdef SET_AP_MPU_REGION + if (is_4g_memory_size_support()) + kernel_base = 0; + else + kernel_base = get_phys_offset(); +#ifdef ENABLE_DRAM_API + dram_size = get_max_DRAM_size(); +#else + dram_size = 256 * 1024 * 1024; +#endif + ap_mem_mpu_id = MPU_REGION_ID_AP; + ap_mem_mpu_attr = MPU_ACCESS_PERMISSON_AP_MD1_RO_ATTR; +#endif + + shr_mem_phy_start = (unsigned int)md_layout->smem_region_phy; + shr_mem_phy_end = ((shr_mem_phy_start + md_layout->smem_region_size + 0xFFFF) & (~0xFFFF)) - 0x1; + +#ifndef ENABLE_DSP_SMEM_SHARE_MPU_REGION + CCCI_BOOTUP_LOG(md->index, TAG, "MPU protect MD Share region<%d:%08x:%08x> %x\n", + shr_mem_mpu_id, shr_mem_phy_start, shr_mem_phy_end, shr_mem_mpu_attr); + emi_mpu_set_region_protection(shr_mem_phy_start, /*START_ADDR */ + shr_mem_phy_end, /*END_ADDR */ + shr_mem_mpu_id, /*region */ + shr_mem_mpu_attr); +#endif +/* This part need to move common part */ +#ifdef SET_AP_MPU_REGION + CCCI_BOOTUP_LOG(md->index, TAG, "MPU protect AP region<%d:%08x:%08x> %x\n", + ap_mem_mpu_id, kernel_base, (kernel_base + dram_size - 1), ap_mem_mpu_attr); + emi_mpu_set_region_protection(kernel_base, (kernel_base + dram_size - 1), ap_mem_mpu_id, ap_mem_mpu_attr); +#endif +#endif +} + +#ifdef SET_EMI_STEP_BY_STAGE +/* For HW DE Error: initial value of domain is wrong, we add protection 1st stage */ +void ccci_set_mem_access_protection_1st_stage(struct ccci_modem *md) +{ +#ifdef ENABLE_EMI_PROTECTION + struct ccci_image_info *img_info; + struct ccci_mem_layout *md_layout; + unsigned int region_id, region_mpu_id, region_mpu_attr, region_mpu_start, region_mpu_end; + mpu_cfg_t *mpu_cfg_inf; + + switch (md->index) { + case MD_SYS1: + if (modem_run_env_ready(MD_SYS1)) { + CCCI_BOOTUP_LOG(md->index, TAG, "Has protected, only MDHW bypass other 1st step\n"); + img_info = &md->img_info[IMG_MD]; + md_layout = &md->mem_layout; + region_mpu_id = MPU_REGION_ID_MD1_MCURO_HWRW; + region_mpu_attr = SET_ACCESS_PERMISSON(NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, NO_PROTECTION, SEC_R_NSEC_R); + region_mpu_start = (unsigned int)md_layout->md_region_phy + + img_info->rmpu_info.region_info[2].region_offset; /* Note here!!!!!, 2 */ + region_mpu_end = + ((region_mpu_start + img_info->rmpu_info.region_info[2].region_size /* Note here, 2 */ + + 0xFFFF)&(~0xFFFF)) - 0x1; + + CCCI_BOOTUP_LOG(md->index, TAG, "Start MPU protect region <%d:%08X:%08X> %X\n", + region_mpu_id, region_mpu_start, region_mpu_end, region_mpu_attr); + emi_mpu_set_region_protection(region_mpu_start, /*START_ADDR */ + region_mpu_end, /*END_ADDR */ + region_mpu_id, /*region */ + region_mpu_attr); + mpu_cfg_inf = get_mpu_region_cfg_info(region_mpu_id); + if (mpu_cfg_inf && (mpu_cfg_inf->relate_region != 0)) { + emi_mpu_set_region_protection(region_mpu_start, /*START_ADDR */ + region_mpu_end, /*END_ADDR */ + mpu_cfg_inf->relate_region, /*region */ + region_mpu_attr); + CCCI_BOOTUP_LOG(md->index, TAG, "Relate region<%d> using same setting(@1st)\n", + mpu_cfg_inf->relate_region); + } else + CCCI_BOOTUP_LOG(md->index, TAG, "No relate region for region<%d>(@1st)\n", + region_mpu_id); + break; + } + img_info = &md->img_info[IMG_MD]; + md_layout = &md->mem_layout; + + for (region_id = MD_SET_REGION_MD1_MCURW_HWRO; region_id < MPU_REGION_INFO_ID_TOTAL_NUM; region_id++) { + /* set 8, 10, 14 region, except 11 */ + region_mpu_id = MPU_REGION_INFO_ID[region_id]; + region_mpu_start = (unsigned int)md_layout->md_region_phy + + img_info->rmpu_info.region_info[region_id].region_offset; + region_mpu_end = + ((region_mpu_start + img_info->rmpu_info.region_info[region_id].region_size + + 0xFFFF)&(~0xFFFF)) - 0x1; + if (region_mpu_id == MPU_REGION_ID_MD1_MCURO_HWRW) + region_mpu_attr = MPU_ACCESS_PERMISSON_MD1RO_HWRW_ATTR; + else + region_mpu_attr = CheckHeader_region_attr_paser(md, region_id); + /*if ((region_mpu_id == MPU_REGION_ID_MD1_MCURO_HWRW) + || (region_mpu_id == MPU_REGION_ID_MD1_MCURW_HWRW) + || (region_mpu_id == MPU_REGION_ID_MD1_MCURW_HWRO)) { + CCCI_NORMAL_LOG(md->index, TAG, "Bypass MPU protect region <%d:%08X:%08X> %X\n", + region_mpu_id, region_mpu_start, region_mpu_end, region_mpu_attr); + CCCI_NORMAL_LOG(md->index, TAG, "BYPASS region <%d:>\n", region_mpu_id); + continue; + }*/ + CCCI_BOOTUP_LOG(md->index, TAG, "Start MPU protect region <%d:%08X:%08X> %X\n", + region_mpu_id, region_mpu_start, region_mpu_end, region_mpu_attr); + emi_mpu_set_region_protection(region_mpu_start, /*START_ADDR */ + region_mpu_end, /*END_ADDR */ + region_mpu_id, /*region */ + region_mpu_attr); + mpu_cfg_inf = get_mpu_region_cfg_info(region_mpu_id); + if (mpu_cfg_inf && (mpu_cfg_inf->relate_region != 0)) { + emi_mpu_set_region_protection(region_mpu_start, /*START_ADDR */ + region_mpu_end, /*END_ADDR */ + mpu_cfg_inf->relate_region, /*region */ + region_mpu_attr); + CCCI_BOOTUP_LOG(md->index, TAG, "Relate region<%d> using same setting(@1st)\n", + mpu_cfg_inf->relate_region); + } else + CCCI_BOOTUP_LOG(md->index, TAG, "No relate region for region<%d>(@1st)\n", + region_mpu_id); + } + break; + case MD_SYS3: + default: + CCCI_DEBUG_LOG(md->index, CORE, "[error]invalid when MPU protect\n"); + return; + } + +#endif +} + +void ccci_set_mem_access_protection_second_stage(struct ccci_modem *md) +{ +#ifdef ENABLE_EMI_PROTECTION + struct ccci_image_info *img_info; + struct ccci_mem_layout *md_layout; + unsigned int region_id, region_mpu_id, region_mpu_attr, region_mpu_start, region_mpu_end; + mpu_cfg_t *mpu_cfg_inf; + + switch (md->index) { + case MD_SYS1: + img_info = &md->img_info[IMG_MD]; + md_layout = &md->mem_layout; + region_id = MD_SET_REGION_MD1_MCURO_HWRW;/*MPU_REGION_ID_MD1_MCURO_HWRW;*/ + /* set 11 */ + region_mpu_id = MPU_REGION_INFO_ID[region_id]; + region_mpu_attr = CheckHeader_region_attr_paser(md, region_id); + region_mpu_start = (unsigned int)md_layout->md_region_phy + + img_info->rmpu_info.region_info[region_id].region_offset; + region_mpu_end = + ((region_mpu_start + img_info->rmpu_info.region_info[region_id].region_size + 0xFFFF)&(~0xFFFF)) - 0x1; + + CCCI_BOOTUP_LOG(md->index, TAG, "Start MPU protect region <%d:%08X:%08X> %X\n", + region_mpu_id, region_mpu_start, region_mpu_end, region_mpu_attr); + emi_mpu_set_region_protection(region_mpu_start, /*START_ADDR */ + region_mpu_end, /*END_ADDR */ + region_mpu_id, /*region */ + region_mpu_attr); + mpu_cfg_inf = get_mpu_region_cfg_info(region_mpu_id); + if (mpu_cfg_inf && (mpu_cfg_inf->relate_region != 0)) { + emi_mpu_set_region_protection(region_mpu_start, /*START_ADDR */ + region_mpu_end, /*END_ADDR */ + mpu_cfg_inf->relate_region, /*region */ + region_mpu_attr); + CCCI_BOOTUP_LOG(md->index, TAG, "Relate region<%d> using same setting(@2nd)\n", + mpu_cfg_inf->relate_region); + } else + CCCI_BOOTUP_LOG(md->index, TAG, "No relate region for region<%d>(@2nd)\n", + region_mpu_id); + break; + case MD_SYS3: + default: + CCCI_DEBUG_LOG(md->index, CORE, "[error]invalid when MPU protect\n"); + return; + } + +#endif +} +#endif + +#ifdef ENABLE_DSP_SMEM_SHARE_MPU_REGION +void ccci_set_exp_region_protection(struct ccci_modem *md) +{ + unsigned int shr_mem_phy_start, shr_mem_phy_end, shr_mem_mpu_id, shr_mem_mpu_attr; + + shr_mem_phy_start = (unsigned int)md->mem_layout.smem_region_phy; + shr_mem_phy_end = ((shr_mem_phy_start + md->mem_layout.smem_region_size + 0xFFFF) & (~0xFFFF)) - 0x1; + shr_mem_mpu_id = MPU_REGION_ID_MD1_SMEM; + shr_mem_mpu_attr = SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN, NO_PROTECTION, NO_PROTECTION); + + CCCI_NORMAL_LOG(md->index, TAG, "After EE: MPU Start protect MD Share region<%d:%08x:%08x> %x\n", + shr_mem_mpu_id, shr_mem_phy_start, shr_mem_phy_end, shr_mem_mpu_attr); + emi_mpu_set_region_protection(shr_mem_phy_start, /*START_ADDR */ + shr_mem_phy_end, /*END_ADDR */ + shr_mem_mpu_id, /*region */ + shr_mem_mpu_attr); +} +#endif + +/* This function has phase out!!! */ +int set_ap_smem_remap(struct ccci_modem *md, phys_addr_t src, phys_addr_t des) +{ + unsigned int remap1_val = 0; + unsigned int remap2_val = 0; + static int smem_remapped; + + if (!smem_remapped) { + smem_remapped = 1; + remap1_val = (((des >> 24) | 0x1) & 0xFF) + + (((INVALID_ADDR >> 16) | 1 << 8) & 0xFF00) + + (((INVALID_ADDR >> 8) | 1 << 16) & 0xFF0000) + + (((INVALID_ADDR >> 0) | 1 << 24) & 0xFF000000); + + remap2_val = (((INVALID_ADDR >> 24) | 0x1) & 0xFF) + + (((INVALID_ADDR >> 16) | 1 << 8) & 0xFF00) + + (((INVALID_ADDR >> 8) | 1 << 16) & 0xFF0000) + + (((INVALID_ADDR >> 0) | 1 << 24) & 0xFF000000); + + CCCI_NORMAL_LOG(md->index, TAG, "AP Smem remap: [%llx]->[%llx](%08x:%08x)\n", (unsigned long long)des, + (unsigned long long)src, remap1_val, remap2_val); + +#ifdef ENABLE_MEM_REMAP_HW + mt_reg_sync_writel(remap1_val, AP_BANK4_MAP0); + mt_reg_sync_writel(remap2_val, AP_BANK4_MAP1); + mt_reg_sync_writel(remap2_val, AP_BANK4_MAP1); /* HW bug, write twice to activate setting */ +#endif + } + return 0; +} + +int set_md_smem_remap(struct ccci_modem *md, phys_addr_t src, phys_addr_t des, phys_addr_t invalid) +{ + unsigned int remap1_val = 0; + unsigned int remap2_val = 0; + + if (is_4g_memory_size_support()) + des &= 0xFFFFFFFF; + else + des -= KERN_EMI_BASE; + + switch (md->index) { + case MD_SYS1: + remap1_val = (((des >> 24) | 0x1) & 0xFF) + + ((((des + 0x2000000 * 1) >> 16) | 1 << 8) & 0xFF00) + + ((((des + 0x2000000 * 2) >> 8) | 1 << 16) & 0xFF0000) + + ((((des + 0x2000000 * 3) >> 0) | 1 << 24) & 0xFF000000); + remap2_val = ((((des + 0x2000000 * 4) >> 24) | 0x1) & 0xFF) + + ((((des + 0x2000000 * 5) >> 16) | 1 << 8) & 0xFF00) + + ((((des + 0x2000000 * 6) >> 8) | 1 << 16) & 0xFF0000) + + ((((des + 0x2000000 * 7) >> 0) | 1 << 24) & 0xFF000000); + +#ifdef ENABLE_MEM_REMAP_HW + mt_reg_sync_writel(remap1_val, MD1_BANK4_MAP0); + mt_reg_sync_writel(remap2_val, MD1_BANK4_MAP1); +#endif + break; + case MD_SYS2: + remap1_val = (((des >> 24) | 0x1) & 0xFF) + + ((((invalid + 0x2000000 * 0) >> 16) | 1 << 8) & 0xFF00) + + ((((invalid + 0x2000000 * 1) >> 8) | 1 << 16) & 0xFF0000) + + ((((invalid + 0x2000000 * 2) >> 0) | 1 << 24) & 0xFF000000); + remap2_val = ((((invalid + 0x2000000 * 3) >> 24) | 0x1) & 0xFF) + + ((((invalid + 0x2000000 * 4) >> 16) | 1 << 8) & 0xFF00) + + ((((invalid + 0x2000000 * 5) >> 8) | 1 << 16) & 0xFF0000) + + ((((invalid + 0x2000000 * 6) >> 0) | 1 << 24) & 0xFF000000); + +#ifdef ENABLE_MEM_REMAP_HW + mt_reg_sync_writel(remap1_val, MD2_BANK4_MAP0); + mt_reg_sync_writel(remap2_val, MD2_BANK4_MAP1); +#endif + break; + case MD_SYS3: + remap1_val = (((des>>24)|0x1)&0xFF) + + ((((invalid+0x2000000*0)>>16)|1<<8)&0xFF00) + + ((((invalid+0x2000000*1)>>8)|1<<16)&0xFF0000) + + ((((invalid+0x2000000*2)>>0)|1<<24)&0xFF000000); + remap2_val = ((((invalid+0x2000000*3)>>24)|0x1)&0xFF) + + ((((invalid+0x2000000*4)>>16)|1<<8)&0xFF00) + + ((((invalid+0x2000000*5)>>8)|1<<16)&0xFF0000) + + ((((invalid+0x2000000*6)>>0)|1<<24)&0xFF000000); + +#ifdef ENABLE_MEM_REMAP_HW + mt_reg_sync_writel(remap1_val, MD3_BANK4_MAP0); + mt_reg_sync_writel(remap2_val, MD3_BANK4_MAP1); +#endif + break; + default: + break; + } + + CCCI_INIT_LOG(md->index, TAG, "MD Smem remap:[%llx]->[%llx](%08x:%08x), invalid_map=0x%llx\n", + (unsigned long long)des, (unsigned long long)src, remap1_val, remap2_val, + (unsigned long long)md->invalid_remap_base); + return 0; +} + +int set_md_rom_rw_mem_remap(struct ccci_modem *md, phys_addr_t src, phys_addr_t des, phys_addr_t invalid) +{ + unsigned int remap1_val = 0; + unsigned int remap2_val = 0; + + if (modem_run_env_ready(md->index)) { + CCCI_BOOTUP_LOG(md->index, TAG, "RO_RW has mapped\n"); + return 0; + } + CCCI_BOOTUP_LOG(md->index, TAG, "Kernel RO_RW mapping\n"); + + if (is_4g_memory_size_support()) + des &= 0xFFFFFFFF; + else + des -= KERN_EMI_BASE; + + switch (md->index) { + case MD_SYS1: + remap1_val = (((des >> 24) | 0x1) & 0xFF) + + ((((des + 0x2000000 * 1) >> 16) | 1 << 8) & 0xFF00) + + ((((des + 0x2000000 * 2) >> 8) | 1 << 16) & 0xFF0000) + + ((((des + 0x2000000 * 3) >> 0) | 1 << 24) & 0xFF000000); + remap2_val = ((((des + 0x2000000 * 4) >> 24) | 0x1) & 0xFF) + + ((((des + 0x2000000 * 5) >> 16) | 1 << 8) & 0xFF00) + + ((((des + 0x2000000 * 6) >> 8) | 1 << 16) & 0xFF0000) + + ((((des + 0x2000000 * 7) >> 0) | 1 << 24) & 0xFF000000); + +#ifdef ENABLE_MEM_REMAP_HW + mt_reg_sync_writel(remap1_val, MD1_BANK0_MAP0); + mt_reg_sync_writel(remap2_val, MD1_BANK0_MAP1); +#endif + break; + case MD_SYS2: + remap1_val = (((des >> 24) | 0x1) & 0xFF) + + ((((des + 0x2000000 * 1) >> 16) | 1 << 8) & 0xFF00) + + ((((des + 0x2000000 * 2) >> 8) | 1 << 16) & 0xFF0000) + + ((((invalid + 0x2000000 * 7) >> 0) | 1 << 24) & 0xFF000000); + remap2_val = ((((invalid + 0x2000000 * 8) >> 24) | 0x1) & 0xFF) + + ((((invalid + 0x2000000 * 9) >> 16) | 1 << 8) & 0xFF00) + + ((((invalid + 0x2000000 * 10) >> 8) | 1 << 16) & 0xFF0000) + + ((((invalid + 0x2000000 * 11) >> 0) | 1 << 24) & 0xFF000000); + +#ifdef ENABLE_MEM_REMAP_HW + mt_reg_sync_writel(remap1_val, MD2_BANK0_MAP0); + mt_reg_sync_writel(remap2_val, MD2_BANK0_MAP1); +#endif + break; + case MD_SYS3: + remap1_val = (((des>>24)|0x1)&0xFF) + + ((((des+0x2000000*1)>>16)|1<<8)&0xFF00) + + ((((des+0x2000000*2)>>8)|1<<16)&0xFF0000) + + ((((invalid+0x2000000*7)>>0)|1<<24)&0xFF000000); + remap2_val = ((((invalid+0x2000000*8)>>24)|0x1)&0xFF) + + ((((invalid+0x2000000*9)>>16)|1<<8)&0xFF00) + + ((((invalid+0x2000000*10)>>8)|1<<16)&0xFF0000) + + ((((invalid+0x2000000*11)>>0)|1<<24)&0xFF000000); + +#ifdef ENABLE_MEM_REMAP_HW + mt_reg_sync_writel(remap1_val, MD3_BANK0_MAP0); + mt_reg_sync_writel(remap2_val, MD3_BANK0_MAP1); +#endif + break; + + default: + break; + } + + CCCI_NORMAL_LOG(md->index, TAG, "MD ROM mem remap:[%llx]->[%llx](%08x:%08x)\n", (unsigned long long)des, + (unsigned long long)src, remap1_val, remap2_val); + return 0; +} + +void ccci_set_mem_remap(struct ccci_modem *md, unsigned long smem_offset, phys_addr_t invalid) +{ + /* + * MD bank4 is remap to nearest 32M aligned address + * assume share memoy layout is: + * |---AP/MD1--| <--MD1 bank4 + * |--MD1/MD3--| <--MD3 bank4 + * |---AP/MD3--| + * this should align with LK's remap setting + */ + phys_addr_t md_bank4_base; + + switch (md->index) { + case MD_SYS1: + md_bank4_base = round_down(md->mem_layout.smem_region_phy, 0x02000000); + break; + case MD_SYS3: + md_bank4_base = round_down(md->mem_layout.md1_md3_smem_phy, 0x02000000); + break; + default: + md_bank4_base = 0; + break; + } + md->invalid_remap_base = invalid; + /* + * AP_view_addr - md_bank4_base + 0x40000000 = MD_view_addr + * AP_view_addr - smem_offset_AP_to_MD = MD_view_addr + */ + md->mem_layout.smem_offset_AP_to_MD = md_bank4_base - 0x40000000; + invalid = md->mem_layout.smem_region_phy + md->mem_layout.smem_region_size; + set_md_rom_rw_mem_remap(md, 0x00000000, md->mem_layout.md_region_phy, invalid); + set_md_smem_remap(md, 0x40000000, md_bank4_base, invalid); + CCCI_NORMAL_LOG(md->index, TAG, "%s 0x%llX 0x%X\n", __func__, + (unsigned long long)md_bank4_base, md->mem_layout.smem_offset_AP_to_MD); +} + +/* + * when MD attached its codeviser for debuging, this bit will be set. so CCCI should disable some + * checkings and operations as MD may not respond to us. + */ +unsigned int ccci_get_md_debug_mode(struct ccci_modem *md) +{ + unsigned int dbg_spare; + static unsigned int debug_setting_flag; + /* this function does NOT distinguish modem ID, may be a risk point */ + if ((debug_setting_flag & DBG_FLAG_JTAG) == 0) { + dbg_spare = ioread32((void __iomem *)(dbgapb_base + 0x10)); + if (dbg_spare & MD_DBG_JTAG_BIT) { + CCCI_NORMAL_LOG(md->index, TAG, "Jtag Debug mode(%08x)\n", dbg_spare); + debug_setting_flag |= DBG_FLAG_JTAG; + mt_reg_sync_writel(dbg_spare & (~MD_DBG_JTAG_BIT), (dbgapb_base + 0x10)); + } + } + return debug_setting_flag; +} +EXPORT_SYMBOL(ccci_get_md_debug_mode); + +void ccci_get_platform_version(char *ver) +{ +#ifdef ENABLE_CHIP_VER_CHECK + sprintf(ver, "MT%04x_S%02x", get_chip_hw_ver_code(), (get_chip_hw_subcode() & 0xFF)); +#else + sprintf(ver, "MT6735_S00"); +#endif +} + +#ifdef FEATURE_LOW_BATTERY_SUPPORT +static int ccci_md_low_power_notify(struct ccci_modem *md, LOW_POEWR_NOTIFY_TYPE type, int level) +{ + unsigned int reserve = 0xFFFFFFFF; + int ret = 0; + + CCCI_NORMAL_LOG(md->index, TAG, "low power notification type=%d, level=%d\n", type, level); + /* + * byte3 byte2 byte1 byte0 + * 0 4G 3G 2G + */ + switch (type) { + case LOW_BATTERY: + if (level == LOW_BATTERY_LEVEL_0) + reserve = 0; /* 0 */ + else if (level == LOW_BATTERY_LEVEL_1 || level == LOW_BATTERY_LEVEL_2) + reserve = (1 << 6); /* 64 */ + ret = port_proxy_send_msg_to_md(md->port_proxy, CCCI_SYSTEM_TX, MD_LOW_BATTERY_LEVEL, reserve, 1); + if (ret) + CCCI_ERROR_LOG(md->index, TAG, "send low battery notification fail, ret=%d\n", ret); + break; + case BATTERY_PERCENT: + if (level == BATTERY_PERCENT_LEVEL_0) + reserve = 0; /* 0 */ + else if (level == BATTERY_PERCENT_LEVEL_1) + reserve = (1 << 6); /* 64 */ + ret = port_proxy_send_msg_to_md(md->port_proxy, CCCI_SYSTEM_TX, MD_LOW_BATTERY_LEVEL, reserve, 1); + if (ret) + CCCI_ERROR_LOG(md->index, TAG, "send battery percent notification fail, ret=%d\n", ret); + break; + default: + break; + }; + + return ret; +} + +static void ccci_md_low_battery_cb(LOW_BATTERY_LEVEL level) +{ + int idx = 0; + struct ccci_modem *md; + + for (idx = 0; idx < MAX_MD_NUM; idx++) { + md = ccci_md_get_modem_by_id(idx); + if (md != NULL) + ccci_md_low_power_notify(md, LOW_BATTERY, level); + } +} + +static void ccci_md_battery_percent_cb(BATTERY_PERCENT_LEVEL level) +{ + int idx = 0; + struct ccci_modem *md; + + for (idx = 0; idx < MAX_MD_NUM; idx++) { + md = ccci_md_get_modem_by_id(idx); + if (md != NULL) + ccci_md_low_power_notify(md, BATTERY_PERCENT, level); + } +} +#endif + +#define PCCIF_BUSY (0x4) +#define PCCIF_TCHNUM (0xC) +#define PCCIF_ACK (0x14) +#define PCCIF_CHDATA (0x100) +#define PCCIF_SRAM_SIZE (512) + +void ccci_reset_ccif_hw(struct ccci_modem *md, int ccif_id, void __iomem *baseA, void __iomem *baseB) +{ + int i; +#if 0 + { + unsigned int tx_channel = 0; + + /* clear occupied channel */ + while (tx_channel < 16) { + if (ccci_read32(baseA, PCCIF_BUSY) & (1< +#include "ccci_config.h" +#include "ccci_modem.h" + +#define INVALID_ADDR (0xF0000000) /* the last EMI bank, properly not used */ +#define KERN_EMI_BASE (0x40000000) /* Bank4 */ + +/* - AP side, using mcu config base */ +/* -- AP Bank4 */ +#define AP_BANK4_MAP0 (0) /* ((volatile unsigned int*)(MCUSYS_CFGREG_BASE+0x200)) */ +#define AP_BANK4_MAP1 (0) /* ((volatile unsigned int*)(MCUSYS_CFGREG_BASE+0x204)) */ + +/* - MD side, using infra config base */ +#define DBG_FLAG_DEBUG (1<<0) +#define DBG_FLAG_JTAG (1<<1) +#define MD_DBG_JTAG_BIT (1<<0) + +#define ccci_write32(b, a, v) mt_reg_sync_writel(v, (b)+(a)) +#define ccci_write16(b, a, v) mt_reg_sync_writew(v, (b)+(a)) +#define ccci_write8(b, a, v) mt_reg_sync_writeb(v, (b)+(a)) +#define ccci_read32(b, a) ioread32((void __iomem *)((b)+(a))) +#define ccci_read16(b, a) ioread16((void __iomem *)((b)+(a))) +#define ccci_read8(b, a) ioread8((void __iomem *)((b)+(a))) + +void ccci_clear_md_region_protection(struct ccci_modem *md); +void ccci_set_mem_access_protection(struct ccci_modem *md); +#ifdef SET_EMI_STEP_BY_STAGE +void ccci_set_mem_access_protection_1st_stage(struct ccci_modem *md); +void ccci_set_mem_access_protection_second_stage(struct ccci_modem *md); +#endif +void ccci_set_ap_region_protection(struct ccci_modem *md); +#ifdef ENABLE_DSP_SMEM_SHARE_MPU_REGION +void ccci_set_exp_region_protection(struct ccci_modem *md); +#endif +void ccci_set_mem_remap(struct ccci_modem *md, unsigned long smem_offset, phys_addr_t invalid); +unsigned int ccci_get_md_debug_mode(struct ccci_modem *md); +void ccci_get_platform_version(char *ver); +void ccci_set_dsp_region_protection(struct ccci_modem *md, int loaded); +void ccci_clear_dsp_region_protection(struct ccci_modem *md); +int ccci_plat_common_init(void); +int ccci_platform_init(struct ccci_modem *md); +void ccci_reset_ccif_hw(struct ccci_modem *md, int ccif_id, void __iomem *baseA, void __iomem *baseB); + +#ifdef ENABLE_DRAM_API +extern phys_addr_t get_max_DRAM_size(void); +extern unsigned int get_phys_offset(void); +#endif +int Is_MD_EMI_voilation(void); +#define MD_IN_DEBUG(md) (0)/* ((ccci_get_md_debug_mode(md)&(DBG_FLAG_JTAG|DBG_FLAG_DEBUG)) != 0) */ +#endif /* __CCCI_PLATFORM_H__ */ diff --git a/drivers/misc/mediatek/eccci/mt6755/ccif_c2k_platform.c b/drivers/misc/mediatek/eccci/mt6755/ccif_c2k_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..905d44a4c2d0f9db1bc67cf8f791426911bb3954 --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/ccif_c2k_platform.c @@ -0,0 +1,732 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include "ccci_config.h" +#include "ccci_modem.h" +#include "ccci_platform.h" +#include "ccif_c2k_platform.h" +#include "modem_ccif.h" +#include "modem_reg_base.h" + +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#include +#endif + +#define TAG "cif" + +#if !defined(CONFIG_MTK_CLKMGR) +#include +static struct clk *clk_scp_sys_md2_main; +static struct clk *clk_scp_sys_md3_main; +#else +#include +#endif + +#define PCCIF_BUSY (0x4) +#define PCCIF_TCHNUM (0xC) +#define PCCIF_ACK (0x14) +#define PCCIF_CHDATA (0x100) +#define PCCIF_SRAM_SIZE (512) + +static unsigned long apmixed_base; +static unsigned long apinfra_base; + +struct c2k_pll_t c2k_pll_reg; +void __iomem *ccirq_base[4]; +void __iomem *c2k_cgbr1_addr; +void __iomem *c2k_debug_reg_vir; + +void __iomem *c2k_mpu_itrace_vir; +void __iomem *c2k_wd_max_time_vir; +void __iomem *c2k_iram_base_vir; +void __iomem *c2k_h2x_zone_vir; +void __iomem *c2k_clk_base_vir; +void __iomem *c2k_pll_base_vir; +void __iomem *c2k_cgbr_sbc_vir; +void __iomem *c2k_boot_rom_vir; + +int md_ccif_get_modem_hw_info(struct platform_device *dev_ptr, + struct ccci_dev_cfg *dev_cfg, + struct md_hw_info *hw_info) +{ + struct device_node *node = NULL; + + memset(dev_cfg, 0, sizeof(struct ccci_dev_cfg)); + memset(hw_info, 0, sizeof(struct md_hw_info)); + +#ifdef CONFIG_OF + if (dev_ptr->dev.of_node == NULL) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, "modem OF node NULL\n"); + return -1; + } + + of_property_read_u32(dev_ptr->dev.of_node, "cell-index", + &dev_cfg->index); + CCCI_NORMAL_LOG(dev_cfg->index, TAG, "modem hw info get idx:%d\n", + dev_cfg->index); + if (!get_modem_is_enabled(dev_cfg->index)) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, "modem %d not enable, exit\n", + dev_cfg->index + 1); + return -1; + } +#else + struct ccci_dev_cfg *dev_cfg_ptr = + (struct ccci_dev_cfg *)dev->dev.platform_data; + dev_cfg->index = dev_cfg_ptr->index; + + CCCI_NORMAL_LOG(dev_cfg->index, TAG, "modem hw info get idx:%d\n", + dev_cfg->index); + if (!get_modem_is_enabled(dev_cfg->index)) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, "modem %d not enable, exit\n", + dev_cfg->index + 1); + return -1; + } +#endif + + switch (dev_cfg->index) { + case 1: /*MD_SYS2 */ +#ifdef CONFIG_OF + of_property_read_u32(dev_ptr->dev.of_node, "ccif,major", + &dev_cfg->major); + of_property_read_u32(dev_ptr->dev.of_node, "ccif,minor_base", + &dev_cfg->minor_base); + of_property_read_u32(dev_ptr->dev.of_node, "ccif,capability", + &dev_cfg->capability); + + hw_info->ap_ccif_base = (unsigned long)of_iomap(dev_ptr->dev.of_node, 0); + /*hw_info->md_ccif_base = hw_info->ap_ccif_base+0x1000; */ + node = of_find_compatible_node(NULL, NULL, "mediatek,MD_CCIF1"); + hw_info->md_ccif_base = (unsigned long)of_iomap(node, 0); + + hw_info->ap_ccif_irq_id = + irq_of_parse_and_map(dev_ptr->dev.of_node, 0); + hw_info->md_wdt_irq_id = + irq_of_parse_and_map(dev_ptr->dev.of_node, 1); + + /*Device tree using none flag to register irq, sensitivity has set at "irq_of_parse_and_map" */ + hw_info->ap_ccif_irq_flags = IRQF_TRIGGER_NONE; + hw_info->md_wdt_irq_flags = IRQF_TRIGGER_NONE; +#endif + + hw_info->sram_size = CCIF_SRAM_SIZE; + hw_info->md_rgu_base = MD2_RGU_BASE; + hw_info->md_boot_slave_Vector = MD2_BOOT_VECTOR; + hw_info->md_boot_slave_Key = MD2_BOOT_VECTOR_KEY; + hw_info->md_boot_slave_En = MD2_BOOT_VECTOR_EN; + +#if !defined(CONFIG_MTK_CLKMGR) + clk_scp_sys_md2_main = + devm_clk_get(&dev_ptr->dev, "scp-sys-md2-main"); + if (IS_ERR(clk_scp_sys_md2_main)) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, + "modem %d get scp-sys-md2-main failed\n", + dev_cfg->index + 1); + return -1; + } +#endif + break; + case 2: /*MD_SYS3 */ +#ifdef CONFIG_OF + dev_cfg->major = 0; + dev_cfg->minor_base = 0; + of_property_read_u32(dev_ptr->dev.of_node, "ccif,capability", + &dev_cfg->capability); + + hw_info->ap_ccif_base = (unsigned long)of_iomap(dev_ptr->dev.of_node, 0); + /*hw_info->md_ccif_base = hw_info->ap_ccif_base+0x1000; */ + node = of_find_compatible_node(NULL, NULL, "mediatek,md_ccif1"); + hw_info->md_ccif_base = (unsigned long)of_iomap(node, 0); + + hw_info->ap_ccif_irq_id = + irq_of_parse_and_map(dev_ptr->dev.of_node, 0); + hw_info->md_wdt_irq_id = + irq_of_parse_and_map(dev_ptr->dev.of_node, 1); + + /*Device tree using none flag to register irq, sensitivity has set at "irq_of_parse_and_map" */ + hw_info->ap_ccif_irq_flags = IRQF_TRIGGER_NONE; + hw_info->md_wdt_irq_flags = IRQF_TRIGGER_NONE; + + hw_info->md1_pccif_base = + (unsigned long)of_iomap(dev_ptr->dev.of_node, 1); + hw_info->md3_pccif_base = + (unsigned long)of_iomap(dev_ptr->dev.of_node, 2); + + node = + of_find_compatible_node(NULL, NULL, "mediatek,infracfg_ao"); + hw_info->infra_ao_base = (unsigned long)of_iomap(node, 0); + + node = of_find_compatible_node(NULL, NULL, "mediatek,sleep"); + hw_info->sleep_base = (unsigned long)of_iomap(node, 0); + + node = of_find_compatible_node(NULL, NULL, "mediatek,toprgu"); + hw_info->toprgu_base = (unsigned long)of_iomap(node, 0); + + node = of_find_compatible_node(NULL, NULL, "mediatek,apmixed"); + apmixed_base = (unsigned long)of_iomap(node, 0); + node = of_find_compatible_node(NULL, NULL, "mediatek,infracfg"); + apinfra_base = (unsigned long)of_iomap(node, 0); + + CCCI_NORMAL_LOG(dev_cfg->index, TAG, + "infra_ao_base=0x%lx, sleep_base=0x%lx, toprgu_base=0x%lx\n", + hw_info->infra_ao_base, hw_info->sleep_base, + hw_info->toprgu_base); + +#endif + + hw_info->sram_size = CCIF_SRAM_SIZE; + hw_info->md_rgu_base = MD3_RGU_BASE; + +#if !defined(CONFIG_MTK_CLKMGR) + clk_scp_sys_md3_main = + devm_clk_get(&dev_ptr->dev, "scp-sys-md2-main"); + if (IS_ERR(clk_scp_sys_md3_main)) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, + "modem %d get scp-sys-md2-main failed\n", + dev_cfg->index + 1); + return -1; + } +#endif + + /*no boot slave for md3 */ + /* + hw_info->md_boot_slave_Vector = MD3_BOOT_VECTOR; + hw_info->md_boot_slave_Key = MD3_BOOT_VECTOR_KEY; + hw_info->md_boot_slave_En = MD3_BOOT_VECTOR_EN; + */ + break; + default: + return -1; + } + + CCCI_NORMAL_LOG(dev_cfg->index, TAG, + "modem ccif of node get dev_major:%d\n", dev_cfg->major); + CCCI_NORMAL_LOG(dev_cfg->index, TAG, + "modem ccif of node get minor_base:%d\n", + dev_cfg->minor_base); + CCCI_NORMAL_LOG(dev_cfg->index, TAG, + "modem ccif of node get capability:%d\n", + dev_cfg->capability); + + CCCI_NORMAL_LOG(dev_cfg->index, TAG, "ap_ccif_base:0x%p\n", + (void *)hw_info->ap_ccif_base); + CCCI_NORMAL_LOG(dev_cfg->index, TAG, "ccif_irq_id:%d\n", + hw_info->ap_ccif_irq_id); + CCCI_NORMAL_LOG(dev_cfg->index, TAG, "md_wdt_irq_id:%d\n", + hw_info->md_wdt_irq_id); + + return 0; +} + +int md_ccif_io_remap_md_side_register(struct ccci_modem *md) +{ + struct md_ccif_ctrl *md_ctrl = (struct md_ccif_ctrl *)md->private_data; + + switch (md->index) { + case MD_SYS2: + md_ctrl->md_boot_slave_Vector = + ioremap_nocache(md_ctrl->hw_info->md_boot_slave_Vector, + 0x4); + md_ctrl->md_boot_slave_Key = + ioremap_nocache(md_ctrl->hw_info->md_boot_slave_Key, 0x4); + md_ctrl->md_boot_slave_En = + ioremap_nocache(md_ctrl->hw_info->md_boot_slave_En, 0x4); + md_ctrl->md_rgu_base = + ioremap_nocache(md_ctrl->hw_info->md_rgu_base, 0x40); + break; + case MD_SYS3: + c2k_pll_reg.c2k_pll_con3 = ioremap_nocache(C2KSYS_BASE + C2K_C2K_PLL_CON3, 0x4); + c2k_pll_reg.c2k_pll_con2 = ioremap_nocache(C2KSYS_BASE + C2K_C2K_PLL_CON2, 0x4); + c2k_pll_reg.c2k_plltd_con0 = ioremap_nocache(C2KSYS_BASE + C2K_C2K_PLLTD_CON0, 0x4); + c2k_pll_reg.c2k_cppll_con0 = ioremap_nocache(C2KSYS_BASE + C2K_C2K_CPPLL_CON0, 0x4); + c2k_pll_reg.c2k_dsppll_con0 = ioremap_nocache(C2KSYS_BASE + C2K_C2K_DSPPLL_CON0, 0x4); + c2k_pll_reg.c2k_c2kpll1_con0 = ioremap_nocache(C2KSYS_BASE + C2K_C2K_C2KPLL1_CON0, 0x4); + c2k_pll_reg.c2k_cg_amba_clksel = ioremap_nocache(C2KSYS_BASE + C2K_CG_ARM_AMBA_CLKSEL, 0x4); + c2k_pll_reg.c2k_clk_ctrl4 = ioremap_nocache(C2KSYS_BASE + C2K_CLK_CTRL4, 0x4); + c2k_pll_reg.c2k_clk_ctrl9 = ioremap_nocache(C2KSYS_BASE + C2K_CLK_CTRL9, 0x4); + /*CCIRQ reg*/ + ccirq_base[0] = ioremap_nocache(L1_C2K_CCIRQ_BASE, 0x100); + ccirq_base[1] = ioremap_nocache(C2K_L1_CCIRQ_BASE, 0x100); + ccirq_base[2] = ioremap_nocache(PS_C2K_CCIRQ_BASE, 0x100); + ccirq_base[3] = ioremap_nocache(C2K_PS_CCIRQ_BASE, 0x100); + + c2k_cgbr1_addr = ioremap_nocache(C2KSYS_BASE + C2K_CGBR1, 0x4); + c2k_debug_reg_vir = ioremap_nocache(C2KSYS_BASE + C2K_DEBUG_REG, 0x10); + + c2k_mpu_itrace_vir = ioremap_nocache(C2KSYS_BASE + C2K_MPU_ITRACE, 0x100); + c2k_wd_max_time_vir = ioremap_nocache(C2KSYS_BASE + C2K_WD_MAX_TIME, 0x4); + c2k_iram_base_vir = ioremap_nocache(C2KSYS_BASE + C2K_IRAM_BASE, C2K_IRAM_DUMP_SIZE); + c2k_h2x_zone_vir = ioremap_nocache(C2KSYS_BASE + C2K_H2X_ZONE_BASE, 0x1000); + c2k_clk_base_vir = ioremap_nocache(C2KSYS_BASE + C2K_CLK_BASE, 0x1000); + c2k_pll_base_vir = ioremap_nocache(C2KSYS_BASE + C2K_PLL_BASE, 0x1000); + c2k_cgbr_sbc_vir = ioremap_nocache(C2KSYS_BASE + C2K_CGBR_SBC_BASE, 0x1000); + c2k_boot_rom_vir = ioremap_nocache(C2K_BOOT_ROM_BASE, 0x1000); + + break; + } + return 0; +} + +static int config_c2k_pll(void) +{ + ccif_write16(c2k_pll_reg.c2k_pll_con3, 0, 0x8805); + ccif_write16(c2k_pll_reg.c2k_pll_con3, 0, 0x0005); + ccif_write16(c2k_pll_reg.c2k_pll_con3, 0, 0x0001); + ccif_write16(c2k_pll_reg.c2k_pll_con2, 0, 0x0); + ccif_write16(c2k_pll_reg.c2k_plltd_con0, 0, 0x0010); + + ccif_write16(c2k_pll_reg.c2k_cppll_con0, 0, + ccif_read16(c2k_pll_reg.c2k_cppll_con0, 0) | (0x1 << 15)); + /* ccif_write16(c2k_pll_reg.c2k_dsppll_con0, 0, + ccif_read16(c2k_pll_reg.c2k_dsppll_con0, 0) | (0x1 << 15)); */ + ccif_write16(c2k_pll_reg.c2k_cg_amba_clksel, 0, + ccif_read16(c2k_pll_reg.c2k_cg_amba_clksel, 0) | (0x1 << 15)); + + udelay(30); + + ccif_write16(c2k_pll_reg.c2k_cg_amba_clksel, 0, 0xC124); + ccif_write16(c2k_pll_reg.c2k_clk_ctrl4, 0, 0x8E43); + ccif_write16(c2k_pll_reg.c2k_clk_ctrl9, 0, 0xA207); + + + return 0; +} + +static int reset_ccirq_hardware(void) +{ + int i = 0; + + CCCI_NORMAL_LOG(MD_SYS3, TAG, "reset_ccirq_hardware start\n"); + for (i = 0; i < 2; i++) { + ccif_write32(ccirq_base[i], 0x4, 0xA00000FF); + ccif_write32(ccirq_base[i], 0xC, 0xA00000FF); + } + for (i = 2; i < 4; i++) { + ccif_write32(ccirq_base[i], 0x4, 0xA000000F); + ccif_write32(ccirq_base[i], 0xC, 0xA000000F); + } + + for (i = 0; i < 4; i++) { + ccif_write32(ccirq_base[i], 0x40, 0x0); + ccif_write32(ccirq_base[i], 0x44, 0x0); + ccif_write32(ccirq_base[i], 0x48, 0x0); + ccif_write32(ccirq_base[i], 0x4C, 0x0); + } + CCCI_NORMAL_LOG(MD_SYS3, TAG, "reset_ccirq_hardware end\n"); + return 0; +} + +/*need modify according to dummy ap*/ +int md_ccif_let_md_go(struct ccci_modem *md) +{ + struct md_ccif_ctrl *md_ctrl = (struct md_ccif_ctrl *)md->private_data; + + if (MD_IN_DEBUG(md)) { + CCCI_BOOTUP_LOG(md->index, TAG, "DBG_FLAG_JTAG is set\n"); + return -1; + } + CCCI_BOOTUP_LOG(md->index, TAG, "md_ccif_let_md_go\n"); + switch (md->index) { + case MD_SYS2: + /*set the start address to let modem to run */ + /*make boot vector programmable */ + ccif_write32(md_ctrl->md_boot_slave_Key, 0, MD2_BOOT_VECTOR_KEY_VALUE); + /*after remap, MD ROM address is 0 from MD's view */ + ccif_write32(md_ctrl->md_boot_slave_Vector, 0, MD2_BOOT_VECTOR_VALUE); + /*make boot vector take effect */ + ccif_write32(md_ctrl->md_boot_slave_En, 0, MD2_BOOT_VECTOR_EN_VALUE); + break; + case MD_SYS3: + /*check if meta mode */ + if (is_meta_mode() || get_boot_mode() == FACTORY_BOOT) { + ccif_write32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG, + (ccif_read32 + (md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG) | ETS_SEL_BIT)); + } + /*step 1: set C2K boot mode */ + /* + ccif_write32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG, + (ccif_read32 + (md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG) & (~(0x7 << 8))) | (0x5 << 8)); + */ + ccif_write32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG, + (ccif_read32 + (md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG)) | (0x1 << 3)); + + ccif_write32(md_ctrl->hw_info->sleep_base, AP_POWERON_CONFIG_EN, + 0x0B160001); + + ccif_write32(md_ctrl->hw_info->sleep_base, SLEEP_CLK_CON, + ccif_read32(md_ctrl->hw_info->sleep_base, + SLEEP_CLK_CON) | 0xc); + + while (((ccif_read32 + (md_ctrl->hw_info->sleep_base, AP_PWR_STATUS) & (0x1 << 28)) != (0x1 << 28)) || + ((ccif_read32 + (md_ctrl->hw_info->sleep_base, AP_PWR_STATUS_2ND) & (0x1 << 28)) != (0x1 << 28))) + ; + + CCCI_BOOTUP_LOG(md->index, TAG, "[C2K] AP_PWR_STATUS = 0x%x\n", + ccif_read32(md_ctrl->hw_info->sleep_base, AP_PWR_STATUS)); + CCCI_BOOTUP_LOG(md->index, TAG, "[C2K] AP_PWR_STATUS_2ND = 0x%x\n", + ccif_read32(md_ctrl->hw_info->sleep_base, AP_PWR_STATUS_2ND)); + + ccif_write32(md_ctrl->hw_info->sleep_base, SLEEP_CLK_CON, + ccif_read32(md_ctrl->hw_info->sleep_base, + SLEEP_CLK_CON) & (~(0x1 << PWR_CLK_DIS))); + ccif_write32(md_ctrl->hw_info->sleep_base, SLEEP_CLK_CON, + ccif_read32(md_ctrl->hw_info->sleep_base, + SLEEP_CLK_CON) & (~(0x1 << PWR_ISO))); + ccif_write32(md_ctrl->hw_info->sleep_base, SLEEP_CLK_CON, + ccif_read32(md_ctrl->hw_info->sleep_base, + SLEEP_CLK_CON) | (0x1 << PWR_RST_B)); + CCCI_BOOTUP_LOG(md->index, TAG, "SLEEP_CLK_CON = 0x%x\n", + ccif_read32(md_ctrl->hw_info->sleep_base, + SLEEP_CLK_CON)); + + /*step 2: config srcclkena selection mask */ + ccif_write32(md_ctrl->hw_info->infra_ao_base, INFRA_MISC2, + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_MISC2) | INFRA_MISC2_C2K_EN); + CCCI_BOOTUP_LOG(md->index, TAG, "INFRA_MISC2 = 0x%x\n", + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_MISC2)); + + + /*step 3: PMIC VTCXO_1 enable */ + /*pmic_config_interface(0x0A02, 0xA12E, 0xFFFF, 0x0);*/ + + /* ccif_write32(apmixed_base, AP_PLL_CON0, + ccif_read32(apmixed_base, + AP_PLL_CON0) | (0x1 << 1)); */ + CCCI_BOOTUP_LOG(md->index, TAG, "AP_PLL_CON0 = 0x%x\n", + ccif_read32(apmixed_base, AP_PLL_CON0)); + + /*ap hold c2k core*/ + /* + ccif_write32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG, + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG) | (0x1 << 1)); + */ + CCCI_BOOTUP_LOG(md->index, TAG, "C2K_CONFIG = 0x%x\n", + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG)); + + /*step 4: wake up C2K */ + /* + ccif_write32(apmixed_base, MDPLL1_CON0, + ccif_read32(apmixed_base, + MDPLL1_CON0) & (~(0x1 << 9))); + CCCI_NORMAL_LOG(md->index, TAG, "MDPLL1_CON0 = 0x%x\n", + ccif_read32(apmixed_base, MDPLL1_CON0)); + */ + +#if 1 + ccif_write32(md_ctrl->hw_info->toprgu_base, + TOP_RGU_WDT_SWSYSRST, + (ccif_read32 + (md_ctrl->hw_info->toprgu_base, + TOP_RGU_WDT_SWSYSRST) | 0x88000000) & (~(0x1 << + 15))); +#else + mtk_wdt_set_c2k_sysrst(1); +#endif + CCCI_BOOTUP_LOG(md->index, TAG, + "[C2K] TOP_RGU_WDT_SWSYSRST = 0x%x\n", + ccif_read32(md_ctrl->hw_info->toprgu_base, + TOP_RGU_WDT_SWSYSRST)); + + /*step 5: mpu already set */ + /*step 6: wake up C2K */ + ccif_write32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_SPM_CTRL, + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_SPM_CTRL) | (0x1 << 1)); + + ccif_write32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_CONFIG, + (ccif_read32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_CONFIG) & + (~(0x3 << 11)))); + while (! + ((ccif_read32 + (md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_STATUS) >> 1) & 0x1)) + ; + + CCCI_BOOTUP_LOG(md->index, TAG, + "[C2K] C2K_STATUS = 0x%x\n", + ccif_read32(md_ctrl->hw_info-> + infra_ao_base, + INFRA_AO_C2K_STATUS)); + + ccif_write32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_SPM_CTRL, + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_SPM_CTRL) & (~(0x1 << 1))); + CCCI_BOOTUP_LOG(md->index, TAG, + "[C2K] C2K_SPM_CTRL = 0x%x, C2K_STATUS = 0x%x\n", + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_SPM_CTRL), + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_STATUS)); + + ccif_write32(md_ctrl->hw_info->infra_ao_base, + INFRA_TOPAXI_PROTECTEN_1, + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_TOPAXI_PROTECTEN_1) & (~(0x3 << 22))); + + while (ccif_read32(c2k_cgbr1_addr, 0) != 0xFE8) + ; + CCCI_BOOTUP_LOG(md->index, TAG, + "[C2K] C2K_CGBR1 = 0x%x\n", ccif_read32(c2k_cgbr1_addr, 0)); + + /*configure c2k debug reg*/ + ccif_write32(c2k_debug_reg_vir, 0, 0xB); + ccif_write32(c2k_debug_reg_vir, 4, 0x5B); + + /*set c2k pll*/ + config_c2k_pll(); + + /*release c2k arm core*/ + /* + ccif_write32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG, + ccif_read32(md_ctrl->hw_info->infra_ao_base, + INFRA_AO_C2K_CONFIG) & (~(0x1 << 1))); + */ + break; + } + return 0; +} + +int md_ccif_power_on(struct ccci_modem *md) +{ + int ret = 0; + struct md_ccif_ctrl *md_ctrl = (struct md_ccif_ctrl *)md->private_data; + + switch (md->index) { + case MD_SYS2: +#if defined(CONFIG_MTK_CLKMGR) + CCCI_NORMAL_LOG(md->index, TAG, "Call start md_power_on()\n"); + ret = md_power_on(SYS_MD2); + CCCI_NORMAL_LOG(md->index, TAG, "Call end md_power_on() ret=%d\n", + ret); +#else + CCCI_NORMAL_LOG(md->index, TAG, + "Call start clk_prepare_enable()\n"); + clk_prepare_enable(clk_scp_sys_md2_main); + CCCI_NORMAL_LOG(md->index, TAG, "Call end clk_prepare_enable()\n"); +#endif + break; + case MD_SYS3: +#if defined(CONFIG_MTK_CLKMGR) + CCCI_NORMAL_LOG(md->index, TAG, "Call start md_power_on()\n"); + ret = md_power_on(SYS_MD2); + CCCI_NORMAL_LOG(md->index, TAG, "Call end md_power_on() ret=%d\n", + ret); +#else + CCCI_NORMAL_LOG(md->index, TAG, + "Call start clk_prepare_enable()\n"); + clk_prepare_enable(clk_scp_sys_md3_main); + CCCI_NORMAL_LOG(md->index, TAG, "Call end clk_prepare_enable()\n"); +#endif + kicker_pbm_by_md(KR_MD3, true); + CCCI_NORMAL_LOG(md->index, TAG, "Call end kicker_pbm_by_md(3,true)\n"); + break; + } + CCCI_BOOTUP_LOG(md->index, TAG, "md_ccif_power_on:ret=%d\n", ret); + if (ret == 0 && md->index != MD_SYS3) { + /*disable MD WDT */ + ccif_write32(md_ctrl->md_rgu_base, WDT_MD_MODE, + WDT_MD_MODE_KEY); + } + return ret; +} + +int md_ccif_power_off(struct ccci_modem *md, unsigned int stop_type) +{ + int ret = 0; +#if defined(CONFIG_MTK_CLKMGR) + unsigned int timeout = 0; + + if (stop_type == MD_FLIGHT_MODE_ENTER) + timeout = 1000; +#endif + + switch (md->index) { + case MD_SYS2: +#if defined(CONFIG_MTK_CLKMGR) + ret = md_power_off(SYS_MD2, timeout); +#else + clk_disable_unprepare(clk_scp_sys_md2_main); +#endif + break; + case MD_SYS3: +#if defined(CONFIG_MTK_CLKMGR) + ret = md_power_off(SYS_MD3, timeout); +#else + clk_disable_unprepare(clk_scp_sys_md3_main); +#endif + kicker_pbm_by_md(KR_MD3, false); + CCCI_NORMAL_LOG(md->index, TAG, "Call end kicker_pbm_by_md(3,false)\n"); + break; + } + CCCI_NORMAL_LOG(md->index, TAG, "md_ccif_power_off:ret=%d\n", ret); + return ret; +} + +void reset_md1_md3_pccif(struct ccci_modem *md) +{ + struct md_ccif_ctrl *md_ctrl = (struct md_ccif_ctrl *)md->private_data; + struct md_hw_info *hw_info = md_ctrl->hw_info; + + reset_ccirq_hardware(); + + ccci_reset_ccif_hw(md, MD1_MD3_CCIF, (void __iomem *)hw_info->md1_pccif_base, + (void __iomem *)hw_info->md3_pccif_base); + + /*clear md1 md3 shared memory*/ + if (md->mem_layout.md1_md3_smem_vir != NULL) + memset_io(md->mem_layout.md1_md3_smem_vir, 0, md->mem_layout.md1_md3_smem_size); + +} + +void dump_c2k_register(struct ccci_modem *md, unsigned int dump_flag) +{ + struct md_ccif_ctrl *md_ctrl = (struct md_ccif_ctrl *)md->private_data; + u32 i, j; + unsigned long reg_base; + + /*start addr, reg count, end must be {0, 0}*/ + u32 h2x_reg[][2] = { {0x3C, 8}, {0, 0} }; + u32 cgbr_sbc_reg[][2] = { {0x0, 7}, {0xF0, 3}, {0x10c, 3}, {0x200, 11}, {0, 0} }; + u32 clk_ctrl_reg[][2] = { {0x0, 5}, {0x64, 1}, {0x234, 1}, {0x25c, 1}, {0x268, 4}, + {0x29c, 1}, {0x300, 3}, {0, 0} }; + u32 pll_reg[][2] = { {0x0, 24}, {0, 0} }; + + CCCI_MEM_LOG_TAG(md->index, TAG, "INFRA_C2K_BOOT_STATUS = 0x%x\n", + ccif_read32(apinfra_base, INFRA_C2K_BOOT_STATUS)); + CCCI_MEM_LOG_TAG(md->index, TAG, "INFRA_C2K_BOOT_STATUS2 = 0x%x\n", + ccif_read32(apinfra_base, INFRA_C2K_BOOT_STATUS2)); + + CCCI_MEM_LOG_TAG(md->index, TAG, "C2K_CONFIG = 0x%x\n", + ccif_read32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_CONFIG)); + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] AP_PWR_STATUS = 0x%x\n", + ccif_read32(md_ctrl->hw_info->sleep_base, AP_PWR_STATUS)); + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] AP_PWR_STATUS_2ND = 0x%x\n", + ccif_read32(md_ctrl->hw_info->sleep_base, AP_PWR_STATUS_2ND)); + + CCCI_MEM_LOG_TAG(md->index, TAG, "SLEEP_CLK_CON = 0x%x\n", + ccif_read32(md_ctrl->hw_info->sleep_base, SLEEP_CLK_CON)); + CCCI_MEM_LOG_TAG(md->index, TAG, "INFRA_MISC2 = 0x%x\n", + ccif_read32(md_ctrl->hw_info->infra_ao_base, INFRA_MISC2)); + + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] C2K_SPM_CTRL = 0x%x, C2K_STATUS = 0x%x\n", + ccif_read32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_SPM_CTRL), + ccif_read32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_STATUS)); + + if (dump_flag == 0) + return; + + /* wdt EE, flag = 1*/ + if (dump_flag == 0x1) { + CCCI_MEM_LOG_TAG(md->index, TAG, "C2K_WD_TIME_MAX = 0x%x\n", + ccif_read32(c2k_wd_max_time_vir, 0)); + + return; + } + + /*default value for HS1 EE*/ + for (i = 0; i < 4; i++) { + ccif_write32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_CONFIG, + (ccif_read32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_CONFIG) & + (~(0x3 << 11))) | (i << 11)); + for (j = 0; j < 16; j++) { + CCCI_MEM_LOG_TAG(md->index, TAG, "C2K_CONFIG = 0x%x\n", + ccif_read32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_CONFIG)); + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] C2K_STATUS = 0x%x\n", + ccif_read32(md_ctrl->hw_info->infra_ao_base, INFRA_AO_C2K_STATUS)); + } + } + + reg_base = C2KSYS_BASE + C2K_MPU_ITRACE; + for (j = 0; j < C2K_MPU_ITRACE_DUMP_SIZE; ) { + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] mpu itrace 0x%lx, value = 0x%x\n", + reg_base + j, ccif_read32(c2k_mpu_itrace_vir, j)); + j += 4; + } + + reg_base = C2KSYS_BASE + C2K_H2X_ZONE_BASE; + for (i = 0; h2x_reg[i][1] != 0; i++) { + for (j = 0; j < h2x_reg[i][1]; j++) + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] reg = 0x%lx, value = 0x%x\n", + reg_base + h2x_reg[i][0] + j*4, ccif_read32(c2k_h2x_zone_vir, h2x_reg[i][0] + j*4)); + } + + reg_base = C2KSYS_BASE + C2K_CGBR_SBC_BASE; + for (i = 0; cgbr_sbc_reg[i][1] != 0; i++) { + for (j = 0; j < cgbr_sbc_reg[i][1]; j++) + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] reg = 0x%lx, value = 0x%x\n", + reg_base + cgbr_sbc_reg[i][0] + j*4, + ccif_read32(c2k_cgbr_sbc_vir, cgbr_sbc_reg[i][0] + j*4)); + } + + reg_base = C2KSYS_BASE + C2K_CLK_BASE; + for (i = 0; clk_ctrl_reg[i][1] != 0; i++) { + for (j = 0; j < clk_ctrl_reg[i][1]; j++) + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] reg = 0x%lx, value = 0x%x\n", + reg_base + clk_ctrl_reg[i][0] + j*4, + ccif_read32(c2k_clk_base_vir, clk_ctrl_reg[i][0] + j*4)); + } + + reg_base = C2KSYS_BASE + C2K_PLL_BASE; + for (i = 0; pll_reg[i][1] != 0; i++) { + for (j = 0; j < pll_reg[i][1]; j++) + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] reg = 0x%lx, value = 0x%x\n", + reg_base + pll_reg[i][0] + j*4, + ccif_read32(c2k_pll_base_vir, pll_reg[i][0] + j*4)); + } + + reg_base = C2KSYS_BASE + C2K_IRAM_BASE; + for (j = 0; j < C2K_IRAM_DUMP_SIZE; ) { + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] iram = 0x%lx, value = 0x%x\n", + reg_base + j, ccif_read32(c2k_iram_base_vir, j)); + j += 4; + } + + reg_base = C2K_BOOT_ROM_BASE; + for (j = 0; j < C2K_BOOTROM_DUMP_SIZE; ) { + CCCI_MEM_LOG_TAG(md->index, TAG, "[C2K] bootrom = 0x%lx, value = 0x%x\n", + reg_base + j, ccif_read32(c2k_boot_rom_vir, j)); + j += 4; + } + + +} + diff --git a/drivers/misc/mediatek/eccci/mt6755/ccif_c2k_platform.h b/drivers/misc/mediatek/eccci/mt6755/ccif_c2k_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..3ecff743305c18dd60f13f597836a83afe050d90 --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/ccif_c2k_platform.h @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __CCIF_PLATFORM_H__ +#define __CCIF_PLATFORM_H__ +#include "ccci_config.h" +#include "ccci_modem.h" +#include + +#define ccif_write32(b, a, v) mt_reg_sync_writel(v, (b)+(a)) +#define ccif_write16(b, a, v) mt_reg_sync_writew(v, (b)+(a)) +#define ccif_write8(b, a, v) mt_reg_sync_writeb(v, (b)+(a)) +#define ccif_read32(b, a) ioread32((void __iomem *)((b)+(a))) +#define ccif_read16(b, a) ioread16((void __iomem *)((b)+(a))) +#define ccif_read8(b, a) ioread8((void __iomem *)((b)+(a))) + +/*MD peripheral register: MD bank8; AP bank2*/ +/*Modem WDT */ +#define WDT_MD_MODE (0x00) +#define WDT_MD_LENGTH (0x04) +#define WDT_MD_RESTART (0x08) +#define WDT_MD_STA (0x0C) +#define WDT_MD_SWRST (0x1C) +#define WDT_MD_MODE_KEY (0x0000220E) + +/*CCIF */ +#define APCCIF_CON (0x00) +#define APCCIF_BUSY (0x04) +#define APCCIF_START (0x08) +#define APCCIF_TCHNUM (0x0C) +#define APCCIF_RCHNUM (0x10) +#define APCCIF_ACK (0x14) +#define APCCIF_CHDATA (0x100) + +/*C2K */ +#define INFRA_AO_C2K_CONFIG (0x360) +#define INFRA_AO_C2K_STATUS (0x364) +#define INFRA_AO_C2K_SPM_CTRL (0x368) + +#define INFRA_C2K_BOOT_STATUS (0x308) +#define INFRA_C2K_BOOT_STATUS2 (0x30c) + +#define SLEEP_CLK_CON (0x328) + +#define TOP_RGU_WDT_MODE (0x0) +#define TOP_RGU_WDT_SWRST (0x14) +#define TOP_RGU_WDT_SWSYSRST (0x18) +#define TOP_RGU_WDT_NONRST_REG (0x20) + +/* [3:0]:mdsrc_req_0_en */ +/* [7:4]:mdsrc_req_1_en */ +#define INFRA_MISC2 (0xF0C) +/* mdsrc_req_0/1_en[2]: for C2K */ +#define INFRA_MISC2_C2K_BIT (2) +#define INFRA_MISC2_C2K_EN (0x11 << INFRA_MISC2_C2K_BIT) + +/****mt6755 special****/ + +#define AP_PLL_CON0 0x0 /* ((UINT32P)(APMIXED_BASE+0x0)) */ +#define MDPLL1_CON0 0x2C8 /* ((UINT32P)(APMIXED_BASE+0x02C8)) */ + +#define INFRA_TOPAXI_PROTECTEN_1 0x250 /*((UINT32P)(INFRACFG_AO_BASE+0x250))*/ +#define AP_POWERON_CONFIG_EN 0x000 /*((UINT32P)(SLEEP_BASE+0x000))*/ +#define AP_PWR_STATUS 0x180 /*((UINT32P)(SLEEP_BASE+0x180))*/ +#define AP_PWR_STATUS_2ND 0x184 /*((UINT32P)(SLEEP_BASE+0x184))*/ +#define PWR_RST_B 0 +#define PWR_ISO 1 +#define PWR_ON 2 +#define PWR_ON_2ND 3 +#define PWR_CLK_DIS 4 +/*#define C2K 28*/ + +#define C2K_MAGIC_NUM 0xC275 + +#define C2K_SBC_KEY0 0x8B0 /* ((UINT32P)(INFRACFG_AO_BASE+0x8B0)) */ +#define C2K_SBC_KEY1 0x8B4 +#define C2K_SBC_KEY2 0x8B8 +#define C2K_SBC_KEY3 0x8BC +#define C2K_SBC_KEY4 0x8C0 +#define C2K_SBC_KEY5 0x8C4 +#define C2K_SBC_KEY6 0x8C8 +#define C2K_SBC_KEY7 0x8CC +#define C2K_SBC_KEY_LOCK 0x8D0 /*((UINT32P)(INFRACFG_AO_BASE+0x8D0))*/ + +/*** C2K side register ***/ +#define C2KSYS_BASE (0x38000000) +#define C2K_CGBR1 0x0200B004 /* (C2KSYS_BASE+0x0200B004) */ +#define C2K_C2K_PLL_CON3 0x02013008 +#define C2K_C2K_PLL_CON2 0x02013004 +#define C2K_C2K_PLLTD_CON0 0x02013074 +#define C2K_CLK_CTRL9 0x0200029C +#define C2K_CLK_CTRL4 0x02000010 +#define C2K_CG_ARM_AMBA_CLKSEL 0x02000234 +#define C2K_C2K_C2KPLL1_CON0 0x02013018 +#define C2K_C2K_CPPLL_CON0 0x02013040 +#define C2K_C2K_DSPPLL_CON0 0x02013050 +#define C2K_DEBUG_REG 0x0200B10C + +#define C2K_MPU_ITRACE 0x020050D0 +#define C2K_WD_MAX_TIME 0x02001084 +#define C2K_IRAM_BASE 0x01000000 /*0x39000000*/ +#define C2K_H2X_ZONE_BASE 0x00000000 +#define C2K_CLK_BASE 0x02000000 +#define C2K_PLL_BASE 0x02013000 +#define C2K_CGBR_SBC_BASE 0x0200B000 +#define C2K_BOOT_ROM_BASE 0x3FFF0000 +/*end of C2K side register*/ +#define C2K_IRAM_DUMP_SIZE 0x20 +#define C2K_BOOTROM_DUMP_SIZE 0x90 +#define C2K_MPU_ITRACE_DUMP_SIZE 0x20 + +#define L1_C2K_CCIRQ_BASE 0x10211400 +#define C2K_L1_CCIRQ_BASE 0x10213400 +#define PS_C2K_CCIRQ_BASE 0x10211000 +#define C2K_PS_CCIRQ_BASE 0x10213000 + +#define ETS_SEL_BIT (0x1 << 13) + +struct md_hw_info { + /*HW info - Register Address */ + unsigned long md_rgu_base; + unsigned long md_boot_slave_Vector; + unsigned long md_boot_slave_Key; + unsigned long md_boot_slave_En; + unsigned long ap_ccif_base; + unsigned long md_ccif_base; + unsigned int sram_size; + /* #ifdef CONFIG_MTK_ECCCI_C2K */ + unsigned long sleep_base; + unsigned long infra_ao_base; + unsigned long toprgu_base; + unsigned long c2k_chip_id_base; + unsigned long md1_pccif_base; + unsigned long md3_pccif_base; + /* #endif */ + + /*HW info - Interrutpt ID */ + unsigned int ap_ccif_irq_id; + unsigned int md_wdt_irq_id; + + /*HW info - Interrupt flags */ + unsigned long ap_ccif_irq_flags; + unsigned long md_wdt_irq_flags; +}; + +struct c2k_pll_t { + void __iomem *c2k_pll_con3; + void __iomem *c2k_pll_con2; + void __iomem *c2k_plltd_con0; + void __iomem *c2k_cppll_con0; + void __iomem *c2k_dsppll_con0; + void __iomem *c2k_c2kpll1_con0; + void __iomem *c2k_cg_amba_clksel; + void __iomem *c2k_clk_ctrl4; + void __iomem *c2k_clk_ctrl9; + +}; + +extern unsigned long ccci_modem_boot_count[]; + +extern int md_ccif_power_off(struct ccci_modem *md, unsigned int stop_type); +extern int md_ccif_power_on(struct ccci_modem *md); +extern int md_ccif_let_md_go(struct ccci_modem *md); +int md_ccif_get_modem_hw_info(struct platform_device *dev_ptr, + struct ccci_dev_cfg *dev_cfg, + struct md_hw_info *hw_info); +int md_ccif_io_remap_md_side_register(struct ccci_modem *md); +void reset_md1_md3_pccif(struct ccci_modem *md); +void dump_c2k_register(struct ccci_modem *md, unsigned int dump_flag); + +extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); +extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity); +extern void mtk_wdt_set_c2k_sysrst(unsigned int flag); +extern void ccci_mem_dump(int md_id, void *start_addr, int len); + +#endif /*__CLDMA_PLATFORM_H__*/ diff --git a/drivers/misc/mediatek/eccci/mt6755/cldma_platform.c b/drivers/misc/mediatek/eccci/mt6755/cldma_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..bcdfb51a6b203889abe2dd87ba63970983d72b72 --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/cldma_platform.c @@ -0,0 +1,1055 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "ccci_config.h" +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif /*CONFIG_MTK_CLKMGR */ + +#ifdef FEATURE_RF_CLK_BUF +#include +#endif +#ifdef FEATURE_INFORM_NFC_VSIM_CHANGE +#include +#endif +#include +#include +#include + +#include "ccci_core.h" +#include "ccci_platform.h" +#include "modem_cldma.h" +#include "cldma_platform.h" +#include "cldma_reg.h" +#include "modem_reg_base.h" +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#include "include/pmic_api_buck.h" +#endif +#include + +#if !defined(CONFIG_MTK_CLKMGR) +static struct clk *clk_scp_sys_md1_main; +#endif +static struct pinctrl *mdcldma_pinctrl; +void __attribute__((weak)) clk_buf_set_by_flightmode(bool is_flightmode_on) +{ +} + +#define TAG "mcd" +void md_cldma_hw_reset(struct ccci_modem *md) +{ + unsigned int reg_value; + + CCCI_DEBUG_LOG(md->index, TAG, "md_cldma_hw_reset:rst cldma\n"); + /* reset cldma hw: AO Domain */ + reg_value = ccci_read32(infra_ao_base, INFRA_RST0_REG_AO); + reg_value &= ~(CLDMA_AO_RST_MASK); /* the bits in reg is WO, */ + reg_value |= (CLDMA_AO_RST_MASK);/* so only this bit effective */ + ccci_write32(infra_ao_base, INFRA_RST0_REG_AO, reg_value); + CCCI_BOOTUP_LOG(md->index, TAG, "md_cldma_hw_reset:clear reset\n"); + /* reset cldma clr */ + reg_value = ccci_read32(infra_ao_base, INFRA_RST1_REG_AO); + reg_value &= ~(CLDMA_AO_RST_MASK);/* read no use, maybe a time delay */ + reg_value |= (CLDMA_AO_RST_MASK); + ccci_write32(infra_ao_base, INFRA_RST1_REG_AO, reg_value); + CCCI_BOOTUP_LOG(md->index, TAG, "md_cldma_hw_reset:done\n"); + + /* reset cldma hw: PD Domain */ + reg_value = ccci_read32(infra_ao_base, INFRA_RST0_REG_PD); + reg_value &= ~(CLDMA_PD_RST_MASK); + reg_value |= (CLDMA_PD_RST_MASK); + ccci_write32(infra_ao_base, INFRA_RST0_REG_PD, reg_value); + CCCI_BOOTUP_LOG(md->index, TAG, "md_cldma_hw_reset:clear reset\n"); + /* reset cldma clr */ + reg_value = ccci_read32(infra_ao_base, INFRA_RST1_REG_PD); + reg_value &= ~(CLDMA_PD_RST_MASK); + reg_value |= (CLDMA_PD_RST_MASK); + ccci_write32(infra_ao_base, INFRA_RST1_REG_PD, reg_value); + CCCI_DEBUG_LOG(md->index, TAG, "md_cldma_hw_reset:done\n"); +} + +int md_cd_get_modem_hw_info(struct platform_device *dev_ptr, struct ccci_dev_cfg *dev_cfg, struct md_hw_info *hw_info) +{ + struct device_node *node = NULL; + + memset(dev_cfg, 0, sizeof(struct ccci_dev_cfg)); + memset(hw_info, 0, sizeof(struct md_hw_info)); + + if (dev_ptr->dev.of_node == NULL) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, "modem OF node NULL\n"); + return -1; + } + + of_property_read_u32(dev_ptr->dev.of_node, "mediatek,md_id", &dev_cfg->index); + CCCI_DEBUG_LOG(dev_cfg->index, TAG, "modem hw info get idx:%d\n", dev_cfg->index); + if (!get_modem_is_enabled(dev_cfg->index)) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, "modem %d not enable, exit\n", dev_cfg->index + 1); + return -1; + } + + switch (dev_cfg->index) { + case 0: /* MD_SYS1 */ + dev_cfg->major = 0; + dev_cfg->minor_base = 0; + of_property_read_u32(dev_ptr->dev.of_node, "mediatek,cldma_capability", &dev_cfg->capability); + + hw_info->cldma_ap_ao_base = (unsigned long)of_iomap(dev_ptr->dev.of_node, 0); + hw_info->cldma_md_ao_base = (unsigned long)of_iomap(dev_ptr->dev.of_node, 1); + hw_info->cldma_ap_pdn_base = (unsigned long)of_iomap(dev_ptr->dev.of_node, 2); + hw_info->cldma_md_pdn_base = (unsigned long)of_iomap(dev_ptr->dev.of_node, 3); + hw_info->ap_ccif_base = (unsigned long)of_iomap(dev_ptr->dev.of_node, 4); + hw_info->md_ccif_base = (unsigned long)of_iomap(dev_ptr->dev.of_node, 5); + hw_info->cldma_irq_id = irq_of_parse_and_map(dev_ptr->dev.of_node, 0); + hw_info->ap_ccif_irq_id = irq_of_parse_and_map(dev_ptr->dev.of_node, 1); + hw_info->md_wdt_irq_id = irq_of_parse_and_map(dev_ptr->dev.of_node, 2); + + /* Device tree using none flag to register irq, sensitivity has set at "irq_of_parse_and_map" */ + hw_info->cldma_irq_flags = IRQF_TRIGGER_NONE; + hw_info->ap_ccif_irq_flags = IRQF_TRIGGER_NONE; + hw_info->md_wdt_irq_flags = IRQF_TRIGGER_NONE; + hw_info->ap2md_bus_timeout_irq_flags = IRQF_TRIGGER_NONE; + + hw_info->sram_size = CCIF_SRAM_SIZE; + hw_info->md_rgu_base = MD_RGU_BASE; + hw_info->l1_rgu_base = L1_RGU_BASE; + hw_info->md_boot_slave_En = MD_BOOT_VECTOR_EN; +#if !defined(CONFIG_MTK_CLKMGR) + mdcldma_pinctrl = devm_pinctrl_get(&dev_ptr->dev); + if (IS_ERR(mdcldma_pinctrl)) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, "modem %d get mdcldma_pinctrl failed\n", + dev_cfg->index + 1); + return -1; + } + clk_scp_sys_md1_main = devm_clk_get(&dev_ptr->dev, "scp-sys-md1-main"); + if (IS_ERR(clk_scp_sys_md1_main)) { + CCCI_ERROR_LOG(dev_cfg->index, TAG, "modem %d get scp-sys-md1-main failed\n", + dev_cfg->index + 1); + return -1; + } +#endif + node = of_find_compatible_node(NULL, NULL, "mediatek,APMIXED"); + hw_info->ap_mixed_base = (unsigned long)of_iomap(node, 0); + break; + default: + return -1; + } + + CCCI_DEBUG_LOG(dev_cfg->index, TAG, "dev_major:%d,minor_base:%d,capability:%d\n", + dev_cfg->major, + dev_cfg->minor_base, dev_cfg->capability); + CCCI_DEBUG_LOG(dev_cfg->index, TAG, + "ap_cldma: ao_base=0x%p, pdn_base=0x%p,md_cldma: ao_base=0x%p, pdn_base=0x%p\n", + (void *)hw_info->cldma_ap_ao_base, (void *)hw_info->cldma_ap_pdn_base, + (void *)hw_info->cldma_md_ao_base, (void *)hw_info->cldma_md_pdn_base); + + CCCI_DEBUG_LOG(dev_cfg->index, TAG, "ap_ccif_base:0x%p, md_ccif_base:0x%p\n", + (void *)hw_info->ap_ccif_base, (void *)hw_info->md_ccif_base); + CCCI_DEBUG_LOG(dev_cfg->index, TAG, "cldma_irq:%d,ccif_irq:%d,md_wdt_irq:%d\n", + hw_info->cldma_irq_id, hw_info->ap_ccif_irq_id, hw_info->md_wdt_irq_id); + + return 0; +} + +int md_cd_io_remap_md_side_register(struct ccci_modem *md) +{ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + struct md_pll_reg *md_reg; + + md_ctrl->cldma_ap_pdn_base = (void __iomem *)(md_ctrl->hw_info->cldma_ap_pdn_base); + md_ctrl->cldma_ap_ao_base = (void __iomem *)(md_ctrl->hw_info->cldma_ap_ao_base); + md_ctrl->cldma_md_pdn_base = (void __iomem *)(md_ctrl->hw_info->cldma_md_pdn_base); + md_ctrl->cldma_md_ao_base = (void __iomem *)(md_ctrl->hw_info->cldma_md_ao_base); + md_ctrl->md_boot_slave_En = ioremap_nocache(md_ctrl->hw_info->md_boot_slave_En, 0x4); + md_ctrl->md_rgu_base = ioremap_nocache(md_ctrl->hw_info->md_rgu_base, 0x300); + md_ctrl->l1_rgu_base = ioremap_nocache(md_ctrl->hw_info->l1_rgu_base, 0x40); + md_ctrl->md_global_con0 = ioremap_nocache(MD_GLOBAL_CON0, 0x4); + + md_ctrl->md_bus_status = ioremap_nocache(MD_BUS_STATUS_BASE, MD_BUS_STATUS_LENGTH); + /* md_ctrl->md_pc_monitor = ioremap_nocache(MD_PC_MONITOR_BASE, MD_PC_MONITOR_LENGTH); */ + md_ctrl->md_topsm_status = ioremap_nocache(MD_TOPSM_STATUS_BASE, MD_TOPSM_STATUS_LENGTH); + md_ctrl->md_ost_status = ioremap_nocache(MD_OST_STATUS_BASE, MD_OST_STATUS_LENGTH); + /* md_ctrl->md_pll = ioremap_nocache(MD_PLL_BASE, MD_PLL_LENGTH); */ + + md_reg = kzalloc(sizeof(struct md_pll_reg), GFP_KERNEL); + if (md_reg == NULL) { + CCCI_ERROR_LOG(-1, TAG, "cldma_sw_init:alloc md reg map mem fail\n"); + return -1; + } + md_reg->md_pc_mon1 = ioremap_nocache(MD_PC_MONITOR_BASE, MD_PC_MONITOR_LENGTH); + md_ctrl->md_pc_monitor = md_reg->md_pc_mon1; + md_reg->md_pc_mon2 = ioremap_nocache(MD_PC_MONITORL1_BASE, MD_PC_MONITORL1_LENGTH); + md_reg->md_clkSW = ioremap_nocache(MD_CLKSW_BASE, MD_CLKSW_LENGTH); + md_reg->md_dcm = ioremap_nocache(MD_GLOBAL_CON_DCM_BASE, MD_GLOBAL_CON_DCM_LEN); + md_reg->psmcu_misc = ioremap_nocache(PSMCU_MISC_BASE, 4); + md_reg->md_peri_misc = ioremap_nocache(MD_PERI_MISC_BASE, MD_PERI_MISC_LEN); + md_reg->md_L1_a0 = ioremap_nocache(MDL1A0_BASE, MDL1A0_LEN); + md_reg->md_top_Pll = ioremap_nocache(MDTOP_PLLMIXED_BASE, 4); + md_reg->md_sys_clk = ioremap_nocache(MDSYS_CLKCTL_BASE, MDSYS_CLKCTL_LEN); + /*md_reg->md_l1_conf = ioremap_nocache(L1_BASE_MADDR_MDL1_CONF, 4);*/ + + md_reg->md_busreg1 = ioremap_nocache(MD_BUSREG_DUMP_ADDR1, MD_BUSREG_DUMP_LEN1); + md_reg->md_busreg2 = ioremap_nocache(MD_BUSREG_DUMP_ADDR2, MD_BUSREG_DUMP_LEN2); + md_reg->md_busrec = ioremap_nocache(MD_BUSREC_DUMP_ADDR, MD_BUSREC_DUMP_LEN); + md_reg->md_ect_0 = ioremap_nocache(MD_ECT_DUMP_ADDR0, MD_ECT_DUMP_LEN0); + md_reg->md_ect_1 = ioremap_nocache(MD_ECT_DUMP_ADDR1, MD_ECT_DUMP_LEN1); + md_reg->md_ect_2 = ioremap_nocache(MD_ECT_DUMP_ADDR2, MD_ECT_DUMP_LEN2); + md_reg->md_ect_3 = ioremap_nocache(MD_ECT_DUMP_ADDR3, MD_ECT_DUMP_LEN3); + md_reg->md_bootup_0 = ioremap_nocache(MD_Bootup_DUMP_ADDR0, MD_Bootup_DUMP_LEN0); + md_reg->md_bootup_1 = ioremap_nocache(MD_Bootup_DUMP_ADDR1, MD_Bootup_DUMP_LEN1); + md_reg->md_bootup_2 = ioremap_nocache(MD_Bootup_DUMP_ADDR2, MD_Bootup_DUMP_LEN2); + md_reg->md_bootup_3 = ioremap_nocache(MD_Bootup_DUMP_ADDR3, MD_Bootup_DUMP_LEN3); + md_reg->md_clk_ctl01 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR01, MD_Clkctrl_DUMP_LEN01); + md_reg->md_clk_ctl02 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR02, MD_Clkctrl_DUMP_LEN02); + md_reg->md_clk_ctl03 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR03, MD_Clkctrl_DUMP_LEN03); + md_reg->md_clk_ctl04 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR04, MD_Clkctrl_DUMP_LEN04); + md_reg->md_clk_ctl05 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR05, MD_Clkctrl_DUMP_LEN05); + md_reg->md_clk_ctl06 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR06, MD_Clkctrl_DUMP_LEN06); + md_reg->md_clk_ctl07 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR07, MD_Clkctrl_DUMP_LEN07); + md_reg->md_clk_ctl08 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR08, MD_Clkctrl_DUMP_LEN08); + md_reg->md_clk_ctl09 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR09, MD_Clkctrl_DUMP_LEN09); + md_reg->md_clk_ctl10 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR10, MD_Clkctrl_DUMP_LEN10); + md_reg->md_clk_ctl11 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR11, MD_Clkctrl_DUMP_LEN11); + md_reg->md_clk_ctl12 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR12, MD_Clkctrl_DUMP_LEN12); + md_reg->md_clk_ctl13 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR13, MD_Clkctrl_DUMP_LEN13); + md_reg->md_clk_ctl14 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR14, MD_Clkctrl_DUMP_LEN14); + md_reg->md_clk_ctl15 = ioremap_nocache(MD_Clkctrl_DUMP_ADDR15, MD_Clkctrl_DUMP_LEN15); + md_reg->md_boot_stats0 = ioremap_nocache(MD1_CFG_BOOT_STATS0, 4); + md_reg->md_boot_stats1 = ioremap_nocache(MD1_CFG_BOOT_STATS1, 4); + + md_ctrl->md_pll_base = md_reg; + +#ifdef MD_PEER_WAKEUP + md_ctrl->md_peer_wakeup = ioremap_nocache(MD_PEER_WAKEUP, 0x4); +#endif + return 0; +} + +void md_cd_lock_cldma_clock_src(int locked) +{ + /* spm_ap_mdsrc_req(locked); */ +} + +void md_cd_lock_modem_clock_src(int locked) +{ + spm_ap_mdsrc_req(locked); +} + +void md_cd_dump_md_bootup_status(struct ccci_modem *md) +{ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + struct md_pll_reg *md_reg = md_ctrl->md_pll_base; + + md_cd_lock_modem_clock_src(1); + /*To avoid AP/MD interface delay, dump 3 times, and buy-in the 3rd dump value.*/ + + cldma_read32(md_reg->md_boot_stats0, 0); /* dummy read */ + cldma_read32(md_reg->md_boot_stats0, 0); /* dummy read */ + CCCI_NOTICE_LOG(md->index, TAG, "md_boot_stats0:0x%X\n", cldma_read32(md_reg->md_boot_stats0, 0)); + + cldma_read32(md_reg->md_boot_stats1, 0); /* dummy read */ + cldma_read32(md_reg->md_boot_stats1, 0); /* dummy read */ + CCCI_NOTICE_LOG(md->index, TAG, "md_boot_stats1:0x%X\n", cldma_read32(md_reg->md_boot_stats1, 0)); + md_cd_lock_modem_clock_src(0); +} + +void md_cd_dump_debug_register(struct ccci_modem *md) +{ +#if 1 /* MD no need dump because of bus hang happened - open for debug */ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; +#if 1 + unsigned int reg_value; + void __iomem *md_addr; +#endif + struct md_pll_reg *md_reg = md_ctrl->md_pll_base; + + if (md->md_state == BOOT_WAITING_FOR_HS1) + return; + + CCCI_MEM_LOG(md->index, TAG, "Dump subsys_if_on\n"); + subsys_if_on(); + + md_cd_lock_modem_clock_src(1); +#if 1 + /* 1. shared memory */ + /* 2. TOPSM */ + if (md->md_dbg_dump_flag & (1 << MD_DBG_DUMP_TOPSM)) { + CCCI_MEM_LOG_TAG(md->index, TAG, "Dump MD TOPSM status 0x%x\n", MD_TOPSM_STATUS_BASE); + ccci_write32(md_reg->md_busreg1, 0x94, 0xE7C5);/* pre-action: permission */ + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->md_topsm_status, MD_TOPSM_STATUS_LENGTH); + } + /* 3. PC Monitor */ + if (md->md_dbg_dump_flag & (1 << MD_DBG_DUMP_PCMON)) { + CCCI_MEM_LOG_TAG(md->index, TAG, "Dump MD PC monitor 0x%x\n", (MD_PC_MONITOR_BASE + 0x100)); + ccci_write32(md_reg->md_busreg1, 0x94, 0xE7C5);/* pre-action: permission */ + /* pre-action: Open Dbgsys clock */ + md_addr = md_reg->md_ect_0; + reg_value = ccci_read32(md_addr, 4); + reg_value |= (0x1 << 3); + CCCI_MEM_LOG(md->index, TAG, "[pre-action]write: %p=0x%x\n", (md_addr + 4), reg_value); + ccci_write32(md_addr, 4, reg_value); /* clear bit[29] */ + reg_value = ccci_read32(md_addr, 4); + CCCI_MEM_LOG(md->index, TAG, "[pre-action] read: %p=0x%x\n", (md_addr + 4), reg_value); + reg_value = ccci_read32(md_addr, 0x20); + CCCI_MEM_LOG(md->index, TAG, "[pre-action] before %p=0x%x\n", (md_addr + 0x20), reg_value); + while (!(ccci_read32(md_addr, 0x20)&(1<<3))) + ; + CCCI_MEM_LOG(md->index, TAG, "[pre-action]after 0x%x\n", reg_value); + + ccci_write32(md_reg->md_pc_mon1, 4, 0x80000000); /* stop MD PCMon */ + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_pc_mon1, 0x48); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, (md_reg->md_pc_mon1 + 0x100), 0x280); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, (md_reg->md_pc_mon1 + 0x400), 0x100); + ccci_write32(md_reg->md_pc_mon1, 4, 0x1); /* restart MD PCMon */ + + ccci_write32(md_reg->md_pc_mon2, 4, 0x80000000); /* stop MD PCMon:L1 */ + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_pc_mon2, 0x48); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, (md_reg->md_pc_mon2 + 0x100), 0x280); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, (md_reg->md_pc_mon2 + 0x400), 0x100); + ccci_write32(md_reg->md_pc_mon2, 4, 0x1); /* restart MD PCMon */ + } + /* 4. MD RGU */ + if (md->md_dbg_dump_flag & (1 << MD_DBG_DUMP_MDRGU)) { + CCCI_MEM_LOG_TAG(md->index, TAG, "Dump MD RGU 0x%x\n", MD_RGU_BASE); + ccci_write32(md_reg->md_busreg1, 0x94, 0xE7C5); /* pre-action */ + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_ctrl->md_rgu_base, 0x8B); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, (md_ctrl->md_rgu_base + 0x200), 0x60); + } + /* 5 OST */ + if (md->md_dbg_dump_flag & (1 << MD_DBG_DUMP_OST)) { + CCCI_MEM_LOG_TAG(md->index, TAG, "Dump MD OST status %x\n", MD_OST_STATUS_BASE); + ccci_write32(md_reg->md_busreg1, 0x94, 0xE7C5); /* pre-action */ + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_ctrl->md_ost_status, MD_OST_STATUS_LENGTH); + } + /* 6. Bus status */ + if (md->md_dbg_dump_flag & (1 << MD_DBG_DUMP_BUS)) { + CCCI_MEM_LOG_TAG(md->index, TAG, "Dump MD Bus status %x\n", MD_BUS_STATUS_BASE); + ccci_write32(md_reg->md_busreg1, 0x94, 0xE7C5);/* pre-action: permission */ + ccci_write32(md_reg->md_busreg1, 0x9C, 0x65);/* pre-action: permission */ + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_ctrl->md_bus_status, 0x38); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, (md_ctrl->md_bus_status + 0x100), 0x30); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_busreg1, MD_BUSREG_DUMP_LEN1); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_busreg2, MD_BUSREG_DUMP_LEN2); + } + /* 7. dump PLL */ + if (md->md_dbg_dump_flag & (1 << MD_DBG_DUMP_PLL)) { + CCCI_MEM_LOG_TAG(md->index, TAG, "Dump MD PLL\n"); + ccci_write32(md_reg->md_busreg1, 0x94, 0xE7C5);/* pre-action: permission */ + ccci_write32(md_reg->md_busreg1, 0x9C, 0x65);/* pre-action: permission */ + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clkSW, 0x4C); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl01, MD_Clkctrl_DUMP_LEN01); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl02, MD_Clkctrl_DUMP_LEN02); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl03, MD_Clkctrl_DUMP_LEN03); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl04, MD_Clkctrl_DUMP_LEN04); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl05, MD_Clkctrl_DUMP_LEN05); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl06, MD_Clkctrl_DUMP_LEN06); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl07, MD_Clkctrl_DUMP_LEN07); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl08, MD_Clkctrl_DUMP_LEN08); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl09, MD_Clkctrl_DUMP_LEN09); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl10, MD_Clkctrl_DUMP_LEN10); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl11, MD_Clkctrl_DUMP_LEN11); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl12, MD_Clkctrl_DUMP_LEN12); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl13, MD_Clkctrl_DUMP_LEN13); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl14, MD_Clkctrl_DUMP_LEN14); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_clk_ctl15, MD_Clkctrl_DUMP_LEN15); + } + /* 8. Bus REC */ + if (md->md_dbg_dump_flag & (1 << MD_DBG_DUMP_BUSREC)) { + CCCI_MEM_LOG_TAG(md->index, TAG, "Dump MD Bus REC%x\n", MD_BUSREC_DUMP_ADDR); + ccci_write32(md_reg->md_busreg1, 0x94, 0xE7C5);/* pre-action: permission */ + /* pre-action: Open Dbgsys clock */ + md_addr = md_reg->md_ect_0; + reg_value = ccci_read32(md_addr, 4); + reg_value |= (0x1 << 3); + CCCI_MEM_LOG(md->index, TAG, "[pre-action]write: %p=0x%x\n", (md_addr + 4), reg_value); + ccci_write32(md_addr, 4, reg_value); /* clear bit[29] */ + reg_value = ccci_read32(md_addr, 4); + CCCI_MEM_LOG(md->index, TAG, "[pre-action] read: %p=0x%x\n", (md_addr + 4), reg_value); + reg_value = ccci_read32(md_addr, 0x20); + CCCI_MEM_LOG(md->index, TAG, "[pre-action] before %p=0x%x\n", (md_addr + 0x20), reg_value); + while (!(ccci_read32(md_addr, 0x20)&(1<<3))) + ; + CCCI_MEM_LOG(md->index, TAG, "[pre-action]after 0x%x\n", reg_value); + ccci_write32(md_reg->md_busrec, 0x4, 0x1);/* pre-action */ + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_busrec, MD_BUSREC_DUMP_LEN); + ccci_write32(md_reg->md_busrec, 0x4, 0x3);/* post-action */ + } + /* 9. ECT: must after 4 TO PSM */ + if (md->md_dbg_dump_flag & (1 << MD_DBG_DUMP_ECT)) { + CCCI_MEM_LOG_TAG(md->index, TAG, "Dump MD ECT 0x%x\n", MD_ECT_DUMP_ADDR0); + ccci_write32(md_reg->md_busreg1, 0x94, 0xE7C5);/* pre-action: permission */ + /* pre-action: Open Dbgsys clock */ + md_addr = md_reg->md_ect_0; + reg_value = ccci_read32(md_addr, 4); + reg_value |= (0x1 << 3); + CCCI_MEM_LOG(md->index, TAG, "[pre-action]write: %p=0x%x\n", (md_addr + 4), reg_value); + ccci_write32(md_addr, 4, reg_value); /* clear bit[29] */ + reg_value = ccci_read32(md_addr, 4); + CCCI_MEM_LOG(md->index, TAG, "[pre-action] read: %p=0x%x\n", (md_addr + 4), reg_value); + reg_value = ccci_read32(md_addr, 0x20); + CCCI_MEM_LOG(md->index, TAG, "[pre-action] before %p=0x%x\n", (md_addr + 0x20), reg_value); + while (!(ccci_read32(md_addr, 0x20)&(1<<3))) + ; + CCCI_MEM_LOG(md->index, TAG, "[pre-action]after 0x%x\n", reg_value); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_ect_1, MD_ECT_DUMP_LEN1); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_ect_2, MD_ECT_DUMP_LEN2); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, md_reg->md_ect_3, MD_ECT_DUMP_LEN3); + } +#endif + md_cd_lock_modem_clock_src(0); +#endif +} + +void md_cd_check_md_DCM(struct ccci_modem *md) +{ +#if 0 + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + + md_cd_lock_modem_clock_src(1); + /* CCCI_BOOTUP_LOG(md->index, TAG, "MD DCM: 0x%X\n", *(unsigned int *)(md_ctrl->md_bus_status + 0x45C)); */ + md_cd_lock_modem_clock_src(0); +#endif +} + +void md_cd_check_emi_state(struct ccci_modem *md, int polling) +{ +} + +/* callback for system power off*/ +void ccci_power_off(void) +{ +} + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +void md1_pmic_setting_off(void) +{ + vmd1_pmic_setting_off(); +} + +void md1_pmic_setting_on(void) +{ + vmd1_pmic_setting_on(); +} +#else +void md1_pmic_setting_off(void) +{ + /* VMODEM off */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN, 0); /* 0x063A[8]=0, 0:SW control, 1:HW control */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_EN, 0); /* 0x062C[0]=0, 0:Disable, 1:Enable */ + /* VMD1 off */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_VSLEEP_EN, 0); /* 0x064E[8]=0, 0:SW control, 1:HW control */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_EN, 0); /* 0x0640[0]=0, 0:Disable, 1:Enable */ + /* VSRAM_MD off */ + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN, 0); /* 0x0662[8]=0, 0:SW control, 1:HW control */ + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_EN, 0); /* 0x0654[0]=0, 0:Disable, 1:Enable */ +} + +void md1_pmic_setting_on(void) +{ + /* VSRAM_MD on */ + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_EN, 1); /* 0x0654[0]=0, 0:Disable, 1:Enable */ + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN, 1); /* 0x0662[8]=0, 0:SW control, 1:HW control */ + + /* VMD1 on */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_EN, 1); /* 0x0640[0]=0, 0:Disable, 1:Enable */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_VSLEEP_EN, 1); /* 0x064E[8]=0, 0:SW control, 1:HW control */ + + /* VMODEM on */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_EN, 1); /* 0x062C[0]=0, 0:Disable, 1:Enable */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN, 1); /* 0x063A[8]=0, 0:SW control, 1:HW control */ + + if (CHIP_SW_VER_01 == mt_get_chip_sw_ver()) { + CCCI_ERR_MSG(0, TAG, "modem E1 chip\n"); + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON, 0x40);/*E1 1.0V; offset:0x65A */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VOSEL_ON, 0x40);/* 1.0V; offset: 0x632 */ + } else { + CCCI_ERR_MSG(0, TAG, "modem E2 chip\n"); + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON, 0x50);/*E2 1.1V; offset:0x65A */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VOSEL_ON, 0x40);/* E2 1.0V; offset: 0x632 */ + } + + udelay(300); + + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL, 1);/* HW mode, bit[1]; offset: 0x650 */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL, 1);/* HW mode, bit[1]; offset: 0x63C */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL, 1);/* HW mode, bit[1]; offset: 0x628 */ +} +#endif + +#define ROr2W(a, b, c) cldma_write32(a, b, (cldma_read32(a, b)|c)) +#define RAnd2W(a, b, c) cldma_write32(a, b, (cldma_read32(a, b)&c)) +#define RabIsc(a, b, c) ((cldma_read32(a, b)&c) != c) + +void md1_pll_on_1(struct ccci_modem *md) +{ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + struct md_pll_reg *md_pll = md_ctrl->md_pll_base; + + /* CCCI_BOOTUP_LOG(md->index, TAG, "md1_pll_on\n"); */ + /* Make md1 208M CG off, switch to software mode */ + ROr2W(md_pll->md_clkSW, 0x20, (0x1<<26)); /* turn off mdpll1 cg */ + ROr2W(md_pll->md_top_Pll, 0x10, (0x1<<16)); /* let mdpll on ctrl into software mode */ + ROr2W(md_pll->md_top_Pll, 0x14, (0x1<<16)); /* let mdpll enable into software mode */ +} + +void md1_pll_on_2(struct ccci_modem *md) +{ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + struct md_pll_reg *md_pll = md_ctrl->md_pll_base; + + RAnd2W(md_pll->md_top_Pll, 0x10, ~(0x1<<16)); /* let mdpll on ctrl into hardware mode */ + RAnd2W(md_pll->md_top_Pll, 0x14, ~(0x1<<16)); /* let mdpll enable into hardware mode */ + RAnd2W(md_pll->md_clkSW, 0x20, ~(0x1<<26)); /* turn on mdpll1 cg */ +} + +void md1_pll_on(struct ccci_modem *md) +{ + void __iomem *map_addr; + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + /* struct md_pll_reg *md_pll = md_ctrl->md_pll_base; */ + + map_addr = (void __iomem *)(md_ctrl->hw_info->ap_mixed_base); + + /* reset MDPLL1_CON0 to default value */ + cldma_write32(map_addr, MDPLL1_CON0, 0x2E8); + CCCI_DEBUG_LOG(md->index, TAG, "md1_pll_on_reset_value, (0x%p)0x%X\n", + map_addr, cldma_read32(map_addr, MDPLL1_CON0)); + + /* If MD1 only or both MD1 and MD3 */ + md1_pll_on_1(md); + /* If MD3 only, do nothing */ + + /* Turn on 208M */ + ROr2W(map_addr, MDPLL1_CON0, (0x1)); + + CCCI_DEBUG_LOG(md->index, TAG, "md1_pll_on_before W, (0x%p)0x%X\n", + map_addr, cldma_read32(map_addr, AP_PLL_CON0)); + /* cldma_write32(map_addr, AP_PLL_CON0, 0x39F1); */ + ROr2W(map_addr, AP_PLL_CON0, (0x1<<1)); + + CCCI_DEBUG_LOG(md->index, TAG, "md1_pll_on_after W, 0x%X\n", cldma_read32(map_addr, AP_PLL_CON0)); + + udelay(200); + + RAnd2W(map_addr, MDPLL1_CON0, ~(0x1)); + RAnd2W(map_addr, MDPLL1_CON0, ~(0x1<<7)); + + /* close 208M and autoK */ + /* cldma_write32(map_addr, AP_PLL_CON0, 0x39F3); */ + CCCI_DEBUG_LOG(md->index, TAG, "md1_pll_on_before W, 0x%X, 0x%X\n", + cldma_read32(map_addr, AP_PLL_CON0), cldma_read32(map_addr, MDPLL1_CON0)); + /* cldma_write32(map_addr, MDPLL1_CON0, 0x02E9); */ + CCCI_DEBUG_LOG(md->index, TAG, "md1_pll_on_after W, 0x%X\n", cldma_read32(map_addr, MDPLL1_CON0)); + /* RAnd2W(map_addr, MDPLL1_CON0, 0xfffffffe); */ + /* RAnd2W(map_addr, MDPLL1_CON0, 0xffffff7f); */ + + /* If MD1 only or both MD1 and MD3 */ + md1_pll_on_2(md); + /* If MD3 only, do nothing */ + + RAnd2W(map_addr, MDPLL1_CON0, ~(0x1<<9)); + CCCI_DEBUG_LOG(md->index, TAG, "md1_pll_on, (0x%p)0x%X\n", map_addr, cldma_read32(map_addr, MDPLL1_CON0)); + /* RAnd2W(map_addr, MDPLL1_CON0, 0xfffffdff); */ /* set mdpll control by md1 and c2k */ +} + +void md1_pll_init(struct ccci_modem *md) +{ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + struct md_pll_reg *md_pll = md_ctrl->md_pll_base; + /* enable L1 permission */ + md1_pll_on(md); + ROr2W(md_pll->md_peri_misc, R_L1_PMS, 0x7); + + /* modify PSMCU2EMI bus divider from 3 to 4. */ + ROr2W(md_pll->md_sys_clk, R_PSMCU_AO_CLK_CTL, 0x83); + + ROr2W(md_pll->md_L1_a0, R_L1MCU_PWR_AWARE, (1<<16)); + + ROr2W(md_pll->md_L1_a0, R_L1AO_PWR_AWARE, (1<<16)); + /* busL2 DCM div 8/normal div 1/ clkslow_en/clock from + PLL /debounce enable/ debounce time 7T */ + /* L2DCM L1BUS div 16 */ + cldma_write32(md_pll->md_L1_a0, R_BUSL2DCM_CON3, 0x0000FDE7); /* <= 1FDE7 */ + cldma_write32(md_pll->md_L1_a0, R_BUSL2DCM_CON3, 0x1000FDE7); /* toggle setting */ + /* DCM div 8/normal div 1/clkslow_en/ clock + from PLL / dcm enable /debounce enable /debounce time 15T */ + cldma_write32(md_pll->md_L1_a0, R_L1MCU_DCM_CON, 0x0001FDE7); + /* DCM config toggle = 0 */ + cldma_write32(md_pll->md_L1_a0, R_L1MCU_DCM_CON2, 0x00000000); + /* DCM config toggle = 1 / */ + cldma_write32(md_pll->md_L1_a0, R_L1MCU_DCM_CON2, 0x80000000); + + /* Wait PSMCU PLL ready */ + CCCI_DEBUG_LOG(md->index, TAG, "Wait PSMCU PLL ready\n"); + while (RabIsc(md_pll->md_clkSW, R_PLL_STS, 0x1)) + ; + CCCI_DEBUG_LOG(md->index, TAG, "Got it\n"); + /* Switch clock, 0: 26MHz, 1: PLL */ + ROr2W(md_pll->md_clkSW, R_CLKSEL_CTL, 0x2); + + /*Wait L1MCU PLL ready */ + CCCI_BOOTUP_LOG(md->index, TAG, "Wait L1MCU PLL ready\n"); + while (RabIsc(md_pll->md_clkSW, R_PLL_STS, 0x2)) + ; + CCCI_BOOTUP_LOG(md->index, TAG, "Got it\n"); + /* Bit 8: L1MCU_CK = L1MCUPLL */ + ROr2W(md_pll->md_clkSW, R_CLKSEL_CTL, 0x100); + + /*DFE/CMP/ICC/IMC clock src select */ + cldma_write32(md_pll->md_clkSW, R_FLEXCKGEN_SEL1, 0x30302020); + /* Bit 29-28 DFE_CLK src = DFEPLL, Bit 21-20 CMP_CLK src = DFEPLL + Bit 13-12 ICC_CLK src = IMCPLL, Bit 5-4 IMC_CLK src = IMCPLL */ + + /*IMC/MD2G clock src select */ + cldma_write32(md_pll->md_clkSW, R_FLEXCKGEN_SEL2, 0x00002030); + /* Bit 13-12 INTF_CLK src = IMCPLL, Bit 5-4 MD2G_CLK src = DFEPLL */ + + /* Wait DFE/IMC PLL ready: Bit 7: DFEPLL_RDY, Bit 4: IMCPLL_RDY */ + while (RabIsc(md_pll->md_clkSW, R_PLL_STS, 0x90)) + ; + + /* Wait L1SYS clock ready */ + CCCI_BOOTUP_LOG(md->index, TAG, "Wait L1SYS clock ready\n"); + while (RabIsc(md_pll->md_clkSW, R_FLEXCKGEN_STS0, 0x80800000)) + ; + + CCCI_DEBUG_LOG(md->index, TAG, "Done\n"); + + CCCI_BOOTUP_LOG(md->index, TAG, "Wait R_FLEXCKGEN_STS1 & 0x80808080 ready\n"); + while (RabIsc(md_pll->md_clkSW, R_FLEXCKGEN_STS1, 0x80808080)) + ; + + CCCI_DEBUG_LOG(md->index, TAG, "Done\n"); + + CCCI_BOOTUP_LOG(md->index, TAG, "Wait R_FLEXCKGEN_STS2 & 0x8080 ready\n"); + while (RabIsc(md_pll->md_clkSW, R_FLEXCKGEN_STS2, 0x8080)) + ; + + CCCI_DEBUG_LOG(md->index, TAG, "Done\n"); + + /*Switch L1SYS clock to PLL clock */ + ROr2W(md_pll->md_clkSW, R_CLKSEL_CTL, 0x3fe00); + + /*MD BUS/ARM7 clock src select */ + cldma_write32(md_pll->md_clkSW, R_FLEXCKGEN_SEL0, 0x30203031); + + cldma_write32(md_pll->md_dcm, MD_GLOBAL_CON_DUMMY, MD_PLL_MAGIC_NUM); + + #if 0 + /*PSMCU DCM */ + ROr2W(md_pll->md_dcm, R_PSMCU_DCM_CTL0, 0x00F1F006); + + ROr2W(md_pll->md_dcm, R_PSMCU_DCM_CTL1, 0x26); + + /*ARM7 DCM */ + ROr2W(md_pll->md_dcm, R_ARM7_DCM_CTL0, 0x00F1F006); + ROr2W(md_pll->md_dcm, R_ARM7_DCM_CTL1, 0x26); + + cldma_write32(md_pll->md_sys_clk, R_DCM_SHR_SET_CTL, 0x00014110); + + /*LTEL2 BUS DCM */ + ROr2W(md_pll->md_sys_clk, R_LTEL2_BUS_DCM_CTL, 0x1); /* Bit 0: DCM_EN */ + + /*MDDMA BUS DCM */ + ROr2W(md_pll->md_sys_clk, R_MDDMA_BUS_DCM_CTL, 0x1); /* Bit 0: DCM_EN */ + + /*MDREG BUS DCM */ + ROr2W(md_pll->md_sys_clk, R_MDREG_BUS_DCM_CTL, 0x1); /* Bit 0: DCM_EN */ + + /*MODULE BUS2X DCM */ + ROr2W(md_pll->md_sys_clk, R_MODULE_BUS2X_DCM_CTL, 0x1); /* Bit 0: DCM_EN */ + + /*MODULE BUS1X DCM */ + ROr2W(md_pll->md_sys_clk, R_MODULE_BUS1X_DCM_CTL, 0x1); /* Bit 0: DCM_EN */ + + /*MD perisys AHB master/slave DCM enable */ + ROr2W(md_pll->md_sys_clk, R_MDINFRA_CKEN, 0xC000001F); + + /*MD debugsys DCM enable */ + ROr2W(md_pll->md_sys_clk, R_MDPERI_CKEN, 0x8003FFFF); + + /*SET MDRGU, MDTOPSM, MDOSTIMER, MDTOPSM DCM MASK */ + ROr2W(md_pll->md_sys_clk, R_MDPERI_DCM_MASK, 0x00001E00); + #endif + + ROr2W(md_pll->md_L1_a0, REG_DCM_PLLCK_SEL, (1<<7)); + + /* wait DCM config done, then switch BUS clock src to PLL */ + CCCI_BOOTUP_LOG(md->index, TAG, "wait DCM config done\n"); + while (RabIsc(md_pll->md_clkSW, R_FLEXCKGEN_STS0, 0x80)) + ; + CCCI_BOOTUP_LOG(md->index, TAG, "done\n"); + /* Bit 1: BUS_CLK = EQPLL/2 */ + ROr2W(md_pll->md_clkSW, R_CLKSEL_CTL, 0x1); +} + +int md_cd_power_on(struct ccci_modem *md) +{ + int ret = 0; + unsigned int reg_value; + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + + /* Fix me, should change to using device tree */ + void __iomem *bpi_bsi_slv1; + + bpi_bsi_slv1 = ioremap_nocache(0x1021F600, 0x20); + if (bpi_bsi_slv1) { + cldma_write32(bpi_bsi_slv1, 0x10, 0xFFFF); + cldma_write32(bpi_bsi_slv1, 0x08, 0x4); + iounmap(bpi_bsi_slv1); + } else + CCCI_BOOTUP_LOG(md->index, TAG, "bps_bsi_slv1 map fail\n"); + + /* step 0: PMIC setting */ + md1_pmic_setting_on(); + + /* steip 1: power on MD_INFRA and MODEM_TOP */ + switch (md->index) { + case MD_SYS1: + clk_buf_set_by_flightmode(false); +#if defined(CONFIG_MTK_CLKMGR) + CCCI_BOOTUP_LOG(md->index, TAG, "Call start md_power_on()\n"); + ret = md_power_on(SYS_MD1); + CCCI_BOOTUP_LOG(md->index, TAG, "Call end md_power_on() ret=%d\n", ret); +#else + CCCI_BOOTUP_LOG(md->index, TAG, "Call start clk_prepare_enable()\n"); + ret = clk_prepare_enable(clk_scp_sys_md1_main); + CCCI_BOOTUP_LOG(md->index, TAG, "Call end clk_prepare_enable() ret=%d\n", ret); +#endif + + kicker_pbm_by_md(KR_MD1, true); + CCCI_BOOTUP_LOG(md->index, TAG, "Call end kicker_pbm_by_md(0,true)\n"); + break; + } + if (ret) + return ret; + + /* step 3: MD srcclkena setting */ + reg_value = ccci_read32(infra_ao_base, INFRA_AO_MD_SRCCLKENA); + +#if defined(CONFIG_MTK_MD3_SUPPORT) && (CONFIG_MTK_MD3_SUPPORT > 0) + reg_value &= ~(0x92); /* md1 set 0x29: bit 0/3/4/7, bit1/5: VRF18 control */ + reg_value |= 0x29; /* C2K set |0x44: bit 2/6 */ +#else + reg_value &= ~(0xFF); + reg_value |= 0x29; +#endif + ccci_write32(infra_ao_base, INFRA_AO_MD_SRCCLKENA, reg_value); + CCCI_BOOTUP_LOG(md->index, CORE, "md_cd_power_on: set md1_srcclkena bit(0x1000_1F0C)=0x%x\n", + ccci_read32(infra_ao_base, INFRA_AO_MD_SRCCLKENA)); + +#ifdef FEATURE_INFORM_NFC_VSIM_CHANGE + /* notify NFC */ + inform_nfc_vsim_change(md->index, 1, 0); +#endif + /* step 4: pll init */ + md1_pll_init(md); + + /* step 5: disable MD WDT */ + cldma_write32(md_ctrl->md_rgu_base, WDT_MD_MODE, WDT_MD_MODE_KEY); + cldma_write32(md_ctrl->l1_rgu_base, REG_L1RSTCTL_WDT_MODE, L1_WDT_MD_MODE_KEY); + +#ifdef SET_EMI_STEP_BY_STAGE + CCCI_BOOTUP_LOG(md->index, KERN, "set domain register\n"); + ccci_write32(md_ctrl->md_pll_base->md_busreg1, 0xC4, 0x7); + ccci_write32(md_ctrl->md_pll_base->md_L1_a0, 0x220, 0x1); + ccci_write32(md_ctrl->md_pll_base->md_L1_a0, 0x220, 0x81); +#endif + return 0; +} + +int md_cd_bootup_cleanup(struct ccci_modem *md, int success) +{ + return 0; +} + +int md_cd_let_md_go(struct ccci_modem *md) +{ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + + if (MD_IN_DEBUG(md)) + return -1; + CCCI_BOOTUP_LOG(md->index, TAG, "set MD boot slave\n"); + + cldma_write32(md_ctrl->md_boot_slave_En, 0, 1); /* make boot vector take effect */ + return 0; +} + +int md_cd_soft_power_off(struct ccci_modem *md, unsigned int mode) +{ + clk_buf_set_by_flightmode(true); + return 0; +} + +int md_cd_soft_power_on(struct ccci_modem *md, unsigned int mode) +{ + clk_buf_set_by_flightmode(false); + return 0; +} + +int md_cd_power_off(struct ccci_modem *md, unsigned int stop_type) +{ + int ret = 0; +#if defined(CONFIG_MTK_CLKMGR) + unsigned int timeout = 0; + + if (stop_type == MD_FLIGHT_MODE_ENTER) + timeout = 1000; +#endif +#ifdef FEATURE_INFORM_NFC_VSIM_CHANGE + /* notify NFC */ + inform_nfc_vsim_change(md->index, 0, 0); +#endif + + /* power off MD_INFRA and MODEM_TOP */ + switch (md->index) { + case MD_SYS1: +#if defined(CONFIG_MTK_CLKMGR) + ret = md_power_off(SYS_MD1, timeout); +#else + clk_disable(clk_scp_sys_md1_main); + clk_unprepare(clk_scp_sys_md1_main); /* cannot be called in mutex context */ +#endif + clk_buf_set_by_flightmode(true); + md1_pmic_setting_off(); + kicker_pbm_by_md(KR_MD1, false); + CCCI_BOOTUP_LOG(md->index, TAG, "Call end kicker_pbm_by_md(0,false)\n"); + break; + } + return ret; +} + +void cldma_dump_register(struct ccci_modem *md) +{ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + + CCCI_MEM_LOG_TAG(md->index, TAG, "dump AP CLDMA Tx pdn register, active=%x\n", md_ctrl->txq_active); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_ap_pdn_base + CLDMA_AP_UL_START_ADDR_0, + CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE - CLDMA_AP_UL_START_ADDR_0 + 4); + CCCI_MEM_LOG_TAG(md->index, TAG, "dump AP CLDMA Tx ao register, active=%x\n", md_ctrl->txq_active); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_ap_ao_base + CLDMA_AP_UL_START_ADDR_BK_0, + CLDMA_AP_UL_CURRENT_ADDR_BK_7 - CLDMA_AP_UL_START_ADDR_BK_0 + 4); + + CCCI_MEM_LOG_TAG(md->index, TAG, "dump AP CLDMA Rx pdn register, active=%x\n", md_ctrl->rxq_active); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_ap_pdn_base + CLDMA_AP_SO_ERROR, + CLDMA_AP_SO_STOP_CMD - CLDMA_AP_SO_ERROR + 4); + + CCCI_MEM_LOG_TAG(md->index, TAG, "dump AP CLDMA Rx ao register, active=%x\n", md_ctrl->rxq_active); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_ap_ao_base + CLDMA_AP_SO_CFG, + CLDMA_AP_DEBUG_ID_EN - CLDMA_AP_SO_CFG + 4); + + CCCI_MEM_LOG_TAG(md->index, TAG, "dump AP CLDMA MISC pdn register\n"); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_ap_pdn_base + CLDMA_AP_L2TISAR0, + CLDMA_AP_CLDMA_IP_BUSY - CLDMA_AP_L2TISAR0 + 4); + + CCCI_MEM_LOG_TAG(md->index, TAG, "dump AP CLDMA MISC ao register\n"); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_ap_ao_base + CLDMA_AP_L2RIMR0, CLDMA_AP_DUMMY - CLDMA_AP_L2RIMR0 + 4); + + CCCI_MEM_LOG_TAG(md->index, TAG, "dump MD CLDMA Tx pdn register, active=%x\n", md_ctrl->txq_active); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_md_pdn_base + CLDMA_AP_UL_START_ADDR_0, + CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE - CLDMA_AP_UL_START_ADDR_0 + 4); + CCCI_MEM_LOG_TAG(md->index, TAG, "dump MD CLDMA Tx ao register, active=%x\n", md_ctrl->txq_active); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_md_ao_base + CLDMA_AP_UL_START_ADDR_BK_0, + CLDMA_AP_UL_CURRENT_ADDR_BK_7 - CLDMA_AP_UL_START_ADDR_BK_0 + 4); + + CCCI_MEM_LOG_TAG(md->index, TAG, "dump MD CLDMA Rx pdn register, active=%x\n", md_ctrl->rxq_active); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_md_pdn_base + CLDMA_AP_SO_ERROR, + CLDMA_AP_SO_STOP_CMD - CLDMA_AP_SO_ERROR + 4); + CCCI_MEM_LOG_TAG(md->index, TAG, "dump MD CLDMA Rx ao register, active=%x\n", md_ctrl->rxq_active); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_md_ao_base + CLDMA_AP_SO_CFG, + CLDMA_AP_DEBUG_ID_EN - CLDMA_AP_SO_CFG + 4); + + CCCI_MEM_LOG_TAG(md->index, TAG, "dump MD CLDMA MISC pdn register\n"); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_md_pdn_base + CLDMA_AP_L2TISAR0, + CLDMA_AP_CLDMA_IP_BUSY - CLDMA_AP_L2TISAR0 + 4); + CCCI_MEM_LOG_TAG(md->index, TAG, "dump MD CLDMA MISC ao register\n"); + ccci_util_mem_dump(md->index, CCCI_DUMP_MEM_DUMP, + md_ctrl->cldma_md_ao_base + CLDMA_AP_L2RIMR0, CLDMA_AP_DUMMY - CLDMA_AP_L2RIMR0 + 4); + +} + +int ccci_modem_remove(struct platform_device *dev) +{ + return 0; +} + +void ccci_modem_shutdown(struct platform_device *dev) +{ +} + +int ccci_modem_suspend(struct platform_device *dev, pm_message_t state) +{ + struct ccci_modem *md = (struct ccci_modem *)dev->dev.platform_data; + + CCCI_DEBUG_LOG(md->index, TAG, "ccci_modem_suspend\n"); + return 0; +} + +int ccci_modem_resume(struct platform_device *dev) +{ + struct ccci_modem *md = (struct ccci_modem *)dev->dev.platform_data; + + CCCI_DEBUG_LOG(md->index, TAG, "ccci_modem_resume\n"); + return 0; +} + +int ccci_modem_pm_suspend(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + + BUG_ON(pdev == NULL); + + return ccci_modem_suspend(pdev, PMSG_SUSPEND); +} + +int ccci_modem_pm_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + + BUG_ON(pdev == NULL); + + return ccci_modem_resume(pdev); +} + +int ccci_modem_pm_restore_noirq(struct device *device) +{ + struct ccci_modem *md = (struct ccci_modem *)device->platform_data; + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + + /* set flag for next md_start */ + md->config.setting |= MD_SETTING_RELOAD; + md->config.setting |= MD_SETTING_FIRST_BOOT; + /* restore IRQ */ +#ifdef FEATURE_PM_IPO_H + irq_set_irq_type(md_ctrl->cldma_irq_id, IRQF_TRIGGER_HIGH); + irq_set_irq_type(md_ctrl->md_wdt_irq_id, IRQF_TRIGGER_FALLING); +#endif + return 0; +} + +void ccci_modem_restore_reg(struct ccci_modem *md) +{ + struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data; + int i; + unsigned long flags; + + if (md->md_state == GATED || md->md_state == RESET || md->md_state == INVALID) { + CCCI_NORMAL_LOG(md->index, TAG, "Resume no need reset cldma for md_state=%d\n", md->md_state); + return; + } + cldma_write32(md_ctrl->ap_ccif_base, APCCIF_CON, 0x01); /* arbitration */ + + if (cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_TQSAR(0))) { + CCCI_DEBUG_LOG(md->index, TAG, "Resume cldma pdn register: No need ...\n"); + } else { + CCCI_NORMAL_LOG(md->index, TAG, "Resume cldma pdn register ...11\n"); + spin_lock_irqsave(&md_ctrl->cldma_timeout_lock, flags); + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_HPQR, 0x00); + /* set checksum */ + switch (CHECKSUM_SIZE) { + case 0: + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE, 0); + break; + case 12: + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE, + CLDMA_BM_ALL_QUEUE); + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG, + cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG) & ~0x10); + break; + case 16: + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE, + CLDMA_BM_ALL_QUEUE); + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG, + cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG) | 0x10); + break; + } + /* set start address */ + for (i = 0; i < QUEUE_LEN(md_ctrl->txq); i++) { + if (cldma_read32(md_ctrl->cldma_ap_ao_base, CLDMA_AP_TQCPBAK(md_ctrl->txq[i].index)) == 0) { + if (i != 7) /* Queue 7 not used currently */ + CCCI_NORMAL_LOG(md->index, TAG, "Resume CH(%d) current bak:== 0\n", i); + cldma_reg_set_tx_start_addr(md_ctrl->cldma_ap_pdn_base, md_ctrl->txq[i].index, + md_ctrl->txq[i].tr_done->gpd_addr); + cldma_reg_set_tx_start_addr_bk(md_ctrl->cldma_ap_ao_base, md_ctrl->txq[i].index, + md_ctrl->txq[i].tr_done->gpd_addr); + } else { + unsigned int bk_addr = cldma_read32(md_ctrl->cldma_ap_ao_base, + CLDMA_AP_TQCPBAK(md_ctrl->txq[i].index)); + + cldma_reg_set_tx_start_addr(md_ctrl->cldma_ap_pdn_base, + md_ctrl->txq[i].index, bk_addr); + cldma_reg_set_tx_start_addr_bk(md_ctrl->cldma_ap_ao_base, + md_ctrl->txq[i].index, bk_addr); + } + } + /* wait write done*/ + wmb(); + /* start all Tx and Rx queues */ +#ifdef NO_START_ON_SUSPEND_RESUME + md_ctrl->txq_started = 0; +#else + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_START_CMD, CLDMA_BM_ALL_QUEUE); + cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_START_CMD); /* dummy read */ +#endif + md_ctrl->txq_active |= CLDMA_BM_ALL_QUEUE; + /* cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_SO_START_CMD, CLDMA_BM_ALL_QUEUE); */ + /* cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_SO_START_CMD); // dummy read */ + /* md_ctrl->rxq_active |= CLDMA_BM_ALL_QUEUE; */ + /* enable L2 DONE and ERROR interrupts */ + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L2TIMCR0, CLDMA_BM_INT_DONE | CLDMA_BM_INT_ERROR); + /* enable all L3 interrupts */ + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L3TIMCR0, CLDMA_BM_INT_ALL); + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L3TIMCR1, CLDMA_BM_INT_ALL); + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L3RIMCR0, CLDMA_BM_INT_ALL); + cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L3RIMCR1, CLDMA_BM_INT_ALL); + spin_unlock_irqrestore(&md_ctrl->cldma_timeout_lock, flags); + CCCI_DEBUG_LOG(md->index, TAG, "Resume cldma pdn register done\n"); + } +} + +int ccci_modem_syssuspend(void) +{ + CCCI_DEBUG_LOG(0, TAG, "ccci_modem_syssuspend\n"); + return 0; +} + +void ccci_modem_sysresume(void) +{ + struct ccci_modem *md; + + CCCI_DEBUG_LOG(0, TAG, "ccci_modem_sysresume\n"); + md = ccci_md_get_modem_by_id(0); + if (md != NULL) + ccci_modem_restore_reg(md); +} diff --git a/drivers/misc/mediatek/eccci/mt6755/cldma_platform.h b/drivers/misc/mediatek/eccci/mt6755/cldma_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..4deba13f7222fdcbaea5658c1587ca4317fbf094 --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/cldma_platform.h @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __CLDMA_PLATFORM_H__ +#define __CLDMA_PLATFORM_H__ + +#include +/* this is the platform header file for CLDMA MODEM, not just CLDMA! */ + +/* Modem WDT */ +/* BASE_ADDR_MDRSTCTL+ */ +#define REG_MDRSTCTL_WDTCR (0x0000) /*WDT_MODE*/ +#define REG_MDRSTCTL_WDTRR (0x0010) /*WDT_RESTART*/ +#define REG_MDRSTCTL_WDTIR (0x023C) /*LENGTH*/ +#define REG_MDRSTCTL_WDTSR (0x0034) /*WDT_STATUS*/ +#define WDT_MD_MODE REG_MDRSTCTL_WDTCR +#define WDT_MD_LENGTH REG_MDRSTCTL_WDTIR +#define WDT_MD_RESTART REG_MDRSTCTL_WDTRR +#define WDT_MD_STA REG_MDRSTCTL_WDTSR +#define WDT_MD_MODE_KEY (0x55000008) +/* L1_BASE_ADDR_L1RGU+ */ +#define REG_L1RSTCTL_WDT_MODE (0x0000) +#define REG_L1RSTCTL_WDT_LENGTH (0x0004) +#define REG_L1RSTCTL_WDT_RESTART (0x0008) +#define REG_L1RSTCTL_WDT_STA (0x000C) +#define REG_L1RSTCTL_WDT_SWRST (0x001C) +#define L1_WDT_MD_MODE_KEY (0x00002200) + +/* MD1 PLL */ +/* MD_CLKSW_BASE+ */ +#define R_CLKSEL_CTL (0x0024) + /*Bit 17: RF1_CKSEL, Bit 16: INTF_CKSEL, Bit 15: MD2G_CKSEL, Bit 14: DFE_CKSEL + Bit 13: CMP_CKSEL, Bit 12: ICC_CKSEL, Bit 11: IMC_CKSEL, Bit 10: EQ_CKSEL + Bit 9: BRP_CKSEL, Bit 8: L1MCU_CKSEL, Bit 6-5: ATB_SRC_CKSEL, + Bit 4: ATB_CKSEL, Bit 3: DBG_CKSEL, Bit 2: ARM7_CKSEL + Bit 1: PSMCU_CKSEL, Bit 0: BUS_CKSEL*/ +#define R_FLEXCKGEN_SEL0 (0x0028) /* Bit 29-28: EQ_CLK src = EQPLL + Bit 26-24: EQ+DIVSEL, divided-by bit[2:0]+1 + Bit 21-20: BRP_CLK src = IMCPLL + Bit 13-12: ARM7_CLK src = DFEPLL + Bit 5-4: BUS_CLK src = EQPLL + Bit 2-0: BUS_DIVSEL, divided-by bit[2:0]+1 */ +#define R_FLEXCKGEN_SEL1 (0x002C) +#define R_FLEXCKGEN_SEL2 (0x0044) +/* Bit 0: PSMCUPLL_RDY, Bit 1: L1MCUPLL_RDY */ +#define R_PLL_STS (0x0040) +#define R_FLEXCKGEN_STS0 (0x0030) + /* Bit 31: EQ_CK_RDY */ + /* Bit 23: BRP_CK_RDY */ + /* Bit 7: BUS_CK_RDY */ +#define R_FLEXCKGEN_STS1 (0x0034) + /* Bit 31: DFE_CK_RDY + Bit 23: CMP_CK_RDY + Bit 15: ICC_CK_RDY + Bit 7: IMC_CK_RDY */ +#define R_FLEXCKGEN_STS2 (0x0048) + /* Bit 15: INTF_CK_RDY, Bit 23: MD2G_CK_RDY */ +/* PSMCU DCM: MD_GLOBAL_CON_DCM_BASE+ */ +/* Bit 26-20: DBC_CNT, Bit 16-12: IDLE_FSEL, Bit 2: DBC_EN, Bit 1: DCM_EN */ +#define R_PSMCU_DCM_CTL0 (0x0010) +/* Bit 5: APB_LOAD_TOG, Bit 4-0: APB_SEL */ +#define R_PSMCU_DCM_CTL1 (0x0014) +/* MD_GLOBAL_CON_DCM_BASE+ */ +/* Bit 26-20: DBC_CNT, Bit 16-12: IDLE_FSEL, Bit 2: DBC_EN, Bit 1: DCM_EN */ +#define R_ARM7_DCM_CTL0 (0x0020) +#define R_ARM7_DCM_CTL1 (0x0024)/* Bit 5: APB_LOAD_TOG, Bit 4-0: APB_SEL */ +#define MD_GLOBAL_CON_DUMMY (0x1000) +#define MD_PLL_MAGIC_NUM (0x67550000) +/* MDSYS_CLKCTL_BASE+ */ +#define R_DCM_SHR_SET_CTL (0x0004) + /* Bit 16: BUS_PLL_SWITCH + Bit 15: BUS_QUARTER_FREQ_SEL + Bit 14: BUS_SLOW_FREQ + Bit 12-8: HFBUS_SFSEL + Bit 4-0: HFBUS_FSEL */ +#define R_LTEL2_BUS_DCM_CTL (0x0010) +#define R_MDDMA_BUS_DCM_CTL (0x0014) +#define R_MDREG_BUS_DCM_CTL (0x0018) +#define R_MODULE_BUS2X_DCM_CTL (0x001C) +#define R_MODULE_BUS1X_DCM_CTL (0x0020) +#define R_MDINFRA_CKEN (0x0044) /* Bit 31: PSPERI_MAS_DCM_EN + Bit 30: PSPERI_SLV_DCM_EN + Bit 4: SOE_CKEN + Bit 3: BUSREC_CKEN + Bit 2: BUSMON_CKEN + Bit 1: MDUART2_CKEN + Bit 0: MDUART1_CKEN */ +#define R_MDPERI_CKEN (0x0048)/* Bit 31: MDDBGSYS_DCM_EN + Bit 21: USB0_LINK_CK_SEL + Bit 20: USB1_LINK_CK_SEL + Bit 17: TRACE_CKEN + Bit 16: MDPERI_MISCREG_CKEN + Bit 15: PCCIF_CKEN + Bit 14: MDEINT_CKEN + Bit 13: MDCFGCTL_CKEN + Bit 12: MDRGU_CKEN + Bit 11: A7OST_CKEN + Bit 10: MDOST_CKEN + Bit 9: MDTOPSM_CKEN + Bit 8: MDCIRQ_CKEN + Bit 7: MDECT_CKEN + Bit 6: USIM2_CKEN + Bit 5: USIM1_CKEN + Bit 4: GPTMLITE_CKEN + Bit 3: MDGPTM_CKEN + Bit 2: I2C_CKEN + Bit 1: MDGDMA_CKEN + Bit 0: MDUART0_CKEN */ +#define R_MDPERI_DCM_MASK (0x0064)/* Bit 12: MDRGU_DCM_MASK + Bit 11: A7OST_DCM_MASK + Bit 10: MDOST_DCM_MASK + Bit 9: MDTOPSM_DCM_MASK */ +#define R_PSMCU_AO_CLK_CTL (0x00C0) +/* MD_PERI_MISC_BASE+ */ +#define R_L1_PMS (0x00C4) +/* PMDL1A0_BASE+ */ +#define REG_DCM_PLLCK_SEL (0x0188) /* Bit 7: 0: clock do not from PLL, 1: clock from PLL */ +#define R_L1MCU_PWR_AWARE (0x0190) +#define R_L1AO_PWR_AWARE (0x0194) +#define R_BUSL2DCM_CON3 (0x0198) +#define R_L1MCU_DCM_CON2 (0x0184) +#define R_L1MCU_DCM_CON (0x0180) +/* ap_mixed_base+ */ +#define AP_PLL_CON0 0x0 /* ((UINT32P)(APMIXED_BASE+0x0)) */ +#define MDPLL1_CON0 0x2C8 /* ((UINT32P)(APMIXED_BASE+0x02C8)) */ + +/* CCIF */ +#define APCCIF_CON (0x00) +#define APCCIF_BUSY (0x04) +#define APCCIF_START (0x08) +#define APCCIF_TCHNUM (0x0C) +#define APCCIF_RCHNUM (0x10) +#define APCCIF_ACK (0x14) +#define APCCIF_CHDATA (0x100) +#define APCCIF_SRAM_SIZE 512 +/* channel usage */ +#define EXCEPTION_NONE (0) +/* AP to MD */ +#define H2D_EXCEPTION_ACK (1) +#define H2D_EXCEPTION_CLEARQ_ACK (2) +#define H2D_FORCE_MD_ASSERT (3) +#define H2D_MPU_FORCE_ASSERT (4) +/* MD to AP */ +#define D2H_EXCEPTION_INIT (1) +#define D2H_EXCEPTION_INIT_DONE (2) +#define D2H_EXCEPTION_CLEARQ_DONE (3) +#define D2H_EXCEPTION_ALLQ_RESET (4) +/* peer */ +#define AP_MD_PEER_WAKEUP (5) +#define AP_MD_SEQ_ERROR (6) +#define AP_MD_CCB_WAKEUP (8) + +struct md_pll_reg { + void __iomem *md_clkSW; + void __iomem *md_dcm; + void __iomem *psmcu_misc; + void __iomem *md_peri_misc; + void __iomem *md_L1_a0; + void __iomem *md_top_Pll; + void __iomem *md_sys_clk; + /*void __iomem *md_l1_conf;*/ + /* the follow is used for dump */ + void __iomem *md_pc_mon1; + void __iomem *md_pc_mon2; + void __iomem *md_busreg1; + void __iomem *md_busreg2; + void __iomem *md_busrec; + void __iomem *md_ect_0; + void __iomem *md_ect_1; + void __iomem *md_ect_2; + void __iomem *md_ect_3; + void __iomem *md_bootup_0; + void __iomem *md_bootup_1; + void __iomem *md_bootup_2; + void __iomem *md_bootup_3; + void __iomem *md_clk_ctl01; + void __iomem *md_clk_ctl02; + void __iomem *md_clk_ctl03; + void __iomem *md_clk_ctl04; + void __iomem *md_clk_ctl05; + void __iomem *md_clk_ctl06; + void __iomem *md_clk_ctl07; + void __iomem *md_clk_ctl08; + void __iomem *md_clk_ctl09; + void __iomem *md_clk_ctl10; + void __iomem *md_clk_ctl11; + void __iomem *md_clk_ctl12; + void __iomem *md_clk_ctl13; + void __iomem *md_clk_ctl14; + void __iomem *md_clk_ctl15; + void __iomem *md_boot_stats0; + void __iomem *md_boot_stats1; +}; +#define MD_BUSREG_DUMP_ADDR1 0x20060000 +#define MD_BUSREG_DUMP_LEN1 (0xF8) +#define MD_BUSREG_DUMP_ADDR2 0x20200000 +#define MD_BUSREG_DUMP_LEN2 (0xE4) +#define MD_BUSREC_DUMP_ADDR 0x203C0000 +#define MD_BUSREC_DUMP_LEN (0x41C) +#define MD_ECT_DUMP_ADDR0 0x200D0A00 +#define MD_ECT_DUMP_LEN0 (0x30) +#define MD_ECT_DUMP_ADDR1 0x10478130 +#define MD_ECT_DUMP_LEN1 (8) +#define MD_ECT_DUMP_ADDR2 0x1046B130 +#define MD_ECT_DUMP_LEN2 (8) +#define MD_ECT_DUMP_ADDR3 0x1046C130 +#define MD_ECT_DUMP_LEN3 (8) +#define MD_Bootup_DUMP_ADDR0 0x20060100 +#define MD_Bootup_DUMP_LEN0 (4) +#define MD_Bootup_DUMP_ADDR1 0x20060200 +#define MD_Bootup_DUMP_LEN1 (4) +#define MD_Bootup_DUMP_ADDR2 0x20141000 +#define MD_Bootup_DUMP_LEN2 (4) +#define MD_Bootup_DUMP_ADDR3 0x20070498 +#define MD_Bootup_DUMP_LEN3 (4) +#define MD_Clkctrl_DUMP_ADDR01 0x20150100 +#define MD_Clkctrl_DUMP_LEN01 0x18 +#define MD_Clkctrl_DUMP_ADDR02 0x20151000 +#define MD_Clkctrl_DUMP_LEN02 0x4 +#define MD_Clkctrl_DUMP_ADDR03 0x20140000 +#define MD_Clkctrl_DUMP_LEN03 0x9C +#define MD_Clkctrl_DUMP_ADDR04 0x20140200 +#define MD_Clkctrl_DUMP_LEN04 0x8 +#define MD_Clkctrl_DUMP_ADDR05 0x20140300 +#define MD_Clkctrl_DUMP_LEN05 0x10 +#define MD_Clkctrl_DUMP_ADDR06 0x20140400 +#define MD_Clkctrl_DUMP_LEN06 0x138 +#define MD_Clkctrl_DUMP_ADDR07 0x20140600 +#define MD_Clkctrl_DUMP_LEN07 0x34 +#define MD_Clkctrl_DUMP_ADDR08 0x20140800 +#define MD_Clkctrl_DUMP_LEN08 0x8 +#define MD_Clkctrl_DUMP_ADDR09 0x20130000 +#define MD_Clkctrl_DUMP_LEN09 0x50 +#define MD_Clkctrl_DUMP_ADDR10 0x20130080 +#define MD_Clkctrl_DUMP_LEN10 0x90 +#define MD_Clkctrl_DUMP_ADDR11 0x20130400 +#define MD_Clkctrl_DUMP_LEN11 0x4 +#define MD_Clkctrl_DUMP_ADDR12 0x20130800 +#define MD_Clkctrl_DUMP_LEN12 0x8 +#define MD_Clkctrl_DUMP_ADDR13 0x20130C00 +#define MD_Clkctrl_DUMP_LEN13 0x10 +#define MD_Clkctrl_DUMP_ADDR14 0x20131000 +#define MD_Clkctrl_DUMP_LEN14 0x4 +#define MD_Clkctrl_DUMP_ADDR15 0x20120000 +#define MD_Clkctrl_DUMP_LEN15 0xC4 + +struct md_hw_info { + /* HW info - Register Address */ + unsigned long cldma_ap_ao_base; + unsigned long cldma_md_ao_base; + unsigned long cldma_ap_pdn_base; + unsigned long cldma_md_pdn_base; + unsigned long md_rgu_base; + unsigned long l1_rgu_base; + unsigned long ap_mixed_base; + unsigned long md_boot_slave_Vector; + unsigned long md_boot_slave_Key; + unsigned long md_boot_slave_En; + unsigned long ap_ccif_base; + unsigned long md_ccif_base; + unsigned int sram_size; + + /* HW info - Interrutpt ID */ + unsigned int cldma_irq_id; + unsigned int ap_ccif_irq_id; + unsigned int md_wdt_irq_id; + unsigned int ap2md_bus_timeout_irq_id; + + /* HW info - Interrupt flags */ + unsigned long cldma_irq_flags; + unsigned long ap_ccif_irq_flags; + unsigned long md_wdt_irq_flags; + unsigned long ap2md_bus_timeout_irq_flags; +}; + +int ccci_modem_remove(struct platform_device *dev); +void ccci_modem_shutdown(struct platform_device *dev); +int ccci_modem_suspend(struct platform_device *dev, pm_message_t state); +int ccci_modem_resume(struct platform_device *dev); +int ccci_modem_pm_suspend(struct device *device); +int ccci_modem_pm_resume(struct device *device); +int ccci_modem_pm_restore_noirq(struct device *device); +int md_cd_power_on(struct ccci_modem *md); +int md_cd_power_off(struct ccci_modem *md, unsigned int stop_type); +int md_cd_soft_power_off(struct ccci_modem *md, unsigned int mode); +int md_cd_soft_power_on(struct ccci_modem *md, unsigned int mode); +int md_cd_let_md_go(struct ccci_modem *md); +void md_cd_lock_cldma_clock_src(int locked); +void md_cd_lock_modem_clock_src(int locked); +int md_cd_bootup_cleanup(struct ccci_modem *md, int success); +int md_cd_low_power_notify(struct ccci_modem *md, LOW_POEWR_NOTIFY_TYPE type, int level); +int md_cd_get_modem_hw_info(struct platform_device *dev_ptr, struct ccci_dev_cfg *dev_cfg, struct md_hw_info *hw_info); +int md_cd_io_remap_md_side_register(struct ccci_modem *md); +void md_cd_dump_debug_register(struct ccci_modem *md); +void md_cd_dump_md_bootup_status(struct ccci_modem *md); +void md_cd_check_emi_state(struct ccci_modem *md, int polling); +void cldma_dump_register(struct ccci_modem *md); +void md_cldma_hw_reset(struct ccci_modem *md); +/* ADD_SYS_CORE */ +int ccci_modem_syssuspend(void); +void ccci_modem_sysresume(void); +void md_cd_check_md_DCM(struct ccci_modem *md); + +extern unsigned long infra_ao_base; +extern void ccci_mem_dump(int md_id, void *start_addr, int len); +extern void subsys_if_on(void); +#endif /* __CLDMA_PLATFORM_H__ */ diff --git a/drivers/misc/mediatek/eccci/mt6755/cldma_reg.h b/drivers/misc/mediatek/eccci/mt6755/cldma_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..3a80213c7ae48ec2a509111d92de945d7c1d1d7d --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/cldma_reg.h @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __CLDMA_REG_H__ +#define __CLDMA_REG_H__ + +#include +/* INFRA */ +#define INFRA_RST0_REG_PD (0x0150) /*(0x0030)*/ /* rgu reset cldma reg */ +#define INFRA_RST1_REG_PD (0x0154) /*(0x0034)*/ /* rgu clear cldma reset reg */ +#define CLDMA_PD_RST_MASK (1<<2) +#define INFRA_RST0_REG_AO (0x0140) +#define INFRA_RST1_REG_AO (0x0144) +#define CLDMA_AO_RST_MASK (1<<6) + +#define INFRA_AO_MD_SRCCLKENA (0xF0C) /* SRC CLK ENA */ +/*===========================CLDMA_AO_INDMA: 10014804-10014844==================================*/ +#define CLDMA_AP_UL_START_ADDR_BK_0 (0x0804) + /* The start address of first TGPD descriptor for power-down back-up. */ +#define CLDMA_AP_UL_START_ADDR_BK_1 (0x0808) +#define CLDMA_AP_UL_START_ADDR_BK_2 (0x080C) +#define CLDMA_AP_UL_START_ADDR_BK_3 (0x0810) +#define CLDMA_AP_UL_START_ADDR_BK_4 (0x0814) +#define CLDMA_AP_UL_START_ADDR_BK_5 (0x0818) +#define CLDMA_AP_UL_START_ADDR_BK_6 (0x081C) +#define CLDMA_AP_UL_START_ADDR_BK_7 (0x0820) +#define CLDMA_AP_UL_CURRENT_ADDR_BK_0 (0x0828) + /* The address of current processing TGPD descriptor for power-down back-up. */ +#define CLDMA_AP_UL_CURRENT_ADDR_BK_1 (0x082C) +#define CLDMA_AP_UL_CURRENT_ADDR_BK_2 (0x0830) +#define CLDMA_AP_UL_CURRENT_ADDR_BK_3 (0x0834) +#define CLDMA_AP_UL_CURRENT_ADDR_BK_4 (0x0838) +#define CLDMA_AP_UL_CURRENT_ADDR_BK_5 (0x083C) +#define CLDMA_AP_UL_CURRENT_ADDR_BK_6 (0x0840) +#define CLDMA_AP_UL_CURRENT_ADDR_BK_7 (0x0844) +/*===========================CLDMA_AO_OUTDMA:10014A04-10014B2C==================================*/ +#define CLDMA_AP_SO_CFG (0x0A04) /* Operation Configuration */ +#define CLDMA_AP_SO_DUMMY_2 (0x0A10) /* Dummy Register 2 */ +#define CLDMA_AP_SO_DUMMY_3 (0x0A14) /* Dummy Register 3 */ +#define CLDMA_AP_SO_CHECKSUM_CHANNEL_ENABLE (0x0A74) /* Per-channel checksum checking function enable */ +#define CLDMA_AP_SO_START_ADDR_0 (0x0A78) /* The start address of first RGPD descriptor */ +#define CLDMA_AP_SO_START_ADDR_1 (0x0A7C) /* The start address of first RGPD descriptor */ +#define CLDMA_AP_SO_START_ADDR_2 (0x0A80) /* The start address of first RGPD descriptor */ +#define CLDMA_AP_SO_START_ADDR_3 (0x0A84) /* The start address of first RGPD descriptor */ +#define CLDMA_AP_SO_START_ADDR_4 (0x0A88) /* The start address of first RGPD descriptor */ +#define CLDMA_AP_SO_START_ADDR_5 (0x0A8C) /* The start address of first RGPD descriptor */ +#define CLDMA_AP_SO_START_ADDR_6 (0x0A90) /* The start address of first RGPD descriptor */ +#define CLDMA_AP_SO_START_ADDR_7 (0x0A94) /* The start address of first RGPD descriptor */ +#define CLDMA_AP_SO_CURRENT_ADDR_0 (0x0A98) /* The address of current processing RGPD descriptor. */ +#define CLDMA_AP_SO_CURRENT_ADDR_1 (0x0A9C) /* The address of current processing RGPD descriptor. */ +#define CLDMA_AP_SO_CURRENT_ADDR_2 (0x0AA0) /* The address of current processing RGPD descriptor. */ +#define CLDMA_AP_SO_CURRENT_ADDR_3 (0x0AA4) /* The address of current processing RGPD descriptor. */ +#define CLDMA_AP_SO_CURRENT_ADDR_4 (0x0AA8) /* The address of current processing RGPD descriptor. */ +#define CLDMA_AP_SO_CURRENT_ADDR_5 (0x0AAC) /* The address of current processing RGPD descriptor. */ +#define CLDMA_AP_SO_CURRENT_ADDR_6 (0x0AB0) /* The address of current processing RGPD descriptor. */ +#define CLDMA_AP_SO_CURRENT_ADDR_7 (0x0AB4) /* The address of current processing RGPD descriptor. */ +#define CLDMA_AP_SO_STATUS (0x0AB8) /* SME OUT SBDMA operation status. */ +#define CLDMA_AP_DEBUG_ID_EN (0x0AC8) /* DEBUG_ID Enable */ +#define CLDMA_AP_SO_LAST_UPDATE_ADDR_0 (0x0AD0) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_SO_LAST_UPDATE_ADDR_1 (0x0AD4) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_SO_LAST_UPDATE_ADDR_2 (0x0AD8) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_SO_LAST_UPDATE_ADDR_3 (0x0ADC) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_SO_LAST_UPDATE_ADDR_4 (0x0AE0) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_SO_LAST_UPDATE_ADDR_5 (0x0AE4) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_SO_LAST_UPDATE_ADDR_6 (0x0AE8) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_SO_LAST_UPDATE_ADDR_7 (0x0AEC) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_SO_NEXT_ALLOW_LEN_1 (0x0AF0) /* Next allow buffer length */ +#define CLDMA_AP_SO_NEXT_ALLOW_LEN_2 (0x0AF4) /* Next allow buffer length */ +#define CLDMA_AP_SO_NEXT_ALLOW_LEN_3 (0x0AF8) /* Next allow buffer length */ +#define CLDMA_AP_SO_NEXT_ALLOW_LEN_4 (0x0AFC) /* Next allow buffer length */ +#define CLDMA_AP_SO_NEXT_ALLOW_LEN_5 (0x0B00) /* Next allow buffer length */ +#define CLDMA_AP_SO_NEXT_ALLOW_LEN_6 (0x0B04) /* Next allow buffer length */ +#define CLDMA_AP_SO_NEXT_ALLOW_LEN_7 (0x0B08) /* Next allow buffer length */ +#define CLDMA_AP_SO_NEXT_BUF_PTR_0 (0x0B10) /* Next data buffer pointer */ +#define CLDMA_AP_SO_NEXT_BUF_PTR_1 (0x0B14) /* Next data buffer pointer */ +#define CLDMA_AP_SO_NEXT_BUF_PTR_2 (0x0B18) /* Next data buffer pointer */ +#define CLDMA_AP_SO_NEXT_BUF_PTR_3 (0x0B1C) /* Next data buffer pointer */ +#define CLDMA_AP_SO_NEXT_BUF_PTR_4 (0x0B20) /* Next data buffer pointer */ +#define CLDMA_AP_SO_NEXT_BUF_PTR_5 (0x0B24) /* Next data buffer pointer */ +#define CLDMA_AP_SO_NEXT_BUF_PTR_6 (0x0B28) /* Next data buffer pointer */ +#define CLDMA_AP_SO_NEXT_BUF_PTR_7 (0x0B2C) /* Next data buffer pointer */ +/*=======================CLDMA_AO_MISC: 10014C58-10014D50==================================*/ +#define CLDMA_AP_L2RIMR0 (0x0C58) /* Level 2 Interrupt Mask Register (RX Part) */ +#define CLDMA_AP_L2RIMR1 (0x0C5C) /* Level 2 Interrupt Mask Register (RX Part) */ +#define CLDMA_AP_L2RIMCR0 (0x0C60) /* Level 2 Interrupt Mask Clear Register (RX Part) */ +#define CLDMA_AP_L2RIMCR1 (0x0C64) /* Level 2 Interrupt Mask Clear Register (RX Part) */ +#define CLDMA_AP_L2RIMSR0 (0x0C68) /* Level 2 Interrupt Mask Set Register (RX Part) */ +#define CLDMA_AP_L2RIMSR1 (0x0C6C) /* Level 2 Interrupt Mask Set Register (RX Part) */ +#define CLDMA_AP_BUS_CFG (0x0C90) /* LTEL2_BUS_INTF configuration register */ +#define CLDMA_AP_CHNL_DISABLE (0x0C94) /* Dma channel disable register */ +#define CLDMA_AP_HIGH_PRIORITY (0x0C98) /* Dma channel high priority register */ +#define CLDMA_AP_ADDR_REMAP_FROM (0x0D44) /* Address Remap From Which Bank */ +#define CLDMA_AP_ADDR_REMAP_TO (0x0D48) /* Address Remap To Which Bank */ +#define CLDMA_AP_ADDR_REMAP_MASK (0x0D4C) /* Address Remap Mask */ +#define CLDMA_AP_DUMMY (0x0D50) /* Dummy Register */ +/*=======================CLDMA_PD_INDMA: 1021B000-1021B160==================================*/ +#define CLDMA_AP_UL_SBDMA_CODA_VERSION (0x0000) /* ULSBDMA Version Control Register */ +#define CLDMA_AP_UL_START_ADDR_0 (0x0004) /* The start address of first TGPD descriptor */ +#define CLDMA_AP_UL_START_ADDR_1 (0x0008) /* The start address of first TGPD descriptor */ +#define CLDMA_AP_UL_START_ADDR_2 (0x000C) /* The start address of first TGPD descriptor */ +#define CLDMA_AP_UL_START_ADDR_3 (0x0010) /* The start address of first TGPD descriptor */ +#define CLDMA_AP_UL_START_ADDR_4 (0x0014) /* The start address of first TGPD descriptor */ +#define CLDMA_AP_UL_START_ADDR_5 (0x0018) /* The start address of first TGPD descriptor */ +#define CLDMA_AP_UL_START_ADDR_6 (0x001C) /* The start address of first TGPD descriptor */ +#define CLDMA_AP_UL_START_ADDR_7 (0x0020) /* The start address of first TGPD descriptor */ +#define CLDMA_AP_UL_CURRENT_ADDR_0 (0x0028) /* The address of current processing TGPD descriptor. */ +#define CLDMA_AP_UL_CURRENT_ADDR_1 (0x002C) /* The address of current processing TGPD descriptor. */ +#define CLDMA_AP_UL_CURRENT_ADDR_2 (0x0030) /* The address of current processing TGPD descriptor. */ +#define CLDMA_AP_UL_CURRENT_ADDR_3 (0x0034) /* The address of current processing TGPD descriptor. */ +#define CLDMA_AP_UL_CURRENT_ADDR_4 (0x0038) /* The address of current processing TGPD descriptor. */ +#define CLDMA_AP_UL_CURRENT_ADDR_5 (0x003C) /* The address of current processing TGPD descriptor. */ +#define CLDMA_AP_UL_CURRENT_ADDR_6 (0x0040) /* The address of current processing TGPD descriptor. */ +#define CLDMA_AP_UL_CURRENT_ADDR_7 (0x0044) /* The address of current processing TGPD descriptor. */ +#define CLDMA_AP_UL_STATUS (0x0050) /* UL SBDMA operation status. */ +#define CLDMA_AP_UL_START_CMD (0x0054) /* UL START SBDMA command. */ +#define CLDMA_AP_UL_RESUME_CMD (0x0058) /* UL RESUME SBDMA command. */ +#define CLDMA_AP_UL_STOP_CMD (0x005C) /* UL STOP SBDMA command. */ +#define CLDMA_AP_UL_ERROR (0x0060) /* ERROR */ +#define CLDMA_AP_UL_CFG (0x0074) /* Operation Configuration */ +#define CLDMA_AP_UL_DUMMY_0 (0x0080) /* Dummy Register 0 */ +#define CLDMA_AP_UL_DUMMY_1 (0x0084) /* Dummy Register 1 */ +#define CLDMA_AP_UL_DUMMY_2 (0x0088) /* Dummy Register 2 */ +#define CLDMA_AP_UL_DUMMY_3 (0x008C) /* Dummy Register 3 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_0 (0x0090) /* Debug Register 0 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_1 (0x0094) /* Debug Register 1 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_2 (0x0098) /* Debug Register 2 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_3 (0x009C) /* Debug Register 3 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_4 (0x00A0) /* Debug Register 4 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_5 (0x00A4) /* Debug Register 5 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_6 (0x00A8) /* Debug Register 6 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_7 (0x00AC) /* Debug Register 7 */ +#define CLDMA_AP_UL_DEBUG_REG_LCMU_8 (0x00B0) /* Debug Register 8 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_0 (0x00B4) /* Debug Register 0 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_1 (0x00B8) /* Debug Register 1 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_2 (0x00BC) /* Debug Register 2 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_3 (0x00C0) /* Debug Register 3 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_4 (0x00C4) /* Debug Register 4 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_5 (0x00C8) /* Debug Register 5 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_6 (0x00CC) /* Debug Register 6 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_7 (0x00D0) /* Debug Register 7 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_8 (0x00D4) /* Debug Register 8 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_9 (0x00D8) /* Debug Register 9 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_10 (0x00DC) /* Debug Register 10 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_11 (0x00E0) /* Debug Register 11 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_12 (0x00E4) /* Debug Register 12 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_13 (0x00E8) /* Debug Register 13 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_14 (0x00EC) /* Debug Register 14 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMU_15 (0x00F0) /* Debug Register 15 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMA_0 (0x00F4) /* Debug Register 0 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMA_1 (0x00F8) /* Debug Register 1 */ +#define CLDMA_AP_UL_DEBUG_REG_LDMA_2 (0x00FC) /* Debug Register 2 */ +#define CLDMA_AP_UL_DEBUG_REG_REG_CTL_0 (0x0100) /* Debug Register 0 */ +#define CLDMA_AP_UL_DEBUG_REG_REG_CTL_1 (0x0104) /* Debug Register 1 */ +#define CLDMA_AP_UL_DEBUG_REG_REG_CTL_2 (0x0108) /* Debug Register 2 */ +#define CLDMA_AP_UL_DEBUG_REG_REG_CTL_3 (0x010C) /* Debug Register 3 */ +#define CLDMA_AP_HPQTCR (0x0110) /* High priority queue traffic control value */ +#define CLDMA_AP_LPQTCR (0x0114) /* Low priority queue traffic control value */ +#define CLDMA_AP_HPQR (0x0118) /* High priority queue register */ +#define CLDMA_AP_TCR0 (0x011C) /* Traffic control value for TX queue 0 */ +#define CLDMA_AP_TCR1 (0x0120) /* Traffic control value for TX queue 1 */ +#define CLDMA_AP_TCR2 (0x0124) /* Traffic control value for TX queue 2 */ +#define CLDMA_AP_TCR3 (0x0128) /* Traffic control value for TX queue 3 */ +#define CLDMA_AP_TCR4 (0x012C) /* Traffic control value for TX queue 4 */ +#define CLDMA_AP_TCR5 (0x0130) /* Traffic control value for TX queue 5 */ +#define CLDMA_AP_TCR6 (0x0134) /* Traffic control value for TX queue 6 */ +#define CLDMA_AP_TCR7 (0x0138) /* Traffic control value for TX queue 7 */ +#define CLDMA_AP_TCR_CMD (0x013C) /* Traffic control command register */ +#define CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE (0x0140) /* Per-channel checksum checking function enable */ +#define CLDMA_AP_UL_LAST_UPDATE_ADDR_0 (0x0144) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_UL_LAST_UPDATE_ADDR_1 (0x0148) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_UL_LAST_UPDATE_ADDR_2 (0x014C) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_UL_LAST_UPDATE_ADDR_3 (0x0150) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_UL_LAST_UPDATE_ADDR_4 (0x0154) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_UL_LAST_UPDATE_ADDR_5 (0x0158) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_UL_LAST_UPDATE_ADDR_6 (0x015C) /* The address of last updated TGPD descriptor. */ +#define CLDMA_AP_UL_LAST_UPDATE_ADDR_7 (0x0160) /* The address of last updated TGPD descriptor. */ + +/*========================CLDMA_PD_OUTDMA:1021B200-1021B3C4==================================*/ +#define CLDMA_AP_SO_OUTDMA_CODA_VERSION (0x0200) /* SOOUTDMA Version Control Register */ +#define CLDMA_AP_SO_ERROR (0x0300) /* ERROR */ +#define CLDMA_AP_SO_DUMMY_0 (0x0308) /* Dummy Register 0 */ +#define CLDMA_AP_SO_DUMMY_1 (0x030C) /* Dummy Register 1 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_0 (0x0318) /* Debug Register 0 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_1 (0x031C) /* Debug Register 1 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_2 (0x0320) /* Debug Register 2 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_3 (0x0324) /* Debug Register 3 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_4 (0x0328) /* Debug Register 4 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_5 (0x032C) /* Debug Register 5 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_6 (0x0330) /* Debug Register 6 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_7 (0x0334) /* Debug Register 7 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_8 (0x0338) /* Debug Register 8 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_9 (0x033C) /* Debug Register 9 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_10 (0x0340) /* Debug Register 10 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_11 (0x0344) /* Debug Register 11 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMU_12 (0x0348) /* Debug Register 12 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMA_0 (0x034C) /* Debug Register 0 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMA_1 (0x0350) /* Debug Register 1 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMA_2 (0x0354) /* Debug Register 2 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMA_3 (0x0358) /* Debug Register 3 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMA_4 (0x035C) /* Debug Register 4 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMA_5 (0x0360) /* Debug Register 5 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMA_6 (0x0364) /* Debug Register 6 */ +#define CLDMA_AP_SO_DEBUG_REG_LDMA_7 (0x0368) /* Debug Register 7 */ +#define CLDMA_AP_SO_DEBUG_REG_REG_CTL_0 (0x036C) /* Debug Register 0 */ +#define CLDMA_AP_SO_DEBUG_REG_REG_CTL_1 (0x0370) /* Debug Register 1 */ +#define CLDMA_AP_SO_START_CMD (0x03BC) /* SME OUT SBDMA START command. */ +#define CLDMA_AP_SO_RESUME_CMD (0x03C0) /* SO OUTDMA RESUME command. */ +#define CLDMA_AP_SO_STOP_CMD (0x03C4) /* SO OUTDMA STOP command. */ +/*===========================CLDMA_PD_MISC: 1021B400-1021B4B4================================*/ +#define CLDMA_AP_CLDMA_CODA_VERSION (0x0400) /* CLDMAVersion Control Register */ +#define CLDMA_AP_L2TISAR0 (0x0410) /* Level 2 Interrupt Status and Acknowledgment Register (TX Part) */ +#define CLDMA_AP_L2TISAR1 (0x0414) /* Level 2 Interrupt Status and Acknowledgment Register (TX Part) */ +#define CLDMA_AP_L2TIMR0 (0x0418) /* Level 2 Interrupt Mask Register (TX Part) */ +#define CLDMA_AP_L2TIMR1 (0x041C) /* Level 2 Interrupt Mask Register (TX Part) */ +#define CLDMA_AP_L2TIMCR0 (0x0420) /* Level 2 Interrupt Mask Clear Register (TX Part) */ +#define CLDMA_AP_L2TIMCR1 (0x0424) /* Level 2 Interrupt Mask Clear Register (TX Part) */ +#define CLDMA_AP_L2TIMSR0 (0x0428) /* Level 2 Interrupt Mask Set Register (TX Part) */ +#define CLDMA_AP_L2TIMSR1 (0x042C) /* Level 2 Interrupt Mask Set Register (TX Part) */ +#define CLDMA_AP_L3TISAR0 (0x0430) /* Level 3 Interrupt Status and Acknowledgment Register (TX Part) */ +#define CLDMA_AP_L3TISAR1 (0x0434) /* Level 3 Interrupt Status and Acknowledgment Register (TX Part) */ +#define CLDMA_AP_L3TIMR0 (0x0438) /* Level 3 Interrupt Mask Register (TX Part) */ +#define CLDMA_AP_L3TIMR1 (0x043C) /* Level 3 Interrupt Mask Register (TX Part) */ +#define CLDMA_AP_L3TIMCR0 (0x0440) /* Level 3 Interrupt Mask Clear Register (TX Part) */ +#define CLDMA_AP_L3TIMCR1 (0x0444) /* Level 3 Interrupt Mask Clear Register (TX Part) */ +#define CLDMA_AP_L3TIMSR0 (0x0448) /* Level 3 Interrupt Mask Set Register (TX Part) */ +#define CLDMA_AP_L3TIMSR1 (0x044C) /* Level 3 Interrupt Mask Set Register (TX Part) */ +#define CLDMA_AP_L2RISAR0 (0x0450) /* Level 2 Interrupt Status and Acknowledgment Register (RX Part) */ +#define CLDMA_AP_L2RISAR1 (0x0454) /* Level 2 Interrupt Status and Acknowledgment Register (RX Part) */ +#define CLDMA_AP_L3RISAR0 (0x0470) /* Level 3 Interrupt Status and Acknowledgment Register (RX Part) */ +#define CLDMA_AP_L3RISAR1 (0x0474) /* Level 3 Interrupt Status and Acknowledgment Register (RX Part) */ +#define CLDMA_AP_L3RIMR0 (0x0478) /* Level 3 Interrupt Mask Register (RX Part) */ +#define CLDMA_AP_L3RIMR1 (0x047C) /* Level 3 Interrupt Mask Register (RX Part) */ +#define CLDMA_AP_L3RIMCR0 (0x0480) /* Level 3 Interrupt Mask Clear Register (RX Part) */ +#define CLDMA_AP_L3RIMCR1 (0x0484) /* Level 3 Interrupt Mask Clear Register (RX Part) */ +#define CLDMA_AP_L3RIMSR0 (0x0488) /* Level 3 Interrupt MaskSet Register (RX Part) */ +#define CLDMA_AP_L3RIMSR1 (0x048C) /* Level 3 Interrupt Mask Set Register (RX Part) */ +#define CLDMA_AP_BUS_STA (0x049C) /* LTEL2_BUS_INTF status register */ +#define CLDMA_AP_BUS_DBG (0x04A0) /* Debug information of ltel2_axi_master */ +#define CLDMA_AP_DBG_RDATA (0x04A4) /* Debug information (rdata) of ltel2_axi_master */ +#define CLDMA_AP_DBG_WADDR (0x04A8) /* Debug information (waddr) of ltel2_axi_master */ +#define CLDMA_AP_DBG_WDATA (0x04AC) /* Debug information (wdata) of ltel2_axi_master */ +#define CLDMA_AP_CHNL_IDLE (0x04B0) /* Dma channel idle */ +#define CLDMA_AP_CLDMA_IP_BUSY (0x04B4) /* Half DMA busy status */ +#define CLDMA_AP_L3TISAR2 (0x04C0) /* Level3 Interrupt Status and Acknowledgment Register(TX Part) */ +#define CLDMA_AP_L3TIMR2 (0x04C4) /* Level3 Interrupt Mask Register(TX Part) */ +#define CLDMA_AP_L3TIMCR2 (0x04C8) /* Level3 Interrupt Mask Clear Register(TX Part) */ +#define CLDMA_AP_L3TIMSR2 (0x04CC) /* Level3 Interrupt Mask Set Register(TX Part) */ + +/*assistant macros*/ +#define CLDMA_AP_TQSAR(i) (CLDMA_AP_UL_START_ADDR_0 + (4 * (i))) +#define CLDMA_AP_TQCPR(i) (CLDMA_AP_UL_CURRENT_ADDR_0 + (4 * (i))) +#define CLDMA_AP_RQSAR(i) (CLDMA_AP_SO_START_ADDR_0 + (4 * (i))) +#define CLDMA_AP_RQCPR(i) (CLDMA_AP_SO_CURRENT_ADDR_0 + (4 * (i))) +#define CLDMA_AP_TQTCR(i) (CLDMA_AP_TCR0 + (4 * (i))) +#define CLDMA_AP_TQSABAK(i) (CLDMA_AP_UL_START_ADDR_BK_0 + (4 * (i))) +#define CLDMA_AP_TQCPBAK(i) (CLDMA_AP_UL_CURRENT_ADDR_BK_0 + (4 * (i))) + +#define cldma_write32(b, a, v) mt_reg_sync_writel(v, (b)+(a)) +#define cldma_write16(b, a, v) mt_reg_sync_writew(v, (b)+(a)) +#define cldma_write8(b, a, v) mt_reg_sync_writeb(v, (b)+(a)) + +#define cldma_read32(b, a) ioread32((void __iomem *)((b)+(a))) +#define cldma_read16(b, a) ioread16((void __iomem *)((b)+(a))) +#define cldma_read8(b, a) ioread8((void __iomem *)((b)+(a))) + +static inline void cldma_reg_set_tx_start_addr(void *base, int idx, dma_addr_t addr) +{ + cldma_write32(base, CLDMA_AP_TQSAR(idx), (u32)addr); +} +static inline void cldma_reg_set_tx_start_addr_bk(void *base, int idx, dma_addr_t addr) +{ + /*Set start bak address in power on domain*/ + cldma_write32(base, CLDMA_AP_TQSABAK(idx), (u32)addr); +} + +static inline void cldma_reg_set_rx_start_addr(void *base, int idx, dma_addr_t addr) +{ + cldma_write32(base, CLDMA_AP_RQSAR(idx), (u32)addr); +} +/*bitmap*/ +#define CLDMA_BM_INT_ALL 0xFFFFFFFF +/* L2 interrupt */ +#define CLDMA_BM_INT_ACTIVE_START 0xFF000000 /* trigger start command on one active queue */ +#define CLDMA_BM_INT_ERROR 0x00FF0000 + /* error occurred on the specified queue, check L3 interrupt register for detail */ +#define CLDMA_BM_INT_QUEUE_EMPTY 0x0000FF00 /* when there is no GPD to be transmitted on the specified queue */ +#define CLDMA_BM_INT_DONE 0x000000FF /* when the transmission if the GPD on the specified queue is done */ +#define CLDMA_BM_INT_ACTIVE_LD_TC 0x000000FF /* modify TC register when one Tx channel is active */ +#define CLDMA_BM_INT_INACTIVE_ERR 0x000000FF /* asserted when a specified Rx queue is inactive */ +/* L3 interrupt */ +#define CLDMA_BM_INT_BD_LEN_ERR 0xFF000000 /* asserted when a length fild in BD is not configured correctly */ +#define CLDMA_BM_INT_GPD_LEN_ERR 0x00FF0000 /* asserted when a length fild in GPD is not configured correctly */ +#define CLDMA_BM_INT_BD_CSERR 0x0000FF00 /* asserted when the BD checksum error happen */ +#define CLDMA_BM_INT_GPD_CSERR 0x000000FF /* asserted when the GPD checksum error happen */ +#define CLDMA_BM_INT_DATA_LEN_MIS 0x00FF0000 /* TGPD data length mismatch error happen */ +#define CLDMA_BM_INT_BD_64KERR 0x0000FF00 /* asserted when the TBD length is more than 64K */ +#define CLDMA_BM_INT_GPD_64KERR 0x000000FF /* asserted when the TGPD length is more than 64K */ +#define CLDMA_BM_INT_RBIDX_ERR 0x80000000 /* internal error for Rx queue */ +#define CLDMA_BM_INT_FIFO_LEN_MIS 0x0000FF00 /* internal error for Rx queue */ +#define CLDMA_BM_INT_ALLEN 0x000000FF + /* asserted when the RGPD/RBD allow data buffer length is not enough */ + +#define CLDMA_BM_ALL_QUEUE 0x7F /* all 7 queues */ + +#endif /* __CLDMA_REG_H__ */ diff --git a/drivers/misc/mediatek/eccci/mt6755/modem_reg_base.h b/drivers/misc/mediatek/eccci/mt6755/modem_reg_base.h new file mode 100644 index 0000000000000000000000000000000000000000..f6354318027d2b5a295f68bace252191890e1943 --- /dev/null +++ b/drivers/misc/mediatek/eccci/mt6755/modem_reg_base.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MODEM_REG_BASE_H__ +#define __MODEM_REG_BASE_H__ + +/* ============================================================ */ +/* Modem 1 part */ +/* ============================================================ */ +/* MD peripheral register: MD bank8; AP bank2 */ +#define CLDMA_AP_BASE 0x200F0000 +#define CLDMA_AP_LENGTH 0x3000 +#define CLDMA_MD_BASE 0x200E0000 +#define CLDMA_MD_LENGTH 0x3000 + +#define MD_BOOT_VECTOR_EN 0x20000024 + +#define MD_GLOBAL_CON0 0x20000450 +#define MD_GLOBAL_CON0_CLDMA_BIT 12 +/* #define MD_PEER_WAKEUP 0x20030B00 */ +#define MD_BUS_STATUS_BASE 0x203B0000/* 0x20000000 */ +#define MD_BUS_STATUS_LENGTH 0x214 /*0x468 */ +#define MD_PC_MONITOR_BASE 0x10473000 /* 0x201F0000 */ +#define MD_PC_MONITOR_LENGTH 0x500 /* 0x114 */ +#define MD_PC_MONITORL1_BASE 0x1046F000 /* 0x201F0000 */ +#define MD_PC_MONITORL1_LENGTH 0x500 /* 0x114 */ +#define MD_TOPSM_STATUS_BASE 0x200D0000 /* 0x20030000 */ +#define MD_TOPSM_STATUS_LENGTH 0xC30 /* 0xBFF */ +#define MD_OST_STATUS_BASE 0x200E000 /* 0x20040000 */ +#define MD_OST_STATUS_LENGTH 0x228 /* 0x1FF */ +/* #define _MD_CCIF0_BASE (AP_CCIF0_BASE+0x1000) */ +#define CCIF_SRAM_SIZE 512 + +#define BASE_ADDR_MDRSTCTL 0x200f0000 /* From md, no use by AP directly */ +#define L1_BASE_ADDR_L1RGU 0x26010000 /* From md, no use by AP directly */ +#define MD_RGU_BASE (BASE_ADDR_MDRSTCTL + 0x100) /* AP use */ +#define L1_RGU_BASE L1_BASE_ADDR_L1RGU /* AP use */ + +/* MD1 PLL */ +#define MD_CLKSW_BASE (0x20150000) +#define MD_CLKSW_LENGTH 0x118 +#define MD_GLOBAL_CON_DCM_BASE (0x20130000) +#define MD_GLOBAL_CON_DCM_LEN 0x1004 +#define PSMCU_MISC_BASE (0x20200000) +#define MD_PERI_MISC_BASE (0x20060000) +#define MD_PERI_MISC_LEN 0xD0 +#define MDL1A0_BASE (0x260F0000) +#define MDL1A0_LEN 0x200 +#define MDTOP_PLLMIXED_BASE (0x20140000) +#define MDSYS_CLKCTL_BASE (0x20120000) +#define MDSYS_CLKCTL_LEN 0xD0 +/*#define L1_BASE_MADDR_MDL1_CONF (0x260F0000)*/ + +/*MD bootup register*/ +/* in modem view */ +/* #define MD1_CFG_BASE (0x20000000) */ +/* #define MD1_CFG_BOOT_STATS0 (MD1_CFG_BASE+0x70) */ +/* #define MD1_CFG_BOOT_STATS1 (MD1_CFG_BASE+0x74) */ + +/* in AP infra view */ +#define MD1_CFG_BOOT_STATS0 (0x10201300) +#define MD1_CFG_BOOT_STATS1 (0x10201304) +/* ============================================================ */ +/* Modem 2 part */ +/* ============================================================ */ +#define MD2_BOOT_VECTOR 0x30190000 +#define MD2_BOOT_VECTOR_KEY 0x3019379C +#define MD2_BOOT_VECTOR_EN 0x30195488 + +#define MD2_BOOT_VECTOR_VALUE 0x00000000 +#define MD2_BOOT_VECTOR_KEY_VALUE 0x3567C766 +#define MD2_BOOT_VECTOR_EN_VALUE 0xA3B66175 +#define MD2_RGU_BASE 0x30050000 +#define APCCIF1_SRAM_SIZE 512 + +/* +* ============================================================ +* Modem 3 part +* ============================================================ +* need modify, haow +*/ +#define MD3_BOOT_VECTOR 0x30190000 +#define MD3_BOOT_VECTOR_KEY 0x3019379C +#define MD3_BOOT_VECTOR_EN 0x30195488 + +#define MD3_BOOT_VECTOR_VALUE 0x00000000 +#define MD3_BOOT_VECTOR_KEY_VALUE 0x3567C766 +#define MD3_BOOT_VECTOR_EN_VALUE 0xA3B66175 + +#define MD3_RGU_BASE 0x3A001080 +#define APCCIF1_SRAM_SIZE 512 + +#endif /* __MODEM_REG_BASE_H__ */ diff --git a/drivers/misc/mediatek/emi_bwl/mt6755/Makefile b/drivers/misc/mediatek/emi_bwl/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1c9c856ea8aadc24f4870ad90ff0d83e17cdd0c6 --- /dev/null +++ b/drivers/misc/mediatek/emi_bwl/mt6755/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += emi_bwl.o diff --git a/drivers/misc/mediatek/emi_bwl/mt6755/emi_bwl.c b/drivers/misc/mediatek/emi_bwl/mt6755/emi_bwl.c new file mode 100644 index 0000000000000000000000000000000000000000..6b1d056910022ff89417103d83a39121a815278c --- /dev/null +++ b/drivers/misc/mediatek/emi_bwl/mt6755/emi_bwl.c @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MET_USER_EVENT_SUPPORT +/* #include */ + +#include +#include + +#include "mach/emi_bwl.h" + +DEFINE_SEMAPHORE(emi_bwl_sem); +void __iomem *EMI_BASE_ADDR = NULL; + +static struct platform_driver mem_bw_ctrl = { + .driver = { + .name = "mem_bw_ctrl", + .owner = THIS_MODULE, + }, +}; + +static struct platform_driver ddr_type = { + .driver = { + .name = "ddr_type", + .owner = THIS_MODULE, + }, +}; + +/* define EMI bandwiwth limiter control table */ +static struct emi_bwl_ctrl ctrl_tbl[NR_CON_SCE]; + +/* current concurrency scenario */ +static int cur_con_sce = 0x0FFFFFFF; + + +/* define concurrency scenario strings */ +static const char const *con_sce_str[] = { +#define X_CON_SCE(con_sce, arba, arbb, arbc, \ +arbd, arbe, arbf, arbg2) (#con_sce), +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE +}; + +/****************** For LPDDR3-1800******************/ + +static const unsigned int emi_arba_lpddr3_1800_val[] = { +#define X_CON_SCE(con_sce, arba, arbb, arbc, arbd, arbe, arbf, arbg2) arba, +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE +}; +static const unsigned int emi_arbb_lpddr3_1800_val[] = { +#define X_CON_SCE(con_sce, arba, arbb, arbc, arbd, arbe, arbf, arbg2) arbb, +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE +}; +static const unsigned int emi_arbc_lpddr3_1800_val[] = { +#define X_CON_SCE(con_sce, arba, arbb, arbc, arbd, arbe, arbf, arbg2) arbc, +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE +}; +static const unsigned int emi_arbd_lpddr3_1800_val[] = { +#define X_CON_SCE(con_sce, arba, arbb, arbc, arbd, arbe, arbf, arbg2) arbd, +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE +}; +static const unsigned int emi_arbe_lpddr3_1800_val[] = { +#define X_CON_SCE(con_sce, arba, arbb, arbc, arbd, arbe, arbf, arbg2) arbe, +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE +}; +static const unsigned int emi_arbf_lpddr3_1800_val[] = { +#define X_CON_SCE(con_sce, arba, arbb, arbc, arbd, arbe, arbf, arbg2) arbf, +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE +}; +static const unsigned int emi_arbg2_lpddr3_1800_val[] = { +#define X_CON_SCE(con_sce, arba, arbb, arbc, arbd, arbe, arbf, arbg2) arbg2, +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE +}; + + +int get_dram_type(void) +{ + unsigned int value = ucDram_Register_Read(DRAMC_ACTIM1); + + if ((value >> 28) & 0x1) + return LPDDR3_1800; + else + return LPDDR2_1066; +} + + +/* + * mtk_mem_bw_ctrl: set EMI bandwidth limiter for memory bandwidth control + * @sce: concurrency scenario ID + * @op: either ENABLE_CON_SCE or DISABLE_CON_SCE + * Return 0 for success; return negative values for failure. + */ +int mtk_mem_bw_ctrl(int sce, int op) +{ + int i, highest; + + if (sce >= NR_CON_SCE) + return -1; + + if (op != ENABLE_CON_SCE && op != DISABLE_CON_SCE) + return -1; + if (in_interrupt()) + return -1; + + down(&emi_bwl_sem); + + if (op == ENABLE_CON_SCE) + ctrl_tbl[sce].ref_cnt++; + else if (op == DISABLE_CON_SCE) { + if (ctrl_tbl[sce].ref_cnt != 0) + ctrl_tbl[sce].ref_cnt--; + } + + /* find the scenario with the highest priority */ + highest = -1; + for (i = 0; i < NR_CON_SCE; i++) { + if (ctrl_tbl[i].ref_cnt != 0) { + highest = i; + break; + } + } + if (highest == -1) + highest = CON_SCE_NORMAL; + + /* set new EMI bandwidth limiter value */ + if (highest != cur_con_sce) { + if (get_dram_type() == LPDDR3_1800) { + writel(emi_arba_lpddr3_1800_val[highest], EMI_ARBA); + writel(emi_arbb_lpddr3_1800_val[highest], EMI_ARBB); + writel(emi_arbc_lpddr3_1800_val[highest], EMI_ARBC); + writel(emi_arbd_lpddr3_1800_val[highest], EMI_ARBD); + writel(emi_arbe_lpddr3_1800_val[highest], EMI_ARBE); + writel(emi_arbf_lpddr3_1800_val[highest], EMI_ARBF); + mt_reg_sync_writel(emi_arbg2_lpddr3_1800_val[highest], + EMI_ARBG_2ND); + } + cur_con_sce = highest; + } + up(&emi_bwl_sem); + return 0; +} + +/* + * ddr_type_show: sysfs ddr_type file show function. + * @driver: + * @buf: the string of ddr type + * Return the number of read bytes. + */ +static ssize_t ddr_type_show(struct device_driver *driver, char *buf) +{ + if (get_dram_type() == LPDDR3_1800) + sprintf(buf, "LPDDR3_1800\n"); + else if (get_dram_type() == LPDDR2_1066) + sprintf(buf, "LPDDR2_1066\n"); + + return strlen(buf); +} + +/* + * ddr_type_store: sysfs ddr_type file store function. + * @driver: + * @buf: + * @count: + * Return the number of write bytes. + */ +static ssize_t ddr_type_store(struct device_driver *driver, +const char *buf, size_t count) +{ + /*do nothing*/ + return count; +} + +DRIVER_ATTR(ddr_type, 0644, ddr_type_show, ddr_type_store); + +/* + * con_sce_show: sysfs con_sce file show function. + * @driver: + * @buf: + * Return the number of read bytes. + */ +static ssize_t con_sce_show(struct device_driver *driver, char *buf) +{ + char *ptr = buf; + int i = 0; + + if (cur_con_sce >= NR_CON_SCE) + ptr += sprintf(ptr, "none\n"); + else + ptr += sprintf(ptr, "current scenario: %s\n", + con_sce_str[cur_con_sce]); + +#if 1 + ptr += sprintf(ptr, "%s\n", con_sce_str[cur_con_sce]); + ptr += sprintf(ptr, "EMI_ARBA = 0x%x\n", readl(IOMEM(EMI_ARBA))); + ptr += sprintf(ptr, "EMI_ARBB = 0x%x\n", readl(IOMEM(EMI_ARBB))); + ptr += sprintf(ptr, "EMI_ARBC = 0x%x\n", readl(IOMEM(EMI_ARBC))); + ptr += sprintf(ptr, "EMI_ARBD = 0x%x\n", readl(IOMEM(EMI_ARBD))); + ptr += sprintf(ptr, "EMI_ARBE = 0x%x\n", readl(IOMEM(EMI_ARBE))); + ptr += sprintf(ptr, "EMI_ARBF = 0x%x\n", readl(IOMEM(EMI_ARBF))); + ptr += sprintf(ptr, "EMI_ARBG = 0x%x\n", readl(IOMEM(EMI_ARBG_2ND))); + for (i = 0; i < NR_CON_SCE; i++) + ptr += sprintf(ptr, "%s = 0x%x\n", con_sce_str[i], + ctrl_tbl[i].ref_cnt); + + pr_debug("[EMI BWL] EMI_ARBA = 0x%x\n", readl(IOMEM(EMI_ARBA))); + pr_debug("[EMI BWL] EMI_ARBB = 0x%x\n", readl(IOMEM(EMI_ARBB))); + pr_debug("[EMI BWL] EMI_ARBC = 0x%x\n", readl(IOMEM(EMI_ARBC))); + pr_debug("[EMI BWL] EMI_ARBD = 0x%x\n", readl(IOMEM(EMI_ARBD))); + pr_debug("[EMI BWL] EMI_ARBE = 0x%x\n", readl(IOMEM(EMI_ARBE))); + pr_debug("[EMI BWL] EMI_ARBF = 0x%x\n", readl(IOMEM(EMI_ARBF))); + pr_debug("[EMI BWL] EMI_ARBG = 0x%x\n", readl(IOMEM(EMI_ARBG_2ND))); +#endif + + return strlen(buf); + +} + +/* + * con_sce_store: sysfs con_sce file store function. + * @driver: + * @buf: + * @count: + * Return the number of write bytes. + */ +static ssize_t con_sce_store(struct device_driver *driver, +const char *buf, size_t count) +{ + int i; + + for (i = 0; i < NR_CON_SCE; i++) { + if (!strncmp(buf, con_sce_str[i], + strlen(con_sce_str[i]))) { + if (!strncmp(buf + strlen(con_sce_str[i]) + 1, + EN_CON_SCE_STR, + strlen(EN_CON_SCE_STR))) { + mtk_mem_bw_ctrl(i, ENABLE_CON_SCE); + pr_debug("concurrency scenario %s ON\n", + con_sce_str[i]); + break; + } else if (!strncmp + (buf + strlen(con_sce_str[i]) + 1, + DIS_CON_SCE_STR, + strlen(DIS_CON_SCE_STR))) { + mtk_mem_bw_ctrl(i, DISABLE_CON_SCE); + pr_debug("concurrency scenario %s OFF\n", + con_sce_str[i]); + break; + } + } + } + return count; +} + +DRIVER_ATTR(concurrency_scenario, 0644, con_sce_show, con_sce_store); + +/* + * emi_bwl_mod_init: module init function. + */ +static int __init emi_bwl_mod_init(void) +{ + int ret; + struct device_node *node; + + /* DTS version */ + if (EMI_BASE_ADDR == NULL) { + node = of_find_compatible_node(NULL, NULL, "mediatek,EMI"); + if (node) { + EMI_BASE_ADDR = of_iomap(node, 0); + pr_err("get EMI_BASE_ADDR @ %p\n", EMI_BASE_ADDR); + } else { + pr_err("can't find compatible node\n"); + return -1; + } + } + + ret = mtk_mem_bw_ctrl(CON_SCE_NORMAL, ENABLE_CON_SCE); + if (ret) + pr_err("[EMI/BWL] fail to set EMI bandwidth limiter\n"); + + /* Register BW ctrl interface */ + ret = platform_driver_register(&mem_bw_ctrl); + if (ret) + pr_err("[EMI/BWL] fail to register EMI_BW_LIMITER driver\n"); + + ret = driver_create_file(&mem_bw_ctrl.driver, + &driver_attr_concurrency_scenario); + if (ret) + pr_err("[EMI/BWL] fail to create EMI_BW_LIMITER sysfs file\n"); + + + /* Register DRAM type information interface */ + ret = platform_driver_register(&ddr_type); + if (ret) + pr_err("[EMI/BWL] fail to register DRAM_TYPE driver\n"); + + ret = driver_create_file(&ddr_type.driver, &driver_attr_ddr_type); + if (ret) + pr_err("[EMI/BWL] fail to create DRAM_TYPE sysfs file\n"); + + return 0; +} + +/* + * emi_bwl_mod_exit: module exit function. + */ +static void __exit emi_bwl_mod_exit(void) +{ +} + +/* EXPORT_SYMBOL(get_dram_type); */ + +late_initcall(emi_bwl_mod_init); +module_exit(emi_bwl_mod_exit); + diff --git a/drivers/misc/mediatek/emi_mpu/mt6755/Makefile b/drivers/misc/mediatek/emi_mpu/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..aaf07d73bdeba4cfaf17d73f290293b24570fd47 --- /dev/null +++ b/drivers/misc/mediatek/emi_mpu/mt6755/Makefile @@ -0,0 +1,15 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += emi_mpu.o + diff --git a/drivers/misc/mediatek/emi_mpu/mt6755/emi_mpu.c b/drivers/misc/mediatek/emi_mpu/mt6755/emi_mpu.c new file mode 100644 index 0000000000000000000000000000000000000000..a770d24c7ac715da6782b48ca9385705a75fe56e --- /dev/null +++ b/drivers/misc/mediatek/emi_mpu/mt6755/emi_mpu.c @@ -0,0 +1,2093 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MTK_AEE_FEATURE +#include +#endif +#include +#include + +#include +#include +#include "mach/irqs.h" +#include +#include +#include +#include +#include +#include "mach/emi_mpu.h" +#include +#include + +static int Violation_PortID = MASTER_ALL; + + +#define ENABLE_EMI_CHKER +#define ENABLE_EMI_WATCH_POINT + +#define MAX_EMI_MPU_STORE_CMD_LEN 128 +#define TIMEOUT 100 +#define AXI_VIO_MONITOR_TIME (1 * HZ) + +static struct work_struct emi_mpu_work; +static struct workqueue_struct *emi_mpu_workqueue; +static unsigned int enable_4gb; +static unsigned int vio_addr; +static unsigned int emi_physical_offset; + +struct mst_tbl_entry { + u32 master; + u32 port; + u32 id_mask; + u32 id_val; + char *note; + char *name; +}; + +struct emi_mpu_notifier_block { + struct list_head list; + emi_mpu_notifier notifier; +}; + +static const struct mst_tbl_entry mst_tbl[] = { + /* apmcu */ + { .master = MST_ID_APMCU_0, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x4, + .note = "CA7LL: Core nn system domain store exclusive", + .name = "CA7" }, + { .master = MST_ID_APMCU_1, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x24, .note = "CA7LL: Core nn barrier", + .name = "CA7" }, + { .master = MST_ID_APMCU_2, .port = 0x0, .id_mask = 0xFFF, + .id_val = 0x4C, .note = "CA7LL: SCU generated barrier", + .name = "CA7" }, + { .master = MST_ID_APMCU_3, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x64, + .note = "CA7LL: Core nn non-re-orderable device write", + .name = "CA7" }, + { .master = MST_ID_APMCU_4, .port = 0x0, .id_mask = 0xF87, + .id_val = 0x84, + .note = "CA7LL: Write to normal memory", + .name = "CA7" }, + { .master = MST_ID_APMCU_5, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x4, + .note = "CA7LL: Core nn exclusive read", + .name = "CA7" }, + { .master = MST_ID_APMCU_6, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x24, .note = "CA7LL: Core nn barrier", + .name = "CA7" }, + { .master = MST_ID_APMCU_7, .port = 0x0, .id_mask = 0xFFF, + .id_val = 0x4C, + .note = "CA7LL: SCU generated barrier or DVM complete", + .name = "CA7" }, + { .master = MST_ID_APMCU_8, .port = 0x0, .id_mask = 0xF9F, + .id_val = 0x8C, .note = "CA7LL: ACP read", + .name = "CA7"}, + { .master = MST_ID_APMCU_9, .port = 0x0, .id_mask = 0xF07, + .id_val = 0x104, .note = "CA7LL: Core nn read", .name = "CA7" }, + { .master = MST_ID_APMCU_10, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x3, + .note = "CA7L: Core nn system domain store exclusive", + .name = "CA7" }, + { .master = MST_ID_APMCU_11, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x23, .note = "CA7L: Core nn barrier", + .name = "CA7" }, + { .master = MST_ID_APMCU_12, .port = 0x0, .id_mask = 0xFFF, + .id_val = 0x4B, .note = "CA7L: SCU generated barrier", + .name = "CA7" }, + { .master = MST_ID_APMCU_13, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x63, + .note = "CA7L: Core nn non-re-orderable device write", + .name = "CA7" }, + { .master = MST_ID_APMCU_14, .port = 0x0, .id_mask = 0xF87, + .id_val = 0x83, + .note = "CA7L: Write to normal memory", + .name = "CA7" }, + { .master = MST_ID_APMCU_15, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x3, + .note = "CA7L: Core nn exclusive read", + .name = "CA7" }, + { .master = MST_ID_APMCU_16, .port = 0x0, .id_mask = 0xFE7, + .id_val = 0x23, .note = "CA7L: Core nn barrier", + .name = "CA7" }, + { .master = MST_ID_APMCU_17, .port = 0x0, .id_mask = 0xFFF, + .id_val = 0x4B, + .note = "CA7L: SCU generated barrier or DVM complete", + .name = "CA7" }, + { .master = MST_ID_APMCU_18, .port = 0x0, .id_mask = 0xF9F, + .id_val = 0x8B, .note = "CA7L: ACP read", .name = "CA7" }, + { .master = MST_ID_APMCU_19, .port = 0x0, .id_mask = 0xF07, + .id_val = 0x103, .note = "CA7L: Core nn read", .name = "CA7" }, + + /* MM */ + { .master = MST_ID_MM_0, .port = 0x1, .id_mask = 0xF80, + .id_val = 0x0, .note = "smi_larb0", .name = "smi_larb0" }, + { .master = MST_ID_MM_1, .port = 0x1, .id_mask = 0xF80, + .id_val = 0x80, .note = "smi_larb1", .name = "smi_larb1" }, + { .master = MST_ID_MM_2, .port = 0x1, .id_mask = 0xF80, + .id_val = 0x100, .note = "smi_larb2", .name = "smi_larb2" }, + { .master = MST_ID_MM_3, .port = 0x1, .id_mask = 0xF80, + .id_val = 0x180, .note = "smi_larb3", .name = "smi_larb3" }, + { .master = MST_ID_MM_4, .port = 0x1, .id_mask = 0xFFE, + .id_val = 0x3FC, .note = "MM IOMMU Internal Used", + .name = "MM IOMMU Internal Used" }, + + /* Periperal */ + { .master = MST_ID_PERI_0, .port = 0x2, .id_mask = 0xFF3, + .id_val = 0x0, .note = "MSDC0", .name = "l_MSDC0" }, + { .master = MST_ID_PERI_1, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x2, .note = "PWM", .name = "l_PWM" }, + { .master = MST_ID_PERI_2, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x6, .note = "MSDC1", .name = "l_MSDC1" }, + { .master = MST_ID_PERI_3, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0xA, .note = "MSDC2", .name = "MSDC2" }, + { .master = MST_ID_PERI_4, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0xE, .note = "SPI0", .name = "l_SPI0" }, + { .master = MST_ID_PERI_5, .port = 0x2, .id_mask = 0xFDF, + .id_val = 0x1, .note = "Debug Top", .name = "Debug Top" }, + { .master = MST_ID_PERI_6, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x5, .note = "AUDIO", .name = "AUDIO" }, + { .master = MST_ID_PERI_7, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x105, .note = "MSDC3", .name = "MSDC3" }, + { .master = MST_ID_PERI_8, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x205, .note = "SPI1", .name = "SPI1" }, + { .master = MST_ID_PERI_9, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x305, .note = "USB2.0", .name = "USB2.0" }, + { .master = MST_ID_PERI_10, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x125, .note = "SPM1_SPM2", .name = "SPM1_SPM2" }, + { .master = MST_ID_PERI_11, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x325, .note = "THERM", .name = "THERM" }, + { .master = MST_ID_PERI_12, .port = 0x2, .id_mask = 0xEFF, + .id_val = 0x45, .note = "U3", .name = "U3" }, + { .master = MST_ID_PERI_13, .port = 0x2, .id_mask = 0xEFF, + .id_val = 0x65, .note = "DMA", .name = "DMA" }, + { .master = MST_ID_PERI_14, .port = 0x2, .id_mask = 0x9FF, + .id_val = 0x85, .note = "MSDC0", .name = "l_MSDC0" }, + { .master = MST_ID_PERI_15, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x185, .note = "PWM", .name = "l_PWM" }, + { .master = MST_ID_PERI_16, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x385, .note = "MSDC1", .name = "l_MSDC1" }, + { .master = MST_ID_PERI_17, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x585, .note = "MSDC2", .name = "MSDC2" }, + { .master = MST_ID_PERI_18, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x785, .note = "SPI0", .name = "l_SPI0" }, + { .master = MST_ID_PERI_19, .port = 0x2, .id_mask = 0xFDF, + .id_val = 0x9, .note = "CONNSYS", .name = "l_CONNSYS" }, + { .master = MST_ID_PERI_20, .port = 0x2, .id_mask = 0xFDF, + .id_val = 0xD, .note = "GCPU_M", .name = "GCPU_M" }, + { .master = MST_ID_PERI_21, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x11, .note = "CLDMA_AP", .name = "CLDMA_AP" }, + { .master = MST_ID_PERI_22, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x31, .note = "CLDMA_MD", .name = "CLDMA_MD" }, + { .master = MST_ID_PERI_23, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x3, .note = "GCE", .name = "l_GCE" }, + { .master = MST_ID_PERI_24, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0x7, .note = "GDMA", .name = "GDMA" }, + { .master = MST_ID_PERI_25, .port = 0x2, .id_mask = 0xFFF, + .id_val = 0xB, .note = "GCE_prefetch", .name = "GCE_prefetch" }, + + /* Modem MCU*/ + { .master = MST_ID_MDMCU_0, .port = 0x3, .id_mask = 0xF0F, + .id_val = 0x0, .note = "MDMCU", .name = "MDMCU" }, + { .master = MST_ID_MDMCU_1, .port = 0x3, .id_mask = 0xF0F, + .id_val = 0x4, .note = "MDMCU PREFETCH", .name = "MDMCU" }, + { .master = MST_ID_MDMCU_2, .port = 0x3, .id_mask = 0xF0F, + .id_val = 0x8, .note = "MDMCU ROW3 NO TITLE", .name = "MDMCU" }, + { .master = MST_ID_MD_L1MCU_0, .port = 0x3, .id_mask = 0xF0F, + .id_val = 0x1, .note = "L1MCU", .name = "L1MCU" }, + { .master = MST_ID_MD_L1MCU_1, .port = 0x3, .id_mask = 0xF0F, + .id_val = 0x5, .note = "L1MCU PREFETCH", .name = "L1MCU" }, + { .master = MST_ID_MD_L1MCU_2, .port = 0x3, .id_mask = 0xF0F, + .id_val = 0x9, .note = "L1MCU ROW3 NO TITLE", .name = "L1MCU" }, + { .master = MST_ID_C2KMCU_0, .port = 0x3, .id_mask = 0x3, + .id_val = 0x2, .note = "C2KMCU ARM D port", .name = "C2KMCU" }, + + /* Modem HW (2G/3G/LTE) */ + { .master = MST_ID_MDHW_0, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x0, .note = "AP2MDREG", .name = "MDHWMIX_AP2MDREG" }, + { .master = MST_ID_MDHW_1, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x1, .note = "MDDBGSYS", .name = "MDHWMIX_MDDBGSYS" }, + { .master = MST_ID_MDHW_2, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x2, .note = "PSMCU2REG", + .name = "MDHWMIX_PSMCU2REG" }, + { .master = MST_ID_MDHW_3, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x100, .note = "MDGDMA", .name = "MDHWMIX_MDGDMA" }, + { .master = MST_ID_MDHW_4, .port = 0x4, .id_mask = 0xFFE, + .id_val = 0x200, .note = "HSPAL2", .name = "MDHWMIX_HSPAL2" }, + { .master = MST_ID_MDHW_5, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x3C0, .note = "Rake_MD2G", + .name = "MDHWMIX_Rake_MD2G" }, + { .master = MST_ID_MDHW_6, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x340, .note = "DFE_B4", .name = "MDHWMIX_DFE" }, + { .master = MST_ID_MDHW_7, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x341, .note = "DFE_DBG", .name = "MDHWMIX_DFE" }, + { .master = MST_ID_MDHW_8, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x342, .note = "DFE_DBG1", .name = "MDHWMIX_DFE" }, + { .master = MST_ID_MDHW_9, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x343, .note = "DFE_SHM", .name = "MDHWMIX_DFE" }, + { .master = MST_ID_MDHW_10, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x380, .note = "RXBRP_HRQ_WR", + .name = "MDHWMIX_RXBRP" }, + { .master = MST_ID_MDHW_11, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x384, .note = "RXBRP_HRQ_WR1", + .name = "MDHWMIX_RXBRP" }, + { .master = MST_ID_MDHW_12, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x381, .note = "RXBRP_HRQ_RD", + .name = "MDHWMIX_RXBRP" }, + { .master = MST_ID_MDHW_13, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x385, .note = "RXBRP_HRQ_RD1", + .name = "MDHWMIX_RXBRP" }, + { .master = MST_ID_MDHW_14, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x382, .note = "RXBRP_HRQ_DBG", + .name = "MDHWMIX_RXBRP" }, + { .master = MST_ID_MDHW_15, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x386, .note = "RXBRP_HRQ_OTH", + .name = "MDHWMIX_RXBRP" }, + { .master = MST_ID_MDHW_16, .port = 0x4, .id_mask = 0xFC7, + .id_val = 0x300, .note = "L1MCU", .name = "MDHWMIX_L1MCU" }, + { .master = MST_ID_MDHW_17, .port = 0x4, .id_mask = 0xFFB, + .id_val = 0x301, .note = "MDL1_GDMA", + .name = "MDHWMIX_MDL1_GDMA" }, + { .master = MST_ID_MDHW_18, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x302, .note = "MDL1_ABM", + .name = "MDHWMIX_MDL1_ABM" }, + { .master = MST_ID_MDHW_19, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x400, .note = "ARM7", .name = "MDHWMIX_ARM7" }, + { .master = MST_ID_MDHW_20, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x500, .note = "PS_PERI", .name = "MDHWMIX_PS_PERI" }, + { .master = MST_ID_MDHW_21, .port = 0x4, .id_mask = 0xFFE, + .id_val = 0x600, .note = "LTEL2DMA", + .name = "MDHWMIX_LTEL2DMA" }, + { .master = MST_ID_MDHW_22, .port = 0x4, .id_mask = 0xFFE, + .id_val = 0x700, .note = "SOE_TRACE", + .name = "MDHWMIX_SOE_TRACE" }, + + { .master = MST_ID_LTE_0, .port = 0x4, .id_mask = 0xFFB, + .id_val = 0x800, .note = "CMP_DSPLOG", + .name = "MDHWLTE_DSPLOG" }, + { .master = MST_ID_LTE_1, .port = 0x4, .id_mask = 0xFFB, + .id_val = 0x800, .note = "CMP_DSPBTDMA", + .name = "MDHWLTE_CMP_DSPBTDMA" }, + { .master = MST_ID_LTE_2, .port = 0x4, .id_mask = 0xFFB, + .id_val = 0x802, .note = "CMP_CNWDMA", + .name = "MDHWLTE_CMP_CNWDMA" }, + { .master = MST_ID_LTE_3, .port = 0x4, .id_mask = 0xFFD, + .id_val = 0x810, .note = "CS", .name = "MDHWLTE_CS" }, + { .master = MST_ID_LTE_4, .port = 0x4, .id_mask = 0xFFB, + .id_val = 0x820, .note = "IMC_RXTDB", .name = "MDHWLTE_IMC" }, + { .master = MST_ID_LTE_5, .port = 0x4, .id_mask = 0xFF7, + .id_val = 0x822, .note = "IMC_DSPLOG", + .name = "MDHWLTE_DSPLOG" }, + { .master = MST_ID_LTE_6, .port = 0x4, .id_mask = 0xFF7, + .id_val = 0x822, .note = "IMC_DSPBTDMA", + .name = "MDHWLTE_IMC" }, + { .master = MST_ID_LTE_7, .port = 0x4, .id_mask = 0xFF7, + .id_val = 0x826, .note = "IMC_CNWDMA", .name = "MDHWLTE_IMC" }, + { .master = MST_ID_LTE_8, .port = 0x4, .id_mask = 0xFFB, + .id_val = 0x830, .note = "ICC_DSPLOG", + .name = "MDHWLTE_DSPLOG" }, + { .master = MST_ID_LTE_9, .port = 0x4, .id_mask = 0xFFB, + .id_val = 0x830, .note = "ICC_DSPBTDMA", + .name = "MDHWLTE_ICC" }, + { .master = MST_ID_LTE_10, .port = 0x4, .id_mask = 0xFFB, + .id_val = 0x832, .note = "ICC_CNWDMA", .name = "MDHWLTE_ICC" }, + { .master = MST_ID_LTE_11, .port = 0x4, .id_mask = 0xFFD, + .id_val = 0x840, .note = "RXDMP", .name = "MDHWLTE_RXDMP" }, + { .master = MST_ID_LTE_12, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x801, .note = "cs id0", .name = "MDHWLTE_CS" }, + { .master = MST_ID_LTE_13, .port = 0x4, .id_mask = 0xFFF, + .id_val = 0x803, .note = "cs id1", .name = "MDHWLTE_CS" }, + + /* MFG */ + { .master = MST_ID_MFG_0, .port = 0x5, .id_mask = 0xFC0, + .id_val = 0x0, .note = "MFG", .name = "l_MFG" }, + +}; + +static const char *UNKNOWN_MASTER = "l_unknown"; +static spinlock_t emi_mpu_lock; + +#ifdef ENABLE_EMI_CHKER +struct timer_list emi_axi_vio_timer; +#endif + +char *smi_larb0_port[17] = { + "disp_ovl_0", "disp_rdma_0", "disp_wdma_0", + "disp_ovl_1", "disp_rdma_1", "disp_wdma_1", + "ufod_rdma0", "ufod_rdma1", "ufod_rdma2", + "ufod_rdma3", "ufod_rdma4", "ufod_rdma5", + "ufod_rdma6", "ufod_rdma7", "mdp_rdma", + "mdp_wdma", "mdp_wrot"}; +char *smi_larb1_port[9] = { + "hw_vdec_mc_ext", "hw_vdec_pp_ext", + "hw_vdec_vld_ext", "hw_vdec_avc_mv_ext", + "hw_vdec_pred_rd_ext", "hw_vdec_pred_wr_ext", + "hw_vdec_ppwarp_ext"}; +char *smi_larb2_port[21] = { + "cam_imgo", "cam_rrzo", "cam_aao", + "cam_esfko", "cam_imgo_s", "cam_isci", + "cam_isci_d", "cam_bpci", "cam_bpci_d", + "cam_ufdi", "cam_imgi", "cam_img2o", + "cam_img3o", "cam_vipi", "cam_vip2i", + "cam_vip3i", "cam_icei", "cam_rb", + "cam_rp", "cam_wr"}; +char *smi_larb3_port[19] = { + "venc_rcpu", "venc_rec", "venc_bsdma", + "venc_sv_comv", "vend_rd_comv", "jpgenc_rdma", + "jpgenc_bsdma", "jpgdec_wdma", "jpgdec_bsdma", + "venc_cur_luma", "venc_cur_chroma", "venc_ref_luma", + "vend_ref_chroma", "redmc_wdma", + "venc_nbm_rdma", "venc_nbm_wdma"}; +char *smi_larb4_port[4] = { + "mjc_mv_rd", "mjc_mv_wr", + "mjc_dma_rd", "mjc_dma_wr"}; + +static int __match_id(u32 axi_id, int tbl_idx, u32 port_ID) +{ + u32 mm_larb; + u32 smi_port; + + if (((axi_id & mst_tbl[tbl_idx].id_mask) == mst_tbl[tbl_idx].id_val) + && (port_ID == mst_tbl[tbl_idx].port)) { + switch (port_ID) { + case 0: /* ARM */ + case 2: /* Peripheral */ + case 3: /* MDMCU ,C2K MCU */ + case 4: /* MD HW ,LTE */ + case 5: /* MFG */ + pr_err("Violation master name is %s.\n", + mst_tbl[tbl_idx].name); + break; + case 1: + /*MM*/ mm_larb = axi_id >> 7; + smi_port = (axi_id & 0x7F) >> 2; + if (mm_larb == 0x0) { + if (smi_port >= ARRAY_SIZE(smi_larb0_port)) { + pr_err("[EMI MPU ERROR] Invalidate master ID! lookup smi table failed!\n"); + return 0; + } + pr_err("Violation master name is %s (%s).\n", + mst_tbl[tbl_idx].name, + smi_larb0_port[smi_port]); + } else if (mm_larb == 0x1) { + if (smi_port >= ARRAY_SIZE(smi_larb1_port)) { + pr_err("[EMI MPU ERROR] Invalidate master ID! lookup smi table failed!\n"); + return 0; + } + pr_err("Violation master name is %s (%s).\n", + mst_tbl[tbl_idx].name, + smi_larb1_port[smi_port]); + } else if (mm_larb == 0x2) { + if (smi_port >= ARRAY_SIZE(smi_larb2_port)) { + pr_err("[EMI MPU ERROR] Invalidate master ID! lookup smi table failed!\n"); + return 0; + } + pr_err("Violation master name is %s (%s).\n", + mst_tbl[tbl_idx].name, + smi_larb2_port[smi_port]); + } else if (mm_larb == 0x3) { /* smi_larb3 */ + if (smi_port >= ARRAY_SIZE(smi_larb3_port)) { + pr_err("[EMI MPU ERROR] Invalidate master ID! lookup smi table failed!\n"); + return 0; + } + pr_err("Violation master name is %s (%s).\n", + mst_tbl[tbl_idx].name, + smi_larb3_port[smi_port]); + } else { /*MM IOMMU Internal Used */ + pr_err("Violation master name is %s.\n", + mst_tbl[tbl_idx].name); + } + break; + default: + pr_err("[EMI MPU ERROR] Invalidate port ID! lookup bus ID table failed!\n"); + break; + } + return 1; + } else { + return 0; + } +} + +#if 0 +static u32 __id2mst(u32 id) +{ + int i; + u32 axi_ID; + u32 port_ID; + + axi_ID = (id >> 3) & 0x000001FFF; + port_ID = id & 0x00000007; + + pr_err("[EMI MPU] axi_id = %x, port_id = %x\n", axi_ID, port_ID); + + for (i = 0; i < ARRAY_SIZE(mst_tbl); i++) { + if (__match_id(axi_ID, i, port_ID)) + return mst_tbl[i].master; + } + return MST_INVALID; +} +#endif + +static int isetocunt; +static void emi_mpu_set_violation_port(int portID) +{ + if (isetocunt == 0) { + Violation_PortID = portID; + isetocunt = 1; + } + else if (isetocunt == 2) { + isetocunt = 0; + } +} + +int emi_mpu_get_violation_port(void) +{ + int ret; + + pr_err("[EMI MPU] emi_mpu_get_violation_port\n"); + + if (isetocunt == 0) { + pr_err("[EMI MPU] EMI did not set Port ID\n"); + isetocunt = 2; + return MASTER_ALL; + } + + ret = Violation_PortID; + isetocunt = 0; + + if (ret >= MASTER_ALL) + pr_err("[EMI MPU] Port ID: %d is an invalid Port ID\n", ret); + else + Violation_PortID = MASTER_ALL; + + return ret; +} + +static char *__id2name(u32 id) +{ + int i; + u32 axi_ID; + u32 port_ID; + + axi_ID = (id >> 3) & 0x00000FFF; + port_ID = id & 0x00000007; + emi_mpu_set_violation_port(port_ID); + pr_err("[EMI MPU] axi_id = %x, port_id = %x\n", axi_ID, port_ID); + + for (i = 0; i < ARRAY_SIZE(mst_tbl); i++) { + if (__match_id(axi_ID, i, port_ID)) + return mst_tbl[i].name; + } + + return (char *)UNKNOWN_MASTER; +} +#define NR_REGIONS 18 +static void __clear_emi_mpu_vio(unsigned int first) +{ + u32 dbg_s, dbg_t; + /* clear violation status */ + + writel(0x00FFF3FF, EMI_MPUP); + writel(0x00FFF3FF, EMI_MPUQ); + writel(0x00FFF3FF, EMI_MPUR); + writel(0x00FFF3FF, EMI_MPUY); + writel(0x00FFF3FF, EMI_MPUP2); + writel(0x00FFF3FF, EMI_MPUQ2); + writel(0x00FFF3FF, EMI_MPUR2); + mt_reg_sync_writel(0x00FFF3FF, EMI_MPUY2); + + /* clear debug info */ + mt_reg_sync_writel(0x80000000 , EMI_MPUS); + dbg_s = readl(IOMEM(EMI_MPUS)); + dbg_t = readl(IOMEM(EMI_MPUT)); + + if (first) { + /* clear the permission setting of MPU*/ + /* do not need to clear here, we already do it at preloader */ + } + + if (dbg_s) { + pr_err("Fail to clear EMI MPU violation\n"); + pr_err("EMI_MPUS = %x, EMI_MPUT = %x", dbg_s, dbg_t); + } +} + +static int mpu_check_violation(void) +{ + u32 dbg_s, dbg_t, dbg_pqry; + u32 master_ID, domain_ID, wr_vio; + s32 region; + char *master_name; + + dbg_s = readl(IOMEM(EMI_MPUS)); + dbg_t = readl(IOMEM(EMI_MPUT)); + + pr_alert("Clear status.\n"); + + master_ID = (dbg_s & 0x00007FFF); + domain_ID = (dbg_s >> 21) & 0x00000007; + wr_vio = (dbg_s >> 28) & 0x00000003; + region = (dbg_s >> 16) & 0x1F; + + switch (domain_ID) { + case 0: + dbg_pqry = readl(IOMEM(EMI_MPUP)); + break; + case 1: + dbg_pqry = readl(IOMEM(EMI_MPUQ)); + break; + case 2: + dbg_pqry = readl(IOMEM(EMI_MPUR)); + break; + case 3: + dbg_pqry = readl(IOMEM(EMI_MPUY)); + break; + case 4: + dbg_pqry = readl(IOMEM(EMI_MPUP2)); + break; + case 5: + dbg_pqry = readl(IOMEM(EMI_MPUQ2)); + break; + case 6: + dbg_pqry = readl(IOMEM(EMI_MPUR2)); + break; + case 7: + dbg_pqry = readl(IOMEM(EMI_MPUY2)); + break; + default: + dbg_pqry = 0; + break; + } + + /*TBD: print the abort region*/ + + pr_err("EMI MPU violation.\n"); + pr_err("[EMI MPU] Debug info start ----------------------------------------\n"); + + pr_err("EMI_MPUS = %x, EMI_MPUT = %x.\n", dbg_s, dbg_t); + pr_err("Current process is \"%s \" (pid: %i).\n", + current->comm, current->pid); + pr_err("Violation address is 0x%x.\n", dbg_t + emi_physical_offset); + pr_err("Violation master ID is 0x%x.\n", master_ID); + /*print out the murderer name*/ + master_name = __id2name(master_ID); + pr_err("Violation domain ID is 0x%x.\n", domain_ID); + pr_err("%s violation.\n", (wr_vio == 1) ? "Write" : "Read"); + pr_err("Corrupted region is %d\n\r", region); + if ((region == 0) || (region == 1)) { /* add log to debug */ + pr_err("EMI_CHKER=%x, EMI_CHKER_TYPE=%x, EMI_CHKER_ADR=%x\n", + readl(IOMEM(EMI_CHKER)), readl(IOMEM(EMI_CHKER_TYPE)), + readl(IOMEM(EMI_CHKER_ADR))); + pr_err("EMI_MPUA=%x, EMI_MPUB=%x, EMI_MPUC=%x\n", + mt_emi_reg_read(EMI_MPUA), mt_emi_reg_read(EMI_MPUB), + mt_emi_reg_read(EMI_MPUC)); + pr_err("EMI_MPUD=%x, EMI_MPUE=%x, EMI_MPUF=%x\n", + mt_emi_reg_read(EMI_MPUD), mt_emi_reg_read(EMI_MPUE), + mt_emi_reg_read(EMI_MPUF)); + pr_err("EMI_MPUG=%x, EMI_MPUH=%x, EMI_MPUA2=%x\n", + mt_emi_reg_read(EMI_MPUG), mt_emi_reg_read(EMI_MPUH), + mt_emi_reg_read(EMI_MPUA2)); + pr_err("EMI_MPUB2=%x, EMI_MPUC2=%x, EMI_MPUD2=%x\n", + mt_emi_reg_read(EMI_MPUB2), mt_emi_reg_read(EMI_MPUC2), + mt_emi_reg_read(EMI_MPUD2)); + pr_err("EMI_MPUE2=%x, EMI_MPUF2=%x, EMI_MPUG2=%x\n", + mt_emi_reg_read(EMI_MPUE2), mt_emi_reg_read(EMI_MPUF2), + mt_emi_reg_read(EMI_MPUG2)); + pr_err("EMI_MPUH2=%x, EMI_MPUA3=%x, EMI_MPUB3=%x\n", + mt_emi_reg_read(EMI_MPUH2), mt_emi_reg_read(EMI_MPUA3), + mt_emi_reg_read(EMI_MPUB3)); + pr_err("EMI_MPUC3=%x, EMI_MPUD3=%x, EMI_MPUI=%x\n", + mt_emi_reg_read(EMI_MPUC3), mt_emi_reg_read(EMI_MPUD3), + mt_emi_reg_read(EMI_MPUI)); + pr_err("EMI_MPUI_2ND=%x, EMI_MPUJ=%x, EMI_MPUJ_2ND=%x\n", + mt_emi_reg_read(EMI_MPUI_2ND), mt_emi_reg_read(EMI_MPUJ), + mt_emi_reg_read(EMI_MPUJ_2ND)); + pr_err("EMI_MPUK=%x, EMI_MPUK_2ND=%x, EMI_MPUL=%x\n", + mt_emi_reg_read(EMI_MPUK), mt_emi_reg_read(EMI_MPUK_2ND), + mt_emi_reg_read(EMI_MPUL)); + pr_err("EMI_MPUL_2ND=%x, EMI_MPUI2=%x, EMI_MPUI2_2ND=%x\n", + mt_emi_reg_read(EMI_MPUL_2ND), mt_emi_reg_read(EMI_MPUI2), + mt_emi_reg_read(EMI_MPUI2_2ND)); + pr_err("EMI_MPUJ2=%x, EMI_MPUJ2_2ND=%x, EMI_MPUK2=%x\n", + mt_emi_reg_read(EMI_MPUJ2), mt_emi_reg_read(EMI_MPUJ2_2ND), + mt_emi_reg_read(EMI_MPUK2)); + pr_err("EMI_MPUK2_2ND=%x, EMI_MPUL2=%x, EMI_MPUL2_2ND=%x\n", + mt_emi_reg_read(EMI_MPUK2_2ND), mt_emi_reg_read(EMI_MPUL2), + mt_emi_reg_read(EMI_MPUL2_2ND)); + pr_err("EMI_MPUI3=%x, EMI_MPUJ3=%x, EMI_MPUK3=%x\n", + mt_emi_reg_read(EMI_MPUI3), mt_emi_reg_read(EMI_MPUJ3), + mt_emi_reg_read(EMI_MPUK3)); + pr_err("EMI_MPUL3=%x, EMI_MPUM=%x, EMI_MPUN=%x\n", + mt_emi_reg_read(EMI_MPUL3), mt_emi_reg_read(EMI_MPUM), + mt_emi_reg_read(EMI_MPUN)); + pr_err("EMI_MPUO=%x, EMI_MPUU=%x, EMI_MPUM2=%x\n", + mt_emi_reg_read(EMI_MPUO), mt_emi_reg_read(EMI_MPUU), + mt_emi_reg_read(EMI_MPUM2)); + pr_err("EMI_MPUN2=%x, EMI_MPUO2=%x, EMI_MPUU2=%x\n", + mt_emi_reg_read(EMI_MPUN2), mt_emi_reg_read(EMI_MPUO2), + mt_emi_reg_read(EMI_MPUU2)); + pr_err("EMI_MPUV=%x, EMI_MPUW=%x, EMI_MPUX=%x\n", + mt_emi_reg_read(EMI_MPUV), mt_emi_reg_read(EMI_MPUW), + mt_emi_reg_read(EMI_MPUX)); + } + if (dbg_pqry & OOR_VIO) + pr_err("Out of range violation.\n"); + + pr_err("[EMI MPU] Debug info end------------------------------------------\n"); + +#ifdef CONFIG_MTK_AEE_FEATURE + if (wr_vio != 0) { + /* EMI violation is relative to MD at user build*/ + #if 0 /* #ifndef CONFIG_MT_ENG_BUILD */ + if (((master_ID & 0x7) == MASTER_MDMCU) || + ((master_ID & 0x7) == MASTER_MDHW)) { + int md_id = 0; + + exec_ccci_kern_func_by_md_id(md_id, + ID_FORCE_MD_ASSERT, NULL, 0); + pr_err("[EMI MPU] MPU violation trigger MD\n"); + } + #else + if (((master_ID & 0x7) == MASTER_MDMCU) || + ((master_ID & 0x7) == MASTER_MDHW)) { + char str[60] = "0"; + char *pstr = str; + + sprintf(pstr, "EMI_MPUS = 0x%x, ADDR = 0x%x", + dbg_s, dbg_t + emi_physical_offset); + + exec_ccci_kern_func_by_md_id(0, + ID_MD_MPU_ASSERT, str, strlen(str)); + pr_err("[EMI MPU] MPU violation trigger MD str=%s strlen(str)=%d\n" + , str, (int)strlen(str)); + } else { + exec_ccci_kern_func_by_md_id(0, + ID_MD_MPU_ASSERT, NULL, 0); + pr_err("[EMI MPU] MPU violation ack to MD\n"); + } + #endif + if ((region == 0) && (mt_emi_reg_read(EMI_MPUA) == 0) + && (mt_emi_reg_read(EMI_MPUI) == 0)) { + pr_err("[EMI MPU] A strange violation.\n"); + } else { + aee_kernel_exception("EMI MPU", +"%sEMI_MPUS = 0x%x,EMI_MPUT = 0x%x\n CHKER = 0x%x,CHKER_TYPE = 0x%x,CHKER_ADR = 0x%x\n MPUA = 0x%x, MPUI = 0x%x\n%s%s\n", + "EMI MPU violation.\n", + dbg_s, + dbg_t+emi_physical_offset, + readl(IOMEM(EMI_CHKER)), + readl(IOMEM(EMI_CHKER_TYPE)), + readl(IOMEM(EMI_CHKER_ADR)), + mt_emi_reg_read(EMI_MPUA), + mt_emi_reg_read(EMI_MPUI), + "CRDISPATCH_KEY:EMI MPU Violation Issue/", + master_name); + } + } +#endif + + __clear_emi_mpu_vio(0); + mt_devapc_clear_emi_violation(); + vio_addr = dbg_t + emi_physical_offset; + return 0; + +} + +/*EMI MPU violation handler*/ +static irqreturn_t mpu_violation_irq(int irq, void *dev_id) +{ + int res, res1; + + /* Need DEVAPC owner porting */ + res = mt_devapc_check_emi_violation(); + if (!res) + pr_err("it's a mt_devapc_emi_violation.\n"); + + res1 = mt_devapc_check_emi_mpu_violation(); + if (!res1) { + pr_err("EMI MPU APB violation.\n"); + pr_err("[EMI MPU] Debug info start ----------------------------------------\n"); + pr_err("EMI_MPUW=%x\n", mt_emi_reg_read(EMI_MPUW)); + pr_err("EMI_MPUV=%x\n", mt_emi_reg_read(EMI_MPUV)); + pr_err("EMI_MPUX=%x\n", mt_emi_reg_read(EMI_MPUX)); + pr_err("Violation address=%x\n", + mt_emi_reg_read(EMI_MPUW) & 0xFFFF); + pr_err("Violation domain=%x\n", + (mt_emi_reg_read(EMI_MPUW)>>16) & 0x7); + + if ((mt_emi_reg_read(EMI_MPUV)>>28) & 0x1) + pr_err("it's a Write violation\n"); + else if ((mt_emi_reg_read(EMI_MPUV)>>29) & 0x1) + pr_err("it's a Read violation\n"); + + pr_err("[EMI MPU] Debug info end------------------------------------------\n"); + mt_emi_reg_write(mt_emi_reg_read(EMI_MPUX)|0x80000000, + EMI_MPUX); + mt_devapc_clear_emi_mpu_violation(); + return IRQ_HANDLED; + } + + if (res && res1) + return IRQ_NONE; + + pr_info("It's a MPU violation.\n"); + mpu_check_violation(); + return IRQ_HANDLED; +} + +#if defined(CONFIG_MTKPASR) +/* Acquire DRAM Setting for PASR/DPD */ +void acquire_dram_setting(struct basic_dram_setting *pasrdpd) +{ + int ch_nr = MAX_CHANNELS; + unsigned int emi_cona, emi_conh, col_bit, row_bit; + unsigned int ch0_rank0_size, ch0_rank1_size; + unsigned int ch1_rank0_size, ch1_rank1_size; + + pasrdpd->channel_nr = ch_nr; + + emi_cona = readl(IOMEM(EMI_CONA)); + emi_conh = readl(IOMEM(EMI_CONH)); + + ch0_rank0_size = (emi_conh >> 16) & 0xf; + ch0_rank1_size = (emi_conh >> 20) & 0xf; + ch1_rank0_size = (emi_conh >> 24) & 0xf; + ch1_rank1_size = (emi_conh >> 28) & 0xf; + + { + pasrdpd->channel[0].rank[0].valid_rank = true; + + if (ch0_rank0_size == 0) { + col_bit = ((emi_cona >> 4) & 0x03) + 9; + row_bit = ((emi_cona >> 12) & 0x03) + 13; + pasrdpd->channel[0].rank[0].rank_size = + (1 << (row_bit + col_bit)) >> 22; + pasrdpd->channel[0].rank[0].segment_nr = 8; + } else { + pasrdpd->channel[0].rank[0].rank_size = + (ch0_rank0_size * 2); + pasrdpd->channel[0].rank[0].segment_nr = 6; + } + + if (0 != (emi_cona & (1 << 17))) { + pasrdpd->channel[0].rank[1].valid_rank = true; + + if (ch0_rank1_size == 0) { + col_bit = ((emi_cona >> 6) & 0x03) + 9; + row_bit = ((emi_cona >> 14) & 0x03) + 13; + pasrdpd->channel[0].rank[1].rank_size = + (1 << (row_bit + col_bit)) >> 22; + pasrdpd->channel[0].rank[1].segment_nr = 8; + } else { + pasrdpd->channel[0].rank[1].rank_size = + (ch0_rank1_size * 2); + pasrdpd->channel[0].rank[1].segment_nr = 6; + } + } else { + pasrdpd->channel[0].rank[1].valid_rank = false; + pasrdpd->channel[0].rank[1].segment_nr = 0; + pasrdpd->channel[0].rank[1].rank_size = 0; + } + } + + if (0 != (emi_cona & 0x01)) { + + pasrdpd->channel[1].rank[0].valid_rank = true; + + if (ch1_rank0_size == 0) { + col_bit = ((emi_cona >> 20) & 0x03) + 9; + row_bit = ((emi_cona >> 28) & 0x03) + 13; + pasrdpd->channel[1].rank[0].rank_size = + (1 << (row_bit + col_bit)) >> 22; + pasrdpd->channel[1].rank[0].segment_nr = 8; + } else { + pasrdpd->channel[1].rank[0].rank_size = + (ch1_rank0_size * 2); + pasrdpd->channel[1].rank[0].segment_nr = 6; + } + + if (0 != (emi_cona & (1 << 16))) { + pasrdpd->channel[1].rank[1].valid_rank = true; + + if (ch1_rank1_size == 0) { + col_bit = ((emi_cona >> 22) & 0x03) + 9; + row_bit = ((emi_cona >> 30) & 0x03) + 13; + pasrdpd->channel[1].rank[1].rank_size = + (1 << (row_bit + col_bit)) >> 22; + pasrdpd->channel[1].rank[1].segment_nr = 8; + } else { + pasrdpd->channel[1].rank[1].rank_size = + (ch1_rank1_size * 2); + pasrdpd->channel[1].rank[1].segment_nr = 6; + } + } else { + pasrdpd->channel[1].rank[1].valid_rank = false; + pasrdpd->channel[1].rank[1].segment_nr = 0; + pasrdpd->channel[1].rank[1].rank_size = 0; + } + } else { + pasrdpd->channel[1].rank[0].valid_rank = false; + pasrdpd->channel[1].rank[0].segment_nr = 0; + pasrdpd->channel[1].rank[0].rank_size = 0; + + pasrdpd->channel[1].rank[1].valid_rank = false; + pasrdpd->channel[1].rank[1].segment_nr = 0; + pasrdpd->channel[1].rank[1].rank_size = 0; + } +} +#endif + +/* + * emi_mpu_set_region_protection: protect a region. + * @start: start address of the region + * @end: end address of the region + * @region: EMI MPU region id + * @access_permission: EMI MPU access permission + * Return 0 for success, otherwise negative status code. + */ +int emi_mpu_set_region_protection(unsigned long long start, +unsigned long long end, int region, unsigned int access_permission) +{ + int ret = 0; + unsigned long flags; + + access_permission = access_permission & 0xFFFFFF; + access_permission = access_permission | ((region & 0x1F)<<27); + spin_lock_irqsave(&emi_mpu_lock, flags); + mt_emi_mpu_set_region_protection(start, end, access_permission); + spin_unlock_irqrestore(&emi_mpu_lock, flags); + + return ret; +} +EXPORT_SYMBOL(emi_mpu_set_region_protection); + +static ssize_t emi_mpu_show(struct device_driver *driver, char *buf) +{ + char *ptr = buf; + unsigned int start, end; + unsigned int reg_value; + unsigned int d0, d1, d2, d3, d4, d5, d6, d7; + static const char *permission[7] = { + "No", + "S_RW", + "S_RW_NS_R", + "S_RW_NS_W", + "S_R_NS_R", + "FOR", + "S_R_NS_RW" + }; + + reg_value = mt_emi_reg_read(EMI_MPUA); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R0 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUB); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R1 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUC); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R2 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUD); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R3 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUE); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R4 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUF); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R5 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUG); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R6 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUH); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R7 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUA2); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R8 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUB2); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R9 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUC2); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R10 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUD2); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R11 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUE2); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R12 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUF2); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R13 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUG2); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R14 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUH2); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R15 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUA3); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R16 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUB3); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R17 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUC3); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R18 --> 0x%x to 0x%x\n", start, end); + + reg_value = mt_emi_reg_read(EMI_MPUD3); + start = ((reg_value >> 16) << 16) + emi_physical_offset; + end = ((reg_value & 0xFFFF) << 16) + emi_physical_offset + 0xFFFF; + ptr += sprintf(ptr, "R19 --> 0x%x to 0x%x\n", start, end); + + ptr += sprintf(ptr, "\n"); + + reg_value = mt_emi_reg_read(EMI_MPUI); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R0 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R0 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUJ); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R1 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R1 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUK); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R2 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R2 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUL); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R3 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R3 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + + reg_value = mt_emi_reg_read(EMI_MPUI_2ND); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R4 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R4 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + + reg_value = mt_emi_reg_read(EMI_MPUJ_2ND); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R5 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R5 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUK_2ND); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R6 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R6 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUL_2ND); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R7 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R7 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUI2); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R8 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R8 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUJ2); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R9 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R9 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUK2); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R10 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R10 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUL2); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R11 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R11 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + + reg_value = mt_emi_reg_read(EMI_MPUI2_2ND); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R12 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R12 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + + reg_value = mt_emi_reg_read(EMI_MPUJ2_2ND); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R13 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R13 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUK2_2ND); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R14 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R14 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUL2_2ND); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R15 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R15 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUI3); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R16 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R16 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUJ3); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R17 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R17 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUK3); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R18 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R18 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + reg_value = mt_emi_reg_read(EMI_MPUL3); + d0 = (reg_value & 0x7); + d1 = (reg_value >> 3) & 0x7; + d2 = (reg_value >> 6) & 0x7; + d3 = (reg_value >> 9) & 0x7; + d4 = (reg_value >> 12) & 0x7; + d5 = (reg_value >> 15) & 0x7; + d6 = (reg_value >> 18) & 0x7; + d7 = (reg_value >> 21) & 0x7; + ptr += sprintf(ptr, "R19 --> d0 = %s, d1 = %s, d2 = %s, d3 = %s\n", + permission[d0], permission[d1], permission[d2], permission[d3]); + ptr += sprintf(ptr, "R19 --> d4 = %s, d5 = %s, d6 = %s, d7 = %s\n", + permission[d4], permission[d5], permission[d6], permission[d7]); + + return strlen(buf); +} + +static ssize_t emi_mpu_store(struct device_driver *driver, +const char *buf, size_t count) +{ + int i; + unsigned int start_addr; + unsigned int end_addr; + unsigned int region; + unsigned int access_permission; + char *command; + char *ptr; + char *token[5]; + ssize_t ret; + + if ((strlen(buf) + 1) > MAX_EMI_MPU_STORE_CMD_LEN) { + pr_err("emi_mpu_store command overflow."); + return count; + } + pr_err("emi_mpu_store: %s\n", buf); + + command = kmalloc((size_t) MAX_EMI_MPU_STORE_CMD_LEN, GFP_KERNEL); + if (!command) + return count; + + strcpy(command, buf); + ptr = (char *)buf; + + if (!strncmp(buf, EN_MPU_STR, strlen(EN_MPU_STR))) { + i = 0; + while (ptr != NULL) { + ptr = strsep(&command, " "); + token[i] = ptr; + pr_devel("token[%d] = %s\n", i, token[i]); + i++; + } + for (i = 0; i < 5; i++) + pr_devel("token[%d] = %s\n", i, token[i]); + + /* kernel standardization + start_addr = simple_strtoul(token[1], &token[1], 16); + end_addr = simple_strtoul(token[2], &token[2], 16); + region = simple_strtoul(token[3], &token[3], 16); + access_permission = simple_strtoul(token[4], &token[4], 16); + */ + ret = kstrtoul(token[1], 16, (unsigned long *)&start_addr); + if (ret != 0) + pr_err("kstrtoul fails to parse start_addr"); + ret = kstrtoul(token[2], 16, (unsigned long *)&end_addr); + if (ret != 0) + pr_err("kstrtoul fails to parse end_addr"); + ret = kstrtoul(token[3], 16, (unsigned long *)®ion); + if (ret != 0) + pr_err("kstrtoul fails to parse region"); + ret = kstrtoul(token[4], 16, + (unsigned long *)&access_permission); + if (ret != 0) + pr_err("kstrtoul fails to parse access_permission"); + emi_mpu_set_region_protection(start_addr, end_addr, + region, access_permission); + pr_err("Set EMI_MPU: start: 0x%x, end: 0x%x, region: %d, permission: 0x%x.\n", + start_addr, end_addr, region, access_permission); + } else if (!strncmp(buf, DIS_MPU_STR, strlen(DIS_MPU_STR))) { + i = 0; + while (ptr != NULL) { + ptr = strsep(&command, " "); + token[i] = ptr; + pr_devel("token[%d] = %s\n", i, token[i]); + i++; + } + for (i = 0; i < 5; i++) + pr_devel("token[%d] = %s\n", i, token[i]); + /* kernel standardization + start_addr = simple_strtoul(token[1], &token[1], 16); + end_addr = simple_strtoul(token[2], &token[2], 16); + region = simple_strtoul(token[3], &token[3], 16); + */ + ret = kstrtoul(token[1], 16, (unsigned long *)&start_addr); + if (ret != 0) + pr_err("kstrtoul fails to parse start_addr"); + ret = kstrtoul(token[2], 16, (unsigned long *)&end_addr); + if (ret != 0) + pr_err("kstrtoul fails to parse end_addr"); + ret = kstrtoul(token[3], 16, (unsigned long *)®ion); + if (ret != 0) + pr_err("kstrtoul fails to parse region"); + + emi_mpu_set_region_protection(0x0, 0x0, region, + SET_ACCESS_PERMISSON(NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION)); + + pr_err("set EMI MPU: start: 0x%x, end: 0x%x, region: %d, permission: 0x%x\n", + 0, 0, region, + SET_ACCESS_PERMISSON(NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION)); + + } else { + pr_err("Unknown emi_mpu command.\n"); + } + + kfree(command); + + return count; +} + +DRIVER_ATTR(mpu_config, 0644, emi_mpu_show, emi_mpu_store); + +void mtk_search_full_pgtab(void) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + unsigned long addr; +#ifndef CONFIG_ARM_LPAE + pte_t *pte; + unsigned long addr_2nd, addr_2nd_end; +#endif + unsigned int v_addr = vio_addr; + + for (addr = 0xC0000000; addr < 0xFFF00000; addr += 0x100000) { + pgd = pgd_offset(&init_mm, addr); + if (pgd_none(*pgd) || !pgd_present(*pgd)) + continue; + + pud = pud_offset(pgd, addr); + if (pud_none(*pud) || !pud_present(*pud)) + continue; + + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd) || !pmd_present(*pmd)) + continue; + +#ifndef CONFIG_ARM_LPAE + if ((pmd_val(*pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) { + /* Page table entry*/ + + addr_2nd = addr; + addr_2nd_end = addr_2nd + 0x100000; + for (; addr_2nd < (addr_2nd_end); addr_2nd += 0x1000) { + pte = pte_offset_map(pmd, addr_2nd); + + if (((unsigned long)v_addr & PAGE_MASK) == + ((unsigned long)pte_val(*(pte)) + & PAGE_MASK)) { + pr_err("[EMI MPU] Find page entry section at pte: %lx. violation address = 0x%x\n", + (unsigned long)(pte), v_addr); + return; + } + } + } else { + /* Section */ + if (((unsigned long)pmd_val(*(pmd)) & SECTION_MASK) == + ((unsigned long)v_addr + & SECTION_MASK)) { + pr_err("[EMI MPU] Find page entry section at pmd: %lx. violation address = 0x%x\n", + (unsigned long)(pmd), v_addr); + return; + } + } +#else + /* TBD */ +#endif + } + pr_err("[EMI MPU] ****** Can not find page table entry! violation address = 0x%x ******\n", + v_addr); +} + +void emi_mpu_work_callback(struct work_struct *work) +{ + pr_err("[EMI MPU] Enter EMI MPU workqueue!\n"); + mtk_search_full_pgtab(); + pr_err("[EMI MPU] Exit EMI MPU workqueue!\n"); +} + +static ssize_t pgt_scan_show(struct device_driver *driver, char *buf) +{ + return 0; +} + +static ssize_t pgt_scan_store(struct device_driver *driver, +const char *buf, size_t count) +{ + unsigned int value; + unsigned int ret; + + if (unlikely(kstrtoint(buf, 0, &value) != 1)) + return -EINVAL; + + if (value == 1) { + ret = queue_work(emi_mpu_workqueue, &emi_mpu_work); + if (!ret) + pr_debug("[EMI MPU] submit workqueue failed, ret = %d\n", + ret); + } + + return count; +} +DRIVER_ATTR(pgt_scan, 0644, pgt_scan_show, pgt_scan_store); + +#ifdef ENABLE_EMI_CHKER +static void emi_axi_set_chker(const unsigned int setting) +{ + int value; + + value = readl(IOMEM(EMI_CHKER)); + value &= ~(0x7 << 16); + value |= (setting); + + mt_reg_sync_writel(value, EMI_CHKER); +} + +static void emi_axi_set_master(const unsigned int setting) +{ + int value; + + value = readl(IOMEM(EMI_CHKER)); + value &= ~(0x0F << AXI_NON_ALIGN_CHK_MST); + value |= (setting & 0xF) << AXI_NON_ALIGN_CHK_MST; + + mt_reg_sync_writel(value, EMI_CHKER); +} + +static void emi_axi_dump_info(int aee_ke_en) +{ + int value, master_ID; + char *master_name; + + value = readl(IOMEM(EMI_CHKER)); + master_ID = (value & 0x0000FFFF); + + if (value & 0x0000FFFF) { + pr_err("AXI violation.\n"); + pr_err("[EMI MPU AXI] Debug info start ----------------------------------------\n"); + + pr_err("EMI_CHKER = %x.\n", value); + pr_err("Violation address is 0x%x.\n", + readl(IOMEM(EMI_CHKER_ADR))); + pr_err("Violation master ID is 0x%x.\n", master_ID); + pr_err("Violation type is: AXI_ADR_CHK_EN(%d), AXI_LOCK_CHK_EN(%d), AXI_NON_ALIGN_CHK_EN(%d).\n", + (value & (1 << AXI_ADR_VIO)) ? 1 : 0, + (value & (1 << AXI_LOCK_ISSUE)) ? 1 : 0, + (value & (1 << AXI_NON_ALIGN_ISSUE)) ? 1 : 0); + pr_err("%s violation.\n", + (value & (1 << AXI_VIO_WR)) ? "Write" : "Read"); + + pr_err("[EMI MPU AXI] Debug info end ----------------------------------------\n"); + + master_name = __id2name(master_ID); +#ifdef CONFIG_MTK_AEE_FEATURE + if (aee_ke_en) + aee_kernel_exception("EMI MPU AXI", + "AXI violation.\nEMI_CHKER = 0x%x\nCRDISPATCH_KEY:EMI MPU Violation Issue/%s\n", + value, master_name); +#endif + /* clear AXI checker status */ + mt_reg_sync_writel((1 << AXI_VIO_CLR) | readl(IOMEM(EMI_CHKER)), + EMI_CHKER); + } +} + +static void emi_axi_vio_timer_func(unsigned long a) +{ + emi_axi_dump_info(1); + + mod_timer(&emi_axi_vio_timer, jiffies + AXI_VIO_MONITOR_TIME); +} + +static ssize_t emi_axi_vio_show(struct device_driver *driver, char *buf) +{ + int value; + + value = readl(IOMEM(EMI_CHKER)); + + emi_axi_dump_info(0); + + return snprintf(buf, + PAGE_SIZE, + "AXI vio setting is: ADR_CHK_EN %s, LOCK_CHK_EN %s, NON_ALIGN_CHK_EN %s\n", + (value & (1 << AXI_ADR_CHK_EN)) ? "ON" : "OFF", + (value & (1 << AXI_LOCK_CHK_EN)) ? "ON" : "OFF", + (value & (1 << AXI_NON_ALIGN_CHK_EN)) ? "ON" : "OFF"); + +} + +ssize_t emi_axi_vio_store(struct device_driver *driver, +const char *buf, size_t count) +{ + int value; + int cpu = 0; + /* assign timer to CPU0 to avoid CPU plug-out + and timer will be unavailable */ + + value = readl(IOMEM(EMI_CHKER)); + + if (!strncmp(buf, "ADR_CHK_ON", strlen("ADR_CHK_ON"))) { + emi_axi_set_chker(1 << AXI_ADR_CHK_EN); + add_timer_on(&emi_axi_vio_timer, cpu); + } else if (!strncmp(buf, "LOCK_CHK_ON", strlen("LOCK_CHK_ON"))) { + emi_axi_set_chker(1 << AXI_LOCK_CHK_EN); + add_timer_on(&emi_axi_vio_timer, cpu); + } else if (!strncmp(buf, "NON_ALIGN_CHK_ON", + strlen("NON_ALIGN_CHK_ON"))) { + emi_axi_set_chker(1 << AXI_NON_ALIGN_CHK_EN); + add_timer_on(&emi_axi_vio_timer, cpu); + } else if (!strncmp(buf, "OFF", strlen("OFF"))) { + emi_axi_set_chker(0); + del_timer(&emi_axi_vio_timer); + } else { + pr_err("invalid setting\n"); + } + + return count; +} + +DRIVER_ATTR(emi_axi_vio, 0644, emi_axi_vio_show, emi_axi_vio_store); + +#endif /* #ifdef ENABLE_EMI_CHKER */ + +#ifdef ENABLE_EMI_WATCH_POINT +static void emi_wp_set_address(unsigned int address) +{ + mt_reg_sync_writel(address - emi_physical_offset, EMI_WP_ADR); +} + +static void emi_wp_set_range(unsigned int range) +{ + unsigned int value; + + value = readl(IOMEM(EMI_WP_CTRL)); + value = (value & (~EMI_WP_RANGE)) | range; + mt_reg_sync_writel(value, EMI_WP_CTRL); +} + +static void emi_wp_set_monitor_type(unsigned int type) +{ + unsigned int value; + + value = readl(IOMEM(EMI_WP_CTRL)); + value = + (value & (~EMI_WP_RW_MONITOR)) | (type << EMI_WP_RW_MONITOR_SHIFT); + mt_reg_sync_writel(value, EMI_WP_CTRL); +} + +#if 0 +static void emi_wp_set_rw_disable(unsigned int type) +{ + unsigned int value; + + value = readl(IOMEM(EMI_WP_CTRL)); + value = + (value & (~EMI_WP_RW_DISABLE)) | (type << EMI_WP_RW_DISABLE_SHIFT); + mt_reg_sync_writel(value, EMI_WP_CTRL); +} +#endif + +static void emi_wp_enable(int enable) +{ + unsigned int value; + + /* Enable WP */ + value = readl(IOMEM(EMI_CHKER)); + value = + (value & ~(1 << EMI_WP_ENABLE_SHIFT)) | (enable << EMI_WP_ENABLE_SHIFT); + mt_reg_sync_writel(value, EMI_CHKER); +} + +static void emi_wp_slave_error_enable(unsigned int enable) +{ + unsigned int value; + + value = readl(IOMEM(EMI_WP_CTRL)); + value = + (value & ~(1 << EMI_WP_SLVERR_SHIFT)) | (enable << EMI_WP_SLVERR_SHIFT); + mt_reg_sync_writel(value, EMI_WP_CTRL); +} + +static void emi_wp_int_enable(unsigned int enable) +{ + unsigned int value; + + value = readl(IOMEM(EMI_WP_CTRL)); + value = + (value & ~(1 << EMI_WP_INT_SHIFT)) | (enable << EMI_WP_INT_SHIFT); + mt_reg_sync_writel(value, EMI_WP_CTRL); +} + +static void emi_wp_clr_status(void) +{ + unsigned int value; + int result; + + value = readl(IOMEM(EMI_CHKER)); + value |= 1 << EMI_WP_VIO_CLR_SHIFT; + mt_reg_sync_writel(value, EMI_CHKER); + + result = readl(IOMEM(EMI_CHKER)) & EMI_WP_AXI_ID; + result |= readl(IOMEM(EMI_CHKER_TYPE)); + result |= readl(IOMEM(EMI_CHKER_ADR)); + + if (result) + pr_err("[EMI_WP] Clear WP status fail!!!!!!!!!!!!!!\n"); +} + +void emi_wp_get_status(void) +{ + unsigned int value, master_ID; + char *master_name; + + value = readl(IOMEM(EMI_CHKER)); + + if ((value & 0x80000000) == 0) { + pr_err("[EMI_WP] No watch point hit\n"); + return; + } + + master_ID = (value & EMI_WP_AXI_ID); + pr_err("[EMI_WP] Violation master ID is 0x%x.\n", master_ID); + pr_err("[EMI_WP] Violation Address is : 0x%X\n", + readl(IOMEM(EMI_CHKER_ADR)) + emi_physical_offset); + + master_name = __id2name(master_ID); + pr_err("[EMI_WP] EMI_CHKER = 0x%x, module is %s.\n", + value, master_name); + + value = readl(IOMEM(EMI_CHKER_TYPE)); + pr_err("[EMI_WP] Transaction Type is : %d beat, %d byte, %s burst type (0x%X)\n", + (value & 0xF) + 1, + 1 << ((value >> 4) & 0x7), + (value >> 7 & 1) ? "INCR" : "WRAP", + value); + + emi_wp_clr_status(); +} + +static int emi_wp_set(unsigned int enable, +unsigned int address, unsigned int range, unsigned int rw) +{ + if (address < emi_physical_offset) { + pr_err("[EMI_WP] Address error, you can't set address less than 0x%X\n", + emi_physical_offset); + return -1; + } + if (range < 4 || range > 32) { + pr_err("[EMI_WP] Range error, you can't set range less than 16 bytes and more than 4G bytes\n"); + return -1; + } + + emi_wp_set_monitor_type(rw); + emi_wp_set_address(address); + emi_wp_set_range(range); + emi_wp_slave_error_enable(1); + emi_wp_int_enable(0); + emi_wp_enable(enable); + + return 0; +} + +static ssize_t emi_wp_vio_show(struct device_driver *driver, char *buf) +{ + unsigned int value, master_ID, type, vio_addr; + char *master_name; + char *ptr = buf; + + value = readl(IOMEM(EMI_CHKER)); + + if ((value & 0x80000000) == 0) { + return snprintf(buf, PAGE_SIZE, + "[EMI_WP] No watch point hit\n"); + } + + master_ID = (value & EMI_WP_AXI_ID); + master_name = __id2name(master_ID); + + type = readl(IOMEM(EMI_CHKER_TYPE)); + vio_addr = readl(IOMEM(EMI_CHKER_ADR)) + emi_physical_offset; + emi_wp_clr_status(); + ptr += snprintf(ptr, PAGE_SIZE, "[EMI WP] vio setting is: CHKER 0x%X, ", + value); + + ptr += snprintf(ptr, PAGE_SIZE, "module is %s, Address is : 0x%X," , + master_name, + vio_addr); + + ptr += snprintf(ptr, PAGE_SIZE, "Transaction Type is : %d beat, ", + (type & 0xF) + 1); + + ptr += snprintf(ptr, PAGE_SIZE, "%d byte, %s burst type (0x%X)\n", + 1 << ((type >> 4) & 0x7), + (type >> 7 & 1) ? "INCR" : "WRAP", + type); + return ptr - buf; +} + +ssize_t emi_wp_vio_store(struct device_driver *driver, +const char *buf, size_t count) +{ + int i; + unsigned int wp_addr; + unsigned int range, start_addr, end_addr; + unsigned int rw; + char *command; + char *ptr; + char *token[5]; + int err = 0; + + if ((strlen(buf) + 1) > MAX_EMI_MPU_STORE_CMD_LEN) { + pr_err("emi_wp_store command overflow."); + return count; + } + pr_err("emi_wp_store: %s\n", buf); + + command = kmalloc((size_t)MAX_EMI_MPU_STORE_CMD_LEN, GFP_KERNEL); + if (!command) + return count; + + strcpy(command, buf); + ptr = (char *)buf; + + if (!strncmp(buf, EN_WP_STR, strlen(EN_WP_STR))) { + i = 0; + while (ptr != NULL) { + ptr = strsep(&command, " "); + token[i] = ptr; + pr_debug("token[%d] = %s\n", i, token[i]); + i++; + } + for (i = 0; i < 4; i++) + pr_debug("token[%d] = %s\n", i, token[i]); + + err += kstrtoul(token[1], 16, (unsigned long *)&wp_addr); + err += kstrtoul(token[2], 16, (unsigned long *)&range); + err += kstrtoul(token[3], 16, (unsigned long *)&rw); + if (err) + goto out; + + emi_wp_set(1, wp_addr, range, rw); + + start_addr = (wp_addr >> range) << range; + end_addr = start_addr + (1 << range) - 1; + pr_err("Set EMI_WP: address: 0x%x, range:%d, start addr: 0x%x, end addr: 0x%x, rw: %d .\n", + wp_addr, range, start_addr, end_addr, rw); + } else if (!strncmp(buf, DIS_WP_STR, strlen(DIS_WP_STR))) { + i = 0; + while (ptr != NULL) { + ptr = strsep(&command, " "); + token[i] = ptr; + pr_debug("token[%d] = %s\n", i, token[i]); + i++; + } + for (i = 0; i < 4; i++) + pr_debug("token[%d] = %s\n", i, token[i]); + + + err += kstrtoul(token[1], 16, (unsigned long *)&wp_addr); + err += kstrtoul(token[2], 16, (unsigned long *)&range); + err += kstrtoul(token[3], 16, (unsigned long *)&rw); + if (err) + goto out; + + emi_wp_set(0, 0x40000000, 4, 2); + pr_err("disable EMI WP\n"); + } else { + pr_err("Unknown emi_wp command.\n"); + } + +out: + kfree(command); + + return count; +} + + +DRIVER_ATTR(emi_wp_vio, 0644, emi_wp_vio_show, emi_wp_vio_store); +#endif /* #ifdef ENABLE_EMI_WATCH_POINT */ + +#define AP_REGION_ID 19 +static void protect_ap_region(void) +{ + + unsigned int ap_mem_mpu_id, ap_mem_mpu_attr; + unsigned long long kernel_base; + phys_addr_t dram_size; + + kernel_base = emi_physical_offset; + dram_size = get_max_DRAM_size(); + + ap_mem_mpu_id = AP_REGION_ID; + ap_mem_mpu_attr = SET_ACCESS_PERMISSON(FORBIDDEN, + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, NO_PROTECTION); + + emi_mpu_set_region_protection(kernel_base, + (kernel_base+dram_size-1), ap_mem_mpu_id, ap_mem_mpu_attr); + +} + +static struct platform_driver emi_mpu_ctrl = { + .driver = { + .name = "emi_mpu_ctrl", + .bus = &platform_bus_type, + .owner = THIS_MODULE, + }, + .id_table = NULL, +}; + +static int __init emi_mpu_mod_init(void) +{ + int ret; + struct device_node *node; + unsigned int mpu_irq; + + pr_info("Initialize EMI MPU.\n"); + + isetocunt = 0; + + /* DTS version */ + if (EMI_BASE_ADDR == NULL) { + node = of_find_compatible_node(NULL, NULL, "mediatek,EMI"); + if (node) { + EMI_BASE_ADDR = of_iomap(node, 0); + pr_err("get EMI_BASE_ADDR @ %p\n", EMI_BASE_ADDR); + } else { + pr_err("can't find compatible node\n"); + return -1; + } + } + + node = of_find_compatible_node(NULL, NULL, "mediatek,devapc"); + if (node) { + mpu_irq = irq_of_parse_and_map(node, 0); + pr_notice("get EMI_MPU irq = %d\n", mpu_irq); + } else { + pr_err("can't find compatible node\n"); + return -1; + } + + spin_lock_init(&emi_mpu_lock); + + pr_err("[EMI MPU] EMI_MPUP = 0x%x\n", readl(IOMEM(EMI_MPUP))); + pr_err("[EMI MPU] EMI_MPUQ = 0x%x\n", readl(IOMEM(EMI_MPUQ))); + pr_err("[EMI MPU] EMI_MPUR = 0x%x\n", readl(IOMEM(EMI_MPUR))); + pr_err("[EMI MPU] EMI_MPUY = 0x%x\n", readl(IOMEM(EMI_MPUY))); + pr_err("[EMI MPU] EMI_MPUP2 = 0x%x\n", readl(IOMEM(EMI_MPUP2))); + pr_err("[EMI MPU] EMI_MPUQ2 = 0x%x\n", readl(IOMEM(EMI_MPUQ2))); + pr_err("[EMI MPU] EMI_MPUR2 = 0x%x\n", readl(IOMEM(EMI_MPUR2))); + pr_err("[EMI MPU] EMI_MPUY2 = 0x%x\n", readl(IOMEM(EMI_MPUY2))); + + pr_err("[EMI MPU] EMI_MPUS = 0x%x\n", readl(IOMEM(EMI_MPUS))); + pr_err("[EMI MPU] EMI_MPUT = 0x%x\n", readl(IOMEM(EMI_MPUT))); + + pr_err("[EMI MPU] EMI_WP_ADR = 0x%x\n", readl(IOMEM(EMI_WP_ADR))); + pr_err("[EMI MPU] EMI_WP_CTRL = 0x%x\n", readl(IOMEM(EMI_WP_CTRL))); + pr_err("[EMI MPU] EMI_CHKER = 0x%x\n", readl(IOMEM(EMI_CHKER))); + pr_err("[EMI MPU] EMI_CHKER_TYPE = 0x%x\n", + readl(IOMEM(EMI_CHKER_TYPE))); + pr_err("[EMI MPU] EMI_CHKER_ADR = 0x%x\n", readl(IOMEM(EMI_CHKER_ADR))); + + pr_err("[EMI MPU] EMI_MPUW = 0x%x\n", mt_emi_reg_read(EMI_MPUW)); + pr_err("[EMI MPU] EMI_MPUV = 0x%x\n", mt_emi_reg_read(EMI_MPUV)); + pr_err("[EMI MPU] EMI_MPUX = 0x%x\n", mt_emi_reg_read(EMI_MPUX)); + + if (readl(IOMEM(EMI_MPUS))) { + pr_err("[EMI MPU] get MPU violation in driver init\n"); + mt_devapc_emi_initial(); + mpu_check_violation(); + } else { + __clear_emi_mpu_vio(0); + /* Set Device APC initialization for EMI-MPU. */ + mt_devapc_emi_initial(); + } + + + if (enable_4gb) + emi_physical_offset = 0; + else + emi_physical_offset = 0x40000000; + + + /* + * NoteXXX: Interrupts of violation (including SPC in SMI, or EMI MPU) + * are triggered by the device APC. + * Need to share the interrupt with the SPC driver. + */ + + ret = request_irq(mpu_irq, + (irq_handler_t)mpu_violation_irq, IRQF_TRIGGER_LOW | IRQF_SHARED, + "mt_emi_mpu", &emi_mpu_ctrl); + if (ret != 0) { + pr_err("Fail to request EMI_MPU interrupt. Error = %d.\n", ret); + return ret; + } + + protect_ap_region(); + +#ifdef ENABLE_EMI_CHKER + /* AXI violation monitor setting and timer function create */ + mt_reg_sync_writel((1 << AXI_VIO_CLR) | readl(IOMEM(EMI_CHKER)), + EMI_CHKER); + emi_axi_set_master(MASTER_ALL); + init_timer(&emi_axi_vio_timer); + emi_axi_vio_timer.expires = jiffies + AXI_VIO_MONITOR_TIME; + emi_axi_vio_timer.function = &emi_axi_vio_timer_func; + emi_axi_vio_timer.data = ((unsigned long) 0); +#endif /* #ifdef ENABLE_EMI_CHKER */ + +#if !defined(USER_BUILD_KERNEL) + + /* register driver and create sysfs files */ + ret = platform_driver_register(&emi_mpu_ctrl); + if (ret) + pr_err("Fail to register EMI_MPU driver.\n"); + + ret = driver_create_file(&emi_mpu_ctrl.driver, &driver_attr_mpu_config); + if (ret) + pr_err("Fail to create MPU config sysfs file.\n"); +#ifdef ENABLE_EMI_CHKER +ret = driver_create_file(&emi_mpu_ctrl.driver, &driver_attr_emi_axi_vio); + + if (ret) + pr_err("Fail to create AXI violation monitor sysfs file.\n"); +#endif + ret = driver_create_file(&emi_mpu_ctrl.driver, &driver_attr_pgt_scan); + if (ret) + pr_err("Fail to create pgt scan sysfs file.\n"); + +#ifdef ENABLE_EMI_WATCH_POINT + ret = driver_create_file(&emi_mpu_ctrl.driver, &driver_attr_emi_wp_vio); + if (ret) + pr_err("Fail to create WP violation monitor sysfs file.\n"); + +#endif +#endif + + /* Create a workqueue to search pagetable entry */ + emi_mpu_workqueue = create_singlethread_workqueue("emi_mpu"); + INIT_WORK(&emi_mpu_work, emi_mpu_work_callback); + + return 0; +} + +static void __exit emi_mpu_mod_exit(void) +{ +} + +module_init(emi_mpu_mod_init); +module_exit(emi_mpu_mod_exit); + +#ifdef CONFIG_MTK_LM_MODE +unsigned int enable_4G(void) +{ + return enable_4gb; +} + +static int __init dram_4gb_init(void) +{ + void __iomem *INFRA_BASE_ADDR = NULL; + void __iomem *PERISYS_BASE_ADDR = NULL; + struct device_node *node; + unsigned int infra_4g_sp, perisis_4g_sp; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-infrasys"); + + if (!node) + pr_err("find INFRACFG_AO node failed\n"); + + INFRA_BASE_ADDR = of_iomap(node, 0); + + if (!INFRA_BASE_ADDR) + pr_err("INFRACFG_AO ioremap failed\n"); + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-perisys"); + + if (!node) + pr_err("find PERICFG node failed\n"); + + PERISYS_BASE_ADDR = of_iomap(node, 0); + + if (!PERISYS_BASE_ADDR) + pr_err("PERISYS_BASE_ADDR ioremap failed\n"); + + infra_4g_sp = readl(IOMEM(INFRA_BASE_ADDR + 0xf00)) & (1 << 13); + perisis_4g_sp = readl(IOMEM(PERISYS_BASE_ADDR + 0x208)) & (1 << 15); + + pr_err("infra = 0x%x perisis = 0x%x result = %d\n", + infra_4g_sp, + perisis_4g_sp, + (infra_4g_sp && perisis_4g_sp)); + + if (infra_4g_sp && perisis_4g_sp) { + enable_4gb = 1; + pr_err("[EMI MPU] 4G mode\n"); + } else { + enable_4gb = 0; + pr_err("[EMI MPU] Not 4G mode\n"); + } + + return 0; +} + +early_initcall(dram_4gb_init); +#endif diff --git a/drivers/misc/mediatek/ext_disp/mt6755/Makefile b/drivers/misc/mediatek/ext_disp/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d4941fb6f9e3dc9322efeaeeaba95dcbd173b23f --- /dev/null +++ b/drivers/misc/mediatek/ext_disp/mt6755/Makefile @@ -0,0 +1,53 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +# +# Makefile for external display driver. +# + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/ \ + -I$(srctree)/drivers/misc/mediatek/ext_disp/ \ + -I$(srctree)/drivers/misc/mediatek/ext_disp/common/test/ \ + -I$(srctree)/drivers/misc/mediatek/gpu/ged/include \ + -I$(srctree)/drivers/misc/mediatek/video/common \ + -I$(srctree)/drivers/misc/mediatek/video/include/ \ + -I$(srctree)/drivers/misc/mediatek/video/$(MTK_PLATFORM)/ \ + -I$(srctree)/drivers/misc/mediatek/video/$(MTK_PLATFORM)/dispsys/ \ + -I$(srctree)/drivers/misc/mediatek/video/$(MTK_PLATFORM)/videox/ \ + -I$(srctree)/drivers/misc/mediatek/sync/ \ + -I$(srctree)/drivers/misc/mediatek/hdmi/$(CONFIG_CUSTOM_KERNEL_HDMI)/ \ + -I$(srctree)/drivers/misc/mediatek/cmdq/v2/ \ + -I$(srctree)/drivers/misc/mediatek/cmdq/v2/$(MTK_PLATFORM)/ \ + -I$(srctree)/drivers/misc/mediatek/hdmi/inc/ \ + -I$(srctree)/drivers/misc/mediatek/smi \ + -I$(srctree)/drivers/staging/android/ion \ + -I$(srctree)/drivers/staging/android/ion/mtk \ + -I$(srctree)/drivers/misc/mediatek/lcm/inc + +subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/m4u/$(MTK_PLATFORM) +subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/mmp/ + +ifeq ($(CONFIG_CUSTOM_KERNEL_HDMI), "MT8193") +ccflags-y += -DHDMI_MT8193_SUPPORT +ccflags-y += -I$(srctree)/drivers/misc/mediatek/hdmi/mt8193/ +endif + +obj-y := \ + external_display.o \ + extd_debug.o \ + ./../mtk_extd_mgr.o \ + ./../extd_utils.o \ + ./../extd_hdmi.o \ + ./../extd_epd.o \ + ./../extd_multi_control.o \ + ./../extd_factory.o diff --git a/drivers/misc/mediatek/ext_disp/mt6755/extd_debug.c b/drivers/misc/mediatek/ext_disp/mt6755/extd_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..815e52b682a012c0cece39cab6032e22245e743f --- /dev/null +++ b/drivers/misc/mediatek/ext_disp/mt6755/extd_debug.c @@ -0,0 +1,166 @@ +#if defined(CONFIG_MTK_HDMI_SUPPORT) +#include +#include +#include +#include + +#include +#include + + +#include "ddp_hal.h" +#include "ddp_reg.h" +#include "ddp_info.h" +#include "ddp_dump.h" +#include "extd_hdmi.h" +#include "external_display.h" + +/*extern DDP_MODULE_DRIVER *ddp_modules_driver[DISP_MODULE_NUM];*/ +/* --------------------------------------------------------------------------- */ +/* External variable declarations */ +/* --------------------------------------------------------------------------- */ + +/* extern LCM_DRIVER *lcm_drv; */ +/* --------------------------------------------------------------------------- */ +/* Debug Options */ +/* --------------------------------------------------------------------------- */ + + +static const char STR_HELP[] = "\n" "USAGE\n" " echo [ACTION]... > hdmi\n" "\n" "ACTION\n" + " hdmitx:[on|off]\n" " enable hdmi video output\n" "\n"; + +/* TODO: this is a temp debug solution */ +/* extern void hdmi_cable_fake_plug_in(void); */ +/* extern int hdmi_drv_init(void); */ +static void process_dbg_opt(const char *opt) +{ + if (0 == strncmp(opt, "on", 2)) + hdmi_power_on(); + else if (0 == strncmp(opt, "off", 3)) + hdmi_power_off(); + else if (0 == strncmp(opt, "suspend", 7)) + hdmi_suspend(); + else if (0 == strncmp(opt, "resume", 6)) + hdmi_resume(); + else if (0 == strncmp(opt, "fakecablein:", 12)) { + if (0 == strncmp(opt + 12, "enable", 6)) + hdmi_cable_fake_plug_in(); + else if (0 == strncmp(opt + 12, "disable", 7)) + hdmi_cable_fake_plug_out(); + else + goto Error; + } else if (0 == strncmp(opt, "path_analyze", 12)) + ext_disp_diagnose(); + else if (0 == strncmp(opt, "UART:", 5)) { + if (0 == strncmp(opt + 5, "on", 2)) { + pr_debug("[hdmi][Debug] Enable UART,disable DPI D6/D7\n"); +/* mt_set_gpio_mode(GPIO19|0x80000000, GPIO_MODE_02); + mt_set_gpio_mode(GPIO20|0x80000000, GPIO_MODE_02);*/ + } else if (0 == strncmp(opt + 5, "off", 3)) { + pr_debug("[hdmi][Debug] Disable UART,enable DPI D6/D7\n"); +/* mt_set_gpio_mode(GPIO19|0x80000000, GPIO_MODE_02); + mt_set_gpio_mode(GPIO20|0x80000000, GPIO_MODE_02);*/ + } + } else if (0 == strncmp(opt, "extd_analyze", 12)) { + ddp_dump_analysis(DISP_MODULE_CONFIG); + ddp_dump_analysis(DISP_MODULE_MUTEX); + ddp_dump_analysis(DISP_MODULE_OVL1); + ddp_dump_analysis(DISP_MODULE_RDMA1); + + ddp_dump_reg(DISP_MODULE_CONFIG); + ddp_dump_reg(DISP_MODULE_MUTEX); + ddp_dump_reg(DISP_MODULE_OVL1); + ddp_dump_reg(DISP_MODULE_RDMA1); + ddp_dump_reg(DISP_MODULE_DPI); + } else if (0 == strncmp(opt, "DPI_DUMP", 8)) + ddp_dump_reg(DISP_MODULE_DPI); + else if (0 == strncmp(opt, "forceon", 7)) + hdmi_force_on(false); + else if (0 == strncmp(opt, "extd_vsync:", 11)) { + if (0 == strncmp(opt + 11, "on", 2)) + hdmi_wait_vsync_debug(1); + else if (0 == strncmp(opt + 11, "off", 3)) + hdmi_wait_vsync_debug(0); + } else + goto Error; + + return; + + Error: + pr_debug("[extd] parse command error!\n\n%s", STR_HELP); +} + +static void process_dbg_cmd(char *cmd) +{ + char *tok; + + pr_debug("[extd] %s\n", cmd); + + while ((tok = strsep(&cmd, " ")) != NULL) + process_dbg_opt(tok); +} + +/* --------------------------------------------------------------------------- */ +/* Debug FileSystem Routines */ +/* --------------------------------------------------------------------------- */ +struct dentry *extd_dbgfs = NULL; + +static int debug_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static char debug_buffer[2048]; + +static ssize_t debug_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) +{ + const int debug_bufmax = sizeof(debug_buffer) - 1; + int n = 0; + + n += scnprintf(debug_buffer + n, debug_bufmax - n, STR_HELP); + debug_buffer[n++] = 0; + + return simple_read_from_buffer(ubuf, count, ppos, debug_buffer, n); +} + +static ssize_t debug_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) +{ + const int debug_bufmax = sizeof(debug_buffer) - 1; + size_t ret; + + ret = count; + + if (count > debug_bufmax) + count = debug_bufmax; + + if (copy_from_user(&debug_buffer, ubuf, count)) + return -EFAULT; + + debug_buffer[count] = 0; + + process_dbg_cmd(debug_buffer); + + return ret; +} + + +static const struct file_operations debug_fops = { + .read = debug_read, + .write = debug_write, + .open = debug_open, +}; + + +void Extd_DBG_Init(void) +{ + extd_dbgfs = debugfs_create_file("extd", S_IFREG | S_IRUGO, NULL, (void *)0, &debug_fops); +} + + +void Extd_DBG_Deinit(void) +{ + debugfs_remove(extd_dbgfs); +} + +#endif diff --git a/drivers/misc/mediatek/ext_disp/mt6755/extd_platform.h b/drivers/misc/mediatek/ext_disp/mt6755/extd_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..7b97a75eea10af4e4a384eaddce21dd14f8ad815 --- /dev/null +++ b/drivers/misc/mediatek/ext_disp/mt6755/extd_platform.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __EXTD_PLATFORM_H__ +#define __EXTD_PLATFORM_H__ + +#include "ddp_hal.h" + + +/* #define MTK_LCD_HW_3D_SUPPORT */ +#define ALIGN_TO(x, n) \ + (((x) + ((n) - 1)) & ~((n) - 1)) + + +#define MTK_EXT_DISP_OVERLAY_SUPPORT + +/* /#define EXTD_DBG_USE_INNER_BUF */ + +#define HW_OVERLAY_COUNT 4 +#define EXTD_OVERLAY_CNT 4 +#define HW_DPI_VSYNC_SUPPORT 1 + +#define DISP_MODULE_RDMA DISP_MODULE_RDMA1 + +#define MM_MHL_DVFS +#define MHL_DYNAMIC_VSYNC_OFFSET + +#define MHL_RESOLUTION_LIMIT_1080P_30 +#endif + diff --git a/drivers/misc/mediatek/ext_disp/mt6755/external_display.c b/drivers/misc/mediatek/ext_disp/mt6755/external_display.c new file mode 100644 index 0000000000000000000000000000000000000000..a8fa4165daf08822df9da9eacedd99a79296ae51 --- /dev/null +++ b/drivers/misc/mediatek/ext_disp/mt6755/external_display.c @@ -0,0 +1,1433 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "mtkfb_info.h" +#include "mtkfb.h" + +#include "ddp_hal.h" +#include "ddp_dump.h" +#include "ddp_path.h" +#include "ddp_drv.h" +#include "ddp_info.h" + +#include +#include "cmdq_def.h" +#include "cmdq_record.h" +#include "cmdq_reg.h" +#include "cmdq_core.h" + +#include "ddp_manager.h" +#include "ddp_mmp.h" +#include "ddp_ovl.h" +#include "lcm_drv.h" + +#include "extd_platform.h" +#include "extd_log.h" +#include "extd_utils.h" +#include "extd_hdmi_types.h" +#include "external_display.h" + +#include "disp_session.h" +#include "disp_lowpower.h" +#include "disp_recorder.h" +#include "extd_info.h" + +int ext_disp_use_cmdq; +int ext_disp_use_m4u; +enum EXT_DISP_PATH_MODE ext_disp_mode; + +static int is_context_inited; +static int init_roi; + +struct ext_disp_path_context { + enum EXTD_POWER_STATE state; + enum EXTD_OVL_REQ_STATUS ovl_req_state; + int init; + unsigned int session; + int need_trigger_overlay; + int suspend_config; + enum EXT_DISP_PATH_MODE mode; + unsigned int last_vsync_tick; + struct mutex lock; + struct mutex vsync_lock; + cmdqRecHandle cmdq_handle_config; + cmdqRecHandle cmdq_handle_trigger; + disp_path_handle dpmgr_handle; + disp_path_handle ovl2mem_path_handle; +}; + +#define pgc _get_context() + +LCM_PARAMS extd_lcm_params; + +static struct ext_disp_path_context *_get_context(void) +{ + static struct ext_disp_path_context g_context; + + if (!is_context_inited) { + memset((void *)&g_context, 0, sizeof(struct ext_disp_path_context)); + is_context_inited = 1; + EXT_DISP_LOG("_get_context set is_context_inited\n"); + } + + return &g_context; +} + +enum EXT_DISP_PATH_MODE ext_disp_path_get_mode(unsigned int session) +{ + return ext_disp_mode; +} + +void ext_disp_path_set_mode(enum EXT_DISP_PATH_MODE mode, unsigned int session) +{ + ext_disp_mode = mode; + init_roi = (mode == EXTD_DIRECT_LINK_MODE ? 1 : 0); +} + +static void _ext_disp_path_lock(void) +{ + extd_sw_mutex_lock(NULL); /* /(&(pgc->lock)); */ +} + +static void _ext_disp_path_unlock(void) +{ + extd_sw_mutex_unlock(NULL); /* (&(pgc->lock)); */ +} + +static void _ext_disp_vsync_lock(unsigned int session) +{ + mutex_lock(&(pgc->vsync_lock)); +} + +static void _ext_disp_vsync_unlock(unsigned int session) +{ + mutex_unlock(&(pgc->vsync_lock)); +} + +static DISP_MODULE_ENUM _get_dst_module_by_lcm(disp_path_handle pHandle) +{ + return DISP_MODULE_DPI; +} + +/*************************************************************** +***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU +*** 1.wait idle: N N Y Y +*** 2.lcm update: N Y N Y +*** 3.path start: idle->Y Y idle->Y Y +*** 4.path trigger: idle->Y Y idle->Y Y +*** 5.mutex enable: N N idle->Y Y +*** 6.set cmdq dirty: N Y N N +*** 7.flush cmdq: Y Y N N +*** 8.reset cmdq: Y Y N N +*** 9.cmdq insert token: Y Y N N +****************************************************************/ + +/* + * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + * 1.wait idle: N N Y Y +*/ +static int _should_wait_path_idle(void) +{ + if (ext_disp_cmdq_enabled()) + return 0; + else + return dpmgr_path_is_busy(pgc->dpmgr_handle); +} + +/* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + * 2.lcm update: N Y N Y +*/ +/* +static int _should_update_lcm(void) +{ + if (ext_disp_cmdq_enabled() || ext_disp_is_video_mode()) + return 0; + else + return 1; +} +*/ + +/* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + * 3.path start: idle->Y Y idle->Y Y +*/ +static int _should_start_path(void) +{ + if (ext_disp_is_video_mode()) + return dpmgr_path_is_idle(pgc->dpmgr_handle); + else + return 1; +} + +/* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + * 4. path trigger: idle->Y Y idle->Y Y + * 5. mutex enable: N N idle->Y Y +*/ +static int _should_trigger_path(void) +{ + /* this is not a perfect design, we can't decide path trigger(ovl/rdma/dsi..) separately with mutex enable */ + /* but it's lucky because path trigger and mutex enable is the same w/o cmdq, and it's correct w/ CMDQ(Y+N). */ + if (ext_disp_is_video_mode()) + return dpmgr_path_is_idle(pgc->dpmgr_handle); + else if (ext_disp_cmdq_enabled()) + return 0; + else + return 1; +} + +/* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + * 6. set cmdq dirty: N Y N N +*/ +static int _should_set_cmdq_dirty(void) +{ + if (ext_disp_cmdq_enabled() && (ext_disp_is_video_mode() == 0)) + return 1; + else + return 0; +} + +/* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + * 7. flush cmdq: Y Y N N +*/ +static int _should_flush_cmdq_config_handle(void) +{ + return ext_disp_cmdq_enabled() ? 1 : 0; +} + +/* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + * 8. reset cmdq: Y Y N N +*/ +static int _should_reset_cmdq_config_handle(void) +{ + return ext_disp_cmdq_enabled() ? 1 : 0; +} + +/* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + * 9. cmdq insert token: Y Y N N +*/ +static int _should_insert_wait_frame_done_token(void) +{ + return ext_disp_cmdq_enabled() ? 1 : 0; +} + +static int _should_trigger_interface(void) +{ + if (pgc->mode == EXTD_DECOUPLE_MODE) + return 0; + else + return 1; +} + +static int _should_config_ovl_input(void) +{ + /* should extend this when display path dynamic switch is ready */ + /* if(pgc->mode == EXTD_SINGLE_LAYER_MODE ||pgc->mode == EXTD_RDMA_DPI_MODE) */ + /* return 0; */ + /* else */ + /* return 1; */ + + if (ext_disp_mode == EXTD_SINGLE_LAYER_MODE || ext_disp_mode == EXTD_RDMA_DPI_MODE) + return 0; + else + return 1; +} + +#define OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO +static long int get_current_time_us(void) +{ + struct timeval t; + + do_gettimeofday(&t); + return (t.tv_sec & 0xFFF) * 1000000 + t.tv_usec; +} + +/* +static enum hrtimer_restart _DISP_CmdModeTimer_handler(struct hrtimer *timer) +{ + EXT_DISP_LOG("fake timer, wake up\n"); + dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); +#if 0 + if ((get_current_time_us() - pgc->last_vsync_tick) > 16666) { + dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + pgc->last_vsync_tick = get_current_time_us(); + } +#endif + return HRTIMER_RESTART; +} + +static int _init_vsync_fake_monitor(int fps) +{ + static struct hrtimer cmd_mode_update_timer; + static ktime_t cmd_mode_update_timer_period; + + if (fps == 0) + fps = 60; + + cmd_mode_update_timer_period = ktime_set(0, 1000 / fps * 1000); + EXT_DISP_LOG("[MTKFB] vsync timer_period=%d\n", 1000 / fps); + hrtimer_init(&cmd_mode_update_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + cmd_mode_update_timer.function = _DISP_CmdModeTimer_handler; + + return 0; +} +*/ + +static int _build_path_direct_link(void) +{ + int ret = 0; + M4U_PORT_STRUCT sPort; + + DISP_MODULE_ENUM dst_module = 0; + + EXT_DISP_FUNC(); + pgc->mode = EXTD_DIRECT_LINK_MODE; + + pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_SUB_DISP, pgc->cmdq_handle_config); + if (pgc->dpmgr_handle) + EXT_DISP_LOG("dpmgr create path SUCCESS(%p)\n", pgc->dpmgr_handle); + else { + EXT_DISP_LOG("dpmgr create path FAIL\n"); + return -1; + } + + dst_module = DISP_MODULE_DPI; + dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module); + /* EXT_DISP_LOG("dpmgr set dst module FINISHED(%s)\n", ddp_get_module_name(dst_module)); */ + sPort.ePortID = M4U_PORT_DISP_OVL1; + sPort.Virtuality = ext_disp_use_m4u; + sPort.Security = 0; + sPort.Distance = 1; + sPort.Direction = 0; + ret = m4u_config_port(&sPort); + if (ret == 0) { + EXT_DISP_LOG("config M4U Port %s to %s SUCCESS\n", + ddp_get_module_name(DISP_MODULE_OVL1), ext_disp_use_m4u ? "virtual" : "physical"); + } else { + EXT_DISP_LOG("config M4U Port %s to %s FAIL(ret=%d)\n", ddp_get_module_name(M4U_PORT_DISP_OVL1), + ext_disp_use_m4u ? "virtual" : "physical", ret); + return -1; + } + + dpmgr_set_lcm_utils(pgc->dpmgr_handle, NULL); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START); + + return ret; +} + + +static int _build_path_decouple(void) +{ + return 0; +} + +static int _build_path_single_layer(void) +{ + return 0; +} + +static int _build_path_rdma_dpi(void) +{ + int ret = 0; + M4U_PORT_STRUCT sPort; + + DISP_MODULE_ENUM dst_module = 0; + + pgc->mode = EXTD_RDMA_DPI_MODE; + + pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_SUB_RDMA1_DISP, pgc->cmdq_handle_config); + if (pgc->dpmgr_handle) + EXT_DISP_LOG("dpmgr create path SUCCESS(%p)\n", pgc->dpmgr_handle); + else { + EXT_DISP_LOG("dpmgr create path FAIL\n"); + return -1; + } + + dst_module = _get_dst_module_by_lcm(pgc->dpmgr_handle); + dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module); + EXT_DISP_LOG("dpmgr set dst module FINISHED(%s)\n", ddp_get_module_name(dst_module)); + + sPort.ePortID = M4U_PORT_DISP_RDMA1; + sPort.Virtuality = ext_disp_use_m4u; + sPort.Security = 0; + sPort.Distance = 1; + sPort.Direction = 0; + ret = m4u_config_port(&sPort); + if (ret == 0) { + EXT_DISP_LOG("config M4U Port %s to %s SUCCESS\n", ddp_get_module_name(DISP_MODULE_RDMA1), + ext_disp_use_m4u ? "virtual" : "physical"); + } else { + EXT_DISP_LOG("config M4U Port %s to %s FAIL(ret=%d)\n", ddp_get_module_name(DISP_MODULE_RDMA1), + ext_disp_use_m4u ? "virtual" : "physical", ret); + return -1; + } + + dpmgr_set_lcm_utils(pgc->dpmgr_handle, NULL); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); + + return ret; +} + +static void _cmdq_build_trigger_loop(void) +{ + int ret = 0; + + cmdqRecCreate(CMDQ_SCENARIO_TRIGGER_LOOP, &(pgc->cmdq_handle_trigger)); + EXT_DISP_LOG("ext_disp path trigger thread cmd handle=%p\n", pgc->cmdq_handle_trigger); + cmdqRecReset(pgc->cmdq_handle_trigger); + + if (ext_disp_is_video_mode()) { + /* wait and clear stream_done, HW will assert mutex enable automatically in frame done reset. */ + /* todo: should let dpmanager to decide wait which mutex's eof. */ + ret = cmdqRecWait(pgc->cmdq_handle_trigger, + dpmgr_path_get_mutex(pgc->dpmgr_handle) + CMDQ_EVENT_MUTEX0_STREAM_EOF); + + /* for some module(like COLOR) to read hw register to GPR after frame done */ + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_AFTER_STREAM_EOF, 0); + } else { + /* DSI command mode doesn't have mutex_stream_eof, need use CMDQ token instead */ + ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + + /* ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_MDP_DSI0_TE_SOF); */ + /* for operations before frame transfer, such as waiting for DSI TE */ + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_BEFORE_STREAM_SOF, 0); + + /* cleat frame done token, now the config thread will not allowed to config registers. */ + /* remember that config thread's priority is higher than trigger thread*/ + /* so all the config queued before will be applied then STREAM_EOF token be cleared */ + /* this is what CMDQ did as "Merge" */ + ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF); + + /* enable mutex, only cmd mode need this */ + /* this is what CMDQ did as "Trigger" */ + dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_ENABLE); + + /* waiting for frame done, because we can't use mutex stream eof here*/ + /* so need to let dpmanager help to decide which event to wait */ + /* most time we wait rdmax frame done event. */ + ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA1_EOF); + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_WAIT_STREAM_EOF_EVENT, 0); + + /* dsi is not idle rightly after rdma frame done, */ + /* so we need to polling about 1us for dsi returns to idle */ + /* do not polling dsi idle directly which will decrease CMDQ performance */ + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_CHECK_IDLE_AFTER_STREAM_EOF, 0); + + /* for some module(like COLOR) to read hw register to GPR after frame done */ + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_AFTER_STREAM_EOF, 0); + + /* polling DSI idle */ + /* ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x1401b00c, 0, 0x80000000); */ + /* polling wdma frame done */ + /* ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x140060A0, 1, 0x1); */ + + /* now frame done, config thread is allowed to config register now */ + ret = cmdqRecSetEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF); + + /* RUN forever!!!! */ + BUG_ON(ret < 0); + } + + /* dump trigger loop instructions to check whether dpmgr_path_build_cmdq works correctly */ + cmdqRecDumpCommand(pgc->cmdq_handle_trigger); + EXT_DISP_LOG("ext display BUILD cmdq trigger loop finished\n"); +} + +static void _cmdq_start_trigger_loop(void) +{ + int ret = 0; + + /* this should be called only once because trigger loop will nevet stop */ + ret = cmdqRecStartLoop(pgc->cmdq_handle_trigger); + if (!ext_disp_is_video_mode()) { + /* need to set STREAM_EOF for the first time, otherwise we will stuck in dead loop */ + cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_STREAM_EOF); + /* /dprec_event_op(DPREC_EVENT_CMDQ_SET_EVENT_ALLOW); */ + } + + EXT_DISP_LOG("START cmdq trigger loop finished\n"); +} + +static void _cmdq_stop_trigger_loop(void) +{ + int ret = 0; + + /* this should be called only once because trigger loop will nevet stop */ + ret = cmdqRecStopLoop(pgc->cmdq_handle_trigger); + + EXT_DISP_LOG("ext display STOP cmdq trigger loop finished\n"); +} + + +static void _cmdq_set_config_handle_dirty(void) +{ + if (!ext_disp_is_video_mode()) { + /* only command mode need to set dirty */ + cmdqRecSetEventToken(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + /* /dprec_event_op(DPREC_EVENT_CMDQ_SET_DIRTY); */ + } +} + +static void _cmdq_reset_config_handle(void) +{ + cmdqRecReset(pgc->cmdq_handle_config); + /* /dprec_event_op(DPREC_EVENT_CMDQ_RESET); */ +} + +static void _cmdq_flush_config_handle(int blocking, void *callback, unsigned int userdata) +{ + if (blocking) { + /* it will be blocked until mutex done */ + cmdqRecFlush(pgc->cmdq_handle_config); + } else { + if (callback) + cmdqRecFlushAsyncCallback(pgc->cmdq_handle_config, callback, userdata); + else + cmdqRecFlushAsync(pgc->cmdq_handle_config); + } + /* dprec_event_op(DPREC_EVENT_CMDQ_FLUSH); */ +} + +static void _cmdq_insert_wait_frame_done_token(int clear_event) +{ + if (ext_disp_is_video_mode()) { + if (clear_event == 0) { + cmdqRecWaitNoClear(pgc->cmdq_handle_config, + dpmgr_path_get_mutex(pgc->dpmgr_handle) + CMDQ_EVENT_MUTEX0_STREAM_EOF); + } else { + cmdqRecWait(pgc->cmdq_handle_config, + dpmgr_path_get_mutex(pgc->dpmgr_handle) + CMDQ_EVENT_MUTEX0_STREAM_EOF); + } + } else { + if (clear_event == 0) + cmdqRecWaitNoClear(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_STREAM_EOF); + else + cmdqRecWait(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_STREAM_EOF); + } + + /* /dprec_event_op(DPREC_EVENT_CMDQ_WAIT_STREAM_EOF); */ +} + +static int _convert_disp_input_to_rdma(RDMA_CONFIG_STRUCT *dst, disp_input_config *src, + unsigned int screen_w, unsigned int screen_h) +{ +/* int right_edge = 0; + int bottom_edge = 0;*/ + unsigned int Bpp = 0; + unsigned long mva_offset = 0; + enum UNIFIED_COLOR_FMT tmp_fmt; + + if (!src || !dst) { + EXT_DISP_ERR("%s src(0x%p) or dst(0x%p) is null\n", __func__, src, dst); + return -1; + } + + dst->idx = src->next_buff_idx; + + tmp_fmt = disp_fmt_to_unified_fmt(src->src_fmt); + ufmt_disable_X_channel(tmp_fmt, &dst->inputFormat, NULL); + + Bpp = UFMT_GET_Bpp(dst->inputFormat); + mva_offset = (src->src_offset_x + src->src_offset_y * src->src_pitch) * Bpp; + + dst->address = (unsigned long)src->src_phy_addr + mva_offset; + dst->pitch = src->src_pitch * Bpp; + + dst->width = min(src->src_width, src->tgt_width); + dst->height = min(src->src_height, src->tgt_height); + dst->security = src->security; + dst->yuv_range = src->yuv_range; + + dst->dst_y = src->tgt_offset_y; + dst->dst_x = src->tgt_offset_x; + dst->dst_h = screen_h; + dst->dst_w = screen_w; + /* + right_edge = screen_w - src->tgt_offset_x - dst->width; + bottom_edge = screen_h - src->tgt_offset_y - dst->height; + + if (right_edge >= 0 && bottom_edge >= 0) { + dst->bg_ctrl.left = src->tgt_offset_x; + dst->bg_ctrl.right = right_edge; + dst->bg_ctrl.top = src->tgt_offset_y; + dst->bg_ctrl.bottom = bottom_edge; + } else + EXT_DISP_ERR("%s right edge:%d, bottom edge:%d\n", __func__, right_edge, bottom_edge); + */ + return 0; +} + +static int _convert_disp_input_to_ovl(OVL_CONFIG_STRUCT *dst, disp_input_config *src) +{ + int force_disable_alpha = 0; + enum UNIFIED_COLOR_FMT tmp_fmt; + unsigned int Bpp = 0; + + if (!src || !dst) { + EXT_DISP_ERR("%s src(0x%p) or dst(0x%p) is null\n", __func__, src, dst); + return -1; + } + + dst->layer = src->layer_id; + dst->isDirty = 1; + dst->buff_idx = src->next_buff_idx; + dst->layer_en = src->layer_enable; + + /* if layer is disable, we just needs config above params. */ + if (!src->layer_enable) + return 0; + + tmp_fmt = disp_fmt_to_unified_fmt(src->src_fmt); + /* display don't support X channel, like XRGB8888 + * we need to enable const_bld*/ + ufmt_disable_X_channel(tmp_fmt, &dst->fmt, &dst->const_bld); +#if 0 + if (tmp_fmt != dst->fmt) + force_disable_alpha = 1; +#endif + Bpp = UFMT_GET_Bpp(dst->fmt); + + dst->addr = (unsigned long)src->src_phy_addr; + dst->vaddr = (unsigned long)src->src_base_addr; + dst->src_x = src->src_offset_x; + dst->src_y = src->src_offset_y; + dst->src_w = src->src_width; + dst->src_h = src->src_height; + dst->src_pitch = src->src_pitch * Bpp; + dst->dst_x = src->tgt_offset_x; + dst->dst_y = src->tgt_offset_y; + + /* dst W/H should <= src W/H */ + dst->dst_w = min(src->src_width, src->tgt_width); + dst->dst_h = min(src->src_height, src->tgt_height); + + dst->keyEn = src->src_use_color_key; + dst->key = src->src_color_key; + + dst->aen = force_disable_alpha ? 0 : src->alpha_enable; + dst->sur_aen = force_disable_alpha ? 0 : src->sur_aen; + + dst->alpha = src->alpha; + dst->src_alpha = src->src_alpha; + dst->dst_alpha = src->dst_alpha; + + dst->identity = src->identity; + dst->connected_type = src->connected_type; + dst->security = src->security; + dst->yuv_range = src->yuv_range; + + if (src->buffer_source == DISP_BUFFER_ALPHA) + dst->source = OVL_LAYER_SOURCE_RESERVED; /* dim layer, constant alpha */ + else if (src->buffer_source == DISP_BUFFER_ION || src->buffer_source == DISP_BUFFER_MVA) + dst->source = OVL_LAYER_SOURCE_MEM; /* from memory */ + else { + EXT_DISP_ERR("unknown source = %d", src->buffer_source); + dst->source = OVL_LAYER_SOURCE_MEM; + } + + return 0; +} + +static int _ext_disp_trigger(int blocking, void *callback, unsigned int userdata) +{ + bool reg_flush = false; + +/* EXT_DISP_FUNC();*/ + + if (_should_wait_path_idle()) + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 2); + + if (_should_start_path()) { + reg_flush = true; + dpmgr_path_start(pgc->dpmgr_handle, ext_disp_cmdq_enabled()); + MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Trigger, 1); + } + + if (_should_trigger_path()) { + /* trigger_loop_handle is used only for build trigger loop*/ + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, ext_disp_cmdq_enabled()); + } + + if (_should_set_cmdq_dirty()) + _cmdq_set_config_handle_dirty(); + + if (_should_flush_cmdq_config_handle()) { + if (reg_flush) + MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Trigger, 2); + + _cmdq_flush_config_handle(blocking, callback, userdata); + } + + if (_should_reset_cmdq_config_handle()) + _cmdq_reset_config_handle(); + + if (_should_insert_wait_frame_done_token()) + _cmdq_insert_wait_frame_done_token(0); + + return 0; +} + +static int _ext_disp_trigger_EPD(int blocking, void *callback, unsigned int userdata) +{ + /* /EXT_DISP_FUNC(); */ + + if (_should_wait_path_idle()) + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 2); + + if (_should_start_path()) { + dpmgr_path_start(pgc->dpmgr_handle, ext_disp_cmdq_enabled()); + MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Trigger, 1); + } + + if (_should_trigger_path()) { + /* trigger_loop_handle is used only for build trigger loop*/ + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, ext_disp_cmdq_enabled()); + } + + if (_should_set_cmdq_dirty()) + _cmdq_set_config_handle_dirty(); + + if (_should_flush_cmdq_config_handle()) + _cmdq_flush_config_handle(blocking, callback, userdata); + + if (_should_reset_cmdq_config_handle()) + _cmdq_reset_config_handle(); + + if (_should_insert_wait_frame_done_token()) { + /* 1 for clear event, cmdqRecWait */ + _cmdq_insert_wait_frame_done_token(1); + } + + return 0; +} + +/* <-- Donglei for K2 compile +//need remove +static unsigned int cmdqDdpClockOn(uint64_t engineFlag) +{ + return 0; +} + +static unsigned int cmdqDdpClockOff(uint64_t engineFlag) +{ + return 0; +} + +static unsigned int cmdqDdpDumpInfo(uint64_t engineFlag, + char *pOutBuf, + unsigned int bufSize) +{ + ext_disp_diagnose(); + return 0; +} + +static unsigned int cmdqDdpResetEng(uint64_t engineFlag) +{ + return 0; +} +*/ + +void ext_disp_probe(void) +{ + EXT_DISP_FUNC(); + + ext_disp_use_cmdq = CMDQ_ENABLE; + ext_disp_use_m4u = 1; + ext_disp_mode = EXTD_DIRECT_LINK_MODE; +} + +int ext_disp_init(char *lcm_name, unsigned int session) +{ + disp_ddp_path_config *data_config; + enum EXT_DISP_STATUS ret; + + EXT_DISP_FUNC(); + ret = EXT_DISP_STATUS_OK; + + dpmgr_init(); + + extd_mutex_init(&(pgc->lock)); + _ext_disp_path_lock(); + +#if 0 + ret = cmdqCoreRegisterCB(CMDQ_GROUP_DISP, cmdqDdpClockOn, cmdqDdpDumpInfo, cmdqDdpResetEng, cmdqDdpClockOff); + if (ret) { + EXT_DISP_ERR("cmdqCoreRegisterCB failed, ret=%d\n", ret); + ret = EXT_DISP_STATUS_ERROR; + goto done; + } +#endif + ret = cmdqRecCreate(CMDQ_SCENARIO_MHL_DISP, &(pgc->cmdq_handle_config)); + if (ret) { + EXT_DISP_LOG("cmdqRecCreate FAIL, ret=%d\n", ret); + ret = EXT_DISP_STATUS_ERROR; + goto done; + } else + EXT_DISP_LOG("cmdqRecCreate SUCCESS, g_cmdq_handle=%p\n", pgc->cmdq_handle_config); + + if (ext_disp_mode == EXTD_DIRECT_LINK_MODE) + _build_path_direct_link(); + else if (ext_disp_mode == EXTD_DECOUPLE_MODE) + _build_path_decouple(); + else if (ext_disp_mode == EXTD_SINGLE_LAYER_MODE) + _build_path_single_layer(); + else if (ext_disp_mode == EXTD_RDMA_DPI_MODE) + _build_path_rdma_dpi(); + else + EXT_DISP_LOG("ext_disp display mode is WRONG\n"); + + if (ext_disp_use_cmdq == CMDQ_ENABLE) { + if (DISP_SESSION_DEV(session) != DEV_EINK + 1) { + _cmdq_build_trigger_loop(); + EXT_DISP_LOG("ext_disp display BUILD cmdq trigger loop finished\n"); + + _cmdq_start_trigger_loop(); + } + } + pgc->session = session; + + EXT_DISP_LOG("ext_disp display START cmdq trigger loop finished\n"); + + dpmgr_path_set_video_mode(pgc->dpmgr_handle, ext_disp_is_video_mode()); + dpmgr_path_init(pgc->dpmgr_handle, CMDQ_DISABLE); + + data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle); + if (data_config) { + memset((void *)data_config, 0, sizeof(disp_ddp_path_config)); + memcpy(&(data_config->dispif_config), &extd_lcm_params, sizeof(LCM_PARAMS)); + + data_config->dst_w = extd_lcm_params.dpi.width; + data_config->dst_h = extd_lcm_params.dpi.height; + data_config->dst_dirty = 1; + data_config->p_golden_setting_context = get_golden_setting_pgc(); + data_config->p_golden_setting_context->ext_dst_width = data_config->dst_w; + data_config->p_golden_setting_context->ext_dst_height = data_config->dst_h; + + init_roi = 0; + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, CMDQ_DISABLE); + EXT_DISP_LOG("ext_disp_init roi w:%d, h:%d\n", data_config->dst_w, data_config->dst_h); + } else + EXT_DISP_LOG("allocate buffer failed!!!\n"); + + /* this will be set to always enable cmdq later */ + if (ext_disp_is_video_mode()) + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_DPI_VSYNC); + + if (ext_disp_use_cmdq == CMDQ_ENABLE) + _cmdq_reset_config_handle(); + + mutex_init(&(pgc->vsync_lock)); + pgc->state = EXTD_INIT; + pgc->ovl_req_state = EXTD_OVL_NO_REQ; + done: + + _ext_disp_path_unlock(); + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + + EXT_DISP_LOG("ext_disp_init done\n"); + return ret; +} + + +int ext_disp_deinit(unsigned int session) +{ + EXT_DISP_FUNC(); + + _ext_disp_path_lock(); + + if (pgc->state == EXTD_DEINIT) + goto deinit_exit; + + if (pgc->state == EXTD_SUSPEND) + dpmgr_path_power_on(pgc->dpmgr_handle, CMDQ_DISABLE); + + dpmgr_path_deinit(pgc->dpmgr_handle, CMDQ_DISABLE); + dpmgr_destroy_path(pgc->dpmgr_handle, NULL); + + cmdqRecDestroy(pgc->cmdq_handle_config); + cmdqRecDestroy(pgc->cmdq_handle_trigger); + + pgc->state = EXTD_DEINIT; + + deinit_exit: + _ext_disp_path_unlock(); + is_context_inited = 0; + EXT_DISP_LOG("ext_disp_deinit done\n"); + return 0; +} + +int ext_disp_wait_for_vsync(void *config, unsigned int session) +{ + int ret = 0; + disp_session_vsync_config *c = (disp_session_vsync_config *) config; + +/* EXT_DISP_FUNC();*/ + + _ext_disp_path_lock(); + if (pgc->state == EXTD_DEINIT) { + _ext_disp_path_unlock(); + msleep(20); + return -1; + } + _ext_disp_path_unlock(); + + _ext_disp_vsync_lock(session); + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, 50); + + if (ret == -2) { + EXT_DISP_LOG("vsync for ext display path not enabled yet\n"); + _ext_disp_vsync_unlock(session); + return -1; + } + /*EXT_DISP_LOG("ext_disp_wait_for_vsync - vsync signaled\n");*/ + c->vsync_ts = get_current_time_us(); + c->vsync_cnt++; + + _ext_disp_vsync_unlock(session); + return ret; +} + +int ext_disp_suspend(unsigned int session) +{ + enum EXT_DISP_STATUS ret = EXT_DISP_STATUS_OK; + + EXT_DISP_FUNC(); + + _ext_disp_path_lock(); + + if (pgc->state == EXTD_DEINIT || pgc->state == EXTD_SUSPEND || session != pgc->session) { + EXT_DISP_ERR("status is not EXTD_RESUME or session is not match\n"); + goto done; + } + + pgc->need_trigger_overlay = 0; + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 30); + + if (ext_disp_use_cmdq == CMDQ_ENABLE && DISP_SESSION_DEV(session) != DEV_EINK + 1) + _cmdq_stop_trigger_loop(); + + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + dpmgr_path_power_off(pgc->dpmgr_handle, CMDQ_DISABLE); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 30); + + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + + pgc->state = EXTD_SUSPEND; + + done: + _ext_disp_path_unlock(); + + EXT_DISP_LOG("ext_disp_suspend done\n"); + return ret; +} + +int ext_disp_resume(unsigned int session) +{ + enum EXT_DISP_STATUS ret = EXT_DISP_STATUS_OK; + + EXT_DISP_FUNC(); + + _ext_disp_path_lock(); + + if (pgc->state != EXTD_SUSPEND) { + EXT_DISP_ERR("EXTD_DEINIT/EXTD_INIT/EXTD_RESUME\n"); + goto done; + } + + if (_should_reset_cmdq_config_handle() && DISP_SESSION_DEV(session) != DEV_EINK + 1) + _cmdq_reset_config_handle(); + + dpmgr_path_power_on(pgc->dpmgr_handle, CMDQ_DISABLE); + + if (ext_disp_use_cmdq == CMDQ_ENABLE && DISP_SESSION_DEV(session) != DEV_EINK + 1) + _cmdq_start_trigger_loop(); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + EXT_DISP_LOG("stop display path failed, still busy\n"); + ret = -1; + goto done; + } + + if (DISP_SESSION_DEV(session) == DEV_EINK + 1) + pgc->suspend_config = 0; + + pgc->state = EXTD_RESUME; + + done: + _ext_disp_path_unlock(); + EXT_DISP_LOG("ext_disp_resume done\n"); + MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Resume, 1); + return ret; +} + +int ext_disp_trigger(int blocking, void *callback, unsigned int userdata, unsigned int session) +{ + int ret = 0; + +/* EXT_DISP_FUNC(); */ + + if (pgc->state == EXTD_DEINIT || pgc->state == EXTD_SUSPEND || pgc->need_trigger_overlay < 1) { + EXT_DISP_LOG("trigger ext display is already slept\n"); + MMProfileLogEx(ddp_mmp_get_events()->Extd_ErrorInfo, MMProfileFlagPulse, Trigger, 0); + return -1; + } + + _ext_disp_path_lock(); + + if (_should_trigger_interface()) { + if (DISP_SESSION_TYPE(session) == DISP_SESSION_EXTERNAL && DISP_SESSION_DEV(session) == DEV_MHL + 1) + _ext_disp_trigger(blocking, callback, userdata); + else if (DISP_SESSION_TYPE(session) == DISP_SESSION_EXTERNAL + && DISP_SESSION_DEV(session) == DEV_EINK + 1) + _ext_disp_trigger_EPD(blocking, callback, userdata); + } else + dpmgr_path_trigger(pgc->ovl2mem_path_handle, NULL, ext_disp_use_cmdq); + + pgc->state = EXTD_RESUME; + _ext_disp_path_unlock(); + /*EXT_DISP_LOG("ext_disp_trigger done\n");*/ + + return ret; +} + +int ext_disp_suspend_trigger(void *callback, unsigned int userdata, unsigned int session) +{ + enum EXT_DISP_STATUS ret = EXT_DISP_STATUS_OK; + + EXT_DISP_FUNC(); + + if (pgc->state != EXTD_RESUME) { + EXT_DISP_LOG("trigger ext display is already slept\n"); + MMProfileLogEx(ddp_mmp_get_events()->Extd_ErrorInfo, MMProfileFlagPulse, Trigger, 0); + return -1; + } + + MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Suspend, 0); + + _ext_disp_path_lock(); + + if (_should_reset_cmdq_config_handle()) + _cmdq_reset_config_handle(); + + if (_should_insert_wait_frame_done_token()) + _cmdq_insert_wait_frame_done_token(0); + + pgc->need_trigger_overlay = 0; + + if (ext_disp_use_cmdq == CMDQ_ENABLE && DISP_SESSION_DEV(session) != DEV_EINK + 1) + _cmdq_stop_trigger_loop(); + + dpmgr_path_stop(pgc->dpmgr_handle, ext_disp_cmdq_enabled()); + + if (_should_flush_cmdq_config_handle()) { + _cmdq_flush_config_handle(1, 0, 0); + _cmdq_reset_config_handle(); + } + + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + dpmgr_path_power_off(pgc->dpmgr_handle, CMDQ_DISABLE); + + if (DISP_SESSION_DEV(session) == DEV_EINK + 1) + pgc->suspend_config = 1; + + pgc->state = EXTD_SUSPEND; + + _ext_disp_path_unlock(); + + MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Suspend, 1); + return ret; +} + +/* +static int extl_disp_dynamic_debug(unsigned int mva, unsigned int pitch, unsigned int w, unsigned int h, + unsigned int pixels, unsigned int lines) +{ + unsigned int real_mva, real_size, map_size; + unsigned long map_va; + int ret; + + ret = m4u_query_mva_info(mva, 0, &real_mva, &real_size); + if (ret) { + pr_err("%s error to query mva = 0x%x\n", __func__, mva); + return -1; + } + ret = m4u_mva_map_kernel(real_mva, real_size, &map_va, &map_size); + if (ret) { + pr_err("%s error to map mva = 0x%x\n", __func__, real_mva); + return -1; + } + pr_err("Donglei - %s mva0x%x, real_mva:0x%x\n", __func__, mva, real_mva); + unsigned char *buf_va = map_va + (mva - real_mva); + int x, y; + + for (y = 0; y < lines; y++) { + for (x = 0; x < pixels; x++) { + buf_va[3*x + y * pitch] = 255; + buf_va[3*x + 1 + y * pitch] = 0; + buf_va[3*x + 2 + y * pitch] = 0; + buf_va[w - 3*x - 1 + y * pitch] = 255; + buf_va[w - 3*x - 1 - 1 + y * pitch] = 255; + buf_va[w - 3*x - 2 - 1 + y * pitch] = 255; + } + } + + m4u_mva_unmap_kernel(real_mva, real_size, map_va); + + return 0; +} +*/ +int ext_disp_config_input_multiple(disp_session_input_config *input, int idx, unsigned int session) +{ + int ret = 0; + int i = 0; + int layer_cnt = 0; + int config_layer_id = 0; + M4U_PORT_STRUCT sPort; + + /* /EXT_DISP_FUNC(); */ + + disp_ddp_path_config *data_config; + + if (pgc->state != EXTD_INIT && pgc->state != EXTD_RESUME && pgc->suspend_config != 1) { + EXT_DISP_LOG("config ext disp is already slept, state:%d\n", pgc->state); + MMProfileLogEx(ddp_mmp_get_events()->Extd_ErrorInfo, MMProfileFlagPulse, Config, idx); + return -2; + } + + for (i = 0; i < input->config_layer_num; i++) { + if (input->config[i].layer_enable) + layer_cnt++; + } + + if (layer_cnt == 1) { + ext_disp_path_change(EXTD_OVL_REMOVE_REQ, session); + if (ext_disp_get_ovl_req_status(session) == EXTD_OVL_REMOVE_REQ) { + EXT_DISP_LOG("config M4U Port DISP_MODULE_RDMA1\n"); + sPort.ePortID = M4U_PORT_DISP_RDMA1; + sPort.Virtuality = 1; + sPort.Security = 0; + sPort.Distance = 1; + sPort.Direction = 0; + ret = m4u_config_port(&sPort); + if (ret != 0) + EXT_DISP_LOG("config M4U Port DISP_MODULE_RDMA1 FAIL\n"); + + pgc->ovl_req_state = EXTD_OVL_REMOVING; + } + } else if (layer_cnt > 1) { + ext_disp_path_change(EXTD_OVL_INSERT_REQ, session); + if (ext_disp_get_ovl_req_status(session) == EXTD_OVL_INSERT_REQ) { + EXT_DISP_LOG("config M4U Port M4U_PORT_DISP_OVL1\n"); + sPort.ePortID = M4U_PORT_DISP_OVL1; + sPort.Virtuality = 1; + sPort.Security = 0; + sPort.Distance = 1; + sPort.Direction = 0; + ret = m4u_config_port(&sPort); + if (ret != 0) + EXT_DISP_LOG("config M4U Port DISP_MODULE_OVL1 FAIL\n"); + } + } + + _ext_disp_path_lock(); + + /* all dirty should be cleared in dpmgr_path_get_last_config() */ + data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle); + + /* hope we can use only 1 input struct for input config, just set layer number */ + if (_should_config_ovl_input()) { + for (i = 0; i < input->config_layer_num; i++) { + config_layer_id = input->config[i].layer_id; + ret = _convert_disp_input_to_ovl(&(data_config->ovl_config[config_layer_id]), + &(input->config[i])); + dprec_mmp_dump_ovl_layer(&(data_config->ovl_config[config_layer_id]), config_layer_id, 2); + + if (init_roi == 1) { + memcpy(&(data_config->dispif_config), &extd_lcm_params, sizeof(LCM_PARAMS)); + + EXT_DISP_LOG("set dest w:%d, h:%d\n", + extd_lcm_params.dpi.width, extd_lcm_params.dpi.height); + data_config->dst_w = extd_lcm_params.dpi.width; + data_config->dst_h = extd_lcm_params.dpi.height; + data_config->dst_dirty = 1; + data_config->rdma_config.address = 0; + } + data_config->ovl_dirty = 1; + pgc->need_trigger_overlay = 1; + } + } else { + OVL_CONFIG_STRUCT ovl_config; + _convert_disp_input_to_ovl(&ovl_config, &(input->config[0])); + dprec_mmp_dump_ovl_layer(&ovl_config, input->config[0].layer_id, 2); + + ret = _convert_disp_input_to_rdma(&(data_config->rdma_config), &(input->config[0]), + extd_lcm_params.dpi.width, extd_lcm_params.dpi.height); + if (data_config->rdma_config.address) { + data_config->rdma_dirty = 1; + pgc->need_trigger_overlay = 1; + } + } + + if (_should_wait_path_idle()) + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 2); + + memcpy(&(data_config->dispif_config), &extd_lcm_params, sizeof(LCM_PARAMS)); + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, + ext_disp_cmdq_enabled() ? pgc->cmdq_handle_config : NULL); + + /* this is used for decouple mode, to indicate whether we need to trigger ovl */ + /* pgc->need_trigger_overlay = 1; */ + init_roi = 0; + + _ext_disp_path_unlock(); + if (data_config->ovl_dirty) { + EXT_DISP_LOG("config_input_multiple idx:%d -w:%d, h:%d, pitch:%d\n", + idx, data_config->ovl_config[0].src_w, data_config->ovl_config[0].src_h, + data_config->ovl_config[0].src_pitch); + } else { + EXT_DISP_LOG("config_input_multiple idx:%d -w:%d, h:%d, pitch:%d, mva:0x%lx\n", + idx, data_config->rdma_config.width, data_config->rdma_config.height, + data_config->rdma_config.pitch, data_config->rdma_config.address); + } + + return ret; +} + +int ext_disp_is_alive(void) +{ + unsigned int temp = 0; + + EXT_DISP_FUNC(); + _ext_disp_path_lock(); + temp = pgc->state; + _ext_disp_path_unlock(); + + return temp; +} + +int ext_disp_is_sleepd(void) +{ + unsigned int temp = 0; + /* EXT_DISP_FUNC(); */ + _ext_disp_path_lock(); + temp = !pgc->state; + _ext_disp_path_unlock(); + + return temp; +} + +int ext_disp_get_width(void) +{ + return 0; +} + +int ext_disp_get_height(void) +{ + return 0; +} + +unsigned int ext_disp_get_sess_id(void) +{ + unsigned int session_id = is_context_inited > 0 ? pgc->session : 0; + return session_id; +} + +int ext_disp_is_video_mode(void) +{ + /* TODO: we should store the video/cmd mode in runtime, because ROME will support cmd/vdo dynamic switch */ + return true; +} + +int ext_disp_diagnose(void) +{ + int ret = 0; + + if (is_context_inited > 0) { + EXT_DISP_LOG("ext_disp_diagnose, is_context_inited --%d\n", is_context_inited); + dpmgr_check_status(pgc->dpmgr_handle); + } + + return ret; +} + +CMDQ_SWITCH ext_disp_cmdq_enabled(void) +{ + return ext_disp_use_cmdq; +} + +int ext_disp_switch_cmdq(CMDQ_SWITCH use_cmdq) +{ + _ext_disp_path_lock(); + + ext_disp_use_cmdq = use_cmdq; + EXT_DISP_LOG("display driver use %s to config register now\n", (use_cmdq == CMDQ_ENABLE) ? "CMDQ" : "CPU"); + + _ext_disp_path_unlock(); + return ext_disp_use_cmdq; +} + +void ext_disp_get_curr_addr(unsigned long *input_curr_addr, int module) +{ + if (module == 1) + ovl_get_address(DISP_MODULE_OVL1, input_curr_addr); + else + dpmgr_get_input_address(pgc->dpmgr_handle, input_curr_addr); +} + +int ext_disp_factory_test(int mode, void *config) +{ + dpmgr_factory_mode_test(DISP_MODULE_DPI, NULL, config); + + return 0; +} + +int ext_disp_get_handle(disp_path_handle *dp_handle, cmdqRecHandle *pHandle) +{ + *dp_handle = pgc->dpmgr_handle; + *pHandle = pgc->cmdq_handle_config; + return pgc->mode; +} + +int ext_disp_set_ovl1_status(int status) +{ +/* dpmgr_set_ovl1_status(status);*/ + return 0; +} + +int ext_disp_set_lcm_param(LCM_PARAMS *pLCMParam) +{ + if (pLCMParam) + memcpy(&extd_lcm_params, pLCMParam, sizeof(LCM_PARAMS)); + + return 0; +} + +enum EXTD_OVL_REQ_STATUS ext_disp_get_ovl_req_status(unsigned int session) +{ + enum EXTD_OVL_REQ_STATUS ret = EXTD_OVL_NO_REQ; + + _ext_disp_path_lock(); + ret = pgc->ovl_req_state; + _ext_disp_path_unlock(); + + return ret; +} + +int ext_disp_path_change(enum EXTD_OVL_REQ_STATUS action, unsigned int session) +{ +/* EXT_DISP_FUNC();*/ + + if (EXTD_OVERLAY_CNT > 0) { + _ext_disp_path_lock(); + switch (action) { + case EXTD_OVL_NO_REQ: +/* if (pgc->ovl_req_state == EXTD_OVL_REMOVED) {*/ + /* 0 - DDP_OVL1_STATUS_IDLE */ +/* dpmgr_set_ovl1_status(0); + }*/ + pgc->ovl_req_state = EXTD_OVL_NO_REQ; + break; + case EXTD_OVL_REQUSTING_REQ: +/* if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) {*/ + /* 1 - DDP_OVL1_STATUS_SUB_REQUESTING */ +/* dpmgr_set_ovl1_status(DDP_OVL1_STATUS_SUB_REQUESTING); + } +*/ break; + case EXTD_OVL_IDLE_REQ: +/* if (ovl_get_status() == DDP_OVL1_STATUS_SUB) {*/ + /* 1 - DDP_OVL1_STATUS_SUB_REQUESTING */ +/* dpmgr_set_ovl1_status(DDP_OVL1_STATUS_IDLE); + } +*/ break; + case EXTD_OVL_SUB_REQ: +/* pgc->ovl_req_state = EXTD_OVL_SUB_REQ;*/ + break; + case EXTD_OVL_REMOVE_REQ: + if (ext_disp_mode != EXTD_RDMA_DPI_MODE) { + dpmgr_remove_ovl1_sub(pgc->dpmgr_handle, pgc->cmdq_handle_config); + ext_disp_path_set_mode(EXTD_RDMA_DPI_MODE, session); + pgc->ovl_req_state = EXTD_OVL_REMOVE_REQ; + } + break; + case EXTD_OVL_REMOVING: + pgc->ovl_req_state = EXTD_OVL_REMOVING; + break; + case EXTD_OVL_REMOVED: + pgc->ovl_req_state = EXTD_OVL_REMOVED; + break; + case EXTD_OVL_INSERT_REQ: + if (ext_disp_mode != EXTD_DIRECT_LINK_MODE) { + dpmgr_insert_ovl1_sub(pgc->dpmgr_handle, pgc->cmdq_handle_config); + ext_disp_path_set_mode(EXTD_DIRECT_LINK_MODE, session); + pgc->ovl_req_state = EXTD_OVL_INSERT_REQ; + } + break; + case EXTD_OVL_INSERTED: + pgc->ovl_req_state = EXTD_OVL_INSERTED; + break; + default: + break; + } + + _ext_disp_path_unlock(); + } + + return 0; +} + +int ext_disp_wait_ovl_available(int ovl_num) +{ + int ret = 0; + + if (EXTD_OVERLAY_CNT > 0) { + /*wait OVL can be used by external display */ + ret = dpmgr_wait_ovl_available(ovl_num); + } + + return ret; +} + +bool ext_disp_path_source_is_RDMA(unsigned int session) +{ + bool is_rdma = false; + if ((ext_disp_mode == EXTD_RDMA_DPI_MODE && pgc->ovl_req_state != EXTD_OVL_REMOVE_REQ + && pgc->ovl_req_state != EXTD_OVL_REMOVING) + || (ext_disp_mode == EXTD_DIRECT_LINK_MODE && pgc->ovl_req_state == EXTD_OVL_INSERT_REQ)) { + /* path source module is RDMA */ + is_rdma = true; + } + + return is_rdma; +} + +int ext_disp_is_dim_layer(unsigned long mva) +{ + int ret = 0; + + ret = is_dim_layer(mva); + + return ret; +} diff --git a/drivers/misc/mediatek/ext_disp/mt6755/external_display.h b/drivers/misc/mediatek/ext_disp/mt6755/external_display.h new file mode 100644 index 0000000000000000000000000000000000000000..e0ff9aeb571e64ee68e961429fe3109be66d5097 --- /dev/null +++ b/drivers/misc/mediatek/ext_disp/mt6755/external_display.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _EXTD_DDP_H_ +#define _EXTD_DDP_H_ + +#include "ddp_hal.h" +#include "ddp_manager.h" + +#define ALIGN_TO(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) + + +enum EXT_DISP_PATH_MODE { + EXTD_DIRECT_LINK_MODE, + EXTD_DECOUPLE_MODE, + EXTD_SINGLE_LAYER_MODE, + EXTD_RDMA_DPI_MODE +}; + +enum EXT_DISP_STATUS { + EXT_DISP_STATUS_OK = 0, + + EXT_DISP_STATUS_NOT_IMPLEMENTED, + EXT_DISP_STATUS_ALREADY_SET, + EXT_DISP_STATUS_ERROR +}; + +enum EXTD_POWER_STATE { + EXTD_DEINIT = 0, + EXTD_INIT, + EXTD_RESUME, + EXTD_SUSPEND +}; + +enum EXTD_OVL_REQ_STATUS { + EXTD_OVL_NO_REQ = 0, + EXTD_OVL_REQUSTING_REQ, + EXTD_OVL_IDLE_REQ, + EXTD_OVL_SUB_REQ, + EXTD_OVL_REMOVE_REQ, + EXTD_OVL_REMOVING, + EXTD_OVL_REMOVED, + EXTD_OVL_INSERT_REQ, + EXTD_OVL_INSERTED +}; + +struct ext_disp_input_config { + unsigned int layer; + unsigned int layer_en; + unsigned int buff_source; + unsigned int fmt; + unsigned long addr; + unsigned long addr_sub_u; + unsigned long addr_sub_v; + unsigned long vaddr; + unsigned int src_x; + unsigned int src_y; + unsigned int src_w; + unsigned int src_h; + unsigned int src_pitch; + unsigned int dst_x; + unsigned int dst_y; + unsigned int dst_w; + unsigned int dst_h; /* clip region */ + unsigned int keyEn; + unsigned int key; + unsigned int aen; + unsigned char alpha; + + unsigned int sur_aen; + unsigned int src_alpha; + unsigned int dst_alpha; + + unsigned int isTdshp; + unsigned int isDirty; + + unsigned int buff_idx; + unsigned int identity; + unsigned int connected_type; + unsigned int security; + unsigned int dirty; +}; + +void ext_disp_probe(void); +int ext_disp_init(char *lcm_name, unsigned int session); +int ext_disp_deinit(unsigned int session); +int ext_disp_suspend(unsigned int session); +int ext_disp_suspend_trigger(void *callback, unsigned int userdata, unsigned int session); +int ext_disp_resume(unsigned int session); +enum EXT_DISP_PATH_MODE ext_disp_path_get_mode(unsigned int session); +void ext_disp_path_set_mode(enum EXT_DISP_PATH_MODE mode, unsigned int session); + +unsigned int ext_disp_get_sess_id(void); + +int ext_disp_get_width(void); +int ext_disp_get_height(void); + +int ext_disp_is_alive(void); +int ext_disp_is_sleepd(void); +int ext_disp_wait_for_vsync(void *config, unsigned int session); +int ext_disp_config_input_multiple(disp_session_input_config *input, int idx, unsigned int session); +int ext_disp_trigger(int blocking, void *callback, unsigned int userdata, unsigned int session); + +int ext_disp_is_video_mode(void); +CMDQ_SWITCH ext_disp_cmdq_enabled(void); +int ext_disp_switch_cmdq(CMDQ_SWITCH use_cmdq); +int ext_disp_diagnose(void); +void ext_disp_get_curr_addr(unsigned long *input_curr_addr, int module); +int ext_disp_factory_test(int mode, void *config); +int ext_disp_get_handle(disp_path_handle *dp_handle, cmdqRecHandle *pHandle); +int ext_disp_set_ovl1_status(int status); +int ext_disp_set_lcm_param(LCM_PARAMS *pLCMParam); +enum EXTD_OVL_REQ_STATUS ext_disp_get_ovl_req_status(unsigned int session); +int ext_disp_path_change(enum EXTD_OVL_REQ_STATUS action, unsigned int session); +int ext_disp_wait_ovl_available(int ovl_num); +bool ext_disp_path_source_is_RDMA(unsigned int session); +int ext_disp_is_dim_layer(unsigned long mva); + +extern int is_dim_layer(unsigned long mva); +#endif diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/Makefile b/drivers/misc/mediatek/flashlight/src/mt6755/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..4fedfa3719fd25c38bc9c3e6778cf5890114967d --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +# +# Makefile for misc devices that really don't fit anywhere else. +# + +obj-y += kd_flashlightlist.o +obj-y += strobe_main_sid2_part2.o +obj-y += strobe_sub_sid2_part1.o +obj-y += strobe_sub_sid2_part2.o +ifneq ($(wildcard $(srctree)/drivers/misc/mediatek/flashlight/src/$(MTK_PLATFORM)/$(ARCH_MTK_PROJECT)/sub_flashlight),) +obj-y += $(ARCH_MTK_PROJECT)/sub_flashlight/sub_strobe.o +else +obj-y += sub_strobe.o +endif +obj-y += strobe_main_sid1_part2.o +obj-y += strobe_part_id.o +obj-y += strobe_sub_sid1_part2.o + +ifeq ($(wildcard $(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/$(ARCH_MTK_PROJECT)/flashlight/strobe_main_sid2_part1.c),) +obj-y += strobe_main_sid2_part1.o +endif + + +#ifeq ($(wildcard $(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/$(ARCH_MTK_PROJECT)/flashlight),) +#ifeq ($(wildcard $(srctree)/arch/arm/mach-$(MTK_PLATFORM)/$(ARCH_MTK_PROJECT)/flashlight),) + +custom_kernel_flashlight := $(addsuffix /, $(shell echo $(CONFIG_CUSTOM_KERNEL_FLASHLIGHT))) + +ifneq ($(wildcard $(srctree)/drivers/misc/mediatek/flashlight/src/$(MTK_PLATFORM)/$(ARCH_MTK_PROJECT)/constant_flashlight),) +obj-y += $(ARCH_MTK_PROJECT)/$(custom_kernel_flashlight) +else +obj-y += $(custom_kernel_flashlight) +endif + + diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/constant_flashlight/Makefile b/drivers/misc/mediatek/flashlight/src/mt6755/constant_flashlight/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e6fb4d8bd456690b179dd6a7c647307962303b33 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/constant_flashlight/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +# +# Makefile for misc devices that really don't fit anywhere else. +# + +obj-y += leds_strobe.o diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/constant_flashlight/leds_strobe.c b/drivers/misc/mediatek/flashlight/src/mt6755/constant_flashlight/leds_strobe.c new file mode 100644 index 0000000000000000000000000000000000000000..5c2531ccbd1fbe0ee67ea6ab8893d5b934a55f33 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/constant_flashlight/leds_strobe.c @@ -0,0 +1,534 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef CONFIG_COMPAT + +#include +#include + +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_flashlight.h" +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +#include +#include +#include + + + +/* +// flash current vs index + 0 1 2 3 4 5 6 7 8 9 10 +93.74 140.63 187.5 281.25 375 468.75 562.5 656.25 750 843.75 937.5 + 11 12 13 14 15 16 +1031.25 1125 1218.75 1312.5 1406.25 1500mA +*/ +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ + +#define TAG_NAME "[leds_strobe.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) + + +/*#define DEBUG_LEDS_STROBE*/ +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#else +#define PK_DBG(a, ...) +#endif + +/****************************************************************************** + * local variables +******************************************************************************/ + +static DEFINE_SPINLOCK(g_strobeSMPLock); /* cotta-- SMP proection */ + + +static u32 strobe_Res; +static u32 strobe_Timeus; +static BOOL g_strobe_On; + +static int gDuty = -1; +static int g_timeOutTimeMs; + +static DEFINE_MUTEX(g_strobeSem); + + + + + +static struct work_struct workTimeOut; + +/* #define FLASH_GPIO_ENF GPIO12 */ +/* #define FLASH_GPIO_ENT GPIO13 */ + + + + +static int gIsTorch[18] = { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static int gLedDuty[18] = { 0, 32, 64, 96, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + +/* current(mA) 50,94,141,188,281,375,469,563,656,750,844,938,1031,1125,1220,1313,1406,1500 */ + + + +/***************************************************************************** +Functions +*****************************************************************************/ +static void work_timeOutFunc(struct work_struct *data); + +static struct i2c_client *RT4505_i2c_client; + + + + +struct RT4505_platform_data { + u8 torch_pin_enable; /* 1: TX1/TORCH pin isa hardware TORCH enable */ + u8 pam_sync_pin_enable; /* 1: TX2 Mode The ENVM/TX2 is a PAM Sync. on input */ + u8 thermal_comp_mode_enable; /* 1: LEDI/NTC pin in Thermal Comparator Mode */ + u8 strobe_pin_disable; /* 1 : STROBE Input disabled */ + u8 vout_mode_enable; /* 1 : Voltage Out Mode enable */ +}; + +struct RT4505_chip_data { + struct i2c_client *client; + + /* struct led_classdev cdev_flash; */ + /* struct led_classdev cdev_torch; */ + /* struct led_classdev cdev_indicator; */ + + struct RT4505_platform_data *pdata; + struct mutex lock; + + u8 last_flag; + u8 no_pdata; +}; + +static int RT4505_write_reg(struct i2c_client *client, u8 reg, u8 val) +{ + int ret = 0; + struct RT4505_chip_data *chip = i2c_get_clientdata(client); + + mutex_lock(&chip->lock); + ret = i2c_smbus_write_byte_data(client, reg, val); + mutex_unlock(&chip->lock); + + if (ret < 0) + PK_DBG("failed writing at 0x%02x\n", reg); + return ret; +} + +static int RT4505_read_reg(struct i2c_client *client, u8 reg) +{ + int val = 0; + struct RT4505_chip_data *chip = i2c_get_clientdata(client); + + mutex_lock(&chip->lock); + val = i2c_smbus_read_byte_data(client, reg); + mutex_unlock(&chip->lock); + + + return val; +} + + + +/* ========================= */ + + + + +static int RT4505_chip_init(struct RT4505_chip_data *chip) +{ + + + return 0; +} + +static int RT4505_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct RT4505_chip_data *chip; + struct RT4505_platform_data *pdata = client->dev.platform_data; + + int err = -1; + + PK_DBG("RT4505_probe start--->.\n"); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + err = -ENODEV; + PK_DBG("RT4505 i2c functionality check fail.\n"); + return err; + } + + chip = kzalloc(sizeof(struct RT4505_chip_data), GFP_KERNEL); + chip->client = client; + + mutex_init(&chip->lock); + i2c_set_clientdata(client, chip); + + if (pdata == NULL) { /* values are set to Zero. */ + PK_DBG("RT4505 Platform data does not exist\n"); + pdata = kzalloc(sizeof(struct RT4505_platform_data), GFP_KERNEL); + chip->pdata = pdata; + chip->no_pdata = 1; + } + + chip->pdata = pdata; + if (RT4505_chip_init(chip) < 0) + goto err_chip_init; + + RT4505_i2c_client = client; + PK_DBG("RT4505 Initializing is done\n"); + + return 0; + +err_chip_init: + i2c_set_clientdata(client, NULL); + kfree(chip); + PK_DBG("RT4505 probe is failed\n"); + return -ENODEV; +} + +static int RT4505_remove(struct i2c_client *client) +{ + struct RT4505_chip_data *chip = i2c_get_clientdata(client); + + if (chip->no_pdata) + kfree(chip->pdata); + kfree(chip); + return 0; +} + + +#define RT4505_NAME "leds-RT4505" +static const struct i2c_device_id RT4505_id[] = { + {RT4505_NAME, 0}, + {} +}; + +#ifdef CONFIG_OF +static const struct of_device_id RT4505_of_match[] = { + {.compatible = "mediatek,strobe_main"}, + {}, +}; +#endif + +static struct i2c_driver RT4505_i2c_driver = { + .driver = { + .name = RT4505_NAME, +#ifdef CONFIG_OF + .of_match_table = RT4505_of_match, +#endif + }, + .probe = RT4505_probe, + .remove = RT4505_remove, + .id_table = RT4505_id, +}; + +static int __init RT4505_init(void) +{ + PK_DBG("RT4505_init\n"); + return i2c_add_driver(&RT4505_i2c_driver); +} + +static void __exit RT4505_exit(void) +{ + i2c_del_driver(&RT4505_i2c_driver); +} + + +module_init(RT4505_init); +module_exit(RT4505_exit); + +MODULE_DESCRIPTION("Flash driver for RT4505"); +MODULE_AUTHOR("pw "); +MODULE_LICENSE("GPL v2"); + +int readReg(int reg) +{ + + int val; + + val = RT4505_read_reg(RT4505_i2c_client, reg); + return (int)val; +} + +int FL_Enable(void) +{ + int buf[2]; + + buf[0] = 10; + if (gIsTorch[gDuty] == 1) + buf[1] = 0x71; + else + buf[1] = 0x77; + RT4505_write_reg(RT4505_i2c_client, buf[0], buf[1]); + PK_DBG(" FL_Enable line=%d\n", __LINE__); + return 0; +} + + + +int FL_Disable(void) +{ + int buf[2]; + + buf[0] = 10; + buf[1] = 0x70; + RT4505_write_reg(RT4505_i2c_client, buf[0], buf[1]); + PK_DBG(" FL_Disable line=%d\n", __LINE__); + return 0; +} + +int FL_dim_duty(kal_uint32 duty) +{ + int buf[2]; + + if (duty > 17) + duty = 17; + if (duty < 0) + duty = 0; + gDuty = duty; + buf[0] = 9; + buf[1] = gLedDuty[duty]; + RT4505_write_reg(RT4505_i2c_client, buf[0], buf[1]); + PK_DBG(" FL_dim_duty line=%d\n", __LINE__); + return 0; +} + + + + +int FL_Init(void) +{ + int buf[2]; + + buf[0] = 0; + buf[1] = 0x80; + RT4505_write_reg(RT4505_i2c_client, buf[0], buf[1]); + + buf[0] = 8; + buf[1] = 0x7; + RT4505_write_reg(RT4505_i2c_client, buf[0], buf[1]); + + PK_DBG(" FL_Init line=%d\n", __LINE__); + return 0; +} + + +int FL_Uninit(void) +{ + FL_Disable(); + return 0; +} + +/***************************************************************************** +User interface +*****************************************************************************/ + +static void work_timeOutFunc(struct work_struct *data) +{ + FL_Disable(); + PK_DBG("ledTimeOut_callback\n"); +} + + + +enum hrtimer_restart ledTimeOutCallback(struct hrtimer *timer) +{ + schedule_work(&workTimeOut); + return HRTIMER_NORESTART; +} + +static struct hrtimer g_timeOutTimer; +void timerInit(void) +{ + static int init_flag; + + if (init_flag == 0) { + init_flag = 1; + INIT_WORK(&workTimeOut, work_timeOutFunc); + g_timeOutTimeMs = 1000; + hrtimer_init(&g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + g_timeOutTimer.function = ledTimeOutCallback; + } +} + + + +static int constant_flashlight_ioctl(unsigned int cmd, unsigned long arg) +{ + int i4RetValue = 0; + int ior_shift; + int iow_shift; + int iowr_shift; + + ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC, 0, int)); + iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC, 0, int)); + iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC, 0, int)); +/* PK_DBG + ("RT4505 constant_flashlight_ioctl() line=%d ior_shift=%d, iow_shift=%d iowr_shift=%d arg=%d\n", + __LINE__, ior_shift, iow_shift, iowr_shift, (int)arg); +*/ + switch (cmd) { + + case FLASH_IOC_SET_TIME_OUT_TIME_MS: + PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n", (int)arg); + g_timeOutTimeMs = arg; + break; + + + case FLASH_IOC_SET_DUTY: + PK_DBG("FLASHLIGHT_DUTY: %d\n", (int)arg); + FL_dim_duty(arg); + break; + + + case FLASH_IOC_SET_STEP: + PK_DBG("FLASH_IOC_SET_STEP: %d\n", (int)arg); + + break; + + case FLASH_IOC_SET_ONOFF: + PK_DBG("FLASHLIGHT_ONOFF: %d\n", (int)arg); + if (arg == 1) { + if (g_timeOutTimeMs != 0) { + ktime_t ktime; + + ktime = ktime_set(0, g_timeOutTimeMs * 1000000); + hrtimer_start(&g_timeOutTimer, ktime, HRTIMER_MODE_REL); + } + FL_Enable(); + } else { + FL_Disable(); + hrtimer_cancel(&g_timeOutTimer); + } + break; + default: + PK_DBG(" No such command\n"); + i4RetValue = -EPERM; + break; + } + return i4RetValue; +} + + + + +static int constant_flashlight_open(void *pArg) +{ + int i4RetValue = 0; + + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + if (0 == strobe_Res) { + FL_Init(); + timerInit(); + } + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + spin_lock_irq(&g_strobeSMPLock); + + + if (strobe_Res) { + PK_DBG(" busy!\n"); + i4RetValue = -EBUSY; + } else { + strobe_Res += 1; + } + + + spin_unlock_irq(&g_strobeSMPLock); + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + return i4RetValue; + +} + + +static int constant_flashlight_release(void *pArg) +{ + PK_DBG(" constant_flashlight_release\n"); + + if (strobe_Res) { + spin_lock_irq(&g_strobeSMPLock); + + strobe_Res = 0; + strobe_Timeus = 0; + + /* LED On Status */ + g_strobe_On = FALSE; + + spin_unlock_irq(&g_strobeSMPLock); + + FL_Uninit(); + } + + PK_DBG(" Done\n"); + + return 0; + +} + + +FLASHLIGHT_FUNCTION_STRUCT constantFlashlightFunc = { + constant_flashlight_open, + constant_flashlight_release, + constant_flashlight_ioctl +}; + + +MUINT32 constantFlashlightInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &constantFlashlightFunc; + return 0; +} + + + +/* LED flash control for high current capture mode*/ +ssize_t strobe_VDIrq(void) +{ + + return 0; +} +EXPORT_SYMBOL(strobe_VDIrq); diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/dummy_flashlight/Makefile b/drivers/misc/mediatek/flashlight/src/mt6755/dummy_flashlight/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..434381e1639eb0b8b096444ad1f8ae25df59676c --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/dummy_flashlight/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + + +obj-y += dummy_flashlight.o + diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/dummy_flashlight/dummy_flashlight.c b/drivers/misc/mediatek/flashlight/src/mt6755/dummy_flashlight/dummy_flashlight.c new file mode 100644 index 0000000000000000000000000000000000000000..54fae5545c41bf189334804a0c4fcc109a67381a --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/dummy_flashlight/dummy_flashlight.c @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_flashlight.h" +#include +#include +/* #include */ +/* #include */ + +/****************************************************************************** + * Definition +******************************************************************************/ +/* device name and major number */ +#define STROBE_DEVNAME "leds_strobe" + +#define DELAY_MS(ms) {mdelay(ms); } +#define DELAY_US(us) {mdelay(us); } +#define DELAY_NS(ns) {mdelay(ns); } + +/****************************************************************************** + * Debug configuration +******************************************************************************/ +#define TAG_NAME "[dummy_flashlight.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + +#if 0 +/******************************************************************************* +* structure & enumeration +*******************************************************************************/ +struct strobe_data { + spinlock_t lock; + wait_queue_head_t read_wait; + struct semaphore sem; +}; + +/****************************************************************************** + * local variables +******************************************************************************/ +static struct class *strobe_class; +static struct device *strobe_device; +static struct strobe_data strobe_private; +static dev_t strobe_devno; +static struct cdev strobe_cdev; +/* static BOOL g_strobe_On = FALSE; */ +#endif +/***************************************************************************** +User interface +*****************************************************************************/ +static int dummy_flashlight_ioctl(unsigned int cmd, unsigned long arg) +{ + int i4RetValue = 0; + int iFlashType = (int)FLASHLIGHT_NONE; + + switch (cmd) { + case FLASHLIGHTIOC_G_FLASHTYPE: + iFlashType = FLASHLIGHT_NONE; + if (0 != arg) { + if (copy_to_user((void __user *)arg, (void *)&iFlashType, _IOC_SIZE(cmd))) { + PK_DBG("[strobe_ioctl] ioctl copy to user failed\n"); + i4RetValue = -EFAULT; + } + } else { + i4RetValue = -EPERM; + } + break; + + default: + PK_DBG("ERROR Cmd ID\n"); + /* i4RetValue = -EPERM; */ + break; + } + return i4RetValue; +} + +static int dummy_flashlight_open(void *pArg) +{ + return 0; +} + +static int dummy_flashlight_release(void *pArg) +{ + return 0; +} + +FLASHLIGHT_FUNCTION_STRUCT dummyFlashlightFunc = { + dummy_flashlight_open, + dummy_flashlight_release, + dummy_flashlight_ioctl +}; + +MUINT32 dummyFlashlightInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &dummyFlashlightFunc; + return 0; +} + + +/* LED flash control for high current capture mode*/ +ssize_t strobe_VDIrq(void) +{ + return 0; +} +EXPORT_SYMBOL(strobe_VDIrq); + +#if 0 +static int strobe_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int strobe_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/*****************************************************************************/ +/* Kernel interface */ +static const struct file_operations strobe_fops = { + .owner = THIS_MODULE, + .ioctl = strobe_ioctl, + .open = strobe_open, + .release = strobe_release, +}; + +/***************************************************************************** +Driver interface +*****************************************************************************/ +#define ALLOC_DEVNO +static int strobe_probe(struct platform_device *dev) +{ + int ret = 0, err = 0; + +#ifdef ALLOC_DEVNO + ret = alloc_chrdev_region(&strobe_devno, 0, 1, STROBE_DEVNAME); + if (ret) { + PK_ERR("alloc_chrdev_region fail: %d\n", ret); + goto strobe_probe_error; + } else { + PK_DBG("major: %d, minor: %d\n", MAJOR(strobe_devno), MINOR(strobe_devno)); + } + cdev_init(&strobe_cdev, &strobe_fops); + strobe_cdev.owner = THIS_MODULE; + err = cdev_add(&strobe_cdev, strobe_devno, 1); + if (err) { + PK_ERR("cdev_add fail: %d\n", err); + goto strobe_probe_error; + } +#else +#define STROBE_MAJOR 242 + ret = register_chrdev(STROBE_MAJOR, STROBE_DEVNAME, &strobe_fops); + if (ret != 0) { + PK_ERR("Unable to register chardev on major=%d (%d)\n", STROBE_MAJOR, ret); + return ret; + } + strobe_devno = MKDEV(STROBE_MAJOR, 0); +#endif + + + strobe_class = class_create(THIS_MODULE, "strobedrv"); + if (IS_ERR(strobe_class)) { + PK_ERR("Unable to create class, err = %d\n", (int)PTR_ERR(strobe_class)); + goto strobe_probe_error; + } + + strobe_device = device_create(strobe_class, NULL, strobe_devno, NULL, STROBE_DEVNAME); + if (NULL == strobe_device) { + PK_ERR("device_create fail\n"); + goto strobe_probe_error; + } + + /*initialize members */ + spin_lock_init(&strobe_private.lock); + init_waitqueue_head(&strobe_private.read_wait); + init_MUTEX(&strobe_private.sem); + + /* LED On Status */ +/* g_strobe_On = FALSE; */ + + return 0; + +strobe_probe_error: +#ifdef ALLOC_DEVNO + if (err == 0) + cdev_del(&strobe_cdev); + if (ret == 0) + unregister_chrdev_region(strobe_devno, 1); +#else + if (ret == 0) + unregister_chrdev(MAJOR(strobe_devno), STROBE_DEVNAME); +#endif + return -1; +} + +static int strobe_remove(struct platform_device *dev) +{ +#ifdef ALLOC_DEVNO + cdev_del(&strobe_cdev); + unregister_chrdev_region(strobe_devno, 1); +#else + unregister_chrdev(MAJOR(strobe_devno), STROBE_DEVNAME); +#endif + device_destroy(strobe_class, strobe_devno); + class_destroy(strobe_class); + + /* LED On Status */ + /* g_strobe_On = FALSE; */ + return 0; +} + + +static struct platform_driver strobe_platform_driver = { + .probe = strobe_probe, + .remove = strobe_remove, + .driver = { + .name = STROBE_DEVNAME, + .owner = THIS_MODULE, + }, +}; + +static struct platform_device strobe_platform_device = { + .name = STROBE_DEVNAME, + .id = 0, + .dev = { + } +}; + +static int __init strobe_init(void) +{ + int ret = 0; + + ret = platform_device_register(&strobe_platform_device); + if (ret) { + PK_ERR("platform_device_register fail\n"); + return ret; + } + + ret = platform_driver_register(&strobe_platform_driver); + if (ret) { + PK_ERR("platform_driver_register fail\n"); + return ret; + } + return ret; +} + +static void __exit strobe_exit(void) +{ + platform_driver_unregister(&strobe_platform_driver); +} + +/*****************************************************************************/ +module_init(strobe_init); +module_exit(strobe_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jackie Su "); +MODULE_DESCRIPTION("LED strobe control Driver"); + +/* LED flash control for capture mode*/ +ssize_t strobe_StillExpCfgStart(void) +{ + return 0; +} +EXPORT_SYMBOL(strobe_StillExpCfgStart); + +ssize_t strobe_StillExpEndIrqCbf(void) +{ + return 0; +} +EXPORT_SYMBOL(strobe_StillExpEndIrqCbf); +#endif diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/kd_flashlightlist.c b/drivers/misc/mediatek/flashlight/src/mt6755/kd_flashlightlist.c new file mode 100644 index 0000000000000000000000000000000000000000..9b8dec164588a8743a5bdf023166cd40dd98be2f --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/kd_flashlightlist.c @@ -0,0 +1,972 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef WIN32 +#include "win_test.h" +#include "stdio.h" +#include "kd_flashlight.h" +#else +#ifdef CONFIG_COMPAT + +#include +#include + +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_flashlight_type.h" +#include +#include +#include +#include +#include +#include +#include +#endif +#ifdef CONFIG_COMPAT +#include +#include +#endif +#include "kd_flashlight.h" +#include + + + +/****************************************************************************** + * Definition +******************************************************************************/ + +/* device name and major number */ +#define FLASHLIGHT_DEVNAME "kd_camera_flashlight" + +/****************************************************************************** + * Debug configuration +******************************************************************************/ +#ifdef WIN32 +#define logI(fmt, ...) {printf(fmt, __VA_ARGS__); printf("\n"); } +#else +#define PFX "[KD_CAMERA_FLASHLIGHT]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(PFX "%s: " fmt, __func__ , ##arg) + +#define DEBUG_KD_STROBE +#ifdef DEBUG_KD_STROBE +#define logI PK_DBG_FUNC +#else +#define logI(a, ...) +#endif +#endif +/* ============================== */ +/* variables */ +/* ============================== */ +static FLASHLIGHT_FUNCTION_STRUCT + *g_pFlashInitFunc[e_Max_Sensor_Dev_Num][e_Max_Strobe_Num_Per_Dev][e_Max_Part_Num_Per_Dev]; +static int gLowBatDuty[e_Max_Sensor_Dev_Num][e_Max_Strobe_Num_Per_Dev]; +static int g_strobePartId[e_Max_Sensor_Dev_Num][e_Max_Strobe_Num_Per_Dev]; +static DEFINE_MUTEX(g_mutex); +/* ============================== */ +/* Pinctrl */ +/* ============================== */ +static struct pinctrl *flashlight_pinctrl; +static struct pinctrl_state *flashlight_hwen_high; +static struct pinctrl_state *flashlight_hwen_low; +static struct pinctrl_state *flashlight_torch_high; +static struct pinctrl_state *flashlight_torch_low; +static struct pinctrl_state *flashlight_flash_high; +static struct pinctrl_state *flashlight_flash_low; +static struct pinctrl_state *sub_flashlight_flash_high; +static struct pinctrl_state *sub_flashlight_flash_low; + +int flashlight_gpio_init(struct platform_device *pdev) +{ + int ret = 0; + + flashlight_pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(flashlight_pinctrl)) { + logI("Cannot find flashlight pinctrl!"); + ret = PTR_ERR(flashlight_pinctrl); + } + /* Flashlight HWEN pin initialization */ + flashlight_hwen_high = pinctrl_lookup_state(flashlight_pinctrl, "hwen_high"); + if (IS_ERR(flashlight_hwen_high)) { + ret = PTR_ERR(flashlight_hwen_high); + logI("%s : init err, flashlight_hwen_high\n", __func__); + } + + flashlight_hwen_low = pinctrl_lookup_state(flashlight_pinctrl, "hwen_low"); + if (IS_ERR(flashlight_hwen_low)) { + ret = PTR_ERR(flashlight_hwen_low); + logI("%s : init err, flashlight_hwen_low\n", __func__); + } + + /* Flashlight TORCH pin initialization */ + flashlight_torch_high = pinctrl_lookup_state(flashlight_pinctrl, "torch_high"); + if (IS_ERR(flashlight_torch_high)) { + ret = PTR_ERR(flashlight_torch_high); + logI("%s : init err, flashlight_torch_high\n", __func__); + } + + flashlight_torch_low = pinctrl_lookup_state(flashlight_pinctrl, "torch_low"); + if (IS_ERR(flashlight_torch_low)) { + ret = PTR_ERR(flashlight_torch_low); + logI("%s : init err, flashlight_torch_low\n", __func__); + } + + /* Flashlight FLASH pin initialization */ + flashlight_flash_high = pinctrl_lookup_state(flashlight_pinctrl, "flash_high"); + if (IS_ERR(flashlight_flash_high)) { + ret = PTR_ERR(flashlight_flash_high); + logI("%s : init err, flashlight_flash_high\n", __func__); + } + + flashlight_flash_low = pinctrl_lookup_state(flashlight_pinctrl, "flash_low"); + if (IS_ERR(flashlight_flash_low)) { + ret = PTR_ERR(flashlight_flash_low); + logI("%s : init err, flashlight_flash_low\n", __func__); + } + + /*Sub Flashlight FLASH pin initialization */ + sub_flashlight_flash_high = pinctrl_lookup_state(flashlight_pinctrl, "sub_flash_high"); + if (IS_ERR(sub_flashlight_flash_high)) { + ret = PTR_ERR(sub_flashlight_flash_high); + logI("%s : init err, sub_flashlight_flash_high\n", __func__); + } + + sub_flashlight_flash_low = pinctrl_lookup_state(flashlight_pinctrl, "sub_flash_low"); + if (IS_ERR(sub_flashlight_flash_low)) { + ret = PTR_ERR(sub_flashlight_flash_low); + logI("%s : init err, sub_flashlight_flash_low\n", __func__); + } + + return ret; +} + +int flashlight_gpio_set(int pin , int state) +{ + int ret = 0; + + if (IS_ERR(flashlight_pinctrl)) { + logI("%s : set err, flashlight_pinctrl not available\n", __func__); + return -1; + } + + switch (pin) { + case FLASHLIGHT_PIN_HWEN: + if (state == STATE_LOW && !IS_ERR(flashlight_hwen_low)) + pinctrl_select_state(flashlight_pinctrl, flashlight_hwen_low); + else if (state == STATE_HIGH && !IS_ERR(flashlight_hwen_high)) + pinctrl_select_state(flashlight_pinctrl, flashlight_hwen_high); + else + logI("%s : set err, pin(%d) state(%d)\n", __func__, pin, state); + break; + case FLASHLIGHT_PIN_TORCH: + if (state == STATE_LOW && !IS_ERR(flashlight_torch_low)) + pinctrl_select_state(flashlight_pinctrl, flashlight_torch_low); + else if (state == STATE_HIGH && !IS_ERR(flashlight_torch_high)) + pinctrl_select_state(flashlight_pinctrl, flashlight_torch_high); + else + logI("%s : set err, pin(%d) state(%d)\n", __func__, pin, state); + break; + case FLASHLIGHT_PIN_FLASH: + if (state == STATE_LOW && !IS_ERR(flashlight_flash_low)) + pinctrl_select_state(flashlight_pinctrl, flashlight_flash_low); + else if (state == STATE_HIGH && !IS_ERR(flashlight_flash_high)) + pinctrl_select_state(flashlight_pinctrl, flashlight_flash_high); + else + logI("%s : set err, pin(%d) state(%d)\n", __func__, pin, state); + break; + case SUB_FLASHLIGHT_PIN_FLASH: + if (state == STATE_LOW && !IS_ERR(sub_flashlight_flash_low)) + pinctrl_select_state(flashlight_pinctrl, sub_flashlight_flash_low); + else if (state == STATE_HIGH && !IS_ERR(sub_flashlight_flash_high)) + pinctrl_select_state(flashlight_pinctrl, sub_flashlight_flash_high); + else + logI("%s : set err, pin(%d) state(%d)\n", __func__, pin, state); + break; + default: + logI("%s : set err, pin(%d) state(%d)\n", __func__, pin, state); + break; + } + logI("%s : pin(%d) state(%d)\n", __func__, pin, state); + return ret; +} + +/* ============================== */ +/* functions */ +/* ============================== */ +int globalInit(void) +{ + int i; + int j; + int k; + + logI("globalInit"); + for (i = 0; i < e_Max_Sensor_Dev_Num; i++) + for (j = 0; j < e_Max_Strobe_Num_Per_Dev; j++) { + gLowBatDuty[i][j] = -1; + g_strobePartId[i][j] = 1; + for (k = 0; k < e_Max_Part_Num_Per_Dev; k++) + g_pFlashInitFunc[i][j][k] = 0; + } + return 0; +} + +int checkAndRelease(void) +{ + int i; + int j; + int k; + + mutex_lock(&g_mutex); + for (i = 0; i < e_Max_Sensor_Dev_Num; i++) + for (j = 0; j < e_Max_Strobe_Num_Per_Dev; j++) + for (k = 0; k < e_Max_Part_Num_Per_Dev; k++) { + if (g_pFlashInitFunc[i][j][k] != 0) { + logI("checkAndRelease %d %d %d", i, j, k); + g_pFlashInitFunc[i][j][k]->flashlight_release(0); + g_pFlashInitFunc[i][j][k] = 0; + } + } + mutex_unlock(&g_mutex); + return 0; +} + +int getSensorDevIndex(int sensorDev) +{ + if (sensorDev == e_CAMERA_MAIN_SENSOR) + return 0; + else if (sensorDev == e_CAMERA_SUB_SENSOR) + return 1; + else if (sensorDev == e_CAMERA_MAIN_2_SENSOR) + return 2; + logI("sensorDev=%d is wrong", sensorDev); + return -1; +} + +int getStrobeIndex(int strobeId) +{ + if (strobeId < 1 || strobeId > 2) { + logI("strobeId=%d is wrong", strobeId); + return -1; + } + return strobeId - 1; +} + +int getPartIndex(int partId) +{ + if (partId < 1 || partId > 2) { + logI("partId=%d is wrong", partId); + return -1; + } + return partId - 1; +} + +MINT32 default_flashlight_open(void *pArg) +{ + logI("[default_flashlight_open] E ~"); + return 0; +} + +MINT32 default_flashlight_release(void *pArg) +{ + logI("[default_flashlight_release] E ~"); + return 0; +} + +MINT32 default_flashlight_ioctl(unsigned int cmd, unsigned long arg) +{ + int i4RetValue = 0; + int iFlashType = (int)FLASHLIGHT_NONE; + kdStrobeDrvArg kdArg; + unsigned long copyRet; + + copyRet = copy_from_user(&kdArg, (void *)arg, sizeof(kdStrobeDrvArg)); + + + switch (cmd) { + case FLASHLIGHTIOC_G_FLASHTYPE: + iFlashType = FLASHLIGHT_NONE; + kdArg.arg = iFlashType; + if (copy_to_user((void __user *)arg, (void *)&kdArg, sizeof(kdStrobeDrvArg))) { + logI("[FLASHLIGHTIOC_G_FLASHTYPE] ioctl copy to user failed ~"); + return -EFAULT; + } + break; + default: + logI("[default_flashlight_ioctl] ~"); + break; + } + return i4RetValue; +} + +FLASHLIGHT_FUNCTION_STRUCT defaultFlashlightFunc = { + default_flashlight_open, + default_flashlight_release, + default_flashlight_ioctl, +}; + +UINT32 strobeInit_dummy(FLASHLIGHT_FUNCTION_STRUCT **pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &defaultFlashlightFunc; + return 0; +} + +/* ======================================================================== */ +static int setFlashDrv(int sensorDev, int strobeId) +{ + int partId; + int sensorDevIndex; + int strobeIndex; + int partIndex; + FLASHLIGHT_FUNCTION_STRUCT **ppF = 0; + + sensorDevIndex = getSensorDevIndex(sensorDev); + strobeIndex = getStrobeIndex(strobeId); + if (sensorDevIndex < 0 || strobeIndex < 0) + return -1; + partId = g_strobePartId[sensorDevIndex][strobeIndex]; + partIndex = getPartIndex(partId); + if (partIndex < 0) + return -1; + + logI("setFlashDrv sensorDev=%d, strobeId=%d, partId=%d ~", sensorDev, strobeId, partId); + + ppF = &g_pFlashInitFunc[sensorDevIndex][strobeIndex][partIndex]; + if (sensorDev == e_CAMERA_MAIN_SENSOR) { +#if defined(DUMMY_FLASHLIGHT) + strobeInit_dummy(ppF); +#else + if (strobeId == 1) { + if (partId == 1) + constantFlashlightInit(ppF); + else if (partId == 2) + strobeInit_main_sid1_part2(ppF); + } else if (strobeId == 2) { + if (partId == 1) + strobeInit_main_sid2_part1(ppF); + + else if (partId == 2) + strobeInit_main_sid2_part2(ppF); + } +#endif + } else if (sensorDev == e_CAMERA_SUB_SENSOR) { + if (strobeId == 1) { + if (partId == 1) + subStrobeInit(ppF); + else if (partId == 2) + strobeInit_sub_sid1_part2(ppF); + } else if (strobeId == 2) { + if (partId == 1) + strobeInit_sub_sid2_part1(ppF); + else if (partId == 2) + strobeInit_sub_sid2_part2(ppF); + } + } + + + if ((*ppF) != 0) { + (*ppF)->flashlight_open(0); + logI("setFlashDrv ok %d", __LINE__); + } else { + logI("set function pointer not found!!"); + return -1; + } + return 0; +} + +/*@@ +static int decFlash(void) +{ + int i; + int j; + int k; + int duty; + for(i=0;iflashlight_ioctl(FLASH_IOC_SET_DUTY, duty); + } + } + } + return 0; +}*/ + +static int closeFlash(void) +{ + int i; + int j; + int k; + + mutex_lock(&g_mutex); + logI("closeFlash due to low power ln=%d", __LINE__); + for (i = 0; i < e_Max_Sensor_Dev_Num; i++) { + /* logI("closeFlash ln=%d %d",__LINE__,i); */ + for (j = 0; j < e_Max_Strobe_Num_Per_Dev; j++) { + /* logI("closeFlash ln=%d %d",__LINE__,j); */ + for (k = 0; k < e_Max_Part_Num_Per_Dev; k++) { + /* logI("closeFlash ln=%d %d %d",__LINE__,k, (int)g_pFlashInitFunc[i][j][k]); */ + if (g_pFlashInitFunc[i][j][k] != 0) { + g_pFlashInitFunc[i][j][k]->flashlight_ioctl + (FLASH_IOC_SET_ONOFF, 0); + } + } + } + } + mutex_unlock(&g_mutex); + return 0; +} + +/* @@{ */ + +/* +#define LOW_BATTERY_LEVEL_0 0 +#define LOW_BATTERY_LEVEL_1 1 +#define LOW_BATTERY_LEVEL_2 2 +#define BATTERY_PERCENT_LEVEL_0 0 +#define BATTERY_PERCENT_LEVEL_1 1 +*/ + +/* /}@@ */ +static int gLowPowerVbat = LOW_BATTERY_LEVEL_0; + +static void Lbat_protection_powerlimit_flash(LOW_BATTERY_LEVEL level) +{ + if (level == LOW_BATTERY_LEVEL_0) { + gLowPowerVbat = LOW_BATTERY_LEVEL_0; + } else if (level == LOW_BATTERY_LEVEL_1) { + closeFlash(); + gLowPowerVbat = LOW_BATTERY_LEVEL_1; + + } else if (level == LOW_BATTERY_LEVEL_2) { + closeFlash(); + gLowPowerVbat = LOW_BATTERY_LEVEL_2; + } else { + /* unlimit cpu and gpu */ + } +} + + + +static int gLowPowerPer = BATTERY_PERCENT_LEVEL_0; + +static void bat_per_protection_powerlimit_flashlight(BATTERY_PERCENT_LEVEL level) +{ + if (level == BATTERY_PERCENT_LEVEL_0) { + gLowPowerPer = BATTERY_PERCENT_LEVEL_0; + } else if (level == BATTERY_PERCENT_LEVEL_1) { + closeFlash(); + gLowPowerPer = BATTERY_PERCENT_LEVEL_1; + } else { + /* unlimit cpu and gpu */ + } +} + + +/* +static int gLowPowerOc=BATTERY_OC_LEVEL_0; + +void bat_oc_protection_powerlimit(BATTERY_OC_LEVEL level) +{ + if (level == BATTERY_OC_LEVEL_1){ + closeFlash(); + gLowPowerOc=BATTERY_OC_LEVEL_1; + } + else{ + gLowPowerOc=BATTERY_OC_LEVEL_0; + } +} +*/ + + + +/* ======================================================================== */ + +static long flashlight_ioctl_core(struct file *file, unsigned int cmd, unsigned long arg) +{ + int partId; + int sensorDevIndex; + int strobeIndex; + int partIndex; + int i4RetValue = 0; + kdStrobeDrvArg kdArg; + unsigned long copyRet; + + copyRet = copy_from_user(&kdArg, (void *)arg, sizeof(kdStrobeDrvArg)); + logI("flashlight_ioctl cmd=0x%x(nr=%d), senorDev=0x%x ledId=0x%x arg=0x%lx", cmd, + _IOC_NR(cmd), kdArg.sensorDev, kdArg.strobeId, (unsigned long)kdArg.arg); + sensorDevIndex = getSensorDevIndex(kdArg.sensorDev); + strobeIndex = getStrobeIndex(kdArg.strobeId); + if (sensorDevIndex < 0 || strobeIndex < 0) + return -1; + partId = g_strobePartId[sensorDevIndex][strobeIndex]; + partIndex = getPartIndex(partId); + if (partIndex < 0) + return -1; + + + + switch (cmd) { + case FLASH_IOC_GET_PROTOCOL_VERSION: + i4RetValue = 1; + break; + case FLASH_IOC_IS_LOW_POWER: + logI("FLASH_IOC_IS_LOW_POWER"); + { + int isLow = 0; + + if (gLowPowerPer != BATTERY_PERCENT_LEVEL_0 + || gLowPowerVbat != LOW_BATTERY_LEVEL_0) + isLow = 1; + logI("FLASH_IOC_IS_LOW_POWER %d %d %d", gLowPowerPer, gLowPowerVbat, isLow); + kdArg.arg = isLow; + if (copy_to_user + ((void __user *)arg, (void *)&kdArg, sizeof(kdStrobeDrvArg))) { + logI("[FLASH_IOC_IS_LOW_POWER] ioctl copy to user failed ~"); + return -EFAULT; + } + } + break; + + case FLASH_IOC_LOW_POWER_DETECT_START: + logI("FLASH_IOC_LOW_POWER_DETECT_START"); + gLowBatDuty[sensorDevIndex][strobeIndex] = kdArg.arg; + break; + + case FLASH_IOC_LOW_POWER_DETECT_END: + logI("FLASH_IOC_LOW_POWER_DETECT_END"); + gLowBatDuty[sensorDevIndex][strobeIndex] = -1; + break; + case FLASHLIGHTIOC_X_SET_DRIVER: + i4RetValue = setFlashDrv(kdArg.sensorDev, kdArg.strobeId); + break; + case FLASH_IOC_GET_PART_ID: + case FLASH_IOC_GET_MAIN_PART_ID: + case FLASH_IOC_GET_SUB_PART_ID: + case FLASH_IOC_GET_MAIN2_PART_ID: + { + int partId; + + partId = strobe_getPartId(kdArg.sensorDev, kdArg.strobeId); + g_strobePartId[sensorDevIndex][strobeIndex] = partId; + kdArg.arg = partId; + if (copy_to_user + ((void __user *)arg, (void *)&kdArg, sizeof(kdStrobeDrvArg))) { + logI("[FLASH_IOC_GET_PART_ID] ioctl copy to user failed ~"); + return -EFAULT; + } + logI("FLASH_IOC_GET_PART_ID line=%d partId=%d", __LINE__, partId); + } + break; + case FLASH_IOC_SET_ONOFF: + { + FLASHLIGHT_FUNCTION_STRUCT *pF; + + pF = g_pFlashInitFunc[sensorDevIndex][strobeIndex][partIndex]; + if (pF != 0) { + kicker_pbm_by_flash(kdArg.arg); + i4RetValue = pF->flashlight_ioctl(cmd, kdArg.arg); + + } else { + logI("[FLASH_IOC_SET_ONOFF] function pointer is wrong -"); + } + } + break; + case FLASH_IOC_UNINIT: + { + FLASHLIGHT_FUNCTION_STRUCT *pF; + + pF = g_pFlashInitFunc[sensorDevIndex][strobeIndex][partIndex]; + if (pF != 0) { + i4RetValue = pF->flashlight_release((void *)0); + pF = 0; + + } else { + logI("[FLASH_IOC_UNINIT] function pointer is wrong ~"); + } + } + break; + default: + { + FLASHLIGHT_FUNCTION_STRUCT *pF; + + pF = g_pFlashInitFunc[sensorDevIndex][strobeIndex][partIndex]; + if (pF != 0) + i4RetValue = pF->flashlight_ioctl(cmd, kdArg.arg); + else + logI("[default] function pointer is wrong ~"); + } + break; + } + return i4RetValue; +} + + +static long flashlight_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int err; +/* int dir; */ + err = flashlight_ioctl_core(file, cmd, arg); + /* dir = _IOC_DIR(cmd); */ + /* if(dir &_IOC_READ) */ + { + /* copy_to_user */ + } + return err; +} + +#ifdef CONFIG_COMPAT + +/* +static int compat_arg_struct_user32_to_kernel( + struct StrobeDrvArg __user *data32, + struct compat_StrobeDrvArg __user *data) +{ + compat_int_t i; + int err=0; + + err |= get_user(i, &data32->sensorDev); + err |= put_user(i, &data->sensorDev); + + err |= get_user(i, &data32->arg); + err |= put_user(i, &data->arg); + + return err; +} + +static int compat_arg_struct_kernel_to_user32( + struct StrobeDrvArg __user *data32, + struct compat_StrobeDrvArg __user *data) + +{ + compat_int_t i; + int err=0; + + err |= get_user(i, &data->sensorDev); + err |= put_user(i, &data32->sensorDev); + err |= get_user(i, &data->arg); + err |= put_user(i, &data32->arg); + + return err; +}*/ + + + +static long my_ioctl_compat(struct file *filep, unsigned int cmd, unsigned long arg) +{ + int err; + /* int copyRet; */ + kdStrobeDrvArg *pUObj; + + logI("flash my_ioctl_compat2 line=%d cmd=%d arg=%ld\n", __LINE__, cmd, arg); + pUObj = compat_ptr(arg); + + /* + kdStrobeDrvArg* pUObj; + pUObj = compat_ptr(arg); + kdStrobeDrvArg obj; + copyRet = copy_from_user(&obj , (void *)pUObj , sizeof(kdStrobeDrvArg)); + logI("strobe arg %d %d %d\n", obj.sensorDev, obj.strobeId, obj.arg); + obj.arg = 23411; + copy_to_user((void __user *) arg , (void*)&obj , sizeof(kdStrobeDrvArg)); + */ + + + + + /* data = compat_alloc_user_space(sizeof(*data)); */ + /* if (sys_data == NULL) */ + /* return -EFAULT; */ + /* err = compat_arg_struct_user32_to_kernel(data32, data); */ + /* arg2 = (unsigned long)data32; */ + err = flashlight_ioctl_core(filep, cmd, (unsigned long)pUObj); + + return err; + +} +#endif + + +static int flashlight_open(struct inode *inode, struct file *file) +{ + int i4RetValue = 0; + static int bInited; + + if (bInited == 0) { + globalInit(); + bInited = 1; + } + logI("[flashlight_open] E ~"); + return i4RetValue; +} + +static int flashlight_release(struct inode *inode, struct file *file) +{ + logI("[flashlight_release] E ~"); + + checkAndRelease(); + + return 0; +} + + +#ifdef WIN32 +int fl_open(struct inode *inode, struct file *file) +{ + return flashlight_open(inode, file); +} + +int fl_release(struct inode *inode, struct file *file) +{ + return flashlight_release(inode, file); +} + +long fl_ioctrl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return flashlight_ioctl(file, cmd, arg); +} + +#else +/* ======================================================================== */ +/* ======================================================================== */ +/* ======================================================================== */ +/* Kernel interface */ +static const struct file_operations flashlight_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = flashlight_ioctl, + .open = flashlight_open, + .release = flashlight_release, +#ifdef CONFIG_COMPAT + .compat_ioctl = my_ioctl_compat, +#endif +}; + +/* ======================================================================== */ +/* Driver interface */ +/* ======================================================================== */ +struct flashlight_data { + spinlock_t lock; + wait_queue_head_t read_wait; + struct semaphore sem; +}; +static struct class *flashlight_class; +static struct device *flashlight_device; +static struct flashlight_data flashlight_private; +static dev_t flashlight_devno; +static struct cdev *g_pFlash_CharDrv; +/* ======================================================================== */ +#define ALLOC_DEVNO +static int flashlight_probe(struct platform_device *dev) +{ + int ret = 0, err = 0; + + logI("[flashlight_probe] start ~"); + +#ifdef ALLOC_DEVNO + ret = alloc_chrdev_region(&flashlight_devno, 0, 1, FLASHLIGHT_DEVNAME); + if (ret) { + logI("[flashlight_probe] alloc_chrdev_region fail: %d ~", ret); + goto flashlight_probe_error; + } else { + logI("[flashlight_probe] major: %d, minor: %d ~", MAJOR(flashlight_devno), + MINOR(flashlight_devno)); + } + /* Allocate driver */ + g_pFlash_CharDrv = cdev_alloc(); + if (NULL == g_pFlash_CharDrv) { + unregister_chrdev_region(flashlight_devno, 1); + + logI("Allocate mem for kobject failed\n"); + + return -1; + } + cdev_init(g_pFlash_CharDrv, &flashlight_fops); + g_pFlash_CharDrv->owner = THIS_MODULE; + err = cdev_add(g_pFlash_CharDrv, flashlight_devno, 1); + if (err) { + logI("[flashlight_probe] cdev_add fail: %d ~", err); + goto flashlight_probe_error; + } +#else +#define FLASHLIGHT_MAJOR 242 + ret = register_chrdev(FLASHLIGHT_MAJOR, FLASHLIGHT_DEVNAME, &flashlight_fops); + if (ret != 0) { + logI("[flashlight_probe] Unable to register chardev on major=%d (%d) ~", + FLASHLIGHT_MAJOR, ret); + return ret; + } + flashlight_devno = MKDEV(FLASHLIGHT_MAJOR, 0); +#endif + + + flashlight_class = class_create(THIS_MODULE, "flashlightdrv"); + if (IS_ERR(flashlight_class)) { + logI("[flashlight_probe] Unable to create class, err = %d ~", + (int)PTR_ERR(flashlight_class)); + goto flashlight_probe_error; + } + + flashlight_device = + device_create(flashlight_class, NULL, flashlight_devno, NULL, FLASHLIGHT_DEVNAME); + if (NULL == flashlight_device) { + logI("[flashlight_probe] device_create fail ~"); + goto flashlight_probe_error; + } + + /* initialize members */ + spin_lock_init(&flashlight_private.lock); + init_waitqueue_head(&flashlight_private.read_wait); + /* init_MUTEX(&flashlight_private.sem); */ + sema_init(&flashlight_private.sem, 1); + + /* GPIO pinctrl initial */ + flashlight_gpio_init(dev); + + logI("[flashlight_probe] Done ~"); + return 0; + +flashlight_probe_error: +#ifdef ALLOC_DEVNO + if (err == 0) + cdev_del(g_pFlash_CharDrv); + if (ret == 0) + unregister_chrdev_region(flashlight_devno, 1); +#else + if (ret == 0) + unregister_chrdev(MAJOR(flashlight_devno), FLASHLIGHT_DEVNAME); +#endif + return -1; +} + +static int flashlight_remove(struct platform_device *dev) +{ + + logI("[flashlight_probe] start\n"); + +#ifdef ALLOC_DEVNO + cdev_del(g_pFlash_CharDrv); + unregister_chrdev_region(flashlight_devno, 1); +#else + unregister_chrdev(MAJOR(flashlight_devno), FLASHLIGHT_DEVNAME); +#endif + device_destroy(flashlight_class, flashlight_devno); + class_destroy(flashlight_class); + + logI("[flashlight_probe] Done ~"); + return 0; +} + +static void flashlight_shutdown(struct platform_device *dev) +{ + + logI("[flashlight_shutdown] start\n"); + checkAndRelease(); + logI("[flashlight_shutdown] Done ~"); +} + +#ifdef CONFIG_OF +static const struct of_device_id FLASHLIGHT_of_match[] = { + {.compatible = "mediatek,mt6755-flashlight"}, + {}, +}; +#endif + +static struct platform_driver flashlight_platform_driver = { + .probe = flashlight_probe, + .remove = flashlight_remove, + .shutdown = flashlight_shutdown, + .driver = { + .name = FLASHLIGHT_DEVNAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = FLASHLIGHT_of_match, +#endif + }, +}; + +#ifndef CONFIG_OF +static struct platform_device flashlight_platform_device = { + .name = FLASHLIGHT_DEVNAME, + .id = 0, + .dev = { + } +}; +#endif + +static int __init flashlight_init(void) +{ + int ret = 0; + + logI("[flashlight_probe] start ~"); + +#ifndef CONFIG_OF + ret = platform_device_register(&flashlight_platform_device); + if (ret) { + logI("[flashlight_probe] platform_device_register fail ~"); + return ret; + } +#endif + + ret = platform_driver_register(&flashlight_platform_driver); + if (ret) { + logI("[flashlight_probe] platform_driver_register fail ~"); + return ret; + } + + register_low_battery_notify(&Lbat_protection_powerlimit_flash, LOW_BATTERY_PRIO_FLASHLIGHT); + register_battery_percent_notify(&bat_per_protection_powerlimit_flashlight, + BATTERY_PERCENT_PRIO_FLASHLIGHT); +/* @@ register_battery_oc_notify(&bat_oc_protection_powerlimit, BATTERY_OC_PRIO_FLASHLIGHT); */ + + + logI("[flashlight_probe] done! ~"); + return ret; +} + +static void __exit flashlight_exit(void) +{ + logI("[flashlight_probe] start ~"); + platform_driver_unregister(&flashlight_platform_driver); + /* to flush work queue */ + /* flush_scheduled_work(); */ + logI("[flashlight_probe] done! ~"); +} + +/* ======================================================== */ +module_init(flashlight_init); +module_exit(flashlight_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jackie Su "); +MODULE_DESCRIPTION("Flashlight control Driver"); + +#endif diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p382/constant_flashlight/Makefile b/drivers/misc/mediatek/flashlight/src/mt6755/p382/constant_flashlight/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..e1f69061aef578727b484b6a9dd05c61ac4aab43 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p382/constant_flashlight/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for misc devices that really don't fit anywhere else. +# + +obj-y += leds_strobe.o diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p382/constant_flashlight/leds_strobe.c b/drivers/misc/mediatek/flashlight/src/mt6755/p382/constant_flashlight/leds_strobe.c new file mode 100755 index 0000000000000000000000000000000000000000..7d756d685746ef9a9e30163881e1edd2a847c114 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p382/constant_flashlight/leds_strobe.c @@ -0,0 +1,313 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_flashlight.h" +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +#include +#include + + + +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ + +#define TAG_NAME "[leds_strobe.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + +/*#define DEBUG_LEDS_STROBE*/ +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#else +#define PK_DBG(a, ...) +#endif + +/****************************************************************************** + * local variables +******************************************************************************/ + +static DEFINE_SPINLOCK(g_strobeSMPLock); /* cotta-- SMP proection */ + + +static u32 strobe_Res; +static u32 strobe_Timeus; +static BOOL g_strobe_On; + +static int g_duty = 0; +static int g_timeOutTimeMs; + +static DEFINE_MUTEX(g_strobeSem); + + + + +static struct work_struct workTimeOut; + +/* #define FLASH_GPIO_ENF GPIO12 */ +/* #define FLASH_GPIO_ENT GPIO13 */ + + +/***************************************************************************** +Functions +*****************************************************************************/ +static void work_timeOutFunc(struct work_struct *data); + + +//struct platform_device *flashlight_plt_dev = NULL; + + +int FL_Enable(void) +{ + PK_DBG("%s line %d \n",__func__,__LINE__); + if(g_duty < 1) + { + flashlight_gpio_set(FLASHLIGHT_PIN_TORCH,STATE_HIGH); + flashlight_gpio_set(FLASHLIGHT_PIN_FLASH,STATE_LOW); + } + else + { + flashlight_gpio_set(FLASHLIGHT_PIN_TORCH,STATE_HIGH); + flashlight_gpio_set(FLASHLIGHT_PIN_FLASH,STATE_HIGH); + } + return 0; +} + + + +int FL_Disable(void) +{ + PK_DBG("%s line %d \n",__func__,__LINE__); + flashlight_gpio_set(FLASHLIGHT_PIN_TORCH,STATE_LOW); + flashlight_gpio_set(FLASHLIGHT_PIN_FLASH,STATE_LOW); + return 0; +} + +int FL_dim_duty(kal_uint32 duty) +{ + PK_DBG(" FL_dim_duty line=%d\n", __LINE__); + g_duty = duty; + return 0; +} + + + + +int FL_Init(void) +{ + PK_DBG(KERN_ERR "%s line %d \n",__func__,__LINE__); + flashlight_gpio_set(FLASHLIGHT_PIN_TORCH,STATE_LOW); + flashlight_gpio_set(FLASHLIGHT_PIN_FLASH,STATE_LOW); + return 0; +} + + +int FL_Uninit(void) +{ + FL_Disable(); + return 0; +} + +/***************************************************************************** +User interface +*****************************************************************************/ + +static void work_timeOutFunc(struct work_struct *data) +{ + FL_Disable(); + PK_DBG("ledTimeOut_callback\n"); +} + + + +enum hrtimer_restart ledTimeOutCallback(struct hrtimer *timer) +{ + schedule_work(&workTimeOut); + return HRTIMER_NORESTART; +} + +static struct hrtimer g_timeOutTimer; +void timerInit(void) +{ + INIT_WORK(&workTimeOut, work_timeOutFunc); + g_timeOutTimeMs = 1000; + hrtimer_init(&g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + g_timeOutTimer.function = ledTimeOutCallback; +} + + + +static int constant_flashlight_ioctl(unsigned int cmd, unsigned long arg) +{ + int i4RetValue = 0; + int ior_shift; + int iow_shift; + int iowr_shift; + + ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC, 0, int)); + iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC, 0, int)); + iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC, 0, int)); +/* PK_DBG + ("LM3642 constant_flashlight_ioctl() line=%d ior_shift=%d, iow_shift=%d iowr_shift=%d arg=%d\n", + __LINE__, ior_shift, iow_shift, iowr_shift, (int)arg); +*/ + switch (cmd) { + + case FLASH_IOC_SET_TIME_OUT_TIME_MS: + PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n", (int)arg); + g_timeOutTimeMs = arg; + break; + + + case FLASH_IOC_SET_DUTY: + PK_DBG("FLASHLIGHT_DUTY: %d\n", (int)arg); + FL_dim_duty(arg); + break; + + + case FLASH_IOC_SET_STEP: + PK_DBG("FLASH_IOC_SET_STEP: %d\n", (int)arg); + + break; + + case FLASH_IOC_SET_ONOFF: + PK_DBG("FLASHLIGHT_ONOFF: %d\n", (int)arg); + if (arg == 1) { + + int s; + int ms; + + if (g_timeOutTimeMs > 1000) { + s = g_timeOutTimeMs / 1000; + ms = g_timeOutTimeMs - s * 1000; + } else { + s = 0; + ms = g_timeOutTimeMs; + } + + if (g_timeOutTimeMs != 0) { + ktime_t ktime; + + ktime = ktime_set(s, ms * 1000000); + hrtimer_start(&g_timeOutTimer, ktime, HRTIMER_MODE_REL); + } + FL_Enable(); + } else { + FL_Disable(); + hrtimer_cancel(&g_timeOutTimer); + } + break; + default: + PK_DBG(" No such command\n"); + i4RetValue = -EPERM; + break; + } + return i4RetValue; +} + + + + +static int constant_flashlight_open(void *pArg) +{ + int i4RetValue = 0; + + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + if (0 == strobe_Res) { + FL_Init(); + timerInit(); + } + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + spin_lock_irq(&g_strobeSMPLock); + + + if (strobe_Res) { + PK_DBG(" busy!\n"); + i4RetValue = -EBUSY; + } else { + strobe_Res += 1; + } + + + spin_unlock_irq(&g_strobeSMPLock); + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + return i4RetValue; + +} + + +static int constant_flashlight_release(void *pArg) +{ + PK_DBG(" constant_flashlight_release\n"); + + if (strobe_Res) { + spin_lock_irq(&g_strobeSMPLock); + + strobe_Res = 0; + strobe_Timeus = 0; + + /* LED On Status */ + g_strobe_On = FALSE; + + spin_unlock_irq(&g_strobeSMPLock); + + FL_Uninit(); + } + + PK_DBG(" Done\n"); + + return 0; + +} + + +FLASHLIGHT_FUNCTION_STRUCT constantFlashlightFunc = { + constant_flashlight_open, + constant_flashlight_release, + constant_flashlight_ioctl +}; + + +MUINT32 constantFlashlightInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &constantFlashlightFunc; + return 0; +} + + + +/* LED flash control for high current capture mode*/ +ssize_t strobe_VDIrq(void) +{ + + return 0; +} +EXPORT_SYMBOL(strobe_VDIrq); diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p383/constant_flashlight/Makefile b/drivers/misc/mediatek/flashlight/src/mt6755/p383/constant_flashlight/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..e1f69061aef578727b484b6a9dd05c61ac4aab43 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p383/constant_flashlight/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for misc devices that really don't fit anywhere else. +# + +obj-y += leds_strobe.o diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p383/constant_flashlight/leds_strobe.c b/drivers/misc/mediatek/flashlight/src/mt6755/p383/constant_flashlight/leds_strobe.c new file mode 100755 index 0000000000000000000000000000000000000000..ec04b0969d102954767256c3921ab2b5b03b3040 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p383/constant_flashlight/leds_strobe.c @@ -0,0 +1,811 @@ +/************************************************************************** +* aw3644_flashlight.c +* +* Create Date : +* +* Modify Date : +* +* Create by : AWINIC Technology CO., LTD +* +* Version : 0.9, 2016/05/15 +**************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "kd_flashlight.h" +#include "kd_flashlight_type.h" +#include +#include +#include +/****************************************************************************** + * Debug configuration +******************************************************************************/ + +#define TAG_NAME "[leds_strobe.c]" +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) + +#define DEBUG_LEDS_STROBE + +#ifdef DEBUG_LEDS_STROBE + #define PK_DBG PK_DBG_FUNC +#else + #define PK_DBG(a, ...) +#endif +/****************************************************************************** + * local variables +******************************************************************************/ +static DEFINE_SPINLOCK(g_strobeSMPLock); /* cotta-- SMP proection */ + +static u32 strobe_Res; +static u32 strobe_Timeus; +static BOOL g_strobe_On; +static BOOL ktd2685_use = 0; +static int g_timeOutTimeMs; + +static struct work_struct workTimeOut; +/***************************************************************************** +Functions +*****************************************************************************/ +static void work_timeOutFunc(struct work_struct *data); +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define AW3644_I2C_NAME "AW3644_FLASHLIGHT" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +unsigned char aw3644_hw_on(void); +unsigned char aw3644_hw_off(void); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static ssize_t aw3644_get_reg(struct device* cd,struct device_attribute *attr, char* buf); +static ssize_t aw3644_set_reg(struct device* cd, struct device_attribute *attr,const char* buf, size_t len); +static ssize_t aw3644_set_hwen(struct device* cd, struct device_attribute *attr,const char* buf, size_t len); +static ssize_t aw3644_get_hwen(struct device* cd, struct device_attribute *attr, char* buf); + +static DEVICE_ATTR(reg, 0660, aw3644_get_reg, aw3644_set_reg); +static DEVICE_ATTR(hwen, 0660, aw3644_get_hwen, aw3644_set_hwen); + +struct i2c_client *aw3644_flashlight_client; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// i2c write and read +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +unsigned char i2c_write_reg(unsigned char addr, unsigned char reg_data) +{ + char ret; + u8 wdbuf[512] = {0}; + + struct i2c_msg msgs[] = { + { + .addr = aw3644_flashlight_client->addr, + .flags = 0, + .len = 2, + .buf = wdbuf, + }, + }; + + wdbuf[0] = addr; + wdbuf[1] = reg_data; + + if(NULL == aw3644_flashlight_client) + { + pr_err("msg %s aw3644_flashlight_client is NULL\n", __func__); + return -1; + } + + ret = i2c_transfer(aw3644_flashlight_client->adapter, msgs, 1); + if (ret < 0) + pr_err("msg %s i2c read error: %d\n", __func__, ret); + + return ret; +} + +unsigned char I2C_read_reg(unsigned char addr) +{ + unsigned char ret; + u8 rdbuf[512] = {0}; + + struct i2c_msg msgs[] = { + { + .addr = aw3644_flashlight_client->addr, + .flags = 0, + .len = 1, + .buf = rdbuf, + }, + { + .addr = aw3644_flashlight_client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = rdbuf, + }, + }; + + rdbuf[0] = addr; + + if(NULL == aw3644_flashlight_client) + { + pr_err("msg %s aw3644_flashlight_client is NULL\n", __func__); + return -1; + } + + ret = i2c_transfer(aw3644_flashlight_client->adapter, msgs, 2); + if (ret < 0) + pr_err("msg %s i2c read error: %d\n", __func__, ret); + + return rdbuf[0]; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// AW3644 Debug +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +unsigned char aw3644_hwen_on(void) +{ + printk("%s enter\n", __func__); + flashlight_gpio_set(FLASHLIGHT_PIN_HWEN, STATE_LOW); + msleep(5); + flashlight_gpio_set(FLASHLIGHT_PIN_HWEN, STATE_HIGH); + msleep(10); + printk("%s exit\n", __func__); + + return 0; +} + +unsigned char aw3644_hwen_off(void) +{ + printk("%s enter\n", __func__); + flashlight_gpio_set(FLASHLIGHT_PIN_HWEN, STATE_LOW); + msleep(5); + printk("%s exit\n", __func__); + + return 0; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//AW3644 Debug file +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static ssize_t aw3644_get_reg(struct device* cd,struct device_attribute *attr, char* buf) +{ + unsigned char reg_val; + unsigned char i; + ssize_t len = 0; + + for(i=0;i<0x0E;i++) + { + reg_val = I2C_read_reg(i); + len += snprintf(buf+len, PAGE_SIZE-len, "reg%2X = 0x%2X, ", i,reg_val); + } + + len += snprintf(buf+len, PAGE_SIZE-len, "\r\n"); + + return len; +} + +static ssize_t aw3644_set_reg(struct device* cd, struct device_attribute *attr, const char* buf, size_t len) +{ + unsigned int databuf[2]; + if(2 == sscanf(buf,"%x %x",&databuf[0], &databuf[1])) + { + i2c_write_reg(databuf[0],databuf[1]); + } + return len; +} + +static ssize_t aw3644_get_hwen(struct device* cd,struct device_attribute *attr, char* buf) +{ + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "aw3644_hwen_on(void)\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "echo 1 > hwen\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "aw3644_hwen_off(void)\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "echo 0 > hwen\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "\n"); + + return len; +} + +static ssize_t aw3644_set_hwen(struct device* cd, struct device_attribute *attr, const char* buf, size_t len) +{ + int databuf[16]; + + sscanf(buf,"%d",&databuf[0]); + if(databuf[0] == 0) { // OFF + aw3644_hwen_off(); + } else { // ON + aw3644_hwen_on(); + } + + return len; +} + + +static int aw3644_create_sysfs(struct i2c_client *client) +{ + int err; + struct device *dev = &(client->dev); + + err = device_create_file(dev, &dev_attr_reg); + err = device_create_file(dev, &dev_attr_hwen); + + return err; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static int aw3644_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + unsigned char reg_chipid, reg_devid; + unsigned char cnt = 3; + int err = 0; + + printk("%s enter\n", __func__); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + err = -ENODEV; + goto exit_check_functionality_failed; + } + + aw3644_flashlight_client = client; + + aw3644_hwen_on(); + + while(cnt>0) + { + reg_chipid = I2C_read_reg(0x00); + reg_devid = I2C_read_reg(0x0C); + printk("aw3644 i2c read chipid=0x%2x, deveice id=0x%02x\n", reg_chipid, reg_devid); + if((reg_chipid == 0x36) && ((reg_devid&0x18) == 0x00)) + { + break; + } + else + { + printk("aw3644 i2c read fail\n"); + } + cnt --; + msleep(10); + } + if(!cnt) + { + ktd2685_use = 1; + //err = -ENODEV; + //aw3644_hwen_off(); + //goto exit_create_singlethread; + } + + aw3644_create_sysfs(client); + + aw3644_hwen_off(); + + return 0; + +//exit_create_singlethread: + aw3644_flashlight_client = NULL; +exit_check_functionality_failed: + return err; +} + +static int aw3644_i2c_remove(struct i2c_client *client) +{ + aw3644_flashlight_client = NULL; + return 0; +} + +static const struct i2c_device_id aw3644_i2c_id[] = { + { AW3644_I2C_NAME, 0 }, + { } +}; + +#ifdef CONFIG_OF +static const struct of_device_id aw3644_i2c_of_match[] = { + {.compatible = "mediatek,strobe_main"}, + {}, +}; +#endif + +static struct i2c_driver aw3644_i2c_driver = { + .driver = { + .name = AW3644_I2C_NAME, +#ifdef CONFIG_OF + .of_match_table = aw3644_i2c_of_match, +#endif +}, + + .probe = aw3644_i2c_probe, + .remove = aw3644_i2c_remove, + .id_table = aw3644_i2c_id, +}; +/* +static int aw3644_flashlight_probe(struct platform_device *pdev) +{ + int ret = 0; + + printk("%s enter!\n", __func__); + + ret = aw3644_pinctrl_init(pdev); + if (ret != 0) { + printk("[%s] failed to init aw3644 pinctrl.\n", __func__); + return ret; + } else { + printk("[%s] Success to init aw3644 pinctrl.\n", __func__); + } + + ret = i2c_add_driver(&aw3644_i2c_driver); + if (ret != 0) { + printk("[%s] failed to register aw3644 i2c driver.\n", __func__); + return ret; + } else { + printk("[%s] Success to register aw3644 i2c driver.\n", __func__); + } + + return ret; +} + +static int aw3644_flashlight_remove(struct platform_device *pdev) +{ + printk("%s enter\n", __func__); + i2c_del_driver(&aw3644_i2c_driver); + printk("%s exit\n", __func__); + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id aw3644_plt_of_match[] = { + {.compatible = "mediatek,aw3644_flashlight"}, + {}, +}; +#endif + +static struct platform_driver aw3644_flashlight_driver = { + .probe = aw3644_flashlight_probe, + .remove = aw3644_flashlight_remove, + .driver = { + .name = "aw3644_flashlight", +#ifdef CONFIG_OF + .of_match_table = aw3644_plt_of_match, +#endif + } +}; +*/ +static int __init aw3644_flashlight_init(void) { + + printk("%s enter \n", __func__); + return i2c_add_driver(&aw3644_i2c_driver); +/* ret = platform_driver_register(&aw3644_flashlight_driver); + if (ret) { + printk("****[%s] Unable to register driver (%d)\n", __func__, ret); + return ret; + } + + return ret; +*/ +} + +static void __exit aw3644_flashlight_exit(void) { + printk("%s enter \n", __func__); + return i2c_del_driver(&aw3644_i2c_driver); + //platform_driver_unregister(&aw3644_flashlight_driver); +} + +module_init(aw3644_flashlight_init); +module_exit(aw3644_flashlight_exit); + +MODULE_AUTHOR(""); +MODULE_DESCRIPTION("AWINIC AW3644 Flash Light Driver"); +MODULE_LICENSE("GPL v2"); + + +/***************************************************************************** +Dual-flash functions +*****************************************************************************/ +enum +{ + e_DutyNum = 26, +}; + +static bool g_IsTorch[26] = { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 }; +/*static char g_TorchDutyCode[26] = { 0x0F, 0x20, 0x31, 0x42, 0x52, 0x63, +*/ +static char g_TorchDutyCode[26] = { 0x06, 0x0f, 0x17, 0x1f, 0x27, 0x2f, + 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; + +static char g_FlashDutyCode[26] = { 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, + 0x0D, 0x10, 0x14, 0x19, 0x1D, 0x21, + 0x25, 0x2A, 0x2E, 0x32, 0x37, 0x3B, + 0x3F, 0x43, 0x48, 0x4C, 0x4E, 0x50, + 0x52, 0x54 }; +static char g_EnableReg; +static int g_duty1 = -1; +static int g_duty2 = -1; + +int flashEnable_aw3644_2(void) +{ + int ret; + unsigned char buf[2]; + + buf[0] = 0x01; /* Enable Register */ + if (g_IsTorch[g_duty2] == 1) /* LED1 in torch mode */ + g_EnableReg |= (0x09); + else + g_EnableReg |= (0x0D); + buf[1] = g_EnableReg; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int flashEnable_aw3644_1(void) +{ + int ret; + unsigned char buf[2]; + + buf[0] = 0x01; /* Enable Register */ + if (g_IsTorch[g_duty1] == 1) /* LED2 in torch mode */ + g_EnableReg |= (0x0A); + else + g_EnableReg |= (0x0E); + buf[1] = g_EnableReg; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int flashDisable_aw3644_2(void) +{ + int ret; + unsigned char buf[2]; + + buf[0] = 0x01; /* Enable Register */ + if ((g_EnableReg&0x02) == 0x02) /* LED2 enabled */ + g_EnableReg &= (~0x01); + else + g_EnableReg &= (~0x0D); + buf[1] = g_EnableReg; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int flashDisable_aw3644_1(void) +{ + int ret; + unsigned char buf[2]; + + buf[0] = 0x01; /* Enable Register */ + if ((g_EnableReg&0x01) == 0x01) /* LED1 enabled */ + g_EnableReg &= (~0x02); + else + g_EnableReg &= (~0x0E); + buf[1] = g_EnableReg; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int setDuty_aw3644_2(int duty) +{ + int ret; + unsigned char buf[2]; + + if (duty < 0) + duty = 0; + else if (duty >= e_DutyNum) + duty = e_DutyNum-1; + + g_duty2 = duty; +#if 0 + if (duty == 0) /* LED1 in torch mode */ + { + buf[0] = 0x03; /* LED1 Flash Brightness Register */ + buf[1] = 0x01; + ret = i2c_write_reg(buf[0], buf[1]); + buf[0] = 0x05; /* LED1 Torch Brightness Register */ + buf[1] = 0x01; + ret = i2c_write_reg(buf[0], buf[1]); + } + else +#endif + { + buf[0] = 0x05; /* LED1 Torch Brightness Register */ + buf[1] = g_TorchDutyCode[duty]; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x03; /* LED1 Flash Brightness Register */ + buf[1] = g_FlashDutyCode[duty]; + ret = i2c_write_reg(buf[0], buf[1]); + } + return ret; +} + +int setDuty_aw3644_1(int duty) +{ + int ret; + unsigned char buf[2]; + + if (duty < 0) + duty = 0; + else if (duty >= e_DutyNum) + duty = e_DutyNum-1; + + g_duty1 = duty; + buf[0] = 0x06; /* LED2 Torch Brightness Register */ + buf[1] = g_TorchDutyCode[duty]; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x04; /* LED2 Flash Brightness Register */ + buf[1] = g_FlashDutyCode[duty]; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int init_aw3644(void) +{ + int ret; + char buf[2]; + + aw3644_hwen_on(); + + buf[0] = 0x01; /* Enable Register */ + buf[1] = 0x00; + g_EnableReg = buf[1]; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x03; /* LED1 Flash Brightness Register */ + buf[1] = 0x3F; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x05; /* LED2 Flash Brightness Register */ + buf[1] = 0x3F; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x08; /* Timing Configuration Register */ + buf[1] = 0x1F; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int FL_Enable(void) +{ + PK_DBG(" FL_Enable line=%d\n", __LINE__); + return flashEnable_aw3644_1(); +} + + + +int FL_Disable(void) +{ + PK_DBG(" FL_Disable line=%d\n", __LINE__); + return flashDisable_aw3644_1(); +} + +int FL_dim_duty(kal_uint32 duty) +{ + PK_DBG(" FL_dim_duty line=%d\n", __LINE__); + return setDuty_aw3644_1(duty); +} + +int FL_Init(void) +{ + PK_DBG(" FL_Init line=%d\n", __LINE__); + init_aw3644(); + return 0; +} + +int FL_Uninit(void) +{ + FL_Disable(); + aw3644_hwen_off(); + return 0; +} + +/***************************************************************************** +User interface +*****************************************************************************/ + +static void work_timeOutFunc(struct work_struct *data) +{ + FL_Disable(); + PK_DBG("ledTimeOut_callback\n"); +} + + + +enum hrtimer_restart ledTimeOutCallback(struct hrtimer *timer) +{ + schedule_work(&workTimeOut); + return HRTIMER_NORESTART; +} +static struct hrtimer g_timeOutTimer; +void timerInit(void) +{ + static int init_flag; + + if (init_flag == 0) { + init_flag = 1; + INIT_WORK(&workTimeOut, work_timeOutFunc); + g_timeOutTimeMs = 1000; + hrtimer_init(&g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + g_timeOutTimer.function = ledTimeOutCallback; + } +} + + + +static int constant_flashlight_ioctl(unsigned int cmd, unsigned long arg) +{ + int i4RetValue = 0; + int ior_shift; + int iow_shift; + int iowr_shift; + + ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC, 0, int)); + iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC, 0, int)); + iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC, 0, int)); +/* PK_DBG + ("LM3643 constant_flashlight_ioctl() line=%d ior_shift=%d, iow_shift=%d iowr_shift=%d arg=%d\n", + __LINE__, ior_shift, iow_shift, iowr_shift, (int)arg); +*/ + switch (cmd) { + + case FLASH_IOC_SET_TIME_OUT_TIME_MS: + PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n", (int)arg); + g_timeOutTimeMs = arg; + break; + + + case FLASH_IOC_SET_DUTY: + PK_DBG("FLASHLIGHT_DUTY: %d\n", (int)arg); + FL_dim_duty(arg); + break; + + + case FLASH_IOC_SET_STEP: + PK_DBG("FLASH_IOC_SET_STEP: %d\n", (int)arg); + + break; + + case FLASH_IOC_SET_ONOFF: + PK_DBG("FLASHLIGHT_ONOFF: %d\n", (int)arg); + if (arg == 1) { + + int s; + int ms; + + if (g_timeOutTimeMs > 1000) { + s = g_timeOutTimeMs / 1000; + ms = g_timeOutTimeMs - s * 1000; + } else { + s = 0; + ms = g_timeOutTimeMs; + } + + if (g_timeOutTimeMs != 0) { + ktime_t ktime; + + ktime = ktime_set(s, ms * 1000000); + hrtimer_start(&g_timeOutTimer, ktime, HRTIMER_MODE_REL); + } + FL_Enable(); + } else { + FL_Disable(); + hrtimer_cancel(&g_timeOutTimer); + } + break; + default: + PK_DBG(" No such command\n"); + i4RetValue = -EPERM; + break; + } + return i4RetValue; +} + + + + +static int constant_flashlight_open(void *pArg) +{ + int i4RetValue = 0; + + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + if (0 == strobe_Res) { + FL_Init(); + timerInit(); + } + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + spin_lock_irq(&g_strobeSMPLock); + + + if (strobe_Res) { + PK_DBG(" busy!\n"); + i4RetValue = -EBUSY; + } else { + strobe_Res += 1; + } + + + spin_unlock_irq(&g_strobeSMPLock); + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + return i4RetValue; + +} + + +static int constant_flashlight_release(void *pArg) +{ + PK_DBG(" constant_flashlight_release\n"); + + if (strobe_Res) { + spin_lock_irq(&g_strobeSMPLock); + + strobe_Res = 0; + strobe_Timeus = 0; + + /* LED On Status */ + g_strobe_On = FALSE; + + spin_unlock_irq(&g_strobeSMPLock); + + FL_Uninit(); + } + + PK_DBG(" Done\n"); + + return 0; + +} + + +FLASHLIGHT_FUNCTION_STRUCT constantFlashlightFunc = { + constant_flashlight_open, + constant_flashlight_release, + constant_flashlight_ioctl +}; + + +MUINT32 constantFlashlightInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &constantFlashlightFunc; + return 0; +} + + + +/* LED flash control for high current capture mode*/ +ssize_t strobe_VDIrq(void) +{ + + return 0; +} +EXPORT_SYMBOL(strobe_VDIrq); diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p386/constant_flashlight/Makefile b/drivers/misc/mediatek/flashlight/src/mt6755/p386/constant_flashlight/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..e1f69061aef578727b484b6a9dd05c61ac4aab43 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p386/constant_flashlight/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for misc devices that really don't fit anywhere else. +# + +obj-y += leds_strobe.o diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p386/constant_flashlight/leds_strobe.c b/drivers/misc/mediatek/flashlight/src/mt6755/p386/constant_flashlight/leds_strobe.c new file mode 100755 index 0000000000000000000000000000000000000000..0fe68e4379b96047899d3553cf41223d28baf7e5 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p386/constant_flashlight/leds_strobe.c @@ -0,0 +1,810 @@ +/************************************************************************** +* aw3644_flashlight.c +* +* Create Date : +* +* Modify Date : +* +* Create by : AWINIC Technology CO., LTD +* +* Version : 0.9, 2016/05/15 +**************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "kd_flashlight.h" +#include "kd_flashlight_type.h" +#include +#include +#include +/****************************************************************************** + * Debug configuration +******************************************************************************/ + +#define TAG_NAME "[leds_strobe.c]" +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) + +#define DEBUG_LEDS_STROBE + +#ifdef DEBUG_LEDS_STROBE + #define PK_DBG PK_DBG_FUNC +#else + #define PK_DBG(a, ...) +#endif +/****************************************************************************** + * local variables +******************************************************************************/ +static DEFINE_SPINLOCK(g_strobeSMPLock); /* cotta-- SMP proection */ + +static u32 strobe_Res; +static u32 strobe_Timeus; +static BOOL g_strobe_On; + +static int g_timeOutTimeMs; + +static struct work_struct workTimeOut; +/***************************************************************************** +Functions +*****************************************************************************/ +static void work_timeOutFunc(struct work_struct *data); +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define AW3644_I2C_NAME "AW3644_FLASHLIGHT" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +unsigned char aw3644_hw_on(void); +unsigned char aw3644_hw_off(void); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static ssize_t aw3644_get_reg(struct device* cd,struct device_attribute *attr, char* buf); +static ssize_t aw3644_set_reg(struct device* cd, struct device_attribute *attr,const char* buf, size_t len); +static ssize_t aw3644_set_hwen(struct device* cd, struct device_attribute *attr,const char* buf, size_t len); +static ssize_t aw3644_get_hwen(struct device* cd, struct device_attribute *attr, char* buf); + +static DEVICE_ATTR(reg, 0660, aw3644_get_reg, aw3644_set_reg); +static DEVICE_ATTR(hwen, 0660, aw3644_get_hwen, aw3644_set_hwen); + +struct i2c_client *aw3644_flashlight_client; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// i2c write and read +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +unsigned char i2c_write_reg(unsigned char addr, unsigned char reg_data) +{ + char ret; + u8 wdbuf[512] = {0}; + + struct i2c_msg msgs[] = { + { + .addr = aw3644_flashlight_client->addr, + .flags = 0, + .len = 2, + .buf = wdbuf, + }, + }; + + wdbuf[0] = addr; + wdbuf[1] = reg_data; + + if(NULL == aw3644_flashlight_client) + { + pr_err("msg %s aw3644_flashlight_client is NULL\n", __func__); + return -1; + } + + ret = i2c_transfer(aw3644_flashlight_client->adapter, msgs, 1); + if (ret < 0) + pr_err("msg %s i2c read error: %d\n", __func__, ret); + + return ret; +} + +unsigned char I2C_read_reg(unsigned char addr) +{ + unsigned char ret; + u8 rdbuf[512] = {0}; + + struct i2c_msg msgs[] = { + { + .addr = aw3644_flashlight_client->addr, + .flags = 0, + .len = 1, + .buf = rdbuf, + }, + { + .addr = aw3644_flashlight_client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = rdbuf, + }, + }; + + rdbuf[0] = addr; + + if(NULL == aw3644_flashlight_client) + { + pr_err("msg %s aw3644_flashlight_client is NULL\n", __func__); + return -1; + } + + ret = i2c_transfer(aw3644_flashlight_client->adapter, msgs, 2); + if (ret < 0) + pr_err("msg %s i2c read error: %d\n", __func__, ret); + + return rdbuf[0]; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// AW3644 Debug +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +unsigned char aw3644_hwen_on(void) +{ + printk("%s enter\n", __func__); + flashlight_gpio_set(FLASHLIGHT_PIN_HWEN, STATE_LOW); + msleep(5); + flashlight_gpio_set(FLASHLIGHT_PIN_HWEN, STATE_HIGH); + msleep(10); + printk("%s exit\n", __func__); + + return 0; +} + +unsigned char aw3644_hwen_off(void) +{ + printk("%s enter\n", __func__); + flashlight_gpio_set(FLASHLIGHT_PIN_HWEN, STATE_LOW); + msleep(5); + printk("%s exit\n", __func__); + + return 0; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//AW3644 Debug file +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static ssize_t aw3644_get_reg(struct device* cd,struct device_attribute *attr, char* buf) +{ + unsigned char reg_val; + unsigned char i; + ssize_t len = 0; + + for(i=0;i<0x0E;i++) + { + reg_val = I2C_read_reg(i); + len += snprintf(buf+len, PAGE_SIZE-len, "reg%2X = 0x%2X, ", i,reg_val); + } + + len += snprintf(buf+len, PAGE_SIZE-len, "\r\n"); + + return len; +} + +static ssize_t aw3644_set_reg(struct device* cd, struct device_attribute *attr, const char* buf, size_t len) +{ + unsigned int databuf[2]; + if(2 == sscanf(buf,"%x %x",&databuf[0], &databuf[1])) + { + i2c_write_reg(databuf[0],databuf[1]); + } + return len; +} + +static ssize_t aw3644_get_hwen(struct device* cd,struct device_attribute *attr, char* buf) +{ + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "aw3644_hwen_on(void)\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "echo 1 > hwen\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "aw3644_hwen_off(void)\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "echo 0 > hwen\n"); + len += snprintf(buf+len, PAGE_SIZE-len, "\n"); + + return len; +} + +static ssize_t aw3644_set_hwen(struct device* cd, struct device_attribute *attr, const char* buf, size_t len) +{ + int databuf[16]; + + sscanf(buf,"%d",&databuf[0]); + if(databuf[0] == 0) { // OFF + aw3644_hwen_off(); + } else { // ON + aw3644_hwen_on(); + } + + return len; +} + + +static int aw3644_create_sysfs(struct i2c_client *client) +{ + int err; + struct device *dev = &(client->dev); + + err = device_create_file(dev, &dev_attr_reg); + err = device_create_file(dev, &dev_attr_hwen); + + return err; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static int aw3644_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + unsigned char reg_chipid, reg_devid; + unsigned char cnt = 5; + int err = 0; + + printk("%s enter\n", __func__); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + err = -ENODEV; + goto exit_check_functionality_failed; + } + + aw3644_flashlight_client = client; + + aw3644_hwen_on(); + + while(cnt>0) + { + reg_chipid = I2C_read_reg(0x00); + reg_devid = I2C_read_reg(0x0C); + printk("aw3644 i2c read chipid=0x%2x, deveice id=0x%02x\n", reg_chipid, reg_devid); + if((reg_chipid == 0x36) && ((reg_devid&0x18) == 0x00)) + { + break; + } + else + { + printk("aw3644 i2c read id is error\n"); + } + cnt --; + msleep(10); + } + if(!cnt) + { + err = -ENODEV; + aw3644_hwen_off(); + goto exit_create_singlethread; + } + + aw3644_create_sysfs(client); + + aw3644_hwen_off(); + + return 0; + +exit_create_singlethread: + aw3644_flashlight_client = NULL; +exit_check_functionality_failed: + return err; +} + +static int aw3644_i2c_remove(struct i2c_client *client) +{ + aw3644_flashlight_client = NULL; + return 0; +} + +static const struct i2c_device_id aw3644_i2c_id[] = { + { AW3644_I2C_NAME, 0 }, + { } +}; + +#ifdef CONFIG_OF +static const struct of_device_id aw3644_i2c_of_match[] = { + {.compatible = "mediatek,strobe_main"}, + {}, +}; +#endif + +static struct i2c_driver aw3644_i2c_driver = { + .driver = { + .name = AW3644_I2C_NAME, +#ifdef CONFIG_OF + .of_match_table = aw3644_i2c_of_match, +#endif +}, + + .probe = aw3644_i2c_probe, + .remove = aw3644_i2c_remove, + .id_table = aw3644_i2c_id, +}; +/* +static int aw3644_flashlight_probe(struct platform_device *pdev) +{ + int ret = 0; + + printk("%s enter!\n", __func__); + + ret = aw3644_pinctrl_init(pdev); + if (ret != 0) { + printk("[%s] failed to init aw3644 pinctrl.\n", __func__); + return ret; + } else { + printk("[%s] Success to init aw3644 pinctrl.\n", __func__); + } + + ret = i2c_add_driver(&aw3644_i2c_driver); + if (ret != 0) { + printk("[%s] failed to register aw3644 i2c driver.\n", __func__); + return ret; + } else { + printk("[%s] Success to register aw3644 i2c driver.\n", __func__); + } + + return ret; +} + +static int aw3644_flashlight_remove(struct platform_device *pdev) +{ + printk("%s enter\n", __func__); + i2c_del_driver(&aw3644_i2c_driver); + printk("%s exit\n", __func__); + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id aw3644_plt_of_match[] = { + {.compatible = "mediatek,aw3644_flashlight"}, + {}, +}; +#endif + +static struct platform_driver aw3644_flashlight_driver = { + .probe = aw3644_flashlight_probe, + .remove = aw3644_flashlight_remove, + .driver = { + .name = "aw3644_flashlight", +#ifdef CONFIG_OF + .of_match_table = aw3644_plt_of_match, +#endif + } +}; +*/ +static int __init aw3644_flashlight_init(void) { + + printk("%s enter \n", __func__); + return i2c_add_driver(&aw3644_i2c_driver); +/* ret = platform_driver_register(&aw3644_flashlight_driver); + if (ret) { + printk("****[%s] Unable to register driver (%d)\n", __func__, ret); + return ret; + } + + return ret; +*/ +} + +static void __exit aw3644_flashlight_exit(void) { + printk("%s enter \n", __func__); + return i2c_del_driver(&aw3644_i2c_driver); + //platform_driver_unregister(&aw3644_flashlight_driver); +} + +module_init(aw3644_flashlight_init); +module_exit(aw3644_flashlight_exit); + +MODULE_AUTHOR(""); +MODULE_DESCRIPTION("AWINIC AW3644 Flash Light Driver"); +MODULE_LICENSE("GPL v2"); + + +/***************************************************************************** +Dual-flash functions +*****************************************************************************/ +enum +{ + e_DutyNum = 26, +}; + +static bool g_IsTorch[26] = { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 }; +/*static char g_TorchDutyCode[26] = { 0x0F, 0x20, 0x31, 0x42, 0x52, 0x63, +*/ +static char g_TorchDutyCode[26] = { 0x06, 0x0f, 0x17, 0x1f, 0x27, 0x2f, + 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; + +static char g_FlashDutyCode[26] = { 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, + 0x0D, 0x10, 0x14, 0x19, 0x1D, 0x21, + 0x25, 0x2A, 0x2E, 0x32, 0x37, 0x3B, + 0x3F, 0x43, 0x48, 0x4C, 0x4E, 0x50, + 0x52, 0x54 }; +static char g_EnableReg; +static int g_duty1 = -1; +static int g_duty2 = -1; + +int flashEnable_aw3644_1(void) +{ + int ret; + unsigned char buf[2]; + + buf[0] = 0x01; /* Enable Register */ + if (g_IsTorch[g_duty1] == 1) /* LED1 in torch mode */ + g_EnableReg |= (0x09); + else + g_EnableReg |= (0x0D); + buf[1] = g_EnableReg; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int flashEnable_aw3644_2(void) +{ + int ret; + unsigned char buf[2]; + + buf[0] = 0x01; /* Enable Register */ + if (g_IsTorch[g_duty2] == 1) /* LED2 in torch mode */ + g_EnableReg |= (0x0A); + else + g_EnableReg |= (0x0E); + buf[1] = g_EnableReg; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int flashDisable_aw3644_1(void) +{ + int ret; + unsigned char buf[2]; + + buf[0] = 0x01; /* Enable Register */ + if ((g_EnableReg&0x02) == 0x02) /* LED2 enabled */ + g_EnableReg &= (~0x01); + else + g_EnableReg &= (~0x0D); + buf[1] = g_EnableReg; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int flashDisable_aw3644_2(void) +{ + int ret; + unsigned char buf[2]; + + buf[0] = 0x01; /* Enable Register */ + if ((g_EnableReg&0x01) == 0x01) /* LED1 enabled */ + g_EnableReg &= (~0x02); + else + g_EnableReg &= (~0x0E); + buf[1] = g_EnableReg; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int setDuty_aw3644_1(int duty) +{ + int ret; + unsigned char buf[2]; + + if (duty < 0) + duty = 0; + else if (duty >= e_DutyNum) + duty = e_DutyNum-1; + + g_duty1 = duty; +#if 0 + if (duty == 0) /* LED1 in torch mode */ + { + buf[0] = 0x03; /* LED1 Flash Brightness Register */ + buf[1] = 0x01; + ret = i2c_write_reg(buf[0], buf[1]); + buf[0] = 0x05; /* LED1 Torch Brightness Register */ + buf[1] = 0x01; + ret = i2c_write_reg(buf[0], buf[1]); + } + else +#endif + { + buf[0] = 0x05; /* LED1 Torch Brightness Register */ + buf[1] = g_TorchDutyCode[duty]; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x03; /* LED1 Flash Brightness Register */ + buf[1] = g_FlashDutyCode[duty]; + ret = i2c_write_reg(buf[0], buf[1]); + } + return ret; +} + +int setDuty_aw3644_2(int duty) +{ + int ret; + unsigned char buf[2]; + + if (duty < 0) + duty = 0; + else if (duty >= e_DutyNum) + duty = e_DutyNum-1; + + g_duty2 = duty; + buf[0] = 0x06; /* LED2 Torch Brightness Register */ + buf[1] = g_TorchDutyCode[duty]; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x04; /* LED2 Flash Brightness Register */ + buf[1] = g_FlashDutyCode[duty]; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int init_aw3644(void) +{ + int ret; + char buf[2]; + + aw3644_hwen_on(); + + buf[0] = 0x01; /* Enable Register */ + buf[1] = 0x00; + g_EnableReg = buf[1]; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x03; /* LED1 Flash Brightness Register */ + buf[1] = 0x3F; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x05; /* LED2 Flash Brightness Register */ + buf[1] = 0x3F; + ret = i2c_write_reg(buf[0], buf[1]); + + buf[0] = 0x08; /* Timing Configuration Register */ + buf[1] = 0x1F; + ret = i2c_write_reg(buf[0], buf[1]); + return ret; +} + +int FL_Enable(void) +{ + PK_DBG(" FL_Enable line=%d\n", __LINE__); + return flashEnable_aw3644_1(); +} + + + +int FL_Disable(void) +{ + PK_DBG(" FL_Disable line=%d\n", __LINE__); + return flashDisable_aw3644_1(); +} + +int FL_dim_duty(kal_uint32 duty) +{ + PK_DBG(" FL_dim_duty line=%d\n", __LINE__); + return setDuty_aw3644_1(duty); +} + +int FL_Init(void) +{ + PK_DBG(" FL_Init line=%d\n", __LINE__); + init_aw3644(); + return 0; +} + +int FL_Uninit(void) +{ + FL_Disable(); + aw3644_hwen_off(); + return 0; +} + +/***************************************************************************** +User interface +*****************************************************************************/ + +static void work_timeOutFunc(struct work_struct *data) +{ + FL_Disable(); + PK_DBG("ledTimeOut_callback\n"); +} + + + +enum hrtimer_restart ledTimeOutCallback(struct hrtimer *timer) +{ + schedule_work(&workTimeOut); + return HRTIMER_NORESTART; +} +static struct hrtimer g_timeOutTimer; +void timerInit(void) +{ + static int init_flag; + + if (init_flag == 0) { + init_flag = 1; + INIT_WORK(&workTimeOut, work_timeOutFunc); + g_timeOutTimeMs = 1000; + hrtimer_init(&g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + g_timeOutTimer.function = ledTimeOutCallback; + } +} + + + +static int constant_flashlight_ioctl(unsigned int cmd, unsigned long arg) +{ + int i4RetValue = 0; + int ior_shift; + int iow_shift; + int iowr_shift; + + ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC, 0, int)); + iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC, 0, int)); + iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC, 0, int)); +/* PK_DBG + ("LM3643 constant_flashlight_ioctl() line=%d ior_shift=%d, iow_shift=%d iowr_shift=%d arg=%d\n", + __LINE__, ior_shift, iow_shift, iowr_shift, (int)arg); +*/ + switch (cmd) { + + case FLASH_IOC_SET_TIME_OUT_TIME_MS: + PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n", (int)arg); + g_timeOutTimeMs = arg; + break; + + + case FLASH_IOC_SET_DUTY: + PK_DBG("FLASHLIGHT_DUTY: %d\n", (int)arg); + FL_dim_duty(arg); + break; + + + case FLASH_IOC_SET_STEP: + PK_DBG("FLASH_IOC_SET_STEP: %d\n", (int)arg); + + break; + + case FLASH_IOC_SET_ONOFF: + PK_DBG("FLASHLIGHT_ONOFF: %d\n", (int)arg); + if (arg == 1) { + + int s; + int ms; + + if (g_timeOutTimeMs > 1000) { + s = g_timeOutTimeMs / 1000; + ms = g_timeOutTimeMs - s * 1000; + } else { + s = 0; + ms = g_timeOutTimeMs; + } + + if (g_timeOutTimeMs != 0) { + ktime_t ktime; + + ktime = ktime_set(s, ms * 1000000); + hrtimer_start(&g_timeOutTimer, ktime, HRTIMER_MODE_REL); + } + FL_Enable(); + } else { + FL_Disable(); + hrtimer_cancel(&g_timeOutTimer); + } + break; + default: + PK_DBG(" No such command\n"); + i4RetValue = -EPERM; + break; + } + return i4RetValue; +} + + + + +static int constant_flashlight_open(void *pArg) +{ + int i4RetValue = 0; + + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + if (0 == strobe_Res) { + FL_Init(); + timerInit(); + } + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + spin_lock_irq(&g_strobeSMPLock); + + + if (strobe_Res) { + PK_DBG(" busy!\n"); + i4RetValue = -EBUSY; + } else { + strobe_Res += 1; + } + + + spin_unlock_irq(&g_strobeSMPLock); + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + return i4RetValue; + +} + + +static int constant_flashlight_release(void *pArg) +{ + PK_DBG(" constant_flashlight_release\n"); + + if (strobe_Res) { + spin_lock_irq(&g_strobeSMPLock); + + strobe_Res = 0; + strobe_Timeus = 0; + + /* LED On Status */ + g_strobe_On = FALSE; + + spin_unlock_irq(&g_strobeSMPLock); + + FL_Uninit(); + } + + PK_DBG(" Done\n"); + + return 0; + +} + + +FLASHLIGHT_FUNCTION_STRUCT constantFlashlightFunc = { + constant_flashlight_open, + constant_flashlight_release, + constant_flashlight_ioctl +}; + + +MUINT32 constantFlashlightInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &constantFlashlightFunc; + return 0; +} + + + +/* LED flash control for high current capture mode*/ +ssize_t strobe_VDIrq(void) +{ + + return 0; +} +EXPORT_SYMBOL(strobe_VDIrq); diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/constant_flashlight/Makefile b/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/constant_flashlight/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..e1f69061aef578727b484b6a9dd05c61ac4aab43 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/constant_flashlight/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for misc devices that really don't fit anywhere else. +# + +obj-y += leds_strobe.o diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/constant_flashlight/leds_strobe.c b/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/constant_flashlight/leds_strobe.c new file mode 100755 index 0000000000000000000000000000000000000000..7d756d685746ef9a9e30163881e1edd2a847c114 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/constant_flashlight/leds_strobe.c @@ -0,0 +1,313 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_flashlight.h" +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +#include +#include + + + +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ + +#define TAG_NAME "[leds_strobe.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + +/*#define DEBUG_LEDS_STROBE*/ +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#else +#define PK_DBG(a, ...) +#endif + +/****************************************************************************** + * local variables +******************************************************************************/ + +static DEFINE_SPINLOCK(g_strobeSMPLock); /* cotta-- SMP proection */ + + +static u32 strobe_Res; +static u32 strobe_Timeus; +static BOOL g_strobe_On; + +static int g_duty = 0; +static int g_timeOutTimeMs; + +static DEFINE_MUTEX(g_strobeSem); + + + + +static struct work_struct workTimeOut; + +/* #define FLASH_GPIO_ENF GPIO12 */ +/* #define FLASH_GPIO_ENT GPIO13 */ + + +/***************************************************************************** +Functions +*****************************************************************************/ +static void work_timeOutFunc(struct work_struct *data); + + +//struct platform_device *flashlight_plt_dev = NULL; + + +int FL_Enable(void) +{ + PK_DBG("%s line %d \n",__func__,__LINE__); + if(g_duty < 1) + { + flashlight_gpio_set(FLASHLIGHT_PIN_TORCH,STATE_HIGH); + flashlight_gpio_set(FLASHLIGHT_PIN_FLASH,STATE_LOW); + } + else + { + flashlight_gpio_set(FLASHLIGHT_PIN_TORCH,STATE_HIGH); + flashlight_gpio_set(FLASHLIGHT_PIN_FLASH,STATE_HIGH); + } + return 0; +} + + + +int FL_Disable(void) +{ + PK_DBG("%s line %d \n",__func__,__LINE__); + flashlight_gpio_set(FLASHLIGHT_PIN_TORCH,STATE_LOW); + flashlight_gpio_set(FLASHLIGHT_PIN_FLASH,STATE_LOW); + return 0; +} + +int FL_dim_duty(kal_uint32 duty) +{ + PK_DBG(" FL_dim_duty line=%d\n", __LINE__); + g_duty = duty; + return 0; +} + + + + +int FL_Init(void) +{ + PK_DBG(KERN_ERR "%s line %d \n",__func__,__LINE__); + flashlight_gpio_set(FLASHLIGHT_PIN_TORCH,STATE_LOW); + flashlight_gpio_set(FLASHLIGHT_PIN_FLASH,STATE_LOW); + return 0; +} + + +int FL_Uninit(void) +{ + FL_Disable(); + return 0; +} + +/***************************************************************************** +User interface +*****************************************************************************/ + +static void work_timeOutFunc(struct work_struct *data) +{ + FL_Disable(); + PK_DBG("ledTimeOut_callback\n"); +} + + + +enum hrtimer_restart ledTimeOutCallback(struct hrtimer *timer) +{ + schedule_work(&workTimeOut); + return HRTIMER_NORESTART; +} + +static struct hrtimer g_timeOutTimer; +void timerInit(void) +{ + INIT_WORK(&workTimeOut, work_timeOutFunc); + g_timeOutTimeMs = 1000; + hrtimer_init(&g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + g_timeOutTimer.function = ledTimeOutCallback; +} + + + +static int constant_flashlight_ioctl(unsigned int cmd, unsigned long arg) +{ + int i4RetValue = 0; + int ior_shift; + int iow_shift; + int iowr_shift; + + ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC, 0, int)); + iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC, 0, int)); + iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC, 0, int)); +/* PK_DBG + ("LM3642 constant_flashlight_ioctl() line=%d ior_shift=%d, iow_shift=%d iowr_shift=%d arg=%d\n", + __LINE__, ior_shift, iow_shift, iowr_shift, (int)arg); +*/ + switch (cmd) { + + case FLASH_IOC_SET_TIME_OUT_TIME_MS: + PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n", (int)arg); + g_timeOutTimeMs = arg; + break; + + + case FLASH_IOC_SET_DUTY: + PK_DBG("FLASHLIGHT_DUTY: %d\n", (int)arg); + FL_dim_duty(arg); + break; + + + case FLASH_IOC_SET_STEP: + PK_DBG("FLASH_IOC_SET_STEP: %d\n", (int)arg); + + break; + + case FLASH_IOC_SET_ONOFF: + PK_DBG("FLASHLIGHT_ONOFF: %d\n", (int)arg); + if (arg == 1) { + + int s; + int ms; + + if (g_timeOutTimeMs > 1000) { + s = g_timeOutTimeMs / 1000; + ms = g_timeOutTimeMs - s * 1000; + } else { + s = 0; + ms = g_timeOutTimeMs; + } + + if (g_timeOutTimeMs != 0) { + ktime_t ktime; + + ktime = ktime_set(s, ms * 1000000); + hrtimer_start(&g_timeOutTimer, ktime, HRTIMER_MODE_REL); + } + FL_Enable(); + } else { + FL_Disable(); + hrtimer_cancel(&g_timeOutTimer); + } + break; + default: + PK_DBG(" No such command\n"); + i4RetValue = -EPERM; + break; + } + return i4RetValue; +} + + + + +static int constant_flashlight_open(void *pArg) +{ + int i4RetValue = 0; + + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + if (0 == strobe_Res) { + FL_Init(); + timerInit(); + } + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + spin_lock_irq(&g_strobeSMPLock); + + + if (strobe_Res) { + PK_DBG(" busy!\n"); + i4RetValue = -EBUSY; + } else { + strobe_Res += 1; + } + + + spin_unlock_irq(&g_strobeSMPLock); + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + return i4RetValue; + +} + + +static int constant_flashlight_release(void *pArg) +{ + PK_DBG(" constant_flashlight_release\n"); + + if (strobe_Res) { + spin_lock_irq(&g_strobeSMPLock); + + strobe_Res = 0; + strobe_Timeus = 0; + + /* LED On Status */ + g_strobe_On = FALSE; + + spin_unlock_irq(&g_strobeSMPLock); + + FL_Uninit(); + } + + PK_DBG(" Done\n"); + + return 0; + +} + + +FLASHLIGHT_FUNCTION_STRUCT constantFlashlightFunc = { + constant_flashlight_open, + constant_flashlight_release, + constant_flashlight_ioctl +}; + + +MUINT32 constantFlashlightInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &constantFlashlightFunc; + return 0; +} + + + +/* LED flash control for high current capture mode*/ +ssize_t strobe_VDIrq(void) +{ + + return 0; +} +EXPORT_SYMBOL(strobe_VDIrq); diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/sub_flashlight/sub_strobe.c b/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/sub_flashlight/sub_strobe.c new file mode 100755 index 0000000000000000000000000000000000000000..d6b7fba4679b0df3dcaa516d7e86a2e224047be0 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/p389bf/sub_flashlight/sub_strobe.c @@ -0,0 +1,239 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_flashlight.h" +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +#include +#include + +/****************************************************************************** + * Debug configuration + ******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ +#define TAG_NAME "[sub_strobe.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + +/****************************************************************************** + * local variables + ******************************************************************************/ +static DEFINE_SPINLOCK(g_strobeSMPLock); /* cotta-- SMP proection */ + +static u32 strobe_Res; +static u32 strobe_Timeus; +static BOOL g_strobe_On; + +static int g_duty = 0; +static int g_timeOutTimeMs; + +static DEFINE_MUTEX(g_strobeSem); +static struct work_struct workTimeOut; + +/***************************************************************************** + Functions + *****************************************************************************/ +static void work_timeOutFunc(struct work_struct *data); + +static int FL_Enable(void) +{ + PK_DBG("%s line %d \n",__func__,__LINE__); + flashlight_gpio_set(SUB_FLASHLIGHT_PIN_FLASH,STATE_HIGH); + return 0; +} + +static int FL_Disable(void) +{ + PK_DBG("%s line %d \n",__func__,__LINE__); + flashlight_gpio_set(SUB_FLASHLIGHT_PIN_FLASH,STATE_LOW); + return 0; +} + +static int FL_dim_duty(kal_uint32 duty) +{ + PK_DBG(" FL_dim_duty line=%d\n", __LINE__); + g_duty = duty; + return 0; +} + +static int FL_Init(void) +{ + PK_DBG(KERN_ERR "%s line %d \n",__func__,__LINE__); + flashlight_gpio_set(SUB_FLASHLIGHT_PIN_FLASH,STATE_LOW); + return 0; +} + +static int FL_Uninit(void) +{ + FL_Disable(); + return 0; +} + +/***************************************************************************** + User interface + *****************************************************************************/ +static void work_timeOutFunc(struct work_struct *data) +{ + FL_Disable(); + PK_DBG("ledTimeOut_callback\n"); +} + +static enum hrtimer_restart ledTimeOutCallback(struct hrtimer *timer) +{ + schedule_work(&workTimeOut); + return HRTIMER_NORESTART; +} + +static struct hrtimer g_timeOutTimer; +static void timerInit(void) +{ + INIT_WORK(&workTimeOut, work_timeOutFunc); + g_timeOutTimeMs = 1000; + hrtimer_init(&g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + g_timeOutTimer.function = ledTimeOutCallback; +} + +static int sub_strobe_ioctl(unsigned int cmd, unsigned long arg) +{ + int i4RetValue = 0; + int ior_shift; + int iow_shift; + int iowr_shift; + + ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC, 0, int)); + iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC, 0, int)); + iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC, 0, int)); + switch (cmd) { + case FLASH_IOC_SET_TIME_OUT_TIME_MS: + PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n", (int)arg); + g_timeOutTimeMs = arg; + break; + case FLASH_IOC_SET_DUTY: + PK_DBG("FLASHLIGHT_DUTY: %d\n", (int)arg); + FL_dim_duty(arg); + break; + case FLASH_IOC_SET_STEP: + PK_DBG("FLASH_IOC_SET_STEP: %d\n", (int)arg); + break; + case FLASH_IOC_SET_ONOFF: + PK_DBG("FLASHLIGHT_ONOFF: %d\n", (int)arg); + if (arg == 1) { + int s; + int ms; + if (g_timeOutTimeMs > 1000) { + s = g_timeOutTimeMs / 1000; + ms = g_timeOutTimeMs - s * 1000; + } else { + s = 0; + ms = g_timeOutTimeMs; + } + if (g_timeOutTimeMs != 0) { + ktime_t ktime; + ktime = ktime_set(s, ms * 1000000); + hrtimer_start(&g_timeOutTimer, ktime, HRTIMER_MODE_REL); + } + FL_Enable(); + } else { + FL_Disable(); + hrtimer_cancel(&g_timeOutTimer); + } + break; + default: + PK_DBG(" No such command\n"); + i4RetValue = -EPERM; + break; + } + return i4RetValue; +} + +static int sub_strobe_open(void *pArg) +{ + int i4RetValue = 0; + + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + if (0 == strobe_Res) { + FL_Init(); + timerInit(); + } + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + spin_lock_irq(&g_strobeSMPLock); + if (strobe_Res) { + PK_DBG(" busy!\n"); + i4RetValue = -EBUSY; + } else { + strobe_Res += 1; + } + spin_unlock_irq(&g_strobeSMPLock); + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + return i4RetValue; +} + +static int sub_strobe_release(void *pArg) +{ + PK_DBG(" constant_flashlight_release\n"); + if (strobe_Res) { + spin_lock_irq(&g_strobeSMPLock); + strobe_Res = 0; + strobe_Timeus = 0; + /* LED On Status */ + g_strobe_On = FALSE; + spin_unlock_irq(&g_strobeSMPLock); + FL_Uninit(); + } + PK_DBG(" Done\n"); + return 0; +} + +FLASHLIGHT_FUNCTION_STRUCT subStrobeFunc = { + sub_strobe_open, + sub_strobe_release, + sub_strobe_ioctl +}; + +MUINT32 subStrobeInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &subStrobeFunc; + return 0; +} diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid1_part2.c b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid1_part2.c new file mode 100644 index 0000000000000000000000000000000000000000..322cb628e4d78f21d396d2d6afd2f39ffb93532f --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid1_part2.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#ifdef CONFIG_COMPAT + +#include +#include + +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include + +#include "kd_flashlight.h" +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ +#define TAG_NAME "[strobe_main_sid1_part2.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + + +static int strobe_ioctl(unsigned int cmd, unsigned long arg) +{ + PK_DBG("sub dummy ioctl"); + return 0; +} + +static int strobe_open(void *pArg) +{ + PK_DBG("sub dummy open"); + return 0; +} + +static int strobe_release(void *pArg) +{ + PK_DBG("sub dummy release"); + return 0; +} + +static FLASHLIGHT_FUNCTION_STRUCT strobeFunc = { + strobe_open, + strobe_release, + strobe_ioctl +}; + +MUINT32 strobeInit_main_sid1_part2(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &strobeFunc; + return 0; +} diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid2_part1.c b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid2_part1.c new file mode 100644 index 0000000000000000000000000000000000000000..c1f5121c7ed5445d914bdbc80d4748f05389d5ef --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid2_part1.c @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef CONFIG_COMPAT + +#include +#include + +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +/* #include */ + +#include "kd_flashlight.h" +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ +#define TAG_NAME "[strobe_main_sid2_part1.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + +/****************************************************************************** + * local variables +******************************************************************************/ +static DEFINE_SPINLOCK(g_strobeSMPLock); /* cotta-- SMP proection */ +static struct work_struct workTimeOut; +static int g_timeOutTimeMs; +static u32 strobe_Res; +/***************************************************************************** +Functions +*****************************************************************************/ +static void work_timeOutFunc(struct work_struct *data); + +/* extern int flashEnable_sky81296_2(void); */ +/* extern int flashDisable_sky81296_2(void); */ +/* extern int setDuty_sky81296_2(int duty); */ +/* int init_sky81296(); */ + + + +static int FL_Enable(void) +{ +/* flashEnable_sky81296_1(); */ + PK_DBG("FL_Enable-"); + + return 0; +} + +static int FL_Disable(void) +{ + /* flashDisable_sky81296_1(); */ + + return 0; +} + +static int FL_dim_duty(kal_uint32 duty) +{ + /* setDuty_sky81296_1(duty); */ + return 0; +} + +/* +static int g_lowPowerLevel=LOW_BATTERY_LEVEL_0; +static void lowPowerCB(LOW_BATTERY_LEVEL lev) +{ + g_lowPowerLevel=lev; +}*/ + +static int FL_Init(void) +{ + PK_DBG(" FL_Init line=%d\n", __LINE__); + INIT_WORK(&workTimeOut, work_timeOutFunc); + /* register_low_battery_callback(&lowPowerCB, LOW_BATTERY_PRIO_FLASHLIGHT); */ + /* register_low_battery_notify(&lowPowerCB, LOW_BATTERY_PRIO_FLASHLIGHT); */ + + + + return 0; +} + +static int FL_Uninit(void) +{ + FL_Disable(); + return 0; +} + +static int FL_hasLowPowerDetect(void) +{ + + return 1; +} + +static int detLowPowerStart(void) +{ + +/* g_lowPowerLevel=LOW_BATTERY_LEVEL_0; */ + return 0; +} + + +static int detLowPowerEnd(void) +{ + + return 0; +} + +/***************************************************************************** +User interface +*****************************************************************************/ +static struct hrtimer g_timeOutTimer; + +static int g_b1stInit = 1; + +static void work_timeOutFunc(struct work_struct *data) +{ + FL_Disable(); + PK_DBG("ledTimeOut_callback\n"); +} + + + +static enum hrtimer_restart ledTimeOutCallback(struct hrtimer *timer) +{ + schedule_work(&workTimeOut); + return HRTIMER_NORESTART; +} + +static void timerInit(void) +{ + /* ktime_t ktime; */ + + + /* mt6333_set_rg_chrwdt_en(0); */ + + /* mt6333_set_rg_chrwdt_td(0); //4 sec */ + /* mt6333_set_rg_chrwdt_en(1); */ + + /* mt6333_set_rg_chrwdt_en(0); */ + + if (g_b1stInit == 1) { + g_b1stInit = 0; + + + INIT_WORK(&workTimeOut, work_timeOutFunc); + g_timeOutTimeMs = 1000; + hrtimer_init(&g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + g_timeOutTimer.function = ledTimeOutCallback; + } + + + +} + + +static int constant_flashlight_ioctl(unsigned int cmd, unsigned long arg) +{ + int temp; + int i4RetValue = 0; + int ior_shift; + int iow_shift; + int iowr_shift; + /* kal_uint8 valTemp; */ + ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC, 0, int)); + iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC, 0, int)); + iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC, 0, int)); + PK_DBG + ("constant_flashlight_ioctl() line=%d ior_shift=%d, iow_shift=%d iowr_shift=%d arg=%d\n", + __LINE__, ior_shift, iow_shift, iowr_shift, (int)arg); + switch (cmd) { + + case FLASH_IOC_SET_TIME_OUT_TIME_MS: + PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n", (int)arg); + g_timeOutTimeMs = arg; + break; + + + case FLASH_IOC_SET_DUTY: + PK_DBG("FLASHLIGHT_DUTY: %d\n", (int)arg); + FL_dim_duty(arg); + break; + + + case FLASH_IOC_SET_STEP: + PK_DBG("FLASH_IOC_SET_STEP: %d\n", (int)arg); + + break; + + case FLASH_IOC_SET_ONOFF: + PK_DBG("FLASHLIGHT_ONOFF: %d\n", (int)arg); + if (arg == 1) { + if (g_timeOutTimeMs != 0) { + ktime_t ktime; + + ktime = ktime_set(0, g_timeOutTimeMs * 1000000); + hrtimer_start(&g_timeOutTimer, ktime, HRTIMER_MODE_REL); + } + FL_Enable(); + } else { + FL_Disable(); + hrtimer_cancel(&g_timeOutTimer); + } + break; +/* + case FLASH_IOC_PRE_ON: + PK_DBG("FLASH_IOC_PRE_ON\n"); + FL_preOn(); + break; + case FLASH_IOC_GET_PRE_ON_TIME_MS: + PK_DBG("FLASH_IOC_GET_PRE_ON_TIME_MS: %d\n",(int)arg); + temp=13; + if(copy_to_user((void __user *) arg , (void*)&temp , 4)) + { + PK_DBG(" ioctl copy to user failed\n"); + return -1; + } + break; +*/ + case FLASH_IOC_SET_REG_ADR: + PK_DBG("FLASH_IOC_SET_REG_ADR: %d\n", (int)arg); + /* g_reg = arg; */ + break; + case FLASH_IOC_SET_REG_VAL: + PK_DBG("FLASH_IOC_SET_REG_VAL: %d\n", (int)arg); + /* g_val = arg; */ + break; + case FLASH_IOC_SET_REG: + /* PK_DBG("FLASH_IOC_SET_REG: %d %d\n",g_reg, g_val); */ + + break; + + case FLASH_IOC_GET_REG: + PK_DBG("FLASH_IOC_GET_REG: %d\n", (int)arg); + + /* i4RetValue = valTemp; */ + /* PK_DBG("FLASH_IOC_GET_REG: v=%d\n",valTemp); */ + break; + + case FLASH_IOC_HAS_LOW_POWER_DETECT: + PK_DBG("FLASH_IOC_HAS_LOW_POWER_DETECT"); + temp = FL_hasLowPowerDetect(); + if (copy_to_user((void __user *)arg, (void *)&temp, 4)) { + PK_DBG(" ioctl copy to user failed\n"); + return -1; + } + break; + case FLASH_IOC_LOW_POWER_DETECT_START: + detLowPowerStart(); + break; + case FLASH_IOC_LOW_POWER_DETECT_END: + i4RetValue = detLowPowerEnd(); + break; + + default: + PK_DBG(" No such command\n"); + i4RetValue = -EPERM; + break; + } + return i4RetValue; +} + + + + +static int constant_flashlight_open(void *pArg) +{ + int i4RetValue = 0; + + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + if (0 == strobe_Res) { + FL_Init(); + timerInit(); + } + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + spin_lock_irq(&g_strobeSMPLock); + + + if (strobe_Res) { + PK_ERR(" busy!\n"); + i4RetValue = -EBUSY; + } else { + strobe_Res += 1; + } + + + spin_unlock_irq(&g_strobeSMPLock); + PK_DBG("constant_flashlight_open line=%d\n", __LINE__); + + return i4RetValue; + +} + + +static int constant_flashlight_release(void *pArg) +{ + PK_DBG(" constant_flashlight_release\n"); + + if (strobe_Res) { + spin_lock_irq(&g_strobeSMPLock); + + strobe_Res = 0; + + + spin_unlock_irq(&g_strobeSMPLock); + FL_Uninit(); + } + PK_DBG(" Done\n"); + return 0; +} + + +static FLASHLIGHT_FUNCTION_STRUCT constantFlashlightFunc = { + constant_flashlight_open, + constant_flashlight_release, + constant_flashlight_ioctl +}; + + + +MUINT32 strobeInit_main_sid2_part1(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &constantFlashlightFunc; + return 0; +} diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid2_part2.c b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid2_part2.c new file mode 100644 index 0000000000000000000000000000000000000000..43b78a096410fbbd94c593e5a85e0a6f592bdc4b --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_main_sid2_part2.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +#ifdef CONFIG_COMPAT +#include +#include +#endif +#include "kd_flashlight.h" +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ +#define TAG_NAME "[strobe_main_sid2_part2.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + + +static int sub_strobe_ioctl(unsigned int cmd, unsigned long arg) +{ + PK_DBG("sub dummy ioctl"); + return 0; +} + +static int sub_strobe_open(void *pArg) +{ + PK_DBG("sub dummy open"); + return 0; + +} + +static int sub_strobe_release(void *pArg) +{ + PK_DBG("sub dummy release"); + return 0; + +} + +static FLASHLIGHT_FUNCTION_STRUCT subStrobeFunc = { + sub_strobe_open, + sub_strobe_release, + sub_strobe_ioctl +}; + + +MUINT32 strobeInit_main_sid2_part2(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &subStrobeFunc; + return 0; +} diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/strobe_part_id.c b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_part_id.c new file mode 100644 index 0000000000000000000000000000000000000000..7955951b4195f76d9601b6955364be91e6d58a59 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_part_id.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#ifdef CONFIG_COMPAT +#include +#include +#endif +#include "kd_flashlight.h" + +int strobe_getPartId(int sensorDev, int strobeId) +{ + /* return 1 or 2 (backup flash part). Other numbers are invalid. */ + if (sensorDev == e_CAMERA_MAIN_SENSOR && strobeId == 1) + return 1; + else if (sensorDev == e_CAMERA_MAIN_SENSOR && strobeId == 2) + return 1; + else if (sensorDev == e_CAMERA_SUB_SENSOR && strobeId == 1) + return 1; + else if (sensorDev == e_CAMERA_SUB_SENSOR && strobeId == 2) + return 1; + /* else sensorDev == e_CAMERA_MAIN_2_SENSOR */ + return 200; +} diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid1_part2.c b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid1_part2.c new file mode 100644 index 0000000000000000000000000000000000000000..c8496b62eee0af6b9c5709594f94d2966298a261 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid1_part2.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include + +#ifdef CONFIG_COMPAT +#include +#include +#endif +#include "kd_flashlight.h" +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ +#define TAG_NAME "[strobe_sub_sid1_part2.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + + +static int strobe_ioctl(unsigned int cmd, unsigned long arg) +{ + PK_DBG("sub dummy ioctl"); + return 0; +} + + +static int strobe_open(void *pArg) +{ + PK_DBG("sub dummy open"); + return 0; +} + +static int strobe_release(void *pArg) +{ + PK_DBG("sub dummy release"); + return 0; +} + +static FLASHLIGHT_FUNCTION_STRUCT strobeFunc = { + strobe_open, + strobe_release, + strobe_ioctl +}; + +MUINT32 strobeInit_sub_sid1_part2(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &strobeFunc; + return 0; +} diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid2_part1.c b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid2_part1.c new file mode 100644 index 0000000000000000000000000000000000000000..33bf933822d89848bcccd3a69696019465dd7383 --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid2_part1.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +#ifdef CONFIG_COMPAT +#include +#include +#endif +#include "kd_flashlight.h" +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ +#define TAG_NAME "[strobe_sub_sid2_part1.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + + +static int sub_strobe_ioctl(unsigned int cmd, unsigned long arg) +{ + PK_DBG("sub dummy ioctl"); + return 0; +} + +static int sub_strobe_open(void *pArg) +{ + PK_DBG("sub dummy open"); + return 0; + +} + +static int sub_strobe_release(void *pArg) +{ + PK_DBG("sub dummy release"); + return 0; + +} + +static FLASHLIGHT_FUNCTION_STRUCT subStrobeFunc = { + sub_strobe_open, + sub_strobe_release, + sub_strobe_ioctl +}; + + +MUINT32 strobeInit_sub_sid2_part1(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &subStrobeFunc; + return 0; +} diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid2_part2.c b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid2_part2.c new file mode 100644 index 0000000000000000000000000000000000000000..32bd64fa97aa5820994d515ad7008fdf2354bf0b --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/strobe_sub_sid2_part2.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +#ifdef CONFIG_COMPAT +#include +#include +#endif +#include "kd_flashlight.h" +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ +#define TAG_NAME "[strobe_sub_sid2_part2.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + + +static int sub_strobe_ioctl(unsigned int cmd, unsigned long arg) +{ + PK_DBG("sub dummy ioctl"); + return 0; +} + +static int sub_strobe_open(void *pArg) +{ + PK_DBG("sub dummy open"); + return 0; + +} + +static int sub_strobe_release(void *pArg) +{ + PK_DBG("sub dummy release"); + return 0; + +} + +static FLASHLIGHT_FUNCTION_STRUCT subStrobeFunc = { + sub_strobe_open, + sub_strobe_release, + sub_strobe_ioctl +}; + + +MUINT32 strobeInit_sub_sid2_part2(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &subStrobeFunc; + return 0; +} diff --git a/drivers/misc/mediatek/flashlight/src/mt6755/sub_strobe.c b/drivers/misc/mediatek/flashlight/src/mt6755/sub_strobe.c new file mode 100644 index 0000000000000000000000000000000000000000..f429f1751e291ac85f2bdd539ae11cb39d06fe1b --- /dev/null +++ b/drivers/misc/mediatek/flashlight/src/mt6755/sub_strobe.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#include +#include +#include +#ifdef CONFIG_COMPAT +#include +#include +#endif +#include "kd_flashlight.h" +/****************************************************************************** + * Debug configuration +******************************************************************************/ +/* availible parameter */ +/* ANDROID_LOG_ASSERT */ +/* ANDROID_LOG_ERROR */ +/* ANDROID_LOG_WARNING */ +/* ANDROID_LOG_INFO */ +/* ANDROID_LOG_DEBUG */ +/* ANDROID_LOG_VERBOSE */ +#define TAG_NAME "[sub_strobe.c]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_WARN(fmt, arg...) pr_warn(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_NOTICE(fmt, arg...) pr_notice(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_INFO(fmt, arg...) pr_info(TAG_NAME "%s: " fmt, __func__ , ##arg) +#define PK_TRC_FUNC(f) pr_debug(TAG_NAME "<%s>\n", __func__) +#define PK_TRC_VERBOSE(fmt, arg...) pr_debug(TAG_NAME fmt, ##arg) +#define PK_ERROR(fmt, arg...) pr_err(TAG_NAME "%s: " fmt, __func__ , ##arg) + +#define DEBUG_LEDS_STROBE +#ifdef DEBUG_LEDS_STROBE +#define PK_DBG PK_DBG_FUNC +#define PK_VER PK_TRC_VERBOSE +#define PK_ERR PK_ERROR +#else +#define PK_DBG(a, ...) +#define PK_VER(a, ...) +#define PK_ERR(a, ...) +#endif + + +static int sub_strobe_ioctl(unsigned int cmd, unsigned long arg) +{ + PK_DBG("sub dummy ioctl"); + return 0; +} + +static int sub_strobe_open(void *pArg) +{ + PK_DBG("sub dummy open"); + return 0; + +} + +static int sub_strobe_release(void *pArg) +{ + PK_DBG("sub dummy release"); + return 0; + +} + +FLASHLIGHT_FUNCTION_STRUCT subStrobeFunc = { + sub_strobe_open, + sub_strobe_release, + sub_strobe_ioctl +}; + + +MUINT32 subStrobeInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc) +{ + if (pfFunc != NULL) + *pfFunc = &subStrobeFunc; + return 0; +} diff --git a/drivers/misc/mediatek/freqhopping/mt6755/Makefile b/drivers/misc/mediatek/freqhopping/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f6b28fe2303297a4851a6e70c55139a3a397d567 --- /dev/null +++ b/drivers/misc/mediatek/freqhopping/mt6755/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/dramc/$(MTK_PLATFORM)/ +obj-y := mt_freqhopping.o + diff --git a/drivers/misc/mediatek/freqhopping/mt6755/mt_freqhopping.c b/drivers/misc/mediatek/freqhopping/mt6755/mt_freqhopping.c new file mode 100644 index 0000000000000000000000000000000000000000..69fbc7108ebe3c207bf55a9d97a0d7857991b156 --- /dev/null +++ b/drivers/misc/mediatek/freqhopping/mt6755/mt_freqhopping.c @@ -0,0 +1,1651 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MET_USER_EVENT_SUPPORT +/* Pending on MET to check in +#include +*/ + +#include "mach/mt_freqhopping.h" +#include "mach/mt_fhreg.h" +/*#include "mach/mt_clkmgr.h"*/ +/*#include "mach/mt_typedefs.h"*/ +/*#include "mach/mt_gpio.h"*/ +/*#include "mach/mt_gpufreq.h"*/ +/*#include "mach/mt_cpufreq.h"*/ +/*#include "mach/emi_bwl.h"*/ +#include "sync_write.h" +/*#include "mach/mt_sleep.h"*/ +#include "mt_freqhopping_drv.h" +/*#include */ +#include +#include "mt_cpufreq_hybrid.h" +#include "mt_dramc.h" + +#ifdef CONFIG_OF +#include +static void __iomem *g_fhctl_base; +static void __iomem *g_apmixed_base; +static void __iomem *g_ddrphy_base; +#endif + +/* masks */ +#define MASK_FRDDSX_DYS (0xFU<<20) +#define MASK_FRDDSX_DTS (0xFU<<16) +#define FH_FHCTLX_SRHMODE (0x1U<<5) +#define FH_SFSTRX_BP (0x1U<<4) +#define FH_SFSTRX_EN (0x1U<<2) +#define FH_FRDDSX_EN (0x1U<<1) +#define FH_FHCTLX_EN (0x1U<<0) +#define FH_FHCTLX_CFG_PAUSE (0x1U<<4) +#define FH_FRDDSX_DNLMT (0xFFU<<16) +#define FH_FRDDSX_UPLMT (0xFFU) +#define FH_FHCTLX_PLL_TGL_ORG (0x1U<<31) +#define FH_FHCTLX_PLL_ORG (0xFFFFFU) +#define FH_FHCTLX_PAUSE (0x1U<<31) +#define FH_FHCTLX_PRD (0x1U<<30) +#define FH_SFSTRX_PRD (0x1U<<29) +#define FH_FRDDSX_PRD (0x1U<<28) +#define FH_FHCTLX_STATE (0xFU<<24) +#define FH_FHCTLX_PLL_CHG (0x1U<<21) +#define FH_FHCTLX_PLL_DDS (0xFFFFFU) + +#define USER_DEFINE_SETTING_ID (1) + +#define MASK21b (0x1FFFFF) +#define BIT32 (1U<<31) + +static DEFINE_SPINLOCK(g_fh_lock); + +#define PERCENT_TO_DDSLMT(dDS, pERCENT_M10) (((dDS * pERCENT_M10) >> 5) / 100) + +static unsigned int g_initialize; + +#ifndef PER_PROJECT_FH_SETTING + +/* +default VCO freq. +TODO: fix these ==> Unnecessary to fix, not in use +*/ +#define ARMCA15PLL_DEF_FREQ 1976000 +#define ARMCA7PLL_DEF_FREQ 1599000 +#define MAINPLL_DEF_FREQ 1092000 +#define MEMPLL_DEF_FREQ 160000 /* It is 160Mbps provided from DRAM expert. */ +#define MMPLL_DEF_FREQ 1092000 +#define MPLL_DEF_FREQ 208000 /* For MP32 used, freq is 208MHz */ +#define VENCPLL_DEF_FREQ 1518002 +#define MSDCPLL_DEF_FREQ 1600000 +#define TVDPLL_DEF_FREQ 1782000 + +/* keep track the status of each PLL */ +static fh_pll_t g_fh_pll[FH_PLL_NUM] = { + /* Enable SSC for RF desense */ + {FH_FH_ENABLE_SSC, FH_PLL_ENABLE, 0, ARMCA15PLL_DEF_FREQ, 0}, + /* Enable SSC for RF desense */ + {FH_FH_ENABLE_SSC, FH_PLL_ENABLE, 0, ARMCA7PLL_DEF_FREQ, 0}, + {FH_FH_DISABLE, FH_PLL_ENABLE, 0, MAINPLL_DEF_FREQ, 0}, +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* Enable SSC for RF desense */ + {FH_FH_ENABLE_SSC, FH_PLL_ENABLE, 0, MEMPLL_DEF_FREQ, 0}, +#else + {FH_FH_DISABLE, FH_PLL_ENABLE, 0, MEMPLL_DEF_FREQ, 0}, +#endif + /* MMPLL SSC > GPU perf fail */ + {FH_FH_DISABLE, FH_PLL_ENABLE, 0, MMPLL_DEF_FREQ, 0}, + {FH_FH_DISABLE, FH_PLL_ENABLE, 0, MPLL_DEF_FREQ, 0}, + {FH_FH_DISABLE, FH_PLL_ENABLE, 0, VENCPLL_DEF_FREQ, 0}, + {FH_FH_DISABLE, FH_PLL_ENABLE, 0, MSDCPLL_DEF_FREQ, 0}, + /* TVDPLL SSC > MHL fail */ + {FH_FH_DISABLE, FH_PLL_ENABLE, 0, TVDPLL_DEF_FREQ, 0} +}; + +/* The initial values of freqhopping_ssc.freq and freqhopping_ssc.dds have no meanings */ +static const struct freqhopping_ssc ssc_armca7pll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {ARMCA7PLL_DEF_FREQ, 0, 9, 0, 1, 0xF6000}, /* 0 ~ -1% */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const struct freqhopping_ssc ssc_mpll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {MPLL_DEF_FREQ, 0, 9, 0, 8, 0x1C000}, /* 0 ~ -8% */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const struct freqhopping_ssc ssc_mainpll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {MAINPLL_DEF_FREQ, 0, 9, 0, 8, 0xA8000}, /* 0 ~ -8% */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const struct freqhopping_ssc ssc_mempll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {MEMPLL_DEF_FREQ, 0, 6, 0, 4, 0x1C000}, /* 0 ~ -4% *//* Df changed to 6 */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const struct freqhopping_ssc ssc_msdcpll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {MSDCPLL_DEF_FREQ, 0, 9, 0, 8, 0xF6276}, /* 0 ~ -8% */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const struct freqhopping_ssc ssc_mmpll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {MMPLL_DEF_FREQ, 0, 9, 0, 8, 0xD8000}, /* 0 ~ -8% */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const struct freqhopping_ssc ssc_vencpll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {VENCPLL_DEF_FREQ, 0, 9, 0, 8, 0xE989E}, /* 0 ~ -8% */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const struct freqhopping_ssc ssc_tvdpll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {TVDPLL_DEF_FREQ, 0, 9, 0, 8, 0x112276}, /* 0 ~ -8% */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const struct freqhopping_ssc ssc_armca15pll_setting[] = { + {0, 0, 0, 0, 0, 0},/* Means disable */ + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* Means User-Define */ + {ARMCA15PLL_DEF_FREQ, 0, 9, 0, 1, 0x130000}, /* 0 ~ -1% */ + {0, 0, 0, 0, 0, 0} /* EOF */ +}; + +static const unsigned int g_default_freq[] = { + ARMCA15PLL_DEF_FREQ, ARMCA7PLL_DEF_FREQ, + MAINPLL_DEF_FREQ, MEMPLL_DEF_FREQ, MMPLL_DEF_FREQ, MPLL_DEF_FREQ, + VENCPLL_DEF_FREQ, MSDCPLL_DEF_FREQ, TVDPLL_DEF_FREQ, +}; + +/* TODO: check the settings */ +static struct freqhopping_ssc mt_ssc_fhpll_userdefined[FH_PLL_NUM] = { + {0, 1, 1, 2, 2, 0}, + {0, 1, 1, 2, 2, 0}, + {0, 1, 1, 2, 2, 0}, + {0, 1, 1, 2, 2, 0}, + {0, 1, 1, 2, 2, 0}, + {0, 1, 1, 2, 2, 0}, + {0, 1, 1, 2, 2, 0}, + {0, 1, 1, 2, 2, 0}, + {0, 1, 1, 2, 2, 0} +}; + +static const int armpll_ssc_pmap[9] = {0, 11, 21, 31, 41, 52, 62, 72, 81}; + +#else/*PER_PROJECT_FH_SETTING*/ + +PER_PROJECT_FH_SETTING + +#endif/*PER_PROJECT_FH_SETTING*/ + +static const struct freqhopping_ssc *g_ssc_setting[] = { + ssc_armca15pll_setting, + ssc_armca7pll_setting, + ssc_mainpll_setting, + ssc_mempll_setting, + ssc_mmpll_setting, + ssc_mpll_setting, + ssc_vencpll_setting, + ssc_msdcpll_setting, + ssc_tvdpll_setting +}; + +static const unsigned int g_ssc_setting_size[] = { + sizeof(ssc_armca15pll_setting)/sizeof(ssc_armca15pll_setting[0]), + sizeof(ssc_armca7pll_setting)/sizeof(ssc_armca7pll_setting[0]), + sizeof(ssc_mainpll_setting)/sizeof(ssc_mainpll_setting[0]), + sizeof(ssc_mempll_setting)/sizeof(ssc_mempll_setting[0]), + sizeof(ssc_mmpll_setting)/sizeof(ssc_mmpll_setting[0]), + sizeof(ssc_mpll_setting)/sizeof(ssc_mpll_setting[0]), + sizeof(ssc_vencpll_setting)/sizeof(ssc_vencpll_setting[0]), + sizeof(ssc_msdcpll_setting)/sizeof(ssc_msdcpll_setting[0]), + sizeof(ssc_tvdpll_setting)/sizeof(ssc_tvdpll_setting[0]) +}; + +#ifdef CONFIG_OF +static unsigned long g_reg_dds[FH_PLL_NUM]; +static unsigned long g_reg_cfg[FH_PLL_NUM]; +static unsigned long g_reg_updnlmt[FH_PLL_NUM]; +static unsigned long g_reg_mon[FH_PLL_NUM]; +static unsigned long g_reg_dvfs[FH_PLL_NUM]; +static unsigned long g_reg_pll_con1[FH_PLL_NUM]; +#else + +static const unsigned long g_reg_pll_con1[] = { + REG_ARMCA15PLL_CON1, REG_ARMCA7PLL_CON1, REG_MAINPLL_CON1, + REG_MEMPLL_CON1, REG_MMPLL_CON1, REG_MPLL_CON1, + REG_VENCPLL_CON1, REG_MSDCPLL_CON1, REG_TVDPLL_CON1}; + +static const unsigned long g_reg_dds[] = { + REG_FHCTL0_DDS, REG_FHCTL1_DDS, REG_FHCTL2_DDS, + REG_FHCTL3_DDS, REG_FHCTL4_DDS, REG_FHCTL5_DDS, + REG_FHCTL6_DDS, REG_FHCTL7_DDS, REG_FHCTL8_DDS}; + +static const unsigned long g_reg_cfg[] = { + REG_FHCTL0_CFG, REG_FHCTL1_CFG, REG_FHCTL2_CFG, + REG_FHCTL3_CFG, REG_FHCTL4_CFG, REG_FHCTL5_CFG, + REG_FHCTL6_CFG, REG_FHCTL7_CFG, REG_FHCTL8_CFG}; + +static const unsigned long g_reg_updnlmt[] = { + REG_FHCTL0_UPDNLMT, REG_FHCTL1_UPDNLMT, REG_FHCTL2_UPDNLMT, + REG_FHCTL3_UPDNLMT, REG_FHCTL4_UPDNLMT, REG_FHCTL5_UPDNLMT, + REG_FHCTL6_UPDNLMT, REG_FHCTL7_UPDNLMT, REG_FHCTL8_UPDNLMT}; + +static const unsigned long g_reg_mon[] = { + REG_FHCTL0_MON, REG_FHCTL1_MON, REG_FHCTL2_MON, + REG_FHCTL3_MON, REG_FHCTL4_MON, REG_FHCTL5_MON, + REG_FHCTL6_MON, REG_FHCTL7_MON, REG_FHCTL8_MON}; + +static const unsigned long g_reg_dvfs[] = { + REG_FHCTL0_DVFS, REG_FHCTL1_DVFS, REG_FHCTL2_DVFS, + REG_FHCTL3_DVFS, REG_FHCTL4_DVFS, REG_FHCTL5_DVFS, + REG_FHCTL6_DVFS, REG_FHCTL7_DVFS, REG_FHCTL8_DVFS}; +#endif /* CONFIG_OF */ + +#define VALIDATE_PLLID(id) BUG_ON(id >= FH_PLL_NUM) + +/* +#define ENABLE_DVT_LTE_SIDEBAND_SIGNAL_TESTCASE +*/ + +/* caller: clk mgr */ +static void mt_fh_hal_default_conf(void) +{ + FH_MSG_DEBUG("%s", __func__); + + /* default enable ARMCA15 and ARMCA7 PLL SSC for RF desense problems. */ + freqhopping_config(FH_ARMCA15_PLLID, g_default_freq[FH_ARMCA15_PLLID], true); + freqhopping_config(FH_ARMCA7_PLLID, g_default_freq[FH_ARMCA7_PLLID], true); + /* default enable MEMPLL SSC for B41 2600MHz desense problems. */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + freqhopping_config(FH_MEM_PLLID, g_default_freq[FH_MEM_PLLID], true); +#endif + +#if 1 + /* Default turn off all PLL SSC on Jade */ + /* + freqhopping_config(FH_ARMCA15_PLLID, g_default_freq[FH_ARMCA15_PLLID], true); + freqhopping_config(FH_ARMCA7_PLLID, g_default_freq[FH_ARMCA7_PLLID], true); + freqhopping_config(FH_MAIN_PLLID, g_default_freq[FH_MAIN_PLLID], true); + freqhopping_config(FH_MEM_PLLID, g_default_freq[FH_MEM_PLLID], true); + freqhopping_config(FH_MM_PLLID, g_default_freq[FH_MM_PLLID], true); + freqhopping_config(FH_M_PLLID, g_default_freq[FH_M_PLLID], true); + freqhopping_config(FH_VENC_PLLID, g_default_freq[FH_VENC_PLLID], true); + freqhopping_config(FH_MSDC_PLLID, g_default_freq[FH_MSDC_PLLID], true); + freqhopping_config(FH_TVD_PLLID, g_default_freq[FH_TVD_PLLID], true); + */ +#endif + +#ifdef ENABLE_DVT_LTE_SIDEBAND_SIGNAL_TESTCASE + fh_set_field(REG_FHCTL1_DDS, (0x1FFFFFU<<0), 0X100000); /* Set default MPLL DDS */ + fh_set_field(REG_FHCTL1_DDS, (0x1U<<32), 1); + + fh_set_field(REG_FHCTL_HP_EN, (0x1U<<31), 1); /* Enable LTE Sideband signal */ + fh_set_field(REG_FHCTL_HP_EN, (0x1U<<1), 0x1); /* MPLL */ + + fh_set_field(REG_FHCTL1_CFG, (0x1U<<0), 1); /* Enable */ + fh_set_field(REG_FHCTL1_CFG, (0x1U<<3), 1); /* DYSSC Enable */ + + /* Set FHCTL_DSSC_CFG(0x1000CF14), Bit3 is RF3(LTE) SSC control. Clear to 0 is enable. */ + fh_set_field(REG_FHCTL_DSSC_CFG, (0x1U<<3), 0); + fh_set_field(REG_FHCTL_DSSC_CFG, (0x1U<<19), 0); /* RF(3) LTE BAN control */ + + /* + fh_set_field(REG_FHCTL_DSSC3_CON, (0x1U<<1), 1); + */ +#endif +} + +static void fh_switch2fhctl(enum FH_PLL_ID pll_id, int i_control) +{ + unsigned int mask = 0; + + VALIDATE_PLLID(pll_id); + + mask = 0x1U<> 10) & MASK21b)|BIT32); + } else { + fh_write32(reg_dst, (fh_read32(reg_src)&MASK21b)|BIT32); + } + return; +} + +static void __enable_ssc(unsigned int pll_id, const struct freqhopping_ssc *setting) +{ + unsigned long flags = 0; + const unsigned long reg_cfg = g_reg_cfg[pll_id]; + const unsigned long reg_updnlmt = g_reg_updnlmt[pll_id]; + const unsigned long reg_dds = g_reg_dds[pll_id]; + + FH_MSG_DEBUG("%s: %x~%x df:%d dt:%d dds:%x", + __func__, setting->lowbnd, setting->upbnd, + setting->df, setting->dt, setting->dds); + + mb(); + + g_fh_pll[pll_id].fh_status = FH_FH_ENABLE_SSC; + + local_irq_save(flags); + + /* Set the relative parameter registers (dt/df/upbnd/downbnd) */ + fh_set_field(reg_cfg, MASK_FRDDSX_DYS, setting->df); + fh_set_field(reg_cfg, MASK_FRDDSX_DTS, setting->dt); + + fh_sync_ncpo_to_fhctl_dds(pll_id); + + /* TODO: Not setting upper due to they are all 0? */ + fh_write32(reg_updnlmt, + (PERCENT_TO_DDSLMT((fh_read32(reg_dds)&MASK21b), setting->lowbnd) << 16)); + + if (pll_id == FH_ARMCA15_PLLID) { + fh_write32((unsigned long) g_apmixed_base+0x900, + (fh_read32((unsigned long) g_apmixed_base+0x900) & 0xFFFF00FF) + + (armpll_ssc_pmap[setting->lowbnd] << 8)); + } + if (pll_id == FH_ARMCA7_PLLID) { + fh_write32((unsigned long) g_apmixed_base+0x900, + (fh_read32((unsigned long) g_apmixed_base+0x900) & 0xFFFFFF00) + + (armpll_ssc_pmap[setting->lowbnd])); + } + + /* Switch to FHCTL */ + fh_switch2fhctl(pll_id, 1); + mb(); + + /* Enable SSC */ + fh_set_field(reg_cfg, FH_FRDDSX_EN, 1); + /* Enable Hopping control */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); + + local_irq_restore(flags); + + return; +} + +static void __disable_ssc(unsigned int pll_id, const struct freqhopping_ssc *ssc_setting) +{ + unsigned long flags = 0; + unsigned long reg_cfg = g_reg_cfg[pll_id]; + + FH_MSG_DEBUG("Calling %s", __func__); + + local_irq_save(flags); + + /* Set the relative registers */ + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); + if (pll_id == FH_ARMCA15_PLLID) { + fh_write32((unsigned long) g_apmixed_base+0x900, + (fh_read32((unsigned long) g_apmixed_base+0x900) & 0xFFFF00FF)); + } + if (pll_id == FH_ARMCA7_PLLID) { + fh_write32((unsigned long) g_apmixed_base+0x900, + (fh_read32((unsigned long) g_apmixed_base+0x900) & 0xFFFFFF00)); + } + mb(); + fh_switch2fhctl(pll_id, 0); + g_fh_pll[pll_id].fh_status = FH_FH_DISABLE; + local_irq_restore(flags); + mb(); + + return; +} + +/* freq is in KHz, return at which number of entry in mt_ssc_xxx_setting[] */ +static noinline int __freq_to_index(enum FH_PLL_ID pll_id, int freq) +{ + unsigned int retVal = 0; + unsigned int i = 2; /* 0 is disable, 1 is user defines, so start from 2 */ + const unsigned int size = g_ssc_setting_size[pll_id]; + + while (i < size) { + if (freq == g_ssc_setting[pll_id][i].freq) { + retVal = i; + break; + } + ++i; + } + + return retVal; +} + +static int __freqhopping_ctrl(struct freqhopping_ioctl *fh_ctl, bool enable) +{ + const struct freqhopping_ssc *pSSC_setting = NULL; + unsigned int ssc_setting_id = 0; + int retVal = 1; + fh_pll_t *pfh_pll = NULL; + + FH_MSG("%s for pll %d", __func__, fh_ctl->pll_id); + + /* check the out of range of frequency hopping PLL ID */ + VALIDATE_PLLID(fh_ctl->pll_id); + + pfh_pll = &g_fh_pll[fh_ctl->pll_id]; + + pfh_pll->curr_freq = g_default_freq[fh_ctl->pll_id]; + + if ((enable == true) && (pfh_pll->fh_status == FH_FH_ENABLE_SSC)) { + __disable_ssc(fh_ctl->pll_id, pSSC_setting); + } else if ((enable == false) && (pfh_pll->fh_status == FH_FH_DISABLE)) { + retVal = 0; + goto Exit; + } + + /* enable freq. hopping @ fh_ctl->pll_id */ + if (enable == true) { + if (pfh_pll->pll_status == FH_PLL_DISABLE) { + pfh_pll->fh_status = FH_FH_ENABLE_SSC; + retVal = 0; + goto Exit; + } else { + if (pfh_pll->user_defined == true) { + FH_MSG("Apply user defined setting"); + + pSSC_setting = &mt_ssc_fhpll_userdefined[fh_ctl->pll_id]; + pfh_pll->setting_id = USER_DEFINE_SETTING_ID; + } else { + if (pfh_pll->curr_freq != 0) { + ssc_setting_id = pfh_pll->setting_id = + __freq_to_index(fh_ctl->pll_id, pfh_pll->curr_freq); + } else { + ssc_setting_id = 0; + } + + if (ssc_setting_id == 0) { + FH_MSG("!!! No corresponding setting found !!!"); + + /* just disable FH & exit */ + __disable_ssc(fh_ctl->pll_id, pSSC_setting); + goto Exit; + } + + pSSC_setting = &g_ssc_setting[fh_ctl->pll_id][ssc_setting_id]; + } /* user defined */ + + if (pSSC_setting == NULL) { + FH_MSG("SSC_setting is NULL!"); + + /* disable FH & exit */ + __disable_ssc(fh_ctl->pll_id, pSSC_setting); + goto Exit; + } + + __enable_ssc(fh_ctl->pll_id, pSSC_setting); + retVal = 0; + } + } else { /* disable req. hopping @ fh_ctl->pll_id */ + __disable_ssc(fh_ctl->pll_id, pSSC_setting); + retVal = 0; + } + +Exit: + return retVal; +} + +static void wait_dds_stable( + unsigned int target_dds, + unsigned long reg_mon, + unsigned int wait_count) +{ + unsigned int fh_dds = 0; + unsigned int i = 0; + + fh_dds = fh_read32(reg_mon) & MASK21b; + while ((target_dds != fh_dds) && (i < wait_count)) { + udelay(10); + #if 0 + if (unlikely(i > 100)) { + BUG_ON(1); + break; + } + #endif + fh_dds = (fh_read32(reg_mon)) & MASK21b; + ++i; + } + FH_MSG_DEBUG("target_dds = %d, fh_dds = %d, i = %d", target_dds, fh_dds, i); +} + +static int mt_fh_hal_dvfs(enum FH_PLL_ID pll_id, unsigned int dds_value) +{ + unsigned long flags = 0; + + FH_MSG_DEBUG("%s for pll %d:", __func__, pll_id); + + VALIDATE_PLLID(pll_id); + + local_irq_save(flags); + + /* 1. sync ncpo to DDS of FHCTL */ + fh_sync_ncpo_to_fhctl_dds(pll_id); + + /* FH_MSG("1. sync ncpo to DDS of FHCTL"); */ + FH_MSG_DEBUG("FHCTL%d_DDS: 0x%08x", pll_id, + (fh_read32(g_reg_dds[pll_id])&MASK21b)); + + /* 2. enable DVFS and Hopping control */ + { + unsigned long reg_cfg = g_reg_cfg[pll_id]; + + fh_set_field(reg_cfg, FH_SFSTRX_EN, 1); /* enable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); /* enable hopping control */ + } + + /* + for slope setting. + TODO: Does this need to be changed? + */ + fh_write32(REG_FHCTL_SLOPE0, 0x6003c97); + + /* FH_MSG("2. enable DVFS and Hopping control"); */ + + /* 3. switch to hopping control */ + fh_switch2fhctl(pll_id, 1); + mb(); + + /* FH_MSG("3. switch to hopping control"); */ + + /* 4. set DFS DDS */ + { + unsigned long dvfs_req = g_reg_dvfs[pll_id]; + fh_write32(dvfs_req, (dds_value)|(BIT32)); /* set dds */ + +/* if (met_fh_dds) { + met_fh_dds[pll_id] = dds_value; + } + + if (met_fh_print_dds) { + met_fh_print_dds(pll_id, dds_value); + }*//* Pending on MET porting done */ + + /* FH_MSG("4. set DFS DDS"); */ + FH_MSG_DEBUG("FHCTL%d_DDS: 0x%08x", pll_id, (fh_read32(dvfs_req)&MASK21b)); + FH_MSG_DEBUG("FHCTL%d_DVFS: 0x%08x", pll_id, (fh_read32(dvfs_req)&MASK21b)); + } + + /* 4.1 ensure jump to target DDS */ + wait_dds_stable(dds_value, g_reg_mon[pll_id], 100); + /* FH_MSG("4.1 ensure jump to target DDS"); */ + + /* 5. write back to ncpo */ + /* FH_MSG("5. write back to ncpo"); */ + { + unsigned long reg_dvfs = 0; + unsigned long reg_pll_con1 = 0; + + if (pll_id == FH_MEM_PLLID) { + /* Jade MEMPLL CON1 reg is not same as other CON1. */ + reg_pll_con1 = g_reg_pll_con1[pll_id]; + reg_dvfs = g_reg_dvfs[pll_id]; + FH_MSG_DEBUG("MEMPLL_CON1: 0x%08x", (fh_read32(reg_pll_con1))); + + fh_write32(reg_pll_con1, + ((fh_read32(g_reg_mon[pll_id])&MASK21b) << 10) + /* left shift 10bit to [30:20] */ + |(fh_read32(reg_pll_con1)&0x80000000)|(BIT32)); + FH_MSG_DEBUG("MEMPLL_CON1: 0x%08x", (fh_read32(reg_pll_con1))); + } else { + reg_pll_con1 = g_reg_pll_con1[pll_id]; + reg_dvfs = g_reg_dvfs[pll_id]; + FH_MSG_DEBUG("PLL_CON1: 0x%08x", (fh_read32(reg_pll_con1)&MASK21b)); + + fh_write32(reg_pll_con1, + (fh_read32(g_reg_mon[pll_id])&MASK21b) + |(fh_read32(reg_pll_con1)&0xFFE00000)|(BIT32)); + FH_MSG_DEBUG("PLL_CON1: 0x%08x", (fh_read32(reg_pll_con1)&MASK21b)); + } + } + + /* 6. switch to register control */ + fh_switch2fhctl(pll_id, 0); + mb(); + + /* FH_MSG("6. switch to register control"); */ + + local_irq_restore(flags); + return 0; +} + +/* armpll dfs mdoe */ +static int mt_fh_hal_dfs_armpll(unsigned int pll, unsigned int dds) +{ + unsigned long flags = 0; + unsigned long reg_cfg = 0; + + if (g_initialize == 0) { + FH_MSG("(Warning) %s FHCTL isn't ready.", __func__); + return -1; + } + + FH_MSG_DEBUG("%s for pll %d dds %d", __func__, pll, dds); + + switch (pll) { + case FH_ARMCA15_PLLID: + case FH_ARMCA7_PLLID: + reg_cfg = g_reg_cfg[pll]; + FH_MSG_DEBUG("(PLL_CON1): 0x%x", (fh_read32(g_reg_pll_con1[pll])&MASK21b)); + break; + default: + BUG_ON(1); + return 1; + }; + + /* TODO: provelock issue spin_lock(&g_fh_lock); */ + spin_lock_irqsave(&g_fh_lock, flags); + +#if 0 + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); /* disable SSC mode */ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); /* disable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); /* disable hopping control */ +#else + if (g_fh_pll[pll].fh_status == FH_FH_ENABLE_SSC) { + unsigned int pll_dds = 0; + unsigned int fh_dds = 0; + + /* only when SSC is enable, turn off ARMPLL hopping */ + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); /* disable SSC mode */ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); /* disable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); /* disable hopping control */ + + pll_dds = (fh_read32(g_reg_dds[pll])) & MASK21b; + fh_dds = (fh_read32(g_reg_mon[pll])) & MASK21b; + + FH_MSG_DEBUG(">p:f< %x:%x", pll_dds, fh_dds); + + if (pll == FH_ARMCA15_PLLID) { + fh_write32((unsigned long) g_apmixed_base+0x900, + (fh_read32((unsigned long) g_apmixed_base+0x900) & 0xFFFF00FF)); + } + if (pll == FH_ARMCA7_PLLID) { + fh_write32((unsigned long) g_apmixed_base+0x900, + (fh_read32((unsigned long) g_apmixed_base+0x900) & 0xFFFFFF00)); + } + + wait_dds_stable(pll_dds, g_reg_mon[pll], 100); + } +#endif + + mt_fh_hal_dvfs(pll, dds); + +#if 0 + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); /* disable SSC mode */ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); /* disable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); /* disable hopping control */ +#else + if (g_fh_pll[pll].fh_status == FH_FH_ENABLE_SSC) { + const struct freqhopping_ssc *p_setting; + + if (pll == FH_ARMCA15_PLLID) + p_setting = &ssc_armca15pll_setting[2]; + else + p_setting = &ssc_armca7pll_setting[2]; + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); /* disable SSC mode */ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); /* disable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); /* disable hopping control */ + + fh_sync_ncpo_to_fhctl_dds(pll); + + FH_MSG_DEBUG("Enable armpll SSC mode"); + FH_MSG_DEBUG("DDS: 0x%08x", (fh_read32(g_reg_dds[pll])&MASK21b)); + + fh_set_field(reg_cfg, MASK_FRDDSX_DYS, p_setting->df); + fh_set_field(reg_cfg, MASK_FRDDSX_DTS, p_setting->dt); + + fh_write32(g_reg_updnlmt[pll], + (PERCENT_TO_DDSLMT((fh_read32(g_reg_dds[pll])&MASK21b), p_setting->lowbnd) << 16)); + FH_MSG_DEBUG("UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[pll])); + if (pll == FH_ARMCA15_PLLID) { + fh_write32((unsigned long) g_apmixed_base+0x900, + (fh_read32((unsigned long) g_apmixed_base+0x900) & 0xFFFF00FF) + + (armpll_ssc_pmap[p_setting->lowbnd] << 8)); + } + if (pll == FH_ARMCA7_PLLID) { + fh_write32((unsigned long) g_apmixed_base+0x900, + (fh_read32((unsigned long) g_apmixed_base+0x900) & 0xFFFFFF00) + + (armpll_ssc_pmap[p_setting->lowbnd])); + } + + fh_switch2fhctl(pll, 1); + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 1); /* enable SSC mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); /* enable hopping control */ + + FH_MSG_DEBUG("CFG: 0x%08x", fh_read32(reg_cfg)); + } +#endif + + spin_unlock_irqrestore(&g_fh_lock, flags); + + return 0; +} + +/* mmpll dfs mode */ +static int mt_fh_hal_dfs_mmpll(unsigned int target_dds) +{ + unsigned long flags = 0; + const unsigned int pll_id = FH_MM_PLLID; + const unsigned long reg_cfg = g_reg_cfg[pll_id]; + + if (g_initialize == 0) { + FH_MSG("(Warning) %s FHCTL isn't ready. ", __func__); + return -1; + } + + FH_MSG_DEBUG("%s, current dds(MMPLL_CON1): 0x%x, target dds %d", + __func__, (fh_read32(g_reg_pll_con1[pll_id])&MASK21b), + target_dds); + + spin_lock_irqsave(&g_fh_lock, flags); + + if (g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC) { + unsigned int pll_dds = 0; + unsigned int fh_dds = 0; + + /* only when SSC is enable, turn off MEMPLL hopping */ + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); /* disable SSC mode */ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); /* disable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); /* disable hopping control */ + + pll_dds = (fh_read32(g_reg_dds[pll_id])) & MASK21b; + fh_dds = (fh_read32(g_reg_mon[pll_id])) & MASK21b; + + FH_MSG_DEBUG(">p:f< %x:%x", pll_dds, fh_dds); + + wait_dds_stable(pll_dds, g_reg_mon[pll_id], 100); + } + +#if 0 + target_dds = (target_freq / 1000) * 8192 / 13; +#endif + + FH_MSG_DEBUG("target dds: 0x%x", target_dds); + mt_fh_hal_dvfs(pll_id, target_dds); + + if (g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC) { + const struct freqhopping_ssc *p_setting = &ssc_mmpll_setting[2]; + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); /* disable SSC mode */ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); /* disable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); /* disable hopping control */ + + fh_sync_ncpo_to_fhctl_dds(pll_id); + + FH_MSG_DEBUG("Enable mmpll SSC mode"); + FH_MSG_DEBUG("DDS: 0x%08x", (fh_read32(g_reg_dds[pll_id])&MASK21b)); + + fh_set_field(reg_cfg, MASK_FRDDSX_DYS, p_setting->df); + fh_set_field(reg_cfg, MASK_FRDDSX_DTS, p_setting->dt); + + fh_write32(g_reg_updnlmt[pll_id], + (PERCENT_TO_DDSLMT((fh_read32(g_reg_dds[pll_id])&MASK21b), p_setting->lowbnd) << 16)); + FH_MSG_DEBUG("UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[pll_id])); + + fh_switch2fhctl(pll_id, 1); + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 1); /* enable SSC mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); /* enable hopping control */ + + FH_MSG_DEBUG("CFG: 0x%08x", fh_read32(reg_cfg)); + } + spin_unlock_irqrestore(&g_fh_lock, flags); + + return 0; +} + +static int mt_fh_hal_dfs_vencpll(unsigned int target_freq) +{ + unsigned long flags = 0; + /* unsigned int target_dds = 0; *//**< target_freq is target_dds */ + const unsigned int pll_id = FH_VENC_PLLID; + const unsigned long reg_cfg = g_reg_cfg[pll_id]; + + if (g_initialize == 0) { + FH_MSG("(Warning) %s FHCTL isn't ready. ", __func__); + return -1; + } + + FH_MSG_DEBUG("%s current dds(VENCPLL_CON1): 0x%x", __func__, + (fh_read32(g_reg_pll_con1[pll_id])&MASK21b)); + + /* TODO: provelock issue spin_lock(&g_fh_lock); */ + spin_lock_irqsave(&g_fh_lock, flags); + + if (g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC) { + unsigned int fh_dds = 0; + unsigned int pll_dds = 0; + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); /* disable SSC mode */ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); /* disable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); /* disable hopping control */ + + pll_dds = (fh_read32(g_reg_dds[pll_id])) & MASK21b; + fh_dds = (fh_read32(g_reg_mon[pll_id])) & MASK21b; + + FH_MSG_DEBUG(">p:f< %x:%x", pll_dds, fh_dds); + + wait_dds_stable(pll_dds, g_reg_mon[pll_id], 100); + } + +#if 0 /**< target_freq is target_dds */ + switch (target_freq) { + case VENCPLL_TARGETVCO_1: + target_dds = VENCPLL_TARGETVCO_1_DDS; + break; + case VENCPLL_TARGETVCO_2: + target_dds = VENCPLL_TARGETVCO_2_DDS; + break; + default: + FH_BUG_ON(1); + return 0; + /* break; */ + }; +#endif + + FH_MSG_DEBUG("target dds: 0x%x", target_freq); + + mt_fh_hal_dvfs(pll_id, target_freq); + + if (g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC) { + const struct freqhopping_ssc *p_setting = &ssc_vencpll_setting[2]; + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0); /* disable SSC mode */ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0); /* disable dvfs mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0); /* disable hopping control */ + + fh_sync_ncpo_to_fhctl_dds(pll_id); + + FH_MSG_DEBUG("Enable vencpll SSC mode"); + FH_MSG_DEBUG("DDS: 0x%08x", (fh_read32(g_reg_dds[pll_id])&MASK21b)); + + fh_set_field(reg_cfg, MASK_FRDDSX_DYS, p_setting->df); + fh_set_field(reg_cfg, MASK_FRDDSX_DTS, p_setting->dt); + + fh_write32(g_reg_updnlmt[pll_id], + (PERCENT_TO_DDSLMT((fh_read32(g_reg_dds[pll_id])&MASK21b), p_setting->lowbnd)<<16)); + FH_MSG_DEBUG("UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[pll_id])); + + fh_switch2fhctl(pll_id, 1); + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 1); /* enable SSC mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); /* enable hopping control */ + + FH_MSG_DEBUG("CFG: 0x%08x", fh_read32(reg_cfg)); + } + spin_unlock_irqrestore(&g_fh_lock, flags); + + return 0; +} + +static int mt_fh_hal_l2h_dvfs_mempll(void) +{ + FH_BUG_ON(1); + return 0; +} + +static int mt_fh_hal_h2l_dvfs_mempll(void) +{ + FH_BUG_ON(1); + return 0; +} + +static int mt_fh_hal_dram_overclock(int clk) +{ + FH_BUG_ON(1); + return 0; +} + +static int mt_fh_hal_get_dramc(void) +{ + FH_BUG_ON(1); + return 0; +} + +static void mt_fh_hal_popod_save(void) +{ + const unsigned int pll_id = FH_MAIN_PLLID; + + FH_MSG_DEBUG("EN: %s", __func__); + + /* disable maipll SSC mode */ + if (g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC) { + unsigned int fh_dds = 0; + unsigned int pll_dds = 0; + const unsigned long reg_cfg = g_reg_cfg[pll_id]; + + /* only when SSC is enable, turn off MAINPLL hopping */ + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0);/*disable SSC mode*/ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0);/*disable dvfs mode*/ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0);/*disable hopping control*/ + + pll_dds = (fh_read32(g_reg_dds[pll_id])) & MASK21b; + fh_dds = (fh_read32(g_reg_mon[pll_id])) & MASK21b; + + FH_MSG_DEBUG("Org pll_dds:%x fh_dds:%x", pll_dds, fh_dds); + + wait_dds_stable(pll_dds, g_reg_mon[pll_id], 100); + + /* write back to ncpo, only for MAINPLL. Don't need to add MEMPLL handle. */ + fh_write32(g_reg_pll_con1[pll_id], + (fh_read32(g_reg_dds[pll_id])&MASK21b)| + (fh_read32(g_reg_pll_con1[pll_id])&0xFFE00000)|(BIT32)); + FH_MSG_DEBUG("MAINPLL_CON1: 0x%08x", (fh_read32(g_reg_pll_con1[pll_id])&MASK21b)); + + /* switch to register control */ + fh_switch2fhctl(pll_id, 0); + + mb(); + } +} + +static void mt_fh_hal_popod_restore(void) +{ + const unsigned int pll_id = FH_MAIN_PLLID; + + FH_MSG_DEBUG("EN: %s", __func__); + + /* enable maipll SSC mode */ + if (g_fh_pll[pll_id].fh_status == FH_FH_ENABLE_SSC) { + const struct freqhopping_ssc *p_setting = &ssc_mainpll_setting[2]; + const unsigned long reg_cfg = g_reg_cfg[pll_id]; + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0);/*disable SSC mode*/ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0);/*disable dvfs mode*/ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0);/*disable hopping control*/ + + fh_sync_ncpo_to_fhctl_dds(pll_id); + + FH_MSG_DEBUG("Enable mainpll SSC mode"); + FH_MSG_DEBUG("sync ncpo to DDS of FHCTL"); + FH_MSG_DEBUG("FHCTL1_DDS: 0x%08x", (fh_read32(g_reg_dds[pll_id])&MASK21b)); + + fh_set_field(reg_cfg, MASK_FRDDSX_DYS, p_setting->df); + fh_set_field(reg_cfg, MASK_FRDDSX_DTS, p_setting->dt); + + fh_write32(g_reg_updnlmt[pll_id], + (PERCENT_TO_DDSLMT((fh_read32(g_reg_dds[pll_id])&MASK21b), p_setting->lowbnd) << 16)); + FH_MSG_DEBUG("REG_FHCTL2_UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[pll_id])); + + fh_switch2fhctl(pll_id, 1); + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 1); /* enable SSC mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); /* enable hopping control */ + + FH_MSG_DEBUG("REG_FHCTL2_CFG: 0x%08x", fh_read32(reg_cfg)); + } +} + +static int fh_dramc_proc_read(struct seq_file *m, void *v) +{ + return 0; +} + +static int fh_dramc_proc_write(struct file *file, const char *buffer, unsigned long count, void *data) +{ + return 0; +} + +static int fh_dvfs_proc_read(struct seq_file *m, void *v) +{ + int i = 0; + + FH_MSG_DEBUG("EN: %s", __func__); + + seq_puts(m, "DVFS:\r\n"); + seq_puts(m, "CFG: 0x3 is SSC mode; 0x5 is DVFS mode \r\n"); + for (i = 0; i < FH_PLL_NUM; ++i) { + seq_printf(m, "FHCTL%d: CFG:0x%08x DVFS:0x%08x\r\n", + i, fh_read32(g_reg_cfg[i]), fh_read32(g_reg_dvfs[i])); + } + return 0; +} + +static int fh_dvfs_proc_write(struct file *file, const char *buffer, unsigned long count, void *data) +{ + unsigned int p1, p2, p3, p4, p5; + + p1 = p2 = p3 = p4 = p5 = 0; + + FH_MSG("EN: %s", __func__); + + if (count == 0) + return -1; + + FH_MSG("EN: p1=%d p2=%d p3=%d", p1, p2, p3); + + switch (p1) { + case FH_ARMCA15_PLLID: + mt_fh_hal_dfs_armpll(p2, p3); + FH_MSG("ARMCA15PLL DVFS completed\n"); + break; + case FH_ARMCA7_PLLID: + mt_fh_hal_dfs_armpll(p2, p3); + FH_MSG("ARMCA7PLL DVFS completed\n"); + break; + case FH_MM_PLLID: + mt_fh_hal_dfs_mmpll(p3); + FH_MSG("MMPLL DVFS completed\n"); + break; + case FH_VENC_PLLID: + mt_fh_hal_dfs_vencpll(p3); + FH_MSG("VENCPLL DVFS completed\n"); + break; + case 4370: + { + unsigned long reg_cfg = 0; + + VALIDATE_PLLID(p2); + + reg_cfg = g_reg_cfg[p2]; + + /* TODO: Find out who use this case */ + FH_MSG("pllid=%d dt=%d df=%d lowbnd=%d", p2, p3, p4, p5); + fh_set_field(reg_cfg, FH_FRDDSX_EN, 0);/*disable SSC mode*/ + fh_set_field(reg_cfg, FH_SFSTRX_EN, 0);/*disable dvfs mode*/ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 0);/*disable hopping control*/ + + fh_sync_ncpo_to_fhctl_dds(p2); + + FH_MSG("Enable FHCTL%d SSC mode", p2); + FH_MSG("DDS: 0x%08x", (fh_read32(reg_cfg)&MASK21b)); + + fh_set_field(reg_cfg, MASK_FRDDSX_DYS, p4); + fh_set_field(reg_cfg, MASK_FRDDSX_DTS, p3); + + fh_write32(g_reg_updnlmt[p2], (PERCENT_TO_DDSLMT((fh_read32(reg_cfg)&MASK21b), p5)<<16)); + FH_MSG("UPDNLMT: 0x%08x", fh_read32(g_reg_updnlmt[p2])); + + fh_switch2fhctl(p2, 1); + + fh_set_field(reg_cfg, FH_FRDDSX_EN, 1); /* enable SSC mode */ + fh_set_field(reg_cfg, FH_FHCTLX_EN, 1); /* enable hopping control */ + + FH_MSG("CFG: 0x%08x", fh_read32(reg_cfg)); + } + break; + case 2222: + /* TODO: and what this case for? */ + if (p2 == 0) /* disable */ + mt_fh_hal_popod_save(); + else if (p2 == 1) /* enable */ + mt_fh_hal_popod_restore(); + break; + default: + mt_fh_hal_dvfs(p1, p2); + break; + }; + + return count; +} + +/* +#define UINT_MAX (unsigned int)(-1) +*/ +static int fh_dumpregs_proc_read(struct seq_file *m, void *v) +{ + int i = 0; + static unsigned int dds_max[FH_PLL_NUM] = {0}; + static unsigned int dds_min[FH_PLL_NUM] = { + UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, + UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX}; + + FH_MSG_DEBUG("EN: %s", __func__); + + for (i = 0; i < FH_PLL_NUM; ++i) { + const unsigned int mon = fh_read32(g_reg_mon[i]); + const unsigned int dds = mon & MASK21b; + + seq_printf(m, "FHCTL%d CFG, UPDNLMT, DDS, MON\r\n", i); + seq_printf(m, "0x%08x 0x%08x 0x%08x 0x%08x\r\n", + fh_read32(g_reg_cfg[i]), fh_read32(g_reg_updnlmt[i]), + fh_read32(g_reg_dds[i]), mon); + + if (dds > dds_max[i]) + dds_max[i] = dds; + if (dds < dds_min[i]) + dds_min[i] = dds; + } + + seq_printf(m, "\r\nFHCTL_HP_EN:\r\n0x%08x\r\n", fh_read32(REG_FHCTL_HP_EN)); + + seq_puts(m, "\r\nPLL_CON0 :\r\n"); + seq_printf(m, "ARMCA15:0x%08x ARMCA7:0x%08x M:0x%08x MAIN:0x%08x MEM:0x%08x ", + fh_read32(REG_ARMCA15PLL_CON0), fh_read32(REG_ARMCA7PLL_CON0), fh_read32(REG_MPLL_CON0), + fh_read32(REG_MAINPLL_CON0), fh_read32(REG_MEMPLL_CON0)); + seq_printf(m, "MSDC:0x%08x MM:0x%08x VENC:0x%08x TVD:0x%08x\r\n", + fh_read32(REG_MSDCPLL_CON0), fh_read32(REG_MMPLL_CON0), + fh_read32(REG_VENCPLL_CON0), fh_read32(REG_TVDPLL_CON0)); + + seq_puts(m, "\r\nPLL_CON1 :\r\n"); + seq_printf(m, "ARMCA15:0x%08x ARMCA7:0x%08x M:0x%08x MAIN:0x%08x MEM:0x%08x ", + fh_read32(REG_ARMCA15PLL_CON1), fh_read32(REG_ARMCA7PLL_CON1), fh_read32(REG_MPLL_CON1), + fh_read32(REG_MAINPLL_CON1), fh_read32(REG_MEMPLL_CON1)); + seq_printf(m, "MSDC:0x%08x MM:0x%08x VENC:0x%08x TVD:0x%08x\r\n", + fh_read32(REG_MSDCPLL_CON1), fh_read32(REG_MMPLL_CON1), + fh_read32(REG_VENCPLL_CON1), fh_read32(REG_TVDPLL_CON1)); + + seq_puts(m, "\r\nRecorded dds range\r\n"); + for (i = 0; i < FH_PLL_NUM; ++i) { + seq_printf(m, "Pll%d dds max 0x%06x, min 0x%06x\r\n", + i, dds_max[i], dds_min[i]); + } + + seq_printf(m, "\r\n %p %p %p\r\n", g_fhctl_base, g_apmixed_base, g_ddrphy_base); + seq_printf(m, "\r\n APMIXEDSYS RSV_RW0_CON 0x%08x RSV_RW1_CON 0x%08x\r\n", + fh_read32((unsigned long) g_apmixed_base+0x900), + fh_read32((unsigned long) g_apmixed_base+0x904)); + + return 0; +} + +static void __reg_tbl_init(void) +{ +#ifdef CONFIG_OF +#if 0 + int i = 0; + + const unsigned long reg_dds[] = { + REG_FHCTL0_DDS, REG_FHCTL1_DDS, REG_FHCTL2_DDS, + REG_FHCTL3_DDS, REG_FHCTL4_DDS, REG_FHCTL5_DDS, + REG_FHCTL6_DDS, REG_FHCTL7_DDS, REG_FHCTL8_DDS}; + + const unsigned long reg_cfg[] = { + REG_FHCTL0_CFG, REG_FHCTL1_CFG, REG_FHCTL2_CFG, + REG_FHCTL3_CFG, REG_FHCTL4_CFG, REG_FHCTL5_CFG, + REG_FHCTL6_CFG, REG_FHCTL7_CFG, REG_FHCTL8_CFG}; + + const unsigned long reg_updnlmt[] = { + REG_FHCTL0_UPDNLMT, REG_FHCTL1_UPDNLMT, REG_FHCTL2_UPDNLMT, + REG_FHCTL3_UPDNLMT, REG_FHCTL4_UPDNLMT, REG_FHCTL5_UPDNLMT, + REG_FHCTL6_UPDNLMT, REG_FHCTL7_UPDNLMT, REG_FHCTL8_UPDNLMT}; + + const unsigned long reg_mon[] = { + REG_FHCTL0_MON, REG_FHCTL1_MON, REG_FHCTL2_MON, + REG_FHCTL3_MON, REG_FHCTL4_MON, REG_FHCTL5_MON, + REG_FHCTL6_MON, REG_FHCTL7_MON, REG_FHCTL8_MON}; + + const unsigned long reg_dvfs[] = { + REG_FHCTL0_DVFS, REG_FHCTL1_DVFS, REG_FHCTL2_DVFS, + REG_FHCTL3_DVFS, REG_FHCTL4_DVFS, REG_FHCTL5_DVFS, + REG_FHCTL6_DVFS, REG_FHCTL7_DVFS, REG_FHCTL8_DVFS}; + + const unsigned long reg_pll_con1[] = { + REG_ARMCA15PLL_CON1, REG_ARMCA7PLL_CON1, REG_MAINPLL_CON1, + REG_MEMPLL_CON1, REG_MMPLL_CON1, REG_MPLL_CON1, + REG_VENCPLL_CON1, REG_MSDCPLL_CON1, REG_TVDPLL_CON1}; + + FH_MSG_DEBUG("EN: %s", __func__); + + for (i = 0; i < FH_PLL_NUM; ++i) { + g_reg_dds[i] = reg_dds[i]; + g_reg_cfg[i] = reg_cfg[i]; + g_reg_updnlmt[i] = reg_updnlmt[i]; + g_reg_mon[i] = reg_mon[i]; + g_reg_dvfs[i] = reg_dvfs[i]; + g_reg_pll_con1[i] = reg_pll_con1[i]; +#ifdef CONFIG_ARM64 + /* + FH_MSG_DEBUG("index:%d %lx %lx %lx %lx %lx %lx", i, g_reg_dds[i], g_reg_cfg[i], + g_reg_updnlmt[i], g_reg_mon[i], g_reg_dvfs[i], g_reg_pll_con1[i]); + */ +#else + /* + FH_MSG_DEBUG("index:%d %x %x %x %x %x %x", i, g_reg_dds[i], g_reg_cfg[i], + g_reg_updnlmt[i], g_reg_mon[i], g_reg_dvfs[i], g_reg_pll_con1[i]); + */ +#endif + } +#else + /* reduce stack size */ + FH_MSG_DEBUG("EN: %s", __func__); + + g_reg_dds[0] = REG_FHCTL0_DDS; + g_reg_dds[1] = REG_FHCTL1_DDS; + g_reg_dds[2] = REG_FHCTL2_DDS; + g_reg_dds[3] = REG_FHCTL3_DDS; + g_reg_dds[4] = REG_FHCTL4_DDS; + g_reg_dds[5] = REG_FHCTL5_DDS; + g_reg_dds[6] = REG_FHCTL6_DDS; + g_reg_dds[7] = REG_FHCTL7_DDS; + g_reg_dds[8] = REG_FHCTL8_DDS; + + g_reg_cfg[0] = REG_FHCTL0_CFG; + g_reg_cfg[1] = REG_FHCTL1_CFG; + g_reg_cfg[2] = REG_FHCTL2_CFG; + g_reg_cfg[3] = REG_FHCTL3_CFG; + g_reg_cfg[4] = REG_FHCTL4_CFG; + g_reg_cfg[5] = REG_FHCTL5_CFG; + g_reg_cfg[6] = REG_FHCTL6_CFG; + g_reg_cfg[7] = REG_FHCTL7_CFG; + g_reg_cfg[8] = REG_FHCTL8_CFG; + + g_reg_updnlmt[0] = REG_FHCTL0_UPDNLMT; + g_reg_updnlmt[1] = REG_FHCTL1_UPDNLMT; + g_reg_updnlmt[2] = REG_FHCTL2_UPDNLMT; + g_reg_updnlmt[3] = REG_FHCTL3_UPDNLMT; + g_reg_updnlmt[4] = REG_FHCTL4_UPDNLMT; + g_reg_updnlmt[5] = REG_FHCTL5_UPDNLMT; + g_reg_updnlmt[6] = REG_FHCTL6_UPDNLMT; + g_reg_updnlmt[7] = REG_FHCTL7_UPDNLMT; + g_reg_updnlmt[8] = REG_FHCTL8_UPDNLMT; + + g_reg_mon[0] = REG_FHCTL0_MON; + g_reg_mon[1] = REG_FHCTL1_MON; + g_reg_mon[2] = REG_FHCTL2_MON; + g_reg_mon[3] = REG_FHCTL3_MON; + g_reg_mon[4] = REG_FHCTL4_MON; + g_reg_mon[5] = REG_FHCTL5_MON; + g_reg_mon[6] = REG_FHCTL6_MON; + g_reg_mon[7] = REG_FHCTL7_MON; + g_reg_mon[8] = REG_FHCTL8_MON; + + g_reg_dvfs[0] = REG_FHCTL0_DVFS; + g_reg_dvfs[1] = REG_FHCTL1_DVFS; + g_reg_dvfs[2] = REG_FHCTL2_DVFS; + g_reg_dvfs[3] = REG_FHCTL3_DVFS; + g_reg_dvfs[4] = REG_FHCTL4_DVFS; + g_reg_dvfs[5] = REG_FHCTL5_DVFS; + g_reg_dvfs[6] = REG_FHCTL6_DVFS; + g_reg_dvfs[7] = REG_FHCTL7_DVFS; + g_reg_dvfs[8] = REG_FHCTL8_DVFS; + + g_reg_pll_con1[0] = REG_ARMCA15PLL_CON1; + g_reg_pll_con1[1] = REG_ARMCA7PLL_CON1; + g_reg_pll_con1[2] = REG_MAINPLL_CON1; + g_reg_pll_con1[3] = REG_MEMPLL_CON1; + g_reg_pll_con1[4] = REG_MMPLL_CON1; + g_reg_pll_con1[5] = REG_MPLL_CON1; + g_reg_pll_con1[6] = REG_VENCPLL_CON1; + g_reg_pll_con1[7] = REG_MSDCPLL_CON1; + g_reg_pll_con1[8] = REG_TVDPLL_CON1; +#endif +#endif +} + +#ifdef CONFIG_OF +/* Device Tree Initialize */ +static int __reg_base_addr_init(void) +{ + struct device_node *fhctl_node; + struct device_node *apmixed_node; + + /* Init FHCTL base address */ + fhctl_node = of_find_compatible_node(NULL, NULL, "mediatek,FHCTL"); + if (!fhctl_node) { + FH_MSG_DEBUG("Error, Cannot find FHCTL device tree node"); + g_fhctl_base = (void *)(0xF0209F00); + } else { + g_fhctl_base = of_iomap(fhctl_node, 0); + if (!g_fhctl_base) { + FH_MSG_DEBUG("Error, FHCTL iomap failed"); + g_fhctl_base = (void *)(0xF0209F00); + } else { + /* FH_MSG_DEBUG("FHCTL dase address:0x%lx", (unsigned long)g_fhctl_base); + */ + } + } /* if-else */ + + /* Init APMIXED base address */ + apmixed_node = of_find_compatible_node(NULL, NULL, "mediatek,APMIXED"); + if (!apmixed_node) { + FH_MSG_DEBUG(" Error, Cannot find APMIXED device tree node"); + g_apmixed_base = (void *)(0xF0209000); + } else { + g_apmixed_base = of_iomap(apmixed_node, 0); + if (!g_apmixed_base) { + FH_MSG_DEBUG("Error, APMIXED iomap failed"); + g_apmixed_base = (void *)(0xF0209000); + } else { + /*FH_MSG_DEBUG("APMIXED dase address:0x%lx", (unsigned long)g_apmixed_base); + */ + } + } /* if-else */ + + /* Init DDRPHY base address */ + g_ddrphy_base = mt_ddrphy_base_get(); + if (!g_ddrphy_base) { + FH_MSG_DEBUG("Error, FHCTL DDRPHY failed"); + g_ddrphy_base = (void *)(0xF000F000); + } else { + /*FH_MSG_DEBUG("DDRPHY dase address:0x%lx", (unsigned long)g_ddrphy_base); + */ + } /* if-else */ + + __reg_tbl_init(); + + return 0; +} +#endif + +/* TODO: __init void mt_freqhopping_init(void) */ +static void mt_fh_hal_init(void) +{ + int i = 0; + unsigned long flags = 0; + + FH_MSG_DEBUG("EN: %s", __func__); + + if (g_initialize == 1) + return; + +#ifdef CONFIG_OF + /* Init relevant register base address by device tree */ + __reg_base_addr_init(); +#endif + + for (i = 0; i < FH_PLL_NUM; ++i) { + unsigned int mask = 1<pll_id, fh_ctl->ssc_setting.dds); + } + break; + case FH_DCTL_CMD_DVFS_SSC_ENABLE: /* PLL DVFS and enable SSC */ + { + __disable_ssc(fh_ctl->pll_id, &(fh_ctl->ssc_setting)); + mt_fh_hal_dvfs(fh_ctl->pll_id, fh_ctl->ssc_setting.dds); + __enable_ssc(fh_ctl->pll_id, &(fh_ctl->ssc_setting)); + } + break; + case FH_DCTL_CMD_DVFS_SSC_DISABLE: /* PLL DVFS and disable SSC */ + { + __disable_ssc(fh_ctl->pll_id, &(fh_ctl->ssc_setting)); + mt_fh_hal_dvfs(fh_ctl->pll_id, fh_ctl->ssc_setting.dds); + } + break; + case FH_DCTL_CMD_SSC_ENABLE: /* SSC enable */ + { + __enable_ssc(fh_ctl->pll_id, &(fh_ctl->ssc_setting)); + } + break; + case FH_DCTL_CMD_SSC_DISABLE: /* SSC disable */ + { + __disable_ssc(fh_ctl->pll_id, &(fh_ctl->ssc_setting)); + } + break; + default: + break; + }; + + return 0; +} + + +static void __ioctl(unsigned int ctlid, void *arg) +{ + switch (ctlid) { + case FH_IO_PROC_READ: + { + FH_IO_PROC_READ_T *tmp = (FH_IO_PROC_READ_T *)(arg); + __fh_debug_proc_read(tmp->m, tmp->v, tmp->pll); + } + break; + case FH_DCTL_CMD_DVFS: /* PLL DVFS */ + case FH_DCTL_CMD_DVFS_SSC_ENABLE: /* PLL DVFS and enable SSC */ + case FH_DCTL_CMD_DVFS_SSC_DISABLE: /* PLL DVFS and disable SSC */ + case FH_DCTL_CMD_SSC_ENABLE: /* SSC enable */ + case FH_DCTL_CMD_SSC_DISABLE: /* SSC disable */ + { + fh_ioctl_dvfs_ssc(ctlid, arg); + } + break; + default: + FH_MSG("Unrecognized ctlid %d", ctlid); + break; + }; +} + +static struct mt_fh_hal_driver g_fh_hal_drv = { + .fh_pll = g_fh_pll, + .fh_usrdef = mt_ssc_fhpll_userdefined, + .mempll = FH_MEM_PLLID, + .lvdspll = FH_MAX_PLLID + 1, + .mainpll = FH_MAIN_PLLID, + .msdcpll = FH_MSDC_PLLID, + .mmpll = FH_MM_PLLID, + .vencpll = FH_VENC_PLLID, + .pll_cnt = FH_PLL_NUM, + .proc.clk_gen_read = NULL, + .proc.clk_gen_write = NULL, + .proc.dramc_read = fh_dramc_proc_read, + .proc.dramc_write = fh_dramc_proc_write, + .proc.dumpregs_read = fh_dumpregs_proc_read, + .proc.dvfs_read = fh_dvfs_proc_read, + .proc.dvfs_write = fh_dvfs_proc_write, + .mt_fh_hal_init = mt_fh_hal_init, + .mt_fh_hal_ctrl = __freqhopping_ctrl, + .mt_fh_lock = mt_fh_hal_lock, + .mt_fh_unlock = mt_fh_hal_unlock, + .mt_fh_get_init = mt_fh_hal_get_init, + .mt_fh_popod_restore = mt_fh_hal_popod_restore, + .mt_fh_popod_save = mt_fh_hal_popod_save, + .mt_l2h_mempll = NULL, + .mt_h2l_mempll = NULL, + .mt_dfs_armpll = mt_fh_hal_dfs_armpll, + .mt_dfs_mmpll = mt_fh_hal_dfs_mmpll, + .mt_dfs_vencpll = mt_fh_hal_dfs_vencpll, /*TODO: should set to NULL*/ + .mt_is_support_DFS_mode = mt_fh_hal_is_support_DFS_mode, + .mt_l2h_dvfs_mempll = mt_fh_hal_l2h_dvfs_mempll, /*TODO: should set to NULL*/ + .mt_h2l_dvfs_mempll = mt_fh_hal_h2l_dvfs_mempll, /*TODO: should set to NULL*/ + .mt_dram_overclock = mt_fh_hal_dram_overclock, /*TODO: should set to NULL*/ + .mt_get_dramc = mt_fh_hal_get_dramc, /*TODO: should set to NULL*/ + .mt_fh_default_conf = mt_fh_hal_default_conf, + .ioctl = __ioctl +}; + +struct mt_fh_hal_driver *mt_get_fh_hal_drv(void) +{ + return &g_fh_hal_drv; +} + +int mt_pause_armpll(unsigned int pll, unsigned int pause) +{ + unsigned long flags = 0; + unsigned long reg_cfg = 0; + + if (g_initialize == 0) { + FH_MSG("(Warning) %s FHCTL isn't ready.", __func__); + return -1; + } + + FH_MSG_DEBUG("%s for pll %d pause %d", __func__, pll, pause); + + switch (pll) { + case FH_ARMCA15_PLLID: + case FH_ARMCA7_PLLID: + reg_cfg = g_reg_cfg[pll]; + FH_MSG_DEBUG("(FHCTLx_CFG): 0x%x", fh_read32(g_reg_cfg[pll])); + break; + default: + BUG_ON(1); + return 1; + }; + + /* TODO: provelock issue spin_lock(&g_fh_lock); */ + spin_lock_irqsave(&g_fh_lock, flags); + + if (pause) + fh_set_field(reg_cfg, FH_FHCTLX_CFG_PAUSE, 1); /* pause */ + else + fh_set_field(reg_cfg, FH_FHCTLX_CFG_PAUSE, 0); /* no pause */ + + spin_unlock_irqrestore(&g_fh_lock, flags); + + return 0; +} +/* +TODO: module_exit(cpufreq_exit); +*/ diff --git a/drivers/misc/mediatek/gpio/mt6755/6755_gpio.h b/drivers/misc/mediatek/gpio/mt6755/6755_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..de0fb7f301f3c3883f492d1c2d2ff76b0057c5b9 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/6755_gpio.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _6755_GPIO_H +#define _6755_GPIO_H + +#include "mt_gpio_base.h" +#include +#include + + +extern ssize_t mt_gpio_show_pin(struct device *dev, struct device_attribute *attr, char *buf); +extern ssize_t mt_gpio_store_pin(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +struct device_node *get_gpio_np(void); +extern long gpio_pull_select_unsupport[MAX_GPIO_PIN]; +extern long gpio_pullen_unsupport[MAX_GPIO_PIN]; +extern long gpio_smt_unsupport[MAX_GPIO_PIN]; +void mt_get_md_gpio_debug(char *str); +#endif /*_6755_GPIO_H*/ diff --git a/drivers/misc/mediatek/gpio/mt6755/Makefile b/drivers/misc/mediatek/gpio/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3082cbedd9776b163787521a4f0da10979503c54 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/Makefile @@ -0,0 +1,23 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ifeq ($(CONFIG_MTK_FPGA),y) +obj-y := mt_gpio_fpga.o +else +obj-y := mt_gpio_base.o +endif +obj-y += mt_gpio_affix.o mt_gpio_debug.o mt_gpio_ext.o +ifeq ($(CONFIG_GPIOLIB),y) +obj-y += mt_gpio_base_linux.o +endif +# obj-y += dcl_sim_gpio.o diff --git a/drivers/misc/mediatek/gpio/mt6755/gpio_cfg.h b/drivers/misc/mediatek/gpio/mt6755/gpio_cfg.h new file mode 100644 index 0000000000000000000000000000000000000000..786de33198c823a713f43bb33a403c90c2e503c0 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/gpio_cfg.h @@ -0,0 +1,4689 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _GPIO_CFG_H_ +#define _GPIO_CFG_H_ + +#include + +typedef struct { + unsigned long addr; +} PIN_addr; + +typedef struct { + s8 offset; +} PIN_offset; +/*#define GPIO_BASE (0x10005000)*/ +#define IOCFG_0_BASE (0x000) +#define IOCFG_1_BASE (0x200) +#define IOCFG_2_BASE (0x400) +#define IOCFG_3_BASE (0x600) +#define IOCFG_4_BASE (0x800) +#define IOCFG_5_BASE (0xA00) + +PIN_addr IES_addr[] = { +/* 0 */ {IOCFG_3_BASE + 0x000}, +/* 1 */ {IOCFG_3_BASE + 0x000}, +/* 2 */ {IOCFG_3_BASE + 0x000}, +/* 3 */ {IOCFG_3_BASE + 0x000}, +/* 4 */ {IOCFG_3_BASE + 0x000}, +/* 5 */ {IOCFG_3_BASE + 0x000}, +/* 6 */ {IOCFG_3_BASE + 0x000}, +/* 7 */ {IOCFG_3_BASE + 0x000}, +/* 8 */ {IOCFG_3_BASE + 0x000}, +/* 9 */ {IOCFG_3_BASE + 0x000}, +/* 10 */ {IOCFG_3_BASE + 0x000}, +/* 11 */ {IOCFG_0_BASE + 0x000}, +/* 12 */ {IOCFG_0_BASE + 0x000}, +/* 13 */ {IOCFG_1_BASE + 0x000}, +/* 14 */ {IOCFG_1_BASE + 0x000}, +/* 15 */ {IOCFG_1_BASE + 0x000}, +/* 16 */ {IOCFG_1_BASE + 0x000}, +/* 17 */ {IOCFG_1_BASE + 0x000}, +/* 18 */ {IOCFG_1_BASE + 0x000}, +/* 19 */ {IOCFG_1_BASE + 0x000}, +/* 20 */ {IOCFG_1_BASE + 0x000}, +/* 21 */ {IOCFG_1_BASE + 0x000}, +/* 22 */ {IOCFG_1_BASE + 0x000}, +/* 23 */ {IOCFG_1_BASE + 0x000}, +/* 24 */ {IOCFG_1_BASE + 0x000}, +/* 25 */ {IOCFG_1_BASE + 0x000}, +/* 26 */ {IOCFG_1_BASE + 0x000}, +/* 27 */ {IOCFG_1_BASE + 0x000}, +/* 28 */ {IOCFG_1_BASE + 0x000}, +/* 29 */ {IOCFG_0_BASE + 0x000}, +/* 30 */ {IOCFG_0_BASE + 0x000}, +/* 31 */ {IOCFG_0_BASE + 0x000}, +/* 32 */ {IOCFG_0_BASE + 0x000}, +/* 33 */ {IOCFG_0_BASE + 0x000}, +/* 34 */ {IOCFG_0_BASE + 0x000}, +/* 35 */ {IOCFG_0_BASE + 0x000}, +/* 36 */ {IOCFG_0_BASE + 0x000}, +/* 37 */ {IOCFG_0_BASE + 0x000}, +/* 38 */ {IOCFG_0_BASE + 0x000}, +/* 39 */ {IOCFG_0_BASE + 0x000}, +/* 40 */ {IOCFG_0_BASE + 0x000}, +/* 41 */ {IOCFG_0_BASE + 0x000}, +/* 42 */ {IOCFG_1_BASE + 0x000}, +/* 43 */ {IOCFG_1_BASE + 0x000}, +/* 44 */ {IOCFG_1_BASE + 0x000}, +/* 45 */ {IOCFG_1_BASE + 0x000}, +/* 46 */ {IOCFG_1_BASE + 0x000}, +/* 47 */ {IOCFG_1_BASE + 0x000}, +/* 48 */ {IOCFG_1_BASE + 0x000}, +/* 49 */ {IOCFG_1_BASE + 0x000}, +/* 50 */ {IOCFG_1_BASE + 0x000}, +/* 51 */ {IOCFG_1_BASE + 0x000}, +/* 52 */ {IOCFG_1_BASE + 0x000}, +/* 53 */ {IOCFG_1_BASE + 0x000}, +/* 54 */ {IOCFG_1_BASE + 0x000}, +/* 55 */ {IOCFG_1_BASE + 0x000}, +/* 56 */ {IOCFG_1_BASE + 0x000}, +/* 57 */ {IOCFG_1_BASE + 0x000}, +/* 58 */ {IOCFG_1_BASE + 0x000}, +/* 59 */ {IOCFG_1_BASE + 0x000}, +/* 60 */ {IOCFG_1_BASE + 0x000}, +/* 61 */ {IOCFG_1_BASE + 0x000}, +/* 62 */ {IOCFG_1_BASE + 0x000}, +/* 63 */ {IOCFG_1_BASE + 0x000}, +/* 64 */ {IOCFG_1_BASE + 0x000}, +/* 65 */ {IOCFG_1_BASE + 0x000}, +/* 66 */ {IOCFG_1_BASE + 0x000}, +/* 67 */ {IOCFG_1_BASE + 0x000}, +/* 68 */ {IOCFG_1_BASE + 0x000}, +/* 69 */ {IOCFG_1_BASE + 0x000}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {IOCFG_2_BASE + 0x000}, +/* 76 */ {IOCFG_2_BASE + 0x000}, +/* 77 */ {IOCFG_2_BASE + 0x000}, +/* 78 */ {IOCFG_2_BASE + 0x000}, +/* 79 */ {IOCFG_2_BASE + 0x000}, +/* 80 */ {IOCFG_2_BASE + 0x000}, +/* 81 */ {IOCFG_2_BASE + 0x000}, +/* 82 */ {IOCFG_2_BASE + 0x000}, +/* 83 */ {IOCFG_2_BASE + 0x000}, +/* 84 */ {IOCFG_2_BASE + 0x000}, +/* 85 */ {IOCFG_2_BASE + 0x000}, +/* 86 */ {IOCFG_2_BASE + 0x000}, +/* 87 */ {IOCFG_2_BASE + 0x000}, +/* 88 */ {IOCFG_2_BASE + 0x000}, +/* 89 */ {IOCFG_2_BASE + 0x000}, +/* 90 */ {IOCFG_2_BASE + 0x000}, +/* 91 */ {IOCFG_3_BASE + 0x000}, +/* 92 */ {IOCFG_3_BASE + 0x000}, +/* 93 */ {IOCFG_3_BASE + 0x000}, +/* 94 */ {IOCFG_3_BASE + 0x000}, +/* 95 */ {IOCFG_3_BASE + 0x000}, +/* 96 */ {IOCFG_3_BASE + 0x000}, +/* 97 */ {IOCFG_3_BASE + 0x000}, +/* 98 */ {IOCFG_3_BASE + 0x000}, +/* 99 */ {IOCFG_3_BASE + 0x000}, +/* 100 */ {IOCFG_3_BASE + 0x000}, +/* 101 */ {IOCFG_3_BASE + 0x000}, +/* 102 */ {IOCFG_3_BASE + 0x000}, +/* 103 */ {IOCFG_3_BASE + 0x000}, +/* 104 */ {IOCFG_3_BASE + 0x000}, +/* 105 */ {IOCFG_3_BASE + 0x000}, +/* 106 */ {IOCFG_3_BASE + 0x000}, +/* 107 */ {IOCFG_3_BASE + 0x000}, +/* 108 */ {IOCFG_3_BASE + 0x000}, +/* 109 */ {IOCFG_3_BASE + 0x000}, +/* 110 */ {IOCFG_3_BASE + 0x000}, +/* 111 */ {IOCFG_3_BASE + 0x000}, +/* 112 */ {IOCFG_3_BASE + 0x000}, +/* 113 */ {IOCFG_3_BASE + 0x000}, +/* 114 */ {IOCFG_4_BASE + 0x000}, +/* 115 */ {IOCFG_4_BASE + 0x000}, +/* 116 */ {IOCFG_4_BASE + 0x000}, +/* 117 */ {IOCFG_4_BASE + 0x000}, +/* 118 */ {IOCFG_4_BASE + 0x000}, +/* 119 */ {IOCFG_4_BASE + 0x000}, +/* 120 */ {IOCFG_4_BASE + 0x000}, +/* 121 */ {IOCFG_4_BASE + 0x000}, +/* 122 */ {IOCFG_4_BASE + 0x000}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {IOCFG_4_BASE + 0x000}, +/* 132 */ {IOCFG_4_BASE + 0x000}, +/* 133 */ {IOCFG_4_BASE + 0x000}, +/* 134 */ {IOCFG_4_BASE + 0x000}, +/* 135 */ {IOCFG_4_BASE + 0x000}, +/* 136 */ {IOCFG_4_BASE + 0x000}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {IOCFG_0_BASE + 0x000}, +/* 148 */ {IOCFG_0_BASE + 0x000}, +/* 149 */ {IOCFG_0_BASE + 0x000}, +/* 150 */ {IOCFG_0_BASE + 0x000}, +/* 151 */ {IOCFG_0_BASE + 0x000}, +/* 152 */ {IOCFG_0_BASE + 0x000}, +/* 153 */ {IOCFG_0_BASE + 0x000}, +/* 154 */ {IOCFG_0_BASE + 0x000}, +/* 155 */ {IOCFG_0_BASE + 0x000}, +/* 156 */ {IOCFG_0_BASE + 0x000}, +/* 157 */ {IOCFG_1_BASE + 0x000}, +/* 158 */ {IOCFG_1_BASE + 0x000}, +/* 159 */ {IOCFG_1_BASE + 0x000}, +/* 160 */ {IOCFG_1_BASE + 0x000}, +/* 161 */ {IOCFG_3_BASE + 0x000}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {IOCFG_5_BASE + 0x000}, +/* 179 */ {IOCFG_5_BASE + 0x000}, +/* 180 */ {IOCFG_5_BASE + 0x000}, +/* 181 */ {IOCFG_5_BASE + 0x000}, +/* 182 */ {IOCFG_5_BASE + 0x000}, +/* 183 */ {IOCFG_5_BASE + 0x000}, +/* 184 */ {IOCFG_5_BASE + 0x000}, +/* 185 */ {IOCFG_5_BASE + 0x000}, +/* 186 */ {IOCFG_5_BASE + 0x000}, +/* 187 */ {IOCFG_5_BASE + 0x000}, +/* 188 */ {IOCFG_5_BASE + 0x000}, +/* 189 */ {IOCFG_5_BASE + 0x000} +}; + + +PIN_offset IES_offset[] = { +/* 0 */ {5}, +/* 1 */ {5}, +/* 2 */ {5}, +/* 3 */ {5}, +/* 4 */ {6}, +/* 5 */ {6}, +/* 6 */ {6}, +/* 7 */ {6}, +/* 8 */ {12}, +/* 9 */ {13}, +/* 10 */ {13}, +/* 11 */ {3}, +/* 12 */ {7}, +/* 13 */ {5}, +/* 14 */ {5}, +/* 15 */ {5}, +/* 16 */ {5}, +/* 17 */ {6}, +/* 18 */ {6}, +/* 19 */ {6}, +/* 20 */ {6}, +/* 21 */ {7}, +/* 22 */ {7}, +/* 23 */ {7}, +/* 24 */ {7}, +/* 25 */ {8}, +/* 26 */ {8}, +/* 27 */ {8}, +/* 28 */ {8}, +/* 29 */ {6}, +/* 30 */ {8}, +/* 31 */ {9}, +/* 32 */ {10}, +/* 33 */ {9}, +/* 34 */ {9}, +/* 35 */ {9}, +/* 36 */ {11}, +/* 37 */ {11}, +/* 38 */ {11}, +/* 39 */ {12}, +/* 40 */ {12}, +/* 41 */ {12}, +/* 42 */ {0}, +/* 43 */ {0}, +/* 44 */ {1}, +/* 45 */ {2}, +/* 46 */ {2}, +/* 47 */ {3}, +/* 48 */ {3}, +/* 49 */ {4}, +/* 50 */ {4}, +/* 51 */ {9}, +/* 52 */ {9}, +/* 53 */ {9}, +/* 54 */ {9}, +/* 55 */ {9}, +/* 56 */ {9}, +/* 57 */ {9}, +/* 58 */ {9}, +/* 59 */ {9}, +/* 60 */ {9}, +/* 61 */ {9}, +/* 62 */ {9}, +/* 63 */ {10}, +/* 64 */ {10}, +/* 65 */ {10}, +/* 66 */ {10}, +/* 67 */ {11}, +/* 68 */ {11}, +/* 69 */ {11}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {0}, +/* 76 */ {0}, +/* 77 */ {0}, +/* 78 */ {0}, +/* 79 */ {1}, +/* 80 */ {1}, +/* 81 */ {1}, +/* 82 */ {1}, +/* 83 */ {2}, +/* 84 */ {2}, +/* 85 */ {2}, +/* 86 */ {2}, +/* 87 */ {3}, +/* 88 */ {3}, +/* 89 */ {3}, +/* 90 */ {3}, + /* 91 */ {0}, +/* 92 */ {1}, +/* 93 */ {1}, + /* 94 */ {0}, +/* 95 */ {2}, + /* 96 */ {2}, +/* 97 */ {2}, +/* 98 */ {2}, +/* 99 */ {3}, +/* 100 */ {3}, +/* 101 */ {4}, +/* 102 */ {4}, +/* 103 */ {4}, +/* 104 */ {4}, +/* 105 */ {7}, +/* 106 */ {7}, +/* 107 */ {8}, +/* 108 */ {8}, +/* 109 */ {10}, +/* 110 */ {11}, +/* 111 */ {11}, +/* 112 */ {14}, +/* 113 */ {14}, +/* 114 */ {0}, +/* 115 */ {0}, +/* 116 */ {0}, +/* 117 */ {1}, +/* 118 */ {1}, +/* 119 */ {2}, +/* 120 */ {2}, +/* 121 */ {2}, +/* 122 */ {2}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {3}, + /* 132 */ {4}, +/* 133 */ {5}, +/* 134 */ {3}, +/* 135 */ {3}, +/* 136 */ {3}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, + /* 147 */ {0}, +/* 148 */ {1}, +/* 149 */ {2}, +/* 150 */ {2}, +/* 151 */ {2}, +/* 152 */ {4}, +/* 153 */ {4}, +/* 154 */ {4}, +/* 155 */ {4}, +/* 156 */ {5}, +/* 157 */ {1}, +/* 158 */ {1}, +/* 159 */ {11}, +/* 160 */ {11}, +/* 161 */ {9}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, + /* 178 */ {0}, +/* 179 */ {1}, +/* 180 */ {2}, +/* 181 */ {0}, +/* 182 */ {0}, +/* 183 */ {0}, +/* 184 */ {0}, + /* 185 */ {3}, +/* 186 */ {0}, +/* 187 */ {0}, +/* 188 */ {0}, +/* 189 */ {4} +}; + + +PIN_addr SMT_addr[] = { +/* 0 */ {IOCFG_3_BASE + 0x010}, +/* 1 */ {IOCFG_3_BASE + 0x010}, +/* 2 */ {IOCFG_3_BASE + 0x010}, +/* 3 */ {IOCFG_3_BASE + 0x010}, +/* 4 */ {IOCFG_3_BASE + 0x010}, +/* 5 */ {IOCFG_3_BASE + 0x010}, +/* 6 */ {IOCFG_3_BASE + 0x010}, +/* 7 */ {IOCFG_3_BASE + 0x010}, +/* 8 */ {IOCFG_3_BASE + 0x010}, +/* 9 */ {IOCFG_3_BASE + 0x010}, +/* 10 */ {IOCFG_3_BASE + 0x010}, +/* 11 */ {IOCFG_0_BASE + 0x010}, +/* 12 */ {IOCFG_0_BASE + 0x010}, +/* 13 */ {IOCFG_1_BASE + 0x010}, +/* 14 */ {IOCFG_1_BASE + 0x010}, +/* 15 */ {IOCFG_1_BASE + 0x010}, +/* 16 */ {IOCFG_1_BASE + 0x010}, +/* 17 */ {IOCFG_1_BASE + 0x010}, +/* 18 */ {IOCFG_1_BASE + 0x010}, +/* 19 */ {IOCFG_1_BASE + 0x010}, +/* 20 */ {IOCFG_1_BASE + 0x010}, +/* 21 */ {IOCFG_1_BASE + 0x010}, +/* 22 */ {IOCFG_1_BASE + 0x010}, +/* 23 */ {IOCFG_1_BASE + 0x010}, +/* 24 */ {IOCFG_1_BASE + 0x010}, +/* 25 */ {IOCFG_1_BASE + 0x010}, +/* 26 */ {IOCFG_1_BASE + 0x010}, +/* 27 */ {IOCFG_1_BASE + 0x010}, +/* 28 */ {IOCFG_1_BASE + 0x010}, +/* 29 */ {IOCFG_0_BASE + 0x010}, +/* 30 */ {IOCFG_0_BASE + 0x010}, +/* 31 */ {IOCFG_0_BASE + 0x010}, +/* 32 */ {IOCFG_0_BASE + 0x010}, +/* 33 */ {IOCFG_0_BASE + 0x010}, +/* 34 */ {IOCFG_0_BASE + 0x010}, +/* 35 */ {IOCFG_0_BASE + 0x010}, +/* 36 */ {IOCFG_0_BASE + 0x010}, +/* 37 */ {IOCFG_0_BASE + 0x010}, +/* 38 */ {IOCFG_0_BASE + 0x010}, +/* 39 */ {IOCFG_0_BASE + 0x010}, +/* 40 */ {IOCFG_0_BASE + 0x010}, +/* 41 */ {IOCFG_0_BASE + 0x010}, +/* 42 */ {IOCFG_1_BASE + 0x010}, +/* 43 */ {IOCFG_1_BASE + 0x010}, +/* 44 */ {IOCFG_1_BASE + 0x010}, +/* 45 */ {IOCFG_1_BASE + 0x010}, +/* 46 */ {IOCFG_1_BASE + 0x010}, +/* 47 */ {IOCFG_1_BASE + 0x010}, +/* 48 */ {IOCFG_1_BASE + 0x010}, +/* 49 */ {IOCFG_1_BASE + 0x010}, +/* 50 */ {IOCFG_1_BASE + 0x010}, +/* 51 */ {IOCFG_1_BASE + 0x010}, +/* 52 */ {IOCFG_1_BASE + 0x010}, +/* 53 */ {IOCFG_1_BASE + 0x010}, +/* 54 */ {IOCFG_1_BASE + 0x010}, +/* 55 */ {IOCFG_1_BASE + 0x010}, +/* 56 */ {IOCFG_1_BASE + 0x010}, +/* 57 */ {IOCFG_1_BASE + 0x010}, +/* 58 */ {IOCFG_1_BASE + 0x010}, +/* 59 */ {IOCFG_1_BASE + 0x010}, +/* 60 */ {IOCFG_1_BASE + 0x010}, +/* 61 */ {IOCFG_1_BASE + 0x010}, +/* 62 */ {IOCFG_1_BASE + 0x010}, +/* 63 */ {IOCFG_1_BASE + 0x010}, +/* 64 */ {IOCFG_1_BASE + 0x010}, +/* 65 */ {IOCFG_1_BASE + 0x010}, +/* 66 */ {IOCFG_1_BASE + 0x010}, +/* 67 */ {IOCFG_1_BASE + 0x010}, +/* 68 */ {IOCFG_1_BASE + 0x010}, +/* 69 */ {IOCFG_1_BASE + 0x010}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {IOCFG_2_BASE + 0x010}, +/* 76 */ {IOCFG_2_BASE + 0x010}, +/* 77 */ {IOCFG_2_BASE + 0x010}, +/* 78 */ {IOCFG_2_BASE + 0x010}, +/* 79 */ {IOCFG_2_BASE + 0x010}, +/* 80 */ {IOCFG_2_BASE + 0x010}, +/* 81 */ {IOCFG_2_BASE + 0x010}, +/* 82 */ {IOCFG_2_BASE + 0x010}, +/* 83 */ {IOCFG_2_BASE + 0x010}, +/* 84 */ {IOCFG_2_BASE + 0x010}, +/* 85 */ {IOCFG_2_BASE + 0x010}, +/* 86 */ {IOCFG_2_BASE + 0x010}, +/* 87 */ {IOCFG_2_BASE + 0x010}, +/* 88 */ {IOCFG_2_BASE + 0x010}, +/* 89 */ {IOCFG_2_BASE + 0x010}, +/* 90 */ {IOCFG_2_BASE + 0x010}, +/* 91 */ {IOCFG_3_BASE + 0x010}, +/* 92 */ {IOCFG_3_BASE + 0x010}, +/* 93 */ {IOCFG_3_BASE + 0x010}, +/* 94 */ {IOCFG_3_BASE + 0x010}, +/* 95 */ {IOCFG_3_BASE + 0x010}, +/* 96 */ {IOCFG_3_BASE + 0x010}, +/* 97 */ {IOCFG_3_BASE + 0x010}, +/* 98 */ {IOCFG_3_BASE + 0x010}, +/* 99 */ {IOCFG_3_BASE + 0x010}, +/* 100 */ {IOCFG_3_BASE + 0x010}, +/* 101 */ {IOCFG_3_BASE + 0x010}, +/* 102 */ {IOCFG_3_BASE + 0x010}, +/* 103 */ {IOCFG_3_BASE + 0x010}, +/* 104 */ {IOCFG_3_BASE + 0x010}, +/* 105 */ {IOCFG_3_BASE + 0x010}, +/* 106 */ {IOCFG_3_BASE + 0x010}, +/* 107 */ {IOCFG_3_BASE + 0x010}, +/* 108 */ {IOCFG_3_BASE + 0x010}, +/* 109 */ {IOCFG_3_BASE + 0x010}, +/* 110 */ {IOCFG_3_BASE + 0x010}, +/* 111 */ {IOCFG_3_BASE + 0x010}, +/* 112 */ {IOCFG_3_BASE + 0x010}, +/* 113 */ {IOCFG_3_BASE + 0x010}, +/* 114 */ {IOCFG_4_BASE + 0x010}, +/* 115 */ {IOCFG_4_BASE + 0x010}, +/* 116 */ {IOCFG_4_BASE + 0x010}, +/* 117 */ {IOCFG_4_BASE + 0x010}, +/* 118 */ {IOCFG_4_BASE + 0x010}, +/* 119 */ {IOCFG_4_BASE + 0x010}, +/* 120 */ {IOCFG_4_BASE + 0x010}, +/* 121 */ {IOCFG_4_BASE + 0x010}, +/* 122 */ {IOCFG_4_BASE + 0x010}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {IOCFG_4_BASE + 0x010}, +/* 132 */ {IOCFG_4_BASE + 0x010}, +/* 133 */ {IOCFG_4_BASE + 0x010}, +/* 134 */ {IOCFG_4_BASE + 0x010}, +/* 135 */ {IOCFG_4_BASE + 0x010}, +/* 136 */ {IOCFG_4_BASE + 0x010}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {IOCFG_0_BASE + 0x010}, +/* 148 */ {IOCFG_0_BASE + 0x010}, +/* 149 */ {IOCFG_0_BASE + 0x010}, +/* 150 */ {IOCFG_0_BASE + 0x010}, +/* 151 */ {IOCFG_0_BASE + 0x010}, +/* 152 */ {IOCFG_0_BASE + 0x010}, +/* 153 */ {IOCFG_0_BASE + 0x010}, +/* 154 */ {IOCFG_0_BASE + 0x010}, +/* 155 */ {IOCFG_0_BASE + 0x010}, +/* 156 */ {IOCFG_0_BASE + 0x010}, +/* 157 */ {IOCFG_1_BASE + 0x010}, +/* 158 */ {IOCFG_1_BASE + 0x010}, +/* 159 */ {IOCFG_1_BASE + 0x010}, +/* 160 */ {IOCFG_1_BASE + 0x010}, +/* 161 */ {IOCFG_3_BASE + 0x010}, + /* 162 */ {-1}, + /* 163 */ {-1}, + /* 164 */ {-1}, + /* 165 */ {-1}, + /* 166 */ {-1}, + /* 167 */ {-1}, + /* 168 */ {-1}, + /* 169 */ {-1}, + /* 170 */ {-1}, + /* 171 */ {-1}, + /* 172 */ {-1}, + /* 173 */ {-1}, + /* 174 */ {-1}, + /* 175 */ {-1}, + /* 176 */ {-1}, + /* 177 */ {-1}, +/* 178 */ {IOCFG_5_BASE + 0x010}, +/* 179 */ {IOCFG_5_BASE + 0x010}, +/* 180 */ {IOCFG_5_BASE + 0x010}, +/* 181 */ {IOCFG_5_BASE + 0x010}, +/* 182 */ {IOCFG_5_BASE + 0x010}, +/* 183 */ {IOCFG_5_BASE + 0x010}, +/* 184 */ {IOCFG_5_BASE + 0x010}, +/* 185 */ {IOCFG_5_BASE + 0x010}, +/* 186 */ {IOCFG_5_BASE + 0x010}, +/* 187 */ {IOCFG_5_BASE + 0x010}, +/* 188 */ {IOCFG_5_BASE + 0x010}, +/* 189 */ {IOCFG_5_BASE + 0x010} +}; + + +PIN_offset SMT_offset[] = { +/* 0 */ {5}, +/* 1 */ {5}, +/* 2 */ {5}, +/* 3 */ {5}, +/* 4 */ {6}, +/* 5 */ {6}, +/* 6 */ {6}, +/* 7 */ {6}, +/* 8 */ {12}, +/* 9 */ {13}, +/* 10 */ {13}, +/* 11 */ {3}, +/* 12 */ {7}, +/* 13 */ {5}, +/* 14 */ {5}, +/* 15 */ {5}, +/* 16 */ {5}, +/* 17 */ {6}, +/* 18 */ {6}, +/* 19 */ {6}, +/* 20 */ {6}, +/* 21 */ {7}, +/* 22 */ {7}, +/* 23 */ {7}, +/* 24 */ {7}, +/* 25 */ {8}, +/* 26 */ {8}, +/* 27 */ {8}, +/* 28 */ {8}, +/* 29 */ {6}, +/* 30 */ {8}, +/* 31 */ {9}, +/* 32 */ {10}, +/* 33 */ {9}, +/* 34 */ {9}, +/* 35 */ {9}, +/* 36 */ {11}, +/* 37 */ {11}, +/* 38 */ {11}, +/* 39 */ {12}, +/* 40 */ {12}, +/* 41 */ {12}, +/* 42 */ {0}, +/* 43 */ {0}, +/* 44 */ {1}, +/* 45 */ {2}, +/* 46 */ {2}, +/* 47 */ {3}, +/* 48 */ {3}, +/* 49 */ {4}, +/* 50 */ {4}, +/* 51 */ {9}, +/* 52 */ {9}, +/* 53 */ {9}, +/* 54 */ {9}, +/* 55 */ {9}, +/* 56 */ {9}, +/* 57 */ {9}, +/* 58 */ {9}, +/* 59 */ {9}, +/* 60 */ {9}, +/* 61 */ {9}, +/* 62 */ {9}, +/* 63 */ {10}, +/* 64 */ {10}, +/* 65 */ {10}, +/* 66 */ {10}, +/* 67 */ {11}, +/* 68 */ {11}, +/* 69 */ {11}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {0}, +/* 76 */ {0}, +/* 77 */ {0}, +/* 78 */ {0}, +/* 79 */ {1}, +/* 80 */ {1}, +/* 81 */ {1}, +/* 82 */ {1}, +/* 83 */ {2}, +/* 84 */ {2}, + /* 85 */ {2}, +/* 86 */ {2}, +/* 87 */ {3}, +/* 88 */ {3}, +/* 89 */ {3}, +/* 90 */ {3}, +/* 91 */ {0}, +/* 92 */ {1}, +/* 93 */ {1}, +/* 94 */ {0}, +/* 95 */ {2}, +/* 96 */ {2}, +/* 97 */ {2}, +/* 98 */ {2}, +/* 99 */ {3}, +/* 100 */ {3}, +/* 101 */ {4}, +/* 102 */ {4}, +/* 103 */ {4}, +/* 104 */ {4}, +/* 105 */ {7}, +/* 106 */ {7}, +/* 107 */ {8}, +/* 108 */ {8}, +/* 109 */ {10}, +/* 110 */ {11}, +/* 111 */ {11}, +/* 112 */ {14}, +/* 113 */ {14}, +/* 114 */ {0}, +/* 115 */ {0}, +/* 116 */ {0}, +/* 117 */ {1}, +/* 118 */ {1}, +/* 119 */ {2}, +/* 120 */ {2}, +/* 121 */ {2}, +/* 122 */ {2}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {3}, +/* 132 */ {4}, +/* 133 */ {5}, +/* 134 */ {3}, +/* 135 */ {3}, +/* 136 */ {3}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {0}, +/* 148 */ {1}, +/* 149 */ {2}, +/* 150 */ {2}, +/* 151 */ {2}, +/* 152 */ {4}, +/* 153 */ {4}, +/* 154 */ {4}, +/* 155 */ {4}, +/* 156 */ {5}, +/* 157 */ {1}, +/* 158 */ {1}, +/* 159 */ {11}, +/* 160 */ {11}, +/* 161 */ {9}, + /* 162 */ {-1}, + /* 163 */ {-1}, + /* 164 */ {-1}, + /* 165 */ {-1}, + /* 166 */ {-1}, + /* 167 */ {-1}, + /* 168 */ {-1}, + /* 169 */ {-1}, + /* 170 */ {-1}, + /* 171 */ {-1}, + /* 172 */ {-1}, + /* 173 */ {-1}, + /* 174 */ {-1}, + /* 175 */ {-1}, + /* 176 */ {-1}, + /* 177 */ {-1}, +/* 178 */ {0}, +/* 179 */ {1}, +/* 180 */ {2}, +/* 181 */ {0}, +/* 182 */ {0}, +/* 183 */ {0}, +/* 184 */ {0}, +/* 185 */ {3}, +/* 186 */ {0}, +/* 187 */ {0}, +/* 188 */ {0}, +/* 189 */ {4} +}; + + +PIN_addr PULLEN_addr[] = { +/* 0 */ {IOCFG_3_BASE + 0x060}, +/* 1 */ {IOCFG_3_BASE + 0x060}, +/* 2 */ {IOCFG_3_BASE + 0x060}, +/* 3 */ {IOCFG_3_BASE + 0x060}, +/* 4 */ {IOCFG_3_BASE + 0x060}, +/* 5 */ {IOCFG_3_BASE + 0x060}, +/* 6 */ {IOCFG_3_BASE + 0x060}, +/* 7 */ {IOCFG_3_BASE + 0x060}, +/* 8 */ {IOCFG_3_BASE + 0x060}, +/* 9 */ {IOCFG_3_BASE + 0x060}, +/* 10 */ {IOCFG_3_BASE + 0x070}, +/* 11 */ {IOCFG_0_BASE + 0x060}, +/* 12 */ {IOCFG_0_BASE + 0x060}, +/* 13 */ {IOCFG_1_BASE + 0x060}, +/* 14 */ {IOCFG_1_BASE + 0x060}, +/* 15 */ {IOCFG_1_BASE + 0x060}, +/* 16 */ {IOCFG_1_BASE + 0x060}, +/* 17 */ {IOCFG_1_BASE + 0x060}, +/* 18 */ {IOCFG_1_BASE + 0x060}, +/* 19 */ {IOCFG_1_BASE + 0x060}, +/* 20 */ {IOCFG_1_BASE + 0x060}, +/* 21 */ {IOCFG_1_BASE + 0x060}, +/* 22 */ {IOCFG_1_BASE + 0x060}, +/* 23 */ {IOCFG_1_BASE + 0x060}, +/* 24 */ {IOCFG_1_BASE + 0x060}, +/* 25 */ {IOCFG_1_BASE + 0x060}, +/* 26 */ {IOCFG_1_BASE + 0x060}, +/* 27 */ {IOCFG_1_BASE + 0x060}, +/* 28 */ {IOCFG_1_BASE + 0x060}, +/* 29 */ {IOCFG_0_BASE + 0x060}, +/* 30 */ {-1}, +/* 31 */ {-1}, +/* 32 */ {-1}, +/* 33 */ {-1}, +/* 34 */ {-1}, +/* 35 */ {-1}, +/* 36 */ {-1}, +/* 37 */ {-1}, +/* 38 */ {-1}, +/* 39 */ {-1}, +/* 40 */ {-1}, +/* 41 */ {-1}, +/* 42 */ {-1}, +/* 43 */ {-1}, +/* 44 */ {IOCFG_1_BASE + 0x060}, +/* 45 */ {IOCFG_1_BASE + 0x060}, +/* 46 */ {IOCFG_1_BASE + 0x060}, +/* 47 */ {IOCFG_1_BASE + 0x060}, +/* 48 */ {IOCFG_1_BASE + 0x060}, +/* 49 */ {IOCFG_1_BASE + 0x060}, +/* 50 */ {IOCFG_1_BASE + 0x060}, +/* 51 */ {IOCFG_1_BASE + 0x060}, +/* 52 */ {IOCFG_1_BASE + 0x060}, +/* 53 */ {IOCFG_1_BASE + 0x060}, +/* 54 */ {IOCFG_1_BASE + 0x060}, +/* 55 */ {IOCFG_1_BASE + 0x060}, +/* 56 */ {IOCFG_1_BASE + 0x070}, +/* 57 */ {IOCFG_1_BASE + 0x070}, +/* 58 */ {IOCFG_1_BASE + 0x070}, +/* 59 */ {IOCFG_1_BASE + 0x070}, +/* 60 */ {IOCFG_1_BASE + 0x070}, +/* 61 */ {IOCFG_1_BASE + 0x070}, +/* 62 */ {IOCFG_1_BASE + 0x070}, +/* 63 */ {IOCFG_1_BASE + 0x070}, +/* 64 */ {IOCFG_1_BASE + 0x070}, +/* 65 */ {IOCFG_1_BASE + 0x070}, +/* 66 */ {IOCFG_1_BASE + 0x070}, +/* 67 */ {IOCFG_1_BASE + 0x070}, +/* 68 */ {IOCFG_1_BASE + 0x070}, +/* 69 */ {IOCFG_1_BASE + 0x070}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {IOCFG_2_BASE + 0x060}, +/* 76 */ {IOCFG_2_BASE + 0x060}, +/* 77 */ {IOCFG_2_BASE + 0x060}, +/* 78 */ {IOCFG_2_BASE + 0x060}, +/* 79 */ {IOCFG_2_BASE + 0x060}, +/* 80 */ {IOCFG_2_BASE + 0x060}, +/* 81 */ {IOCFG_2_BASE + 0x060}, +/* 82 */ {IOCFG_2_BASE + 0x060}, +/* 83 */ {IOCFG_2_BASE + 0x060}, +/* 84 */ {IOCFG_2_BASE + 0x060}, +/* 85 */ {IOCFG_2_BASE + 0x060}, +/* 86 */ {IOCFG_2_BASE + 0x060}, +/* 87 */ {IOCFG_2_BASE + 0x060}, +/* 88 */ {IOCFG_2_BASE + 0x060}, +/* 89 */ {IOCFG_2_BASE + 0x060}, +/* 90 */ {IOCFG_2_BASE + 0x060}, +/* 91 */ {IOCFG_3_BASE + 0x060}, +/* 92 */ {IOCFG_3_BASE + 0x060}, +/* 93 */ {IOCFG_3_BASE + 0x060}, +/* 94 */ {IOCFG_3_BASE + 0x060}, +/* 95 */ {IOCFG_3_BASE + 0x060}, +/* 96 */ {IOCFG_3_BASE + 0x060}, +/* 97 */ {IOCFG_3_BASE + 0x060}, +/* 98 */ {IOCFG_3_BASE + 0x060}, +/* 99 */ {IOCFG_3_BASE + 0x060}, +/* 100 */ {IOCFG_3_BASE + 0x060}, +/* 101 */ {-1}, +/* 102 */ {-1}, +/* 103 */ {-1}, +/* 104 */ {-1}, +/* 105 */ {IOCFG_3_BASE + 0x060}, +/* 106 */ {IOCFG_3_BASE + 0x060}, +/* 107 */ {IOCFG_3_BASE + 0x060}, +/* 108 */ {IOCFG_3_BASE + 0x060}, +/* 109 */ {IOCFG_3_BASE + 0x060}, +/* 110 */ {IOCFG_3_BASE + 0x060}, +/* 111 */ {IOCFG_3_BASE + 0x060}, +/* 112 */ {IOCFG_3_BASE + 0x070}, +/* 113 */ {IOCFG_3_BASE + 0x070}, +/* 114 */ {-1}, +/* 115 */ {-1}, +/* 116 */ {-1}, +/* 117 */ {IOCFG_4_BASE + 0x060}, +/* 118 */ {IOCFG_4_BASE + 0x060}, +/* 119 */ {IOCFG_4_BASE + 0x060}, +/* 120 */ {IOCFG_4_BASE + 0x060}, +/* 121 */ {IOCFG_4_BASE + 0x060}, +/* 122 */ {IOCFG_4_BASE + 0x060}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {-1}, +/* 132 */ {-1}, +/* 133 */ {-1}, +/* 134 */ {-1}, +/* 135 */ {-1}, +/* 136 */ {-1}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {IOCFG_0_BASE + 0x060}, +/* 148 */ {IOCFG_0_BASE + 0x060}, +/* 149 */ {IOCFG_0_BASE + 0x060}, +/* 150 */ {IOCFG_0_BASE + 0x060}, +/* 151 */ {IOCFG_0_BASE + 0x060}, +/* 152 */ {IOCFG_0_BASE + 0x060}, +/* 153 */ {IOCFG_0_BASE + 0x060}, +/* 154 */ {IOCFG_0_BASE + 0x060}, +/* 155 */ {IOCFG_0_BASE + 0x060}, +/* 156 */ {IOCFG_0_BASE + 0x060}, +/* 157 */ {IOCFG_1_BASE + 0x060}, +/* 158 */ {IOCFG_1_BASE + 0x060}, +/* 159 */ {IOCFG_1_BASE + 0x070}, +/* 160 */ {IOCFG_1_BASE + 0x070}, +/* 161 */ {IOCFG_3_BASE + 0x060}, + /* 162 */ {-1}, + /* 163 */ {-1}, + /* 164 */ {-1}, + /* 165 */ {-1}, + /* 166 */ {-1}, + /* 167 */ {-1}, + /* 168 */ {-1}, + /* 169 */ {-1}, + /* 170 */ {-1}, + /* 171 */ {-1}, + /* 172 */ {-1}, + /* 173 */ {-1}, + /* 174 */ {-1}, + /* 175 */ {-1}, + /* 176 */ {-1}, + /* 177 */ {-1}, + /* 178 */ {-1}, + /* 179 */ {-1}, + /* 180 */ {-1}, + /* 181 */ {-1}, + /* 182 */ {-1}, + /* 183 */ {-1}, + /* 184 */ {-1}, + /* 185 */ {-1}, +/* 186 */ {-1}, +/* 187 */ {-1}, +/* 188 */ {-1}, +/* 189 */ {-1} +}; + +PIN_offset PULLEN_offset[] = { +/* 0 */ {14}, +/* 1 */ {15}, +/* 2 */ {16}, +/* 3 */ {17}, +/* 4 */ {18}, +/* 5 */ {19}, +/* 6 */ {20}, +/* 7 */ {21}, +/* 8 */ {30}, +/* 9 */ {31}, +/* 10 */ {0}, +/* 11 */ {5}, +/* 12 */ {12}, +/* 13 */ {11}, +/* 14 */ {12}, +/* 15 */ {13}, +/* 16 */ {14}, +/* 17 */ {15}, +/* 18 */ {16}, +/* 19 */ {17}, +/* 20 */ {18}, +/* 21 */ {19}, +/* 22 */ {20}, +/* 23 */ {21}, +/* 24 */ {22}, +/* 25 */ {23}, +/* 26 */ {24}, +/* 27 */ {25}, +/* 28 */ {26}, +/* 29 */ {11}, +/* 30 */ {-1}, +/* 31 */ {-1}, +/* 32 */ {-1}, +/* 33 */ {-1}, +/* 34 */ {-1}, +/* 35 */ {-1}, +/* 36 */ {-1}, +/* 37 */ {-1}, +/* 38 */ {-1}, +/* 39 */ {-1}, +/* 40 */ {-1}, +/* 41 */ {-1}, +/* 42 */ {-1}, +/* 43 */ {-1}, +/* 44 */ {3}, +/* 45 */ {5}, +/* 46 */ {6}, +/* 47 */ {7}, +/* 48 */ {8}, +/* 49 */ {9}, +/* 50 */ {10}, +/* 51 */ {27}, + /* 52 */ {28}, +/* 53 */ {29}, +/* 54 */ {30}, +/* 55 */ {31}, +/* 56 */ {0}, +/* 57 */ {1}, +/* 58 */ {2}, +/* 59 */ {3}, +/* 60 */ {4}, +/* 61 */ {5}, +/* 62 */ {6}, +/* 63 */ {7}, +/* 64 */ {8}, +/* 65 */ {9}, +/* 66 */ {10}, +/* 67 */ {11}, +/* 68 */ {12}, +/* 69 */ {13}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {0}, +/* 76 */ {1}, +/* 77 */ {2}, +/* 78 */ {3}, +/* 79 */ {4}, +/* 80 */ {5}, +/* 81 */ {6}, +/* 82 */ {7}, +/* 83 */ {8}, +/* 84 */ {9}, +/* 85 */ {10}, +/* 86 */ {11}, +/* 87 */ {12}, +/* 88 */ {13}, +/* 89 */ {14}, +/* 90 */ {15}, +/* 91 */ {0}, +/* 92 */ {1}, +/* 93 */ {2}, +/* 94 */ {3}, +/* 95 */ {4}, +/* 96 */ {5}, +/* 97 */ {6}, +/* 98 */ {7}, +/* 99 */ {8}, +/* 100 */ {9}, +/* 101 */ {-1}, +/* 102 */ {-1}, +/* 103 */ {-1}, +/* 104 */ {-1}, +/* 105 */ {22}, +/* 106 */ {23}, +/* 107 */ {24}, +/* 108 */ {25}, +/* 109 */ {27}, +/* 110 */ {28}, +/* 111 */ {29}, +/* 112 */ {1}, +/* 113 */ {2}, +/* 114 */ {-1}, +/* 115 */ {-1}, +/* 116 */ {-1}, +/* 117 */ {3}, +/* 118 */ {4}, +/* 119 */ {5}, +/* 120 */ {6}, +/* 121 */ {7}, +/* 122 */ {8}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {-1}, +/* 132 */ {-1}, +/* 133 */ {-1}, +/* 134 */ {-1}, +/* 135 */ {-1}, +/* 136 */ {-1}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {0}, +/* 148 */ {1}, +/* 149 */ {2}, +/* 150 */ {3}, +/* 151 */ {4}, +/* 152 */ {6}, +/* 153 */ {7}, +/* 154 */ {8}, +/* 155 */ {9}, +/* 156 */ {10}, +/* 157 */ {2}, +/* 158 */ {4}, +/* 159 */ {14}, +/* 160 */ {15}, +/* 161 */ {26}, + /* 162 */ {-1}, + /* 163 */ {-1}, + /* 164 */ {-1}, + /* 165 */ {-1}, + /* 166 */ {-1}, + /* 167 */ {-1}, + /* 168 */ {-1}, + /* 169 */ {-1}, + /* 170 */ {-1}, + /* 171 */ {-1}, + /* 172 */ {-1}, + /* 173 */ {-1}, + /* 174 */ {-1}, + /* 175 */ {-1}, + /* 176 */ {-1}, + /* 177 */ {-1}, + /* 178 */ {-1}, + /* 179 */ {-1}, + /* 180 */ {-1}, + /* 181 */ {-1}, + /* 182 */ {-1}, + /* 183 */ {-1}, + /* 184 */ {-1}, + /* 185 */ {-1}, +/* 186 */ {-1}, +/* 187 */ {-1}, +/* 188 */ {-1}, +/* 189 */ {-1} +}; + + +PIN_addr PULLSEL_addr[] = { +/* 0 */ {IOCFG_3_BASE + 0x080}, +/* 1 */ {IOCFG_3_BASE + 0x080}, +/* 2 */ {IOCFG_3_BASE + 0x080}, +/* 3 */ {IOCFG_3_BASE + 0x080}, +/* 4 */ {IOCFG_3_BASE + 0x080}, +/* 5 */ {IOCFG_3_BASE + 0x080}, +/* 6 */ {IOCFG_3_BASE + 0x080}, +/* 7 */ {IOCFG_3_BASE + 0x080}, +/* 8 */ {IOCFG_3_BASE + 0x080}, +/* 9 */ {IOCFG_3_BASE + 0x080}, +/* 10 */ {IOCFG_3_BASE + 0x090}, +/* 11 */ {IOCFG_0_BASE + 0x080}, +/* 12 */ {IOCFG_0_BASE + 0x080}, +/* 13 */ {IOCFG_1_BASE + 0x080}, +/* 14 */ {IOCFG_1_BASE + 0x080}, +/* 15 */ {IOCFG_1_BASE + 0x080}, +/* 16 */ {IOCFG_1_BASE + 0x080}, +/* 17 */ {IOCFG_1_BASE + 0x080}, +/* 18 */ {IOCFG_1_BASE + 0x080}, +/* 19 */ {IOCFG_1_BASE + 0x080}, +/* 20 */ {IOCFG_1_BASE + 0x080}, +/* 21 */ {IOCFG_1_BASE + 0x080}, +/* 22 */ {IOCFG_1_BASE + 0x080}, +/* 23 */ {IOCFG_1_BASE + 0x080}, +/* 24 */ {IOCFG_1_BASE + 0x080}, +/* 25 */ {IOCFG_1_BASE + 0x080}, +/* 26 */ {IOCFG_1_BASE + 0x080}, +/* 27 */ {IOCFG_1_BASE + 0x080}, +/* 28 */ {IOCFG_1_BASE + 0x080}, +/* 29 */ {IOCFG_0_BASE + 0x080}, +/* 30 */ {-1}, +/* 31 */ {-1}, +/* 32 */ {-1}, +/* 33 */ {-1}, +/* 34 */ {-1}, +/* 35 */ {-1}, +/* 36 */ {-1}, +/* 37 */ {-1}, +/* 38 */ {-1}, +/* 39 */ {-1}, +/* 40 */ {-1}, +/* 41 */ {-1}, +/* 42 */ {-1}, +/* 43 */ {-1}, +/* 44 */ {IOCFG_1_BASE + 0x080}, +/* 45 */ {IOCFG_1_BASE + 0x080}, +/* 46 */ {IOCFG_1_BASE + 0x080}, +/* 47 */ {IOCFG_1_BASE + 0x080}, +/* 48 */ {IOCFG_1_BASE + 0x080}, +/* 49 */ {IOCFG_1_BASE + 0x080}, +/* 50 */ {IOCFG_1_BASE + 0x080}, +/* 51 */ {IOCFG_1_BASE + 0x080}, +/* 52 */ {IOCFG_1_BASE + 0x080}, +/* 53 */ {IOCFG_1_BASE + 0x080}, +/* 54 */ {IOCFG_1_BASE + 0x080}, +/* 55 */ {IOCFG_1_BASE + 0x080}, +/* 56 */ {IOCFG_1_BASE + 0x090}, +/* 57 */ {IOCFG_1_BASE + 0x090}, +/* 58 */ {IOCFG_1_BASE + 0x090}, +/* 59 */ {IOCFG_1_BASE + 0x090}, +/* 60 */ {IOCFG_1_BASE + 0x090}, +/* 61 */ {IOCFG_1_BASE + 0x090}, +/* 62 */ {IOCFG_1_BASE + 0x090}, +/* 63 */ {IOCFG_1_BASE + 0x090}, +/* 64 */ {IOCFG_1_BASE + 0x090}, +/* 65 */ {IOCFG_1_BASE + 0x090}, +/* 66 */ {IOCFG_1_BASE + 0x090}, +/* 67 */ {IOCFG_1_BASE + 0x090}, +/* 68 */ {IOCFG_1_BASE + 0x090}, +/* 69 */ {IOCFG_1_BASE + 0x090}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {IOCFG_2_BASE + 0x080}, +/* 76 */ {IOCFG_2_BASE + 0x080}, +/* 77 */ {IOCFG_2_BASE + 0x080}, +/* 78 */ {IOCFG_2_BASE + 0x080}, +/* 79 */ {IOCFG_2_BASE + 0x080}, +/* 80 */ {IOCFG_2_BASE + 0x080}, +/* 81 */ {IOCFG_2_BASE + 0x080}, +/* 82 */ {IOCFG_2_BASE + 0x080}, +/* 83 */ {IOCFG_2_BASE + 0x080}, +/* 84 */ {IOCFG_2_BASE + 0x080}, +/* 85 */ {IOCFG_2_BASE + 0x080}, +/* 86 */ {IOCFG_2_BASE + 0x080}, +/* 87 */ {IOCFG_2_BASE + 0x080}, +/* 88 */ {IOCFG_2_BASE + 0x080}, +/* 89 */ {IOCFG_2_BASE + 0x080}, +/* 90 */ {IOCFG_2_BASE + 0x080}, +/* 91 */ {IOCFG_3_BASE + 0x080}, +/* 92 */ {IOCFG_3_BASE + 0x080}, +/* 93 */ {IOCFG_3_BASE + 0x080}, +/* 94 */ {IOCFG_3_BASE + 0x080}, +/* 95 */ {IOCFG_3_BASE + 0x080}, +/* 96 */ {IOCFG_3_BASE + 0x080}, +/* 97 */ {IOCFG_3_BASE + 0x080}, +/* 98 */ {IOCFG_3_BASE + 0x080}, +/* 99 */ {IOCFG_3_BASE + 0x080}, +/* 100 */ {IOCFG_3_BASE + 0x080}, +/* 101 */ {-1}, +/* 102 */ {-1}, +/* 103 */ {-1}, +/* 104 */ {-1}, +/* 105 */ {IOCFG_3_BASE + 0x080}, +/* 106 */ {IOCFG_3_BASE + 0x080}, +/* 107 */ {IOCFG_3_BASE + 0x080}, +/* 108 */ {IOCFG_3_BASE + 0x080}, +/* 109 */ {IOCFG_3_BASE + 0x080}, +/* 110 */ {IOCFG_3_BASE + 0x080}, +/* 111 */ {IOCFG_3_BASE + 0x080}, +/* 112 */ {IOCFG_3_BASE + 0x090}, +/* 113 */ {IOCFG_3_BASE + 0x090}, +/* 114 */ {-1}, +/* 115 */ {-1}, +/* 116 */ {-1}, +/* 117 */ {IOCFG_4_BASE + 0x080}, +/* 118 */ {IOCFG_4_BASE + 0x080}, +/* 119 */ {IOCFG_4_BASE + 0x080}, +/* 120 */ {IOCFG_4_BASE + 0x080}, +/* 121 */ {IOCFG_4_BASE + 0x080}, +/* 122 */ {IOCFG_4_BASE + 0x080}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {-1}, +/* 132 */ {-1}, +/* 133 */ {-1}, +/* 134 */ {-1}, +/* 135 */ {-1}, +/* 136 */ {-1}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {IOCFG_0_BASE + 0x080}, +/* 148 */ {IOCFG_0_BASE + 0x080}, +/* 149 */ {IOCFG_0_BASE + 0x080}, +/* 150 */ {IOCFG_0_BASE + 0x080}, +/* 151 */ {IOCFG_0_BASE + 0x080}, +/* 152 */ {IOCFG_0_BASE + 0x080}, +/* 153 */ {IOCFG_0_BASE + 0x080}, +/* 154 */ {IOCFG_0_BASE + 0x080}, +/* 155 */ {IOCFG_0_BASE + 0x080}, +/* 156 */ {IOCFG_0_BASE + 0x080}, +/* 157 */ {IOCFG_1_BASE + 0x080}, +/* 158 */ {IOCFG_1_BASE + 0x080}, +/* 159 */ {IOCFG_1_BASE + 0x090}, +/* 160 */ {IOCFG_1_BASE + 0x090}, +/* 161 */ {IOCFG_3_BASE + 0x080}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {-1}, +/* 179 */ {-1}, +/* 180 */ {-1}, +/* 181 */ {-1}, +/* 182 */ {-1}, +/* 183 */ {-1}, +/* 184 */ {-1}, +/* 185 */ {-1}, +/* 186 */ {-1}, +/* 187 */ {-1}, +/* 188 */ {-1}, +/* 189 */ {-1} +}; + +PIN_offset PULLSEL_offset[] = { +/* 0 */ {14}, +/* 1 */ {15}, +/* 2 */ {16}, +/* 3 */ {17}, +/* 4 */ {18}, +/* 5 */ {19}, +/* 6 */ {20}, +/* 7 */ {21}, +/* 8 */ {30}, +/* 9 */ {31}, +/* 10 */ {0}, +/* 11 */ {5}, +/* 12 */ {12}, +/* 13 */ {11}, +/* 14 */ {12}, +/* 15 */ {13}, +/* 16 */ {14}, +/* 17 */ {15}, +/* 18 */ {16}, +/* 19 */ {17}, +/* 20 */ {18}, +/* 21 */ {19}, +/* 22 */ {20}, +/* 23 */ {21}, +/* 24 */ {22}, +/* 25 */ {23}, +/* 26 */ {24}, +/* 27 */ {25}, +/* 28 */ {26}, +/* 29 */ {11}, +/* 30 */ {-1}, +/* 31 */ {-1}, +/* 32 */ {-1}, +/* 33 */ {-1}, +/* 34 */ {-1}, +/* 35 */ {-1}, +/* 36 */ {-1}, +/* 37 */ {-1}, +/* 38 */ {-1}, +/* 39 */ {-1}, +/* 40 */ {-1}, +/* 41 */ {-1}, +/* 42 */ {-1}, +/* 43 */ {-1}, +/* 44 */ {3}, +/* 45 */ {5}, +/* 46 */ {6}, +/* 47 */ {7}, +/* 48 */ {8}, +/* 49 */ {9}, +/* 50 */ {10}, +/* 51 */ {27}, +/* 52 */ {28}, +/* 53 */ {29}, +/* 54 */ {30}, +/* 55 */ {31}, +/* 56 */ {0}, +/* 57 */ {1}, +/* 58 */ {2}, +/* 59 */ {3}, +/* 60 */ {4}, +/* 61 */ {5}, +/* 62 */ {6}, +/* 63 */ {7}, +/* 64 */ {8}, +/* 65 */ {9}, +/* 66 */ {10}, +/* 67 */ {11}, +/* 68 */ {12}, +/* 69 */ {13}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {0}, +/* 76 */ {1}, +/* 77 */ {2}, +/* 78 */ {3}, +/* 79 */ {4}, +/* 80 */ {5}, +/* 81 */ {6}, +/* 82 */ {7}, +/* 83 */ {8}, +/* 84 */ {9}, +/* 85 */ {10}, +/* 86 */ {11}, +/* 87 */ {12}, +/* 88 */ {13}, +/* 89 */ {14}, +/* 90 */ {15}, +/* 91 */ {0}, +/* 92 */ {1}, +/* 93 */ {2}, +/* 94 */ {3}, +/* 95 */ {4}, +/* 96 */ {5}, +/* 97 */ {6}, +/* 98 */ {7}, +/* 99 */ {8}, +/* 100 */ {9}, +/* 101 */ {-1}, +/* 102 */ {-1}, +/* 103 */ {-1}, +/* 104 */ {-1}, +/* 105 */ {22}, +/* 106 */ {23}, +/* 107 */ {24}, +/* 108 */ {25}, +/* 109 */ {27}, +/* 110 */ {28}, +/* 111 */ {29}, +/* 112 */ {1}, +/* 113 */ {2}, +/* 114 */ {-1}, +/* 115 */ {-1}, +/* 116 */ {-1}, +/* 117 */ {3}, +/* 118 */ {4}, +/* 119 */ {5}, +/* 120 */ {6}, +/* 121 */ {7}, +/* 122 */ {8}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {-1}, +/* 132 */ {-1}, +/* 133 */ {-1}, +/* 134 */ {-1}, +/* 135 */ {-1}, +/* 136 */ {-1}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {0}, +/* 148 */ {1}, +/* 149 */ {2}, +/* 150 */ {3}, +/* 151 */ {4}, +/* 152 */ {6}, +/* 153 */ {7}, +/* 154 */ {8}, +/* 155 */ {9}, +/* 156 */ {10}, +/* 157 */ {2}, +/* 158 */ {4}, +/* 159 */ {14}, +/* 160 */ {15}, +/* 161 */ {26}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {-1}, +/* 179 */ {-1}, +/* 180 */ {-1}, +/* 181 */ {-1}, +/* 182 */ {-1}, +/* 183 */ {-1}, +/* 184 */ {-1}, +/* 185 */ {-1}, +/* 186 */ {-1}, +/* 187 */ {-1}, +/* 188 */ {-1}, +/* 189 */ {-1} +}; + + +PIN_addr PUPD_addr[] = { + /* 0 */ {-1}, + /* 1 */ {-1}, + /* 2 */ {-1}, + /* 3 */ {-1}, + /* 4 */ {-1}, + /* 5 */ {-1}, + /* 6 */ {-1}, + /* 7 */ {-1}, + /* 8 */ {-1}, + /* 9 */ {-1}, + /* 10 */ {-1}, + /* 11 */ {-1}, + /* 12 */ {-1}, + /* 13 */ {-1}, + /* 14 */ {-1}, + /* 15 */ {-1}, + /* 16 */ {-1}, + /* 17 */ {-1}, + /* 18 */ {-1}, + /* 19 */ {-1}, + /* 20 */ {-1}, + /* 21 */ {-1}, + /* 22 */ {-1}, + /* 23 */ {-1}, + /* 24 */ {-1}, + /* 25 */ {-1}, + /* 26 */ {-1}, + /* 27 */ {-1}, + /* 28 */ {-1}, + /* 29 */ {-1}, +/* 30 */ {IOCFG_0_BASE + 0x0C0}, +/* 31 */ {IOCFG_0_BASE + 0x0C0}, +/* 32 */ {IOCFG_0_BASE + 0x0C0}, +/* 33 */ {IOCFG_0_BASE + 0x0C0}, +/* 34 */ {IOCFG_0_BASE + 0x0C0}, +/* 35 */ {IOCFG_0_BASE + 0x0C0}, +/* 36 */ {IOCFG_0_BASE + 0x0D0}, +/* 37 */ {IOCFG_0_BASE + 0x0D0}, +/* 38 */ {IOCFG_0_BASE + 0x0D0}, +/* 39 */ {IOCFG_0_BASE + 0x0D0}, +/* 40 */ {IOCFG_0_BASE + 0x0D0}, +/* 41 */ {IOCFG_0_BASE + 0x0D0}, +/* 42 */ {IOCFG_1_BASE + 0x0C0}, +/* 43 */ {IOCFG_1_BASE + 0x0C0}, + /* 44 */ {-1}, + /* 45 */ {-1}, + /* 46 */ {-1}, + /* 47 */ {-1}, + /* 48 */ {-1}, + /* 49 */ {-1}, + /* 50 */ {-1}, + /* 51 */ {-1}, + /* 52 */ {-1}, + /* 53 */ {-1}, + /* 54 */ {-1}, + /* 55 */ {-1}, + /* 56 */ {-1}, + /* 57 */ {-1}, + /* 58 */ {-1}, + /* 59 */ {-1}, + /* 60 */ {-1}, + /* 61 */ {-1}, + /* 62 */ {-1}, + /* 63 */ {-1}, + /* 64 */ {-1}, + /* 65 */ {-1}, + /* 66 */ {-1}, + /* 67 */ {-1}, + /* 68 */ {-1}, + /* 69 */ {-1}, + /* 70 */ {-1}, + /* 71 */ {-1}, + /* 72 */ {-1}, + /* 73 */ {-1}, + /* 74 */ {-1}, + /* 75 */ {-1}, + /* 76 */ {-1}, + /* 77 */ {-1}, + /* 78 */ {-1}, + /* 79 */ {-1}, + /* 80 */ {-1}, + /* 81 */ {-1}, + /* 82 */ {-1}, + /* 83 */ {-1}, + /* 84 */ {-1}, + /* 85 */ {-1}, + /* 86 */ {-1}, + /* 87 */ {-1}, + /* 88 */ {-1}, + /* 89 */ {-1}, + /* 90 */ {-1}, + /* 91 */ {-1}, + /* 92 */ {-1}, + /* 93 */ {-1}, + /* 94 */ {-1}, + /* 95 */ {-1}, + /* 96 */ {-1}, + /* 97 */ {-1}, + /* 98 */ {-1}, + /* 99 */ {-1}, + /* 100 */ {-1}, +/* 101 */ {IOCFG_3_BASE + 0x0C0}, +/* 102 */ {IOCFG_3_BASE + 0x0C0}, +/* 103 */ {IOCFG_3_BASE + 0x0C0}, +/* 104 */ {IOCFG_3_BASE + 0x0C0}, + /* 105 */ {-1}, + /* 106 */ {-1}, + /* 107 */ {-1}, + /* 108 */ {-1}, + /* 109 */ {-1}, + /* 110 */ {-1}, + /* 111 */ {-1}, + /* 112 */ {-1}, + /* 113 */ {-1}, +/* 114 */ {IOCFG_4_BASE + 0x0C0}, +/* 115 */ {IOCFG_4_BASE + 0x0C0}, +/* 116 */ {IOCFG_4_BASE + 0x0C0}, + /* 117 */ {-1}, + /* 118 */ {-1}, + /* 119 */ {-1}, + /* 120 */ {-1}, + /* 121 */ {-1}, + /* 122 */ {-1}, + /* 123 */ {-1}, + /* 124 */ {-1}, + /* 125 */ {-1}, + /* 126 */ {-1}, + /* 127 */ {-1}, + /* 128 */ {-1}, + /* 129 */ {-1}, + /* 130 */ {-1}, +/* 131 */ {IOCFG_4_BASE + 0x0C0}, +/* 132 */ {IOCFG_4_BASE + 0x0C0}, +/* 133 */ {IOCFG_4_BASE + 0x0C0}, +/* 134 */ {IOCFG_4_BASE + 0x0C0}, +/* 135 */ {IOCFG_4_BASE + 0x0C0}, +/* 136 */ {IOCFG_4_BASE + 0x0D0}, + /* 137 */ {-1}, + /* 138 */ {-1}, + /* 139 */ {-1}, + /* 140 */ {-1}, + /* 141 */ {-1}, + /* 142 */ {-1}, + /* 143 */ {-1}, + /* 144 */ {-1}, + /* 145 */ {-1}, + /* 146 */ {-1}, + /* 147 */ {-1}, + /* 148 */ {-1}, +/* 149 */ {-1}, +/* 150 */ {-1}, +/* 151 */ {-1}, +/* 152 */ {-1}, +/* 153 */ {-1}, +/* 154 */ {-1}, +/* 155 */ {-1}, +/* 156 */ {-1}, +/* 157 */ {-1}, +/* 158 */ {-1}, +/* 159 */ {-1}, +/* 160 */ {-1}, +/* 161 */ {-1}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {IOCFG_5_BASE + 0x0C0}, +/* 179 */ {IOCFG_5_BASE + 0x0C0}, +/* 180 */ {IOCFG_5_BASE + 0x0C0}, +/* 181 */ {IOCFG_5_BASE + 0x0C0}, +/* 182 */ {IOCFG_5_BASE + 0x0C0}, +/* 183 */ {IOCFG_5_BASE + 0x0C0}, +/* 184 */ {IOCFG_5_BASE + 0x0C0}, +/* 185 */ {IOCFG_5_BASE + 0x0C0}, +/* 186 */ {IOCFG_5_BASE + 0x0D0}, +/* 187 */ {IOCFG_5_BASE + 0x0D0}, +/* 188 */ {IOCFG_5_BASE + 0x0D0}, +/* 189 */ {IOCFG_5_BASE + 0x0D0} +}; + + +PIN_offset PUPD_offset[] = { + /* 0 */ {-1}, + /* 1 */ {-1}, + /* 2 */ {-1}, + /* 3 */ {-1}, + /* 4 */ {-1}, + /* 5 */ {-1}, + /* 6 */ {-1}, + /* 7 */ {-1}, + /* 8 */ {-1}, + /* 9 */ {-1}, + /* 10 */ {-1}, + /* 11 */ {-1}, + /* 12 */ {-1}, + /* 13 */ {-1}, + /* 14 */ {-1}, + /* 15 */ {-1}, + /* 16 */ {-1}, + /* 17 */ {-1}, + /* 18 */ {-1}, + /* 19 */ {-1}, + /* 20 */ {-1}, + /* 21 */ {-1}, + /* 22 */ {-1}, + /* 23 */ {-1}, + /* 24 */ {-1}, + /* 25 */ {-1}, + /* 26 */ {-1}, + /* 27 */ {-1}, + /* 28 */ {-1}, + /* 29 */ {-1}, +/* 30 */ {0}, +/* 31 */ {4}, +/* 32 */ {8}, +/* 33 */ {12}, +/* 34 */ {16}, +/* 35 */ {20}, +/* 36 */ {0}, +/* 37 */ {4}, +/* 38 */ {8}, +/* 39 */ {12}, +/* 40 */ {16}, +/* 41 */ {20}, +/* 42 */ {0}, +/* 43 */ {4}, + /* 44 */ {-1}, + /* 45 */ {-1}, + /* 46 */ {-1}, + /* 47 */ {-1}, + /* 48 */ {-1}, + /* 49 */ {-1}, + /* 50 */ {-1}, + /* 51 */ {-1}, + /* 52 */ {-1}, + /* 53 */ {-1}, + /* 54 */ {-1}, + /* 55 */ {-1}, + /* 56 */ {-1}, + /* 57 */ {-1}, + /* 58 */ {-1}, + /* 59 */ {-1}, + /* 60 */ {-1}, + /* 61 */ {-1}, + /* 62 */ {-1}, + /* 63 */ {-1}, + /* 64 */ {-1}, + /* 65 */ {-1}, + /* 66 */ {-1}, + /* 67 */ {-1}, + /* 68 */ {-1}, + /* 69 */ {-1}, + /* 70 */ {-1}, + /* 71 */ {-1}, + /* 72 */ {-1}, + /* 73 */ {-1}, + /* 74 */ {-1}, + /* 75 */ {-1}, + /* 76 */ {-1}, + /* 77 */ {-1}, + /* 78 */ {-1}, + /* 79 */ {-1}, + /* 80 */ {-1}, + /* 81 */ {-1}, + /* 82 */ {-1}, + /* 83 */ {-1}, + /* 84 */ {-1}, + /* 85 */ {-1}, + /* 86 */ {-1}, + /* 87 */ {-1}, + /* 88 */ {-1}, + /* 89 */ {-1}, + /* 90 */ {-1}, + /* 91 */ {-1}, + /* 92 */ {-1}, + /* 93 */ {-1}, + /* 94 */ {-1}, + /* 95 */ {-1}, + /* 96 */ {-1}, + /* 97 */ {-1}, + /* 98 */ {-1}, + /* 99 */ {-1}, + /* 100 */ {-1}, +/* 101 */ {0}, +/* 102 */ {4}, +/* 103 */ {16}, +/* 104 */ {20}, + /* 105 */ {-1}, + /* 106 */ {-1}, + /* 107 */ {-1}, + /* 108 */ {-1}, + /* 109 */ {-1}, + /* 110 */ {-1}, + /* 111 */ {-1}, + /* 112 */ {-1}, + /* 113 */ {-1}, +/* 114 */ {0}, +/* 115 */ {4}, +/* 116 */ {8}, + /* 117 */ {-1}, + /* 118 */ {-1}, + /* 119 */ {-1}, + /* 120 */ {-1}, + /* 121 */ {-1}, + /* 122 */ {-1}, + /* 123 */ {-1}, + /* 124 */ {-1}, + /* 125 */ {-1}, + /* 126 */ {-1}, + /* 127 */ {-1}, + /* 128 */ {-1}, + /* 129 */ {-1}, + /* 130 */ {-1}, +/* 131 */ {12}, +/* 132 */ {16}, +/* 133 */ {20}, +/* 134 */ {24}, +/* 135 */ {28}, +/* 136 */ {0}, + /* 137 */ {-1}, + /* 138 */ {-1}, + /* 139 */ {-1}, + /* 140 */ {-1}, + /* 141 */ {-1}, + /* 142 */ {-1}, + /* 143 */ {-1}, + /* 144 */ {-1}, + /* 145 */ {-1}, + /* 146 */ {-1}, + /* 147 */ {-1}, + /* 148 */ {-1}, +/* 149 */ {-1}, +/* 150 */ {-1}, +/* 151 */ {-1}, +/* 152 */ {-1}, +/* 153 */ {-1}, +/* 154 */ {-1}, +/* 155 */ {-1}, +/* 156 */ {-1}, +/* 157 */ {-1}, +/* 158 */ {-1}, +/* 159 */ {-1}, +/* 160 */ {-1}, +/* 161 */ {-1}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {0}, +/* 179 */ {4}, +/* 180 */ {8}, +/* 181 */ {12}, +/* 182 */ {16}, +/* 183 */ {20}, +/* 184 */ {24}, +/* 185 */ {28}, +/* 186 */ {0}, +/* 187 */ {4}, +/* 188 */ {8}, +/* 189 */ {12} +}; + + + +PIN_addr MODE_addr[] = { +/* 0 */ {0x300}, +/* 1 */ {0x300}, +/* 2 */ {0x300}, +/* 3 */ {0x300}, +/* 4 */ {0x300}, +/* 5 */ {0x300}, +/* 6 */ {0x300}, +/* 7 */ {0x300}, +/* 8 */ {0x300}, +/* 9 */ {0x300}, +/* 10 */ {0x310}, +/* 11 */ {0x310}, +/* 12 */ {0x310}, +/* 13 */ {0x310}, +/* 14 */ {0x310}, +/* 15 */ {0x310}, +/* 16 */ {0x310}, +/* 17 */ {0x310}, +/* 18 */ {0x310}, +/* 19 */ {0x310}, +/* 20 */ {0x320}, +/* 21 */ {0x320}, +/* 22 */ {0x320}, +/* 23 */ {0x320}, +/* 24 */ {0x320}, +/* 25 */ {0x320}, +/* 26 */ {0x320}, +/* 27 */ {0x320}, +/* 28 */ {0x320}, +/* 29 */ {0x320}, +/* 30 */ {0x330}, +/* 31 */ {0x330}, +/* 32 */ {0x330}, +/* 33 */ {0x330}, +/* 34 */ {0x330}, +/* 35 */ {0x330}, +/* 36 */ {0x330}, +/* 37 */ {0x330}, +/* 38 */ {0x330}, +/* 39 */ {0x330}, +/* 40 */ {0x340}, +/* 41 */ {0x340}, +/* 42 */ {0x340}, +/* 43 */ {0x340}, +/* 44 */ {0x340}, +/* 45 */ {0x340}, +/* 46 */ {0x340}, +/* 47 */ {0x340}, +/* 48 */ {0x340}, +/* 49 */ {0x340}, +/* 50 */ {0x350}, +/* 51 */ {0x350}, +/* 52 */ {0x350}, +/* 53 */ {0x350}, +/* 54 */ {0x350}, +/* 55 */ {0x350}, +/* 56 */ {0x350}, +/* 57 */ {0x350}, +/* 58 */ {0x350}, +/* 59 */ {0x350}, +/* 60 */ {0x360}, +/* 61 */ {0x360}, +/* 62 */ {0x360}, +/* 63 */ {0x360}, +/* 64 */ {0x360}, +/* 65 */ {0x360}, +/* 66 */ {0x360}, +/* 67 */ {0x360}, +/* 68 */ {0x360}, +/* 69 */ {0x360}, +/* 70 */ {0x370}, +/* 71 */ {0x370}, +/* 72 */ {0x370}, +/* 73 */ {0x370}, +/* 74 */ {0x370}, +/* 75 */ {0x370}, +/* 76 */ {0x370}, +/* 77 */ {0x370}, +/* 78 */ {0x370}, +/* 79 */ {0x370}, +/* 80 */ {0x380}, +/* 81 */ {0x380}, +/* 82 */ {0x380}, +/* 83 */ {0x380}, +/* 84 */ {0x380}, +/* 85 */ {0x380}, +/* 86 */ {0x380}, +/* 87 */ {0x380}, +/* 88 */ {0x380}, +/* 89 */ {0x380}, +/* 90 */ {0x390}, +/* 91 */ {0x390}, +/* 92 */ {0x390}, +/* 93 */ {0x390}, +/* 94 */ {0x390}, +/* 95 */ {0x390}, +/* 96 */ {0x390}, +/* 97 */ {0x390}, +/* 98 */ {0x390}, +/* 99 */ {0x390}, +/* 100 */ {0x3A0}, +/* 101 */ {0x3A0}, +/* 102 */ {0x3A0}, +/* 103 */ {0x3A0}, +/* 104 */ {0x3A0}, +/* 105 */ {0x3A0}, +/* 106 */ {0x3A0}, +/* 107 */ {0x3A0}, +/* 108 */ {0x3A0}, +/* 109 */ {0x3A0}, +/* 110 */ {0x3B0}, +/* 111 */ {0x3B0}, +/* 112 */ {0x3B0}, +/* 113 */ {0x3B0}, +/* 114 */ {0x3B0}, +/* 115 */ {0x3B0}, +/* 116 */ {0x3B0}, +/* 117 */ {0x3B0}, +/* 118 */ {0x3B0}, +/* 119 */ {0x3B0}, +/* 120 */ {0x3C0}, +/* 121 */ {0x3C0}, +/* 122 */ {0x3C0}, +/* 123 */ {0x3C0}, +/* 124 */ {0x3C0}, +/* 125 */ {0x3C0}, +/* 126 */ {0x3C0}, +/* 127 */ {0x3C0}, +/* 128 */ {0x3C0}, +/* 129 */ {0x3C0}, +/* 130 */ {0x3D0}, +/* 131 */ {0x3D0}, +/* 132 */ {0x3D0}, +/* 133 */ {0x3D0}, +/* 134 */ {0x3D0}, +/* 135 */ {0x3D0}, +/* 136 */ {0x3D0}, +/* 137 */ {0x3D0}, +/* 138 */ {0x3D0}, +/* 139 */ {0x3D0}, +/* 140 */ {0x3E0}, +/* 141 */ {0x3E0}, +/* 142 */ {0x3E0}, +/* 143 */ {0x3E0}, +/* 144 */ {0x3E0}, +/* 145 */ {0x3E0}, +/* 146 */ {0x3E0}, +/* 147 */ {0x3E0}, +/* 148 */ {0x3E0}, +/* 149 */ {0x3E0}, +/* 150 */ {0x3F0}, +/* 151 */ {0x3F0}, +/* 152 */ {0x3F0}, +/* 153 */ {0x3F0}, +/* 154 */ {0x3F0}, +/* 155 */ {0x3F0}, +/* 156 */ {0x3F0}, +/* 157 */ {0x3F0}, +/* 158 */ {0x3F0}, +/* 159 */ {0x3F0}, +/* 160 */ {0x400}, +/* 161 */ {0x400}, +/* 162 */ {0x400}, +/* 163 */ {0x400}, +/* 164 */ {0x400}, +/* 165 */ {0x400}, +/* 166 */ {0x400}, +/* 167 */ {0x400}, +/* 168 */ {0x400}, +/* 169 */ {0x400}, +/* 170 */ {0x410}, +/* 171 */ {0x410}, +/* 172 */ {0x410}, +/* 173 */ {0x410}, +/* 174 */ {0x410}, +/* 175 */ {0x410}, +/* 176 */ {0x410}, +/* 177 */ {0x410}, +/* 178 */ {0x410}, +/* 179 */ {0x410}, +/* 180 */ {0x420}, +/* 181 */ {0x420}, +/* 182 */ {0x420}, +/* 183 */ {0x420}, +/* 184 */ {0x420}, +/* 185 */ {0x420}, +/* 186 */ {0x420}, +/* 187 */ {0x420}, +/* 188 */ {0x420}, +/* 189 */ {0x420} +}; + +PIN_offset MODE_offset[] = { +/* 0 */ {0}, +/* 1 */ {3}, +/* 2 */ {6}, +/* 3 */ {9}, +/* 4 */ {12}, +/* 5 */ {16}, +/* 6 */ {19}, +/* 7 */ {22}, +/* 8 */ {25}, +/* 9 */ {28}, +/* 10 */ {0}, +/* 11 */ {3}, +/* 12 */ {6}, +/* 13 */ {9}, +/* 14 */ {12}, +/* 15 */ {16}, +/* 16 */ {19}, +/* 17 */ {22}, +/* 18 */ {25}, +/* 19 */ {28}, +/* 20 */ {0}, +/* 21 */ {3}, +/* 22 */ {6}, +/* 23 */ {9}, +/* 24 */ {12}, +/* 25 */ {16}, +/* 26 */ {19}, +/* 27 */ {22}, +/* 28 */ {25}, +/* 29 */ {28}, +/* 30 */ {0}, +/* 31 */ {3}, +/* 32 */ {6}, +/* 33 */ {9}, +/* 34 */ {12}, +/* 35 */ {16}, +/* 36 */ {19}, +/* 37 */ {22}, +/* 38 */ {25}, +/* 39 */ {28}, +/* 40 */ {0}, +/* 41 */ {3}, +/* 42 */ {6}, +/* 43 */ {9}, +/* 44 */ {12}, +/* 45 */ {16}, +/* 46 */ {19}, +/* 47 */ {22}, +/* 48 */ {25}, +/* 49 */ {28}, +/* 50 */ {0}, +/* 51 */ {3}, +/* 52 */ {6}, +/* 53 */ {9}, +/* 54 */ {12}, +/* 55 */ {16}, +/* 56 */ {19}, +/* 57 */ {22}, +/* 58 */ {25}, +/* 59 */ {28}, +/* 60 */ {0}, +/* 61 */ {3}, +/* 62 */ {6}, +/* 63 */ {9}, +/* 64 */ {12}, +/* 65 */ {16}, +/* 66 */ {19}, +/* 67 */ {22}, +/* 68 */ {25}, +/* 69 */ {28}, +/* 70 */ {0}, +/* 71 */ {3}, +/* 72 */ {6}, +/* 73 */ {9}, +/* 74 */ {12}, +/* 75 */ {16}, +/* 76 */ {19}, +/* 77 */ {22}, +/* 78 */ {25}, +/* 79 */ {28}, +/* 80 */ {0}, +/* 81 */ {3}, +/* 82 */ {6}, +/* 83 */ {9}, +/* 84 */ {12}, +/* 85 */ {16}, +/* 86 */ {19}, +/* 87 */ {22}, +/* 88 */ {25}, +/* 89 */ {28}, +/* 90 */ {0}, +/* 91 */ {3}, +/* 92 */ {6}, +/* 93 */ {9}, +/* 94 */ {12}, +/* 95 */ {16}, +/* 96 */ {19}, +/* 97 */ {22}, +/* 98 */ {25}, +/* 99 */ {28}, +/* 100 */ {0}, +/* 101 */ {3}, +/* 102 */ {6}, +/* 103 */ {9}, +/* 104 */ {12}, +/* 105 */ {16}, +/* 106 */ {19}, +/* 107 */ {22}, +/* 108 */ {25}, +/* 109 */ {28}, +/* 110 */ {0}, +/* 111 */ {3}, +/* 112 */ {6}, +/* 113 */ {9}, +/* 114 */ {12}, +/* 115 */ {16}, +/* 116 */ {19}, +/* 117 */ {22}, +/* 118 */ {25}, +/* 119 */ {28}, +/* 120 */ {0}, +/* 121 */ {3}, +/* 122 */ {6}, +/* 123 */ {9}, +/* 124 */ {12}, +/* 125 */ {16}, +/* 126 */ {19}, +/* 127 */ {22}, +/* 128 */ {25}, +/* 129 */ {28}, +/* 130 */ {0}, +/* 131 */ {3}, +/* 132 */ {6}, +/* 133 */ {9}, +/* 134 */ {12}, +/* 135 */ {16}, +/* 136 */ {19}, +/* 137 */ {22}, +/* 138 */ {25}, +/* 139 */ {28}, +/* 140 */ {0}, +/* 141 */ {3}, +/* 142 */ {6}, +/* 143 */ {9}, +/* 144 */ {12}, +/* 145 */ {16}, +/* 146 */ {19}, +/* 147 */ {22}, +/* 148 */ {25}, +/* 149 */ {28}, +/* 150 */ {0}, +/* 151 */ {3}, +/* 152 */ {6}, +/* 153 */ {9}, +/* 154 */ {12}, +/* 155 */ {16}, +/* 156 */ {19}, +/* 157 */ {22}, +/* 158 */ {25}, +/* 159 */ {28}, +/* 160 */ {0}, +/* 161 */ {3}, +/* 162 */ {6}, +/* 163 */ {9}, +/* 164 */ {12}, +/* 165 */ {16}, +/* 166 */ {19}, +/* 167 */ {22}, +/* 168 */ {25}, +/* 169 */ {28}, +/* 170 */ {0}, +/* 171 */ {3}, +/* 172 */ {6}, +/* 173 */ {9}, +/* 174 */ {12}, +/* 175 */ {16}, +/* 176 */ {19}, +/* 177 */ {22}, +/* 178 */ {25}, +/* 179 */ {28}, +/* 180 */ {0}, +/* 181 */ {3}, +/* 182 */ {6}, +/* 183 */ {9}, +/* 184 */ {12}, +/* 185 */ {16}, +/* 186 */ {19}, +/* 187 */ {22}, +/* 188 */ {25}, +/* 189 */ {28} +}; + +#if 0 +PIN_addr DATAOUT_addr[] = { +/* 0 */ {0x100}, +/* 1 */ {0x100}, +/* 2 */ {0x100}, +/* 3 */ {0x100}, +/* 4 */ {0x100}, +/* 5 */ {0x100}, +/* 6 */ {0x100}, +/* 7 */ {0x100}, +/* 8 */ {0x100}, +/* 9 */ {0x100}, +/* 10 */ {0x100}, +/* 11 */ {0x100}, +/* 12 */ {0x100}, +/* 13 */ {0x100}, +/* 14 */ {0x100}, +/* 15 */ {0x100}, +/* 16 */ {0x100}, +/* 17 */ {0x100}, +/* 18 */ {0x100}, +/* 19 */ {0x100}, +/* 20 */ {0x100}, +/* 21 */ {0x100}, +/* 22 */ {0x100}, +/* 23 */ {0x100}, +/* 24 */ {0x100}, +/* 25 */ {0x100}, +/* 26 */ {0x100}, +/* 27 */ {0x100}, +/* 28 */ {0x100}, +/* 29 */ {0x100}, +/* 30 */ {0x100}, +/* 31 */ {0x100}, +/* 32 */ {0x110}, +/* 33 */ {0x110}, +/* 34 */ {0x110}, +/* 35 */ {0x110}, +/* 36 */ {0x110}, +/* 37 */ {0x110}, +/* 38 */ {0x110}, +/* 39 */ {0x110}, +/* 40 */ {0x110}, +/* 41 */ {0x110}, +/* 42 */ {0x110}, +/* 43 */ {0x110}, +/* 44 */ {0x110}, +/* 45 */ {0x110}, +/* 46 */ {0x110}, +/* 47 */ {0x110}, +/* 48 */ {0x110}, +/* 49 */ {0x110}, +/* 50 */ {0x110}, +/* 51 */ {0x110}, +/* 52 */ {0x110}, +/* 53 */ {0x110}, +/* 54 */ {0x110}, +/* 55 */ {0x110}, +/* 56 */ {0x110}, +/* 57 */ {0x110}, +/* 58 */ {0x110}, +/* 59 */ {0x110}, +/* 60 */ {0x110}, +/* 61 */ {0x110}, +/* 62 */ {0x110}, +/* 63 */ {0x110}, +/* 64 */ {0x120}, +/* 65 */ {0x120}, +/* 66 */ {0x120}, +/* 67 */ {0x120}, +/* 68 */ {0x120}, +/* 69 */ {0x120}, +/* 70 */ {0x120}, +/* 71 */ {0x120}, +/* 72 */ {0x120}, +/* 73 */ {0x120}, +/* 74 */ {0x120}, +/* 75 */ {0x120}, +/* 76 */ {0x120}, +/* 77 */ {0x120}, +/* 78 */ {0x120}, +/* 79 */ {0x120}, +/* 80 */ {0x120}, +/* 81 */ {0x120}, +/* 82 */ {0x120}, +/* 83 */ {0x120}, +/* 84 */ {0x120}, +/* 85 */ {0x120}, +/* 86 */ {0x120}, +/* 87 */ {0x120}, +/* 88 */ {0x120}, +/* 89 */ {0x120}, +/* 90 */ {0x120}, +/* 91 */ {0x120}, +/* 92 */ {0x120}, +/* 93 */ {0x120}, +/* 94 */ {0x120}, +/* 95 */ {0x120}, +/* 96 */ {0x130}, +/* 97 */ {0x130}, +/* 98 */ {0x130}, +/* 99 */ {0x130}, +/* 100 */ {0x130}, +/* 101 */ {0x130}, +/* 102 */ {0x130}, +/* 103 */ {0x130}, +/* 104 */ {0x130}, +/* 105 */ {0x130}, +/* 106 */ {0x130}, +/* 107 */ {0x130}, +/* 108 */ {0x130}, +/* 109 */ {0x130}, +/* 110 */ {0x130}, +/* 111 */ {0x130}, +/* 112 */ {0x130}, +/* 113 */ {0x130}, +/* 114 */ {0x130}, +/* 115 */ {0x130}, +/* 116 */ {0x130}, +/* 117 */ {0x130}, +/* 118 */ {0x130}, +/* 119 */ {0x130}, +/* 120 */ {0x130}, +/* 121 */ {0x130}, +/* 122 */ {0x130}, +/* 123 */ {0x130}, +/* 124 */ {0x130}, +/* 125 */ {0x130}, +/* 126 */ {0x130}, +/* 127 */ {0x130}, +/* 128 */ {0x140}, +/* 129 */ {0x140}, +/* 130 */ {0x140}, +/* 131 */ {0x140}, +/* 132 */ {0x140}, +/* 133 */ {0x140}, +/* 134 */ {0x140}, +/* 135 */ {0x140}, +/* 136 */ {0x140}, +/* 137 */ {0x140}, +/* 138 */ {0x140}, +/* 139 */ {0x140}, +/* 140 */ {0x140}, +/* 141 */ {0x140}, +/* 142 */ {0x140}, +/* 143 */ {0x140}, +/* 144 */ {0x140}, +/* 145 */ {0x140}, +/* 146 */ {0x140}, +/* 147 */ {0x140}, +/* 148 */ {0x140}, +/* 149 */ {0x140}, +/* 150 */ {0x140}, +/* 151 */ {0x140}, +/* 152 */ {0x140}, +/* 153 */ {0x140}, +/* 154 */ {0x140}, +/* 155 */ {0x140}, +/* 156 */ {0x140}, +/* 157 */ {0x140}, +/* 158 */ {0x140}, +/* 159 */ {0x140}, +/* 160 */ {0x150}, +/* 161 */ {0x150}, +/* 162 */ {0x150}, +/* 163 */ {0x150}, +/* 164 */ {0x150}, +/* 165 */ {0x150}, +/* 166 */ {0x150}, +/* 167 */ {0x150}, +/* 168 */ {0x150}, +/* 169 */ {0x150}, +/* 170 */ {0x150}, +/* 171 */ {0x150}, +/* 172 */ {0x150}, +/* 173 */ {0x150}, +/* 174 */ {0x150}, +/* 175 */ {0x150}, +/* 176 */ {0x150}, +/* 177 */ {0x150}, +/* 178 */ {0x150}, +/* 179 */ {0x150}, +/* 180 */ {0x150}, +/* 181 */ {0x150}, +/* 182 */ {0x150}, +/* 183 */ {0x150}, +/* 184 */ {0x150}, +/* 185 */ {0x150}, +/* 186 */ {0x150}, +/* 187 */ {0x150}, +/* 188 */ {0x150}, +/* 189 */ {0x150} +}; + + +PIN_offset DATAOUT_offset[] = { +/* 0 */ {0}, +/* 1 */ {1}, +/* 2 */ {2}, +/* 3 */ {3}, +/* 4 */ {4}, +/* 5 */ {5}, +/* 6 */ {6}, +/* 7 */ {7}, +/* 8 */ {8}, +/* 9 */ {9}, +/* 10 */ {10}, +/* 11 */ {11}, +/* 12 */ {12}, +/* 13 */ {13}, +/* 14 */ {14}, +/* 15 */ {15}, +/* 16 */ {16}, +/* 17 */ {17}, +/* 18 */ {18}, +/* 19 */ {19}, +/* 20 */ {20}, +/* 21 */ {21}, +/* 22 */ {22}, +/* 23 */ {23}, +/* 24 */ {24}, +/* 25 */ {25}, +/* 26 */ {26}, +/* 27 */ {27}, +/* 28 */ {28}, +/* 29 */ {29}, +/* 30 */ {30}, +/* 31 */ {31}, +/* 32 */ {0}, +/* 33 */ {1}, +/* 34 */ {2}, +/* 35 */ {3}, +/* 36 */ {4}, +/* 37 */ {5}, +/* 38 */ {6}, +/* 39 */ {7}, +/* 40 */ {8}, +/* 41 */ {9}, +/* 42 */ {10}, +/* 43 */ {11}, +/* 44 */ {12}, +/* 45 */ {13}, +/* 46 */ {14}, +/* 47 */ {15}, +/* 48 */ {16}, +/* 49 */ {17}, +/* 50 */ {18}, +/* 51 */ {19}, +/* 52 */ {20}, +/* 53 */ {21}, +/* 54 */ {22}, +/* 55 */ {23}, +/* 56 */ {24}, +/* 57 */ {25}, +/* 58 */ {26}, +/* 59 */ {27}, +/* 60 */ {28}, +/* 61 */ {29}, +/* 62 */ {30}, +/* 63 */ {31}, +/* 64 */ {0}, +/* 65 */ {1}, +/* 66 */ {2}, +/* 67 */ {3}, +/* 68 */ {4}, +/* 69 */ {5}, +/* 70 */ {6}, +/* 71 */ {7}, +/* 72 */ {8}, +/* 73 */ {9}, +/* 74 */ {10}, +/* 75 */ {11}, +/* 76 */ {12}, +/* 77 */ {13}, +/* 78 */ {14}, +/* 79 */ {15}, +/* 80 */ {16}, +/* 81 */ {17}, +/* 82 */ {18}, +/* 83 */ {19}, +/* 84 */ {20}, +/* 85 */ {21}, +/* 86 */ {22}, +/* 87 */ {23}, +/* 88 */ {24}, +/* 89 */ {25}, +/* 90 */ {26}, +/* 91 */ {27}, +/* 92 */ {28}, +/* 93 */ {29}, +/* 94 */ {30}, +/* 95 */ {31}, +/* 96 */ {0}, +/* 97 */ {1}, +/* 98 */ {2}, +/* 99 */ {3}, +/* 100 */ {4}, +/* 101 */ {5}, +/* 102 */ {6}, +/* 103 */ {7}, +/* 104 */ {8}, +/* 105 */ {9}, +/* 106 */ {10}, +/* 107 */ {11}, +/* 108 */ {12}, +/* 109 */ {13}, +/* 110 */ {14}, +/* 111 */ {15}, +/* 112 */ {16}, +/* 113 */ {17}, +/* 114 */ {18}, +/* 115 */ {19}, +/* 116 */ {20}, +/* 117 */ {21}, +/* 118 */ {22}, +/* 119 */ {23}, +/* 120 */ {24}, +/* 121 */ {25}, +/* 122 */ {26}, +/* 123 */ {27}, +/* 124 */ {28}, +/* 125 */ {29}, +/* 126 */ {30}, +/* 127 */ {31}, +/* 128 */ {0}, +/* 129 */ {1}, +/* 130 */ {2}, +/* 131 */ {3}, +/* 132 */ {4}, +/* 133 */ {5}, +/* 134 */ {6}, +/* 135 */ {7}, +/* 136 */ {8}, +/* 137 */ {9}, +/* 138 */ {10}, +/* 139 */ {11}, +/* 140 */ {12}, +/* 141 */ {13}, +/* 142 */ {14}, +/* 143 */ {15}, +/* 144 */ {16}, +/* 145 */ {17}, +/* 146 */ {18}, +/* 147 */ {19}, +/* 148 */ {20}, +/* 149 */ {21}, +/* 150 */ {22}, +/* 151 */ {23}, +/* 152 */ {24}, +/* 153 */ {25}, +/* 154 */ {26}, +/* 155 */ {27}, +/* 156 */ {28}, +/* 157 */ {29}, +/* 158 */ {30}, +/* 159 */ {31}, +/* 160 */ {0}, +/* 161 */ {1}, +/* 162 */ {2}, + /* 163 */ {3}, +/* 164 */ {4}, +/* 165 */ {5}, +/* 166 */ {6}, +/* 167 */ {7}, +/* 168 */ {8}, + /* 169 */ {9}, +/* 170 */ {10}, +/* 171 */ {11}, +/* 172 */ {12}, +/* 173 */ {13}, +/* 174 */ {14}, +/* 175 */ {15}, +/* 176 */ {16}, +/* 177 */ {17}, +/* 178 */ {18}, +/* 179 */ {19}, +/* 180 */ {20}, +/* 181 */ {21}, +/* 182 */ {22}, +/* 183 */ {23}, +/* 184 */ {24}, +/* 185 */ {25}, +/* 186 */ {26}, +/* 187 */ {27}, +/* 188 */ {28}, +/* 189 */ {29} +}; + + +PIN_addr DIN_addr[] = { +/* 0 */ {0x200}, +/* 1 */ {0x200}, +/* 2 */ {0x200}, +/* 3 */ {0x200}, +/* 4 */ {0x200}, +/* 5 */ {0x200}, +/* 6 */ {0x200}, +/* 7 */ {0x200}, +/* 8 */ {0x200}, +/* 9 */ {0x200}, +/* 10 */ {0x200}, +/* 11 */ {0x200}, +/* 12 */ {0x200}, +/* 13 */ {0x200}, +/* 14 */ {0x200}, +/* 15 */ {0x200}, +/* 16 */ {0x200}, +/* 17 */ {0x200}, +/* 18 */ {0x200}, +/* 19 */ {0x200}, +/* 20 */ {0x200}, +/* 21 */ {0x200}, +/* 22 */ {0x200}, +/* 23 */ {0x200}, +/* 24 */ {0x200}, +/* 25 */ {0x200}, +/* 26 */ {0x200}, +/* 27 */ {0x200}, +/* 28 */ {0x200}, +/* 29 */ {0x200}, +/* 30 */ {0x200}, +/* 31 */ {0x200}, +/* 32 */ {0x210}, +/* 33 */ {0x210}, +/* 34 */ {0x210}, +/* 35 */ {0x210}, +/* 36 */ {0x210}, +/* 37 */ {0x210}, +/* 38 */ {0x210}, +/* 39 */ {0x210}, +/* 40 */ {0x210}, +/* 41 */ {0x210}, +/* 42 */ {0x210}, +/* 43 */ {0x210}, +/* 44 */ {0x210}, +/* 45 */ {0x210}, +/* 46 */ {0x210}, +/* 47 */ {0x210}, +/* 48 */ {0x210}, +/* 49 */ {0x210}, +/* 50 */ {0x210}, +/* 51 */ {0x210}, +/* 52 */ {0x210}, +/* 53 */ {0x210}, +/* 54 */ {0x210}, +/* 55 */ {0x210}, +/* 56 */ {0x210}, +/* 57 */ {0x210}, +/* 58 */ {0x210}, +/* 59 */ {0x210}, +/* 60 */ {0x210}, +/* 61 */ {0x210}, +/* 62 */ {0x210}, +/* 63 */ {0x210}, +/* 64 */ {0x220}, +/* 65 */ {0x220}, +/* 66 */ {0x220}, +/* 67 */ {0x220}, +/* 68 */ {0x220}, +/* 69 */ {0x220}, +/* 70 */ {0x220}, +/* 71 */ {0x220}, +/* 72 */ {0x220}, +/* 73 */ {0x220}, +/* 74 */ {0x220}, +/* 75 */ {0x220}, +/* 76 */ {0x220}, +/* 77 */ {0x220}, +/* 78 */ {0x220}, +/* 79 */ {0x220}, +/* 80 */ {0x220}, +/* 81 */ {0x220}, +/* 82 */ {0x220}, +/* 83 */ {0x220}, +/* 84 */ {0x220}, +/* 85 */ {0x220}, +/* 86 */ {0x220}, +/* 87 */ {0x220}, +/* 88 */ {0x220}, +/* 89 */ {0x220}, +/* 90 */ {0x220}, +/* 91 */ {0x220}, +/* 92 */ {0x220}, +/* 93 */ {0x220}, +/* 94 */ {0x220}, +/* 95 */ {0x220}, +/* 96 */ {0x230}, +/* 97 */ {0x230}, +/* 98 */ {0x230}, +/* 99 */ {0x230}, +/* 100 */ {0x230}, +/* 101 */ {0x230}, +/* 102 */ {0x230}, +/* 103 */ {0x230}, +/* 104 */ {0x230}, +/* 105 */ {0x230}, +/* 106 */ {0x230}, +/* 107 */ {0x230}, +/* 108 */ {0x230}, +/* 109 */ {0x230}, +/* 110 */ {0x230}, +/* 111 */ {0x230}, +/* 112 */ {0x230}, +/* 113 */ {0x230}, +/* 114 */ {0x230}, +/* 115 */ {0x230}, +/* 116 */ {0x230}, +/* 117 */ {0x230}, +/* 118 */ {0x230}, +/* 119 */ {0x230}, +/* 120 */ {0x230}, +/* 121 */ {0x230}, +/* 122 */ {0x230}, +/* 123 */ {0x230}, +/* 124 */ {0x230}, +/* 125 */ {0x230}, +/* 126 */ {0x230}, +/* 127 */ {0x230}, +/* 128 */ {0x240}, +/* 129 */ {0x240}, +/* 130 */ {0x240}, +/* 131 */ {0x240}, +/* 132 */ {0x240}, +/* 133 */ {0x240}, +/* 134 */ {0x240}, +/* 135 */ {0x240}, +/* 136 */ {0x240}, +/* 137 */ {0x240}, +/* 138 */ {0x240}, +/* 139 */ {0x240}, +/* 140 */ {0x240}, +/* 141 */ {0x240}, +/* 142 */ {0x240}, +/* 143 */ {0x240}, +/* 144 */ {0x240}, +/* 145 */ {0x240}, +/* 146 */ {0x240}, +/* 147 */ {0x240}, +/* 148 */ {0x240}, +/* 149 */ {0x240}, +/* 150 */ {0x240}, +/* 151 */ {0x240}, +/* 152 */ {0x240}, +/* 153 */ {0x240}, +/* 154 */ {0x240}, +/* 155 */ {0x240}, +/* 156 */ {0x240}, +/* 157 */ {0x240}, +/* 158 */ {0x240}, +/* 159 */ {0x240}, +/* 160 */ {0x250}, +/* 161 */ {0x250}, +/* 162 */ {0x250}, +/* 163 */ {0x250}, +/* 164 */ {0x250}, +/* 165 */ {0x250}, +/* 166 */ {0x250}, +/* 167 */ {0x250}, +/* 168 */ {0x250}, +/* 169 */ {0x250}, +/* 170 */ {0x250}, +/* 171 */ {0x250}, +/* 172 */ {0x250}, +/* 173 */ {0x250}, +/* 174 */ {0x250}, +/* 175 */ {0x250}, +/* 176 */ {0x250}, +/* 177 */ {0x250}, +/* 178 */ {0x250}, +/* 179 */ {0x250}, +/* 180 */ {0x250}, +/* 181 */ {0x250}, +/* 182 */ {0x250}, +/* 183 */ {0x250}, +/* 184 */ {0x250}, +/* 185 */ {0x250}, +/* 186 */ {0x250}, +/* 187 */ {0x250}, +/* 188 */ {0x250}, +/* 189 */ {0x250} +}; + + +PIN_offset DIN_offset[] = { +/* 0 */ {0}, +/* 1 */ {1}, +/* 2 */ {2}, +/* 3 */ {3}, +/* 4 */ {4}, +/* 5 */ {5}, +/* 6 */ {6}, +/* 7 */ {7}, +/* 8 */ {8}, +/* 9 */ {9}, +/* 10 */ {10}, +/* 11 */ {11}, +/* 12 */ {12}, +/* 13 */ {13}, +/* 14 */ {14}, +/* 15 */ {15}, +/* 16 */ {16}, +/* 17 */ {17}, +/* 18 */ {18}, +/* 19 */ {19}, +/* 20 */ {20}, +/* 21 */ {21}, +/* 22 */ {22}, +/* 23 */ {23}, +/* 24 */ {24}, +/* 25 */ {25}, +/* 26 */ {26}, +/* 27 */ {27}, +/* 28 */ {28}, +/* 29 */ {29}, +/* 30 */ {30}, +/* 31 */ {31}, +/* 32 */ {0}, +/* 33 */ {1}, +/* 34 */ {2}, +/* 35 */ {3}, +/* 36 */ {4}, +/* 37 */ {5}, +/* 38 */ {6}, +/* 39 */ {7}, +/* 40 */ {8}, +/* 41 */ {9}, +/* 42 */ {10}, +/* 43 */ {11}, +/* 44 */ {12}, +/* 45 */ {13}, +/* 46 */ {14}, +/* 47 */ {15}, +/* 48 */ {16}, +/* 49 */ {17}, +/* 50 */ {18}, +/* 51 */ {19}, +/* 52 */ {20}, +/* 53 */ {21}, +/* 54 */ {22}, +/* 55 */ {23}, +/* 56 */ {24}, +/* 57 */ {25}, +/* 58 */ {26}, +/* 59 */ {27}, +/* 60 */ {28}, +/* 61 */ {29}, +/* 62 */ {30}, +/* 63 */ {31}, +/* 64 */ {0}, +/* 65 */ {1}, +/* 66 */ {2}, +/* 67 */ {3}, +/* 68 */ {4}, +/* 69 */ {5}, +/* 70 */ {6}, +/* 71 */ {7}, +/* 72 */ {8}, +/* 73 */ {9}, +/* 74 */ {10}, +/* 75 */ {11}, +/* 76 */ {12}, +/* 77 */ {13}, +/* 78 */ {14}, +/* 79 */ {15}, +/* 80 */ {16}, +/* 81 */ {17}, +/* 82 */ {18}, +/* 83 */ {19}, +/* 84 */ {20}, +/* 85 */ {21}, +/* 86 */ {22}, +/* 87 */ {23}, +/* 88 */ {24}, +/* 89 */ {25}, +/* 90 */ {26}, +/* 91 */ {27}, +/* 92 */ {28}, +/* 93 */ {29}, +/* 94 */ {30}, +/* 95 */ {31}, +/* 96 */ {0}, +/* 97 */ {1}, +/* 98 */ {2}, +/* 99 */ {3}, +/* 100 */ {4}, +/* 101 */ {5}, +/* 102 */ {6}, +/* 103 */ {7}, +/* 104 */ {8}, +/* 105 */ {9}, +/* 106 */ {10}, +/* 107 */ {11}, +/* 108 */ {12}, +/* 109 */ {13}, +/* 110 */ {14}, +/* 111 */ {15}, +/* 112 */ {16}, +/* 113 */ {17}, +/* 114 */ {18}, +/* 115 */ {19}, +/* 116 */ {20}, +/* 117 */ {21}, +/* 118 */ {22}, +/* 119 */ {23}, +/* 120 */ {24}, +/* 121 */ {25}, +/* 122 */ {26}, +/* 123 */ {27}, +/* 124 */ {28}, +/* 125 */ {29}, +/* 126 */ {30}, +/* 127 */ {31}, +/* 128 */ {0}, +/* 129 */ {1}, +/* 130 */ {2}, +/* 131 */ {3}, +/* 132 */ {4}, +/* 133 */ {5}, +/* 134 */ {6}, +/* 135 */ {7}, +/* 136 */ {8}, +/* 137 */ {9}, +/* 138 */ {10}, +/* 139 */ {11}, +/* 140 */ {12}, +/* 141 */ {13}, +/* 142 */ {14}, +/* 143 */ {15}, +/* 144 */ {16}, +/* 145 */ {17}, +/* 146 */ {18}, +/* 147 */ {19}, +/* 148 */ {20}, +/* 149 */ {21}, +/* 150 */ {22}, +/* 151 */ {23}, +/* 152 */ {24}, +/* 153 */ {25}, +/* 154 */ {26}, +/* 155 */ {27}, +/* 156 */ {28}, +/* 157 */ {29}, +/* 158 */ {30}, +/* 159 */ {31}, +/* 160 */ {0}, +/* 161 */ {1}, +/* 162 */ {2}, +/* 163 */ {3}, +/* 164 */ {4}, +/* 165 */ {5}, +/* 166 */ {6}, +/* 167 */ {7}, +/* 168 */ {8}, +/* 169 */ {9}, +/* 170 */ {10}, +/* 171 */ {11}, +/* 172 */ {12}, +/* 173 */ {13}, +/* 174 */ {14}, +/* 175 */ {15}, +/* 176 */ {16}, +/* 177 */ {17}, +/* 178 */ {18}, +/* 179 */ {19}, +/* 180 */ {20}, +/* 181 */ {21}, +/* 182 */ {22}, +/* 183 */ {23}, +/* 184 */ {24}, +/* 185 */ {25}, +/* 186 */ {26}, +/* 187 */ {27}, +/* 188 */ {28}, +/* 189 */ {29} +}; + + +PIN_addr DIR_addr[] = { +/* 0 */ {0x000}, +/* 1 */ {0x000}, +/* 2 */ {0x000}, +/* 3 */ {0x000}, +/* 4 */ {0x000}, +/* 5 */ {0x000}, +/* 6 */ {0x000}, +/* 7 */ {0x000}, +/* 8 */ {0x000}, +/* 9 */ {0x000}, +/* 10 */ {0x000}, +/* 11 */ {0x000}, +/* 12 */ {0x000}, +/* 13 */ {0x000}, +/* 14 */ {0x000}, +/* 15 */ {0x000}, +/* 16 */ {0x000}, +/* 17 */ {0x000}, +/* 18 */ {0x000}, +/* 19 */ {0x000}, +/* 20 */ {0x000}, +/* 21 */ {0x000}, +/* 22 */ {0x000}, +/* 23 */ {0x000}, +/* 24 */ {0x000}, +/* 25 */ {0x000}, +/* 26 */ {0x000}, +/* 27 */ {0x000}, +/* 28 */ {0x000}, +/* 29 */ {0x000}, +/* 30 */ {0x000}, +/* 31 */ {0x000}, +/* 32 */ {0x010}, +/* 33 */ {0x010}, +/* 34 */ {0x010}, +/* 35 */ {0x010}, +/* 36 */ {0x010}, +/* 37 */ {0x010}, +/* 38 */ {0x010}, +/* 39 */ {0x010}, +/* 40 */ {0x010}, +/* 41 */ {0x010}, +/* 42 */ {0x010}, +/* 43 */ {0x010}, +/* 44 */ {0x010}, +/* 45 */ {0x010}, +/* 46 */ {0x010}, +/* 47 */ {0x010}, +/* 48 */ {0x010}, +/* 49 */ {0x010}, +/* 50 */ {0x010}, +/* 51 */ {0x010}, +/* 52 */ {0x010}, +/* 53 */ {0x010}, +/* 54 */ {0x010}, +/* 55 */ {0x010}, +/* 56 */ {0x010}, +/* 57 */ {0x010}, +/* 58 */ {0x010}, +/* 59 */ {0x010}, +/* 60 */ {0x010}, +/* 61 */ {0x010}, +/* 62 */ {0x010}, +/* 63 */ {0x010}, +/* 64 */ {0x020}, +/* 65 */ {0x020}, +/* 66 */ {0x020}, +/* 67 */ {0x020}, +/* 68 */ {0x020}, +/* 69 */ {0x020}, +/* 70 */ {0x020}, +/* 71 */ {0x020}, +/* 72 */ {0x020}, +/* 73 */ {0x020}, +/* 74 */ {0x020}, +/* 75 */ {0x020}, +/* 76 */ {0x020}, +/* 77 */ {0x020}, +/* 78 */ {0x020}, +/* 79 */ {0x020}, +/* 80 */ {0x020}, +/* 81 */ {0x020}, +/* 82 */ {0x020}, +/* 83 */ {0x020}, +/* 84 */ {0x020}, +/* 85 */ {0x020}, +/* 86 */ {0x020}, +/* 87 */ {0x020}, +/* 88 */ {0x020}, +/* 89 */ {0x020}, +/* 90 */ {0x020}, +/* 91 */ {0x020}, +/* 92 */ {0x020}, +/* 93 */ {0x020}, +/* 94 */ {0x020}, +/* 95 */ {0x020}, +/* 96 */ {0x030}, +/* 97 */ {0x030}, +/* 98 */ {0x030}, +/* 99 */ {0x030}, +/* 100 */ {0x030}, +/* 101 */ {0x030}, +/* 102 */ {0x030}, +/* 103 */ {0x030}, +/* 104 */ {0x030}, +/* 105 */ {0x030}, +/* 106 */ {0x030}, +/* 107 */ {0x030}, +/* 108 */ {0x030}, +/* 109 */ {0x030}, +/* 110 */ {0x030}, +/* 111 */ {0x030}, +/* 112 */ {0x030}, +/* 113 */ {0x030}, +/* 114 */ {0x030}, +/* 115 */ {0x030}, +/* 116 */ {0x030}, +/* 117 */ {0x030}, +/* 118 */ {0x030}, +/* 119 */ {0x030}, +/* 120 */ {0x030}, +/* 121 */ {0x030}, +/* 122 */ {0x030}, +/* 123 */ {0x030}, +/* 124 */ {0x030}, +/* 125 */ {0x030}, +/* 126 */ {0x030}, +/* 127 */ {0x030}, +/* 128 */ {0x040}, +/* 129 */ {0x040}, +/* 130 */ {0x040}, +/* 131 */ {0x040}, +/* 132 */ {0x040}, +/* 133 */ {0x040}, +/* 134 */ {0x040}, +/* 135 */ {0x040}, +/* 136 */ {0x040}, +/* 137 */ {0x040}, +/* 138 */ {0x040}, +/* 139 */ {0x040}, +/* 140 */ {0x040}, +/* 141 */ {0x040}, +/* 142 */ {0x040}, +/* 143 */ {0x040}, +/* 144 */ {0x040}, +/* 145 */ {0x040}, +/* 146 */ {0x040}, +/* 147 */ {0x040}, +/* 148 */ {0x040}, +/* 149 */ {0x040}, +/* 150 */ {0x040}, +/* 151 */ {0x040}, +/* 152 */ {0x040}, +/* 153 */ {0x040}, +/* 154 */ {0x040}, +/* 155 */ {0x040}, +/* 156 */ {0x040}, +/* 157 */ {0x040}, +/* 158 */ {0x040}, +/* 159 */ {0x040}, +/* 160 */ {0x050}, +/* 161 */ {0x050}, +/* 162 */ {0x050}, +/* 163 */ {0x050}, +/* 164 */ {0x050}, +/* 165 */ {0x050}, +/* 166 */ {0x050}, +/* 167 */ {0x050}, +/* 168 */ {0x050}, +/* 169 */ {0x050}, +/* 170 */ {0x050}, +/* 171 */ {0x050}, +/* 172 */ {0x050}, +/* 173 */ {0x050}, +/* 174 */ {0x050}, +/* 175 */ {0x050}, +/* 176 */ {0x050}, +/* 177 */ {0x050}, +/* 178 */ {0x050}, +/* 179 */ {0x050}, +/* 180 */ {0x050}, +/* 181 */ {0x050}, +/* 182 */ {0x050}, +/* 183 */ {0x050}, +/* 184 */ {0x050}, +/* 185 */ {0x050}, +/* 186 */ {0x050}, +/* 187 */ {0x050}, +/* 188 */ {0x050}, +/* 189 */ {0x050} +}; + + +PIN_offset DIR_offset[] = { +/* 0 */ {0}, +/* 1 */ {1}, +/* 2 */ {2}, +/* 3 */ {3}, +/* 4 */ {4}, +/* 5 */ {5}, +/* 6 */ {6}, +/* 7 */ {7}, +/* 8 */ {8}, +/* 9 */ {9}, +/* 10 */ {10}, +/* 11 */ {11}, +/* 12 */ {12}, +/* 13 */ {13}, +/* 14 */ {14}, +/* 15 */ {15}, +/* 16 */ {16}, +/* 17 */ {17}, +/* 18 */ {18}, +/* 19 */ {19}, +/* 20 */ {20}, +/* 21 */ {21}, +/* 22 */ {22}, +/* 23 */ {23}, +/* 24 */ {24}, +/* 25 */ {25}, +/* 26 */ {26}, +/* 27 */ {27}, +/* 28 */ {28}, +/* 29 */ {29}, +/* 30 */ {30}, +/* 31 */ {31}, +/* 32 */ {0}, +/* 33 */ {1}, +/* 34 */ {2}, +/* 35 */ {3}, +/* 36 */ {4}, +/* 37 */ {5}, +/* 38 */ {6}, +/* 39 */ {7}, +/* 40 */ {8}, +/* 41 */ {9}, +/* 42 */ {10}, +/* 43 */ {11}, +/* 44 */ {12}, +/* 45 */ {13}, +/* 46 */ {14}, +/* 47 */ {15}, +/* 48 */ {16}, +/* 49 */ {17}, +/* 50 */ {18}, +/* 51 */ {19}, +/* 52 */ {20}, +/* 53 */ {21}, +/* 54 */ {22}, +/* 55 */ {23}, +/* 56 */ {24}, +/* 57 */ {25}, +/* 58 */ {26}, +/* 59 */ {27}, +/* 60 */ {28}, +/* 61 */ {29}, +/* 62 */ {30}, +/* 63 */ {31}, +/* 64 */ {0}, +/* 65 */ {1}, +/* 66 */ {2}, +/* 67 */ {3}, +/* 68 */ {4}, +/* 69 */ {5}, +/* 70 */ {6}, +/* 71 */ {7}, +/* 72 */ {8}, +/* 73 */ {9}, +/* 74 */ {10}, +/* 75 */ {11}, +/* 76 */ {12}, +/* 77 */ {13}, +/* 78 */ {14}, +/* 79 */ {15}, +/* 80 */ {16}, +/* 81 */ {17}, +/* 82 */ {18}, +/* 83 */ {19}, +/* 84 */ {20}, +/* 85 */ {21}, +/* 86 */ {22}, +/* 87 */ {23}, +/* 88 */ {24}, +/* 89 */ {25}, +/* 90 */ {26}, +/* 91 */ {27}, +/* 92 */ {28}, +/* 93 */ {29}, +/* 94 */ {30}, +/* 95 */ {31}, +/* 96 */ {0}, +/* 97 */ {1}, +/* 98 */ {2}, +/* 99 */ {3}, +/* 100 */ {4}, +/* 101 */ {5}, +/* 102 */ {6}, +/* 103 */ {7}, +/* 104 */ {8}, +/* 105 */ {9}, +/* 106 */ {10}, +/* 107 */ {11}, +/* 108 */ {12}, +/* 109 */ {13}, +/* 110 */ {14}, +/* 111 */ {15}, +/* 112 */ {16}, +/* 113 */ {17}, +/* 114 */ {18}, +/* 115 */ {19}, +/* 116 */ {20}, +/* 117 */ {21}, +/* 118 */ {22}, +/* 119 */ {23}, +/* 120 */ {24}, +/* 121 */ {25}, +/* 122 */ {26}, +/* 123 */ {27}, +/* 124 */ {28}, +/* 125 */ {29}, +/* 126 */ {30}, +/* 127 */ {31}, +/* 128 */ {0}, +/* 129 */ {1}, +/* 130 */ {2}, +/* 131 */ {3}, +/* 132 */ {4}, +/* 133 */ {5}, +/* 134 */ {6}, +/* 135 */ {7}, +/* 136 */ {8}, +/* 137 */ {9}, +/* 138 */ {10}, +/* 139 */ {11}, +/* 140 */ {12}, +/* 141 */ {13}, +/* 142 */ {14}, +/* 143 */ {15}, +/* 144 */ {16}, +/* 145 */ {17}, +/* 146 */ {18}, +/* 147 */ {19}, +/* 148 */ {20}, +/* 149 */ {21}, +/* 150 */ {22}, +/* 151 */ {23}, +/* 152 */ {24}, +/* 153 */ {25}, +/* 154 */ {26}, +/* 155 */ {27}, +/* 156 */ {28}, +/* 157 */ {29}, +/* 158 */ {30}, +/* 159 */ {31}, +/* 160 */ {0}, +/* 161 */ {1}, +/* 162 */ {2}, +/* 163 */ {3}, +/* 164 */ {4}, +/* 165 */ {5}, +/* 166 */ {6}, +/* 167 */ {7}, +/* 168 */ {8}, +/* 169 */ {9}, +/* 170 */ {10}, +/* 171 */ {11}, +/* 172 */ {12}, +/* 173 */ {13}, +/* 174 */ {14}, +/* 175 */ {15}, +/* 176 */ {16}, +/* 177 */ {17}, +/* 178 */ {18}, +/* 179 */ {19}, +/* 180 */ {20}, +/* 181 */ {21}, +/* 182 */ {22}, +/* 183 */ {23}, +/* 184 */ {24}, +/* 185 */ {25}, +/* 186 */ {26}, +/* 187 */ {27}, +/* 188 */ {28}, +/* 189 */ {29} +}; + + +PIN_addr DRV_addr[] = { +/* 0 */ {IOCFG_3_BASE + 0x0A0}, +/* 1 */ {IOCFG_3_BASE + 0x0A0}, +/* 2 */ {IOCFG_3_BASE + 0x0A0}, +/* 3 */ {IOCFG_3_BASE + 0x0A0}, +/* 4 */ {IOCFG_3_BASE + 0x0A0}, +/* 5 */ {IOCFG_3_BASE + 0x0A0}, +/* 6 */ {IOCFG_3_BASE + 0x0A0}, +/* 7 */ {IOCFG_3_BASE + 0x0A0}, +/* 8 */ {IOCFG_3_BASE + 0x0B0}, +/* 9 */ {IOCFG_3_BASE + 0x0B0}, +/* 10 */ {IOCFG_3_BASE + 0x0B0}, +/* 11 */ {IOCFG_0_BASE + 0x0A0}, +/* 12 */ {IOCFG_0_BASE + 0x0A0}, +/* 13 */ {IOCFG_1_BASE + 0x0A0}, +/* 14 */ {IOCFG_1_BASE + 0x0A0}, +/* 15 */ {IOCFG_1_BASE + 0x0A0}, +/* 16 */ {IOCFG_1_BASE + 0x0A0}, +/* 17 */ {IOCFG_1_BASE + 0x0A0}, +/* 18 */ {IOCFG_1_BASE + 0x0A0}, +/* 19 */ {IOCFG_1_BASE + 0x0A0}, +/* 20 */ {IOCFG_1_BASE + 0x0A0}, +/* 21 */ {IOCFG_1_BASE + 0x0A0}, +/* 22 */ {IOCFG_1_BASE + 0x0A0}, +/* 23 */ {IOCFG_1_BASE + 0x0A0}, +/* 24 */ {IOCFG_1_BASE + 0x0A0}, +/* 25 */ {IOCFG_1_BASE + 0x0B0}, +/* 26 */ {IOCFG_1_BASE + 0x0B0}, +/* 27 */ {IOCFG_1_BASE + 0x0B0}, +/* 28 */ {IOCFG_1_BASE + 0x0B0}, +/* 29 */ {IOCFG_0_BASE + 0x0A0}, +/* 30 */ {IOCFG_0_BASE + 0x0B0}, +/* 31 */ {IOCFG_0_BASE + 0x0B0}, +/* 32 */ {IOCFG_0_BASE + 0x0B0}, +/* 33 */ {IOCFG_0_BASE + 0x0B0}, +/* 34 */ {IOCFG_0_BASE + 0x0B0}, +/* 35 */ {IOCFG_0_BASE + 0x0B0}, +/* 36 */ {IOCFG_0_BASE + 0x0B0}, +/* 37 */ {IOCFG_0_BASE + 0x0B0}, +/* 38 */ {IOCFG_0_BASE + 0x0B0}, +/* 39 */ {IOCFG_0_BASE + 0x0B0}, +/* 40 */ {IOCFG_0_BASE + 0x0B0}, +/* 41 */ {IOCFG_0_BASE + 0x0B0}, +/* 42 */ {IOCFG_1_BASE + 0x0A0}, +/* 43 */ {IOCFG_1_BASE + 0x0A0}, +/* 44 */ {IOCFG_1_BASE + 0x0A0}, +/* 45 */ {IOCFG_1_BASE + 0x0A0}, +/* 46 */ {IOCFG_1_BASE + 0x0A0}, +/* 47 */ {IOCFG_1_BASE + 0x0A0}, +/* 48 */ {IOCFG_1_BASE + 0x0A0}, +/* 49 */ {IOCFG_1_BASE + 0x0A0}, +/* 50 */ {IOCFG_1_BASE + 0x0A0}, +/* 51 */ {IOCFG_1_BASE + 0x0B0}, +/* 52 */ {IOCFG_1_BASE + 0x0B0}, +/* 53 */ {IOCFG_1_BASE + 0x0B0}, +/* 54 */ {IOCFG_1_BASE + 0x0B0}, +/* 55 */ {IOCFG_1_BASE + 0x0B0}, +/* 56 */ {IOCFG_1_BASE + 0x0B0}, +/* 57 */ {IOCFG_1_BASE + 0x0B0}, +/* 58 */ {IOCFG_1_BASE + 0x0B0}, +/* 59 */ {IOCFG_1_BASE + 0x0B0}, +/* 60 */ {IOCFG_1_BASE + 0x0B0}, +/* 61 */ {IOCFG_1_BASE + 0x0B0}, +/* 62 */ {IOCFG_1_BASE + 0x0B0}, +/* 63 */ {IOCFG_1_BASE + 0x0B0}, +/* 64 */ {IOCFG_1_BASE + 0x0B0}, +/* 65 */ {IOCFG_1_BASE + 0x0B0}, +/* 66 */ {IOCFG_1_BASE + 0x0B0}, +/* 67 */ {IOCFG_1_BASE + 0x0B0}, +/* 68 */ {IOCFG_1_BASE + 0x0B0}, +/* 69 */ {IOCFG_1_BASE + 0x0B0}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {IOCFG_2_BASE + 0x0A0}, +/* 76 */ {IOCFG_2_BASE + 0x0A0}, +/* 77 */ {IOCFG_2_BASE + 0x0A0}, +/* 78 */ {IOCFG_2_BASE + 0x0A0}, +/* 79 */ {IOCFG_2_BASE + 0x0A0}, +/* 80 */ {IOCFG_2_BASE + 0x0A0}, +/* 81 */ {IOCFG_2_BASE + 0x0A0}, +/* 82 */ {IOCFG_2_BASE + 0x0A0}, +/* 83 */ {IOCFG_2_BASE + 0x0A0}, +/* 84 */ {IOCFG_2_BASE + 0x0A0}, +/* 85 */ {IOCFG_2_BASE + 0x0A0}, +/* 86 */ {IOCFG_2_BASE + 0x0A0}, +/* 87 */ {IOCFG_2_BASE + 0x0A0}, +/* 88 */ {IOCFG_2_BASE + 0x0A0}, +/* 89 */ {IOCFG_2_BASE + 0x0A0}, +/* 90 */ {IOCFG_2_BASE + 0x0A0}, +/* 91 */ {IOCFG_3_BASE + 0x0A0}, +/* 92 */ {IOCFG_3_BASE + 0x0A0}, +/* 93 */ {IOCFG_3_BASE + 0x0A0}, +/* 94 */ {IOCFG_3_BASE + 0x0A0}, +/* 95 */ {IOCFG_3_BASE + 0x0A0}, +/* 96 */ {IOCFG_3_BASE + 0x0A0}, +/* 97 */ {IOCFG_3_BASE + 0x0A0}, +/* 98 */ {IOCFG_3_BASE + 0x0A0}, +/* 99 */ {IOCFG_3_BASE + 0x0A0}, +/* 100 */ {IOCFG_3_BASE + 0x0A0}, +/* 101 */ {IOCFG_3_BASE + 0x0A0}, +/* 102 */ {IOCFG_3_BASE + 0x0A0}, +/* 103 */ {IOCFG_3_BASE + 0x0A0}, +/* 104 */ {IOCFG_3_BASE + 0x0A0}, +/* 105 */ {IOCFG_3_BASE + 0x0A0}, +/* 106 */ {IOCFG_3_BASE + 0x0A0}, +/* 107 */ {IOCFG_3_BASE + 0x0B0}, +/* 108 */ {IOCFG_3_BASE + 0x0B0}, +/* 109 */ {IOCFG_3_BASE + 0x0B0}, +/* 110 */ {IOCFG_3_BASE + 0x0B0}, +/* 111 */ {IOCFG_3_BASE + 0x0B0}, +/* 112 */ {IOCFG_3_BASE + 0x0B0}, +/* 113 */ {IOCFG_3_BASE + 0x0B0}, +/* 114 */ {IOCFG_4_BASE + 0x0A0}, +/* 115 */ {IOCFG_4_BASE + 0x0A0}, +/* 116 */ {IOCFG_4_BASE + 0x0A0}, +/* 117 */ {IOCFG_4_BASE + 0x0A0}, +/* 118 */ {IOCFG_4_BASE + 0x0A0}, +/* 119 */ {IOCFG_4_BASE + 0x0A0}, +/* 120 */ {IOCFG_4_BASE + 0x0A0}, +/* 121 */ {IOCFG_4_BASE + 0x0A0}, +/* 122 */ {IOCFG_4_BASE + 0x0A0}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {IOCFG_4_BASE + 0x0A0}, +/* 132 */ {IOCFG_4_BASE + 0x0A0}, +/* 133 */ {IOCFG_4_BASE + 0x0A0}, +/* 134 */ {IOCFG_4_BASE + 0x0A0}, +/* 135 */ {IOCFG_4_BASE + 0x0A0}, +/* 136 */ {IOCFG_4_BASE + 0x0A0}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {IOCFG_0_BASE + 0x0A0}, +/* 148 */ {IOCFG_0_BASE + 0x0A0}, +/* 149 */ {IOCFG_0_BASE + 0x0A0}, +/* 150 */ {IOCFG_0_BASE + 0x0A0}, +/* 151 */ {IOCFG_0_BASE + 0x0A0}, +/* 152 */ {IOCFG_0_BASE + 0x0A0}, +/* 153 */ {IOCFG_0_BASE + 0x0A0}, +/* 154 */ {IOCFG_0_BASE + 0x0A0}, +/* 155 */ {IOCFG_0_BASE + 0x0A0}, +/* 156 */ {IOCFG_0_BASE + 0x0A0}, +/* 157 */ {IOCFG_1_BASE + 0x0A0}, +/* 158 */ {IOCFG_1_BASE + 0x0A0}, +/* 159 */ {IOCFG_1_BASE + 0x0B0}, +/* 160 */ {IOCFG_1_BASE + 0x0B0}, +/* 161 */ {IOCFG_3_BASE + 0x0B0}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {IOCFG_5_BASE + 0x0A0}, +/* 179 */ {IOCFG_5_BASE + 0x0A0}, +/* 180 */ {IOCFG_5_BASE + 0x0A0}, +/* 181 */ {IOCFG_5_BASE + 0x0A0}, +/* 182 */ {IOCFG_5_BASE + 0x0A0}, +/* 183 */ {IOCFG_5_BASE + 0x0A0}, +/* 184 */ {IOCFG_5_BASE + 0x0A0}, +/* 185 */ {IOCFG_5_BASE + 0x0A0}, +/* 186 */ {IOCFG_5_BASE + 0x0A0}, +/* 187 */ {IOCFG_5_BASE + 0x0A0}, +/* 188 */ {IOCFG_5_BASE + 0x0A0}, +/* 189 */ {IOCFG_5_BASE + 0x0A0} +}; + + +PIN_offset DRV_offset[] = { +/* 0 */ {20}, +/* 1 */ {20}, +/* 2 */ {20}, +/* 3 */ {20}, +/* 4 */ {24}, +/* 5 */ {24}, +/* 6 */ {24}, +/* 7 */ {24}, +/* 8 */ {16}, +/* 9 */ {20}, +/* 10 */ {20}, +/* 11 */ {12}, +/* 12 */ {28}, +/* 13 */ {20}, +/* 14 */ {20}, +/* 15 */ {20}, +/* 16 */ {20}, +/* 17 */ {24}, +/* 18 */ {24}, +/* 19 */ {24}, +/* 20 */ {24}, +/* 21 */ {28}, +/* 22 */ {28}, +/* 23 */ {28}, +/* 24 */ {28}, +/* 25 */ {0}, +/* 26 */ {0}, +/* 27 */ {0}, +/* 28 */ {0}, +/* 29 */ {24}, +/* 30 */ {0}, +/* 31 */ {4}, +/* 32 */ {8}, +/* 33 */ {4}, +/* 34 */ {4}, +/* 35 */ {4}, +/* 36 */ {12}, +/* 37 */ {12}, +/* 38 */ {12}, +/* 39 */ {16}, +/* 40 */ {16}, +/* 41 */ {16}, +/* 42 */ {0}, +/* 43 */ {0}, +/* 44 */ {4}, +/* 45 */ {8}, +/* 46 */ {8}, +/* 47 */ {12}, +/* 48 */ {12}, +/* 49 */ {16}, +/* 50 */ {16}, +/* 51 */ {4}, +/* 52 */ {4}, +/* 53 */ {4}, +/* 54 */ {4}, +/* 55 */ {4}, +/* 56 */ {4}, +/* 57 */ {4}, +/* 58 */ {4}, +/* 59 */ {4}, +/* 60 */ {4}, +/* 61 */ {4}, +/* 62 */ {4}, +/* 63 */ {8}, +/* 64 */ {8}, +/* 65 */ {8}, +/* 66 */ {8}, +/* 67 */ {12}, +/* 68 */ {12}, +/* 69 */ {12}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {0}, +/* 76 */ {0}, +/* 77 */ {0}, +/* 78 */ {0}, +/* 79 */ {4}, +/* 80 */ {4}, +/* 81 */ {4}, +/* 82 */ {4}, +/* 83 */ {8}, +/* 84 */ {8}, +/* 85 */ {8}, +/* 86 */ {8}, +/* 87 */ {12}, +/* 88 */ {12}, +/* 89 */ {12}, +/* 90 */ {12}, +/* 91 */ {0}, +/* 92 */ {4}, +/* 93 */ {4}, +/* 94 */ {0}, +/* 95 */ {8}, +/* 96 */ {8}, +/* 97 */ {8}, +/* 98 */ {8}, +/* 99 */ {12}, +/* 100 */ {12}, +/* 101 */ {16}, +/* 102 */ {16}, +/* 103 */ {16}, +/* 104 */ {16}, +/* 105 */ {28}, +/* 106 */ {28}, +/* 107 */ {0}, +/* 108 */ {0}, +/* 109 */ {8}, +/* 110 */ {12}, +/* 111 */ {12}, +/* 112 */ {24}, +/* 113 */ {24}, +/* 114 */ {0}, +/* 115 */ {0}, +/* 116 */ {0}, +/* 117 */ {4}, +/* 118 */ {4}, +/* 119 */ {8}, +/* 120 */ {8}, +/* 121 */ {8}, +/* 122 */ {8}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {12}, +/* 132 */ {16}, +/* 133 */ {20}, +/* 134 */ {12}, +/* 135 */ {12}, +/* 136 */ {12}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {0}, +/* 148 */ {4}, +/* 149 */ {8}, +/* 150 */ {8}, +/* 151 */ {8}, +/* 152 */ {16}, +/* 153 */ {16}, +/* 154 */ {16}, +/* 155 */ {16}, +/* 156 */ {20}, +/* 157 */ {4}, +/* 158 */ {4}, +/* 159 */ {12}, +/* 160 */ {12}, +/* 161 */ {4}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, + /* 178 */ {0}, +/* 179 */ {4}, +/* 180 */ {8}, +/* 181 */ {0}, +/* 182 */ {0}, +/* 183 */ {0}, +/* 184 */ {0}, +/* 185 */ {12}, +/* 186 */ {0}, +/* 187 */ {0}, +/* 188 */ {0}, +/* 189 */ {16} +}; + + +PIN_addr TDSEL_addr[] = { +/* 0 */ {IOCFG_3_BASE + 0x020}, +/* 1 */ {IOCFG_3_BASE + 0x020}, +/* 2 */ {IOCFG_3_BASE + 0x020}, +/* 3 */ {IOCFG_3_BASE + 0x020}, +/* 4 */ {IOCFG_3_BASE + 0x020}, +/* 5 */ {IOCFG_3_BASE + 0x020}, +/* 6 */ {IOCFG_3_BASE + 0x020}, +/* 7 */ {IOCFG_3_BASE + 0x020}, +/* 8 */ {IOCFG_3_BASE + 0x030}, +/* 9 */ {IOCFG_3_BASE + 0x030}, +/* 10 */ {IOCFG_3_BASE + 0x030}, +/* 11 */ {IOCFG_0_BASE + 0x020}, +/* 12 */ {IOCFG_0_BASE + 0x020}, +/* 13 */ {IOCFG_1_BASE + 0x020}, +/* 14 */ {IOCFG_1_BASE + 0x020}, +/* 15 */ {IOCFG_1_BASE + 0x020}, +/* 16 */ {IOCFG_1_BASE + 0x020}, +/* 17 */ {IOCFG_1_BASE + 0x020}, +/* 18 */ {IOCFG_1_BASE + 0x020}, +/* 19 */ {IOCFG_1_BASE + 0x020}, +/* 20 */ {IOCFG_1_BASE + 0x020}, +/* 21 */ {IOCFG_1_BASE + 0x020}, +/* 22 */ {IOCFG_1_BASE + 0x020}, +/* 23 */ {IOCFG_1_BASE + 0x020}, +/* 24 */ {IOCFG_1_BASE + 0x020}, +/* 25 */ {IOCFG_1_BASE + 0x030}, +/* 26 */ {IOCFG_1_BASE + 0x030}, +/* 27 */ {IOCFG_1_BASE + 0x030}, +/* 28 */ {IOCFG_1_BASE + 0x030}, +/* 29 */ {IOCFG_0_BASE + 0x020}, +/* 30 */ {IOCFG_0_BASE + 0x030}, +/* 31 */ {IOCFG_0_BASE + 0x030}, +/* 32 */ {IOCFG_0_BASE + 0x030}, +/* 33 */ {IOCFG_0_BASE + 0x030}, +/* 34 */ {IOCFG_0_BASE + 0x030}, +/* 35 */ {IOCFG_0_BASE + 0x030}, +/* 36 */ {IOCFG_0_BASE + 0x030}, +/* 37 */ {IOCFG_0_BASE + 0x030}, +/* 38 */ {IOCFG_0_BASE + 0x030}, +/* 39 */ {IOCFG_0_BASE + 0x030}, +/* 40 */ {IOCFG_0_BASE + 0x030}, +/* 41 */ {IOCFG_0_BASE + 0x030}, +/* 42 */ {IOCFG_1_BASE + 0x020}, +/* 43 */ {IOCFG_1_BASE + 0x020}, +/* 44 */ {IOCFG_1_BASE + 0x020}, +/* 45 */ {IOCFG_1_BASE + 0x020}, +/* 46 */ {IOCFG_1_BASE + 0x020}, +/* 47 */ {IOCFG_1_BASE + 0x020}, +/* 48 */ {IOCFG_1_BASE + 0x020}, +/* 49 */ {IOCFG_1_BASE + 0x020}, +/* 50 */ {IOCFG_1_BASE + 0x020}, +/* 51 */ {IOCFG_1_BASE + 0x030}, +/* 52 */ {IOCFG_1_BASE + 0x030}, +/* 53 */ {IOCFG_1_BASE + 0x030}, +/* 54 */ {IOCFG_1_BASE + 0x030}, +/* 55 */ {IOCFG_1_BASE + 0x030}, +/* 56 */ {IOCFG_1_BASE + 0x030}, +/* 57 */ {IOCFG_1_BASE + 0x030}, +/* 58 */ {IOCFG_1_BASE + 0x030}, +/* 59 */ {IOCFG_1_BASE + 0x030}, +/* 60 */ {IOCFG_1_BASE + 0x030}, +/* 61 */ {IOCFG_1_BASE + 0x030}, +/* 62 */ {IOCFG_1_BASE + 0x030}, +/* 63 */ {IOCFG_1_BASE + 0x030}, +/* 64 */ {IOCFG_1_BASE + 0x030}, +/* 65 */ {IOCFG_1_BASE + 0x030}, +/* 66 */ {IOCFG_1_BASE + 0x030}, +/* 67 */ {IOCFG_1_BASE + 0x030}, +/* 68 */ {IOCFG_1_BASE + 0x030}, +/* 69 */ {IOCFG_1_BASE + 0x030}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {IOCFG_2_BASE + 0x020}, +/* 76 */ {IOCFG_2_BASE + 0x020}, +/* 77 */ {IOCFG_2_BASE + 0x020}, +/* 78 */ {IOCFG_2_BASE + 0x020}, +/* 79 */ {IOCFG_2_BASE + 0x020}, +/* 80 */ {IOCFG_2_BASE + 0x020}, +/* 81 */ {IOCFG_2_BASE + 0x020}, +/* 82 */ {IOCFG_2_BASE + 0x020}, +/* 83 */ {IOCFG_2_BASE + 0x020}, +/* 84 */ {IOCFG_2_BASE + 0x020}, +/* 85 */ {IOCFG_2_BASE + 0x020}, +/* 86 */ {IOCFG_2_BASE + 0x020}, +/* 87 */ {IOCFG_2_BASE + 0x020}, +/* 88 */ {IOCFG_2_BASE + 0x020}, +/* 89 */ {IOCFG_2_BASE + 0x020}, +/* 90 */ {IOCFG_2_BASE + 0x020}, +/* 91 */ {IOCFG_3_BASE + 0x020}, +/* 92 */ {IOCFG_3_BASE + 0x020}, +/* 93 */ {IOCFG_3_BASE + 0x020}, +/* 94 */ {IOCFG_3_BASE + 0x020}, +/* 95 */ {IOCFG_3_BASE + 0x020}, +/* 96 */ {IOCFG_3_BASE + 0x020}, +/* 97 */ {IOCFG_3_BASE + 0x020}, +/* 98 */ {IOCFG_3_BASE + 0x020}, +/* 99 */ {IOCFG_3_BASE + 0x020}, +/* 100 */ {IOCFG_3_BASE + 0x020}, +/* 101 */ {IOCFG_3_BASE + 0x020}, +/* 102 */ {IOCFG_3_BASE + 0x020}, +/* 103 */ {IOCFG_3_BASE + 0x020}, +/* 104 */ {IOCFG_3_BASE + 0x020}, +/* 105 */ {IOCFG_3_BASE + 0x020}, +/* 106 */ {IOCFG_3_BASE + 0x020}, +/* 107 */ {IOCFG_3_BASE + 0x030}, +/* 108 */ {IOCFG_3_BASE + 0x030}, +/* 109 */ {IOCFG_3_BASE + 0x030}, +/* 110 */ {IOCFG_3_BASE + 0x030}, +/* 111 */ {IOCFG_3_BASE + 0x030}, +/* 112 */ {IOCFG_3_BASE + 0x030}, +/* 113 */ {IOCFG_3_BASE + 0x030}, +/* 114 */ {IOCFG_4_BASE + 0x020}, +/* 115 */ {IOCFG_4_BASE + 0x020}, +/* 116 */ {IOCFG_4_BASE + 0x020}, +/* 117 */ {IOCFG_4_BASE + 0x020}, +/* 118 */ {IOCFG_4_BASE + 0x020}, +/* 119 */ {IOCFG_4_BASE + 0x020}, +/* 120 */ {IOCFG_4_BASE + 0x020}, +/* 121 */ {IOCFG_4_BASE + 0x020}, +/* 122 */ {IOCFG_4_BASE + 0x020}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {IOCFG_4_BASE + 0x020}, +/* 132 */ {IOCFG_4_BASE + 0x020}, +/* 133 */ {IOCFG_4_BASE + 0x020}, +/* 134 */ {IOCFG_4_BASE + 0x020}, +/* 135 */ {IOCFG_4_BASE + 0x020}, +/* 136 */ {IOCFG_4_BASE + 0x020}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {IOCFG_0_BASE + 0x020}, +/* 148 */ {IOCFG_0_BASE + 0x020}, +/* 149 */ {IOCFG_0_BASE + 0x020}, +/* 150 */ {IOCFG_0_BASE + 0x020}, +/* 151 */ {IOCFG_0_BASE + 0x020}, +/* 152 */ {IOCFG_0_BASE + 0x020}, +/* 153 */ {IOCFG_0_BASE + 0x020}, +/* 154 */ {IOCFG_0_BASE + 0x020}, +/* 155 */ {IOCFG_0_BASE + 0x020}, +/* 156 */ {IOCFG_0_BASE + 0x020}, +/* 157 */ {IOCFG_1_BASE + 0x020}, +/* 158 */ {IOCFG_1_BASE + 0x020}, +/* 159 */ {IOCFG_1_BASE + 0x030}, +/* 160 */ {IOCFG_1_BASE + 0x030}, +/* 161 */ {IOCFG_3_BASE + 0x030}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {IOCFG_5_BASE + 0x020}, +/* 179 */ {IOCFG_5_BASE + 0x020}, +/* 180 */ {IOCFG_5_BASE + 0x020}, +/* 181 */ {IOCFG_5_BASE + 0x020}, +/* 182 */ {IOCFG_5_BASE + 0x020}, +/* 183 */ {IOCFG_5_BASE + 0x020}, +/* 184 */ {IOCFG_5_BASE + 0x020}, +/* 185 */ {IOCFG_5_BASE + 0x020}, +/* 186 */ {IOCFG_5_BASE + 0x020}, +/* 187 */ {IOCFG_5_BASE + 0x020}, +/* 188 */ {IOCFG_5_BASE + 0x020}, +/* 189 */ {IOCFG_5_BASE + 0x020} +}; + + +PIN_offset TDSEL_offset[] = { +/* 0 */ {20}, +/* 1 */ {20}, +/* 2 */ {20}, +/* 3 */ {20}, +/* 4 */ {24}, +/* 5 */ {24}, +/* 6 */ {24}, +/* 7 */ {24}, +/* 8 */ {16}, +/* 9 */ {20}, +/* 10 */ {20}, +/* 11 */ {12}, +/* 12 */ {28}, +/* 13 */ {20}, +/* 14 */ {20}, +/* 15 */ {20}, +/* 16 */ {20}, +/* 17 */ {24}, +/* 18 */ {24}, +/* 19 */ {24}, +/* 20 */ {24}, +/* 21 */ {28}, +/* 22 */ {28}, +/* 23 */ {28}, +/* 24 */ {28}, +/* 25 */ {0}, +/* 26 */ {0}, +/* 27 */ {0}, +/* 28 */ {0}, +/* 29 */ {24}, +/* 30 */ {0}, +/* 31 */ {4}, +/* 32 */ {8}, +/* 33 */ {4}, +/* 34 */ {4}, +/* 35 */ {4}, +/* 36 */ {12}, +/* 37 */ {12}, +/* 38 */ {12}, +/* 39 */ {16}, +/* 40 */ {16}, +/* 41 */ {16}, +/* 42 */ {0}, +/* 43 */ {0}, +/* 44 */ {4}, +/* 45 */ {8}, +/* 46 */ {8}, +/* 47 */ {12}, +/* 48 */ {12}, +/* 49 */ {16}, +/* 50 */ {16}, +/* 51 */ {4}, +/* 52 */ {4}, +/* 53 */ {4}, +/* 54 */ {4}, +/* 55 */ {4}, +/* 56 */ {4}, +/* 57 */ {4}, +/* 58 */ {4}, +/* 59 */ {4}, +/* 60 */ {4}, +/* 61 */ {4}, +/* 62 */ {4}, +/* 63 */ {8}, +/* 64 */ {8}, +/* 65 */ {8}, +/* 66 */ {8}, +/* 67 */ {12}, +/* 68 */ {12}, +/* 69 */ {12}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {0}, +/* 76 */ {0}, +/* 77 */ {0}, +/* 78 */ {0}, +/* 79 */ {4}, +/* 80 */ {4}, +/* 81 */ {4}, +/* 82 */ {4}, +/* 83 */ {8}, +/* 84 */ {8}, +/* 85 */ {8}, +/* 86 */ {8}, +/* 87 */ {12}, +/* 88 */ {12}, +/* 89 */ {12}, +/* 90 */ {12}, +/* 91 */ {0}, +/* 92 */ {4}, +/* 93 */ {4}, +/* 94 */ {0}, +/* 95 */ {8}, +/* 96 */ {8}, +/* 97 */ {8}, +/* 98 */ {8}, +/* 99 */ {12}, +/* 100 */ {12}, +/* 101 */ {16}, +/* 102 */ {16}, +/* 103 */ {16}, +/* 104 */ {16}, +/* 105 */ {28}, +/* 106 */ {28}, +/* 107 */ {0}, +/* 108 */ {0}, +/* 109 */ {8}, +/* 110 */ {12}, +/* 111 */ {12}, +/* 112 */ {24}, +/* 113 */ {24}, +/* 114 */ {0}, +/* 115 */ {0}, +/* 116 */ {0}, +/* 117 */ {4}, +/* 118 */ {4}, +/* 119 */ {8}, +/* 120 */ {8}, +/* 121 */ {8}, +/* 122 */ {8}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {12}, +/* 132 */ {16}, +/* 133 */ {20}, +/* 134 */ {12}, +/* 135 */ {12}, +/* 136 */ {12}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {0}, +/* 148 */ {4}, +/* 149 */ {8}, +/* 150 */ {8}, +/* 151 */ {8}, +/* 152 */ {16}, +/* 153 */ {16}, +/* 154 */ {16}, +/* 155 */ {16}, +/* 156 */ {20}, +/* 157 */ {4}, +/* 158 */ {4}, +/* 159 */ {12}, +/* 160 */ {12}, +/* 161 */ {4}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {0}, +/* 179 */ {4}, +/* 180 */ {8}, +/* 181 */ {0}, +/* 182 */ {0}, +/* 183 */ {0}, +/* 184 */ {0}, +/* 185 */ {12}, +/* 186 */ {0}, +/* 187 */ {0}, +/* 188 */ {0}, +/* 189 */ {16} +}; + + +PIN_addr RDSEL_addr[] = { +/* 0 */ {IOCFG_3_BASE + 0x040}, +/* 1 */ {IOCFG_3_BASE + 0x040}, +/* 2 */ {IOCFG_3_BASE + 0x040}, +/* 3 */ {IOCFG_3_BASE + 0x040}, +/* 4 */ {IOCFG_3_BASE + 0x040}, +/* 5 */ {IOCFG_3_BASE + 0x040}, +/* 6 */ {IOCFG_3_BASE + 0x040}, +/* 7 */ {IOCFG_3_BASE + 0x040}, +/* 8 */ {IOCFG_3_BASE + 0x040}, +/* 9 */ {IOCFG_3_BASE + 0x040}, +/* 10 */ {IOCFG_3_BASE + 0x040}, +/* 11 */ {IOCFG_0_BASE + 0x040}, +/* 12 */ {IOCFG_0_BASE + 0x040}, +/* 13 */ {IOCFG_1_BASE + 0x040}, +/* 14 */ {IOCFG_1_BASE + 0x040}, +/* 15 */ {IOCFG_1_BASE + 0x040}, +/* 16 */ {IOCFG_1_BASE + 0x040}, +/* 17 */ {IOCFG_1_BASE + 0x040}, +/* 18 */ {IOCFG_1_BASE + 0x040}, +/* 19 */ {IOCFG_1_BASE + 0x040}, +/* 20 */ {IOCFG_1_BASE + 0x040}, +/* 21 */ {IOCFG_1_BASE + 0x040}, +/* 22 */ {IOCFG_1_BASE + 0x040}, +/* 23 */ {IOCFG_1_BASE + 0x040}, +/* 24 */ {IOCFG_1_BASE + 0x040}, +/* 25 */ {IOCFG_1_BASE + 0x040}, +/* 26 */ {IOCFG_1_BASE + 0x040}, +/* 27 */ {IOCFG_1_BASE + 0x040}, +/* 28 */ {IOCFG_1_BASE + 0x040}, +/* 29 */ {IOCFG_0_BASE + 0x040}, +/* 30 */ {IOCFG_0_BASE + 0x040}, +/* 31 */ {IOCFG_0_BASE + 0x040}, +/* 32 */ {IOCFG_0_BASE + 0x050}, +/* 33 */ {IOCFG_0_BASE + 0x040}, +/* 34 */ {IOCFG_0_BASE + 0x040}, +/* 35 */ {IOCFG_0_BASE + 0x040}, +/* 36 */ {IOCFG_0_BASE + 0x050}, +/* 37 */ {IOCFG_0_BASE + 0x050}, +/* 38 */ {IOCFG_0_BASE + 0x050}, +/* 39 */ {IOCFG_0_BASE + 0x050}, +/* 40 */ {IOCFG_0_BASE + 0x050}, +/* 41 */ {IOCFG_0_BASE + 0x050}, +/* 42 */ {IOCFG_1_BASE + 0x040}, +/* 43 */ {IOCFG_1_BASE + 0x040}, +/* 44 */ {IOCFG_1_BASE + 0x040}, +/* 45 */ {IOCFG_1_BASE + 0x040}, +/* 46 */ {IOCFG_1_BASE + 0x040}, +/* 47 */ {IOCFG_1_BASE + 0x040}, +/* 48 */ {IOCFG_1_BASE + 0x040}, +/* 49 */ {IOCFG_1_BASE + 0x040}, +/* 50 */ {IOCFG_1_BASE + 0x040}, +/* 51 */ {IOCFG_1_BASE + 0x040}, +/* 52 */ {IOCFG_1_BASE + 0x040}, +/* 53 */ {IOCFG_1_BASE + 0x040}, +/* 54 */ {IOCFG_1_BASE + 0x040}, +/* 55 */ {IOCFG_1_BASE + 0x040}, +/* 56 */ {IOCFG_1_BASE + 0x040}, +/* 57 */ {IOCFG_1_BASE + 0x040}, +/* 58 */ {IOCFG_1_BASE + 0x040}, +/* 59 */ {IOCFG_1_BASE + 0x040}, +/* 60 */ {IOCFG_1_BASE + 0x040}, +/* 61 */ {IOCFG_1_BASE + 0x040}, +/* 62 */ {IOCFG_1_BASE + 0x040}, +/* 63 */ {IOCFG_1_BASE + 0x040}, +/* 64 */ {IOCFG_1_BASE + 0x040}, +/* 65 */ {IOCFG_1_BASE + 0x040}, +/* 66 */ {IOCFG_1_BASE + 0x040}, +/* 67 */ {IOCFG_1_BASE + 0x040}, +/* 68 */ {IOCFG_1_BASE + 0x040}, +/* 69 */ {IOCFG_1_BASE + 0x040}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {IOCFG_2_BASE + 0x040}, +/* 76 */ {IOCFG_2_BASE + 0x040}, +/* 77 */ {IOCFG_2_BASE + 0x040}, +/* 78 */ {IOCFG_2_BASE + 0x040}, +/* 79 */ {IOCFG_2_BASE + 0x040}, +/* 80 */ {IOCFG_2_BASE + 0x040}, +/* 81 */ {IOCFG_2_BASE + 0x040}, +/* 82 */ {IOCFG_2_BASE + 0x040}, +/* 83 */ {IOCFG_2_BASE + 0x040}, +/* 84 */ {IOCFG_2_BASE + 0x040}, +/* 85 */ {IOCFG_2_BASE + 0x040}, +/* 86 */ {IOCFG_2_BASE + 0x040}, +/* 87 */ {IOCFG_2_BASE + 0x040}, +/* 88 */ {IOCFG_2_BASE + 0x040}, +/* 89 */ {IOCFG_2_BASE + 0x040}, +/* 90 */ {IOCFG_2_BASE + 0x040}, +/* 91 */ {IOCFG_3_BASE + 0x040}, +/* 92 */ {IOCFG_3_BASE + 0x040}, +/* 93 */ {IOCFG_3_BASE + 0x040}, +/* 94 */ {IOCFG_3_BASE + 0x040}, +/* 95 */ {IOCFG_3_BASE + 0x040}, +/* 96 */ {IOCFG_3_BASE + 0x040}, +/* 97 */ {IOCFG_3_BASE + 0x040}, +/* 98 */ {IOCFG_3_BASE + 0x040}, +/* 99 */ {IOCFG_3_BASE + 0x040}, +/* 100 */ {IOCFG_3_BASE + 0x040}, +/* 101 */ {IOCFG_3_BASE + 0x040}, +/* 102 */ {IOCFG_3_BASE + 0x040}, +/* 103 */ {IOCFG_3_BASE + 0x040}, +/* 104 */ {IOCFG_3_BASE + 0x040}, +/* 105 */ {IOCFG_3_BASE + 0x040}, +/* 106 */ {IOCFG_3_BASE + 0x040}, +/* 107 */ {IOCFG_3_BASE + 0x040}, +/* 108 */ {IOCFG_3_BASE + 0x040}, +/* 109 */ {IOCFG_3_BASE + 0x040}, +/* 110 */ {IOCFG_3_BASE + 0x040}, +/* 111 */ {IOCFG_3_BASE + 0x040}, +/* 112 */ {IOCFG_3_BASE + 0x040}, +/* 113 */ {IOCFG_3_BASE + 0x040}, +/* 114 */ {IOCFG_4_BASE + 0x040}, +/* 115 */ {IOCFG_4_BASE + 0x040}, +/* 116 */ {IOCFG_4_BASE + 0x040}, +/* 117 */ {IOCFG_4_BASE + 0x040}, +/* 118 */ {IOCFG_4_BASE + 0x040}, +/* 119 */ {IOCFG_4_BASE + 0x040}, +/* 120 */ {IOCFG_4_BASE + 0x040}, +/* 121 */ {IOCFG_4_BASE + 0x040}, +/* 122 */ {IOCFG_4_BASE + 0x040}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {IOCFG_4_BASE + 0x040}, +/* 132 */ {IOCFG_4_BASE + 0x040}, +/* 133 */ {IOCFG_4_BASE + 0x040}, +/* 134 */ {IOCFG_4_BASE + 0x040}, +/* 135 */ {IOCFG_4_BASE + 0x040}, +/* 136 */ {IOCFG_4_BASE + 0x040}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {IOCFG_0_BASE + 0x040}, +/* 148 */ {IOCFG_0_BASE + 0x040}, +/* 149 */ {IOCFG_0_BASE + 0x040}, +/* 150 */ {IOCFG_0_BASE + 0x040}, +/* 151 */ {IOCFG_0_BASE + 0x040}, +/* 152 */ {IOCFG_0_BASE + 0x040}, +/* 153 */ {IOCFG_0_BASE + 0x040}, +/* 154 */ {IOCFG_0_BASE + 0x040}, +/* 155 */ {IOCFG_0_BASE + 0x040}, +/* 156 */ {IOCFG_0_BASE + 0x040}, +/* 157 */ {IOCFG_1_BASE + 0x040}, +/* 158 */ {IOCFG_1_BASE + 0x040}, +/* 159 */ {IOCFG_1_BASE + 0x040}, +/* 160 */ {IOCFG_1_BASE + 0x040}, +/* 161 */ {IOCFG_3_BASE + 0x040}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {IOCFG_5_BASE + 0x040}, +/* 179 */ {IOCFG_5_BASE + 0x040}, +/* 180 */ {IOCFG_5_BASE + 0x040}, +/* 181 */ {IOCFG_5_BASE + 0x040}, +/* 182 */ {IOCFG_5_BASE + 0x040}, +/* 183 */ {IOCFG_5_BASE + 0x040}, +/* 184 */ {IOCFG_5_BASE + 0x040}, +/* 185 */ {IOCFG_5_BASE + 0x040}, +/* 186 */ {IOCFG_5_BASE + 0x040}, +/* 187 */ {IOCFG_5_BASE + 0x040}, +/* 188 */ {IOCFG_5_BASE + 0x040}, +/* 189 */ {IOCFG_5_BASE + 0x040} +}; + + +PIN_offset RDSEL_offset[] = { +/* 0 */ {10}, +/* 1 */ {10}, +/* 2 */ {10}, +/* 3 */ {10}, +/* 4 */ {12}, +/* 5 */ {12}, +/* 6 */ {12}, +/* 7 */ {12}, +/* 8 */ {24}, +/* 9 */ {26}, +/* 10 */ {26}, +/* 11 */ {6}, +/* 12 */ {14}, +/* 13 */ {10}, +/* 14 */ {10}, +/* 15 */ {10}, +/* 16 */ {10}, +/* 17 */ {12}, +/* 18 */ {12}, +/* 19 */ {12}, +/* 20 */ {12}, +/* 21 */ {14}, +/* 22 */ {14}, +/* 23 */ {14}, +/* 24 */ {14}, +/* 25 */ {16}, +/* 26 */ {16}, +/* 27 */ {16}, +/* 28 */ {16}, +/* 29 */ {12}, +/* 30 */ {16}, +/* 31 */ {22}, +/* 32 */ {6}, +/* 33 */ {22}, +/* 34 */ {22}, +/* 35 */ {22}, +/* 36 */ {12}, +/* 37 */ {12}, +/* 38 */ {12}, +/* 39 */ {18}, +/* 40 */ {18}, +/* 41 */ {18}, +/* 42 */ {0}, +/* 43 */ {0}, +/* 44 */ {2}, +/* 45 */ {4}, +/* 46 */ {4}, +/* 47 */ {6}, +/* 48 */ {6}, +/* 49 */ {8}, +/* 50 */ {8}, +/* 51 */ {18}, +/* 52 */ {18}, +/* 53 */ {18}, +/* 54 */ {18}, +/* 55 */ {18}, +/* 56 */ {18}, +/* 57 */ {18}, +/* 58 */ {18}, +/* 59 */ {18}, +/* 60 */ {18}, +/* 61 */ {18}, +/* 62 */ {18}, +/* 63 */ {20}, +/* 64 */ {20}, +/* 65 */ {20}, +/* 66 */ {20}, +/* 67 */ {22}, +/* 68 */ {22}, +/* 69 */ {22}, +/* 70 */ {-1}, +/* 71 */ {-1}, +/* 72 */ {-1}, +/* 73 */ {-1}, +/* 74 */ {-1}, +/* 75 */ {0}, +/* 76 */ {0}, +/* 77 */ {0}, +/* 78 */ {0}, +/* 79 */ {2}, +/* 80 */ {2}, +/* 81 */ {2}, +/* 82 */ {2}, +/* 83 */ {4}, +/* 84 */ {4}, +/* 85 */ {4}, +/* 86 */ {4}, +/* 87 */ {6}, +/* 88 */ {6}, +/* 89 */ {6}, +/* 90 */ {6}, +/* 91 */ {0}, +/* 92 */ {2}, +/* 93 */ {2}, +/* 94 */ {0}, +/* 95 */ {4}, +/* 96 */ {4}, +/* 97 */ {4}, +/* 98 */ {4}, +/* 99 */ {6}, +/* 100 */ {6}, +/* 101 */ {8}, +/* 102 */ {8}, +/* 103 */ {8}, +/* 104 */ {8}, +/* 105 */ {14}, +/* 106 */ {14}, +/* 107 */ {16}, +/* 108 */ {16}, +/* 109 */ {20}, +/* 110 */ {22}, +/* 111 */ {22}, +/* 112 */ {28}, +/* 113 */ {28}, +/* 114 */ {0}, +/* 115 */ {0}, +/* 116 */ {0}, +/* 117 */ {6}, +/* 118 */ {6}, +/* 119 */ {8}, +/* 120 */ {8}, +/* 121 */ {8}, +/* 122 */ {8}, +/* 123 */ {-1}, +/* 124 */ {-1}, +/* 125 */ {-1}, +/* 126 */ {-1}, +/* 127 */ {-1}, +/* 128 */ {-1}, +/* 129 */ {-1}, +/* 130 */ {-1}, +/* 131 */ {10}, +/* 132 */ {16}, +/* 133 */ {22}, +/* 134 */ {10}, +/* 135 */ {10}, +/* 136 */ {10}, +/* 137 */ {-1}, +/* 138 */ {-1}, +/* 139 */ {-1}, +/* 140 */ {-1}, +/* 141 */ {-1}, +/* 142 */ {-1}, +/* 143 */ {-1}, +/* 144 */ {-1}, +/* 145 */ {-1}, +/* 146 */ {-1}, +/* 147 */ {0}, +/* 148 */ {2}, +/* 149 */ {4}, +/* 150 */ {4}, +/* 151 */ {4}, +/* 152 */ {8}, +/* 153 */ {8}, +/* 154 */ {8}, +/* 155 */ {8}, +/* 156 */ {10}, +/* 157 */ {2}, +/* 158 */ {2}, +/* 159 */ {22}, +/* 160 */ {22}, +/* 161 */ {18}, +/* 162 */ {-1}, +/* 163 */ {-1}, +/* 164 */ {-1}, +/* 165 */ {-1}, +/* 166 */ {-1}, +/* 167 */ {-1}, +/* 168 */ {-1}, +/* 169 */ {-1}, +/* 170 */ {-1}, +/* 171 */ {-1}, +/* 172 */ {-1}, +/* 173 */ {-1}, +/* 174 */ {-1}, +/* 175 */ {-1}, +/* 176 */ {-1}, +/* 177 */ {-1}, +/* 178 */ {0}, +/* 179 */ {6}, +/* 180 */ {12}, +/* 181 */ {0}, +/* 182 */ {0}, +/* 183 */ {0}, +/* 184 */ {0}, +/* 185 */ {18}, +/* 186 */ {0}, +/* 187 */ {0}, +/* 188 */ {0}, +/* 189 */ {24} +}; + +#endif + +#endif /* _GPIO_CFG_H_ */ diff --git a/drivers/misc/mediatek/gpio/mt6755/mt_gpio_affix.c b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_affix.c new file mode 100644 index 0000000000000000000000000000000000000000..595a3f5477dde91c0a39efc443ae946a75c8a1c8 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_affix.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include "mt-plat/sync_write.h" +#include +#include +/* #include */ +#include +#include "6755_gpio.h" + + +void mt_gpio_pin_decrypt(unsigned long *cipher) +{ + /* just for debug, find out who used pin number directly */ + if ((*cipher & (0x80000000)) == 0) { + GPIOERR("GPIO%u HARDCODE warning!!!\n", (unsigned int)(*cipher)); + dump_stack(); + /* return; */ + } + + /* GPIOERR("Pin magic number is %x\n",*cipher); */ + *cipher &= ~(0x80000000); +} + + +/*---------------------------------------------------------------------------*/ +static DEVICE_ATTR(pin, 0664, mt_gpio_show_pin, mt_gpio_store_pin); +/*---------------------------------------------------------------------------*/ +static struct device_attribute *gpio_attr_list[] = { + &dev_attr_pin, +}; + +/*---------------------------------------------------------------------------*/ +int mt_gpio_create_attr(struct device *dev) +{ + int idx, err = 0; + int num = (int)(sizeof(gpio_attr_list)/sizeof(gpio_attr_list[0])); + + if (!dev) + return -EINVAL; + for (idx = 0; idx < num; idx++) { + if (device_create_file(dev, gpio_attr_list[idx])) + break; + } + return err; +} +/*---------------------------------------------------------------------------*/ +int mt_gpio_delete_attr(struct device *dev) +{ + int idx , err = 0; + int num = (int)(sizeof(gpio_attr_list)/sizeof(gpio_attr_list[0])); + + if (!dev) + return -EINVAL; + for (idx = 0; idx < num; idx++) + device_remove_file(dev, gpio_attr_list[idx]); + return err; +} diff --git a/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base.c b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base.c new file mode 100644 index 0000000000000000000000000000000000000000..d4e82e00e8b06c97d33dfe6fc9dfcf43fae75064 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base.c @@ -0,0 +1,588 @@ +/****************************************************************************** + * mt_gpio_base.c - MTKLinux GPIO Device Driver + * + * Copyright 2008-2009 MediaTek Co.,Ltd. + * + * DESCRIPTION: + * This file provid the other drivers GPIO relative functions + * + ******************************************************************************/ + + +#include "6755_gpio.h" +#include +#include "mt-plat/sync_write.h" +#include +#include +#include "mt_gpio_base.h" +/* autogen */ +#include "gpio_cfg.h" +#ifdef CONFIG_OF +#include +#endif + +long gpio_pull_select_unsupport[MAX_GPIO_PIN] = { 0 }; +long gpio_pullen_unsupport[MAX_GPIO_PIN] = { 0 }; +long gpio_smt_unsupport[MAX_GPIO_PIN] = { 0 }; + +struct mt_gpio_vbase gpio_vbase; +#define REGSET (4) +#define REGCLR (8) + +static GPIO_REGS *gpio_reg; +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_dir_base(unsigned long pin, unsigned long dir) +{ + unsigned long pos; + unsigned long bit; + GPIO_REGS *reg = gpio_reg; + + if (!reg) + return -ERACCESS; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (dir >= GPIO_DIR_MAX) + return -ERINVAL; + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + if (dir == GPIO_DIR_IN) + GPIO_SET_BITS((1L << bit), ®->dir[pos].rst); + else + GPIO_SET_BITS((1L << bit), ®->dir[pos].set); + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_dir_base(unsigned long pin) +{ + unsigned long pos; + unsigned long bit; + unsigned long data; + GPIO_REGS *reg = gpio_reg; + + if (!reg) + return -ERACCESS; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + data = GPIO_RD32(®->dir[pos].val); + return ((data & (1L << bit)) != 0) ? 1 : 0; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_out_base(unsigned long pin, unsigned long output) +{ + + unsigned long pos; + unsigned long bit; + GPIO_REGS *reg = gpio_reg; + + if (!reg) + return -ERACCESS; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (output >= GPIO_OUT_MAX) + return -ERINVAL; + + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + if (output == GPIO_OUT_ZERO) + GPIO_SET_BITS((1L << bit), ®->dout[pos].rst); + else + GPIO_SET_BITS((1L << bit), ®->dout[pos].set); + return RSUCCESS; + +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_out_base(unsigned long pin) +{ + unsigned long pos; + unsigned long bit; + unsigned long data; + GPIO_REGS *reg = gpio_reg; + + if (!reg) + return -ERACCESS; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + data = GPIO_RD32(®->dout[pos].val); + return ((data & (1L << bit)) != 0) ? 1 : 0; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_in_base(unsigned long pin) +{ + unsigned long pos; + unsigned long bit; + unsigned long data; + GPIO_REGS *reg = gpio_reg; + + if (!reg) + return -ERACCESS; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + data = GPIO_RD32(®->din[pos].val); + return ((data & (1L << bit)) != 0) ? 1 : 0; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_mode_base(unsigned long pin, unsigned long mode) +{ + unsigned long bit; + unsigned long data; + u32 mask; + unsigned long base; + GPIO_REGS *reg = gpio_reg; + + if (!reg) + return -ERACCESS; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (mode >= GPIO_MODE_MAX) + return -ERINVAL; + + +#ifdef SUPPORT_MODE_MWR + /* This is most wanted version after CD1CD2 unification. + * if MWR is supported, no need to read before write. + * MWR[3:0] has 4 bits not 3 bits ; additional 1 bit,MWR[3], is for update enable + * data[3:0] = MWR[3] | MWR[2:0]. + */ + unsigned long pos; + + pos = pin / MAX_GPIO_MODE_PER_REG; + bit = pin % MAX_GPIO_MODE_PER_REG; + + data = ((1L << (GPIO_MODE_BITS * bit)) << 3) | (mode << (GPIO_MODE_BITS * bit)); + GPIO_WR32(®->mode[pos]._align1, data); + +#else + /* For DNL/JD, there is no mwr register for simple register setting. + * Need 1R+1W to set MODE registers + */ + mask = (1L << GPIO_MODE_BITS) - 1; + mode = mode & mask; + +#ifdef REGULAR_MODE_OFFSET + unsigned long pos; + + pos = pin / MAX_GPIO_MODE_PER_REG; + /*for bit to be valid, difference series offset must be provided by HW */ + bit = pin % MAX_GPIO_MODE_PER_REG; + + data = GPIO_RD32(®->mode[pos].val); + data &= (~(mask << bit)); + data |= (mode << bit); + GPIO_WR32(®->mode[pos].val, data); +#else + bit = MODE_offset[pin].offset; + + data = GPIO_RD32(GPIO_BASE + MODE_addr[pin].addr); + data &= (~(mask << bit)); + data |= (mode << bit); + + base = (unsigned long) GPIO_BASE + MODE_addr[pin].addr; + GPIO_WR32(base, data); +#endif + + +#endif + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_mode_base(unsigned long pin) +{ + unsigned long bit; + unsigned long data; + u32 mask; + GPIO_REGS *reg = gpio_reg; + + if (!reg) + return -ERACCESS; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + mask = (1L << GPIO_MODE_BITS) - 1; + +#ifdef SUPPORT_MODE_MWR + unsigned long pos; + + pos = pin / MAX_GPIO_MODE_PER_REG; + bit = pin % MAX_GPIO_MODE_PER_REG; + + data = GPIO_RD32(®->mode[pos].val); + return (data >> (GPIO_MODE_BITS * bit)) & mask; +#else + + bit = MODE_offset[pin].offset; + data = GPIO_RD32(GPIO_BASE + MODE_addr[pin].addr); + return (data >> bit) & mask; +#endif + + +} + + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_smt_base(unsigned long pin, unsigned long enable) +{ + unsigned long reg = 0; + unsigned long bit = 0; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (SMT_offset[pin].offset == -1) { + return GPIO_SMT_UNSUPPORTED; + + } else { + bit = SMT_offset[pin].offset; + reg = IOCFG_RD32(SMT_addr[pin].addr); + if (enable == GPIO_SMT_DISABLE) + reg &= (~(1 << bit)); + /* IOCFG_SET_BITS((1L << bit), SMT_addr[pin].addr + REGCLR); */ + else + reg |= (1 << bit); + /* IOCFG_SET_BITS((1L << bit), SMT_addr[pin].addr + REGSET); */ + } + + IOCFG_WR32(SMT_addr[pin].addr, reg); + + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_smt_base(unsigned long pin) +{ + unsigned long data; + unsigned long bit = 0; + int smt; + + bit = SMT_offset[pin].offset; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (SMT_offset[pin].offset != -1) { + data = IOCFG_RD32(SMT_addr[pin].addr); + smt = ((data & (1L << bit)) != 0) ? 1 : 0; + } else { + return GPIO_SMT_UNSUPPORTED; + } + + return smt; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_ies_base(unsigned long pin, unsigned long enable) +{ + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (IES_offset[pin].offset != -1) { + if (enable == GPIO_IES_DISABLE) + IOCFG_SET_BITS((1L << (IES_offset[pin].offset)), + IES_addr[pin].addr + REGCLR); + else + IOCFG_SET_BITS((1L << (IES_offset[pin].offset)), + IES_addr[pin].addr + REGSET); + + } else + return GPIO_IES_UNSUPPORTED; + + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_ies_base(unsigned long pin) +{ + unsigned long data; + int ies; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (IES_offset[pin].offset != -1) { + data = IOCFG_RD32(IES_addr[pin].addr); + ies = ((data & (1L << (IES_offset[pin].offset))) != 0) ? 1 : 0; + } else { + return GPIO_IES_UNSUPPORTED; + } + + return ies; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_pull_enable_base(unsigned long pin, unsigned long enable) +{ + unsigned long reg; + u32 bit; + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (PULLEN_offset[pin].offset == -1 && PUPD_offset[pin].offset == -1) { + gpio_pullen_unsupport[pin] = -1; + return GPIO_PULL_EN_UNSUPPORTED; + } + if (PULLEN_offset[pin].offset != -1) { + if (enable == GPIO_PULL_DISABLE) + IOCFG_SET_BITS((1L << (PULLEN_offset[pin].offset)), + PULLEN_addr[pin].addr + REGCLR); + else + IOCFG_SET_BITS((1L << (PULLEN_offset[pin].offset)), + PULLEN_addr[pin].addr + REGSET); + } else { + bit = PUPD_offset[pin].offset; + reg = IOCFG_RD32(PUPD_addr[pin].addr); + if (enable == GPIO_PULL_DISABLE) + reg &= (~(0x7 << bit)); + else + reg |= (1 << bit); + IOCFG_WR32(PUPD_addr[pin].addr, reg); + } +/* GPIOERR("%s:pin:%ld, enable:%ld, value:0x%x\n",__FUNCTION__, pin, enable, GPIO_RD32(PULLEN_addr[pin].addr)); */ + + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_pull_enable_base(unsigned long pin) +{ + unsigned long data; + u32 bit = 0; + int en; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if (PULLEN_offset[pin].offset == -1 && PUPD_offset[pin].offset == -1) + return GPIO_PULL_EN_UNSUPPORTED; + + + if (PULLEN_offset[pin].offset != -1) { + bit = PULLEN_offset[pin].offset; + data = IOCFG_RD32(PULLEN_addr[pin].addr); + en = ((data & (1L << bit)) != 0) ? 1 : 0; + } else { + bit = PUPD_offset[pin].offset; + data = IOCFG_RD32(PUPD_addr[pin].addr); + en = ((data & (0x3 << bit)) != 0) ? 1 : 0; + } + + return en; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_pull_select_base(unsigned long pin, unsigned long select) +{ + /* unsigned long flags; */ + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + + if ((PULLSEL_offset[pin].offset == -1) && (PUPD_offset[pin].offset == -1)) { + gpio_pull_select_unsupport[pin] = -1; + return GPIO_PULL_UNSUPPORTED; + } else if (PULLSEL_offset[pin].offset == -1) { + /* spin_lock_irqsave(&mtk_gpio_lock, flags); */ + /* + * SIM1, SIM2 may need special care for resistance selection + */ + if (select == GPIO_PULL_DOWN) { + IOCFG_SET_BITS((1L << (PUPD_offset[pin].offset + 2)), + PUPD_addr[pin].addr + REGSET); + } else { + IOCFG_SET_BITS((1L << (PUPD_offset[pin].offset + 2)), + PUPD_addr[pin].addr + REGCLR); + } + /* spin_unlock_irqrestore(&mtk_gpio_lock, flags); */ + } else { + if (select == GPIO_PULL_DOWN) + IOCFG_SET_BITS((1L << (PULLSEL_offset[pin].offset)), + PULLSEL_addr[pin].addr + REGCLR); + else + IOCFG_SET_BITS((1L << (PULLSEL_offset[pin].offset)), + PULLSEL_addr[pin].addr + REGSET); + } + + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_pull_select_base(unsigned long pin) +{ + unsigned long data; + int pupd; + + if (pin >= MAX_GPIO_PIN) + return -ERINVAL; + + if ((PULLSEL_offset[pin].offset == -1) && (PUPD_offset[pin].offset == -1)) { + return GPIO_PULL_UNSUPPORTED; + } else if (PULLSEL_offset[pin].offset == -1) { + data = IOCFG_RD32(PUPD_addr[pin].addr); + pupd = ((data & (1L << (PUPD_offset[pin].offset + 2))) != 0) ? 0 : 1; + } else { + data = IOCFG_RD32(PULLSEL_addr[pin].addr); + pupd = ((data & (1L << (PULLSEL_offset[pin].offset))) != 0) ? 1 : 0; + } + + return pupd; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_inversion_base(unsigned long pin, unsigned long enable) +{ /*FIX-ME + */ + GPIOERR("%s:function not supprted", __func__); + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_inversion_base(unsigned long pin) +{ /*FIX-ME */ + GPIOERR("%s:function not supprted", __func__); + return 0; /* FIX-ME */ +} +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_slew_rate_base(unsigned long pin, unsigned long enable) +{ + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_slew_rate_base(unsigned long pin) +{ + return RSUCCESS; +} +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_pull_resistor_base(unsigned long pin, unsigned long resistors) +{ + return RSUCCESS; +} +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_pull_resistor_base(unsigned long pin) +{ + return RSUCCESS; +} +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_driving_base(unsigned long pin, unsigned long strength) +{ + return RSUCCESS; +} +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_driving_base(unsigned long pin) +{ + return RSUCCESS; +} + +/*---------------------------------------------------------------------------*/ +void get_gpio_vbase(struct device_node *node) +{ + /* compatible with HAL */ + if (!(gpio_vbase.gpio_regs)) { + + gpio_vbase.gpio_regs = of_iomap(node, 0); + + if (!gpio_vbase.gpio_regs) { + GPIOERR("GPIO base addr is NULL\n"); + return; + } + gpio_reg = (GPIO_REGS *) gpio_vbase.gpio_regs; + GPIOERR("GPIO base add is 0x%p\n", gpio_vbase.gpio_regs); + } + GPIOERR("GPIO base addr is 0x%p, %s\n", gpio_vbase.gpio_regs, __func__); +} + +/*-----------------------User need GPIO APIs before GPIO probe------------------*/ +/*extern struct device_node *get_gpio_np(void);*/ +/*extern struct device_node *get_iocfg_np(void);*/ +#if 0 +static int __init get_gpio_vbase_early(void) +{ + struct device_node *np_gpio = NULL; + struct device_node *np_iocfg = NULL; + + gpio_vbase.gpio_regs = NULL; + gpio_vbase.iocfg_regs = NULL; + np_gpio = get_gpio_np(); + np_iocfg = get_iocfg_np(); + /* Setup IO addresses */ + gpio_vbase.gpio_regs = of_iomap(np_gpio, 0); + if (!gpio_vbase.gpio_regs) { + GPIOERR("GPIO base addr is NULL\n"); + return 0; + } + gpio_vbase.iocfg_regs = of_iomap(np_iocfg, 0); + if (!gpio_vbase.iocfg_regs) { + GPIOERR("GPIO base addr is NULL\n"); + return 0; + } + /* gpio_reg = (GPIO_REGS*)(GPIO_BASE); */ + GPIOERR("GPIO base addr is 0x%p, %s\n", gpio_vbase.gpio_regs, __func__); + return 0; +} +postcore_initcall(get_gpio_vbase_early); +#endif +/*---------------------------------------------------------------------------*/ +void get_io_cfg_vbase(void) +{ + struct device_node *np_iocfg = NULL; + + np_iocfg = of_find_compatible_node(NULL, NULL, "mediatek,IOCFG_0"); + if (np_iocfg) { + /* Setup IOCFG addresses */ + gpio_vbase.iocfg_regs = of_iomap(np_iocfg, 0); + GPIOLOG("IOCFG_BASE is gpio_vbase.iocfg_regs=0x%lx\n", + (unsigned long)gpio_vbase.iocfg_regs); + } +} + +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +#ifdef CONFIG_PM +/*---------------------------------------------------------------------------*/ +void mt_gpio_suspend(void) +{ + /* compatible with HAL */ +} + +/*---------------------------------------------------------------------------*/ +void mt_gpio_resume(void) +{ + /* compatible with HAL */ +} + +/*---------------------------------------------------------------------------*/ +#endif /*CONFIG_PM */ +/*---------------------------------------------------------------------------*/ diff --git a/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base.h b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base.h new file mode 100644 index 0000000000000000000000000000000000000000..c12e2100f8f20700df2eaac701c40b4de56cf8d4 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_GPIO_BASE_H_ +#define _MT_GPIO_BASE_H_ + +#include "mt-plat/sync_write.h" +#include + +#define GPIO_WR32(addr, data) mt_reg_sync_writel(data, (unsigned long)addr) +#define GPIO_RD32(addr) __raw_readl(addr) +/* #define GPIO_SET_BITS(BIT,REG) ((*(volatile unsigned long*)(REG)) = (unsigned long)(BIT)) */ +/* #define GPIO_CLR_BITS(BIT,REG) ((*(volatile unsigned long*)(REG)) &= ~((unsigned long)(BIT))) */ +#define GPIO_SW_SET_BITS(BIT, REG) GPIO_WR32(REG, GPIO_RD32(REG) | ((BIT))) +#define GPIO_SET_BITS(BIT, REG) GPIO_WR32(REG, (BIT)) +#define GPIO_CLR_BITS(BIT, REG) GPIO_WR32(REG, GPIO_RD32(REG) & ~((BIT))) + + +#define IOCFG_WR32(addr, data) mt_reg_sync_writel(data, (IOCFG_BASE + (unsigned long)addr)) +#define IOCFG_RD32(addr) __raw_readl((IOCFG_BASE + (unsigned long)addr)) +#define IOCFG_SW_SET_BITS(BIT, REG) IOCFG_WR32(REG, IOCFG_RD32(REG) | ((unsigned long)(BIT))) +#define IOCFG_SET_BITS(BIT, REG) IOCFG_WR32(REG, (unsigned long)(BIT)) +#define IOCFG_CLR_BITS(BIT, REG) IOCFG_WR32(REG, IOCFG_RD32(REG) & ~((unsigned long)(BIT))) + +/*----------------------------------------------------------------------------*/ +typedef struct { /*FIXME: check GPIO spec */ + unsigned int val; + unsigned int set; + unsigned int rst; + unsigned int _align1; +} VAL_REGS; +/*----------------------------------------------------------------------------*/ +typedef struct { + VAL_REGS dir[6]; /*0x0000 ~ 0x005F: 96 bytes */ + u8 rsv00[160]; /*0x0060 ~ 0x00FF: 160 bytes */ + VAL_REGS dout[6]; /*0x0100 ~ 0x015F: 96 bytes */ + u8 rsv01[160]; /*0x0160 ~ 0x01FF: 160 bytes */ + VAL_REGS din[6]; /*0x0200 ~ 0x025F: 96 bytes */ + u8 rsv02[160]; /*0x0260 ~ 0x02FF: 160 bytes */ + VAL_REGS mode[19]; /*0x0300 ~ 0x042F: 384 bytes */ +} GPIO_REGS; +#define MAX_GPIO_PIN MT_GPIO_BASE_MAX + +extern struct device_node *get_gpio_np(void); +extern struct device_node *get_iocfg_np(void); +#endif /* _MT_GPIO_BASE_H_ */ diff --git a/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base_linux.c b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..5180be2c8b4204d922dee42e925d445a34bc5306 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_base_linux.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "mt_gpio_base.h" +#include +/*#include */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const signed int pin_eint_map[MT_GPIO_BASE_MAX] = { + +}; + +static int mtk_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + return mt_set_gpio_mode_base(offset, 0); +} + +static int mtk_get_gpio_direction(struct gpio_chip *chip, unsigned offset) +{ + return 1 - mt_get_gpio_dir_base(offset); +} + +static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return mt_set_gpio_dir_base(offset, 0); +} + +static int mtk_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + /*int status = mt_get_gpio_dir_base(offset);*/ + /*if (status == 0)*/ + return mt_get_gpio_in_base(offset); + /*else if (status == 1)*/ + /* return mt_get_gpio_out_base(offset);*/ + /*return 1;*/ +} + +static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) +{ + return mt_set_gpio_dir_base(offset, 1); +} + +static void mtk_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + mt_set_gpio_out_base(offset, value); +} + +static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned pin) +{ + return mt_gpio_to_irq(pin); + return 0; +} + +static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, unsigned debounce) +{ + mt_eint_set_hw_debounce(offset, debounce); + return 0; +} + +static struct gpio_chip mtk_gpio_chip = { + .label = "mtk-gpio", + .request = mtk_gpio_request, + .get_direction = mtk_get_gpio_direction, + .direction_input = mtk_gpio_direction_input, + .get = mtk_gpio_get, + .direction_output = mtk_gpio_direction_output, + .set = mtk_gpio_set, + .base = MT_GPIO_BASE_START, + .ngpio = MT_GPIO_BASE_MAX, + .to_irq = mtk_gpio_to_irq, + .set_debounce = mtk_gpio_set_debounce, +}; + +static int __init mtk_gpio_init(void) +{ + return gpiochip_add(&mtk_gpio_chip); +} +postcore_initcall(mtk_gpio_init); diff --git a/drivers/misc/mediatek/gpio/mt6755/mt_gpio_debug.c b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..b1d882ee7dae24679fb1644d23a0a3302548c552 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_debug.c @@ -0,0 +1,707 @@ +/****************************************************************************** + * mt_gpio_debug.c - MTKLinux GPIO Device Driver + * + * Copyright 2008-2009 MediaTek Co.,Ltd. + * + * DESCRIPTION: + * This file provid the other drivers GPIO debug functions + * + ******************************************************************************/ + +#include +/*#ifndef CONFIG_OF +#include +#endif*/ +#include "6755_gpio.h" +#include +#include +/*#include */ + +/*----------------------------------------------------------------------------*/ +typedef struct { /*FIXME: check GPIO spec */ + unsigned int no:16; + unsigned int mode:3; + unsigned int pullsel:1; + unsigned int din:1; + unsigned int dout:1; + unsigned int pullen:1; + unsigned int dir:1; +/* unsigned int dinv : 1;*/ + unsigned int ies:1; + unsigned int _align:7; +} GPIO_CFG; + +/* #define MAX_GPIO_REG_BITS 16 */ +/* #define MAX_GPIO_MODE_PER_REG 5 */ +/* #define GPIO_MODE_BITS 3 */ +/****************************************************************************** +*clock out module +*******************************************************************************/ +int mt_set_clock_output(unsigned long num, unsigned long src, unsigned long div) +{ + GPIOERR("GPIO CLKM module not be implement any more!\n"); + return RSUCCESS; +} + +int mt_get_clock_output(unsigned long num, unsigned long *src, unsigned long *div) +{ + GPIOERR("GPIO CLKM module not be implement any more!\n"); + return RSUCCESS; +} + +/*****************************************************************************/ +/* sysfs operation */ +/*****************************************************************************/ + + +/*---------------------------------------------------------------------------- +void mt_gpio_load_ext(GPIOEXT_REGS *regs) +{ + GPIOEXT_REGS *pReg = (GPIOEXT_REGS*)(GPIOEXT_BASE); + int idx; + + if (!regs) + GPIOERR("%s: null pointer\n", __func__); + memset(regs, 0x00, sizeof(*regs)); + for (idx = 0; idx < sizeof(pReg->dir)/sizeof(pReg->dir[0]); idx++) + regs->dir[idx].val = GPIOEXT_RD(&pReg->dir[idx]); + for (idx = 0; idx < sizeof(pReg->pullen)/sizeof(pReg->pullen[0]); idx++) + regs->pullen[idx].val = GPIOEXT_RD(&pReg->pullen[idx]); + for (idx = 0; idx < sizeof(pReg->pullsel)/sizeof(pReg->pullsel[0]); idx++) + regs->pullsel[idx].val =GPIOEXT_RD(&pReg->pullsel[idx]); + for (idx = 0; idx < sizeof(pReg->dinv)/sizeof(pReg->dinv[0]); idx++) + regs->dinv[idx].val =GPIOEXT_RD(&pReg->dinv[idx]); + for (idx = 0; idx < sizeof(pReg->dout)/sizeof(pReg->dout[0]); idx++) + regs->dout[idx].val = GPIOEXT_RD(&pReg->dout[idx]); + for (idx = 0; idx < sizeof(pReg->mode)/sizeof(pReg->mode[0]); idx++) + regs->mode[idx].val = GPIOEXT_RD(&pReg->mode[idx]); + for (idx = 0; idx < sizeof(pReg->din)/sizeof(pReg->din[0]); idx++) + regs->din[idx].val = GPIOEXT_RD(&pReg->din[idx]); +} +EXPORT_SYMBOL(mt_gpio_load_ext); +----------------------------------------------------------------------------*/ +void mt_gpio_load_base(GPIO_REGS *regs) +{ + GPIO_REGS *pReg = (GPIO_REGS *) (GPIO_BASE); + int idx; + + if (!regs) + GPIOERR("%s: null pointer\n", __func__); + memset(regs, 0x00, sizeof(*regs)); + for (idx = 0; idx < sizeof(pReg->dir) / sizeof(pReg->dir[0]); idx++) + regs->dir[idx].val = __raw_readl(&pReg->dir[idx]); + /* for (idx = 0; idx < sizeof(pReg->ies)/sizeof(pReg->ies[0]); idx++) */ + /* regs->ies[idx].val = __raw_readl(&pReg->ies[idx]); */ + /* for (idx = 0; idx < sizeof(pReg->pullen)/sizeof(pReg->pullen[0]); idx++) */ + /* regs->pullen[idx].val = __raw_readl(&pReg->pullen[idx]); */ + /* for (idx = 0; idx < sizeof(pReg->pullsel)/sizeof(pReg->pullsel[0]); idx++) */ + /* regs->pullsel[idx].val =__raw_readl(&pReg->pullsel[idx]); */ + /* for (idx = 0; idx < sizeof(pReg->dinv)/sizeof(pReg->dinv[0]); idx++) */ + /* regs->dinv[idx].val =__raw_readl(&pReg->dinv[idx]); */ + for (idx = 0; idx < sizeof(pReg->dout) / sizeof(pReg->dout[0]); idx++) + regs->dout[idx].val = __raw_readl(&pReg->dout[idx]); + for (idx = 0; idx < sizeof(pReg->mode) / sizeof(pReg->mode[0]); idx++) + regs->mode[idx].val = __raw_readl(&pReg->mode[idx]); + for (idx = 0; idx < sizeof(pReg->din) / sizeof(pReg->din[0]); idx++) + regs->din[idx].val = __raw_readl(&pReg->din[idx]); +} + +/* EXPORT_SYMBOL(mt_gpio_load_base); */ +/*---------------------------------------------------------------------------- +----------------------------------------------------------------------------*/ +void mt_gpio_dump_base(GPIO_REGS *regs) +{ + GPIO_REGS *cur = NULL; + int idx; + + GPIOMSG("%s\n", __func__); + if (regs == NULL) { /*if arg is null, load & dump; otherwise, dump only */ + cur = kzalloc(sizeof(*cur), GFP_KERNEL); + if (cur == NULL) { + GPIOERR("null pointer\n"); + return; + } + regs = cur; + mt_gpio_load_base(regs); + GPIOMSG("dump current: %p\n", regs); + } else { + GPIOMSG("dump %p ...\n", regs); + } + + GPIOMSG("---# dir #-----------------------------------------------------------------\n"); +#ifdef CONFIG_64BIT + GPIOMSG("Offset 0x%lx\n", (void *)(®s->dir[0]) - (void *)regs); +#else + GPIOMSG("Offset 0x%04X\n", (void *)(®s->dir[0]) - (void *)regs); +#endif + for (idx = 0; idx < sizeof(regs->dir) / sizeof(regs->dir[0]); idx++) { + GPIOMSG("0x%04X ", regs->dir[idx].val); + if (7 == (idx % 8)) + GPIOMSG("\n"); + } + /* GPIOMSG("\n---# ies #-----------------------------------------------------------------\n"); */ + /* GPIOMSG("Offset 0x%04X\n",(void *)(®s->ies[0])-(void *)regs); */ + /* for (idx = 0; idx < sizeof(regs->ies)/sizeof(regs->ies[0]); idx++) { */ + /* GPIOMSG("0x%04X ", regs->ies[idx].val); */ + /* if (7 == (idx % 8)) GPIOMSG("\n"); */ + /* } */ + /* GPIOMSG("\n---# pullen #--------------------------------------------------------------\n"); */ + /* GPIOMSG("Offset 0x%04X\n",(void *)(®s->pullen[0])-(void *)regs); */ + /* for (idx = 0; idx < sizeof(regs->pullen)/sizeof(regs->pullen[0]); idx++) { */ + /* GPIOMSG("0x%04X ", regs->pullen[idx].val); */ + /* if (7 == (idx % 8)) GPIOMSG("\n"); */ + /* } */ + /* GPIOMSG("\n---# pullsel #-------------------------------------------------------------\n"); */ + /* GPIOMSG("Offset 0x%04X\n",(void *)(®s->pullsel[0])-(void *)regs); */ + /* for (idx = 0; idx < sizeof(regs->pullsel)/sizeof(regs->pullsel[0]); idx++) { */ + /* GPIOMSG("0x%04X ", regs->pullsel[idx].val); */ + /* if (7 == (idx % 8)) GPIOMSG("\n"); */ + /* } */ + /* GPIOMSG("\n---# dinv #----------------------------------------------------------------\n"); */ + /* GPIOMSG("Offset 0x%04X\n",(void *)(®s->dinv[0])-(void *)regs); */ + /* for (idx = 0; idx < sizeof(regs->dinv)/sizeof(regs->dinv[0]); idx++) { */ + /* GPIOMSG("0x%04X ", regs->dinv[idx].val); */ + /* if (7 == (idx % 8)) GPIOMSG("\n"); */ + /* } */ + GPIOMSG("\n---# dout #----------------------------------------------------------------\n"); +#ifdef CONFIG_64BIT + GPIOMSG("Offset 0x%lx\n", (void *)(®s->dout[0]) - (void *)regs); +#else + GPIOMSG("Offset 0x%04X\n", (void *)(®s->dout[0]) - (void *)regs); +#endif + for (idx = 0; idx < sizeof(regs->dout) / sizeof(regs->dout[0]); idx++) { + GPIOMSG("0x%04X ", regs->dout[idx].val); + if (7 == (idx % 8)) + GPIOMSG("\n"); + } + GPIOMSG("\n---# din #----------------------------------------------------------------\n"); +#ifdef CONFIG_64BIT + GPIOMSG("Offset 0x%lx\n", (void *)(®s->din[0]) - (void *)regs); +#else + GPIOMSG("Offset 0x%04X\n", (void *)(®s->din[0]) - (void *)regs); +#endif + for (idx = 0; idx < sizeof(regs->din) / sizeof(regs->din[0]); idx++) { + GPIOMSG("0x%04X ", regs->din[idx].val); + if (7 == (idx % 8)) + GPIOMSG("\n"); + } + GPIOMSG("\n---# mode #----------------------------------------------------------------\n"); +#ifdef CONFIG_64BIT + GPIOMSG("Offset 0x%lx\n", (void *)(®s->mode[0]) - (void *)regs); +#else + GPIOMSG("Offset 0x%04X\n", (void *)(®s->mode[0]) - (void *)regs); +#endif + for (idx = 0; idx < sizeof(regs->mode) / sizeof(regs->mode[0]); idx++) { + GPIOMSG("0x%04X ", regs->mode[idx].val); + if (7 == (idx % 8)) + GPIOMSG("\n"); + } + GPIOMSG("\n---------------------------------------------------------------------------\n"); + + + if (cur != NULL) + kfree(cur); + +} + +/*----------------------------------------------------------------------------*/ + +void mt_gpio_dump(void) +{ + mt_gpio_dump_base(NULL); + /* mt_gpio_dump_ext(NULL); */ +} + +/*----------------------------------------------------------------------------*/ +void gpio_dump_regs(void) +{ + int idx = 0; + + GPIOMSG("PIN: [MODE] [PULL_SEL] [DIN] [DOUT] [PULL EN] [DIR] [IES]\n"); + for (idx = MT_GPIO_BASE_START; idx < MT_GPIO_BASE_MAX; idx++) { + pr_debug("idx = %3d: %d %d %d %d %d %d %d\n", + idx, mt_get_gpio_mode_base(idx), mt_get_gpio_pull_select_base(idx), + mt_get_gpio_in_base(idx), mt_get_gpio_out_base(idx), + mt_get_gpio_pull_enable_base(idx), mt_get_gpio_dir_base(idx), + mt_get_gpio_ies_base(idx)); + } +} + +/* EXPORT_SYMBOL(gpio_dump_regs); */ +/*----------------------------------------------------------------------------*/ +/* +static ssize_t mt_gpio_dump_regs(char *buf, ssize_t bufLen) +{ + int idx = 0, len = 0; + char tmp[]="PIN: [MODE] [PULL_SEL] [DIN] [DOUT] [PULL EN] [DIR] [INV] [IES]\n"; + len += snprintf(buf+len, bufLen-len, "%s",tmp); + for (idx = 0; idx < MT_GPIO_MAX_PIN; idx++) { + len += snprintf(buf+len, bufLen-len, "%3d:%d%d%d%d%d%d%d%d\n", + idx,mt_get_gpio_mode(idx), mt_get_gpio_pull_select(idx), mt_get_gpio_in(idx),mt_get_gpio_out(idx), + mt_get_gpio_pull_enable(idx),mt_get_gpio_dir(idx),mt_get_gpio_inversion(idx),mt_get_gpio_ies(idx)); + } + return len; +} +*/ +/*---------------------------------------------------------------------------*/ +static void mt_gpio_read_pin_base(GPIO_CFG *cfg, int method) +{ + if (method == 0) { + GPIO_REGS *cur = (GPIO_REGS *) GPIO_BASE; + u32 mask = (1L << GPIO_MODE_BITS) - 1; + int num, bit; + + num = cfg->no / MAX_GPIO_REG_BITS; + bit = cfg->no % MAX_GPIO_REG_BITS; + if (cfg->no < MT_GPIO_BASE_MAX) { + /* cfg->pullsel= (cur->pullsel[num].val & (1L << bit)) ? (1) : (0); */ + cfg->din = (cur->din[num].val & (1L << bit)) ? (1) : (0); + cfg->dout = (cur->dout[num].val & (1L << bit)) ? (1) : (0); + /* cfg->pullen = (cur->pullen[num].val & (1L << bit)) ? (1) : (0); */ + cfg->dir = (cur->dir[num].val & (1L << bit)) ? (1) : (0); + /* cfg->dinv = (cur->dinv[num].val & (1L << bit)) ? (1) : (0); */ + num = cfg->no / MAX_GPIO_MODE_PER_REG; + bit = cfg->no % MAX_GPIO_MODE_PER_REG; + cfg->mode = (cur->mode[num].val >> (GPIO_MODE_BITS * bit)) & mask; + } + } else if (method == 1) { + /* cfg->pullsel= mt_get_gpio_pull_select(cfg->no); */ + cfg->din = mt_get_gpio_in(cfg->no); + cfg->dout = mt_get_gpio_out(cfg->no); + /* cfg->pullen = mt_get_gpio_pull_enable(cfg->no); */ + cfg->dir = mt_get_gpio_dir(cfg->no); + /* cfg->dinv = mt_get_gpio_inversion(cfg->no); */ + /* cfg->ies = mt_get_gpio_ies(cfg->no); */ + cfg->mode = mt_get_gpio_mode(cfg->no); + } +} + +/* +static void mt_gpio_read_pin_ext(GPIO_CFG* cfg, int method) +{ + if (method == 0) { + GPIOEXT_REGS *cur = (GPIOEXT_REGS*)GPIOEXT_BASE; + u32 mask = (1L << GPIO_MODE_BITS) - 1; + int num, bit; + num = cfg->no / MAX_GPIO_REG_BITS; + bit = cfg->no % MAX_GPIO_REG_BITS; + if(cfg->no >= MT_GPIO_EXT_START){ + // + cfg->pullsel= (cur->pullsel[num].val & (1L << bit)) ? (1) : (0); + cfg->din = (cur->din[num].val & (1L << bit)) ? (1) : (0); + cfg->dout = (cur->dout[num].val & (1L << bit)) ? (1) : (0); + cfg->pullen = (cur->pullen[num].val & (1L << bit)) ? (1) : (0); + cfg->dir = (cur->dir[num].val & (1L << bit)) ? (1) : (0); + cfg->dinv = (cur->dinv[num].val & (1L << bit)) ? (1) : (0); + num = cfg->no / MAX_GPIO_MODE_PER_REG; + bit = cfg->no % MAX_GPIO_MODE_PER_REG; + cfg->mode = (cur->mode[num].val >> (GPIO_MODE_BITS*bit)) & mask; + + } + } else if (method == 1) { + cfg->pullsel= mt_get_gpio_pull_select(cfg->no); + cfg->din = mt_get_gpio_in(cfg->no); + cfg->dout = mt_get_gpio_out(cfg->no); + cfg->pullen = mt_get_gpio_pull_enable(cfg->no); + cfg->dir = mt_get_gpio_dir(cfg->no); + cfg->dinv = mt_get_gpio_inversion(cfg->no); + cfg->mode = mt_get_gpio_mode(cfg->no); + } +}*/ + +static ssize_t mt_gpio_dump_addr_base(void) +{ + int idx; + GPIO_REGS *reg = (GPIO_REGS *) GPIO_BASE; + + GPIOMSG("# direction\n"); + for (idx = 0; idx < sizeof(reg->dir) / sizeof(reg->dir[0]); idx++) + GPIOMSG("val[%2d] %p\nset[%2d] %p\nrst[%2d] %p\n", idx, ®->dir[idx].val, idx, + ®->dir[idx].set, idx, ®->dir[idx].rst); + /* GPIOMSG("# ies\n"); */ + /* for (idx = 0; idx < sizeof(reg->ies)/sizeof(reg->ies[0]); idx++) */ + /* GPIOMSG("val[%2d] %p\nset[%2d] %p\nrst[%2d] %p\n", idx, ®->ies[idx].val, +idx, ®->ies[idx].set, idx, ®->ies[idx].rst); */ + /* GPIOMSG("# pull enable\n"); */ + /* for (idx = 0; idx < sizeof(reg->pullen)/sizeof(reg->pullen[0]); idx++) */ + /* GPIOMSG("val[%2d] %p\nset[%2d] %p\nrst[%2d] %p\n", idx, ®->pullen[idx].val, +idx, ®->pullen[idx].set, idx, ®->pullen[idx].rst); */ + /* GPIOMSG("# pull select\n"); */ + /* for (idx = 0; idx < sizeof(reg->pullsel)/sizeof(reg->pullsel[0]); idx++) */ + /* GPIOMSG("val[%2d] %p\nset[%2d] %p\nrst[%2d] %p\n", idx, ®->pullsel[idx].val, +idx, ®->pullsel[idx].set, idx, ®->pullsel[idx].rst); */ + /* GPIOMSG("# data inversion\n"); */ + /* for (idx = 0; idx < sizeof(reg->dinv)/sizeof(reg->dinv[0]); idx++) */ + /* GPIOMSG("val[%2d] %p\nset[%2d] %p\nrst[%2d] %p\n", idx, ®->dinv[idx].val, +idx, ®->dinv[idx].set, idx, ®->dinv[idx].rst); */ + GPIOMSG("# data output\n"); + for (idx = 0; idx < sizeof(reg->dout) / sizeof(reg->dout[0]); idx++) + GPIOMSG("val[%2d] %p\nset[%2d] %p\nrst[%2d] %p\n", idx, ®->dout[idx].val, idx, + ®->dout[idx].set, idx, ®->dout[idx].rst); + GPIOMSG("# data input\n"); + for (idx = 0; idx < sizeof(reg->din) / sizeof(reg->din[0]); idx++) + GPIOMSG("val[%2d] %p\n", idx, ®->din[idx].val); + GPIOMSG("# mode\n"); + for (idx = 0; idx < sizeof(reg->mode) / sizeof(reg->mode[0]); idx++) + GPIOMSG("val[%2d] %p\nset[%2d] %p\nrst[%2d] %p\n", idx, ®->mode[idx].val, idx, + ®->mode[idx].set, idx, ®->mode[idx].rst); + return 0; +} + +/*--------------------------------------------------------------------------- +static void mt_gpio_compare_ext(void) +{ + int idx; + GPIOEXT_REGS *reg = (GPIOEXT_REGS*)GPIOEXT_BASE; + GPIOEXT_REGS *cur = kzalloc(sizeof(*cur), GFP_KERNEL); + + if (!cur) + return; + + mt_gpio_load_ext(cur); + for (idx = 0; idx < sizeof(reg->dir)/sizeof(reg->dir[0]); idx++) + if (reg->dir[idx].val != cur->dir[idx].val) + GPIOERR("GPIOEXT mismatch dir[%2d]: %x <> %x\n", idx, reg->dir[idx].val, cur->dir[idx].val); + for (idx = 0; idx < sizeof(reg->pullen)/sizeof(reg->pullen[0]); idx++) + if (reg->pullen[idx].val != cur->pullen[idx].val) + GPIOERR("GPIOEXT mismatch pullen[%2d]: %x <> %x\n", idx, reg->pullen[idx].val, cur->pullen[idx].val); + for (idx = 0; idx < sizeof(reg->pullsel)/sizeof(reg->pullsel[0]); idx++) + if (reg->pullsel[idx].val != cur->pullsel[idx].val) + GPIOERR("GPIOEXT mismatch pullsel[%2d]: %x <> %x\n", idx, reg->pullsel[idx].val, cur->pullsel[idx].val); + for (idx = 0; idx < sizeof(reg->dinv)/sizeof(reg->dinv[0]); idx++) + if (reg->dinv[idx].val != cur->dinv[idx].val) + GPIOERR("GPIOEXT mismatch dinv[%2d]: %x <> %x\n", idx, reg->dinv[idx].val, cur->dinv[idx].val); + for (idx = 0; idx < sizeof(reg->dout)/sizeof(reg->dout[0]); idx++) + if (reg->dout[idx].val != cur->dout[idx].val) + GPIOERR("GPIOEXT mismatch dout[%2d]: %x <> %x\n", idx, reg->dout[idx].val, cur->dout[idx].val); + for (idx = 0; idx < sizeof(reg->din)/sizeof(reg->din[0]); idx++) + if (reg->din[idx].val != cur->din[idx].val) + GPIOERR("GPIOEXT mismatch din[%2d]: %x <> %x\n", idx, reg->din[idx].val, cur->din[idx].val); + for (idx = 0; idx < sizeof(reg->mode)/sizeof(reg->mode[0]); idx++) + if (reg->mode[idx].val != cur->mode[idx].val) + GPIOERR("GPIOEXT mismatch mode[%2d]: %x <> %x\n", idx, reg->mode[idx].val, cur->mode[idx].val); + + kfree(cur); + return; +}*/ +static ssize_t mt_gpio_compare_base(void) +{ + int idx; + GPIO_REGS *reg = (GPIO_REGS *) GPIO_BASE; + GPIO_REGS *cur = kzalloc(sizeof(*cur), GFP_KERNEL); + + if (!cur) + return 0; + + mt_gpio_load_base(cur); + for (idx = 0; idx < sizeof(reg->dir) / sizeof(reg->dir[0]); idx++) + if (reg->dir[idx].val != cur->dir[idx].val) + GPIOERR("mismatch dir[%2d]: %x <> %x\n", idx, reg->dir[idx].val, + cur->dir[idx].val); + /* for (idx = 0; idx < sizeof(reg->pullen)/sizeof(reg->pullen[0]); idx++) */ + /* if (reg->pullen[idx].val != cur->pullen[idx].val) */ + /* GPIOERR("mismatch pullen[%2d]: %x <> %x\n", idx, reg->pullen[idx].val, cur->pullen[idx].val); */ + /* for (idx = 0; idx < sizeof(reg->pullsel)/sizeof(reg->pullsel[0]); idx++) */ + /* if (reg->pullsel[idx].val != cur->pullsel[idx].val) */ + /* GPIOERR("mismatch pullsel[%2d]: %x <> %x\n", idx, reg->pullsel[idx].val, cur->pullsel[idx].val); */ + /* for (idx = 0; idx < sizeof(reg->dinv)/sizeof(reg->dinv[0]); idx++) */ + /* if (reg->dinv[idx].val != cur->dinv[idx].val) */ + /* GPIOERR("mismatch dinv[%2d]: %x <> %x\n", idx, reg->dinv[idx].val, cur->dinv[idx].val); */ + for (idx = 0; idx < sizeof(reg->dout) / sizeof(reg->dout[0]); idx++) + if (reg->dout[idx].val != cur->dout[idx].val) + GPIOERR("mismatch dout[%2d]: %x <> %x\n", idx, reg->dout[idx].val, + cur->dout[idx].val); + for (idx = 0; idx < sizeof(reg->din) / sizeof(reg->din[0]); idx++) + if (reg->din[idx].val != cur->din[idx].val) + GPIOERR("mismatch din[%2d]: %x <> %x\n", idx, reg->din[idx].val, + cur->din[idx].val); + for (idx = 0; idx < sizeof(reg->mode) / sizeof(reg->mode[0]); idx++) + if (reg->mode[idx].val != cur->mode[idx].val) + GPIOERR("mismatch mode[%2d]: %x <> %x\n", idx, reg->mode[idx].val, + cur->mode[idx].val); + + kfree(cur); + return 0; +} + +static ssize_t mt_gpio_dump_regs(char *buf, ssize_t bufLen) +{ + int idx = 0, len = 0; +#ifdef CONFIG_MTK_FPGA + char tmp[] = "PIN: [DIN] [DOUT] [DIR]\n"; + + len += snprintf(buf + len, bufLen - len, "%s", tmp); + for (idx = MT_GPIO_BASE_START; idx < MT_GPIO_BASE_MAX; idx++) { + len += snprintf(buf + len, bufLen - len, "%3d:%d%d%d\n", + idx, mt_get_gpio_in_base(idx), mt_get_gpio_out_base(idx), + mt_get_gpio_dir_base(idx)); + } +#else + /*char tmp[]="PIN: [MODE] [PULL_SEL] [DIN] [DOUT] [PULL EN] [DIR] [INV] [IES]\n"; */ + char tmp[] = "PIN: [MODE] [PULL_SEL] [DIN] [DOUT] [PULL EN] [DIR] [IES] [SMT]\n"; + + len += snprintf(buf + len, bufLen - len, "%s", tmp); + for (idx = MT_GPIO_BASE_START; idx < MT_GPIO_BASE_MAX; idx++) { + len += snprintf(buf + len, bufLen - len, "%3d:%d%d%d%d%d%d%d%d\n", + idx, mt_get_gpio_mode_base(idx), mt_get_gpio_pull_select_base(idx), + mt_get_gpio_in_base(idx), mt_get_gpio_out_base(idx), + mt_get_gpio_pull_enable_base(idx), mt_get_gpio_dir_base(idx), + mt_get_gpio_ies_base(idx), mt_get_gpio_smt_base(idx)); + /* printk("%3d:%d%d%d%d%d%d%d%d\n",idx, */ + /* mt_get_gpio_mode_base(idx), mt_get_gpio_pull_select_base(idx), +mt_get_gpio_in_base(idx),mt_get_gpio_out_base(idx), */ + /* mt_get_gpio_pull_enable_base(idx),mt_get_gpio_dir_base(idx), +mt_get_gpio_inversion_base(idx),mt_get_gpio_ies_base(idx)); */ + + } +#endif +/* len += snprintf(buf+len, bufLen-len, "%s","EXT GPIO\n"); + for (idx = MT_GPIO_EXT_START; idx < MT_GPIO_EXT_MAX; idx++) { + len += snprintf(buf+len, bufLen-len, "%3d:%d%d%d%d%d%d%d%d\n", + idx,mt_get_gpio_mode_ext(idx), mt_get_gpio_pull_select_ext(idx), +mt_get_gpio_in_ext(idx),mt_get_gpio_out_ext(idx), + mt_get_gpio_pull_enable_ext(idx),mt_get_gpio_dir_ext(idx), +mt_get_gpio_inversion_ext(idx),mt_get_gpio_ies_ext(idx)); + }*/ + return len; +} + +/*---------------------------------------------------------------------------*/ +ssize_t mt_gpio_show_pin(struct device *dev, struct device_attribute *attr, char *buf) +{ + return mt_gpio_dump_regs(buf, PAGE_SIZE); +} + +/****************************************************************************** +*MD convert gpio-name to gpio-number +*******************************************************************************/ +struct mt_gpio_modem_info { + char name[40]; + int num; +}; + +static struct mt_gpio_modem_info mt_gpio_info[] = { + {"GPIO_MD_TEST", 800}, +#ifdef GPIO_AST_CS_PIN + {"GPIO_AST_HIF_CS", GPIO_AST_CS_PIN}, +#endif +#ifdef GPIO_AST_CS_PIN_NCE + {"GPIO_AST_HIF_CS_ID", GPIO_AST_CS_PIN_NCE}, +#endif +#ifdef GPIO_AST_RST_PIN + {"GPIO_AST_Reset", GPIO_AST_RST_PIN}, +#endif +#ifdef GPIO_AST_CLK32K_PIN + {"GPIO_AST_CLK_32K", GPIO_AST_CLK32K_PIN}, +#endif +#ifdef GPIO_AST_CLK32K_PIN_CLK + {"GPIO_AST_CLK_32K_CLKM", GPIO_AST_CLK32K_PIN_CLK}, +#endif +#ifdef GPIO_AST_WAKEUP_PIN + {"GPIO_AST_Wakeup", GPIO_AST_WAKEUP_PIN}, +#endif +#ifdef GPIO_AST_INTR_PIN + {"GPIO_AST_INT", GPIO_AST_INTR_PIN}, +#endif +#ifdef GPIO_AST_WAKEUP_INTR_PIN + {"GPIO_AST_WAKEUP_INT", GPIO_AST_WAKEUP_INTR_PIN}, +#endif +#ifdef GPIO_AST_AFC_SWITCH_PIN + {"GPIO_AST_AFC_Switch", GPIO_AST_AFC_SWITCH_PIN}, +#endif +#ifdef GPIO_FDD_BAND_SUPPORT_DETECT_1ST_PIN + {"GPIO_FDD_Band_Support_Detection_1", GPIO_FDD_BAND_SUPPORT_DETECT_1ST_PIN}, +#endif +#ifdef GPIO_FDD_BAND_SUPPORT_DETECT_2ND_PIN + {"GPIO_FDD_Band_Support_Detection_2", GPIO_FDD_BAND_SUPPORT_DETECT_2ND_PIN}, +#endif +#ifdef GPIO_FDD_BAND_SUPPORT_DETECT_3RD_PIN + {"GPIO_FDD_Band_Support_Detection_3", GPIO_FDD_BAND_SUPPORT_DETECT_3RD_PIN}, +#endif +#ifdef GPIO_FDD_BAND_SUPPORT_DETECT_4TH_PIN + {"GPIO_FDD_Band_Support_Detection_4", GPIO_FDD_BAND_SUPPORT_DETECT_4TH_PIN}, +#endif +#ifdef GPIO_FDD_BAND_SUPPORT_DETECT_5TH_PIN + {"GPIO_FDD_Band_Support_Detection_5", GPIO_FDD_BAND_SUPPORT_DETECT_5TH_PIN}, +#endif +#ifdef GPIO_FDD_BAND_SUPPORT_DETECT_6TH_PIN + {"GPIO_FDD_Band_Support_Detection_6", GPIO_FDD_BAND_SUPPORT_DETECT_6TH_PIN}, +#endif +#ifdef GPIO_SIM_SWITCH_CLK_PIN + {"GPIO_SIM_SWITCH_CLK", GPIO_SIM_SWITCH_CLK_PIN}, +#endif +#ifdef GPIO_SIM_SWITCH_DAT_PIN + {"GPIO_SIM_SWITCH_DAT", GPIO_SIM_SWITCH_DAT_PIN}, +#endif +#ifdef GPIO_SIM1_HOT_PLUG + {"GPIO_SIM1_INT", GPIO_SIM1_HOT_PLUG}, +#endif +#ifdef GPIO_SIM2_HOT_PLUG + {"GPIO_SIM2_INT", GPIO_SIM2_HOT_PLUG}, +#endif +/*if you have new GPIO pin add bellow*/ + +}; + +int mt_get_md_gpio(char *gpio_name, int len) +{ + unsigned int i; + unsigned long number; + + for (i = 0; i < ARRAY_SIZE(mt_gpio_info); i++) { + if (!strncmp(gpio_name, mt_gpio_info[i].name, len)) { + number = mt_gpio_info[i].num; + GPIOMSG("Modern get number=%d, name:%s\n", mt_gpio_info[i].num, gpio_name); + mt_gpio_pin_decrypt(&number); + return number; + } + } + GPIOERR("Modem gpio name can't match!!!\n"); + return -1; +} + +void mt_get_md_gpio_debug(char *str) +{ + if (strcmp(str, "ALL") == 0) { + int i; + + for (i = 0; i < ARRAY_SIZE(mt_gpio_info); i++) + GPIOMSG("GPIO number=%d,%s\n", mt_gpio_info[i].num, mt_gpio_info[i].name); + + } else { + GPIOMSG("GPIO number=%d,%s\n", mt_get_md_gpio(str, strlen(str)), str); + } + +} +/*---------------------------------------------------------------------------*/ +ssize_t mt_gpio_store_pin(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int pin; +#ifdef MTK_MT6306_SUPPORT + int group, on; +#endif + int mode, pullsel, dout, pullen, dir, ies, smt; + u32 num, src, div; + /*char md_str[128] = "GPIO_MD_TEST";*/ + /* struct mt_gpio_obj *obj = (struct mt_gpio_obj*)dev_get_drvdata(dev); */ + if (!strncmp(buf, "-h", 2)) { + GPIOMSG("cat pin #show all pin setting\n"); + GPIOMSG("echo -wmode num x > pin #num:pin,x:the mode 0~7\n"); + GPIOMSG("echo -wpsel num x > pin #x: 1,pull-up; 0,pull-down\n"); + GPIOMSG("echo -wdout num x > pin #x: 1,high; 0, low\n"); + GPIOMSG("echo -wpen num x > pin #x: 1,pull enable; 0 pull disable\n"); + GPIOMSG("echo -wies num x > pin #x: 1,ies enable; 0 ies disable\n"); + GPIOMSG("echo -wdir num x > pin #x: 1, output; 0, input\n"); + /*GPIOMSG("echo -wdinv num x > pin #x: 1, inversion enable; 0, disable\n"); */ + GPIOMSG("echo -w=num x x x x x x > pin #set all property one time\n"); + GPIOMSG("PIN: [MODE] [PSEL] [DIN] [DOUT] [PEN] [DIR] [IES]\n"); + } else if (!strncmp(buf, "-r0", 3) && (1 == sscanf(buf + 3, "%d", &pin))) { + GPIO_CFG cfg = {.no = pin }; + /*if pmic */ + mt_gpio_read_pin_base(&cfg, 0); + GPIOMSG("%3d: %d %d %d %d %d %d\n", cfg.no, cfg.mode, cfg.pullsel, + cfg.din, cfg.dout, cfg.pullen, cfg.dir); + } else if (!strncmp(buf, "-r1", 3) && (1 == sscanf(buf + 3, "%d", &pin))) { + GPIO_CFG cfg = {.no = pin }; + + mt_gpio_read_pin_base(&cfg, 1); + GPIOMSG("%3d: %d %d %d %d %d %d %d\n", cfg.no, cfg.mode, cfg.pullsel, + cfg.din, cfg.dout, cfg.pullen, cfg.dir, cfg.ies); + } else if (!strncmp(buf, "-w", 2)) { + buf += 2; + if (!strncmp(buf, "mode", 4) && (2 == sscanf(buf + 4, "%d %d", &pin, &mode))) + GPIOMSG("set mode(%3d, %d)=%d\n", pin, mode, mt_set_gpio_mode(pin, mode)); + else if (!strncmp(buf, "psel", 4) + && (2 == sscanf(buf + 4, "%d %d", &pin, &pullsel))) + GPIOMSG("set psel(%3d, %d)=%d\n", pin, pullsel, + mt_set_gpio_pull_select(pin, pullsel)); + else if (!strncmp(buf, "dout", 4) && (2 == sscanf(buf + 4, "%d %d", &pin, &dout))) + GPIOMSG("set dout(%3d, %d)=%d\n", pin, dout, mt_set_gpio_out(pin, dout)); + else if (!strncmp(buf, "pen", 3) && (2 == sscanf(buf + 3, "%d %d", &pin, &pullen))) + GPIOMSG("set pen (%3d, %d)=%d\n", pin, pullen, + mt_set_gpio_pull_enable(pin, pullen)); + else if (!strncmp(buf, "ies", 3) && (2 == sscanf(buf + 3, "%d %d", &pin, &ies))) + GPIOMSG("set ies (%3d, %d)=%d\n", pin, ies, mt_set_gpio_ies(pin, ies)); + else if (!strncmp(buf, "dir", 3) && (2 == sscanf(buf + 3, "%d %d", &pin, &dir))) + GPIOMSG("set dir (%3d, %d)=%d\n", pin, dir, mt_set_gpio_dir(pin, dir)); + /* else if (!strncmp(buf, "dinv", 4) && (2 == sscanf(buf+4, "%d %d", &pin, &dinv))) */ + /* GPIOMSG("set dinv(%3d, %d)=%d\n", pin, dinv, mt_set_gpio_inversion(pin, dinv)); */ +#ifdef CONFIG_MTK_FPGA + else if (3 == sscanf(buf, "=%d:%d %d", &pin, &dout, &dir)) { + GPIOMSG("set dout(%3d, %d)=%d\n", pin, dout, mt_set_gpio_out(pin, dout)); + GPIOMSG("set dir (%3d, %d)=%d\n", pin, dir, mt_set_gpio_dir(pin, dir)); +#else + else if (8 == sscanf(buf, "=%d:%d %d %d %d %d %d %d", &pin, &mode, &pullsel, &dout, + &pullen, &dir, &ies, &smt)) { + GPIOMSG("set mode(%3d, %d)=%d\n", pin, mode, mt_set_gpio_mode(pin, mode)); + GPIOMSG("set psel(%3d, %d)=%d\n", pin, pullsel, + mt_set_gpio_pull_select(pin, pullsel)); + GPIOMSG("set dout(%3d, %d)=%d\n", pin, dout, mt_set_gpio_out(pin, dout)); + GPIOMSG("set pen (%3d, %d)=%d\n", pin, pullen, + mt_set_gpio_pull_enable(pin, pullen)); + GPIOMSG("set dir (%3d, %d)=%d\n", pin, dir, mt_set_gpio_dir(pin, dir)); + /* GPIOMSG("set dinv(%3d, %d)=%d\n", pin, dinv, mt_set_gpio_inversion(pin, dinv)); */ + GPIOMSG("set ies (%3d, %d)=%d\n", pin, ies, mt_set_gpio_ies(pin, ies)); + GPIOMSG("set smt (%3d, %d)=%d\n", pin, smt, mt_set_gpio_smt(pin, smt)); +#endif + } else + GPIOMSG("invalid format: '%s'", buf); +#ifdef MTK_MT6306_SUPPORT + } else if (!strncmp(buf, "ww", 2)) { + /* MT6306 GPIO */ + buf += 2; + if (3 == sscanf(buf, "=%d:%d %d", &pin, &dout, &dir)) { + GPIOMSG("[MT6306] set dout(%3d, %d)=%d\n", pin, dout, + mt6306_set_gpio_out(pin, dout)); + GPIOMSG("[MT6306] set dir (%3d, %d)=%d\n", pin, dir, + mt6306_set_gpio_dir(pin, dir)); + } else + GPIOMSG("invalid format: '%s'", buf); + } else if (!strncmp(buf, "wy", 2)) { + /* MT6306 GPIO */ + buf += 2; + if (2 == sscanf(buf, "=%d:%d", &group, &on)) { + GPIOMSG("[MT6306] set pin group vccen (%3d, %d)=%d\n", group, on, + mt6306_set_GPIO_pin_group_power(group, on)); + GPIOMSG("[MT6306] set pin group vccen (%3d, %d)=%d\n", group, on, + mt6306_set_GPIO_pin_group_power(group, on)); + } else + GPIOMSG("invalid format: '%s'", buf); +#endif + } else if (!strncmp(buf, "-t", 2)) { + /*mt_gpio_self_test();*/ + } else if (!strncmp(buf, "-c", 2)) { + mt_gpio_compare_base(); + /* mt_gpio_compare_ext(); */ + } else if (!strncmp(buf, "-da", 3)) { + mt_gpio_dump_addr_base(); + /* mt_gpio_dump_addr_ext(); */ + } else if (!strncmp(buf, "-dp", 3)) { + gpio_dump_regs(); + } else if (!strncmp(buf, "-d", 2)) { + mt_gpio_dump(); + } else if (!strncmp(buf, "tt", 2)) { + /* GPIOMSG("gpio reg test for next chip!\n"); */ + /* mt_reg_test(); */ + } else if (!strncmp(buf, "-md", 3)) { + /* buf +=3; */ + /* sscanf(buf,"%s",md_str); */ + /* mt_get_md_gpio_debug(md_str); */ + } else if (!strncmp(buf, "-k", 2)) { + buf += 2; + if (!strncmp(buf, "s", 1) && (3 == sscanf(buf + 1, "%d %d %d", &num, &src, &div))) + GPIOMSG("set num(%d, %d, %d)=%d\n", num, src, div, + mt_set_clock_output(num, src, div)); + } else if (!strncmp(buf, "g", 1) && (1 == sscanf(buf + 1, "%d", &num))) { + /* ret = mt_get_clock_output(num, &src,&div); */ + /* GPIOMSG("get num(%ld, %ld, %ld)=%d\n", num, src, div,ret); */ + } else { + GPIOMSG("invalid format: '%s'", buf); + } + return count; +} + + + + diff --git a/drivers/misc/mediatek/gpio/mt6755/mt_gpio_ext.c b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_ext.c new file mode 100644 index 0000000000000000000000000000000000000000..d70bb5d541a4637f6ba3676b7f35d209e0443666 --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_ext.c @@ -0,0 +1,141 @@ +/****************************************************************************** + * mt_gpio_ext.c - MTKLinux GPIO Device Driver + * + * Copyright 2008-2009 MediaTek Co.,Ltd. + * + * DESCRIPTION: + * This file provid the other drivers GPIO debug functions + * + ******************************************************************************/ + +/*#include +#include */ +#include +#include +#include "mt_gpio_ext.h" + +/*#define MAX_GPIO_REG_BITS 16*/ +/*#define MAX_GPIO_MODE_PER_REG 5*/ +/*#define GPIO_MODE_BITS 3*/ +#define GPIOEXT_BASE (0x0) /*PMIC GPIO base. */ + +/*static GPIOEXT_REGS *gpioext_reg = (GPIOEXT_REGS*)(GPIOEXT_BASE);*/ +/*set extend GPIO*/ +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_dir_ext(unsigned long pin, unsigned long dir) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_dir_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_pull_enable_ext(unsigned long pin, unsigned long enable) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_pull_enable_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_smt_ext(unsigned long pin, unsigned long enable) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_smt_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_ies_ext(unsigned long pin, unsigned long enable) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_ies_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_pull_select_ext(unsigned long pin, unsigned long select) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_pull_select_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_inversion_ext(unsigned long pin, unsigned long enable) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_inversion_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_out_ext(unsigned long pin, unsigned long output) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_out_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_in_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_set_gpio_mode_ext(unsigned long pin, unsigned long mode) +{ + dump_stack(); + return -1; +} + +/*---------------------------------------------------------------------------*/ +int mt_get_gpio_mode_ext(unsigned long pin) +{ + dump_stack(); + return -1; +} diff --git a/drivers/misc/mediatek/gpio/mt6755/mt_gpio_ext.h b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_ext.h new file mode 100644 index 0000000000000000000000000000000000000000..03cc3802b0c989ac946485f5d8c1c1e30a099c3e --- /dev/null +++ b/drivers/misc/mediatek/gpio/mt6755/mt_gpio_ext.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_GPIO_EXT_H_ +#define _MT_GPIO_EXT_H_ + +#include + +#define GPIOEXT_WR(addr, data) pwrap_write((unsigned long)addr, data) +#define GPIOEXT_RD(addr) ({ \ + unsigned long ext_data; \ + (pwrap_read((unsigned long)addr, &ext_data) != 0) ? -1:ext_data; }) +#define GPIOEXT_SET_BITS(BIT, REG) (GPIOEXT_WR(REG, (unsigned long)(BIT))) +#define GPIOEXT_CLR_BITS(BIT, REG) ({ \ + unsigned long ext_data; \ + int ret; \ + ret = GPIOEXT_RD(REG);\ + ext_data = ret;\ + (ret < 0) ? -1:(GPIOEXT_WR(REG, ext_data & ~((unsigned long)(BIT))))}) + +/*----------------------------------------------------------------------------*/ +typedef struct { + unsigned short val; + unsigned short set; + unsigned short rst; + unsigned short _align; +} EXT_VAL_REGS; +/*----------------------------------------------------------------------------*/ +typedef struct { + EXT_VAL_REGS dir[4]; /*0x0000 ~ 0x001F: 32 bytes */ + EXT_VAL_REGS pullen[4]; /*0x0020 ~ 0x003F: 32 bytes */ + EXT_VAL_REGS pullsel[4]; /*0x0040 ~ 0x005F: 32 bytes */ + EXT_VAL_REGS dinv[4]; /*0x0060 ~ 0x007F: 32 bytes */ + EXT_VAL_REGS dout[4]; /*0x0080 ~ 0x009F: 32 bytes */ + EXT_VAL_REGS din[4]; /*0x00A0 ~ 0x00BF: 32 bytes */ + EXT_VAL_REGS mode[10]; /*0x00C0 ~ 0x010F: 80 bytes */ +} GPIOEXT_REGS; + +#endif /*_MT_GPIO_EXT_H_*/ diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/Kbuild b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..da62b1da69f364d6b3da3c3300b5edcf9d54e4a7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/Kbuild @@ -0,0 +1,5 @@ +#MTK port custom Kbuild +#To Add 1.environment variable +include $(src)/../../Kbuild-mtk-custom-env + +obj-y += mtk_config_platform.o diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..12ca470d4dee35ae34235fac5f6a8468d9fd0f68 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h @@ -0,0 +1,95 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX (5000) +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN (5000) + +/** + * Values used for determining the GPU frequency based on the LogicTile type + * Used by the function kbase_get_platform_logic_tile_type + */ +#define VE_VIRTEX6_GPU_FREQ_MIN 5000 +#define VE_VIRTEX6_GPU_FREQ_MAX 5000 +#define VE_VIRTEX7_GPU_FREQ_MIN 40000 +#define VE_VIRTEX7_GPU_FREQ_MAX 40000 + +/** + * CPU_SPEED_FUNC - A pointer to a function that calculates the CPU clock + * + * CPU clock speed of the platform is in MHz - see kbase_cpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_cpu_clk_speed_func. + * Default Value: NA + */ +#define CPU_SPEED_FUNC (&kbase_get_vexpress_cpu_clock_speed) + +/** + * GPU_SPEED_FUNC - A pointer to a function that calculates the GPU clock + * + * GPU clock speed of the platform in MHz - see kbase_gpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_gpu_clk_speed_func. + * Default Value: NA + */ +#define GPU_SPEED_FUNC (NULL) + +/** + * Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ +#define POWER_MANAGEMENT_CALLBACKS (&pm_callbacks) + +/** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ +#define PLATFORM_FUNCS (NULL) + +/** Power model for IPA + * + * Attached value: pointer to @ref mali_pa_model_ops + */ +#define POWER_MODEL_CALLBACKS (NULL) + +/** + * Secure mode switch + * + * Attached value: pointer to @ref kbase_secure_ops + */ +#define SECURE_CALLBACKS (NULL) + +extern struct kbase_pm_callback_conf pm_callbacks; diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h new file mode 100644 index 0000000000000000000000000000000000000000..6c30cea7094cc49f50dcc5dd6becaa0cd1089d4a --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h @@ -0,0 +1,35 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef __MTK_COMMON_H__ +#define __MTK_COMMON_H__ + +/* MTK device context driver private data */ +struct mtk_config { + + /* mtk mfg mapped register */ + void __iomem *mfg_register; + + /* main clock for gpu */ + struct clk *clk_mfg; + /* smi clock */ + struct clk *clk_smi_common; + /* mfg MTCMOS */ + struct clk *clk_mfg_scp; + /* display MTCMOS */ + struct clk *clk_display_scp; + +}; + + +#endif /* __MTK_COMMON_H__ */ diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..bec214a24c35b61f029ef5fb426eef898e5ce3e6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c @@ -0,0 +1,318 @@ +/* + * + * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include "mali_kbase_config_platform.h" + +#include +#include + +/* mtk */ +#include +#include "mtk_common.h" +#include "mtk_mfg_reg.h" +#include "mt_gpufreq.h" + +#ifdef ENABLE_COMMON_DVFS +#include +#endif + + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0xFC010000, + .end = 0xFC010000 + (4096 * 4) - 1 + } +}; +#endif /* CONFIG_OF */ + +/** + * Get MFG register map + * +*/ +static int mtk_mfg_reg_map(struct kbase_device *kbdev) +{ + int err = -ENOMEM; + struct device_node *dnode; + const char *mfg_device_tree_name = "mediatek,mt6755-mfgsys"; + struct mtk_config *config; + + if (!kbdev) { + pr_alert("MALI: input parameter is NULL \n"); + goto out_ioremap_err; + } + + config = (struct mtk_config *)kbdev->mtk_config; + + dnode = of_find_compatible_node(NULL, NULL, mfg_device_tree_name); + if (!dnode) { + pr_alert("[Mali][mtk_mfg_reg_map] mfgsys find node failed\n"); + goto out_ioremap_err; + }else{ + if (!config) { + pr_alert("[Mal][mtk_mfg_reg_map] mtk_config is NULL \n"); + goto out_ioremap_err; + } + config->mfg_register = of_iomap(dnode, 0); + } + + if (!config->mfg_register) { + dev_err(kbdev->dev, "[Mali][mtk_mfg_reg_map] Can't remap mfgsys register \n"); + err = -EINVAL; + goto out_ioremap_err; + } + + return 0; + +out_ioremap_err: + return err; + +} + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + int ret; + struct mtk_config *config; + void __iomem *clk_mfgsys_base; + + if (!kbdev) { + pr_alert("MALI: input parameter is NULL \n"); + return -1; + } + + config = (struct mtk_config *)kbdev->mtk_config; + if (!config) { + pr_alert("MALI: mtk_config is NULL \n"); + return -1; + } + clk_mfgsys_base = config->mfg_register; + + mt_gpufreq_voltage_enable_set(1); + mtk_set_vgpu_power_on_flag(MTK_VGPU_POWER_ON); + +#ifdef ENABLE_COMMON_DVFS + ged_dvfs_gpu_clock_switch_notify(1); +#endif + + ret = clk_prepare_enable(config->clk_display_scp); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling display MTCMOS"); + } + + ret = clk_prepare_enable(config->clk_smi_common); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling display smi_common clock"); + } + + ret = clk_prepare_enable(config->clk_mfg_scp); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling mfg MTCMOS"); + } + + ret = clk_prepare_enable(config->clk_mfg); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling mfg clock"); + } + + + MFG_WRITE32(0x7, clk_mfgsys_base+ 0x1C); + + pr_debug("MALI :[Power on] get GPU ID : 0x%x \n", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID)) ); + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#define DELAY_LOOP_COUNT 100000 + + volatile int polling_count = 100000; + volatile int i = 0; + struct mtk_config *config; + void __iomem *clk_mfgsys_base; + + if (!kbdev) { + pr_alert("[MALI] input parameter is NULL \n"); + return; + } + config = (struct mtk_config *)kbdev->mtk_config; + clk_mfgsys_base = config->mfg_register; + + if (!clk_mfgsys_base) { + pr_alert("[Mali] mfg_register find node failed\n"); + } else { + + /* 1. Delay 0.01ms before power off */ + for (i = 0; i < DELAY_LOOP_COUNT; i++); + if (DELAY_LOOP_COUNT != i) { + pr_alert("[MALI] power off delay error!\n"); + } + + /* 2. Polling MFG_DEBUG_REG for checking GPU idle before MTCNOW power off (0.1ms) */ + MFG_WRITE32(0x3, MFG_DEBUG_CTRL_REG(clk_mfgsys_base)); + + do { + + /* + * 0x13000184[2] + * 1'b1: bus idle + * 1'b0: bus busy + */ + if (MFG_READ32(MFG_DEBUG_STAT_REG(clk_mfgsys_base)) & MFG_BUS_IDLE_BIT) { + break; + } + } while (polling_count--); + + if (0 >= polling_count) { + pr_alert("[MALI]!!!!MFG(GPU) subsys is still BUSY!!!!!, polling_count=%d\n", polling_count); + } + } + +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif + + /* Polling the MFG_DEBUG_REG for checking GPU IDLE before MTCMOS power off (0.1ms) */ + MFG_WRITE32(0x3, MFG_DEBUG_CTRL_REG(clk_mfgsys_base)); + + do { + /* + * 0x13000184[2] + * 1'b1: bus idle + * 1'b0: bus busy + */ + if (MFG_READ32(MFG_DEBUG_STAT_REG(clk_mfgsys_base)) & MFG_BUS_IDLE_BIT) + { + break; + } + } while (polling_count--); + + if (0 >= polling_count) { + pr_alert("[MALI]!!!!MFG(GPU) subsys is still BUSY2!!!!!, polling_count=%d\n", polling_count); + } + + clk_disable_unprepare(config->clk_mfg); + clk_disable_unprepare(config->clk_mfg_scp); + clk_disable_unprepare(config->clk_smi_common); + clk_disable_unprepare(config->clk_display_scp); + + mt_gpufreq_voltage_enable_set(0); +#ifdef ENABLE_COMMON_DVFS + ged_dvfs_gpu_clock_switch_notify(0); +#endif + mtk_set_vgpu_power_on_flag(MTK_VGPU_POWER_OFF); + +} + +struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +static struct kbase_platform_config versatile_platform_config = { +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + +int mtk_platform_init(struct platform_device *pdev, struct kbase_device *kbdev) +{ + struct mtk_config *config; + unsigned int gpu_efuse; + extern int g_mtk_gpu_efuse_set_already; + + if (!pdev || !kbdev) { + pr_alert("input parameter is NULL \n"); + return -1; + } + + config = (struct mtk_config *)kbdev->mtk_config; + if (!config) { + pr_alert("[MALI] Alloc mtk_config\n"); + config = kmalloc(sizeof(struct mtk_config), GFP_KERNEL); + if (NULL == config) { + pr_alert("[MALI] Fail to alloc mtk_config \n"); + return -1; + } + kbdev->mtk_config = config; + } + + if (0 != mtk_mfg_reg_map(kbdev)) { + return -1; + } + + config->clk_mfg = devm_clk_get(&pdev->dev, "mfg-main"); + + if (IS_ERR(config->clk_mfg)) { + pr_alert("cannot get mfg main clock\n"); + return PTR_ERR(config->clk_mfg); + } + config->clk_smi_common = devm_clk_get(&pdev->dev, "mfg-smi-common"); + if (IS_ERR(config->clk_smi_common)) { + pr_alert("cannot get smi common clock\n"); + return PTR_ERR(config->clk_smi_common); + } + config->clk_mfg_scp = devm_clk_get(&pdev->dev, "mtcmos-mfg"); + if (IS_ERR(config->clk_mfg_scp)) { + pr_alert("cannot get mtcmos mfg\n"); + return PTR_ERR(config->clk_mfg_scp); + } + config->clk_display_scp = devm_clk_get(&pdev->dev, "mtcmos-display"); + if (IS_ERR(config->clk_display_scp)) { + pr_alert("cannot get mtcmos display\n"); + return PTR_ERR(config->clk_display_scp); + } + + gpu_efuse = (get_devinfo_with_index(17) >> 6)&0x01; + pr_alert("[Mali] get_devinfo_with_index = 0x%x , gpu_efuse = 0x%x \n", get_devinfo_with_index(17), gpu_efuse); +/* if( gpu_efuse == 1 ) + kbdev->pm.debug_core_mask = (u64)1; // 1-core + else + kbdev->pm.debug_core_mask = (u64)3; // 2-core +*/ + g_mtk_gpu_efuse_set_already = 1; + + return 0; +} diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..788070feb764d6bd2f870c1636c96ceb14b1218b --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h @@ -0,0 +1,27 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef __MTK_MFG_REG_H__ +#define __MTK_MFG_REG_H__ + +/* MT6755 MFG reg */ +#define MFG_DEBUG_SEL 0x180 +#define MFG_DEBUG_A 0x184 +#define MFG_BUS_IDLE_BIT (1 << 2) + +#define MFG_WRITE32(value, addr) writel(value, addr) +#define MFG_READ32(addr) readl(addr) +#define MFG_DEBUG_CTRL_REG(value) ((value) + MFG_DEBUG_SEL) +#define MFG_DEBUG_STAT_REG(value) ((value) + MFG_DEBUG_A) + +#endif /* __MTK_MFG_REG_H__ */ \ No newline at end of file diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/Kbuild b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/Kbuild new file mode 100644 index 0000000000000000000000000000000000000000..da62b1da69f364d6b3da3c3300b5edcf9d54e4a7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/Kbuild @@ -0,0 +1,5 @@ +#MTK port custom Kbuild +#To Add 1.environment variable +include $(src)/../../Kbuild-mtk-custom-env + +obj-y += mtk_config_platform.o diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..12ca470d4dee35ae34235fac5f6a8468d9fd0f68 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h @@ -0,0 +1,95 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX (5000) +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN (5000) + +/** + * Values used for determining the GPU frequency based on the LogicTile type + * Used by the function kbase_get_platform_logic_tile_type + */ +#define VE_VIRTEX6_GPU_FREQ_MIN 5000 +#define VE_VIRTEX6_GPU_FREQ_MAX 5000 +#define VE_VIRTEX7_GPU_FREQ_MIN 40000 +#define VE_VIRTEX7_GPU_FREQ_MAX 40000 + +/** + * CPU_SPEED_FUNC - A pointer to a function that calculates the CPU clock + * + * CPU clock speed of the platform is in MHz - see kbase_cpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_cpu_clk_speed_func. + * Default Value: NA + */ +#define CPU_SPEED_FUNC (&kbase_get_vexpress_cpu_clock_speed) + +/** + * GPU_SPEED_FUNC - A pointer to a function that calculates the GPU clock + * + * GPU clock speed of the platform in MHz - see kbase_gpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_gpu_clk_speed_func. + * Default Value: NA + */ +#define GPU_SPEED_FUNC (NULL) + +/** + * Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ +#define POWER_MANAGEMENT_CALLBACKS (&pm_callbacks) + +/** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ +#define PLATFORM_FUNCS (NULL) + +/** Power model for IPA + * + * Attached value: pointer to @ref mali_pa_model_ops + */ +#define POWER_MODEL_CALLBACKS (NULL) + +/** + * Secure mode switch + * + * Attached value: pointer to @ref kbase_secure_ops + */ +#define SECURE_CALLBACKS (NULL) + +extern struct kbase_pm_callback_conf pm_callbacks; diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h new file mode 100644 index 0000000000000000000000000000000000000000..6c30cea7094cc49f50dcc5dd6becaa0cd1089d4a --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h @@ -0,0 +1,35 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef __MTK_COMMON_H__ +#define __MTK_COMMON_H__ + +/* MTK device context driver private data */ +struct mtk_config { + + /* mtk mfg mapped register */ + void __iomem *mfg_register; + + /* main clock for gpu */ + struct clk *clk_mfg; + /* smi clock */ + struct clk *clk_smi_common; + /* mfg MTCMOS */ + struct clk *clk_mfg_scp; + /* display MTCMOS */ + struct clk *clk_display_scp; + +}; + + +#endif /* __MTK_COMMON_H__ */ diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..bec214a24c35b61f029ef5fb426eef898e5ce3e6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c @@ -0,0 +1,318 @@ +/* + * + * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include "mali_kbase_config_platform.h" + +#include +#include + +/* mtk */ +#include +#include "mtk_common.h" +#include "mtk_mfg_reg.h" +#include "mt_gpufreq.h" + +#ifdef ENABLE_COMMON_DVFS +#include +#endif + + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0xFC010000, + .end = 0xFC010000 + (4096 * 4) - 1 + } +}; +#endif /* CONFIG_OF */ + +/** + * Get MFG register map + * +*/ +static int mtk_mfg_reg_map(struct kbase_device *kbdev) +{ + int err = -ENOMEM; + struct device_node *dnode; + const char *mfg_device_tree_name = "mediatek,mt6755-mfgsys"; + struct mtk_config *config; + + if (!kbdev) { + pr_alert("MALI: input parameter is NULL \n"); + goto out_ioremap_err; + } + + config = (struct mtk_config *)kbdev->mtk_config; + + dnode = of_find_compatible_node(NULL, NULL, mfg_device_tree_name); + if (!dnode) { + pr_alert("[Mali][mtk_mfg_reg_map] mfgsys find node failed\n"); + goto out_ioremap_err; + }else{ + if (!config) { + pr_alert("[Mal][mtk_mfg_reg_map] mtk_config is NULL \n"); + goto out_ioremap_err; + } + config->mfg_register = of_iomap(dnode, 0); + } + + if (!config->mfg_register) { + dev_err(kbdev->dev, "[Mali][mtk_mfg_reg_map] Can't remap mfgsys register \n"); + err = -EINVAL; + goto out_ioremap_err; + } + + return 0; + +out_ioremap_err: + return err; + +} + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + int ret; + struct mtk_config *config; + void __iomem *clk_mfgsys_base; + + if (!kbdev) { + pr_alert("MALI: input parameter is NULL \n"); + return -1; + } + + config = (struct mtk_config *)kbdev->mtk_config; + if (!config) { + pr_alert("MALI: mtk_config is NULL \n"); + return -1; + } + clk_mfgsys_base = config->mfg_register; + + mt_gpufreq_voltage_enable_set(1); + mtk_set_vgpu_power_on_flag(MTK_VGPU_POWER_ON); + +#ifdef ENABLE_COMMON_DVFS + ged_dvfs_gpu_clock_switch_notify(1); +#endif + + ret = clk_prepare_enable(config->clk_display_scp); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling display MTCMOS"); + } + + ret = clk_prepare_enable(config->clk_smi_common); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling display smi_common clock"); + } + + ret = clk_prepare_enable(config->clk_mfg_scp); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling mfg MTCMOS"); + } + + ret = clk_prepare_enable(config->clk_mfg); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling mfg clock"); + } + + + MFG_WRITE32(0x7, clk_mfgsys_base+ 0x1C); + + pr_debug("MALI :[Power on] get GPU ID : 0x%x \n", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID)) ); + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#define DELAY_LOOP_COUNT 100000 + + volatile int polling_count = 100000; + volatile int i = 0; + struct mtk_config *config; + void __iomem *clk_mfgsys_base; + + if (!kbdev) { + pr_alert("[MALI] input parameter is NULL \n"); + return; + } + config = (struct mtk_config *)kbdev->mtk_config; + clk_mfgsys_base = config->mfg_register; + + if (!clk_mfgsys_base) { + pr_alert("[Mali] mfg_register find node failed\n"); + } else { + + /* 1. Delay 0.01ms before power off */ + for (i = 0; i < DELAY_LOOP_COUNT; i++); + if (DELAY_LOOP_COUNT != i) { + pr_alert("[MALI] power off delay error!\n"); + } + + /* 2. Polling MFG_DEBUG_REG for checking GPU idle before MTCNOW power off (0.1ms) */ + MFG_WRITE32(0x3, MFG_DEBUG_CTRL_REG(clk_mfgsys_base)); + + do { + + /* + * 0x13000184[2] + * 1'b1: bus idle + * 1'b0: bus busy + */ + if (MFG_READ32(MFG_DEBUG_STAT_REG(clk_mfgsys_base)) & MFG_BUS_IDLE_BIT) { + break; + } + } while (polling_count--); + + if (0 >= polling_count) { + pr_alert("[MALI]!!!!MFG(GPU) subsys is still BUSY!!!!!, polling_count=%d\n", polling_count); + } + } + +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif + + /* Polling the MFG_DEBUG_REG for checking GPU IDLE before MTCMOS power off (0.1ms) */ + MFG_WRITE32(0x3, MFG_DEBUG_CTRL_REG(clk_mfgsys_base)); + + do { + /* + * 0x13000184[2] + * 1'b1: bus idle + * 1'b0: bus busy + */ + if (MFG_READ32(MFG_DEBUG_STAT_REG(clk_mfgsys_base)) & MFG_BUS_IDLE_BIT) + { + break; + } + } while (polling_count--); + + if (0 >= polling_count) { + pr_alert("[MALI]!!!!MFG(GPU) subsys is still BUSY2!!!!!, polling_count=%d\n", polling_count); + } + + clk_disable_unprepare(config->clk_mfg); + clk_disable_unprepare(config->clk_mfg_scp); + clk_disable_unprepare(config->clk_smi_common); + clk_disable_unprepare(config->clk_display_scp); + + mt_gpufreq_voltage_enable_set(0); +#ifdef ENABLE_COMMON_DVFS + ged_dvfs_gpu_clock_switch_notify(0); +#endif + mtk_set_vgpu_power_on_flag(MTK_VGPU_POWER_OFF); + +} + +struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +static struct kbase_platform_config versatile_platform_config = { +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + +int mtk_platform_init(struct platform_device *pdev, struct kbase_device *kbdev) +{ + struct mtk_config *config; + unsigned int gpu_efuse; + extern int g_mtk_gpu_efuse_set_already; + + if (!pdev || !kbdev) { + pr_alert("input parameter is NULL \n"); + return -1; + } + + config = (struct mtk_config *)kbdev->mtk_config; + if (!config) { + pr_alert("[MALI] Alloc mtk_config\n"); + config = kmalloc(sizeof(struct mtk_config), GFP_KERNEL); + if (NULL == config) { + pr_alert("[MALI] Fail to alloc mtk_config \n"); + return -1; + } + kbdev->mtk_config = config; + } + + if (0 != mtk_mfg_reg_map(kbdev)) { + return -1; + } + + config->clk_mfg = devm_clk_get(&pdev->dev, "mfg-main"); + + if (IS_ERR(config->clk_mfg)) { + pr_alert("cannot get mfg main clock\n"); + return PTR_ERR(config->clk_mfg); + } + config->clk_smi_common = devm_clk_get(&pdev->dev, "mfg-smi-common"); + if (IS_ERR(config->clk_smi_common)) { + pr_alert("cannot get smi common clock\n"); + return PTR_ERR(config->clk_smi_common); + } + config->clk_mfg_scp = devm_clk_get(&pdev->dev, "mtcmos-mfg"); + if (IS_ERR(config->clk_mfg_scp)) { + pr_alert("cannot get mtcmos mfg\n"); + return PTR_ERR(config->clk_mfg_scp); + } + config->clk_display_scp = devm_clk_get(&pdev->dev, "mtcmos-display"); + if (IS_ERR(config->clk_display_scp)) { + pr_alert("cannot get mtcmos display\n"); + return PTR_ERR(config->clk_display_scp); + } + + gpu_efuse = (get_devinfo_with_index(17) >> 6)&0x01; + pr_alert("[Mali] get_devinfo_with_index = 0x%x , gpu_efuse = 0x%x \n", get_devinfo_with_index(17), gpu_efuse); +/* if( gpu_efuse == 1 ) + kbdev->pm.debug_core_mask = (u64)1; // 1-core + else + kbdev->pm.debug_core_mask = (u64)3; // 2-core +*/ + g_mtk_gpu_efuse_set_already = 1; + + return 0; +} diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..46b319da45d6386dab7783fddfe0d5f8ffa84e2e --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r12p1/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h @@ -0,0 +1,27 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifndef __MTK_MFG_REG_H__ +#define __MTK_MFG_REG_H__ + +/* MT6755 MFG reg */ +#define MFG_DEBUG_SEL 0x180 +#define MFG_DEBUG_A 0x184 +#define MFG_BUS_IDLE_BIT (1 << 2) + +#define MFG_WRITE32(value, addr) writel(value, addr) +#define MFG_READ32(addr) readl(addr) +#define MFG_DEBUG_CTRL_REG(value) ((value) + MFG_DEBUG_SEL) +#define MFG_DEBUG_STAT_REG(value) ((value) + MFG_DEBUG_A) + +#endif /* __MTK_MFG_REG_H__ */ \ No newline at end of file diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/Kbuild b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..da62b1da69f364d6b3da3c3300b5edcf9d54e4a7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/Kbuild @@ -0,0 +1,5 @@ +#MTK port custom Kbuild +#To Add 1.environment variable +include $(src)/../../Kbuild-mtk-custom-env + +obj-y += mtk_config_platform.o diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h new file mode 100755 index 0000000000000000000000000000000000000000..12ca470d4dee35ae34235fac5f6a8468d9fd0f68 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mali_kbase_config_platform.h @@ -0,0 +1,95 @@ +/* + * + * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX (5000) +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN (5000) + +/** + * Values used for determining the GPU frequency based on the LogicTile type + * Used by the function kbase_get_platform_logic_tile_type + */ +#define VE_VIRTEX6_GPU_FREQ_MIN 5000 +#define VE_VIRTEX6_GPU_FREQ_MAX 5000 +#define VE_VIRTEX7_GPU_FREQ_MIN 40000 +#define VE_VIRTEX7_GPU_FREQ_MAX 40000 + +/** + * CPU_SPEED_FUNC - A pointer to a function that calculates the CPU clock + * + * CPU clock speed of the platform is in MHz - see kbase_cpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_cpu_clk_speed_func. + * Default Value: NA + */ +#define CPU_SPEED_FUNC (&kbase_get_vexpress_cpu_clock_speed) + +/** + * GPU_SPEED_FUNC - A pointer to a function that calculates the GPU clock + * + * GPU clock speed of the platform in MHz - see kbase_gpu_clk_speed_func + * for the function prototype. + * + * Attached value: A kbase_gpu_clk_speed_func. + * Default Value: NA + */ +#define GPU_SPEED_FUNC (NULL) + +/** + * Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ +#define POWER_MANAGEMENT_CALLBACKS (&pm_callbacks) + +/** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ +#define PLATFORM_FUNCS (NULL) + +/** Power model for IPA + * + * Attached value: pointer to @ref mali_pa_model_ops + */ +#define POWER_MODEL_CALLBACKS (NULL) + +/** + * Secure mode switch + * + * Attached value: pointer to @ref kbase_secure_ops + */ +#define SECURE_CALLBACKS (NULL) + +extern struct kbase_pm_callback_conf pm_callbacks; diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h new file mode 100755 index 0000000000000000000000000000000000000000..cad1e8f6e5ff053e0f4a16e437bc08be9c0265c4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_common.h @@ -0,0 +1,22 @@ +#ifndef __MTK_COMMON_H__ +#define __MTK_COMMON_H__ + +/* MTK device context driver private data */ +struct mtk_config { + + /* mtk mfg mapped register */ + void __iomem *mfg_register; + + /* main clock for gpu */ + struct clk *clk_mfg; + /* smi clock */ + struct clk *clk_smi_common; + /* mfg MTCMOS */ + struct clk *clk_mfg_scp; + /* display MTCMOS */ + struct clk *clk_display_scp; + +}; + + +#endif /* __MTK_COMMON_H__ */ diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..d012af731bf1c7898c78330d815fcd16276bac63 --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_config_platform.c @@ -0,0 +1,318 @@ +/* + * + * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include "mali_kbase_config_platform.h" + +#include +#include + +/* mtk */ +#include +#include "mtk_common.h" +#include "mtk_mfg_reg.h" +#include "mt_gpufreq.h" + +#ifdef ENABLE_COMMON_DVFS +#include +#endif + + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0xFC010000, + .end = 0xFC010000 + (4096 * 4) - 1 + } +}; +#endif /* CONFIG_OF */ + +/** + * Get MFG register map + * +*/ +static int mtk_mfg_reg_map(struct kbase_device *kbdev) +{ + int err = -ENOMEM; + struct device_node *dnode; + const char *mfg_device_tree_name = "mediatek,mt6755-mfgsys"; + struct mtk_config *config; + + if (!kbdev) { + pr_alert("MALI: input parameter is NULL \n"); + goto out_ioremap_err; + } + + config = (struct mtk_config *)kbdev->mtk_config; + + dnode = of_find_compatible_node(NULL, NULL, mfg_device_tree_name); + if (!dnode) { + pr_alert("[Mali][mtk_mfg_reg_map] mfgsys find node failed\n"); + goto out_ioremap_err; + }else{ + if (!config) { + pr_alert("[Mal][mtk_mfg_reg_map] mtk_config is NULL \n"); + goto out_ioremap_err; + } + config->mfg_register = of_iomap(dnode, 0); + } + + if (!config->mfg_register) { + dev_err(kbdev->dev, "[Mali][mtk_mfg_reg_map] Can't remap mfgsys register \n"); + err = -EINVAL; + goto out_ioremap_err; + } + + return 0; + +out_ioremap_err: + return err; + +} + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + int ret; + struct mtk_config *config; + void __iomem *clk_mfgsys_base; + + if (!kbdev) { + pr_alert("MALI: input parameter is NULL \n"); + return -1; + } + + config = (struct mtk_config *)kbdev->mtk_config; + if (!config) { + pr_alert("MALI: mtk_config is NULL \n"); + return -1; + } + clk_mfgsys_base = config->mfg_register; + + mt_gpufreq_voltage_enable_set(1); + mtk_set_vgpu_power_on_flag(MTK_VGPU_POWER_ON); + +#ifdef ENABLE_COMMON_DVFS + ged_dvfs_gpu_clock_switch_notify(1); +#endif + + ret = clk_prepare_enable(config->clk_display_scp); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling display MTCMOS"); + } + + ret = clk_prepare_enable(config->clk_smi_common); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling display smi_common clock"); + } + + ret = clk_prepare_enable(config->clk_mfg_scp); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling mfg MTCMOS"); + } + + ret = clk_prepare_enable(config->clk_mfg); + if (ret) { + pr_alert("MALI: clk_prepare_enable failed when enabling mfg clock"); + } + + + MFG_WRITE32(0x7, clk_mfgsys_base+ 0x1C); + + pr_debug("MALI :[Power on] get GPU ID : 0x%x \n", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID)) ); + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#define DELAY_LOOP_COUNT 100000 + + volatile int polling_count = 100000; + volatile int i = 0; + struct mtk_config *config; + void __iomem *clk_mfgsys_base; + + if (!kbdev) { + pr_alert("[MALI] input parameter is NULL \n"); + return; + } + config = (struct mtk_config *)kbdev->mtk_config; + clk_mfgsys_base = config->mfg_register; + + if (!clk_mfgsys_base) { + pr_alert("[Mali] mfg_register find node failed\n"); + } else { + + /* 1. Delay 0.01ms before power off */ + for (i = 0; i < DELAY_LOOP_COUNT; i++); + if (DELAY_LOOP_COUNT != i) { + pr_alert("[MALI] power off delay error!\n"); + } + + /* 2. Polling MFG_DEBUG_REG for checking GPU idle before MTCNOW power off (0.1ms) */ + MFG_WRITE32(0x3, MFG_DEBUG_CTRL_REG(clk_mfgsys_base)); + + do { + + /* + * 0x13000184[2] + * 1'b1: bus idle + * 1'b0: bus busy + */ + if (MFG_READ32(MFG_DEBUG_STAT_REG(clk_mfgsys_base)) & MFG_BUS_IDLE_BIT) { + break; + } + } while (polling_count--); + + if (0 >= polling_count) { + pr_alert("[MALI]!!!!MFG(GPU) subsys is still BUSY!!!!!, polling_count=%d\n", polling_count); + } + } + +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif + + /* Polling the MFG_DEBUG_REG for checking GPU IDLE before MTCMOS power off (0.1ms) */ + MFG_WRITE32(0x3, MFG_DEBUG_CTRL_REG(clk_mfgsys_base)); + + do { + /* + * 0x13000184[2] + * 1'b1: bus idle + * 1'b0: bus busy + */ + if (MFG_READ32(MFG_DEBUG_STAT_REG(clk_mfgsys_base)) & MFG_BUS_IDLE_BIT) + { + break; + } + } while (polling_count--); + + if (0 >= polling_count) { + pr_alert("[MALI]!!!!MFG(GPU) subsys is still BUSY2!!!!!, polling_count=%d\n", polling_count); + } + + clk_disable_unprepare(config->clk_mfg); + clk_disable_unprepare(config->clk_mfg_scp); + clk_disable_unprepare(config->clk_smi_common); + clk_disable_unprepare(config->clk_display_scp); + + mt_gpufreq_voltage_enable_set(0); +#ifdef ENABLE_COMMON_DVFS + ged_dvfs_gpu_clock_switch_notify(0); +#endif + mtk_set_vgpu_power_on_flag(MTK_VGPU_POWER_OFF); + +} + +struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +static struct kbase_platform_config versatile_platform_config = { +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + +int mtk_platform_init(struct platform_device *pdev, struct kbase_device *kbdev) +{ + struct mtk_config *config; + unsigned int gpu_efuse; + extern int g_mtk_gpu_efuse_set_already; + + if (!pdev || !kbdev) { + pr_alert("input parameter is NULL \n"); + return -1; + } + + config = (struct mtk_config *)kbdev->mtk_config; + if (!config) { + pr_alert("[MALI] Alloc mtk_config\n"); + config = kmalloc(sizeof(struct mtk_config), GFP_KERNEL); + if (NULL == config) { + pr_alert("[MALI] Fail to alloc mtk_config \n"); + return -1; + } + kbdev->mtk_config = config; + } + + if (0 != mtk_mfg_reg_map(kbdev)) { + return -1; + } + + config->clk_mfg = devm_clk_get(&pdev->dev, "mfg-main"); + + if (IS_ERR(config->clk_mfg)) { + pr_alert("cannot get mfg main clock\n"); + return PTR_ERR(config->clk_mfg); + } + config->clk_smi_common = devm_clk_get(&pdev->dev, "mfg-smi-common"); + if (IS_ERR(config->clk_smi_common)) { + pr_alert("cannot get smi common clock\n"); + return PTR_ERR(config->clk_smi_common); + } + config->clk_mfg_scp = devm_clk_get(&pdev->dev, "mtcmos-mfg"); + if (IS_ERR(config->clk_mfg_scp)) { + pr_alert("cannot get mtcmos mfg\n"); + return PTR_ERR(config->clk_mfg_scp); + } + config->clk_display_scp = devm_clk_get(&pdev->dev, "mtcmos-display"); + if (IS_ERR(config->clk_display_scp)) { + pr_alert("cannot get mtcmos display\n"); + return PTR_ERR(config->clk_display_scp); + } + + gpu_efuse = (get_devinfo_with_index(17) >> 6)&0x01; + pr_alert("[Mali] get_devinfo_with_index = 0x%x , gpu_efuse = 0x%x \n", get_devinfo_with_index(17), gpu_efuse); + if( gpu_efuse == 1 ) + kbdev->pm.debug_core_mask = (u64)1; // 1-core + else + kbdev->pm.debug_core_mask = (u64)3; // 2-core + + g_mtk_gpu_efuse_set_already = 1; + + return 0; +} diff --git a/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h new file mode 100755 index 0000000000000000000000000000000000000000..7a0c3945dba62c7a63240f47043f21ca25c5ddec --- /dev/null +++ b/drivers/misc/mediatek/gpu/gpu_mali/mali_midgard/mali-r7p0/drivers/gpu/arm/midgard/platform/mt6755/mtk_mfg_reg.h @@ -0,0 +1,14 @@ +#ifndef __MTK_MFG_REG_H__ +#define __MTK_MFG_REG_H__ + +/* MT6755 MFG reg */ +#define MFG_DEBUG_SEL 0x180 +#define MFG_DEBUG_A 0x184 +#define MFG_BUS_IDLE_BIT (1 << 2) + +#define MFG_WRITE32(value, addr) writel(value, addr) +#define MFG_READ32(addr) readl(addr) +#define MFG_DEBUG_CTRL_REG(value) ((value) + MFG_DEBUG_SEL) +#define MFG_DEBUG_STAT_REG(value) ((value) + MFG_DEBUG_A) + +#endif /* __MTK_MFG_REG_H__ */ \ No newline at end of file diff --git a/drivers/misc/mediatek/gpu/mt6755/Makefile b/drivers/misc/mediatek/gpu/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c9f712de318cffe740956f1df9723a4b73781537 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +#ccflags-y += -Werror + +obj-y += mali-EAC/drivers/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/devicetree/bindings/arm/mali-midgard.txt b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/devicetree/bindings/arm/mali-midgard.txt new file mode 100755 index 0000000000000000000000000000000000000000..fb0a992c875a5385e6b8da5d0726321abd3015d8 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/devicetree/bindings/arm/mali-midgard.txt @@ -0,0 +1,43 @@ +# +# (C) COPYRIGHT 2013-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +* ARM Mali Midgard devices + + +Required properties: + +- compatible : Should be mali, replacing digits with x from the back, +until malitxx, ending with arm,mali-midgard, the latter not optional. +- reg : Physical base address of the device and length of the register area. +- interrupts : Contains the three IRQ lines required by T-6xx devices +- interrupt-names : Contains the names of IRQ resources in the order they were +provided in the interrupts property. Must contain: "JOB, "MMU", "GPU". + +Optional: + +- clocks : Phandle to clock for the Mali T-6xx device. +- clock-names : Shall be "clk_mali". + +Example for a Mali-T602: + +gpu@0xfc010000 { + compatible = "arm,malit602", "arm,malit60x", "arm,malit6xx", "arm,mali-midgard"; + reg = <0xfc010000 0x4000>; + interrupts = <0 36 4>, <0 37 4>, <0 38 4>; + interrupt-names = "JOB", "MMU", "GPU"; + + clocks = <&pclk_mali>; + clock-names = "clk_mali"; +}; diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/dma-buf-test-exporter.txt b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/dma-buf-test-exporter.txt new file mode 100755 index 0000000000000000000000000000000000000000..4208010cc78839fc18c3e9cad1a1ce5682cd4151 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/dma-buf-test-exporter.txt @@ -0,0 +1,40 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +===================== +dma-buf-test-exporter +===================== + +Overview +-------- + +The dma-buf-test-exporter is a simple exporter of dma_buf objects. +It has a private API to allocate and manipulate the buffers which are represented as dma_buf fds. +The private API allows: +* simple allocation of physically non-contiguous buffers +* simple allocation of physically contiguous buffers +* query kernel side API usage stats (number of attachments, number of mappings, mmaps) +* failure mode configuration (fail attach, mapping, mmap) +* kernel side memset of buffers + +The buffers support all of the dma_buf API, including mmap. + +It supports being compiled as a module both in-tree and out-of-tree. + +See include/linux/dma-buf-test-exporter.h for the ioctl interface. +See Documentation/dma-buf-sharing.txt for details on dma_buf. + + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/kds.txt b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/kds.txt new file mode 100755 index 0000000000000000000000000000000000000000..639288c106b7269e13100e0f3a0b0ab93d317864 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/Documentation/kds.txt @@ -0,0 +1,268 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +============================== +kds - Kernel Dependency System +============================== + +Introduction +------------ +kds provides a mechanism for clients to atomically lock down multiple abstract resources. +This can be done either synchronously or asynchronously. +Abstract resources is used to allow a set of clients to use kds to control access to any +resource, an example is structured memory buffers. + +kds supports that buffer is locked for exclusive access and sharing of buffers. + +kds can be built as either a integrated feature of the kernel or as a module. +It supports being compiled as a module both in-tree and out-of-tree. + + +Concepts +-------- +A core concept in kds is abstract resources. +A kds resource is just an abstraction for some client object, kds doesn't care what it is. +Typically EGL will consider UMP buffers as being a resource, thus each UMP buffer has +a kds resource for synchronization to the buffer. + +kds allows a client to create and destroy the abstract resource objects. +A new resource object is made available asap (it is just a simple malloc with some initializations), +while destroy it requires some external synchronization. + +The other core concept in kds is consumer of resources. +kds is requested to allow a client to consume a set of resources and the client will be notified when it can consume the resources. + +Exclusive access allows only one client to consume a resource. +Shared access permits multiple consumers to acceess a resource concurrently. + + +APIs +---- +kds provides simple resource allocate and destroy functions. +Clients use this to instantiate and control the lifetime of the resources kds manages. + +kds provides two ways to wait for resources: +- Asynchronous wait: the client specifies a function pointer to be called when wait is over +- Synchronous wait: Function blocks until access is gained. + +The synchronous API has a timeout for the wait. +The call can early out if a signal is delivered. + +After a client is done consuming the resource kds must be notified to release the resources and let some other client take ownership. +This is done via resource set release call. + +A Windows comparison: +kds implements WaitForMultipleObjectsEx(..., bWaitAll = TRUE, ...) but also has an asynchronous version in addition. +kds resources can be seen as being the same as NT object manager resources. + +Internals +--------- +kds guarantees atomicity when a set of resources is operated on. +This is implemented via a global resource lock which is taken by kds when it updates resource objects. + +Internally a resource in kds is a linked list head with some flags. + +When a consumer requests access to a set of resources it is queued on each of the resources. +The link from the consumer to the resources can be triggered. Once all links are triggered +the registered callback is called or the blocking function returns. +A link is considered triggered if it is the first on the list of consumers of a resource, +or if all the links ahead of it is marked as shared and itself is of the type shared. + +When the client is done consuming the consumer object is removed from the linked lists of +the resources and a potential new consumer becomes the head of the resources. +As we add and remove consumers atomically across all resources we can guarantee that +we never introduces a A->B + B->A type of loops/deadlocks. + + +kbase/base implementation +------------------------- +A HW job needs access to a set of shared resources. +EGL tracks this and encodes the set along with the atom in the ringbuffer. +EGL allocates a (k)base dep object to represent the dependency to the set of resources and encodes that along with the list of resources. +This dep object is use to create a dependency from a job chain(atom) to the resources it needs to run. +When kbase decodes the atom in the ringbuffer it finds the set of resources and calls kds to request all the needed resources. +As EGL needs to know when the kds request is delivered a new base event object is needed: atom enqueued. This event is only delivered for atoms which uses kds. +The callback kbase registers trigger the dependency object described which would trigger the existing JD system to release the job chain. +When the atom is done kds resource set release is call to release the resources. + +EGL will typically use exclusive access to the render target, while all buffers used as input can be marked as shared. + + +Buffer publish/vsync +-------------------- +EGL will use a separate ioctl or DRM flip to request the flip. +If the LCD driver is integrated with kds EGL can do these operations early. +The LCD driver must then implement the ioctl or DRM flip to be asynchronous with kds async call. +The LCD driver binds a kds resource to each virtual buffer (2 buffers in case of double-buffering). +EGL will make a dependency to the target kds resource in the kbase atom. +After EGL receives a atom enqueued event it can ask the LCD driver to pan to the target kds resource. +When the atom is completed it'll release the resource and the LCD driver will get its callback. +In the callback it'll load the target buffer into the DMA unit of the LCD hardware. +The LCD driver will be the consumer of both buffers for a short period. +The LCD driver will call kds resource set release on the previous on-screen buffer when the next vsync/dma read end is handled. + +=============================================== +Kernel driver kds client design considerations +=============================================== + +Number of resources +-------------------- + +The kds api allows a client to wait for ownership of a number of resources, where by the client does not take on ownership of any of the resources in the resource set +until all of the resources in the set are released. Consideration must be made with respect to performance, as waiting on large number of resources will incur +a greater overhead and may increase system latency. It may be worth considering how independent each of the resources are, for example if the same set of resources +are waited upon by each of the clients, then it may be possible to aggregate these into one resource that each client waits upon. + +Clients with shared access +--------------------------- + +The kds api allows a number of clients to gain shared access to a resource simultaneously, consideration must be made with respect to performance, large numbers of clients +wanting shared access can incur a performance penalty and may increase system latency, specifically when the clients are granted access. Having an excessively high +number of clients with shared access should be avoided, consideration should be made to the call back configuration being used. See Callbacks and Scenario 1 below. + +Callbacks +---------- + +Careful consideration must be made as to which callback type is most appropriate for kds clients, direct callbacks are called immediately from the context in which the +ownership of the resource is passed to the next waiter in the list. Where as when using deferred callbacks the callback is deferred and called from outside the context +that is relinquishing ownership, while this reduces the latency in the releasing clients context it does incur a cost as there is more latency between a resource +becoming free and the new client owning the resource callback being executed. + +Obviously direct callbacks have a performance advantage, as the call back is immediate and does not have to wait for the kernel to context switch to schedule in the +execution of the callback. + +However as the callback is immediate and within the context that is granting ownership it is important that the callback perform the MINIMUM amount of work necessary, +long call backs could cause poor system latency. Special care and attention must be taken if the direct callbacks can be called from IRQ handlers, such as when +kds_resource_set_release is called from an IRQ handler, in this case you have to avoid any calls that may sleep. + +Deferred contexts have the advantage that the call backs are deferred until they are scheduled by the kernel, therefore they are allowed to call functions that may sleep +and if scheduled from IRQ context not incur as much system latency as would be seen with direct callbacks from within the IRQ. + +Once the clients callback has been called, the client is considered to be owning the resource. Within the callback the client may only need to perform a small amount of work +before the client need to give up owner ship. The kds_resource_release function may be called from with in the call back, but consideration must be made when using direct +callbacks, with both respect to execution time and stack usage. Consider the example in Scenario 2 with direct callbacks: + +Scenario 1 - Shared client access - direct callbacks: + +Resources: X +Clients: A(S), B(S), C(S), D(S), E(E) +where: (S) = shared user, (E) = exclusive + +Clients kds callback handler: + +client__cb( p1, p2 ) +{ +} + +Where is either A,B,C,D + Queue |Owner +1. E Requests X exclusive | +2. E Owns X exclusive |E +3. A Requests X shared A|E +4. B Requests X shared BA|E +5. C Requests X shared CBA|E +6. D Requests X shared DCBA|E +7. E Releases X |DCBA +8. A Owns X shared |DCBA +9. B Owns X shared |DCBA +10. C Owns X shared |DCBA +11. D Owns X shared |DCBA + +At point 7 it is important to note that when E releases X; A,B,C and D become the new shared owners of X and the call back for each of the client(A,B,C,D) triggered, so consideration +must be made as to whether a direct or deferred callback is suitable, using direct callbacks would result in the call graph. + +Call graph when E releases X: + kds_resource_set_release( .. ) + +->client_A_cb( .. ) + +->client_B_cb( .. ) + +->client_C_cb( .. ) + +->client_D_cb( .. ) + + +Scenario 2 - Immediate resource release - direct callbacks: + +Resource: X +Clients: A, B, C, D + +Clients kds callback handler: + +client__cb( p1, p2 ) +{ + kds_resource_set_release( .. ); +} + +Where is either A,B,C,D + +1. A Owns X exclusive +2. B Requests X exclusive (direct callback) +3. C Requests X exclusive (direct callback) +4. D Requests X exclusive (direct callback) +5. A Releases X + +Call graph when A releases X: + kds_resource_set_release( .. ) + +->client_B_cb( .. ) + +->kds_resource_set_release( .. ) + +->client_C_cb( .. ) + +->kds_resource_set_release( .. ) + +->client_D_cb( .. ) + +As can be seen when a client releases the resource, with direct call backs it is possible to create nested calls + +IRQ Considerations +------------------- + +Usage of kds_resource_release in IRQ handlers should be carefully considered. + +Things to keep in mind: + +1.) Are you using direct or deferred callbacks? +2.) How many resources are you releasing? +3.) How many shared waiters are pending on the resource? + +Releasing ownership and wait cancellation +------------------------------------------ + +Client Wait Cancellation +------------------------- + +It may be necessary in certain circumstances for the client to cancel the wait for kds resources for error handling, process termination etc. Cancellation is +performed using kds_resource_set_release or kds_resource_set_release_sync using the rset that was received from kds_async_waitall, kds_resource_set_release_sync +being used for waits which are using deferred callbacks. + +It is possible that while the request to cancel the wait is being issued by the client, the client is granted access to the resources. Normally after the client +has taken ownership and finishes with that resource, it will release ownership to signal other waiters which are pending, this causes a race with the cancellation. +To prevent KDS trying to remove a wait twice from the internal list and accessing memory that is potentially freed, it is very important that all releasers use the +same rset pointer. Here is a simplified example of bad usage that must be avoided in any client implementation: + +Senario 3 - Bad release from multiple contexts: + + This scenaro is highlighting bad usage of the kds API + + kds_resource_set * rset; + kds_resource_set * rset_copy; + + kds_async_waitall( &rset, ... ... ... ); + + /* Don't do this */ + rset_copy = rset; + +Context A: + kds_resource_set_release( &rset ) + +Context B: + kds_resource_set_release( &rset_copy ) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..c82fcc684d88cd1e3809209fb30faaff24d62822 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += gpu/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..05908b2d589bababf064c2e3c48ff792c4ea1cb3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/sconscript @@ -0,0 +1,27 @@ +# +# (C) COPYRIGHT 2012, 2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +import os +import re +Import('env') + +linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' +search_term = '^[\ ]*CONFIG_DMA_SHARED_BUFFER_USES_KDS[\ ]*=[\ ]*y' +for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + SConscript( 'src/sconscript' ) + if Glob('tests/sconscript'): + SConscript( 'tests/sconscript' ) + break diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..68dad07ad6077a511c433f2a2edca84bdb500913 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +ifneq ($(CONFIG_DMA_SHARED_BUFFER),) +obj-m := dma_buf_lock.o +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..cf76132e6dde7f870d63609d0d2e0f36367c2c70 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/Makefile @@ -0,0 +1,32 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: dma_buf_lock + +dma_buf_lock: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../include" + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.c new file mode 100644 index 0000000000000000000000000000000000000000..658218273db972091eb04b87beccfef135d1af97 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.c @@ -0,0 +1,481 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma_buf_lock.h" + +/* Maximum number of buffers that a single handle can address */ +#define DMA_BUF_LOCK_BUF_MAX 32 + +#define DMA_BUF_LOCK_DEBUG 1 + +static dev_t dma_buf_lock_dev; +static struct cdev dma_buf_lock_cdev; +static struct class *dma_buf_lock_class; +static char dma_buf_lock_dev_name[] = "dma_buf_lock"; + +#ifdef HAVE_UNLOCKED_IOCTL +static long dma_buf_lock_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +static int dma_buf_lock_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif + +static struct file_operations dma_buf_lock_fops = +{ + .owner = THIS_MODULE, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = dma_buf_lock_ioctl, +#else + .ioctl = dma_buf_lock_ioctl, +#endif + .compat_ioctl = dma_buf_lock_ioctl, +}; + +typedef struct dma_buf_lock_resource +{ + int *list_of_dma_buf_fds; /* List of buffers copied from userspace */ + atomic_t locked; /* Status of lock */ + struct dma_buf **dma_bufs; + struct kds_resource **kds_resources; /* List of KDS resources associated with buffers */ + struct kds_resource_set *resource_set; + unsigned long exclusive; /* Exclusive access bitmap */ + wait_queue_head_t wait; + struct kds_callback cb; + struct kref refcount; + struct list_head link; + int count; +} dma_buf_lock_resource; + +static LIST_HEAD(dma_buf_lock_resource_list); +static DEFINE_MUTEX(dma_buf_lock_mutex); + +static inline int is_dma_buf_lock_file(struct file *); +static void dma_buf_lock_dounlock(struct kref *ref); + +static int dma_buf_lock_handle_release(struct inode *inode, struct file *file) +{ + dma_buf_lock_resource *resource; + + if (!is_dma_buf_lock_file(file)) + return -EINVAL; + + resource = file->private_data; +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_handle_release\n"); +#endif + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + + return 0; +} + +static void dma_buf_lock_kds_callback(void *param1, void *param2) +{ + dma_buf_lock_resource *resource = param1; +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_kds_callback\n"); +#endif + atomic_set(&resource->locked, 1); + + wake_up(&resource->wait); +} + +static unsigned int dma_buf_lock_handle_poll(struct file *file, + struct poll_table_struct *wait) +{ + dma_buf_lock_resource *resource; + unsigned int ret = 0; + + if (!is_dma_buf_lock_file(file)) + return POLLERR; + + resource = file->private_data; +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_handle_poll\n"); +#endif + if (1 == atomic_read(&resource->locked)) + { + /* Resources have been locked */ + ret = POLLIN | POLLRDNORM; + if (resource->exclusive) + { + ret |= POLLOUT | POLLWRNORM; + } + } + else + { + if (!poll_does_not_wait(wait)) + { + poll_wait(file, &resource->wait, wait); + } + } +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_handle_poll : return %i\n", ret); +#endif + return ret; +} + +static const struct file_operations dma_buf_lock_handle_fops = { + .release = dma_buf_lock_handle_release, + .poll = dma_buf_lock_handle_poll, +}; + +/* + * is_dma_buf_lock_file - Check if struct file* is associated with dma_buf_lock + */ +static inline int is_dma_buf_lock_file(struct file *file) +{ + return file->f_op == &dma_buf_lock_handle_fops; +} + + + +/* + * Start requested lock. + * + * Allocates required memory, copies dma_buf_fd list from userspace, + * acquires related KDS resources, and starts the lock. + */ +static int dma_buf_lock_dolock(dma_buf_lock_k_request *request) +{ + dma_buf_lock_resource *resource; + int size; + int fd; + int i; + int ret; + + if (NULL == request->list_of_dma_buf_fds) + { + return -EINVAL; + } + if (request->count <= 0) + { + return -EINVAL; + } + if (request->count > DMA_BUF_LOCK_BUF_MAX) + { + return -EINVAL; + } + if (request->exclusive != DMA_BUF_LOCK_NONEXCLUSIVE && + request->exclusive != DMA_BUF_LOCK_EXCLUSIVE) + { + return -EINVAL; + } + + resource = kzalloc(sizeof(dma_buf_lock_resource), GFP_KERNEL); + if (NULL == resource) + { + return -ENOMEM; + } + + atomic_set(&resource->locked, 0); + kref_init(&resource->refcount); + INIT_LIST_HEAD(&resource->link); + resource->count = request->count; + + /* Allocate space to store dma_buf_fds received from user space */ + size = request->count * sizeof(int); + resource->list_of_dma_buf_fds = kmalloc(size, GFP_KERNEL); + + if (NULL == resource->list_of_dma_buf_fds) + { + kfree(resource); + return -ENOMEM; + } + + /* Allocate space to store dma_buf pointers associated with dma_buf_fds */ + size = sizeof(struct dma_buf *) * request->count; + resource->dma_bufs = kmalloc(size, GFP_KERNEL); + + if (NULL == resource->dma_bufs) + { + kfree(resource->list_of_dma_buf_fds); + kfree(resource); + return -ENOMEM; + } + /* Allocate space to store kds_resources associated with dma_buf_fds */ + size = sizeof(struct kds_resource *) * request->count; + resource->kds_resources = kmalloc(size, GFP_KERNEL); + + if (NULL == resource->kds_resources) + { + kfree(resource->dma_bufs); + kfree(resource->list_of_dma_buf_fds); + kfree(resource); + return -ENOMEM; + } + + /* Copy requested list of dma_buf_fds from user space */ + size = request->count * sizeof(int); + if (0 != copy_from_user(resource->list_of_dma_buf_fds, (void __user *)request->list_of_dma_buf_fds, size)) + { + kfree(resource->list_of_dma_buf_fds); + kfree(resource->dma_bufs); + kfree(resource->kds_resources); + kfree(resource); + return -ENOMEM; + } +#if DMA_BUF_LOCK_DEBUG + for (i = 0; i < request->count; i++) + { + pr_debug("dma_buf %i = %X\n", i, resource->list_of_dma_buf_fds[i]); + } +#endif + + /* Add resource to global list */ + mutex_lock(&dma_buf_lock_mutex); + + list_add(&resource->link, &dma_buf_lock_resource_list); + + mutex_unlock(&dma_buf_lock_mutex); + + for (i = 0; i < request->count; i++) + { + /* Convert fd into dma_buf structure */ + resource->dma_bufs[i] = dma_buf_get(resource->list_of_dma_buf_fds[i]); + + if (IS_ERR_VALUE(PTR_ERR(resource->dma_bufs[i]))) + { + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + return -EINVAL; + } + + /*Get kds_resource associated with dma_buf */ + resource->kds_resources[i] = get_dma_buf_kds_resource(resource->dma_bufs[i]); + + if (NULL == resource->kds_resources[i]) + { + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + return -EINVAL; + } +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_dolock : dma_buf_fd %i dma_buf %X kds_resource %X\n", resource->list_of_dma_buf_fds[i], + (unsigned int)resource->dma_bufs[i], (unsigned int)resource->kds_resources[i]); +#endif + } + + kds_callback_init(&resource->cb, 1, dma_buf_lock_kds_callback); + init_waitqueue_head(&resource->wait); + + kref_get(&resource->refcount); + + /* Create file descriptor associated with lock request */ + fd = anon_inode_getfd("dma_buf_lock", &dma_buf_lock_handle_fops, + (void *)resource, 0); + if (fd < 0) + { + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + return fd; + } + + resource->exclusive = request->exclusive; + + /* Start locking process */ + ret = kds_async_waitall(&resource->resource_set, + &resource->cb, resource, NULL, + request->count, &resource->exclusive, + resource->kds_resources); + + if (IS_ERR_VALUE(ret)) + { + put_unused_fd(fd); + + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + + return ret; + } + +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_dolock : complete\n"); +#endif + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + + return fd; +} + +static void dma_buf_lock_dounlock(struct kref *ref) +{ + int i; + dma_buf_lock_resource *resource = container_of(ref, dma_buf_lock_resource, refcount); + + atomic_set(&resource->locked, 0); + + kds_callback_term(&resource->cb); + + kds_resource_set_release(&resource->resource_set); + + list_del(&resource->link); + + for (i = 0; i < resource->count; i++) + { + dma_buf_put(resource->dma_bufs[i]); + } + + kfree(resource->kds_resources); + kfree(resource->dma_bufs); + kfree(resource->list_of_dma_buf_fds); + kfree(resource); +} + +static int __init dma_buf_lock_init(void) +{ + int err; +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_init\n"); +#endif + err = alloc_chrdev_region(&dma_buf_lock_dev, 0, 1, dma_buf_lock_dev_name); + + if (0 == err) + { + cdev_init(&dma_buf_lock_cdev, &dma_buf_lock_fops); + + err = cdev_add(&dma_buf_lock_cdev, dma_buf_lock_dev, 1); + + if (0 == err) + { + dma_buf_lock_class = class_create(THIS_MODULE, dma_buf_lock_dev_name); + if (IS_ERR(dma_buf_lock_class)) + { + err = PTR_ERR(dma_buf_lock_class); + } + else + { + struct device *mdev; + mdev = device_create(dma_buf_lock_class, NULL, dma_buf_lock_dev, NULL, dma_buf_lock_dev_name); + if (!IS_ERR(mdev)) + { + return 0; + } + + err = PTR_ERR(mdev); + class_destroy(dma_buf_lock_class); + } + cdev_del(&dma_buf_lock_cdev); + } + + unregister_chrdev_region(dma_buf_lock_dev, 1); + } +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_init failed\n"); +#endif + return err; +} + +static void __exit dma_buf_lock_exit(void) +{ +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_exit\n"); +#endif + + /* Unlock all outstanding references */ + while (1) + { + mutex_lock(&dma_buf_lock_mutex); + if (list_empty(&dma_buf_lock_resource_list)) + { + mutex_unlock(&dma_buf_lock_mutex); + break; + } + else + { + dma_buf_lock_resource *resource = list_entry(dma_buf_lock_resource_list.next, + dma_buf_lock_resource, link); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + } + } + + device_destroy(dma_buf_lock_class, dma_buf_lock_dev); + + class_destroy(dma_buf_lock_class); + + cdev_del(&dma_buf_lock_cdev); + + unregister_chrdev_region(dma_buf_lock_dev, 1); +} + +#ifdef HAVE_UNLOCKED_IOCTL +static long dma_buf_lock_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +static int dma_buf_lock_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + dma_buf_lock_k_request request; + int size = _IOC_SIZE(cmd); + + if (_IOC_TYPE(cmd) != DMA_BUF_LOCK_IOC_MAGIC) + { + return -ENOTTY; + + } + if ((_IOC_NR(cmd) < DMA_BUF_LOCK_IOC_MINNR) || (_IOC_NR(cmd) > DMA_BUF_LOCK_IOC_MAXNR)) + { + return -ENOTTY; + } + + switch (cmd) + { + case DMA_BUF_LOCK_FUNC_LOCK_ASYNC: + if (size != sizeof(dma_buf_lock_k_request)) + { + return -ENOTTY; + } + if (copy_from_user(&request, (void __user *)arg, size)) + { + return -EFAULT; + } +#if DMA_BUF_LOCK_DEBUG + pr_debug("DMA_BUF_LOCK_FUNC_LOCK_ASYNC - %i\n", request.count); +#endif + return dma_buf_lock_dolock(&request); + } + + return -ENOTTY; +} + +module_init(dma_buf_lock_init); +module_exit(dma_buf_lock_exit); + +MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.h new file mode 100644 index 0000000000000000000000000000000000000000..5d248e8ccaed409d66f315da836e428383abedbd --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.h @@ -0,0 +1,42 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _DMA_BUF_LOCK_H +#define _DMA_BUF_LOCK_H + +typedef enum dma_buf_lock_exclusive +{ + DMA_BUF_LOCK_NONEXCLUSIVE = 0, + DMA_BUF_LOCK_EXCLUSIVE = -1 +} dma_buf_lock_exclusive; + +typedef struct dma_buf_lock_k_request +{ + int count; + int *list_of_dma_buf_fds; + int timeout; + dma_buf_lock_exclusive exclusive; +} dma_buf_lock_k_request; + +#define DMA_BUF_LOCK_IOC_MAGIC '~' + +#define DMA_BUF_LOCK_FUNC_LOCK_ASYNC _IOW(DMA_BUF_LOCK_IOC_MAGIC, 11, dma_buf_lock_k_request) + +#define DMA_BUF_LOCK_IOC_MINNR 11 +#define DMA_BUF_LOCK_IOC_MAXNR 11 + +#endif /* _DMA_BUF_LOCK_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..251c9a6f53d50a9584e31789e5c2fa9ccd27bdd7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_lock/src/sconscript @@ -0,0 +1,36 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +import os +import re +Import('env') + +if env['v'] != '1': + env['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +src = [Glob('#kernel/drivers/base/dma_buf_lock/src/*.c'), Glob('#kernel/drivers/base/dma_buf_lock/src/*.h'), Glob('#kernel/drivers/base/dma_buf_lock/src/K*')] + +if env.GetOption('clean') : + # Clean module + env.Execute(Action("make clean", '[CLEAN] dma_buf_lock')) + cmd = env.Command('$STATIC_LIB_PATH/dma_buf_lock.ko', src, []) + env.ProgTarget('dma_buf_lock', cmd) + +else: + # Build module + makeAction=Action("cd ${SOURCE.dir} && make dma_buf_lock && cp dma_buf_lock.ko $STATIC_LIB_PATH/", '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/dma_buf_lock.ko', src, [makeAction]) + env.ProgTarget('dma_buf_lock', cmd) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..56b9f86d2d52acafd705bbfd0770dec588105618 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +ifneq ($(CONFIG_DMA_SHARED_BUFFER),) +obj-$(CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER) += dma-buf-test-exporter.o +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..974f0c23dbd272f1c8b72222665578090cb998c6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Kconfig @@ -0,0 +1,20 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +config DMA_SHARED_BUFFER_TEST_EXPORTER + tristate "Test exporter for the dma-buf framework" + depends on DMA_SHARED_BUFFER + help + This option enables the test exporter usable to help test importerts. diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..06e3d5c121a525d605c2b53ee5a51a2035fa9590 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/Makefile @@ -0,0 +1,30 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER=m + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c new file mode 100644 index 0000000000000000000000000000000000000000..375d48079c535c1f48e7878c5b00f65f3161d092 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c @@ -0,0 +1,617 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) +#include +#include +#endif + +struct dma_buf_te_alloc { + /* the real alloc */ + int nr_pages; + struct page **pages; + + /* the debug usage tracking */ + int nr_attached_devices; + int nr_device_mappings; + int nr_cpu_mappings; + + /* failure simulation */ + int fail_attach; + int fail_map; + int fail_mmap; + + bool contiguous; + dma_addr_t contig_dma_addr; + void *contig_cpu_addr; +}; + +static struct miscdevice te_device; + +static int dma_buf_te_attach(struct dma_buf *buf, struct device *dev, struct dma_buf_attachment *attachment) +{ + struct dma_buf_te_alloc *alloc; + alloc = buf->priv; + + if (alloc->fail_attach) + return -EFAULT; + + /* dma_buf is externally locked during call */ + alloc->nr_attached_devices++; + return 0; +} + +static void dma_buf_te_detach(struct dma_buf *buf, struct dma_buf_attachment *attachment) +{ + struct dma_buf_te_alloc *alloc; + alloc = buf->priv; + /* dma_buf is externally locked during call */ + + alloc->nr_attached_devices--; +} + +static struct sg_table *dma_buf_te_map(struct dma_buf_attachment *attachment, enum dma_data_direction direction) +{ + struct sg_table *sg; + struct scatterlist *iter; + struct dma_buf_te_alloc *alloc; + int i; + int ret; + + alloc = attachment->dmabuf->priv; + + if (alloc->fail_map) + return ERR_PTR(-ENOMEM); + +#ifndef ARCH_HAS_SG_CHAIN + /* if the ARCH can't chain we can't have allocs larger than a single sg can hold */ + if (alloc->nr_pages > SG_MAX_SINGLE_ALLOC) + return ERR_PTR(-EINVAL); +#endif + + sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!sg) + return ERR_PTR(-ENOMEM); + + /* from here we access the allocation object, so lock the dmabuf pointing to it */ + mutex_lock(&attachment->dmabuf->lock); + + if (alloc->contiguous) + ret = sg_alloc_table(sg, 1, GFP_KERNEL); + else + ret = sg_alloc_table(sg, alloc->nr_pages, GFP_KERNEL); + if (ret) { + mutex_unlock(&attachment->dmabuf->lock); + kfree(sg); + return ERR_PTR(ret); + } + + if (alloc->contiguous) { + sg_dma_len(sg->sgl) = alloc->nr_pages * PAGE_SIZE; + sg_set_page(sg->sgl, pfn_to_page(PFN_DOWN(alloc->contig_dma_addr)), alloc->nr_pages * PAGE_SIZE, 0); + sg_dma_address(sg->sgl) = alloc->contig_dma_addr; + } else { + for_each_sg(sg->sgl, iter, alloc->nr_pages, i) + sg_set_page(iter, alloc->pages[i], PAGE_SIZE, 0); + } + + if (!dma_map_sg(attachment->dev, sg->sgl, sg->nents, direction)) { + mutex_unlock(&attachment->dmabuf->lock); + sg_free_table(sg); + kfree(sg); + return ERR_PTR(-ENOMEM); + } + + alloc->nr_device_mappings++; + mutex_unlock(&attachment->dmabuf->lock); + return sg; +} + +static void dma_buf_te_unmap(struct dma_buf_attachment *attachment, + struct sg_table *sg, enum dma_data_direction direction) +{ + struct dma_buf_te_alloc *alloc; + + alloc = attachment->dmabuf->priv; + + dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, direction); + sg_free_table(sg); + kfree(sg); + + mutex_lock(&attachment->dmabuf->lock); + alloc->nr_device_mappings--; + mutex_unlock(&attachment->dmabuf->lock); +} + +static void dma_buf_te_release(struct dma_buf *buf) +{ + int i; + struct dma_buf_te_alloc *alloc; + alloc = buf->priv; + /* no need for locking */ + + dev_info(te_device.this_device, "%s", __func__); + + if (alloc->contiguous) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + DEFINE_DMA_ATTRS(attrs); + + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + dma_free_attrs(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + alloc->contig_cpu_addr, alloc->contig_dma_addr, &attrs); +#else + dma_free_writecombine(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + alloc->contig_cpu_addr, alloc->contig_dma_addr); +#endif + } else { + for (i = 0; i < alloc->nr_pages; i++) + __free_page(alloc->pages[i]); + } + kfree(alloc->pages); + kfree(alloc); +} + + +static void dma_buf_te_mmap_open(struct vm_area_struct *vma) +{ + struct dma_buf *dma_buf; + struct dma_buf_te_alloc *alloc; + dma_buf = vma->vm_private_data; + alloc = dma_buf->priv; + + mutex_lock(&dma_buf->lock); + alloc->nr_cpu_mappings++; + mutex_unlock(&dma_buf->lock); +} + +static void dma_buf_te_mmap_close(struct vm_area_struct *vma) +{ + struct dma_buf *dma_buf; + struct dma_buf_te_alloc *alloc; + dma_buf = vma->vm_private_data; + alloc = dma_buf->priv; + + BUG_ON(alloc->nr_cpu_mappings <= 0); + mutex_lock(&dma_buf->lock); + alloc->nr_cpu_mappings--; + mutex_unlock(&dma_buf->lock); +} + +static int dma_buf_te_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct dma_buf_te_alloc *alloc; + struct dma_buf *dmabuf; + struct page *pageptr; + + dmabuf = vma->vm_private_data; + alloc = dmabuf->priv; + + if (vmf->pgoff > alloc->nr_pages) + return VM_FAULT_SIGBUS; + + pageptr = alloc->pages[vmf->pgoff]; + + BUG_ON(!pageptr); + + get_page(pageptr); + vmf->page = pageptr; + + return 0; +} + +struct vm_operations_struct dma_buf_te_vm_ops = { + .open = dma_buf_te_mmap_open, + .close = dma_buf_te_mmap_close, + .fault = dma_buf_te_mmap_fault +}; + +static int dma_buf_te_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct dma_buf_te_alloc *alloc; + alloc = dmabuf->priv; + + if (alloc->fail_mmap) + return -ENOMEM; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; +#else + vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTEXPAND; +#endif + vma->vm_ops = &dma_buf_te_vm_ops; + vma->vm_private_data = dmabuf; + + /* we fault in the pages on access */ + + /* call open to do the ref-counting */ + dma_buf_te_vm_ops.open(vma); + + return 0; +} + +static void *dma_buf_te_kmap_atomic(struct dma_buf *buf, unsigned long page_num) +{ + /* IGNORE */ + return NULL; +} + +static void *dma_buf_te_kmap(struct dma_buf *buf, unsigned long page_num) +{ + /* IGNORE */ + return NULL; +} + +static struct dma_buf_ops dma_buf_te_ops = { + /* real handlers */ + .attach = dma_buf_te_attach, + .detach = dma_buf_te_detach, + .map_dma_buf = dma_buf_te_map, + .unmap_dma_buf = dma_buf_te_unmap, + .release = dma_buf_te_release, + .mmap = dma_buf_te_mmap, + + /* nop handlers for mandatory functions we ignore */ + .kmap_atomic = dma_buf_te_kmap_atomic, + .kmap = dma_buf_te_kmap +}; + +static int do_dma_buf_te_ioctl_version(struct dma_buf_te_ioctl_version __user *buf) +{ + struct dma_buf_te_ioctl_version v; + + if (copy_from_user(&v, buf, sizeof(v))) + return -EFAULT; + + if (v.op != DMA_BUF_TE_ENQ) + return -EFAULT; + + v.op = DMA_BUF_TE_ACK; + v.major = DMA_BUF_TE_VER_MAJOR; + v.minor = DMA_BUF_TE_VER_MINOR; + + if (copy_to_user(buf, &v, sizeof(v))) + return -EFAULT; + else + return 0; +} + +static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf, bool contiguous) +{ + struct dma_buf_te_ioctl_alloc alloc_req; + struct dma_buf_te_alloc *alloc; + struct dma_buf *dma_buf; + int i = 0; + int fd; + + if (copy_from_user(&alloc_req, buf, sizeof(alloc_req))) { + dev_err(te_device.this_device, "%s: couldn't get user data", __func__); + goto no_input; + } + + if (!alloc_req.size) { + dev_err(te_device.this_device, "%s: no size specified", __func__); + goto zero_size; + } + + alloc = kzalloc(sizeof(struct dma_buf_te_alloc), GFP_KERNEL); + if (NULL == alloc) { + dev_err(te_device.this_device, "%s: couldn't alloc object", __func__); + goto no_alloc_object; + } + + alloc->nr_pages = alloc_req.size; + alloc->contiguous = contiguous; + + alloc->pages = kzalloc(sizeof(struct page *) * alloc->nr_pages, GFP_KERNEL); + if (!alloc->pages) { + dev_err(te_device.this_device, + "%s: couldn't alloc %d page structures", __func__, + alloc->nr_pages); + goto free_alloc_object; + } + + if (contiguous) { + dma_addr_t dma_aux; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + DEFINE_DMA_ATTRS(attrs); + + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + alloc->contig_cpu_addr = dma_alloc_attrs(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + &alloc->contig_dma_addr, GFP_KERNEL, &attrs); +#else + alloc->contig_cpu_addr = dma_alloc_writecombine(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + &alloc->contig_dma_addr, GFP_KERNEL); +#endif + if (!alloc->contig_cpu_addr) { + dev_err(te_device.this_device, "%s: couldn't alloc contiguous buffer %d pages", __func__, alloc->nr_pages); + goto free_page_struct; + } + dma_aux = alloc->contig_dma_addr; + for (i = 0; i < alloc->nr_pages; i++) { + alloc->pages[i] = pfn_to_page(PFN_DOWN(dma_aux)); + dma_aux += PAGE_SIZE; + } + } else { + for (i = 0; i < alloc->nr_pages; i++) { + alloc->pages[i] = alloc_page(GFP_KERNEL); + if (NULL == alloc->pages[i]) { + dev_err(te_device.this_device, "%s: couldn't alloc page", __func__); + goto no_page; + } + } + } + + /* alloc ready, let's export it */ + dma_buf = dma_buf_export(alloc, &dma_buf_te_ops, alloc->nr_pages << PAGE_SHIFT, O_CLOEXEC|O_RDWR); + + if (IS_ERR_OR_NULL(dma_buf)) { + dev_err(te_device.this_device, "%s: couldn't export dma_buf", __func__); + goto no_export; + } + + /* get fd for buf */ + fd = dma_buf_fd(dma_buf, O_CLOEXEC); + + if (fd < 0) { + dev_err(te_device.this_device, "%s: couldn't get fd from dma_buf", __func__); + goto no_fd; + } + + return fd; + +no_fd: + dma_buf_put(dma_buf); +no_export: + /* i still valid */ +no_page: + if (contiguous) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + DEFINE_DMA_ATTRS(attrs); + + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + dma_free_attrs(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + alloc->contig_cpu_addr, alloc->contig_dma_addr, &attrs); +#else + dma_free_writecombine(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + alloc->contig_cpu_addr, alloc->contig_dma_addr); +#endif + } else { + while (i-- > 0) + __free_page(alloc->pages[i]); + } +free_page_struct: + kfree(alloc->pages); +free_alloc_object: + kfree(alloc); +no_alloc_object: +zero_size: +no_input: + return -EFAULT; +} + +static int do_dma_buf_te_ioctl_status(struct dma_buf_te_ioctl_status __user *arg) +{ + struct dma_buf_te_ioctl_status status; + struct dma_buf *dmabuf; + struct dma_buf_te_alloc *alloc; + int res = -EINVAL; + + if (copy_from_user(&status, arg, sizeof(status))) + return -EFAULT; + + dmabuf = dma_buf_get(status.fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EINVAL; + + /* verify it's one of ours */ + if (dmabuf->ops != &dma_buf_te_ops) + goto err_have_dmabuf; + + /* ours, get the current status */ + alloc = dmabuf->priv; + + /* lock while reading status to take a snapshot */ + mutex_lock(&dmabuf->lock); + status.attached_devices = alloc->nr_attached_devices; + status.device_mappings = alloc->nr_device_mappings; + status.cpu_mappings = alloc->nr_cpu_mappings; + mutex_unlock(&dmabuf->lock); + + if (copy_to_user(arg, &status, sizeof(status))) + goto err_have_dmabuf; + + /* All OK */ + res = 0; + +err_have_dmabuf: + dma_buf_put(dmabuf); + return res; +} + +static int do_dma_buf_te_ioctl_set_failing(struct dma_buf_te_ioctl_set_failing __user *arg) +{ + struct dma_buf *dmabuf; + struct dma_buf_te_ioctl_set_failing f; + struct dma_buf_te_alloc *alloc; + int res = -EINVAL; + + if (copy_from_user(&f, arg, sizeof(f))) + return -EFAULT; + + dmabuf = dma_buf_get(f.fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EINVAL; + + /* verify it's one of ours */ + if (dmabuf->ops != &dma_buf_te_ops) + goto err_have_dmabuf; + + /* ours, set the fail modes */ + alloc = dmabuf->priv; + /* lock to set the fail modes atomically */ + mutex_lock(&dmabuf->lock); + alloc->fail_attach = f.fail_attach; + alloc->fail_map = f.fail_map; + alloc->fail_mmap = f.fail_mmap; + mutex_unlock(&dmabuf->lock); + + /* success */ + res = 0; + +err_have_dmabuf: + dma_buf_put(dmabuf); + return res; +} + +static u32 dma_te_buf_fill(struct dma_buf *dma_buf, unsigned int value) +{ + struct dma_buf_attachment *attachment; + struct sg_table *sgt; + struct scatterlist *sg; + unsigned int count; + unsigned int offset = 0; + int ret = 0; + int i; + + attachment = dma_buf_attach(dma_buf, te_device.this_device); + if (IS_ERR_OR_NULL(attachment)) + return -EBUSY; + + sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(sgt)) { + ret = PTR_ERR(sgt); + goto no_import; + } + + for_each_sg(sgt->sgl, sg, sgt->nents, count) { + ret = dma_buf_begin_cpu_access(dma_buf, offset, sg_dma_len(sg), DMA_BIDIRECTIONAL); + if (ret) + goto no_cpu_access; + for (i = 0; i < sg_dma_len(sg); i = i + PAGE_SIZE) { + void *addr; + + addr = dma_buf_kmap(dma_buf, i >> PAGE_SHIFT); + if (!addr) { + /* dma_buf_kmap is unimplemented in exynos and returns NULL */ + dma_buf_end_cpu_access(dma_buf, offset, sg_dma_len(sg), DMA_BIDIRECTIONAL); + ret = -EPERM; + goto no_cpu_access; + } + memset(addr, value, PAGE_SIZE); + dma_buf_kunmap(dma_buf, i >> PAGE_SHIFT, addr); + } + dma_buf_end_cpu_access(dma_buf, offset, sg_dma_len(sg), DMA_BIDIRECTIONAL); + offset += sg_dma_len(sg); + } + +no_cpu_access: + dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL); +no_import: + dma_buf_detach(dma_buf, attachment); + return ret; +} + +static int do_dma_buf_te_ioctl_fill(struct dma_buf_te_ioctl_fill __user *arg) +{ + + struct dma_buf *dmabuf; + struct dma_buf_te_ioctl_fill f; + int ret; + + if (copy_from_user(&f, arg, sizeof(f))) + return -EFAULT; + + dmabuf = dma_buf_get(f.fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EINVAL; + + ret = dma_te_buf_fill(dmabuf, f.value); + dma_buf_put(dmabuf); + + return ret; +} + +static long dma_buf_te_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case DMA_BUF_TE_VERSION: + return do_dma_buf_te_ioctl_version((struct dma_buf_te_ioctl_version __user *)arg); + case DMA_BUF_TE_ALLOC: + return do_dma_buf_te_ioctl_alloc((struct dma_buf_te_ioctl_alloc __user *)arg, false); + case DMA_BUF_TE_ALLOC_CONT: + return do_dma_buf_te_ioctl_alloc((struct dma_buf_te_ioctl_alloc __user *)arg, true); + case DMA_BUF_TE_QUERY: + return do_dma_buf_te_ioctl_status((struct dma_buf_te_ioctl_status __user *)arg); + case DMA_BUF_TE_SET_FAILING: + return do_dma_buf_te_ioctl_set_failing((struct dma_buf_te_ioctl_set_failing __user *)arg); + case DMA_BUF_TE_FILL: + return do_dma_buf_te_ioctl_fill((struct dma_buf_te_ioctl_fill __user *)arg); + default: + return -ENOTTY; + } +} + +static const struct file_operations dma_buf_te_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = dma_buf_te_ioctl, + .compat_ioctl = dma_buf_te_ioctl, +}; + +static int __init dma_buf_te_init(void) +{ + int res; + te_device.minor = MISC_DYNAMIC_MINOR; + te_device.name = "dma_buf_te"; + te_device.fops = &dma_buf_te_fops; + + res = misc_register(&te_device); + if (res) { + pr_debug("Misc device registration failed of 'dma_buf_te'\n"); + return res; + } + te_device.this_device->coherent_dma_mask = DMA_BIT_MASK(32); + + dev_info(te_device.this_device, "dma_buf_te ready\n"); + return 0; + +} + +static void __exit dma_buf_te_exit(void) +{ + misc_deregister(&te_device); +} + +module_init(dma_buf_te_init); +module_exit(dma_buf_te_exit); +MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..bfb8a99f9d45d296df6d4c63f8e12c067af58c01 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/dma_buf_test_exporter/sconscript @@ -0,0 +1,36 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +Import('env') + +if env['v'] != '1': + env['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +src = [Glob('#kernel/drivers/base/dma_buf_test_exporter/*.c'), Glob('#kernel/include/linux/*.h'), Glob('#kernel/drivers/base/dma_buf_test_exporter/K*')] + +env.Append( CPPPATH = '#kernel/include' ) + +if env.GetOption('clean') : + env.Execute(Action("make clean", '[CLEAN] dma-buf-test-exporter')) + cmd = env.Command('$STATIC_LIB_PATH/dma-buf-test-exporter.ko', src, []) + env.ProgTarget('dma-buf-test-exporter', cmd) +else: + makeAction=Action("cd ${SOURCE.dir} && make && ( ( [ -f dma-buf-test-exporter.ko ] && cp dma-buf-test-exporter.ko $STATIC_LIB_PATH/ ) || touch $STATIC_LIB_PATH/dma-buf-test-exporter.ko)", '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/dma-buf-test-exporter.ko', src, [makeAction]) + env.ProgTarget('dma-buf-test-exporter', cmd) + + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..a88acd8fdce8516286f16848df7625d35763889a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +obj-$(CONFIG_KDS) += kds.o +obj-$(CONFIG_KDS_TEST) += kds_test.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..5f96165f67d535f2b6b654b454d0dbfd3d31dff5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Kconfig @@ -0,0 +1,20 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +config KDS + tristate "Kernel dependency system" + help + This option enables the generic kernel dependency system diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..364d1515c1ae4e25d4a7419dee7725dfcf5911b4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/Makefile @@ -0,0 +1,37 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) +CONFIG_KDS_TEST ?= n + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: kds + +kds: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_KDS=m + +kds_test: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_KDS_TEST=m + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/kds.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/kds.c new file mode 100644 index 0000000000000000000000000000000000000000..de114a0937fe8b722048a7a18233efd02e710398 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/kds.c @@ -0,0 +1,545 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define KDS_LINK_TRIGGERED (1u << 0) +#define KDS_LINK_EXCLUSIVE (1u << 1) + +#define KDS_INVALID (void *)-2 +#define KDS_RESOURCE (void *)-1 + +struct kds_resource_set +{ + unsigned long num_resources; + unsigned long pending; + struct kds_callback *cb; + void *callback_parameter; + void *callback_extra_parameter; + struct list_head callback_link; + struct work_struct callback_work; + atomic_t cb_queued; + + /* This is only initted when kds_waitall() is called. */ + wait_queue_head_t wake; + + struct kds_link resources[0]; +}; + +static DEFINE_SPINLOCK(kds_lock); + +int kds_callback_init(struct kds_callback *cb, int direct, kds_callback_fn user_cb) +{ + int ret = 0; + + cb->direct = direct; + cb->user_cb = user_cb; + + if (!direct) + { + cb->wq = alloc_workqueue("kds", WQ_UNBOUND | WQ_HIGHPRI, WQ_UNBOUND_MAX_ACTIVE); + if (!cb->wq) + ret = -ENOMEM; + } + else + { + cb->wq = NULL; + } + + return ret; +} +EXPORT_SYMBOL(kds_callback_init); + +void kds_callback_term(struct kds_callback *cb) +{ + if (!cb->direct) + { + BUG_ON(!cb->wq); + destroy_workqueue(cb->wq); + } + else + { + BUG_ON(cb->wq); + } +} + +EXPORT_SYMBOL(kds_callback_term); + +static void kds_do_user_callback(struct kds_resource_set *rset) +{ + rset->cb->user_cb(rset->callback_parameter, rset->callback_extra_parameter); +} + +static void kds_queued_callback(struct work_struct *work) +{ + struct kds_resource_set *rset; + rset = container_of(work, struct kds_resource_set, callback_work); + + atomic_dec(&rset->cb_queued); + + kds_do_user_callback(rset); +} + +static void kds_callback_perform(struct kds_resource_set *rset) +{ + if (rset->cb->direct) + kds_do_user_callback(rset); + else + { + int result; + + atomic_inc(&rset->cb_queued); + + result = queue_work(rset->cb->wq, &rset->callback_work); + /* if we got a 0 return it means we've triggered the same rset twice! */ + WARN_ON(!result); + } +} + +void kds_resource_init(struct kds_resource * const res) +{ + BUG_ON(!res); + INIT_LIST_HEAD(&res->waiters.link); + res->waiters.parent = KDS_RESOURCE; +} +EXPORT_SYMBOL(kds_resource_init); + +int kds_resource_term(struct kds_resource *res) +{ + unsigned long lflags; + BUG_ON(!res); + spin_lock_irqsave(&kds_lock, lflags); + if (!list_empty(&res->waiters.link)) + { + spin_unlock_irqrestore(&kds_lock, lflags); + pr_err("ERROR: KDS resource is still in use\n"); + return -EBUSY; + } + res->waiters.parent = KDS_INVALID; + spin_unlock_irqrestore(&kds_lock, lflags); + return 0; +} +EXPORT_SYMBOL(kds_resource_term); + +int kds_async_waitall( + struct kds_resource_set ** const pprset, + struct kds_callback *cb, + void *callback_parameter, + void *callback_extra_parameter, + int number_resources, + unsigned long *exclusive_access_bitmap, + struct kds_resource **resource_list) +{ + struct kds_resource_set *rset = NULL; + unsigned long lflags; + int i; + int triggered; + int err = -EFAULT; + + BUG_ON(!pprset); + BUG_ON(!resource_list); + BUG_ON(!cb); + + WARN_ONCE(number_resources > 10, "Waiting on a high numbers of resources may increase latency, see documentation."); + + rset = kmalloc(sizeof(*rset) + number_resources * sizeof(struct kds_link), GFP_KERNEL); + if (!rset) + { + return -ENOMEM; + } + + rset->num_resources = number_resources; + rset->pending = number_resources; + rset->cb = cb; + rset->callback_parameter = callback_parameter; + rset->callback_extra_parameter = callback_extra_parameter; + INIT_LIST_HEAD(&rset->callback_link); + INIT_WORK(&rset->callback_work, kds_queued_callback); + atomic_set(&rset->cb_queued, 0); + + for (i = 0; i < number_resources; i++) + { + INIT_LIST_HEAD(&rset->resources[i].link); + rset->resources[i].parent = rset; + } + + spin_lock_irqsave(&kds_lock, lflags); + + for (i = 0; i < number_resources; i++) + { + unsigned long link_state = 0; + + if (test_bit(i, exclusive_access_bitmap)) + { + link_state |= KDS_LINK_EXCLUSIVE; + } + + /* no-one else waiting? */ + if (list_empty(&resource_list[i]->waiters.link)) + { + link_state |= KDS_LINK_TRIGGERED; + rset->pending--; + } + /* Adding a non-exclusive and the current tail is a triggered non-exclusive? */ + else if (((link_state & KDS_LINK_EXCLUSIVE) == 0) && + (((list_entry(resource_list[i]->waiters.link.prev, struct kds_link, link)->state & (KDS_LINK_EXCLUSIVE | KDS_LINK_TRIGGERED)) == KDS_LINK_TRIGGERED))) + { + link_state |= KDS_LINK_TRIGGERED; + rset->pending--; + } + rset->resources[i].state = link_state; + + /* avoid double wait (hang) */ + if (!list_empty(&resource_list[i]->waiters.link)) + { + /* adding same rset again? */ + if (list_entry(resource_list[i]->waiters.link.prev, struct kds_link, link)->parent == rset) + { + goto roll_back; + } + } + list_add_tail(&rset->resources[i].link, &resource_list[i]->waiters.link); + } + + triggered = (rset->pending == 0); + + /* set the pointer before the callback is called so it sees it */ + *pprset = rset; + + spin_unlock_irqrestore(&kds_lock, lflags); + + if (triggered) + { + /* all resources obtained, trigger callback */ + kds_callback_perform(rset); + } + + return 0; + +roll_back: + /* roll back */ + while (i-- > 0) + { + list_del(&rset->resources[i].link); + } + err = -EINVAL; + + spin_unlock_irqrestore(&kds_lock, lflags); + kfree(rset); + return err; +} +EXPORT_SYMBOL(kds_async_waitall); + +static void wake_up_sync_call(void *callback_parameter, void *callback_extra_parameter) +{ + wait_queue_head_t *wait = (wait_queue_head_t *)callback_parameter; + wake_up(wait); +} + +static struct kds_callback sync_cb = +{ + wake_up_sync_call, + 1, + NULL, +}; + +struct kds_resource_set *kds_waitall( + int number_resources, + unsigned long *exclusive_access_bitmap, + struct kds_resource **resource_list, + unsigned long jiffies_timeout) +{ + struct kds_resource_set *rset; + unsigned long lflags; + int i; + int triggered = 0; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + + rset = kmalloc(sizeof(*rset) + number_resources * sizeof(struct kds_link), GFP_KERNEL); + if (!rset) + return rset; + + rset->num_resources = number_resources; + rset->pending = number_resources; + init_waitqueue_head(&rset->wake); + INIT_LIST_HEAD(&rset->callback_link); + INIT_WORK(&rset->callback_work, kds_queued_callback); + atomic_set(&rset->cb_queued, 0); + + spin_lock_irqsave(&kds_lock, lflags); + + for (i = 0; i < number_resources; i++) + { + unsigned long link_state = 0; + + if (test_bit(i, exclusive_access_bitmap)) + { + link_state |= KDS_LINK_EXCLUSIVE; + } + + if (list_empty(&resource_list[i]->waiters.link)) + { + link_state |= KDS_LINK_TRIGGERED; + rset->pending--; + } + /* Adding a non-exclusive and the current tail is a triggered non-exclusive? */ + else if (((link_state & KDS_LINK_EXCLUSIVE) == 0) && + (((list_entry(resource_list[i]->waiters.link.prev, struct kds_link, link)->state & (KDS_LINK_EXCLUSIVE | KDS_LINK_TRIGGERED)) == KDS_LINK_TRIGGERED))) + { + link_state |= KDS_LINK_TRIGGERED; + rset->pending--; + } + + INIT_LIST_HEAD(&rset->resources[i].link); + rset->resources[i].parent = rset; + rset->resources[i].state = link_state; + + /* avoid double wait (hang) */ + if (!list_empty(&resource_list[i]->waiters.link)) + { + /* adding same rset again? */ + if (list_entry(resource_list[i]->waiters.link.prev, struct kds_link, link)->parent == rset) + { + goto roll_back; + } + } + + list_add_tail(&rset->resources[i].link, &resource_list[i]->waiters.link); + } + + if (rset->pending == 0) + triggered = 1; + else + { + rset->cb = &sync_cb; + rset->callback_parameter = &rset->wake; + rset->callback_extra_parameter = NULL; + } + + spin_unlock_irqrestore(&kds_lock, lflags); + + if (!triggered) + { + long wait_res = 0; + long timeout = (jiffies_timeout == KDS_WAIT_BLOCKING) ? + MAX_SCHEDULE_TIMEOUT : jiffies_timeout; + + if (timeout) + { + wait_res = wait_event_interruptible_timeout(rset->wake, + rset->pending == 0, timeout); + } + + if ((wait_res == -ERESTARTSYS) || (wait_res == 0)) + { + /* use \a kds_resource_set_release to roll back */ + kds_resource_set_release(&rset); + return ERR_PTR(wait_res); + } + } + return rset; + +roll_back: + /* roll back */ + while (i-- > 0) + { + list_del(&rset->resources[i].link); + } + + spin_unlock_irqrestore(&kds_lock, lflags); + kfree(rset); + return ERR_PTR(-EINVAL); +} +EXPORT_SYMBOL(kds_waitall); + +static void __kds_resource_set_release_common(struct kds_resource_set *rset) +{ + struct list_head triggered = LIST_HEAD_INIT(triggered); + struct kds_resource_set *it; + unsigned long lflags; + int i; + + spin_lock_irqsave(&kds_lock, lflags); + + for (i = 0; i < rset->num_resources; i++) + { + struct kds_resource *resource; + struct kds_link *it = NULL; + + /* fetch the previous entry on the linked list */ + it = list_entry(rset->resources[i].link.prev, struct kds_link, link); + /* unlink ourself */ + list_del(&rset->resources[i].link); + + /* any waiters? */ + if (list_empty(&it->link)) + continue; + + /* were we the head of the list? (head if prev is a resource) */ + if (it->parent != KDS_RESOURCE) + { + if ((it->state & KDS_LINK_TRIGGERED) && !(it->state & KDS_LINK_EXCLUSIVE)) + { + /* + * previous was triggered and not exclusive, so we + * trigger non-exclusive until end-of-list or first + * exclusive + */ + + struct kds_link *it_waiting = it; + + list_for_each_entry(it, &it_waiting->link, link) + { + /* exclusive found, stop triggering */ + if (it->state & KDS_LINK_EXCLUSIVE) + break; + + it->state |= KDS_LINK_TRIGGERED; + /* a parent to update? */ + if (it->parent != KDS_RESOURCE) + { + if (0 == --it->parent->pending) + { + /* new owner now triggered, track for callback later */ + list_add(&it->parent->callback_link, &triggered); + } + } + } + } + continue; + } + + /* we were the head, find the kds_resource */ + resource = container_of(it, struct kds_resource, waiters); + + /* we know there is someone waiting from the any-waiters test above */ + + /* find the head of the waiting list */ + it = list_first_entry(&resource->waiters.link, struct kds_link, link); + + /* new exclusive owner? */ + if (it->state & KDS_LINK_EXCLUSIVE) + { + /* link now triggered */ + it->state |= KDS_LINK_TRIGGERED; + /* a parent to update? */ + if (0 == --it->parent->pending) + { + /* new owner now triggered, track for callback later */ + list_add(&it->parent->callback_link, &triggered); + } + } + /* exclusive releasing ? */ + else if (rset->resources[i].state & KDS_LINK_EXCLUSIVE) + { + /* trigger non-exclusive until end-of-list or first exclusive */ + list_for_each_entry(it, &resource->waiters.link, link) + { + /* exclusive found, stop triggering */ + if (it->state & KDS_LINK_EXCLUSIVE) + break; + + it->state |= KDS_LINK_TRIGGERED; + /* a parent to update? */ + if (0 == --it->parent->pending) + { + /* new owner now triggered, track for callback later */ + list_add(&it->parent->callback_link, &triggered); + } + } + } + } + + spin_unlock_irqrestore(&kds_lock, lflags); + + while (!list_empty(&triggered)) + { + it = list_first_entry(&triggered, struct kds_resource_set, callback_link); + list_del(&it->callback_link); + kds_callback_perform(it); + } +} + +void kds_resource_set_release(struct kds_resource_set **pprset) +{ + struct kds_resource_set *rset; + int queued; + + rset = cmpxchg(pprset, *pprset, NULL); + + if (!rset) + { + /* caught a race between a cancelation + * and a completion, nothing to do */ + return; + } + + __kds_resource_set_release_common(rset); + + /* + * Caller is responsible for guaranteeing that callback work is not + * pending (i.e. its running or completed) prior to calling release. + */ + queued = atomic_read(&rset->cb_queued); + BUG_ON(queued); + + /* free the resource set */ + kfree(rset); +} +EXPORT_SYMBOL(kds_resource_set_release); + +void kds_resource_set_release_sync(struct kds_resource_set **pprset) +{ + struct kds_resource_set *rset; + + rset = cmpxchg(pprset, *pprset, NULL); + if (!rset) + { + /* caught a race between a cancelation + * and a completion, nothing to do */ + return; + } + + __kds_resource_set_release_common(rset); + + /* + * In the case of a kds async wait cancellation ensure the deferred + * call back does not get scheduled if a trigger fired at the same time + * to release the wait. + */ + cancel_work_sync(&rset->callback_work); + + /* free the resource set */ + kfree(rset); +} +EXPORT_SYMBOL(kds_resource_set_release_sync); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION("1.0"); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..ec2c4cc34a3ff701062c2456afe6f0fae0f124cc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/kds/sconscript @@ -0,0 +1,71 @@ +# +# (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +import re +Import('env') + +#Android uses sync_pt to accomplish KDS functionality. +#Midgard KDS is not used by Android +if env['os'] == 'android': + Return() + +# If KDS is built into the kernel already we skip building the module ourselves +linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' +search_term = '^[\ ]*CONFIG_KDS[\ ]*=[\ ]*y' +build_kds = 1 +for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + # KDS in kernel. Do not build KDS kernel module but + # still allow for building kds_test module. + build_kds = 0 + +if env['v'] != '1': + env['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +src = [Glob('#kernel/drivers/base/kds/*.c'), Glob('#kernel/include/linux/*.h'), Glob('#kernel/drivers/base/kds/K*')] + +env.Append( CPPPATH = '#kernel/include' ) + +if Glob('tests/sconscript'): + SConscript( 'tests/sconscript' ) + +if env.GetOption('clean') : + # Clean KDS module + if build_kds: + env.Execute(Action("make clean", '[CLEAN] kds')) + cmd = env.Command('$STATIC_LIB_PATH/kds.ko', src, []) + env.ProgTarget('kds', cmd) + + # Clean KDS test module + if (int(env['unit']) == 1): + cmdTest = env.Command('$STATIC_LIB_PATH/kds_test.ko', src, []) + env.ProgTarget('kds', cmdTest) +else: + # Build KDS module + if build_kds: + makeAction=Action("cd ${SOURCE.dir} && make kds && cp kds.ko $STATIC_LIB_PATH/", '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/kds.ko', src, [makeAction]) + env.ProgTarget('kds', cmd) + + # Build KDS test module + if int(env['unit']) == 1: + makeActionTest=Action("cd ${SOURCE.dir} && make kds_test && cp kds_test.ko $STATIC_LIB_PATH/", '$MAKECOMSTR') + cmdTest = env.Command('$STATIC_LIB_PATH/kds_test.ko', src, [makeActionTest]) + env.ProgTarget('kds', cmdTest) + if build_kds: + Depends(cmdTest, cmd) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..55b8399922b12284410cfe8f2784f6145dd4dc06 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/sconscript @@ -0,0 +1,28 @@ +# +# (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +if Glob('dma_buf_lock/sconscript'): + SConscript('dma_buf_lock/sconscript') + +if Glob('kds/sconscript'): + SConscript('kds/sconscript') + +if Glob('ump/sconscript'): + SConscript('ump/sconscript') + +if Glob('dma_buf_test_exporter/sconscript'): + SConscript('dma_buf_test_exporter/sconscript') + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..2bbdba27d76f16b0c36d5ac9989ef9219dcbddcd --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +obj-y += src/ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..f7451e67a5ee8a627061382f07e758e848ac8de2 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/Kconfig @@ -0,0 +1,26 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +config UMP + tristate "Enable Unified Memory Provider (UMP) support" + default n + help + Enable this option to build support for the ARM UMP module. + UMP can be used by the Mali T6xx module to improve performance + by reducing the copying of data by sharing memory. + + To compile this driver as a module, choose M here: + this will generate one module, called ump. diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/docs/Doxyfile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/docs/Doxyfile new file mode 100755 index 0000000000000000000000000000000000000000..fbec8eb40a02d90ce232386a28d88e3990fd6db6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/docs/Doxyfile @@ -0,0 +1,125 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +############################################################################## + +# This file contains per-module Doxygen configuration. Please do not add +# extra settings to this file without consulting all stakeholders, as they +# may cause override project-wide settings. +# +# Additionally, when defining aliases, macros, sections etc, use the module +# name as a prefix e.g. gles_my_alias. + +############################################################################## + +@INCLUDE = ../../bldsys/Doxyfile_common + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT += ../../kernel/include/linux/ump-common.h ../../kernel/include/linux/ump.h + +############################################################################## +# Everything below here is optional, and in most cases not required +############################################################################## + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES += + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS += + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS += + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE += + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS += + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS += + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH += ../../kernel/drivers/base/ump + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH += + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH += + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED += + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED += + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS += diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/docs/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/docs/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..521278d138bd460ea609429fcf8a896b674406fb --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/docs/sconscript @@ -0,0 +1,31 @@ +# +# (C) COPYRIGHT 2010-2011, 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +Import('env') + +doxygen_sources = [ + 'Doxyfile', + Glob('*.png'), + Glob('../*.h'), + Glob('../src/*.h') ] + +if env['doc'] == '1': + doxygen_target = env.Command('doxygen/html/index.html', doxygen_sources, + ['cd ${SOURCE.dir} && doxygen']) + env.Clean(doxygen_target, './doxygen') + + Alias('doxygen', doxygen_target) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/example_kernel_api.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/example_kernel_api.c new file mode 100644 index 0000000000000000000000000000000000000000..eb9b12930f8ac9d77523247912b4ab4cfd11ffbe --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/example_kernel_api.c @@ -0,0 +1,73 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +#include +#include + +/* + * Example routine to display information about an UMP allocation + * The routine takes an secure_id which can come from a different kernel module + * or from a client application (i.e. an ioctl). + * It creates a ump handle from the secure id (which validates the secure id) + * and if successful dumps the physical memory information. + * It follows the API and pins the memory while "using" the physical memory. + * Finally it calls the release function to indicate it's finished with the handle. + * + * If the function can't look up the handle it fails with return value -1. + * If the testy succeeds then it return 0. + * */ + +static int display_ump_memory_information(ump_secure_id secure_id) +{ + const ump_dd_physical_block_64 * ump_blocks = NULL; + ump_dd_handle ump_mem; + uint64_t nr_blocks; + int i; + ump_alloc_flags flags; + + /* get a handle from the secure id */ + ump_mem = ump_dd_from_secure_id(secure_id); + + if (UMP_DD_INVALID_MEMORY_HANDLE == ump_mem) + { + /* invalid ID received */ + return -1; + } + + /* at this point we know we've added a reference to the ump allocation, so we must release it with ump_dd_release */ + + ump_dd_phys_blocks_get_64(ump_mem, &nr_blocks, &ump_blocks); + flags = ump_dd_allocation_flags_get(ump_mem); + + printf("UMP allocation with secure ID %u consists of %zd physical block(s):\n", secure_id, nr_blocks); + + for(i=0; i +#include +#include + +/* + * Example routine to exercise the user space UMP api. + * This routine initializes the UMP api and allocates some CPU+device X memory. + * No usage hints are given, so the driver will use the default cacheability policy. + * With the allocation it creates a duplicate handle and plays with the reference count. + * Then it simulates interacting with a device and contains pseudo code for the device. + * + * If any error is detected correct cleanup will be performed and -1 will be returned. + * If successful then 0 will be returned. + */ + +static int test_ump_user_api(void) +{ + /* This is the size we try to allocate*/ + const size_t alloc_size = 4096; + + ump_handle h = UMP_INVALID_MEMORY_HANDLE; + ump_handle h_copy = UMP_INVALID_MEMORY_HANDLE; + ump_handle h_clone = UMP_INVALID_MEMORY_HANDLE; + + void * mapping = NULL; + + ump_result ump_api_res; + int result = -1; + + ump_secure_id id; + + size_t size_returned; + + ump_api_res = ump_open(); + if (UMP_OK != ump_api_res) + { + /* failed to open an ump session */ + /* early out */ + return -1; + } + + h = ump_allocate_64(alloc_size, UMP_PROT_CPU_RD | UMP_PROT_CPU_WR | UMP_PROT_X_RD | UMP_PROT_X_WR); + /* the refcount is now 1 */ + if (UMP_INVALID_MEMORY_HANDLE == h) + { + /* allocation failure */ + goto cleanup; + } + + /* this is how we could share this allocation with another process */ + + /* in process A: */ + id = ump_secure_id_get(h); + /* still ref count 1 */ + /* send the id to process B */ + + /* in process B: */ + /* receive the id from A */ + h_clone = ump_from_secure_id(id); + /* the ref count of the allocation is now 2 (one from each handle to it) */ + /* do something ... */ + /* release our clone */ + ump_release(h_clone); /* safe to call even if ump_from_secure_id failed */ + h_clone = UMP_INVALID_MEMORY_HANDLE; + + + /* a simple save-for-future-use logic inside the driver would just copy the handle (but add a ref manually too!) */ + /* + * void assign_memory_to_job(h) + * { + */ + h_copy = h; + ump_retain(h_copy); /* manual retain needed as we just assigned the handle, now 2 */ + /* + * } + * + * void job_completed(void) + * { + */ + ump_release(h_copy); /* normal handle release as if we got via an ump_allocate */ + h_copy = UMP_INVALID_MEMORY_HANDLE; + /* + * } + */ + + /* we're now back at ref count 1, and only h is a valid handle */ + /* enough handle duplication show-off, let's play with the contents instead */ + + mapping = ump_map(h, 0, alloc_size); + if (NULL == mapping) + { + /* mapping failure, either out of address space or some other error */ + goto cleanup; + } + + memset(mapping, 0, alloc_size); + + /* let's pretend we're going to start some hw device on this buffer and read the result afterwards */ + ump_cpu_msync_now(h, UMP_MSYNC_CLEAN, mapping, alloc_size); + /* + device cache invalidate + + memory barrier + + start device + + memory barrier + + wait for device + + memory barrier + + device cache clean + + memory barrier + */ + ump_cpu_msync_now(h, UMP_MSYNC_CLEAN_AND_INVALIDATE, mapping, alloc_size); + + /* we could now peek at the result produced by the hw device, which is now accessible via our mapping */ + + /* unmap the buffer when we're done with it */ + ump_unmap(h, mapping, alloc_size); + + result = 0; + +cleanup: + ump_release(h); + h = UMP_INVALID_MEMORY_HANDLE; + + ump_close(); + + return result; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..b4aa8b6853a52c6e821f03f6b13ff079bd186b7a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/sconscript @@ -0,0 +1,21 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +Import('env') + +if Glob('src/sconscript') and int(env['ump']) == 1: + SConscript( 'src/sconscript' ) + SConscript( 'docs/sconscript' ) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..de6d30770d154d64b53e5003ed67bec19c182ac4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Kbuild @@ -0,0 +1,50 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +# Paths required for build +UMP_PATH = $(src)/../.. +UMP_DEVICEDRV_PATH = $(src)/. + +# Set up defaults if not defined by the user +MALI_UNIT_TEST ?= 0 + +SRC :=\ + common/ump_kernel_core.c \ + common/ump_kernel_descriptor_mapping.c \ + linux/ump_kernel_linux.c \ + linux/ump_kernel_linux_mem.c + +UNIT_TEST_DEFINES= +ifeq ($(MALI_UNIT_TEST), 1) + MALI_DEBUG ?= 1 + + UNIT_TEST_DEFINES = -DMALI_UNIT_TEST=1 \ + -DMALI_DEBUG=$(MALI_DEBUG) +endif + +# Use our defines when compiling +ccflags-y += -I$(UMP_PATH) -I$(UMP_DEVICEDRV_PATH) $(UNIT_TEST_DEFINES) + + +# Tell the Linux build system from which .o file to create the kernel module +obj-$(CONFIG_UMP) += ump.o +ifeq ($(CONFIG_ION),y) +ccflags-y += -I$(srctree)/drivers/staging/android/ion -I$(srctree)/include/linux +obj-$(CONFIG_UMP) += imports/ion/ump_kernel_import_ion.o +endif + +# Tell the Linux build system to enable building of our .c files +ump-y := $(SRC:.c=.o) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..45428adbdf77bb5ae7d52d675e32c557ab8ca182 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Makefile @@ -0,0 +1,81 @@ +# +# (C) COPYRIGHT 2008-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +ifneq ($(KBUILD_EXTMOD),) +include $(KBUILD_EXTMOD)/Makefile.common +else +include ./Makefile.common +endif + +# default to building for the host +ARCH ?= $(shell uname -m) + +# linux build system integration +RELATIVE_ROOT=../../../../.. +ROOT = $(CURDIR)/$(RELATIVE_ROOT) + +EXTRA_CFLAGS=-I$(CURDIR)/../../../../include + +ifeq ($(MALI_UNIT_TEST),1) + EXTRA_CFLAGS += -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) +endif + +# Get any user defined KDIR- or maybe even a hardcoded KDIR +-include KDIR_CONFIGURATION + +# Define host system directory +KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build + +CONFIG ?= $(ARCH) + +# default cpu to select +CPU ?= $(shell uname -m) + +# look up KDIR based om CPU selection +KDIR ?= $(KDIR-$(CPU)) + +ifeq ($(KDIR),) +$(error No KDIR found for platform $(CPU)) +endif + +# Validate selected config +ifneq ($(shell [ -d arch-$(CONFIG) ] && [ -f arch-$(CONFIG)/config.h ] && echo "OK"), OK) +$(warning Current directory is $(shell pwd)) +$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists) +else +# Link arch to the selected arch-config directory +$(shell [ -L arch ] && rm arch) +$(shell ln -sf arch-$(CONFIG) arch) +$(shell touch arch/config.h) +endif + +EXTRA_SYMBOLS= + +ifeq ($(MALI_UNIT_TEST),1) + KBASE_PATH=$(ROOT)/kernel/drivers/gpu/arm/midgard + EXTRA_SYMBOLS+=$(KBASE_PATH)/tests/internal/src/kernel_assert_module/linux/Module.symvers +endif +KDS_PATH=$(ROOT)/kernel/drivers/base/kds +EXTRA_SYMBOLS+=$(KDS_PATH)/Module.symvers + +all: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="$(EXTRA_CFLAGS) $(SCONS_CFLAGS)" CONFIG_UMP=m KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules + +kernelrelease: + $(MAKE) -C $(KDIR) KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" kernelrelease + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Makefile.common b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Makefile.common new file mode 100755 index 0000000000000000000000000000000000000000..f29a4c1cffa5a04c704e292fd16ca1cb38a25153 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/Makefile.common @@ -0,0 +1,19 @@ +# +# (C) COPYRIGHT 2008-2010, 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +SRC = $(UMP_FILE_PREFIX)/common/ump_kernel_core.c \ + $(UMP_FILE_PREFIX)/common/ump_kernel_descriptor_mapping.c + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/arch-arm/config.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/arch-arm/config.h new file mode 100644 index 0000000000000000000000000000000000000000..afb44d6cb74511ef6002528141496a1f4f3e6b1c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/arch-arm/config.h @@ -0,0 +1,27 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +#define ARCH_UMP_BACKEND_DEFAULT 1 +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x00000000 +#define ARCH_UMP_MEMORY_SIZE_DEFAULT 32UL * 1024UL * 1024UL + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/arch-arm64/config.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/arch-arm64/config.h new file mode 100644 index 0000000000000000000000000000000000000000..afb44d6cb74511ef6002528141496a1f4f3e6b1c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/arch-arm64/config.h @@ -0,0 +1,27 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +#define ARCH_UMP_BACKEND_DEFAULT 1 +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x00000000 +#define ARCH_UMP_MEMORY_SIZE_DEFAULT 32UL * 1024UL * 1024UL + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_core.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_core.c new file mode 100644 index 0000000000000000000000000000000000000000..7bbef009ca4ad79915d5a905c843b552741b0fa8 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_core.c @@ -0,0 +1,756 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* module headers */ +#include +#include + +/* local headers */ +#include +#include +#include +#include + +#define UMP_FLAGS_RANGE ((UMP_PROT_SHAREABLE<<1) - 1u) + +static umpp_device device; + +ump_result umpp_core_constructor(void) +{ + mutex_init(&device.secure_id_map_lock); + device.secure_id_map = umpp_descriptor_mapping_create(UMP_EXPECTED_IDS, UMP_MAX_IDS); + if (NULL != device.secure_id_map) + { + if (UMP_OK == umpp_device_initialize()) + { + return UMP_OK; + } + umpp_descriptor_mapping_destroy(device.secure_id_map); + } + mutex_destroy(&device.secure_id_map_lock); + + return UMP_ERROR; +} + +void umpp_core_destructor(void) +{ + umpp_device_terminate(); + umpp_descriptor_mapping_destroy(device.secure_id_map); + mutex_destroy(&device.secure_id_map_lock); +} + +umpp_session *umpp_core_session_start(void) +{ + umpp_session * session; + + session = kzalloc(sizeof(*session), GFP_KERNEL); + if (NULL != session) + { + mutex_init(&session->session_lock); + + INIT_LIST_HEAD(&session->memory_usage); + + /* try to create import client session, not a failure if they fail to initialize */ + umpp_import_handlers_init(session); + } + + return session; +} + +void umpp_core_session_end(umpp_session *session) +{ + umpp_session_memory_usage * usage, *_usage; + UMP_ASSERT(session); + + list_for_each_entry_safe(usage, _usage, &session->memory_usage, link) + { + pr_debug("UMP: Memory usage cleanup, releasing secure ID %d\n", ump_dd_secure_id_get(usage->mem)); + ump_dd_release(usage->mem); + kfree(usage); + + } + + /* we should now not hold any imported memory objects, + * detatch all import handlers */ + umpp_import_handlers_term(session); + + mutex_destroy(&session->session_lock); + kfree(session); +} + +ump_dd_handle ump_dd_allocate_64(uint64_t size, ump_alloc_flags flags, ump_dd_security_filter filter_func, ump_dd_final_release_callback final_release_func, void* callback_data) +{ + umpp_allocation * alloc; + int i; + + UMP_ASSERT(size); + + if (flags & (~UMP_FLAGS_RANGE)) + { + pr_debug("UMP: allocation flags out of allowed bits range\n"); + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + if( ( flags & (UMP_PROT_CPU_RD | UMP_PROT_W_RD | UMP_PROT_X_RD | UMP_PROT_Y_RD | UMP_PROT_Z_RD ) ) == 0 || + ( flags & (UMP_PROT_CPU_WR | UMP_PROT_W_WR | UMP_PROT_X_WR | UMP_PROT_Y_WR | UMP_PROT_Z_WR )) == 0 ) + { + pr_debug("UMP: allocation flags should have at least one read and one write permission bit set\n"); + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + /*check permission flags to be set if hit flags are set too*/ + for (i = UMP_DEVICE_CPU_SHIFT; i<=UMP_DEVICE_Z_SHIFT; i+=4) + { + if (flags & (UMP_HINT_DEVICE_RD<flags = flags; + alloc->filter_func = filter_func; + alloc->final_release_func = final_release_func; + alloc->callback_data = callback_data; + alloc->size = size; + + mutex_init(&alloc->map_list_lock); + INIT_LIST_HEAD(&alloc->map_list); + atomic_set(&alloc->refcount, 1); + +#ifdef CONFIG_KDS + kds_resource_init(&alloc->kds_res); +#endif + + if (!(alloc->flags & UMP_PROT_SHAREABLE)) + { + alloc->owner = get_current()->pid; + } + + if (0 != umpp_phys_commit(alloc)) + { + goto out2; + } + + /* all set up, allocate an ID for it */ + + mutex_lock(&device.secure_id_map_lock); + alloc->id = umpp_descriptor_mapping_allocate(device.secure_id_map, (void*)alloc); + mutex_unlock(&device.secure_id_map_lock); + + if ((int)alloc->id == 0) + { + /* failed to allocate a secure_id */ + goto out3; + } + + return alloc; + +out3: + umpp_phys_free(alloc); +out2: + kfree(alloc); +out1: + return UMP_DD_INVALID_MEMORY_HANDLE; +} + +uint64_t ump_dd_size_get_64(const ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + return alloc->size; +} + +/* + * UMP v1 API + */ +unsigned long ump_dd_size_get(ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + UMP_ASSERT(alloc->flags & UMP_CONSTRAINT_32BIT_ADDRESSABLE); + UMP_ASSERT(alloc->size <= UMP_UINT32_MAX); + + return (unsigned long)alloc->size; +} + +ump_secure_id ump_dd_secure_id_get(const ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + return alloc->id; +} + +#ifdef CONFIG_KDS +struct kds_resource * ump_dd_kds_resource_get(const ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + return &alloc->kds_res; +} +#endif + +ump_alloc_flags ump_dd_allocation_flags_get(const ump_dd_handle mem) +{ + const umpp_allocation * alloc; + + UMP_ASSERT(mem); + alloc = (const umpp_allocation *)mem; + + return alloc->flags; +} + +ump_dd_handle ump_dd_from_secure_id(ump_secure_id secure_id) +{ + umpp_allocation * alloc = UMP_DD_INVALID_MEMORY_HANDLE; + + mutex_lock(&device.secure_id_map_lock); + + if (0 == umpp_descriptor_mapping_lookup(device.secure_id_map, secure_id, (void**)&alloc)) + { + if (NULL != alloc->filter_func) + { + if (!alloc->filter_func(secure_id, alloc, alloc->callback_data)) + { + alloc = UMP_DD_INVALID_MEMORY_HANDLE; /* the filter denied access */ + } + } + + /* check permission to access it */ + if ((UMP_DD_INVALID_MEMORY_HANDLE != alloc) && !(alloc->flags & UMP_PROT_SHAREABLE)) + { + if (alloc->owner != get_current()->pid) + { + alloc = UMP_DD_INVALID_MEMORY_HANDLE; /*no rights for the current process*/ + } + } + + if (UMP_DD_INVALID_MEMORY_HANDLE != alloc) + { + if( ump_dd_retain(alloc) != UMP_DD_SUCCESS) + { + alloc = UMP_DD_INVALID_MEMORY_HANDLE; + } + } + } + mutex_unlock(&device.secure_id_map_lock); + + return alloc; +} + +/* + * UMP v1 API + */ +ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id) +{ + return ump_dd_from_secure_id(secure_id); +} + +int ump_dd_retain(ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + /* check for overflow */ + while(1) + { + int refcnt = atomic_read(&alloc->refcount); + if (refcnt + 1 > 0) + { + if(atomic_cmpxchg(&alloc->refcount, refcnt, refcnt + 1) == refcnt) + { + return 0; + } + } + else + { + return -EBUSY; + } + } +} + +/* + * UMP v1 API + */ +void ump_dd_reference_add(ump_dd_handle mem) +{ + ump_dd_retain(mem); +} + + +void ump_dd_release(ump_dd_handle mem) +{ + umpp_allocation * alloc; + uint32_t new_cnt; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + /* secure the id for lookup while releasing */ + mutex_lock(&device.secure_id_map_lock); + + /* do the actual release */ + new_cnt = atomic_sub_return(1, &alloc->refcount); + if (0 == new_cnt) + { + /* remove from the table as this was the last ref */ + umpp_descriptor_mapping_remove(device.secure_id_map, alloc->id); + } + + /* release the lock as early as possible */ + mutex_unlock(&device.secure_id_map_lock); + + if (0 != new_cnt) + { + /* exit if still have refs */ + return; + } + + UMP_ASSERT(list_empty(&alloc->map_list)); + +#ifdef CONFIG_KDS + if (kds_resource_term(&alloc->kds_res)) + { + pr_err("ump_dd_release: kds_resource_term failed," + "unable to release UMP allocation\n"); + return; + } +#endif + /* cleanup */ + if (NULL != alloc->final_release_func) + { + alloc->final_release_func(alloc, alloc->callback_data); + } + + if (0 == (alloc->management_flags & UMP_MGMT_EXTERNAL)) + { + umpp_phys_free(alloc); + } + else + { + kfree(alloc->block_array); + } + + mutex_destroy(&alloc->map_list_lock); + + kfree(alloc); +} + +/* + * UMP v1 API + */ +void ump_dd_reference_release(ump_dd_handle mem) +{ + ump_dd_release(mem); +} + +void ump_dd_phys_blocks_get_64(const ump_dd_handle mem, uint64_t * const pCount, const ump_dd_physical_block_64 ** const pArray) +{ + const umpp_allocation * alloc; + UMP_ASSERT(pCount); + UMP_ASSERT(pArray); + UMP_ASSERT(mem); + alloc = (const umpp_allocation *)mem; + *pCount = alloc->blocksCount; + *pArray = alloc->block_array; +} + +/* + * UMP v1 API + */ +ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block * const blocks, unsigned long num_blocks) +{ + const umpp_allocation * alloc; + unsigned long i; + UMP_ASSERT(mem); + UMP_ASSERT(blocks); + UMP_ASSERT(num_blocks); + + alloc = (const umpp_allocation *)mem; + + UMP_ASSERT(alloc->flags & UMP_CONSTRAINT_32BIT_ADDRESSABLE); + + if((uint64_t)num_blocks != alloc->blocksCount) + { + return UMP_DD_INVALID; + } + + for( i = 0; i < num_blocks; i++) + { + UMP_ASSERT(alloc->block_array[i].addr <= UMP_UINT32_MAX); + UMP_ASSERT(alloc->block_array[i].size <= UMP_UINT32_MAX); + + blocks[i].addr = (unsigned long)alloc->block_array[i].addr; + blocks[i].size = (unsigned long)alloc->block_array[i].size; + } + + return UMP_DD_SUCCESS; +} +/* + * UMP v1 API + */ +ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block * const block) +{ + const umpp_allocation * alloc; + UMP_ASSERT(mem); + UMP_ASSERT(block); + alloc = (const umpp_allocation *)mem; + + UMP_ASSERT(alloc->flags & UMP_CONSTRAINT_32BIT_ADDRESSABLE); + + UMP_ASSERT(alloc->block_array[index].addr <= UMP_UINT32_MAX); + UMP_ASSERT(alloc->block_array[index].size <= UMP_UINT32_MAX); + + block->addr = (unsigned long)alloc->block_array[index].addr; + block->size = (unsigned long)alloc->block_array[index].size; + + return UMP_DD_SUCCESS; +} + +/* + * UMP v1 API + */ +unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem) +{ + const umpp_allocation * alloc; + UMP_ASSERT(mem); + alloc = (const umpp_allocation *)mem; + + UMP_ASSERT(alloc->flags & UMP_CONSTRAINT_32BIT_ADDRESSABLE); + UMP_ASSERT(alloc->blocksCount <= UMP_UINT32_MAX); + + return (unsigned long)alloc->blocksCount; +} + +umpp_cpu_mapping * umpp_dd_find_enclosing_mapping(umpp_allocation * alloc, void *uaddr, size_t size) +{ + umpp_cpu_mapping *map; + + void *target_first = uaddr; + void *target_last = (void*)((uintptr_t)uaddr - 1 + size); + + if (target_last < target_first) /* wrapped */ + { + return NULL; + } + + mutex_lock(&alloc->map_list_lock); + list_for_each_entry(map, &alloc->map_list, link) + { + if ( map->vaddr_start <= target_first && + (void*)((uintptr_t)map->vaddr_start + (map->nr_pages << PAGE_SHIFT) - 1) >= target_last) + { + goto out; + } + } + map = NULL; +out: + mutex_unlock(&alloc->map_list_lock); + + return map; +} + +void umpp_dd_add_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * map) +{ + UMP_ASSERT(alloc); + UMP_ASSERT(map); + mutex_lock(&alloc->map_list_lock); + list_add(&map->link, &alloc->map_list); + mutex_unlock(&alloc->map_list_lock); +} + +void umpp_dd_remove_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * target) +{ + umpp_cpu_mapping * map; + + UMP_ASSERT(alloc); + UMP_ASSERT(target); + + mutex_lock(&alloc->map_list_lock); + list_for_each_entry(map, &alloc->map_list, link) + { + if (map == target) + { + list_del(&target->link); + kfree(target); + mutex_unlock(&alloc->map_list_lock); + return; + } + } + + /* not found, error */ + UMP_ASSERT(0); +} + +int umpp_dd_find_start_block(const umpp_allocation * alloc, uint64_t offset, uint64_t * const block_index, uint64_t * const block_internal_offset) +{ + uint64_t i; + + for (i = 0 ; i < alloc->blocksCount; i++) + { + if (offset < alloc->block_array[i].size) + { + /* found the block_array element containing this offset */ + *block_index = i; + *block_internal_offset = offset; + return 0; + } + offset -= alloc->block_array[i].size; + } + + return -ENXIO; +} + +void umpp_dd_cpu_msync_now(ump_dd_handle mem, ump_cpu_msync_op op, void * address, size_t size) +{ + umpp_allocation * alloc; + void *vaddr; + umpp_cpu_mapping * mapping; + uint64_t virt_page_off; /* offset of given address from beginning of the virtual mapping */ + uint64_t phys_page_off; /* offset of the virtual mapping from the beginning of the physical buffer */ + uint64_t page_count; /* number of pages to sync */ + uint64_t i; + uint64_t block_idx; + uint64_t block_offset; + uint64_t paddr; + + UMP_ASSERT((UMP_MSYNC_CLEAN == op) || (UMP_MSYNC_CLEAN_AND_INVALIDATE == op)); + + alloc = (umpp_allocation*)mem; + vaddr = (void*)(uintptr_t)address; + + if((alloc->flags & UMP_CONSTRAINT_UNCACHED) != 0) + { + /* mapping is not cached */ + return; + } + + mapping = umpp_dd_find_enclosing_mapping(alloc, vaddr, size); + if (NULL == mapping) + { + pr_debug("UMP: Illegal cache sync address %lx\n", (uintptr_t)vaddr); + return; /* invalid pointer or size causes out-of-bounds */ + } + + /* we already know that address + size don't wrap around as umpp_dd_find_enclosing_mapping didn't fail */ + page_count = ((((((uintptr_t)address + size - 1) & PAGE_MASK) - ((uintptr_t)address & PAGE_MASK))) >> PAGE_SHIFT) + 1; + virt_page_off = (vaddr - mapping->vaddr_start) >> PAGE_SHIFT; + phys_page_off = mapping->page_off; + + if (umpp_dd_find_start_block(alloc, (virt_page_off + phys_page_off) << PAGE_SHIFT, &block_idx, &block_offset)) + { + /* should not fail as a valid mapping was found, so the phys mem must exists */ + pr_debug("UMP: Unable to find physical start block with offset %llx\n", virt_page_off + phys_page_off); + UMP_ASSERT(0); + return; + } + + paddr = alloc->block_array[block_idx].addr + block_offset + (((uintptr_t)vaddr) & ((1u << PAGE_SHIFT)-1)); + + for (i = 0; i < page_count; i++) + { + size_t offset = ((uintptr_t)vaddr) & ((1u << PAGE_SHIFT)-1); + size_t sz = min((size_t)PAGE_SIZE - offset, size); + + /* check if we've overrrun the current block, if so move to the next block */ + if (paddr >= (alloc->block_array[block_idx].addr + alloc->block_array[block_idx].size)) + { + block_idx++; + UMP_ASSERT(block_idx < alloc->blocksCount); + paddr = alloc->block_array[block_idx].addr; + } + + if (UMP_MSYNC_CLEAN == op) + { + ump_sync_to_memory(paddr, vaddr, sz); + } + else /* (UMP_MSYNC_CLEAN_AND_INVALIDATE == op) already validated on entry */ + { + ump_sync_to_cpu(paddr, vaddr, sz); + } + + /* advance to next page */ + vaddr = (void*)((uintptr_t)vaddr + sz); + size -= sz; + paddr += sz; + } +} + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_create_from_phys_blocks_64(const ump_dd_physical_block_64 * blocks, uint64_t num_blocks, ump_alloc_flags flags, ump_dd_security_filter filter_func, ump_dd_final_release_callback final_release_func, void* callback_data) +{ + uint64_t size = 0; + uint64_t i; + umpp_allocation * alloc; + + UMP_ASSERT(blocks); + UMP_ASSERT(num_blocks); + + for (i = 0; i < num_blocks; i++) + { + size += blocks[i].size; + } + UMP_ASSERT(size); + + if (flags & (~UMP_FLAGS_RANGE)) + { + pr_debug("UMP: allocation flags out of allowed bits range\n"); + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + if( ( flags & (UMP_PROT_CPU_RD | UMP_PROT_W_RD | UMP_PROT_X_RD | UMP_PROT_Y_RD | UMP_PROT_Z_RD + | UMP_PROT_CPU_WR | UMP_PROT_W_WR | UMP_PROT_X_WR | UMP_PROT_Y_WR | UMP_PROT_Z_WR )) == 0 ) + { + pr_debug("UMP: allocation flags should have at least one read or write permission bit set\n"); + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + /*check permission flags to be set if hit flags are set too*/ + for (i = UMP_DEVICE_CPU_SHIFT; i<=UMP_DEVICE_Z_SHIFT; i+=4) + { + if (flags & (UMP_HINT_DEVICE_RD<block_array = kzalloc(sizeof(ump_dd_physical_block_64) * num_blocks,__GFP_HARDWALL | GFP_KERNEL); + if (NULL == alloc->block_array) + { + goto out2; + } + + memcpy(alloc->block_array, blocks, sizeof(ump_dd_physical_block_64) * num_blocks); + +#ifdef CONFIG_KDS + kds_resource_init(&alloc->kds_res); +#endif + alloc->size = size; + alloc->blocksCount = num_blocks; + alloc->flags = flags; + alloc->filter_func = filter_func; + alloc->final_release_func = final_release_func; + alloc->callback_data = callback_data; + + if (!(alloc->flags & UMP_PROT_SHAREABLE)) + { + alloc->owner = get_current()->pid; + } + + mutex_init(&alloc->map_list_lock); + INIT_LIST_HEAD(&alloc->map_list); + atomic_set(&alloc->refcount, 1); + + /* all set up, allocate an ID */ + + mutex_lock(&device.secure_id_map_lock); + alloc->id = umpp_descriptor_mapping_allocate(device.secure_id_map, (void*)alloc); + mutex_unlock(&device.secure_id_map_lock); + + if ((int)alloc->id == 0) + { + /* failed to allocate a secure_id */ + goto out3; + } + + alloc->management_flags |= UMP_MGMT_EXTERNAL; + + return alloc; + +out3: + kfree(alloc->block_array); +out2: + kfree(alloc); +out1: + return UMP_DD_INVALID_MEMORY_HANDLE; +} + + +/* + * UMP v1 API + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks) +{ + ump_dd_handle mem; + ump_dd_physical_block_64 *block_64_array; + ump_alloc_flags flags = UMP_V1_API_DEFAULT_ALLOCATION_FLAGS; + unsigned long i; + + UMP_ASSERT(blocks); + UMP_ASSERT(num_blocks); + + block_64_array = kzalloc(num_blocks * sizeof(*block_64_array), __GFP_HARDWALL | GFP_KERNEL); + + if(block_64_array == NULL) + { + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + /* copy physical blocks */ + for( i = 0; i < num_blocks; i++) + { + block_64_array[i].addr = blocks[i].addr; + block_64_array[i].size = blocks[i].size; + } + + mem = ump_dd_create_from_phys_blocks_64(block_64_array, num_blocks, flags, NULL, NULL, NULL); + + kfree(block_64_array); + + return mem; + +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_core.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_core.h new file mode 100644 index 0000000000000000000000000000000000000000..2329c45f0ebe17e150a00cc0a9de70b47eabb87e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_core.h @@ -0,0 +1,228 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_KERNEL_CORE_H_ +#define _UMP_KERNEL_CORE_H_ + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_KDS +#include +#endif +#include +#include + +/* forward decl */ +struct umpp_session; + +/** + * UMP handle metadata. + * Tracks various data about a handle not of any use to user space + */ +typedef enum +{ + UMP_MGMT_EXTERNAL = (1ul << 0) /**< Handle created via the ump_dd_create_from_phys_blocks interface */ + /* (1ul << 31) not to be used */ +} umpp_management_flags; + +/** + * Structure tracking the single global UMP device. + * Holds global data like the ID map + */ +typedef struct umpp_device +{ + struct mutex secure_id_map_lock; /**< Lock protecting access to the map */ + umpp_descriptor_mapping * secure_id_map; /**< Map of all known secure IDs on the system */ +} umpp_device; + +/** + * Structure tracking all memory allocations of a UMP allocation. + * Tracks info about an mapping so we can verify cache maintenace + * operations and help in the unmap cleanup. + */ +typedef struct umpp_cpu_mapping +{ + struct list_head link; /**< link to list of mappings for an allocation */ + void *vaddr_start; /**< CPU VA start of the mapping */ + size_t nr_pages; /**< Size (in pages) of the mapping */ + uint64_t page_off; /**< Offset (in pages) from start of the allocation where the mapping starts */ + ump_dd_handle handle; /**< Which handle this mapping is linked to */ + struct umpp_session * session; /**< Which session created the mapping */ +} umpp_cpu_mapping; + +/** + * Structure tracking UMP allocation. + * Represent a memory allocation with its ID. + * Tracks all needed meta-data about an allocation. + * */ +typedef struct umpp_allocation +{ + ump_secure_id id; /**< Secure ID of the allocation */ + atomic_t refcount; /**< Usage count */ + + ump_alloc_flags flags; /**< Flags for all supported devices */ + uint32_t management_flags; /**< Managment flags tracking */ + + pid_t owner; /**< The process ID owning the memory if not sharable */ + + ump_dd_security_filter filter_func; /**< Hook to verify use, called during retains from new clients */ + ump_dd_final_release_callback final_release_func; /**< Hook called when the last reference is removed */ + void* callback_data; /**< Additional data given to release hook */ + + uint64_t size; /**< Size (in bytes) of the allocation */ + uint64_t blocksCount; /**< Number of physsical blocks the allocation is built up of */ + ump_dd_physical_block_64 * block_array; /**< Array, one entry per block, describing block start and length */ + + struct mutex map_list_lock; /**< Lock protecting the map_list */ + struct list_head map_list; /**< Tracks all CPU VA mappings of this allocation */ + +#ifdef CONFIG_KDS + struct kds_resource kds_res; /**< The KDS resource controlling access to this allocation */ +#endif + + void * backendData; /**< Physical memory backend meta-data */ +} umpp_allocation; + +/** + * Structure tracking use of UMP memory by a session. + * Tracks the use of an allocation by a session so session termination can clean up any outstanding references. + * Also protects agains non-matched release calls from user space. + */ +typedef struct umpp_session_memory_usage +{ + ump_secure_id id; /**< ID being used. For quick look-up */ + ump_dd_handle mem; /**< Handle being used. */ + + /** + * Track how many times has the process retained this handle in the kernel. + * This should usually just be 1(allocated or resolved) or 2(mapped), + * but could be more if someone is playing with the low-level API + * */ + atomic_t process_usage_count; + + struct list_head link; /**< link to other usage trackers for a session */ +} umpp_session_memory_usage; + +/** + * Structure representing a session/client. + * Tracks the UMP allocations being used by this client. + */ +typedef struct umpp_session +{ + struct mutex session_lock; /**< Lock for memory usage manipulation */ + struct list_head memory_usage; /**< list of memory currently being used by the this session */ + void* import_handler_data[UMPP_EXTERNAL_MEM_COUNT]; /**< Import modules per-session data pointer */ +} umpp_session; + +/** + * UMP core setup. + * Called by any OS specific startup function to initialize the common part. + * @return UMP_OK if core initialized correctly, any other value for errors + */ +ump_result umpp_core_constructor(void); + +/** + * UMP core teardown. + * Called by any OS specific unload function to clean up the common part. + */ +void umpp_core_destructor(void); + +/** + * UMP session start. + * Called by any OS specific session handler when a new session is detected + * @return Non-NULL if a matching core session could be set up. NULL on failure + */ +umpp_session *umpp_core_session_start(void); + +/** + * UMP session end. + * Called by any OS specific session handler when a session is ended/terminated. + * @param session The core session object returned by ump_core_session_start + */ +void umpp_core_session_end(umpp_session *session); + +/** + * Find a mapping object (if any) for this allocation. + * Called by any function needing to identify a mapping from a user virtual address. + * Verifies that the whole range to be within a mapping object. + * @param alloc The UMP allocation to find a matching mapping object of + * @param uaddr User mapping address to find the mapping object for + * @param size Length of the mapping + * @return NULL on error (no match found), pointer to mapping object if match found + */ +umpp_cpu_mapping * umpp_dd_find_enclosing_mapping(umpp_allocation * alloc, void* uaddr, size_t size); + +/** + * Register a new mapping of an allocation. + * Called by functions creating a new mapping of an allocation, typically OS specific handlers. + * @param alloc The allocation object which has been mapped + * @param map Info about the mapping + */ +void umpp_dd_add_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * map); + +/** + * Remove and free mapping object from an allocation. + * @param alloc The allocation object to remove the mapping info from + * @param target The mapping object to remove + */ +void umpp_dd_remove_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * target); + +/** + * Helper to find a block in the blockArray which holds a given byte offset. + * @param alloc The allocation object to find the block in + * @param offset Offset (in bytes) from allocation start to find the block of + * @param[out] block_index Pointer to the index of the block matching + * @param[out] block_internal_offset Offset within the returned block of the searched offset + * @return 0 if a matching block was found, any other value for error + */ +int umpp_dd_find_start_block(const umpp_allocation * alloc, uint64_t offset, uint64_t * const block_index, uint64_t * const block_internal_offset); + +/** + * Cache maintenance helper. + * Performs the requested cache operation on the given handle. + * @param mem Allocation handle + * @param op Cache maintenance operation to perform + * @param address User mapping at which to do the operation + * @param size Length (in bytes) of the range to do the operation on + */ +void umpp_dd_cpu_msync_now(ump_dd_handle mem, ump_cpu_msync_op op, void * address, size_t size); + +/** + * Import module session early init. + * Calls session_begin on all installed import modules. + * @param session The core session object to initialized the import handler for + * */ +void umpp_import_handlers_init(umpp_session * session); + +/** + * Import module session cleanup. + * Calls session_end on all import modules bound to the session. + * @param session The core session object to initialized the import handler for + */ +void umpp_import_handlers_term(umpp_session * session); + +#endif /* _UMP_KERNEL_CORE_H_ */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.c new file mode 100644 index 0000000000000000000000000000000000000000..c25f21af790af1519d6cd1dfeb5bb51e4db26262 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.c @@ -0,0 +1,162 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + + +#include +#include + +#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1)) + +/** + * Allocate a descriptor table capable of holding 'count' mappings + * @param count Number of mappings in the table + * @return Pointer to a new table, NULL on error + */ +static umpp_descriptor_table * descriptor_table_alloc(unsigned int count); + +/** + * Free a descriptor table + * @param table The table to free + */ +static void descriptor_table_free(umpp_descriptor_table * table); + +umpp_descriptor_mapping * umpp_descriptor_mapping_create(unsigned int init_entries, unsigned int max_entries) +{ + umpp_descriptor_mapping * map = kzalloc(sizeof(umpp_descriptor_mapping), GFP_KERNEL); + + init_entries = MALI_PAD_INT(init_entries); + max_entries = MALI_PAD_INT(max_entries); + + if (NULL != map) + { + map->table = descriptor_table_alloc(init_entries); + if (NULL != map->table) + { + init_rwsem( &map->lock); + set_bit(0, map->table->usage); + map->max_nr_mappings_allowed = max_entries; + map->current_nr_mappings = init_entries; + return map; + + descriptor_table_free(map->table); + } + kfree(map); + } + return NULL; +} + +void umpp_descriptor_mapping_destroy(umpp_descriptor_mapping * map) +{ + UMP_ASSERT(NULL != map); + descriptor_table_free(map->table); + kfree(map); +} + +unsigned int umpp_descriptor_mapping_allocate(umpp_descriptor_mapping * map, void * target) +{ + int descriptor = 0; + UMP_ASSERT(NULL != map); + down_write( &map->lock); + descriptor = find_first_zero_bit(map->table->usage, map->current_nr_mappings); + if (descriptor == map->current_nr_mappings) + { + /* no free descriptor, try to expand the table */ + umpp_descriptor_table * new_table; + umpp_descriptor_table * old_table = map->table; + int nr_mappings_new = map->current_nr_mappings + BITS_PER_LONG; + + if (map->current_nr_mappings >= map->max_nr_mappings_allowed) + { + descriptor = 0; + goto unlock_and_exit; + } + + new_table = descriptor_table_alloc(nr_mappings_new); + if (NULL == new_table) + { + descriptor = 0; + goto unlock_and_exit; + } + + memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + + map->table = new_table; + map->current_nr_mappings = nr_mappings_new; + descriptor_table_free(old_table); + } + + /* we have found a valid descriptor, set the value and usage bit */ + set_bit(descriptor, map->table->usage); + map->table->mappings[descriptor] = target; + +unlock_and_exit: + up_write(&map->lock); + return descriptor; +} + +int umpp_descriptor_mapping_lookup(umpp_descriptor_mapping * map, unsigned int descriptor, void** const target) +{ + int result = -EINVAL; + UMP_ASSERT(map); + UMP_ASSERT(target); + down_read(&map->lock); + if ( (descriptor > 0) && (descriptor < map->current_nr_mappings) && test_bit(descriptor, map->table->usage) ) + { + *target = map->table->mappings[descriptor]; + result = 0; + } + /* keep target untouched if the descriptor was not found */ + up_read(&map->lock); + return result; +} + +void umpp_descriptor_mapping_remove(umpp_descriptor_mapping * map, unsigned int descriptor) +{ + UMP_ASSERT(map); + down_write(&map->lock); + if ( (descriptor > 0) && (descriptor < map->current_nr_mappings) && test_bit(descriptor, map->table->usage) ) + { + map->table->mappings[descriptor] = NULL; + clear_bit(descriptor, map->table->usage); + } + up_write(&map->lock); +} + +static umpp_descriptor_table * descriptor_table_alloc(unsigned int count) +{ + umpp_descriptor_table * table; + + table = kzalloc(sizeof(umpp_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count), __GFP_HARDWALL | GFP_KERNEL ); + + if (NULL != table) + { + table->usage = (unsigned long*)((u8*)table + sizeof(umpp_descriptor_table)); + table->mappings = (void**)((u8*)table + sizeof(umpp_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG)); + } + + return table; +} + +static void descriptor_table_free(umpp_descriptor_table * table) +{ + UMP_ASSERT(table); + kfree(table); +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.h new file mode 100644 index 0000000000000000000000000000000000000000..3260d52c5945f000954fa3d305749d2743bdbc38 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.h @@ -0,0 +1,94 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file ump_kernel_descriptor_mapping.h + */ + +#ifndef _UMP_KERNEL_DESCRIPTOR_MAPPING_H_ +#define _UMP_KERNEL_DESCRIPTOR_MAPPING_H_ + +#include +#include +/** + * The actual descriptor mapping table, never directly accessed by clients + */ +typedef struct umpp_descriptor_table +{ + /* keep as a unsigned long to rely on the OS's bitops support */ + unsigned long * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used(1) or not(0) */ + void** mappings; /**< Array of the pointers the descriptors map to */ +} umpp_descriptor_table; + +/** + * The descriptor mapping object + * Provides a separate namespace where we can map an integer to a pointer + */ +typedef struct umpp_descriptor_mapping +{ + struct rw_semaphore lock; /**< Lock protecting access to the mapping object */ + unsigned int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */ + unsigned int current_nr_mappings; /**< Current number of possible mappings */ + umpp_descriptor_table * table; /**< Pointer to the current mapping table */ +} umpp_descriptor_mapping; + +/** + * Create a descriptor mapping object. + * Create a descriptor mapping capable of holding init_entries growable to max_entries. + * ID 0 is reserved so the number of available entries will be max - 1. + * @param init_entries Number of entries to preallocate memory for + * @param max_entries Number of entries to max support + * @return Pointer to a descriptor mapping object, NULL on failure + */ +umpp_descriptor_mapping * umpp_descriptor_mapping_create(unsigned int init_entries, unsigned int max_entries); + +/** + * Destroy a descriptor mapping object + * @param[in] map The map to free + */ +void umpp_descriptor_mapping_destroy(umpp_descriptor_mapping * map); + +/** + * Allocate a new mapping entry (descriptor ID) + * Allocates a new entry in the map. + * @param[in] map The map to allocate a new entry in + * @param[in] target The value to map to + * @return The descriptor allocated, ID 0 on failure. + */ +unsigned int umpp_descriptor_mapping_allocate(umpp_descriptor_mapping * map, void * target); + +/** + * Get the value mapped to by a descriptor ID + * @param[in] map The map to lookup the descriptor id in + * @param[in] descriptor The descriptor ID to lookup + * @param[out] target Pointer to a pointer which will receive the stored value + * + * @return 0 on success lookup, -EINVAL on lookup failure. + */ +int umpp_descriptor_mapping_lookup(umpp_descriptor_mapping * map, unsigned int descriptor, void** const target); + +/** + * Free the descriptor ID + * For the descriptor to be reused it has to be freed + * @param[in] map The map to free the descriptor from + * @param descriptor The descriptor ID to free + */ +void umpp_descriptor_mapping_remove(umpp_descriptor_mapping * map, unsigned int descriptor); + +#endif /* _UMP_KERNEL_DESCRIPTOR_MAPPING_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_priv.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..e921193f6fda3460a56487fac6d2a9462ec97f93 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/common/ump_kernel_priv.h @@ -0,0 +1,80 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_KERNEL_PRIV_H_ +#define _UMP_KERNEL_PRIV_H_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#endif + + +#define UMP_EXPECTED_IDS 64 +#define UMP_MAX_IDS 32768 + +#ifdef __KERNEL__ +#define UMP_ASSERT(expr) \ + if (!(expr)) { \ + pr_err("UMP: Assertion failed! %s,%s,%s,line=%d\n",\ + #expr,__FILE__,__func__,__LINE__); \ + BUG(); \ + } + +static inline void ump_sync_to_memory(uint64_t paddr, void* vaddr, size_t sz) +{ +#ifdef CONFIG_ARM + __cpuc_flush_dcache_area(vaddr, sz); + outer_flush_range(paddr, paddr+sz); +#elif defined(CONFIG_ARM64) + /*TODO (MID64-46): There's no other suitable cache flush function for ARM64 */ + flush_cache_all(); +#elif defined(CONFIG_X86) + struct scatterlist scl = {0, }; + sg_set_page(&scl, pfn_to_page(PFN_DOWN(paddr)), sz, + paddr & (PAGE_SIZE -1 )); + dma_sync_sg_for_cpu(NULL, &scl, 1, DMA_TO_DEVICE); + mb(); /* for outer_sync (if needed) */ +#else +#error Implement cache maintenance for your architecture here +#endif +} + +static inline void ump_sync_to_cpu(uint64_t paddr, void* vaddr, size_t sz) +{ +#ifdef CONFIG_ARM + __cpuc_flush_dcache_area(vaddr, sz); + outer_flush_range(paddr, paddr+sz); +#elif defined(CONFIG_ARM64) + /* TODO (MID64-46): There's no other suitable cache flush function for ARM64 */ + flush_cache_all(); +#elif defined(CONFIG_X86) + struct scatterlist scl = {0, }; + sg_set_page(&scl, pfn_to_page(PFN_DOWN(paddr)), sz, + paddr & (PAGE_SIZE -1 )); + dma_sync_sg_for_cpu(NULL, &scl, 1, DMA_FROM_DEVICE); +#else +#error Implement cache maintenance for your architecture here +#endif +} +#endif /* __KERNEL__*/ +#endif /* _UMP_KERNEL_PRIV_H_ */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..ef74b273f7ad3d91642c1d5f2a33436d5b0c9b99 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/Makefile @@ -0,0 +1,53 @@ +# +# (C) COPYRIGHT 2011, 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +# default to building for the host +ARCH ?= $(shell uname -m) + +# linux build system integration + +ifneq ($(KERNELRELEASE),) +# Inside the kernel build system + +EXTRA_CFLAGS += -I$(KBUILD_EXTMOD) -I$(KBUILD_EXTMOD)/../../../../.. +KBUILD_EXTRA_SYMBOLS += "$(KBUILD_EXTMOD)/../../Module.symvers" + +SRC += ump_kernel_import_ion.c + +MODULE:=ump_ion_import.ko + +obj-m := $(MODULE:.ko=.o) +$(MODULE:.ko=-y) := $(SRC:.c=.o) +$(MODULE:.ko=-objs) := $(SRC:.c=.o) + +else +# Outside the kernel build system +# +# + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + +endif + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..749bb1f541f0ea85ff3ca7a4141fe0a6fdebd19b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/sconscript @@ -0,0 +1,52 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +Import('env') + +# Clone the environment so changes don't affect other build files +env_ion = env.Clone() + +if env_ion['ump_ion'] != '1': + Return() + +if env_ion['v'] != '1': + env_ion['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +# Source files required for UMP. +ion_src = [Glob('#kernel/drivers/base/ump/src/imports/ion/*.c')] + +# Note: cleaning via the Linux kernel build system does not yet work +if env_ion.GetOption('clean') : + makeAction=Action("cd ${SOURCE.dir} && make clean", '$MAKECOMSTR') +else: + makeAction=Action("cd ${SOURCE.dir} && make PLATFORM=${platform} && cp ump_ion_import.ko $STATIC_LIB_PATH/ump_ion_import.ko", '$MAKECOMSTR') +# The target is ump_import_ion.ko, built from the source in ion_src, via the action makeAction +# ump_import_ion.ko will be copied to $STATIC_LIB_PATH after being built by the standard Linux +# kernel build system, after which it can be installed to the directory specified if +# "libs_install" is set; this is done by LibTarget. +cmd = env_ion.Command('$STATIC_LIB_PATH/ump_ion_import.ko', ion_src, [makeAction]) + +# Until we fathom out how the invoke the Linux build system to clean, we can use Clean +# to remove generated files. + +patterns = ['*.mod.c', '*.o', '*.ko', '*.a', '.*.cmd', 'modules.order', '.tmp_versions', 'Module.symvers'] + +for p in patterns: + Clean(cmd, Glob('#kernel/drivers/base/ump/src/imports/ion/%s' % p)) + +env_ion.Depends('$STATIC_LIB_PATH/ump_ion_import.ko', '$STATIC_LIB_PATH/ump.ko') +env_ion.ProgTarget('ump', cmd) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/ump_kernel_import_ion.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/ump_kernel_import_ion.c new file mode 100644 index 0000000000000000000000000000000000000000..56dd610ba1c9a66eb20cda7719803b3c8357e200 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/ion/ump_kernel_import_ion.c @@ -0,0 +1,204 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include "ion.h" +#include +#include +#include + +struct ion_wrapping_info +{ + struct ion_client * ion_client; + struct ion_handle * ion_handle; + int num_phys_blocks; + struct scatterlist * sglist; +}; + +static struct ion_device * ion_device_get(void) +{ + /* < Customer to provide implementation > + * Return a pointer to the global ion_device on the system + */ + return NULL; +} + +static int import_ion_client_create(void** const custom_session_data) +{ + struct ion_client ** ion_client; + + ion_client = (struct ion_client**)custom_session_data; + + *ion_client = ion_client_create(ion_device_get(), "ump"); + + return PTR_RET(*ion_client); +} + + +static void import_ion_client_destroy(void* custom_session_data) +{ + struct ion_client * ion_client; + + ion_client = (struct ion_client*)custom_session_data; + BUG_ON(!ion_client); + + ion_client_destroy(ion_client); +} + + +static void import_ion_final_release_callback(const ump_dd_handle handle, void * info) +{ + struct ion_wrapping_info * ion_info; + + BUG_ON(!info); + + (void)handle; + ion_info = (struct ion_wrapping_info*)info; + + dma_unmap_sg(NULL, ion_info->sglist, ion_info->num_phys_blocks, DMA_BIDIRECTIONAL); + + ion_free(ion_info->ion_client, ion_info->ion_handle); + kfree(ion_info); + module_put(THIS_MODULE); +} + +static ump_dd_handle import_ion_import(void * custom_session_data, void * pfd, ump_alloc_flags flags) +{ + int fd; + ump_dd_handle ump_handle; + struct scatterlist * sg; + int num_dma_blocks; + ump_dd_physical_block_64 * phys_blocks; + unsigned long i; + struct sg_table * sgt; + + struct ion_wrapping_info * ion_info; + + BUG_ON(!custom_session_data); + BUG_ON(!pfd); + + ion_info = kzalloc(GFP_KERNEL, sizeof(*ion_info)); + if (NULL == ion_info) + { + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + ion_info->ion_client = (struct ion_client*)custom_session_data; + + if (get_user(fd, (int*)pfd)) + { + goto out; + } + + ion_info->ion_handle = ion_import_dma_buf(ion_info->ion_client, fd); + + if (IS_ERR_OR_NULL(ion_info->ion_handle)) + { + goto out; + } + + sgt = ion_sg_table(ion_info->ion_client, ion_info->ion_handle); + if (IS_ERR_OR_NULL(sgt)) + { + goto ion_dma_map_failed; + } + + ion_info->sglist = sgt->sgl; + + sg = ion_info->sglist; + while (sg) + { + ion_info->num_phys_blocks++; + sg = sg_next(sg); + } + + num_dma_blocks = dma_map_sg(NULL, ion_info->sglist, ion_info->num_phys_blocks, DMA_BIDIRECTIONAL); + + if (0 == num_dma_blocks) + { + goto linux_dma_map_failed; + } + + phys_blocks = vmalloc(num_dma_blocks * sizeof(*phys_blocks)); + if (NULL == phys_blocks) + { + goto vmalloc_failed; + } + + for_each_sg(ion_info->sglist, sg, num_dma_blocks, i) + { + phys_blocks[i].addr = sg_phys(sg); + phys_blocks[i].size = sg_dma_len(sg); + } + + ump_handle = ump_dd_create_from_phys_blocks_64(phys_blocks, num_dma_blocks, flags, NULL, import_ion_final_release_callback, ion_info); + + vfree(phys_blocks); + + if (ump_handle != UMP_DD_INVALID_MEMORY_HANDLE) + { + /* + * As we have a final release callback installed + * we must keep the module locked until + * the callback has been triggered + * */ + __module_get(THIS_MODULE); + return ump_handle; + } + + /* failed*/ +vmalloc_failed: + dma_unmap_sg(NULL, ion_info->sglist, ion_info->num_phys_blocks, DMA_BIDIRECTIONAL); +linux_dma_map_failed: +ion_dma_map_failed: + ion_free(ion_info->ion_client, ion_info->ion_handle); +out: + kfree(ion_info); + return UMP_DD_INVALID_MEMORY_HANDLE; +} + +struct ump_import_handler import_handler_ion = +{ + .linux_module = THIS_MODULE, + .session_begin = import_ion_client_create, + .session_end = import_ion_client_destroy, + .import = import_ion_import +}; + +static int __init import_ion_initialize_module(void) +{ + /* register with UMP */ + return ump_import_module_register(UMP_EXTERNAL_MEM_TYPE_ION, &import_handler_ion); +} + +static void __exit import_ion_cleanup_module(void) +{ + /* unregister import handler */ + ump_import_module_unregister(UMP_EXTERNAL_MEM_TYPE_ION); +} + +/* Setup init and exit functions for this module */ +module_init(import_ion_initialize_module); +module_exit(import_ion_cleanup_module); + +/* And some module information */ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION("1.0"); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..8f506839d1d204624d4cc8f3738b033c3357847a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/imports/sconscript @@ -0,0 +1,25 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os, sys +Import('env') + +import_modules = [ os.path.join( path, 'sconscript' ) for path in sorted(os.listdir( os.getcwd() )) ] + +for m in import_modules: + if os.path.exists(m): + SConscript( m, variant_dir=os.path.join( env['BUILD_DIR_PATH'], os.path.dirname(m) ), duplicate=0 ) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..618587868974c48aa2dfdd594696a953e7985b55 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux.c @@ -0,0 +1,831 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include + +#include /* copy_*_user */ +#include +#include /* kernel module definitions */ +#include /* file system operations */ +#include /* character device definitions */ +#include /* request_mem_region */ +#include /* class registration support */ + +#include + +#include "ump_kernel_linux_mem.h" +#include + + +struct ump_linux_device +{ + struct cdev cdev; + struct class * ump_class; +}; + +/* Name of the UMP device driver */ +static char ump_dev_name[] = "ump"; /* should be const, but the functions we call requires non-cost */ + +/* Module parameter to control log level */ +int ump_debug_level = 2; +module_param(ump_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(ump_debug_level, "Higher number, more dmesg output"); + +/* By default the module uses any available major, but it's possible to set it at load time to a specific number */ +int ump_major = 0; +module_param(ump_major, int, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_major, "Device major number"); + +#define UMP_REV_STRING "1.0" + +char * ump_revision = UMP_REV_STRING; +module_param(ump_revision, charp, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_revision, "Revision info"); + +static int umpp_linux_open(struct inode *inode, struct file *filp); +static int umpp_linux_release(struct inode *inode, struct file *filp); +#ifdef HAVE_UNLOCKED_IOCTL +static long umpp_linux_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +static int umpp_linux_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif + +/* This variable defines the file operations this UMP device driver offers */ +static struct file_operations ump_fops = +{ + .owner = THIS_MODULE, + .open = umpp_linux_open, + .release = umpp_linux_release, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = umpp_linux_ioctl, +#else + .ioctl = umpp_linux_ioctl, +#endif + .compat_ioctl = umpp_linux_ioctl, + .mmap = umpp_linux_mmap +}; + +/* import module handling */ +DEFINE_MUTEX(import_list_lock); +struct ump_import_handler * import_handlers[UMPP_EXTERNAL_MEM_COUNT]; + +/* The global variable containing the global device data */ +static struct ump_linux_device ump_linux_device; + +#define DBG_MSG(level, ...) do { \ +if ((level) <= ump_debug_level)\ +{\ +pr_debug("UMP<" #level ">:\n" __VA_ARGS__);\ +} \ +} while (0) + +#define MSG_ERR(...) do{ \ +pr_err("UMP: ERR: %s\n %s()%4d\n", __FILE__, __func__ , __LINE__) ; \ +pr_err( __VA_ARGS__); \ +pr_err("\n"); \ +} while(0) + +#define MSG(...) do{ \ +pr_debug("UMP: " __VA_ARGS__);\ +} while (0) + +/* + * This function is called by Linux to initialize this module. + * All we do is initialize the UMP device driver. + */ +static int __init umpp_linux_initialize_module(void) +{ + ump_result err; + + err = umpp_core_constructor(); + if (UMP_OK != err) + { + MSG_ERR("UMP device driver init failed\n"); + return -ENOTTY; + } + + MSG("UMP device driver %s loaded\n", UMP_REV_STRING); + return 0; +} + + + +/* + * This function is called by Linux to unload/terminate/exit/cleanup this module. + * All we do is terminate the UMP device driver. + */ +static void __exit umpp_linux_cleanup_module(void) +{ + DBG_MSG(2, "Unloading UMP device driver\n"); + umpp_core_destructor(); + DBG_MSG(2, "Module unloaded\n"); +} + + + +/* + * Initialize the UMP device driver. + */ +ump_result umpp_device_initialize(void) +{ + int err; + dev_t dev = 0; + + if (0 == ump_major) + { + /* auto select a major */ + err = alloc_chrdev_region(&dev, 0, 1, ump_dev_name); + ump_major = MAJOR(dev); + } + else + { + /* use load time defined major number */ + dev = MKDEV(ump_major, 0); + err = register_chrdev_region(dev, 1, ump_dev_name); + } + + if (0 == err) + { + memset(&ump_linux_device, 0, sizeof(ump_linux_device)); + + /* initialize our char dev data */ + cdev_init(&ump_linux_device.cdev, &ump_fops); + ump_linux_device.cdev.owner = THIS_MODULE; + ump_linux_device.cdev.ops = &ump_fops; + + /* register char dev with the kernel */ + err = cdev_add(&ump_linux_device.cdev, dev, 1/*count*/); + if (0 == err) + { + + ump_linux_device.ump_class = class_create(THIS_MODULE, ump_dev_name); + if (IS_ERR(ump_linux_device.ump_class)) + { + err = PTR_ERR(ump_linux_device.ump_class); + } + else + { + struct device * mdev; + mdev = device_create(ump_linux_device.ump_class, NULL, dev, NULL, ump_dev_name); + if (!IS_ERR(mdev)) + { + return UMP_OK; + } + + err = PTR_ERR(mdev); + class_destroy(ump_linux_device.ump_class); + } + cdev_del(&ump_linux_device.cdev); + } + + unregister_chrdev_region(dev, 1); + } + + return UMP_ERROR; +} + + + +/* + * Terminate the UMP device driver + */ +void umpp_device_terminate(void) +{ + dev_t dev = MKDEV(ump_major, 0); + + device_destroy(ump_linux_device.ump_class, dev); + class_destroy(ump_linux_device.ump_class); + + /* unregister char device */ + cdev_del(&ump_linux_device.cdev); + + /* free major */ + unregister_chrdev_region(dev, 1); +} + + +static int umpp_linux_open(struct inode *inode, struct file *filp) +{ + umpp_session *session; + + session = umpp_core_session_start(); + if (NULL == session) + { + return -EFAULT; + } + + filp->private_data = session; + + return 0; +} + +static int umpp_linux_release(struct inode *inode, struct file *filp) +{ + umpp_session *session; + + session = filp->private_data; + + umpp_core_session_end(session); + + filp->private_data = NULL; + + return 0; +} + +/**************************/ +/*ioctl specific functions*/ +/**************************/ +static int do_ump_dd_allocate(umpp_session * session, ump_k_allocate * params) +{ + ump_dd_handle new_allocation; + new_allocation = ump_dd_allocate_64(params->size, params->alloc_flags, NULL, NULL, NULL); + + if (UMP_DD_INVALID_MEMORY_HANDLE != new_allocation) + { + umpp_session_memory_usage * tracker; + + tracker = kmalloc(sizeof(*tracker), GFP_KERNEL | __GFP_HARDWALL); + if (NULL != tracker) + { + /* update the return struct with the new ID */ + params->secure_id = ump_dd_secure_id_get(new_allocation); + + tracker->mem = new_allocation; + tracker->id = params->secure_id; + atomic_set(&tracker->process_usage_count, 1); + + /* link it into the session in-use list */ + mutex_lock(&session->session_lock); + list_add(&tracker->link, &session->memory_usage); + mutex_unlock(&session->session_lock); + + return 0; + } + ump_dd_release(new_allocation); + } + + pr_debug("UMP: Allocation FAILED\n"); + return -ENOMEM; +} + +static int do_ump_dd_retain(umpp_session * session, ump_k_retain * params) +{ + umpp_session_memory_usage * it; + + mutex_lock(&session->session_lock); + + /* try to find it on the session usage list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found to already be in use */ + /* check for overflow */ + while(1) + { + int refcnt = atomic_read(&it->process_usage_count); + if (refcnt + 1 > 0) + { + /* add a process local ref */ + if(atomic_cmpxchg(&it->process_usage_count, refcnt, refcnt + 1) == refcnt) + { + mutex_unlock(&session->session_lock); + return 0; + } + } + else + { + /* maximum usage cap reached */ + mutex_unlock(&session->session_lock); + return -EBUSY; + } + } + } + } + /* try to look it up globally */ + + it = kmalloc(sizeof(*it), GFP_KERNEL); + + if (NULL != it) + { + it->mem = ump_dd_from_secure_id(params->secure_id); + if (UMP_DD_INVALID_MEMORY_HANDLE != it->mem) + { + /* found, add it to the session usage list */ + it->id = params->secure_id; + atomic_set(&it->process_usage_count, 1); + list_add(&it->link, &session->memory_usage); + } + else + { + /* not found */ + kfree(it); + it = NULL; + } + } + + mutex_unlock(&session->session_lock); + + return (NULL != it) ? 0 : -ENODEV; +} + + +static int do_ump_dd_release(umpp_session * session, ump_k_release * params) +{ + umpp_session_memory_usage * it; + int result = -ENODEV; + + mutex_lock(&session->session_lock); + + /* only do a release if found on the session list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found, a valid call */ + result = 0; + + if (0 == atomic_sub_return(1, &it->process_usage_count)) + { + /* last ref in this process remove from the usage list and remove the underlying ref */ + list_del(&it->link); + ump_dd_release(it->mem); + kfree(it); + } + + break; + } + } + mutex_unlock(&session->session_lock); + + return result; +} + +static int do_ump_dd_sizequery(umpp_session * session, ump_k_sizequery * params) +{ + umpp_session_memory_usage * it; + int result = -ENODEV; + + mutex_lock(&session->session_lock); + + /* only valid if found on the session list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found, a valid call */ + params->size = ump_dd_size_get_64(it->mem); + result = 0; + break; + } + + } + mutex_unlock(&session->session_lock); + + return result; +} + +static int do_ump_dd_allocation_flags_get(umpp_session * session, ump_k_allocation_flags * params) +{ + umpp_session_memory_usage * it; + int result = -ENODEV; + + mutex_lock(&session->session_lock); + + /* only valid if found on the session list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found, a valid call */ + params->alloc_flags = ump_dd_allocation_flags_get(it->mem); + result = 0; + break; + } + + } + mutex_unlock(&session->session_lock); + + return result; +} + +static int do_ump_dd_msync_now(umpp_session * session, ump_k_msync * params) +{ + umpp_session_memory_usage * it; + int result = -ENODEV; + + mutex_lock(&session->session_lock); + + /* only valid if found on the session list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found, do the cache op */ +#ifdef CONFIG_COMPAT + if (is_compat_task()) + { + umpp_dd_cpu_msync_now(it->mem, params->cache_operation, compat_ptr(params->mapped_ptr.compat_value), params->size); + result = 0; + } + else + { +#endif + umpp_dd_cpu_msync_now(it->mem, params->cache_operation, params->mapped_ptr.value, params->size); + result = 0; +#ifdef CONFIG_COMPAT + } +#endif + break; + } + } + mutex_unlock(&session->session_lock); + + return result; +} + + +void umpp_import_handlers_init(umpp_session * session) +{ + int i; + mutex_lock(&import_list_lock); + for ( i = 1; i < UMPP_EXTERNAL_MEM_COUNT; i++ ) + { + if (import_handlers[i]) + { + import_handlers[i]->session_begin(&session->import_handler_data[i]); + /* It is OK if session_begin returned an error. + * We won't do any import calls if so */ + } + } + mutex_unlock(&import_list_lock); +} + +void umpp_import_handlers_term(umpp_session * session) +{ + int i; + mutex_lock(&import_list_lock); + for ( i = 1; i < UMPP_EXTERNAL_MEM_COUNT; i++ ) + { + /* only call if session_begin succeeded */ + if (session->import_handler_data[i] != NULL) + { + /* if session_beging succeeded the handler + * should not have unregistered with us */ + BUG_ON(!import_handlers[i]); + import_handlers[i]->session_end(session->import_handler_data[i]); + session->import_handler_data[i] = NULL; + } + } + mutex_unlock(&import_list_lock); +} + +int ump_import_module_register(enum ump_external_memory_type type, struct ump_import_handler * handler) +{ + int res = -EEXIST; + + /* validate input */ + BUG_ON(type == 0 || type >= UMPP_EXTERNAL_MEM_COUNT); + BUG_ON(!handler); + BUG_ON(!handler->linux_module); + BUG_ON(!handler->session_begin); + BUG_ON(!handler->session_end); + BUG_ON(!handler->import); + + mutex_lock(&import_list_lock); + + if (!import_handlers[type]) + { + import_handlers[type] = handler; + res = 0; + } + + mutex_unlock(&import_list_lock); + + return res; +} + +void ump_import_module_unregister(enum ump_external_memory_type type) +{ + BUG_ON(type == 0 || type >= UMPP_EXTERNAL_MEM_COUNT); + + mutex_lock(&import_list_lock); + /* an error to call this if ump_import_module_register didn't succeed */ + BUG_ON(!import_handlers[type]); + import_handlers[type] = NULL; + mutex_unlock(&import_list_lock); +} + +static struct ump_import_handler * import_handler_get(unsigned int type_id) +{ + enum ump_external_memory_type type; + struct ump_import_handler * handler; + + /* validate and convert input */ + /* handle bad data here, not just BUG_ON */ + if (type_id == 0 || type_id >= UMPP_EXTERNAL_MEM_COUNT) + return NULL; + + type = (enum ump_external_memory_type)type_id; + + /* find the handler */ + mutex_lock(&import_list_lock); + + handler = import_handlers[type]; + + if (handler) + { + if (!try_module_get(handler->linux_module)) + { + handler = NULL; + } + } + + mutex_unlock(&import_list_lock); + + return handler; +} + +static void import_handler_put(struct ump_import_handler * handler) +{ + module_put(handler->linux_module); +} + +static int do_ump_dd_import(umpp_session * session, ump_k_import * params) +{ + ump_dd_handle new_allocation = UMP_DD_INVALID_MEMORY_HANDLE; + struct ump_import_handler * handler; + + handler = import_handler_get(params->type); + + if (handler) + { + /* try late binding if not already bound */ + if (!session->import_handler_data[params->type]) + { + handler->session_begin(&session->import_handler_data[params->type]); + } + + /* do we have a bound session? */ + if (session->import_handler_data[params->type]) + { + new_allocation = handler->import( session->import_handler_data[params->type], + params->phandle.value, + params->alloc_flags); + } + + /* done with the handler */ + import_handler_put(handler); + } + + /* did the import succeed? */ + if (UMP_DD_INVALID_MEMORY_HANDLE != new_allocation) + { + umpp_session_memory_usage * tracker; + + tracker = kmalloc(sizeof(*tracker), GFP_KERNEL | __GFP_HARDWALL); + if (NULL != tracker) + { + /* update the return struct with the new ID */ + params->secure_id = ump_dd_secure_id_get(new_allocation); + + tracker->mem = new_allocation; + tracker->id = params->secure_id; + atomic_set(&tracker->process_usage_count, 1); + + /* link it into the session in-use list */ + mutex_lock(&session->session_lock); + list_add(&tracker->link, &session->memory_usage); + mutex_unlock(&session->session_lock); + + return 0; + } + ump_dd_release(new_allocation); + } + + return -ENOMEM; + +} + +#ifdef HAVE_UNLOCKED_IOCTL +static long umpp_linux_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +static int umpp_linux_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + int ret; + uint64_t msg[(UMP_CALL_MAX_SIZE+7)>>3]; /* alignment fixup */ + uint32_t size = _IOC_SIZE(cmd); + struct umpp_session *session = filp->private_data; + +#ifndef HAVE_UNLOCKED_IOCTL + (void)inode; /* unused arg */ +#endif + + /* + * extract the type and number bitfields, and don't decode + * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() + */ + if (_IOC_TYPE(cmd) != UMP_IOC_MAGIC) + { + return -ENOTTY; + + } + if (_IOC_NR(cmd) > UMP_IOC_MAXNR) + { + return -ENOTTY; + } + + switch(cmd) + { + case UMP_FUNC_ALLOCATE: + if (size != sizeof(ump_k_allocate)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_allocate(session, (ump_k_allocate *)&msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + case UMP_FUNC_SIZEQUERY: + if (size != sizeof(ump_k_sizequery)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_sizequery(session,(ump_k_sizequery*) &msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + case UMP_FUNC_MSYNC: + if (size != sizeof(ump_k_msync)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_msync_now(session,(ump_k_msync*) &msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + case UMP_FUNC_IMPORT: + if (size != sizeof(ump_k_import)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user*)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_import(session, (ump_k_import*) &msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + /* used only by v1 API */ + case UMP_FUNC_ALLOCATION_FLAGS_GET: + if (size != sizeof(ump_k_allocation_flags)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_allocation_flags_get(session,(ump_k_allocation_flags*) &msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + case UMP_FUNC_RETAIN: + if (size != sizeof(ump_k_retain)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_retain(session,(ump_k_retain*) &msg); + if (ret) + { + return ret; + } + return 0; + case UMP_FUNC_RELEASE: + if (size != sizeof(ump_k_release)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_release(session,(ump_k_release*) &msg); + if (ret) + { + return ret; + } + return 0; + default: + /* not ours */ + return -ENOTTY; + } + /*redundant below*/ + return -ENOTTY; +} + + +/* Export UMP kernel space API functions */ +EXPORT_SYMBOL(ump_dd_allocate_64); +EXPORT_SYMBOL(ump_dd_allocation_flags_get); +EXPORT_SYMBOL(ump_dd_secure_id_get); +EXPORT_SYMBOL(ump_dd_from_secure_id); +EXPORT_SYMBOL(ump_dd_phys_blocks_get_64); +EXPORT_SYMBOL(ump_dd_size_get_64); +EXPORT_SYMBOL(ump_dd_retain); +EXPORT_SYMBOL(ump_dd_release); +EXPORT_SYMBOL(ump_dd_create_from_phys_blocks_64); +#ifdef CONFIG_KDS +EXPORT_SYMBOL(ump_dd_kds_resource_get); +#endif + +/* import API */ +EXPORT_SYMBOL(ump_import_module_register); +EXPORT_SYMBOL(ump_import_module_unregister); + + + +/* V1 API */ +EXPORT_SYMBOL(ump_dd_handle_create_from_secure_id); +EXPORT_SYMBOL(ump_dd_phys_block_count_get); +EXPORT_SYMBOL(ump_dd_phys_block_get); +EXPORT_SYMBOL(ump_dd_phys_blocks_get); +EXPORT_SYMBOL(ump_dd_size_get); +EXPORT_SYMBOL(ump_dd_reference_add); +EXPORT_SYMBOL(ump_dd_reference_release); +EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); + + +/* Setup init and exit functions for this module */ +module_init(umpp_linux_initialize_module); +module_exit(umpp_linux_cleanup_module); + +/* And some module informatio */ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION(UMP_REV_STRING); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.c new file mode 100644 index 0000000000000000000000000000000000000000..159b56ab37d46455983ad9acadb764495bd18cc3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.c @@ -0,0 +1,250 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include + +#include +#include /* kernel module definitions */ +#include /* file system operations */ +#include /* character device definitions */ +#include /* request_mem_region */ +#include /* memory mananger definitions */ +#include +#include /*kmap*/ + +#include /* is_compat_task */ + +#include +#include +#include + +static void umpp_vm_close(struct vm_area_struct *vma) +{ + umpp_cpu_mapping * mapping; + umpp_session * session; + ump_dd_handle handle; + + mapping = (umpp_cpu_mapping*)vma->vm_private_data; + UMP_ASSERT(mapping); + + session = mapping->session; + handle = mapping->handle; + + umpp_dd_remove_cpu_mapping(mapping->handle, mapping); /* will free the mapping object */ + ump_dd_release(handle); +} + + +static const struct vm_operations_struct umpp_vm_ops = { + .close = umpp_vm_close +}; + +int umpp_phys_commit(umpp_allocation * alloc) +{ + uint64_t i; + + /* round up to a page boundary */ + alloc->size = (alloc->size + PAGE_SIZE - 1) & ~((uint64_t)PAGE_SIZE-1) ; + /* calculate number of pages */ + alloc->blocksCount = alloc->size >> PAGE_SHIFT; + + if( (sizeof(ump_dd_physical_block_64) * alloc->blocksCount) > ((size_t)-1)) + { + pr_debug("UMP: umpp_phys_commit - trying to allocate more than possible\n"); + return -ENOMEM; + } + + alloc->block_array = kmalloc(sizeof(ump_dd_physical_block_64) * alloc->blocksCount, __GFP_HARDWALL | GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); + if (NULL == alloc->block_array) + { + return -ENOMEM; + } + + for (i = 0; i < alloc->blocksCount; i++) + { + void * mp; + struct page * page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); + if (NULL == page) + { + break; + } + + alloc->block_array[i].addr = page_to_pfn(page) << PAGE_SHIFT; + alloc->block_array[i].size = PAGE_SIZE; + + mp = kmap(page); + if (NULL == mp) + { + __free_page(page); + break; + } + + memset(mp, 0x00, PAGE_SIZE); /* instead of __GFP_ZERO, so we can do cache maintenance */ + ump_sync_to_memory(PFN_PHYS(page_to_pfn(page)), mp, PAGE_SIZE); + kunmap(page); + } + + if (i == alloc->blocksCount) + { + return 0; + } + else + { + uint64_t j; + for (j = 0; j < i; j++) + { + struct page * page; + page = pfn_to_page(alloc->block_array[j].addr >> PAGE_SHIFT); + __free_page(page); + } + + kfree(alloc->block_array); + + return -ENOMEM; + } +} + +void umpp_phys_free(umpp_allocation * alloc) +{ + uint64_t i; + + for (i = 0; i < alloc->blocksCount; i++) + { + __free_page(pfn_to_page(alloc->block_array[i].addr >> PAGE_SHIFT)); + } + + kfree(alloc->block_array); +} + +int umpp_linux_mmap(struct file * filp, struct vm_area_struct * vma) +{ + ump_secure_id id; + ump_dd_handle h; + size_t offset; + int err = -EINVAL; + size_t length = vma->vm_end - vma->vm_start; + + umpp_cpu_mapping * map = NULL; + umpp_session *session = filp->private_data; + + if ( 0 == length ) + { + return -EINVAL; + } + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (NULL == map) + { + WARN_ON(1); + err = -ENOMEM; + goto out; + } + + /* unpack our arg */ +#if defined CONFIG_64BIT && CONFIG_64BIT + if (is_compat_task()) + { +#endif + id = vma->vm_pgoff >> UMP_LINUX_OFFSET_BITS_32; + offset = vma->vm_pgoff & UMP_LINUX_OFFSET_MASK_32; +#if defined CONFIG_64BIT && CONFIG_64BIT + } + else + { + id = vma->vm_pgoff >> UMP_LINUX_OFFSET_BITS_64; + offset = vma->vm_pgoff & UMP_LINUX_OFFSET_MASK_64; + } +#endif + + h = ump_dd_from_secure_id(id); + if (UMP_DD_INVALID_MEMORY_HANDLE != h) + { + uint64_t i; + uint64_t block_idx; + uint64_t block_offset; + uint64_t paddr; + umpp_allocation * alloc; + uint64_t last_byte; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_IO | VM_MIXEDMAP | VM_DONTDUMP; +#else + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO | VM_MIXEDMAP; +#endif + vma->vm_ops = &umpp_vm_ops; + vma->vm_private_data = map; + + alloc = (umpp_allocation*)h; + + if( (alloc->flags & UMP_CONSTRAINT_UNCACHED) != 0) + { + /* cache disabled flag set, disable caching for cpu mappings */ + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + } + + last_byte = length + (offset << PAGE_SHIFT) - 1; + if (last_byte >= alloc->size || last_byte < (offset << PAGE_SHIFT)) + { + goto err_out; + } + + if (umpp_dd_find_start_block(alloc, offset << PAGE_SHIFT, &block_idx, &block_offset)) + { + goto err_out; + } + + paddr = alloc->block_array[block_idx].addr + block_offset; + + for (i = 0; i < (length >> PAGE_SHIFT); i++) + { + /* check if we've overrrun the current block, if so move to the next block */ + if (paddr >= (alloc->block_array[block_idx].addr + alloc->block_array[block_idx].size)) + { + block_idx++; + UMP_ASSERT(block_idx < alloc->blocksCount); + paddr = alloc->block_array[block_idx].addr; + } + + err = vm_insert_mixed(vma, vma->vm_start + (i << PAGE_SHIFT), paddr >> PAGE_SHIFT); + paddr += PAGE_SIZE; + } + + map->vaddr_start = (void*)vma->vm_start; + map->nr_pages = length >> PAGE_SHIFT; + map->page_off = offset; + map->handle = h; + map->session = session; + + umpp_dd_add_cpu_mapping(h, map); + + return 0; + + err_out: + + ump_dd_release(h); + } + + kfree(map); + +out: + + return err; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.h new file mode 100644 index 0000000000000000000000000000000000000000..40dcd30bd3be809c509023714947411975a1f0ce --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_KERNEL_LINUX_MEM_H_ +#define _UMP_KERNEL_LINUX_MEM_H_ + + +int umpp_linux_mmap(struct file * filp, struct vm_area_struct * vma); + +#endif /* _UMP_KERNEL_LINUX_MEM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..1a32127658b1302487adf5ea4863aeeea6dbdbb7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/sconscript @@ -0,0 +1,77 @@ +# +# (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +import re +Import('env') + +# Clone the environment so changes don't affect other build files +env_ump = env.Clone() + +if env_ump['v'] != '1': + env_ump['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +# Source files required for UMP. +ump_src = [Glob('#kernel/drivers/base/ump/src/linux/*.c'), Glob('#kernel/drivers/base/ump/src/common/*.c'), Glob('#kernel/drivers/base/ump/src/imports/*/*.c')] + +env_ump.Append( CPPPATH='#kernel/drivers/base/ump/src/' ) + +# Note: cleaning via the Linux kernel build system does not yet work +if env_ump.GetOption('clean') : + makeAction=Action("cd ${SOURCE.dir}/.. && make clean", '$MAKECOMSTR') +else: + if env['unit'] == '1': + makeAction=Action("cd ${SOURCE.dir}/.. && make MALI_UNIT_TEST=${unit} PLATFORM=${platform} %s && cp ump.ko $STATIC_LIB_PATH/ump.ko" % env.kernel_get_config_defines(), '$MAKECOMSTR') + else: + makeAction=Action("cd ${SOURCE.dir}/.. && make PLATFORM=${platform} %s && cp ump.ko $STATIC_LIB_PATH/ump.ko" % env.kernel_get_config_defines(), '$MAKECOMSTR') +# The target is ump.ko, built from the source in ump_src, via the action makeAction +# ump.ko will be copied to $STATIC_LIB_PATH after being built by the standard Linux +# kernel build system, after which it can be installed to the directory specified if +# "libs_install" is set; this is done by LibTarget. +cmd = env_ump.Command('$STATIC_LIB_PATH/ump.ko', ump_src, [makeAction]) + +if env['unit'] == '1': + env.Depends('$STATIC_LIB_PATH/ump.ko', '$STATIC_LIB_PATH/libosk.a') + +# Add a dependency on kds.ko only when the build is not Android +# Android uses sync_pt instead of Midgard KDS to achieve KDS functionality +# Only necessary when KDS is not built into the kernel. +# +if env['os'] != 'android': + linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' + search_term = '^[\ ]*CONFIG_KDS[\ ]*=[\ ]*y' + kds_in_kernel = 0 + for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + # KDS in kernel. + kds_in_kernel = 1 + if not kds_in_kernel: + env.Depends('$STATIC_LIB_PATH/ump.ko', '$STATIC_LIB_PATH/kds.ko') + +# Until we fathom out how the invoke the Linux build system to clean, we can use Clean +# to remove generated files. + +patterns = ['*.mod.c', '*.o', '*.ko', '*.a', '.*.cmd', 'modules.order', '.tmp_versions', 'Module.symvers'] + +for p in patterns: + Clean(cmd, Glob('#kernel/drivers/base/ump/src/common/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/base/ump/src/linux/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/base/ump/src/%s' % p)) + +env_ump.ProgTarget('ump', cmd) + +SConscript( 'imports/sconscript' ) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/ump_arch.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/ump_arch.h new file mode 100644 index 0000000000000000000000000000000000000000..bbbadabef11ac8a6c05f5d7a0c7310caf119e89e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/src/ump_arch.h @@ -0,0 +1,42 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_ARCH_H_ +#define _UMP_ARCH_H_ + +#include + +/** + * Device specific setup. + * Called by the UMP core code to to host OS/device specific setup. + * Typical use case is device node creation for talking to user space. + * @return UMP_OK on success, any other value on failure + */ +extern ump_result umpp_device_initialize(void); + +/** + * Device specific teardown. + * Undo any things done by ump_device_initialize. + */ +extern void umpp_device_terminate(void); + +extern int umpp_phys_commit(umpp_allocation * alloc); +extern void umpp_phys_free(umpp_allocation * alloc); + +#endif /* _UMP_ARCH_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/ump_ref_drv.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/ump_ref_drv.h new file mode 100644 index 0000000000000000000000000000000000000000..60018326597acf5c4f1315dc17810b4cf92068ad --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/base/ump/ump_ref_drv.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file ump_ref_drv.h + * + * This file contains the link to user space part of the UMP API for usage by MALI 400 gralloc. + * + */ + +#ifndef _UMP_REF_DRV_H_ +#define _UMP_REF_DRV_H_ + +#include + + +#endif /* _UMP_REF_DRV_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..b2480dfba4c6859791bda64a8be2da93085865e5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += arm/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..243e092d189b1bec18b609896f6db932265d2348 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Kbuild @@ -0,0 +1,17 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +CONFIG_MALI_MIDGARD := y + +obj-$(CONFIG_MALI_MIDGARD) += midgard/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..1f30eb541d65256b153abbf1e3b39094571d2650 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Kconfig @@ -0,0 +1,19 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +menu "ARM GPU Configuration" +source "drivers/gpu/arm/midgard/Kconfig" +endmenu diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..590cc4b4b9525abb57a9fada1f05c3147ae4e777 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += midgard/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..5f98e06456de7afe8220e05116ce29d8e167e16e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kbuild @@ -0,0 +1,264 @@ +# +# (C) COPYRIGHT 2012,2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +#MTK port custom Kbuild +#To Add 1.environment variable +include $(src)/Kbuild-mtk-custom-env + +# Driver version string which is returned to userspace via an ioctl +MALI_RELEASE_NAME ?= "r5p0-06rel0" + +# Paths required for build +KBASE_PATH = $(src) +KBASE_PLATFORM_PATH = $(KBASE_PATH)/platform_dummy +UMP_PATH = $(src)/../../../base + +ifeq ($(CONFIG_MALI_ERROR_INJECTION),y) +MALI_ERROR_INJECT_ON = 1 +endif + +# Set up defaults if not defined by build system +MALI_CUSTOMER_RELEASE ?= 1 +MALI_UNIT_TEST ?= 0 +MALI_KERNEL_TEST_API ?= 0 +MALI_ERROR_INJECT_ON ?= 0 +MALI_MOCK_TEST ?= 0 +MALI_COVERAGE ?= 0 +MALI_INSTRUMENTATION_LEVEL ?= 0 +# This workaround is for what seems to be a compiler bug we observed in +# GCC 4.7 on AOSP 4.3. The bug caused an intermittent failure compiling +# the "_Pragma" syntax, where an error message is returned: +# +# "internal compiler error: unspellable token PRAGMA" +# +# This regression has thus far only been seen on the GCC 4.7 compiler bundled +# with AOSP 4.3.0. So this makefile, intended for in-tree kernel builds +# which are not known to be used with AOSP, is hardcoded to disable the +# workaround, i.e. set the define to 0. +MALI_GCC_WORKAROUND_MIDCOM_4598 ?= 0 + +# Set up our defines, which will be passed to gcc +DEFINES = \ + -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \ + -DMALI_KERNEL_TEST_API=$(MALI_KERNEL_TEST_API) \ + -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \ + -DMALI_ERROR_INJECT_ON=$(MALI_ERROR_INJECT_ON) \ + -DMALI_MOCK_TEST=$(MALI_MOCK_TEST) \ + -DMALI_COVERAGE=$(MALI_COVERAGE) \ + -DMALI_INSTRUMENTATION_LEVEL=$(MALI_INSTRUMENTATION_LEVEL) \ + -DMALI_RELEASE_NAME=\"$(MALI_RELEASE_NAME)\" \ + -DMALI_GCC_WORKAROUND_MIDCOM_4598=$(MALI_GCC_WORKAROUND_MIDCOM_4598) + +ifeq ($(KBUILD_EXTMOD),) +# in-tree +DEFINES +=-DMALI_KBASE_THIRDPARTY_PATH=../../$(src)/platform/$(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME) +else +# out-of-tree +DEFINES +=-DMALI_KBASE_THIRDPARTY_PATH=$(src)/platform/$(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME) +endif + +DEFINES += -I$(srctree)/drivers/staging/android + +# Use our defines when compiling +ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(KBASE_PLATFORM_PATH) -I$(UMP_PATH) -I$(srctree)/include/linux +subdir-ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(KBASE_PLATFORM_PATH) -I$(OSK_PATH) -I$(UMP_PATH) -I$(srctree)/include/linux + +SRC := \ + mali_kbase_device.c \ + mali_kbase_cache_policy.c \ + mali_kbase_mem.c \ + mali_kbase_mmu.c \ + mali_kbase_jd.c \ + mali_kbase_jd_debugfs.c \ + mali_kbase_jm.c \ + mali_kbase_cpuprops.c \ + mali_kbase_gpuprops.c \ + mali_kbase_js.c \ + mali_kbase_js_affinity.c \ + mali_kbase_js_ctx_attr.c \ + mali_kbase_event.c \ + mali_kbase_context.c \ + mali_kbase_pm.c \ + mali_kbase_pm_driver.c \ + mali_kbase_pm_metrics.c \ + mali_kbase_pm_ca.c \ + mali_kbase_pm_ca_fixed.c \ + mali_kbase_pm_always_on.c \ + mali_kbase_pm_coarse_demand.c \ + mali_kbase_pm_demand.c \ + mali_kbase_pm_policy.c \ + mali_kbase_config.c \ + mali_kbase_security.c \ + mali_kbase_instr.c \ + mali_kbase_softjobs.c \ + mali_kbase_10969_workaround.c \ + mali_kbase_hw.c \ + mali_kbase_utility.c \ + mali_kbase_debug.c \ + mali_kbase_trace_timeline.c \ + mali_kbase_gpu_memory_debugfs.c \ + mali_kbase_mem_linux.c \ + mali_kbase_core_linux.c \ + mali_kbase_sync.c \ + mali_kbase_sync_user.c \ + mali_kbase_replay.c \ + mali_kbase_mem_profile_debugfs.c \ + mali_kbase_mmu_hw_direct.c \ + mali_kbase_disjoint_events.c \ + mali_kbase_gator_api.c + +ifeq ($(MALI_CUSTOMER_RELEASE),0) +SRC += \ + mali_kbase_pm_ca_random.c \ + mali_kbase_pm_demand_always_powered.c \ + mali_kbase_pm_fast_start.c +endif + +# Job Scheduler Policy: Completely Fair Scheduler +SRC += mali_kbase_js_policy_cfs.c + +ifeq ($(CONFIG_MACH_MANTA),y) + SRC += mali_kbase_mem_alloc_carveout.c +else + SRC += mali_kbase_mem_alloc.c +endif + +# ensure GPL version of malisw gets pulled in +ccflags-y += -I$(KBASE_PATH) + +ifeq ($(CONFIG_MALI_NO_MALI),y) + # Dummy model + SRC += mali_kbase_model_dummy.c + SRC += mali_kbase_model_linux.c + # HW error simulation + SRC += mali_kbase_model_error_generator.c +endif + +ifeq ($(MALI_MOCK_TEST),1) + # Test functionality + SRC += tests/internal/src/mock/mali_kbase_pm_driver_mock.c +endif + +# in-tree/out-of-tree logic needs to be slightly different to determine if a file is present +ifeq ($(KBUILD_EXTMOD),) +# in-tree +MALI_METRICS_PATH = $(srctree)/drivers/gpu/arm/midgard +else +# out-of-tree +MALI_METRICS_PATH = $(KBUILD_EXTMOD) +endif + +# Use vsync metrics example using PL111 driver, if available +ifeq ($(wildcard $(MALI_METRICS_PATH)/mali_kbase_pm_metrics_linux.c),) + SRC += mali_kbase_pm_metrics_dummy.c +else + SRC += mali_kbase_pm_metrics_linux.c +endif + +ifeq ($(CONFIG_MALI_PLATFORM_FAKE),y) + SRC += mali_kbase_platform_fake.c + + ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS),y) + SRC += platform/vexpress/mali_kbase_config_vexpress.c \ + platform/vexpress/mali_kbase_cpu_vexpress.c + ccflags-y += -I$(src)/platform/vexpress + endif + + ifeq ($(CONFIG_MALI_PLATFORM_RTSM_VE),y) + SRC += platform/rtsm_ve/mali_kbase_config_vexpress.c + ccflags-y += -I$(src)/platform/rtsm_ve + endif + + ifeq ($(CONFIG_MALI_PLATFORM_JUNO),y) + SRC += platform/juno/mali_kbase_config_vexpress.c + ccflags-y += -I$(src)/platform/juno + endif + + ifeq ($(CONFIG_MALI_PLATFORM_JUNO_SOC),y) + SRC += platform/juno_soc/mali_kbase_config_juno_soc.c + ccflags-y += -I$(src)/platform/juno_soc + endif + + ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS_1XV7_A57),y) + SRC += platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c + ccflags-y += -I$(src)/platform/vexpress_1xv7_a57 + endif + + ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ),y) + SRC += platform/vexpress_virtex7_40mhz/mali_kbase_config_vexpress.c \ + platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.c + ccflags-y += -I$(src)/platform/vexpress_virtex7_40mhz + endif + + ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS_6XVIRTEX7_10MHZ),y) + SRC += platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c \ + platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c + ccflags-y += -I$(src)/platform/vexpress_6xvirtex7_10mhz + endif + + ifeq ($(CONFIG_MALI_PLATFORM_GOLDFISH),y) + SRC += platform/goldfish/mali_kbase_config_goldfish.c + ccflags-y += -I$(src)/platform/goldfish + endif + + ifeq ($(CONFIG_MALI_PLATFORM_PBX),y) + SRC += platform/pbx/mali_kbase_config_pbx.c + ccflags-y += -I$(src)/platform/pbx + endif + + ifeq ($(CONFIG_MALI_PLATFORM_PANDA),y) + SRC += platform/panda/mali_kbase_config_panda.c + ccflags-y += -I$(src)/platform/panda + endif + + ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y) + # remove begin and end quotes from the Kconfig string type + platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)) + MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name) + ccflags-y += -I$(src)/$(MALI_PLATFORM_THIRDPARTY_DIR) + ifeq ($(CONFIG_MALI_MIDGARD),m) + include $(src)/platform/$(platform_name)/Kbuild + else ifeq ($(CONFIG_MALI_MIDGARD),y) + obj-$(CONFIG_MALI_MIDGARD) += platform/ + endif + endif +endif # CONFIG_MALI_PLATFORM_FAKE=y + +ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y) +# remove begin and end quotes from the Kconfig string type +platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)) +MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name) +ccflags-y += -I$(src)/$(MALI_PLATFORM_THIRDPARTY_DIR) +ifeq ($(CONFIG_MALI_MIDGARD),m) +include $(src)/platform/$(platform_name)/Kbuild +else ifeq ($(CONFIG_MALI_MIDGARD),y) +obj-$(CONFIG_MALI_MIDGARD) += platform/ +endif +endif + +# Tell the Linux build system from which .o file to create the kernel module +obj-$(CONFIG_MALI_MIDGARD) += mali_kbase.o + +# Tell the Linux build system to enable building of our .c files +mali_kbase-y := $(SRC:.c=.o) + +mali_kbase-$(CONFIG_MALI_DEVFREQ) += mali_kbase_devfreq.o +mali_kbase-$(CONFIG_MALI_POWER_ACTOR) += mali_kbase_power_actor.o + +ifneq ($(wildcard $(src)/internal/Kbuild),) +ifeq ($(MALI_CUSTOMER_RELEASE),0) +include $(src)/internal/Kbuild +mali_kbase-y += $(INTERNAL:.c=.o) +endif +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kbuild-mtk-custom-env b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kbuild-mtk-custom-env new file mode 100644 index 0000000000000000000000000000000000000000..31bdfb0a263fa29ba5f3ffade5c3233588210292 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kbuild-mtk-custom-env @@ -0,0 +1,52 @@ +$(info mali MTK evironment) + +#build support for a ARM Mali Midgard GPU +CONFIG_MALI_MIDGARD := y + +#use mt6755 platform +CONFIG_MALI_PLATFORM_THIRDPARTY := n +CONFIG_MALI_PLATFORM_THIRDPARTY_NAME := vexpress + +CONFIG_MALI_PLATFORM_FAKE := y + +CONFIG_MALI_PLATFORM_VEXPRESS := y +CONFIG_MALI_DEBUG := y + +ccflags-y += -DCONFIG_MALI_PLATFORM_FAKE +ccflags-y += -DCONFIG_MALI_MIDGARD_DVFS + +#Add include path for kernel 3.10 +ccflags-y += -I-I$(srctree)/include + +#Add include path for linux sync.h +ccflags-y += -I$(srctree)/drivers/staging/android + +#include clock manager for clock use +#ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/mt6755/include + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/mt6755 + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/gpu/ged/include + +#ifeq ($(CONFIG_MTK_GPU_COMMON_DVFS_SUPPORT),y) +ccflags-y += -DENABLE_COMMON_DVFS +#endif + + +VER:=eng +ifneq ($(strip $(TARGET_BUILD_VARIANT)),) +ifneq ($(strip $(TARGET_BUILD_VARIANT)),eng) +VER:=user +endif +endif + +ccflags-y += -DCONFIG_DEBUG_FS +ccflags-y += -DCONFIG_PROC_FS + +ifeq ($(VER),eng) +ccflags-y += -DCONFIG_MALI_DEBUG +else +ccflags-y += -UCONFIG_MALI_DEBUG +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..852b2b6fb447801e528f809ffc5e17f6a5b453eb --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Kconfig @@ -0,0 +1,193 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +menuconfig MALI_MIDGARD + tristate "Mali Midgard series support" + default n + help + Enable this option to build support for a ARM Mali Midgard GPU. + + To compile this driver as a module, choose M here: + this will generate a single module, called mali_kbase. + +config MALI_GATOR_SUPPORT + bool "Streamline Debug support" + depends on MALI_MIDGARD + default n + help + Adds diagnostic support for use with the ARM Streamline Performance Analyzer. + You will need the Gator device driver already loaded before loading this driver when enabling + Streamline debug support. + +config MALI_MIDGARD_DVFS + bool "Enable DVFS" + depends on MALI_MIDGARD + default n + help + Choose this option to enable DVFS in the Mali Midgard DDK. + +config MALI_MIDGARD_RT_PM + bool "Enable Runtime power management" + depends on MALI_MIDGARD + depends on PM_RUNTIME + default n + help + Choose this option to enable runtime power management in the Mali Midgard DDK. + +config MALI_MIDGARD_ENABLE_TRACE + bool "Enable kbase tracing" + depends on MALI_MIDGARD + default n + help + Enables tracing in kbase. Trace log available through + the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled + +config MALI_MIDGARD_DEBUG_SYS + bool "Enable sysfs for the Mali Midgard DDK " + depends on MALI_MIDGARD && SYSFS + default n + help + Enables sysfs for the Mali Midgard DDK. Set/Monitor the Mali Midgard DDK + +# MALI_EXPERT configuration options + +menuconfig MALI_EXPERT + depends on MALI_MIDGARD + bool "Enable Expert Settings" + default n + help + Enabling this option and modifying the default settings may produce a driver with performance or + other limitations. + +config MALI_DEVFREQ + bool "devfreq support for Mali" + depends on MALI_MIDGARD && PM_DEVFREQ + help + Support devfreq for Mali. + + Using the devfreq framework and, by default, the simpleondemand + governor, the frequency of Mali will be dynamically selected from the + available OPPs. + +config MALI_POWER_ACTOR + bool "Thermal API support for Mali" + depends on MALI_MIDGARD && DEVFREQ_THERMAL && THERMAL_POWER_ACTOR + help + Support the thermal API for Mali. + + This can be used with the power allocator thermal governor to + dynamically allocate the power budget to Mali. + +config MALI_DEBUG_SHADER_SPLIT_FS + bool "Allow mapping of shader cores via sysfs" + depends on MALI_MIDGARD && MALI_MIDGARD_DEBUG_SYS && MALI_EXPERT + default n + help + Select this option to provide a sysfs entry for runtime configuration of shader + core affinity masks. + +config MALI_PLATFORM_FAKE + bool "Enable fake platform device support" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + When you start to work with the Mali Midgard series device driver the platform-specific code of + the Linux kernel for your platform may not be complete. In this situation the kernel device driver + supports creating the platform device outside of the Linux platform-specific code. + Enable this option if would like to use a platform device configuration from within the device driver. + +choice + prompt "Platform configuration" + depends on MALI_MIDGARD && MALI_EXPERT + default MALI_PLATFORM_VEXPRESS + help + Select the SOC platform that contains a Mali Midgard GPU + +config MALI_PLATFORM_VEXPRESS + depends on ARCH_VEXPRESS && (ARCH_VEXPRESS_CA9X4 || ARCH_VEXPRESS_CA15X4) + bool "Versatile Express" +config MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ + depends on ARCH_VEXPRESS && (ARCH_VEXPRESS_CA9X4 || ARCH_VEXPRESS_CA15X4) + bool "Versatile Express w/Virtex7 @ 40Mhz" +config MALI_PLATFORM_GOLDFISH + depends on ARCH_GOLDFISH + bool "Android Goldfish virtual CPU" +config MALI_PLATFORM_PBX + depends on ARCH_REALVIEW && REALVIEW_EB_A9MP && MACH_REALVIEW_PBX + bool "Realview PBX-A9" +config MALI_PLATFORM_THIRDPARTY + bool "Third Party Platform" +endchoice + +config MALI_PLATFORM_THIRDPARTY_NAME + depends on MALI_MIDGARD && MALI_PLATFORM_THIRDPARTY && MALI_EXPERT + string "Third party platform name" + help + Enter the name of a third party platform that is supported. The third part configuration + file must be in midgard/config/tpip/mali_kbase_config_xxx.c where xxx is the name + specified here. + +config MALI_DEBUG + bool "Debug build" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Select this option for increased checking and reporting of errors. + +config MALI_NO_MALI + bool "No Mali" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + This can be used to test the driver in a simulated environment + whereby the hardware is not physically present. If the hardware is physically + present it will not be used. This can be used to test the majority of the + driver without needing actual hardware or for software benchmarking. + All calls to the simulated hardware will complete immediately as if the hardware + completed the task. + +config MALI_ERROR_INJECT + bool "Error injection" + depends on MALI_MIDGARD && MALI_EXPERT && MALI_NO_MALI + default n + help + Enables insertion of errors to test module failure and recovery mechanisms. + +config MALI_TRACE_TIMELINE + bool "Timeline tracing" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Enables timeline tracing through the kernel tracepoint system. + +config MALI_SYSTEM_TRACE + bool "Enable system event tracing support" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Choose this option to enable system trace events for each + kbase event. This is typically used for debugging but has + minimal overhead when not in use. Enable only if you know what + you are doing. + +config MALI_GPU_TRACEPOINTS + bool "Enable GPU tracepoints" + depends on MALI_MIDGARD && ANDROID + select GPU_TRACEPOINTS + help + Enables GPU tracepoints using Android trace event definitions. + +source "drivers/gpu/arm/midgard/platform/Kconfig" diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..9820be2b4446f4e24dc261fa0a1e0295a12efe3b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Makefile @@ -0,0 +1,36 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +KDIR ?= /lib/modules/$(shell uname -r)/build + +UMP_PATH_RELATIVE = $(CURDIR)/../../../base/ump +KBASE_PATH_RELATIVE = $(CURDIR) +KDS_PATH_RELATIVE = $(CURDIR)/../../../.. +EXTRA_SYMBOLS = $(UMP_PATH_RELATIVE)/src/Module.symvers + +ifeq ($(MALI_UNIT_TEST), 1) + EXTRA_SYMBOLS += $(KBASE_PATH_RELATIVE)/tests/internal/src/kernel_assert_module/linux/Module.symvers +endif + +# GPL driver supports KDS +EXTRA_SYMBOLS += $(KDS_PATH_RELATIVE)/drivers/base/kds/Module.symvers + +# we get the symbols from modules using KBUILD_EXTRA_SYMBOLS to prevent warnings about unknown functions +all: + $(MAKE) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../include $(SCONS_CFLAGS)" $(SCONS_CONFIGS) KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules + +clean: + $(MAKE) -C $(KDIR) M=$(CURDIR) clean diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Makefile.kbase b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Makefile.kbase new file mode 100755 index 0000000000000000000000000000000000000000..2bef9c25eaeb89307738e77ed2a1f7fc5602639b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/Makefile.kbase @@ -0,0 +1,17 @@ +# +# (C) COPYRIGHT 2010 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +EXTRA_CFLAGS += -I$(ROOT) -I$(KBASE_PATH) -I$(OSK_PATH)/src/linux/include -I$(KBASE_PATH)/platform_$(PLATFORM) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/Doxyfile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/Doxyfile new file mode 100755 index 0000000000000000000000000000000000000000..e2662c2dfaeb6e58a5a0261adc796b2d37848a64 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/Doxyfile @@ -0,0 +1,126 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +############################################################################## + +# This file contains per-module Doxygen configuration. Please do not add +# extra settings to this file without consulting all stakeholders, as they +# may cause override project-wide settings. +# +# Additionally, when defining aliases, macros, sections etc, use the module +# name as a prefix e.g. gles_my_alias. + +############################################################################## + +@INCLUDE = ../../bldsys/Doxyfile_common + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT += ../../kernel/drivers/gpu/arm/midgard/ + +############################################################################## +# Everything below here is optional, and in most cases not required +############################################################################## + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES += + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS += + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS += + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +EXCLUDE += ../../kernel/drivers/gpu/arm/midgard/malisw/ ../../kernel/drivers/gpu/arm/midgard/platform ../../kernel/drivers/gpu/arm/midgard/platform_dummy ../../kernel/drivers/gpu/arm/midgard/scripts ../../kernel/drivers/gpu/arm/midgard/tests ../../kernel/drivers/gpu/arm/midgard/Makefile ../../kernel/drivers/gpu/arm/midgard/Makefile.kbase ../../kernel/drivers/gpu/arm/midgard/Kbuild ../../kernel/drivers/gpu/arm/midgard/Kconfig ../../kernel/drivers/gpu/arm/midgard/sconscript ../../kernel/drivers/gpu/arm/midgard/docs ../../kernel/drivers/gpu/arm/midgard/pm_test_script.sh ../../kernel/drivers/gpu/arm/midgard/mali_uk.h ../../kernel/drivers/gpu/arm/midgard/Makefile + + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS += + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS += + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH += + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH += + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH += + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED += + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED += + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS += ../../kernel/drivers/gpu/arm/midgard/docs + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/policy_operation_diagram.dot b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/policy_operation_diagram.dot new file mode 100644 index 0000000000000000000000000000000000000000..a70b54947088794911513049b069a5afda530bb5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/policy_operation_diagram.dot @@ -0,0 +1,112 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +digraph policy_objects_diagram { + rankdir=LR; + size="12,8"; + compound=true; + + node [ shape = box ]; + + subgraph cluster_policy_queues { + low_queue [ shape=record label = "LowP | {ctx_lo | ... | ctx_i | ... | ctx_hi}" ]; + queues_middle_sep [ label="" shape=plaintext width=0 height=0 ]; + + rt_queue [ shape=record label = "RT | {ctx_lo | ... | ctx_j | ... | ctx_hi}" ]; + + label = "Policy's Queue(s)"; + } + + call_enqueue [ shape=plaintext label="enqueue_ctx()" ]; + + { + rank=same; + ordering=out; + call_dequeue [ shape=plaintext label="dequeue_head_ctx()\n+ runpool_add_ctx()" ]; + call_ctxfinish [ shape=plaintext label="runpool_remove_ctx()" ]; + + call_ctxdone [ shape=plaintext label="don't requeue;\n/* ctx has no more jobs */" ]; + } + + subgraph cluster_runpool { + + as0 [ width=2 height = 0.25 label="AS0: Job_1, ..., Job_n" ]; + as1 [ width=2 height = 0.25 label="AS1: Job_1, ..., Job_m" ]; + as2 [ width=2 height = 0.25 label="AS2: Job_1, ..., Job_p" ]; + as3 [ width=2 height = 0.25 label="AS3: Job_1, ..., Job_q" ]; + + label = "Policy's Run Pool"; + } + + { + rank=same; + call_jdequeue [ shape=plaintext label="dequeue_job()" ]; + sstop_dotfixup [ shape=plaintext label="" width=0 height=0 ]; + } + + { + rank=same; + ordering=out; + sstop [ shape=ellipse label="SS-Timer expires" ] + jobslots [ shape=record label="Jobslots: | <0>js[0] | <1>js[1] | <2>js[2]" ]; + + irq [ label="IRQ" shape=ellipse ]; + + job_finish [ shape=plaintext label="don't requeue;\n/* job done */" ]; + } + + hstop [ shape=ellipse label="HS-Timer expires" ] + + /* + * Edges + */ + + call_enqueue -> queues_middle_sep [ lhead=cluster_policy_queues ]; + + low_queue:qr -> call_dequeue:w; + rt_queue:qr -> call_dequeue:w; + + call_dequeue -> as1 [lhead=cluster_runpool]; + + as1->call_jdequeue [ltail=cluster_runpool]; + call_jdequeue->jobslots:0; + call_jdequeue->sstop_dotfixup [ arrowhead=none]; + sstop_dotfixup->sstop [label="Spawn SS-Timer"]; + sstop->jobslots [label="SoftStop"]; + sstop->hstop [label="Spawn HS-Timer"]; + hstop->jobslots:ne [label="HardStop"]; + + + as3->call_ctxfinish:ne [ ltail=cluster_runpool ]; + call_ctxfinish:sw->rt_queue:qm [ lhead=cluster_policy_queues label="enqueue_ctx()\n/* ctx still has jobs */" ]; + + call_ctxfinish->call_ctxdone [constraint=false]; + + call_ctxdone->call_enqueue [weight=0.1 labeldistance=20.0 labelangle=0.0 taillabel="Job submitted to the ctx" style=dotted constraint=false]; + + + { + jobslots->irq [constraint=false]; + + irq->job_finish [constraint=false]; + } + + irq->as2 [lhead=cluster_runpool label="requeue_job()\n/* timeslice expired */" ]; + +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/policy_overview.dot b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/policy_overview.dot new file mode 100644 index 0000000000000000000000000000000000000000..bd5e21b074ca10755569e8fc7c94b872615fdf67 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/docs/policy_overview.dot @@ -0,0 +1,63 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +digraph policy_objects_diagram { + rankdir=LR + size="6,6" + compound=true; + + node [ shape = box ]; + + call_enqueue [ shape=plaintext label="enqueue ctx" ]; + + + policy_queue [ label="Policy's Queue" ]; + + { + rank=same; + runpool [ label="Policy's Run Pool" ]; + + ctx_finish [ label="ctx finished" ]; + } + + { + rank=same; + jobslots [ shape=record label="Jobslots: | <0>js[0] | <1>js[1] | <2>js[2]" ]; + + job_finish [ label="Job finished" ]; + } + + + + /* + * Edges + */ + + call_enqueue -> policy_queue; + + policy_queue->runpool [label="dequeue ctx" weight=0.1]; + runpool->policy_queue [label="requeue ctx" weight=0.1]; + + runpool->ctx_finish [ style=dotted ]; + + runpool->jobslots [label="dequeue job" weight=0.1]; + jobslots->runpool [label="requeue job" weight=0.1]; + + jobslots->job_finish [ style=dotted ]; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..963d6329eceb4b1b0c6000d0b9f395d791eb3b05 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig.h @@ -0,0 +1,31 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file + * Software workarounds configuration for Hardware issues. + */ + +#ifndef _BASE_HWCONFIG_H_ +#define _BASE_HWCONFIG_H_ + +#include + +#include "mali_base_hwconfig_issues.h" +#include "mali_base_hwconfig_features.h" + +#endif /* _BASE_HWCONFIG_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h new file mode 100644 index 0000000000000000000000000000000000000000..da582a596b5bcb00bd997193293776fa32b15539 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h @@ -0,0 +1,117 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features, + * please update user/midgard/mali_base_hwconfig_{issues,features}.h and + * re-run hwconfig_header_generator instead. This tool is available in + * progs_install directory for host builds. More information is available in + * base/tools/hwconfig_header_generator/README */ + +#ifndef _BASE_HWCONFIG_FEATURES_H_ +#define _BASE_HWCONFIG_FEATURES_H_ + +enum base_hw_feature { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_OPTIMIZED_COVERAGE_MASK, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_WORKGROUP_ROUND_MULTIPLE_OF_4, + BASE_HW_FEATURE_IMAGES_IN_FRAGMENT_SHADERS, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_generic[] = { + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t60x[] = { + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t62x[] = { + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t72x[] = { + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_OPTIMIZED_COVERAGE_MASK, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_WORKGROUP_ROUND_MULTIPLE_OF_4, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t76x[] = { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_tFxx[] = { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_END +}; + +#endif /* _BASE_HWCONFIG_FEATURES_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h new file mode 100644 index 0000000000000000000000000000000000000000..d0c4bffcb38f3f4c9764d24697b3cd7555a0505d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h @@ -0,0 +1,698 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features, + * please update user/midgard/mali_base_hwconfig_{issues,features}.h and + * re-run hwconfig_header_generator instead. This tool is available in + * progs_install directory for host builds. More information is available in + * base/tools/hwconfig_header_generator/README */ + +#ifndef _BASE_HWCONFIG_ISSUES_H_ +#define _BASE_HWCONFIG_ISSUES_H_ + +enum base_hw_issue { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6398, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7144, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8073, + BASE_HW_ISSUE_8186, + BASE_HW_ISSUE_8215, + BASE_HW_ISSUE_8245, + BASE_HW_ISSUE_8250, + BASE_HW_ISSUE_8260, + BASE_HW_ISSUE_8280, + BASE_HW_ISSUE_8316, + BASE_HW_ISSUE_8381, + BASE_HW_ISSUE_8394, + BASE_HW_ISSUE_8401, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8443, + BASE_HW_ISSUE_8456, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8634, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8791, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8833, + BASE_HW_ISSUE_8879, + BASE_HW_ISSUE_8896, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_8986, + BASE_HW_ISSUE_8987, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_9566, + BASE_HW_ISSUE_9630, + BASE_HW_ISSUE_10127, + BASE_HW_ISSUE_10327, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10817, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_10984, + BASE_HW_ISSUE_10995, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_2121, + BASE_HW_ISSUE_T76X_2315, + BASE_HW_ISSUE_T76X_2686, + BASE_HW_ISSUE_T76X_2712, + BASE_HW_ISSUE_T76X_2772, + BASE_HW_ISSUE_T76X_2906, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3285, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3759, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_generic[] = { + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p0_15dev0[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6398, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7144, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8073, + BASE_HW_ISSUE_8186, + BASE_HW_ISSUE_8215, + BASE_HW_ISSUE_8245, + BASE_HW_ISSUE_8250, + BASE_HW_ISSUE_8260, + BASE_HW_ISSUE_8280, + BASE_HW_ISSUE_8316, + BASE_HW_ISSUE_8381, + BASE_HW_ISSUE_8394, + BASE_HW_ISSUE_8401, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8443, + BASE_HW_ISSUE_8456, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8634, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8791, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8833, + BASE_HW_ISSUE_8896, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_8986, + BASE_HW_ISSUE_8987, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_9566, + BASE_HW_ISSUE_9630, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_10984, + BASE_HW_ISSUE_10995, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p0_eac[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p1[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r0p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10127, + BASE_HW_ISSUE_10327, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10817, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r1p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r1p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p0_beta[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_2121, + BASE_HW_ISSUE_T76X_2315, + BASE_HW_ISSUE_T76X_2686, + BASE_HW_ISSUE_T76X_2712, + BASE_HW_ISSUE_T76X_2772, + BASE_HW_ISSUE_T76X_2906, + BASE_HW_ISSUE_T76X_3285, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3759, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p1[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p1_50rel0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p2[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p3[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r1p0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r0p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r1p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r1p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t72x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t76x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t60x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t62x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +#if defined(MALI_INCLUDE_TFRX) +static const enum base_hw_issue base_hw_issues_tFRx_r0p0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +#endif /* defined(MALI_INCLUDE_TFRX) */ + +#if defined(MALI_INCLUDE_TFRX) +static const enum base_hw_issue base_hw_issues_tFRx_r0p1[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +#endif /* defined(MALI_INCLUDE_TFRX) */ + +#if defined(MALI_INCLUDE_TFRX) +static const enum base_hw_issue base_hw_issues_tFRx_r0p2[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_END +}; + +#endif /* defined(MALI_INCLUDE_TFRX) */ + +#if defined(MALI_INCLUDE_TFRX) +static const enum base_hw_issue base_hw_issues_model_tFRx[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_END +}; + +#endif /* defined(MALI_INCLUDE_TFRX) */ + +static const enum base_hw_issue base_hw_issues_t86x_r0p0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t86x_r0p2[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t86x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_END +}; + +#endif /* _BASE_HWCONFIG_ISSUES_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_kernel.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..02a255239cdd7fe64545cc699013c870444efe1a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_kernel.h @@ -0,0 +1,1569 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Base structures shared with the kernel. + */ + +#ifndef _BASE_KERNEL_H_ +#define _BASE_KERNEL_H_ + +#ifndef __user +#define __user +#endif + +/* Support UK6 IOCTLS */ +#define BASE_LEGACY_UK6_SUPPORT 1 + +/* Support UK7 IOCTLS */ +/* NB: To support UK6 we also need to support UK7 */ +#define BASE_LEGACY_UK7_SUPPORT 1 + +typedef mali_addr64 base_mem_handle; + +#include "mali_base_mem_priv.h" +#include "mali_kbase_profiling_gator_api.h" + +/* + * Dependency stuff, keep it private for now. May want to expose it if + * we decide to make the number of semaphores a configurable + * option. + */ +#define BASE_JD_ATOM_COUNT 256 + +#define BASEP_JD_SEM_PER_WORD_LOG2 5 +#define BASEP_JD_SEM_PER_WORD (1 << BASEP_JD_SEM_PER_WORD_LOG2) +#define BASEP_JD_SEM_WORD_NR(x) ((x) >> BASEP_JD_SEM_PER_WORD_LOG2) +#define BASEP_JD_SEM_MASK_IN_WORD(x) (1 << ((x) & (BASEP_JD_SEM_PER_WORD - 1))) +#define BASEP_JD_SEM_ARRAY_SIZE BASEP_JD_SEM_WORD_NR(BASE_JD_ATOM_COUNT) + +#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3 + +#define BASE_MAX_COHERENT_GROUPS 16 + +#if defined CDBG_ASSERT +#define LOCAL_ASSERT CDBG_ASSERT +#elif defined KBASE_DEBUG_ASSERT +#define LOCAL_ASSERT KBASE_DEBUG_ASSERT +#else +#error assert macro not defined! +#endif + +#if defined PAGE_MASK +#define LOCAL_PAGE_LSB ~PAGE_MASK +#else +#include + +#if defined OSU_CONFIG_CPU_PAGE_SIZE_LOG2 +#define LOCAL_PAGE_LSB ((1ul << OSU_CONFIG_CPU_PAGE_SIZE_LOG2) - 1) +#else +#error Failed to find page size +#endif +#endif + +/** 32/64-bit neutral way to represent pointers */ +typedef union kbase_pointer { + void __user *value; /**< client should store their pointers here */ + u32 compat_value; /**< 64-bit kernels should fetch value here when handling 32-bit clients */ + u64 sizer; /**< Force 64-bit storage for all clients regardless */ +} kbase_pointer; + +/** + * @addtogroup base_user_api User-side Base APIs + * @{ + */ + +/** + * @addtogroup base_user_api_memory User-side Base Memory APIs + * @{ + */ + +/** + * @brief Memory allocation, access/hint flags + * + * A combination of MEM_PROT/MEM_HINT flags must be passed to each allocator + * in order to determine the best cache policy. Some combinations are + * of course invalid (eg @c MEM_PROT_CPU_WR | @c MEM_HINT_CPU_RD), + * which defines a @a write-only region on the CPU side, which is + * heavily read by the CPU... + * Other flags are only meaningful to a particular allocator. + * More flags can be added to this list, as long as they don't clash + * (see ::BASE_MEM_FLAGS_NR_TOTAL_BITS for the number of the first free bit). + */ +typedef u32 base_mem_alloc_flags; + +/** + * @brief Memory allocation, access/hint flags + * + * See ::base_mem_alloc_flags. + * + */ +enum { +/* IN */ + BASE_MEM_PROT_CPU_RD = (1U << 0), /**< Read access CPU side */ + BASE_MEM_PROT_CPU_WR = (1U << 1), /**< Write access CPU side */ + BASE_MEM_PROT_GPU_RD = (1U << 2), /**< Read access GPU side */ + BASE_MEM_PROT_GPU_WR = (1U << 3), /**< Write access GPU side */ + BASE_MEM_PROT_GPU_EX = (1U << 4), /**< Execute allowed on the GPU + side */ + + /* Note that the HINT flags are obsolete now. If you want the memory + * to be cached on the CPU please use the BASE_MEM_CACHED_CPU flag + */ + BASE_MEM_HINT_CPU_RD = (1U << 5), /**< Heavily read CPU side + - OBSOLETE */ + BASE_MEM_HINT_CPU_WR = (1U << 6), /**< Heavily written CPU side + - OBSOLETE */ + BASE_MEM_HINT_GPU_RD = (1U << 7), /**< Heavily read GPU side + - OBSOLETE */ + BASE_MEM_HINT_GPU_WR = (1U << 8), /**< Heavily written GPU side + - OBSOLETE */ + + BASE_MEM_GROW_ON_GPF = (1U << 9), /**< Grow backing store on GPU + Page Fault */ + + BASE_MEM_COHERENT_SYSTEM = (1U << 10), /**< Page coherence Outer + shareable */ + BASE_MEM_COHERENT_LOCAL = (1U << 11), /**< Page coherence Inner + shareable */ + BASE_MEM_CACHED_CPU = (1U << 12), /**< Should be cached on the + CPU */ + +/* IN/OUT */ + BASE_MEM_SAME_VA = (1U << 13), /**< Must have same VA on both the GPU + and the CPU */ +/* OUT */ + BASE_MEM_NEED_MMAP = (1U << 14) /**< Must call mmap to aquire a GPU + address for the alloc */ +}; + +/** + * @brief Number of bits used as flags for base memory management + * + * Must be kept in sync with the ::base_mem_alloc_flags flags + */ +#define BASE_MEM_FLAGS_NR_INPUT_BITS 14 +#define BASE_MEM_FLAGS_NR_OUTPUT_BITS 1 +#define BASE_MEM_FLAGS_NR_TOTAL_BITS ((BASE_MEM_FLAGS_NR_INPUT_BITS) + (BASE_MEM_FLAGS_NR_OUTPUT_BITS)) +#define BASE_MEM_FLAGS_NR_BITS 15 + +#if BASE_MEM_FLAGS_NR_TOTAL_BITS > BASE_MEM_FLAGS_NR_BITS +#error "Too many flag bits, will require change in cmem" +#endif + +/** + * @brief Memory types supported by @a base_mem_import + * + * Each type defines what the supported handle type is. + * + * If any new type is added here ARM must be contacted + * to allocate a numeric value for it. + * Do not just add a new type without synchronizing with ARM + * as future releases from ARM might include other new types + * which could clash with your custom types. + */ +typedef enum base_mem_import_type { + BASE_MEM_IMPORT_TYPE_INVALID = 0, + /** UMP import. Handle type is ump_secure_id. */ + BASE_MEM_IMPORT_TYPE_UMP = 1, + /** UMM import. Handle type is a file descriptor (int) */ + BASE_MEM_IMPORT_TYPE_UMM = 2 +} base_mem_import_type; + +/* legacy API wrappers */ +#define base_tmem_import_type base_mem_import_type +#define BASE_TMEM_IMPORT_TYPE_INVALID BASE_MEM_IMPORT_TYPE_INVALID +#define BASE_TMEM_IMPORT_TYPE_UMP BASE_MEM_IMPORT_TYPE_UMP +#define BASE_TMEM_IMPORT_TYPE_UMM BASE_MEM_IMPORT_TYPE_UMM + +/** + * @brief Invalid memory handle type. + * Return value from functions returning @a base_mem_handle on error. + */ +#define BASE_MEM_INVALID_HANDLE (0ull << 12) +#define BASE_MEM_MMU_DUMP_HANDLE (1ull << 12) +#define BASE_MEM_TRACE_BUFFER_HANDLE (2ull << 12) +#define BASE_MEM_MAP_TRACKING_HANDLE (3ull << 12) +#define BASE_MEM_WRITE_ALLOC_PAGES_HANDLE (4ull << 12) +/* reserved handles ..-64< for future special handles */ +#define BASE_MEM_COOKIE_BASE (64ul << 12) +#define BASE_MEM_FIRST_FREE_ADDRESS ((BITS_PER_LONG << 12) + \ + BASE_MEM_COOKIE_BASE) + +/* Bit mask of cookies used for for memory allocation setup */ +#define KBASE_COOKIE_MASK ~1UL /* bit 0 is reserved */ + + +/** + * @brief Result codes of changing the size of the backing store allocated to a tmem region + */ +typedef enum base_backing_threshold_status { + BASE_BACKING_THRESHOLD_OK = 0, /**< Resize successful */ + BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE = -1, /**< Not a growable tmem object */ + BASE_BACKING_THRESHOLD_ERROR_OOM = -2, /**< Increase failed due to an out-of-memory condition */ + BASE_BACKING_THRESHOLD_ERROR_MAPPED = -3, /**< Resize attempted on buffer while it was mapped, which is not permitted */ + BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS = -4 /**< Invalid arguments (not tmem, illegal size request, etc.) */ +} base_backing_threshold_status; + +/** + * @addtogroup base_user_api_memory_defered User-side Base Defered Memory Coherency APIs + * @{ + */ + +/** + * @brief a basic memory operation (sync-set). + * + * The content of this structure is private, and should only be used + * by the accessors. + */ +typedef struct base_syncset { + struct basep_syncset basep_sset; +} base_syncset; + +/** @} end group base_user_api_memory_defered */ + +/** + * Handle to represent imported memory object. + * Simple opague handle to imported memory, can't be used + * with anything but base_external_resource_init to bind to an atom. + */ +typedef struct base_import_handle { + struct { + mali_addr64 handle; + } basep; +} base_import_handle; + +/** @} end group base_user_api_memory */ + +/** + * @addtogroup base_user_api_job_dispatch User-side Base Job Dispatcher APIs + * @{ + */ + +typedef int platform_fence_type; +#define INVALID_PLATFORM_FENCE ((platform_fence_type)-1) + +/** + * Base stream handle. + * + * References an underlying base stream object. + */ +typedef struct base_stream { + struct { + int fd; + } basep; +} base_stream; + +/** + * Base fence handle. + * + * References an underlying base fence object. + */ +typedef struct base_fence { + struct { + int fd; + int stream_fd; + } basep; +} base_fence; + +/** + * @brief Per-job data + * + * This structure is used to store per-job data, and is completly unused + * by the Base driver. It can be used to store things such as callback + * function pointer, data to handle job completion. It is guaranteed to be + * untouched by the Base driver. + */ +typedef struct base_jd_udata { + u64 blob[2]; /**< per-job data array */ +} base_jd_udata; + +/** + * @brief Memory aliasing info + * + * Describes a memory handle to be aliased. + * A subset of the handle can be chosen for aliasing, given an offset and a + * length. + * A special handle BASE_MEM_WRITE_ALLOC_PAGES_HANDLE is used to represent a + * region where a special page is mapped with a write-alloc cache setup, + * typically used when the write result of the GPU isn't needed, but the GPU + * must write anyway. + * + * Offset and length are specified in pages. + * Offset must be within the size of the handle. + * Offset+length must not overrun the size of the handle. + * + * @handle Handle to alias, can be BASE_MEM_WRITE_ALLOC_PAGES_HANDLE + * @offset Offset within the handle to start aliasing from, in pages. + * Not used with BASE_MEM_WRITE_ALLOC_PAGES_HANDLE. + * @length Length to alias, in pages. For BASE_MEM_WRITE_ALLOC_PAGES_HANDLE + * specifies the number of times the special page is needed. + */ +struct base_mem_aliasing_info { + base_mem_handle handle; + u64 offset; + u64 length; +}; + +/** + * @brief Job dependency type. + * + * A flags field will be inserted into the atom structure to specify whether a dependency is a data or + * ordering dependency (by putting it before/after 'core_req' in the structure it should be possible to add without + * changing the structure size). + * When the flag is set for a particular dependency to signal that it is an ordering only dependency then + * errors will not be propagated. + */ +typedef u8 base_jd_dep_type; + + +#define BASE_JD_DEP_TYPE_INVALID (0) /**< Invalid dependency */ +#define BASE_JD_DEP_TYPE_DATA (1U << 0) /**< Data dependency */ +#define BASE_JD_DEP_TYPE_ORDER (1U << 1) /**< Order dependency */ + +/** + * @brief Job chain hardware requirements. + * + * A job chain must specify what GPU features it needs to allow the + * driver to schedule the job correctly. By not specifying the + * correct settings can/will cause an early job termination. Multiple + * values can be ORed together to specify multiple requirements. + * Special case is ::BASE_JD_REQ_DEP, which is used to express complex + * dependencies, and that doesn't execute anything on the hardware. + */ +typedef u16 base_jd_core_req; + +/* Requirements that come from the HW */ +#define BASE_JD_REQ_DEP 0 /**< No requirement, dependency only */ +#define BASE_JD_REQ_FS (1U << 0) /**< Requires fragment shaders */ +/** + * Requires compute shaders + * This covers any of the following Midgard Job types: + * - Vertex Shader Job + * - Geometry Shader Job + * - An actual Compute Shader Job + * + * Compare this with @ref BASE_JD_REQ_ONLY_COMPUTE, which specifies that the + * job is specifically just the "Compute Shader" job type, and not the "Vertex + * Shader" nor the "Geometry Shader" job type. + */ +#define BASE_JD_REQ_CS (1U << 1) +#define BASE_JD_REQ_T (1U << 2) /**< Requires tiling */ +#define BASE_JD_REQ_CF (1U << 3) /**< Requires cache flushes */ +#define BASE_JD_REQ_V (1U << 4) /**< Requires value writeback */ + +/* SW-only requirements - the HW does not expose these as part of the job slot capabilities */ + +/* Requires fragment job with AFBC encoding */ +#define BASE_JD_REQ_FS_AFBC (1U << 13) + +/** + * SW Only requirement: the job chain requires a coherent core group. We don't + * mind which coherent core group is used. + */ +#define BASE_JD_REQ_COHERENT_GROUP (1U << 6) + +/** + * SW Only requirement: The performance counters should be enabled only when + * they are needed, to reduce power consumption. + */ + +#define BASE_JD_REQ_PERMON (1U << 7) + +/** + * SW Only requirement: External resources are referenced by this atom. + * When external resources are referenced no syncsets can be bundled with the atom + * but should instead be part of a NULL jobs inserted into the dependency tree. + * The first pre_dep object must be configured for the external resouces to use, + * the second pre_dep object can be used to create other dependencies. + */ +#define BASE_JD_REQ_EXTERNAL_RESOURCES (1U << 8) + +/** + * SW Only requirement: Software defined job. Jobs with this bit set will not be submitted + * to the hardware but will cause some action to happen within the driver + */ +#define BASE_JD_REQ_SOFT_JOB (1U << 9) + +#define BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME (BASE_JD_REQ_SOFT_JOB | 0x1) +#define BASE_JD_REQ_SOFT_FENCE_TRIGGER (BASE_JD_REQ_SOFT_JOB | 0x2) +#define BASE_JD_REQ_SOFT_FENCE_WAIT (BASE_JD_REQ_SOFT_JOB | 0x3) + +/** + * SW Only requirement : Replay job. + * + * If the preceeding job fails, the replay job will cause the jobs specified in + * the list of base_jd_replay_payload pointed to by the jc pointer to be + * replayed. + * + * A replay job will only cause jobs to be replayed up to BASEP_JD_REPLAY_LIMIT + * times. If a job fails more than BASEP_JD_REPLAY_LIMIT times then the replay + * job is failed, as well as any following dependencies. + * + * The replayed jobs will require a number of atom IDs. If there are not enough + * free atom IDs then the replay job will fail. + * + * If the preceeding job does not fail, then the replay job is returned as + * completed. + * + * The replayed jobs will never be returned to userspace. The preceeding failed + * job will be returned to userspace as failed; the status of this job should + * be ignored. Completion should be determined by the status of the replay soft + * job. + * + * In order for the jobs to be replayed, the job headers will have to be + * modified. The Status field will be reset to NOT_STARTED. If the Job Type + * field indicates a Vertex Shader Job then it will be changed to Null Job. + * + * The replayed jobs have the following assumptions : + * + * - No external resources. Any required external resources will be held by the + * replay atom. + * - Pre-dependencies are created based on job order. + * - Atom numbers are automatically assigned. + * - device_nr is set to 0. This is not relevant as + * BASE_JD_REQ_SPECIFIC_COHERENT_GROUP should not be set. + * - Priority is inherited from the replay job. + */ +#define BASE_JD_REQ_SOFT_REPLAY (BASE_JD_REQ_SOFT_JOB | 0x4) + +/** + * HW Requirement: Requires Compute shaders (but not Vertex or Geometry Shaders) + * + * This indicates that the Job Chain contains Midgard Jobs of the 'Compute Shaders' type. + * + * In contrast to @ref BASE_JD_REQ_CS, this does \b not indicate that the Job + * Chain contains 'Geometry Shader' or 'Vertex Shader' jobs. + * + * @note This is a more flexible variant of the @ref BASE_CONTEXT_HINT_ONLY_COMPUTE flag, + * allowing specific jobs to be marked as 'Only Compute' instead of the entire context + */ +#define BASE_JD_REQ_ONLY_COMPUTE (1U << 10) + +/** + * HW Requirement: Use the base_jd_atom::device_nr field to specify a + * particular core group + * + * If both BASE_JD_REQ_COHERENT_GROUP and this flag are set, this flag takes priority + * + * This is only guaranteed to work for BASE_JD_REQ_ONLY_COMPUTE atoms. + * + * If the core availability policy is keeping the required core group turned off, then + * the job will fail with a BASE_JD_EVENT_PM_EVENT error code. + */ +#define BASE_JD_REQ_SPECIFIC_COHERENT_GROUP (1U << 11) + +/** + * SW Flag: If this bit is set then the successful completion of this atom + * will not cause an event to be sent to userspace + */ +#define BASE_JD_REQ_EVENT_ONLY_ON_FAILURE (1U << 12) + +/** + * SW Flag: If this bit is set then completion of this atom will not cause an + * event to be sent to userspace, whether successful or not. + */ +#define BASEP_JD_REQ_EVENT_NEVER (1U << 14) + +/** +* These requirement bits are currently unused in base_jd_core_req (currently a u16) +*/ + +#define BASEP_JD_REQ_RESERVED_BIT5 (1U << 5) +#define BASEP_JD_REQ_RESERVED_BIT15 (1U << 15) + +/** +* Mask of all the currently unused requirement bits in base_jd_core_req. +*/ + +#define BASEP_JD_REQ_RESERVED (BASEP_JD_REQ_RESERVED_BIT5 | \ + BASEP_JD_REQ_RESERVED_BIT15) + +/** + * Mask of all bits in base_jd_core_req that control the type of the atom. + * + * This allows dependency only atoms to have flags set + */ +#define BASEP_JD_REQ_ATOM_TYPE (~(BASEP_JD_REQ_RESERVED | BASE_JD_REQ_EVENT_ONLY_ON_FAILURE |\ + BASE_JD_REQ_EXTERNAL_RESOURCES | BASEP_JD_REQ_EVENT_NEVER)) + +/** + * @brief States to model state machine processed by kbasep_js_job_check_ref_cores(), which + * handles retaining cores for power management and affinity management. + * + * The state @ref KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY prevents an attack + * where lots of atoms could be submitted before powerup, and each has an + * affinity chosen that causes other atoms to have an affinity + * violation. Whilst the affinity was not causing violations at the time it + * was chosen, it could cause violations thereafter. For example, 1000 jobs + * could have had their affinity chosen during the powerup time, so any of + * those 1000 jobs could cause an affinity violation later on. + * + * The attack would otherwise occur because other atoms/contexts have to wait for: + * -# the currently running atoms (which are causing the violation) to + * finish + * -# and, the atoms that had their affinity chosen during powerup to + * finish. These are run preferrentially because they don't cause a + * violation, but instead continue to cause the violation in others. + * -# or, the attacker is scheduled out (which might not happen for just 2 + * contexts) + * + * By re-choosing the affinity (which is designed to avoid violations at the + * time it's chosen), we break condition (2) of the wait, which minimizes the + * problem to just waiting for current jobs to finish (which can be bounded if + * the Job Scheduling Policy has a timer). + */ +enum kbase_atom_coreref_state { + /** Starting state: No affinity chosen, and cores must be requested. kbase_jd_atom::affinity==0 */ + KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED, + /** Cores requested, but waiting for them to be powered. Requested cores given by kbase_jd_atom::affinity */ + KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES, + /** Cores given by kbase_jd_atom::affinity are powered, but affinity might be out-of-date, so must recheck */ + KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY, + /** Cores given by kbase_jd_atom::affinity are powered, and affinity is up-to-date, but must check for violations */ + KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS, + /** Cores are powered, kbase_jd_atom::affinity up-to-date, no affinity violations: atom can be submitted to HW */ + KBASE_ATOM_COREREF_STATE_READY +}; + +enum kbase_jd_atom_state { + /** Atom is not used */ + KBASE_JD_ATOM_STATE_UNUSED, + /** Atom is queued in JD */ + KBASE_JD_ATOM_STATE_QUEUED, + /** Atom has been given to JS (is runnable/running) */ + KBASE_JD_ATOM_STATE_IN_JS, + /** Atom has been completed, but not yet handed back to userspace */ + KBASE_JD_ATOM_STATE_COMPLETED +}; + +typedef u8 base_atom_id; /**< Type big enough to store an atom number in */ + +struct base_dependency { + base_atom_id atom_id; /**< An atom number */ + base_jd_dep_type dependency_type; /**< Dependency type */ +}; + +typedef struct base_jd_atom_v2 { + mali_addr64 jc; /**< job-chain GPU address */ + struct base_jd_udata udata; /**< user data */ + kbase_pointer extres_list; /**< list of external resources */ + u16 nr_extres; /**< nr of external resources */ + base_jd_core_req core_req; /**< core requirements */ + const struct base_dependency pre_dep[2]; /**< pre-dependencies, one need to use SETTER function to assign this field, + this is done in order to reduce possibility of improper assigment of a dependency field */ + base_atom_id atom_number; /**< unique number to identify the atom */ + s8 prio; /**< priority - smaller is higher priority */ + u8 device_nr; /**< coregroup when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP specified */ + u8 padding[5]; +} base_jd_atom_v2; + +#ifdef BASE_LEGACY_UK6_SUPPORT +struct base_jd_atom_v2_uk6 { + mali_addr64 jc; /**< job-chain GPU address */ + struct base_jd_udata udata; /**< user data */ + kbase_pointer extres_list; /**< list of external resources */ + u16 nr_extres; /**< nr of external resources */ + base_jd_core_req core_req; /**< core requirements */ + base_atom_id pre_dep[2]; /**< pre-dependencies */ + base_atom_id atom_number; /**< unique number to identify the atom */ + s8 prio; /**< priority - smaller is higher priority */ + u8 device_nr; /**< coregroup when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP specified */ + u8 padding[7]; +}; +#endif + +typedef enum base_external_resource_access { + BASE_EXT_RES_ACCESS_SHARED, + BASE_EXT_RES_ACCESS_EXCLUSIVE +} base_external_resource_access; + +typedef struct base_external_resource { + u64 ext_resource; +} base_external_resource; + +/** + * @brief Setter for a dependency structure + * + * @param[in] dep The kbase jd atom dependency to be initialized. + * @param id The atom_id to be assigned. + * @param dep_type The dep_type to be assigned. + * + */ +static INLINE void base_jd_atom_dep_set(const struct base_dependency* const_dep, base_atom_id id, base_jd_dep_type dep_type) +{ + struct base_dependency* dep; + + LOCAL_ASSERT(const_dep != NULL); + /* make sure we don't set not allowed combinations of atom_id/dependency_type */ + LOCAL_ASSERT( ( id == 0 && dep_type == BASE_JD_DEP_TYPE_INVALID) || + (id > 0 && dep_type != BASE_JD_DEP_TYPE_INVALID) ); + + dep = REINTERPRET_CAST(struct base_dependency*)const_dep; + + dep->atom_id = id; + dep->dependency_type = dep_type; +} + +/** + * @brief Make a copy of a dependency structure + * + * @param[in,out] dep The kbase jd atom dependency to be written. + * @param[in] from The dependency to make a copy from. + * + */ +static INLINE void base_jd_atom_dep_copy(const struct base_dependency* const_dep, const struct base_dependency* from) +{ + LOCAL_ASSERT(const_dep != NULL); + + base_jd_atom_dep_set(const_dep, from->atom_id, from->dependency_type); +} + +/** + * @brief Soft-atom fence trigger setup. + * + * Sets up an atom to be a SW-only atom signaling a fence + * when it reaches the run state. + * + * Using the existing base dependency system the fence can + * be set to trigger when a GPU job has finished. + * + * The base fence object must not be terminated until the atom + * has been submitted to @a base_jd_submit_bag and @a base_jd_submit_bag has returned. + * + * @a fence must be a valid fence set up with @a base_fence_init. + * Calling this function with a uninitialized fence results in undefined behavior. + * + * @param[out] atom A pre-allocated atom to configure as a fence trigger SW atom + * @param[in] fence The base fence object to trigger. + */ +static INLINE void base_jd_fence_trigger_setup_v2(struct base_jd_atom_v2 *atom, struct base_fence *fence) +{ + LOCAL_ASSERT(atom); + LOCAL_ASSERT(fence); + LOCAL_ASSERT(fence->basep.fd == INVALID_PLATFORM_FENCE); + LOCAL_ASSERT(fence->basep.stream_fd >= 0); + atom->jc = (uintptr_t) fence; + atom->core_req = BASE_JD_REQ_SOFT_FENCE_TRIGGER; +} + +/** + * @brief Soft-atom fence wait setup. + * + * Sets up an atom to be a SW-only atom waiting on a fence. + * When the fence becomes triggered the atom becomes runnable + * and completes immediately. + * + * Using the existing base dependency system the fence can + * be set to block a GPU job until it has been triggered. + * + * The base fence object must not be terminated until the atom + * has been submitted to @a base_jd_submit_bag and @a base_jd_submit_bag has returned. + * + * @a fence must be a valid fence set up with @a base_fence_init or @a base_fence_import. + * Calling this function with a uninitialized fence results in undefined behavior. + * + * @param[out] atom A pre-allocated atom to configure as a fence wait SW atom + * @param[in] fence The base fence object to wait on + */ +static INLINE void base_jd_fence_wait_setup_v2(struct base_jd_atom_v2 *atom, struct base_fence *fence) +{ + LOCAL_ASSERT(atom); + LOCAL_ASSERT(fence); + LOCAL_ASSERT(fence->basep.fd >= 0); + atom->jc = (uintptr_t) fence; + atom->core_req = BASE_JD_REQ_SOFT_FENCE_WAIT; +} + +/** + * @brief External resource info initialization. + * + * Sets up a external resource object to reference + * a memory allocation and the type of access requested. + * + * @param[in] res The resource object to initialize + * @param handle The handle to the imported memory object + * @param access The type of access requested + */ +static INLINE void base_external_resource_init(struct base_external_resource * res, struct base_import_handle handle, base_external_resource_access access) +{ + mali_addr64 address; + address = handle.basep.handle; + + LOCAL_ASSERT(res != NULL); + LOCAL_ASSERT(0 == (address & LOCAL_PAGE_LSB)); + LOCAL_ASSERT(access == BASE_EXT_RES_ACCESS_SHARED || access == BASE_EXT_RES_ACCESS_EXCLUSIVE); + + res->ext_resource = address | (access & LOCAL_PAGE_LSB); +} + +/** + * @brief Job chain event code bits + * Defines the bits used to create ::base_jd_event_code + */ +enum { + BASE_JD_SW_EVENT_KERNEL = (1u << 15), /**< Kernel side event */ + BASE_JD_SW_EVENT = (1u << 14), /**< SW defined event */ + BASE_JD_SW_EVENT_SUCCESS = (1u << 13), /**< Event idicates success (SW events only) */ + BASE_JD_SW_EVENT_JOB = (0u << 11), /**< Job related event */ + BASE_JD_SW_EVENT_BAG = (1u << 11), /**< Bag related event */ + BASE_JD_SW_EVENT_INFO = (2u << 11), /**< Misc/info event */ + BASE_JD_SW_EVENT_RESERVED = (3u << 11), /**< Reserved event type */ + BASE_JD_SW_EVENT_TYPE_MASK = (3u << 11) /**< Mask to extract the type from an event code */ +}; + +/** + * @brief Job chain event codes + * + * HW and low-level SW events are represented by event codes. + * The status of jobs which succeeded are also represented by + * an event code (see ::BASE_JD_EVENT_DONE). + * Events are usually reported as part of a ::base_jd_event. + * + * The event codes are encoded in the following way: + * @li 10:0 - subtype + * @li 12:11 - type + * @li 13 - SW success (only valid if the SW bit is set) + * @li 14 - SW event (HW event if not set) + * @li 15 - Kernel event (should never be seen in userspace) + * + * Events are split up into ranges as follows: + * - BASE_JD_EVENT_RANGE_\_START + * - BASE_JD_EVENT_RANGE_\_END + * + * \a code is in \'s range when: + * - BASE_JD_EVENT_RANGE_\_START <= code < BASE_JD_EVENT_RANGE_\_END + * + * Ranges can be asserted for adjacency by testing that the END of the previous + * is equal to the START of the next. This is useful for optimizing some tests + * for range. + * + * A limitation is that the last member of this enum must explicitly be handled + * (with an assert-unreachable statement) in switch statements that use + * variables of this type. Otherwise, the compiler warns that we have not + * handled that enum value. + */ +typedef enum base_jd_event_code { + /* HW defined exceptions */ + + /** Start of HW Non-fault status codes + * + * @note Obscurely, BASE_JD_EVENT_TERMINATED indicates a real fault, + * because the job was hard-stopped + */ + BASE_JD_EVENT_RANGE_HW_NONFAULT_START = 0, + + /* non-fatal exceptions */ + BASE_JD_EVENT_NOT_STARTED = 0x00, /**< Can't be seen by userspace, treated as 'previous job done' */ + BASE_JD_EVENT_DONE = 0x01, + BASE_JD_EVENT_STOPPED = 0x03, /**< Can't be seen by userspace, becomes TERMINATED, DONE or JOB_CANCELLED */ + BASE_JD_EVENT_TERMINATED = 0x04, /**< This is actually a fault status code - the job was hard stopped */ + BASE_JD_EVENT_ACTIVE = 0x08, /**< Can't be seen by userspace, jobs only returned on complete/fail/cancel */ + + /** End of HW Non-fault status codes + * + * @note Obscurely, BASE_JD_EVENT_TERMINATED indicates a real fault, + * because the job was hard-stopped + */ + BASE_JD_EVENT_RANGE_HW_NONFAULT_END = 0x40, + + /** Start of HW fault and SW Error status codes */ + BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_START = 0x40, + + /* job exceptions */ + BASE_JD_EVENT_JOB_CONFIG_FAULT = 0x40, + BASE_JD_EVENT_JOB_POWER_FAULT = 0x41, + BASE_JD_EVENT_JOB_READ_FAULT = 0x42, + BASE_JD_EVENT_JOB_WRITE_FAULT = 0x43, + BASE_JD_EVENT_JOB_AFFINITY_FAULT = 0x44, + BASE_JD_EVENT_JOB_BUS_FAULT = 0x48, + BASE_JD_EVENT_INSTR_INVALID_PC = 0x50, + BASE_JD_EVENT_INSTR_INVALID_ENC = 0x51, + BASE_JD_EVENT_INSTR_TYPE_MISMATCH = 0x52, + BASE_JD_EVENT_INSTR_OPERAND_FAULT = 0x53, + BASE_JD_EVENT_INSTR_TLS_FAULT = 0x54, + BASE_JD_EVENT_INSTR_BARRIER_FAULT = 0x55, + BASE_JD_EVENT_INSTR_ALIGN_FAULT = 0x56, + BASE_JD_EVENT_DATA_INVALID_FAULT = 0x58, + BASE_JD_EVENT_TILE_RANGE_FAULT = 0x59, + BASE_JD_EVENT_STATE_FAULT = 0x5A, + BASE_JD_EVENT_OUT_OF_MEMORY = 0x60, + BASE_JD_EVENT_UNKNOWN = 0x7F, + + /* GPU exceptions */ + BASE_JD_EVENT_DELAYED_BUS_FAULT = 0x80, + BASE_JD_EVENT_SHAREABILITY_FAULT = 0x88, + + /* MMU exceptions */ + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL1 = 0xC1, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL2 = 0xC2, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL3 = 0xC3, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL4 = 0xC4, + BASE_JD_EVENT_PERMISSION_FAULT = 0xC8, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL1 = 0xD1, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL2 = 0xD2, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL3 = 0xD3, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL4 = 0xD4, + BASE_JD_EVENT_ACCESS_FLAG = 0xD8, + + /* SW defined exceptions */ + BASE_JD_EVENT_MEM_GROWTH_FAILED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x000, + BASE_JD_EVENT_TIMED_OUT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x001, + BASE_JD_EVENT_JOB_CANCELLED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x002, + BASE_JD_EVENT_JOB_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x003, + BASE_JD_EVENT_PM_EVENT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x004, + BASE_JD_EVENT_FORCE_REPLAY = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x005, + + BASE_JD_EVENT_BAG_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_BAG | 0x003, + + /** End of HW fault and SW Error status codes */ + BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_RESERVED | 0x3FF, + + /** Start of SW Success status codes */ + BASE_JD_EVENT_RANGE_SW_SUCCESS_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | 0x000, + + BASE_JD_EVENT_PROGRESS_REPORT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_JOB | 0x000, + BASE_JD_EVENT_BAG_DONE = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_BAG | 0x000, + BASE_JD_EVENT_DRV_TERMINATED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_INFO | 0x000, + + /** End of SW Success status codes */ + BASE_JD_EVENT_RANGE_SW_SUCCESS_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_RESERVED | 0x3FF, + + /** Start of Kernel-only status codes. Such codes are never returned to user-space */ + BASE_JD_EVENT_RANGE_KERNEL_ONLY_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | 0x000, + BASE_JD_EVENT_REMOVED_FROM_NEXT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | BASE_JD_SW_EVENT_JOB | 0x000, + + /** End of Kernel-only status codes. */ + BASE_JD_EVENT_RANGE_KERNEL_ONLY_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | BASE_JD_SW_EVENT_RESERVED | 0x3FF +} base_jd_event_code; + +/** + * @brief Event reporting structure + * + * This structure is used by the kernel driver to report information + * about GPU events. The can either be HW-specific events or low-level + * SW events, such as job-chain completion. + * + * The event code contains an event type field which can be extracted + * by ANDing with ::BASE_JD_SW_EVENT_TYPE_MASK. + * + * Based on the event type base_jd_event::data holds: + * @li ::BASE_JD_SW_EVENT_JOB : the offset in the ring-buffer for the completed + * job-chain + * @li ::BASE_JD_SW_EVENT_BAG : The address of the ::base_jd_bag that has + * been completed (ie all contained job-chains have been completed). + * @li ::BASE_JD_SW_EVENT_INFO : base_jd_event::data not used + */ +typedef struct base_jd_event_v2 { + base_jd_event_code event_code; /**< event code */ + base_atom_id atom_number; /**< the atom number that has completed */ + struct base_jd_udata udata; /**< user data */ +} base_jd_event_v2; + +/** + * Padding required to ensure that the @ref struct base_dump_cpu_gpu_counters structure fills + * a full cache line. + */ + +#define BASE_CPU_GPU_CACHE_LINE_PADDING (36) + + +/** + * @brief Structure for BASE_JD_REQ_SOFT_DUMP_CPU_GPU_COUNTERS jobs. + * + * This structure is stored into the memory pointed to by the @c jc field of @ref base_jd_atom. + * + * This structure must be padded to ensure that it will occupy whole cache lines. This is to avoid + * cases where access to pages containing the structure is shared between cached and un-cached + * memory regions, which would cause memory corruption. Here we set the structure size to be 64 bytes + * which is the cache line for ARM A15 processors. + */ + +typedef struct base_dump_cpu_gpu_counters { + u64 system_time; + u64 cycle_counter; + u64 sec; + u32 usec; + u8 padding[BASE_CPU_GPU_CACHE_LINE_PADDING]; +} base_dump_cpu_gpu_counters; + + + +/** @} end group base_user_api_job_dispatch */ + +#ifdef __KERNEL__ +/* + * The following typedefs should be removed when a midg types header is added. + * See MIDCOM-1657 for details. + */ +typedef u32 midg_product_id; +typedef u32 midg_cache_features; +typedef u32 midg_tiler_features; +typedef u32 midg_mem_features; +typedef u32 midg_mmu_features; +typedef u32 midg_js_features; +typedef u32 midg_as_present; +typedef u32 midg_js_present; + +#define MIDG_MAX_JOB_SLOTS 16 + +#else +#include +#endif + +/** + * @page page_base_user_api_gpuprops User-side Base GPU Property Query API + * + * The User-side Base GPU Property Query API encapsulates two + * sub-modules: + * + * - @ref base_user_api_gpuprops_dyn "Dynamic GPU Properties" + * - @ref base_plat_config_gpuprops "Base Platform Config GPU Properties" + * + * There is a related third module outside of Base, which is owned by the MIDG + * module: + * - @ref midg_gpuprops_static "Midgard Compile-time GPU Properties" + * + * Base only deals with properties that vary between different Midgard + * implementations - the Dynamic GPU properties and the Platform Config + * properties. + * + * For properties that are constant for the Midgard Architecture, refer to the + * MIDG module. However, we will discuss their relevance here just to + * provide background information. + * + * @section sec_base_user_api_gpuprops_about About the GPU Properties in Base and MIDG modules + * + * The compile-time properties (Platform Config, Midgard Compile-time + * properties) are exposed as pre-processor macros. + * + * Complementing the compile-time properties are the Dynamic GPU + * Properties, which act as a conduit for the Midgard Configuration + * Discovery. + * + * In general, the dynamic properties are present to verify that the platform + * has been configured correctly with the right set of Platform Config + * Compile-time Properties. + * + * As a consistant guide across the entire DDK, the choice for dynamic or + * compile-time should consider the following, in order: + * -# Can the code be written so that it doesn't need to know the + * implementation limits at all? + * -# If you need the limits, get the information from the Dynamic Property + * lookup. This should be done once as you fetch the context, and then cached + * as part of the context data structure, so it's cheap to access. + * -# If there's a clear and arguable inefficiency in using Dynamic Properties, + * then use a Compile-Time Property (Platform Config, or Midgard Compile-time + * property). Examples of where this might be sensible follow: + * - Part of a critical inner-loop + * - Frequent re-use throughout the driver, causing significant extra load + * instructions or control flow that would be worthwhile optimizing out. + * + * We cannot provide an exhaustive set of examples, neither can we provide a + * rule for every possible situation. Use common sense, and think about: what + * the rest of the driver will be doing; how the compiler might represent the + * value if it is a compile-time constant; whether an OEM shipping multiple + * devices would benefit much more from a single DDK binary, instead of + * insignificant micro-optimizations. + * + * @section sec_base_user_api_gpuprops_dyn Dynamic GPU Properties + * + * Dynamic GPU properties are presented in two sets: + * -# the commonly used properties in @ref base_gpu_props, which have been + * unpacked from GPU register bitfields. + * -# The full set of raw, unprocessed properties in @ref midg_raw_gpu_props + * (also a member of @ref base_gpu_props). All of these are presented in + * the packed form, as presented by the GPU registers themselves. + * + * @usecase The raw properties in @ref midg_raw_gpu_props are necessary to + * allow a user of the Mali Tools (e.g. PAT) to determine "Why is this device + * behaving differently?". In this case, all information about the + * configuration is potentially useful, but it does not need to be processed + * by the driver. Instead, the raw registers can be processed by the Mali + * Tools software on the host PC. + * + * The properties returned extend the Midgard Configuration Discovery + * registers. For example, GPU clock speed is not specified in the Midgard + * Architecture, but is necessary for OpenCL's clGetDeviceInfo() function. + * + * The GPU properties are obtained by a call to + * _mali_base_get_gpu_props(). This simply returns a pointer to a const + * base_gpu_props structure. It is constant for the life of a base + * context. Multiple calls to _mali_base_get_gpu_props() to a base context + * return the same pointer to a constant structure. This avoids cache pollution + * of the common data. + * + * This pointer must not be freed, because it does not point to the start of a + * region allocated by the memory allocator; instead, just close the @ref + * base_context. + * + * + * @section sec_base_user_api_gpuprops_config Platform Config Compile-time Properties + * + * The Platform Config File sets up gpu properties that are specific to a + * certain platform. Properties that are 'Implementation Defined' in the + * Midgard Architecture spec are placed here. + * + * @note Reference configurations are provided for Midgard Implementations, such as + * the Mali-T600 family. The customer need not repeat this information, and can select one of + * these reference configurations. For example, VA_BITS, PA_BITS and the + * maximum number of samples per pixel might vary between Midgard Implementations, but + * \b not for platforms using the Mali-T604. This information is placed in + * the reference configuration files. + * + * The System Integrator creates the following structure: + * - platform_XYZ + * - platform_XYZ/plat + * - platform_XYZ/plat/plat_config.h + * + * They then edit plat_config.h, using the example plat_config.h files as a + * guide. + * + * At the very least, the customer must set @ref CONFIG_GPU_CORE_TYPE, and will + * receive a helpful \#error message if they do not do this correctly. This + * selects the Reference Configuration for the Midgard Implementation. The rationale + * behind this decision (against asking the customer to write \#include + * in their plat_config.h) is as follows: + * - This mechanism 'looks' like a regular config file (such as Linux's + * .config) + * - It is difficult to get wrong in a way that will produce strange build + * errors: + * - They need not know where the mali_t600.h, other_midg_gpu.h etc. files are stored - and + * so they won't accidentally pick another file with 'mali_t600' in its name + * - When the build doesn't work, the System Integrator may think the DDK is + * doesn't work, and attempt to fix it themselves: + * - For the @ref CONFIG_GPU_CORE_TYPE mechanism, the only way to get past the + * error is to set @ref CONFIG_GPU_CORE_TYPE, and this is what the \#error tells + * you. + * - For a \#include mechanism, checks must still be made elsewhere, which the + * System Integrator may try working around by setting \#defines (such as + * VA_BITS) themselves in their plat_config.h. In the worst case, they may + * set the prevention-mechanism \#define of + * "A_CORRECT_MIDGARD_CORE_WAS_CHOSEN". + * - In this case, they would believe they are on the right track, because + * the build progresses with their fix, but with errors elsewhere. + * + * However, there is nothing to prevent the customer using \#include to organize + * their own configurations files hierarchically. + * + * The mechanism for the header file processing is as follows: + * + * @dot + digraph plat_config_mechanism { + rankdir=BT + size="6,6" + + "mali_base.h"; + "midg/midg.h"; + + node [ shape=box ]; + { + rank = same; ordering = out; + + "midg/midg_gpu_props.h"; + "base/midg_gpus/mali_t600.h"; + "base/midg_gpus/other_midg_gpu.h"; + } + { rank = same; "plat/plat_config.h"; } + { + rank = same; + "midg/midg.h" [ shape=box ]; + gpu_chooser [ label="" style="invisible" width=0 height=0 fixedsize=true ]; + select_gpu [ label="Mali-T600 | Other\n(select_gpu.h)" shape=polygon,sides=4,distortion=0.25 width=3.3 height=0.99 fixedsize=true ] ; + } + node [ shape=box ]; + { rank = same; "plat/plat_config.h"; } + { rank = same; "mali_base.h"; } + + "mali_base.h" -> "midg/midg.h" -> "midg/midg_gpu_props.h"; + "mali_base.h" -> "plat/plat_config.h" ; + "mali_base.h" -> select_gpu ; + + "plat/plat_config.h" -> gpu_chooser [style="dotted,bold" dir=none weight=4] ; + gpu_chooser -> select_gpu [style="dotted,bold"] ; + + select_gpu -> "base/midg_gpus/mali_t600.h" ; + select_gpu -> "base/midg_gpus/other_midg_gpu.h" ; + } + @enddot + * + * + * @section sec_base_user_api_gpuprops_kernel Kernel Operation + * + * During Base Context Create time, user-side makes a single kernel call: + * - A call to fill user memory with GPU information structures + * + * The kernel-side will fill the provided the entire processed @ref base_gpu_props + * structure, because this information is required in both + * user and kernel side; it does not make sense to decode it twice. + * + * Coherency groups must be derived from the bitmasks, but this can be done + * kernel side, and just once at kernel startup: Coherency groups must already + * be known kernel-side, to support chains that specify a 'Only Coherent Group' + * SW requirement, or 'Only Coherent Group with Tiler' SW requirement. + * + * @section sec_base_user_api_gpuprops_cocalc Coherency Group calculation + * Creation of the coherent group data is done at device-driver startup, and so + * is one-time. This will most likely involve a loop with CLZ, shifting, and + * bit clearing on the L2_PRESENT or L3_PRESENT masks, depending on whether the + * system is L2 or L2+L3 Coherent. The number of shader cores is done by a + * population count, since faulty cores may be disabled during production, + * producing a non-contiguous mask. + * + * The memory requirements for this algoirthm can be determined either by a u64 + * population count on the L2/L3_PRESENT masks (a LUT helper already is + * requried for the above), or simple assumption that there can be no more than + * 16 coherent groups, since core groups are typically 4 cores. + */ + +/** + * @addtogroup base_user_api_gpuprops User-side Base GPU Property Query APIs + * @{ + */ + +/** + * @addtogroup base_user_api_gpuprops_dyn Dynamic HW Properties + * @{ + */ + +#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3 + +#define BASE_MAX_COHERENT_GROUPS 16 + +struct mali_base_gpu_core_props { + /** + * Product specific value. + */ + midg_product_id product_id; + + /** + * Status of the GPU release. + * No defined values, but starts at 0 and increases by one for each release + * status (alpha, beta, EAC, etc.). + * 4 bit values (0-15). + */ + u16 version_status; + + /** + * Minor release number of the GPU. "P" part of an "RnPn" release number. + * 8 bit values (0-255). + */ + u16 minor_revision; + + /** + * Major release number of the GPU. "R" part of an "RnPn" release number. + * 4 bit values (0-15). + */ + u16 major_revision; + + u16 padding; + + /** + * @usecase GPU clock speed is not specified in the Midgard Architecture, but is + * necessary for OpenCL's clGetDeviceInfo() function. + */ + u32 gpu_speed_mhz; + + /** + * @usecase GPU clock max/min speed is required for computing best/worst case + * in tasks as job scheduling ant irq_throttling. (It is not specified in the + * Midgard Architecture). + */ + u32 gpu_freq_khz_max; + u32 gpu_freq_khz_min; + + /** + * Size of the shader program counter, in bits. + */ + u32 log2_program_counter_size; + + /** + * TEXTURE_FEATURES_x registers, as exposed by the GPU. This is a + * bitpattern where a set bit indicates that the format is supported. + * + * Before using a texture format, it is recommended that the corresponding + * bit be checked. + */ + u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + + /** + * Theoretical maximum memory available to the GPU. It is unlikely that a + * client will be able to allocate all of this memory for their own + * purposes, but this at least provides an upper bound on the memory + * available to the GPU. + * + * This is required for OpenCL's clGetDeviceInfo() call when + * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL GPU devices. The + * client will not be expecting to allocate anywhere near this value. + */ + u64 gpu_available_memory_size; +}; + +/** + * + * More information is possible - but associativity and bus width are not + * required by upper-level apis. + */ +struct mali_base_gpu_l2_cache_props { + u8 log2_line_size; + u8 log2_cache_size; + u8 num_l2_slices; /* Number of L2C slices. 1 or higher */ + u8 padding[5]; +}; + +struct mali_base_gpu_l3_cache_props { + u8 log2_line_size; + u8 log2_cache_size; + u8 padding[6]; +}; + +struct mali_base_gpu_tiler_props { + u32 bin_size_bytes; /* Max is 4*2^15 */ + u32 max_active_levels; /* Max is 2^15 */ +}; + +/** + * GPU threading system details. + */ +struct mali_base_gpu_thread_props { + u32 max_threads; /* Max. number of threads per core */ + u32 max_workgroup_size; /* Max. number of threads per workgroup */ + u32 max_barrier_size; /* Max. number of threads that can synchronize on a simple barrier */ + u16 max_registers; /* Total size [1..65535] of the register file available per core. */ + u8 max_task_queue; /* Max. tasks [1..255] which may be sent to a core before it becomes blocked. */ + u8 max_thread_group_split; /* Max. allowed value [1..15] of the Thread Group Split field. */ + u8 impl_tech; /* 0 = Not specified, 1 = Silicon, 2 = FPGA, 3 = SW Model/Emulation */ + u8 padding[7]; +}; + +/** + * @brief descriptor for a coherent group + * + * \c core_mask exposes all cores in that coherent group, and \c num_cores + * provides a cached population-count for that mask. + * + * @note Whilst all cores are exposed in the mask, not all may be available to + * the application, depending on the Kernel Job Scheduler policy. Therefore, + * the application should not further restrict the core mask itself, as it may + * result in an empty core mask. However, it can guarentee that there will be + * at least one core available for each core group exposed . + * + * @usecase Chains marked at certain user-side priorities (e.g. the Long-running + * (batch) priority ) can be prevented from running on entire core groups by the + * Kernel Chain Scheduler policy. + * + * @note if u64s must be 8-byte aligned, then this structure has 32-bits of wastage. + */ +struct mali_base_gpu_coherent_group { + u64 core_mask; /**< Core restriction mask required for the group */ + u16 num_cores; /**< Number of cores in the group */ + u16 padding[3]; +}; + +/** + * @brief Coherency group information + * + * Note that the sizes of the members could be reduced. However, the \c group + * member might be 8-byte aligned to ensure the u64 core_mask is 8-byte + * aligned, thus leading to wastage if the other members sizes were reduced. + * + * The groups are sorted by core mask. The core masks are non-repeating and do + * not intersect. + */ +struct mali_base_gpu_coherent_group_info { + u32 num_groups; + + /** + * Number of core groups (coherent or not) in the GPU. Equivalent to the number of L2 Caches. + * + * The GPU Counter dumping writes 2048 bytes per core group, regardless of + * whether the core groups are coherent or not. Hence this member is needed + * to calculate how much memory is required for dumping. + * + * @note Do not use it to work out how many valid elements are in the + * group[] member. Use num_groups instead. + */ + u32 num_core_groups; + + /** + * Coherency features of the memory, accessed by @ref midg_mem_features + * methods + */ + midg_mem_features coherency; + + u32 padding; + + /** + * Descriptors of coherent groups + */ + struct mali_base_gpu_coherent_group group[BASE_MAX_COHERENT_GROUPS]; +}; + +/** + * A complete description of the GPU's Hardware Configuration Discovery + * registers. + * + * The information is presented inefficiently for access. For frequent access, + * the values should be better expressed in an unpacked form in the + * base_gpu_props structure. + * + * @usecase The raw properties in @ref midg_raw_gpu_props are necessary to + * allow a user of the Mali Tools (e.g. PAT) to determine "Why is this device + * behaving differently?". In this case, all information about the + * configuration is potentially useful, but it does not need to be processed + * by the driver. Instead, the raw registers can be processed by the Mali + * Tools software on the host PC. + * + */ +struct midg_raw_gpu_props { + u64 shader_present; + u64 tiler_present; + u64 l2_present; + u64 l3_present; + + midg_cache_features l2_features; + midg_cache_features l3_features; + midg_mem_features mem_features; + midg_mmu_features mmu_features; + + midg_as_present as_present; + + u32 js_present; + midg_js_features js_features[MIDG_MAX_JOB_SLOTS]; + midg_tiler_features tiler_features; + u32 texture_features[3]; + + u32 gpu_id; + + u32 thread_max_threads; + u32 thread_max_workgroup_size; + u32 thread_max_barrier_size; + u32 thread_features; + + u32 padding; +}; + +/** + * Return structure for _mali_base_get_gpu_props(). + * + * NOTE: the raw_props member in this datastructure contains the register + * values from which the value of the other members are derived. The derived + * members exist to allow for efficient access and/or shielding the details + * of the layout of the registers. + * + */ +typedef struct mali_base_gpu_props { + struct mali_base_gpu_core_props core_props; + struct mali_base_gpu_l2_cache_props l2_props; + struct mali_base_gpu_l3_cache_props l3_props; + struct mali_base_gpu_tiler_props tiler_props; + struct mali_base_gpu_thread_props thread_props; + + /** This member is large, likely to be 128 bytes */ + struct midg_raw_gpu_props raw_props; + + /** This must be last member of the structure */ + struct mali_base_gpu_coherent_group_info coherency_info; +} base_gpu_props; + +/** @} end group base_user_api_gpuprops_dyn */ + +/** @} end group base_user_api_gpuprops */ + +/** + * @addtogroup base_user_api_core User-side Base core APIs + * @{ + */ + +/** + * \enum base_context_create_flags + * + * Flags to pass to ::base_context_init. + * Flags can be ORed together to enable multiple things. + * + * These share the same space as @ref basep_context_private_flags, and so must + * not collide with them. + */ +enum base_context_create_flags { + /** No flags set */ + BASE_CONTEXT_CREATE_FLAG_NONE = 0, + + /** Base context is embedded in a cctx object (flag used for CINSTR software counter macros) */ + BASE_CONTEXT_CCTX_EMBEDDED = (1u << 0), + + /** Base context is a 'System Monitor' context for Hardware counters. + * + * One important side effect of this is that job submission is disabled. */ + BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED = (1u << 1), + + /** Base context flag indicating a 'hint' that this context uses Compute + * Jobs only. + * + * Specifially, this means that it only sends atoms that do not + * contain the following @ref base_jd_core_req : + * - BASE_JD_REQ_FS + * - BASE_JD_REQ_T + * + * Violation of these requirements will cause the Job-Chains to be rejected. + * + * In addition, it is inadvisable for the atom's Job-Chains to contain Jobs + * of the following @ref midg_job_type (whilst it may work now, it may not + * work in future) : + * - @ref MIDG_JOB_VERTEX + * - @ref MIDG_JOB_GEOMETRY + * + * @note An alternative to using this is to specify the BASE_JD_REQ_ONLY_COMPUTE + * requirement in atoms. + */ + BASE_CONTEXT_HINT_ONLY_COMPUTE = (1u << 2) +}; + +/** + * Bitpattern describing the ::base_context_create_flags that can be passed to base_context_init() + */ +#define BASE_CONTEXT_CREATE_ALLOWED_FLAGS \ + (((u32)BASE_CONTEXT_CCTX_EMBEDDED) | \ + ((u32)BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) | \ + ((u32)BASE_CONTEXT_HINT_ONLY_COMPUTE)) + +/** + * Bitpattern describing the ::base_context_create_flags that can be passed to the kernel + */ +#define BASE_CONTEXT_CREATE_KERNEL_FLAGS \ + (((u32)BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) | \ + ((u32)BASE_CONTEXT_HINT_ONLY_COMPUTE)) + +/** + * Private flags used on the base context + * + * These start at bit 31, and run down to zero. + * + * They share the same space as @ref base_context_create_flags, and so must + * not collide with them. + */ +enum basep_context_private_flags { + /** Private flag tracking whether job descriptor dumping is disabled */ + BASEP_CONTEXT_FLAG_JOB_DUMP_DISABLED = (1 << 31) +}; + +/** @} end group base_user_api_core */ + +/** @} end group base_user_api */ + +/** + * @addtogroup base_plat_config_gpuprops Base Platform Config GPU Properties + * @{ + * + * C Pre-processor macros are exposed here to do with Platform + * Config. + * + * These include: + * - GPU Properties that are constant on a particular Midgard Family + * Implementation e.g. Maximum samples per pixel on Mali-T600. + * - General platform config for the GPU, such as the GPU major and minor + * revison. + */ + +/** @} end group base_plat_config_gpuprops */ + +/** + * @addtogroup base_api Base APIs + * @{ + */ + +/** + * @brief The payload for a replay job. This must be in GPU memory. + */ +typedef struct base_jd_replay_payload { + /** + * Pointer to the first entry in the base_jd_replay_jc list. These + * will be replayed in @b reverse order (so that extra ones can be added + * to the head in future soft jobs without affecting this soft job) + */ + mali_addr64 tiler_jc_list; + + /** + * Pointer to the fragment job chain. + */ + mali_addr64 fragment_jc; + + /** + * Pointer to the tiler heap free FBD field to be modified. + */ + mali_addr64 tiler_heap_free; + + /** + * Hierarchy mask for the replayed fragment jobs. May be zero. + */ + u16 fragment_hierarchy_mask; + + /** + * Hierarchy mask for the replayed tiler jobs. May be zero. + */ + u16 tiler_hierarchy_mask; + + /** + * Default weight to be used for hierarchy levels not in the original + * mask. + */ + u32 hierarchy_default_weight; + + /** + * Core requirements for the tiler job chain + */ + base_jd_core_req tiler_core_req; + + /** + * Core requirements for the fragment job chain + */ + base_jd_core_req fragment_core_req; + + u8 padding[4]; +} base_jd_replay_payload; + +/** + * @brief An entry in the linked list of job chains to be replayed. This must + * be in GPU memory. + */ +typedef struct base_jd_replay_jc { + /** + * Pointer to next entry in the list. A setting of NULL indicates the + * end of the list. + */ + mali_addr64 next; + + /** + * Pointer to the job chain. + */ + mali_addr64 jc; + +} base_jd_replay_jc; + +/* Maximum number of jobs allowed in a fragment chain in the payload of a + * replay job */ +#define BASE_JD_REPLAY_F_CHAIN_JOB_LIMIT 256 + +/** @} end group base_api */ + +typedef struct base_profiling_controls { + u32 profiling_controls[FBDUMP_CONTROL_MAX]; +} base_profiling_controls; + +#endif /* _BASE_KERNEL_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_kernel_sync.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_kernel_sync.h new file mode 100644 index 0000000000000000000000000000000000000000..01a837cfae8bfcb8e1b2bbb837df533dfecfb6dd --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_kernel_sync.h @@ -0,0 +1,47 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Base cross-proccess sync API. + */ + +#ifndef _BASE_KERNEL_SYNC_H_ +#define _BASE_KERNEL_SYNC_H_ + +#include + +#define STREAM_IOC_MAGIC '~' + +/* Fence insert. + * + * Inserts a fence on the stream operated on. + * Fence can be waited via a base fence wait soft-job + * or triggered via a base fence trigger soft-job. + * + * Fences must be cleaned up with close when no longer needed. + * + * No input/output arguments. + * Returns + * >=0 fd + * <0 error code + */ +#define STREAM_IOC_FENCE_INSERT _IO(STREAM_IOC_MAGIC, 0) + +#endif /* _BASE_KERNEL_SYNC_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_mem_priv.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_mem_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..40942283824ad0a57744f8a977cb0e458c92e2d8 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_mem_priv.h @@ -0,0 +1,52 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _BASE_MEM_PRIV_H_ +#define _BASE_MEM_PRIV_H_ + +#define BASE_SYNCSET_OP_MSYNC (1U << 0) +#define BASE_SYNCSET_OP_CSYNC (1U << 1) + +/* + * This structure describe a basic memory coherency operation. + * It can either be: + * @li a sync from CPU to Memory: + * - type = ::BASE_SYNCSET_OP_MSYNC + * - mem_handle = a handle to the memory object on which the operation + * is taking place + * - user_addr = the address of the range to be synced + * - size = the amount of data to be synced, in bytes + * - offset is ignored. + * @li a sync from Memory to CPU: + * - type = ::BASE_SYNCSET_OP_CSYNC + * - mem_handle = a handle to the memory object on which the operation + * is taking place + * - user_addr = the address of the range to be synced + * - size = the amount of data to be synced, in bytes. + * - offset is ignored. + */ +typedef struct basep_syncset { + base_mem_handle mem_handle; + u64 user_addr; + u64 size; + u8 type; + u8 padding[7]; +} basep_syncset; + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_vendor_specific_func.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_vendor_specific_func.h new file mode 100644 index 0000000000000000000000000000000000000000..ce02e8b8e2bb8aab9a38cfc5d2ab222fcb3c8711 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_base_vendor_specific_func.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#ifndef _BASE_VENDOR_SPEC_FUNC_H_ +#define _BASE_VENDOR_SPEC_FUNC_H_ + +#include + +mali_error kbase_get_vendor_specific_cpu_clock_speed(u32 * const); + +#endif /*_BASE_VENDOR_SPEC_FUNC_H_*/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase.h new file mode 100644 index 0000000000000000000000000000000000000000..e94681f474af820255ff658d5c70b36678308617 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase.h @@ -0,0 +1,558 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_H_ +#define _KBASE_H_ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mali_base_kernel.h" +#include +#include + +#include "mali_kbase_pm.h" +#include "mali_kbase_mem_lowlevel.h" +#include "mali_kbase_defs.h" +#include "mali_kbase_trace_timeline.h" +#include "mali_kbase_js.h" +#include "mali_kbase_mem.h" +#include "mali_kbase_security.h" +#include "mali_kbase_utility.h" +#include "mali_kbase_gpu_memory_debugfs.h" +#include "mali_kbase_mem_profile_debugfs.h" +#include "mali_kbase_jd_debugfs.h" +#include "mali_kbase_cpuprops.h" +#include "mali_kbase_gpuprops.h" +#ifdef CONFIG_GPU_TRACEPOINTS +#include +#endif +/** + * @page page_base_kernel_main Kernel-side Base (KBase) APIs + * + * The Kernel-side Base (KBase) APIs are divided up as follows: + * - @subpage page_kbase_js_policy + */ + +/** + * @defgroup base_kbase_api Kernel-side Base (KBase) APIs + */ + +struct kbase_device *kbase_device_alloc(void); +/* +* note: configuration attributes member of kbdev needs to have +* been setup before calling kbase_device_init +*/ + +/* +* API to acquire device list semaphone and return pointer +* to the device list head +*/ +const struct list_head *kbase_dev_list_get(void); +/* API to release the device list semaphore */ +void kbase_dev_list_put(const struct list_head *dev_list); + +mali_error kbase_device_init(struct kbase_device * const kbdev); +void kbase_device_term(struct kbase_device *kbdev); +void kbase_device_free(struct kbase_device *kbdev); +int kbase_device_has_feature(struct kbase_device *kbdev, u32 feature); +struct kbase_device *kbase_find_device(int minor); /* Only needed for gator integration */ +void kbase_release_device(struct kbase_device *kbdev); + +void kbase_set_profiling_control(struct kbase_device *kbdev, u32 control, u32 value); + +u32 kbase_get_profiling_control(struct kbase_device *kbdev, u32 control); + +/** + * Ensure that all IRQ handlers have completed execution + * + * @param kbdev The kbase device + */ +void kbase_synchronize_irqs(struct kbase_device *kbdev); +void kbase_synchronize_irqs(struct kbase_device *kbdev); + +struct kbase_context * +kbase_create_context(struct kbase_device *kbdev, bool is_compat); +void kbase_destroy_context(struct kbase_context *kctx); +mali_error kbase_context_set_create_flags(struct kbase_context *kctx, u32 flags); + +mali_error kbase_instr_hwcnt_setup(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup); +mali_error kbase_instr_hwcnt_enable(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup); +mali_error kbase_instr_hwcnt_disable(struct kbase_context *kctx); +mali_error kbase_instr_hwcnt_clear(struct kbase_context *kctx); +mali_error kbase_instr_hwcnt_dump(struct kbase_context *kctx); +mali_error kbase_instr_hwcnt_dump_irq(struct kbase_context *kctx); +mali_bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx, mali_bool * const success); +void kbase_instr_hwcnt_suspend(struct kbase_device *kbdev); +void kbase_instr_hwcnt_resume(struct kbase_device *kbdev); + +void kbasep_cache_clean_worker(struct work_struct *data); +void kbase_clean_caches_done(struct kbase_device *kbdev); + +/** + * The GPU has completed performance count sampling successfully. + */ +void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev); + +mali_error kbase_jd_init(struct kbase_context *kctx); +void kbase_jd_exit(struct kbase_context *kctx); +#ifdef BASE_LEGACY_UK6_SUPPORT +mali_error kbase_jd_submit(struct kbase_context *kctx, + const struct kbase_uk_job_submit *submit_data, + int uk6_atom); +#else +mali_error kbase_jd_submit(struct kbase_context *kctx, + const struct kbase_uk_job_submit *submit_data); +#endif +void kbase_jd_done(struct kbase_jd_atom *katom, int slot_nr, ktime_t *end_timestamp, + kbasep_js_atom_done_code done_code); +void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom); +void kbase_jd_zap_context(struct kbase_context *kctx); +mali_bool jd_done_nolock(struct kbase_jd_atom *katom); +void kbase_jd_free_external_resources(struct kbase_jd_atom *katom); +mali_bool jd_submit_atom(struct kbase_context *kctx, + const struct base_jd_atom_v2 *user_atom, + struct kbase_jd_atom *katom); + +mali_error kbase_job_slot_init(struct kbase_device *kbdev); +void kbase_job_slot_halt(struct kbase_device *kbdev); +void kbase_job_slot_term(struct kbase_device *kbdev); +void kbase_job_done(struct kbase_device *kbdev, u32 done); +void kbase_job_zap_context(struct kbase_context *kctx); + +void kbase_job_slot_softstop(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom); +void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom, u32 sw_flags); +void kbase_job_slot_hardstop(struct kbase_context *kctx, int js, + struct kbase_jd_atom *target_katom); +void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, + u16 core_reqs, struct kbase_jd_atom *target_katom); +void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, + struct kbase_jd_atom *target_katom); + +void kbase_event_post(struct kbase_context *ctx, struct kbase_jd_atom *event); +int kbase_event_dequeue(struct kbase_context *ctx, struct base_jd_event_v2 *uevent); +int kbase_event_pending(struct kbase_context *ctx); +mali_error kbase_event_init(struct kbase_context *kctx); +void kbase_event_close(struct kbase_context *kctx); +void kbase_event_cleanup(struct kbase_context *kctx); +void kbase_event_wakeup(struct kbase_context *kctx); + +int kbase_process_soft_job(struct kbase_jd_atom *katom); +mali_error kbase_prepare_soft_job(struct kbase_jd_atom *katom); +void kbase_finish_soft_job(struct kbase_jd_atom *katom); +void kbase_cancel_soft_job(struct kbase_jd_atom *katom); +void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev); + +bool kbase_replay_process(struct kbase_jd_atom *katom); + +/* api used internally for register access. Contains validation and tracing */ +void kbase_reg_write(struct kbase_device *kbdev, u16 offset, u32 value, struct kbase_context *kctx); +u32 kbase_reg_read(struct kbase_device *kbdev, u16 offset, struct kbase_context *kctx); +void kbase_device_trace_register_access(struct kbase_context *kctx, enum kbase_reg_access_type type, u16 reg_offset, u32 reg_value); +void kbase_device_trace_buffer_install(struct kbase_context *kctx, u32 *tb, size_t size); +void kbase_device_trace_buffer_uninstall(struct kbase_context *kctx); + +/* api to be ported per OS, only need to do the raw register access */ +void kbase_os_reg_write(struct kbase_device *kbdev, u16 offset, u32 value); +u32 kbase_os_reg_read(struct kbase_device *kbdev, u16 offset); + +void kbasep_as_do_poke(struct work_struct *work); + +/** Report a GPU fault. + * + * This function is called from the interrupt handler when a GPU fault occurs. + * It reports the details of the fault using KBASE_DEBUG_PRINT_WARN. + * + * @param kbdev The kbase device that the GPU fault occurred from. + * @param multiple Zero if only GPU_FAULT was raised, non-zero if MULTIPLE_GPU_FAULTS was also set + */ +void kbase_report_gpu_fault(struct kbase_device *kbdev, int multiple); + +/** Kill all jobs that are currently running from a context + * + * This is used in response to a page fault to remove all jobs from the faulting context from the hardware. + * + * @param kctx The context to kill jobs from + */ +void kbase_job_kill_jobs_from_context(struct kbase_context *kctx); + +/** + * GPU interrupt handler + * + * This function is called from the interrupt handler when a GPU irq is to be handled. + * + * @param kbdev The kbase device to handle an IRQ for + * @param val The value of the GPU IRQ status register which triggered the call + */ +void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val); + +/** + * Prepare for resetting the GPU. + * This function just soft-stops all the slots to ensure that as many jobs as possible are saved. + * + * The function returns a boolean which should be interpreted as follows: + * - MALI_TRUE - Prepared for reset, kbase_reset_gpu should be called. + * - MALI_FALSE - Another thread is performing a reset, kbase_reset_gpu should not be called. + * + * @return See description + */ +mali_bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev); + +/** + * Pre-locked version of @a kbase_prepare_to_reset_gpu. + * + * Identical to @a kbase_prepare_to_reset_gpu, except that the + * kbasep_js_device_data::runpool_irq::lock is externally locked. + * + * @see kbase_prepare_to_reset_gpu + */ +mali_bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev); + +/** Reset the GPU + * + * This function should be called after kbase_prepare_to_reset_gpu iff it returns MALI_TRUE. + * It should never be called without a corresponding call to kbase_prepare_to_reset_gpu. + * + * After this function is called (or not called if kbase_prepare_to_reset_gpu returned MALI_FALSE), + * the caller should wait for kbdev->reset_waitq to be signalled to know when the reset has completed. + */ +void kbase_reset_gpu(struct kbase_device *kbdev); + +/** + * Pre-locked version of @a kbase_reset_gpu. + * + * Identical to @a kbase_reset_gpu, except that the + * kbasep_js_device_data::runpool_irq::lock is externally locked. + * + * @see kbase_reset_gpu + */ +void kbase_reset_gpu_locked(struct kbase_device *kbdev); + +/** Returns the name associated with a Mali exception code + * + * @param[in] exception_code exception code + * @return name associated with the exception code + */ +const char *kbase_exception_name(u32 exception_code); + +/** + * Check whether a system suspend is in progress, or has already been suspended + * + * The caller should ensure that either kbdev->pm.active_count_lock is held, or + * a dmb was executed recently (to ensure the value is most + * up-to-date). However, without a lock the value could change afterwards. + * + * @return MALI_FALSE if a suspend is not in progress + * @return !=MALI_FALSE otherwise + */ +static INLINE mali_bool kbase_pm_is_suspending(struct kbase_device *kbdev) { + return kbdev->pm.suspending; +} + +/** + * Return the atom's ID, as was originally supplied by userspace in + * base_jd_atom_v2::atom_number + */ +static INLINE int kbase_jd_atom_id(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + int result; + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->kctx == kctx); + + result = katom - &kctx->jctx.atoms[0]; + KBASE_DEBUG_ASSERT(result >= 0 && result <= BASE_JD_ATOM_COUNT); + return result; +} + +/** + * Initialize the disjoint state + * + * The disjoint event count and state are both set to zero. + * + * Disjoint functions usage: + * + * The disjoint event count should be incremented whenever a disjoint event occurs. + * + * There are several cases which are regarded as disjoint behavior. Rather than just increment + * the counter during disjoint events we also increment the counter when jobs may be affected + * by what the GPU is currently doing. To facilitate this we have the concept of disjoint state. + * + * Disjoint state is entered during GPU reset and for the entire time that an atom is replaying + * (as part of the replay workaround). Increasing the disjoint state also increases the count of + * disjoint events. + * + * The disjoint state is then used to increase the count of disjoint events during job submission + * and job completion. Any atom submitted or completed while the disjoint state is greater than + * zero is regarded as a disjoint event. + * + * The disjoint event counter is also incremented immediately whenever a job is soft stopped + * and during context creation. + * + * @param kbdev The kbase device + */ +void kbase_disjoint_init(struct kbase_device *kbdev); + +/** + * Increase the count of disjoint events + * called when a disjoint event has happened + * + * @param kbdev The kbase device + */ +void kbase_disjoint_event(struct kbase_device *kbdev); + +/** + * Increase the count of disjoint events only if the GPU is in a disjoint state + * + * This should be called when something happens which could be disjoint if the GPU + * is in a disjoint state. The state refcount keeps track of this. + * + * @param kbdev The kbase device + */ +void kbase_disjoint_event_potential(struct kbase_device *kbdev); + +/** + * Returns the count of disjoint events + * + * @param kbdev The kbase device + * @return the count of disjoint events + */ +u32 kbase_disjoint_event_get(struct kbase_device *kbdev); + +/** + * Increment the refcount state indicating that the GPU is in a disjoint state. + * + * Also Increment the disjoint event count (calls @ref kbase_disjoint_event) + * eventually after the disjoint state has completed @ref kbase_disjoint_state_down + * should be called + * + * @param kbdev The kbase device + */ +void kbase_disjoint_state_up(struct kbase_device *kbdev); + +/** + * Decrement the refcount state + * + * Also Increment the disjoint event count (calls @ref kbase_disjoint_event) + * + * Called after @ref kbase_disjoint_state_up once the disjoint state is over + * + * @param kbdev The kbase device + */ +void kbase_disjoint_state_down(struct kbase_device *kbdev); + +/** + * If a job is soft stopped and the number of contexts is >= this value + * it is reported as a disjoint event + */ +#define KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD 2 + +#if KBASE_TRACE_ENABLE +#ifndef CONFIG_MALI_SYSTEM_TRACE +/** Add trace values about a job-slot + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, 0) + +/** Add trace values about a job-slot, with info + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, info_val) + +/** Add trace values about a ctx refcount + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, 0) +/** Add trace values about a ctx refcount, and info + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, info_val) + +/** Add trace values (no slot or refcount) + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD(kbdev, code, ctx, katom, gpu_addr, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + 0, 0, 0, info_val) + +/** Clear the trace */ +#define KBASE_TRACE_CLEAR(kbdev) \ + kbasep_trace_clear(kbdev) + +/** Dump the slot trace */ +#define KBASE_TRACE_DUMP(kbdev) \ + kbasep_trace_dump(kbdev) + +/** PRIVATE - do not use directly. Use KBASE_TRACE_ADD() instead */ +void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val); +/** PRIVATE - do not use directly. Use KBASE_TRACE_CLEAR() instead */ +void kbasep_trace_clear(struct kbase_device *kbdev); +#else /* #ifndef CONFIG_MALI_SYSTEM_TRACE */ +/* Dispatch kbase trace events as system trace events */ +#include +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot)\ + trace_mali_##code(jobslot, 0) + +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val)\ + trace_mali_##code(jobslot, info_val) + +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount)\ + trace_mali_##code(refcount, 0) + +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val)\ + trace_mali_##code(refcount, info_val) + +#define KBASE_TRACE_ADD(kbdev, code, ctx, katom, gpu_addr, info_val)\ + trace_mali_##code(gpu_addr, info_val) + +#define KBASE_TRACE_CLEAR(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#define KBASE_TRACE_DUMP(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) + +#endif /* #ifndef CONFIG_MALI_SYSTEM_TRACE */ +#else +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(jobslot);\ + } while (0) + +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(jobslot);\ + CSTD_UNUSED(info_val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(refcount);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(info_val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD(kbdev, code, subcode, ctx, katom, val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(subcode);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_CLEAR(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#define KBASE_TRACE_DUMP(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#endif /* KBASE_TRACE_ENABLE */ +/** PRIVATE - do not use directly. Use KBASE_TRACE_DUMP() instead */ +void kbasep_trace_dump(struct kbase_device *kbdev); +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.c new file mode 100644 index 0000000000000000000000000000000000000000..4ee29098eba34f00ffb9ea2f3d1ca7baffb4c0f4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.c @@ -0,0 +1,204 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#include +#include +#include + +/* This function is used to solve an HW issue with single iterator GPUs. + * If a fragment job is soft-stopped on the edge of its bounding box, can happen that the + * restart index is out of bounds and the rerun causes a tile range fault. If this happens + * we try to clamp the restart index to a correct value and rerun the job. + */ +/* Mask of X and Y coordinates for the coordinates words in the descriptors*/ +#define X_COORDINATE_MASK 0x00000FFF +#define Y_COORDINATE_MASK 0x0FFF0000 +/* Max number of words needed from the fragment shader job descriptor */ +#define JOB_HEADER_SIZE_IN_WORDS 10 +#define JOB_HEADER_SIZE (JOB_HEADER_SIZE_IN_WORDS*sizeof(u32)) + +/* Word 0: Status Word */ +#define JOB_DESC_STATUS_WORD 0 +/* Word 1: Restart Index */ +#define JOB_DESC_RESTART_INDEX_WORD 1 +/* Word 2: Fault address low word */ +#define JOB_DESC_FAULT_ADDR_LOW_WORD 2 +/* Word 8: Minimum Tile Coordinates */ +#define FRAG_JOB_DESC_MIN_TILE_COORD_WORD 8 +/* Word 9: Maximum Tile Coordinates */ +#define FRAG_JOB_DESC_MAX_TILE_COORD_WORD 9 + +int kbasep_10969_workaround_clamp_coordinates(struct kbase_jd_atom *katom) +{ + struct device *dev = katom->kctx->kbdev->dev; + u32 clamped = 0; + struct kbase_va_region *region; + phys_addr_t *page_array; + u64 page_index; + u32 offset = katom->jc & (~PAGE_MASK); + u32 *page_1 = NULL; + u32 *page_2 = NULL; + u32 job_header[JOB_HEADER_SIZE_IN_WORDS]; + void *dst = job_header; + u32 minX, minY, maxX, maxY; + u32 restartX, restartY; + struct page *p; + u32 copy_size; + + dev_warn(dev, "Called TILE_RANGE_FAULT workaround clamping function.\n"); + if (!(katom->core_req & BASE_JD_REQ_FS)) + return 0; + + kbase_gpu_vm_lock(katom->kctx); + region = kbase_region_tracker_find_region_enclosing_address(katom->kctx, + katom->jc); + if (!region || (region->flags & KBASE_REG_FREE)) + goto out_unlock; + + page_array = kbase_get_phy_pages(region); + if (!page_array) + goto out_unlock; + + page_index = (katom->jc >> PAGE_SHIFT) - region->start_pfn; + + p = pfn_to_page(PFN_DOWN(page_array[page_index])); + + /* we need the first 10 words of the fragment shader job descriptor. + * We need to check that the offset + 10 words is less that the page + * size otherwise we need to load the next page. + * page_size_overflow will be equal to 0 in case the whole descriptor + * is within the page > 0 otherwise. + */ + copy_size = MIN(PAGE_SIZE - offset, JOB_HEADER_SIZE); + + page_1 = kmap_atomic(p); + + /* page_1 is a u32 pointer, offset is expressed in bytes */ + page_1 += offset>>2; + dma_sync_single_for_cpu(katom->kctx->kbdev->dev, + kbase_dma_addr(p) + offset, + copy_size, DMA_BIDIRECTIONAL); + memcpy(dst, page_1, copy_size); + + /* The data needed overflows page the dimension, + * need to map the subsequent page */ + if (copy_size < JOB_HEADER_SIZE) { + p = pfn_to_page(PFN_DOWN(page_array[page_index + 1])); + page_2 = kmap_atomic(p); + + dma_sync_single_for_cpu(katom->kctx->kbdev->dev, + kbase_dma_addr(p), + JOB_HEADER_SIZE - copy_size, DMA_BIDIRECTIONAL); + memcpy(dst + copy_size, page_2, JOB_HEADER_SIZE - copy_size); + } + + /* We managed to correctly map one or two pages (in case of overflow) */ + /* Get Bounding Box data and restart index from fault address low word */ + minX = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & X_COORDINATE_MASK; + minY = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & Y_COORDINATE_MASK; + maxX = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & X_COORDINATE_MASK; + maxY = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & Y_COORDINATE_MASK; + restartX = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & X_COORDINATE_MASK; + restartY = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & Y_COORDINATE_MASK; + + dev_warn(dev, "Before Clamping:\n" + "Jobstatus: %08x\n" + "restartIdx: %08x\n" + "Fault_addr_low: %08x\n" + "minCoordsX: %08x minCoordsY: %08x\n" + "maxCoordsX: %08x maxCoordsY: %08x\n", + job_header[JOB_DESC_STATUS_WORD], + job_header[JOB_DESC_RESTART_INDEX_WORD], + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD], + minX, minY, + maxX, maxY); + + /* Set the restart index to the one which generated the fault*/ + job_header[JOB_DESC_RESTART_INDEX_WORD] = + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD]; + + if (restartX < minX) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (minX) | restartY; + dev_warn(dev, + "Clamping restart X index to minimum. %08x clamped to %08x\n", + restartX, minX); + clamped = 1; + } + if (restartY < minY) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (minY) | restartX; + dev_warn(dev, + "Clamping restart Y index to minimum. %08x clamped to %08x\n", + restartY, minY); + clamped = 1; + } + if (restartX > maxX) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxX) | restartY; + dev_warn(dev, + "Clamping restart X index to maximum. %08x clamped to %08x\n", + restartX, maxX); + clamped = 1; + } + if (restartY > maxY) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxY) | restartX; + dev_warn(dev, + "Clamping restart Y index to maximum. %08x clamped to %08x\n", + restartY, maxY); + clamped = 1; + } + + if (clamped) { + /* Reset the fault address low word + * and set the job status to STOPPED */ + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] = 0x0; + job_header[JOB_DESC_STATUS_WORD] = BASE_JD_EVENT_STOPPED; + dev_warn(dev, "After Clamping:\n" + "Jobstatus: %08x\n" + "restartIdx: %08x\n" + "Fault_addr_low: %08x\n" + "minCoordsX: %08x minCoordsY: %08x\n" + "maxCoordsX: %08x maxCoordsY: %08x\n", + job_header[JOB_DESC_STATUS_WORD], + job_header[JOB_DESC_RESTART_INDEX_WORD], + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD], + minX, minY, + maxX, maxY); + + /* Flush CPU cache to update memory for future GPU reads*/ + memcpy(page_1, dst, copy_size); + p = pfn_to_page(PFN_DOWN(page_array[page_index])); + dma_sync_single_for_device(katom->kctx->kbdev->dev, + kbase_dma_addr(p) + offset, + copy_size, DMA_TO_DEVICE); + + if (copy_size < JOB_HEADER_SIZE) { + memcpy(page_2, dst + copy_size, + JOB_HEADER_SIZE - copy_size); + p = pfn_to_page(PFN_DOWN(page_array[page_index + 1])); + dma_sync_single_for_device(katom->kctx->kbdev->dev, + kbase_dma_addr(p), + JOB_HEADER_SIZE - copy_size, + DMA_TO_DEVICE); + } + } + if (copy_size < JOB_HEADER_SIZE) + kunmap_atomic(page_2); + + kunmap_atomic(page_1); + +out_unlock: + kbase_gpu_vm_unlock(katom->kctx); + return clamped; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.h new file mode 100644 index 0000000000000000000000000000000000000000..90bd027be30af875b64bf1af23d3595accd051e1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.h @@ -0,0 +1,23 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_10969_WORKAROUND_ +#define _KBASE_10969_WORKAROUND_ + +int kbasep_10969_workaround_clamp_coordinates(struct kbase_jd_atom *katom); + +#endif /* _KBASE_10969_WORKAROUND_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c new file mode 100644 index 0000000000000000000000000000000000000000..a1c3aa88307b40a361fe2ad217e6381f1d3eb8d0 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c @@ -0,0 +1,41 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_cache_policy.h + * Cache Policy API. + */ + +#include "mali_kbase_cache_policy.h" + +/* + * The output flags should be a combination of the following values: + * KBASE_REG_CPU_CACHED: CPU cache should be enabled + */ +u32 kbase_cache_enabled(u32 flags, u32 nr_pages) +{ + u32 cache_flags = 0; + + CSTD_UNUSED(nr_pages); + + if (flags & BASE_MEM_CACHED_CPU) + cache_flags |= KBASE_REG_CPU_CACHED; + + return cache_flags; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h new file mode 100644 index 0000000000000000000000000000000000000000..70f8a4c8ada21472d1e9924503bf23668e1defcf --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h @@ -0,0 +1,47 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_cache_policy.h + * Cache Policy API. + */ + +#ifndef _KBASE_CACHE_POLICY_H_ +#define _KBASE_CACHE_POLICY_H_ + +#include +#include "mali_kbase.h" +#include "mali_base_kernel.h" + +/** + * @brief Choose the cache policy for a specific region + * + * Tells whether the CPU and GPU caches should be enabled or not for a specific region. + * This function can be modified to customize the cache policy depending on the flags + * and size of the region. + * + * @param[in] flags flags describing attributes of the region + * @param[in] nr_pages total number of pages (backed or not) for the region + * + * @return a combination of KBASE_REG_CPU_CACHED and KBASE_REG_GPU_CACHED depending + * on the cache policy + */ +u32 kbase_cache_enabled(u32 flags, u32 nr_pages); + +#endif /* _KBASE_CACHE_POLICY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config.c new file mode 100644 index 0000000000000000000000000000000000000000..88315acf42638f41e38b72fc05eb8ec85408496e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config.c @@ -0,0 +1,292 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include + +/* Specifies how many attributes are permitted in the config (excluding terminating attribute). + * This is used in validation function so we can detect if configuration is properly terminated. This value can be + * changed if we need to introduce more attributes or many memory regions need to be defined */ +#define ATTRIBUTE_COUNT_MAX 32 + +int kbasep_get_config_attribute_count(const struct kbase_attribute *attributes) +{ + int count = 1; + + if (!attributes) + return -EINVAL; + + while (attributes->id != KBASE_CONFIG_ATTR_END) { + attributes++; + count++; + } + + return count; +} + +const struct kbase_attribute *kbasep_get_next_attribute(const struct kbase_attribute *attributes, int attribute_id) +{ + KBASE_DEBUG_ASSERT(attributes != NULL); + + while (attributes->id != KBASE_CONFIG_ATTR_END) { + if (attributes->id == attribute_id) + return attributes; + + attributes++; + } + return NULL; +} + +KBASE_EXPORT_TEST_API(kbasep_get_next_attribute) + +int kbase_cpuprops_get_default_clock_speed(u32 * const clock_speed) +{ + KBASE_DEBUG_ASSERT(NULL != clock_speed); + + *clock_speed = 100; + return 0; +} + +uintptr_t kbasep_get_config_value(struct kbase_device *kbdev, const struct kbase_attribute *attributes, int attribute_id) +{ + const struct kbase_attribute *attr; + + KBASE_DEBUG_ASSERT(attributes != NULL); + + attr = kbasep_get_next_attribute(attributes, attribute_id); + if (attr != NULL) + return attr->data; + + /* default values */ + switch (attribute_id) { + /* Begin scheduling defaults */ + case KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS: + return DEFAULT_JS_SCHEDULING_TICK_NS; + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS: + return DEFAULT_JS_SOFT_STOP_TICKS; + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL: + return DEFAULT_JS_SOFT_STOP_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS: + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + return DEFAULT_JS_HARD_STOP_TICKS_SS_HW_ISSUE_8408; + else + return DEFAULT_JS_HARD_STOP_TICKS_SS; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL: + return DEFAULT_JS_HARD_STOP_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS: + return DEFAULT_JS_HARD_STOP_TICKS_NSS; + case KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS: + return DEFAULT_JS_CTX_TIMESLICE_NS; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS: + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + return DEFAULT_JS_RESET_TICKS_SS_HW_ISSUE_8408; + else + return DEFAULT_JS_RESET_TICKS_SS; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL: + return DEFAULT_JS_RESET_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS: + return DEFAULT_JS_RESET_TICKS_NSS; + case KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS: + return DEFAULT_JS_RESET_TIMEOUT_MS; + /* End scheduling defaults */ + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS: + return 0; + case KBASE_CONFIG_ATTR_PLATFORM_FUNCS: + return 0; + case KBASE_CONFIG_ATTR_CPU_SPEED_FUNC: + return DEFAULT_CPU_SPEED_FUNC; + case KBASE_CONFIG_ATTR_GPU_SPEED_FUNC: + return 0; + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ: + return DEFAULT_PM_DVFS_FREQ; + case KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: + return DEFAULT_PM_GPU_POWEROFF_TICK_NS; + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER: + return DEFAULT_PM_POWEROFF_TICK_SHADER; + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU: + return DEFAULT_PM_POWEROFF_TICK_GPU; + case KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS: + return 0; + + default: + dev_err(kbdev->dev, "kbasep_get_config_value. Cannot get value of attribute with id=%d and no default value defined", attribute_id); + return 0; + } +} + +KBASE_EXPORT_TEST_API(kbasep_get_config_value) + +mali_bool kbasep_platform_device_init(struct kbase_device *kbdev) +{ + struct kbase_platform_funcs_conf *platform_funcs; + + platform_funcs = (struct kbase_platform_funcs_conf *)kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PLATFORM_FUNCS); + if (platform_funcs) { + if (platform_funcs->platform_init_func) + return platform_funcs->platform_init_func(kbdev); + } + return MALI_TRUE; +} + +void kbasep_platform_device_term(struct kbase_device *kbdev) +{ + struct kbase_platform_funcs_conf *platform_funcs; + + platform_funcs = (struct kbase_platform_funcs_conf *)kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PLATFORM_FUNCS); + if (platform_funcs) { + if (platform_funcs->platform_term_func) + platform_funcs->platform_term_func(kbdev); + } +} + +static mali_bool kbasep_validate_pm_callback(const struct kbase_pm_callback_conf *callbacks, const struct kbase_device *kbdev) +{ + if (callbacks == NULL) { + /* Having no callbacks is valid */ + return MALI_TRUE; + } + + if ((callbacks->power_off_callback != NULL && callbacks->power_on_callback == NULL) || (callbacks->power_off_callback == NULL && callbacks->power_on_callback != NULL)) { + dev_warn(kbdev->dev, "Invalid power management callbacks: Only one of power_off_callback and power_on_callback was specified"); + return MALI_FALSE; + } + return MALI_TRUE; +} + +static mali_bool kbasep_validate_cpu_speed_func(kbase_cpuprops_clock_speed_function fcn) +{ + return fcn != NULL; +} + +mali_bool kbasep_validate_configuration_attributes(struct kbase_device *kbdev, const struct kbase_attribute *attributes) +{ + int i; + + KBASE_DEBUG_ASSERT(attributes); + + for (i = 0; attributes[i].id != KBASE_CONFIG_ATTR_END; i++) { + if (i >= ATTRIBUTE_COUNT_MAX) { + dev_warn(kbdev->dev, "More than ATTRIBUTE_COUNT_MAX=%d configuration attributes defined. Is attribute list properly terminated?", ATTRIBUTE_COUNT_MAX); + return MALI_FALSE; + } + + switch (attributes[i].id) { + /* Only non-zero unsigned 32-bit values accepted */ + case KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS: +#if CSTD_CPU_64BIT + if (attributes[i].data == 0u || (u64) attributes[i].data > (u64) U32_MAX) { +#else + if (attributes[i].data == 0u) { +#endif + dev_warn(kbdev->dev, "Invalid Job Scheduling Configuration attribute for " "KBASE_CONFIG_ATTR_JS_SCHEDULING_TICKS_NS: %d", (int)attributes[i].data); + return MALI_FALSE; + } + break; + + /* All these Job Scheduling attributes are FALLTHROUGH: only unsigned 32-bit values accepted */ + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS: + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS: + case KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS: + case KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "Job Scheduling Configuration attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS: + if (MALI_FALSE == kbasep_validate_pm_callback((struct kbase_pm_callback_conf *)attributes[i].data, kbdev)) { + /* Warning message handled by kbasep_validate_pm_callback() */ + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_CPU_SPEED_FUNC: + if (MALI_FALSE == kbasep_validate_cpu_speed_func((kbase_cpuprops_clock_speed_function) attributes[i].data)) { + dev_warn(kbdev->dev, "Invalid function pointer in KBASE_CONFIG_ATTR_CPU_SPEED_FUNC"); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_GPU_SPEED_FUNC: + if (0 == attributes[i].data) { + dev_warn(kbdev->dev, "Invalid function pointer in KBASE_CONFIG_ATTR_GPU_SPEED_FUNC"); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_PLATFORM_FUNCS: + /* any value is allowed */ + break; + + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "PM DVFS interval exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: +#if CSTD_CPU_64BIT + if (attributes[i].data == 0u || (u64) attributes[i].data > (u64) U32_MAX) { +#else + if (attributes[i].data == 0u) { +#endif + dev_warn(kbdev->dev, "Invalid Power Manager Configuration attribute for " "KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: %d", (int)attributes[i].data); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER: + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "Power Manager Configuration attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS: + if (0 == attributes[i].data) { + dev_warn(kbdev->dev, "Power model callbacks is specified but NULL: " "id==%d val==%d", + attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } + break; + + default: + dev_warn(kbdev->dev, "Invalid attribute found in configuration: %d", attributes[i].id); + return MALI_FALSE; + } + } + + return MALI_TRUE; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config.h new file mode 100644 index 0000000000000000000000000000000000000000..3a1acf89ac7b48f98cf657191d19ea9ea92dfd5f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config.h @@ -0,0 +1,722 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_config.h + * Configuration API and Attributes for KBase + */ + +#ifndef _KBASE_CONFIG_H_ +#define _KBASE_CONFIG_H_ + +#include + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_config Configuration API and Attributes + * @{ + */ + +#if !MALI_CUSTOMER_RELEASE +/* This flag is set for internal builds so we can run tests without credentials. */ +#define KBASE_HWCNT_DUMP_BYPASS_ROOT 1 +#else +#define KBASE_HWCNT_DUMP_BYPASS_ROOT 0 +#endif + +/* Enable power management API, note that KBASE_PM_EN==0 is not supported */ +#define KBASE_PM_EN 1 +/* Enable GPU reset API, note that KBASE_GPU_RESET_EN==0 is not supported */ +#define KBASE_GPU_RESET_EN 1 +/* Enable HW MMU backend, note that KBASE_MMU_HW_BACKEND==0 is not supported */ +#define KBASE_MMU_HW_BACKEND 1 + + +#include + + +/** + * Device wide configuration + */ +enum { + /** + * Invalid attribute ID (reserve 0). + * + * Attached value: Ignored + * Default value: NA + * */ + KBASE_CONFIG_ATTR_INVALID, + + /*** Begin Job Scheduling Configs ***/ + /** + * Job Scheduler scheduling tick granuality. This is in nanoseconds to + * allow HR timer support. + * + * On each scheduling tick, the scheduler may decide to: + * -# soft stop a job (the job will be re-run later, and other jobs will + * be able to run on the GPU now). This effectively controls the + * 'timeslice' given to a job. + * -# hard stop a job (to kill a job if it has spent too long on the GPU + * and didn't soft-stop). + * + * The numbers of ticks for these events are controlled by: + * - @ref KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS + * - @ref KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS + * - @ref KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS + * + * A soft-stopped job will later be resumed, allowing it to use more GPU + * time in total than that defined by any of the above. However, + * the scheduling policy attempts to limit the amount of \em uninterrupted + * time spent on the GPU using the above values (that is, the 'timeslice' + * of a job) + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::scheduling_tick_ns. + * The value might be rounded down to lower precision. Must be non-zero + * after rounding.
+ * Default value: @ref DEFAULT_JS_SCHEDULING_TICK_NS + * + * @note this value is allowed to be greater than + * @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS. This allows jobs to run on (much) + * longer than the job-timeslice, but once this happens, the context gets + * scheduled in (much) less frequently than others that stay within the + * ctx-timeslice. + */ + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + + /** + * Job Scheduler minimum number of scheduling ticks before non-CL jobs + * are soft-stopped. + * + * This defines the amount of time a job is allowed to stay on the GPU, + * before it is soft-stopped to allow other jobs to run. + * + * That is, this defines the 'timeslice' of the job. It is separate from the + * timeslice of the context that contains the job (see + * @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS). + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::soft_stop_ticks
+ * Default value: @ref DEFAULT_JS_SOFT_STOP_TICKS + * + * @note a value of zero means "the quickest time to soft-stop a job", + * which is somewhere between instant and one tick later. + * + * @note this value is allowed to be greater than + * @ref KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS or + * @ref KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS. This effectively disables + * soft-stop, and just uses hard-stop instead. In this case, this value + * should be much greater than any of the hard stop values (to avoid + * soft-stop-after-hard-stop) + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + + /** + * Job Scheduler minimum number of scheduling ticks before CL jobs + * are soft-stopped. + * + * This defines the amount of time a job is allowed to stay on the GPU, + * before it is soft-stopped to allow other jobs to run. + * + * That is, this defines the 'timeslice' of the job. It is separate + * from the timeslice of the context that contains the job (see + * @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS). + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit + * kbasep_js_device_data::soft_stop_ticks_cl
+ * Default value: @ref DEFAULT_JS_SOFT_STOP_TICKS_CL + * + * @note a value of zero means "the quickest time to soft-stop a job", + * which is somewhere between instant and one tick later. + * + * @note this value is allowed to be greater than + * @ref KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL. This effectively + * disables soft-stop, and just uses hard-stop instead. In this case, + * this value should be much greater than any of the hard stop values + * (to avoid soft-stop-after-hard-stop) + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + + /** + * Job Scheduler minimum number of scheduling ticks before non-CL jobs + * are hard-stopped. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is killed. Such jobs won't be resumed if killed. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::hard_stop_ticks_ss
+ * Default value: @ref DEFAULT_JS_HARD_STOP_TICKS_SS + * + * @note a value of zero means "the quickest time to hard-stop a job", + * which is somewhere between instant and one tick later. + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + + /** + * Job Scheduler minimum number of scheduling ticks before CL jobs are hard-stopped. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is killed. Such jobs won't be resumed if killed. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::hard_stop_ticks_cl
+ * Default value: @ref DEFAULT_JS_HARD_STOP_TICKS_CL + * + * @note a value of zero means "the quickest time to hard-stop a job", + * which is somewhere between instant and one tick later. + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + + /** + * Job Scheduler minimum number of scheduling ticks before jobs are hard-stopped + * when dumping. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is killed. Such jobs won't be resumed if killed. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::hard_stop_ticks_nss
+ * Default value: @ref DEFAULT_JS_HARD_STOP_TICKS_NSS + * + * @note a value of zero means "the quickest time to hard-stop a job", + * which is somewhere between instant and one tick later. + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + + /** + * Job Scheduler timeslice that a context is scheduled in for, in nanoseconds. + * + * When a context has used up this amount of time across its jobs, it is + * scheduled out to let another run. + * + * @note the resolution is nanoseconds (ns) here, because that's the format + * often used by the OS. + * + * This value controls affects the actual time defined by the following + * defaults: + * - @ref DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES + * - @ref DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::ctx_timeslice_ns. + * The value might be rounded down to lower precision.
+ * Default value: @ref DEFAULT_JS_CTX_TIMESLICE_NS + * + * @note a value of zero models a "Round Robin" scheduling policy, and + * disables @ref DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES + * (initially causing LIFO scheduling) and + * @ref DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES (allowing + * not-run-often contexts to get scheduled in quickly, but to only use + * a single timeslice when they get scheduled in). + */ + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + + /** + * Job Scheduler minimum number of scheduling ticks before non-CL jobs + * cause the GPU to be reset. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is assumed that the GPU has hung and needs to be reset. The assumes that the job + * has been hard-stopped already and so the presence of a job that has remained on + * the GPU for so long indicates that the GPU has in some way hung. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::gpu_reset_ticks_nss
+ * Default value: @ref DEFAULT_JS_RESET_TICKS_SS + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + + /** + * Job Scheduler minimum number of scheduling ticks before CL jobs + * cause the GPU to be reset. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is assumed that the GPU has hung and needs to be reset. The assumes that the job + * has been hard-stopped already and so the presence of a job that has remained on + * the GPU for so long indicates that the GPU has in some way hung. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::gpu_reset_ticks_cl
+ * Default value: @ref DEFAULT_JS_RESET_TICKS_CL + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + + /** + * Job Scheduler minimum number of scheduling ticks before jobs cause the GPU to be + * reset when dumping. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is assumed that the GPU has hung and needs to be reset. The assumes that the job + * has been hard-stopped already and so the presence of a job that has remained on + * the GPU for so long indicates that the GPU has in some way hung. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::gpu_reset_ticks_nss
+ * Default value: @ref DEFAULT_JS_RESET_TICKS_NSS + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + + /** + * Number of milliseconds given for other jobs on the GPU to be + * soft-stopped when the GPU needs to be reset. + * + * Attached value: number in milliseconds + * Default value: @ref DEFAULT_JS_RESET_TIMEOUT_MS + */ + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + /*** End Job Scheduling Configs ***/ + + /** Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + + /** + * A pointer to a function that calculates the CPU clock + * speed of the platform in MHz - see + * @ref kbase_cpuprops_clock_speed_function for the function + * prototype. + * + * Attached value: A @ref kbase_cpuprops_clock_speed_function. + * Default Value: Pointer to @ref DEFAULT_CPU_SPEED_FUNC - + * returns a clock speed of 100 MHz. + */ + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + + /** + * A pointer to a function that calculates the GPU clock + * speed of the platform in MHz - see + * @ref kbase_gpuprops_clock_speed_function for the function + * prototype. + * + * Attached value: A @ref kbase_gpuprops_clock_speed_function. + * Default Value: NULL (in which case the driver assumes maximum + * GPU frequency stored in gpu_freq_khz_max) + */ + KBASE_CONFIG_ATTR_GPU_SPEED_FUNC, + + /** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ + KBASE_CONFIG_ATTR_PLATFORM_FUNCS, + + /** + * Rate at which dvfs data should be collected. + * + * Attached value: u32 value + * Default value: 500 Milliseconds + */ + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ, + + /** + * Power Management poweroff tick granuality. This is in nanoseconds to + * allow HR timer support. + * + * On each scheduling tick, the power manager core may decide to: + * -# Power off one or more shader cores + * -# Power off the entire GPU + * + * Attached value: number in nanoseconds + * Default value: @ref DEFAULT_PM_GPU_POWEROFF_TICK_NS, + */ + KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS, + + /** + * Power Manager number of ticks before shader cores are powered off + * + * Attached value: unsigned 32-bit kbasep_pm_device_data::poweroff_shader_ticks
+ * Default value: @ref DEFAULT_PM_POWEROFF_TICK_SHADER + * + * @see KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS + */ + KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER, + + /** + * Power Manager number of ticks before GPU is powered off + * + * Attached value: unsigned 32-bit kbasep_pm_device_data::poweroff_gpu_ticks
+ * Default value: @ref DEFAULT_PM_POWEROFF_TICK_GPU + * + * @see KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS + */ + KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU, + + /** Power model for IPA + * + * Attached value: pointer to @ref mali_pa_model_ops + */ + KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS, + + /** + * End of attribute list indicator. + * The configuration loader will stop processing any more elements + * when it encounters this attribute. + * + * Default value: NA + */ + KBASE_CONFIG_ATTR_END = 0x1FFFUL +}; + +/* + * @brief specifies a single attribute + * + * Attribute is identified by attr field. Data is either integer or a pointer to attribute-specific structure. + */ +typedef struct kbase_attribute { + int id; + uintptr_t data; +} kbase_attribute; + +/* Forward declaration of struct kbase_device */ +struct kbase_device; + +/* + * @brief Specifies the functions for platform specific initialization and termination + * + * By default no functions are required. No additional platform specific control is necessary. + */ +typedef struct kbase_platform_funcs_conf { + /** + * Function pointer for platform specific initialization or NULL if no initialization function is required. + * This function will be called \em before any other callbacks listed in the struct kbase_attribute struct (such as + * Power Management callbacks). + * The platform specific private pointer kbase_device::platform_context can be accessed (and possibly initialized) in here. + */ + mali_bool(*platform_init_func) (struct kbase_device *kbdev); + /** + * Function pointer for platform specific termination or NULL if no termination function is required. + * This function will be called \em after any other callbacks listed in the struct kbase_attribute struct (such as + * Power Management callbacks). + * The platform specific private pointer kbase_device::platform_context can be accessed (and possibly terminated) in here. + */ + void (*platform_term_func)(struct kbase_device *kbdev); + +} kbase_platform_funcs_conf; + +/* + * @brief Specifies the callbacks for power management + * + * By default no callbacks will be made and the GPU must not be powered off. + */ +typedef struct kbase_pm_callback_conf { + /** Callback for when the GPU is idle and the power to it can be switched off. + * + * The system integrator can decide whether to either do nothing, just switch off + * the clocks to the GPU, or to completely power down the GPU. + * The platform specific private pointer kbase_device::platform_context can be accessed and modified in here. It is the + * platform \em callbacks responsiblity to initialize and terminate this pointer if used (see @ref kbase_platform_funcs_conf). + */ + void (*power_off_callback)(struct kbase_device *kbdev); + + /** Callback for when the GPU is about to become active and power must be supplied. + * + * This function must not return until the GPU is powered and clocked sufficiently for register access to + * succeed. The return value specifies whether the GPU was powered down since the call to power_off_callback. + * If the GPU state has been lost then this function must return 1, otherwise it should return 0. + * The platform specific private pointer kbase_device::platform_context can be accessed and modified in here. It is the + * platform \em callbacks responsiblity to initialize and terminate this pointer if used (see @ref kbase_platform_funcs_conf). + * + * The return value of the first call to this function is ignored. + * + * @return 1 if the GPU state may have been lost, 0 otherwise. + */ + int (*power_on_callback)(struct kbase_device *kbdev); + + /** Callback for when the system is requesting a suspend and GPU power + * must be switched off. + * + * Note that if this callback is present, then this may be called + * without a preceding call to power_off_callback. Therefore this + * callback must be able to take any action that might otherwise happen + * in power_off_callback. + * + * The platform specific private pointer kbase_device::platform_context + * can be accessed and modified in here. It is the platform \em + * callbacks responsibility to initialize and terminate this pointer if + * used (see @ref kbase_platform_funcs_conf). + */ + void (*power_suspend_callback)(struct kbase_device *kbdev); + + /** Callback for when the system is resuming from a suspend and GPU + * power must be switched on. + * + * Note that if this callback is present, then this may be called + * without a following call to power_on_callback. Therefore this + * callback must be able to take any action that might otherwise happen + * in power_on_callback. + * + * The platform specific private pointer kbase_device::platform_context + * can be accessed and modified in here. It is the platform \em + * callbacks responsibility to initialize and terminate this pointer if + * used (see @ref kbase_platform_funcs_conf). + */ + void (*power_resume_callback)(struct kbase_device *kbdev); + + /** Callback for handling runtime power management initialization. + * + * The runtime power management callbacks @ref power_runtime_off_callback and @ref power_runtime_on_callback + * will become active from calls made to the OS from within this function. + * The runtime calls can be triggered by calls from @ref power_off_callback and @ref power_on_callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * + * @return MALI_ERROR_NONE on success, else mali_error erro code. + */ + mali_error(*power_runtime_init_callback) (struct kbase_device *kbdev); + + /** Callback for handling runtime power management termination. + * + * The runtime power management callbacks @ref power_runtime_off_callback and @ref power_runtime_on_callback + * should no longer be called by the OS on completion of this function. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + */ + void (*power_runtime_term_callback)(struct kbase_device *kbdev); + + /** Callback for runtime power-off power management callback + * + * For linux this callback will be called by the kernel runtime_suspend callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * + * @return 0 on success, else OS error code. + */ + void (*power_runtime_off_callback)(struct kbase_device *kbdev); + + /** Callback for runtime power-on power management callback + * + * For linux this callback will be called by the kernel runtime_resume callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + */ + int (*power_runtime_on_callback)(struct kbase_device *kbdev); + +} kbase_pm_callback_conf; + +/** + * @brief Default implementation of @ref KBASE_CONFIG_ATTR_CPU_SPEED_FUNC. + * + * This function sets clock_speed to 100, so will be an underestimate for + * any real system. + * + * See @ref kbase_cpuprops_clock_speed_function for details on the parameters + * and return value. + */ +int kbase_cpuprops_get_default_clock_speed(u32 * const clock_speed); + +/** + * Type of the function pointer for KBASE_CONFIG_ATTR_CPU_SPEED_FUNC. + * + * @param clock_speed [out] Once called this will contain the current CPU clock speed in MHz. + * This is mainly used to implement OpenCL's clGetDeviceInfo(). + * + * @return 0 on success, 1 on error. + */ +typedef int (*kbase_cpuprops_clock_speed_function) (u32 *clock_speed); + +/** + * Type of the function pointer for KBASE_CONFIG_ATTR_GPU_SPEED_FUNC. + * + * @param clock_speed [out] Once called this will contain the current GPU clock speed in MHz. + * If the system timer is not available then this function is required + * for the OpenCL queue profiling to return correct timing information. + * + * @return 0 on success, 1 on error. When an error is returned the caller assumes maximum + * GPU speed stored in gpu_freq_khz_max. + */ +typedef int (*kbase_gpuprops_clock_speed_function) (u32 *clock_speed); + +#ifdef CONFIG_OF +typedef struct kbase_platform_config { + const struct kbase_attribute *attributes; + u32 midgard_type; +} kbase_platform_config; +#else + +/* + * @brief Specifies start and end of I/O memory region. + */ +typedef struct kbase_io_memory_region { + u64 start; + u64 end; +} kbase_io_memory_region; + +/* + * @brief Specifies I/O related resources like IRQs and memory region for I/O operations. + */ +typedef struct kbase_io_resources { + + u32 job_irq_number; + u32 mmu_irq_number; + u32 gpu_irq_number; + struct kbase_io_memory_region io_memory_region; +} kbase_io_resources; + +typedef struct kbase_platform_config { + const struct kbase_attribute *attributes; + const struct kbase_io_resources *io_resources; + u32 midgard_type; +} kbase_platform_config; + +#endif /* CONFIG_OF */ + +/** + * @brief Return character string associated with the given midgard type. + * + * @param[in] midgard_type - ID of midgard type + * + * @return Pointer to NULL-terminated character array associated with the given midgard type + */ +const char *kbasep_midgard_type_to_string(u32 midgard_type); + +/** + * @brief Gets the next config attribute with the specified ID from the array of attributes. + * + * Function gets the next attribute with specified attribute id within specified array. If no such attribute is found, + * NULL is returned. + * + * @param[in] attributes Array of attributes in which lookup is performed + * @param[in] attribute_id ID of attribute + * + * @return Pointer to the first attribute matching id or NULL if none is found. + */ +const struct kbase_attribute *kbasep_get_next_attribute(const struct kbase_attribute *attributes, int attribute_id); + +/** + * @brief Gets the value of a single config attribute. + * + * Function gets the value of attribute specified as parameter. If no such attribute is found in the array of + * attributes, default value is used. + * + * @param[in] kbdev Kbase device pointer + * @param[in] attributes Array of attributes in which lookup is performed + * @param[in] attribute_id ID of attribute + * + * @return Value of attribute with the given id + */ +uintptr_t kbasep_get_config_value(struct kbase_device *kbdev, const struct kbase_attribute *attributes, int attribute_id); + +/** + * @brief Validates configuration attributes + * + * Function checks validity of given configuration attributes. It will fail on any attribute with unknown id, attribute + * with invalid value or attribute list that is not correctly terminated. + * + * @param[in] kbdev Kbase device pointer + * @param[in] attributes Array of attributes to validate + * + * @return MALI_TRUE if no errors have been found in the config. MALI_FALSE otherwise. + */ +mali_bool kbasep_validate_configuration_attributes(struct kbase_device *kbdev, const struct kbase_attribute *attributes); + +/** + * @brief Gets the pointer to platform config. + * + * @return Pointer to the platform config + */ +struct kbase_platform_config *kbase_get_platform_config(void); + +/** + * @brief Gets the count of attributes in array + * + * Function gets the count of attributes in array. Note that end of list indicator is also included. + * + * @param[in] attributes Array of attributes + * + * @return Number of attributes in the array including end of list indicator. + */ +int kbasep_get_config_attribute_count(const struct kbase_attribute *attributes); + +/** + * @brief Platform specific call to initialize hardware + * + * Function calls a platform defined routine if specified in the configuration attributes. + * The routine can initialize any hardware and context state that is required for the GPU block to function. + * + * @param[in] kbdev Kbase device pointer + * + * @return MALI_TRUE if no errors have been found in the config. MALI_FALSE otherwise. + */ +mali_bool kbasep_platform_device_init(struct kbase_device *kbdev); + +/** + * @brief Platform specific call to terminate hardware + * + * Function calls a platform defined routine if specified in the configuration attributes. + * The routine can destroy any platform specific context state and shut down any hardware functionality that are + * outside of the Power Management callbacks. + * + * @param[in] kbdev Kbase device pointer + * + */ +void kbasep_platform_device_term(struct kbase_device *kbdev); + + /** @} *//* end group kbase_config */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_CONFIG_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h new file mode 100644 index 0000000000000000000000000000000000000000..8204e611dd82a2bd3923664ad4a4971963e99ddc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h @@ -0,0 +1,288 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_config_defaults.h + * + * Default values for configuration settings + * + */ + +#ifndef _KBASE_CONFIG_DEFAULTS_H_ +#define _KBASE_CONFIG_DEFAULTS_H_ + +/* Include mandatory definitions per platform */ +#include + +/** + * Irq throttle. It is the minimum desired time in between two + * consecutive gpu interrupts (given in 'us'). The irq throttle + * gpu register will be configured after this, taking into + * account the configured max frequency. + * + * Attached value: number in micro seconds + */ +#define DEFAULT_IRQ_THROTTLE_TIME_US 20 + +/*** Begin Scheduling defaults ***/ + +/** + * Default scheduling tick granuality, in nanoseconds + */ +/* 50ms */ +#define DEFAULT_JS_SCHEDULING_TICK_NS 50000000u + +/** + * Default minimum number of scheduling ticks before jobs are soft-stopped. + * + * This defines the time-slice for a job (which may be different from that of + * a context) + */ +/* Between 0.1 and 0.15s before soft-stop */ +#define DEFAULT_JS_SOFT_STOP_TICKS 2 + +/** + * Default minimum number of scheduling ticks before CL jobs are soft-stopped. + */ +/* Between 0.05 and 0.1s before soft-stop */ +#define DEFAULT_JS_SOFT_STOP_TICKS_CL 1 + +/** + * Default minimum number of scheduling ticks before jobs are hard-stopped + */ +/* 1.2s before hard-stop, for a certain GLES2 test at 128x128 (bound by + * combined vertex+tiler job) + */ +#define DEFAULT_JS_HARD_STOP_TICKS_SS_HW_ISSUE_8408 24 +/* Between 0.2 and 0.25s before hard-stop */ +#define DEFAULT_JS_HARD_STOP_TICKS_SS 4 + +/** + * Default minimum number of scheduling ticks before CL jobs are hard-stopped. + */ +/* Between 0.1 and 0.15s before hard-stop */ +#define DEFAULT_JS_HARD_STOP_TICKS_CL 2 + +/** + * Default minimum number of scheduling ticks before jobs are hard-stopped + * during dumping + */ +/* 60s @ 50ms tick */ +#define DEFAULT_JS_HARD_STOP_TICKS_NSS 1200 + +/** + * Default minimum number of scheduling ticks before the GPU is reset + * to clear a "stuck" job + */ +/* 1.8s before resetting GPU, for a certain GLES2 test at 128x128 (bound by + * combined vertex+tiler job) + */ +#define DEFAULT_JS_RESET_TICKS_SS_HW_ISSUE_8408 36 +/* 0.3-0.35s before GPU is reset */ +#define DEFAULT_JS_RESET_TICKS_SS 6 + +/** + * Default minimum number of scheduling ticks before the GPU is reset + * to clear a "stuck" CL job. + */ +/* 0.2-0.25s before GPU is reset */ +#define DEFAULT_JS_RESET_TICKS_CL 4 + +/** + * Default minimum number of scheduling ticks before the GPU is reset + * to clear a "stuck" job during dumping. + */ +/* 60.1s @ 100ms tick */ +#define DEFAULT_JS_RESET_TICKS_NSS 1202 + +/** + * Number of milliseconds given for other jobs on the GPU to be + * soft-stopped when the GPU needs to be reset. + */ +#define DEFAULT_JS_RESET_TIMEOUT_MS 3000 + +/** + * Default timeslice that a context is scheduled in for, in nanoseconds. + * + * When a context has used up this amount of time across its jobs, it is + * scheduled out to let another run. + * + * @note the resolution is nanoseconds (ns) here, because that's the format + * often used by the OS. + */ +/* 0.05s - at 20fps a ctx does at least 1 frame before being scheduled out. + * At 40fps, 2 frames, etc + */ +#define DEFAULT_JS_CTX_TIMESLICE_NS 50000000 + +/** + * Default Job Scheduler initial runtime of a context for the CFS Policy, + * in time-slices. + * + * This value is relative to that of the least-run context, and defines + * where in the CFS queue a new context is added. A value of 1 means 'after + * the least-run context has used its timeslice'. Therefore, when all + * contexts consistently use the same amount of time, a value of 1 models a + * FIFO. A value of 0 would model a LIFO. + * + * The value is represented in "numbers of time slices". Multiply this + * value by that defined in @ref DEFAULT_JS_CTX_TIMESLICE_NS to get + * the time value for this in nanoseconds. + */ +#define DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES 1 + +/** + * Default Job Scheduler minimum runtime value of a context for CFS, in + * time_slices relative to that of the least-run context. + * + * This is a measure of how much preferrential treatment is given to a + * context that is not run very often. + * + * Specficially, this value defines how many timeslices such a context is + * (initially) allowed to use at once. Such contexts (e.g. 'interactive' + * processes) will appear near the front of the CFS queue, and can initially + * use more time than contexts that run continuously (e.g. 'batch' + * processes). + * + * This limit \b prevents a "stored-up timeslices" DoS attack, where a ctx + * not run for a long time attacks the system by using a very large initial + * number of timeslices when it finally does run. + * + * @note A value of zero allows not-run-often contexts to get scheduled in + * quickly, but to only use a single timeslice when they get scheduled in. + */ +#define DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES 2 + +/** +* Boolean indicating whether the driver is configured to be secure at +* a potential loss of performance. +* +* This currently affects only r0p0-15dev0 HW and earlier. +* +* On r0p0-15dev0 HW and earlier, there are tradeoffs between security and +* performance: +* +* - When this is set to MALI_TRUE, the driver remains fully secure, +* but potentially loses performance compared with setting this to +* MALI_FALSE. +* - When set to MALI_FALSE, the driver is open to certain security +* attacks. +* +* From r0p0-00rel0 and onwards, there is no security loss by setting +* this to MALI_FALSE, and no performance loss by setting it to +* MALI_TRUE. +*/ +#define DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE MALI_FALSE + +enum { + /** + * Use unrestricted Address ID width on the AXI bus. + */ + KBASE_AID_32 = 0x0, + + /** + * Restrict GPU to a half of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_16 = 0x3, + + /** + * Restrict GPU to a quarter of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_8 = 0x2, + + /** + * Restrict GPU to an eighth of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_4 = 0x1 +}; + +/** + * Default setting for read Address ID limiting on AXI bus. + * + * Attached value: u32 register value + * KBASE_AID_32 - use the full 32 IDs (5 ID bits) + * KBASE_AID_16 - use 16 IDs (4 ID bits) + * KBASE_AID_8 - use 8 IDs (3 ID bits) + * KBASE_AID_4 - use 4 IDs (2 ID bits) + * Default value: KBASE_AID_32 (no limit). Note hardware implementation + * may limit to a lower value. + */ +#define DEFAULT_ARID_LIMIT KBASE_AID_32 + +/** + * Default setting for write Address ID limiting on AXI. + * + * Attached value: u32 register value + * KBASE_AID_32 - use the full 32 IDs (5 ID bits) + * KBASE_AID_16 - use 16 IDs (4 ID bits) + * KBASE_AID_8 - use 8 IDs (3 ID bits) + * KBASE_AID_4 - use 4 IDs (2 ID bits) + * Default value: KBASE_AID_32 (no limit). Note hardware implementation + * may limit to a lower value. + */ +#define DEFAULT_AWID_LIMIT KBASE_AID_32 + +/** + * Default setting for using alternative hardware counters. + */ +#define DEFAULT_ALTERNATIVE_HWC MALI_FALSE + +/*** End Scheduling defaults ***/ + +/*** Begin Power Manager defaults */ + +/* Milliseconds */ +#define DEFAULT_PM_DVFS_FREQ 25 + +/** + * Default poweroff tick granuality, in nanoseconds + */ +/* 400us */ +#define DEFAULT_PM_GPU_POWEROFF_TICK_NS 400000 + +/** + * Default number of poweroff ticks before shader cores are powered off + */ +/* 400-800us */ +#define DEFAULT_PM_POWEROFF_TICK_SHADER 2 + +/** + * Default number of poweroff ticks before GPU is powered off + */ +#define DEFAULT_PM_POWEROFF_TICK_GPU 2 /* 400-800us */ + +/*** End Power Manager defaults ***/ + + +/** + * Default UMP device mapping. A UMP_DEVICE__SHIFT value which + * defines which UMP device this GPU should be mapped to. + */ +#define DEFAULT_UMP_GPU_DEVICE_SHIFT UMP_DEVICE_Z_SHIFT + +/** + * Default value for KBASE_CONFIG_ATTR_CPU_SPEED_FUNC. + * Points to @ref kbase_cpuprops_get_default_clock_speed. + */ +#define DEFAULT_CPU_SPEED_FUNC \ + ((uintptr_t)kbase_cpuprops_get_default_clock_speed) + +#endif /* _KBASE_CONFIG_DEFAULTS_H_ */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_context.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_context.c new file mode 100644 index 0000000000000000000000000000000000000000..1d42445672b8abd2f2d4d7dc657610c138e4ae3f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_context.c @@ -0,0 +1,280 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_context.c + * Base kernel context APIs + */ + +#include +#include + +#define MEMPOOL_PAGES 16384 + + +/** + * @brief Create a kernel base context. + * + * Allocate and init a kernel base context. + */ +struct kbase_context * +kbase_create_context(struct kbase_device *kbdev, bool is_compat) +{ + struct kbase_context *kctx; + mali_error mali_err; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* zero-inited as lot of code assume it's zero'ed out on create */ + kctx = vzalloc(sizeof(*kctx)); + + if (!kctx) + goto out; + + /* creating a context is considered a disjoint event */ + kbase_disjoint_event(kbdev); + + kctx->kbdev = kbdev; + kctx->as_nr = KBASEP_AS_NR_INVALID; + kctx->is_compat = is_compat; +#ifdef CONFIG_MALI_TRACE_TIMELINE + kctx->timeline.owner_tgid = task_tgid_nr(current); +#endif + atomic_set(&kctx->setup_complete, 0); + atomic_set(&kctx->setup_in_progress, 0); + kctx->keep_gpu_powered = MALI_FALSE; + spin_lock_init(&kctx->mm_update_lock); + kctx->process_mm = NULL; + atomic_set(&kctx->nonmapped_pages, 0); + + if (MALI_ERROR_NONE != kbase_mem_allocator_init(&kctx->osalloc, + MEMPOOL_PAGES, + kctx->kbdev)) + goto free_kctx; + + kctx->pgd_allocator = &kctx->osalloc; + atomic_set(&kctx->used_pages, 0); + + if (kbase_jd_init(kctx)) + goto free_allocator; + + mali_err = kbasep_js_kctx_init(kctx); + if (MALI_ERROR_NONE != mali_err) + goto free_jd; /* safe to call kbasep_js_kctx_term in this case */ + + mali_err = kbase_event_init(kctx); + if (MALI_ERROR_NONE != mali_err) + goto free_jd; + + mutex_init(&kctx->reg_lock); + + INIT_LIST_HEAD(&kctx->waiting_soft_jobs); +#ifdef CONFIG_KDS + INIT_LIST_HEAD(&kctx->waiting_kds_resource); +#endif + + mali_err = kbase_mmu_init(kctx); + if (MALI_ERROR_NONE != mali_err) + goto free_event; + + kctx->pgd = kbase_mmu_alloc_pgd(kctx); + if (!kctx->pgd) + goto free_mmu; + + if (MALI_ERROR_NONE != kbase_mem_allocator_alloc(&kctx->osalloc, 1, &kctx->aliasing_sink_page)) + goto no_sink_page; + + kctx->tgid = current->tgid; + kctx->pid = current->pid; + init_waitqueue_head(&kctx->event_queue); + + kctx->cookies = KBASE_COOKIE_MASK; + + /* Make sure page 0 is not used... */ + if (kbase_region_tracker_init(kctx)) + goto no_region_tracker; +#ifdef CONFIG_GPU_TRACEPOINTS + atomic_set(&kctx->jctx.work_id, 0); +#endif +#ifdef CONFIG_MALI_TRACE_TIMELINE + atomic_set(&kctx->timeline.jd_atoms_in_flight, 0); +#endif + + kctx->id = atomic_add_return(1, &(kbdev->ctx_num)) - 1; + + mali_err = kbasep_mem_profile_debugfs_add(kctx); + if (MALI_ERROR_NONE != mali_err) + goto no_region_tracker; + + if (kbasep_jd_debugfs_ctx_add(kctx)) + goto free_mem_profile; + + return kctx; + +free_mem_profile: + kbasep_mem_profile_debugfs_remove(kctx); +no_region_tracker: +no_sink_page: + kbase_mem_allocator_free(&kctx->osalloc, 1, &kctx->aliasing_sink_page, 0); + kbase_mmu_free_pgd(kctx); +free_mmu: + kbase_mmu_term(kctx); +free_event: + kbase_event_cleanup(kctx); +free_jd: + /* Safe to call this one even when didn't initialize (assuming kctx was sufficiently zeroed) */ + kbasep_js_kctx_term(kctx); + kbase_jd_exit(kctx); +free_allocator: + kbase_mem_allocator_term(&kctx->osalloc); +free_kctx: + vfree(kctx); +out: + return NULL; + +} +KBASE_EXPORT_SYMBOL(kbase_create_context) + +static void kbase_reg_pending_dtor(struct kbase_va_region *reg) +{ + dev_dbg(reg->kctx->kbdev->dev, "Freeing pending unmapped region\n"); + kbase_mem_phy_alloc_put(reg->alloc); + kfree(reg); +} + +/** + * @brief Destroy a kernel base context. + * + * Destroy a kernel base context. Calls kbase_destroy_os_context() to + * free OS specific structures. Will release all outstanding regions. + */ +void kbase_destroy_context(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + int pages; + unsigned long pending_regions_to_clean; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + KBASE_TRACE_ADD(kbdev, CORE_CTX_DESTROY, kctx, NULL, 0u, 0u); + + kbasep_jd_debugfs_ctx_remove(kctx); + + kbasep_mem_profile_debugfs_remove(kctx); + + /* Ensure the core is powered up for the destroy process */ + /* A suspend won't happen here, because we're in a syscall from a userspace + * thread. */ + kbase_pm_context_active(kbdev); + + if (kbdev->hwcnt.kctx == kctx) { + /* disable the use of the hw counters if the app didn't use the API correctly or crashed */ + KBASE_TRACE_ADD(kbdev, CORE_CTX_HWINSTR_TERM, kctx, NULL, 0u, 0u); + dev_warn(kbdev->dev, "The privileged process asking for instrumentation forgot to disable it " "before exiting. Will end instrumentation for them"); + kbase_instr_hwcnt_disable(kctx); + } + + kbase_jd_zap_context(kctx); + kbase_event_cleanup(kctx); + + kbase_gpu_vm_lock(kctx); + + /* MMU is disabled as part of scheduling out the context */ + kbase_mmu_free_pgd(kctx); + + /* drop the aliasing sink page now that it can't be mapped anymore */ + kbase_mem_allocator_free(&kctx->osalloc, 1, &kctx->aliasing_sink_page, 0); + + /* free pending region setups */ + pending_regions_to_clean = (~kctx->cookies) & KBASE_COOKIE_MASK; + while (pending_regions_to_clean) { + unsigned int cookie = __ffs(pending_regions_to_clean); + BUG_ON(!kctx->pending_regions[cookie]); + + kbase_reg_pending_dtor(kctx->pending_regions[cookie]); + + kctx->pending_regions[cookie] = NULL; + pending_regions_to_clean &= ~(1UL << cookie); + } + + kbase_region_tracker_term(kctx); + kbase_gpu_vm_unlock(kctx); + + /* Safe to call this one even when didn't initialize (assuming kctx was sufficiently zeroed) */ + kbasep_js_kctx_term(kctx); + + kbase_jd_exit(kctx); + + kbase_pm_context_idle(kbdev); + + kbase_mmu_term(kctx); + + pages = atomic_read(&kctx->used_pages); + if (pages != 0) + dev_warn(kbdev->dev, "%s: %d pages in use!\n", __func__, pages); + + if (kctx->keep_gpu_powered) { + atomic_dec(&kbdev->keep_gpu_powered_count); + kbase_pm_context_idle(kbdev); + } + + kbase_mem_allocator_term(&kctx->osalloc); + WARN_ON(atomic_read(&kctx->nonmapped_pages) != 0); + + vfree(kctx); +} +KBASE_EXPORT_SYMBOL(kbase_destroy_context) + +/** + * Set creation flags on a context + */ +mali_error kbase_context_set_create_flags(struct kbase_context *kctx, u32 flags) +{ + mali_error err = MALI_ERROR_NONE; + struct kbasep_js_kctx_info *js_kctx_info; + KBASE_DEBUG_ASSERT(NULL != kctx); + + js_kctx_info = &kctx->jctx.sched_info; + + /* Validate flags */ + if (flags != (flags & BASE_CONTEXT_CREATE_KERNEL_FLAGS)) { + err = MALI_ERROR_FUNCTION_FAILED; + goto out; + } + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + + /* Translate the flags */ + if ((flags & BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) == 0) + js_kctx_info->ctx.flags &= ~((u32) KBASE_CTX_FLAG_SUBMIT_DISABLED); + + if ((flags & BASE_CONTEXT_HINT_ONLY_COMPUTE) != 0) + js_kctx_info->ctx.flags |= (u32) KBASE_CTX_FLAG_HINT_ONLY_COMPUTE; + + /* Latch the initial attributes into the Job Scheduler */ + kbasep_js_ctx_attr_set_initial_attrs(kctx->kbdev, kctx); + + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + out: + return err; +} +KBASE_EXPORT_SYMBOL(kbase_context_set_create_flags) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_core_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..964902bde02bccf925ef35aac3dff15330716878 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_core_linux.c @@ -0,0 +1,3822 @@ + +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/** + * @file mali_kbase_core_linux.c + * Base kernel driver init. + */ + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MALI_DEVFREQ +#include "mali_kbase_devfreq.h" +#endif /* CONFIG_MALI_DEVFREQ */ +#include +#ifdef CONFIG_MALI_NO_MALI +#include "mali_kbase_model_linux.h" +#endif /* CONFIG_MALI_NO_MALI */ +#include "mali_kbase_mem_profile_debugfs_buf_size.h" + +#ifdef CONFIG_KDS +#include +#include +#include +#endif /* CONFIG_KDS */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* is_compat_task */ +#include +#include +#include +#ifdef CONFIG_SYNC +#include +#endif /* CONFIG_SYNC */ +#ifdef CONFIG_PM_DEVFREQ +#include +#endif /* CONFIG_PM_DEVFREQ */ +#include + +/* + * This file is included since when we support device tree we don't + * use the platform fake code for registering the kbase config attributes. + */ +#ifdef CONFIG_OF +#include +#include +#include +#endif + +#ifdef CONFIG_MACH_MANTA +#include +#endif + +/* MTK GPU DVFS */ +#include +#include "mt_gpufreq.h" + +/* GPU IRQ Tags */ +#define JOB_IRQ_TAG 0 +#define MMU_IRQ_TAG 1 +#define GPU_IRQ_TAG 2 + +#ifdef CONFIG_OF +void __iomem *clk_mfgcfg_base_addr; +#endif + +struct kbase_irq_table { + u32 tag; + irq_handler_t handler; +}; +#if MALI_UNIT_TEST +static struct kbase_exported_test_data shared_kernel_test_data; +EXPORT_SYMBOL(shared_kernel_test_data); +#endif /* MALI_UNIT_TEST */ + +#define KBASE_DRV_NAME "mali" + +static const char kbase_drv_name[] = KBASE_DRV_NAME; + +static int kbase_dev_nr; + +//#define NO_DVFS_FOR_BRINGUP + +/* MTK GPU DVFS freq */ + +// TBEX: +static struct kbase_device *gpsMaliData = NULL; + +int g_current_freq_id = 3; +int g_deferred_down_shift = 0; + +#define MTK_GPU_BOOST_DURATION 2 +int g_gpu_boost_duartion = 0; +int g_gpu_boost_id = 0; /* MTK for touch boost (only for a period of time) */ +int g_custom_gpu_boost_id = 0; /* MTK for mtk_custom_boost_gpu_freq (always set as lower bound of frequency). The lower bound function is used for performance service currently. */ +int g_ged_gpu_boost_id = 0; /* MTK for mtk_set_boost_gpu_freq (always set as lower bound of frequency). The lower bound function is used for GED boost currently. */ + +/* + Add by mediatek, Hook the memory query function pointer to (*mtk_get_gpu_memory_usage_fp) in order to + provide the gpu total memory usage to mlogger module +*/ +extern unsigned int (*mtk_get_gpu_memory_usage_fp)(void); + +static DEFINE_SEMAPHORE(kbase_dev_list_lock); +static LIST_HEAD(kbase_dev_list); + +KBASE_EXPORT_TEST_API(kbase_dev_list_lock) +KBASE_EXPORT_TEST_API(kbase_dev_list) +#define KERNEL_SIDE_DDK_VERSION_STRING "K:" MALI_RELEASE_NAME "(GPL)" +static INLINE void __compile_time_asserts(void) +{ + CSTD_COMPILE_TIME_ASSERT(sizeof(KERNEL_SIDE_DDK_VERSION_STRING) <= KBASE_GET_VERSION_BUFFER_SIZE); +} + +#ifdef CONFIG_KDS + +struct kbasep_kds_resource_set_file_data { + struct kds_resource_set *lock; +}; + +static int kds_resource_release(struct inode *inode, struct file *file); + +static const struct file_operations kds_resource_fops = { + .release = kds_resource_release +}; + +struct kbase_kds_resource_list_data { + struct kds_resource **kds_resources; + unsigned long *kds_access_bitmap; + int num_elems; +}; + +static int kds_resource_release(struct inode *inode, struct file *file) +{ + struct kbasep_kds_resource_set_file_data *data; + + data = (struct kbasep_kds_resource_set_file_data *)file->private_data; + if (NULL != data) { + if (NULL != data->lock) + kds_resource_set_release(&data->lock); + + kfree(data); + } + return 0; +} + +static mali_error kbasep_kds_allocate_resource_list_data(struct kbase_context *kctx, struct base_external_resource *ext_res, int num_elems, struct kbase_kds_resource_list_data *resources_list) +{ + struct base_external_resource *res = ext_res; + int res_id; + + /* assume we have to wait for all */ + + KBASE_DEBUG_ASSERT(0 != num_elems); + resources_list->kds_resources = kmalloc_array(num_elems, + sizeof(struct kds_resource *), GFP_KERNEL); + + if (NULL == resources_list->kds_resources) + return MALI_ERROR_OUT_OF_MEMORY; + + KBASE_DEBUG_ASSERT(0 != num_elems); + resources_list->kds_access_bitmap = kzalloc( + sizeof(unsigned long) * + ((num_elems + BITS_PER_LONG - 1) / BITS_PER_LONG), + GFP_KERNEL); + + if (NULL == resources_list->kds_access_bitmap) { + kfree(resources_list->kds_access_bitmap); + return MALI_ERROR_OUT_OF_MEMORY; + } + + kbase_gpu_vm_lock(kctx); + for (res_id = 0; res_id < num_elems; res_id++, res++) { + int exclusive; + struct kbase_va_region *reg; + struct kds_resource *kds_res = NULL; + + exclusive = res->ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE; + reg = kbase_region_tracker_find_region_enclosing_address(kctx, res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE); + + /* did we find a matching region object? */ + if (NULL == reg || (reg->flags & KBASE_REG_FREE)) + break; + + /* no need to check reg->alloc as only regions with an alloc has + * a size, and kbase_region_tracker_find_region_enclosing_address + * only returns regions with size > 0 */ + switch (reg->alloc->type) { +#if defined(CONFIG_UMP) && defined(CONFIG_KDS) + case KBASE_MEM_TYPE_IMPORTED_UMP: + kds_res = ump_dd_kds_resource_get(reg->alloc->imported.ump_handle); + break; +#endif /* defined(CONFIG_UMP) && defined(CONFIG_KDS) */ + default: + break; + } + + /* no kds resource for the region ? */ + if (!kds_res) + break; + + resources_list->kds_resources[res_id] = kds_res; + + if (exclusive) + set_bit(res_id, resources_list->kds_access_bitmap); + } + kbase_gpu_vm_unlock(kctx); + + /* did the loop run to completion? */ + if (res_id == num_elems) + return MALI_ERROR_NONE; + + /* Clean up as the resource list is not valid. */ + kfree(resources_list->kds_resources); + kfree(resources_list->kds_access_bitmap); + + return MALI_ERROR_FUNCTION_FAILED; +} + +static mali_bool kbasep_validate_kbase_pointer(union kbase_pointer *p) +{ +#ifdef CONFIG_COMPAT + if (is_compat_task()) { + if (p->compat_value == 0) + return MALI_FALSE; + } else { +#endif /* CONFIG_COMPAT */ + if (NULL == p->value) + return MALI_FALSE; +#ifdef CONFIG_COMPAT + } +#endif /* CONFIG_COMPAT */ + return MALI_TRUE; +} + +static mali_error kbase_external_buffer_lock(struct kbase_context *kctx, struct kbase_uk_ext_buff_kds_data *args, u32 args_size) +{ + struct base_external_resource *ext_res_copy; + size_t ext_resource_size; + mali_error return_error = MALI_ERROR_FUNCTION_FAILED; + int fd; + + if (args_size != sizeof(struct kbase_uk_ext_buff_kds_data)) + return MALI_ERROR_FUNCTION_FAILED; + + /* Check user space has provided valid data */ + if (!kbasep_validate_kbase_pointer(&args->external_resource) || !kbasep_validate_kbase_pointer(&args->file_descriptor) || (0 == args->num_res) || (args->num_res > KBASE_MAXIMUM_EXT_RESOURCES)) + return MALI_ERROR_FUNCTION_FAILED; + + ext_resource_size = sizeof(struct base_external_resource) * args->num_res; + + KBASE_DEBUG_ASSERT(0 != ext_resource_size); + ext_res_copy = kmalloc(ext_resource_size, GFP_KERNEL); + + if (NULL != ext_res_copy) { + struct base_external_resource __user *ext_res_user; + int __user *file_descriptor_user; +#ifdef CONFIG_COMPAT + if (is_compat_task()) { + ext_res_user = compat_ptr(args->external_resource.compat_value); + file_descriptor_user = compat_ptr(args->file_descriptor.compat_value); + } else { +#endif /* CONFIG_COMPAT */ + ext_res_user = args->external_resource.value; + file_descriptor_user = args->file_descriptor.value; +#ifdef CONFIG_COMPAT + } +#endif /* CONFIG_COMPAT */ + + /* Copy the external resources to lock from user space */ + if (0 == copy_from_user(ext_res_copy, ext_res_user, ext_resource_size)) { + struct kbasep_kds_resource_set_file_data *fdata; + + /* Allocate data to be stored in the file */ + fdata = kmalloc(sizeof(*fdata), GFP_KERNEL); + + if (NULL != fdata) { + struct kbase_kds_resource_list_data resource_list_data; + /* Parse given elements and create resource and access lists */ + return_error = kbasep_kds_allocate_resource_list_data(kctx, ext_res_copy, args->num_res, &resource_list_data); + if (MALI_ERROR_NONE == return_error) { + long err; + + fdata->lock = NULL; + + fd = anon_inode_getfd("kds_ext", &kds_resource_fops, fdata, 0); + + err = copy_to_user(file_descriptor_user, &fd, sizeof(fd)); + + /* If the file descriptor was valid and we successfully copied it to user space, then we + * can try and lock the requested kds resources. + */ + if ((fd >= 0) && (0 == err)) { + struct kds_resource_set *lock; + + lock = kds_waitall(args->num_res, resource_list_data.kds_access_bitmap, + resource_list_data.kds_resources, + KDS_WAIT_BLOCKING); + + if (IS_ERR_OR_NULL(lock)) { + return_error = MALI_ERROR_FUNCTION_FAILED; + } else { + return_error = MALI_ERROR_NONE; + fdata->lock = lock; + } + } else { + return_error = MALI_ERROR_FUNCTION_FAILED; + } + + kfree(resource_list_data.kds_resources); + kfree(resource_list_data.kds_access_bitmap); + } + + if (MALI_ERROR_NONE != return_error) { + /* If the file was opened successfully then close it which will clean up + * the file data, otherwise we clean up the file data ourself. */ + if (fd >= 0) + sys_close(fd); + else + kfree(fdata); + } + } else { + return_error = MALI_ERROR_OUT_OF_MEMORY; + } + } + kfree(ext_res_copy); + } + return return_error; +} +#endif /* CONFIG_KDS */ + +struct kbase_device *MaliGetMaliData(void) +{ + return gpsMaliData; +} + +static void _mtk_set_gpu_boost_duration(void) +{ + g_gpu_boost_duartion = MTK_GPU_BOOST_DURATION; +} + +static void _mtk_decrease_gpu_boost_duration(void) +{ + g_gpu_boost_duartion--; +} + +static int _mtk_get_gpu_boost_duration(void) +{ + return g_gpu_boost_duartion; +} + +void mtk_gpu_input_boost_CB(unsigned int ui32BoostFreqID) +{ + int iCurrentFreqID; + //pr_debug("[MALI] mtk_gpu_input_boost_CB! boost to index=%d\n", ui32BoostFreqID); + + // check if input boost enabled + if(mtk_get_input_boost_enabled() == 0) + return; + + _mtk_set_gpu_boost_duration(); + + // set gpu boost id + g_gpu_boost_id = ui32BoostFreqID; + + iCurrentFreqID = mt_gpufreq_get_cur_freq_index(); + pr_debug("[MALI] current gpu freq id=%d, touch boost to index=%d\n", iCurrentFreqID, ui32BoostFreqID); + + if(ui32BoostFreqID < iCurrentFreqID) + { + pr_debug("[MALI] boost CB set to FREQ id=%d\n", ui32BoostFreqID); + mtk_set_touch_boost_flag(ui32BoostFreqID); + } + +} + +void mtk_gpu_power_limit_CB(unsigned int ui32LimitFreqID) +{ + int iCurrentFreqID; + + pr_debug("[MALI] boost CB set to freq id=%d\n", ui32LimitFreqID); + + iCurrentFreqID = mt_gpufreq_get_cur_freq_index(); + + if(ui32LimitFreqID > iCurrentFreqID) + mtk_set_mt_gpufreq_target(ui32LimitFreqID); +} + +void mtk_kbase_boost_gpu_freq(void) +{ + mtk_gpu_input_boost_CB(0); + + return; +} + + +/* MTK custom boost. 0 is the lowest frequency index. The function is used for performance service currently.*/ +void mtk_kbase_custom_boost_gpu_freq(unsigned int ui32FreqLevel) +{ + unsigned int uiTableNum; + uiTableNum = mt_gpufreq_get_dvfs_table_num(); + + g_custom_gpu_boost_id = uiTableNum - ui32FreqLevel - 1; + + pr_debug("[MALI] mtk_kbase_custom_boost_gpu_freq() ui32FreqLevel=%d, g_custom_gpu_boost_id=%d", ui32FreqLevel, g_custom_gpu_boost_id); + + if(g_custom_gpu_boost_id < mt_gpufreq_get_cur_freq_index()) + { + pr_debug("[MALI] mtk_kbase_custom_boost_gpu_freq set gpu freq to index=%d, cuurent index=%d", g_custom_gpu_boost_id, mt_gpufreq_get_cur_freq_index()); + mtk_set_mt_gpufreq_target(g_custom_gpu_boost_id); + } + + return; +} + +/* MTK set boost. 0 is the lowest frequency index. The function is used for GED boost currently.*/ +void mtk_kbase_ged_bottom_gpu_freq(unsigned int ui32FreqLevel) +{ + unsigned int uiTableNum; + uiTableNum = mt_gpufreq_get_dvfs_table_num(); + + if (ui32FreqLevel >= uiTableNum) + { + ui32FreqLevel = uiTableNum - 1; + } + + g_ged_gpu_boost_id = uiTableNum - ui32FreqLevel - 1; + + pr_debug("[MALI] mtk_kbase_set_bottom_gpu_freq_fp() ui32FreqLevel=%d, g_custom_gpu_boost_id=%d (GED boost)", ui32FreqLevel, g_ged_gpu_boost_id); + + if(g_ged_gpu_boost_id < mt_gpufreq_get_cur_freq_index()) + { + pr_debug("[MALI] mtk_kbase_set_bottom_gpu_freq_fp set gpu freq to index=%d, cuurent index=%d (GED boost)", g_ged_gpu_boost_id, mt_gpufreq_get_cur_freq_index()); + mtk_set_mt_gpufreq_target(g_ged_gpu_boost_id); + } + + return; +} + + +unsigned int mtk_kbase_custom_get_gpu_freq_level_count(void) +{ + return mt_gpufreq_get_dvfs_table_num(); +} + +int _mtk_dvfs_index_clipping(int iTargetVirtualFreqID, int start, int end) +{ + if(iTargetVirtualFreqID < start) + return start; + else if(iTargetVirtualFreqID > end) + return end; + else + return iTargetVirtualFreqID; +} + +void mtk_gpu_dvfs_commit(unsigned long ui32NewFreqID, GED_DVFS_COMMIT_TYPE eCommitType, int* pbCommited) +{ + int ret = -1; + ret = mtk_set_mt_gpufreq_target(ui32NewFreqID); + if(NULL!=pbCommited){ + if(ret == 0){ + *pbCommited = true; + }else{ + *pbCommited = false; + } + } +} + +int mtk_gpu_dvfs(void) +{ + + int iCurrentFreqID, iTargetFreqID; + int iCurrentVirtualFreqID = 0, iTargetVirtualFreqID; + int iCurrentGPUPlatformID; + int iCurrentGPUBoostDurationCount; + int i; + enum kbase_pm_dvfs_action action; + int higher_boost_id; + + action = mtk_get_dvfs_action(); + + + if(action == KBASE_PM_DVFS_NONSENSE) + { + /* if action < 0, action is not updated yet. */ + return MALI_TRUE; + } + + mtk_clear_dvfs_action(); + + // get current frequency id + iCurrentFreqID = mt_gpufreq_get_cur_freq_index(); + + // get current platform type + iCurrentGPUPlatformID = mtk_get_current_gpu_platform_id(); + + //calculate current virtual frequency ID + for(i=0 ; i 0) + { + _mtk_decrease_gpu_boost_duration(); + if(iTargetFreqID >= g_gpu_boost_id) + { + return MALI_TRUE; + } + } + + + // [MTK] mtk_custom_gpu_boost. do nothing if g_custom_gpu_boost_id is higher + + /* calculate higher boost frequency (e.g. lower index id) */ + if(g_custom_gpu_boost_id < g_ged_gpu_boost_id) + higher_boost_id = g_custom_gpu_boost_id; + else + higher_boost_id = g_ged_gpu_boost_id; + + if(iTargetFreqID > higher_boost_id) + { + mtk_set_mt_gpufreq_target(higher_boost_id); + return MALI_FALSE; + } + + if(iCurrentFreqID == iTargetFreqID) + { + //pr_debug("[MALI] (*)current freq == target freq (%d)\n", iCurrentFreqID); + return MALI_TRUE; + } + + if(mtk_set_mt_gpufreq_target(iTargetFreqID) == 0) + { + return MALI_TRUE; + } + else + { + return MALI_FALSE; + } + +} + + +static mali_error kbase_dispatch(struct kbase_context *kctx, void * const args, u32 args_size) +{ + struct kbase_device *kbdev; + union uk_header *ukh = args; + u32 id; + + KBASE_DEBUG_ASSERT(ukh != NULL); + + kbdev = kctx->kbdev; + id = ukh->id; + ukh->ret = MALI_ERROR_NONE; /* Be optimistic */ + + if (UKP_FUNC_ID_CHECK_VERSION == id) { + if (args_size == sizeof(struct uku_version_check_args)) { + struct uku_version_check_args *version_check = (struct uku_version_check_args *)args; + + switch (version_check->major) { +#ifdef BASE_LEGACY_UK6_SUPPORT + case 6: + /* We are backwards compatible with version 6, + * so pretend to be the old version */ + version_check->major = 6; + version_check->minor = 1; + break; +#endif /* BASE_LEGACY_UK6_SUPPORT */ +#ifdef BASE_LEGACY_UK7_SUPPORT + case 7: + /* We are backwards compatible with version 7, + * so pretend to be the old version */ + version_check->major = 7; + version_check->minor = 1; + break; +#endif /* BASE_LEGACY_UK7_SUPPORT */ + default: + /* We return our actual version regardless if it + * matches the version returned by userspace - + * userspace can bail if it can't handle this + * version */ + version_check->major = BASE_UK_VERSION_MAJOR; + version_check->minor = BASE_UK_VERSION_MINOR; + } + + ukh->ret = MALI_ERROR_NONE; + } else { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } + return MALI_ERROR_NONE; + } + + + if (!atomic_read(&kctx->setup_complete)) { + /* setup pending, try to signal that we'll do the setup */ + if (atomic_cmpxchg(&kctx->setup_in_progress, 0, 1)) { + /* setup was already in progress, err this call */ + return MALI_ERROR_FUNCTION_FAILED; + } + + /* we're the one doing setup */ + + /* is it the only call we accept? */ + if (id == KBASE_FUNC_SET_FLAGS) { + struct kbase_uk_set_flags *kbase_set_flags = (struct kbase_uk_set_flags *)args; + + if (sizeof(*kbase_set_flags) != args_size) { + /* not matching the expected call, stay stuck in setup mode */ + goto bad_size; + } + + if (MALI_ERROR_NONE != kbase_context_set_create_flags(kctx, kbase_set_flags->create_flags)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + /* bad flags, will stay stuck in setup mode */ + return MALI_ERROR_NONE; + } else { + /* we've done the setup, all OK */ + atomic_set(&kctx->setup_complete, 1); + return MALI_ERROR_NONE; + } + } else { + /* unexpected call, will stay stuck in setup mode */ + return MALI_ERROR_FUNCTION_FAILED; + } + } + + /* setup complete, perform normal operation */ + switch (id) { + case KBASE_FUNC_MEM_ALLOC: + { + struct kbase_uk_mem_alloc *mem = args; + struct kbase_va_region *reg; + + if (sizeof(*mem) != args_size) + goto bad_size; + + reg = kbase_mem_alloc(kctx, mem->va_pages, mem->commit_pages, mem->extent, &mem->flags, &mem->gpu_va, &mem->va_alignment); + if (!reg) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + case KBASE_FUNC_MEM_IMPORT: + { + struct kbase_uk_mem_import *mem_import = args; + int __user *phandle; + int handle; + + if (sizeof(*mem_import) != args_size) + goto bad_size; +#ifdef CONFIG_64BIT + if (is_compat_task()) + phandle = compat_ptr(mem_import->phandle.compat_value); + else +#endif + phandle = mem_import->phandle.value; + + switch (mem_import->type) { + case BASE_MEM_IMPORT_TYPE_UMP: + get_user(handle, phandle); + break; + case BASE_MEM_IMPORT_TYPE_UMM: + get_user(handle, phandle); + break; + default: + goto bad_type; + break; + } + + if (kbase_mem_import(kctx, mem_import->type, handle, &mem_import->gpu_va, &mem_import->va_pages, &mem_import->flags)) { +bad_type: + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } + break; + } + case KBASE_FUNC_MEM_ALIAS: { + struct kbase_uk_mem_alias *alias = args; + struct base_mem_aliasing_info __user *user_ai; + struct base_mem_aliasing_info *ai; + + if (sizeof(*alias) != args_size) + goto bad_size; + + if (alias->nents > 2048) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + +#ifdef CONFIG_64BIT + if (is_compat_task()) + user_ai = compat_ptr(alias->ai.compat_value); + else +#endif + user_ai = alias->ai.value; + + ai = vmalloc(sizeof(*ai) * alias->nents); + + if (!ai) { + ukh->ret = MALI_ERROR_OUT_OF_MEMORY; + break; + } + + if (copy_from_user(ai, user_ai, + sizeof(*ai) * alias->nents)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + goto copy_failed; + } + + alias->gpu_va = kbase_mem_alias(kctx, &alias->flags, + alias->stride, + alias->nents, ai, + &alias->va_pages); + if (!alias->gpu_va) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + goto no_alias; + } +no_alias: +copy_failed: + vfree(ai); + break; + } + case KBASE_FUNC_MEM_COMMIT: + { + struct kbase_uk_mem_commit *commit = args; + + if (sizeof(*commit) != args_size) + goto bad_size; + + if (commit->gpu_addr & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_COMMIT: commit->gpu_addr: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (kbase_mem_commit(kctx, commit->gpu_addr, + commit->pages, + (base_backing_threshold_status *)&commit->result_subcode)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + break; + } + + case KBASE_FUNC_MEM_QUERY: + { + struct kbase_uk_mem_query *query = args; + + if (sizeof(*query) != args_size) + goto bad_size; + + if (query->gpu_addr & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_QUERY: query->gpu_addr: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + if (query->query != KBASE_MEM_QUERY_COMMIT_SIZE && + query->query != KBASE_MEM_QUERY_VA_SIZE && + query->query != KBASE_MEM_QUERY_FLAGS) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_QUERY: query->query = %lld unknown", (unsigned long long)query->query); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + ukh->ret = kbase_mem_query(kctx, query->gpu_addr, query->query, &query->value); + break; + } + break; + + case KBASE_FUNC_MEM_FLAGS_CHANGE: + { + struct kbase_uk_mem_flags_change *fc = args; + + if (sizeof(*fc) != args_size) + goto bad_size; + + if ((fc->gpu_va & ~PAGE_MASK) && (fc->gpu_va >= PAGE_SIZE)) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_FLAGS_CHANGE: mem->gpu_va: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (kbase_mem_flags_change(kctx, fc->gpu_va, fc->flags, fc->mask)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + break; + } + case KBASE_FUNC_MEM_FREE: + { + struct kbase_uk_mem_free *mem = args; + + if (sizeof(*mem) != args_size) + goto bad_size; + + if ((mem->gpu_addr & ~PAGE_MASK) && (mem->gpu_addr >= PAGE_SIZE)) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_FREE: mem->gpu_addr: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (kbase_mem_free(kctx, mem->gpu_addr)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_JOB_SUBMIT: + { + struct kbase_uk_job_submit *job = args; + + if (sizeof(*job) != args_size) + goto bad_size; + +#ifdef BASE_LEGACY_UK6_SUPPORT + if (MALI_ERROR_NONE != kbase_jd_submit(kctx, job, 0)) +#else + if (MALI_ERROR_NONE != kbase_jd_submit(kctx, job)) +#endif /* BASE_LEGACY_UK6_SUPPORT */ + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + +#ifndef ENABLE_COMMON_DVFS + //dev_err(kbdev->dev, "5566 JOB SUBMIT BASED"); + if(mtk_get_dvfs_enabled()) + { + mtk_gpu_dvfs(); + } +#endif + + break; + } + +#ifdef BASE_LEGACY_UK6_SUPPORT + case KBASE_FUNC_JOB_SUBMIT_UK6: + { + struct kbase_uk_job_submit *job = args; + + if (sizeof(*job) != args_size) + goto bad_size; + + if (MALI_ERROR_NONE != kbase_jd_submit(kctx, job, 1)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } +#endif + + case KBASE_FUNC_SYNC: + { + struct kbase_uk_sync_now *sn = args; + + if (sizeof(*sn) != args_size) + goto bad_size; + + if (sn->sset.basep_sset.mem_handle & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_SYNC: sn->sset.basep_sset.mem_handle: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (MALI_ERROR_NONE != kbase_sync_now(kctx, &sn->sset)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_DISJOINT_QUERY: + { + struct kbase_uk_disjoint_query *dquery = args; + + if (sizeof(*dquery) != args_size) + goto bad_size; + + /* Get the disjointness counter value. */ + dquery->counter = kbase_disjoint_event_get(kctx->kbdev); + break; + } + + case KBASE_FUNC_POST_TERM: + { + kbase_event_close(kctx); + break; + } + + case KBASE_FUNC_HWCNT_SETUP: + { + struct kbase_uk_hwcnt_setup *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + if (MALI_ERROR_NONE != kbase_instr_hwcnt_setup(kctx, setup)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_HWCNT_DUMP: + { + /* args ignored */ + if (MALI_ERROR_NONE != kbase_instr_hwcnt_dump(kctx)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_HWCNT_CLEAR: + { + /* args ignored */ + if (MALI_ERROR_NONE != kbase_instr_hwcnt_clear(kctx)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + +#ifdef BASE_LEGACY_UK7_SUPPORT + case KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE: + { + struct kbase_uk_cpuprops *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + if (MALI_ERROR_NONE != kbase_cpuprops_uk_get_props(kctx, setup)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } +#endif /* BASE_LEGACY_UK7_SUPPORT */ + + case KBASE_FUNC_GPU_PROPS_REG_DUMP: + { + struct kbase_uk_gpuprops *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + if (MALI_ERROR_NONE != kbase_gpuprops_uk_get_props(kctx, setup)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + case KBASE_FUNC_FIND_CPU_OFFSET: + { + struct kbase_uk_find_cpu_offset *find = args; + + if (sizeof(*find) != args_size) + goto bad_size; + + if (find->gpu_addr & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_FIND_CPU_OFFSET: find->gpu_addr: passed parameter is invalid"); + goto out_bad; + } + + if (find->size > SIZE_MAX || find->cpu_addr > ULONG_MAX) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } else { + mali_error err; + + err = kbasep_find_enclosing_cpu_mapping_offset( + kctx, + find->gpu_addr, + (uintptr_t) find->cpu_addr, + (size_t) find->size, + &find->offset); + + if (err != MALI_ERROR_NONE) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } + break; + } + case KBASE_FUNC_GET_VERSION: + { + struct kbase_uk_get_ddk_version *get_version = (struct kbase_uk_get_ddk_version *)args; + + if (sizeof(*get_version) != args_size) + goto bad_size; + + /* version buffer size check is made in compile time assert */ + memcpy(get_version->version_buffer, KERNEL_SIDE_DDK_VERSION_STRING, sizeof(KERNEL_SIDE_DDK_VERSION_STRING)); + get_version->version_string_size = sizeof(KERNEL_SIDE_DDK_VERSION_STRING); + break; + } + + case KBASE_FUNC_STREAM_CREATE: + { +#ifdef CONFIG_SYNC + struct kbase_uk_stream_create *screate = (struct kbase_uk_stream_create *)args; + + if (sizeof(*screate) != args_size) + goto bad_size; + + if (strnlen(screate->name, sizeof(screate->name)) >= sizeof(screate->name)) { + /* not NULL terminated */ + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + ukh->ret = kbase_stream_create(screate->name, &screate->fd); +#else /* CONFIG_SYNC */ + ukh->ret = MALI_ERROR_FUNCTION_FAILED; +#endif /* CONFIG_SYNC */ + break; + } + case KBASE_FUNC_FENCE_VALIDATE: + { +#ifdef CONFIG_SYNC + struct kbase_uk_fence_validate *fence_validate = (struct kbase_uk_fence_validate *)args; + + if (sizeof(*fence_validate) != args_size) + goto bad_size; + + ukh->ret = kbase_fence_validate(fence_validate->fd); +#endif /* CONFIG_SYNC */ + break; + } + + case KBASE_FUNC_EXT_BUFFER_LOCK: + { +#ifdef CONFIG_KDS + ukh->ret = kbase_external_buffer_lock(kctx, (struct kbase_uk_ext_buff_kds_data *)args, args_size); +#endif /* CONFIG_KDS */ + break; + } + + case KBASE_FUNC_SET_TEST_DATA: + { +#if MALI_UNIT_TEST + struct kbase_uk_set_test_data *set_data = args; + + shared_kernel_test_data = set_data->test_data; + shared_kernel_test_data.kctx.value = (void __user *)kctx; + shared_kernel_test_data.mm.value = (void __user *)current->mm; + ukh->ret = MALI_ERROR_NONE; +#endif /* MALI_UNIT_TEST */ + break; + } + + case KBASE_FUNC_INJECT_ERROR: + { +#ifdef CONFIG_MALI_ERROR_INJECT + unsigned long flags; + struct kbase_error_params params = ((struct kbase_uk_error_params *)args)->params; + + /*mutex lock */ + spin_lock_irqsave(&kbdev->reg_op_lock, flags); + ukh->ret = job_atom_inject_error(¶ms); + spin_unlock_irqrestore(&kbdev->reg_op_lock, flags); + /*mutex unlock */ +#endif /* CONFIG_MALI_ERROR_INJECT */ + break; + } + + case KBASE_FUNC_MODEL_CONTROL: + { +#ifdef CONFIG_MALI_NO_MALI + unsigned long flags; + struct kbase_model_control_params params = + ((struct kbase_uk_model_control_params *)args)->params; + + /*mutex lock */ + spin_lock_irqsave(&kbdev->reg_op_lock, flags); + ukh->ret = midg_model_control(kbdev->model, ¶ms); + spin_unlock_irqrestore(&kbdev->reg_op_lock, flags); + /*mutex unlock */ +#endif /* CONFIG_MALI_NO_MALI */ + break; + } + + case KBASE_FUNC_KEEP_GPU_POWERED: + { + struct kbase_uk_keep_gpu_powered *kgp = + (struct kbase_uk_keep_gpu_powered *)args; + + /* A suspend won't happen here, because we're in a syscall from a + * userspace thread. + * + * Nevertheless, we'd get the wrong pm_context_active/idle counting + * here if a suspend did happen, so let's assert it won't: */ + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + + if (kgp->enabled && !kctx->keep_gpu_powered) { + kbase_pm_context_active(kbdev); + atomic_inc(&kbdev->keep_gpu_powered_count); + kctx->keep_gpu_powered = MALI_TRUE; + } else if (!kgp->enabled && kctx->keep_gpu_powered) { + atomic_dec(&kbdev->keep_gpu_powered_count); + kbase_pm_context_idle(kbdev); + kctx->keep_gpu_powered = MALI_FALSE; + } + + break; + } + + case KBASE_FUNC_GET_PROFILING_CONTROLS: + { + struct kbase_uk_profiling_controls *controls = + (struct kbase_uk_profiling_controls *)args; + u32 i; + + if (sizeof(*controls) != args_size) + goto bad_size; + + for (i = FBDUMP_CONTROL_MIN; i < FBDUMP_CONTROL_MAX; i++) + controls->profiling_controls[i] = kbase_get_profiling_control(kbdev, i); + + break; + } + + /* used only for testing purposes; these controls are to be set by gator through gator API */ + case KBASE_FUNC_SET_PROFILING_CONTROLS: + { + struct kbase_uk_profiling_controls *controls = + (struct kbase_uk_profiling_controls *)args; + u32 i; + + if (sizeof(*controls) != args_size) + goto bad_size; + + for (i = FBDUMP_CONTROL_MIN; i < FBDUMP_CONTROL_MAX; i++) + _mali_profiling_control(i, controls->profiling_controls[i]); + + break; + } + + case KBASE_FUNC_DEBUGFS_MEM_PROFILE_ADD: + { + struct kbase_uk_debugfs_mem_profile_add *add_data = + (struct kbase_uk_debugfs_mem_profile_add *)args; + char *buf; + char __user *user_buf; + + if (sizeof(*add_data) != args_size) + goto bad_size; + + if (add_data->len > KBASE_MEM_PROFILE_MAX_BUF_SIZE) { + dev_err(kbdev->dev, "buffer too big"); + goto out_bad; + } + +#ifdef CONFIG_64BIT + if (is_compat_task()) + user_buf = compat_ptr(add_data->buf.compat_value); + else +#endif + user_buf = add_data->buf.value; + + buf = kmalloc(add_data->len, GFP_KERNEL); + if (!buf) + goto out_bad; + + if (0 != copy_from_user(buf, user_buf, add_data->len)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + kfree(buf); + goto out_bad; + } + kbasep_mem_profile_debugfs_insert(kctx, buf, + add_data->len); + + break; + } + + default: + dev_err(kbdev->dev, "unknown ioctl %u", id); + goto out_bad; + } + + return MALI_ERROR_NONE; + + bad_size: + dev_err(kbdev->dev, "Wrong syscall size (%d) for %08x\n", args_size, id); + out_bad: + return MALI_ERROR_FUNCTION_FAILED; +} + +static struct kbase_device *to_kbase_device(struct device *dev) +{ + return dev_get_drvdata(dev); +} + +/* + * API to acquire device list semaphore and + * return pointer to the device list head + */ +const struct list_head *kbase_dev_list_get(void) +{ + down(&kbase_dev_list_lock); + return &kbase_dev_list; +} + +/* API to release the device list semaphore */ +void kbase_dev_list_put(const struct list_head *dev_list) +{ + up(&kbase_dev_list_lock); +} + +/* Find a particular kbase device (as specified by minor number), or find the "first" device if -1 is specified */ +struct kbase_device *kbase_find_device(int minor) +{ + struct kbase_device *kbdev = NULL; + struct list_head *entry; + + down(&kbase_dev_list_lock); + list_for_each(entry, &kbase_dev_list) { + struct kbase_device *tmp; + + tmp = list_entry(entry, struct kbase_device, entry); + if (tmp->mdev.minor == minor || minor == -1) { + kbdev = tmp; + get_device(kbdev->dev); + break; + } + } + up(&kbase_dev_list_lock); + + return kbdev; +} +EXPORT_SYMBOL(kbase_find_device); + +void kbase_release_device(struct kbase_device *kbdev) +{ + put_device(kbdev->dev); +} +EXPORT_SYMBOL(kbase_release_device); + +static int kbase_open(struct inode *inode, struct file *filp) +{ + struct kbase_device *kbdev = NULL; + struct kbase_context *kctx; + int ret = 0; + + kbdev = kbase_find_device(iminor(inode)); + + if (!kbdev) + return -ENODEV; + + kctx = kbase_create_context(kbdev, is_compat_task()); + if (!kctx) { + ret = -ENOMEM; + goto out; + } + + init_waitqueue_head(&kctx->event_queue); + filp->private_data = kctx; + + dev_dbg(kbdev->dev, "created base context\n"); + + { + struct kbasep_kctx_list_element *element; + + element = kzalloc(sizeof(*element), GFP_KERNEL); + if (element) { + mutex_lock(&kbdev->kctx_list_lock); + element->kctx = kctx; + list_add(&element->link, &kbdev->kctx_list); + mutex_unlock(&kbdev->kctx_list_lock); + } else { + /* we don't treat this as a fail - just warn about it */ + dev_warn(kbdev->dev, "couldn't add kctx to kctx_list\n"); + } + } + return 0; + + out: + kbase_release_device(kbdev); + return ret; +} + +static int kbase_release(struct inode *inode, struct file *filp) +{ + struct kbase_context *kctx = filp->private_data; + struct kbase_device *kbdev = kctx->kbdev; + struct kbasep_kctx_list_element *element, *tmp; + mali_bool found_element = MALI_FALSE; + + mutex_lock(&kbdev->kctx_list_lock); + list_for_each_entry_safe(element, tmp, &kbdev->kctx_list, link) { + if (element->kctx == kctx) { + list_del(&element->link); + kfree(element); + found_element = MALI_TRUE; + } + } + mutex_unlock(&kbdev->kctx_list_lock); + if (!found_element) + dev_warn(kbdev->dev, "kctx not in kctx_list\n"); + + filp->private_data = NULL; + kbase_destroy_context(kctx); + + dev_dbg(kbdev->dev, "deleted base context\n"); + kbase_release_device(kbdev); + return 0; +} + +#define CALL_MAX_SIZE 536 + +static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + ///u64 msg[(CALL_MAX_SIZE + 7) >> 3] = { 0xdeadbeefdeadbeefull }; /* alignment fixup */ + u64* msg = kmalloc(CALL_MAX_SIZE + 7, GFP_KERNEL); + u32 size = _IOC_SIZE(cmd); + struct kbase_context *kctx = filp->private_data; + + if (size > CALL_MAX_SIZE){ + kfree(msg); + return -ENOTTY; + } + + if (!msg) { + pr_alert("kmalloc fail, %d byte\n", CALL_MAX_SIZE + 7); + kfree(msg); + return -EFAULT; + } + *msg = 0xdeadbeefdeadbeefull; + + if (0 != copy_from_user(msg, (void __user *)arg, size)) { + dev_err(kctx->kbdev->dev, "failed to copy ioctl argument into kernel space\n"); + kfree(msg); + return -EFAULT; + } + + if (MALI_ERROR_NONE != kbase_dispatch(kctx, msg, size)){ + kfree(msg); + return -EFAULT; + } + if (0 != copy_to_user((void __user *)arg, msg, size)) { + dev_err(kctx->kbdev->dev, "failed to copy results of UK call back to user space\n"); + kfree(msg); + return -EFAULT; + } + + kfree(msg); + return 0; +} + +static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + struct kbase_context *kctx = filp->private_data; + struct base_jd_event_v2 uevent; + int out_count = 0; + + if (count < sizeof(uevent)) + return -ENOBUFS; + + do { + while (kbase_event_dequeue(kctx, &uevent)) { + if (out_count > 0) + goto out; + + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + + if (wait_event_interruptible(kctx->event_queue, kbase_event_pending(kctx))) + return -ERESTARTSYS; + } + if (uevent.event_code == BASE_JD_EVENT_DRV_TERMINATED) { + if (out_count == 0) + return -EPIPE; + goto out; + } + + if (copy_to_user(buf, &uevent, sizeof(uevent))) + return -EFAULT; + + buf += sizeof(uevent); + out_count++; + count -= sizeof(uevent); + } while (count >= sizeof(uevent)); + + out: + return out_count * sizeof(uevent); +} + +static unsigned int kbase_poll(struct file *filp, poll_table *wait) +{ + struct kbase_context *kctx = filp->private_data; + + poll_wait(filp, &kctx->event_queue, wait); + if (kbase_event_pending(kctx)) + return POLLIN | POLLRDNORM; + + return 0; +} + +void kbase_event_wakeup(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + + wake_up_interruptible(&kctx->event_queue); +} + +KBASE_EXPORT_TEST_API(kbase_event_wakeup) + +static int kbase_check_flags(int flags) +{ + /* Enforce that the driver keeps the O_CLOEXEC flag so that execve() always + * closes the file descriptor in a child process. + */ + if (0 == (flags & O_CLOEXEC)) + return -EINVAL; + + return 0; +} + +static unsigned long kbase_get_unmapped_area(struct file *filp, + const unsigned long addr, const unsigned long len, + const unsigned long pgoff, const unsigned long flags) +{ +#ifdef CONFIG_64BIT + /* based on get_unmapped_area, but simplified slightly due to that some + * values are known in advance */ + struct kbase_context *kctx = filp->private_data; + + if (!is_compat_task() && !addr && + kbase_hw_has_feature(kctx->kbdev, BASE_HW_FEATURE_33BIT_VA)) { + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long low_limit, high_limit, gap_start, gap_end; + + /* Hardware has smaller VA than userspace, ensure the page + * comes from a VA which can be used on the GPU */ + + gap_end = (1UL<<33); + if (gap_end < len) + return -ENOMEM; + high_limit = gap_end - len; + low_limit = PAGE_SIZE + len; + + gap_start = mm->highest_vm_end; + if (gap_start <= high_limit) + goto found_highest; + + if (RB_EMPTY_ROOT(&mm->mm_rb)) + return -ENOMEM; + vma = rb_entry(mm->mm_rb.rb_node, struct vm_area_struct, vm_rb); + if (vma->rb_subtree_gap < len) + return -ENOMEM; + + while (true) { + gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; + if (gap_start <= high_limit && vma->vm_rb.rb_right) { + struct vm_area_struct *right = + rb_entry(vma->vm_rb.rb_right, + struct vm_area_struct, vm_rb); + if (right->rb_subtree_gap >= len) { + vma = right; + continue; + } + } +check_current: + gap_end = vma->vm_start; + if (gap_end < low_limit) + return -ENOMEM; + if (gap_start <= high_limit && + gap_end - gap_start >= len) + goto found; + + if (vma->vm_rb.rb_left) { + struct vm_area_struct *left = + rb_entry(vma->vm_rb.rb_left, + struct vm_area_struct, vm_rb); + + if (left->rb_subtree_gap >= len) { + vma = left; + continue; + } + } + while (true) { + struct rb_node *prev = &vma->vm_rb; + + if (!rb_parent(prev)) + return -ENOMEM; + vma = rb_entry(rb_parent(prev), + struct vm_area_struct, vm_rb); + if (prev == vma->vm_rb.rb_right) { + gap_start = vma->vm_prev ? + vma->vm_prev->vm_end : 0; + goto check_current; + } + } + } + +found: + if (gap_end > (1UL<<33)) + gap_end = (1UL<<33); + +found_highest: + gap_end -= len; + + VM_BUG_ON(gap_end < PAGE_SIZE); + VM_BUG_ON(gap_end < gap_start); + return gap_end; + } +#endif + /* No special requirements - fallback to the default version */ + return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags); +} + +static const struct file_operations kbase_fops = { + .owner = THIS_MODULE, + .open = kbase_open, + .release = kbase_release, + .read = kbase_read, + .poll = kbase_poll, + .unlocked_ioctl = kbase_ioctl, + .compat_ioctl = kbase_ioctl, + .mmap = kbase_mmap, + .check_flags = kbase_check_flags, + .get_unmapped_area = kbase_get_unmapped_area, +}; + +#ifndef CONFIG_MALI_NO_MALI +void kbase_os_reg_write(struct kbase_device *kbdev, u16 offset, u32 value) +{ + writel(value, kbdev->reg + offset); +} + +u32 kbase_os_reg_read(struct kbase_device *kbdev, u16 offset) +{ + return readl(kbdev->reg + offset); +} +#endif + +#ifndef CONFIG_MALI_NO_MALI + +static void *kbase_tag(void *ptr, u32 tag) +{ + return (void *)(((uintptr_t) ptr) | tag); +} + +static void *kbase_untag(void *ptr) +{ + return (void *)(((uintptr_t) ptr) & ~3); +} + + + + +static irqreturn_t kbase_job_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.driver_ready_for_irqs) + dev_warn(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_job_done(kbdev, val); + + return IRQ_HANDLED; +} + +KBASE_EXPORT_TEST_API(kbase_job_irq_handler); + +static irqreturn_t kbase_mmu_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.driver_ready_for_irqs) + dev_warn(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_mmu_interrupt(kbdev, val); + + return IRQ_HANDLED; +} + +static irqreturn_t kbase_gpu_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.driver_ready_for_irqs) + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_gpu_interrupt(kbdev, val); + + return IRQ_HANDLED; +} +static irq_handler_t kbase_handler_table[] = { + [JOB_IRQ_TAG] = kbase_job_irq_handler, + [MMU_IRQ_TAG] = kbase_mmu_irq_handler, + [GPU_IRQ_TAG] = kbase_gpu_irq_handler, +}; + + +#ifdef CONFIG_MALI_DEBUG +#define JOB_IRQ_HANDLER JOB_IRQ_TAG +#define MMU_IRQ_HANDLER MMU_IRQ_TAG +#define GPU_IRQ_HANDLER GPU_IRQ_TAG + +/** + * @brief Registers given interrupt handler for requested interrupt type + * Case irq handler is not specified default handler shall be registered + * + * @param[in] kbdev - Device for which the handler is to be registered + * @param[in] custom_handler - Handler to be registered + * @param[in] irq_type - Interrupt type + * @return MALI_ERROR_NONE case success, MALI_ERROR_FUNCTION_FAILED otherwise + */ +static mali_error kbase_set_custom_irq_handler(struct kbase_device *kbdev, irq_handler_t custom_handler, int irq_type) +{ + mali_error result = MALI_ERROR_NONE; + irq_handler_t requested_irq_handler = NULL; + + KBASE_DEBUG_ASSERT((JOB_IRQ_HANDLER <= irq_type) && (GPU_IRQ_HANDLER >= irq_type)); + + /* Release previous handler */ + if (kbdev->irqs[irq_type].irq) + free_irq(kbdev->irqs[irq_type].irq, kbase_tag(kbdev, irq_type)); + + requested_irq_handler = (NULL != custom_handler) ? custom_handler : kbase_handler_table[irq_type]; + + if (0 != request_irq(kbdev->irqs[irq_type].irq, + requested_irq_handler, + kbdev->irqs[irq_type].flags | IRQF_SHARED, + dev_name(kbdev->dev), kbase_tag(kbdev, irq_type))) { + result = MALI_ERROR_FUNCTION_FAILED; + dev_err(kbdev->dev, "Can't request interrupt %d (index %d)\n", kbdev->irqs[irq_type].irq, irq_type); +#ifdef CONFIG_SPARSE_IRQ + dev_err(kbdev->dev, "You have CONFIG_SPARSE_IRQ support enabled - is the interrupt number correct for this configuration?\n"); +#endif /* CONFIG_SPARSE_IRQ */ + } + + return result; +} + +KBASE_EXPORT_TEST_API(kbase_set_custom_irq_handler) + +/* test correct interrupt assigment and reception by cpu */ +struct kbasep_irq_test { + struct hrtimer timer; + wait_queue_head_t wait; + int triggered; + u32 timeout; +}; + +static struct kbasep_irq_test kbasep_irq_test_data; + +#define IRQ_TEST_TIMEOUT 500 + +static irqreturn_t kbase_job_irq_test_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_STATUS), NULL); + + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbasep_irq_test_data.triggered = 1; + wake_up(&kbasep_irq_test_data.wait); + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), val, NULL); + + return IRQ_HANDLED; +} + +static irqreturn_t kbase_mmu_irq_test_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_STATUS), NULL); + + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbasep_irq_test_data.triggered = 1; + wake_up(&kbasep_irq_test_data.wait); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), val, NULL); + + return IRQ_HANDLED; +} + +static enum hrtimer_restart kbasep_test_interrupt_timeout(struct hrtimer *timer) +{ + struct kbasep_irq_test *test_data = container_of(timer, struct kbasep_irq_test, timer); + + test_data->timeout = 1; + test_data->triggered = 1; + wake_up(&test_data->wait); + return HRTIMER_NORESTART; +} + +static mali_error kbasep_common_test_interrupt(struct kbase_device * const kbdev, u32 tag) +{ + mali_error err = MALI_ERROR_NONE; + irq_handler_t test_handler; + + u32 old_mask_val; + u16 mask_offset; + u16 rawstat_offset; + + switch (tag) { + case JOB_IRQ_TAG: + test_handler = kbase_job_irq_test_handler; + rawstat_offset = JOB_CONTROL_REG(JOB_IRQ_RAWSTAT); + mask_offset = JOB_CONTROL_REG(JOB_IRQ_MASK); + break; + case MMU_IRQ_TAG: + test_handler = kbase_mmu_irq_test_handler; + rawstat_offset = MMU_REG(MMU_IRQ_RAWSTAT); + mask_offset = MMU_REG(MMU_IRQ_MASK); + break; + case GPU_IRQ_TAG: + /* already tested by pm_driver - bail out */ + default: + return MALI_ERROR_NONE; + } + + /* store old mask */ + old_mask_val = kbase_reg_read(kbdev, mask_offset, NULL); + /* mask interrupts */ + kbase_reg_write(kbdev, mask_offset, 0x0, NULL); + + if (kbdev->irqs[tag].irq) { + /* release original handler and install test handler */ + if (MALI_ERROR_NONE != kbase_set_custom_irq_handler(kbdev, test_handler, tag)) { + err = MALI_ERROR_FUNCTION_FAILED; + } else { + kbasep_irq_test_data.timeout = 0; + hrtimer_init(&kbasep_irq_test_data.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbasep_irq_test_data.timer.function = kbasep_test_interrupt_timeout; + + /* trigger interrupt */ + kbase_reg_write(kbdev, mask_offset, 0x1, NULL); + kbase_reg_write(kbdev, rawstat_offset, 0x1, NULL); + + hrtimer_start(&kbasep_irq_test_data.timer, HR_TIMER_DELAY_MSEC(IRQ_TEST_TIMEOUT), HRTIMER_MODE_REL); + + wait_event(kbasep_irq_test_data.wait, kbasep_irq_test_data.triggered != 0); + + if (kbasep_irq_test_data.timeout != 0) { + dev_err(kbdev->dev, "Interrupt %d (index %d) didn't reach CPU.\n", kbdev->irqs[tag].irq, tag); + err = MALI_ERROR_FUNCTION_FAILED; + } else { + dev_dbg(kbdev->dev, "Interrupt %d (index %d) reached CPU.\n", kbdev->irqs[tag].irq, tag); + } + + hrtimer_cancel(&kbasep_irq_test_data.timer); + kbasep_irq_test_data.triggered = 0; + + /* mask interrupts */ + kbase_reg_write(kbdev, mask_offset, 0x0, NULL); + + /* release test handler */ + free_irq(kbdev->irqs[tag].irq, kbase_tag(kbdev, tag)); + } + + /* restore original interrupt */ + if (request_irq(kbdev->irqs[tag].irq, kbase_handler_table[tag], kbdev->irqs[tag].flags | IRQF_SHARED, dev_name(kbdev->dev), kbase_tag(kbdev, tag))) { + dev_err(kbdev->dev, "Can't restore original interrupt %d (index %d)\n", kbdev->irqs[tag].irq, tag); + err = MALI_ERROR_FUNCTION_FAILED; + } + } + /* restore old mask */ + kbase_reg_write(kbdev, mask_offset, old_mask_val, NULL); + + return err; +} + +static mali_error kbasep_common_test_interrupt_handlers(struct kbase_device * const kbdev) +{ + mali_error err; + + init_waitqueue_head(&kbasep_irq_test_data.wait); + kbasep_irq_test_data.triggered = 0; + + /* A suspend won't happen during startup/insmod */ + kbase_pm_context_active(kbdev); + + err = kbasep_common_test_interrupt(kbdev, JOB_IRQ_TAG); + if (MALI_ERROR_NONE != err) { + dev_err(kbdev->dev, "Interrupt JOB_IRQ didn't reach CPU. Check interrupt assignments.\n"); + goto out; + } + + err = kbasep_common_test_interrupt(kbdev, MMU_IRQ_TAG); + if (MALI_ERROR_NONE != err) { + dev_err(kbdev->dev, "Interrupt MMU_IRQ didn't reach CPU. Check interrupt assignments.\n"); + goto out; + } + + dev_dbg(kbdev->dev, "Interrupts are correctly assigned.\n"); + + out: + kbase_pm_context_idle(kbdev); + + return err; +} +#endif /* CONFIG_MALI_DEBUG */ + +static int kbase_install_interrupts(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + int err; + u32 i; + + for (i = 0; i < nr; i++) { + err = request_irq(kbdev->irqs[i].irq, kbase_handler_table[i], kbdev->irqs[i].flags | IRQF_SHARED, dev_name(kbdev->dev), kbase_tag(kbdev, i)); + if (err) { + dev_err(kbdev->dev, "Can't request interrupt %d (index %d)\n", kbdev->irqs[i].irq, i); +#ifdef CONFIG_SPARSE_IRQ + dev_err(kbdev->dev, "You have CONFIG_SPARSE_IRQ support enabled - is the interrupt number correct for this configuration?\n"); +#endif /* CONFIG_SPARSE_IRQ */ + goto release; + } + } + + return 0; + + release: + while (i-- > 0) + free_irq(kbdev->irqs[i].irq, kbase_tag(kbdev, i)); + + return err; +} + +static void kbase_release_interrupts(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + u32 i; + + for (i = 0; i < nr; i++) { + if (kbdev->irqs[i].irq) + free_irq(kbdev->irqs[i].irq, kbase_tag(kbdev, i)); + } +} + +void kbase_synchronize_irqs(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + u32 i; + + for (i = 0; i < nr; i++) { + if (kbdev->irqs[i].irq) + synchronize_irq(kbdev->irqs[i].irq); + } +} +#endif /* CONFIG_MALI_NO_MALI */ + +#if KBASE_PM_EN +/** Show callback for the @c power_policy sysfs file. + * + * This function is called to get the contents of the @c power_policy sysfs + * file. This is a list of the available policies with the currently active one + * surrounded by square brackets. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_policy(struct device *dev, struct device_attribute *attr, char *const buf) +{ + struct kbase_device *kbdev; + const struct kbase_pm_policy *current_policy; + const struct kbase_pm_policy *const *policy_list; + int policy_count; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + current_policy = kbase_pm_get_policy(kbdev); + + policy_count = kbase_pm_list_policies(&policy_list); + + for (i = 0; i < policy_count && ret < PAGE_SIZE; i++) { + if (policy_list[i] == current_policy) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s] ", policy_list[i]->name); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ", policy_list[i]->name); + } + + if (ret < PAGE_SIZE - 1) { + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); + } else { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** Store callback for the @c power_policy sysfs file. + * + * This function is called when the @c power_policy sysfs file is written to. + * It matches the requested policy against the available policies and if a + * matching policy is found calls @ref kbase_pm_set_policy to change the + * policy. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_policy(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + const struct kbase_pm_policy *new_policy = NULL; + const struct kbase_pm_policy *const *policy_list; + int policy_count; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + policy_count = kbase_pm_list_policies(&policy_list); + + for (i = 0; i < policy_count; i++) { + if (sysfs_streq(policy_list[i]->name, buf)) { + new_policy = policy_list[i]; + break; + } + } + + if (!new_policy) { + dev_err(dev, "power_policy: policy not found\n"); + return -EINVAL; + } + + kbase_pm_set_policy(kbdev, new_policy); + + return count; +} + +/** The sysfs file @c power_policy. + * + * This is used for obtaining information about the available policies, + * determining which policy is currently active, and changing the active + * policy. + */ +static DEVICE_ATTR(power_policy, S_IRUGO | S_IWUSR, show_policy, set_policy); + +/** Show callback for the @c core_availability_policy sysfs file. + * + * This function is called to get the contents of the @c core_availability_policy + * sysfs file. This is a list of the available policies with the currently + * active one surrounded by square brackets. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_ca_policy(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + const struct kbase_pm_ca_policy *current_policy; + const struct kbase_pm_ca_policy *const *policy_list; + int policy_count; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + current_policy = kbase_pm_ca_get_policy(kbdev); + + policy_count = kbase_pm_ca_list_policies(&policy_list); + + for (i = 0; i < policy_count && ret < PAGE_SIZE; i++) { + if (policy_list[i] == current_policy) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s] ", policy_list[i]->name); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ", policy_list[i]->name); + } + + if (ret < PAGE_SIZE - 1) { + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); + } else { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** Store callback for the @c core_availability_policy sysfs file. + * + * This function is called when the @c core_availability_policy sysfs file is + * written to. It matches the requested policy against the available policies + * and if a matching policy is found calls @ref kbase_pm_set_policy to change + * the policy. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_ca_policy(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + const struct kbase_pm_ca_policy *new_policy = NULL; + const struct kbase_pm_ca_policy *const *policy_list; + int policy_count; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + policy_count = kbase_pm_ca_list_policies(&policy_list); + + for (i = 0; i < policy_count; i++) { + if (sysfs_streq(policy_list[i]->name, buf)) { + new_policy = policy_list[i]; + break; + } + } + + if (!new_policy) { + dev_err(dev, "core_availability_policy: policy not found\n"); + return -EINVAL; + } + + kbase_pm_ca_set_policy(kbdev, new_policy); + + return count; +} + +/** The sysfs file @c core_availability_policy + * + * This is used for obtaining information about the available policies, + * determining which policy is currently active, and changing the active + * policy. + */ +static DEVICE_ATTR(core_availability_policy, S_IRUGO | S_IWUSR, show_ca_policy, set_ca_policy); + +/** Show callback for the @c core_mask sysfs file. + * + * This function is called to get the contents of the @c core_mask sysfs + * file. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_core_mask(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "Current core mask : 0x%llX\n", kbdev->pm.debug_core_mask); + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "Available core mask : 0x%llX\n", kbdev->shader_present_bitmap); + + return ret; +} + +/** Store callback for the @c core_mask sysfs file. + * + * This function is called when the @c core_mask sysfs file is written to. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_core_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + u64 new_core_mask; + int rc; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + rc = kstrtoull(buf, 16, &new_core_mask); + if (rc) + return rc; + + if ((new_core_mask & kbdev->shader_present_bitmap) != new_core_mask || + !(new_core_mask & kbdev->gpu_props.props.coherency_info.group[0].core_mask)) { + dev_err(dev, "power_policy: invalid core specification\n"); + return -EINVAL; + } + + if (kbdev->pm.debug_core_mask != new_core_mask) { + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + kbdev->pm.debug_core_mask = new_core_mask; + kbase_pm_update_cores_state_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + } + + return count; +} + +/** The sysfs file @c core_mask. + * + * This is used to restrict shader core availability for debugging purposes. + * Reading it will show the current core mask and the mask of cores available. + * Writing to it will set the current core mask. + */ +static DEVICE_ATTR(core_mask, S_IRUGO | S_IWUSR, show_core_mask, set_core_mask); +#endif /* KBASE_PM_EN */ + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS +/* Import the external affinity mask variables */ +extern u64 mali_js0_affinity_mask; +extern u64 mali_js1_affinity_mask; +extern u64 mali_js2_affinity_mask; + +/** + * Structure containing a single shader affinity split configuration. + */ +struct sc_split_config { + char const *tag; + char const *human_readable; + u64 js0_mask; + u64 js1_mask; + u64 js2_mask; +}; + +/** + * Array of available shader affinity split configurations. + */ +static struct sc_split_config const sc_split_configs[] = { + /* All must be the first config (default). */ + { + "all", "All cores", + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL + }, + { + "mp1", "MP1 shader core", + 0x1, 0x1, 0x1 + }, + { + "mp2", "MP2 shader core", + 0x3, 0x3, 0x3 + }, + { + "mp4", "MP4 shader core", + 0xF, 0xF, 0xF + }, + { + "mp1_vf", "MP1 vertex + MP1 fragment shader core", + 0x2, 0x1, 0xFFFFFFFFFFFFFFFFULL + }, + { + "mp2_vf", "MP2 vertex + MP2 fragment shader core", + 0xA, 0x5, 0xFFFFFFFFFFFFFFFFULL + }, + /* This must be the last config. */ + { + NULL, NULL, + 0x0, 0x0, 0x0 + }, +}; + +/* Pointer to the currently active shader split configuration. */ +static struct sc_split_config const *current_sc_split_config = &sc_split_configs[0]; + +/** Show callback for the @c sc_split sysfs file + * + * Returns the current shader core affinity policy. + */ +static ssize_t show_split(struct device *dev, struct device_attribute *attr, char * const buf) +{ + ssize_t ret; + /* We know we are given a buffer which is PAGE_SIZE long. Our strings are all guaranteed + * to be shorter than that at this time so no length check needed. */ + ret = scnprintf(buf, PAGE_SIZE, "Current sc_split: '%s'\n", current_sc_split_config->tag); + return ret; +} + +/** Store callback for the @c sc_split sysfs file. + * + * This function is called when the @c sc_split sysfs file is written to + * It modifies the system shader core affinity configuration to allow + * system profiling with different hardware configurations. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_split(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct sc_split_config const *config = &sc_split_configs[0]; + + /* Try to match: loop until we hit the last "NULL" entry */ + while (config->tag) { + if (sysfs_streq(config->tag, buf)) { + current_sc_split_config = config; + mali_js0_affinity_mask = config->js0_mask; + mali_js1_affinity_mask = config->js1_mask; + mali_js2_affinity_mask = config->js2_mask; + dev_dbg(dev, "Setting sc_split: '%s'\n", config->tag); + return count; + } + config++; + } + + /* No match found in config list */ + dev_err(dev, "sc_split: invalid value\n"); + dev_err(dev, " Possible settings: mp[1|2|4], mp[1|2]_vf\n"); + return -ENOENT; +} + +/** The sysfs file @c sc_split + * + * This is used for configuring/querying the current shader core work affinity + * configuration. + */ +static DEVICE_ATTR(sc_split, S_IRUGO|S_IWUSR, show_split, set_split); +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ + + +#if !MALI_CUSTOMER_RELEASE +/** Store callback for the @c js_timeouts sysfs file. + * + * This function is called to get the contents of the @c js_timeouts sysfs + * file. This file contains five values separated by whitespace. The values + * are basically the same as KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, BASE_CONFIG_ATTR_JS_RESET_TICKS_NSS + * configuration values (in that order), with the difference that the js_timeout + * valus are expressed in MILLISECONDS. + * + * The js_timeouts sysfile file allows the current values in + * use by the job scheduler to get override. Note that a value needs to + * be other than 0 for it to override the current job scheduler value. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_js_timeouts(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int items; + unsigned long js_soft_stop_ms; + unsigned long js_soft_stop_ms_cl; + unsigned long js_hard_stop_ms_ss; + unsigned long js_hard_stop_ms_cl; + unsigned long js_hard_stop_ms_nss; + unsigned long js_reset_ms_ss; + unsigned long js_reset_ms_cl; + unsigned long js_reset_ms_nss; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + items = sscanf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu", + &js_soft_stop_ms, &js_soft_stop_ms_cl, + &js_hard_stop_ms_ss, &js_hard_stop_ms_cl, + &js_hard_stop_ms_nss, &js_reset_ms_ss, + &js_reset_ms_cl, &js_reset_ms_nss); + + if (items == 8) { + u64 ticks; + + ticks = js_soft_stop_ms * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_soft_stop_ticks = ticks; + + ticks = js_soft_stop_ms_cl * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_soft_stop_ticks_cl = ticks; + + ticks = js_hard_stop_ms_ss * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_hard_stop_ticks_ss = ticks; + + ticks = js_hard_stop_ms_cl * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_hard_stop_ticks_cl = ticks; + + ticks = js_hard_stop_ms_nss * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_hard_stop_ticks_nss = ticks; + + ticks = js_reset_ms_ss * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_reset_ticks_ss = ticks; + + ticks = js_reset_ms_cl * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_reset_ticks_cl = ticks; + + ticks = js_reset_ms_nss * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_reset_ticks_nss = ticks; + + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_soft_stop_ticks, js_soft_stop_ms); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_soft_stop_ticks_cl, js_soft_stop_ms_cl); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_hard_stop_ticks_ss, js_hard_stop_ms_ss); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_hard_stop_ticks_cl, js_hard_stop_ms_cl); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_hard_stop_ticks_nss, js_hard_stop_ms_nss); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_reset_ticks_ss, js_reset_ms_ss); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_reset_ticks_cl, js_reset_ms_cl); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_reset_ticks_nss, js_reset_ms_nss); + + return count; + } else { + dev_err(kbdev->dev, "Couldn't process js_timeouts write operation.\nUse format " " \n"); + return -EINVAL; + } +} + +/** Show callback for the @c js_timeouts sysfs file. + * + * This function is called to get the contents of the @c js_timeouts sysfs + * file. It returns the last set values written to the js_timeouts sysfs file. + * If the file didn't get written yet, the values will be 0. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_js_timeouts(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + u64 ms; + unsigned long js_soft_stop_ms; + unsigned long js_soft_stop_ms_cl; + unsigned long js_hard_stop_ms_ss; + unsigned long js_hard_stop_ms_cl; + unsigned long js_hard_stop_ms_nss; + unsigned long js_reset_ms_ss; + unsigned long js_reset_ms_cl; + unsigned long js_reset_ms_nss; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ms = (u64) kbdev->js_soft_stop_ticks * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_soft_stop_ms = (unsigned long)ms; + + ms = (u64) kbdev->js_soft_stop_ticks_cl * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_soft_stop_ms_cl = (unsigned long)ms; + + ms = (u64) kbdev->js_hard_stop_ticks_ss * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_hard_stop_ms_ss = (unsigned long)ms; + + ms = (u64) kbdev->js_hard_stop_ticks_cl * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_hard_stop_ms_cl = (unsigned long)ms; + + ms = (u64) kbdev->js_hard_stop_ticks_nss * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_hard_stop_ms_nss = (unsigned long)ms; + + ms = (u64) kbdev->js_reset_ticks_ss * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_reset_ms_ss = (unsigned long)ms; + + ms = (u64) kbdev->js_reset_ticks_cl * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_reset_ms_cl = (unsigned long)ms; + + ms = (u64) kbdev->js_reset_ticks_nss * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_reset_ms_nss = (unsigned long)ms; + + ret = scnprintf(buf, PAGE_SIZE, "%lu %lu %lu %lu %lu %lu %lu %lu\n", + js_soft_stop_ms, js_soft_stop_ms_cl, + js_hard_stop_ms_ss, js_hard_stop_ms_cl, + js_hard_stop_ms_nss, js_reset_ms_ss, + js_reset_ms_cl, js_reset_ms_nss); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** The sysfs file @c js_timeouts. + * + * This is used to override the current job scheduler values for + * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_SS + * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_CL + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS. + */ +static DEVICE_ATTR(js_timeouts, S_IRUGO | S_IWUSR, show_js_timeouts, set_js_timeouts); + + + +/** Store callback for the @c force_replay sysfs file. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_force_replay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + if (!strncmp("limit=", buf, MIN(6, count))) { + int force_replay_limit; + int items = sscanf(buf, "limit=%u", &force_replay_limit); + + if (items == 1) { + kbdev->force_replay_random = MALI_FALSE; + kbdev->force_replay_limit = force_replay_limit; + kbdev->force_replay_count = 0; + + return count; + } + } else if (!strncmp("random_limit", buf, MIN(12, count))) { + kbdev->force_replay_random = MALI_TRUE; + kbdev->force_replay_count = 0; + + return count; + } else if (!strncmp("norandom_limit", buf, MIN(14, count))) { + kbdev->force_replay_random = MALI_FALSE; + kbdev->force_replay_limit = KBASEP_FORCE_REPLAY_DISABLED; + kbdev->force_replay_count = 0; + + return count; + } else if (!strncmp("core_req=", buf, MIN(9, count))) { + unsigned int core_req; + int items = sscanf(buf, "core_req=%x", &core_req); + + if (items == 1) { + kbdev->force_replay_core_req = (base_jd_core_req)core_req; + + return count; + } + } + dev_err(kbdev->dev, "Couldn't process force_replay write operation.\nPossible settings: limit=, random_limit, norandom_limit, core_req=\n"); + return -EINVAL; +} + +/** Show callback for the @c force_replay sysfs file. + * + * This function is called to get the contents of the @c force_replay sysfs + * file. It returns the last set value written to the force_replay sysfs file. + * If the file didn't get written yet, the values will be 0. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_force_replay(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + if (kbdev->force_replay_random) + ret = scnprintf(buf, PAGE_SIZE, + "limit=0\nrandom_limit\ncore_req=%x\n", + kbdev->force_replay_core_req); + else + ret = scnprintf(buf, PAGE_SIZE, + "limit=%u\nnorandom_limit\ncore_req=%x\n", + kbdev->force_replay_limit, + kbdev->force_replay_core_req); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** The sysfs file @c force_replay. + * + */ +static DEVICE_ATTR(force_replay, S_IRUGO | S_IWUSR, show_force_replay, set_force_replay); +#endif /* !MALI_CUSTOMER_RELEASE */ + +#ifdef CONFIG_MALI_DEBUG +static ssize_t set_js_softstop_always(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int items; + int softstop_always; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + items = sscanf(buf, "%d", &softstop_always); + if ((items == 1) && ((softstop_always == 0) || (softstop_always == 1))) { + kbdev->js_data.softstop_always = (mali_bool) softstop_always; + dev_dbg(kbdev->dev, "Support for softstop on a single context: %s\n", (kbdev->js_data.softstop_always == MALI_FALSE) ? "Disabled" : "Enabled"); + return count; + } else { + dev_err(kbdev->dev, "Couldn't process js_softstop_always write operation.\nUse format " "\n"); + return -EINVAL; + } +} + +static ssize_t show_js_softstop_always(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = scnprintf(buf, PAGE_SIZE, "%d\n", kbdev->js_data.softstop_always); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** + * By default, soft-stops are disabled when only a single context is present. The ability to + * enable soft-stop when only a single context is present can be used for debug and unit-testing purposes. + * (see CL t6xx_stress_1 unit-test as an example whereby this feature is used.) + */ +static DEVICE_ATTR(js_softstop_always, S_IRUGO | S_IWUSR, show_js_softstop_always, set_js_softstop_always); +#endif /* CONFIG_MALI_DEBUG */ + +#ifdef CONFIG_MALI_DEBUG +typedef void (kbasep_debug_command_func) (struct kbase_device *); + +enum kbasep_debug_command_code { + KBASEP_DEBUG_COMMAND_DUMPTRACE, + + /* This must be the last enum */ + KBASEP_DEBUG_COMMAND_COUNT +}; + +struct kbasep_debug_command { + char *str; + kbasep_debug_command_func *func; +}; + +/** Debug commands supported by the driver */ +static const struct kbasep_debug_command debug_commands[] = { + { + .str = "dumptrace", + .func = &kbasep_trace_dump, + } +}; + +/** Show callback for the @c debug_command sysfs file. + * + * This function is called to get the contents of the @c debug_command sysfs + * file. This is a list of the available debug commands, separated by newlines. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_debug(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + for (i = 0; i < KBASEP_DEBUG_COMMAND_COUNT && ret < PAGE_SIZE; i++) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s\n", debug_commands[i].str); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** Store callback for the @c debug_command sysfs file. + * + * This function is called when the @c debug_command sysfs file is written to. + * It matches the requested command against the available commands, and if + * a matching command is found calls the associated function from + * @ref debug_commands to issue the command. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t issue_debug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + for (i = 0; i < KBASEP_DEBUG_COMMAND_COUNT; i++) { + if (sysfs_streq(debug_commands[i].str, buf)) { + debug_commands[i].func(kbdev); + return count; + } + } + + /* Debug Command not found */ + dev_err(dev, "debug_command: command not known\n"); + return -EINVAL; +} + +/** The sysfs file @c debug_command. + * + * This is used to issue general debug commands to the device driver. + * Reading it will produce a list of debug commands, separated by newlines. + * Writing to it with one of those commands will issue said command. + */ +static DEVICE_ATTR(debug_command, S_IRUGO | S_IWUSR, show_debug, issue_debug); +#endif /* CONFIG_MALI_DEBUG */ + + +#ifdef CONFIG_MALI_NO_MALI +static int kbase_common_reg_map(struct kbase_device *kbdev) +{ + return 0; +} +static void kbase_common_reg_unmap(struct kbase_device * const kbdev) +{ +} +#else /* CONFIG_MALI_NO_MALI */ +static int kbase_common_reg_map(struct kbase_device *kbdev) +{ + int err = -ENOMEM; + + kbdev->reg_res = request_mem_region(kbdev->reg_start, kbdev->reg_size, dev_name(kbdev->dev)); + if (!kbdev->reg_res) { + dev_err(kbdev->dev, "Register window unavailable\n"); + err = -EIO; + goto out_region; + } + + kbdev->reg = ioremap(kbdev->reg_start, kbdev->reg_size); + if (!kbdev->reg) { + dev_err(kbdev->dev, "Can't remap register window\n"); + err = -EINVAL; + goto out_ioremap; + } + + return 0; + + out_ioremap: + release_resource(kbdev->reg_res); + kfree(kbdev->reg_res); + out_region: + return err; +} + +static int mtk_mfg_reg_map(struct kbase_device *kbdev) +{ + int err = -ENOMEM; + struct device_node *dnode; + //void __iomem *clk_mfgsys_base; + + dnode = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-mfgsys"); + if (!dnode) { + pr_alert("[Mali][mtk_mfg_reg_map] mfgsys find node failed\n"); + goto out_ioremap_err; + }else{ + kbdev->mfg_register = of_iomap(dnode, 0); + } + + if (!kbdev->mfg_register) { + dev_err(kbdev->dev, "[Mali][mtk_mfg_reg_map] Can't remap mfgsys register \n"); + err = -EINVAL; + goto out_ioremap_err; + } + + return 0; + + out_ioremap_err: + return err; +} +static void kbase_common_reg_unmap(struct kbase_device * const kbdev) +{ + iounmap(kbdev->reg); + release_resource(kbdev->reg_res); + kfree(kbdev->reg_res); +} +#endif /* CONFIG_MALI_NO_MALI */ + +static int kbase_common_device_init(struct kbase_device *kbdev) +{ + int err = -ENOMEM; + mali_error mali_err; + enum { + inited_mem = (1u << 0), + inited_job_slot = (1u << 1), + inited_pm = (1u << 2), + inited_js = (1u << 3), + inited_irqs = (1u << 4), + inited_debug = (1u << 5), + inited_js_softstop = (1u << 6), +#if !MALI_CUSTOMER_RELEASE + inited_js_timeouts = (1u << 7), + inited_force_replay = (1u << 13), +#endif /* !MALI_CUSTOMER_RELEASE */ + inited_pm_runtime_init = (1u << 8), +#ifdef CONFIG_DEBUG_FS + inited_gpu_memory = (1u << 9), +#endif /* CONFIG_DEBUG_FS */ +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + inited_sc_split = (1u << 11), +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ +#ifdef CONFIG_MALI_TRACE_TIMELINE + inited_timeline = (1u << 12), +#endif /* CONFIG_MALI_TRACE_LINE */ + inited_pm_powerup = (1u << 14), + }; + + int inited = 0; + + dev_set_drvdata(kbdev->dev, kbdev); + + kbdev->mdev.minor = MISC_DYNAMIC_MINOR; + kbdev->mdev.name = kbdev->devname; + kbdev->mdev.fops = &kbase_fops; + kbdev->mdev.parent = get_device(kbdev->dev); + + kbase_disjoint_init(kbdev); + + scnprintf(kbdev->devname, DEVNAME_SIZE, "%s%d", kbase_drv_name, kbase_dev_nr++); + + if (misc_register(&kbdev->mdev)) { + dev_err(kbdev->dev, "Couldn't register misc dev %s\n", kbdev->devname); + err = -EINVAL; + goto out_misc; + } +#if KBASE_PM_EN + if (device_create_file(kbdev->dev, &dev_attr_power_policy)) { + dev_err(kbdev->dev, "Couldn't create power_policy sysfs file\n"); + goto out_file; + } + + if (device_create_file(kbdev->dev, &dev_attr_core_availability_policy)) { + dev_err(kbdev->dev, "Couldn't create core_availability_policy sysfs file\n"); + goto out_file_core_availability_policy; + } + + if (device_create_file(kbdev->dev, &dev_attr_core_mask)) { + dev_err(kbdev->dev, "Couldn't create core_mask sysfs file\n"); + goto out_file_core_mask; + } +#endif /* KBASE_PM_EN */ + down(&kbase_dev_list_lock); + list_add(&kbdev->entry, &kbase_dev_list); + up(&kbase_dev_list_lock); + dev_info(kbdev->dev, "Probed as %s\n", dev_name(kbdev->mdev.this_device)); + + mali_err = kbase_pm_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_pm; + + if (kbdev->pm.callback_power_runtime_init) { + mali_err = kbdev->pm.callback_power_runtime_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_pm_runtime_init; + } + + mali_err = kbase_mem_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_mem; + + mali_err = kbase_job_slot_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_job_slot; + + mali_err = kbasep_js_devdata_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_js; + + err = kbase_install_interrupts(kbdev); + if (err) + goto out_partial; + + inited |= inited_irqs; + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + if (device_create_file(kbdev->dev, &dev_attr_sc_split)) { + dev_err(kbdev->dev, "Couldn't create sc_split sysfs file\n"); + goto out_partial; + } + + inited |= inited_sc_split; +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ + +#ifdef CONFIG_DEBUG_FS + if (kbasep_gpu_memory_debugfs_init(kbdev)) { + dev_err(kbdev->dev, "Couldn't create gpu_memory debugfs file\n"); + goto out_partial; + } + inited |= inited_gpu_memory; + +#endif /* CONFIG_DEBUG_FS */ + + mtk_get_gpu_memory_usage_fp = kbase_report_gpu_memory_usage; + +#ifdef CONFIG_PROC_FS + proc_mali_register(); +#endif + +#ifdef CONFIG_MALI_DEBUG + + if (device_create_file(kbdev->dev, &dev_attr_debug_command)) { + dev_err(kbdev->dev, "Couldn't create debug_command sysfs file\n"); + goto out_partial; + } + inited |= inited_debug; + + if (device_create_file(kbdev->dev, &dev_attr_js_softstop_always)) { + dev_err(kbdev->dev, "Couldn't create js_softstop_always sysfs file\n"); + goto out_partial; + } + inited |= inited_js_softstop; +#endif /* CONFIG_MALI_DEBUG */ + +#if !MALI_CUSTOMER_RELEASE + if (device_create_file(kbdev->dev, &dev_attr_js_timeouts)) { + dev_err(kbdev->dev, "Couldn't create js_timeouts sysfs file\n"); + goto out_partial; + } + inited |= inited_js_timeouts; + + if (device_create_file(kbdev->dev, &dev_attr_force_replay)) { + dev_err(kbdev->dev, "Couldn't create force_replay sysfs file\n"); + goto out_partial; + } + inited |= inited_force_replay; +#endif /* !MALI_CUSTOMER_RELEASE */ + +#ifdef CONFIG_MALI_TRACE_TIMELINE + if (kbasep_trace_timeline_debugfs_init(kbdev)) { + dev_err(kbdev->dev, "Couldn't create mali_timeline_defs debugfs file\n"); + goto out_partial; + } + inited |= inited_timeline; +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +#ifdef CONFIG_MALI_DEVFREQ + kbase_devfreq_init(kbdev); +#endif + + mali_err = kbase_pm_powerup(kbdev); + if (MALI_ERROR_NONE == mali_err) { + inited |= inited_pm_powerup; +#ifdef CONFIG_MALI_DEBUG +#if !defined(CONFIG_MALI_NO_MALI) + if (MALI_ERROR_NONE != kbasep_common_test_interrupt_handlers(kbdev)) { + dev_err(kbdev->dev, "Interrupt assigment check failed.\n"); + err = -EINVAL; + goto out_partial; + } +#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_DEBUG */ + /* intialise the kctx list */ + mutex_init(&kbdev->kctx_list_lock); + INIT_LIST_HEAD(&kbdev->kctx_list); + return 0; + } else { + /* Failed to power up the GPU. */ + dev_err(kbdev->dev, "GPU power up failed.\n"); + err = -ENODEV; + } + + out_partial: +#ifdef CONFIG_MALI_TRACE_TIMELINE + if (inited & inited_timeline) + kbasep_trace_timeline_debugfs_term(kbdev); +#endif /* CONFIG_MALI_TRACE_TIMELINE */ +#if !MALI_CUSTOMER_RELEASE + if (inited & inited_force_replay) + device_remove_file(kbdev->dev, &dev_attr_force_replay); + if (inited & inited_js_timeouts) + device_remove_file(kbdev->dev, &dev_attr_js_timeouts); +#endif /* !MALI_CUSTOMER_RELEASE */ +#ifdef CONFIG_MALI_DEBUG + if (inited & inited_js_softstop) + device_remove_file(kbdev->dev, &dev_attr_js_softstop_always); + + if (inited & inited_debug) + device_remove_file(kbdev->dev, &dev_attr_debug_command); + +#endif /* CONFIG_MALI_DEBUG */ + +#ifdef CONFIG_DEBUG_FS + if (inited & inited_gpu_memory) + kbasep_gpu_memory_debugfs_term(kbdev); +#endif /* CONFIG_DEBUG_FS */ + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + if (inited & inited_sc_split) + device_remove_file(kbdev->dev, &dev_attr_sc_split); +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ + + if (inited & inited_js) + kbasep_js_devdata_halt(kbdev); + + if (inited & inited_job_slot) + kbase_job_slot_halt(kbdev); + + if (inited & inited_mem) + kbase_mem_halt(kbdev); + + if (inited & inited_pm_powerup) + kbase_pm_halt(kbdev); + + if (inited & inited_irqs) + kbase_release_interrupts(kbdev); + + if (inited & inited_js) + kbasep_js_devdata_term(kbdev); + + if (inited & inited_job_slot) + kbase_job_slot_term(kbdev); + + if (inited & inited_mem) + kbase_mem_term(kbdev); + + if (inited & inited_pm_runtime_init) { + if (kbdev->pm.callback_power_runtime_term) + kbdev->pm.callback_power_runtime_term(kbdev); + } + + if (inited & inited_pm) + kbase_pm_term(kbdev); + + down(&kbase_dev_list_lock); + list_del(&kbdev->entry); + up(&kbase_dev_list_lock); +#if KBASE_PM_EN + device_remove_file(kbdev->dev, &dev_attr_core_mask); + out_file_core_mask: + device_remove_file(kbdev->dev, &dev_attr_core_availability_policy); + out_file_core_availability_policy: + device_remove_file(kbdev->dev, &dev_attr_power_policy); + out_file: +#endif /*KBASE_PM_EN*/ + misc_deregister(&kbdev->mdev); + out_misc: + put_device(kbdev->dev); + return err; +} + + +static int kbase_platform_device_probe(struct platform_device *pdev) +{ + struct kbase_device *kbdev; + struct resource *reg_res; + struct kbase_attribute *platform_data; + int err; + int i; + struct mali_base_gpu_core_props *core_props; +#ifdef CONFIG_MALI_NO_MALI + mali_error mali_err; +#endif /* CONFIG_MALI_NO_MALI */ +#ifdef CONFIG_OF +#ifdef CONFIG_MALI_PLATFORM_FAKE + struct kbase_platform_config *config; + struct device_node *node; + int attribute_count; + int probe_count=0; + +probe_begin: + + pr_alert("[MALI]Using mali midgard r5p0-EAC DDK kernel device driver. GPU probe() begin. probe_count = %d, [%s][l:%d] \n", probe_count, __func__, __LINE__); + +#ifdef CONFIG_OF + //mfgcfg + node = of_find_compatible_node(NULL, NULL, "mediatek,G3D_CONFIG"); + if (!node) { + pr_debug("[CLK_G3D_CONFIG] find node failed\n"); + } + clk_mfgcfg_base_addr = of_iomap(node, 0); + if (!clk_mfgcfg_base_addr) + pr_debug("[CLK_G3D_CONFIG] base failed\n"); +#endif + config = kbase_get_platform_config(); + attribute_count = kbasep_get_config_attribute_count(config->attributes); + + err = platform_device_add_data(pdev, config->attributes, + attribute_count * sizeof(config->attributes[0])); + if (err){ + pr_alert("[MALI]Using platform_device_add_data err, [%s][l:%d] \n", __func__, __LINE__); + goto out; + // return err; // remove return for probe re-try machinization + } +#endif /* CONFIG_MALI_PLATFORM_FAKE */ +#endif /* CONFIG_OF */ + + kbdev = kbase_device_alloc(); + if (!kbdev) { + pr_alert("[Mali]Can't allocate device\n"); + err = -ENOMEM; + goto out; + } +#ifdef CONFIG_MALI_NO_MALI + mali_err = midg_device_create(kbdev); + if (MALI_ERROR_NONE != mali_err) { + pr_alert("[Mali]Can't initialize dummy model\n"); + err = -ENOMEM; + goto out_midg; + } +#endif /* CONFIG_MALI_NO_MALI */ + + kbdev->dev = &pdev->dev; + platform_data = (struct kbase_attribute *)kbdev->dev->platform_data; + + if (NULL == platform_data) { + pr_alert("[Mali]Platform data not specified\n"); + err = -ENOENT; + goto out_free_dev; + } + + if (MALI_TRUE != kbasep_validate_configuration_attributes(kbdev, platform_data)) { + pr_alert("[Mali]Configuration attributes failed to validate\n"); + err = -EINVAL; + goto out_free_dev; + } + kbdev->config_attributes = platform_data; + + /* 3 IRQ resources */ + for (i = 0; i < 3; i++) { + struct resource *irq_res; + int irqtag; + + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + if (!irq_res) { + pr_alert("[Mali]No IRQ resource at index %d\n", i); + err = -ENOENT; + goto out_free_dev; + } + +#ifdef CONFIG_OF + if (!strcmp(irq_res->name, "JOB")) { + irqtag = JOB_IRQ_TAG; + } else if (!strcmp(irq_res->name, "MMU")) { + irqtag = MMU_IRQ_TAG; + } else if (!strcmp(irq_res->name, "GPU")) { + irqtag = GPU_IRQ_TAG; + } else { + pr_alert("Invalid irq res name: '%s'\n", + irq_res->name); + err = -EINVAL; + goto out_free_dev; + } +#else + irqtag = i; +#endif /* CONFIG_OF */ + kbdev->irqs[irqtag].irq = irq_res->start; + kbdev->irqs[irqtag].flags = (irq_res->flags & IRQF_TRIGGER_MASK); + } + + /* the first memory resource is the physical address of the GPU registers */ + reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!reg_res) { + pr_alert("[Mali]Invalid register resource\n"); + err = -ENOENT; + goto out_free_dev; + } + + kbdev->reg_start = reg_res->start; + kbdev->reg_size = resource_size(reg_res); + + err = kbase_common_reg_map(kbdev); + if (err) + goto out_free_dev; + + err = mtk_mfg_reg_map(kbdev); + if (err) + goto out_free_dev; +#ifdef CONFIG_HAVE_CLK // MTK + kbdev->clock = clk_get(kbdev->dev, "clk_mali"); + if (IS_ERR_OR_NULL(kbdev->clock)) { + pr_alert("[Mali]Continuing without Mali clock control\n"); + kbdev->clock = NULL; + /* Allow probe to continue without clock. */ + } else { + err = clk_prepare_enable(kbdev->clock); + if (err) { + pr_alert("[Mali]Failed to prepare and enable clock (%d)\n", err); + goto out_clock_get; + } + } +#endif /* CONFIG_HAVE_CLK */ + +#ifdef CONFIG_DEBUG_FS + kbdev->mali_debugfs_directory = debugfs_create_dir("mali", NULL); + if (NULL == kbdev->mali_debugfs_directory) { + pr_alert("[Mali]Couldn't create mali debugfs directory\n"); + goto out_clock_enable; + } + kbdev->memory_profile_directory = debugfs_create_dir("mem", + kbdev->mali_debugfs_directory); + if (NULL == kbdev->memory_profile_directory) { + pr_alert("[Mali]Couldn't create mali mem debugfs directory\n"); + goto out_mali_debugfs_remove; + } + if (kbasep_jd_debugfs_init(kbdev)) { + pr_alert("[Mali]Couldn't create mali jd debugfs entries\n"); + goto out_mem_profile_remove; + } +#endif /* CONFIG_DEBUG_FS */ + +//#if 0 +#if defined(CONFIG_MTK_CLKMGR) +#else + kbdev->clk_mfg = devm_clk_get(&pdev->dev, "mfg-main"); + if (IS_ERR(kbdev->clk_mfg)) { + pr_alert("cannot get mfg main clock\n"); + return PTR_ERR(kbdev->clk_mfg); + } + kbdev->clk_smi_common = devm_clk_get(&pdev->dev, "mfg-smi-common"); + if (IS_ERR(kbdev->clk_smi_common)) { + pr_alert("cannot get smi common clock\n"); + return PTR_ERR(kbdev->clk_smi_common); + } + kbdev->clk_mfg_scp = devm_clk_get(&pdev->dev, "mtcmos-mfg"); + if (IS_ERR(kbdev->clk_mfg_scp)) { + pr_alert("cannot get mtcmos mfg\n"); + return PTR_ERR(kbdev->clk_mfg_scp); + } + kbdev->clk_display_scp = devm_clk_get(&pdev->dev, "mtcmos-display"); + if (IS_ERR(kbdev->clk_display_scp)) { + pr_alert("cannot get mtcmos display\n"); + return PTR_ERR(kbdev->clk_display_scp); + } +#endif + +//#endif + + + if (MALI_ERROR_NONE != kbase_device_init(kbdev)) { + pr_alert("Can't initialize device\n"); + + err = -ENOMEM; + goto out_debugfs_remove; + } + + /* obtain min/max configured gpu frequencies */ + core_props = &(kbdev->gpu_props.props.core_props); + core_props->gpu_freq_khz_min = GPU_FREQ_KHZ_MIN; + core_props->gpu_freq_khz_max = GPU_FREQ_KHZ_MAX; + kbdev->gpu_props.irq_throttle_time_us = DEFAULT_IRQ_THROTTLE_TIME_US; + + err = kbase_common_device_init(kbdev); + if (err) { + pr_alert("[Mali]Failed kbase_common_device_init\n"); + goto out_term_dev; + } + + pr_alert("[MALI]Using mali midgard r5p0-EAC DDK kernel device driver. GPU probe() end. [%s][l:%d] \n", __func__, __LINE__); + + gpsMaliData = kbdev; + return 0; + +out_term_dev: + kbase_device_term(kbdev); +out_debugfs_remove: +#ifdef CONFIG_DEBUG_FS + kbasep_jd_debugfs_term(kbdev); +out_mem_profile_remove: + debugfs_remove(kbdev->memory_profile_directory); +out_mali_debugfs_remove: + debugfs_remove(kbdev->mali_debugfs_directory); +out_clock_enable: +#endif /* CONFIG_DEBUG_FS */ +#ifdef CONFIG_HAVE_CLK + clk_disable_unprepare(kbdev->clock); +out_clock_get: + clk_put(kbdev->clock); + kbase_common_reg_unmap(kbdev); +#endif /* CONFIG_HAVE_CLK */ +out_free_dev: +#ifdef CONFIG_MALI_NO_MALI + midg_device_destroy(kbdev); +out_midg: +#endif /* CONFIG_MALI_NO_MALI */ + kbase_device_free(kbdev); +out: + gpsMaliData = NULL; + if(probe_count++ <3){ + pr_alert("[Mali]Failed probe_count to re-try\n"); + goto probe_begin; + } + pr_alert("[Mali]Failed probe inite to re-try three , probe_count = %d !!\n",probe_count); + BUG_ON(probe_count>=3); + return err; +} + +static int kbase_common_device_remove(struct kbase_device *kbdev) +{ + mtk_get_gpu_memory_usage_fp = NULL; + +#ifdef CONFIG_MALI_DEVFREQ + kbase_devfreq_term(kbdev); +#endif + + if (kbdev->pm.callback_power_runtime_term) + kbdev->pm.callback_power_runtime_term(kbdev); +#if KBASE_PM_EN + /* Remove the sys power policy file */ + device_remove_file(kbdev->dev, &dev_attr_power_policy); + device_remove_file(kbdev->dev, &dev_attr_core_availability_policy); + device_remove_file(kbdev->dev, &dev_attr_core_mask); +#endif +#ifdef CONFIG_MALI_TRACE_TIMELINE + kbasep_trace_timeline_debugfs_term(kbdev); +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +#ifdef CONFIG_MALI_DEBUG + device_remove_file(kbdev->dev, &dev_attr_js_softstop_always); + device_remove_file(kbdev->dev, &dev_attr_debug_command); +#endif /* CONFIG_MALI_DEBUG */ +#if !MALI_CUSTOMER_RELEASE + device_remove_file(kbdev->dev, &dev_attr_js_timeouts); + device_remove_file(kbdev->dev, &dev_attr_force_replay); +#endif /* !MALI_CUSTOMER_RELEASE */ +#ifdef CONFIG_DEBUG_FS + kbasep_gpu_memory_debugfs_term(kbdev); +#endif + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + device_remove_file(kbdev->dev, &dev_attr_sc_split); +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ + + kbasep_js_devdata_halt(kbdev); + kbase_job_slot_halt(kbdev); + kbase_mem_halt(kbdev); + kbase_pm_halt(kbdev); + + kbase_release_interrupts(kbdev); + + kbasep_js_devdata_term(kbdev); + kbase_job_slot_term(kbdev); + kbase_mem_term(kbdev); + kbase_pm_term(kbdev); + + down(&kbase_dev_list_lock); + list_del(&kbdev->entry); + up(&kbase_dev_list_lock); + + misc_deregister(&kbdev->mdev); + put_device(kbdev->dev); + kbase_common_reg_unmap(kbdev); + kbase_device_term(kbdev); +#ifdef CONFIG_DEBUG_FS + kbasep_jd_debugfs_term(kbdev); + debugfs_remove(kbdev->memory_profile_directory); + debugfs_remove(kbdev->mali_debugfs_directory); +#endif /* CONFIG_DEBUG_FS */ +#ifdef CONFIG_HAVE_CLK // MTK + if (kbdev->clock) { + clk_disable_unprepare(kbdev->clock); + clk_put(kbdev->clock); + kbdev->clock = NULL; + } +#endif /* CONFIG_HAVE_CLK */ +#ifdef CONFIG_MALI_NO_MALI + midg_device_destroy(kbdev); +#endif /* CONFIG_MALI_NO_MALI */ + kbase_device_free(kbdev); + + return 0; +} + +static int kbase_platform_device_remove(struct platform_device *pdev) +{ + struct kbase_device *kbdev = to_kbase_device(&pdev->dev); + + if (!kbdev) + return -ENODEV; + + return kbase_common_device_remove(kbdev); +} + +/** Suspend callback from the OS. + * + * This is called by Linux when the device should suspend. + * + * @param dev The device to suspend + * + * @return A standard Linux error code + */ +static int kbase_device_suspend(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + +#if defined(CONFIG_PM_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + devfreq_suspend_device(kbdev->devfreq); +#endif + + kbase_pm_suspend(kbdev); + return 0; +} + +/** Resume callback from the OS. + * + * This is called by Linux when the device should resume from suspension. + * + * @param dev The device to resume + * + * @return A standard Linux error code + */ +static int kbase_device_resume(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + kbase_pm_resume(kbdev); + +#if defined(CONFIG_PM_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + devfreq_resume_device(kbdev->devfreq); +#endif + return 0; +} + +/** Runtime suspend callback from the OS. + * + * This is called by Linux when the device should prepare for a condition in which it will + * not be able to communicate with the CPU(s) and RAM due to power management. + * + * @param dev The device to suspend + * + * @return A standard Linux error code + */ +#ifdef CONFIG_PM_RUNTIME +static int kbase_device_runtime_suspend(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + +#if defined(CONFIG_PM_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + devfreq_suspend_device(kbdev->devfreq); +#endif + + if (kbdev->pm.callback_power_runtime_off) { + kbdev->pm.callback_power_runtime_off(kbdev); + dev_dbg(dev, "runtime suspend\n"); + } + return 0; +} +#endif /* CONFIG_PM_RUNTIME */ + +/** Runtime resume callback from the OS. + * + * This is called by Linux when the device should go into a fully active state. + * + * @param dev The device to suspend + * + * @return A standard Linux error code + */ + +#ifdef CONFIG_PM_RUNTIME +int kbase_device_runtime_resume(struct device *dev) +{ + int ret = 0; + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + if (kbdev->pm.callback_power_runtime_on) { + ret = kbdev->pm.callback_power_runtime_on(kbdev); + dev_dbg(dev, "runtime resume\n"); + } + +#if defined(CONFIG_PM_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + devfreq_resume_device(kbdev->devfreq); +#endif + + return ret; +} +#endif /* CONFIG_PM_RUNTIME */ + +/** Runtime idle callback from the OS. + * + * This is called by Linux when the device appears to be inactive and it might be + * placed into a low power state + * + * @param dev The device to suspend + * + * @return A standard Linux error code + */ + +#ifdef CONFIG_PM_RUNTIME +static int kbase_device_runtime_idle(struct device *dev) +{ + /* Avoid pm_runtime_suspend being called */ + return 1; +} +#endif /* CONFIG_PM_RUNTIME */ + +/** The power management operations for the platform driver. + */ +static const struct dev_pm_ops kbase_pm_ops = { + .suspend = kbase_device_suspend, + .resume = kbase_device_resume, +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = kbase_device_runtime_suspend, + .runtime_resume = kbase_device_runtime_resume, + .runtime_idle = kbase_device_runtime_idle, +#endif /* CONFIG_PM_RUNTIME */ +}; + +#ifdef CONFIG_OF +static const struct of_device_id kbase_dt_ids[] = { + { .compatible = "arm,malit6xx" }, + { .compatible = "arm,mali-midgard" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, kbase_dt_ids); +#endif + +static struct platform_driver kbase_platform_driver = { + .probe = kbase_platform_device_probe, + .remove = kbase_platform_device_remove, + .driver = { + .name = kbase_drv_name, + .owner = THIS_MODULE, + .pm = &kbase_pm_ops, + .of_match_table = of_match_ptr(kbase_dt_ids), + }, +}; + +/* + * The driver will not provide a shortcut to create the Mali platform device + * anymore when using Device Tree. + */ +#ifdef CONFIG_OF +module_platform_driver(kbase_platform_driver); +#else /* CONFIG_MALI_PLATFORM_FAKE */ + +extern int kbase_platform_early_init(void); + +#ifdef CONFIG_MALI_PLATFORM_FAKE +extern int kbase_platform_fake_register(void); +extern void kbase_platform_fake_unregister(void); +#endif + +static int __init kbase_driver_init(void) +{ + int ret; + + ret = kbase_platform_early_init(); + if (ret) + return ret; + +#ifdef CONFIG_MALI_PLATFORM_FAKE + ret = kbase_platform_fake_register(); + if (ret) + return ret; +#endif + ret = platform_driver_register(&kbase_platform_driver); +#ifdef CONFIG_MALI_PLATFORM_FAKE + if (ret) + kbase_platform_fake_unregister(); +#endif + + return ret; +} + +static void __exit kbase_driver_exit(void) +{ + platform_driver_unregister(&kbase_platform_driver); +#ifdef CONFIG_MALI_PLATFORM_FAKE + kbase_platform_fake_unregister(); +#endif +} + +module_init(kbase_driver_init); +module_exit(kbase_driver_exit); + +#endif /* CONFIG_OF */ + +MODULE_LICENSE("GPL"); +MODULE_VERSION(MALI_RELEASE_NAME); + +#if defined(CONFIG_MALI_GATOR_SUPPORT) || defined(CONFIG_MALI_SYSTEM_TRACE) +#define CREATE_TRACE_POINTS +#endif + +#ifdef CONFIG_MALI_GATOR_SUPPORT +/* Create the trace points (otherwise we just get code to call a tracepoint) */ +#include "mali_linux_trace.h" + +#define MET_USER_EVENT_SUPPORT +#include + +void kbase_trace_mali_pm_status(u32 event, u64 value) +{ + switch (event) { + case KBASE_PM_CORE_SHADER: + met_tag_oneshot(0, "MALI_SHADER_STATUS", (unsigned int)value); + break; + case KBASE_PM_CORE_TILER: + met_tag_oneshot(0, "MALI_TILER_STATUS", (unsigned int)value); + break; + case KBASE_PM_CORE_L2: + met_tag_oneshot(0, "MALI_L2_STATUS", (unsigned int)value); + break; + } + trace_mali_pm_status(event, value); +} + +void kbase_trace_mali_pm_power_off(u32 event, u64 value) +{ + switch (event) { + case KBASE_PM_CORE_SHADER: + met_tag_oneshot(0, "MALI_SHADER_OFF", (unsigned int)value); + break; + case KBASE_PM_CORE_TILER: + met_tag_oneshot(0, "MALI_TILER_OFF", (unsigned int)value); + break; + case KBASE_PM_CORE_L2: + met_tag_oneshot(0, "MALI_L2_OFF", (unsigned int)value); + break; + } + trace_mali_pm_power_off(event, value); +} + +void kbase_trace_mali_pm_power_on(u32 event, u64 value) +{ + switch (event) { + case KBASE_PM_CORE_SHADER: + met_tag_oneshot(0, "MALI_SHADER_ON", (unsigned int)value); + break; + case KBASE_PM_CORE_TILER: + met_tag_oneshot(0, "MALI_TILER_ON", (unsigned int)value); + break; + case KBASE_PM_CORE_L2: + met_tag_oneshot(0, "MALI_L2_ON", (unsigned int)value); + break; + } + trace_mali_pm_power_on(event, value); +} + +void kbase_trace_mali_job_slots_event(u32 event, const struct kbase_context *kctx, u8 atom_id) +{ + trace_mali_job_slots_event(event, (kctx != NULL ? kctx->tgid : 0), (kctx != NULL ? kctx->pid : 0), atom_id, \ + (kctx != NULL ? kctx->jctx.atoms[atom_id].work_id : 0)); +} + +void kbase_trace_mali_page_fault_insert_pages(int event, u32 value) +{ + trace_mali_page_fault_insert_pages(event, value); +} + +void kbase_trace_mali_mmu_as_in_use(int event) +{ + trace_mali_mmu_as_in_use(event); +} + +void kbase_trace_mali_mmu_as_released(int event) +{ + trace_mali_mmu_as_released(event); +} + +void kbase_trace_mali_total_alloc_pages_change(long long int event) +{ + trace_mali_total_alloc_pages_change(event); +} +#endif /* CONFIG_MALI_GATOR_SUPPORT */ +#ifdef CONFIG_MALI_SYSTEM_TRACE +#include "mali_linux_kbase_trace.h" +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.c new file mode 100644 index 0000000000000000000000000000000000000000..a1ef0109d2b4a94396eb91a834d91c5d01a799f9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.c @@ -0,0 +1,124 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_cpuprops.c + * Base kernel property query APIs + */ + +#include "mali_kbase.h" +#ifdef BASE_LEGACY_UK7_SUPPORT + +#include "mali_kbase_cpuprops.h" +#include "mali_kbase_uku.h" +#include +#include +#include +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +#include +#endif + +#define KBASE_DEFAULT_CPU_NUM 0 + +#define L1_DCACHE_LINE_SIZE_LOG2 L1_CACHE_SHIFT + +/** + * @brief Macros used to extract cpu id info + * @see Doc's for Main ID register + */ +#define KBASE_CPUPROPS_ID_GET_REV(cpuid) ((cpuid) & 0x0F) /* [3:0] Revision */ +#define KBASE_CPUPROPS_ID_GET_PART_NR(cpuid)(((cpuid) >> 4) & 0xFFF) /* [15:4] Part number */ +#define KBASE_CPUPROPS_ID_GET_ARCH(cpuid) (((cpuid) >> 16) & 0x0F) /* [19:16] Architecture */ +#define KBASE_CPUPROPS_ID_GET_VARIANT(cpuid)(((cpuid) >> 20) & 0x0F) /* [23:20] Variant */ +#define KBASE_CPUPROPS_ID_GET_CODE(cpuid) (((cpuid) >> 24) & 0xFF) /* [31:23] ASCII code of implementer trademark */ + +/*Below value sourced from OSK*/ +#define L1_DCACHE_SIZE ((u32)0x00008000) + +/** + * @brief Retrieves detailed CPU info from given cpu_val ( ID reg ) + * + * @param kbase_props CPU props to be filled-in with cpu id info + * + */ +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +static void kbasep_cpuprops_uk_get_cpu_id_info(struct kbase_uk_cpuprops * const kbase_props) +{ + kbase_props->props.cpu_id.id = read_cpuid_id(); + + kbase_props->props.cpu_id.valid = 1; + kbase_props->props.cpu_id.rev = KBASE_CPUPROPS_ID_GET_REV(kbase_props->props.cpu_id.id); + kbase_props->props.cpu_id.part = KBASE_CPUPROPS_ID_GET_PART_NR(kbase_props->props.cpu_id.id); + kbase_props->props.cpu_id.arch = KBASE_CPUPROPS_ID_GET_ARCH(kbase_props->props.cpu_id.id); + kbase_props->props.cpu_id.variant = KBASE_CPUPROPS_ID_GET_VARIANT(kbase_props->props.cpu_id.id); + kbase_props->props.cpu_id.implementer = KBASE_CPUPROPS_ID_GET_CODE(kbase_props->props.cpu_id.id); +} +#else +static void kbasep_cpuprops_uk_get_cpu_id_info(struct kbase_uk_cpuprops * const kbase_props) +{ + kbase_props->props.cpu_id.id = 0; + kbase_props->props.cpu_id.valid = 0; + kbase_props->props.cpu_id.rev = 0; + kbase_props->props.cpu_id.part = 0; + kbase_props->props.cpu_id.arch = 0; + kbase_props->props.cpu_id.variant = 0; + kbase_props->props.cpu_id.implementer = 'N'; +} +#endif + +/** + * This function (and file!) is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ + +mali_error kbase_cpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_cpuprops * const kbase_props) +{ + unsigned int max_cpu_freq; + + kbase_props->props.cpu_l1_dcache_line_size_log2 = L1_DCACHE_LINE_SIZE_LOG2; + kbase_props->props.cpu_l1_dcache_size = L1_DCACHE_SIZE; + kbase_props->props.cpu_flags = BASE_CPU_PROPERTY_FLAG_LITTLE_ENDIAN; + + kbase_props->props.nr_cores = NR_CPUS; + kbase_props->props.cpu_page_size_log2 = PAGE_SHIFT; + kbase_props->props.available_memory_size = totalram_pages << PAGE_SHIFT; + + kbasep_cpuprops_uk_get_cpu_id_info(kbase_props); + + /* check if kernel supports dynamic frequency scaling */ + max_cpu_freq = cpufreq_quick_get_max(KBASE_DEFAULT_CPU_NUM); + if (max_cpu_freq != 0) { + /* convert from kHz to mHz */ + kbase_props->props.max_cpu_clock_speed_mhz = max_cpu_freq / 1000; + } else { + /* fallback if CONFIG_CPU_FREQ turned off */ + int result; + kbase_cpuprops_clock_speed_function kbase_cpuprops_uk_get_clock_speed; + + kbase_cpuprops_uk_get_clock_speed = (kbase_cpuprops_clock_speed_function) kbasep_get_config_value(kctx->kbdev, kctx->kbdev->config_attributes, KBASE_CONFIG_ATTR_CPU_SPEED_FUNC); + result = kbase_cpuprops_uk_get_clock_speed(&kbase_props->props.max_cpu_clock_speed_mhz); + if (result != 0) + return MALI_ERROR_FUNCTION_FAILED; + } + + return MALI_ERROR_NONE; +} + +#endif /* BASE_LEGACY_UK7_SUPPORT */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.h new file mode 100644 index 0000000000000000000000000000000000000000..b107f4ac5a292d831122d48d175d9e40c541075f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.h @@ -0,0 +1,55 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase.h" +#ifdef BASE_LEGACY_UK7_SUPPORT + +/** + * @file mali_kbase_cpuprops.h + * Base kernel property query APIs + */ + +#ifndef _KBASE_CPUPROPS_H_ +#define _KBASE_CPUPROPS_H_ + +#include + +/* Forward declarations */ +struct kbase_uk_cpuprops; + +/** + * This file is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ + +/** + * @brief Provides CPU properties data. + * + * Fill the struct kbase_uk_cpuprops with values from CPU configuration. + * + * @param kctx The kbase context + * @param kbase_props A copy of the struct kbase_uk_cpuprops structure from userspace + * + * @return MALI_ERROR_NONE on success. Any other value indicates failure. + */ +mali_error kbase_cpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_cpuprops * const kbase_props); + +#endif /*_KBASE_CPUPROPS_H_*/ +#endif /* BASE_LEGACY_UK7_SUPPORT */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..ce571c9970be08f235122a714eae82379785fa63 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.c @@ -0,0 +1,39 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +static struct kbasep_debug_assert_cb kbasep_debug_assert_registered_cb = { + NULL, + NULL +}; + +void kbase_debug_assert_register_hook(kbase_debug_assert_hook *func, void *param) +{ + kbasep_debug_assert_registered_cb.func = func; + kbasep_debug_assert_registered_cb.param = param; +} + +void kbasep_debug_assert_call_hook(void) +{ + if (kbasep_debug_assert_registered_cb.func != NULL) + kbasep_debug_assert_registered_cb.func(kbasep_debug_assert_registered_cb.param); +} +KBASE_EXPORT_SYMBOL(kbasep_debug_assert_call_hook); + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..e4ced8c76145507fdae6ec633a136cd9e02e79c9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.h @@ -0,0 +1,164 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_DEBUG_H +#define _KBASE_DEBUG_H + +#include + +/** @brief If equals to 0, a trace containing the file, line, and function will be displayed before each message. */ +#define KBASE_DEBUG_SKIP_TRACE 0 + +/** @brief If different from 0, the trace will only contain the file and line. */ +#define KBASE_DEBUG_SKIP_FUNCTION_NAME 0 + +/** @brief Disable the asserts tests if set to 1. Default is to disable the asserts in release. */ +#ifndef KBASE_DEBUG_DISABLE_ASSERTS +#ifdef CONFIG_MALI_DEBUG +#define KBASE_DEBUG_DISABLE_ASSERTS 0 +#else +#define KBASE_DEBUG_DISABLE_ASSERTS 1 +#endif +#endif /* KBASE_DEBUG_DISABLE_ASSERTS */ + +/** Function type that is called on an KBASE_DEBUG_ASSERT() or KBASE_DEBUG_ASSERT_MSG() */ +typedef void (kbase_debug_assert_hook) (void *); + +typedef struct kbasep_debug_assert_cb { + kbase_debug_assert_hook *func; + void *param; +} kbasep_debug_assert_cb; + +/** + * @def KBASEP_DEBUG_PRINT_TRACE + * @brief Private macro containing the format of the trace to display before every message + * @sa KBASE_DEBUG_SKIP_TRACE, KBASE_DEBUG_SKIP_FUNCTION_NAME + */ +#if !KBASE_DEBUG_SKIP_TRACE +#define KBASEP_DEBUG_PRINT_TRACE \ + "In file: " __FILE__ " line: " CSTD_STR2(__LINE__) +#if !KBASE_DEBUG_SKIP_FUNCTION_NAME +#define KBASEP_DEBUG_PRINT_FUNCTION CSTD_FUNC +#else +#define KBASEP_DEBUG_PRINT_FUNCTION "" +#endif +#else +#define KBASEP_DEBUG_PRINT_TRACE "" +#endif + +/** + * @def KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) + * @brief (Private) system printing function associated to the @see KBASE_DEBUG_ASSERT_MSG event. + * @param trace location in the code from where the message is printed + * @param function function from where the message is printed + * @param ... Format string followed by format arguments. + * @note function parameter cannot be concatenated with other strings + */ +/* Select the correct system output function*/ +#ifdef CONFIG_MALI_DEBUG +#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...)\ + do { \ + pr_err("Mali: %s function:%s ", trace, function);\ + pr_err(__VA_ARGS__);\ + pr_err("\n");\ + } while (MALI_FALSE) +#else +#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) CSTD_NOP() +#endif + +#ifdef CONFIG_MALI_DEBUG +#define KBASE_CALL_ASSERT_HOOK() kbasep_debug_assert_call_hook(); +#else +#define KBASE_CALL_ASSERT_HOOK() CSTD_NOP(); +#endif + +/** + * @def KBASE_DEBUG_ASSERT(expr) + * @brief Calls @see KBASE_PRINT_ASSERT and prints the expression @a expr if @a expr is false + * + * @note This macro does nothing if the flag @see KBASE_DEBUG_DISABLE_ASSERTS is set to 1 + * + * @param expr Boolean expression + */ +#define KBASE_DEBUG_ASSERT(expr) \ + KBASE_DEBUG_ASSERT_MSG(expr, #expr) + +#if KBASE_DEBUG_DISABLE_ASSERTS +#define KBASE_DEBUG_ASSERT_MSG(expr, ...) CSTD_NOP() +#else + /** + * @def KBASE_DEBUG_ASSERT_MSG(expr, ...) + * @brief Calls @see KBASEP_DEBUG_ASSERT_OUT and prints the given message if @a expr is false + * + * @note This macro does nothing if the flag @see KBASE_DEBUG_DISABLE_ASSERTS is set to 1 + * + * @param expr Boolean expression + * @param ... Message to display when @a expr is false, as a format string followed by format arguments. + */ +#define KBASE_DEBUG_ASSERT_MSG(expr, ...) \ + do { \ + if (!(expr)) { \ + KBASEP_DEBUG_ASSERT_OUT(KBASEP_DEBUG_PRINT_TRACE, KBASEP_DEBUG_PRINT_FUNCTION, __VA_ARGS__);\ + KBASE_CALL_ASSERT_HOOK();\ + BUG();\ + } \ + } while (MALI_FALSE) +#endif /* KBASE_DEBUG_DISABLE_ASSERTS */ + +/** + * @def KBASE_DEBUG_CODE( X ) + * @brief Executes the code inside the macro only in debug mode + * + * @param X Code to compile only in debug mode. + */ +#ifdef CONFIG_MALI_DEBUG +#define KBASE_DEBUG_CODE(X) X +#else +#define KBASE_DEBUG_CODE(X) CSTD_NOP() +#endif /* CONFIG_MALI_DEBUG */ + +/** @} */ + +/** + * @brief Register a function to call on ASSERT + * + * Such functions will \b only be called during Debug mode, and for debugging + * features \b only. Do not rely on them to be called in general use. + * + * To disable the hook, supply NULL to \a func. + * + * @note This function is not thread-safe, and should only be used to + * register/deregister once in the module's lifetime. + * + * @param[in] func the function to call when an assert is triggered. + * @param[in] param the parameter to pass to \a func when calling it + */ +void kbase_debug_assert_register_hook(kbase_debug_assert_hook *func, void *param); + +/** + * @brief Call a debug assert hook previously registered with kbase_debug_assert_register_hook() + * + * @note This function is not thread-safe with respect to multiple threads + * registering functions and parameters with + * kbase_debug_assert_register_hook(). Otherwise, thread safety is the + * responsibility of the registered hook. + */ +void kbasep_debug_assert_call_hook(void); + +#endif /* _KBASE_DEBUG_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_defs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..c53c264fb3d500c98839533a1a033735f225eec3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_defs.h @@ -0,0 +1,982 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_defs.h + * + * Defintions (types, defines, etcs) common to Kbase. They are placed here to + * allow the hierarchy of header files to work. + */ + +#ifndef _KBASE_DEFS_H_ +#define _KBASE_DEFS_H_ + +#include +#include +#include +#include +#include + + +#include +#include +#include + +#ifdef CONFIG_KDS +#include +#endif /* CONFIG_KDS */ + +#ifdef CONFIG_SYNC +#include "sync.h" +#endif /* CONFIG_SYNC */ + +#ifdef CONFIG_DEBUG_FS +#include +#endif /* CONFIG_DEBUG_FS */ + +#ifdef CONFIG_PM_DEVFREQ +#include +#endif /* CONFIG_DEVFREQ */ + +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + +/** Enable SW tracing when set */ +#ifdef CONFIG_MALI_MIDGARD_ENABLE_TRACE +#define KBASE_TRACE_ENABLE 1 +#endif + +#ifndef KBASE_TRACE_ENABLE +#ifdef CONFIG_MALI_DEBUG +#define KBASE_TRACE_ENABLE 1 +#else +#define KBASE_TRACE_ENABLE 0 +#endif /* CONFIG_MALI_DEBUG */ +#endif /* KBASE_TRACE_ENABLE */ + +/** Dump Job slot trace on error (only active if KBASE_TRACE_ENABLE != 0) */ +#define KBASE_TRACE_DUMP_ON_JOB_SLOT_ERROR 1 + +/** + * Number of milliseconds before resetting the GPU when a job cannot be "zapped" from the hardware. + * Note that the time is actually ZAP_TIMEOUT+SOFT_STOP_RESET_TIMEOUT between the context zap starting and the GPU + * actually being reset to give other contexts time for their jobs to be soft-stopped and removed from the hardware + * before resetting. + */ +#define ZAP_TIMEOUT 1000 + +/** Number of milliseconds before we time out on a GPU soft/hard reset */ +#define RESET_TIMEOUT 500 + +/** + * Prevent soft-stops from occuring in scheduling situations + * + * This is not due to HW issues, but when scheduling is desired to be more predictable. + * + * Therefore, soft stop may still be disabled due to HW issues. + * + * @note Soft stop will still be used for non-scheduling purposes e.g. when terminating a context. + * + * @note if not in use, define this value to 0 instead of \#undef'ing it + */ +#define KBASE_DISABLE_SCHEDULING_SOFT_STOPS 0 +/** + * Prevent hard-stops from occuring in scheduling situations + * + * This is not due to HW issues, but when scheduling is desired to be more predictable. + * + * @note Hard stop will still be used for non-scheduling purposes e.g. when terminating a context. + * + * @note if not in use, define this value to 0 instead of \#undef'ing it + */ +#define KBASE_DISABLE_SCHEDULING_HARD_STOPS 0 + +/** + * The maximum number of Job Slots to support in the Hardware. + * + * You can optimize this down if your target devices will only ever support a + * small number of job slots. + */ +#define BASE_JM_MAX_NR_SLOTS 16 + +/** + * The maximum number of Address Spaces to support in the Hardware. + * + * You can optimize this down if your target devices will only ever support a + * small number of Address Spaces + */ +#define BASE_MAX_NR_AS 16 + +/* mmu */ +#define ENTRY_IS_ATE 1ULL +#define ENTRY_IS_INVAL 2ULL +#define ENTRY_IS_PTE 3ULL + +#define MIDGARD_MMU_VA_BITS 48 + +#define ENTRY_ATTR_BITS (7ULL << 2) /* bits 4:2 */ +#define ENTRY_RD_BIT (1ULL << 6) +#define ENTRY_WR_BIT (1ULL << 7) +#define ENTRY_SHARE_BITS (3ULL << 8) /* bits 9:8 */ +#define ENTRY_ACCESS_BIT (1ULL << 10) +#define ENTRY_NX_BIT (1ULL << 54) + +#define ENTRY_FLAGS_MASK (ENTRY_ATTR_BITS | ENTRY_RD_BIT | ENTRY_WR_BIT | ENTRY_SHARE_BITS | ENTRY_ACCESS_BIT | ENTRY_NX_BIT) + +#if MIDGARD_MMU_VA_BITS > 39 +#define MIDGARD_MMU_TOPLEVEL 0 +#else +#define MIDGARD_MMU_TOPLEVEL 1 +#endif + +#define GROWABLE_FLAGS_REQUIRED (KBASE_REG_PF_GROW) + +/** setting in kbase_context::as_nr that indicates it's invalid */ +#define KBASEP_AS_NR_INVALID (-1) + +#define KBASE_LOCK_REGION_MAX_SIZE (63) +#define KBASE_LOCK_REGION_MIN_SIZE (11) + +#define KBASE_TRACE_SIZE_LOG2 8 /* 256 entries */ +#define KBASE_TRACE_SIZE (1 << KBASE_TRACE_SIZE_LOG2) +#define KBASE_TRACE_MASK ((1 << KBASE_TRACE_SIZE_LOG2)-1) + +#include "mali_kbase_js_defs.h" + +#define KBASEP_FORCE_REPLAY_DISABLED 0 + +/* Maximum force replay limit when randomization is enabled */ +#define KBASEP_FORCE_REPLAY_RANDOM_LIMIT 16 + +/** Atom has been previously soft-stoppped */ +#define KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED (1<<1) +/** Atom has been previously retried to execute */ +#define KBASE_KATOM_FLAGS_RERUN (1<<2) +#define KBASE_KATOM_FLAGS_JOBCHAIN (1<<3) +/** Atom has been previously hard-stopped. */ +#define KBASE_KATOM_FLAG_BEEN_HARD_STOPPED (1<<4) +/** Atom has caused us to enter disjoint state */ +#define KBASE_KATOM_FLAG_IN_DISJOINT (1<<5) + +/* SW related flags about types of JS_COMMAND action + * NOTE: These must be masked off by JS_COMMAND_MASK */ + +/** This command causes a disjoint event */ +#define JS_COMMAND_SW_CAUSES_DISJOINT 0x100 + +/** Bitmask of all SW related flags */ +#define JS_COMMAND_SW_BITS (JS_COMMAND_SW_CAUSES_DISJOINT) + +#if (JS_COMMAND_SW_BITS & JS_COMMAND_MASK) +#error JS_COMMAND_SW_BITS not masked off by JS_COMMAND_MASK. Must update JS_COMMAND_SW_<..> bitmasks +#endif + +/** Soft-stop command that causes a Disjoint event. This of course isn't + * entirely masked off by JS_COMMAND_MASK */ +#define JS_COMMAND_SOFT_STOP_WITH_SW_DISJOINT \ + (JS_COMMAND_SW_CAUSES_DISJOINT | JS_COMMAND_SOFT_STOP) + + +struct kbase_jd_atom_dependency +{ + struct kbase_jd_atom *atom; + u8 dep_type; +}; + +/** + * @brief The function retrieves a read-only reference to the atom field from + * the kbase_jd_atom_dependency structure + * + * @param[in] dep kbase jd atom dependency. + * + * @return readonly reference to dependent ATOM. + */ +static INLINE const struct kbase_jd_atom* const kbase_jd_katom_dep_atom(const struct kbase_jd_atom_dependency* dep) +{ + LOCAL_ASSERT(dep != NULL); + + return (const struct kbase_jd_atom* const )(dep->atom); +} + +/** + * @brief The function retrieves a read-only reference to the dependency type field from + * the kbase_jd_atom_dependency structure + * + * @param[in] dep kbase jd atom dependency. + * + * @return A dependency type value. + */ +static INLINE const u8 kbase_jd_katom_dep_type(const struct kbase_jd_atom_dependency* dep) +{ + LOCAL_ASSERT(dep != NULL); + + return dep->dep_type; +} + +/** + * @brief Setter macro for dep_atom array entry in kbase_jd_atom + * + * @param[in] dep The kbase jd atom dependency. + * @param[in] a The ATOM to be set as a dependency. + * @param type The ATOM dependency type to be set. + * + */ +static INLINE void kbase_jd_katom_dep_set(const struct kbase_jd_atom_dependency* const_dep, + struct kbase_jd_atom * a, + u8 type) +{ + struct kbase_jd_atom_dependency* dep; + + LOCAL_ASSERT(const_dep != NULL); + + dep = (REINTERPRET_CAST(struct kbase_jd_atom_dependency* )const_dep); + + dep->atom = a; + dep->dep_type = type; +} + +/** + * @brief Setter macro for dep_atom array entry in kbase_jd_atom + * + * @param[in] dep The kbase jd atom dependency to be cleared. + * + */ +static INLINE void kbase_jd_katom_dep_clear(const struct kbase_jd_atom_dependency* const_dep) +{ + struct kbase_jd_atom_dependency* dep; + + LOCAL_ASSERT(const_dep != NULL); + + dep = (REINTERPRET_CAST(struct kbase_jd_atom_dependency* )const_dep); + + dep->atom = NULL; + dep->dep_type = BASE_JD_DEP_TYPE_INVALID; +} + +struct kbase_ext_res +{ + mali_addr64 gpu_address; + struct kbase_mem_phy_alloc * alloc; +}; + +struct kbase_jd_atom { + struct work_struct work; + ktime_t start_timestamp; + u64 time_spent_us; /**< Total time spent on the GPU in microseconds */ + + struct base_jd_udata udata; + struct kbase_context *kctx; + + struct list_head dep_head[2]; + struct list_head dep_item[2]; + const struct kbase_jd_atom_dependency dep[2]; + + u16 nr_extres; + struct kbase_ext_res * extres; + + u32 device_nr; + u64 affinity; + u64 jc; + enum kbase_atom_coreref_state coreref_state; +#ifdef CONFIG_KDS + struct list_head node; + struct kds_resource_set *kds_rset; + mali_bool kds_dep_satisfied; +#endif /* CONFIG_KDS */ +#ifdef CONFIG_SYNC + struct sync_fence *fence; + struct sync_fence_waiter sync_waiter; +#endif /* CONFIG_SYNC */ + + /* Note: refer to kbasep_js_atom_retained_state, which will take a copy of some of the following members */ + enum base_jd_event_code event_code; + base_jd_core_req core_req; /**< core requirements */ + /** Job Slot to retry submitting to if submission from IRQ handler failed + * + * NOTE: see if this can be unified into the another member e.g. the event */ + int retry_submit_on_slot; + + union kbasep_js_policy_job_info sched_info; + /* atom priority scaled to nice range with +20 offset 0..39 */ + int nice_prio; + + int poking; /* BASE_HW_ISSUE_8316 */ + + wait_queue_head_t completed; + enum kbase_jd_atom_state status; +#ifdef CONFIG_GPU_TRACEPOINTS + int work_id; +#endif + /* Assigned after atom is completed. Used to check whether PRLAM-10676 workaround should be applied */ + int slot_nr; + + u32 atom_flags; + + /* Number of times this atom has been retried. Used by replay soft job. + */ + int retry_count; +}; + +/* + * Theory of operations: + * + * Atom objects are statically allocated within the context structure. + * + * Each atom is the head of two lists, one for the "left" set of dependencies, one for the "right" set. + */ + +#define KBASE_JD_DEP_QUEUE_SIZE 256 + +struct kbase_jd_context { + struct mutex lock; + struct kbasep_js_kctx_info sched_info; + struct kbase_jd_atom atoms[BASE_JD_ATOM_COUNT]; + + /** Tracks all job-dispatch jobs. This includes those not tracked by + * the scheduler: 'not ready to run' and 'dependency-only' jobs. */ + u32 job_nr; + + /** Waitq that reflects whether there are no jobs (including SW-only + * dependency jobs). This is set when no jobs are present on the ctx, + * and clear when there are jobs. + * + * @note: Job Dispatcher knows about more jobs than the Job Scheduler: + * the Job Scheduler is unaware of jobs that are blocked on dependencies, + * and SW-only dependency jobs. + * + * This waitq can be waited upon to find out when the context jobs are all + * done/cancelled (including those that might've been blocked on + * dependencies) - and so, whether it can be terminated. However, it should + * only be terminated once it is neither present in the policy-queue (see + * kbasep_js_policy_try_evict_ctx() ) nor the run-pool (see + * kbasep_js_kctx_info::ctx::is_scheduled). + * + * Since the waitq is only set under kbase_jd_context::lock, + * the waiter should also briefly obtain and drop kbase_jd_context::lock to + * guarentee that the setter has completed its work on the kbase_context + * + * This must be updated atomically with: + * - kbase_jd_context::job_nr */ + wait_queue_head_t zero_jobs_wait; + + /** Job Done workqueue. */ + struct workqueue_struct *job_done_wq; + + spinlock_t tb_lock; + u32 *tb; + size_t tb_wrap_offset; + +#ifdef CONFIG_KDS + struct kds_callback kds_cb; +#endif /* CONFIG_KDS */ +#ifdef CONFIG_GPU_TRACEPOINTS + atomic_t work_id; +#endif +}; + +struct kbase_jm_slot { + /* The number of slots must be a power of two */ +#define BASE_JM_SUBMIT_SLOTS 16 +#define BASE_JM_SUBMIT_SLOTS_MASK (BASE_JM_SUBMIT_SLOTS - 1) + + struct kbase_jd_atom *submitted[BASE_JM_SUBMIT_SLOTS]; + + struct kbase_context *last_context; + + u8 submitted_head; + u8 submitted_nr; + u8 job_chain_flag; + +}; + +struct kbase_device_info { + u32 features; +}; + +/** Poking state for BASE_HW_ISSUE_8316 */ +enum { + KBASE_AS_POKE_STATE_IN_FLIGHT = 1<<0, + KBASE_AS_POKE_STATE_KILLING_POKE = 1<<1 +}; + +/** Poking state for BASE_HW_ISSUE_8316 */ +typedef u32 kbase_as_poke_state; + +struct kbase_mmu_setup { + u64 transtab; + u64 memattr; +}; + +/** + * Important: Our code makes assumptions that a struct kbase_as structure is always at + * kbase_device->as[number]. This is used to recover the containing + * struct kbase_device from a struct kbase_as structure. + * + * Therefore, struct kbase_as structures must not be allocated anywhere else. + */ +struct kbase_as { + int number; + + struct workqueue_struct *pf_wq; + struct work_struct work_pagefault; + struct work_struct work_busfault; + enum kbase_mmu_fault_type fault_type; + u32 fault_status; + mali_addr64 fault_addr; + struct mutex transaction_mutex; + + struct kbase_mmu_setup current_setup; + + /* BASE_HW_ISSUE_8316 */ + struct workqueue_struct *poke_wq; + struct work_struct poke_work; + /** Protected by kbasep_js_device_data::runpool_irq::lock */ + int poke_refcount; + /** Protected by kbasep_js_device_data::runpool_irq::lock */ + kbase_as_poke_state poke_state; + struct hrtimer poke_timer; +}; + +static inline int kbase_as_has_bus_fault(struct kbase_as *as) +{ + return as->fault_type == KBASE_MMU_FAULT_TYPE_BUS; +} + +static inline int kbase_as_has_page_fault(struct kbase_as *as) +{ + return as->fault_type == KBASE_MMU_FAULT_TYPE_PAGE; +} + +/** + * Instrumentation State Machine States + */ +enum kbase_instr_state { + /** State where instrumentation is not active */ + KBASE_INSTR_STATE_DISABLED = 0, + /** State machine is active and ready for a command. */ + KBASE_INSTR_STATE_IDLE, + /** Hardware is currently dumping a frame. */ + KBASE_INSTR_STATE_DUMPING, + /** We've requested a clean to occur on a workqueue */ + KBASE_INSTR_STATE_REQUEST_CLEAN, + /** Hardware is currently cleaning and invalidating caches. */ + KBASE_INSTR_STATE_CLEANING, + /** Cache clean completed, and either a) a dump is complete, or + * b) instrumentation can now be setup. */ + KBASE_INSTR_STATE_CLEANED, + /** kbasep_reset_timeout_worker() has started (but not compelted) a + * reset. This generally indicates the current action should be aborted, and + * kbasep_reset_timeout_worker() will handle the cleanup */ + KBASE_INSTR_STATE_RESETTING, + /** An error has occured during DUMPING (page fault). */ + KBASE_INSTR_STATE_FAULT +}; + +void kbasep_reset_timeout_worker(struct work_struct *data); +enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *data); + +struct kbasep_mem_device { + atomic_t used_pages; /* Tracks usage of OS shared memory. Updated + when OS memory is allocated/freed. */ + +}; + + + +#define KBASE_TRACE_CODE(X) KBASE_TRACE_CODE_ ## X + +enum kbase_trace_code { + /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE + * THIS MUST BE USED AT THE START OF THE ENUM */ +#define KBASE_TRACE_CODE_MAKE_CODE(X) KBASE_TRACE_CODE(X) +#include "mali_kbase_trace_defs.h" +#undef KBASE_TRACE_CODE_MAKE_CODE + /* Comma on its own, to extend the list */ + , + /* Must be the last in the enum */ + KBASE_TRACE_CODE_COUNT +}; + +#define KBASE_TRACE_FLAG_REFCOUNT (((u8)1) << 0) +#define KBASE_TRACE_FLAG_JOBSLOT (((u8)1) << 1) + +struct kbase_trace { + struct timespec timestamp; + u32 thread_id; + u32 cpu; + void *ctx; + mali_bool katom; + int atom_number; + u64 atom_udata[2]; + u64 gpu_addr; + unsigned long info_val; + u8 code; + u8 jobslot; + u8 refcount; + u8 flags; +}; + +/** Event IDs for the power management framework. + * + * Any of these events might be missed, so they should not be relied upon to + * find the precise state of the GPU at a particular time in the + * trace. Overall, we should get a high percentage of these events for + * statisical purposes, and so a few missing should not be a problem */ +enum kbase_timeline_pm_event { + /* helper for tests */ + KBASEP_TIMELINE_PM_EVENT_FIRST, + + /** Event reserved for backwards compatibility with 'init' events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_0 = KBASEP_TIMELINE_PM_EVENT_FIRST, + + /** The power state of the device has changed. + * + * Specifically, the device has reached a desired or available state. + */ + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED, + + /** The GPU is becoming active. + * + * This event is sent when the first context is about to use the GPU. + */ + KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE, + + /** The GPU is becoming idle. + * + * This event is sent when the last context has finished using the GPU. + */ + KBASE_TIMELINE_PM_EVENT_GPU_IDLE, + + /** Event reserved for backwards compatibility with 'policy_change' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_4, + + /** Event reserved for backwards compatibility with 'system_suspend' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_5, + + /** Event reserved for backwards compatibility with 'system_resume' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_6, + + /** The job scheduler is requesting to power up/down cores. + * + * This event is sent when: + * - powered down cores are needed to complete a job + * - powered up cores are not needed anymore + */ + KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE, + + KBASEP_TIMELINE_PM_EVENT_LAST = KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE, +}; + +#ifdef CONFIG_MALI_TRACE_TIMELINE +struct kbase_trace_kctx_timeline { + atomic_t jd_atoms_in_flight; + u32 owner_tgid; +}; + +struct kbase_trace_kbdev_timeline { + /** DebugFS entry */ + struct dentry *dentry; + + /* Note: strictly speaking, not needed, because it's in sync with + * kbase_device::jm_slots[]::submitted_nr + * + * But it's kept as an example of how to add global timeline tracking + * information + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock when + * accessing this */ + u8 slot_atoms_submitted[BASE_JM_SUBMIT_SLOTS]; + + /* Last UID for each PM event */ + atomic_t pm_event_uid[KBASEP_TIMELINE_PM_EVENT_LAST+1]; + /* Counter for generating PM event UIDs */ + atomic_t pm_event_uid_counter; + /* + * L2 transition state - MALI_TRUE indicates that the transition is ongoing + * Expected to be protected by pm.power_change_lock */ + mali_bool l2_transitioning; +}; +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + + +struct kbasep_kctx_list_element { + struct list_head link; + struct kbase_context *kctx; +}; + +#define DEVNAME_SIZE 16 + +struct kbase_device { + /** jm_slots is protected by kbasep_js_device_data::runpool_irq::lock */ + struct kbase_jm_slot jm_slots[BASE_JM_MAX_NR_SLOTS]; + s8 slot_submit_count_irq[BASE_JM_MAX_NR_SLOTS]; + + struct list_head entry; + struct device *dev; + struct miscdevice mdev; + u64 reg_start; + size_t reg_size; + void __iomem *reg; + struct resource *reg_res; + struct { + int irq; + int flags; + } irqs[3]; +#ifdef CONFIG_HAVE_CLK + struct clk *clock; +#endif + void __iomem *mfg_register; + char devname[DEVNAME_SIZE]; + +#ifdef CONFIG_MALI_NO_MALI + void *model; + struct kmem_cache *irq_slab; + struct workqueue_struct *irq_workq; + atomic_t serving_job_irq; + atomic_t serving_gpu_irq; + atomic_t serving_mmu_irq; + spinlock_t reg_op_lock; +#endif /* CONFIG_MALI_NO_MALI */ + + struct kbase_pm_device_data pm; + struct kbasep_js_device_data js_data; + struct kbasep_mem_device memdev; + struct kbase_as as[BASE_MAX_NR_AS]; + + spinlock_t mmu_mask_change; + + kbase_gpu_props gpu_props; + + /** List of SW workarounds for HW issues */ + unsigned long hw_issues_mask[(BASE_HW_ISSUE_END + BITS_PER_LONG - 1) / BITS_PER_LONG]; + /** List of features available */ + unsigned long hw_features_mask[(BASE_HW_FEATURE_END + BITS_PER_LONG - 1) / BITS_PER_LONG]; + + /* Cached present bitmaps - these are the same as the corresponding hardware registers */ + u64 shader_present_bitmap; + u64 tiler_present_bitmap; + u64 l2_present_bitmap; + u64 l3_present_bitmap; + + /* Bitmaps of cores that are currently in use (running jobs). + * These should be kept up to date by the job scheduler. + * + * pm.power_change_lock should be held when accessing these members. + * + * kbase_pm_check_transitions_nolock() should be called when bits are + * cleared to update the power management system and allow transitions to + * occur. */ + u64 shader_inuse_bitmap; + + /* Refcount for cores in use */ + u32 shader_inuse_cnt[64]; + + /* Bitmaps of cores the JS needs for jobs ready to run */ + u64 shader_needed_bitmap; + + /* Refcount for cores needed */ + u32 shader_needed_cnt[64]; + + u32 tiler_inuse_cnt; + + u32 tiler_needed_cnt; + + /* struct for keeping track of the disjoint information + * + * The state is > 0 if the GPU is in a disjoint state. Otherwise 0 + * The count is the number of disjoint events that have occurred on the GPU + */ + struct { + atomic_t count; + atomic_t state; + } disjoint_event; + + /* Refcount for tracking users of the l2 cache, e.g. when using hardware counter instrumentation. */ + u32 l2_users_count; + + /* Bitmaps of cores that are currently available (powered up and the power policy is happy for jobs to be + * submitted to these cores. These are updated by the power management code. The job scheduler should avoid + * submitting new jobs to any cores that are not marked as available. + * + * pm.power_change_lock should be held when accessing these members. + */ + u64 shader_available_bitmap; + u64 tiler_available_bitmap; + u64 l2_available_bitmap; + + u64 shader_ready_bitmap; + u64 shader_transitioning_bitmap; + + s8 nr_hw_address_spaces; /**< Number of address spaces in the GPU (constant after driver initialisation) */ + s8 nr_user_address_spaces; /**< Number of address spaces available to user contexts */ + + /* Structure used for instrumentation and HW counters dumping */ + struct { + /* The lock should be used when accessing any of the following members */ + spinlock_t lock; + + struct kbase_context *kctx; + u64 addr; + wait_queue_head_t wait; + int triggered; + enum kbase_instr_state state; + wait_queue_head_t cache_clean_wait; + struct workqueue_struct *cache_clean_wq; + struct work_struct cache_clean_work; + + struct kbase_context *suspended_kctx; + struct kbase_uk_hwcnt_setup suspended_state; + } hwcnt; + + /* Set when we're about to reset the GPU */ + atomic_t reset_gpu; +#define KBASE_RESET_GPU_NOT_PENDING 0 /* The GPU reset isn't pending */ +#define KBASE_RESET_GPU_PREPARED 1 /* kbase_prepare_to_reset_gpu has been called */ +#define KBASE_RESET_GPU_COMMITTED 2 /* kbase_reset_gpu has been called - the reset will now definitely happen + * within the timeout period */ +#define KBASE_RESET_GPU_HAPPENING 3 /* The GPU reset process is currently occuring (timeout has expired or + * kbasep_try_reset_gpu_early was called) */ + + /* Work queue and work item for performing the reset in */ + struct workqueue_struct *reset_workq; + struct work_struct reset_work; + wait_queue_head_t reset_wait; + struct hrtimer reset_timer; + + /*value to be written to the irq_throttle register each time an irq is served */ + atomic_t irq_throttle_cycles; + + const struct kbase_attribute *config_attributes; + +#if KBASE_TRACE_ENABLE + spinlock_t trace_lock; + u16 trace_first_out; + u16 trace_next_in; + struct kbase_trace *trace_rbuf; +#endif + +#if !MALI_CUSTOMER_RELEASE + /* This is used to override the current job scheduler values for + * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_SS + * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_CL + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS. + * + * These values are set via the js_timeouts sysfs file. + */ + u32 js_soft_stop_ticks; + u32 js_soft_stop_ticks_cl; + u32 js_hard_stop_ticks_ss; + u32 js_hard_stop_ticks_cl; + u32 js_hard_stop_ticks_nss; + u32 js_reset_ticks_ss; + u32 js_reset_ticks_cl; + u32 js_reset_ticks_nss; +#endif + + struct mutex cacheclean_lock; + + /* Platform specific private data to be accessed by mali_kbase_config_xxx.c only */ + void *platform_context; + + /** Count of contexts keeping the GPU powered */ + atomic_t keep_gpu_powered_count; + + /* List of kbase_contexts created */ + struct list_head kctx_list; + struct mutex kctx_list_lock; + +#ifdef CONFIG_MALI_MIDGARD_RT_PM + struct delayed_work runtime_pm_workqueue; +#endif + +#ifdef CONFIG_PM_DEVFREQ + struct devfreq_dev_profile devfreq_profile; + struct devfreq *devfreq; + unsigned long freq; +#ifdef CONFIG_DEVFREQ_THERMAL + struct devfreq_cooling_device *devfreq_cooling; +#ifdef CONFIG_MALI_POWER_ACTOR + struct power_actor *power_actor; +#endif +#endif +#endif + +#ifdef CONFIG_MALI_TRACE_TIMELINE + struct kbase_trace_kbdev_timeline timeline; +#endif + +#ifdef CONFIG_DEBUG_FS + /* directory for debugfs entries */ + struct dentry *mali_debugfs_directory; + /* debugfs entry for gpu_memory */ + struct dentry *gpu_memory_dentry; + /* debugfs entry for trace */ + struct dentry *trace_dentry; + /* directory for per-ctx memory profiling data */ + struct dentry *memory_profile_directory; + /* Root directory for job dispatcher data */ + struct dentry *jd_directory; +#endif /* CONFIG_DEBUG_FS */ + + /* fbdump profiling controls set by gator */ + u32 kbase_profiling_controls[FBDUMP_CONTROL_MAX]; + + +#if MALI_CUSTOMER_RELEASE == 0 + /* Number of jobs that are run before a job is forced to fail and + * replay. May be KBASEP_FORCE_REPLAY_DISABLED, to disable forced + * failures. */ + int force_replay_limit; + /* Count of jobs between forced failures. Incremented on each job. A + * job is forced to fail once this is greater than or equal to + * force_replay_limit. */ + int force_replay_count; + /* Core requirement for jobs to be failed and replayed. May be zero. */ + base_jd_core_req force_replay_core_req; + /* MALI_TRUE if force_replay_limit should be randomized. The random + * value will be in the range of 1 - KBASEP_FORCE_REPLAY_RANDOM_LIMIT. + */ + mali_bool force_replay_random; +#endif + + /* Total number of created contexts */ + atomic_t ctx_num; + +#if !defined(CONFIG_MTK_CLKMGR) + struct clk *clk_mfg; /* main clock for gpu */ + struct clk *clk_smi_common; /* smi clock */ + struct clk *clk_mfg_scp; /* mfg MTCMOS */ + struct clk *clk_display_scp; /* display MTCMOS */ +#endif /* !defined(CONFIG_MTK_CLKMGR) */ +}; + +struct kbase_context { + struct kbase_device *kbdev; + int id; /* System wide unique id */ + phys_addr_t pgd; + struct list_head event_list; + struct mutex event_mutex; + mali_bool event_closed; + struct workqueue_struct *event_workq; + + u64 mem_attrs; + bool is_compat; + + atomic_t setup_complete; + atomic_t setup_in_progress; + + mali_bool keep_gpu_powered; + + u64 *mmu_teardown_pages; + + phys_addr_t aliasing_sink_page; + + struct mutex reg_lock; /* To be converted to a rwlock? */ + struct rb_root reg_rbtree; /* Red-Black tree of GPU regions (live regions) */ + + unsigned long cookies; + struct kbase_va_region *pending_regions[BITS_PER_LONG]; + + wait_queue_head_t event_queue; + pid_t tgid; + pid_t pid; + + struct kbase_jd_context jctx; + atomic_t used_pages; + atomic_t nonmapped_pages; + + struct kbase_mem_allocator osalloc; + struct kbase_mem_allocator * pgd_allocator; + + struct list_head waiting_soft_jobs; +#ifdef CONFIG_KDS + struct list_head waiting_kds_resource; +#endif + /** This is effectively part of the Run Pool, because it only has a valid + * setting (!=KBASEP_AS_NR_INVALID) whilst the context is scheduled in + * + * The kbasep_js_device_data::runpool_irq::lock must be held whilst accessing + * this. + * + * If the context relating to this as_nr is required, you must use + * kbasep_js_runpool_retain_ctx() to ensure that the context doesn't disappear + * whilst you're using it. Alternatively, just hold the kbasep_js_device_data::runpool_irq::lock + * to ensure the context doesn't disappear (but this has restrictions on what other locks + * you can take whilst doing this) */ + int as_nr; + + /* NOTE: + * + * Flags are in jctx.sched_info.ctx.flags + * Mutable flags *must* be accessed under jctx.sched_info.ctx.jsctx_mutex + * + * All other flags must be added there */ + spinlock_t mm_update_lock; + struct mm_struct * process_mm; + +#ifdef CONFIG_MALI_TRACE_TIMELINE + struct kbase_trace_kctx_timeline timeline; +#endif +#ifdef CONFIG_DEBUG_FS + /* debugfs entry for memory profile */ + struct dentry *mem_dentry; + /* Content of mem_profile file */ + char *mem_profile_data; + /* Size of @c mem_profile_data */ + size_t mem_profile_size; + /* Spinlock guarding data */ + spinlock_t mem_profile_lock; + /* Per-context directory for JD data */ + struct dentry *jd_ctx_dir; +#endif /* CONFIG_DEBUG_FS */ +}; + +enum kbase_reg_access_type { + REG_READ, + REG_WRITE +}; + +enum kbase_share_attr_bits { + /* (1ULL << 8) bit is reserved */ + SHARE_BOTH_BITS = (2ULL << 8), /* inner and outer shareable coherency */ + SHARE_INNER_BITS = (3ULL << 8) /* inner shareable coherency */ +}; + +/* Conversion helpers for setting up high resolution timers */ +#define HR_TIMER_DELAY_MSEC(x) (ns_to_ktime((x)*1000000U)) +#define HR_TIMER_DELAY_NSEC(x) (ns_to_ktime(x)) + +/* Maximum number of loops polling the GPU for a cache flush before we assume it must have completed */ +#define KBASE_CLEAN_CACHE_MAX_LOOPS 100000 +/* Maximum number of loops polling the GPU for an AS command to complete before we assume the GPU has hung */ +#define KBASE_AS_INACTIVE_MAX_LOOPS 100000 + +/* Maximum number of times a job can be replayed */ +#define BASEP_JD_REPLAY_LIMIT 15 + +#endif /* _KBASE_DEFS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.c new file mode 100644 index 0000000000000000000000000000000000000000..7847556a2707df6cac7437a1c7cdbdecc585e532 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.c @@ -0,0 +1,247 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include + +#include +#ifdef CONFIG_DEVFREQ_THERMAL +#include +#endif + +#include "mali_kbase_power_actor.h" + +static int +kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + struct dev_pm_opp *opp; + unsigned long freq = 0; + int err; + + freq = *target_freq; + + rcu_read_lock(); + opp = devfreq_recommended_opp(dev, &freq, flags); + rcu_read_unlock(); + if (IS_ERR_OR_NULL(opp)) { + dev_err(dev, "Failed to get opp (%ld)\n", PTR_ERR(opp)); + return PTR_ERR(opp); + } + + /* + * Only update if there is a change of frequency + */ + if (kbdev->freq == freq) { + *target_freq = freq; + return 0; + } + + err = clk_set_rate(kbdev->clock, freq); + if (err) { + dev_err(dev, "Failed to set clock %lu (target %lu)\n", + freq, *target_freq); + return err; + } + + kbdev->freq = freq; + *target_freq = freq; + + kbase_pm_reset_dvfs_utilisation(kbdev); + + return 0; +} + +static int +kbase_devfreq_cur_freq(struct device *dev, unsigned long *freq) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + *freq = kbdev->freq; + + return 0; +} + +static int +kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *stat) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + stat->current_frequency = kbdev->freq; + + kbase_pm_get_dvfs_utilisation(kbdev, + &stat->total_time, &stat->busy_time); + + stat->private_data = NULL; + + return 0; +} + +static int kbase_devfreq_init_freq_table(struct kbase_device *kbdev, + struct devfreq_dev_profile *dp) +{ + int count; + int i = 0; + unsigned long freq = 0; + struct dev_pm_opp *opp; + + rcu_read_lock(); + count = dev_pm_opp_get_opp_count(kbdev->dev); + if (count < 0) { + rcu_read_unlock(); + return count; + } + rcu_read_unlock(); + + dp->freq_table = kmalloc_array(count, sizeof(dp->freq_table[0]), + GFP_KERNEL); + if (!dp->freq_table) + return -ENOMEM; + + rcu_read_lock(); + for (i = 0; i < count; i++, freq++) { + opp = dev_pm_opp_find_freq_ceil(kbdev->dev, &freq); + if (IS_ERR(opp)) + break; + + dp->freq_table[i] = freq; + } + rcu_read_unlock(); + + if (count != i) + dev_warn(kbdev->dev, "Unable to enumerate all OPPs (%d!=%d\n", + count, i); + + dp->max_state = i; + + return 0; +} + +static void kbase_devfreq_term_freq_table(struct kbase_device *kbdev) +{ + struct devfreq_dev_profile *dp = kbdev->devfreq->profile; + + kfree(dp->freq_table); +} + +static void kbase_devfreq_exit(struct device *dev) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + kbase_devfreq_term_freq_table(kbdev); +} + +int kbase_devfreq_init(struct kbase_device *kbdev) +{ + struct devfreq_dev_profile *dp; + int err; + + dev_dbg(kbdev->dev, "Init Mali devfreq\n"); + + if (!kbdev->clock) + return -ENODEV; + + kbdev->freq = clk_get_rate(kbdev->clock); + + dp = &kbdev->devfreq_profile; + + dp->initial_freq = kbdev->freq; + dp->polling_ms = 100; + dp->target = kbase_devfreq_target; + dp->get_dev_status = kbase_devfreq_status; + dp->get_cur_freq = kbase_devfreq_cur_freq; + dp->exit = kbase_devfreq_exit; + + if (kbase_devfreq_init_freq_table(kbdev, dp)) + return -EFAULT; + + kbdev->devfreq = devfreq_add_device(kbdev->dev, dp, + "simple_ondemand", NULL); + if (IS_ERR_OR_NULL(kbdev->devfreq)) { + kbase_devfreq_term_freq_table(kbdev); + return PTR_ERR(kbdev->devfreq); + } + + err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq); + if (err) { + dev_err(kbdev->dev, + "Failed to register OPP notifier (%d)\n", err); + goto opp_notifier_failed; + } + +#ifdef CONFIG_DEVFREQ_THERMAL + kbdev->devfreq_cooling = of_devfreq_cooling_register( + kbdev->dev->of_node, + kbdev->devfreq); + if (IS_ERR_OR_NULL(kbdev->devfreq_cooling)) { + err = PTR_ERR(kbdev->devfreq_cooling); + dev_err(kbdev->dev, + "Failed to register cooling device (%d)\n", err); + goto cooling_failed; + } + +#ifdef CONFIG_MALI_POWER_ACTOR + err = mali_pa_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Failed to init power actor\n"); + goto pa_failed; + } +#endif +#endif + + return 0; + +#ifdef CONFIG_DEVFREQ_THERMAL +#ifdef CONFIG_MALI_POWER_ACTOR +pa_failed: + devfreq_cooling_unregister(kbdev->devfreq_cooling); +#endif /* CONFIG_MALI_POWER_ACTOR */ +cooling_failed: + devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq); +#endif /* CONFIG_DEVFREQ_THERMAL */ +opp_notifier_failed: + err = devfreq_remove_device(kbdev->devfreq); + if (err) + dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err); + else + kbdev->devfreq = NULL; + + return err; +} + +void kbase_devfreq_term(struct kbase_device *kbdev) +{ + int err; + + dev_dbg(kbdev->dev, "Term Mali devfreq\n"); + +#ifdef CONFIG_DEVFREQ_THERMAL +#ifdef CONFIG_MALI_POWER_ACTOR + mali_pa_term(kbdev); +#endif + + devfreq_cooling_unregister(kbdev->devfreq_cooling); +#endif + + devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq); + + err = devfreq_remove_device(kbdev->devfreq); + if (err) + dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err); + else + kbdev->devfreq = NULL; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.h new file mode 100644 index 0000000000000000000000000000000000000000..e3b333ac35505642dccfc04427b7e0be13d79122 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.h @@ -0,0 +1,24 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _BASE_DEVFREQ_H_ +#define _BASE_DEVFREQ_H_ + +int kbase_devfreq_init(struct kbase_device *kbdev); +void kbase_devfreq_term(struct kbase_device *kbdev); + +#endif /* _BASE_DEVFREQ_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_device.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_device.c new file mode 100644 index 0000000000000000000000000000000000000000..39043c96dbbbe3ac6866db31ec9b4031dd50e1b7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_device.c @@ -0,0 +1,817 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_device.c + * Base kernel device APIs + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* NOTE: Magic - 0x45435254 (TRCE in ASCII). + * Supports tracing feature provided in the base module. + * Please keep it in sync with the value of base module. + */ +#define TRACE_BUFFER_HEADER_SPECIAL 0x45435254 + +#if defined(CONFIG_MALI_PLATFORM_VEXPRESS) || defined(CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ) +#ifdef CONFIG_MALI_PLATFORM_FAKE +extern struct kbase_attribute config_attributes_hw_issue_8408[]; +#endif /* CONFIG_MALI_PLATFORM_FAKE */ +#endif /* CONFIG_MALI_PLATFORM_VEXPRESS || CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ */ + +#if KBASE_TRACE_ENABLE +STATIC CONST char *kbasep_trace_code_string[] = { + /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE + * THIS MUST BE USED AT THE START OF THE ARRAY */ +#define KBASE_TRACE_CODE_MAKE_CODE(X) # X +#include "mali_kbase_trace_defs.h" +#undef KBASE_TRACE_CODE_MAKE_CODE +}; +#endif + +#define DEBUG_MESSAGE_SIZE 256 + +STATIC mali_error kbasep_trace_init(struct kbase_device *kbdev); +STATIC void kbasep_trace_term(struct kbase_device *kbdev); +STATIC void kbasep_trace_hook_wrapper(void *param); +#if KBASE_TRACE_ENABLE +STATIC void kbasep_trace_debugfs_init(struct kbase_device *kbdev); +STATIC void kbasep_trace_debugfs_term(struct kbase_device *kbdev); +#endif + +struct kbase_device *kbase_device_alloc(void) +{ + return kzalloc(sizeof(struct kbase_device), GFP_KERNEL); +} + +mali_error kbase_device_init(struct kbase_device * const kbdev) +{ + int i; /* i used after the for loop, don't reuse ! */ + + spin_lock_init(&kbdev->mmu_mask_change); + + /* Initialize platform specific context */ + if (MALI_FALSE == kbasep_platform_device_init(kbdev)) + goto fail; + + /* Ensure we can access the GPU registers */ + kbase_pm_register_access_enable(kbdev); + + /* Find out GPU properties based on the GPU feature registers */ + kbase_gpuprops_set(kbdev); + + /* Get the list of workarounds for issues on the current HW (identified by the GPU_ID register) */ + if (MALI_ERROR_NONE != kbase_hw_set_issues_mask(kbdev)) { + kbase_pm_register_access_disable(kbdev); + goto free_platform; + } + /* Set the list of features available on the current HW (identified by the GPU_ID register) */ + kbase_hw_set_features_mask(kbdev); + +#if defined(CONFIG_ARM64) + set_dma_ops(kbdev->dev, &noncoherent_swiotlb_dma_ops); +#endif + + /* Workaround a pre-3.13 Linux issue, where dma_mask is NULL when our + * device structure was created by device-tree + */ + if (!kbdev->dev->dma_mask) + kbdev->dev->dma_mask = &kbdev->dev->coherent_dma_mask; + + if (dma_set_mask(kbdev->dev, + DMA_BIT_MASK(kbdev->gpu_props.mmu.pa_bits))) + goto dma_set_mask_failed; + + if (dma_set_coherent_mask(kbdev->dev, + DMA_BIT_MASK(kbdev->gpu_props.mmu.pa_bits))) + goto dma_set_mask_failed; + + if (kbase_mem_lowlevel_init(kbdev)) + goto mem_lowlevel_init_failed; + + kbdev->nr_hw_address_spaces = kbdev->gpu_props.num_address_spaces; + + /* We're done accessing the GPU registers for now. */ + kbase_pm_register_access_disable(kbdev); + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { + const char format[] = "mali_mmu%d"; + char name[sizeof(format)]; + const char poke_format[] = "mali_mmu%d_poker"; /* BASE_HW_ISSUE_8316 */ + char poke_name[sizeof(poke_format)]; /* BASE_HW_ISSUE_8316 */ + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) { + if (0 > snprintf(poke_name, sizeof(poke_name), poke_format, i)) + goto free_workqs; + } + + if (0 > snprintf(name, sizeof(name), format, i)) + goto free_workqs; + + kbdev->as[i].number = i; + kbdev->as[i].fault_addr = 0ULL; + + kbdev->as[i].pf_wq = alloc_workqueue(name, 0, 1); + if (NULL == kbdev->as[i].pf_wq) + goto free_workqs; + + mutex_init(&kbdev->as[i].transaction_mutex); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) { + struct hrtimer *poking_timer = &kbdev->as[i].poke_timer; + + kbdev->as[i].poke_wq = alloc_workqueue(poke_name, 0, 1); + if (NULL == kbdev->as[i].poke_wq) { + destroy_workqueue(kbdev->as[i].pf_wq); + goto free_workqs; + } + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&kbdev->as[i].poke_work)); + INIT_WORK(&kbdev->as[i].poke_work, kbasep_as_do_poke); + + hrtimer_init(poking_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + + poking_timer->function = kbasep_as_poke_timer_callback; + + kbdev->as[i].poke_refcount = 0; + kbdev->as[i].poke_state = 0u; + } + } + /* don't change i after this point */ + + spin_lock_init(&kbdev->hwcnt.lock); + + kbdev->hwcnt.state = KBASE_INSTR_STATE_DISABLED; + init_waitqueue_head(&kbdev->reset_wait); + init_waitqueue_head(&kbdev->hwcnt.wait); + init_waitqueue_head(&kbdev->hwcnt.cache_clean_wait); + INIT_WORK(&kbdev->hwcnt.cache_clean_work, kbasep_cache_clean_worker); + kbdev->hwcnt.triggered = 0; + + kbdev->hwcnt.cache_clean_wq = alloc_workqueue("Mali cache cleaning workqueue", + 0, 1); + if (NULL == kbdev->hwcnt.cache_clean_wq) + goto free_workqs; + +#if KBASE_GPU_RESET_EN + kbdev->reset_workq = alloc_workqueue("Mali reset workqueue", 0, 1); + if (NULL == kbdev->reset_workq) + goto free_cache_clean_workq; + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&kbdev->reset_work)); + INIT_WORK(&kbdev->reset_work, kbasep_reset_timeout_worker); + + hrtimer_init(&kbdev->reset_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->reset_timer.function = kbasep_reset_timer_callback; + + if (kbasep_trace_init(kbdev) != MALI_ERROR_NONE) + goto free_reset_workq; +#else + if (kbasep_trace_init(kbdev) != MALI_ERROR_NONE) + goto free_cache_clean_workq; +#endif /* KBASE_GPU_RESET_EN */ + + mutex_init(&kbdev->cacheclean_lock); + atomic_set(&kbdev->keep_gpu_powered_count, 0); + +#ifdef CONFIG_MALI_TRACE_TIMELINE + for (i = 0; i < BASE_JM_SUBMIT_SLOTS; ++i) + kbdev->timeline.slot_atoms_submitted[i] = 0; + + for (i = 0; i <= KBASEP_TIMELINE_PM_EVENT_LAST; ++i) + atomic_set(&kbdev->timeline.pm_event_uid[i], 0); +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + + /* fbdump profiling controls set to 0 - fbdump not enabled until changed by gator */ + for (i = 0; i < FBDUMP_CONTROL_MAX; i++) + kbdev->kbase_profiling_controls[i] = 0; + + kbase_debug_assert_register_hook(&kbasep_trace_hook_wrapper, kbdev); + +#if defined(CONFIG_MALI_PLATFORM_VEXPRESS) || defined(CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ) +#ifdef CONFIG_MALI_PLATFORM_FAKE + /* BASE_HW_ISSUE_8408 requires a configuration with different timeouts for + * the vexpress platform */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + kbdev->config_attributes = config_attributes_hw_issue_8408; +#endif /* CONFIG_MALI_PLATFORM_FAKE */ +#endif /* CONFIG_MALI_PLATFORM_VEXPRESS || CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ */ + + atomic_set(&kbdev->ctx_num, 0); + + return MALI_ERROR_NONE; +#if KBASE_GPU_RESET_EN +free_reset_workq: + destroy_workqueue(kbdev->reset_workq); +#endif /* KBASE_GPU_RESET_EN */ +free_cache_clean_workq: + destroy_workqueue(kbdev->hwcnt.cache_clean_wq); + free_workqs: + while (i > 0) { + i--; + destroy_workqueue(kbdev->as[i].pf_wq); + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + destroy_workqueue(kbdev->as[i].poke_wq); + } + kbase_mem_lowlevel_term(kbdev); +mem_lowlevel_init_failed: +dma_set_mask_failed: +free_platform: + kbasep_platform_device_term(kbdev); +fail: + return MALI_ERROR_FUNCTION_FAILED; +} + +void kbase_device_term(struct kbase_device *kbdev) +{ + int i; + + KBASE_DEBUG_ASSERT(kbdev); + +#if KBASE_TRACE_ENABLE + kbase_debug_assert_register_hook(NULL, NULL); +#endif + + kbasep_trace_term(kbdev); + +#if KBASE_GPU_RESET_EN + destroy_workqueue(kbdev->reset_workq); +#endif + + destroy_workqueue(kbdev->hwcnt.cache_clean_wq); + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { + destroy_workqueue(kbdev->as[i].pf_wq); + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + destroy_workqueue(kbdev->as[i].poke_wq); + } + + kbase_mem_lowlevel_term(kbdev); + kbasep_platform_device_term(kbdev); +} + +void kbase_device_free(struct kbase_device *kbdev) +{ + kfree(kbdev); +} + +void kbase_device_trace_buffer_install(struct kbase_context *kctx, u32 *tb, size_t size) +{ + unsigned long flags; + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(tb); + + /* set up the header */ + /* magic number in the first 4 bytes */ + tb[0] = TRACE_BUFFER_HEADER_SPECIAL; + /* Store (write offset = 0, wrap counter = 0, transaction active = no) + * write offset 0 means never written. + * Offsets 1 to (wrap_offset - 1) used to store values when trace started + */ + tb[1] = 0; + + /* install trace buffer */ + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + kctx->jctx.tb_wrap_offset = size / 8; + kctx->jctx.tb = tb; + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); +} + +void kbase_device_trace_buffer_uninstall(struct kbase_context *kctx) +{ + unsigned long flags; + KBASE_DEBUG_ASSERT(kctx); + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + kctx->jctx.tb = NULL; + kctx->jctx.tb_wrap_offset = 0; + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); +} + +void kbase_device_trace_register_access(struct kbase_context *kctx, enum kbase_reg_access_type type, u16 reg_offset, u32 reg_value) +{ + unsigned long flags; + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + if (kctx->jctx.tb) { + u16 wrap_count; + u16 write_offset; + u32 *tb = kctx->jctx.tb; + u32 header_word; + + header_word = tb[1]; + KBASE_DEBUG_ASSERT(0 == (header_word & 0x1)); + + wrap_count = (header_word >> 1) & 0x7FFF; + write_offset = (header_word >> 16) & 0xFFFF; + + /* mark as transaction in progress */ + tb[1] |= 0x1; + mb(); + + /* calculate new offset */ + write_offset++; + if (write_offset == kctx->jctx.tb_wrap_offset) { + /* wrap */ + write_offset = 1; + wrap_count++; + wrap_count &= 0x7FFF; /* 15bit wrap counter */ + } + + /* store the trace entry at the selected offset */ + tb[write_offset * 2 + 0] = (reg_offset & ~0x3) | ((type == REG_WRITE) ? 0x1 : 0x0); + tb[write_offset * 2 + 1] = reg_value; + mb(); + + /* new header word */ + header_word = (write_offset << 16) | (wrap_count << 1) | 0x0; /* transaction complete */ + tb[1] = header_word; + } + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); +} + +void kbase_reg_write(struct kbase_device *kbdev, u16 offset, u32 value, struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered); + KBASE_DEBUG_ASSERT(kctx == NULL || kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbdev->dev != NULL); + dev_dbg(kbdev->dev, "w: reg %04x val %08x", offset, value); + kbase_os_reg_write(kbdev, offset, value); + if (kctx && kctx->jctx.tb) + kbase_device_trace_register_access(kctx, REG_WRITE, offset, value); +} + +KBASE_EXPORT_TEST_API(kbase_reg_write) + +u32 kbase_reg_read(struct kbase_device *kbdev, u16 offset, struct kbase_context *kctx) +{ + u32 val; + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered); + KBASE_DEBUG_ASSERT(kctx == NULL || kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbdev->dev != NULL); + val = kbase_os_reg_read(kbdev, offset); + dev_dbg(kbdev->dev, "r: reg %04x val %08x", offset, val); + if (kctx && kctx->jctx.tb) + kbase_device_trace_register_access(kctx, REG_READ, offset, val); + return val; +} + +KBASE_EXPORT_TEST_API(kbase_reg_read) + +#if KBASE_PM_EN +void kbase_report_gpu_fault(struct kbase_device *kbdev, int multiple) +{ + u32 status; + u64 address; + + status = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS), NULL); + address = (u64) kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTADDRESS_HI), NULL) << 32; + address |= kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTADDRESS_LO), NULL); + + dev_warn(kbdev->dev, "GPU Fault 0x%08x (%s) at 0x%016llx", status & 0xFF, kbase_exception_name(status), address); + if (multiple) + dev_warn(kbdev->dev, "There were multiple GPU faults - some have not been reported\n"); +} + +void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) +{ + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, NULL, 0u, val); + if (val & GPU_FAULT) + kbase_report_gpu_fault(kbdev, val & MULTIPLE_GPU_FAULTS); + + if (val & RESET_COMPLETED) + kbase_pm_reset_done(kbdev); + + if (val & PRFCNT_SAMPLE_COMPLETED) + kbase_instr_hwcnt_sample_done(kbdev); + + if (val & CLEAN_CACHES_COMPLETED) + kbase_clean_caches_done(kbdev); + + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, NULL, 0u, val); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), val, NULL); + + /* kbase_pm_check_transitions must be called after the IRQ has been cleared. This is because it might trigger + * further power transitions and we don't want to miss the interrupt raised to notify us that these further + * transitions have finished. + */ + if (val & POWER_CHANGED_ALL) { + mali_bool cores_are_available; + unsigned long flags; + + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_START); + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_END); + + if (cores_are_available) { + /* Fast-path Job Scheduling on PM IRQ */ + int js; + /* Log timelining information that a change in state has completed */ + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + + spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags); + /* A simplified check to ensure the last context hasn't exited + * after dropping the PM lock whilst doing a PM IRQ: any bits set + * in 'submit_allowed' indicate that we have a context in the + * runpool (which can't leave whilst we hold this lock). It is + * sometimes zero even when we have a context in the runpool, but + * that's no problem because we'll be unable to submit jobs + * anyway */ + if (kbdev->js_data.runpool_irq.submit_allowed) + for (js = 0; js < kbdev->gpu_props.num_job_slots; ++js) { + mali_bool needs_retry; + s8 submitted_count = 0; + needs_retry = kbasep_js_try_run_next_job_on_slot_irq_nolock(kbdev, js, &submitted_count); + /* Don't need to retry outside of IRQ context - this can + * only happen if we submitted too many in one IRQ, such + * that they were completing faster than we could + * submit. In this case, a job IRQ will fire to cause more + * work to be submitted in some way */ + CSTD_UNUSED(needs_retry); + } + spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags); + } + } + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_DONE, NULL, NULL, 0u, val); +} +#endif /* KBASE_PM_EN */ +/* + * Device trace functions + */ +#if KBASE_TRACE_ENABLE + +STATIC mali_error kbasep_trace_init(struct kbase_device *kbdev) +{ + void *rbuf; + + rbuf = kmalloc(sizeof(struct kbase_trace) * KBASE_TRACE_SIZE, GFP_KERNEL); + + if (!rbuf) + return MALI_ERROR_FUNCTION_FAILED; + + kbdev->trace_rbuf = rbuf; + spin_lock_init(&kbdev->trace_lock); + kbasep_trace_debugfs_init(kbdev); + return MALI_ERROR_NONE; +} + +STATIC void kbasep_trace_term(struct kbase_device *kbdev) +{ + kbasep_trace_debugfs_term(kbdev); + kfree(kbdev->trace_rbuf); +} + +static void kbasep_trace_format_msg(struct kbase_trace *trace_msg, char *buffer, int len) +{ + s32 written = 0; + + /* Initial part of message */ + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d.%.6d,%d,%d,%s,%p,", (int)trace_msg->timestamp.tv_sec, (int)(trace_msg->timestamp.tv_nsec / 1000), trace_msg->thread_id, trace_msg->cpu, kbasep_trace_code_string[trace_msg->code], trace_msg->ctx), 0); + + if (trace_msg->katom != MALI_FALSE) { + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "atom %d (ud: 0x%llx 0x%llx)", trace_msg->atom_number, trace_msg->atom_udata[0], trace_msg->atom_udata[1]), 0); + } + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ",%.8llx,", trace_msg->gpu_addr), 0); + + /* NOTE: Could add function callbacks to handle different message types */ + /* Jobslot present */ + if ((trace_msg->flags & KBASE_TRACE_FLAG_JOBSLOT) != MALI_FALSE) + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->jobslot), 0); + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0); + + /* Refcount present */ + if ((trace_msg->flags & KBASE_TRACE_FLAG_REFCOUNT) != MALI_FALSE) + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->refcount), 0); + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0); + + /* Rest of message */ + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "0x%.8lx", trace_msg->info_val), 0); + +} + +static void kbasep_trace_dump_msg(struct kbase_device *kbdev, struct kbase_trace *trace_msg) +{ + char buffer[DEBUG_MESSAGE_SIZE]; + + kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE); + dev_dbg(kbdev->dev, "%s", buffer); +} + +void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val) +{ + unsigned long irqflags; + struct kbase_trace *trace_msg; + + spin_lock_irqsave(&kbdev->trace_lock, irqflags); + + trace_msg = &kbdev->trace_rbuf[kbdev->trace_next_in]; + + /* Fill the message */ + trace_msg->thread_id = task_pid_nr(current); + trace_msg->cpu = task_cpu(current); + + getnstimeofday(&trace_msg->timestamp); + + trace_msg->code = code; + trace_msg->ctx = ctx; + + if (NULL == katom) { + trace_msg->katom = MALI_FALSE; + } else { + trace_msg->katom = MALI_TRUE; + trace_msg->atom_number = kbase_jd_atom_id(katom->kctx, katom); + trace_msg->atom_udata[0] = katom->udata.blob[0]; + trace_msg->atom_udata[1] = katom->udata.blob[1]; + } + + trace_msg->gpu_addr = gpu_addr; + trace_msg->jobslot = jobslot; + trace_msg->refcount = MIN((unsigned int)refcount, 0xFF); + trace_msg->info_val = info_val; + trace_msg->flags = flags; + + /* Update the ringbuffer indices */ + kbdev->trace_next_in = (kbdev->trace_next_in + 1) & KBASE_TRACE_MASK; + if (kbdev->trace_next_in == kbdev->trace_first_out) + kbdev->trace_first_out = (kbdev->trace_first_out + 1) & KBASE_TRACE_MASK; + + /* Done */ + + spin_unlock_irqrestore(&kbdev->trace_lock, irqflags); +} + +void kbasep_trace_clear(struct kbase_device *kbdev) +{ + unsigned long flags; + spin_lock_irqsave(&kbdev->trace_lock, flags); + kbdev->trace_first_out = kbdev->trace_next_in; + spin_unlock_irqrestore(&kbdev->trace_lock, flags); +} + +void kbasep_trace_dump(struct kbase_device *kbdev) +{ + unsigned long flags; + u32 start; + u32 end; + + dev_dbg(kbdev->dev, "Dumping trace:\nsecs,nthread,cpu,code,ctx,katom,gpu_addr,jobslot,refcount,info_val"); + spin_lock_irqsave(&kbdev->trace_lock, flags); + start = kbdev->trace_first_out; + end = kbdev->trace_next_in; + + while (start != end) { + struct kbase_trace *trace_msg = &kbdev->trace_rbuf[start]; + kbasep_trace_dump_msg(kbdev, trace_msg); + + start = (start + 1) & KBASE_TRACE_MASK; + } + dev_dbg(kbdev->dev, "TRACE_END"); + + spin_unlock_irqrestore(&kbdev->trace_lock, flags); + + KBASE_TRACE_CLEAR(kbdev); +} + +STATIC void kbasep_trace_hook_wrapper(void *param) +{ + struct kbase_device *kbdev = (struct kbase_device *)param; + kbasep_trace_dump(kbdev); +} + +#ifdef CONFIG_DEBUG_FS +struct trace_seq_state { + struct kbase_trace trace_buf[KBASE_TRACE_SIZE]; + u32 start; + u32 end; +}; + +static void *kbasep_trace_seq_start(struct seq_file *s, loff_t *pos) +{ + struct trace_seq_state *state = s->private; + int i; + + if (*pos > KBASE_TRACE_SIZE) + return NULL; + i = state->start + *pos; + if ((state->end >= state->start && i >= state->end) || + i >= state->end + KBASE_TRACE_SIZE) + return NULL; + + i &= KBASE_TRACE_MASK; + + return &state->trace_buf[i]; +} + +static void kbasep_trace_seq_stop(struct seq_file *s, void *data) +{ +} + +static void *kbasep_trace_seq_next(struct seq_file *s, void *data, loff_t *pos) +{ + struct trace_seq_state *state = s->private; + int i; + + (*pos)++; + + i = (state->start + *pos) & KBASE_TRACE_MASK; + if (i == state->end) + return NULL; + + return &state->trace_buf[i]; +} + +static int kbasep_trace_seq_show(struct seq_file *s, void *data) +{ + struct kbase_trace *trace_msg = data; + char buffer[DEBUG_MESSAGE_SIZE]; + + kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE); + seq_printf(s, "%s\n", buffer); + return 0; +} + +static const struct seq_operations kbasep_trace_seq_ops = { + .start = kbasep_trace_seq_start, + .next = kbasep_trace_seq_next, + .stop = kbasep_trace_seq_stop, + .show = kbasep_trace_seq_show, +}; + +static int kbasep_trace_debugfs_open(struct inode *inode, struct file *file) +{ + struct kbase_device *kbdev = inode->i_private; + unsigned long flags; + + struct trace_seq_state *state; + + state = __seq_open_private(file, &kbasep_trace_seq_ops, sizeof(*state)); + if (!state) + return -ENOMEM; + + spin_lock_irqsave(&kbdev->trace_lock, flags); + state->start = kbdev->trace_first_out; + state->end = kbdev->trace_next_in; + memcpy(state->trace_buf, kbdev->trace_rbuf, sizeof(state->trace_buf)); + spin_unlock_irqrestore(&kbdev->trace_lock, flags); + + return 0; +} + +static const struct file_operations kbasep_trace_debugfs_fops = { + .open = kbasep_trace_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +STATIC void kbasep_trace_debugfs_init(struct kbase_device *kbdev) +{ + kbdev->trace_dentry = debugfs_create_file("mali_trace", S_IRUGO, + kbdev->mali_debugfs_directory, kbdev, + &kbasep_trace_debugfs_fops); +} + +STATIC void kbasep_trace_debugfs_term(struct kbase_device *kbdev) +{ + debugfs_remove(kbdev->trace_dentry); + kbdev->trace_dentry = NULL; +} +#else +STATIC void kbasep_trace_debugfs_init(struct kbase_device *kbdev) +{ + +} +STATIC void kbasep_trace_debugfs_term(struct kbase_device *kbdev) +{ + +} +#endif /* CONFIG_DEBUG_FS */ + +#else /* KBASE_TRACE_ENABLE */ +STATIC mali_error kbasep_trace_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); + return MALI_ERROR_NONE; +} + +STATIC void kbasep_trace_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +STATIC void kbasep_trace_hook_wrapper(void *param) +{ + CSTD_UNUSED(param); +} + +void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(code); + CSTD_UNUSED(ctx); + CSTD_UNUSED(katom); + CSTD_UNUSED(gpu_addr); + CSTD_UNUSED(flags); + CSTD_UNUSED(refcount); + CSTD_UNUSED(jobslot); + CSTD_UNUSED(info_val); +} + +void kbasep_trace_clear(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbasep_trace_dump(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} +#endif /* KBASE_TRACE_ENABLE */ + +void kbase_set_profiling_control(struct kbase_device *kbdev, u32 control, u32 value) +{ + switch (control) { + case FBDUMP_CONTROL_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RATE: + /* fall through */ + case SW_COUNTER_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RESIZE_FACTOR: + kbdev->kbase_profiling_controls[control] = value; + break; + default: + dev_err(kbdev->dev, "Profiling control %d not found\n", control); + break; + } +} + +u32 kbase_get_profiling_control(struct kbase_device *kbdev, u32 control) +{ + u32 ret_value = 0; + + switch (control) { + case FBDUMP_CONTROL_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RATE: + /* fall through */ + case SW_COUNTER_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RESIZE_FACTOR: + ret_value = kbdev->kbase_profiling_controls[control]; + break; + default: + dev_err(kbdev->dev, "Profiling control %d not found\n", control); + break; + } + + return ret_value; +} + +/* + * Called by gator to control the production of + * profiling information at runtime + * */ + +void _mali_profiling_control(u32 action, u32 value) +{ + struct kbase_device *kbdev = NULL; + + /* find the first i.e. call with -1 */ + kbdev = kbase_find_device(-1); + + if (NULL != kbdev) { + kbase_set_profiling_control(kbdev, action, value); + } +} + +KBASE_EXPORT_SYMBOL(_mali_profiling_control); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c new file mode 100644 index 0000000000000000000000000000000000000000..22b62277cc924e8bbc70e948cd942bb68e5d9133 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c @@ -0,0 +1,77 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_disjoint_events.c + * Base kernel disjoint events helper functions + */ + +#include + +void kbase_disjoint_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_set(&kbdev->disjoint_event.count, 0); + atomic_set(&kbdev->disjoint_event.state, 0); +} + +/* increment the disjoint event count */ +void kbase_disjoint_event(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_inc(&kbdev->disjoint_event.count); +} + +/* increment the state and the event counter */ +void kbase_disjoint_state_up(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_inc(&kbdev->disjoint_event.state); + + kbase_disjoint_event(kbdev); +} + +/* decrement the state */ +void kbase_disjoint_state_down(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->disjoint_event.state) > 0); + + kbase_disjoint_event(kbdev); + + atomic_dec(&kbdev->disjoint_event.state); +} + +/* increments the count only if the state is > 0 */ +void kbase_disjoint_event_potential(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + if (atomic_read(&kbdev->disjoint_event.state)) + kbase_disjoint_event(kbdev); +} + +u32 kbase_disjoint_event_get(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return atomic_read(&kbdev->disjoint_event.count); +} +KBASE_EXPORT_TEST_API(kbase_disjoint_event_get) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_event.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_event.c new file mode 100644 index 0000000000000000000000000000000000000000..27312ca7a1252713723bf90af3af08018863099f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_event.c @@ -0,0 +1,186 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include + +STATIC struct base_jd_udata kbase_event_process(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct base_jd_udata data; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED); + + data = katom->udata; + + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_sub_return(1, &kctx->timeline.jd_atoms_in_flight)); + + mutex_lock(&kctx->jctx.lock); + katom->status = KBASE_JD_ATOM_STATE_UNUSED; + mutex_unlock(&kctx->jctx.lock); + + wake_up(&katom->completed); + + return data; +} + +int kbase_event_pending(struct kbase_context *ctx) +{ + int ret; + + KBASE_DEBUG_ASSERT(ctx); + + mutex_lock(&ctx->event_mutex); + ret = (!list_empty(&ctx->event_list)) || (MALI_TRUE == ctx->event_closed); + mutex_unlock(&ctx->event_mutex); + + return ret; +} + +KBASE_EXPORT_TEST_API(kbase_event_pending) + +int kbase_event_dequeue(struct kbase_context *ctx, struct base_jd_event_v2 *uevent) +{ + struct kbase_jd_atom *atom; + + KBASE_DEBUG_ASSERT(ctx); + + mutex_lock(&ctx->event_mutex); + + if (list_empty(&ctx->event_list)) { + if (ctx->event_closed) { + /* generate the BASE_JD_EVENT_DRV_TERMINATED message on the fly */ + mutex_unlock(&ctx->event_mutex); + uevent->event_code = BASE_JD_EVENT_DRV_TERMINATED; + memset(&uevent->udata, 0, sizeof(uevent->udata)); + dev_dbg(ctx->kbdev->dev, + "event system closed, returning BASE_JD_EVENT_DRV_TERMINATED(0x%X)\n", + BASE_JD_EVENT_DRV_TERMINATED); + return 0; + } else { + mutex_unlock(&ctx->event_mutex); + return -1; + } + } + + /* normal event processing */ + atom = list_entry(ctx->event_list.next, struct kbase_jd_atom, dep_item[0]); + list_del(ctx->event_list.next); + + mutex_unlock(&ctx->event_mutex); + + dev_dbg(ctx->kbdev->dev, "event dequeuing %p\n", (void *)atom); + uevent->event_code = atom->event_code; + uevent->atom_number = (atom - ctx->jctx.atoms); + uevent->udata = kbase_event_process(ctx, atom); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_event_dequeue) + +static void kbase_event_post_worker(struct work_struct *data) +{ + struct kbase_jd_atom *atom = container_of(data, struct kbase_jd_atom, work); + struct kbase_context *ctx = atom->kctx; + + if (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) + kbase_jd_free_external_resources(atom); + + if (atom->core_req & BASE_JD_REQ_EVENT_ONLY_ON_FAILURE) { + if (atom->event_code == BASE_JD_EVENT_DONE) { + /* Don't report the event */ + kbase_event_process(ctx, atom); + return; + } + } + + if (atom->core_req & BASEP_JD_REQ_EVENT_NEVER) { + /* Don't report the event */ + kbase_event_process(ctx, atom); + return; + } + + mutex_lock(&ctx->event_mutex); + list_add_tail(&atom->dep_item[0], &ctx->event_list); + mutex_unlock(&ctx->event_mutex); + + kbase_event_wakeup(ctx); +} + +void kbase_event_post(struct kbase_context *ctx, struct kbase_jd_atom *atom) +{ + KBASE_DEBUG_ASSERT(ctx); + KBASE_DEBUG_ASSERT(ctx->event_workq); + KBASE_DEBUG_ASSERT(atom); + + INIT_WORK(&atom->work, kbase_event_post_worker); + queue_work(ctx->event_workq, &atom->work); +} + +KBASE_EXPORT_TEST_API(kbase_event_post) + +void kbase_event_close(struct kbase_context *kctx) +{ + mutex_lock(&kctx->event_mutex); + kctx->event_closed = MALI_TRUE; + mutex_unlock(&kctx->event_mutex); + kbase_event_wakeup(kctx); +} + +mali_error kbase_event_init(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + + INIT_LIST_HEAD(&kctx->event_list); + mutex_init(&kctx->event_mutex); + kctx->event_closed = MALI_FALSE; + kctx->event_workq = alloc_workqueue("kbase_event", WQ_MEM_RECLAIM, 1); + + if (NULL == kctx->event_workq) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_event_init) + +void kbase_event_cleanup(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(kctx->event_workq); + + flush_workqueue(kctx->event_workq); + destroy_workqueue(kctx->event_workq); + + /* We use kbase_event_dequeue to remove the remaining events as that + * deals with all the cleanup needed for the atoms. + * + * Note: use of kctx->event_list without a lock is safe because this must be the last + * thread using it (because we're about to terminate the lock) + */ + while (!list_empty(&kctx->event_list)) { + struct base_jd_event_v2 event; + + kbase_event_dequeue(kctx, &event); + } +} + +KBASE_EXPORT_TEST_API(kbase_event_cleanup) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator.h new file mode 100644 index 0000000000000000000000000000000000000000..c931af6dfa08d968c3d1f9d4e669eca3b1b9f2a5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator.h @@ -0,0 +1,44 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* NB taken from gator */ +/* + * List of possible actions to be controlled by Streamline. + * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting. + * We cannot use the enums in mali_uk_types.h because they are unknown inside gator. + */ +#ifndef _KBASE_GATOR_H_ +#define _KBASE_GATOR_H_ + +#ifdef CONFIG_MALI_GATOR_SUPPORT +#define GATOR_MAKE_EVENT(type, number) (((type) << 24) | ((number) << 16)) +#define GATOR_JOB_SLOT_START 1 +#define GATOR_JOB_SLOT_STOP 2 +#define GATOR_JOB_SLOT_SOFT_STOPPED 3 + +void kbase_trace_mali_job_slots_event(u32 event, const struct kbase_context *kctx, u8 atom_id); +void kbase_trace_mali_pm_status(u32 event, u64 value); +void kbase_trace_mali_pm_power_off(u32 event, u64 value); +void kbase_trace_mali_pm_power_on(u32 event, u64 value); +void kbase_trace_mali_page_fault_insert_pages(int event, u32 value); +void kbase_trace_mali_mmu_as_in_use(int event); +void kbase_trace_mali_mmu_as_released(int event); +void kbase_trace_mali_total_alloc_pages_change(long long int event); + +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + +#endif /* _KBASE_GATOR_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.c new file mode 100644 index 0000000000000000000000000000000000000000..eee9b7c72da3936f934d695b276427166702780d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.c @@ -0,0 +1,315 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase.h" +#include "mali_kbase_mem_linux.h" +#include "mali_kbase_gator_api.h" +#include "mali_kbase_gator_hwcnt_names.h" + +#define MALI_MAX_CORES_PER_GROUP 4 +#define MALI_MAX_NUM_BLOCKS_PER_GROUP 8 +#define MALI_COUNTERS_PER_BLOCK 64 +#define MALI_BYTES_PER_COUNTER 4 + +struct kbase_gator_hwcnt_handles { + struct kbase_device *kbdev; + struct kbase_context *kctx; + mali_addr64 hwcnt_gpu_va; + void *hwcnt_cpu_va; + struct kbase_vmap_struct hwcnt_map; +}; + +const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters) +{ + uint32_t gpu_id; + const char * const *hardware_counters; + struct kbase_device *kbdev; + + if (!total_counters) + return NULL; + + /* Get the first device - it doesn't matter in this case */ + kbdev = kbase_find_device(-1); + if (!kbdev) + return NULL; + + gpu_id = kbdev->gpu_props.props.core_props.product_id; + + switch (gpu_id) { + /* If we are using a Mali-T60x device */ + case GPU_ID_PI_T60X: + hardware_counters = hardware_counters_mali_t60x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t60x); + break; + /* If we are using a Mali-T62x device */ + case GPU_ID_PI_T62X: + hardware_counters = hardware_counters_mali_t62x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t62x); + break; + /* If we are using a Mali-T72x device */ + case GPU_ID_PI_T72X: + hardware_counters = hardware_counters_mali_t72x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t72x); + break; + /* If we are using a Mali-T76x device */ + case GPU_ID_PI_T76X: + hardware_counters = hardware_counters_mali_t76x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t76x); + break; + /* If we are using a Mali-T86x device */ + case GPU_ID_PI_T86X: + hardware_counters = hardware_counters_mali_t86x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t86x); + break; + /* If we are using a Mali-T88x device */ +#ifdef MALI_INCLUDE_TFRX + case GPU_ID_PI_TFRX: + hardware_counters = hardware_counters_mali_t88x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t88x); + break; +#endif /* MALI_INCLUDE_TRFX */ + default: + hardware_counters = NULL; + *total_counters = 0; + dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n", gpu_id); + break; + } + + /* Release the kbdev reference. */ + kbase_release_device(kbdev); + + /* If we return a string array take a reference on the module (or fail). */ + if (hardware_counters && !try_module_get(THIS_MODULE)) + return NULL; + + return hardware_counters; +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init_names) + +void kbase_gator_hwcnt_term_names(void) +{ + /* Release the module reference. */ + module_put(THIS_MODULE); +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term_names) + +struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info) +{ + struct kbase_gator_hwcnt_handles *hand; + struct kbase_uk_hwcnt_setup setup; + mali_error err; + uint32_t dump_size = 0, i = 0; + struct kbase_va_region *reg; + u64 flags; + u64 nr_pages; + u16 va_alignment = 0; + + if (!in_out_info) + return NULL; + + hand = kzalloc(sizeof(*hand), GFP_KERNEL); + if (!hand) + return NULL; + + /* Get the first device */ + hand->kbdev = kbase_find_device(-1); + if (!hand->kbdev) + goto free_hand; + + /* Create a kbase_context */ + hand->kctx = kbase_create_context(hand->kbdev, true); + if (!hand->kctx) + goto release_device; + + in_out_info->nr_cores = hand->kbdev->gpu_props.num_cores; + in_out_info->nr_core_groups = hand->kbdev->gpu_props.num_core_groups; + in_out_info->gpu_id = hand->kbdev->gpu_props.props.core_props.product_id; + + /* If we are using a Mali-T6xx or Mali-T72x device */ + if (in_out_info->gpu_id == GPU_ID_PI_T60X || + in_out_info->gpu_id == GPU_ID_PI_T62X || + in_out_info->gpu_id == GPU_ID_PI_T72X) { + uint32_t cg, j; + uint64_t core_mask; + + /* There are 8 hardware counters blocks per core group */ + in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * + MALI_MAX_NUM_BLOCKS_PER_GROUP * + in_out_info->nr_core_groups, GFP_KERNEL); + + if (!in_out_info->hwc_layout) + goto destroy_context; + + dump_size = in_out_info->nr_core_groups * + MALI_MAX_NUM_BLOCKS_PER_GROUP * + MALI_COUNTERS_PER_BLOCK * + MALI_BYTES_PER_COUNTER; + + for (cg = 0; cg < in_out_info->nr_core_groups; cg++) { + core_mask = hand->kbdev->gpu_props.props.coherency_info.group[cg].core_mask; + + for (j = 0; j < MALI_MAX_CORES_PER_GROUP; j++) { + if (core_mask & (1u << j)) + in_out_info->hwc_layout[i++] = SHADER_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + } + + in_out_info->hwc_layout[i++] = TILER_BLOCK; + in_out_info->hwc_layout[i++] = MMU_L2_BLOCK; + + /* There are no implementation with L3 cache */ + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + + if (0 == cg) + in_out_info->hwc_layout[i++] = JM_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + } + /* If we are using a Mali-T76x device */ + } else if ( + (in_out_info->gpu_id == GPU_ID_PI_T76X) +#ifdef MALI_INCLUDE_TFRX + || (in_out_info->gpu_id == GPU_ID_PI_TFRX) +#endif /* MALI_INCLUDE_TFRX */ + || (in_out_info->gpu_id == GPU_ID_PI_T86X) +#ifdef MALI_INCLUDE_TGAL + || (in_out_info->gpu_id == GPU_ID_PI_TGAL) +#endif + ) { + uint32_t nr_l2, nr_sc, j; + uint64_t core_mask; + + nr_l2 = hand->kbdev->gpu_props.props.l2_props.num_l2_slices; + + core_mask = hand->kbdev->gpu_props.props.coherency_info.group[0].core_mask; + + nr_sc = hand->kbdev->gpu_props.props.coherency_info.group[0].num_cores; + + /* For Mali-T76x, the job manager and tiler sets of counters are always present */ + in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc + nr_l2), GFP_KERNEL); + + if (!in_out_info->hwc_layout) + goto destroy_context; + + dump_size = (2 + nr_sc + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER; + + in_out_info->hwc_layout[i++] = JM_BLOCK; + in_out_info->hwc_layout[i++] = TILER_BLOCK; + + for (j = 0; j < nr_l2; j++) + in_out_info->hwc_layout[i++] = MMU_L2_BLOCK; + + while (core_mask != 0ull) { + if ((core_mask & 1ull) != 0ull) + in_out_info->hwc_layout[i++] = SHADER_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + core_mask >>= 1; + } + } + + in_out_info->nr_hwc_blocks = i; + + in_out_info->size = dump_size; + + flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_WR; + nr_pages = PFN_UP(dump_size); + reg = kbase_mem_alloc(hand->kctx, nr_pages, nr_pages, 0, + &flags, &hand->hwcnt_gpu_va, &va_alignment); + if (!reg) + goto free_layout; + + hand->hwcnt_cpu_va = kbase_vmap(hand->kctx, hand->hwcnt_gpu_va, + dump_size, &hand->hwcnt_map); + + if (!hand->hwcnt_cpu_va) + goto free_buffer; + + in_out_info->kernel_dump_buffer = hand->hwcnt_cpu_va; + + /*setup.dump_buffer = (uintptr_t)in_out_info->kernel_dump_buffer;*/ + setup.dump_buffer = hand->hwcnt_gpu_va; + setup.jm_bm = in_out_info->bitmask[0]; + setup.tiler_bm = in_out_info->bitmask[1]; + setup.shader_bm = in_out_info->bitmask[2]; + setup.mmu_l2_bm = in_out_info->bitmask[3]; + + /* There are no implementations with L3 cache */ + setup.l3_cache_bm = 0; + + err = kbase_instr_hwcnt_enable(hand->kctx, &setup); + if (err != MALI_ERROR_NONE) + goto free_unmap; + + kbase_instr_hwcnt_clear(hand->kctx); + + return hand; + +free_unmap: + kbase_vunmap(hand->kctx, &hand->hwcnt_map); + +free_buffer: + kbase_mem_free(hand->kctx, hand->hwcnt_gpu_va); + +free_layout: + kfree(in_out_info->hwc_layout); + +destroy_context: + kbase_destroy_context(hand->kctx); + +release_device: + kbase_release_device(hand->kbdev); + +free_hand: + kfree(hand); + + return NULL; +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init) + +void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles) +{ + if (in_out_info) + kfree(in_out_info->hwc_layout); + + if (opaque_handles) { + kbase_instr_hwcnt_disable(opaque_handles->kctx); + kbase_vunmap(opaque_handles->kctx, &opaque_handles->hwcnt_map); + kbase_mem_free(opaque_handles->kctx, opaque_handles->hwcnt_gpu_va); + kbase_destroy_context(opaque_handles->kctx); + kbase_release_device(opaque_handles->kbdev); + kfree(opaque_handles); + } +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term) + +uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success) +{ + if (opaque_handles && success) + return (kbase_instr_hwcnt_dump_complete(opaque_handles->kctx, success) != 0); + return 0; +} +KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_complete) + +uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles) +{ + if (opaque_handles) + return (kbase_instr_hwcnt_dump_irq(opaque_handles->kctx) == MALI_ERROR_NONE); + return 0; +} +KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_irq) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.h new file mode 100644 index 0000000000000000000000000000000000000000..13c44c816856cb5c363e951101870d2f839f40f4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.h @@ -0,0 +1,219 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_GATOR_API_H_ +#define _KBASE_GATOR_API_H_ + +/** + * @brief This file describes the API used by Gator to collect hardware counters data from a Mali device. + */ + +/* This define is used by the gator kernel module compile to select which DDK + * API calling convention to use. If not defined (legacy DDK) gator assumes + * version 1. The version to DDK release mapping is: + * Version 1 API: DDK versions r1px, r2px + * Version 2 API: DDK versions r3px, r4px + * Version 3 API: DDK version r5p0 and newer + * + * API Usage + * ========= + * + * 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter + * names for the GPU present in this device. + * + * 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for + * the counters you want enabled. The enables can all be set for simplicity in + * most use cases, but disabling some will let you minimize bandwidth impact. + * + * 3] Call kbase_gator_hwcnt_init() using the above structure, to create a + * counter context. On successful return the DDK will have populated the + * structure with a variety of useful information. + * + * 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a + * counter dump. If this returns a non-zero value the request has been queued, + * otherwise the driver has been unable to do so (typically because of another + * user of the instrumentation exists concurrently). + * + * 5] Call kbase_gator_hwcnt_dump_complete() to test whether the previously + * requested dump has been succesful. If this returns non-zero the counter dump + * has resolved, but the value of *success must also be tested as the dump + * may have not been successful. If it returns zero the counter dump was + * abandoned due to the device being busy (typically because of another + * user of the instrumentation exists concurrently). + * + * 6] Process the counters stored in the buffer pointed to by ... + * + * kbase_gator_hwcnt_info->kernel_dump_buffer + * + * In pseudo code you can find all of the counters via this approach: + * + * + * hwcnt_info # pointer to kbase_gator_hwcnt_info structure + * hwcnt_name # pointer to name list + * + * u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer + * + * # Iterate over each 64-counter block in this GPU configuration + * for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) { + * hwc_type type = hwcnt_info->hwc_layout[i]; + * + * # Skip reserved type blocks - they contain no counters at all + * if( type == RESERVED_BLOCK ) { + * continue; + * } + * + * size_t name_offset = type * 64; + * size_t data_offset = i * 64; + * + * # Iterate over the names of the counters in this block type + * for( j = 0; j < 64; j++) { + * const char * name = hwcnt_name[name_offset+j]; + * + * # Skip empty name strings - there is no counter here + * if( name[0] == '\0' ) { + * continue; + * } + * + * u32 data = hwcnt_data[data_offset+j]; + * + * pr_debug( "COUNTER: %s DATA: %u\n", name, data ); + * } + * } + * + * + * Note that in most implementations you typically want to either SUM or + * AVERAGE multiple instances of the same counter if, for example, you have + * multiple shader cores or multiple L2 caches. The most sensible view for + * analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU + * counters. + * + * 7] Goto 4, repeating until you want to stop collecting counters. + * + * 8] Release the dump resources by calling kbase_gator_hwcnt_term(). + * + * 9] Release the name table resources by calling kbase_gator_hwcnt_term_names(). + * This function must only be called if init_names() returned a non-NULL value. + **/ + +#define MALI_DDK_GATOR_API_VERSION 3 + +enum hwc_type { + JM_BLOCK = 0, + TILER_BLOCK, + SHADER_BLOCK, + MMU_L2_BLOCK, + RESERVED_BLOCK +}; + +struct kbase_gator_hwcnt_info { + + /* Passed from Gator to kbase */ + + /* the bitmask of enabled hardware counters for each counter block */ + uint16_t bitmask[4]; + + /* Passed from kbase to Gator */ + + /* ptr to counter dump memory */ + void *kernel_dump_buffer; + + /* size of counter dump memory */ + uint32_t size; + + /* the ID of the Mali device */ + uint32_t gpu_id; + + /* the number of shader cores in the GPU */ + uint32_t nr_cores; + + /* the number of core groups */ + uint32_t nr_core_groups; + + /* the memory layout of the performance counters */ + enum hwc_type *hwc_layout; + + /* the total number of hardware couter blocks */ + uint32_t nr_hwc_blocks; +}; + +/** + * @brief Opaque block of Mali data which Gator needs to return to the API later. + */ +struct kbase_gator_hwcnt_handles; + +/** + * @brief Initialize the resources Gator needs for performance profiling. + * + * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the Mali + * specific information that will be returned to Gator. On entry Gator must have populated the + * 'bitmask' field with the counters it wishes to enable for each class of counter block. + * Each entry in the array corresponds to a single counter class based on the "hwc_type" + * enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables + * the first 4 counters in the block, and so on). See the GPU counter array as returned by + * kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU. + * + * @return Pointer to an opaque handle block on success, NULL on error. + */ +extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info); + +/** + * @brief Free all resources once Gator has finished using performance counters. + * + * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the + * Mali specific information that will be returned to Gator. + * @param opaque_handles A wrapper structure for kbase structures. + */ +extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles); + +/** + * @brief Poll whether a counter dump is successful. + * + * @param opaque_handles A wrapper structure for kbase structures. + * @param[out] success Non-zero on success, zero on failure. + * + * @return Zero if the dump is still pending, non-zero if the dump has completed. Note that a + * completed dump may not have dumped succesfully, so the caller must test for both + * a completed and successful dump before processing counters. + */ +extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success); + +/** + * @brief Request the generation of a new counter dump. + * + * @param opaque_handles A wrapper structure for kbase structures. + * + * @return Zero if the hardware device is busy and cannot handle the request, non-zero otherwise. + */ +extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles); + +/** + * @brief This function is used to fetch the names table based on the Mali device in use. + * + * @param[out] total_number_of_counters The total number of counters short names in the Mali devices' list. + * + * @return Pointer to an array of strings of length *total_number_of_counters. + */ +extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters); + +/** + * @brief This function is used to terminate the use of the names table. + * + * This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value. + */ +extern void kbase_gator_hwcnt_term_names(void); + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_hwcnt_names.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_hwcnt_names.h new file mode 100644 index 0000000000000000000000000000000000000000..c68daab5873e4bdb6bd8f48225e9a48e3510a252 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_hwcnt_names.h @@ -0,0 +1,1627 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_GATOR_HWCNT_NAMES_H_ +#define _KBASE_GATOR_HWCNT_NAMES_H_ + +/* + * "Short names" for hardware counters used by Streamline. Counters names are + * stored in accordance with their memory layout in the binary counter block + * emitted by the Mali GPU. Each "master" in the GPU emits a fixed-size block + * of 64 counters, and each GPU implements the same set of "masters" although + * the counters each master exposes within its block of 64 may vary. + * + * Counters which are an empty string are simply "holes" in the counter memory + * where no counter exists. + */ + +static const char * const hardware_counters_mali_t60x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T60x_MESSAGES_SENT", + "T60x_MESSAGES_RECEIVED", + "T60x_GPU_ACTIVE", + "T60x_IRQ_ACTIVE", + "T60x_JS0_JOBS", + "T60x_JS0_TASKS", + "T60x_JS0_ACTIVE", + "", + "T60x_JS0_WAIT_READ", + "T60x_JS0_WAIT_ISSUE", + "T60x_JS0_WAIT_DEPEND", + "T60x_JS0_WAIT_FINISH", + "T60x_JS1_JOBS", + "T60x_JS1_TASKS", + "T60x_JS1_ACTIVE", + "", + "T60x_JS1_WAIT_READ", + "T60x_JS1_WAIT_ISSUE", + "T60x_JS1_WAIT_DEPEND", + "T60x_JS1_WAIT_FINISH", + "T60x_JS2_JOBS", + "T60x_JS2_TASKS", + "T60x_JS2_ACTIVE", + "", + "T60x_JS2_WAIT_READ", + "T60x_JS2_WAIT_ISSUE", + "T60x_JS2_WAIT_DEPEND", + "T60x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T60x_TI_JOBS_PROCESSED", + "T60x_TI_TRIANGLES", + "T60x_TI_QUADS", + "T60x_TI_POLYGONS", + "T60x_TI_POINTS", + "T60x_TI_LINES", + "T60x_TI_VCACHE_HIT", + "T60x_TI_VCACHE_MISS", + "T60x_TI_FRONT_FACING", + "T60x_TI_BACK_FACING", + "T60x_TI_PRIM_VISIBLE", + "T60x_TI_PRIM_CULLED", + "T60x_TI_PRIM_CLIPPED", + "T60x_TI_LEVEL0", + "T60x_TI_LEVEL1", + "T60x_TI_LEVEL2", + "T60x_TI_LEVEL3", + "T60x_TI_LEVEL4", + "T60x_TI_LEVEL5", + "T60x_TI_LEVEL6", + "T60x_TI_LEVEL7", + "T60x_TI_COMMAND_1", + "T60x_TI_COMMAND_2", + "T60x_TI_COMMAND_3", + "T60x_TI_COMMAND_4", + "T60x_TI_COMMAND_4_7", + "T60x_TI_COMMAND_8_15", + "T60x_TI_COMMAND_16_63", + "T60x_TI_COMMAND_64", + "T60x_TI_COMPRESS_IN", + "T60x_TI_COMPRESS_OUT", + "T60x_TI_COMPRESS_FLUSH", + "T60x_TI_TIMESTAMPS", + "T60x_TI_PCACHE_HIT", + "T60x_TI_PCACHE_MISS", + "T60x_TI_PCACHE_LINE", + "T60x_TI_PCACHE_STALL", + "T60x_TI_WRBUF_HIT", + "T60x_TI_WRBUF_MISS", + "T60x_TI_WRBUF_LINE", + "T60x_TI_WRBUF_PARTIAL", + "T60x_TI_WRBUF_STALL", + "T60x_TI_ACTIVE", + "T60x_TI_LOADING_DESC", + "T60x_TI_INDEX_WAIT", + "T60x_TI_INDEX_RANGE_WAIT", + "T60x_TI_VERTEX_WAIT", + "T60x_TI_PCACHE_WAIT", + "T60x_TI_WRBUF_WAIT", + "T60x_TI_BUS_READ", + "T60x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T60x_TI_UTLB_STALL", + "T60x_TI_UTLB_REPLAY_MISS", + "T60x_TI_UTLB_REPLAY_FULL", + "T60x_TI_UTLB_NEW_MISS", + "T60x_TI_UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "", + "T60x_FRAG_ACTIVE", + "T60x_FRAG_PRIMITIVES", + "T60x_FRAG_PRIMITIVES_DROPPED", + "T60x_FRAG_CYCLES_DESC", + "T60x_FRAG_CYCLES_PLR", + "T60x_FRAG_CYCLES_VERT", + "T60x_FRAG_CYCLES_TRISETUP", + "T60x_FRAG_CYCLES_RAST", + "T60x_FRAG_THREADS", + "T60x_FRAG_DUMMY_THREADS", + "T60x_FRAG_QUADS_RAST", + "T60x_FRAG_QUADS_EZS_TEST", + "T60x_FRAG_QUADS_EZS_KILLED", + "T60x_FRAG_THREADS_LZS_TEST", + "T60x_FRAG_THREADS_LZS_KILLED", + "T60x_FRAG_CYCLES_NO_TILE", + "T60x_FRAG_NUM_TILES", + "T60x_FRAG_TRANS_ELIM", + "T60x_COMPUTE_ACTIVE", + "T60x_COMPUTE_TASKS", + "T60x_COMPUTE_THREADS", + "T60x_COMPUTE_CYCLES_DESC", + "T60x_TRIPIPE_ACTIVE", + "T60x_ARITH_WORDS", + "T60x_ARITH_CYCLES_REG", + "T60x_ARITH_CYCLES_L0", + "T60x_ARITH_FRAG_DEPEND", + "T60x_LS_WORDS", + "T60x_LS_ISSUES", + "T60x_LS_RESTARTS", + "T60x_LS_REISSUES_MISS", + "T60x_LS_REISSUES_VD", + "T60x_LS_REISSUE_ATTRIB_MISS", + "T60x_LS_NO_WB", + "T60x_TEX_WORDS", + "T60x_TEX_BUBBLES", + "T60x_TEX_WORDS_L0", + "T60x_TEX_WORDS_DESC", + "T60x_TEX_ISSUES", + "T60x_TEX_RECIRC_FMISS", + "T60x_TEX_RECIRC_DESC", + "T60x_TEX_RECIRC_MULTI", + "T60x_TEX_RECIRC_PMISS", + "T60x_TEX_RECIRC_CONF", + "T60x_LSC_READ_HITS", + "T60x_LSC_READ_MISSES", + "T60x_LSC_WRITE_HITS", + "T60x_LSC_WRITE_MISSES", + "T60x_LSC_ATOMIC_HITS", + "T60x_LSC_ATOMIC_MISSES", + "T60x_LSC_LINE_FETCHES", + "T60x_LSC_DIRTY_LINE", + "T60x_LSC_SNOOPS", + "T60x_AXI_TLB_STALL", + "T60x_AXI_TLB_MIESS", + "T60x_AXI_TLB_TRANSACTION", + "T60x_LS_TLB_MISS", + "T60x_LS_TLB_HIT", + "T60x_AXI_BEATS_READ", + "T60x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T60x_MMU_HIT", + "T60x_MMU_NEW_MISS", + "T60x_MMU_REPLAY_FULL", + "T60x_MMU_REPLAY_MISS", + "T60x_MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "T60x_UTLB_HIT", + "T60x_UTLB_NEW_MISS", + "T60x_UTLB_REPLAY_FULL", + "T60x_UTLB_REPLAY_MISS", + "T60x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T60x_L2_EXT_WRITE_BEATS", + "T60x_L2_EXT_READ_BEATS", + "T60x_L2_ANY_LOOKUP", + "T60x_L2_READ_LOOKUP", + "T60x_L2_SREAD_LOOKUP", + "T60x_L2_READ_REPLAY", + "T60x_L2_READ_SNOOP", + "T60x_L2_READ_HIT", + "T60x_L2_CLEAN_MISS", + "T60x_L2_WRITE_LOOKUP", + "T60x_L2_SWRITE_LOOKUP", + "T60x_L2_WRITE_REPLAY", + "T60x_L2_WRITE_SNOOP", + "T60x_L2_WRITE_HIT", + "T60x_L2_EXT_READ_FULL", + "T60x_L2_EXT_READ_HALF", + "T60x_L2_EXT_WRITE_FULL", + "T60x_L2_EXT_WRITE_HALF", + "T60x_L2_EXT_READ", + "T60x_L2_EXT_READ_LINE", + "T60x_L2_EXT_WRITE", + "T60x_L2_EXT_WRITE_LINE", + "T60x_L2_EXT_WRITE_SMALL", + "T60x_L2_EXT_BARRIER", + "T60x_L2_EXT_AR_STALL", + "T60x_L2_EXT_R_BUF_FULL", + "T60x_L2_EXT_RD_BUF_FULL", + "T60x_L2_EXT_R_RAW", + "T60x_L2_EXT_W_STALL", + "T60x_L2_EXT_W_BUF_FULL", + "T60x_L2_EXT_R_W_HAZARD", + "T60x_L2_TAG_HAZARD", + "T60x_L2_SNOOP_FULL", + "T60x_L2_REPLAY_FULL" +}; +static const char * const hardware_counters_mali_t62x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T62x_MESSAGES_SENT", + "T62x_MESSAGES_RECEIVED", + "T62x_GPU_ACTIVE", + "T62x_IRQ_ACTIVE", + "T62x_JS0_JOBS", + "T62x_JS0_TASKS", + "T62x_JS0_ACTIVE", + "", + "T62x_JS0_WAIT_READ", + "T62x_JS0_WAIT_ISSUE", + "T62x_JS0_WAIT_DEPEND", + "T62x_JS0_WAIT_FINISH", + "T62x_JS1_JOBS", + "T62x_JS1_TASKS", + "T62x_JS1_ACTIVE", + "", + "T62x_JS1_WAIT_READ", + "T62x_JS1_WAIT_ISSUE", + "T62x_JS1_WAIT_DEPEND", + "T62x_JS1_WAIT_FINISH", + "T62x_JS2_JOBS", + "T62x_JS2_TASKS", + "T62x_JS2_ACTIVE", + "", + "T62x_JS2_WAIT_READ", + "T62x_JS2_WAIT_ISSUE", + "T62x_JS2_WAIT_DEPEND", + "T62x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T62x_TI_JOBS_PROCESSED", + "T62x_TI_TRIANGLES", + "T62x_TI_QUADS", + "T62x_TI_POLYGONS", + "T62x_TI_POINTS", + "T62x_TI_LINES", + "T62x_TI_VCACHE_HIT", + "T62x_TI_VCACHE_MISS", + "T62x_TI_FRONT_FACING", + "T62x_TI_BACK_FACING", + "T62x_TI_PRIM_VISIBLE", + "T62x_TI_PRIM_CULLED", + "T62x_TI_PRIM_CLIPPED", + "T62x_TI_LEVEL0", + "T62x_TI_LEVEL1", + "T62x_TI_LEVEL2", + "T62x_TI_LEVEL3", + "T62x_TI_LEVEL4", + "T62x_TI_LEVEL5", + "T62x_TI_LEVEL6", + "T62x_TI_LEVEL7", + "T62x_TI_COMMAND_1", + "T62x_TI_COMMAND_2", + "T62x_TI_COMMAND_3", + "T62x_TI_COMMAND_4", + "T62x_TI_COMMAND_5_7", + "T62x_TI_COMMAND_8_15", + "T62x_TI_COMMAND_16_63", + "T62x_TI_COMMAND_64", + "T62x_TI_COMPRESS_IN", + "T62x_TI_COMPRESS_OUT", + "T62x_TI_COMPRESS_FLUSH", + "T62x_TI_TIMESTAMPS", + "T62x_TI_PCACHE_HIT", + "T62x_TI_PCACHE_MISS", + "T62x_TI_PCACHE_LINE", + "T62x_TI_PCACHE_STALL", + "T62x_TI_WRBUF_HIT", + "T62x_TI_WRBUF_MISS", + "T62x_TI_WRBUF_LINE", + "T62x_TI_WRBUF_PARTIAL", + "T62x_TI_WRBUF_STALL", + "T62x_TI_ACTIVE", + "T62x_TI_LOADING_DESC", + "T62x_TI_INDEX_WAIT", + "T62x_TI_INDEX_RANGE_WAIT", + "T62x_TI_VERTEX_WAIT", + "T62x_TI_PCACHE_WAIT", + "T62x_TI_WRBUF_WAIT", + "T62x_TI_BUS_READ", + "T62x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T62x_TI_UTLB_STALL", + "T62x_TI_UTLB_REPLAY_MISS", + "T62x_TI_UTLB_REPLAY_FULL", + "T62x_TI_UTLB_NEW_MISS", + "T62x_TI_UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "T62x_SHADER_CORE_ACTIVE", + "T62x_FRAG_ACTIVE", + "T62x_FRAG_PRIMITIVES", + "T62x_FRAG_PRIMITIVES_DROPPED", + "T62x_FRAG_CYCLES_DESC", + "T62x_FRAG_CYCLES_FPKQ_ACTIVE", + "T62x_FRAG_CYCLES_VERT", + "T62x_FRAG_CYCLES_TRISETUP", + "T62x_FRAG_CYCLES_EZS_ACTIVE", + "T62x_FRAG_THREADS", + "T62x_FRAG_DUMMY_THREADS", + "T62x_FRAG_QUADS_RAST", + "T62x_FRAG_QUADS_EZS_TEST", + "T62x_FRAG_QUADS_EZS_KILLED", + "T62x_FRAG_THREADS_LZS_TEST", + "T62x_FRAG_THREADS_LZS_KILLED", + "T62x_FRAG_CYCLES_NO_TILE", + "T62x_FRAG_NUM_TILES", + "T62x_FRAG_TRANS_ELIM", + "T62x_COMPUTE_ACTIVE", + "T62x_COMPUTE_TASKS", + "T62x_COMPUTE_THREADS", + "T62x_COMPUTE_CYCLES_DESC", + "T62x_TRIPIPE_ACTIVE", + "T62x_ARITH_WORDS", + "T62x_ARITH_CYCLES_REG", + "T62x_ARITH_CYCLES_L0", + "T62x_ARITH_FRAG_DEPEND", + "T62x_LS_WORDS", + "T62x_LS_ISSUES", + "T62x_LS_RESTARTS", + "T62x_LS_REISSUES_MISS", + "T62x_LS_REISSUES_VD", + "T62x_LS_REISSUE_ATTRIB_MISS", + "T62x_LS_NO_WB", + "T62x_TEX_WORDS", + "T62x_TEX_BUBBLES", + "T62x_TEX_WORDS_L0", + "T62x_TEX_WORDS_DESC", + "T62x_TEX_ISSUES", + "T62x_TEX_RECIRC_FMISS", + "T62x_TEX_RECIRC_DESC", + "T62x_TEX_RECIRC_MULTI", + "T62x_TEX_RECIRC_PMISS", + "T62x_TEX_RECIRC_CONF", + "T62x_LSC_READ_HITS", + "T62x_LSC_READ_MISSES", + "T62x_LSC_WRITE_HITS", + "T62x_LSC_WRITE_MISSES", + "T62x_LSC_ATOMIC_HITS", + "T62x_LSC_ATOMIC_MISSES", + "T62x_LSC_LINE_FETCHES", + "T62x_LSC_DIRTY_LINE", + "T62x_LSC_SNOOPS", + "T62x_AXI_TLB_STALL", + "T62x_AXI_TLB_MIESS", + "T62x_AXI_TLB_TRANSACTION", + "T62x_LS_TLB_MISS", + "T62x_LS_TLB_HIT", + "T62x_AXI_BEATS_READ", + "T62x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T62x_MMU_HIT", + "T62x_MMU_NEW_MISS", + "T62x_MMU_REPLAY_FULL", + "T62x_MMU_REPLAY_MISS", + "T62x_MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "T62x_UTLB_HIT", + "T62x_UTLB_NEW_MISS", + "T62x_UTLB_REPLAY_FULL", + "T62x_UTLB_REPLAY_MISS", + "T62x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T62x_L2_EXT_WRITE_BEATS", + "T62x_L2_EXT_READ_BEATS", + "T62x_L2_ANY_LOOKUP", + "T62x_L2_READ_LOOKUP", + "T62x_L2_SREAD_LOOKUP", + "T62x_L2_READ_REPLAY", + "T62x_L2_READ_SNOOP", + "T62x_L2_READ_HIT", + "T62x_L2_CLEAN_MISS", + "T62x_L2_WRITE_LOOKUP", + "T62x_L2_SWRITE_LOOKUP", + "T62x_L2_WRITE_REPLAY", + "T62x_L2_WRITE_SNOOP", + "T62x_L2_WRITE_HIT", + "T62x_L2_EXT_READ_FULL", + "T62x_L2_EXT_READ_HALF", + "T62x_L2_EXT_WRITE_FULL", + "T62x_L2_EXT_WRITE_HALF", + "T62x_L2_EXT_READ", + "T62x_L2_EXT_READ_LINE", + "T62x_L2_EXT_WRITE", + "T62x_L2_EXT_WRITE_LINE", + "T62x_L2_EXT_WRITE_SMALL", + "T62x_L2_EXT_BARRIER", + "T62x_L2_EXT_AR_STALL", + "T62x_L2_EXT_R_BUF_FULL", + "T62x_L2_EXT_RD_BUF_FULL", + "T62x_L2_EXT_R_RAW", + "T62x_L2_EXT_W_STALL", + "T62x_L2_EXT_W_BUF_FULL", + "T62x_L2_EXT_R_W_HAZARD", + "T62x_L2_TAG_HAZARD", + "T62x_L2_SNOOP_FULL", + "T62x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t72x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T72x_GPU_ACTIVE", + "T72x_IRQ_ACTIVE", + "T72x_JS0_JOBS", + "T72x_JS0_TASKS", + "T72x_JS0_ACTIVE", + "T72x_JS1_JOBS", + "T72x_JS1_TASKS", + "T72x_JS1_ACTIVE", + "T72x_JS2_JOBS", + "T72x_JS2_TASKS", + "T72x_JS2_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T72x_TI_JOBS_PROCESSED", + "T72x_TI_TRIANGLES", + "T72x_TI_QUADS", + "T72x_TI_POLYGONS", + "T72x_TI_POINTS", + "T72x_TI_LINES", + "T72x_TI_FRONT_FACING", + "T72x_TI_BACK_FACING", + "T72x_TI_PRIM_VISIBLE", + "T72x_TI_PRIM_CULLED", + "T72x_TI_PRIM_CLIPPED", + "", + "", + "", + "", + "", + "", + "", + "", + "T72x_TI_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Shader Core */ + "", + "", + "", + "", + "T72x_FRAG_ACTIVE", + "T72x_FRAG_PRIMITIVES", + "T72x_FRAG_PRIMITIVES_DROPPED", + "T72x_FRAG_THREADS", + "T72x_FRAG_DUMMY_THREADS", + "T72x_FRAG_QUADS_RAST", + "T72x_FRAG_QUADS_EZS_TEST", + "T72x_FRAG_QUADS_EZS_KILLED", + "T72x_FRAG_THREADS_LZS_TEST", + "T72x_FRAG_THREADS_LZS_KILLED", + "T72x_FRAG_CYCLES_NO_TILE", + "T72x_FRAG_NUM_TILES", + "T72x_FRAG_TRANS_ELIM", + "T72x_COMPUTE_ACTIVE", + "T72x_COMPUTE_TASKS", + "T72x_COMPUTE_THREADS", + "T72x_TRIPIPE_ACTIVE", + "T72x_ARITH_WORDS", + "T72x_ARITH_CYCLES_REG", + "T72x_LS_WORDS", + "T72x_LS_ISSUES", + "T72x_LS_RESTARTS", + "T72x_LS_REISSUES_MISS", + "T72x_TEX_WORDS", + "T72x_TEX_BUBBLES", + "T72x_TEX_ISSUES", + "T72x_LSC_READ_HITS", + "T72x_LSC_READ_MISSES", + "T72x_LSC_WRITE_HITS", + "T72x_LSC_WRITE_MISSES", + "T72x_LSC_ATOMIC_HITS", + "T72x_LSC_ATOMIC_MISSES", + "T72x_LSC_LINE_FETCHES", + "T72x_LSC_DIRTY_LINE", + "T72x_LSC_SNOOPS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*L2 and MMU */ + "", + "", + "", + "", + "T72x_L2_EXT_WRITE_BEAT", + "T72x_L2_EXT_READ_BEAT", + "T72x_L2_READ_SNOOP", + "T72x_L2_READ_HIT", + "T72x_L2_WRITE_SNOOP", + "T72x_L2_WRITE_HIT", + "T72x_L2_EXT_WRITE_SMALL", + "T72x_L2_EXT_BARRIER", + "T72x_L2_EXT_AR_STALL", + "T72x_L2_EXT_W_STALL", + "T72x_L2_SNOOP_FULL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" +}; + +static const char * const hardware_counters_mali_t76x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T76x_MESSAGES_SENT", + "T76x_MESSAGES_RECEIVED", + "T76x_GPU_ACTIVE", + "T76x_IRQ_ACTIVE", + "T76x_JS0_JOBS", + "T76x_JS0_TASKS", + "T76x_JS0_ACTIVE", + "", + "T76x_JS0_WAIT_READ", + "T76x_JS0_WAIT_ISSUE", + "T76x_JS0_WAIT_DEPEND", + "T76x_JS0_WAIT_FINISH", + "T76x_JS1_JOBS", + "T76x_JS1_TASKS", + "T76x_JS1_ACTIVE", + "", + "T76x_JS1_WAIT_READ", + "T76x_JS1_WAIT_ISSUE", + "T76x_JS1_WAIT_DEPEND", + "T76x_JS1_WAIT_FINISH", + "T76x_JS2_JOBS", + "T76x_JS2_TASKS", + "T76x_JS2_ACTIVE", + "", + "T76x_JS2_WAIT_READ", + "T76x_JS2_WAIT_ISSUE", + "T76x_JS2_WAIT_DEPEND", + "T76x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T76x_TI_JOBS_PROCESSED", + "T76x_TI_TRIANGLES", + "T76x_TI_QUADS", + "T76x_TI_POLYGONS", + "T76x_TI_POINTS", + "T76x_TI_LINES", + "T76x_TI_VCACHE_HIT", + "T76x_TI_VCACHE_MISS", + "T76x_TI_FRONT_FACING", + "T76x_TI_BACK_FACING", + "T76x_TI_PRIM_VISIBLE", + "T76x_TI_PRIM_CULLED", + "T76x_TI_PRIM_CLIPPED", + "T76x_TI_LEVEL0", + "T76x_TI_LEVEL1", + "T76x_TI_LEVEL2", + "T76x_TI_LEVEL3", + "T76x_TI_LEVEL4", + "T76x_TI_LEVEL5", + "T76x_TI_LEVEL6", + "T76x_TI_LEVEL7", + "T76x_TI_COMMAND_1", + "T76x_TI_COMMAND_2", + "T76x_TI_COMMAND_3", + "T76x_TI_COMMAND_4", + "T76x_TI_COMMAND_5_7", + "T76x_TI_COMMAND_8_15", + "T76x_TI_COMMAND_16_63", + "T76x_TI_COMMAND_64", + "T76x_TI_COMPRESS_IN", + "T76x_TI_COMPRESS_OUT", + "T76x_TI_COMPRESS_FLUSH", + "T76x_TI_TIMESTAMPS", + "T76x_TI_PCACHE_HIT", + "T76x_TI_PCACHE_MISS", + "T76x_TI_PCACHE_LINE", + "T76x_TI_PCACHE_STALL", + "T76x_TI_WRBUF_HIT", + "T76x_TI_WRBUF_MISS", + "T76x_TI_WRBUF_LINE", + "T76x_TI_WRBUF_PARTIAL", + "T76x_TI_WRBUF_STALL", + "T76x_TI_ACTIVE", + "T76x_TI_LOADING_DESC", + "T76x_TI_INDEX_WAIT", + "T76x_TI_INDEX_RANGE_WAIT", + "T76x_TI_VERTEX_WAIT", + "T76x_TI_PCACHE_WAIT", + "T76x_TI_WRBUF_WAIT", + "T76x_TI_BUS_READ", + "T76x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T76x_TI_UTLB_HIT", + "T76x_TI_UTLB_NEW_MISS", + "T76x_TI_UTLB_REPLAY_FULL", + "T76x_TI_UTLB_REPLAY_MISS", + "T76x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T76x_FRAG_ACTIVE", + "T76x_FRAG_PRIMITIVES", + "T76x_FRAG_PRIMITIVES_DROPPED", + "T76x_FRAG_CYCLES_DESC", + "T76x_FRAG_CYCLES_FPKQ_ACTIVE", + "T76x_FRAG_CYCLES_VERT", + "T76x_FRAG_CYCLES_TRISETUP", + "T76x_FRAG_CYCLES_EZS_ACTIVE", + "T76x_FRAG_THREADS", + "T76x_FRAG_DUMMY_THREADS", + "T76x_FRAG_QUADS_RAST", + "T76x_FRAG_QUADS_EZS_TEST", + "T76x_FRAG_QUADS_EZS_KILLED", + "T76x_FRAG_THREADS_LZS_TEST", + "T76x_FRAG_THREADS_LZS_KILLED", + "T76x_FRAG_CYCLES_NO_TILE", + "T76x_FRAG_NUM_TILES", + "T76x_FRAG_TRANS_ELIM", + "T76x_COMPUTE_ACTIVE", + "T76x_COMPUTE_TASKS", + "T76x_COMPUTE_THREADS", + "T76x_COMPUTE_CYCLES_DESC", + "T76x_TRIPIPE_ACTIVE", + "T76x_ARITH_WORDS", + "T76x_ARITH_CYCLES_REG", + "T76x_ARITH_CYCLES_L0", + "T76x_ARITH_FRAG_DEPEND", + "T76x_LS_WORDS", + "T76x_LS_ISSUES", + "T76x_LS_REISSUE_ATTR", + "T76x_LS_REISSUES_VARY", + "T76x_LS_VARY_RV_MISS", + "T76x_LS_VARY_RV_HIT", + "T76x_LS_NO_UNPARK", + "T76x_TEX_WORDS", + "T76x_TEX_BUBBLES", + "T76x_TEX_WORDS_L0", + "T76x_TEX_WORDS_DESC", + "T76x_TEX_ISSUES", + "T76x_TEX_RECIRC_FMISS", + "T76x_TEX_RECIRC_DESC", + "T76x_TEX_RECIRC_MULTI", + "T76x_TEX_RECIRC_PMISS", + "T76x_TEX_RECIRC_CONF", + "T76x_LSC_READ_HITS", + "T76x_LSC_READ_OP", + "T76x_LSC_WRITE_HITS", + "T76x_LSC_WRITE_OP", + "T76x_LSC_ATOMIC_HITS", + "T76x_LSC_ATOMIC_OP", + "T76x_LSC_LINE_FETCHES", + "T76x_LSC_DIRTY_LINE", + "T76x_LSC_SNOOPS", + "T76x_AXI_TLB_STALL", + "T76x_AXI_TLB_MIESS", + "T76x_AXI_TLB_TRANSACTION", + "T76x_LS_TLB_MISS", + "T76x_LS_TLB_HIT", + "T76x_AXI_BEATS_READ", + "T76x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T76x_MMU_HIT", + "T76x_MMU_NEW_MISS", + "T76x_MMU_REPLAY_FULL", + "T76x_MMU_REPLAY_MISS", + "T76x_MMU_TABLE_WALK", + "T76x_MMU_REQUESTS", + "", + "", + "T76x_UTLB_HIT", + "T76x_UTLB_NEW_MISS", + "T76x_UTLB_REPLAY_FULL", + "T76x_UTLB_REPLAY_MISS", + "T76x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T76x_L2_EXT_WRITE_BEATS", + "T76x_L2_EXT_READ_BEATS", + "T76x_L2_ANY_LOOKUP", + "T76x_L2_READ_LOOKUP", + "T76x_L2_SREAD_LOOKUP", + "T76x_L2_READ_REPLAY", + "T76x_L2_READ_SNOOP", + "T76x_L2_READ_HIT", + "T76x_L2_CLEAN_MISS", + "T76x_L2_WRITE_LOOKUP", + "T76x_L2_SWRITE_LOOKUP", + "T76x_L2_WRITE_REPLAY", + "T76x_L2_WRITE_SNOOP", + "T76x_L2_WRITE_HIT", + "T76x_L2_EXT_READ_FULL", + "", + "T76x_L2_EXT_WRITE_FULL", + "T76x_L2_EXT_R_W_HAZARD", + "T76x_L2_EXT_READ", + "T76x_L2_EXT_READ_LINE", + "T76x_L2_EXT_WRITE", + "T76x_L2_EXT_WRITE_LINE", + "T76x_L2_EXT_WRITE_SMALL", + "T76x_L2_EXT_BARRIER", + "T76x_L2_EXT_AR_STALL", + "T76x_L2_EXT_R_BUF_FULL", + "T76x_L2_EXT_RD_BUF_FULL", + "T76x_L2_EXT_R_RAW", + "T76x_L2_EXT_W_STALL", + "T76x_L2_EXT_W_BUF_FULL", + "T76x_L2_EXT_R_BUF_FULL", + "T76x_L2_TAG_HAZARD", + "T76x_L2_SNOOP_FULL", + "T76x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t86x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T86x_MESSAGES_SENT", + "T86x_MESSAGES_RECEIVED", + "T86x_GPU_ACTIVE", + "T86x_IRQ_ACTIVE", + "T86x_JS0_JOBS", + "T86x_JS0_TASKS", + "T86x_JS0_ACTIVE", + "", + "T86x_JS0_WAIT_READ", + "T86x_JS0_WAIT_ISSUE", + "T86x_JS0_WAIT_DEPEND", + "T86x_JS0_WAIT_FINISH", + "T86x_JS1_JOBS", + "T86x_JS1_TASKS", + "T86x_JS1_ACTIVE", + "", + "T86x_JS1_WAIT_READ", + "T86x_JS1_WAIT_ISSUE", + "T86x_JS1_WAIT_DEPEND", + "T86x_JS1_WAIT_FINISH", + "T86x_JS2_JOBS", + "T86x_JS2_TASKS", + "T86x_JS2_ACTIVE", + "", + "T86x_JS2_WAIT_READ", + "T86x_JS2_WAIT_ISSUE", + "T86x_JS2_WAIT_DEPEND", + "T86x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T86x_TI_JOBS_PROCESSED", + "T86x_TI_TRIANGLES", + "T86x_TI_QUADS", + "T86x_TI_POLYGONS", + "T86x_TI_POINTS", + "T86x_TI_LINES", + "T86x_TI_VCACHE_HIT", + "T86x_TI_VCACHE_MISS", + "T86x_TI_FRONT_FACING", + "T86x_TI_BACK_FACING", + "T86x_TI_PRIM_VISIBLE", + "T86x_TI_PRIM_CULLED", + "T86x_TI_PRIM_CLIPPED", + "T86x_TI_LEVEL0", + "T86x_TI_LEVEL1", + "T86x_TI_LEVEL2", + "T86x_TI_LEVEL3", + "T86x_TI_LEVEL4", + "T86x_TI_LEVEL5", + "T86x_TI_LEVEL6", + "T86x_TI_LEVEL7", + "T86x_TI_COMMAND_1", + "T86x_TI_COMMAND_2", + "T86x_TI_COMMAND_3", + "T86x_TI_COMMAND_4", + "T86x_TI_COMMAND_5_7", + "T86x_TI_COMMAND_8_15", + "T86x_TI_COMMAND_16_63", + "T86x_TI_COMMAND_64", + "T86x_TI_COMPRESS_IN", + "T86x_TI_COMPRESS_OUT", + "T86x_TI_COMPRESS_FLUSH", + "T86x_TI_TIMESTAMPS", + "T86x_TI_PCACHE_HIT", + "T86x_TI_PCACHE_MISS", + "T86x_TI_PCACHE_LINE", + "T86x_TI_PCACHE_STALL", + "T86x_TI_WRBUF_HIT", + "T86x_TI_WRBUF_MISS", + "T86x_TI_WRBUF_LINE", + "T86x_TI_WRBUF_PARTIAL", + "T86x_TI_WRBUF_STALL", + "T86x_TI_ACTIVE", + "T86x_TI_LOADING_DESC", + "T86x_TI_INDEX_WAIT", + "T86x_TI_INDEX_RANGE_WAIT", + "T86x_TI_VERTEX_WAIT", + "T86x_TI_PCACHE_WAIT", + "T86x_TI_WRBUF_WAIT", + "T86x_TI_BUS_READ", + "T86x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T86x_TI_UTLB_HIT", + "T86x_TI_UTLB_NEW_MISS", + "T86x_TI_UTLB_REPLAY_FULL", + "T86x_TI_UTLB_REPLAY_MISS", + "T86x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T86x_FRAG_ACTIVE", + "T86x_FRAG_PRIMITIVES", + "T86x_FRAG_PRIMITIVES_DROPPED", + "T86x_FRAG_CYCLES_DESC", + "T86x_FRAG_CYCLES_FPKQ_ACTIVE", + "T86x_FRAG_CYCLES_VERT", + "T86x_FRAG_CYCLES_TRISETUP", + "T86x_FRAG_CYCLES_EZS_ACTIVE", + "T86x_FRAG_THREADS", + "T86x_FRAG_DUMMY_THREADS", + "T86x_FRAG_QUADS_RAST", + "T86x_FRAG_QUADS_EZS_TEST", + "T86x_FRAG_QUADS_EZS_KILLED", + "T86x_FRAG_THREADS_LZS_TEST", + "T86x_FRAG_THREADS_LZS_KILLED", + "T86x_FRAG_CYCLES_NO_TILE", + "T86x_FRAG_NUM_TILES", + "T86x_FRAG_TRANS_ELIM", + "T86x_COMPUTE_ACTIVE", + "T86x_COMPUTE_TASKS", + "T86x_COMPUTE_THREADS", + "T86x_COMPUTE_CYCLES_DESC", + "T86x_TRIPIPE_ACTIVE", + "T86x_ARITH_WORDS", + "T86x_ARITH_CYCLES_REG", + "T86x_ARITH_CYCLES_L0", + "T86x_ARITH_FRAG_DEPEND", + "T86x_LS_WORDS", + "T86x_LS_ISSUES", + "T86x_LS_REISSUE_ATTR", + "T86x_LS_REISSUES_VARY", + "T86x_LS_VARY_RV_MISS", + "T86x_LS_VARY_RV_HIT", + "T86x_LS_NO_UNPARK", + "T86x_TEX_WORDS", + "T86x_TEX_BUBBLES", + "T86x_TEX_WORDS_L0", + "T86x_TEX_WORDS_DESC", + "T86x_TEX_ISSUES", + "T86x_TEX_RECIRC_FMISS", + "T86x_TEX_RECIRC_DESC", + "T86x_TEX_RECIRC_MULTI", + "T86x_TEX_RECIRC_PMISS", + "T86x_TEX_RECIRC_CONF", + "T86x_LSC_READ_HITS", + "T86x_LSC_READ_OP", + "T86x_LSC_WRITE_HITS", + "T86x_LSC_WRITE_OP", + "T86x_LSC_ATOMIC_HITS", + "T86x_LSC_ATOMIC_OP", + "T86x_LSC_LINE_FETCHES", + "T86x_LSC_DIRTY_LINE", + "T86x_LSC_SNOOPS", + "T86x_AXI_TLB_STALL", + "T86x_AXI_TLB_MIESS", + "T86x_AXI_TLB_TRANSACTION", + "T86x_LS_TLB_MISS", + "T86x_LS_TLB_HIT", + "T86x_AXI_BEATS_READ", + "T86x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T86x_MMU_HIT", + "T86x_MMU_NEW_MISS", + "T86x_MMU_REPLAY_FULL", + "T86x_MMU_REPLAY_MISS", + "T86x_MMU_TABLE_WALK", + "T86x_MMU_REQUESTS", + "", + "", + "T86x_UTLB_HIT", + "T86x_UTLB_NEW_MISS", + "T86x_UTLB_REPLAY_FULL", + "T86x_UTLB_REPLAY_MISS", + "T86x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T86x_L2_EXT_WRITE_BEATS", + "T86x_L2_EXT_READ_BEATS", + "T86x_L2_ANY_LOOKUP", + "T86x_L2_READ_LOOKUP", + "T86x_L2_SREAD_LOOKUP", + "T86x_L2_READ_REPLAY", + "T86x_L2_READ_SNOOP", + "T86x_L2_READ_HIT", + "T86x_L2_CLEAN_MISS", + "T86x_L2_WRITE_LOOKUP", + "T86x_L2_SWRITE_LOOKUP", + "T86x_L2_WRITE_REPLAY", + "T86x_L2_WRITE_SNOOP", + "T86x_L2_WRITE_HIT", + "T86x_L2_EXT_READ_FULL", + "", + "T86x_L2_EXT_WRITE_FULL", + "T86x_L2_EXT_R_W_HAZARD", + "T86x_L2_EXT_READ", + "T86x_L2_EXT_READ_LINE", + "T86x_L2_EXT_WRITE", + "T86x_L2_EXT_WRITE_LINE", + "T86x_L2_EXT_WRITE_SMALL", + "T86x_L2_EXT_BARRIER", + "T86x_L2_EXT_AR_STALL", + "T86x_L2_EXT_R_BUF_FULL", + "T86x_L2_EXT_RD_BUF_FULL", + "T86x_L2_EXT_R_RAW", + "T86x_L2_EXT_W_STALL", + "T86x_L2_EXT_W_BUF_FULL", + "T86x_L2_EXT_R_BUF_FULL", + "T86x_L2_TAG_HAZARD", + "T86x_L2_SNOOP_FULL", + "T86x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t88x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T88x_MESSAGES_SENT", + "T88x_MESSAGES_RECEIVED", + "T88x_GPU_ACTIVE", + "T88x_IRQ_ACTIVE", + "T88x_JS0_JOBS", + "T88x_JS0_TASKS", + "T88x_JS0_ACTIVE", + "", + "T88x_JS0_WAIT_READ", + "T88x_JS0_WAIT_ISSUE", + "T88x_JS0_WAIT_DEPEND", + "T88x_JS0_WAIT_FINISH", + "T88x_JS1_JOBS", + "T88x_JS1_TASKS", + "T88x_JS1_ACTIVE", + "", + "T88x_JS1_WAIT_READ", + "T88x_JS1_WAIT_ISSUE", + "T88x_JS1_WAIT_DEPEND", + "T88x_JS1_WAIT_FINISH", + "T88x_JS2_JOBS", + "T88x_JS2_TASKS", + "T88x_JS2_ACTIVE", + "", + "T88x_JS2_WAIT_READ", + "T88x_JS2_WAIT_ISSUE", + "T88x_JS2_WAIT_DEPEND", + "T88x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T88x_TI_JOBS_PROCESSED", + "T88x_TI_TRIANGLES", + "T88x_TI_QUADS", + "T88x_TI_POLYGONS", + "T88x_TI_POINTS", + "T88x_TI_LINES", + "T88x_TI_VCACHE_HIT", + "T88x_TI_VCACHE_MISS", + "T88x_TI_FRONT_FACING", + "T88x_TI_BACK_FACING", + "T88x_TI_PRIM_VISIBLE", + "T88x_TI_PRIM_CULLED", + "T88x_TI_PRIM_CLIPPED", + "T88x_TI_LEVEL0", + "T88x_TI_LEVEL1", + "T88x_TI_LEVEL2", + "T88x_TI_LEVEL3", + "T88x_TI_LEVEL4", + "T88x_TI_LEVEL5", + "T88x_TI_LEVEL6", + "T88x_TI_LEVEL7", + "T88x_TI_COMMAND_1", + "T88x_TI_COMMAND_2", + "T88x_TI_COMMAND_3", + "T88x_TI_COMMAND_4", + "T88x_TI_COMMAND_5_7", + "T88x_TI_COMMAND_8_15", + "T88x_TI_COMMAND_16_63", + "T88x_TI_COMMAND_64", + "T88x_TI_COMPRESS_IN", + "T88x_TI_COMPRESS_OUT", + "T88x_TI_COMPRESS_FLUSH", + "T88x_TI_TIMESTAMPS", + "T88x_TI_PCACHE_HIT", + "T88x_TI_PCACHE_MISS", + "T88x_TI_PCACHE_LINE", + "T88x_TI_PCACHE_STALL", + "T88x_TI_WRBUF_HIT", + "T88x_TI_WRBUF_MISS", + "T88x_TI_WRBUF_LINE", + "T88x_TI_WRBUF_PARTIAL", + "T88x_TI_WRBUF_STALL", + "T88x_TI_ACTIVE", + "T88x_TI_LOADING_DESC", + "T88x_TI_INDEX_WAIT", + "T88x_TI_INDEX_RANGE_WAIT", + "T88x_TI_VERTEX_WAIT", + "T88x_TI_PCACHE_WAIT", + "T88x_TI_WRBUF_WAIT", + "T88x_TI_BUS_READ", + "T88x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T88x_TI_UTLB_HIT", + "T88x_TI_UTLB_NEW_MISS", + "T88x_TI_UTLB_REPLAY_FULL", + "T88x_TI_UTLB_REPLAY_MISS", + "T88x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T88x_FRAG_ACTIVE", + "T88x_FRAG_PRIMITIVES", + "T88x_FRAG_PRIMITIVES_DROPPED", + "T88x_FRAG_CYCLES_DESC", + "T88x_FRAG_CYCLES_FPKQ_ACTIVE", + "T88x_FRAG_CYCLES_VERT", + "T88x_FRAG_CYCLES_TRISETUP", + "T88x_FRAG_CYCLES_EZS_ACTIVE", + "T88x_FRAG_THREADS", + "T88x_FRAG_DUMMY_THREADS", + "T88x_FRAG_QUADS_RAST", + "T88x_FRAG_QUADS_EZS_TEST", + "T88x_FRAG_QUADS_EZS_KILLED", + "T88x_FRAG_THREADS_LZS_TEST", + "T88x_FRAG_THREADS_LZS_KILLED", + "T88x_FRAG_CYCLES_NO_TILE", + "T88x_FRAG_NUM_TILES", + "T88x_FRAG_TRANS_ELIM", + "T88x_COMPUTE_ACTIVE", + "T88x_COMPUTE_TASKS", + "T88x_COMPUTE_THREADS", + "T88x_COMPUTE_CYCLES_DESC", + "T88x_TRIPIPE_ACTIVE", + "T88x_ARITH_WORDS", + "T88x_ARITH_CYCLES_REG", + "T88x_ARITH_CYCLES_L0", + "T88x_ARITH_FRAG_DEPEND", + "T88x_LS_WORDS", + "T88x_LS_ISSUES", + "T88x_LS_REISSUE_ATTR", + "T88x_LS_REISSUES_VARY", + "T88x_LS_VARY_RV_MISS", + "T88x_LS_VARY_RV_HIT", + "T88x_LS_NO_UNPARK", + "T88x_TEX_WORDS", + "T88x_TEX_BUBBLES", + "T88x_TEX_WORDS_L0", + "T88x_TEX_WORDS_DESC", + "T88x_TEX_ISSUES", + "T88x_TEX_RECIRC_FMISS", + "T88x_TEX_RECIRC_DESC", + "T88x_TEX_RECIRC_MULTI", + "T88x_TEX_RECIRC_PMISS", + "T88x_TEX_RECIRC_CONF", + "T88x_LSC_READ_HITS", + "T88x_LSC_READ_OP", + "T88x_LSC_WRITE_HITS", + "T88x_LSC_WRITE_OP", + "T88x_LSC_ATOMIC_HITS", + "T88x_LSC_ATOMIC_OP", + "T88x_LSC_LINE_FETCHES", + "T88x_LSC_DIRTY_LINE", + "T88x_LSC_SNOOPS", + "T88x_AXI_TLB_STALL", + "T88x_AXI_TLB_MIESS", + "T88x_AXI_TLB_TRANSACTION", + "T88x_LS_TLB_MISS", + "T88x_LS_TLB_HIT", + "T88x_AXI_BEATS_READ", + "T88x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T88x_MMU_HIT", + "T88x_MMU_NEW_MISS", + "T88x_MMU_REPLAY_FULL", + "T88x_MMU_REPLAY_MISS", + "T88x_MMU_TABLE_WALK", + "T88x_MMU_REQUESTS", + "", + "", + "T88x_UTLB_HIT", + "T88x_UTLB_NEW_MISS", + "T88x_UTLB_REPLAY_FULL", + "T88x_UTLB_REPLAY_MISS", + "T88x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T88x_L2_EXT_WRITE_BEATS", + "T88x_L2_EXT_READ_BEATS", + "T88x_L2_ANY_LOOKUP", + "T88x_L2_READ_LOOKUP", + "T88x_L2_SREAD_LOOKUP", + "T88x_L2_READ_REPLAY", + "T88x_L2_READ_SNOOP", + "T88x_L2_READ_HIT", + "T88x_L2_CLEAN_MISS", + "T88x_L2_WRITE_LOOKUP", + "T88x_L2_SWRITE_LOOKUP", + "T88x_L2_WRITE_REPLAY", + "T88x_L2_WRITE_SNOOP", + "T88x_L2_WRITE_HIT", + "T88x_L2_EXT_READ_FULL", + "", + "T88x_L2_EXT_WRITE_FULL", + "T88x_L2_EXT_R_W_HAZARD", + "T88x_L2_EXT_READ", + "T88x_L2_EXT_READ_LINE", + "T88x_L2_EXT_WRITE", + "T88x_L2_EXT_WRITE_LINE", + "T88x_L2_EXT_WRITE_SMALL", + "T88x_L2_EXT_BARRIER", + "T88x_L2_EXT_AR_STALL", + "T88x_L2_EXT_R_BUF_FULL", + "T88x_L2_EXT_RD_BUF_FULL", + "T88x_L2_EXT_R_RAW", + "T88x_L2_EXT_W_STALL", + "T88x_L2_EXT_W_BUF_FULL", + "T88x_L2_EXT_R_BUF_FULL", + "T88x_L2_TAG_HAZARD", + "T88x_L2_SNOOP_FULL", + "T88x_L2_REPLAY_FULL" +}; + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..41470a3418f6c17f5be1c0d5feeaa9d682eb0d46 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c @@ -0,0 +1,113 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#ifdef CONFIG_DEBUG_FS +/** Show callback for the @c gpu_memory debugfs file. + * + * This function is called to get the contents of the @c gpu_memory debugfs + * file. This is a report of current gpu memory usage. + * + * @param sfile The debugfs entry + * @param data Data associated with the entry + * + * @return 0 if successfully prints data in debugfs entry file + * -1 if it encountered an error + */ + +static int kbasep_gpu_memory_seq_show(struct seq_file *sfile, void *data) +{ + ssize_t ret = 0; + struct list_head *entry; + const struct list_head *kbdev_list; + kbdev_list = kbase_dev_list_get(); + list_for_each(entry, kbdev_list) { + struct kbase_device *kbdev = NULL; + struct kbasep_kctx_list_element *element; + + kbdev = list_entry(entry, struct kbase_device, entry); + /* output the total memory usage and cap for this device */ + ret = seq_printf(sfile, "%-16s %10u\n", \ + kbdev->devname, \ + atomic_read(&(kbdev->memdev.used_pages))); + mutex_lock(&kbdev->kctx_list_lock); + list_for_each_entry(element, &kbdev->kctx_list, link) { + /* output the memory usage and cap for each kctx + * opened on this device */ + ret = seq_printf(sfile, " %s-0x%p %10u %10u\n", \ + "kctx", + element->kctx, \ + atomic_read(&(element->kctx->used_pages)), + element->kctx->tgid); + } + mutex_unlock(&kbdev->kctx_list_lock); + } + kbase_dev_list_put(kbdev_list); + return ret; +} + +/* + * File operations related to debugfs entry for gpu_memory + */ +STATIC int kbasep_gpu_memory_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_gpu_memory_seq_show , NULL); +} + +static const struct file_operations kbasep_gpu_memory_debugfs_fops = { + .open = kbasep_gpu_memory_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * Initialize debugfs entry for gpu_memory + */ +mali_error kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev) +{ + kbdev->gpu_memory_dentry = debugfs_create_file("gpu_memory", \ + S_IRUGO, \ + kbdev->mali_debugfs_directory, \ + NULL, \ + &kbasep_gpu_memory_debugfs_fops); + if (IS_ERR(kbdev->gpu_memory_dentry)) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +/* + * Terminate debugfs entry for gpu_memory + */ +void kbasep_gpu_memory_debugfs_term(struct kbase_device *kbdev) +{ + debugfs_remove(kbdev->gpu_memory_dentry); +} +#else +/* + * Stub functions for when debugfs is disabled + */ +mali_error kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev) +{ + return MALI_ERROR_NONE; +} +void kbasep_gpu_memory_debugfs_term(struct kbase_device *kbdev) +{ +} +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..7ceb380a2653aa94c492b5b9e4f3bff91429ef99 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h @@ -0,0 +1,43 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpu_memory_debugfs.h + * Header file for gpu_memory entry in debugfs + * + */ + +#ifndef _KBASE_GPU_MEMORY_H +#define _KBASE_GPU_MEMORY_H + +#include +#include +#include + +/** + * @brief Initialize gpu_memory debugfs entry + */ +mali_error kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev); + +/** + * @brief Terminate gpu_memory debugfs entry + */ +void kbasep_gpu_memory_debugfs_term(struct kbase_device *kbdev); + +#endif /*_KBASE_GPU_MEMORY_H*/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c new file mode 100644 index 0000000000000000000000000000000000000000..2d2ff64b90cfcc18f1b881909d5e1cc843117d07 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c @@ -0,0 +1,335 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpuprops.c + * Base kernel property query APIs + */ + +#include +#include +#include + +/** + * @brief Extracts bits from a 32-bit bitfield. + * @hideinitializer + * + * @param[in] value The value from which to extract bits. + * @param[in] offset The first bit to extract (0 being the LSB). + * @param[in] size The number of bits to extract. + * @return Bits [@a offset, @a offset + @a size) from @a value. + * + * @pre offset + size <= 32. + */ +/* from mali_cdsb.h */ +#define KBASE_UBFX32(value, offset, size) \ + (((u32)(value) >> (u32)(offset)) & (u32)((1ULL << (u32)(size)) - 1)) + +mali_error kbase_gpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_gpuprops * const kbase_props) +{ + kbase_gpuprops_clock_speed_function get_gpu_speed_mhz; + u32 gpu_speed_mhz; + int rc = 1; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kbase_props); + + /* Current GPU speed is requested from the system integrator via the KBASE_CONFIG_ATTR_GPU_SPEED_FUNC function. + * If that function fails, or the function is not provided by the system integrator, we report the maximum + * GPU speed as specified by GPU_FREQ_KHZ_MAX. + */ + get_gpu_speed_mhz = (kbase_gpuprops_clock_speed_function) kbasep_get_config_value(kctx->kbdev, kctx->kbdev->config_attributes, KBASE_CONFIG_ATTR_GPU_SPEED_FUNC); + if (get_gpu_speed_mhz != NULL) { + rc = get_gpu_speed_mhz(&gpu_speed_mhz); +#ifdef CONFIG_MALI_DEBUG + /* Issue a warning message when the reported GPU speed falls outside the min/max range */ + if (rc == 0) { + u32 gpu_speed_khz = gpu_speed_mhz * 1000; + if (gpu_speed_khz < kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min || gpu_speed_khz > kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max) + dev_warn(kctx->kbdev->dev, "GPU Speed is outside of min/max range (got %lu Khz, min %lu Khz, max %lu Khz)\n", (unsigned long)gpu_speed_khz, (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min, (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max); + } +#endif /* CONFIG_MALI_DEBUG */ + } + if (rc != 0) + gpu_speed_mhz = kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max / 1000; + + kctx->kbdev->gpu_props.props.core_props.gpu_speed_mhz = gpu_speed_mhz; + + memcpy(&kbase_props->props, &kctx->kbdev->gpu_props.props, sizeof(kbase_props->props)); + + return MALI_ERROR_NONE; +} + +STATIC void kbase_gpuprops_dump_registers(struct kbase_device *kbdev, struct kbase_gpuprops_regdump *regdump) +{ + int i; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != regdump); + + /* Fill regdump with the content of the relevant registers */ + regdump->gpu_id = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID)); + + regdump->l2_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_FEATURES)); + regdump->l3_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_FEATURES)); + regdump->tiler_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_FEATURES)); + regdump->mem_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(MEM_FEATURES)); + regdump->mmu_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(MMU_FEATURES)); + regdump->as_present = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(AS_PRESENT)); + regdump->js_present = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(JS_PRESENT)); + + for (i = 0; i < MIDG_MAX_JOB_SLOTS; i++) + regdump->js_features[i] = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(JS_FEATURES_REG(i))); + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + regdump->texture_features[i] = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TEXTURE_FEATURES_REG(i))); + + regdump->thread_max_threads = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_THREADS)); + regdump->thread_max_workgroup_size = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_WORKGROUP_SIZE)); + regdump->thread_max_barrier_size = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_BARRIER_SIZE)); + regdump->thread_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_FEATURES)); + + regdump->shader_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(SHADER_PRESENT_LO)); + regdump->shader_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(SHADER_PRESENT_HI)); + + regdump->tiler_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_PRESENT_LO)); + regdump->tiler_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_PRESENT_HI)); + + regdump->l2_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_PRESENT_LO)); + regdump->l2_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_PRESENT_HI)); + + regdump->l3_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_PRESENT_LO)); + regdump->l3_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_PRESENT_HI)); +} + +STATIC void kbase_gpuprops_construct_coherent_groups(base_gpu_props * const props) +{ + struct mali_base_gpu_coherent_group *current_group; + u64 group_present; + u64 group_mask; + u64 first_set, first_set_prev; + u32 num_groups = 0; + + KBASE_DEBUG_ASSERT(NULL != props); + + props->coherency_info.coherency = props->raw_props.mem_features; + props->coherency_info.num_core_groups = hweight64(props->raw_props.l2_present); + + if (props->coherency_info.coherency & GROUPS_L3_COHERENT) { + /* Group is l3 coherent */ + group_present = props->raw_props.l3_present; + } else if (props->coherency_info.coherency & GROUPS_L2_COHERENT) { + /* Group is l2 coherent */ + group_present = props->raw_props.l2_present; + } else { + /* Group is l1 coherent */ + group_present = props->raw_props.shader_present; + } + + /* + * The coherent group mask can be computed from the l2/l3 present + * register. + * + * For the coherent group n: + * group_mask[n] = (first_set[n] - 1) & ~(first_set[n-1] - 1) + * where first_set is group_present with only its nth set-bit kept + * (i.e. the position from where a new group starts). + * + * For instance if the groups are l2 coherent and l2_present=0x0..01111: + * The first mask is: + * group_mask[1] = (first_set[1] - 1) & ~(first_set[0] - 1) + * = (0x0..010 - 1) & ~(0x0..01 - 1) + * = 0x0..00f + * The second mask is: + * group_mask[2] = (first_set[2] - 1) & ~(first_set[1] - 1) + * = (0x0..100 - 1) & ~(0x0..010 - 1) + * = 0x0..0f0 + * And so on until all the bits from group_present have been cleared + * (i.e. there is no group left). + */ + + current_group = props->coherency_info.group; + first_set = group_present & ~(group_present - 1); + + while (group_present != 0 && num_groups < BASE_MAX_COHERENT_GROUPS) { + group_present -= first_set; /* Clear the current group bit */ + first_set_prev = first_set; + + first_set = group_present & ~(group_present - 1); + group_mask = (first_set - 1) & ~(first_set_prev - 1); + + /* Populate the coherent_group structure for each group */ + current_group->core_mask = group_mask & props->raw_props.shader_present; + current_group->num_cores = hweight64(current_group->core_mask); + + num_groups++; + current_group++; + } + + if (group_present != 0) + pr_warn("Too many coherent groups (keeping only %d groups).\n", BASE_MAX_COHERENT_GROUPS); + + props->coherency_info.num_groups = num_groups; +} + +/** + * @brief Get the GPU configuration + * + * Fill the base_gpu_props structure with values from the GPU configuration registers. + * Only the raw properties are filled in this function + * + * @param gpu_props The base_gpu_props structure + * @param kbdev The struct kbase_device structure for the device + */ +static void kbase_gpuprops_get_props(base_gpu_props * const gpu_props, struct kbase_device *kbdev) +{ + struct kbase_gpuprops_regdump regdump; + int i; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != gpu_props); + + /* Dump relevant registers */ + kbase_gpuprops_dump_registers(kbdev, ®dump); + gpu_props->raw_props.gpu_id = regdump.gpu_id; + gpu_props->raw_props.tiler_features = regdump.tiler_features; + gpu_props->raw_props.mem_features = regdump.mem_features; + gpu_props->raw_props.mmu_features = regdump.mmu_features; + gpu_props->raw_props.l2_features = regdump.l2_features; + gpu_props->raw_props.l3_features = regdump.l3_features; + + gpu_props->raw_props.as_present = regdump.as_present; + gpu_props->raw_props.js_present = regdump.js_present; + gpu_props->raw_props.shader_present = ((u64) regdump.shader_present_hi << 32) + regdump.shader_present_lo; + gpu_props->raw_props.tiler_present = ((u64) regdump.tiler_present_hi << 32) + regdump.tiler_present_lo; + gpu_props->raw_props.l2_present = ((u64) regdump.l2_present_hi << 32) + regdump.l2_present_lo; + gpu_props->raw_props.l3_present = ((u64) regdump.l3_present_hi << 32) + regdump.l3_present_lo; + + for (i = 0; i < MIDG_MAX_JOB_SLOTS; i++) + gpu_props->raw_props.js_features[i] = regdump.js_features[i]; + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + gpu_props->raw_props.texture_features[i] = regdump.texture_features[i]; + + gpu_props->raw_props.thread_max_barrier_size = regdump.thread_max_barrier_size; + gpu_props->raw_props.thread_max_threads = regdump.thread_max_threads; + gpu_props->raw_props.thread_max_workgroup_size = regdump.thread_max_workgroup_size; + gpu_props->raw_props.thread_features = regdump.thread_features; +} + +/** + * @brief Calculate the derived properties + * + * Fill the base_gpu_props structure with values derived from the GPU configuration registers + * + * @param gpu_props The base_gpu_props structure + * @param kbdev The struct kbase_device structure for the device + */ +static void kbase_gpuprops_calculate_props(base_gpu_props * const gpu_props, struct kbase_device *kbdev) +{ + int i; + + /* Populate the base_gpu_props structure */ + gpu_props->core_props.version_status = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 0U, 4); + gpu_props->core_props.minor_revision = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 4U, 8); + gpu_props->core_props.major_revision = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 12U, 4); + gpu_props->core_props.product_id = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 16U, 16); + gpu_props->core_props.log2_program_counter_size = KBASE_GPU_PC_SIZE_LOG2; + gpu_props->core_props.gpu_available_memory_size = totalram_pages << PAGE_SHIFT; + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + gpu_props->core_props.texture_features[i] = gpu_props->raw_props.texture_features[i]; + + gpu_props->l2_props.log2_line_size = KBASE_UBFX32(gpu_props->raw_props.l2_features, 0U, 8); + gpu_props->l2_props.log2_cache_size = KBASE_UBFX32(gpu_props->raw_props.l2_features, 16U, 8); + gpu_props->l2_props.num_l2_slices = 1; + if (gpu_props->core_props.product_id == GPU_ID_PI_T76X) { + gpu_props->l2_props.num_l2_slices = KBASE_UBFX32(gpu_props->raw_props.mem_features, 8U, 4) + 1; + } + + gpu_props->l3_props.log2_line_size = KBASE_UBFX32(gpu_props->raw_props.l3_features, 0U, 8); + gpu_props->l3_props.log2_cache_size = KBASE_UBFX32(gpu_props->raw_props.l3_features, 16U, 8); + + gpu_props->tiler_props.bin_size_bytes = 1 << KBASE_UBFX32(gpu_props->raw_props.tiler_features, 0U, 6); + gpu_props->tiler_props.max_active_levels = KBASE_UBFX32(gpu_props->raw_props.tiler_features, 8U, 4); + + if (gpu_props->raw_props.thread_max_threads == 0) + gpu_props->thread_props.max_threads = THREAD_MT_DEFAULT; + else + gpu_props->thread_props.max_threads = gpu_props->raw_props.thread_max_threads; + + if (gpu_props->raw_props.thread_max_workgroup_size == 0) + gpu_props->thread_props.max_workgroup_size = THREAD_MWS_DEFAULT; + else + gpu_props->thread_props.max_workgroup_size = gpu_props->raw_props.thread_max_workgroup_size; + + if (gpu_props->raw_props.thread_max_barrier_size == 0) + gpu_props->thread_props.max_barrier_size = THREAD_MBS_DEFAULT; + else + gpu_props->thread_props.max_barrier_size = gpu_props->raw_props.thread_max_barrier_size; + + gpu_props->thread_props.max_registers = KBASE_UBFX32(gpu_props->raw_props.thread_features, 0U, 16); + gpu_props->thread_props.max_task_queue = KBASE_UBFX32(gpu_props->raw_props.thread_features, 16U, 8); + gpu_props->thread_props.max_thread_group_split = KBASE_UBFX32(gpu_props->raw_props.thread_features, 24U, 6); + gpu_props->thread_props.impl_tech = KBASE_UBFX32(gpu_props->raw_props.thread_features, 30U, 2); + + /* If values are not specified, then use defaults */ + if (gpu_props->thread_props.max_registers == 0) { + gpu_props->thread_props.max_registers = THREAD_MR_DEFAULT; + gpu_props->thread_props.max_task_queue = THREAD_MTQ_DEFAULT; + gpu_props->thread_props.max_thread_group_split = THREAD_MTGS_DEFAULT; + } + /* Initialize the coherent_group structure for each group */ + kbase_gpuprops_construct_coherent_groups(gpu_props); +} + +void kbase_gpuprops_set(struct kbase_device *kbdev) +{ + kbase_gpu_props *gpu_props; + struct midg_raw_gpu_props *raw; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + gpu_props = &kbdev->gpu_props; + raw = &gpu_props->props.raw_props; + + /* Initialize the base_gpu_props structure from the hardware */ + kbase_gpuprops_get_props(&gpu_props->props, kbdev); + + /* Populate the derived properties */ + kbase_gpuprops_calculate_props(&gpu_props->props, kbdev); + + /* Populate kbase-only fields */ + gpu_props->l2_props.associativity = KBASE_UBFX32(raw->l2_features, 8U, 8); + gpu_props->l2_props.external_bus_width = KBASE_UBFX32(raw->l2_features, 24U, 8); + + gpu_props->l3_props.associativity = KBASE_UBFX32(raw->l3_features, 8U, 8); + gpu_props->l3_props.external_bus_width = KBASE_UBFX32(raw->l3_features, 24U, 8); + + gpu_props->mem.core_group = KBASE_UBFX32(raw->mem_features, 0U, 1); + gpu_props->mem.supergroup = KBASE_UBFX32(raw->mem_features, 1U, 1); + + gpu_props->mmu.va_bits = KBASE_UBFX32(raw->mmu_features, 0U, 8); + gpu_props->mmu.pa_bits = KBASE_UBFX32(raw->mmu_features, 8U, 8); + + gpu_props->num_cores = hweight64(raw->shader_present); + gpu_props->num_core_groups = hweight64(raw->l2_present); + gpu_props->num_supergroups = hweight64(raw->l3_present); + gpu_props->num_address_spaces = hweight32(raw->as_present); + gpu_props->num_job_slots = hweight32(raw->js_present); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h new file mode 100644 index 0000000000000000000000000000000000000000..fe2676cd9b998089cf49f051dec2702519a4ab95 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h @@ -0,0 +1,54 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpuprops.h + * Base kernel property query APIs + */ + +#ifndef _KBASE_GPUPROPS_H_ +#define _KBASE_GPUPROPS_H_ + +#include "mali_kbase_gpuprops_types.h" + +/* Forward definition - see mali_kbase.h */ +struct kbase_device; + +/** + * @brief Set up Kbase GPU properties. + * + * Set up Kbase GPU properties with information from the GPU registers + * + * @param kbdev The struct kbase_device structure for the device + */ +void kbase_gpuprops_set(struct kbase_device *kbdev); + +/** + * @brief Provide GPU properties to userside through UKU call. + * + * Fill the struct kbase_uk_gpuprops with values from GPU configuration registers. + * + * @param kctx The struct kbase_context structure + * @param kbase_props A copy of the struct kbase_uk_gpuprops structure from userspace + * + * @return MALI_ERROR_NONE on success. Any other value indicates failure. + */ +mali_error kbase_gpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_gpuprops * const kbase_props); + +#endif /* _KBASE_GPUPROPS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h new file mode 100644 index 0000000000000000000000000000000000000000..6ae5a20d5d4e9b90d05464a335e41ef2fabf7779 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h @@ -0,0 +1,96 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpuprops_types.h + * Base kernel property query APIs + */ + +#ifndef _KBASE_GPUPROPS_TYPES_H_ +#define _KBASE_GPUPROPS_TYPES_H_ + +#include "mali_base_kernel.h" + +#define KBASE_GPU_SPEED_MHZ 123 +#define KBASE_GPU_PC_SIZE_LOG2 24U + +typedef struct kbase_gpuprops_regdump { + u32 gpu_id; + u32 l2_features; + u32 l3_features; + u32 tiler_features; + u32 mem_features; + u32 mmu_features; + u32 as_present; + u32 js_present; + u32 thread_max_threads; + u32 thread_max_workgroup_size; + u32 thread_max_barrier_size; + u32 thread_features; + u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + u32 js_features[MIDG_MAX_JOB_SLOTS]; + u32 shader_present_lo; + u32 shader_present_hi; + u32 tiler_present_lo; + u32 tiler_present_hi; + u32 l2_present_lo; + u32 l2_present_hi; + u32 l3_present_lo; + u32 l3_present_hi; +} kbase_gpuprops_regdump; + +typedef struct kbase_gpu_cache_props { + u8 associativity; + u8 external_bus_width; +} kbase_gpu_cache_props; + +typedef struct kbase_gpu_mem_props { + u8 core_group; + u8 supergroup; +} kbase_gpu_mem_props; + +typedef struct kbase_gpu_mmu_props { + u8 va_bits; + u8 pa_bits; +} kbase_gpu_mmu_props; + +typedef struct mali_kbase_gpu_props { + /* kernel-only properties */ + u8 num_cores; + u8 num_core_groups; + u8 num_supergroups; + u8 num_address_spaces; + u8 num_job_slots; + + struct kbase_gpu_cache_props l2_props; + struct kbase_gpu_cache_props l3_props; + + struct kbase_gpu_mem_props mem; + struct kbase_gpu_mmu_props mmu; + + /** + * Implementation specific irq throttle value (us), should be adjusted during integration. + */ + int irq_throttle_time_us; + + /* Properties shared with userspace */ + base_gpu_props props; +} kbase_gpu_props; + +#endif /* _KBASE_GPUPROPS_TYPES_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..d97f35a4d39d5a1ab105718cc85069e5ad1e526d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.c @@ -0,0 +1,322 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Run-time work-arounds helpers + */ + +#include +#include +#include "mali_kbase.h" +#include "mali_kbase_hw.h" + +//MTK{{ +#include +#include +//}}MTK + +void kbase_hw_set_features_mask(struct kbase_device *kbdev) +{ + const enum base_hw_feature *features; + u32 gpu_id; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + gpu_id &= GPU_ID_VERSION_PRODUCT_ID; + gpu_id = gpu_id >> GPU_ID_VERSION_PRODUCT_ID_SHIFT; + + switch (gpu_id) { + case GPU_ID_PI_T76X: + features = base_hw_features_t76x; + break; +#ifdef MALI_INCLUDE_TFRX + case GPU_ID_PI_TFRX: + /* Fall through */ +#endif /* MALI_INCLUDE_TFRX */ + case GPU_ID_PI_T86X: + features = base_hw_features_tFxx; + break; + case GPU_ID_PI_T72X: + features = base_hw_features_t72x; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 0, 1, 0): + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 1, 0): + features = base_hw_features_t62x; + break; + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_15DEV0): + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_EAC): + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 1, 0): + features = base_hw_features_t60x; + break; + default: + features = base_hw_features_generic; + break; + } + + for (; *features != BASE_HW_FEATURE_END; features++) + set_bit(*features, &kbdev->hw_features_mask[0]); +} + +//MTK{{ +void mtk_get_clk_MFG_HW_REST(void) +{ +/* +b. MFG HW REST bit (0x10007018 ) +*/ + struct device_node *node; + void __iomem *clk_apmixed_base; + + node = of_find_compatible_node(NULL, NULL, "mediatek,TOPRGU"); + if (!node) { + pr_alert("[Mali]MFG HW REST bit find node failed\n"); + } + clk_apmixed_base = of_iomap(node, 0); + if (!clk_apmixed_base){ + pr_alert("[Mali] MFG HW REST bit failed\n"); + }else{ + pr_alert("[Mali]MFG HW REST bit : 0x%08x \n",readl(clk_apmixed_base + 0x18) ); + } + +} + +void mtk_get_clk_MFG_APB_PWR(void) +{ +/* +c. MFG APB SW reset (0x10001150 ) +*/ + struct device_node *node; + void __iomem *clk_apmixed_base; + + node = of_find_compatible_node(NULL, NULL, "mediatek,INFRACFG_AO"); + if (!node) { + pr_alert("[Mali]MFG APB SW reset find node failed\n"); + } + clk_apmixed_base = of_iomap(node, 0); + if (!clk_apmixed_base){ + pr_alert("[Mali] MFG APB SW reset failed\n"); + }else{ + pr_alert("[Mali]MFG APB SW reset : 0x%08x \n",readl(clk_apmixed_base + 0x150) ); + } + +} + +void mtk_get_clk_MFG_CG_CON(void) +{ +/* +f. MFG CG( 0x13000000 MFG_CG_CON ,correct : 0) +*/ + struct device_node *node; + void __iomem *clk_apmixed_base; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-mfgsys"); + if (!node) { + pr_alert("[Mali]MFG_CG_CON find node failed\n"); + } + clk_apmixed_base = of_iomap(node, 0); + if (!clk_apmixed_base){ + pr_alert("[Mali] MFG_CG_CON failed\n"); + }else{ + pr_alert("[Mali]MFG_CG_CON : 0x%08x \n",readl(clk_apmixed_base + 0x18) ); + pr_alert("[Mali]MFG 0x13000020 : 0x%08x \n",readl(clk_apmixed_base + 0x20) ); //Default Value 0x2A + } + +} + +void mtk_get_clk_MFG_PWR(void) +{ +#define MFG_ASYNC_PWR_CON_OFFSET 0x334 +#define MFG_PWR_CON_OFFSET 0x338 + + struct device_node *node; + void __iomem *clk_apmixed_base; + + + node = of_find_compatible_node(NULL, NULL, "mediatek,SLEEP"); + if (!node) { + pr_alert("[Mali] find node failed\n"); + } + clk_apmixed_base = of_iomap(node, 0); + if (!clk_apmixed_base){ + pr_alert("[Mali] base failed\n"); + }else{ + pr_alert("[Mali]MFG_ASYNC_PWR_CON : 0x%08x \n",readl(clk_apmixed_base + MFG_ASYNC_PWR_CON_OFFSET) ); + pr_alert("[Mali]MFG_PWR : 0x%08x \n",readl(clk_apmixed_base + MFG_PWR_CON_OFFSET)); + pr_alert("[Mali]PWR_STATUS : 0x%08x \n",readl(clk_apmixed_base + 0x180) ); + pr_alert("[Mali]PWR_STATUS_2ND : 0x%08x \n",readl(clk_apmixed_base + 0x184)); + + } + mtk_get_clk_MFG_HW_REST(); + mtk_get_clk_MFG_APB_PWR(); + mtk_get_clk_MFG_CG_CON(); + /* + b. MFG HW REST bit (0x10007018 ) +c. MFG APB SW reset (0x10001150 ) +d. PWR_STATUS (0x110006180) +e. PWR_STATUS_2ND (0x110006184) +f. MFG CG( 0x13000000 MFG_CG_CON ,correct : 0) +*/ + + +} +void get_more_Mali_Register(struct kbase_device *kbdev) +{ + pr_alert("MALI :[Register] get GPU ID : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID)) ); + pr_alert("MALI :[Register] get L2_FEATURES : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_FEATURES)) ); + pr_alert("MALI :[Register] get L3_FEATURES : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_FEATURES)) ); + pr_alert("MALI :[Register] get TILER_FEATURES : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_FEATURES)) ); + pr_alert("MALI :[Register] get MEM_FEATURES : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(MEM_FEATURES)) ); + pr_alert("MALI :[Register] get MMU_FEATURES : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(MMU_FEATURES)) ); + pr_alert("MALI :[Register] get AS_PRESENT : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(AS_PRESENT)) ); + pr_alert("MALI :[Register] get JS_PRESENT : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(JS_PRESENT)) ); + pr_alert("MALI :[Register] get GPU_IRQ_RAWSTAT : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)) ); + pr_alert("MALI :[Register] get GPU_IRQ_MASK : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK)) ); + pr_alert("MALI :[Register] get GPU_IRQ_STATUS : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_STATUS)) ); + pr_alert("MALI :[Register] get GPU_STATUS : 0x%x", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS)) ); +} + +//}}MTK + +mali_error kbase_hw_set_issues_mask(struct kbase_device *kbdev) +{ + const enum base_hw_issue *issues; + u32 gpu_id; + u32 impl_tech; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + impl_tech = kbdev->gpu_props.props.thread_props.impl_tech; + + mtk_get_clk_MFG_PWR(); + pr_alert("[Mali] base gpu_id = 0x%x \n",gpu_id); + + if (impl_tech != IMPLEMENTATION_MODEL) { + switch (gpu_id) { + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_15DEV0): + issues = base_hw_issues_t60x_r0p0_15dev0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_EAC): + issues = base_hw_issues_t60x_r0p0_eac; + break; + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 1, 0): + issues = base_hw_issues_t60x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 0, 1, 0): + issues = base_hw_issues_t62x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 1): + issues = base_hw_issues_t62x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 1, 0): + issues = base_hw_issues_t62x_r1p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 0, 0): + issues = base_hw_issues_t76x_r0p0_beta; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 0, 1): + issues = base_hw_issues_t76x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 1, 1): + issues = base_hw_issues_t76x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 1, 9): + issues = base_hw_issues_t76x_r0p1_50rel0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 2, 1): + issues = base_hw_issues_t76x_r0p2; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 3, 1): + issues = base_hw_issues_t76x_r0p3; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 1, 0, 0): + issues = base_hw_issues_t76x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 1): + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 2): + issues = base_hw_issues_t72x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 1, 0, 0): + issues = base_hw_issues_t72x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 1, 1, 0): + issues = base_hw_issues_t72x_r1p1; + break; +#ifdef MALI_INCLUDE_TFRX + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 0, 1): + issues = base_hw_issues_tFRx_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 1, 2): + issues = base_hw_issues_tFRx_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 2, 0): + issues = base_hw_issues_tFRx_r0p2; + break; +#endif /* MALI_INCLUDE_TFRX */ + case GPU_ID_MAKE(GPU_ID_PI_T86X, 0, 0, 1): + issues = base_hw_issues_t86x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T86X, 0, 2, 0): + issues = base_hw_issues_t86x_r0p2; + break; + default: + dev_err(kbdev->dev, "Unknown GPU ID %x", gpu_id); + mtk_get_clk_MFG_PWR(); + get_more_Mali_Register(kbdev); + return MALI_ERROR_FUNCTION_FAILED; + } + } else { + /* Software model */ + switch (gpu_id >> GPU_ID_VERSION_PRODUCT_ID_SHIFT) { + case GPU_ID_PI_T60X: + issues = base_hw_issues_model_t60x; + break; + case GPU_ID_PI_T62X: + issues = base_hw_issues_model_t62x; + break; + case GPU_ID_PI_T72X: + issues = base_hw_issues_model_t72x; + break; + case GPU_ID_PI_T76X: + issues = base_hw_issues_model_t76x; + break; +#ifdef MALI_INCLUDE_TFRX + case GPU_ID_PI_TFRX: + issues = base_hw_issues_model_tFRx; + break; +#endif /* MALI_INCLUDE_TFRX */ + case GPU_ID_PI_T86X: + issues = base_hw_issues_model_t86x; + break; + default: + dev_err(kbdev->dev, "Unknown GPU ID %x", gpu_id); + mtk_get_clk_MFG_PWR(); + get_more_Mali_Register(kbdev); + return MALI_ERROR_FUNCTION_FAILED; + } + } + + pr_alert("GPU identified as 0x%04x r%dp%d status %d", (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >> GPU_ID_VERSION_PRODUCT_ID_SHIFT, (gpu_id & GPU_ID_VERSION_MAJOR) >> GPU_ID_VERSION_MAJOR_SHIFT, (gpu_id & GPU_ID_VERSION_MINOR) >> GPU_ID_VERSION_MINOR_SHIFT, (gpu_id & GPU_ID_VERSION_STATUS) >> GPU_ID_VERSION_STATUS_SHIFT); + + for (; *issues != BASE_HW_ISSUE_END; issues++) + set_bit(*issues, &kbdev->hw_issues_mask[0]); + + return MALI_ERROR_NONE; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..1074290702ae455e3d7c080e21421f3951ba29c5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.h @@ -0,0 +1,52 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Run-time work-arounds helpers + */ + +#ifndef _KBASE_HW_H_ +#define _KBASE_HW_H_ + +#include "mali_kbase_defs.h" + +/** + * @brief Tell whether a work-around should be enabled + */ +#define kbase_hw_has_issue(kbdev, issue)\ + test_bit(issue, &(kbdev)->hw_issues_mask[0]) + +/** + * @brief Tell whether a feature is supported + */ +#define kbase_hw_has_feature(kbdev, feature)\ + test_bit(feature, &(kbdev)->hw_features_mask[0]) + +/** + * @brief Set the HW issues mask depending on the GPU ID + */ +mali_error kbase_hw_set_issues_mask(struct kbase_device *kbdev); + +/** + * @brief Set the features mask depending on the GPU ID + */ +void kbase_hw_set_features_mask(struct kbase_device *kbdev); + +#endif /* _KBASE_HW_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_instr.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_instr.c new file mode 100644 index 0000000000000000000000000000000000000000..a5cdba6fa6bd655039830904ce22f50f13aa7bef --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_instr.c @@ -0,0 +1,619 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_instr.c + * Base kernel instrumentation APIs. + */ + +#include +#include + +/** + * @brief Issue Cache Clean & Invalidate command to hardware + */ +static void kbasep_instr_hwcnt_cacheclean(struct kbase_device *kbdev) +{ + unsigned long flags; + unsigned long pm_flags; + u32 irq_mask; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Wait for any reset to complete */ + while (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.cache_clean_wait, + kbdev->hwcnt.state != KBASE_INSTR_STATE_RESETTING); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_REQUEST_CLEAN); + + /* Enable interrupt */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask | CLEAN_CACHES_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags); + + /* clean&invalidate the caches so we're sure the mmu tables for the dump buffer is valid */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CLEAN_INV_CACHES, NULL); + kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANING; + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); +} + +STATIC mali_error kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup) +{ + unsigned long flags, pm_flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbasep_js_device_data *js_devdata; + u32 irq_mask; + int ret; + u64 shader_cores_needed; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != setup); + KBASE_DEBUG_ASSERT(NULL == kbdev->hwcnt.suspended_kctx); + + shader_cores_needed = kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER); + + js_devdata = &kbdev->js_data; + + /* alignment failure */ + if ((setup->dump_buffer == 0ULL) || (setup->dump_buffer & (2048 - 1))) + goto out_err; + + /* Override core availability policy to ensure all cores are available */ + kbase_pm_ca_instr_enable(kbdev); + + /* Mark the context as active so the GPU is kept turned on */ + /* A suspend won't happen here, because we're in a syscall from a userspace + * thread. */ + kbase_pm_context_active(kbdev); + + /* Request the cores early on synchronously - we'll release them on any errors + * (e.g. instrumentation already active) */ + kbase_pm_request_cores_sync(kbdev, MALI_TRUE, shader_cores_needed); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + + if (kbdev->hwcnt.state != KBASE_INSTR_STATE_DISABLED) { + /* Instrumentation is already enabled */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out_unrequest_cores; + } + + /* Enable interrupt */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask | PRFCNT_SAMPLE_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags); + + /* In use, this context is the owner */ + kbdev->hwcnt.kctx = kctx; + /* Remember the dump address so we can reprogram it later */ + kbdev->hwcnt.addr = setup->dump_buffer; + /* Remember all the settings for suspend/resume */ + if (&kbdev->hwcnt.suspended_state != setup) + memcpy(&kbdev->hwcnt.suspended_state, setup, sizeof(kbdev->hwcnt.suspended_state)); + + /* Request the clean */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_REQUEST_CLEAN; + kbdev->hwcnt.triggered = 0; + /* Clean&invalidate the caches so we're sure the mmu tables for the dump buffer is valid */ + ret = queue_work(kbdev->hwcnt.cache_clean_wq, &kbdev->hwcnt.cache_clean_work); + KBASE_DEBUG_ASSERT(ret); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Wait for cacheclean to complete */ + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + + KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE); + + /* Schedule the context in */ + kbasep_js_schedule_privileged_ctx(kbdev, kctx); + + /* Configure */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_OFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), setup->dump_buffer & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), setup->dump_buffer >> 32, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), setup->jm_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), setup->shader_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), setup->l3_cache_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), setup->mmu_l2_bm, kctx); + /* Due to PRLAM-8186 we need to disable the Tiler before we enable the HW counter dump. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), 0, kctx); + else + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), setup->tiler_bm, kctx); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_MANUAL, kctx); + + /* If HW has PRLAM-8186 we can now re-enable the tiler HW counters dump */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), setup->tiler_bm, kctx); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + err = MALI_ERROR_NONE; + + dev_dbg(kbdev->dev, "HW counters dumping set-up for context %p", kctx); + return err; + out_unrequest_cores: + kbase_pm_unrequest_cores(kbdev, MALI_TRUE, shader_cores_needed); + kbase_pm_context_idle(kbdev); + out_err: + return err; +} + +/** + * @brief Enable HW counters collection + * + * Note: will wait for a cache clean to complete + */ +mali_error kbase_instr_hwcnt_enable(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup) +{ + struct kbase_device *kbdev; + mali_bool access_allowed; + + kbdev = kctx->kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + /* Determine if the calling task has access to this capability */ + access_allowed = kbase_security_has_capability(kctx, KBASE_SEC_INSTR_HW_COUNTERS_COLLECT, KBASE_SEC_FLAG_NOAUDIT); + if (MALI_FALSE == access_allowed) + return MALI_ERROR_FUNCTION_FAILED; + + return kbase_instr_hwcnt_enable_internal(kbdev, kctx, setup); +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_enable) + +/** + * @brief Disable HW counters collection + * + * Note: might sleep, waiting for an ongoing dump to complete + */ +mali_error kbase_instr_hwcnt_disable(struct kbase_context *kctx) +{ + unsigned long flags, pm_flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + u32 irq_mask; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + while (1) { + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_DISABLED) { + /* Instrumentation is not enabled */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out; + } + + if (kbdev->hwcnt.kctx != kctx) { + /* Instrumentation has been setup for another context */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out; + } + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE) + break; + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Ongoing dump/setup - wait for its completion */ + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + } + + kbdev->hwcnt.state = KBASE_INSTR_STATE_DISABLED; + kbdev->hwcnt.triggered = 0; + + /* Disable interrupt */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask & ~PRFCNT_SAMPLE_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags); + + /* Disable the counters */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), 0, kctx); + + kbdev->hwcnt.kctx = NULL; + kbdev->hwcnt.addr = 0ULL; + + kbase_pm_ca_instr_disable(kbdev); + + kbase_pm_unrequest_cores(kbdev, MALI_TRUE, kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER)); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Release the context. This had its own Power Manager Active reference */ + kbasep_js_release_privileged_ctx(kbdev, kctx); + + /* Also release our Power Manager Active reference */ + kbase_pm_context_idle(kbdev); + + dev_dbg(kbdev->dev, "HW counters dumping disabled for context %p", kctx); + + err = MALI_ERROR_NONE; + + out: + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_disable) + +/** + * @brief Configure HW counters collection + */ +mali_error kbase_instr_hwcnt_setup(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup) +{ + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + if (NULL == setup) { + /* Bad parameter - abort */ + goto out; + } + + if (setup->dump_buffer != 0ULL) { + /* Enable HW counters */ + err = kbase_instr_hwcnt_enable(kctx, setup); + } else { + /* Disable HW counters */ + err = kbase_instr_hwcnt_disable(kctx); + } + + out: + return err; +} + +/** + * @brief Issue Dump command to hardware + * + * Notes: + * - does not sleep + */ +mali_error kbase_instr_hwcnt_dump_irq(struct kbase_context *kctx) +{ + unsigned long flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.kctx != kctx) { + /* The instrumentation has been setup for another context */ + goto unlock; + } + + if (kbdev->hwcnt.state != KBASE_INSTR_STATE_IDLE) { + /* HW counters are disabled or another dump is ongoing, or we're resetting */ + goto unlock; + } + + kbdev->hwcnt.triggered = 0; + + /* Mark that we're dumping - the PF handler can signal that we faulted */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_DUMPING; + + /* Reconfigure the dump address */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), kbdev->hwcnt.addr & 0xFFFFFFFF, NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), kbdev->hwcnt.addr >> 32, NULL); + + /* Start dumping */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_PRFCNT_SAMPLE, NULL, NULL, kbdev->hwcnt.addr, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_PRFCNT_SAMPLE, kctx); + + dev_dbg(kbdev->dev, "HW counters dumping done for context %p", kctx); + + err = MALI_ERROR_NONE; + + unlock: + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_irq) + +/** + * @brief Tell whether the HW counters dump has completed + * + * Notes: + * - does not sleep + * - success will be set to MALI_TRUE if the dump succeeded or + * MALI_FALSE on failure + */ +mali_bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx, mali_bool * const success) +{ + unsigned long flags; + mali_bool complete = MALI_FALSE; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != success); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE) { + *success = MALI_TRUE; + complete = MALI_TRUE; + } else if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) { + *success = MALI_FALSE; + complete = MALI_TRUE; + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + } + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + return complete; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_complete) + +/** + * @brief Issue Dump command to hardware and wait for completion + */ +mali_error kbase_instr_hwcnt_dump(struct kbase_context *kctx) +{ + unsigned long flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + err = kbase_instr_hwcnt_dump_irq(kctx); + if (MALI_ERROR_NONE != err) { + /* Can't dump HW counters */ + goto out; + } + + /* Wait for dump & cacheclean to complete */ + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) { + err = MALI_ERROR_FUNCTION_FAILED; + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + } else { + /* Dump done */ + KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE); + err = MALI_ERROR_NONE; + } + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + out: + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump) + +/** + * @brief Clear the HW counters + */ +mali_error kbase_instr_hwcnt_clear(struct kbase_context *kctx) +{ + unsigned long flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + + /* Check it's the context previously set up and we're not already dumping */ + if (kbdev->hwcnt.kctx != kctx || kbdev->hwcnt.state != KBASE_INSTR_STATE_IDLE) + goto out; + + /* Clear the counters */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_PRFCNT_CLEAR, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_PRFCNT_CLEAR, kctx); + + err = MALI_ERROR_NONE; + + out: + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_clear) + +/** + * Workqueue for handling cache cleaning + */ +void kbasep_cache_clean_worker(struct work_struct *data) +{ + struct kbase_device *kbdev; + unsigned long flags; + + kbdev = container_of(data, struct kbase_device, hwcnt.cache_clean_work); + + mutex_lock(&kbdev->cacheclean_lock); + kbasep_instr_hwcnt_cacheclean(kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Wait for our condition, and any reset to complete */ + while (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING || + kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANING) { + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.cache_clean_wait, + (kbdev->hwcnt.state != KBASE_INSTR_STATE_RESETTING + && kbdev->hwcnt.state != KBASE_INSTR_STATE_CLEANING)); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANED); + + /* All finished and idle */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + mutex_unlock(&kbdev->cacheclean_lock); +} + +/** + * @brief Dump complete interrupt received + */ +void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) { + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + } else if (kbdev->hwcnt.state == KBASE_INSTR_STATE_DUMPING) { + int ret; + /* Always clean and invalidate the cache after a successful dump */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_REQUEST_CLEAN; + ret = queue_work(kbdev->hwcnt.cache_clean_wq, &kbdev->hwcnt.cache_clean_work); + KBASE_DEBUG_ASSERT(ret); + } + /* NOTE: In the state KBASE_INSTR_STATE_RESETTING, We're in a reset, + * and the instrumentation state hasn't been restored yet - + * kbasep_reset_timeout_worker() will do the rest of the work */ + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); +} + +/** + * @brief Cache clean interrupt received + */ +void kbase_clean_caches_done(struct kbase_device *kbdev) +{ + u32 irq_mask; + + if (kbdev->hwcnt.state != KBASE_INSTR_STATE_DISABLED) { + unsigned long flags; + unsigned long pm_flags; + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Disable interrupt */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask & ~CLEAN_CACHES_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags); + + /* Wakeup... */ + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANING) { + /* Only wake if we weren't resetting */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANED; + wake_up(&kbdev->hwcnt.cache_clean_wait); + } + /* NOTE: In the state KBASE_INSTR_STATE_RESETTING, We're in a reset, + * and the instrumentation state hasn't been restored yet - + * kbasep_reset_timeout_worker() will do the rest of the work */ + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + } +} + + +/* Disable instrumentation and wait for any existing dump to complete + * It's assumed that there's only one privileged context + * Safe to do this without lock when doing an OS suspend, because it only + * changes in response to user-space IOCTLs */ +void kbase_instr_hwcnt_suspend(struct kbase_device *kbdev) +{ + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(!kbdev->hwcnt.suspended_kctx); + + kctx = kbdev->hwcnt.kctx; + kbdev->hwcnt.suspended_kctx = kctx; + + /* Relevant state was saved into hwcnt.suspended_state when enabling the + * counters */ + + if (kctx) { + KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED); + kbase_instr_hwcnt_disable(kctx); + } +} + +void kbase_instr_hwcnt_resume(struct kbase_device *kbdev) +{ + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(kbdev); + + kctx = kbdev->hwcnt.suspended_kctx; + kbdev->hwcnt.suspended_kctx = NULL; + + if (kctx) { + mali_error err; + err = kbase_instr_hwcnt_enable_internal(kbdev, kctx, &kbdev->hwcnt.suspended_state); + WARN(err != MALI_ERROR_NONE, + "Failed to restore instrumented hardware counters on resume\n"); + } +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd.c new file mode 100644 index 0000000000000000000000000000000000000000..e15c8e2518d86ea01a98b8cbcca396a2e560bf96 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd.c @@ -0,0 +1,1727 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#if defined(CONFIG_DMA_SHARED_BUFFER) +#include +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ +#ifdef CONFIG_COMPAT +#include +#endif +#include +#include +#include +#include +#ifdef CONFIG_UMP +#include +#endif /* CONFIG_UMP */ +#include + +#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) +/* random32 was renamed to prandom_u32 in 3.8 */ +#define prandom_u32 random32 +#endif + +/* + * This is the kernel side of the API. Only entry points are: + * - kbase_jd_submit(): Called from userspace to submit a single bag + * - kbase_jd_done(): Called from interrupt context to track the + * completion of a job. + * Callouts: + * - to the job manager (enqueue a job) + * - to the event subsystem (signals the completion/failure of bag/job-chains). + */ + +static void __user * +get_compat_pointer(struct kbase_context *kctx, const union kbase_pointer *p) +{ +#ifdef CONFIG_COMPAT + if (kctx->is_compat) + return compat_ptr(p->compat_value); + else +#endif + return p->value; +} + +/* Runs an atom, either by handing to the JS or by immediately running it in the case of soft-jobs + * + * Returns whether the JS needs a reschedule. + * + * Note that the caller must also check the atom status and + * if it is KBASE_JD_ATOM_STATE_COMPLETED must call jd_done_nolock + */ +static int jd_run_atom(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED); + + if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) == BASE_JD_REQ_DEP) { + /* Dependency only atom */ + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + return 0; + } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { + /* Soft-job */ + if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (!kbase_replay_process(katom)) + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + } else if (kbase_process_soft_job(katom) == 0) { + kbase_finish_soft_job(katom); + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + } else { + /* The job has not completed */ + list_add_tail(&katom->dep_item[0], &kctx->waiting_soft_jobs); + } + return 0; + } + + katom->status = KBASE_JD_ATOM_STATE_IN_JS; + /* Queue an action about whether we should try scheduling a context */ + return kbasep_js_add_job(kctx, katom); +} + +#ifdef CONFIG_KDS + +/* Add the katom to the kds waiting list. + * Atoms must be added to the waiting list after a successful call to kds_async_waitall. + * The caller must hold the kbase_jd_context.lock */ + +static void kbase_jd_kds_waiters_add(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(katom); + + kctx = katom->kctx; + + list_add_tail(&katom->node, &kctx->waiting_kds_resource); +} + +/* Remove the katom from the kds waiting list. + * Atoms must be removed from the waiting list before a call to kds_resource_set_release_sync. + * The supplied katom must first have been added to the list with a call to kbase_jd_kds_waiters_add. + * The caller must hold the kbase_jd_context.lock */ + +static void kbase_jd_kds_waiters_remove(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + list_del(&katom->node); +} + +static void kds_dep_clear(void *callback_parameter, void *callback_extra_parameter) +{ + struct kbase_jd_atom *katom; + struct kbase_jd_context *ctx; + struct kbase_device *kbdev; + + katom = (struct kbase_jd_atom *)callback_parameter; + KBASE_DEBUG_ASSERT(katom); + ctx = &katom->kctx->jctx; + kbdev = katom->kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev); + + mutex_lock(&ctx->lock); + + /* KDS resource has already been satisfied (e.g. due to zapping) */ + if (katom->kds_dep_satisfied) + goto out; + + /* This atom's KDS dependency has now been met */ + katom->kds_dep_satisfied = MALI_TRUE; + + /* Check whether the atom's other dependencies were already met */ + if (!kbase_jd_katom_dep_atom(&katom->dep[0]) && + !kbase_jd_katom_dep_atom(&katom->dep[1])) { + /* katom dep complete, attempt to run it */ + mali_bool resched = MALI_FALSE; + + resched = jd_run_atom(katom); + + if (katom->status == KBASE_JD_ATOM_STATE_COMPLETED) { + /* The atom has already finished */ + resched |= jd_done_nolock(katom); + } + + if (resched) + kbasep_js_try_schedule_head_ctx(kbdev); + } + out: + mutex_unlock(&ctx->lock); +} + +static void kbase_cancel_kds_wait_job(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + + /* Prevent job_done_nolock from being called twice on an atom when + * there is a race between job completion and cancellation */ + + if (katom->status == KBASE_JD_ATOM_STATE_QUEUED) { + /* Wait was cancelled - zap the atom */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + if (jd_done_nolock(katom)) + kbasep_js_try_schedule_head_ctx(katom->kctx->kbdev); + } +} +#endif /* CONFIG_KDS */ + +#ifdef CONFIG_DMA_SHARED_BUFFER +static mali_error kbase_jd_umm_map(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + struct sg_table *sgt; + struct scatterlist *s; + int i; + phys_addr_t *pa; + mali_error err; + size_t count = 0; + + KBASE_DEBUG_ASSERT(reg->alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM); + KBASE_DEBUG_ASSERT(NULL == reg->alloc->imported.umm.sgt); + sgt = dma_buf_map_attachment(reg->alloc->imported.umm.dma_attachment, DMA_BIDIRECTIONAL); + + if (IS_ERR_OR_NULL(sgt)) + return MALI_ERROR_FUNCTION_FAILED; + + /* save for later */ + reg->alloc->imported.umm.sgt = sgt; + + pa = kbase_get_phy_pages(reg); + KBASE_DEBUG_ASSERT(pa); + + for_each_sg(sgt->sgl, s, sgt->nents, i) { + int j; + size_t pages = PFN_UP(sg_dma_len(s)); + + WARN_ONCE(sg_dma_len(s) & (PAGE_SIZE-1), + "sg_dma_len(s)=%u is not a multiple of PAGE_SIZE\n", + sg_dma_len(s)); + + WARN_ONCE(sg_dma_address(s) & (PAGE_SIZE-1), + "sg_dma_address(s)=%llx is not aligned to PAGE_SIZE\n", + (unsigned long long) sg_dma_address(s)); + + for (j = 0; (j < pages) && (count < reg->nr_pages); j++, count++) + *pa++ = sg_dma_address(s) + (j << PAGE_SHIFT); + WARN_ONCE(j < pages, + "sg list from dma_buf_map_attachment > dma_buf->size=%zu\n", + reg->alloc->imported.umm.dma_buf->size); + } + + if (WARN_ONCE(count < reg->nr_pages, + "sg list from dma_buf_map_attachment < dma_buf->size=%zu\n", + reg->alloc->imported.umm.dma_buf->size)) { + err = MALI_ERROR_FUNCTION_FAILED; + goto out; + } + + /* Update nents as we now have pages to map */ + reg->alloc->nents = count; + + err = kbase_mmu_insert_pages(kctx, reg->start_pfn, kbase_get_phy_pages(reg), kbase_reg_current_backed_size(reg), reg->flags | KBASE_REG_GPU_WR | KBASE_REG_GPU_RD); + +out: + if (MALI_ERROR_NONE != err) { + dma_buf_unmap_attachment(reg->alloc->imported.umm.dma_attachment, reg->alloc->imported.umm.sgt, DMA_BIDIRECTIONAL); + reg->alloc->imported.umm.sgt = NULL; + } + + return err; +} + +static void kbase_jd_umm_unmap(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(alloc); + KBASE_DEBUG_ASSERT(alloc->imported.umm.dma_attachment); + KBASE_DEBUG_ASSERT(alloc->imported.umm.sgt); + dma_buf_unmap_attachment(alloc->imported.umm.dma_attachment, + alloc->imported.umm.sgt, DMA_BIDIRECTIONAL); + alloc->imported.umm.sgt = NULL; + alloc->nents = 0; +} +#endif /* CONFIG_DMA_SHARED_BUFFER */ + +void kbase_jd_free_external_resources(struct kbase_jd_atom *katom) +{ +#ifdef CONFIG_KDS + if (katom->kds_rset) { + struct kbase_jd_context *jctx = &katom->kctx->jctx; + + /* + * As the atom is no longer waiting, remove it from + * the waiting list. + */ + + mutex_lock(&jctx->lock); + kbase_jd_kds_waiters_remove(katom); + mutex_unlock(&jctx->lock); + + /* Release the kds resource or cancel if zapping */ + kds_resource_set_release_sync(&katom->kds_rset); + } +#endif /* CONFIG_KDS */ +} + +static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); + +#ifdef CONFIG_KDS + /* Prevent the KDS resource from triggering the atom in case of zapping */ + if (katom->kds_rset) + katom->kds_dep_satisfied = MALI_TRUE; +#endif /* CONFIG_KDS */ + + kbase_gpu_vm_lock(katom->kctx); + /* only roll back if extres is non-NULL */ + if (katom->extres) { + u32 res_no; + + res_no = katom->nr_extres; + while (res_no-- > 0) { + struct kbase_mem_phy_alloc *alloc = katom->extres[res_no].alloc; +#ifdef CONFIG_DMA_SHARED_BUFFER + if (alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) { + alloc->imported.umm.current_mapping_usage_count--; + + if (0 == alloc->imported.umm.current_mapping_usage_count) { + struct kbase_va_region *reg; + + reg = kbase_region_tracker_find_region_base_address( + katom->kctx, + katom->extres[res_no].gpu_address); + + if (reg && reg->alloc == alloc) + kbase_mmu_teardown_pages( + katom->kctx, + reg->start_pfn, + kbase_reg_current_backed_size(reg)); + + kbase_jd_umm_unmap(katom->kctx, alloc); + } + } +#endif /* CONFIG_DMA_SHARED_BUFFER */ + kbase_mem_phy_alloc_put(katom->extres[res_no].alloc); + } + kfree(katom->extres); + katom->extres = NULL; + } + kbase_gpu_vm_unlock(katom->kctx); +} + +#if (defined(CONFIG_KDS) && defined(CONFIG_UMP)) || defined(CONFIG_DMA_SHARED_BUFFER_USES_KDS) +static void add_kds_resource(struct kds_resource *kds_res, struct kds_resource **kds_resources, u32 *kds_res_count, unsigned long *kds_access_bitmap, mali_bool exclusive) +{ + u32 i; + + for (i = 0; i < *kds_res_count; i++) { + /* Duplicate resource, ignore */ + if (kds_resources[i] == kds_res) + return; + } + + kds_resources[*kds_res_count] = kds_res; + if (exclusive) + set_bit(*kds_res_count, kds_access_bitmap); + (*kds_res_count)++; +} +#endif + +/* + * Set up external resources needed by this job. + * + * jctx.lock must be held when this is called. + */ + +static mali_error kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const struct base_jd_atom_v2 *user_atom) +{ + mali_error err_ret_val = MALI_ERROR_FUNCTION_FAILED; + u32 res_no; +#ifdef CONFIG_KDS + u32 kds_res_count = 0; + struct kds_resource **kds_resources = NULL; + unsigned long *kds_access_bitmap = NULL; +#endif /* CONFIG_KDS */ + struct base_external_resource *input_extres; + + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); + + /* no resources encoded, early out */ + if (!katom->nr_extres) + return MALI_ERROR_FUNCTION_FAILED; + + katom->extres = kmalloc_array(katom->nr_extres, sizeof(*katom->extres), GFP_KERNEL); + if (NULL == katom->extres) { + err_ret_val = MALI_ERROR_OUT_OF_MEMORY; + goto early_err_out; + } + + /* copy user buffer to the end of our real buffer. + * Make sure the struct sizes haven't changed in a way + * we don't support */ + BUILD_BUG_ON(sizeof(*input_extres) > sizeof(*katom->extres)); + input_extres = (struct base_external_resource *) + (((unsigned char *)katom->extres) + + (sizeof(*katom->extres) - sizeof(*input_extres)) * + katom->nr_extres); + + if (copy_from_user(input_extres, + get_compat_pointer(katom->kctx, &user_atom->extres_list), + sizeof(*input_extres) * katom->nr_extres) != 0) { + err_ret_val = MALI_ERROR_FUNCTION_FAILED; + goto early_err_out; + } +#ifdef CONFIG_KDS + /* assume we have to wait for all */ + KBASE_DEBUG_ASSERT(0 != katom->nr_extres); + kds_resources = kmalloc_array(katom->nr_extres, sizeof(struct kds_resource *), GFP_KERNEL); + + if (NULL == kds_resources) { + err_ret_val = MALI_ERROR_OUT_OF_MEMORY; + goto early_err_out; + } + + KBASE_DEBUG_ASSERT(0 != katom->nr_extres); + kds_access_bitmap = kzalloc(sizeof(unsigned long) * ((katom->nr_extres + BITS_PER_LONG - 1) / BITS_PER_LONG), GFP_KERNEL); + + if (NULL == kds_access_bitmap) { + err_ret_val = MALI_ERROR_OUT_OF_MEMORY; + goto early_err_out; + } +#endif /* CONFIG_KDS */ + + /* need to keep the GPU VM locked while we set up UMM buffers */ + kbase_gpu_vm_lock(katom->kctx); + for (res_no = 0; res_no < katom->nr_extres; res_no++) { + struct base_external_resource *res; + struct kbase_va_region *reg; + + res = &input_extres[res_no]; + reg = kbase_region_tracker_find_region_enclosing_address(katom->kctx, + res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE); + /* did we find a matching region object? */ + if (NULL == reg || (reg->flags & KBASE_REG_FREE)) { + /* roll back */ + goto failed_loop; + } + + /* decide what needs to happen for this resource */ + switch (reg->alloc->type) { + case BASE_TMEM_IMPORT_TYPE_UMP: + { +#if defined(CONFIG_KDS) && defined(CONFIG_UMP) + struct kds_resource *kds_res; + + kds_res = ump_dd_kds_resource_get(reg->alloc->imported.ump_handle); + if (kds_res) + add_kds_resource(kds_res, kds_resources, &kds_res_count, + kds_access_bitmap, + res->ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE); +#endif /*defined(CONFIG_KDS) && defined(CONFIG_UMP) */ + break; + } +#ifdef CONFIG_DMA_SHARED_BUFFER + case BASE_TMEM_IMPORT_TYPE_UMM: + { +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct kds_resource *kds_res; + + kds_res = get_dma_buf_kds_resource(reg->alloc->imported.umm.dma_buf); + if (kds_res) + add_kds_resource(kds_res, kds_resources, &kds_res_count, kds_access_bitmap, res->ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE); +#endif + reg->alloc->imported.umm.current_mapping_usage_count++; + if (1 == reg->alloc->imported.umm.current_mapping_usage_count) { + /* use a local variable to not pollute err_ret_val + * with a potential success value as some other gotos depend + * on the default error code stored in err_ret_val */ + mali_error tmp; + tmp = kbase_jd_umm_map(katom->kctx, reg); + if (MALI_ERROR_NONE != tmp) { + /* failed to map this buffer, roll back */ + err_ret_val = tmp; + reg->alloc->imported.umm.current_mapping_usage_count--; + goto failed_loop; + } + } + break; + } +#endif + default: + goto failed_loop; + } + + /* finish with updating out array with the data we found */ + /* NOTE: It is important that this is the last thing we do (or + * at least not before the first write) as we overwrite elements + * as we loop and could be overwriting ourself, so no writes + * until the last read for an element. + * */ + katom->extres[res_no].gpu_address = reg->start_pfn << PAGE_SHIFT; /* save the start_pfn (as an address, not pfn) to use fast lookup later */ + katom->extres[res_no].alloc = kbase_mem_phy_alloc_get(reg->alloc); + } + /* successfully parsed the extres array */ + /* drop the vm lock before we call into kds */ + kbase_gpu_vm_unlock(katom->kctx); + +#ifdef CONFIG_KDS + if (kds_res_count) { + int wait_failed; + + /* We have resources to wait for with kds */ + katom->kds_dep_satisfied = MALI_FALSE; + + wait_failed = kds_async_waitall(&katom->kds_rset, + &katom->kctx->jctx.kds_cb, katom, NULL, + kds_res_count, kds_access_bitmap, + kds_resources); + + if (wait_failed) + goto failed_kds_setup; + else + kbase_jd_kds_waiters_add(katom); + } else { + /* Nothing to wait for, so kds dep met */ + katom->kds_dep_satisfied = MALI_TRUE; + } + kfree(kds_resources); + kfree(kds_access_bitmap); +#endif /* CONFIG_KDS */ + + /* all done OK */ + return MALI_ERROR_NONE; + +/* error handling section */ + +#ifdef CONFIG_KDS + failed_kds_setup: + + /* lock before we unmap */ + kbase_gpu_vm_lock(katom->kctx); +#endif /* CONFIG_KDS */ + + failed_loop: + /* undo the loop work */ + while (res_no-- > 0) { + struct kbase_mem_phy_alloc *alloc = katom->extres[res_no].alloc; +#ifdef CONFIG_DMA_SHARED_BUFFER + if (alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) { + alloc->imported.umm.current_mapping_usage_count--; + + if (0 == alloc->imported.umm.current_mapping_usage_count) { + struct kbase_va_region *reg; + + reg = kbase_region_tracker_find_region_base_address( + katom->kctx, + katom->extres[res_no].gpu_address); + + if (reg && reg->alloc == alloc) + kbase_mmu_teardown_pages(katom->kctx, + reg->start_pfn, + kbase_reg_current_backed_size(reg)); + + kbase_jd_umm_unmap(katom->kctx, alloc); + } + } +#endif /* CONFIG_DMA_SHARED_BUFFER */ + kbase_mem_phy_alloc_put(alloc); + } + kbase_gpu_vm_unlock(katom->kctx); + + early_err_out: + kfree(katom->extres); + katom->extres = NULL; +#ifdef CONFIG_KDS + kfree(kds_resources); + kfree(kds_access_bitmap); +#endif /* CONFIG_KDS */ + return err_ret_val; +} + +STATIC INLINE void jd_resolve_dep(struct list_head *out_list, struct kbase_jd_atom *katom, u8 d, bool ctx_is_dying) +{ + u8 other_d = !d; + + while (!list_empty(&katom->dep_head[d])) { + struct kbase_jd_atom *dep_atom; + u8 dep_type; + + dep_atom = list_entry(katom->dep_head[d].next, + struct kbase_jd_atom, dep_item[d]); + dep_type = kbase_jd_katom_dep_type(&dep_atom->dep[d]); + + list_del(katom->dep_head[d].next); + + kbase_jd_katom_dep_clear(&dep_atom->dep[d]); + + if (katom->event_code != BASE_JD_EVENT_DONE && + (dep_type != BASE_JD_DEP_TYPE_ORDER || ctx_is_dying)) { + /* Atom failed, so remove the other dependencies and immediately fail the atom */ + if (kbase_jd_katom_dep_atom(&dep_atom->dep[other_d])) { + list_del(&dep_atom->dep_item[other_d]); + kbase_jd_katom_dep_clear(&dep_atom->dep[other_d]); + } +#ifdef CONFIG_KDS + if (!dep_atom->kds_dep_satisfied) { + /* Just set kds_dep_satisfied to true. If the callback happens after this then it will early out and + * do nothing. If the callback doesn't happen then kbase_jd_post_external_resources will clean up + */ + dep_atom->kds_dep_satisfied = MALI_TRUE; + } +#endif + /* at this point a dependency to the failed job is already removed */ + dep_atom->event_code = katom->event_code; + KBASE_DEBUG_ASSERT(dep_atom->status != KBASE_JD_ATOM_STATE_UNUSED); + dep_atom->status = KBASE_JD_ATOM_STATE_COMPLETED; + + list_add_tail(&dep_atom->dep_item[0], out_list); + } else if (!kbase_jd_katom_dep_atom(&dep_atom->dep[other_d])) { +#ifdef CONFIG_KDS + if (dep_atom->kds_dep_satisfied) +#endif + list_add_tail(&dep_atom->dep_item[0], out_list); + } + } +} + +KBASE_EXPORT_TEST_API(jd_resolve_dep) + +#if MALI_CUSTOMER_RELEASE == 0 +static void jd_force_failure(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + kbdev->force_replay_count++; + + if (kbdev->force_replay_count >= kbdev->force_replay_limit) { + kbdev->force_replay_count = 0; + katom->event_code = BASE_JD_EVENT_FORCE_REPLAY; + + if (kbdev->force_replay_random) + kbdev->force_replay_limit = + (prandom_u32() % KBASEP_FORCE_REPLAY_RANDOM_LIMIT) + 1; + + dev_info(kbdev->dev, "force_replay : promoting to error\n"); + } +} + +/** Test to see if atom should be forced to fail. + * + * This function will check if an atom has a replay job as a dependent. If so + * then it will be considered for forced failure. */ +static void jd_check_force_failure(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct kbase_device *kbdev = kctx->kbdev; + int i; + + if ((kbdev->force_replay_limit == KBASEP_FORCE_REPLAY_DISABLED) || + (katom->core_req & BASEP_JD_REQ_EVENT_NEVER)) + return; + + for (i = 1; i < BASE_JD_ATOM_COUNT; i++) { + if (kbase_jd_katom_dep_atom(&kctx->jctx.atoms[i].dep[0]) == katom || + kbase_jd_katom_dep_atom(&kctx->jctx.atoms[i].dep[1]) == katom) { + struct kbase_jd_atom *dep_atom = &kctx->jctx.atoms[i]; + + if ((dep_atom->core_req & BASEP_JD_REQ_ATOM_TYPE) == + BASE_JD_REQ_SOFT_REPLAY && + (dep_atom->core_req & kbdev->force_replay_core_req) + == kbdev->force_replay_core_req) { + jd_force_failure(kbdev, katom); + return; + } + } + } +} +#endif + +/* + * Perform the necessary handling of an atom that has finished running + * on the GPU. + * + * Note that if this is a soft-job that has had kbase_prepare_soft_job called on it then the caller + * is responsible for calling kbase_finish_soft_job *before* calling this function. + * + * The caller must hold the kbase_jd_context.lock. + */ +mali_bool jd_done_nolock(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info; + struct kbase_device *kbdev = kctx->kbdev; + struct list_head completed_jobs; + struct list_head runnable_jobs; + mali_bool need_to_try_schedule_context = MALI_FALSE; + int i; + + INIT_LIST_HEAD(&completed_jobs); + INIT_LIST_HEAD(&runnable_jobs); + + KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED); + +#if MALI_CUSTOMER_RELEASE == 0 + jd_check_force_failure(katom); +#endif + + + /* This is needed in case an atom is failed due to being invalid, this + * can happen *before* the jobs that the atom depends on have completed */ + for (i = 0; i < 2; i++) { + if (kbase_jd_katom_dep_atom(&katom->dep[i])) { + list_del(&katom->dep_item[i]); + kbase_jd_katom_dep_clear(&katom->dep[i]); + } + } + + /* With PRLAM-10817 or PRLAM-10959 the last tile of a fragment job being soft-stopped can fail with + * BASE_JD_EVENT_TILE_RANGE_FAULT. + * + * So here if the fragment job failed with TILE_RANGE_FAULT and it has been soft-stopped, then we promote the + * error code to BASE_JD_EVENT_DONE + */ + + if ((kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10817) || kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10959)) && + katom->event_code == BASE_JD_EVENT_TILE_RANGE_FAULT) { + if ((katom->core_req & BASE_JD_REQ_FS) && (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED)) { + /* Promote the failure to job done */ + katom->event_code = BASE_JD_EVENT_DONE; + katom->atom_flags = katom->atom_flags & (~KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED); + } + } + + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + list_add_tail(&katom->dep_item[0], &completed_jobs); + + while (!list_empty(&completed_jobs)) { + katom = list_entry(completed_jobs.prev, struct kbase_jd_atom, dep_item[0]); + list_del(completed_jobs.prev); + + KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED); + + for (i = 0; i < 2; i++) + jd_resolve_dep(&runnable_jobs, katom, i, + js_kctx_info->ctx.is_dying); + + if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) + kbase_jd_post_external_resources(katom); + + while (!list_empty(&runnable_jobs)) { + struct kbase_jd_atom *node; + + node = list_entry(runnable_jobs.prev, struct kbase_jd_atom, dep_item[0]); + + list_del(runnable_jobs.prev); + + KBASE_DEBUG_ASSERT(node->status != KBASE_JD_ATOM_STATE_UNUSED); + + if (node->status != KBASE_JD_ATOM_STATE_COMPLETED) { + need_to_try_schedule_context |= jd_run_atom(node); + } else { + node->event_code = katom->event_code; + + if ((node->core_req & BASEP_JD_REQ_ATOM_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(node)) + /* Don't complete this atom */ + continue; + } else if (node->core_req & + BASE_JD_REQ_SOFT_JOB) { + /* If this is a fence wait then remove it from the list of sync waiters. */ + if (BASE_JD_REQ_SOFT_FENCE_WAIT == node->core_req) + list_del(&node->dep_item[0]); + + kbase_finish_soft_job(node); + } + node->status = KBASE_JD_ATOM_STATE_COMPLETED; + } + + if (node->status == KBASE_JD_ATOM_STATE_COMPLETED) + list_add_tail(&node->dep_item[0], &completed_jobs); + } + + /* Register a completed job as a disjoint event when the GPU + * is in a disjoint state (ie. being reset or replaying jobs). + */ + kbase_disjoint_event_potential(kctx->kbdev); + kbase_event_post(kctx, katom); + + /* Decrement and check the TOTAL number of jobs. This includes + * those not tracked by the scheduler: 'not ready to run' and + * 'dependency-only' jobs. */ + if (--kctx->jctx.job_nr == 0) + wake_up(&kctx->jctx.zero_jobs_wait); /* All events are safely queued now, and we can signal any waiter + * that we've got no more jobs (so we can be safely terminated) */ + } + + return need_to_try_schedule_context; +} + +KBASE_EXPORT_TEST_API(jd_done_nolock) + +#ifdef CONFIG_GPU_TRACEPOINTS +enum { + CORE_REQ_DEP_ONLY, + CORE_REQ_SOFT, + CORE_REQ_COMPUTE, + CORE_REQ_FRAGMENT, + CORE_REQ_VERTEX, + CORE_REQ_TILER, + CORE_REQ_FRAGMENT_VERTEX, + CORE_REQ_FRAGMENT_VERTEX_TILER, + CORE_REQ_FRAGMENT_TILER, + CORE_REQ_VERTEX_TILER, + CORE_REQ_UNKNOWN +}; +static const char * const core_req_strings[] = { + "Dependency Only Job", + "Soft Job", + "Compute Shader Job", + "Fragment Shader Job", + "Vertex/Geometry Shader Job", + "Tiler Job", + "Fragment Shader + Vertex/Geometry Shader Job", + "Fragment Shader + Vertex/Geometry Shader Job + Tiler Job", + "Fragment Shader + Tiler Job", + "Vertex/Geometry Shader Job + Tiler Job", + "Unknown Job" +}; +static const char *kbasep_map_core_reqs_to_string(base_jd_core_req core_req) +{ + if (core_req & BASE_JD_REQ_SOFT_JOB) + return core_req_strings[CORE_REQ_SOFT]; + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) + return core_req_strings[CORE_REQ_COMPUTE]; + switch (core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) { + case BASE_JD_REQ_DEP: + return core_req_strings[CORE_REQ_DEP_ONLY]; + case BASE_JD_REQ_FS: + return core_req_strings[CORE_REQ_FRAGMENT]; + case BASE_JD_REQ_CS: + return core_req_strings[CORE_REQ_VERTEX]; + case BASE_JD_REQ_T: + return core_req_strings[CORE_REQ_TILER]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_CS): + return core_req_strings[CORE_REQ_FRAGMENT_VERTEX]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_FRAGMENT_TILER]; + case (BASE_JD_REQ_CS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_VERTEX_TILER]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_FRAGMENT_VERTEX_TILER]; + } + return core_req_strings[CORE_REQ_UNKNOWN]; +} +#endif + +mali_bool jd_submit_atom(struct kbase_context *kctx, + const struct base_jd_atom_v2 *user_atom, + struct kbase_jd_atom *katom) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + base_jd_core_req core_req; + int queued = 0; + int i; + mali_bool ret; + + /* Update the TOTAL number of jobs. This includes those not tracked by + * the scheduler: 'not ready to run' and 'dependency-only' jobs. */ + jctx->job_nr++; + + core_req = user_atom->core_req; + + katom->start_timestamp.tv64 = 0; + katom->time_spent_us = 0; + katom->udata = user_atom->udata; + katom->kctx = kctx; + katom->nr_extres = user_atom->nr_extres; + katom->extres = NULL; + katom->device_nr = user_atom->device_nr; + katom->affinity = 0; + katom->jc = user_atom->jc; + katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED; + katom->core_req = core_req; + katom->nice_prio = user_atom->prio; + katom->atom_flags = 0; + katom->retry_count = 0; + +#ifdef CONFIG_KDS + /* Start by assuming that the KDS dependencies are satisfied, + * kbase_jd_pre_external_resources will correct this if there are dependencies */ + katom->kds_dep_satisfied = MALI_TRUE; + katom->kds_rset = NULL; +#endif /* CONFIG_KDS */ + + /* Don't do anything if there is a mess up with dependencies. + This is done in a separate cycle to check both the dependencies at ones, otherwise + it will be extra complexity to deal with 1st dependency ( just added to the list ) + if only the 2nd one has invalid config. + */ + for (i = 0; i < 2; i++) { + int dep_atom_number = user_atom->pre_dep[i].atom_id; + base_jd_dep_type dep_atom_type = user_atom->pre_dep[i].dependency_type; + + if (dep_atom_number) { + if ( dep_atom_type != BASE_JD_DEP_TYPE_ORDER && + dep_atom_type != BASE_JD_DEP_TYPE_DATA ) { + katom->event_code = BASE_JD_EVENT_JOB_CONFIG_FAULT; + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + ret = jd_done_nolock(katom); + goto out; + } + } + } + + /* Add dependencies */ + for (i = 0; i < 2; i++) { + int dep_atom_number = user_atom->pre_dep[i].atom_id; + base_jd_dep_type dep_atom_type = user_atom->pre_dep[i].dependency_type; + + kbase_jd_katom_dep_clear(&katom->dep[i]); + + if (dep_atom_number) { + struct kbase_jd_atom *dep_atom = &jctx->atoms[dep_atom_number]; + + if (dep_atom->status == KBASE_JD_ATOM_STATE_UNUSED || dep_atom->status == KBASE_JD_ATOM_STATE_COMPLETED) { + if (dep_atom->event_code != BASE_JD_EVENT_DONE) { + /* don't stop this atom if it has an order dependency only to the failed one, + try to submit it throught the normal path */ + if ( dep_atom_type == BASE_JD_DEP_TYPE_ORDER && + dep_atom->event_code > BASE_JD_EVENT_ACTIVE) { + continue; + } + + if (i == 1 && kbase_jd_katom_dep_atom(&katom->dep[0])) { + /* Remove the previous dependency */ + list_del(&katom->dep_item[0]); + kbase_jd_katom_dep_clear(&katom->dep[0]); + } + + /* Atom has completed, propagate the error code if any */ + katom->event_code = dep_atom->event_code; + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + if ((katom->core_req & + BASEP_JD_REQ_ATOM_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(katom)) { + ret = MALI_FALSE; + goto out; + } + } + ret = jd_done_nolock(katom); + + goto out; + } + } else { + /* Atom is in progress, add this atom to the list */ + list_add_tail(&katom->dep_item[i], &dep_atom->dep_head[i]); + kbase_jd_katom_dep_set(&katom->dep[i], dep_atom, dep_atom_type); + queued = 1; + } + } + } + + /* These must occur after the above loop to ensure that an atom that + * depends on a previous atom with the same number behaves as expected */ + katom->event_code = BASE_JD_EVENT_DONE; + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + + /* Reject atoms with job chain = NULL, as these cause issues with soft-stop */ + if (0 == katom->jc && (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) { + dev_warn(kctx->kbdev->dev, "Rejecting atom with jc = NULL"); + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + + /* Reject atoms with an invalid device_nr */ + if ((katom->core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) && + (katom->device_nr >= kctx->kbdev->gpu_props.num_core_groups)) { + dev_warn(kctx->kbdev->dev, "Rejecting atom with invalid device_nr %d", katom->device_nr); + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + + /* + * If the priority is increased we need to check the caller has security caps to do this, if + * priority is decreased then this is ok as the result will have no negative impact on other + * processes running. + */ + if (0 > katom->nice_prio) { + mali_bool access_allowed; + + access_allowed = kbase_security_has_capability(kctx, + KBASE_SEC_MODIFY_PRIORITY, KBASE_SEC_FLAG_NOAUDIT); + + if (!access_allowed) { + /* For unprivileged processes - a negative priority is interpreted as zero */ + katom->nice_prio = 0; + } + } + + /* Scale priority range to use NICE range */ + if (katom->nice_prio) { + /* Remove sign for calculation */ + int nice_priority = katom->nice_prio + 128; + + /* Fixed point maths to scale from ..255 to 0..39 (NICE range with +20 offset) */ + katom->nice_prio = (((20 << 16) / 128) * nice_priority) >> 16; + } + + if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { + /* handle what we need to do to access the external resources */ + if (MALI_ERROR_NONE != kbase_jd_pre_external_resources(katom, user_atom)) { + /* setup failed (no access, bad resource, unknown resource types, etc.) */ + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + } + + /* Initialize the jobscheduler policy for this atom. Function will + * return error if the atom is malformed. + * + * Soft-jobs never enter the job scheduler but have their own initialize method. + * + * If either fail then we immediately complete the atom with an error. + */ + if ((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0) { + union kbasep_js_policy *js_policy = &(kctx->kbdev->js_data.policy); + + if (MALI_ERROR_NONE != kbasep_js_policy_init_job(js_policy, kctx, katom)) { + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + } else { + /* Soft-job */ + if (MALI_ERROR_NONE != kbase_prepare_soft_job(katom)) { + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + } + +#ifdef CONFIG_GPU_TRACEPOINTS + katom->work_id = atomic_inc_return(&jctx->work_id); + trace_gpu_job_enqueue((u32)kctx->id, katom->work_id, kbasep_map_core_reqs_to_string(katom->core_req)); +#endif + + if (queued) { + ret = MALI_FALSE; + goto out; + } +#ifdef CONFIG_KDS + if (!katom->kds_dep_satisfied) { + /* Queue atom due to KDS dependency */ + ret = MALI_FALSE; + goto out; + } +#endif /* CONFIG_KDS */ + + if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(katom)) + ret = MALI_FALSE; + else + ret = jd_done_nolock(katom); + + goto out; + } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { + if (kbase_process_soft_job(katom) == 0) { + kbase_finish_soft_job(katom); + ret = jd_done_nolock(katom); + goto out; + } + /* The job has not yet completed */ + list_add_tail(&katom->dep_item[0], &kctx->waiting_soft_jobs); + ret = MALI_FALSE; + } else if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) { + katom->status = KBASE_JD_ATOM_STATE_IN_JS; + ret = kbasep_js_add_job(kctx, katom); + } else { + /* This is a pure dependency. Resolve it immediately */ + ret = jd_done_nolock(katom); + } + + out: + return ret; +} + +#ifdef BASE_LEGACY_UK6_SUPPORT +mali_error kbase_jd_submit(struct kbase_context *kctx, + const struct kbase_uk_job_submit *submit_data, + int uk6_atom) +#else +mali_error kbase_jd_submit(struct kbase_context *kctx, + const struct kbase_uk_job_submit *submit_data) +#endif /* BASE_LEGACY_UK6_SUPPORT */ +{ + struct kbase_jd_context *jctx = &kctx->jctx; + mali_error err = MALI_ERROR_NONE; + int i; + mali_bool need_to_try_schedule_context = MALI_FALSE; + struct kbase_device *kbdev; + void __user *user_addr; + + /* + * kbase_jd_submit isn't expected to fail and so all errors with the jobs + * are reported by immediately falling them (through event system) + */ + kbdev = kctx->kbdev; + + beenthere(kctx, "%s", "Enter"); + + if ((kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) != 0) { + dev_err(kbdev->dev, "Attempt to submit to a context that has SUBMIT_DISABLED set on it"); + return MALI_ERROR_FUNCTION_FAILED; + } + +#ifdef BASE_LEGACY_UK6_SUPPORT + if ((uk6_atom && submit_data->stride != + sizeof(struct base_jd_atom_v2_uk6)) || + submit_data->stride != sizeof(base_jd_atom_v2)) { +#else + if (submit_data->stride != sizeof(base_jd_atom_v2)) { +#endif /* BASE_LEGACY_UK6_SUPPORT */ + dev_err(kbdev->dev, "Stride passed to job_submit doesn't match kernel"); + return MALI_ERROR_FUNCTION_FAILED; + } + + user_addr = get_compat_pointer(kctx, &submit_data->addr); + + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_add_return(submit_data->nr_atoms, &kctx->timeline.jd_atoms_in_flight)); + + for (i = 0; i < submit_data->nr_atoms; i++) { + struct base_jd_atom_v2 user_atom; + struct kbase_jd_atom *katom; + +#ifdef BASE_LEGACY_UK6_SUPPORT + if (uk6_atom) { + struct base_jd_atom_v2_uk6 user_atom_v6; + base_jd_dep_type dep_types[2] = {BASE_JD_DEP_TYPE_DATA, BASE_JD_DEP_TYPE_DATA}; + + if (copy_from_user(&user_atom_v6, user_addr, + sizeof(user_atom_v6))) { + err = MALI_ERROR_FUNCTION_FAILED; + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, + atomic_sub_return( + submit_data->nr_atoms - i, + &kctx->timeline.jd_atoms_in_flight)); + break; + } + /* Convert from UK6 atom format to UK7 format */ + user_atom.jc = user_atom_v6.jc; + user_atom.udata = user_atom_v6.udata; + user_atom.extres_list = user_atom_v6.extres_list; + user_atom.nr_extres = user_atom_v6.nr_extres; + user_atom.core_req = user_atom_v6.core_req; + + /* atom number 0 is used for no dependency atoms */ + if (!user_atom_v6.pre_dep[0]) + dep_types[0] = BASE_JD_DEP_TYPE_INVALID; + + base_jd_atom_dep_set(&user_atom.pre_dep[0], + user_atom_v6.pre_dep[0], + dep_types[0]); + + /* atom number 0 is used for no dependency atoms */ + if (!user_atom_v6.pre_dep[1]) + dep_types[1] = BASE_JD_DEP_TYPE_INVALID; + + base_jd_atom_dep_set(&user_atom.pre_dep[1], + user_atom_v6.pre_dep[1], + dep_types[1]); + + user_atom.atom_number = user_atom_v6.atom_number; + user_atom.prio = user_atom_v6.prio; + user_atom.device_nr = user_atom_v6.device_nr; + } else { +#endif /* BASE_LEGACY_UK6_SUPPORT */ + if (copy_from_user(&user_atom, user_addr, sizeof(user_atom)) != 0) { + err = MALI_ERROR_FUNCTION_FAILED; + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_sub_return(submit_data->nr_atoms - i, &kctx->timeline.jd_atoms_in_flight)); + break; + } +#ifdef BASE_LEGACY_UK6_SUPPORT + } +#endif /* BASE_LEGACY_UK6_SUPPORT */ + + user_addr = (void __user *)((uintptr_t) user_addr + submit_data->stride); + + mutex_lock(&jctx->lock); + katom = &jctx->atoms[user_atom.atom_number]; + + while (katom->status != KBASE_JD_ATOM_STATE_UNUSED) { + /* Atom number is already in use, wait for the atom to + * complete + */ + mutex_unlock(&jctx->lock); + + /* This thread will wait for the atom to complete. Due + * to thread scheduling we are not sure that the other + * thread that owns the atom will also schedule the + * context, so we force the scheduler to be active and + * hence eventually schedule this context at some point + * later. + */ + kbasep_js_try_schedule_head_ctx(kctx->kbdev); + if (wait_event_killable(katom->completed, + katom->status == KBASE_JD_ATOM_STATE_UNUSED)) { + /* We're being killed so the result code + * doesn't really matter + */ + return MALI_ERROR_NONE; + } + mutex_lock(&jctx->lock); + } + + need_to_try_schedule_context |= + jd_submit_atom(kctx, &user_atom, katom); + + /* Register a completed job as a disjoint event when the GPU is in a disjoint state + * (ie. being reset or replaying jobs). + */ + kbase_disjoint_event_potential(kbdev); + + mutex_unlock(&jctx->lock); + } + + if (need_to_try_schedule_context) + kbasep_js_try_schedule_head_ctx(kbdev); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_jd_submit) + +static void kbasep_jd_cacheclean(struct kbase_device *kbdev) +{ + /* Limit the number of loops to avoid a hang if the interrupt is missed */ + u32 max_loops = KBASE_CLEAN_CACHE_MAX_LOOPS; + + mutex_lock(&kbdev->cacheclean_lock); + + /* use GPU_COMMAND completion solution */ + /* clean & invalidate the caches */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CLEAN_INV_CACHES, NULL); + + /* wait for cache flush to complete before continuing */ + while (--max_loops && (kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL) & CLEAN_CACHES_COMPLETED) == 0) + ; + + /* clear the CLEAN_CACHES_COMPLETED irq */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, NULL, 0u, CLEAN_CACHES_COMPLETED); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), CLEAN_CACHES_COMPLETED, NULL); + KBASE_DEBUG_ASSERT_MSG(kbdev->hwcnt.state != KBASE_INSTR_STATE_CLEANING, + "Instrumentation code was cleaning caches, but Job Management code cleared their IRQ - Instrumentation code will now hang."); + + mutex_unlock(&kbdev->cacheclean_lock); +} + +/** + * This function: + * - requeues the job from the runpool (if it was soft-stopped/removed from NEXT registers) + * - removes it from the system if it finished/failed/was cancelled. + * - resolves dependencies to add dependent jobs to the context, potentially starting them if necessary (which may add more references to the context) + * - releases the reference to the context from the no-longer-running job. + * - Handles retrying submission outside of IRQ context if it failed from within IRQ context. + */ +static void jd_done_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); + struct kbase_jd_context *jctx; + struct kbase_context *kctx; + struct kbasep_js_kctx_info *js_kctx_info; + union kbasep_js_policy *js_policy; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + u64 cache_jc = katom->jc; + struct kbasep_js_atom_retained_state katom_retained_state; + + /* Soft jobs should never reach this function */ + KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); + + kctx = katom->kctx; + jctx = &kctx->jctx; + kbdev = kctx->kbdev; + js_kctx_info = &kctx->jctx.sched_info; + + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + + KBASE_TRACE_ADD(kbdev, JD_DONE_WORKER, kctx, katom, katom->jc, 0); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6787) && katom->event_code != BASE_JD_EVENT_DONE && !(katom->event_code & BASE_JD_SW_EVENT)) + kbasep_jd_cacheclean(kbdev); /* cache flush when jobs complete with non-done codes */ + else if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10676)) { + if (kbdev->gpu_props.num_core_groups > 1 && + !(katom->affinity & kbdev->gpu_props.props.coherency_info.group[0].core_mask) && + (katom->affinity & kbdev->gpu_props.props.coherency_info.group[1].core_mask)) { + dev_dbg(kbdev->dev, "JD: Flushing cache due to PRLAM-10676\n"); + kbasep_jd_cacheclean(kbdev); + } + } + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10969) && + (katom->core_req & BASE_JD_REQ_FS) && + katom->event_code == BASE_JD_EVENT_TILE_RANGE_FAULT && + (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED) && + !(katom->atom_flags & KBASE_KATOM_FLAGS_RERUN)) { + dev_dbg(kbdev->dev, "Soft-stopped fragment shader job got a TILE_RANGE_FAULT. Possible HW issue, trying SW workaround\n"); + if (kbasep_10969_workaround_clamp_coordinates(katom)) { + /* The job had a TILE_RANGE_FAULT after was soft-stopped. + * Due to an HW issue we try to execute the job + * again. + */ + dev_dbg(kbdev->dev, "Clamping has been executed, try to rerun the job\n"); + katom->event_code = BASE_JD_EVENT_STOPPED; + katom->atom_flags |= KBASE_KATOM_FLAGS_RERUN; + + /* The atom will be requeued, but requeing does not submit more + * jobs. If this was the last job, we must also ensure that more + * jobs will be run on slot 0 - this is a Fragment job. */ + kbasep_js_set_job_retry_submit_slot(katom, 0); + } + } + + /* + * Begin transaction on JD context and JS context + */ + mutex_lock(&jctx->lock); + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + + /* This worker only gets called on contexts that are scheduled *in*. This is + * because it only happens in response to an IRQ from a job that was + * running. + */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE); + + /* If job was rejected due to BASE_JD_EVENT_PM_EVENT but was not + * specifically targeting core group 1, then re-submit targeting core + * group 0 */ + if (katom->event_code == BASE_JD_EVENT_PM_EVENT && !(katom->core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) { + katom->event_code = BASE_JD_EVENT_STOPPED; + /* Don't need to worry about any previously set retry-slot - it's + * impossible for it to have been set previously, because we guarantee + * kbase_jd_done() was called with done_code==0 on this atom */ + kbasep_js_set_job_retry_submit_slot(katom, 1); + } + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + kbase_as_poking_timer_release_atom(kbdev, kctx, katom); + + /* Release cores this job was using (this might power down unused cores, and + * cause extra latency if a job submitted here - such as depenedent jobs - + * would use those cores) */ + kbasep_js_job_check_deref_cores(kbdev, katom); + + /* Retain state before the katom disappears */ + kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); + + if (!kbasep_js_has_atom_finished(&katom_retained_state)) { + unsigned long flags; + + /* Requeue the atom on soft-stop / removed from NEXT registers */ + dev_dbg(kbdev->dev, "JS: Soft Stopped/Removed from next on Ctx %p; Requeuing", kctx); + + mutex_lock(&js_devdata->runpool_mutex); + kbasep_js_clear_job_retry_submit(katom); + /* An atom that has been hard-stopped might have previously + * been soft-stopped and has just finished before the hard-stop + * occurred. For this reason, clear the hard-stopped flag */ + katom->atom_flags &= ~(KBASE_KATOM_FLAG_BEEN_HARD_STOPPED); + + KBASE_TIMELINE_ATOM_READY(kctx, kbase_jd_atom_id(kctx, katom)); + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_policy_enqueue_job(js_policy, katom); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + /* A STOPPED/REMOVED job must cause a re-submit to happen, in case it + * was the last job left. Crucially, work items on work queues can run + * out of order e.g. on different CPUs, so being able to submit from + * the IRQ handler is not a good indication that we don't need to run + * jobs; the submitted job could be processed on the work-queue + * *before* the stopped job, even though it was submitted after. */ + { + int tmp; + KBASE_DEBUG_ASSERT(kbasep_js_get_atom_retry_submit_slot(&katom_retained_state, &tmp) != MALI_FALSE); + CSTD_UNUSED(tmp); + } + + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + } else { + /* Remove the job from the system for all other reasons */ + mali_bool need_to_try_schedule_context; + + kbasep_js_remove_job(kbdev, kctx, katom); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + /* jd_done_nolock() requires the jsctx_mutex lock to be dropped */ + + need_to_try_schedule_context = jd_done_nolock(katom); + + /* This ctx is already scheduled in, so return value guarenteed FALSE */ + KBASE_DEBUG_ASSERT(need_to_try_schedule_context == MALI_FALSE); + } + /* katom may have been freed now, do not use! */ + + /* + * Transaction complete + */ + mutex_unlock(&jctx->lock); + + /* Job is now no longer running, so can now safely release the context + * reference, and handle any actions that were logged against the atom's retained state */ + kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state); + + KBASE_TRACE_ADD(kbdev, JD_DONE_WORKER_END, kctx, NULL, cache_jc, 0); +} + +/** + * Work queue job cancel function + * Only called as part of 'Zapping' a context (which occurs on termination) + * Operates serially with the jd_done_worker() on the work queue. + * + * This can only be called on contexts that aren't scheduled. + * + * @note We don't need to release most of the resources that would occur on + * kbase_jd_done() or jd_done_worker(), because the atoms here must not be + * running (by virtue of only being called on contexts that aren't + * scheduled). The only resources that are an exception to this are: + * - those held by kbasep_js_job_check_ref_cores(), because these resources are + * held for non-running atoms as well as running atoms. + */ +static void jd_cancel_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); + struct kbase_jd_context *jctx; + struct kbase_context *kctx; + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool need_to_try_schedule_context; + struct kbase_device *kbdev; + + /* Soft jobs should never reach this function */ + KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); + + kctx = katom->kctx; + kbdev = kctx->kbdev; + jctx = &kctx->jctx; + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TRACE_ADD(kbdev, JD_CANCEL_WORKER, kctx, katom, katom->jc, 0); + + /* This only gets called on contexts that are scheduled out. Hence, we must + * make sure we don't de-ref the number of running jobs (there aren't + * any), nor must we try to schedule out the context (it's already + * scheduled out). + */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + + /* Release cores this job was using (this might power down unused cores) */ + kbasep_js_job_check_deref_cores(kctx->kbdev, katom); + + /* Scheduler: Remove the job from the system */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + kbasep_js_remove_cancelled_job(kbdev, kctx, katom); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + mutex_lock(&jctx->lock); + + need_to_try_schedule_context = jd_done_nolock(katom); + /* Because we're zapping, we're not adding any more jobs to this ctx, so no need to + * schedule the context. There's also no need for the jsctx_mutex to have been taken + * around this too. */ + KBASE_DEBUG_ASSERT(need_to_try_schedule_context == MALI_FALSE); + + /* katom may have been freed now, do not use! */ + mutex_unlock(&jctx->lock); +} + +/** + * @brief Complete a job that has been removed from the Hardware + * + * This must be used whenever a job has been removed from the Hardware, e.g.: + * - An IRQ indicates that the job finished (for both error and 'done' codes) + * - The job was evicted from the JS_HEAD_NEXT registers during a Soft/Hard stop. + * + * Some work is carried out immediately, and the rest is deferred onto a workqueue + * + * This can be called safely from atomic context. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock + * + */ +void kbase_jd_done(struct kbase_jd_atom *katom, int slot_nr, ktime_t *end_timestamp, + kbasep_js_atom_done_code done_code) +{ + struct kbase_context *kctx; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(katom); + kctx = katom->kctx; + KBASE_DEBUG_ASSERT(kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev); + + if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT) + katom->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; + + kbase_timeline_job_slot_done(kbdev, kctx, katom, slot_nr, done_code); + + KBASE_TRACE_ADD(kbdev, JD_DONE, kctx, katom, katom->jc, 0); + + kbase_job_check_leave_disjoint(kbdev, katom); + kbasep_js_job_done_slot_irq(katom, slot_nr, end_timestamp, done_code); + + katom->slot_nr = slot_nr; + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, jd_done_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +KBASE_EXPORT_TEST_API(kbase_jd_done) + +void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != katom); + kctx = katom->kctx; + KBASE_DEBUG_ASSERT(NULL != kctx); + + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TRACE_ADD(kbdev, JD_CANCEL, kctx, katom, katom->jc, 0); + + /* This should only be done from a context that is not scheduled */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, jd_cancel_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +struct zap_reset_data { + /* The stages are: + * 1. The timer has never been called + * 2. The zap has timed out, all slots are soft-stopped - the GPU reset will happen. + * The GPU has been reset when kbdev->reset_waitq is signalled + * + * (-1 - The timer has been cancelled) + */ + int stage; + struct kbase_device *kbdev; + struct hrtimer timer; + spinlock_t lock; /* protects updates to stage member */ +}; + +static enum hrtimer_restart zap_timeout_callback(struct hrtimer *timer) +{ + struct zap_reset_data *reset_data = container_of(timer, struct zap_reset_data, timer); + struct kbase_device *kbdev = reset_data->kbdev; + unsigned long flags; + + spin_lock_irqsave(&reset_data->lock, flags); + + if (reset_data->stage == -1) + goto out; + +#if KBASE_GPU_RESET_EN + if (kbase_prepare_to_reset_gpu(kbdev)) { + dev_err(kbdev->dev, "Issueing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", ZAP_TIMEOUT); + kbase_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + reset_data->stage = 2; + + out: + spin_unlock_irqrestore(&reset_data->lock, flags); + + return HRTIMER_NORESTART; +} + +void kbase_jd_zap_context(struct kbase_context *kctx) +{ + struct kbase_jd_atom *katom; + struct list_head *entry, *tmp; + struct kbase_device *kbdev; + struct zap_reset_data reset_data; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kctx); + + kbdev = kctx->kbdev; + + KBASE_TRACE_ADD(kbdev, JD_ZAP_CONTEXT, kctx, NULL, 0u, 0u); + kbase_job_zap_context(kctx); + + mutex_lock(&kctx->jctx.lock); + + /* + * While holding the struct kbase_jd_context lock clean up jobs which are known to kbase but are + * queued outside the job scheduler. + */ + + list_for_each_safe(entry, tmp, &kctx->waiting_soft_jobs) { + katom = list_entry(entry, struct kbase_jd_atom, dep_item[0]); + kbase_cancel_soft_job(katom); + } + + +#ifdef CONFIG_KDS + + /* For each job waiting on a kds resource, cancel the wait and force the job to + * complete early, this is done so that we don't leave jobs outstanding waiting + * on kds resources which may never be released when contexts are zapped, resulting + * in a hang. + * + * Note that we can safely iterate over the list as the struct kbase_jd_context lock is held, + * this prevents items being removed when calling job_done_nolock in kbase_cancel_kds_wait_job. + */ + + list_for_each(entry, &kctx->waiting_kds_resource) { + katom = list_entry(entry, struct kbase_jd_atom, node); + + kbase_cancel_kds_wait_job(katom); + } +#endif + + mutex_unlock(&kctx->jctx.lock); + + hrtimer_init_on_stack(&reset_data.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + reset_data.timer.function = zap_timeout_callback; + + spin_lock_init(&reset_data.lock); + + reset_data.kbdev = kbdev; + reset_data.stage = 1; + + hrtimer_start(&reset_data.timer, HR_TIMER_DELAY_MSEC(ZAP_TIMEOUT), HRTIMER_MODE_REL); + + /* Wait for all jobs to finish, and for the context to be not-scheduled + * (due to kbase_job_zap_context(), we also guarentee it's not in the JS + * policy queue either */ + wait_event(kctx->jctx.zero_jobs_wait, kctx->jctx.job_nr == 0); + wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, kctx->jctx.sched_info.ctx.is_scheduled == MALI_FALSE); + + spin_lock_irqsave(&reset_data.lock, flags); + if (reset_data.stage == 1) { + /* The timer hasn't run yet - so cancel it */ + reset_data.stage = -1; + } + spin_unlock_irqrestore(&reset_data.lock, flags); + + hrtimer_cancel(&reset_data.timer); + + if (reset_data.stage == 2) { + /* The reset has already started. + * Wait for the reset to complete + */ + wait_event(kbdev->reset_wait, atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_NOT_PENDING); + } + destroy_hrtimer_on_stack(&reset_data.timer); + + dev_dbg(kbdev->dev, "Zap: Finished Context %p", kctx); + + /* Ensure that the signallers of the waitqs have finished */ + mutex_lock(&kctx->jctx.lock); + mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + mutex_unlock(&kctx->jctx.lock); +} + +KBASE_EXPORT_TEST_API(kbase_jd_zap_context) + +mali_error kbase_jd_init(struct kbase_context *kctx) +{ + int i; + mali_error mali_err = MALI_ERROR_NONE; +#ifdef CONFIG_KDS + int err; +#endif /* CONFIG_KDS */ + + KBASE_DEBUG_ASSERT(kctx); + + kctx->jctx.job_done_wq = alloc_workqueue("mali_jd", WQ_HIGHPRI | WQ_UNBOUND, 1); + if (NULL == kctx->jctx.job_done_wq) { + mali_err = MALI_ERROR_OUT_OF_MEMORY; + goto out1; + } + + for (i = 0; i < BASE_JD_ATOM_COUNT; i++) { + init_waitqueue_head(&kctx->jctx.atoms[i].completed); + + INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[0]); + INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[1]); + + /* Catch userspace attempting to use an atom which doesn't exist as a pre-dependency */ + kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_INVALID; + kctx->jctx.atoms[i].status = KBASE_JD_ATOM_STATE_UNUSED; + } + + mutex_init(&kctx->jctx.lock); + + init_waitqueue_head(&kctx->jctx.zero_jobs_wait); + + spin_lock_init(&kctx->jctx.tb_lock); + +#ifdef CONFIG_KDS + err = kds_callback_init(&kctx->jctx.kds_cb, 0, kds_dep_clear); + if (0 != err) { + mali_err = MALI_ERROR_FUNCTION_FAILED; + goto out2; + } +#endif /* CONFIG_KDS */ + + kctx->jctx.job_nr = 0; + + return MALI_ERROR_NONE; + +#ifdef CONFIG_KDS + out2: + destroy_workqueue(kctx->jctx.job_done_wq); +#endif /* CONFIG_KDS */ + out1: + return mali_err; +} + +KBASE_EXPORT_TEST_API(kbase_jd_init) + +void kbase_jd_exit(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + +#ifdef CONFIG_KDS + kds_callback_term(&kctx->jctx.kds_cb); +#endif /* CONFIG_KDS */ + /* Work queue is emptied by this */ + destroy_workqueue(kctx->jctx.job_done_wq); +} + +KBASE_EXPORT_TEST_API(kbase_jd_exit) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..c9daa90f5ee55f37be94d854195e652aa979999d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c @@ -0,0 +1,192 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#include + +#ifdef CONFIG_DEBUG_FS + +/** + * @brief Show callback for the @c JD atoms debugfs file. + * + * This function is called to get the contents of the @c JD atoms debugfs file. + * This is a report of all atoms managed by kbase_jd_context::atoms . + * + * @param sfile The debugfs entry + * @param data Data associated with the entry + * + * @return 0 if successfully prints data in debugfs entry file, failure + * otherwise + */ +static int kbasep_jd_debugfs_atoms_show(struct seq_file *sfile, void *data) +{ + struct kbase_context *kctx = sfile->private; + struct kbase_jd_atom *atoms; + unsigned long irq_flags; + int i; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* Print table heading */ + seq_puts(sfile, "atom id,core reqs,status,coreref status,predeps,start time,time on gpu\n"); + + atoms = kctx->jctx.atoms; + /* General atom states */ + mutex_lock(&kctx->jctx.lock); + /* JS-related states */ + spin_lock_irqsave(&kctx->kbdev->js_data.runpool_irq.lock, irq_flags); + for (i = 0; i != BASE_JD_ATOM_COUNT; ++i) { + struct kbase_jd_atom *atom = &atoms[i]; + s64 start_timestamp = 0; + + if (atom->status == KBASE_JD_ATOM_STATE_UNUSED) + continue; + + /* start_timestamp is cleared as soon as the atom leaves UNUSED state + * and set before a job is submitted to the h/w, a non-zero value means + * it is valid */ + if (ktime_to_ns(atom->start_timestamp)) + start_timestamp = ktime_to_ns( + ktime_sub(ktime_get(), atom->start_timestamp)); + +#ifdef CONFIG_64BIT + seq_printf(sfile, + "%i,%u,%u,%u,%lu %lu,%lli,%llu\n", + i, atom->core_req, atom->status, atom->coreref_state, + atom->dep[0].atom ? atom->dep[0].atom - atoms : 0, + atom->dep[1].atom ? atom->dep[1].atom - atoms : 0, + (signed long long)start_timestamp, + (unsigned long long)(atom->time_spent_us ? + atom->time_spent_us * 1000 : start_timestamp) + ); +#else + seq_printf(sfile, + "%i,%u,%u,%u,%u %u,%lli,%llu\n", + i, atom->core_req, atom->status, atom->coreref_state, + atom->dep[0].atom ? atom->dep[0].atom - atoms : 0, + atom->dep[1].atom ? atom->dep[1].atom - atoms : 0, + (signed long long)start_timestamp, + (unsigned long long)(atom->time_spent_us ? + atom->time_spent_us * 1000 : start_timestamp) + ); +#endif + } + spin_unlock_irqrestore(&kctx->kbdev->js_data.runpool_irq.lock, irq_flags); + mutex_unlock(&kctx->jctx.lock); + + return 0; +} + + +/** + * @brief File operations related to debugfs entry for atoms + */ +static int kbasep_jd_debugfs_atoms_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_jd_debugfs_atoms_show, in->i_private); +} + +static const struct file_operations kbasep_jd_debugfs_atoms_fops = { + .open = kbasep_jd_debugfs_atoms_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + +int kbasep_jd_debugfs_init(struct kbase_device *kbdev) +{ + kbdev->jd_directory = debugfs_create_dir( + "jd", kbdev->mali_debugfs_directory); + if (IS_ERR(kbdev->jd_directory)) { + dev_err(kbdev->dev, "Couldn't create mali jd debugfs directory\n"); + goto err; + } + + return 0; + +err: + return -1; +} + + +void kbasep_jd_debugfs_term(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + if (!IS_ERR(kbdev->jd_directory)) + debugfs_remove_recursive(kbdev->jd_directory); +} + + +int kbasep_jd_debugfs_ctx_add(struct kbase_context *kctx) +{ + /* Refer below for format string, %u is 10 chars max */ + char dir_name[10 * 2 + 2]; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* Create per-context directory */ + scnprintf(dir_name, sizeof(dir_name), "%u_%u", kctx->pid, kctx->id); + kctx->jd_ctx_dir = debugfs_create_dir(dir_name, kctx->kbdev->jd_directory); + if (IS_ERR(kctx->jd_ctx_dir)) + goto err; + + /* Expose all atoms */ + if (IS_ERR(debugfs_create_file("atoms", S_IRUGO, + kctx->jd_ctx_dir, kctx, &kbasep_jd_debugfs_atoms_fops))) + goto err_jd_ctx_dir; + + return 0; + +err_jd_ctx_dir: + debugfs_remove_recursive(kctx->jd_ctx_dir); +err: + return -1; +} + + +void kbasep_jd_debugfs_ctx_remove(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + + if (!IS_ERR(kctx->jd_ctx_dir)) + debugfs_remove_recursive(kctx->jd_ctx_dir); +} + +#else /* CONFIG_DEBUG_FS */ + +/** + * @brief Stub functions for when debugfs is disabled + */ +int kbasep_jd_debugfs_init(struct kbase_device *kbdev) +{ + return 0; +} +void kbasep_jd_debugfs_term(struct kbase_device *kbdev) +{ +} +int kbasep_jd_debugfs_ctx_add(struct kbase_context *ctx) +{ + return 0; +} +void kbasep_jd_debugfs_ctx_remove(struct kbase_context *ctx) +{ +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..c045736139b64fa633b22471369b1bf53879c871 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h @@ -0,0 +1,66 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_jd_debugfs.h + * Header file for job dispatcher-related entries in debugfs + */ + +#ifndef _KBASE_JD_DEBUGFS_H +#define _KBASE_JD_DEBUGFS_H + +#include + +#include + +/** + * @brief Initialize JD debugfs entries + * + * This should be called during device probing after the main mali debugfs + * directory has been created. + * + * @param[in] kbdev Pointer to kbase_device + */ +int kbasep_jd_debugfs_init(struct kbase_device *kbdev); + +/** + * @brief Clean up all JD debugfs entries and related data + * + * This should be called during device removal before the main mali debugfs + * directory will be removed. + * + * @param[in] kbdev Pointer to kbase_device + */ +void kbasep_jd_debugfs_term(struct kbase_device *kbdev); + +/** + * @brief Add new entry to JD debugfs + * + * @param[in] kctx Pointer to kbase_context + * + * @return 0 on success, failure otherwise + */ +int kbasep_jd_debugfs_ctx_add(struct kbase_context *kctx); + +/** + * @brief Remove entry from JD debugfs + * + * param[in] kctx Pointer to kbase_context + */ +void kbasep_jd_debugfs_ctx_remove(struct kbase_context *kctx); + +#endif /*_KBASE_JD_DEBUGFS_H*/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.c new file mode 100644 index 0000000000000000000000000000000000000000..b04f5967f7f5d688e0ab91ade43646e5bc9cc16c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.c @@ -0,0 +1,1532 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_jm.c + * Base kernel job manager APIs + */ + +#include +#include +#include +#include +#include +#include + +#include "mali_kbase_jm.h" + +#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS +u64 mali_js0_affinity_mask = 0xFFFFFFFFFFFFFFFFULL; +u64 mali_js1_affinity_mask = 0xFFFFFFFFFFFFFFFFULL; +u64 mali_js2_affinity_mask = 0xFFFFFFFFFFFFFFFFULL; +#endif + +#if KBASE_GPU_RESET_EN +static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev); +#endif /* KBASE_GPU_RESET_EN */ + +#ifdef CONFIG_GPU_TRACEPOINTS +static char *kbasep_make_job_slot_string(int js, char *js_string) +{ + sprintf(js_string, "job_slot_%i", js); + return js_string; +} +#endif + +static void kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js) +{ + struct kbase_context *kctx; + u32 cfg; + u64 jc_head = katom->jc; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(katom); + + kctx = katom->kctx; + + /* Command register must be available */ + KBASE_DEBUG_ASSERT(kbasep_jm_is_js_free(kbdev, js, kctx)); + /* Affinity is not violating */ + kbase_js_debug_log_current_affinities(kbdev); + KBASE_DEBUG_ASSERT(!kbase_js_affinity_would_violate(kbdev, js, katom->affinity)); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), jc_head & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), jc_head >> 32, kctx); + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + { + u64 mask; + u32 value; + + if (0 == js) + { + mask = mali_js0_affinity_mask; + } + else if (1 == js) + { + mask = mali_js1_affinity_mask; + } + else + { + mask = mali_js2_affinity_mask; + } + + value = katom->affinity & (mask & 0xFFFFFFFF); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_LO), value, kctx); + + value = (katom->affinity >> 32) & ((mask>>32) & 0xFFFFFFFF); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_HI), value, kctx); + } +#else + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_LO), katom->affinity & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_HI), katom->affinity >> 32, kctx); +#endif + + /* start MMU, medium priority, cache clean/flush on end, clean/flush on start */ + cfg = kctx->as_nr | JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE | JS_CONFIG_START_MMU | JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE | JS_CONFIG_THREAD_PRI(8); + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { + if (!kbdev->jm_slots[js].job_chain_flag) { + cfg |= JS_CONFIG_JOB_CHAIN_FLAG; + katom->atom_flags |= KBASE_KATOM_FLAGS_JOBCHAIN; + kbdev->jm_slots[js].job_chain_flag = MALI_TRUE; + } else { + katom->atom_flags &= ~KBASE_KATOM_FLAGS_JOBCHAIN; + kbdev->jm_slots[js].job_chain_flag = MALI_FALSE; + } + } + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_CONFIG_NEXT), cfg, kctx); + + /* Write an approximate start timestamp. + * It's approximate because there might be a job in the HEAD register. In + * such cases, we'll try to make a better approximation in the IRQ handler + * (up to the KBASE_JS_IRQ_THROTTLE_TIME_US). */ + katom->start_timestamp = ktime_get(); + + /* GO ! */ + dev_dbg(kbdev->dev, "JS: Submitting atom %p from ctx %p to js[%d] with head=0x%llx, affinity=0x%llx", katom, kctx, js, jc_head, katom->affinity); + + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_SUBMIT, kctx, katom, jc_head, js, (u32) katom->affinity); + +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_START, js), kctx, kbase_jd_atom_id(kctx, katom)); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ +#ifdef CONFIG_GPU_TRACEPOINTS + if (kbasep_jm_nr_jobs_submitted(&kbdev->jm_slots[js]) == 1) + { + /* If this is the only job on the slot, trace it as starting */ + char js_string[16]; + trace_gpu_sched_switch(kbasep_make_job_slot_string(js, js_string), ktime_to_ns(katom->start_timestamp), (u32)katom->kctx->id, 0, katom->work_id); + kbdev->jm_slots[js].last_context = katom->kctx; + } +#endif + kbase_timeline_job_slot_submit(kbdev, kctx, katom, js); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_START, katom->kctx); +} + +void kbase_job_submit_nolock(struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js) +{ + struct kbase_jm_slot *jm_slots; +#if KBASE_PM_EN + base_jd_core_req core_req; +#endif + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(katom); + + jm_slots = kbdev->jm_slots; + +#if KBASE_PM_EN + core_req = katom->core_req; + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) { + unsigned long flags; + int device_nr = (core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) ? katom->device_nr : 0; + KBASE_DEBUG_ASSERT(device_nr < 2); + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbasep_pm_record_job_status(kbdev); + kbdev->pm.metrics.active_cl_ctx[device_nr]++; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + } else { + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbasep_pm_record_job_status(kbdev); + kbdev->pm.metrics.active_gl_ctx++; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + } +#endif + + /* + * We can have: + * - one job already done (pending interrupt), + * - one running, + * - one ready to be run. + * Hence a maximum of 3 inflight jobs. We have a 4 job + * queue, which I hope will be enough... + */ + kbasep_jm_enqueue_submit_slot(&jm_slots[js], katom); + kbase_job_hw_submit(kbdev, katom, js); +} + +void kbase_job_done_slot(struct kbase_device *kbdev, int s, u32 completion_code, u64 job_tail, ktime_t *end_timestamp) +{ + struct kbase_jm_slot *slot; + struct kbase_jd_atom *katom; + mali_addr64 jc_head; + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(kbdev); + + if (completion_code != BASE_JD_EVENT_DONE && completion_code != BASE_JD_EVENT_STOPPED) + dev_err(kbdev->dev, "GPU fault 0x%02lx from job slot %d\n", (unsigned long)completion_code, s); + + /* IMPORTANT: this function must only contain work necessary to complete a + * job from a Real IRQ (and not 'fake' completion, e.g. from + * Soft-stop). For general work that must happen no matter how the job was + * removed from the hardware, place it in kbase_jd_done() */ + + slot = &kbdev->jm_slots[s]; + katom = kbasep_jm_dequeue_submit_slot(slot); + + /* If the katom completed is because it's a dummy job for HW workarounds, then take no further action */ + if (kbasep_jm_is_dummy_workaround_job(kbdev, katom)) { + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_JOB_DONE, NULL, NULL, 0, s, completion_code); + return; + } + + jc_head = katom->jc; + kctx = katom->kctx; + + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_JOB_DONE, kctx, katom, jc_head, s, completion_code); + + if (completion_code != BASE_JD_EVENT_DONE && completion_code != BASE_JD_EVENT_STOPPED) { + +#if KBASE_TRACE_DUMP_ON_JOB_SLOT_ERROR != 0 + KBASE_TRACE_DUMP(kbdev); +#endif + } + if (job_tail != 0) { + mali_bool was_updated = (job_tail != jc_head); + /* Some of the job has been executed, so we update the job chain address to where we should resume from */ + katom->jc = job_tail; + if (was_updated) + KBASE_TRACE_ADD_SLOT(kbdev, JM_UPDATE_HEAD, kctx, katom, job_tail, s); + } + + /* Only update the event code for jobs that weren't cancelled */ + if (katom->event_code != BASE_JD_EVENT_JOB_CANCELLED) + katom->event_code = (base_jd_event_code) completion_code; + + kbase_device_trace_register_access(kctx, REG_WRITE, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 1 << s); + + /* Complete the job, and start new ones + * + * Also defer remaining work onto the workqueue: + * - Re-queue Soft-stopped jobs + * - For any other jobs, queue the job back into the dependency system + * - Schedule out the parent context if necessary, and schedule a new one in. + */ +#ifdef CONFIG_GPU_TRACEPOINTS + if (kbasep_jm_nr_jobs_submitted(slot) != 0) { + struct kbase_jd_atom *katom; + char js_string[16]; + katom = kbasep_jm_peek_idx_submit_slot(slot, 0); /* The atom in the HEAD */ + trace_gpu_sched_switch(kbasep_make_job_slot_string(s, js_string), ktime_to_ns(*end_timestamp), (u32)katom->kctx->id, 0, katom->work_id); + slot->last_context = katom->kctx; + } else { + char js_string[16]; + trace_gpu_sched_switch(kbasep_make_job_slot_string(s, js_string), ktime_to_ns(ktime_get()), 0, 0, 0); + slot->last_context = 0; + } +#endif + kbase_jd_done(katom, s, end_timestamp, KBASE_JS_ATOM_DONE_START_NEW_ATOMS); +} + +/** + * Update the start_timestamp of the job currently in the HEAD, based on the + * fact that we got an IRQ for the previous set of completed jobs. + * + * The estimate also takes into account the KBASE_JS_IRQ_THROTTLE_TIME_US and + * the time the job was submitted, to work out the best estimate (which might + * still result in an over-estimate to the calculated time spent) + */ +STATIC void kbasep_job_slot_update_head_start_timestamp(struct kbase_device *kbdev, struct kbase_jm_slot *slot, ktime_t end_timestamp) +{ + KBASE_DEBUG_ASSERT(slot); + + if (kbasep_jm_nr_jobs_submitted(slot) > 0) { + struct kbase_jd_atom *katom; + ktime_t new_timestamp; + ktime_t timestamp_diff; + katom = kbasep_jm_peek_idx_submit_slot(slot, 0); /* The atom in the HEAD */ + + KBASE_DEBUG_ASSERT(katom != NULL); + + if (kbasep_jm_is_dummy_workaround_job(kbdev, katom) != MALI_FALSE) { + /* Don't access the members of HW workaround 'dummy' jobs */ + return; + } + + /* Account for any IRQ Throttle time - makes an overestimate of the time spent by the job */ + new_timestamp = ktime_sub_ns(end_timestamp, KBASE_JS_IRQ_THROTTLE_TIME_US * 1000); + timestamp_diff = ktime_sub(new_timestamp, katom->start_timestamp); + if (ktime_to_ns(timestamp_diff) >= 0) { + /* Only update the timestamp if it's a better estimate than what's currently stored. + * This is because our estimate that accounts for the throttle time may be too much + * of an overestimate */ + katom->start_timestamp = new_timestamp; + } + } +} + +void kbase_job_done(struct kbase_device *kbdev, u32 done) +{ + unsigned long flags; + int i; + u32 count = 0; + ktime_t end_timestamp = ktime_get(); + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + KBASE_TRACE_ADD(kbdev, JM_IRQ, NULL, NULL, 0, done); + + memset(&kbdev->slot_submit_count_irq[0], 0, sizeof(kbdev->slot_submit_count_irq)); + + /* write irq throttle register, this will prevent irqs from occurring until + * the given number of gpu clock cycles have passed */ + { + int irq_throttle_cycles = atomic_read(&kbdev->irq_throttle_cycles); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_THROTTLE), irq_throttle_cycles, NULL); + } + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + while (done) { + struct kbase_jm_slot *slot; + u32 failed = done >> 16; + + /* treat failed slots as finished slots */ + u32 finished = (done & 0xFFFF) | failed; + + /* Note: This is inherently unfair, as we always check + * for lower numbered interrupts before the higher + * numbered ones.*/ + i = ffs(finished) - 1; + KBASE_DEBUG_ASSERT(i >= 0); + + slot = &kbdev->jm_slots[i]; + + do { + int nr_done; + u32 active; + u32 completion_code = BASE_JD_EVENT_DONE; /* assume OK */ + u64 job_tail = 0; + + if (failed & (1u << i)) { + /* read out the job slot status code if the job slot reported failure */ + completion_code = kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_STATUS), NULL); + + switch (completion_code) { + case BASE_JD_EVENT_STOPPED: +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_SOFT_STOPPED, i), NULL, 0); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + /* Soft-stopped job - read the value of JS_TAIL so that the job chain can be resumed */ + job_tail = (u64) kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_TAIL_LO), NULL) | ((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_TAIL_HI), NULL) << 32); + break; + case BASE_JD_EVENT_NOT_STARTED: + /* PRLAM-10673 can cause a TERMINATED job to come back as NOT_STARTED, but the error interrupt helps us detect it */ + completion_code = BASE_JD_EVENT_TERMINATED; + /* fall throught */ + default: + dev_warn(kbdev->dev, "error detected from slot %d, job status 0x%08x (%s)", i, completion_code, kbase_exception_name(completion_code)); + } + } + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), done & ((1 << i) | (1 << (i + 16))), NULL); + active = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_JS_STATE), NULL); + + if (((active >> i) & 1) == 0 && (((done >> (i + 16)) & 1) == 0)) { + /* There is a potential race we must work around: + * + * 1. A job slot has a job in both current and next registers + * 2. The job in current completes successfully, the IRQ handler reads RAWSTAT + * and calls this function with the relevant bit set in "done" + * 3. The job in the next registers becomes the current job on the GPU + * 4. Sometime before the JOB_IRQ_CLEAR line above the job on the GPU _fails_ + * 5. The IRQ_CLEAR clears the done bit but not the failed bit. This atomically sets + * JOB_IRQ_JS_STATE. However since both jobs have now completed the relevant bits + * for the slot are set to 0. + * + * If we now did nothing then we'd incorrectly assume that _both_ jobs had completed + * successfully (since we haven't yet observed the fail bit being set in RAWSTAT). + * + * So at this point if there are no active jobs left we check to see if RAWSTAT has a failure + * bit set for the job slot. If it does we know that there has been a new failure that we + * didn't previously know about, so we make sure that we record this in active (but we wait + * for the next loop to deal with it). + * + * If we were handling a job failure (i.e. done has the relevant high bit set) then we know that + * the value read back from JOB_IRQ_JS_STATE is the correct number of remaining jobs because + * the failed job will have prevented any futher jobs from starting execution. + */ + u32 rawstat = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL); + + if ((rawstat >> (i + 16)) & 1) { + /* There is a failed job that we've missed - add it back to active */ + active |= (1u << i); + } + } + + dev_dbg(kbdev->dev, "Job ended with status 0x%08X\n", completion_code); + + nr_done = kbasep_jm_nr_jobs_submitted(slot); + nr_done -= (active >> i) & 1; + nr_done -= (active >> (i + 16)) & 1; + + if (nr_done <= 0) { + dev_warn(kbdev->dev, "Spurious interrupt on slot %d", i); + goto spurious; + } + + count += nr_done; + + while (nr_done) { + if (nr_done == 1) { + kbase_job_done_slot(kbdev, i, completion_code, job_tail, &end_timestamp); + } else { + /* More than one job has completed. Since this is not the last job being reported this time it + * must have passed. This is because the hardware will not allow further jobs in a job slot to + * complete until the faile job is cleared from the IRQ status. + */ + kbase_job_done_slot(kbdev, i, BASE_JD_EVENT_DONE, 0, &end_timestamp); + } + nr_done--; + } + + spurious: + done = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10883)) { + /* Workaround for missing interrupt caused by PRLAM-10883 */ + if (((active >> i) & 1) && (0 == kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_STATUS), NULL))) { + /* Force job slot to be processed again */ + done |= (1u << i); + } + } + + failed = done >> 16; + finished = (done & 0xFFFF) | failed; + } while (finished & (1 << i)); + + kbasep_job_slot_update_head_start_timestamp(kbdev, slot, end_timestamp); + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); +#if KBASE_GPU_RESET_EN + if (atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_COMMITTED) { + /* If we're trying to reset the GPU then we might be able to do it early + * (without waiting for a timeout) because some jobs have completed + */ + kbasep_try_reset_gpu_early(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + KBASE_TRACE_ADD(kbdev, JM_IRQ_END, NULL, NULL, 0, count); +} +KBASE_EXPORT_TEST_API(kbase_job_done) + +static mali_bool kbasep_soft_stop_allowed(struct kbase_device *kbdev, u16 core_reqs) +{ + mali_bool soft_stops_allowed = MALI_TRUE; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) { + if ((core_reqs & BASE_JD_REQ_T) != 0) + soft_stops_allowed = MALI_FALSE; + } + return soft_stops_allowed; +} + +static mali_bool kbasep_hard_stop_allowed(struct kbase_device *kbdev, u16 core_reqs) +{ + mali_bool hard_stops_allowed = MALI_TRUE; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8394)) { + if ((core_reqs & BASE_JD_REQ_T) != 0) + hard_stops_allowed = MALI_FALSE; + } + return hard_stops_allowed; +} + +static void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, int js, u32 action, u16 core_reqs, struct kbase_jd_atom *target_katom) +{ + struct kbase_context *kctx = target_katom->kctx; +#if KBASE_TRACE_ENABLE + u32 status_reg_before; + u64 job_in_head_before; + u32 status_reg_after; + + KBASE_DEBUG_ASSERT(!(action & (~JS_COMMAND_MASK))); + + /* Check the head pointer */ + job_in_head_before = ((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_LO), NULL)) + | (((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_HI), NULL)) << 32); + status_reg_before = kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_STATUS), NULL); +#endif + + if (action == JS_COMMAND_SOFT_STOP) { + mali_bool soft_stop_allowed = kbasep_soft_stop_allowed(kbdev, core_reqs); + if (!soft_stop_allowed) { +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kbdev->dev, "Attempt made to soft-stop a job that cannot be soft-stopped. core_reqs = 0x%X", (unsigned int)core_reqs); +#endif /* CONFIG_MALI_DEBUG */ + return; + } + + /* We are about to issue a soft stop, so mark the atom as having been soft stopped */ + target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED; + } + + if (action == JS_COMMAND_HARD_STOP) { + mali_bool hard_stop_allowed = kbasep_hard_stop_allowed(kbdev, core_reqs); + if (!hard_stop_allowed) { + /* Jobs can be hard-stopped for the following reasons: + * * CFS decides the job has been running too long (and soft-stop has not occurred). + * In this case the GPU will be reset by CFS if the job remains on the GPU. + * + * * The context is destroyed, kbase_jd_zap_context will attempt to hard-stop the job. However + * it also has a watchdog which will cause the GPU to be reset if the job remains on the GPU. + * + * * An (unhandled) MMU fault occurred. As long as BASE_HW_ISSUE_8245 is defined then + * the GPU will be reset. + * + * All three cases result in the GPU being reset if the hard-stop fails, + * so it is safe to just return and ignore the hard-stop request. + */ + dev_warn(kbdev->dev, "Attempt made to hard-stop a job that cannot be hard-stopped. core_reqs = 0x%X", (unsigned int)core_reqs); + return; + } + target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_HARD_STOPPED; + } + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316) && action == JS_COMMAND_SOFT_STOP) { + int i; + struct kbase_jm_slot *slot; + slot = &kbdev->jm_slots[js]; + + for (i = 0; i < kbasep_jm_nr_jobs_submitted(slot); i++) { + struct kbase_jd_atom *katom; + + katom = kbasep_jm_peek_idx_submit_slot(slot, i); + + KBASE_DEBUG_ASSERT(katom); + + if (kbasep_jm_is_dummy_workaround_job(kbdev, katom) != MALI_FALSE) { + /* Don't access the members of HW workaround 'dummy' jobs + * + * This assumes that such jobs can't cause HW_ISSUE_8316, and could only be blocked + * by other jobs causing HW_ISSUE_8316 (which will get poked/or eventually get killed) */ + continue; + } + + /* For HW_ISSUE_8316, only 'bad' jobs attacking the system can + * cause this issue: normally, all memory should be allocated in + * multiples of 4 pages, and growable memory should be changed size + * in multiples of 4 pages. + * + * Whilst such 'bad' jobs can be cleared by a GPU reset, the + * locking up of a uTLB entry caused by the bad job could also + * stall other ASs, meaning that other ASs' jobs don't complete in + * the 'grace' period before the reset. We don't want to lose other + * ASs' jobs when they would normally complete fine, so we must + * 'poke' the MMU regularly to help other ASs complete */ + kbase_as_poking_timer_retain_atom(kbdev, katom->kctx, katom); + } + } + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { + if (action == JS_COMMAND_SOFT_STOP) + action = (target_katom->atom_flags & KBASE_KATOM_FLAGS_JOBCHAIN) ? + JS_COMMAND_SOFT_STOP_1 : + JS_COMMAND_SOFT_STOP_0; + else + action = (target_katom->atom_flags & KBASE_KATOM_FLAGS_JOBCHAIN) ? + JS_COMMAND_HARD_STOP_1 : + JS_COMMAND_HARD_STOP_0; + } + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND), action, kctx); + +#if KBASE_TRACE_ENABLE + status_reg_after = kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_STATUS), NULL); + if (status_reg_after == BASE_JD_EVENT_ACTIVE) { + struct kbase_jm_slot *slot; + struct kbase_jd_atom *head; + struct kbase_context *head_kctx; + + slot = &kbdev->jm_slots[js]; + head = kbasep_jm_peek_idx_submit_slot(slot, slot->submitted_nr - 1); + head_kctx = head->kctx; + + /* We don't need to check kbasep_jm_is_dummy_workaround_job( head ) here: + * - Members are not indirected through + * - The members will all be zero anyway + */ + if (status_reg_before == BASE_JD_EVENT_ACTIVE) + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, head_kctx, head, job_in_head_before, js); + else + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, 0, js); + + switch (action) { + case JS_COMMAND_SOFT_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_SOFT_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_0, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_SOFT_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_1, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_0, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_1, head_kctx, head, head->jc, js); + break; + default: + BUG(); + break; + } + } else { + if (status_reg_before == BASE_JD_EVENT_ACTIVE) + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, job_in_head_before, js); + else + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, 0, js); + + switch (action) { + case JS_COMMAND_SOFT_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP, NULL, NULL, 0, js); + break; + case JS_COMMAND_SOFT_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_0, NULL, NULL, 0, js); + break; + case JS_COMMAND_SOFT_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_1, NULL, NULL, 0, js); + break; + case JS_COMMAND_HARD_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP, NULL, NULL, 0, js); + break; + case JS_COMMAND_HARD_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_0, NULL, NULL, 0, js); + break; + case JS_COMMAND_HARD_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_1, NULL, NULL, 0, js); + break; + default: + BUG(); + break; + } + } +#endif +} + +/* Helper macros used by kbasep_job_slot_soft_or_hard_stop */ +#define JM_SLOT_MAX_JOB_SUBMIT_REGS 2 +#define JM_JOB_IS_CURRENT_JOB_INDEX(n) (1 == n) /* Index of the last job to process */ +#define JM_JOB_IS_NEXT_JOB_INDEX(n) (2 == n) /* Index of the prior to last job to process */ + +/** Soft or hard-stop a slot + * + * This function safely ensures that the correct job is either hard or soft-stopped. + * It deals with evicting jobs from the next registers where appropriate. + * + * This does not attempt to stop or evict jobs that are 'dummy' jobs for HW workarounds. + * + * @param kbdev The kbase device + * @param kctx The context to soft/hard-stop job(s) from (or NULL is all jobs should be targeted) + * @param js The slot that the job(s) are on + * @param target_katom The atom that should be targeted (or NULL if all jobs from the context should be targeted) + * @param action The action to perform, either JS_COMMAND_HARD_STOP or JS_COMMAND_SOFT_STOP + */ +static void kbasep_job_slot_soft_or_hard_stop(struct kbase_device *kbdev, struct kbase_context *kctx, int js, struct kbase_jd_atom *target_katom, u32 action) +{ + struct kbase_jd_atom *katom; + u8 i; + u8 jobs_submitted; + struct kbase_jm_slot *slot; + u16 core_reqs; + struct kbasep_js_device_data *js_devdata; + mali_bool can_safely_stop = kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION); + u32 hw_action = action & JS_COMMAND_MASK; + + KBASE_DEBUG_ASSERT(hw_action == JS_COMMAND_HARD_STOP || + hw_action == JS_COMMAND_SOFT_STOP); + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + slot = &kbdev->jm_slots[js]; + KBASE_DEBUG_ASSERT(slot); + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + jobs_submitted = kbasep_jm_nr_jobs_submitted(slot); + + KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 1); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_SLOT_SOFT_OR_HARD_STOP, kctx, NULL, 0u, js, jobs_submitted); + + if (jobs_submitted > JM_SLOT_MAX_JOB_SUBMIT_REGS) + i = jobs_submitted - JM_SLOT_MAX_JOB_SUBMIT_REGS; + else + i = 0; + + /* Loop through all jobs that have been submitted to the slot and haven't completed */ + for (; i < jobs_submitted; i++) { + katom = kbasep_jm_peek_idx_submit_slot(slot, i); + + if (kctx && katom->kctx != kctx) + continue; + + if (target_katom && katom != target_katom) + continue; + + if (kbasep_jm_is_dummy_workaround_job(kbdev, katom)) + continue; + + core_reqs = katom->core_req; + + /* This will be repeated for anything removed from the next + * registers, since their normal flow was also interrupted, and + * this function might not enter disjoint state e.g. if we + * don't actually do a hard stop on the head atom + */ + kbase_job_check_enter_disjoint(kbdev, action, core_reqs, katom); + + if (JM_JOB_IS_CURRENT_JOB_INDEX(jobs_submitted - i)) { + /* The last job in the slot, check if there is a job in the next register */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), NULL) == 0) { + kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, + js, hw_action, core_reqs, katom); + } else { + /* The job is in the next registers */ + beenthere(kctx, "clearing job from next registers on slot %d", js); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_NOP, NULL); + /* Check to see if we did remove a job from the next registers */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), NULL) != 0) { + /* The job was successfully cleared from the next registers, requeue it */ + struct kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot); + KBASE_DEBUG_ASSERT(dequeued_katom == katom); + jobs_submitted--; + + /* Set the next registers to NULL */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), 0, NULL); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), 0, NULL); + + /* As the job is removed from the next registers we undo the associated + * update to the job_chain_flag for the job slot. */ + if (can_safely_stop) + slot->job_chain_flag = !slot->job_chain_flag; + + KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js); + + kbase_job_check_enter_disjoint(kbdev, action, 0u, dequeued_katom); + /* Complete the job, indicate it took no time, but don't submit any more at this point */ + kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT); + } else { + /* The job transitioned into the current registers before we managed to evict it, + * in this case we fall back to soft/hard-stopping the job */ + beenthere(kctx, "missed job in next register, soft/hard-stopping slot %d", js); + kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, + js, hw_action, core_reqs, katom); + } + } + } else if (JM_JOB_IS_NEXT_JOB_INDEX(jobs_submitted - i)) { + /* There's a job after this one, check to see if that + * job is in the next registers. If so, we need to pay + * attention to not accidently stop that one when + * issueing the command to stop the one pointed to by + * the head registers (as the one in the head may + * finish in the mean time and the one in the next + * moves to the head). Either the hardware has support + * for this using job chain disambiguation or we need + * to evict the job from the next registers first to + * ensure we can safely stop the one pointed to by the + * head registers. + */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), NULL) != 0) { + struct kbase_jd_atom *check_next_atom; + /* It is - we should remove that job and soft/hard-stop the slot */ + + /* Only proceed when the next job isn't a HW workaround 'dummy' job + * + * This can't be an ASSERT due to MMU fault code: + * - This first hard-stops the job that caused the fault + * - Under HW Issue 8245, it will then reset the GPU + * - This causes a Soft-stop to occur on all slots + * - By the time of the soft-stop, we may (depending on timing) still have: + * - The original job in HEAD, if it's not finished the hard-stop + * - The dummy workaround job in NEXT + * + * Other cases could be coded in future that cause back-to-back Soft/Hard + * stops with dummy workaround jobs in place, e.g. MMU handler code and Job + * Scheduler watchdog timer running in parallel. + * + * Note, the index i+1 is valid to peek from: i == jobs_submitted-2, therefore + * i+1 == jobs_submitted-1 */ + check_next_atom = kbasep_jm_peek_idx_submit_slot(slot, i + 1); + if (kbasep_jm_is_dummy_workaround_job(kbdev, check_next_atom) != MALI_FALSE) + continue; + + if (!can_safely_stop) { + beenthere(kctx, "clearing job from next registers on slot %d", js); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_NOP, NULL); + + /* Check to see if we did remove a job from the next registers */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), NULL) != 0) { + /* We did remove a job from the next registers, requeue it */ + struct kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot); + KBASE_DEBUG_ASSERT(dequeued_katom != NULL); + jobs_submitted--; + + /* Set the next registers to NULL */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), 0, NULL); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), 0, NULL); + + KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js); + + kbase_job_check_enter_disjoint(kbdev, action, 0u, dequeued_katom); + /* Complete the job, indicate it took no time, but don't submit any more at this point */ + kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT); + } else { + /* We missed the job, that means the job we're interested in left the hardware before + * we managed to do anything, so we can proceed to the next job */ + continue; + } + } + + /* Next is now free, so we can soft/hard-stop the slot */ + beenthere(kctx, "soft/hard-stopped slot %d (there was a job in next which was successfully cleared)\n", js); + kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, + js, hw_action, core_reqs, katom); + } + /* If there was no job in the next registers, then the job we were + * interested in has finished, so we need not take any action + */ + } + } + + KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 0); +} + +void kbase_job_kill_jobs_from_context(struct kbase_context *kctx) +{ + unsigned long flags; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + int i; + + KBASE_DEBUG_ASSERT(kctx != NULL); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + /* Cancel any remaining running jobs for this kctx */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* Invalidate all jobs in context, to prevent re-submitting */ + for (i = 0; i < BASE_JD_ATOM_COUNT; i++) + kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_CANCELLED; + + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbase_job_slot_hardstop(kctx, i, NULL); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); +} + +void kbase_job_zap_context(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + int i; + mali_bool evict_success; + + KBASE_DEBUG_ASSERT(kctx != NULL); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + /* + * Critical assumption: No more submission is possible outside of the + * workqueue. This is because the OS *must* prevent U/K calls (IOCTLs) + * whilst the struct kbase_context is terminating. + */ + + /* First, atomically do the following: + * - mark the context as dying + * - try to evict it from the policy queue */ + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + js_kctx_info->ctx.is_dying = MALI_TRUE; + + dev_dbg(kbdev->dev, "Zap: Try Evict Ctx %p", kctx); + mutex_lock(&js_devdata->queue_mutex); + evict_success = kbasep_js_policy_try_evict_ctx(&js_devdata->policy, kctx); + mutex_unlock(&js_devdata->queue_mutex); + + /* + * At this point we know: + * - If eviction succeeded, it was in the policy queue, but now no longer is + * - We must cancel the jobs here. No Power Manager active reference to + * release. + * - This happens asynchronously - kbase_jd_zap_context() will wait for + * those jobs to be killed. + * - If eviction failed, then it wasn't in the policy queue. It is one of + * the following: + * - a. it didn't have any jobs, and so is not in the Policy Queue or the + * Run Pool (not scheduled) + * - Hence, no more work required to cancel jobs. No Power Manager active + * reference to release. + * - b. it was in the middle of a scheduling transaction (and thus must + * have at least 1 job). This can happen from a syscall or a kernel thread. + * We still hold the jsctx_mutex, and so the thread must be waiting inside + * kbasep_js_try_schedule_head_ctx(), before checking whether the runpool + * is full. That thread will continue after we drop the mutex, and will + * notice the context is dying. It will rollback the transaction, killing + * all jobs at the same time. kbase_jd_zap_context() will wait for those + * jobs to be killed. + * - Hence, no more work required to cancel jobs, or to release the Power + * Manager active reference. + * - c. it is scheduled, and may or may not be running jobs + * - We must cause it to leave the runpool by stopping it from submitting + * any more jobs. When it finally does leave, + * kbasep_js_runpool_requeue_or_kill_ctx() will kill all remaining jobs + * (because it is dying), release the Power Manager active reference, and + * will not requeue the context in the policy queue. kbase_jd_zap_context() + * will wait for those jobs to be killed. + * - Hence, work required just to make it leave the runpool. Cancelling + * jobs and releasing the Power manager active reference will be handled + * when it leaves the runpool. + */ + + if (evict_success != MALI_FALSE || js_kctx_info->ctx.is_scheduled == MALI_FALSE) { + /* The following events require us to kill off remaining jobs and + * update PM book-keeping: + * - we evicted it correctly (it must have jobs to be in the Policy Queue) + * + * These events need no action, but take this path anyway: + * - Case a: it didn't have any jobs, and was never in the Queue + * - Case b: scheduling transaction will be partially rolled-back (this + * already cancels the jobs) + */ + + KBASE_TRACE_ADD(kbdev, JM_ZAP_NON_SCHEDULED, kctx, NULL, 0u, js_kctx_info->ctx.is_scheduled); + + dev_dbg(kbdev->dev, "Zap: Ctx %p evict_success=%d, scheduled=%d", kctx, evict_success, js_kctx_info->ctx.is_scheduled); + + if (evict_success != MALI_FALSE) { + /* Only cancel jobs when we evicted from the policy queue. No Power + * Manager active reference was held. + * + * Having is_dying set ensures that this kills, and doesn't requeue */ + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_FALSE); + } + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + } else { + unsigned long flags; + mali_bool was_retained; + /* Case c: didn't evict, but it is scheduled - it's in the Run Pool */ + KBASE_TRACE_ADD(kbdev, JM_ZAP_SCHEDULED, kctx, NULL, 0u, js_kctx_info->ctx.is_scheduled); + dev_dbg(kbdev->dev, "Zap: Ctx %p is in RunPool", kctx); + + /* Disable the ctx from submitting any more jobs */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_clear_submit_allowed(js_devdata, kctx); + + /* Retain and (later) release the context whilst it is is now disallowed from submitting + * jobs - ensures that someone somewhere will be removing the context later on */ + was_retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + + /* Since it's scheduled and we have the jsctx_mutex, it must be retained successfully */ + KBASE_DEBUG_ASSERT(was_retained != MALI_FALSE); + + dev_dbg(kbdev->dev, "Zap: Ctx %p Kill Any Running jobs", kctx); + /* Cancel any remaining running jobs for this kctx - if any. Submit is disallowed + * which takes effect immediately, so no more new jobs will appear after we do this. */ + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbase_job_slot_hardstop(kctx, i, NULL); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + dev_dbg(kbdev->dev, "Zap: Ctx %p Release (may or may not schedule out immediately)", kctx); + kbasep_js_runpool_release_ctx(kbdev, kctx); + } + KBASE_TRACE_ADD(kbdev, JM_ZAP_DONE, kctx, NULL, 0u, 0u); + + /* After this, you must wait on both the kbase_jd_context::zero_jobs_wait + * and the kbasep_js_kctx_info::ctx::is_scheduled_waitq - to wait for the + * jobs to be destroyed, and the context to be de-scheduled (if it was on + * the runpool). + * + * kbase_jd_zap_context() will do this. */ +} +KBASE_EXPORT_TEST_API(kbase_job_zap_context) + +mali_error kbase_job_slot_init(struct kbase_device *kbdev) +{ + int i; + KBASE_DEBUG_ASSERT(kbdev); + + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbasep_jm_init_submit_slot(&kbdev->jm_slots[i]); + + return MALI_ERROR_NONE; +} +KBASE_EXPORT_TEST_API(kbase_job_slot_init) + +void kbase_job_slot_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbase_job_slot_term(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev); +} +KBASE_EXPORT_TEST_API(kbase_job_slot_term) + +/** + * Soft-stop the specified job slot, with extra information about the stop + * + * The job slot lock must be held when calling this function. + * The job slot must not already be in the process of being soft-stopped. + * + * Where possible any job in the next register is evicted before the soft-stop. + * + * @param kbdev The kbase device + * @param js The job slot to soft-stop + * @param target_katom The job that should be soft-stopped (or NULL for any job) + * @param sw_flags Flags to pass in about the soft-stop + */ +void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom, u32 sw_flags) +{ + KBASE_DEBUG_ASSERT(!(sw_flags & JS_COMMAND_MASK)); + kbasep_job_slot_soft_or_hard_stop(kbdev, NULL, js, target_katom, + JS_COMMAND_SOFT_STOP | sw_flags); +} + +/** + * Soft-stop the specified job slot + * + * The job slot lock must be held when calling this function. + * The job slot must not already be in the process of being soft-stopped. + * + * Where possible any job in the next register is evicted before the soft-stop. + * + * @param kbdev The kbase device + * @param js The job slot to soft-stop + * @param target_katom The job that should be soft-stopped (or NULL for any job) + */ +void kbase_job_slot_softstop(struct kbase_device *kbdev, int js, struct kbase_jd_atom *target_katom) +{ + kbase_job_slot_softstop_swflags(kbdev, js, target_katom, 0u); +} + +/** + * Hard-stop the specified job slot + * + * The job slot lock must be held when calling this function. + * + * @param kctx The kbase context that contains the job(s) that should + * be hard-stopped + * @param js The job slot to hard-stop + * @param target_katom The job that should be hard-stopped (or NULL for all + * jobs from the context) + */ +void kbase_job_slot_hardstop(struct kbase_context *kctx, int js, + struct kbase_jd_atom *target_katom) +{ + struct kbase_device *kbdev = kctx->kbdev; + + kbasep_job_slot_soft_or_hard_stop(kbdev, kctx, js, target_katom, + JS_COMMAND_HARD_STOP); +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_8401) || + kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_9510) || + (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_T76X_3542) && + (target_katom == NULL || target_katom->core_req & BASE_JD_REQ_FS_AFBC))) { + /* MIDBASE-2916 if a fragment job with AFBC encoding is + * hardstopped, ensure to do a soft reset also in order to + * clear the GPU status. + * Workaround for HW issue 8401 has an issue,so after + * hard-stopping just reset the GPU. This will ensure that the + * jobs leave the GPU.*/ + if (kbase_prepare_to_reset_gpu_locked(kbdev)) { + dev_err(kbdev->dev, "Issueing GPU\ + soft-reset after hard stopping due to hardware issue"); + kbase_reset_gpu_locked(kbdev); + } + } +#endif +} + +/** + * For a certain soft/hard-stop action, work out whether to enter disjoint + * state. + * + * This does not register multiple disjoint events if the atom has already + * started a disjoint period + * + * core_reqs can be supplied as 0 if the atom had not started on the hardware + * (and so a 'real' soft/hard-stop was not required, but it still interrupted + * flow, perhaps on another context) + * + * kbase_job_check_leave_disjoint() should be used to end the disjoint + * state when the soft/hard-stop action is complete + */ +void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, + u16 core_reqs, struct kbase_jd_atom *target_katom) +{ + u32 hw_action = action & JS_COMMAND_MASK; + + /* For hard-stop, don't enter if hard-stop not allowed */ + if (hw_action == JS_COMMAND_HARD_STOP && + !kbasep_hard_stop_allowed(kbdev, core_reqs)) + return; + + /* For soft-stop, don't enter if soft-stop not allowed, or isn't + * causing disjoint */ + if (hw_action == JS_COMMAND_SOFT_STOP && + !(kbasep_soft_stop_allowed(kbdev, core_reqs) && + (action & JS_COMMAND_SW_CAUSES_DISJOINT))) + return; + + /* Nothing to do if already logged disjoint state on this atom */ + if (target_katom->atom_flags & KBASE_KATOM_FLAG_IN_DISJOINT) + return; + + target_katom->atom_flags |= KBASE_KATOM_FLAG_IN_DISJOINT; + kbase_disjoint_state_up(kbdev); +} + +/** + * Work out whether to leave disjoint state when finishing an atom that was + * originated by kbase_job_check_enter_disjoint(). + */ +void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, + struct kbase_jd_atom *target_katom) +{ + if (target_katom->atom_flags & KBASE_KATOM_FLAG_IN_DISJOINT) { + target_katom->atom_flags &= ~KBASE_KATOM_FLAG_IN_DISJOINT; + kbase_disjoint_state_down(kbdev); + } +} + + +#if KBASE_GPU_RESET_EN +static void kbase_debug_dump_registers(struct kbase_device *kbdev) +{ + int i; + dev_err(kbdev->dev, "Register state:"); + dev_err(kbdev->dev, " GPU_IRQ_RAWSTAT=0x%08x GPU_STATUS=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS), NULL)); + dev_err(kbdev->dev, " JOB_IRQ_RAWSTAT=0x%08x JOB_IRQ_JS_STATE=0x%08x JOB_IRQ_THROTTLE=0x%08x", + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_JS_STATE), NULL), + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_THROTTLE), NULL)); + for (i = 0; i < 3; i++) { + dev_err(kbdev->dev, " JS%d_STATUS=0x%08x JS%d_HEAD_LO=0x%08x", + i, kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_STATUS), + NULL), + i, kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_HEAD_LO), + NULL)); + } + dev_err(kbdev->dev, " MMU_IRQ_RAWSTAT=0x%08x GPU_FAULTSTATUS=0x%08x", + kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS), NULL)); + dev_err(kbdev->dev, " GPU_IRQ_MASK=0x%08x JOB_IRQ_MASK=0x%08x MMU_IRQ_MASK=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL), + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), NULL), + kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL)); + dev_err(kbdev->dev, " PWR_OVERRIDE0=0x%08x PWR_OVERRIDE1=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE0), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE1), NULL)); + dev_err(kbdev->dev, " SHADER_CONFIG=0x%08x L2_MMU_CONFIG=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(SHADER_CONFIG), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), NULL)); +} + +void kbasep_reset_timeout_worker(struct work_struct *data) +{ + unsigned long flags; + struct kbase_device *kbdev; + int i; + ktime_t end_timestamp = ktime_get(); + struct kbasep_js_device_data *js_devdata; + struct kbase_uk_hwcnt_setup hwcnt_setup = { {0} }; + enum kbase_instr_state bckp_state; + + KBASE_DEBUG_ASSERT(data); + + kbdev = container_of(data, struct kbase_device, reset_work); + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + KBASE_TRACE_ADD(kbdev, JM_BEGIN_RESET_WORKER, NULL, NULL, 0u, 0); + + /* Make sure the timer has completed - this cannot be done from interrupt context, + * so this cannot be done within kbasep_try_reset_gpu_early. */ + hrtimer_cancel(&kbdev->reset_timer); + + if (kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + /* This would re-activate the GPU. Since it's already idle, there's no + * need to reset it */ + atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING); + kbase_disjoint_state_down(kbdev); + wake_up(&kbdev->reset_wait); + return; + } + + mutex_lock(&kbdev->pm.lock); + /* We hold the pm lock, so there ought to be a current policy */ + KBASE_DEBUG_ASSERT(kbdev->pm.pm_current_policy); + + /* All slot have been soft-stopped and we've waited SOFT_STOP_RESET_TIMEOUT for the slots to clear, at this point + * we assume that anything that is still left on the GPU is stuck there and we'll kill it when we reset the GPU */ + + dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)", RESET_TIMEOUT); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { /*the same interrupt handler preempted itself */ + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + /* Save the HW counters setup */ + if (kbdev->hwcnt.kctx != NULL) { + struct kbase_context *kctx = kbdev->hwcnt.kctx; + hwcnt_setup.dump_buffer = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), kctx) & 0xffffffff; + hwcnt_setup.dump_buffer |= (mali_addr64) kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), kctx) << 32; + hwcnt_setup.jm_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), kctx); + hwcnt_setup.shader_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), kctx); + hwcnt_setup.tiler_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), kctx); + hwcnt_setup.l3_cache_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), kctx); + hwcnt_setup.mmu_l2_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), kctx); + } + + /* Output the state of some interesting registers to help in the + * debugging of GPU resets */ + kbase_debug_dump_registers(kbdev); + + bckp_state = kbdev->hwcnt.state; + kbdev->hwcnt.state = KBASE_INSTR_STATE_RESETTING; + kbdev->hwcnt.triggered = 0; + /* Disable IRQ to avoid IRQ handlers to kick in after releaseing the spinlock; + * this also clears any outstanding interrupts */ + kbase_pm_disable_interrupts(kbdev); + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Ensure that any IRQ handlers have finished + * Must be done without any locks IRQ handlers will take */ + kbase_synchronize_irqs(kbdev); + + /* Reset the GPU */ + kbase_pm_init_hw(kbdev, MALI_TRUE); + /* IRQs were re-enabled by kbase_pm_init_hw, and GPU is still powered */ + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Restore the HW counters setup */ + if (kbdev->hwcnt.kctx != NULL) { + struct kbase_context *kctx = kbdev->hwcnt.kctx; + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_OFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), hwcnt_setup.dump_buffer & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), hwcnt_setup.dump_buffer >> 32, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), hwcnt_setup.jm_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), hwcnt_setup.shader_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), hwcnt_setup.l3_cache_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), hwcnt_setup.mmu_l2_bm, kctx); + + /* Due to PRLAM-8186 we need to disable the Tiler before we enable the HW counter dump. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), 0, kctx); + else + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), hwcnt_setup.tiler_bm, kctx); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_MANUAL, kctx); + + /* If HW has PRLAM-8186 we can now re-enable the tiler HW counters dump */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), hwcnt_setup.tiler_bm, kctx); + } + kbdev->hwcnt.state = bckp_state; + switch (kbdev->hwcnt.state) { + /* Cases for waking kbasep_cache_clean_worker worker */ + case KBASE_INSTR_STATE_CLEANED: + /* Cache-clean IRQ occurred, but we reset: + * Wakeup incase the waiter saw RESETTING */ + case KBASE_INSTR_STATE_REQUEST_CLEAN: + /* After a clean was requested, but before the regs were written: + * Wakeup incase the waiter saw RESETTING */ + wake_up(&kbdev->hwcnt.cache_clean_wait); + break; + case KBASE_INSTR_STATE_CLEANING: + /* Either: + * 1) We've not got the Cache-clean IRQ yet: it was lost, or: + * 2) We got it whilst resetting: it was voluntarily lost + * + * So, move to the next state and wakeup: */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANED; + wake_up(&kbdev->hwcnt.cache_clean_wait); + break; + + /* Cases for waking anyone else */ + case KBASE_INSTR_STATE_DUMPING: + /* If dumping, abort the dump, because we may've lost the IRQ */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + break; + case KBASE_INSTR_STATE_DISABLED: + case KBASE_INSTR_STATE_IDLE: + case KBASE_INSTR_STATE_FAULT: + /* Every other reason: wakeup in that state */ + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + break; + + /* Unhandled cases */ + case KBASE_INSTR_STATE_RESETTING: + default: + BUG(); + break; + } + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Complete any jobs that were still on the GPU */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) { + int nr_done; + struct kbase_jm_slot *slot = &kbdev->jm_slots[i]; + + nr_done = kbasep_jm_nr_jobs_submitted(slot); + while (nr_done) { + dev_err(kbdev->dev, "Job stuck in slot %d on the GPU was cancelled", i); + kbase_job_done_slot(kbdev, i, BASE_JD_EVENT_JOB_CANCELLED, 0, &end_timestamp); + nr_done--; + } + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + mutex_lock(&js_devdata->runpool_mutex); + + /* Reprogram the GPU's MMU */ + for (i = 0; i < BASE_MAX_NR_AS; i++) { + if (js_devdata->runpool_irq.per_as_data[i].kctx) { + struct kbase_as *as = &kbdev->as[i]; + mutex_lock(&as->transaction_mutex); + kbase_mmu_update(js_devdata->runpool_irq.per_as_data[i].kctx); + mutex_unlock(&as->transaction_mutex); + } + } + + atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING); + + kbase_disjoint_state_down(kbdev); + wake_up(&kbdev->reset_wait); + dev_err(kbdev->dev, "Reset complete"); + + /* Find out what cores are required now */ + kbase_pm_update_cores_state(kbdev); + + /* Synchronously request and wait for those cores, because if + * instrumentation is enabled it would need them immediately. */ + kbase_pm_check_transitions_sync(kbdev); + + /* Try submitting some jobs to restart processing */ + if (js_devdata->nr_user_contexts_running > 0) { + KBASE_TRACE_ADD(kbdev, JM_SUBMIT_AFTER_RESET, NULL, NULL, 0u, 0); + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_try_run_next_job_nolock(kbdev); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + } + + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&kbdev->pm.lock); + + kbase_pm_context_idle(kbdev); + KBASE_TRACE_ADD(kbdev, JM_END_RESET_WORKER, NULL, NULL, 0u, 0); +} + +enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *timer) +{ + struct kbase_device *kbdev = container_of(timer, struct kbase_device, reset_timer); + + KBASE_DEBUG_ASSERT(kbdev); + + /* Reset still pending? */ + if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) == KBASE_RESET_GPU_COMMITTED) + queue_work(kbdev->reset_workq, &kbdev->reset_work); + + return HRTIMER_NORESTART; +} + +/* + * If all jobs are evicted from the GPU then we can reset the GPU + * immediately instead of waiting for the timeout to elapse + */ + +static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev) +{ + int i; + int pending_jobs = 0; + + KBASE_DEBUG_ASSERT(kbdev); + + /* Count the number of jobs */ + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) { + struct kbase_jm_slot *slot = &kbdev->jm_slots[i]; + pending_jobs += kbasep_jm_nr_jobs_submitted(slot); + } + + if (pending_jobs > 0) { + /* There are still jobs on the GPU - wait */ + return; + } + + /* Check that the reset has been committed to (i.e. kbase_reset_gpu has been called), and that no other + * thread beat this thread to starting the reset */ + if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) != KBASE_RESET_GPU_COMMITTED) { + /* Reset has already occurred */ + return; + } + queue_work(kbdev->reset_workq, &kbdev->reset_work); +} + +static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + + js_devdata = &kbdev->js_data; + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_try_reset_gpu_early_locked(kbdev); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); +} + +/* + * Prepare for resetting the GPU. + * This function just soft-stops all the slots to ensure that as many jobs as possible are saved. + * + * The function returns a boolean which should be interpreted as follows: + * - MALI_TRUE - Prepared for reset, kbase_reset_gpu should be called. + * - MALI_FALSE - Another thread is performing a reset, kbase_reset_gpu should not be called. + * + * @return See description + */ +mali_bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev) +{ + int i; + + KBASE_DEBUG_ASSERT(kbdev); + + if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING, KBASE_RESET_GPU_PREPARED) != KBASE_RESET_GPU_NOT_PENDING) { + /* Some other thread is already resetting the GPU */ + return MALI_FALSE; + } + + kbase_disjoint_state_up(kbdev); + + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbase_job_slot_softstop(kbdev, i, NULL); + + return MALI_TRUE; +} + +mali_bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev) +{ + unsigned long flags; + mali_bool ret; + struct kbasep_js_device_data *js_devdata; + + js_devdata = &kbdev->js_data; + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + ret = kbase_prepare_to_reset_gpu_locked(kbdev); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return ret; +} +KBASE_EXPORT_TEST_API(kbase_prepare_to_reset_gpu) + +/* + * This function should be called after kbase_prepare_to_reset_gpu iff it returns MALI_TRUE. + * It should never be called without a corresponding call to kbase_prepare_to_reset_gpu. + * + * After this function is called (or not called if kbase_prepare_to_reset_gpu returned MALI_FALSE), + * the caller should wait for kbdev->reset_waitq to be signalled to know when the reset has completed. + */ +void kbase_reset_gpu(struct kbase_device *kbdev) +{ + u32 timeout_ms; + + KBASE_DEBUG_ASSERT(kbdev); + + /* Note this is an assert/atomic_set because it is a software issue for a race to be occuring here */ + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_PREPARED); + atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED); + + timeout_ms = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS); + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", timeout_ms); + hrtimer_start(&kbdev->reset_timer, HR_TIMER_DELAY_MSEC(timeout_ms), HRTIMER_MODE_REL); + + /* Try resetting early */ + kbasep_try_reset_gpu_early(kbdev); +} +KBASE_EXPORT_TEST_API(kbase_reset_gpu) + +void kbase_reset_gpu_locked(struct kbase_device *kbdev) +{ + u32 timeout_ms; + + KBASE_DEBUG_ASSERT(kbdev); + + /* Note this is an assert/atomic_set because it is a software issue for a race to be occuring here */ + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_PREPARED); + atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED); + + timeout_ms = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS); + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", timeout_ms); + hrtimer_start(&kbdev->reset_timer, HR_TIMER_DELAY_MSEC(timeout_ms), HRTIMER_MODE_REL); + + /* Try resetting early */ + kbasep_try_reset_gpu_early_locked(kbdev); +} +#endif /* KBASE_GPU_RESET_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.h new file mode 100644 index 0000000000000000000000000000000000000000..d171833813113f4da7b78a8e388b98ec9f762245 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.h @@ -0,0 +1,199 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_jm.h + * Job Manager Low-level APIs. + */ + +#ifndef _KBASE_JM_H_ +#define _KBASE_JM_H_ + +#include +#include +#include + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_jm Job Manager Low-level APIs + * @{ + * + */ + +static INLINE int kbasep_jm_is_js_free(struct kbase_device *kbdev, int js, struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= js && js < kbdev->gpu_props.num_job_slots); + + return !kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), kctx); +} + +/** + * This checks that: + * - there is enough space in the GPU's buffers (JS_NEXT and JS_HEAD registers) to accomodate the job. + * - there is enough space to track the job in a our Submit Slots. Note that we have to maintain space to + * requeue one job in case the next registers on the hardware need to be cleared. + */ +static INLINE mali_bool kbasep_jm_is_submit_slots_free(struct kbase_device *kbdev, int js, struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= js && js < kbdev->gpu_props.num_job_slots); + + if (atomic_read(&kbdev->reset_gpu) != KBASE_RESET_GPU_NOT_PENDING) { + /* The GPU is being reset - so prevent submission */ + return MALI_FALSE; + } + + return (mali_bool) (kbasep_jm_is_js_free(kbdev, js, kctx) + && kbdev->jm_slots[js].submitted_nr < (BASE_JM_SUBMIT_SLOTS - 2)); +} + +/** + * Initialize a submit slot + */ +static INLINE void kbasep_jm_init_submit_slot(struct kbase_jm_slot *slot) +{ + slot->submitted_nr = 0; + slot->submitted_head = 0; +} + +/** + * Find the atom at the idx'th element in the queue without removing it, starting at the head with idx==0. + */ +static INLINE struct kbase_jd_atom *kbasep_jm_peek_idx_submit_slot(struct kbase_jm_slot *slot, u8 idx) +{ + u8 pos; + struct kbase_jd_atom *katom; + + KBASE_DEBUG_ASSERT(idx < BASE_JM_SUBMIT_SLOTS); + + pos = (slot->submitted_head + idx) & BASE_JM_SUBMIT_SLOTS_MASK; + katom = slot->submitted[pos]; + + return katom; +} + +/** + * Pop front of the submitted + */ +static INLINE struct kbase_jd_atom *kbasep_jm_dequeue_submit_slot(struct kbase_jm_slot *slot) +{ + u8 pos; + struct kbase_jd_atom *katom; + + pos = slot->submitted_head & BASE_JM_SUBMIT_SLOTS_MASK; + katom = slot->submitted[pos]; + slot->submitted[pos] = NULL; /* Just to catch bugs... */ + KBASE_DEBUG_ASSERT(katom); + + /* rotate the buffers */ + slot->submitted_head = (slot->submitted_head + 1) & BASE_JM_SUBMIT_SLOTS_MASK; + slot->submitted_nr--; + + dev_dbg(katom->kctx->kbdev->dev, "katom %p new head %u", (void *)katom, (unsigned int)slot->submitted_head); + + return katom; +} + +/* Pop back of the submitted queue (unsubmit a job) + */ +static INLINE struct kbase_jd_atom *kbasep_jm_dequeue_tail_submit_slot(struct kbase_jm_slot *slot) +{ + u8 pos; + + slot->submitted_nr--; + + pos = (slot->submitted_head + slot->submitted_nr) & BASE_JM_SUBMIT_SLOTS_MASK; + + return slot->submitted[pos]; +} + +static INLINE u8 kbasep_jm_nr_jobs_submitted(struct kbase_jm_slot *slot) +{ + return slot->submitted_nr; +} + +/** + * Push back of the submitted + */ +static INLINE void kbasep_jm_enqueue_submit_slot(struct kbase_jm_slot *slot, struct kbase_jd_atom *katom) +{ + u8 nr; + u8 pos; + nr = slot->submitted_nr++; + KBASE_DEBUG_ASSERT(nr < BASE_JM_SUBMIT_SLOTS); + + pos = (slot->submitted_head + nr) & BASE_JM_SUBMIT_SLOTS_MASK; + slot->submitted[pos] = katom; +} + +/** + * @brief Query whether a job peeked/dequeued from the submit slots is a + * 'dummy' job that is used for hardware workaround purposes. + * + * Any time a job is peeked/dequeued from the submit slots, this should be + * queried on that job. + * + * If a \a atom is indicated as being a dummy job, then you must not attempt + * to use \a atom. This is because its members will not necessarily be + * initialized, and so could lead to a fault if they were used. + * + * @param[in] kbdev kbase device pointer + * @param[in] atom The atom to query + * + * @return MALI_TRUE if \a atom is for a dummy job, in which case you must not + * attempt to use it. + * @return MALI_FALSE otherwise, and \a atom is safe to use. + */ +static INLINE mali_bool kbasep_jm_is_dummy_workaround_job(struct kbase_device *kbdev, struct kbase_jd_atom *atom) +{ + /* Query the set of workaround jobs here */ + /* none exists today */ + return MALI_FALSE; +} + +/** + * @brief Submit a job to a certain job-slot + * + * The caller must check kbasep_jm_is_submit_slots_free() != MALI_FALSE before calling this. + * + * The following locking conditions are made on the caller: + * - it must hold the kbasep_js_device_data::runpoool_irq::lock + */ +void kbase_job_submit_nolock(struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js); + +/** + * @brief Complete the head job on a particular job-slot + */ +void kbase_job_done_slot(struct kbase_device *kbdev, int s, u32 completion_code, u64 job_tail, ktime_t *end_timestamp); + + /** @} *//* end group kbase_jm */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js.c new file mode 100644 index 0000000000000000000000000000000000000000..7c2ad5d55198d06eca77e4b1b486a50dbb897841 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js.c @@ -0,0 +1,2157 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Job Scheduler Implementation + */ +#include +#include +#include +#include +#include + +#include "mali_kbase_jm.h" +#include +#include + +/* + * Private types + */ + +/** Bitpattern indicating the result of releasing a context */ +enum { + /** The context was descheduled - caller should try scheduling in a new one + * to keep the runpool full */ + KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED = (1u << 0), +}; + +typedef u32 kbasep_js_release_result; + +/* + * Private function prototypes + */ +STATIC INLINE void kbasep_js_deref_permon_check_and_disable_cycle_counter(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +STATIC INLINE void kbasep_js_ref_permon_check_and_enable_cycle_counter(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +STATIC kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state); + +/** Helper for trace subcodes */ +#if KBASE_TRACE_ENABLE +STATIC int kbasep_js_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int as_nr; + int refcnt = 0; + + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + as_nr = kctx->as_nr; + if (as_nr != KBASEP_AS_NR_INVALID) { + struct kbasep_js_per_as_data *js_per_as_data; + + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + refcnt = js_per_as_data->as_busy_refcount; + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return refcnt; +} +#else /* KBASE_TRACE_ENABLE */ +STATIC int kbasep_js_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(kctx); + return 0; +} +#endif /* KBASE_TRACE_ENABLE */ + +/* + * Private types + */ +enum { + JS_DEVDATA_INIT_NONE = 0, + JS_DEVDATA_INIT_CONSTANTS = (1 << 0), + JS_DEVDATA_INIT_POLICY = (1 << 1), + JS_DEVDATA_INIT_ALL = ((1 << 2) - 1) +}; + +enum { + JS_KCTX_INIT_NONE = 0, + JS_KCTX_INIT_CONSTANTS = (1 << 0), + JS_KCTX_INIT_POLICY = (1 << 1), + JS_KCTX_INIT_ALL = ((1 << 2) - 1) +}; + +/* + * Private functions + */ + +/** + * Check if the job had performance monitoring enabled and decrement the count. If no jobs require + * performance monitoring, then the cycle counters will be disabled in the GPU. + * + * No locks need to be held - locking is handled further down + * + * This function does not sleep. + */ + +STATIC INLINE void kbasep_js_deref_permon_check_and_disable_cycle_counter(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + if (katom->core_req & BASE_JD_REQ_PERMON) + kbase_pm_release_gpu_cycle_counter(kbdev); +} + +/** + * Check if the job has performance monitoring enabled and keep a count of it. If at least one + * job requires performance monitoring, then the cycle counters will be enabled in the GPU. + * + * No locks need to be held - locking is handled further down + * + * The L2 Cache must be ON when this function is called + * + * This function does not sleep. + */ + +STATIC INLINE void kbasep_js_ref_permon_check_and_enable_cycle_counter(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + if (katom->core_req & BASE_JD_REQ_PERMON) + kbase_pm_request_gpu_cycle_counter_l2_is_on(kbdev); +} + +/* + * The following locking conditions are made on the caller: + * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. + * - The caller must hold the kbasep_js_device_data::runpool_mutex + */ +STATIC INLINE void runpool_inc_context_count(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex)); + + /* Track total contexts */ + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running < S8_MAX); + ++(js_devdata->nr_all_contexts_running); + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) { + /* Track contexts that can submit jobs */ + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running < S8_MAX); + ++(js_devdata->nr_user_contexts_running); + } +} + +/* + * The following locking conditions are made on the caller: + * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. + * - The caller must hold the kbasep_js_device_data::runpool_mutex + */ +STATIC INLINE void runpool_dec_context_count(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex)); + + /* Track total contexts */ + --(js_devdata->nr_all_contexts_running); + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running >= 0); + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) { + /* Track contexts that can submit jobs */ + --(js_devdata->nr_user_contexts_running); + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running >= 0); + } +} + +/** + * @brief check whether the runpool is full for a specified context + * + * If kctx == NULL, then this makes the least restrictive check on the + * runpool. A specific context that is supplied immediately after could fail + * the check, even under the same conditions. + * + * Therefore, once a context is obtained you \b must re-check it with this + * function, since the return value could change to MALI_FALSE. + * + * The following locking conditions are made on the caller: + * - In all cases, the caller must hold kbasep_js_device_data::runpool_mutex + * - When kctx != NULL the caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. + * - When kctx == NULL, then the caller need not hold any jsctx_mutex locks (but it doesn't do any harm to do so). + */ +STATIC mali_bool check_is_runpool_full(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + mali_bool is_runpool_full; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex)); + + /* Regardless of whether a context is submitting or not, can't have more than there + * are HW address spaces */ + is_runpool_full = (mali_bool) (js_devdata->nr_all_contexts_running >= kbdev->nr_hw_address_spaces); + + if (kctx != NULL && (kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) { + BUG_ON(!mutex_is_locked(&kctx->jctx.sched_info.ctx.jsctx_mutex)); + /* Contexts that submit might use less of the address spaces available, due to HW + * workarounds. In which case, the runpool is also full when the number of + * submitting contexts exceeds the number of submittable address spaces. + * + * Both checks must be made: can have nr_user_address_spaces == nr_hw_address spaces, + * and at the same time can have nr_user_contexts_running < nr_all_contexts_running. */ + is_runpool_full |= (mali_bool) (js_devdata->nr_user_contexts_running >= kbdev->nr_user_address_spaces); + } + + return is_runpool_full; +} + +STATIC base_jd_core_req core_reqs_from_jsn_features(u16 features) /* JS_FEATURE register value */ +{ + base_jd_core_req core_req = 0u; + + if ((features & JS_FEATURE_SET_VALUE_JOB) != 0) + core_req |= BASE_JD_REQ_V; + + if ((features & JS_FEATURE_CACHE_FLUSH_JOB) != 0) + core_req |= BASE_JD_REQ_CF; + + if ((features & JS_FEATURE_COMPUTE_JOB) != 0) + core_req |= BASE_JD_REQ_CS; + + if ((features & JS_FEATURE_TILER_JOB) != 0) + core_req |= BASE_JD_REQ_T; + + if ((features & JS_FEATURE_FRAGMENT_JOB) != 0) + core_req |= BASE_JD_REQ_FS; + + return core_req; +} + +/** + * Picks and reserves an address space. + * + * When this function returns, the address space returned is reserved and + * cannot be picked for another context until it is released. + * + * The caller must ensure there \b is a free address space before calling this. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + * + * @return a non-NULL pointer to a struct kbase_as that is not in use by any other context + */ +STATIC struct kbase_as *pick_free_addr_space(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + struct kbase_as *current_as; + long ffs_result; + + js_devdata = &kbdev->js_data; + + lockdep_assert_held(&js_devdata->runpool_mutex); + + /* Find the free address space */ + ffs_result = ffs(js_devdata->as_free) - 1; + + /* ASSERT that we should've found a free one */ + KBASE_DEBUG_ASSERT(0 <= ffs_result && ffs_result < kbdev->nr_hw_address_spaces); + /* Ensure no-one else picks this one */ + js_devdata->as_free &= ~((u16) (1u << ffs_result)); + + current_as = &kbdev->as[ffs_result]; + + return current_as; +} + +/** + * Release an address space, making it available for being picked again. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + */ +STATIC INLINE void release_addr_space(struct kbase_device *kbdev, int kctx_as_nr) +{ + struct kbasep_js_device_data *js_devdata; + u16 as_bit = (1u << kctx_as_nr); + + js_devdata = &kbdev->js_data; + lockdep_assert_held(&js_devdata->runpool_mutex); + + /* The address space must not already be free */ + KBASE_DEBUG_ASSERT(!(js_devdata->as_free & as_bit)); + + js_devdata->as_free |= as_bit; +} + +/** + * Assign an Address Space (AS) to a context, and add the context to the Policy. + * + * This includes: + * - setting up the global runpool_irq structure and the context on the AS + * - Activating the MMU on the AS + * - Allowing jobs to be submitted on the AS + * + * Locking conditions: + * - Caller must hold the kbasep_js_kctx_info::jsctx_mutex + * - Caller must hold the kbasep_js_device_data::runpool_mutex + * - Caller must hold AS transaction mutex + * - Caller must hold Runpool IRQ lock + */ +STATIC void assign_and_activate_kctx_addr_space(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_as *current_as) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_per_as_data *js_per_as_data; + int as_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(current_as != NULL); + + js_devdata = &kbdev->js_data; + as_nr = current_as->number; + + lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex); + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(¤t_as->transaction_mutex); + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + /* Attribute handling */ + kbasep_js_ctx_attr_runpool_retain_ctx(kbdev, kctx); + + /* Assign addr space */ + kctx->as_nr = as_nr; +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_mmu_as_in_use(kctx->as_nr); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + /* Activate this address space on the MMU */ + kbase_mmu_update(kctx); + + /* Allow it to run jobs */ + kbasep_js_set_submit_allowed(js_devdata, kctx); + + /* Book-keeping */ + js_per_as_data->kctx = kctx; + js_per_as_data->as_busy_refcount = 0; + + /* Lastly, add the context to the policy's runpool - this really allows it to run jobs */ + kbasep_js_policy_runpool_add_ctx(&js_devdata->policy, kctx); +} + +void kbasep_js_try_run_next_job_nolock(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + int js; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + /* It's cheap and simple to retest this here - otherwise we burden the + * caller with it. In some cases, we do this higher up to optimize out the + * spinlock. */ + if (js_devdata->nr_user_contexts_running == 0) + return; /* No contexts present - the GPU might be powered off, so just return */ + + for (js = 0; js < kbdev->gpu_props.num_job_slots; ++js) + kbasep_js_try_run_next_job_on_slot_nolock(kbdev, js); +} + +/** Hold the kbasep_js_device_data::runpool_irq::lock for this */ +mali_bool kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_per_as_data *js_per_as_data; + mali_bool result = MALI_FALSE; + int as_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_devdata = &kbdev->js_data; + + as_nr = kctx->as_nr; + if (as_nr != KBASEP_AS_NR_INVALID) { + int new_refcnt; + + KBASE_DEBUG_ASSERT(as_nr >= 0); + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + KBASE_DEBUG_ASSERT(js_per_as_data->kctx != NULL); + + new_refcnt = ++(js_per_as_data->as_busy_refcount); + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RETAIN_CTX_NOLOCK, kctx, NULL, 0u, new_refcnt); + result = MALI_TRUE; + } + + return result; +} + +/* + * Functions private to KBase ('Protected' functions) + */ +void kbase_js_try_run_jobs(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + mutex_lock(&js_devdata->runpool_mutex); + if (js_devdata->nr_user_contexts_running != 0) { + /* Only try running jobs when we have contexts present, otherwise the GPU might be powered off. */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + kbasep_js_try_run_next_job_nolock(kbdev); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + } + mutex_unlock(&js_devdata->runpool_mutex); +} + +void kbase_js_try_run_jobs_on_slot(struct kbase_device *kbdev, int js) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + mutex_lock(&js_devdata->runpool_mutex); + if (js_devdata->nr_user_contexts_running != 0) { + /* Only try running jobs when we have contexts present, otherwise the GPU might be powered off. */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + kbasep_js_try_run_next_job_on_slot_nolock(kbdev, js); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + } + mutex_unlock(&js_devdata->runpool_mutex); +} + +mali_error kbasep_js_devdata_init(struct kbase_device * const kbdev) +{ + struct kbasep_js_device_data *js_devdata; + mali_error err; + int i; + u16 as_present; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(js_devdata->init_status == JS_DEVDATA_INIT_NONE); + + /* These two must be recalculated if nr_hw_address_spaces changes (e.g. for HW workarounds) */ + as_present = (1U << kbdev->nr_hw_address_spaces) - 1; + kbdev->nr_user_address_spaces = kbdev->nr_hw_address_spaces; + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + mali_bool use_workaround_for_security; + + use_workaround_for_security = DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE; + if (use_workaround_for_security != MALI_FALSE) { + dev_dbg(kbdev->dev, "GPU has HW ISSUE 8987, and driver configured for security workaround: 1 address space only"); + kbdev->nr_user_address_spaces = 1; + } + } +#ifdef CONFIG_MALI_DEBUG + /* Soft-stop will be disabled on a single context by default unless softstop_always is set */ + js_devdata->softstop_always = MALI_FALSE; +#endif /* CONFIG_MALI_DEBUG */ + js_devdata->nr_all_contexts_running = 0; + js_devdata->nr_user_contexts_running = 0; + js_devdata->as_free = as_present; /* All ASs initially free */ + js_devdata->runpool_irq.submit_allowed = 0u; /* No ctx allowed to submit */ + memset(js_devdata->runpool_irq.ctx_attr_ref_count, 0, sizeof(js_devdata->runpool_irq.ctx_attr_ref_count)); + memset(js_devdata->runpool_irq.slot_affinities, 0, sizeof(js_devdata->runpool_irq.slot_affinities)); + js_devdata->runpool_irq.slots_blocked_on_affinity = 0u; + memset(js_devdata->runpool_irq.slot_affinity_refcount, 0, sizeof(js_devdata->runpool_irq.slot_affinity_refcount)); + INIT_LIST_HEAD(&js_devdata->suspended_soft_jobs_list); + + /* Config attributes */ + js_devdata->scheduling_tick_ns = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS); + js_devdata->soft_stop_ticks = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS); + js_devdata->soft_stop_ticks_cl = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL); + js_devdata->hard_stop_ticks_ss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS); + js_devdata->hard_stop_ticks_cl = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL); + js_devdata->hard_stop_ticks_nss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS); + js_devdata->gpu_reset_ticks_ss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS); + js_devdata->gpu_reset_ticks_cl = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL); + js_devdata->gpu_reset_ticks_nss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS); + js_devdata->ctx_timeslice_ns = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS); + js_devdata->cfs_ctx_runtime_init_slices = DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES; + js_devdata->cfs_ctx_runtime_min_slices = DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES; + + dev_dbg(kbdev->dev, "JS Config Attribs: "); + dev_dbg(kbdev->dev, "\tscheduling_tick_ns:%u", js_devdata->scheduling_tick_ns); + dev_dbg(kbdev->dev, "\tsoft_stop_ticks:%u", js_devdata->soft_stop_ticks); + dev_dbg(kbdev->dev, "\tsoft_stop_ticks_cl:%u", js_devdata->soft_stop_ticks_cl); + dev_dbg(kbdev->dev, "\thard_stop_ticks_ss:%u", js_devdata->hard_stop_ticks_ss); + dev_dbg(kbdev->dev, "\thard_stop_ticks_cl:%u", js_devdata->hard_stop_ticks_cl); + dev_dbg(kbdev->dev, "\thard_stop_ticks_nss:%u", js_devdata->hard_stop_ticks_nss); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_ss:%u", js_devdata->gpu_reset_ticks_ss); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_cl:%u", js_devdata->gpu_reset_ticks_cl); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_nss:%u", js_devdata->gpu_reset_ticks_nss); + dev_dbg(kbdev->dev, "\tctx_timeslice_ns:%u", js_devdata->ctx_timeslice_ns); + dev_dbg(kbdev->dev, "\tcfs_ctx_runtime_init_slices:%u", js_devdata->cfs_ctx_runtime_init_slices); + dev_dbg(kbdev->dev, "\tcfs_ctx_runtime_min_slices:%u", js_devdata->cfs_ctx_runtime_min_slices); + +#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS + dev_dbg(kbdev->dev, "Job Scheduling Policy Soft-stops disabled, ignoring value for soft_stop_ticks==%u at %uns per tick. Other soft-stops may still occur.", js_devdata->soft_stop_ticks, js_devdata->scheduling_tick_ns); +#endif +#if KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_dbg(kbdev->dev, "Job Scheduling Policy Hard-stops disabled, ignoring values for hard_stop_ticks_ss==%d and hard_stop_ticks_nss==%u at %uns per tick. Other hard-stops may still occur.", js_devdata->hard_stop_ticks_ss, js_devdata->hard_stop_ticks_nss, js_devdata->scheduling_tick_ns); +#endif +#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS && KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_dbg(kbdev->dev, "Note: The JS policy's tick timer (if coded) will still be run, but do nothing."); +#endif + + /* setup the number of irq throttle cycles base on given time */ + { + int irq_throttle_time_us = kbdev->gpu_props.irq_throttle_time_us; + int irq_throttle_cycles = kbasep_js_convert_us_to_gpu_ticks_max_freq(kbdev, irq_throttle_time_us); + + atomic_set(&kbdev->irq_throttle_cycles, irq_throttle_cycles); + } + + /* Clear the AS data, including setting NULL pointers */ + memset(&js_devdata->runpool_irq.per_as_data[0], 0, sizeof(js_devdata->runpool_irq.per_as_data)); + + for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) + js_devdata->js_reqs[i] = core_reqs_from_jsn_features(kbdev->gpu_props.props.raw_props.js_features[i]); + + js_devdata->init_status |= JS_DEVDATA_INIT_CONSTANTS; + + /* On error, we could continue on: providing none of the below resources + * rely on the ones above */ + + mutex_init(&js_devdata->runpool_mutex); + mutex_init(&js_devdata->queue_mutex); + mutex_init(&js_devdata->mtk_sj_mutex); + spin_lock_init(&js_devdata->runpool_irq.lock); + + err = kbasep_js_policy_init(kbdev); + if (err == MALI_ERROR_NONE) + js_devdata->init_status |= JS_DEVDATA_INIT_POLICY; + + /* On error, do no cleanup; this will be handled by the caller(s), since + * we've designed this resource to be safe to terminate on init-fail */ + if (js_devdata->init_status != JS_DEVDATA_INIT_ALL) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +void kbasep_js_devdata_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbasep_js_devdata_term(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + if ((js_devdata->init_status & JS_DEVDATA_INIT_CONSTANTS)) { + s8 zero_ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT] = { 0, }; + /* The caller must de-register all contexts before calling this */ + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running == 0); + KBASE_DEBUG_ASSERT(memcmp(js_devdata->runpool_irq.ctx_attr_ref_count, zero_ctx_attr_ref_count, sizeof(js_devdata->runpool_irq.ctx_attr_ref_count)) == 0); + CSTD_UNUSED(zero_ctx_attr_ref_count); + } + if ((js_devdata->init_status & JS_DEVDATA_INIT_POLICY)) + kbasep_js_policy_term(&js_devdata->policy); + + js_devdata->init_status = JS_DEVDATA_INIT_NONE; +} + +mali_error kbasep_js_kctx_init(struct kbase_context * const kctx) +{ + struct kbase_device *kbdev; + struct kbasep_js_kctx_info *js_kctx_info; + mali_error err; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_kctx_info = &kctx->jctx.sched_info; + KBASE_DEBUG_ASSERT(js_kctx_info->init_status == JS_KCTX_INIT_NONE); + + js_kctx_info->ctx.nr_jobs = 0; + js_kctx_info->ctx.is_scheduled = MALI_FALSE; + js_kctx_info->ctx.is_dying = MALI_FALSE; + memset(js_kctx_info->ctx.ctx_attr_ref_count, 0, sizeof(js_kctx_info->ctx.ctx_attr_ref_count)); + + /* Initially, the context is disabled from submission until the create flags are set */ + js_kctx_info->ctx.flags = KBASE_CTX_FLAG_SUBMIT_DISABLED; + + js_kctx_info->init_status |= JS_KCTX_INIT_CONSTANTS; + + /* On error, we could continue on: providing none of the below resources + * rely on the ones above */ + mutex_init(&js_kctx_info->ctx.jsctx_mutex); + + init_waitqueue_head(&js_kctx_info->ctx.is_scheduled_wait); + + err = kbasep_js_policy_init_ctx(kbdev, kctx); + if (err == MALI_ERROR_NONE) + js_kctx_info->init_status |= JS_KCTX_INIT_POLICY; + + /* On error, do no cleanup; this will be handled by the caller(s), since + * we've designed this resource to be safe to terminate on init-fail */ + if (js_kctx_info->init_status != JS_KCTX_INIT_ALL) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +void kbasep_js_kctx_term(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbasep_js_kctx_info *js_kctx_info; + union kbasep_js_policy *js_policy; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_policy = &kbdev->js_data.policy; + js_kctx_info = &kctx->jctx.sched_info; + + if ((js_kctx_info->init_status & JS_KCTX_INIT_CONSTANTS)) { + /* The caller must de-register all jobs before calling this */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs == 0); + } + + if ((js_kctx_info->init_status & JS_KCTX_INIT_POLICY)) + kbasep_js_policy_term_ctx(js_policy, kctx); + + js_kctx_info->init_status = JS_KCTX_INIT_NONE; +} + +/* Evict jobs from the NEXT registers + * + * The caller must hold: + * - kbasep_js_kctx_info::ctx::jsctx_mutex + * - kbasep_js_device_data::runpool_mutex + */ +STATIC void kbasep_js_runpool_evict_next_jobs(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + int js; + struct kbasep_js_device_data *js_devdata; + + js_devdata = &kbdev->js_data; + + BUG_ON(!mutex_is_locked(&kctx->jctx.sched_info.ctx.jsctx_mutex)); + BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex)); + + /* Prevent contexts in the runpool from submitting jobs */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* There's no need to prevent contexts in the runpool from submitting jobs, + * because we complete this operation by the time we release the + * runpool_irq.lock */ + + /* Evict jobs from the NEXT registers */ + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + struct kbase_jm_slot *slot; + struct kbase_jd_atom *tail; + + if (!kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), NULL)) { + /* No job in the NEXT register */ + continue; + } + + slot = &kbdev->jm_slots[js]; + tail = kbasep_jm_peek_idx_submit_slot(slot, slot->submitted_nr - 1); + + KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 1); + /* Clearing job from next registers */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_NOP, NULL); + + /* Check to see if we did remove a job from the next registers */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), NULL) != 0) { + /* The job was successfully cleared from the next registers, requeue it */ + struct kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot); + + KBASE_DEBUG_ASSERT(dequeued_katom == tail); + + /* Set the next registers to NULL */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), 0, NULL); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), 0, NULL); + + KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js); + + /* Complete the job, indicate that it took no time, and don't start + * new atoms */ + kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT); + } + KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 0); + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); +} + +/** + * Fast start a higher priority job + * If the runpool is full, the lower priority contexts with no running jobs + * will be evicted from the runpool + * + * If \a kctx_new is NULL, the first context with no running jobs will be evicted + * + * The following locking conditions are made on the caller: + * - The caller must \b not hold \a kctx_new's + * kbasep_js_kctx_info::ctx::jsctx_mutex, or that mutex of any ctx in the + * runpool. This is because \a kctx_new's jsctx_mutex and one of the other + * scheduled ctx's jsctx_mutex will be obtained internally. + * - it must \em not hold kbasep_js_device_data::runpool_irq::lock (as this will be + * obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used + * internally). + */ +STATIC void kbasep_js_runpool_attempt_fast_start_ctx(struct kbase_device *kbdev, struct kbase_context *kctx_new) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_new; + union kbasep_js_policy *js_policy; + struct kbasep_js_per_as_data *js_per_as_data; + int evict_as_nr; + struct kbasep_js_atom_retained_state katom_retained_state; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + + if (kctx_new != NULL) { + js_kctx_new = &kctx_new->jctx.sched_info; + mutex_lock(&js_kctx_new->ctx.jsctx_mutex); + } else { + js_kctx_new = NULL; + CSTD_UNUSED(js_kctx_new); + } + + /* Setup a dummy katom_retained_state */ + kbasep_js_atom_retained_state_init_invalid(&katom_retained_state); + + mutex_lock(&js_devdata->runpool_mutex); + + /* If the runpool is full and either there is no specified context or the specified context is not dying, then + attempt to fast start the specified context or evict the first context with no running jobs. */ + if (check_is_runpool_full(kbdev, kctx_new) && + (!js_kctx_new || (js_kctx_new && + !js_kctx_new->ctx.is_dying))) { + /* No free address spaces - attempt to evict non-running lower priority context */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + for (evict_as_nr = 0; evict_as_nr < kbdev->nr_hw_address_spaces; evict_as_nr++) { + struct kbase_context *kctx_evict; + + js_per_as_data = &js_devdata->runpool_irq.per_as_data[evict_as_nr]; + kctx_evict = js_per_as_data->kctx; + + /* Look for the AS which is not currently running */ + if (0 == js_per_as_data->as_busy_refcount && kctx_evict != NULL) { + /* Now compare the scheduled priority we are considering evicting with the new ctx priority + * and take into consideration if the scheduled priority is a realtime policy or not. + * Note that the lower the number, the higher the priority + */ + if ((kctx_new == NULL) || kbasep_js_policy_ctx_has_priority(js_policy, kctx_evict, kctx_new)) { + mali_bool retain_result; + kbasep_js_release_result release_result; + + KBASE_TRACE_ADD(kbdev, JS_FAST_START_EVICTS_CTX, kctx_evict, NULL, 0u, (uintptr_t)kctx_new); + + /* Retain the ctx to work on it - this shouldn't be able to fail */ + retain_result = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx_evict); + KBASE_DEBUG_ASSERT(retain_result != MALI_FALSE); + CSTD_UNUSED(retain_result); + + /* This will cause the context to be scheduled out on the next runpool_release_ctx(), + * and also stop its refcount increasing */ + kbasep_js_clear_submit_allowed(js_devdata, kctx_evict); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(&js_devdata->runpool_mutex); + if (kctx_new != NULL) + mutex_unlock(&js_kctx_new->ctx.jsctx_mutex); + + /* Stop working on the target context, start working on the kctx_evict context */ + + mutex_lock(&kctx_evict->jctx.sched_info.ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx_evict, &katom_retained_state); + mutex_unlock(&js_devdata->runpool_mutex); + /* Only requeue if actually descheduled, which is more robust in case + * something else retains it (e.g. two high priority contexts racing + * to evict the same lower priority context) */ + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx_evict, MALI_TRUE); + + mutex_unlock(&kctx_evict->jctx.sched_info.ctx.jsctx_mutex); + + /* release_result isn't propogated further: + * - the caller will be scheduling in a context anyway + * - which will also cause new jobs to run */ + + /* ctx fast start has taken place */ + return; + } + } + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + } + + /* ctx fast start has not taken place */ + mutex_unlock(&js_devdata->runpool_mutex); + if (kctx_new != NULL) + mutex_unlock(&js_kctx_new->ctx.jsctx_mutex); +} + +mali_bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom) +{ + unsigned long flags; + struct kbasep_js_kctx_info *js_kctx_info; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + union kbasep_js_policy *js_policy; + + mali_bool policy_queue_updated = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(atom != NULL); + lockdep_assert_held(&kctx->jctx.lock); + + kbdev = kctx->kbdev; + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TIMELINE_ATOM_READY(kctx, kbase_jd_atom_id(kctx, atom)); + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + /* Policy-specific initialization of atoms (which cannot fail). Anything that + * could've failed must've been done at kbasep_jd_policy_init_job() time. */ + kbasep_js_policy_register_job(js_policy, kctx, atom); + + /* + * Begin Runpool transaction + */ + mutex_lock(&js_devdata->runpool_mutex); + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_ADD_JOB, kctx, atom, atom->jc, kbasep_js_trace_get_refcnt(kbdev, kctx)); + + /* Refcount ctx.nr_jobs */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs < U32_MAX); + ++(js_kctx_info->ctx.nr_jobs); + + /* Setup any scheduling information */ + kbasep_js_clear_job_retry_submit(atom); + + /* Lock for state available during IRQ */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* Context Attribute Refcounting */ + kbasep_js_ctx_attr_ctx_retain_atom(kbdev, kctx, atom); + + /* Enqueue the job in the policy, causing it to be scheduled if the + * parent context gets scheduled */ + kbasep_js_policy_enqueue_job(js_policy, atom); + + if (js_kctx_info->ctx.is_scheduled != MALI_FALSE) { + /* Handle an already running context - try to run the new job, in case it + * matches requirements that aren't matched by any other job in the Run + * Pool */ + kbasep_js_try_run_next_job_nolock(kbdev); + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(&js_devdata->runpool_mutex); + /* End runpool transaction */ + + if (js_kctx_info->ctx.is_scheduled == MALI_FALSE) { + if (js_kctx_info->ctx.is_dying) { + /* A job got added while/after kbase_job_zap_context() was called + * on a non-scheduled context (e.g. KDS dependency resolved). Kill + * that job by killing the context. */ + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_FALSE); + } else if (js_kctx_info->ctx.nr_jobs == 1) { + /* Handle Refcount going from 0 to 1: schedule the context on the Policy Queue */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + dev_dbg(kbdev->dev, "JS: Enqueue Context %p", kctx); + + mutex_lock(&js_devdata->queue_mutex); + kbasep_js_policy_enqueue_ctx(js_policy, kctx); + mutex_unlock(&js_devdata->queue_mutex); + + /* Policy Queue was updated - caller must try to schedule the head context + * We also try to encourage a fast-start from here. */ + policy_queue_updated = MALI_TRUE; + } + } + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + /* If the runpool is full and this job has a higher priority than the + * non-running job in the runpool - evict it so this higher priority job + * starts faster. Fast-starting requires the jsctx_mutex to be dropped, + * because it works on multiple ctxs + * + * Note: If the context is being killed with kbase_job_zap_context(), then + * kctx can't disappear after the jsctx_mutex was dropped. This is because + * the caller holds kctx->jctx.lock */ + if (policy_queue_updated) + kbasep_js_runpool_attempt_fast_start_ctx(kbdev, kctx); + + return policy_queue_updated; +} + +void kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *atom) +{ + struct kbasep_js_kctx_info *js_kctx_info; + struct kbasep_js_device_data *js_devdata; + union kbasep_js_policy *js_policy; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(atom != NULL); + + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_REMOVE_JOB, kctx, atom, atom->jc, kbasep_js_trace_get_refcnt(kbdev, kctx)); + + /* De-refcount ctx.nr_jobs */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs > 0); + --(js_kctx_info->ctx.nr_jobs); + + /* De-register the job from the system */ + kbasep_js_policy_deregister_job(js_policy, kctx, atom); +} + +void kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + unsigned long flags; + struct kbasep_js_atom_retained_state katom_retained_state; + struct kbasep_js_device_data *js_devdata; + mali_bool attr_state_changed; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + js_devdata = &kbdev->js_data; + + kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); + kbasep_js_remove_job(kbdev, kctx, katom); + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* The atom has 'finished' (will not be re-run), so no need to call + * kbasep_js_has_atom_finished(). + * + * This is because it returns MALI_FALSE for soft-stopped atoms, but we + * want to override that, because we're cancelling an atom regardless of + * whether it was soft-stopped or not */ + attr_state_changed = kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, &katom_retained_state); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + if (attr_state_changed != MALI_FALSE) { + /* A change in runpool ctx attributes might mean we can run more jobs + * than before. */ + kbase_js_try_run_jobs(kbdev); + } +} + +mali_bool kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + mali_bool result; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + /* KBASE_TRACE_ADD_REFCOUNT( kbdev, JS_RETAIN_CTX, kctx, NULL, 0, + kbasep_js_trace_get_refcnt(kbdev, kctx)); */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + result = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return result; +} + +struct kbase_context *kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev, int as_nr) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbase_context *found_kctx = NULL; + struct kbasep_js_per_as_data *js_per_as_data; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS); + js_devdata = &kbdev->js_data; + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + found_kctx = js_per_as_data->kctx; + + if (found_kctx != NULL) + ++(js_per_as_data->as_busy_refcount); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return found_kctx; +} + +/** + * @brief Try running more jobs after releasing a context and/or atom + * + * This collates a set of actions that must happen whilst + * kbasep_js_device_data::runpool_irq::lock is held. + * + * This includes running more jobs when: + * - The previously released kctx caused a ctx attribute change + * - The released atom caused a ctx attribute change + * - Slots were previously blocked due to affinity restrictions + * - Submission during IRQ handling failed + */ +STATIC void kbasep_js_run_jobs_after_ctx_and_atom_release(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state, mali_bool runpool_ctx_attr_change) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom_retained_state != NULL); + js_devdata = &kbdev->js_data; + + lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex); + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + if (js_devdata->nr_user_contexts_running != 0) { + mali_bool retry_submit; + int retry_jobslot; + + retry_submit = kbasep_js_get_atom_retry_submit_slot(katom_retained_state, &retry_jobslot); + + if (runpool_ctx_attr_change != MALI_FALSE) { + /* A change in runpool ctx attributes might mean we can run more jobs + * than before */ + kbasep_js_try_run_next_job_nolock(kbdev); + + /* A retry submit on all slots has now happened, so don't need to do it again */ + retry_submit = MALI_FALSE; + } + + /* Submit on any slots that might've had atoms blocked by the affinity of + * a completed atom. + * + * If no atom has recently completed, then this is harmelss */ + kbase_js_affinity_submit_to_blocked_slots(kbdev); + + /* If the IRQ handler failed to get a job from the policy, try again from + * outside the IRQ handler + * NOTE: We may've already cleared retry_submit from submitting above */ + if (retry_submit != MALI_FALSE) { + KBASE_TRACE_ADD_SLOT(kbdev, JD_DONE_TRY_RUN_NEXT_JOB, kctx, NULL, 0u, retry_jobslot); + kbasep_js_try_run_next_job_on_slot_nolock(kbdev, retry_jobslot); + } + } +} + +/** + * Internal function to release the reference on a ctx and an atom's "retained + * state", only taking the runpool and as transaction mutexes + * + * This also starts more jobs running in the case of an ctx-attribute state change + * + * This does none of the followup actions for scheduling: + * - It does not schedule in a new context + * - It does not requeue or handle dying contexts + * + * For those tasks, just call kbasep_js_runpool_release_ctx() instead + * + * Requires: + * - Context is scheduled in, and kctx->as_nr matches kctx_as_nr + * - Context has a non-zero refcount + * - Caller holds js_kctx_info->ctx.jsctx_mutex + * - Caller holds js_devdata->runpool_mutex + */ +STATIC kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + union kbasep_js_policy *js_policy; + struct kbasep_js_per_as_data *js_per_as_data; + + kbasep_js_release_result release_result = 0u; + mali_bool runpool_ctx_attr_change = MALI_FALSE; + int kctx_as_nr; + struct kbase_as *current_as; + int new_ref_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE); + + /* kctx->as_nr and js_per_as_data are only read from here. The caller's + * js_ctx_mutex provides a barrier that ensures they are up-to-date. + * + * They will not change whilst we're reading them, because the refcount + * is non-zero (and we ASSERT on that last fact). + */ + kctx_as_nr = kctx->as_nr; + KBASE_DEBUG_ASSERT(kctx_as_nr != KBASEP_AS_NR_INVALID); + js_per_as_data = &js_devdata->runpool_irq.per_as_data[kctx_as_nr]; + KBASE_DEBUG_ASSERT(js_per_as_data->as_busy_refcount > 0); + + /* + * Transaction begins on AS and runpool_irq + * + * Assert about out calling contract + */ + current_as = &kbdev->as[kctx_as_nr]; + mutex_lock(¤t_as->transaction_mutex); + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + KBASE_DEBUG_ASSERT(kctx_as_nr == kctx->as_nr); + KBASE_DEBUG_ASSERT(js_per_as_data->as_busy_refcount > 0); + + /* Update refcount */ + new_ref_count = --(js_per_as_data->as_busy_refcount); + + /* Release the atom if it finished (i.e. wasn't soft-stopped) */ + if (kbasep_js_has_atom_finished(katom_retained_state) != MALI_FALSE) + runpool_ctx_attr_change |= kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, katom_retained_state); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RELEASE_CTX, kctx, NULL, 0u, new_ref_count); + + if (new_ref_count == 1 && kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED && + !kbase_pm_is_suspending(kbdev)) { + /* Context is kept scheduled into an address space even when there are no jobs, in this case we have + * to handle the situation where all jobs have been evicted from the GPU and submission is disabled. + * + * At this point we re-enable submission to allow further jobs to be executed + */ + kbasep_js_set_submit_allowed(js_devdata, kctx); + } + + /* Make a set of checks to see if the context should be scheduled out */ + if (new_ref_count == 0 && (kctx->jctx.sched_info.ctx.nr_jobs == 0 || kbasep_js_is_submit_allowed(js_devdata, kctx) == MALI_FALSE)) { + /* Last reference, and we've been told to remove this context from the Run Pool */ + dev_dbg(kbdev->dev, "JS: RunPool Remove Context %p because as_busy_refcount=%d, jobs=%d, allowed=%d", kctx, new_ref_count, js_kctx_info->ctx.nr_jobs, kbasep_js_is_submit_allowed(js_devdata, kctx)); + + kbasep_js_policy_runpool_remove_ctx(js_policy, kctx); + + /* Stop any more refcounts occuring on the context */ + js_per_as_data->kctx = NULL; + + /* Ensure we prevent the context from submitting any new jobs + * e.g. from kbasep_js_try_run_next_job_on_slot_irq_nolock() */ + kbasep_js_clear_submit_allowed(js_devdata, kctx); + + /* Disable the MMU on the affected address space, and indicate it's invalid */ + kbase_mmu_disable(kctx); + +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_mmu_as_released(kctx->as_nr); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + + kctx->as_nr = KBASEP_AS_NR_INVALID; + + /* Ctx Attribute handling + * + * Releasing atoms attributes must either happen before this, or after + * 'is_scheduled' is changed, otherwise we double-decount the attributes*/ + runpool_ctx_attr_change |= kbasep_js_ctx_attr_runpool_release_ctx(kbdev, kctx); + + /* Early update of context count, to optimize the + * kbasep_js_run_jobs_after_ctx_and_atom_release() call */ + runpool_dec_context_count(kbdev, kctx); + + /* Releasing the context and katom retained state can allow more jobs to run */ + kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx, katom_retained_state, runpool_ctx_attr_change); + + /* + * Transaction ends on AS and runpool_irq: + * + * By this point, the AS-related data is now clear and ready for re-use. + * + * Since releases only occur once for each previous successful retain, and no more + * retains are allowed on this context, no other thread will be operating in this + * code whilst we are + */ + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(¤t_as->transaction_mutex); + + /* Free up the address space */ + release_addr_space(kbdev, kctx_as_nr); + /* Note: Don't reuse kctx_as_nr now */ + + /* Synchronize with any policy timers */ + kbasep_js_policy_runpool_timers_sync(js_policy); + + /* update book-keeping info */ + js_kctx_info->ctx.is_scheduled = MALI_FALSE; + /* Signal any waiter that the context is not scheduled, so is safe for + * termination - once the jsctx_mutex is also dropped, and jobs have + * finished. */ + wake_up(&js_kctx_info->ctx.is_scheduled_wait); + + /* Queue an action to occur after we've dropped the lock */ + release_result |= KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED; + + } else { + kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx, katom_retained_state, runpool_ctx_attr_change); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(¤t_as->transaction_mutex); + } + + return release_result; +} + +void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, mali_bool has_pm_ref) +{ + struct kbasep_js_device_data *js_devdata; + union kbasep_js_policy *js_policy; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_policy = &kbdev->js_data.policy; + js_devdata = &kbdev->js_data; + + /* This is called if and only if you've you've detached the context from + * the Runpool or the Policy Queue, and not added it back to the Runpool */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + + if (js_kctx_info->ctx.is_dying != MALI_FALSE) { + /* Dying: don't requeue, but kill all jobs on the context. This happens + * asynchronously */ + dev_dbg(kbdev->dev, "JS: ** Killing Context %p on RunPool Remove **", kctx); + kbasep_js_policy_foreach_ctx_job(js_policy, kctx, &kbase_jd_cancel, MALI_TRUE); + } else if (js_kctx_info->ctx.nr_jobs > 0) { + /* Not dying, has jobs: de-ref core counts from each job before addding + * back to the queue */ + kbasep_js_policy_foreach_ctx_job(js_policy, kctx, &kbasep_js_job_check_deref_cores, MALI_FALSE); + + dev_dbg(kbdev->dev, "JS: Requeue Context %p", kctx); + mutex_lock(&js_devdata->queue_mutex); + kbasep_js_policy_enqueue_ctx(js_policy, kctx); + mutex_unlock(&js_devdata->queue_mutex); + } else { + /* Not dying, no jobs: don't add back to the queue */ + dev_dbg(kbdev->dev, "JS: Idling Context %p (not requeued)", kctx); + } + + if (has_pm_ref) { + /* In all cases where we had a pm active refcount, release it */ + kbase_pm_context_idle(kbdev); + } +} + +void kbasep_js_runpool_release_ctx_and_katom_retained_state(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + kbasep_js_release_result release_result; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, katom_retained_state); + + /* Drop the runpool mutex to allow requeing kctx */ + mutex_unlock(&js_devdata->runpool_mutex); + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_TRUE); + + /* Drop the jsctx_mutex to allow scheduling in a new context */ + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) { + /* We've freed up an address space, so let's try to schedule in another + * context + * + * Note: if there's a context to schedule in, then it also tries to run + * another job, in case the new context has jobs satisfying requirements + * that no other context/job in the runpool does */ + kbasep_js_try_schedule_head_ctx(kbdev); + } +} + +void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_atom_retained_state katom_retained_state; + + kbasep_js_atom_retained_state_init_invalid(&katom_retained_state); + + kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state); +} + +/** Variant of kbasep_js_runpool_release_ctx() that doesn't call into + * kbasep_js_try_schedule_head_ctx() */ +STATIC void kbasep_js_runpool_release_ctx_no_schedule(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + kbasep_js_release_result release_result; + struct kbasep_js_atom_retained_state katom_retained_state_struct; + struct kbasep_js_atom_retained_state *katom_retained_state = &katom_retained_state_struct; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + kbasep_js_atom_retained_state_init_invalid(katom_retained_state); + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, katom_retained_state); + + /* Drop the runpool mutex to allow requeing kctx */ + mutex_unlock(&js_devdata->runpool_mutex); + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_TRUE); + + /* Drop the jsctx_mutex to allow scheduling in a new context */ + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + /* NOTE: could return release_result if the caller would like to know + * whether it should schedule a new context, but currently no callers do */ +} + + +/** + * @brief Handle retaining cores for power management and affinity management, + * ensuring that cores are powered up and won't violate affinity restrictions. + * + * This function enters at the following @ref enum kbase_atom_coreref_state states: + * + * - NO_CORES_REQUESTED, + * - WAITING_FOR_REQUESTED_CORES, + * - RECHECK_AFFINITY, + * + * The transitions are as folows: + * - NO_CORES_REQUESTED -> WAITING_FOR_REQUESTED_CORES + * - WAITING_FOR_REQUESTED_CORES -> ( WAITING_FOR_REQUESTED_CORES or RECHECK_AFFINITY ) + * - RECHECK_AFFINITY -> ( WAITING_FOR_REQUESTED_CORES or CHECK_AFFINITY_VIOLATIONS ) + * - CHECK_AFFINITY_VIOLATIONS -> ( RECHECK_AFFINITY or READY ) + * + * The caller must hold: + * - kbasep_js_device_data::runpool_irq::lock + * + * @return MALI_FALSE when the function makes a transition to the same or lower state, indicating + * that the cores are not ready. + * @return MALI_TRUE once READY state is reached, indicating that the cores are 'ready' and won't + * violate affinity restrictions. + * + */ +STATIC mali_bool kbasep_js_job_check_ref_cores(struct kbase_device *kbdev, int js, struct kbase_jd_atom *katom) +{ + /* The most recently checked affinity. Having this at this scope allows us + * to guarantee that we've checked the affinity in this function call. */ + u64 recently_chosen_affinity = 0; + mali_bool chosen_affinity = MALI_FALSE; + mali_bool retry; + + do { + retry = MALI_FALSE; + + /* NOTE: The following uses a number of FALLTHROUGHs to optimize the + * calls to this function. Ending of the function is indicated by BREAK OUT */ + switch (katom->coreref_state) { + /* State when job is first attempted to be run */ + case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED: + KBASE_DEBUG_ASSERT(katom->affinity == 0); + + /* Compute affinity */ + if (MALI_FALSE == kbase_js_choose_affinity(&recently_chosen_affinity, kbdev, katom, js)) { + /* No cores are currently available */ + /* *** BREAK OUT: No state transition *** */ + break; + } + + chosen_affinity = MALI_TRUE; + + /* Request the cores */ + kbase_pm_request_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity); + + katom->affinity = recently_chosen_affinity; + + /* Proceed to next state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES: + { + enum kbase_pm_cores_ready cores_ready; + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + + cores_ready = kbase_pm_register_inuse_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity); + if (cores_ready == KBASE_NEW_AFFINITY) { + /* Affinity no longer valid - return to previous state */ + kbasep_js_job_check_deref_cores(kbdev, katom); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + /* *** BREAK OUT: Return to previous state, retry *** */ + retry = MALI_TRUE; + break; + } + if (cores_ready == KBASE_CORES_NOT_READY) { + /* Stay in this state and return, to retry at this state later */ + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + /* *** BREAK OUT: No state transition *** */ + break; + } + /* Proceed to next state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + } + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY: + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + + /* Optimize out choosing the affinity twice in the same function call */ + if (chosen_affinity == MALI_FALSE) { + /* See if the affinity changed since a previous call. */ + if (MALI_FALSE == kbase_js_choose_affinity(&recently_chosen_affinity, kbdev, katom, js)) { + /* No cores are currently available */ + kbasep_js_job_check_deref_cores(kbdev, katom); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REQUEST_ON_RECHECK_FAILED, katom->kctx, katom, katom->jc, js, (u32) recently_chosen_affinity); + /* *** BREAK OUT: Transition to lower state *** */ + break; + } + chosen_affinity = MALI_TRUE; + } + + /* Now see if this requires a different set of cores */ + if (recently_chosen_affinity != katom->affinity) { + enum kbase_pm_cores_ready cores_ready; + + kbase_pm_request_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity); + + /* Register new cores whilst we still hold the old ones, to minimize power transitions */ + cores_ready = kbase_pm_register_inuse_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity); + kbasep_js_job_check_deref_cores(kbdev, katom); + + /* Fixup the state that was reduced by deref_cores: */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + katom->affinity = recently_chosen_affinity; + if (cores_ready == KBASE_NEW_AFFINITY) { + /* Affinity no longer valid - return to previous state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + kbasep_js_job_check_deref_cores(kbdev, katom); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + /* *** BREAK OUT: Return to previous state, retry *** */ + retry = MALI_TRUE; + break; + } + /* Now might be waiting for powerup again, with a new affinity */ + if (cores_ready == KBASE_CORES_NOT_READY) { + /* Return to previous state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_ON_RECHECK_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + /* *** BREAK OUT: Transition to lower state *** */ + break; + } + } + /* Proceed to next state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + case KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS: + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + KBASE_DEBUG_ASSERT(katom->affinity == recently_chosen_affinity); + + /* Note: this is where the caller must've taken the runpool_irq.lock */ + + /* Check for affinity violations - if there are any, then we just ask + * the caller to requeue and try again later */ + if (kbase_js_affinity_would_violate(kbdev, js, katom->affinity) != MALI_FALSE) { + /* Cause a re-attempt to submit from this slot on the next job complete */ + kbase_js_affinity_slot_blocked_an_atom(kbdev, js); + /* Return to previous state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + /* *** BREAK OUT: Transition to lower state *** */ + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_AFFINITY_WOULD_VIOLATE, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + break; + } + + /* No affinity violations would result, so the cores are ready */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_READY; + /* *** BREAK OUT: Cores Ready *** */ + break; + + default: + KBASE_DEBUG_ASSERT_MSG(MALI_FALSE, "Unhandled kbase_atom_coreref_state %d", katom->coreref_state); + break; + } + } while (retry != MALI_FALSE); + + return (katom->coreref_state == KBASE_ATOM_COREREF_STATE_READY); +} + +void kbasep_js_job_check_deref_cores(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + switch (katom->coreref_state) { + case KBASE_ATOM_COREREF_STATE_READY: + /* State where atom was submitted to the HW - just proceed to power-down */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + + /* *** FALLTHROUGH *** */ + + case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY: + /* State where cores were registered */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + kbase_pm_release_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity); + + /* Note: We do not clear the state for kbase_js_affinity_slot_blocked_an_atom(). + * That is handled after finishing the job. This might be slightly + * suboptimal for some corner cases, but is otherwise not a problem + * (and resolves itself after the next job completes). */ + + break; + + case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES: + /* State where cores were requested, but not registered */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + kbase_pm_unrequest_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity); + break; + + case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED: + /* Initial state - nothing required */ + KBASE_DEBUG_ASSERT(katom->affinity == 0); + break; + + default: + KBASE_DEBUG_ASSERT_MSG(MALI_FALSE, "Unhandled coreref_state: %d", katom->coreref_state); + break; + } + + katom->affinity = 0; + katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED; +} + +/* + * Note: this function is quite similar to kbasep_js_try_run_next_job_on_slot() + */ +mali_bool kbasep_js_try_run_next_job_on_slot_irq_nolock(struct kbase_device *kbdev, int js, s8 *submit_count) +{ + struct kbasep_js_device_data *js_devdata; + mali_bool cores_ready; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + /* The caller of this function may not be aware of Ctx Attribute state changes so we + * must recheck if the given slot is still valid. Otherwise do not try to run. + */ + if (kbase_js_can_run_job_on_slot_no_lock(kbdev, js)) { + /* Keep submitting while there's space to run a job on this job-slot, + * and there are jobs to get that match its requirements (see 'break' + * statement below) */ + while (*submit_count < KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ && kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE) { + struct kbase_jd_atom *dequeued_atom; + mali_bool has_job = MALI_FALSE; + + /* Dequeue a job that matches the requirements */ + has_job = kbasep_js_policy_dequeue_job(kbdev, js, &dequeued_atom); + + if (has_job != MALI_FALSE) { + /* NOTE: since the runpool_irq lock is currently held and acts across + * all address spaces, any context whose busy refcount has reached + * zero won't yet be scheduled out whilst we're trying to run jobs + * from it */ + struct kbase_context *parent_ctx = dequeued_atom->kctx; + mali_bool retain_success; + + /* Retain/power up the cores it needs, check if cores are ready */ + cores_ready = kbasep_js_job_check_ref_cores(kbdev, js, dequeued_atom); + + if (dequeued_atom->event_code == BASE_JD_EVENT_PM_EVENT || cores_ready != MALI_TRUE) { + /* The job either can't be submitted until the cores are ready, or + * the job will fail due to the specified core group being unavailable. + * To avoid recursion this will be handled outside of IRQ content by + * kbasep_js_try_run_next_job_on_slot_nolock */ + kbasep_js_policy_enqueue_job(&kbdev->js_data.policy, dequeued_atom); + return MALI_TRUE; + } + + /* ASSERT that the Policy picked a job from an allowed context */ + KBASE_DEBUG_ASSERT(kbasep_js_is_submit_allowed(js_devdata, parent_ctx)); + + /* Retain the context to stop it from being scheduled out + * This is released when the job finishes */ + retain_success = kbasep_js_runpool_retain_ctx_nolock(kbdev, parent_ctx); + KBASE_DEBUG_ASSERT(retain_success != MALI_FALSE); + CSTD_UNUSED(retain_success); + + /* Retain the affinity on the slot */ + kbase_js_affinity_retain_slot_cores(kbdev, js, dequeued_atom->affinity); + + /* Check if this job needs the cycle counter enabled before submission */ + kbasep_js_ref_permon_check_and_enable_cycle_counter(kbdev, dequeued_atom); + + /* Submit the job */ + kbase_job_submit_nolock(kbdev, dequeued_atom, js); + + ++(*submit_count); + } else { + /* No more jobs - stop submitting for this slot */ + break; + } + } + } + + /* Indicate whether a retry in submission should be tried on a different + * dequeue function. These are the reasons why it *must* happen: + * - the KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ threshold was reached + * and new scheduling must be performed outside of IRQ mode. + * + * Failure to indicate this correctly could stop further jobs being processed. + * + * However, we do not _need_ to indicate a retry for the following: + * - kbasep_js_policy_dequeue_job() couldn't get a job. In which case, + * there's no point re-trying outside of IRQ, because the result will be + * the same until job dependencies are resolved, or user-space provides + * more jobs. In both those cases, we try to run jobs anyway, so + * processing does not stop. + * - kbasep_jm_is_submit_slots_free() was MALI_FALSE, indicating jobs were + * already running. When those jobs complete, that will still cause events + * that cause us to resume job submission. + * - kbase_js_can_run_job_on_slot_no_lock() was MALI_FALSE - this is for + * Ctx Attribute handling. That _can_ change outside of IRQ context, but + * is handled explicitly by kbasep_js_runpool_release_ctx_and_katom_retained_state(). + */ + return (mali_bool) (*submit_count >= KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ); +} + +void kbasep_js_try_run_next_job_on_slot_nolock(struct kbase_device *kbdev, int js) +{ + struct kbasep_js_device_data *js_devdata; + mali_bool has_job; + mali_bool cores_ready; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running > 0); + + /* Keep submitting while there's space to run a job on this job-slot, + * and there are jobs to get that match its requirements (see 'break' + * statement below) */ + if (kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE) { + /* The caller of this function may not be aware of Ctx Attribute state changes so we + * must recheck if the given slot is still valid. Otherwise do not try to run. + */ + if (kbase_js_can_run_job_on_slot_no_lock(kbdev, js)) { + do { + struct kbase_jd_atom *dequeued_atom; + + /* Dequeue a job that matches the requirements */ + has_job = kbasep_js_policy_dequeue_job(kbdev, js, &dequeued_atom); + + if (has_job != MALI_FALSE) { + /* NOTE: since the runpool_irq lock is currently held and acts across + * all address spaces, any context whose busy refcount has reached + * zero won't yet be scheduled out whilst we're trying to run jobs + * from it */ + struct kbase_context *parent_ctx = dequeued_atom->kctx; + mali_bool retain_success; + + /* Retain/power up the cores it needs, check if cores are ready */ + cores_ready = kbasep_js_job_check_ref_cores(kbdev, js, dequeued_atom); + + if (cores_ready != MALI_TRUE && dequeued_atom->event_code != BASE_JD_EVENT_PM_EVENT) { + /* The job can't be submitted until the cores are ready, requeue the job */ + kbasep_js_policy_enqueue_job(&kbdev->js_data.policy, dequeued_atom); + break; + } + /* ASSERT that the Policy picked a job from an allowed context */ + KBASE_DEBUG_ASSERT(kbasep_js_is_submit_allowed(js_devdata, parent_ctx)); + + /* Retain the context to stop it from being scheduled out + * This is released when the job finishes */ + retain_success = kbasep_js_runpool_retain_ctx_nolock(kbdev, parent_ctx); + KBASE_DEBUG_ASSERT(retain_success != MALI_FALSE); + CSTD_UNUSED(retain_success); + + /* Retain the affinity on the slot */ + kbase_js_affinity_retain_slot_cores(kbdev, js, dequeued_atom->affinity); + + /* Check if this job needs the cycle counter enabled before submission */ + kbasep_js_ref_permon_check_and_enable_cycle_counter(kbdev, dequeued_atom); + + if (dequeued_atom->event_code == BASE_JD_EVENT_PM_EVENT) { + dev_warn(kbdev->dev, "Rejecting atom due to BASE_JD_EVENT_PM_EVENT\n"); + /* The job has failed due to the specified core group being unavailable */ + kbase_jd_done(dequeued_atom, js, NULL, 0); + } else { + /* Submit the job */ + kbase_job_submit_nolock(kbdev, dequeued_atom, js); + } + } + + } while (kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE && has_job != MALI_FALSE); + } + } +} + +void kbasep_js_try_schedule_head_ctx(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + mali_bool has_kctx; + struct kbase_context *head_kctx; + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool is_runpool_full; + struct kbase_as *new_address_space; + unsigned long flags; + mali_bool head_kctx_suspended = MALI_FALSE; + int pm_active_err; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + /* We *don't* make a speculative check on whether we can fit a context in the + * runpool, because most of our use-cases assume 2 or fewer contexts, and + * so we will usually have enough address spaces free. + * + * In any case, the check will be done later on once we have a context */ + + /* Grab the context off head of queue - if there is one */ + mutex_lock(&js_devdata->queue_mutex); + has_kctx = kbasep_js_policy_dequeue_head_ctx(&js_devdata->policy, &head_kctx); + mutex_unlock(&js_devdata->queue_mutex); + + if (has_kctx == MALI_FALSE) { + /* No ctxs to run - nothing to do */ + return; + } + js_kctx_info = &head_kctx->jctx.sched_info; + + dev_dbg(kbdev->dev, "JS: Dequeue Context %p", head_kctx); + + pm_active_err = kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE); + + /* + * Atomic transaction on the Context and Run Pool begins + */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + + /* Check to see if we shouldn't add the context to run Run Pool: + * - it can't take the specified context, and so is 'full'. This may be + * 'full' even when there are addres spaces available, since some contexts + * are allowed in whereas others may not due to HW workarounds + * - A suspend is taking place + * - The context is dying due to kbase_job_zap_context() */ + is_runpool_full = check_is_runpool_full(kbdev, head_kctx); + if (is_runpool_full || pm_active_err || js_kctx_info->ctx.is_dying) { + /* Roll back the transaction so far and return */ + mutex_unlock(&js_devdata->runpool_mutex); + + /* Note: If a Power Management active reference was taken, it's released by + * this: */ + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, head_kctx, !pm_active_err); + + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + return; + } + + /* From the point on, the Power Management active reference is released + * only if kbasep_js_runpool_release_ctx() causes the context to be removed + * from the runpool */ + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_TRY_SCHEDULE_HEAD_CTX, head_kctx, NULL, 0u, kbasep_js_trace_get_refcnt(kbdev, head_kctx)); + +#if !MALI_CUSTOMER_RELEASE + if (js_devdata->nr_user_contexts_running == 0) { + /* Only when there are no other contexts submitting jobs: + * Latch in run-time job scheduler timeouts that were set through js_timeouts sysfs file */ + if (kbdev->js_soft_stop_ticks != 0) + js_devdata->soft_stop_ticks = kbdev->js_soft_stop_ticks; + + if (kbdev->js_soft_stop_ticks_cl != 0) + js_devdata->soft_stop_ticks_cl = kbdev->js_soft_stop_ticks_cl; + + if (kbdev->js_hard_stop_ticks_ss != 0) + js_devdata->hard_stop_ticks_ss = kbdev->js_hard_stop_ticks_ss; + + if (kbdev->js_hard_stop_ticks_cl != 0) + js_devdata->hard_stop_ticks_cl = kbdev->js_hard_stop_ticks_cl; + + if (kbdev->js_hard_stop_ticks_nss != 0) + js_devdata->hard_stop_ticks_nss = kbdev->js_hard_stop_ticks_nss; + + if (kbdev->js_reset_ticks_ss != 0) + js_devdata->gpu_reset_ticks_ss = kbdev->js_reset_ticks_ss; + + if (kbdev->js_reset_ticks_cl != 0) + js_devdata->gpu_reset_ticks_cl = kbdev->js_reset_ticks_cl; + + if (kbdev->js_reset_ticks_nss != 0) + js_devdata->gpu_reset_ticks_nss = kbdev->js_reset_ticks_nss; + } +#endif + + runpool_inc_context_count(kbdev, head_kctx); + /* Cause any future waiter-on-termination to wait until the context is + * descheduled */ + js_kctx_info->ctx.is_scheduled = MALI_TRUE; + wake_up(&js_kctx_info->ctx.is_scheduled_wait); + + /* Pick the free address space (guaranteed free by check_is_runpool_full() ) */ + new_address_space = pick_free_addr_space(kbdev); + + /* Lock the address space whilst working on it */ + mutex_lock(&new_address_space->transaction_mutex); + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* Do all the necessaries to assign the address space (inc. update book-keeping info) + * Add the context to the Run Pool, and allow it to run jobs */ + assign_and_activate_kctx_addr_space(kbdev, head_kctx, new_address_space); + + /* NOTE: If Linux allows, then we can drop the new_address_space->transaction mutex here */ + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) != 0) { + /* We need to retain it to keep the corresponding address space */ + kbasep_js_runpool_retain_ctx_nolock(kbdev, head_kctx); + } + + /* Re-check for suspending: a suspend could've occurred after we + * pm_context_active'd, and all the contexts could've been removed from the + * runpool before we took this lock. In this case, we don't want to allow + * this context to run jobs, we just want it out immediately. + * + * The DMB required to read the suspend flag was issued recently as part of + * the runpool_irq locking. If a suspend occurs *after* that lock was taken + * (i.e. this condition doesn't execute), then the kbasep_js_suspend() code + * will cleanup this context instead (by virtue of it being called strictly + * after the suspend flag is set, and will wait for this lock to drop) */ + if (kbase_pm_is_suspending(kbdev)) { + /* Cause it to leave at some later point */ + mali_bool retained; + + retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, head_kctx); + KBASE_DEBUG_ASSERT(retained); + kbasep_js_clear_submit_allowed(js_devdata, head_kctx); + head_kctx_suspended = MALI_TRUE; + } + + /* Try to run the next job, in case this context has jobs that match the + * job slot requirements, but none of the other currently running contexts + * do */ + kbasep_js_try_run_next_job_nolock(kbdev); + + /* Transaction complete */ + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(&new_address_space->transaction_mutex); + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + /* Note: after this point, the context could potentially get scheduled out immediately */ + + if (head_kctx_suspended) { + /* Finishing forcing out the context due to a suspend. Use a variant of + * kbasep_js_runpool_release_ctx() that doesn't schedule a new context, + * to prevent a risk of recursion back into this function */ + kbasep_js_runpool_release_ctx_no_schedule(kbdev, head_kctx); + } +} + +void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_kctx_info *js_kctx_info; + struct kbasep_js_device_data *js_devdata; + mali_bool is_scheduled; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + /* This must never be attempted whilst suspending - i.e. it should only + * happen in response to a syscall from a user-space thread */ + BUG_ON(kbase_pm_is_suspending(kbdev)); + + kbase_pm_request_l2_caches(kbdev); + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + /* Mark the context as privileged */ + js_kctx_info->ctx.flags |= KBASE_CTX_FLAG_PRIVILEGED; + + is_scheduled = js_kctx_info->ctx.is_scheduled; + if (is_scheduled == MALI_FALSE) { + mali_bool is_runpool_full; + + /* Add the context to the runpool */ + mutex_lock(&js_devdata->queue_mutex); + kbasep_js_policy_enqueue_ctx(&js_devdata->policy, kctx); + mutex_unlock(&js_devdata->queue_mutex); + + mutex_lock(&js_devdata->runpool_mutex); + { + is_runpool_full = check_is_runpool_full(kbdev, kctx); + if (is_runpool_full != MALI_FALSE) { + /* Evict jobs from the NEXT registers to free an AS asap */ + kbasep_js_runpool_evict_next_jobs(kbdev, kctx); + } + } + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + /* Fast-starting requires the jsctx_mutex to be dropped, because it works on multiple ctxs */ + + if (is_runpool_full != MALI_FALSE) { + /* Evict non-running contexts from the runpool */ + kbasep_js_runpool_attempt_fast_start_ctx(kbdev, NULL); + } + /* Try to schedule the context in */ + kbasep_js_try_schedule_head_ctx(kbdev); + + /* Wait for the context to be scheduled in */ + wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, kctx->jctx.sched_info.ctx.is_scheduled == MALI_TRUE); + } else { + /* Already scheduled in - We need to retain it to keep the corresponding address space */ + kbasep_js_runpool_retain_ctx(kbdev, kctx); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + } +} + +void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + + /* We don't need to use the address space anymore */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + js_kctx_info->ctx.flags &= (~KBASE_CTX_FLAG_PRIVILEGED); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + kbase_pm_release_l2_caches(kbdev); + + /* Release the context - it will be scheduled out if there is no pending job */ + kbasep_js_runpool_release_ctx(kbdev, kctx); +} + +void kbasep_js_job_done_slot_irq(struct kbase_jd_atom *katom, int slot_nr, + ktime_t *end_timestamp, kbasep_js_atom_done_code done_code) +{ + struct kbase_device *kbdev; + union kbasep_js_policy *js_policy; + struct kbasep_js_device_data *js_devdata; + mali_bool submit_retry_needed = MALI_TRUE; /* If we don't start jobs here, start them from the workqueue */ + ktime_t tick_diff; + u64 microseconds_spent = 0u; + struct kbase_context *parent_ctx; + + KBASE_DEBUG_ASSERT(katom); + parent_ctx = katom->kctx; + KBASE_DEBUG_ASSERT(parent_ctx); + kbdev = parent_ctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev); + + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + /* + * Release resources before submitting new jobs (bounds the refcount of + * the resource to BASE_JM_SUBMIT_SLOTS) + */ +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_STOP, slot_nr), NULL, 0); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + + /* Check if submitted jobs no longer require the cycle counter to be enabled */ + kbasep_js_deref_permon_check_and_disable_cycle_counter(kbdev, katom); + + /* Release the affinity from the slot - must happen before next submission to this slot */ + kbase_js_affinity_release_slot_cores(kbdev, slot_nr, katom->affinity); + kbase_js_debug_log_current_affinities(kbdev); + /* Calculate the job's time used */ + if (end_timestamp != NULL) { + /* Only calculating it for jobs that really run on the HW (e.g. removed + * from next jobs never actually ran, so really did take zero time) */ + tick_diff = ktime_sub(*end_timestamp, katom->start_timestamp); + + microseconds_spent = ktime_to_ns(tick_diff); + do_div(microseconds_spent, 1000); + + /* Round up time spent to the minimum timer resolution */ + if (microseconds_spent < KBASEP_JS_TICK_RESOLUTION_US) + microseconds_spent = KBASEP_JS_TICK_RESOLUTION_US; + } + + /* Log the result of the job (completion status, and time spent). */ + kbasep_js_policy_log_job_result(js_policy, katom, microseconds_spent); + /* Determine whether the parent context's timeslice is up */ + if (kbasep_js_policy_should_remove_ctx(js_policy, parent_ctx) != MALI_FALSE) + kbasep_js_clear_submit_allowed(js_devdata, parent_ctx); + + if (done_code & KBASE_JS_ATOM_DONE_START_NEW_ATOMS) { + /* Submit a new job (if there is one) to help keep the GPU's HEAD and NEXT registers full */ + KBASE_TRACE_ADD_SLOT(kbdev, JS_JOB_DONE_TRY_RUN_NEXT_JOB, parent_ctx, katom, katom->jc, slot_nr); + + submit_retry_needed = kbasep_js_try_run_next_job_on_slot_irq_nolock(kbdev, slot_nr, &kbdev->slot_submit_count_irq[slot_nr]); + } + + if (submit_retry_needed != MALI_FALSE || katom->event_code == BASE_JD_EVENT_STOPPED) { + /* The extra condition on STOPPED jobs is needed because they may be + * the only job present, but they won't get re-run until the JD work + * queue activates. Crucially, work queues can run items out of order + * e.g. on different CPUs, so being able to submit from the IRQ handler + * is not a good indication that we don't need to run jobs; the + * submitted job could be processed on the work-queue *before* the + * stopped job, even though it was submitted after. + * + * Therefore, we must try to run it, otherwise it might not get run at + * all after this. */ + + KBASE_TRACE_ADD_SLOT(kbdev, JS_JOB_DONE_RETRY_NEEDED, parent_ctx, katom, katom->jc, slot_nr); + kbasep_js_set_job_retry_submit_slot(katom, slot_nr); + } +} + +void kbasep_js_suspend(struct kbase_device *kbdev) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int i; + u16 retained = 0u; + int nr_privileged_ctx = 0; + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kbase_pm_is_suspending(kbdev)); + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* Prevent all contexts from submitting */ + js_devdata->runpool_irq.submit_allowed = 0; + + /* Retain each of the contexts, so we can cause it to leave even if it had + * no refcount to begin with */ + for (i = BASE_MAX_NR_AS - 1; i >= 0; --i) { + struct kbasep_js_per_as_data *js_per_as_data = &js_devdata->runpool_irq.per_as_data[i]; + struct kbase_context *kctx = js_per_as_data->kctx; + + retained = retained << 1; + + if (kctx) { + ++(js_per_as_data->as_busy_refcount); + retained |= 1u; + /* We can only cope with up to 1 privileged context - the + * instrumented context. It'll be suspended by disabling + * instrumentation */ + if (kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) + KBASE_DEBUG_ASSERT(++nr_privileged_ctx == 1); + } + } + CSTD_UNUSED(nr_privileged_ctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + /* De-ref the previous retain to ensure each context gets pulled out + * sometime later. */ + for (i = 0; + i < BASE_MAX_NR_AS; + ++i, retained = retained >> 1) { + struct kbasep_js_per_as_data *js_per_as_data = &js_devdata->runpool_irq.per_as_data[i]; + struct kbase_context *kctx = js_per_as_data->kctx; + + if (retained & 1u) + kbasep_js_runpool_release_ctx(kbdev, kctx); + } + + /* Caller must wait for all Power Manager active references to be dropped */ +} + +void kbasep_js_resume(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + int i; + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + + /* Schedule in as many contexts as address spaces. This also starts atoms. */ + for (i = 0 ; i < kbdev->nr_hw_address_spaces; ++i) + kbasep_js_try_schedule_head_ctx(kbdev); + + /* JS Resume complete */ +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js.h new file mode 100644 index 0000000000000000000000000000000000000000..3eb01c38e0572e2e217b63f4b6d8ee9aace8f905 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js.h @@ -0,0 +1,931 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js.h + * Job Scheduler APIs. + */ + +#ifndef _KBASE_JS_H_ +#define _KBASE_JS_H_ + +#include + +#include "mali_kbase_js_defs.h" +#include "mali_kbase_js_policy.h" +#include "mali_kbase_defs.h" +#include "mali_kbase_debug.h" + +#include "mali_kbase_js_ctx_attr.h" + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js Job Scheduler Internal APIs + * @{ + * + * These APIs are Internal to KBase and are available for use by the + * @ref kbase_js_policy "Job Scheduler Policy APIs" + */ + +/** + * @brief Initialize the Job Scheduler + * + * The struct kbasep_js_device_data sub-structure of \a kbdev must be zero + * initialized before passing to the kbasep_js_devdata_init() function. This is + * to give efficient error path code. + */ +mali_error kbasep_js_devdata_init(struct kbase_device * const kbdev); + +/** + * @brief Halt the Job Scheduler. + * + * It is safe to call this on \a kbdev even if it the kbasep_js_device_data + * sub-structure was never initialized/failed initialization, to give efficient + * error-path code. + * + * For this to work, the struct kbasep_js_device_data sub-structure of \a kbdev must + * be zero initialized before passing to the kbasep_js_devdata_init() + * function. This is to give efficient error path code. + * + * It is a Programming Error to call this whilst there are still kbase_context + * structures registered with this scheduler. + * + */ +void kbasep_js_devdata_halt(struct kbase_device *kbdev); + +/** + * @brief Terminate the Job Scheduler + * + * It is safe to call this on \a kbdev even if it the kbasep_js_device_data + * sub-structure was never initialized/failed initialization, to give efficient + * error-path code. + * + * For this to work, the struct kbasep_js_device_data sub-structure of \a kbdev must + * be zero initialized before passing to the kbasep_js_devdata_init() + * function. This is to give efficient error path code. + * + * It is a Programming Error to call this whilst there are still kbase_context + * structures registered with this scheduler. + */ +void kbasep_js_devdata_term(struct kbase_device *kbdev); + +/** + * @brief Initialize the Scheduling Component of a struct kbase_context on the Job Scheduler. + * + * This effectively registers a struct kbase_context with a Job Scheduler. + * + * It does not register any jobs owned by the struct kbase_context with the scheduler. + * Those must be separately registered by kbasep_js_add_job(). + * + * The struct kbase_context must be zero intitialized before passing to the + * kbase_js_init() function. This is to give efficient error path code. + */ +mali_error kbasep_js_kctx_init(struct kbase_context * const kctx); + +/** + * @brief Terminate the Scheduling Component of a struct kbase_context on the Job Scheduler + * + * This effectively de-registers a struct kbase_context from its Job Scheduler + * + * It is safe to call this on a struct kbase_context that has never had or failed + * initialization of its jctx.sched_info member, to give efficient error-path + * code. + * + * For this to work, the struct kbase_context must be zero intitialized before passing + * to the kbase_js_init() function. + * + * It is a Programming Error to call this whilst there are still jobs + * registered with this context. + */ +void kbasep_js_kctx_term(struct kbase_context *kctx); + +/** + * @brief Add a job chain to the Job Scheduler, and take necessary actions to + * schedule the context/run the job. + * + * This atomically does the following: + * - Update the numbers of jobs information + * - Add the job to the run pool if necessary (part of init_job) + * + * Once this is done, then an appropriate action is taken: + * - If the ctx is scheduled, it attempts to start the next job (which might be + * this added job) + * - Otherwise, and if this is the first job on the context, it enqueues it on + * the Policy Queue + * + * The Policy's Queue can be updated by this in the following ways: + * - In the above case that this is the first job on the context + * - If the job is high priority and the context is not scheduled, then it + * could cause the Policy to schedule out a low-priority context, allowing + * this context to be scheduled in. + * + * If the context is already scheduled on the RunPool, then adding a job to it + * is guarenteed not to update the Policy Queue. And so, the caller is + * guarenteed to not need to try scheduling a context from the Run Pool - it + * can safely assert that the result is MALI_FALSE. + * + * It is a programming error to have more than U32_MAX jobs in flight at a time. + * + * The following locking conditions are made on the caller: + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_js_device_data::runpool_irq::lock (as this will be + * obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). + * + * @return MALI_TRUE indicates that the Policy Queue was updated, and so the + * caller will need to try scheduling a context onto the Run Pool. + * @return MALI_FALSE indicates that no updates were made to the Policy Queue, + * so no further action is required from the caller. This is \b always returned + * when the context is currently scheduled. + */ +mali_bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom); + +/** + * @brief Remove a job chain from the Job Scheduler, except for its 'retained state'. + * + * Completely removing a job requires several calls: + * - kbasep_js_copy_atom_retained_state(), to capture the 'retained state' of + * the atom + * - kbasep_js_remove_job(), to partially remove the atom from the Job Scheduler + * - kbasep_js_runpool_release_ctx_and_katom_retained_state(), to release the + * remaining state held as part of the job having been run. + * + * In the common case of atoms completing normally, this set of actions is more optimal for spinlock purposes than having kbasep_js_remove_job() handle all of the actions. + * + * In the case of cancelling atoms, it is easier to call kbasep_js_remove_cancelled_job(), which handles all the necessary actions. + * + * It is a programming error to call this when: + * - \a atom is not a job belonging to kctx. + * - \a atom has already been removed from the Job Scheduler. + * - \a atom is still in the runpool: + * - it has not been removed with kbasep_js_policy_dequeue_job() + * - or, it has not been removed with kbasep_js_policy_dequeue_job_irq() + * + * Do not use this for removing jobs being killed by kbase_jd_cancel() - use + * kbasep_js_remove_cancelled_job() instead. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * + */ +void kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *atom); + +/** + * @brief Completely remove a job chain from the Job Scheduler, in the case + * where the job chain was cancelled. + * + * This is a variant of kbasep_js_remove_job() that takes care of removing all + * of the retained state too. This is generally useful for cancelled atoms, + * which need not be handled in an optimal way. + * + * It is a programming error to call this when: + * - \a atom is not a job belonging to kctx. + * - \a atom has already been removed from the Job Scheduler. + * - \a atom is still in the runpool: + * - it is not being killed with kbasep_jd_cancel() + * - or, it has not been removed with kbasep_js_policy_dequeue_job() + * - or, it has not been removed with kbasep_js_policy_dequeue_job_irq() + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, (as this will be + * obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this could be + * obtained internally) + */ +void kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief Refcount a context as being busy, preventing it from being scheduled + * out. + * + * @note This function can safely be called from IRQ context. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * + * @return value != MALI_FALSE if the retain succeeded, and the context will not be scheduled out. + * @return MALI_FALSE if the retain failed (because the context is being/has been scheduled out). + */ +mali_bool kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Refcount a context as being busy, preventing it from being scheduled + * out. + * + * @note This function can safely be called from IRQ context. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + * + * @return value != MALI_FALSE if the retain succeeded, and the context will not be scheduled out. + * @return MALI_FALSE if the retain failed (because the context is being/has been scheduled out). + */ +mali_bool kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Lookup a context in the Run Pool based upon its current address space + * and ensure that is stays scheduled in. + * + * The context is refcounted as being busy to prevent it from scheduling + * out. It must be released with kbasep_js_runpool_release_ctx() when it is no + * longer required to stay scheduled in. + * + * @note This function can safely be called from IRQ context. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpoool_irq::lock, because + * it will be used internally. + * + * @return a valid struct kbase_context on success, which has been refcounted as being busy. + * @return NULL on failure, indicating that no context was found in \a as_nr + */ +struct kbase_context *kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev, int as_nr); + +/** + * @brief Handling the requeuing/killing of a context that was evicted from the + * policy queue or runpool. + * + * This should be used whenever handing off a context that has been evicted + * from the policy queue or the runpool: + * - If the context is not dying and has jobs, it gets re-added to the policy + * queue + * - Otherwise, it is not added + * + * In addition, if the context is dying the jobs are killed asynchronously. + * + * In all cases, the Power Manager active reference is released + * (kbase_pm_context_idle()) whenever the has_pm_ref parameter is true. \a + * has_pm_ref must be set to false whenever the context was not previously in + * the runpool and does not hold a Power Manager active refcount. Note that + * contexts in a rollback of kbasep_js_try_schedule_head_ctx() might have an + * active refcount even though they weren't in the runpool. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_jd_device_data::queue_mutex (as this will be + * obtained internally) + */ +void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, mali_bool has_pm_ref); + +/** + * @brief Release a refcount of a context being busy, allowing it to be + * scheduled out. + * + * When the refcount reaches zero and the context \em might be scheduled out + * (depending on whether the Scheudling Policy has deemed it so, or if it has run + * out of jobs). + * + * If the context does get scheduled out, then The following actions will be + * taken as part of deschduling a context: + * - For the context being descheduled: + * - If the context is in the processing of dying (all the jobs are being + * removed from it), then descheduling also kills off any jobs remaining in the + * context. + * - If the context is not dying, and any jobs remain after descheduling the + * context then it is re-enqueued to the Policy's Queue. + * - Otherwise, the context is still known to the scheduler, but remains absent + * from the Policy Queue until a job is next added to it. + * - In all descheduling cases, the Power Manager active reference (obtained + * during kbasep_js_try_schedule_head_ctx()) is released (kbase_pm_context_idle()). + * + * Whilst the context is being descheduled, this also handles actions that + * cause more atoms to be run: + * - Attempt submitting atoms when the Context Attributes on the Runpool have + * changed. This is because the context being scheduled out could mean that + * there are more opportunities to run atoms. + * - Attempt submitting to a slot that was previously blocked due to affinity + * restrictions. This is usually only necessary when releasing a context + * happens as part of completing a previous job, but is harmless nonetheless. + * - Attempt scheduling in a new context (if one is available), and if necessary, + * running a job from that new context. + * + * Unlike retaining a context in the runpool, this function \b cannot be called + * from IRQ context. + * + * It is a programming error to call this on a \a kctx that is not currently + * scheduled, or that already has a zero refcount. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::as[n].transaction_mutex (as this will be obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (as this will be + * obtained internally) + * + */ +void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Variant of kbasep_js_runpool_release_ctx() that handles additional + * actions from completing an atom. + * + * This is usually called as part of completing an atom and releasing the + * refcount on the context held by the atom. + * + * Therefore, the extra actions carried out are part of handling actions queued + * on a completed atom, namely: + * - Releasing the atom's context attributes + * - Retrying the submission on a particular slot, because we couldn't submit + * on that slot from an IRQ handler. + * + * The locking conditions of this function are the same as those for + * kbasep_js_runpool_release_ctx() + */ +void kbasep_js_runpool_release_ctx_and_katom_retained_state(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state); + +/** + * @brief Try to submit the next job on a \b particular slot whilst in IRQ + * context, and whilst the caller already holds the runpool IRQ spinlock. + * + * \a *submit_count will be checked against + * KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ to see whether too many jobs have + * been submitted. This is to prevent the IRQ handler looping over lots of GPU + * NULL jobs, which may complete whilst the IRQ handler is still processing. \a + * submit_count itself should point to kbase_device::slot_submit_count_irq[ \a js ], + * which is initialized to zero on entry to the IRQ handler. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + * + * @return truthful (i.e. != MALI_FALSE) if too many jobs were submitted from + * IRQ. Therefore, this indicates that submission should be retried from a + * work-queue, by using + * kbasep_js_try_run_next_job_on_slot_nolock()/kbase_js_try_run_jobs_on_slot(). + * @return MALI_FALSE if submission had no problems: the GPU is either already + * full of jobs in the HEAD and NEXT registers, or we were able to get enough + * jobs from the Run Pool to fill the GPU's HEAD and NEXT registers. + */ +mali_bool kbasep_js_try_run_next_job_on_slot_irq_nolock(struct kbase_device *kbdev, int js, s8 *submit_count); + +/** + * @brief Try to submit the next job on a particular slot, outside of IRQ context + * + * This obtains the Job Slot lock for the duration of the call only. + * + * Unlike kbasep_js_try_run_next_job_on_slot_irq_nolock(), there is no limit on + * submission, because eventually IRQ_THROTTLE will kick in to prevent us + * getting stuck in a loop of submitting GPU NULL jobs. This is because the IRQ + * handler will be delayed, and so this function will eventually fill up the + * space in our software 'submitted' slot (kbase_jm_slot::submitted). + * + * In addition, there's no return value - we'll run the maintenence functions + * on the Policy's Run Pool, but if there's nothing there after that, then the + * Run Pool is truely empty, and so no more action need be taken. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + * - it must hold kbasep_js_device_data::runpool_irq::lock + * + * This must only be called whilst the GPU is powered - for example, when + * kbdev->jsdata.nr_user_contexts_running > 0. + * + * @note The caller \em might be holding one of the + * kbasep_js_kctx_info::ctx::jsctx_mutex locks. + * + */ +void kbasep_js_try_run_next_job_on_slot_nolock(struct kbase_device *kbdev, int js); + +/** + * @brief Try to submit the next job for each slot in the system, outside of IRQ context + * + * This will internally call kbasep_js_try_run_next_job_on_slot_nolock(), so similar + * locking conditions on the caller are required. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + * - it must hold kbasep_js_device_data::runpool_irq::lock + * + * @note The caller \em might be holding one of the + * kbasep_js_kctx_info::ctx::jsctx_mutex locks. + * + */ +void kbasep_js_try_run_next_job_nolock(struct kbase_device *kbdev); + +/** + * @brief Try to schedule the next context onto the Run Pool + * + * This checks whether there's space in the Run Pool to accommodate a new + * context. If so, it attempts to dequeue a context from the Policy Queue, and + * submit this to the Run Pool. + * + * If the scheduling succeeds, then it also makes a call to + * kbasep_js_try_run_next_job_nolock(), in case the new context has jobs + * matching the job slot requirements, but no other currently scheduled context + * has such jobs. + * + * Whilst attempting to obtain a context from the policy queue, or add a + * context to the runpool, this function takes a Power Manager active + * reference. If for any reason a context cannot be added to the runpool, any + * reference obtained is released once the context is safely back in the policy + * queue. If no context was available on the policy queue, any reference + * obtained is released too. + * + * Only if the context gets placed in the runpool does the Power Manager active + * reference stay held (and is effectively now owned by the + * context/runpool). It is only released once the context is removed + * completely, or added back to the policy queue + * (e.g. kbasep_js_runpool_release_ctx(), + * kbasep_js_runpool_requeue_or_kill_ctx(), etc) + * + * If any of these actions fail (Run Pool Full, Policy Queue empty, can't get + * PM active reference due to a suspend, etc) then any actions taken are rolled + * back and the function just returns normally. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::as[n].transaction_mutex (as this will be obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex, because it will + * be used internally. + * + */ +void kbasep_js_try_schedule_head_ctx(struct kbase_device *kbdev); + +/** + * @brief Schedule in a privileged context + * + * This schedules a context in regardless of the context priority. + * If the runpool is full, a context will be forced out of the runpool and the function will wait + * for the new context to be scheduled in. + * The context will be kept scheduled in (and the corresponding address space reserved) until + * kbasep_js_release_privileged_ctx is called). + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::as[n].transaction_mutex (as this will be obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex, because it will + * be used internally. + * + */ +void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Release a privileged context, allowing it to be scheduled out. + * + * See kbasep_js_runpool_release_ctx for potential side effects. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::as[n].transaction_mutex (as this will be obtained internally) + * + */ +void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Handle the Job Scheduler component for the IRQ of a job finishing + * + * This does the following: + * -# Releases resources held by the atom + * -# if \a end_timestamp != NULL, updates the runpool's notion of time spent by a running ctx + * -# determines whether a context should be marked for scheduling out + * -# examines done_code to determine whether to submit the next job on the slot + * (picking from all ctxs in the runpool) + * + * In addition, if submission didn't happen (the submit-from-IRQ function + * failed or done_code didn't specify to start new jobs), then this sets a + * message on katom that submission needs to be retried from the worker thread. + * + * Normally, the time calculated from end_timestamp is rounded up to the + * minimum time precision. Therefore, to ensure the job is recorded as not + * spending any time, then set end_timestamp to NULL. For example, this is necessary when + * evicting jobs from JS_HEAD_NEXT (because they didn't actually run). + * + * NOTE: It's possible to move the steps (2) and (3) (inc calculating job's time + * used) into the worker (outside of IRQ context), but this may allow a context + * to use up to twice as much timeslice as is allowed by the policy. For + * policies that order by time spent, this is not a problem for overall + * 'fairness', but can still increase latency between contexts. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpoool_irq::lock + */ +void kbasep_js_job_done_slot_irq(struct kbase_jd_atom *katom, int slot_nr, + ktime_t *end_timestamp, + kbasep_js_atom_done_code done_code); + +/** + * @brief Try to submit the next job on each slot + * + * The following locks may be used: + * - kbasep_js_device_data::runpool_mutex + * - kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_try_run_jobs(struct kbase_device *kbdev); + +/** + * @brief Try to submit the next job on a specfic slot + * + * The following locking conditions are made on the caller: + * + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_irq::lock (as this + * will be obtained internally) + * + */ +void kbase_js_try_run_jobs_on_slot(struct kbase_device *kbdev, int js); + +/** + * @brief Handle releasing cores for power management and affinity management, + * ensuring that cores are powered down and affinity tracking is updated. + * + * This must only be called on an atom that is not currently running, and has + * not been re-queued onto the context (and so does not need locking) + * + * This function enters at the following @ref enum kbase_atom_coreref_state states: + * - NO_CORES_REQUESTED + * - WAITING_FOR_REQUESTED_CORES + * - RECHECK_AFFINITY + * - READY + * + * It transitions the above states back to NO_CORES_REQUESTED by the end of the + * function call (possibly via intermediate states). + * + * No locks need be held by the caller, since this takes the necessary Power + * Management locks itself. The runpool_irq.lock is not taken (the work that + * requires it is handled by kbase_js_affinity_submit_to_blocked_slots() ). + * + * @note The corresponding kbasep_js_job_check_ref_cores() is private to the + * Job Scheduler, and is called automatically when running the next job. + */ +void kbasep_js_job_check_deref_cores(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +/** + * @brief Suspend the job scheduler during a Power Management Suspend event. + * + * Causes all contexts to be removed from the runpool, and prevents any + * contexts from (re)entering the runpool. + * + * This does not handle suspending the one privileged context: the caller must + * instead do this by by suspending the GPU HW Counter Instrumentation. + * + * This will eventually cause all Power Management active references held by + * contexts on the runpool to be released, without running any more atoms. + * + * The caller must then wait for all Power Mangement active refcount to become + * zero before completing the suspend. + * + * The emptying mechanism may take some time to complete, since it can wait for + * jobs to complete naturally instead of forcing them to end quickly. However, + * this is bounded by the Job Scheduling Policy's Job Timeouts. Hence, this + * function is guaranteed to complete in a finite time whenever the Job + * Scheduling Policy implements Job Timeouts (such as those done by CFS). + */ +void kbasep_js_suspend(struct kbase_device *kbdev); + +/** + * @brief Resume the Job Scheduler after a Power Management Resume event. + * + * This restores the actions from kbasep_js_suspend(): + * - Schedules contexts back into the runpool + * - Resumes running atoms on the GPU + */ +void kbasep_js_resume(struct kbase_device *kbdev); + + +/* + * Helpers follow + */ + +/** + * @brief Check that a context is allowed to submit jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * As with any mali_bool, never test the return value with MALI_TRUE. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock. + */ +static INLINE mali_bool kbasep_js_is_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 test_bit; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.is_scheduled != MALI_FALSE); + + test_bit = (u16) (1u << kctx->as_nr); + + return (mali_bool) (js_devdata->runpool_irq.submit_allowed & test_bit); +} + +/** + * @brief Allow a context to submit jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock. + */ +static INLINE void kbasep_js_set_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 set_bit; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.is_scheduled != MALI_FALSE); + + set_bit = (u16) (1u << kctx->as_nr); + + dev_dbg(kctx->kbdev->dev, "JS: Setting Submit Allowed on %p (as=%d)", kctx, kctx->as_nr); + + js_devdata->runpool_irq.submit_allowed |= set_bit; +} + +/** + * @brief Prevent a context from submitting more jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock. + */ +static INLINE void kbasep_js_clear_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 clear_bit; + u16 clear_mask; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.is_scheduled != MALI_FALSE); + + clear_bit = (u16) (1u << kctx->as_nr); + clear_mask = ~clear_bit; + + dev_dbg(kctx->kbdev->dev, "JS: Clearing Submit Allowed on %p (as=%d)", kctx, kctx->as_nr); + + js_devdata->runpool_irq.submit_allowed &= clear_mask; +} + +/** + * @brief Manage the 'retry_submit_on_slot' part of a kbase_jd_atom + */ +static INLINE void kbasep_js_clear_job_retry_submit(struct kbase_jd_atom *atom) +{ + atom->retry_submit_on_slot = KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID; +} + +/** + * Mark a slot as requiring resubmission by carrying that information on a + * completing atom. + * + * @note This can ASSERT in debug builds if the submit slot has been set to + * something other than the current value for @a js. This is because you might + * be unintentionally stopping more jobs being submitted on the old submit + * slot, and that might cause a scheduling-hang. + * + * @note If you can guarantee that the atoms for the original slot will be + * submitted on some other slot, then call kbasep_js_clear_job_retry_submit() + * first to silence the ASSERT. + */ +static INLINE void kbasep_js_set_job_retry_submit_slot(struct kbase_jd_atom *atom, int js) +{ + KBASE_DEBUG_ASSERT(0 <= js && js <= BASE_JM_MAX_NR_SLOTS); + KBASE_DEBUG_ASSERT(atom->retry_submit_on_slot == KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID + || atom->retry_submit_on_slot == js); + + atom->retry_submit_on_slot = js; +} + +/** + * Create an initial 'invalid' atom retained state, that requires no + * atom-related work to be done on releasing with + * kbasep_js_runpool_release_ctx_and_katom_retained_state() + */ +static INLINE void kbasep_js_atom_retained_state_init_invalid(struct kbasep_js_atom_retained_state *retained_state) +{ + retained_state->event_code = BASE_JD_EVENT_NOT_STARTED; + retained_state->core_req = KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID; + retained_state->retry_submit_on_slot = KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID; +} + +/** + * Copy atom state that can be made available after jd_done_nolock() is called + * on that atom. + */ +static INLINE void kbasep_js_atom_retained_state_copy(struct kbasep_js_atom_retained_state *retained_state, const struct kbase_jd_atom *katom) +{ + retained_state->event_code = katom->event_code; + retained_state->core_req = katom->core_req; + retained_state->retry_submit_on_slot = katom->retry_submit_on_slot; + retained_state->device_nr = katom->device_nr; +} + +/** + * @brief Determine whether an atom has finished (given its retained state), + * and so should be given back to userspace/removed from the system. + * + * Reasons for an atom not finishing include: + * - Being soft-stopped (and so, the atom should be resubmitted sometime later) + * + * @param[in] katom_retained_state the retained state of the atom to check + * @return MALI_FALSE if the atom has not finished + * @return !=MALI_FALSE if the atom has finished + */ +static INLINE mali_bool kbasep_js_has_atom_finished(const struct kbasep_js_atom_retained_state *katom_retained_state) +{ + return (mali_bool) (katom_retained_state->event_code != BASE_JD_EVENT_STOPPED && katom_retained_state->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT); +} + +/** + * @brief Determine whether a struct kbasep_js_atom_retained_state is valid + * + * An invalid struct kbasep_js_atom_retained_state is allowed, and indicates that the + * code should just ignore it. + * + * @param[in] katom_retained_state the atom's retained state to check + * @return MALI_FALSE if the retained state is invalid, and can be ignored + * @return !=MALI_FALSE if the retained state is valid + */ +static INLINE mali_bool kbasep_js_atom_retained_state_is_valid(const struct kbasep_js_atom_retained_state *katom_retained_state) +{ + return (mali_bool) (katom_retained_state->core_req != KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID); +} + +static INLINE mali_bool kbasep_js_get_atom_retry_submit_slot(const struct kbasep_js_atom_retained_state *katom_retained_state, int *res) +{ + int js = katom_retained_state->retry_submit_on_slot; + *res = js; + return (mali_bool) (js >= 0); +} + +#if KBASE_DEBUG_DISABLE_ASSERTS == 0 +/** + * Debug Check the refcount of a context. Only use within ASSERTs + * + * Obtains kbasep_js_device_data::runpool_irq::lock + * + * @return negative value if the context is not scheduled in + * @return current refcount of the context if it is scheduled in. The refcount + * is not guarenteed to be kept constant. + */ +static INLINE int kbasep_js_debug_check_ctx_refcount(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int result = -1; + int as_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + as_nr = kctx->as_nr; + if (as_nr != KBASEP_AS_NR_INVALID) + result = js_devdata->runpool_irq.per_as_data[as_nr].as_busy_refcount; + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return result; +} +#endif /* KBASE_DEBUG_DISABLE_ASSERTS == 0 */ + +/** + * @brief Variant of kbasep_js_runpool_lookup_ctx() that can be used when the + * context is guarenteed to be already previously retained. + * + * It is a programming error to supply the \a as_nr of a context that has not + * been previously retained/has a busy refcount of zero. The only exception is + * when there is no ctx in \a as_nr (NULL returned). + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpoool_irq::lock, because + * it will be used internally. + * + * @return a valid struct kbase_context on success, with a refcount that is guarenteed + * to be non-zero and unmodified by this function. + * @return NULL on failure, indicating that no context was found in \a as_nr + */ +static INLINE struct kbase_context *kbasep_js_runpool_lookup_ctx_noretain(struct kbase_device *kbdev, int as_nr) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbase_context *found_kctx; + struct kbasep_js_per_as_data *js_per_as_data; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS); + js_devdata = &kbdev->js_data; + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + found_kctx = js_per_as_data->kctx; + KBASE_DEBUG_ASSERT(found_kctx == NULL || js_per_as_data->as_busy_refcount > 0); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return found_kctx; +} + +/** + * This will provide a conversion from time (us) to ticks of the gpu clock + * based on the minimum available gpu frequency. + * This is usually good to compute best/worst case (where the use of current + * frequency is not valid due to DVFS). + * e.g.: when you need the number of cycles to guarantee you won't wait for + * longer than 'us' time (you might have a shorter wait). + */ +static INLINE u32 kbasep_js_convert_us_to_gpu_ticks_min_freq(struct kbase_device *kbdev, u32 us) +{ + u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_min; + KBASE_DEBUG_ASSERT(0 != gpu_freq); + return us * (gpu_freq / 1000); +} + +/** + * This will provide a conversion from time (us) to ticks of the gpu clock + * based on the maximum available gpu frequency. + * This is usually good to compute best/worst case (where the use of current + * frequency is not valid due to DVFS). + * e.g.: When you need the number of cycles to guarantee you'll wait at least + * 'us' amount of time (but you might wait longer). + */ +static INLINE u32 kbasep_js_convert_us_to_gpu_ticks_max_freq(struct kbase_device *kbdev, u32 us) +{ + u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_max; + KBASE_DEBUG_ASSERT(0 != gpu_freq); + return us * (u32) (gpu_freq / 1000); +} + +/** + * This will provide a conversion from ticks of the gpu clock to time (us) + * based on the minimum available gpu frequency. + * This is usually good to compute best/worst case (where the use of current + * frequency is not valid due to DVFS). + * e.g.: When you need to know the worst-case wait that 'ticks' cycles will + * take (you guarantee that you won't wait any longer than this, but it may + * be shorter). + */ +static INLINE u32 kbasep_js_convert_gpu_ticks_to_us_min_freq(struct kbase_device *kbdev, u32 ticks) +{ + u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_min; + KBASE_DEBUG_ASSERT(0 != gpu_freq); + return ticks / gpu_freq * 1000; +} + +/** + * This will provide a conversion from ticks of the gpu clock to time (us) + * based on the maximum available gpu frequency. + * This is usually good to compute best/worst case (where the use of current + * frequency is not valid due to DVFS). + * e.g.: When you need to know the best-case wait for 'tick' cycles (you + * guarantee to be waiting for at least this long, but it may be longer). + */ +static INLINE u32 kbasep_js_convert_gpu_ticks_to_us_max_freq(struct kbase_device *kbdev, u32 ticks) +{ + u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_max; + KBASE_DEBUG_ASSERT(0 != gpu_freq); + return ticks / gpu_freq * 1000; +} + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.c new file mode 100644 index 0000000000000000000000000000000000000000..7a4cae3be870bfad6261fc84fb14d6e853af4df0 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.c @@ -0,0 +1,382 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_affinity.c + * Base kernel affinity manager APIs + */ + +#include +#include "mali_kbase_js_affinity.h" + + +STATIC INLINE mali_bool affinity_job_uses_high_cores(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + struct kbase_context *kctx; + kbase_context_flags ctx_flags; + + kctx = katom->kctx; + ctx_flags = kctx->jctx.sched_info.ctx.flags; + + /* In this HW Workaround, compute-only jobs/contexts use the high cores + * during a core-split, all other contexts use the low cores. */ + return (mali_bool) ((katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) != 0 || (ctx_flags & KBASE_CTX_FLAG_HINT_ONLY_COMPUTE) != 0); + } + return MALI_FALSE; +} + +/** + * @brief Decide whether a split in core affinity is required across job slots + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_irq::lock + * + * @param kbdev The kbase device structure of the device + * @return MALI_FALSE if a core split is not required + * @return != MALI_FALSE if a core split is required. + */ +STATIC INLINE mali_bool kbase_affinity_requires_split(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + s8 nr_compute_ctxs = kbasep_js_ctx_attr_count_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_COMPUTE); + s8 nr_noncompute_ctxs = kbasep_js_ctx_attr_count_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_NON_COMPUTE); + + /* In this case, a mix of Compute+Non-Compute determines whether a + * core-split is required, to ensure jobs with different numbers of RMUs + * don't use the same cores. + * + * When it's entirely compute, or entirely non-compute, then no split is + * required. + * + * A context can be both Compute and Non-compute, in which case this will + * correctly decide that a core-split is required. */ + + return (mali_bool) (nr_compute_ctxs > 0 && nr_noncompute_ctxs > 0); + } + return MALI_FALSE; +} + +mali_bool kbase_js_can_run_job_on_slot_no_lock(struct kbase_device *kbdev, int js) +{ + /* + * Here are the reasons for using job slot 2: + * - BASE_HW_ISSUE_8987 (which is entirely used for that purpose) + * - In absence of the above, then: + * - Atoms with BASE_JD_REQ_COHERENT_GROUP + * - But, only when there aren't contexts with + * KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES, because the atoms that run on + * all cores on slot 1 could be blocked by those using a coherent group + * on slot 2 + * - And, only when you actually have 2 or more coregroups - if you only + * have 1 coregroup, then having jobs for slot 2 implies they'd also be + * for slot 1, meaning you'll get interference from them. Jobs able to + * run on slot 2 could also block jobs that can only run on slot 1 + * (tiler jobs) + */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) + return MALI_TRUE; + + if (js != 2) + return MALI_TRUE; + + /* Only deal with js==2 now: */ + if (kbdev->gpu_props.num_core_groups > 1) { + /* Only use slot 2 in the 2+ coregroup case */ + if (kbasep_js_ctx_attr_is_attr_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES) == MALI_FALSE) { + /* ...But only when we *don't* have atoms that run on all cores */ + + /* No specific check for BASE_JD_REQ_COHERENT_GROUP atoms - the policy will sort that out */ + return MALI_TRUE; + } + } + + /* Above checks failed mean we shouldn't use slot 2 */ + return MALI_FALSE; +} + +/* + * As long as it has been decided to have a deeper modification of + * what job scheduler, power manager and affinity manager will + * implement, this function is just an intermediate step that + * assumes: + * - all working cores will be powered on when this is called. + * - largest current configuration is 2 core groups. + * - It has been decided not to have hardcoded values so the low + * and high cores in a core split will be evently distributed. + * - Odd combinations of core requirements have been filtered out + * and do not get to this function (e.g. CS+T+NSS is not + * supported here). + * - This function is frequently called and can be optimized, + * (see notes in loops), but as the functionallity will likely + * be modified, optimization has not been addressed. +*/ +mali_bool kbase_js_choose_affinity(u64 * const affinity, struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js) +{ + base_jd_core_req core_req = katom->core_req; + unsigned int num_core_groups = kbdev->gpu_props.num_core_groups; + u64 core_availability_mask; + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + core_availability_mask = kbase_pm_ca_get_core_mask(kbdev); + + /* + * If no cores are currently available (core availability policy is + * transitioning) then fail. + */ + if (0 == core_availability_mask) { + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + *affinity = 0; + return MALI_FALSE; + } + + KBASE_DEBUG_ASSERT(js >= 0); + + if ((core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) == BASE_JD_REQ_T) { + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + /* Tiler only job, bit 0 needed to enable tiler but no shader cores required */ + *affinity = 1; + return MALI_TRUE; + } + + if (1 == kbdev->gpu_props.num_cores) { + /* trivial case only one core, nothing to do */ + *affinity = core_availability_mask; + } else if (kbase_affinity_requires_split(kbdev) == MALI_FALSE) { + if ((core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP))) { + if (js == 0 || num_core_groups == 1) { + /* js[0] and single-core-group systems just get the first core group */ + *affinity = kbdev->gpu_props.props.coherency_info.group[0].core_mask & core_availability_mask; + } else { + /* js[1], js[2] use core groups 0, 1 for dual-core-group systems */ + u32 core_group_idx = ((u32) js) - 1; + + KBASE_DEBUG_ASSERT(core_group_idx < num_core_groups); + *affinity = kbdev->gpu_props.props.coherency_info.group[core_group_idx].core_mask & core_availability_mask; + + /* If the job is specifically targeting core group 1 and the core + * availability policy is keeping that core group off, then fail */ + if (*affinity == 0 && core_group_idx == 1 && kbdev->pm.cg1_disabled == MALI_TRUE) + katom->event_code = BASE_JD_EVENT_PM_EVENT; + } + } else { + /* All cores are available when no core split is required */ + *affinity = core_availability_mask; + } + } else { + /* Core split required - divide cores in two non-overlapping groups */ + u64 low_bitmap, high_bitmap; + int n_high_cores = kbdev->gpu_props.num_cores >> 1; + KBASE_DEBUG_ASSERT(1 == num_core_groups); + KBASE_DEBUG_ASSERT(0 != n_high_cores); + + /* compute the reserved high cores bitmap */ + high_bitmap = ~0; + /* note: this can take a while, optimization desirable */ + while (n_high_cores != hweight32(high_bitmap & kbdev->shader_present_bitmap)) + high_bitmap = high_bitmap << 1; + + high_bitmap &= core_availability_mask; + low_bitmap = core_availability_mask ^ high_bitmap; + + if (affinity_job_uses_high_cores(kbdev, katom)) + *affinity = high_bitmap; + else + *affinity = low_bitmap; + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* + * If no cores are currently available in the desired core group(s) + * (core availability policy is transitioning) then fail. + */ + if (*affinity == 0) + return MALI_FALSE; + + /* Enable core 0 if tiler required */ + if (core_req & BASE_JD_REQ_T) + *affinity = *affinity | 1; + + return MALI_TRUE; +} + +STATIC INLINE mali_bool kbase_js_affinity_is_violating(struct kbase_device *kbdev, u64 *affinities) +{ + /* This implementation checks whether the two slots involved in Generic thread creation + * have intersecting affinity. This is due to micro-architectural issues where a job in + * slot A targetting cores used by slot B could prevent the job in slot B from making + * progress until the job in slot A has completed. + * + * @note It just so happens that this restriction also allows + * BASE_HW_ISSUE_8987 to be worked around by placing on job slot 2 the + * atoms from ctxs with KBASE_CTX_FLAG_HINT_ONLY_COMPUTE flag set + */ + u64 affinity_set_left; + u64 affinity_set_right; + u64 intersection; + + KBASE_DEBUG_ASSERT(affinities != NULL); + + affinity_set_left = affinities[1]; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + /* The left set also includes those on the Fragment slot when + * we are using the HW workaround for BASE_HW_ISSUE_8987 */ + affinity_set_left |= affinities[0]; + } + + affinity_set_right = affinities[2]; + + /* A violation occurs when any bit in the left_set is also in the right_set */ + intersection = affinity_set_left & affinity_set_right; + + return (mali_bool) (intersection != (u64) 0u); +} + +mali_bool kbase_js_affinity_would_violate(struct kbase_device *kbdev, int js, u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 new_affinities[BASE_JM_MAX_NR_SLOTS]; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + memcpy(new_affinities, js_devdata->runpool_irq.slot_affinities, sizeof(js_devdata->runpool_irq.slot_affinities)); + + new_affinities[js] |= affinity; + + return kbase_js_affinity_is_violating(kbdev, new_affinities); +} + +void kbase_js_affinity_retain_slot_cores(struct kbase_device *kbdev, int js, u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 cores; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(kbase_js_affinity_would_violate(kbdev, js, affinity) == MALI_FALSE); + + cores = affinity; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + s8 cnt; + + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum] < BASE_JM_SUBMIT_SLOTS); + + cnt = ++(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum]); + + if (cnt == 1) + js_devdata->runpool_irq.slot_affinities[js] |= bit; + + cores &= ~bit; + } +} + +void kbase_js_affinity_release_slot_cores(struct kbase_device *kbdev, int js, u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 cores; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + cores = affinity; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + s8 cnt; + + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum] > 0); + + cnt = --(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum]); + + if (0 == cnt) + js_devdata->runpool_irq.slot_affinities[js] &= ~bit; + + cores &= ~bit; + } + +} + +void kbase_js_affinity_slot_blocked_an_atom(struct kbase_device *kbdev, int js) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + js_devdata->runpool_irq.slots_blocked_on_affinity |= 1u << js; +} + +void kbase_js_affinity_submit_to_blocked_slots(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + u16 slots; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running != 0); + + /* Must take a copy because submitting jobs will update this member. */ + slots = js_devdata->runpool_irq.slots_blocked_on_affinity; + + while (slots) { + int bitnum = fls(slots) - 1; + + u16 bit = 1u << bitnum; + slots &= ~bit; + + KBASE_TRACE_ADD_SLOT(kbdev, JS_AFFINITY_SUBMIT_TO_BLOCKED, NULL, NULL, 0u, bitnum); + + /* must update this before we submit, incase it's set again */ + js_devdata->runpool_irq.slots_blocked_on_affinity &= ~bit; + + kbasep_js_try_run_next_job_on_slot_nolock(kbdev, bitnum); + + /* Don't re-read slots_blocked_on_affinity after this - it could loop for a long time */ + } +} + +#if KBASE_TRACE_ENABLE +void kbase_js_debug_log_current_affinities(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + int slot_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + for (slot_nr = 0; slot_nr < 3; ++slot_nr) + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_AFFINITY_CURRENT, NULL, NULL, 0u, slot_nr, (u32) js_devdata->runpool_irq.slot_affinities[slot_nr]); +} +#endif /* KBASE_TRACE_ENABLE */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.h new file mode 100644 index 0000000000000000000000000000000000000000..83da812802dc8eaa66f2cf10281bb215f2077ac7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.h @@ -0,0 +1,157 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_affinity.h + * Affinity Manager internal APIs. + */ + +#ifndef _KBASE_JS_AFFINITY_H_ +#define _KBASE_JS_AFFINITY_H_ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js_affinity Affinity Manager internal APIs. + * @{ + * + */ + +/** + * @brief Decide whether it is possible to submit a job to a particular job slot in the current status + * + * Will check if submitting to the given job slot is allowed in the current + * status. For example using job slot 2 while in soft-stoppable state and only + * having 1 coregroup is not allowed by the policy. This function should be + * called prior to submitting a job to a slot to make sure policy rules are not + * violated. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_irq::lock + * + * @param kbdev The kbase device structure of the device + * @param js Job slot number to check for allowance + */ +mali_bool kbase_js_can_run_job_on_slot_no_lock(struct kbase_device *kbdev, int js); + +/** + * @brief Compute affinity for a given job. + * + * Currently assumes an all-on/all-off power management policy. + * Also assumes there is at least one core with tiler available. + * + * Returns MALI_TRUE if a valid affinity was chosen, MALI_FALSE if + * no cores were available. + * + * @param[out] affinity Affinity bitmap computed + * @param kbdev The kbase device structure of the device + * @param katom Job chain of which affinity is going to be found + * @param js Slot the job chain is being submitted + + */ +mali_bool kbase_js_choose_affinity(u64 * const affinity, struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js); + +/** + * @brief Determine whether a proposed \a affinity on job slot \a js would + * cause a violation of affinity restrictions. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + */ +mali_bool kbase_js_affinity_would_violate(struct kbase_device *kbdev, int js, u64 affinity); + +/** + * @brief Affinity tracking: retain cores used by a slot + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_affinity_retain_slot_cores(struct kbase_device *kbdev, int js, u64 affinity); + +/** + * @brief Affinity tracking: release cores used by a slot + * + * Cores \b must be released as soon as a job is dequeued from a slot's 'submit + * slots', and before another job is submitted to those slots. Otherwise, the + * refcount could exceed the maximum number submittable to a slot, + * BASE_JM_SUBMIT_SLOTS. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_affinity_release_slot_cores(struct kbase_device *kbdev, int js, u64 affinity); + +/** + * @brief Register a slot as blocking atoms due to affinity violations + * + * Once a slot has been registered, we must check after every atom completion + * (including those on different slots) to see if the slot can be + * unblocked. This is done by calling + * kbase_js_affinity_submit_to_blocked_slots(), which will also deregister the + * slot if it no long blocks atoms due to affinity violations. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_affinity_slot_blocked_an_atom(struct kbase_device *kbdev, int js); + +/** + * @brief Submit to job slots that have registered that an atom was blocked on + * the slot previously due to affinity violations. + * + * This submits to all slots registered by + * kbase_js_affinity_slot_blocked_an_atom(). If submission succeeded, then the + * slot is deregistered as having blocked atoms due to affinity + * violations. Otherwise it stays registered, and the next atom to complete + * must attempt to submit to the blocked slots again. + * + * This must only be called whilst the GPU is powered - for example, when + * kbdev->jsdata.nr_user_contexts_running > 0. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + * - it must hold kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_affinity_submit_to_blocked_slots(struct kbase_device *kbdev); + +/** + * @brief Output to the Trace log the current tracked affinities on all slots + */ +#if KBASE_TRACE_ENABLE +void kbase_js_debug_log_current_affinities(struct kbase_device *kbdev); +#else /* KBASE_TRACE_ENABLE */ +static INLINE void kbase_js_debug_log_current_affinities(struct kbase_device *kbdev) +{ +} +#endif /* KBASE_TRACE_ENABLE */ + + /** @} *//* end group kbase_js_affinity */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + + +#endif /* _KBASE_JS_AFFINITY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c new file mode 100644 index 0000000000000000000000000000000000000000..aa13bdb7fda3e0092341bd9b7f054308dc39cb3b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c @@ -0,0 +1,329 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#include +#include + +/* + * Private functions follow + */ + +/** + * @brief Check whether a ctx has a certain attribute, and if so, retain that + * attribute on the runpool. + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx is scheduled on the runpool + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +STATIC mali_bool kbasep_js_ctx_attr_runpool_retain_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE); + + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != MALI_FALSE) { + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] < S8_MAX); + ++(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]); + + if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 1) { + /* First refcount indicates a state change */ + runpool_state_changed = MALI_TRUE; + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_ON_RUNPOOL, kctx, NULL, 0u, attribute); + } + } + + return runpool_state_changed; +} + +/** + * @brief Check whether a ctx has a certain attribute, and if so, release that + * attribute on the runpool. + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx is scheduled on the runpool + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +STATIC mali_bool kbasep_js_ctx_attr_runpool_release_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE); + + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != MALI_FALSE) { + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] > 0); + --(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]); + + if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 0) { + /* Last de-refcount indicates a state change */ + runpool_state_changed = MALI_TRUE; + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_OFF_RUNPOOL, kctx, NULL, 0u, attribute); + } + } + + return runpool_state_changed; +} + +/** + * @brief Retain a certain attribute on a ctx, also retaining it on the runpool + * if the context is scheduled. + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * This may allow the scheduler to submit more jobs than previously. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +STATIC mali_bool kbasep_js_ctx_attr_ctx_retain_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] < U32_MAX); + + ++(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); + + if (js_kctx_info->ctx.is_scheduled != MALI_FALSE && js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) { + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + /* Only ref-count the attribute on the runpool for the first time this contexts sees this attribute */ + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_ON_CTX, kctx, NULL, 0u, attribute); + runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, attribute); + } + + return runpool_state_changed; +} + +/** + * @brief Release a certain attribute on a ctx, also releasign it from the runpool + * if the context is scheduled. + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * This may allow the scheduler to submit more jobs than previously. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +STATIC mali_bool kbasep_js_ctx_attr_ctx_release_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] > 0); + + if (js_kctx_info->ctx.is_scheduled != MALI_FALSE && js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) { + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + /* Only de-ref-count the attribute on the runpool when this is the last ctx-reference to it */ + runpool_state_changed = kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, attribute); + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_OFF_CTX, kctx, NULL, 0u, attribute); + } + + /* De-ref must happen afterwards, because kbasep_js_ctx_attr_runpool_release() needs to check it too */ + --(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); + + return runpool_state_changed; +} + +/* + * More commonly used public functions + */ + +void kbasep_js_ctx_attr_set_initial_attrs(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) != MALI_FALSE) { + /* This context never submits, so don't track any scheduling attributes */ + return; + } + + /* Transfer attributes held in the context flags for contexts that have submit enabled */ + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_HINT_ONLY_COMPUTE) != MALI_FALSE) { + /* Compute context */ + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); + } + /* NOTE: Whether this is a non-compute context depends on the jobs being + * run, e.g. it might be submitting jobs with BASE_JD_REQ_ONLY_COMPUTE */ + + /* ... More attributes can be added here ... */ + + /* The context should not have been scheduled yet, so ASSERT if this caused + * runpool state changes (note that other threads *can't* affect the value + * of runpool_state_changed, due to how it's calculated) */ + KBASE_DEBUG_ASSERT(runpool_state_changed == MALI_FALSE); + CSTD_UNUSED(runpool_state_changed); +} + +void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + mali_bool runpool_state_changed; + int i; + + /* Retain any existing attributes */ + for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) { + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr) i) != MALI_FALSE) { + /* The context is being scheduled in, so update the runpool with the new attributes */ + runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, (enum kbasep_js_ctx_attr) i); + + /* We don't need to know about state changed, because retaining a + * context occurs on scheduling it, and that itself will also try + * to run new atoms */ + CSTD_UNUSED(runpool_state_changed); + } + } +} + +mali_bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + mali_bool runpool_state_changed = MALI_FALSE; + int i; + + /* Release any existing attributes */ + for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) { + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr) i) != MALI_FALSE) { + /* The context is being scheduled out, so update the runpool on the removed attributes */ + runpool_state_changed |= kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, (enum kbasep_js_ctx_attr) i); + } + } + + return runpool_state_changed; +} + +void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + mali_bool runpool_state_changed = MALI_FALSE; + base_jd_core_req core_req; + + KBASE_DEBUG_ASSERT(katom); + core_req = katom->core_req; + + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); + else + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE); + + if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) { + /* Atom that can run on slot1 or slot2, and can use all cores */ + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES); + } + + /* We don't need to know about state changed, because retaining an + * atom occurs on adding it, and that itself will also try to run + * new atoms */ + CSTD_UNUSED(runpool_state_changed); +} + +mali_bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state) +{ + mali_bool runpool_state_changed = MALI_FALSE; + base_jd_core_req core_req; + + KBASE_DEBUG_ASSERT(katom_retained_state); + core_req = katom_retained_state->core_req; + + /* No-op for invalid atoms */ + if (kbasep_js_atom_retained_state_is_valid(katom_retained_state) == MALI_FALSE) + return MALI_FALSE; + + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) { +#if KBASE_PM_EN + unsigned long flags; + int device_nr = (core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) ? katom_retained_state->device_nr : 0; + KBASE_DEBUG_ASSERT(device_nr < 2); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbasep_pm_record_job_status(kbdev); + kbdev->pm.metrics.active_cl_ctx[device_nr]--; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +#endif + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); + } else { +#if KBASE_PM_EN + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbasep_pm_record_job_status(kbdev); + kbdev->pm.metrics.active_gl_ctx--; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +#endif + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE); + } + + if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) { + /* Atom that can run on slot1 or slot2, and can use all cores */ + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES); + } + + return runpool_state_changed; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h new file mode 100644 index 0000000000000000000000000000000000000000..6a57538298d0b3f0f47380e03c51b6063b99939b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h @@ -0,0 +1,158 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_ctx_attr.h + * Job Scheduler Context Attribute APIs + */ + +#ifndef _KBASE_JS_CTX_ATTR_H_ +#define _KBASE_JS_CTX_ATTR_H_ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js + * @{ + */ + +/** + * Set the initial attributes of a context (when context create flags are set) + * + * Requires: + * - Hold the jsctx_mutex + */ +void kbasep_js_ctx_attr_set_initial_attrs(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Retain all attributes of a context + * + * This occurs on scheduling in the context on the runpool (but after + * is_scheduled is set) + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx->is_scheduled is true + */ +void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Release all attributes of a context + * + * This occurs on scheduling out the context from the runpool (but before + * is_scheduled is cleared) + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx->is_scheduled is true + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +mali_bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Retain all attributes of an atom + * + * This occurs on adding an atom to a context + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + */ +void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * Release all attributes of an atom, given its retained state. + * + * This occurs after (permanently) removing an atom from a context + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * This is a no-op when \a katom_retained_state is invalid. + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +mali_bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state); + +/** + * Requires: + * - runpool_irq spinlock + */ +static INLINE s8 kbasep_js_ctx_attr_count_on_runpool(struct kbase_device *kbdev, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + + return js_devdata->runpool_irq.ctx_attr_ref_count[attribute]; +} + +/** + * Requires: + * - runpool_irq spinlock + */ +static INLINE mali_bool kbasep_js_ctx_attr_is_attr_on_runpool(struct kbase_device *kbdev, enum kbasep_js_ctx_attr attribute) +{ + /* In general, attributes are 'on' when they have a non-zero refcount (note: the refcount will never be < 0) */ + return (mali_bool) kbasep_js_ctx_attr_count_on_runpool(kbdev, attribute); +} + +/** + * Requires: + * - jsctx mutex + */ +static INLINE mali_bool kbasep_js_ctx_attr_is_attr_on_ctx(struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + /* In general, attributes are 'on' when they have a refcount (which should never be < 0) */ + return (mali_bool) (js_kctx_info->ctx.ctx_attr_ref_count[attribute]); +} + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_DEFS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_defs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..6a9c059911894712fe17801bcbf73d9374789aa9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_defs.h @@ -0,0 +1,482 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js.h + * Job Scheduler Type Definitions + */ + +#ifndef _KBASE_JS_DEFS_H_ +#define _KBASE_JS_DEFS_H_ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js + * @{ + */ +/* Forward decls */ +struct kbase_device; +struct kbase_jd_atom; + + +/* Types used by the policies must go here */ +enum { + /** Context will not submit any jobs */ + KBASE_CTX_FLAG_SUBMIT_DISABLED = (1u << 0), + + /** Set if the context uses an address space and should be kept scheduled in */ + KBASE_CTX_FLAG_PRIVILEGED = (1u << 1), + + /** Kernel-side equivalent of BASE_CONTEXT_HINT_ONLY_COMPUTE. Non-mutable after creation flags set */ + KBASE_CTX_FLAG_HINT_ONLY_COMPUTE = (1u << 2) + + /* NOTE: Add flags for other things, such as 'is scheduled', and 'is dying' */ +}; + +typedef u32 kbase_context_flags; + +struct kbasep_atom_req { + base_jd_core_req core_req; + kbase_context_flags ctx_req; + u32 device_nr; +}; + +#include "mali_kbase_js_policy_cfs.h" + +/* Wrapper Interface - doxygen is elsewhere */ +union kbasep_js_policy { +#ifdef KBASE_JS_POLICY_AVAILABLE_FCFS + struct kbasep_js_policy_fcfs fcfs; +#endif +#ifdef KBASE_JS_POLICY_AVAILABLE_CFS + struct kbasep_js_policy_cfs cfs; +#endif +}; + +/* Wrapper Interface - doxygen is elsewhere */ +union kbasep_js_policy_ctx_info { +#ifdef KBASE_JS_POLICY_AVAILABLE_FCFS + struct kbasep_js_policy_fcfs_ctx fcfs; +#endif +#ifdef KBASE_JS_POLICY_AVAILABLE_CFS + struct kbasep_js_policy_cfs_ctx cfs; +#endif +}; + +/* Wrapper Interface - doxygen is elsewhere */ +union kbasep_js_policy_job_info { +#ifdef KBASE_JS_POLICY_AVAILABLE_FCFS + struct kbasep_js_policy_fcfs_job fcfs; +#endif +#ifdef KBASE_JS_POLICY_AVAILABLE_CFS + struct kbasep_js_policy_cfs_job cfs; +#endif +}; + + +/** Callback function run on all of a context's jobs registered with the Job + * Scheduler */ +typedef void (*kbasep_js_policy_ctx_job_cb)(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +/** + * @brief Maximum number of jobs that can be submitted to a job slot whilst + * inside the IRQ handler. + * + * This is important because GPU NULL jobs can complete whilst the IRQ handler + * is running. Otherwise, it potentially allows an unlimited number of GPU NULL + * jobs to be submitted inside the IRQ handler, which increases IRQ latency. + */ +#define KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ 2 + +/** + * @brief the IRQ_THROTTLE time in microseconds + * + * This will be converted via the GPU's clock frequency into a cycle-count. + * + * @note we can make an estimate of the GPU's frequency by periodically + * sampling its CYCLE_COUNT register + */ +#define KBASE_JS_IRQ_THROTTLE_TIME_US 20 + +/** + * @brief Context attributes + * + * Each context attribute can be thought of as a boolean value that caches some + * state information about either the runpool, or the context: + * - In the case of the runpool, it is a cache of "Do any contexts owned by + * the runpool have attribute X?" + * - In the case of a context, it is a cache of "Do any atoms owned by the + * context have attribute X?" + * + * The boolean value of the context attributes often affect scheduling + * decisions, such as affinities to use and job slots to use. + * + * To accomodate changes of state in the context, each attribute is refcounted + * in the context, and in the runpool for all running contexts. Specifically: + * - The runpool holds a refcount of how many contexts in the runpool have this + * attribute. + * - The context holds a refcount of how many atoms have this attribute. + * + * Examples of use: + * - Finding out when there are a mix of @ref BASE_CONTEXT_HINT_ONLY_COMPUTE + * and ! @ref BASE_CONTEXT_HINT_ONLY_COMPUTE contexts in the runpool + */ +enum kbasep_js_ctx_attr { + /** Attribute indicating a context that contains Compute jobs. That is, + * @ref BASE_CONTEXT_HINT_ONLY_COMPUTE is \b set and/or the context has jobs of type + * @ref BASE_JD_REQ_ONLY_COMPUTE + * + * @note A context can be both 'Compute' and 'Non Compute' if it contains + * both types of jobs. + */ + KBASEP_JS_CTX_ATTR_COMPUTE, + + /** Attribute indicating a context that contains Non-Compute jobs. That is, + * the context has some jobs that are \b not of type @ref + * BASE_JD_REQ_ONLY_COMPUTE. The context usually has + * BASE_CONTEXT_HINT_COMPUTE \b clear, but this depends on the HW + * workarounds in use in the Job Scheduling Policy. + * + * @note A context can be both 'Compute' and 'Non Compute' if it contains + * both types of jobs. + */ + KBASEP_JS_CTX_ATTR_NON_COMPUTE, + + /** Attribute indicating that a context contains compute-job atoms that + * aren't restricted to a coherent group, and can run on all cores. + * + * Specifically, this is when the atom's \a core_req satisfy: + * - (\a core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T) // uses slot 1 or slot 2 + * - && !(\a core_req & BASE_JD_REQ_COHERENT_GROUP) // not restricted to coherent groups + * + * Such atoms could be blocked from running if one of the coherent groups + * is being used by another job slot, so tracking this context attribute + * allows us to prevent such situations. + * + * @note This doesn't take into account the 1-coregroup case, where all + * compute atoms would effectively be able to run on 'all cores', but + * contexts will still not always get marked with this attribute. Instead, + * it is the caller's responsibility to take into account the number of + * coregroups when interpreting this attribute. + * + * @note Whilst Tiler atoms are normally combined with + * BASE_JD_REQ_COHERENT_GROUP, it is possible to send such atoms without + * BASE_JD_REQ_COHERENT_GROUP set. This is an unlikely case, but it's easy + * enough to handle anyway. + */ + KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES, + + /** Must be the last in the enum */ + KBASEP_JS_CTX_ATTR_COUNT +}; + +enum { + /** Bit indicating that new atom should be started because this atom completed */ + KBASE_JS_ATOM_DONE_START_NEW_ATOMS = (1u << 0), + /** Bit indicating that the atom was evicted from the JS_NEXT registers */ + KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT = (1u << 1) +}; + +/** Combination of KBASE_JS_ATOM_DONE_<...> bits */ +typedef u32 kbasep_js_atom_done_code; + +/** + * Data used by the scheduler that is unique for each Address Space. + * + * This is used in IRQ context and kbasep_js_device_data::runpoool_irq::lock + * must be held whilst accessing this data (inculding reads and atomic + * decisions based on the read). + */ +struct kbasep_js_per_as_data { + /** + * Ref count of whether this AS is busy, and must not be scheduled out + * + * When jobs are running this is always positive. However, it can still be + * positive when no jobs are running. If all you need is a heuristic to + * tell you whether jobs might be running, this should be sufficient. + */ + int as_busy_refcount; + + /** Pointer to the current context on this address space, or NULL for no context */ + struct kbase_context *kctx; +}; + +/** + * @brief KBase Device Data Job Scheduler sub-structure + * + * This encapsulates the current context of the Job Scheduler on a particular + * device. This context is global to the device, and is not tied to any + * particular struct kbase_context running on the device. + * + * nr_contexts_running and as_free are optimized for packing together (by making + * them smaller types than u32). The operations on them should rarely involve + * masking. The use of signed types for arithmetic indicates to the compiler that + * the value will not rollover (which would be undefined behavior), and so under + * the Total License model, it is free to make optimizations based on that (i.e. + * to remove masking). + */ +struct kbasep_js_device_data { + /** Sub-structure to collect together Job Scheduling data used in IRQ context */ + struct runpool_irq { + /** + * Lock for accessing Job Scheduling data used in IRQ context + * + * This lock must be held whenever this data is accessed (read, or + * write). Even for read-only access, memory barriers would be needed. + * In any case, it is likely that decisions based on only reading must + * also be atomic with respect to data held here and elsewhere in the + * Job Scheduler. + * + * This lock must also be held for accessing: + * - kbase_context::as_nr + * - kbase_device::jm_slots + * - Parts of the kbasep_js_policy, dependent on the policy (refer to + * the policy in question for more information) + * - Parts of kbasep_js_policy_ctx_info, dependent on the policy (refer to + * the policy in question for more information) + */ + spinlock_t lock; + + /** Bitvector indicating whether a currently scheduled context is allowed to submit jobs. + * When bit 'N' is set in this, it indicates whether the context bound to address space + * 'N' (per_as_data[N].kctx) is allowed to submit jobs. + * + * It is placed here because it's much more memory efficient than having a mali_bool8 in + * struct kbasep_js_per_as_data to store this flag */ + u16 submit_allowed; + + /** Context Attributes: + * Each is large enough to hold a refcount of the number of contexts + * that can fit into the runpool. This is currently BASE_MAX_NR_AS + * + * Note that when BASE_MAX_NR_AS==16 we need 5 bits (not 4) to store + * the refcount. Hence, it's not worthwhile reducing this to + * bit-manipulation on u32s to save space (where in contrast, 4 bit + * sub-fields would be easy to do and would save space). + * + * Whilst this must not become negative, the sign bit is used for: + * - error detection in debug builds + * - Optimization: it is undefined for a signed int to overflow, and so + * the compiler can optimize for that never happening (thus, no masking + * is required on updating the variable) */ + s8 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT]; + + /** Data that is unique for each AS */ + struct kbasep_js_per_as_data per_as_data[BASE_MAX_NR_AS]; + + /* + * Affinity management and tracking + */ + /** Bitvector to aid affinity checking. Element 'n' bit 'i' indicates + * that slot 'n' is using core i (i.e. slot_affinity_refcount[n][i] > 0) */ + u64 slot_affinities[BASE_JM_MAX_NR_SLOTS]; + /** Bitvector indicating which slots \em might have atoms blocked on + * them because otherwise they'd violate affinity restrictions */ + u16 slots_blocked_on_affinity; + /** Refcount for each core owned by each slot. Used to generate the + * slot_affinities array of bitvectors + * + * The value of the refcount will not exceed BASE_JM_SUBMIT_SLOTS, + * because it is refcounted only when a job is definitely about to be + * submitted to a slot, and is de-refcounted immediately after a job + * finishes */ + s8 slot_affinity_refcount[BASE_JM_MAX_NR_SLOTS][64]; + } runpool_irq; + + /** + * Run Pool mutex, for managing contexts within the runpool. + * Unless otherwise specified, you must hold this lock whilst accessing any + * members that follow + * + * In addition, this is used to access: + * - the kbasep_js_kctx_info::runpool substructure + */ + struct mutex runpool_mutex; + + /** + * Queue Lock, used to access the Policy's queue of contexts independently + * of the Run Pool. + * + * Of course, you don't need the Run Pool lock to access this. + */ + struct mutex queue_mutex; + + u16 as_free; /**< Bitpattern of free Address Spaces */ + + /** Number of currently scheduled user contexts (excluding ones that are not submitting jobs) */ + s8 nr_user_contexts_running; + /** Number of currently scheduled contexts (including ones that are not submitting jobs) */ + s8 nr_all_contexts_running; + + /** + * Policy-specific information. + * + * Refer to the structure defined by the current policy to determine which + * locks must be held when accessing this. + */ + union kbasep_js_policy policy; + + /** Core Requirements to match up with base_js_atom's core_req memeber + * @note This is a write-once member, and so no locking is required to read */ + base_jd_core_req js_reqs[BASE_JM_MAX_NR_SLOTS]; + + u32 scheduling_tick_ns; /**< Value for KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS */ + u32 soft_stop_ticks; /**< Value for KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS */ + u32 soft_stop_ticks_cl; /**< Value for KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL */ + u32 hard_stop_ticks_ss; /**< Value for KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS */ + u32 hard_stop_ticks_cl; /**< Value for KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL */ + u32 hard_stop_ticks_nss; /**< Value for KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS */ + u32 gpu_reset_ticks_ss; /**< Value for KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS */ + u32 gpu_reset_ticks_cl; /**< Value for KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL */ + u32 gpu_reset_ticks_nss; /**< Value for KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS */ + u32 ctx_timeslice_ns; /**< Value for KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS */ + u32 cfs_ctx_runtime_init_slices; /**< Value for DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES */ + u32 cfs_ctx_runtime_min_slices; /**< Value for DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES */ + + /** List of suspended soft jobs */ + struct list_head suspended_soft_jobs_list; + +#ifdef CONFIG_MALI_DEBUG + /* Support soft-stop on a single context */ + mali_bool softstop_always; +#endif /* CONFIG_MALI_DEBUG */ + /** The initalized-flag is placed at the end, to avoid cache-pollution (we should + * only be using this during init/term paths). + * @note This is a write-once member, and so no locking is required to read */ + int init_status; + struct mutex mtk_sj_mutex; +}; + +/** + * @brief KBase Context Job Scheduling information structure + * + * This is a substructure in the struct kbase_context that encapsulates all the + * scheduling information. + */ +struct kbasep_js_kctx_info { + /** + * Runpool substructure. This must only be accessed whilst the Run Pool + * mutex ( kbasep_js_device_data::runpool_mutex ) is held. + * + * In addition, the kbasep_js_device_data::runpool_irq::lock may need to be + * held for certain sub-members. + * + * @note some of the members could be moved into struct kbasep_js_device_data for + * improved d-cache/tlb efficiency. + */ + struct { + union kbasep_js_policy_ctx_info policy_ctx; /**< Policy-specific context */ + } runpool; + + /** + * Job Scheduler Context information sub-structure. These members are + * accessed regardless of whether the context is: + * - In the Policy's Run Pool + * - In the Policy's Queue + * - Not queued nor in the Run Pool. + * + * You must obtain the jsctx_mutex before accessing any other members of + * this substructure. + * + * You may not access any of these members from IRQ context. + */ + struct { + struct mutex jsctx_mutex; /**< Job Scheduler Context lock */ + + /** Number of jobs ready to run - does \em not include the jobs waiting in + * the dispatcher, and dependency-only jobs. See kbase_jd_context::job_nr + * for such jobs*/ + u32 nr_jobs; + + /** Context Attributes: + * Each is large enough to hold a refcount of the number of atoms on + * the context. **/ + u32 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT]; + + kbase_context_flags flags; + /* NOTE: Unify the following flags into kbase_context_flags */ + /** + * Is the context scheduled on the Run Pool? + * + * This is only ever updated whilst the jsctx_mutex is held. + */ + mali_bool is_scheduled; + /** + * Wait queue to wait for is_scheduled state changes. + * */ + wait_queue_head_t is_scheduled_wait; + + mali_bool is_dying; /**< Is the context in the process of being evicted? */ + } ctx; + + /* The initalized-flag is placed at the end, to avoid cache-pollution (we should + * only be using this during init/term paths) */ + int init_status; +}; + +/** Subset of atom state that can be available after jd_done_nolock() is called + * on that atom. A copy must be taken via kbasep_js_atom_retained_state_copy(), + * because the original atom could disappear. */ +struct kbasep_js_atom_retained_state { + /** Event code - to determine whether the atom has finished */ + enum base_jd_event_code event_code; + /** core requirements */ + base_jd_core_req core_req; + /** Job Slot to retry submitting to if submission from IRQ handler failed */ + int retry_submit_on_slot; + /* Core group atom was executed on */ + u32 device_nr; + +}; + +/** + * Value signifying 'no retry on a slot required' for: + * - kbase_js_atom_retained_state::retry_submit_on_slot + * - kbase_jd_atom::retry_submit_on_slot + */ +#define KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID (-1) + +/** + * base_jd_core_req value signifying 'invalid' for a kbase_jd_atom_retained_state. + * + * @see kbase_atom_retained_state_is_valid() + */ +#define KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID BASE_JD_REQ_DEP + +/** + * @brief The JS timer resolution, in microseconds + * + * Any non-zero difference in time will be at least this size. + */ +#define KBASEP_JS_TICK_RESOLUTION_US 1 + +#endif /* _KBASE_JS_DEFS_H_ */ + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy.h new file mode 100644 index 0000000000000000000000000000000000000000..6c777a92000dfaa396a4ea4340ac68231a0a8be1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy.h @@ -0,0 +1,767 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_policy.h + * Job Scheduler Policy APIs. + */ + +#ifndef _KBASE_JS_POLICY_H_ +#define _KBASE_JS_POLICY_H_ + +/** + * @page page_kbase_js_policy Job Scheduling Policies + * The Job Scheduling system is described in the following: + * - @subpage page_kbase_js_policy_overview + * - @subpage page_kbase_js_policy_operation + * + * The API details are as follows: + * - @ref kbase_jm + * - @ref kbase_js + * - @ref kbase_js_policy + */ + +/** + * @page page_kbase_js_policy_overview Overview of the Policy System + * + * The Job Scheduler Policy manages: + * - The assigning of KBase Contexts to GPU Address Spaces (\em ASs) + * - The choosing of Job Chains (\em Jobs) from a KBase context, to run on the + * GPU's Job Slots (\em JSs). + * - The amount of \em time a context is assigned to (scheduled on) an + * Address Space + * - The amount of \em time a Job spends running on the GPU + * + * The Policy implements this management via 2 components: + * - A Policy Queue, which manages a set of contexts that are ready to run, + * but not currently running. + * - A Policy Run Pool, which manages the currently running contexts (one per Address + * Space) and the jobs to run on the Job Slots. + * + * Each Graphics Process in the system has at least one KBase Context. Therefore, + * the Policy Queue can be seen as a queue of Processes waiting to run Jobs on + * the GPU. + * + * + * @dotfile policy_overview.dot "Diagram showing a very simplified overview of the Policy System. IRQ handling, soft/hard-stopping, contexts re-entering the system and Policy details are omitted" + * + * The main operations on the queue are: + * - Enqueuing a Context to it + * - Dequeuing a Context from it, to run it. + * - Note: requeuing a context is much the same as enqueuing a context, but + * occurs when a context is scheduled out of the system to allow other contexts + * to run. + * + * These operations have much the same meaning for the Run Pool - Jobs are + * dequeued to run on a Jobslot, and requeued when they are scheduled out of + * the GPU. + * + * @note This is an over-simplification of the Policy APIs - there are more + * operations than 'Enqueue'/'Dequeue', and a Dequeue from the Policy Queue + * takes at least two function calls: one to Dequeue from the Queue, one to add + * to the Run Pool. + * + * As indicated on the diagram, Jobs permanently leave the scheduling system + * when they are completed, otherwise they get dequeued/requeued until this + * happens. Similarly, Contexts leave the scheduling system when their jobs + * have all completed. However, Contexts may later return to the scheduling + * system (not shown on the diagram) if more Bags of Jobs are submitted to + * them. + */ + +/** + * @page page_kbase_js_policy_operation Policy Operation + * + * We describe the actions that the Job Scheduler Core takes on the Policy in + * the following cases: + * - The IRQ Path + * - The Job Submission Path + * - The High Priority Job Submission Path + * + * This shows how the Policy APIs will be used by the Job Scheduler core. + * + * The following diagram shows an example Policy that contains a Low Priority + * queue, and a Real-time (High Priority) Queue. The RT queue is examined + * before the LowP one on dequeuing from the head. The Low Priority Queue is + * ordered by time, and the RT queue is ordered by RT-priority, and then by + * time. In addition, it shows that the Job Scheduler Core will start a + * Soft-Stop Timer (SS-Timer) when it dequeue's and submits a job. The + * Soft-Stop time is set by a global configuration value, and must be a value + * appropriate for the policy. For example, this could include "don't run a + * soft-stop timer" for a First-Come-First-Served (FCFS) policy. + * + * + * @dotfile policy_operation_diagram.dot "Diagram showing the objects managed by an Example Policy, and the operations made upon these objects by the Job Scheduler Core." + * + * @section sec_kbase_js_policy_operation_prio Dealing with Priority + * + * Priority applies both to a context as a whole, and to the jobs within a + * context. The jobs specify a priority in the base_jd_atom::prio member, which + * is relative to that of the context. A positive setting indicates a reduction + * in priority, whereas a negative setting indicates a boost in priority. Of + * course, the boost in priority should only be honoured when the originating + * process has sufficient priviledges, and should be ignored for unpriviledged + * processes. The meaning of the combined priority value is up to the policy + * itself, and could be a logarithmic scale instead of a linear scale (e.g. the + * policy could implement an increase/decrease in priority by 1 results in an + * increase/decrease in \em proportion of time spent scheduled in by 25%, an + * effective change in timeslice by 11%). + * + * It is up to the policy whether a boost in priority boosts the priority of + * the entire context (e.g. to such an extent where it may pre-empt other + * running contexts). If it chooses to do this, the Policy must make sure that + * only the high-priority jobs are run, and that the context is scheduled out + * once only low priority jobs remain. This ensures that the low priority jobs + * within the context do not gain from the priority boost, yet they still get + * scheduled correctly with respect to other low priority contexts. + * + * + * @section sec_kbase_js_policy_operation_irq IRQ Path + * + * The following happens on the IRQ path from the Job Scheduler Core: + * - Note the slot that completed (for later) + * - Log the time spent by the job (and implicitly, the time spent by the + * context) + * - call kbasep_js_policy_log_job_result() in the context of the irq + * handler. + * - This must happen regardless of whether the job completed successfully or + * not (otherwise the context gets away with DoS'ing the system with faulty jobs) + * - What was the result of the job? + * - If Completed: job is just removed from the system + * - If Hard-stop or failure: job is removed from the system + * - If Soft-stop: queue the book-keeping work onto a work-queue: have a + * work-queue call kbasep_js_policy_enqueue_job() + * - Check the timeslice used by the owning context + * - call kbasep_js_policy_should_remove_ctx() in the context of the irq + * handler. + * - If this returns true, clear the "allowed" flag. + * - Check the ctx's flags for "allowed", "has jobs to run" and "is running + * jobs" + * - And so, should the context stay scheduled in? + * - If No, push onto a work-queue the work of scheduling out the old context, + * and getting a new one. That is: + * - kbasep_js_policy_runpool_remove_ctx() on old_ctx + * - kbasep_js_policy_enqueue_ctx() on old_ctx + * - kbasep_js_policy_dequeue_head_ctx() to get new_ctx + * - kbasep_js_policy_runpool_add_ctx() on new_ctx + * - (all of this work is deferred on a work-queue to keep the IRQ handler quick) + * - If there is space in the completed job slots' HEAD/NEXT registers, run the next job: + * - kbasep_js_policy_dequeue_job() in the context of the irq + * handler with core_req set to that of the completing slot + * - if this returned MALI_TRUE, submit the job to the completed slot. + * - This is repeated until kbasep_js_policy_dequeue_job() returns + * MALI_FALSE, or the job slot has a job queued on both the HEAD and NEXT registers. + * - If kbasep_js_policy_dequeue_job() returned false, submit some work to + * the work-queue to retry from outside of IRQ context (calling + * kbasep_js_policy_dequeue_job() from a work-queue). + * + * Since the IRQ handler submits new jobs \em and re-checks the IRQ_RAWSTAT, + * this sequence could loop a large number of times: this could happen if + * the jobs submitted completed on the GPU very quickly (in a few cycles), such + * as GPU NULL jobs. Then, the HEAD/NEXT registers will always be free to take + * more jobs, causing us to loop until we run out of jobs. + * + * To mitigate this, we must limit the number of jobs submitted per slot during + * the IRQ handler - for example, no more than 2 jobs per slot per IRQ should + * be sufficient (to fill up the HEAD + NEXT registers in normal cases). For + * Mali-T600 with 3 job slots, this means that up to 6 jobs could be submitted per + * slot. Note that IRQ Throttling can make this situation commonplace: 6 jobs + * could complete but the IRQ for each of them is delayed by the throttling. By + * the time you get the IRQ, all 6 jobs could've completed, meaning you can + * submit jobs to fill all 6 HEAD+NEXT registers again. + * + * @note As much work is deferred as possible, which includes the scheduling + * out of a context and scheduling in a new context. However, we can still make + * starting a single high-priorty context quick despite this: + * - On Mali-T600 family, there is one more AS than JSs. + * - This means we can very quickly schedule out one AS, no matter what the + * situation (because there will always be one AS that's not currently running + * on the job slot - it can only have a job in the NEXT register). + * - Even with this scheduling out, fair-share can still be guaranteed e.g. by + * a timeline-based Completely Fair Scheduler. + * - When our high-priority context comes in, we can do this quick-scheduling + * out immediately, and then schedule in the high-priority context without having to block. + * - This all assumes that the context to schedule out is of lower + * priority. Otherwise, we will have to block waiting for some other low + * priority context to finish its jobs. Note that it's likely (but not + * impossible) that the high-priority context \b is running jobs, by virtue of + * it being high priority. + * - Therefore, we can give a high liklihood that on Mali-T600 at least one + * high-priority context can be started very quickly. For the general case, we + * can guarantee starting (no. ASs) - (no. JSs) high priority contexts + * quickly. In any case, there is a high likelihood that we're able to start + * more than one high priority context quickly. + * + * In terms of the functions used in the IRQ handler directly, these are the + * perfomance considerations: + * - kbase_js_policy_log_job_result(): + * - This is just adding to a 64-bit value (possibly even a 32-bit value if we + * only store the time the job's recently spent - see below on 'priority weighting') + * - For priority weighting, a divide operation ('div') could happen, but + * this can happen in a deferred context (outside of IRQ) when scheduling out + * the ctx; as per our Engineering Specification, the contexts of different + * priority still stay scheduled in for the same timeslice, but higher priority + * ones scheduled back in more often. + * - That is, the weighted and unweighted times must be stored separately, and + * the weighted time is only updated \em outside of IRQ context. + * - Of course, this divide is more likely to be a 'multiply by inverse of the + * weight', assuming that the weight (priority) doesn't change. + * - kbasep_js_policy_should_remove_ctx(): + * - This is usually just a comparison of the stored time value against some + * maximum value. + * + * @note all deferred work can be wrapped up into one call - we usually need to + * indicate that a job/bag is done outside of IRQ context anyway. + * + * + * + * @section sec_kbase_js_policy_operation_submit Submission path + * + * Start with a Context with no jobs present, and assume equal priority of all + * contexts in the system. The following work all happens outside of IRQ + * Context : + * - As soon as job is made 'ready to 'run', then is must be registerd with the Job + * Scheduler Policy: + * - 'Ready to run' means they've satisified their dependencies in the + * Kernel-side Job Dispatch system. + * - Call kbasep_js_policy_enqueue_job() + * - This indicates that the job should be scheduled (it is ready to run). + * - As soon as a ctx changes from having 0 jobs 'ready to run' to >0 jobs + * 'ready to run', we enqueue the context on the policy queue: + * - Call kbasep_js_policy_enqueue_ctx() + * - This indicates that the \em ctx should be scheduled (it is ready to run) + * + * Next, we need to handle adding a context to the Run Pool - if it's sensible + * to do so. This can happen due to two reasons: + * -# A context is enqueued as above, and there are ASs free for it to run on + * (e.g. it is the first context to be run, in which case it can be added to + * the Run Pool immediately after enqueuing on the Policy Queue) + * -# A previous IRQ caused another ctx to be scheduled out, requiring that the + * context at the head of the queue be scheduled in. Such steps would happen in + * a work queue (work deferred from the IRQ context). + * + * In both cases, we'd handle it as follows: + * - Get the context at the Head of the Policy Queue: + * - Call kbasep_js_policy_dequeue_head_ctx() + * - Assign the Context an Address Space (Assert that there will be one free, + * given the above two reasons) + * - Add this context to the Run Pool: + * - Call kbasep_js_policy_runpool_add_ctx() + * - Now see if a job should be run: + * - Mostly, this will be done in the IRQ handler at the completion of a + * previous job. + * - However, there are two cases where this cannot be done: a) The first job + * enqueued to the system (there is no previous IRQ to act upon) b) When jobs + * are submitted at a low enough rate to not fill up all Job Slots (or, not to + * fill both the 'HEAD' and 'NEXT' registers in the job-slots) + * - Hence, on each ctx and job submission we should try to see if we + * can run a job: + * - For each job slot that has free space (in NEXT or HEAD+NEXT registers): + * - Call kbasep_js_policy_dequeue_job() with core_req set to that of the + * slot + * - if we got one, submit it to the job slot. + * - This is repeated until kbasep_js_policy_dequeue_job() returns + * MALI_FALSE, or the job slot has a job queued on both the HEAD and NEXT registers. + * + * The above case shows that we should attempt to run jobs in cases where a) a ctx + * has been added to the Run Pool, and b) new jobs have been added to a context + * in the Run Pool: + * - In the latter case, the context is in the runpool because it's got a job + * ready to run, or is already running a job + * - We could just wait until the IRQ handler fires, but for certain types of + * jobs this can take comparatively a long time to complete, e.g. GLES FS jobs + * generally take much longer to run that GLES CS jobs, which are vertex shader + * jobs. + * - Therefore, when a new job appears in the ctx, we must check the job-slots + * to see if they're free, and run the jobs as before. + * + * + * + * @section sec_kbase_js_policy_operation_submit_hipri Submission path for High Priority Contexts + * + * For High Priority Contexts on Mali-T600, we can make sure that at least 1 of + * them can be scheduled in immediately to start high prioriy jobs. In general, + * (no. ASs) - (no JSs) high priority contexts may be started immediately. The + * following describes how this happens: + * + * Similar to the previous section, consider what happens with a high-priority + * context (a context with a priority higher than that of any in the Run Pool) + * that starts out with no jobs: + * - A job becomes ready to run on the context, and so we enqueue the context + * on the Policy's Queue. + * - However, we'd like to schedule in this context immediately, instead of + * waiting for one of the Run Pool contexts' timeslice to expire + * - The policy's Enqueue function must detect this (because it is the policy + * that embodies the concept of priority), and take appropriate action + * - That is, kbasep_js_policy_enqueue_ctx() should check the Policy's Run + * Pool to see if a lower priority context should be scheduled out, and then + * schedule in the High Priority context. + * - For Mali-T600, we can always pick a context to schedule out immediately + * (because there are more ASs than JSs), and so scheduling out a victim context + * and scheduling in the high priority context can happen immediately. + * - If a policy implements fair-sharing, then this can still ensure the + * victim later on gets a fair share of the GPU. + * - As a note, consider whether the victim can be of equal/higher priority + * than the incoming context: + * - Usually, higher priority contexts will be the ones currently running + * jobs, and so the context with the lowest priority is usually not running + * jobs. + * - This makes it likely that the victim context is low priority, but + * it's not impossible for it to be a high priority one: + * - Suppose 3 high priority contexts are submitting only FS jobs, and one low + * priority context submitting CS jobs. Then, the context not running jobs will + * be one of the hi priority contexts (because only 2 FS jobs can be + * queued/running on the GPU HW for Mali-T600). + * - The problem can be mitigated by extra action, but it's questionable + * whether we need to: we already have a high likelihood that there's at least + * one high priority context - that should be good enough. + * - And so, this method makes sure that at least one high priority context + * can be started very quickly, but more than one high priority contexts could be + * delayed (up to one timeslice). + * - To improve this, use a GPU with a higher number of Address Spaces vs Job + * Slots. + * - At this point, let's assume this high priority context has been scheduled + * in immediately. The next step is to ensure it can start some jobs quickly. + * - It must do this by Soft-Stopping jobs on any of the Job Slots that it can + * submit to. + * - The rest of the logic for starting the jobs is taken care of by the IRQ + * handler. All the policy needs to do is ensure that + * kbasep_js_policy_dequeue_job() will return the jobs from the high priority + * context. + * + * @note in SS state, we currently only use 2 job-slots (even for T608, but + * this might change in future). In this case, it's always possible to schedule + * out 2 ASs quickly (their jobs won't be in the HEAD registers). At the same + * time, this maximizes usage of the job-slots (only 2 are in use), because you + * can guarantee starting of the jobs from the High Priority contexts immediately too. + * + * + * + * @section sec_kbase_js_policy_operation_notes Notes + * + * - In this design, a separate 'init' is needed from dequeue/requeue, so that + * information can be retained between the dequeue/requeue calls. For example, + * the total time spent for a context/job could be logged between + * dequeue/requeuing, to implement Fair Sharing. In this case, 'init' just + * initializes that information to some known state. + * + * + * + */ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js_policy Job Scheduler Policy APIs + * @{ + * + * Refer to @ref page_kbase_js_policy for an overview and detailed operation of + * the Job Scheduler Policy and its use from the Job Scheduler Core. + */ + +/** + * @brief Job Scheduler Policy structure + */ +union kbasep_js_policy; + +/** + * @brief Initialize the Job Scheduler Policy + */ +mali_error kbasep_js_policy_init(struct kbase_device *kbdev); + +/** + * @brief Terminate the Job Scheduler Policy + */ +void kbasep_js_policy_term(union kbasep_js_policy *js_policy); + +/** + * @addtogroup kbase_js_policy_ctx Job Scheduler Policy, Context Management API + * @{ + * + * Refer to @ref page_kbase_js_policy for an overview and detailed operation of + * the Job Scheduler Policy and its use from the Job Scheduler Core. + */ + +/** + * @brief Job Scheduler Policy Ctx Info structure + * + * This structure is embedded in the struct kbase_context structure. It is used to: + * - track information needed for the policy to schedule the context (e.g. time + * used, OS priority etc.) + * - link together kbase_contexts into a queue, so that a struct kbase_context can be + * obtained as the container of the policy ctx info. This allows the API to + * return what "the next context" should be. + * - obtain other information already stored in the struct kbase_context for + * scheduling purposes (e.g process ID to get the priority of the originating + * process) + */ +union kbasep_js_policy_ctx_info; + +/** + * @brief Initialize a ctx for use with the Job Scheduler Policy + * + * This effectively initializes the union kbasep_js_policy_ctx_info structure within + * the struct kbase_context (itself located within the kctx->jctx.sched_info structure). + */ +mali_error kbasep_js_policy_init_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Terminate resources associated with using a ctx in the Job Scheduler + * Policy. + */ +void kbasep_js_policy_term_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Enqueue a context onto the Job Scheduler Policy Queue + * + * If the context enqueued has a priority higher than any in the Run Pool, then + * it is the Policy's responsibility to decide whether to schedule out a low + * priority context from the Run Pool to allow the high priority context to be + * scheduled in. + * + * If the context has the privileged flag set, it will always be kept at the + * head of the queue. + * + * The caller will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + * The caller will be holding kbasep_js_device_data::queue_mutex. + */ +void kbasep_js_policy_enqueue_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Dequeue a context from the Head of the Job Scheduler Policy Queue + * + * The caller will be holding kbasep_js_device_data::queue_mutex. + * + * @return MALI_TRUE if a context was available, and *kctx_ptr points to + * the kctx dequeued. + * @return MALI_FALSE if no contexts were available. + */ +mali_bool kbasep_js_policy_dequeue_head_ctx(union kbasep_js_policy *js_policy, struct kbase_context ** const kctx_ptr); + +/** + * @brief Evict a context from the Job Scheduler Policy Queue + * + * This is only called as part of destroying a kbase_context. + * + * There are many reasons why this might fail during the lifetime of a + * context. For example, the context is in the process of being scheduled. In + * that case a thread doing the scheduling might have a pointer to it, but the + * context is neither in the Policy Queue, nor is it in the Run + * Pool. Crucially, neither the Policy Queue, Run Pool, or the Context itself + * are locked. + * + * Hence to find out where in the system the context is, it is important to do + * more than just check the kbasep_js_kctx_info::ctx::is_scheduled member. + * + * The caller will be holding kbasep_js_device_data::queue_mutex. + * + * @return MALI_TRUE if the context was evicted from the Policy Queue + * @return MALI_FALSE if the context was not found in the Policy Queue + */ +mali_bool kbasep_js_policy_try_evict_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Call a function on all jobs belonging to a non-queued, non-running + * context, optionally detaching the jobs from the context as it goes. + * + * At the time of the call, the context is guarenteed to be not-currently + * scheduled on the Run Pool (is_scheduled == MALI_FALSE), and not present in + * the Policy Queue. This is because one of the following functions was used + * recently on the context: + * - kbasep_js_policy_evict_ctx() + * - kbasep_js_policy_runpool_remove_ctx() + * + * In both cases, no subsequent call was made on the context to any of: + * - kbasep_js_policy_runpool_add_ctx() + * - kbasep_js_policy_enqueue_ctx() + * + * Due to the locks that might be held at the time of the call, the callback + * may need to defer work on a workqueue to complete its actions (e.g. when + * cancelling jobs) + * + * \a detach_jobs must only be set when cancelling jobs (which occurs as part + * of context destruction). + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + */ +void kbasep_js_policy_foreach_ctx_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, + kbasep_js_policy_ctx_job_cb callback, mali_bool detach_jobs); + +/** + * @brief Add a context to the Job Scheduler Policy's Run Pool + * + * If the context enqueued has a priority higher than any in the Run Pool, then + * it is the Policy's responsibility to decide whether to schedule out low + * priority jobs that are currently running on the GPU. + * + * The number of contexts present in the Run Pool will never be more than the + * number of Address Spaces. + * + * The following guarentees are made about the state of the system when this + * is called: + * - kctx->as_nr member is valid + * - the context has its submit_allowed flag set + * - kbasep_js_device_data::runpool_irq::per_as_data[kctx->as_nr] is valid + * - The refcount of the context is guarenteed to be zero. + * - kbasep_js_kctx_info::ctx::is_scheduled will be MALI_TRUE. + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it will be holding kbasep_js_device_data::runpool_mutex. + * - it will be holding kbasep_js_device_data::runpool_irq::lock (a spinlock) + * + * Due to a spinlock being held, this function must not call any APIs that sleep. + */ +void kbasep_js_policy_runpool_add_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Remove a context from the Job Scheduler Policy's Run Pool + * + * The kctx->as_nr member is valid and the context has its submit_allowed flag + * set when this is called. The state of + * kbasep_js_device_data::runpool_irq::per_as_data[kctx->as_nr] is also + * valid. The refcount of the context is guarenteed to be zero. + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it will be holding kbasep_js_device_data::runpool_mutex. + * - it will be holding kbasep_js_device_data::runpool_irq::lock (a spinlock) + * + * Due to a spinlock being held, this function must not call any APIs that sleep. + */ +void kbasep_js_policy_runpool_remove_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Indicate whether a context should be removed from the Run Pool + * (should be scheduled out). + * + * The kbasep_js_device_data::runpool_irq::lock will be held by the caller. + * + * @note This API is called from IRQ context. + */ +mali_bool kbasep_js_policy_should_remove_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Synchronize with any timers acting upon the runpool + * + * The policy should check whether any timers it owns should be running. If + * they should not, the policy must cancel such timers and ensure they are not + * re-run by the time this function finishes. + * + * In particular, the timers must not be running when there are no more contexts + * on the runpool, because the GPU could be powered off soon after this call. + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it will be holding kbasep_js_device_data::runpool_mutex. + */ +void kbasep_js_policy_runpool_timers_sync(union kbasep_js_policy *js_policy); + + +/** + * @brief Indicate whether a new context has an higher priority than the current context. + * + * + * The caller has the following conditions on locking: + * - kbasep_js_kctx_info::ctx::jsctx_mutex will be held for \a new_ctx + * + * This function must not sleep, because an IRQ spinlock might be held whilst + * this is called. + * + * @note There is nothing to stop the priority of \a current_ctx changing + * during or immediately after this function is called (because its jsctx_mutex + * cannot be held). Therefore, this function should only be seen as a heuristic + * guide as to whether \a new_ctx is higher priority than \a current_ctx + */ +mali_bool kbasep_js_policy_ctx_has_priority(union kbasep_js_policy *js_policy, struct kbase_context *current_ctx, struct kbase_context *new_ctx); + + /** @} *//* end group kbase_js_policy_ctx */ + +/** + * @addtogroup kbase_js_policy_job Job Scheduler Policy, Job Chain Management API + * @{ + * + * Refer to @ref page_kbase_js_policy for an overview and detailed operation of + * the Job Scheduler Policy and its use from the Job Scheduler Core. + */ + +/** + * @brief Job Scheduler Policy Job Info structure + * + * This structure is embedded in the struct kbase_jd_atom structure. It is used to: + * - track information needed for the policy to schedule the job (e.g. time + * used, OS priority etc.) + * - link together jobs into a queue/buffer, so that a struct kbase_jd_atom can be + * obtained as the container of the policy job info. This allows the API to + * return what "the next job" should be. + * - obtain other information already stored in the struct kbase_context for + * scheduling purposes (e.g user-side relative priority) + */ +union kbasep_js_policy_job_info; + +/** + * @brief Initialize a job for use with the Job Scheduler Policy + * + * This function initializes the union kbasep_js_policy_job_info structure within the + * kbase_jd_atom. It will only initialize/allocate resources that are specific + * to the job. + * + * That is, this function makes \b no attempt to: + * - initialize any context/policy-wide information + * - enqueue the job on the policy. + * + * At some later point, the following functions must be called on the job, in this order: + * - kbasep_js_policy_register_job() to register the job and initialize policy/context wide data. + * - kbasep_js_policy_enqueue_job() to enqueue the job + * + * A job must only ever be initialized on the Policy once, and must be + * terminated on the Policy before the job is freed. + * + * The caller will not be holding any locks, and so this function will not + * modify any information in \a kctx or \a js_policy. + * + * @return MALI_ERROR_NONE if initialization was correct. + */ +mali_error kbasep_js_policy_init_job(const union kbasep_js_policy *js_policy, const struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief Register context/policy-wide information for a job on the Job Scheduler Policy. + * + * Registers the job with the policy. This is used to track the job before it + * has been enqueued/requeued by kbasep_js_policy_enqueue_job(). Specifically, + * it is used to update information under a lock that could not be updated at + * kbasep_js_policy_init_job() time (such as context/policy-wide data). + * + * @note This function will not fail, and hence does not allocate any + * resources. Any failures that could occur on registration will be caught + * during kbasep_js_policy_init_job() instead. + * + * A job must only ever be registerd on the Policy once, and must be + * deregistered on the Policy on completion (whether or not that completion was + * success/failure). + * + * The caller has the following conditions on locking: + * - kbasep_js_kctx_info::ctx::jsctx_mutex will be held. + */ +void kbasep_js_policy_register_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief De-register context/policy-wide information for a on the Job Scheduler Policy. + * + * This must be used before terminating the resources associated with using a + * job in the Job Scheduler Policy. This function does not itself terminate any + * resources, at most it just updates information in the policy and context. + * + * The caller has the following conditions on locking: + * - kbasep_js_kctx_info::ctx::jsctx_mutex will be held. + */ +void kbasep_js_policy_deregister_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief Dequeue a Job for a job slot from the Job Scheduler Policy Run Pool + * + * The job returned by the policy will match at least one of the bits in the + * job slot's core requirements (but it may match more than one, or all @ref + * base_jd_core_req bits supported by the job slot). + * + * In addition, the requirements of the job returned will be a subset of those + * requested - the job returned will not have requirements that \a job_slot_idx + * cannot satisfy. + * + * The caller will submit the job to the GPU as soon as the GPU's NEXT register + * for the corresponding slot is empty. Of course, the GPU will then only run + * this new job when the currently executing job (in the jobslot's HEAD + * register) has completed. + * + * @return MALI_TRUE if a job was available, and *kctx_ptr points to + * the kctx dequeued. + * @return MALI_FALSE if no jobs were available among all ctxs in the Run Pool. + * + * @note base_jd_core_req is currently a u8 - beware of type conversion. + * + * The caller has the following conditions on locking: + * - kbasep_js_device_data::runpool_lock::irq will be held. + * - kbasep_js_device_data::runpool_mutex will be held. + * - kbasep_js_kctx_info::ctx::jsctx_mutex. will be held + */ +mali_bool kbasep_js_policy_dequeue_job(struct kbase_device *kbdev, int job_slot_idx, struct kbase_jd_atom ** const katom_ptr); + +/** + * @brief Requeue a Job back into the the Job Scheduler Policy Run Pool + * + * This will be used to enqueue a job after its creation and also to requeue + * a job into the Run Pool that was previously dequeued (running). It notifies + * the policy that the job should be run again at some point later. + * + * The caller has the following conditions on locking: + * - kbasep_js_device_data::runpool_irq::lock (a spinlock) will be held. + * - kbasep_js_device_data::runpool_mutex will be held. + * - kbasep_js_kctx_info::ctx::jsctx_mutex will be held. + */ +void kbasep_js_policy_enqueue_job(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom); + +/** + * @brief Log the result of a job: the time spent on a job/context, and whether + * the job failed or not. + * + * Since a struct kbase_jd_atom contains a pointer to the struct kbase_context owning it, + * then this can also be used to log time on either/both the job and the + * containing context. + * + * The completion state of the job can be found by examining \a katom->event.event_code + * + * If the Job failed and the policy is implementing fair-sharing, then the + * policy must penalize the failing job/context: + * - At the very least, it should penalize the time taken by the amount of + * time spent processing the IRQ in SW. This because a job in the NEXT slot + * waiting to run will be delayed until the failing job has had the IRQ + * cleared. + * - \b Optionally, the policy could apply other penalties. For example, based + * on a threshold of a number of failing jobs, after which a large penalty is + * applied. + * + * The kbasep_js_device_data::runpool_mutex will be held by the caller. + * + * @note This API is called from IRQ context. + * + * The caller has the following conditions on locking: + * - kbasep_js_device_data::runpool_irq::lock will be held. + * + * @param js_policy job scheduler policy + * @param katom job dispatch atom + * @param time_spent_us the time spent by the job, in microseconds (10^-6 seconds). + */ +void kbasep_js_policy_log_job_result(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom, u64 time_spent_us); + + /** @} *//* end group kbase_js_policy_job */ + + /** @} *//* end group kbase_js_policy */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_POLICY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.c new file mode 100644 index 0000000000000000000000000000000000000000..78ec5f1fb5519ad543250a7817345760b11c23f3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.c @@ -0,0 +1,1482 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Job Scheduler: Completely Fair Policy Implementation + */ + +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) +#include +#endif + +/** + * Define for when dumping is enabled. + * This should not be based on the instrumentation level as whether dumping is enabled for a particular level is down to the integrator. + * However this is being used for now as otherwise the cinstr headers would be needed. + */ +#define CINSTR_DUMPING_ENABLED (2 == MALI_INSTRUMENTATION_LEVEL) + +/** Fixed point constants used for runtime weight calculations */ +#define WEIGHT_FIXEDPOINT_SHIFT 10 +#define WEIGHT_TABLE_SIZE 40 +#define WEIGHT_0_NICE (WEIGHT_TABLE_SIZE/2) +#define WEIGHT_0_VAL (1 << WEIGHT_FIXEDPOINT_SHIFT) + +#define LOOKUP_VARIANT_MASK ((1u<process_priority + ctx_info->bag_priority; + + /* Adjust runtime_us using priority weight if required */ + if (priority != 0 && time_us != 0) { + int clamped_priority; + + /* Clamp values to min..max weights */ + if (priority > PROCESS_PRIORITY_MAX) + clamped_priority = PROCESS_PRIORITY_MAX; + else if (priority < PROCESS_PRIORITY_MIN) + clamped_priority = PROCESS_PRIORITY_MIN; + else + clamped_priority = priority; + + /* Fixed point multiplication */ + time_delta_us = (time_us * weight_of_priority[WEIGHT_0_NICE + clamped_priority]); + /* Remove fraction */ + time_delta_us = time_delta_us >> WEIGHT_FIXEDPOINT_SHIFT; + /* Make sure the time always increases */ + if (0 == time_delta_us) + time_delta_us++; + } else { + time_delta_us = time_us; + } + + return time_delta_us; +} + +#if KBASE_TRACE_ENABLE +STATIC int kbasep_js_policy_trace_get_refcnt_nolock(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + int as_nr; + int refcnt = 0; + + js_devdata = &kbdev->js_data; + + as_nr = kctx->as_nr; + if (as_nr != KBASEP_AS_NR_INVALID) { + struct kbasep_js_per_as_data *js_per_as_data; + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + refcnt = js_per_as_data->as_busy_refcount; + } + + return refcnt; +} + +STATIC INLINE int kbasep_js_policy_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int refcnt = 0; + + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + refcnt = kbasep_js_policy_trace_get_refcnt_nolock(kbdev, kctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return refcnt; +} +#else /* KBASE_TRACE_ENABLE */ +STATIC int kbasep_js_policy_trace_get_refcnt_nolock(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(kctx); + return 0; +} + +STATIC INLINE int kbasep_js_policy_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(kctx); + return 0; +} +#endif /* KBASE_TRACE_ENABLE */ + +#ifdef CONFIG_MALI_DEBUG +STATIC void kbasep_js_debug_check(struct kbasep_js_policy_cfs *policy_info, struct kbase_context *kctx, kbasep_js_check check_flag) +{ + /* This function uses the ternary operator and non-explicit comparisons, + * because it makes for much shorter, easier to read code */ + + if (check_flag & KBASEP_JS_CHECKFLAG_QUEUED) { + mali_bool is_queued; + mali_bool expect_queued; + + is_queued = (kbasep_list_member_of( + &policy_info->ctx_queue_head, + &kctx->jctx.sched_info.runpool.policy_ctx.cfs.list)) ? + MALI_TRUE : MALI_FALSE; + + if (!is_queued) + is_queued = (kbasep_list_member_of(&policy_info->ctx_rt_queue_head, &kctx->jctx.sched_info.runpool.policy_ctx.cfs.list)) ? MALI_TRUE : MALI_FALSE; + + expect_queued = (check_flag & KBASEP_JS_CHECKFLAG_IS_QUEUED) ? MALI_TRUE : MALI_FALSE; + + KBASE_DEBUG_ASSERT_MSG(expect_queued == is_queued, "Expected context %p to be %s but it was %s\n", kctx, (expect_queued) ? "queued" : "not queued", (is_queued) ? "queued" : "not queued"); + + } + + if (check_flag & KBASEP_JS_CHECKFLAG_SCHEDULED) { + mali_bool is_scheduled; + mali_bool expect_scheduled; + + is_scheduled = (kbasep_list_member_of( + &policy_info->scheduled_ctxs_head, + &kctx->jctx.sched_info.runpool.policy_ctx.cfs.list)) ? + MALI_TRUE : MALI_FALSE; + + expect_scheduled = (check_flag & KBASEP_JS_CHECKFLAG_IS_SCHEDULED) ? MALI_TRUE : MALI_FALSE; + KBASE_DEBUG_ASSERT_MSG(expect_scheduled == is_scheduled, "Expected context %p to be %s but it was %s\n", kctx, (expect_scheduled) ? "scheduled" : "not scheduled", (is_scheduled) ? "scheduled" : "not scheduled"); + } + +} +#else /* CONFIG_MALI_DEBUG */ +STATIC void kbasep_js_debug_check(struct kbasep_js_policy_cfs *policy_info, struct kbase_context *kctx, kbasep_js_check check_flag) +{ + CSTD_UNUSED(policy_info); + CSTD_UNUSED(kctx); + CSTD_UNUSED(check_flag); +} +#endif /* CONFIG_MALI_DEBUG */ + +STATIC INLINE void set_slot_to_variant_lookup(u32 *bit_array, u32 slot_idx, u32 variants_supported) +{ + u32 overall_bit_idx = slot_idx * KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS; + u32 word_idx = overall_bit_idx / 32; + u32 bit_idx = overall_bit_idx % 32; + + KBASE_DEBUG_ASSERT(slot_idx < BASE_JM_MAX_NR_SLOTS); + KBASE_DEBUG_ASSERT((variants_supported & ~LOOKUP_VARIANT_MASK) == 0); + + bit_array[word_idx] |= variants_supported << bit_idx; +} + +STATIC INLINE u32 get_slot_to_variant_lookup(u32 *bit_array, u32 slot_idx) +{ + u32 overall_bit_idx = slot_idx * KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS; + u32 word_idx = overall_bit_idx / 32; + u32 bit_idx = overall_bit_idx % 32; + + u32 res; + + KBASE_DEBUG_ASSERT(slot_idx < BASE_JM_MAX_NR_SLOTS); + + res = bit_array[word_idx] >> bit_idx; + res &= LOOKUP_VARIANT_MASK; + + return res; +} + +/* Check the core_req_variants: make sure that every job slot is satisifed by + * one of the variants. This checks that cached_variant_idx_init will produce a + * valid result for jobs that make maximum use of the job slots. + * + * @note The checks are limited to the job slots - this does not check that + * every context requirement is covered (because some are intentionally not + * supported, such as KBASE_CTX_FLAG_SUBMIT_DISABLED) */ +#ifdef CONFIG_MALI_DEBUG +STATIC void debug_check_core_req_variants(struct kbase_device *kbdev, struct kbasep_js_policy_cfs *policy_info) +{ + struct kbasep_js_device_data *js_devdata; + u32 i; + int j; + + js_devdata = &kbdev->js_data; + + for (j = 0; j < kbdev->gpu_props.num_job_slots; ++j) { + base_jd_core_req job_core_req; + mali_bool found = MALI_FALSE; + + job_core_req = js_devdata->js_reqs[j]; + for (i = 0; i < policy_info->num_core_req_variants; ++i) { + base_jd_core_req var_core_req; + + var_core_req = policy_info->core_req_variants[i].core_req; + + if ((var_core_req & job_core_req) == job_core_req) { + found = MALI_TRUE; + break; + } + } + + /* Early-out on any failure */ + KBASE_DEBUG_ASSERT_MSG(found != MALI_FALSE, "Job slot %d features 0x%x not matched by core_req_variants. " "Rework core_req_variants and vairants_supported_<...>_state[] to match\n", j, job_core_req); + } +} +#endif + +STATIC void build_core_req_variants(struct kbase_device *kbdev, struct kbasep_js_policy_cfs *policy_info) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(policy_info != NULL); + CSTD_UNUSED(kbdev); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + KBASE_DEBUG_ASSERT(NUM_CORE_REQ_VARIANTS_8987 <= KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS); + + /* Assume a static set of variants */ + memcpy(policy_info->core_req_variants, core_req_variants_8987, sizeof(core_req_variants_8987)); + + policy_info->num_core_req_variants = NUM_CORE_REQ_VARIANTS_8987; + } else { + KBASE_DEBUG_ASSERT(NUM_CORE_REQ_VARIANTS <= KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS); + + /* Assume a static set of variants */ + memcpy(policy_info->core_req_variants, core_req_variants, sizeof(core_req_variants)); + + policy_info->num_core_req_variants = NUM_CORE_REQ_VARIANTS; + } + + KBASE_DEBUG_CODE(debug_check_core_req_variants(kbdev, policy_info)); +} + +STATIC void build_slot_lookups(struct kbase_device *kbdev, struct kbasep_js_policy_cfs *policy_info) +{ + u8 i; + const u32 *variants_supported_ss_for_this_hw = variants_supported_ss_state; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(policy_info != NULL); + + KBASE_DEBUG_ASSERT(kbdev->gpu_props.num_job_slots <= NELEMS(variants_supported_ss_state)); + KBASE_DEBUG_ASSERT(kbdev->gpu_props.num_job_slots <= NELEMS(variants_supported_ss_allcore_state)); + KBASE_DEBUG_ASSERT(kbdev->gpu_props.num_job_slots <= NELEMS(variants_supported_ss_state_8987)); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) + variants_supported_ss_for_this_hw = variants_supported_ss_state_8987; + + /* Given the static set of variants, provide a static set of lookups */ + for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) { + set_slot_to_variant_lookup(policy_info->slot_to_variant_lookup_ss_state, i, variants_supported_ss_for_this_hw[i]); + + set_slot_to_variant_lookup(policy_info->slot_to_variant_lookup_ss_allcore_state, i, variants_supported_ss_allcore_state[i]); + } + +} + +STATIC mali_error cached_variant_idx_init(const struct kbasep_js_policy_cfs *policy_info, const struct kbase_context *kctx, struct kbase_jd_atom *atom) +{ + struct kbasep_js_policy_cfs_job *job_info; + u32 i; + base_jd_core_req job_core_req; + u32 job_device_nr; + kbase_context_flags ctx_flags; + const struct kbasep_js_kctx_info *js_kctx_info; + const struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(policy_info != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(atom != NULL); + + kbdev = container_of(policy_info, const struct kbase_device, js_data.policy.cfs); + job_info = &atom->sched_info.cfs; + job_core_req = atom->core_req; + job_device_nr = atom->device_nr; + js_kctx_info = &kctx->jctx.sched_info; + ctx_flags = js_kctx_info->ctx.flags; + + /* Initial check for atoms targetting a specific coregroup */ + if ((job_core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) != MALI_FALSE && job_device_nr >= kbdev->gpu_props.num_core_groups) { + /* device_nr exceeds the number of coregroups - not allowed by + * @ref struct base_jd_atom_v2 API contract */ + return MALI_ERROR_FUNCTION_FAILED; + } + + /* Pick a core_req variant that matches us. Since they're ordered by least + * restrictive first, it picks the least restrictive variant */ + for (i = 0; i < policy_info->num_core_req_variants; ++i) { + base_jd_core_req var_core_req; + kbase_context_flags var_ctx_req; + u32 var_device_nr; + var_core_req = policy_info->core_req_variants[i].core_req; + var_ctx_req = policy_info->core_req_variants[i].ctx_req; + var_device_nr = policy_info->core_req_variants[i].device_nr; + + if ((var_core_req & job_core_req) == job_core_req && (var_ctx_req & ctx_flags) == ctx_flags && ((var_core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) == MALI_FALSE || var_device_nr == job_device_nr)) { + job_info->cached_variant_idx = i; + return MALI_ERROR_NONE; + } + } + + /* Could not find a matching requirement, this should only be caused by an + * attempt to attack the driver. */ + return MALI_ERROR_FUNCTION_FAILED; +} + +STATIC mali_bool dequeue_job(struct kbase_device *kbdev, + struct kbase_context *kctx, + u32 variants_supported, + struct kbase_jd_atom ** const katom_ptr, + int job_slot_idx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_policy_cfs_ctx *ctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom_ptr != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + policy_info = &js_devdata->policy.cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + /* Only submit jobs from contexts that are allowed */ + if (kbasep_js_is_submit_allowed(js_devdata, kctx) != MALI_FALSE) { + /* Check each variant in turn */ + while (variants_supported != 0) { + long variant_idx; + struct list_head *job_list; + + variant_idx = ffs(variants_supported) - 1; + job_list = &ctx_info->job_list_head[variant_idx]; + + if (!list_empty(job_list)) { + /* Found a context with a matching job */ + { + struct kbase_jd_atom *front_atom = + list_entry(job_list->next, struct kbase_jd_atom, sched_info.cfs.list); + + KBASE_TRACE_ADD_SLOT(kbdev, JS_POLICY_DEQUEUE_JOB, front_atom->kctx, front_atom, front_atom->jc, job_slot_idx); + } + *katom_ptr = list_entry(job_list->next, struct kbase_jd_atom, sched_info.cfs.list); + list_del(job_list->next); + + (*katom_ptr)->sched_info.cfs.ticks = 0; + + /* Put this context at the back of the Run Pool */ + list_del(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); + list_add_tail(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list, &policy_info->scheduled_ctxs_head); + + return MALI_TRUE; + } + + variants_supported &= ~(1u << variant_idx); + } + /* All variants checked by here */ + } + + /* The context does not have a matching job */ + + return MALI_FALSE; +} + +/** + * Hold the runpool_irq spinlock for this + */ +STATIC INLINE mali_bool timer_callback_should_run(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + s8 nr_running_ctxs; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + /* nr_user_contexts_running is updated with the runpool_mutex. However, the + * locking in the caller gives us a barrier that ensures nr_user_contexts is + * up-to-date for reading */ + nr_running_ctxs = js_devdata->nr_user_contexts_running; + +#ifdef CONFIG_MALI_DEBUG + if (js_devdata->softstop_always && nr_running_ctxs > 0) { + /* Debug support for allowing soft-stop on a single context */ + return MALI_TRUE; + } +#endif /* CONFIG_MALI_DEBUG */ + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_9435)) { + /* Timeouts would have to be 4x longer (due to micro-architectural design) + * to support OpenCL conformance tests, so only run the timer when there's: + * - 2 or more CL contexts + * - 1 or more GLES contexts + * + * NOTE: We will treat a context that has both Compute and Non-Compute jobs + * will be treated as an OpenCL context (hence, we don't check + * KBASEP_JS_CTX_ATTR_NON_COMPUTE). + */ + { + s8 nr_compute_ctxs = kbasep_js_ctx_attr_count_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_COMPUTE); + s8 nr_noncompute_ctxs = nr_running_ctxs - nr_compute_ctxs; + + return (mali_bool) (nr_compute_ctxs >= 2 || nr_noncompute_ctxs > 0); + } + } else { + /* Run the timer callback whenever you have at least 1 context */ + return (mali_bool) (nr_running_ctxs > 0); + } +} + +static enum hrtimer_restart timer_callback(struct hrtimer *timer) +{ + unsigned long flags; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs *policy_info; + int s; + mali_bool reset_needed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(timer != NULL); + + policy_info = container_of(timer, struct kbasep_js_policy_cfs, scheduling_timer); + kbdev = container_of(policy_info, struct kbase_device, js_data.policy.cfs); + js_devdata = &kbdev->js_data; + + /* Loop through the slots */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + for (s = 0; s < kbdev->gpu_props.num_job_slots; s++) { + struct kbase_jm_slot *slot = &kbdev->jm_slots[s]; + struct kbase_jd_atom *atom = NULL; + + if (kbasep_jm_nr_jobs_submitted(slot) > 0) { + atom = kbasep_jm_peek_idx_submit_slot(slot, 0); + KBASE_DEBUG_ASSERT(atom != NULL); + + if (kbasep_jm_is_dummy_workaround_job(kbdev, atom) != MALI_FALSE) { + /* Prevent further use of the atom - never cause a soft-stop, hard-stop, or a GPU reset due to it. */ + atom = NULL; + } + } + + if (atom != NULL) { + /* The current version of the model doesn't support Soft-Stop */ + if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_5736)) { + u32 ticks = atom->sched_info.cfs.ticks++; + +#if !CINSTR_DUMPING_ENABLED + u32 soft_stop_ticks, hard_stop_ticks, gpu_reset_ticks; + if (atom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { + soft_stop_ticks = js_devdata->soft_stop_ticks_cl; + hard_stop_ticks = js_devdata->hard_stop_ticks_cl; + gpu_reset_ticks = js_devdata->gpu_reset_ticks_cl; + } else { + soft_stop_ticks = js_devdata->soft_stop_ticks; + hard_stop_ticks = js_devdata->hard_stop_ticks_ss; + gpu_reset_ticks = js_devdata->gpu_reset_ticks_ss; + } + + /* Job is Soft-Stoppable */ + if (ticks == soft_stop_ticks) { + int disjoint_threshold = + KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD; + u32 softstop_flags = 0u; + /* Job has been scheduled for at least js_devdata->soft_stop_ticks ticks. + * Soft stop the slot so we can run other jobs. + */ + dev_dbg(kbdev->dev, "Soft-stop"); + +#if !KBASE_DISABLE_SCHEDULING_SOFT_STOPS + /* nr_user_contexts_running is updated with the runpool_mutex, + * but we can't take that here. + * + * However, if it's about to be increased then the new context + * can't run any jobs until they take the runpool_irq lock, so + * it's OK to observe the older value. + * + * Similarly, if it's about to be decreased, the last job from + * another context has already finished, so it's not too bad + * that we observe the older value and register a disjoint + * event when we try soft-stopping */ + if (js_devdata->nr_user_contexts_running >= disjoint_threshold) + softstop_flags |= JS_COMMAND_SW_CAUSES_DISJOINT; + kbase_job_slot_softstop_swflags(kbdev, + s, atom, softstop_flags); +#endif + } else if (ticks == hard_stop_ticks) { + /* Job has been scheduled for at least js_devdata->hard_stop_ticks_ss ticks. + * It should have been soft-stopped by now. Hard stop the slot. + */ +#if !KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_warn(kbdev->dev, "JS: Job Hard-Stopped (took more than %lu ticks at %lu ms/tick)", (unsigned long)ticks, (unsigned long)(js_devdata->scheduling_tick_ns / 1000000u)); + kbase_job_slot_hardstop(atom->kctx, s, atom); +#endif + } else if (ticks == gpu_reset_ticks) { + /* Job has been scheduled for at least js_devdata->gpu_reset_ticks_ss ticks. + * It should have left the GPU by now. Signal that the GPU needs to be reset. + */ + reset_needed = MALI_TRUE; + } +#else /* !CINSTR_DUMPING_ENABLED */ + /* NOTE: During CINSTR_DUMPING_ENABLED, we use the alternate timeouts, which + * makes the hard-stop and GPU reset timeout much longer. We also ensure that + * we don't soft-stop at all. */ + if (ticks == js_devdata->soft_stop_ticks) { + /* Job has been scheduled for at least js_devdata->soft_stop_ticks. + * We do not soft-stop during CINSTR_DUMPING_ENABLED, however. + */ + dev_dbg(kbdev->dev, "Soft-stop"); + } else if (ticks == js_devdata->hard_stop_ticks_nss) { + /* Job has been scheduled for at least js_devdata->hard_stop_ticks_nss ticks. + * Hard stop the slot. + */ +#if !KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_warn(kbdev->dev, "JS: Job Hard-Stopped (took more than %lu ticks at %lu ms/tick)", (unsigned long)ticks, (unsigned long)(js_devdata->scheduling_tick_ns / 1000000u)); + kbase_job_slot_hardstop(atom->kctx, s, atom); +#endif + } else if (ticks == js_devdata->gpu_reset_ticks_nss) { + /* Job has been scheduled for at least js_devdata->gpu_reset_ticks_nss ticks. + * It should have left the GPU by now. Signal that the GPU needs to be reset. + */ + reset_needed = MALI_TRUE; + } +#endif /* !CINSTR_DUMPING_ENABLED */ + } + } + } +#if KBASE_GPU_RESET_EN + if (reset_needed) { + dev_err(kbdev->dev, "JS: Job has been on the GPU for too long (KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS/NSS timeout hit). Issueing GPU soft-reset to resolve."); + + if (kbase_prepare_to_reset_gpu_locked(kbdev)) + kbase_reset_gpu_locked(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* the timer is re-issued if there is contexts in the run-pool */ + + if (timer_callback_should_run(kbdev) != MALI_FALSE) { + hrtimer_start(&policy_info->scheduling_timer, HR_TIMER_DELAY_NSEC(js_devdata->scheduling_tick_ns), HRTIMER_MODE_REL); + } else { + KBASE_TRACE_ADD(kbdev, JS_POLICY_TIMER_END, NULL, NULL, 0u, 0u); + /* timer_running state is updated by kbasep_js_policy_runpool_timers_sync() */ + } + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return HRTIMER_NORESTART; +} + +/* + * Non-private functions + */ + +mali_error kbasep_js_policy_init(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs *policy_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + policy_info = &js_devdata->policy.cfs; + + INIT_LIST_HEAD(&policy_info->ctx_queue_head); + INIT_LIST_HEAD(&policy_info->scheduled_ctxs_head); + INIT_LIST_HEAD(&policy_info->ctx_rt_queue_head); + + atomic64_set(&policy_info->least_runtime_us, KBASEP_JS_RUNTIME_EMPTY); + atomic64_set(&policy_info->rt_least_runtime_us, KBASEP_JS_RUNTIME_EMPTY); + + hrtimer_init(&policy_info->scheduling_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + policy_info->scheduling_timer.function = timer_callback; + + policy_info->timer_running = MALI_FALSE; + policy_info->head_runtime_us = 0; + + /* Build up the core_req variants */ + build_core_req_variants(kbdev, policy_info); + /* Build the slot to variant lookups */ + build_slot_lookups(kbdev, policy_info); + + return MALI_ERROR_NONE; +} + +void kbasep_js_policy_term(union kbasep_js_policy *js_policy) +{ + struct kbasep_js_policy_cfs *policy_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + policy_info = &js_policy->cfs; + + /* ASSERT that there are no contexts queued */ + KBASE_DEBUG_ASSERT(list_empty(&policy_info->ctx_queue_head)); + KBASE_DEBUG_ASSERT(KBASEP_JS_RUNTIME_EMPTY == atomic64_read(&policy_info->least_runtime_us)); + + /* ASSERT that there are no contexts scheduled */ + KBASE_DEBUG_ASSERT(list_empty(&policy_info->scheduled_ctxs_head)); + + /* ASSERT that there are no contexts queued */ + KBASE_DEBUG_ASSERT(list_empty(&policy_info->ctx_rt_queue_head)); + KBASE_DEBUG_ASSERT(KBASEP_JS_RUNTIME_EMPTY == atomic64_read(&policy_info->rt_least_runtime_us)); + + hrtimer_cancel(&policy_info->scheduling_timer); +} + +mali_error kbasep_js_policy_init_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbasep_js_policy_cfs *policy_info; + u32 i; + int policy; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + policy_info = &kbdev->js_data.policy.cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_INIT_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx)); + + for (i = 0; i < policy_info->num_core_req_variants; ++i) + INIT_LIST_HEAD(&ctx_info->job_list_head[i]); + + policy = current->policy; + if (policy == SCHED_FIFO || policy == SCHED_RR) { + ctx_info->process_rt_policy = MALI_TRUE; + ctx_info->process_priority = (((MAX_RT_PRIO - 1) - current->rt_priority) / 5) - 20; + } else { + ctx_info->process_rt_policy = MALI_FALSE; + ctx_info->process_priority = (current->static_prio - MAX_RT_PRIO) - 20; + } + + ctx_info->bag_total_priority = 0; + ctx_info->bag_total_nr_atoms = 0; + + /* Initial runtime (relative to least-run context runtime) + * + * This uses the Policy Queue's most up-to-date head_runtime_us by using the + * queue mutex to issue memory barriers - also ensure future updates to + * head_runtime_us occur strictly after this context is initialized */ + mutex_lock(&js_devdata->queue_mutex); + + /* No need to hold the the runpool_irq.lock here, because we're initializing + * the value, and the context is definitely not being updated in the + * runpool at this point. The queue_mutex ensures the memory barrier. */ + ctx_info->runtime_us = policy_info->head_runtime_us + priority_weight(ctx_info, (u64) js_devdata->cfs_ctx_runtime_init_slices * (u64) (js_devdata->ctx_timeslice_ns / 1000u)); + + mutex_unlock(&js_devdata->queue_mutex); + + return MALI_ERROR_NONE; +} + +void kbasep_js_policy_term_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbasep_js_policy_cfs *policy_info; + u32 i; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + { + struct kbase_device *kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_TERM_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx)); + } + + /* ASSERT that no jobs are present */ + for (i = 0; i < policy_info->num_core_req_variants; ++i) + KBASE_DEBUG_ASSERT(list_empty(&ctx_info->job_list_head[i])); + + /* No work to do */ +} + +/* + * Context Management + */ + +void kbasep_js_policy_enqueue_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbase_context *head_ctx; + struct kbase_context *list_kctx = NULL; + struct kbasep_js_device_data *js_devdata; + struct list_head *queue_head; + struct list_head *pos; + struct kbase_device *kbdev; + atomic64_t *least_runtime_us; + u64 head_runtime; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + js_devdata = &kbdev->js_data; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_ENQUEUE_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx)); + + /* ASSERT about scheduled-ness/queued-ness */ + kbasep_js_debug_check(policy_info, kctx, KBASEP_JS_CHECK_NOTQUEUED); + + /* Clamp the runtime to prevent DoS attacks through "stored-up" runtime */ + if (policy_info->head_runtime_us > ctx_info->runtime_us + (u64) js_devdata->cfs_ctx_runtime_min_slices * (u64) (js_devdata->ctx_timeslice_ns / 1000u)) { + /* No need to hold the the runpool_irq.lock here, because we're essentially + * initializing the value, and the context is definitely not being updated in the + * runpool at this point. The queue_mutex held by the caller ensures the memory + * barrier. */ + ctx_info->runtime_us = policy_info->head_runtime_us - (u64) js_devdata->cfs_ctx_runtime_min_slices * (u64) (js_devdata->ctx_timeslice_ns / 1000u); + } + + /* Find the position where the context should be enqueued */ + if (ctx_info->process_rt_policy) { + queue_head = &policy_info->ctx_rt_queue_head; + least_runtime_us = &policy_info->rt_least_runtime_us; + } else { + queue_head = &policy_info->ctx_queue_head; + least_runtime_us = &policy_info->least_runtime_us; + } + + if (list_empty(queue_head)) { + list_add_tail(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list, queue_head); + } else { + list_for_each(pos, queue_head) { + struct kbasep_js_policy_cfs_ctx *list_ctx_info; + + list_kctx = list_entry(pos, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + list_ctx_info = &list_kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + if ((kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) != 0) + break; + + if ((list_ctx_info->runtime_us > ctx_info->runtime_us) && ((list_kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) == 0)) + break; + } + + /* Add the context to the queue */ + list_add_tail(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list, &list_kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); + } + + /* Ensure least_runtime_us is up to date*/ + head_ctx = list_entry(queue_head->next, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + head_runtime = head_ctx->jctx.sched_info.runpool.policy_ctx.cfs.runtime_us; + atomic64_set(least_runtime_us, head_runtime); +} + +mali_bool kbasep_js_policy_dequeue_head_ctx(union kbasep_js_policy *js_policy, struct kbase_context ** const kctx_ptr) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbase_context *head_ctx; + struct list_head *queue_head; + atomic64_t *least_runtime_us; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx_ptr != NULL); + + policy_info = &js_policy->cfs; + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + + /* attempt to dequeue from the 'realttime' queue first */ + if (list_empty(&policy_info->ctx_rt_queue_head)) { + if (list_empty(&policy_info->ctx_queue_head)) { + /* Nothing to dequeue */ + return MALI_FALSE; + } else { + queue_head = &policy_info->ctx_queue_head; + least_runtime_us = &policy_info->least_runtime_us; + } + } else { + queue_head = &policy_info->ctx_rt_queue_head; + least_runtime_us = &policy_info->rt_least_runtime_us; + } + + /* Contexts are dequeued from the front of the queue */ + *kctx_ptr = list_entry(queue_head->next, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + /* If dequeuing will empty the list, then set least_runtime_us prior to deletion */ + if (queue_head->next->next == queue_head) + atomic64_set(least_runtime_us, KBASEP_JS_RUNTIME_EMPTY); + list_del(queue_head->next); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_DEQUEUE_HEAD_CTX, *kctx_ptr, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, *kctx_ptr)); + + /* Update the head runtime */ + if (!list_empty(queue_head)) { + u64 head_runtime; + + head_ctx = list_entry(queue_head->next, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + + /* No need to hold the the runpool_irq.lock here for reading - the + * context is definitely not being updated in the runpool at this + * point. The queue_mutex held by the caller ensures the memory barrier. */ + head_runtime = head_ctx->jctx.sched_info.runpool.policy_ctx.cfs.runtime_us; + + if (head_runtime > policy_info->head_runtime_us) + policy_info->head_runtime_us = head_runtime; + + atomic64_set(least_runtime_us, head_runtime); + } + + return MALI_TRUE; +} + +mali_bool kbasep_js_policy_try_evict_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbasep_js_policy_cfs *policy_info; + mali_bool is_present; + struct list_head *queue_head; + atomic64_t *least_runtime_us; + struct list_head *qhead; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + + if (ctx_info->process_rt_policy) { + queue_head = &policy_info->ctx_rt_queue_head; + least_runtime_us = &policy_info->rt_least_runtime_us; + } else { + queue_head = &policy_info->ctx_queue_head; + least_runtime_us = &policy_info->least_runtime_us; + } + + qhead = queue_head; + + is_present = kbasep_list_member_of(qhead, &kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); + + KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, JS_POLICY_TRY_EVICT_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx), is_present); + + if (is_present != MALI_FALSE) { + struct kbase_context *head_ctx; + + qhead = queue_head; + + /* If dequeuing will empty the list, then set least_runtime_us prior to deletion */ + if (queue_head->next->next == queue_head) + atomic64_set(least_runtime_us, KBASEP_JS_RUNTIME_EMPTY); + + /* Remove the context */ + list_del(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); + + qhead = queue_head; + /* Update the head runtime */ + if (!list_empty(qhead)) { + u64 head_runtime; + + head_ctx = list_entry(qhead->next, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + + /* No need to hold the the runpool_irq.lock here for reading - the + * context is definitely not being updated in the runpool at this + * point. The queue_mutex held by the caller ensures the memory barrier. */ + head_runtime = head_ctx->jctx.sched_info.runpool.policy_ctx.cfs.runtime_us; + + if (head_runtime > policy_info->head_runtime_us) + policy_info->head_runtime_us = head_runtime; + + atomic64_set(least_runtime_us, head_runtime); + } + } + + return is_present; +} + +void kbasep_js_policy_foreach_ctx_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, + kbasep_js_policy_ctx_job_cb callback, mali_bool detach_jobs) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbase_device *kbdev; + u32 i; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_FOREACH_CTX_JOBS, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx)); + + /* Invoke callback on jobs on each variant in turn */ + for (i = 0; i < policy_info->num_core_req_variants; ++i) { + struct list_head *job_list; + struct kbase_jd_atom *atom; + struct kbase_jd_atom *tmp_iter; + job_list = &ctx_info->job_list_head[i]; + /* Invoke callback on all kbase_jd_atoms in this list, optionally + * removing them from the list */ + list_for_each_entry_safe(atom, tmp_iter, job_list, sched_info.cfs.list) { + if (detach_jobs) + list_del(&atom->sched_info.cfs.list); + callback(kbdev, atom); + } + } + +} + +void kbasep_js_policy_runpool_add_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_device_data *js_devdata; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + js_devdata = container_of(js_policy, struct kbasep_js_device_data, policy); + + kbdev = kctx->kbdev; + + { + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_RUNPOOL_ADD_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt_nolock(kbdev, kctx)); + } + + /* ASSERT about scheduled-ness/queued-ness */ + kbasep_js_debug_check(policy_info, kctx, KBASEP_JS_CHECK_NOTSCHEDULED); + + /* All enqueued contexts go to the back of the runpool */ + list_add_tail(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list, &policy_info->scheduled_ctxs_head); + + if (timer_callback_should_run(kbdev) != MALI_FALSE && policy_info->timer_running == MALI_FALSE) { + hrtimer_start(&policy_info->scheduling_timer, HR_TIMER_DELAY_NSEC(js_devdata->scheduling_tick_ns), HRTIMER_MODE_REL); + + KBASE_TRACE_ADD(kbdev, JS_POLICY_TIMER_START, NULL, NULL, 0u, 0u); + policy_info->timer_running = MALI_TRUE; + } +} + +void kbasep_js_policy_runpool_remove_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs *policy_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + + { + struct kbase_device *kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_RUNPOOL_REMOVE_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt_nolock(kbdev, kctx)); + } + + /* ASSERT about scheduled-ness/queued-ness */ + kbasep_js_debug_check(policy_info, kctx, KBASEP_JS_CHECK_SCHEDULED); + + /* No searching or significant list maintenance required to remove this context */ + list_del(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); +} + +mali_bool kbasep_js_policy_should_remove_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_device_data *js_devdata; + u64 least_runtime_us; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + js_devdata = container_of(js_policy, struct kbasep_js_device_data, policy); + + if (ctx_info->process_rt_policy) + least_runtime_us = atomic64_read(&policy_info->rt_least_runtime_us); + else + least_runtime_us = atomic64_read(&policy_info->least_runtime_us); + + if (KBASEP_JS_RUNTIME_EMPTY == least_runtime_us) { + /* Queue is empty */ + return MALI_FALSE; + } + + if ((least_runtime_us + priority_weight(ctx_info, (u64) (js_devdata->ctx_timeslice_ns / 1000u))) + < ctx_info->runtime_us) { + /* The context is scheduled out if it's not the least-run context anymore. + * The "real" head runtime is used instead of the cached runtime so the current + * context is not scheduled out when there is less contexts than address spaces. + */ + return MALI_TRUE; + } + + return MALI_FALSE; +} + +void kbasep_js_policy_runpool_timers_sync(union kbasep_js_policy *js_policy) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + + policy_info = &js_policy->cfs; + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + js_devdata = &kbdev->js_data; + + if (!timer_callback_should_run(kbdev)) { + unsigned long flags; + + /* If the timer is running now, synchronize with it by + * locking/unlocking its spinlock, to ensure it's not using an old value + * from timer_callback_should_run() */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + /* From now on, return value of timer_callback_should_run() will also + * cause the timer to not requeue itself. Its return value cannot + * change, because it depends on variables updated with the + * runpool_mutex held, which the caller of this must also hold */ + hrtimer_cancel(&policy_info->scheduling_timer); + + policy_info->timer_running = MALI_FALSE; + } +} + +/* + * Job Chain Management + */ + +mali_error kbasep_js_policy_init_job(const union kbasep_js_policy *js_policy, const struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + const struct kbasep_js_policy_cfs *policy_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + + /* Determine the job's index into the job list head, will return error if the + * atom is malformed and so is reported. */ + return cached_variant_idx_init(policy_info, kctx, katom); +} + +void kbasep_js_policy_register_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + /* Adjust context priority to include the new job */ + ctx_info->bag_total_nr_atoms++; + ctx_info->bag_total_priority += katom->nice_prio; + + /* Get average priority and convert to NICE range -20..19 */ + if (ctx_info->bag_total_nr_atoms) + ctx_info->bag_priority = (ctx_info->bag_total_priority / ctx_info->bag_total_nr_atoms) - 20; +} + +void kbasep_js_policy_deregister_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + CSTD_UNUSED(js_policy); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + /* Adjust context priority to no longer include removed job */ + KBASE_DEBUG_ASSERT(ctx_info->bag_total_nr_atoms > 0); + ctx_info->bag_total_nr_atoms--; + ctx_info->bag_total_priority -= katom->nice_prio; + KBASE_DEBUG_ASSERT(ctx_info->bag_total_priority >= 0); + + /* Get average priority and convert to NICE range -20..19 */ + if (ctx_info->bag_total_nr_atoms) + ctx_info->bag_priority = (ctx_info->bag_total_priority / ctx_info->bag_total_nr_atoms) - 20; +} +KBASE_EXPORT_TEST_API(kbasep_js_policy_deregister_job) + +mali_bool kbasep_js_policy_dequeue_job(struct kbase_device *kbdev, + int job_slot_idx, + struct kbase_jd_atom ** const katom_ptr) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs *policy_info; + struct kbase_context *kctx; + u32 variants_supported; + struct list_head *pos; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom_ptr != NULL); + KBASE_DEBUG_ASSERT(job_slot_idx < BASE_JM_MAX_NR_SLOTS); + + js_devdata = &kbdev->js_data; + policy_info = &js_devdata->policy.cfs; + + /* Get the variants for this slot */ + if (kbdev->gpu_props.num_core_groups > 1 && kbasep_js_ctx_attr_is_attr_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES) != MALI_FALSE) { + /* SS-allcore state, and there's more than one coregroup */ + variants_supported = get_slot_to_variant_lookup(policy_info->slot_to_variant_lookup_ss_allcore_state, job_slot_idx); + } else { + /* SS-state */ + variants_supported = get_slot_to_variant_lookup(policy_info->slot_to_variant_lookup_ss_state, job_slot_idx); + } + + /* First pass through the runpool we consider the realtime priority jobs */ + list_for_each(pos, &policy_info->scheduled_ctxs_head) { + kctx = list_entry(pos, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + if (kctx->jctx.sched_info.runpool.policy_ctx.cfs.process_rt_policy) { + if (dequeue_job(kbdev, kctx, variants_supported, katom_ptr, job_slot_idx)) { + /* Realtime policy job matched */ + return MALI_TRUE; + } + } + } + + /* Second pass through the runpool we consider the non-realtime priority jobs */ + list_for_each(pos, &policy_info->scheduled_ctxs_head) { + kctx = list_entry(pos, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + if (kctx->jctx.sched_info.runpool.policy_ctx.cfs.process_rt_policy == MALI_FALSE) { + if (dequeue_job(kbdev, kctx, variants_supported, katom_ptr, job_slot_idx)) { + /* Non-realtime policy job matched */ + return MALI_TRUE; + } + } + } + + /* By this point, no contexts had a matching job */ + return MALI_FALSE; +} + +void kbasep_js_policy_enqueue_job(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom) +{ + struct kbasep_js_policy_cfs_job *job_info; + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbase_context *parent_ctx; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + parent_ctx = katom->kctx; + KBASE_DEBUG_ASSERT(parent_ctx != NULL); + + job_info = &katom->sched_info.cfs; + ctx_info = &parent_ctx->jctx.sched_info.runpool.policy_ctx.cfs; + + { + struct kbase_device *kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + KBASE_TRACE_ADD(kbdev, JS_POLICY_ENQUEUE_JOB, katom->kctx, katom, katom->jc, 0); + } + list_add_tail(&katom->sched_info.cfs.list, &ctx_info->job_list_head[job_info->cached_variant_idx]); +} + +void kbasep_js_policy_log_job_result(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom, u64 time_spent_us) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbase_context *parent_ctx; + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + CSTD_UNUSED(js_policy); + + parent_ctx = katom->kctx; + KBASE_DEBUG_ASSERT(parent_ctx != NULL); + + ctx_info = &parent_ctx->jctx.sched_info.runpool.policy_ctx.cfs; + + ctx_info->runtime_us += priority_weight(ctx_info, time_spent_us); + + katom->time_spent_us += time_spent_us; +} + +mali_bool kbasep_js_policy_ctx_has_priority(union kbasep_js_policy *js_policy, struct kbase_context *current_ctx, struct kbase_context *new_ctx) +{ + struct kbasep_js_policy_cfs_ctx *current_ctx_info; + struct kbasep_js_policy_cfs_ctx *new_ctx_info; + + KBASE_DEBUG_ASSERT(current_ctx != NULL); + KBASE_DEBUG_ASSERT(new_ctx != NULL); + CSTD_UNUSED(js_policy); + + current_ctx_info = ¤t_ctx->jctx.sched_info.runpool.policy_ctx.cfs; + new_ctx_info = &new_ctx->jctx.sched_info.runpool.policy_ctx.cfs; + + if ((current_ctx_info->process_rt_policy == MALI_FALSE) && (new_ctx_info->process_rt_policy == MALI_TRUE)) + return MALI_TRUE; + + if ((current_ctx_info->process_rt_policy == new_ctx_info->process_rt_policy) && (current_ctx_info->bag_priority > new_ctx_info->bag_priority)) + return MALI_TRUE; + + return MALI_FALSE; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.h new file mode 100644 index 0000000000000000000000000000000000000000..099f25799b4b8daa152337900cd1a30b3a8cdedc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.h @@ -0,0 +1,167 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_policy_cfs.h + * Completely Fair Job Scheduler Policy structure definitions + */ + +#ifndef _KBASE_JS_POLICY_CFS_H_ +#define _KBASE_JS_POLICY_CFS_H_ + +#define KBASE_JS_POLICY_AVAILABLE_CFS + +/** @addtogroup base_api + * @{ */ +/** @addtogroup base_kbase_api + * @{ */ +/** @addtogroup kbase_js_policy + * @{ */ + +/** + * Internally, this policy keeps a few internal queues for different variants + * of core requirements, which are used to decide how to schedule onto the + * different job slots. + * + * Must be a power of 2 to keep the lookup math simple + */ +#define KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS_LOG2 3 +#define KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS (1u << KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS_LOG2) + +/** Bits needed in the lookup to support all slots */ +#define KBASEP_JS_VARIANT_LOOKUP_BITS_NEEDED (BASE_JM_MAX_NR_SLOTS * KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS) +/** Number of u32s needed in the lookup array to support all slots */ +#define KBASEP_JS_VARIANT_LOOKUP_WORDS_NEEDED ((KBASEP_JS_VARIANT_LOOKUP_BITS_NEEDED + 31) / 32) + +#define KBASEP_JS_RUNTIME_EMPTY ((u64)-1) + +typedef struct kbasep_js_policy_cfs { + /** List of all contexts in the context queue. Hold + * kbasep_js_device_data::queue_mutex whilst accessing. */ + struct list_head ctx_queue_head; + + /** List of all contexts in the realtime (priority) context queue */ + struct list_head ctx_rt_queue_head; + + /** List of scheduled contexts. Hold kbasep_jd_device_data::runpool_irq::lock + * whilst accessing, which is a spinlock */ + struct list_head scheduled_ctxs_head; + + /** Number of valid elements in the core_req_variants member, and the + * kbasep_js_policy_rr_ctx::job_list_head array */ + u32 num_core_req_variants; + + /** Variants of the core requirements */ + struct kbasep_atom_req core_req_variants[KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS]; + + /* Lookups per job slot against which core_req_variants match it */ + u32 slot_to_variant_lookup_ss_state[KBASEP_JS_VARIANT_LOOKUP_WORDS_NEEDED]; + u32 slot_to_variant_lookup_ss_allcore_state[KBASEP_JS_VARIANT_LOOKUP_WORDS_NEEDED]; + + /* The timer tick used for rescheduling jobs */ + struct hrtimer scheduling_timer; + + /* Is the timer running? + * + * The kbasep_js_device_data::runpool_mutex must be held whilst modifying this. */ + mali_bool timer_running; + + /* Number of us the least-run context has been running for + * + * The kbasep_js_device_data::queue_mutex must be held whilst updating this + * Reads are possible without this mutex, but an older value might be read + * if no memory barriers are issued beforehand. */ + u64 head_runtime_us; + + /* Number of us the least-run context in the context queue has been running for. + * -1 if context queue is empty. */ + atomic64_t least_runtime_us; + + /* Number of us the least-run context in the realtime (priority) context queue + * has been running for. -1 if realtime context queue is empty. */ + atomic64_t rt_least_runtime_us; +} kbasep_js_policy_cfs; + +/** + * This policy contains a single linked list of all contexts. + */ +typedef struct kbasep_js_policy_cfs_ctx { + /** Link implementing the Policy's Queue, and Currently Scheduled list */ + struct list_head list; + + /** Job lists for use when in the Run Pool - only using + * kbasep_js_policy_fcfs::num_unique_slots of them. We still need to track + * the jobs when we're not in the runpool, so this member is accessed from + * outside the policy queue (for the first job), inside the policy queue, + * and inside the runpool. + * + * If the context is in the runpool, then this must only be accessed with + * kbasep_js_device_data::runpool_irq::lock held + * + * Jobs are still added to this list even when the context is not in the + * runpool. In that case, the kbasep_js_kctx_info::ctx::jsctx_mutex must be + * held before accessing this. */ + struct list_head job_list_head[KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS]; + + /** Number of us this context has been running for + * + * The kbasep_js_device_data::runpool_irq::lock (a spinlock) must be held + * whilst updating this. Initializing will occur on context init and + * context enqueue (which can only occur in one thread at a time), but + * multi-thread access only occurs while the context is in the runpool. + * + * Reads are possible without this spinlock, but an older value might be read + * if no memory barriers are issued beforehand */ + u64 runtime_us; + + /* Calling process policy scheme is a realtime scheduler and will use the priority queue + * Non-mutable after ctx init */ + mali_bool process_rt_policy; + /* Calling process NICE priority */ + int process_priority; + /* Average NICE priority of all atoms in bag: + * Hold the kbasep_js_kctx_info::ctx::jsctx_mutex when accessing */ + int bag_priority; + /* Total NICE priority of all atoms in bag + * Hold the kbasep_js_kctx_info::ctx::jsctx_mutex when accessing */ + int bag_total_priority; + /* Total number of atoms in the bag + * Hold the kbasep_js_kctx_info::ctx::jsctx_mutex when accessing */ + int bag_total_nr_atoms; + +} kbasep_js_policy_cfs_ctx; + +/** + * In this policy, each Job is part of at most one of the per_corereq lists + */ +typedef struct kbasep_js_policy_cfs_job { + struct list_head list; /**< Link implementing the Run Pool list/Jobs owned by the ctx */ + u32 cached_variant_idx; /**< Cached index of the list this should be entered into on re-queue */ + + /** Number of ticks that this job has been executing for + * + * To access this, the kbasep_js_device_data::runpool_irq::lock must be held */ + u32 ticks; +} kbasep_js_policy_cfs_job; + + /** @} *//* end group kbase_js_policy */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_linux.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_linux.h new file mode 100644 index 0000000000000000000000000000000000000000..0d024f27976125afb449a7fccdd1888ce301d46f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_linux.h @@ -0,0 +1,47 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_linux.h + * Base kernel APIs, Linux implementation. + */ + +#ifndef _KBASE_LINUX_H_ +#define _KBASE_LINUX_H_ + +/* All things that are needed for the Linux port. */ +#include +#include +#include +#include +#include + +#if defined(MALI_KERNEL_TEST_API) +#if (1 == MALI_KERNEL_TEST_API) +#define KBASE_EXPORT_TEST_API(func) EXPORT_SYMBOL(func); +#else +#define KBASE_EXPORT_TEST_API(func) +#endif +#else +#define KBASE_EXPORT_TEST_API(func) +#endif + +#define KBASE_EXPORT_SYMBOL(func) EXPORT_SYMBOL(func); + +#endif /* _KBASE_LINUX_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.c new file mode 100644 index 0000000000000000000000000000000000000000..77a43a414973e47b836ca8d12322be040b88049c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.c @@ -0,0 +1,1357 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem.c + * Base kernel memory APIs + */ +#ifdef CONFIG_DMA_SHARED_BUFFER +#include +#endif /* CONFIG_DMA_SHARED_BUFFER */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +atomic_t g_mtk_gpu_total_memory_usage_in_pages; +atomic_t g_mtk_gpu_peak_memory_usage_in_pages; + +KBASE_EXPORT_TEST_API(kbase_report_gpu_memory_usage) +unsigned int kbase_report_gpu_memory_usage() +{ +#if 0 + ssize_t ret = 0; + struct list_head *entry; + const struct list_head *kbdev_list; + int pages = 0; + kbdev_list = kbase_dev_list_get(); + list_for_each(entry, kbdev_list) { + struct kbase_device *kbdev = NULL; + kbasep_kctx_list_element *element; + kbdev = list_entry(entry, struct kbase_device, entry); + pages = atomic_read(&(kbdev->memdev.used_pages)); + } + kbase_dev_list_put(kbdev_list); +#endif + return (atomic_read(&g_mtk_gpu_total_memory_usage_in_pages)*4096); +} + +int kbase_report_gpu_memory_peak() +{ + return (atomic_read(&g_mtk_gpu_peak_memory_usage_in_pages)*4096); +} + +/** + * @brief Check the zone compatibility of two regions. + */ +STATIC int kbase_region_tracker_match_zone(struct kbase_va_region *reg1, struct kbase_va_region *reg2) +{ + return ((reg1->flags & KBASE_REG_ZONE_MASK) == (reg2->flags & KBASE_REG_ZONE_MASK)); +} + +KBASE_EXPORT_TEST_API(kbase_region_tracker_match_zone) + +/* This function inserts a region into the tree. */ +static void kbase_region_tracker_insert(struct kbase_context *kctx, struct kbase_va_region *new_reg) +{ + u64 start_pfn = new_reg->start_pfn; + struct rb_node **link = &(kctx->reg_rbtree.rb_node); + struct rb_node *parent = NULL; + + /* Find the right place in the tree using tree search */ + while (*link) { + struct kbase_va_region *old_reg; + + parent = *link; + old_reg = rb_entry(parent, struct kbase_va_region, rblink); + + /* RBTree requires no duplicate entries. */ + KBASE_DEBUG_ASSERT(old_reg->start_pfn != start_pfn); + + if (old_reg->start_pfn > start_pfn) + link = &(*link)->rb_left; + else + link = &(*link)->rb_right; + } + + /* Put the new node there, and rebalance tree */ + rb_link_node(&(new_reg->rblink), parent, link); + rb_insert_color(&(new_reg->rblink), &(kctx->reg_rbtree)); +} + +/* Find allocated region enclosing free range. */ +static struct kbase_va_region *kbase_region_tracker_find_region_enclosing_range_free( + struct kbase_context *kctx, u64 start_pfn, size_t nr_pages) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + + u64 end_pfn = start_pfn + nr_pages; + + rbnode = kctx->reg_rbtree.rb_node; + while (rbnode) { + u64 tmp_start_pfn, tmp_end_pfn; + + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + tmp_start_pfn = reg->start_pfn; + tmp_end_pfn = reg->start_pfn + reg->nr_pages; + + /* If start is lower than this, go left. */ + if (start_pfn < tmp_start_pfn) + rbnode = rbnode->rb_left; + /* If end is higher than this, then go right. */ + else if (end_pfn > tmp_end_pfn) + rbnode = rbnode->rb_right; + else /* Enclosing */ + return reg; + } + + return NULL; +} + +/* Find region enclosing given address. */ +struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(struct kbase_context *kctx, mali_addr64 gpu_addr) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + u64 gpu_pfn = gpu_addr >> PAGE_SHIFT; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + rbnode = kctx->reg_rbtree.rb_node; + while (rbnode) { + u64 tmp_start_pfn, tmp_end_pfn; + + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + tmp_start_pfn = reg->start_pfn; + tmp_end_pfn = reg->start_pfn + reg->nr_pages; + + /* If start is lower than this, go left. */ + if (gpu_pfn < tmp_start_pfn) + rbnode = rbnode->rb_left; + /* If end is higher than this, then go right. */ + else if (gpu_pfn >= tmp_end_pfn) + rbnode = rbnode->rb_right; + else /* Enclosing */ + return reg; + } + + return NULL; +} + +KBASE_EXPORT_TEST_API(kbase_region_tracker_find_region_enclosing_address) + +/* Find region with given base address */ +struct kbase_va_region *kbase_region_tracker_find_region_base_address(struct kbase_context *kctx, mali_addr64 gpu_addr) +{ + u64 gpu_pfn = gpu_addr >> PAGE_SHIFT; + struct rb_node *rbnode; + struct kbase_va_region *reg; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + rbnode = kctx->reg_rbtree.rb_node; + while (rbnode) { + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + if (reg->start_pfn > gpu_pfn) + rbnode = rbnode->rb_left; + else if (reg->start_pfn < gpu_pfn) + rbnode = rbnode->rb_right; + else if (gpu_pfn == reg->start_pfn) + return reg; + else + rbnode = NULL; + } + + return NULL; +} + +KBASE_EXPORT_TEST_API(kbase_region_tracker_find_region_base_address) + +/* Find region meeting given requirements */ +static struct kbase_va_region *kbase_region_tracker_find_region_meeting_reqs(struct kbase_context *kctx, struct kbase_va_region *reg_reqs, size_t nr_pages, size_t align) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + + /* Note that this search is a linear search, as we do not have a target + address in mind, so does not benefit from the rbtree search */ + rbnode = rb_first(&(kctx->reg_rbtree)); + while (rbnode) { + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + if ((reg->nr_pages >= nr_pages) && + (reg->flags & KBASE_REG_FREE) && + kbase_region_tracker_match_zone(reg, reg_reqs)) { + /* Check alignment */ + u64 start_pfn = (reg->start_pfn + align - 1) & ~(align - 1); + + if ((start_pfn >= reg->start_pfn) && + (start_pfn <= (reg->start_pfn + reg->nr_pages - 1)) && + ((start_pfn + nr_pages - 1) <= (reg->start_pfn + reg->nr_pages - 1))) + return reg; + } + rbnode = rb_next(rbnode); + } + + return NULL; +} + +/** + * @brief Remove a region object from the global list. + * + * The region reg is removed, possibly by merging with other free and + * compatible adjacent regions. It must be called with the context + * region lock held. The associated memory is not released (see + * kbase_free_alloced_region). Internal use only. + */ +STATIC mali_error kbase_remove_va_region(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + struct rb_node *rbprev; + struct kbase_va_region *prev = NULL; + struct rb_node *rbnext; + struct kbase_va_region *next = NULL; + + int merged_front = 0; + int merged_back = 0; + mali_error err = MALI_ERROR_NONE; + + /* Try to merge with the previous block first */ + rbprev = rb_prev(&(reg->rblink)); + if (rbprev) { + prev = rb_entry(rbprev, struct kbase_va_region, rblink); + if ((prev->flags & KBASE_REG_FREE) && kbase_region_tracker_match_zone(prev, reg)) { + /* We're compatible with the previous VMA, merge with it */ + prev->nr_pages += reg->nr_pages; + rb_erase(&(reg->rblink), &kctx->reg_rbtree); + reg = prev; + merged_front = 1; + } + } + + /* Try to merge with the next block second */ + /* Note we do the lookup here as the tree may have been rebalanced. */ + rbnext = rb_next(&(reg->rblink)); + if (rbnext) { + /* We're compatible with the next VMA, merge with it */ + next = rb_entry(rbnext, struct kbase_va_region, rblink); + if ((next->flags & KBASE_REG_FREE) && kbase_region_tracker_match_zone(next, reg)) { + next->start_pfn = reg->start_pfn; + next->nr_pages += reg->nr_pages; + rb_erase(&(reg->rblink), &kctx->reg_rbtree); + merged_back = 1; + if (merged_front) { + /* We already merged with prev, free it */ + kbase_free_alloced_region(reg); + } + } + } + + /* If we failed to merge then we need to add a new block */ + if (!(merged_front || merged_back)) { + /* + * We didn't merge anything. Add a new free + * placeholder and remove the original one. + */ + struct kbase_va_region *free_reg; + + free_reg = kbase_alloc_free_region(kctx, reg->start_pfn, reg->nr_pages, reg->flags & KBASE_REG_ZONE_MASK); + if (!free_reg) { + err = MALI_ERROR_OUT_OF_MEMORY; + goto out; + } + + rb_replace_node(&(reg->rblink), &(free_reg->rblink), &(kctx->reg_rbtree)); + } + + out: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_remove_va_region) + +/** + * @brief Insert a VA region to the list, replacing the current at_reg. + */ +static mali_error kbase_insert_va_region_nolock(struct kbase_context *kctx, struct kbase_va_region *new_reg, struct kbase_va_region *at_reg, u64 start_pfn, size_t nr_pages) +{ + mali_error err = MALI_ERROR_NONE; + + /* Must be a free region */ + KBASE_DEBUG_ASSERT((at_reg->flags & KBASE_REG_FREE) != 0); + /* start_pfn should be contained within at_reg */ + KBASE_DEBUG_ASSERT((start_pfn >= at_reg->start_pfn) && (start_pfn < at_reg->start_pfn + at_reg->nr_pages)); + /* at least nr_pages from start_pfn should be contained within at_reg */ + KBASE_DEBUG_ASSERT(start_pfn + nr_pages <= at_reg->start_pfn + at_reg->nr_pages); + + new_reg->start_pfn = start_pfn; + new_reg->nr_pages = nr_pages; + + /* Regions are a whole use, so swap and delete old one. */ + if (at_reg->start_pfn == start_pfn && at_reg->nr_pages == nr_pages) { + rb_replace_node(&(at_reg->rblink), &(new_reg->rblink), &(kctx->reg_rbtree)); + kbase_free_alloced_region(at_reg); + } + /* New region replaces the start of the old one, so insert before. */ + else if (at_reg->start_pfn == start_pfn) { + at_reg->start_pfn += nr_pages; + KBASE_DEBUG_ASSERT(at_reg->nr_pages >= nr_pages); + at_reg->nr_pages -= nr_pages; + + kbase_region_tracker_insert(kctx, new_reg); + } + /* New region replaces the end of the old one, so insert after. */ + else if ((at_reg->start_pfn + at_reg->nr_pages) == (start_pfn + nr_pages)) { + at_reg->nr_pages -= nr_pages; + + kbase_region_tracker_insert(kctx, new_reg); + } + /* New region splits the old one, so insert and create new */ + else { + struct kbase_va_region *new_front_reg; + + new_front_reg = kbase_alloc_free_region(kctx, + at_reg->start_pfn, + start_pfn - at_reg->start_pfn, + at_reg->flags & KBASE_REG_ZONE_MASK); + + if (new_front_reg) { + at_reg->nr_pages -= nr_pages + new_front_reg->nr_pages; + at_reg->start_pfn = start_pfn + nr_pages; + + kbase_region_tracker_insert(kctx, new_front_reg); + kbase_region_tracker_insert(kctx, new_reg); + } else { + err = MALI_ERROR_OUT_OF_MEMORY; + } + } + + return err; +} + +/** + * @brief Add a VA region to the list. + */ +mali_error kbase_add_va_region(struct kbase_context *kctx, + struct kbase_va_region *reg, mali_addr64 addr, + size_t nr_pages, size_t align) +{ + struct kbase_va_region *tmp; + u64 gpu_pfn = addr >> PAGE_SHIFT; + mali_error err = MALI_ERROR_NONE; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + + lockdep_assert_held(&kctx->reg_lock); + + if (!align) + align = 1; + + /* must be a power of 2 */ + KBASE_DEBUG_ASSERT((align & (align - 1)) == 0); + KBASE_DEBUG_ASSERT(nr_pages > 0); + + /* Path 1: Map a specific address. Find the enclosing region, which *must* be free. */ + if (gpu_pfn) { + struct device *dev = kctx->kbdev->dev; + + KBASE_DEBUG_ASSERT(!(gpu_pfn & (align - 1))); + + tmp = kbase_region_tracker_find_region_enclosing_range_free(kctx, gpu_pfn, nr_pages); + if (!tmp) { + dev_warn(dev, "Enclosing region not found: 0x%08llx gpu_pfn, %zu nr_pages", gpu_pfn, nr_pages); + err = MALI_ERROR_OUT_OF_GPU_MEMORY; + goto exit; + } + + if ((!kbase_region_tracker_match_zone(tmp, reg)) || + (!(tmp->flags & KBASE_REG_FREE))) { + dev_warn(dev, "Zone mismatch: %lu != %lu", tmp->flags & KBASE_REG_ZONE_MASK, reg->flags & KBASE_REG_ZONE_MASK); + dev_warn(dev, "!(tmp->flags & KBASE_REG_FREE): tmp->start_pfn=0x%llx tmp->flags=0x%lx tmp->nr_pages=0x%zx gpu_pfn=0x%llx nr_pages=0x%zx\n", tmp->start_pfn, tmp->flags, tmp->nr_pages, gpu_pfn, nr_pages); + dev_warn(dev, "in function %s (%p, %p, 0x%llx, 0x%zx, 0x%zx)\n", __func__, kctx, reg, addr, nr_pages, align); + err = MALI_ERROR_OUT_OF_GPU_MEMORY; + goto exit; + } + + err = kbase_insert_va_region_nolock(kctx, reg, tmp, gpu_pfn, nr_pages); + if (err) { + dev_warn(dev, "Failed to insert va region"); + err = MALI_ERROR_OUT_OF_GPU_MEMORY; + goto exit; + } + + goto exit; + } + + /* Path 2: Map any free address which meets the requirements. */ + { + u64 start_pfn; + + tmp = kbase_region_tracker_find_region_meeting_reqs(kctx, reg, nr_pages, align); + if (!tmp) { + err = MALI_ERROR_OUT_OF_GPU_MEMORY; + goto exit; + } + start_pfn = (tmp->start_pfn + align - 1) & ~(align - 1); + err = kbase_insert_va_region_nolock(kctx, reg, tmp, start_pfn, nr_pages); + } + + exit: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_add_va_region) + +/** + * @brief Initialize the internal region tracker data structure. + */ +static void kbase_region_tracker_ds_init(struct kbase_context *kctx, struct kbase_va_region *same_va_reg, struct kbase_va_region *exec_reg, struct kbase_va_region *custom_va_reg) +{ + kctx->reg_rbtree = RB_ROOT; + kbase_region_tracker_insert(kctx, same_va_reg); + + /* exec and custom_va_reg doesn't always exist */ + if (exec_reg && custom_va_reg) { + kbase_region_tracker_insert(kctx, exec_reg); + kbase_region_tracker_insert(kctx, custom_va_reg); + } +} + +void kbase_region_tracker_term(struct kbase_context *kctx) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + + do { + rbnode = rb_first(&(kctx->reg_rbtree)); + if (rbnode) { + rb_erase(rbnode, &(kctx->reg_rbtree)); + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + kbase_free_alloced_region(reg); + } + } while (rbnode); +} + +/** + * Initialize the region tracker data structure. + */ +mali_error kbase_region_tracker_init(struct kbase_context *kctx) +{ + struct kbase_va_region *same_va_reg; + struct kbase_va_region *exec_reg = NULL; + struct kbase_va_region *custom_va_reg = NULL; + size_t same_va_bits = sizeof(void *) * BITS_PER_BYTE; + u64 custom_va_size = KBASE_REG_ZONE_CUSTOM_VA_SIZE; + u64 gpu_va_limit = (1ULL << kctx->kbdev->gpu_props.mmu.va_bits) >> PAGE_SHIFT; + +#if defined(CONFIG_ARM64) + same_va_bits = VA_BITS; +#elif defined(CONFIG_X86_64) + same_va_bits = 47; +#elif defined(CONFIG_64BIT) +#error Unsupported 64-bit architecture +#endif + +#ifdef CONFIG_64BIT + if (kctx->is_compat) + same_va_bits = 32; + else if (kbase_hw_has_feature(kctx->kbdev, BASE_HW_FEATURE_33BIT_VA)) + same_va_bits = 33; +#endif + + if (kctx->kbdev->gpu_props.mmu.va_bits < same_va_bits) + return MALI_ERROR_FUNCTION_FAILED; + + /* all have SAME_VA */ + same_va_reg = kbase_alloc_free_region(kctx, 1, + (1ULL << (same_va_bits - PAGE_SHIFT)) - 2, + KBASE_REG_ZONE_SAME_VA); + + if (!same_va_reg) + return MALI_ERROR_OUT_OF_MEMORY; + +#ifdef CONFIG_64BIT + /* only 32-bit clients have the other two zones */ + if (kctx->is_compat) { +#endif + if (gpu_va_limit <= KBASE_REG_ZONE_CUSTOM_VA_BASE) { + kbase_free_alloced_region(same_va_reg); + return MALI_ERROR_FUNCTION_FAILED; + } + /* If the current size of TMEM is out of range of the + * virtual address space addressable by the MMU then + * we should shrink it to fit + */ + if ((KBASE_REG_ZONE_CUSTOM_VA_BASE + KBASE_REG_ZONE_CUSTOM_VA_SIZE) >= gpu_va_limit) + custom_va_size = gpu_va_limit - KBASE_REG_ZONE_CUSTOM_VA_BASE; + + exec_reg = kbase_alloc_free_region(kctx, + KBASE_REG_ZONE_EXEC_BASE, + KBASE_REG_ZONE_EXEC_SIZE, + KBASE_REG_ZONE_EXEC); + + if (!exec_reg) { + kbase_free_alloced_region(same_va_reg); + return MALI_ERROR_OUT_OF_MEMORY; + } + + custom_va_reg = kbase_alloc_free_region(kctx, + KBASE_REG_ZONE_CUSTOM_VA_BASE, + custom_va_size, KBASE_REG_ZONE_CUSTOM_VA); + + if (!custom_va_reg) { + kbase_free_alloced_region(same_va_reg); + kbase_free_alloced_region(exec_reg); + return MALI_ERROR_OUT_OF_MEMORY; + } +#ifdef CONFIG_64BIT + } +#endif + + kbase_region_tracker_ds_init(kctx, same_va_reg, exec_reg, custom_va_reg); + + return MALI_ERROR_NONE; +} + +mali_error kbase_mem_init(struct kbase_device *kbdev) +{ + struct kbasep_mem_device *memdev; + + KBASE_DEBUG_ASSERT(kbdev); + + memdev = &kbdev->memdev; + + /* Initialize memory usage */ + atomic_set(&memdev->used_pages, 0); + + atomic_set(&g_mtk_gpu_total_memory_usage_in_pages, 0); + + atomic_set(&g_mtk_gpu_peak_memory_usage_in_pages, 0); + + /* nothing to do, zero-inited when struct kbase_device was created */ + return MALI_ERROR_NONE; +} + +void kbase_mem_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbase_mem_term(struct kbase_device *kbdev) +{ + struct kbasep_mem_device *memdev; + int pages; + + KBASE_DEBUG_ASSERT(kbdev); + + memdev = &kbdev->memdev; + + pages = atomic_read(&memdev->used_pages); + if (pages != 0) + dev_warn(kbdev->dev, "%s: %d pages in use!\n", __func__, pages); +} + +KBASE_EXPORT_TEST_API(kbase_mem_term) + +/** + * @brief Wait for GPU write flush - only in use for BASE_HW_ISSUE_6367 + * + * Wait 1000 GPU clock cycles. This delay is known to give the GPU time to flush its write buffer. + * @note If GPU resets occur then the counters are reset to zero, the delay may not be as expected. + */ +#ifndef CONFIG_MALI_NO_MALI +void kbase_wait_write_flush(struct kbase_context *kctx) +{ + u32 base_count = 0; + + /* A suspend won't happen here, because we're in a syscall from a userspace thread */ + kbase_pm_context_active(kctx->kbdev); + kbase_pm_request_gpu_cycle_counter(kctx->kbdev); + + while (MALI_TRUE) { + u32 new_count; + + new_count = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(CYCLE_COUNT_LO), NULL); + /* First time around, just store the count. */ + if (base_count == 0) { + base_count = new_count; + continue; + } + + /* No need to handle wrapping, unsigned maths works for this. */ + if ((new_count - base_count) > 1000) + break; + } + + kbase_pm_release_gpu_cycle_counter(kctx->kbdev); + kbase_pm_context_idle(kctx->kbdev); +} +#endif /* CONFIG_MALI_NO_MALI */ + + + +/** + * @brief Allocate a free region object. + * + * The allocated object is not part of any list yet, and is flagged as + * KBASE_REG_FREE. No mapping is allocated yet. + * + * zone is KBASE_REG_ZONE_CUSTOM_VA, KBASE_REG_ZONE_SAME_VA, or KBASE_REG_ZONE_EXEC + * + */ +struct kbase_va_region *kbase_alloc_free_region(struct kbase_context *kctx, u64 start_pfn, size_t nr_pages, int zone) +{ + struct kbase_va_region *new_reg; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* zone argument should only contain zone related region flags */ + KBASE_DEBUG_ASSERT((zone & ~KBASE_REG_ZONE_MASK) == 0); + KBASE_DEBUG_ASSERT(nr_pages > 0); + KBASE_DEBUG_ASSERT(start_pfn + nr_pages <= (UINT64_MAX / PAGE_SIZE)); /* 64-bit address range is the max */ + + new_reg = kzalloc(sizeof(*new_reg), GFP_KERNEL); + + if (!new_reg) { + dev_warn(kctx->kbdev->dev, "kzalloc failed"); + return NULL; + } + + new_reg->alloc = NULL; /* no alloc bound yet */ + new_reg->kctx = kctx; + new_reg->flags = zone | KBASE_REG_FREE; + + new_reg->flags |= KBASE_REG_GROWABLE; + + /* Set up default MEMATTR usage */ + new_reg->flags |= KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_DEFAULT); + + new_reg->start_pfn = start_pfn; + new_reg->nr_pages = nr_pages; + + return new_reg; +} + +KBASE_EXPORT_TEST_API(kbase_alloc_free_region) + +/** + * @brief Free a region object. + * + * The described region must be freed of any mapping. + * + * If the region is not flagged as KBASE_REG_FREE, the region's + * alloc object will be released. + * It is a bug if no alloc object exists for non-free regions. + * + */ +void kbase_free_alloced_region(struct kbase_va_region *reg) +{ + KBASE_DEBUG_ASSERT(NULL != reg); + if (!(reg->flags & KBASE_REG_FREE)) { + kbase_mem_phy_alloc_put(reg->alloc); + /* To detect use-after-free in debug builds */ + KBASE_DEBUG_CODE(reg->flags |= KBASE_REG_FREE); + } + kfree(reg); +} + +KBASE_EXPORT_TEST_API(kbase_free_alloced_region) + +void kbase_mmu_update(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbase_as *as; + struct kbase_mmu_setup *current_setup; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + /* ASSERT that the context has a valid as_nr, which is only the case + * when it's scheduled in. + * + * as_nr won't change because the caller has the runpool_irq lock */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + kbdev = kctx->kbdev; + as = &kbdev->as[kctx->as_nr]; + current_setup = &as->current_setup; + + /* Use GPU implementation-defined caching policy. */ + current_setup->memattr = kctx->mem_attrs; + + current_setup->transtab = (u64) kctx->pgd & ((0xFFFFFFFFULL << 32) | AS_TRANSTAB_ADDR_SPACE_MASK); + current_setup->transtab |= AS_TRANSTAB_READ_INNER | + AS_TRANSTAB_ADRMODE_TABLE; + + /* Apply the address space setting */ + kbase_mmu_hw_configure(kbdev, as, kctx); +} + +KBASE_EXPORT_TEST_API(kbase_mmu_update) + +void kbase_mmu_disable(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbase_as *as; + struct kbase_mmu_setup *current_setup; + + KBASE_DEBUG_ASSERT(NULL != kctx); + /* ASSERT that the context has a valid as_nr, which is only the case + * when it's scheduled in. + * + * as_nr won't change because the caller has the runpool_irq lock */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + kbdev = kctx->kbdev; + as = &kbdev->as[kctx->as_nr]; + current_setup = &as->current_setup; + + current_setup->transtab = 0ULL; + + /* Apply the address space setting */ + kbase_mmu_hw_configure(kbdev, as, kctx); +} + +KBASE_EXPORT_TEST_API(kbase_mmu_disable) + +mali_error kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, mali_addr64 addr, size_t nr_pages, size_t align) +{ + mali_error err; + size_t i = 0; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + + err = kbase_add_va_region(kctx, reg, addr, nr_pages, align); + if (MALI_ERROR_NONE != err) + return err; + + if (reg->alloc->type == KBASE_MEM_TYPE_ALIAS) { + u64 stride; + + stride = reg->alloc->imported.alias.stride; + KBASE_DEBUG_ASSERT(reg->alloc->imported.alias.aliased); + for (i = 0; i < reg->alloc->imported.alias.nents; i++) { + if (reg->alloc->imported.alias.aliased[i].alloc) { + err = kbase_mmu_insert_pages(kctx, + reg->start_pfn + (i * stride), + reg->alloc->imported.alias.aliased[i].alloc->pages + reg->alloc->imported.alias.aliased[i].offset, + reg->alloc->imported.alias.aliased[i].length, + reg->flags); + if (MALI_ERROR_NONE != err) + goto bad_insert; + + kbase_mem_phy_alloc_gpu_mapped(reg->alloc->imported.alias.aliased[i].alloc); + } else { + err = kbase_mmu_insert_single_page(kctx, + reg->start_pfn + i * stride, + kctx->aliasing_sink_page, + reg->alloc->imported.alias.aliased[i].length, + (reg->flags & ~KBASE_REG_MEMATTR_MASK) | KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_WRITE_ALLOC) + ); + if (MALI_ERROR_NONE != err) + goto bad_insert; + } + } + } else { + err = kbase_mmu_insert_pages(kctx, reg->start_pfn, + kbase_get_phy_pages(reg), + kbase_reg_current_backed_size(reg), + reg->flags); + if (MALI_ERROR_NONE != err) + goto bad_insert; + kbase_mem_phy_alloc_gpu_mapped(reg->alloc); + } + + return err; + +bad_insert: + if (reg->alloc->type == KBASE_MEM_TYPE_ALIAS) { + u64 stride; + + stride = reg->alloc->imported.alias.stride; + KBASE_DEBUG_ASSERT(reg->alloc->imported.alias.aliased); + while (i--) + if (reg->alloc->imported.alias.aliased[i].alloc) { + kbase_mmu_teardown_pages(kctx, reg->start_pfn + (i * stride), reg->alloc->imported.alias.aliased[i].length); + kbase_mem_phy_alloc_gpu_unmapped(reg->alloc->imported.alias.aliased[i].alloc); + } + } + + kbase_remove_va_region(kctx, reg); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_gpu_mmap) + +mali_error kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + mali_error err; + + if (reg->start_pfn == 0) + return MALI_ERROR_NONE; + + if (reg->alloc && reg->alloc->type == KBASE_MEM_TYPE_ALIAS) { + size_t i; + + err = kbase_mmu_teardown_pages(kctx, reg->start_pfn, reg->nr_pages); + KBASE_DEBUG_ASSERT(reg->alloc->imported.alias.aliased); + for (i = 0; i < reg->alloc->imported.alias.nents; i++) + if (reg->alloc->imported.alias.aliased[i].alloc) + kbase_mem_phy_alloc_gpu_unmapped(reg->alloc->imported.alias.aliased[i].alloc); + } else { + err = kbase_mmu_teardown_pages(kctx, reg->start_pfn, kbase_reg_current_backed_size(reg)); + kbase_mem_phy_alloc_gpu_unmapped(reg->alloc); + } + + if (MALI_ERROR_NONE != err) + return err; + + err = kbase_remove_va_region(kctx, reg); + return err; +} + +STATIC struct kbase_cpu_mapping *kbasep_find_enclosing_cpu_mapping_of_region(const struct kbase_va_region *reg, unsigned long uaddr, size_t size) +{ + struct kbase_cpu_mapping *map; + struct list_head *pos; + + KBASE_DEBUG_ASSERT(NULL != reg); + KBASE_DEBUG_ASSERT(reg->alloc); + + if ((uintptr_t) uaddr + size < (uintptr_t) uaddr) /* overflow check */ + return NULL; + + list_for_each(pos, ®->alloc->mappings) { + map = list_entry(pos, kbase_cpu_mapping, mappings_list); + if (map->vm_start <= uaddr && map->vm_end >= uaddr + size) + return map; + } + + return NULL; +} + +KBASE_EXPORT_TEST_API(kbasep_find_enclosing_cpu_mapping_of_region) + +mali_error kbasep_find_enclosing_cpu_mapping_offset( + struct kbase_context *kctx, mali_addr64 gpu_addr, + unsigned long uaddr, size_t size, mali_size64 *offset) +{ + struct kbase_cpu_mapping *map = NULL; + const struct kbase_va_region *reg; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbase_gpu_vm_lock(kctx); + + reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); + if (reg && !(reg->flags & KBASE_REG_FREE)) { + map = kbasep_find_enclosing_cpu_mapping_of_region(reg, uaddr, + size); + if (map) { + *offset = (uaddr - PTR_TO_U64(map->vm_start)) + + (map->page_off << PAGE_SHIFT); + err = MALI_ERROR_NONE; + } + } + + kbase_gpu_vm_unlock(kctx); + + return err; +} + +KBASE_EXPORT_TEST_API(kbasep_find_enclosing_cpu_mapping_offset) + +void kbase_sync_single(struct kbase_context *kctx, + phys_addr_t pa, size_t size, kbase_sync_kmem_fn sync_fn) +{ + struct page *p = pfn_to_page(PFN_DOWN(pa)); + off_t offset = pa & ~PAGE_MASK; + dma_addr_t dma_addr; + + BUG_ON(!p); + BUG_ON(offset + size > PAGE_SIZE); + + dma_addr = kbase_dma_addr(p) + offset; + + sync_fn(kctx->kbdev->dev, dma_addr, size, DMA_BIDIRECTIONAL); +} + +static mali_error kbase_do_syncset(struct kbase_context *kctx, struct base_syncset *set, kbase_sync_kmem_fn sync_fn) +{ + mali_error err = MALI_ERROR_NONE; + struct basep_syncset *sset = &set->basep_sset; + struct kbase_va_region *reg; + struct kbase_cpu_mapping *map; + unsigned long start; + size_t size; + phys_addr_t *pa; + u64 page_off, page_count; + u64 i; + unsigned int offset; + + kbase_os_mem_map_lock(kctx); + kbase_gpu_vm_lock(kctx); + + /* find the region where the virtual address is contained */ + reg = kbase_region_tracker_find_region_enclosing_address(kctx, sset->mem_handle); + if (!reg) { + dev_warn(kctx->kbdev->dev, "Can't find region at VA 0x%016llX", sset->mem_handle); + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + if (!(reg->flags & KBASE_REG_CPU_CACHED)) + goto out_unlock; + + start = (uintptr_t)sset->user_addr; + size = (size_t)sset->size; + + map = kbasep_find_enclosing_cpu_mapping_of_region(reg, start, size); + if (!map) { + dev_warn(kctx->kbdev->dev, "Can't find CPU mapping 0x%016lX for VA 0x%016llX", start, sset->mem_handle); + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + offset = start & (PAGE_SIZE - 1); + page_off = map->page_off + ((start - map->vm_start) >> PAGE_SHIFT); + page_count = (size + offset + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pa = kbase_get_phy_pages(reg); + + /* Sync first page */ + if (pa[page_off]) { + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + + kbase_sync_single(kctx, pa[page_off] + offset, sz, sync_fn); + } + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + /* we grow upwards, so bail on first non-present page */ + if (!pa[page_off + i]) + break; + + kbase_sync_single(kctx, pa[page_off + i], PAGE_SIZE, sync_fn); + } + + /* Sync last page (if any) */ + if (page_count > 1 && pa[page_off + page_count - 1]) { + size_t sz = ((start + size - 1) & ~PAGE_MASK) + 1; + + kbase_sync_single(kctx, pa[page_off + page_count - 1], sz, + sync_fn); + } + +out_unlock: + kbase_gpu_vm_unlock(kctx); + kbase_os_mem_map_unlock(kctx); + return err; +} + +mali_error kbase_sync_now(struct kbase_context *kctx, struct base_syncset *syncset) +{ + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct basep_syncset *sset; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != syncset); + + sset = &syncset->basep_sset; + + switch (sset->type) { + case BASE_SYNCSET_OP_MSYNC: + err = kbase_do_syncset(kctx, syncset, dma_sync_single_for_device); + break; + + case BASE_SYNCSET_OP_CSYNC: + err = kbase_do_syncset(kctx, syncset, dma_sync_single_for_cpu); + break; + + default: + dev_warn(kctx->kbdev->dev, "Unknown msync op %d\n", sset->type); + break; + } + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_sync_now) + +/* vm lock must be held */ +mali_error kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + mali_error err; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + BUG_ON(!mutex_is_locked(&kctx->reg_lock)); + err = kbase_gpu_munmap(kctx, reg); + if (err) { + dev_warn(reg->kctx->kbdev->dev, "Could not unmap from the GPU...\n"); + goto out; + } + + if (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_6367)) { + /* Wait for GPU to flush write buffer before freeing physical pages */ + kbase_wait_write_flush(kctx); + } + + /* This will also free the physical pages */ + kbase_free_alloced_region(reg); + + out: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mem_free_region) + +/** + * @brief Free the region from the GPU and unregister it. + * + * This function implements the free operation on a memory segment. + * It will loudly fail if called with outstanding mappings. + */ +mali_error kbase_mem_free(struct kbase_context *kctx, mali_addr64 gpu_addr) +{ + mali_error err = MALI_ERROR_NONE; + struct kbase_va_region *reg; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + if (0 == gpu_addr) { + dev_warn(kctx->kbdev->dev, "gpu_addr 0 is reserved for the ringbuffer and it's an error to try to free it using kbase_mem_free\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + kbase_gpu_vm_lock(kctx); + + if (gpu_addr >= BASE_MEM_COOKIE_BASE && + gpu_addr < BASE_MEM_FIRST_FREE_ADDRESS) { + int cookie = PFN_DOWN(gpu_addr - BASE_MEM_COOKIE_BASE); + + reg = kctx->pending_regions[cookie]; + if (!reg) { + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + /* ask to unlink the cookie as we'll free it */ + + kctx->pending_regions[cookie] = NULL; + kctx->cookies |= (1UL << cookie); + + kbase_free_alloced_region(reg); + } else { + /* A real GPU va */ + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) { + dev_warn(kctx->kbdev->dev, "kbase_mem_free called with nonexistent gpu_addr 0x%llX", + gpu_addr); + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + if ((reg->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_SAME_VA) { + /* SAME_VA must be freed through munmap */ + dev_warn(kctx->kbdev->dev, "%s called on SAME_VA memory 0x%llX", __func__, + gpu_addr); + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + err = kbase_mem_free_region(kctx, reg); + } + + out_unlock: + kbase_gpu_vm_unlock(kctx); + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mem_free) + +void kbase_update_region_flags(struct kbase_va_region *reg, unsigned long flags) +{ + KBASE_DEBUG_ASSERT(NULL != reg); + KBASE_DEBUG_ASSERT((flags & ~((1ul << BASE_MEM_FLAGS_NR_BITS) - 1)) == 0); + + reg->flags |= kbase_cache_enabled(flags, reg->nr_pages); + /* all memory is now growable */ + reg->flags |= KBASE_REG_GROWABLE; + + if (flags & BASE_MEM_GROW_ON_GPF) + reg->flags |= KBASE_REG_PF_GROW; + + if (flags & BASE_MEM_PROT_CPU_WR) + reg->flags |= KBASE_REG_CPU_WR; + + if (flags & BASE_MEM_PROT_CPU_RD) + reg->flags |= KBASE_REG_CPU_RD; + + if (flags & BASE_MEM_PROT_GPU_WR) + reg->flags |= KBASE_REG_GPU_WR; + + if (flags & BASE_MEM_PROT_GPU_RD) + reg->flags |= KBASE_REG_GPU_RD; + + if (0 == (flags & BASE_MEM_PROT_GPU_EX)) + reg->flags |= KBASE_REG_GPU_NX; + + if (flags & BASE_MEM_COHERENT_LOCAL) + reg->flags |= KBASE_REG_SHARE_IN; + else if (flags & BASE_MEM_COHERENT_SYSTEM) + reg->flags |= KBASE_REG_SHARE_BOTH; +} +KBASE_EXPORT_TEST_API(kbase_update_region_flags) + +int kbase_alloc_phy_pages_helper( + struct kbase_mem_phy_alloc *alloc, + size_t nr_pages_requested) +{ + int curr; + int peak; + + KBASE_DEBUG_ASSERT(alloc); + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_NATIVE); + KBASE_DEBUG_ASSERT(alloc->imported.kctx); + + if (nr_pages_requested == 0) + goto done; /*nothing to do*/ + + kbase_atomic_add_pages(nr_pages_requested, &alloc->imported.kctx->used_pages); + kbase_atomic_add_pages(nr_pages_requested, &alloc->imported.kctx->kbdev->memdev.used_pages); + + kbase_atomic_add_pages(nr_pages_requested, &g_mtk_gpu_total_memory_usage_in_pages); + + /* Increase mm counters before we allocate pages so that this + * allocation is visible to the OOM killer */ + kbase_process_page_usage_inc(alloc->imported.kctx, nr_pages_requested); + + curr = atomic_read(&g_mtk_gpu_total_memory_usage_in_pages); + peak = atomic_read(&g_mtk_gpu_peak_memory_usage_in_pages); + if (curr > peak) + atomic_set(&g_mtk_gpu_peak_memory_usage_in_pages, curr); + + if (MALI_ERROR_NONE != kbase_mem_allocator_alloc(&alloc->imported.kctx->osalloc, nr_pages_requested, alloc->pages + alloc->nents)) + goto no_alloc; + + alloc->nents += nr_pages_requested; + +done: + return 0; + +no_alloc: + kbase_process_page_usage_dec(alloc->imported.kctx, nr_pages_requested); + kbase_atomic_sub_pages(nr_pages_requested, &alloc->imported.kctx->used_pages); + kbase_atomic_sub_pages(nr_pages_requested, &alloc->imported.kctx->kbdev->memdev.used_pages); + + kbase_atomic_sub_pages(nr_pages_requested, &g_mtk_gpu_total_memory_usage_in_pages); + + return -ENOMEM; +} + +int kbase_free_phy_pages_helper( + struct kbase_mem_phy_alloc *alloc, + size_t nr_pages_to_free) +{ + mali_bool syncback; + phys_addr_t *start_free; + + KBASE_DEBUG_ASSERT(alloc); + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_NATIVE); + KBASE_DEBUG_ASSERT(alloc->imported.kctx); + KBASE_DEBUG_ASSERT(alloc->nents >= nr_pages_to_free); + + /* early out if nothing to do */ + if (0 == nr_pages_to_free) + return 0; + + start_free = alloc->pages + alloc->nents - nr_pages_to_free; + + syncback = (alloc->properties & KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED) ? MALI_TRUE : MALI_FALSE; + + kbase_mem_allocator_free(&alloc->imported.kctx->osalloc, + nr_pages_to_free, + start_free, + syncback); + + alloc->nents -= nr_pages_to_free; + kbase_process_page_usage_dec(alloc->imported.kctx, nr_pages_to_free); + kbase_atomic_sub_pages(nr_pages_to_free, &alloc->imported.kctx->used_pages); + kbase_atomic_sub_pages(nr_pages_to_free, &alloc->imported.kctx->kbdev->memdev.used_pages); + + kbase_atomic_sub_pages(nr_pages_to_free, &g_mtk_gpu_total_memory_usage_in_pages); + + return 0; +} + +void kbase_mem_kref_free(struct kref *kref) +{ + struct kbase_mem_phy_alloc *alloc; + + alloc = container_of(kref, struct kbase_mem_phy_alloc, kref); + + switch (alloc->type) { + case KBASE_MEM_TYPE_NATIVE: { + KBASE_DEBUG_ASSERT(alloc->imported.kctx); + kbase_free_phy_pages_helper(alloc, alloc->nents); + break; + } + case KBASE_MEM_TYPE_ALIAS: { + /* just call put on the underlying phy allocs */ + size_t i; + struct kbase_aliased *aliased; + + aliased = alloc->imported.alias.aliased; + if (aliased) { + for (i = 0; i < alloc->imported.alias.nents; i++) + if (aliased[i].alloc) + kbase_mem_phy_alloc_put(aliased[i].alloc); + vfree(aliased); + } + break; + } + case KBASE_MEM_TYPE_RAW: + /* raw pages, external cleanup */ + break; + #ifdef CONFIG_UMP + case KBASE_MEM_TYPE_IMPORTED_UMP: + ump_dd_release(alloc->imported.ump_handle); + break; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: + dma_buf_detach(alloc->imported.umm.dma_buf, + alloc->imported.umm.dma_attachment); + dma_buf_put(alloc->imported.umm.dma_buf); + break; +#endif + case KBASE_MEM_TYPE_TB:{ + void *tb; + + tb = alloc->imported.kctx->jctx.tb; + kbase_device_trace_buffer_uninstall(alloc->imported.kctx); + vfree(tb); + break; + } + default: + WARN(1, "Unexecpted free of type %d\n", alloc->type); + break; + } + + /* Free based on allocation type */ + if (alloc->properties & KBASE_MEM_PHY_ALLOC_LARGE) + vfree(alloc); + else + kfree(alloc); +} + +KBASE_EXPORT_TEST_API(kbase_mem_kref_free); + +int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size) +{ + KBASE_DEBUG_ASSERT(NULL != reg); + KBASE_DEBUG_ASSERT(vsize > 0); + + /* validate user provided arguments */ + if (size > vsize || vsize > reg->nr_pages) + goto out_term; + + /* Prevent vsize*sizeof from wrapping around. + * For instance, if vsize is 2**29+1, we'll allocate 1 byte and the alloc won't fail. + */ + if ((size_t) vsize > ((size_t) -1 / sizeof(*reg->alloc->pages))) + goto out_term; + + KBASE_DEBUG_ASSERT(0 != vsize); + + if (MALI_ERROR_NONE != kbase_alloc_phy_pages_helper(reg->alloc, size)) + goto out_term; + + return 0; + + out_term: + return -1; +} + +KBASE_EXPORT_TEST_API(kbase_alloc_phy_pages) + +mali_bool kbase_check_alloc_flags(unsigned long flags) +{ + /* Only known flags should be set. */ + if (flags & ~((1ul << BASE_MEM_FLAGS_NR_INPUT_BITS) - 1)) + return MALI_FALSE; + + /* At least one flag should be set */ + if (flags == 0) + return MALI_FALSE; + + /* Either the GPU or CPU must be reading from the allocated memory */ + if ((flags & (BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD)) == 0) + return MALI_FALSE; + + /* Either the GPU or CPU must be writing to the allocated memory */ + if ((flags & (BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR)) == 0) + return MALI_FALSE; + + /* GPU cannot be writing to GPU executable memory and cannot grow the memory on page fault. */ + if ((flags & BASE_MEM_PROT_GPU_EX) && (flags & (BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF))) + return MALI_FALSE; + + /* GPU should have at least read or write access otherwise there is no + reason for allocating. */ + if ((flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR)) == 0) + return MALI_FALSE; + + return MALI_TRUE; +} + +/** + * @brief Acquire the per-context region list lock + */ +void kbase_gpu_vm_lock(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + mutex_lock(&kctx->reg_lock); +} + +KBASE_EXPORT_TEST_API(kbase_gpu_vm_lock) + +/** + * @brief Release the per-context region list lock + */ +void kbase_gpu_vm_unlock(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + mutex_unlock(&kctx->reg_lock); +} + +KBASE_EXPORT_TEST_API(kbase_gpu_vm_unlock) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.h new file mode 100644 index 0000000000000000000000000000000000000000..9c1ab551480a84ac576a10885ab521a24261be22 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.h @@ -0,0 +1,698 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem.h + * Base kernel memory APIs + */ + +#ifndef _KBASE_MEM_H_ +#define _KBASE_MEM_H_ + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +#include +#include + +#ifdef CONFIG_UMP +#include +#endif /* CONFIG_UMP */ +#include "mali_base_kernel.h" +#include +#include "mali_kbase_pm.h" +#include "mali_kbase_defs.h" +#ifdef CONFIG_MALI_GATOR_SUPPORT +#include "mali_kbase_gator.h" +#endif /*CONFIG_MALI_GATOR_SUPPORT*/ + +/* Part of the workaround for uTLB invalid pages is to ensure we grow/shrink tmem by 4 pages at a time */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_8316 (2) /* round to 4 pages */ + +/* Part of the workaround for PRLAM-9630 requires us to grow/shrink memory by 8 pages. +The MMU reads in 8 page table entries from memory at a time, if we have more than one page fault within the same 8 pages and +page tables are updated accordingly, the MMU does not re-read the page table entries from memory for the subsequent page table +updates and generates duplicate page faults as the page table information used by the MMU is not valid. */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_9630 (3) /* round to 8 pages */ + +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2 (0) /* round to 1 page */ + +/* This must always be a power of 2 */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2) +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_HW_ISSUE_8316 (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_8316) +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_HW_ISSUE_9630 (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_9630) +/** + * A CPU mapping + */ +typedef struct kbase_cpu_mapping { + struct list_head mappings_list; + struct kbase_mem_phy_alloc *alloc; + struct kbase_context *kctx; + struct kbase_va_region *region; + pgoff_t page_off; + int count; + unsigned long vm_start; + unsigned long vm_end; +} kbase_cpu_mapping; + +enum kbase_memory_type { + KBASE_MEM_TYPE_NATIVE, + KBASE_MEM_TYPE_IMPORTED_UMP, + KBASE_MEM_TYPE_IMPORTED_UMM, + KBASE_MEM_TYPE_ALIAS, + KBASE_MEM_TYPE_TB, + KBASE_MEM_TYPE_RAW +}; + +/* internal structure, mirroring base_mem_aliasing_info, + * but with alloc instead of a gpu va (handle) */ +struct kbase_aliased { + struct kbase_mem_phy_alloc *alloc; /* NULL for special, non-NULL for native */ + u64 offset; /* in pages */ + u64 length; /* in pages */ +}; + +/** + * @brief Physical pages tracking object properties + */ +#define KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED (1ul << 0) +#define KBASE_MEM_PHY_ALLOC_LARGE (1ul << 1) + +/* physical pages tracking object. + * Set up to track N pages. + * N not stored here, the creator holds that info. + * This object only tracks how many elements are actually valid (present). + * Changing of nents or *pages should only happen if the kbase_mem_phy_alloc is not + * shared with another region or client. CPU mappings are OK to exist when changing, as + * long as the tracked mappings objects are updated as part of the change. + */ +struct kbase_mem_phy_alloc +{ + struct kref kref; /* number of users of this alloc */ + atomic_t gpu_mappings; + size_t nents; /* 0..N */ + phys_addr_t * pages; /* N elements, only 0..nents are valid */ + + /* kbase_cpu_mappings */ + struct list_head mappings; + + /* type of buffer */ + enum kbase_memory_type type; + + unsigned long properties; + + /* member in union valid based on @a type */ + union { +#ifdef CONFIG_UMP + ump_dd_handle ump_handle; +#endif /* CONFIG_UMP */ +#if defined(CONFIG_DMA_SHARED_BUFFER) + struct { + struct dma_buf *dma_buf; + struct dma_buf_attachment *dma_attachment; + unsigned int current_mapping_usage_count; + struct sg_table *sgt; + } umm; +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ + struct { + mali_size64 stride; + size_t nents; + struct kbase_aliased *aliased; + } alias; + /* Used by type = (KBASE_MEM_TYPE_NATIVE, KBASE_MEM_TYPE_TB) */ + struct kbase_context *kctx; + } imported; +}; + +static inline void kbase_mem_phy_alloc_gpu_mapped(struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(alloc); + /* we only track mappings of NATIVE buffers */ + if (alloc->type == KBASE_MEM_TYPE_NATIVE) + atomic_inc(&alloc->gpu_mappings); +} + +static inline void kbase_mem_phy_alloc_gpu_unmapped(struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(alloc); + /* we only track mappings of NATIVE buffers */ + if (alloc->type == KBASE_MEM_TYPE_NATIVE) + if (0 > atomic_dec_return(&alloc->gpu_mappings)) { + pr_err("Mismatched %s:\n", __func__); + dump_stack(); + } +} + +void kbase_mem_kref_free(struct kref * kref); + +mali_error kbase_mem_init(struct kbase_device * kbdev); +void kbase_mem_halt(struct kbase_device * kbdev); +void kbase_mem_term(struct kbase_device * kbdev); + +static inline struct kbase_mem_phy_alloc * kbase_mem_phy_alloc_get(struct kbase_mem_phy_alloc * alloc) +{ + kref_get(&alloc->kref); + return alloc; +} + +static inline struct kbase_mem_phy_alloc * kbase_mem_phy_alloc_put(struct kbase_mem_phy_alloc * alloc) +{ + kref_put(&alloc->kref, kbase_mem_kref_free); + return NULL; +} + +/** + * A GPU memory region, and attributes for CPU mappings. + */ +typedef struct kbase_va_region { + struct rb_node rblink; + struct list_head link; + + struct kbase_context *kctx; /* Backlink to base context */ + + u64 start_pfn; /* The PFN in GPU space */ + size_t nr_pages; + +/* Free region */ +#define KBASE_REG_FREE (1ul << 0) +/* CPU write access */ +#define KBASE_REG_CPU_WR (1ul << 1) +/* GPU write access */ +#define KBASE_REG_GPU_WR (1ul << 2) +/* No eXecute flag */ +#define KBASE_REG_GPU_NX (1ul << 3) +/* Is CPU cached? */ +#define KBASE_REG_CPU_CACHED (1ul << 4) +/* Is GPU cached? */ +#define KBASE_REG_GPU_CACHED (1ul << 5) + +#define KBASE_REG_GROWABLE (1ul << 6) +/* Can grow on pf? */ +#define KBASE_REG_PF_GROW (1ul << 7) + +/* VA managed by us */ +#define KBASE_REG_CUSTOM_VA (1ul << 8) + +/* inner shareable coherency */ +#define KBASE_REG_SHARE_IN (1ul << 9) +/* inner & outer shareable coherency */ +#define KBASE_REG_SHARE_BOTH (1ul << 10) + +/* Space for 4 different zones */ +#define KBASE_REG_ZONE_MASK (3ul << 11) +#define KBASE_REG_ZONE(x) (((x) & 3) << 11) + +/* GPU read access */ +#define KBASE_REG_GPU_RD (1ul<<13) +/* CPU read access */ +#define KBASE_REG_CPU_RD (1ul<<14) + +/* Aligned for GPU EX in SAME_VA */ +#define KBASE_REG_ALIGNED (1ul<<15) + +/* Index of chosen MEMATTR for this region (0..7) */ +#define KBASE_REG_MEMATTR_MASK (7ul << 16) +#define KBASE_REG_MEMATTR_INDEX(x) (((x) & 7) << 16) +#define KBASE_REG_MEMATTR_VALUE(x) (((x) & KBASE_REG_MEMATTR_MASK) >> 16) + +#define KBASE_REG_ZONE_SAME_VA KBASE_REG_ZONE(0) + +/* only used with 32-bit clients */ +/* + * On a 32bit platform, custom VA should be wired from (4GB + shader region) + * to the VA limit of the GPU. Unfortunately, the Linux mmap() interface + * limits us to 2^32 pages (2^44 bytes, see mmap64 man page for reference). + * So we put the default limit to the maximum possible on Linux and shrink + * it down, if required by the GPU, during initialization. + */ +#define KBASE_REG_ZONE_EXEC KBASE_REG_ZONE(1) /* Dedicated 16MB region for shader code */ +#define KBASE_REG_ZONE_EXEC_BASE ((1ULL << 32) >> PAGE_SHIFT) +#define KBASE_REG_ZONE_EXEC_SIZE ((16ULL * 1024 * 1024) >> PAGE_SHIFT) + +#define KBASE_REG_ZONE_CUSTOM_VA KBASE_REG_ZONE(2) +#define KBASE_REG_ZONE_CUSTOM_VA_BASE (KBASE_REG_ZONE_EXEC_BASE + KBASE_REG_ZONE_EXEC_SIZE) /* Starting after KBASE_REG_ZONE_EXEC */ +#define KBASE_REG_ZONE_CUSTOM_VA_SIZE (((1ULL << 44) >> PAGE_SHIFT) - KBASE_REG_ZONE_CUSTOM_VA_BASE) +/* end 32-bit clients only */ + + unsigned long flags; + + size_t extent; /* nr of pages alloc'd on PF */ + + struct kbase_mem_phy_alloc * alloc; /* the one alloc object we mmap to the GPU and CPU when mapping this region */ + + /* non-NULL if this memory object is a kds_resource */ + struct kds_resource *kds_res; + +} kbase_va_region; + +/* Common functions */ +static INLINE phys_addr_t *kbase_get_phy_pages(struct kbase_va_region *reg) +{ + KBASE_DEBUG_ASSERT(reg); + KBASE_DEBUG_ASSERT(reg->alloc); + + return reg->alloc->pages; +} + +static INLINE size_t kbase_reg_current_backed_size(struct kbase_va_region * reg) +{ + KBASE_DEBUG_ASSERT(reg); + /* if no alloc object the backed size naturally is 0 */ + if (reg->alloc) + return reg->alloc->nents; + else + return 0; +} + +#define KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD ((size_t)(4*1024)) /* size above which vmalloc is used over kmalloc */ + +static INLINE struct kbase_mem_phy_alloc * kbase_alloc_create(size_t nr_pages, enum kbase_memory_type type) +{ + struct kbase_mem_phy_alloc *alloc; + const size_t alloc_size = + sizeof(*alloc) + sizeof(*alloc->pages) * nr_pages; + + /* Prevent nr_pages*sizeof + sizeof(*alloc) from wrapping around. */ + if (nr_pages > ((((size_t) -1) - sizeof(*alloc)) + / sizeof(*alloc->pages))) + return ERR_PTR(-ENOMEM); + + /* Allocate based on the size to reduce internal fragmentation of vmem */ + if (alloc_size > KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD) + alloc = vzalloc(alloc_size); + else + alloc = kzalloc(alloc_size, GFP_KERNEL); + + if (!alloc) + return ERR_PTR(-ENOMEM); + + /* Store allocation method */ + if (alloc_size > KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD) + alloc->properties |= KBASE_MEM_PHY_ALLOC_LARGE; + + kref_init(&alloc->kref); + atomic_set(&alloc->gpu_mappings, 0); + alloc->nents = 0; + alloc->pages = (void*)(alloc + 1); + INIT_LIST_HEAD(&alloc->mappings); + alloc->type = type; + + return alloc; +} + +static INLINE int kbase_reg_prepare_native(struct kbase_va_region * reg, struct kbase_context * kctx) +{ + KBASE_DEBUG_ASSERT(reg); + KBASE_DEBUG_ASSERT(!reg->alloc); + KBASE_DEBUG_ASSERT(reg->flags & KBASE_REG_FREE); + + reg->alloc = kbase_alloc_create(reg->nr_pages, KBASE_MEM_TYPE_NATIVE); + if (IS_ERR(reg->alloc)) + return PTR_ERR(reg->alloc); + else if (!reg->alloc) + return -ENOMEM; + reg->alloc->imported.kctx = kctx; + reg->flags &= ~KBASE_REG_FREE; + return 0; +} + +static inline int kbase_atomic_add_pages(int num_pages, atomic_t *used_pages) +{ + int new_val = atomic_add_return(num_pages, used_pages); +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_total_alloc_pages_change((long long int)new_val); +#endif + return new_val; +} + +static inline int kbase_atomic_sub_pages(int num_pages, atomic_t *used_pages) +{ + int new_val = atomic_sub_return(num_pages, used_pages); +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_total_alloc_pages_change((long long int)new_val); +#endif + return new_val; +} + +/** + * @brief Initialize low-level memory access for a kbase device + * + * Performs any low-level setup needed for a kbase device to access memory on + * the device. + * + * @param kbdev kbase device to initialize memory access for + * @return 0 on success, Linux error code on failure + */ +int kbase_mem_lowlevel_init(struct kbase_device *kbdev); + + +/** + * @brief Terminate low-level memory access for a kbase device + * + * Perform any low-level cleanup needed to clean + * after @ref kbase_mem_lowlevel_init + * + * @param kbdev kbase device to clean up for + */ +void kbase_mem_lowlevel_term(struct kbase_device *kbdev); + +/** + * @brief Initialize an OS based memory allocator. + * + * Initializes a allocator. + * Must be called before any allocation is attempted. + * \a kbase_mem_allocator_alloc and \a kbase_mem_allocator_free is used + * to allocate and free memory. + * \a kbase_mem_allocator_term must be called to clean up the allocator. + * All memory obtained via \a kbase_mem_allocator_alloc must have been + * \a kbase_mem_allocator_free before \a kbase_mem_allocator_term is called. + * + * @param allocator Allocator object to initialize + * @param max_size Maximum number of pages to keep on the freelist. + * @param kbdev The kbase device this allocator is used with + * @return MALI_ERROR_NONE on success, an error code indicating what failed on + * error. + */ +mali_error kbase_mem_allocator_init(struct kbase_mem_allocator *allocator, + unsigned int max_size, + struct kbase_device *kbdev); + +/** + * @brief Allocate memory via an OS based memory allocator. + * + * @param[in] allocator Allocator to obtain the memory from + * @param nr_pages Number of pages to allocate + * @param[out] pages Pointer to an array where the physical address of the allocated pages will be stored + * @return MALI_ERROR_NONE if the pages were allocated, an error code indicating what failed on error + */ +mali_error kbase_mem_allocator_alloc(struct kbase_mem_allocator * allocator, size_t nr_pages, phys_addr_t *pages); + +/** + * @brief Free memory obtained for an OS based memory allocator. + * + * @param[in] allocator Allocator to free the memory back to + * @param nr_pages Number of pages to free + * @param[in] pages Pointer to an array holding the physical address of the paghes to free. + * @param[in] sync_back MALI_TRUE case the memory should be synced back + */ +void kbase_mem_allocator_free(struct kbase_mem_allocator * allocator, size_t nr_pages, phys_addr_t *pages, mali_bool sync_back); + +/** + * @brief Terminate an OS based memory allocator. + * + * Frees all cached allocations and clean up internal state. + * All allocate pages must have been \a kbase_mem_allocator_free before + * this function is called. + * + * @param[in] allocator Allocator to terminate + */ +void kbase_mem_allocator_term(struct kbase_mem_allocator * allocator); + + + +mali_error kbase_region_tracker_init(struct kbase_context *kctx); +void kbase_region_tracker_term(struct kbase_context *kctx); + +struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(struct kbase_context *kctx, mali_addr64 gpu_addr); + +/** + * @brief Check that a pointer is actually a valid region. + * + * Must be called with context lock held. + */ +struct kbase_va_region *kbase_region_tracker_find_region_base_address(struct kbase_context *kctx, mali_addr64 gpu_addr); + +struct kbase_va_region *kbase_alloc_free_region(struct kbase_context *kctx, u64 start_pfn, size_t nr_pages, int zone); +void kbase_free_alloced_region(struct kbase_va_region *reg); +mali_error kbase_add_va_region(struct kbase_context *kctx, struct kbase_va_region *reg, mali_addr64 addr, size_t nr_pages, size_t align); + +mali_error kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, mali_addr64 addr, size_t nr_pages, size_t align); +mali_bool kbase_check_alloc_flags(unsigned long flags); +void kbase_update_region_flags(struct kbase_va_region *reg, unsigned long flags); + +void kbase_gpu_vm_lock(struct kbase_context *kctx); +void kbase_gpu_vm_unlock(struct kbase_context *kctx); + +int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size); + +mali_error kbase_mmu_init(struct kbase_context *kctx); +void kbase_mmu_term(struct kbase_context *kctx); + +phys_addr_t kbase_mmu_alloc_pgd(struct kbase_context *kctx); +void kbase_mmu_free_pgd(struct kbase_context *kctx); +mali_error kbase_mmu_insert_pages(struct kbase_context *kctx, u64 vpfn, + phys_addr_t *phys, size_t nr, + unsigned long flags); +mali_error kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, + phys_addr_t phys, size_t nr, + unsigned long flags); + +mali_error kbase_mmu_teardown_pages(struct kbase_context *kctx, u64 vpfn, size_t nr); +mali_error kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, phys_addr_t* phys, size_t nr, unsigned long flags); + +/** + * @brief Register region and map it on the GPU. + * + * Call kbase_add_va_region() and map the region on the GPU. + */ +mali_error kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, mali_addr64 addr, size_t nr_pages, size_t align); + +/** + * @brief Remove the region from the GPU and unregister it. + * + * Must be called with context lock held. + */ +mali_error kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg); + +/** + * The caller has the following locking conditions: + * - It must hold kbase_as::transaction_mutex on kctx's address space + * - It must hold the kbasep_js_device_data::runpool_irq::lock + */ +void kbase_mmu_update(struct kbase_context *kctx); + +/** + * The caller has the following locking conditions: + * - It must hold kbase_as::transaction_mutex on kctx's address space + * - It must hold the kbasep_js_device_data::runpool_irq::lock + */ +void kbase_mmu_disable(struct kbase_context *kctx); + +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat); + +/** Dump the MMU tables to a buffer + * + * This function allocates a buffer (of @c nr_pages pages) to hold a dump of the MMU tables and fills it. If the + * buffer is too small then the return value will be NULL. + * + * The GPU vm lock must be held when calling this function. + * + * The buffer returned should be freed with @ref vfree when it is no longer required. + * + * @param[in] kctx The kbase context to dump + * @param[in] nr_pages The number of pages to allocate for the buffer. + * + * @return The address of the buffer containing the MMU dump or NULL on error (including if the @c nr_pages is too + * small) + */ +void *kbase_mmu_dump(struct kbase_context *kctx, int nr_pages); + +mali_error kbase_sync_now(struct kbase_context *kctx, struct base_syncset *syncset); +void kbase_sync_single(struct kbase_context *kctx, phys_addr_t pa, + size_t size, kbase_sync_kmem_fn sync_fn); +void kbase_pre_job_sync(struct kbase_context *kctx, struct base_syncset *syncsets, size_t nr); +void kbase_post_job_sync(struct kbase_context *kctx, struct base_syncset *syncsets, size_t nr); + +/** + * Set attributes for imported tmem region + * + * This function sets (extends with) requested attributes for given region + * of imported external memory + * + * @param[in] kctx The kbase context which the tmem belongs to + * @param[in] gpu_addr The base address of the tmem region + * @param[in] attributes The attributes of tmem region to be set + * + * @return MALI_ERROR_NONE on success. Any other value indicates failure. + */ +mali_error kbase_tmem_set_attributes(struct kbase_context *kctx, mali_addr64 gpu_addr, u32 attributes); + +/** + * Get attributes of imported tmem region + * + * This function retrieves the attributes of imported external memory + * + * @param[in] kctx The kbase context which the tmem belongs to + * @param[in] gpu_addr The base address of the tmem region + * @param[out] attributes The actual attributes of tmem region + * + * @return MALI_ERROR_NONE on success. Any other value indicates failure. + */ +mali_error kbase_tmem_get_attributes(struct kbase_context *kctx, mali_addr64 gpu_addr, u32 * const attributes); + +/* OS specific functions */ +mali_error kbase_mem_free(struct kbase_context *kctx, mali_addr64 gpu_addr); +mali_error kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *reg); +void kbase_os_mem_map_lock(struct kbase_context *kctx); +void kbase_os_mem_map_unlock(struct kbase_context *kctx); + +/** + * @brief Update the memory allocation counters for the current process + * + * OS specific call to updates the current memory allocation counters for the current process with + * the supplied delta. + * + * @param[in] kctx The kbase context + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +void kbasep_os_process_page_usage_update(struct kbase_context *kctx, int pages); + +/** + * @brief Add to the memory allocation counters for the current process + * + * OS specific call to add to the current memory allocation counters for the current process by + * the supplied amount. + * + * @param[in] kctx The kernel base context used for the allocation. + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +static INLINE void kbase_process_page_usage_inc(struct kbase_context *kctx, int pages) +{ + kbasep_os_process_page_usage_update(kctx, pages); +} + +/** + * @brief Subtract from the memory allocation counters for the current process + * + * OS specific call to subtract from the current memory allocation counters for the current process by + * the supplied amount. + * + * @param[in] kctx The kernel base context used for the allocation. + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +static INLINE void kbase_process_page_usage_dec(struct kbase_context *kctx, int pages) +{ + kbasep_os_process_page_usage_update(kctx, 0 - pages); +} + +/** + * @brief Find the offset of the CPU mapping of a memory allocation containing + * a given address range + * + * Searches for a CPU mapping of any part of the region starting at @p gpu_addr + * that fully encloses the CPU virtual address range specified by @p uaddr and + * @p size. Returns a failure indication if only part of the address range lies + * within a CPU mapping, or the address range lies within a CPU mapping of a + * different region. + * + * @param[in,out] kctx The kernel base context used for the allocation. + * @param[in] gpu_addr GPU address of the start of the allocated region + * within which to search. + * @param[in] uaddr Start of the CPU virtual address range. + * @param[in] size Size of the CPU virtual address range (in bytes). + * @param[out] offset The offset from the start of the allocation to the + * specified CPU virtual address. + * + * @return MALI_ERROR_NONE if offset was obtained successfully. Error code + * otherwise. + */ +mali_error kbasep_find_enclosing_cpu_mapping_offset(struct kbase_context *kctx, + mali_addr64 gpu_addr, + unsigned long uaddr, + size_t size, + mali_size64 *offset); + +enum hrtimer_restart kbasep_as_poke_timer_callback(struct hrtimer *timer); +void kbase_as_poking_timer_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); +void kbase_as_poking_timer_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** +* @brief Allocates physical pages. +* +* Allocates \a nr_pages_requested and updates the alloc object. +* +* @param[in] alloc allocation object to add pages to +* @param[in] nr_pages_requested number of physical pages to allocate +* +* @return 0 if all pages have been successfully allocated. Error code otherwise +*/ +int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc * alloc, size_t nr_pages_requested); + +/** +* @brief Free physical pages. +* +* Frees \a nr_pages and updates the alloc object. +* +* @param[in] alloc allocation object to free pages from +* @param[in] nr_pages_to_free number of physical pages to free +*/ +int kbase_free_phy_pages_helper(struct kbase_mem_phy_alloc * alloc, size_t nr_pages_to_free); + +#ifdef CONFIG_MALI_NO_MALI +static inline void kbase_wait_write_flush(struct kbase_context *kctx) +{ +} +#else +void kbase_wait_write_flush(struct kbase_context *kctx); +#endif + +static inline void kbase_set_dma_addr(struct page *p, dma_addr_t dma_addr) +{ + SetPagePrivate(p); + if (sizeof(dma_addr_t) > sizeof(p->private)) { + /* on 32-bit ARM with LPAE dma_addr_t becomes larger, but the + * private filed stays the same. So we have to be clever and + * use the fact that we only store DMA addresses of whole pages, + * so the low bits should be zero */ + KBASE_DEBUG_ASSERT(!(dma_addr & (PAGE_SIZE - 1))); + set_page_private(p, dma_addr >> PAGE_SHIFT); + } else { + set_page_private(p, dma_addr); + } +} + +static inline dma_addr_t kbase_dma_addr(struct page *p) +{ + if (sizeof(dma_addr_t) > sizeof(p->private)) + return ((dma_addr_t)page_private(p)) << PAGE_SHIFT; + + return (dma_addr_t)page_private(p); +} +/** +* @brief Process a bus or page fault. +* +* This function will process a fault on a specific address space +* +* @param[in] kbdev The @ref kbase_device the fault happened on +* @param[in] kctx The @ref kbase_context for the faulting address space if +* one was found. +* @param[in] as The address space that has the fault +*/ +void kbase_mmu_interrupt_process(struct kbase_device *kbdev, + struct kbase_context *kctx, struct kbase_as *as); + +unsigned int kbase_report_gpu_memory_usage(void); + +int kbase_report_gpu_memory_peak(void); + +#endif /* _KBASE_MEM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..248eb549f5205d0b4a82569f6050eabf6183f991 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.c @@ -0,0 +1,304 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem.c + * Base kernel memory APIs + */ +#include +#include +#include +#include +#include +#include +#include + +int kbase_mem_lowlevel_init(struct kbase_device *kbdev) +{ + return 0; +} + +void kbase_mem_lowlevel_term(struct kbase_device *kbdev) +{ + return; +} + +static unsigned long kbase_mem_allocator_count(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_mem_allocator *allocator; + + allocator = container_of(s, struct kbase_mem_allocator, free_list_reclaimer); + return atomic_read(&allocator->free_list_size); +} + +static unsigned long kbase_mem_allocator_scan(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_mem_allocator *allocator; + int i; + int freed; + + allocator = container_of(s, struct kbase_mem_allocator, free_list_reclaimer); + + might_sleep(); + + mutex_lock(&allocator->free_list_lock); + i = MIN(atomic_read(&allocator->free_list_size), sc->nr_to_scan); + freed = i; + + atomic_sub(i, &allocator->free_list_size); + + while (i--) { + struct page *p; + + BUG_ON(list_empty(&allocator->free_list_head)); + p = list_first_entry(&allocator->free_list_head, + struct page, lru); + list_del(&p->lru); + ClearPagePrivate(p); + __free_page(p); + } + mutex_unlock(&allocator->free_list_lock); + return atomic_read(&allocator->free_list_size); + +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) +static int kbase_mem_allocator_shrink(struct shrinker *s, + struct shrink_control *sc) +{ + if (sc->nr_to_scan == 0) + return kbase_mem_allocator_count(s, sc); + else + return kbase_mem_allocator_scan(s, sc); +} +#endif + +mali_error kbase_mem_allocator_init(struct kbase_mem_allocator *const allocator, + unsigned int max_size, struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(NULL != allocator); + KBASE_DEBUG_ASSERT(kbdev); + + INIT_LIST_HEAD(&allocator->free_list_head); + + allocator->kbdev = kbdev; + + mutex_init(&allocator->free_list_lock); + + atomic_set(&allocator->free_list_size, 0); + + allocator->free_list_max_size = max_size; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) + allocator->free_list_reclaimer.shrink = kbase_mem_allocator_shrink; +#else + allocator->free_list_reclaimer.count_objects = + kbase_mem_allocator_count; + allocator->free_list_reclaimer.scan_objects = kbase_mem_allocator_scan; +#endif + allocator->free_list_reclaimer.seeks = DEFAULT_SEEKS; + /* Kernel versions prior to 3.1 : + * struct shrinker does not define batch */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) + allocator->free_list_reclaimer.batch = 0; +#endif + + register_shrinker(&allocator->free_list_reclaimer); + + return MALI_ERROR_NONE; +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_init) + +void kbase_mem_allocator_term(struct kbase_mem_allocator *allocator) +{ + KBASE_DEBUG_ASSERT(NULL != allocator); + + unregister_shrinker(&allocator->free_list_reclaimer); + mutex_lock(&allocator->free_list_lock); + while (!list_empty(&allocator->free_list_head)) { + struct page *p; + + p = list_first_entry(&allocator->free_list_head, struct page, + lru); + list_del(&p->lru); + dma_unmap_page(allocator->kbdev->dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + __free_page(p); + } + atomic_set(&allocator->free_list_size, 0); + mutex_unlock(&allocator->free_list_lock); + mutex_destroy(&allocator->free_list_lock); +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_term) + +mali_error kbase_mem_allocator_alloc(struct kbase_mem_allocator *allocator, size_t nr_pages, phys_addr_t *pages) +{ + struct page *p; + void *mp; + int i; + int num_from_free_list; + struct list_head from_free_list = LIST_HEAD_INIT(from_free_list); + gfp_t gfp; + + might_sleep(); + + KBASE_DEBUG_ASSERT(NULL != allocator); + + /* take from the free list first */ + mutex_lock(&allocator->free_list_lock); + num_from_free_list = MIN(nr_pages, atomic_read(&allocator->free_list_size)); + atomic_sub(num_from_free_list, &allocator->free_list_size); + for (i = 0; i < num_from_free_list; i++) + { + BUG_ON(list_empty(&allocator->free_list_head)); + p = list_first_entry(&allocator->free_list_head, struct page, lru); + list_move(&p->lru, &from_free_list); + } + mutex_unlock(&allocator->free_list_lock); + i = 0; + + /* Allocate as many pages from the pool of already allocated pages. */ + list_for_each_entry(p, &from_free_list, lru) { + pages[i] = PFN_PHYS(page_to_pfn(p)); + i++; + } + + if (i == nr_pages) + return MALI_ERROR_NONE; + +#if defined(CONFIG_ARM) && !defined(CONFIG_HAVE_DMA_ATTRS) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) + /* DMA cache sync fails for HIGHMEM before 3.5 on ARM */ + gfp = GFP_USER; +#else + gfp = GFP_HIGHUSER; +#endif + + if (current->flags & PF_KTHREAD) { + /* Don't trigger OOM killer from kernel threads, e.g. when + * growing memory on GPU page fault */ + gfp |= __GFP_NORETRY; + } + + /* If not all pages were sourced from the pool, request new ones. */ + for (; i < nr_pages; i++) { + dma_addr_t dma_addr; + p = alloc_page(gfp); + if (NULL == p) + goto err_out_roll_back; + mp = kmap(p); + if (NULL == mp) { + __free_page(p); + goto err_out_roll_back; + } + memset(mp, 0x00, PAGE_SIZE); /* instead of __GFP_ZERO, so we can do cache maintenance */ + kunmap(p); + + dma_addr = dma_map_page(allocator->kbdev->dev, p, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(allocator->kbdev->dev, dma_addr)) { + __free_page(p); + goto err_out_roll_back; + } + + SetPagePrivate(p); + kbase_set_dma_addr(p, dma_addr); + pages[i] = PFN_PHYS(page_to_pfn(p)); + BUG_ON(dma_addr != pages[i]); + } + + return MALI_ERROR_NONE; + +err_out_roll_back: + while (i--) { + struct page *p; + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + dma_unmap_page(allocator->kbdev->dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + __free_page(p); + } + + return MALI_ERROR_OUT_OF_MEMORY; +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_alloc) + +void kbase_mem_allocator_free(struct kbase_mem_allocator *allocator, size_t nr_pages, phys_addr_t *pages, mali_bool sync_back) +{ + int i = 0; + int page_count = 0; + int tofree; + + LIST_HEAD(new_free_list_items); + + KBASE_DEBUG_ASSERT(NULL != allocator); + + might_sleep(); + + /* Starting by just freeing the overspill. + * As we do this outside of the lock we might spill too many pages + * or get too many on the free list, but the max_size is just a ballpark so it is ok + * providing that tofree doesn't exceed nr_pages + */ + tofree = MAX((int)allocator->free_list_max_size - atomic_read(&allocator->free_list_size), 0); + tofree = nr_pages - MIN(tofree, nr_pages); + for (; i < tofree; i++) { + if (likely(0 != pages[i])) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + dma_unmap_page(allocator->kbdev->dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + pages[i] = (phys_addr_t)0; + __free_page(p); + } + } + + for (; i < nr_pages; i++) { + if (likely(0 != pages[i])) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + /* Sync back the memory to ensure that future cache + * invalidations don't trample on memory. + */ + if (sync_back) + dma_sync_single_for_cpu(allocator->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + + list_add(&p->lru, &new_free_list_items); + page_count++; + } + } + mutex_lock(&allocator->free_list_lock); + list_splice(&new_free_list_items, &allocator->free_list_head); + atomic_add(page_count, &allocator->free_list_size); + mutex_unlock(&allocator->free_list_lock); +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_free) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.h new file mode 100644 index 0000000000000000000000000000000000000000..cb0e153b13bf4e00e6a3179596b275342a2bd9db --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include + +/* raw page handling */ +struct kbase_mem_allocator +{ + struct kbase_device *kbdev; + atomic_t free_list_size; + unsigned int free_list_max_size; + struct mutex free_list_lock; + struct list_head free_list_head; + struct shrinker free_list_reclaimer; +}; diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc_carveout.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc_carveout.c new file mode 100644 index 0000000000000000000000000000000000000000..97bb864a528ad4dcc3a37777454b8dffd924380d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc_carveout.c @@ -0,0 +1,410 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_mem.c + * Base kernel memory APIs + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* This code does not support having multiple kbase devices, or rmmod/insmod */ + +static unsigned long kbase_carveout_start_pfn = ~0UL; +static unsigned long kbase_carveout_end_pfn; +static LIST_HEAD(kbase_carveout_free_list); +static DEFINE_MUTEX(kbase_carveout_free_list_lock); +static unsigned int kbase_carveout_pages; +static atomic_t kbase_carveout_used_pages; +static atomic_t kbase_carveout_system_pages; + +static struct page *kbase_carveout_get_page(struct kbase_mem_allocator *allocator) +{ + struct page *p = NULL; + gfp_t gfp; + + mutex_lock(&kbase_carveout_free_list_lock); + if (!list_empty(&kbase_carveout_free_list)) { + p = list_first_entry(&kbase_carveout_free_list, struct page, lru); + list_del(&p->lru); + atomic_inc(&kbase_carveout_used_pages); + } + mutex_unlock(&kbase_carveout_free_list_lock); + + if (!p) { + dma_addr_t dma_addr; +#if defined(CONFIG_ARM) && !defined(CONFIG_HAVE_DMA_ATTRS) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) + /* DMA cache sync fails for HIGHMEM before 3.5 on ARM */ + gfp = GFP_USER; +#else + gfp = GFP_HIGHUSER; +#endif + + if (current->flags & PF_KTHREAD) { + /* Don't trigger OOM killer from kernel threads, e.g. + * when growing memory on GPU page fault */ + gfp |= __GFP_NORETRY; + } + + p = alloc_page(gfp); + if (!p) + goto out; + + dma_addr = dma_map_page(allocator->kbdev->dev, p, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(allocator->kbdev->dev, dma_addr)) { + __free_page(p); + p = NULL; + goto out; + } + + kbase_set_dma_addr(p, dma_addr); + BUG_ON(dma_addr != PFN_PHYS(page_to_pfn(p))); + atomic_inc(&kbase_carveout_system_pages); + } +out: + return p; +} + +static void kbase_carveout_put_page(struct page *p, + struct kbase_mem_allocator *allocator) +{ + if (page_to_pfn(p) >= kbase_carveout_start_pfn && + page_to_pfn(p) <= kbase_carveout_end_pfn) { + mutex_lock(&kbase_carveout_free_list_lock); + list_add(&p->lru, &kbase_carveout_free_list); + atomic_dec(&kbase_carveout_used_pages); + mutex_unlock(&kbase_carveout_free_list_lock); + } else { + dma_unmap_page(allocator->kbdev->dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + __free_page(p); + atomic_dec(&kbase_carveout_system_pages); + } +} + +static int kbase_carveout_seq_show(struct seq_file *s, void *data) +{ + seq_printf(s, "carveout pages: %u\n", kbase_carveout_pages); + seq_printf(s, "used carveout pages: %u\n", + atomic_read(&kbase_carveout_used_pages)); + seq_printf(s, "used system pages: %u\n", + atomic_read(&kbase_carveout_system_pages)); + return 0; +} + +static int kbasep_carveout_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, kbase_carveout_seq_show, NULL); +} + +static const struct file_operations kbase_carveout_debugfs_fops = { + .open = kbasep_carveout_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int kbase_carveout_init(struct device *dev) +{ + unsigned long pfn; + static int once; + + mutex_lock(&kbase_carveout_free_list_lock); + BUG_ON(once); + once = 1; + + for (pfn = kbase_carveout_start_pfn; pfn <= kbase_carveout_end_pfn; pfn++) { + struct page *p = pfn_to_page(pfn); + dma_addr_t dma_addr; + + dma_addr = dma_map_page(dev, p, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_addr)) + goto out_rollback; + + kbase_set_dma_addr(p, dma_addr); + BUG_ON(dma_addr != PFN_PHYS(page_to_pfn(p))); + + list_add_tail(&p->lru, &kbase_carveout_free_list); + } + + mutex_unlock(&kbase_carveout_free_list_lock); + + debugfs_create_file("kbase_carveout", S_IRUGO, NULL, NULL, + &kbase_carveout_debugfs_fops); + + return 0; + +out_rollback: + while (!list_empty(&kbase_carveout_free_list)) { + struct page *p; + + p = list_first_entry(&kbase_carveout_free_list, struct page, lru); + dma_unmap_page(dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + list_del(&p->lru); + } + + mutex_unlock(&kbase_carveout_free_list_lock); + return -ENOMEM; +} + +int __init kbase_carveout_mem_reserve(phys_addr_t size) +{ + phys_addr_t mem; + +#if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) + /* DMA cache sync fails for HIGHMEM before 3.5 on ARM */ + mem = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ACCESSIBLE); +#else + mem = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); +#endif + if (mem == 0) { + pr_warn("%s: Failed to allocate %d for kbase carveout\n", + __func__, size); + return -ENOMEM; + } + + kbase_carveout_start_pfn = PFN_DOWN(mem); + kbase_carveout_end_pfn = PFN_DOWN(mem + size - 1); + kbase_carveout_pages = kbase_carveout_end_pfn - kbase_carveout_start_pfn + 1; + + return 0; +} + +int kbase_mem_lowlevel_init(struct kbase_device *kbdev) +{ + return kbase_carveout_init(kbdev->dev); +} + +void kbase_mem_lowlevel_term(struct kbase_device *kbdev) +{ +} + +STATIC int kbase_mem_allocator_shrink(struct shrinker *s, struct shrink_control *sc) +{ + struct kbase_mem_allocator *allocator; + int i; + int freed; + + allocator = container_of(s, struct kbase_mem_allocator, free_list_reclaimer); + + if (sc->nr_to_scan == 0) + return atomic_read(&allocator->free_list_size); + + might_sleep(); + + mutex_lock(&allocator->free_list_lock); + i = MIN(atomic_read(&allocator->free_list_size), sc->nr_to_scan); + freed = i; + + atomic_sub(i, &allocator->free_list_size); + + while (i--) { + struct page *p; + + BUG_ON(list_empty(&allocator->free_list_head)); + p = list_first_entry(&allocator->free_list_head, struct page, lru); + list_del(&p->lru); + kbase_carveout_put_page(p, allocator); + } + mutex_unlock(&allocator->free_list_lock); + return atomic_read(&allocator->free_list_size); +} + +mali_error kbase_mem_allocator_init(struct kbase_mem_allocator * const allocator, + unsigned int max_size, struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(NULL != allocator); + KBASE_DEBUG_ASSERT(kbdev); + + INIT_LIST_HEAD(&allocator->free_list_head); + + allocator->kbdev = kbdev; + + mutex_init(&allocator->free_list_lock); + + atomic_set(&allocator->free_list_size, 0); + + allocator->free_list_max_size = max_size; + allocator->free_list_reclaimer.shrink = kbase_mem_allocator_shrink; + allocator->free_list_reclaimer.seeks = DEFAULT_SEEKS; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) /* Kernel versions prior to 3.1 : struct shrinker does not define batch */ + allocator->free_list_reclaimer.batch = 0; +#endif + + register_shrinker(&allocator->free_list_reclaimer); + + return MALI_ERROR_NONE; +} + +void kbase_mem_allocator_term(struct kbase_mem_allocator *allocator) +{ + KBASE_DEBUG_ASSERT(NULL != allocator); + + unregister_shrinker(&allocator->free_list_reclaimer); + + while (!list_empty(&allocator->free_list_head)) { + struct page *p; + + p = list_first_entry(&allocator->free_list_head, struct page, + lru); + list_del(&p->lru); + + kbase_carveout_put_page(p, allocator); + } + mutex_destroy(&allocator->free_list_lock); +} + + +mali_error kbase_mem_allocator_alloc(struct kbase_mem_allocator *allocator, size_t nr_pages, phys_addr_t *pages) +{ + struct page *p; + void *mp; + int i; + int num_from_free_list; + struct list_head from_free_list = LIST_HEAD_INIT(from_free_list); + + might_sleep(); + + KBASE_DEBUG_ASSERT(NULL != allocator); + + /* take from the free list first */ + mutex_lock(&allocator->free_list_lock); + num_from_free_list = MIN(nr_pages, atomic_read(&allocator->free_list_size)); + atomic_sub(num_from_free_list, &allocator->free_list_size); + for (i = 0; i < num_from_free_list; i++) { + BUG_ON(list_empty(&allocator->free_list_head)); + p = list_first_entry(&allocator->free_list_head, struct page, lru); + list_move(&p->lru, &from_free_list); + } + mutex_unlock(&allocator->free_list_lock); + i = 0; + + /* Allocate as many pages from the pool of already allocated pages. */ + list_for_each_entry(p, &from_free_list, lru) + { + pages[i] = PFN_PHYS(page_to_pfn(p)); + i++; + } + + if (i == nr_pages) + return MALI_ERROR_NONE; + + /* If not all pages were sourced from the pool, request new ones. */ + for (; i < nr_pages; i++) { + p = kbase_carveout_get_page(allocator); + if (NULL == p) + goto err_out_roll_back; + + mp = kmap(p); + if (NULL == mp) { + kbase_carveout_put_page(p, allocator); + goto err_out_roll_back; + } + memset(mp, 0x00, PAGE_SIZE); /* instead of __GFP_ZERO, so we can + do cache maintenance */ + dma_sync_single_for_device(allocator->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + kunmap(p); + pages[i] = PFN_PHYS(page_to_pfn(p)); + } + + return MALI_ERROR_NONE; + +err_out_roll_back: + while (i--) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + kbase_carveout_put_page(p, allocator); + } + + return MALI_ERROR_OUT_OF_MEMORY; +} + +void kbase_mem_allocator_free(struct kbase_mem_allocator *allocator, u32 nr_pages, phys_addr_t *pages, mali_bool sync_back) +{ + int i = 0; + int page_count = 0; + int tofree; + + LIST_HEAD(new_free_list_items); + + KBASE_DEBUG_ASSERT(NULL != allocator); + + might_sleep(); + + /* Starting by just freeing the overspill. + * As we do this outside of the lock we might spill too many pages + * or get too many on the free list, but the max_size is just a ballpark so it is ok + * providing that tofree doesn't exceed nr_pages + */ + tofree = MAX((int)allocator->free_list_max_size - atomic_read(&allocator->free_list_size), 0); + tofree = nr_pages - MIN(tofree, nr_pages); + for (; i < tofree; i++) { + if (likely(0 != pages[i])) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + kbase_carveout_put_page(p, allocator); + } + } + + for (; i < nr_pages; i++) { + if (likely(0 != pages[i])) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + /* Sync back the memory to ensure that future cache + * invalidations don't trample on memory. + */ + if (sync_back) + dma_sync_single_for_cpu(allocator->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + list_add(&p->lru, &new_free_list_items); + page_count++; + } + } + mutex_lock(&allocator->free_list_lock); + list_splice(&new_free_list_items, &allocator->free_list_head); + atomic_add(page_count, &allocator->free_list_size); + mutex_unlock(&allocator->free_list_lock); +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_free) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..60a1f033bed8d6b8e1c06e265db4ab44d77f6e74 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c @@ -0,0 +1,1827 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_linux.c + * Base kernel memory APIs, Linux implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + #include +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER +#include +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ + +#include +#include +#include + +static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma); +static const struct vm_operations_struct kbase_vm_ops; + +struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages, u64 commit_pages, u64 extent, u64 *flags, u64 *gpu_va, u16 *va_alignment) +{ + int zone; + int gpu_pc_bits; + int cpu_va_bits; + struct kbase_va_region *reg; + struct device *dev; + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(flags); + KBASE_DEBUG_ASSERT(gpu_va); + KBASE_DEBUG_ASSERT(va_alignment); + + dev = kctx->kbdev->dev; + *va_alignment = 0; /* no alignment by default */ + *gpu_va = 0; /* return 0 on failure */ + + gpu_pc_bits = kctx->kbdev->gpu_props.props.core_props.log2_program_counter_size; + cpu_va_bits = BITS_PER_LONG; + + if (0 == va_pages) { + dev_warn(dev, "kbase_mem_alloc called with 0 va_pages!"); + goto bad_size; + } + + if (va_pages > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + +#if defined(CONFIG_64BIT) + if (kctx->is_compat) + cpu_va_bits = 32; + else + /* force SAME_VA if a 64-bit client */ + *flags |= BASE_MEM_SAME_VA; +#endif + + if (!kbase_check_alloc_flags(*flags)) { + dev_warn(dev, + "kbase_mem_alloc called with bad flags (%llx)", + (unsigned long long)*flags); + goto bad_flags; + } + + /* Limit GPU executable allocs to GPU PC size */ + if ((*flags & BASE_MEM_PROT_GPU_EX) && + (va_pages > (1ULL << gpu_pc_bits >> PAGE_SHIFT))) + goto bad_ex_size; + + /* find out which VA zone to use */ + if (*flags & BASE_MEM_SAME_VA) + zone = KBASE_REG_ZONE_SAME_VA; + else if (*flags & BASE_MEM_PROT_GPU_EX) + zone = KBASE_REG_ZONE_EXEC; + else + zone = KBASE_REG_ZONE_CUSTOM_VA; + + reg = kbase_alloc_free_region(kctx, 0, va_pages, zone); + if (!reg) { + dev_err(dev, "Failed to allocate free region"); + goto no_region; + } + + if (MALI_ERROR_NONE != kbase_reg_prepare_native(reg, kctx)) { + dev_err(dev, "Failed to prepare region"); + goto prepare_failed; + } + + kbase_update_region_flags(reg, *flags); + + if (*flags & BASE_MEM_GROW_ON_GPF) + reg->extent = extent; + else + reg->extent = 0; + + if (kbase_alloc_phy_pages(reg, va_pages, commit_pages)) { + dev_warn(dev, "Failed to allocate %lld pages (va_pages=%lld)", + (unsigned long long)commit_pages, + (unsigned long long)va_pages); + goto no_mem; + } + + kbase_gpu_vm_lock(kctx); + + /* mmap needed to setup VA? */ + if (*flags & BASE_MEM_SAME_VA) { + /* Bind to a cookie */ + if (!kctx->cookies) { + dev_err(dev, "No cookies available for allocation!"); + goto no_cookie; + } + /* return a cookie */ + *gpu_va = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << *gpu_va); + BUG_ON(kctx->pending_regions[*gpu_va]); + kctx->pending_regions[*gpu_va] = reg; + + /* relocate to correct base */ + *gpu_va += PFN_DOWN(BASE_MEM_COOKIE_BASE); + *gpu_va <<= PAGE_SHIFT; + + /* See if we must align memory due to GPU PC bits vs CPU VA */ + if ((*flags & BASE_MEM_PROT_GPU_EX) && + (cpu_va_bits > gpu_pc_bits)) { + *va_alignment = gpu_pc_bits; + reg->flags |= KBASE_REG_ALIGNED; + } + } else /* we control the VA */ { + if (MALI_ERROR_NONE != kbase_gpu_mmap(kctx, reg, 0, va_pages, 1)) { + dev_warn(dev, "Failed to map memory on GPU"); + goto no_mmap; + } + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + } + + kbase_gpu_vm_unlock(kctx); + return reg; + +no_mmap: +no_cookie: + kbase_gpu_vm_unlock(kctx); +no_mem: + kbase_mem_phy_alloc_put(reg->alloc); +prepare_failed: + kfree(reg); +no_region: +bad_ex_size: +bad_flags: +bad_size: + return NULL; +} + +mali_error kbase_mem_query(struct kbase_context *kctx, mali_addr64 gpu_addr, int query, u64 * const out) +{ + struct kbase_va_region *reg; + mali_error ret = MALI_ERROR_FUNCTION_FAILED; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(out); + + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + switch (query) { + case KBASE_MEM_QUERY_COMMIT_SIZE: + if (reg->alloc->type != KBASE_MEM_TYPE_ALIAS) { + *out = kbase_reg_current_backed_size(reg); + } else { + size_t i; + struct kbase_aliased *aliased; + *out = 0; + aliased = reg->alloc->imported.alias.aliased; + for (i = 0; i < reg->alloc->imported.alias.nents; i++) + *out += aliased[i].length; + } + break; + case KBASE_MEM_QUERY_VA_SIZE: + *out = reg->nr_pages; + break; + case KBASE_MEM_QUERY_FLAGS: + { + *out = 0; + if (KBASE_REG_CPU_WR & reg->flags) + *out |= BASE_MEM_PROT_CPU_WR; + if (KBASE_REG_CPU_RD & reg->flags) + *out |= BASE_MEM_PROT_CPU_RD; + if (KBASE_REG_CPU_CACHED & reg->flags) + *out |= BASE_MEM_CACHED_CPU; + if (KBASE_REG_GPU_WR & reg->flags) + *out |= BASE_MEM_PROT_GPU_WR; + if (KBASE_REG_GPU_RD & reg->flags) + *out |= BASE_MEM_PROT_GPU_RD; + if (!(KBASE_REG_GPU_NX & reg->flags)) + *out |= BASE_MEM_PROT_GPU_EX; + if (KBASE_REG_SHARE_BOTH & reg->flags) + *out |= BASE_MEM_COHERENT_SYSTEM; + if (KBASE_REG_SHARE_IN & reg->flags) + *out |= BASE_MEM_COHERENT_LOCAL; + break; + } + default: + *out = 0; + goto out_unlock; + } + + ret = MALI_ERROR_NONE; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + return ret; +} + +mali_error kbase_mem_flags_change(struct kbase_context *kctx, mali_addr64 gpu_addr, unsigned int flags, unsigned int mask) +{ + struct kbase_va_region *reg; + mali_error ret = MALI_ERROR_FUNCTION_FAILED; + unsigned int real_flags = 0; + unsigned int prev_flags = 0; + + KBASE_DEBUG_ASSERT(kctx); + + if (!gpu_addr) + return MALI_ERROR_FUNCTION_FAILED; + + /* nuke other bits */ + flags &= mask; + + /* check for only supported flags */ + if (flags & ~(BASE_MEM_COHERENT_SYSTEM | BASE_MEM_COHERENT_LOCAL)) + goto out; + + /* mask covers bits we don't support? */ + if (mask & ~(BASE_MEM_COHERENT_SYSTEM | BASE_MEM_COHERENT_LOCAL)) + goto out; + + /* convert flags */ + if (BASE_MEM_COHERENT_SYSTEM & flags) + real_flags |= KBASE_REG_SHARE_BOTH; + else if (BASE_MEM_COHERENT_LOCAL & flags) + real_flags |= KBASE_REG_SHARE_IN; + + /* now we can lock down the context, and find the region */ + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + /* limit to imported memory */ + if ((reg->alloc->type != KBASE_MEM_TYPE_IMPORTED_UMP) && + (reg->alloc->type != KBASE_MEM_TYPE_IMPORTED_UMM)) + goto out_unlock; + + /* no change? */ + if (real_flags == (reg->flags & (KBASE_REG_SHARE_IN | KBASE_REG_SHARE_BOTH))) { + ret = MALI_ERROR_NONE; + goto out_unlock; + } + + /* save for roll back */ + prev_flags = reg->flags; + reg->flags &= ~(KBASE_REG_SHARE_IN | KBASE_REG_SHARE_BOTH); + reg->flags |= real_flags; + + /* Currently supporting only imported memory */ + switch (reg->alloc->type) { +#ifdef CONFIG_UMP + case KBASE_MEM_TYPE_IMPORTED_UMP: + ret = kbase_mmu_update_pages(kctx, reg->start_pfn, kbase_get_phy_pages(reg), reg->alloc->nents, reg->flags); + break; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: + /* Future use will use the new flags, existing mapping will NOT be updated + * as memory should not be in use by the GPU when updating the flags. + */ + ret = MALI_ERROR_NONE; + WARN_ON(reg->alloc->imported.umm.current_mapping_usage_count); + break; +#endif + default: + break; + } + + /* roll back on error, i.e. not UMP */ + if (ret != MALI_ERROR_NONE) + reg->flags = prev_flags; + +out_unlock: + kbase_gpu_vm_unlock(kctx); +out: + return ret; +} + +#define KBASE_MEM_IMPORT_HAVE_PAGES (1UL << BASE_MEM_FLAGS_NR_TOTAL_BITS) + +#ifdef CONFIG_UMP +static struct kbase_va_region *kbase_mem_from_ump(struct kbase_context *kctx, ump_secure_id id, u64 *va_pages, u64 *flags) +{ + struct kbase_va_region *reg; + ump_dd_handle umph; + u64 block_count; + const ump_dd_physical_block_64 *block_array; + u64 i, j; + int page = 0; + ump_alloc_flags ump_flags; + ump_alloc_flags cpu_flags; + ump_alloc_flags gpu_flags; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(va_pages); + KBASE_DEBUG_ASSERT(flags); + + umph = ump_dd_from_secure_id(id); + if (UMP_DD_INVALID_MEMORY_HANDLE == umph) + goto bad_id; + + ump_flags = ump_dd_allocation_flags_get(umph); + cpu_flags = (ump_flags >> UMP_DEVICE_CPU_SHIFT) & UMP_DEVICE_MASK; + gpu_flags = (ump_flags >> DEFAULT_UMP_GPU_DEVICE_SHIFT) & + UMP_DEVICE_MASK; + + *va_pages = ump_dd_size_get_64(umph); + *va_pages >>= PAGE_SHIFT; + + if (!*va_pages) + goto bad_size; + + if (*va_pages > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + if (*flags & BASE_MEM_SAME_VA) + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_SAME_VA); + else + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_CUSTOM_VA); + + if (!reg) + goto no_region; + + /* we've got pages to map now, and support SAME_VA */ + *flags |= KBASE_MEM_IMPORT_HAVE_PAGES; + + reg->alloc = kbase_alloc_create(*va_pages, KBASE_MEM_TYPE_IMPORTED_UMP); + if (IS_ERR_OR_NULL(reg->alloc)) + goto no_alloc_obj; + + reg->alloc->imported.ump_handle = umph; + + reg->flags &= ~KBASE_REG_FREE; + reg->flags |= KBASE_REG_GPU_NX; /* UMP is always No eXecute */ + reg->flags &= ~KBASE_REG_GROWABLE; /* UMP cannot be grown */ + + /* Override import flags based on UMP flags */ + *flags &= ~(BASE_MEM_CACHED_CPU); + *flags &= ~(BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR); + *flags &= ~(BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR); + + if ((cpu_flags & (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) == + (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) { + reg->flags |= KBASE_REG_CPU_CACHED; + *flags |= BASE_MEM_CACHED_CPU; + } + + if (cpu_flags & UMP_PROT_CPU_WR) { + reg->flags |= KBASE_REG_CPU_WR; + *flags |= BASE_MEM_PROT_CPU_WR; + } + + if (cpu_flags & UMP_PROT_CPU_RD) { + reg->flags |= KBASE_REG_CPU_RD; + *flags |= BASE_MEM_PROT_CPU_RD; + } + + if ((gpu_flags & (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) == + (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) + reg->flags |= KBASE_REG_GPU_CACHED; + + if (gpu_flags & UMP_PROT_DEVICE_WR) { + reg->flags |= KBASE_REG_GPU_WR; + *flags |= BASE_MEM_PROT_GPU_WR; + } + + if (gpu_flags & UMP_PROT_DEVICE_RD) { + reg->flags |= KBASE_REG_GPU_RD; + *flags |= BASE_MEM_PROT_GPU_RD; + } + + /* ump phys block query */ + ump_dd_phys_blocks_get_64(umph, &block_count, &block_array); + + for (i = 0; i < block_count; i++) { + for (j = 0; j < (block_array[i].size >> PAGE_SHIFT); j++) { + reg->alloc->pages[page] = block_array[i].addr + (j << PAGE_SHIFT); + page++; + } + } + reg->alloc->nents = *va_pages; + reg->extent = 0; + + return reg; + +no_alloc_obj: + kfree(reg); +no_region: +bad_size: + ump_dd_release(umph); +bad_id: + return NULL; +} +#endif /* CONFIG_UMP */ + +#ifdef CONFIG_DMA_SHARED_BUFFER +static struct kbase_va_region *kbase_mem_from_umm(struct kbase_context *kctx, int fd, u64 *va_pages, u64 *flags) +{ + struct kbase_va_region *reg; + struct dma_buf *dma_buf; + struct dma_buf_attachment *dma_attachment; + + dma_buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(dma_buf)) + goto no_buf; + + dma_attachment = dma_buf_attach(dma_buf, kctx->kbdev->dev); + if (!dma_attachment) + goto no_attachment; + + *va_pages = PAGE_ALIGN(dma_buf->size) >> PAGE_SHIFT; + if (!*va_pages) + goto bad_size; + + if (*va_pages > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + /* ignore SAME_VA */ + *flags &= ~BASE_MEM_SAME_VA; + +#ifdef CONFIG_64BIT + if (!kctx->is_compat) { + /* 64-bit tasks must MMAP anyway, but not expose this address to clients */ + *flags |= BASE_MEM_NEED_MMAP; + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_SAME_VA); + } else { +#else + if (1) { +#endif + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_CUSTOM_VA); + } + + if (!reg) + goto no_region; + + reg->alloc = kbase_alloc_create(*va_pages, KBASE_MEM_TYPE_IMPORTED_UMM); + if (IS_ERR_OR_NULL(reg->alloc)) + goto no_alloc_obj; + + /* No pages to map yet */ + reg->alloc->nents = 0; + + reg->flags &= ~KBASE_REG_FREE; + reg->flags |= KBASE_REG_GPU_NX; /* UMM is always No eXecute */ + reg->flags &= ~KBASE_REG_GROWABLE; /* UMM cannot be grown */ + reg->flags |= KBASE_REG_GPU_CACHED; + + if (*flags & BASE_MEM_PROT_CPU_WR) + reg->flags |= KBASE_REG_CPU_WR; + + if (*flags & BASE_MEM_PROT_CPU_RD) + reg->flags |= KBASE_REG_CPU_RD; + + if (*flags & BASE_MEM_PROT_GPU_WR) + reg->flags |= KBASE_REG_GPU_WR; + + if (*flags & BASE_MEM_PROT_GPU_RD) + reg->flags |= KBASE_REG_GPU_RD; + + /* no read or write permission given on import, only on run do we give the right permissions */ + + reg->alloc->type = BASE_TMEM_IMPORT_TYPE_UMM; + reg->alloc->imported.umm.sgt = NULL; + reg->alloc->imported.umm.dma_buf = dma_buf; + reg->alloc->imported.umm.dma_attachment = dma_attachment; + reg->alloc->imported.umm.current_mapping_usage_count = 0; + reg->extent = 0; + + return reg; + +no_alloc_obj: + kfree(reg); +no_region: +bad_size: + dma_buf_detach(dma_buf, dma_attachment); +no_attachment: + dma_buf_put(dma_buf); +no_buf: + return NULL; +} +#endif /* CONFIG_DMA_SHARED_BUFFER */ + +u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, + u64 nents, struct base_mem_aliasing_info *ai, + u64 *num_pages) +{ + struct kbase_va_region *reg; + u64 gpu_va; + size_t i; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(flags); + KBASE_DEBUG_ASSERT(ai); + KBASE_DEBUG_ASSERT(num_pages); + + /* mask to only allowed flags */ + *flags &= (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | + BASE_MEM_HINT_GPU_RD | BASE_MEM_HINT_GPU_WR | + BASE_MEM_COHERENT_SYSTEM | BASE_MEM_COHERENT_LOCAL); + + if (!(*flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR))) { + dev_warn(kctx->kbdev->dev, + "kbase_mem_alias called with bad flags (%llx)", + (unsigned long long)*flags); + goto bad_flags; + } + + if (!stride) + goto bad_stride; + + if (!nents) + goto bad_nents; + + if ((nents * stride) > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + /* calculate the number of pages this alias will cover */ + *num_pages = nents * stride; + +#ifdef CONFIG_64BIT + if (!kctx->is_compat) { + /* 64-bit tasks must MMAP anyway, but not expose this address to + * clients */ + *flags |= BASE_MEM_NEED_MMAP; + reg = kbase_alloc_free_region(kctx, 0, *num_pages, + KBASE_REG_ZONE_SAME_VA); + } else { +#else + if (1) { +#endif + reg = kbase_alloc_free_region(kctx, 0, *num_pages, + KBASE_REG_ZONE_CUSTOM_VA); + } + + if (!reg) + goto no_reg; + + /* zero-sized page array, as we don't need one/can support one */ + reg->alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_ALIAS); + if (IS_ERR_OR_NULL(reg->alloc)) + goto no_alloc_obj; + + kbase_update_region_flags(reg, *flags); + + reg->alloc->imported.alias.nents = nents; + reg->alloc->imported.alias.stride = stride; + reg->alloc->imported.alias.aliased = vzalloc(sizeof(*reg->alloc->imported.alias.aliased) * nents); + if (!reg->alloc->imported.alias.aliased) + goto no_aliased_array; + + kbase_gpu_vm_lock(kctx); + + /* validate and add src handles */ + for (i = 0; i < nents; i++) { + if (ai[i].handle < BASE_MEM_FIRST_FREE_ADDRESS) { + if (ai[i].handle != BASE_MEM_WRITE_ALLOC_PAGES_HANDLE) + goto bad_handle; /* unsupported magic handle */ + if (!ai[i].length) + goto bad_handle; /* must be > 0 */ + if (ai[i].length > stride) + goto bad_handle; /* can't be larger than the + stride */ + reg->alloc->imported.alias.aliased[i].length = ai[i].length; + } else { + struct kbase_va_region *aliasing_reg; + struct kbase_mem_phy_alloc *alloc; + + aliasing_reg = kbase_region_tracker_find_region_base_address(kctx, (ai[i].handle >> PAGE_SHIFT) << PAGE_SHIFT); + + /* validate found region */ + if (!aliasing_reg) + goto bad_handle; /* Not found */ + if (aliasing_reg->flags & KBASE_REG_FREE) + goto bad_handle; /* Free region */ + if (!aliasing_reg->alloc) + goto bad_handle; /* No alloc */ + if (aliasing_reg->alloc->type != KBASE_MEM_TYPE_NATIVE) + goto bad_handle; /* Not a native alloc */ + + /* check size against stride */ + if (!ai[i].length) + goto bad_handle; /* must be > 0 */ + if (ai[i].length > stride) + goto bad_handle; /* can't be larger than the + stride */ + + alloc = aliasing_reg->alloc; + + /* check against the alloc's size */ + if (ai[i].offset > alloc->nents) + goto bad_handle; /* beyond end */ + if (ai[i].offset + ai[i].length > alloc->nents) + goto bad_handle; /* beyond end */ + + reg->alloc->imported.alias.aliased[i].alloc = kbase_mem_phy_alloc_get(alloc); + reg->alloc->imported.alias.aliased[i].length = ai[i].length; + reg->alloc->imported.alias.aliased[i].offset = ai[i].offset; + } + } + +#ifdef CONFIG_64BIT + if (!kctx->is_compat) { + /* Bind to a cookie */ + if (!kctx->cookies) { + dev_err(kctx->kbdev->dev, "No cookies available for allocation!"); + goto no_cookie; + } + /* return a cookie */ + gpu_va = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << gpu_va); + BUG_ON(kctx->pending_regions[gpu_va]); + kctx->pending_regions[gpu_va] = reg; + + /* relocate to correct base */ + gpu_va += PFN_DOWN(BASE_MEM_COOKIE_BASE); + gpu_va <<= PAGE_SHIFT; + } else /* we control the VA */ { +#else + if (1) { +#endif + if (MALI_ERROR_NONE != kbase_gpu_mmap(kctx, reg, 0, + *num_pages, 1)) { + dev_warn(kctx->kbdev->dev, + "Failed to map memory on GPU"); + goto no_mmap; + } + /* return real GPU VA */ + gpu_va = reg->start_pfn << PAGE_SHIFT; + } + + reg->flags &= ~KBASE_REG_FREE; + reg->flags &= ~KBASE_REG_GROWABLE; + + kbase_gpu_vm_unlock(kctx); + + return gpu_va; + +#ifdef CONFIG_64BIT +no_cookie: +#endif +no_mmap: +bad_handle: + kbase_gpu_vm_unlock(kctx); +no_aliased_array: + kbase_mem_phy_alloc_put(reg->alloc); +no_alloc_obj: + kfree(reg); +no_reg: +bad_size: +bad_nents: +bad_stride: +bad_flags: + return 0; +} + +int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type, int handle, mali_addr64 *gpu_va, u64 *va_pages, u64 *flags) +{ + struct kbase_va_region *reg; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(gpu_va); + KBASE_DEBUG_ASSERT(va_pages); + KBASE_DEBUG_ASSERT(flags); + +#ifdef CONFIG_64BIT + if (!kctx->is_compat) + *flags |= BASE_MEM_SAME_VA; +#endif + + switch (type) { +#ifdef CONFIG_UMP + case BASE_MEM_IMPORT_TYPE_UMP: + reg = kbase_mem_from_ump(kctx, (ump_secure_id)handle, va_pages, flags); + break; +#endif /* CONFIG_UMP */ +#ifdef CONFIG_DMA_SHARED_BUFFER + case BASE_MEM_IMPORT_TYPE_UMM: + reg = kbase_mem_from_umm(kctx, handle, va_pages, flags); + break; +#endif /* CONFIG_DMA_SHARED_BUFFER */ + default: + reg = NULL; + break; + } + + if (!reg) + goto no_reg; + + kbase_gpu_vm_lock(kctx); + + /* mmap needed to setup VA? */ + if (*flags & (BASE_MEM_SAME_VA | BASE_MEM_NEED_MMAP)) { + /* Bind to a cookie */ + if (!kctx->cookies) + goto no_cookie; + /* return a cookie */ + *gpu_va = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << *gpu_va); + BUG_ON(kctx->pending_regions[*gpu_va]); + kctx->pending_regions[*gpu_va] = reg; + + /* relocate to correct base */ + *gpu_va += PFN_DOWN(BASE_MEM_COOKIE_BASE); + *gpu_va <<= PAGE_SHIFT; + + } else if (*flags & KBASE_MEM_IMPORT_HAVE_PAGES) { + /* we control the VA, mmap now to the GPU */ + if (MALI_ERROR_NONE != kbase_gpu_mmap(kctx, reg, 0, *va_pages, 1)) + goto no_gpu_va; + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + } else { + /* we control the VA, but nothing to mmap yet */ + if (MALI_ERROR_NONE != kbase_add_va_region(kctx, reg, 0, *va_pages, 1)) + goto no_gpu_va; + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + } + + /* clear out private flags */ + *flags &= ((1UL << BASE_MEM_FLAGS_NR_TOTAL_BITS) - 1); + + kbase_gpu_vm_unlock(kctx); + + return 0; + +no_gpu_va: +no_cookie: + kbase_gpu_vm_unlock(kctx); + kbase_mem_phy_alloc_put(reg->alloc); + kfree(reg); +no_reg: + *gpu_va = 0; + *va_pages = 0; + *flags = 0; + return -ENOMEM; +} + + +static int zap_range_nolock(struct mm_struct *mm, + const struct vm_operations_struct *vm_ops, + unsigned long start, unsigned long end) +{ + struct vm_area_struct *vma; + int err = -EINVAL; /* in case end < start */ + + while (start < end) { + unsigned long local_end; + + vma = find_vma_intersection(mm, start, end); + if (!vma) + break; + + /* is it ours? */ + if (vma->vm_ops != vm_ops) + goto try_next; + + local_end = vma->vm_end; + + if (end < local_end) + local_end = end; + + err = zap_vma_ptes(vma, start, local_end - start); + if (unlikely(err)) + break; + +try_next: + /* go to next vma, if any */ + start = vma->vm_end; + } + + return err; +} + +int kbase_mem_commit(struct kbase_context *kctx, mali_addr64 gpu_addr, u64 new_pages, enum base_backing_threshold_status *failure_reason) +{ + u64 old_pages; + u64 delta; + int res = -EINVAL; + struct kbase_va_region *reg; + phys_addr_t *phy_pages; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(failure_reason); + KBASE_DEBUG_ASSERT(gpu_addr != 0); + + down_read(¤t->mm->mmap_sem); + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS; + goto out_unlock; + } + + KBASE_DEBUG_ASSERT(reg->alloc); + + if (reg->alloc->type != KBASE_MEM_TYPE_NATIVE) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE; + goto out_unlock; + } + + if (0 == (reg->flags & KBASE_REG_GROWABLE)) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE; + goto out_unlock; + } + + if (new_pages > reg->nr_pages) { + /* Would overflow the VA region */ + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS; + goto out_unlock; + } + + /* can't be mapped more than once on the GPU */ + if (atomic_read(®->alloc->gpu_mappings) > 1) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE; + goto out_unlock; + } + + if (new_pages == reg->alloc->nents) { + /* no change */ + res = 0; + goto out_unlock; + } + + phy_pages = kbase_get_phy_pages(reg); + old_pages = kbase_reg_current_backed_size(reg); + + if (new_pages > old_pages) { + /* growing */ + mali_error err; + delta = new_pages - old_pages; + /* Allocate some more pages */ + if (MALI_ERROR_NONE != kbase_alloc_phy_pages_helper(reg->alloc, delta)) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_OOM; + goto out_unlock; + } + err = kbase_mmu_insert_pages(kctx, reg->start_pfn + old_pages, phy_pages + old_pages, delta, reg->flags); + if (MALI_ERROR_NONE != err) { + kbase_free_phy_pages_helper(reg->alloc, delta); + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_OOM; + goto out_unlock; + } + } else { + /* shrinking */ + struct kbase_cpu_mapping *mapping; + mali_error err; + + /* first, unmap from any mappings affected */ + list_for_each_entry(mapping, ®->alloc->mappings, mappings_list) { + unsigned long mapping_size = (mapping->vm_end - mapping->vm_start) >> PAGE_SHIFT; + + /* is this mapping affected ?*/ + if ((mapping->page_off + mapping_size) > new_pages) { + unsigned long first_bad = 0; + int zap_res; + + if (new_pages > mapping->page_off) + first_bad = new_pages - mapping->page_off; + + zap_res = zap_range_nolock(current->mm, + &kbase_vm_ops, + mapping->vm_start + + (first_bad << PAGE_SHIFT), + mapping->vm_end); + WARN(zap_res, + "Failed to zap VA range (0x%lx - 0x%lx);\n", + mapping->vm_start + + (first_bad << PAGE_SHIFT), + mapping->vm_end + ); + } + } + + /* Free some pages */ + delta = old_pages - new_pages; + err = kbase_mmu_teardown_pages(kctx, reg->start_pfn + new_pages, delta); + if (MALI_ERROR_NONE != err) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_OOM; + goto out_unlock; + } + + if (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_6367)) { + /* Wait for GPU to flush write buffer before freeing physical pages */ + kbase_wait_write_flush(kctx); + } + + kbase_free_phy_pages_helper(reg->alloc, delta); + } + + res = 0; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + up_read(¤t->mm->mmap_sem); + + return res; +} + +STATIC void kbase_cpu_vm_open(struct vm_area_struct *vma) +{ + struct kbase_cpu_mapping *map = vma->vm_private_data; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + /* non-atomic as we're under Linux' mm lock */ + map->count++; +} + +STATIC void kbase_cpu_vm_close(struct vm_area_struct *vma) +{ + struct kbase_cpu_mapping *map = vma->vm_private_data; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + + /* non-atomic as we're under Linux' mm lock */ + if (--map->count) + return; + + KBASE_DEBUG_ASSERT(map->kctx); + KBASE_DEBUG_ASSERT(map->alloc); + + kbase_gpu_vm_lock(map->kctx); + + if (map->region) { + KBASE_DEBUG_ASSERT((map->region->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_SAME_VA); + kbase_mem_free_region(map->kctx, map->region); + } + + list_del(&map->mappings_list); + + kbase_gpu_vm_unlock(map->kctx); + + kbase_mem_phy_alloc_put(map->alloc); + kfree(map); +} + +KBASE_EXPORT_TEST_API(kbase_cpu_vm_close) + + +STATIC int kbase_cpu_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct kbase_cpu_mapping *map = vma->vm_private_data; + pgoff_t rel_pgoff; + size_t i; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + KBASE_DEBUG_ASSERT(map->kctx); + KBASE_DEBUG_ASSERT(map->alloc); + + /* we don't use vmf->pgoff as it's affected by our mmap with + * offset being a GPU VA or a cookie */ + rel_pgoff = ((unsigned long)vmf->virtual_address - map->vm_start) + >> PAGE_SHIFT; + + kbase_gpu_vm_lock(map->kctx); + if (map->page_off + rel_pgoff >= map->alloc->nents) + goto locked_bad_fault; + + /* insert all valid pages from the fault location */ + for (i = rel_pgoff; + i < MIN((vma->vm_end - vma->vm_start) >> PAGE_SHIFT, + map->alloc->nents - map->page_off); i++) { + int ret = vm_insert_pfn(vma, map->vm_start + (i << PAGE_SHIFT), + PFN_DOWN(map->alloc->pages[map->page_off + i])); + if (ret < 0 && ret != -EBUSY) + goto locked_bad_fault; + } + + kbase_gpu_vm_unlock(map->kctx); + /* we resolved it, nothing for VM to do */ + return VM_FAULT_NOPAGE; + +locked_bad_fault: + kbase_gpu_vm_unlock(map->kctx); + send_sig(SIGSEGV, current, 1); + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct kbase_vm_ops = { + .open = kbase_cpu_vm_open, + .close = kbase_cpu_vm_close, + .fault = kbase_cpu_vm_fault +}; + +static int kbase_cpu_mmap(struct kbase_va_region *reg, struct vm_area_struct *vma, void *kaddr, size_t nr_pages, unsigned long aligned_offset, int free_on_close) +{ + struct kbase_cpu_mapping *map; + u64 start_off = vma->vm_pgoff - reg->start_pfn; + phys_addr_t *page_array; + int err = 0; + int i; + + map = kzalloc(sizeof(*map), GFP_KERNEL); + + if (!map) { + WARN_ON(1); + err = -ENOMEM; + goto out; + } + + /* + * VM_DONTCOPY - don't make this mapping available in fork'ed processes + * VM_DONTEXPAND - disable mremap on this region + * VM_IO - disables paging + * VM_DONTDUMP - Don't include in core dumps (3.7 only) + * VM_MIXEDMAP - Support mixing struct page*s and raw pfns. + * This is needed to support using the dedicated and + * the OS based memory backends together. + */ + /* + * This will need updating to propagate coherency flags + * See MIDBASE-1057 + */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_DONTCOPY | VM_DONTDUMP | VM_DONTEXPAND | VM_IO; +#else + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO; +#endif + vma->vm_ops = &kbase_vm_ops; + vma->vm_private_data = map; + + page_array = kbase_get_phy_pages(reg); + + if (!(reg->flags & KBASE_REG_CPU_CACHED) && + (reg->flags & (KBASE_REG_CPU_WR|KBASE_REG_CPU_RD))) { + /* We can't map vmalloc'd memory uncached. + * Other memory will have been returned from + * kbase_mem_allocator_alloc which would be + * suitable for mapping uncached. + */ + BUG_ON(kaddr); + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + } + + if (!kaddr) { + vma->vm_flags |= VM_PFNMAP; + for (i = 0; i < nr_pages; i++) { + err = vm_insert_pfn(vma, vma->vm_start + (i << PAGE_SHIFT), page_array[i + start_off] >> PAGE_SHIFT); + if (WARN_ON(err)) + break; + } + } else { + /* MIXEDMAP so we can vfree the kaddr early and not track it after map time */ + vma->vm_flags |= VM_MIXEDMAP; + /* vmalloc remaping is easy... */ + err = remap_vmalloc_range(vma, kaddr, 0); + WARN_ON(err); + } + + if (err) { + kfree(map); + goto out; + } + + map->page_off = start_off; + map->region = free_on_close ? reg : NULL; + map->kctx = reg->kctx; + map->vm_start = vma->vm_start + aligned_offset; + if (aligned_offset) { + KBASE_DEBUG_ASSERT(!start_off); + map->vm_end = map->vm_start + (reg->nr_pages << PAGE_SHIFT); + } else { + map->vm_end = vma->vm_end; + } + map->alloc = kbase_mem_phy_alloc_get(reg->alloc); + map->count = 1; /* start with one ref */ + + if (reg->flags & KBASE_REG_CPU_CACHED) + map->alloc->properties |= KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED; + + list_add(&map->mappings_list, &map->alloc->mappings); + + out: + return err; +} + +static int kbase_trace_buffer_mmap(struct kbase_context *kctx, struct vm_area_struct *vma, struct kbase_va_region **const reg, void **const kaddr) +{ + struct kbase_va_region *new_reg; + u32 nr_pages; + size_t size; + int err = 0; + u32 *tb; + int owns_tb = 1; + + dev_dbg(kctx->kbdev->dev, "in %s\n", __func__); + size = (vma->vm_end - vma->vm_start); + nr_pages = size >> PAGE_SHIFT; + + if (!kctx->jctx.tb) { + KBASE_DEBUG_ASSERT(0 != size); + tb = vmalloc_user(size); + + if (NULL == tb) { + err = -ENOMEM; + goto out; + } + + kbase_device_trace_buffer_install(kctx, tb, size); + } else { + err = -EINVAL; + goto out; + } + + *kaddr = kctx->jctx.tb; + + new_reg = kbase_alloc_free_region(kctx, 0, nr_pages, KBASE_REG_ZONE_SAME_VA); + if (!new_reg) { + err = -ENOMEM; + WARN_ON(1); + goto out_no_region; + } + + new_reg->alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_TB); + if (IS_ERR_OR_NULL(new_reg->alloc)) { + err = -ENOMEM; + new_reg->alloc = NULL; + WARN_ON(1); + goto out_no_alloc; + } + + new_reg->alloc->imported.kctx = kctx; + new_reg->flags &= ~KBASE_REG_FREE; + new_reg->flags |= KBASE_REG_CPU_CACHED; + + /* alloc now owns the tb */ + owns_tb = 0; + + if (MALI_ERROR_NONE != kbase_add_va_region(kctx, new_reg, vma->vm_start, nr_pages, 1)) { + err = -ENOMEM; + WARN_ON(1); + goto out_no_va_region; + } + + *reg = new_reg; + + /* map read only, noexec */ + vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE | VM_EXEC | VM_MAYEXEC); + /* the rest of the flags is added by the cpu_mmap handler */ + + dev_dbg(kctx->kbdev->dev, "%s done\n", __func__); + return 0; + +out_no_va_region: +out_no_alloc: + kbase_free_alloced_region(new_reg); +out_no_region: + if (owns_tb) { + kbase_device_trace_buffer_uninstall(kctx); + vfree(tb); + } +out: + return err; +} + +static int kbase_mmu_dump_mmap(struct kbase_context *kctx, struct vm_area_struct *vma, struct kbase_va_region **const reg, void **const kmap_addr) +{ + struct kbase_va_region *new_reg; + void *kaddr; + u32 nr_pages; + size_t size; + int err = 0; + + dev_dbg(kctx->kbdev->dev, "in kbase_mmu_dump_mmap\n"); + size = (vma->vm_end - vma->vm_start); + nr_pages = size >> PAGE_SHIFT; + + kaddr = kbase_mmu_dump(kctx, nr_pages); + + if (!kaddr) { + err = -ENOMEM; + goto out; + } + + new_reg = kbase_alloc_free_region(kctx, 0, nr_pages, KBASE_REG_ZONE_SAME_VA); + if (!new_reg) { + err = -ENOMEM; + WARN_ON(1); + goto out; + } + + new_reg->alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_RAW); + if (IS_ERR_OR_NULL(new_reg->alloc)) { + err = -ENOMEM; + new_reg->alloc = NULL; + WARN_ON(1); + goto out_no_alloc; + } + + new_reg->flags &= ~KBASE_REG_FREE; + new_reg->flags |= KBASE_REG_CPU_CACHED; + if (MALI_ERROR_NONE != kbase_add_va_region(kctx, new_reg, vma->vm_start, nr_pages, 1)) { + err = -ENOMEM; + WARN_ON(1); + goto out_va_region; + } + + *kmap_addr = kaddr; + *reg = new_reg; + + dev_dbg(kctx->kbdev->dev, "kbase_mmu_dump_mmap done\n"); + return 0; + +out_no_alloc: +out_va_region: + kbase_free_alloced_region(new_reg); +out: + return err; +} + + +void kbase_os_mem_map_lock(struct kbase_context *kctx) +{ + struct mm_struct *mm = current->mm; + (void)kctx; + down_read(&mm->mmap_sem); +} + +void kbase_os_mem_map_unlock(struct kbase_context *kctx) +{ + struct mm_struct *mm = current->mm; + (void)kctx; + up_read(&mm->mmap_sem); +} + +int kbase_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct kbase_context *kctx = file->private_data; + struct kbase_va_region *reg; + void *kaddr = NULL; + size_t nr_pages; + int err = 0; + int free_on_close = 0; + struct device *dev = kctx->kbdev->dev; + size_t aligned_offset = 0; + + dev_dbg(dev, "kbase_mmap\n"); + nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + + /* strip away corresponding VM_MAY% flags to the VM_% flags requested */ + vma->vm_flags &= ~((vma->vm_flags & (VM_READ | VM_WRITE)) << 4); + + if (0 == nr_pages) { + err = -EINVAL; + goto out; + } + + if (!(vma->vm_flags & VM_SHARED)) { + err = -EINVAL; + goto out; + } + + kbase_gpu_vm_lock(kctx); + + if (vma->vm_pgoff == PFN_DOWN(BASE_MEM_MAP_TRACKING_HANDLE)) { + /* The non-mapped tracking helper page */ + err = kbase_tracking_page_setup(kctx, vma); + goto out_unlock; + } + + /* if not the MTP, verify that the MTP has been mapped */ + rcu_read_lock(); + /* catches both when the special page isn't present or + * when we've forked */ + if (rcu_dereference(kctx->process_mm) != current->mm) { + err = -EINVAL; + rcu_read_unlock(); + goto out_unlock; + } + rcu_read_unlock(); + + switch (vma->vm_pgoff) { + case PFN_DOWN(BASE_MEM_INVALID_HANDLE): + case PFN_DOWN(BASE_MEM_WRITE_ALLOC_PAGES_HANDLE): + /* Illegal handle for direct map */ + err = -EINVAL; + goto out_unlock; + case PFN_DOWN(BASE_MEM_TRACE_BUFFER_HANDLE): + err = kbase_trace_buffer_mmap(kctx, vma, ®, &kaddr); + if (0 != err) + goto out_unlock; + dev_dbg(dev, "kbase_trace_buffer_mmap ok\n"); + /* free the region on munmap */ + free_on_close = 1; + goto map; + case PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE): + /* MMU dump */ + err = kbase_mmu_dump_mmap(kctx, vma, ®, &kaddr); + if (0 != err) + goto out_unlock; + /* free the region on munmap */ + free_on_close = 1; + goto map; + case PFN_DOWN(BASE_MEM_COOKIE_BASE) ... + PFN_DOWN(BASE_MEM_FIRST_FREE_ADDRESS) - 1: { + /* SAME_VA stuff, fetch the right region */ + int gpu_pc_bits; + int cookie = vma->vm_pgoff - PFN_DOWN(BASE_MEM_COOKIE_BASE); + + gpu_pc_bits = kctx->kbdev->gpu_props.props.core_props.log2_program_counter_size; + reg = kctx->pending_regions[cookie]; + if (NULL != reg) { + if (reg->flags & KBASE_REG_ALIGNED) { + /* nr_pages must be able to hold alignment pages + * plus actual pages */ + if (nr_pages != ((1UL << gpu_pc_bits >> + PAGE_SHIFT) + + reg->nr_pages)) { + /* incorrect mmap size */ + /* leave the cookie for a potential + * later mapping, or to be reclaimed + * later when the context is freed */ + err = -ENOMEM; + goto out_unlock; + } + + aligned_offset = (vma->vm_start + + (1UL << gpu_pc_bits) - 1) & + ~((1UL << gpu_pc_bits) - 1); + aligned_offset -= vma->vm_start; + } else if (reg->nr_pages != nr_pages) { + /* incorrect mmap size */ + /* leave the cookie for a potential later + * mapping, or to be reclaimed later when the + * context is freed */ + err = -ENOMEM; + goto out_unlock; + } + + if ((vma->vm_flags & VM_READ && + !(reg->flags & KBASE_REG_CPU_RD)) || + (vma->vm_flags & VM_WRITE && + !(reg->flags & KBASE_REG_CPU_WR))) { + /* VM flags inconsistent with region flags */ + err = -EPERM; + dev_err(dev, "%s:%d inconsistent VM flags\n", + __FILE__, __LINE__); + goto out_unlock; + } + + /* adjust down nr_pages to what we have physically */ + nr_pages = kbase_reg_current_backed_size(reg); + + if (MALI_ERROR_NONE != kbase_gpu_mmap(kctx, reg, + vma->vm_start + + aligned_offset, + reg->nr_pages, + 1)) { + dev_err(dev, "%s:%d\n", __FILE__, __LINE__); + /* Unable to map in GPU space. */ + WARN_ON(1); + err = -ENOMEM; + goto out_unlock; + } + + /* no need for the cookie anymore */ + kctx->pending_regions[cookie] = NULL; + kctx->cookies |= (1UL << cookie); + + /* + * Overwrite the offset with the + * region start_pfn, so we effectively + * map from offset 0 in the region. + */ + vma->vm_pgoff = reg->start_pfn; + + /* free the region on munmap */ + free_on_close = 1; + goto map; + } + + err = -ENOMEM; + goto out_unlock; + } + default: { + reg = kbase_region_tracker_find_region_enclosing_address(kctx, (u64)vma->vm_pgoff << PAGE_SHIFT); + + if (reg && !(reg->flags & KBASE_REG_FREE)) { + /* will this mapping overflow the size of the region? */ + if (nr_pages > (reg->nr_pages - (vma->vm_pgoff - reg->start_pfn))) + goto overflow; + + if ((vma->vm_flags & VM_READ && + !(reg->flags & KBASE_REG_CPU_RD)) || + (vma->vm_flags & VM_WRITE && + !(reg->flags & KBASE_REG_CPU_WR))) { + /* VM flags inconsistent with region flags */ + err = -EPERM; + dev_err(dev, "%s:%d inconsistent VM flags\n", + __FILE__, __LINE__); + goto out_unlock; + } + +#ifdef CONFIG_DMA_SHARED_BUFFER + if (reg->alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) + goto dma_map; +#endif /* CONFIG_DMA_SHARED_BUFFER */ + + /* limit what we map to the amount currently backed */ + if (reg->alloc->nents < (vma->vm_pgoff - reg->start_pfn + nr_pages)) { + if ((vma->vm_pgoff - reg->start_pfn) >= reg->alloc->nents) + nr_pages = 0; + else + nr_pages = reg->alloc->nents - (vma->vm_pgoff - reg->start_pfn); + } + + goto map; + } + +overflow: + err = -ENOMEM; + goto out_unlock; + } /* default */ + } /* switch */ +map: + err = kbase_cpu_mmap(reg, vma, kaddr, nr_pages, aligned_offset, free_on_close); + + if (vma->vm_pgoff == PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE)) { + /* MMU dump - userspace should now have a reference on + * the pages, so we can now free the kernel mapping */ + vfree(kaddr); + } + goto out_unlock; + +#ifdef CONFIG_DMA_SHARED_BUFFER +dma_map: + err = dma_buf_mmap(reg->alloc->imported.umm.dma_buf, vma, vma->vm_pgoff - reg->start_pfn); +#endif /* CONFIG_DMA_SHARED_BUFFER */ +out_unlock: + kbase_gpu_vm_unlock(kctx); +out: + if (err) + dev_err(dev, "mmap failed %d\n", err); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mmap) + +void *kbase_vmap(struct kbase_context *kctx, mali_addr64 gpu_addr, size_t size, + struct kbase_vmap_struct *map) +{ + struct kbase_va_region *reg; + unsigned long page_index; + unsigned int offset = gpu_addr & ~PAGE_MASK; + size_t page_count = PFN_UP(offset + size); + phys_addr_t *page_array; + struct page **pages; + void *cpu_addr = NULL; + pgprot_t prot; + size_t i; + + if (!size || !map) + return NULL; + + /* check if page_count calculation will wrap */ + if (size > ((size_t)-1 / PAGE_SIZE)) + return NULL; + + kbase_gpu_vm_lock(kctx); + + reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + page_index = (gpu_addr >> PAGE_SHIFT) - reg->start_pfn; + + /* check if page_index + page_count will wrap */ + if (-1UL - page_count < page_index) + goto out_unlock; + + if (page_index + page_count > kbase_reg_current_backed_size(reg)) + goto out_unlock; + + page_array = kbase_get_phy_pages(reg); + if (!page_array) + goto out_unlock; + + pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); + if (!pages) + goto out_unlock; + + for (i = 0; i < page_count; i++) + pages[i] = pfn_to_page(PFN_DOWN(page_array[page_index + i])); + + prot = PAGE_KERNEL; + if (!(reg->flags & KBASE_REG_CPU_CACHED)) { + /* Map uncached */ + prot = pgprot_writecombine(prot); + } + + cpu_addr = vmap(pages, page_count, VM_MAP, prot); + + kfree(pages); + + if (!cpu_addr) + goto out_unlock; + + map->gpu_addr = gpu_addr; + map->alloc = kbase_mem_phy_alloc_get(reg->alloc); + map->pages = &kbase_get_phy_pages(reg)[page_index]; + map->addr = (void *)((uintptr_t)cpu_addr + offset); + map->size = size; + map->is_cached = (reg->flags & KBASE_REG_CPU_CACHED) != 0; + + if (map->is_cached) { + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + phys_addr_t pa = map->pages[0] + offset; + + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_cpu); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + pa = map->pages[i]; + kbase_sync_single(kctx, pa, PAGE_SIZE, dma_sync_single_for_cpu); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + pa = map->pages[page_count - 1]; + sz = ((offset + size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_cpu); + } + } + + kbase_gpu_vm_unlock(kctx); + + return map->addr; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + return NULL; +} + +void kbase_vunmap(struct kbase_context *kctx, struct kbase_vmap_struct *map) +{ + void *addr = (void *)((uintptr_t)map->addr & PAGE_MASK); + + vunmap(addr); + + if (map->is_cached) { + off_t offset = (uintptr_t)map->addr & ~PAGE_MASK; + size_t size = map->size; + size_t page_count = PFN_UP(offset + size); + size_t i; + + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + phys_addr_t pa = map->pages[0] + offset; + + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_device); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + pa = map->pages[i]; + kbase_sync_single(kctx, pa, PAGE_SIZE, dma_sync_single_for_device); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + pa = map->pages[page_count - 1]; + sz = ((offset + size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_device); + } + } + + map->gpu_addr = 0; + map->alloc = kbase_mem_phy_alloc_put(map->alloc); + map->pages = NULL; + map->addr = NULL; + map->size = 0; + map->is_cached = false; +} + +void kbasep_os_process_page_usage_update(struct kbase_context *kctx, int pages) +{ + struct mm_struct *mm; + + rcu_read_lock(); + mm = rcu_dereference(kctx->process_mm); + if (mm) { + atomic_add(pages, &kctx->nonmapped_pages); +#ifdef SPLIT_RSS_COUNTING + add_mm_counter(mm, MM_FILEPAGES, pages); +#else + spin_lock(&mm->page_table_lock); + add_mm_counter(mm, MM_FILEPAGES, pages); + spin_unlock(&mm->page_table_lock); +#endif + } + rcu_read_unlock(); +} + +static void kbasep_os_process_page_usage_drain(struct kbase_context *kctx) +{ + int pages; + struct mm_struct *mm; + + spin_lock(&kctx->mm_update_lock); + mm = rcu_dereference_protected(kctx->process_mm, lockdep_is_held(&kctx->mm_update_lock)); + if (!mm) { + spin_unlock(&kctx->mm_update_lock); + return; + } + + rcu_assign_pointer(kctx->process_mm, NULL); + spin_unlock(&kctx->mm_update_lock); + synchronize_rcu(); + + pages = atomic_xchg(&kctx->nonmapped_pages, 0); +#ifdef SPLIT_RSS_COUNTING + add_mm_counter(mm, MM_FILEPAGES, -pages); +#else + spin_lock(&mm->page_table_lock); + add_mm_counter(mm, MM_FILEPAGES, -pages); + spin_unlock(&mm->page_table_lock); +#endif +} + +static void kbase_special_vm_close(struct vm_area_struct *vma) +{ + struct kbase_context *kctx; + + kctx = vma->vm_private_data; + kbasep_os_process_page_usage_drain(kctx); +} + +static const struct vm_operations_struct kbase_vm_special_ops = { + .close = kbase_special_vm_close, +}; + +static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma) +{ + /* check that this is the only tracking page */ + spin_lock(&kctx->mm_update_lock); + if (rcu_dereference_protected(kctx->process_mm, lockdep_is_held(&kctx->mm_update_lock))) { + spin_unlock(&kctx->mm_update_lock); + return -EFAULT; + } + + rcu_assign_pointer(kctx->process_mm, current->mm); + + spin_unlock(&kctx->mm_update_lock); + + /* no real access */ + vma->vm_flags &= ~(VM_READ | VM_MAYREAD | VM_WRITE | VM_MAYWRITE | VM_EXEC | VM_MAYEXEC); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP | VM_IO; +#else + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO; +#endif + vma->vm_ops = &kbase_vm_special_ops; + vma->vm_private_data = kctx; + + return 0; +} +void *kbase_va_alloc(struct kbase_context *kctx, u32 size, struct kbase_hwc_dma_mapping *handle) +{ + int i; + int res; + void *va; + dma_addr_t dma_pa; + struct kbase_va_region *reg; + phys_addr_t *page_array; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + //DEFINE_DMA_ATTRS(attrs); +#endif + + u32 pages = ((size - 1) >> PAGE_SHIFT) + 1; + u32 flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR | + BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(0 != size); + KBASE_DEBUG_ASSERT(0 != pages); + + if (size == 0) + goto err; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + //dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + //va = dma_alloc_attrs(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL, &attrs); + va = dma_alloc_coherent(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL); +#else + va = dma_alloc_writecombine(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL); +#endif + if (!va) + goto err; + + /* Store the state so we can free it later. */ + handle->cpu_va = va; + handle->dma_pa = dma_pa; + handle->size = size; + + + reg = kbase_alloc_free_region(kctx, 0, pages, KBASE_REG_ZONE_SAME_VA); + if (!reg) + goto no_reg; + + reg->flags &= ~KBASE_REG_FREE; + kbase_update_region_flags(reg, flags); + + reg->alloc = kbase_alloc_create(pages, KBASE_MEM_TYPE_RAW); + if (IS_ERR_OR_NULL(reg->alloc)) + goto no_alloc; + + page_array = kbase_get_phy_pages(reg); + + for (i = 0; i < pages; i++) + page_array[i] = dma_pa + (i << PAGE_SHIFT); + + reg->alloc->nents = pages; + + kbase_gpu_vm_lock(kctx); + res = kbase_gpu_mmap(kctx, reg, (uintptr_t) va, pages, 1); + kbase_gpu_vm_unlock(kctx); + if (res) + goto no_mmap; + + return va; + +no_mmap: + kbase_mem_phy_alloc_put(reg->alloc); +no_alloc: + kfree(reg); +no_reg: +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + //dma_free_attrs(kctx->kbdev->dev, size, va, dma_pa, &attrs); + dma_free_coherent(kctx->kbdev->dev, size, va, dma_pa); +#else + dma_free_writecombine(kctx->kbdev->dev, size, va, dma_pa); +#endif +err: + return NULL; +} +KBASE_EXPORT_SYMBOL(kbase_va_alloc); + +void kbase_va_free(struct kbase_context *kctx, struct kbase_hwc_dma_mapping *handle) +{ + struct kbase_va_region *reg; + mali_error err; + +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) +// DEFINE_DMA_ATTRS(attrs); +//#endif + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(handle->cpu_va != NULL); + + kbase_gpu_vm_lock(kctx); + reg = kbase_region_tracker_find_region_base_address(kctx, (uintptr_t)handle->cpu_va); + KBASE_DEBUG_ASSERT(reg); + err = kbase_gpu_munmap(kctx, reg); + kbase_gpu_vm_unlock(kctx); + KBASE_DEBUG_ASSERT(err == MALI_ERROR_NONE); + + kbase_mem_phy_alloc_put(reg->alloc); + kfree(reg); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + //dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + //dma_free_attrs(kctx->kbdev->dev, handle->size, + // handle->cpu_va, handle->dma_pa, &attrs); + dma_free_coherent(kctx->kbdev->dev, handle->size, + handle->cpu_va, handle->dma_pa); +#else + dma_free_writecombine(kctx->kbdev->dev, handle->size, + handle->cpu_va, handle->dma_pa); +#endif +} +KBASE_EXPORT_SYMBOL(kbase_va_free); + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h new file mode 100644 index 0000000000000000000000000000000000000000..6bd1d0d86d06ae1b866d8106a98dc7d64eacd679 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h @@ -0,0 +1,71 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_linux.h + * Base kernel memory APIs, Linux implementation. + */ + +#ifndef _KBASE_MEM_LINUX_H_ +#define _KBASE_MEM_LINUX_H_ + +/** A HWC dump mapping */ +typedef struct kbase_hwc_dma_mapping { + void *cpu_va; + dma_addr_t dma_pa; + size_t size; +} kbase_hwc_dma_mapping; + +struct kbase_va_region * kbase_mem_alloc(struct kbase_context * kctx, u64 va_pages, u64 commit_pages, u64 extent, u64 * flags, u64 * gpu_va, u16 * va_alignment); +mali_error kbase_mem_query(struct kbase_context *kctx, mali_addr64 gpu_addr, int query, u64 * const pages); +int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type, int handle, mali_addr64 * gpu_va, u64 * va_pages, u64 * flags); +u64 kbase_mem_alias(struct kbase_context *kctx, u64* flags, u64 stride, u64 nents, struct base_mem_aliasing_info* ai, u64 * num_pages); +mali_error kbase_mem_flags_change(struct kbase_context *kctx, mali_addr64 gpu_addr, unsigned int flags, unsigned int mask); +int kbase_mem_commit(struct kbase_context * kctx, mali_addr64 gpu_addr, u64 new_pages, enum base_backing_threshold_status * failure_reason); +int kbase_mmap(struct file *file, struct vm_area_struct *vma); + +struct kbase_vmap_struct { + mali_addr64 gpu_addr; + struct kbase_mem_phy_alloc *alloc; + phys_addr_t *pages; + void *addr; + size_t size; + bool is_cached; +}; +void *kbase_vmap(struct kbase_context *kctx, mali_addr64 gpu_addr, size_t size, + struct kbase_vmap_struct *map); +void kbase_vunmap(struct kbase_context *kctx, struct kbase_vmap_struct *map); + +/** @brief Allocate memory from kernel space and map it onto the GPU + * + * @param kctx The context used for the allocation/mapping + * @param size The size of the allocation in bytes + * @param handle An opaque structure used to contain the state needed to free the memory + * @return the VA for kernel space and GPU MMU + */ +void *kbase_va_alloc(struct kbase_context *kctx, u32 size, struct kbase_hwc_dma_mapping *handle); + +/** @brief Free/unmap memory allocated by kbase_va_alloc + * + * @param kctx The context used for the allocation/mapping + * @param handle An opaque structure returned by the kbase_va_alloc function. + */ +void kbase_va_free(struct kbase_context *kctx, struct kbase_hwc_dma_mapping *handle); + +#endif /* _KBASE_MEM_LINUX_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h new file mode 100644 index 0000000000000000000000000000000000000000..2b3985ea4fca6320abc4fa459a39c2d7dc34a89f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h @@ -0,0 +1,48 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_MEM_LOWLEVEL_H +#define _KBASE_MEM_LOWLEVEL_H + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +#include + +/** + * @brief Flags for kbase_phy_allocator_pages_alloc + */ +#define KBASE_PHY_PAGES_FLAG_DEFAULT (0) /** Default allocation flag */ +#define KBASE_PHY_PAGES_FLAG_CLEAR (1 << 0) /** Clear the pages after allocation */ +#define KBASE_PHY_PAGES_FLAG_POISON (1 << 1) /** Fill the memory with a poison value */ + +#define KBASE_PHY_PAGES_SUPPORTED_FLAGS (KBASE_PHY_PAGES_FLAG_DEFAULT|KBASE_PHY_PAGES_FLAG_CLEAR|KBASE_PHY_PAGES_FLAG_POISON) + +#define KBASE_PHY_PAGES_POISON_VALUE 0xFD /** Value to fill the memory with when KBASE_PHY_PAGES_FLAG_POISON is set */ + +/** + * A pointer to a cache synchronization function, either dma_sync_single_for_cpu + * or dma_sync_single_for_device. + */ +typedef void (*kbase_sync_kmem_fn) (struct device *, dma_addr_t, size_t size, + enum dma_data_direction); + + +#endif /* _KBASE_LOWLEVEL_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..b7d709e8696d7c2ad465df71941b61cf9d70c87b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c @@ -0,0 +1,137 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#ifdef CONFIG_DEBUG_FS + +/* mam_profile file name max length 22 based on format _\0 */ +#define KBASEP_DEBUGFS_FNAME_SIZE_MAX (10+1+10+1) + +void kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size) +{ + spin_lock(&kctx->mem_profile_lock); + kfree(kctx->mem_profile_data); + kctx->mem_profile_data = data; + kctx->mem_profile_size = size; + spin_unlock(&kctx->mem_profile_lock); +} + +/** Show callback for the @c mem_profile debugfs file. + * + * This function is called to get the contents of the @c mem_profile debugfs + * file. This is a report of current memory usage and distribution in userspace. + * + * @param sfile The debugfs entry + * @param data Data associated with the entry + * + * @return 0 if successfully prints data in debugfs entry file + * -1 if it encountered an error + */ +static int kbasep_mem_profile_seq_show(struct seq_file *sfile, void *data) +{ + struct kbase_context *kctx = sfile->private; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + spin_lock(&kctx->mem_profile_lock); + seq_write(sfile, kctx->mem_profile_data, kctx->mem_profile_size); + seq_putc(sfile, '\n'); + spin_unlock(&kctx->mem_profile_lock); + + return 0; +} + +/* + * File operations related to debugfs entry for mem_profile + */ +STATIC int kbasep_mem_profile_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_mem_profile_seq_show, in->i_private); +} + +static const struct file_operations kbasep_mem_profile_debugfs_fops = { + .open = kbasep_mem_profile_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +mali_error kbasep_mem_profile_debugfs_add(struct kbase_context *kctx) +{ + char name[KBASEP_DEBUGFS_FNAME_SIZE_MAX]; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + spin_lock_init(&kctx->mem_profile_lock); + + scnprintf(name, KBASEP_DEBUGFS_FNAME_SIZE_MAX, "%d_%d", kctx->pid, + kctx->id); + + kctx->mem_dentry = debugfs_create_file(name, S_IRUGO, + kctx->kbdev->memory_profile_directory, + kctx, &kbasep_mem_profile_debugfs_fops); + if (IS_ERR(kctx->mem_dentry)) + goto error_out; + + return MALI_ERROR_NONE; + +error_out: + return MALI_ERROR_FUNCTION_FAILED; +} + +void kbasep_mem_profile_debugfs_remove(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + + spin_lock(&kctx->mem_profile_lock); + kfree(kctx->mem_profile_data); + kctx->mem_profile_data = NULL; + spin_unlock(&kctx->mem_profile_lock); + + if (IS_ERR(kctx->mem_dentry)) + return; + debugfs_remove(kctx->mem_dentry); +} + +#else /* CONFIG_DEBUG_FS */ + +/** + * @brief Stub function for when debugfs is disabled + */ +mali_error kbasep_mem_profile_debugfs_add(struct kbase_context *ctx) +{ + return MALI_ERROR_NONE; +} + +/** + * @brief Stub function for when debugfs is disabled + */ +void kbasep_mem_profile_debugfs_remove(struct kbase_context *ctx) +{ +} + +/** + * @brief Stub function for when debugfs is disabled + */ +void kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size) +{ + kfree(data); +} +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..ef908c84247556d820d8e29fa9e1ed20492cf52f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h @@ -0,0 +1,58 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_profile_debugfs.h + * Header file for mem profiles entries in debugfs + * + */ + +#ifndef _KBASE_MEM_PROFILE_DEBUGFS_H +#define _KBASE_MEM_PROFILE_DEBUGFS_H + +#include +#include +#include + +/** + * @brief Add new entry to Mali memory profile debugfs + */ +mali_error kbasep_mem_profile_debugfs_add(struct kbase_context *kctx); + +/** + * @brief Remove entry from Mali memory profile debugfs + */ +void kbasep_mem_profile_debugfs_remove(struct kbase_context *kctx); + +/** + * @brief Insert data to debugfs file, so it can be read by userspce + * + * Function takes ownership of @c data and frees it later when new data + * are inserted. + * + * @param kctx Context to which file data should be inserted + * @param data NULL-terminated string to be inserted to mem_profile file, + without trailing new line character + * @param size @c buf length + */ +void kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size); + +#endif /*_KBASE_MEM_PROFILE_DEBUGFS_H*/ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h new file mode 100644 index 0000000000000000000000000000000000000000..176392115997b6e3e6278f3626f4473df32a4ef1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_mem_profile_debugfs_buf_size.h + * Header file for the size of the buffer to accumulate the histogram report text in + */ + +#ifndef _KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ +#define _KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ + +/** + * The size of the buffer to accumulate the histogram report text in + * @see @ref CCTXP_HIST_BUF_SIZE_MAX_LENGTH_REPORT + */ +#define KBASE_MEM_PROFILE_MAX_BUF_SIZE ( ( size_t ) ( 64 + ( ( 80 + ( 56 * 64 ) ) * 15 ) + 56 ) ) + +#endif /*_KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_*/ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..2a4aa39f23507066fac3dedfe3707bf033f67764 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu.c @@ -0,0 +1,1665 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mmu.c + * Base kernel MMU management. + */ + +/* #define DEBUG 1 */ +#include +#include +#include +#include +#include + +#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#include +#include +#include + +#define KBASE_MMU_PAGE_ENTRIES 512 + +extern atomic_t g_mtk_gpu_total_memory_usage_in_pages; +/* + * Definitions: + * - PGD: Page Directory. + * - PTE: Page Table Entry. A 64bit value pointing to the next + * level of translation + * - ATE: Address Transation Entry. A 64bit value pointing to + * a 4kB physical page. + */ + +static void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, + struct kbase_as *as, const char *reason_str); + + +/* Helper Function to perform assignment of page table entries, to ensure the use of + * strd, which is required on LPAE systems. + */ + +static inline void page_table_entry_set(struct kbase_device *kbdev, u64 *pte, u64 phy) +{ +#ifdef CONFIG_64BIT + *pte = phy; +#elif defined(CONFIG_ARM) + /* + * + * In order to prevent the compiler keeping cached copies of memory, we have to explicitly + * say that we have updated memory. + * + * Note: We could manually move the data ourselves into R0 and R1 by specifying + * register variables that are explicitly given registers assignments, the down side of + * this is that we have to assume cpu endianess. To avoid this we can use the ldrd to read the + * data from memory into R0 and R1 which will respect the cpu endianess, we then use strd to + * make the 64 bit assignment to the page table entry. + * + */ + + asm volatile("ldrd r0, r1, [%[ptemp]]\n\t" + "strd r0, r1, [%[pte]]\n\t" + : "=m" (*pte) + : [ptemp] "r" (&phy), [pte] "r" (pte), "m" (phy) + : "r0", "r1"); +#else +#error "64-bit atomic write must be implemented for your architecture" +#endif +} + +static size_t make_multiple(size_t minimum, size_t multiple) +{ + size_t remainder = minimum % multiple; + if (remainder == 0) + return minimum; + else + return minimum + multiple - remainder; +} + +static void page_fault_worker(struct work_struct *data) +{ + u64 fault_pfn; + u32 fault_access; + size_t new_pages; + size_t fault_rel_pfn; + struct kbase_as *faulting_as; + int as_no; + struct kbase_context *kctx; + struct kbase_device *kbdev; + struct kbase_va_region *region; + mali_error err; + + faulting_as = container_of(data, struct kbase_as, work_pagefault); + fault_pfn = faulting_as->fault_addr >> PAGE_SHIFT; + as_no = faulting_as->number; + + kbdev = container_of(faulting_as, struct kbase_device, as[as_no]); + + /* Grab the context that was already refcounted in kbase_mmu_interrupt(). + * Therefore, it cannot be scheduled out of this AS until we explicitly release it + * + * NOTE: NULL can be returned here if we're gracefully handling a spurious interrupt */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as_no); + + if (kctx == NULL) { + /* Only handle this if not already suspended */ + if (!kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + struct kbase_mmu_setup *current_setup = &faulting_as->current_setup; + + /* Address space has no context, terminate the work */ + + /* AS transaction begin */ + mutex_lock(&faulting_as->transaction_mutex); + + /* Switch to unmapped mode */ + current_setup->transtab &= ~(u64)MMU_TRANSTAB_ADRMODE_MASK; + current_setup->transtab |= AS_TRANSTAB_ADRMODE_UNMAPPED; + + /* Apply new address space settings */ + kbase_mmu_hw_configure(kbdev, faulting_as, kctx); + + mutex_unlock(&faulting_as->transaction_mutex); + /* AS transaction end */ + + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_pm_context_idle(kbdev); + } + return; + } + + KBASE_DEBUG_ASSERT(kctx->kbdev == kbdev); + + kbase_gpu_vm_lock(kctx); + + region = kbase_region_tracker_find_region_enclosing_address(kctx, faulting_as->fault_addr); + if (NULL == region || region->flags & KBASE_REG_FREE) { + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Memory is not mapped on the GPU"); + goto fault_done; + } + + fault_access = faulting_as->fault_status & AS_FAULTSTATUS_ACCESS_TYPE_MASK; + if (((fault_access == AS_FAULTSTATUS_ACCESS_TYPE_READ) && + !(region->flags & KBASE_REG_GPU_RD)) || + ((fault_access == AS_FAULTSTATUS_ACCESS_TYPE_WRITE) && + !(region->flags & KBASE_REG_GPU_WR)) || + ((fault_access == AS_FAULTSTATUS_ACCESS_TYPE_EX) && + (region->flags & KBASE_REG_GPU_NX))) { + dev_warn(kbdev->dev, "Access permissions don't match: region->flags=0x%lx", region->flags); + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Access permissions mismatch"); + goto fault_done; + } + + if (!(region->flags & GROWABLE_FLAGS_REQUIRED)) { + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Memory is not growable"); + goto fault_done; + } + + /* find the size we need to grow it by */ + /* we know the result fit in a size_t due to kbase_region_tracker_find_region_enclosing_address + * validating the fault_adress to be within a size_t from the start_pfn */ + fault_rel_pfn = fault_pfn - region->start_pfn; + + if (fault_rel_pfn < kbase_reg_current_backed_size(region)) { + dev_dbg(kbdev->dev, "Page fault @ 0x%llx in allocated region 0x%llx-0x%llx of growable TMEM: Ignoring", + faulting_as->fault_addr, region->start_pfn, + region->start_pfn + + kbase_reg_current_backed_size(region)); + + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + /* [1] in case another page fault occurred while we were + * handling the (duplicate) page fault we need to ensure we + * don't loose the other page fault as result of us clearing + * the MMU IRQ. Therefore, after we clear the MMU IRQ we send + * an UNLOCK command that will retry any stalled memory + * transaction (which should cause the other page fault to be + * raised again). + */ + kbase_mmu_hw_do_operation(kbdev, faulting_as, 0, 0, 0, + AS_COMMAND_UNLOCK, 1); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + goto fault_done; + } + + new_pages = make_multiple(fault_rel_pfn - + kbase_reg_current_backed_size(region) + 1, + region->extent); + + /* cap to max vsize */ + if (new_pages + kbase_reg_current_backed_size(region) > + region->nr_pages) + new_pages = region->nr_pages - + kbase_reg_current_backed_size(region); + + if (0 == new_pages) { + /* Duplicate of a fault we've already handled, nothing to do */ + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + /* See comment [1] about UNLOCK usage */ + kbase_mmu_hw_do_operation(kbdev, faulting_as, 0, 0, 0, + AS_COMMAND_UNLOCK, 1); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + goto fault_done; + } + + if (MALI_ERROR_NONE == kbase_alloc_phy_pages_helper(region->alloc, new_pages)) { + u32 op; + + /* alloc success */ + KBASE_DEBUG_ASSERT(kbase_reg_current_backed_size(region) <= region->nr_pages); + + /* AS transaction begin */ + mutex_lock(&faulting_as->transaction_mutex); + + /* set up the new pages */ + err = kbase_mmu_insert_pages(kctx, region->start_pfn + kbase_reg_current_backed_size(region) - new_pages, &kbase_get_phy_pages(region)[kbase_reg_current_backed_size(region) - new_pages], new_pages, region->flags); + if (MALI_ERROR_NONE != err) { + /* failed to insert pages, handle as a normal PF */ + mutex_unlock(&faulting_as->transaction_mutex); + kbase_free_phy_pages_helper(region->alloc, new_pages); + kbase_gpu_vm_unlock(kctx); + /* The locked VA region will be unlocked and the cache invalidated in here */ + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Page table update failure"); + goto fault_done; + } +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_page_fault_insert_pages(as_no, new_pages); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + + /* flush L2 and unlock the VA (resumes the MMU) */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6367)) + op = AS_COMMAND_FLUSH; + else + op = AS_COMMAND_FLUSH_PT; + + /* clear MMU interrupt - this needs to be done after updating + * the page tables but before issuing a FLUSH command. The + * FLUSH cmd has a side effect that it restarts stalled memory + * transactions in other address spaces which may cause + * another fault to occur. If we didn't clear the interrupt at + * this stage a new IRQ might not be raised when the GPU finds + * a MMU IRQ is already pending. + */ + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + + kbase_mmu_hw_do_operation(kbdev, faulting_as, kctx, + faulting_as->fault_addr >> PAGE_SHIFT, + new_pages, + op, 1); + + mutex_unlock(&faulting_as->transaction_mutex); + /* AS transaction end */ + + /* reenable this in the mask */ + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + } else { + /* failed to extend, handle as a normal PF */ + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Page allocation failure"); + } + +fault_done: + /* + * By this point, the fault was handled in some way, + * so release the ctx refcount + */ + kbasep_js_runpool_release_ctx(kbdev, kctx); +} + +phys_addr_t kbase_mmu_alloc_pgd(struct kbase_context *kctx) +{ + phys_addr_t pgd; + u64 *page; + int i; + struct page *p; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbase_atomic_add_pages(1, &kctx->used_pages); + kbase_atomic_add_pages(1, &kctx->kbdev->memdev.used_pages); + kbase_atomic_add_pages(1, &g_mtk_gpu_total_memory_usage_in_pages); + + if (MALI_ERROR_NONE != kbase_mem_allocator_alloc(kctx->pgd_allocator, 1, &pgd)) + goto sub_pages; + + p = pfn_to_page(PFN_DOWN(pgd)); + page = kmap(p); + if (NULL == page) + goto alloc_free; + + kbase_process_page_usage_inc(kctx, 1); + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) + page_table_entry_set(kctx->kbdev, &page[i], ENTRY_IS_INVAL); + + /* Clean the full page */ + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_TO_DEVICE); + kunmap(pfn_to_page(PFN_DOWN(pgd))); + return pgd; + +alloc_free: + kbase_mem_allocator_free(kctx->pgd_allocator, 1, &pgd, MALI_FALSE); +sub_pages: + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); + kbase_atomic_sub_pages(1, &g_mtk_gpu_total_memory_usage_in_pages); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_alloc_pgd) + +static phys_addr_t mmu_pte_to_phy_addr(u64 entry) +{ + if (!(entry & 1)) + return 0; + + return entry & ~0xFFF; +} + +static u64 mmu_phyaddr_to_pte(phys_addr_t phy) +{ + return (phy & ~0xFFF) | ENTRY_IS_PTE; +} + +static u64 mmu_phyaddr_to_ate(phys_addr_t phy, u64 flags) +{ + return (phy & ~0xFFF) | (flags & ENTRY_FLAGS_MASK) | ENTRY_IS_ATE; +} + +/* Given PGD PFN for level N, return PGD PFN for level N+1 */ +static phys_addr_t mmu_get_next_pgd(struct kbase_context *kctx, phys_addr_t pgd, u64 vpfn, int level) +{ + u64 *page; + phys_addr_t target_pgd; + struct page *p; + + KBASE_DEBUG_ASSERT(pgd); + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + /* + * Architecture spec defines level-0 as being the top-most. + * This is a bit unfortunate here, but we keep the same convention. + */ + vpfn >>= (3 - level) * 9; + vpfn &= 0x1FF; + + p = pfn_to_page(PFN_DOWN(pgd)); + page = kmap(p); + if (NULL == page) { + dev_warn(kctx->kbdev->dev, "mmu_get_next_pgd: kmap failure\n"); + return 0; + } + + target_pgd = mmu_pte_to_phy_addr(page[vpfn]); + + if (!target_pgd) { + target_pgd = kbase_mmu_alloc_pgd(kctx); + if (!target_pgd) { + dev_warn(kctx->kbdev->dev, "mmu_get_next_pgd: kbase_mmu_alloc_pgd failure\n"); + kunmap(p); + return 0; + } + + page_table_entry_set(kctx->kbdev, &page[vpfn], + mmu_phyaddr_to_pte(target_pgd)); + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_TO_DEVICE); + /* Rely on the caller to update the address space flags. */ + } + + kunmap(p); + return target_pgd; +} + +static phys_addr_t mmu_get_bottom_pgd(struct kbase_context *kctx, u64 vpfn) +{ + phys_addr_t pgd; + int l; + + pgd = kctx->pgd; + + for (l = MIDGARD_MMU_TOPLEVEL; l < 3; l++) { + pgd = mmu_get_next_pgd(kctx, pgd, vpfn, l); + /* Handle failure condition */ + if (!pgd) { + dev_warn(kctx->kbdev->dev, "mmu_get_bottom_pgd: mmu_get_next_pgd failure\n"); + return 0; + } + } + + return pgd; +} + +static phys_addr_t mmu_insert_pages_recover_get_next_pgd(struct kbase_context *kctx, phys_addr_t pgd, u64 vpfn, int level) +{ + u64 *page; + phys_addr_t target_pgd; + + KBASE_DEBUG_ASSERT(pgd); + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + /* + * Architecture spec defines level-0 as being the top-most. + * This is a bit unfortunate here, but we keep the same convention. + */ + vpfn >>= (3 - level) * 9; + vpfn &= 0x1FF; + + page = kmap_atomic(pfn_to_page(PFN_DOWN(pgd))); + /* kmap_atomic should NEVER fail */ + KBASE_DEBUG_ASSERT(NULL != page); + + target_pgd = mmu_pte_to_phy_addr(page[vpfn]); + /* As we are recovering from what has already been set up, we should have a target_pgd */ + KBASE_DEBUG_ASSERT(0 != target_pgd); + + kunmap_atomic(page); + return target_pgd; +} + +static phys_addr_t mmu_insert_pages_recover_get_bottom_pgd(struct kbase_context *kctx, u64 vpfn) +{ + phys_addr_t pgd; + int l; + + pgd = kctx->pgd; + + for (l = MIDGARD_MMU_TOPLEVEL; l < 3; l++) { + pgd = mmu_insert_pages_recover_get_next_pgd(kctx, pgd, vpfn, l); + /* Should never fail */ + KBASE_DEBUG_ASSERT(0 != pgd); + } + + return pgd; +} + +static void mmu_insert_pages_failure_recovery(struct kbase_context *kctx, u64 vpfn, + size_t nr) +{ + phys_addr_t pgd; + u64 *pgd_page; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(vpfn <= (UINT64_MAX / PAGE_SIZE)); + + lockdep_assert_held(&kctx->reg_lock); + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + pgd = mmu_insert_pages_recover_get_bottom_pgd(kctx, vpfn); + KBASE_DEBUG_ASSERT(0 != pgd); + + p = pfn_to_page(PFN_DOWN(pgd)); + + pgd_page = kmap_atomic(p); + KBASE_DEBUG_ASSERT(NULL != pgd_page); + + /* Invalidate the entries we added */ + for (i = 0; i < count; i++) + page_table_entry_set(kctx->kbdev, &pgd_page[index + i], + ENTRY_IS_INVAL); + + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, DMA_TO_DEVICE); + kunmap_atomic(pgd_page); + } +} + +/** + * Map KBASE_REG flags to MMU flags + */ +static u64 kbase_mmu_get_mmu_flags(unsigned long flags) +{ + u64 mmu_flags; + + /* store mem_attr index as 4:2 (macro called ensures 3 bits already) */ + mmu_flags = KBASE_REG_MEMATTR_VALUE(flags) << 2; + + /* write perm if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_WR) ? ENTRY_WR_BIT : 0; + /* read perm if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_RD) ? ENTRY_RD_BIT : 0; + /* nx if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_NX) ? ENTRY_NX_BIT : 0; + + if (flags & KBASE_REG_SHARE_BOTH) { + /* inner and outer shareable */ + mmu_flags |= SHARE_BOTH_BITS; + } else if (flags & KBASE_REG_SHARE_IN) { + /* inner shareable coherency */ + mmu_flags |= SHARE_INNER_BITS; + } + + return mmu_flags; +} + +/* + * Map the single page 'phys' 'nr' of times, starting at GPU PFN 'vpfn' + */ +mali_error kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, + phys_addr_t phys, size_t nr, + unsigned long flags) +{ + phys_addr_t pgd; + u64 *pgd_page; + u64 pte_entry; + /* In case the insert_single_page only partially completes we need to be + * able to recover */ + mali_bool recover_required = MALI_FALSE; + u64 recover_vpfn = vpfn; + size_t recover_count = 0; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(vpfn <= (UINT64_MAX / PAGE_SIZE)); + + lockdep_assert_held(&kctx->reg_lock); + + /* the one entry we'll populate everywhere */ + pte_entry = mmu_phyaddr_to_ate(phys, kbase_mmu_get_mmu_flags(flags)); + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + /* + * Repeatedly calling mmu_get_bottom_pte() is clearly + * suboptimal. We don't have to re-parse the whole tree + * each time (just cache the l0-l2 sequence). + * On the other hand, it's only a gain when we map more than + * 256 pages at once (on average). Do we really care? + */ + pgd = mmu_get_bottom_pgd(kctx, vpfn); + if (!pgd) { + dev_warn(kctx->kbdev->dev, + "kbase_mmu_insert_pages: " + "mmu_get_bottom_pgd failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_count); + } + return MALI_ERROR_FUNCTION_FAILED; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, + "kbase_mmu_insert_pages: " + "kmap failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_count); + } + return MALI_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; i++) { + unsigned int ofs = index + i; + KBASE_DEBUG_ASSERT(0 == (pgd_page[ofs] & 1UL)); + page_table_entry_set(kctx->kbdev, &pgd_page[ofs], + pte_entry); + } + + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p) + + (index * sizeof(u64)), + count * sizeof(u64), + DMA_TO_DEVICE); + + + kunmap(p); + /* We have started modifying the page table. + * If further pages need inserting and fail we need to undo what + * has already taken place */ + recover_required = MALI_TRUE; + recover_count += count; + } + return MALI_ERROR_NONE; +} + +/* + * Map 'nr' pages pointed to by 'phys' at GPU PFN 'vpfn' + */ +mali_error kbase_mmu_insert_pages(struct kbase_context *kctx, u64 vpfn, + phys_addr_t *phys, size_t nr, + unsigned long flags) +{ + phys_addr_t pgd; + u64 *pgd_page; + u64 mmu_flags = 0; + /* In case the insert_pages only partially completes we need to be able + * to recover */ + mali_bool recover_required = MALI_FALSE; + u64 recover_vpfn = vpfn; + size_t recover_count = 0; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(vpfn <= (UINT64_MAX / PAGE_SIZE)); + + lockdep_assert_held(&kctx->reg_lock); + + mmu_flags = kbase_mmu_get_mmu_flags(flags); + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + /* + * Repeatedly calling mmu_get_bottom_pte() is clearly + * suboptimal. We don't have to re-parse the whole tree + * each time (just cache the l0-l2 sequence). + * On the other hand, it's only a gain when we map more than + * 256 pages at once (on average). Do we really care? + */ + pgd = mmu_get_bottom_pgd(kctx, vpfn); + if (!pgd) { + dev_warn(kctx->kbdev->dev, + "kbase_mmu_insert_pages: " + "mmu_get_bottom_pgd failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_count); + } + return MALI_ERROR_FUNCTION_FAILED; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, + "kbase_mmu_insert_pages: " + "kmap failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_count); + } + return MALI_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; i++) { + unsigned int ofs = index + i; + KBASE_DEBUG_ASSERT(0 == (pgd_page[ofs] & 1UL)); + page_table_entry_set(kctx->kbdev, &pgd_page[ofs], + mmu_phyaddr_to_ate(phys[i], + mmu_flags) + ); + } + + phys += count; + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p) + + (index * sizeof(u64)), + count * sizeof(u64), + DMA_TO_DEVICE); + + kunmap(p); + /* We have started modifying the page table. If further pages + * need inserting and fail we need to undo what has already + * taken place */ + recover_required = MALI_TRUE; + recover_count += count; + } + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_insert_pages) + +/** + * This function is responsible for validating the MMU PTs + * triggering reguired flushes. + * + * * IMPORTANT: This uses kbasep_js_runpool_release_ctx() when the context is + * currently scheduled into the runpool, and so potentially uses a lot of locks. + * These locks must be taken in the correct order with respect to others + * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more + * information. + */ +static void kbase_mmu_flush(struct kbase_context *kctx, u64 vpfn, size_t nr) +{ + struct kbase_device *kbdev; + mali_bool ctx_is_in_runpool; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + kbdev = kctx->kbdev; + + /* We must flush if we're currently running jobs. At the very least, we need to retain the + * context to ensure it doesn't schedule out whilst we're trying to flush it */ + ctx_is_in_runpool = kbasep_js_runpool_retain_ctx(kbdev, kctx); + + if (ctx_is_in_runpool) { + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + /* Second level check is to try to only do this when jobs are running. The refcount is + * a heuristic for this. */ + if (kbdev->js_data.runpool_irq.per_as_data[kctx->as_nr].as_busy_refcount >= 2) { + int ret; + u32 op; + + /* AS transaction begin */ + mutex_lock(&kbdev->as[kctx->as_nr].transaction_mutex); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6367)) + op = AS_COMMAND_FLUSH; + else + op = AS_COMMAND_FLUSH_MEM; + + ret = kbase_mmu_hw_do_operation(kbdev, + &kbdev->as[kctx->as_nr], + kctx, vpfn, nr, + op, 0); +#if KBASE_GPU_RESET_EN + if (ret) { + /* Flush failed to complete, assume the GPU has hung and perform a reset to recover */ + dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issueing GPU soft-reset to recover\n"); + if (kbase_prepare_to_reset_gpu(kbdev)) + kbase_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + + mutex_unlock(&kbdev->as[kctx->as_nr].transaction_mutex); + /* AS transaction end */ + } + kbasep_js_runpool_release_ctx(kbdev, kctx); + } +} + +/* + * We actually only discard the ATE, and not the page table + * pages. There is a potential DoS here, as we'll leak memory by + * having PTEs that are potentially unused. Will require physical + * page accounting, so MMU pages are part of the process allocation. + * + * IMPORTANT: This uses kbasep_js_runpool_release_ctx() when the context is + * currently scheduled into the runpool, and so potentially uses a lot of locks. + * These locks must be taken in the correct order with respect to others + * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more + * information. + */ +mali_error kbase_mmu_teardown_pages(struct kbase_context *kctx, u64 vpfn, size_t nr) +{ + phys_addr_t pgd; + u64 *pgd_page; + struct kbase_device *kbdev; + size_t requested_nr = nr; + + KBASE_DEBUG_ASSERT(NULL != kctx); + beenthere(kctx, "kctx %p vpfn %lx nr %zd", (void *)kctx, (unsigned long)vpfn, nr); + + lockdep_assert_held(&kctx->reg_lock); + + if (0 == nr) { + /* early out if nothing to do */ + return MALI_ERROR_NONE; + } + + kbdev = kctx->kbdev; + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + if (count > nr) + count = nr; + + pgd = mmu_get_bottom_pgd(kctx, vpfn); + if (!pgd) { + dev_warn(kbdev->dev, "kbase_mmu_teardown_pages: mmu_get_bottom_pgd failure\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kbdev->dev, "kbase_mmu_teardown_pages: kmap failure\n"); + return MALI_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; i++) { + page_table_entry_set(kctx->kbdev, &pgd_page[index + i], ENTRY_IS_INVAL); + } + + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p) + + (index * sizeof(u64)), + count * sizeof(u64), + DMA_TO_DEVICE); + + kunmap(p); + } + + kbase_mmu_flush(kctx, vpfn, requested_nr); + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_teardown_pages) + +/** + * Update the entries for specified number of pages pointed to by 'phys' at GPU PFN 'vpfn'. + * This call is being triggered as a response to the changes of the mem attributes + * + * @pre : The caller is responsible for validating the memory attributes + * + * IMPORTANT: This uses kbasep_js_runpool_release_ctx() when the context is + * currently scheduled into the runpool, and so potentially uses a lot of locks. + * These locks must be taken in the correct order with respect to others + * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more + * information. + */ +mali_error kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, phys_addr_t* phys, size_t nr, unsigned long flags) +{ + phys_addr_t pgd; + u64* pgd_page; + u64 mmu_flags = 0; + size_t requested_nr = nr; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + KBASE_DEBUG_ASSERT(vpfn <= (UINT64_MAX / PAGE_SIZE)); + + lockdep_assert_held(&kctx->reg_lock); + + mmu_flags = kbase_mmu_get_mmu_flags(flags); + + dev_warn(kctx->kbdev->dev, "kbase_mmu_update_pages(): updating page share flags "\ + "on GPU PFN 0x%llx from phys %p, %zu pages", + vpfn, phys, nr); + + + while(nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + size_t count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + pgd = mmu_get_bottom_pgd(kctx, vpfn); + if (!pgd) { + dev_warn(kctx->kbdev->dev, "mmu_get_bottom_pgd failure\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, "kmap failure\n"); + return MALI_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; i++) { + page_table_entry_set(kctx->kbdev, &pgd_page[index + i], mmu_phyaddr_to_ate(phys[i], mmu_flags)); + } + + phys += count; + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p) + + (index * sizeof(u64)), + count * sizeof(u64), + DMA_TO_DEVICE); + + kunmap(pfn_to_page(PFN_DOWN(pgd))); + } + + kbase_mmu_flush(kctx, vpfn, requested_nr); + + return MALI_ERROR_NONE; +} + +static int mmu_pte_is_valid(u64 pte) +{ + return ((pte & 3) == ENTRY_IS_ATE); +} + +/* This is a debug feature only */ +static void mmu_check_unused(struct kbase_context *kctx, phys_addr_t pgd) +{ + u64 *page; + int i; + + page = kmap_atomic(pfn_to_page(PFN_DOWN(pgd))); + /* kmap_atomic should NEVER fail. */ + KBASE_DEBUG_ASSERT(NULL != page); + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { + if (mmu_pte_is_valid(page[i])) + beenthere(kctx, "live pte %016lx", (unsigned long)page[i]); + } + kunmap_atomic(page); +} + +static void mmu_teardown_level(struct kbase_context *kctx, phys_addr_t pgd, int level, int zap, u64 *pgd_page_buffer) +{ + phys_addr_t target_pgd; + u64 *pgd_page; + int i; + + KBASE_DEBUG_ASSERT(NULL != kctx); + lockdep_assert_held(&kctx->reg_lock); + + pgd_page = kmap_atomic(pfn_to_page(PFN_DOWN(pgd))); + /* kmap_atomic should NEVER fail. */ + KBASE_DEBUG_ASSERT(NULL != pgd_page); + /* Copy the page to our preallocated buffer so that we can minimize kmap_atomic usage */ + memcpy(pgd_page_buffer, pgd_page, PAGE_SIZE); + kunmap_atomic(pgd_page); + pgd_page = pgd_page_buffer; + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { + target_pgd = mmu_pte_to_phy_addr(pgd_page[i]); + + if (target_pgd) { + if (level < 2) { + mmu_teardown_level(kctx, target_pgd, level + 1, zap, pgd_page_buffer + (PAGE_SIZE / sizeof(u64))); + } else { + /* + * So target_pte is a level-3 page. + * As a leaf, it is safe to free it. + * Unless we have live pages attached to it! + */ + mmu_check_unused(kctx, target_pgd); + } + + beenthere(kctx, "pte %lx level %d", (unsigned long)target_pgd, level + 1); + if (zap) { + kbase_mem_allocator_free(kctx->pgd_allocator, 1, &target_pgd, MALI_TRUE); + kbase_process_page_usage_dec(kctx, 1); + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); + kbase_atomic_sub_pages(1, &g_mtk_gpu_total_memory_usage_in_pages); + } + } + } +} + +mali_error kbase_mmu_init(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL == kctx->mmu_teardown_pages); + + /* Preallocate MMU depth of four pages for mmu_teardown_level to use */ + kctx->mmu_teardown_pages = kmalloc(PAGE_SIZE * 4, GFP_KERNEL); + + kctx->mem_attrs = (AS_MEMATTR_IMPL_DEF_CACHE_POLICY << + (AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY * 8)) | + (AS_MEMATTR_FORCE_TO_CACHE_ALL << + (AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL * 8)) | + (AS_MEMATTR_WRITE_ALLOC << + (AS_MEMATTR_INDEX_WRITE_ALLOC * 8)) | + 0; /* The other indices are unused for now */ + + if (NULL == kctx->mmu_teardown_pages) + return MALI_ERROR_OUT_OF_MEMORY; + + return MALI_ERROR_NONE; +} + +void kbase_mmu_term(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kctx->mmu_teardown_pages); + + kfree(kctx->mmu_teardown_pages); + kctx->mmu_teardown_pages = NULL; +} + +void kbase_mmu_free_pgd(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kctx->mmu_teardown_pages); + + lockdep_assert_held(&kctx->reg_lock); + + mmu_teardown_level(kctx, kctx->pgd, MIDGARD_MMU_TOPLEVEL, 1, kctx->mmu_teardown_pages); + + beenthere(kctx, "pgd %lx", (unsigned long)kctx->pgd); + kbase_mem_allocator_free(kctx->pgd_allocator, 1, &kctx->pgd, MALI_TRUE); + kbase_process_page_usage_dec(kctx, 1); + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); + kbase_atomic_sub_pages(1, &g_mtk_gpu_total_memory_usage_in_pages); +} + +KBASE_EXPORT_TEST_API(kbase_mmu_free_pgd) + +static size_t kbasep_mmu_dump_level(struct kbase_context *kctx, phys_addr_t pgd, int level, char ** const buffer, size_t *size_left) +{ + phys_addr_t target_pgd; + u64 *pgd_page; + int i; + size_t size = KBASE_MMU_PAGE_ENTRIES * sizeof(u64) + sizeof(u64); + size_t dump_size; + + KBASE_DEBUG_ASSERT(NULL != kctx); + lockdep_assert_held(&kctx->reg_lock); + + pgd_page = kmap(pfn_to_page(PFN_DOWN(pgd))); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, "kbasep_mmu_dump_level: kmap failure\n"); + return 0; + } + + if (*size_left >= size) { + /* A modified physical address that contains the page table level */ + u64 m_pgd = pgd | level; + + /* Put the modified physical address in the output buffer */ + memcpy(*buffer, &m_pgd, sizeof(m_pgd)); + *buffer += sizeof(m_pgd); + + /* Followed by the page table itself */ + memcpy(*buffer, pgd_page, sizeof(u64) * KBASE_MMU_PAGE_ENTRIES); + *buffer += sizeof(u64) * KBASE_MMU_PAGE_ENTRIES; + + *size_left -= size; + } + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { + if ((pgd_page[i] & ENTRY_IS_PTE) == ENTRY_IS_PTE) { + target_pgd = mmu_pte_to_phy_addr(pgd_page[i]); + + dump_size = kbasep_mmu_dump_level(kctx, target_pgd, level + 1, buffer, size_left); + if (!dump_size) { + kunmap(pfn_to_page(PFN_DOWN(pgd))); + return 0; + } + size += dump_size; + } + } + + kunmap(pfn_to_page(PFN_DOWN(pgd))); + + return size; +} + +void *kbase_mmu_dump(struct kbase_context *kctx, int nr_pages) +{ + void *kaddr; + size_t size_left; + + KBASE_DEBUG_ASSERT(kctx); + + lockdep_assert_held(&kctx->reg_lock); + + if (0 == nr_pages) { + /* can't find in a 0 sized buffer, early out */ + return NULL; + } + + size_left = nr_pages * PAGE_SIZE; + + KBASE_DEBUG_ASSERT(0 != size_left); + kaddr = vmalloc_user(size_left); + + if (kaddr) { + u64 end_marker = 0xFFULL; + char *buffer = (char *)kaddr; + + size_t size = kbasep_mmu_dump_level(kctx, kctx->pgd, MIDGARD_MMU_TOPLEVEL, &buffer, &size_left); + if (!size) { + vfree(kaddr); + return NULL; + } + + /* Add on the size for the end marker */ + size += sizeof(u64); + + if (size > nr_pages * PAGE_SIZE || size_left < sizeof(u64)) { + /* The buffer isn't big enough - free the memory and return failure */ + vfree(kaddr); + return NULL; + } + + /* Add the end marker */ + memcpy(buffer, &end_marker, sizeof(u64)); + } + + return kaddr; +} +KBASE_EXPORT_TEST_API(kbase_mmu_dump) + +static void bus_fault_worker(struct work_struct *data) +{ + struct kbase_as *faulting_as; + int as_no; + struct kbase_context *kctx; + struct kbase_device *kbdev; +#if KBASE_GPU_RESET_EN + mali_bool reset_status = MALI_FALSE; +#endif /* KBASE_GPU_RESET_EN */ + + faulting_as = container_of(data, struct kbase_as, work_busfault); + + as_no = faulting_as->number; + + kbdev = container_of(faulting_as, struct kbase_device, as[as_no]); + + /* Grab the context that was already refcounted in kbase_mmu_interrupt(). + * Therefore, it cannot be scheduled out of this AS until we explicitly release it + * + * NOTE: NULL can be returned here if we're gracefully handling a spurious interrupt */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as_no); +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245)) { + /* Due to H/W issue 8245 we need to reset the GPU after using UNMAPPED mode. + * We start the reset before switching to UNMAPPED to ensure that unrelated jobs + * are evicted from the GPU before the switch. + */ + dev_err(kbdev->dev, "GPU bus error occurred. For this GPU version we now soft-reset as part of bus error recovery\n"); + reset_status = kbase_prepare_to_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* NOTE: If GPU already powered off for suspend, we don't need to switch to unmapped */ + if (!kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + struct kbase_mmu_setup *current_setup = &faulting_as->current_setup; + + /* switch to UNMAPPED mode, will abort all jobs and stop any hw counter dumping */ + /* AS transaction begin */ + mutex_lock(&kbdev->as[as_no].transaction_mutex); + + /* Set the MMU into unmapped mode */ + current_setup->transtab &= ~(u64)MMU_TRANSTAB_ADRMODE_MASK; + current_setup->transtab |= AS_TRANSTAB_ADRMODE_UNMAPPED; + + /* Apply the new settings */ + kbase_mmu_hw_configure(kbdev, faulting_as, kctx); + + mutex_unlock(&kbdev->as[as_no].transaction_mutex); + /* AS transaction end */ + + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_BUS); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_BUS); + + kbase_pm_context_idle(kbdev); + } +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245) && reset_status) + kbase_reset_gpu(kbdev); +#endif /* KBASE_GPU_RESET_EN */ + /* By this point, the fault was handled in some way, so release the ctx refcount */ + if (kctx != NULL) + kbasep_js_runpool_release_ctx(kbdev, kctx); +} + +const char *kbase_exception_name(u32 exception_code) +{ + const char *e; + + switch (exception_code) { + /* Non-Fault Status code */ + case 0x00: + e = "NOT_STARTED/IDLE/OK"; + break; + case 0x01: + e = "DONE"; + break; + case 0x02: + e = "INTERRUPTED"; + break; + case 0x03: + e = "STOPPED"; + break; + case 0x04: + e = "TERMINATED"; + break; + case 0x08: + e = "ACTIVE"; + break; + /* Job exceptions */ + case 0x40: + e = "JOB_CONFIG_FAULT"; + break; + case 0x41: + e = "JOB_POWER_FAULT"; + break; + case 0x42: + e = "JOB_READ_FAULT"; + break; + case 0x43: + e = "JOB_WRITE_FAULT"; + break; + case 0x44: + e = "JOB_AFFINITY_FAULT"; + break; + case 0x48: + e = "JOB_BUS_FAULT"; + break; + case 0x50: + e = "INSTR_INVALID_PC"; + break; + case 0x51: + e = "INSTR_INVALID_ENC"; + break; + case 0x52: + e = "INSTR_TYPE_MISMATCH"; + break; + case 0x53: + e = "INSTR_OPERAND_FAULT"; + break; + case 0x54: + e = "INSTR_TLS_FAULT"; + break; + case 0x55: + e = "INSTR_BARRIER_FAULT"; + break; + case 0x56: + e = "INSTR_ALIGN_FAULT"; + break; + case 0x58: + e = "DATA_INVALID_FAULT"; + break; + case 0x59: + e = "TILE_RANGE_FAULT"; + break; + case 0x5A: + e = "ADDR_RANGE_FAULT"; + break; + case 0x60: + e = "OUT_OF_MEMORY"; + break; + /* GPU exceptions */ + case 0x80: + e = "DELAYED_BUS_FAULT"; + break; + case 0x88: + e = "SHAREABILITY_FAULT"; + break; + /* MMU exceptions */ + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + e = "TRANSLATION_FAULT"; + break; + case 0xC8: + e = "PERMISSION_FAULT"; + break; + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + e = "TRANSTAB_BUS_FAULT"; + break; + case 0xD8: + e = "ACCESS_FLAG"; + break; + default: + e = "UNKNOWN"; + break; + }; + + return e; +} + +/** + * The caller must ensure it's retained the ctx to prevent it from being scheduled out whilst it's being worked on. + */ +static void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, + struct kbase_as *as, const char *reason_str) +{ + unsigned long flags; + int exception_type; + int access_type; + int source_id; + int as_no; + struct kbase_device *kbdev; + struct kbase_mmu_setup *current_setup; + struct kbasep_js_device_data *js_devdata; + +#if KBASE_GPU_RESET_EN + mali_bool reset_status = MALI_FALSE; +#endif + static const char * const access_type_names[] = { "RESERVED", "EXECUTE", "READ", "WRITE" }; + + as_no = as->number; + kbdev = kctx->kbdev; + js_devdata = &kbdev->js_data; + + /* ASSERT that the context won't leave the runpool */ + KBASE_DEBUG_ASSERT(kbasep_js_debug_check_ctx_refcount(kbdev, kctx) > 0); + + /* decode the fault status */ + exception_type = as->fault_status & 0xFF; + access_type = (as->fault_status >> 8) & 0x3; + source_id = (as->fault_status >> 16); + + /* terminal fault, print info about the fault */ + dev_err(kbdev->dev, + "Unhandled Page fault in AS%d at VA 0x%016llX\n" + "Reason: %s\n" + "raw fault status 0x%X\n" + "decoded fault status: %s\n" + "exception type 0x%X: %s\n" + "access type 0x%X: %s\n" + "source id 0x%X\n", + as_no, as->fault_addr, + reason_str, + as->fault_status, + (as->fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"), + exception_type, kbase_exception_name(exception_type), + access_type, access_type_names[access_type], + source_id); + + /* hardware counters dump fault handling */ + if ((kbdev->hwcnt.kctx) && (kbdev->hwcnt.kctx->as_nr == as_no) && (kbdev->hwcnt.state == KBASE_INSTR_STATE_DUMPING)) { + unsigned int num_core_groups = kbdev->gpu_props.num_core_groups; + if ((as->fault_addr >= kbdev->hwcnt.addr) && (as->fault_addr < (kbdev->hwcnt.addr + (num_core_groups * 2048)))) + kbdev->hwcnt.state = KBASE_INSTR_STATE_FAULT; + } + + /* Stop the kctx from submitting more jobs and cause it to be scheduled + * out/rescheduled - this will occur on releasing the context's refcount */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_clear_submit_allowed(js_devdata, kctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + /* Kill any running jobs from the context. Submit is disallowed, so no more jobs from this + * context can appear in the job slots from this point on */ + kbase_job_kill_jobs_from_context(kctx); + /* AS transaction begin */ + mutex_lock(&as->transaction_mutex); +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245)) { + /* Due to H/W issue 8245 we need to reset the GPU after using UNMAPPED mode. + * We start the reset before switching to UNMAPPED to ensure that unrelated jobs + * are evicted from the GPU before the switch. + */ + dev_err(kbdev->dev, "Unhandled page fault. For this GPU version we now soft-reset the GPU as part of page fault recovery."); + reset_status = kbase_prepare_to_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* switch to UNMAPPED mode, will abort all jobs and stop any hw counter dumping */ + current_setup = &as->current_setup; + + current_setup->transtab &= ~(u64)MMU_TRANSTAB_ADRMODE_MASK; + current_setup->transtab |= AS_TRANSTAB_ADRMODE_UNMAPPED; + + /* Apply the new address space setting */ + kbase_mmu_hw_configure(kbdev, as, kctx); + + mutex_unlock(&as->transaction_mutex); + /* AS transaction end */ + + /* Clear down the fault */ + kbase_mmu_hw_clear_fault(kbdev, as, kctx, KBASE_MMU_FAULT_TYPE_PAGE); + kbase_mmu_hw_enable_fault(kbdev, as, kctx, KBASE_MMU_FAULT_TYPE_PAGE); + +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245) && reset_status) + kbase_reset_gpu(kbdev); +#endif /* KBASE_GPU_RESET_EN */ +} + +void kbasep_as_do_poke(struct work_struct *work) +{ + struct kbase_as *as; + struct kbase_device *kbdev; + struct kbase_context *kctx; + unsigned long flags; + + KBASE_DEBUG_ASSERT(work); + as = container_of(work, struct kbase_as, poke_work); + kbdev = container_of(as, struct kbase_device, as[as->number]); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + /* GPU power will already be active by virtue of the caller holding a JS + * reference on the address space, and will not release it until this worker + * has finished */ + + /* Further to the comment above, we know that while this function is running + * the AS will not be released as before the atom is released this workqueue + * is flushed (in kbase_as_poking_timer_release_atom) + */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as->number); + + /* AS transaction begin */ + mutex_lock(&as->transaction_mutex); + /* Force a uTLB invalidate */ + kbase_mmu_hw_do_operation(kbdev, as, kctx, 0, 0, + AS_COMMAND_UNLOCK, 0); + mutex_unlock(&as->transaction_mutex); + /* AS transaction end */ + + spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags); + if (as->poke_refcount && + !(as->poke_state & KBASE_AS_POKE_STATE_KILLING_POKE)) { + /* Only queue up the timer if we need it, and we're not trying to kill it */ + hrtimer_start(&as->poke_timer, HR_TIMER_DELAY_MSEC(5), HRTIMER_MODE_REL); + } + spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags); + +} + +enum hrtimer_restart kbasep_as_poke_timer_callback(struct hrtimer *timer) +{ + struct kbase_as *as; + int queue_work_ret; + + KBASE_DEBUG_ASSERT(NULL != timer); + as = container_of(timer, struct kbase_as, poke_timer); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + queue_work_ret = queue_work(as->poke_wq, &as->poke_work); + KBASE_DEBUG_ASSERT(queue_work_ret); + return HRTIMER_NORESTART; +} + +/** + * Retain the poking timer on an atom's context (if the atom hasn't already + * done so), and start the timer (if it's not already started). + * + * This must only be called on a context that's scheduled in, and an atom + * that's running on the GPU. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock + * + * This can be called safely from atomic context + */ +void kbase_as_poking_timer_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbase_as *as; + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + if (katom->poking) + return; + + katom->poking = 1; + + /* It's safe to work on the as/as_nr without an explicit reference, + * because the caller holds the runpool_irq lock, and the atom itself + * was also running and had already taken a reference */ + as = &kbdev->as[kctx->as_nr]; + + if (++(as->poke_refcount) == 1) { + /* First refcount for poke needed: check if not already in flight */ + if (!as->poke_state) { + /* need to start poking */ + as->poke_state |= KBASE_AS_POKE_STATE_IN_FLIGHT; + queue_work(as->poke_wq, &as->poke_work); + } + } +} + +/** + * If an atom holds a poking timer, release it and wait for it to finish + * + * This must only be called on a context that's scheduled in, and an atom + * that still has a JS reference on the context + * + * This must \b not be called from atomic context, since it can sleep. + */ +void kbase_as_poking_timer_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbase_as *as; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + if (!katom->poking) + return; + + as = &kbdev->as[kctx->as_nr]; + + spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags); + KBASE_DEBUG_ASSERT(as->poke_refcount > 0); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + if (--(as->poke_refcount) == 0) { + as->poke_state |= KBASE_AS_POKE_STATE_KILLING_POKE; + spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags); + + hrtimer_cancel(&as->poke_timer); + flush_workqueue(as->poke_wq); + + spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags); + + /* Re-check whether it's still needed */ + if (as->poke_refcount) { + int queue_work_ret; + /* Poking still needed: + * - Another retain will not be starting the timer or queueing work, + * because it's still marked as in-flight + * - The hrtimer has finished, and has not started a new timer or + * queued work because it's been marked as killing + * + * So whatever happens now, just queue the work again */ + as->poke_state &= ~((kbase_as_poke_state)KBASE_AS_POKE_STATE_KILLING_POKE); + queue_work_ret = queue_work(as->poke_wq, &as->poke_work); + KBASE_DEBUG_ASSERT(queue_work_ret); + } else { + /* It isn't - so mark it as not in flight, and not killing */ + as->poke_state = 0u; + + /* The poke associated with the atom has now finished. If this is + * also the last atom on the context, then we can guarentee no more + * pokes (and thus no more poking register accesses) will occur on + * the context until new atoms are run */ + } + } + spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags); + + katom->poking = 0; +} + +void kbase_mmu_interrupt_process(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_as *as) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + unsigned long flags; + + if (kctx == NULL) { + dev_warn(kbdev->dev, "%s in AS%d at 0x%016llx with no context present! Suprious IRQ or SW Design Error?\n", + kbase_as_has_bus_fault(as) ? "Bus error" : "Page fault", + as->number, as->fault_addr); + } + + if (kbase_as_has_bus_fault(as)) { + if (kctx) { + /* + * hw counters dumping in progress, signal the + * other thread that it failed + */ + if ((kbdev->hwcnt.kctx == kctx) && + (kbdev->hwcnt.state == KBASE_INSTR_STATE_DUMPING)) + kbdev->hwcnt.state = KBASE_INSTR_STATE_FAULT; + + /* + * Stop the kctx from submitting more jobs and cause it + * to be scheduled out/rescheduled when all references + * to it are released + */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_clear_submit_allowed(js_devdata, kctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, + flags); + + dev_warn(kbdev->dev, "Bus error in AS%d at 0x%016llx\n", + as->number, as->fault_addr); + } + + /* + * We need to switch to UNMAPPED mode - but we do this in a + * worker so that we can sleep + */ + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&as->work_busfault)); + INIT_WORK(&as->work_busfault, bus_fault_worker); + queue_work(as->pf_wq, &as->work_busfault); + } else { + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&as->work_pagefault)); + INIT_WORK(&as->work_pagefault, page_fault_worker); + queue_work(as->pf_wq, &as->work_pagefault); + } +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..876eae8abd7fc65ff84f65a7b2ba998427ca6c3e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw.h @@ -0,0 +1,121 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file + * Interface file for accessing MMU hardware functionality + */ + +/** + * @page mali_kbase_mmu_hw_page MMU hardware interface + * + * @section mali_kbase_mmu_hw_intro_sec Introduction + * This module provides an abstraction for accessing the functionality provided + * by the midgard MMU and thus allows all MMU HW access to be contained within + * one common place and allows for different backends (implementations) to + * be provided. + */ + +#ifndef _MALI_KBASE_MMU_HW_H_ +#define _MALI_KBASE_MMU_HW_H_ + +/* Forward declarations */ +struct kbase_device; +struct kbase_as; +struct kbase_context; + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup mali_kbase_mmu_hw MMU access APIs + * @{ + */ + +/** @brief MMU fault type descriptor. + */ +enum kbase_mmu_fault_type { + KBASE_MMU_FAULT_TYPE_UNKNOWN = 0, + KBASE_MMU_FAULT_TYPE_PAGE, + KBASE_MMU_FAULT_TYPE_BUS +}; + +/** @brief Configure an address space for use. + * + * Configure the MMU using the address space details setup in the + * @ref kbase_context structure. + * + * @param[in] kbdev kbase device to configure. + * @param[in] as address space to configure. + * @param[in] kctx kbase context to configure. + */ +void kbase_mmu_hw_configure(struct kbase_device *kbdev, + struct kbase_as *as, struct kbase_context *kctx); + +/** @brief Issue an operation to the MMU. + * + * Issue an operation (MMU invalidate, MMU flush, etc) on the address space that + * is associated with the provided @ref kbase_context over the specified range + * + * @param[in] kbdev kbase device to issue the MMU operation on. + * @param[in] as address space to issue the MMU operation on. + * @param[in] kctx kbase context to issue the MMU operation on. + * @param[in] vpfn MMU Virtual Page Frame Number to start the + * operation on. + * @param[in] nr Number of pages to work on. + * @param[in] type Operation type (written to ASn_COMMAND). + * @param[in] handling_irq Is this operation being called during the handling + * of an interrupt? + * + * @return Zero if the operation was successful, non-zero otherwise. + */ +int kbase_mmu_hw_do_operation(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, u64 vpfn, u32 nr, u32 type, + unsigned int handling_irq); + +/** @brief Clear a fault that has been previously reported by the MMU. + * + * Clear a bus error or page fault that has been reported by the MMU. + * + * @param[in] kbdev kbase device to clear the fault from. + * @param[in] as address space to clear the fault from. + * @param[in] kctx kbase context to clear the fault from or NULL. + * @param[in] type The type of fault that needs to be cleared. + */ +void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type); + +/** @brief Enable fault that has been previously reported by the MMU. + * + * After a page fault or bus error has been reported by the MMU these + * will be disabled. After these are handled this function needs to be + * called to enable the page fault or bus error fault again. + * + * @param[in] kbdev kbase device to again enable the fault from. + * @param[in] as address space to again enable the fault from. + * @param[in] kctx kbase context to again enable the fault from. + * @param[in] type The type of fault that needs to be enabled again. + */ +void kbase_mmu_hw_enable_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type); + +/** @} *//* end group mali_kbase_mmu_hw */ +/** @} *//* end group base_kbase_api */ + +#endif /* _MALI_KBASE_MMU_HW_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.c new file mode 100644 index 0000000000000000000000000000000000000000..7ce94e922584c55d14f65f6586284933d169f1e5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.c @@ -0,0 +1,294 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#include +#include +#include +#include + +#if KBASE_MMU_HW_BACKEND + +static inline u64 lock_region(struct kbase_device *kbdev, u64 pfn, + u32 num_pages) +{ + u64 region; + + /* can't lock a zero sized range */ + KBASE_DEBUG_ASSERT(num_pages); + + region = pfn << PAGE_SHIFT; + /* + * fls returns (given the ASSERT above): + * 1 .. 32 + * + * 10 + fls(num_pages) + * results in the range (11 .. 42) + */ + + /* gracefully handle num_pages being zero */ + if (0 == num_pages) { + region |= 11; + } else { + u8 region_width; + + region_width = 10 + fls(num_pages); + if (num_pages != (1ul << (region_width - 11))) { + /* not pow2, so must go up to the next pow2 */ + region_width += 1; + } + KBASE_DEBUG_ASSERT(region_width <= KBASE_LOCK_REGION_MAX_SIZE); + KBASE_DEBUG_ASSERT(region_width >= KBASE_LOCK_REGION_MIN_SIZE); + region |= region_width; + } + + return region; +} + +static int wait_ready(struct kbase_device *kbdev, + unsigned int as_nr, struct kbase_context *kctx) +{ + unsigned int max_loops = KBASE_AS_INACTIVE_MAX_LOOPS; + + /* Wait for the MMU status to indicate there is no active command. */ + while (--max_loops && kbase_reg_read(kbdev, + MMU_AS_REG(as_nr, AS_STATUS), + kctx) & AS_STATUS_AS_ACTIVE) { + ; + } + + if (max_loops == 0) { + dev_err(kbdev->dev, "AS_ACTIVE bit stuck\n"); + return -1; + } + + return 0; +} + +static int write_cmd(struct kbase_device *kbdev, int as_nr, u32 cmd, + struct kbase_context *kctx) +{ + int status; + + /* write AS_COMMAND when MMU is ready to accept another command */ + status = wait_ready(kbdev, as_nr, kctx); + if (status == 0) + kbase_reg_write(kbdev, MMU_AS_REG(as_nr, AS_COMMAND), cmd, kctx); + + return status; +} + +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat) +{ + const int num_as = 16; + const int busfault_shift = MMU_PAGE_FAULT_FLAGS; + const int pf_shift = 0; + const unsigned long as_bit_mask = (1UL << num_as) - 1; + unsigned long flags; + u32 new_mask; + u32 tmp; + + /* bus faults */ + u32 bf_bits = (irq_stat >> busfault_shift) & as_bit_mask; + /* page faults (note: Ignore ASes with both pf and bf) */ + u32 pf_bits = ((irq_stat >> pf_shift) & as_bit_mask) & ~bf_bits; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + + /* remember current mask */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + new_mask = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL); + /* mask interrupts for now */ + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0, NULL); + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); + + while (bf_bits | pf_bits) { + struct kbase_as *as; + int as_no; + struct kbase_context *kctx; + + /* + * the while logic ensures we have a bit set, no need to check + * for not-found here + */ + as_no = ffs(bf_bits | pf_bits) - 1; + as = &kbdev->as[as_no]; + + /* + * Refcount the kctx ASAP - it shouldn't disappear anyway, since + * Bus/Page faults _should_ only occur whilst jobs are running, + * and a job causing the Bus/Page fault shouldn't complete until + * the MMU is updated + */ + kctx = kbasep_js_runpool_lookup_ctx(kbdev, as_no); + + /* find faulting address */ + as->fault_addr = kbase_reg_read(kbdev, + MMU_AS_REG(as_no, AS_FAULTADDRESS_HI), + kctx); + as->fault_addr <<= 32; + as->fault_addr |= kbase_reg_read(kbdev, + MMU_AS_REG(as_no, AS_FAULTADDRESS_LO), + kctx); + + /* record the fault status */ + as->fault_status = kbase_reg_read(kbdev, + MMU_AS_REG(as_no, AS_FAULTSTATUS), + kctx); + + /* find the fault type */ + as->fault_type = (bf_bits & (1 << as_no)) ? + KBASE_MMU_FAULT_TYPE_BUS : + KBASE_MMU_FAULT_TYPE_PAGE; + + if (kbase_as_has_bus_fault(as)) { + /* Mark bus fault as handled. + * Note that a bus fault is processed first in case + * where both a bus fault and page fault occur. + */ + bf_bits &= ~(1UL << as_no); + + /* remove the queued BF (and PF) from the mask */ + new_mask &= ~(MMU_BUS_ERROR(as_no) | + MMU_PAGE_FAULT(as_no)); + } else { + /* Mark page fault as handled */ + pf_bits &= ~(1UL << as_no); + + /* remove the queued PF from the mask */ + new_mask &= ~MMU_PAGE_FAULT(as_no); + } + + /* Process the interrupt for this address space */ + kbase_mmu_interrupt_process(kbdev, kctx, as); + } + + /* reenable interrupts */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + tmp = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL); + new_mask |= tmp; + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), new_mask, NULL); + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); +} + +void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx) +{ + struct kbase_mmu_setup *current_setup = &as->current_setup; + + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSTAB_LO), + current_setup->transtab & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSTAB_HI), + (current_setup->transtab >> 32) & 0xFFFFFFFFUL, kctx); + + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_MEMATTR_LO), + current_setup->memattr & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_MEMATTR_HI), + (current_setup->memattr >> 32) & 0xFFFFFFFFUL, kctx); + write_cmd(kbdev, as->number, AS_COMMAND_UPDATE, kctx); +} + +int kbase_mmu_hw_do_operation(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, u64 vpfn, u32 nr, u32 op, + unsigned int handling_irq) +{ + int ret; + + if (op == AS_COMMAND_UNLOCK) { + /* Unlock doesn't require a lock first */ + ret = write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + } else { + u64 lock_addr = lock_region(kbdev, vpfn, nr); + + /* Lock the region that needs to be updated */ + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_LOCKADDR_LO), + lock_addr & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_LOCKADDR_HI), + (lock_addr >> 32) & 0xFFFFFFFFUL, kctx); + write_cmd(kbdev, as->number, AS_COMMAND_LOCK, kctx); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_3285) && + handling_irq) { + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), + (1UL << as->number), NULL); + write_cmd(kbdev, as->number, AS_COMMAND_LOCK, kctx); + } + + /* Run the MMU operation */ + write_cmd(kbdev, as->number, op, kctx); + + /* Wait for the flush to complete */ + ret = wait_ready(kbdev, as->number, kctx); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_9630)) { + /* Issue an UNLOCK command to ensure that valid page + tables are re-read by the GPU after an update. + Note that, the FLUSH command should perform all the + actions necessary, however the bus logs show that if + multiple page faults occur within an 8 page region + the MMU does not always re-read the updated page + table entries for later faults or is only partially + read, it subsequently raises the page fault IRQ for + the same addresses, the unlock ensures that the MMU + cache is flushed, so updates can be re-read. As the + region is now unlocked we need to issue 2 UNLOCK + commands in order to flush the MMU/uTLB, + see PRLAM-8812. + */ + write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + } + } + + return ret; +} + +void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type) +{ + u32 pf_bf_mask; + + /* Clear the page (and bus fault IRQ as well in case one occurred) */ + pf_bf_mask = MMU_PAGE_FAULT(as->number); + if (type == KBASE_MMU_FAULT_TYPE_BUS) + pf_bf_mask |= MMU_BUS_ERROR(as->number); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), pf_bf_mask, kctx); +} + +void kbase_mmu_hw_enable_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type) +{ + unsigned long flags; + u32 irq_mask; + + /* Enable the page fault IRQ (and bus fault IRQ as well in case one + * occurred) */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + + irq_mask = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), kctx) | + MMU_PAGE_FAULT(as->number); + + if (type == KBASE_MMU_FAULT_TYPE_BUS) + irq_mask |= MMU_BUS_ERROR(as->number); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), irq_mask, kctx); + + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); +} +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.h new file mode 100644 index 0000000000000000000000000000000000000000..9737dbb9aa2e22aad707ea0edab0fcf464dc9402 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.h @@ -0,0 +1,59 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file + * Interface file for the direct implementation for MMU hardware access + */ + +/** + * @page mali_kbase_mmu_hw_direct_page Direct MMU hardware interface + * + * @section mali_kbase_mmu_hw_direct_intro_sec Introduction + * This module provides the interface(s) that are required by the direct + * register access implementation of the MMU hardware interface + * @ref mali_kbase_mmu_hw_page . + */ + +#ifndef _MALI_KBASE_MMU_HW_DIRECT_H_ +#define _MALI_KBASE_MMU_HW_DIRECT_H_ + +#include + +/** + * @addtogroup mali_kbase_mmu_hw + * @{ + */ + +/** + * @addtogroup mali_kbase_mmu_hw_direct Direct register access to MMU + * @{ + */ + +/** @brief Process an MMU interrupt. + * + * Process the MMU interrupt that was reported by the @ref kbase_device. + * + * @param[in] kbdev kbase context to clear the fault from. + * @param[in] irq_stat Value of the MMU_IRQ_STATUS register + */ +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat); + +/** @} *//* end group mali_kbase_mmu_hw_direct */ +/** @} *//* end group mali_kbase_mmu_hw */ + +#endif /* _MALI_KBASE_MMU_HW_DIRECT_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c new file mode 100644 index 0000000000000000000000000000000000000000..c36b9358949722c430eedc020839f3d9483b6ea4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c @@ -0,0 +1,142 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifdef CONFIG_MALI_PLATFORM_FAKE + +#include +#include +#include +#include +#include + +#ifdef CONFIG_MACH_MANTA +#include +#endif + +/* + * This file is included only for type definitions and functions belonging to + * specific platform folders. Do not add dependencies with symbols that are + * defined somewhere else. + */ +#include + +#define PLATFORM_CONFIG_RESOURCE_COUNT 4 +#define PLATFORM_CONFIG_IRQ_RES_COUNT 3 + +static struct platform_device *mali_device; + +#ifndef CONFIG_OF +/** + * @brief Convert data in struct kbase_io_resources struct to Linux-specific resources + * + * Function converts data in struct kbase_io_resources struct to an array of Linux resource structures. Note that function + * assumes that size of linux_resource array is at least PLATFORM_CONFIG_RESOURCE_COUNT. + * Resources are put in fixed order: I/O memory region, job IRQ, MMU IRQ, GPU IRQ. + * + * @param[in] io_resource Input IO resource data + * @param[out] linux_resources Pointer to output array of Linux resource structures + */ +static void kbasep_config_parse_io_resources(const struct kbase_io_resources *io_resources, struct resource *const linux_resources) +{ + if (!io_resources || !linux_resources) { + pr_err("%s: couldn't find proper resources\n", __func__); + return; + } + + memset(linux_resources, 0, PLATFORM_CONFIG_RESOURCE_COUNT * sizeof(struct resource)); + + linux_resources[0].start = io_resources->io_memory_region.start; + linux_resources[0].end = io_resources->io_memory_region.end; + linux_resources[0].flags = IORESOURCE_MEM; + linux_resources[1].start = io_resources->job_irq_number; + linux_resources[1].end = io_resources->job_irq_number; + linux_resources[1].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; + + linux_resources[2].start = io_resources->mmu_irq_number; + linux_resources[2].end = io_resources->mmu_irq_number; + linux_resources[2].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; + + linux_resources[3].start = io_resources->gpu_irq_number; + linux_resources[3].end = io_resources->gpu_irq_number; + linux_resources[3].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; +} +#endif /* CONFIG_OF */ + +int kbase_platform_fake_register(void) +{ + struct kbase_platform_config *config; + int attribute_count; +#ifndef CONFIG_OF + struct resource resources[PLATFORM_CONFIG_RESOURCE_COUNT]; +#endif + int err; + + config = kbase_get_platform_config(); /* declared in midgard/mali_kbase_config.h but defined in platform folder */ + if (config == NULL) { + pr_err("%s: couldn't get platform config\n", __func__); + return -ENODEV; + } + + attribute_count = kbasep_get_config_attribute_count(config->attributes); +#ifdef CONFIG_MACH_MANTA + err = platform_device_add_data(&exynos5_device_g3d, config->attributes, attribute_count * sizeof(config->attributes[0])); + if (err) + return err; +#else + + mali_device = platform_device_alloc("mali", 0); + if (mali_device == NULL) + return -ENOMEM; + +#ifndef CONFIG_OF + kbasep_config_parse_io_resources(config->io_resources, resources); + err = platform_device_add_resources(mali_device, resources, PLATFORM_CONFIG_RESOURCE_COUNT); + if (err) { + platform_device_put(mali_device); + mali_device = NULL; + return err; + } +#endif /* CONFIG_OF */ + + err = platform_device_add_data(mali_device, config->attributes, attribute_count * sizeof(config->attributes[0])); + if (err) { + platform_device_unregister(mali_device); + mali_device = NULL; + return err; + } + + err = platform_device_add(mali_device); + if (err) { + platform_device_unregister(mali_device); + mali_device = NULL; + return err; + } +#endif /* CONFIG_CONFIG_MACH_MANTA */ + + return 0; +} +EXPORT_SYMBOL(kbase_platform_fake_register); + +void kbase_platform_fake_unregister(void) +{ + if (mali_device) + platform_device_unregister(mali_device); +} +EXPORT_SYMBOL(kbase_platform_fake_unregister); + +#endif /* CONFIG_MALI_PLATFORM_FAKE */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.c new file mode 100644 index 0000000000000000000000000000000000000000..17d25f43c939fa6f2b763b648ed0d156993b2ae3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.c @@ -0,0 +1,554 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm.c + * Base kernel power management APIs + */ + +#include +#include + +#include + +//#define NO_DVFS_FOR_BRINGUP + +#if KBASE_PM_EN + +/* MTK GPU DVFS */ +#include "mt_gpufreq.h" +#include "mt_chip.h" +//#include "mach/mt_devinfo.h" + +extern u32 get_devinfo_with_index(u32 index); +unsigned int g_current_gpu_platform_id = 0; + +mtk_gpu_freq_limit_data mt6755_gpu_freq_limit_data[MTK_MT6755_GPU_LIMIT_COUNT]= +{ {8, 4, (const int[]){0,2,4,7}}, // MT6755; no limit +}; + +extern unsigned int (*mtk_get_gpu_loading_fp)(void); +extern void (*mtk_boost_gpu_freq_fp)(void); +extern void (*mtk_custom_boost_gpu_freq_fp)(unsigned int ui32FreqLevel); +extern void (*mtk_set_bottom_gpu_freq_fp)(unsigned int ui32FreqLevel); +extern unsigned int (*mtk_custom_get_gpu_freq_level_count_fp)(void); + +/* for MTK GPU boost and power limit */ +extern void __attribute__((weak)) mt_gpufreq_input_boost_notify_registerCB(gpufreq_input_boost_notify pCB); +extern void __attribute__((weak)) mt_gpufreq_power_limit_notify_registerCB(gpufreq_power_limit_notify pCB); + +extern unsigned int mt_gpufreq_get_dvfs_table_num(void); +/* gpu SODI */ +extern void (*mtk_gpu_sodi_entry_fp)(void); +extern void (*mtk_gpu_sodi_exit_fp)(void); +extern void mali_SODI_begin(void); +extern void mali_SODI_exit(void); + +unsigned int mtk_get_current_gpu_platform_id() +{ + return g_current_gpu_platform_id; +} + +void _mtk_gpu_dvfs_init(void) +{ + int i; + unsigned int iCurrentFreqCount; + pr_debug("[MALI] _mtk_gpu_dvfs_init\n"); + + iCurrentFreqCount = mt_gpufreq_get_dvfs_table_num(); + pr_alert("[MALI] _mtk_gpu_dvfs_init, count: %d\n", iCurrentFreqCount); + + + // get curent platform index + for(i=0 ; iconfig_attributes, KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS); + + if (callbacks) + callbacks->power_on_callback(kbdev); +} + +void kbase_pm_register_access_disable(struct kbase_device *kbdev) +{ + struct kbase_pm_callback_conf *callbacks; + + callbacks = (struct kbase_pm_callback_conf *)kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS); + + if (callbacks) + callbacks->power_off_callback(kbdev); +} + +extern void (*ged_dvfs_cal_gpu_utilization_fp)(unsigned int* pui32Loading , unsigned int* pui32Block,unsigned int* pui32Idle); +extern void (*ged_dvfs_gpu_freq_commit_fp)(unsigned long ui32NewFreqID, GED_DVFS_COMMIT_TYPE eCommitType, int* pbCommited); +extern unsigned int (*mtk_get_gpu_power_loading_fp)(void); + +mali_error kbase_pm_init(struct kbase_device *kbdev) +{ + mali_error ret = MALI_ERROR_NONE; + struct kbase_pm_callback_conf *callbacks; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_init(&kbdev->pm.lock); + + kbdev->pm.gpu_powered = MALI_FALSE; + kbdev->pm.suspending = MALI_FALSE; +#ifdef CONFIG_MALI_DEBUG + kbdev->pm.driver_ready_for_irqs = MALI_FALSE; +#endif /* CONFIG_MALI_DEBUG */ + kbdev->pm.gpu_in_desired_state = MALI_TRUE; + init_waitqueue_head(&kbdev->pm.gpu_in_desired_state_wait); + + callbacks = (struct kbase_pm_callback_conf *)kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS); + if (callbacks) { + kbdev->pm.callback_power_on = callbacks->power_on_callback; + kbdev->pm.callback_power_off = callbacks->power_off_callback; + kbdev->pm.callback_power_suspend = + callbacks->power_suspend_callback; + kbdev->pm.callback_power_resume = + callbacks->power_resume_callback; + kbdev->pm.callback_power_runtime_init = callbacks->power_runtime_init_callback; + kbdev->pm.callback_power_runtime_term = callbacks->power_runtime_term_callback; + kbdev->pm.callback_power_runtime_on = callbacks->power_runtime_on_callback; + kbdev->pm.callback_power_runtime_off = callbacks->power_runtime_off_callback; + } else { + kbdev->pm.callback_power_on = NULL; + kbdev->pm.callback_power_off = NULL; + kbdev->pm.callback_power_suspend = NULL; + kbdev->pm.callback_power_resume = NULL; + kbdev->pm.callback_power_runtime_init = NULL; + kbdev->pm.callback_power_runtime_term = NULL; + kbdev->pm.callback_power_runtime_on = NULL; + kbdev->pm.callback_power_runtime_off = NULL; + } + + /* MTK GPU DVFS init */ + _mtk_gpu_dvfs_init(); +#ifndef ENABLE_COMMON_DVFS + /* MTK Register input boost and power limit call back function */ + mt_gpufreq_input_boost_notify_registerCB(mtk_gpu_input_boost_CB); + mt_gpufreq_power_limit_notify_registerCB(mtk_gpu_power_limit_CB); + + /* Register gpu boost function to MTK HAL */ + mtk_boost_gpu_freq_fp = mtk_kbase_boost_gpu_freq; + mtk_custom_boost_gpu_freq_fp = mtk_kbase_custom_boost_gpu_freq; /* used for for performance service boost */ + mtk_set_bottom_gpu_freq_fp = mtk_kbase_ged_bottom_gpu_freq; /* used for GED boost */ + mtk_custom_get_gpu_freq_level_count_fp = mtk_kbase_custom_get_gpu_freq_level_count; + + /* MTK MET use */ + mtk_get_gpu_loading_fp = kbasep_get_gl_utilization; + /* SODI callback function */ + mtk_gpu_sodi_entry_fp = mali_SODI_begin; + mtk_gpu_sodi_exit_fp = mali_SODI_exit; +#else + ged_dvfs_cal_gpu_utilization_fp = MTKCalGpuUtilization; + ged_dvfs_gpu_freq_commit_fp = mtk_gpu_dvfs_commit; +#endif + mtk_get_gpu_power_loading_fp = MTKCalPowerIndex; + + kbdev->pm.platform_dvfs_frequency = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ); + + /* Initialise the metrics subsystem */ + ret = kbasep_pm_metrics_init(kbdev); + if (MALI_ERROR_NONE != ret) + return ret; + + init_waitqueue_head(&kbdev->pm.l2_powered_wait); + kbdev->pm.l2_powered = 0; + + init_waitqueue_head(&kbdev->pm.reset_done_wait); + kbdev->pm.reset_done = MALI_FALSE; + + init_waitqueue_head(&kbdev->pm.zero_active_count_wait); + kbdev->pm.active_count = 0; + + spin_lock_init(&kbdev->pm.power_change_lock); + spin_lock_init(&kbdev->pm.gpu_cycle_counter_requests_lock); + spin_lock_init(&kbdev->pm.gpu_powered_lock); + + if (MALI_ERROR_NONE != kbase_pm_ca_init(kbdev)) + goto workq_fail; + + if (MALI_ERROR_NONE != kbase_pm_policy_init(kbdev)) + goto pm_policy_fail; + + return MALI_ERROR_NONE; + +pm_policy_fail: + kbase_pm_ca_term(kbdev); +workq_fail: + kbasep_pm_metrics_term(kbdev); + return MALI_ERROR_FUNCTION_FAILED; +} + +KBASE_EXPORT_TEST_API(kbase_pm_init) + +void kbase_pm_do_poweron(struct kbase_device *kbdev, mali_bool is_resume) +{ + lockdep_assert_held(&kbdev->pm.lock); + + /* Turn clocks and interrupts on - no-op if we haven't done a previous + * kbase_pm_clock_off() */ + kbase_pm_clock_on(kbdev, is_resume); + + /* Update core status as required by the policy */ + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_START); + kbase_pm_update_cores_state(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_END); + + /* NOTE: We don't wait to reach the desired state, since running atoms + * will wait for that state to be reached anyway */ +} + +void kbase_pm_do_poweroff(struct kbase_device *kbdev, mali_bool is_suspend) +{ + unsigned long flags; + mali_bool cores_are_available; + + lockdep_assert_held(&kbdev->pm.lock); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + /* Force all cores off */ + kbdev->pm.desired_shader_state = 0; + + /* Force all cores to be unavailable, in the situation where + * transitions are in progress for some cores but not others, + * and kbase_pm_check_transitions_nolock can not immediately + * power off the cores */ + kbdev->shader_available_bitmap = 0; + kbdev->tiler_available_bitmap = 0; + kbdev->l2_available_bitmap = 0; + + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_START); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_END); + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* NOTE: We won't wait to reach the core's desired state, even if we're + * powering off the GPU itself too. It's safe to cut the power whilst + * they're transitioning to off, because the cores should be idle and all + * cache flushes should already have occurred */ + + /* Consume any change-state events */ + kbase_timeline_pm_check_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + /* Disable interrupts and turn the clock off */ + kbase_pm_clock_off(kbdev, is_suspend); +} + +mali_error kbase_pm_powerup(struct kbase_device *kbdev) +{ + unsigned long flags; + mali_error ret; + unsigned int gpu_efuse; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_lock(&kbdev->pm.lock); + + /* A suspend won't happen during startup/insmod */ + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + + /* Power up the GPU, don't enable IRQs as we are not ready to receive them. */ + ret = kbase_pm_init_hw(kbdev, MALI_FALSE); + if (ret != MALI_ERROR_NONE) { + mutex_unlock(&kbdev->pm.lock); + return ret; + } + + kbasep_pm_read_present_cores(kbdev); + + // read GPU efuse info. + gpu_efuse = (get_devinfo_with_index(17) >> 6)&0x01; + pr_alert("[Mali] get_devinfo_with_index = 0x%x , gpu_efuse = 0x%x \n", get_devinfo_with_index(17), gpu_efuse); + if( gpu_efuse == 1 ){ + kbdev->pm.debug_core_mask = (u64)1; // 1-core + pr_alert("[Mali] get_devinfo_with_index = 0x%x, MP1 core \n", get_devinfo_with_index(17)); + }else{ + kbdev->pm.debug_core_mask = kbdev->shader_present_bitmap; + } + + /* Pretend the GPU is active to prevent a power policy turning the GPU cores off */ + kbdev->pm.active_count = 1; + + spin_lock_irqsave(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + /* Ensure cycle counter is off */ + kbdev->pm.gpu_cycle_counter_requests = 0; + spin_unlock_irqrestore(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + /* We are ready to receive IRQ's now as power policy is set up, so enable them now. */ +#ifdef CONFIG_MALI_DEBUG + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + kbdev->pm.driver_ready_for_irqs = MALI_TRUE; + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); +#endif + kbase_pm_enable_interrupts(kbdev); + + /* Turn on the GPU and any cores needed by the policy */ + kbase_pm_do_poweron(kbdev, MALI_FALSE); + mutex_unlock(&kbdev->pm.lock); + + /* Idle the GPU and/or cores, if the policy wants it to */ + kbase_pm_context_idle(kbdev); + + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_pm_powerup) + +void kbase_pm_context_active(struct kbase_device *kbdev) +{ + (void)kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE); +} + +int kbase_pm_context_active_handle_suspend(struct kbase_device *kbdev, enum kbase_pm_suspend_handler suspend_handler) +{ + int c; + int old_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* Trace timeline information about how long it took to handle the decision + * to powerup. Sometimes the event might be missed due to reading the count + * outside of mutex, but this is necessary to get the trace timing + * correct. */ + old_count = kbdev->pm.active_count; + if (old_count == 0) + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + + mutex_lock(&kbdev->pm.lock); + if (kbase_pm_is_suspending(kbdev)) { + switch (suspend_handler) { + case KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE: + if (kbdev->pm.active_count != 0) + break; + /* FALLTHROUGH */ + case KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE: + mutex_unlock(&kbdev->pm.lock); + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + return 1; + + case KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE: + /* FALLTHROUGH */ + default: + KBASE_DEBUG_ASSERT_MSG(MALI_FALSE, "unreachable"); + break; + } + } + c = ++kbdev->pm.active_count; + KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, c); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, PM_CONTEXT_ACTIVE, NULL, NULL, 0u, c); + + /* Trace the event being handled */ + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + + if (c == 1) { + /* First context active: Power on the GPU and any cores requested by + * the policy */ + kbase_pm_update_active(kbdev); + + kbasep_pm_record_gpu_active(kbdev); + } + + mutex_unlock(&kbdev->pm.lock); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_pm_context_active) + +void kbase_pm_context_idle(struct kbase_device *kbdev) +{ + int c; + int old_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* Trace timeline information about how long it took to handle the decision + * to powerdown. Sometimes the event might be missed due to reading the + * count outside of mutex, but this is necessary to get the trace timing + * correct. */ + old_count = kbdev->pm.active_count; + if (old_count == 0) + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_IDLE); + + mutex_lock(&kbdev->pm.lock); + + c = --kbdev->pm.active_count; + KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, c); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, PM_CONTEXT_IDLE, NULL, NULL, 0u, c); + + KBASE_DEBUG_ASSERT(c >= 0); + + /* Trace the event being handled */ + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_IDLE); + + if (c == 0) { + /* Last context has gone idle */ + kbase_pm_update_active(kbdev); + + kbasep_pm_record_gpu_idle(kbdev); + + /* Wake up anyone waiting for this to become 0 (e.g. suspend). The + * waiters must synchronize with us by locking the pm.lock after + * waiting */ + wake_up(&kbdev->pm.zero_active_count_wait); + } + + mutex_unlock(&kbdev->pm.lock); +} + +KBASE_EXPORT_TEST_API(kbase_pm_context_idle) + +void kbase_pm_halt(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_lock(&kbdev->pm.lock); + kbase_pm_cancel_deferred_poweroff(kbdev); + kbase_pm_do_poweroff(kbdev, MALI_FALSE); + mutex_unlock(&kbdev->pm.lock); +} + +KBASE_EXPORT_TEST_API(kbase_pm_halt) + +void kbase_pm_term(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kbdev->pm.active_count == 0); + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_cycle_counter_requests == 0); + + /* Free any resources the policy allocated */ + kbase_pm_policy_term(kbdev); + kbase_pm_ca_term(kbdev); + + /* Shut down the metrics subsystem */ + kbasep_pm_metrics_term(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_term) + +void kbase_pm_suspend(struct kbase_device *kbdev) +{ + int nr_keep_gpu_powered_ctxs; + + KBASE_DEBUG_ASSERT(kbdev); + + mutex_lock(&kbdev->pm.lock); + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + kbdev->pm.suspending = MALI_TRUE; + mutex_unlock(&kbdev->pm.lock); + + /* From now on, the active count will drop towards zero. Sometimes, it'll + * go up briefly before going down again. However, once it reaches zero it + * will stay there - guaranteeing that we've idled all pm references */ + + /* Suspend job scheduler and associated components, so that it releases all + * the PM active count references */ + kbasep_js_suspend(kbdev); + + /* Suspend any counter collection that might be happening */ + kbase_instr_hwcnt_suspend(kbdev); + + /* Cancel the keep_gpu_powered calls */ + for (nr_keep_gpu_powered_ctxs = atomic_read(&kbdev->keep_gpu_powered_count); + nr_keep_gpu_powered_ctxs > 0; + --nr_keep_gpu_powered_ctxs) { + kbase_pm_context_idle(kbdev); + } + + /* Wait for the active count to reach zero. This is not the same as + * waiting for a power down, since not all policies power down when this + * reaches zero. */ + wait_event(kbdev->pm.zero_active_count_wait, kbdev->pm.active_count == 0); + + /* NOTE: We synchronize with anything that was just finishing a + * kbase_pm_context_idle() call by locking the pm.lock below */ + + /* Force power off the GPU and all cores (regardless of policy), only after + * the PM active count reaches zero (otherwise, we risk turning it off + * prematurely) */ + mutex_lock(&kbdev->pm.lock); + kbase_pm_cancel_deferred_poweroff(kbdev); + kbase_pm_do_poweroff(kbdev, MALI_TRUE); + mutex_unlock(&kbdev->pm.lock); +} + +void kbase_pm_resume(struct kbase_device *kbdev) +{ + int nr_keep_gpu_powered_ctxs; + + /* MUST happen before any pm_context_active calls occur */ + mutex_lock(&kbdev->pm.lock); + kbdev->pm.suspending = MALI_FALSE; + kbase_pm_do_poweron(kbdev, MALI_TRUE); + mutex_unlock(&kbdev->pm.lock); + + /* Initial active call, to power on the GPU/cores if needed */ + kbase_pm_context_active(kbdev); + + /* Restore the keep_gpu_powered calls */ + for (nr_keep_gpu_powered_ctxs = atomic_read(&kbdev->keep_gpu_powered_count); + nr_keep_gpu_powered_ctxs > 0; + --nr_keep_gpu_powered_ctxs) { + kbase_pm_context_active(kbdev); + } + + /* Re-enable instrumentation, if it was previously disabled */ + kbase_instr_hwcnt_resume(kbdev); + + /* Resume any blocked atoms (which may cause contexts to be scheduled in + * and dependent atoms to run) */ + kbase_resume_suspended_soft_jobs(kbdev); + + /* Resume the Job Scheduler and associated components, and start running + * atoms */ + kbasep_js_resume(kbdev); + + /* Matching idle call, to power off the GPU/cores if we didn't actually + * need it and the policy doesn't want it on */ + kbase_pm_context_idle(kbdev); +} +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.h new file mode 100755 index 0000000000000000000000000000000000000000..5ac666aed960c816855ac8662828829c606145f5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.h @@ -0,0 +1,948 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm.h + * Power management API definitions + */ + +#ifndef _KBASE_PM_H_ +#define _KBASE_PM_H_ + +#include +#include + +/* Forward definition - see mali_kbase.h */ +struct kbase_device; + +#include "mali_kbase_pm_ca.h" +#include "mali_kbase_pm_policy.h" + +#include "mali_kbase_pm_ca_fixed.h" +#if !MALI_CUSTOMER_RELEASE +#include "mali_kbase_pm_ca_random.h" +#endif + +#include "mali_kbase_pm_always_on.h" +#include "mali_kbase_pm_coarse_demand.h" +#include "mali_kbase_pm_demand.h" +#if !MALI_CUSTOMER_RELEASE +#include "mali_kbase_pm_demand_always_powered.h" +#include "mali_kbase_pm_fast_start.h" +#endif + +#include "ged_dvfs.h" + +/** The types of core in a GPU. + * + * These enumerated values are used in calls to: + * - @ref kbase_pm_get_present_cores + * - @ref kbase_pm_get_active_cores + * - @ref kbase_pm_get_trans_cores + * - @ref kbase_pm_get_ready_cores. + * + * They specify which type of core should be acted on. These values are set in + * a manner that allows @ref core_type_to_reg function to be simpler and more + * efficient. + */ +enum kbase_pm_core_type { + KBASE_PM_CORE_L3 = L3_PRESENT_LO, /**< The L3 cache */ + KBASE_PM_CORE_L2 = L2_PRESENT_LO, /**< The L2 cache */ + KBASE_PM_CORE_SHADER = SHADER_PRESENT_LO, /**< Shader cores */ + KBASE_PM_CORE_TILER = TILER_PRESENT_LO /**< Tiler cores */ +}; +/* MTK DVFS */ +#define MTK_MT6755_GPU_LIMIT_COUNT 1 + +typedef struct _mtk_gpu_freq_limit_data{ + const int actual_freq_index_count; + const int virtual_freq_index_count; + const int *virtual_freq_index; +}mtk_gpu_freq_limit_data; +enum mtk_vgpu_power_on { + MTK_VGPU_POWER_OFF, /** VGPU_POWER_OFF */ + MTK_VGPU_POWER_ON, /** VGPU_POWER_ON */ +}; + +extern mtk_gpu_freq_limit_data mt6755_gpu_freq_limit_data[]; + + +/** Initialize the power management framework. + * + * Must be called before any other power management function + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE if the power management framework was successfully initialized. + */ +mali_error kbase_pm_init(struct kbase_device *kbdev); + +/** Power up GPU after all modules have been initialized and interrupt handlers installed. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE if powerup was successful. + */ +mali_error kbase_pm_powerup(struct kbase_device *kbdev); + +/** + * Halt the power management framework. + * Should ensure that no new interrupts are generated, + * but allow any currently running interrupt handlers to complete successfully. + * The GPU is forced off by the time this function returns, regardless of + * whether or not the active power policy asks for the GPU to be powered off. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_halt(struct kbase_device *kbdev); + +/** Terminate the power management framework. + * + * No power management functions may be called after this + * (except @ref kbase_pm_init) + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_term(struct kbase_device *kbdev); + +/** Metrics data collected for use by the power management framework. + * + */ +struct kbasep_pm_metrics_data { + int vsync_hit; + int utilisation; + int util_gl_share; + int util_cl_share[2]; /* 2 is a max number of core groups we can have */ + ktime_t time_period_start; + u32 time_busy; + u32 time_idle; + mali_bool gpu_active; + u32 busy_cl[2]; + u32 busy_gl; + u32 active_cl_ctx[2]; + u32 active_gl_ctx; + + spinlock_t lock; + +#ifdef CONFIG_MALI_MIDGARD_DVFS + struct hrtimer timer; + mali_bool timer_active; +#endif + + void *platform_data; + struct kbase_device *kbdev; +}; + +/** Actions for DVFS. + * + * kbase_pm_get_dvfs_action will return one of these enumerated values to + * describe the action that the DVFS system should take. + */ +enum kbase_pm_dvfs_action { + KBASE_PM_DVFS_NOP, /**< No change in clock frequency is requested */ + KBASE_PM_DVFS_CLOCK_UP, /**< The clock frequency should be increased if possible */ + KBASE_PM_DVFS_CLOCK_DOWN, /**< The clock frequency should be decreased if possible */ + KBASE_PM_DVFS_NONSENSE /* [MTK] clear state, no need to do dvfs action */ +}; + +union kbase_pm_policy_data { + struct kbasep_pm_policy_always_on always_on; + struct kbasep_pm_policy_coarse_demand coarse_demand; + struct kbasep_pm_policy_demand demand; +#if !MALI_CUSTOMER_RELEASE + struct kbasep_pm_policy_demand_always_powered demand_always_powered; + struct kbasep_pm_policy_fast_start fast_start; +#endif +}; + +union kbase_pm_ca_policy_data { + struct kbasep_pm_ca_policy_fixed fixed; +#if !MALI_CUSTOMER_RELEASE + struct kbasep_pm_ca_policy_random random; +#endif +}; + +/** Data stored per device for power management. + * + * This structure contains data for the power management framework. There is one instance of this structure per device + * in the system. + */ +struct kbase_pm_device_data { + /** The lock protecting Power Management structures accessed + * outside of IRQ. + * + * This lock must also be held whenever the GPU is being powered on or off. + */ + struct mutex lock; + + /** The policy that is currently actively controlling core availability. + * + * @note: During an IRQ, this can be NULL when the policy is being changed + * with kbase_pm_ca_set_policy(). The change is protected under + * kbase_device::pm::power_change_lock. Direct access to this from IRQ + * context must therefore check for NULL. If NULL, then + * kbase_pm_ca_set_policy() will re-issue the policy functions that would've + * been done under IRQ. + */ + const struct kbase_pm_ca_policy *ca_current_policy; + + /** The policy that is currently actively controlling the power state. + * + * @note: During an IRQ, this can be NULL when the policy is being changed + * with kbase_pm_set_policy(). The change is protected under + * kbase_device::pm::power_change_lock. Direct access to this from IRQ + * context must therefore check for NULL. If NULL, then + * kbase_pm_set_policy() will re-issue the policy functions that would've + * been done under IRQ. + */ + const struct kbase_pm_policy *pm_current_policy; + + /** Private data for current CA policy */ + union kbase_pm_ca_policy_data ca_policy_data; + + /** Private data for current PM policy */ + union kbase_pm_policy_data pm_policy_data; + + /** Flag indicating when core availability policy is transitioning cores. + * The core availability policy must set this when a change in core availability + * is occuring. + * + * power_change_lock must be held when accessing this. */ + mali_bool ca_in_transition; + + /** Waiting for reset and a queue to wait for changes */ + mali_bool reset_done; + wait_queue_head_t reset_done_wait; + + /** Wait queue for whether the l2 cache has been powered as requested */ + wait_queue_head_t l2_powered_wait; + /** State indicating whether all the l2 caches are powered. + * Non-zero indicates they're *all* powered + * Zero indicates that some (or all) are not powered */ + int l2_powered; + + /** The reference count of active contexts on this device. */ + int active_count; + /** Flag indicating suspending/suspended */ + mali_bool suspending; + /* Wait queue set when active_count == 0 */ + wait_queue_head_t zero_active_count_wait; + + /** The reference count of active gpu cycle counter users */ + int gpu_cycle_counter_requests; + /** Lock to protect gpu_cycle_counter_requests */ + spinlock_t gpu_cycle_counter_requests_lock; + + /** A bit mask identifying the shader cores that the power policy would like to be on. + * The current state of the cores may be different, but there should be transitions in progress that will + * eventually achieve this state (assuming that the policy doesn't change its mind in the mean time. + */ + u64 desired_shader_state; + /** bit mask indicating which shader cores are currently in a power-on transition */ + u64 powering_on_shader_state; + /** A bit mask identifying the tiler cores that the power policy would like to be on. + * @see kbase_pm_device_data:desired_shader_state */ + u64 desired_tiler_state; + /** bit mask indicating which tiler core are currently in a power-on transition */ + u64 powering_on_tiler_state; + + /** bit mask indicating which l2-caches are currently in a power-on transition */ + u64 powering_on_l2_state; + /** bit mask indicating which l3-caches are currently in a power-on transition */ + u64 powering_on_l3_state; + + /** Lock protecting the power state of the device. + * + * This lock must be held when accessing the shader_available_bitmap, tiler_available_bitmap, l2_available_bitmap, + * shader_inuse_bitmap and tiler_inuse_bitmap fields of kbase_device, and the ca_in_transition and shader_poweroff_pending + * fields of kbase_pm_device_data. It is also held when the hardware power registers are being written to, to ensure + * that two threads do not conflict over the power transitions that the hardware should make. + */ + spinlock_t power_change_lock; + + /** This flag is set iff the GPU is powered as requested by the + * desired_xxx_state variables */ + mali_bool gpu_in_desired_state; + /* Wait queue set when gpu_in_desired_state != 0 */ + wait_queue_head_t gpu_in_desired_state_wait; + + /** Set to true when the GPU is powered and register accesses are possible, false otherwise */ + mali_bool gpu_powered; + + /** A bit mask identifying the available shader cores that are specified via sysfs */ + u64 debug_core_mask; + + /** Set to true when instrumentation is enabled, false otherwise */ + mali_bool instr_enabled; + + mali_bool cg1_disabled; + +#ifdef CONFIG_MALI_DEBUG + /** Debug state indicating whether sufficient initialization of the driver + * has occurred to handle IRQs */ + mali_bool driver_ready_for_irqs; +#endif /* CONFIG_MALI_DEBUG */ + + /** Spinlock that must be held when: + * - writing gpu_powered + * - accessing driver_ready_for_irqs (in CONFIG_MALI_DEBUG builds) */ + spinlock_t gpu_powered_lock; + + /** Time in milliseconds between each dvfs sample */ + + u32 platform_dvfs_frequency; + + /** Structure to hold metrics for the GPU */ + + struct kbasep_pm_metrics_data metrics; + + /** Set to the number of poweroff timer ticks until the GPU is powered off */ + int gpu_poweroff_pending; + + /** Set to the number of poweroff timer ticks until shaders are powered off */ + int shader_poweroff_pending_time; + + /** Timer for powering off GPU */ + struct hrtimer gpu_poweroff_timer; + + struct workqueue_struct *gpu_poweroff_wq; + + struct work_struct gpu_poweroff_work; + + /** Period of GPU poweroff timer */ + ktime_t gpu_poweroff_time; + + /** Bit mask of shaders to be powered off on next timer callback */ + u64 shader_poweroff_pending; + + /** Set to MALI_TRUE if the poweroff timer is currently running, MALI_FALSE otherwise */ + mali_bool poweroff_timer_needed; + + int poweroff_shader_ticks; + + int poweroff_gpu_ticks; + + /** Callback when the GPU needs to be turned on. See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + * + * @return 1 if GPU state was lost, 0 otherwise + */ + int (*callback_power_on)(struct kbase_device *kbdev); + + /** Callback when the GPU may be turned off. See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + */ + void (*callback_power_off)(struct kbase_device *kbdev); + + /** Callback when a suspend occurs and the GPU needs to be turned off. + * See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + */ + void (*callback_power_suspend)(struct kbase_device *kbdev); + + /** Callback when a resume occurs and the GPU needs to be turned on. + * See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + */ + void (*callback_power_resume)(struct kbase_device *kbdev); + + /** Callback for initializing the runtime power management. + * + * @param kbdev The kbase device + * + * @return MALI_ERROR_NONE on success, else error code + */ + mali_error (*callback_power_runtime_init)(struct kbase_device *kbdev); + + /** Callback for terminating the runtime power management. + * + * @param kbdev The kbase device + */ + void (*callback_power_runtime_term)(struct kbase_device *kbdev); + + /** Callback when the GPU needs to be turned on. See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + * + * @return 1 if GPU state was lost, 0 otherwise + */ + int (*callback_power_runtime_on)(struct kbase_device *kbdev); + + /** Callback when the GPU may be turned off. See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + */ + void (*callback_power_runtime_off)(struct kbase_device *kbdev); + +}; + +/** The GPU is idle. + * + * The OS may choose to turn off idle devices + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_dev_idle(struct kbase_device *kbdev); + +/** The GPU is active. + * + * The OS should avoid opportunistically turning off the GPU while it is active + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_dev_activate(struct kbase_device *kbdev); + +/** Get details of the cores that are present in the device. + * + * This function can be called by the active power policy to return a bitmask of the cores (of a specified type) + * present in the GPU device and also a count of the number of cores. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param type The type of core (see the @ref enum kbase_pm_core_type enumeration) + * + * @return The bit mask of cores present + */ +u64 kbase_pm_get_present_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); + +/** Get details of the cores that are currently active in the device. + * + * This function can be called by the active power policy to return a bitmask of the cores (of a specified type) that + * are actively processing work (i.e. turned on *and* busy). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param type The type of core (see the @ref enum kbase_pm_core_type enumeration) + * + * @return The bit mask of active cores + */ +u64 kbase_pm_get_active_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); + +/** Get details of the cores that are currently transitioning between power states. + * + * This function can be called by the active power policy to return a bitmask of the cores (of a specified type) that + * are currently transitioning between power states. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param type The type of core (see the @ref enum kbase_pm_core_type enumeration) + * + * @return The bit mask of transitioning cores + */ +u64 kbase_pm_get_trans_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); + +/** Get details of the cores that are currently powered and ready for jobs. + * + * This function can be called by the active power policy to return a bitmask of the cores (of a specified type) that + * are powered and ready for jobs (they may or may not be currently executing jobs). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param type The type of core (see the @ref enum kbase_pm_core_type enumeration) + * + * @return The bit mask of ready cores + */ +u64 kbase_pm_get_ready_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); + +/** Turn the clock for the device on, and enable device interrupts. + * + * This function can be used by a power policy to turn the clock for the GPU on. It should be modified during + * integration to perform the necessary actions to ensure that the GPU is fully powered and clocked. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param is_resume MALI_TRUE if clock on due to resume after suspend, + * MALI_FALSE otherwise + */ +void kbase_pm_clock_on(struct kbase_device *kbdev, mali_bool is_resume); + +/** Disable device interrupts, and turn the clock for the device off. + * + * This function can be used by a power policy to turn the clock for the GPU off. It should be modified during + * integration to perform the necessary actions to turn the clock off (if this is possible in the integration). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param is_suspend MALI_TRUE if clock off due to suspend, MALI_FALSE otherwise + */ +void kbase_pm_clock_off(struct kbase_device *kbdev, mali_bool is_suspend); + +/** Enable interrupts on the device. + * + * Interrupts are also enabled after a call to kbase_pm_clock_on(). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_enable_interrupts(struct kbase_device *kbdev); + +/** Disable interrupts on the device. + * + * This prevents delivery of Power Management interrupts to the CPU so that + * kbase_pm_check_transitions_nolock() will not be called from the IRQ handler + * until @ref kbase_pm_enable_interrupts or kbase_pm_clock_on() is called. + * + * Interrupts are also disabled after a call to kbase_pm_clock_off(). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_disable_interrupts(struct kbase_device *kbdev); + +/** Initialize the hardware + * + * This function checks the GPU ID register to ensure that the GPU is supported by the driver and performs a reset on + * the device so that it is in a known state before the device is used. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param enable_irqs When set to MALI_TRUE gpu irqs will be enabled after this call, else + * they will be left disabled. + * + * @return MALI_ERROR_NONE if the device is supported and successfully reset. + */ +mali_error kbase_pm_init_hw(struct kbase_device *kbdev, mali_bool enable_irqs); + +/** The GPU has been reset successfully. + * + * This function must be called by the GPU interrupt handler when the RESET_COMPLETED bit is set. It signals to the + * power management initialization code that the GPU has been successfully reset. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_reset_done(struct kbase_device *kbdev); + +/** Increment the count of active contexts. + * + * This function should be called when a context is about to submit a job. It informs the active power policy that the + * GPU is going to be in use shortly and the policy is expected to start turning on the GPU. + * + * This function will block until the GPU is available. + * + * This function ASSERTS if a suspend is occuring/has occurred whilst this is + * in use. Use kbase_pm_contect_active_unless_suspending() instead. + * + * @note a Suspend is only visible to Kernel threads; user-space threads in a + * syscall cannot witness a suspend, because they are frozen before the suspend + * begins. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_context_active(struct kbase_device *kbdev); + + +/** Handler codes for doing kbase_pm_context_active_handle_suspend() */ +enum kbase_pm_suspend_handler { + /** A suspend is not expected/not possible - this is the same as + * kbase_pm_context_active() */ + KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE, + /** If we're suspending, fail and don't increase the active count */ + KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE, + /** If we're suspending, succeed and allow the active count to increase iff + * it didn't go from 0->1 (i.e., we didn't re-activate the GPU). + * + * This should only be used when there is a bounded time on the activation + * (e.g. guarantee it's going to be idled very soon after) */ + KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE +}; + +/** Suspend 'safe' variant of kbase_pm_context_active() + * + * If a suspend is in progress, this allows for various different ways of + * handling the suspend. Refer to @ref enum kbase_pm_suspend_handler for details. + * + * We returns a status code indicating whether we're allowed to keep the GPU + * active during the suspend, depending on the handler code. If the status code + * indicates a failure, the caller must abort whatever operation it was + * attempting, and potentially queue it up for after the OS has resumed. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param suspend_handler The handler code for how to handle a suspend that might occur + * @return zero Indicates success + * @return non-zero Indicates failure due to the system being suspending/suspended. + */ +int kbase_pm_context_active_handle_suspend(struct kbase_device *kbdev, enum kbase_pm_suspend_handler suspend_handler); + +/** Decrement the reference count of active contexts. + * + * This function should be called when a context becomes idle. After this call the GPU may be turned off by the power + * policy so the calling code should ensure that it does not access the GPU's registers. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_context_idle(struct kbase_device *kbdev); + +/** Check if there are any power transitions to make, and if so start them. + * + * This function will check the desired_xx_state members of struct kbase_pm_device_data and the actual status of the + * hardware to see if any power transitions can be made at this time to make the hardware state closer to the state + * desired by the power policy. + * + * The return value can be used to check whether all the desired cores are + * available, and so whether it's worth submitting a job (e.g. from a Power + * Management IRQ). + * + * Note that this still returns MALI_TRUE when desired_xx_state has no + * cores. That is: of the no cores desired, none were unavailable. In + * this case, the caller may still need to try submitting jobs. This is because + * the Core Availability Policy might have taken us to an intermediate state + * where no cores are powered, before powering on more cores (e.g. for core + * rotation) + * + * The caller must hold kbase_device::pm::power_change_lock + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @return non-zero when all desired cores are available. That is, + * it's worthwhile for the caller to submit a job. + * @return MALI_FALSE otherwise + */ +mali_bool kbase_pm_check_transitions_nolock(struct kbase_device *kbdev); + +/** Synchronous and locking variant of kbase_pm_check_transitions_nolock() + * + * On returning, the desired state at the time of the call will have been met. + * + * @note There is nothing to stop the core being switched off by calls to + * kbase_pm_release_cores() or kbase_pm_unrequest_cores(). Therefore, the + * caller must have already made a call to + * kbase_pm_request_cores()/kbase_pm_request_cores_sync() previously. + * + * The usual use-case for this is to ensure cores are 'READY' after performing + * a GPU Reset. + * + * Unlike kbase_pm_check_transitions_nolock(), the caller must not hold + * kbase_device::pm::power_change_lock, because this function will take that + * lock itself. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_check_transitions_sync(struct kbase_device *kbdev); + +/** Variant of kbase_pm_update_cores_state() where the caller must hold + * kbase_device::pm::power_change_lock + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev); + +/** Update the desired state of shader cores from the Power Policy, and begin + * any power transitions. + * + * This function will update the desired_xx_state members of + * struct kbase_pm_device_data by calling into the current Power Policy. It will then + * begin power transitions to make the hardware acheive the desired shader core + * state. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_pm_update_cores_state(struct kbase_device *kbdev); + +/** Cancel any pending requests to power off the GPU and/or shader cores. + * + * This should be called by any functions which directly power off the GPU. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_pm_cancel_deferred_poweroff(struct kbase_device *kbdev); + +/** Read the bitmasks of present cores. + * + * This information is cached to avoid having to perform register reads whenever the information is required. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_read_present_cores(struct kbase_device *kbdev); + +/** Initialize the metrics gathering framework. + * + * This must be called before other metric gathering APIs are called. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE on success, MALI_ERROR_FUNCTION_FAILED on error + */ +mali_error kbasep_pm_metrics_init(struct kbase_device *kbdev); + +/** Terminate the metrics gathering framework. + * + * This must be called when metric gathering is no longer required. It is an error to call any metrics gathering + * function (other than kbasep_pm_metrics_init) after calling this function. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_metrics_term(struct kbase_device *kbdev); + +/** Record state of jobs currently active on GPU. + * + * This function record time spent executing jobs split per GL and CL + * contexts, per core group (only CL jobs). + * + * @param kbdev The kbase device structure for the device + * (must be a valid pointer) + */ +void kbasep_pm_record_job_status(struct kbase_device *kbdev); + +/** Record that the GPU is active. + * + * This records that the GPU is now active. The previous GPU state must have been idle, the function will assert if + * this is not true in a debug build. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_record_gpu_active(struct kbase_device *kbdev); + +/** Record that the GPU is idle. + * + * This records that the GPU is now idle. The previous GPU state must have been active, the function will assert if + * this is not true in a debug build. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_record_gpu_idle(struct kbase_device *kbdev); + +/** Function to be called by the frame buffer driver to update the vsync metric. + * + * This function should be called by the frame buffer driver to update whether the system is hitting the vsync target + * or not. buffer_updated should be true if the vsync corresponded with a new frame being displayed, otherwise it + * should be false. This function does not need to be called every vsync, but only when the value of buffer_updated + * differs from a previous call. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param buffer_updated True if the buffer has been updated on this VSync, false otherwise + */ +void kbase_pm_report_vsync(struct kbase_device *kbdev, int buffer_updated); + +/** Configure the frame buffer device to set the vsync callback. + * + * This function should do whatever is necessary for this integration to ensure that kbase_pm_report_vsync is + * called appropriately. + * + * This function will need porting as part of the integration for a device. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_register_vsync_callback(struct kbase_device *kbdev); + +/** Free any resources that kbase_pm_register_vsync_callback allocated. + * + * This function should perform any cleanup required from the call to kbase_pm_register_vsync_callback. + * No call backs should occur after this function has returned. + * + * This function will need porting as part of the integration for a device. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_unregister_vsync_callback(struct kbase_device *kbdev); + +/** Determine whether the DVFS system should change the clock speed of the GPU. + * + * This function should be called regularly by the DVFS system to check whether the clock speed of the GPU needs + * updating. It will return one of three enumerated values of kbase_pm_dvfs_action: + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @retval KBASE_PM_DVFS_NOP The clock does not need changing + * @retval KBASE_PM_DVFS_CLOCK_UP, The clock frequency should be increased if possible. + * @retval KBASE_PM_DVFS_CLOCK_DOWN The clock frequency should be decreased if possible. + */ +enum kbase_pm_dvfs_action kbase_pm_get_dvfs_action(struct kbase_device *kbdev); + +/** Mark that the GPU cycle counter is needed, if the caller is the first caller + * then the GPU cycle counters will be enabled along with the l2 cache + * + * The GPU must be powered when calling this function (i.e. @ref kbase_pm_context_active must have been called). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_gpu_cycle_counter(struct kbase_device *kbdev); + +/** This is a version of the above function (@ref kbase_pm_request_gpu_cycle_counter) suitable for being + * called when the l2 cache is known to be on and assured to be on until the subsequent call of + * kbase_pm_release_gpu_cycle_counter such as when a job is submitted. + * It does not sleep and can be called from atomic functions. + * + * The GPU must be powered when calling this function (i.e. @ref kbase_pm_context_active must have been called). + * and the l2 cache must be powered on + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_gpu_cycle_counter_l2_is_on(struct kbase_device *kbdev); + +/** Mark that the GPU cycle counter is no longer in use, if the caller is the last + * caller then the GPU cycle counters will be disabled. A request must have been made + * before a call to this. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + +void kbase_pm_release_gpu_cycle_counter(struct kbase_device *kbdev); + +/** Enables access to the GPU registers before power management has powered up the GPU + * with kbase_pm_powerup(). + * + * Access to registers should be done using kbase_os_reg_read/write() at this stage, + * not kbase_reg_read/write(). + * + * This results in the power management callbacks provided in the driver configuration + * to get called to turn on power and/or clocks to the GPU. + * See @ref kbase_pm_callback_conf. + * + * This should only be used before power management is powered up with kbase_pm_powerup() + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_register_access_enable(struct kbase_device *kbdev); + +/** Disables access to the GPU registers enabled earlier by a call to + * kbase_pm_register_access_enable(). + * + * This results in the power management callbacks provided in the driver configuration + * to get called to turn off power and/or clocks to the GPU. + * See @ref kbase_pm_callback_conf + * + * This should only be used before power management is powered up with kbase_pm_powerup() + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_register_access_disable(struct kbase_device *kbdev); + +/** + * Suspend the GPU and prevent any further register accesses to it from Kernel + * threads. + * + * This is called in response to an OS suspend event, and calls into the various + * kbase components to complete the suspend. + * + * @note the mechanisms used here rely on all user-space threads being frozen + * by the OS before we suspend. Otherwise, an IOCTL could occur that powers up + * the GPU e.g. via atom submission. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_suspend(struct kbase_device *kbdev); + +/** + * Resume the GPU, allow register accesses to it, and resume running atoms on + * the GPU. + * + * This is called in response to an OS resume event, and calls into the various + * kbase components to complete the resume. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_resume(struct kbase_device *kbdev); + +/* NOTE: kbase_pm_is_suspending is in mali_kbase.h, because it is an inline function */ + +/** + * Check if the power management metrics collection is active. + * + * Note that this returns if the power management metrics collection was + * active at the time of calling, it is possible that after the call the metrics + * collection enable may have changed state. + * + * The caller must handle the consequence that the state may have changed. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @return MALI_TRUE if metrics collection was active else MALI_FALSE. + */ + +mali_bool kbase_pm_metrics_is_active(struct kbase_device *kbdev); + +/** + * Power on the GPU, and any cores that are requested. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param is_resume MALI_TRUE if power on due to resume after suspend, + * MALI_FALSE otherwise + */ +void kbase_pm_do_poweron(struct kbase_device *kbdev, mali_bool is_resume); + +/** + * Power off the GPU, and any cores that have been requested. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param is_suspend MALI_TRUE if power off due to suspend, + * MALI_FALSE otherwise + */ +void kbase_pm_do_poweroff(struct kbase_device *kbdev, mali_bool is_suspend); + +#ifdef CONFIG_PM_DEVFREQ +void kbase_pm_get_dvfs_utilisation(struct kbase_device *kbdev, + unsigned long *total, unsigned long *busy, bool reset); +#endif + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +/** + * Function provided by platform specific code when DVFS is enabled to allow + * the power management metrics system to report utilisation. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param utilisation The current calculated utilisation by the metrics system. + * @param util_gl_share The current calculated gl share of utilisation. + * @param util_cl_share The current calculated cl share of utilisation per core group. + * @return Returns 0 on failure and non zero on success. + */ + +int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, + u32 util_gl_share, u32 util_cl_share[2]); +#endif + +void proc_mali_register(void); +void proc_mali_unregister(void); + +u32 kbasep_get_gl_utilization(void); +u32 kbasep_get_cl_js0_utilization(void); +u32 kbasep_get_cl_js1_utilization(void); + +enum kbase_pm_dvfs_action mtk_get_dvfs_action(void); + +void mtk_clear_dvfs_action(void); +int mtk_get_dvfs_enabled(void); +unsigned int mtk_get_current_gpu_platform_id(void); + +void mtk_gpu_input_boost_CB(unsigned int ui32BoostFreqID); +void mtk_gpu_power_limit_CB(unsigned int ui32LimitFreqID); + +int mtk_get_input_boost_enabled(void); + +void mtk_kbase_boost_gpu_freq(void); + +void mtk_kbase_custom_boost_gpu_freq(unsigned int ui32FreqLevel); +void mtk_kbase_ged_bottom_gpu_freq(unsigned int ui32FreqLevel); +unsigned int mtk_kbase_custom_get_gpu_freq_level_count(void); + +int mtk_get_dvfs_freq(void); +int mtk_get_dvfs_threshold_max(void); +int mtk_get_dvfs_threshold_min(void); +int mtk_get_dvfs_deferred_count(void); + +void mtk_get_touch_boost_flag(int *touch_boost_flag, int *touch_boost_id); +void mtk_set_touch_boost_flag(int boost_id); +void mtk_clear_touch_boost_flag(void); +void mtk_set_vgpu_power_on_flag(int power_on_id); +int mtk_set_mt_gpufreq_target(int freq_id); +void mtk_get_power_on_freq_flag(int *power_on_freq_flag, int *power_on_freq_id); +void mtk_set_power_on_freq_flag(int power_on_freq_id); +void mtk_clear_power_on_freq_flag(void); + +struct kbase_device *MaliGetMaliData(void); + +void MTKCalGpuUtilization(unsigned int* pui32Loading , unsigned int* pui32Block,unsigned int* pui32Idle); +void mtk_gpu_dvfs_commit(unsigned long ui32NewFreqID, GED_DVFS_COMMIT_TYPE eCommitTyp, int* pbCommited); +unsigned int MTKCalPowerIndex(void); +int mtk_get_vgpu_power_on_flag(void); +#endif /* _KBASE_PM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.c new file mode 100644 index 0000000000000000000000000000000000000000..4d3878b50937fc4cea2d80da64c5ccdebb98f0e7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.c @@ -0,0 +1,64 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_always_on.c + * "Always on" power management policy + */ + +#include +#include + +#if KBASE_PM_EN +static u64 always_on_get_core_mask(struct kbase_device *kbdev) +{ + return kbdev->shader_present_bitmap; +} + +static mali_bool always_on_get_core_active(struct kbase_device *kbdev) +{ + return MALI_TRUE; +} + +static void always_on_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void always_on_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/** The @ref struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback and name. + */ +const struct kbase_pm_policy kbase_pm_always_on_policy_ops = { + "always_on", /* name */ + always_on_init, /* init */ + always_on_term, /* term */ + always_on_get_core_mask, /* get_core_mask */ + always_on_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_ALWAYS_ON, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_always_on_policy_ops) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.h new file mode 100644 index 0000000000000000000000000000000000000000..a3858045bd0c235bab3a49fece49c50fa2ca04f2 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.h @@ -0,0 +1,68 @@ + +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_always_on.h + * "Always on" power management policy + */ + +#ifndef MALI_KBASE_PM_ALWAYS_ON_H +#define MALI_KBASE_PM_ALWAYS_ON_H + +/** + * The "Always on" power management policy has the following + * characteristics: + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * - All Shader Cores are powered up, regardless of whether or not they will + * be needed later. + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * - All Shader Cores are kept powered, regardless of whether or not they will + * be needed + * - When KBase indicates that the GPU need not be powered: + * - The Shader Cores are kept powered, regardless of whether or not they will + * be needed. The GPU itself is also kept powered, even though it is not + * needed. + * + * This policy is automatically overridden during system suspend: the desired + * core state is ignored, and the cores are forced off regardless of what the + * policy requests. After resuming from suspend, new changes to the desired + * core state made by the policy are honored. + * + * @note: + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * Private structure for policy instance data. + * + * This contains data that is private to the particular power policy that is active. + */ +typedef struct kbasep_pm_policy_always_on { + /** No state needed - just have a dummy variable here */ + int dummy; +} kbasep_pm_policy_always_on; + +#endif /* MALI_KBASE_PM_ALWAYS_ON_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.c new file mode 100644 index 0000000000000000000000000000000000000000..9d5fb94c8218dd619b97be195e700828ebc22e0e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.c @@ -0,0 +1,173 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_ca.c + * Base kernel core availability APIs + */ + +#include +#include +#if KBASE_PM_EN +extern const struct kbase_pm_ca_policy kbase_pm_ca_fixed_policy_ops; +#if !MALI_CUSTOMER_RELEASE +extern const struct kbase_pm_ca_policy kbase_pm_ca_random_policy_ops; +#endif + +static const struct kbase_pm_ca_policy *const policy_list[] = { + &kbase_pm_ca_fixed_policy_ops, +#if !MALI_CUSTOMER_RELEASE + &kbase_pm_ca_random_policy_ops +#endif +}; + +/** The number of policies available in the system. + * This is derived from the number of functions listed in policy_get_functions. + */ +#define POLICY_COUNT (sizeof(policy_list)/sizeof(*policy_list)) + +mali_error kbase_pm_ca_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + kbdev->pm.ca_current_policy = policy_list[0]; + + kbdev->pm.ca_current_policy->init(kbdev); + + return MALI_ERROR_NONE; +} + +void kbase_pm_ca_term(struct kbase_device *kbdev) +{ + kbdev->pm.ca_current_policy->term(kbdev); +} + +int kbase_pm_ca_list_policies(const struct kbase_pm_ca_policy * const **list) +{ + if (!list) + return POLICY_COUNT; + + *list = policy_list; + + return POLICY_COUNT; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_list_policies) + +const struct kbase_pm_ca_policy *kbase_pm_ca_get_policy(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return kbdev->pm.ca_current_policy; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_get_policy) + +void kbase_pm_ca_set_policy(struct kbase_device *kbdev, const struct kbase_pm_ca_policy *new_policy) +{ + const struct kbase_pm_ca_policy *old_policy; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(new_policy != NULL); + + KBASE_TRACE_ADD(kbdev, PM_CA_SET_POLICY, NULL, NULL, 0u, new_policy->id); + + /* During a policy change we pretend the GPU is active */ + /* A suspend won't happen here, because we're in a syscall from a userspace thread */ + kbase_pm_context_active(kbdev); + + mutex_lock(&kbdev->pm.lock); + + /* Remove the policy to prevent IRQ handlers from working on it */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + old_policy = kbdev->pm.ca_current_policy; + kbdev->pm.ca_current_policy = NULL; + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + if (old_policy->term) + old_policy->term(kbdev); + + if (new_policy->init) + new_policy->init(kbdev); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbdev->pm.ca_current_policy = new_policy; + + /* If any core power state changes were previously attempted, but couldn't + * be made because the policy was changing (current_policy was NULL), then + * re-try them here. */ + kbase_pm_update_cores_state_nolock(kbdev); + + kbdev->pm.ca_current_policy->update_core_status(kbdev, kbdev->shader_ready_bitmap, kbdev->shader_transitioning_bitmap); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + mutex_unlock(&kbdev->pm.lock); + + /* Now the policy change is finished, we release our fake context active reference */ + kbase_pm_context_idle(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_set_policy) + +u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.power_change_lock); + + /* All cores must be enabled when instrumentation is in use */ + if (kbdev->pm.instr_enabled == MALI_TRUE) + return kbdev->shader_present_bitmap & kbdev->pm.debug_core_mask; + + if (kbdev->pm.ca_current_policy == NULL) + return kbdev->shader_present_bitmap & kbdev->pm.debug_core_mask; + + return kbdev->pm.ca_current_policy->get_core_mask(kbdev) & kbdev->pm.debug_core_mask; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_get_core_mask) + +void kbase_pm_ca_update_core_status(struct kbase_device *kbdev, u64 cores_ready, u64 cores_transitioning) +{ + lockdep_assert_held(&kbdev->pm.power_change_lock); + + if (kbdev->pm.ca_current_policy != NULL) + kbdev->pm.ca_current_policy->update_core_status(kbdev, cores_ready, cores_transitioning); +} + +void kbase_pm_ca_instr_enable(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbdev->pm.instr_enabled = MALI_TRUE; + + kbase_pm_update_cores_state_nolock(kbdev); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +void kbase_pm_ca_instr_disable(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbdev->pm.instr_enabled = MALI_FALSE; + + kbase_pm_update_cores_state_nolock(kbdev); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.h new file mode 100644 index 0000000000000000000000000000000000000000..e073470e085501e1ae4531f9b36a8319cd5c2780 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.h @@ -0,0 +1,170 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_ca.h + * Base kernel core availability APIs + */ + +#ifndef _KBASE_PM_CA_H_ +#define _KBASE_PM_CA_H_ + +enum kbase_pm_ca_policy_id { + KBASE_PM_CA_POLICY_ID_FIXED = 1, + KBASE_PM_CA_POLICY_ID_RANDOM +}; + +typedef u32 kbase_pm_ca_policy_flags; + +/** Core availability policy structure. + * + * Each core availability policy exposes a (static) instance of this structure which contains function pointers to the + * policy's methods. + */ +struct kbase_pm_ca_policy { + /** The name of this policy */ + char *name; + + /** Function called when the policy is selected + * + * This should initialize the kbdev->pm.ca_policy_data structure. It should not attempt + * to make any changes to hardware state. + * + * It is undefined what state the cores are in when the function is called. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + void (*init)(struct kbase_device *kbdev); + + /** Function called when the policy is unselected. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + void (*term)(struct kbase_device *kbdev); + + /** Function called to get the current shader core availability mask + * + * When a change in core availability is occuring, the policy must set kbdev->pm.ca_in_transition + * to MALI_TRUE. This is to indicate that reporting changes in power state cannot be optimized out, + * even if kbdev->pm.desired_shader_state remains unchanged. This must be done by any functions + * internal to the Core Availability Policy that change the return value of + * kbase_pm_ca_policy::get_core_mask. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The current core availability mask */ + u64 (*get_core_mask)(struct kbase_device *kbdev); + + /** Function called to update the current core status + * + * If none of the cores in core group 0 are ready or transitioning, then the policy must + * ensure that the next call to get_core_mask does not return 0 for all cores in core group + * 0. It is an error to disable core group 0 through the core availability policy. + * + * When a change in core availability has finished, the policy must set kbdev->pm.ca_in_transition + * to MALI_FALSE. This is to indicate that changes in power state can once again be optimized out + * when kbdev->pm.desired_shader_state is unchanged. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param cores_ready The mask of cores currently powered and ready to run jobs + * @param cores_transitioning The mask of cores currently transitioning power state */ + void (*update_core_status)(struct kbase_device *kbdev, u64 cores_ready, u64 cores_transitioning); + + /** Field indicating flags for this policy */ + kbase_pm_ca_policy_flags flags; + + /** Field indicating an ID for this policy. This is not necessarily the + * same as its index in the list returned by kbase_pm_list_policies(). + * It is used purely for debugging. */ + enum kbase_pm_ca_policy_id id; +}; + +/** Initialize core availability framework + * + * Must be called before calling any other core availability function + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE if the core availability framework was successfully initialized. + */ +mali_error kbase_pm_ca_init(struct kbase_device *kbdev); + +/** Terminate core availability framework + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_ca_term(struct kbase_device *kbdev); + +/** Return mask of currently available shaders cores + * Calls into the core availability policy + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The bit mask of available cores + */ +u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev); + +/** Update core availability policy with current core power status + * Calls into the core availability policy + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param cores_ready The bit mask of cores ready for job submission + * @param cores_transitioning The bit mask of cores that are transitioning power state + */ +void kbase_pm_ca_update_core_status(struct kbase_device *kbdev, u64 cores_ready, u64 cores_transitioning); + +/** Enable override for instrumentation + * + * This overrides the output of the core availability policy, ensuring that all cores are available + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_ca_instr_enable(struct kbase_device *kbdev); + +/** Disable override for instrumentation + * + * This disables any previously enabled override, and resumes normal policy functionality + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_ca_instr_disable(struct kbase_device *kbdev); + +/** Get the current policy. + * Returns the policy that is currently active. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The current policy + */ +const struct kbase_pm_ca_policy *kbase_pm_ca_get_policy(struct kbase_device *kbdev); + +/** Change the policy to the one specified. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param policy The policy to change to (valid pointer returned from @ref kbase_pm_ca_list_policies) + */ +void kbase_pm_ca_set_policy(struct kbase_device *kbdev, const struct kbase_pm_ca_policy *policy); + +/** Retrieve a static list of the available policies. + * @param[out] policies An array pointer to take the list of policies. This may be NULL. + * The contents of this array must not be modified. + * + * @return The number of policies + */ +int kbase_pm_ca_list_policies(const struct kbase_pm_ca_policy * const **policies); + +#endif /* _KBASE_PM_CA_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.c new file mode 100644 index 0000000000000000000000000000000000000000..d81cdbd42e7cf0d0fd89aca6f78c13724de00996 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.c @@ -0,0 +1,63 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_ca_fixed.c + * A power policy implementing fixed core availability + */ + +#include +#include +#if KBASE_PM_EN +static void fixed_init(struct kbase_device *kbdev) +{ + kbdev->pm.ca_in_transition = MALI_FALSE; +} + +static void fixed_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static u64 fixed_get_core_mask(struct kbase_device *kbdev) +{ + return kbdev->shader_present_bitmap; +} + +static void fixed_update_core_status(struct kbase_device *kbdev, u64 cores_ready, u64 cores_transitioning) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(cores_ready); + CSTD_UNUSED(cores_transitioning); +} + +/** The @ref struct kbase_pm_policy structure for the fixed power policy. + * + * This is the static structure that defines the fixed power policy's callback and name. + */ +const struct kbase_pm_ca_policy kbase_pm_ca_fixed_policy_ops = { + "fixed", /* name */ + fixed_init, /* init */ + fixed_term, /* term */ + fixed_get_core_mask, /* get_core_mask */ + fixed_update_core_status, /* update_core_status */ + 0u, /* flags */ + KBASE_PM_CA_POLICY_ID_FIXED, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_ca_fixed_policy_ops) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.h new file mode 100644 index 0000000000000000000000000000000000000000..9d95e07a2d524e266ae3c794ce48a2c7c8b75a56 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.h @@ -0,0 +1,37 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_ca_fixed.h + * A power policy implementing fixed core availability + */ + +#ifndef MALI_KBASE_PM_CA_FIXED_H +#define MALI_KBASE_PM_CA_FIXED_H + +/** + * Private structure for policy instance data. + * + * This contains data that is private to the particular power policy that is active. + */ +typedef struct kbasep_pm_ca_policy_fixed { + /** No state needed - just have a dummy variable here */ + int dummy; +} kbasep_pm_ca_policy_fixed; + +#endif /* MALI_KBASE_PM_CA_FIXED_H */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.c new file mode 100644 index 0000000000000000000000000000000000000000..8093e32e4dcd29a02ef582cac7005223a074631c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.c @@ -0,0 +1,70 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_coarse_demand.c + * "Coarse Demand" power management policy + */ + +#include +#include + +#if KBASE_PM_EN +static u64 coarse_demand_get_core_mask(struct kbase_device *kbdev) +{ + if (kbdev->pm.active_count == 0) + return 0; + + return kbdev->shader_present_bitmap; +} + +static mali_bool coarse_demand_get_core_active(struct kbase_device *kbdev) +{ + if (kbdev->pm.active_count == 0) + return MALI_FALSE; + + return MALI_TRUE; +} + +static void coarse_demand_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void coarse_demand_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/** The @ref struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback and name. + */ +const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops = { + "coarse_demand", /* name */ + coarse_demand_init, /* init */ + coarse_demand_term, /* term */ + coarse_demand_get_core_mask, /* get_core_mask */ + coarse_demand_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_COARSE_DEMAND, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_coarse_demand_policy_ops) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.h new file mode 100644 index 0000000000000000000000000000000000000000..afe3fc93b42deaa36d77e843c07d4458f47c2264 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.h @@ -0,0 +1,60 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_coarse_demand.h + * "Coarse Demand" power management policy + */ + +#ifndef MALI_KBASE_PM_COARSE_DEMAND_H +#define MALI_KBASE_PM_COARSE_DEMAND_H + +/** + * The "Coarse" demand power management policy has the following + * characteristics: + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * - All Shader Cores are powered up, regardless of whether or not they will + * be needed later. + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * - All Shader Cores are kept powered, regardless of whether or not they will + * be needed + * - When KBase indicates that the GPU need not be powered: + * - The Shader Cores are powered off, and the GPU itself is powered off too. + * + * @note: + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * Private structure for policy instance data. + * + * This contains data that is private to the particular power policy that is active. + */ +typedef struct kbasep_pm_policy_coarse_demand { + /** No state needed - just have a dummy variable here */ + int dummy; +} kbasep_pm_policy_coarse_demand; + +#endif /* MALI_KBASE_PM_COARSE_DEMAND_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.c new file mode 100644 index 0000000000000000000000000000000000000000..0e322924c7ef14eccb6761dfc23d1d2a35651ddd --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.c @@ -0,0 +1,73 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_demand.c + * A simple demand based power management policy + */ + +#include +#include + +#if KBASE_PM_EN + +static u64 demand_get_core_mask(struct kbase_device *kbdev) +{ + u64 desired = kbdev->shader_needed_bitmap | kbdev->shader_inuse_bitmap; + + if (0 == kbdev->pm.active_count) + return 0; + + return desired; +} + +static mali_bool demand_get_core_active(struct kbase_device *kbdev) +{ + if (0 == kbdev->pm.active_count) + return MALI_FALSE; + + return MALI_TRUE; +} + +static void demand_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void demand_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/** The @ref struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback and name. + */ +const struct kbase_pm_policy kbase_pm_demand_policy_ops = { + "demand", /* name */ + demand_init, /* init */ + demand_term, /* term */ + demand_get_core_mask, /* get_core_mask */ + demand_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_DEMAND, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_demand_policy_ops) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.h new file mode 100644 index 0000000000000000000000000000000000000000..8579181d7dd0909d8cf85cda42ee7ea9630e7c27 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.h @@ -0,0 +1,57 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_demand.h + * A simple demand based power management policy + */ + +#ifndef MALI_KBASE_PM_DEMAND_H +#define MALI_KBASE_PM_DEMAND_H + +/** + * The demand power management policy has the following characteristics: + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * - The Shader Cores are not powered up + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * - Only those Shader Cores are powered up + * - When KBase indicates that the GPU need not be powered: + * - The Shader Cores are powered off, and the GPU itself is powered off too. + * + * @note: + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * Private structure for policy instance data. + * + * This contains data that is private to the particular power policy that is active. + */ +typedef struct kbasep_pm_policy_demand { + /** No state needed - just have a dummy variable here */ + int dummy; +} kbasep_pm_policy_demand; + +#endif /* MALI_KBASE_PM_DEMAND_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_driver.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_driver.c new file mode 100644 index 0000000000000000000000000000000000000000..32b24b104b48bc25e6da91d19160da4d19142dad --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_driver.c @@ -0,0 +1,1013 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_driver.c + * Base kernel Power Management hardware control + */ + +#include +#include +#include +#include +#include +#include + +#if KBASE_PM_EN + +#if MALI_MOCK_TEST +#define MOCKABLE(function) function##_original +#else +#define MOCKABLE(function) function +#endif /* MALI_MOCK_TEST */ + +/** Actions that can be performed on a core. + * + * This enumeration is private to the file. Its values are set to allow @ref core_type_to_reg function, + * which decodes this enumeration, to be simpler and more efficient. + */ +enum kbasep_pm_action { + ACTION_PRESENT = 0, + ACTION_READY = (SHADER_READY_LO - SHADER_PRESENT_LO), + ACTION_PWRON = (SHADER_PWRON_LO - SHADER_PRESENT_LO), + ACTION_PWROFF = (SHADER_PWROFF_LO - SHADER_PRESENT_LO), + ACTION_PWRTRANS = (SHADER_PWRTRANS_LO - SHADER_PRESENT_LO), + ACTION_PWRACTIVE = (SHADER_PWRACTIVE_LO - SHADER_PRESENT_LO) +}; + +/** Decode a core type and action to a register. + * + * Given a core type (defined by @ref kbase_pm_core_type) and an action (defined by @ref kbasep_pm_action) this + * function will return the register offset that will perform the action on the core type. The register returned is + * the \c _LO register and an offset must be applied to use the \c _HI register. + * + * @param core_type The type of core + * @param action The type of action + * + * @return The register offset of the \c _LO register that performs an action of type \c action on a core of type \c + * core_type. + */ +static u32 core_type_to_reg(enum kbase_pm_core_type core_type, enum kbasep_pm_action action) +{ + return (u32)core_type + (u32)action; +} + +/** Invokes an action on a core set + * + * This function performs the action given by \c action on a set of cores of a type given by \c core_type. It is a + * static function used by @ref kbase_pm_transition_core_type + * + * @param kbdev The kbase device structure of the device + * @param core_type The type of core that the action should be performed on + * @param cores A bit mask of cores to perform the action on (low 32 bits) + * @param action The action to perform on the cores + */ +STATIC void kbase_pm_invoke(struct kbase_device *kbdev, enum kbase_pm_core_type core_type, u64 cores, enum kbasep_pm_action action) +{ + u32 reg; + u32 lo = cores & 0xFFFFFFFF; + u32 hi = (cores >> 32) & 0xFFFFFFFF; + + lockdep_assert_held(&kbdev->pm.power_change_lock); + + reg = core_type_to_reg(core_type, action); + + KBASE_DEBUG_ASSERT(reg); +#ifdef CONFIG_MALI_GATOR_SUPPORT + if (cores) { + if (action == ACTION_PWRON) + kbase_trace_mali_pm_power_on(core_type, cores); + else if (action == ACTION_PWROFF) + kbase_trace_mali_pm_power_off(core_type, cores); + } +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + /* Tracing */ + if (cores) { + if (action == ACTION_PWRON) + switch (core_type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_PWRON, NULL, NULL, 0u, lo); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_PWRON_TILER, NULL, NULL, 0u, lo); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_PWRON_L2, NULL, NULL, 0u, lo); + break; + default: + /* L3 not handled */ + break; + } + else if (action == ACTION_PWROFF) + switch (core_type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_PWROFF, NULL, NULL, 0u, lo); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_PWROFF_TILER, NULL, NULL, 0u, lo); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_PWROFF_L2, NULL, NULL, 0u, lo); + break; + default: + /* L3 not handled */ + break; + } + } + + if (lo != 0) + kbase_reg_write(kbdev, GPU_CONTROL_REG(reg), lo, NULL); + + if (hi != 0) + kbase_reg_write(kbdev, GPU_CONTROL_REG(reg + 4), hi, NULL); +} + +/** Get information about a core set + * + * This function gets information (chosen by \c action) about a set of cores of a type given by \c core_type. It is a + * static function used by @ref kbase_pm_get_present_cores, @ref kbase_pm_get_active_cores, @ref + * kbase_pm_get_trans_cores and @ref kbase_pm_get_ready_cores. + * + * @param kbdev The kbase device structure of the device + * @param core_type The type of core that the should be queried + * @param action The property of the cores to query + * + * @return A bit mask specifying the state of the cores + */ +static u64 kbase_pm_get_state(struct kbase_device *kbdev, enum kbase_pm_core_type core_type, enum kbasep_pm_action action) +{ + u32 reg; + u32 lo, hi; + + reg = core_type_to_reg(core_type, action); + + KBASE_DEBUG_ASSERT(reg); + + lo = kbase_reg_read(kbdev, GPU_CONTROL_REG(reg), NULL); + hi = kbase_reg_read(kbdev, GPU_CONTROL_REG(reg + 4), NULL); + + return (((u64) hi) << 32) | ((u64) lo); +} + +void kbasep_pm_read_present_cores(struct kbase_device *kbdev) +{ + kbdev->shader_present_bitmap = kbase_pm_get_state(kbdev, KBASE_PM_CORE_SHADER, ACTION_PRESENT); + kbdev->tiler_present_bitmap = kbase_pm_get_state(kbdev, KBASE_PM_CORE_TILER, ACTION_PRESENT); + kbdev->l2_present_bitmap = kbase_pm_get_state(kbdev, KBASE_PM_CORE_L2, ACTION_PRESENT); + kbdev->l3_present_bitmap = kbase_pm_get_state(kbdev, KBASE_PM_CORE_L3, ACTION_PRESENT); + + kbdev->shader_inuse_bitmap = 0; + kbdev->shader_needed_bitmap = 0; + kbdev->shader_available_bitmap = 0; + kbdev->tiler_available_bitmap = 0; + kbdev->l2_users_count = 0; + kbdev->l2_available_bitmap = 0; + kbdev->tiler_needed_cnt = 0; + kbdev->tiler_inuse_cnt = 0; + + memset(kbdev->shader_needed_cnt, 0, sizeof(kbdev->shader_needed_cnt)); +} + +KBASE_EXPORT_TEST_API(kbasep_pm_read_present_cores) + +/** Get the cores that are present + */ +u64 kbase_pm_get_present_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + switch (type) { + case KBASE_PM_CORE_L3: + return kbdev->l3_present_bitmap; + break; + case KBASE_PM_CORE_L2: + return kbdev->l2_present_bitmap; + break; + case KBASE_PM_CORE_SHADER: + return kbdev->shader_present_bitmap; + break; + case KBASE_PM_CORE_TILER: + return kbdev->tiler_present_bitmap; + break; + } + KBASE_DEBUG_ASSERT(0); + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_present_cores) + +/** Get the cores that are "active" (busy processing work) + */ +u64 kbase_pm_get_active_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type) +{ + return kbase_pm_get_state(kbdev, type, ACTION_PWRACTIVE); +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_active_cores) + +/** Get the cores that are transitioning between power states + */ +u64 kbase_pm_get_trans_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type) +{ + return kbase_pm_get_state(kbdev, type, ACTION_PWRTRANS); +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_trans_cores) +/** Get the cores that are powered on + */ +u64 kbase_pm_get_ready_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type) +{ + u64 result; + + result = kbase_pm_get_state(kbdev, type, ACTION_READY); + + switch (type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED, NULL, NULL, 0u, (u32) result); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED_TILER, NULL, NULL, 0u, (u32) result); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED_L2, NULL, NULL, 0u, (u32) result); + break; + default: + /* NB: L3 not currently traced */ + break; + } + + return result; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_ready_cores) + +/** Perform power transitions for a particular core type. + * + * This function will perform any available power transitions to make the actual hardware state closer to the desired + * state. If a core is currently transitioning then changes to the power state of that call cannot be made until the + * transition has finished. Cores which are not present in the hardware are ignored if they are specified in the + * desired_state bitmask, however the return value will always be 0 in this case. + * + * @param kbdev The kbase device + * @param type The core type to perform transitions for + * @param desired_state A bit mask of the desired state of the cores + * @param in_use A bit mask of the cores that are currently running jobs. + * These cores have to be kept powered up because there are jobs + * running (or about to run) on them. + * @param[out] available Receives a bit mask of the cores that the job scheduler can use to submit jobs to. + * May be NULL if this is not needed. + * @param[in,out] powering_on Bit mask to update with cores that are transitioning to a power-on state. + * + * @return MALI_TRUE if the desired state has been reached, MALI_FALSE otherwise + */ +STATIC mali_bool kbase_pm_transition_core_type(struct kbase_device *kbdev, enum kbase_pm_core_type type, u64 desired_state, + u64 in_use, u64 * const available, u64 *powering_on) +{ + u64 present; + u64 ready; + u64 trans; + u64 powerup; + u64 powerdown; + u64 powering_on_trans; + u64 desired_state_in_use; + + lockdep_assert_held(&kbdev->pm.power_change_lock); + + /* Get current state */ + present = kbase_pm_get_present_cores(kbdev, type); + trans = kbase_pm_get_trans_cores(kbdev, type); + ready = kbase_pm_get_ready_cores(kbdev, type); + /* mask off ready from trans in case transitions finished between the register reads */ + trans &= ~ready; + + powering_on_trans = trans & *powering_on; + *powering_on = powering_on_trans; + + if (available != NULL) + *available = (ready | powering_on_trans) & desired_state; + + /* Update desired state to include the in-use cores. These have to be kept powered up because there are jobs + * running or about to run on these cores + */ + desired_state_in_use = desired_state | in_use; + + /* Update state of whether l2 caches are powered */ + if (type == KBASE_PM_CORE_L2) { + if ((ready == present) && (desired_state_in_use == ready) && (trans == 0)) { + /* All are ready, none will be turned off, and none are transitioning */ + kbdev->pm.l2_powered = 1; + if (kbdev->l2_users_count > 0) { + /* Notify any registered l2 cache users (optimized out when no users waiting) */ + wake_up(&kbdev->pm.l2_powered_wait); + } + } else { + kbdev->pm.l2_powered = 0; + } + } + + if (desired_state_in_use == ready && (trans == 0)) + return MALI_TRUE; + + /* Restrict the cores to those that are actually present */ + powerup = desired_state_in_use & present; + powerdown = (~desired_state_in_use) & present; + + /* Restrict to cores that are not already in the desired state */ + powerup &= ~ready; + powerdown &= ready; + + /* Don't transition any cores that are already transitioning, except for + * Mali cores that support the following case: + * + * If the SHADER_PWRON or TILER_PWRON registers are written to turn on + * a core that is currently transitioning to power off, then this is + * remembered and the shader core is automatically powered up again once + * the original transition completes. Once the automatic power on is + * complete any job scheduled on the shader core should start. + */ + powerdown &= ~trans; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS)) + if (KBASE_PM_CORE_SHADER == type || KBASE_PM_CORE_TILER == type) + trans = powering_on_trans; /* for exception cases, only mask off cores in power on transitions */ + + powerup &= ~trans; + + /* Perform transitions if any */ + kbase_pm_invoke(kbdev, type, powerup, ACTION_PWRON); + kbase_pm_invoke(kbdev, type, powerdown, ACTION_PWROFF); + + /* Recalculate cores transitioning on, and re-evaluate our state */ + powering_on_trans |= powerup; + *powering_on = powering_on_trans; + if (available != NULL) + *available = (ready | powering_on_trans) & desired_state; + + return MALI_FALSE; +} + +KBASE_EXPORT_TEST_API(kbase_pm_transition_core_type) + +/** Determine which caches should be on for a particular core state. + * + * This function takes a bit mask of the present caches and the cores (or caches) that are attached to the caches that + * will be powered. It then computes which caches should be turned on to allow the cores requested to be powered up. + * + * @param present The bit mask of present caches + * @param cores_powered A bit mask of cores (or L2 caches) that are desired to be powered + * + * @return A bit mask of the caches that should be turned on + */ +STATIC u64 get_desired_cache_status(u64 present, u64 cores_powered) +{ + u64 desired = 0; + + while (present) { + /* Find out which is the highest set bit */ + u64 bit = fls64(present) - 1; + u64 bit_mask = 1ull << bit; + /* Create a mask which has all bits from 'bit' upwards set */ + + u64 mask = ~(bit_mask - 1); + + /* If there are any cores powered at this bit or above (that haven't previously been processed) then we need + * this core on */ + if (cores_powered & mask) + desired |= bit_mask; + + /* Remove bits from cores_powered and present */ + cores_powered &= ~mask; + present &= ~bit_mask; + } + + return desired; +} + +KBASE_EXPORT_TEST_API(get_desired_cache_status) + +mali_bool MOCKABLE(kbase_pm_check_transitions_nolock) (struct kbase_device *kbdev) +{ + mali_bool cores_are_available = MALI_FALSE; + mali_bool in_desired_state = MALI_TRUE; + u64 desired_l2_state; + u64 desired_l3_state; + u64 cores_powered; + u64 tiler_available_bitmap; + u64 shader_available_bitmap; + u64 shader_ready_bitmap; + u64 shader_transitioning_bitmap; + u64 l2_available_bitmap; + u64 prev_l2_available_bitmap; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.power_change_lock); + + spin_lock(&kbdev->pm.gpu_powered_lock); + if (kbdev->pm.gpu_powered == MALI_FALSE) { + spin_unlock(&kbdev->pm.gpu_powered_lock); + if (kbdev->pm.desired_shader_state == 0 && kbdev->pm.desired_tiler_state == 0) + return MALI_TRUE; + return MALI_FALSE; + } + + /* Trace that a change-state is being requested, and that it took + * (effectively) no time to start it. This is useful for counting how many + * state changes occurred, in a way that's backwards-compatible with + * processing the trace data */ + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE); + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE); + + /* If any cores are already powered then, we must keep the caches on */ + cores_powered = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); + + cores_powered |= kbdev->pm.desired_shader_state; + + /* If there are l2 cache users registered, keep all l2s powered even if all other cores are off. */ + if (kbdev->l2_users_count > 0) + cores_powered |= kbdev->l2_present_bitmap; + + desired_l2_state = get_desired_cache_status(kbdev->l2_present_bitmap, cores_powered); + + /* If any l2 cache is on, then enable l2 #0, for use by job manager */ + if (0 != desired_l2_state) { + desired_l2_state |= 1; + /* Also enable tiler if l2 cache is powered */ + kbdev->pm.desired_tiler_state = kbdev->tiler_present_bitmap; + } else { + kbdev->pm.desired_tiler_state = 0; + } + + desired_l3_state = get_desired_cache_status(kbdev->l3_present_bitmap, desired_l2_state); + prev_l2_available_bitmap = kbdev->l2_available_bitmap; + in_desired_state &= kbase_pm_transition_core_type(kbdev, KBASE_PM_CORE_L3, desired_l3_state, 0, NULL, &kbdev->pm.powering_on_l3_state); + in_desired_state &= kbase_pm_transition_core_type(kbdev, KBASE_PM_CORE_L2, desired_l2_state, 0, &l2_available_bitmap, &kbdev->pm.powering_on_l2_state); + + if (kbdev->l2_available_bitmap != l2_available_bitmap) { + KBASE_TIMELINE_POWER_L2(kbdev, l2_available_bitmap); + } + + kbdev->l2_available_bitmap = l2_available_bitmap; + + if (in_desired_state) { + in_desired_state &= kbase_pm_transition_core_type(kbdev, KBASE_PM_CORE_TILER, kbdev->pm.desired_tiler_state, 0, &tiler_available_bitmap, &kbdev->pm.powering_on_tiler_state); + in_desired_state &= kbase_pm_transition_core_type(kbdev, KBASE_PM_CORE_SHADER, kbdev->pm.desired_shader_state, kbdev->shader_inuse_bitmap, &shader_available_bitmap, &kbdev->pm.powering_on_shader_state); + + if (kbdev->shader_available_bitmap != shader_available_bitmap) { + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, NULL, 0u, (u32) shader_available_bitmap); + KBASE_TIMELINE_POWER_SHADER(kbdev, shader_available_bitmap); + } + + kbdev->shader_available_bitmap = shader_available_bitmap; + + if (kbdev->tiler_available_bitmap != tiler_available_bitmap) { + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, NULL, 0u, (u32) tiler_available_bitmap); + KBASE_TIMELINE_POWER_TILER(kbdev, tiler_available_bitmap); + } + + kbdev->tiler_available_bitmap = tiler_available_bitmap; + + } else if ((l2_available_bitmap & kbdev->tiler_present_bitmap) != kbdev->tiler_present_bitmap) { + tiler_available_bitmap = 0; + + if (kbdev->tiler_available_bitmap != tiler_available_bitmap) { + KBASE_TIMELINE_POWER_TILER(kbdev, tiler_available_bitmap); + } + + kbdev->tiler_available_bitmap = tiler_available_bitmap; + } + + /* State updated for slow-path waiters */ + kbdev->pm.gpu_in_desired_state = in_desired_state; + + shader_ready_bitmap = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); + shader_transitioning_bitmap = kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_SHADER); + + /* Determine whether the cores are now available (even if the set of + * available cores is empty). Note that they can be available even if we've + * not finished transitioning to the desired state */ + if ((kbdev->shader_available_bitmap & kbdev->pm.desired_shader_state) == kbdev->pm.desired_shader_state && + (kbdev->tiler_available_bitmap & kbdev->pm.desired_tiler_state) == kbdev->pm.desired_tiler_state) { + cores_are_available = MALI_TRUE; + + KBASE_TRACE_ADD(kbdev, PM_CORES_AVAILABLE, NULL, NULL, 0u, (u32)(kbdev->shader_available_bitmap & kbdev->pm.desired_shader_state)); + KBASE_TRACE_ADD(kbdev, PM_CORES_AVAILABLE_TILER, NULL, NULL, 0u, (u32)(kbdev->tiler_available_bitmap & kbdev->pm.desired_tiler_state)); + + /* Log timelining information about handling events that power up + * cores, to match up either with immediate submission either because + * cores already available, or from PM IRQ */ + if (!in_desired_state) + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + } + + if (in_desired_state) { + KBASE_DEBUG_ASSERT(cores_are_available); + +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_pm_status(KBASE_PM_CORE_L3, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L3)); + kbase_trace_mali_pm_status(KBASE_PM_CORE_L2, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2)); + kbase_trace_mali_pm_status(KBASE_PM_CORE_SHADER, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER)); + kbase_trace_mali_pm_status(KBASE_PM_CORE_TILER, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_TILER)); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + + KBASE_TRACE_ADD(kbdev, PM_DESIRED_REACHED, NULL, NULL, kbdev->pm.gpu_in_desired_state, (u32)kbdev->pm.desired_shader_state); + KBASE_TRACE_ADD(kbdev, PM_DESIRED_REACHED_TILER, NULL, NULL, 0u, (u32)kbdev->pm.desired_tiler_state); + + /* Log timelining information for synchronous waiters */ + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + /* Wake slow-path waiters. Job scheduler does not use this. */ + KBASE_TRACE_ADD(kbdev, PM_WAKE_WAITERS, NULL, NULL, 0u, 0); + wake_up(&kbdev->pm.gpu_in_desired_state_wait); + } + + spin_unlock(&kbdev->pm.gpu_powered_lock); + + /* kbase_pm_ca_update_core_status can cause one-level recursion into + * this function, so it must only be called once all changes to kbdev + * have been committed, and after the gpu_powered_lock has been + * dropped. */ + if (kbdev->shader_ready_bitmap != shader_ready_bitmap || + kbdev->shader_transitioning_bitmap != shader_transitioning_bitmap) { + kbdev->shader_ready_bitmap = shader_ready_bitmap; + kbdev->shader_transitioning_bitmap = shader_transitioning_bitmap; + + kbase_pm_ca_update_core_status(kbdev, shader_ready_bitmap, shader_transitioning_bitmap); + } + + /* The core availability policy is not allowed to keep core group 0 turned off (unless it was changing the l2 power state) */ + if (!((shader_ready_bitmap | shader_transitioning_bitmap) & kbdev->gpu_props.props.coherency_info.group[0].core_mask) && + (prev_l2_available_bitmap == desired_l2_state) && + !(kbase_pm_ca_get_core_mask(kbdev) & kbdev->gpu_props.props.coherency_info.group[0].core_mask)) + BUG(); + + /* The core availability policy is allowed to keep core group 1 off, + * but all jobs specifically targeting CG1 must fail */ + if (!((shader_ready_bitmap | shader_transitioning_bitmap) & kbdev->gpu_props.props.coherency_info.group[1].core_mask) && + !(kbase_pm_ca_get_core_mask(kbdev) & kbdev->gpu_props.props.coherency_info.group[1].core_mask)) + kbdev->pm.cg1_disabled = MALI_TRUE; + else + kbdev->pm.cg1_disabled = MALI_FALSE; + + return cores_are_available; +} +KBASE_EXPORT_TEST_API(kbase_pm_check_transitions_nolock) + +void kbase_pm_check_transitions_sync(struct kbase_device *kbdev) +{ + unsigned long flags; + mali_bool cores_are_available; + /* Force the transition to be checked and reported - the cores may be + * 'available' (for job submission) but not fully powered up. */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* Wait for cores */ + wait_event(kbdev->pm.gpu_in_desired_state_wait, kbdev->pm.gpu_in_desired_state); + + /* Log timelining information that a change in state has completed */ + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); +} +KBASE_EXPORT_TEST_API(kbase_pm_check_transitions_sync) + +void kbase_pm_enable_interrupts(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + /* + * Clear all interrupts, + * and unmask them all. + */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), GPU_IRQ_REG_ALL, NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), GPU_IRQ_REG_ALL, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 0xFFFFFFFF, NULL); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), 0xFFFFFFFF, NULL); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), 0xFFFFFFFF, NULL); + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0xFFFFFFFF, NULL); +} + +KBASE_EXPORT_TEST_API(kbase_pm_enable_interrupts) + +void kbase_pm_disable_interrupts(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + /* + * Mask all interrupts, + * and clear them all. + */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), GPU_IRQ_REG_ALL, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 0xFFFFFFFF, NULL); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), 0xFFFFFFFF, NULL); +} + +KBASE_EXPORT_TEST_API(kbase_pm_disable_interrupts) + +/* + * pmu layout: + * 0x0000: PMU TAG (RO) (0xCAFECAFE) + * 0x0004: PMU VERSION ID (RO) (0x00000000) + * 0x0008: CLOCK ENABLE (RW) (31:1 SBZ, 0 CLOCK STATE) + */ +void kbase_pm_clock_on(struct kbase_device *kbdev, mali_bool is_resume) +{ + mali_bool reset_required = is_resume; + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.lock); + + if (kbdev->pm.gpu_powered) { + /* Already turned on */ + KBASE_DEBUG_ASSERT(!is_resume); + return; + } + + KBASE_TRACE_ADD(kbdev, PM_GPU_ON, NULL, NULL, 0u, 0u); + + if (is_resume && kbdev->pm.callback_power_resume) { + kbdev->pm.callback_power_resume(kbdev); + } else if (kbdev->pm.callback_power_on) { + kbdev->pm.callback_power_on(kbdev); + /* If your platform properly keeps the GPU state you may use the return + * value of the callback_power_on function to conditionally reset the + * GPU on power up. Currently we are conservative and always reset the + * GPU. */ + reset_required = MALI_TRUE; + } + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + kbdev->pm.gpu_powered = MALI_TRUE; + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (reset_required) { + /* GPU state was lost, reset GPU to ensure it is in a + * consistent state */ + kbase_pm_init_hw(kbdev, MALI_TRUE); + } + + /* Lastly, enable the interrupts */ + kbase_pm_enable_interrupts(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_clock_on) + +void kbase_pm_clock_off(struct kbase_device *kbdev, mali_bool is_suspend) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.lock); + + /* ASSERT that the cores should now be unavailable. No lock needed. */ + KBASE_DEBUG_ASSERT(kbdev->shader_available_bitmap == 0u); + + if (!kbdev->pm.gpu_powered) { + /* Already turned off */ + if (is_suspend && kbdev->pm.callback_power_suspend) + kbdev->pm.callback_power_suspend(kbdev); + return; + } + + KBASE_TRACE_ADD(kbdev, PM_GPU_OFF, NULL, NULL, 0u, 0u); + + /* Disable interrupts. This also clears any outstanding interrupts */ + kbase_pm_disable_interrupts(kbdev); + /* Ensure that any IRQ handlers have finished */ + kbase_synchronize_irqs(kbdev); + + /* The GPU power may be turned off from this point */ + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + kbdev->pm.gpu_powered = MALI_FALSE; + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (is_suspend && kbdev->pm.callback_power_suspend) + kbdev->pm.callback_power_suspend(kbdev); + else if (kbdev->pm.callback_power_off) + kbdev->pm.callback_power_off(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_clock_off) + +struct kbasep_reset_timeout_data { + struct hrtimer timer; + mali_bool timed_out; + struct kbase_device *kbdev; +}; + +void kbase_pm_reset_done(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + kbdev->pm.reset_done = MALI_TRUE; + wake_up(&kbdev->pm.reset_done_wait); +} + +/** + * Wait for the RESET_COMPLETED IRQ to occur, then reset the waiting state. + */ +STATIC void kbase_pm_wait_for_reset(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.lock); + + wait_event(kbdev->pm.reset_done_wait, (kbdev->pm.reset_done)); + kbdev->pm.reset_done = MALI_FALSE; +} + +KBASE_EXPORT_TEST_API(kbase_pm_reset_done) + +static enum hrtimer_restart kbasep_reset_timeout(struct hrtimer *timer) +{ + struct kbasep_reset_timeout_data *rtdata = container_of(timer, struct kbasep_reset_timeout_data, timer); + + rtdata->timed_out = 1; + + /* Set the wait queue to wake up kbase_pm_init_hw even though the reset hasn't completed */ + kbase_pm_reset_done(rtdata->kbdev); + + return HRTIMER_NORESTART; +} + +static void kbase_pm_hw_issues(struct kbase_device *kbdev) +{ + u32 value = 0; + + /* Needed due to MIDBASE-1494: LS_PAUSEBUFFER_DISABLE. See PRLAM-8443. + * and + * needed due to MIDGLES-3539. See PRLAM-11035 */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8443) || + kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_11035)) + value |= SC_LS_PAUSEBUFFER_DISABLE; + + /* Needed due to MIDBASE-2054: SDC_DISABLE_OQ_DISCARD. See PRLAM-10327. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10327)) + value |= SC_SDC_DISABLE_OQ_DISCARD; + + /* Enable alternative hardware counter selection if configured. */ + if (DEFAULT_ALTERNATIVE_HWC) + value |= SC_ALT_COUNTERS; + + /* Use software control of forward pixel kill when needed. See MIDEUR-174. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_2121)) + value |= SC_OVERRIDE_FWD_PIXEL_KILL; + + /* Needed due to MIDBASE-2795. ENABLE_TEXGRD_FLAGS. See PRLAM-10797. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10797)) + value |= SC_ENABLE_TEXGRD_FLAGS; + + if (value != 0) + kbase_reg_write(kbdev, GPU_CONTROL_REG(SHADER_CONFIG), value, NULL); + + /* Set tiler clock gate override if required */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_3953)) { + value = kbase_reg_read(kbdev, GPU_CONTROL_REG(TILER_CONFIG), NULL); + value |= TC_CLOCK_GATE_OVERRIDE; + kbase_reg_write(kbdev, GPU_CONTROL_REG(TILER_CONFIG), value, NULL); + } + + /* Limit the GPU bus bandwidth if the platform needs this. */ + value = kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), NULL); + + /* Limit read ID width for AXI */ + value &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_READS); + value |= (DEFAULT_ARID_LIMIT & 0x3) << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT; + + /* Limit write ID width for AXI */ + value &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES); + value |= (DEFAULT_AWID_LIMIT & 0x3) << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT; + + kbase_reg_write(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), value, NULL); +} + +mali_error kbase_pm_init_hw(struct kbase_device *kbdev, mali_bool enable_irqs) +{ + unsigned long flags; + struct kbasep_reset_timeout_data rtdata; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.lock); + + /* Ensure the clock is on before attempting to access the hardware */ + if (!kbdev->pm.gpu_powered) { + if (kbdev->pm.callback_power_on) + kbdev->pm.callback_power_on(kbdev); + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + kbdev->pm.gpu_powered = MALI_TRUE; + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + } + + /* Ensure interrupts are off to begin with, this also clears any outstanding interrupts */ + kbase_pm_disable_interrupts(kbdev); + + /* Prepare for the soft-reset */ + kbdev->pm.reset_done = MALI_FALSE; + + /* The cores should be made unavailable due to the reset */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + if (kbdev->shader_available_bitmap != 0u) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, NULL, 0u, (u32)0u); + if (kbdev->tiler_available_bitmap != 0u) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, NULL, 0u, (u32)0u); + kbdev->shader_available_bitmap = 0u; + kbdev->tiler_available_bitmap = 0u; + kbdev->l2_available_bitmap = 0u; + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* Soft reset the GPU */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_SOFT_RESET, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_SOFT_RESET, NULL); + + /* Unmask the reset complete interrupt only */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), RESET_COMPLETED, NULL); + + /* Initialize a structure for tracking the status of the reset */ + rtdata.kbdev = kbdev; + rtdata.timed_out = 0; + + /* Create a timer to use as a timeout on the reset */ + hrtimer_init_on_stack(&rtdata.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + rtdata.timer.function = kbasep_reset_timeout; + + hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT), HRTIMER_MODE_REL); + + /* Wait for the RESET_COMPLETED interrupt to be raised */ + kbase_pm_wait_for_reset(kbdev); + + if (rtdata.timed_out == 0) { + /* GPU has been reset */ + hrtimer_cancel(&rtdata.timer); + destroy_hrtimer_on_stack(&rtdata.timer); + goto out; + } + + /* No interrupt has been received - check if the RAWSTAT register says the reset has completed */ + if (kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL) & RESET_COMPLETED) { + /* The interrupt is set in the RAWSTAT; this suggests that the interrupts are not getting to the CPU */ + dev_warn(kbdev->dev, "Reset interrupt didn't reach CPU. Check interrupt assignments.\n"); + /* If interrupts aren't working we can't continue. */ + destroy_hrtimer_on_stack(&rtdata.timer); + goto out; + } + + /* The GPU doesn't seem to be responding to the reset so try a hard reset */ + dev_err(kbdev->dev, "Failed to soft-reset GPU (timed out after %d ms), now attempting a hard reset\n", RESET_TIMEOUT); + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET, NULL); + + /* Restart the timer to wait for the hard reset to complete */ + rtdata.timed_out = 0; + + hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT), HRTIMER_MODE_REL); + + /* Wait for the RESET_COMPLETED interrupt to be raised */ + kbase_pm_wait_for_reset(kbdev); + + if (rtdata.timed_out == 0) { + /* GPU has been reset */ + hrtimer_cancel(&rtdata.timer); + destroy_hrtimer_on_stack(&rtdata.timer); + goto out; + } + + destroy_hrtimer_on_stack(&rtdata.timer); + + dev_err(kbdev->dev, "Failed to hard-reset the GPU (timed out after %d ms)\n", RESET_TIMEOUT); + + /* The GPU still hasn't reset, give up */ + return MALI_ERROR_FUNCTION_FAILED; + + out: + + /* If cycle counter was in use-re enable it enable_irqs will only be false when called from kbase_pm_powerup */ + if (kbdev->pm.gpu_cycle_counter_requests && enable_irqs) { + /* enable interrupts as the L2 may have to be powered on */ + kbase_pm_enable_interrupts(kbdev); + kbase_pm_request_l2_caches(kbdev); + + /* Re-enable the counters if we need to */ + spin_lock_irqsave(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + if (kbdev->pm.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CYCLE_COUNT_START, NULL); + spin_unlock_irqrestore(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + kbase_pm_release_l2_caches(kbdev); + kbase_pm_disable_interrupts(kbdev); + } + + if (enable_irqs) + kbase_pm_enable_interrupts(kbdev); + + kbase_pm_hw_issues(kbdev); + + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_pm_init_hw) + +/** Increase the count of cycle counter users and turn the cycle counters on if they were previously off + * + * this function is designed to be called by @ref kbase_pm_request_gpu_cycle_counter or + * @ref kbase_pm_request_gpu_cycle_counter_l2_is_on only + * + * When this function is called the l2 cache must be on and the l2 cache users count must + * have been incremented by a call to (@ref kbase_pm_request_l2_caches or @ref kbase_pm_request_l2_caches_l2_on) + * + * @param kbdev The kbase device structure of the device + * + */ +static void kbase_pm_request_gpu_cycle_counter_do_request(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + ++kbdev->pm.gpu_cycle_counter_requests; + + if (1 == kbdev->pm.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CYCLE_COUNT_START, NULL); + + spin_unlock_irqrestore(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); +} + +void kbase_pm_request_gpu_cycle_counter(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_cycle_counter_requests < INT_MAX); + + kbase_pm_request_l2_caches(kbdev); + + kbase_pm_request_gpu_cycle_counter_do_request(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_gpu_cycle_counter) + +void kbase_pm_request_gpu_cycle_counter_l2_is_on(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_cycle_counter_requests < INT_MAX); + + kbase_pm_request_l2_caches_l2_is_on(kbdev); + + kbase_pm_request_gpu_cycle_counter_do_request(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_gpu_cycle_counter_l2_is_on) + +void kbase_pm_release_gpu_cycle_counter(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_cycle_counter_requests > 0); + + --kbdev->pm.gpu_cycle_counter_requests; + + if (0 == kbdev->pm.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CYCLE_COUNT_STOP, NULL); + + spin_unlock_irqrestore(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + kbase_pm_release_l2_caches(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_gpu_cycle_counter) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics.c new file mode 100644 index 0000000000000000000000000000000000000000..76a7245e33cf7f01bc35494a11e54e495cd3e2b3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics.c @@ -0,0 +1,1388 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_metrics.c + * Metrics for power management + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +//#define NO_DVFS_FOR_BRINGUP + +#include +#include +#if KBASE_PM_EN + +/* When VSync is being hit aim for utilisation between 70-90% */ +#define KBASE_PM_VSYNC_MIN_UTILISATION 30//70 +#define KBASE_PM_VSYNC_MAX_UTILISATION 50//90 +/* Otherwise aim for 10-40% */ +#define KBASE_PM_NO_VSYNC_MIN_UTILISATION 10 +#define KBASE_PM_NO_VSYNC_MAX_UTILISATION 40 + +#define KBASE_TIMER_THRESHOLD 3000 +#ifdef CONFIG_MALI_MIDGARD_DVFS + +int g_current_sample_gl_utilization = 0; +int g_current_sample_cl_utilization[2] = {0}; + +/* MTK GPU DVFS */ +#include "mt_gpufreq.h" +#include "random.h" + +int g_dvfs_enabled = 1; +int g_input_boost_enabled = 1; +enum kbase_pm_dvfs_action g_current_action = KBASE_PM_DVFS_NOP; +int g_dvfs_freq = DEFAULT_PM_DVFS_FREQ; +int g_dvfs_threshold_max = KBASE_PM_VSYNC_MAX_UTILISATION; +int g_dvfs_threshold_min = KBASE_PM_VSYNC_MIN_UTILISATION; +int g_dvfs_deferred_count = 4; +#endif // CONFIG_MALI_MIDGARD_DVFS +int g_touch_boost_flag = 0; +int g_touch_boost_id = 0; + +struct timeval g_tv_timer_start; + +static enum hrtimer_restart dvfs_callback(struct hrtimer *timer); + +int g_vgpu_power_on_flag = 0; // on:1, off:0 +int g_power_on_freq_flag = 0; +int g_power_on_freq_id = 0; +void __iomem *g_clk_topck_base = 0x0; +void __iomem *gb_DFP_base = 0x0; + + +void mali_SODI_begin(void) +{ + struct list_head *entry; + const struct list_head *kbdev_list; + kbdev_list = kbase_dev_list_get(); + + list_for_each(entry, kbdev_list) + { + struct kbase_device *kbdev = NULL; + kbdev = list_entry(entry, struct kbase_device, entry); + + if (MALI_TRUE == kbdev->pm.metrics.timer_active) + { + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbdev->pm.metrics.timer_active = MALI_FALSE; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + + hrtimer_cancel(&kbdev->pm.metrics.timer); + } + } + kbase_dev_list_put(kbdev_list); +} +KBASE_EXPORT_TEST_API(mali_SODI_begin); + + +void mali_SODI_exit(void) +{ + struct list_head *entry; + const struct list_head *kbdev_list; + struct timeval tv_timer_end; + long timer_time_elapse; + + kbdev_list = kbase_dev_list_get(); + list_for_each(entry, kbdev_list) + { + struct kbase_device *kbdev = NULL; + kbdev = list_entry(entry, struct kbase_device, entry); + + if((MALI_FALSE == kbdev->pm.metrics.timer_active) ) + { + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbdev->pm.metrics.timer_active = MALI_TRUE; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + + // exit SODI, calculate the length of timer before SODI cancelled the timer. + do_gettimeofday(&tv_timer_end); + timer_time_elapse = (tv_timer_end.tv_sec - g_tv_timer_start.tv_sec)*1000000 + (tv_timer_end.tv_usec - g_tv_timer_start.tv_usec); + + + if( timer_time_elapse > (mtk_get_dvfs_freq()*1000 - KBASE_TIMER_THRESHOLD) ) + { + // remain time is too short, calcute loading immediately + dvfs_callback(&kbdev->pm.metrics.timer); + } + else if( (timer_time_elapse <= (mtk_get_dvfs_freq()*1000 - KBASE_TIMER_THRESHOLD)) && (timer_time_elapse > 0)) + { + hrtimer_init(&kbdev->pm.metrics.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->pm.platform_dvfs_frequency = mtk_get_dvfs_freq() - timer_time_elapse/1000; /* set timer length to: original - elasped time */ + kbdev->pm.metrics.timer.function = dvfs_callback; + do_gettimeofday( &g_tv_timer_start); + hrtimer_start(&kbdev->pm.metrics.timer, HR_TIMER_DELAY_MSEC(kbdev->pm.platform_dvfs_frequency), HRTIMER_MODE_REL); + } + else + { + // unknown case + hrtimer_init(&kbdev->pm.metrics.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->pm.platform_dvfs_frequency = mtk_get_dvfs_freq(); + kbdev->pm.metrics.timer.function = dvfs_callback; + do_gettimeofday( &g_tv_timer_start); + hrtimer_start(&kbdev->pm.metrics.timer, HR_TIMER_DELAY_MSEC(kbdev->pm.platform_dvfs_frequency), HRTIMER_MODE_REL); + } + + } + } + kbase_dev_list_put(kbdev_list); +} +KBASE_EXPORT_TEST_API(mali_SODI_exit); + +/* Shift used for kbasep_pm_metrics_data.time_busy/idle - units of (1 << 8) ns + This gives a maximum period between samples of 2^(32+8)/100 ns = slightly under 11s. + Exceeding this will cause overflow */ +#define KBASE_PM_TIME_SHIFT 8 + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +void mtk_get_touch_boost_flag(int *touch_boost_flag, int *touch_boost_id) +{ + *touch_boost_flag = g_touch_boost_flag; + *touch_boost_id = g_touch_boost_id; + return; +} + +void mtk_set_touch_boost_flag(int touch_boost_id) +{ + g_touch_boost_flag = 1; + g_touch_boost_id = touch_boost_id; + return; +} + +void mtk_clear_touch_boost_flag(void) +{ + g_touch_boost_flag = 0; + return; +} + +int mtk_get_input_boost_enabled() +{ + return g_input_boost_enabled; +} + +int mtk_get_dvfs_enabled() +{ + return g_dvfs_enabled; +} + +int mtk_get_dvfs_freq() +{ + return g_dvfs_freq; +} + +int mtk_get_dvfs_threshold_max() +{ + return g_dvfs_threshold_max; +} + +int mtk_get_dvfs_threshold_min() +{ + return g_dvfs_threshold_min; +} + +int mtk_get_dvfs_deferred_count() +{ + return g_dvfs_deferred_count; +} + +void mtk_set_vgpu_power_on_flag(int power_on_id) +{ + g_vgpu_power_on_flag = power_on_id; + return; +} +int mtk_get_vgpu_power_on_flag(void) +{ + return g_vgpu_power_on_flag; +} + +int mtk_set_mt_gpufreq_target(int freq_id) +{ + if(MTK_VGPU_POWER_ON == mtk_get_vgpu_power_on_flag()){ + return mt_gpufreq_target(freq_id); + }else{ + mtk_set_power_on_freq_flag(freq_id); + pr_alert("MALI: VGPU power is off, ignore set freq: %d. \n",freq_id); + } + return -1; + +} + +void mtk_get_power_on_freq_flag(int *power_on_freq_flag, int *power_on_freq_id) +{ + *power_on_freq_flag = g_power_on_freq_flag; + *power_on_freq_id = g_power_on_freq_id; + return; +} + +void mtk_set_power_on_freq_flag(int power_on_freq_id) +{ + g_power_on_freq_flag = 1; + g_power_on_freq_id = power_on_freq_id; + return; +} + +void mtk_clear_power_on_freq_flag(void) +{ + g_power_on_freq_flag = 0; + return; +} +enum kbase_pm_dvfs_action mtk_get_dvfs_action() +{ + return g_current_action; +} + +void mtk_clear_dvfs_action() +{ + g_current_action = KBASE_PM_DVFS_NONSENSE; +} + +static enum hrtimer_restart dvfs_callback(struct hrtimer *timer) +{ + unsigned long flags; + enum kbase_pm_dvfs_action action; + struct kbasep_pm_metrics_data *metrics; + + KBASE_DEBUG_ASSERT(timer != NULL); + + metrics = container_of(timer, struct kbasep_pm_metrics_data, timer); + action = kbase_pm_get_dvfs_action(metrics->kbdev); + + g_current_action = action; + spin_lock_irqsave(&metrics->lock, flags); + metrics->kbdev->pm.platform_dvfs_frequency = mtk_get_dvfs_freq(); + + if (metrics->timer_active) + { + do_gettimeofday( &g_tv_timer_start); + hrtimer_start(timer, + HR_TIMER_DELAY_MSEC(metrics->kbdev->pm.platform_dvfs_frequency), + HRTIMER_MODE_REL); + } + + spin_unlock_irqrestore(&metrics->lock, flags); + + return HRTIMER_NORESTART; +} +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + +mali_error kbasep_pm_metrics_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + kbdev->pm.metrics.kbdev = kbdev; + kbdev->pm.metrics.vsync_hit = 1; /* [MTK] vsync notifiy is not implemented yet, assumed always hit. */ + kbdev->pm.metrics.utilisation = 0; + kbdev->pm.metrics.util_cl_share[0] = 0; + kbdev->pm.metrics.util_cl_share[1] = 0; + kbdev->pm.metrics.util_gl_share = 0; + + kbdev->pm.metrics.time_period_start = ktime_get(); + kbdev->pm.metrics.time_busy = 0; + kbdev->pm.metrics.time_idle = 0; + kbdev->pm.metrics.gpu_active = MALI_TRUE; + kbdev->pm.metrics.active_cl_ctx[0] = 0; + kbdev->pm.metrics.active_cl_ctx[1] = 0; + kbdev->pm.metrics.active_gl_ctx = 0; + kbdev->pm.metrics.busy_cl[0] = 0; + kbdev->pm.metrics.busy_cl[1] = 0; + kbdev->pm.metrics.busy_gl = 0; + + spin_lock_init(&kbdev->pm.metrics.lock); + +#ifdef CONFIG_MALI_MIDGARD_DVFS +#ifndef ENABLE_COMMON_DVFS + kbdev->pm.metrics.timer_active = MALI_TRUE; + hrtimer_init(&kbdev->pm.metrics.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->pm.metrics.timer.function = dvfs_callback; + + do_gettimeofday( &g_tv_timer_start); + hrtimer_start(&kbdev->pm.metrics.timer, HR_TIMER_DELAY_MSEC(kbdev->pm.platform_dvfs_frequency), HRTIMER_MODE_REL); +#endif +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + + kbase_pm_register_vsync_callback(kbdev); + + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbasep_pm_metrics_init) + +void kbasep_pm_metrics_term(struct kbase_device *kbdev) +{ +#ifdef CONFIG_MALI_MIDGARD_DVFS + unsigned long flags; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbdev->pm.metrics.timer_active = MALI_FALSE; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + + hrtimer_cancel(&kbdev->pm.metrics.timer); +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + + kbase_pm_unregister_vsync_callback(kbdev); +} + +KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term) + +/*caller needs to hold kbdev->pm.metrics.lock before calling this function*/ +void kbasep_pm_record_job_status(struct kbase_device *kbdev) +{ + ktime_t now; + ktime_t diff; + u32 ns_time; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + now = ktime_get(); + diff = ktime_sub(now, kbdev->pm.metrics.time_period_start); + + ns_time = (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + kbdev->pm.metrics.time_busy += ns_time; + kbdev->pm.metrics.busy_gl += ns_time * kbdev->pm.metrics.active_gl_ctx; + kbdev->pm.metrics.busy_cl[0] += ns_time * kbdev->pm.metrics.active_cl_ctx[0]; + kbdev->pm.metrics.busy_cl[1] += ns_time * kbdev->pm.metrics.active_cl_ctx[1]; + kbdev->pm.metrics.time_period_start = now; +} + +KBASE_EXPORT_TEST_API(kbasep_pm_record_job_status) + +void kbasep_pm_record_gpu_idle(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + + KBASE_DEBUG_ASSERT(kbdev->pm.metrics.gpu_active == MALI_TRUE); + + kbdev->pm.metrics.gpu_active = MALI_FALSE; + + kbasep_pm_record_job_status(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +KBASE_EXPORT_TEST_API(kbasep_pm_record_gpu_idle) + +void kbasep_pm_record_gpu_active(struct kbase_device *kbdev) +{ + unsigned long flags; + ktime_t now; + ktime_t diff; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + + KBASE_DEBUG_ASSERT(kbdev->pm.metrics.gpu_active == MALI_FALSE); + + kbdev->pm.metrics.gpu_active = MALI_TRUE; + + now = ktime_get(); + diff = ktime_sub(now, kbdev->pm.metrics.time_period_start); + + kbdev->pm.metrics.time_idle += (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + kbdev->pm.metrics.time_period_start = now; + + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +KBASE_EXPORT_TEST_API(kbasep_pm_record_gpu_active) + +void kbase_pm_report_vsync(struct kbase_device *kbdev, int buffer_updated) +{ + unsigned long flags; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbdev->pm.metrics.vsync_hit = buffer_updated; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_report_vsync) + +/*caller needs to hold kbdev->pm.metrics.lock before calling this function*/ +static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev, ktime_t now) +{ + ktime_t diff; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + diff = ktime_sub(now, kbdev->pm.metrics.time_period_start); + + if (kbdev->pm.metrics.gpu_active) { + u32 ns_time = (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + kbdev->pm.metrics.time_busy += ns_time; + kbdev->pm.metrics.busy_cl[0] += ns_time * kbdev->pm.metrics.active_cl_ctx[0]; + kbdev->pm.metrics.busy_cl[1] += ns_time * kbdev->pm.metrics.active_cl_ctx[1]; + kbdev->pm.metrics.busy_gl += ns_time * kbdev->pm.metrics.active_gl_ctx; + } else { + kbdev->pm.metrics.time_idle += (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + } +} + +/*caller needs to hold kbdev->pm.metrics.lock before calling this function*/ +static void kbase_pm_get_dvfs_utilisation_reset(struct kbase_device *kbdev, ktime_t now) +{ + kbdev->pm.metrics.time_period_start = now; + kbdev->pm.metrics.time_idle = 0; + kbdev->pm.metrics.time_busy = 0; + kbdev->pm.metrics.busy_cl[0] = 0; + kbdev->pm.metrics.busy_cl[1] = 0; + kbdev->pm.metrics.busy_gl = 0; +} + +void kbase_pm_get_dvfs_utilisation(struct kbase_device *kbdev, unsigned long *total, unsigned long *busy, bool reset) +{ + ktime_t now = ktime_get(); + unsigned long tmp, flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbase_pm_get_dvfs_utilisation_calc(kbdev, now); + + tmp = kbdev->pm.metrics.busy_gl; + tmp += kbdev->pm.metrics.busy_cl[0]; + tmp += kbdev->pm.metrics.busy_cl[1]; + + *busy = tmp; + *total = tmp + kbdev->pm.metrics.time_idle; + + if (reset) + kbase_pm_get_dvfs_utilisation_reset(kbdev, now); + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +/*caller needs to hold kbdev->pm.metrics.lock before calling this function*/ +int kbase_pm_get_dvfs_utilisation_old(struct kbase_device *kbdev, int *util_gl_share, int util_cl_share[2]) +{ + int utilisation; + int busy; + ktime_t now = ktime_get(); + + kbase_pm_get_dvfs_utilisation_calc(kbdev, now); + + if (kbdev->pm.metrics.time_idle + kbdev->pm.metrics.time_busy == 0) { + /* No data - so we return NOP */ + utilisation = -1; + if (util_gl_share) + *util_gl_share = -1; + if (util_cl_share) { + util_cl_share[0] = -1; + util_cl_share[1] = -1; + } + goto out; + } + + utilisation = (100 * kbdev->pm.metrics.time_busy) / + (kbdev->pm.metrics.time_idle + + kbdev->pm.metrics.time_busy); + + busy = kbdev->pm.metrics.busy_gl + + kbdev->pm.metrics.busy_cl[0] + + kbdev->pm.metrics.busy_cl[1]; + + if (busy != 0) { + if (util_gl_share) + *util_gl_share = + (100 * kbdev->pm.metrics.busy_gl) / busy; + if (util_cl_share) { + util_cl_share[0] = + (100 * kbdev->pm.metrics.busy_cl[0]) / busy; + util_cl_share[1] = + (100 * kbdev->pm.metrics.busy_cl[1]) / busy; + } + } else { + if (util_gl_share) + *util_gl_share = -1; + if (util_cl_share) { + util_cl_share[0] = -1; + util_cl_share[1] = -1; + } + } + +out: + kbase_pm_get_dvfs_utilisation_reset(kbdev, now); + + return utilisation; +} + +void MTKCalGpuUtilization(unsigned int* pui32Loading , unsigned int* pui32Block,unsigned int* pui32Idle) +{ + struct kbase_device *kbdev = MaliGetMaliData(); + + unsigned long flags; + int utilisation, util_gl_share; + int util_cl_share[2]; + int random_action; + enum kbase_pm_dvfs_action action; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + + utilisation = kbase_pm_get_dvfs_utilisation_old(kbdev, &util_gl_share, util_cl_share); + + if(pui32Loading) + *pui32Loading = utilisation; + if(pui32Idle) + *pui32Idle = 100 - utilisation; + + /* + if(pui32Block) + *pui32Block = 0; // no ref value in r5px + */ + + if (utilisation < 0 || util_gl_share < 0 || util_cl_share[0] < 0 || util_cl_share[1] < 0) { + action = KBASE_PM_DVFS_NOP; + utilisation = 0; + util_gl_share = 0; + util_cl_share[0] = 0; + util_cl_share[1] = 0; + goto out; + } + + if (kbdev->pm.metrics.vsync_hit) { + /* VSync is being met */ + if (utilisation < mtk_get_dvfs_threshold_min()) + action = KBASE_PM_DVFS_CLOCK_DOWN; + else if (utilisation > mtk_get_dvfs_threshold_max()) + action = KBASE_PM_DVFS_CLOCK_UP; + else + action = KBASE_PM_DVFS_NOP; + } else { + /* VSync is being missed */ + if (utilisation < KBASE_PM_NO_VSYNC_MIN_UTILISATION) + action = KBASE_PM_DVFS_CLOCK_DOWN; + else if (utilisation > KBASE_PM_NO_VSYNC_MAX_UTILISATION) + action = KBASE_PM_DVFS_CLOCK_UP; + else + action = KBASE_PM_DVFS_NOP; + } + + // get a radom action for stress test + if (mtk_get_dvfs_enabled() == 2) + { + get_random_bytes( &random_action, sizeof(random_action)); + random_action = random_action%3; + pr_debug("[MALI] GPU DVFS stress test - genereate random action here: action = %d", random_action); + action = random_action; + } + + kbdev->pm.metrics.utilisation = utilisation; + kbdev->pm.metrics.util_cl_share[0] = util_cl_share[0]; + kbdev->pm.metrics.util_cl_share[1] = util_cl_share[1]; + kbdev->pm.metrics.util_gl_share = util_gl_share; + + g_current_sample_gl_utilization = utilisation; + g_current_sample_cl_utilization[0] = util_cl_share[0]; + g_current_sample_cl_utilization[1] = util_cl_share[1]; + +out: +#if 0 /// def CONFIG_MALI_MIDGARD_DVFS + kbase_platform_dvfs_event(kbdev, utilisation, util_gl_share, util_cl_share); +#endif /*CONFIG_MALI_MIDGARD_DVFS */ + kbdev->pm.metrics.time_idle = 0; + kbdev->pm.metrics.time_busy = 0; + kbdev->pm.metrics.busy_cl[0] = 0; + kbdev->pm.metrics.busy_cl[1] = 0; + kbdev->pm.metrics.busy_gl = 0; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} +#define base_write32(addr, value) writel(value, addr) +#define base_read32(addr) readl(addr) +void mtk_Power_Enable_MFG(void) +{ + struct kbase_device *kbdev = MaliGetMaliData(); + void __iomem *clk_mfgsys_base = kbdev->mfg_register; +#define MFG_PERF_EN_0 (clk_mfgsys_base +0x1B0) +#define MFG_PERF_EN_1 (clk_mfgsys_base +0x1B4) +#define MFG_PERF_EN_2 (clk_mfgsys_base +0x1B8) + if (!clk_mfgsys_base){ + pr_alert("[Mali] mtk_Power_Enable_MFG failed\n"); + }else{ + base_write32(MFG_PERF_EN_0, 0xffffffff); + ///pr_alert("[Mali] MFG_PERF_EN_0 = %08x\n",base_read32(MFG_PERF_EN_0)); + base_write32(MFG_PERF_EN_1, 0xffffffff); + ///pr_alert("[Mali] MFG_PERF_EN_1 = %08x\n",base_read32(MFG_PERF_EN_1)); + base_write32(MFG_PERF_EN_2, 0xffffffff); + ///pr_alert("[Mali] MFG_PERF_EN_2 = %08x\n",base_read32(MFG_PERF_EN_2)); + } +} + +void mtk_Power_Enable_Topck(void) +{ + struct device_node *node; + void __iomem *clk_topck_base; + +#define CLK_MISC_CFG_0 (clk_topck_base + 0x104) + + if(g_clk_topck_base == 0x0){ + pr_alert("[Mali][pmeter]g_clk_topck_base: %p \n",g_clk_topck_base); + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-topckgen"); + if (!node) { + pr_alert("[Mali]mtk_Power_Enable_TOPCK find node failed\n"); + } + clk_topck_base = of_iomap(node, 0); + g_clk_topck_base= clk_topck_base; + }else{ + clk_topck_base = g_clk_topck_base; + } + if (!clk_topck_base){ + pr_alert("[Mali] mtk_Power_Enable_TOP_CK failed\n"); + }else{ + base_write32(CLK_MISC_CFG_0, base_read32(CLK_MISC_CFG_0) & 0xfffffffe); + ///pr_alert("[Mali] CLK_MISC_CFG_0 : %08x\n",base_read32(CLK_MISC_CFG_0)); + } + +} + + +/* TODO: config by CONFIG_OF */ +int dfp_weights[] = { + 173, 9, 1, 9, 2726, 793, 1277, 0, 8318, 4434, + 211, 8338, 0, 2572, 2163, 3254, 687, 0, 39499, 0, + 0, 0, 1988, 673, 0, 0, 890, 352, 0, 4803, + 611, 1051, 82, 0, 215, 211, 8338, 0, 2572, 2163, + 3254, 697, 0, 39499, 44, 42, 206, 17, 2, 31, + 26, 6, 566, 39, 52, 5, 0, 1171, 2232, 328, + 126, 776, 97, 17451, 33052, 65131, 1623, 66, 43, 91, + 19, 133, 12, 0, 3, 54, 3, 35, 217, 600, + 487, 2146, 572, 359, 13009, 253, 16889, 399, 1, 10, + 79, 22, 299, 304, 9, 1164, 412, 361, 61, 22, + 3, 2, 80, 29795, 46, 1009, 167, 390, 232, 113 +}; + +#define DFP_ID 0x0 +#define DFP_CTRL 0x4 +//#define DFP_EVENT_ACCUM_CTRL 0x8 +#define DFP_PM_VALUE 0x38 +#define DFP_LP_CONSTANT 0x3c +#define DFP_LEAKAGE_VALUE 0x40 +#define DFP_SCALING_FACTOR 0x44 // 0x50 +#define DFP_VOLT_FACTOR 0x48 // 0x54 +#define DFP_PIECE_PWR 0x50 +#define DFP_PM_PERIOD 0x5c +#define DFP_COUNTER_EN_0 0x60 +#define DFP_COUNTER_EN_1 0x64 +#define DFP_LINAER_A0 0x68 +#define DFP_WEIGHT_(x) (0x70+4*x) + +#define DFP_DEBUG 0 + +unsigned int MTKCalPowerIndex(void){ + struct device_node *node; + void __iomem *g_DFP_base; + unsigned int dep =0; + + if(gb_DFP_base==0x0){ + pr_alert("[Mali][pmeter]gb_DFP_base: %p \n",gb_DFP_base); + node = of_find_compatible_node(NULL, NULL, "mediatek,mfg_dfp"); + if (!node) { + pr_alert("[Mali]mfg_dfp find node failed\n"); + } + g_DFP_base = of_iomap(node, 0); + gb_DFP_base = g_DFP_base; + }else{ + g_DFP_base =gb_DFP_base; + } + if (!g_DFP_base){ + pr_alert("[Mali] g_DFP_base failed\n"); + }else{ + + +#define DFP_write32(addr, value) base_write32(g_DFP_base+addr, value) +#define DFP_read32(addr) base_read32(g_DFP_base+addr) + + int i,id,pm_period,linear_a0, scaling_factor,vlotage_factor,leakage_val; + + pm_period = 0; + linear_a0 = 0; + vlotage_factor = 1; + scaling_factor = 14; + leakage_val = 10; + + // turn on clock + mtk_Power_Enable_Topck(); + // GPU perforamcne clock gated + mtk_Power_Enable_MFG(); + + //pr_alert("[MALI]MTKCalPowerIndex g_DFP_base = 0x%08x \n", (int)g_DFP_base); + + DFP_write32(DFP_CTRL, DFP_read32(DFP_CTRL) | 0x2); // bit[0] -> dpm enable, bit[1] -> dcm enable + + DFP_write32(DFP_ID, 0x55aa3344); + id = DFP_read32(DFP_ID); + + DFP_write32(DFP_LEAKAGE_VALUE, leakage_val); + DFP_write32(DFP_VOLT_FACTOR, vlotage_factor); + DFP_write32(DFP_SCALING_FACTOR, scaling_factor); + DFP_write32(DFP_PM_PERIOD, pm_period); + DFP_write32(DFP_LP_CONSTANT, 9); + DFP_write32(DFP_LINAER_A0, linear_a0); + + if(DFP_DEBUG){ + pr_alert("[MALI]MTKCalPowerIndex ID_value = 0x%08x \n", id); + pr_alert("[MALI]MTKCalPowerIndex Leakage_value = 0x%08x \n", DFP_read32(DFP_LEAKAGE_VALUE)); + pr_alert("[MALI]MTKCalPowerIndex DFP_VOLT_FACTOR = 0x%08x \n", DFP_read32(DFP_VOLT_FACTOR)); + pr_alert("[MALI]MTKCalPowerIndex DFP_SCALING_FACTOR = 0x%08x \n", DFP_read32(DFP_SCALING_FACTOR)); + pr_alert("[MALI]MTKCalPowerIndex DFP_PM_PERIOD = 0x%08x \n", DFP_read32(DFP_PM_PERIOD)); + pr_alert("[MALI]MTKCalPowerIndex DFP_LP_CONSTANT = 0x%08x \n", DFP_read32(DFP_LP_CONSTANT)); + pr_alert("[MALI]MTKCalPowerIndex DFP_LINAER_A0 = 0x%08x \n", DFP_read32(DFP_LINAER_A0)); + pr_alert("[MALI]MTKCalPowerIndex DFP_COUNTER_EN_0 = 0x%08x \n", DFP_read32(DFP_COUNTER_EN_0)); + pr_alert("[MALI]MTKCalPowerIndex DFP_COUNTER_EN_1 = 0x%08x \n", DFP_read32(DFP_COUNTER_EN_1)); + pr_alert("[MALI]MTKCalPowerIndex g_vgpu_power_on_flag = 0x%08x \n", g_vgpu_power_on_flag); + + } + + + + for (i = 0; i < 60; ++i) + { + DFP_write32(DFP_WEIGHT_(i), dfp_weights[i]); + } + + DFP_write32(DFP_CTRL, DFP_read32(DFP_CTRL) | 0x1); // bit[0] -> dpm enable, bit[1] -> dcm enable + if(DFP_DEBUG){ + pr_alert("[MALI]MTKCalPowerIndex DFP_CTRL 1= 0x%08x \n", DFP_read32(DFP_CTRL)); + } + + + DFP_write32(DFP_CTRL, 0x3 ); // bit[0] -> dpm enable, bit[1] -> dcm enable + if(DFP_DEBUG){ + pr_alert("[MALI]MTKCalPowerIndex DFP_CTRL 2 = 0x%08x \n", DFP_read32(DFP_CTRL)); + } + + + for(i=0;i<100;i++) + { + dep = DFP_read32(DFP_PIECE_PWR); + ///pr_alert("[MALI]MTKCalPowerIndex normal piece_pwr = 0x%08x \n", dep); + } + + + dep = DFP_read32(DFP_PM_VALUE); //MFG_DFP_60_PM_VALUE + pr_alert("[MALI]MTKCalPowerIndex normal PM_value = %d \n", DFP_read32(DFP_PM_VALUE)); + + + } + + + return dep; +} + + +enum kbase_pm_dvfs_action kbase_pm_get_dvfs_action(struct kbase_device *kbdev) +{ + unsigned long flags; + int utilisation, util_gl_share; + int util_cl_share[2]; + int random_action; + enum kbase_pm_dvfs_action action; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + + utilisation = kbase_pm_get_dvfs_utilisation_old(kbdev, &util_gl_share, util_cl_share); + + if (utilisation < 0 || util_gl_share < 0 || util_cl_share[0] < 0 || util_cl_share[1] < 0) { + action = KBASE_PM_DVFS_NOP; + utilisation = 0; + util_gl_share = 0; + util_cl_share[0] = 0; + util_cl_share[1] = 0; + goto out; + } + + if (kbdev->pm.metrics.vsync_hit) { + /* VSync is being met */ + if (utilisation < mtk_get_dvfs_threshold_min()) + action = KBASE_PM_DVFS_CLOCK_DOWN; + else if (utilisation > mtk_get_dvfs_threshold_max()) + action = KBASE_PM_DVFS_CLOCK_UP; + else + action = KBASE_PM_DVFS_NOP; + } else { + /* VSync is being missed */ + if (utilisation < KBASE_PM_NO_VSYNC_MIN_UTILISATION) + action = KBASE_PM_DVFS_CLOCK_DOWN; + else if (utilisation > KBASE_PM_NO_VSYNC_MAX_UTILISATION) + action = KBASE_PM_DVFS_CLOCK_UP; + else + action = KBASE_PM_DVFS_NOP; + } + + // get a radom action for stress test + if (mtk_get_dvfs_enabled() == 2) + { + get_random_bytes( &random_action, sizeof(random_action)); + random_action = random_action%3; + pr_debug("[MALI] GPU DVFS stress test - genereate random action here: action = %d", random_action); + action = random_action; + } + + kbdev->pm.metrics.utilisation = utilisation; + kbdev->pm.metrics.util_cl_share[0] = util_cl_share[0]; + kbdev->pm.metrics.util_cl_share[1] = util_cl_share[1]; + kbdev->pm.metrics.util_gl_share = util_gl_share; + + g_current_sample_gl_utilization = utilisation; + g_current_sample_cl_utilization[0] = util_cl_share[0]; + g_current_sample_cl_utilization[1] = util_cl_share[1]; + +out: +#if 0 /// def CONFIG_MALI_MIDGARD_DVFS + kbase_platform_dvfs_event(kbdev, utilisation, util_gl_share, util_cl_share); +#endif /*CONFIG_MALI_MIDGARD_DVFS */ + kbdev->pm.metrics.time_idle = 0; + kbdev->pm.metrics.time_busy = 0; + kbdev->pm.metrics.busy_cl[0] = 0; + kbdev->pm.metrics.busy_cl[1] = 0; + kbdev->pm.metrics.busy_gl = 0; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + + return action; +} +KBASE_EXPORT_TEST_API(kbase_pm_get_dvfs_action) + +mali_bool kbase_pm_metrics_is_active(struct kbase_device *kbdev) +{ + mali_bool isactive; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + isactive = (kbdev->pm.metrics.timer_active == MALI_TRUE); + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + + return isactive; +} + +KBASE_EXPORT_TEST_API(kbase_pm_metrics_is_active) + +u32 kbasep_get_gl_utilization(void) +{ + return g_current_sample_gl_utilization; +} +KBASE_EXPORT_TEST_API(kbasep_get_gl_utilization) + +u32 kbasep_get_cl_js0_utilization(void) +{ + return g_current_sample_cl_utilization[0]; +} +KBASE_EXPORT_TEST_API(kbasep_get_cl_js0_utilization) + +u32 kbasep_get_cl_js1_utilization(void) +{ + return g_current_sample_cl_utilization[1]; +} +KBASE_EXPORT_TEST_API(kbasep_get_cl_js1_utilization) + + +//extern unsigned int (*mtk_get_gpu_loading_fp)(void) = kbasep_get_gl_utilization; + +static unsigned int _mtk_gpu_dvfs_index_to_frequency(int iFreq) +{ + unsigned int iCurrentFreqCount; + iCurrentFreqCount =mt_gpufreq_get_dvfs_table_num(); + if(iCurrentFreqCount == 8) // MT6755 + { + switch(iFreq) + { + case 0: + return 728000; + case 1: + return 650000; + case 2: + return 598000; + case 3: + return 520000; + case 4: + return 468000; + case 5: + return 429000; + case 6: + return 390000; + case 7: + return 351000; + default: + return 351000; + } + } + return 351000; + +} + +///===================================================================================== +/// The below function is added by Mediatek +/// In order to provide the debug sysfs command for change parameter dynamiically +///===================================================================================== + +/// 1. For GPU memory usage +static int proc_gpu_memoryusage_show(struct seq_file *m, void *v) +{ + ssize_t ret = 0; + int total_size_in_bytes; + int peak_size_in_bytes; + + total_size_in_bytes = kbase_report_gpu_memory_usage(); + peak_size_in_bytes = kbase_report_gpu_memory_peak(); + + ret = seq_printf(m, "curr: %10u, peak %10u\n", total_size_in_bytes, peak_size_in_bytes); + + return ret; +} + +static int kbasep_gpu_memoryusage_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_memoryusage_show, NULL); +} + +static const struct file_operations kbasep_gpu_memory_usage_debugfs_open = { + .open = kbasep_gpu_memoryusage_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + + +/// 2. For GL/CL utilization +static int proc_gpu_utilization_show(struct seq_file *m, void *v) +{ + unsigned long gl, cl0, cl1; + unsigned int iCurrentFreq; + + iCurrentFreq =mt_gpufreq_get_cur_freq_index(); + + gl = kbasep_get_gl_utilization(); + cl0 = kbasep_get_cl_js0_utilization(); + cl1 = kbasep_get_cl_js1_utilization(); + + seq_printf(m, "gpu/cljs0/cljs1=%lu/%lu/%lu, frequency=%d(kHz)\n", gl, cl0, cl1, _mtk_gpu_dvfs_index_to_frequency(iCurrentFreq)); + + return 0; +} + +static int kbasep_gpu_utilization_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_utilization_show , NULL); +} + +static const struct file_operations kbasep_gpu_utilization_debugfs_fops = { + .open = kbasep_gpu_utilization_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int proc_gpu_powermeter_show(struct seq_file *m, void *v) +{ + + seq_printf(m, "gpu/pm =%d \n", MTKCalPowerIndex()); + + return 0; +} +static int kbasep_gpu_powermeter_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_powermeter_show , NULL); +} +static const struct file_operations kbasep_gpu_powermeter_debugfs_fops = { + .open = kbasep_gpu_powermeter_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +/// 3. For query GPU frequency +static int proc_gpu_frequency_show(struct seq_file *m, void *v) +{ + + unsigned int iCurrentFreq; + + iCurrentFreq =mt_gpufreq_get_cur_freq_index(); + + seq_printf(m, "GPU Frequency: %u(kHz)\n", _mtk_gpu_dvfs_index_to_frequency(iCurrentFreq)); + + return 0; +} + +static int kbasep_gpu_frequency_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_frequency_show , NULL); +} + +static const struct file_operations kbasep_gpu_frequency_debugfs_fops = { + .open = kbasep_gpu_frequency_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + + +/// 4. For query GPU dynamically enable DVFS +static int proc_gpu_dvfs_enabled_show(struct seq_file *m, void *v) +{ + + int dvfs_enabled; + + dvfs_enabled = mtk_get_dvfs_enabled(); + + seq_printf(m, "dvfs_enabled: %d\n", dvfs_enabled); + + return 0; +} + +static int kbasep_gpu_dvfs_enable_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_dvfs_enabled_show , NULL); +} + +static ssize_t kbasep_gpu_dvfs_enable_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(!strncmp(desc, "1", 1)) + g_dvfs_enabled = 1; + else if(!strncmp(desc, "0", 1)) + g_dvfs_enabled = 0; + else if(!strncmp(desc, "2", 1)) + g_dvfs_enabled = 2; + + return count; +} + +static const struct file_operations kbasep_gpu_dvfs_enable_debugfs_fops = { + .open = kbasep_gpu_dvfs_enable_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_dvfs_enable_write, + .release = single_release, +}; + + + +/// 5. For query GPU dynamically enable input boost +static int proc_gpu_input_boost_show(struct seq_file *m, void *v) +{ + + int input_boost_enabled; + + input_boost_enabled = mtk_get_input_boost_enabled(); + + seq_printf(m, "GPU input boost enabled: %d\n", input_boost_enabled); + + return 0; +} + +static int kbasep_gpu_input_boost_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_input_boost_show , NULL); +} + +static ssize_t kbasep_gpu_input_boost_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(!strncmp(desc, "1", 1)) + g_input_boost_enabled = 1; + else if(!strncmp(desc, "0", 1)) + g_input_boost_enabled = 0; + + return count; +} + +static const struct file_operations kbasep_gpu_input_boost_debugfs_fops = { + .open = kbasep_gpu_input_boost_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_input_boost_write, + .release = single_release, +}; + + + +/// 6. For query GPU dynamically set dvfs frequency (ms) +static int proc_gpu_dvfs_freq_show(struct seq_file *m, void *v) +{ + + int dvfs_freq; + + dvfs_freq = mtk_get_dvfs_freq(); + + seq_printf(m, "GPU DVFS freq : %d(ms)\n", dvfs_freq); + + return 0; +} + +static int kbasep_gpu_dvfs_freq_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_dvfs_freq_show , NULL); +} + +static ssize_t kbasep_gpu_dvfs_freq_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + int dvfs_freq = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(sscanf(desc, "%d", &dvfs_freq) == 1) + g_dvfs_freq = dvfs_freq; + else + pr_debug("[MALI] warning! echo [dvfs_freq(ms)] > /proc/mali/dvfs_freq\n"); + + return count; +} + +static const struct file_operations kbasep_gpu_dvfs_freq_debugfs_fops = { + .open = kbasep_gpu_dvfs_freq_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_dvfs_freq_write, + .release = single_release, +}; + + + +/// 7.For query GPU dynamically set dvfs threshold +static int proc_gpu_dvfs_threshold_show(struct seq_file *m, void *v) +{ + + int threshold_max, threshold_min; + + threshold_max = mtk_get_dvfs_threshold_max(); + threshold_min = mtk_get_dvfs_threshold_min(); + + seq_printf(m, "GPU DVFS threshold : max:%d min:%d\n", threshold_max, threshold_min); + + return 0; +} + +static int kbasep_gpu_dvfs_threshold_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_dvfs_threshold_show , NULL); +} + +static ssize_t kbasep_gpu_dvfs_threshold_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + int threshold_max, threshold_min; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(sscanf(desc, "%d %d", &threshold_max, &threshold_min) == 2) + { + g_dvfs_threshold_max = threshold_max; + g_dvfs_threshold_min = threshold_min; + } + else + pr_debug("[MALI] warning! echo [dvfs_threshold_max] [dvfs_threshold_min] > /proc/mali/dvfs_threshold\n"); + + return count; +} + +static const struct file_operations kbasep_gpu_dvfs_threshold_debugfs_fops = { + .open = kbasep_gpu_dvfs_threshold_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_dvfs_threshold_write, + .release = single_release, +}; + + + +/// 8.For query GPU dynamically set dvfs deferred count +static int proc_gpu_dvfs_deferred_count_show(struct seq_file *m, void *v) +{ + + int deferred_count; + + deferred_count = mtk_get_dvfs_deferred_count(); + + seq_printf(m, "GPU DVFS deferred_count : %d\n", deferred_count); + + return 0; +} + +static int kbasep_gpu_dvfs_deferred_count_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_dvfs_deferred_count_show , NULL); +} + +static ssize_t kbasep_gpu_dvfs_deferred_count_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + int dvfs_deferred_count; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(sscanf(desc, "%d", &dvfs_deferred_count) == 1) + g_dvfs_deferred_count = dvfs_deferred_count; + else + pr_debug("[MALI] warning! echo [dvfs_deferred_count] > /proc/mali/dvfs_deferred_count\n"); + + return count; +} + +static const struct file_operations kbasep_gpu_dvfs_deferred_count_debugfs_fops = { + .open = kbasep_gpu_dvfs_deferred_count_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_dvfs_deferred_count_write, + .release = single_release, +}; + + +/// 9. For query the support command +static int proc_gpu_help_show(struct seq_file *m, void *v) +{ + seq_printf(m, "======================================================================\n"); + seq_printf(m, "A.For Query GPU/CPU related Command:\n"); + seq_printf(m, " cat /proc/mali/utilization\n"); + seq_printf(m, " cat /proc/mali/frequency\n"); + seq_printf(m, " cat /proc/mali/memory_usage\n"); + seq_printf(m, " cat /proc/mali/powermeter\n"); + seq_printf(m, " cat /proc/gpufreq/gpufreq_var_dump\n"); + seq_printf(m, " cat /proc/pm_init/ckgen_meter_test\n"); + seq_printf(m, " cat /proc/cpufreq/cpufreq_cur_freq\n"); + seq_printf(m, "======================================================================\n"); + seq_printf(m, "B.For Fix GPU Frequency:\n"); + seq_printf(m, " echo > (728000, 520000, 312000) /proc/gpufreq/gpufreq_opp_freq\n"); + seq_printf(m, " echo 0 > /proc/gpufreq/gpufreq_opp_freq(re-enable GPU DVFS)\n"); + seq_printf(m, "C.For Turn On/Off CPU core number:\n"); + seq_printf(m, " echo (1, 0) > /sys/devices/system/cpu/cpu1/online\n"); + seq_printf(m, " echo (1, 0) > /sys/devices/system/cpu/cpu2/online\n"); + seq_printf(m, " echo (1, 0) > /sys/devices/system/cpu/cpuN/online\n"); + seq_printf(m, "D.For CPU Performance mode(Force CPU to run at highest speed:\n"); + seq_printf(m, " echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor\n"); + seq_printf(m, " echo interactive > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor(re-enable CPU DVFS)\n"); + seq_printf(m, "==============================================================================================\n"); + seq_printf(m, "E.For GPU advanced debugging command:\n"); + seq_printf(m, " echo [dvfs_freq(ms)] > /proc/mali/dvfs_freq\n"); + seq_printf(m, " echo [dvfs_thr_max] [dvfs_thr_min] > /proc/mali/dvfs_threshold\n"); + seq_printf(m, " echo [dvfs_deferred_count] > /proc/mali/dvfs_deferred_count\n"); + seq_printf(m, "==============================================================================================\n"); + + return 0; +} + +static int kbasep_gpu_help_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_help_show , NULL); +} + +static const struct file_operations kbasep_gpu_help_debugfs_fops = { + .open = kbasep_gpu_help_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *mali_pentry; + +void proc_mali_register(void) +{ + mali_pentry = proc_mkdir("mali", NULL); + + if (!mali_pentry) + return; + + proc_create("help", 0, mali_pentry, &kbasep_gpu_help_debugfs_fops); + proc_create("memory_usage", 0, mali_pentry, &kbasep_gpu_memory_usage_debugfs_open); + proc_create("utilization", 0, mali_pentry, &kbasep_gpu_utilization_debugfs_fops); + proc_create("frequency", 0, mali_pentry, &kbasep_gpu_frequency_debugfs_fops); + proc_create("powermeter", 0, mali_pentry, &kbasep_gpu_powermeter_debugfs_fops); + proc_create("dvfs_enable", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_dvfs_enable_debugfs_fops); + proc_create("input_boost", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_input_boost_debugfs_fops); + proc_create("dvfs_freq", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_dvfs_freq_debugfs_fops); + proc_create("dvfs_threshold", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_dvfs_threshold_debugfs_fops); + proc_create("dvfs_deferred_count", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_dvfs_deferred_count_debugfs_fops); +} +void proc_mali_unregister(void) +{ + if (!mali_pentry) + return; + + remove_proc_entry("help", mali_pentry); + remove_proc_entry("memory_usage", mali_pentry); + remove_proc_entry("utilization", mali_pentry); + remove_proc_entry("frequency", mali_pentry); + remove_proc_entry("powermeter", mali_pentry); + remove_proc_entry("mali", NULL); + mali_pentry = NULL; +} +#else +#define proc_mali_register() do{}while(0) +#define proc_mali_unregister() do{}while(0) +#endif /// CONFIG_PROC_FS + +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics_dummy.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics_dummy.c new file mode 100644 index 0000000000000000000000000000000000000000..7823d824f5a32888b0367904681b96013ad8ffbb --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics_dummy.c @@ -0,0 +1,41 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_metrics_dummy.c + * Dummy Metrics for power management. + */ + +#include +#include + +#if KBASE_PM_EN +void kbase_pm_register_vsync_callback(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* no VSync metrics will be available */ + kbdev->pm.metrics.platform_data = NULL; +} + +void kbase_pm_unregister_vsync_callback(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); +} +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.c new file mode 100644 index 0000000000000000000000000000000000000000..06f033c595238c7683848ac08bf286addb839a42 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.c @@ -0,0 +1,822 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_policy.c + * Power policy API implementations + */ + +#include +#include +#include +#include + +#if KBASE_PM_EN + +extern const struct kbase_pm_policy kbase_pm_always_on_policy_ops; +extern const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops; +extern const struct kbase_pm_policy kbase_pm_demand_policy_ops; + +#if !MALI_CUSTOMER_RELEASE +extern const struct kbase_pm_policy kbase_pm_fast_start_policy_ops; +extern const struct kbase_pm_policy kbase_pm_demand_always_powered_policy_ops; +#endif + +static const struct kbase_pm_policy *const policy_list[] = { +#ifdef CONFIG_MALI_NO_MALI + &kbase_pm_always_on_policy_ops, + &kbase_pm_demand_policy_ops, + &kbase_pm_coarse_demand_policy_ops, +#if !MALI_CUSTOMER_RELEASE + &kbase_pm_demand_always_powered_policy_ops, + &kbase_pm_fast_start_policy_ops, +#endif +#else /* CONFIG_MALI_NO_MALI */ + &kbase_pm_demand_policy_ops, + &kbase_pm_always_on_policy_ops, + &kbase_pm_coarse_demand_policy_ops, +#if !MALI_CUSTOMER_RELEASE + &kbase_pm_demand_always_powered_policy_ops, + &kbase_pm_fast_start_policy_ops, +#endif +#endif /* CONFIG_MALI_NO_MALI */ +}; + +/** The number of policies available in the system. + * This is derived from the number of functions listed in policy_get_functions. + */ +#define POLICY_COUNT (sizeof(policy_list)/sizeof(*policy_list)) + + +/* Function IDs for looking up Timeline Trace codes in kbase_pm_change_state_trace_code */ +enum kbase_pm_func_id { + KBASE_PM_FUNC_ID_REQUEST_CORES_START, + KBASE_PM_FUNC_ID_REQUEST_CORES_END, + KBASE_PM_FUNC_ID_RELEASE_CORES_START, + KBASE_PM_FUNC_ID_RELEASE_CORES_END, + /* Note: kbase_pm_unrequest_cores() is on the slow path, and we neither + * expect to hit it nor tend to hit it very much anyway. We can detect + * whether we need more instrumentation by a difference between + * PM_CHECKTRANS events and PM_SEND/HANDLE_EVENT. */ + + /* Must be the last */ + KBASE_PM_FUNC_ID_COUNT +}; + + +/* State changes during request/unrequest/release-ing cores */ +enum { + KBASE_PM_CHANGE_STATE_SHADER = (1u << 0), + KBASE_PM_CHANGE_STATE_TILER = (1u << 1), + + /* These two must be last */ + KBASE_PM_CHANGE_STATE_MASK = (KBASE_PM_CHANGE_STATE_TILER|KBASE_PM_CHANGE_STATE_SHADER), + KBASE_PM_CHANGE_STATE_COUNT = KBASE_PM_CHANGE_STATE_MASK + 1 +}; +typedef u32 kbase_pm_change_state; + + +#ifdef CONFIG_MALI_TRACE_TIMELINE +/* Timeline Trace code lookups for each function */ +static u32 kbase_pm_change_state_trace_code[KBASE_PM_FUNC_ID_COUNT][KBASE_PM_CHANGE_STATE_COUNT] = { + /* kbase_pm_request_cores */ + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][0] = 0, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_START, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_START, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_SHADER|KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_START, + + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][0] = 0, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_END, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_END, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_SHADER|KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_END, + + /* kbase_pm_release_cores */ + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][0] = 0, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_START, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_START, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_SHADER|KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_START, + + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][0] = 0, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_END, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_END, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_SHADER|KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_END +}; + +STATIC INLINE void kbase_timeline_pm_cores_func(struct kbase_device *kbdev, + enum kbase_pm_func_id func_id, + kbase_pm_change_state state) +{ + int trace_code; + + KBASE_DEBUG_ASSERT(func_id >= 0 && func_id < KBASE_PM_FUNC_ID_COUNT); + KBASE_DEBUG_ASSERT(state != 0 && (state & KBASE_PM_CHANGE_STATE_MASK) == state); + + trace_code = kbase_pm_change_state_trace_code[func_id][state]; + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code); +} + +#else /* CONFIG_MALI_TRACE_TIMELINE */ +STATIC INLINE void kbase_timeline_pm_cores_func(struct kbase_device *kbdev, + enum kbase_pm_func_id func_id, kbase_pm_change_state state) +{ +} + +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +static enum hrtimer_restart kbasep_pm_do_gpu_poweroff_callback(struct hrtimer *timer) +{ + struct kbase_device *kbdev; + + kbdev = container_of(timer, struct kbase_device, pm.gpu_poweroff_timer); + + /* It is safe for this call to do nothing if the work item is already queued. + * The worker function will read the must up-to-date state of kbdev->pm.gpu_poweroff_pending + * under lock. + * + * If a state change occurs while the worker function is processing, this + * call will succeed as a work item can be requeued once it has started + * processing. + */ + if (kbdev->pm.gpu_poweroff_pending) + queue_work(kbdev->pm.gpu_poweroff_wq, &kbdev->pm.gpu_poweroff_work); + + if (kbdev->pm.shader_poweroff_pending) { + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + if (kbdev->pm.shader_poweroff_pending) { + kbdev->pm.shader_poweroff_pending_time--; + + KBASE_DEBUG_ASSERT(kbdev->pm.shader_poweroff_pending_time >= 0); + + if (kbdev->pm.shader_poweroff_pending_time == 0) { + u64 prev_shader_state = kbdev->pm.desired_shader_state; + + kbdev->pm.desired_shader_state &= ~kbdev->pm.shader_poweroff_pending; + kbdev->pm.shader_poweroff_pending = 0; + + if (prev_shader_state != kbdev->pm.desired_shader_state || + kbdev->pm.ca_in_transition != MALI_FALSE) { + mali_bool cores_are_available; + + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_START); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_END); + + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); + } + } + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + } + + if (kbdev->pm.poweroff_timer_needed) { + hrtimer_add_expires(timer, kbdev->pm.gpu_poweroff_time); + + return HRTIMER_RESTART; + } + + return HRTIMER_NORESTART; +} + +static void kbasep_pm_do_gpu_poweroff_wq(struct work_struct *data) +{ + unsigned long flags; + struct kbase_device *kbdev; + mali_bool do_poweroff = MALI_FALSE; + + kbdev = container_of(data, struct kbase_device, pm.gpu_poweroff_work); + + mutex_lock(&kbdev->pm.lock); + + if (kbdev->pm.gpu_poweroff_pending == 0) { + mutex_unlock(&kbdev->pm.lock); + return; + } + + kbdev->pm.gpu_poweroff_pending--; + + if (kbdev->pm.gpu_poweroff_pending > 0) { + mutex_unlock(&kbdev->pm.lock); + return; + } + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_poweroff_pending == 0); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + /* Only power off the GPU if a request is still pending */ + if (kbdev->pm.pm_current_policy->get_core_active(kbdev) == MALI_FALSE) + do_poweroff = MALI_TRUE; + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + if (do_poweroff != MALI_FALSE) { + kbdev->pm.poweroff_timer_needed = MALI_FALSE; + /* Power off the GPU */ + kbase_pm_do_poweroff(kbdev, MALI_FALSE); + hrtimer_cancel(&kbdev->pm.gpu_poweroff_timer); + } + + mutex_unlock(&kbdev->pm.lock); +} + +mali_error kbase_pm_policy_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + kbdev->pm.gpu_poweroff_wq = alloc_workqueue("kbase_pm_do_poweroff", WQ_HIGHPRI | WQ_UNBOUND, 1); + if (NULL == kbdev->pm.gpu_poweroff_wq) + return MALI_ERROR_OUT_OF_MEMORY; + INIT_WORK(&kbdev->pm.gpu_poweroff_work, kbasep_pm_do_gpu_poweroff_wq); + + hrtimer_init(&kbdev->pm.gpu_poweroff_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->pm.gpu_poweroff_timer.function = kbasep_pm_do_gpu_poweroff_callback; + + kbdev->pm.pm_current_policy = policy_list[0]; + + kbdev->pm.pm_current_policy->init(kbdev); + + kbdev->pm.gpu_poweroff_time = HR_TIMER_DELAY_NSEC(kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS)); + + kbdev->pm.poweroff_shader_ticks = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER); + kbdev->pm.poweroff_gpu_ticks = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU); + + return MALI_ERROR_NONE; +} + +void kbase_pm_policy_term(struct kbase_device *kbdev) +{ + kbdev->pm.pm_current_policy->term(kbdev); +} + +void kbase_pm_cancel_deferred_poweroff(struct kbase_device *kbdev) +{ + unsigned long flags; + + lockdep_assert_held(&kbdev->pm.lock); + + kbdev->pm.poweroff_timer_needed = MALI_FALSE; + hrtimer_cancel(&kbdev->pm.gpu_poweroff_timer); + + /* If wq is already running but is held off by pm.lock, make sure it has no effect */ + kbdev->pm.gpu_poweroff_pending = 0; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + kbdev->pm.shader_poweroff_pending = 0; + kbdev->pm.shader_poweroff_pending_time = 0; + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +void kbase_pm_update_active(struct kbase_device *kbdev) +{ + unsigned long flags; + mali_bool active; + + lockdep_assert_held(&kbdev->pm.lock); + + /* pm_current_policy will never be NULL while pm.lock is held */ + KBASE_DEBUG_ASSERT(kbdev->pm.pm_current_policy); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + active = kbdev->pm.pm_current_policy->get_core_active(kbdev); + + if (active != MALI_FALSE) { + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + if (kbdev->pm.gpu_poweroff_pending) { + /* Cancel any pending power off request */ + kbdev->pm.gpu_poweroff_pending = 0; + + /* If a request was pending then the GPU was still powered, so no need to continue */ + return; + } + + if (!kbdev->pm.poweroff_timer_needed && !kbdev->pm.gpu_powered) { + kbdev->pm.poweroff_timer_needed = MALI_TRUE; + hrtimer_start(&kbdev->pm.gpu_poweroff_timer, kbdev->pm.gpu_poweroff_time, HRTIMER_MODE_REL); + } + + /* Power on the GPU and any cores requested by the policy */ + kbase_pm_do_poweron(kbdev, MALI_FALSE); + } else { + /* It is an error for the power policy to power off the GPU + * when there are contexts active */ + KBASE_DEBUG_ASSERT(kbdev->pm.active_count == 0); + + if (kbdev->pm.shader_poweroff_pending) { + kbdev->pm.shader_poweroff_pending = 0; + kbdev->pm.shader_poweroff_pending_time = 0; + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + + /* Request power off */ + if (kbdev->pm.gpu_powered) { + kbdev->pm.gpu_poweroff_pending = kbdev->pm.poweroff_gpu_ticks; + if (!kbdev->pm.poweroff_timer_needed) { + /* Start timer if not running (eg if power policy has been changed from always_on + * to something else). This will ensure the GPU is actually powered off */ + kbdev->pm.poweroff_timer_needed = MALI_TRUE; + hrtimer_start(&kbdev->pm.gpu_poweroff_timer, kbdev->pm.gpu_poweroff_time, HRTIMER_MODE_REL); + } + } + } +} + +void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev) +{ + u64 desired_bitmap; + mali_bool cores_are_available; + + lockdep_assert_held(&kbdev->pm.power_change_lock); + + if (kbdev->pm.pm_current_policy == NULL) + return; + + desired_bitmap = kbdev->pm.pm_current_policy->get_core_mask(kbdev); + desired_bitmap &= kbase_pm_ca_get_core_mask(kbdev); + + /* Enable core 0 if tiler required, regardless of core availability */ + if (kbdev->tiler_needed_cnt > 0 || kbdev->tiler_inuse_cnt > 0) + desired_bitmap |= 1; + + if (kbdev->pm.desired_shader_state != desired_bitmap) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_DESIRED, NULL, NULL, 0u, (u32)desired_bitmap); + + /* Are any cores being powered on? */ + if (~kbdev->pm.desired_shader_state & desired_bitmap || + kbdev->pm.ca_in_transition != MALI_FALSE) { + /* Check if we are powering off any cores before updating shader state */ + if (kbdev->pm.desired_shader_state & ~desired_bitmap) { + /* Start timer to power off cores */ + kbdev->pm.shader_poweroff_pending |= (kbdev->pm.desired_shader_state & ~desired_bitmap); + kbdev->pm.shader_poweroff_pending_time = kbdev->pm.poweroff_shader_ticks; + } + + kbdev->pm.desired_shader_state = desired_bitmap; + + /* If any cores are being powered on, transition immediately */ + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + } else if (kbdev->pm.desired_shader_state & ~desired_bitmap) { + /* Start timer to power off cores */ + kbdev->pm.shader_poweroff_pending |= (kbdev->pm.desired_shader_state & ~desired_bitmap); + kbdev->pm.shader_poweroff_pending_time = kbdev->pm.poweroff_shader_ticks; + } else if (kbdev->pm.active_count == 0 && desired_bitmap != 0 && kbdev->pm.poweroff_timer_needed) { + /* If power policy is keeping cores on despite there being no + * active contexts then disable poweroff timer as it isn't + * required. + * Only reset poweroff_timer_needed if we're not in the middle + * of the power off callback */ + kbdev->pm.poweroff_timer_needed = MALI_FALSE; + hrtimer_try_to_cancel(&kbdev->pm.gpu_poweroff_timer); + } + + /* Ensure timer does not power off wanted cores and make sure to power off unwanted cores */ + if (kbdev->pm.shader_poweroff_pending != 0) { + kbdev->pm.shader_poweroff_pending &= ~(kbdev->pm.desired_shader_state & desired_bitmap); + if (kbdev->pm.shader_poweroff_pending == 0) + kbdev->pm.shader_poweroff_pending_time = 0; + } + + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); +} + +void kbase_pm_update_cores_state(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + kbase_pm_update_cores_state_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +int kbase_pm_list_policies(const struct kbase_pm_policy * const **list) +{ + if (!list) + return POLICY_COUNT; + + *list = policy_list; + + return POLICY_COUNT; +} + +KBASE_EXPORT_TEST_API(kbase_pm_list_policies) + +const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return kbdev->pm.pm_current_policy; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_policy) + +void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_policy *new_policy) +{ + const struct kbase_pm_policy *old_policy; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(new_policy != NULL); + + KBASE_TRACE_ADD(kbdev, PM_SET_POLICY, NULL, NULL, 0u, new_policy->id); + + /* During a policy change we pretend the GPU is active */ + /* A suspend won't happen here, because we're in a syscall from a userspace thread */ + kbase_pm_context_active(kbdev); + + mutex_lock(&kbdev->pm.lock); + + /* Remove the policy to prevent IRQ handlers from working on it */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + old_policy = kbdev->pm.pm_current_policy; + kbdev->pm.pm_current_policy = NULL; + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + KBASE_TRACE_ADD(kbdev, PM_CURRENT_POLICY_TERM, NULL, NULL, 0u, old_policy->id); + if (old_policy->term) + old_policy->term(kbdev); + + KBASE_TRACE_ADD(kbdev, PM_CURRENT_POLICY_INIT, NULL, NULL, 0u, new_policy->id); + if (new_policy->init) + new_policy->init(kbdev); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbdev->pm.pm_current_policy = new_policy; + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* If any core power state changes were previously attempted, but couldn't + * be made because the policy was changing (current_policy was NULL), then + * re-try them here. */ + kbase_pm_update_active(kbdev); + kbase_pm_update_cores_state(kbdev); + + mutex_unlock(&kbdev->pm.lock); + + /* Now the policy change is finished, we release our fake context active reference */ + kbase_pm_context_idle(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_set_policy) + +/** Check whether a state change has finished, and trace it as completed */ +STATIC void kbase_pm_trace_check_and_finish_state_change(struct kbase_device *kbdev) +{ + if ((kbdev->shader_available_bitmap & kbdev->pm.desired_shader_state) == kbdev->pm.desired_shader_state && + (kbdev->tiler_available_bitmap & kbdev->pm.desired_tiler_state) == kbdev->pm.desired_tiler_state) + kbase_timeline_pm_check_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); +} + +void kbase_pm_request_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + unsigned long flags; + u64 cores; + + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + cores = shader_cores; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + + /* It should be almost impossible for this to overflow. It would require 2^32 atoms + * to request a particular core, which would require 2^24 contexts to submit. This + * would require an amount of memory that is impossible on a 32-bit system and + * extremely unlikely on a 64-bit system. */ + int cnt = ++kbdev->shader_needed_cnt[bitnum]; + + if (1 == cnt) { + kbdev->shader_needed_bitmap |= bit; + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + cores &= ~bit; + } + + if (tiler_required != MALI_FALSE) { + ++kbdev->tiler_needed_cnt; + + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt != 0); + + /* For tiler jobs, we must make sure that core 0 is not turned off if it's already on. + * However, it's safe for core 0 to be left off and turned on later whilst a tiler job + * is running. Hence, we don't need to update the cores state immediately. Also, + * attempts to turn off cores will always check the tiler_needed/inuse state first anyway. + * + * Finally, kbase_js_choose_affinity() ensures core 0 is always requested for tiler jobs + * anyway. Hence when there's only a tiler job in the system, this will still cause + * kbase_pm_update_cores_state_nolock() to be called. + * + * Note that we still need to keep track of tiler_needed/inuse_cnt, to ensure that + * kbase_pm_update_cores_state_nolock() can override the core availability policy and + * force core 0 to be powered when a tiler job is in the system. */ + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_REQUEST_CHANGE_SHADER_NEEDED, NULL, NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + kbase_timeline_pm_cores_func(kbdev, KBASE_PM_FUNC_ID_REQUEST_CORES_START, change_gpu_state); + kbase_pm_update_cores_state_nolock(kbdev); + kbase_timeline_pm_cores_func(kbdev, KBASE_PM_FUNC_ID_REQUEST_CORES_END, change_gpu_state); + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_cores) + +void kbase_pm_unrequest_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + unsigned long flags; + + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_needed_cnt[bitnum] > 0); + + cnt = --kbdev->shader_needed_cnt[bitnum]; + + if (0 == cnt) { + kbdev->shader_needed_bitmap &= ~bit; + + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + shader_cores &= ~bit; + } + + if (tiler_required != MALI_FALSE) { + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt > 0); + + --kbdev->tiler_needed_cnt; + + /* Whilst tiler jobs must not allow core 0 to be turned off, we don't need to make an + * extra call to kbase_pm_update_cores_state_nolock() to ensure core 0 is turned off + * when the last tiler job unrequests cores: kbase_js_choose_affinity() ensures core 0 + * was originally requested for tiler jobs. Hence when there's only a tiler job in the + * system, this will still cause kbase_pm_update_cores_state_nolock() to be called. */ + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_UNREQUEST_CHANGE_SHADER_NEEDED, NULL, NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + kbase_pm_update_cores_state_nolock(kbdev); + + /* Trace that any state change effectively completes immediately - + * no-one will wait on the state change */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_unrequest_cores) + +enum kbase_pm_cores_ready kbase_pm_register_inuse_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + unsigned long flags; + u64 prev_shader_needed; /* Just for tracing */ + u64 prev_shader_inuse; /* Just for tracing */ + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + prev_shader_needed = kbdev->shader_needed_bitmap; + prev_shader_inuse = kbdev->shader_inuse_bitmap; + + /* If desired_shader_state does not contain the requested cores, then power + * management is not attempting to powering those cores (most likely + * due to core availability policy) and a new job affinity must be + * chosen */ + if ((kbdev->pm.desired_shader_state & shader_cores) != shader_cores) { + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + return KBASE_NEW_AFFINITY; + } + + if ((kbdev->shader_available_bitmap & shader_cores) != shader_cores || + (tiler_required != MALI_FALSE && !kbdev->tiler_available_bitmap)) { + /* Trace ongoing core transition */ + kbase_timeline_pm_l2_transition_start(kbdev); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + return KBASE_CORES_NOT_READY; + } + + /* If we started to trace a state change, then trace it has being finished + * by now, at the very latest */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + /* Trace core transition done */ + kbase_timeline_pm_l2_transition_done(kbdev); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_needed_cnt[bitnum] > 0); + + cnt = --kbdev->shader_needed_cnt[bitnum]; + + if (0 == cnt) + kbdev->shader_needed_bitmap &= ~bit; + + /* shader_inuse_cnt should not overflow because there can only be a + * very limited number of jobs on the h/w at one time */ + + kbdev->shader_inuse_cnt[bitnum]++; + kbdev->shader_inuse_bitmap |= bit; + + shader_cores &= ~bit; + } + + if (tiler_required != MALI_FALSE) { + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt > 0); + + --kbdev->tiler_needed_cnt; + + kbdev->tiler_inuse_cnt++; + + KBASE_DEBUG_ASSERT(kbdev->tiler_inuse_cnt != 0); + } + + if (prev_shader_needed != kbdev->shader_needed_bitmap) + KBASE_TRACE_ADD(kbdev, PM_REGISTER_CHANGE_SHADER_NEEDED, NULL, NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + if (prev_shader_inuse != kbdev->shader_inuse_bitmap) + KBASE_TRACE_ADD(kbdev, PM_REGISTER_CHANGE_SHADER_INUSE, NULL, NULL, 0u, (u32) kbdev->shader_inuse_bitmap); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + return KBASE_CORES_READY; +} + +KBASE_EXPORT_TEST_API(kbase_pm_register_inuse_cores) + +void kbase_pm_release_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + unsigned long flags; + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_inuse_cnt[bitnum] > 0); + + cnt = --kbdev->shader_inuse_cnt[bitnum]; + + if (0 == cnt) { + kbdev->shader_inuse_bitmap &= ~bit; + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + shader_cores &= ~bit; + } + + if (tiler_required != MALI_FALSE) { + KBASE_DEBUG_ASSERT(kbdev->tiler_inuse_cnt > 0); + + --kbdev->tiler_inuse_cnt; + + /* Whilst tiler jobs must not allow core 0 to be turned off, we don't need to make an + * extra call to kbase_pm_update_cores_state_nolock() to ensure core 0 is turned off + * when the last tiler job finishes: kbase_js_choose_affinity() ensures core 0 was + * originally requested for tiler jobs. Hence when there's only a tiler job in the + * system, this will still cause kbase_pm_update_cores_state_nolock() to be called */ + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_RELEASE_CHANGE_SHADER_INUSE, NULL, NULL, 0u, (u32) kbdev->shader_inuse_bitmap); + + kbase_timeline_pm_cores_func(kbdev, KBASE_PM_FUNC_ID_RELEASE_CORES_START, change_gpu_state); + kbase_pm_update_cores_state_nolock(kbdev); + kbase_timeline_pm_cores_func(kbdev, KBASE_PM_FUNC_ID_RELEASE_CORES_END, change_gpu_state); + + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_cores) + +void kbase_pm_request_cores_sync(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + kbase_pm_request_cores(kbdev, tiler_required, shader_cores); + + kbase_pm_check_transitions_sync(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_cores_sync) + +void kbase_pm_request_l2_caches(struct kbase_device *kbdev) +{ + unsigned long flags; + u32 prior_l2_users_count; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + prior_l2_users_count = kbdev->l2_users_count++; + + KBASE_DEBUG_ASSERT(kbdev->l2_users_count != 0); + + /* if the GPU is reset while the l2 is on, l2 will be off but prior_l2_users_count will be > 0 + * l2_available_bitmap will have been set to 0 though by kbase_pm_init_hw */ + if (!prior_l2_users_count || !kbdev->l2_available_bitmap) + kbase_pm_check_transitions_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + wait_event(kbdev->pm.l2_powered_wait, kbdev->pm.l2_powered == 1); + + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_l2_caches) + +void kbase_pm_request_l2_caches_l2_is_on(struct kbase_device *kbdev) +{ + unsigned long flags; + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + kbdev->l2_users_count++; + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_l2_caches_l2_is_on) + +void kbase_pm_release_l2_caches(struct kbase_device *kbdev) +{ + unsigned long flags; + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + KBASE_DEBUG_ASSERT(kbdev->l2_users_count > 0); + + --kbdev->l2_users_count; + + if (!kbdev->l2_users_count) { + kbase_pm_check_transitions_nolock(kbdev); + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_l2_caches) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.h new file mode 100644 index 0000000000000000000000000000000000000000..4a8cc44b6308fc6cedc78e96d071b00eea0c7e1c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.h @@ -0,0 +1,277 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_policy.h + * Power policy API definitions + */ + +#ifndef _KBASE_PM_POLICY_H_ +#define _KBASE_PM_POLICY_H_ + +/** List of policy IDs */ +enum kbase_pm_policy_id { + KBASE_PM_POLICY_ID_DEMAND = 1, + KBASE_PM_POLICY_ID_ALWAYS_ON, + KBASE_PM_POLICY_ID_COARSE_DEMAND, +#if !MALI_CUSTOMER_RELEASE + KBASE_PM_POLICY_ID_DEMAND_ALWAYS_POWERED, + KBASE_PM_POLICY_ID_FAST_START +#endif +}; + +typedef u32 kbase_pm_policy_flags; + +/** Power policy structure. + * + * Each power policy exposes a (static) instance of this structure which contains function pointers to the + * policy's methods. + */ +typedef struct kbase_pm_policy { + /** The name of this policy */ + char *name; + + /** Function called when the policy is selected + * + * This should initialize the kbdev->pm.pm_policy_data structure. It should not attempt + * to make any changes to hardware state. + * + * It is undefined what state the cores are in when the function is called. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + void (*init)(struct kbase_device *kbdev); + + /** Function called when the policy is unselected. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + void (*term)(struct kbase_device *kbdev); + + /** Function called to get the current shader core mask + * + * The returned mask should meet or exceed (kbdev->shader_needed_bitmap | kbdev->shader_inuse_bitmap). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The mask of shader cores to be powered */ + u64 (*get_core_mask)(struct kbase_device *kbdev); + + /** Function called to get the current overall GPU power state + * + * This function should consider the state of kbdev->pm.active_count. If this count is greater than 0 then + * there is at least one active context on the device and the GPU should be powered. If it is equal to 0 + * then there are no active contexts and the GPU could be powered off if desired. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_TRUE if the GPU should be powered, MALI_FALSE otherwise */ + mali_bool (*get_core_active) (struct kbase_device *kbdev); + + /** Field indicating flags for this policy */ + kbase_pm_policy_flags flags; + + /** Field indicating an ID for this policy. This is not necessarily the + * same as its index in the list returned by kbase_pm_list_policies(). + * It is used purely for debugging. */ + enum kbase_pm_policy_id id; +} kbase_pm_policy; + +/** Initialize power policy framework + * + * Must be called before calling any other policy function + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE if the power policy framework was successfully initialized. + */ +mali_error kbase_pm_policy_init(struct kbase_device *kbdev); + +/** Terminate power policy framework + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_policy_term(struct kbase_device *kbdev); + +/** Update the active power state of the GPU + * Calls into the current power policy + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_update_active(struct kbase_device *kbdev); + +/** Update the desired core state of the GPU + * Calls into the current power policy + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_update_cores(struct kbase_device *kbdev); + +/** Get the current policy. + * Returns the policy that is currently active. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The current policy + */ +const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev); + +/** Change the policy to the one specified. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param policy The policy to change to (valid pointer returned from @ref kbase_pm_list_policies) + */ +void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_policy *policy); + +/** Retrieve a static list of the available policies. + * @param[out] policies An array pointer to take the list of policies. This may be NULL. + * The contents of this array must not be modified. + * + * @return The number of policies + */ +int kbase_pm_list_policies(const struct kbase_pm_policy * const **policies); + + +enum kbase_pm_cores_ready { + KBASE_CORES_NOT_READY = 0, + KBASE_NEW_AFFINITY = 1, + KBASE_CORES_READY = 2 +}; + + +/** Synchronous variant of kbase_pm_request_cores() + * + * When this function returns, the @a shader_cores will be in the READY state. + * + * This is safe variant of kbase_pm_check_transitions_sync(): it handles the + * work of ensuring the requested cores will remain powered until a matching + * call to kbase_pm_unrequest_cores()/kbase_pm_release_cores() (as appropriate) + * is made. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores which are necessary for the job + */ + +void kbase_pm_request_cores_sync(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Mark one or more cores as being required for jobs to be submitted. + * + * This function is called by the job scheduler to mark one or more cores + * as being required to submit jobs that are ready to run. + * + * The cores requested are reference counted and a subsequent call to @ref kbase_pm_register_inuse_cores or + * @ref kbase_pm_unrequest_cores should be made to dereference the cores as being 'needed'. + * + * The active power policy will meet or exceed the requirements of the + * requested cores in the system. Any core transitions needed will be begun + * immediately, but they might not complete/the cores might not be available + * until a Power Management IRQ. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores which are necessary for the job + * + * @return MALI_ERROR_NONE if the cores were successfully requested. + */ +void kbase_pm_request_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Unmark one or more cores as being required for jobs to be submitted. + * + * This function undoes the effect of @ref kbase_pm_request_cores. It should be used when a job is not + * going to be submitted to the hardware (e.g. the job is cancelled before it is enqueued). + * + * The active power policy will meet or exceed the requirements of the + * requested cores in the system. Any core transitions needed will be begun + * immediately, but they might not complete until a Power Management IRQ. + * + * The policy may use this as an indication that it can power down cores. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores (as given to @ref kbase_pm_request_cores) + */ +void kbase_pm_unrequest_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Register a set of cores as in use by a job. + * + * This function should be called after @ref kbase_pm_request_cores when the job is about to be submitted to + * the hardware. It will check that the necessary cores are available and if so update the 'needed' and 'inuse' + * bitmasks to reflect that the job is now committed to being run. + * + * If the necessary cores are not currently available then the function will return MALI_FALSE and have no effect. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores (as given to @ref kbase_pm_request_cores) + * + * @return MALI_TRUE if the job can be submitted to the hardware or MALI_FALSE if the job is not ready to run. + */ +enum kbase_pm_cores_ready kbase_pm_register_inuse_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Release cores after a job has run. + * + * This function should be called when a job has finished running on the hardware. A call to @ref + * kbase_pm_register_inuse_cores must have previously occurred. The reference counts of the specified cores will be + * decremented which may cause the bitmask of 'inuse' cores to be reduced. The power policy may then turn off any + * cores which are no longer 'inuse'. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores (as given to @ref kbase_pm_register_inuse_cores) + */ +void kbase_pm_release_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Request the use of l2 caches for all core groups, power up, wait and prevent the power manager from + * powering down the l2 caches. + * + * This tells the power management that the caches should be powered up, and they + * should remain powered, irrespective of the usage of shader cores. This does not + * return until the l2 caches are powered up. + * + * The caller must call @ref kbase_pm_release_l2_caches when they are finished to + * allow normal power management of the l2 caches to resume. + * + * This should only be used when power management is active. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_l2_caches(struct kbase_device *kbdev); + +/** Increment the count of l2 users but do not attempt to power on the l2 + * It is the callers responsibility to ensure that the l2 is already powered up + * and to eventually call @ref kbase_pm_release_l2_caches + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_l2_caches_l2_is_on(struct kbase_device *kbdev); + +/** Release the use of l2 caches for all core groups and allow the power manager to + * power them down when necessary. + * + * This tells the power management that the caches can be powered down if necessary, with respect + * to the usage of shader cores. + * + * The caller must have called @ref kbase_pm_request_l2_caches prior to a call to this. + * + * This should only be used when power management is active. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_release_l2_caches(struct kbase_device *kbdev); + +#endif /* _KBASE_PM_POLICY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.c new file mode 100644 index 0000000000000000000000000000000000000000..b781b939ed0ad32a53ebc419770c6be0459d3c4b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.c @@ -0,0 +1,260 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include + +#include +#include +#include + +#include "mali_kbase_power_actor.h" + + +static u32 mali_pa_get_req_power(struct power_actor *actor, struct thermal_zone_device *zone) +{ + struct mali_power_actor *mali_actor = actor->data; + struct kbase_device *kbdev = mali_actor->kbdev; + unsigned long total_time, busy_time; + unsigned long power, temperature; + struct dev_pm_opp *opp; + unsigned long voltage; + unsigned long freq; + + kbase_pm_get_dvfs_utilisation(kbdev, &total_time, &busy_time); + + freq = clk_get_rate(kbdev->clock); + + rcu_read_lock(); + opp = dev_pm_opp_find_freq_floor(kbdev->dev, &freq); + if (IS_ERR_OR_NULL(opp)) { + rcu_read_unlock(); + return 0; + } + + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + rcu_read_unlock(); + + power = mali_actor->ops->get_dynamic_power(freq, voltage); + power = (power * busy_time) / total_time; + + temperature = zone->temperature; + + /* Assume all cores are always powered */ + power += mali_actor->ops->get_static_power(voltage, temperature); + + dev_dbg(kbdev->dev, "get req power = %lu\n", power); + + return (u32)power; +} + +static u32 mali_pa_get_max_power(struct power_actor *actor, struct thermal_zone_device *zone) +{ + struct mali_power_actor *mali_actor = actor->data; + struct kbase_device *kbdev = mali_actor->kbdev; + struct dev_pm_opp *opp; + unsigned long voltage, temperature; + unsigned long freq = ULONG_MAX; + u32 power; + + rcu_read_lock(); + opp = dev_pm_opp_find_freq_floor(kbdev->dev, &freq); + if (IS_ERR_OR_NULL(opp)) { + rcu_read_unlock(); + dev_err(kbdev->dev, "Failed to get OPP for max freq\n"); + return 0; + } + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + rcu_read_unlock(); + + temperature = zone->temperature; + + power = mali_actor->ops->get_static_power(voltage, temperature) + + mali_actor->ops->get_dynamic_power(freq, voltage); + + dev_dbg(kbdev->dev, "get max power = %u\n", power); + + return power; +} + +static int mali_pa_set_power(struct power_actor *actor, struct thermal_zone_device *zone, u32 power) +{ + struct mali_power_actor *mali_actor = actor->data; + struct kbase_device *kbdev = mali_actor->kbdev; + struct thermal_cooling_device *cdev; + unsigned long total_time, busy_time; + unsigned long freq, state; + unsigned long static_power, normalized_power; + unsigned long voltage, temperature; + struct dev_pm_opp *opp; + int err, i; + + dev_dbg(kbdev->dev, "Setting max power %u\n", power); + + kbase_pm_get_dvfs_utilisation(kbdev, &total_time, &busy_time); + + freq = clk_get_rate(kbdev->clock); + + rcu_read_lock(); + opp = dev_pm_opp_find_freq_exact(kbdev->dev, freq, true); + if (IS_ERR_OR_NULL(opp)) { + rcu_read_unlock(); + return -ENOENT; + } + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + rcu_read_unlock(); + + temperature = zone->temperature; + + static_power = mali_actor->ops->get_static_power(voltage, temperature); + + if (power < static_power) { + normalized_power = 0; + } else { + unsigned long dyn_power = power - static_power; + + if (!busy_time) + normalized_power = dyn_power; + else + normalized_power = (dyn_power * total_time) / busy_time; + } + + /* Find target frequency. Use the lowest OPP if allocated power is too + * low. */ + freq = mali_actor->dyn_table[0].freq; + for (i = 1; i < mali_actor->dyn_table_count; i++) { + if (mali_actor->dyn_table[i].power > normalized_power) + break; + else + freq = mali_actor->dyn_table[i].freq; + } + + state = devfreq_cooling_get_level(kbdev->devfreq, freq); + if (state == THERMAL_CSTATE_INVALID) { + dev_err(kbdev->dev, + "Failed to lookup cooling level for freq %ld\n", freq); + return -EINVAL; + } + + cdev = kbdev->devfreq_cooling->cdev; + err = cdev->ops->set_cur_state(cdev, state); + + dev_dbg(kbdev->dev, + "Max power set to %u using frequency %ld (cooling level %ld) (%d)\n", + power, freq, state, err); + + return err; +} + +static struct power_actor_ops mali_pa_ops = { + .get_req_power = mali_pa_get_req_power, + .get_max_power = mali_pa_get_max_power, + .set_power = mali_pa_set_power, +}; + +int mali_pa_init(struct kbase_device *kbdev) +{ + struct power_actor *actor; + struct mali_power_actor *mali_actor; + struct mali_pa_model_ops *callbacks; + struct mali_pa_power_table *table; + unsigned long freq; + int i, num_opps; + + callbacks = (void *)kbasep_get_config_value(kbdev, kbdev->config_attributes, + KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS); + if (!callbacks) + return -ENODEV; + + mali_actor = kzalloc(sizeof(*mali_actor), GFP_KERNEL); + if (!mali_actor) + return -ENOMEM; + + mali_actor->ops = callbacks; + mali_actor->kbdev = kbdev; + + rcu_read_lock(); + num_opps = dev_pm_opp_get_opp_count(kbdev->dev); + rcu_read_unlock(); + + table = kcalloc(num_opps, sizeof(table[0]), GFP_KERNEL); + if (!table) { + kfree(mali_actor); + return -ENOMEM; + } + + rcu_read_lock(); + for (i = 0, freq = 0; i < num_opps; i++, freq++) { + unsigned long power_static, power_dyn, voltage; + struct dev_pm_opp *opp; + + opp = dev_pm_opp_find_freq_ceil(kbdev->dev, &freq); + if (IS_ERR(opp)) + break; + + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + + table[i].freq = freq; + + power_dyn = callbacks->get_dynamic_power(freq, voltage); + power_static = callbacks->get_static_power(voltage, 85000); + + dev_info(kbdev->dev, "Power table: %lu MHz @ %lu mV: %lu + %lu = %lu mW\n", + freq / 1000000, voltage, + power_dyn, power_static, power_dyn + power_static); + + table[i].power = power_dyn; + } + rcu_read_unlock(); + + if (i != num_opps) + dev_warn(kbdev->dev, "Power actor: Unable to enumerate all OPPs (%d != %d)\n", + i, num_opps); + + mali_actor->dyn_table = table; + mali_actor->dyn_table_count = i; + + /* Register power actor. + * Set default actor weight to 1 (8-bit fixed point). */ + actor = power_actor_register(1 * 256, &mali_pa_ops, mali_actor); + if (IS_ERR_OR_NULL(actor)) { + kfree(mali_actor->dyn_table); + kfree(mali_actor); + return PTR_ERR(actor); + } + + kbdev->power_actor = actor; + + dev_info(kbdev->dev, "Initalized power actor\n"); + + return 0; +} + +void mali_pa_term(struct kbase_device *kbdev) +{ + struct mali_power_actor *mali_actor; + + if (kbdev->power_actor) { + mali_actor = kbdev->power_actor->data; + + power_actor_unregister(kbdev->power_actor); + kbdev->power_actor = NULL; + + kfree(mali_actor->dyn_table); + kfree(mali_actor); + } +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.h new file mode 100644 index 0000000000000000000000000000000000000000..17f52e7718015f8de1e8bcfed048b5c35ace0a72 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.h @@ -0,0 +1,58 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#ifndef _KBASE_POWER_ACTOR_H_ +#define _KBASE_POWER_ACTOR_H_ + +#include + +#include + +/** struct mali_pa_model_ops - Function pointer for power model + * + * @get_static_power: Pointer to a function that returns the estimated static + * power usage in mW, based on the input voltage in mV and + * temperature in millidegrees Celsius. + * @get_dynamic_power: Pointer to a function that returns the estimated dynamic power + * usage in mW, based on the input voltage in mV and + * frequency in Hz. + */ +struct mali_pa_model_ops { + unsigned long (*get_static_power)(unsigned long voltage, + unsigned long temperature); + unsigned long (*get_dynamic_power)(unsigned long freq, + unsigned long voltage); +}; + +struct mali_pa_power_table { + unsigned long freq; + unsigned long power; +}; + +struct mali_power_actor { + struct kbase_device *kbdev; + struct mali_pa_model_ops *ops; + struct mali_pa_power_table *dyn_table; + int dyn_table_count; +}; + +int mali_pa_init(struct kbase_device *kbdev); +void mali_pa_term(struct kbase_device *kbdev); + + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_profiling_gator_api.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_profiling_gator_api.h new file mode 100644 index 0000000000000000000000000000000000000000..6f9db71f7a0641c7ac84a9e75e588a8dfca0bac3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_profiling_gator_api.h @@ -0,0 +1,40 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_profiling_gator_api.h + * Model interface + */ + +#ifndef _KBASE_PROFILING_GATOR_API_H_ +#define _KBASE_PROFILING_GATOR_API_H_ + +/* + * List of possible actions to be controlled by Streamline. + * The following numbers are used by gator to control + * the frame buffer dumping and s/w counter reporting. + */ +#define FBDUMP_CONTROL_ENABLE (1) +#define FBDUMP_CONTROL_RATE (2) +#define SW_COUNTER_ENABLE (3) +#define FBDUMP_CONTROL_RESIZE_FACTOR (4) +#define FBDUMP_CONTROL_MAX (5) +#define FBDUMP_CONTROL_MIN FBDUMP_CONTROL_ENABLE + +void _mali_profiling_control(u32 action, u32 value); + +#endif /* _KBASE_PROFILING_GATOR_API */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_replay.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_replay.c new file mode 100644 index 0000000000000000000000000000000000000000..e47d865601c896614ee365a43adfde0e5436110b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_replay.c @@ -0,0 +1,1284 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_replay.c + * Replay soft job handlers + */ + +#include +#include +#include +#include + +#define JOB_NOT_STARTED 0 +#define JOB_TYPE_MASK 0xfe +#define JOB_TYPE_NULL (1 << 1) +#define JOB_TYPE_VERTEX (5 << 1) +#define JOB_TYPE_TILER (7 << 1) +#define JOB_TYPE_FUSED (8 << 1) +#define JOB_TYPE_FRAGMENT (9 << 1) + +#define JOB_FLAG_DESC_SIZE (1 << 0) +#define JOB_FLAG_PERFORM_JOB_BARRIER (1 << 8) + +#define JOB_HEADER_32_FBD_OFFSET (31*4) +#define JOB_HEADER_64_FBD_OFFSET (44*4) + +#define FBD_POINTER_MASK (~0x3f) + +#define SFBD_TILER_OFFSET (48*4) + +#define MFBD_TILER_OFFSET (14*4) + +#define FBD_HIERARCHY_WEIGHTS 8 +#define FBD_HIERARCHY_MASK_MASK 0x1fff + +#define FBD_TYPE 1 + +#define HIERARCHY_WEIGHTS 13 + +#define JOB_HEADER_ID_MAX 0xffff + +#define JOB_SOURCE_ID(status) (((status) >> 16) & 0xFFFF) +#define JOB_POLYGON_LIST (0x03) + +struct job_head { + u32 status; + u32 not_complete_index; + u64 fault_addr; + u16 flags; + u16 index; + u16 dependencies[2]; + union { + u64 _64; + u32 _32; + } next; + u32 x[2]; + union { + u64 _64; + u32 _32; + } fragment_fbd; +}; + +static void dump_job_head(struct kbase_context *kctx, char *head_str, + struct job_head *job) +{ +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "%s\n", head_str); + dev_dbg(kctx->kbdev->dev, "addr = %p\n" + "status = %x\n" + "not_complete_index = %x\n" + "fault_addr = %llx\n" + "flags = %x\n" + "index = %x\n" + "dependencies = %x,%x\n", + job, job->status, job->not_complete_index, + job->fault_addr, job->flags, job->index, + job->dependencies[0], + job->dependencies[1]); + + if (job->flags & JOB_FLAG_DESC_SIZE) + dev_dbg(kctx->kbdev->dev, "next = %llx\n", + job->next._64); + else + dev_dbg(kctx->kbdev->dev, "next = %x\n", + job->next._32); +#endif +} + +struct kbasep_map_struct { + mali_addr64 gpu_addr; + struct kbase_mem_phy_alloc *alloc; + struct page **pages; + void *addr; + size_t size; + mali_bool is_cached; +}; + +static void *kbasep_map(struct kbase_context *kctx, mali_addr64 gpu_addr, + size_t size, struct kbasep_map_struct *map) +{ + struct kbase_va_region *region; + unsigned long page_index; + unsigned int offset = gpu_addr & ~PAGE_MASK; + size_t page_count = PFN_UP(offset + size); + phys_addr_t *page_array; + struct page **pages; + void *cpu_addr = NULL; + pgprot_t prot; + size_t i; + + if (!size || !map) + return NULL; + + /* check if page_count calculation will wrap */ + if (size > ((size_t)-1 / PAGE_SIZE)) + return NULL; + + region = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); + if (!region || (region->flags & KBASE_REG_FREE)) + return NULL; + + page_index = (gpu_addr >> PAGE_SHIFT) - region->start_pfn; + + /* check if page_index + page_count will wrap */ + if (-1UL - page_count < page_index) + return NULL; + + if (page_index + page_count > kbase_reg_current_backed_size(region)) + return NULL; + + page_array = kbase_get_phy_pages(region); + if (!page_array) + return NULL; + + pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); + if (!pages) + return NULL; + + for (i = 0; i < page_count; i++) + pages[i] = pfn_to_page(PFN_DOWN(page_array[page_index + i])); + + prot = PAGE_KERNEL; + if (!(region->flags & KBASE_REG_CPU_CACHED)) { + /* Map uncached */ + prot = pgprot_writecombine(prot); + } + + cpu_addr = vmap(pages, page_count, VM_MAP, prot); + if (!cpu_addr) + goto vmap_failed; + + map->gpu_addr = gpu_addr; + map->alloc = kbase_mem_phy_alloc_get(region->alloc); + map->pages = pages; + map->addr = (void *)((uintptr_t)cpu_addr + offset); + map->size = size; + map->is_cached = (region->flags & KBASE_REG_CPU_CACHED) != 0; + + if (map->is_cached) { + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + phys_addr_t pa = page_to_phys(map->pages[0]) + offset; + + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_cpu); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + pa = page_to_phys(map->pages[i]); + kbase_sync_single(kctx, pa, PAGE_SIZE, + dma_sync_single_for_cpu); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + pa = page_to_phys(map->pages[page_count - 1]); + sz = ((offset + size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, pa, sz, + dma_sync_single_for_cpu); + } + } + + return map->addr; + +vmap_failed: + kfree(pages); + + return NULL; +} + +static void kbasep_unmap(struct kbase_context *kctx, + struct kbasep_map_struct *map) +{ + void *addr = (void *)((uintptr_t)map->addr & PAGE_MASK); + + vunmap(addr); + + if (map->is_cached) { + off_t offset = (uintptr_t)map->addr & ~PAGE_MASK; + size_t size = map->size; + size_t page_count = PFN_UP(offset + size); + size_t i; + + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + phys_addr_t pa = page_to_phys(map->pages[0]) + offset; + + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_device); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + pa = page_to_phys(map->pages[i]); + kbase_sync_single(kctx, pa, PAGE_SIZE, + dma_sync_single_for_device); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + pa = page_to_phys(map->pages[page_count - 1]); + sz = ((offset + size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, pa, sz, + dma_sync_single_for_device); + } + } + + kfree(map->pages); + + map->gpu_addr = 0; + map->alloc = kbase_mem_phy_alloc_put(map->alloc); + map->pages = NULL; + map->addr = NULL; + map->size = 0; + map->is_cached = MALI_FALSE; +} + +static mali_error kbasep_replay_reset_sfbd(struct kbase_context *kctx, + mali_addr64 fbd_address, mali_addr64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight) +{ + struct { + u32 padding_1[1]; + u32 flags; + u64 padding_2[2]; + u64 heap_free_address; + u32 padding[8]; + u32 weights[FBD_HIERARCHY_WEIGHTS]; + } *fbd_tiler; + struct kbasep_map_struct map; + + dev_dbg(kctx->kbdev->dev, "fbd_address: %llx\n", fbd_address); + + fbd_tiler = kbasep_map(kctx, fbd_address + SFBD_TILER_OFFSET, + sizeof(*fbd_tiler), &map); + if (!fbd_tiler) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_fbd: failed to map fbd\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, + "FBD tiler:\n" + "flags = %x\n" + "heap_free_address = %llx\n", + fbd_tiler->flags, fbd_tiler->heap_free_address); +#endif + if (hierarchy_mask) { + u32 weights[HIERARCHY_WEIGHTS]; + u16 old_hierarchy_mask = fbd_tiler->flags & + FBD_HIERARCHY_MASK_MASK; + int i, j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (old_hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + weights[i] = fbd_tiler->weights[j++]; + } else { + weights[i] = default_weight; + } + } + + + dev_dbg(kctx->kbdev->dev, "Old hierarchy mask=%x New hierarchy mask=%x\n", + old_hierarchy_mask, hierarchy_mask); + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) + dev_dbg(kctx->kbdev->dev, " Hierarchy weight %02d: %08x\n", + i, weights[i]); + + j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + + dev_dbg(kctx->kbdev->dev, " Writing hierarchy level %02d (%08x) to %d\n", + i, weights[i], j); + + fbd_tiler->weights[j++] = weights[i]; + } + } + + for (; j < FBD_HIERARCHY_WEIGHTS; j++) + fbd_tiler->weights[j] = 0; + + fbd_tiler->flags = hierarchy_mask | (1 << 16); + } + + fbd_tiler->heap_free_address = tiler_heap_free; + + dev_dbg(kctx->kbdev->dev, "heap_free_address=%llx flags=%x\n", + fbd_tiler->heap_free_address, fbd_tiler->flags); + + kbasep_unmap(kctx, &map); + + return MALI_ERROR_NONE; +} + +static mali_error kbasep_replay_reset_mfbd(struct kbase_context *kctx, + mali_addr64 fbd_address, mali_addr64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight) +{ + struct kbasep_map_struct map; + struct { + u32 padding_0; + u32 flags; + u64 padding_1[2]; + u64 heap_free_address; + u64 padding_2; + u32 weights[FBD_HIERARCHY_WEIGHTS]; + } *fbd_tiler; + + dev_dbg(kctx->kbdev->dev, "fbd_address: %llx\n", fbd_address); + + fbd_tiler = kbasep_map(kctx, fbd_address + MFBD_TILER_OFFSET, + sizeof(*fbd_tiler), &map); + if (!fbd_tiler) { + dev_err(kctx->kbdev->dev, + "kbasep_replay_reset_fbd: failed to map fbd\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "FBD tiler:\n" + "flags = %x\n" + "heap_free_address = %llx\n", + fbd_tiler->flags, + fbd_tiler->heap_free_address); +#endif + if (hierarchy_mask) { + u32 weights[HIERARCHY_WEIGHTS]; + u16 old_hierarchy_mask = (fbd_tiler->flags) & + FBD_HIERARCHY_MASK_MASK; + int i, j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (old_hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + weights[i] = fbd_tiler->weights[j++]; + } else { + weights[i] = default_weight; + } + } + + + dev_dbg(kctx->kbdev->dev, "Old hierarchy mask=%x New hierarchy mask=%x\n", + old_hierarchy_mask, hierarchy_mask); + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) + dev_dbg(kctx->kbdev->dev, " Hierarchy weight %02d: %08x\n", + i, weights[i]); + + j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + + dev_dbg(kctx->kbdev->dev, + " Writing hierarchy level %02d (%08x) to %d\n", + i, weights[i], j); + + fbd_tiler->weights[j++] = weights[i]; + } + } + + for (; j < FBD_HIERARCHY_WEIGHTS; j++) + fbd_tiler->weights[j] = 0; + + fbd_tiler->flags = hierarchy_mask | (1 << 16); + } + + fbd_tiler->heap_free_address = tiler_heap_free; + + kbasep_unmap(kctx, &map); + + return MALI_ERROR_NONE; +} + +/** + * @brief Reset the status of an FBD pointed to by a tiler job + * + * This performs two functions : + * - Set the hierarchy mask + * - Reset the tiler free heap address + * + * @param[in] kctx Context pointer + * @param[in] job_header Address of job header to reset. + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] job_64 MALI_TRUE if this job is using 64-bit + * descriptors + * + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_reset_tiler_job(struct kbase_context *kctx, + mali_addr64 job_header, mali_addr64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight, mali_bool job_64) +{ + struct kbasep_map_struct map; + mali_addr64 fbd_address; + + if (job_64) { + u64 *job_ext; + + job_ext = kbasep_map(kctx, + job_header + JOB_HEADER_64_FBD_OFFSET, + sizeof(*job_ext), &map); + + if (!job_ext) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_tiler_job: failed to map jc\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + fbd_address = *job_ext; + + kbasep_unmap(kctx, &map); + } else { + u32 *job_ext; + + job_ext = kbasep_map(kctx, + job_header + JOB_HEADER_32_FBD_OFFSET, + sizeof(*job_ext), &map); + + if (!job_ext) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_tiler_job: failed to map jc\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + fbd_address = *job_ext; + + kbasep_unmap(kctx, &map); + } + + if (fbd_address & FBD_TYPE) { + return kbasep_replay_reset_mfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight); + } else { + return kbasep_replay_reset_sfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight); + } +} + +/** + * @brief Reset the status of a job + * + * This performs the following functions : + * + * - Reset the Job Status field of each job to NOT_STARTED. + * - Set the Job Type field of any Vertex Jobs to Null Job. + * - For any jobs using an FBD, set the Tiler Heap Free field to the value of + * the tiler_heap_free parameter, and set the hierarchy level mask to the + * hier_mask parameter. + * - Offset HW dependencies by the hw_job_id_offset parameter + * - Set the Perform Job Barrier flag if this job is the first in the chain + * - Read the address of the next job header + * + * @param[in] kctx Context pointer + * @param[in,out] job_header Address of job header to reset. Set to address + * of next job header on exit. + * @param[in] prev_jc Previous job chain to link to, if this job is + * the last in the chain. + * @param[in] hw_job_id_offset Offset for HW job IDs + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] first_in_chain MALI_TRUE if this job is the first in the chain + * @param[in] fragment_chain MALI_TRUE if this job is in the fragment chain + * + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_reset_job(struct kbase_context *kctx, + mali_addr64 *job_header, mali_addr64 prev_jc, + mali_addr64 tiler_heap_free, u16 hierarchy_mask, + u32 default_weight, u16 hw_job_id_offset, + mali_bool first_in_chain, mali_bool fragment_chain) +{ + struct job_head *job; + mali_addr64 new_job_header; + struct kbasep_map_struct map; + + job = kbasep_map(kctx, *job_header, sizeof(*job), &map); + if (!job) { + dev_err(kctx->kbdev->dev, + "kbasep_replay_parse_jc: failed to map jc\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + dump_job_head(kctx, "Job header:", job); + + if (job->status == JOB_NOT_STARTED && !fragment_chain) { + dev_err(kctx->kbdev->dev, "Job already not started\n"); + goto out_unmap; + } + job->status = JOB_NOT_STARTED; + + if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_VERTEX) + job->flags = (job->flags & ~JOB_TYPE_MASK) | JOB_TYPE_NULL; + + if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_FUSED) { + dev_err(kctx->kbdev->dev, "Fused jobs can not be replayed\n"); + goto out_unmap; + } + + if (first_in_chain) + job->flags |= JOB_FLAG_PERFORM_JOB_BARRIER; + + if ((job->dependencies[0] + hw_job_id_offset) > JOB_HEADER_ID_MAX || + (job->dependencies[1] + hw_job_id_offset) > JOB_HEADER_ID_MAX || + (job->index + hw_job_id_offset) > JOB_HEADER_ID_MAX) { + dev_err(kctx->kbdev->dev, + "Job indicies/dependencies out of valid range\n"); + goto out_unmap; + } + + if (job->dependencies[0]) + job->dependencies[0] += hw_job_id_offset; + if (job->dependencies[1]) + job->dependencies[1] += hw_job_id_offset; + + job->index += hw_job_id_offset; + + if (job->flags & JOB_FLAG_DESC_SIZE) { + new_job_header = job->next._64; + if (!job->next._64) + job->next._64 = prev_jc; + } else { + new_job_header = job->next._32; + if (!job->next._32) + job->next._32 = prev_jc; + } + dump_job_head(kctx, "Updated to:", job); + + if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_TILER) { + mali_bool job_64 = (job->flags & JOB_FLAG_DESC_SIZE) != 0; + + if (kbasep_replay_reset_tiler_job(kctx, *job_header, + tiler_heap_free, hierarchy_mask, + default_weight, job_64) != MALI_ERROR_NONE) + goto out_unmap; + + } else if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_FRAGMENT) { + u64 fbd_address; + + if (job->flags & JOB_FLAG_DESC_SIZE) + fbd_address = job->fragment_fbd._64; + else + fbd_address = (u64)job->fragment_fbd._32; + + if (fbd_address & FBD_TYPE) { + if (kbasep_replay_reset_mfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight) != MALI_ERROR_NONE) + goto out_unmap; + } else { + if (kbasep_replay_reset_sfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight) != MALI_ERROR_NONE) + goto out_unmap; + } + } + + kbasep_unmap(kctx, &map); + + *job_header = new_job_header; + + return MALI_ERROR_NONE; + +out_unmap: + kbasep_unmap(kctx, &map); + return MALI_ERROR_FUNCTION_FAILED; +} + +/** + * @brief Find the highest job ID in a job chain + * + * @param[in] kctx Context pointer + * @param[in] jc Job chain start address + * @param[out] hw_job_id Highest job ID in chain + * + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_find_hw_job_id(struct kbase_context *kctx, + mali_addr64 jc, u16 *hw_job_id) +{ + while (jc) { + struct job_head *job; + struct kbasep_map_struct map; + + dev_dbg(kctx->kbdev->dev, + "kbasep_replay_find_hw_job_id: parsing jc=%llx\n", jc); + + job = kbasep_map(kctx, jc, sizeof(*job), &map); + if (!job) { + dev_err(kctx->kbdev->dev, "failed to map jc\n"); + + return MALI_ERROR_FUNCTION_FAILED; + } + + if (job->index > *hw_job_id) + *hw_job_id = job->index; + + if (job->flags & JOB_FLAG_DESC_SIZE) + jc = job->next._64; + else + jc = job->next._32; + + kbasep_unmap(kctx, &map); + } + + return MALI_ERROR_NONE; +} + +/** + * @brief Reset the status of a number of jobs + * + * This function walks the provided job chain, and calls + * kbasep_replay_reset_job for each job. It also links the job chain to the + * provided previous job chain. + * + * The function will fail if any of the jobs passed already have status of + * NOT_STARTED. + * + * @param[in] kctx Context pointer + * @param[in] jc Job chain to be processed + * @param[in] prev_jc Job chain to be added to. May be NULL + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] hw_job_id_offset Offset for HW job IDs + * @param[in] fragment_chain MAIL_TRUE if this chain is the fragment chain + * + * @return MALI_ERROR_NONE on success, error code otherwise + */ +static mali_error kbasep_replay_parse_jc(struct kbase_context *kctx, + mali_addr64 jc, mali_addr64 prev_jc, + mali_addr64 tiler_heap_free, u16 hierarchy_mask, + u32 default_weight, u16 hw_job_id_offset, + mali_bool fragment_chain) +{ + mali_bool first_in_chain = MALI_TRUE; + int nr_jobs = 0; + + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_jc: jc=%llx hw_job_id=%x\n", + jc, hw_job_id_offset); + + while (jc) { + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_jc: parsing jc=%llx\n", jc); + + if (kbasep_replay_reset_job(kctx, &jc, prev_jc, + tiler_heap_free, hierarchy_mask, + default_weight, hw_job_id_offset, + first_in_chain, fragment_chain) != MALI_ERROR_NONE) + return MALI_ERROR_FUNCTION_FAILED; + + first_in_chain = MALI_FALSE; + + nr_jobs++; + if (fragment_chain && + nr_jobs >= BASE_JD_REPLAY_F_CHAIN_JOB_LIMIT) { + dev_err(kctx->kbdev->dev, + "Exceeded maximum number of jobs in fragment chain\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + } + + return MALI_ERROR_NONE; +} + +/** + * @brief Reset the status of a replay job, and set up dependencies + * + * This performs the actions to allow the replay job to be re-run following + * completion of the passed dependency. + * + * @param[in] katom The atom to be reset + * @param[in] dep_atom The dependency to be attached to the atom + */ +static void kbasep_replay_reset_softjob(struct kbase_jd_atom *katom, + struct kbase_jd_atom *dep_atom) +{ + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + kbase_jd_katom_dep_set(&katom->dep[0], dep_atom, BASE_JD_DEP_TYPE_DATA); + list_add_tail(&katom->dep_item[0], &dep_atom->dep_head[0]); +} + +/** + * @brief Allocate an unused katom + * + * This will search the provided context for an unused katom, and will mark it + * as KBASE_JD_ATOM_STATE_QUEUED. + * + * If no atoms are available then the function will fail. + * + * @param[in] kctx Context pointer + * @return An atom ID, or -1 on failure + */ +static int kbasep_allocate_katom(struct kbase_context *kctx) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + int i; + + for (i = BASE_JD_ATOM_COUNT-1; i > 0; i--) { + if (jctx->atoms[i].status == KBASE_JD_ATOM_STATE_UNUSED) { + jctx->atoms[i].status = KBASE_JD_ATOM_STATE_QUEUED; + dev_dbg(kctx->kbdev->dev, + "kbasep_allocate_katom: Allocated atom %d\n", + i); + return i; + } + } + + return -1; +} + +/** + * @brief Release a katom + * + * This will mark the provided atom as available, and remove any dependencies. + * + * For use on error path. + * + * @param[in] kctx Context pointer + * @param[in] atom_id ID of atom to release + */ +static void kbasep_release_katom(struct kbase_context *kctx, int atom_id) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + + dev_dbg(kctx->kbdev->dev, "kbasep_release_katom: Released atom %d\n", + atom_id); + + while (!list_empty(&jctx->atoms[atom_id].dep_head[0])) + list_del(jctx->atoms[atom_id].dep_head[0].next); + + while (!list_empty(&jctx->atoms[atom_id].dep_head[1])) + list_del(jctx->atoms[atom_id].dep_head[1].next); + + jctx->atoms[atom_id].status = KBASE_JD_ATOM_STATE_UNUSED; +} + +static void kbasep_replay_create_atom(struct kbase_context *kctx, + struct base_jd_atom_v2 *atom, + int atom_nr, + int prio) +{ + atom->nr_extres = 0; + atom->extres_list.value = NULL; + atom->device_nr = 0; + /* Convert priority back from NICE range */ + atom->prio = ((prio << 16) / ((20 << 16) / 128)) - 128; + atom->atom_number = atom_nr; + + base_jd_atom_dep_set(&atom->pre_dep[0], 0 , BASE_JD_DEP_TYPE_INVALID); + base_jd_atom_dep_set(&atom->pre_dep[1], 0 , BASE_JD_DEP_TYPE_INVALID); + + atom->udata.blob[0] = 0; + atom->udata.blob[1] = 0; +} + +/** + * @brief Create two atoms for the purpose of replaying jobs + * + * Two atoms are allocated and created. The jc pointer is not set at this + * stage. The second atom has a dependency on the first. The remaining fields + * are set up as follows : + * + * - No external resources. Any required external resources will be held by the + * replay atom. + * - device_nr is set to 0. This is not relevant as + * BASE_JD_REQ_SPECIFIC_COHERENT_GROUP should not be set. + * - Priority is inherited from the replay job. + * + * @param[out] t_atom Atom to use for tiler jobs + * @param[out] f_atom Atom to use for fragment jobs + * @param[in] prio Priority of new atom (inherited from replay soft + * job) + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_create_atoms(struct kbase_context *kctx, + struct base_jd_atom_v2 *t_atom, + struct base_jd_atom_v2 *f_atom, int prio) +{ + int t_atom_nr, f_atom_nr; + + t_atom_nr = kbasep_allocate_katom(kctx); + if (t_atom_nr < 0) { + dev_err(kctx->kbdev->dev, "Failed to allocate katom\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + f_atom_nr = kbasep_allocate_katom(kctx); + if (f_atom_nr < 0) { + dev_err(kctx->kbdev->dev, "Failed to allocate katom\n"); + kbasep_release_katom(kctx, t_atom_nr); + return MALI_ERROR_FUNCTION_FAILED; + } + + kbasep_replay_create_atom(kctx, t_atom, t_atom_nr, prio); + kbasep_replay_create_atom(kctx, f_atom, f_atom_nr, prio); + + base_jd_atom_dep_set(&f_atom->pre_dep[0], t_atom_nr , BASE_JD_DEP_TYPE_DATA); + + return MALI_ERROR_NONE; +} + +#ifdef CONFIG_MALI_DEBUG +static void payload_dump(struct kbase_context *kctx, base_jd_replay_payload *payload) +{ + mali_addr64 next; + + dev_dbg(kctx->kbdev->dev, "Tiler jc list :\n"); + next = payload->tiler_jc_list; + + while (next) { + struct kbasep_map_struct map; + base_jd_replay_jc *jc_struct; + + jc_struct = kbasep_map(kctx, next, sizeof(*jc_struct), &map); + + if (!jc_struct) + return; + + dev_dbg(kctx->kbdev->dev, "* jc_struct=%p jc=%llx next=%llx\n", + jc_struct, jc_struct->jc, jc_struct->next); + + next = jc_struct->next; + + kbasep_unmap(kctx, &map); + } +} +#endif + +/** + * @brief Parse a base_jd_replay_payload provided by userspace + * + * This will read the payload from userspace, and parse the job chains. + * + * @param[in] kctx Context pointer + * @param[in] replay_atom Replay soft job atom + * @param[in] t_atom Atom to use for tiler jobs + * @param[in] f_atom Atom to use for fragment jobs + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_parse_payload(struct kbase_context *kctx, + struct kbase_jd_atom *replay_atom, + struct base_jd_atom_v2 *t_atom, + struct base_jd_atom_v2 *f_atom) +{ + base_jd_replay_payload *payload; + mali_addr64 next; + mali_addr64 prev_jc = 0; + u16 hw_job_id_offset = 0; + mali_error ret = MALI_ERROR_FUNCTION_FAILED; + struct kbasep_map_struct map; + + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_payload: replay_atom->jc = %llx sizeof(payload) = %zu\n", + replay_atom->jc, sizeof(payload)); + + kbase_gpu_vm_lock(kctx); + + payload = kbasep_map(kctx, replay_atom->jc, sizeof(*payload), &map); + + if (!payload) { + kbase_gpu_vm_unlock(kctx); + dev_err(kctx->kbdev->dev, "kbasep_replay_parse_payload: failed to map payload into kernel space\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_payload: payload=%p\n", payload); + dev_dbg(kctx->kbdev->dev, "Payload structure:\n" + "tiler_jc_list = %llx\n" + "fragment_jc = %llx\n" + "tiler_heap_free = %llx\n" + "fragment_hierarchy_mask = %x\n" + "tiler_hierarchy_mask = %x\n" + "hierarchy_default_weight = %x\n" + "tiler_core_req = %x\n" + "fragment_core_req = %x\n", + payload->tiler_jc_list, + payload->fragment_jc, + payload->tiler_heap_free, + payload->fragment_hierarchy_mask, + payload->tiler_hierarchy_mask, + payload->hierarchy_default_weight, + payload->tiler_core_req, + payload->fragment_core_req); + payload_dump(kctx, payload); +#endif + + t_atom->core_req = payload->tiler_core_req | BASEP_JD_REQ_EVENT_NEVER; + f_atom->core_req = payload->fragment_core_req | BASEP_JD_REQ_EVENT_NEVER; + + /* Sanity check core requirements*/ + if ((t_atom->core_req & BASEP_JD_REQ_ATOM_TYPE & + ~BASE_JD_REQ_COHERENT_GROUP) != BASE_JD_REQ_T || + (f_atom->core_req & BASEP_JD_REQ_ATOM_TYPE & + ~BASE_JD_REQ_COHERENT_GROUP) != BASE_JD_REQ_FS || + t_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES || + f_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { + dev_err(kctx->kbdev->dev, "Invalid core requirements\n"); + goto out; + } + + /* Process tiler job chains */ + next = payload->tiler_jc_list; + if (!next) { + dev_err(kctx->kbdev->dev, "Invalid tiler JC list\n"); + goto out; + } + + while (next) { + base_jd_replay_jc *jc_struct; + struct kbasep_map_struct jc_map; + mali_addr64 jc; + + jc_struct = kbasep_map(kctx, next, sizeof(*jc_struct), &jc_map); + + if (!jc_struct) { + dev_err(kctx->kbdev->dev, "Failed to map jc struct\n"); + goto out; + } + + jc = jc_struct->jc; + next = jc_struct->next; + if (next) + jc_struct->jc = 0; + + kbasep_unmap(kctx, &jc_map); + + if (jc) { + u16 max_hw_job_id = 0; + + if (kbasep_replay_find_hw_job_id(kctx, jc, + &max_hw_job_id) != MALI_ERROR_NONE) + goto out; + + if (kbasep_replay_parse_jc(kctx, jc, prev_jc, + payload->tiler_heap_free, + payload->tiler_hierarchy_mask, + payload->hierarchy_default_weight, + hw_job_id_offset, MALI_FALSE) != + MALI_ERROR_NONE) { + goto out; + } + + hw_job_id_offset += max_hw_job_id; + + prev_jc = jc; + } + } + t_atom->jc = prev_jc; + + /* Process fragment job chain */ + f_atom->jc = payload->fragment_jc; + if (kbasep_replay_parse_jc(kctx, payload->fragment_jc, 0, + payload->tiler_heap_free, + payload->fragment_hierarchy_mask, + payload->hierarchy_default_weight, 0, + MALI_TRUE) != MALI_ERROR_NONE) { + goto out; + } + + if (!t_atom->jc || !f_atom->jc) { + dev_err(kctx->kbdev->dev, "Invalid payload\n"); + goto out; + } + + dev_dbg(kctx->kbdev->dev, "t_atom->jc=%llx f_atom->jc=%llx\n", + t_atom->jc, f_atom->jc); + ret = MALI_ERROR_NONE; + +out: + kbasep_unmap(kctx, &map); + + kbase_gpu_vm_unlock(kctx); + + return ret; +} + +static void kbase_replay_process_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom; + struct kbase_context *kctx; + struct kbase_jd_context *jctx; + bool need_to_try_schedule_context = false; + + struct base_jd_atom_v2 t_atom, f_atom; + struct kbase_jd_atom *t_katom, *f_katom; + + katom = container_of(data, struct kbase_jd_atom, work); + kctx = katom->kctx; + jctx = &kctx->jctx; + + mutex_lock(&jctx->lock); + + if (kbasep_replay_create_atoms(kctx, &t_atom, &f_atom, + katom->nice_prio) != MALI_ERROR_NONE) { + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + t_katom = &jctx->atoms[t_atom.atom_number]; + f_katom = &jctx->atoms[f_atom.atom_number]; + + if (kbasep_replay_parse_payload(kctx, katom, &t_atom, &f_atom) != + MALI_ERROR_NONE) { + kbasep_release_katom(kctx, t_atom.atom_number); + kbasep_release_katom(kctx, f_atom.atom_number); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + kbasep_replay_reset_softjob(katom, f_katom); + + need_to_try_schedule_context |= jd_submit_atom(kctx, &t_atom, t_katom); + if (t_katom->event_code == BASE_JD_EVENT_JOB_INVALID) { + dev_err(kctx->kbdev->dev, "Replay failed to submit atom\n"); + kbasep_release_katom(kctx, f_atom.atom_number); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + need_to_try_schedule_context |= jd_submit_atom(kctx, &f_atom, f_katom); + if (f_katom->event_code == BASE_JD_EVENT_JOB_INVALID) { + dev_err(kctx->kbdev->dev, "Replay failed to submit atom\n"); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + katom->event_code = BASE_JD_EVENT_DONE; + +out: + if (katom->event_code != BASE_JD_EVENT_DONE) + need_to_try_schedule_context |= jd_done_nolock(katom); + + if (need_to_try_schedule_context) + kbasep_js_try_schedule_head_ctx(kctx->kbdev); + mutex_unlock(&jctx->lock); +} + +/** + * @brief Check job replay fault + * + * This will read the job payload, checks fault type and source, then decides + * whether replay is required. + * + * @param[in] katom The atom to be processed + * @return true (success) if replay required or false on failure. + */ +static bool kbase_replay_fault_check(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct device *dev = kctx->kbdev->dev; + base_jd_replay_payload *payload; + mali_addr64 job_header; + mali_addr64 job_loop_detect; + struct job_head *job; + struct kbasep_map_struct job_map; + struct kbasep_map_struct map; + bool err = false; + + /* Replay job if fault is of type BASE_JD_EVENT_JOB_WRITE_FAULT or + * if force_replay is enabled. + */ + if (BASE_JD_EVENT_TERMINATED == katom->event_code) { + return false; + } else if (BASE_JD_EVENT_JOB_WRITE_FAULT == katom->event_code) { + return true; + } else if (BASE_JD_EVENT_FORCE_REPLAY == katom->event_code) { + katom->event_code = BASE_JD_EVENT_DATA_INVALID_FAULT; + return true; + } else if (BASE_JD_EVENT_DATA_INVALID_FAULT != katom->event_code) { + /* No replay for faults of type other than + * BASE_JD_EVENT_DATA_INVALID_FAULT. + */ + return false; + } + + /* Job fault is BASE_JD_EVENT_DATA_INVALID_FAULT, now scan fragment jc + * to find out whether the source of exception is POLYGON_LIST. Replay + * is required if the source of fault is POLYGON_LIST. + */ + kbase_gpu_vm_lock(kctx); + + payload = kbasep_map(kctx, katom->jc, sizeof(*payload), &map); + if (!payload) { + kbase_gpu_vm_unlock(kctx); + dev_err(dev, "kbase_replay_fault_check: failed to map payload.\n"); + return false; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(dev, "kbase_replay_fault_check: payload=%p\n", payload); + dev_dbg(dev, "\nPayload structure:\n" + "fragment_jc = 0x%llx\n" + "fragment_hierarchy_mask = 0x%x\n" + "fragment_core_req = 0x%x\n", + payload->fragment_jc, + payload->fragment_hierarchy_mask, + payload->fragment_core_req); +#endif + /* Process fragment job chain */ + job_header = (mali_addr64) payload->fragment_jc; + job_loop_detect = job_header; + while (job_header) { + job = kbasep_map(kctx, job_header, sizeof(*job), &job_map); + if (!job) { + dev_err(dev, "failed to map jc\n"); + /* unmap payload*/ + kbasep_unmap(kctx, &map); + kbase_gpu_vm_unlock(kctx); + return false; + } + + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(dev, "\njob_head structure:\n" + "Source ID:0x%x Access:0x%x Exception:0x%x\n" + "at job addr = %p\n" + "not_complete_index = 0x%x\n" + "fault_addr = 0x%llx\n" + "flags = 0x%x\n" + "index = 0x%x\n" + "dependencies = 0x%x,0x%x\n", + JOB_SOURCE_ID(job->status), + ((job->status >> 8) & 0x3), + (job->status & 0xFF), + job, + job->not_complete_index, + job->fault_addr, + job->flags, + job->index, + job->dependencies[0], + job->dependencies[1]); +#endif + + /* Replay only when the polygon list reader caused the + * DATA_INVALID_FAULT */ + if ((BASE_JD_EVENT_DATA_INVALID_FAULT == katom->event_code) && + (JOB_POLYGON_LIST == JOB_SOURCE_ID(job->status))) { + err = true; + kbasep_unmap(kctx, &job_map); + break; + } + + /* Move on to next fragment job in the list */ + if (job->flags & JOB_FLAG_DESC_SIZE) + job_header = job->next._64; + else + job_header = job->next._32; + + kbasep_unmap(kctx, &job_map); + + /* Job chain loop detected */ + if (job_header == job_loop_detect) + break; + } + + /* unmap payload*/ + kbasep_unmap(kctx, &map); + kbase_gpu_vm_unlock(kctx); + + return err; +} + + +/** + * @brief Process a replay job + * + * Called from kbase_process_soft_job. + * + * On exit, if the job has completed, katom->event_code will have been updated. + * If the job has not completed, and is replaying jobs, then the atom status + * will have been reset to KBASE_JD_ATOM_STATE_QUEUED. + * + * @param[in] katom The atom to be processed + * @return false if the atom has completed + * true if the atom is replaying jobs + */ +bool kbase_replay_process(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct kbase_jd_context *jctx = &kctx->jctx; + + if (katom->event_code == BASE_JD_EVENT_DONE) { + dev_dbg(kctx->kbdev->dev, "Previous job succeeded - not replaying\n"); + + if (katom->retry_count) + kbase_disjoint_state_down(kctx->kbdev); + + return false; + } + + if (jctx->sched_info.ctx.is_dying) { + dev_dbg(kctx->kbdev->dev, "Not replaying; context is dying\n"); + + if (katom->retry_count) + kbase_disjoint_state_down(kctx->kbdev); + + return false; + } + + /* Check job exception type and source before replaying. */ + if (false == kbase_replay_fault_check(katom)) { + dev_dbg(kctx->kbdev->dev, + "Replay cancelled on event %x\n", katom->event_code); + /* katom->event_code is already set to the failure code of the + * previous job. + */ + return false; + } + + dev_warn(kctx->kbdev->dev, "Replaying jobs retry=%d\n", + katom->retry_count); + + katom->retry_count++; + + if (katom->retry_count > BASEP_JD_REPLAY_LIMIT) { + dev_err(kctx->kbdev->dev, "Replay exceeded limit - failing jobs\n"); + + kbase_disjoint_state_down(kctx->kbdev); + + /* katom->event_code is already set to the failure code of the + previous job */ + return false; + } + + /* only enter the disjoint state once for the whole time while the replay is ongoing */ + if (katom->retry_count == 1) + kbase_disjoint_state_up(kctx->kbdev); + + INIT_WORK(&katom->work, kbase_replay_process_worker); + queue_work(kctx->event_workq, &katom->work); + + return true; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_security.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_security.c new file mode 100644 index 0000000000000000000000000000000000000000..e7916374ffefc8dc28a76a42a6e5d4d6ded57e46 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_security.c @@ -0,0 +1,78 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_security.c + * Base kernel security capability API + */ + +#include + +static inline mali_bool kbasep_am_i_root(void) +{ +#if KBASE_HWCNT_DUMP_BYPASS_ROOT + return MALI_TRUE; +#else + /* Check if root */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + if (uid_eq(current_euid(), GLOBAL_ROOT_UID)) + return MALI_TRUE; +#else + if (current_euid() == 0) + return MALI_TRUE; +#endif /*LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)*/ + return MALI_FALSE; +#endif /*KBASE_HWCNT_DUMP_BYPASS_ROOT*/ +} + +/** + * kbase_security_has_capability - see mali_kbase_caps.h for description. + */ + +mali_bool kbase_security_has_capability(struct kbase_context *kctx, enum kbase_security_capability cap, u32 flags) +{ + /* Assume failure */ + mali_bool access_allowed = MALI_FALSE; + mali_bool audit = (KBASE_SEC_FLAG_AUDIT & flags) ? MALI_TRUE : MALI_FALSE; + + KBASE_DEBUG_ASSERT(NULL != kctx); + CSTD_UNUSED(kctx); + + /* Detect unsupported flags */ + KBASE_DEBUG_ASSERT(((~KBASE_SEC_FLAG_MASK) & flags) == 0); + + /* Determine if access is allowed for the given cap */ + switch (cap) { + case KBASE_SEC_MODIFY_PRIORITY: + case KBASE_SEC_INSTR_HW_COUNTERS_COLLECT: + /* Access is granted only if the caller is privileged */ + access_allowed = kbasep_am_i_root(); + break; + } + + /* Report problem if requested */ + if (MALI_FALSE == access_allowed) { + if (MALI_FALSE != audit) + dev_warn(kctx->kbdev->dev, "Security capability failure: %d, %p", cap, (void *)kctx); + } + + return access_allowed; +} + +KBASE_EXPORT_TEST_API(kbase_security_has_capability) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_security.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_security.h new file mode 100644 index 0000000000000000000000000000000000000000..c8d4e53ae3b0b03ce648e7fbed70a5933231b7a6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_security.h @@ -0,0 +1,52 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_security.h + * Base kernel security capability APIs + */ + +#ifndef _KBASE_SECURITY_H_ +#define _KBASE_SECURITY_H_ + +/* Security flags */ +#define KBASE_SEC_FLAG_NOAUDIT (0u << 0) /* Silently handle privilege failure */ +#define KBASE_SEC_FLAG_AUDIT (1u << 0) /* Write audit message on privilege failure */ +#define KBASE_SEC_FLAG_MASK (KBASE_SEC_FLAG_AUDIT) /* Mask of all valid flag bits */ + +/* List of unique capabilities that have security access privileges */ +enum kbase_security_capability { + /* Instrumentation Counters access privilege */ + KBASE_SEC_INSTR_HW_COUNTERS_COLLECT = 1, + KBASE_SEC_MODIFY_PRIORITY + /* Add additional access privileges here */ +}; + +/** + * kbase_security_has_capability - determine whether a task has a particular effective capability + * @param[in] kctx The task context. + * @param[in] cap The capability to check for. + * @param[in] flags Additional configuration information + * Such as whether to write an audit message or not. + * @return MALI_TRUE if success (capability is allowed), MALI_FALSE otherwise. + */ + +mali_bool kbase_security_has_capability(struct kbase_context *kctx, enum kbase_security_capability cap, u32 flags); + +#endif /* _KBASE_SECURITY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_softjobs.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_softjobs.c new file mode 100644 index 0000000000000000000000000000000000000000..22fc30d1795ce2825d620d7a1b2f19c84059bf4e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_softjobs.c @@ -0,0 +1,453 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +#include +#ifdef CONFIG_SYNC +#include "sync.h" +#include +#include "mali_kbase_sync.h" +#endif + + +/* Mask to check cache alignment of data structures */ +#define KBASE_CACHE_ALIGNMENT_MASK ((1<jc; + struct kbase_context *kctx = katom->kctx; + int pm_active_err; + + u32 hi1, hi2; + + memset(&data, 0, sizeof(data)); + + /* Take the PM active reference as late as possible - otherwise, it could + * delay suspend until we process the atom (which may be at the end of a + * long chain of dependencies */ + pm_active_err = kbase_pm_context_active_handle_suspend(kctx->kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE); + if (pm_active_err) { + struct kbasep_js_device_data *js_devdata = &kctx->kbdev->js_data; + + /* We're suspended - queue this on the list of suspended jobs + * Use dep_item[1], because dep_item[0] is in use for 'waiting_soft_jobs' */ + mutex_lock(&js_devdata->runpool_mutex); + list_add_tail(&katom->dep_item[1], &js_devdata->suspended_soft_jobs_list); + mutex_unlock(&js_devdata->runpool_mutex); + + return pm_active_err; + } + + kbase_pm_request_gpu_cycle_counter(kctx->kbdev); + + /* Read hi, lo, hi to ensure that overflow from lo to hi is handled correctly */ + do { + hi1 = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(CYCLE_COUNT_HI), NULL); + cycle_counter = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(CYCLE_COUNT_LO), NULL); + hi2 = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(CYCLE_COUNT_HI), NULL); + cycle_counter |= (((u64) hi1) << 32); + } while (hi1 != hi2); + + /* Read hi, lo, hi to ensure that overflow from lo to hi is handled correctly */ + do { + hi1 = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(TIMESTAMP_HI), NULL); + system_time = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(TIMESTAMP_LO), NULL); + hi2 = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(TIMESTAMP_HI), NULL); + system_time |= (((u64) hi1) << 32); + } while (hi1 != hi2); + + /* Record the CPU's idea of current time */ + getrawmonotonic(&ts); + + kbase_pm_release_gpu_cycle_counter(kctx->kbdev); + + kbase_pm_context_idle(kctx->kbdev); + + data.sec = ts.tv_sec; + data.usec = ts.tv_nsec / 1000; + data.system_time = system_time; + data.cycle_counter = cycle_counter; + + pfn = jc >> PAGE_SHIFT; + offset = jc & ~PAGE_MASK; + + /* Assume this atom will be cancelled until we know otherwise */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + if (offset > 0x1000 - sizeof(data)) { + /* Wouldn't fit in the page */ + return 0; + } + + kbase_gpu_vm_lock(kctx); + reg = kbase_region_tracker_find_region_enclosing_address(kctx, jc); + if (reg && + (reg->flags & KBASE_REG_GPU_WR) && + reg->alloc && reg->alloc->pages) + addr = reg->alloc->pages[pfn - reg->start_pfn]; + + kbase_gpu_vm_unlock(kctx); + if (!addr) + return 0; + + page = kmap(pfn_to_page(PFN_DOWN(addr))); + if (!page) + return 0; + + dma_sync_single_for_cpu(katom->kctx->kbdev->dev, + kbase_dma_addr(pfn_to_page(PFN_DOWN(addr))) + + offset, sizeof(data), + DMA_BIDIRECTIONAL); + memcpy(page + offset, &data, sizeof(data)); + dma_sync_single_for_device(katom->kctx->kbdev->dev, + kbase_dma_addr(pfn_to_page(PFN_DOWN(addr))) + + offset, sizeof(data), + DMA_BIDIRECTIONAL); + kunmap(pfn_to_page(PFN_DOWN(addr))); + + /* Atom was fine - mark it as done */ + katom->event_code = BASE_JD_EVENT_DONE; + + return 0; +} + +#ifdef CONFIG_SYNC + +/* Complete an atom that has returned '1' from kbase_process_soft_job (i.e. has waited) + * + * @param katom The atom to complete + */ +static void complete_soft_job(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + mutex_lock(&kctx->jctx.lock); + list_del(&katom->dep_item[0]); + kbase_finish_soft_job(katom); + if (jd_done_nolock(katom)) + kbasep_js_try_schedule_head_ctx(kctx->kbdev); + mutex_unlock(&kctx->jctx.lock); +} + +static enum base_jd_event_code kbase_fence_trigger(struct kbase_jd_atom *katom, int result) +{ + struct sync_pt *pt; + struct sync_timeline *timeline; +#if 0 + if (!list_is_singular(&katom->fence->pt_list_head)) { + /* Not exactly one item in the list - so it didn't (directly) come from us */ + return BASE_JD_EVENT_JOB_CANCELLED; + } +#endif + + if (katom->fence->num_fences != 1) { + /* Not exactly one item in the list - so it didn't (directly) come from us */ + return BASE_JD_EVENT_JOB_CANCELLED; + } + + //pt = list_first_entry(&katom->fence->pt_list_head, struct sync_pt, pt_list); + pt = container_of(katom->fence->cbs[0].sync_pt, struct sync_pt, base); + //timeline = pt->parent; + timeline = sync_pt_parent(pt); + + if (!kbase_sync_timeline_is_ours(timeline)) { + /* Fence has a sync_pt which isn't ours! */ + return BASE_JD_EVENT_JOB_CANCELLED; + } + + kbase_sync_signal_pt(pt, result); + + sync_timeline_signal(timeline); + + return (result < 0) ? BASE_JD_EVENT_JOB_CANCELLED : BASE_JD_EVENT_DONE; +} + +static void kbase_fence_wait_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom; + struct kbase_context *kctx; + + katom = container_of(data, struct kbase_jd_atom, work); + kctx = katom->kctx; + + complete_soft_job(katom); +} + +static void kbase_fence_wait_callback(struct sync_fence *fence, struct sync_fence_waiter *waiter) +{ + struct kbase_jd_atom *katom = container_of(waiter, struct kbase_jd_atom, sync_waiter); + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(NULL != katom); + + kctx = katom->kctx; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + /* Propagate the fence status to the atom. + * If negative then cancel this atom and its dependencies. + */ + //if (fence->status < 0) + if(atomic_add_negative( 0, &fence->status)) + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + /* To prevent a potential deadlock we schedule the work onto the job_done_wq workqueue + * + * The issue is that we may signal the timeline while holding kctx->jctx.lock and + * the callbacks are run synchronously from sync_timeline_signal. So we simply defer the work. + */ + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, kbase_fence_wait_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +static int kbase_fence_wait(struct kbase_jd_atom *katom) +{ + int ret; + + KBASE_DEBUG_ASSERT(NULL != katom); + KBASE_DEBUG_ASSERT(NULL != katom->kctx); + + sync_fence_waiter_init(&katom->sync_waiter, kbase_fence_wait_callback); + + ret = sync_fence_wait_async(katom->fence, &katom->sync_waiter); + + if (ret == 1) { + /* Already signalled */ + return 0; + } else if (ret < 0) { + goto cancel_atom; + } + return 1; + + cancel_atom: + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + /* We should cause the dependant jobs in the bag to be failed, + * to do this we schedule the work queue to complete this job */ + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, kbase_fence_wait_worker); + queue_work(katom->kctx->jctx.job_done_wq, &katom->work); + return 1; +} + +static void kbase_fence_cancel_wait(struct kbase_jd_atom *katom) +{ + if (sync_fence_cancel_async(katom->fence, &katom->sync_waiter) != 0) { + /* The wait wasn't cancelled - leave the cleanup for kbase_fence_wait_callback */ + return; + } + + /* Wait was cancelled - zap the atoms */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + kbase_finish_soft_job(katom); + + if (jd_done_nolock(katom)) + kbasep_js_try_schedule_head_ctx(katom->kctx->kbdev); +} +#endif /* CONFIG_SYNC */ + +int kbase_process_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + return kbase_dump_cpu_gpu_time(katom); +#ifdef CONFIG_SYNC + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + KBASE_DEBUG_ASSERT(katom->fence != NULL); + katom->event_code = kbase_fence_trigger(katom, katom->event_code == BASE_JD_EVENT_DONE ? 0 : -EFAULT); + /* Release the reference as we don't need it any more */ + sync_fence_put(katom->fence); + katom->fence = NULL; + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + return kbase_fence_wait(katom); +#endif /* CONFIG_SYNC */ + case BASE_JD_REQ_SOFT_REPLAY: + return kbase_replay_process(katom); + } + + /* Atom is complete */ + return 0; +} + +void kbase_cancel_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) { +#ifdef CONFIG_SYNC + case BASE_JD_REQ_SOFT_FENCE_WAIT: + kbase_fence_cancel_wait(katom); + break; +#endif + default: + /* This soft-job doesn't support cancellation! */ + KBASE_DEBUG_ASSERT(0); + } +} + +mali_error kbase_prepare_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + { + if (0 != (katom->jc & KBASE_CACHE_ALIGNMENT_MASK)) + return MALI_ERROR_FUNCTION_FAILED; + } + break; +#ifdef CONFIG_SYNC + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + { + struct base_fence fence; + int fd; + + if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence))) + return MALI_ERROR_FUNCTION_FAILED; + + fd = kbase_stream_create_fence(fence.basep.stream_fd); + if (fd < 0) + return MALI_ERROR_FUNCTION_FAILED; + + katom->fence = sync_fence_fdget(fd); + + if (katom->fence == NULL) { + /* The only way the fence can be NULL is if userspace closed it for us. + * So we don't need to clear it up */ + return MALI_ERROR_FUNCTION_FAILED; + } + fence.basep.fd = fd; + if (0 != copy_to_user((__user void *)(uintptr_t) katom->jc, &fence, sizeof(fence))) { + katom->fence = NULL; + sys_close(fd); + return MALI_ERROR_FUNCTION_FAILED; + } + } + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + { + struct base_fence fence; + + if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence))) + return MALI_ERROR_FUNCTION_FAILED; + + /* Get a reference to the fence object */ + katom->fence = sync_fence_fdget(fence.basep.fd); + if (katom->fence == NULL) + return MALI_ERROR_FUNCTION_FAILED; + } + break; +#endif /* CONFIG_SYNC */ + case BASE_JD_REQ_SOFT_REPLAY: + break; + default: + /* Unsupported soft-job */ + return MALI_ERROR_FUNCTION_FAILED; + } + return MALI_ERROR_NONE; +} + +void kbase_finish_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + /* Nothing to do */ + break; +#ifdef CONFIG_SYNC + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + if (katom->fence) { + /* The fence has not yet been signalled, so we do it now */ + kbase_fence_trigger(katom, katom->event_code == BASE_JD_EVENT_DONE ? 0 : -EFAULT); + sync_fence_put(katom->fence); + katom->fence = NULL; + } + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + /* Release the reference to the fence object */ + sync_fence_put(katom->fence); + katom->fence = NULL; + break; +#endif /* CONFIG_SYNC */ + } +} + +void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev) +{ + LIST_HEAD(local_suspended_soft_jobs); + struct kbase_jd_atom *tmp_iter; + struct kbase_jd_atom *katom_iter; + struct kbasep_js_device_data *js_devdata; + mali_bool resched = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev); + + js_devdata = &kbdev->js_data; + + /* Move out the entire list */ + mutex_lock(&js_devdata->runpool_mutex); + list_splice_init(&js_devdata->suspended_soft_jobs_list, &local_suspended_soft_jobs); + mutex_unlock(&js_devdata->runpool_mutex); + + mutex_lock(&js_devdata->mtk_sj_mutex); + /* Each atom must be detached from the list and ran separately - it could + * be re-added to the old list, but this is unlikely */ + list_for_each_entry_safe(katom_iter, tmp_iter, &local_suspended_soft_jobs, dep_item[1]) + { + struct kbase_context *kctx = katom_iter->kctx; + + mutex_lock(&kctx->jctx.lock); + + /* Remove from the global list */ + list_del(&katom_iter->dep_item[1]); + /* Remove from the context's list of waiting soft jobs */ + list_del(&katom_iter->dep_item[0]); + + if (kbase_process_soft_job(katom_iter) == 0) { + kbase_finish_soft_job(katom_iter); + resched |= jd_done_nolock(katom_iter); + } else { + /* The job has not completed */ + KBASE_DEBUG_ASSERT((katom_iter->core_req & BASEP_JD_REQ_ATOM_TYPE) + != BASE_JD_REQ_SOFT_REPLAY); + list_add_tail(&katom_iter->dep_item[0], &kctx->waiting_soft_jobs); + } + + mutex_unlock(&kctx->jctx.lock); + } + mutex_unlock(&js_devdata->mtk_sj_mutex); + + if (resched) + kbasep_js_try_schedule_head_ctx(kbdev); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.c new file mode 100644 index 0000000000000000000000000000000000000000..705e3b3504ad93d3a2c5289070b02817e0249e9b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.c @@ -0,0 +1,192 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_sync.c + * + */ + +#ifdef CONFIG_SYNC + +#include "sync.h" +#include + +struct mali_sync_timeline { + struct sync_timeline timeline; + atomic_t counter; + atomic_t signalled; +}; + +struct mali_sync_pt { + struct sync_pt pt; + int order; + int result; +}; + +static struct mali_sync_timeline *to_mali_sync_timeline(struct sync_timeline *timeline) +{ + return container_of(timeline, struct mali_sync_timeline, timeline); +} + +static struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt) +{ + return container_of(pt, struct mali_sync_pt, pt); +} + +static struct sync_pt *timeline_dup(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_pt *new_mpt; + //struct sync_pt *new_pt = sync_pt_create(pt->parent, sizeof(struct mali_sync_pt)); + struct sync_pt *new_pt = sync_pt_create( sync_pt_parent(pt), sizeof(struct mali_sync_pt)); + + if (!new_pt) + return NULL; + + new_mpt = to_mali_sync_pt(new_pt); + new_mpt->order = mpt->order; + new_mpt->result = mpt->result; + + return new_pt; +} + +static int timeline_has_signaled(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + //struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent); + struct mali_sync_timeline *mtl = to_mali_sync_timeline( sync_pt_parent(pt)); + int result = mpt->result; + + int diff = atomic_read(&mtl->signalled) - mpt->order; + + if (diff >= 0) + return result < 0 ? result : 1; + else + return 0; +} + +static int timeline_compare(struct sync_pt *a, struct sync_pt *b) +{ + struct mali_sync_pt *ma = container_of(a, struct mali_sync_pt, pt); + struct mali_sync_pt *mb = container_of(b, struct mali_sync_pt, pt); + + int diff = ma->order - mb->order; + + if (diff < 0) + return -1; + else if (diff == 0) + return 0; + else + return 1; +} + +static void timeline_value_str(struct sync_timeline *timeline, char *str, + int size) +{ + struct mali_sync_timeline *mtl = to_mali_sync_timeline(timeline); + + snprintf(str, size, "%d", atomic_read(&mtl->signalled)); +} + +static void pt_value_str(struct sync_pt *pt, char *str, int size) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + + snprintf(str, size, "%d(%d)", mpt->order, mpt->result); +} + +static struct sync_timeline_ops mali_timeline_ops = { + .driver_name = "Mali", + .dup = timeline_dup, + .has_signaled = timeline_has_signaled, + .compare = timeline_compare, + .timeline_value_str = timeline_value_str, + .pt_value_str = pt_value_str, +}; + +int kbase_sync_timeline_is_ours(struct sync_timeline *timeline) +{ + return timeline->ops == &mali_timeline_ops; +} + +struct sync_timeline *kbase_sync_timeline_alloc(const char *name) +{ + struct sync_timeline *tl; + struct mali_sync_timeline *mtl; + + tl = sync_timeline_create(&mali_timeline_ops, sizeof(struct mali_sync_timeline), name); + if (!tl) + return NULL; + + /* Set the counter in our private struct */ + mtl = to_mali_sync_timeline(tl); + atomic_set(&mtl->counter, 0); + atomic_set(&mtl->signalled, 0); + + return tl; +} + +struct sync_pt *kbase_sync_pt_alloc(struct sync_timeline *parent) +{ + struct sync_pt *pt = sync_pt_create(parent, sizeof(struct mali_sync_pt)); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(parent); + struct mali_sync_pt *mpt; + + if (!pt) + return NULL; + + mpt = to_mali_sync_pt(pt); + mpt->order = atomic_inc_return(&mtl->counter); + mpt->result = 0; + + return pt; +} + +void kbase_sync_signal_pt(struct sync_pt *pt, int result) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + //struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(sync_pt_parent(pt)); + int signalled; + int diff; + + mpt->result = result; + + do { + signalled = atomic_read(&mtl->signalled); + + diff = signalled - mpt->order; + + if (diff > 0) { + /* The timeline is already at or ahead of this point. + * This should not happen unless userspace has been + * signalling fences out of order, so warn but don't + * violate the sync_pt API. + * The warning is only in debug builds to prevent + * a malicious user being able to spam dmesg. + */ +#ifdef CONFIG_MALI_DEBUG + pr_err("Fences were triggered in a different order to allocation!"); +#endif /* CONFIG_MALI_DEBUG */ + return; + } + } while (atomic_cmpxchg(&mtl->signalled, signalled, mpt->order) != signalled); +} + +#endif /* CONFIG_SYNC */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.h new file mode 100644 index 0000000000000000000000000000000000000000..b9f295146c7c3aa2449e9ad6a0d9c709a04e02a9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.h @@ -0,0 +1,83 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_sync.h + * + */ + +#ifndef MALI_KBASE_SYNC_H +#define MALI_KBASE_SYNC_H + +#include "sync.h" +#include + +/* + * Create a stream object. + * Built on top of timeline object. + * Exposed as a file descriptor. + * Life-time controlled via the file descriptor: + * - dup to add a ref + * - close to remove a ref + */ +mali_error kbase_stream_create(const char *name, int *const out_fd); + +/* + * Create a fence in a stream object + */ +int kbase_stream_create_fence(int tl_fd); + +/* + * Validate a fd to be a valid fence + * No reference is taken. + * + * This function is only usable to catch unintentional user errors early, + * it does not stop malicious code changing the fd after this function returns. + */ +mali_error kbase_fence_validate(int fd); + +/* Returns true if the specified timeline is allocated by Mali */ +int kbase_sync_timeline_is_ours(struct sync_timeline *timeline); + +/* Allocates a timeline for Mali + * + * One timeline should be allocated per API context. + */ +struct sync_timeline *kbase_sync_timeline_alloc(const char *name); + +/* Allocates a sync point within the timeline. + * + * The timeline must be the one allocated by kbase_sync_timeline_alloc + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + */ +struct sync_pt *kbase_sync_pt_alloc(struct sync_timeline *parent); + +/* Signals a particular sync point + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + * + * If they are signalled in the wrong order then a message will be printed in debug + * builds and otherwise attempts to signal order sync_pts will be ignored. + * + * result can be negative to indicate error, any other value is interpreted as success. + */ +void kbase_sync_signal_pt(struct sync_pt *pt, int result); + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync_user.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync_user.c new file mode 100644 index 0000000000000000000000000000000000000000..c823226e151a0bb1bac2773ff87af606b07e41a9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_sync_user.c @@ -0,0 +1,158 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_sync_user.c + * + */ + +#ifdef CONFIG_SYNC + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int kbase_stream_close(struct inode *inode, struct file *file) +{ + struct sync_timeline *tl; + + tl = (struct sync_timeline *)file->private_data; + BUG_ON(!tl); + sync_timeline_destroy(tl); + return 0; +} + +static const struct file_operations stream_fops = { + .owner = THIS_MODULE, + .release = kbase_stream_close, +}; + +mali_error kbase_stream_create(const char *name, int *const out_fd) +{ + struct sync_timeline *tl; + + BUG_ON(!out_fd); + + tl = kbase_sync_timeline_alloc(name); + if (!tl) + return MALI_ERROR_FUNCTION_FAILED; + + *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC); + + if (*out_fd < 0) { + sync_timeline_destroy(tl); + return MALI_ERROR_FUNCTION_FAILED; + } else { + return MALI_ERROR_NONE; + } +} + +int kbase_stream_create_fence(int tl_fd) +{ + struct sync_timeline *tl; + struct sync_pt *pt; + struct sync_fence *fence; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) + struct files_struct *files; + struct fdtable *fdt; +#endif + int fd; + struct file *tl_file; + + tl_file = fget(tl_fd); + if (tl_file == NULL) + return -EBADF; + + if (tl_file->f_op != &stream_fops) { + fd = -EBADF; + goto out; + } + + tl = tl_file->private_data; + + pt = kbase_sync_pt_alloc(tl); + if (!pt) { + fd = -EFAULT; + goto out; + } + + fence = sync_fence_create("mali_fence", pt); + if (!fence) { + sync_pt_free(pt); + fd = -EFAULT; + goto out; + } + + /* from here the fence owns the sync_pt */ + + /* create a fd representing the fence */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC); + if (fd < 0) { + sync_fence_put(fence); + goto out; + } +#else + fd = get_unused_fd(); + if (fd < 0) { + sync_fence_put(fence); + goto out; + } + + files = current->files; + spin_lock(&files->file_lock); + fdt = files_fdtable(files); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + __set_close_on_exec(fd, fdt); +#else + FD_SET(fd, fdt->close_on_exec); +#endif + spin_unlock(&files->file_lock); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */ + + /* bind fence to the new fd */ + sync_fence_install(fence, fd); + + out: + fput(tl_file); + + return fd; +} + +mali_error kbase_fence_validate(int fd) +{ + struct sync_fence *fence; + + fence = sync_fence_fdget(fd); + if (NULL != fence) { + sync_fence_put(fence); + return MALI_ERROR_NONE; + } else { + return MALI_ERROR_FUNCTION_FAILED; + } +} + +#endif /* CONFIG_SYNC */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_defs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..e492ff2ca4815baf332fb4666b0605511e6362b5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_defs.h @@ -0,0 +1,264 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* ***** IMPORTANT: THIS IS NOT A NORMAL HEADER FILE ***** + * ***** DO NOT INCLUDE DIRECTLY ***** + * ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ + +/* + * The purpose of this header file is just to contain a list of trace code idenitifers + * + * Each identifier is wrapped in a macro, so that its string form and enum form can be created + * + * Each macro is separated with a comma, to allow insertion into an array initializer or enum definition block. + * + * This allows automatic creation of an enum and a corresponding array of strings + * + * Before #including, the includer MUST #define KBASE_TRACE_CODE_MAKE_CODE. + * After #including, the includer MUST #under KBASE_TRACE_CODE_MAKE_CODE. + * + * e.g.: + * #define KBASE_TRACE_CODE( X ) KBASE_TRACE_CODE_ ## X + * typedef enum + * { + * #define KBASE_TRACE_CODE_MAKE_CODE( X ) KBASE_TRACE_CODE( X ) + * #include "mali_kbase_trace_defs.h" + * #undef KBASE_TRACE_CODE_MAKE_CODE + * } kbase_trace_code; + * + * IMPORTANT: THIS FILE MUST NOT BE USED FOR ANY OTHER PURPOSE OTHER THAN THE ABOVE + * + * + * The use of the macro here is: + * - KBASE_TRACE_CODE_MAKE_CODE( X ) + * + * Which produces: + * - For an enum, KBASE_TRACE_CODE_X + * - For a string, "X" + * + * + * For example: + * - KBASE_TRACE_CODE_MAKE_CODE( JM_JOB_COMPLETE ) expands to: + * - KBASE_TRACE_CODE_JM_JOB_COMPLETE for the enum + * - "JM_JOB_COMPLETE" for the string + * - To use it to trace an event, do: + * - KBASE_TRACE_ADD( kbdev, JM_JOB_COMPLETE, subcode, kctx, uatom, val ); + */ + +#if 0 /* Dummy section to avoid breaking formatting */ +int dummy_array[] = { +#endif + +/* + * Core events + */ + /* no info_val, no gpu_addr, no atom */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_CTX_DESTROY), + /* no info_val, no gpu_addr, no atom */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_CTX_HWINSTR_TERM), + /* info_val == GPU_IRQ_STATUS register */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ), + /* info_val == bits cleared */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ_CLEAR), + /* info_val == GPU_IRQ_STATUS register */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ_DONE), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_SOFT_RESET), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_HARD_RESET), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_PRFCNT_CLEAR), + /* GPU addr==dump address */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_PRFCNT_SAMPLE), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_CLEAN_INV_CACHES), +/* + * Job Slot management events + */ + /* info_val==irq rawstat at start */ + KBASE_TRACE_CODE_MAKE_CODE(JM_IRQ), + /* info_val==jobs processed */ + KBASE_TRACE_CODE_MAKE_CODE(JM_IRQ_END), +/* In the following: + * + * - ctx is set if a corresponding job found (NULL otherwise, e.g. some soft-stop cases) + * - uatom==kernel-side mapped uatom address (for correlation with user-side) + */ + /* info_val==exit code; gpu_addr==chain gpuaddr */ + KBASE_TRACE_CODE_MAKE_CODE(JM_JOB_DONE), + /* gpu_addr==JS_HEAD_NEXT written, info_val==lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SUBMIT), + /* gpu_addr is as follows: + * - If JS_STATUS active after soft-stop, val==gpu addr written to + * JS_HEAD on submit + * - otherwise gpu_addr==0 */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP), + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP_0), + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP_1), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP_0), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP_1), + /* gpu_addr==JS_TAIL read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_UPDATE_HEAD), +/* gpu_addr is as follows: + * - If JS_STATUS active before soft-stop, val==JS_HEAD + * - otherwise gpu_addr==0 + */ + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_CHECK_HEAD), + KBASE_TRACE_CODE_MAKE_CODE(JM_FLUSH_WORKQS), + KBASE_TRACE_CODE_MAKE_CODE(JM_FLUSH_WORKQS_DONE), + /* info_val == is_scheduled */ + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_NON_SCHEDULED), + /* info_val == is_scheduled */ + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_SCHEDULED), + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_DONE), + /* info_val == nr jobs submitted */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SLOT_SOFT_OR_HARD_STOP), + /* gpu_addr==JS_HEAD_NEXT last written */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SLOT_EVICT), + KBASE_TRACE_CODE_MAKE_CODE(JM_SUBMIT_AFTER_RESET), + KBASE_TRACE_CODE_MAKE_CODE(JM_BEGIN_RESET_WORKER), + KBASE_TRACE_CODE_MAKE_CODE(JM_END_RESET_WORKER), +/* + * Job dispatch events + */ + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_WORKER), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_WORKER_END), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_TRY_RUN_NEXT_JOB), + /* gpu_addr==0, info_val==0, uatom==0 */ + KBASE_TRACE_CODE_MAKE_CODE(JD_ZAP_CONTEXT), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_CANCEL), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_CANCEL_WORKER), +/* + * Scheduler Core events + */ + KBASE_TRACE_CODE_MAKE_CODE(JS_RETAIN_CTX_NOLOCK), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_ADD_JOB), + /* gpu_addr==last value written/would be written to JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_REMOVE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_RETAIN_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_RELEASE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_TRY_SCHEDULE_HEAD_CTX), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_JOB_DONE_TRY_RUN_NEXT_JOB), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_JOB_DONE_RETRY_NEEDED), + /* kctx is the one being evicted, info_val == kctx to put in */ + KBASE_TRACE_CODE_MAKE_CODE(JS_FAST_START_EVICTS_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_AFFINITY_SUBMIT_TO_BLOCKED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_AFFINITY_CURRENT), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REQUEST_CORES_FAILED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REGISTER_INUSE_FAILED), + /* info_val == lower 32 bits of rechecked affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REQUEST_ON_RECHECK_FAILED), + /* info_val == lower 32 bits of rechecked affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REGISTER_ON_RECHECK_FAILED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_AFFINITY_WOULD_VIOLATE), + /* info_val == the ctx attribute now on ctx */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_ON_CTX), + /* info_val == the ctx attribute now on runpool */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_ON_RUNPOOL), + /* info_val == the ctx attribute now off ctx */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_OFF_CTX), + /* info_val == the ctx attribute now off runpool */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_OFF_RUNPOOL), +/* + * Scheduler Policy events + */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_INIT_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TERM_CTX), + /* info_val == whether it was evicted */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TRY_EVICT_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_FOREACH_CTX_JOBS), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_ENQUEUE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_HEAD_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_RUNPOOL_ADD_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_RUNPOOL_REMOVE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_JOB_IRQ), + /* gpu_addr==JS_HEAD to write if the job were run */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_ENQUEUE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TIMER_START), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TIMER_END), +/* + * Power Management Events + */ + KBASE_TRACE_CODE_MAKE_CODE(PM_JOB_SUBMIT_AFTER_POWERING_UP), + KBASE_TRACE_CODE_MAKE_CODE(PM_JOB_SUBMIT_AFTER_POWERED_UP), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_DESIRED), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_DESIRED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_AVAILABLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_AVAILABLE_TILER), + /* PM_DESIRED_REACHED: gpu_addr == pm.gpu_in_desired_state */ + KBASE_TRACE_CODE_MAKE_CODE(PM_DESIRED_REACHED), + KBASE_TRACE_CODE_MAKE_CODE(PM_DESIRED_REACHED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_SHADER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_TILER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_RELEASE_CHANGE_SHADER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_RELEASE_CHANGE_TILER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_UNREQUEST_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_UNREQUEST_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REQUEST_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REQUEST_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_WAKE_WAITERS), + KBASE_TRACE_CODE_MAKE_CODE(PM_CONTEXT_ACTIVE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CONTEXT_IDLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_GPU_ON), + KBASE_TRACE_CODE_MAKE_CODE(PM_GPU_OFF), + /* info_val == policy number, or -1 for "Already changing" */ + KBASE_TRACE_CODE_MAKE_CODE(PM_SET_POLICY), + KBASE_TRACE_CODE_MAKE_CODE(PM_CA_SET_POLICY), + /* info_val == policy number */ + KBASE_TRACE_CODE_MAKE_CODE(PM_CURRENT_POLICY_INIT), + /* info_val == policy number */ + KBASE_TRACE_CODE_MAKE_CODE(PM_CURRENT_POLICY_TERM), +/* Unused code just to make it easier to not have a comma at the end. + * All other codes MUST come before this */ + KBASE_TRACE_CODE_MAKE_CODE(DUMMY) + +#if 0 /* Dummy section to avoid breaking formatting */ +}; +#endif + +/* ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.c new file mode 100644 index 0000000000000000000000000000000000000000..49f5035a913e31e921abdad1171178565d1cdf98 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.c @@ -0,0 +1,231 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include + +#define CREATE_TRACE_POINTS + +#ifdef CONFIG_MALI_TRACE_TIMELINE +#include "mali_timeline.h" + +#include +#include + +struct kbase_trace_timeline_desc +{ + char *enum_str; + char *desc; + char *format; + char *format_desc; +}; + +struct kbase_trace_timeline_desc kbase_trace_timeline_desc_table[] = +{ + #define KBASE_TIMELINE_TRACE_CODE(enum_val, desc, format, format_desc) { #enum_val, desc, format, format_desc } + #include "mali_kbase_trace_timeline_defs.h" + #undef KBASE_TIMELINE_TRACE_CODE +}; + +#define KBASE_NR_TRACE_CODES ARRAY_SIZE(kbase_trace_timeline_desc_table) + +STATIC void *kbasep_trace_timeline_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos >= KBASE_NR_TRACE_CODES) + return NULL; + + return &kbase_trace_timeline_desc_table[*pos]; +} + +STATIC void kbasep_trace_timeline_seq_stop(struct seq_file *s, void *data) +{ +} + +STATIC void *kbasep_trace_timeline_seq_next(struct seq_file *s, void *data, loff_t *pos) +{ + (*pos)++; + + if (*pos == KBASE_NR_TRACE_CODES) + return NULL; + + return &kbase_trace_timeline_desc_table[*pos]; +} + +STATIC int kbasep_trace_timeline_seq_show(struct seq_file *s, void *data) +{ + struct kbase_trace_timeline_desc *trace_desc = data; + + seq_printf(s, "%s#%s#%s#%s\n", trace_desc->enum_str, trace_desc->desc, trace_desc->format, trace_desc->format_desc); + return 0; +} + + +static const struct seq_operations kbasep_trace_timeline_seq_ops = { + .start = kbasep_trace_timeline_seq_start, + .next = kbasep_trace_timeline_seq_next, + .stop = kbasep_trace_timeline_seq_stop, + .show = kbasep_trace_timeline_seq_show, +}; + +STATIC int kbasep_trace_timeline_debugfs_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &kbasep_trace_timeline_seq_ops); +} + +static const struct file_operations kbasep_trace_timeline_debugfs_fops = { + .open = kbasep_trace_timeline_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +mali_error kbasep_trace_timeline_debugfs_init(struct kbase_device *kbdev) +{ + kbdev->timeline.dentry = debugfs_create_file("mali_timeline_defs", + S_IRUGO, kbdev->mali_debugfs_directory, NULL, + &kbasep_trace_timeline_debugfs_fops); + if (IS_ERR(kbdev->timeline.dentry)) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +void kbasep_trace_timeline_debugfs_term(struct kbase_device *kbdev) +{ + debugfs_remove(kbdev->timeline.dentry); +} + +void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js) +{ + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + if (kbdev->timeline.slot_atoms_submitted[js] > 0) { + KBASE_TIMELINE_JOB_START_NEXT(kctx, js, 1); + } else { + base_atom_id atom_number = kbase_jd_atom_id(kctx, katom); + KBASE_TIMELINE_JOB_START_HEAD(kctx, js, 1); + KBASE_TIMELINE_JOB_START(kctx, js, atom_number); + } + ++kbdev->timeline.slot_atoms_submitted[js]; + + KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, kbdev->timeline.slot_atoms_submitted[js]); +} + +void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code) +{ + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT) { + KBASE_TIMELINE_JOB_START_NEXT(kctx, js, 0); + } else { + /* Job finished in JS_HEAD */ + base_atom_id atom_number = kbase_jd_atom_id(kctx, katom); + KBASE_TIMELINE_JOB_START_HEAD(kctx, js, 0); + KBASE_TIMELINE_JOB_STOP(kctx, js, atom_number); + /* see if we need to trace the job in JS_NEXT moving to JS_HEAD */ + if (kbdev->timeline.slot_atoms_submitted[js] > 1) { + /* Tag events with next_katom's kctx */ + struct kbase_jm_slot *slot = &kbdev->jm_slots[js]; + struct kbase_jd_atom *next_katom; + struct kbase_context *next_kctx; + KBASE_DEBUG_ASSERT(kbasep_jm_nr_jobs_submitted(slot) > 0); + + /* Peek the next atom - note that the atom in JS_HEAD will already + * have been dequeued */ + next_katom = kbasep_jm_peek_idx_submit_slot(slot, 0); + next_kctx = next_katom->kctx; + KBASE_TIMELINE_JOB_START_NEXT(next_kctx, js, 0); + KBASE_TIMELINE_JOB_START_HEAD(next_kctx, js, 1); + KBASE_TIMELINE_JOB_START(next_kctx, js, kbase_jd_atom_id(next_kctx, next_katom)); + } + } + + --kbdev->timeline.slot_atoms_submitted[js]; + + KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, kbdev->timeline.slot_atoms_submitted[js]); +} + +void kbase_timeline_pm_send_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event_sent) +{ + int uid = 0; + int old_uid; + + /* If a producer already exists for the event, try to use their UID (multiple-producers) */ + uid = atomic_read(&kbdev->timeline.pm_event_uid[event_sent]); + old_uid = uid; + + /* Get a new non-zero UID if we don't have one yet */ + while (!uid) + uid = atomic_inc_return(&kbdev->timeline.pm_event_uid_counter); + + /* Try to use this UID */ + if (old_uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event_sent], old_uid, uid)) + /* If it changed, raced with another producer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_sent, uid); +} + +void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ + int uid = atomic_read(&kbdev->timeline.pm_event_uid[event]); + + if (uid != 0) { + if (uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event], uid, 0)) + /* If it changed, raced with another consumer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event, uid); + } +} + +void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ + int uid = atomic_read(&kbdev->timeline.pm_event_uid[event]); + + if (uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event], uid, 0)) + /* If it changed, raced with another consumer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event, uid); +} + +void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.power_change_lock); + /* Simply log the start of the transition */ + kbdev->timeline.l2_transitioning = MALI_TRUE; + KBASE_TIMELINE_POWERING_L2(kbdev); +} + +void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.power_change_lock); + /* Simply log the end of the transition */ + if (MALI_FALSE != kbdev->timeline.l2_transitioning) + { + kbdev->timeline.l2_transitioning = MALI_FALSE; + KBASE_TIMELINE_POWERED_L2(kbdev); + } +} + +#endif /* CONFIG_MALI_TRACE_TIMELINE */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.h new file mode 100644 index 0000000000000000000000000000000000000000..63cacff66e1c36c4fe8729a7b5a47ddb5305de08 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.h @@ -0,0 +1,380 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#if !defined(_KBASE_TRACE_TIMELINE_H) +#define _KBASE_TRACE_TIMELINE_H + +#ifdef CONFIG_MALI_TRACE_TIMELINE + +typedef enum +{ + #define KBASE_TIMELINE_TRACE_CODE(enum_val, desc, format, format_desc) enum_val + #include "mali_kbase_trace_timeline_defs.h" + #undef KBASE_TIMELINE_TRACE_CODE +} kbase_trace_timeline_code; + +/** Initialize Timeline DebugFS entries */ +mali_error kbasep_trace_timeline_debugfs_init(struct kbase_device *kbdev); +/** Terminate Timeline DebugFS entries */ +void kbasep_trace_timeline_debugfs_term(struct kbase_device *kbdev); + +/* mali_timeline.h defines kernel tracepoints used by the KBASE_TIMELINE + * functions. + * Output is timestamped by either sched_clock() (default), local_clock(), or + * cpu_clock(), depending on /sys/kernel/debug/tracing/trace_clock */ +#include "mali_timeline.h" + +/* Trace number of atoms in flight for kctx (atoms either not completed, or in + process of being returned to user */ +#define KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_atoms_in_flight(ts.tv_sec, ts.tv_nsec, \ + (int)kctx->timeline.owner_tgid, \ + count); \ + } while (0) + +/* Trace atom_id being Ready to Run */ +#define KBASE_TIMELINE_ATOM_READY(kctx, atom_id) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_atom(ts.tv_sec, ts.tv_nsec, \ + CTX_FLOW_ATOM_READY, \ + (int)kctx->timeline.owner_tgid, \ + atom_id); \ + } while (0) + +/* Trace number of atoms submitted to job slot js + * + * NOTE: This uses a different tracepoint to the head/next/soft-stop actions, + * so that those actions can be filtered out separately from this + * + * This is because this is more useful, as we can use it to calculate general + * utilization easily and accurately */ +#define KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_slot_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_ACTIVE, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + + +/* Trace atoms present in JS_NEXT */ +#define KBASE_TIMELINE_JOB_START_NEXT(kctx, js, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_NEXT, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + +/* Trace atoms present in JS_HEAD */ +#define KBASE_TIMELINE_JOB_START_HEAD(kctx, js, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_HEAD, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + +/* Trace that a soft stop/evict from next is being attempted on a slot */ +#define KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_STOPPING, \ + (kctx) ? (int)kctx->timeline.owner_tgid : 0, \ + js, count); \ + } while (0) + + + +/* Trace state of overall GPU power */ +#define KBASE_TIMELINE_GPU_POWER(kbdev, active) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_ACTIVE, active); \ + } while (0) + +/* Trace state of tiler power */ +#define KBASE_TIMELINE_POWER_TILER(kbdev, bitmap) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_TILER_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace number of shaders currently powered */ +#define KBASE_TIMELINE_POWER_SHADER(kbdev, bitmap) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_SHADER_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace state of L2 power */ +#define KBASE_TIMELINE_POWER_L2(kbdev, bitmap) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_L2_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace state of L2 cache*/ +#define KBASE_TIMELINE_POWERING_L2(kbdev) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_l2_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_GPU_POWER_L2_POWERING, \ + 1); \ + } while (0) + +#define KBASE_TIMELINE_POWERED_L2(kbdev) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_l2_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_GPU_POWER_L2_ACTIVE, \ + 1); \ + } while (0) + +/* Trace kbase_pm_send_event message send */ +#define KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_type, pm_event_id) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_pm_event(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_PM_SEND_EVENT, \ + event_type, pm_event_id); \ + } while (0) + +/* Trace kbase_pm_worker message receive */ +#define KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event_type, pm_event_id) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_pm_event(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_PM_HANDLE_EVENT, \ + event_type, pm_event_id); \ + } while (0) + + +/* Trace atom_id starting in JS_HEAD */ +#define KBASE_TIMELINE_JOB_START(kctx, js, _consumerof_atom_number) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_slot_atom(ts.tv_sec, ts.tv_nsec, \ + HW_START_GPU_JOB_CHAIN_SW_APPROX, \ + (int)kctx->timeline.owner_tgid, \ + js, _consumerof_atom_number); \ + } while (0) + +/* Trace atom_id stopping on JS_HEAD */ +#define KBASE_TIMELINE_JOB_STOP(kctx, js, _producerof_atom_number_completed) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_slot_atom(ts.tv_sec, ts.tv_nsec, \ + HW_STOP_GPU_JOB_CHAIN_SW_APPROX, \ + (int)kctx->timeline.owner_tgid, \ + js, _producerof_atom_number_completed); \ + } while (0) + +/** Trace beginning/end of a call to kbase_pm_check_transitions_nolock from a + * certin caller */ +#define KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_pm_checktrans(ts.tv_sec, ts.tv_nsec, \ + trace_code, \ + 1); \ + } while (0) + +/* Trace number of contexts active */ +#define KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_context_active(ts.tv_sec, ts.tv_nsec, \ + count); \ + } while (0) + + +/* NOTE: kbase_timeline_pm_cores_func() is in mali_kbase_pm_policy.c */ + +/** + * Trace that an atom is starting on a job slot + * + * The caller must be holding kbasep_js_device_data::runpool_irq::lock + */ +void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js); + +/** + * Trace that an atom has done on a job slot + * + * 'Done' in this sense can occur either because: + * - the atom in JS_HEAD finished + * - the atom in JS_NEXT was evicted + * + * Whether the atom finished or was evicted is passed in @a done_code + * + * It is assumed that the atom has already been removed from the submit slot, + * with either: + * - kbasep_jm_dequeue_submit_slot() + * - kbasep_jm_dequeue_tail_submit_slot() + * + * The caller must be holding kbasep_js_device_data::runpool_irq::lock + */ +void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code); + + +/** Trace a pm event starting */ +void kbase_timeline_pm_send_event(struct kbase_device *kbdev, + enum kbase_timeline_pm_event event_sent); + +/** Trace a pm event finishing */ +void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event); + +/** Check whether a pm event was present, and if so trace finishing it */ +void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event); + +/** Trace L2 power-up start */ +void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev); + +/** Trace L2 power-up done */ +void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev); + +#else + +#define KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, count) CSTD_NOP() + +#define KBASE_TIMELINE_ATOM_READY(kctx, atom_id) CSTD_NOP() + +#define KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START_NEXT(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START_HEAD(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_GPU_POWER(kbdev, active) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_TILER(kbdev, bitmap) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_SHADER(kbdev, bitmap) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_L2(kbdev, active) CSTD_NOP() + +#define KBASE_TIMELINE_POWERING_L2(kbdev) CSTD_NOP() + +#define KBASE_TIMELINE_POWERED_L2(kbdev) CSTD_NOP() + +#define KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_type, pm_event_id) CSTD_NOP() + +#define KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event_type, pm_event_id) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START(kctx, js, _consumerof_atom_number) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_STOP(kctx, js, _producerof_atom_number_completed) CSTD_NOP() + +#define KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code) CSTD_NOP() + +#define KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, count) CSTD_NOP() + +static INLINE void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js) +{ + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); +} + +static INLINE void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code) +{ + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); +} + +static INLINE void kbase_timeline_pm_send_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event_sent) +{ +} + +static INLINE void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ +} + +static INLINE void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ +} + +static INLINE void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev) +{ + +} + +static INLINE void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev) +{ + +} +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +#endif /* _KBASE_TRACE_TIMELINE_H */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline_defs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..04d414cd0db95f9a619461f0d6f0d488cc92aed4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline_defs.h @@ -0,0 +1,134 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* ***** IMPORTANT: THIS IS NOT A NORMAL HEADER FILE ***** + * ***** DO NOT INCLUDE DIRECTLY ***** + * ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ + +/* + * Conventions on Event Names: + * + * - The prefix determines something about how the timeline should be + * displayed, and is split up into various parts, separated by underscores: + * - 'SW' and 'HW' as the first part will be used to determine whether a + * timeline is to do with Software or Hardware - effectively, separate + * 'channels' for Software and Hardware + * - 'START', 'STOP', 'ENTER', 'LEAVE' can be used in the second part, and + * signify related pairs of events - these are optional. + * - 'FLOW' indicates a generic event, which can use dependencies + * - This gives events such as: + * - 'SW_ENTER_FOO' + * - 'SW_LEAVE_FOO' + * - 'SW_FLOW_BAR_1' + * - 'SW_FLOW_BAR_2' + * - 'HW_START_BAZ' + * - 'HW_STOP_BAZ' + * - And an unadorned HW event: + * - 'HW_BAZ_FROZBOZ' + */ + +/* + * Conventions on parameter names: + * - anything with 'instance' in the name will have a separate timeline based + * on that instances. + * - underscored-prefixed parameters will by hidden by default on timelines + * + * Hence: + * - Different job slots have their own 'instance', based on the instance value + * - Per-context info (e.g. atoms on a context) have their own 'instance' + * (i.e. each context should be on a different timeline) + * + * Note that globally-shared resources can be tagged with a tgid, but we don't + * want an instance per context: + * - There's no point having separate Job Slot timelines for each context, that + * would be confusing - there's only really 3 job slots! + * - There's no point having separate Shader-powered timelines for each + * context, that would be confusing - all shader cores (whether it be 4, 8, + * etc) are shared in the system. + */ + + /* + * CTX events + */ + /* Separate timelines for each context 'instance'*/ + KBASE_TIMELINE_TRACE_CODE(CTX_SET_NR_ATOMS_IN_FLIGHT, "CTX: Atoms in flight", "%d,%d", "_instance_tgid,_value_number_of_atoms"), + KBASE_TIMELINE_TRACE_CODE(CTX_FLOW_ATOM_READY, "CTX: Atoms Ready to Run", "%d,%d,%d", "_instance_tgid,_consumerof_atom_number,_producerof_atom_number_ready"), + + /* + * SW Events + */ + /* Separate timelines for each slot 'instance' */ + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_ACTIVE, "SW: GPU slot active", "%d,%d,%d", "_tgid,_instance_slot,_value_number_of_atoms"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_NEXT, "SW: GPU atom in NEXT", "%d,%d,%d", "_tgid,_instance_slot,_value_is_an_atom_in_next"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_HEAD, "SW: GPU atom in HEAD", "%d,%d,%d", "_tgid,_instance_slot,_value_is_an_atom_in_head"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_STOPPING, "SW: Try Soft-Stop on GPU slot", "%d,%d,%d", "_tgid,_instance_slot,_value_is_slot_stopping"), + /* Shader and overall power is shared - can't have separate instances of + * it, just tagging with the context */ + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_ACTIVE, "SW: GPU power active", "%d,%d", "_tgid,_value_is_power_active"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_TILER_ACTIVE, "SW: GPU tiler powered", "%d,%d", "_tgid,_value_number_of_tilers"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_SHADER_ACTIVE, "SW: GPU shaders powered", "%d,%d", "_tgid,_value_number_of_shaders"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_L2_ACTIVE, "SW: GPU L2 powered", "%d,%d", "_tgid,_value_number_of_l2"), + + /* SW Power event messaging. _event_type is one from the kbase_pm_event enum */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_SEND_EVENT, "SW: PM Send Event", "%d,%d,%d", "_tgid,_event_type,_writerof_pm_event_id"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_HANDLE_EVENT, "SW: PM Handle Event", "%d,%d,%d", "_tgid,_event_type,_finalconsumerof_pm_event_id"), + /* SW L2 power events */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_GPU_POWER_L2_POWERING, "SW: GPU L2 powering", "%d,%d", "_tgid,_writerof_l2_transitioning"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_GPU_POWER_L2_ACTIVE, "SW: GPU L2 powering done", "%d,%d", "_tgid,_finalconsumerof_l2_transitioning"), + + KBASE_TIMELINE_TRACE_CODE(SW_SET_CONTEXT_ACTIVE, "SW: Context Active", "%d,%d", "_tgid,_value_active"), + + /* + * BEGIN: Significant SW Functions that call kbase_pm_check_transitions_nolock() + */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_START, "SW: PM CheckTrans from kbase_pm_do_poweroff", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_poweroff"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_END, "SW: PM CheckTrans from kbase_pm_do_poweroff", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_poweroff"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_START, "SW: PM CheckTrans from kbase_pm_do_poweron", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_poweron"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_END, "SW: PM CheckTrans from kbase_pm_do_poweron", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_poweron"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_START, "SW: PM CheckTrans from kbase_gpu_interrupt", "%d,%d", "_tgid,_writerof_pm_checktrans_gpu_interrupt"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_END, "SW: PM CheckTrans from kbase_gpu_interrupt", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_gpu_interrupt"), + + /* + * Significant Indirect callers of kbase_pm_check_transitions_nolock() + */ + /* kbase_pm_request_cores */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_START, "SW: PM CheckTrans from kbase_pm_request_cores(shader)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_END, "SW: PM CheckTrans from kbase_pm_request_cores(shader)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_START, "SW: PM CheckTrans from kbase_pm_request_cores(tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_END, "SW: PM CheckTrans from kbase_pm_request_cores(tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_START, "SW: PM CheckTrans from kbase_pm_request_cores(shader+tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_END, "SW: PM CheckTrans from kbase_pm_request_cores(shader+tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_shader_tiler"), + /* kbase_pm_release_cores */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_START, "SW: PM CheckTrans from kbase_pm_release_cores(shader)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_END, "SW: PM CheckTrans from kbase_pm_release_cores(shader)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_START, "SW: PM CheckTrans from kbase_pm_release_cores(tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_END, "SW: PM CheckTrans from kbase_pm_release_cores(tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_START, "SW: PM CheckTrans from kbase_pm_release_cores(shader+tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_END, "SW: PM CheckTrans from kbase_pm_release_cores(shader+tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_START, "SW: PM CheckTrans from kbasep_pm_do_shader_poweroff_callback", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_shader_poweroff_callback"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_END, "SW: PM CheckTrans from kbasep_pm_do_shader_poweroff_callback", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_shader_poweroff_callback"), + /* + * END: SW Functions that call kbase_pm_check_transitions_nolock() + */ + + /* + * HW Events + */ + KBASE_TIMELINE_TRACE_CODE(HW_START_GPU_JOB_CHAIN_SW_APPROX, "HW: Job Chain start (SW approximated)", "%d,%d,%d", "_tgid,job_slot,_consumerof_atom_number_ready"), + KBASE_TIMELINE_TRACE_CODE(HW_STOP_GPU_JOB_CHAIN_SW_APPROX, "HW: Job Chain stop (SW approximated)", "%d,%d,%d", "_tgid,job_slot,_producerof_atom_number_completed") diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_uku.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_uku.h new file mode 100644 index 0000000000000000000000000000000000000000..0e2fecf33d77c8accabb1a615024b387b12a2c1b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_uku.h @@ -0,0 +1,477 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_UKU_H_ +#define _KBASE_UKU_H_ + +#include "mali_uk.h" +#include +#include "mali_base_kernel.h" + +/* This file needs to support being included from kernel and userside (which use different defines) */ +#if defined(CONFIG_MALI_ERROR_INJECT) +#define SUPPORT_MALI_ERROR_INJECT +#elif defined(MALI_ERROR_INJECT) +#if MALI_ERROR_INJECT +#define SUPPORT_MALI_ERROR_INJECT +#endif +#endif +#if defined(CONFIG_MALI_NO_MALI) +#define SUPPORT_MALI_NO_MALI +#elif defined(MALI_NO_MALI) +#if MALI_NO_MALI +#define SUPPORT_MALI_NO_MALI +#endif +#endif + +#if defined(SUPPORT_MALI_NO_MALI) || defined(SUPPORT_MALI_ERROR_INJECT) +#include "mali_kbase_model_dummy.h" +#endif + +#include "mali_kbase_gpuprops_types.h" + +#define BASE_UK_VERSION_MAJOR 8 +#define BASE_UK_VERSION_MINOR 0 + +struct kbase_uk_mem_alloc { + union uk_header header; + /* IN */ + u64 va_pages; + u64 commit_pages; + u64 extent; + /* IN/OUT */ + u64 flags; + /* OUT */ + u64 gpu_va; + u16 va_alignment; + u8 padding[6]; +}; + +struct kbase_uk_mem_free { + union uk_header header; + /* IN */ + mali_addr64 gpu_addr; + /* OUT */ +}; + +struct kbase_uk_mem_alias { + union uk_header header; + /* IN/OUT */ + u64 flags; + /* IN */ + u64 stride; + u64 nents; + union kbase_pointer ai; + /* OUT */ + u64 gpu_va; + u64 va_pages; +}; + +struct kbase_uk_mem_import { + union uk_header header; + /* IN */ + union kbase_pointer phandle; + u32 type; + u32 padding; + /* IN/OUT */ + u64 flags; + /* OUT */ + mali_addr64 gpu_va; + u64 va_pages; +}; + +struct kbase_uk_mem_flags_change { + union uk_header header; + /* IN */ + mali_addr64 gpu_va; + u64 flags; + u64 mask; +}; + +struct kbase_uk_job_submit { + union uk_header header; + /* IN */ + union kbase_pointer addr; + u32 nr_atoms; + u32 stride; /* bytes between atoms, i.e. sizeof(base_jd_atom_v2) */ + /* OUT */ +}; + +struct kbase_uk_post_term { + union uk_header header; +}; + +struct kbase_uk_sync_now { + union uk_header header; + + /* IN */ + struct base_syncset sset; + + /* OUT */ +}; + +struct kbase_uk_hwcnt_setup { + union uk_header header; + + /* IN */ + mali_addr64 dump_buffer; + u32 jm_bm; + u32 shader_bm; + u32 tiler_bm; + u32 l3_cache_bm; + u32 mmu_l2_bm; + u32 padding; + /* OUT */ +}; + +struct kbase_uk_hwcnt_dump { + union uk_header header; +}; + +struct kbase_uk_hwcnt_clear { + union uk_header header; +}; + +struct kbase_uk_fence_validate { + union uk_header header; + /* IN */ + s32 fd; + u32 padding; + /* OUT */ +}; + +struct kbase_uk_stream_create { + union uk_header header; + /* IN */ + char name[32]; + /* OUT */ + s32 fd; + u32 padding; +}; + +#ifdef BASE_LEGACY_UK7_SUPPORT +/** + * This structure is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ +#define BASE_CPU_PROPERTY_FLAG_LITTLE_ENDIAN F_BIT_0 +struct base_cpu_id_props { + /** + * CPU ID + */ + u32 id; + + /** + * CPU Part number + */ + u16 part; + /** + * ASCII code of implementer trademark + */ + u8 implementer; + + /** + * CPU Variant + */ + u8 variant; + /** + * CPU Architecture + */ + u8 arch; + + /** + * CPU revision + */ + u8 rev; + + /** + * Validity of CPU id where 0-invalid and + * 1-valid only if ALL the cpu_id props are valid + */ + u8 valid; + + u8 padding[1]; +}; + +/** + * This structure is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ +struct base_cpu_props { + u32 nr_cores; /**< Number of CPU cores */ + + /** + * CPU page size as a Logarithm to Base 2. The compile-time + * equivalent is @ref OSU_CONFIG_CPU_PAGE_SIZE_LOG2 + */ + u32 cpu_page_size_log2; + + /** + * CPU L1 Data cache line size as a Logarithm to Base 2. The compile-time + * equivalent is @ref OSU_CONFIG_CPU_L1_DCACHE_LINE_SIZE_LOG2. + */ + u32 cpu_l1_dcache_line_size_log2; + + /** + * CPU L1 Data cache size, in bytes. The compile-time equivalient is + * @ref OSU_CONFIG_CPU_L1_DCACHE_SIZE. + * + * This CPU Property is mainly provided to implement OpenCL's + * clGetDeviceInfo(), which allows the CL_DEVICE_GLOBAL_MEM_CACHE_SIZE + * hint to be queried. + */ + u32 cpu_l1_dcache_size; + + /** + * CPU Property Flags bitpattern. + * + * This is a combination of bits as specified by the macros prefixed with + * 'BASE_CPU_PROPERTY_FLAG_'. + */ + u32 cpu_flags; + + /** + * Maximum clock speed in MHz. + * @usecase 'Maximum' CPU Clock Speed information is required by OpenCL's + * clGetDeviceInfo() function for the CL_DEVICE_MAX_CLOCK_FREQUENCY hint. + */ + u32 max_cpu_clock_speed_mhz; + + /** + * @brief Total memory, in bytes. + * + * This is the theoretical maximum memory available to the CPU. It is + * unlikely that a client will be able to allocate all of this memory for + * their own purposes, but this at least provides an upper bound on the + * memory available to the CPU. + * + * This is required for OpenCL's clGetDeviceInfo() call when + * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL CPU devices. + */ + u64 available_memory_size; + + /** + * CPU ID detailed info + */ + struct base_cpu_id_props cpu_id; + + u32 padding; +}; + +/** + * This structure is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ +struct kbase_uk_cpuprops { + union uk_header header; + + /* IN */ + struct base_cpu_props props; + /* OUT */ +}; +#endif /* BASE_LEGACY_UK7_SUPPORT */ + +struct kbase_uk_gpuprops { + union uk_header header; + + /* IN */ + struct mali_base_gpu_props props; + /* OUT */ +}; + +struct kbase_uk_mem_query { + union uk_header header; + /* IN */ + mali_addr64 gpu_addr; +#define KBASE_MEM_QUERY_COMMIT_SIZE 1 +#define KBASE_MEM_QUERY_VA_SIZE 2 +#define KBASE_MEM_QUERY_FLAGS 3 + u64 query; + /* OUT */ + u64 value; +}; + +struct kbase_uk_mem_commit { + union uk_header header; + /* IN */ + mali_addr64 gpu_addr; + u64 pages; + /* OUT */ + u32 result_subcode; + u32 padding; +}; + +struct kbase_uk_find_cpu_offset { + union uk_header header; + /* IN */ + mali_addr64 gpu_addr; + u64 cpu_addr; + u64 size; + /* OUT */ + mali_size64 offset; +}; + +#define KBASE_GET_VERSION_BUFFER_SIZE 64 +struct kbase_uk_get_ddk_version { + union uk_header header; + /* OUT */ + char version_buffer[KBASE_GET_VERSION_BUFFER_SIZE]; + u32 version_string_size; + u32 padding; +}; + +struct kbase_uk_disjoint_query { + union uk_header header; + /* OUT */ + u32 counter; + u32 padding; +}; + +struct kbase_uk_set_flags { + union uk_header header; + /* IN */ + u32 create_flags; + u32 padding; +}; + +#if MALI_UNIT_TEST +#define TEST_ADDR_COUNT 4 +#define KBASE_TEST_BUFFER_SIZE 128 +typedef struct kbase_exported_test_data { + mali_addr64 test_addr[TEST_ADDR_COUNT]; /**< memory address */ + u32 test_addr_pages[TEST_ADDR_COUNT]; /**< memory size in pages */ + union kbase_pointer kctx; /**< base context created by process */ + union kbase_pointer mm; /**< pointer to process address space */ + u8 buffer1[KBASE_TEST_BUFFER_SIZE]; /**< unit test defined parameter */ + u8 buffer2[KBASE_TEST_BUFFER_SIZE]; /**< unit test defined parameter */ +} kbase_exported_test_data; + +struct kbase_uk_set_test_data { + union uk_header header; + /* IN */ + struct kbase_exported_test_data test_data; +}; + +#endif /* MALI_UNIT_TEST */ + +#ifdef SUPPORT_MALI_ERROR_INJECT +struct kbase_uk_error_params { + union uk_header header; + /* IN */ + struct kbase_error_params params; +}; +#endif /* SUPPORT_MALI_ERROR_INJECT */ + +#ifdef SUPPORT_MALI_NO_MALI +struct kbase_uk_model_control_params { + union uk_header header; + /* IN */ + struct kbase_model_control_params params; +}; +#endif /* SUPPORT_MALI_NO_MALI */ + +#define KBASE_MAXIMUM_EXT_RESOURCES 255 + +struct kbase_uk_ext_buff_kds_data { + union uk_header header; + union kbase_pointer external_resource; + union kbase_pointer file_descriptor; + u32 num_res; /* limited to KBASE_MAXIMUM_EXT_RESOURCES */ + u32 padding; +}; + +struct kbase_uk_keep_gpu_powered { + union uk_header header; + u32 enabled; + u32 padding; +}; + +struct kbase_uk_profiling_controls { + union uk_header header; + u32 profiling_controls[FBDUMP_CONTROL_MAX]; +}; + +struct kbase_uk_debugfs_mem_profile_add { + union uk_header header; + u32 len; + union kbase_pointer buf; +}; + +enum kbase_uk_function_id { + KBASE_FUNC_MEM_ALLOC = (UK_FUNC_ID + 0), + KBASE_FUNC_MEM_IMPORT = (UK_FUNC_ID + 1), + KBASE_FUNC_MEM_COMMIT = (UK_FUNC_ID + 2), + KBASE_FUNC_MEM_QUERY = (UK_FUNC_ID + 3), + KBASE_FUNC_MEM_FREE = (UK_FUNC_ID + 4), + KBASE_FUNC_MEM_FLAGS_CHANGE = (UK_FUNC_ID + 5), + KBASE_FUNC_MEM_ALIAS = (UK_FUNC_ID + 6), + +#ifdef BASE_LEGACY_UK6_SUPPORT + KBASE_FUNC_JOB_SUBMIT_UK6 = (UK_FUNC_ID + 7), +#endif /* BASE_LEGACY_UK6_SUPPORT */ + + KBASE_FUNC_SYNC = (UK_FUNC_ID + 8), + + KBASE_FUNC_POST_TERM = (UK_FUNC_ID + 9), + + KBASE_FUNC_HWCNT_SETUP = (UK_FUNC_ID + 10), + KBASE_FUNC_HWCNT_DUMP = (UK_FUNC_ID + 11), + KBASE_FUNC_HWCNT_CLEAR = (UK_FUNC_ID + 12), + +#ifdef BASE_LEGACY_UK7_SUPPORT + KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE = (UK_FUNC_ID + 13), +#endif /* BASE_LEGACY_UK7_SUPPORT */ + KBASE_FUNC_GPU_PROPS_REG_DUMP = (UK_FUNC_ID + 14), + + KBASE_FUNC_FIND_CPU_OFFSET = (UK_FUNC_ID + 15), + + KBASE_FUNC_GET_VERSION = (UK_FUNC_ID + 16), + KBASE_FUNC_EXT_BUFFER_LOCK = (UK_FUNC_ID + 17), + KBASE_FUNC_SET_FLAGS = (UK_FUNC_ID + 18), + + KBASE_FUNC_SET_TEST_DATA = (UK_FUNC_ID + 19), + KBASE_FUNC_INJECT_ERROR = (UK_FUNC_ID + 20), + KBASE_FUNC_MODEL_CONTROL = (UK_FUNC_ID + 21), + + KBASE_FUNC_KEEP_GPU_POWERED = (UK_FUNC_ID + 22), + + KBASE_FUNC_FENCE_VALIDATE = (UK_FUNC_ID + 23), + KBASE_FUNC_STREAM_CREATE = (UK_FUNC_ID + 24), + KBASE_FUNC_GET_PROFILING_CONTROLS = (UK_FUNC_ID + 25), + KBASE_FUNC_SET_PROFILING_CONTROLS = (UK_FUNC_ID + 26), + /* to be used only for testing + * purposes, otherwise these controls + * are set through gator API */ + + KBASE_FUNC_DEBUGFS_MEM_PROFILE_ADD = (UK_FUNC_ID + 27), + KBASE_FUNC_JOB_SUBMIT = (UK_FUNC_ID + 28), + KBASE_FUNC_DISJOINT_QUERY = (UK_FUNC_ID + 29) + +}; + +#endif /* _KBASE_UKU_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.c new file mode 100644 index 0000000000000000000000000000000000000000..d159872306c5ccbf6059b9b62718819c191af5a7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.c @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +mali_bool kbasep_list_member_of(const struct list_head *base, struct list_head *entry) +{ + struct list_head *pos = base->next; + + while (pos != base) { + if (pos == entry) + return MALI_TRUE; + + pos = pos->next; + } + return MALI_FALSE; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.h new file mode 100644 index 0000000000000000000000000000000000000000..59988163fd2eb1fa2f70d0af6f67f36e6aa8fcb9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.h @@ -0,0 +1,37 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_UTILITY_H +#define _KBASE_UTILITY_H + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +/** Test whether the given list entry is a member of the given list. + * + * @param base The head of the list to be tested + * @param entry The list entry to be tested + * + * @return MALI_TRUE if entry is a member of base + * MALI_FALSE otherwise + */ +mali_bool kbasep_list_member_of(const struct list_head *base, struct list_head *entry); + +#endif /* _KBASE_UTILITY_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_linux_kbase_trace.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_linux_kbase_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..20250592dd632c9965175209c74bbc0549b76e80 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_linux_kbase_trace.h @@ -0,0 +1,201 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#if !defined(_TRACE_MALI_KBASE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MALI_KBASE_H + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali + +#include + +DECLARE_EVENT_CLASS(mali_slot_template, + TP_PROTO(int jobslot, unsigned int info_val), + TP_ARGS(jobslot, info_val), + TP_STRUCT__entry( + __field(unsigned int, jobslot) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->jobslot = jobslot; + __entry->info_val = info_val; + ), + TP_printk("jobslot=%u info=%u", __entry->jobslot, __entry->info_val) +); + +#define DEFINE_MALI_SLOT_EVENT(name) \ +DEFINE_EVENT(mali_slot_template, mali_##name, \ + TP_PROTO(int jobslot, unsigned int info_val), \ + TP_ARGS(jobslot, info_val)) +DEFINE_MALI_SLOT_EVENT(JM_SUBMIT); +DEFINE_MALI_SLOT_EVENT(JM_JOB_DONE); +DEFINE_MALI_SLOT_EVENT(JM_UPDATE_HEAD); +DEFINE_MALI_SLOT_EVENT(JM_CHECK_HEAD); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP_0); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP_1); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP_0); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP_1); +DEFINE_MALI_SLOT_EVENT(JM_SLOT_SOFT_OR_HARD_STOP); +DEFINE_MALI_SLOT_EVENT(JM_SLOT_EVICT); +DEFINE_MALI_SLOT_EVENT(JM_BEGIN_RESET_WORKER); +DEFINE_MALI_SLOT_EVENT(JM_END_RESET_WORKER); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REGISTER_ON_RECHECK_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_AFFINITY_SUBMIT_TO_BLOCKED); +DEFINE_MALI_SLOT_EVENT(JS_AFFINITY_CURRENT); +DEFINE_MALI_SLOT_EVENT(JD_DONE_TRY_RUN_NEXT_JOB); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REQUEST_CORES_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REGISTER_INUSE_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REQUEST_ON_RECHECK_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_AFFINITY_WOULD_VIOLATE); +DEFINE_MALI_SLOT_EVENT(JS_JOB_DONE_TRY_RUN_NEXT_JOB); +DEFINE_MALI_SLOT_EVENT(JS_JOB_DONE_RETRY_NEEDED); +DEFINE_MALI_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB); +DEFINE_MALI_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB_IRQ); +#undef DEFINE_MALI_SLOT_EVENT + +DECLARE_EVENT_CLASS(mali_refcount_template, + TP_PROTO(int refcount, unsigned int info_val), + TP_ARGS(refcount, info_val), + TP_STRUCT__entry( + __field(unsigned int, refcount) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->refcount = refcount; + __entry->info_val = info_val; + ), + TP_printk("refcount=%u info=%u", __entry->refcount, __entry->info_val) +); + +#define DEFINE_MALI_REFCOUNT_EVENT(name) \ +DEFINE_EVENT(mali_refcount_template, mali_##name, \ + TP_PROTO(int refcount, unsigned int info_val), \ + TP_ARGS(refcount, info_val)) +DEFINE_MALI_REFCOUNT_EVENT(JS_RETAIN_CTX_NOLOCK); +DEFINE_MALI_REFCOUNT_EVENT(JS_ADD_JOB); +DEFINE_MALI_REFCOUNT_EVENT(JS_REMOVE_JOB); +DEFINE_MALI_REFCOUNT_EVENT(JS_RETAIN_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_RELEASE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_TRY_SCHEDULE_HEAD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_INIT_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_TERM_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_ENQUEUE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_DEQUEUE_HEAD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_TRY_EVICT_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_RUNPOOL_ADD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_RUNPOOL_REMOVE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_FOREACH_CTX_JOBS); +DEFINE_MALI_REFCOUNT_EVENT(PM_CONTEXT_ACTIVE); +DEFINE_MALI_REFCOUNT_EVENT(PM_CONTEXT_IDLE); +#undef DEFINE_MALI_REFCOUNT_EVENT + +DECLARE_EVENT_CLASS(mali_add_template, + TP_PROTO(int gpu_addr, unsigned int info_val), + TP_ARGS(gpu_addr, info_val), + TP_STRUCT__entry( + __field(unsigned int, gpu_addr) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->gpu_addr = gpu_addr; + __entry->info_val = info_val; + ), + TP_printk("gpu_addr=%u info=%u", __entry->gpu_addr, __entry->info_val) +); + +#define DEFINE_MALI_ADD_EVENT(name) \ +DEFINE_EVENT(mali_add_template, mali_##name, \ + TP_PROTO(int gpu_addr, unsigned int info_val), \ + TP_ARGS(gpu_addr, info_val)) +DEFINE_MALI_ADD_EVENT(CORE_CTX_DESTROY); +DEFINE_MALI_ADD_EVENT(CORE_CTX_HWINSTR_TERM); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ_CLEAR); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ_DONE); +DEFINE_MALI_ADD_EVENT(CORE_GPU_SOFT_RESET); +DEFINE_MALI_ADD_EVENT(CORE_GPU_HARD_RESET); +DEFINE_MALI_ADD_EVENT(CORE_GPU_PRFCNT_SAMPLE); +DEFINE_MALI_ADD_EVENT(CORE_GPU_PRFCNT_CLEAR); +DEFINE_MALI_ADD_EVENT(CORE_GPU_CLEAN_INV_CACHES); +DEFINE_MALI_ADD_EVENT(JD_DONE_WORKER); +DEFINE_MALI_ADD_EVENT(JD_DONE_WORKER_END); +DEFINE_MALI_ADD_EVENT(JD_CANCEL_WORKER); +DEFINE_MALI_ADD_EVENT(JD_DONE); +DEFINE_MALI_ADD_EVENT(JD_CANCEL); +DEFINE_MALI_ADD_EVENT(JD_ZAP_CONTEXT); +DEFINE_MALI_ADD_EVENT(JM_IRQ); +DEFINE_MALI_ADD_EVENT(JM_IRQ_END); +DEFINE_MALI_ADD_EVENT(JM_FLUSH_WORKQS); +DEFINE_MALI_ADD_EVENT(JM_FLUSH_WORKQS_DONE); +DEFINE_MALI_ADD_EVENT(JM_ZAP_NON_SCHEDULED); +DEFINE_MALI_ADD_EVENT(JM_ZAP_SCHEDULED); +DEFINE_MALI_ADD_EVENT(JM_ZAP_DONE); +DEFINE_MALI_ADD_EVENT(JM_SUBMIT_AFTER_RESET); +DEFINE_MALI_ADD_EVENT(JM_JOB_COMPLETE); +DEFINE_MALI_ADD_EVENT(JS_FAST_START_EVICTS_CTX); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_ON_RUNPOOL); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_OFF_RUNPOOL); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_ON_CTX); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_OFF_CTX); +DEFINE_MALI_ADD_EVENT(JS_POLICY_TIMER_END); +DEFINE_MALI_ADD_EVENT(JS_POLICY_TIMER_START); +DEFINE_MALI_ADD_EVENT(JS_POLICY_ENQUEUE_JOB); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_DESIRED); +DEFINE_MALI_ADD_EVENT(PM_JOB_SUBMIT_AFTER_POWERING_UP); +DEFINE_MALI_ADD_EVENT(PM_JOB_SUBMIT_AFTER_POWERED_UP); +DEFINE_MALI_ADD_EVENT(PM_PWRON); +DEFINE_MALI_ADD_EVENT(PM_PWRON_TILER); +DEFINE_MALI_ADD_EVENT(PM_PWRON_L2); +DEFINE_MALI_ADD_EVENT(PM_PWROFF); +DEFINE_MALI_ADD_EVENT(PM_PWROFF_TILER); +DEFINE_MALI_ADD_EVENT(PM_PWROFF_L2); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED_TILER); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED_L2); +DEFINE_MALI_ADD_EVENT(PM_DESIRED_REACHED); +DEFINE_MALI_ADD_EVENT(PM_DESIRED_REACHED_TILER); +DEFINE_MALI_ADD_EVENT(PM_UNREQUEST_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REQUEST_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REGISTER_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REGISTER_CHANGE_SHADER_INUSE); +DEFINE_MALI_ADD_EVENT(PM_RELEASE_CHANGE_SHADER_INUSE); +DEFINE_MALI_ADD_EVENT(PM_CORES_AVAILABLE); +DEFINE_MALI_ADD_EVENT(PM_CORES_AVAILABLE_TILER); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE_TILER); +DEFINE_MALI_ADD_EVENT(PM_GPU_ON); +DEFINE_MALI_ADD_EVENT(PM_GPU_OFF); +DEFINE_MALI_ADD_EVENT(PM_SET_POLICY); +DEFINE_MALI_ADD_EVENT(PM_CURRENT_POLICY_INIT); +DEFINE_MALI_ADD_EVENT(PM_CURRENT_POLICY_TERM); +DEFINE_MALI_ADD_EVENT(PM_CA_SET_POLICY); +DEFINE_MALI_ADD_EVENT(PM_WAKE_WAITERS); +#undef DEFINE_MALI_ADD_EVENT + +#endif /* _TRACE_MALI_KBASE_H */ + +#undef TRACE_INCLUDE_PATH +#undef linux +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mali_linux_kbase_trace + +/* This part must be outside protection */ +#include diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_linux_trace.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_linux_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..62207a45a898e77754d342e8f8a981b6b1a7b7ab --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_linux_trace.h @@ -0,0 +1,129 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#if !defined(_TRACE_MALI_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MALI_H + +#include +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali +#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM) +#define TRACE_INCLUDE_FILE mali_linux_trace + +#define MALI_JOB_SLOTS_EVENT_CHANGED + +/** + * mali_job_slots_event - called from mali_kbase_core_linux.c + * @event_id: ORed together bitfields representing a type of event, made with the GATOR_MAKE_EVENT() macro. + */ +TRACE_EVENT(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char atom_id, u32 job_id), TP_ARGS(event_id, tgid, pid, atom_id, job_id), TP_STRUCT__entry(__field(unsigned int, event_id) + __field(unsigned int, tgid) + __field(unsigned int, pid) + __field(unsigned char, job_id) + ), TP_fast_assign(__entry->event_id = event_id; __entry->tgid = tgid; __entry->pid = pid; __entry->atom_id = atom_id; __entry->job_id = job_id;), TP_printk("event=%u tgid=%u pid=%u atom_id=%u job_id=%u", __entry->event_id, __entry->tgid, __entry->pid, __entry->atom_id, __entry->job_id) + ); + +/** + * mali_pm_status - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache, l3 cache) + * @value: 64bits bitmask reporting either power status of the cores (1-ON, 0-OFF) + */ +TRACE_EVENT(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(unsigned int, event_id) + __field(unsigned long long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %u = %llu", __entry->event_id, __entry->value) + ); + +/** + * mali_pm_power_on - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache, l3 cache) + * @value: 64bits bitmask reporting the cores to power up + */ +TRACE_EVENT(mali_pm_power_on, TP_PROTO(unsigned int event_id, unsigned long long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(unsigned int, event_id) + __field(unsigned long long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %u = %llu", __entry->event_id, __entry->value) + ); + +/** + * mali_pm_power_off - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache, l3 cache) + * @value: 64bits bitmask reporting the cores to power down + */ +TRACE_EVENT(mali_pm_power_off, TP_PROTO(unsigned int event_id, unsigned long long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(unsigned int, event_id) + __field(unsigned long long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %u = %llu", __entry->event_id, __entry->value) + ); + +/** + * mali_page_fault_insert_pages - Called by page_fault_worker() + * it reports an MMU page fault resulting in new pages being mapped. + * @event_id: MMU address space number. + * @value: number of newly allocated pages + */ +TRACE_EVENT(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(int, event_id) + __field(unsigned long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %d = %lu", __entry->event_id, __entry->value) + ); + +/** + * mali_mmu_as_in_use - Called by assign_and_activate_kctx_addr_space() + * it reports that a certain MMU address space is in use now. + * @event_id: MMU address space number. + */ +TRACE_EVENT(mali_mmu_as_in_use, TP_PROTO(int event_id), TP_ARGS(event_id), TP_STRUCT__entry(__field(int, event_id) + ), TP_fast_assign(__entry->event_id = event_id;), TP_printk("event=%d", __entry->event_id) + ); + +/** + * mali_mmu_as_released - Called by kbasep_js_runpool_release_ctx_internal() + * it reports that a certain MMU address space has been released now. + * @event_id: MMU address space number. + */ +TRACE_EVENT(mali_mmu_as_released, TP_PROTO(int event_id), TP_ARGS(event_id), TP_STRUCT__entry(__field(int, event_id) + ), TP_fast_assign(__entry->event_id = event_id;), TP_printk("event=%d", __entry->event_id) + ); + +/** + * mali_total_alloc_pages_change - Called by kbase_atomic_add_pages() + * and by kbase_atomic_sub_pages() + * it reports that the total number of allocated pages is changed. + * @event_id: number of pages to be added or subtracted (according to the sign). + */ +TRACE_EVENT(mali_total_alloc_pages_change, TP_PROTO(long long int event_id), TP_ARGS(event_id), TP_STRUCT__entry(__field(long long int, event_id) + ), TP_fast_assign(__entry->event_id = event_id;), TP_printk("event=%lld", __entry->event_id) + ); + +/** + * mali_sw_counter - not currently used + * @event_id: counter id + */ +TRACE_EVENT(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(int, event_id) + __field(long long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %d = %lld", __entry->event_id, __entry->value) + ); + +#endif /* _TRACE_MALI_H */ + +#undef TRACE_INCLUDE_PATH +#undef linux +#define TRACE_INCLUDE_PATH . + +/* This part must be outside protection */ +#include diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_midg_regmap.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_midg_regmap.h new file mode 100644 index 0000000000000000000000000000000000000000..a6231183a9a5796c44e158aace0afd636bb0df0b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_midg_regmap.h @@ -0,0 +1,527 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _MIDGARD_REGMAP_H_ +#define _MIDGARD_REGMAP_H_ + +/* + * Begin Register Offsets + */ + +#define GPU_CONTROL_BASE 0x0000 +#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r)) +#define GPU_ID 0x000 /* (RO) GPU and revision identifier */ +#define L2_FEATURES 0x004 /* (RO) Level 2 cache features */ +#define L3_FEATURES 0x008 /* (RO) Level 3 cache features */ +#define TILER_FEATURES 0x00C /* (RO) Tiler Features */ +#define MEM_FEATURES 0x010 /* (RO) Memory system features */ +#define MMU_FEATURES 0x014 /* (RO) MMU features */ +#define AS_PRESENT 0x018 /* (RO) Address space slots present */ +#define JS_PRESENT 0x01C /* (RO) Job slots present */ +#define GPU_IRQ_RAWSTAT 0x020 /* (RW) */ +#define GPU_IRQ_CLEAR 0x024 /* (WO) */ +#define GPU_IRQ_MASK 0x028 /* (RW) */ +#define GPU_IRQ_STATUS 0x02C /* (RO) */ + +/* IRQ flags */ +#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */ +#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */ +#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. Intended to use with SOFT_RESET + commands which may take time. */ +#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */ +#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down + and the power manager is idle. */ + +#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */ +#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */ + +#define GPU_IRQ_REG_ALL (GPU_FAULT | MULTIPLE_GPU_FAULTS | RESET_COMPLETED \ + | POWER_CHANGED_ALL | PRFCNT_SAMPLE_COMPLETED) + +#define GPU_COMMAND 0x030 /* (WO) */ +#define GPU_STATUS 0x034 /* (RO) */ + +#define GROUPS_L2_COHERENT (1 << 0) /* Cores groups are l2 coherent */ +#define GROUPS_L3_COHERENT (1 << 1) /* Cores groups are l3 coherent */ + +#define GPU_FAULTSTATUS 0x03C /* (RO) GPU exception type and fault status */ +#define GPU_FAULTADDRESS_LO 0x040 /* (RO) GPU exception fault address, low word */ +#define GPU_FAULTADDRESS_HI 0x044 /* (RO) GPU exception fault address, high word */ + +#define PWR_KEY 0x050 /* (WO) Power manager key register */ +#define PWR_OVERRIDE0 0x054 /* (RW) Power manager override settings */ +#define PWR_OVERRIDE1 0x058 /* (RW) Power manager override settings */ + +#define PRFCNT_BASE_LO 0x060 /* (RW) Performance counter memory region base address, low word */ +#define PRFCNT_BASE_HI 0x064 /* (RW) Performance counter memory region base address, high word */ +#define PRFCNT_CONFIG 0x068 /* (RW) Performance counter configuration */ +#define PRFCNT_JM_EN 0x06C /* (RW) Performance counter enable flags for Job Manager */ +#define PRFCNT_SHADER_EN 0x070 /* (RW) Performance counter enable flags for shader cores */ +#define PRFCNT_TILER_EN 0x074 /* (RW) Performance counter enable flags for tiler */ +#define PRFCNT_L3_CACHE_EN 0x078 /* (RW) Performance counter enable flags for L3 cache */ +#define PRFCNT_MMU_L2_EN 0x07C /* (RW) Performance counter enable flags for MMU/L2 cache */ + +#define CYCLE_COUNT_LO 0x090 /* (RO) Cycle counter, low word */ +#define CYCLE_COUNT_HI 0x094 /* (RO) Cycle counter, high word */ +#define TIMESTAMP_LO 0x098 /* (RO) Global time stamp counter, low word */ +#define TIMESTAMP_HI 0x09C /* (RO) Global time stamp counter, high word */ + +#define THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */ +#define THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */ +#define THREAD_MAX_BARRIER_SIZE 0x0A8 /* (RO) Maximum threads waiting at a barrier */ +#define THREAD_FEATURES 0x0AC /* (RO) Thread features */ + +#define TEXTURE_FEATURES_0 0x0B0 /* (RO) Support flags for indexed texture formats 0..31 */ +#define TEXTURE_FEATURES_1 0x0B4 /* (RO) Support flags for indexed texture formats 32..63 */ +#define TEXTURE_FEATURES_2 0x0B8 /* (RO) Support flags for indexed texture formats 64..95 */ + +#define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2)) + +#define JS0_FEATURES 0x0C0 /* (RO) Features of job slot 0 */ +#define JS1_FEATURES 0x0C4 /* (RO) Features of job slot 1 */ +#define JS2_FEATURES 0x0C8 /* (RO) Features of job slot 2 */ +#define JS3_FEATURES 0x0CC /* (RO) Features of job slot 3 */ +#define JS4_FEATURES 0x0D0 /* (RO) Features of job slot 4 */ +#define JS5_FEATURES 0x0D4 /* (RO) Features of job slot 5 */ +#define JS6_FEATURES 0x0D8 /* (RO) Features of job slot 6 */ +#define JS7_FEATURES 0x0DC /* (RO) Features of job slot 7 */ +#define JS8_FEATURES 0x0E0 /* (RO) Features of job slot 8 */ +#define JS9_FEATURES 0x0E4 /* (RO) Features of job slot 9 */ +#define JS10_FEATURES 0x0E8 /* (RO) Features of job slot 10 */ +#define JS11_FEATURES 0x0EC /* (RO) Features of job slot 11 */ +#define JS12_FEATURES 0x0F0 /* (RO) Features of job slot 12 */ +#define JS13_FEATURES 0x0F4 /* (RO) Features of job slot 13 */ +#define JS14_FEATURES 0x0F8 /* (RO) Features of job slot 14 */ +#define JS15_FEATURES 0x0FC /* (RO) Features of job slot 15 */ + +#define JS_FEATURES_REG(n) GPU_CONTROL_REG(JS0_FEATURES + ((n) << 2)) + +#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ +#define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */ + +#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ +#define TILER_PRESENT_HI 0x114 /* (RO) Tiler core present bitmap, high word */ + +#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ +#define L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */ + +#define L3_PRESENT_LO 0x130 /* (RO) Level 3 cache present bitmap, low word */ +#define L3_PRESENT_HI 0x134 /* (RO) Level 3 cache present bitmap, high word */ + +#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */ +#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */ + +#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */ +#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */ + +#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */ +#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */ + +#define L3_READY_LO 0x170 /* (RO) Level 3 cache ready bitmap, low word */ +#define L3_READY_HI 0x174 /* (RO) Level 3 cache ready bitmap, high word */ + +#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */ +#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */ + +#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */ +#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */ + +#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */ +#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */ + +#define L3_PWRON_LO 0x1B0 /* (WO) Level 3 cache power on bitmap, low word */ +#define L3_PWRON_HI 0x1B4 /* (WO) Level 3 cache power on bitmap, high word */ + +#define SHADER_PWROFF_LO 0x1C0 /* (WO) Shader core power off bitmap, low word */ +#define SHADER_PWROFF_HI 0x1C4 /* (WO) Shader core power off bitmap, high word */ + +#define TILER_PWROFF_LO 0x1D0 /* (WO) Tiler core power off bitmap, low word */ +#define TILER_PWROFF_HI 0x1D4 /* (WO) Tiler core power off bitmap, high word */ + +#define L2_PWROFF_LO 0x1E0 /* (WO) Level 2 cache power off bitmap, low word */ +#define L2_PWROFF_HI 0x1E4 /* (WO) Level 2 cache power off bitmap, high word */ + +#define L3_PWROFF_LO 0x1F0 /* (WO) Level 3 cache power off bitmap, low word */ +#define L3_PWROFF_HI 0x1F4 /* (WO) Level 3 cache power off bitmap, high word */ + +#define SHADER_PWRTRANS_LO 0x200 /* (RO) Shader core power transition bitmap, low word */ +#define SHADER_PWRTRANS_HI 0x204 /* (RO) Shader core power transition bitmap, high word */ + +#define TILER_PWRTRANS_LO 0x210 /* (RO) Tiler core power transition bitmap, low word */ +#define TILER_PWRTRANS_HI 0x214 /* (RO) Tiler core power transition bitmap, high word */ + +#define L2_PWRTRANS_LO 0x220 /* (RO) Level 2 cache power transition bitmap, low word */ +#define L2_PWRTRANS_HI 0x224 /* (RO) Level 2 cache power transition bitmap, high word */ + +#define L3_PWRTRANS_LO 0x230 /* (RO) Level 3 cache power transition bitmap, low word */ +#define L3_PWRTRANS_HI 0x234 /* (RO) Level 3 cache power transition bitmap, high word */ + +#define SHADER_PWRACTIVE_LO 0x240 /* (RO) Shader core active bitmap, low word */ +#define SHADER_PWRACTIVE_HI 0x244 /* (RO) Shader core active bitmap, high word */ + +#define TILER_PWRACTIVE_LO 0x250 /* (RO) Tiler core active bitmap, low word */ +#define TILER_PWRACTIVE_HI 0x254 /* (RO) Tiler core active bitmap, high word */ + +#define L2_PWRACTIVE_LO 0x260 /* (RO) Level 2 cache active bitmap, low word */ +#define L2_PWRACTIVE_HI 0x264 /* (RO) Level 2 cache active bitmap, high word */ + +#define L3_PWRACTIVE_LO 0x270 /* (RO) Level 3 cache active bitmap, low word */ +#define L3_PWRACTIVE_HI 0x274 /* (RO) Level 3 cache active bitmap, high word */ + +#define SHADER_CONFIG 0xF04 /* (RW) Shader core configuration settings (Implementation specific register) */ +#define TILER_CONFIG 0xF08 /* (RW) Tiler core configuration settings (Implementation specific register) */ +#define L2_MMU_CONFIG 0xF0C /* (RW) Configuration of the L2 cache and MMU (Implementation specific register) */ + +#define JOB_CONTROL_BASE 0x1000 + +#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r)) + +#define JOB_IRQ_RAWSTAT 0x000 /* Raw interrupt status register */ +#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */ +#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */ +#define JOB_IRQ_STATUS 0x00C /* Interrupt status register */ +#define JOB_IRQ_JS_STATE 0x010 /* status==active and _next == busy snapshot from last JOB_IRQ_CLEAR */ +#define JOB_IRQ_THROTTLE 0x014 /* cycles to delay delivering an interrupt externally. The JOB_IRQ_STATUS is NOT affected by this, just the delivery of the interrupt. */ + +#define JOB_SLOT0 0x800 /* Configuration registers for job slot 0 */ +#define JOB_SLOT1 0x880 /* Configuration registers for job slot 1 */ +#define JOB_SLOT2 0x900 /* Configuration registers for job slot 2 */ +#define JOB_SLOT3 0x980 /* Configuration registers for job slot 3 */ +#define JOB_SLOT4 0xA00 /* Configuration registers for job slot 4 */ +#define JOB_SLOT5 0xA80 /* Configuration registers for job slot 5 */ +#define JOB_SLOT6 0xB00 /* Configuration registers for job slot 6 */ +#define JOB_SLOT7 0xB80 /* Configuration registers for job slot 7 */ +#define JOB_SLOT8 0xC00 /* Configuration registers for job slot 8 */ +#define JOB_SLOT9 0xC80 /* Configuration registers for job slot 9 */ +#define JOB_SLOT10 0xD00 /* Configuration registers for job slot 10 */ +#define JOB_SLOT11 0xD80 /* Configuration registers for job slot 11 */ +#define JOB_SLOT12 0xE00 /* Configuration registers for job slot 12 */ +#define JOB_SLOT13 0xE80 /* Configuration registers for job slot 13 */ +#define JOB_SLOT14 0xF00 /* Configuration registers for job slot 14 */ +#define JOB_SLOT15 0xF80 /* Configuration registers for job slot 15 */ + +#define JOB_SLOT_REG(n, r) (JOB_CONTROL_REG(JOB_SLOT0 + ((n) << 7)) + (r)) + +#define JS_HEAD_LO 0x00 /* (RO) Job queue head pointer for job slot n, low word */ +#define JS_HEAD_HI 0x04 /* (RO) Job queue head pointer for job slot n, high word */ +#define JS_TAIL_LO 0x08 /* (RO) Job queue tail pointer for job slot n, low word */ +#define JS_TAIL_HI 0x0C /* (RO) Job queue tail pointer for job slot n, high word */ +#define JS_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */ +#define JS_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */ +#define JS_CONFIG 0x18 /* (RO) Configuration settings for job slot n */ + +#define JS_COMMAND 0x20 /* (WO) Command register for job slot n */ +#define JS_STATUS 0x24 /* (RO) Status register for job slot n */ + +#define JS_HEAD_NEXT_LO 0x40 /* (RW) Next job queue head pointer for job slot n, low word */ +#define JS_HEAD_NEXT_HI 0x44 /* (RW) Next job queue head pointer for job slot n, high word */ + +#define JS_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */ +#define JS_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */ +#define JS_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */ + +#define JS_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */ + +#define MEMORY_MANAGEMENT_BASE 0x2000 +#define MMU_REG(r) (MEMORY_MANAGEMENT_BASE + (r)) + +#define MMU_IRQ_RAWSTAT 0x000 /* (RW) Raw interrupt status register */ +#define MMU_IRQ_CLEAR 0x004 /* (WO) Interrupt clear register */ +#define MMU_IRQ_MASK 0x008 /* (RW) Interrupt mask register */ +#define MMU_IRQ_STATUS 0x00C /* (RO) Interrupt status register */ + +#define MMU_AS0 0x400 /* Configuration registers for address space 0 */ +#define MMU_AS1 0x440 /* Configuration registers for address space 1 */ +#define MMU_AS2 0x480 /* Configuration registers for address space 2 */ +#define MMU_AS3 0x4C0 /* Configuration registers for address space 3 */ +#define MMU_AS4 0x500 /* Configuration registers for address space 4 */ +#define MMU_AS5 0x540 /* Configuration registers for address space 5 */ +#define MMU_AS6 0x580 /* Configuration registers for address space 6 */ +#define MMU_AS7 0x5C0 /* Configuration registers for address space 7 */ +#define MMU_AS8 0x600 /* Configuration registers for address space 8 */ +#define MMU_AS9 0x640 /* Configuration registers for address space 9 */ +#define MMU_AS10 0x680 /* Configuration registers for address space 10 */ +#define MMU_AS11 0x6C0 /* Configuration registers for address space 11 */ +#define MMU_AS12 0x700 /* Configuration registers for address space 12 */ +#define MMU_AS13 0x740 /* Configuration registers for address space 13 */ +#define MMU_AS14 0x780 /* Configuration registers for address space 14 */ +#define MMU_AS15 0x7C0 /* Configuration registers for address space 15 */ + +#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r)) + +#define AS_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */ +#define AS_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */ +#define AS_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */ +#define AS_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */ +#define AS_LOCKADDR_LO 0x10 /* (RW) Lock region address for address space n, low word */ +#define AS_LOCKADDR_HI 0x14 /* (RW) Lock region address for address space n, high word */ +#define AS_COMMAND 0x18 /* (WO) MMU command register for address space n */ +#define AS_FAULTSTATUS 0x1C /* (RO) MMU fault status register for address space n */ +#define AS_FAULTADDRESS_LO 0x20 /* (RO) Fault Address for address space n, low word */ +#define AS_FAULTADDRESS_HI 0x24 /* (RO) Fault Address for address space n, high word */ +#define AS_STATUS 0x28 /* (RO) Status flags for address space n */ + +/* End Register Offsets */ + +/* + * MMU_IRQ_RAWSTAT register values. Values are valid also for + MMU_IRQ_CLEAR, MMU_IRQ_MASK, MMU_IRQ_STATUS registers. + */ + +#define MMU_PAGE_FAULT_FLAGS 16 + +/* Macros returning a bitmask to retrieve page fault or bus error flags from + * MMU registers */ +#define MMU_PAGE_FAULT(n) (1UL << (n)) +#define MMU_BUS_ERROR(n) (1UL << ((n) + MMU_PAGE_FAULT_FLAGS)) + +/* + * Begin MMU TRANSTAB register values + */ +#define AS_TRANSTAB_ADDR_SPACE_MASK 0xfffff000 +#define AS_TRANSTAB_ADRMODE_UNMAPPED (0u << 0) +#define AS_TRANSTAB_ADRMODE_IDENTITY (1u << 1) +#define AS_TRANSTAB_ADRMODE_TABLE (3u << 0) +#define AS_TRANSTAB_READ_INNER (1u << 2) +#define AS_TRANSTAB_SHARE_OUTER (1u << 4) + +#define MMU_TRANSTAB_ADRMODE_MASK 0x00000003 + +/* + * Begin MMU STATUS register values + */ +#define AS_STATUS_AS_ACTIVE 0x01 + +#define AS_FAULTSTATUS_ACCESS_TYPE_MASK (0x3<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_EX (0x1<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_READ (0x2<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3<<8) + +/* + * Begin Command Values + */ + +/* JS_COMMAND register commands */ +#define JS_COMMAND_NOP 0x00 /* NOP Operation. Writing this value is ignored */ +#define JS_COMMAND_START 0x01 /* Start processing a job chain. Writing this value is ignored */ +#define JS_COMMAND_SOFT_STOP 0x02 /* Gently stop processing a job chain */ +#define JS_COMMAND_HARD_STOP 0x03 /* Rudely stop processing a job chain */ +#define JS_COMMAND_SOFT_STOP_0 0x04 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 0 */ +#define JS_COMMAND_HARD_STOP_0 0x05 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 0 */ +#define JS_COMMAND_SOFT_STOP_1 0x06 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 1 */ +#define JS_COMMAND_HARD_STOP_1 0x07 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 1 */ + +#define JS_COMMAND_MASK 0x07 /* Mask of bits currently in use by the HW */ + +/* AS_COMMAND register commands */ +#define AS_COMMAND_NOP 0x00 /* NOP Operation */ +#define AS_COMMAND_UPDATE 0x01 /* Broadcasts the values in AS_TRANSTAB and ASn_MEMATTR to all MMUs */ +#define AS_COMMAND_LOCK 0x02 /* Issue a lock region command to all MMUs */ +#define AS_COMMAND_UNLOCK 0x03 /* Issue a flush region command to all MMUs */ +#define AS_COMMAND_FLUSH 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs + (deprecated - only for use with T60x) */ +#define AS_COMMAND_FLUSH_PT 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs */ +#define AS_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then + flush all L2 caches then issue a flush region command to all MMUs */ + +/* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */ +#define JS_CONFIG_START_FLUSH_NO_ACTION (0u << 0) +#define JS_CONFIG_START_FLUSH_CLEAN (1u << 8) +#define JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE (3u << 8) +#define JS_CONFIG_START_MMU (1u << 10) +#define JS_CONFIG_JOB_CHAIN_FLAG (1u << 11) +#define JS_CONFIG_END_FLUSH_NO_ACTION JS_CONFIG_START_FLUSH_NO_ACTION +#define JS_CONFIG_END_FLUSH_CLEAN (1u << 12) +#define JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE (3u << 12) +#define JS_CONFIG_THREAD_PRI(n) ((n) << 16) + +/* JS_STATUS register values */ + +/* NOTE: Please keep this values in sync with enum base_jd_event_code in mali_base_kernel.h. + * The values are separated to avoid dependency of userspace and kernel code. + */ + +/* Group of values representing the job status insead a particular fault */ +#define JS_STATUS_NO_EXCEPTION_BASE 0x00 +#define JS_STATUS_INTERRUPTED (JS_STATUS_NO_EXCEPTION_BASE + 0x02) /* 0x02 means INTERRUPTED */ +#define JS_STATUS_STOPPED (JS_STATUS_NO_EXCEPTION_BASE + 0x03) /* 0x03 means STOPPED */ +#define JS_STATUS_TERMINATED (JS_STATUS_NO_EXCEPTION_BASE + 0x04) /* 0x04 means TERMINATED */ + +/* General fault values */ +#define JS_STATUS_FAULT_BASE 0x40 +#define JS_STATUS_CONFIG_FAULT (JS_STATUS_FAULT_BASE) /* 0x40 means CONFIG FAULT */ +#define JS_STATUS_POWER_FAULT (JS_STATUS_FAULT_BASE + 0x01) /* 0x41 means POWER FAULT */ +#define JS_STATUS_READ_FAULT (JS_STATUS_FAULT_BASE + 0x02) /* 0x42 means READ FAULT */ +#define JS_STATUS_WRITE_FAULT (JS_STATUS_FAULT_BASE + 0x03) /* 0x43 means WRITE FAULT */ +#define JS_STATUS_AFFINITY_FAULT (JS_STATUS_FAULT_BASE + 0x04) /* 0x44 means AFFINITY FAULT */ +#define JS_STATUS_BUS_FAULT (JS_STATUS_FAULT_BASE + 0x08) /* 0x48 means BUS FAULT */ + +/* Instruction or data faults */ +#define JS_STATUS_INSTRUCTION_FAULT_BASE 0x50 +#define JS_STATUS_INSTR_INVALID_PC (JS_STATUS_INSTRUCTION_FAULT_BASE) /* 0x50 means INSTR INVALID PC */ +#define JS_STATUS_INSTR_INVALID_ENC (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x01) /* 0x51 means INSTR INVALID ENC */ +#define JS_STATUS_INSTR_TYPE_MISMATCH (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x02) /* 0x52 means INSTR TYPE MISMATCH */ +#define JS_STATUS_INSTR_OPERAND_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x03) /* 0x53 means INSTR OPERAND FAULT */ +#define JS_STATUS_INSTR_TLS_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x04) /* 0x54 means INSTR TLS FAULT */ +#define JS_STATUS_INSTR_BARRIER_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x05) /* 0x55 means INSTR BARRIER FAULT */ +#define JS_STATUS_INSTR_ALIGN_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x06) /* 0x56 means INSTR ALIGN FAULT */ +/* NOTE: No fault with 0x57 code defined in spec. */ +#define JS_STATUS_DATA_INVALID_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x08) /* 0x58 means DATA INVALID FAULT */ +#define JS_STATUS_TILE_RANGE_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x09) /* 0x59 means TILE RANGE FAULT */ +#define JS_STATUS_ADDRESS_RANGE_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x0A) /* 0x5A means ADDRESS RANGE FAULT */ + +/* Other faults */ +#define JS_STATUS_MEMORY_FAULT_BASE 0x60 +#define JS_STATUS_OUT_OF_MEMORY (JS_STATUS_MEMORY_FAULT_BASE) /* 0x60 means OUT OF MEMORY */ +#define JS_STATUS_UNKNOWN 0x7F /* 0x7F means UNKNOWN */ + +/* GPU_COMMAND values */ +#define GPU_COMMAND_NOP 0x00 /* No operation, nothing happens */ +#define GPU_COMMAND_SOFT_RESET 0x01 /* Stop all external bus interfaces, and then reset the entire GPU. */ +#define GPU_COMMAND_HARD_RESET 0x02 /* Immediately reset the entire GPU. */ +#define GPU_COMMAND_PRFCNT_CLEAR 0x03 /* Clear all performance counters, setting them all to zero. */ +#define GPU_COMMAND_PRFCNT_SAMPLE 0x04 /* Sample all performance counters, writing them out to memory */ +#define GPU_COMMAND_CYCLE_COUNT_START 0x05 /* Starts the cycle counter, and system timestamp propagation */ +#define GPU_COMMAND_CYCLE_COUNT_STOP 0x06 /* Stops the cycle counter, and system timestamp propagation */ +#define GPU_COMMAND_CLEAN_CACHES 0x07 /* Clean all caches */ +#define GPU_COMMAND_CLEAN_INV_CACHES 0x08 /* Clean and invalidate all caches */ + +/* End Command Values */ + +/* GPU_STATUS values */ +#define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */ + +/* PRFCNT_CONFIG register values */ +#define PRFCNT_CONFIG_AS_SHIFT 4 /* address space bitmap starts from bit 4 of the register */ +#define PRFCNT_CONFIG_MODE_OFF 0 /* The performance counters are disabled. */ +#define PRFCNT_CONFIG_MODE_MANUAL 1 /* The performance counters are enabled, but are only written out when a PRFCNT_SAMPLE command is issued using the GPU_COMMAND register. */ +#define PRFCNT_CONFIG_MODE_TILE 2 /* The performance counters are enabled, and are written out each time a tile finishes rendering. */ + +/* AS_MEMATTR values: */ +/* Use GPU implementation-defined caching policy. */ +#define AS_MEMATTR_IMPL_DEF_CACHE_POLICY 0x48 +/* The attribute set to force all resources to be cached. */ +#define AS_MEMATTR_FORCE_TO_CACHE_ALL 0x4F +/* Inner write-alloc cache setup, no outer caching */ +#define AS_MEMATTR_WRITE_ALLOC 0x4D +/* symbol for default MEMATTR to use */ +#define AS_MEMATTR_INDEX_DEFAULT 0 +/* HW implementation defined caching */ +#define AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY 0 +/* Force cache on */ +#define AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL 1 +/* Write-alloc inner */ +#define AS_MEMATTR_INDEX_WRITE_ALLOC 2 + +/* GPU_ID register */ +#define GPU_ID_VERSION_STATUS_SHIFT 0 +#define GPU_ID_VERSION_MINOR_SHIFT 4 +#define GPU_ID_VERSION_MAJOR_SHIFT 12 +#define GPU_ID_VERSION_PRODUCT_ID_SHIFT 16 +#define GPU_ID_VERSION_STATUS (0xF << GPU_ID_VERSION_STATUS_SHIFT) +#define GPU_ID_VERSION_MINOR (0xFF << GPU_ID_VERSION_MINOR_SHIFT) +#define GPU_ID_VERSION_MAJOR (0xF << GPU_ID_VERSION_MAJOR_SHIFT) +#define GPU_ID_VERSION_PRODUCT_ID (0xFFFF << GPU_ID_VERSION_PRODUCT_ID_SHIFT) + +/* Values for GPU_ID_VERSION_PRODUCT_ID bitfield */ +#define GPU_ID_PI_T60X 0x6956 +#define GPU_ID_PI_T62X 0x0620 +#define GPU_ID_PI_T76X 0x0750 +#define GPU_ID_PI_T72X 0x0720 +#ifdef MALI_INCLUDE_TFRX +#define GPU_ID_PI_TFRX 0x0880 +#endif /* MALI_INCLUDE_TFRX */ +#define GPU_ID_PI_T86X 0x0860 + +/* Values for GPU_ID_VERSION_STATUS field for PRODUCT_ID GPU_ID_PI_T60X */ +#define GPU_ID_S_15DEV0 0x1 +#define GPU_ID_S_EAC 0x2 + +/* Helper macro to create a GPU_ID assuming valid values for id, major, minor, status */ +#define GPU_ID_MAKE(id, major, minor, status) \ + (((id) << GPU_ID_VERSION_PRODUCT_ID_SHIFT) | \ + ((major) << GPU_ID_VERSION_MAJOR_SHIFT) | \ + ((minor) << GPU_ID_VERSION_MINOR_SHIFT) | \ + ((status) << GPU_ID_VERSION_STATUS_SHIFT)) + +/* End GPU_ID register */ + +/* JS_FEATURES register */ + +#define JS_FEATURE_NULL_JOB (1u << 1) +#define JS_FEATURE_SET_VALUE_JOB (1u << 2) +#define JS_FEATURE_CACHE_FLUSH_JOB (1u << 3) +#define JS_FEATURE_COMPUTE_JOB (1u << 4) +#define JS_FEATURE_VERTEX_JOB (1u << 5) +#define JS_FEATURE_GEOMETRY_JOB (1u << 6) +#define JS_FEATURE_TILER_JOB (1u << 7) +#define JS_FEATURE_FUSED_JOB (1u << 8) +#define JS_FEATURE_FRAGMENT_JOB (1u << 9) + +/* End JS_FEATURES register */ + +/* L2_MMU_CONFIG register */ +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT (24) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) + +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT (26) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +/* End L2_MMU_CONFIG register */ + +/* THREAD_* registers */ + +/* THREAD_FEATURES IMPLEMENTATION_TECHNOLOGY values */ +#define IMPLEMENTATION_UNSPECIFIED 0 +#define IMPLEMENTATION_SILICON 1 +#define IMPLEMENTATION_FPGA 2 +#define IMPLEMENTATION_MODEL 3 + +/* Default values when registers are not supported by the implemented hardware */ +#define THREAD_MT_DEFAULT 256 +#define THREAD_MWS_DEFAULT 256 +#define THREAD_MBS_DEFAULT 256 +#define THREAD_MR_DEFAULT 1024 +#define THREAD_MTQ_DEFAULT 4 +#define THREAD_MTGS_DEFAULT 10 + +/* End THREAD_* registers */ + +/* SHADER_CONFIG register */ + +#define SC_ALT_COUNTERS (1ul << 3) +#define SC_OVERRIDE_FWD_PIXEL_KILL (1ul << 4) +#define SC_SDC_DISABLE_OQ_DISCARD (1ul << 6) +#define SC_LS_PAUSEBUFFER_DISABLE (1ul << 16) +#define SC_ENABLE_TEXGRD_FLAGS (1ul << 25) +/* End SHADER_CONFIG register */ + +/* TILER_CONFIG register */ + +#define TC_CLOCK_GATE_OVERRIDE (1ul << 0) + +/* End TILER_CONFIG register */ + + +#endif /* _MIDGARD_REGMAP_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_timeline.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_timeline.h new file mode 100644 index 0000000000000000000000000000000000000000..83a29cd304fb96667ebb86b0651fe64477f31ae6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_timeline.h @@ -0,0 +1,396 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali_timeline + +#if !defined(_MALI_TIMELINE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _MALI_TIMELINE_H + +#include + +TRACE_EVENT(mali_timeline_atoms_in_flight, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int tgid, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + tgid, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, tgid) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->tgid = tgid; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i", CTX_SET_NR_ATOMS_IN_FLIGHT, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->count) +); + + +TRACE_EVENT(mali_timeline_atom, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int atom_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + atom_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, atom_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->atom_id = atom_id; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->atom_id, + __entry->atom_id) +); + +TRACE_EVENT(mali_timeline_gpu_slot_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->count) +); + +TRACE_EVENT(mali_timeline_gpu_slot_action, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->count) +); + +TRACE_EVENT(mali_timeline_gpu_power_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int active), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + active), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, active) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->active = active; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->active) + +); + +TRACE_EVENT(mali_timeline_l2_power_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int state), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + state), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, state) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->state = state; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->state) + +); +TRACE_EVENT(mali_timeline_pm_event, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int pm_event_type, + unsigned int pm_event_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + pm_event_type, + pm_event_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, pm_event_type) + __field(unsigned int, pm_event_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->pm_event_type = pm_event_type; + __entry->pm_event_id = pm_event_id; + ), + + TP_printk("%i,%i.%.9i,0,%i,%u", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->pm_event_type, __entry->pm_event_id) + +); + +TRACE_EVENT(mali_timeline_slot_atom, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int atom_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + atom_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, atom_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->atom_id = atom_id; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->atom_id) +); + +TRACE_EVENT(mali_timeline_pm_checktrans, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int trans_code, + int trans_id), + + TP_ARGS(ts_sec, + ts_nsec, + trans_code, + trans_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, trans_code) + __field(int, trans_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->trans_code = trans_code; + __entry->trans_id = trans_id; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->trans_code, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->trans_id) + +); + +TRACE_EVENT(mali_timeline_context_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,0,%i", SW_SET_CONTEXT_ACTIVE, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->count) +); + +#endif /* _MALI_TIMELINE_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +/* This part must be outside protection */ +#include + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_uk.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_uk.h new file mode 100644 index 0000000000000000000000000000000000000000..5d9e0dd218ecb8966b4dfba94a098bba07993def --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/mali_uk.h @@ -0,0 +1,143 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_uk.h + * Types and definitions that are common across OSs for both the user + * and kernel side of the User-Kernel interface. + */ + +#ifndef _UK_H_ +#define _UK_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @defgroup uk_api User-Kernel Interface API + * + * The User-Kernel Interface abstracts the communication mechanism between the user and kernel-side code of device + * drivers developed as part of the Midgard DDK. Currently that includes the Base driver and the UMP driver. + * + * It exposes an OS independent API to user-side code (UKU) which routes functions calls to an OS-independent + * kernel-side API (UKK) via an OS-specific communication mechanism. + * + * This API is internal to the Midgard DDK and is not exposed to any applications. + * + * @{ + */ + +/** + * These are identifiers for kernel-side drivers implementing a UK interface, aka UKK clients. The + * UK module maps this to an OS specific device name, e.g. "gpu_base" -> "GPU0:". Specify this + * identifier to select a UKK client to the uku_open() function. + * + * When a new UKK client driver is created a new identifier needs to be added to the uk_client_id + * enumeration and the uku_open() implemenation for the various OS ports need to be updated to + * provide a mapping of the identifier to the OS specific device name. + * + */ +enum uk_client_id { + /** + * Value used to identify the Base driver UK client. + */ + UK_CLIENT_MALI_T600_BASE, + + /** The number of uk clients supported. This must be the last member of the enum */ + UK_CLIENT_COUNT +}; + +/** + * Each function callable through the UK interface has a unique number. + * Functions provided by UK clients start from number UK_FUNC_ID. + * Numbers below UK_FUNC_ID are used for internal UK functions. + */ +enum uk_func { + UKP_FUNC_ID_CHECK_VERSION, /**< UKK Core internal function */ + /** + * Each UK client numbers the functions they provide starting from + * number UK_FUNC_ID. This number is then eventually assigned to the + * id field of the union uk_header structure when preparing to make a + * UK call. See your UK client for a list of their function numbers. + */ + UK_FUNC_ID = 512 +}; + +/** + * Arguments for a UK call are stored in a structure. This structure consists + * of a fixed size header and a payload. The header carries a 32-bit number + * identifying the UK function to be called (see uk_func). When the UKK client + * receives this header and executed the requested UK function, it will use + * the same header to store the result of the function in the form of a + * mali_error return code. The size of this structure is such that the + * first member of the payload following the header can be accessed efficiently + * on a 32 and 64-bit kernel and the structure has the same size regardless + * of a 32 or 64-bit kernel. The uk_kernel_size_type type should be defined + * accordingly in the OS specific mali_uk_os.h header file. + */ +union uk_header { + /** + * 32-bit number identifying the UK function to be called. + * Also see uk_func. + */ + u32 id; + /** + * The mali_error return code returned by the called UK function. + * See the specification of the particular UK function you are + * calling for the meaning of the error codes returned. All + * UK functions return MALI_ERROR_NONE on success. + */ + u32 ret; + /* + * Used to ensure 64-bit alignment of this union. Do not remove. + * This field is used for padding and does not need to be initialized. + */ + u64 sizer; +}; + +/** + * This structure carries a 16-bit major and minor number and is sent along with an internal UK call + * used during uku_open to identify the versions of the UK module in use by the user-side and kernel-side. + */ +struct uku_version_check_args { + union uk_header header; + /**< UK call header */ + u16 major; + /**< This field carries the user-side major version on input and the kernel-side major version on output */ + u16 minor; + /**< This field carries the user-side minor version on input and the kernel-side minor version on output. */ + u8 padding[4]; +}; + +/** @} end group uk_api */ + +/** @} *//* end group base_api */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _UK_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd.h new file mode 100644 index 0000000000000000000000000000000000000000..9226d977f7a5fd7ca27959d1b43238da665e12d9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd.h @@ -0,0 +1,481 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @addtogroup malisw + * @{ + */ + +/* ============================================================================ + Description +============================================================================ */ +/** + * @defgroup arm_cstd_coding_standard ARM C standard types and constants + * The common files are a set of standard headers which are used by all parts + * of this development, describing types, and generic constants. + * + * Files in group: + * - arm_cstd.h + * - arm_cstd_compilers.h + * - arm_cstd_types.h + * - arm_cstd_types_rvct.h + * - arm_cstd_types_gcc.h + * - arm_cstd_types_msvc.h + * - arm_cstd_pack_push.h + * - arm_cstd_pack_pop.h + */ + +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +#ifndef _ARM_CSTD_ +#define _ARM_CSTD_ + +/* ============================================================================ + Import standard C99 types +============================================================================ */ +#include "arm_cstd_compilers.h" +#include "arm_cstd_types.h" + +/* ============================================================================ + Min and Max Values +============================================================================ */ +#if !defined(INT8_MAX) + #define INT8_MAX ((int8_t) 0x7F) +#endif +#if !defined(INT8_MIN) + #define INT8_MIN (-INT8_MAX - 1) +#endif + +#if !defined(INT16_MAX) + #define INT16_MAX ((int16_t)0x7FFF) +#endif +#if !defined(INT16_MIN) + #define INT16_MIN (-INT16_MAX - 1) +#endif + +#if !defined(INT32_MAX) + #define INT32_MAX ((int32_t)0x7FFFFFFF) +#endif +#if !defined(INT32_MIN) + #define INT32_MIN (-INT32_MAX - 1) +#endif + +#if !defined(INT64_MAX) + #define INT64_MAX ((int64_t)0x7FFFFFFFFFFFFFFFLL) +#endif +#if !defined(INT64_MIN) + #define INT64_MIN (-INT64_MAX - 1) +#endif + +#if !defined(UINT8_MAX) + #define UINT8_MAX ((uint8_t) 0xFF) +#endif + +#if !defined(UINT16_MAX) + #define UINT16_MAX ((uint16_t)0xFFFF) +#endif + +#if !defined(UINT32_MAX) + #define UINT32_MAX ((uint32_t)0xFFFFFFFF) +#endif + +#if !defined(UINT64_MAX) + #define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFFULL) +#endif + +/* fallbacks if limits.h wasn't available */ +#if !defined(UCHAR_MAX) + #define UCHAR_MAX ((unsigned char)~0U) +#endif + +#if !defined(SCHAR_MAX) + #define SCHAR_MAX ((signed char)(UCHAR_MAX >> 1)) +#endif +#if !defined(SCHAR_MIN) + #define SCHAR_MIN ((signed char)(-SCHAR_MAX - 1)) +#endif + +#if !defined(USHRT_MAX) + #define USHRT_MAX ((unsigned short)~0U) +#endif + +#if !defined(SHRT_MAX) + #define SHRT_MAX ((signed short)(USHRT_MAX >> 1)) +#endif +#if !defined(SHRT_MIN) + #define SHRT_MIN ((signed short)(-SHRT_MAX - 1)) +#endif + +#if !defined(UINT_MAX) + #define UINT_MAX ((unsigned int)~0U) +#endif + +#if !defined(INT_MAX) + #define INT_MAX ((signed int)(UINT_MAX >> 1)) +#endif +#if !defined(INT_MIN) + #define INT_MIN ((signed int)(-INT_MAX - 1)) +#endif + +#if !defined(ULONG_MAX) + #define ULONG_MAX ((unsigned long)~0UL) +#endif + +#if !defined(LONG_MAX) + #define LONG_MAX ((signed long)(ULONG_MAX >> 1)) +#endif +#if !defined(LONG_MIN) + #define LONG_MIN ((signed long)(-LONG_MAX - 1)) +#endif + +#if !defined(ULLONG_MAX) + #define ULLONG_MAX ((unsigned long long)~0ULL) +#endif + +#if !defined(LLONG_MAX) + #define LLONG_MAX ((signed long long)(ULLONG_MAX >> 1)) +#endif +#if !defined(LLONG_MIN) + #define LLONG_MIN ((signed long long)(-LLONG_MAX - 1)) +#endif + +#if !defined(SIZE_MAX) + #if 1 == CSTD_CPU_32BIT + #define SIZE_MAX UINT32_MAX + #elif 1 == CSTD_CPU_64BIT + #define SIZE_MAX UINT64_MAX + #endif +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/* Portable keywords. */ + +#if !defined(CONST) +/** + * @hideinitializer + * Variable is a C @c const, which can be made non-const for testing purposes. + */ + #define CONST const +#endif + +#if !defined(STATIC) +/** + * @hideinitializer + * Variable is a C @c static, which can be made non-static for testing + * purposes. + */ + #define STATIC static +#endif + +/** + * Specifies a function as being exported outside of a logical module. + */ +#define PUBLIC + +/** + * @def PROTECTED + * Specifies a a function which is internal to an logical module, but which + * should not be used outside of that module. This cannot be enforced by the + * compiler, as a module is typically more than one translation unit. + */ +#define PROTECTED + +/** + * Specifies a function as being internal to a translation unit. Private + * functions would typically be declared as STATIC, unless they are being + * exported for unit test purposes. + */ +#define PRIVATE STATIC + +/** + * Specify an assertion value which is evaluated at compile time. Recommended + * usage is specification of a @c static @c INLINE function containing all of + * the assertions thus: + * + * @code + * static INLINE [module]_compile_time_assertions( void ) + * { + * COMPILE_TIME_ASSERT( sizeof(uintptr_t) == sizeof(intptr_t) ); + * } + * @endcode + * + * @note Use @c static not @c STATIC. We never want to turn off this @c static + * specification for testing purposes. + */ +#define CSTD_COMPILE_TIME_ASSERT( expr ) \ + do { switch(0){case 0: case (expr):;} } while( FALSE ) + +/** + * @hideinitializer + * @deprecated Prefered form is @c CSTD_UNUSED + * Function-like macro for suppressing unused variable warnings. Where possible + * such variables should be removed; this macro is present for cases where we + * much support API backwards compatibility. + */ +#define UNUSED( x ) ((void)(x)) + +/** + * @hideinitializer + * Function-like macro for suppressing unused variable warnings. Where possible + * such variables should be removed; this macro is present for cases where we + * much support API backwards compatibility. + */ +#define CSTD_UNUSED( x ) ((void)(x)) + +/** + * @hideinitializer + * Function-like macro for use where "no behavior" is desired. This is useful + * when compile time macros turn a function-like macro in to a no-op, but + * where having no statement is otherwise invalid. + */ +#define CSTD_NOP( ... ) ((void)#__VA_ARGS__) + +/** + * @hideinitializer + * Function-like macro for converting a pointer in to a u64 for storing into + * an external data structure. This is commonly used when pairing a 32-bit + * CPU with a 64-bit peripheral, such as a Midgard GPU. C's type promotion + * is complex and a straight cast does not work reliably as pointers are + * often considered as signed. + */ +#define CSTD_PTR_TO_U64( x ) ((uint64_t)((uintptr_t)(x))) + +/** + * @hideinitializer + * Function-like macro for stringizing a single level macro. + * @code + * #define MY_MACRO 32 + * CSTD_STR1( MY_MACRO ) + * > "MY_MACRO" + * @endcode + */ +#define CSTD_STR1( x ) #x + +/** + * @hideinitializer + * Function-like macro for stringizing a macro's value. This should not be used + * if the macro is defined in a way which may have no value; use the + * alternative @c CSTD_STR2N macro should be used instead. + * @code + * #define MY_MACRO 32 + * CSTD_STR2( MY_MACRO ) + * > "32" + * @endcode + */ +#define CSTD_STR2( x ) CSTD_STR1( x ) + +/** + * @hideinitializer + * Utility function for stripping the first character off a string. + */ +static INLINE char* arm_cstd_strstrip( char * string ) +{ + return ++string; +} + +/** + * @hideinitializer + * Function-like macro for stringizing a single level macro where the macro + * itself may not have a value. Parameter @c a should be set to any single + * character which is then stripped by the macro via an inline function. This + * should only be used via the @c CSTD_STR2N macro; for printing a single + * macro only the @c CSTD_STR1 macro is a better alternative. + * + * This macro requires run-time code to handle the case where the macro has + * no value (you can't concat empty strings in the preprocessor). + */ +#define CSTD_STR1N( a, x ) arm_cstd_strstrip( CSTD_STR1( a##x ) ) + +/** + * @hideinitializer + * Function-like macro for stringizing a two level macro where the macro itself + * may not have a value. + * @code + * #define MY_MACRO 32 + * CSTD_STR2N( MY_MACRO ) + * > "32" + * + * #define MY_MACRO 32 + * CSTD_STR2N( MY_MACRO ) + * > "32" + * @endcode + */ +#define CSTD_STR2N( x ) CSTD_STR1N( _, x ) + +/* ============================================================================ + Validate portability constructs +============================================================================ */ +static INLINE void arm_cstd_compile_time_assertions( void ) +{ + CSTD_COMPILE_TIME_ASSERT( sizeof(uint8_t) == 1 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int8_t) == 1 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint16_t) == 2 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int16_t) == 2 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint32_t) == 4 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int32_t) == 4 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint64_t) == 8 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int64_t) == 8 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(intptr_t) == sizeof(uintptr_t) ); + + CSTD_COMPILE_TIME_ASSERT( 1 == TRUE ); + CSTD_COMPILE_TIME_ASSERT( 0 == FALSE ); + +#if 1 == CSTD_CPU_32BIT + CSTD_COMPILE_TIME_ASSERT( sizeof(uintptr_t) == 4 ); +#elif 1 == CSTD_CPU_64BIT + CSTD_COMPILE_TIME_ASSERT( sizeof(uintptr_t) == 8 ); +#endif + +} + +/* ============================================================================ + Useful function-like macro +============================================================================ */ +/** + * @brief Return the lesser of two values. + * As a macro it may evaluate its arguments more than once. + * @see CSTD_MAX + */ +#define CSTD_MIN( x, y ) ((x) < (y) ? (x) : (y)) + +/** + * @brief Return the greater of two values. + * As a macro it may evaluate its arguments more than once. + * If called on the same two arguments as CSTD_MIN it is guaranteed to return + * the one that CSTD_MIN didn't return. This is significant for types where not + * all values are comparable e.g. NaNs in floating-point types. But if you want + * to retrieve the min and max of two values, consider using a conditional swap + * instead. + */ +#define CSTD_MAX( x, y ) ((x) < (y) ? (y) : (x)) + +/** + * @brief Clamp value @c x to within @c min and @c max inclusive. + */ +#define CSTD_CLAMP( x, min, max ) ((x)<(min) ? (min):((x)>(max) ? (max):(x))) + +/** + * Flag a cast as a reinterpretation, usually of a pointer type. + */ +#define CSTD_REINTERPRET_CAST(type) (type) + +/** + * Flag a cast as casting away const, usually of a pointer type. + */ +#define CSTD_CONST_CAST(type) (type) + +/** + * Flag a cast as a (potentially complex) value conversion, usually of a + * numerical type. + */ +#define CSTD_STATIC_CAST(type) (type) + +/* ============================================================================ + Useful bit constants +============================================================================ */ +/** + * @cond arm_cstd_utilities + */ + +/* Common bit constant values, useful in embedded programming. */ +#define F_BIT_0 ((uint32_t)0x00000001) +#define F_BIT_1 ((uint32_t)0x00000002) +#define F_BIT_2 ((uint32_t)0x00000004) +#define F_BIT_3 ((uint32_t)0x00000008) +#define F_BIT_4 ((uint32_t)0x00000010) +#define F_BIT_5 ((uint32_t)0x00000020) +#define F_BIT_6 ((uint32_t)0x00000040) +#define F_BIT_7 ((uint32_t)0x00000080) +#define F_BIT_8 ((uint32_t)0x00000100) +#define F_BIT_9 ((uint32_t)0x00000200) +#define F_BIT_10 ((uint32_t)0x00000400) +#define F_BIT_11 ((uint32_t)0x00000800) +#define F_BIT_12 ((uint32_t)0x00001000) +#define F_BIT_13 ((uint32_t)0x00002000) +#define F_BIT_14 ((uint32_t)0x00004000) +#define F_BIT_15 ((uint32_t)0x00008000) +#define F_BIT_16 ((uint32_t)0x00010000) +#define F_BIT_17 ((uint32_t)0x00020000) +#define F_BIT_18 ((uint32_t)0x00040000) +#define F_BIT_19 ((uint32_t)0x00080000) +#define F_BIT_20 ((uint32_t)0x00100000) +#define F_BIT_21 ((uint32_t)0x00200000) +#define F_BIT_22 ((uint32_t)0x00400000) +#define F_BIT_23 ((uint32_t)0x00800000) +#define F_BIT_24 ((uint32_t)0x01000000) +#define F_BIT_25 ((uint32_t)0x02000000) +#define F_BIT_26 ((uint32_t)0x04000000) +#define F_BIT_27 ((uint32_t)0x08000000) +#define F_BIT_28 ((uint32_t)0x10000000) +#define F_BIT_29 ((uint32_t)0x20000000) +#define F_BIT_30 ((uint32_t)0x40000000) +#define F_BIT_31 ((uint32_t)0x80000000) + +/* Common 2^n size values, useful in embedded programming. */ +#define C_SIZE_1B ((uint32_t)0x00000001) +#define C_SIZE_2B ((uint32_t)0x00000002) +#define C_SIZE_4B ((uint32_t)0x00000004) +#define C_SIZE_8B ((uint32_t)0x00000008) +#define C_SIZE_16B ((uint32_t)0x00000010) +#define C_SIZE_32B ((uint32_t)0x00000020) +#define C_SIZE_64B ((uint32_t)0x00000040) +#define C_SIZE_128B ((uint32_t)0x00000080) +#define C_SIZE_256B ((uint32_t)0x00000100) +#define C_SIZE_512B ((uint32_t)0x00000200) +#define C_SIZE_1KB ((uint32_t)0x00000400) +#define C_SIZE_2KB ((uint32_t)0x00000800) +#define C_SIZE_4KB ((uint32_t)0x00001000) +#define C_SIZE_8KB ((uint32_t)0x00002000) +#define C_SIZE_16KB ((uint32_t)0x00004000) +#define C_SIZE_32KB ((uint32_t)0x00008000) +#define C_SIZE_64KB ((uint32_t)0x00010000) +#define C_SIZE_128KB ((uint32_t)0x00020000) +#define C_SIZE_256KB ((uint32_t)0x00040000) +#define C_SIZE_512KB ((uint32_t)0x00080000) +#define C_SIZE_1MB ((uint32_t)0x00100000) +#define C_SIZE_2MB ((uint32_t)0x00200000) +#define C_SIZE_4MB ((uint32_t)0x00400000) +#define C_SIZE_8MB ((uint32_t)0x00800000) +#define C_SIZE_16MB ((uint32_t)0x01000000) +#define C_SIZE_32MB ((uint32_t)0x02000000) +#define C_SIZE_64MB ((uint32_t)0x04000000) +#define C_SIZE_128MB ((uint32_t)0x08000000) +#define C_SIZE_256MB ((uint32_t)0x10000000) +#define C_SIZE_512MB ((uint32_t)0x20000000) +#define C_SIZE_1GB ((uint32_t)0x40000000) +#define C_SIZE_2GB ((uint32_t)0x80000000) + +/** + * @endcond + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_compilers.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_compilers.h new file mode 100644 index 0000000000000000000000000000000000000000..55637cf8afc030d5600e0535040cc462cfb328fc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_compilers.h @@ -0,0 +1,617 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_COMPILERS_H_ +#define _ARM_CSTD_COMPILERS_H_ + +/* ============================================================================ + Document default definitions - assuming nothing set at this point. +============================================================================ */ +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is Microsoft Visual Studio, 0 + * otherwise. + */ +#define CSTD_TOOLCHAIN_MSVC 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is the GNU Compiler Collection, 0 + * otherwise. + */ +#define CSTD_TOOLCHAIN_GCC 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is ARM RealView Compiler Tools, 0 + * otherwise. Note - if running RVCT in GCC mode this define will be set to 0; + * @c CSTD_TOOLCHAIN_GCC and @c CSTD_TOOLCHAIN_RVCT_GCC_MODE will both be + * defined as 1. + */ +#define CSTD_TOOLCHAIN_RVCT 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is ARM RealView Compiler Tools running + * in GCC mode, 0 otherwise. + */ +#define CSTD_TOOLCHAIN_RVCT_GCC_MODE 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an x86 32-bit machine, 0 otherwise. + */ +#define CSTD_CPU_X86_32 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an x86-64 (AMD64) machine, 0 + * otherwise. + */ +#define CSTD_CPU_X86_64 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an ARM machine, 0 otherwise. + */ +#define CSTD_CPU_ARM 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an AARCH64 machine, 0 otherwise. + */ +#define CSTD_CPU_AARCH64 0 + + +/** + * @hideinitializer + * Defined with value of 1 if processor is a MIPS machine, 0 otherwise. + */ +#define CSTD_CPU_MIPS 0 + +/** + * @hideinitializer + * Defined with value of 1 if CPU is 32-bit, 0 otherwise. + */ +#define CSTD_CPU_32BIT 0 + +/** + * @hideinitializer + * Defined with value of 1 if CPU is 64-bit, 0 otherwise. + */ +#define CSTD_CPU_64BIT 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor configured as big-endian, 0 if it + * is little-endian. + */ +#define CSTD_CPU_BIG_ENDIAN 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a version of Windows, 0 if + * it is not. + */ +#define CSTD_OS_WINDOWS 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Windows, + * 0 if it is not. + */ +#define CSTD_OS_WIN32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Windows, + * 0 if it is not. + */ +#define CSTD_OS_WIN64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is Linux, 0 if it is not. + */ +#define CSTD_OS_LINUX 0 + +/** + * @hideinitializer + * Defined with value of 1 if we are compiling Linux kernel code, 0 otherwise. + */ +#define CSTD_OS_LINUX_KERNEL 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Linux, + * 0 if it is not. + */ +#define CSTD_OS_LINUX32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Linux, + * 0 if it is not. + */ +#define CSTD_OS_LINUX64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is Android, 0 if it is not. + */ +#define CSTD_OS_ANDROID 0 + +/** + * @hideinitializer + * Defined with value of 1 if we are compiling Android kernel code, 0 otherwise. + */ +#define CSTD_OS_ANDROID_KERNEL 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Android, + * 0 if it is not. + */ +#define CSTD_OS_ANDROID32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Android, + * 0 if it is not. + */ +#define CSTD_OS_ANDROID64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS64 0 + +/** + * @def CSTD_OS_SYMBIAN + * @hideinitializer + * Defined with value of 1 if operating system is Symbian, 0 if it is not. + */ +#define CSTD_OS_SYMBIAN 0 + +/** + * @def CSTD_OS_NONE + * @hideinitializer + * Defined with value of 1 if there is no operating system (bare metal), 0 + * otherwise + */ +#define CSTD_OS_NONE 0 + +/* ============================================================================ + Determine the compiler in use +============================================================================ */ + +/* Default empty definitions of compiler-specific option enable/disable. This will be overridden + * if applicable by preprocessor defines below. */ +#define CSTD_PUSH_WARNING_GCC_WADDRESS +#define CSTD_POP_WARNING_GCC_WADDRESS + +#if defined(_MSC_VER) + #undef CSTD_TOOLCHAIN_MSVC + #define CSTD_TOOLCHAIN_MSVC 1 + +#elif defined(__GNUC__) + #undef CSTD_TOOLCHAIN_GCC + #define CSTD_TOOLCHAIN_GCC 1 + + /* Detect RVCT pretending to be GCC. */ + #if defined(__ARMCC_VERSION) + #undef CSTD_TOOLCHAIN_RVCT_GCC_MODE + #define CSTD_TOOLCHAIN_RVCT_GCC_MODE 1 + #endif + + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && MALI_GCC_WORKAROUND_MIDCOM_4598 == 0) + /* As a workaround to MIDCOM-4598 (GCC internal defect), these pragmas are not compiled if the GCC version + * is within a certain range, or if a #define is enabled by the build system. For more, see a comment + * in the build system also referring to the MIDCOM issue mentioned, where the environment is updated + * for the GNU toolchain. */ + #undef CSTD_PUSH_WARNING_GCC_WADDRESS + #define CSTD_PUSH_WARNING_GCC_WADDRESS \ + do\ + {\ + _Pragma("GCC diagnostic push")\ + _Pragma("GCC diagnostic ignored \"-Waddress\"")\ + }while(MALI_FALSE) + + #undef CSTD_POP_WARNING_GCC_WADDRESS + #define CSTD_POP_WARNING_GCC_WADDRESS \ + do\ + {\ + _Pragma("GCC diagnostic pop")\ + }while(MALI_FALSE) + #endif + +#elif defined(__ARMCC_VERSION) + #undef CSTD_TOOLCHAIN_RVCT + #define CSTD_TOOLCHAIN_RVCT 1 + +#else + #warning "Unsupported or unknown toolchain" + +#endif + +/* ============================================================================ + Determine the processor +============================================================================ */ +#if 1 == CSTD_TOOLCHAIN_MSVC + #if defined(_M_IX86) + #undef CSTD_CPU_X86_32 + #define CSTD_CPU_X86_32 1 + + #elif defined(_M_X64) || defined(_M_AMD64) + #undef CSTD_CPU_X86_64 + #define CSTD_CPU_X86_64 1 + + #elif defined(_M_ARM) + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + + #elif defined(_M_MIPS) + #undef CSTD_CPU_MIPS + #define CSTD_CPU_MIPS 1 + + #else + #warning "Unsupported or unknown host CPU for MSVC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_GCC + #if defined(__amd64__) + #undef CSTD_CPU_X86_64 + #define CSTD_CPU_X86_64 1 + + #elif defined(__i386__) + #undef CSTD_CPU_X86_32 + #define CSTD_CPU_X86_32 1 + + #elif defined(__arm__) + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + + #elif defined(__aarch64__) + #undef CSTD_CPU_AARCH64 + #define CSTD_CPU_AARCH64 1 + + #elif defined(__mips__) + #undef CSTD_CPU_MIPS + #define CSTD_CPU_MIPS 1 + + #else + #warning "Unsupported or unknown host CPU for GCC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_RVCT + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + +#else + #warning "Unsupported or unknown toolchain" + +#endif + +/* ============================================================================ + Determine the Processor Endianness +============================================================================ */ + +#if ((1 == CSTD_CPU_X86_32) || (1 == CSTD_CPU_X86_64)) + /* Note: x86 and x86-64 are always little endian, so leave at default. */ + +#elif 1 == CSTD_CPU_AARCH64 + /* No big endian support? */ + +#elif 1 == CSTD_TOOLCHAIN_RVCT + #if defined(__BIG_ENDIAN) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif ((1 == CSTD_TOOLCHAIN_GCC) && (1 == CSTD_CPU_ARM)) + #if defined(__ARMEB__) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif ((1 == CSTD_TOOLCHAIN_GCC) && (1 == CSTD_CPU_MIPS)) + #if defined(__MIPSEB__) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif 1 == CSTD_TOOLCHAIN_MSVC + /* Note: Microsoft only support little endian, so leave at default. */ + +#else + #warning "Unsupported or unknown CPU" + +#endif + +/* ============================================================================ + Determine the operating system and addressing width +============================================================================ */ +#if 1 == CSTD_TOOLCHAIN_MSVC + #if defined(_WIN32) && !defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN32 + #define CSTD_OS_WIN32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #elif defined(_WIN32) && defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN64 + #define CSTD_OS_WIN64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + + #else + #warning "Unsupported or unknown host OS for MSVC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_GCC + #if defined(_WIN32) && defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN64 + #define CSTD_OS_WIN64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + + #elif defined(_WIN32) && !defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN32 + #define CSTD_OS_WIN32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #elif defined(ANDROID) + #undef CSTD_OS_ANDROID + #define CSTD_OS_ANDROID 1 + + #if defined(__KERNEL__) + #undef CSTD_OS_ANDROID_KERNEL + #define CSTD_OS_ANDROID_KERNEL 1 + #endif + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_ANDROID64 + #define CSTD_OS_ANDROID64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_ANDROID32 + #define CSTD_OS_ANDROID32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__KERNEL__) || defined(__linux) + #undef CSTD_OS_LINUX + #define CSTD_OS_LINUX 1 + + #if defined(__KERNEL__) + #undef CSTD_OS_LINUX_KERNEL + #define CSTD_OS_LINUX_KERNEL 1 + #endif + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_LINUX64 + #define CSTD_OS_LINUX64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_LINUX32 + #define CSTD_OS_LINUX32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__APPLE__) + #undef CSTD_OS_APPLEOS + #define CSTD_OS_APPLEOS 1 + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_APPLEOS64 + #define CSTD_OS_APPLEOS64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_APPLEOS32 + #define CSTD_OS_APPLEOS32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__SYMBIAN32__) + #undef CSTD_OS_SYMBIAN + #define CSTD_OS_SYMBIAN 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #else + #undef CSTD_OS_NONE + #define CSTD_OS_NONE 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + +#endif + +#elif 1 == CSTD_TOOLCHAIN_RVCT + + #if defined(ANDROID) + #undef CSTD_OS_ANDROID + #undef CSTD_OS_ANDROID32 + #define CSTD_OS_ANDROID 1 + #define CSTD_OS_ANDROID32 1 + + #elif defined(__linux) + #undef CSTD_OS_LINUX + #undef CSTD_OS_LINUX32 + #define CSTD_OS_LINUX 1 + #define CSTD_OS_LINUX32 1 + + #elif defined(__SYMBIAN32__) + #undef CSTD_OS_SYMBIAN + #define CSTD_OS_SYMBIAN 1 + + #else + #undef CSTD_OS_NONE + #define CSTD_OS_NONE 1 + +#endif + +#else + #warning "Unsupported or unknown host OS" + +#endif + +/* ============================================================================ + Determine the correct linker symbol Import and Export Macros +============================================================================ */ +/** + * @defgroup arm_cstd_linkage_specifiers Linkage Specifiers + * @{ + * + * This set of macros contain system-dependent linkage specifiers which + * determine the visibility of symbols across DLL boundaries. A header for a + * particular DLL should define a set of local macros derived from these, + * and should not use these macros to decorate functions directly as there may + * be multiple DLLs being used. + * + * These DLL library local macros should be (with appropriate library prefix) + * [MY_LIBRARY]_API, [MY_LIBRARY]_IMPL, and + * [MY_LIBRARY]_LOCAL. + * + * - [MY_LIBRARY]_API should be use to decorate the function + * declarations in the header. It should be defined as either + * @c CSTD_LINK_IMPORT or @c CSTD_LINK_EXPORT, depending whether the + * current situation is a compile of the DLL itself (use export) or a + * compile of an external user of the DLL (use import). + * - [MY_LIBRARY]_IMPL should be defined as @c CSTD_LINK_IMPL + * and should be used to decorate the definition of functions in the C + * file. + * - [MY_LIBRARY]_LOCAL should be used to decorate function + * declarations which are exported across translation units within the + * DLL, but which are not exported outside of the DLL boundary. + * + * Functions which are @c static in either a C file or in a header file do not + * need any form of linkage decoration, and should therefore have no linkage + * macro applied to them. + */ + +/** + * @def CSTD_LINK_IMPORT + * Specifies a function as being imported to a translation unit across a DLL + * boundary. + */ + +/** + * @def CSTD_LINK_EXPORT + * Specifies a function as being exported across a DLL boundary by a + * translation unit. + */ + +/** + * @def CSTD_LINK_IMPL + * Specifies a function which will be exported across a DLL boundary as + * being implemented by a translation unit. + */ + +/** + * @def CSTD_LINK_LOCAL + * Specifies a function which is internal to a DLL, and which should not be + * exported outside of it. + */ + +/** + * @} + */ + +#if 1 == CSTD_OS_LINUX + #define CSTD_LINK_IMPORT __attribute__((visibility("default"))) + #define CSTD_LINK_EXPORT __attribute__((visibility("default"))) + #define CSTD_LINK_IMPL __attribute__((visibility("default"))) + #define CSTD_LINK_LOCAL __attribute__((visibility("hidden"))) + +#elif 1 == CSTD_OS_WINDOWS + #define CSTD_LINK_IMPORT __declspec(dllimport) + #define CSTD_LINK_EXPORT __declspec(dllexport) + #define CSTD_LINK_IMPL __declspec(dllexport) + #define CSTD_LINK_LOCAL + +#elif 1 == CSTD_OS_SYMBIAN + #define CSTD_LINK_IMPORT IMPORT_C + #define CSTD_LINK_EXPORT IMPORT_C + #define CSTD_LINK_IMPL EXPORT_C + #define CSTD_LINK_LOCAL + +#elif 1 == CSTD_OS_APPLEOS + #define CSTD_LINK_IMPORT __attribute__((visibility("default"))) + #define CSTD_LINK_EXPORT __attribute__((visibility("default"))) + #define CSTD_LINK_IMPL __attribute__((visibility("default"))) + #define CSTD_LINK_LOCAL __attribute__((visibility("hidden"))) + +#elif 1 == CSTD_OS_ANDROID + #define CSTD_LINK_IMPORT __attribute__((visibility("default"))) + #define CSTD_LINK_EXPORT __attribute__((visibility("default"))) + #define CSTD_LINK_IMPL __attribute__((visibility("default"))) + #define CSTD_LINK_LOCAL __attribute__((visibility("hidden"))) + +#else /* CSTD_OS_NONE */ + #define CSTD_LINK_IMPORT + #define CSTD_LINK_EXPORT + #define CSTD_LINK_IMPL + #define CSTD_LINK_LOCAL + +#endif + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_COMPILERS_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_pop.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_pop.h new file mode 100644 index 0000000000000000000000000000000000000000..20862ec1fa79e6bcb9c1cf5c4f0d2f1ed2bc19b1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_pop.h @@ -0,0 +1,27 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_PACK_POP_H_ +#define _ARM_CSTD_PACK_POP_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include +#endif + +#endif /* End (_ARM_CSTD_PACK_POP_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_push.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_push.h new file mode 100644 index 0000000000000000000000000000000000000000..bc24e6942b11d0cddd056fbe55b36800f36a81be --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_push.h @@ -0,0 +1,27 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_PACK_PUSH_H_ +#define _ARM_CSTD_PACK_PUSH_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include +#endif + +#endif /* End (_ARM_CSTD_PACK_PUSH_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types.h new file mode 100644 index 0000000000000000000000000000000000000000..efeefa590c6527e2e270a75c454b21e001d3a042 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_TYPES_H_ +#define _ARM_CSTD_TYPES_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include "arm_cstd_types_msvc.h" +#elif 1 == CSTD_TOOLCHAIN_GCC + #include "arm_cstd_types_gcc.h" +#elif 1 == CSTD_TOOLCHAIN_RVCT + #include "arm_cstd_types_rvct.h" +#else + #error "Toolchain not recognized" +#endif + +#endif /* End (_ARM_CSTD_TYPES_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_gcc.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_gcc.h new file mode 100644 index 0000000000000000000000000000000000000000..679819655002f928a65f8a22aff6517aa0990ec9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_gcc.h @@ -0,0 +1,92 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_TYPES_GCC_H_ +#define _ARM_CSTD_TYPES_GCC_H_ + +/* ============================================================================ + Type definitions +============================================================================ */ +/* All modern versions of GCC support stdint outside of C99 Mode. */ +/* However, Linux kernel limits what headers are available! */ +#if 1 == CSTD_OS_LINUX_KERNEL + #include + #include + #include + #include + + /* Fix up any types which CSTD provdes but which Linux is missing. */ + /* Note Linux assumes pointers are "long", so this is safe. */ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + typedef unsigned long uintptr_t; + #endif + typedef long intptr_t; + +#else + #include + #include + #include +#endif + +typedef uint32_t bool_t; + +#if !defined(TRUE) + #define TRUE ((bool_t)1) +#endif + +#if !defined(FALSE) + #define FALSE ((bool_t)0) +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/* Doxygen documentation for these is in the RVCT header. */ +#define ASM __asm__ + +#define INLINE __inline__ + +#define FORCE_INLINE __attribute__((__always_inline__)) __inline__ + +#define NEVER_INLINE __attribute__((__noinline__)) + +#define PURE __attribute__((__pure__)) + +#define PACKED __attribute__((__packed__)) + +/* GCC does not support pointers to UNALIGNED data, so we do not define it to + * force a compile error if this macro is used. */ + +#define RESTRICT __restrict__ + +/* RVCT in GCC mode does not support the CHECK_RESULT attribute. */ +#if 0 == CSTD_TOOLCHAIN_RVCT_GCC_MODE + #define CHECK_RESULT __attribute__((__warn_unused_result__)) +#else + #define CHECK_RESULT +#endif + +/* RVCT in GCC mode does not support the __func__ name outside of C99. */ +#if (0 == CSTD_TOOLCHAIN_RVCT_GCC_MODE) + #define CSTD_FUNC __func__ +#else + #define CSTD_FUNC __FUNCTION__ +#endif + +#endif /* End (_ARM_CSTD_TYPES_GCC_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_rvct.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_rvct.h new file mode 100644 index 0000000000000000000000000000000000000000..a8efda0040a148da5230cf0fef2735f52e04db1d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_rvct.h @@ -0,0 +1,192 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_TYPES_RVCT_H_ +#define _ARM_CSTD_TYPES_RVCT_H_ + +/* ============================================================================ + Type definitions +============================================================================ */ +#include +#include + +#if 199901L <= __STDC_VERSION__ + #include +#else + typedef unsigned char uint8_t; + typedef signed char int8_t; + typedef unsigned short uint16_t; + typedef signed short int16_t; + typedef unsigned int uint32_t; + typedef signed int int32_t; + typedef unsigned __int64 uint64_t; + typedef signed __int64 int64_t; + typedef ptrdiff_t intptr_t; + typedef size_t uintptr_t; +#endif + +typedef uint32_t bool_t; + +#if !defined(TRUE) + #define TRUE ((bool_t)1) +#endif + +#if !defined(FALSE) + #define FALSE ((bool_t)0) +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +/** + * @def ASM + * @hideinitializer + * Mark an assembler block. Such blocks are often compiler specific, so often + * need to be surrounded in appropriate @c ifdef and @c endif blocks + * using the relevant @c CSTD_TOOLCHAIN macro. + */ +#define ASM __asm + +/** + * @def INLINE + * @hideinitializer + * Mark a definition as something which should be inlined. This is not always + * possible on a given compiler, and may be disabled at lower optimization + * levels. + */ +#define INLINE __inline + +/** + * @def FORCE_INLINE + * @hideinitializer + * Mark a definition as something which should be inlined. This provides a much + * stronger hint to the compiler than @c INLINE, and if supported should always + * result in an inlined function being emitted. If not supported this falls + * back to using the @c INLINE definition. + */ +#define FORCE_INLINE __forceinline + +/** + * @def NEVER_INLINE + * @hideinitializer + * Mark a definition as something which should not be inlined. This provides a + * stronger hint to the compiler than the function should not be inlined, + * bypassing any heuristic rules the compiler normally applies. If not + * supported by a toolchain this falls back to being an empty macro. + */ +#define NEVER_INLINE __declspec(noinline) + +/** + * @def PURE + * @hideinitializer + * Denotes that a function's return is only dependent on its inputs, enabling + * more efficient optimizations. Falls back to an empty macro if not supported. + */ +#define PURE __pure + +/** + * @def PACKED + * @hideinitializer + * Denotes that a structure should be stored in a packed form. This macro must + * be used in conjunction with the @c arm_cstd_pack_* headers for portability: + * + * @code + * #include + * + * struct PACKED myStruct { + * ... + * }; + * + * #include + * PACKED + * @endcode + */ +#define PACKED __packed + +/** + * @def UNALIGNED + * @hideinitializer + * Denotes that a pointer points to a buffer with lower alignment than the + * natural alignment required by the C standard. This should only be used + * in extreme cases, as the emitted code is normally more efficient if memory + * is aligned. + * + * @warning This is \b NON-PORTABLE. The GNU tools are anti-unaligned pointers + * and have no support for such a construction. + */ +#define UNALIGNED __packed + +/** + * @def RESTRICT + * @hideinitializer + * Denotes that a pointer does not overlap with any other points currently in + * scope, increasing the range of optimizations which can be performed by the + * compiler. + * + * @warning Specification of @c RESTRICT is a contract between the programmer + * and the compiler. If you place @c RESTICT on buffers which do actually + * overlap the behavior is undefined, and likely to vary at different + * optimization levels.! + */ +#define RESTRICT __restrict + +/** + * @def CHECK_RESULT + * @hideinitializer + * Function attribute which causes a warning to be emitted if the compiler's + * return value is not used by the caller. Compiles to an empty macro if + * there is no supported mechanism for this check in the underlying compiler. + * + * @note At the time of writing this is only supported by GCC. RVCT does not + * support this attribute, even in GCC mode, so engineers are encouraged to + * compile their code using GCC even if primarily working with another + * compiler. + * + * @code + * CHECK_RESULT int my_func( void ); + * @endcode + */ +#define CHECK_RESULT + +/** + * @def CSTD_FUNC + * Specify the @c CSTD_FUNC macro, a portable construct containing the name of + * the current function. On most compilers it is illegal to use this macro + * outside of a function scope. If not supported by the compiler we define + * @c CSTD_FUNC as an empty string. + * + * @warning Due to the implementation of this on most modern compilers this + * expands to a magically defined "static const" variable, not a constant + * string. This makes injecting @c CSTD_FUNC directly in to compile-time + * strings impossible, so if you want to make the function name part of a + * larger string you must use a printf-like function with a @c @%s template + * which is populated with @c CSTD_FUNC + */ +#define CSTD_FUNC __FUNCTION__ + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_TYPES_RVCT_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/mali_malisw.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/mali_malisw.h new file mode 100644 index 0000000000000000000000000000000000000000..15faf15bf13afb74ad3c99a6b962ecbca4da5c12 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/mali_malisw.h @@ -0,0 +1,242 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _MALISW_H_ +#define _MALISW_H_ + +/** + * @file mali_malisw.h + * Driver-wide include for common macros and types. + */ + +/** + * @defgroup malisw Mali software definitions and types + * @{ + */ + +#include + +#include "mali_stdtypes.h" + +/** @brief Gets the container object when given a pointer to a member of an object. */ +#define CONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type,member))) + +/** @brief Gets the number of elements of type s in a fixed length array of s */ +#define NELEMS(s) (sizeof(s)/sizeof((s)[0])) + +/** + * @brief The lesser of two values. + * May evaluate its arguments more than once. + * @see CSTD_MIN + */ +#define MIN(x,y) CSTD_MIN(x,y) + +/** + * @brief The greater of two values. + * May evaluate its arguments more than once. + * @see CSTD_MAX + */ +#define MAX(x,y) CSTD_MAX(x,y) + +/** + * @brief Clamp value x to within min and max inclusive + * May evaluate its arguments more than once. + * @see CSTD_CLAMP + */ +#define CLAMP( x, min, max ) CSTD_CLAMP( x, min, max ) + +/** + * @brief Convert a pointer into a u64 for storing in a data structure. + * This is commonly used when pairing a 32-bit CPU with a 64-bit peripheral, + * such as a Midgard GPU. C's type promotion is complex and a straight cast + * does not work reliably as pointers are often considered as signed. + */ +#define PTR_TO_U64( x ) CSTD_PTR_TO_U64( x ) + +/** + * @name Mali library linkage specifiers + * These directly map to the cstd versions described in detail here: @ref arm_cstd_linkage_specifiers + * @{ + */ +#define MALI_IMPORT CSTD_LINK_IMPORT +#define MALI_EXPORT CSTD_LINK_EXPORT +#define MALI_IMPL CSTD_LINK_IMPL +#if defined(CONFIG_MALI_DEBUG) || !MALI_CUSTOMER_RELEASE +#define MALI_LOCAL CSTD_LINK_EXPORT +#else +#define MALI_LOCAL CSTD_LINK_LOCAL +#endif + +/** @brief Decorate exported function prototypes. + * + * The file containing the implementation of the function should define this to be MALI_EXPORT before including + * malisw/mali_malisw.h. + */ +#ifndef MALI_API +#define MALI_API MALI_IMPORT +#endif +/** @} */ + +/** @name Testable static functions + * @{ + * + * These macros can be used to allow functions to be static in release builds but exported from a shared library in unit + * test builds, allowing them to be tested or used to assist testing. + * + * Example mali_foo_bar.c containing the function to test: + * + * @code + * #define MALI_API MALI_EXPORT + * + * #include + * #include "mali_foo_testable_statics.h" + * + * MALI_TESTABLE_STATIC_IMPL void my_func() + * { + * //Implementation + * } + * @endcode + * + * Example mali_foo_testable_statics.h: + * + * @code + * #if 1 == MALI_UNIT_TEST + * #include + * + * MALI_TESTABLE_STATIC_API void my_func(); + * + * #endif + * @endcode + * + * Example mali_foo_tests.c: + * + * @code + * #include + * + * void my_test_func() + * { + * my_func(); + * } + * @endcode + */ + +/** @brief Decorate testable static function implementations. + * + * A header file containing a MALI_TESTABLE_STATIC_API-decorated prototype for each static function will be required + * when MALI_UNIT_TEST == 1 in order to link the function from the test. + */ +#if 1 == MALI_UNIT_TEST +#define MALI_TESTABLE_STATIC_IMPL MALI_IMPL +#else +#define MALI_TESTABLE_STATIC_IMPL static +#endif + +/** @brief Decorate testable static function prototypes. + * + * @note Prototypes should @em only be declared when MALI_UNIT_TEST == 1 + */ +#define MALI_TESTABLE_STATIC_API MALI_API +/** @} */ + +/** @name Testable local functions + * @{ + * + * These macros can be used to allow functions to be local to a shared library in release builds but be exported in unit + * test builds, allowing them to be tested or used to assist testing. + * + * Example mali_foo_bar.c containing the function to test: + * + * @code + * #define MALI_API MALI_EXPORT + * + * #include + * #include "mali_foo_bar.h" + * + * MALI_TESTABLE_LOCAL_IMPL void my_func() + * { + * //Implementation + * } + * @endcode + * + * Example mali_foo_bar.h: + * + * @code + * #include + * + * MALI_TESTABLE_LOCAL_API void my_func(); + * + * @endcode + * + * Example mali_foo_tests.c: + * + * @code + * #include + * + * void my_test_func() + * { + * my_func(); + * } + * @endcode + */ + +/** @brief Decorate testable local function implementations. + * + * This can be used to have a function normally local to the shared library except in debug builds where it will be + * exported. + */ +#ifdef CONFIG_MALI_DEBUG +#define MALI_TESTABLE_LOCAL_IMPL MALI_IMPL +#else +#define MALI_TESTABLE_LOCAL_IMPL MALI_LOCAL +#endif /* CONFIG_MALI_DEBUG */ + +/** @brief Decorate testable local function prototypes. + * + * This can be used to have a function normally local to the shared library except in debug builds where it will be + * exported. + */ +#ifdef CONFIG_MALI_DEBUG +#define MALI_TESTABLE_LOCAL_API MALI_API +#else +#define MALI_TESTABLE_LOCAL_API MALI_LOCAL +#endif /* CONFIG_MALI_DEBUG */ +/** @} */ + +/** + * Flag a cast as a reinterpretation, usually of a pointer type. + * @see CSTD_REINTERPRET_CAST + */ +#define REINTERPRET_CAST(type) CSTD_REINTERPRET_CAST(type) + +/** + * Flag a cast as casting away const, usually of a pointer type. + * @see CSTD_CONST_CAST + */ +#define CONST_CAST(type) (type) CSTD_CONST_CAST(type) + +/** + * Flag a cast as a (potentially complex) value conversion, usually of a numerical type. + * @see CSTD_STATIC_CAST + */ +#define STATIC_CAST(type) (type) CSTD_STATIC_CAST(type) + + +/** @} */ + +#endif /* _MALISW_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/mali_stdtypes.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/mali_stdtypes.h new file mode 100644 index 0000000000000000000000000000000000000000..5dabe26ec01c29f82c57fbe2c19472853e0a22c4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/malisw/mali_stdtypes.h @@ -0,0 +1,265 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _MALISW_STDTYPES_H_ +#define _MALISW_STDTYPES_H_ + +/** + * @file mali_stdtypes.h + * This file defines the standard types used by the Mali codebase. + */ + +/** + * @addtogroup malisw + * @{ + */ + +/** + * @defgroup malisw_stdtypes Mali software standard types + * + * Basic driver-wide types. + */ + +/** + * @addtogroup malisw_stdtypes + * @{ + */ + +#include "arm_cstd/arm_cstd.h" + +/** + * @name Scalar types. + * These are the scalar types used within the mali driver. + * @{ + */ +/* Note: if compiling the Linux kernel then avoid redefining these. */ +#if 0 == CSTD_OS_LINUX_KERNEL + typedef uint64_t u64; + typedef uint32_t u32; + typedef uint16_t u16; + typedef uint8_t u8; + + typedef int64_t s64; + typedef int32_t s32; + typedef int16_t s16; + typedef int8_t s8; +#endif + +typedef double f64; +typedef float f32; +typedef u16 f16; + +typedef u32 mali_fixed16_16; +/* @} */ + +/** + * @name Boolean types. + * The intended use is for bool8 to be used when storing boolean values in + * structures, casting to mali_bool to be used in code sections. + * @{ + */ +typedef bool_t mali_bool; +typedef u8 mali_bool8; + +#define MALI_FALSE FALSE +#define MALI_TRUE TRUE +/* @} */ + +/** + * @name Integer bounding values + * Maximum and minimum values for integer types + * @{ + */ +#ifndef U64_MAX +#define U64_MAX UINT64_MAX +#endif + +#ifndef U32_MAX +#define U32_MAX UINT32_MAX +#endif + +#ifndef U16_MAX +#define U16_MAX UINT16_MAX +#endif + +#ifndef U8_MAX +#define U8_MAX UINT8_MAX +#endif + +#ifndef S64_MAX +#define S64_MAX INT64_MAX +#endif + +#ifndef S64_MIN +#define S64_MIN INT64_MIN +#endif + +#ifndef S32_MAX +#define S32_MAX INT32_MAX +#endif + +#ifndef S32_MIN +#define S32_MIN INT32_MIN +#endif + +#ifndef S16_MAX +#define S16_MAX INT16_MAX +#endif + +#ifndef S16_MIN +#define S16_MIN INT16_MIN +#endif + +#ifndef S8_MAX +#define S8_MAX INT8_MAX +#endif + +#ifndef S8_MIN +#define S8_MIN INT8_MIN +#endif + +/* @} */ + +/** + * @name GPU address types + * Types for integers which hold a GPU pointer or GPU pointer offsets. + * @{ + */ +typedef u64 mali_addr64; +typedef u32 mali_addr32; +typedef u64 mali_size64; +typedef s64 mali_offset64; +/* 32 bit offsets and sizes are always for native types and so use ptrdiff_t and size_t respectively */ +/* @} */ + +/** + * @name Mali error types + * @brief The common error type for the mali drivers + * The mali_error type, all driver error handling should be of this type unless + * it must deal with a specific APIs error type. + * @{ + */ +typedef enum +{ + /** + * @brief Common Mali errors for the entire driver + * MALI_ERROR_NONE is guaranteed to be 0. + * @{ + */ + MALI_ERROR_NONE = 0, + MALI_ERROR_OUT_OF_GPU_MEMORY, + MALI_ERROR_OUT_OF_MEMORY, + MALI_ERROR_FUNCTION_FAILED, + /* @} */ + /** + * @brief Mali errors for Client APIs to pass to EGL when creating EGLImages + * These errors must only be returned to EGL from one of the Client APIs as part of the + * (clientapi)_egl_image_interface.h + * @{ + */ + MALI_ERROR_EGLP_BAD_ACCESS, + MALI_ERROR_EGLP_BAD_PARAMETER, + /* @} */ + /** + * @brief Mali errors for the MCL module. + * These errors must only be used within the private components of the OpenCL implementation that report + * directly to API functions for cases where errors cannot be detected in the entrypoints file. They must + * not be passed between driver components. + * These are errors in the mali error space specifically for the MCL module, hence the MCLP prefix. + * @{ + */ + MALI_ERROR_MCLP_DEVICE_NOT_FOUND, + MALI_ERROR_MCLP_DEVICE_NOT_AVAILABLE, + MALI_ERROR_MCLP_COMPILER_NOT_AVAILABLE, + MALI_ERROR_MCLP_MEM_OBJECT_ALLOCATION_FAILURE, + MALI_ERROR_MCLP_PROFILING_INFO_NOT_AVAILABLE, + MALI_ERROR_MCLP_MEM_COPY_OVERLAP, + MALI_ERROR_MCLP_IMAGE_FORMAT_MISMATCH, + MALI_ERROR_MCLP_IMAGE_FORMAT_NOT_SUPPORTED, + MALI_ERROR_MCLP_BUILD_PROGRAM_FAILURE, + MALI_ERROR_MCLP_MAP_FAILURE, + MALI_ERROR_MCLP_MISALIGNED_SUB_BUFFER_OFFSET, + MALI_ERROR_MCLP_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, + MALI_ERROR_MCLP_INVALID_VALUE, + MALI_ERROR_MCLP_INVALID_DEVICE_TYPE, + MALI_ERROR_MCLP_INVALID_PLATFORM, + MALI_ERROR_MCLP_INVALID_DEVICE, + MALI_ERROR_MCLP_INVALID_CONTEXT, + MALI_ERROR_MCLP_INVALID_QUEUE_PROPERTIES, + MALI_ERROR_MCLP_INVALID_COMMAND_QUEUE, + MALI_ERROR_MCLP_INVALID_HOST_PTR, + MALI_ERROR_MCLP_INVALID_MEM_OBJECT, + MALI_ERROR_MCLP_INVALID_IMAGE_FORMAT_DESCRIPTOR, + MALI_ERROR_MCLP_INVALID_IMAGE_SIZE, + MALI_ERROR_MCLP_INVALID_SAMPLER, + MALI_ERROR_MCLP_INVALID_BINARY, + MALI_ERROR_MCLP_INVALID_BUILD_OPTIONS, + MALI_ERROR_MCLP_INVALID_PROGRAM, + MALI_ERROR_MCLP_INVALID_PROGRAM_EXECUTABLE, + MALI_ERROR_MCLP_INVALID_KERNEL_NAME, + MALI_ERROR_MCLP_INVALID_KERNEL_DEFINITION, + MALI_ERROR_MCLP_INVALID_KERNEL, + MALI_ERROR_MCLP_INVALID_ARG_INDEX, + MALI_ERROR_MCLP_INVALID_ARG_VALUE, + MALI_ERROR_MCLP_INVALID_ARG_SIZE, + MALI_ERROR_MCLP_INVALID_KERNEL_ARGS, + MALI_ERROR_MCLP_INVALID_WORK_DIMENSION, + MALI_ERROR_MCLP_INVALID_WORK_GROUP_SIZE, + MALI_ERROR_MCLP_INVALID_WORK_ITEM_SIZE, + MALI_ERROR_MCLP_INVALID_GLOBAL_OFFSET, + MALI_ERROR_MCLP_INVALID_EVENT_WAIT_LIST, + MALI_ERROR_MCLP_INVALID_EVENT, + MALI_ERROR_MCLP_INVALID_OPERATION, + MALI_ERROR_MCLP_INVALID_GL_OBJECT, + MALI_ERROR_MCLP_INVALID_BUFFER_SIZE, + MALI_ERROR_MCLP_INVALID_MIP_LEVEL, + MALI_ERROR_MCLP_INVALID_GLOBAL_WORK_SIZE, + MALI_ERROR_MCLP_INVALID_GL_SHAREGROUP_REFERENCE_KHR, + MALI_ERROR_MCLP_INVALID_EGL_OBJECT, + /* @} */ + /** + * @brief Mali errors for the BASE module + * These errors must only be used within the private components of the Base implementation. They will not + * passed to other modules by the base driver. + * These are errors in the mali error space specifically for the BASE module, hence the BASEP prefix. + * @{ + */ + MALI_ERROR_BASEP_INVALID_FUNCTION, + /* @} */ + /** A dependency exists upon a resource that the client application wants to modify, so the driver must either + * create a copy of the resource (if possible) or block until the dependency has been satisfied. + */ + MALI_ERROR_RESOURCE_IN_USE, + + /** + * @brief A stride value was too big. + * + * A surface descriptor can store strides of up to 231-1 bytes but strides greater than + * 228-1 bytes cannot be expressed in bits without overflow. + */ + MALI_ERROR_STRIDE_TOO_BIG + +} mali_error; +/* @} */ + +/* @} */ + +/* @} */ + +#endif /* _MALISW_STDTYPES_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..558657bbced900f03f3b2532c14a8d33b29fb377 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/Kbuild @@ -0,0 +1,21 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y) +# remove begin and end quotes from the Kconfig string type + platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)) + obj-y += $(platform_name)/ +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..8fb4e917c4fa37407c5c11e707ba019910e0e184 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/Kconfig @@ -0,0 +1,24 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +# Add your platform specific Kconfig file here +# +# "drivers/gpu/arm/midgard/platform/xxx/Kconfig" +# +# Where xxx is the platform name is the name set in MALI_PLATFORM_THIRDPARTY_NAME +# + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..f6af6220be12a503fafe4a387465f43af65b3912 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/Kbuild @@ -0,0 +1,19 @@ +# +# (C) COPYRIGHT 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +obj-y += mali_kbase_config_juno_soc.o + + +obj-m += juno_mali_opp.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/juno_mali_opp.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/juno_mali_opp.c new file mode 100644 index 0000000000000000000000000000000000000000..f137226f409aee9742551821a044cd47e3994003 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/juno_mali_opp.c @@ -0,0 +1,73 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include + + +static int init_juno_opps_from_scpi(struct device *dev) +{ + struct scpi_opp *sopp; + int i; + + /* Hard coded for Juno. 2 is GPU domain */ + sopp = scpi_dvfs_get_opps(2); + if (IS_ERR_OR_NULL(sopp)) + return PTR_ERR(sopp); + + for (i = 0; i < sopp->count; i++) { + struct scpi_opp_entry *e = &sopp->opp[i]; + dev_info(dev, "Mali OPP from SCPI: %u Hz @ %u mV\n", + e->freq_hz, e->volt_mv); + + dev_pm_opp_add(dev, e->freq_hz, e->volt_mv * 1000); + } + + return 0; +} + +static int juno_setup_opps(void) +{ + struct device_node *np; + struct platform_device *pdev; + int err; + + np = of_find_node_by_name(NULL, "gpu"); + if (!np) { + pr_err("Failed to find DT entry for Mali\n"); + return -EFAULT; + } + + pdev = of_find_device_by_node(np); + if (!pdev) { + pr_err("Failed to find device for Mali\n"); + of_node_put(np); + return -EFAULT; + } + + err = init_juno_opps_from_scpi(&pdev->dev); + + of_node_put(np); + + return err; +} + +module_init(juno_setup_opps); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_juno_soc.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_juno_soc.c new file mode 100644 index 0000000000000000000000000000000000000000..d8f14330528030afc6b091a2a5b16ef16f52df8b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_juno_soc.c @@ -0,0 +1,134 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include + +#include "../mali_kbase_power_actor.h" + +/* Versatile Express (VE) Juno Development Platform */ + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 65, + .mmu_irq_number = 66, + .gpu_irq_number = 64, + .io_memory_region = { + .start = 0x2D000000, + .end = 0x2D000000 + (4096 * 4) - 1} +}; +#endif + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +static unsigned long juno_model_static_power(unsigned long voltage, unsigned long temperature) +{ + /* Calculate power, corrected for voltage. + * Shifts are done to avoid overflow. */ + const unsigned long coefficient = (410UL << 20) / (729000000UL >> 10); + const unsigned long voltage_cubed = (voltage * voltage * voltage) >> 10; + + /* Calculate the temperature scaling factor. To be applied to the + * voltage scaled power. */ + const unsigned long temp = temperature / 1000; + const unsigned long temp_squared = temp * temp; + const unsigned long temp_cubed = temp_squared * temp; + const unsigned long temp_scaling_factor = + (2 * temp_cubed) + - (80 * temp_squared) + + (4700 * temp) + + 32000; + + return (((coefficient * voltage_cubed) >> 20) * temp_scaling_factor) / 1000000; +} + +static unsigned long juno_model_dynamic_power(unsigned long freq, + unsigned long voltage) +{ + /* The inputs: freq (f) is in Hz, and voltage (v) in mV. + * The coefficient (c) is in mW/(MHz mV mV). + * + * This function calculates the dynamic power after this formula: + * Pdyn (mW) = c (mW/(MHz*mV*mV)) * v (mV) * v (mV) * f (MHz) + */ + const unsigned long v2 = (voltage * voltage) / 1000; /* m*(V*V) */ + const unsigned long f_mhz = freq / 1000000; /* MHz */ + const unsigned long coefficient = 3600; /* mW/(MHz*mV*mV) */ + + return (coefficient * v2 * f_mhz) / 1000000; /* mW */ +} + +static struct mali_pa_model_ops juno_model_ops = { + .get_static_power = juno_model_static_power, + .get_dynamic_power = juno_model_dynamic_power, +}; + +static struct kbase_attribute config_attributes[] = { + { KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, 500 }, + { KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, ((uintptr_t)&pm_callbacks) }, + { KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS, ((uintptr_t)&juno_model_ops) }, + + { KBASE_CONFIG_ATTR_END, 0 } +}; + +static struct kbase_platform_config versatile_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..196de7129a578f6f2c4d2cc7a4d0be0ed2bcdbb9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_platform.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 600000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 600000 diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h new file mode 100644 index 0000000000000000000000000000000000000000..b0d8e3249b8058904a3e5d55ffa085a25d87533d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @brief Entry point to transfer control to a platform for early initialization + * + * This function is called early on in the initialization during execution of + * @ref kbase_driver_init. + * + * @return Zero to indicate success non-zero for failure. + */ +int kbase_platform_early_init(void); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..084a156134363034dd636be4671b9c49dbb6b4a3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +obj-y += mali_kbase_config_vexpress.o +obj-y += mali_kbase_cpu_vexpress.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..81259485ee00b3c7662d976c06472612a14bba0f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 5000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 5000 diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..fff382b789fde25549bbcc201b20e502b3f61484 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c @@ -0,0 +1,454 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +/* MTK clock modified */ +#include "mt_gpufreq.h" +#include "upmu_common.h" +#include "upmu_sw.h" +#include "upmu_hw.h" +#include "mali_kbase_pm.h" + +#include "mt_chip.h" +#if defined(CONFIG_MTK_CLKMGR) +#include "mach/mt_clkmgr.h" +#endif /* defined(CONFIG_MTK_CLKMGR) */ +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif /* !CONFIG_MTK_CLKMGR */ + +#include +#include + +/* Versatile Express (VE) configuration defaults shared between config_attributes[] + * and config_attributes_hw_issue_8408[]. Settings are not shared for + * JS_HARD_STOP_TICKS_SS and JS_RESET_TICKS_SS. + */ +#define KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG 15000000u /* 15ms, an agressive tick for testing purposes. This will reduce performance significantly */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG 1 /* between 15ms and 30ms before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG 1 /* between 15ms and 30ms before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG 333 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG 2000 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG 166 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG 100000 /* 1500s (25mins) before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS_DEBUG 500 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG 3000 /* 7.5s before resetting GPU - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL_DEBUG 500 /* 45s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS_DEBUG 100166 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_SCHEDULING_TICK_NS 1250000000u /* 1.25s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS 2 /* 2.5s before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL 1 /* 1.25s before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS 4 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401 24 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL 2 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS 1200 /* 1500s before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS 6 /* 7.5s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401 36 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL 3 /* 7.5s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS 1201 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_RESET_TIMEOUT_MS 3000 /* 3s before cancelling stuck jobs */ +#define KBASE_VE_JS_CTX_TIMESLICE_NS 1000000 /* 1ms - an agressive timeslice for testing purposes (causes lots of scheduling out for >4 ctxs) */ +#define KBASE_VE_POWER_MANAGEMENT_CALLBACKS ((uintptr_t)&pm_callbacks) +#define KBASE_VE_CPU_SPEED_FUNC ((uintptr_t)&kbase_get_vexpress_cpu_clock_speed) + +#define HARD_RESET_AT_POWER_OFF 1 + +#ifndef CONFIG_OF +static kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0xFC010000, + .end = 0xFC010000 + (4096 * 4) - 1 + } +}; +#endif /* CONFIG_OF */ + +//#define NO_DVFS_FOR_BRINGUP + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + int touch_boost_flag, touch_boost_id; + int power_on_freq_flag, power_on_freq_id; + int ret; + + /* MTK clock modified */ + /*if(mt6325_upmu_get_swcid() >= PMIC6325_E3_CID_CODE) + { + mt_gpufreq_voltage_enable_set(1); + }*/ + mt_gpufreq_voltage_enable_set(1); + mtk_set_vgpu_power_on_flag(MTK_VGPU_POWER_ON); + ged_dvfs_gpu_clock_switch_notify(1); + +#if defined(CONFIG_MTK_CLKMGR) + enable_clock( MT_CG_DISP0_SMI_COMMON, "GPU"); + enable_clock( MT_CG_MFG_BG3D, "GPU"); +#else + ret = clk_prepare_enable(kbdev->clk_display_scp); + if (ret) + { + pr_alert("MALI: clk_prepare_enable failed when enabling display MTCMOS"); + } + + ret = clk_prepare_enable(kbdev->clk_smi_common); + if (ret) + { + pr_alert("MALI: clk_prepare_enable failed when enabling display smi_common clock"); + } + + ret = clk_prepare_enable(kbdev->clk_mfg_scp); + if (ret) + { + pr_alert("MALI: clk_prepare_enable failed when enabling mfg MTCMOS"); + } + + ret = clk_prepare_enable(kbdev->clk_mfg); + if (ret) + { + pr_alert("MALI: clk_prepare_enable failed when enabling mfg clock"); + } +#endif + pr_debug("MALI :[Power on] get GPU ID : 0x%x \n", kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID)) ); + + mtk_get_touch_boost_flag( &touch_boost_flag, &touch_boost_id); + if(touch_boost_flag > 0) + { + + mtk_set_mt_gpufreq_target(touch_boost_id); + mtk_clear_touch_boost_flag(); + } + + mtk_get_power_on_freq_flag( &power_on_freq_flag, &power_on_freq_id); + if(power_on_freq_flag > 0) + { + mtk_set_mt_gpufreq_target(power_on_freq_id); + mtk_clear_power_on_freq_flag(); + } + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +/*----------------------------------------------------------------------------- + Macro +-----------------------------------------------------------------------------*/ +#define DELAY_LOOP_COUNT 100000 +#define MFG_DEBUG_SEL 0x3 +#define MFG_BUS_IDLE_BIT (1 << 2) + +#define MFG_DEBUG_CTRL_REG(value) (value + 0x180) +#define MFG_DEBUG_STAT_REG(value) (value + 0x184) + +#define MFG_WRITE32(value, addr) writel(value, addr) +#define MFG_READ32(addr) readl(addr) + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ + volatile int polling_count = 100000; + volatile int i = 0; + void __iomem *clk_mfgsys_base = kbdev->mfg_register; + if (!clk_mfgsys_base ) { + pr_alert("[Mali] mfg_register find node failed\n"); + }else{ + + /// 1. Delay 0.01ms before power off + for (i=0; i < DELAY_LOOP_COUNT;i++); + if (DELAY_LOOP_COUNT != i) + { + pr_alert("[MALI] power off delay error!\n"); + } + + /// 2. Polling the MFG_DEBUG_REG for checking GPU IDLE before MTCMOS power off (0.1ms) + + MFG_WRITE32(0x3, MFG_DEBUG_CTRL_REG(clk_mfgsys_base)); + + do { + /// 0x13000184[2] + /// 1'b1: bus idle + /// 1'b0: bus busy + if (MFG_READ32(MFG_DEBUG_STAT_REG(clk_mfgsys_base)) & MFG_BUS_IDLE_BIT) + { + /// pr_debug("[MALI]MFG BUS already IDLE! Ready to power off, %d\n", polling_count); + break; + } + } while (polling_count--); + + if (polling_count <=0) + { + pr_alert("[MALI]!!!!MFG(GPU) subsys is still BUSY!!!!!, polling_count=%d\n", polling_count); + } + } +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ +// KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif + + /// Polling the MFG_DEBUG_REG for checking GPU IDLE before MTCMOS power off (0.1ms) + MFG_WRITE32(0x3, MFG_DEBUG_CTRL_REG(clk_mfgsys_base)); + + do { + /// 0x13000184[2] + /// 1'b1: bus idle + /// 1'b0: bus busy + if (MFG_READ32(MFG_DEBUG_STAT_REG(clk_mfgsys_base)) & MFG_BUS_IDLE_BIT) + { + /// pr_alert("[MALI]MFG BUS already IDLE! Ready to power off, %d\n", polling_count); + break; + } + } while (polling_count--); + + if (polling_count <=0) + { + pr_alert("[MALI]!!!!MFG(GPU) subsys is still BUSY2!!!!!, polling_count=%d\n", polling_count); + } + + /* MTK clock modified */ +#if defined(CONFIG_MTK_CLKMGR) + disable_clock( MT_CG_MFG_BG3D, "GPU"); + disable_clock( MT_CG_DISP0_SMI_COMMON, "GPU"); +#else + clk_disable_unprepare(kbdev->clk_mfg); + clk_disable_unprepare(kbdev->clk_mfg_scp); + clk_disable_unprepare(kbdev->clk_smi_common); + clk_disable_unprepare(kbdev->clk_display_scp); +#endif + /*if(mt6325_upmu_get_swcid() >= PMIC6325_E3_CID_CODE) + { + mt_gpufreq_voltage_enable_set(0); + }*/ + mt_gpufreq_voltage_enable_set(0); + mtk_set_vgpu_power_on_flag(MTK_VGPU_POWER_OFF); + ged_dvfs_gpu_clock_switch_notify(0); + +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +/* Please keep table config_attributes in sync with config_attributes_hw_issue_8408 */ +static struct kbase_attribute config_attributes[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +/* as config_attributes array above except with different settings for + * JS_HARD_STOP_TICKS_SS, JS_RESET_TICKS_SS that + * are needed for BASE_HW_ISSUE_8408. + */ +struct kbase_attribute config_attributes_hw_issue_8408[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +static struct kbase_platform_config versatile_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..3dd6c0f5504604ee3b184d8dfa45bb4f007cdde8 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.c @@ -0,0 +1,180 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HZ_IN_MHZ (1000000) + +#define CORETILE_EXPRESS_A9X4_SCC_START (0x100E2000) +#define MOTHERBOARD_SYS_CFG_START (0x10000000) +#define SYS_CFGDATA_OFFSET (0x000000A0) +#define SYS_CFGCTRL_OFFSET (0x000000A4) +#define SYS_CFGSTAT_OFFSET (0x000000A8) + +#define SYS_CFGCTRL_START_BIT_VALUE (1 << 31) +#define READ_REG_BIT_VALUE (0 << 30) +#define DCC_DEFAULT_BIT_VALUE (0 << 26) +#define SYS_CFG_OSC_FUNC_BIT_VALUE (1 << 20) +#define SITE_DEFAULT_BIT_VALUE (1 << 16) +#define BOARD_STACK_POS_DEFAULT_BIT_VALUE (0 << 12) +#define DEVICE_DEFAULT_BIT_VALUE (2 << 0) +#define SYS_CFG_COMPLETE_BIT_VALUE (1 << 0) +#define SYS_CFG_ERROR_BIT_VALUE (1 << 1) + +#define FEED_REG_BIT_MASK (0x0F) +#define FCLK_PA_DIVIDE_BIT_SHIFT (0x03) +#define FCLK_PB_DIVIDE_BIT_SHIFT (0x07) +#define FCLK_PC_DIVIDE_BIT_SHIFT (0x0B) +#define AXICLK_PA_DIVIDE_BIT_SHIFT (0x0F) +#define AXICLK_PB_DIVIDE_BIT_SHIFT (0x13) + +#define IS_SINGLE_BIT_SET(val, pos) (val&(1<> FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[10:7] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PB_DIVIDE_BIT_SHIFT)) >> FCLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + if (IS_SINGLE_BIT_SET(reg_val, 1)) { /*CFGRW0[1] - CLKOC */ + /* CFGRW0[6:3] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PA_DIVIDE_BIT_SHIFT)) >> FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[14:11] */ + pc_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PC_DIVIDE_BIT_SHIFT)) >> FCLK_PC_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pc_divide + 1); + } else if (IS_SINGLE_BIT_SET(reg_val, 2)) { /*CFGRW0[2] - FACLK */ + /* CFGRW0[18:15] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << AXICLK_PA_DIVIDE_BIT_SHIFT)) >> AXICLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[22:19] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << AXICLK_PB_DIVIDE_BIT_SHIFT)) >> AXICLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + result = 1; + } + } + } + } else { + result = 1; + } + raw_spin_unlock(&syscfg_lock); + /* Convert result expressed in Hz to Mhz units. */ + *cpu_clock /= HZ_IN_MHZ; + if (!result) + { + cpu_clock_speed = *cpu_clock; + } + + /* Unmap memory */ + iounmap(pSCCReg); + + pSCCReg_map_failed: + iounmap(pSysCfgReg); + + pSysCfgReg_map_failed: + + return result; + } +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.h new file mode 100644 index 0000000000000000000000000000000000000000..f607d1800a72ccebf372fa01079fe50e0aa57d62 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.h @@ -0,0 +1,28 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_CPU_VEXPRESS_H_ +#define _KBASE_CPU_VEXPRESS_H_ + +/** + * Versatile Express implementation of @ref kbase_cpuprops_clock_speed_function. + */ +int kbase_get_vexpress_cpu_clock_speed(u32 *cpu_clock); + +#endif /* _KBASE_CPU_VEXPRESS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..d9bfabc28b6bcb9bbded96b4441610a8f8ce9592 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild @@ -0,0 +1,16 @@ +# +# (C) COPYRIGHT 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +obj-y += mali_kbase_config_vexpress.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..81259485ee00b3c7662d976c06472612a14bba0f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 5000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 5000 diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..0ec2821d256f0920328a4d318789534a26c803d7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c @@ -0,0 +1,279 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include + +/* Versatile Express (VE) configuration defaults shared between config_attributes[] + * and config_attributes_hw_issue_8408[]. Settings are not shared for + * JS_HARD_STOP_TICKS_SS and JS_RESET_TICKS_SS. + */ +#define KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG 3000000000u /* 3s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG 10 /* 30s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG 5 /* 15s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG 20 /* 60s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG 120 /* 360s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG 10 /* 30s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG 6000 /* 18000s */ +#define KBASE_VE_JS_RESET_TICKS_SS_DEBUG 30 /* 180s */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG 180 /* 540s */ +#define KBASE_VE_JS_RESET_TICKS_CL_DEBUG 30 /* 180s */ +#define KBASE_VE_JS_RESET_TICKS_NSS_DEBUG 6010 /* 18030s*/ + +#define KBASE_VE_JS_SCHEDULING_TICK_NS 3000000000u /* 3s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS 10 /* 30s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL 5 /* 15s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS 20 /* 60s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401 120 /* 360s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL 10 /* 30s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS 6000 /* 18000s */ +#define KBASE_VE_JS_RESET_TICKS_SS 30 /* 180s */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401 180 /* 540s */ +#define KBASE_VE_JS_RESET_TICKS_CL 30 /* 180s */ +#define KBASE_VE_JS_RESET_TICKS_NSS 6010 /* 18030s*/ + +#define KBASE_VE_JS_RESET_TIMEOUT_MS 3000 /* 3s before cancelling stuck jobs */ +#define KBASE_VE_JS_CTX_TIMESLICE_NS 1000000 /* 1ms - an agressive timeslice for testing purposes (causes lots of scheduling out for >4 ctxs) */ +#define KBASE_VE_POWER_MANAGEMENT_CALLBACKS ((uintptr_t)&pm_callbacks) + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0x2f010000, + .end = 0x2f010000 + (4096 * 4) - 1} +}; +#endif + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +/* Please keep table config_attributes in sync with config_attributes_hw_issue_8408 */ +static struct kbase_attribute config_attributes[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +/* as config_attributes array above except with different settings for + * JS_HARD_STOP_TICKS_SS, JS_RESET_TICKS_SS that + * are needed for BASE_HW_ISSUE_8408. + */ +struct kbase_attribute config_attributes_hw_issue_8408[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +static struct kbase_platform_config versatile_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..0cb41ce8952d462a7f9ee0842368ba76837d218c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +obj-y += mali_kbase_config_vexpress.o +obj-y += mali_kbase_cpu_vexpress.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..ad6bfb2d59a8f44eef823ced6414d35cf758b27f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 10000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 10000 diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..f1921c02bb8c583f7a94d5443308d1b94f0c2519 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c @@ -0,0 +1,292 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +/* Versatile Express (VE) configuration defaults shared between config_attributes[] + * and config_attributes_hw_issue_8408[]. Settings are not shared for + * JS_HARD_STOP_TICKS_SS and JS_RESET_TICKS_SS. + */ +#define KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG 15000000u /* 15ms, an agressive tick for testing purposes. This will reduce performance significantly */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG 1 /* between 15ms and 30ms before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG 1 /* between 15ms and 30ms before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG 333 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG 2000 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG 166 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG 100000 /* 1500s (25mins) before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS_DEBUG 500 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG 3000 /* 7.5s before resetting GPU - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL_DEBUG 500 /* 45s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS_DEBUG 100166 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_SCHEDULING_TICK_NS 1250000000u /* 1.25s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS 2 /* 2.5s before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL 1 /* 1.25s before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS 4 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401 24 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL 2 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS 1200 /* 1500s before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS 6 /* 7.5s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401 36 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL 3 /* 3.75s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS 1201 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_RESET_TIMEOUT_MS 3000 /* 3s before cancelling stuck jobs */ +#define KBASE_VE_JS_CTX_TIMESLICE_NS 1000000 /* 1ms - an agressive timeslice for testing purposes (causes lots of scheduling out for >4 ctxs) */ +#define KBASE_VE_POWER_MANAGEMENT_CALLBACKS ((uintptr_t)&pm_callbacks) +#define KBASE_VE_CPU_SPEED_FUNC ((uintptr_t)&kbase_get_vexpress_cpu_clock_speed) + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 75, + .mmu_irq_number = 76, + .gpu_irq_number = 77, + .io_memory_region = { + .start = 0x2F000000, + .end = 0x2F000000 + (4096 * 4) - 1} +}; +#endif + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +/* Please keep table config_attributes in sync with config_attributes_hw_issue_8408 */ +static struct kbase_attribute config_attributes[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +/* as config_attributes array above except with different settings for + * JS_HARD_STOP_TICKS_SS, JS_RESET_TICKS_SS that + * are needed for BASE_HW_ISSUE_8408. + */ +struct kbase_attribute config_attributes_hw_issue_8408[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +static struct kbase_platform_config versatile_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..1577f8cef7877e638193d54e4a7eb5361b0d77f6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c @@ -0,0 +1,71 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HZ_IN_MHZ (1000000) + +#define CORETILE_EXPRESS_A9X4_SCC_START (0x100E2000) +#define MOTHERBOARD_SYS_CFG_START (0x10000000) +#define SYS_CFGDATA_OFFSET (0x000000A0) +#define SYS_CFGCTRL_OFFSET (0x000000A4) +#define SYS_CFGSTAT_OFFSET (0x000000A8) + +#define SYS_CFGCTRL_START_BIT_VALUE (1 << 31) +#define READ_REG_BIT_VALUE (0 << 30) +#define DCC_DEFAULT_BIT_VALUE (0 << 26) +#define SYS_CFG_OSC_FUNC_BIT_VALUE (1 << 20) +#define SITE_DEFAULT_BIT_VALUE (1 << 16) +#define BOARD_STACK_POS_DEFAULT_BIT_VALUE (0 << 12) +#define DEVICE_DEFAULT_BIT_VALUE (2 << 0) +#define SYS_CFG_COMPLETE_BIT_VALUE (1 << 0) +#define SYS_CFG_ERROR_BIT_VALUE (1 << 1) + +#define FEED_REG_BIT_MASK (0x0F) +#define FCLK_PA_DIVIDE_BIT_SHIFT (0x03) +#define FCLK_PB_DIVIDE_BIT_SHIFT (0x07) +#define FCLK_PC_DIVIDE_BIT_SHIFT (0x0B) +#define AXICLK_PA_DIVIDE_BIT_SHIFT (0x0F) +#define AXICLK_PB_DIVIDE_BIT_SHIFT (0x13) + +#define IS_SINGLE_BIT_SET(val, pos) (val&(1< +#include +#include +#include + +#include "mali_kbase_cpu_vexpress.h" + +/* Versatile Express (VE) configuration defaults shared between config_attributes[] + * and config_attributes_hw_issue_8408[]. Settings are not shared for + * JS_HARD_STOP_TICKS_SS and JS_RESET_TICKS_SS. + */ +#define KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG 15000000u /* 15ms, an agressive tick for testing purposes. This will reduce performance significantly */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG 1 /* between 15ms and 30ms before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG 1 /* between 15ms and 30ms before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG 333 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG 2000 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG 166 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG 100000 /* 1500s (25mins) before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS_DEBUG 500 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG 3000 /* 7.5s before resetting GPU - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL_DEBUG 500 /* 45s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS_DEBUG 100166 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_SCHEDULING_TICK_NS 1250000000u /* 1.25s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS 2 /* 2.5s before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL 1 /* 1.25s before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS 4 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401 24 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL 2 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS 1200 /* 1500s before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS 6 /* 7.5s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401 36 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL 3 /* 3.75s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS 1201 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_RESET_TIMEOUT_MS 3000 /* 3s before cancelling stuck jobs */ +#define KBASE_VE_JS_CTX_TIMESLICE_NS 1000000 /* 1ms - an agressive timeslice for testing purposes (causes lots of scheduling out for >4 ctxs) */ +#define KBASE_VE_POWER_MANAGEMENT_CALLBACKS ((uintptr_t)&pm_callbacks) +#define KBASE_VE_CPU_SPEED_FUNC ((uintptr_t)&kbase_get_vexpress_cpu_clock_speed) + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0xFC010000, + .end = 0xFC010000 + (4096 * 4) - 1 + } + +}; +#endif /* CONFIG_OF */ + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +/* Please keep table config_attributes in sync with config_attributes_hw_issue_8408 */ +static struct kbase_attribute config_attributes[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +/* as config_attributes array above except with different settings for + * JS_HARD_STOP_TICKS_SS, JS_RESET_TICKS_SS that + * are needed for BASE_HW_ISSUE_8408. + */ +struct kbase_attribute config_attributes_hw_issue_8408[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +static struct kbase_platform_config virtex7_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &virtex7_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..f0036a34545374744b2afd8e5b376a6adc91fe42 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.c @@ -0,0 +1,178 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HZ_IN_MHZ (1000000) + +#define CORETILE_EXPRESS_A9X4_SCC_START (0x100E2000) +#define MOTHERBOARD_SYS_CFG_START (0x10000000) +#define SYS_CFGDATA_OFFSET (0x000000A0) +#define SYS_CFGCTRL_OFFSET (0x000000A4) +#define SYS_CFGSTAT_OFFSET (0x000000A8) + +#define SYS_CFGCTRL_START_BIT_VALUE (1 << 31) +#define READ_REG_BIT_VALUE (0 << 30) +#define DCC_DEFAULT_BIT_VALUE (0 << 26) +#define SYS_CFG_OSC_FUNC_BIT_VALUE (1 << 20) +#define SITE_DEFAULT_BIT_VALUE (1 << 16) +#define BOARD_STACK_POS_DEFAULT_BIT_VALUE (0 << 12) +#define DEVICE_DEFAULT_BIT_VALUE (2 << 0) +#define SYS_CFG_COMPLETE_BIT_VALUE (1 << 0) +#define SYS_CFG_ERROR_BIT_VALUE (1 << 1) + +#define FEED_REG_BIT_MASK (0x0F) +#define FCLK_PA_DIVIDE_BIT_SHIFT (0x03) +#define FCLK_PB_DIVIDE_BIT_SHIFT (0x07) +#define FCLK_PC_DIVIDE_BIT_SHIFT (0x0B) +#define AXICLK_PA_DIVIDE_BIT_SHIFT (0x0F) +#define AXICLK_PB_DIVIDE_BIT_SHIFT (0x13) + +#define IS_SINGLE_BIT_SET(val, pos) (val&(1<> FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[10:7] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PB_DIVIDE_BIT_SHIFT)) >> FCLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + if (IS_SINGLE_BIT_SET(reg_val, 1)) { /*CFGRW0[1] - CLKOC */ + /* CFGRW0[6:3] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PA_DIVIDE_BIT_SHIFT)) >> FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[14:11] */ + pc_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PC_DIVIDE_BIT_SHIFT)) >> FCLK_PC_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pc_divide + 1); + } else if (IS_SINGLE_BIT_SET(reg_val, 2)) { /*CFGRW0[2] - FACLK */ + /* CFGRW0[18:15] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << AXICLK_PA_DIVIDE_BIT_SHIFT)) >> AXICLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[22:19] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << AXICLK_PB_DIVIDE_BIT_SHIFT)) >> AXICLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + result = 1; + } + } + } + } else { + result = 1; + } + raw_spin_unlock(&syscfg_lock); + /* Convert result expressed in Hz to Mhz units. */ + *cpu_clock /= HZ_IN_MHZ; + if (!result) + { + cpu_clock_speed = *cpu_clock; + } + + /* Unmap memory */ + iounmap(pSCCReg); + + pSCCReg_map_failed: + iounmap(pSysCfgReg); + + pSysCfgReg_map_failed: + + return result; + } +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.h new file mode 100644 index 0000000000000000000000000000000000000000..3f6c68ece3928a718a22674be5a14399be9c2771 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_CPU_VEXPRESS_H_ +#define _KBASE_CPU_VEXPRESS_H_ + +/** + * Versatile Express implementation of @ref kbase_cpuprops_clock_speed_function. + */ +int kbase_get_vexpress_cpu_clock_speed(u32 *cpu_clock); + +#endif /* _KBASE_CPU_VEXPRESS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform_dummy/mali_ukk_os.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform_dummy/mali_ukk_os.h new file mode 100644 index 0000000000000000000000000000000000000000..daaa8c0198a50c04b1fac6f4875bb701abeb830a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/platform_dummy/mali_ukk_os.h @@ -0,0 +1,54 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_ukk_os.h + * Types and definitions that are common for Linux OSs for the kernel side of the + * User-Kernel interface. + */ + +#ifndef _UKK_OS_H_ /* Linux version */ +#define _UKK_OS_H_ + +#include + +/** + * @addtogroup uk_api User-Kernel Interface API + * @{ + */ + +/** + * @addtogroup uk_api_kernel UKK (Kernel side) + * @{ + */ + +/** + * Internal OS specific data structure associated with each UKK session. Part + * of a ukk_session object. + */ +typedef struct ukkp_session +{ + int dummy; /**< No internal OS specific data at this time */ +} ukkp_session; + +/** @} end group uk_api_kernel */ + +/** @} end group uk_api */ + +#endif /* _UKK_OS_H__ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..230ce4b7a23403ed13f7764d0de3b2e90a0d2c62 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/sconscript @@ -0,0 +1,114 @@ +# +# (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +import re +import sys +Import('env') + +if Glob('tests/sconscript'): + SConscript( 'tests/sconscript' ) + +mock_test = 0 + +if env['v'] != '1': + env['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +# Fake platform is a transient solution for GPL drivers running in kernel that does not provide configuration via platform data. +# For such kernels fake_platform_device should be set to 1. For kernels providing platform data fake_platform_device should be set to 0. +fake_platform_device = 1 + +# Source files required for kbase. +kbase_src = [Glob('#kernel/drivers/gpu/arm/midgard/*.c'), + Glob('#kernel/drivers/gpu/arm/midgard/*.c'), + Glob('#kernel/drivers/gpu/arm/midgard/platform/%s/*.c' % (env['platform_config'])), + Glob('#kernel/drivers/gpu/arm/midgard/*.h'), + Glob('#kernel/drivers/gpu/arm/midgard/*.h'), + ] + +kbase_src += [Glob('#kernel/drivers/gpu/arm/midgard/internal/*/*.c')] + +if Glob('#kernel/drivers/gpu/arm/midgard/tests/internal/src/mock') and env['unit'] == '1': + kbase_src += [Glob('#kernel/drivers/gpu/arm/midgard/tests/internal/src/mock/*.c')] + mock_test = 1 + +# we need platform config for GPL version using fake platform +if fake_platform_device==1: + # Check if we are compiling for PBX + linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' + search_term = '^[\ ]*CONFIG_MACH_REALVIEW_PBX[\ ]*=[\ ]*y' + REALVIEW_PBX = 0 + for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + REALVIEW_PBX = 1 + break + if REALVIEW_PBX == 1 and (env['platform_config'] == 'vexpress' or env['platform_config'] == 'vexpress_virtex7_40mhz' or env['platform_config'] == 'vexpress_6xvirtex7_10mhz'): + sys.stderr.write("WARNING: Building for a PBX kernel but with platform_config=vexpress*\n") + # if the file platform config file is in the tpip directory then use that, otherwise use the default config directory + if Glob('#kernel/drivers/gpu/arm/midgard/config/tpip/*%s.c' % (env['platform_config'])): + kbase_src += Glob('#kernel/drivers/gpu/arm/midgard/config/tpip/*%s.c' % (env['platform_config'])) + else: + kbase_src += Glob('#kernel/drivers/gpu/arm/midgard/config/*%s.c' % (env['platform_config'])) + +# Note: cleaning via the Linux kernel build system does not yet work +if env.GetOption('clean') : + makeAction=Action("cd ${SOURCE.dir} && make clean", '$MAKECOMSTR') + cmd = env.Command(['$STATIC_LIB_PATH/mali_kbase.ko', '$STATIC_LIB_PATH/mali_platform_fake.ko'], kbase_src, [makeAction]) +else: + if env['os'] == 'android': + env['android'] = 1 + else: + env['android'] = 0 + + if env['unit'] == '1': + env['kernel_test'] = 1 + else: + env['kernel_test'] = 0 + + makeAction=Action("cd ${SOURCE.dir} && make PLATFORM=${platform} MALI_ERROR_INJECT_ON=${error_inject} MALI_ANDROID=${android} MALI_KERNEL_TEST_API=${kernel_test} MALI_UNIT_TEST=${unit} MALI_RELEASE_NAME=\"${mali_release_name}\" MALI_MOCK_TEST=%s MALI_CUSTOMER_RELEASE=${release} MALI_INSTRUMENTATION_LEVEL=${instr} MALI_COVERAGE=${coverage} %s && cp mali_kbase.ko $STATIC_LIB_PATH/mali_kbase.ko" % (mock_test, env.kernel_get_config_defines(fake_platform_device)), '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/mali_kbase.ko', kbase_src, [makeAction]) + +# Add a dependency on kds.ko. +# Only necessary when KDS is not built into the kernel. +# +if env['os'] != 'android': + linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' + search_term = '^[\ ]*CONFIG_KDS[\ ]*=[\ ]*y' + kds_in_kernel = 0 + for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + # KDS in kernel. + kds_in_kernel = 1 + if not kds_in_kernel: + env.Depends('$STATIC_LIB_PATH/mali_kbase.ko', '$STATIC_LIB_PATH/kds.ko') + +# need Module.symvers from ump.ko build +if int(env['ump']) == 1: + env.Depends('$STATIC_LIB_PATH/mali_kbase.ko', '$STATIC_LIB_PATH/ump.ko') + +# Until we fathom out how the invoke the Linux build system to clean, we can use Clean +# to remove generated files. +patterns = ['*.mod.c', '*.o', '*.ko', '*.a', '.*.cmd', 'modules.order', '.tmp_versions', 'Module.symvers'] + +for p in patterns: + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/config/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/tests/internal/src/mock/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/platform/%s/%s' % ((env['platform_config']), p) )) + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/internal/*/%s' % p)) +env.ProgTarget('kbase', cmd) + +env.AppendUnique(BASE=['cutils_list']) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/tests/customer/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/tests/customer/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..508e3724e9baeba5405a1dc517f0fcb4801e4258 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/tests/customer/sconscript @@ -0,0 +1,8 @@ +# This confidential and proprietary software may be used only as +# authorised by a licensing agreement from ARM Limited +# (C) COPYRIGHT 2010-2011, 2013 ARM Limited +# ALL RIGHTS RESERVED +# The entire notice above must be reproduced on all authorised +# copies and copies may only be made to the extent permitted +# by a licensing agreement from ARM Limited. + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/tests/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/tests/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..67040eecd036af46cf0dac2f8c110499140c0096 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/midgard/tests/sconscript @@ -0,0 +1,11 @@ +# This confidential and proprietary software may be used only as +# authorised by a licensing agreement from ARM Limited +# (C) COPYRIGHT 2010-2011, 2013 ARM Limited +# ALL RIGHTS RESERVED +# The entire notice above must be reproduced on all authorised +# copies and copies may only be made to the extent permitted +# by a licensing agreement from ARM Limited. + +SConscript( 'customer/sconscript' ) +if Glob('internal/sconscript'): + SConscript( 'internal/sconscript' ) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..c31eec7cc1708ff68215b16443bc6b598a90da61 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/sconscript @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +SConscript('midgard/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/t6xx/license.txt b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/t6xx/license.txt new file mode 100755 index 0000000000000000000000000000000000000000..77c14bdc45b8c8ae9daa55c279a09296363aab30 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/arm/t6xx/license.txt @@ -0,0 +1,198 @@ +GPLV2 LICENCE AGREEMENT FOR MALI GPUS LINUX KERNEL DEVICE DRIVERS SOURCE CODE + +THE USE OF THE SOFTWARE ACCOMPANYING THIS DOCUMENT IS EXPRESSLY SUBJECT TO THE TERMS OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION AND SET OUT BELOW FOR REFERENCE (?GPL LICENCE?). ARM IS ONLY WILLING TO DISTRIBUTE THE SOFTWARE TO YOU ON CONDITION THAT YOU ACCEPT ALL OF THE TERMS IN THE GPL LICENCE PRIOR TO MODIFYING OR DISTRIBUTING THE SOFTWARE. + + + +Further for the period of three (3) years, ARM hereby offers to make available the source code of any part of the software program that is supplied as object code or in executable form. + + + +GPL Licence + + + +GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + + + +Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + + + +Preamble + + + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + + + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + + + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + + + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + + + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + + + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + + + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + + + +The precise terms and conditions for copying, distribution and modification follow. + + + +GNU GENERAL PUBLIC LICENSE + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + + + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). + +Whether that is true depends on what the Program does. + + + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; + +and give any other recipients of the Program a copy of this License along with the Program. + + + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + + +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + + +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + + +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + + + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + + + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + + + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + + + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + + +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + + +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + + +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + + + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + + + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + + + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + + + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the + +Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + + + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. + +You are not responsible for enforcing compliance by third parties to this License. + + + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + + + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + + + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + + + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + + + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + + + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + + + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + + + +NO WARRANTY + + + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +/end + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..f10d58c70dff212a6b00fbf0e6dbb0e415ec8d51 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Kbuild @@ -0,0 +1,28 @@ +# +# (C) COPYRIGHT ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +pl111_drm-y += pl111_drm_device.o \ + pl111_drm_connector.o \ + pl111_drm_crtc.o \ + pl111_drm_cursor.o \ + pl111_drm_dma_buf.o \ + pl111_drm_encoder.o \ + pl111_drm_fb.o \ + pl111_drm_gem.o \ + pl111_drm_pl111.o \ + pl111_drm_platform.o \ + pl111_drm_suspend.o \ + pl111_drm_vma.o + +obj-$(CONFIG_DRM_PL111) += pl111_drm.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..60b465c56c5137a3f06e2ca057d4fc6f29071bfc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Kconfig @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +config DRM_PL111 + tristate "DRM Support for PL111 CLCD Controller" + depends on DRM + select DRM_KMS_HELPER + select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE + help + Choose this option for DRM support for the PL111 CLCD controller. + If M is selected the module will be called pl111_drm. + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..2869f587266b96eb0793ab0168aa1d24341ffb2c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/Makefile @@ -0,0 +1,32 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: pl111_drm + +pl111_drm: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_DMA_SHARED_BUFFER_USES_KDS=y CONFIG_DRM_PL111=m + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_clcd_ext.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_clcd_ext.h new file mode 100644 index 0000000000000000000000000000000000000000..43f212efac6b8cf40066a731daef41ee8c50bbd3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_clcd_ext.h @@ -0,0 +1,95 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +/** + * pl111_clcd_ext.h + * Extended CLCD register definitions + */ + +#ifndef PL111_CLCD_EXT_H_ +#define PL111_CLCD_EXT_H_ + +/* + * PL111 cursor register definitions not defined in the kernel's clcd header. + * + * TODO MIDEGL-1718: move to include/linux/amba/clcd.h + */ + +#define CLCD_CRSR_IMAGE 0x00000800 +#define CLCD_CRSR_IMAGE_MAX_WORDS 256 +#define CLCD_CRSR_IMAGE_WORDS_PER_LINE 4 +#define CLCD_CRSR_IMAGE_PIXELS_PER_WORD 16 + +#define CLCD_CRSR_LBBP_COLOR_MASK 0x00000003 +#define CLCD_CRSR_LBBP_BACKGROUND 0x0 +#define CLCD_CRSR_LBBP_FOREGROUND 0x1 +#define CLCD_CRSR_LBBP_TRANSPARENT 0x2 +#define CLCD_CRSR_LBBP_INVERSE 0x3 + + +#define CLCD_CRSR_CTRL 0x00000c00 +#define CLCD_CRSR_CONFIG 0x00000c04 +#define CLCD_CRSR_PALETTE_0 0x00000c08 +#define CLCD_CRSR_PALETTE_1 0x00000c0c +#define CLCD_CRSR_XY 0x00000c10 +#define CLCD_CRSR_CLIP 0x00000c14 +#define CLCD_CRSR_IMSC 0x00000c20 +#define CLCD_CRSR_ICR 0x00000c24 +#define CLCD_CRSR_RIS 0x00000c28 +#define CLCD_MIS 0x00000c2c + +#define CRSR_CTRL_CRSR_ON (1 << 0) +#define CRSR_CTRL_CRSR_MAX 3 +#define CRSR_CTRL_CRSR_NUM_SHIFT 4 +#define CRSR_CTRL_CRSR_NUM_MASK \ + (CRSR_CTRL_CRSR_MAX << CRSR_CTRL_CRSR_NUM_SHIFT) +#define CRSR_CTRL_CURSOR_0 0 +#define CRSR_CTRL_CURSOR_1 1 +#define CRSR_CTRL_CURSOR_2 2 +#define CRSR_CTRL_CURSOR_3 3 + +#define CRSR_CONFIG_CRSR_SIZE (1 << 0) +#define CRSR_CONFIG_CRSR_FRAME_SYNC (1 << 1) + +#define CRSR_PALETTE_RED_SHIFT 0 +#define CRSR_PALETTE_GREEN_SHIFT 8 +#define CRSR_PALETTE_BLUE_SHIFT 16 + +#define CRSR_PALETTE_RED_MASK 0x000000ff +#define CRSR_PALETTE_GREEN_MASK 0x0000ff00 +#define CRSR_PALETTE_BLUE_MASK 0x00ff0000 +#define CRSR_PALETTE_MASK (~0xff000000) + +#define CRSR_XY_MASK 0x000003ff +#define CRSR_XY_X_SHIFT 0 +#define CRSR_XY_Y_SHIFT 16 + +#define CRSR_XY_X_MASK CRSR_XY_MASK +#define CRSR_XY_Y_MASK (CRSR_XY_MASK << CRSR_XY_Y_SHIFT) + +#define CRSR_CLIP_MASK 0x3f +#define CRSR_CLIP_X_SHIFT 0 +#define CRSR_CLIP_Y_SHIFT 8 + +#define CRSR_CLIP_X_MASK CRSR_CLIP_MASK +#define CRSR_CLIP_Y_MASK (CRSR_CLIP_MASK << CRSR_CLIP_Y_SHIFT) + +#define CRSR_IMSC_CRSR_IM (1<<0) +#define CRSR_ICR_CRSR_IC (1<<0) +#define CRSR_RIS_CRSR_RIS (1<<0) +#define CRSR_MIS_CRSR_MIS (1<<0) + +#endif /* PL111_CLCD_EXT_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm.h new file mode 100644 index 0000000000000000000000000000000000000000..e151e8c02b117887b7fb88a7acf625d0459dcb5a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm.h @@ -0,0 +1,270 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _PL111_DRM_H_ +#define _PL111_DRM_H_ + +#define DRIVER_AUTHOR "ARM Ltd." +#define DRIVER_NAME "pl111_drm" +#define DRIVER_DESC "DRM module for PL111" +#define DRIVER_LICENCE "GPL" +#define DRIVER_ALIAS "platform:pl111_drm" +#define DRIVER_DATE "20101111" +#define DRIVER_VERSION "0.2" +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 1 + +/* + * Number of flips allowed in flight at any one time. Any more flips requested + * beyond this value will cause the caller to block until earlier flips have + * completed. + * + * For performance reasons, this must be greater than the number of buffers + * used in the rendering pipeline. Note that the rendering pipeline can contain + * different types of buffer, e.g.: + * - 2 final framebuffers + * - >2 geometry buffers for GPU use-cases + * - >2 vertex buffers for GPU use-cases + * + * For example, a system using 5 geometry buffers could have 5 flips in flight, + * and so NR_FLIPS_IN_FLIGHT_THRESHOLD must be 5 or greater. + * + * Whilst there may be more intermediate buffers (such as vertex/geometry) than + * final framebuffers, KDS is used to ensure that GPU rendering waits for the + * next off-screen buffer, so it doesn't overwrite an on-screen buffer and + * produce tearing. + */ + +/* + * Here, we choose a conservative value. A lower value is most likely + * suitable for GPU use-cases. + */ +#define NR_FLIPS_IN_FLIGHT_THRESHOLD 16 + +#define CLCD_IRQ_NEXTBASE_UPDATE (1u<<2) + +struct pl111_drm_flip_resource; + +struct pl111_gem_bo_dma { + dma_addr_t fb_dev_addr; + void *fb_cpu_addr; +}; + +struct pl111_gem_bo_shm { + struct page **pages; + dma_addr_t *dma_addrs; +}; + +struct pl111_gem_bo { + struct drm_gem_object gem_object; + u32 type; + union { + struct pl111_gem_bo_dma dma; + struct pl111_gem_bo_shm shm; + } backing_data; + struct sg_table *sgt; +}; + +extern struct pl111_drm_dev_private priv; + +struct pl111_drm_framebuffer { + struct drm_framebuffer fb; + struct pl111_gem_bo *bo; +}; + +struct pl111_drm_flip_resource { +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* This is the kds set associated to the dma_buf we want to flip */ + struct kds_resource_set *kds_res_set; +#endif + struct drm_framebuffer *fb; + struct drm_crtc *crtc; + struct list_head link; + bool page_flip; + struct drm_pending_vblank_event *event; +}; + +struct pl111_drm_crtc { + struct drm_crtc crtc; + int crtc_index; + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* This protects "old_kds_res_set" and "displaying_fb" */ + spinlock_t current_displaying_lock; + /* + * When a buffer is displayed its associated kds resource + * will be obtained and stored here. Every time a buffer + * flip is completed this old kds set is released and assigned + * the kds set of the new buffer. + */ + struct kds_resource_set *old_kds_res_set; + /* + * Stores which frame buffer is currently being displayed by + * this CRTC or NULL if nothing is being displayed. It is used + * to tell whether we need to obtain a set of kds resources for + * exported buffer objects. + */ + struct drm_framebuffer *displaying_fb; +#endif + struct drm_display_mode *new_mode; + struct drm_display_mode *current_mode; + int last_bpp; + + /* + * This spinlock protects "update_queue", "current_update_res" + * and calls to do_flip_to_res() which updates the CLCD base + * registers. + */ + spinlock_t base_update_lock; + /* + * The resource that caused a base address update. Only one can be + * pending, hence it's != NULL if there's a pending update + */ + struct pl111_drm_flip_resource *current_update_res; + /* Queue of things waiting to update the base address */ + struct list_head update_queue; + + void (*show_framebuffer_cb)(struct pl111_drm_flip_resource *flip_res, + struct drm_framebuffer *fb); +}; + +struct pl111_drm_connector { + struct drm_connector connector; +}; + +struct pl111_drm_encoder { + struct drm_encoder encoder; +}; + +struct pl111_drm_dev_private { + struct pl111_drm_crtc *pl111_crtc; + + struct amba_device *amba_dev; + unsigned long mmio_start; + __u32 mmio_len; + void *regs; + struct clk *clk; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct kds_callback kds_cb; + struct kds_callback kds_obtain_current_cb; +#endif + /* + * Number of flips that were started in show_framebuffer_on_crtc(), + * but haven't completed yet - because we do deferred flipping + */ + atomic_t nr_flips_in_flight; + wait_queue_head_t wait_for_flips; + + /* + * Used to prevent race between pl111_dma_buf_release and + * drm_gem_prime_handle_to_fd + */ + struct mutex export_dma_buf_lock; + + uint32_t number_crtcs; + + /* Cache for flip resources used to avoid kmalloc on each page flip */ + struct kmem_cache *page_flip_slab; +}; + +enum pl111_cursor_size { + CURSOR_32X32, + CURSOR_64X64 +}; + +enum pl111_cursor_sync { + CURSOR_SYNC_NONE, + CURSOR_SYNC_VSYNC +}; + + +/** + * Buffer allocation function which is more flexible than dumb_create(), + * it allows passing driver specific flags to control the kind of buffer + * to be allocated. + */ +int pl111_drm_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +/****** TODO MIDEGL-1718: this should be moved to uapi/include/drm/pl111_drm.h ********/ + +/* + * Parameters for different buffer objects: + * bit [0]: backing storage + * (0 -> SHM) + * (1 -> DMA) + * bit [2:1]: kind of mapping + * (0x0 -> uncached) + * (0x1 -> write combine) + * (0x2 -> cached) + */ +#define PL111_BOT_MASK (0x7) +#define PL111_BOT_SHM (0x0 << 0) +#define PL111_BOT_DMA (0x1 << 0) +#define PL111_BOT_UNCACHED (0x0 << 1) +#define PL111_BOT_WC (0x1 << 1) +#define PL111_BOT_CACHED (0x2 << 1) + +/** + * User-desired buffer creation information structure. + * + * @size: user-desired memory allocation size. + * - this size value would be page-aligned internally. + * @flags: user request for setting memory type or cache attributes as a bit op + * - PL111_BOT_DMA / PL111_BOT_SHM + * - PL111_BOT_UNCACHED / PL111_BOT_WC / PL111_BOT_CACHED + * @handle: returned a handle to created gem object. + * - this handle will be set by gem module of kernel side. + */ +struct drm_pl111_gem_create { + uint32_t height; + uint32_t width; + uint32_t bpp; + uint32_t flags; + /* handle, pitch, size will be returned */ + uint32_t handle; + uint32_t pitch; + uint64_t size; +}; + +#define DRM_PL111_GEM_CREATE 0x00 + +#define DRM_IOCTL_PL111_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_PL111_GEM_CREATE, struct drm_pl111_gem_create) +/****************************************************************************/ + +#define PL111_FB_FROM_FRAMEBUFFER(drm_fb) \ + (container_of(drm_fb, struct pl111_drm_framebuffer, fb)) + +#define PL111_BO_FROM_FRAMEBUFFER(drm_fb) \ + (container_of(drm_fb, struct pl111_drm_framebuffer, fb)->bo) + +#define PL111_BO_FROM_GEM(gem_obj) \ + container_of(gem_obj, struct pl111_gem_bo, gem_object) + +#define to_pl111_crtc(x) container_of(x, struct pl111_drm_crtc, crtc) + +#define PL111_ENCODER_FROM_ENCODER(x) \ + container_of(x, struct pl111_drm_encoder, encoder) + +#define PL111_CONNECTOR_FROM_CONNECTOR(x) \ + container_of(x, struct pl111_drm_connector, connector) + +#include "pl111_drm_funcs.h" + +#endif /* _PL111_DRM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_connector.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_connector.c new file mode 100644 index 0000000000000000000000000000000000000000..5d9cf80de6189126284dcbec953bdc4ed2e5996f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_connector.c @@ -0,0 +1,170 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_connector.c + * Implementation of the connector functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + + +static struct { + int w, h, type; +} pl111_drm_modes[] = { + { 640, 480, DRM_MODE_TYPE_PREFERRED}, + { 800, 600, 0}, + {1024, 768, 0}, + { -1, -1, -1} +}; + +void pl111_connector_destroy(struct drm_connector *connector) +{ + struct pl111_drm_connector *pl111_connector = + PL111_CONNECTOR_FROM_CONNECTOR(connector); + + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(pl111_connector); +} + +enum drm_connector_status pl111_connector_detect(struct drm_connector + *connector, bool force) +{ + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + return connector_status_connected; +} + +void pl111_connector_dpms(struct drm_connector *connector, int mode) +{ + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); +} + +struct drm_encoder * +pl111_connector_helper_best_encoder(struct drm_connector *connector) +{ + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + + if (connector->encoder != NULL) { + return connector->encoder; /* Return attached encoder */ + } else { + /* + * If there is no attached encoder we choose the best candidate + * from the list. + * For PL111 there is only one encoder so we return the first + * one we find. + * Other h/w would require a suitable criterion below. + */ + struct drm_encoder *encoder = NULL; + struct drm_device *dev = connector->dev; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, + head) { + if (1) { /* criterion ? */ + break; + } + } + return encoder; /* return best candidate encoder */ + } +} + +int pl111_connector_helper_get_modes(struct drm_connector *connector) +{ + int i = 0; + int count = 0; + + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + + while (pl111_drm_modes[i].w != -1) { + struct drm_display_mode *mode = + drm_mode_find_dmt(connector->dev, + pl111_drm_modes[i].w, + pl111_drm_modes[i].h, + 60 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + , false +#endif + ); + + if (mode != NULL) { + mode->type |= pl111_drm_modes[i].type; + drm_mode_probed_add(connector, mode); + count++; + } + + i++; + } + + DRM_DEBUG_KMS("found %d modes\n", count); + + return count; +} + +int pl111_connector_helper_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + return MODE_OK; +} + +const struct drm_connector_funcs connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = pl111_connector_destroy, + .detect = pl111_connector_detect, + .dpms = pl111_connector_dpms, +}; + +const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = pl111_connector_helper_get_modes, + .mode_valid = pl111_connector_helper_mode_valid, + .best_encoder = pl111_connector_helper_best_encoder, +}; + +struct pl111_drm_connector *pl111_connector_create(struct drm_device *dev) +{ + struct pl111_drm_connector *pl111_connector; + + pl111_connector = kzalloc(sizeof(struct pl111_drm_connector), + GFP_KERNEL); + + if (pl111_connector == NULL) { + pr_err("Failed to allocated pl111_drm_connector\n"); + return NULL; + } + + drm_connector_init(dev, &pl111_connector->connector, &connector_funcs, + DRM_MODE_CONNECTOR_DVII); + + drm_connector_helper_add(&pl111_connector->connector, + &connector_helper_funcs); + + drm_sysfs_connector_add(&pl111_connector->connector); + + return pl111_connector; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_crtc.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_crtc.c new file mode 100644 index 0000000000000000000000000000000000000000..a06c991dbf23d164cfb6729c9ed9bacd2ea9cc37 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_crtc.c @@ -0,0 +1,421 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_crtc.c + * Implementation of the CRTC functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + +static int pl111_crtc_num; + +void pl111_common_irq(struct pl111_drm_crtc *pl111_crtc) +{ + struct drm_device *dev = pl111_crtc->crtc.dev; + struct pl111_drm_flip_resource *old_flip_res; + struct pl111_gem_bo *bo; + unsigned long irq_flags; + int flips_in_flight; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + unsigned long flags; +#endif + + spin_lock_irqsave(&pl111_crtc->base_update_lock, irq_flags); + + /* + * Cache the flip resource that caused the IRQ since it will be + * dispatched later. Early return if the IRQ isn't associated to + * a base register update. + * + * TODO MIDBASE-2790: disable IRQs when a flip is not pending. + */ + old_flip_res = pl111_crtc->current_update_res; + if (!old_flip_res) { + spin_unlock_irqrestore(&pl111_crtc->base_update_lock, irq_flags); + return; + } + pl111_crtc->current_update_res = NULL; + + /* Prepare the next flip (if any) of the queue as soon as possible. */ + if (!list_empty(&pl111_crtc->update_queue)) { + struct pl111_drm_flip_resource *flip_res; + /* Remove the head of the list */ + flip_res = list_first_entry(&pl111_crtc->update_queue, + struct pl111_drm_flip_resource, link); + list_del(&flip_res->link); + do_flip_to_res(flip_res); + /* + * current_update_res will be set, so guarentees that + * another flip_res coming in gets queued instead of + * handled immediately + */ + } + spin_unlock_irqrestore(&pl111_crtc->base_update_lock, irq_flags); + + /* Finalize properly the flip that caused the IRQ */ + DRM_DEBUG_KMS("DRM Finalizing old_flip_res=%p\n", old_flip_res); + + bo = PL111_BO_FROM_FRAMEBUFFER(old_flip_res->fb); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + release_kds_resource_and_display(old_flip_res); + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, flags); +#endif + /* Release DMA buffer on this flip */ + if (bo->gem_object.export_dma_buf != NULL) + dma_buf_put(bo->gem_object.export_dma_buf); + + drm_handle_vblank(dev, pl111_crtc->crtc_index); + + /* Wake up any processes waiting for page flip event */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + if (old_flip_res->event) { + spin_lock_bh(&dev->event_lock); + drm_send_vblank_event(dev, pl111_crtc->crtc_index, + old_flip_res->event); + spin_unlock_bh(&dev->event_lock); + } +#else + if (old_flip_res->event) { + struct drm_pending_vblank_event *e = old_flip_res->event; + struct timeval now; + unsigned int seq; + + DRM_DEBUG_KMS("%s: wake up page flip event (%p)\n", __func__, + old_flip_res->event); + + spin_lock_bh(&dev->event_lock); + seq = drm_vblank_count_and_time(dev, pl111_crtc->crtc_index, + &now); + e->pipe = pl111_crtc->crtc_index; + e->event.sequence = seq; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + + list_add_tail(&e->base.link, + &e->base.file_priv->event_list); + + wake_up_interruptible(&e->base.file_priv->event_wait); + spin_unlock_bh(&dev->event_lock); + } +#endif + + drm_vblank_put(dev, pl111_crtc->crtc_index); + + /* + * workqueue.c:process_one_work(): + * "It is permissible to free the struct work_struct from + * inside the function that is called from it" + */ + kmem_cache_free(priv.page_flip_slab, old_flip_res); + + flips_in_flight = atomic_dec_return(&priv.nr_flips_in_flight); + if (flips_in_flight == 0 || + flips_in_flight == (NR_FLIPS_IN_FLIGHT_THRESHOLD - 1)) + wake_up(&priv.wait_for_flips); + + DRM_DEBUG_KMS("DRM release flip_res=%p\n", old_flip_res); +} + +void show_framebuffer_on_crtc_cb(void *cb1, void *cb2) +{ + struct pl111_drm_flip_resource *flip_res = cb1; + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(flip_res->crtc); + + pl111_crtc->show_framebuffer_cb(cb1, cb2); +} + +int show_framebuffer_on_crtc(struct drm_crtc *crtc, + struct drm_framebuffer *fb, bool page_flip, + struct drm_pending_vblank_event *event) +{ + struct pl111_gem_bo *bo; + struct pl111_drm_flip_resource *flip_res; + int flips_in_flight; + int old_flips_in_flight; + + crtc->fb = fb; + + bo = PL111_BO_FROM_FRAMEBUFFER(fb); + if (bo == NULL) { + DRM_DEBUG_KMS("Failed to get pl111_gem_bo object\n"); + return -EINVAL; + } + + /* If this is a full modeset, wait for all outstanding flips to complete + * before continuing. This avoids unnecessary complication from being + * able to queue up multiple modesets and queues of mixed modesets and + * page flips. + * + * Modesets should be uncommon and will not be performant anyway, so + * making them synchronous should have negligible performance impact. + */ + if (!page_flip) { + int ret = wait_event_killable(priv.wait_for_flips, + atomic_read(&priv.nr_flips_in_flight) == 0); + if (ret) + return ret; + } + + /* + * There can be more 'early display' flips in flight than there are + * buffers, and there is (currently) no explicit bound on the number of + * flips. Hence, we need a new allocation for each one. + * + * Note: this could be optimized down if we knew a bound on the flips, + * since an application can only have so many buffers in flight to be + * useful/not hog all the memory + */ + flip_res = kmem_cache_alloc(priv.page_flip_slab, GFP_KERNEL); + if (flip_res == NULL) { + pr_err("kmem_cache_alloc failed to alloc - flip ignored\n"); + return -ENOMEM; + } + + /* + * increment flips in flight, whilst blocking when we reach + * NR_FLIPS_IN_FLIGHT_THRESHOLD + */ + do { + /* + * Note: use of assign-and-then-compare in the condition to set + * flips_in_flight + */ + int ret = wait_event_killable(priv.wait_for_flips, + (flips_in_flight = + atomic_read(&priv.nr_flips_in_flight)) + < NR_FLIPS_IN_FLIGHT_THRESHOLD); + if (ret != 0) { + kmem_cache_free(priv.page_flip_slab, flip_res); + return ret; + } + + old_flips_in_flight = atomic_cmpxchg(&priv.nr_flips_in_flight, + flips_in_flight, flips_in_flight + 1); + } while (old_flips_in_flight != flips_in_flight); + + flip_res->fb = fb; + flip_res->crtc = crtc; + flip_res->page_flip = page_flip; + flip_res->event = event; + INIT_LIST_HEAD(&flip_res->link); + DRM_DEBUG_KMS("DRM alloc flip_res=%p\n", flip_res); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + if (bo->gem_object.export_dma_buf != NULL) { + struct dma_buf *buf = bo->gem_object.export_dma_buf; + unsigned long shared[1] = { 0 }; + struct kds_resource *resource_list[1] = { + get_dma_buf_kds_resource(buf) }; + int err; + + get_dma_buf(buf); + DRM_DEBUG_KMS("Got dma_buf %p\n", buf); + + /* Wait for the KDS resource associated with this buffer */ + err = kds_async_waitall(&flip_res->kds_res_set, + &priv.kds_cb, flip_res, fb, 1, shared, + resource_list); + BUG_ON(err); + } else { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + + DRM_DEBUG_KMS("No dma_buf for this flip\n"); + + /* No dma-buf attached so just call the callback directly */ + flip_res->kds_res_set = NULL; + pl111_crtc->show_framebuffer_cb(flip_res, fb); + } +#else + if (bo->gem_object.export_dma_buf != NULL) { + struct dma_buf *buf = bo->gem_object.export_dma_buf; + + get_dma_buf(buf); + DRM_DEBUG_KMS("Got dma_buf %p\n", buf); + } else { + DRM_DEBUG_KMS("No dma_buf for this flip\n"); + } + + /* No dma-buf attached to this so just call the callback directly */ + { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + pl111_crtc->show_framebuffer_cb(flip_res, fb); + } +#endif + + /* For the same reasons as the wait at the start of this function, + * wait for the modeset to complete before continuing. + */ + if (!page_flip) { + int ret = wait_event_killable(priv.wait_for_flips, + flips_in_flight == 0); + if (ret) + return ret; + } + + return 0; +} + +int pl111_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + DRM_DEBUG_KMS("%s: crtc=%p, fb=%p, event=%p\n", + __func__, crtc, fb, event); + return show_framebuffer_on_crtc(crtc, fb, true, event); +} + +int pl111_crtc_helper_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb) +{ + int ret; + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + struct drm_display_mode *duplicated_mode; + + DRM_DEBUG_KMS("DRM crtc_helper_mode_set, x=%d y=%d bpp=%d\n", + adjusted_mode->hdisplay, adjusted_mode->vdisplay, + crtc->fb->bits_per_pixel); + + duplicated_mode = drm_mode_duplicate(crtc->dev, adjusted_mode); + if (!duplicated_mode) + return -ENOMEM; + + pl111_crtc->new_mode = duplicated_mode; + ret = show_framebuffer_on_crtc(crtc, crtc->fb, false, NULL); + if (ret != 0) { + pl111_crtc->new_mode = pl111_crtc->current_mode; + drm_mode_destroy(crtc->dev, duplicated_mode); + } + + return ret; +} + +void pl111_crtc_helper_prepare(struct drm_crtc *crtc) +{ + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); +} + +void pl111_crtc_helper_commit(struct drm_crtc *crtc) +{ + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); +} + +bool pl111_crtc_helper_mode_fixup(struct drm_crtc *crtc, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + const struct drm_display_mode *mode, +#else + struct drm_display_mode *mode, +#endif + struct drm_display_mode *adjusted_mode) +{ + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); + +#ifdef CONFIG_ARCH_VEXPRESS + /* + * 1024x768 with more than 16 bits per pixel may not work + * correctly on Versatile Express due to bandwidth issues + */ + if (mode->hdisplay == 1024 && mode->vdisplay == 768 && + crtc->fb->bits_per_pixel > 16) { + DRM_INFO("*WARNING* 1024x768 at > 16 bpp may suffer corruption\n"); + } +#endif + + return true; +} + +void pl111_crtc_helper_disable(struct drm_crtc *crtc) +{ + int ret; + + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); + + /* don't disable crtc until no flips in flight as irq will be disabled */ + ret = wait_event_killable(priv.wait_for_flips, atomic_read(&priv.nr_flips_in_flight) == 0); + if(ret) { + pr_err("pl111_crtc_helper_disable failed\n"); + return; + } + clcd_disable(crtc); +} + +void pl111_crtc_destroy(struct drm_crtc *crtc) +{ + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); + + drm_crtc_cleanup(crtc); + kfree(pl111_crtc); +} + +const struct drm_crtc_funcs crtc_funcs = { + .cursor_set = pl111_crtc_cursor_set, + .cursor_move = pl111_crtc_cursor_move, + .set_config = drm_crtc_helper_set_config, + .page_flip = pl111_crtc_page_flip, + .destroy = pl111_crtc_destroy +}; + +const struct drm_crtc_helper_funcs crtc_helper_funcs = { + .mode_set = pl111_crtc_helper_mode_set, + .prepare = pl111_crtc_helper_prepare, + .commit = pl111_crtc_helper_commit, + .mode_fixup = pl111_crtc_helper_mode_fixup, + .disable = pl111_crtc_helper_disable, +}; + +struct pl111_drm_crtc *pl111_crtc_create(struct drm_device *dev) +{ + struct pl111_drm_crtc *pl111_crtc; + + pl111_crtc = kzalloc(sizeof(struct pl111_drm_crtc), GFP_KERNEL); + if (pl111_crtc == NULL) { + pr_err("Failed to allocated pl111_drm_crtc\n"); + return NULL; + } + + drm_crtc_init(dev, &pl111_crtc->crtc, &crtc_funcs); + drm_crtc_helper_add(&pl111_crtc->crtc, &crtc_helper_funcs); + + pl111_crtc->crtc_index = pl111_crtc_num; + pl111_crtc_num++; + pl111_crtc->crtc.enabled = 0; + pl111_crtc->last_bpp = 0; + pl111_crtc->current_update_res = NULL; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + pl111_crtc->displaying_fb = NULL; + pl111_crtc->old_kds_res_set = NULL; + spin_lock_init(&pl111_crtc->current_displaying_lock); +#endif + pl111_crtc->show_framebuffer_cb = show_framebuffer_on_crtc_cb_internal; + INIT_LIST_HEAD(&pl111_crtc->update_queue); + spin_lock_init(&pl111_crtc->base_update_lock); + + return pl111_crtc; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_cursor.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_cursor.c new file mode 100644 index 0000000000000000000000000000000000000000..87f1007d16dd5bc48f4ad510d657501b4a122523 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_cursor.c @@ -0,0 +1,331 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_cursor.c + * Implementation of cursor functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "pl111_clcd_ext.h" +#include "pl111_drm.h" + +#define PL111_MAX_CURSOR_WIDTH (64) +#define PL111_MAX_CURSOR_HEIGHT (64) + +#define ARGB_2_LBBP_BINARY_THRESHOLD (1 << 7) +#define ARGB_ALPHA_SHIFT 24 +#define ARGB_ALPHA_MASK (0xff << ARGB_ALPHA_SHIFT) +#define ARGB_RED_SHIFT 16 +#define ARGB_RED_MASK (0xff << ARGB_RED_SHIFT) +#define ARGB_GREEN_SHIFT 8 +#define ARGB_GREEN_MASK (0xff << ARGB_GREEN_SHIFT) +#define ARGB_BLUE_SHIFT 0 +#define ARGB_BLUE_MASK (0xff << ARGB_BLUE_SHIFT) + + +void pl111_set_cursor_size(enum pl111_cursor_size size) +{ + u32 reg_data = readl(priv.regs + CLCD_CRSR_CONFIG); + + if (size == CURSOR_64X64) + reg_data |= CRSR_CONFIG_CRSR_SIZE; + else + reg_data &= ~CRSR_CONFIG_CRSR_SIZE; + + writel(reg_data, priv.regs + CLCD_CRSR_CONFIG); +} + +void pl111_set_cursor_sync(enum pl111_cursor_sync sync) +{ + u32 reg_data = readl(priv.regs + CLCD_CRSR_CONFIG); + + if (sync == CURSOR_SYNC_VSYNC) + reg_data |= CRSR_CONFIG_CRSR_FRAME_SYNC; + else + reg_data &= ~CRSR_CONFIG_CRSR_FRAME_SYNC; + + writel(reg_data, priv.regs + CLCD_CRSR_CONFIG); +} + +void pl111_set_cursor(u32 cursor) +{ + u32 reg_data = readl(priv.regs + CLCD_CRSR_CTRL); + + reg_data &= ~(CRSR_CTRL_CRSR_MAX << CRSR_CTRL_CRSR_NUM_SHIFT); + reg_data |= (cursor & CRSR_CTRL_CRSR_MAX) << CRSR_CTRL_CRSR_NUM_SHIFT; + + writel(reg_data, priv.regs + CLCD_CRSR_CTRL); +} + +void pl111_set_cursor_enable(bool enable) +{ + u32 reg_data = readl(priv.regs + CLCD_CRSR_CTRL); + + if (enable) + reg_data |= CRSR_CTRL_CRSR_ON; + else + reg_data &= ~CRSR_CTRL_CRSR_ON; + + writel(reg_data, priv.regs + CLCD_CRSR_CTRL); +} + +void pl111_set_cursor_position(u32 x, u32 y) +{ + u32 reg_data = (x & CRSR_XY_MASK) | + ((y & CRSR_XY_MASK) << CRSR_XY_Y_SHIFT); + + writel(reg_data, priv.regs + CLCD_CRSR_XY); +} + +void pl111_set_cursor_clipping(u32 x, u32 y) +{ + u32 reg_data; + + /* + * Do not allow setting clipping values larger than + * the cursor size since the cursor is already fully hidden + * when x,y = PL111_MAX_CURSOR_WIDTH. + */ + if (x > PL111_MAX_CURSOR_WIDTH) + x = PL111_MAX_CURSOR_WIDTH; + if (y > PL111_MAX_CURSOR_WIDTH) + y = PL111_MAX_CURSOR_WIDTH; + + reg_data = (x & CRSR_CLIP_MASK) | + ((y & CRSR_CLIP_MASK) << CRSR_CLIP_Y_SHIFT); + + writel(reg_data, priv.regs + CLCD_CRSR_CLIP); +} + +void pl111_set_cursor_palette(u32 color0, u32 color1) +{ + writel(color0 & CRSR_PALETTE_MASK, priv.regs + CLCD_CRSR_PALETTE_0); + writel(color1 & CRSR_PALETTE_MASK, priv.regs + CLCD_CRSR_PALETTE_1); +} + +void pl111_cursor_enable(void) +{ + pl111_set_cursor_sync(CURSOR_SYNC_VSYNC); + pl111_set_cursor_size(CURSOR_64X64); + pl111_set_cursor_palette(0x0, 0x00ffffff); + pl111_set_cursor_enable(true); +} + +void pl111_cursor_disable(void) +{ + pl111_set_cursor_enable(false); +} + +/* shift required to locate pixel into the correct position in + * a cursor LBBP word, indexed by x mod 16. + */ +static const unsigned char +x_mod_16_to_value_shift[CLCD_CRSR_IMAGE_PIXELS_PER_WORD] = { + 6, 4, 2, 0, 14, 12, 10, 8, 22, 20, 18, 16, 30, 28, 26, 24 +}; + +/* Pack the pixel value into its correct position in the buffer as specified + * for LBBP */ +static inline void +set_lbbp_pixel(uint32_t *buffer, unsigned int x, unsigned int y, + uint32_t value) +{ + u32 *cursor_ram = priv.regs + CLCD_CRSR_IMAGE; + uint32_t shift; + uint32_t data; + + shift = x_mod_16_to_value_shift[x % CLCD_CRSR_IMAGE_PIXELS_PER_WORD]; + + /* Get the word containing this pixel */ + cursor_ram = cursor_ram + (x >> CLCD_CRSR_IMAGE_WORDS_PER_LINE) + (y << 2); + + /* Update pixel in cursor RAM */ + data = readl(cursor_ram); + data &= ~(CLCD_CRSR_LBBP_COLOR_MASK << shift); + data |= value << shift; + writel(data, cursor_ram); +} + +static u32 pl111_argb_to_lbbp(u32 argb_pix) +{ + u32 lbbp_pix = CLCD_CRSR_LBBP_TRANSPARENT; + u32 alpha = (argb_pix & ARGB_ALPHA_MASK) >> ARGB_ALPHA_SHIFT; + u32 red = (argb_pix & ARGB_RED_MASK) >> ARGB_RED_SHIFT; + u32 green = (argb_pix & ARGB_GREEN_MASK) >> ARGB_GREEN_SHIFT; + u32 blue = (argb_pix & ARGB_BLUE_MASK) >> ARGB_BLUE_SHIFT; + + /* + * Converting from 8 pixel transparency to binary transparency + * it's the best we can achieve. + */ + if (alpha & ARGB_2_LBBP_BINARY_THRESHOLD) { + u32 gray, max, min; + + /* + * Convert to gray using the lightness method: + * gray = [max(R,G,B) + min(R,G,B)]/2 + */ + min = min(red, green); + min = min(min, blue); + max = max(red, green); + max = max(max, blue); + gray = (min + max) >> 1; /* divide by 2 */ + /* Apply binary threshold to the gray value calculated */ + if (gray & ARGB_2_LBBP_BINARY_THRESHOLD) + lbbp_pix = CLCD_CRSR_LBBP_FOREGROUND; + else + lbbp_pix = CLCD_CRSR_LBBP_BACKGROUND; + } + + return lbbp_pix; +} + +/* + * The PL111 hardware cursor supports only LBBP which is a 2bpp format but + * the cursor format from userspace is ARGB8888 so we need to convert + * to LBBP here. + */ +static void pl111_set_cursor_image(u32 *data) +{ +#ifdef ARGB_LBBP_CONVERSION_DEBUG + /* Add 1 on width to insert trailing NULL */ + char string_cursor[PL111_MAX_CURSOR_WIDTH + 1]; +#endif /* ARGB_LBBP_CONVERSION_DEBUG */ + unsigned int x; + unsigned int y; + + for (y = 0; y < PL111_MAX_CURSOR_HEIGHT; y++) { + for (x = 0; x < PL111_MAX_CURSOR_WIDTH; x++) { + u32 value = pl111_argb_to_lbbp(*data); + +#ifdef ARGB_LBBP_CONVERSION_DEBUG + if (value == CLCD_CRSR_LBBP_TRANSPARENT) + string_cursor[x] = 'T'; + else if (value == CLCD_CRSR_LBBP_FOREGROUND) + string_cursor[x] = 'F'; + else if (value == CLCD_CRSR_LBBP_INVERSE) + string_cursor[x] = 'I'; + else + string_cursor[x] = 'B'; + +#endif /* ARGB_LBBP_CONVERSION_DEBUG */ + set_lbbp_pixel(data, x, y, value); + ++data; + } +#ifdef ARGB_LBBP_CONVERSION_DEBUG + string_cursor[PL111_MAX_CURSOR_WIDTH] = '\0'; + DRM_INFO("%s\n", string_cursor); +#endif /* ARGB_LBBP_CONVERSION_DEBUG */ + } +} + +int pl111_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height) +{ + struct drm_gem_object *obj; + struct pl111_gem_bo *bo; + + DRM_DEBUG_KMS("handle = %u, width = %u, height = %u\n", + handle, width, height); + + if (!handle) { + pl111_cursor_disable(); + return 0; + } + + if ((width != PL111_MAX_CURSOR_WIDTH) || + (height != PL111_MAX_CURSOR_HEIGHT)) + return -EINVAL; + + obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); + if (!obj) { + DRM_ERROR("Cannot find cursor object for handle = %d\n", + handle); + return -ENOENT; + } + + /* + * We expect a PL111_MAX_CURSOR_WIDTH x PL111_MAX_CURSOR_HEIGHT + * ARGB888 buffer object in the input. + * + */ + if (obj->size < (PL111_MAX_CURSOR_WIDTH * PL111_MAX_CURSOR_HEIGHT * 4)) { + DRM_ERROR("Cannot set cursor with an obj size = %d\n", + obj->size); + drm_gem_object_unreference_unlocked(obj); + return -EINVAL; + } + + bo = PL111_BO_FROM_GEM(obj); + if (!(bo->type & PL111_BOT_DMA)) { + DRM_ERROR("Tried to set cursor with non DMA backed obj = %p\n", + obj); + drm_gem_object_unreference_unlocked(obj); + return -EINVAL; + } + + pl111_set_cursor_image(bo->backing_data.dma.fb_cpu_addr); + + /* + * Since we copy the contents of the buffer to the HW cursor internal + * memory this GEM object is not needed anymore. + */ + drm_gem_object_unreference_unlocked(obj); + + pl111_cursor_enable(); + + return 0; +} + +int pl111_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + int x_clip = 0; + int y_clip = 0; + + DRM_DEBUG("x %d y %d\n", x, y); + + /* + * The cursor image is clipped automatically at the screen limits when + * it extends beyond the screen image to the right or bottom but + * we must clip it using pl111 HW features for negative values. + */ + if (x < 0) { + x_clip = -x; + x = 0; + } + if (y < 0) { + y_clip = -y; + y = 0; + } + + pl111_set_cursor_clipping(x_clip, y_clip); + pl111_set_cursor_position(x, y); + + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_device.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_device.c new file mode 100644 index 0000000000000000000000000000000000000000..b8ea5f6725ecda4b17c312cf3ceadfadd4690ea5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_device.c @@ -0,0 +1,326 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_device.c + * Implementation of the Linux device driver entrypoints for PL111 DRM + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + +struct pl111_drm_dev_private priv; + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS +static void initial_kds_obtained(void *cb1, void *cb2) +{ + wait_queue_head_t *wait = (wait_queue_head_t *) cb1; + bool *cb_has_called = (bool *) cb2; + + *cb_has_called = true; + wake_up(wait); +} + +/* Must be called from within current_displaying_lock spinlock */ +void release_kds_resource_and_display(struct pl111_drm_flip_resource *flip_res) +{ + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(flip_res->crtc); + pl111_crtc->displaying_fb = flip_res->fb; + + /* Release the previous buffer */ + if (pl111_crtc->old_kds_res_set != NULL) { + /* + * Can flip to the same buffer, but must not release the current + * resource set + */ + BUG_ON(pl111_crtc->old_kds_res_set == flip_res->kds_res_set); + kds_resource_set_release(&pl111_crtc->old_kds_res_set); + } + /* Record the current buffer, to release on the next buffer flip */ + pl111_crtc->old_kds_res_set = flip_res->kds_res_set; +} +#endif + +void pl111_drm_preclose(struct drm_device *dev, struct drm_file *file_priv) +{ + DRM_DEBUG_KMS("DRM %s on dev=%p\n", __func__, dev); +} + +void pl111_drm_lastclose(struct drm_device *dev) +{ + DRM_DEBUG_KMS("DRM %s on dev=%p\n", __func__, dev); +} + +/* + * pl111 does not have a proper HW counter for vblank IRQs so enable_vblank + * and disable_vblank are just no op callbacks. + */ +static int pl111_enable_vblank(struct drm_device *dev, int crtc) +{ + DRM_DEBUG_KMS("%s: dev=%p, crtc=%d", __func__, dev, crtc); + return 0; +} + +static void pl111_disable_vblank(struct drm_device *dev, int crtc) +{ + DRM_DEBUG_KMS("%s: dev=%p, crtc=%d", __func__, dev, crtc); +} + +struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = pl111_fb_create, +}; + +static int pl111_modeset_init(struct drm_device *dev) +{ + struct drm_mode_config *mode_config; + struct pl111_drm_dev_private *priv = dev->dev_private; + struct pl111_drm_connector *pl111_connector; + struct pl111_drm_encoder *pl111_encoder; + int ret = 0; + + if (priv == NULL) + return -EINVAL; + + drm_mode_config_init(dev); + mode_config = &dev->mode_config; + mode_config->funcs = &mode_config_funcs; + mode_config->min_width = 1; + mode_config->max_width = 1024; + mode_config->min_height = 1; + mode_config->max_height = 768; + + priv->pl111_crtc = pl111_crtc_create(dev); + if (priv->pl111_crtc == NULL) { + pr_err("Failed to create pl111_drm_crtc\n"); + ret = -ENOMEM; + goto out_config; + } + + priv->number_crtcs = 1; + + pl111_connector = pl111_connector_create(dev); + if (pl111_connector == NULL) { + pr_err("Failed to create pl111_drm_connector\n"); + ret = -ENOMEM; + goto out_config; + } + + pl111_encoder = pl111_encoder_create(dev, 1); + if (pl111_encoder == NULL) { + pr_err("Failed to create pl111_drm_encoder\n"); + ret = -ENOMEM; + goto out_config; + } + + ret = drm_mode_connector_attach_encoder(&pl111_connector->connector, + &pl111_encoder->encoder); + if (ret != 0) { + DRM_ERROR("Failed to attach encoder\n"); + goto out_config; + } + + pl111_connector->connector.encoder = &pl111_encoder->encoder; + + goto finish; + +out_config: + drm_mode_config_cleanup(dev); +finish: + DRM_DEBUG("%s returned %d\n", __func__, ret); + return ret; +} + +static void pl111_modeset_fini(struct drm_device *dev) +{ + drm_mode_config_cleanup(dev); +} + +static int pl111_drm_load(struct drm_device *dev, unsigned long chipset) +{ + int ret = 0; + + pr_info("DRM %s\n", __func__); + + mutex_init(&priv.export_dma_buf_lock); + atomic_set(&priv.nr_flips_in_flight, 0); + init_waitqueue_head(&priv.wait_for_flips); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + ret = kds_callback_init(&priv.kds_cb, 1, show_framebuffer_on_crtc_cb); + if (ret != 0) { + pr_err("Failed to initialise KDS callback\n"); + goto finish; + } + + ret = kds_callback_init(&priv.kds_obtain_current_cb, 1, + initial_kds_obtained); + if (ret != 0) { + pr_err("Failed to init KDS obtain callback\n"); + kds_callback_term(&priv.kds_cb); + goto finish; + } +#endif + + /* Create a cache for page flips */ + priv.page_flip_slab = kmem_cache_create("page flip slab", + sizeof(struct pl111_drm_flip_resource), 0, 0, NULL); + if (priv.page_flip_slab == NULL) { + DRM_ERROR("Failed to create slab\n"); + ret = -ENOMEM; + goto out_kds_callbacks; + } + + dev->dev_private = &priv; + + ret = pl111_modeset_init(dev); + if (ret != 0) { + pr_err("Failed to init modeset\n"); + goto out_slab; + } + + ret = pl111_device_init(dev); + if (ret != 0) { + DRM_ERROR("Failed to init MMIO and IRQ\n"); + goto out_modeset; + } + + ret = drm_vblank_init(dev, 1); + if (ret != 0) { + DRM_ERROR("Failed to init vblank\n"); + goto out_vblank; + } + + goto finish; + +out_vblank: + pl111_device_fini(dev); +out_modeset: + pl111_modeset_fini(dev); +out_slab: + kmem_cache_destroy(priv.page_flip_slab); +out_kds_callbacks: +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + kds_callback_term(&priv.kds_obtain_current_cb); + kds_callback_term(&priv.kds_cb); +#endif +finish: + DRM_DEBUG_KMS("pl111_drm_load returned %d\n", ret); + return ret; +} + +static int pl111_drm_unload(struct drm_device *dev) +{ + pr_info("DRM %s\n", __func__); + + kmem_cache_destroy(priv.page_flip_slab); + + drm_vblank_cleanup(dev); + pl111_modeset_fini(dev); + pl111_device_fini(dev); + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + kds_callback_term(&priv.kds_obtain_current_cb); + kds_callback_term(&priv.kds_cb); +#endif + return 0; +} + +static struct vm_operations_struct pl111_gem_vm_ops = { + .fault = pl111_gem_fault, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +#else + .open = pl111_gem_vm_open, + .close = pl111_gem_vm_close, +#endif +}; + +static const struct file_operations drm_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = pl111_gem_mmap, + .poll = drm_poll, + .read = drm_read, + .fasync = drm_fasync, +}; + +static struct drm_ioctl_desc pl111_ioctls[] = { + DRM_IOCTL_DEF_DRV(PL111_GEM_CREATE, pl111_drm_gem_create_ioctl, + DRM_CONTROL_ALLOW | DRM_UNLOCKED), +}; + +static struct drm_driver driver = { + .driver_features = + DRIVER_MODESET | DRIVER_FB_DMA | DRIVER_GEM | DRIVER_PRIME, + .load = pl111_drm_load, + .unload = pl111_drm_unload, + .context_dtor = NULL, + .preclose = pl111_drm_preclose, + .lastclose = pl111_drm_lastclose, + .suspend = pl111_drm_suspend, + .resume = pl111_drm_resume, + .get_vblank_counter = drm_vblank_count, + .enable_vblank = pl111_enable_vblank, + .disable_vblank = pl111_disable_vblank, + .ioctls = pl111_ioctls, + .fops = &drm_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, + .dumb_create = pl111_dumb_create, + .dumb_destroy = pl111_dumb_destroy, + .dumb_map_offset = pl111_dumb_map_offset, + .gem_free_object = pl111_gem_free_object, + .gem_vm_ops = &pl111_gem_vm_ops, + .prime_handle_to_fd = &pl111_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_export = &pl111_gem_prime_export, + .gem_prime_import = &pl111_gem_prime_import, +}; + +int pl111_drm_init(struct platform_device *dev) +{ + int ret; + pr_info("DRM %s\n", __func__); + pr_info("PL111 DRM initialize, driver name: %s, version %d.%d\n", + DRIVER_NAME, DRIVER_MAJOR, DRIVER_MINOR); + driver.num_ioctls = DRM_ARRAY_SIZE(pl111_ioctls); + ret = 0; + driver.kdriver.platform_device = dev; + return drm_platform_init(&driver, dev); + +} + +void pl111_drm_exit(struct platform_device *dev) +{ + pr_info("DRM %s\n", __func__); + drm_platform_exit(&driver, dev); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_dma_buf.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_dma_buf.c new file mode 100644 index 0000000000000000000000000000000000000000..a0d65f1d5faf4e7cb5ae14c71f319ff53815bfdb --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_dma_buf.c @@ -0,0 +1,615 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_dma_buf.c + * Implementation of the dma_buf functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS +static void obtain_kds_if_currently_displayed(struct drm_device *dev, + struct pl111_gem_bo *bo, + struct dma_buf *dma_buf) +{ + unsigned long shared[1] = { 0 }; + struct kds_resource *resource_list[1]; + struct kds_resource_set *kds_res_set; + struct drm_crtc *crtc; + bool cb_has_called = false; + unsigned long flags; + int err; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + + DRM_DEBUG_KMS("Obtaining initial KDS res for bo:%p dma_buf:%p\n", + bo, dma_buf); + + resource_list[0] = get_dma_buf_kds_resource(dma_buf); + get_dma_buf(dma_buf); + + /* + * Can't use kds_waitall(), because kbase will be let through due to + * locked ignore' + */ + err = kds_async_waitall(&kds_res_set, + &priv.kds_obtain_current_cb, &wake, + &cb_has_called, 1, shared, resource_list); + BUG_ON(err); + wait_event(wake, cb_has_called == true); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + if (pl111_crtc->displaying_fb) { + struct pl111_drm_framebuffer *pl111_fb; + struct drm_framebuffer *fb = pl111_crtc->displaying_fb; + + pl111_fb = PL111_FB_FROM_FRAMEBUFFER(fb); + + if (pl111_fb->bo == bo) { + DRM_DEBUG_KMS("Initial KDS resource for bo %p", bo); + DRM_DEBUG_KMS(" is being displayed, keeping\n"); + /* There shouldn't be a previous buffer to release */ + BUG_ON(pl111_crtc->old_kds_res_set); + + if (kds_res_set == NULL) { + err = kds_async_waitall(&kds_res_set, + &priv.kds_obtain_current_cb, + &wake, &cb_has_called, + 1, shared, resource_list); + BUG_ON(err); + wait_event(wake, cb_has_called == true); + } + + /* Current buffer will need releasing on next flip */ + pl111_crtc->old_kds_res_set = kds_res_set; + + /* + * Clear kds_res_set, so a new kds_res_set is allocated + * for additional CRTCs + */ + kds_res_set = NULL; + } + } + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, flags); + } + + /* kds_res_set will be NULL here if any CRTCs are displaying fb */ + if (kds_res_set != NULL) { + DRM_DEBUG_KMS("Initial KDS resource for bo %p", bo); + DRM_DEBUG_KMS(" not being displayed, discarding\n"); + /* They're not being displayed, release them */ + kds_resource_set_release(&kds_res_set); + } + + dma_buf_put(dma_buf); +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) + +static int pl111_dma_buf_mmap(struct dma_buf *buffer, + struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = buffer->priv; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + struct drm_device *dev = obj->dev; + int ret; + + DRM_DEBUG_KMS("DRM %s on dma_buf=%p\n", __func__, buffer); + + mutex_lock(&dev->struct_mutex); + ret = drm_gem_mmap_obj(obj, obj->size, vma); + mutex_unlock(&dev->struct_mutex); + if (ret) + return ret; + + return pl111_bo_mmap(obj, bo, vma, buffer->size); +} + +#else + +static int pl111_dma_buf_mmap(struct dma_buf *buffer, + struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = buffer->priv; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + struct drm_device *dev = obj->dev; + + DRM_DEBUG_KMS("DRM %s on dma_buf=%p\n", __func__, buffer); + + mutex_lock(&dev->struct_mutex); + + /* Check for valid size. */ + if (obj->size < vma->vm_end - vma->vm_start) + return -EINVAL; + + BUG_ON(!dev->driver->gem_vm_ops); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; +#else + vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND; +#endif + + vma->vm_ops = dev->driver->gem_vm_ops; + vma->vm_private_data = obj; + + /* Take a ref for this mapping of the object, so that the fault + * handler can dereference the mmap offset's pointer to the object. + * This reference is cleaned up by the corresponding vm_close + * (which should happen whether the vma was created by this call, or + * by a vm_open due to mremap or partial unmap or whatever). + */ + drm_gem_object_reference(obj); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) + pl111_drm_vm_open_locked(dev, vma); +#else + drm_vm_open_locked(dev, vma); +#endif + + mutex_unlock(&dev->struct_mutex); + + return pl111_bo_mmap(obj, bo, vma, buffer->size); +} + +#endif /* KERNEL_VERSION */ + +static void pl111_dma_buf_release(struct dma_buf *buf) +{ + /* + * Need to release the dma_buf's reference on the gem object it was + * exported from, and also clear the gem object's export_dma_buf + * pointer to this dma_buf as it no longer exists + */ + struct drm_gem_object *obj = (struct drm_gem_object *)buf->priv; + struct pl111_gem_bo *bo; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct drm_crtc *crtc; + unsigned long flags; +#endif + bo = PL111_BO_FROM_GEM(obj); + + DRM_DEBUG_KMS("Releasing dma_buf %p, drm_gem_obj=%p\n", buf, obj); + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + list_for_each_entry(crtc, &bo->gem_object.dev->mode_config.crtc_list, + head) { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + if (pl111_crtc->displaying_fb) { + struct pl111_drm_framebuffer *pl111_fb; + struct drm_framebuffer *fb = pl111_crtc->displaying_fb; + + pl111_fb = PL111_FB_FROM_FRAMEBUFFER(fb); + if (pl111_fb->bo == bo) { + kds_resource_set_release(&pl111_crtc->old_kds_res_set); + pl111_crtc->old_kds_res_set = NULL; + } + } + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, flags); + } +#endif + mutex_lock(&priv.export_dma_buf_lock); + + obj->export_dma_buf = NULL; + drm_gem_object_unreference_unlocked(obj); + + mutex_unlock(&priv.export_dma_buf_lock); +} + +static int pl111_dma_buf_attach(struct dma_buf *buf, struct device *dev, + struct dma_buf_attachment *attach) +{ + DRM_DEBUG_KMS("Attaching dma_buf %p to device %p attach=%p\n", buf, + dev, attach); + + attach->priv = dev; + + return 0; +} + +static void pl111_dma_buf_detach(struct dma_buf *buf, + struct dma_buf_attachment *attach) +{ + DRM_DEBUG_KMS("Detaching dma_buf %p attach=%p\n", attach->dmabuf, + attach); +} + +/* Heavily from exynos_drm_dmabuf.c */ +static struct sg_table *pl111_dma_buf_map_dma_buf(struct dma_buf_attachment + *attach, + enum dma_data_direction + direction) +{ + struct drm_gem_object *obj = attach->dmabuf->priv; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + struct drm_device *dev = obj->dev; + int size, n_pages, nents; + struct scatterlist *s, *sg; + struct sg_table *sgt; + int ret, i; + + DRM_DEBUG_KMS("Mapping dma_buf %p from attach=%p (bo=%p)\n", attach->dmabuf, + attach, bo); + + /* + * Nothing to do, if we are trying to map a dmabuf that has been imported. + * Just return the existing sgt. + */ + if (obj->import_attach) { + BUG_ON(!bo->sgt); + return bo->sgt; + } + + size = obj->size; + n_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; + + if (bo->type & PL111_BOT_DMA) { + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) { + DRM_ERROR("Failed to allocate sg_table\n"); + return ERR_PTR(-ENOMEM); + } + + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); + if (ret < 0) { + DRM_ERROR("Failed to allocate page table\n"); + return ERR_PTR(-ENOMEM); + } + sg_dma_len(sgt->sgl) = size; + /* We use DMA coherent mappings for PL111_BOT_DMA so we must + * use the virtual address returned at buffer allocation */ + sg_set_buf(sgt->sgl, bo->backing_data.dma.fb_cpu_addr, size); + sg_dma_address(sgt->sgl) = bo->backing_data.dma.fb_dev_addr; + } else { /* PL111_BOT_SHM */ + struct page **pages; + int pg = 0; + + mutex_lock(&dev->struct_mutex); + pages = get_pages(obj); + if (IS_ERR(pages)) { + dev_err(obj->dev->dev, "could not get pages: %ld\n", + PTR_ERR(pages)); + return ERR_CAST(pages); + } + sgt = drm_prime_pages_to_sg(pages, n_pages); + if (sgt == NULL) + return ERR_PTR(-ENOMEM); + + pl111_gem_sync_to_dma(bo); + + /* + * At this point the pages have been dma-mapped by either + * get_pages() for non cached maps or pl111_gem_sync_to_dma() + * for cached. So the physical addresses can be assigned + * to the sg entries. + * drm_prime_pages_to_sg() may have combined contiguous pages + * into chunks so we assign the physical address of the first + * page of a chunk to the chunk and check that the physical + * addresses of the rest of the pages in that chunk are also + * contiguous. + */ + sg = sgt->sgl; + nents = sgt->nents; + + for_each_sg(sg, s, nents, i) { + int j, n_pages_in_chunk = sg_dma_len(s) >> PAGE_SHIFT; + + sg_dma_address(s) = bo->backing_data.shm.dma_addrs[pg]; + + for (j = pg+1; j < pg+n_pages_in_chunk; j++) { + BUG_ON(bo->backing_data.shm.dma_addrs[j] != + bo->backing_data.shm.dma_addrs[j-1]+PAGE_SIZE); + } + + pg += n_pages_in_chunk; + } + + mutex_unlock(&dev->struct_mutex); + } + bo->sgt = sgt; + return sgt; +} + +static void pl111_dma_buf_unmap_dma_buf(struct dma_buf_attachment *attach, + struct sg_table *sgt, + enum dma_data_direction direction) +{ + struct drm_gem_object *obj = attach->dmabuf->priv; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + + DRM_DEBUG_KMS("Unmapping dma_buf %p from attach=%p (bo=%p)\n", attach->dmabuf, + attach, bo); + + sg_free_table(sgt); + kfree(sgt); + bo->sgt = NULL; +} + +/* + * There isn't any operation here that can sleep or fail so this callback can + * be used for both kmap and kmap_atomic implementations. + */ +static void *pl111_dma_buf_kmap(struct dma_buf *dma_buf, unsigned long pageno) +{ + struct pl111_gem_bo *bo = dma_buf->priv; + void *vaddr = NULL; + + /* Make sure we cannot access outside the memory range */ + if (((pageno + 1) << PAGE_SHIFT) > bo->gem_object.size) + return NULL; + + if (bo->type & PL111_BOT_DMA) { + vaddr = (bo->backing_data.dma.fb_cpu_addr + + (pageno << PAGE_SHIFT)); + } else { + vaddr = page_address(bo->backing_data.shm.pages[pageno]); + } + + return vaddr; +} + +/* + * Find a scatterlist that starts in "start" and has "len" + * or return a NULL dma_handle. + */ +static dma_addr_t pl111_find_matching_sg(struct sg_table *sgt, size_t start, + size_t len) +{ + struct scatterlist *sg; + unsigned int count; + size_t size = 0; + dma_addr_t dma_handle = 0; + + /* Find a scatterlist that starts in "start" and has "len" + * or return error */ + for_each_sg(sgt->sgl, sg, sgt->nents, count) { + if ((size == start) && (len == sg_dma_len(sg))) { + dma_handle = sg_dma_address(sg); + break; + } + size += sg_dma_len(sg); + } + return dma_handle; +} + +static int pl111_dma_buf_begin_cpu(struct dma_buf *dma_buf, + size_t start, size_t len, + enum dma_data_direction dir) +{ + struct pl111_gem_bo *bo = dma_buf->priv; + struct sg_table *sgt = bo->sgt; + dma_addr_t dma_handle; + + if ((start + len) > bo->gem_object.size) + return -EINVAL; + + if (!(bo->type & PL111_BOT_SHM)) { + struct device *dev = bo->gem_object.dev->dev; + + dma_handle = pl111_find_matching_sg(sgt, start, len); + if (!dma_handle) + return -EINVAL; + + dma_sync_single_range_for_cpu(dev, dma_handle, 0, len, dir); + } + /* PL111_BOT_DMA uses coherents mappings, no need to sync */ + return 0; +} + +static void pl111_dma_buf_end_cpu(struct dma_buf *dma_buf, + size_t start, size_t len, + enum dma_data_direction dir) +{ + struct pl111_gem_bo *bo = dma_buf->priv; + struct sg_table *sgt = bo->sgt; + dma_addr_t dma_handle; + + if ((start + len) > bo->gem_object.size) + return; + + if (!(bo->type & PL111_BOT_DMA)) { + struct device *dev = bo->gem_object.dev->dev; + + dma_handle = pl111_find_matching_sg(sgt, start, len); + if (!dma_handle) + return; + + dma_sync_single_range_for_device(dev, dma_handle, 0, len, dir); + } + /* PL111_BOT_DMA uses coherents mappings, no need to sync */ +} + +static struct dma_buf_ops pl111_dma_buf_ops = { + .release = &pl111_dma_buf_release, + .attach = &pl111_dma_buf_attach, + .detach = &pl111_dma_buf_detach, + .map_dma_buf = &pl111_dma_buf_map_dma_buf, + .unmap_dma_buf = &pl111_dma_buf_unmap_dma_buf, + .kmap_atomic = &pl111_dma_buf_kmap, + .kmap = &pl111_dma_buf_kmap, + .begin_cpu_access = &pl111_dma_buf_begin_cpu, + .end_cpu_access = &pl111_dma_buf_end_cpu, + .mmap = &pl111_dma_buf_mmap, +}; + +struct drm_gem_object *pl111_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf) +{ + struct dma_buf_attachment *attachment; + struct drm_gem_object *obj; + struct pl111_gem_bo *bo; + struct scatterlist *sgl; + struct sg_table *sgt; + dma_addr_t cont_phys; + int ret = 0; + int i; + + DRM_DEBUG_KMS("DRM %s on dev=%p dma_buf=%p\n", __func__, dev, dma_buf); + + /* is this one of own objects? */ + if (dma_buf->ops == &pl111_dma_buf_ops) { + obj = dma_buf->priv; + /* is it from our device? */ + if (obj->dev == dev) { + /* + * Importing dmabuf exported from our own gem increases + * refcount on gem itself instead of f_count of dmabuf. + */ + drm_gem_object_reference(obj); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) + /* before v3.10.0 we assume the caller has taken a ref on the dma_buf + * we don't want it for self-imported buffers so drop it here */ + dma_buf_put(dma_buf); +#endif + + return obj; + } + } + + attachment = dma_buf_attach(dma_buf, dev->dev); + if (IS_ERR(attachment)) + return ERR_CAST(attachment); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) + /* from 3.10.0 we assume the caller has not taken a ref so we take one here */ + get_dma_buf(dma_buf); +#endif + + sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(sgt)) { + ret = PTR_ERR(sgt); + goto err_buf_detach; + } + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); + if (!bo) { + DRM_ERROR("%s: failed to allocate buffer object.\n", __func__); + ret = -ENOMEM; + goto err_unmap_attach; + } + + /* Find out whether the buffer is contiguous or not */ + sgl = sgt->sgl; + cont_phys = sg_phys(sgl); + bo->type |= PL111_BOT_DMA; + for_each_sg(sgt->sgl, sgl, sgt->nents, i) { + dma_addr_t real_phys = sg_phys(sgl); + if (real_phys != cont_phys) { + bo->type &= ~PL111_BOT_DMA; + break; + } + cont_phys += (PAGE_SIZE - sgl->offset); + } + + ret = drm_gem_private_object_init(dev, &bo->gem_object, + dma_buf->size); + if (ret != 0) { + DRM_ERROR("DRM could not import DMA GEM obj\n"); + goto err_free_buffer; + } + + if (bo->type & PL111_BOT_DMA) { + bo->backing_data.dma.fb_cpu_addr = sg_virt(sgt->sgl); + bo->backing_data.dma.fb_dev_addr = sg_phys(sgt->sgl); + DRM_DEBUG_KMS("DRM %s pl111_gem_bo=%p, contiguous import\n", __func__, bo); + } else { /* PL111_BOT_SHM */ + DRM_DEBUG_KMS("DRM %s pl111_gem_bo=%p, non contiguous import\n", __func__, bo); + } + + bo->gem_object.import_attach = attachment; + bo->sgt = sgt; + + return &bo->gem_object; + +err_free_buffer: + kfree(bo); + bo = NULL; +err_unmap_attach: + dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL); +err_buf_detach: + dma_buf_detach(dma_buf, attachment); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) + /* from 3.10.0 we will have taken a ref so drop it here */ + dma_buf_put(dma_buf); +#endif + return ERR_PTR(ret); +} + +struct dma_buf *pl111_gem_prime_export(struct drm_device *dev, + struct drm_gem_object *obj, int flags) +{ + struct dma_buf *new_buf; + struct pl111_gem_bo *bo; + size_t size; + + DRM_DEBUG("DRM %s on dev=%p drm_gem_obj=%p\n", __func__, dev, obj); + size = obj->size; + + new_buf = dma_buf_export(obj /*priv */ , &pl111_dma_buf_ops, size, + flags | O_RDWR); + bo = PL111_BO_FROM_GEM(new_buf->priv); + + /* + * bo->gem_object.export_dma_buf not setup until after gem_prime_export + * finishes + */ + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* + * Ensure that we hold the kds resource if it's the currently + * displayed buffer. + */ + obtain_kds_if_currently_displayed(dev, bo, new_buf); +#endif + + DRM_DEBUG("Created dma_buf %p\n", new_buf); + + return new_buf; +} + +int pl111_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, + uint32_t handle, uint32_t flags, int *prime_fd) +{ + int result; + /* + * This will re-use any existing exports, and calls + * driver->gem_prime_export to do the first export when needed + */ + DRM_DEBUG_KMS("DRM %s on file_priv=%p, handle=0x%.8x\n", __func__, + file_priv, handle); + + mutex_lock(&priv.export_dma_buf_lock); + result = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, + prime_fd); + mutex_unlock(&priv.export_dma_buf_lock); + + return result; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_encoder.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_encoder.c new file mode 100644 index 0000000000000000000000000000000000000000..b7dbbf2794ab896a3a59bd76aa730d022f0c3c3a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_encoder.c @@ -0,0 +1,107 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_encoder.c + * Implementation of the encoder functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + +bool pl111_encoder_helper_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); + return true; +} + +void pl111_encoder_helper_prepare(struct drm_encoder *encoder) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); +} + +void pl111_encoder_helper_commit(struct drm_encoder *encoder) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); +} + +void pl111_encoder_helper_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); +} + +void pl111_encoder_helper_disable(struct drm_encoder *encoder) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); +} + +void pl111_encoder_destroy(struct drm_encoder *encoder) +{ + struct pl111_drm_encoder *pl111_encoder = + PL111_ENCODER_FROM_ENCODER(encoder); + + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); + + drm_encoder_cleanup(encoder); + kfree(pl111_encoder); +} + +const struct drm_encoder_funcs encoder_funcs = { + .destroy = pl111_encoder_destroy, +}; + +const struct drm_encoder_helper_funcs encoder_helper_funcs = { + .mode_fixup = pl111_encoder_helper_mode_fixup, + .prepare = pl111_encoder_helper_prepare, + .commit = pl111_encoder_helper_commit, + .mode_set = pl111_encoder_helper_mode_set, + .disable = pl111_encoder_helper_disable, +}; + +struct pl111_drm_encoder *pl111_encoder_create(struct drm_device *dev, + int possible_crtcs) +{ + struct pl111_drm_encoder *pl111_encoder; + + pl111_encoder = kzalloc(sizeof(struct pl111_drm_encoder), GFP_KERNEL); + if (pl111_encoder == NULL) { + pr_err("Failed to allocated pl111_drm_encoder\n"); + return NULL; + } + + drm_encoder_init(dev, &pl111_encoder->encoder, &encoder_funcs, + DRM_MODE_ENCODER_DAC); + + drm_encoder_helper_add(&pl111_encoder->encoder, &encoder_helper_funcs); + + pl111_encoder->encoder.possible_crtcs = possible_crtcs; + + return pl111_encoder; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_fb.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_fb.c new file mode 100644 index 0000000000000000000000000000000000000000..546e4d45f4c95842c82cffaadcf3a0607f022178 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_fb.c @@ -0,0 +1,202 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_fb.c + * Implementation of the framebuffer functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "pl111_drm.h" + +static void pl111_fb_destroy(struct drm_framebuffer *framebuffer) +{ + struct pl111_drm_framebuffer *pl111_fb; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct drm_crtc *crtc; + unsigned long flags; +#endif + DRM_DEBUG_KMS("Destroying framebuffer 0x%p...\n", framebuffer); + + pl111_fb = PL111_FB_FROM_FRAMEBUFFER(framebuffer); + + /* + * Because flips are deferred, wait for all previous flips to complete + */ + wait_event(priv.wait_for_flips, + atomic_read(&priv.nr_flips_in_flight) == 0); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* + * Release KDS resources if it's currently being displayed. Only occurs + * when the last framebuffer is destroyed. + */ + list_for_each_entry(crtc, &framebuffer->dev->mode_config.crtc_list, + head) { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + if (pl111_crtc->displaying_fb == framebuffer) { + /* Release the current buffers */ + if (pl111_crtc->old_kds_res_set != NULL) { + DRM_DEBUG_KMS("Releasing KDS resources for "); + DRM_DEBUG_KMS("displayed 0x%p\n", framebuffer); + kds_resource_set_release( + &pl111_crtc->old_kds_res_set); + } + pl111_crtc->old_kds_res_set = NULL; + } + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, + flags); + } +#endif + drm_framebuffer_cleanup(framebuffer); + + if ((pl111_fb->bo != NULL) && (&pl111_fb->bo->gem_object != NULL)) + drm_gem_object_unreference_unlocked(&pl111_fb->bo->gem_object); + + kfree(pl111_fb); + + DRM_DEBUG_KMS("Destroyed framebuffer 0x%p\n", framebuffer); +} + +static int pl111_fb_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + struct pl111_gem_bo *bo = PL111_BO_FROM_FRAMEBUFFER(fb); + DRM_DEBUG_KMS("DRM %s on fb=%p\n", __func__, fb); + + if (bo == NULL) + return -EINVAL; + + return drm_gem_handle_create(file_priv, &bo->gem_object, handle); +} + +const struct drm_framebuffer_funcs fb_funcs = { + .destroy = pl111_fb_destroy, + .create_handle = pl111_fb_create_handle, +}; + +struct drm_framebuffer *pl111_fb_create(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct pl111_drm_framebuffer *pl111_fb = NULL; + struct drm_framebuffer *fb = NULL; + struct drm_gem_object *gem_obj; + struct pl111_gem_bo *bo; + int err = 0; + size_t min_size; + int bpp; + int depth; + + pr_info("DRM %s\n", __func__); + gem_obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (gem_obj == NULL) { + DRM_ERROR("Could not get gem obj from handle to create fb\n"); + err = -ENOENT; + goto error; + } + + bo = PL111_BO_FROM_GEM(gem_obj); + drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + if (mode_cmd->pitches[0] < mode_cmd->width * (bpp >> 3)) { + DRM_ERROR("bad pitch %u for plane 0\n", mode_cmd->pitches[0]); + err = -EINVAL; + goto error; + } + + min_size = (mode_cmd->height - 1) * mode_cmd->pitches[0] + + mode_cmd->width * (bpp >> 3); + + if (bo->gem_object.size < min_size) { + DRM_ERROR("gem obj size < min size\n"); + err = -EINVAL; + goto error; + } + + /* We can't scan out SHM so we can't create an fb for it */ + if (!(bo->type & PL111_BOT_DMA)) { + DRM_ERROR("Can't create FB for non-scanout buffer\n"); + err = -EINVAL; + goto error; + } + + switch ((char)(mode_cmd->pixel_format & 0xFF)) { + case 'Y': + case 'U': + case 'V': + case 'N': + case 'T': + DRM_ERROR("YUV formats not supported\n"); + err = -EINVAL; + goto error; + } + + pl111_fb = kzalloc(sizeof(struct pl111_drm_framebuffer), GFP_KERNEL); + if (pl111_fb == NULL) { + DRM_ERROR("Could not allocate pl111_drm_framebuffer\n"); + err = -ENOMEM; + goto error; + } + fb = &pl111_fb->fb; + + err = drm_framebuffer_init(dev, fb, &fb_funcs); + if (err) { + DRM_ERROR("drm_framebuffer_init failed\n"); + kfree(fb); + fb = NULL; + goto error; + } + + drm_helper_mode_fill_fb_struct(fb, mode_cmd); + + /* The only framebuffer formats supported by pl111 + * are 16 bpp or 32 bpp with 24 bit depth. + * See clcd_enable() + */ + if (!((fb->bits_per_pixel == 16) || + (fb->bits_per_pixel == 32 && fb->depth == 24))) { + DRM_DEBUG_KMS("unsupported pixel format bpp=%d, depth=%d\n", fb->bits_per_pixel, fb->depth); + drm_framebuffer_cleanup(fb); + kfree(fb); + fb = NULL; + err = -EINVAL; + goto error; + } + + pl111_fb->bo = bo; + + DRM_DEBUG_KMS("Created fb 0x%p with gem_obj 0x%p physaddr=0x%.8x\n", + fb, gem_obj, bo->backing_data.dma.fb_dev_addr); + + return fb; + +error: + if (gem_obj != NULL) + drm_gem_object_unreference_unlocked(gem_obj); + + return ERR_PTR(err); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_funcs.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_funcs.h new file mode 100644 index 0000000000000000000000000000000000000000..34e0bad994d7667846a96952166eeeb59dd37e2a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_funcs.h @@ -0,0 +1,130 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_funcs.h + * Function prototypes for PL111 DRM + */ + +#ifndef PL111_DRM_FUNCS_H_ +#define PL111_DRM_FUNCS_H_ + +/* Platform Initialisation */ +int pl111_drm_init(struct platform_device *dev); +void pl111_drm_exit(struct platform_device *dev); + +/* KDS Callbacks */ +void show_framebuffer_on_crtc_cb(void *cb1, void *cb2); +void release_kds_resource_and_display(struct pl111_drm_flip_resource *flip_res); + +/* CRTC Functions */ +struct pl111_drm_crtc *pl111_crtc_create(struct drm_device *dev); +struct pl111_drm_crtc *pl111_crtc_dummy_create(struct drm_device *dev); +void pl111_crtc_destroy(struct drm_crtc *crtc); + +bool pl111_crtc_is_fb_currently_displayed(struct drm_device *dev, + struct drm_framebuffer *fb); + +int show_framebuffer_on_crtc(struct drm_crtc *crtc, + struct drm_framebuffer *fb, bool page_flip, + struct drm_pending_vblank_event *event); + +/* Common IRQ handler */ +void pl111_common_irq(struct pl111_drm_crtc *pl111_crtc); + +int pl111_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height); +int pl111_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y); + +/* Connector Functions */ +struct pl111_drm_connector *pl111_connector_create(struct drm_device *dev); +void pl111_connector_destroy(struct drm_connector *connector); +struct pl111_drm_connector *pl111_connector_dummy_create(struct drm_device + *dev); + +/* Encoder Functions */ +struct pl111_drm_encoder *pl111_encoder_create(struct drm_device *dev, + int possible_crtcs); +struct pl111_drm_encoder *pl111_encoder_dummy_create(struct drm_device *dev, + int possible_crtcs); +void pl111_encoder_destroy(struct drm_encoder *encoder); + +/* Frame Buffer Functions */ +struct drm_framebuffer *pl111_fb_create(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_mode_fb_cmd2 *mode_cmd); + +/* VMA Functions */ +int pl111_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); +int pl111_gem_mmap(struct file *file_priv, struct vm_area_struct *vma); +struct page **get_pages(struct drm_gem_object *obj); +void put_pages(struct drm_gem_object *obj, struct page **pages); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) +void pl111_drm_vm_open_locked(struct drm_device *dev, + struct vm_area_struct *vma); +void pl111_gem_vm_open(struct vm_area_struct *vma); +void pl111_gem_vm_close(struct vm_area_struct *vma); +#endif + +/* Suspend Functions */ +int pl111_drm_resume(struct drm_device *dev); +int pl111_drm_suspend(struct drm_device *dev, pm_message_t state); + +/* GEM Functions */ +int pl111_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); +int pl111_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle); +int pl111_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); +void pl111_gem_free_object(struct drm_gem_object *obj); + +int pl111_bo_mmap(struct drm_gem_object *obj, struct pl111_gem_bo *bo, + struct vm_area_struct *vma, size_t size); +void pl111_gem_sync_to_cpu(struct pl111_gem_bo *bo, int pgoff); +void pl111_gem_sync_to_dma(struct pl111_gem_bo *bo); + +/* DMA BUF Functions */ +struct drm_gem_object *pl111_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf); +int pl111_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, + uint32_t handle, uint32_t flags, int *prime_fd); +struct dma_buf *pl111_gem_prime_export(struct drm_device *dev, + struct drm_gem_object *obj, int flags); + +/* Pl111 Functions */ +void show_framebuffer_on_crtc_cb_internal(struct pl111_drm_flip_resource + *flip_res, struct drm_framebuffer *fb); +int clcd_disable(struct drm_crtc *crtc); +void do_flip_to_res(struct pl111_drm_flip_resource *flip_res); +int pl111_amba_probe(struct amba_device *dev, const struct amba_id *id); +int pl111_amba_remove(struct amba_device *dev); + +int pl111_device_init(struct drm_device *dev); +void pl111_device_fini(struct drm_device *dev); + +void pl111_convert_drm_mode_to_timing(struct drm_display_mode *mode, + struct clcd_regs *timing); +void pl111_convert_timing_to_drm_mode(struct clcd_regs *timing, + struct drm_display_mode *mode); +#endif /* PL111_DRM_FUNCS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_gem.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_gem.c new file mode 100644 index 0000000000000000000000000000000000000000..ed5dcabe0082af3b9c35434e6e20b3512d030a0d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_gem.c @@ -0,0 +1,401 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_gem.c + * Implementation of the GEM functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pl111_drm.h" + +void pl111_gem_free_object(struct drm_gem_object *obj) +{ + struct pl111_gem_bo *bo; + struct drm_device *dev = obj->dev; + DRM_DEBUG_KMS("DRM %s on drm_gem_object=%p\n", __func__, obj); + + bo = PL111_BO_FROM_GEM(obj); + + if (obj->import_attach) + drm_prime_gem_destroy(obj, bo->sgt); + + if (obj->map_list.map != NULL) + drm_gem_free_mmap_offset(obj); + + /* + * Only free the backing memory if the object has not been imported. + * If it has been imported, the exporter is in charge to free that + * once dmabuf's refcount becomes 0. + */ + if (obj->import_attach) + goto imported_out; + + if (bo->type & PL111_BOT_DMA) { + dma_free_writecombine(dev->dev, obj->size, + bo->backing_data.dma.fb_cpu_addr, + bo->backing_data.dma.fb_dev_addr); + } else if (bo->backing_data.shm.pages != NULL) { + put_pages(obj, bo->backing_data.shm.pages); + } + +imported_out: + drm_gem_object_release(obj); + + kfree(bo); + + DRM_DEBUG_KMS("Destroyed dumb_bo handle 0x%p\n", bo); +} + +static int pl111_gem_object_create(struct drm_device *dev, u64 size, + u32 flags, struct drm_file *file_priv, + u32 *handle) +{ + int ret = 0; + struct pl111_gem_bo *bo = NULL; + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); + if (bo == NULL) { + ret = -ENOMEM; + goto finish; + } + + bo->type = flags; + +#ifndef ARCH_HAS_SG_CHAIN + /* + * If the ARCH can't chain we can't have non-contiguous allocs larger + * than a single sg can hold. + * In this case we fall back to using contiguous memory + */ + if (!(bo->type & PL111_BOT_DMA)) { + long unsigned int n_pages = + PAGE_ALIGN(size) >> PAGE_SHIFT; + if (n_pages > SG_MAX_SINGLE_ALLOC) { + bo->type |= PL111_BOT_DMA; + /* + * Non-contiguous allocation request changed to + * contigous + */ + DRM_INFO("non-contig alloc to contig %lu > %lu pages.", + n_pages, SG_MAX_SINGLE_ALLOC); + } + } +#endif + if (bo->type & PL111_BOT_DMA) { + /* scanout compatible - use physically contiguous buffer */ + bo->backing_data.dma.fb_cpu_addr = + dma_alloc_writecombine(dev->dev, size, + &bo->backing_data.dma.fb_dev_addr, + GFP_KERNEL); + if (bo->backing_data.dma.fb_cpu_addr == NULL) { + DRM_ERROR("dma_alloc_writecombine failed\n"); + ret = -ENOMEM; + goto free_bo; + } + + ret = drm_gem_private_object_init(dev, &bo->gem_object, + size); + if (ret != 0) { + DRM_ERROR("DRM could not initialise GEM object\n"); + goto free_dma; + } + } else { /* PL111_BOT_SHM */ + /* not scanout compatible - use SHM backed object */ + ret = drm_gem_object_init(dev, &bo->gem_object, size); + if (ret != 0) { + DRM_ERROR("DRM could not init SHM backed GEM obj\n"); + ret = -ENOMEM; + goto free_bo; + } + DRM_DEBUG_KMS("Num bytes: %d\n", bo->gem_object.size); + } + + DRM_DEBUG("s=%llu, flags=0x%x, %s 0x%.8lx, type=%d\n", + size, flags, + (bo->type & PL111_BOT_DMA) ? "physaddr" : "shared page array", + (bo->type & PL111_BOT_DMA) ? + (unsigned long)bo->backing_data.dma.fb_dev_addr: + (unsigned long)bo->backing_data.shm.pages, + bo->type); + + ret = drm_gem_handle_create(file_priv, &bo->gem_object, handle); + if (ret != 0) { + DRM_ERROR("DRM failed to create GEM handle\n"); + goto obj_release; + } + + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(&bo->gem_object); + + return 0; + +obj_release: + drm_gem_object_release(&bo->gem_object); +free_dma: + if (bo->type & PL111_BOT_DMA) + dma_free_writecombine(dev->dev, size, + bo->backing_data.dma.fb_cpu_addr, + bo->backing_data.dma.fb_dev_addr); +free_bo: + kfree(bo); +finish: + return ret; +} + +int pl111_drm_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_pl111_gem_create *args = data; + uint32_t bytes_pp; + + /* Round bpp up, to allow for case where bpp<8 */ + bytes_pp = args->bpp >> 3; + if (args->bpp & ((1 << 3) - 1)) + bytes_pp++; + + if (args->flags & ~PL111_BOT_MASK) { + DRM_ERROR("wrong flags: 0x%x\n", args->flags); + return -EINVAL; + } + + args->pitch = ALIGN(args->width * bytes_pp, 64); + args->size = PAGE_ALIGN(args->pitch * args->height); + + DRM_DEBUG_KMS("gem_create w=%d h=%d p=%d bpp=%d b=%d s=%llu f=0x%x\n", + args->width, args->height, args->pitch, args->bpp, + bytes_pp, args->size, args->flags); + + return pl111_gem_object_create(dev, args->size, args->flags, file_priv, + &args->handle); +} + +int pl111_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, struct drm_mode_create_dumb *args) +{ + uint32_t bytes_pp; + + /* Round bpp up, to allow for case where bpp<8 */ + bytes_pp = args->bpp >> 3; + if (args->bpp & ((1 << 3) - 1)) + bytes_pp++; + + if (args->flags) { + DRM_ERROR("flags must be zero: 0x%x\n", args->flags); + return -EINVAL; + } + + args->pitch = ALIGN(args->width * bytes_pp, 64); + args->size = PAGE_ALIGN(args->pitch * args->height); + + DRM_DEBUG_KMS("dumb_create w=%d h=%d p=%d bpp=%d b=%d s=%llu f=0x%x\n", + args->width, args->height, args->pitch, args->bpp, + bytes_pp, args->size, args->flags); + + return pl111_gem_object_create(dev, args->size, + PL111_BOT_DMA | PL111_BOT_UNCACHED, + file_priv, &args->handle); +} + +int pl111_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, + uint32_t handle) +{ + DRM_DEBUG_KMS("DRM %s on file_priv=%p handle=0x%.8x\n", __func__, + file_priv, handle); + return drm_gem_handle_delete(file_priv, handle); +} + +int pl111_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset) +{ + struct drm_gem_object *obj; + int ret = 0; + DRM_DEBUG_KMS("DRM %s on file_priv=%p handle=0x%.8x\n", __func__, + file_priv, handle); + + /* GEM does all our handle to object mapping */ + obj = drm_gem_object_lookup(dev, file_priv, handle); + if (obj == NULL) { + ret = -ENOENT; + goto fail; + } + + if (obj->map_list.map == NULL) { + ret = drm_gem_create_mmap_offset(obj); + if (ret != 0) { + drm_gem_object_unreference_unlocked(obj); + goto fail; + } + } + + *offset = (uint64_t) obj->map_list.hash.key << PAGE_SHIFT; + + drm_gem_object_unreference_unlocked(obj); +fail: + return ret; +} + +/* sync the buffer for DMA access */ +void pl111_gem_sync_to_dma(struct pl111_gem_bo *bo) +{ + struct drm_device *dev = bo->gem_object.dev; + + if (!(bo->type & PL111_BOT_DMA) && (bo->type & PL111_BOT_CACHED)) { + int i, npages = bo->gem_object.size >> PAGE_SHIFT; + struct page **pages = bo->backing_data.shm.pages; + bool dirty = false; + + for (i = 0; i < npages; i++) { + if (!bo->backing_data.shm.dma_addrs[i]) { + DRM_DEBUG("%s: dma map page=%d bo=%p\n", __func__, i, bo); + bo->backing_data.shm.dma_addrs[i] = + dma_map_page(dev->dev, pages[i], 0, + PAGE_SIZE, DMA_BIDIRECTIONAL); + dirty = true; + } + } + + if (dirty) { + DRM_DEBUG("%s: zap ptes (and flush cache) bo=%p\n", __func__, bo); + /* + * TODO MIDEGL-1813 + * + * Use flush_cache_page() and outer_flush_range() to + * flush only the user space mappings of the dirty pages + */ + flush_cache_all(); + outer_flush_all(); + unmap_mapping_range(bo->gem_object.filp->f_mapping, 0, + bo->gem_object.size, 1); + } + } +} + +void pl111_gem_sync_to_cpu(struct pl111_gem_bo *bo, int pgoff) +{ + struct drm_device *dev = bo->gem_object.dev; + + /* + * TODO MIDEGL-1808 + * + * The following check was meant to detect if the CPU is trying to access + * a buffer that is currently mapped for DMA accesses, which is illegal + * as described by the DMA-API. + * + * However, some of our tests are trying to do that, which triggers the message + * below and avoids dma-unmapping the pages not to annoy the DMA device but that + * leads to the test failing because of caches not being properly flushed. + */ + + /* + if (bo->sgt) { + DRM_ERROR("%s: the CPU is trying to access a dma-mapped buffer\n", __func__); + return; + } + */ + + if (!(bo->type & PL111_BOT_DMA) && (bo->type & PL111_BOT_CACHED) && + bo->backing_data.shm.dma_addrs[pgoff]) { + DRM_DEBUG("%s: unmap bo=%p (s=%d), paddr=%08x\n", + __func__, bo, bo->gem_object.size, + bo->backing_data.shm.dma_addrs[pgoff]); + dma_unmap_page(dev->dev, bo->backing_data.shm.dma_addrs[pgoff], + PAGE_SIZE, DMA_BIDIRECTIONAL); + bo->backing_data.shm.dma_addrs[pgoff] = 0; + } +} + +/* Based on omapdrm driver */ +int pl111_bo_mmap(struct drm_gem_object *obj, struct pl111_gem_bo *bo, + struct vm_area_struct *vma, size_t size) +{ + DRM_DEBUG("DRM %s on drm_gem_object=%p, pl111_gem_bo=%p type=%08x\n", + __func__, obj, bo, bo->type); + + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_flags |= VM_MIXEDMAP; + + if (bo->type & PL111_BOT_WC) { + vma->vm_page_prot = + pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + } else if (bo->type & PL111_BOT_CACHED) { + /* + * Objects that do not have a filp (DMA backed) can't be + * mapped as cached now. Write-combine should be enough. + */ + if (WARN_ON(!obj->filp)) + return -EINVAL; + + /* + * As explained in Documentation/dma-buf-sharing.txt + * we need this trick so that we can manually zap ptes + * in order to fake coherency. + */ + fput(vma->vm_file); + vma->vm_pgoff = 0; + get_file(obj->filp); + vma->vm_file = obj->filp; + + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + } else { /* PL111_BOT_UNCACHED */ + vma->vm_page_prot = + pgprot_noncached(vm_get_page_prot(vma->vm_flags)); + } + return 0; +} + +int pl111_gem_mmap(struct file *file_priv, struct vm_area_struct *vma) +{ + int ret; + struct drm_file *priv = file_priv->private_data; + struct drm_device *dev = priv->minor->dev; + struct drm_gem_mm *mm = dev->mm_private; + struct drm_local_map *map = NULL; + struct drm_hash_item *hash; + struct drm_gem_object *obj; + struct pl111_gem_bo *bo; + + DRM_DEBUG_KMS("DRM %s\n", __func__); + + drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash); + map = drm_hash_entry(hash, struct drm_map_list, hash)->map; + obj = map->handle; + bo = PL111_BO_FROM_GEM(obj); + + DRM_DEBUG_KMS("DRM %s on pl111_gem_bo %p bo->type 0x%08x\n", __func__, bo, bo->type); + + /* for an imported buffer we let the exporter handle the mmap */ + if (obj->import_attach) + return dma_buf_mmap(obj->import_attach->dmabuf, vma, 0); + + ret = drm_gem_mmap(file_priv, vma); + if (ret < 0) { + DRM_ERROR("failed to mmap\n"); + return ret; + } + + return pl111_bo_mmap(obj, bo, vma, vma->vm_end - vma->vm_start); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_pl111.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_pl111.c new file mode 100644 index 0000000000000000000000000000000000000000..0b3c6813b36cce9bc33e07bc9a3acf4388d369e6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_pl111.c @@ -0,0 +1,417 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_pl111.c + * PL111 specific functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pl111_drm.h" + +/* This can't be called from IRQ context, due to clk_get() and board->enable */ +static int clcd_enable(struct drm_framebuffer *fb) +{ + __u32 cntl; + struct clcd_board *board; + + pr_info("DRM %s\n", __func__); + + clk_prepare_enable(priv.clk); + + /* Enable and Power Up */ + cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDPWR | CNTL_LCDVCOMP(1); + DRM_DEBUG_KMS("fb->bits_per_pixel = %d\n", fb->bits_per_pixel); + if (fb->bits_per_pixel == 16) + cntl |= CNTL_LCDBPP16_565; + else if (fb->bits_per_pixel == 32 && fb->depth == 24) + cntl |= CNTL_LCDBPP24; + else + BUG_ON(1); + + cntl |= CNTL_BGR; + + writel(cntl, priv.regs + CLCD_PL111_CNTL); + + if (priv.amba_dev->dev.platform_data) { + board = priv.amba_dev->dev.platform_data; + + if (board->enable) + board->enable(NULL); + } + + /* Enable Interrupts */ + writel(CLCD_IRQ_NEXTBASE_UPDATE, priv.regs + CLCD_PL111_IENB); + + return 0; +} + +int clcd_disable(struct drm_crtc *crtc) +{ + struct clcd_board *board; + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + unsigned long flags; +#endif + + pr_info("DRM %s\n", __func__); + + /* Disable Interrupts */ + writel(0x00000000, priv.regs + CLCD_PL111_IENB); + + if (priv.amba_dev->dev.platform_data) { + board = priv.amba_dev->dev.platform_data; + + if (board->disable) + board->disable(NULL); + } + + /* Disable and Power Down */ + writel(0, priv.regs + CLCD_PL111_CNTL); + + /* Disable clock */ + clk_disable_unprepare(priv.clk); + + pl111_crtc->last_bpp = 0; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + /* Release the previous buffers */ + if (pl111_crtc->old_kds_res_set != NULL) + kds_resource_set_release(&pl111_crtc->old_kds_res_set); + + pl111_crtc->old_kds_res_set = NULL; + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, flags); +#endif + return 0; +} + +/* + * To avoid a possible race where "pl111_crtc->current_update_res" has + * been updated (non NULL) but the corresponding scanout buffer has not been + * written to the base registers we must always call this function holding + * the "base_update_lock" spinlock with IRQs disabled (spin_lock_irqsave()). + */ +void do_flip_to_res(struct pl111_drm_flip_resource *flip_res) +{ + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(flip_res->crtc); + struct drm_framebuffer *fb; + struct pl111_gem_bo *bo; + size_t min_size; + fb = flip_res->fb; + bo = PL111_BO_FROM_FRAMEBUFFER(fb); + + + + min_size = (fb->height - 1) * fb->pitches[0] + + fb->width * (fb->bits_per_pixel >> 3); + + BUG_ON(bo->gem_object.size < min_size); + + /* Don't even attempt PL111_BOT_SHM, it's not contiguous */ + BUG_ON(bo->type != PL111_BOT_DMA); + + /* + * Note the buffer for releasing after IRQ, and don't allow any more + * updates until then. + * + * This clcd controller latches the new address on next vsync. Address + * latching is indicated by CLCD_IRQ_NEXTBASE_UPDATE, and so we must + * wait for that before releasing the previous buffer's kds + * resources. Otherwise, we'll allow writers to write to the old buffer + * whilst it is still being displayed + */ + pl111_crtc->current_update_res = flip_res; + + DRM_DEBUG_KMS("Displaying fb 0x%p, dumb_bo 0x%p, physaddr %.8x\n", + fb, bo, bo->backing_data.dma.fb_dev_addr); + + if (drm_vblank_get(pl111_crtc->crtc.dev, pl111_crtc->crtc_index) < 0) + DRM_ERROR("Could not get vblank reference for crtc %d\n", + pl111_crtc->crtc_index); + + /* Set the scanout buffer */ + writel(bo->backing_data.dma.fb_dev_addr, priv.regs + CLCD_UBAS); + writel(bo->backing_data.dma.fb_dev_addr + + ((fb->height - 1) * fb->pitches[0]), priv.regs + CLCD_LBAS); +} + +void +show_framebuffer_on_crtc_cb_internal(struct pl111_drm_flip_resource *flip_res, + struct drm_framebuffer *fb) +{ + unsigned long irq_flags; + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(flip_res->crtc); + + spin_lock_irqsave(&pl111_crtc->base_update_lock, irq_flags); + if (list_empty(&pl111_crtc->update_queue) && + !pl111_crtc->current_update_res) { + do_flip_to_res(flip_res); + } else { + /* + * Enqueue the update to occur on a future IRQ + * This only happens on triple-or-greater buffering + */ + DRM_DEBUG_KMS("Deferring 3+ buffered flip to fb %p to IRQ\n", + fb); + list_add_tail(&flip_res->link, &pl111_crtc->update_queue); + } + spin_unlock_irqrestore(&pl111_crtc->base_update_lock, irq_flags); + + if (!flip_res->page_flip && (pl111_crtc->last_bpp == 0 || + pl111_crtc->last_bpp != fb->bits_per_pixel || + !drm_mode_equal(pl111_crtc->new_mode, + pl111_crtc->current_mode))) { + struct clcd_regs timing; + + pl111_convert_drm_mode_to_timing(pl111_crtc->new_mode, &timing); + + DRM_DEBUG_KMS("Set timing: %08X:%08X:%08X:%08X clk=%ldHz\n", + timing.tim0, timing.tim1, timing.tim2, + timing.tim3, timing.pixclock); + + /* This is the actual mode setting part */ + clk_set_rate(priv.clk, timing.pixclock); + + writel(timing.tim0, priv.regs + CLCD_TIM0); + writel(timing.tim1, priv.regs + CLCD_TIM1); + writel(timing.tim2, priv.regs + CLCD_TIM2); + writel(timing.tim3, priv.regs + CLCD_TIM3); + + clcd_enable(fb); + pl111_crtc->last_bpp = fb->bits_per_pixel; + } + + if (!flip_res->page_flip) { + drm_mode_destroy(flip_res->crtc->dev, pl111_crtc->current_mode); + pl111_crtc->current_mode = pl111_crtc->new_mode; + pl111_crtc->new_mode = NULL; + } + + BUG_ON(!pl111_crtc->current_mode); + + /* + * If IRQs weren't enabled before, they are now. This will eventually + * cause flip_res to be released via pl111_common_irq, which updates + * every time the Base Address is latched (i.e. every frame, regardless + * of whether we update the base address or not) + */ +} + +irqreturn_t pl111_irq(int irq, void *data) +{ + u32 irq_stat; + struct pl111_drm_crtc *pl111_crtc = priv.pl111_crtc; + + irq_stat = readl(priv.regs + CLCD_PL111_MIS); + + if (!irq_stat) + return IRQ_NONE; + + if (irq_stat & CLCD_IRQ_NEXTBASE_UPDATE) + pl111_common_irq(pl111_crtc); + + /* Clear the interrupt once done */ + writel(irq_stat, priv.regs + CLCD_PL111_ICR); + + return IRQ_HANDLED; +} + +int pl111_device_init(struct drm_device *dev) +{ + struct pl111_drm_dev_private *priv = dev->dev_private; + int ret; + + if (priv == NULL) { + pr_err("%s no private data\n", __func__); + return -EINVAL; + } + + if (priv->amba_dev == NULL) { + pr_err("%s no amba device found\n", __func__); + return -EINVAL; + } + + /* set up MMIO for register access */ + priv->mmio_start = priv->amba_dev->res.start; + priv->mmio_len = resource_size(&priv->amba_dev->res); + + DRM_DEBUG_KMS("mmio_start=%lu, mmio_len=%u\n", priv->mmio_start, + priv->mmio_len); + + priv->regs = ioremap(priv->mmio_start, priv->mmio_len); + if (priv->regs == NULL) { + pr_err("%s failed mmio\n", __func__); + return -EINVAL; + } + + /* turn off interrupts */ + writel(0, priv->regs + CLCD_PL111_IENB); + + ret = request_irq(priv->amba_dev->irq[0], pl111_irq, 0, + "pl111_irq_handler", NULL); + if (ret != 0) { + pr_err("%s failed %d\n", __func__, ret); + goto out_mmio; + } + + goto finish; + +out_mmio: + iounmap(priv->regs); +finish: + DRM_DEBUG_KMS("pl111_device_init returned %d\n", ret); + return ret; +} + +void pl111_device_fini(struct drm_device *dev) +{ + struct pl111_drm_dev_private *priv = dev->dev_private; + u32 cntl; + + if (priv == NULL || priv->regs == NULL) + return; + + free_irq(priv->amba_dev->irq[0], NULL); + + cntl = readl(priv->regs + CLCD_PL111_CNTL); + + cntl &= ~CNTL_LCDEN; + writel(cntl, priv->regs + CLCD_PL111_CNTL); + + cntl &= ~CNTL_LCDPWR; + writel(cntl, priv->regs + CLCD_PL111_CNTL); + + iounmap(priv->regs); +} + +int pl111_amba_probe(struct amba_device *dev, const struct amba_id *id) +{ + struct clcd_board *board = dev->dev.platform_data; + int ret; + pr_info("DRM %s\n", __func__); + + if (!board) + dev_warn(&dev->dev, "board data not available\n"); + + ret = amba_request_regions(dev, NULL); + if (ret != 0) { + DRM_ERROR("CLCD: unable to reserve regs region\n"); + goto out; + } + + priv.amba_dev = dev; + + priv.clk = clk_get(&priv.amba_dev->dev, NULL); + if (IS_ERR(priv.clk)) { + DRM_ERROR("CLCD: unable to get clk.\n"); + ret = PTR_ERR(priv.clk); + goto clk_err; + } + + return 0; + +clk_err: + amba_release_regions(dev); +out: + return ret; +} + +int pl111_amba_remove(struct amba_device *dev) +{ + DRM_DEBUG_KMS("DRM %s\n", __func__); + + clk_put(priv.clk); + + amba_release_regions(dev); + + priv.amba_dev = NULL; + + return 0; +} + +void pl111_convert_drm_mode_to_timing(struct drm_display_mode *mode, + struct clcd_regs *timing) +{ + unsigned int ppl, hsw, hfp, hbp; + unsigned int lpp, vsw, vfp, vbp; + unsigned int cpl; + + memset(timing, 0, sizeof(struct clcd_regs)); + + ppl = (mode->hdisplay / 16) - 1; + hsw = mode->hsync_end - mode->hsync_start - 1; + hfp = mode->hsync_start - mode->hdisplay - 1; + hbp = mode->htotal - mode->hsync_end - 1; + + lpp = mode->vdisplay - 1; + vsw = mode->vsync_end - mode->vsync_start - 1; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + + cpl = mode->hdisplay - 1; + + timing->tim0 = (ppl << 2) | (hsw << 8) | (hfp << 16) | (hbp << 24); + timing->tim1 = lpp | (vsw << 10) | (vfp << 16) | (vbp << 24); + timing->tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC | TIM2_BCD | (cpl << 16); + timing->tim3 = 0; + + timing->pixclock = mode->clock * 1000; +} + +void pl111_convert_timing_to_drm_mode(struct clcd_regs *timing, + struct drm_display_mode *mode) +{ + unsigned int ppl, hsw, hfp, hbp; + unsigned int lpp, vsw, vfp, vbp; + + ppl = (timing->tim0 >> 2) & 0x3f; + hsw = (timing->tim0 >> 8) & 0xff; + hfp = (timing->tim0 >> 16) & 0xff; + hbp = (timing->tim0 >> 24) & 0xff; + + lpp = timing->tim1 & 0x3ff; + vsw = (timing->tim1 >> 10) & 0x3f; + vfp = (timing->tim1 >> 16) & 0xff; + vbp = (timing->tim1 >> 24) & 0xff; + + mode->hdisplay = (ppl + 1) * 16; + mode->hsync_start = ((ppl + 1) * 16) + hfp + 1; + mode->hsync_end = ((ppl + 1) * 16) + hfp + hsw + 2; + mode->htotal = ((ppl + 1) * 16) + hfp + hsw + hbp + 3; + mode->hskew = 0; + + mode->vdisplay = lpp + 1; + mode->vsync_start = lpp + vfp + 1; + mode->vsync_end = lpp + vfp + vsw + 2; + mode->vtotal = lpp + vfp + vsw + vbp + 2; + + mode->flags = 0; + + mode->width_mm = 0; + mode->height_mm = 0; + + mode->clock = timing->pixclock / 1000; + mode->hsync = timing->pixclock / mode->htotal; + mode->vrefresh = mode->hsync / mode->vtotal; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_platform.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..fe7db7392792a77d5031e28cad6cd5c9aa4cd6b3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_platform.c @@ -0,0 +1,151 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_platform.c + * Implementation of the Linux platform device entrypoints for PL111 DRM + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pl111_drm.h" + +static int pl111_platform_drm_suspend(struct platform_device *dev, + pm_message_t state) +{ + pr_info("DRM %s\n", __func__); + return 0; +} + +static int pl111_platform_drm_resume(struct platform_device *dev) +{ + pr_info("DRM %s\n", __func__); + return 0; +} + +int pl111_platform_drm_probe(struct platform_device *dev) +{ + pr_info("DRM %s\n", __func__); + return pl111_drm_init(dev); +} + +static int pl111_platform_drm_remove(struct platform_device *dev) +{ + pr_info("DRM %s\n", __func__); + pl111_drm_exit(dev); + + return 0; +} + +static struct amba_id pl111_id_table[] = { + { + .id = 0x00041110, + .mask = 0x000ffffe, + }, + {0, 0}, +}; + +static struct amba_driver pl111_amba_driver = { + .drv = { + .name = "clcd-pl11x", + }, + .probe = pl111_amba_probe, + .remove = pl111_amba_remove, + .id_table = pl111_id_table, +}; + +static struct platform_driver platform_drm_driver = { + .probe = pl111_platform_drm_probe, + .remove = pl111_platform_drm_remove, + .suspend = pl111_platform_drm_suspend, + .resume = pl111_platform_drm_resume, + .driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME, + }, +}; + +static const struct platform_device_info pl111_drm_pdevinfo = { + .name = DRIVER_NAME, + .id = -1, + .dma_mask = ~0UL +}; + +static struct platform_device *pl111_drm_device; + +static int __init pl111_platform_drm_init(void) +{ + int ret; + + pr_info("DRM %s\n", __func__); + + pl111_drm_device = platform_device_register_full(&pl111_drm_pdevinfo); + if (pl111_drm_device == NULL) { + pr_err("DRM platform_device_register_full() failed\n"); + return -ENOMEM; + } + + ret = amba_driver_register(&pl111_amba_driver); + if (ret != 0) { + pr_err("DRM amba_driver_register() failed %d\n", ret); + goto err_amba_reg; + } + + ret = platform_driver_register(&platform_drm_driver); + if (ret != 0) { + pr_err("DRM platform_driver_register() failed %d\n", ret); + goto err_pdrv_reg; + } + + return 0; + +err_pdrv_reg: + amba_driver_unregister(&pl111_amba_driver); +err_amba_reg: + platform_device_unregister(pl111_drm_device); + + return ret; +} + +static void __exit pl111_platform_drm_exit(void) +{ + pr_info("DRM %s\n", __func__); + + platform_device_unregister(pl111_drm_device); + amba_driver_unregister(&pl111_amba_driver); + platform_driver_unregister(&platform_drm_driver); +} + +#ifdef MODULE +module_init(pl111_platform_drm_init); +#else +late_initcall(pl111_platform_drm_init); +#endif +module_exit(pl111_platform_drm_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE(DRIVER_LICENCE); +MODULE_ALIAS(DRIVER_ALIAS); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_suspend.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_suspend.c new file mode 100644 index 0000000000000000000000000000000000000000..a61636f8424ff7389855437d3cb34b6b71a849cc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_suspend.c @@ -0,0 +1,43 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_suspend.c + * Implementation of the suspend/resume functions for PL111 DRM + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pl111_drm.h" + +int pl111_drm_suspend(struct drm_device *dev, pm_message_t state) +{ + pr_info("DRM %s\n", __func__); + return 0; +} + +int pl111_drm_resume(struct drm_device *dev) +{ + pr_info("DRM %s\n", __func__); + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_vma.c b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_vma.c new file mode 100644 index 0000000000000000000000000000000000000000..c9918f79e939f36c89cb1555e3f00ad099b3b395 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/pl111_drm_vma.c @@ -0,0 +1,307 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_vma.c + * Implementation of the VM functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "pl111_drm.h" + +/* BEGIN drivers/staging/omapdrm/omap_gem_helpers.c */ +/** + * drm_gem_put_pages - helper to free backing pages for a GEM object + * @obj: obj in question + * @pages: pages to free + */ +static void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, + bool dirty, bool accessed) +{ + int i, npages; + struct pl111_gem_bo *bo; + npages = obj->size >> PAGE_SHIFT; + bo = PL111_BO_FROM_GEM(obj); + for (i = 0; i < npages; i++) { + if (dirty) + set_page_dirty(pages[i]); + if (accessed) + mark_page_accessed(pages[i]); + /* Undo the reference we took when populating the table */ + page_cache_release(pages[i]); + } + drm_free_large(pages); +} + +void put_pages(struct drm_gem_object *obj, struct page **pages) +{ + int i, npages; + struct pl111_gem_bo *bo; + npages = obj->size >> PAGE_SHIFT; + bo = PL111_BO_FROM_GEM(obj); + _drm_gem_put_pages(obj, pages, true, true); + if (bo->backing_data.shm.dma_addrs) { + for (i = 0; i < npages; i++) { + /* Filter pages unmapped because of CPU accesses */ + if (!bo->backing_data.shm.dma_addrs[i]) + continue; + if (!dma_mapping_error(obj->dev->dev, + bo->backing_data.shm.dma_addrs[i])) { + dma_unmap_page(obj->dev->dev, + bo->backing_data.shm.dma_addrs[i], + PAGE_SIZE, + DMA_BIDIRECTIONAL); + } + } + kfree(bo->backing_data.shm.dma_addrs); + bo->backing_data.shm.dma_addrs = NULL; + } +} + +/** + * drm_gem_get_pages - helper to allocate backing pages for a GEM object + * @obj: obj in question + * @gfpmask: gfp mask of requested pages + */ +static struct page **_drm_gem_get_pages(struct drm_gem_object *obj, + gfp_t gfpmask) +{ + struct inode *inode; + struct address_space *mapping; + struct page *p, **pages; + int i, npages; + + /* This is the shared memory object that backs the GEM resource */ + inode = obj->filp->f_path.dentry->d_inode; + mapping = inode->i_mapping; + + npages = obj->size >> PAGE_SHIFT; + + pages = drm_malloc_ab(npages, sizeof(struct page *)); + if (pages == NULL) + return ERR_PTR(-ENOMEM); + + gfpmask |= mapping_gfp_mask(mapping); + + for (i = 0; i < npages; i++) { + p = shmem_read_mapping_page_gfp(mapping, i, gfpmask); + if (IS_ERR(p)) + goto fail; + pages[i] = p; + + /* + * There is a hypothetical issue w/ drivers that require + * buffer memory in the low 4GB.. if the pages are un- + * pinned, and swapped out, they can end up swapped back + * in above 4GB. If pages are already in memory, then + * shmem_read_mapping_page_gfp will ignore the gfpmask, + * even if the already in-memory page disobeys the mask. + * + * It is only a theoretical issue today, because none of + * the devices with this limitation can be populated with + * enough memory to trigger the issue. But this BUG_ON() + * is here as a reminder in case the problem with + * shmem_read_mapping_page_gfp() isn't solved by the time + * it does become a real issue. + * + * See this thread: http://lkml.org/lkml/2011/7/11/238 + */ + BUG_ON((gfpmask & __GFP_DMA32) && + (page_to_pfn(p) >= 0x00100000UL)); + } + + return pages; + +fail: + while (i--) + page_cache_release(pages[i]); + + drm_free_large(pages); + return ERR_PTR(PTR_ERR(p)); +} + +struct page **get_pages(struct drm_gem_object *obj) +{ + struct pl111_gem_bo *bo; + bo = PL111_BO_FROM_GEM(obj); + + if (bo->backing_data.shm.pages == NULL) { + struct page **p; + int npages = obj->size >> PAGE_SHIFT; + int i; + + p = _drm_gem_get_pages(obj, GFP_KERNEL); + if (IS_ERR(p)) + return ERR_PTR(-ENOMEM); + + bo->backing_data.shm.pages = p; + + if (bo->backing_data.shm.dma_addrs == NULL) { + bo->backing_data.shm.dma_addrs = + kzalloc(npages * sizeof(dma_addr_t), + GFP_KERNEL); + if (bo->backing_data.shm.dma_addrs == NULL) + goto error_out; + } + + if (!(bo->type & PL111_BOT_CACHED)) { + for (i = 0; i < npages; ++i) { + bo->backing_data.shm.dma_addrs[i] = + dma_map_page(obj->dev->dev, p[i], 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(obj->dev->dev, + bo->backing_data.shm.dma_addrs[i])) + goto error_out; + } + } + } + + return bo->backing_data.shm.pages; + +error_out: + put_pages(obj, bo->backing_data.shm.pages); + bo->backing_data.shm.pages = NULL; + return ERR_PTR(-ENOMEM); +} + +/* END drivers/staging/omapdrm/omap_gem_helpers.c */ +int pl111_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct page **pages; + pgoff_t pgoff; + unsigned long pfn; + struct drm_gem_object *obj = vma->vm_private_data; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + struct drm_device *dev = obj->dev; + int ret; + + mutex_lock(&dev->struct_mutex); + + /* We don't use vmf->pgoff since that has the fake offset: */ + pgoff = ((unsigned long)vmf->virtual_address - + vma->vm_start) >> PAGE_SHIFT; + + if (bo->type & PL111_BOT_DMA) { + pfn = (bo->backing_data.dma.fb_dev_addr >> PAGE_SHIFT) + pgoff; + } else { /* PL111_BOT_SHM */ + pages = get_pages(obj); + if (IS_ERR(pages)) { + dev_err(obj->dev->dev, + "could not get pages: %ld\n", PTR_ERR(pages)); + ret = PTR_ERR(pages); + goto error; + } + pfn = page_to_pfn(pages[pgoff]); + pl111_gem_sync_to_cpu(bo, pgoff); + } + + DRM_DEBUG("bo=%p physaddr=0x%.8x for offset 0x%x\n", + bo, PFN_PHYS(pfn), PFN_PHYS(pgoff)); + + ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); + +error: + mutex_unlock(&dev->struct_mutex); + + switch (ret) { + case 0: + case -ERESTARTSYS: + case -EINTR: + case -EBUSY: + return VM_FAULT_NOPAGE; + case -ENOMEM: + return VM_FAULT_OOM; + default: + return VM_FAULT_SIGBUS; + } +} + +/* + * The core drm_vm_ functions in kernel 3.4 are not ready + * to handle dma_buf cases where vma->vm_file->private_data + * cannot be accessed to get the device. + * + * We use these functions from 3.5 instead where the device + * pointer is passed explicitly. + * + * However they aren't exported from the kernel until 3.10 + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) +void pl111_drm_vm_open_locked(struct drm_device *dev, + struct vm_area_struct *vma) +{ + struct drm_vma_entry *vma_entry; + + DRM_DEBUG("0x%08lx,0x%08lx\n", + vma->vm_start, vma->vm_end - vma->vm_start); + atomic_inc(&dev->vma_count); + + vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL); + if (vma_entry) { + vma_entry->vma = vma; + vma_entry->pid = current->pid; + list_add(&vma_entry->head, &dev->vmalist); + } +} + +void pl111_drm_vm_close_locked(struct drm_device *dev, + struct vm_area_struct *vma) +{ + struct drm_vma_entry *pt, *temp; + + DRM_DEBUG("0x%08lx,0x%08lx\n", + vma->vm_start, vma->vm_end - vma->vm_start); + atomic_dec(&dev->vma_count); + + list_for_each_entry_safe(pt, temp, &dev->vmalist, head) { + if (pt->vma == vma) { + list_del(&pt->head); + kfree(pt); + break; + } + } +} + +void pl111_gem_vm_open(struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = vma->vm_private_data; + + drm_gem_object_reference(obj); + + mutex_lock(&obj->dev->struct_mutex); + pl111_drm_vm_open_locked(obj->dev, vma); + mutex_unlock(&obj->dev->struct_mutex); +} + +void pl111_gem_vm_close(struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = vma->vm_private_data; + struct drm_device *dev = obj->dev; + + mutex_lock(&dev->struct_mutex); + pl111_drm_vm_close_locked(obj->dev, vma); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); +} +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..dd274f5492d26ecd4e874bab87bc6deb97ef8cb3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/pl111/sconscript @@ -0,0 +1,59 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +import os +import shutil +Import('env') + +# Generate a build environment for the integration tests, taking a copy of the top-level build environment +# (env) as a start. +drm_env = env.Clone() + +# Xorg uses C++ style comments and 'inline' keyword +if '-std=c89' in drm_env['CFLAGS']: + drm_env['CFLAGS'].remove('-std=c89') + +# X11 generates a lot of warnings +if '-Werror' in drm_env['CCFLAGS']: + drm_env['CCFLAGS'].remove('-Werror') + +#remove the 'lib'prefix +drm_env['LIBPREFIX'] = '' + +src = Glob('*.c') + +# Note: cleaning via the Linux kernel build system does not yet work +if drm_env.GetOption('clean') : + makeAction=Action("cd ${SOURCE.dir} && make clean", '$MAKECOMSTR') +else: + makeAction=Action("cd ${SOURCE.dir} && make MALI_DEBUG=${debug} && cp pl111_drm.ko $STATIC_LIB_PATH/mali_drm.ko", '$MAKECOMSTR') + +# The target is mali_drm.ko, built from the source in pl111_drm/pl111, via the action makeAction +# mali_drm.ko will be copied to $STATIC_LIB_PATH after being built by the standard Linux +# kernel build system, after which it can be installed to the directory specified if +# "libs_install" is set; this is done by LibTarget. +cmd = drm_env.Command('$STATIC_LIB_PATH/mali_drm.ko', src, [makeAction]) + +# need Module.symvers from drm.ko +#drm_env.Depends('$STATIC_LIB_PATH/pl111_drm.ko', '$STATIC_LIB_PATH/drm.ko') + +# Until we fathom out how the invoke the Linux build system to clean, we can use Clean +# to remove generated files. +patterns = ['*.mod.c', '*.o', '*.ko', '*.a', '.*.cmd', 'modules.order', '.tmp_versions', 'Module.symvers'] +for p in patterns: + Clean(cmd, Glob('#kernel/drivers/gpu/drm/pl111/%s' % p)) + +env.ProgTarget('x11', cmd) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..d2bff1fa22d3278842f4ef65312e6d64bd4ba073 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/drm/sconscript @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +Import('env') + +if env['winsys'] == 'x11': + # pl111_drm isn't released so only try to build it if it's there + if Glob('pl111/sconscript') and (env['platform_config'] == 'vexpress' or env['platform_config'] == 'vexpress_virtex7_40mhz' or env['platform_config'] == 'vexpress_6xvirtex7_10mhz'): + SConscript('pl111/sconscript') + +#SConscript('dummy_drm/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..729dbda13c197516644805eff621bdb7ca9ea39f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/gpu/sconscript @@ -0,0 +1,21 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +SConscript('arm/sconscript') + +if Glob('drm/sconscript'): + SConscript('drm/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..dd6a637ccacd5238a89d4eee66cb184ab438d31a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/drivers/sconscript @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +if Glob('base/sconscript'): + SConscript('base/sconscript') + +if Glob('video/sconscript'): + SConscript('video/sconscript') + +SConscript('gpu/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/dma-buf-test-exporter.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/dma-buf-test-exporter.h new file mode 100644 index 0000000000000000000000000000000000000000..db0e93898133043113745593488f85ac68e55cbc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/dma-buf-test-exporter.h @@ -0,0 +1,78 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#ifndef _LINUX_DMA_BUF_TEST_EXPORTER_H_ +#define _LINUX_DMA_BUF_TEST_EXPORTER_H_ + +#include +#include + +#define DMA_BUF_TE_VER_MAJOR 1 +#define DMA_BUF_TE_VER_MINOR 0 +#define DMA_BUF_TE_ENQ 0x642d7465 +#define DMA_BUF_TE_ACK 0x68692100 + +struct dma_buf_te_ioctl_version +{ + int op; /**< Must be set to DMA_BUF_TE_ENQ by client, driver will set it to DMA_BUF_TE_ACK */ + int major; /**< Major version */ + int minor; /**< Minor version */ +}; + +struct dma_buf_te_ioctl_alloc +{ + __u64 size; /* size of buffer to allocate, in pages */ +}; + +struct dma_buf_te_ioctl_status +{ + /* in */ + int fd; /* the dma_buf to query, only dma_buf objects exported by this driver is supported */ + /* out */ + int attached_devices; /* number of devices attached (active 'dma_buf_attach's) */ + int device_mappings; /* number of device mappings (active 'dma_buf_map_attachment's) */ + int cpu_mappings; /* number of cpu mappings (active 'mmap's) */ +}; + +struct dma_buf_te_ioctl_set_failing +{ + /* in */ + int fd; /* the dma_buf to set failure mode for, only dma_buf objects exported by this driver is supported */ + + /* zero = no fail injection, non-zero = inject failure */ + int fail_attach; + int fail_map; + int fail_mmap; +}; + +struct dma_buf_te_ioctl_fill +{ + int fd; + unsigned int value; +}; + +#define DMA_BUF_TE_IOCTL_BASE 'E' +/* Below all returning 0 if successful or -errcode except DMA_BUF_TE_ALLOC which will return fd or -errcode */ +#define DMA_BUF_TE_VERSION _IOR(DMA_BUF_TE_IOCTL_BASE, 0x00, struct dma_buf_te_ioctl_version) +#define DMA_BUF_TE_ALLOC _IOR(DMA_BUF_TE_IOCTL_BASE, 0x01, struct dma_buf_te_ioctl_alloc) +#define DMA_BUF_TE_QUERY _IOR(DMA_BUF_TE_IOCTL_BASE, 0x02, struct dma_buf_te_ioctl_status) +#define DMA_BUF_TE_SET_FAILING _IOW(DMA_BUF_TE_IOCTL_BASE, 0x03, struct dma_buf_te_ioctl_set_failing) +#define DMA_BUF_TE_ALLOC_CONT _IOR(DMA_BUF_TE_IOCTL_BASE, 0x04, struct dma_buf_te_ioctl_alloc) +#define DMA_BUF_TE_FILL _IOR(DMA_BUF_TE_IOCTL_BASE, 0x05, struct dma_buf_te_ioctl_fill) + +#endif /* _LINUX_DMA_BUF_TEST_EXPORTER_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/kds.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/kds.h new file mode 100644 index 0000000000000000000000000000000000000000..0ba994db08e7cc1b279fc27e0676b9eb8f487940 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/kds.h @@ -0,0 +1,173 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KDS_H_ +#define _KDS_H_ + +#include +#include + +#define KDS_WAIT_BLOCKING (ULONG_MAX) + +struct kds_resource_set; + +typedef void (*kds_callback_fn) (void *callback_parameter, void *callback_extra_parameter); + +struct kds_callback +{ + kds_callback_fn user_cb; /* real cb */ + int direct; /* do direct or queued call? */ + struct workqueue_struct *wq; +}; + +struct kds_link +{ + struct kds_resource_set *parent; + struct list_head link; + unsigned long state; +}; + +struct kds_resource +{ + struct kds_link waiters; +}; + +/* callback API */ + +/* Initialize a callback object. + * + * Typically created per context or per hw resource. + * + * Callbacks can be performed directly if no nested locking can + * happen in the client. + * + * Nested locking can occur when a lock is held during the kds_async_waitall or + * kds_resource_set_release call. If the callback needs to take the same lock + * nested locking will happen. + * + * If nested locking could happen non-direct callbacks can be requested. + * Callbacks will then be called asynchronous to the triggering call. + */ +int kds_callback_init(struct kds_callback *cb, int direct, kds_callback_fn user_cb); + +/* Terminate the use of a callback object. + * + * If the callback object was set up as non-direct + * any pending callbacks will be flushed first. + * Note that to avoid a deadlock the lock callbacks needs + * can't be held when a callback object is terminated. + */ +void kds_callback_term(struct kds_callback *cb); + + +/* resource object API */ + +/* initialize a resource handle for a shared resource */ +void kds_resource_init(struct kds_resource * const resource); + +/* + * Will return 0 on success. + * If the resource is being used or waited -EBUSY is returned. + * The caller should NOT try to terminate a resource that could still have clients. + * After the function returns the resource is no longer known by kds. + */ +int kds_resource_term(struct kds_resource *resource); + +/* Asynchronous wait for a set of resources. + * Callback will be called when all resources are available. + * If all the resources was available the callback will be called before kds_async_waitall returns. + * So one must not hold any locks the callback code-flow can take when calling kds_async_waitall. + * Caller considered to own/use the resources until \a kds_rset_release is called. + * exclusive_access_bitmap is a bitmap where a high bit means exclusive access while a low bit means shared access. + * Use the Linux __set_bit API, where the index of the buffer to control is used as the bit index. + * + * Standard Linux error return value. + */ +int kds_async_waitall( + struct kds_resource_set ** const pprset, + struct kds_callback *cb, + void *callback_parameter, + void *callback_extra_parameter, + int number_resources, + unsigned long *exclusive_access_bitmap, + struct kds_resource **resource_list); + +/* Synchronous wait for a set of resources. + * Function will return when one of these have happened: + * - all resources have been obtained + * - timeout lapsed while waiting + * - a signal was received while waiting + * + * To wait without a timeout, specify KDS_WAIT_BLOCKING for \a jifies_timeout, otherwise + * the timeout in jiffies. A zero timeout attempts to obtain all resources and returns + * immediately with a timeout if all resources could not be obtained. + * + * Caller considered to own/use the resources when the function returns. + * Caller must release the resources using \a kds_rset_release. + * + * Calling this function while holding already locked resources or other locking primitives is dangerous. + * One must if this is needed decide on a lock order of the resources and/or the other locking primitives + * and always take the resources/locking primitives in the specific order. + * + * Use the ERR_PTR framework to decode the return value. + * NULL = time out + * If IS_ERR then PTR_ERR gives: + * ERESTARTSYS = signal received, retry call after signal + * all other values = internal error, lock failed + * Other values = successful wait, now the owner, must call kds_resource_set_release + */ +struct kds_resource_set *kds_waitall( + int number_resources, + unsigned long *exclusive_access_bitmap, + struct kds_resource **resource_list, + unsigned long jifies_timeout); + +/* Release resources after use. + * Caller must handle that other async callbacks will trigger, + * so must avoid holding any locks a callback will take. + * + * The function takes a pointer to your poiner to handle a race + * between a cancelation and a completion. + * + * If the caller can't guarantee that a race can't occur then + * the passed in pointer must be the same in both call paths + * to allow kds to manage the potential race. + */ +void kds_resource_set_release(struct kds_resource_set **pprset); + +/* Release resources after use and wait callbacks to complete. + * Caller must handle that other async callbacks will trigger, + * so must avoid holding any locks a callback will take. + * + * The function takes a pointer to your poiner to handle a race + * between a cancelation and a completion. + * + * If the caller can't guarantee that a race can't occur then + * the passed in pointer must be the same in both call paths + * to allow kds to manage the potential race. + * + * This should be used to cancel waits which are pending on a kds + * resource. + * + * It is a bug to call this from atomic contexts and from within + * a kds callback that now owns the kds_rseource. + */ + +void kds_resource_set_release_sync(struct kds_resource_set **pprset); +#endif /* _KDS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-common.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-common.h new file mode 100644 index 0000000000000000000000000000000000000000..1deefd84381f1e5d44af83d8c256d7b59810d13d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-common.h @@ -0,0 +1,252 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file ump-common.h + * + * This file contains some common enum values used both in both the user and kernel space side of UMP. + */ + +#ifndef _UMP_COMMON_H_ +#define _UMP_COMMON_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#define UMP_UINT32_MAX (4294967295U) +#define UMP_UINT64_MAX (18446744073709551615ULL) + +#ifdef __GNUC__ + #define CHECK_RESULT __attribute__((__warn_unused_result__)) + #define INLINE __inline__ +#else + #define CHECK_RESULT + #define INLINE __inline +#endif + +#ifndef STATIC + #define STATIC static +#endif + +/** + * Values to identify major and minor version of UMP + */ +#define UMP_VERSION_MAJOR 2 +#define UMP_VERSION_MINOR 0 + +/** + * Typedef for a secure ID, a system wide identifier for UMP memory buffers. + */ +typedef int32_t ump_secure_id; + +/** + * Value to indicate an invalid secure Id. + */ +#define UMP_INVALID_SECURE_ID ((ump_secure_id)0) + +/** + * UMP error codes. + */ +typedef enum +{ + UMP_OK = 0, /**< indicates success */ + UMP_ERROR = 1 /**< indicates failure */ +} ump_result; + +/** + * Allocation flag bits. + * + * ump_allocate accepts zero or more flags to specify the type of memory to allocate and how to expose it to devices. + * + * For each supported device there are 4 flags to control access permissions and give usage characteristic hints to optimize the allocation/mapping. + * They are; + * @li @a UMP_PROT__RD read permission + * @li @a UMP_PROT__WR write permission + * @li @a UMP_HINT__RD read often + * @li @a UMP_HINT__WR written often + * + * 5 devices are currently supported, with a device being the CPU itself. + * The other 4 devices will be mapped to real devices per SoC design. + * They are just named W,X,Y,Z by UMP as it has no knowledge of their real names/identifiers. + * As an example device W could be a camera device while device Z could be an ARM GPU device, leaving X and Y unused. + * + * 2 additional flags control the allocation; + * @li @a UMP_CONSTRAINT_PHYSICALLY_LINEAR the allocation must be physical linear. Typical for devices without an MMU and no IOMMU to help it. + * @li @a UMP_PROT_SHAREABLE the allocation can be shared with other processes on the system. Without this flag the returned allocation won't be resolvable in other processes. + * + * All UMP allocation are growable unless they're @a UMP_PROT_SHAREABLE. + * The hint bits should be used to indicate the access pattern so the driver can select the most optimal memory type and cache settings based on the what the system supports. + */ +typedef enum +{ + /* Generic helpers */ + UMP_PROT_DEVICE_RD = (1u << 0), + UMP_PROT_DEVICE_WR = (1u << 1), + UMP_HINT_DEVICE_RD = (1u << 2), + UMP_HINT_DEVICE_WR = (1u << 3), + UMP_DEVICE_MASK = 0xF, + UMP_DEVICE_CPU_SHIFT = 0, + UMP_DEVICE_W_SHIFT = 4, + UMP_DEVICE_X_SHIFT = 8, + UMP_DEVICE_Y_SHIFT = 12, + UMP_DEVICE_Z_SHIFT = 16, + + /* CPU protection and hints. */ + UMP_PROT_CPU_RD = (1u << 0), + UMP_PROT_CPU_WR = (1u << 1), + UMP_HINT_CPU_RD = (1u << 2), + UMP_HINT_CPU_WR = (1u << 3), + + /* device W */ + UMP_PROT_W_RD = (1u << 4), + UMP_PROT_W_WR = (1u << 5), + UMP_HINT_W_RD = (1u << 6), + UMP_HINT_W_WR = (1u << 7), + + /* device X */ + UMP_PROT_X_RD = (1u << 8), + UMP_PROT_X_WR = (1u << 9), + UMP_HINT_X_RD = (1u << 10), + UMP_HINT_X_WR = (1u << 11), + + /* device Y */ + UMP_PROT_Y_RD = (1u << 12), + UMP_PROT_Y_WR = (1u << 13), + UMP_HINT_Y_RD = (1u << 14), + UMP_HINT_Y_WR = (1u << 15), + + /* device Z */ + UMP_PROT_Z_RD = (1u << 16), + UMP_PROT_Z_WR = (1u << 17), + UMP_HINT_Z_RD = (1u << 18), + UMP_HINT_Z_WR = (1u << 19), + + /* 20-26 reserved for future use */ + UMPP_ALLOCBITS_UNUSED = (0x7Fu << 20), + /** Allocations marked as @ UMP_CONSTRAINT_UNCACHED won't be mapped as cached by the cpu */ + UMP_CONSTRAINT_UNCACHED = (1u << 27), + /** Require 32-bit physically addressable memory */ + UMP_CONSTRAINT_32BIT_ADDRESSABLE = (1u << 28), + /** For devices without an MMU and with no IOMMU assistance. */ + UMP_CONSTRAINT_PHYSICALLY_LINEAR = (1u << 29), + /** Shareable must be set to allow the allocation to be used by other processes, the default is non-shared */ + UMP_PROT_SHAREABLE = (1u << 30) + /* (1u << 31) should not be used to ensure compiler portability */ +} ump_allocation_bits; + +/** + * ump_allocation_bits combination argument type. + * + * Type used to pass zero or more bits from the @ref ump_allocation_bits enum + */ +typedef uint32_t ump_alloc_flags; + + +/** + * Default allocation flags for UMP v1 compatible allocations. + */ +#define UMP_V1_API_DEFAULT_ALLOCATION_FLAGS UMP_PROT_CPU_RD | UMP_PROT_CPU_WR | \ + UMP_PROT_W_RD | UMP_PROT_W_WR | \ + UMP_PROT_X_RD | UMP_PROT_X_WR | \ + UMP_PROT_Y_RD | UMP_PROT_Y_WR | \ + UMP_PROT_Z_RD | UMP_PROT_Z_WR | \ + UMP_PROT_SHAREABLE | \ + UMP_CONSTRAINT_32BIT_ADDRESSABLE + +/** + * CPU cache sync operations. + * + * Cache synchronization operations to pass to @ref ump_cpu_msync_now + */ +enum +{ + /** + * Cleans any dirty cache lines to main memory, but the data will still be available in the cache. + * After a clean the contents of memory is considered to be "owned" by the device. + * */ + UMP_MSYNC_CLEAN = 1, + + /** Cleans any dirty cache lines to main memory and Ejects all lines from the cache. + * After an clean&invalidate the contents of memory is considered to be "owned" by the CPU. + * Any subsequent access will fetch data from main memory. + * + * @note Due to CPUs doing speculative prefetching a UMP_MSYNC_CLEAN_AND_INVALIDATE must be done before and after interacting with hardware. + * */ + UMP_MSYNC_CLEAN_AND_INVALIDATE + +}; + +typedef uint32_t ump_cpu_msync_op; + +/** + * Memory import types supported. + * If new import types are added they will appear here. + * They must be added before UMPP_EXTERNAL_MEM_COUNT and + * must be assigned an explicit sequantial number. + * + * @li UMP_EXTERNAL_MEM_TYPE_ION - Import an ION allocation + * Takes a int* (pointer to a file descriptor) + * Another ION reference is taken which is released on the final ump_release + */ +enum ump_external_memory_type +{ + UMPP_EXTERNAL_MEM_TYPE_UNUSED = 0, /* reserve type 0 */ + UMP_EXTERNAL_MEM_TYPE_ION = 1, + UMPP_EXTERNAL_MEM_COUNT +}; + +/** @name UMP v1 API + * + *@{ + */ + +/** + * Allocation constraints. + * + * Allocation flags to pass @ref ump_ref_drv_allocate + * + * UMP v1 API only. + */ +typedef enum +{ + /** the allocation is mapped as noncached. */ + UMP_REF_DRV_CONSTRAINT_NONE = 0, + /** not supported. */ + UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1, + /** the allocation is mapped as cached by the cpu. */ + UMP_REF_DRV_CONSTRAINT_USE_CACHE = 4 +} ump_alloc_constraints; + +/* @} */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _UMP_COMMON_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-import.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-import.h new file mode 100644 index 0000000000000000000000000000000000000000..0641111afb6e9211c74ca389cd593154a804165f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-import.h @@ -0,0 +1,99 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_IMPORT_H_ +#define _UMP_IMPORT_H_ + +#include +#include + +/** + * UMP import module info. + * Contains information about the Linux module providing the import module, + * used to block unloading of the Linux module while imported memory exists. + * Lists the functions implementing the UMP import functions. + */ +struct ump_import_handler +{ + /** + * Linux module of the import handler + */ + struct module * linux_module; + + /** + * UMP session usage begin. + * + * Called when a UMP session first is bound to the handler. + * Typically used to set up any import module specific per-session data. + * The function returns a pointer to this data in the output pointer custom_session_data + * which will be passed to \a session_end and \a import. + * + * Note: custom_session_data must be set to non-NULL if successful. + * If no pointer is needed set it a magic value to validate instead. + * + * @param[out] custom_session_data Pointer to a generic pointer where any data can be stored + * @return 0 on success, error code if the session could not be initiated. + */ + int (*session_begin)(void ** custom_session_data); + + /** + * UMP session usage end. + * + * Called when a UMP session is no longer using the handler. + * Only called if @a session_begin returned OK. + * + * @param[in] custom_session_data The value set by the session_begin handler + */ + void (*session_end)(void * custom_session_data); + + /** + * Import request. + * + * Called when a client has asked to import a resource of the type the import module was installed for. + * Only called if @a session_begin returned OK. + * + * The requested flags must be verified to be valid to apply to the imported memory. + * If not valid return UMP_DD_INVALID_MEMORY_HANDLE. + * If the flags are found to be valid call \a ump_dd_create_from_phys_blocks_64 to create a handle. + * + * @param[in] custom_session_data The value set by the session_begin handler + * @param[in] phandle Pointer to the handle to import + * @param flags The requested UMPv2 flags to assign to the imported handle + * @return UMP_DD_INVALID_MEMORY_HANDLE if the import failed, a valid ump handle on success + */ + ump_dd_handle (*import)(void * custom_session_data, void * phandle, ump_alloc_flags flags); +}; + +/** + * Import module registration. + * Registers a ump_import_handler structure for a memory type. + * @param type Type of the memory to register a handler for + * @param[in] handler Handler strcture to install + * @return 0 on success, a Linux error code on failure + */ +int ump_import_module_register(enum ump_external_memory_type type, struct ump_import_handler * handler); + +/** + * Import module deregistration. + * Uninstalls the handler for the given memory type. + * @param type Type of the memory to unregister the handler for + */ +void ump_import_module_unregister(enum ump_external_memory_type type); + +#endif /* _UMP_IMPORT_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-ioctl.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-ioctl.h new file mode 100644 index 0000000000000000000000000000000000000000..a6219566ebb4febbde77ea32f89da609068ad21a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump-ioctl.h @@ -0,0 +1,152 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_IOCTL_H_ +#define _UMP_IOCTL_H + +#include + +/* + * The order and size of the members of these have been chosen so the structures look the same in 32-bit and 64-bit builds. + * If any changes are done build the ump_struct_size_checker test for 32-bit and 64-bit targets. Both must compile successfully to commit. + */ + +/** 32/64-bit neutral way to represent pointers */ +typedef union ump_pointer +{ + void * value; /**< client should store their pointers here */ + uint32_t compat_value; /**< 64-bit kernels should fetch value here when handling 32-bit clients */ + uint64_t sizer; /**< Force 64-bit storage for all clients regardless */ +} ump_pointer; + +/** + * UMP allocation request. + * Used when performing ump_allocate + */ +typedef struct ump_k_allocate +{ + uint64_t size; /**< [in] Size in bytes to allocate */ + ump_secure_id secure_id; /**< [out] Secure ID of allocation on success */ + ump_alloc_flags alloc_flags; /**< [in] Flags to use when allocating */ +} ump_k_allocate; + +/** + * UMP size query request. + * Used when performing ump_size_get + */ +typedef struct ump_k_sizequery +{ + uint64_t size; /**< [out] Size of allocation */ + ump_secure_id secure_id; /**< [in] ID of allocation to query the size of */ + uint32_t padding; /* don't remove */ +} ump_k_sizequery; + +/** + * UMP cache synchronization request. + * Used when performing ump_cpu_msync_now + */ +typedef struct ump_k_msync +{ + ump_pointer mapped_ptr; /**< [in] CPU VA to perform cache operation on */ + ump_secure_id secure_id; /**< [in] ID of allocation to perform cache operation on */ + ump_cpu_msync_op cache_operation; /**< [in] Cache operation to perform */ + uint64_t size; /**< [in] Size in bytes of the range to synchronize */ +} ump_k_msync; + +/** + * UMP memory retain request. + * Used when performing ump_retain + */ +typedef struct ump_k_retain +{ + ump_secure_id secure_id; /**< [in] ID of allocation to retain a reference to */ + uint32_t padding; /* don't remove */ +} ump_k_retain; + +/** + * UMP memory release request. + * Used when performing ump_release + */ +typedef struct ump_k_release +{ + ump_secure_id secure_id; /**< [in] ID of allocation to release a reference to */ + uint32_t padding; /* don't remove */ +} ump_k_release; + +typedef struct ump_k_import +{ + ump_pointer phandle; /**< [in] Pointer to handle to import */ + uint32_t type; /**< [in] Type of handle to import */ + ump_alloc_flags alloc_flags; /**< [in] Flags to assign to the imported memory */ + ump_secure_id secure_id; /**< [out] UMP ID representing the imported memory */ + uint32_t padding; /* don't remove */ +} ump_k_import; + +/** + * UMP allocation flags request. + * Used when performing umpp_get_allocation_flags + * + * used only by v1 API + */ +typedef struct ump_k_allocation_flags +{ + ump_secure_id secure_id; /**< [in] Secure ID of allocation on success */ + ump_alloc_flags alloc_flags; /**< [out] Flags to use when allocating */ +} ump_k_allocation_flags; + +#define UMP_CALL_MAX_SIZE 512 +/* + * Ioctl definitions + */ + +/* Use '~' as magic number */ + +#define UMP_IOC_MAGIC '~' + +#define UMP_FUNC_ALLOCATE _IOWR(UMP_IOC_MAGIC, 1, ump_k_allocate) +#define UMP_FUNC_SIZEQUERY _IOWR(UMP_IOC_MAGIC, 2, ump_k_sizequery) +#define UMP_FUNC_MSYNC _IOWR(UMP_IOC_MAGIC, 3, ump_k_msync) +#define UMP_FUNC_RETAIN _IOW(UMP_IOC_MAGIC, 4, ump_k_retain) +#define UMP_FUNC_RELEASE _IOW(UMP_IOC_MAGIC, 5, ump_k_release) +#define UMP_FUNC_ALLOCATION_FLAGS_GET _IOWR(UMP_IOC_MAGIC, 6, ump_k_allocation_flags) +#define UMP_FUNC_IMPORT _IOWR(UMP_IOC_MAGIC, 7, ump_k_import) + +/*max ioctl sequential number*/ +#define UMP_IOC_MAXNR 7 + +/* 15 bits for the UMP ID (allowing 32768 IDs) */ +#define UMP_LINUX_ID_BITS 15 +#define UMP_LINUX_ID_MASK ((1ULL << UMP_LINUX_ID_BITS) - 1ULL) + +/* 64-bit (really 52 bits) encoding: 15 bits for the ID, 37 bits for the offset */ +#define UMP_LINUX_OFFSET_BITS_64 37 +#define UMP_LINUX_OFFSET_MASK_64 ((1ULL << UMP_LINUX_OFFSET_BITS_64)-1) +/* 32-bit encoding: 15 bits for the ID, 17 bits for the offset */ +#define UMP_LINUX_OFFSET_BITS_32 17 +#define UMP_LINUX_OFFSET_MASK_32 ((1ULL << UMP_LINUX_OFFSET_BITS_32)-1) + +#if __SIZEOF_LONG__ == 8 +#define UMP_LINUX_OFFSET_BITS UMP_LINUX_OFFSET_BITS_64 +#define UMP_LINUX_OFFSET_MASK UMP_LINUX_OFFSET_MASK_64 +#else +#define UMP_LINUX_OFFSET_BITS UMP_LINUX_OFFSET_BITS_32 +#define UMP_LINUX_OFFSET_MASK UMP_LINUX_OFFSET_MASK_32 +#endif + +#endif /* _UMP_IOCTL_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump.h b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump.h new file mode 100644 index 0000000000000000000000000000000000000000..423ba852a84109671723f6ddc6f10491dc67b110 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/include/linux/ump.h @@ -0,0 +1,481 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * + * This file contains the kernel space part of the UMP API. + * + */ + +#ifndef _UMP_KERNEL_INTERFACE_H_ +#define _UMP_KERNEL_INTERFACE_H_ + +/** + * @addtogroup ump_api + * @{ + */ + +/** @defgroup ump_kernel_space_api UMP Kernel Space API + * @{ */ + +/** + * External representation of a UMP handle in kernel space. + */ +typedef void * ump_dd_handle; + +#ifdef CONFIG_KDS +#include +#endif + +#include + +#define UMP_KERNEL_API_EXPORT + +#if defined(__KERNEL__) +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Value to indicate an invalid UMP memory handle. + */ +#define UMP_DD_INVALID_MEMORY_HANDLE ((ump_dd_handle)0) + +/** + * Struct used to describe a physical block used by UMP memory + */ +typedef struct ump_dd_physical_block_64 +{ + uint64_t addr; /**< The physical address of the block */ + uint64_t size; /**< The length of the block, in bytes, typically page aligned */ +} ump_dd_physical_block_64; + +/** + * Security filter hook. + * + * Each allocation can have a security filter attached to it.@n + * The hook receives + * @li the secure ID + * @li a handle to the allocation + * @li the callback_data argument provided to @ref ump_dd_allocate_64 or @ref ump_dd_create_from_phys_blocks_64 + * + * The hook must return @a MALI_TRUE to indicate that access to the handle is allowed or @n + * @a MALI_FALSE to state that no access is permitted.@n + * This hook is guaranteed to be called in the context of the requesting process/address space. + * + * The arguments provided to the hook are; + * @li the secure ID + * @li handle to the allocation + * @li the callback_data set when registering the hook + * + * Return value; + * @li @a TRUE to permit access + * @li @a FALSE to deny access + */ +typedef bool (*ump_dd_security_filter)(ump_secure_id, ump_dd_handle, void *); + +/** + * Final release notify hook. + * + * Allocations can have a hook attached to them which is called when the last reference to the allocation is released. + * No reference count manipulation is allowed on the provided handle, just property querying (ID get, size get, phys block get). + * This is similar to finalizers in OO languages. + * + * The arguments provided to the hook are; + * * handle to the allocation + * * the callback_data set when registering the hook + */ +typedef void (*ump_dd_final_release_callback)(const ump_dd_handle, void *); + +/** + * Allocate a buffer. + * The lifetime of the allocation is controlled by a reference count. + * The reference count of the returned buffer is set to 1. + * The memory will be freed once the reference count reaches 0. + * Use @ref ump_dd_retain and @ref ump_dd_release to control the reference count. + * @param size Number of bytes to allocate. Will be padded up to a multiple of the page size. + * @param flags Bit-wise OR of zero or more of the allocation flag bits. + * @param[in] filter_func Pointer to a function which will be called when an allocation is required from a + * secure id before the allocation itself is returned to user-space. + * NULL permitted if no need for a callback. + * @param[in] final_release_func Pointer to a function which will be called when the last reference is removed, + * just before the allocation is freed. NULL permitted if no need for a callback. + * @param[in] callback_data An opaque pointer which will be provided to @a filter_func and @a final_release_func + * @return Handle to the new allocation, or @a UMP_DD_INVALID_MEMORY_HANDLE on allocation failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_allocate_64(uint64_t size, ump_alloc_flags flags, ump_dd_security_filter filter_func, ump_dd_final_release_callback final_release_func, void* callback_data); + + +/** + * Allocation bits getter. + * Retrieves the allocation flags used when instantiating the given handle. + * Just a copy of the flag given to @ref ump_dd_allocate_64 and @ref ump_dd_create_from_phys_blocks_64 + * @param mem The handle retrieve the bits for + * @return The allocation bits used to instantiate the allocation + */ +UMP_KERNEL_API_EXPORT ump_alloc_flags ump_dd_allocation_flags_get(const ump_dd_handle mem); + + +/** + * Retrieves the secure ID for the specified UMP memory. + * + * This identifier is unique across the entire system, and uniquely identifies + * the specified UMP memory allocation. This identifier can later be used through the + * @ref ump_dd_from_secure_id or + * @ref ump_from_secure_id + * functions in order to access this UMP memory, for instance from another process (if shared of course). + * Unless the allocation was marked as shared the returned ID will only be resolvable in the same process as did the allocation. + * + * Calling on an @a UMP_DD_INVALID_MEMORY_HANDLE will result in undefined behavior. + * Debug builds will assert on this. + * + * @note There is a user space equivalent function called @ref ump_secure_id_get + * + * @see ump_dd_from_secure_id + * @see ump_from_secure_id + * @see ump_secure_id_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the secure ID for the specified UMP memory. + */ +UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(const ump_dd_handle mem); + +#ifdef CONFIG_KDS +/** + * Retrieve the KDS resource for the specified UMP memory. + * + * The KDS resource should be used to synchronize access to the UMP allocation. + * See the KDS API for how to do that. + * + * @param mem Handle to the UMP memory to query. + * @return Pointer to the KDS resource controlling access to the UMP memory. + */ +UMP_KERNEL_API_EXPORT struct kds_resource * ump_dd_kds_resource_get(const ump_dd_handle mem); +#endif + +/** + * Retrieves a handle to allocated UMP memory. + * + * The usage of UMP memory is reference counted, so this will increment the reference + * count by one for the specified UMP memory. + * Use @ref ump_dd_release when there is no longer any + * use for the retrieved handle. + * + * If called on an non-shared allocation and this is a different process @a UMP_DD_INVALID_MEMORY_HANDLE will be returned. + * + * Calling on an @a UMP_INVALID_SECURE_ID will return @a UMP_DD_INVALID_MEMORY_HANDLE + * + * @note There is a user space equivalent function called @ref ump_from_secure_id + * + * @see ump_dd_release + * @see ump_from_secure_id + * + * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get function. + * + * @return @a UMP_DD_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_from_secure_id(ump_secure_id secure_id); + + +/** + * Retrieves all physical memory block information for specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * This function will return a pointer to an array of @ref ump_dd_physical_block_64 in @a pArray and the number of array elements in @a pCount + * + * Calling on an @a UMP_DD_INVALID_MEMORY_HANDLE results in undefined behavior. + * Debug builds will assert on this. + * + * @param mem Handle to UMP memory. + * @param[out] pCount Pointer to where to store the number of items in the returned array + * @param[out] pArray Pointer to where to store a pointer to the physical blocks array + */ +UMP_KERNEL_API_EXPORT void ump_dd_phys_blocks_get_64(const ump_dd_handle mem, uint64_t * const pCount, const ump_dd_physical_block_64 ** const pArray); + +/** + * Retrieves the actual size of the specified UMP memory. + * + * The size is reported in bytes, and is typically page aligned. + * + * Calling on an @a UMP_DD_INVALID_MEMORY_HANDLE results in undefined behavior. + * Debug builds will assert on this. + * + * @note There is a user space equivalent function called @ref ump_size_get + * + * @see ump_size_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the allocated size of the specified UMP memory, in bytes. + */ +UMP_KERNEL_API_EXPORT uint64_t ump_dd_size_get_64(const ump_dd_handle mem); + + +/** + * Adds an extra reference to the specified UMP memory allocation. + * + * The function @ref ump_dd_release must then be used + * to release each copy of the UMP memory handle. + * + * Calling on an @a UMP_DD_INVALID_MEMORY_HANDLE results in undefined behavior. + * Debug builds will assert on this. + * + * @note You are not required to call @ref ump_dd_retain + * for UMP handles returned from + * @ref ump_dd_from_secure_id, + * because these handles are already reference counted by this function. + * + * @note There is a user space equivalent function called @ref ump_retain + * + * @see ump_retain + * + * @param mem Handle to UMP memory. + * @return 0 indicates success, any other value indicates failure. + */ +UMP_KERNEL_API_EXPORT int ump_dd_retain(ump_dd_handle mem); + + +/** + * Releases a reference from the specified UMP memory. + * + * This function must be called once for every reference to the UMP memory handle. + * When the last reference is released, all resources associated with this UMP memory + * handle are freed. + * + * One can only call ump_release when matched with a successful ump_dd_retain, ump_dd_allocate_64 or ump_dd_from_secure_id + * If called on an @a UMP_DD_INVALID_MEMORY_HANDLE the function will early out. + * + * @note There is a user space equivalent function called @ref ump_release + * + * @see ump_release + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_release(ump_dd_handle mem); + +/** + * Create an ump allocation handle based on externally managed memory. + * Used to wrap an existing allocation as an UMP memory handle. + * Once wrapped the memory acts just like a normal allocation coming from @ref ump_dd_allocate_64. + * The only exception is that the freed physical memory is not put into the pool of free memory, but instead considered returned to the caller once @a final_release_func returns. + * The blocks array will be copied, so no need to hold on to it after this function returns. + * @param[in] blocks Array of @ref ump_dd_physical_block_64 + * @param num_blocks Number of elements in the array pointed to by @a blocks + * @param flags Allocation flags to mark the handle with + * @param[in] filter_func Pointer to a function which will be called when an allocation is required from a secure id before the allocation itself is returned to user-space. + * NULL permitted if no need for a callback. + * @param[in] final_release_func Pointer to a function which will be called when the last reference is removed, just before the allocation is freed. NULL permitted if no need for a callback. + * @param[in] callback_data An opaque pointer which will be provided to @a filter_func and @a final_release_func + * @return Handle to the UMP allocation handle created, or @a UMP_DD_INVALID_MEMORY_HANDLE if no such handle could be created. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_create_from_phys_blocks_64(const ump_dd_physical_block_64 * blocks, uint64_t num_blocks, ump_alloc_flags flags, ump_dd_security_filter filter_func, ump_dd_final_release_callback final_release_func, void* callback_data); + + +/** @name UMP v1 API + * Functions provided to support compatibility with UMP v1 API + * + *@{ + */ + +/** + * Value to indicate an invalid UMP memory handle. + */ +#define UMP_DD_HANDLE_INVALID UMP_DD_INVALID_MEMORY_HANDLE + +/** + * UMP error codes for kernel space. + */ +typedef enum +{ + UMP_DD_SUCCESS, /**< indicates success */ + UMP_DD_INVALID /**< indicates failure */ +} ump_dd_status_code; + + +/** + * Struct used to describe a physical block used by UMP memory + */ +typedef struct ump_dd_physical_block +{ + unsigned long addr; /**< The physical address of the block */ + unsigned long size; /**< The length of the block, typically page aligned */ +} ump_dd_physical_block; + + +/** + * Retrieves a handle to allocated UMP memory. + * + * The usage of UMP memory is reference counted, so this will increment the reference + * count by one for the specified UMP memory. + * Use @ref ump_dd_reference_release "ump_dd_reference_release" when there is no longer any + * use for the retrieved handle. + * + * @note There is a user space equivalent function called @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" + * + * @see ump_dd_reference_release + * @see ump_handle_create_from_secure_id + * + * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function. + * + * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id); + + + +/** + * Create an ump allocation handle based on externally managed memory. + * Used to wrap an existing allocation as an UMP memory handle. + * + * @param[in] blocks Array of @ref ump_dd_physical_block + * @param num_blocks Number of elements in the array pointed to by @a blocks + * + * @return Handle to the UMP allocation handle created, or @a UMP_DD_INVALID_MEMORY_HANDLE if no such handle could be created. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks); + + +/** + * Retrieves the number of physical blocks used by the specified UMP memory. + * + * This function retrieves the number of @ref ump_dd_physical_block "ump_dd_physical_block" structs needed + * to describe the physical memory layout of the given UMP memory. This can later be used when calling + * the functions @ref ump_dd_phys_blocks_get "ump_dd_phys_blocks_get" and + * @ref ump_dd_phys_block_get "ump_dd_phys_block_get". + * + * @see ump_dd_phys_blocks_get + * @see ump_dd_phys_block_get + * + * @param mem Handle to UMP memory. + * + * @return The number of ump_dd_physical_block structs required to describe the physical memory layout of the specified UMP memory. + */ +UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem); + + +/** + * Retrieves all physical memory block information for specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * + * @note This function will fail if the num_blocks parameter is either to large or to small. + * + * @see ump_dd_phys_block_get + * + * @param mem Handle to UMP memory. + * @param blocks An array of @ref ump_dd_physical_block "ump_dd_physical_block" structs that will receive the physical description. + * @param num_blocks The number of blocks to return in the blocks array. Use the function + * @ref ump_dd_phys_block_count_get "ump_dd_phys_block_count_get" first to determine the number of blocks required. + * + * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block * const blocks, unsigned long num_blocks); + + +/** + * Retrieves the physical memory block information for specified block for the specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * + * @note This function will return UMP_DD_INVALID if the specified index is out of range. + * + * @see ump_dd_phys_blocks_get + * + * @param mem Handle to UMP memory. + * @param index Which physical info block to retrieve. + * @param block Pointer to a @ref ump_dd_physical_block "ump_dd_physical_block" struct which will receive the requested information. + * + * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block * const block); + + +/** + * Retrieves the actual size of the specified UMP memory. + * + * The size is reported in bytes, and is typically page aligned. + * + * @note There is a user space equivalent function called @ref ump_size_get "ump_size_get" + * + * @see ump_size_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the allocated size of the specified UMP memory, in bytes. + */ +UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle mem); + + +/** + * Adds an extra reference to the specified UMP memory. + * + * This function adds an extra reference to the specified UMP memory. This function should + * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_dd_handle + * variable. The function @ref ump_dd_reference_release "ump_dd_reference_release" must then be used + * to release each copy of the UMP memory handle. + * + * @note You are not required to call @ref ump_dd_reference_add "ump_dd_reference_add" + * for UMP handles returned from + * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id", + * because these handles are already reference counted by this function. + * + * @note There is a user space equivalent function called @ref ump_reference_add "ump_reference_add" + * + * @see ump_reference_add + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle mem); + + +/** + * Releases a reference from the specified UMP memory. + * + * This function should be called once for every reference to the UMP memory handle. + * When the last reference is released, all resources associated with this UMP memory + * handle are freed. + * + * @note There is a user space equivalent function called @ref ump_reference_release "ump_reference_release" + * + * @see ump_reference_release + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle mem); + +/* @} */ + +#ifdef __cplusplus +} +#endif + + +/** @} */ /* end group ump_kernel_space_api */ + +/** @} */ /* end group ump_api */ + +#endif /* _UMP_KERNEL_INTERFACE_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-EAC/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..0fa60e2da7cf59ab0a744d383014826b43df5e22 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-EAC/sconscript @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +Import('env') + +if env['backend'] == 'kernel' and int(env['kernel_modules']) == 1: + SConscript('drivers/sconscript') + + if Glob('tests/sconscript'): + SConscript('tests/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/devicetree/bindings/arm/mali-midgard.txt b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/devicetree/bindings/arm/mali-midgard.txt new file mode 100755 index 0000000000000000000000000000000000000000..fb0a992c875a5385e6b8da5d0726321abd3015d8 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/devicetree/bindings/arm/mali-midgard.txt @@ -0,0 +1,43 @@ +# +# (C) COPYRIGHT 2013-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +* ARM Mali Midgard devices + + +Required properties: + +- compatible : Should be mali, replacing digits with x from the back, +until malitxx, ending with arm,mali-midgard, the latter not optional. +- reg : Physical base address of the device and length of the register area. +- interrupts : Contains the three IRQ lines required by T-6xx devices +- interrupt-names : Contains the names of IRQ resources in the order they were +provided in the interrupts property. Must contain: "JOB, "MMU", "GPU". + +Optional: + +- clocks : Phandle to clock for the Mali T-6xx device. +- clock-names : Shall be "clk_mali". + +Example for a Mali-T602: + +gpu@0xfc010000 { + compatible = "arm,malit602", "arm,malit60x", "arm,malit6xx", "arm,mali-midgard"; + reg = <0xfc010000 0x4000>; + interrupts = <0 36 4>, <0 37 4>, <0 38 4>; + interrupt-names = "JOB", "MMU", "GPU"; + + clocks = <&pclk_mali>; + clock-names = "clk_mali"; +}; diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/dma-buf-test-exporter.txt b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/dma-buf-test-exporter.txt new file mode 100755 index 0000000000000000000000000000000000000000..4208010cc78839fc18c3e9cad1a1ce5682cd4151 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/dma-buf-test-exporter.txt @@ -0,0 +1,40 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +===================== +dma-buf-test-exporter +===================== + +Overview +-------- + +The dma-buf-test-exporter is a simple exporter of dma_buf objects. +It has a private API to allocate and manipulate the buffers which are represented as dma_buf fds. +The private API allows: +* simple allocation of physically non-contiguous buffers +* simple allocation of physically contiguous buffers +* query kernel side API usage stats (number of attachments, number of mappings, mmaps) +* failure mode configuration (fail attach, mapping, mmap) +* kernel side memset of buffers + +The buffers support all of the dma_buf API, including mmap. + +It supports being compiled as a module both in-tree and out-of-tree. + +See include/linux/dma-buf-test-exporter.h for the ioctl interface. +See Documentation/dma-buf-sharing.txt for details on dma_buf. + + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/kds.txt b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/kds.txt new file mode 100755 index 0000000000000000000000000000000000000000..639288c106b7269e13100e0f3a0b0ab93d317864 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/Documentation/kds.txt @@ -0,0 +1,268 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +============================== +kds - Kernel Dependency System +============================== + +Introduction +------------ +kds provides a mechanism for clients to atomically lock down multiple abstract resources. +This can be done either synchronously or asynchronously. +Abstract resources is used to allow a set of clients to use kds to control access to any +resource, an example is structured memory buffers. + +kds supports that buffer is locked for exclusive access and sharing of buffers. + +kds can be built as either a integrated feature of the kernel or as a module. +It supports being compiled as a module both in-tree and out-of-tree. + + +Concepts +-------- +A core concept in kds is abstract resources. +A kds resource is just an abstraction for some client object, kds doesn't care what it is. +Typically EGL will consider UMP buffers as being a resource, thus each UMP buffer has +a kds resource for synchronization to the buffer. + +kds allows a client to create and destroy the abstract resource objects. +A new resource object is made available asap (it is just a simple malloc with some initializations), +while destroy it requires some external synchronization. + +The other core concept in kds is consumer of resources. +kds is requested to allow a client to consume a set of resources and the client will be notified when it can consume the resources. + +Exclusive access allows only one client to consume a resource. +Shared access permits multiple consumers to acceess a resource concurrently. + + +APIs +---- +kds provides simple resource allocate and destroy functions. +Clients use this to instantiate and control the lifetime of the resources kds manages. + +kds provides two ways to wait for resources: +- Asynchronous wait: the client specifies a function pointer to be called when wait is over +- Synchronous wait: Function blocks until access is gained. + +The synchronous API has a timeout for the wait. +The call can early out if a signal is delivered. + +After a client is done consuming the resource kds must be notified to release the resources and let some other client take ownership. +This is done via resource set release call. + +A Windows comparison: +kds implements WaitForMultipleObjectsEx(..., bWaitAll = TRUE, ...) but also has an asynchronous version in addition. +kds resources can be seen as being the same as NT object manager resources. + +Internals +--------- +kds guarantees atomicity when a set of resources is operated on. +This is implemented via a global resource lock which is taken by kds when it updates resource objects. + +Internally a resource in kds is a linked list head with some flags. + +When a consumer requests access to a set of resources it is queued on each of the resources. +The link from the consumer to the resources can be triggered. Once all links are triggered +the registered callback is called or the blocking function returns. +A link is considered triggered if it is the first on the list of consumers of a resource, +or if all the links ahead of it is marked as shared and itself is of the type shared. + +When the client is done consuming the consumer object is removed from the linked lists of +the resources and a potential new consumer becomes the head of the resources. +As we add and remove consumers atomically across all resources we can guarantee that +we never introduces a A->B + B->A type of loops/deadlocks. + + +kbase/base implementation +------------------------- +A HW job needs access to a set of shared resources. +EGL tracks this and encodes the set along with the atom in the ringbuffer. +EGL allocates a (k)base dep object to represent the dependency to the set of resources and encodes that along with the list of resources. +This dep object is use to create a dependency from a job chain(atom) to the resources it needs to run. +When kbase decodes the atom in the ringbuffer it finds the set of resources and calls kds to request all the needed resources. +As EGL needs to know when the kds request is delivered a new base event object is needed: atom enqueued. This event is only delivered for atoms which uses kds. +The callback kbase registers trigger the dependency object described which would trigger the existing JD system to release the job chain. +When the atom is done kds resource set release is call to release the resources. + +EGL will typically use exclusive access to the render target, while all buffers used as input can be marked as shared. + + +Buffer publish/vsync +-------------------- +EGL will use a separate ioctl or DRM flip to request the flip. +If the LCD driver is integrated with kds EGL can do these operations early. +The LCD driver must then implement the ioctl or DRM flip to be asynchronous with kds async call. +The LCD driver binds a kds resource to each virtual buffer (2 buffers in case of double-buffering). +EGL will make a dependency to the target kds resource in the kbase atom. +After EGL receives a atom enqueued event it can ask the LCD driver to pan to the target kds resource. +When the atom is completed it'll release the resource and the LCD driver will get its callback. +In the callback it'll load the target buffer into the DMA unit of the LCD hardware. +The LCD driver will be the consumer of both buffers for a short period. +The LCD driver will call kds resource set release on the previous on-screen buffer when the next vsync/dma read end is handled. + +=============================================== +Kernel driver kds client design considerations +=============================================== + +Number of resources +-------------------- + +The kds api allows a client to wait for ownership of a number of resources, where by the client does not take on ownership of any of the resources in the resource set +until all of the resources in the set are released. Consideration must be made with respect to performance, as waiting on large number of resources will incur +a greater overhead and may increase system latency. It may be worth considering how independent each of the resources are, for example if the same set of resources +are waited upon by each of the clients, then it may be possible to aggregate these into one resource that each client waits upon. + +Clients with shared access +--------------------------- + +The kds api allows a number of clients to gain shared access to a resource simultaneously, consideration must be made with respect to performance, large numbers of clients +wanting shared access can incur a performance penalty and may increase system latency, specifically when the clients are granted access. Having an excessively high +number of clients with shared access should be avoided, consideration should be made to the call back configuration being used. See Callbacks and Scenario 1 below. + +Callbacks +---------- + +Careful consideration must be made as to which callback type is most appropriate for kds clients, direct callbacks are called immediately from the context in which the +ownership of the resource is passed to the next waiter in the list. Where as when using deferred callbacks the callback is deferred and called from outside the context +that is relinquishing ownership, while this reduces the latency in the releasing clients context it does incur a cost as there is more latency between a resource +becoming free and the new client owning the resource callback being executed. + +Obviously direct callbacks have a performance advantage, as the call back is immediate and does not have to wait for the kernel to context switch to schedule in the +execution of the callback. + +However as the callback is immediate and within the context that is granting ownership it is important that the callback perform the MINIMUM amount of work necessary, +long call backs could cause poor system latency. Special care and attention must be taken if the direct callbacks can be called from IRQ handlers, such as when +kds_resource_set_release is called from an IRQ handler, in this case you have to avoid any calls that may sleep. + +Deferred contexts have the advantage that the call backs are deferred until they are scheduled by the kernel, therefore they are allowed to call functions that may sleep +and if scheduled from IRQ context not incur as much system latency as would be seen with direct callbacks from within the IRQ. + +Once the clients callback has been called, the client is considered to be owning the resource. Within the callback the client may only need to perform a small amount of work +before the client need to give up owner ship. The kds_resource_release function may be called from with in the call back, but consideration must be made when using direct +callbacks, with both respect to execution time and stack usage. Consider the example in Scenario 2 with direct callbacks: + +Scenario 1 - Shared client access - direct callbacks: + +Resources: X +Clients: A(S), B(S), C(S), D(S), E(E) +where: (S) = shared user, (E) = exclusive + +Clients kds callback handler: + +client__cb( p1, p2 ) +{ +} + +Where is either A,B,C,D + Queue |Owner +1. E Requests X exclusive | +2. E Owns X exclusive |E +3. A Requests X shared A|E +4. B Requests X shared BA|E +5. C Requests X shared CBA|E +6. D Requests X shared DCBA|E +7. E Releases X |DCBA +8. A Owns X shared |DCBA +9. B Owns X shared |DCBA +10. C Owns X shared |DCBA +11. D Owns X shared |DCBA + +At point 7 it is important to note that when E releases X; A,B,C and D become the new shared owners of X and the call back for each of the client(A,B,C,D) triggered, so consideration +must be made as to whether a direct or deferred callback is suitable, using direct callbacks would result in the call graph. + +Call graph when E releases X: + kds_resource_set_release( .. ) + +->client_A_cb( .. ) + +->client_B_cb( .. ) + +->client_C_cb( .. ) + +->client_D_cb( .. ) + + +Scenario 2 - Immediate resource release - direct callbacks: + +Resource: X +Clients: A, B, C, D + +Clients kds callback handler: + +client__cb( p1, p2 ) +{ + kds_resource_set_release( .. ); +} + +Where is either A,B,C,D + +1. A Owns X exclusive +2. B Requests X exclusive (direct callback) +3. C Requests X exclusive (direct callback) +4. D Requests X exclusive (direct callback) +5. A Releases X + +Call graph when A releases X: + kds_resource_set_release( .. ) + +->client_B_cb( .. ) + +->kds_resource_set_release( .. ) + +->client_C_cb( .. ) + +->kds_resource_set_release( .. ) + +->client_D_cb( .. ) + +As can be seen when a client releases the resource, with direct call backs it is possible to create nested calls + +IRQ Considerations +------------------- + +Usage of kds_resource_release in IRQ handlers should be carefully considered. + +Things to keep in mind: + +1.) Are you using direct or deferred callbacks? +2.) How many resources are you releasing? +3.) How many shared waiters are pending on the resource? + +Releasing ownership and wait cancellation +------------------------------------------ + +Client Wait Cancellation +------------------------- + +It may be necessary in certain circumstances for the client to cancel the wait for kds resources for error handling, process termination etc. Cancellation is +performed using kds_resource_set_release or kds_resource_set_release_sync using the rset that was received from kds_async_waitall, kds_resource_set_release_sync +being used for waits which are using deferred callbacks. + +It is possible that while the request to cancel the wait is being issued by the client, the client is granted access to the resources. Normally after the client +has taken ownership and finishes with that resource, it will release ownership to signal other waiters which are pending, this causes a race with the cancellation. +To prevent KDS trying to remove a wait twice from the internal list and accessing memory that is potentially freed, it is very important that all releasers use the +same rset pointer. Here is a simplified example of bad usage that must be avoided in any client implementation: + +Senario 3 - Bad release from multiple contexts: + + This scenaro is highlighting bad usage of the kds API + + kds_resource_set * rset; + kds_resource_set * rset_copy; + + kds_async_waitall( &rset, ... ... ... ); + + /* Don't do this */ + rset_copy = rset; + +Context A: + kds_resource_set_release( &rset ) + +Context B: + kds_resource_set_release( &rset_copy ) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..c82fcc684d88cd1e3809209fb30faaff24d62822 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += gpu/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..05908b2d589bababf064c2e3c48ff792c4ea1cb3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/sconscript @@ -0,0 +1,27 @@ +# +# (C) COPYRIGHT 2012, 2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +import os +import re +Import('env') + +linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' +search_term = '^[\ ]*CONFIG_DMA_SHARED_BUFFER_USES_KDS[\ ]*=[\ ]*y' +for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + SConscript( 'src/sconscript' ) + if Glob('tests/sconscript'): + SConscript( 'tests/sconscript' ) + break diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..68dad07ad6077a511c433f2a2edca84bdb500913 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +ifneq ($(CONFIG_DMA_SHARED_BUFFER),) +obj-m := dma_buf_lock.o +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..cf76132e6dde7f870d63609d0d2e0f36367c2c70 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/Makefile @@ -0,0 +1,32 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: dma_buf_lock + +dma_buf_lock: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../include" + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.c new file mode 100644 index 0000000000000000000000000000000000000000..658218273db972091eb04b87beccfef135d1af97 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.c @@ -0,0 +1,481 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dma_buf_lock.h" + +/* Maximum number of buffers that a single handle can address */ +#define DMA_BUF_LOCK_BUF_MAX 32 + +#define DMA_BUF_LOCK_DEBUG 1 + +static dev_t dma_buf_lock_dev; +static struct cdev dma_buf_lock_cdev; +static struct class *dma_buf_lock_class; +static char dma_buf_lock_dev_name[] = "dma_buf_lock"; + +#ifdef HAVE_UNLOCKED_IOCTL +static long dma_buf_lock_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +static int dma_buf_lock_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif + +static struct file_operations dma_buf_lock_fops = +{ + .owner = THIS_MODULE, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = dma_buf_lock_ioctl, +#else + .ioctl = dma_buf_lock_ioctl, +#endif + .compat_ioctl = dma_buf_lock_ioctl, +}; + +typedef struct dma_buf_lock_resource +{ + int *list_of_dma_buf_fds; /* List of buffers copied from userspace */ + atomic_t locked; /* Status of lock */ + struct dma_buf **dma_bufs; + struct kds_resource **kds_resources; /* List of KDS resources associated with buffers */ + struct kds_resource_set *resource_set; + unsigned long exclusive; /* Exclusive access bitmap */ + wait_queue_head_t wait; + struct kds_callback cb; + struct kref refcount; + struct list_head link; + int count; +} dma_buf_lock_resource; + +static LIST_HEAD(dma_buf_lock_resource_list); +static DEFINE_MUTEX(dma_buf_lock_mutex); + +static inline int is_dma_buf_lock_file(struct file *); +static void dma_buf_lock_dounlock(struct kref *ref); + +static int dma_buf_lock_handle_release(struct inode *inode, struct file *file) +{ + dma_buf_lock_resource *resource; + + if (!is_dma_buf_lock_file(file)) + return -EINVAL; + + resource = file->private_data; +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_handle_release\n"); +#endif + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + + return 0; +} + +static void dma_buf_lock_kds_callback(void *param1, void *param2) +{ + dma_buf_lock_resource *resource = param1; +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_kds_callback\n"); +#endif + atomic_set(&resource->locked, 1); + + wake_up(&resource->wait); +} + +static unsigned int dma_buf_lock_handle_poll(struct file *file, + struct poll_table_struct *wait) +{ + dma_buf_lock_resource *resource; + unsigned int ret = 0; + + if (!is_dma_buf_lock_file(file)) + return POLLERR; + + resource = file->private_data; +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_handle_poll\n"); +#endif + if (1 == atomic_read(&resource->locked)) + { + /* Resources have been locked */ + ret = POLLIN | POLLRDNORM; + if (resource->exclusive) + { + ret |= POLLOUT | POLLWRNORM; + } + } + else + { + if (!poll_does_not_wait(wait)) + { + poll_wait(file, &resource->wait, wait); + } + } +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_handle_poll : return %i\n", ret); +#endif + return ret; +} + +static const struct file_operations dma_buf_lock_handle_fops = { + .release = dma_buf_lock_handle_release, + .poll = dma_buf_lock_handle_poll, +}; + +/* + * is_dma_buf_lock_file - Check if struct file* is associated with dma_buf_lock + */ +static inline int is_dma_buf_lock_file(struct file *file) +{ + return file->f_op == &dma_buf_lock_handle_fops; +} + + + +/* + * Start requested lock. + * + * Allocates required memory, copies dma_buf_fd list from userspace, + * acquires related KDS resources, and starts the lock. + */ +static int dma_buf_lock_dolock(dma_buf_lock_k_request *request) +{ + dma_buf_lock_resource *resource; + int size; + int fd; + int i; + int ret; + + if (NULL == request->list_of_dma_buf_fds) + { + return -EINVAL; + } + if (request->count <= 0) + { + return -EINVAL; + } + if (request->count > DMA_BUF_LOCK_BUF_MAX) + { + return -EINVAL; + } + if (request->exclusive != DMA_BUF_LOCK_NONEXCLUSIVE && + request->exclusive != DMA_BUF_LOCK_EXCLUSIVE) + { + return -EINVAL; + } + + resource = kzalloc(sizeof(dma_buf_lock_resource), GFP_KERNEL); + if (NULL == resource) + { + return -ENOMEM; + } + + atomic_set(&resource->locked, 0); + kref_init(&resource->refcount); + INIT_LIST_HEAD(&resource->link); + resource->count = request->count; + + /* Allocate space to store dma_buf_fds received from user space */ + size = request->count * sizeof(int); + resource->list_of_dma_buf_fds = kmalloc(size, GFP_KERNEL); + + if (NULL == resource->list_of_dma_buf_fds) + { + kfree(resource); + return -ENOMEM; + } + + /* Allocate space to store dma_buf pointers associated with dma_buf_fds */ + size = sizeof(struct dma_buf *) * request->count; + resource->dma_bufs = kmalloc(size, GFP_KERNEL); + + if (NULL == resource->dma_bufs) + { + kfree(resource->list_of_dma_buf_fds); + kfree(resource); + return -ENOMEM; + } + /* Allocate space to store kds_resources associated with dma_buf_fds */ + size = sizeof(struct kds_resource *) * request->count; + resource->kds_resources = kmalloc(size, GFP_KERNEL); + + if (NULL == resource->kds_resources) + { + kfree(resource->dma_bufs); + kfree(resource->list_of_dma_buf_fds); + kfree(resource); + return -ENOMEM; + } + + /* Copy requested list of dma_buf_fds from user space */ + size = request->count * sizeof(int); + if (0 != copy_from_user(resource->list_of_dma_buf_fds, (void __user *)request->list_of_dma_buf_fds, size)) + { + kfree(resource->list_of_dma_buf_fds); + kfree(resource->dma_bufs); + kfree(resource->kds_resources); + kfree(resource); + return -ENOMEM; + } +#if DMA_BUF_LOCK_DEBUG + for (i = 0; i < request->count; i++) + { + pr_debug("dma_buf %i = %X\n", i, resource->list_of_dma_buf_fds[i]); + } +#endif + + /* Add resource to global list */ + mutex_lock(&dma_buf_lock_mutex); + + list_add(&resource->link, &dma_buf_lock_resource_list); + + mutex_unlock(&dma_buf_lock_mutex); + + for (i = 0; i < request->count; i++) + { + /* Convert fd into dma_buf structure */ + resource->dma_bufs[i] = dma_buf_get(resource->list_of_dma_buf_fds[i]); + + if (IS_ERR_VALUE(PTR_ERR(resource->dma_bufs[i]))) + { + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + return -EINVAL; + } + + /*Get kds_resource associated with dma_buf */ + resource->kds_resources[i] = get_dma_buf_kds_resource(resource->dma_bufs[i]); + + if (NULL == resource->kds_resources[i]) + { + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + return -EINVAL; + } +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_dolock : dma_buf_fd %i dma_buf %X kds_resource %X\n", resource->list_of_dma_buf_fds[i], + (unsigned int)resource->dma_bufs[i], (unsigned int)resource->kds_resources[i]); +#endif + } + + kds_callback_init(&resource->cb, 1, dma_buf_lock_kds_callback); + init_waitqueue_head(&resource->wait); + + kref_get(&resource->refcount); + + /* Create file descriptor associated with lock request */ + fd = anon_inode_getfd("dma_buf_lock", &dma_buf_lock_handle_fops, + (void *)resource, 0); + if (fd < 0) + { + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + return fd; + } + + resource->exclusive = request->exclusive; + + /* Start locking process */ + ret = kds_async_waitall(&resource->resource_set, + &resource->cb, resource, NULL, + request->count, &resource->exclusive, + resource->kds_resources); + + if (IS_ERR_VALUE(ret)) + { + put_unused_fd(fd); + + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + + return ret; + } + +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_dolock : complete\n"); +#endif + mutex_lock(&dma_buf_lock_mutex); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + + return fd; +} + +static void dma_buf_lock_dounlock(struct kref *ref) +{ + int i; + dma_buf_lock_resource *resource = container_of(ref, dma_buf_lock_resource, refcount); + + atomic_set(&resource->locked, 0); + + kds_callback_term(&resource->cb); + + kds_resource_set_release(&resource->resource_set); + + list_del(&resource->link); + + for (i = 0; i < resource->count; i++) + { + dma_buf_put(resource->dma_bufs[i]); + } + + kfree(resource->kds_resources); + kfree(resource->dma_bufs); + kfree(resource->list_of_dma_buf_fds); + kfree(resource); +} + +static int __init dma_buf_lock_init(void) +{ + int err; +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_init\n"); +#endif + err = alloc_chrdev_region(&dma_buf_lock_dev, 0, 1, dma_buf_lock_dev_name); + + if (0 == err) + { + cdev_init(&dma_buf_lock_cdev, &dma_buf_lock_fops); + + err = cdev_add(&dma_buf_lock_cdev, dma_buf_lock_dev, 1); + + if (0 == err) + { + dma_buf_lock_class = class_create(THIS_MODULE, dma_buf_lock_dev_name); + if (IS_ERR(dma_buf_lock_class)) + { + err = PTR_ERR(dma_buf_lock_class); + } + else + { + struct device *mdev; + mdev = device_create(dma_buf_lock_class, NULL, dma_buf_lock_dev, NULL, dma_buf_lock_dev_name); + if (!IS_ERR(mdev)) + { + return 0; + } + + err = PTR_ERR(mdev); + class_destroy(dma_buf_lock_class); + } + cdev_del(&dma_buf_lock_cdev); + } + + unregister_chrdev_region(dma_buf_lock_dev, 1); + } +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_init failed\n"); +#endif + return err; +} + +static void __exit dma_buf_lock_exit(void) +{ +#if DMA_BUF_LOCK_DEBUG + pr_debug("dma_buf_lock_exit\n"); +#endif + + /* Unlock all outstanding references */ + while (1) + { + mutex_lock(&dma_buf_lock_mutex); + if (list_empty(&dma_buf_lock_resource_list)) + { + mutex_unlock(&dma_buf_lock_mutex); + break; + } + else + { + dma_buf_lock_resource *resource = list_entry(dma_buf_lock_resource_list.next, + dma_buf_lock_resource, link); + kref_put(&resource->refcount, dma_buf_lock_dounlock); + mutex_unlock(&dma_buf_lock_mutex); + } + } + + device_destroy(dma_buf_lock_class, dma_buf_lock_dev); + + class_destroy(dma_buf_lock_class); + + cdev_del(&dma_buf_lock_cdev); + + unregister_chrdev_region(dma_buf_lock_dev, 1); +} + +#ifdef HAVE_UNLOCKED_IOCTL +static long dma_buf_lock_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +static int dma_buf_lock_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + dma_buf_lock_k_request request; + int size = _IOC_SIZE(cmd); + + if (_IOC_TYPE(cmd) != DMA_BUF_LOCK_IOC_MAGIC) + { + return -ENOTTY; + + } + if ((_IOC_NR(cmd) < DMA_BUF_LOCK_IOC_MINNR) || (_IOC_NR(cmd) > DMA_BUF_LOCK_IOC_MAXNR)) + { + return -ENOTTY; + } + + switch (cmd) + { + case DMA_BUF_LOCK_FUNC_LOCK_ASYNC: + if (size != sizeof(dma_buf_lock_k_request)) + { + return -ENOTTY; + } + if (copy_from_user(&request, (void __user *)arg, size)) + { + return -EFAULT; + } +#if DMA_BUF_LOCK_DEBUG + pr_debug("DMA_BUF_LOCK_FUNC_LOCK_ASYNC - %i\n", request.count); +#endif + return dma_buf_lock_dolock(&request); + } + + return -ENOTTY; +} + +module_init(dma_buf_lock_init); +module_exit(dma_buf_lock_exit); + +MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.h new file mode 100644 index 0000000000000000000000000000000000000000..5d248e8ccaed409d66f315da836e428383abedbd --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/dma_buf_lock.h @@ -0,0 +1,42 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _DMA_BUF_LOCK_H +#define _DMA_BUF_LOCK_H + +typedef enum dma_buf_lock_exclusive +{ + DMA_BUF_LOCK_NONEXCLUSIVE = 0, + DMA_BUF_LOCK_EXCLUSIVE = -1 +} dma_buf_lock_exclusive; + +typedef struct dma_buf_lock_k_request +{ + int count; + int *list_of_dma_buf_fds; + int timeout; + dma_buf_lock_exclusive exclusive; +} dma_buf_lock_k_request; + +#define DMA_BUF_LOCK_IOC_MAGIC '~' + +#define DMA_BUF_LOCK_FUNC_LOCK_ASYNC _IOW(DMA_BUF_LOCK_IOC_MAGIC, 11, dma_buf_lock_k_request) + +#define DMA_BUF_LOCK_IOC_MINNR 11 +#define DMA_BUF_LOCK_IOC_MAXNR 11 + +#endif /* _DMA_BUF_LOCK_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..251c9a6f53d50a9584e31789e5c2fa9ccd27bdd7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_lock/src/sconscript @@ -0,0 +1,36 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +import os +import re +Import('env') + +if env['v'] != '1': + env['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +src = [Glob('#kernel/drivers/base/dma_buf_lock/src/*.c'), Glob('#kernel/drivers/base/dma_buf_lock/src/*.h'), Glob('#kernel/drivers/base/dma_buf_lock/src/K*')] + +if env.GetOption('clean') : + # Clean module + env.Execute(Action("make clean", '[CLEAN] dma_buf_lock')) + cmd = env.Command('$STATIC_LIB_PATH/dma_buf_lock.ko', src, []) + env.ProgTarget('dma_buf_lock', cmd) + +else: + # Build module + makeAction=Action("cd ${SOURCE.dir} && make dma_buf_lock && cp dma_buf_lock.ko $STATIC_LIB_PATH/", '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/dma_buf_lock.ko', src, [makeAction]) + env.ProgTarget('dma_buf_lock', cmd) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..56b9f86d2d52acafd705bbfd0770dec588105618 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +ifneq ($(CONFIG_DMA_SHARED_BUFFER),) +obj-$(CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER) += dma-buf-test-exporter.o +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..974f0c23dbd272f1c8b72222665578090cb998c6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Kconfig @@ -0,0 +1,20 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +config DMA_SHARED_BUFFER_TEST_EXPORTER + tristate "Test exporter for the dma-buf framework" + depends on DMA_SHARED_BUFFER + help + This option enables the test exporter usable to help test importerts. diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..06e3d5c121a525d605c2b53ee5a51a2035fa9590 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/Makefile @@ -0,0 +1,30 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER=m + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c new file mode 100644 index 0000000000000000000000000000000000000000..375d48079c535c1f48e7878c5b00f65f3161d092 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c @@ -0,0 +1,617 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) +#include +#include +#endif + +struct dma_buf_te_alloc { + /* the real alloc */ + int nr_pages; + struct page **pages; + + /* the debug usage tracking */ + int nr_attached_devices; + int nr_device_mappings; + int nr_cpu_mappings; + + /* failure simulation */ + int fail_attach; + int fail_map; + int fail_mmap; + + bool contiguous; + dma_addr_t contig_dma_addr; + void *contig_cpu_addr; +}; + +static struct miscdevice te_device; + +static int dma_buf_te_attach(struct dma_buf *buf, struct device *dev, struct dma_buf_attachment *attachment) +{ + struct dma_buf_te_alloc *alloc; + alloc = buf->priv; + + if (alloc->fail_attach) + return -EFAULT; + + /* dma_buf is externally locked during call */ + alloc->nr_attached_devices++; + return 0; +} + +static void dma_buf_te_detach(struct dma_buf *buf, struct dma_buf_attachment *attachment) +{ + struct dma_buf_te_alloc *alloc; + alloc = buf->priv; + /* dma_buf is externally locked during call */ + + alloc->nr_attached_devices--; +} + +static struct sg_table *dma_buf_te_map(struct dma_buf_attachment *attachment, enum dma_data_direction direction) +{ + struct sg_table *sg; + struct scatterlist *iter; + struct dma_buf_te_alloc *alloc; + int i; + int ret; + + alloc = attachment->dmabuf->priv; + + if (alloc->fail_map) + return ERR_PTR(-ENOMEM); + +#ifndef ARCH_HAS_SG_CHAIN + /* if the ARCH can't chain we can't have allocs larger than a single sg can hold */ + if (alloc->nr_pages > SG_MAX_SINGLE_ALLOC) + return ERR_PTR(-EINVAL); +#endif + + sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!sg) + return ERR_PTR(-ENOMEM); + + /* from here we access the allocation object, so lock the dmabuf pointing to it */ + mutex_lock(&attachment->dmabuf->lock); + + if (alloc->contiguous) + ret = sg_alloc_table(sg, 1, GFP_KERNEL); + else + ret = sg_alloc_table(sg, alloc->nr_pages, GFP_KERNEL); + if (ret) { + mutex_unlock(&attachment->dmabuf->lock); + kfree(sg); + return ERR_PTR(ret); + } + + if (alloc->contiguous) { + sg_dma_len(sg->sgl) = alloc->nr_pages * PAGE_SIZE; + sg_set_page(sg->sgl, pfn_to_page(PFN_DOWN(alloc->contig_dma_addr)), alloc->nr_pages * PAGE_SIZE, 0); + sg_dma_address(sg->sgl) = alloc->contig_dma_addr; + } else { + for_each_sg(sg->sgl, iter, alloc->nr_pages, i) + sg_set_page(iter, alloc->pages[i], PAGE_SIZE, 0); + } + + if (!dma_map_sg(attachment->dev, sg->sgl, sg->nents, direction)) { + mutex_unlock(&attachment->dmabuf->lock); + sg_free_table(sg); + kfree(sg); + return ERR_PTR(-ENOMEM); + } + + alloc->nr_device_mappings++; + mutex_unlock(&attachment->dmabuf->lock); + return sg; +} + +static void dma_buf_te_unmap(struct dma_buf_attachment *attachment, + struct sg_table *sg, enum dma_data_direction direction) +{ + struct dma_buf_te_alloc *alloc; + + alloc = attachment->dmabuf->priv; + + dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, direction); + sg_free_table(sg); + kfree(sg); + + mutex_lock(&attachment->dmabuf->lock); + alloc->nr_device_mappings--; + mutex_unlock(&attachment->dmabuf->lock); +} + +static void dma_buf_te_release(struct dma_buf *buf) +{ + int i; + struct dma_buf_te_alloc *alloc; + alloc = buf->priv; + /* no need for locking */ + + dev_info(te_device.this_device, "%s", __func__); + + if (alloc->contiguous) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + DEFINE_DMA_ATTRS(attrs); + + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + dma_free_attrs(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + alloc->contig_cpu_addr, alloc->contig_dma_addr, &attrs); +#else + dma_free_writecombine(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + alloc->contig_cpu_addr, alloc->contig_dma_addr); +#endif + } else { + for (i = 0; i < alloc->nr_pages; i++) + __free_page(alloc->pages[i]); + } + kfree(alloc->pages); + kfree(alloc); +} + + +static void dma_buf_te_mmap_open(struct vm_area_struct *vma) +{ + struct dma_buf *dma_buf; + struct dma_buf_te_alloc *alloc; + dma_buf = vma->vm_private_data; + alloc = dma_buf->priv; + + mutex_lock(&dma_buf->lock); + alloc->nr_cpu_mappings++; + mutex_unlock(&dma_buf->lock); +} + +static void dma_buf_te_mmap_close(struct vm_area_struct *vma) +{ + struct dma_buf *dma_buf; + struct dma_buf_te_alloc *alloc; + dma_buf = vma->vm_private_data; + alloc = dma_buf->priv; + + BUG_ON(alloc->nr_cpu_mappings <= 0); + mutex_lock(&dma_buf->lock); + alloc->nr_cpu_mappings--; + mutex_unlock(&dma_buf->lock); +} + +static int dma_buf_te_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct dma_buf_te_alloc *alloc; + struct dma_buf *dmabuf; + struct page *pageptr; + + dmabuf = vma->vm_private_data; + alloc = dmabuf->priv; + + if (vmf->pgoff > alloc->nr_pages) + return VM_FAULT_SIGBUS; + + pageptr = alloc->pages[vmf->pgoff]; + + BUG_ON(!pageptr); + + get_page(pageptr); + vmf->page = pageptr; + + return 0; +} + +struct vm_operations_struct dma_buf_te_vm_ops = { + .open = dma_buf_te_mmap_open, + .close = dma_buf_te_mmap_close, + .fault = dma_buf_te_mmap_fault +}; + +static int dma_buf_te_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct dma_buf_te_alloc *alloc; + alloc = dmabuf->priv; + + if (alloc->fail_mmap) + return -ENOMEM; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; +#else + vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTEXPAND; +#endif + vma->vm_ops = &dma_buf_te_vm_ops; + vma->vm_private_data = dmabuf; + + /* we fault in the pages on access */ + + /* call open to do the ref-counting */ + dma_buf_te_vm_ops.open(vma); + + return 0; +} + +static void *dma_buf_te_kmap_atomic(struct dma_buf *buf, unsigned long page_num) +{ + /* IGNORE */ + return NULL; +} + +static void *dma_buf_te_kmap(struct dma_buf *buf, unsigned long page_num) +{ + /* IGNORE */ + return NULL; +} + +static struct dma_buf_ops dma_buf_te_ops = { + /* real handlers */ + .attach = dma_buf_te_attach, + .detach = dma_buf_te_detach, + .map_dma_buf = dma_buf_te_map, + .unmap_dma_buf = dma_buf_te_unmap, + .release = dma_buf_te_release, + .mmap = dma_buf_te_mmap, + + /* nop handlers for mandatory functions we ignore */ + .kmap_atomic = dma_buf_te_kmap_atomic, + .kmap = dma_buf_te_kmap +}; + +static int do_dma_buf_te_ioctl_version(struct dma_buf_te_ioctl_version __user *buf) +{ + struct dma_buf_te_ioctl_version v; + + if (copy_from_user(&v, buf, sizeof(v))) + return -EFAULT; + + if (v.op != DMA_BUF_TE_ENQ) + return -EFAULT; + + v.op = DMA_BUF_TE_ACK; + v.major = DMA_BUF_TE_VER_MAJOR; + v.minor = DMA_BUF_TE_VER_MINOR; + + if (copy_to_user(buf, &v, sizeof(v))) + return -EFAULT; + else + return 0; +} + +static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf, bool contiguous) +{ + struct dma_buf_te_ioctl_alloc alloc_req; + struct dma_buf_te_alloc *alloc; + struct dma_buf *dma_buf; + int i = 0; + int fd; + + if (copy_from_user(&alloc_req, buf, sizeof(alloc_req))) { + dev_err(te_device.this_device, "%s: couldn't get user data", __func__); + goto no_input; + } + + if (!alloc_req.size) { + dev_err(te_device.this_device, "%s: no size specified", __func__); + goto zero_size; + } + + alloc = kzalloc(sizeof(struct dma_buf_te_alloc), GFP_KERNEL); + if (NULL == alloc) { + dev_err(te_device.this_device, "%s: couldn't alloc object", __func__); + goto no_alloc_object; + } + + alloc->nr_pages = alloc_req.size; + alloc->contiguous = contiguous; + + alloc->pages = kzalloc(sizeof(struct page *) * alloc->nr_pages, GFP_KERNEL); + if (!alloc->pages) { + dev_err(te_device.this_device, + "%s: couldn't alloc %d page structures", __func__, + alloc->nr_pages); + goto free_alloc_object; + } + + if (contiguous) { + dma_addr_t dma_aux; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + DEFINE_DMA_ATTRS(attrs); + + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + alloc->contig_cpu_addr = dma_alloc_attrs(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + &alloc->contig_dma_addr, GFP_KERNEL, &attrs); +#else + alloc->contig_cpu_addr = dma_alloc_writecombine(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + &alloc->contig_dma_addr, GFP_KERNEL); +#endif + if (!alloc->contig_cpu_addr) { + dev_err(te_device.this_device, "%s: couldn't alloc contiguous buffer %d pages", __func__, alloc->nr_pages); + goto free_page_struct; + } + dma_aux = alloc->contig_dma_addr; + for (i = 0; i < alloc->nr_pages; i++) { + alloc->pages[i] = pfn_to_page(PFN_DOWN(dma_aux)); + dma_aux += PAGE_SIZE; + } + } else { + for (i = 0; i < alloc->nr_pages; i++) { + alloc->pages[i] = alloc_page(GFP_KERNEL); + if (NULL == alloc->pages[i]) { + dev_err(te_device.this_device, "%s: couldn't alloc page", __func__); + goto no_page; + } + } + } + + /* alloc ready, let's export it */ + dma_buf = dma_buf_export(alloc, &dma_buf_te_ops, alloc->nr_pages << PAGE_SHIFT, O_CLOEXEC|O_RDWR); + + if (IS_ERR_OR_NULL(dma_buf)) { + dev_err(te_device.this_device, "%s: couldn't export dma_buf", __func__); + goto no_export; + } + + /* get fd for buf */ + fd = dma_buf_fd(dma_buf, O_CLOEXEC); + + if (fd < 0) { + dev_err(te_device.this_device, "%s: couldn't get fd from dma_buf", __func__); + goto no_fd; + } + + return fd; + +no_fd: + dma_buf_put(dma_buf); +no_export: + /* i still valid */ +no_page: + if (contiguous) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + DEFINE_DMA_ATTRS(attrs); + + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + dma_free_attrs(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + alloc->contig_cpu_addr, alloc->contig_dma_addr, &attrs); +#else + dma_free_writecombine(te_device.this_device, + alloc->nr_pages * PAGE_SIZE, + alloc->contig_cpu_addr, alloc->contig_dma_addr); +#endif + } else { + while (i-- > 0) + __free_page(alloc->pages[i]); + } +free_page_struct: + kfree(alloc->pages); +free_alloc_object: + kfree(alloc); +no_alloc_object: +zero_size: +no_input: + return -EFAULT; +} + +static int do_dma_buf_te_ioctl_status(struct dma_buf_te_ioctl_status __user *arg) +{ + struct dma_buf_te_ioctl_status status; + struct dma_buf *dmabuf; + struct dma_buf_te_alloc *alloc; + int res = -EINVAL; + + if (copy_from_user(&status, arg, sizeof(status))) + return -EFAULT; + + dmabuf = dma_buf_get(status.fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EINVAL; + + /* verify it's one of ours */ + if (dmabuf->ops != &dma_buf_te_ops) + goto err_have_dmabuf; + + /* ours, get the current status */ + alloc = dmabuf->priv; + + /* lock while reading status to take a snapshot */ + mutex_lock(&dmabuf->lock); + status.attached_devices = alloc->nr_attached_devices; + status.device_mappings = alloc->nr_device_mappings; + status.cpu_mappings = alloc->nr_cpu_mappings; + mutex_unlock(&dmabuf->lock); + + if (copy_to_user(arg, &status, sizeof(status))) + goto err_have_dmabuf; + + /* All OK */ + res = 0; + +err_have_dmabuf: + dma_buf_put(dmabuf); + return res; +} + +static int do_dma_buf_te_ioctl_set_failing(struct dma_buf_te_ioctl_set_failing __user *arg) +{ + struct dma_buf *dmabuf; + struct dma_buf_te_ioctl_set_failing f; + struct dma_buf_te_alloc *alloc; + int res = -EINVAL; + + if (copy_from_user(&f, arg, sizeof(f))) + return -EFAULT; + + dmabuf = dma_buf_get(f.fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EINVAL; + + /* verify it's one of ours */ + if (dmabuf->ops != &dma_buf_te_ops) + goto err_have_dmabuf; + + /* ours, set the fail modes */ + alloc = dmabuf->priv; + /* lock to set the fail modes atomically */ + mutex_lock(&dmabuf->lock); + alloc->fail_attach = f.fail_attach; + alloc->fail_map = f.fail_map; + alloc->fail_mmap = f.fail_mmap; + mutex_unlock(&dmabuf->lock); + + /* success */ + res = 0; + +err_have_dmabuf: + dma_buf_put(dmabuf); + return res; +} + +static u32 dma_te_buf_fill(struct dma_buf *dma_buf, unsigned int value) +{ + struct dma_buf_attachment *attachment; + struct sg_table *sgt; + struct scatterlist *sg; + unsigned int count; + unsigned int offset = 0; + int ret = 0; + int i; + + attachment = dma_buf_attach(dma_buf, te_device.this_device); + if (IS_ERR_OR_NULL(attachment)) + return -EBUSY; + + sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(sgt)) { + ret = PTR_ERR(sgt); + goto no_import; + } + + for_each_sg(sgt->sgl, sg, sgt->nents, count) { + ret = dma_buf_begin_cpu_access(dma_buf, offset, sg_dma_len(sg), DMA_BIDIRECTIONAL); + if (ret) + goto no_cpu_access; + for (i = 0; i < sg_dma_len(sg); i = i + PAGE_SIZE) { + void *addr; + + addr = dma_buf_kmap(dma_buf, i >> PAGE_SHIFT); + if (!addr) { + /* dma_buf_kmap is unimplemented in exynos and returns NULL */ + dma_buf_end_cpu_access(dma_buf, offset, sg_dma_len(sg), DMA_BIDIRECTIONAL); + ret = -EPERM; + goto no_cpu_access; + } + memset(addr, value, PAGE_SIZE); + dma_buf_kunmap(dma_buf, i >> PAGE_SHIFT, addr); + } + dma_buf_end_cpu_access(dma_buf, offset, sg_dma_len(sg), DMA_BIDIRECTIONAL); + offset += sg_dma_len(sg); + } + +no_cpu_access: + dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL); +no_import: + dma_buf_detach(dma_buf, attachment); + return ret; +} + +static int do_dma_buf_te_ioctl_fill(struct dma_buf_te_ioctl_fill __user *arg) +{ + + struct dma_buf *dmabuf; + struct dma_buf_te_ioctl_fill f; + int ret; + + if (copy_from_user(&f, arg, sizeof(f))) + return -EFAULT; + + dmabuf = dma_buf_get(f.fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EINVAL; + + ret = dma_te_buf_fill(dmabuf, f.value); + dma_buf_put(dmabuf); + + return ret; +} + +static long dma_buf_te_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case DMA_BUF_TE_VERSION: + return do_dma_buf_te_ioctl_version((struct dma_buf_te_ioctl_version __user *)arg); + case DMA_BUF_TE_ALLOC: + return do_dma_buf_te_ioctl_alloc((struct dma_buf_te_ioctl_alloc __user *)arg, false); + case DMA_BUF_TE_ALLOC_CONT: + return do_dma_buf_te_ioctl_alloc((struct dma_buf_te_ioctl_alloc __user *)arg, true); + case DMA_BUF_TE_QUERY: + return do_dma_buf_te_ioctl_status((struct dma_buf_te_ioctl_status __user *)arg); + case DMA_BUF_TE_SET_FAILING: + return do_dma_buf_te_ioctl_set_failing((struct dma_buf_te_ioctl_set_failing __user *)arg); + case DMA_BUF_TE_FILL: + return do_dma_buf_te_ioctl_fill((struct dma_buf_te_ioctl_fill __user *)arg); + default: + return -ENOTTY; + } +} + +static const struct file_operations dma_buf_te_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = dma_buf_te_ioctl, + .compat_ioctl = dma_buf_te_ioctl, +}; + +static int __init dma_buf_te_init(void) +{ + int res; + te_device.minor = MISC_DYNAMIC_MINOR; + te_device.name = "dma_buf_te"; + te_device.fops = &dma_buf_te_fops; + + res = misc_register(&te_device); + if (res) { + pr_debug("Misc device registration failed of 'dma_buf_te'\n"); + return res; + } + te_device.this_device->coherent_dma_mask = DMA_BIT_MASK(32); + + dev_info(te_device.this_device, "dma_buf_te ready\n"); + return 0; + +} + +static void __exit dma_buf_te_exit(void) +{ + misc_deregister(&te_device); +} + +module_init(dma_buf_te_init); +module_exit(dma_buf_te_exit); +MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..bfb8a99f9d45d296df6d4c63f8e12c067af58c01 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/dma_buf_test_exporter/sconscript @@ -0,0 +1,36 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +Import('env') + +if env['v'] != '1': + env['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +src = [Glob('#kernel/drivers/base/dma_buf_test_exporter/*.c'), Glob('#kernel/include/linux/*.h'), Glob('#kernel/drivers/base/dma_buf_test_exporter/K*')] + +env.Append( CPPPATH = '#kernel/include' ) + +if env.GetOption('clean') : + env.Execute(Action("make clean", '[CLEAN] dma-buf-test-exporter')) + cmd = env.Command('$STATIC_LIB_PATH/dma-buf-test-exporter.ko', src, []) + env.ProgTarget('dma-buf-test-exporter', cmd) +else: + makeAction=Action("cd ${SOURCE.dir} && make && ( ( [ -f dma-buf-test-exporter.ko ] && cp dma-buf-test-exporter.ko $STATIC_LIB_PATH/ ) || touch $STATIC_LIB_PATH/dma-buf-test-exporter.ko)", '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/dma-buf-test-exporter.ko', src, [makeAction]) + env.ProgTarget('dma-buf-test-exporter', cmd) + + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..a88acd8fdce8516286f16848df7625d35763889a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +obj-$(CONFIG_KDS) += kds.o +obj-$(CONFIG_KDS_TEST) += kds_test.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..5f96165f67d535f2b6b654b454d0dbfd3d31dff5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Kconfig @@ -0,0 +1,20 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +config KDS + tristate "Kernel dependency system" + help + This option enables the generic kernel dependency system diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..364d1515c1ae4e25d4a7419dee7725dfcf5911b4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/Makefile @@ -0,0 +1,37 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) +CONFIG_KDS_TEST ?= n + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: kds + +kds: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_KDS=m + +kds_test: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_KDS_TEST=m + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/kds.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/kds.c new file mode 100644 index 0000000000000000000000000000000000000000..de114a0937fe8b722048a7a18233efd02e710398 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/kds.c @@ -0,0 +1,545 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define KDS_LINK_TRIGGERED (1u << 0) +#define KDS_LINK_EXCLUSIVE (1u << 1) + +#define KDS_INVALID (void *)-2 +#define KDS_RESOURCE (void *)-1 + +struct kds_resource_set +{ + unsigned long num_resources; + unsigned long pending; + struct kds_callback *cb; + void *callback_parameter; + void *callback_extra_parameter; + struct list_head callback_link; + struct work_struct callback_work; + atomic_t cb_queued; + + /* This is only initted when kds_waitall() is called. */ + wait_queue_head_t wake; + + struct kds_link resources[0]; +}; + +static DEFINE_SPINLOCK(kds_lock); + +int kds_callback_init(struct kds_callback *cb, int direct, kds_callback_fn user_cb) +{ + int ret = 0; + + cb->direct = direct; + cb->user_cb = user_cb; + + if (!direct) + { + cb->wq = alloc_workqueue("kds", WQ_UNBOUND | WQ_HIGHPRI, WQ_UNBOUND_MAX_ACTIVE); + if (!cb->wq) + ret = -ENOMEM; + } + else + { + cb->wq = NULL; + } + + return ret; +} +EXPORT_SYMBOL(kds_callback_init); + +void kds_callback_term(struct kds_callback *cb) +{ + if (!cb->direct) + { + BUG_ON(!cb->wq); + destroy_workqueue(cb->wq); + } + else + { + BUG_ON(cb->wq); + } +} + +EXPORT_SYMBOL(kds_callback_term); + +static void kds_do_user_callback(struct kds_resource_set *rset) +{ + rset->cb->user_cb(rset->callback_parameter, rset->callback_extra_parameter); +} + +static void kds_queued_callback(struct work_struct *work) +{ + struct kds_resource_set *rset; + rset = container_of(work, struct kds_resource_set, callback_work); + + atomic_dec(&rset->cb_queued); + + kds_do_user_callback(rset); +} + +static void kds_callback_perform(struct kds_resource_set *rset) +{ + if (rset->cb->direct) + kds_do_user_callback(rset); + else + { + int result; + + atomic_inc(&rset->cb_queued); + + result = queue_work(rset->cb->wq, &rset->callback_work); + /* if we got a 0 return it means we've triggered the same rset twice! */ + WARN_ON(!result); + } +} + +void kds_resource_init(struct kds_resource * const res) +{ + BUG_ON(!res); + INIT_LIST_HEAD(&res->waiters.link); + res->waiters.parent = KDS_RESOURCE; +} +EXPORT_SYMBOL(kds_resource_init); + +int kds_resource_term(struct kds_resource *res) +{ + unsigned long lflags; + BUG_ON(!res); + spin_lock_irqsave(&kds_lock, lflags); + if (!list_empty(&res->waiters.link)) + { + spin_unlock_irqrestore(&kds_lock, lflags); + pr_err("ERROR: KDS resource is still in use\n"); + return -EBUSY; + } + res->waiters.parent = KDS_INVALID; + spin_unlock_irqrestore(&kds_lock, lflags); + return 0; +} +EXPORT_SYMBOL(kds_resource_term); + +int kds_async_waitall( + struct kds_resource_set ** const pprset, + struct kds_callback *cb, + void *callback_parameter, + void *callback_extra_parameter, + int number_resources, + unsigned long *exclusive_access_bitmap, + struct kds_resource **resource_list) +{ + struct kds_resource_set *rset = NULL; + unsigned long lflags; + int i; + int triggered; + int err = -EFAULT; + + BUG_ON(!pprset); + BUG_ON(!resource_list); + BUG_ON(!cb); + + WARN_ONCE(number_resources > 10, "Waiting on a high numbers of resources may increase latency, see documentation."); + + rset = kmalloc(sizeof(*rset) + number_resources * sizeof(struct kds_link), GFP_KERNEL); + if (!rset) + { + return -ENOMEM; + } + + rset->num_resources = number_resources; + rset->pending = number_resources; + rset->cb = cb; + rset->callback_parameter = callback_parameter; + rset->callback_extra_parameter = callback_extra_parameter; + INIT_LIST_HEAD(&rset->callback_link); + INIT_WORK(&rset->callback_work, kds_queued_callback); + atomic_set(&rset->cb_queued, 0); + + for (i = 0; i < number_resources; i++) + { + INIT_LIST_HEAD(&rset->resources[i].link); + rset->resources[i].parent = rset; + } + + spin_lock_irqsave(&kds_lock, lflags); + + for (i = 0; i < number_resources; i++) + { + unsigned long link_state = 0; + + if (test_bit(i, exclusive_access_bitmap)) + { + link_state |= KDS_LINK_EXCLUSIVE; + } + + /* no-one else waiting? */ + if (list_empty(&resource_list[i]->waiters.link)) + { + link_state |= KDS_LINK_TRIGGERED; + rset->pending--; + } + /* Adding a non-exclusive and the current tail is a triggered non-exclusive? */ + else if (((link_state & KDS_LINK_EXCLUSIVE) == 0) && + (((list_entry(resource_list[i]->waiters.link.prev, struct kds_link, link)->state & (KDS_LINK_EXCLUSIVE | KDS_LINK_TRIGGERED)) == KDS_LINK_TRIGGERED))) + { + link_state |= KDS_LINK_TRIGGERED; + rset->pending--; + } + rset->resources[i].state = link_state; + + /* avoid double wait (hang) */ + if (!list_empty(&resource_list[i]->waiters.link)) + { + /* adding same rset again? */ + if (list_entry(resource_list[i]->waiters.link.prev, struct kds_link, link)->parent == rset) + { + goto roll_back; + } + } + list_add_tail(&rset->resources[i].link, &resource_list[i]->waiters.link); + } + + triggered = (rset->pending == 0); + + /* set the pointer before the callback is called so it sees it */ + *pprset = rset; + + spin_unlock_irqrestore(&kds_lock, lflags); + + if (triggered) + { + /* all resources obtained, trigger callback */ + kds_callback_perform(rset); + } + + return 0; + +roll_back: + /* roll back */ + while (i-- > 0) + { + list_del(&rset->resources[i].link); + } + err = -EINVAL; + + spin_unlock_irqrestore(&kds_lock, lflags); + kfree(rset); + return err; +} +EXPORT_SYMBOL(kds_async_waitall); + +static void wake_up_sync_call(void *callback_parameter, void *callback_extra_parameter) +{ + wait_queue_head_t *wait = (wait_queue_head_t *)callback_parameter; + wake_up(wait); +} + +static struct kds_callback sync_cb = +{ + wake_up_sync_call, + 1, + NULL, +}; + +struct kds_resource_set *kds_waitall( + int number_resources, + unsigned long *exclusive_access_bitmap, + struct kds_resource **resource_list, + unsigned long jiffies_timeout) +{ + struct kds_resource_set *rset; + unsigned long lflags; + int i; + int triggered = 0; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + + rset = kmalloc(sizeof(*rset) + number_resources * sizeof(struct kds_link), GFP_KERNEL); + if (!rset) + return rset; + + rset->num_resources = number_resources; + rset->pending = number_resources; + init_waitqueue_head(&rset->wake); + INIT_LIST_HEAD(&rset->callback_link); + INIT_WORK(&rset->callback_work, kds_queued_callback); + atomic_set(&rset->cb_queued, 0); + + spin_lock_irqsave(&kds_lock, lflags); + + for (i = 0; i < number_resources; i++) + { + unsigned long link_state = 0; + + if (test_bit(i, exclusive_access_bitmap)) + { + link_state |= KDS_LINK_EXCLUSIVE; + } + + if (list_empty(&resource_list[i]->waiters.link)) + { + link_state |= KDS_LINK_TRIGGERED; + rset->pending--; + } + /* Adding a non-exclusive and the current tail is a triggered non-exclusive? */ + else if (((link_state & KDS_LINK_EXCLUSIVE) == 0) && + (((list_entry(resource_list[i]->waiters.link.prev, struct kds_link, link)->state & (KDS_LINK_EXCLUSIVE | KDS_LINK_TRIGGERED)) == KDS_LINK_TRIGGERED))) + { + link_state |= KDS_LINK_TRIGGERED; + rset->pending--; + } + + INIT_LIST_HEAD(&rset->resources[i].link); + rset->resources[i].parent = rset; + rset->resources[i].state = link_state; + + /* avoid double wait (hang) */ + if (!list_empty(&resource_list[i]->waiters.link)) + { + /* adding same rset again? */ + if (list_entry(resource_list[i]->waiters.link.prev, struct kds_link, link)->parent == rset) + { + goto roll_back; + } + } + + list_add_tail(&rset->resources[i].link, &resource_list[i]->waiters.link); + } + + if (rset->pending == 0) + triggered = 1; + else + { + rset->cb = &sync_cb; + rset->callback_parameter = &rset->wake; + rset->callback_extra_parameter = NULL; + } + + spin_unlock_irqrestore(&kds_lock, lflags); + + if (!triggered) + { + long wait_res = 0; + long timeout = (jiffies_timeout == KDS_WAIT_BLOCKING) ? + MAX_SCHEDULE_TIMEOUT : jiffies_timeout; + + if (timeout) + { + wait_res = wait_event_interruptible_timeout(rset->wake, + rset->pending == 0, timeout); + } + + if ((wait_res == -ERESTARTSYS) || (wait_res == 0)) + { + /* use \a kds_resource_set_release to roll back */ + kds_resource_set_release(&rset); + return ERR_PTR(wait_res); + } + } + return rset; + +roll_back: + /* roll back */ + while (i-- > 0) + { + list_del(&rset->resources[i].link); + } + + spin_unlock_irqrestore(&kds_lock, lflags); + kfree(rset); + return ERR_PTR(-EINVAL); +} +EXPORT_SYMBOL(kds_waitall); + +static void __kds_resource_set_release_common(struct kds_resource_set *rset) +{ + struct list_head triggered = LIST_HEAD_INIT(triggered); + struct kds_resource_set *it; + unsigned long lflags; + int i; + + spin_lock_irqsave(&kds_lock, lflags); + + for (i = 0; i < rset->num_resources; i++) + { + struct kds_resource *resource; + struct kds_link *it = NULL; + + /* fetch the previous entry on the linked list */ + it = list_entry(rset->resources[i].link.prev, struct kds_link, link); + /* unlink ourself */ + list_del(&rset->resources[i].link); + + /* any waiters? */ + if (list_empty(&it->link)) + continue; + + /* were we the head of the list? (head if prev is a resource) */ + if (it->parent != KDS_RESOURCE) + { + if ((it->state & KDS_LINK_TRIGGERED) && !(it->state & KDS_LINK_EXCLUSIVE)) + { + /* + * previous was triggered and not exclusive, so we + * trigger non-exclusive until end-of-list or first + * exclusive + */ + + struct kds_link *it_waiting = it; + + list_for_each_entry(it, &it_waiting->link, link) + { + /* exclusive found, stop triggering */ + if (it->state & KDS_LINK_EXCLUSIVE) + break; + + it->state |= KDS_LINK_TRIGGERED; + /* a parent to update? */ + if (it->parent != KDS_RESOURCE) + { + if (0 == --it->parent->pending) + { + /* new owner now triggered, track for callback later */ + list_add(&it->parent->callback_link, &triggered); + } + } + } + } + continue; + } + + /* we were the head, find the kds_resource */ + resource = container_of(it, struct kds_resource, waiters); + + /* we know there is someone waiting from the any-waiters test above */ + + /* find the head of the waiting list */ + it = list_first_entry(&resource->waiters.link, struct kds_link, link); + + /* new exclusive owner? */ + if (it->state & KDS_LINK_EXCLUSIVE) + { + /* link now triggered */ + it->state |= KDS_LINK_TRIGGERED; + /* a parent to update? */ + if (0 == --it->parent->pending) + { + /* new owner now triggered, track for callback later */ + list_add(&it->parent->callback_link, &triggered); + } + } + /* exclusive releasing ? */ + else if (rset->resources[i].state & KDS_LINK_EXCLUSIVE) + { + /* trigger non-exclusive until end-of-list or first exclusive */ + list_for_each_entry(it, &resource->waiters.link, link) + { + /* exclusive found, stop triggering */ + if (it->state & KDS_LINK_EXCLUSIVE) + break; + + it->state |= KDS_LINK_TRIGGERED; + /* a parent to update? */ + if (0 == --it->parent->pending) + { + /* new owner now triggered, track for callback later */ + list_add(&it->parent->callback_link, &triggered); + } + } + } + } + + spin_unlock_irqrestore(&kds_lock, lflags); + + while (!list_empty(&triggered)) + { + it = list_first_entry(&triggered, struct kds_resource_set, callback_link); + list_del(&it->callback_link); + kds_callback_perform(it); + } +} + +void kds_resource_set_release(struct kds_resource_set **pprset) +{ + struct kds_resource_set *rset; + int queued; + + rset = cmpxchg(pprset, *pprset, NULL); + + if (!rset) + { + /* caught a race between a cancelation + * and a completion, nothing to do */ + return; + } + + __kds_resource_set_release_common(rset); + + /* + * Caller is responsible for guaranteeing that callback work is not + * pending (i.e. its running or completed) prior to calling release. + */ + queued = atomic_read(&rset->cb_queued); + BUG_ON(queued); + + /* free the resource set */ + kfree(rset); +} +EXPORT_SYMBOL(kds_resource_set_release); + +void kds_resource_set_release_sync(struct kds_resource_set **pprset) +{ + struct kds_resource_set *rset; + + rset = cmpxchg(pprset, *pprset, NULL); + if (!rset) + { + /* caught a race between a cancelation + * and a completion, nothing to do */ + return; + } + + __kds_resource_set_release_common(rset); + + /* + * In the case of a kds async wait cancellation ensure the deferred + * call back does not get scheduled if a trigger fired at the same time + * to release the wait. + */ + cancel_work_sync(&rset->callback_work); + + /* free the resource set */ + kfree(rset); +} +EXPORT_SYMBOL(kds_resource_set_release_sync); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION("1.0"); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..ec2c4cc34a3ff701062c2456afe6f0fae0f124cc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/kds/sconscript @@ -0,0 +1,71 @@ +# +# (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +import re +Import('env') + +#Android uses sync_pt to accomplish KDS functionality. +#Midgard KDS is not used by Android +if env['os'] == 'android': + Return() + +# If KDS is built into the kernel already we skip building the module ourselves +linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' +search_term = '^[\ ]*CONFIG_KDS[\ ]*=[\ ]*y' +build_kds = 1 +for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + # KDS in kernel. Do not build KDS kernel module but + # still allow for building kds_test module. + build_kds = 0 + +if env['v'] != '1': + env['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +src = [Glob('#kernel/drivers/base/kds/*.c'), Glob('#kernel/include/linux/*.h'), Glob('#kernel/drivers/base/kds/K*')] + +env.Append( CPPPATH = '#kernel/include' ) + +if Glob('tests/sconscript'): + SConscript( 'tests/sconscript' ) + +if env.GetOption('clean') : + # Clean KDS module + if build_kds: + env.Execute(Action("make clean", '[CLEAN] kds')) + cmd = env.Command('$STATIC_LIB_PATH/kds.ko', src, []) + env.ProgTarget('kds', cmd) + + # Clean KDS test module + if (int(env['unit']) == 1): + cmdTest = env.Command('$STATIC_LIB_PATH/kds_test.ko', src, []) + env.ProgTarget('kds', cmdTest) +else: + # Build KDS module + if build_kds: + makeAction=Action("cd ${SOURCE.dir} && make kds && cp kds.ko $STATIC_LIB_PATH/", '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/kds.ko', src, [makeAction]) + env.ProgTarget('kds', cmd) + + # Build KDS test module + if int(env['unit']) == 1: + makeActionTest=Action("cd ${SOURCE.dir} && make kds_test && cp kds_test.ko $STATIC_LIB_PATH/", '$MAKECOMSTR') + cmdTest = env.Command('$STATIC_LIB_PATH/kds_test.ko', src, [makeActionTest]) + env.ProgTarget('kds', cmdTest) + if build_kds: + Depends(cmdTest, cmd) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..55b8399922b12284410cfe8f2784f6145dd4dc06 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/sconscript @@ -0,0 +1,28 @@ +# +# (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +if Glob('dma_buf_lock/sconscript'): + SConscript('dma_buf_lock/sconscript') + +if Glob('kds/sconscript'): + SConscript('kds/sconscript') + +if Glob('ump/sconscript'): + SConscript('ump/sconscript') + +if Glob('dma_buf_test_exporter/sconscript'): + SConscript('dma_buf_test_exporter/sconscript') + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..2bbdba27d76f16b0c36d5ac9989ef9219dcbddcd --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +obj-y += src/ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..f7451e67a5ee8a627061382f07e758e848ac8de2 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/Kconfig @@ -0,0 +1,26 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +config UMP + tristate "Enable Unified Memory Provider (UMP) support" + default n + help + Enable this option to build support for the ARM UMP module. + UMP can be used by the Mali T6xx module to improve performance + by reducing the copying of data by sharing memory. + + To compile this driver as a module, choose M here: + this will generate one module, called ump. diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/docs/Doxyfile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/docs/Doxyfile new file mode 100755 index 0000000000000000000000000000000000000000..fbec8eb40a02d90ce232386a28d88e3990fd6db6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/docs/Doxyfile @@ -0,0 +1,125 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +############################################################################## + +# This file contains per-module Doxygen configuration. Please do not add +# extra settings to this file without consulting all stakeholders, as they +# may cause override project-wide settings. +# +# Additionally, when defining aliases, macros, sections etc, use the module +# name as a prefix e.g. gles_my_alias. + +############################################################################## + +@INCLUDE = ../../bldsys/Doxyfile_common + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT += ../../kernel/include/linux/ump-common.h ../../kernel/include/linux/ump.h + +############################################################################## +# Everything below here is optional, and in most cases not required +############################################################################## + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES += + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS += + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS += + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE += + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS += + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS += + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH += ../../kernel/drivers/base/ump + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH += + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH += + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED += + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED += + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS += diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/docs/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/docs/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..521278d138bd460ea609429fcf8a896b674406fb --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/docs/sconscript @@ -0,0 +1,31 @@ +# +# (C) COPYRIGHT 2010-2011, 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +Import('env') + +doxygen_sources = [ + 'Doxyfile', + Glob('*.png'), + Glob('../*.h'), + Glob('../src/*.h') ] + +if env['doc'] == '1': + doxygen_target = env.Command('doxygen/html/index.html', doxygen_sources, + ['cd ${SOURCE.dir} && doxygen']) + env.Clean(doxygen_target, './doxygen') + + Alias('doxygen', doxygen_target) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/example_kernel_api.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/example_kernel_api.c new file mode 100644 index 0000000000000000000000000000000000000000..eb9b12930f8ac9d77523247912b4ab4cfd11ffbe --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/example_kernel_api.c @@ -0,0 +1,73 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +#include +#include + +/* + * Example routine to display information about an UMP allocation + * The routine takes an secure_id which can come from a different kernel module + * or from a client application (i.e. an ioctl). + * It creates a ump handle from the secure id (which validates the secure id) + * and if successful dumps the physical memory information. + * It follows the API and pins the memory while "using" the physical memory. + * Finally it calls the release function to indicate it's finished with the handle. + * + * If the function can't look up the handle it fails with return value -1. + * If the testy succeeds then it return 0. + * */ + +static int display_ump_memory_information(ump_secure_id secure_id) +{ + const ump_dd_physical_block_64 * ump_blocks = NULL; + ump_dd_handle ump_mem; + uint64_t nr_blocks; + int i; + ump_alloc_flags flags; + + /* get a handle from the secure id */ + ump_mem = ump_dd_from_secure_id(secure_id); + + if (UMP_DD_INVALID_MEMORY_HANDLE == ump_mem) + { + /* invalid ID received */ + return -1; + } + + /* at this point we know we've added a reference to the ump allocation, so we must release it with ump_dd_release */ + + ump_dd_phys_blocks_get_64(ump_mem, &nr_blocks, &ump_blocks); + flags = ump_dd_allocation_flags_get(ump_mem); + + printf("UMP allocation with secure ID %u consists of %zd physical block(s):\n", secure_id, nr_blocks); + + for(i=0; i +#include +#include + +/* + * Example routine to exercise the user space UMP api. + * This routine initializes the UMP api and allocates some CPU+device X memory. + * No usage hints are given, so the driver will use the default cacheability policy. + * With the allocation it creates a duplicate handle and plays with the reference count. + * Then it simulates interacting with a device and contains pseudo code for the device. + * + * If any error is detected correct cleanup will be performed and -1 will be returned. + * If successful then 0 will be returned. + */ + +static int test_ump_user_api(void) +{ + /* This is the size we try to allocate*/ + const size_t alloc_size = 4096; + + ump_handle h = UMP_INVALID_MEMORY_HANDLE; + ump_handle h_copy = UMP_INVALID_MEMORY_HANDLE; + ump_handle h_clone = UMP_INVALID_MEMORY_HANDLE; + + void * mapping = NULL; + + ump_result ump_api_res; + int result = -1; + + ump_secure_id id; + + size_t size_returned; + + ump_api_res = ump_open(); + if (UMP_OK != ump_api_res) + { + /* failed to open an ump session */ + /* early out */ + return -1; + } + + h = ump_allocate_64(alloc_size, UMP_PROT_CPU_RD | UMP_PROT_CPU_WR | UMP_PROT_X_RD | UMP_PROT_X_WR); + /* the refcount is now 1 */ + if (UMP_INVALID_MEMORY_HANDLE == h) + { + /* allocation failure */ + goto cleanup; + } + + /* this is how we could share this allocation with another process */ + + /* in process A: */ + id = ump_secure_id_get(h); + /* still ref count 1 */ + /* send the id to process B */ + + /* in process B: */ + /* receive the id from A */ + h_clone = ump_from_secure_id(id); + /* the ref count of the allocation is now 2 (one from each handle to it) */ + /* do something ... */ + /* release our clone */ + ump_release(h_clone); /* safe to call even if ump_from_secure_id failed */ + h_clone = UMP_INVALID_MEMORY_HANDLE; + + + /* a simple save-for-future-use logic inside the driver would just copy the handle (but add a ref manually too!) */ + /* + * void assign_memory_to_job(h) + * { + */ + h_copy = h; + ump_retain(h_copy); /* manual retain needed as we just assigned the handle, now 2 */ + /* + * } + * + * void job_completed(void) + * { + */ + ump_release(h_copy); /* normal handle release as if we got via an ump_allocate */ + h_copy = UMP_INVALID_MEMORY_HANDLE; + /* + * } + */ + + /* we're now back at ref count 1, and only h is a valid handle */ + /* enough handle duplication show-off, let's play with the contents instead */ + + mapping = ump_map(h, 0, alloc_size); + if (NULL == mapping) + { + /* mapping failure, either out of address space or some other error */ + goto cleanup; + } + + memset(mapping, 0, alloc_size); + + /* let's pretend we're going to start some hw device on this buffer and read the result afterwards */ + ump_cpu_msync_now(h, UMP_MSYNC_CLEAN, mapping, alloc_size); + /* + device cache invalidate + + memory barrier + + start device + + memory barrier + + wait for device + + memory barrier + + device cache clean + + memory barrier + */ + ump_cpu_msync_now(h, UMP_MSYNC_CLEAN_AND_INVALIDATE, mapping, alloc_size); + + /* we could now peek at the result produced by the hw device, which is now accessible via our mapping */ + + /* unmap the buffer when we're done with it */ + ump_unmap(h, mapping, alloc_size); + + result = 0; + +cleanup: + ump_release(h); + h = UMP_INVALID_MEMORY_HANDLE; + + ump_close(); + + return result; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..b4aa8b6853a52c6e821f03f6b13ff079bd186b7a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/sconscript @@ -0,0 +1,21 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +Import('env') + +if Glob('src/sconscript') and int(env['ump']) == 1: + SConscript( 'src/sconscript' ) + SConscript( 'docs/sconscript' ) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..de6d30770d154d64b53e5003ed67bec19c182ac4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Kbuild @@ -0,0 +1,50 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +# Paths required for build +UMP_PATH = $(src)/../.. +UMP_DEVICEDRV_PATH = $(src)/. + +# Set up defaults if not defined by the user +MALI_UNIT_TEST ?= 0 + +SRC :=\ + common/ump_kernel_core.c \ + common/ump_kernel_descriptor_mapping.c \ + linux/ump_kernel_linux.c \ + linux/ump_kernel_linux_mem.c + +UNIT_TEST_DEFINES= +ifeq ($(MALI_UNIT_TEST), 1) + MALI_DEBUG ?= 1 + + UNIT_TEST_DEFINES = -DMALI_UNIT_TEST=1 \ + -DMALI_DEBUG=$(MALI_DEBUG) +endif + +# Use our defines when compiling +ccflags-y += -I$(UMP_PATH) -I$(UMP_DEVICEDRV_PATH) $(UNIT_TEST_DEFINES) + + +# Tell the Linux build system from which .o file to create the kernel module +obj-$(CONFIG_UMP) += ump.o +ifeq ($(CONFIG_ION),y) +ccflags-y += -I$(srctree)/drivers/staging/android/ion -I$(srctree)/include/linux +obj-$(CONFIG_UMP) += imports/ion/ump_kernel_import_ion.o +endif + +# Tell the Linux build system to enable building of our .c files +ump-y := $(SRC:.c=.o) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..45428adbdf77bb5ae7d52d675e32c557ab8ca182 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Makefile @@ -0,0 +1,81 @@ +# +# (C) COPYRIGHT 2008-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +ifneq ($(KBUILD_EXTMOD),) +include $(KBUILD_EXTMOD)/Makefile.common +else +include ./Makefile.common +endif + +# default to building for the host +ARCH ?= $(shell uname -m) + +# linux build system integration +RELATIVE_ROOT=../../../../.. +ROOT = $(CURDIR)/$(RELATIVE_ROOT) + +EXTRA_CFLAGS=-I$(CURDIR)/../../../../include + +ifeq ($(MALI_UNIT_TEST),1) + EXTRA_CFLAGS += -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) +endif + +# Get any user defined KDIR- or maybe even a hardcoded KDIR +-include KDIR_CONFIGURATION + +# Define host system directory +KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build + +CONFIG ?= $(ARCH) + +# default cpu to select +CPU ?= $(shell uname -m) + +# look up KDIR based om CPU selection +KDIR ?= $(KDIR-$(CPU)) + +ifeq ($(KDIR),) +$(error No KDIR found for platform $(CPU)) +endif + +# Validate selected config +ifneq ($(shell [ -d arch-$(CONFIG) ] && [ -f arch-$(CONFIG)/config.h ] && echo "OK"), OK) +$(warning Current directory is $(shell pwd)) +$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists) +else +# Link arch to the selected arch-config directory +$(shell [ -L arch ] && rm arch) +$(shell ln -sf arch-$(CONFIG) arch) +$(shell touch arch/config.h) +endif + +EXTRA_SYMBOLS= + +ifeq ($(MALI_UNIT_TEST),1) + KBASE_PATH=$(ROOT)/kernel/drivers/gpu/arm/midgard + EXTRA_SYMBOLS+=$(KBASE_PATH)/tests/internal/src/kernel_assert_module/linux/Module.symvers +endif +KDS_PATH=$(ROOT)/kernel/drivers/base/kds +EXTRA_SYMBOLS+=$(KDS_PATH)/Module.symvers + +all: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="$(EXTRA_CFLAGS) $(SCONS_CFLAGS)" CONFIG_UMP=m KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules + +kernelrelease: + $(MAKE) -C $(KDIR) KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" kernelrelease + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Makefile.common b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Makefile.common new file mode 100755 index 0000000000000000000000000000000000000000..f29a4c1cffa5a04c704e292fd16ca1cb38a25153 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/Makefile.common @@ -0,0 +1,19 @@ +# +# (C) COPYRIGHT 2008-2010, 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +SRC = $(UMP_FILE_PREFIX)/common/ump_kernel_core.c \ + $(UMP_FILE_PREFIX)/common/ump_kernel_descriptor_mapping.c + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/arch-arm/config.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/arch-arm/config.h new file mode 100644 index 0000000000000000000000000000000000000000..afb44d6cb74511ef6002528141496a1f4f3e6b1c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/arch-arm/config.h @@ -0,0 +1,27 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +#define ARCH_UMP_BACKEND_DEFAULT 1 +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x00000000 +#define ARCH_UMP_MEMORY_SIZE_DEFAULT 32UL * 1024UL * 1024UL + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/arch-arm64/config.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/arch-arm64/config.h new file mode 100644 index 0000000000000000000000000000000000000000..afb44d6cb74511ef6002528141496a1f4f3e6b1c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/arch-arm64/config.h @@ -0,0 +1,27 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef __ARCH_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +#define ARCH_UMP_BACKEND_DEFAULT 1 +#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x00000000 +#define ARCH_UMP_MEMORY_SIZE_DEFAULT 32UL * 1024UL * 1024UL + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_core.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_core.c new file mode 100644 index 0000000000000000000000000000000000000000..7bbef009ca4ad79915d5a905c843b552741b0fa8 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_core.c @@ -0,0 +1,756 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* module headers */ +#include +#include + +/* local headers */ +#include +#include +#include +#include + +#define UMP_FLAGS_RANGE ((UMP_PROT_SHAREABLE<<1) - 1u) + +static umpp_device device; + +ump_result umpp_core_constructor(void) +{ + mutex_init(&device.secure_id_map_lock); + device.secure_id_map = umpp_descriptor_mapping_create(UMP_EXPECTED_IDS, UMP_MAX_IDS); + if (NULL != device.secure_id_map) + { + if (UMP_OK == umpp_device_initialize()) + { + return UMP_OK; + } + umpp_descriptor_mapping_destroy(device.secure_id_map); + } + mutex_destroy(&device.secure_id_map_lock); + + return UMP_ERROR; +} + +void umpp_core_destructor(void) +{ + umpp_device_terminate(); + umpp_descriptor_mapping_destroy(device.secure_id_map); + mutex_destroy(&device.secure_id_map_lock); +} + +umpp_session *umpp_core_session_start(void) +{ + umpp_session * session; + + session = kzalloc(sizeof(*session), GFP_KERNEL); + if (NULL != session) + { + mutex_init(&session->session_lock); + + INIT_LIST_HEAD(&session->memory_usage); + + /* try to create import client session, not a failure if they fail to initialize */ + umpp_import_handlers_init(session); + } + + return session; +} + +void umpp_core_session_end(umpp_session *session) +{ + umpp_session_memory_usage * usage, *_usage; + UMP_ASSERT(session); + + list_for_each_entry_safe(usage, _usage, &session->memory_usage, link) + { + pr_debug("UMP: Memory usage cleanup, releasing secure ID %d\n", ump_dd_secure_id_get(usage->mem)); + ump_dd_release(usage->mem); + kfree(usage); + + } + + /* we should now not hold any imported memory objects, + * detatch all import handlers */ + umpp_import_handlers_term(session); + + mutex_destroy(&session->session_lock); + kfree(session); +} + +ump_dd_handle ump_dd_allocate_64(uint64_t size, ump_alloc_flags flags, ump_dd_security_filter filter_func, ump_dd_final_release_callback final_release_func, void* callback_data) +{ + umpp_allocation * alloc; + int i; + + UMP_ASSERT(size); + + if (flags & (~UMP_FLAGS_RANGE)) + { + pr_debug("UMP: allocation flags out of allowed bits range\n"); + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + if( ( flags & (UMP_PROT_CPU_RD | UMP_PROT_W_RD | UMP_PROT_X_RD | UMP_PROT_Y_RD | UMP_PROT_Z_RD ) ) == 0 || + ( flags & (UMP_PROT_CPU_WR | UMP_PROT_W_WR | UMP_PROT_X_WR | UMP_PROT_Y_WR | UMP_PROT_Z_WR )) == 0 ) + { + pr_debug("UMP: allocation flags should have at least one read and one write permission bit set\n"); + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + /*check permission flags to be set if hit flags are set too*/ + for (i = UMP_DEVICE_CPU_SHIFT; i<=UMP_DEVICE_Z_SHIFT; i+=4) + { + if (flags & (UMP_HINT_DEVICE_RD<flags = flags; + alloc->filter_func = filter_func; + alloc->final_release_func = final_release_func; + alloc->callback_data = callback_data; + alloc->size = size; + + mutex_init(&alloc->map_list_lock); + INIT_LIST_HEAD(&alloc->map_list); + atomic_set(&alloc->refcount, 1); + +#ifdef CONFIG_KDS + kds_resource_init(&alloc->kds_res); +#endif + + if (!(alloc->flags & UMP_PROT_SHAREABLE)) + { + alloc->owner = get_current()->pid; + } + + if (0 != umpp_phys_commit(alloc)) + { + goto out2; + } + + /* all set up, allocate an ID for it */ + + mutex_lock(&device.secure_id_map_lock); + alloc->id = umpp_descriptor_mapping_allocate(device.secure_id_map, (void*)alloc); + mutex_unlock(&device.secure_id_map_lock); + + if ((int)alloc->id == 0) + { + /* failed to allocate a secure_id */ + goto out3; + } + + return alloc; + +out3: + umpp_phys_free(alloc); +out2: + kfree(alloc); +out1: + return UMP_DD_INVALID_MEMORY_HANDLE; +} + +uint64_t ump_dd_size_get_64(const ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + return alloc->size; +} + +/* + * UMP v1 API + */ +unsigned long ump_dd_size_get(ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + UMP_ASSERT(alloc->flags & UMP_CONSTRAINT_32BIT_ADDRESSABLE); + UMP_ASSERT(alloc->size <= UMP_UINT32_MAX); + + return (unsigned long)alloc->size; +} + +ump_secure_id ump_dd_secure_id_get(const ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + return alloc->id; +} + +#ifdef CONFIG_KDS +struct kds_resource * ump_dd_kds_resource_get(const ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + return &alloc->kds_res; +} +#endif + +ump_alloc_flags ump_dd_allocation_flags_get(const ump_dd_handle mem) +{ + const umpp_allocation * alloc; + + UMP_ASSERT(mem); + alloc = (const umpp_allocation *)mem; + + return alloc->flags; +} + +ump_dd_handle ump_dd_from_secure_id(ump_secure_id secure_id) +{ + umpp_allocation * alloc = UMP_DD_INVALID_MEMORY_HANDLE; + + mutex_lock(&device.secure_id_map_lock); + + if (0 == umpp_descriptor_mapping_lookup(device.secure_id_map, secure_id, (void**)&alloc)) + { + if (NULL != alloc->filter_func) + { + if (!alloc->filter_func(secure_id, alloc, alloc->callback_data)) + { + alloc = UMP_DD_INVALID_MEMORY_HANDLE; /* the filter denied access */ + } + } + + /* check permission to access it */ + if ((UMP_DD_INVALID_MEMORY_HANDLE != alloc) && !(alloc->flags & UMP_PROT_SHAREABLE)) + { + if (alloc->owner != get_current()->pid) + { + alloc = UMP_DD_INVALID_MEMORY_HANDLE; /*no rights for the current process*/ + } + } + + if (UMP_DD_INVALID_MEMORY_HANDLE != alloc) + { + if( ump_dd_retain(alloc) != UMP_DD_SUCCESS) + { + alloc = UMP_DD_INVALID_MEMORY_HANDLE; + } + } + } + mutex_unlock(&device.secure_id_map_lock); + + return alloc; +} + +/* + * UMP v1 API + */ +ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id) +{ + return ump_dd_from_secure_id(secure_id); +} + +int ump_dd_retain(ump_dd_handle mem) +{ + umpp_allocation * alloc; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + /* check for overflow */ + while(1) + { + int refcnt = atomic_read(&alloc->refcount); + if (refcnt + 1 > 0) + { + if(atomic_cmpxchg(&alloc->refcount, refcnt, refcnt + 1) == refcnt) + { + return 0; + } + } + else + { + return -EBUSY; + } + } +} + +/* + * UMP v1 API + */ +void ump_dd_reference_add(ump_dd_handle mem) +{ + ump_dd_retain(mem); +} + + +void ump_dd_release(ump_dd_handle mem) +{ + umpp_allocation * alloc; + uint32_t new_cnt; + + UMP_ASSERT(mem); + + alloc = (umpp_allocation*)mem; + + /* secure the id for lookup while releasing */ + mutex_lock(&device.secure_id_map_lock); + + /* do the actual release */ + new_cnt = atomic_sub_return(1, &alloc->refcount); + if (0 == new_cnt) + { + /* remove from the table as this was the last ref */ + umpp_descriptor_mapping_remove(device.secure_id_map, alloc->id); + } + + /* release the lock as early as possible */ + mutex_unlock(&device.secure_id_map_lock); + + if (0 != new_cnt) + { + /* exit if still have refs */ + return; + } + + UMP_ASSERT(list_empty(&alloc->map_list)); + +#ifdef CONFIG_KDS + if (kds_resource_term(&alloc->kds_res)) + { + pr_err("ump_dd_release: kds_resource_term failed," + "unable to release UMP allocation\n"); + return; + } +#endif + /* cleanup */ + if (NULL != alloc->final_release_func) + { + alloc->final_release_func(alloc, alloc->callback_data); + } + + if (0 == (alloc->management_flags & UMP_MGMT_EXTERNAL)) + { + umpp_phys_free(alloc); + } + else + { + kfree(alloc->block_array); + } + + mutex_destroy(&alloc->map_list_lock); + + kfree(alloc); +} + +/* + * UMP v1 API + */ +void ump_dd_reference_release(ump_dd_handle mem) +{ + ump_dd_release(mem); +} + +void ump_dd_phys_blocks_get_64(const ump_dd_handle mem, uint64_t * const pCount, const ump_dd_physical_block_64 ** const pArray) +{ + const umpp_allocation * alloc; + UMP_ASSERT(pCount); + UMP_ASSERT(pArray); + UMP_ASSERT(mem); + alloc = (const umpp_allocation *)mem; + *pCount = alloc->blocksCount; + *pArray = alloc->block_array; +} + +/* + * UMP v1 API + */ +ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block * const blocks, unsigned long num_blocks) +{ + const umpp_allocation * alloc; + unsigned long i; + UMP_ASSERT(mem); + UMP_ASSERT(blocks); + UMP_ASSERT(num_blocks); + + alloc = (const umpp_allocation *)mem; + + UMP_ASSERT(alloc->flags & UMP_CONSTRAINT_32BIT_ADDRESSABLE); + + if((uint64_t)num_blocks != alloc->blocksCount) + { + return UMP_DD_INVALID; + } + + for( i = 0; i < num_blocks; i++) + { + UMP_ASSERT(alloc->block_array[i].addr <= UMP_UINT32_MAX); + UMP_ASSERT(alloc->block_array[i].size <= UMP_UINT32_MAX); + + blocks[i].addr = (unsigned long)alloc->block_array[i].addr; + blocks[i].size = (unsigned long)alloc->block_array[i].size; + } + + return UMP_DD_SUCCESS; +} +/* + * UMP v1 API + */ +ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block * const block) +{ + const umpp_allocation * alloc; + UMP_ASSERT(mem); + UMP_ASSERT(block); + alloc = (const umpp_allocation *)mem; + + UMP_ASSERT(alloc->flags & UMP_CONSTRAINT_32BIT_ADDRESSABLE); + + UMP_ASSERT(alloc->block_array[index].addr <= UMP_UINT32_MAX); + UMP_ASSERT(alloc->block_array[index].size <= UMP_UINT32_MAX); + + block->addr = (unsigned long)alloc->block_array[index].addr; + block->size = (unsigned long)alloc->block_array[index].size; + + return UMP_DD_SUCCESS; +} + +/* + * UMP v1 API + */ +unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem) +{ + const umpp_allocation * alloc; + UMP_ASSERT(mem); + alloc = (const umpp_allocation *)mem; + + UMP_ASSERT(alloc->flags & UMP_CONSTRAINT_32BIT_ADDRESSABLE); + UMP_ASSERT(alloc->blocksCount <= UMP_UINT32_MAX); + + return (unsigned long)alloc->blocksCount; +} + +umpp_cpu_mapping * umpp_dd_find_enclosing_mapping(umpp_allocation * alloc, void *uaddr, size_t size) +{ + umpp_cpu_mapping *map; + + void *target_first = uaddr; + void *target_last = (void*)((uintptr_t)uaddr - 1 + size); + + if (target_last < target_first) /* wrapped */ + { + return NULL; + } + + mutex_lock(&alloc->map_list_lock); + list_for_each_entry(map, &alloc->map_list, link) + { + if ( map->vaddr_start <= target_first && + (void*)((uintptr_t)map->vaddr_start + (map->nr_pages << PAGE_SHIFT) - 1) >= target_last) + { + goto out; + } + } + map = NULL; +out: + mutex_unlock(&alloc->map_list_lock); + + return map; +} + +void umpp_dd_add_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * map) +{ + UMP_ASSERT(alloc); + UMP_ASSERT(map); + mutex_lock(&alloc->map_list_lock); + list_add(&map->link, &alloc->map_list); + mutex_unlock(&alloc->map_list_lock); +} + +void umpp_dd_remove_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * target) +{ + umpp_cpu_mapping * map; + + UMP_ASSERT(alloc); + UMP_ASSERT(target); + + mutex_lock(&alloc->map_list_lock); + list_for_each_entry(map, &alloc->map_list, link) + { + if (map == target) + { + list_del(&target->link); + kfree(target); + mutex_unlock(&alloc->map_list_lock); + return; + } + } + + /* not found, error */ + UMP_ASSERT(0); +} + +int umpp_dd_find_start_block(const umpp_allocation * alloc, uint64_t offset, uint64_t * const block_index, uint64_t * const block_internal_offset) +{ + uint64_t i; + + for (i = 0 ; i < alloc->blocksCount; i++) + { + if (offset < alloc->block_array[i].size) + { + /* found the block_array element containing this offset */ + *block_index = i; + *block_internal_offset = offset; + return 0; + } + offset -= alloc->block_array[i].size; + } + + return -ENXIO; +} + +void umpp_dd_cpu_msync_now(ump_dd_handle mem, ump_cpu_msync_op op, void * address, size_t size) +{ + umpp_allocation * alloc; + void *vaddr; + umpp_cpu_mapping * mapping; + uint64_t virt_page_off; /* offset of given address from beginning of the virtual mapping */ + uint64_t phys_page_off; /* offset of the virtual mapping from the beginning of the physical buffer */ + uint64_t page_count; /* number of pages to sync */ + uint64_t i; + uint64_t block_idx; + uint64_t block_offset; + uint64_t paddr; + + UMP_ASSERT((UMP_MSYNC_CLEAN == op) || (UMP_MSYNC_CLEAN_AND_INVALIDATE == op)); + + alloc = (umpp_allocation*)mem; + vaddr = (void*)(uintptr_t)address; + + if((alloc->flags & UMP_CONSTRAINT_UNCACHED) != 0) + { + /* mapping is not cached */ + return; + } + + mapping = umpp_dd_find_enclosing_mapping(alloc, vaddr, size); + if (NULL == mapping) + { + pr_debug("UMP: Illegal cache sync address %lx\n", (uintptr_t)vaddr); + return; /* invalid pointer or size causes out-of-bounds */ + } + + /* we already know that address + size don't wrap around as umpp_dd_find_enclosing_mapping didn't fail */ + page_count = ((((((uintptr_t)address + size - 1) & PAGE_MASK) - ((uintptr_t)address & PAGE_MASK))) >> PAGE_SHIFT) + 1; + virt_page_off = (vaddr - mapping->vaddr_start) >> PAGE_SHIFT; + phys_page_off = mapping->page_off; + + if (umpp_dd_find_start_block(alloc, (virt_page_off + phys_page_off) << PAGE_SHIFT, &block_idx, &block_offset)) + { + /* should not fail as a valid mapping was found, so the phys mem must exists */ + pr_debug("UMP: Unable to find physical start block with offset %llx\n", virt_page_off + phys_page_off); + UMP_ASSERT(0); + return; + } + + paddr = alloc->block_array[block_idx].addr + block_offset + (((uintptr_t)vaddr) & ((1u << PAGE_SHIFT)-1)); + + for (i = 0; i < page_count; i++) + { + size_t offset = ((uintptr_t)vaddr) & ((1u << PAGE_SHIFT)-1); + size_t sz = min((size_t)PAGE_SIZE - offset, size); + + /* check if we've overrrun the current block, if so move to the next block */ + if (paddr >= (alloc->block_array[block_idx].addr + alloc->block_array[block_idx].size)) + { + block_idx++; + UMP_ASSERT(block_idx < alloc->blocksCount); + paddr = alloc->block_array[block_idx].addr; + } + + if (UMP_MSYNC_CLEAN == op) + { + ump_sync_to_memory(paddr, vaddr, sz); + } + else /* (UMP_MSYNC_CLEAN_AND_INVALIDATE == op) already validated on entry */ + { + ump_sync_to_cpu(paddr, vaddr, sz); + } + + /* advance to next page */ + vaddr = (void*)((uintptr_t)vaddr + sz); + size -= sz; + paddr += sz; + } +} + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_create_from_phys_blocks_64(const ump_dd_physical_block_64 * blocks, uint64_t num_blocks, ump_alloc_flags flags, ump_dd_security_filter filter_func, ump_dd_final_release_callback final_release_func, void* callback_data) +{ + uint64_t size = 0; + uint64_t i; + umpp_allocation * alloc; + + UMP_ASSERT(blocks); + UMP_ASSERT(num_blocks); + + for (i = 0; i < num_blocks; i++) + { + size += blocks[i].size; + } + UMP_ASSERT(size); + + if (flags & (~UMP_FLAGS_RANGE)) + { + pr_debug("UMP: allocation flags out of allowed bits range\n"); + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + if( ( flags & (UMP_PROT_CPU_RD | UMP_PROT_W_RD | UMP_PROT_X_RD | UMP_PROT_Y_RD | UMP_PROT_Z_RD + | UMP_PROT_CPU_WR | UMP_PROT_W_WR | UMP_PROT_X_WR | UMP_PROT_Y_WR | UMP_PROT_Z_WR )) == 0 ) + { + pr_debug("UMP: allocation flags should have at least one read or write permission bit set\n"); + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + /*check permission flags to be set if hit flags are set too*/ + for (i = UMP_DEVICE_CPU_SHIFT; i<=UMP_DEVICE_Z_SHIFT; i+=4) + { + if (flags & (UMP_HINT_DEVICE_RD<block_array = kzalloc(sizeof(ump_dd_physical_block_64) * num_blocks,__GFP_HARDWALL | GFP_KERNEL); + if (NULL == alloc->block_array) + { + goto out2; + } + + memcpy(alloc->block_array, blocks, sizeof(ump_dd_physical_block_64) * num_blocks); + +#ifdef CONFIG_KDS + kds_resource_init(&alloc->kds_res); +#endif + alloc->size = size; + alloc->blocksCount = num_blocks; + alloc->flags = flags; + alloc->filter_func = filter_func; + alloc->final_release_func = final_release_func; + alloc->callback_data = callback_data; + + if (!(alloc->flags & UMP_PROT_SHAREABLE)) + { + alloc->owner = get_current()->pid; + } + + mutex_init(&alloc->map_list_lock); + INIT_LIST_HEAD(&alloc->map_list); + atomic_set(&alloc->refcount, 1); + + /* all set up, allocate an ID */ + + mutex_lock(&device.secure_id_map_lock); + alloc->id = umpp_descriptor_mapping_allocate(device.secure_id_map, (void*)alloc); + mutex_unlock(&device.secure_id_map_lock); + + if ((int)alloc->id == 0) + { + /* failed to allocate a secure_id */ + goto out3; + } + + alloc->management_flags |= UMP_MGMT_EXTERNAL; + + return alloc; + +out3: + kfree(alloc->block_array); +out2: + kfree(alloc); +out1: + return UMP_DD_INVALID_MEMORY_HANDLE; +} + + +/* + * UMP v1 API + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks) +{ + ump_dd_handle mem; + ump_dd_physical_block_64 *block_64_array; + ump_alloc_flags flags = UMP_V1_API_DEFAULT_ALLOCATION_FLAGS; + unsigned long i; + + UMP_ASSERT(blocks); + UMP_ASSERT(num_blocks); + + block_64_array = kzalloc(num_blocks * sizeof(*block_64_array), __GFP_HARDWALL | GFP_KERNEL); + + if(block_64_array == NULL) + { + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + /* copy physical blocks */ + for( i = 0; i < num_blocks; i++) + { + block_64_array[i].addr = blocks[i].addr; + block_64_array[i].size = blocks[i].size; + } + + mem = ump_dd_create_from_phys_blocks_64(block_64_array, num_blocks, flags, NULL, NULL, NULL); + + kfree(block_64_array); + + return mem; + +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_core.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_core.h new file mode 100644 index 0000000000000000000000000000000000000000..2329c45f0ebe17e150a00cc0a9de70b47eabb87e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_core.h @@ -0,0 +1,228 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_KERNEL_CORE_H_ +#define _UMP_KERNEL_CORE_H_ + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_KDS +#include +#endif +#include +#include + +/* forward decl */ +struct umpp_session; + +/** + * UMP handle metadata. + * Tracks various data about a handle not of any use to user space + */ +typedef enum +{ + UMP_MGMT_EXTERNAL = (1ul << 0) /**< Handle created via the ump_dd_create_from_phys_blocks interface */ + /* (1ul << 31) not to be used */ +} umpp_management_flags; + +/** + * Structure tracking the single global UMP device. + * Holds global data like the ID map + */ +typedef struct umpp_device +{ + struct mutex secure_id_map_lock; /**< Lock protecting access to the map */ + umpp_descriptor_mapping * secure_id_map; /**< Map of all known secure IDs on the system */ +} umpp_device; + +/** + * Structure tracking all memory allocations of a UMP allocation. + * Tracks info about an mapping so we can verify cache maintenace + * operations and help in the unmap cleanup. + */ +typedef struct umpp_cpu_mapping +{ + struct list_head link; /**< link to list of mappings for an allocation */ + void *vaddr_start; /**< CPU VA start of the mapping */ + size_t nr_pages; /**< Size (in pages) of the mapping */ + uint64_t page_off; /**< Offset (in pages) from start of the allocation where the mapping starts */ + ump_dd_handle handle; /**< Which handle this mapping is linked to */ + struct umpp_session * session; /**< Which session created the mapping */ +} umpp_cpu_mapping; + +/** + * Structure tracking UMP allocation. + * Represent a memory allocation with its ID. + * Tracks all needed meta-data about an allocation. + * */ +typedef struct umpp_allocation +{ + ump_secure_id id; /**< Secure ID of the allocation */ + atomic_t refcount; /**< Usage count */ + + ump_alloc_flags flags; /**< Flags for all supported devices */ + uint32_t management_flags; /**< Managment flags tracking */ + + pid_t owner; /**< The process ID owning the memory if not sharable */ + + ump_dd_security_filter filter_func; /**< Hook to verify use, called during retains from new clients */ + ump_dd_final_release_callback final_release_func; /**< Hook called when the last reference is removed */ + void* callback_data; /**< Additional data given to release hook */ + + uint64_t size; /**< Size (in bytes) of the allocation */ + uint64_t blocksCount; /**< Number of physsical blocks the allocation is built up of */ + ump_dd_physical_block_64 * block_array; /**< Array, one entry per block, describing block start and length */ + + struct mutex map_list_lock; /**< Lock protecting the map_list */ + struct list_head map_list; /**< Tracks all CPU VA mappings of this allocation */ + +#ifdef CONFIG_KDS + struct kds_resource kds_res; /**< The KDS resource controlling access to this allocation */ +#endif + + void * backendData; /**< Physical memory backend meta-data */ +} umpp_allocation; + +/** + * Structure tracking use of UMP memory by a session. + * Tracks the use of an allocation by a session so session termination can clean up any outstanding references. + * Also protects agains non-matched release calls from user space. + */ +typedef struct umpp_session_memory_usage +{ + ump_secure_id id; /**< ID being used. For quick look-up */ + ump_dd_handle mem; /**< Handle being used. */ + + /** + * Track how many times has the process retained this handle in the kernel. + * This should usually just be 1(allocated or resolved) or 2(mapped), + * but could be more if someone is playing with the low-level API + * */ + atomic_t process_usage_count; + + struct list_head link; /**< link to other usage trackers for a session */ +} umpp_session_memory_usage; + +/** + * Structure representing a session/client. + * Tracks the UMP allocations being used by this client. + */ +typedef struct umpp_session +{ + struct mutex session_lock; /**< Lock for memory usage manipulation */ + struct list_head memory_usage; /**< list of memory currently being used by the this session */ + void* import_handler_data[UMPP_EXTERNAL_MEM_COUNT]; /**< Import modules per-session data pointer */ +} umpp_session; + +/** + * UMP core setup. + * Called by any OS specific startup function to initialize the common part. + * @return UMP_OK if core initialized correctly, any other value for errors + */ +ump_result umpp_core_constructor(void); + +/** + * UMP core teardown. + * Called by any OS specific unload function to clean up the common part. + */ +void umpp_core_destructor(void); + +/** + * UMP session start. + * Called by any OS specific session handler when a new session is detected + * @return Non-NULL if a matching core session could be set up. NULL on failure + */ +umpp_session *umpp_core_session_start(void); + +/** + * UMP session end. + * Called by any OS specific session handler when a session is ended/terminated. + * @param session The core session object returned by ump_core_session_start + */ +void umpp_core_session_end(umpp_session *session); + +/** + * Find a mapping object (if any) for this allocation. + * Called by any function needing to identify a mapping from a user virtual address. + * Verifies that the whole range to be within a mapping object. + * @param alloc The UMP allocation to find a matching mapping object of + * @param uaddr User mapping address to find the mapping object for + * @param size Length of the mapping + * @return NULL on error (no match found), pointer to mapping object if match found + */ +umpp_cpu_mapping * umpp_dd_find_enclosing_mapping(umpp_allocation * alloc, void* uaddr, size_t size); + +/** + * Register a new mapping of an allocation. + * Called by functions creating a new mapping of an allocation, typically OS specific handlers. + * @param alloc The allocation object which has been mapped + * @param map Info about the mapping + */ +void umpp_dd_add_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * map); + +/** + * Remove and free mapping object from an allocation. + * @param alloc The allocation object to remove the mapping info from + * @param target The mapping object to remove + */ +void umpp_dd_remove_cpu_mapping(umpp_allocation * alloc, umpp_cpu_mapping * target); + +/** + * Helper to find a block in the blockArray which holds a given byte offset. + * @param alloc The allocation object to find the block in + * @param offset Offset (in bytes) from allocation start to find the block of + * @param[out] block_index Pointer to the index of the block matching + * @param[out] block_internal_offset Offset within the returned block of the searched offset + * @return 0 if a matching block was found, any other value for error + */ +int umpp_dd_find_start_block(const umpp_allocation * alloc, uint64_t offset, uint64_t * const block_index, uint64_t * const block_internal_offset); + +/** + * Cache maintenance helper. + * Performs the requested cache operation on the given handle. + * @param mem Allocation handle + * @param op Cache maintenance operation to perform + * @param address User mapping at which to do the operation + * @param size Length (in bytes) of the range to do the operation on + */ +void umpp_dd_cpu_msync_now(ump_dd_handle mem, ump_cpu_msync_op op, void * address, size_t size); + +/** + * Import module session early init. + * Calls session_begin on all installed import modules. + * @param session The core session object to initialized the import handler for + * */ +void umpp_import_handlers_init(umpp_session * session); + +/** + * Import module session cleanup. + * Calls session_end on all import modules bound to the session. + * @param session The core session object to initialized the import handler for + */ +void umpp_import_handlers_term(umpp_session * session); + +#endif /* _UMP_KERNEL_CORE_H_ */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.c new file mode 100644 index 0000000000000000000000000000000000000000..c25f21af790af1519d6cd1dfeb5bb51e4db26262 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.c @@ -0,0 +1,162 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + + +#include +#include + +#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1)) + +/** + * Allocate a descriptor table capable of holding 'count' mappings + * @param count Number of mappings in the table + * @return Pointer to a new table, NULL on error + */ +static umpp_descriptor_table * descriptor_table_alloc(unsigned int count); + +/** + * Free a descriptor table + * @param table The table to free + */ +static void descriptor_table_free(umpp_descriptor_table * table); + +umpp_descriptor_mapping * umpp_descriptor_mapping_create(unsigned int init_entries, unsigned int max_entries) +{ + umpp_descriptor_mapping * map = kzalloc(sizeof(umpp_descriptor_mapping), GFP_KERNEL); + + init_entries = MALI_PAD_INT(init_entries); + max_entries = MALI_PAD_INT(max_entries); + + if (NULL != map) + { + map->table = descriptor_table_alloc(init_entries); + if (NULL != map->table) + { + init_rwsem( &map->lock); + set_bit(0, map->table->usage); + map->max_nr_mappings_allowed = max_entries; + map->current_nr_mappings = init_entries; + return map; + + descriptor_table_free(map->table); + } + kfree(map); + } + return NULL; +} + +void umpp_descriptor_mapping_destroy(umpp_descriptor_mapping * map) +{ + UMP_ASSERT(NULL != map); + descriptor_table_free(map->table); + kfree(map); +} + +unsigned int umpp_descriptor_mapping_allocate(umpp_descriptor_mapping * map, void * target) +{ + int descriptor = 0; + UMP_ASSERT(NULL != map); + down_write( &map->lock); + descriptor = find_first_zero_bit(map->table->usage, map->current_nr_mappings); + if (descriptor == map->current_nr_mappings) + { + /* no free descriptor, try to expand the table */ + umpp_descriptor_table * new_table; + umpp_descriptor_table * old_table = map->table; + int nr_mappings_new = map->current_nr_mappings + BITS_PER_LONG; + + if (map->current_nr_mappings >= map->max_nr_mappings_allowed) + { + descriptor = 0; + goto unlock_and_exit; + } + + new_table = descriptor_table_alloc(nr_mappings_new); + if (NULL == new_table) + { + descriptor = 0; + goto unlock_and_exit; + } + + memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + + map->table = new_table; + map->current_nr_mappings = nr_mappings_new; + descriptor_table_free(old_table); + } + + /* we have found a valid descriptor, set the value and usage bit */ + set_bit(descriptor, map->table->usage); + map->table->mappings[descriptor] = target; + +unlock_and_exit: + up_write(&map->lock); + return descriptor; +} + +int umpp_descriptor_mapping_lookup(umpp_descriptor_mapping * map, unsigned int descriptor, void** const target) +{ + int result = -EINVAL; + UMP_ASSERT(map); + UMP_ASSERT(target); + down_read(&map->lock); + if ( (descriptor > 0) && (descriptor < map->current_nr_mappings) && test_bit(descriptor, map->table->usage) ) + { + *target = map->table->mappings[descriptor]; + result = 0; + } + /* keep target untouched if the descriptor was not found */ + up_read(&map->lock); + return result; +} + +void umpp_descriptor_mapping_remove(umpp_descriptor_mapping * map, unsigned int descriptor) +{ + UMP_ASSERT(map); + down_write(&map->lock); + if ( (descriptor > 0) && (descriptor < map->current_nr_mappings) && test_bit(descriptor, map->table->usage) ) + { + map->table->mappings[descriptor] = NULL; + clear_bit(descriptor, map->table->usage); + } + up_write(&map->lock); +} + +static umpp_descriptor_table * descriptor_table_alloc(unsigned int count) +{ + umpp_descriptor_table * table; + + table = kzalloc(sizeof(umpp_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count), __GFP_HARDWALL | GFP_KERNEL ); + + if (NULL != table) + { + table->usage = (unsigned long*)((u8*)table + sizeof(umpp_descriptor_table)); + table->mappings = (void**)((u8*)table + sizeof(umpp_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG)); + } + + return table; +} + +static void descriptor_table_free(umpp_descriptor_table * table) +{ + UMP_ASSERT(table); + kfree(table); +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.h new file mode 100644 index 0000000000000000000000000000000000000000..3260d52c5945f000954fa3d305749d2743bdbc38 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_descriptor_mapping.h @@ -0,0 +1,94 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file ump_kernel_descriptor_mapping.h + */ + +#ifndef _UMP_KERNEL_DESCRIPTOR_MAPPING_H_ +#define _UMP_KERNEL_DESCRIPTOR_MAPPING_H_ + +#include +#include +/** + * The actual descriptor mapping table, never directly accessed by clients + */ +typedef struct umpp_descriptor_table +{ + /* keep as a unsigned long to rely on the OS's bitops support */ + unsigned long * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used(1) or not(0) */ + void** mappings; /**< Array of the pointers the descriptors map to */ +} umpp_descriptor_table; + +/** + * The descriptor mapping object + * Provides a separate namespace where we can map an integer to a pointer + */ +typedef struct umpp_descriptor_mapping +{ + struct rw_semaphore lock; /**< Lock protecting access to the mapping object */ + unsigned int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */ + unsigned int current_nr_mappings; /**< Current number of possible mappings */ + umpp_descriptor_table * table; /**< Pointer to the current mapping table */ +} umpp_descriptor_mapping; + +/** + * Create a descriptor mapping object. + * Create a descriptor mapping capable of holding init_entries growable to max_entries. + * ID 0 is reserved so the number of available entries will be max - 1. + * @param init_entries Number of entries to preallocate memory for + * @param max_entries Number of entries to max support + * @return Pointer to a descriptor mapping object, NULL on failure + */ +umpp_descriptor_mapping * umpp_descriptor_mapping_create(unsigned int init_entries, unsigned int max_entries); + +/** + * Destroy a descriptor mapping object + * @param[in] map The map to free + */ +void umpp_descriptor_mapping_destroy(umpp_descriptor_mapping * map); + +/** + * Allocate a new mapping entry (descriptor ID) + * Allocates a new entry in the map. + * @param[in] map The map to allocate a new entry in + * @param[in] target The value to map to + * @return The descriptor allocated, ID 0 on failure. + */ +unsigned int umpp_descriptor_mapping_allocate(umpp_descriptor_mapping * map, void * target); + +/** + * Get the value mapped to by a descriptor ID + * @param[in] map The map to lookup the descriptor id in + * @param[in] descriptor The descriptor ID to lookup + * @param[out] target Pointer to a pointer which will receive the stored value + * + * @return 0 on success lookup, -EINVAL on lookup failure. + */ +int umpp_descriptor_mapping_lookup(umpp_descriptor_mapping * map, unsigned int descriptor, void** const target); + +/** + * Free the descriptor ID + * For the descriptor to be reused it has to be freed + * @param[in] map The map to free the descriptor from + * @param descriptor The descriptor ID to free + */ +void umpp_descriptor_mapping_remove(umpp_descriptor_mapping * map, unsigned int descriptor); + +#endif /* _UMP_KERNEL_DESCRIPTOR_MAPPING_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_priv.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..e921193f6fda3460a56487fac6d2a9462ec97f93 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/common/ump_kernel_priv.h @@ -0,0 +1,80 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_KERNEL_PRIV_H_ +#define _UMP_KERNEL_PRIV_H_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#endif + + +#define UMP_EXPECTED_IDS 64 +#define UMP_MAX_IDS 32768 + +#ifdef __KERNEL__ +#define UMP_ASSERT(expr) \ + if (!(expr)) { \ + pr_err("UMP: Assertion failed! %s,%s,%s,line=%d\n",\ + #expr,__FILE__,__func__,__LINE__); \ + BUG(); \ + } + +static inline void ump_sync_to_memory(uint64_t paddr, void* vaddr, size_t sz) +{ +#ifdef CONFIG_ARM + __cpuc_flush_dcache_area(vaddr, sz); + outer_flush_range(paddr, paddr+sz); +#elif defined(CONFIG_ARM64) + /*TODO (MID64-46): There's no other suitable cache flush function for ARM64 */ + flush_cache_all(); +#elif defined(CONFIG_X86) + struct scatterlist scl = {0, }; + sg_set_page(&scl, pfn_to_page(PFN_DOWN(paddr)), sz, + paddr & (PAGE_SIZE -1 )); + dma_sync_sg_for_cpu(NULL, &scl, 1, DMA_TO_DEVICE); + mb(); /* for outer_sync (if needed) */ +#else +#error Implement cache maintenance for your architecture here +#endif +} + +static inline void ump_sync_to_cpu(uint64_t paddr, void* vaddr, size_t sz) +{ +#ifdef CONFIG_ARM + __cpuc_flush_dcache_area(vaddr, sz); + outer_flush_range(paddr, paddr+sz); +#elif defined(CONFIG_ARM64) + /* TODO (MID64-46): There's no other suitable cache flush function for ARM64 */ + flush_cache_all(); +#elif defined(CONFIG_X86) + struct scatterlist scl = {0, }; + sg_set_page(&scl, pfn_to_page(PFN_DOWN(paddr)), sz, + paddr & (PAGE_SIZE -1 )); + dma_sync_sg_for_cpu(NULL, &scl, 1, DMA_FROM_DEVICE); +#else +#error Implement cache maintenance for your architecture here +#endif +} +#endif /* __KERNEL__*/ +#endif /* _UMP_KERNEL_PRIV_H_ */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..ef74b273f7ad3d91642c1d5f2a33436d5b0c9b99 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/Makefile @@ -0,0 +1,53 @@ +# +# (C) COPYRIGHT 2011, 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +# default to building for the host +ARCH ?= $(shell uname -m) + +# linux build system integration + +ifneq ($(KERNELRELEASE),) +# Inside the kernel build system + +EXTRA_CFLAGS += -I$(KBUILD_EXTMOD) -I$(KBUILD_EXTMOD)/../../../../.. +KBUILD_EXTRA_SYMBOLS += "$(KBUILD_EXTMOD)/../../Module.symvers" + +SRC += ump_kernel_import_ion.c + +MODULE:=ump_ion_import.ko + +obj-m := $(MODULE:.ko=.o) +$(MODULE:.ko=-y) := $(SRC:.c=.o) +$(MODULE:.ko=-objs) := $(SRC:.c=.o) + +else +# Outside the kernel build system +# +# + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + +endif + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..749bb1f541f0ea85ff3ca7a4141fe0a6fdebd19b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/sconscript @@ -0,0 +1,52 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +Import('env') + +# Clone the environment so changes don't affect other build files +env_ion = env.Clone() + +if env_ion['ump_ion'] != '1': + Return() + +if env_ion['v'] != '1': + env_ion['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +# Source files required for UMP. +ion_src = [Glob('#kernel/drivers/base/ump/src/imports/ion/*.c')] + +# Note: cleaning via the Linux kernel build system does not yet work +if env_ion.GetOption('clean') : + makeAction=Action("cd ${SOURCE.dir} && make clean", '$MAKECOMSTR') +else: + makeAction=Action("cd ${SOURCE.dir} && make PLATFORM=${platform} && cp ump_ion_import.ko $STATIC_LIB_PATH/ump_ion_import.ko", '$MAKECOMSTR') +# The target is ump_import_ion.ko, built from the source in ion_src, via the action makeAction +# ump_import_ion.ko will be copied to $STATIC_LIB_PATH after being built by the standard Linux +# kernel build system, after which it can be installed to the directory specified if +# "libs_install" is set; this is done by LibTarget. +cmd = env_ion.Command('$STATIC_LIB_PATH/ump_ion_import.ko', ion_src, [makeAction]) + +# Until we fathom out how the invoke the Linux build system to clean, we can use Clean +# to remove generated files. + +patterns = ['*.mod.c', '*.o', '*.ko', '*.a', '.*.cmd', 'modules.order', '.tmp_versions', 'Module.symvers'] + +for p in patterns: + Clean(cmd, Glob('#kernel/drivers/base/ump/src/imports/ion/%s' % p)) + +env_ion.Depends('$STATIC_LIB_PATH/ump_ion_import.ko', '$STATIC_LIB_PATH/ump.ko') +env_ion.ProgTarget('ump', cmd) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/ump_kernel_import_ion.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/ump_kernel_import_ion.c new file mode 100644 index 0000000000000000000000000000000000000000..56dd610ba1c9a66eb20cda7719803b3c8357e200 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/ion/ump_kernel_import_ion.c @@ -0,0 +1,204 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include "ion.h" +#include +#include +#include + +struct ion_wrapping_info +{ + struct ion_client * ion_client; + struct ion_handle * ion_handle; + int num_phys_blocks; + struct scatterlist * sglist; +}; + +static struct ion_device * ion_device_get(void) +{ + /* < Customer to provide implementation > + * Return a pointer to the global ion_device on the system + */ + return NULL; +} + +static int import_ion_client_create(void** const custom_session_data) +{ + struct ion_client ** ion_client; + + ion_client = (struct ion_client**)custom_session_data; + + *ion_client = ion_client_create(ion_device_get(), "ump"); + + return PTR_RET(*ion_client); +} + + +static void import_ion_client_destroy(void* custom_session_data) +{ + struct ion_client * ion_client; + + ion_client = (struct ion_client*)custom_session_data; + BUG_ON(!ion_client); + + ion_client_destroy(ion_client); +} + + +static void import_ion_final_release_callback(const ump_dd_handle handle, void * info) +{ + struct ion_wrapping_info * ion_info; + + BUG_ON(!info); + + (void)handle; + ion_info = (struct ion_wrapping_info*)info; + + dma_unmap_sg(NULL, ion_info->sglist, ion_info->num_phys_blocks, DMA_BIDIRECTIONAL); + + ion_free(ion_info->ion_client, ion_info->ion_handle); + kfree(ion_info); + module_put(THIS_MODULE); +} + +static ump_dd_handle import_ion_import(void * custom_session_data, void * pfd, ump_alloc_flags flags) +{ + int fd; + ump_dd_handle ump_handle; + struct scatterlist * sg; + int num_dma_blocks; + ump_dd_physical_block_64 * phys_blocks; + unsigned long i; + struct sg_table * sgt; + + struct ion_wrapping_info * ion_info; + + BUG_ON(!custom_session_data); + BUG_ON(!pfd); + + ion_info = kzalloc(GFP_KERNEL, sizeof(*ion_info)); + if (NULL == ion_info) + { + return UMP_DD_INVALID_MEMORY_HANDLE; + } + + ion_info->ion_client = (struct ion_client*)custom_session_data; + + if (get_user(fd, (int*)pfd)) + { + goto out; + } + + ion_info->ion_handle = ion_import_dma_buf(ion_info->ion_client, fd); + + if (IS_ERR_OR_NULL(ion_info->ion_handle)) + { + goto out; + } + + sgt = ion_sg_table(ion_info->ion_client, ion_info->ion_handle); + if (IS_ERR_OR_NULL(sgt)) + { + goto ion_dma_map_failed; + } + + ion_info->sglist = sgt->sgl; + + sg = ion_info->sglist; + while (sg) + { + ion_info->num_phys_blocks++; + sg = sg_next(sg); + } + + num_dma_blocks = dma_map_sg(NULL, ion_info->sglist, ion_info->num_phys_blocks, DMA_BIDIRECTIONAL); + + if (0 == num_dma_blocks) + { + goto linux_dma_map_failed; + } + + phys_blocks = vmalloc(num_dma_blocks * sizeof(*phys_blocks)); + if (NULL == phys_blocks) + { + goto vmalloc_failed; + } + + for_each_sg(ion_info->sglist, sg, num_dma_blocks, i) + { + phys_blocks[i].addr = sg_phys(sg); + phys_blocks[i].size = sg_dma_len(sg); + } + + ump_handle = ump_dd_create_from_phys_blocks_64(phys_blocks, num_dma_blocks, flags, NULL, import_ion_final_release_callback, ion_info); + + vfree(phys_blocks); + + if (ump_handle != UMP_DD_INVALID_MEMORY_HANDLE) + { + /* + * As we have a final release callback installed + * we must keep the module locked until + * the callback has been triggered + * */ + __module_get(THIS_MODULE); + return ump_handle; + } + + /* failed*/ +vmalloc_failed: + dma_unmap_sg(NULL, ion_info->sglist, ion_info->num_phys_blocks, DMA_BIDIRECTIONAL); +linux_dma_map_failed: +ion_dma_map_failed: + ion_free(ion_info->ion_client, ion_info->ion_handle); +out: + kfree(ion_info); + return UMP_DD_INVALID_MEMORY_HANDLE; +} + +struct ump_import_handler import_handler_ion = +{ + .linux_module = THIS_MODULE, + .session_begin = import_ion_client_create, + .session_end = import_ion_client_destroy, + .import = import_ion_import +}; + +static int __init import_ion_initialize_module(void) +{ + /* register with UMP */ + return ump_import_module_register(UMP_EXTERNAL_MEM_TYPE_ION, &import_handler_ion); +} + +static void __exit import_ion_cleanup_module(void) +{ + /* unregister import handler */ + ump_import_module_unregister(UMP_EXTERNAL_MEM_TYPE_ION); +} + +/* Setup init and exit functions for this module */ +module_init(import_ion_initialize_module); +module_exit(import_ion_cleanup_module); + +/* And some module information */ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION("1.0"); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..8f506839d1d204624d4cc8f3738b033c3357847a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/imports/sconscript @@ -0,0 +1,25 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os, sys +Import('env') + +import_modules = [ os.path.join( path, 'sconscript' ) for path in sorted(os.listdir( os.getcwd() )) ] + +for m in import_modules: + if os.path.exists(m): + SConscript( m, variant_dir=os.path.join( env['BUILD_DIR_PATH'], os.path.dirname(m) ), duplicate=0 ) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..618587868974c48aa2dfdd594696a953e7985b55 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux.c @@ -0,0 +1,831 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include + +#include /* copy_*_user */ +#include +#include /* kernel module definitions */ +#include /* file system operations */ +#include /* character device definitions */ +#include /* request_mem_region */ +#include /* class registration support */ + +#include + +#include "ump_kernel_linux_mem.h" +#include + + +struct ump_linux_device +{ + struct cdev cdev; + struct class * ump_class; +}; + +/* Name of the UMP device driver */ +static char ump_dev_name[] = "ump"; /* should be const, but the functions we call requires non-cost */ + +/* Module parameter to control log level */ +int ump_debug_level = 2; +module_param(ump_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(ump_debug_level, "Higher number, more dmesg output"); + +/* By default the module uses any available major, but it's possible to set it at load time to a specific number */ +int ump_major = 0; +module_param(ump_major, int, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_major, "Device major number"); + +#define UMP_REV_STRING "1.0" + +char * ump_revision = UMP_REV_STRING; +module_param(ump_revision, charp, S_IRUGO); /* r--r--r-- */ +MODULE_PARM_DESC(ump_revision, "Revision info"); + +static int umpp_linux_open(struct inode *inode, struct file *filp); +static int umpp_linux_release(struct inode *inode, struct file *filp); +#ifdef HAVE_UNLOCKED_IOCTL +static long umpp_linux_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +static int umpp_linux_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#endif + +/* This variable defines the file operations this UMP device driver offers */ +static struct file_operations ump_fops = +{ + .owner = THIS_MODULE, + .open = umpp_linux_open, + .release = umpp_linux_release, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = umpp_linux_ioctl, +#else + .ioctl = umpp_linux_ioctl, +#endif + .compat_ioctl = umpp_linux_ioctl, + .mmap = umpp_linux_mmap +}; + +/* import module handling */ +DEFINE_MUTEX(import_list_lock); +struct ump_import_handler * import_handlers[UMPP_EXTERNAL_MEM_COUNT]; + +/* The global variable containing the global device data */ +static struct ump_linux_device ump_linux_device; + +#define DBG_MSG(level, ...) do { \ +if ((level) <= ump_debug_level)\ +{\ +pr_debug("UMP<" #level ">:\n" __VA_ARGS__);\ +} \ +} while (0) + +#define MSG_ERR(...) do{ \ +pr_err("UMP: ERR: %s\n %s()%4d\n", __FILE__, __func__ , __LINE__) ; \ +pr_err( __VA_ARGS__); \ +pr_err("\n"); \ +} while(0) + +#define MSG(...) do{ \ +pr_debug("UMP: " __VA_ARGS__);\ +} while (0) + +/* + * This function is called by Linux to initialize this module. + * All we do is initialize the UMP device driver. + */ +static int __init umpp_linux_initialize_module(void) +{ + ump_result err; + + err = umpp_core_constructor(); + if (UMP_OK != err) + { + MSG_ERR("UMP device driver init failed\n"); + return -ENOTTY; + } + + MSG("UMP device driver %s loaded\n", UMP_REV_STRING); + return 0; +} + + + +/* + * This function is called by Linux to unload/terminate/exit/cleanup this module. + * All we do is terminate the UMP device driver. + */ +static void __exit umpp_linux_cleanup_module(void) +{ + DBG_MSG(2, "Unloading UMP device driver\n"); + umpp_core_destructor(); + DBG_MSG(2, "Module unloaded\n"); +} + + + +/* + * Initialize the UMP device driver. + */ +ump_result umpp_device_initialize(void) +{ + int err; + dev_t dev = 0; + + if (0 == ump_major) + { + /* auto select a major */ + err = alloc_chrdev_region(&dev, 0, 1, ump_dev_name); + ump_major = MAJOR(dev); + } + else + { + /* use load time defined major number */ + dev = MKDEV(ump_major, 0); + err = register_chrdev_region(dev, 1, ump_dev_name); + } + + if (0 == err) + { + memset(&ump_linux_device, 0, sizeof(ump_linux_device)); + + /* initialize our char dev data */ + cdev_init(&ump_linux_device.cdev, &ump_fops); + ump_linux_device.cdev.owner = THIS_MODULE; + ump_linux_device.cdev.ops = &ump_fops; + + /* register char dev with the kernel */ + err = cdev_add(&ump_linux_device.cdev, dev, 1/*count*/); + if (0 == err) + { + + ump_linux_device.ump_class = class_create(THIS_MODULE, ump_dev_name); + if (IS_ERR(ump_linux_device.ump_class)) + { + err = PTR_ERR(ump_linux_device.ump_class); + } + else + { + struct device * mdev; + mdev = device_create(ump_linux_device.ump_class, NULL, dev, NULL, ump_dev_name); + if (!IS_ERR(mdev)) + { + return UMP_OK; + } + + err = PTR_ERR(mdev); + class_destroy(ump_linux_device.ump_class); + } + cdev_del(&ump_linux_device.cdev); + } + + unregister_chrdev_region(dev, 1); + } + + return UMP_ERROR; +} + + + +/* + * Terminate the UMP device driver + */ +void umpp_device_terminate(void) +{ + dev_t dev = MKDEV(ump_major, 0); + + device_destroy(ump_linux_device.ump_class, dev); + class_destroy(ump_linux_device.ump_class); + + /* unregister char device */ + cdev_del(&ump_linux_device.cdev); + + /* free major */ + unregister_chrdev_region(dev, 1); +} + + +static int umpp_linux_open(struct inode *inode, struct file *filp) +{ + umpp_session *session; + + session = umpp_core_session_start(); + if (NULL == session) + { + return -EFAULT; + } + + filp->private_data = session; + + return 0; +} + +static int umpp_linux_release(struct inode *inode, struct file *filp) +{ + umpp_session *session; + + session = filp->private_data; + + umpp_core_session_end(session); + + filp->private_data = NULL; + + return 0; +} + +/**************************/ +/*ioctl specific functions*/ +/**************************/ +static int do_ump_dd_allocate(umpp_session * session, ump_k_allocate * params) +{ + ump_dd_handle new_allocation; + new_allocation = ump_dd_allocate_64(params->size, params->alloc_flags, NULL, NULL, NULL); + + if (UMP_DD_INVALID_MEMORY_HANDLE != new_allocation) + { + umpp_session_memory_usage * tracker; + + tracker = kmalloc(sizeof(*tracker), GFP_KERNEL | __GFP_HARDWALL); + if (NULL != tracker) + { + /* update the return struct with the new ID */ + params->secure_id = ump_dd_secure_id_get(new_allocation); + + tracker->mem = new_allocation; + tracker->id = params->secure_id; + atomic_set(&tracker->process_usage_count, 1); + + /* link it into the session in-use list */ + mutex_lock(&session->session_lock); + list_add(&tracker->link, &session->memory_usage); + mutex_unlock(&session->session_lock); + + return 0; + } + ump_dd_release(new_allocation); + } + + pr_debug("UMP: Allocation FAILED\n"); + return -ENOMEM; +} + +static int do_ump_dd_retain(umpp_session * session, ump_k_retain * params) +{ + umpp_session_memory_usage * it; + + mutex_lock(&session->session_lock); + + /* try to find it on the session usage list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found to already be in use */ + /* check for overflow */ + while(1) + { + int refcnt = atomic_read(&it->process_usage_count); + if (refcnt + 1 > 0) + { + /* add a process local ref */ + if(atomic_cmpxchg(&it->process_usage_count, refcnt, refcnt + 1) == refcnt) + { + mutex_unlock(&session->session_lock); + return 0; + } + } + else + { + /* maximum usage cap reached */ + mutex_unlock(&session->session_lock); + return -EBUSY; + } + } + } + } + /* try to look it up globally */ + + it = kmalloc(sizeof(*it), GFP_KERNEL); + + if (NULL != it) + { + it->mem = ump_dd_from_secure_id(params->secure_id); + if (UMP_DD_INVALID_MEMORY_HANDLE != it->mem) + { + /* found, add it to the session usage list */ + it->id = params->secure_id; + atomic_set(&it->process_usage_count, 1); + list_add(&it->link, &session->memory_usage); + } + else + { + /* not found */ + kfree(it); + it = NULL; + } + } + + mutex_unlock(&session->session_lock); + + return (NULL != it) ? 0 : -ENODEV; +} + + +static int do_ump_dd_release(umpp_session * session, ump_k_release * params) +{ + umpp_session_memory_usage * it; + int result = -ENODEV; + + mutex_lock(&session->session_lock); + + /* only do a release if found on the session list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found, a valid call */ + result = 0; + + if (0 == atomic_sub_return(1, &it->process_usage_count)) + { + /* last ref in this process remove from the usage list and remove the underlying ref */ + list_del(&it->link); + ump_dd_release(it->mem); + kfree(it); + } + + break; + } + } + mutex_unlock(&session->session_lock); + + return result; +} + +static int do_ump_dd_sizequery(umpp_session * session, ump_k_sizequery * params) +{ + umpp_session_memory_usage * it; + int result = -ENODEV; + + mutex_lock(&session->session_lock); + + /* only valid if found on the session list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found, a valid call */ + params->size = ump_dd_size_get_64(it->mem); + result = 0; + break; + } + + } + mutex_unlock(&session->session_lock); + + return result; +} + +static int do_ump_dd_allocation_flags_get(umpp_session * session, ump_k_allocation_flags * params) +{ + umpp_session_memory_usage * it; + int result = -ENODEV; + + mutex_lock(&session->session_lock); + + /* only valid if found on the session list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found, a valid call */ + params->alloc_flags = ump_dd_allocation_flags_get(it->mem); + result = 0; + break; + } + + } + mutex_unlock(&session->session_lock); + + return result; +} + +static int do_ump_dd_msync_now(umpp_session * session, ump_k_msync * params) +{ + umpp_session_memory_usage * it; + int result = -ENODEV; + + mutex_lock(&session->session_lock); + + /* only valid if found on the session list */ + list_for_each_entry(it, &session->memory_usage, link) + { + if (it->id == params->secure_id) + { + /* found, do the cache op */ +#ifdef CONFIG_COMPAT + if (is_compat_task()) + { + umpp_dd_cpu_msync_now(it->mem, params->cache_operation, compat_ptr(params->mapped_ptr.compat_value), params->size); + result = 0; + } + else + { +#endif + umpp_dd_cpu_msync_now(it->mem, params->cache_operation, params->mapped_ptr.value, params->size); + result = 0; +#ifdef CONFIG_COMPAT + } +#endif + break; + } + } + mutex_unlock(&session->session_lock); + + return result; +} + + +void umpp_import_handlers_init(umpp_session * session) +{ + int i; + mutex_lock(&import_list_lock); + for ( i = 1; i < UMPP_EXTERNAL_MEM_COUNT; i++ ) + { + if (import_handlers[i]) + { + import_handlers[i]->session_begin(&session->import_handler_data[i]); + /* It is OK if session_begin returned an error. + * We won't do any import calls if so */ + } + } + mutex_unlock(&import_list_lock); +} + +void umpp_import_handlers_term(umpp_session * session) +{ + int i; + mutex_lock(&import_list_lock); + for ( i = 1; i < UMPP_EXTERNAL_MEM_COUNT; i++ ) + { + /* only call if session_begin succeeded */ + if (session->import_handler_data[i] != NULL) + { + /* if session_beging succeeded the handler + * should not have unregistered with us */ + BUG_ON(!import_handlers[i]); + import_handlers[i]->session_end(session->import_handler_data[i]); + session->import_handler_data[i] = NULL; + } + } + mutex_unlock(&import_list_lock); +} + +int ump_import_module_register(enum ump_external_memory_type type, struct ump_import_handler * handler) +{ + int res = -EEXIST; + + /* validate input */ + BUG_ON(type == 0 || type >= UMPP_EXTERNAL_MEM_COUNT); + BUG_ON(!handler); + BUG_ON(!handler->linux_module); + BUG_ON(!handler->session_begin); + BUG_ON(!handler->session_end); + BUG_ON(!handler->import); + + mutex_lock(&import_list_lock); + + if (!import_handlers[type]) + { + import_handlers[type] = handler; + res = 0; + } + + mutex_unlock(&import_list_lock); + + return res; +} + +void ump_import_module_unregister(enum ump_external_memory_type type) +{ + BUG_ON(type == 0 || type >= UMPP_EXTERNAL_MEM_COUNT); + + mutex_lock(&import_list_lock); + /* an error to call this if ump_import_module_register didn't succeed */ + BUG_ON(!import_handlers[type]); + import_handlers[type] = NULL; + mutex_unlock(&import_list_lock); +} + +static struct ump_import_handler * import_handler_get(unsigned int type_id) +{ + enum ump_external_memory_type type; + struct ump_import_handler * handler; + + /* validate and convert input */ + /* handle bad data here, not just BUG_ON */ + if (type_id == 0 || type_id >= UMPP_EXTERNAL_MEM_COUNT) + return NULL; + + type = (enum ump_external_memory_type)type_id; + + /* find the handler */ + mutex_lock(&import_list_lock); + + handler = import_handlers[type]; + + if (handler) + { + if (!try_module_get(handler->linux_module)) + { + handler = NULL; + } + } + + mutex_unlock(&import_list_lock); + + return handler; +} + +static void import_handler_put(struct ump_import_handler * handler) +{ + module_put(handler->linux_module); +} + +static int do_ump_dd_import(umpp_session * session, ump_k_import * params) +{ + ump_dd_handle new_allocation = UMP_DD_INVALID_MEMORY_HANDLE; + struct ump_import_handler * handler; + + handler = import_handler_get(params->type); + + if (handler) + { + /* try late binding if not already bound */ + if (!session->import_handler_data[params->type]) + { + handler->session_begin(&session->import_handler_data[params->type]); + } + + /* do we have a bound session? */ + if (session->import_handler_data[params->type]) + { + new_allocation = handler->import( session->import_handler_data[params->type], + params->phandle.value, + params->alloc_flags); + } + + /* done with the handler */ + import_handler_put(handler); + } + + /* did the import succeed? */ + if (UMP_DD_INVALID_MEMORY_HANDLE != new_allocation) + { + umpp_session_memory_usage * tracker; + + tracker = kmalloc(sizeof(*tracker), GFP_KERNEL | __GFP_HARDWALL); + if (NULL != tracker) + { + /* update the return struct with the new ID */ + params->secure_id = ump_dd_secure_id_get(new_allocation); + + tracker->mem = new_allocation; + tracker->id = params->secure_id; + atomic_set(&tracker->process_usage_count, 1); + + /* link it into the session in-use list */ + mutex_lock(&session->session_lock); + list_add(&tracker->link, &session->memory_usage); + mutex_unlock(&session->session_lock); + + return 0; + } + ump_dd_release(new_allocation); + } + + return -ENOMEM; + +} + +#ifdef HAVE_UNLOCKED_IOCTL +static long umpp_linux_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#else +static int umpp_linux_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + int ret; + uint64_t msg[(UMP_CALL_MAX_SIZE+7)>>3]; /* alignment fixup */ + uint32_t size = _IOC_SIZE(cmd); + struct umpp_session *session = filp->private_data; + +#ifndef HAVE_UNLOCKED_IOCTL + (void)inode; /* unused arg */ +#endif + + /* + * extract the type and number bitfields, and don't decode + * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() + */ + if (_IOC_TYPE(cmd) != UMP_IOC_MAGIC) + { + return -ENOTTY; + + } + if (_IOC_NR(cmd) > UMP_IOC_MAXNR) + { + return -ENOTTY; + } + + switch(cmd) + { + case UMP_FUNC_ALLOCATE: + if (size != sizeof(ump_k_allocate)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_allocate(session, (ump_k_allocate *)&msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + case UMP_FUNC_SIZEQUERY: + if (size != sizeof(ump_k_sizequery)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_sizequery(session,(ump_k_sizequery*) &msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + case UMP_FUNC_MSYNC: + if (size != sizeof(ump_k_msync)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_msync_now(session,(ump_k_msync*) &msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + case UMP_FUNC_IMPORT: + if (size != sizeof(ump_k_import)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user*)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_import(session, (ump_k_import*) &msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + /* used only by v1 API */ + case UMP_FUNC_ALLOCATION_FLAGS_GET: + if (size != sizeof(ump_k_allocation_flags)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_allocation_flags_get(session,(ump_k_allocation_flags*) &msg); + if (ret) + { + return ret; + } + if (copy_to_user((void *)arg, &msg, size)) + { + return -EFAULT; + } + return 0; + case UMP_FUNC_RETAIN: + if (size != sizeof(ump_k_retain)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_retain(session,(ump_k_retain*) &msg); + if (ret) + { + return ret; + } + return 0; + case UMP_FUNC_RELEASE: + if (size != sizeof(ump_k_release)) + { + return -ENOTTY; + } + if (copy_from_user(&msg, (void __user *)arg, size)) + { + return -EFAULT; + } + ret = do_ump_dd_release(session,(ump_k_release*) &msg); + if (ret) + { + return ret; + } + return 0; + default: + /* not ours */ + return -ENOTTY; + } + /*redundant below*/ + return -ENOTTY; +} + + +/* Export UMP kernel space API functions */ +EXPORT_SYMBOL(ump_dd_allocate_64); +EXPORT_SYMBOL(ump_dd_allocation_flags_get); +EXPORT_SYMBOL(ump_dd_secure_id_get); +EXPORT_SYMBOL(ump_dd_from_secure_id); +EXPORT_SYMBOL(ump_dd_phys_blocks_get_64); +EXPORT_SYMBOL(ump_dd_size_get_64); +EXPORT_SYMBOL(ump_dd_retain); +EXPORT_SYMBOL(ump_dd_release); +EXPORT_SYMBOL(ump_dd_create_from_phys_blocks_64); +#ifdef CONFIG_KDS +EXPORT_SYMBOL(ump_dd_kds_resource_get); +#endif + +/* import API */ +EXPORT_SYMBOL(ump_import_module_register); +EXPORT_SYMBOL(ump_import_module_unregister); + + + +/* V1 API */ +EXPORT_SYMBOL(ump_dd_handle_create_from_secure_id); +EXPORT_SYMBOL(ump_dd_phys_block_count_get); +EXPORT_SYMBOL(ump_dd_phys_block_get); +EXPORT_SYMBOL(ump_dd_phys_blocks_get); +EXPORT_SYMBOL(ump_dd_size_get); +EXPORT_SYMBOL(ump_dd_reference_add); +EXPORT_SYMBOL(ump_dd_reference_release); +EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); + + +/* Setup init and exit functions for this module */ +module_init(umpp_linux_initialize_module); +module_exit(umpp_linux_cleanup_module); + +/* And some module informatio */ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION(UMP_REV_STRING); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.c new file mode 100644 index 0000000000000000000000000000000000000000..159b56ab37d46455983ad9acadb764495bd18cc3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.c @@ -0,0 +1,250 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include + +#include +#include /* kernel module definitions */ +#include /* file system operations */ +#include /* character device definitions */ +#include /* request_mem_region */ +#include /* memory mananger definitions */ +#include +#include /*kmap*/ + +#include /* is_compat_task */ + +#include +#include +#include + +static void umpp_vm_close(struct vm_area_struct *vma) +{ + umpp_cpu_mapping * mapping; + umpp_session * session; + ump_dd_handle handle; + + mapping = (umpp_cpu_mapping*)vma->vm_private_data; + UMP_ASSERT(mapping); + + session = mapping->session; + handle = mapping->handle; + + umpp_dd_remove_cpu_mapping(mapping->handle, mapping); /* will free the mapping object */ + ump_dd_release(handle); +} + + +static const struct vm_operations_struct umpp_vm_ops = { + .close = umpp_vm_close +}; + +int umpp_phys_commit(umpp_allocation * alloc) +{ + uint64_t i; + + /* round up to a page boundary */ + alloc->size = (alloc->size + PAGE_SIZE - 1) & ~((uint64_t)PAGE_SIZE-1) ; + /* calculate number of pages */ + alloc->blocksCount = alloc->size >> PAGE_SHIFT; + + if( (sizeof(ump_dd_physical_block_64) * alloc->blocksCount) > ((size_t)-1)) + { + pr_debug("UMP: umpp_phys_commit - trying to allocate more than possible\n"); + return -ENOMEM; + } + + alloc->block_array = kmalloc(sizeof(ump_dd_physical_block_64) * alloc->blocksCount, __GFP_HARDWALL | GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); + if (NULL == alloc->block_array) + { + return -ENOMEM; + } + + for (i = 0; i < alloc->blocksCount; i++) + { + void * mp; + struct page * page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); + if (NULL == page) + { + break; + } + + alloc->block_array[i].addr = page_to_pfn(page) << PAGE_SHIFT; + alloc->block_array[i].size = PAGE_SIZE; + + mp = kmap(page); + if (NULL == mp) + { + __free_page(page); + break; + } + + memset(mp, 0x00, PAGE_SIZE); /* instead of __GFP_ZERO, so we can do cache maintenance */ + ump_sync_to_memory(PFN_PHYS(page_to_pfn(page)), mp, PAGE_SIZE); + kunmap(page); + } + + if (i == alloc->blocksCount) + { + return 0; + } + else + { + uint64_t j; + for (j = 0; j < i; j++) + { + struct page * page; + page = pfn_to_page(alloc->block_array[j].addr >> PAGE_SHIFT); + __free_page(page); + } + + kfree(alloc->block_array); + + return -ENOMEM; + } +} + +void umpp_phys_free(umpp_allocation * alloc) +{ + uint64_t i; + + for (i = 0; i < alloc->blocksCount; i++) + { + __free_page(pfn_to_page(alloc->block_array[i].addr >> PAGE_SHIFT)); + } + + kfree(alloc->block_array); +} + +int umpp_linux_mmap(struct file * filp, struct vm_area_struct * vma) +{ + ump_secure_id id; + ump_dd_handle h; + size_t offset; + int err = -EINVAL; + size_t length = vma->vm_end - vma->vm_start; + + umpp_cpu_mapping * map = NULL; + umpp_session *session = filp->private_data; + + if ( 0 == length ) + { + return -EINVAL; + } + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (NULL == map) + { + WARN_ON(1); + err = -ENOMEM; + goto out; + } + + /* unpack our arg */ +#if defined CONFIG_64BIT && CONFIG_64BIT + if (is_compat_task()) + { +#endif + id = vma->vm_pgoff >> UMP_LINUX_OFFSET_BITS_32; + offset = vma->vm_pgoff & UMP_LINUX_OFFSET_MASK_32; +#if defined CONFIG_64BIT && CONFIG_64BIT + } + else + { + id = vma->vm_pgoff >> UMP_LINUX_OFFSET_BITS_64; + offset = vma->vm_pgoff & UMP_LINUX_OFFSET_MASK_64; + } +#endif + + h = ump_dd_from_secure_id(id); + if (UMP_DD_INVALID_MEMORY_HANDLE != h) + { + uint64_t i; + uint64_t block_idx; + uint64_t block_offset; + uint64_t paddr; + umpp_allocation * alloc; + uint64_t last_byte; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_IO | VM_MIXEDMAP | VM_DONTDUMP; +#else + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO | VM_MIXEDMAP; +#endif + vma->vm_ops = &umpp_vm_ops; + vma->vm_private_data = map; + + alloc = (umpp_allocation*)h; + + if( (alloc->flags & UMP_CONSTRAINT_UNCACHED) != 0) + { + /* cache disabled flag set, disable caching for cpu mappings */ + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + } + + last_byte = length + (offset << PAGE_SHIFT) - 1; + if (last_byte >= alloc->size || last_byte < (offset << PAGE_SHIFT)) + { + goto err_out; + } + + if (umpp_dd_find_start_block(alloc, offset << PAGE_SHIFT, &block_idx, &block_offset)) + { + goto err_out; + } + + paddr = alloc->block_array[block_idx].addr + block_offset; + + for (i = 0; i < (length >> PAGE_SHIFT); i++) + { + /* check if we've overrrun the current block, if so move to the next block */ + if (paddr >= (alloc->block_array[block_idx].addr + alloc->block_array[block_idx].size)) + { + block_idx++; + UMP_ASSERT(block_idx < alloc->blocksCount); + paddr = alloc->block_array[block_idx].addr; + } + + err = vm_insert_mixed(vma, vma->vm_start + (i << PAGE_SHIFT), paddr >> PAGE_SHIFT); + paddr += PAGE_SIZE; + } + + map->vaddr_start = (void*)vma->vm_start; + map->nr_pages = length >> PAGE_SHIFT; + map->page_off = offset; + map->handle = h; + map->session = session; + + umpp_dd_add_cpu_mapping(h, map); + + return 0; + + err_out: + + ump_dd_release(h); + } + + kfree(map); + +out: + + return err; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.h new file mode 100644 index 0000000000000000000000000000000000000000..40dcd30bd3be809c509023714947411975a1f0ce --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/linux/ump_kernel_linux_mem.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_KERNEL_LINUX_MEM_H_ +#define _UMP_KERNEL_LINUX_MEM_H_ + + +int umpp_linux_mmap(struct file * filp, struct vm_area_struct * vma); + +#endif /* _UMP_KERNEL_LINUX_MEM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..1a32127658b1302487adf5ea4863aeeea6dbdbb7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/sconscript @@ -0,0 +1,77 @@ +# +# (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +import re +Import('env') + +# Clone the environment so changes don't affect other build files +env_ump = env.Clone() + +if env_ump['v'] != '1': + env_ump['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +# Source files required for UMP. +ump_src = [Glob('#kernel/drivers/base/ump/src/linux/*.c'), Glob('#kernel/drivers/base/ump/src/common/*.c'), Glob('#kernel/drivers/base/ump/src/imports/*/*.c')] + +env_ump.Append( CPPPATH='#kernel/drivers/base/ump/src/' ) + +# Note: cleaning via the Linux kernel build system does not yet work +if env_ump.GetOption('clean') : + makeAction=Action("cd ${SOURCE.dir}/.. && make clean", '$MAKECOMSTR') +else: + if env['unit'] == '1': + makeAction=Action("cd ${SOURCE.dir}/.. && make MALI_UNIT_TEST=${unit} PLATFORM=${platform} %s && cp ump.ko $STATIC_LIB_PATH/ump.ko" % env.kernel_get_config_defines(), '$MAKECOMSTR') + else: + makeAction=Action("cd ${SOURCE.dir}/.. && make PLATFORM=${platform} %s && cp ump.ko $STATIC_LIB_PATH/ump.ko" % env.kernel_get_config_defines(), '$MAKECOMSTR') +# The target is ump.ko, built from the source in ump_src, via the action makeAction +# ump.ko will be copied to $STATIC_LIB_PATH after being built by the standard Linux +# kernel build system, after which it can be installed to the directory specified if +# "libs_install" is set; this is done by LibTarget. +cmd = env_ump.Command('$STATIC_LIB_PATH/ump.ko', ump_src, [makeAction]) + +if env['unit'] == '1': + env.Depends('$STATIC_LIB_PATH/ump.ko', '$STATIC_LIB_PATH/libosk.a') + +# Add a dependency on kds.ko only when the build is not Android +# Android uses sync_pt instead of Midgard KDS to achieve KDS functionality +# Only necessary when KDS is not built into the kernel. +# +if env['os'] != 'android': + linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' + search_term = '^[\ ]*CONFIG_KDS[\ ]*=[\ ]*y' + kds_in_kernel = 0 + for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + # KDS in kernel. + kds_in_kernel = 1 + if not kds_in_kernel: + env.Depends('$STATIC_LIB_PATH/ump.ko', '$STATIC_LIB_PATH/kds.ko') + +# Until we fathom out how the invoke the Linux build system to clean, we can use Clean +# to remove generated files. + +patterns = ['*.mod.c', '*.o', '*.ko', '*.a', '.*.cmd', 'modules.order', '.tmp_versions', 'Module.symvers'] + +for p in patterns: + Clean(cmd, Glob('#kernel/drivers/base/ump/src/common/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/base/ump/src/linux/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/base/ump/src/%s' % p)) + +env_ump.ProgTarget('ump', cmd) + +SConscript( 'imports/sconscript' ) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/ump_arch.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/ump_arch.h new file mode 100644 index 0000000000000000000000000000000000000000..bbbadabef11ac8a6c05f5d7a0c7310caf119e89e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/src/ump_arch.h @@ -0,0 +1,42 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_ARCH_H_ +#define _UMP_ARCH_H_ + +#include + +/** + * Device specific setup. + * Called by the UMP core code to to host OS/device specific setup. + * Typical use case is device node creation for talking to user space. + * @return UMP_OK on success, any other value on failure + */ +extern ump_result umpp_device_initialize(void); + +/** + * Device specific teardown. + * Undo any things done by ump_device_initialize. + */ +extern void umpp_device_terminate(void); + +extern int umpp_phys_commit(umpp_allocation * alloc); +extern void umpp_phys_free(umpp_allocation * alloc); + +#endif /* _UMP_ARCH_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/ump_ref_drv.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/ump_ref_drv.h new file mode 100644 index 0000000000000000000000000000000000000000..60018326597acf5c4f1315dc17810b4cf92068ad --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/base/ump/ump_ref_drv.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file ump_ref_drv.h + * + * This file contains the link to user space part of the UMP API for usage by MALI 400 gralloc. + * + */ + +#ifndef _UMP_REF_DRV_H_ +#define _UMP_REF_DRV_H_ + +#include + + +#endif /* _UMP_REF_DRV_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..b2480dfba4c6859791bda64a8be2da93085865e5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += arm/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..243e092d189b1bec18b609896f6db932265d2348 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Kbuild @@ -0,0 +1,17 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +CONFIG_MALI_MIDGARD := y + +obj-$(CONFIG_MALI_MIDGARD) += midgard/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..1f30eb541d65256b153abbf1e3b39094571d2650 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Kconfig @@ -0,0 +1,19 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +menu "ARM GPU Configuration" +source "drivers/gpu/arm/midgard/Kconfig" +endmenu diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..590cc4b4b9525abb57a9fada1f05c3147ae4e777 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += midgard/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..7c823c4931065b053b85b07bdb6bd92be2c52d60 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kbuild @@ -0,0 +1,264 @@ +# +# (C) COPYRIGHT 2012,2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +#MTK port custom Kbuild +#To Add 1.environment variable +include $(src)/Kbuild-mtk-custom-env + +# Driver version string which is returned to userspace via an ioctl +MALI_RELEASE_NAME ?= "r5p1-00rel1" + +# Paths required for build +KBASE_PATH = $(src) +KBASE_PLATFORM_PATH = $(KBASE_PATH)/platform_dummy +UMP_PATH = $(src)/../../../base + +ifeq ($(CONFIG_MALI_ERROR_INJECTION),y) +MALI_ERROR_INJECT_ON = 1 +endif + +# Set up defaults if not defined by build system +MALI_CUSTOMER_RELEASE ?= 1 +MALI_UNIT_TEST ?= 0 +MALI_KERNEL_TEST_API ?= 0 +MALI_ERROR_INJECT_ON ?= 0 +MALI_MOCK_TEST ?= 0 +MALI_COVERAGE ?= 0 +MALI_INSTRUMENTATION_LEVEL ?= 0 +# This workaround is for what seems to be a compiler bug we observed in +# GCC 4.7 on AOSP 4.3. The bug caused an intermittent failure compiling +# the "_Pragma" syntax, where an error message is returned: +# +# "internal compiler error: unspellable token PRAGMA" +# +# This regression has thus far only been seen on the GCC 4.7 compiler bundled +# with AOSP 4.3.0. So this makefile, intended for in-tree kernel builds +# which are not known to be used with AOSP, is hardcoded to disable the +# workaround, i.e. set the define to 0. +MALI_GCC_WORKAROUND_MIDCOM_4598 ?= 0 + +# Set up our defines, which will be passed to gcc +DEFINES = \ + -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \ + -DMALI_KERNEL_TEST_API=$(MALI_KERNEL_TEST_API) \ + -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \ + -DMALI_ERROR_INJECT_ON=$(MALI_ERROR_INJECT_ON) \ + -DMALI_MOCK_TEST=$(MALI_MOCK_TEST) \ + -DMALI_COVERAGE=$(MALI_COVERAGE) \ + -DMALI_INSTRUMENTATION_LEVEL=$(MALI_INSTRUMENTATION_LEVEL) \ + -DMALI_RELEASE_NAME=\"$(MALI_RELEASE_NAME)\" \ + -DMALI_GCC_WORKAROUND_MIDCOM_4598=$(MALI_GCC_WORKAROUND_MIDCOM_4598) + +ifeq ($(KBUILD_EXTMOD),) +# in-tree +DEFINES +=-DMALI_KBASE_THIRDPARTY_PATH=../../$(src)/platform/$(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME) +else +# out-of-tree +DEFINES +=-DMALI_KBASE_THIRDPARTY_PATH=$(src)/platform/$(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME) +endif + +DEFINES += -I$(srctree)/drivers/staging/android + +# Use our defines when compiling +ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(KBASE_PLATFORM_PATH) -I$(UMP_PATH) -I$(srctree)/include/linux +subdir-ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(KBASE_PLATFORM_PATH) -I$(OSK_PATH) -I$(UMP_PATH) -I$(srctree)/include/linux + +SRC := \ + mali_kbase_device.c \ + mali_kbase_cache_policy.c \ + mali_kbase_mem.c \ + mali_kbase_mmu.c \ + mali_kbase_jd.c \ + mali_kbase_jd_debugfs.c \ + mali_kbase_jm.c \ + mali_kbase_cpuprops.c \ + mali_kbase_gpuprops.c \ + mali_kbase_js.c \ + mali_kbase_js_affinity.c \ + mali_kbase_js_ctx_attr.c \ + mali_kbase_event.c \ + mali_kbase_context.c \ + mali_kbase_pm.c \ + mali_kbase_pm_driver.c \ + mali_kbase_pm_metrics.c \ + mali_kbase_pm_ca.c \ + mali_kbase_pm_ca_fixed.c \ + mali_kbase_pm_always_on.c \ + mali_kbase_pm_coarse_demand.c \ + mali_kbase_pm_demand.c \ + mali_kbase_pm_policy.c \ + mali_kbase_config.c \ + mali_kbase_security.c \ + mali_kbase_instr.c \ + mali_kbase_softjobs.c \ + mali_kbase_10969_workaround.c \ + mali_kbase_hw.c \ + mali_kbase_utility.c \ + mali_kbase_debug.c \ + mali_kbase_trace_timeline.c \ + mali_kbase_gpu_memory_debugfs.c \ + mali_kbase_mem_linux.c \ + mali_kbase_core_linux.c \ + mali_kbase_sync.c \ + mali_kbase_sync_user.c \ + mali_kbase_replay.c \ + mali_kbase_mem_profile_debugfs.c \ + mali_kbase_mmu_hw_direct.c \ + mali_kbase_disjoint_events.c \ + mali_kbase_gator_api.c + +ifeq ($(MALI_CUSTOMER_RELEASE),0) +SRC += \ + mali_kbase_pm_ca_random.c \ + mali_kbase_pm_demand_always_powered.c \ + mali_kbase_pm_fast_start.c +endif + +# Job Scheduler Policy: Completely Fair Scheduler +SRC += mali_kbase_js_policy_cfs.c + +ifeq ($(CONFIG_MACH_MANTA),y) + SRC += mali_kbase_mem_alloc_carveout.c +else + SRC += mali_kbase_mem_alloc.c +endif + +# ensure GPL version of malisw gets pulled in +ccflags-y += -I$(KBASE_PATH) + +ifeq ($(CONFIG_MALI_NO_MALI),y) + # Dummy model + SRC += mali_kbase_model_dummy.c + SRC += mali_kbase_model_linux.c + # HW error simulation + SRC += mali_kbase_model_error_generator.c +endif + +ifeq ($(MALI_MOCK_TEST),1) + # Test functionality + SRC += tests/internal/src/mock/mali_kbase_pm_driver_mock.c +endif + +# in-tree/out-of-tree logic needs to be slightly different to determine if a file is present +ifeq ($(KBUILD_EXTMOD),) +# in-tree +MALI_METRICS_PATH = $(srctree)/drivers/gpu/arm/midgard +else +# out-of-tree +MALI_METRICS_PATH = $(KBUILD_EXTMOD) +endif + +# Use vsync metrics example using PL111 driver, if available +ifeq ($(wildcard $(MALI_METRICS_PATH)/mali_kbase_pm_metrics_linux.c),) + SRC += mali_kbase_pm_metrics_dummy.c +else + SRC += mali_kbase_pm_metrics_linux.c +endif + +ifeq ($(CONFIG_MALI_PLATFORM_FAKE),y) + SRC += mali_kbase_platform_fake.c + + ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS),y) + SRC += platform/vexpress/mali_kbase_config_vexpress.c \ + platform/vexpress/mali_kbase_cpu_vexpress.c + ccflags-y += -I$(src)/platform/vexpress + endif + + ifeq ($(CONFIG_MALI_PLATFORM_RTSM_VE),y) + SRC += platform/rtsm_ve/mali_kbase_config_vexpress.c + ccflags-y += -I$(src)/platform/rtsm_ve + endif + + ifeq ($(CONFIG_MALI_PLATFORM_JUNO),y) + SRC += platform/juno/mali_kbase_config_vexpress.c + ccflags-y += -I$(src)/platform/juno + endif + + ifeq ($(CONFIG_MALI_PLATFORM_JUNO_SOC),y) + SRC += platform/juno_soc/mali_kbase_config_juno_soc.c + ccflags-y += -I$(src)/platform/juno_soc + endif + + ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS_1XV7_A57),y) + SRC += platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c + ccflags-y += -I$(src)/platform/vexpress_1xv7_a57 + endif + + ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ),y) + SRC += platform/vexpress_virtex7_40mhz/mali_kbase_config_vexpress.c \ + platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.c + ccflags-y += -I$(src)/platform/vexpress_virtex7_40mhz + endif + + ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS_6XVIRTEX7_10MHZ),y) + SRC += platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c \ + platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c + ccflags-y += -I$(src)/platform/vexpress_6xvirtex7_10mhz + endif + + ifeq ($(CONFIG_MALI_PLATFORM_GOLDFISH),y) + SRC += platform/goldfish/mali_kbase_config_goldfish.c + ccflags-y += -I$(src)/platform/goldfish + endif + + ifeq ($(CONFIG_MALI_PLATFORM_PBX),y) + SRC += platform/pbx/mali_kbase_config_pbx.c + ccflags-y += -I$(src)/platform/pbx + endif + + ifeq ($(CONFIG_MALI_PLATFORM_PANDA),y) + SRC += platform/panda/mali_kbase_config_panda.c + ccflags-y += -I$(src)/platform/panda + endif + + ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y) + # remove begin and end quotes from the Kconfig string type + platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)) + MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name) + ccflags-y += -I$(src)/$(MALI_PLATFORM_THIRDPARTY_DIR) + ifeq ($(CONFIG_MALI_MIDGARD),m) + include $(src)/platform/$(platform_name)/Kbuild + else ifeq ($(CONFIG_MALI_MIDGARD),y) + obj-$(CONFIG_MALI_MIDGARD) += platform/ + endif + endif +endif # CONFIG_MALI_PLATFORM_FAKE=y + +ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y) +# remove begin and end quotes from the Kconfig string type +platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)) +MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name) +ccflags-y += -I$(src)/$(MALI_PLATFORM_THIRDPARTY_DIR) +ifeq ($(CONFIG_MALI_MIDGARD),m) +include $(src)/platform/$(platform_name)/Kbuild +else ifeq ($(CONFIG_MALI_MIDGARD),y) +obj-$(CONFIG_MALI_MIDGARD) += platform/ +endif +endif + +# Tell the Linux build system from which .o file to create the kernel module +obj-$(CONFIG_MALI_MIDGARD) += mali_kbase.o + +# Tell the Linux build system to enable building of our .c files +mali_kbase-y := $(SRC:.c=.o) + +mali_kbase-$(CONFIG_MALI_DEVFREQ) += mali_kbase_devfreq.o +mali_kbase-$(CONFIG_MALI_POWER_ACTOR) += mali_kbase_power_actor.o + +ifneq ($(wildcard $(src)/internal/Kbuild),) +ifeq ($(MALI_CUSTOMER_RELEASE),0) +include $(src)/internal/Kbuild +mali_kbase-y += $(INTERNAL:.c=.o) +endif +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kbuild-mtk-custom-env b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kbuild-mtk-custom-env new file mode 100755 index 0000000000000000000000000000000000000000..b9e4fcb8580d9579a12772bf3744a4529ff604b9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kbuild-mtk-custom-env @@ -0,0 +1,41 @@ +$(info mali MTK evironment) + +#build support for a ARM Mali Midgard GPU +CONFIG_MALI_MIDGARD := y + +#use mt6755 platform +CONFIG_MALI_PLATFORM_THIRDPARTY := n +CONFIG_MALI_PLATFORM_THIRDPARTY_NAME := vexpress + +CONFIG_MALI_PLATFORM_FAKE := y + +CONFIG_MALI_PLATFORM_VEXPRESS := y +CONFIG_MALI_DEBUG := y + +ccflags-y += -DCONFIG_MALI_PLATFORM_FAKE +ccflags-y += -DCONFIG_MALI_MIDGARD_DVFS + +#Add include path for kernel 3.10 +ccflags-y += -I-I$(srctree)/include + +#Add include path for linux sync.h +ccflags-y += -I$(srctree)/drivers/staging/android + +#include clock manager for clock use +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/mt6755/include + +VER:=eng +ifneq ($(strip $(TARGET_BUILD_VARIANT)),) +ifneq ($(strip $(TARGET_BUILD_VARIANT)),eng) +VER:=user +endif +endif + +ccflags-y += -DCONFIG_DEBUG_FS +ccflags-y += -DCONFIG_PROC_FS + +ifeq ($(VER),eng) +ccflags-y += -DCONFIG_MALI_DEBUG +else +ccflags-y += -UCONFIG_MALI_DEBUG +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..852b2b6fb447801e528f809ffc5e17f6a5b453eb --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Kconfig @@ -0,0 +1,193 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +menuconfig MALI_MIDGARD + tristate "Mali Midgard series support" + default n + help + Enable this option to build support for a ARM Mali Midgard GPU. + + To compile this driver as a module, choose M here: + this will generate a single module, called mali_kbase. + +config MALI_GATOR_SUPPORT + bool "Streamline Debug support" + depends on MALI_MIDGARD + default n + help + Adds diagnostic support for use with the ARM Streamline Performance Analyzer. + You will need the Gator device driver already loaded before loading this driver when enabling + Streamline debug support. + +config MALI_MIDGARD_DVFS + bool "Enable DVFS" + depends on MALI_MIDGARD + default n + help + Choose this option to enable DVFS in the Mali Midgard DDK. + +config MALI_MIDGARD_RT_PM + bool "Enable Runtime power management" + depends on MALI_MIDGARD + depends on PM_RUNTIME + default n + help + Choose this option to enable runtime power management in the Mali Midgard DDK. + +config MALI_MIDGARD_ENABLE_TRACE + bool "Enable kbase tracing" + depends on MALI_MIDGARD + default n + help + Enables tracing in kbase. Trace log available through + the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled + +config MALI_MIDGARD_DEBUG_SYS + bool "Enable sysfs for the Mali Midgard DDK " + depends on MALI_MIDGARD && SYSFS + default n + help + Enables sysfs for the Mali Midgard DDK. Set/Monitor the Mali Midgard DDK + +# MALI_EXPERT configuration options + +menuconfig MALI_EXPERT + depends on MALI_MIDGARD + bool "Enable Expert Settings" + default n + help + Enabling this option and modifying the default settings may produce a driver with performance or + other limitations. + +config MALI_DEVFREQ + bool "devfreq support for Mali" + depends on MALI_MIDGARD && PM_DEVFREQ + help + Support devfreq for Mali. + + Using the devfreq framework and, by default, the simpleondemand + governor, the frequency of Mali will be dynamically selected from the + available OPPs. + +config MALI_POWER_ACTOR + bool "Thermal API support for Mali" + depends on MALI_MIDGARD && DEVFREQ_THERMAL && THERMAL_POWER_ACTOR + help + Support the thermal API for Mali. + + This can be used with the power allocator thermal governor to + dynamically allocate the power budget to Mali. + +config MALI_DEBUG_SHADER_SPLIT_FS + bool "Allow mapping of shader cores via sysfs" + depends on MALI_MIDGARD && MALI_MIDGARD_DEBUG_SYS && MALI_EXPERT + default n + help + Select this option to provide a sysfs entry for runtime configuration of shader + core affinity masks. + +config MALI_PLATFORM_FAKE + bool "Enable fake platform device support" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + When you start to work with the Mali Midgard series device driver the platform-specific code of + the Linux kernel for your platform may not be complete. In this situation the kernel device driver + supports creating the platform device outside of the Linux platform-specific code. + Enable this option if would like to use a platform device configuration from within the device driver. + +choice + prompt "Platform configuration" + depends on MALI_MIDGARD && MALI_EXPERT + default MALI_PLATFORM_VEXPRESS + help + Select the SOC platform that contains a Mali Midgard GPU + +config MALI_PLATFORM_VEXPRESS + depends on ARCH_VEXPRESS && (ARCH_VEXPRESS_CA9X4 || ARCH_VEXPRESS_CA15X4) + bool "Versatile Express" +config MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ + depends on ARCH_VEXPRESS && (ARCH_VEXPRESS_CA9X4 || ARCH_VEXPRESS_CA15X4) + bool "Versatile Express w/Virtex7 @ 40Mhz" +config MALI_PLATFORM_GOLDFISH + depends on ARCH_GOLDFISH + bool "Android Goldfish virtual CPU" +config MALI_PLATFORM_PBX + depends on ARCH_REALVIEW && REALVIEW_EB_A9MP && MACH_REALVIEW_PBX + bool "Realview PBX-A9" +config MALI_PLATFORM_THIRDPARTY + bool "Third Party Platform" +endchoice + +config MALI_PLATFORM_THIRDPARTY_NAME + depends on MALI_MIDGARD && MALI_PLATFORM_THIRDPARTY && MALI_EXPERT + string "Third party platform name" + help + Enter the name of a third party platform that is supported. The third part configuration + file must be in midgard/config/tpip/mali_kbase_config_xxx.c where xxx is the name + specified here. + +config MALI_DEBUG + bool "Debug build" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Select this option for increased checking and reporting of errors. + +config MALI_NO_MALI + bool "No Mali" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + This can be used to test the driver in a simulated environment + whereby the hardware is not physically present. If the hardware is physically + present it will not be used. This can be used to test the majority of the + driver without needing actual hardware or for software benchmarking. + All calls to the simulated hardware will complete immediately as if the hardware + completed the task. + +config MALI_ERROR_INJECT + bool "Error injection" + depends on MALI_MIDGARD && MALI_EXPERT && MALI_NO_MALI + default n + help + Enables insertion of errors to test module failure and recovery mechanisms. + +config MALI_TRACE_TIMELINE + bool "Timeline tracing" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Enables timeline tracing through the kernel tracepoint system. + +config MALI_SYSTEM_TRACE + bool "Enable system event tracing support" + depends on MALI_MIDGARD && MALI_EXPERT + default n + help + Choose this option to enable system trace events for each + kbase event. This is typically used for debugging but has + minimal overhead when not in use. Enable only if you know what + you are doing. + +config MALI_GPU_TRACEPOINTS + bool "Enable GPU tracepoints" + depends on MALI_MIDGARD && ANDROID + select GPU_TRACEPOINTS + help + Enables GPU tracepoints using Android trace event definitions. + +source "drivers/gpu/arm/midgard/platform/Kconfig" diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..9820be2b4446f4e24dc261fa0a1e0295a12efe3b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Makefile @@ -0,0 +1,36 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +KDIR ?= /lib/modules/$(shell uname -r)/build + +UMP_PATH_RELATIVE = $(CURDIR)/../../../base/ump +KBASE_PATH_RELATIVE = $(CURDIR) +KDS_PATH_RELATIVE = $(CURDIR)/../../../.. +EXTRA_SYMBOLS = $(UMP_PATH_RELATIVE)/src/Module.symvers + +ifeq ($(MALI_UNIT_TEST), 1) + EXTRA_SYMBOLS += $(KBASE_PATH_RELATIVE)/tests/internal/src/kernel_assert_module/linux/Module.symvers +endif + +# GPL driver supports KDS +EXTRA_SYMBOLS += $(KDS_PATH_RELATIVE)/drivers/base/kds/Module.symvers + +# we get the symbols from modules using KBUILD_EXTRA_SYMBOLS to prevent warnings about unknown functions +all: + $(MAKE) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../include $(SCONS_CFLAGS)" $(SCONS_CONFIGS) KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules + +clean: + $(MAKE) -C $(KDIR) M=$(CURDIR) clean diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Makefile.kbase b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Makefile.kbase new file mode 100755 index 0000000000000000000000000000000000000000..2bef9c25eaeb89307738e77ed2a1f7fc5602639b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/Makefile.kbase @@ -0,0 +1,17 @@ +# +# (C) COPYRIGHT 2010 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +EXTRA_CFLAGS += -I$(ROOT) -I$(KBASE_PATH) -I$(OSK_PATH)/src/linux/include -I$(KBASE_PATH)/platform_$(PLATFORM) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/Doxyfile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/Doxyfile new file mode 100755 index 0000000000000000000000000000000000000000..e2662c2dfaeb6e58a5a0261adc796b2d37848a64 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/Doxyfile @@ -0,0 +1,126 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +############################################################################## + +# This file contains per-module Doxygen configuration. Please do not add +# extra settings to this file without consulting all stakeholders, as they +# may cause override project-wide settings. +# +# Additionally, when defining aliases, macros, sections etc, use the module +# name as a prefix e.g. gles_my_alias. + +############################################################################## + +@INCLUDE = ../../bldsys/Doxyfile_common + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT += ../../kernel/drivers/gpu/arm/midgard/ + +############################################################################## +# Everything below here is optional, and in most cases not required +############################################################################## + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES += + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS += + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS += + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +EXCLUDE += ../../kernel/drivers/gpu/arm/midgard/malisw/ ../../kernel/drivers/gpu/arm/midgard/platform ../../kernel/drivers/gpu/arm/midgard/platform_dummy ../../kernel/drivers/gpu/arm/midgard/scripts ../../kernel/drivers/gpu/arm/midgard/tests ../../kernel/drivers/gpu/arm/midgard/Makefile ../../kernel/drivers/gpu/arm/midgard/Makefile.kbase ../../kernel/drivers/gpu/arm/midgard/Kbuild ../../kernel/drivers/gpu/arm/midgard/Kconfig ../../kernel/drivers/gpu/arm/midgard/sconscript ../../kernel/drivers/gpu/arm/midgard/docs ../../kernel/drivers/gpu/arm/midgard/pm_test_script.sh ../../kernel/drivers/gpu/arm/midgard/mali_uk.h ../../kernel/drivers/gpu/arm/midgard/Makefile + + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS += + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS += + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH += + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH += + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH += + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED += + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED += + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS += ../../kernel/drivers/gpu/arm/midgard/docs + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/policy_operation_diagram.dot b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/policy_operation_diagram.dot new file mode 100644 index 0000000000000000000000000000000000000000..a70b54947088794911513049b069a5afda530bb5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/policy_operation_diagram.dot @@ -0,0 +1,112 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +digraph policy_objects_diagram { + rankdir=LR; + size="12,8"; + compound=true; + + node [ shape = box ]; + + subgraph cluster_policy_queues { + low_queue [ shape=record label = "LowP | {ctx_lo | ... | ctx_i | ... | ctx_hi}" ]; + queues_middle_sep [ label="" shape=plaintext width=0 height=0 ]; + + rt_queue [ shape=record label = "RT | {ctx_lo | ... | ctx_j | ... | ctx_hi}" ]; + + label = "Policy's Queue(s)"; + } + + call_enqueue [ shape=plaintext label="enqueue_ctx()" ]; + + { + rank=same; + ordering=out; + call_dequeue [ shape=plaintext label="dequeue_head_ctx()\n+ runpool_add_ctx()" ]; + call_ctxfinish [ shape=plaintext label="runpool_remove_ctx()" ]; + + call_ctxdone [ shape=plaintext label="don't requeue;\n/* ctx has no more jobs */" ]; + } + + subgraph cluster_runpool { + + as0 [ width=2 height = 0.25 label="AS0: Job_1, ..., Job_n" ]; + as1 [ width=2 height = 0.25 label="AS1: Job_1, ..., Job_m" ]; + as2 [ width=2 height = 0.25 label="AS2: Job_1, ..., Job_p" ]; + as3 [ width=2 height = 0.25 label="AS3: Job_1, ..., Job_q" ]; + + label = "Policy's Run Pool"; + } + + { + rank=same; + call_jdequeue [ shape=plaintext label="dequeue_job()" ]; + sstop_dotfixup [ shape=plaintext label="" width=0 height=0 ]; + } + + { + rank=same; + ordering=out; + sstop [ shape=ellipse label="SS-Timer expires" ] + jobslots [ shape=record label="Jobslots: | <0>js[0] | <1>js[1] | <2>js[2]" ]; + + irq [ label="IRQ" shape=ellipse ]; + + job_finish [ shape=plaintext label="don't requeue;\n/* job done */" ]; + } + + hstop [ shape=ellipse label="HS-Timer expires" ] + + /* + * Edges + */ + + call_enqueue -> queues_middle_sep [ lhead=cluster_policy_queues ]; + + low_queue:qr -> call_dequeue:w; + rt_queue:qr -> call_dequeue:w; + + call_dequeue -> as1 [lhead=cluster_runpool]; + + as1->call_jdequeue [ltail=cluster_runpool]; + call_jdequeue->jobslots:0; + call_jdequeue->sstop_dotfixup [ arrowhead=none]; + sstop_dotfixup->sstop [label="Spawn SS-Timer"]; + sstop->jobslots [label="SoftStop"]; + sstop->hstop [label="Spawn HS-Timer"]; + hstop->jobslots:ne [label="HardStop"]; + + + as3->call_ctxfinish:ne [ ltail=cluster_runpool ]; + call_ctxfinish:sw->rt_queue:qm [ lhead=cluster_policy_queues label="enqueue_ctx()\n/* ctx still has jobs */" ]; + + call_ctxfinish->call_ctxdone [constraint=false]; + + call_ctxdone->call_enqueue [weight=0.1 labeldistance=20.0 labelangle=0.0 taillabel="Job submitted to the ctx" style=dotted constraint=false]; + + + { + jobslots->irq [constraint=false]; + + irq->job_finish [constraint=false]; + } + + irq->as2 [lhead=cluster_runpool label="requeue_job()\n/* timeslice expired */" ]; + +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/policy_overview.dot b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/policy_overview.dot new file mode 100644 index 0000000000000000000000000000000000000000..bd5e21b074ca10755569e8fc7c94b872615fdf67 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/docs/policy_overview.dot @@ -0,0 +1,63 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +digraph policy_objects_diagram { + rankdir=LR + size="6,6" + compound=true; + + node [ shape = box ]; + + call_enqueue [ shape=plaintext label="enqueue ctx" ]; + + + policy_queue [ label="Policy's Queue" ]; + + { + rank=same; + runpool [ label="Policy's Run Pool" ]; + + ctx_finish [ label="ctx finished" ]; + } + + { + rank=same; + jobslots [ shape=record label="Jobslots: | <0>js[0] | <1>js[1] | <2>js[2]" ]; + + job_finish [ label="Job finished" ]; + } + + + + /* + * Edges + */ + + call_enqueue -> policy_queue; + + policy_queue->runpool [label="dequeue ctx" weight=0.1]; + runpool->policy_queue [label="requeue ctx" weight=0.1]; + + runpool->ctx_finish [ style=dotted ]; + + runpool->jobslots [label="dequeue job" weight=0.1]; + jobslots->runpool [label="requeue job" weight=0.1]; + + jobslots->job_finish [ style=dotted ]; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..963d6329eceb4b1b0c6000d0b9f395d791eb3b05 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig.h @@ -0,0 +1,31 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file + * Software workarounds configuration for Hardware issues. + */ + +#ifndef _BASE_HWCONFIG_H_ +#define _BASE_HWCONFIG_H_ + +#include + +#include "mali_base_hwconfig_issues.h" +#include "mali_base_hwconfig_features.h" + +#endif /* _BASE_HWCONFIG_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h new file mode 100644 index 0000000000000000000000000000000000000000..da582a596b5bcb00bd997193293776fa32b15539 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h @@ -0,0 +1,117 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features, + * please update user/midgard/mali_base_hwconfig_{issues,features}.h and + * re-run hwconfig_header_generator instead. This tool is available in + * progs_install directory for host builds. More information is available in + * base/tools/hwconfig_header_generator/README */ + +#ifndef _BASE_HWCONFIG_FEATURES_H_ +#define _BASE_HWCONFIG_FEATURES_H_ + +enum base_hw_feature { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_OPTIMIZED_COVERAGE_MASK, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_WORKGROUP_ROUND_MULTIPLE_OF_4, + BASE_HW_FEATURE_IMAGES_IN_FRAGMENT_SHADERS, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_generic[] = { + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t60x[] = { + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t62x[] = { + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t72x[] = { + BASE_HW_FEATURE_33BIT_VA, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_INTERPIPE_REG_ALIASING, + BASE_HW_FEATURE_OPTIMIZED_COVERAGE_MASK, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_WORKGROUP_ROUND_MULTIPLE_OF_4, + BASE_HW_FEATURE_WARPING, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_t76x[] = { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_END +}; + +static const enum base_hw_feature base_hw_features_tFxx[] = { + BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION, + BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS, + BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS, + BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL, + BASE_HW_FEATURE_BRNDOUT_CC, + BASE_HW_FEATURE_BRNDOUT_KILL, + BASE_HW_FEATURE_LD_ST_LEA_TEX, + BASE_HW_FEATURE_LD_ST_TILEBUFFER, + BASE_HW_FEATURE_LINEAR_FILTER_FLOAT, + BASE_HW_FEATURE_MRT, + BASE_HW_FEATURE_MSAA_16X, + BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE, + BASE_HW_FEATURE_OUT_OF_ORDER_EXEC, + BASE_HW_FEATURE_T7XX_PAIRING_RULES, + BASE_HW_FEATURE_TEST4_DATUM_MODE, + BASE_HW_FEATURE_END +}; + +#endif /* _BASE_HWCONFIG_FEATURES_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h new file mode 100644 index 0000000000000000000000000000000000000000..e7aa7d8347c65fad61d657aa0e05f3e9f5a68583 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h @@ -0,0 +1,699 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features, + * please update user/midgard/mali_base_hwconfig_{issues,features}.h and + * re-run hwconfig_header_generator instead. This tool is available in + * progs_install directory for host builds. More information is available in + * base/tools/hwconfig_header_generator/README */ + +#ifndef _BASE_HWCONFIG_ISSUES_H_ +#define _BASE_HWCONFIG_ISSUES_H_ + +enum base_hw_issue { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6398, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7144, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8073, + BASE_HW_ISSUE_8186, + BASE_HW_ISSUE_8215, + BASE_HW_ISSUE_8245, + BASE_HW_ISSUE_8250, + BASE_HW_ISSUE_8260, + BASE_HW_ISSUE_8280, + BASE_HW_ISSUE_8316, + BASE_HW_ISSUE_8381, + BASE_HW_ISSUE_8394, + BASE_HW_ISSUE_8401, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8443, + BASE_HW_ISSUE_8456, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8634, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8791, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8833, + BASE_HW_ISSUE_8879, + BASE_HW_ISSUE_8896, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_8986, + BASE_HW_ISSUE_8987, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_9566, + BASE_HW_ISSUE_9630, + BASE_HW_ISSUE_10127, + BASE_HW_ISSUE_10327, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10817, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_10984, + BASE_HW_ISSUE_10995, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_2121, + BASE_HW_ISSUE_T76X_2315, + BASE_HW_ISSUE_T76X_2686, + BASE_HW_ISSUE_T76X_2712, + BASE_HW_ISSUE_T76X_2772, + BASE_HW_ISSUE_T76X_2906, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3285, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3759, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_generic[] = { + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p0_15dev0[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6398, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7144, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8073, + BASE_HW_ISSUE_8186, + BASE_HW_ISSUE_8215, + BASE_HW_ISSUE_8245, + BASE_HW_ISSUE_8250, + BASE_HW_ISSUE_8260, + BASE_HW_ISSUE_8280, + BASE_HW_ISSUE_8316, + BASE_HW_ISSUE_8381, + BASE_HW_ISSUE_8394, + BASE_HW_ISSUE_8401, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8443, + BASE_HW_ISSUE_8456, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8634, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8791, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8833, + BASE_HW_ISSUE_8896, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_8986, + BASE_HW_ISSUE_8987, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_9566, + BASE_HW_ISSUE_9630, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_10984, + BASE_HW_ISSUE_10995, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p0_eac[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9418, + BASE_HW_ISSUE_9423, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10969, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t60x_r0p1[] = { + BASE_HW_ISSUE_6367, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_6787, + BASE_HW_ISSUE_7027, + BASE_HW_ISSUE_7304, + BASE_HW_ISSUE_8408, + BASE_HW_ISSUE_8564, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8975, + BASE_HW_ISSUE_9010, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_9510, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r0p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10127, + BASE_HW_ISSUE_10327, + BASE_HW_ISSUE_10410, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10487, + BASE_HW_ISSUE_10607, + BASE_HW_ISSUE_10632, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10676, + BASE_HW_ISSUE_10682, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10817, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11035, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r1p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t62x_r1p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p0_beta[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_10959, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_2121, + BASE_HW_ISSUE_T76X_2315, + BASE_HW_ISSUE_T76X_2686, + BASE_HW_ISSUE_T76X_2712, + BASE_HW_ISSUE_T76X_2772, + BASE_HW_ISSUE_T76X_2906, + BASE_HW_ISSUE_T76X_3285, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3759, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p1[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p1_50rel0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p2[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r0p3[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_26, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3542, + BASE_HW_ISSUE_T76X_3556, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t76x_r1p0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r0p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r1p0[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t72x_r1p1[] = { + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10684, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t72x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10471, + BASE_HW_ISSUE_10797, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t76x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t60x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_8778, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t62x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_6402, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10472, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_11012, + BASE_HW_ISSUE_11020, + BASE_HW_ISSUE_11024, + BASE_HW_ISSUE_11042, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tFRx_r0p0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tFRx_r0p1[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_tFRx_r0p2[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_tFRx[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t86x_r0p0[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3960, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_t86x_r0p2[] = { + BASE_HW_ISSUE_8803, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10649, + BASE_HW_ISSUE_10821, + BASE_HW_ISSUE_10883, + BASE_HW_ISSUE_10946, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_T76X_3953, + BASE_HW_ISSUE_T76X_3966, + BASE_HW_ISSUE_END +}; + +static const enum base_hw_issue base_hw_issues_model_t86x[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9275, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_10931, + BASE_HW_ISSUE_T76X_1963, + BASE_HW_ISSUE_T76X_3086, + BASE_HW_ISSUE_T76X_3700, + BASE_HW_ISSUE_T76X_3793, + BASE_HW_ISSUE_END +}; + +#endif /* _BASE_HWCONFIG_ISSUES_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_kernel.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..02a255239cdd7fe64545cc699013c870444efe1a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_kernel.h @@ -0,0 +1,1569 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Base structures shared with the kernel. + */ + +#ifndef _BASE_KERNEL_H_ +#define _BASE_KERNEL_H_ + +#ifndef __user +#define __user +#endif + +/* Support UK6 IOCTLS */ +#define BASE_LEGACY_UK6_SUPPORT 1 + +/* Support UK7 IOCTLS */ +/* NB: To support UK6 we also need to support UK7 */ +#define BASE_LEGACY_UK7_SUPPORT 1 + +typedef mali_addr64 base_mem_handle; + +#include "mali_base_mem_priv.h" +#include "mali_kbase_profiling_gator_api.h" + +/* + * Dependency stuff, keep it private for now. May want to expose it if + * we decide to make the number of semaphores a configurable + * option. + */ +#define BASE_JD_ATOM_COUNT 256 + +#define BASEP_JD_SEM_PER_WORD_LOG2 5 +#define BASEP_JD_SEM_PER_WORD (1 << BASEP_JD_SEM_PER_WORD_LOG2) +#define BASEP_JD_SEM_WORD_NR(x) ((x) >> BASEP_JD_SEM_PER_WORD_LOG2) +#define BASEP_JD_SEM_MASK_IN_WORD(x) (1 << ((x) & (BASEP_JD_SEM_PER_WORD - 1))) +#define BASEP_JD_SEM_ARRAY_SIZE BASEP_JD_SEM_WORD_NR(BASE_JD_ATOM_COUNT) + +#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3 + +#define BASE_MAX_COHERENT_GROUPS 16 + +#if defined CDBG_ASSERT +#define LOCAL_ASSERT CDBG_ASSERT +#elif defined KBASE_DEBUG_ASSERT +#define LOCAL_ASSERT KBASE_DEBUG_ASSERT +#else +#error assert macro not defined! +#endif + +#if defined PAGE_MASK +#define LOCAL_PAGE_LSB ~PAGE_MASK +#else +#include + +#if defined OSU_CONFIG_CPU_PAGE_SIZE_LOG2 +#define LOCAL_PAGE_LSB ((1ul << OSU_CONFIG_CPU_PAGE_SIZE_LOG2) - 1) +#else +#error Failed to find page size +#endif +#endif + +/** 32/64-bit neutral way to represent pointers */ +typedef union kbase_pointer { + void __user *value; /**< client should store their pointers here */ + u32 compat_value; /**< 64-bit kernels should fetch value here when handling 32-bit clients */ + u64 sizer; /**< Force 64-bit storage for all clients regardless */ +} kbase_pointer; + +/** + * @addtogroup base_user_api User-side Base APIs + * @{ + */ + +/** + * @addtogroup base_user_api_memory User-side Base Memory APIs + * @{ + */ + +/** + * @brief Memory allocation, access/hint flags + * + * A combination of MEM_PROT/MEM_HINT flags must be passed to each allocator + * in order to determine the best cache policy. Some combinations are + * of course invalid (eg @c MEM_PROT_CPU_WR | @c MEM_HINT_CPU_RD), + * which defines a @a write-only region on the CPU side, which is + * heavily read by the CPU... + * Other flags are only meaningful to a particular allocator. + * More flags can be added to this list, as long as they don't clash + * (see ::BASE_MEM_FLAGS_NR_TOTAL_BITS for the number of the first free bit). + */ +typedef u32 base_mem_alloc_flags; + +/** + * @brief Memory allocation, access/hint flags + * + * See ::base_mem_alloc_flags. + * + */ +enum { +/* IN */ + BASE_MEM_PROT_CPU_RD = (1U << 0), /**< Read access CPU side */ + BASE_MEM_PROT_CPU_WR = (1U << 1), /**< Write access CPU side */ + BASE_MEM_PROT_GPU_RD = (1U << 2), /**< Read access GPU side */ + BASE_MEM_PROT_GPU_WR = (1U << 3), /**< Write access GPU side */ + BASE_MEM_PROT_GPU_EX = (1U << 4), /**< Execute allowed on the GPU + side */ + + /* Note that the HINT flags are obsolete now. If you want the memory + * to be cached on the CPU please use the BASE_MEM_CACHED_CPU flag + */ + BASE_MEM_HINT_CPU_RD = (1U << 5), /**< Heavily read CPU side + - OBSOLETE */ + BASE_MEM_HINT_CPU_WR = (1U << 6), /**< Heavily written CPU side + - OBSOLETE */ + BASE_MEM_HINT_GPU_RD = (1U << 7), /**< Heavily read GPU side + - OBSOLETE */ + BASE_MEM_HINT_GPU_WR = (1U << 8), /**< Heavily written GPU side + - OBSOLETE */ + + BASE_MEM_GROW_ON_GPF = (1U << 9), /**< Grow backing store on GPU + Page Fault */ + + BASE_MEM_COHERENT_SYSTEM = (1U << 10), /**< Page coherence Outer + shareable */ + BASE_MEM_COHERENT_LOCAL = (1U << 11), /**< Page coherence Inner + shareable */ + BASE_MEM_CACHED_CPU = (1U << 12), /**< Should be cached on the + CPU */ + +/* IN/OUT */ + BASE_MEM_SAME_VA = (1U << 13), /**< Must have same VA on both the GPU + and the CPU */ +/* OUT */ + BASE_MEM_NEED_MMAP = (1U << 14) /**< Must call mmap to aquire a GPU + address for the alloc */ +}; + +/** + * @brief Number of bits used as flags for base memory management + * + * Must be kept in sync with the ::base_mem_alloc_flags flags + */ +#define BASE_MEM_FLAGS_NR_INPUT_BITS 14 +#define BASE_MEM_FLAGS_NR_OUTPUT_BITS 1 +#define BASE_MEM_FLAGS_NR_TOTAL_BITS ((BASE_MEM_FLAGS_NR_INPUT_BITS) + (BASE_MEM_FLAGS_NR_OUTPUT_BITS)) +#define BASE_MEM_FLAGS_NR_BITS 15 + +#if BASE_MEM_FLAGS_NR_TOTAL_BITS > BASE_MEM_FLAGS_NR_BITS +#error "Too many flag bits, will require change in cmem" +#endif + +/** + * @brief Memory types supported by @a base_mem_import + * + * Each type defines what the supported handle type is. + * + * If any new type is added here ARM must be contacted + * to allocate a numeric value for it. + * Do not just add a new type without synchronizing with ARM + * as future releases from ARM might include other new types + * which could clash with your custom types. + */ +typedef enum base_mem_import_type { + BASE_MEM_IMPORT_TYPE_INVALID = 0, + /** UMP import. Handle type is ump_secure_id. */ + BASE_MEM_IMPORT_TYPE_UMP = 1, + /** UMM import. Handle type is a file descriptor (int) */ + BASE_MEM_IMPORT_TYPE_UMM = 2 +} base_mem_import_type; + +/* legacy API wrappers */ +#define base_tmem_import_type base_mem_import_type +#define BASE_TMEM_IMPORT_TYPE_INVALID BASE_MEM_IMPORT_TYPE_INVALID +#define BASE_TMEM_IMPORT_TYPE_UMP BASE_MEM_IMPORT_TYPE_UMP +#define BASE_TMEM_IMPORT_TYPE_UMM BASE_MEM_IMPORT_TYPE_UMM + +/** + * @brief Invalid memory handle type. + * Return value from functions returning @a base_mem_handle on error. + */ +#define BASE_MEM_INVALID_HANDLE (0ull << 12) +#define BASE_MEM_MMU_DUMP_HANDLE (1ull << 12) +#define BASE_MEM_TRACE_BUFFER_HANDLE (2ull << 12) +#define BASE_MEM_MAP_TRACKING_HANDLE (3ull << 12) +#define BASE_MEM_WRITE_ALLOC_PAGES_HANDLE (4ull << 12) +/* reserved handles ..-64< for future special handles */ +#define BASE_MEM_COOKIE_BASE (64ul << 12) +#define BASE_MEM_FIRST_FREE_ADDRESS ((BITS_PER_LONG << 12) + \ + BASE_MEM_COOKIE_BASE) + +/* Bit mask of cookies used for for memory allocation setup */ +#define KBASE_COOKIE_MASK ~1UL /* bit 0 is reserved */ + + +/** + * @brief Result codes of changing the size of the backing store allocated to a tmem region + */ +typedef enum base_backing_threshold_status { + BASE_BACKING_THRESHOLD_OK = 0, /**< Resize successful */ + BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE = -1, /**< Not a growable tmem object */ + BASE_BACKING_THRESHOLD_ERROR_OOM = -2, /**< Increase failed due to an out-of-memory condition */ + BASE_BACKING_THRESHOLD_ERROR_MAPPED = -3, /**< Resize attempted on buffer while it was mapped, which is not permitted */ + BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS = -4 /**< Invalid arguments (not tmem, illegal size request, etc.) */ +} base_backing_threshold_status; + +/** + * @addtogroup base_user_api_memory_defered User-side Base Defered Memory Coherency APIs + * @{ + */ + +/** + * @brief a basic memory operation (sync-set). + * + * The content of this structure is private, and should only be used + * by the accessors. + */ +typedef struct base_syncset { + struct basep_syncset basep_sset; +} base_syncset; + +/** @} end group base_user_api_memory_defered */ + +/** + * Handle to represent imported memory object. + * Simple opague handle to imported memory, can't be used + * with anything but base_external_resource_init to bind to an atom. + */ +typedef struct base_import_handle { + struct { + mali_addr64 handle; + } basep; +} base_import_handle; + +/** @} end group base_user_api_memory */ + +/** + * @addtogroup base_user_api_job_dispatch User-side Base Job Dispatcher APIs + * @{ + */ + +typedef int platform_fence_type; +#define INVALID_PLATFORM_FENCE ((platform_fence_type)-1) + +/** + * Base stream handle. + * + * References an underlying base stream object. + */ +typedef struct base_stream { + struct { + int fd; + } basep; +} base_stream; + +/** + * Base fence handle. + * + * References an underlying base fence object. + */ +typedef struct base_fence { + struct { + int fd; + int stream_fd; + } basep; +} base_fence; + +/** + * @brief Per-job data + * + * This structure is used to store per-job data, and is completly unused + * by the Base driver. It can be used to store things such as callback + * function pointer, data to handle job completion. It is guaranteed to be + * untouched by the Base driver. + */ +typedef struct base_jd_udata { + u64 blob[2]; /**< per-job data array */ +} base_jd_udata; + +/** + * @brief Memory aliasing info + * + * Describes a memory handle to be aliased. + * A subset of the handle can be chosen for aliasing, given an offset and a + * length. + * A special handle BASE_MEM_WRITE_ALLOC_PAGES_HANDLE is used to represent a + * region where a special page is mapped with a write-alloc cache setup, + * typically used when the write result of the GPU isn't needed, but the GPU + * must write anyway. + * + * Offset and length are specified in pages. + * Offset must be within the size of the handle. + * Offset+length must not overrun the size of the handle. + * + * @handle Handle to alias, can be BASE_MEM_WRITE_ALLOC_PAGES_HANDLE + * @offset Offset within the handle to start aliasing from, in pages. + * Not used with BASE_MEM_WRITE_ALLOC_PAGES_HANDLE. + * @length Length to alias, in pages. For BASE_MEM_WRITE_ALLOC_PAGES_HANDLE + * specifies the number of times the special page is needed. + */ +struct base_mem_aliasing_info { + base_mem_handle handle; + u64 offset; + u64 length; +}; + +/** + * @brief Job dependency type. + * + * A flags field will be inserted into the atom structure to specify whether a dependency is a data or + * ordering dependency (by putting it before/after 'core_req' in the structure it should be possible to add without + * changing the structure size). + * When the flag is set for a particular dependency to signal that it is an ordering only dependency then + * errors will not be propagated. + */ +typedef u8 base_jd_dep_type; + + +#define BASE_JD_DEP_TYPE_INVALID (0) /**< Invalid dependency */ +#define BASE_JD_DEP_TYPE_DATA (1U << 0) /**< Data dependency */ +#define BASE_JD_DEP_TYPE_ORDER (1U << 1) /**< Order dependency */ + +/** + * @brief Job chain hardware requirements. + * + * A job chain must specify what GPU features it needs to allow the + * driver to schedule the job correctly. By not specifying the + * correct settings can/will cause an early job termination. Multiple + * values can be ORed together to specify multiple requirements. + * Special case is ::BASE_JD_REQ_DEP, which is used to express complex + * dependencies, and that doesn't execute anything on the hardware. + */ +typedef u16 base_jd_core_req; + +/* Requirements that come from the HW */ +#define BASE_JD_REQ_DEP 0 /**< No requirement, dependency only */ +#define BASE_JD_REQ_FS (1U << 0) /**< Requires fragment shaders */ +/** + * Requires compute shaders + * This covers any of the following Midgard Job types: + * - Vertex Shader Job + * - Geometry Shader Job + * - An actual Compute Shader Job + * + * Compare this with @ref BASE_JD_REQ_ONLY_COMPUTE, which specifies that the + * job is specifically just the "Compute Shader" job type, and not the "Vertex + * Shader" nor the "Geometry Shader" job type. + */ +#define BASE_JD_REQ_CS (1U << 1) +#define BASE_JD_REQ_T (1U << 2) /**< Requires tiling */ +#define BASE_JD_REQ_CF (1U << 3) /**< Requires cache flushes */ +#define BASE_JD_REQ_V (1U << 4) /**< Requires value writeback */ + +/* SW-only requirements - the HW does not expose these as part of the job slot capabilities */ + +/* Requires fragment job with AFBC encoding */ +#define BASE_JD_REQ_FS_AFBC (1U << 13) + +/** + * SW Only requirement: the job chain requires a coherent core group. We don't + * mind which coherent core group is used. + */ +#define BASE_JD_REQ_COHERENT_GROUP (1U << 6) + +/** + * SW Only requirement: The performance counters should be enabled only when + * they are needed, to reduce power consumption. + */ + +#define BASE_JD_REQ_PERMON (1U << 7) + +/** + * SW Only requirement: External resources are referenced by this atom. + * When external resources are referenced no syncsets can be bundled with the atom + * but should instead be part of a NULL jobs inserted into the dependency tree. + * The first pre_dep object must be configured for the external resouces to use, + * the second pre_dep object can be used to create other dependencies. + */ +#define BASE_JD_REQ_EXTERNAL_RESOURCES (1U << 8) + +/** + * SW Only requirement: Software defined job. Jobs with this bit set will not be submitted + * to the hardware but will cause some action to happen within the driver + */ +#define BASE_JD_REQ_SOFT_JOB (1U << 9) + +#define BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME (BASE_JD_REQ_SOFT_JOB | 0x1) +#define BASE_JD_REQ_SOFT_FENCE_TRIGGER (BASE_JD_REQ_SOFT_JOB | 0x2) +#define BASE_JD_REQ_SOFT_FENCE_WAIT (BASE_JD_REQ_SOFT_JOB | 0x3) + +/** + * SW Only requirement : Replay job. + * + * If the preceeding job fails, the replay job will cause the jobs specified in + * the list of base_jd_replay_payload pointed to by the jc pointer to be + * replayed. + * + * A replay job will only cause jobs to be replayed up to BASEP_JD_REPLAY_LIMIT + * times. If a job fails more than BASEP_JD_REPLAY_LIMIT times then the replay + * job is failed, as well as any following dependencies. + * + * The replayed jobs will require a number of atom IDs. If there are not enough + * free atom IDs then the replay job will fail. + * + * If the preceeding job does not fail, then the replay job is returned as + * completed. + * + * The replayed jobs will never be returned to userspace. The preceeding failed + * job will be returned to userspace as failed; the status of this job should + * be ignored. Completion should be determined by the status of the replay soft + * job. + * + * In order for the jobs to be replayed, the job headers will have to be + * modified. The Status field will be reset to NOT_STARTED. If the Job Type + * field indicates a Vertex Shader Job then it will be changed to Null Job. + * + * The replayed jobs have the following assumptions : + * + * - No external resources. Any required external resources will be held by the + * replay atom. + * - Pre-dependencies are created based on job order. + * - Atom numbers are automatically assigned. + * - device_nr is set to 0. This is not relevant as + * BASE_JD_REQ_SPECIFIC_COHERENT_GROUP should not be set. + * - Priority is inherited from the replay job. + */ +#define BASE_JD_REQ_SOFT_REPLAY (BASE_JD_REQ_SOFT_JOB | 0x4) + +/** + * HW Requirement: Requires Compute shaders (but not Vertex or Geometry Shaders) + * + * This indicates that the Job Chain contains Midgard Jobs of the 'Compute Shaders' type. + * + * In contrast to @ref BASE_JD_REQ_CS, this does \b not indicate that the Job + * Chain contains 'Geometry Shader' or 'Vertex Shader' jobs. + * + * @note This is a more flexible variant of the @ref BASE_CONTEXT_HINT_ONLY_COMPUTE flag, + * allowing specific jobs to be marked as 'Only Compute' instead of the entire context + */ +#define BASE_JD_REQ_ONLY_COMPUTE (1U << 10) + +/** + * HW Requirement: Use the base_jd_atom::device_nr field to specify a + * particular core group + * + * If both BASE_JD_REQ_COHERENT_GROUP and this flag are set, this flag takes priority + * + * This is only guaranteed to work for BASE_JD_REQ_ONLY_COMPUTE atoms. + * + * If the core availability policy is keeping the required core group turned off, then + * the job will fail with a BASE_JD_EVENT_PM_EVENT error code. + */ +#define BASE_JD_REQ_SPECIFIC_COHERENT_GROUP (1U << 11) + +/** + * SW Flag: If this bit is set then the successful completion of this atom + * will not cause an event to be sent to userspace + */ +#define BASE_JD_REQ_EVENT_ONLY_ON_FAILURE (1U << 12) + +/** + * SW Flag: If this bit is set then completion of this atom will not cause an + * event to be sent to userspace, whether successful or not. + */ +#define BASEP_JD_REQ_EVENT_NEVER (1U << 14) + +/** +* These requirement bits are currently unused in base_jd_core_req (currently a u16) +*/ + +#define BASEP_JD_REQ_RESERVED_BIT5 (1U << 5) +#define BASEP_JD_REQ_RESERVED_BIT15 (1U << 15) + +/** +* Mask of all the currently unused requirement bits in base_jd_core_req. +*/ + +#define BASEP_JD_REQ_RESERVED (BASEP_JD_REQ_RESERVED_BIT5 | \ + BASEP_JD_REQ_RESERVED_BIT15) + +/** + * Mask of all bits in base_jd_core_req that control the type of the atom. + * + * This allows dependency only atoms to have flags set + */ +#define BASEP_JD_REQ_ATOM_TYPE (~(BASEP_JD_REQ_RESERVED | BASE_JD_REQ_EVENT_ONLY_ON_FAILURE |\ + BASE_JD_REQ_EXTERNAL_RESOURCES | BASEP_JD_REQ_EVENT_NEVER)) + +/** + * @brief States to model state machine processed by kbasep_js_job_check_ref_cores(), which + * handles retaining cores for power management and affinity management. + * + * The state @ref KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY prevents an attack + * where lots of atoms could be submitted before powerup, and each has an + * affinity chosen that causes other atoms to have an affinity + * violation. Whilst the affinity was not causing violations at the time it + * was chosen, it could cause violations thereafter. For example, 1000 jobs + * could have had their affinity chosen during the powerup time, so any of + * those 1000 jobs could cause an affinity violation later on. + * + * The attack would otherwise occur because other atoms/contexts have to wait for: + * -# the currently running atoms (which are causing the violation) to + * finish + * -# and, the atoms that had their affinity chosen during powerup to + * finish. These are run preferrentially because they don't cause a + * violation, but instead continue to cause the violation in others. + * -# or, the attacker is scheduled out (which might not happen for just 2 + * contexts) + * + * By re-choosing the affinity (which is designed to avoid violations at the + * time it's chosen), we break condition (2) of the wait, which minimizes the + * problem to just waiting for current jobs to finish (which can be bounded if + * the Job Scheduling Policy has a timer). + */ +enum kbase_atom_coreref_state { + /** Starting state: No affinity chosen, and cores must be requested. kbase_jd_atom::affinity==0 */ + KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED, + /** Cores requested, but waiting for them to be powered. Requested cores given by kbase_jd_atom::affinity */ + KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES, + /** Cores given by kbase_jd_atom::affinity are powered, but affinity might be out-of-date, so must recheck */ + KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY, + /** Cores given by kbase_jd_atom::affinity are powered, and affinity is up-to-date, but must check for violations */ + KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS, + /** Cores are powered, kbase_jd_atom::affinity up-to-date, no affinity violations: atom can be submitted to HW */ + KBASE_ATOM_COREREF_STATE_READY +}; + +enum kbase_jd_atom_state { + /** Atom is not used */ + KBASE_JD_ATOM_STATE_UNUSED, + /** Atom is queued in JD */ + KBASE_JD_ATOM_STATE_QUEUED, + /** Atom has been given to JS (is runnable/running) */ + KBASE_JD_ATOM_STATE_IN_JS, + /** Atom has been completed, but not yet handed back to userspace */ + KBASE_JD_ATOM_STATE_COMPLETED +}; + +typedef u8 base_atom_id; /**< Type big enough to store an atom number in */ + +struct base_dependency { + base_atom_id atom_id; /**< An atom number */ + base_jd_dep_type dependency_type; /**< Dependency type */ +}; + +typedef struct base_jd_atom_v2 { + mali_addr64 jc; /**< job-chain GPU address */ + struct base_jd_udata udata; /**< user data */ + kbase_pointer extres_list; /**< list of external resources */ + u16 nr_extres; /**< nr of external resources */ + base_jd_core_req core_req; /**< core requirements */ + const struct base_dependency pre_dep[2]; /**< pre-dependencies, one need to use SETTER function to assign this field, + this is done in order to reduce possibility of improper assigment of a dependency field */ + base_atom_id atom_number; /**< unique number to identify the atom */ + s8 prio; /**< priority - smaller is higher priority */ + u8 device_nr; /**< coregroup when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP specified */ + u8 padding[5]; +} base_jd_atom_v2; + +#ifdef BASE_LEGACY_UK6_SUPPORT +struct base_jd_atom_v2_uk6 { + mali_addr64 jc; /**< job-chain GPU address */ + struct base_jd_udata udata; /**< user data */ + kbase_pointer extres_list; /**< list of external resources */ + u16 nr_extres; /**< nr of external resources */ + base_jd_core_req core_req; /**< core requirements */ + base_atom_id pre_dep[2]; /**< pre-dependencies */ + base_atom_id atom_number; /**< unique number to identify the atom */ + s8 prio; /**< priority - smaller is higher priority */ + u8 device_nr; /**< coregroup when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP specified */ + u8 padding[7]; +}; +#endif + +typedef enum base_external_resource_access { + BASE_EXT_RES_ACCESS_SHARED, + BASE_EXT_RES_ACCESS_EXCLUSIVE +} base_external_resource_access; + +typedef struct base_external_resource { + u64 ext_resource; +} base_external_resource; + +/** + * @brief Setter for a dependency structure + * + * @param[in] dep The kbase jd atom dependency to be initialized. + * @param id The atom_id to be assigned. + * @param dep_type The dep_type to be assigned. + * + */ +static INLINE void base_jd_atom_dep_set(const struct base_dependency* const_dep, base_atom_id id, base_jd_dep_type dep_type) +{ + struct base_dependency* dep; + + LOCAL_ASSERT(const_dep != NULL); + /* make sure we don't set not allowed combinations of atom_id/dependency_type */ + LOCAL_ASSERT( ( id == 0 && dep_type == BASE_JD_DEP_TYPE_INVALID) || + (id > 0 && dep_type != BASE_JD_DEP_TYPE_INVALID) ); + + dep = REINTERPRET_CAST(struct base_dependency*)const_dep; + + dep->atom_id = id; + dep->dependency_type = dep_type; +} + +/** + * @brief Make a copy of a dependency structure + * + * @param[in,out] dep The kbase jd atom dependency to be written. + * @param[in] from The dependency to make a copy from. + * + */ +static INLINE void base_jd_atom_dep_copy(const struct base_dependency* const_dep, const struct base_dependency* from) +{ + LOCAL_ASSERT(const_dep != NULL); + + base_jd_atom_dep_set(const_dep, from->atom_id, from->dependency_type); +} + +/** + * @brief Soft-atom fence trigger setup. + * + * Sets up an atom to be a SW-only atom signaling a fence + * when it reaches the run state. + * + * Using the existing base dependency system the fence can + * be set to trigger when a GPU job has finished. + * + * The base fence object must not be terminated until the atom + * has been submitted to @a base_jd_submit_bag and @a base_jd_submit_bag has returned. + * + * @a fence must be a valid fence set up with @a base_fence_init. + * Calling this function with a uninitialized fence results in undefined behavior. + * + * @param[out] atom A pre-allocated atom to configure as a fence trigger SW atom + * @param[in] fence The base fence object to trigger. + */ +static INLINE void base_jd_fence_trigger_setup_v2(struct base_jd_atom_v2 *atom, struct base_fence *fence) +{ + LOCAL_ASSERT(atom); + LOCAL_ASSERT(fence); + LOCAL_ASSERT(fence->basep.fd == INVALID_PLATFORM_FENCE); + LOCAL_ASSERT(fence->basep.stream_fd >= 0); + atom->jc = (uintptr_t) fence; + atom->core_req = BASE_JD_REQ_SOFT_FENCE_TRIGGER; +} + +/** + * @brief Soft-atom fence wait setup. + * + * Sets up an atom to be a SW-only atom waiting on a fence. + * When the fence becomes triggered the atom becomes runnable + * and completes immediately. + * + * Using the existing base dependency system the fence can + * be set to block a GPU job until it has been triggered. + * + * The base fence object must not be terminated until the atom + * has been submitted to @a base_jd_submit_bag and @a base_jd_submit_bag has returned. + * + * @a fence must be a valid fence set up with @a base_fence_init or @a base_fence_import. + * Calling this function with a uninitialized fence results in undefined behavior. + * + * @param[out] atom A pre-allocated atom to configure as a fence wait SW atom + * @param[in] fence The base fence object to wait on + */ +static INLINE void base_jd_fence_wait_setup_v2(struct base_jd_atom_v2 *atom, struct base_fence *fence) +{ + LOCAL_ASSERT(atom); + LOCAL_ASSERT(fence); + LOCAL_ASSERT(fence->basep.fd >= 0); + atom->jc = (uintptr_t) fence; + atom->core_req = BASE_JD_REQ_SOFT_FENCE_WAIT; +} + +/** + * @brief External resource info initialization. + * + * Sets up a external resource object to reference + * a memory allocation and the type of access requested. + * + * @param[in] res The resource object to initialize + * @param handle The handle to the imported memory object + * @param access The type of access requested + */ +static INLINE void base_external_resource_init(struct base_external_resource * res, struct base_import_handle handle, base_external_resource_access access) +{ + mali_addr64 address; + address = handle.basep.handle; + + LOCAL_ASSERT(res != NULL); + LOCAL_ASSERT(0 == (address & LOCAL_PAGE_LSB)); + LOCAL_ASSERT(access == BASE_EXT_RES_ACCESS_SHARED || access == BASE_EXT_RES_ACCESS_EXCLUSIVE); + + res->ext_resource = address | (access & LOCAL_PAGE_LSB); +} + +/** + * @brief Job chain event code bits + * Defines the bits used to create ::base_jd_event_code + */ +enum { + BASE_JD_SW_EVENT_KERNEL = (1u << 15), /**< Kernel side event */ + BASE_JD_SW_EVENT = (1u << 14), /**< SW defined event */ + BASE_JD_SW_EVENT_SUCCESS = (1u << 13), /**< Event idicates success (SW events only) */ + BASE_JD_SW_EVENT_JOB = (0u << 11), /**< Job related event */ + BASE_JD_SW_EVENT_BAG = (1u << 11), /**< Bag related event */ + BASE_JD_SW_EVENT_INFO = (2u << 11), /**< Misc/info event */ + BASE_JD_SW_EVENT_RESERVED = (3u << 11), /**< Reserved event type */ + BASE_JD_SW_EVENT_TYPE_MASK = (3u << 11) /**< Mask to extract the type from an event code */ +}; + +/** + * @brief Job chain event codes + * + * HW and low-level SW events are represented by event codes. + * The status of jobs which succeeded are also represented by + * an event code (see ::BASE_JD_EVENT_DONE). + * Events are usually reported as part of a ::base_jd_event. + * + * The event codes are encoded in the following way: + * @li 10:0 - subtype + * @li 12:11 - type + * @li 13 - SW success (only valid if the SW bit is set) + * @li 14 - SW event (HW event if not set) + * @li 15 - Kernel event (should never be seen in userspace) + * + * Events are split up into ranges as follows: + * - BASE_JD_EVENT_RANGE_\_START + * - BASE_JD_EVENT_RANGE_\_END + * + * \a code is in \'s range when: + * - BASE_JD_EVENT_RANGE_\_START <= code < BASE_JD_EVENT_RANGE_\_END + * + * Ranges can be asserted for adjacency by testing that the END of the previous + * is equal to the START of the next. This is useful for optimizing some tests + * for range. + * + * A limitation is that the last member of this enum must explicitly be handled + * (with an assert-unreachable statement) in switch statements that use + * variables of this type. Otherwise, the compiler warns that we have not + * handled that enum value. + */ +typedef enum base_jd_event_code { + /* HW defined exceptions */ + + /** Start of HW Non-fault status codes + * + * @note Obscurely, BASE_JD_EVENT_TERMINATED indicates a real fault, + * because the job was hard-stopped + */ + BASE_JD_EVENT_RANGE_HW_NONFAULT_START = 0, + + /* non-fatal exceptions */ + BASE_JD_EVENT_NOT_STARTED = 0x00, /**< Can't be seen by userspace, treated as 'previous job done' */ + BASE_JD_EVENT_DONE = 0x01, + BASE_JD_EVENT_STOPPED = 0x03, /**< Can't be seen by userspace, becomes TERMINATED, DONE or JOB_CANCELLED */ + BASE_JD_EVENT_TERMINATED = 0x04, /**< This is actually a fault status code - the job was hard stopped */ + BASE_JD_EVENT_ACTIVE = 0x08, /**< Can't be seen by userspace, jobs only returned on complete/fail/cancel */ + + /** End of HW Non-fault status codes + * + * @note Obscurely, BASE_JD_EVENT_TERMINATED indicates a real fault, + * because the job was hard-stopped + */ + BASE_JD_EVENT_RANGE_HW_NONFAULT_END = 0x40, + + /** Start of HW fault and SW Error status codes */ + BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_START = 0x40, + + /* job exceptions */ + BASE_JD_EVENT_JOB_CONFIG_FAULT = 0x40, + BASE_JD_EVENT_JOB_POWER_FAULT = 0x41, + BASE_JD_EVENT_JOB_READ_FAULT = 0x42, + BASE_JD_EVENT_JOB_WRITE_FAULT = 0x43, + BASE_JD_EVENT_JOB_AFFINITY_FAULT = 0x44, + BASE_JD_EVENT_JOB_BUS_FAULT = 0x48, + BASE_JD_EVENT_INSTR_INVALID_PC = 0x50, + BASE_JD_EVENT_INSTR_INVALID_ENC = 0x51, + BASE_JD_EVENT_INSTR_TYPE_MISMATCH = 0x52, + BASE_JD_EVENT_INSTR_OPERAND_FAULT = 0x53, + BASE_JD_EVENT_INSTR_TLS_FAULT = 0x54, + BASE_JD_EVENT_INSTR_BARRIER_FAULT = 0x55, + BASE_JD_EVENT_INSTR_ALIGN_FAULT = 0x56, + BASE_JD_EVENT_DATA_INVALID_FAULT = 0x58, + BASE_JD_EVENT_TILE_RANGE_FAULT = 0x59, + BASE_JD_EVENT_STATE_FAULT = 0x5A, + BASE_JD_EVENT_OUT_OF_MEMORY = 0x60, + BASE_JD_EVENT_UNKNOWN = 0x7F, + + /* GPU exceptions */ + BASE_JD_EVENT_DELAYED_BUS_FAULT = 0x80, + BASE_JD_EVENT_SHAREABILITY_FAULT = 0x88, + + /* MMU exceptions */ + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL1 = 0xC1, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL2 = 0xC2, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL3 = 0xC3, + BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL4 = 0xC4, + BASE_JD_EVENT_PERMISSION_FAULT = 0xC8, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL1 = 0xD1, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL2 = 0xD2, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL3 = 0xD3, + BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL4 = 0xD4, + BASE_JD_EVENT_ACCESS_FLAG = 0xD8, + + /* SW defined exceptions */ + BASE_JD_EVENT_MEM_GROWTH_FAILED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x000, + BASE_JD_EVENT_TIMED_OUT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x001, + BASE_JD_EVENT_JOB_CANCELLED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x002, + BASE_JD_EVENT_JOB_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x003, + BASE_JD_EVENT_PM_EVENT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x004, + BASE_JD_EVENT_FORCE_REPLAY = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x005, + + BASE_JD_EVENT_BAG_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_BAG | 0x003, + + /** End of HW fault and SW Error status codes */ + BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_RESERVED | 0x3FF, + + /** Start of SW Success status codes */ + BASE_JD_EVENT_RANGE_SW_SUCCESS_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | 0x000, + + BASE_JD_EVENT_PROGRESS_REPORT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_JOB | 0x000, + BASE_JD_EVENT_BAG_DONE = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_BAG | 0x000, + BASE_JD_EVENT_DRV_TERMINATED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_INFO | 0x000, + + /** End of SW Success status codes */ + BASE_JD_EVENT_RANGE_SW_SUCCESS_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_RESERVED | 0x3FF, + + /** Start of Kernel-only status codes. Such codes are never returned to user-space */ + BASE_JD_EVENT_RANGE_KERNEL_ONLY_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | 0x000, + BASE_JD_EVENT_REMOVED_FROM_NEXT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | BASE_JD_SW_EVENT_JOB | 0x000, + + /** End of Kernel-only status codes. */ + BASE_JD_EVENT_RANGE_KERNEL_ONLY_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | BASE_JD_SW_EVENT_RESERVED | 0x3FF +} base_jd_event_code; + +/** + * @brief Event reporting structure + * + * This structure is used by the kernel driver to report information + * about GPU events. The can either be HW-specific events or low-level + * SW events, such as job-chain completion. + * + * The event code contains an event type field which can be extracted + * by ANDing with ::BASE_JD_SW_EVENT_TYPE_MASK. + * + * Based on the event type base_jd_event::data holds: + * @li ::BASE_JD_SW_EVENT_JOB : the offset in the ring-buffer for the completed + * job-chain + * @li ::BASE_JD_SW_EVENT_BAG : The address of the ::base_jd_bag that has + * been completed (ie all contained job-chains have been completed). + * @li ::BASE_JD_SW_EVENT_INFO : base_jd_event::data not used + */ +typedef struct base_jd_event_v2 { + base_jd_event_code event_code; /**< event code */ + base_atom_id atom_number; /**< the atom number that has completed */ + struct base_jd_udata udata; /**< user data */ +} base_jd_event_v2; + +/** + * Padding required to ensure that the @ref struct base_dump_cpu_gpu_counters structure fills + * a full cache line. + */ + +#define BASE_CPU_GPU_CACHE_LINE_PADDING (36) + + +/** + * @brief Structure for BASE_JD_REQ_SOFT_DUMP_CPU_GPU_COUNTERS jobs. + * + * This structure is stored into the memory pointed to by the @c jc field of @ref base_jd_atom. + * + * This structure must be padded to ensure that it will occupy whole cache lines. This is to avoid + * cases where access to pages containing the structure is shared between cached and un-cached + * memory regions, which would cause memory corruption. Here we set the structure size to be 64 bytes + * which is the cache line for ARM A15 processors. + */ + +typedef struct base_dump_cpu_gpu_counters { + u64 system_time; + u64 cycle_counter; + u64 sec; + u32 usec; + u8 padding[BASE_CPU_GPU_CACHE_LINE_PADDING]; +} base_dump_cpu_gpu_counters; + + + +/** @} end group base_user_api_job_dispatch */ + +#ifdef __KERNEL__ +/* + * The following typedefs should be removed when a midg types header is added. + * See MIDCOM-1657 for details. + */ +typedef u32 midg_product_id; +typedef u32 midg_cache_features; +typedef u32 midg_tiler_features; +typedef u32 midg_mem_features; +typedef u32 midg_mmu_features; +typedef u32 midg_js_features; +typedef u32 midg_as_present; +typedef u32 midg_js_present; + +#define MIDG_MAX_JOB_SLOTS 16 + +#else +#include +#endif + +/** + * @page page_base_user_api_gpuprops User-side Base GPU Property Query API + * + * The User-side Base GPU Property Query API encapsulates two + * sub-modules: + * + * - @ref base_user_api_gpuprops_dyn "Dynamic GPU Properties" + * - @ref base_plat_config_gpuprops "Base Platform Config GPU Properties" + * + * There is a related third module outside of Base, which is owned by the MIDG + * module: + * - @ref midg_gpuprops_static "Midgard Compile-time GPU Properties" + * + * Base only deals with properties that vary between different Midgard + * implementations - the Dynamic GPU properties and the Platform Config + * properties. + * + * For properties that are constant for the Midgard Architecture, refer to the + * MIDG module. However, we will discuss their relevance here just to + * provide background information. + * + * @section sec_base_user_api_gpuprops_about About the GPU Properties in Base and MIDG modules + * + * The compile-time properties (Platform Config, Midgard Compile-time + * properties) are exposed as pre-processor macros. + * + * Complementing the compile-time properties are the Dynamic GPU + * Properties, which act as a conduit for the Midgard Configuration + * Discovery. + * + * In general, the dynamic properties are present to verify that the platform + * has been configured correctly with the right set of Platform Config + * Compile-time Properties. + * + * As a consistant guide across the entire DDK, the choice for dynamic or + * compile-time should consider the following, in order: + * -# Can the code be written so that it doesn't need to know the + * implementation limits at all? + * -# If you need the limits, get the information from the Dynamic Property + * lookup. This should be done once as you fetch the context, and then cached + * as part of the context data structure, so it's cheap to access. + * -# If there's a clear and arguable inefficiency in using Dynamic Properties, + * then use a Compile-Time Property (Platform Config, or Midgard Compile-time + * property). Examples of where this might be sensible follow: + * - Part of a critical inner-loop + * - Frequent re-use throughout the driver, causing significant extra load + * instructions or control flow that would be worthwhile optimizing out. + * + * We cannot provide an exhaustive set of examples, neither can we provide a + * rule for every possible situation. Use common sense, and think about: what + * the rest of the driver will be doing; how the compiler might represent the + * value if it is a compile-time constant; whether an OEM shipping multiple + * devices would benefit much more from a single DDK binary, instead of + * insignificant micro-optimizations. + * + * @section sec_base_user_api_gpuprops_dyn Dynamic GPU Properties + * + * Dynamic GPU properties are presented in two sets: + * -# the commonly used properties in @ref base_gpu_props, which have been + * unpacked from GPU register bitfields. + * -# The full set of raw, unprocessed properties in @ref midg_raw_gpu_props + * (also a member of @ref base_gpu_props). All of these are presented in + * the packed form, as presented by the GPU registers themselves. + * + * @usecase The raw properties in @ref midg_raw_gpu_props are necessary to + * allow a user of the Mali Tools (e.g. PAT) to determine "Why is this device + * behaving differently?". In this case, all information about the + * configuration is potentially useful, but it does not need to be processed + * by the driver. Instead, the raw registers can be processed by the Mali + * Tools software on the host PC. + * + * The properties returned extend the Midgard Configuration Discovery + * registers. For example, GPU clock speed is not specified in the Midgard + * Architecture, but is necessary for OpenCL's clGetDeviceInfo() function. + * + * The GPU properties are obtained by a call to + * _mali_base_get_gpu_props(). This simply returns a pointer to a const + * base_gpu_props structure. It is constant for the life of a base + * context. Multiple calls to _mali_base_get_gpu_props() to a base context + * return the same pointer to a constant structure. This avoids cache pollution + * of the common data. + * + * This pointer must not be freed, because it does not point to the start of a + * region allocated by the memory allocator; instead, just close the @ref + * base_context. + * + * + * @section sec_base_user_api_gpuprops_config Platform Config Compile-time Properties + * + * The Platform Config File sets up gpu properties that are specific to a + * certain platform. Properties that are 'Implementation Defined' in the + * Midgard Architecture spec are placed here. + * + * @note Reference configurations are provided for Midgard Implementations, such as + * the Mali-T600 family. The customer need not repeat this information, and can select one of + * these reference configurations. For example, VA_BITS, PA_BITS and the + * maximum number of samples per pixel might vary between Midgard Implementations, but + * \b not for platforms using the Mali-T604. This information is placed in + * the reference configuration files. + * + * The System Integrator creates the following structure: + * - platform_XYZ + * - platform_XYZ/plat + * - platform_XYZ/plat/plat_config.h + * + * They then edit plat_config.h, using the example plat_config.h files as a + * guide. + * + * At the very least, the customer must set @ref CONFIG_GPU_CORE_TYPE, and will + * receive a helpful \#error message if they do not do this correctly. This + * selects the Reference Configuration for the Midgard Implementation. The rationale + * behind this decision (against asking the customer to write \#include + * in their plat_config.h) is as follows: + * - This mechanism 'looks' like a regular config file (such as Linux's + * .config) + * - It is difficult to get wrong in a way that will produce strange build + * errors: + * - They need not know where the mali_t600.h, other_midg_gpu.h etc. files are stored - and + * so they won't accidentally pick another file with 'mali_t600' in its name + * - When the build doesn't work, the System Integrator may think the DDK is + * doesn't work, and attempt to fix it themselves: + * - For the @ref CONFIG_GPU_CORE_TYPE mechanism, the only way to get past the + * error is to set @ref CONFIG_GPU_CORE_TYPE, and this is what the \#error tells + * you. + * - For a \#include mechanism, checks must still be made elsewhere, which the + * System Integrator may try working around by setting \#defines (such as + * VA_BITS) themselves in their plat_config.h. In the worst case, they may + * set the prevention-mechanism \#define of + * "A_CORRECT_MIDGARD_CORE_WAS_CHOSEN". + * - In this case, they would believe they are on the right track, because + * the build progresses with their fix, but with errors elsewhere. + * + * However, there is nothing to prevent the customer using \#include to organize + * their own configurations files hierarchically. + * + * The mechanism for the header file processing is as follows: + * + * @dot + digraph plat_config_mechanism { + rankdir=BT + size="6,6" + + "mali_base.h"; + "midg/midg.h"; + + node [ shape=box ]; + { + rank = same; ordering = out; + + "midg/midg_gpu_props.h"; + "base/midg_gpus/mali_t600.h"; + "base/midg_gpus/other_midg_gpu.h"; + } + { rank = same; "plat/plat_config.h"; } + { + rank = same; + "midg/midg.h" [ shape=box ]; + gpu_chooser [ label="" style="invisible" width=0 height=0 fixedsize=true ]; + select_gpu [ label="Mali-T600 | Other\n(select_gpu.h)" shape=polygon,sides=4,distortion=0.25 width=3.3 height=0.99 fixedsize=true ] ; + } + node [ shape=box ]; + { rank = same; "plat/plat_config.h"; } + { rank = same; "mali_base.h"; } + + "mali_base.h" -> "midg/midg.h" -> "midg/midg_gpu_props.h"; + "mali_base.h" -> "plat/plat_config.h" ; + "mali_base.h" -> select_gpu ; + + "plat/plat_config.h" -> gpu_chooser [style="dotted,bold" dir=none weight=4] ; + gpu_chooser -> select_gpu [style="dotted,bold"] ; + + select_gpu -> "base/midg_gpus/mali_t600.h" ; + select_gpu -> "base/midg_gpus/other_midg_gpu.h" ; + } + @enddot + * + * + * @section sec_base_user_api_gpuprops_kernel Kernel Operation + * + * During Base Context Create time, user-side makes a single kernel call: + * - A call to fill user memory with GPU information structures + * + * The kernel-side will fill the provided the entire processed @ref base_gpu_props + * structure, because this information is required in both + * user and kernel side; it does not make sense to decode it twice. + * + * Coherency groups must be derived from the bitmasks, but this can be done + * kernel side, and just once at kernel startup: Coherency groups must already + * be known kernel-side, to support chains that specify a 'Only Coherent Group' + * SW requirement, or 'Only Coherent Group with Tiler' SW requirement. + * + * @section sec_base_user_api_gpuprops_cocalc Coherency Group calculation + * Creation of the coherent group data is done at device-driver startup, and so + * is one-time. This will most likely involve a loop with CLZ, shifting, and + * bit clearing on the L2_PRESENT or L3_PRESENT masks, depending on whether the + * system is L2 or L2+L3 Coherent. The number of shader cores is done by a + * population count, since faulty cores may be disabled during production, + * producing a non-contiguous mask. + * + * The memory requirements for this algoirthm can be determined either by a u64 + * population count on the L2/L3_PRESENT masks (a LUT helper already is + * requried for the above), or simple assumption that there can be no more than + * 16 coherent groups, since core groups are typically 4 cores. + */ + +/** + * @addtogroup base_user_api_gpuprops User-side Base GPU Property Query APIs + * @{ + */ + +/** + * @addtogroup base_user_api_gpuprops_dyn Dynamic HW Properties + * @{ + */ + +#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3 + +#define BASE_MAX_COHERENT_GROUPS 16 + +struct mali_base_gpu_core_props { + /** + * Product specific value. + */ + midg_product_id product_id; + + /** + * Status of the GPU release. + * No defined values, but starts at 0 and increases by one for each release + * status (alpha, beta, EAC, etc.). + * 4 bit values (0-15). + */ + u16 version_status; + + /** + * Minor release number of the GPU. "P" part of an "RnPn" release number. + * 8 bit values (0-255). + */ + u16 minor_revision; + + /** + * Major release number of the GPU. "R" part of an "RnPn" release number. + * 4 bit values (0-15). + */ + u16 major_revision; + + u16 padding; + + /** + * @usecase GPU clock speed is not specified in the Midgard Architecture, but is + * necessary for OpenCL's clGetDeviceInfo() function. + */ + u32 gpu_speed_mhz; + + /** + * @usecase GPU clock max/min speed is required for computing best/worst case + * in tasks as job scheduling ant irq_throttling. (It is not specified in the + * Midgard Architecture). + */ + u32 gpu_freq_khz_max; + u32 gpu_freq_khz_min; + + /** + * Size of the shader program counter, in bits. + */ + u32 log2_program_counter_size; + + /** + * TEXTURE_FEATURES_x registers, as exposed by the GPU. This is a + * bitpattern where a set bit indicates that the format is supported. + * + * Before using a texture format, it is recommended that the corresponding + * bit be checked. + */ + u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + + /** + * Theoretical maximum memory available to the GPU. It is unlikely that a + * client will be able to allocate all of this memory for their own + * purposes, but this at least provides an upper bound on the memory + * available to the GPU. + * + * This is required for OpenCL's clGetDeviceInfo() call when + * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL GPU devices. The + * client will not be expecting to allocate anywhere near this value. + */ + u64 gpu_available_memory_size; +}; + +/** + * + * More information is possible - but associativity and bus width are not + * required by upper-level apis. + */ +struct mali_base_gpu_l2_cache_props { + u8 log2_line_size; + u8 log2_cache_size; + u8 num_l2_slices; /* Number of L2C slices. 1 or higher */ + u8 padding[5]; +}; + +struct mali_base_gpu_l3_cache_props { + u8 log2_line_size; + u8 log2_cache_size; + u8 padding[6]; +}; + +struct mali_base_gpu_tiler_props { + u32 bin_size_bytes; /* Max is 4*2^15 */ + u32 max_active_levels; /* Max is 2^15 */ +}; + +/** + * GPU threading system details. + */ +struct mali_base_gpu_thread_props { + u32 max_threads; /* Max. number of threads per core */ + u32 max_workgroup_size; /* Max. number of threads per workgroup */ + u32 max_barrier_size; /* Max. number of threads that can synchronize on a simple barrier */ + u16 max_registers; /* Total size [1..65535] of the register file available per core. */ + u8 max_task_queue; /* Max. tasks [1..255] which may be sent to a core before it becomes blocked. */ + u8 max_thread_group_split; /* Max. allowed value [1..15] of the Thread Group Split field. */ + u8 impl_tech; /* 0 = Not specified, 1 = Silicon, 2 = FPGA, 3 = SW Model/Emulation */ + u8 padding[7]; +}; + +/** + * @brief descriptor for a coherent group + * + * \c core_mask exposes all cores in that coherent group, and \c num_cores + * provides a cached population-count for that mask. + * + * @note Whilst all cores are exposed in the mask, not all may be available to + * the application, depending on the Kernel Job Scheduler policy. Therefore, + * the application should not further restrict the core mask itself, as it may + * result in an empty core mask. However, it can guarentee that there will be + * at least one core available for each core group exposed . + * + * @usecase Chains marked at certain user-side priorities (e.g. the Long-running + * (batch) priority ) can be prevented from running on entire core groups by the + * Kernel Chain Scheduler policy. + * + * @note if u64s must be 8-byte aligned, then this structure has 32-bits of wastage. + */ +struct mali_base_gpu_coherent_group { + u64 core_mask; /**< Core restriction mask required for the group */ + u16 num_cores; /**< Number of cores in the group */ + u16 padding[3]; +}; + +/** + * @brief Coherency group information + * + * Note that the sizes of the members could be reduced. However, the \c group + * member might be 8-byte aligned to ensure the u64 core_mask is 8-byte + * aligned, thus leading to wastage if the other members sizes were reduced. + * + * The groups are sorted by core mask. The core masks are non-repeating and do + * not intersect. + */ +struct mali_base_gpu_coherent_group_info { + u32 num_groups; + + /** + * Number of core groups (coherent or not) in the GPU. Equivalent to the number of L2 Caches. + * + * The GPU Counter dumping writes 2048 bytes per core group, regardless of + * whether the core groups are coherent or not. Hence this member is needed + * to calculate how much memory is required for dumping. + * + * @note Do not use it to work out how many valid elements are in the + * group[] member. Use num_groups instead. + */ + u32 num_core_groups; + + /** + * Coherency features of the memory, accessed by @ref midg_mem_features + * methods + */ + midg_mem_features coherency; + + u32 padding; + + /** + * Descriptors of coherent groups + */ + struct mali_base_gpu_coherent_group group[BASE_MAX_COHERENT_GROUPS]; +}; + +/** + * A complete description of the GPU's Hardware Configuration Discovery + * registers. + * + * The information is presented inefficiently for access. For frequent access, + * the values should be better expressed in an unpacked form in the + * base_gpu_props structure. + * + * @usecase The raw properties in @ref midg_raw_gpu_props are necessary to + * allow a user of the Mali Tools (e.g. PAT) to determine "Why is this device + * behaving differently?". In this case, all information about the + * configuration is potentially useful, but it does not need to be processed + * by the driver. Instead, the raw registers can be processed by the Mali + * Tools software on the host PC. + * + */ +struct midg_raw_gpu_props { + u64 shader_present; + u64 tiler_present; + u64 l2_present; + u64 l3_present; + + midg_cache_features l2_features; + midg_cache_features l3_features; + midg_mem_features mem_features; + midg_mmu_features mmu_features; + + midg_as_present as_present; + + u32 js_present; + midg_js_features js_features[MIDG_MAX_JOB_SLOTS]; + midg_tiler_features tiler_features; + u32 texture_features[3]; + + u32 gpu_id; + + u32 thread_max_threads; + u32 thread_max_workgroup_size; + u32 thread_max_barrier_size; + u32 thread_features; + + u32 padding; +}; + +/** + * Return structure for _mali_base_get_gpu_props(). + * + * NOTE: the raw_props member in this datastructure contains the register + * values from which the value of the other members are derived. The derived + * members exist to allow for efficient access and/or shielding the details + * of the layout of the registers. + * + */ +typedef struct mali_base_gpu_props { + struct mali_base_gpu_core_props core_props; + struct mali_base_gpu_l2_cache_props l2_props; + struct mali_base_gpu_l3_cache_props l3_props; + struct mali_base_gpu_tiler_props tiler_props; + struct mali_base_gpu_thread_props thread_props; + + /** This member is large, likely to be 128 bytes */ + struct midg_raw_gpu_props raw_props; + + /** This must be last member of the structure */ + struct mali_base_gpu_coherent_group_info coherency_info; +} base_gpu_props; + +/** @} end group base_user_api_gpuprops_dyn */ + +/** @} end group base_user_api_gpuprops */ + +/** + * @addtogroup base_user_api_core User-side Base core APIs + * @{ + */ + +/** + * \enum base_context_create_flags + * + * Flags to pass to ::base_context_init. + * Flags can be ORed together to enable multiple things. + * + * These share the same space as @ref basep_context_private_flags, and so must + * not collide with them. + */ +enum base_context_create_flags { + /** No flags set */ + BASE_CONTEXT_CREATE_FLAG_NONE = 0, + + /** Base context is embedded in a cctx object (flag used for CINSTR software counter macros) */ + BASE_CONTEXT_CCTX_EMBEDDED = (1u << 0), + + /** Base context is a 'System Monitor' context for Hardware counters. + * + * One important side effect of this is that job submission is disabled. */ + BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED = (1u << 1), + + /** Base context flag indicating a 'hint' that this context uses Compute + * Jobs only. + * + * Specifially, this means that it only sends atoms that do not + * contain the following @ref base_jd_core_req : + * - BASE_JD_REQ_FS + * - BASE_JD_REQ_T + * + * Violation of these requirements will cause the Job-Chains to be rejected. + * + * In addition, it is inadvisable for the atom's Job-Chains to contain Jobs + * of the following @ref midg_job_type (whilst it may work now, it may not + * work in future) : + * - @ref MIDG_JOB_VERTEX + * - @ref MIDG_JOB_GEOMETRY + * + * @note An alternative to using this is to specify the BASE_JD_REQ_ONLY_COMPUTE + * requirement in atoms. + */ + BASE_CONTEXT_HINT_ONLY_COMPUTE = (1u << 2) +}; + +/** + * Bitpattern describing the ::base_context_create_flags that can be passed to base_context_init() + */ +#define BASE_CONTEXT_CREATE_ALLOWED_FLAGS \ + (((u32)BASE_CONTEXT_CCTX_EMBEDDED) | \ + ((u32)BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) | \ + ((u32)BASE_CONTEXT_HINT_ONLY_COMPUTE)) + +/** + * Bitpattern describing the ::base_context_create_flags that can be passed to the kernel + */ +#define BASE_CONTEXT_CREATE_KERNEL_FLAGS \ + (((u32)BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) | \ + ((u32)BASE_CONTEXT_HINT_ONLY_COMPUTE)) + +/** + * Private flags used on the base context + * + * These start at bit 31, and run down to zero. + * + * They share the same space as @ref base_context_create_flags, and so must + * not collide with them. + */ +enum basep_context_private_flags { + /** Private flag tracking whether job descriptor dumping is disabled */ + BASEP_CONTEXT_FLAG_JOB_DUMP_DISABLED = (1 << 31) +}; + +/** @} end group base_user_api_core */ + +/** @} end group base_user_api */ + +/** + * @addtogroup base_plat_config_gpuprops Base Platform Config GPU Properties + * @{ + * + * C Pre-processor macros are exposed here to do with Platform + * Config. + * + * These include: + * - GPU Properties that are constant on a particular Midgard Family + * Implementation e.g. Maximum samples per pixel on Mali-T600. + * - General platform config for the GPU, such as the GPU major and minor + * revison. + */ + +/** @} end group base_plat_config_gpuprops */ + +/** + * @addtogroup base_api Base APIs + * @{ + */ + +/** + * @brief The payload for a replay job. This must be in GPU memory. + */ +typedef struct base_jd_replay_payload { + /** + * Pointer to the first entry in the base_jd_replay_jc list. These + * will be replayed in @b reverse order (so that extra ones can be added + * to the head in future soft jobs without affecting this soft job) + */ + mali_addr64 tiler_jc_list; + + /** + * Pointer to the fragment job chain. + */ + mali_addr64 fragment_jc; + + /** + * Pointer to the tiler heap free FBD field to be modified. + */ + mali_addr64 tiler_heap_free; + + /** + * Hierarchy mask for the replayed fragment jobs. May be zero. + */ + u16 fragment_hierarchy_mask; + + /** + * Hierarchy mask for the replayed tiler jobs. May be zero. + */ + u16 tiler_hierarchy_mask; + + /** + * Default weight to be used for hierarchy levels not in the original + * mask. + */ + u32 hierarchy_default_weight; + + /** + * Core requirements for the tiler job chain + */ + base_jd_core_req tiler_core_req; + + /** + * Core requirements for the fragment job chain + */ + base_jd_core_req fragment_core_req; + + u8 padding[4]; +} base_jd_replay_payload; + +/** + * @brief An entry in the linked list of job chains to be replayed. This must + * be in GPU memory. + */ +typedef struct base_jd_replay_jc { + /** + * Pointer to next entry in the list. A setting of NULL indicates the + * end of the list. + */ + mali_addr64 next; + + /** + * Pointer to the job chain. + */ + mali_addr64 jc; + +} base_jd_replay_jc; + +/* Maximum number of jobs allowed in a fragment chain in the payload of a + * replay job */ +#define BASE_JD_REPLAY_F_CHAIN_JOB_LIMIT 256 + +/** @} end group base_api */ + +typedef struct base_profiling_controls { + u32 profiling_controls[FBDUMP_CONTROL_MAX]; +} base_profiling_controls; + +#endif /* _BASE_KERNEL_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_kernel_sync.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_kernel_sync.h new file mode 100644 index 0000000000000000000000000000000000000000..01a837cfae8bfcb8e1b2bbb837df533dfecfb6dd --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_kernel_sync.h @@ -0,0 +1,47 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Base cross-proccess sync API. + */ + +#ifndef _BASE_KERNEL_SYNC_H_ +#define _BASE_KERNEL_SYNC_H_ + +#include + +#define STREAM_IOC_MAGIC '~' + +/* Fence insert. + * + * Inserts a fence on the stream operated on. + * Fence can be waited via a base fence wait soft-job + * or triggered via a base fence trigger soft-job. + * + * Fences must be cleaned up with close when no longer needed. + * + * No input/output arguments. + * Returns + * >=0 fd + * <0 error code + */ +#define STREAM_IOC_FENCE_INSERT _IO(STREAM_IOC_MAGIC, 0) + +#endif /* _BASE_KERNEL_SYNC_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_mem_priv.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_mem_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..40942283824ad0a57744f8a977cb0e458c92e2d8 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_mem_priv.h @@ -0,0 +1,52 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _BASE_MEM_PRIV_H_ +#define _BASE_MEM_PRIV_H_ + +#define BASE_SYNCSET_OP_MSYNC (1U << 0) +#define BASE_SYNCSET_OP_CSYNC (1U << 1) + +/* + * This structure describe a basic memory coherency operation. + * It can either be: + * @li a sync from CPU to Memory: + * - type = ::BASE_SYNCSET_OP_MSYNC + * - mem_handle = a handle to the memory object on which the operation + * is taking place + * - user_addr = the address of the range to be synced + * - size = the amount of data to be synced, in bytes + * - offset is ignored. + * @li a sync from Memory to CPU: + * - type = ::BASE_SYNCSET_OP_CSYNC + * - mem_handle = a handle to the memory object on which the operation + * is taking place + * - user_addr = the address of the range to be synced + * - size = the amount of data to be synced, in bytes. + * - offset is ignored. + */ +typedef struct basep_syncset { + base_mem_handle mem_handle; + u64 user_addr; + u64 size; + u8 type; + u8 padding[7]; +} basep_syncset; + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_vendor_specific_func.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_vendor_specific_func.h new file mode 100644 index 0000000000000000000000000000000000000000..ce02e8b8e2bb8aab9a38cfc5d2ab222fcb3c8711 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_base_vendor_specific_func.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#ifndef _BASE_VENDOR_SPEC_FUNC_H_ +#define _BASE_VENDOR_SPEC_FUNC_H_ + +#include + +mali_error kbase_get_vendor_specific_cpu_clock_speed(u32 * const); + +#endif /*_BASE_VENDOR_SPEC_FUNC_H_*/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase.h new file mode 100644 index 0000000000000000000000000000000000000000..e94681f474af820255ff658d5c70b36678308617 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase.h @@ -0,0 +1,558 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_H_ +#define _KBASE_H_ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mali_base_kernel.h" +#include +#include + +#include "mali_kbase_pm.h" +#include "mali_kbase_mem_lowlevel.h" +#include "mali_kbase_defs.h" +#include "mali_kbase_trace_timeline.h" +#include "mali_kbase_js.h" +#include "mali_kbase_mem.h" +#include "mali_kbase_security.h" +#include "mali_kbase_utility.h" +#include "mali_kbase_gpu_memory_debugfs.h" +#include "mali_kbase_mem_profile_debugfs.h" +#include "mali_kbase_jd_debugfs.h" +#include "mali_kbase_cpuprops.h" +#include "mali_kbase_gpuprops.h" +#ifdef CONFIG_GPU_TRACEPOINTS +#include +#endif +/** + * @page page_base_kernel_main Kernel-side Base (KBase) APIs + * + * The Kernel-side Base (KBase) APIs are divided up as follows: + * - @subpage page_kbase_js_policy + */ + +/** + * @defgroup base_kbase_api Kernel-side Base (KBase) APIs + */ + +struct kbase_device *kbase_device_alloc(void); +/* +* note: configuration attributes member of kbdev needs to have +* been setup before calling kbase_device_init +*/ + +/* +* API to acquire device list semaphone and return pointer +* to the device list head +*/ +const struct list_head *kbase_dev_list_get(void); +/* API to release the device list semaphore */ +void kbase_dev_list_put(const struct list_head *dev_list); + +mali_error kbase_device_init(struct kbase_device * const kbdev); +void kbase_device_term(struct kbase_device *kbdev); +void kbase_device_free(struct kbase_device *kbdev); +int kbase_device_has_feature(struct kbase_device *kbdev, u32 feature); +struct kbase_device *kbase_find_device(int minor); /* Only needed for gator integration */ +void kbase_release_device(struct kbase_device *kbdev); + +void kbase_set_profiling_control(struct kbase_device *kbdev, u32 control, u32 value); + +u32 kbase_get_profiling_control(struct kbase_device *kbdev, u32 control); + +/** + * Ensure that all IRQ handlers have completed execution + * + * @param kbdev The kbase device + */ +void kbase_synchronize_irqs(struct kbase_device *kbdev); +void kbase_synchronize_irqs(struct kbase_device *kbdev); + +struct kbase_context * +kbase_create_context(struct kbase_device *kbdev, bool is_compat); +void kbase_destroy_context(struct kbase_context *kctx); +mali_error kbase_context_set_create_flags(struct kbase_context *kctx, u32 flags); + +mali_error kbase_instr_hwcnt_setup(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup); +mali_error kbase_instr_hwcnt_enable(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup); +mali_error kbase_instr_hwcnt_disable(struct kbase_context *kctx); +mali_error kbase_instr_hwcnt_clear(struct kbase_context *kctx); +mali_error kbase_instr_hwcnt_dump(struct kbase_context *kctx); +mali_error kbase_instr_hwcnt_dump_irq(struct kbase_context *kctx); +mali_bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx, mali_bool * const success); +void kbase_instr_hwcnt_suspend(struct kbase_device *kbdev); +void kbase_instr_hwcnt_resume(struct kbase_device *kbdev); + +void kbasep_cache_clean_worker(struct work_struct *data); +void kbase_clean_caches_done(struct kbase_device *kbdev); + +/** + * The GPU has completed performance count sampling successfully. + */ +void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev); + +mali_error kbase_jd_init(struct kbase_context *kctx); +void kbase_jd_exit(struct kbase_context *kctx); +#ifdef BASE_LEGACY_UK6_SUPPORT +mali_error kbase_jd_submit(struct kbase_context *kctx, + const struct kbase_uk_job_submit *submit_data, + int uk6_atom); +#else +mali_error kbase_jd_submit(struct kbase_context *kctx, + const struct kbase_uk_job_submit *submit_data); +#endif +void kbase_jd_done(struct kbase_jd_atom *katom, int slot_nr, ktime_t *end_timestamp, + kbasep_js_atom_done_code done_code); +void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom); +void kbase_jd_zap_context(struct kbase_context *kctx); +mali_bool jd_done_nolock(struct kbase_jd_atom *katom); +void kbase_jd_free_external_resources(struct kbase_jd_atom *katom); +mali_bool jd_submit_atom(struct kbase_context *kctx, + const struct base_jd_atom_v2 *user_atom, + struct kbase_jd_atom *katom); + +mali_error kbase_job_slot_init(struct kbase_device *kbdev); +void kbase_job_slot_halt(struct kbase_device *kbdev); +void kbase_job_slot_term(struct kbase_device *kbdev); +void kbase_job_done(struct kbase_device *kbdev, u32 done); +void kbase_job_zap_context(struct kbase_context *kctx); + +void kbase_job_slot_softstop(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom); +void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom, u32 sw_flags); +void kbase_job_slot_hardstop(struct kbase_context *kctx, int js, + struct kbase_jd_atom *target_katom); +void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, + u16 core_reqs, struct kbase_jd_atom *target_katom); +void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, + struct kbase_jd_atom *target_katom); + +void kbase_event_post(struct kbase_context *ctx, struct kbase_jd_atom *event); +int kbase_event_dequeue(struct kbase_context *ctx, struct base_jd_event_v2 *uevent); +int kbase_event_pending(struct kbase_context *ctx); +mali_error kbase_event_init(struct kbase_context *kctx); +void kbase_event_close(struct kbase_context *kctx); +void kbase_event_cleanup(struct kbase_context *kctx); +void kbase_event_wakeup(struct kbase_context *kctx); + +int kbase_process_soft_job(struct kbase_jd_atom *katom); +mali_error kbase_prepare_soft_job(struct kbase_jd_atom *katom); +void kbase_finish_soft_job(struct kbase_jd_atom *katom); +void kbase_cancel_soft_job(struct kbase_jd_atom *katom); +void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev); + +bool kbase_replay_process(struct kbase_jd_atom *katom); + +/* api used internally for register access. Contains validation and tracing */ +void kbase_reg_write(struct kbase_device *kbdev, u16 offset, u32 value, struct kbase_context *kctx); +u32 kbase_reg_read(struct kbase_device *kbdev, u16 offset, struct kbase_context *kctx); +void kbase_device_trace_register_access(struct kbase_context *kctx, enum kbase_reg_access_type type, u16 reg_offset, u32 reg_value); +void kbase_device_trace_buffer_install(struct kbase_context *kctx, u32 *tb, size_t size); +void kbase_device_trace_buffer_uninstall(struct kbase_context *kctx); + +/* api to be ported per OS, only need to do the raw register access */ +void kbase_os_reg_write(struct kbase_device *kbdev, u16 offset, u32 value); +u32 kbase_os_reg_read(struct kbase_device *kbdev, u16 offset); + +void kbasep_as_do_poke(struct work_struct *work); + +/** Report a GPU fault. + * + * This function is called from the interrupt handler when a GPU fault occurs. + * It reports the details of the fault using KBASE_DEBUG_PRINT_WARN. + * + * @param kbdev The kbase device that the GPU fault occurred from. + * @param multiple Zero if only GPU_FAULT was raised, non-zero if MULTIPLE_GPU_FAULTS was also set + */ +void kbase_report_gpu_fault(struct kbase_device *kbdev, int multiple); + +/** Kill all jobs that are currently running from a context + * + * This is used in response to a page fault to remove all jobs from the faulting context from the hardware. + * + * @param kctx The context to kill jobs from + */ +void kbase_job_kill_jobs_from_context(struct kbase_context *kctx); + +/** + * GPU interrupt handler + * + * This function is called from the interrupt handler when a GPU irq is to be handled. + * + * @param kbdev The kbase device to handle an IRQ for + * @param val The value of the GPU IRQ status register which triggered the call + */ +void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val); + +/** + * Prepare for resetting the GPU. + * This function just soft-stops all the slots to ensure that as many jobs as possible are saved. + * + * The function returns a boolean which should be interpreted as follows: + * - MALI_TRUE - Prepared for reset, kbase_reset_gpu should be called. + * - MALI_FALSE - Another thread is performing a reset, kbase_reset_gpu should not be called. + * + * @return See description + */ +mali_bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev); + +/** + * Pre-locked version of @a kbase_prepare_to_reset_gpu. + * + * Identical to @a kbase_prepare_to_reset_gpu, except that the + * kbasep_js_device_data::runpool_irq::lock is externally locked. + * + * @see kbase_prepare_to_reset_gpu + */ +mali_bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev); + +/** Reset the GPU + * + * This function should be called after kbase_prepare_to_reset_gpu iff it returns MALI_TRUE. + * It should never be called without a corresponding call to kbase_prepare_to_reset_gpu. + * + * After this function is called (or not called if kbase_prepare_to_reset_gpu returned MALI_FALSE), + * the caller should wait for kbdev->reset_waitq to be signalled to know when the reset has completed. + */ +void kbase_reset_gpu(struct kbase_device *kbdev); + +/** + * Pre-locked version of @a kbase_reset_gpu. + * + * Identical to @a kbase_reset_gpu, except that the + * kbasep_js_device_data::runpool_irq::lock is externally locked. + * + * @see kbase_reset_gpu + */ +void kbase_reset_gpu_locked(struct kbase_device *kbdev); + +/** Returns the name associated with a Mali exception code + * + * @param[in] exception_code exception code + * @return name associated with the exception code + */ +const char *kbase_exception_name(u32 exception_code); + +/** + * Check whether a system suspend is in progress, or has already been suspended + * + * The caller should ensure that either kbdev->pm.active_count_lock is held, or + * a dmb was executed recently (to ensure the value is most + * up-to-date). However, without a lock the value could change afterwards. + * + * @return MALI_FALSE if a suspend is not in progress + * @return !=MALI_FALSE otherwise + */ +static INLINE mali_bool kbase_pm_is_suspending(struct kbase_device *kbdev) { + return kbdev->pm.suspending; +} + +/** + * Return the atom's ID, as was originally supplied by userspace in + * base_jd_atom_v2::atom_number + */ +static INLINE int kbase_jd_atom_id(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + int result; + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->kctx == kctx); + + result = katom - &kctx->jctx.atoms[0]; + KBASE_DEBUG_ASSERT(result >= 0 && result <= BASE_JD_ATOM_COUNT); + return result; +} + +/** + * Initialize the disjoint state + * + * The disjoint event count and state are both set to zero. + * + * Disjoint functions usage: + * + * The disjoint event count should be incremented whenever a disjoint event occurs. + * + * There are several cases which are regarded as disjoint behavior. Rather than just increment + * the counter during disjoint events we also increment the counter when jobs may be affected + * by what the GPU is currently doing. To facilitate this we have the concept of disjoint state. + * + * Disjoint state is entered during GPU reset and for the entire time that an atom is replaying + * (as part of the replay workaround). Increasing the disjoint state also increases the count of + * disjoint events. + * + * The disjoint state is then used to increase the count of disjoint events during job submission + * and job completion. Any atom submitted or completed while the disjoint state is greater than + * zero is regarded as a disjoint event. + * + * The disjoint event counter is also incremented immediately whenever a job is soft stopped + * and during context creation. + * + * @param kbdev The kbase device + */ +void kbase_disjoint_init(struct kbase_device *kbdev); + +/** + * Increase the count of disjoint events + * called when a disjoint event has happened + * + * @param kbdev The kbase device + */ +void kbase_disjoint_event(struct kbase_device *kbdev); + +/** + * Increase the count of disjoint events only if the GPU is in a disjoint state + * + * This should be called when something happens which could be disjoint if the GPU + * is in a disjoint state. The state refcount keeps track of this. + * + * @param kbdev The kbase device + */ +void kbase_disjoint_event_potential(struct kbase_device *kbdev); + +/** + * Returns the count of disjoint events + * + * @param kbdev The kbase device + * @return the count of disjoint events + */ +u32 kbase_disjoint_event_get(struct kbase_device *kbdev); + +/** + * Increment the refcount state indicating that the GPU is in a disjoint state. + * + * Also Increment the disjoint event count (calls @ref kbase_disjoint_event) + * eventually after the disjoint state has completed @ref kbase_disjoint_state_down + * should be called + * + * @param kbdev The kbase device + */ +void kbase_disjoint_state_up(struct kbase_device *kbdev); + +/** + * Decrement the refcount state + * + * Also Increment the disjoint event count (calls @ref kbase_disjoint_event) + * + * Called after @ref kbase_disjoint_state_up once the disjoint state is over + * + * @param kbdev The kbase device + */ +void kbase_disjoint_state_down(struct kbase_device *kbdev); + +/** + * If a job is soft stopped and the number of contexts is >= this value + * it is reported as a disjoint event + */ +#define KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD 2 + +#if KBASE_TRACE_ENABLE +#ifndef CONFIG_MALI_SYSTEM_TRACE +/** Add trace values about a job-slot + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, 0) + +/** Add trace values about a job-slot, with info + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, info_val) + +/** Add trace values about a ctx refcount + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, 0) +/** Add trace values about a ctx refcount, and info + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, info_val) + +/** Add trace values (no slot or refcount) + * + * @note Any functions called through this macro will still be evaluated in + * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any + * functions called to get the parameters supplied to this macro must: + * - be static or static inline + * - must just return 0 and have no other statements present in the body. + */ +#define KBASE_TRACE_ADD(kbdev, code, ctx, katom, gpu_addr, info_val) \ + kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \ + 0, 0, 0, info_val) + +/** Clear the trace */ +#define KBASE_TRACE_CLEAR(kbdev) \ + kbasep_trace_clear(kbdev) + +/** Dump the slot trace */ +#define KBASE_TRACE_DUMP(kbdev) \ + kbasep_trace_dump(kbdev) + +/** PRIVATE - do not use directly. Use KBASE_TRACE_ADD() instead */ +void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val); +/** PRIVATE - do not use directly. Use KBASE_TRACE_CLEAR() instead */ +void kbasep_trace_clear(struct kbase_device *kbdev); +#else /* #ifndef CONFIG_MALI_SYSTEM_TRACE */ +/* Dispatch kbase trace events as system trace events */ +#include +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot)\ + trace_mali_##code(jobslot, 0) + +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val)\ + trace_mali_##code(jobslot, info_val) + +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount)\ + trace_mali_##code(refcount, 0) + +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val)\ + trace_mali_##code(refcount, info_val) + +#define KBASE_TRACE_ADD(kbdev, code, ctx, katom, gpu_addr, info_val)\ + trace_mali_##code(gpu_addr, info_val) + +#define KBASE_TRACE_CLEAR(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#define KBASE_TRACE_DUMP(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) + +#endif /* #ifndef CONFIG_MALI_SYSTEM_TRACE */ +#else +#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(jobslot);\ + } while (0) + +#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(jobslot);\ + CSTD_UNUSED(info_val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(refcount);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(gpu_addr);\ + CSTD_UNUSED(info_val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_ADD(kbdev, code, subcode, ctx, katom, val)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(code);\ + CSTD_UNUSED(subcode);\ + CSTD_UNUSED(ctx);\ + CSTD_UNUSED(katom);\ + CSTD_UNUSED(val);\ + CSTD_NOP(0);\ + } while (0) + +#define KBASE_TRACE_CLEAR(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#define KBASE_TRACE_DUMP(kbdev)\ + do {\ + CSTD_UNUSED(kbdev);\ + CSTD_NOP(0);\ + } while (0) +#endif /* KBASE_TRACE_ENABLE */ +/** PRIVATE - do not use directly. Use KBASE_TRACE_DUMP() instead */ +void kbasep_trace_dump(struct kbase_device *kbdev); +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.c new file mode 100644 index 0000000000000000000000000000000000000000..4ee29098eba34f00ffb9ea2f3d1ca7baffb4c0f4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.c @@ -0,0 +1,204 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#include +#include +#include + +/* This function is used to solve an HW issue with single iterator GPUs. + * If a fragment job is soft-stopped on the edge of its bounding box, can happen that the + * restart index is out of bounds and the rerun causes a tile range fault. If this happens + * we try to clamp the restart index to a correct value and rerun the job. + */ +/* Mask of X and Y coordinates for the coordinates words in the descriptors*/ +#define X_COORDINATE_MASK 0x00000FFF +#define Y_COORDINATE_MASK 0x0FFF0000 +/* Max number of words needed from the fragment shader job descriptor */ +#define JOB_HEADER_SIZE_IN_WORDS 10 +#define JOB_HEADER_SIZE (JOB_HEADER_SIZE_IN_WORDS*sizeof(u32)) + +/* Word 0: Status Word */ +#define JOB_DESC_STATUS_WORD 0 +/* Word 1: Restart Index */ +#define JOB_DESC_RESTART_INDEX_WORD 1 +/* Word 2: Fault address low word */ +#define JOB_DESC_FAULT_ADDR_LOW_WORD 2 +/* Word 8: Minimum Tile Coordinates */ +#define FRAG_JOB_DESC_MIN_TILE_COORD_WORD 8 +/* Word 9: Maximum Tile Coordinates */ +#define FRAG_JOB_DESC_MAX_TILE_COORD_WORD 9 + +int kbasep_10969_workaround_clamp_coordinates(struct kbase_jd_atom *katom) +{ + struct device *dev = katom->kctx->kbdev->dev; + u32 clamped = 0; + struct kbase_va_region *region; + phys_addr_t *page_array; + u64 page_index; + u32 offset = katom->jc & (~PAGE_MASK); + u32 *page_1 = NULL; + u32 *page_2 = NULL; + u32 job_header[JOB_HEADER_SIZE_IN_WORDS]; + void *dst = job_header; + u32 minX, minY, maxX, maxY; + u32 restartX, restartY; + struct page *p; + u32 copy_size; + + dev_warn(dev, "Called TILE_RANGE_FAULT workaround clamping function.\n"); + if (!(katom->core_req & BASE_JD_REQ_FS)) + return 0; + + kbase_gpu_vm_lock(katom->kctx); + region = kbase_region_tracker_find_region_enclosing_address(katom->kctx, + katom->jc); + if (!region || (region->flags & KBASE_REG_FREE)) + goto out_unlock; + + page_array = kbase_get_phy_pages(region); + if (!page_array) + goto out_unlock; + + page_index = (katom->jc >> PAGE_SHIFT) - region->start_pfn; + + p = pfn_to_page(PFN_DOWN(page_array[page_index])); + + /* we need the first 10 words of the fragment shader job descriptor. + * We need to check that the offset + 10 words is less that the page + * size otherwise we need to load the next page. + * page_size_overflow will be equal to 0 in case the whole descriptor + * is within the page > 0 otherwise. + */ + copy_size = MIN(PAGE_SIZE - offset, JOB_HEADER_SIZE); + + page_1 = kmap_atomic(p); + + /* page_1 is a u32 pointer, offset is expressed in bytes */ + page_1 += offset>>2; + dma_sync_single_for_cpu(katom->kctx->kbdev->dev, + kbase_dma_addr(p) + offset, + copy_size, DMA_BIDIRECTIONAL); + memcpy(dst, page_1, copy_size); + + /* The data needed overflows page the dimension, + * need to map the subsequent page */ + if (copy_size < JOB_HEADER_SIZE) { + p = pfn_to_page(PFN_DOWN(page_array[page_index + 1])); + page_2 = kmap_atomic(p); + + dma_sync_single_for_cpu(katom->kctx->kbdev->dev, + kbase_dma_addr(p), + JOB_HEADER_SIZE - copy_size, DMA_BIDIRECTIONAL); + memcpy(dst + copy_size, page_2, JOB_HEADER_SIZE - copy_size); + } + + /* We managed to correctly map one or two pages (in case of overflow) */ + /* Get Bounding Box data and restart index from fault address low word */ + minX = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & X_COORDINATE_MASK; + minY = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & Y_COORDINATE_MASK; + maxX = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & X_COORDINATE_MASK; + maxY = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & Y_COORDINATE_MASK; + restartX = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & X_COORDINATE_MASK; + restartY = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & Y_COORDINATE_MASK; + + dev_warn(dev, "Before Clamping:\n" + "Jobstatus: %08x\n" + "restartIdx: %08x\n" + "Fault_addr_low: %08x\n" + "minCoordsX: %08x minCoordsY: %08x\n" + "maxCoordsX: %08x maxCoordsY: %08x\n", + job_header[JOB_DESC_STATUS_WORD], + job_header[JOB_DESC_RESTART_INDEX_WORD], + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD], + minX, minY, + maxX, maxY); + + /* Set the restart index to the one which generated the fault*/ + job_header[JOB_DESC_RESTART_INDEX_WORD] = + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD]; + + if (restartX < minX) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (minX) | restartY; + dev_warn(dev, + "Clamping restart X index to minimum. %08x clamped to %08x\n", + restartX, minX); + clamped = 1; + } + if (restartY < minY) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (minY) | restartX; + dev_warn(dev, + "Clamping restart Y index to minimum. %08x clamped to %08x\n", + restartY, minY); + clamped = 1; + } + if (restartX > maxX) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxX) | restartY; + dev_warn(dev, + "Clamping restart X index to maximum. %08x clamped to %08x\n", + restartX, maxX); + clamped = 1; + } + if (restartY > maxY) { + job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxY) | restartX; + dev_warn(dev, + "Clamping restart Y index to maximum. %08x clamped to %08x\n", + restartY, maxY); + clamped = 1; + } + + if (clamped) { + /* Reset the fault address low word + * and set the job status to STOPPED */ + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] = 0x0; + job_header[JOB_DESC_STATUS_WORD] = BASE_JD_EVENT_STOPPED; + dev_warn(dev, "After Clamping:\n" + "Jobstatus: %08x\n" + "restartIdx: %08x\n" + "Fault_addr_low: %08x\n" + "minCoordsX: %08x minCoordsY: %08x\n" + "maxCoordsX: %08x maxCoordsY: %08x\n", + job_header[JOB_DESC_STATUS_WORD], + job_header[JOB_DESC_RESTART_INDEX_WORD], + job_header[JOB_DESC_FAULT_ADDR_LOW_WORD], + minX, minY, + maxX, maxY); + + /* Flush CPU cache to update memory for future GPU reads*/ + memcpy(page_1, dst, copy_size); + p = pfn_to_page(PFN_DOWN(page_array[page_index])); + dma_sync_single_for_device(katom->kctx->kbdev->dev, + kbase_dma_addr(p) + offset, + copy_size, DMA_TO_DEVICE); + + if (copy_size < JOB_HEADER_SIZE) { + memcpy(page_2, dst + copy_size, + JOB_HEADER_SIZE - copy_size); + p = pfn_to_page(PFN_DOWN(page_array[page_index + 1])); + dma_sync_single_for_device(katom->kctx->kbdev->dev, + kbase_dma_addr(p), + JOB_HEADER_SIZE - copy_size, + DMA_TO_DEVICE); + } + } + if (copy_size < JOB_HEADER_SIZE) + kunmap_atomic(page_2); + + kunmap_atomic(page_1); + +out_unlock: + kbase_gpu_vm_unlock(katom->kctx); + return clamped; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.h new file mode 100644 index 0000000000000000000000000000000000000000..90bd027be30af875b64bf1af23d3595accd051e1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_10969_workaround.h @@ -0,0 +1,23 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_10969_WORKAROUND_ +#define _KBASE_10969_WORKAROUND_ + +int kbasep_10969_workaround_clamp_coordinates(struct kbase_jd_atom *katom); + +#endif /* _KBASE_10969_WORKAROUND_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c new file mode 100644 index 0000000000000000000000000000000000000000..a1c3aa88307b40a361fe2ad217e6381f1d3eb8d0 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c @@ -0,0 +1,41 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_cache_policy.h + * Cache Policy API. + */ + +#include "mali_kbase_cache_policy.h" + +/* + * The output flags should be a combination of the following values: + * KBASE_REG_CPU_CACHED: CPU cache should be enabled + */ +u32 kbase_cache_enabled(u32 flags, u32 nr_pages) +{ + u32 cache_flags = 0; + + CSTD_UNUSED(nr_pages); + + if (flags & BASE_MEM_CACHED_CPU) + cache_flags |= KBASE_REG_CPU_CACHED; + + return cache_flags; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h new file mode 100644 index 0000000000000000000000000000000000000000..70f8a4c8ada21472d1e9924503bf23668e1defcf --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h @@ -0,0 +1,47 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_cache_policy.h + * Cache Policy API. + */ + +#ifndef _KBASE_CACHE_POLICY_H_ +#define _KBASE_CACHE_POLICY_H_ + +#include +#include "mali_kbase.h" +#include "mali_base_kernel.h" + +/** + * @brief Choose the cache policy for a specific region + * + * Tells whether the CPU and GPU caches should be enabled or not for a specific region. + * This function can be modified to customize the cache policy depending on the flags + * and size of the region. + * + * @param[in] flags flags describing attributes of the region + * @param[in] nr_pages total number of pages (backed or not) for the region + * + * @return a combination of KBASE_REG_CPU_CACHED and KBASE_REG_GPU_CACHED depending + * on the cache policy + */ +u32 kbase_cache_enabled(u32 flags, u32 nr_pages); + +#endif /* _KBASE_CACHE_POLICY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config.c new file mode 100644 index 0000000000000000000000000000000000000000..88315acf42638f41e38b72fc05eb8ec85408496e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config.c @@ -0,0 +1,292 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include + +/* Specifies how many attributes are permitted in the config (excluding terminating attribute). + * This is used in validation function so we can detect if configuration is properly terminated. This value can be + * changed if we need to introduce more attributes or many memory regions need to be defined */ +#define ATTRIBUTE_COUNT_MAX 32 + +int kbasep_get_config_attribute_count(const struct kbase_attribute *attributes) +{ + int count = 1; + + if (!attributes) + return -EINVAL; + + while (attributes->id != KBASE_CONFIG_ATTR_END) { + attributes++; + count++; + } + + return count; +} + +const struct kbase_attribute *kbasep_get_next_attribute(const struct kbase_attribute *attributes, int attribute_id) +{ + KBASE_DEBUG_ASSERT(attributes != NULL); + + while (attributes->id != KBASE_CONFIG_ATTR_END) { + if (attributes->id == attribute_id) + return attributes; + + attributes++; + } + return NULL; +} + +KBASE_EXPORT_TEST_API(kbasep_get_next_attribute) + +int kbase_cpuprops_get_default_clock_speed(u32 * const clock_speed) +{ + KBASE_DEBUG_ASSERT(NULL != clock_speed); + + *clock_speed = 100; + return 0; +} + +uintptr_t kbasep_get_config_value(struct kbase_device *kbdev, const struct kbase_attribute *attributes, int attribute_id) +{ + const struct kbase_attribute *attr; + + KBASE_DEBUG_ASSERT(attributes != NULL); + + attr = kbasep_get_next_attribute(attributes, attribute_id); + if (attr != NULL) + return attr->data; + + /* default values */ + switch (attribute_id) { + /* Begin scheduling defaults */ + case KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS: + return DEFAULT_JS_SCHEDULING_TICK_NS; + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS: + return DEFAULT_JS_SOFT_STOP_TICKS; + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL: + return DEFAULT_JS_SOFT_STOP_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS: + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + return DEFAULT_JS_HARD_STOP_TICKS_SS_HW_ISSUE_8408; + else + return DEFAULT_JS_HARD_STOP_TICKS_SS; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL: + return DEFAULT_JS_HARD_STOP_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS: + return DEFAULT_JS_HARD_STOP_TICKS_NSS; + case KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS: + return DEFAULT_JS_CTX_TIMESLICE_NS; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS: + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + return DEFAULT_JS_RESET_TICKS_SS_HW_ISSUE_8408; + else + return DEFAULT_JS_RESET_TICKS_SS; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL: + return DEFAULT_JS_RESET_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS: + return DEFAULT_JS_RESET_TICKS_NSS; + case KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS: + return DEFAULT_JS_RESET_TIMEOUT_MS; + /* End scheduling defaults */ + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS: + return 0; + case KBASE_CONFIG_ATTR_PLATFORM_FUNCS: + return 0; + case KBASE_CONFIG_ATTR_CPU_SPEED_FUNC: + return DEFAULT_CPU_SPEED_FUNC; + case KBASE_CONFIG_ATTR_GPU_SPEED_FUNC: + return 0; + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ: + return DEFAULT_PM_DVFS_FREQ; + case KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: + return DEFAULT_PM_GPU_POWEROFF_TICK_NS; + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER: + return DEFAULT_PM_POWEROFF_TICK_SHADER; + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU: + return DEFAULT_PM_POWEROFF_TICK_GPU; + case KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS: + return 0; + + default: + dev_err(kbdev->dev, "kbasep_get_config_value. Cannot get value of attribute with id=%d and no default value defined", attribute_id); + return 0; + } +} + +KBASE_EXPORT_TEST_API(kbasep_get_config_value) + +mali_bool kbasep_platform_device_init(struct kbase_device *kbdev) +{ + struct kbase_platform_funcs_conf *platform_funcs; + + platform_funcs = (struct kbase_platform_funcs_conf *)kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PLATFORM_FUNCS); + if (platform_funcs) { + if (platform_funcs->platform_init_func) + return platform_funcs->platform_init_func(kbdev); + } + return MALI_TRUE; +} + +void kbasep_platform_device_term(struct kbase_device *kbdev) +{ + struct kbase_platform_funcs_conf *platform_funcs; + + platform_funcs = (struct kbase_platform_funcs_conf *)kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PLATFORM_FUNCS); + if (platform_funcs) { + if (platform_funcs->platform_term_func) + platform_funcs->platform_term_func(kbdev); + } +} + +static mali_bool kbasep_validate_pm_callback(const struct kbase_pm_callback_conf *callbacks, const struct kbase_device *kbdev) +{ + if (callbacks == NULL) { + /* Having no callbacks is valid */ + return MALI_TRUE; + } + + if ((callbacks->power_off_callback != NULL && callbacks->power_on_callback == NULL) || (callbacks->power_off_callback == NULL && callbacks->power_on_callback != NULL)) { + dev_warn(kbdev->dev, "Invalid power management callbacks: Only one of power_off_callback and power_on_callback was specified"); + return MALI_FALSE; + } + return MALI_TRUE; +} + +static mali_bool kbasep_validate_cpu_speed_func(kbase_cpuprops_clock_speed_function fcn) +{ + return fcn != NULL; +} + +mali_bool kbasep_validate_configuration_attributes(struct kbase_device *kbdev, const struct kbase_attribute *attributes) +{ + int i; + + KBASE_DEBUG_ASSERT(attributes); + + for (i = 0; attributes[i].id != KBASE_CONFIG_ATTR_END; i++) { + if (i >= ATTRIBUTE_COUNT_MAX) { + dev_warn(kbdev->dev, "More than ATTRIBUTE_COUNT_MAX=%d configuration attributes defined. Is attribute list properly terminated?", ATTRIBUTE_COUNT_MAX); + return MALI_FALSE; + } + + switch (attributes[i].id) { + /* Only non-zero unsigned 32-bit values accepted */ + case KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS: +#if CSTD_CPU_64BIT + if (attributes[i].data == 0u || (u64) attributes[i].data > (u64) U32_MAX) { +#else + if (attributes[i].data == 0u) { +#endif + dev_warn(kbdev->dev, "Invalid Job Scheduling Configuration attribute for " "KBASE_CONFIG_ATTR_JS_SCHEDULING_TICKS_NS: %d", (int)attributes[i].data); + return MALI_FALSE; + } + break; + + /* All these Job Scheduling attributes are FALLTHROUGH: only unsigned 32-bit values accepted */ + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS: + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS: + case KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS: + case KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "Job Scheduling Configuration attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS: + if (MALI_FALSE == kbasep_validate_pm_callback((struct kbase_pm_callback_conf *)attributes[i].data, kbdev)) { + /* Warning message handled by kbasep_validate_pm_callback() */ + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_CPU_SPEED_FUNC: + if (MALI_FALSE == kbasep_validate_cpu_speed_func((kbase_cpuprops_clock_speed_function) attributes[i].data)) { + dev_warn(kbdev->dev, "Invalid function pointer in KBASE_CONFIG_ATTR_CPU_SPEED_FUNC"); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_GPU_SPEED_FUNC: + if (0 == attributes[i].data) { + dev_warn(kbdev->dev, "Invalid function pointer in KBASE_CONFIG_ATTR_GPU_SPEED_FUNC"); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_PLATFORM_FUNCS: + /* any value is allowed */ + break; + + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "PM DVFS interval exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: +#if CSTD_CPU_64BIT + if (attributes[i].data == 0u || (u64) attributes[i].data > (u64) U32_MAX) { +#else + if (attributes[i].data == 0u) { +#endif + dev_warn(kbdev->dev, "Invalid Power Manager Configuration attribute for " "KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: %d", (int)attributes[i].data); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER: + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "Power Manager Configuration attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS: + if (0 == attributes[i].data) { + dev_warn(kbdev->dev, "Power model callbacks is specified but NULL: " "id==%d val==%d", + attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } + break; + + default: + dev_warn(kbdev->dev, "Invalid attribute found in configuration: %d", attributes[i].id); + return MALI_FALSE; + } + } + + return MALI_TRUE; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config.h new file mode 100644 index 0000000000000000000000000000000000000000..3a1acf89ac7b48f98cf657191d19ea9ea92dfd5f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config.h @@ -0,0 +1,722 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_config.h + * Configuration API and Attributes for KBase + */ + +#ifndef _KBASE_CONFIG_H_ +#define _KBASE_CONFIG_H_ + +#include + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_config Configuration API and Attributes + * @{ + */ + +#if !MALI_CUSTOMER_RELEASE +/* This flag is set for internal builds so we can run tests without credentials. */ +#define KBASE_HWCNT_DUMP_BYPASS_ROOT 1 +#else +#define KBASE_HWCNT_DUMP_BYPASS_ROOT 0 +#endif + +/* Enable power management API, note that KBASE_PM_EN==0 is not supported */ +#define KBASE_PM_EN 1 +/* Enable GPU reset API, note that KBASE_GPU_RESET_EN==0 is not supported */ +#define KBASE_GPU_RESET_EN 1 +/* Enable HW MMU backend, note that KBASE_MMU_HW_BACKEND==0 is not supported */ +#define KBASE_MMU_HW_BACKEND 1 + + +#include + + +/** + * Device wide configuration + */ +enum { + /** + * Invalid attribute ID (reserve 0). + * + * Attached value: Ignored + * Default value: NA + * */ + KBASE_CONFIG_ATTR_INVALID, + + /*** Begin Job Scheduling Configs ***/ + /** + * Job Scheduler scheduling tick granuality. This is in nanoseconds to + * allow HR timer support. + * + * On each scheduling tick, the scheduler may decide to: + * -# soft stop a job (the job will be re-run later, and other jobs will + * be able to run on the GPU now). This effectively controls the + * 'timeslice' given to a job. + * -# hard stop a job (to kill a job if it has spent too long on the GPU + * and didn't soft-stop). + * + * The numbers of ticks for these events are controlled by: + * - @ref KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS + * - @ref KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS + * - @ref KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS + * + * A soft-stopped job will later be resumed, allowing it to use more GPU + * time in total than that defined by any of the above. However, + * the scheduling policy attempts to limit the amount of \em uninterrupted + * time spent on the GPU using the above values (that is, the 'timeslice' + * of a job) + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::scheduling_tick_ns. + * The value might be rounded down to lower precision. Must be non-zero + * after rounding.
+ * Default value: @ref DEFAULT_JS_SCHEDULING_TICK_NS + * + * @note this value is allowed to be greater than + * @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS. This allows jobs to run on (much) + * longer than the job-timeslice, but once this happens, the context gets + * scheduled in (much) less frequently than others that stay within the + * ctx-timeslice. + */ + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + + /** + * Job Scheduler minimum number of scheduling ticks before non-CL jobs + * are soft-stopped. + * + * This defines the amount of time a job is allowed to stay on the GPU, + * before it is soft-stopped to allow other jobs to run. + * + * That is, this defines the 'timeslice' of the job. It is separate from the + * timeslice of the context that contains the job (see + * @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS). + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::soft_stop_ticks
+ * Default value: @ref DEFAULT_JS_SOFT_STOP_TICKS + * + * @note a value of zero means "the quickest time to soft-stop a job", + * which is somewhere between instant and one tick later. + * + * @note this value is allowed to be greater than + * @ref KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS or + * @ref KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS. This effectively disables + * soft-stop, and just uses hard-stop instead. In this case, this value + * should be much greater than any of the hard stop values (to avoid + * soft-stop-after-hard-stop) + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + + /** + * Job Scheduler minimum number of scheduling ticks before CL jobs + * are soft-stopped. + * + * This defines the amount of time a job is allowed to stay on the GPU, + * before it is soft-stopped to allow other jobs to run. + * + * That is, this defines the 'timeslice' of the job. It is separate + * from the timeslice of the context that contains the job (see + * @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS). + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit + * kbasep_js_device_data::soft_stop_ticks_cl
+ * Default value: @ref DEFAULT_JS_SOFT_STOP_TICKS_CL + * + * @note a value of zero means "the quickest time to soft-stop a job", + * which is somewhere between instant and one tick later. + * + * @note this value is allowed to be greater than + * @ref KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL. This effectively + * disables soft-stop, and just uses hard-stop instead. In this case, + * this value should be much greater than any of the hard stop values + * (to avoid soft-stop-after-hard-stop) + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + + /** + * Job Scheduler minimum number of scheduling ticks before non-CL jobs + * are hard-stopped. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is killed. Such jobs won't be resumed if killed. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::hard_stop_ticks_ss
+ * Default value: @ref DEFAULT_JS_HARD_STOP_TICKS_SS + * + * @note a value of zero means "the quickest time to hard-stop a job", + * which is somewhere between instant and one tick later. + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + + /** + * Job Scheduler minimum number of scheduling ticks before CL jobs are hard-stopped. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is killed. Such jobs won't be resumed if killed. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::hard_stop_ticks_cl
+ * Default value: @ref DEFAULT_JS_HARD_STOP_TICKS_CL + * + * @note a value of zero means "the quickest time to hard-stop a job", + * which is somewhere between instant and one tick later. + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + + /** + * Job Scheduler minimum number of scheduling ticks before jobs are hard-stopped + * when dumping. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is killed. Such jobs won't be resumed if killed. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::hard_stop_ticks_nss
+ * Default value: @ref DEFAULT_JS_HARD_STOP_TICKS_NSS + * + * @note a value of zero means "the quickest time to hard-stop a job", + * which is somewhere between instant and one tick later. + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + + /** + * Job Scheduler timeslice that a context is scheduled in for, in nanoseconds. + * + * When a context has used up this amount of time across its jobs, it is + * scheduled out to let another run. + * + * @note the resolution is nanoseconds (ns) here, because that's the format + * often used by the OS. + * + * This value controls affects the actual time defined by the following + * defaults: + * - @ref DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES + * - @ref DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::ctx_timeslice_ns. + * The value might be rounded down to lower precision.
+ * Default value: @ref DEFAULT_JS_CTX_TIMESLICE_NS + * + * @note a value of zero models a "Round Robin" scheduling policy, and + * disables @ref DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES + * (initially causing LIFO scheduling) and + * @ref DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES (allowing + * not-run-often contexts to get scheduled in quickly, but to only use + * a single timeslice when they get scheduled in). + */ + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + + /** + * Job Scheduler minimum number of scheduling ticks before non-CL jobs + * cause the GPU to be reset. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is assumed that the GPU has hung and needs to be reset. The assumes that the job + * has been hard-stopped already and so the presence of a job that has remained on + * the GPU for so long indicates that the GPU has in some way hung. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::gpu_reset_ticks_nss
+ * Default value: @ref DEFAULT_JS_RESET_TICKS_SS + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + + /** + * Job Scheduler minimum number of scheduling ticks before CL jobs + * cause the GPU to be reset. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is assumed that the GPU has hung and needs to be reset. The assumes that the job + * has been hard-stopped already and so the presence of a job that has remained on + * the GPU for so long indicates that the GPU has in some way hung. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::gpu_reset_ticks_cl
+ * Default value: @ref DEFAULT_JS_RESET_TICKS_CL + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + + /** + * Job Scheduler minimum number of scheduling ticks before jobs cause the GPU to be + * reset when dumping. + * + * This defines the amount of time a job is allowed to spend on the GPU before it + * is assumed that the GPU has hung and needs to be reset. The assumes that the job + * has been hard-stopped already and so the presence of a job that has remained on + * the GPU for so long indicates that the GPU has in some way hung. + * + * This value is supported by the following scheduling policies: + * - The Completely Fair Share (CFS) policy + * + * Attached value: unsigned 32-bit kbasep_js_device_data::gpu_reset_ticks_nss
+ * Default value: @ref DEFAULT_JS_RESET_TICKS_NSS + * + * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS + */ + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + + /** + * Number of milliseconds given for other jobs on the GPU to be + * soft-stopped when the GPU needs to be reset. + * + * Attached value: number in milliseconds + * Default value: @ref DEFAULT_JS_RESET_TIMEOUT_MS + */ + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + /*** End Job Scheduling Configs ***/ + + /** Power management configuration + * + * Attached value: pointer to @ref kbase_pm_callback_conf + * Default value: See @ref kbase_pm_callback_conf + */ + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + + /** + * A pointer to a function that calculates the CPU clock + * speed of the platform in MHz - see + * @ref kbase_cpuprops_clock_speed_function for the function + * prototype. + * + * Attached value: A @ref kbase_cpuprops_clock_speed_function. + * Default Value: Pointer to @ref DEFAULT_CPU_SPEED_FUNC - + * returns a clock speed of 100 MHz. + */ + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + + /** + * A pointer to a function that calculates the GPU clock + * speed of the platform in MHz - see + * @ref kbase_gpuprops_clock_speed_function for the function + * prototype. + * + * Attached value: A @ref kbase_gpuprops_clock_speed_function. + * Default Value: NULL (in which case the driver assumes maximum + * GPU frequency stored in gpu_freq_khz_max) + */ + KBASE_CONFIG_ATTR_GPU_SPEED_FUNC, + + /** + * Platform specific configuration functions + * + * Attached value: pointer to @ref kbase_platform_funcs_conf + * Default value: See @ref kbase_platform_funcs_conf + */ + KBASE_CONFIG_ATTR_PLATFORM_FUNCS, + + /** + * Rate at which dvfs data should be collected. + * + * Attached value: u32 value + * Default value: 500 Milliseconds + */ + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ, + + /** + * Power Management poweroff tick granuality. This is in nanoseconds to + * allow HR timer support. + * + * On each scheduling tick, the power manager core may decide to: + * -# Power off one or more shader cores + * -# Power off the entire GPU + * + * Attached value: number in nanoseconds + * Default value: @ref DEFAULT_PM_GPU_POWEROFF_TICK_NS, + */ + KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS, + + /** + * Power Manager number of ticks before shader cores are powered off + * + * Attached value: unsigned 32-bit kbasep_pm_device_data::poweroff_shader_ticks
+ * Default value: @ref DEFAULT_PM_POWEROFF_TICK_SHADER + * + * @see KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS + */ + KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER, + + /** + * Power Manager number of ticks before GPU is powered off + * + * Attached value: unsigned 32-bit kbasep_pm_device_data::poweroff_gpu_ticks
+ * Default value: @ref DEFAULT_PM_POWEROFF_TICK_GPU + * + * @see KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS + */ + KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU, + + /** Power model for IPA + * + * Attached value: pointer to @ref mali_pa_model_ops + */ + KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS, + + /** + * End of attribute list indicator. + * The configuration loader will stop processing any more elements + * when it encounters this attribute. + * + * Default value: NA + */ + KBASE_CONFIG_ATTR_END = 0x1FFFUL +}; + +/* + * @brief specifies a single attribute + * + * Attribute is identified by attr field. Data is either integer or a pointer to attribute-specific structure. + */ +typedef struct kbase_attribute { + int id; + uintptr_t data; +} kbase_attribute; + +/* Forward declaration of struct kbase_device */ +struct kbase_device; + +/* + * @brief Specifies the functions for platform specific initialization and termination + * + * By default no functions are required. No additional platform specific control is necessary. + */ +typedef struct kbase_platform_funcs_conf { + /** + * Function pointer for platform specific initialization or NULL if no initialization function is required. + * This function will be called \em before any other callbacks listed in the struct kbase_attribute struct (such as + * Power Management callbacks). + * The platform specific private pointer kbase_device::platform_context can be accessed (and possibly initialized) in here. + */ + mali_bool(*platform_init_func) (struct kbase_device *kbdev); + /** + * Function pointer for platform specific termination or NULL if no termination function is required. + * This function will be called \em after any other callbacks listed in the struct kbase_attribute struct (such as + * Power Management callbacks). + * The platform specific private pointer kbase_device::platform_context can be accessed (and possibly terminated) in here. + */ + void (*platform_term_func)(struct kbase_device *kbdev); + +} kbase_platform_funcs_conf; + +/* + * @brief Specifies the callbacks for power management + * + * By default no callbacks will be made and the GPU must not be powered off. + */ +typedef struct kbase_pm_callback_conf { + /** Callback for when the GPU is idle and the power to it can be switched off. + * + * The system integrator can decide whether to either do nothing, just switch off + * the clocks to the GPU, or to completely power down the GPU. + * The platform specific private pointer kbase_device::platform_context can be accessed and modified in here. It is the + * platform \em callbacks responsiblity to initialize and terminate this pointer if used (see @ref kbase_platform_funcs_conf). + */ + void (*power_off_callback)(struct kbase_device *kbdev); + + /** Callback for when the GPU is about to become active and power must be supplied. + * + * This function must not return until the GPU is powered and clocked sufficiently for register access to + * succeed. The return value specifies whether the GPU was powered down since the call to power_off_callback. + * If the GPU state has been lost then this function must return 1, otherwise it should return 0. + * The platform specific private pointer kbase_device::platform_context can be accessed and modified in here. It is the + * platform \em callbacks responsiblity to initialize and terminate this pointer if used (see @ref kbase_platform_funcs_conf). + * + * The return value of the first call to this function is ignored. + * + * @return 1 if the GPU state may have been lost, 0 otherwise. + */ + int (*power_on_callback)(struct kbase_device *kbdev); + + /** Callback for when the system is requesting a suspend and GPU power + * must be switched off. + * + * Note that if this callback is present, then this may be called + * without a preceding call to power_off_callback. Therefore this + * callback must be able to take any action that might otherwise happen + * in power_off_callback. + * + * The platform specific private pointer kbase_device::platform_context + * can be accessed and modified in here. It is the platform \em + * callbacks responsibility to initialize and terminate this pointer if + * used (see @ref kbase_platform_funcs_conf). + */ + void (*power_suspend_callback)(struct kbase_device *kbdev); + + /** Callback for when the system is resuming from a suspend and GPU + * power must be switched on. + * + * Note that if this callback is present, then this may be called + * without a following call to power_on_callback. Therefore this + * callback must be able to take any action that might otherwise happen + * in power_on_callback. + * + * The platform specific private pointer kbase_device::platform_context + * can be accessed and modified in here. It is the platform \em + * callbacks responsibility to initialize and terminate this pointer if + * used (see @ref kbase_platform_funcs_conf). + */ + void (*power_resume_callback)(struct kbase_device *kbdev); + + /** Callback for handling runtime power management initialization. + * + * The runtime power management callbacks @ref power_runtime_off_callback and @ref power_runtime_on_callback + * will become active from calls made to the OS from within this function. + * The runtime calls can be triggered by calls from @ref power_off_callback and @ref power_on_callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * + * @return MALI_ERROR_NONE on success, else mali_error erro code. + */ + mali_error(*power_runtime_init_callback) (struct kbase_device *kbdev); + + /** Callback for handling runtime power management termination. + * + * The runtime power management callbacks @ref power_runtime_off_callback and @ref power_runtime_on_callback + * should no longer be called by the OS on completion of this function. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + */ + void (*power_runtime_term_callback)(struct kbase_device *kbdev); + + /** Callback for runtime power-off power management callback + * + * For linux this callback will be called by the kernel runtime_suspend callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * + * @return 0 on success, else OS error code. + */ + void (*power_runtime_off_callback)(struct kbase_device *kbdev); + + /** Callback for runtime power-on power management callback + * + * For linux this callback will be called by the kernel runtime_resume callback. + * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + */ + int (*power_runtime_on_callback)(struct kbase_device *kbdev); + +} kbase_pm_callback_conf; + +/** + * @brief Default implementation of @ref KBASE_CONFIG_ATTR_CPU_SPEED_FUNC. + * + * This function sets clock_speed to 100, so will be an underestimate for + * any real system. + * + * See @ref kbase_cpuprops_clock_speed_function for details on the parameters + * and return value. + */ +int kbase_cpuprops_get_default_clock_speed(u32 * const clock_speed); + +/** + * Type of the function pointer for KBASE_CONFIG_ATTR_CPU_SPEED_FUNC. + * + * @param clock_speed [out] Once called this will contain the current CPU clock speed in MHz. + * This is mainly used to implement OpenCL's clGetDeviceInfo(). + * + * @return 0 on success, 1 on error. + */ +typedef int (*kbase_cpuprops_clock_speed_function) (u32 *clock_speed); + +/** + * Type of the function pointer for KBASE_CONFIG_ATTR_GPU_SPEED_FUNC. + * + * @param clock_speed [out] Once called this will contain the current GPU clock speed in MHz. + * If the system timer is not available then this function is required + * for the OpenCL queue profiling to return correct timing information. + * + * @return 0 on success, 1 on error. When an error is returned the caller assumes maximum + * GPU speed stored in gpu_freq_khz_max. + */ +typedef int (*kbase_gpuprops_clock_speed_function) (u32 *clock_speed); + +#ifdef CONFIG_OF +typedef struct kbase_platform_config { + const struct kbase_attribute *attributes; + u32 midgard_type; +} kbase_platform_config; +#else + +/* + * @brief Specifies start and end of I/O memory region. + */ +typedef struct kbase_io_memory_region { + u64 start; + u64 end; +} kbase_io_memory_region; + +/* + * @brief Specifies I/O related resources like IRQs and memory region for I/O operations. + */ +typedef struct kbase_io_resources { + + u32 job_irq_number; + u32 mmu_irq_number; + u32 gpu_irq_number; + struct kbase_io_memory_region io_memory_region; +} kbase_io_resources; + +typedef struct kbase_platform_config { + const struct kbase_attribute *attributes; + const struct kbase_io_resources *io_resources; + u32 midgard_type; +} kbase_platform_config; + +#endif /* CONFIG_OF */ + +/** + * @brief Return character string associated with the given midgard type. + * + * @param[in] midgard_type - ID of midgard type + * + * @return Pointer to NULL-terminated character array associated with the given midgard type + */ +const char *kbasep_midgard_type_to_string(u32 midgard_type); + +/** + * @brief Gets the next config attribute with the specified ID from the array of attributes. + * + * Function gets the next attribute with specified attribute id within specified array. If no such attribute is found, + * NULL is returned. + * + * @param[in] attributes Array of attributes in which lookup is performed + * @param[in] attribute_id ID of attribute + * + * @return Pointer to the first attribute matching id or NULL if none is found. + */ +const struct kbase_attribute *kbasep_get_next_attribute(const struct kbase_attribute *attributes, int attribute_id); + +/** + * @brief Gets the value of a single config attribute. + * + * Function gets the value of attribute specified as parameter. If no such attribute is found in the array of + * attributes, default value is used. + * + * @param[in] kbdev Kbase device pointer + * @param[in] attributes Array of attributes in which lookup is performed + * @param[in] attribute_id ID of attribute + * + * @return Value of attribute with the given id + */ +uintptr_t kbasep_get_config_value(struct kbase_device *kbdev, const struct kbase_attribute *attributes, int attribute_id); + +/** + * @brief Validates configuration attributes + * + * Function checks validity of given configuration attributes. It will fail on any attribute with unknown id, attribute + * with invalid value or attribute list that is not correctly terminated. + * + * @param[in] kbdev Kbase device pointer + * @param[in] attributes Array of attributes to validate + * + * @return MALI_TRUE if no errors have been found in the config. MALI_FALSE otherwise. + */ +mali_bool kbasep_validate_configuration_attributes(struct kbase_device *kbdev, const struct kbase_attribute *attributes); + +/** + * @brief Gets the pointer to platform config. + * + * @return Pointer to the platform config + */ +struct kbase_platform_config *kbase_get_platform_config(void); + +/** + * @brief Gets the count of attributes in array + * + * Function gets the count of attributes in array. Note that end of list indicator is also included. + * + * @param[in] attributes Array of attributes + * + * @return Number of attributes in the array including end of list indicator. + */ +int kbasep_get_config_attribute_count(const struct kbase_attribute *attributes); + +/** + * @brief Platform specific call to initialize hardware + * + * Function calls a platform defined routine if specified in the configuration attributes. + * The routine can initialize any hardware and context state that is required for the GPU block to function. + * + * @param[in] kbdev Kbase device pointer + * + * @return MALI_TRUE if no errors have been found in the config. MALI_FALSE otherwise. + */ +mali_bool kbasep_platform_device_init(struct kbase_device *kbdev); + +/** + * @brief Platform specific call to terminate hardware + * + * Function calls a platform defined routine if specified in the configuration attributes. + * The routine can destroy any platform specific context state and shut down any hardware functionality that are + * outside of the Power Management callbacks. + * + * @param[in] kbdev Kbase device pointer + * + */ +void kbasep_platform_device_term(struct kbase_device *kbdev); + + /** @} *//* end group kbase_config */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_CONFIG_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h new file mode 100644 index 0000000000000000000000000000000000000000..8204e611dd82a2bd3923664ad4a4971963e99ddc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h @@ -0,0 +1,288 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_config_defaults.h + * + * Default values for configuration settings + * + */ + +#ifndef _KBASE_CONFIG_DEFAULTS_H_ +#define _KBASE_CONFIG_DEFAULTS_H_ + +/* Include mandatory definitions per platform */ +#include + +/** + * Irq throttle. It is the minimum desired time in between two + * consecutive gpu interrupts (given in 'us'). The irq throttle + * gpu register will be configured after this, taking into + * account the configured max frequency. + * + * Attached value: number in micro seconds + */ +#define DEFAULT_IRQ_THROTTLE_TIME_US 20 + +/*** Begin Scheduling defaults ***/ + +/** + * Default scheduling tick granuality, in nanoseconds + */ +/* 50ms */ +#define DEFAULT_JS_SCHEDULING_TICK_NS 50000000u + +/** + * Default minimum number of scheduling ticks before jobs are soft-stopped. + * + * This defines the time-slice for a job (which may be different from that of + * a context) + */ +/* Between 0.1 and 0.15s before soft-stop */ +#define DEFAULT_JS_SOFT_STOP_TICKS 2 + +/** + * Default minimum number of scheduling ticks before CL jobs are soft-stopped. + */ +/* Between 0.05 and 0.1s before soft-stop */ +#define DEFAULT_JS_SOFT_STOP_TICKS_CL 1 + +/** + * Default minimum number of scheduling ticks before jobs are hard-stopped + */ +/* 1.2s before hard-stop, for a certain GLES2 test at 128x128 (bound by + * combined vertex+tiler job) + */ +#define DEFAULT_JS_HARD_STOP_TICKS_SS_HW_ISSUE_8408 24 +/* Between 0.2 and 0.25s before hard-stop */ +#define DEFAULT_JS_HARD_STOP_TICKS_SS 4 + +/** + * Default minimum number of scheduling ticks before CL jobs are hard-stopped. + */ +/* Between 0.1 and 0.15s before hard-stop */ +#define DEFAULT_JS_HARD_STOP_TICKS_CL 2 + +/** + * Default minimum number of scheduling ticks before jobs are hard-stopped + * during dumping + */ +/* 60s @ 50ms tick */ +#define DEFAULT_JS_HARD_STOP_TICKS_NSS 1200 + +/** + * Default minimum number of scheduling ticks before the GPU is reset + * to clear a "stuck" job + */ +/* 1.8s before resetting GPU, for a certain GLES2 test at 128x128 (bound by + * combined vertex+tiler job) + */ +#define DEFAULT_JS_RESET_TICKS_SS_HW_ISSUE_8408 36 +/* 0.3-0.35s before GPU is reset */ +#define DEFAULT_JS_RESET_TICKS_SS 6 + +/** + * Default minimum number of scheduling ticks before the GPU is reset + * to clear a "stuck" CL job. + */ +/* 0.2-0.25s before GPU is reset */ +#define DEFAULT_JS_RESET_TICKS_CL 4 + +/** + * Default minimum number of scheduling ticks before the GPU is reset + * to clear a "stuck" job during dumping. + */ +/* 60.1s @ 100ms tick */ +#define DEFAULT_JS_RESET_TICKS_NSS 1202 + +/** + * Number of milliseconds given for other jobs on the GPU to be + * soft-stopped when the GPU needs to be reset. + */ +#define DEFAULT_JS_RESET_TIMEOUT_MS 3000 + +/** + * Default timeslice that a context is scheduled in for, in nanoseconds. + * + * When a context has used up this amount of time across its jobs, it is + * scheduled out to let another run. + * + * @note the resolution is nanoseconds (ns) here, because that's the format + * often used by the OS. + */ +/* 0.05s - at 20fps a ctx does at least 1 frame before being scheduled out. + * At 40fps, 2 frames, etc + */ +#define DEFAULT_JS_CTX_TIMESLICE_NS 50000000 + +/** + * Default Job Scheduler initial runtime of a context for the CFS Policy, + * in time-slices. + * + * This value is relative to that of the least-run context, and defines + * where in the CFS queue a new context is added. A value of 1 means 'after + * the least-run context has used its timeslice'. Therefore, when all + * contexts consistently use the same amount of time, a value of 1 models a + * FIFO. A value of 0 would model a LIFO. + * + * The value is represented in "numbers of time slices". Multiply this + * value by that defined in @ref DEFAULT_JS_CTX_TIMESLICE_NS to get + * the time value for this in nanoseconds. + */ +#define DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES 1 + +/** + * Default Job Scheduler minimum runtime value of a context for CFS, in + * time_slices relative to that of the least-run context. + * + * This is a measure of how much preferrential treatment is given to a + * context that is not run very often. + * + * Specficially, this value defines how many timeslices such a context is + * (initially) allowed to use at once. Such contexts (e.g. 'interactive' + * processes) will appear near the front of the CFS queue, and can initially + * use more time than contexts that run continuously (e.g. 'batch' + * processes). + * + * This limit \b prevents a "stored-up timeslices" DoS attack, where a ctx + * not run for a long time attacks the system by using a very large initial + * number of timeslices when it finally does run. + * + * @note A value of zero allows not-run-often contexts to get scheduled in + * quickly, but to only use a single timeslice when they get scheduled in. + */ +#define DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES 2 + +/** +* Boolean indicating whether the driver is configured to be secure at +* a potential loss of performance. +* +* This currently affects only r0p0-15dev0 HW and earlier. +* +* On r0p0-15dev0 HW and earlier, there are tradeoffs between security and +* performance: +* +* - When this is set to MALI_TRUE, the driver remains fully secure, +* but potentially loses performance compared with setting this to +* MALI_FALSE. +* - When set to MALI_FALSE, the driver is open to certain security +* attacks. +* +* From r0p0-00rel0 and onwards, there is no security loss by setting +* this to MALI_FALSE, and no performance loss by setting it to +* MALI_TRUE. +*/ +#define DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE MALI_FALSE + +enum { + /** + * Use unrestricted Address ID width on the AXI bus. + */ + KBASE_AID_32 = 0x0, + + /** + * Restrict GPU to a half of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_16 = 0x3, + + /** + * Restrict GPU to a quarter of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_8 = 0x2, + + /** + * Restrict GPU to an eighth of maximum Address ID count. + * This will reduce performance, but reduce bus load due to GPU. + */ + KBASE_AID_4 = 0x1 +}; + +/** + * Default setting for read Address ID limiting on AXI bus. + * + * Attached value: u32 register value + * KBASE_AID_32 - use the full 32 IDs (5 ID bits) + * KBASE_AID_16 - use 16 IDs (4 ID bits) + * KBASE_AID_8 - use 8 IDs (3 ID bits) + * KBASE_AID_4 - use 4 IDs (2 ID bits) + * Default value: KBASE_AID_32 (no limit). Note hardware implementation + * may limit to a lower value. + */ +#define DEFAULT_ARID_LIMIT KBASE_AID_32 + +/** + * Default setting for write Address ID limiting on AXI. + * + * Attached value: u32 register value + * KBASE_AID_32 - use the full 32 IDs (5 ID bits) + * KBASE_AID_16 - use 16 IDs (4 ID bits) + * KBASE_AID_8 - use 8 IDs (3 ID bits) + * KBASE_AID_4 - use 4 IDs (2 ID bits) + * Default value: KBASE_AID_32 (no limit). Note hardware implementation + * may limit to a lower value. + */ +#define DEFAULT_AWID_LIMIT KBASE_AID_32 + +/** + * Default setting for using alternative hardware counters. + */ +#define DEFAULT_ALTERNATIVE_HWC MALI_FALSE + +/*** End Scheduling defaults ***/ + +/*** Begin Power Manager defaults */ + +/* Milliseconds */ +#define DEFAULT_PM_DVFS_FREQ 25 + +/** + * Default poweroff tick granuality, in nanoseconds + */ +/* 400us */ +#define DEFAULT_PM_GPU_POWEROFF_TICK_NS 400000 + +/** + * Default number of poweroff ticks before shader cores are powered off + */ +/* 400-800us */ +#define DEFAULT_PM_POWEROFF_TICK_SHADER 2 + +/** + * Default number of poweroff ticks before GPU is powered off + */ +#define DEFAULT_PM_POWEROFF_TICK_GPU 2 /* 400-800us */ + +/*** End Power Manager defaults ***/ + + +/** + * Default UMP device mapping. A UMP_DEVICE__SHIFT value which + * defines which UMP device this GPU should be mapped to. + */ +#define DEFAULT_UMP_GPU_DEVICE_SHIFT UMP_DEVICE_Z_SHIFT + +/** + * Default value for KBASE_CONFIG_ATTR_CPU_SPEED_FUNC. + * Points to @ref kbase_cpuprops_get_default_clock_speed. + */ +#define DEFAULT_CPU_SPEED_FUNC \ + ((uintptr_t)kbase_cpuprops_get_default_clock_speed) + +#endif /* _KBASE_CONFIG_DEFAULTS_H_ */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_context.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_context.c new file mode 100644 index 0000000000000000000000000000000000000000..1d42445672b8abd2f2d4d7dc657610c138e4ae3f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_context.c @@ -0,0 +1,280 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_context.c + * Base kernel context APIs + */ + +#include +#include + +#define MEMPOOL_PAGES 16384 + + +/** + * @brief Create a kernel base context. + * + * Allocate and init a kernel base context. + */ +struct kbase_context * +kbase_create_context(struct kbase_device *kbdev, bool is_compat) +{ + struct kbase_context *kctx; + mali_error mali_err; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* zero-inited as lot of code assume it's zero'ed out on create */ + kctx = vzalloc(sizeof(*kctx)); + + if (!kctx) + goto out; + + /* creating a context is considered a disjoint event */ + kbase_disjoint_event(kbdev); + + kctx->kbdev = kbdev; + kctx->as_nr = KBASEP_AS_NR_INVALID; + kctx->is_compat = is_compat; +#ifdef CONFIG_MALI_TRACE_TIMELINE + kctx->timeline.owner_tgid = task_tgid_nr(current); +#endif + atomic_set(&kctx->setup_complete, 0); + atomic_set(&kctx->setup_in_progress, 0); + kctx->keep_gpu_powered = MALI_FALSE; + spin_lock_init(&kctx->mm_update_lock); + kctx->process_mm = NULL; + atomic_set(&kctx->nonmapped_pages, 0); + + if (MALI_ERROR_NONE != kbase_mem_allocator_init(&kctx->osalloc, + MEMPOOL_PAGES, + kctx->kbdev)) + goto free_kctx; + + kctx->pgd_allocator = &kctx->osalloc; + atomic_set(&kctx->used_pages, 0); + + if (kbase_jd_init(kctx)) + goto free_allocator; + + mali_err = kbasep_js_kctx_init(kctx); + if (MALI_ERROR_NONE != mali_err) + goto free_jd; /* safe to call kbasep_js_kctx_term in this case */ + + mali_err = kbase_event_init(kctx); + if (MALI_ERROR_NONE != mali_err) + goto free_jd; + + mutex_init(&kctx->reg_lock); + + INIT_LIST_HEAD(&kctx->waiting_soft_jobs); +#ifdef CONFIG_KDS + INIT_LIST_HEAD(&kctx->waiting_kds_resource); +#endif + + mali_err = kbase_mmu_init(kctx); + if (MALI_ERROR_NONE != mali_err) + goto free_event; + + kctx->pgd = kbase_mmu_alloc_pgd(kctx); + if (!kctx->pgd) + goto free_mmu; + + if (MALI_ERROR_NONE != kbase_mem_allocator_alloc(&kctx->osalloc, 1, &kctx->aliasing_sink_page)) + goto no_sink_page; + + kctx->tgid = current->tgid; + kctx->pid = current->pid; + init_waitqueue_head(&kctx->event_queue); + + kctx->cookies = KBASE_COOKIE_MASK; + + /* Make sure page 0 is not used... */ + if (kbase_region_tracker_init(kctx)) + goto no_region_tracker; +#ifdef CONFIG_GPU_TRACEPOINTS + atomic_set(&kctx->jctx.work_id, 0); +#endif +#ifdef CONFIG_MALI_TRACE_TIMELINE + atomic_set(&kctx->timeline.jd_atoms_in_flight, 0); +#endif + + kctx->id = atomic_add_return(1, &(kbdev->ctx_num)) - 1; + + mali_err = kbasep_mem_profile_debugfs_add(kctx); + if (MALI_ERROR_NONE != mali_err) + goto no_region_tracker; + + if (kbasep_jd_debugfs_ctx_add(kctx)) + goto free_mem_profile; + + return kctx; + +free_mem_profile: + kbasep_mem_profile_debugfs_remove(kctx); +no_region_tracker: +no_sink_page: + kbase_mem_allocator_free(&kctx->osalloc, 1, &kctx->aliasing_sink_page, 0); + kbase_mmu_free_pgd(kctx); +free_mmu: + kbase_mmu_term(kctx); +free_event: + kbase_event_cleanup(kctx); +free_jd: + /* Safe to call this one even when didn't initialize (assuming kctx was sufficiently zeroed) */ + kbasep_js_kctx_term(kctx); + kbase_jd_exit(kctx); +free_allocator: + kbase_mem_allocator_term(&kctx->osalloc); +free_kctx: + vfree(kctx); +out: + return NULL; + +} +KBASE_EXPORT_SYMBOL(kbase_create_context) + +static void kbase_reg_pending_dtor(struct kbase_va_region *reg) +{ + dev_dbg(reg->kctx->kbdev->dev, "Freeing pending unmapped region\n"); + kbase_mem_phy_alloc_put(reg->alloc); + kfree(reg); +} + +/** + * @brief Destroy a kernel base context. + * + * Destroy a kernel base context. Calls kbase_destroy_os_context() to + * free OS specific structures. Will release all outstanding regions. + */ +void kbase_destroy_context(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + int pages; + unsigned long pending_regions_to_clean; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + KBASE_TRACE_ADD(kbdev, CORE_CTX_DESTROY, kctx, NULL, 0u, 0u); + + kbasep_jd_debugfs_ctx_remove(kctx); + + kbasep_mem_profile_debugfs_remove(kctx); + + /* Ensure the core is powered up for the destroy process */ + /* A suspend won't happen here, because we're in a syscall from a userspace + * thread. */ + kbase_pm_context_active(kbdev); + + if (kbdev->hwcnt.kctx == kctx) { + /* disable the use of the hw counters if the app didn't use the API correctly or crashed */ + KBASE_TRACE_ADD(kbdev, CORE_CTX_HWINSTR_TERM, kctx, NULL, 0u, 0u); + dev_warn(kbdev->dev, "The privileged process asking for instrumentation forgot to disable it " "before exiting. Will end instrumentation for them"); + kbase_instr_hwcnt_disable(kctx); + } + + kbase_jd_zap_context(kctx); + kbase_event_cleanup(kctx); + + kbase_gpu_vm_lock(kctx); + + /* MMU is disabled as part of scheduling out the context */ + kbase_mmu_free_pgd(kctx); + + /* drop the aliasing sink page now that it can't be mapped anymore */ + kbase_mem_allocator_free(&kctx->osalloc, 1, &kctx->aliasing_sink_page, 0); + + /* free pending region setups */ + pending_regions_to_clean = (~kctx->cookies) & KBASE_COOKIE_MASK; + while (pending_regions_to_clean) { + unsigned int cookie = __ffs(pending_regions_to_clean); + BUG_ON(!kctx->pending_regions[cookie]); + + kbase_reg_pending_dtor(kctx->pending_regions[cookie]); + + kctx->pending_regions[cookie] = NULL; + pending_regions_to_clean &= ~(1UL << cookie); + } + + kbase_region_tracker_term(kctx); + kbase_gpu_vm_unlock(kctx); + + /* Safe to call this one even when didn't initialize (assuming kctx was sufficiently zeroed) */ + kbasep_js_kctx_term(kctx); + + kbase_jd_exit(kctx); + + kbase_pm_context_idle(kbdev); + + kbase_mmu_term(kctx); + + pages = atomic_read(&kctx->used_pages); + if (pages != 0) + dev_warn(kbdev->dev, "%s: %d pages in use!\n", __func__, pages); + + if (kctx->keep_gpu_powered) { + atomic_dec(&kbdev->keep_gpu_powered_count); + kbase_pm_context_idle(kbdev); + } + + kbase_mem_allocator_term(&kctx->osalloc); + WARN_ON(atomic_read(&kctx->nonmapped_pages) != 0); + + vfree(kctx); +} +KBASE_EXPORT_SYMBOL(kbase_destroy_context) + +/** + * Set creation flags on a context + */ +mali_error kbase_context_set_create_flags(struct kbase_context *kctx, u32 flags) +{ + mali_error err = MALI_ERROR_NONE; + struct kbasep_js_kctx_info *js_kctx_info; + KBASE_DEBUG_ASSERT(NULL != kctx); + + js_kctx_info = &kctx->jctx.sched_info; + + /* Validate flags */ + if (flags != (flags & BASE_CONTEXT_CREATE_KERNEL_FLAGS)) { + err = MALI_ERROR_FUNCTION_FAILED; + goto out; + } + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + + /* Translate the flags */ + if ((flags & BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) == 0) + js_kctx_info->ctx.flags &= ~((u32) KBASE_CTX_FLAG_SUBMIT_DISABLED); + + if ((flags & BASE_CONTEXT_HINT_ONLY_COMPUTE) != 0) + js_kctx_info->ctx.flags |= (u32) KBASE_CTX_FLAG_HINT_ONLY_COMPUTE; + + /* Latch the initial attributes into the Job Scheduler */ + kbasep_js_ctx_attr_set_initial_attrs(kctx->kbdev, kctx); + + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + out: + return err; +} +KBASE_EXPORT_SYMBOL(kbase_context_set_create_flags) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_core_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..bec2e64c64fe5558bb764d5d23bb07907f8e7297 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_core_linux.c @@ -0,0 +1,3721 @@ + +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +/** + * @file mali_kbase_core_linux.c + * Base kernel driver init. + */ + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MALI_DEVFREQ +#include "mali_kbase_devfreq.h" +#endif /* CONFIG_MALI_DEVFREQ */ +#include +#ifdef CONFIG_MALI_NO_MALI +#include "mali_kbase_model_linux.h" +#endif /* CONFIG_MALI_NO_MALI */ +#include "mali_kbase_mem_profile_debugfs_buf_size.h" + +#ifdef CONFIG_KDS +#include +#include +#include +#endif /* CONFIG_KDS */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* is_compat_task */ +#include +#include +#include +#ifdef CONFIG_SYNC +#include +#endif /* CONFIG_SYNC */ +#ifdef CONFIG_PM_DEVFREQ +#include +#endif /* CONFIG_PM_DEVFREQ */ +#include + +/* + * This file is included since when we support device tree we don't + * use the platform fake code for registering the kbase config attributes. + */ +#ifdef CONFIG_OF +#include +#endif + +#ifdef CONFIG_MACH_MANTA +#include +#endif + +/* MTK GPU DVFS */ +#include +#include "mach/mt_gpufreq.h" + +/* GPU IRQ Tags */ +#define JOB_IRQ_TAG 0 +#define MMU_IRQ_TAG 1 +#define GPU_IRQ_TAG 2 + + +struct kbase_irq_table { + u32 tag; + irq_handler_t handler; +}; +#if MALI_UNIT_TEST +static struct kbase_exported_test_data shared_kernel_test_data; +EXPORT_SYMBOL(shared_kernel_test_data); +#endif /* MALI_UNIT_TEST */ + +#define KBASE_DRV_NAME "mali" + +static const char kbase_drv_name[] = KBASE_DRV_NAME; + +static int kbase_dev_nr; + +/* MTK GPU DVFS freq */ +int g_current_freq_id = 3; +int g_deferred_down_shift = 0; + +#define MTK_GPU_BOOST_DURATION 2 +int g_gpu_boost_duartion = 0; +int g_gpu_boost_id = 0; /* MTK for touch boost (only for a period of time) */ +int g_custom_gpu_boost_id = 0; /* MTK for mtk_custom_boost_gpu_freq (always set as lower bound of frequency). The lower bound function is used for performance service currently. */ +int g_ged_gpu_boost_id = 0; /* MTK for mtk_set_boost_gpu_freq (always set as lower bound of frequency). The lower bound function is used for GED boost currently. */ + +/* + Add by mediatek, Hook the memory query function pointer to (*mtk_get_gpu_memory_usage_fp) in order to + provide the gpu total memory usage to mlogger module +*/ +extern unsigned int (*mtk_get_gpu_memory_usage_fp)(void); + +static DEFINE_SEMAPHORE(kbase_dev_list_lock); +static LIST_HEAD(kbase_dev_list); + +KBASE_EXPORT_TEST_API(kbase_dev_list_lock) +KBASE_EXPORT_TEST_API(kbase_dev_list) +#define KERNEL_SIDE_DDK_VERSION_STRING "K:" MALI_RELEASE_NAME "(GPL)" +static INLINE void __compile_time_asserts(void) +{ + CSTD_COMPILE_TIME_ASSERT(sizeof(KERNEL_SIDE_DDK_VERSION_STRING) <= KBASE_GET_VERSION_BUFFER_SIZE); +} + +#ifdef CONFIG_KDS + +struct kbasep_kds_resource_set_file_data { + struct kds_resource_set *lock; +}; + +static int kds_resource_release(struct inode *inode, struct file *file); + +static const struct file_operations kds_resource_fops = { + .release = kds_resource_release +}; + +struct kbase_kds_resource_list_data { + struct kds_resource **kds_resources; + unsigned long *kds_access_bitmap; + int num_elems; +}; + +static int kds_resource_release(struct inode *inode, struct file *file) +{ + struct kbasep_kds_resource_set_file_data *data; + + data = (struct kbasep_kds_resource_set_file_data *)file->private_data; + if (NULL != data) { + if (NULL != data->lock) + kds_resource_set_release(&data->lock); + + kfree(data); + } + return 0; +} + +static mali_error kbasep_kds_allocate_resource_list_data(struct kbase_context *kctx, struct base_external_resource *ext_res, int num_elems, struct kbase_kds_resource_list_data *resources_list) +{ + struct base_external_resource *res = ext_res; + int res_id; + + /* assume we have to wait for all */ + + KBASE_DEBUG_ASSERT(0 != num_elems); + resources_list->kds_resources = kmalloc_array(num_elems, + sizeof(struct kds_resource *), GFP_KERNEL); + + if (NULL == resources_list->kds_resources) + return MALI_ERROR_OUT_OF_MEMORY; + + KBASE_DEBUG_ASSERT(0 != num_elems); + resources_list->kds_access_bitmap = kzalloc( + sizeof(unsigned long) * + ((num_elems + BITS_PER_LONG - 1) / BITS_PER_LONG), + GFP_KERNEL); + + if (NULL == resources_list->kds_access_bitmap) { + kfree(resources_list->kds_access_bitmap); + return MALI_ERROR_OUT_OF_MEMORY; + } + + kbase_gpu_vm_lock(kctx); + for (res_id = 0; res_id < num_elems; res_id++, res++) { + int exclusive; + struct kbase_va_region *reg; + struct kds_resource *kds_res = NULL; + + exclusive = res->ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE; + reg = kbase_region_tracker_find_region_enclosing_address(kctx, res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE); + + /* did we find a matching region object? */ + if (NULL == reg || (reg->flags & KBASE_REG_FREE)) + break; + + /* no need to check reg->alloc as only regions with an alloc has + * a size, and kbase_region_tracker_find_region_enclosing_address + * only returns regions with size > 0 */ + switch (reg->alloc->type) { +#if defined(CONFIG_UMP) && defined(CONFIG_KDS) + case KBASE_MEM_TYPE_IMPORTED_UMP: + kds_res = ump_dd_kds_resource_get(reg->alloc->imported.ump_handle); + break; +#endif /* defined(CONFIG_UMP) && defined(CONFIG_KDS) */ + default: + break; + } + + /* no kds resource for the region ? */ + if (!kds_res) + break; + + resources_list->kds_resources[res_id] = kds_res; + + if (exclusive) + set_bit(res_id, resources_list->kds_access_bitmap); + } + kbase_gpu_vm_unlock(kctx); + + /* did the loop run to completion? */ + if (res_id == num_elems) + return MALI_ERROR_NONE; + + /* Clean up as the resource list is not valid. */ + kfree(resources_list->kds_resources); + kfree(resources_list->kds_access_bitmap); + + return MALI_ERROR_FUNCTION_FAILED; +} + +static mali_bool kbasep_validate_kbase_pointer( + struct kbase_context *kctx, union kbase_pointer *p) +{ + if (kctx->is_compat) { + if (p->compat_value == 0) + return MALI_FALSE; + } else { + if (NULL == p->value) + return MALI_FALSE; + } + return MALI_TRUE; +} + +static mali_error kbase_external_buffer_lock(struct kbase_context *kctx, struct kbase_uk_ext_buff_kds_data *args, u32 args_size) +{ + struct base_external_resource *ext_res_copy; + size_t ext_resource_size; + mali_error return_error = MALI_ERROR_FUNCTION_FAILED; + int fd; + + if (args_size != sizeof(struct kbase_uk_ext_buff_kds_data)) + return MALI_ERROR_FUNCTION_FAILED; + + /* Check user space has provided valid data */ + if (!kbasep_validate_kbase_pointer(kctx, &args->external_resource) || + !kbasep_validate_kbase_pointer(kctx, &args->file_descriptor) || + (0 == args->num_res) || + (args->num_res > KBASE_MAXIMUM_EXT_RESOURCES)) + return MALI_ERROR_FUNCTION_FAILED; + + ext_resource_size = sizeof(struct base_external_resource) * args->num_res; + + KBASE_DEBUG_ASSERT(0 != ext_resource_size); + ext_res_copy = kmalloc(ext_resource_size, GFP_KERNEL); + + if (NULL != ext_res_copy) { + struct base_external_resource __user *ext_res_user; + int __user *file_descriptor_user; +#ifdef CONFIG_COMPAT + if (kctx->is_compat) { + ext_res_user = compat_ptr(args->external_resource.compat_value); + file_descriptor_user = compat_ptr(args->file_descriptor.compat_value); + } else { +#endif /* CONFIG_COMPAT */ + ext_res_user = args->external_resource.value; + file_descriptor_user = args->file_descriptor.value; +#ifdef CONFIG_COMPAT + } +#endif /* CONFIG_COMPAT */ + + /* Copy the external resources to lock from user space */ + if (0 == copy_from_user(ext_res_copy, ext_res_user, ext_resource_size)) { + struct kbasep_kds_resource_set_file_data *fdata; + + /* Allocate data to be stored in the file */ + fdata = kmalloc(sizeof(*fdata), GFP_KERNEL); + + if (NULL != fdata) { + struct kbase_kds_resource_list_data resource_list_data; + /* Parse given elements and create resource and access lists */ + return_error = kbasep_kds_allocate_resource_list_data(kctx, ext_res_copy, args->num_res, &resource_list_data); + if (MALI_ERROR_NONE == return_error) { + long err; + + fdata->lock = NULL; + + fd = anon_inode_getfd("kds_ext", &kds_resource_fops, fdata, 0); + + err = copy_to_user(file_descriptor_user, &fd, sizeof(fd)); + + /* If the file descriptor was valid and we successfully copied it to user space, then we + * can try and lock the requested kds resources. + */ + if ((fd >= 0) && (0 == err)) { + struct kds_resource_set *lock; + + lock = kds_waitall(args->num_res, resource_list_data.kds_access_bitmap, + resource_list_data.kds_resources, + KDS_WAIT_BLOCKING); + + if (IS_ERR_OR_NULL(lock)) { + return_error = MALI_ERROR_FUNCTION_FAILED; + } else { + return_error = MALI_ERROR_NONE; + fdata->lock = lock; + } + } else { + return_error = MALI_ERROR_FUNCTION_FAILED; + } + + kfree(resource_list_data.kds_resources); + kfree(resource_list_data.kds_access_bitmap); + } + + if (MALI_ERROR_NONE != return_error) { + /* If the file was opened successfully then close it which will clean up + * the file data, otherwise we clean up the file data ourself. */ + if (fd >= 0) + sys_close(fd); + else + kfree(fdata); + } + } else { + return_error = MALI_ERROR_OUT_OF_MEMORY; + } + } + kfree(ext_res_copy); + } + return return_error; +} +#endif /* CONFIG_KDS */ + +static void _mtk_set_gpu_boost_duration() +{ + g_gpu_boost_duartion = MTK_GPU_BOOST_DURATION; +} + +static void _mtk_decrease_gpu_boost_duration() +{ + g_gpu_boost_duartion--; +} + +static int _mtk_get_gpu_boost_duration() +{ + return g_gpu_boost_duartion; +} + +void mtk_gpu_input_boost_CB(unsigned int ui32BoostFreqID) +{ + //pr_debug("[MALI] mtk_gpu_input_boost_CB! boost to index=%d\n", ui32BoostFreqID); + + // check if input boost enabled + if(mtk_get_input_boost_enabled() == 0) + return; + + _mtk_set_gpu_boost_duration(); + + // set gpu boost id + g_gpu_boost_id = ui32BoostFreqID; + + int iCurrentFreqID; + + iCurrentFreqID = mt_gpufreq_get_cur_freq_index(); + pr_debug("[MALI] current gpu freq id=%d, touch boost to index=%d\n", iCurrentFreqID, ui32BoostFreqID); + + if(ui32BoostFreqID < iCurrentFreqID) + { + pr_debug("[MALI] boost CB set to FREQ id=%d\n", ui32BoostFreqID); + mtk_set_touch_boost_flag(ui32BoostFreqID); + } + +} + +void mtk_gpu_power_limit_CB(unsigned int ui32LimitFreqID) +{ + int iCurrentFreqID; + + pr_debug("[MALI] boost CB set to freq id=%d\n", ui32LimitFreqID); + + iCurrentFreqID = mt_gpufreq_get_cur_freq_index(); + + if(ui32LimitFreqID > iCurrentFreqID) + mt_gpufreq_target(ui32LimitFreqID); +} + +void mtk_kbase_boost_gpu_freq() +{ + mtk_gpu_input_boost_CB(0); + + return; +} + + +/* MTK custom boost. 0 is the lowest frequency index. The function is used for performance service currently.*/ +void mtk_kbase_custom_boost_gpu_freq(unsigned int ui32FreqLevel) +{ + unsigned int uiTableNum; + uiTableNum = mt_gpufreq_get_dvfs_table_num(); + + g_custom_gpu_boost_id = uiTableNum - ui32FreqLevel - 1; + + pr_debug("[MALI] mtk_kbase_custom_boost_gpu_freq() ui32FreqLevel=%d, g_custom_gpu_boost_id=%d", ui32FreqLevel, g_custom_gpu_boost_id); + + if(g_custom_gpu_boost_id < mt_gpufreq_get_cur_freq_index()) + { + pr_debug("[MALI] mtk_kbase_custom_boost_gpu_freq set gpu freq to index=%d, cuurent index=%d", g_custom_gpu_boost_id, mt_gpufreq_get_cur_freq_index()); + mt_gpufreq_target(g_custom_gpu_boost_id); + } + + return; +} + +/* MTK set boost. 0 is the lowest frequency index. The function is used for GED boost currently.*/ +void mtk_kbase_ged_bottom_gpu_freq(unsigned int ui32FreqLevel) +{ + unsigned int uiTableNum; + uiTableNum = mt_gpufreq_get_dvfs_table_num(); + + if (ui32FreqLevel >= uiTableNum) + { + ui32FreqLevel = uiTableNum - 1; + } + + g_ged_gpu_boost_id = uiTableNum - ui32FreqLevel - 1; + + pr_debug("[MALI] mtk_kbase_set_bottom_gpu_freq_fp() ui32FreqLevel=%d, g_custom_gpu_boost_id=%d (GED boost)", ui32FreqLevel, g_ged_gpu_boost_id); + + if(g_ged_gpu_boost_id < mt_gpufreq_get_cur_freq_index()) + { + pr_debug("[MALI] mtk_kbase_set_bottom_gpu_freq_fp set gpu freq to index=%d, cuurent index=%d (GED boost)", g_ged_gpu_boost_id, mt_gpufreq_get_cur_freq_index()); + mt_gpufreq_target(g_ged_gpu_boost_id); + } + + return; +} + + +unsigned int mtk_kbase_custom_get_gpu_freq_level_count() +{ + return mt_gpufreq_get_dvfs_table_num(); +} + +int _mtk_dvfs_index_clipping(int iTargetVirtualFreqID, int start, int end) +{ + if(iTargetVirtualFreqID < start) + return start; + else if(iTargetVirtualFreqID > end) + return end; + else + return iTargetVirtualFreqID; +} + + +int mtk_gpu_dvfs() +{ + int iCurrentFreqID, iTargetFreqID; + int iCurrentVirtualFreqID, iTargetVirtualFreqID; + int iCurrentGPUPlatformID; + int iCurrentGPUBoostDurationCount; + int i; + enum kbase_pm_dvfs_action action; + + action = mtk_get_dvfs_action(); + + + if(action == KBASE_PM_DVFS_NONSENSE) + { + /* if action < 0, action is not updated yet. */ + return MALI_TRUE; + } + + mtk_clear_dvfs_action(); + + // get current frequency id + iCurrentFreqID = mt_gpufreq_get_cur_freq_index(); + + // get current platform type + iCurrentGPUPlatformID = mtk_get_current_gpu_platform_id(); + + //calculate current virtual frequency ID + for(i=0 ; i 0) + { + _mtk_decrease_gpu_boost_duration(); + if(iTargetFreqID >= g_gpu_boost_id) + { + return MALI_TRUE; + } + } + + + // [MTK] mtk_custom_gpu_boost. do nothing if g_custom_gpu_boost_id is higher + int higher_boost_id; + + /* calculate higher boost frequency (e.g. lower index id) */ + if(g_custom_gpu_boost_id < g_ged_gpu_boost_id) + higher_boost_id = g_custom_gpu_boost_id; + else + higher_boost_id = g_ged_gpu_boost_id; + + if(iTargetFreqID > higher_boost_id) + { + mt_gpufreq_target(higher_boost_id); + return MALI_FALSE; + } + + if(iCurrentFreqID == iTargetFreqID) + { + //pr_debug("[MALI] (*)current freq == target freq (%d)\n", iCurrentFreqID); + return MALI_TRUE; + } + + if(mt_gpufreq_target(iTargetFreqID) == 0) + { + return MALI_TRUE; + } + else + { + return MALI_FALSE; + } + +} + + +static mali_error kbase_dispatch(struct kbase_context *kctx, void * const args, u32 args_size) +{ + struct kbase_device *kbdev; + union uk_header *ukh = args; + u32 id; + + KBASE_DEBUG_ASSERT(ukh != NULL); + + kbdev = kctx->kbdev; + id = ukh->id; + ukh->ret = MALI_ERROR_NONE; /* Be optimistic */ + + if (UKP_FUNC_ID_CHECK_VERSION == id) { + if (args_size == sizeof(struct uku_version_check_args)) { + struct uku_version_check_args *version_check = (struct uku_version_check_args *)args; + + switch (version_check->major) { +#ifdef BASE_LEGACY_UK6_SUPPORT + case 6: + /* We are backwards compatible with version 6, + * so pretend to be the old version */ + version_check->major = 6; + version_check->minor = 1; + break; +#endif /* BASE_LEGACY_UK6_SUPPORT */ +#ifdef BASE_LEGACY_UK7_SUPPORT + case 7: + /* We are backwards compatible with version 7, + * so pretend to be the old version */ + version_check->major = 7; + version_check->minor = 1; + break; +#endif /* BASE_LEGACY_UK7_SUPPORT */ + default: + /* We return our actual version regardless if it + * matches the version returned by userspace - + * userspace can bail if it can't handle this + * version */ + version_check->major = BASE_UK_VERSION_MAJOR; + version_check->minor = BASE_UK_VERSION_MINOR; + } + + ukh->ret = MALI_ERROR_NONE; + } else { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } + return MALI_ERROR_NONE; + } + + + if (!atomic_read(&kctx->setup_complete)) { + /* setup pending, try to signal that we'll do the setup */ + if (atomic_cmpxchg(&kctx->setup_in_progress, 0, 1)) { + /* setup was already in progress, err this call */ + return MALI_ERROR_FUNCTION_FAILED; + } + + /* we're the one doing setup */ + + /* is it the only call we accept? */ + if (id == KBASE_FUNC_SET_FLAGS) { + struct kbase_uk_set_flags *kbase_set_flags = (struct kbase_uk_set_flags *)args; + + if (sizeof(*kbase_set_flags) != args_size) { + /* not matching the expected call, stay stuck in setup mode */ + goto bad_size; + } + + if (MALI_ERROR_NONE != kbase_context_set_create_flags(kctx, kbase_set_flags->create_flags)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + /* bad flags, will stay stuck in setup mode */ + return MALI_ERROR_NONE; + } else { + /* we've done the setup, all OK */ + atomic_set(&kctx->setup_complete, 1); + return MALI_ERROR_NONE; + } + } else { + /* unexpected call, will stay stuck in setup mode */ + return MALI_ERROR_FUNCTION_FAILED; + } + } + + /* setup complete, perform normal operation */ + switch (id) { + case KBASE_FUNC_MEM_ALLOC: + { + struct kbase_uk_mem_alloc *mem = args; + struct kbase_va_region *reg; + + if (sizeof(*mem) != args_size) + goto bad_size; + + reg = kbase_mem_alloc(kctx, mem->va_pages, mem->commit_pages, mem->extent, &mem->flags, &mem->gpu_va, &mem->va_alignment); + if (!reg) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + case KBASE_FUNC_MEM_IMPORT: + { + struct kbase_uk_mem_import *mem_import = args; + int __user *phandle; + int handle; + + if (sizeof(*mem_import) != args_size) + goto bad_size; +#ifdef CONFIG_COMPAT + if (kctx->is_compat) + phandle = compat_ptr(mem_import->phandle.compat_value); + else +#endif + phandle = mem_import->phandle.value; + + switch (mem_import->type) { + case BASE_MEM_IMPORT_TYPE_UMP: + get_user(handle, phandle); + break; + case BASE_MEM_IMPORT_TYPE_UMM: + get_user(handle, phandle); + break; + default: + goto bad_type; + break; + } + + if (kbase_mem_import(kctx, mem_import->type, handle, &mem_import->gpu_va, &mem_import->va_pages, &mem_import->flags)) { +bad_type: + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } + break; + } + case KBASE_FUNC_MEM_ALIAS: { + struct kbase_uk_mem_alias *alias = args; + struct base_mem_aliasing_info __user *user_ai; + struct base_mem_aliasing_info *ai; + + if (sizeof(*alias) != args_size) + goto bad_size; + + if (alias->nents > 2048) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + +#ifdef CONFIG_COMPAT + if (kctx->is_compat) + user_ai = compat_ptr(alias->ai.compat_value); + else +#endif + user_ai = alias->ai.value; + + ai = vmalloc(sizeof(*ai) * alias->nents); + + if (!ai) { + ukh->ret = MALI_ERROR_OUT_OF_MEMORY; + break; + } + + if (copy_from_user(ai, user_ai, + sizeof(*ai) * alias->nents)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + goto copy_failed; + } + + alias->gpu_va = kbase_mem_alias(kctx, &alias->flags, + alias->stride, + alias->nents, ai, + &alias->va_pages); + if (!alias->gpu_va) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + goto no_alias; + } +no_alias: +copy_failed: + vfree(ai); + break; + } + case KBASE_FUNC_MEM_COMMIT: + { + struct kbase_uk_mem_commit *commit = args; + + if (sizeof(*commit) != args_size) + goto bad_size; + + if (commit->gpu_addr & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_COMMIT: commit->gpu_addr: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (kbase_mem_commit(kctx, commit->gpu_addr, + commit->pages, + (base_backing_threshold_status *)&commit->result_subcode)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + break; + } + + case KBASE_FUNC_MEM_QUERY: + { + struct kbase_uk_mem_query *query = args; + + if (sizeof(*query) != args_size) + goto bad_size; + + if (query->gpu_addr & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_QUERY: query->gpu_addr: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + if (query->query != KBASE_MEM_QUERY_COMMIT_SIZE && + query->query != KBASE_MEM_QUERY_VA_SIZE && + query->query != KBASE_MEM_QUERY_FLAGS) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_QUERY: query->query = %lld unknown", (unsigned long long)query->query); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + ukh->ret = kbase_mem_query(kctx, query->gpu_addr, query->query, &query->value); + break; + } + break; + + case KBASE_FUNC_MEM_FLAGS_CHANGE: + { + struct kbase_uk_mem_flags_change *fc = args; + + if (sizeof(*fc) != args_size) + goto bad_size; + + if ((fc->gpu_va & ~PAGE_MASK) && (fc->gpu_va >= PAGE_SIZE)) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_FLAGS_CHANGE: mem->gpu_va: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (kbase_mem_flags_change(kctx, fc->gpu_va, fc->flags, fc->mask)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + break; + } + case KBASE_FUNC_MEM_FREE: + { + struct kbase_uk_mem_free *mem = args; + + if (sizeof(*mem) != args_size) + goto bad_size; + + if ((mem->gpu_addr & ~PAGE_MASK) && (mem->gpu_addr >= PAGE_SIZE)) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_MEM_FREE: mem->gpu_addr: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (kbase_mem_free(kctx, mem->gpu_addr)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_JOB_SUBMIT: + { + struct kbase_uk_job_submit *job = args; + + if (sizeof(*job) != args_size) + goto bad_size; + +#ifdef BASE_LEGACY_UK6_SUPPORT + if (MALI_ERROR_NONE != kbase_jd_submit(kctx, job, 0)) +#else + if (MALI_ERROR_NONE != kbase_jd_submit(kctx, job)) +#endif /* BASE_LEGACY_UK6_SUPPORT */ + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + + if(mtk_get_dvfs_enabled()) + { + mtk_gpu_dvfs(); + } + + break; + } + +#ifdef BASE_LEGACY_UK6_SUPPORT + case KBASE_FUNC_JOB_SUBMIT_UK6: + { + struct kbase_uk_job_submit *job = args; + + if (sizeof(*job) != args_size) + goto bad_size; + + if (MALI_ERROR_NONE != kbase_jd_submit(kctx, job, 1)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } +#endif + + case KBASE_FUNC_SYNC: + { + struct kbase_uk_sync_now *sn = args; + + if (sizeof(*sn) != args_size) + goto bad_size; + + if (sn->sset.basep_sset.mem_handle & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_SYNC: sn->sset.basep_sset.mem_handle: passed parameter is invalid"); + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + if (MALI_ERROR_NONE != kbase_sync_now(kctx, &sn->sset)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_DISJOINT_QUERY: + { + struct kbase_uk_disjoint_query *dquery = args; + + if (sizeof(*dquery) != args_size) + goto bad_size; + + /* Get the disjointness counter value. */ + dquery->counter = kbase_disjoint_event_get(kctx->kbdev); + break; + } + + case KBASE_FUNC_POST_TERM: + { + kbase_event_close(kctx); + break; + } + + case KBASE_FUNC_HWCNT_SETUP: + { + struct kbase_uk_hwcnt_setup *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + if (MALI_ERROR_NONE != kbase_instr_hwcnt_setup(kctx, setup)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_HWCNT_DUMP: + { + /* args ignored */ + if (MALI_ERROR_NONE != kbase_instr_hwcnt_dump(kctx)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + case KBASE_FUNC_HWCNT_CLEAR: + { + /* args ignored */ + if (MALI_ERROR_NONE != kbase_instr_hwcnt_clear(kctx)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + +#ifdef BASE_LEGACY_UK7_SUPPORT + case KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE: + { + struct kbase_uk_cpuprops *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + if (MALI_ERROR_NONE != kbase_cpuprops_uk_get_props(kctx, setup)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } +#endif /* BASE_LEGACY_UK7_SUPPORT */ + + case KBASE_FUNC_GPU_PROPS_REG_DUMP: + { + struct kbase_uk_gpuprops *setup = args; + + if (sizeof(*setup) != args_size) + goto bad_size; + + if (MALI_ERROR_NONE != kbase_gpuprops_uk_get_props(kctx, setup)) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + case KBASE_FUNC_FIND_CPU_OFFSET: + { + struct kbase_uk_find_cpu_offset *find = args; + + if (sizeof(*find) != args_size) + goto bad_size; + + if (find->gpu_addr & ~PAGE_MASK) { + dev_warn(kbdev->dev, "kbase_dispatch case KBASE_FUNC_FIND_CPU_OFFSET: find->gpu_addr: passed parameter is invalid"); + goto out_bad; + } + + if (find->size > SIZE_MAX || find->cpu_addr > ULONG_MAX) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } else { + mali_error err; + + err = kbasep_find_enclosing_cpu_mapping_offset( + kctx, + find->gpu_addr, + (uintptr_t) find->cpu_addr, + (size_t) find->size, + &find->offset); + + if (err != MALI_ERROR_NONE) + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + } + break; + } + case KBASE_FUNC_GET_VERSION: + { + struct kbase_uk_get_ddk_version *get_version = (struct kbase_uk_get_ddk_version *)args; + + if (sizeof(*get_version) != args_size) + goto bad_size; + + /* version buffer size check is made in compile time assert */ + memcpy(get_version->version_buffer, KERNEL_SIDE_DDK_VERSION_STRING, sizeof(KERNEL_SIDE_DDK_VERSION_STRING)); + get_version->version_string_size = sizeof(KERNEL_SIDE_DDK_VERSION_STRING); + break; + } + + case KBASE_FUNC_STREAM_CREATE: + { +#ifdef CONFIG_SYNC + struct kbase_uk_stream_create *screate = (struct kbase_uk_stream_create *)args; + + if (sizeof(*screate) != args_size) + goto bad_size; + + if (strnlen(screate->name, sizeof(screate->name)) >= sizeof(screate->name)) { + /* not NULL terminated */ + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + break; + } + + ukh->ret = kbase_stream_create(screate->name, &screate->fd); +#else /* CONFIG_SYNC */ + ukh->ret = MALI_ERROR_FUNCTION_FAILED; +#endif /* CONFIG_SYNC */ + break; + } + case KBASE_FUNC_FENCE_VALIDATE: + { +#ifdef CONFIG_SYNC + struct kbase_uk_fence_validate *fence_validate = (struct kbase_uk_fence_validate *)args; + + if (sizeof(*fence_validate) != args_size) + goto bad_size; + + ukh->ret = kbase_fence_validate(fence_validate->fd); +#endif /* CONFIG_SYNC */ + break; + } + + case KBASE_FUNC_EXT_BUFFER_LOCK: + { +#ifdef CONFIG_KDS + ukh->ret = kbase_external_buffer_lock(kctx, (struct kbase_uk_ext_buff_kds_data *)args, args_size); +#endif /* CONFIG_KDS */ + break; + } + + case KBASE_FUNC_SET_TEST_DATA: + { +#if MALI_UNIT_TEST + struct kbase_uk_set_test_data *set_data = args; + + shared_kernel_test_data = set_data->test_data; + shared_kernel_test_data.kctx.value = (void __user *)kctx; + shared_kernel_test_data.mm.value = (void __user *)current->mm; + ukh->ret = MALI_ERROR_NONE; +#endif /* MALI_UNIT_TEST */ + break; + } + + case KBASE_FUNC_INJECT_ERROR: + { +#ifdef CONFIG_MALI_ERROR_INJECT + unsigned long flags; + struct kbase_error_params params = ((struct kbase_uk_error_params *)args)->params; + + /*mutex lock */ + spin_lock_irqsave(&kbdev->reg_op_lock, flags); + ukh->ret = job_atom_inject_error(¶ms); + spin_unlock_irqrestore(&kbdev->reg_op_lock, flags); + /*mutex unlock */ +#endif /* CONFIG_MALI_ERROR_INJECT */ + break; + } + + case KBASE_FUNC_MODEL_CONTROL: + { +#ifdef CONFIG_MALI_NO_MALI + unsigned long flags; + struct kbase_model_control_params params = + ((struct kbase_uk_model_control_params *)args)->params; + + /*mutex lock */ + spin_lock_irqsave(&kbdev->reg_op_lock, flags); + ukh->ret = midg_model_control(kbdev->model, ¶ms); + spin_unlock_irqrestore(&kbdev->reg_op_lock, flags); + /*mutex unlock */ +#endif /* CONFIG_MALI_NO_MALI */ + break; + } + + case KBASE_FUNC_KEEP_GPU_POWERED: + { + struct kbase_uk_keep_gpu_powered *kgp = + (struct kbase_uk_keep_gpu_powered *)args; + + /* A suspend won't happen here, because we're in a syscall from a + * userspace thread. + * + * Nevertheless, we'd get the wrong pm_context_active/idle counting + * here if a suspend did happen, so let's assert it won't: */ + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + + if (kgp->enabled && !kctx->keep_gpu_powered) { + kbase_pm_context_active(kbdev); + atomic_inc(&kbdev->keep_gpu_powered_count); + kctx->keep_gpu_powered = MALI_TRUE; + } else if (!kgp->enabled && kctx->keep_gpu_powered) { + atomic_dec(&kbdev->keep_gpu_powered_count); + kbase_pm_context_idle(kbdev); + kctx->keep_gpu_powered = MALI_FALSE; + } + + break; + } + + case KBASE_FUNC_GET_PROFILING_CONTROLS: + { + struct kbase_uk_profiling_controls *controls = + (struct kbase_uk_profiling_controls *)args; + u32 i; + + if (sizeof(*controls) != args_size) + goto bad_size; + + for (i = FBDUMP_CONTROL_MIN; i < FBDUMP_CONTROL_MAX; i++) + controls->profiling_controls[i] = kbase_get_profiling_control(kbdev, i); + + break; + } + + /* used only for testing purposes; these controls are to be set by gator through gator API */ + case KBASE_FUNC_SET_PROFILING_CONTROLS: + { + struct kbase_uk_profiling_controls *controls = + (struct kbase_uk_profiling_controls *)args; + u32 i; + + if (sizeof(*controls) != args_size) + goto bad_size; + + for (i = FBDUMP_CONTROL_MIN; i < FBDUMP_CONTROL_MAX; i++) + _mali_profiling_control(i, controls->profiling_controls[i]); + + break; + } + + case KBASE_FUNC_DEBUGFS_MEM_PROFILE_ADD: + { + struct kbase_uk_debugfs_mem_profile_add *add_data = + (struct kbase_uk_debugfs_mem_profile_add *)args; + char *buf; + char __user *user_buf; + + if (sizeof(*add_data) != args_size) + goto bad_size; + + if (add_data->len > KBASE_MEM_PROFILE_MAX_BUF_SIZE) { + dev_err(kbdev->dev, "buffer too big"); + goto out_bad; + } + +#ifdef CONFIG_COMPAT + if (kctx->is_compat) + user_buf = compat_ptr(add_data->buf.compat_value); + else +#endif + user_buf = add_data->buf.value; + + buf = kmalloc(add_data->len, GFP_KERNEL); + if (!buf) + goto out_bad; + + if (0 != copy_from_user(buf, user_buf, add_data->len)) { + ukh->ret = MALI_ERROR_FUNCTION_FAILED; + kfree(buf); + goto out_bad; + } + kbasep_mem_profile_debugfs_insert(kctx, buf, + add_data->len); + + break; + } + + default: + dev_err(kbdev->dev, "unknown ioctl %u", id); + goto out_bad; + } + + return MALI_ERROR_NONE; + + bad_size: + dev_err(kbdev->dev, "Wrong syscall size (%d) for %08x\n", args_size, id); + out_bad: + return MALI_ERROR_FUNCTION_FAILED; +} + +static struct kbase_device *to_kbase_device(struct device *dev) +{ + return dev_get_drvdata(dev); +} + +/* + * API to acquire device list semaphore and + * return pointer to the device list head + */ +const struct list_head *kbase_dev_list_get(void) +{ + down(&kbase_dev_list_lock); + return &kbase_dev_list; +} + +/* API to release the device list semaphore */ +void kbase_dev_list_put(const struct list_head *dev_list) +{ + up(&kbase_dev_list_lock); +} + +/* Find a particular kbase device (as specified by minor number), or find the "first" device if -1 is specified */ +struct kbase_device *kbase_find_device(int minor) +{ + struct kbase_device *kbdev = NULL; + struct list_head *entry; + + down(&kbase_dev_list_lock); + list_for_each(entry, &kbase_dev_list) { + struct kbase_device *tmp; + + tmp = list_entry(entry, struct kbase_device, entry); + if (tmp->mdev.minor == minor || minor == -1) { + kbdev = tmp; + get_device(kbdev->dev); + break; + } + } + up(&kbase_dev_list_lock); + + return kbdev; +} +EXPORT_SYMBOL(kbase_find_device); + +void kbase_release_device(struct kbase_device *kbdev) +{ + put_device(kbdev->dev); +} +EXPORT_SYMBOL(kbase_release_device); + +static int kbase_open(struct inode *inode, struct file *filp) +{ + struct kbase_device *kbdev = NULL; + struct kbase_context *kctx; + int ret = 0; + + kbdev = kbase_find_device(iminor(inode)); + + if (!kbdev) + return -ENODEV; + + kctx = kbase_create_context(kbdev, is_compat_task()); + if (!kctx) { + ret = -ENOMEM; + goto out; + } + + init_waitqueue_head(&kctx->event_queue); + filp->private_data = kctx; + + dev_dbg(kbdev->dev, "created base context\n"); + + { + struct kbasep_kctx_list_element *element; + + element = kzalloc(sizeof(*element), GFP_KERNEL); + if (element) { + mutex_lock(&kbdev->kctx_list_lock); + element->kctx = kctx; + list_add(&element->link, &kbdev->kctx_list); + mutex_unlock(&kbdev->kctx_list_lock); + } else { + /* we don't treat this as a fail - just warn about it */ + dev_warn(kbdev->dev, "couldn't add kctx to kctx_list\n"); + } + } + return 0; + + out: + kbase_release_device(kbdev); + return ret; +} + +static int kbase_release(struct inode *inode, struct file *filp) +{ + struct kbase_context *kctx = filp->private_data; + struct kbase_device *kbdev = kctx->kbdev; + struct kbasep_kctx_list_element *element, *tmp; + mali_bool found_element = MALI_FALSE; + + mutex_lock(&kbdev->kctx_list_lock); + list_for_each_entry_safe(element, tmp, &kbdev->kctx_list, link) { + if (element->kctx == kctx) { + list_del(&element->link); + kfree(element); + found_element = MALI_TRUE; + } + } + mutex_unlock(&kbdev->kctx_list_lock); + if (!found_element) + dev_warn(kbdev->dev, "kctx not in kctx_list\n"); + + filp->private_data = NULL; + kbase_destroy_context(kctx); + + dev_dbg(kbdev->dev, "deleted base context\n"); + kbase_release_device(kbdev); + return 0; +} + +#define CALL_MAX_SIZE 536 + +static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + u64 msg[(CALL_MAX_SIZE + 7) >> 3] = { 0xdeadbeefdeadbeefull }; /* alignment fixup */ + u32 size = _IOC_SIZE(cmd); + struct kbase_context *kctx = filp->private_data; + + if (size > CALL_MAX_SIZE) + return -ENOTTY; + + if (0 != copy_from_user(&msg, (void __user *)arg, size)) { + dev_err(kctx->kbdev->dev, "failed to copy ioctl argument into kernel space\n"); + return -EFAULT; + } + + if (MALI_ERROR_NONE != kbase_dispatch(kctx, &msg, size)) + return -EFAULT; + + if (0 != copy_to_user((void __user *)arg, &msg, size)) { + dev_err(kctx->kbdev->dev, "failed to copy results of UK call back to user space\n"); + return -EFAULT; + } + return 0; +} + +static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + struct kbase_context *kctx = filp->private_data; + struct base_jd_event_v2 uevent; + int out_count = 0; + + if (count < sizeof(uevent)) + return -ENOBUFS; + + do { + while (kbase_event_dequeue(kctx, &uevent)) { + if (out_count > 0) + goto out; + + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + + if (wait_event_interruptible(kctx->event_queue, kbase_event_pending(kctx))) + return -ERESTARTSYS; + } + if (uevent.event_code == BASE_JD_EVENT_DRV_TERMINATED) { + if (out_count == 0) + return -EPIPE; + goto out; + } + + if (copy_to_user(buf, &uevent, sizeof(uevent))) + return -EFAULT; + + buf += sizeof(uevent); + out_count++; + count -= sizeof(uevent); + } while (count >= sizeof(uevent)); + + out: + return out_count * sizeof(uevent); +} + +static unsigned int kbase_poll(struct file *filp, poll_table *wait) +{ + struct kbase_context *kctx = filp->private_data; + + poll_wait(filp, &kctx->event_queue, wait); + if (kbase_event_pending(kctx)) + return POLLIN | POLLRDNORM; + + return 0; +} + +void kbase_event_wakeup(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + + wake_up_interruptible(&kctx->event_queue); +} + +KBASE_EXPORT_TEST_API(kbase_event_wakeup) + +static int kbase_check_flags(int flags) +{ + /* Enforce that the driver keeps the O_CLOEXEC flag so that execve() always + * closes the file descriptor in a child process. + */ + if (0 == (flags & O_CLOEXEC)) + return -EINVAL; + + return 0; +} + +static unsigned long kbase_get_unmapped_area(struct file *filp, + const unsigned long addr, const unsigned long len, + const unsigned long pgoff, const unsigned long flags) +{ +#ifdef CONFIG_64BIT + /* based on get_unmapped_area, but simplified slightly due to that some + * values are known in advance */ + struct kbase_context *kctx = filp->private_data; + + if (!kctx->is_compat && !addr && + kbase_hw_has_feature(kctx->kbdev, BASE_HW_FEATURE_33BIT_VA)) { + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long low_limit, high_limit, gap_start, gap_end; + + /* Hardware has smaller VA than userspace, ensure the page + * comes from a VA which can be used on the GPU */ + + gap_end = (1UL<<33); + if (gap_end < len) + return -ENOMEM; + high_limit = gap_end - len; + low_limit = PAGE_SIZE + len; + + gap_start = mm->highest_vm_end; + if (gap_start <= high_limit) + goto found_highest; + + if (RB_EMPTY_ROOT(&mm->mm_rb)) + return -ENOMEM; + vma = rb_entry(mm->mm_rb.rb_node, struct vm_area_struct, vm_rb); + if (vma->rb_subtree_gap < len) + return -ENOMEM; + + while (true) { + gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; + if (gap_start <= high_limit && vma->vm_rb.rb_right) { + struct vm_area_struct *right = + rb_entry(vma->vm_rb.rb_right, + struct vm_area_struct, vm_rb); + if (right->rb_subtree_gap >= len) { + vma = right; + continue; + } + } +check_current: + gap_end = vma->vm_start; + if (gap_end < low_limit) + return -ENOMEM; + if (gap_start <= high_limit && + gap_end - gap_start >= len) + goto found; + + if (vma->vm_rb.rb_left) { + struct vm_area_struct *left = + rb_entry(vma->vm_rb.rb_left, + struct vm_area_struct, vm_rb); + + if (left->rb_subtree_gap >= len) { + vma = left; + continue; + } + } + while (true) { + struct rb_node *prev = &vma->vm_rb; + + if (!rb_parent(prev)) + return -ENOMEM; + vma = rb_entry(rb_parent(prev), + struct vm_area_struct, vm_rb); + if (prev == vma->vm_rb.rb_right) { + gap_start = vma->vm_prev ? + vma->vm_prev->vm_end : 0; + goto check_current; + } + } + } + +found: + if (gap_end > (1UL<<33)) + gap_end = (1UL<<33); + +found_highest: + gap_end -= len; + + VM_BUG_ON(gap_end < PAGE_SIZE); + VM_BUG_ON(gap_end < gap_start); + return gap_end; + } +#endif + /* No special requirements - fallback to the default version */ + return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags); +} + +static const struct file_operations kbase_fops = { + .owner = THIS_MODULE, + .open = kbase_open, + .release = kbase_release, + .read = kbase_read, + .poll = kbase_poll, + .unlocked_ioctl = kbase_ioctl, + .compat_ioctl = kbase_ioctl, + .mmap = kbase_mmap, + .check_flags = kbase_check_flags, + .get_unmapped_area = kbase_get_unmapped_area, +}; + +#ifndef CONFIG_MALI_NO_MALI +void kbase_os_reg_write(struct kbase_device *kbdev, u16 offset, u32 value) +{ + writel(value, kbdev->reg + offset); +} + +u32 kbase_os_reg_read(struct kbase_device *kbdev, u16 offset) +{ + return readl(kbdev->reg + offset); +} +#endif + +#ifndef CONFIG_MALI_NO_MALI + +static void *kbase_tag(void *ptr, u32 tag) +{ + return (void *)(((uintptr_t) ptr) | tag); +} + +static void *kbase_untag(void *ptr) +{ + return (void *)(((uintptr_t) ptr) & ~3); +} + + + + +static irqreturn_t kbase_job_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.driver_ready_for_irqs) + dev_warn(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_job_done(kbdev, val); + + return IRQ_HANDLED; +} + +KBASE_EXPORT_TEST_API(kbase_job_irq_handler); + +static irqreturn_t kbase_mmu_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.driver_ready_for_irqs) + dev_warn(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_mmu_interrupt(kbdev, val); + + return IRQ_HANDLED; +} + +static irqreturn_t kbase_gpu_irq_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_STATUS), NULL); + +#ifdef CONFIG_MALI_DEBUG + if (!kbdev->pm.driver_ready_for_irqs) + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x before driver is ready\n", + __func__, irq, val); +#endif /* CONFIG_MALI_DEBUG */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbase_gpu_interrupt(kbdev, val); + + return IRQ_HANDLED; +} +static irq_handler_t kbase_handler_table[] = { + [JOB_IRQ_TAG] = kbase_job_irq_handler, + [MMU_IRQ_TAG] = kbase_mmu_irq_handler, + [GPU_IRQ_TAG] = kbase_gpu_irq_handler, +}; + + +#ifdef CONFIG_MALI_DEBUG +#define JOB_IRQ_HANDLER JOB_IRQ_TAG +#define MMU_IRQ_HANDLER MMU_IRQ_TAG +#define GPU_IRQ_HANDLER GPU_IRQ_TAG + +/** + * @brief Registers given interrupt handler for requested interrupt type + * Case irq handler is not specified default handler shall be registered + * + * @param[in] kbdev - Device for which the handler is to be registered + * @param[in] custom_handler - Handler to be registered + * @param[in] irq_type - Interrupt type + * @return MALI_ERROR_NONE case success, MALI_ERROR_FUNCTION_FAILED otherwise + */ +static mali_error kbase_set_custom_irq_handler(struct kbase_device *kbdev, irq_handler_t custom_handler, int irq_type) +{ + mali_error result = MALI_ERROR_NONE; + irq_handler_t requested_irq_handler = NULL; + + KBASE_DEBUG_ASSERT((JOB_IRQ_HANDLER <= irq_type) && (GPU_IRQ_HANDLER >= irq_type)); + + /* Release previous handler */ + if (kbdev->irqs[irq_type].irq) + free_irq(kbdev->irqs[irq_type].irq, kbase_tag(kbdev, irq_type)); + + requested_irq_handler = (NULL != custom_handler) ? custom_handler : kbase_handler_table[irq_type]; + + if (0 != request_irq(kbdev->irqs[irq_type].irq, + requested_irq_handler, + kbdev->irqs[irq_type].flags | IRQF_SHARED, + dev_name(kbdev->dev), kbase_tag(kbdev, irq_type))) { + result = MALI_ERROR_FUNCTION_FAILED; + dev_err(kbdev->dev, "Can't request interrupt %d (index %d)\n", kbdev->irqs[irq_type].irq, irq_type); +#ifdef CONFIG_SPARSE_IRQ + dev_err(kbdev->dev, "You have CONFIG_SPARSE_IRQ support enabled - is the interrupt number correct for this configuration?\n"); +#endif /* CONFIG_SPARSE_IRQ */ + } + + return result; +} + +KBASE_EXPORT_TEST_API(kbase_set_custom_irq_handler) + +/* test correct interrupt assigment and reception by cpu */ +struct kbasep_irq_test { + struct hrtimer timer; + wait_queue_head_t wait; + int triggered; + u32 timeout; +}; + +static struct kbasep_irq_test kbasep_irq_test_data; + +#define IRQ_TEST_TIMEOUT 500 + +static irqreturn_t kbase_job_irq_test_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_STATUS), NULL); + + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbasep_irq_test_data.triggered = 1; + wake_up(&kbasep_irq_test_data.wait); + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), val, NULL); + + return IRQ_HANDLED; +} + +static irqreturn_t kbase_mmu_irq_test_handler(int irq, void *data) +{ + unsigned long flags; + struct kbase_device *kbdev = kbase_untag(data); + u32 val; + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + + if (!kbdev->pm.gpu_powered) { + /* GPU is turned off - IRQ is not for us */ + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + return IRQ_NONE; + } + + val = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_STATUS), NULL); + + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (!val) + return IRQ_NONE; + + dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); + + kbasep_irq_test_data.triggered = 1; + wake_up(&kbasep_irq_test_data.wait); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), val, NULL); + + return IRQ_HANDLED; +} + +static enum hrtimer_restart kbasep_test_interrupt_timeout(struct hrtimer *timer) +{ + struct kbasep_irq_test *test_data = container_of(timer, struct kbasep_irq_test, timer); + + test_data->timeout = 1; + test_data->triggered = 1; + wake_up(&test_data->wait); + return HRTIMER_NORESTART; +} + +static mali_error kbasep_common_test_interrupt(struct kbase_device * const kbdev, u32 tag) +{ + mali_error err = MALI_ERROR_NONE; + irq_handler_t test_handler; + + u32 old_mask_val; + u16 mask_offset; + u16 rawstat_offset; + + switch (tag) { + case JOB_IRQ_TAG: + test_handler = kbase_job_irq_test_handler; + rawstat_offset = JOB_CONTROL_REG(JOB_IRQ_RAWSTAT); + mask_offset = JOB_CONTROL_REG(JOB_IRQ_MASK); + break; + case MMU_IRQ_TAG: + test_handler = kbase_mmu_irq_test_handler; + rawstat_offset = MMU_REG(MMU_IRQ_RAWSTAT); + mask_offset = MMU_REG(MMU_IRQ_MASK); + break; + case GPU_IRQ_TAG: + /* already tested by pm_driver - bail out */ + default: + return MALI_ERROR_NONE; + } + + /* store old mask */ + old_mask_val = kbase_reg_read(kbdev, mask_offset, NULL); + /* mask interrupts */ + kbase_reg_write(kbdev, mask_offset, 0x0, NULL); + + if (kbdev->irqs[tag].irq) { + /* release original handler and install test handler */ + if (MALI_ERROR_NONE != kbase_set_custom_irq_handler(kbdev, test_handler, tag)) { + err = MALI_ERROR_FUNCTION_FAILED; + } else { + kbasep_irq_test_data.timeout = 0; + hrtimer_init(&kbasep_irq_test_data.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbasep_irq_test_data.timer.function = kbasep_test_interrupt_timeout; + + /* trigger interrupt */ + kbase_reg_write(kbdev, mask_offset, 0x1, NULL); + kbase_reg_write(kbdev, rawstat_offset, 0x1, NULL); + + hrtimer_start(&kbasep_irq_test_data.timer, HR_TIMER_DELAY_MSEC(IRQ_TEST_TIMEOUT), HRTIMER_MODE_REL); + + wait_event(kbasep_irq_test_data.wait, kbasep_irq_test_data.triggered != 0); + + if (kbasep_irq_test_data.timeout != 0) { + dev_err(kbdev->dev, "Interrupt %d (index %d) didn't reach CPU.\n", kbdev->irqs[tag].irq, tag); + err = MALI_ERROR_FUNCTION_FAILED; + } else { + dev_dbg(kbdev->dev, "Interrupt %d (index %d) reached CPU.\n", kbdev->irqs[tag].irq, tag); + } + + hrtimer_cancel(&kbasep_irq_test_data.timer); + kbasep_irq_test_data.triggered = 0; + + /* mask interrupts */ + kbase_reg_write(kbdev, mask_offset, 0x0, NULL); + + /* release test handler */ + free_irq(kbdev->irqs[tag].irq, kbase_tag(kbdev, tag)); + } + + /* restore original interrupt */ + if (request_irq(kbdev->irqs[tag].irq, kbase_handler_table[tag], kbdev->irqs[tag].flags | IRQF_SHARED, dev_name(kbdev->dev), kbase_tag(kbdev, tag))) { + dev_err(kbdev->dev, "Can't restore original interrupt %d (index %d)\n", kbdev->irqs[tag].irq, tag); + err = MALI_ERROR_FUNCTION_FAILED; + } + } + /* restore old mask */ + kbase_reg_write(kbdev, mask_offset, old_mask_val, NULL); + + return err; +} + +static mali_error kbasep_common_test_interrupt_handlers(struct kbase_device * const kbdev) +{ + mali_error err; + + init_waitqueue_head(&kbasep_irq_test_data.wait); + kbasep_irq_test_data.triggered = 0; + + /* A suspend won't happen during startup/insmod */ + kbase_pm_context_active(kbdev); + + err = kbasep_common_test_interrupt(kbdev, JOB_IRQ_TAG); + if (MALI_ERROR_NONE != err) { + dev_err(kbdev->dev, "Interrupt JOB_IRQ didn't reach CPU. Check interrupt assignments.\n"); + goto out; + } + + err = kbasep_common_test_interrupt(kbdev, MMU_IRQ_TAG); + if (MALI_ERROR_NONE != err) { + dev_err(kbdev->dev, "Interrupt MMU_IRQ didn't reach CPU. Check interrupt assignments.\n"); + goto out; + } + + dev_dbg(kbdev->dev, "Interrupts are correctly assigned.\n"); + + out: + kbase_pm_context_idle(kbdev); + + return err; +} +#endif /* CONFIG_MALI_DEBUG */ + +static int kbase_install_interrupts(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + int err; + u32 i; + + for (i = 0; i < nr; i++) { + err = request_irq(kbdev->irqs[i].irq, kbase_handler_table[i], kbdev->irqs[i].flags | IRQF_SHARED, dev_name(kbdev->dev), kbase_tag(kbdev, i)); + if (err) { + dev_err(kbdev->dev, "Can't request interrupt %d (index %d)\n", kbdev->irqs[i].irq, i); +#ifdef CONFIG_SPARSE_IRQ + dev_err(kbdev->dev, "You have CONFIG_SPARSE_IRQ support enabled - is the interrupt number correct for this configuration?\n"); +#endif /* CONFIG_SPARSE_IRQ */ + goto release; + } + } + + return 0; + + release: + while (i-- > 0) + free_irq(kbdev->irqs[i].irq, kbase_tag(kbdev, i)); + + return err; +} + +static void kbase_release_interrupts(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + u32 i; + + for (i = 0; i < nr; i++) { + if (kbdev->irqs[i].irq) + free_irq(kbdev->irqs[i].irq, kbase_tag(kbdev, i)); + } +} + +void kbase_synchronize_irqs(struct kbase_device *kbdev) +{ + u32 nr = ARRAY_SIZE(kbase_handler_table); + u32 i; + + for (i = 0; i < nr; i++) { + if (kbdev->irqs[i].irq) + synchronize_irq(kbdev->irqs[i].irq); + } +} +#endif /* CONFIG_MALI_NO_MALI */ + +#if KBASE_PM_EN +/** Show callback for the @c power_policy sysfs file. + * + * This function is called to get the contents of the @c power_policy sysfs + * file. This is a list of the available policies with the currently active one + * surrounded by square brackets. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_policy(struct device *dev, struct device_attribute *attr, char *const buf) +{ + struct kbase_device *kbdev; + const struct kbase_pm_policy *current_policy; + const struct kbase_pm_policy *const *policy_list; + int policy_count; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + current_policy = kbase_pm_get_policy(kbdev); + + policy_count = kbase_pm_list_policies(&policy_list); + + for (i = 0; i < policy_count && ret < PAGE_SIZE; i++) { + if (policy_list[i] == current_policy) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s] ", policy_list[i]->name); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ", policy_list[i]->name); + } + + if (ret < PAGE_SIZE - 1) { + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); + } else { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** Store callback for the @c power_policy sysfs file. + * + * This function is called when the @c power_policy sysfs file is written to. + * It matches the requested policy against the available policies and if a + * matching policy is found calls @ref kbase_pm_set_policy to change the + * policy. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_policy(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + const struct kbase_pm_policy *new_policy = NULL; + const struct kbase_pm_policy *const *policy_list; + int policy_count; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + policy_count = kbase_pm_list_policies(&policy_list); + + for (i = 0; i < policy_count; i++) { + if (sysfs_streq(policy_list[i]->name, buf)) { + new_policy = policy_list[i]; + break; + } + } + + if (!new_policy) { + dev_err(dev, "power_policy: policy not found\n"); + return -EINVAL; + } + + kbase_pm_set_policy(kbdev, new_policy); + + return count; +} + +/** The sysfs file @c power_policy. + * + * This is used for obtaining information about the available policies, + * determining which policy is currently active, and changing the active + * policy. + */ +static DEVICE_ATTR(power_policy, S_IRUGO | S_IWUSR, show_policy, set_policy); + +/** Show callback for the @c core_availability_policy sysfs file. + * + * This function is called to get the contents of the @c core_availability_policy + * sysfs file. This is a list of the available policies with the currently + * active one surrounded by square brackets. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_ca_policy(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + const struct kbase_pm_ca_policy *current_policy; + const struct kbase_pm_ca_policy *const *policy_list; + int policy_count; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + current_policy = kbase_pm_ca_get_policy(kbdev); + + policy_count = kbase_pm_ca_list_policies(&policy_list); + + for (i = 0; i < policy_count && ret < PAGE_SIZE; i++) { + if (policy_list[i] == current_policy) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s] ", policy_list[i]->name); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ", policy_list[i]->name); + } + + if (ret < PAGE_SIZE - 1) { + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); + } else { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** Store callback for the @c core_availability_policy sysfs file. + * + * This function is called when the @c core_availability_policy sysfs file is + * written to. It matches the requested policy against the available policies + * and if a matching policy is found calls @ref kbase_pm_set_policy to change + * the policy. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_ca_policy(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + const struct kbase_pm_ca_policy *new_policy = NULL; + const struct kbase_pm_ca_policy *const *policy_list; + int policy_count; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + policy_count = kbase_pm_ca_list_policies(&policy_list); + + for (i = 0; i < policy_count; i++) { + if (sysfs_streq(policy_list[i]->name, buf)) { + new_policy = policy_list[i]; + break; + } + } + + if (!new_policy) { + dev_err(dev, "core_availability_policy: policy not found\n"); + return -EINVAL; + } + + kbase_pm_ca_set_policy(kbdev, new_policy); + + return count; +} + +/** The sysfs file @c core_availability_policy + * + * This is used for obtaining information about the available policies, + * determining which policy is currently active, and changing the active + * policy. + */ +static DEVICE_ATTR(core_availability_policy, S_IRUGO | S_IWUSR, show_ca_policy, set_ca_policy); + +/** Show callback for the @c core_mask sysfs file. + * + * This function is called to get the contents of the @c core_mask sysfs + * file. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_core_mask(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "Current core mask : 0x%llX\n", kbdev->pm.debug_core_mask); + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "Available core mask : 0x%llX\n", kbdev->shader_present_bitmap); + + return ret; +} + +/** Store callback for the @c core_mask sysfs file. + * + * This function is called when the @c core_mask sysfs file is written to. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_core_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + u64 new_core_mask; + int rc; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + rc = kstrtoull(buf, 16, &new_core_mask); + if (rc) + return rc; + + if ((new_core_mask & kbdev->shader_present_bitmap) != new_core_mask || + !(new_core_mask & kbdev->gpu_props.props.coherency_info.group[0].core_mask)) { + dev_err(dev, "power_policy: invalid core specification\n"); + return -EINVAL; + } + + if (kbdev->pm.debug_core_mask != new_core_mask) { + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + kbdev->pm.debug_core_mask = new_core_mask; + kbase_pm_update_cores_state_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + } + + return count; +} + +/** The sysfs file @c core_mask. + * + * This is used to restrict shader core availability for debugging purposes. + * Reading it will show the current core mask and the mask of cores available. + * Writing to it will set the current core mask. + */ +static DEVICE_ATTR(core_mask, S_IRUGO | S_IWUSR, show_core_mask, set_core_mask); +#endif /* KBASE_PM_EN */ + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS +/* Import the external affinity mask variables */ +extern u64 mali_js0_affinity_mask; +extern u64 mali_js1_affinity_mask; +extern u64 mali_js2_affinity_mask; + +/** + * Structure containing a single shader affinity split configuration. + */ +struct sc_split_config { + char const *tag; + char const *human_readable; + u64 js0_mask; + u64 js1_mask; + u64 js2_mask; +}; + +/** + * Array of available shader affinity split configurations. + */ +static struct sc_split_config const sc_split_configs[] = { + /* All must be the first config (default). */ + { + "all", "All cores", + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL + }, + { + "mp1", "MP1 shader core", + 0x1, 0x1, 0x1 + }, + { + "mp2", "MP2 shader core", + 0x3, 0x3, 0x3 + }, + { + "mp4", "MP4 shader core", + 0xF, 0xF, 0xF + }, + { + "mp1_vf", "MP1 vertex + MP1 fragment shader core", + 0x2, 0x1, 0xFFFFFFFFFFFFFFFFULL + }, + { + "mp2_vf", "MP2 vertex + MP2 fragment shader core", + 0xA, 0x5, 0xFFFFFFFFFFFFFFFFULL + }, + /* This must be the last config. */ + { + NULL, NULL, + 0x0, 0x0, 0x0 + }, +}; + +/* Pointer to the currently active shader split configuration. */ +static struct sc_split_config const *current_sc_split_config = &sc_split_configs[0]; + +/** Show callback for the @c sc_split sysfs file + * + * Returns the current shader core affinity policy. + */ +static ssize_t show_split(struct device *dev, struct device_attribute *attr, char * const buf) +{ + ssize_t ret; + /* We know we are given a buffer which is PAGE_SIZE long. Our strings are all guaranteed + * to be shorter than that at this time so no length check needed. */ + ret = scnprintf(buf, PAGE_SIZE, "Current sc_split: '%s'\n", current_sc_split_config->tag); + return ret; +} + +/** Store callback for the @c sc_split sysfs file. + * + * This function is called when the @c sc_split sysfs file is written to + * It modifies the system shader core affinity configuration to allow + * system profiling with different hardware configurations. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_split(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct sc_split_config const *config = &sc_split_configs[0]; + + /* Try to match: loop until we hit the last "NULL" entry */ + while (config->tag) { + if (sysfs_streq(config->tag, buf)) { + current_sc_split_config = config; + mali_js0_affinity_mask = config->js0_mask; + mali_js1_affinity_mask = config->js1_mask; + mali_js2_affinity_mask = config->js2_mask; + dev_dbg(dev, "Setting sc_split: '%s'\n", config->tag); + return count; + } + config++; + } + + /* No match found in config list */ + dev_err(dev, "sc_split: invalid value\n"); + dev_err(dev, " Possible settings: mp[1|2|4], mp[1|2]_vf\n"); + return -ENOENT; +} + +/** The sysfs file @c sc_split + * + * This is used for configuring/querying the current shader core work affinity + * configuration. + */ +static DEVICE_ATTR(sc_split, S_IRUGO|S_IWUSR, show_split, set_split); +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ + + +#if !MALI_CUSTOMER_RELEASE +/** Store callback for the @c js_timeouts sysfs file. + * + * This function is called to get the contents of the @c js_timeouts sysfs + * file. This file contains five values separated by whitespace. The values + * are basically the same as KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, BASE_CONFIG_ATTR_JS_RESET_TICKS_NSS + * configuration values (in that order), with the difference that the js_timeout + * valus are expressed in MILLISECONDS. + * + * The js_timeouts sysfile file allows the current values in + * use by the job scheduler to get override. Note that a value needs to + * be other than 0 for it to override the current job scheduler value. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_js_timeouts(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int items; + unsigned long js_soft_stop_ms; + unsigned long js_soft_stop_ms_cl; + unsigned long js_hard_stop_ms_ss; + unsigned long js_hard_stop_ms_cl; + unsigned long js_hard_stop_ms_nss; + unsigned long js_reset_ms_ss; + unsigned long js_reset_ms_cl; + unsigned long js_reset_ms_nss; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + items = sscanf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu", + &js_soft_stop_ms, &js_soft_stop_ms_cl, + &js_hard_stop_ms_ss, &js_hard_stop_ms_cl, + &js_hard_stop_ms_nss, &js_reset_ms_ss, + &js_reset_ms_cl, &js_reset_ms_nss); + + if (items == 8) { + u64 ticks; + + ticks = js_soft_stop_ms * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_soft_stop_ticks = ticks; + + ticks = js_soft_stop_ms_cl * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_soft_stop_ticks_cl = ticks; + + ticks = js_hard_stop_ms_ss * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_hard_stop_ticks_ss = ticks; + + ticks = js_hard_stop_ms_cl * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_hard_stop_ticks_cl = ticks; + + ticks = js_hard_stop_ms_nss * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_hard_stop_ticks_nss = ticks; + + ticks = js_reset_ms_ss * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_reset_ticks_ss = ticks; + + ticks = js_reset_ms_cl * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_reset_ticks_cl = ticks; + + ticks = js_reset_ms_nss * 1000000ULL; + do_div(ticks, kbdev->js_data.scheduling_tick_ns); + kbdev->js_reset_ticks_nss = ticks; + + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_soft_stop_ticks, js_soft_stop_ms); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_soft_stop_ticks_cl, js_soft_stop_ms_cl); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_hard_stop_ticks_ss, js_hard_stop_ms_ss); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_hard_stop_ticks_cl, js_hard_stop_ms_cl); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_hard_stop_ticks_nss, js_hard_stop_ms_nss); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_reset_ticks_ss, js_reset_ms_ss); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_reset_ticks_cl, js_reset_ms_cl); + dev_dbg(kbdev->dev, "Overriding KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS with %lu ticks (%lu ms)\n", (unsigned long)kbdev->js_reset_ticks_nss, js_reset_ms_nss); + + return count; + } else { + dev_err(kbdev->dev, "Couldn't process js_timeouts write operation.\nUse format " " \n"); + return -EINVAL; + } +} + +/** Show callback for the @c js_timeouts sysfs file. + * + * This function is called to get the contents of the @c js_timeouts sysfs + * file. It returns the last set values written to the js_timeouts sysfs file. + * If the file didn't get written yet, the values will be 0. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_js_timeouts(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + u64 ms; + unsigned long js_soft_stop_ms; + unsigned long js_soft_stop_ms_cl; + unsigned long js_hard_stop_ms_ss; + unsigned long js_hard_stop_ms_cl; + unsigned long js_hard_stop_ms_nss; + unsigned long js_reset_ms_ss; + unsigned long js_reset_ms_cl; + unsigned long js_reset_ms_nss; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ms = (u64) kbdev->js_soft_stop_ticks * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_soft_stop_ms = (unsigned long)ms; + + ms = (u64) kbdev->js_soft_stop_ticks_cl * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_soft_stop_ms_cl = (unsigned long)ms; + + ms = (u64) kbdev->js_hard_stop_ticks_ss * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_hard_stop_ms_ss = (unsigned long)ms; + + ms = (u64) kbdev->js_hard_stop_ticks_cl * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_hard_stop_ms_cl = (unsigned long)ms; + + ms = (u64) kbdev->js_hard_stop_ticks_nss * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_hard_stop_ms_nss = (unsigned long)ms; + + ms = (u64) kbdev->js_reset_ticks_ss * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_reset_ms_ss = (unsigned long)ms; + + ms = (u64) kbdev->js_reset_ticks_cl * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_reset_ms_cl = (unsigned long)ms; + + ms = (u64) kbdev->js_reset_ticks_nss * kbdev->js_data.scheduling_tick_ns; + do_div(ms, 1000000UL); + js_reset_ms_nss = (unsigned long)ms; + + ret = scnprintf(buf, PAGE_SIZE, "%lu %lu %lu %lu %lu %lu %lu %lu\n", + js_soft_stop_ms, js_soft_stop_ms_cl, + js_hard_stop_ms_ss, js_hard_stop_ms_cl, + js_hard_stop_ms_nss, js_reset_ms_ss, + js_reset_ms_cl, js_reset_ms_nss); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** The sysfs file @c js_timeouts. + * + * This is used to override the current job scheduler values for + * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_SS + * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_CL + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS. + */ +static DEVICE_ATTR(js_timeouts, S_IRUGO | S_IWUSR, show_js_timeouts, set_js_timeouts); + + + +/** Store callback for the @c force_replay sysfs file. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t set_force_replay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + if (!strncmp("limit=", buf, MIN(6, count))) { + int force_replay_limit; + int items = sscanf(buf, "limit=%u", &force_replay_limit); + + if (items == 1) { + kbdev->force_replay_random = MALI_FALSE; + kbdev->force_replay_limit = force_replay_limit; + kbdev->force_replay_count = 0; + + return count; + } + } else if (!strncmp("random_limit", buf, MIN(12, count))) { + kbdev->force_replay_random = MALI_TRUE; + kbdev->force_replay_count = 0; + + return count; + } else if (!strncmp("norandom_limit", buf, MIN(14, count))) { + kbdev->force_replay_random = MALI_FALSE; + kbdev->force_replay_limit = KBASEP_FORCE_REPLAY_DISABLED; + kbdev->force_replay_count = 0; + + return count; + } else if (!strncmp("core_req=", buf, MIN(9, count))) { + unsigned int core_req; + int items = sscanf(buf, "core_req=%x", &core_req); + + if (items == 1) { + kbdev->force_replay_core_req = (base_jd_core_req)core_req; + + return count; + } + } + dev_err(kbdev->dev, "Couldn't process force_replay write operation.\nPossible settings: limit=, random_limit, norandom_limit, core_req=\n"); + return -EINVAL; +} + +/** Show callback for the @c force_replay sysfs file. + * + * This function is called to get the contents of the @c force_replay sysfs + * file. It returns the last set value written to the force_replay sysfs file. + * If the file didn't get written yet, the values will be 0. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_force_replay(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + if (kbdev->force_replay_random) + ret = scnprintf(buf, PAGE_SIZE, + "limit=0\nrandom_limit\ncore_req=%x\n", + kbdev->force_replay_core_req); + else + ret = scnprintf(buf, PAGE_SIZE, + "limit=%u\nnorandom_limit\ncore_req=%x\n", + kbdev->force_replay_limit, + kbdev->force_replay_core_req); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** The sysfs file @c force_replay. + * + */ +static DEVICE_ATTR(force_replay, S_IRUGO | S_IWUSR, show_force_replay, set_force_replay); +#endif /* !MALI_CUSTOMER_RELEASE */ + +#ifdef CONFIG_MALI_DEBUG +static ssize_t set_js_softstop_always(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int items; + int softstop_always; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + items = sscanf(buf, "%d", &softstop_always); + if ((items == 1) && ((softstop_always == 0) || (softstop_always == 1))) { + kbdev->js_data.softstop_always = (mali_bool) softstop_always; + dev_dbg(kbdev->dev, "Support for softstop on a single context: %s\n", (kbdev->js_data.softstop_always == MALI_FALSE) ? "Disabled" : "Enabled"); + return count; + } else { + dev_err(kbdev->dev, "Couldn't process js_softstop_always write operation.\nUse format " "\n"); + return -EINVAL; + } +} + +static ssize_t show_js_softstop_always(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + ssize_t ret; + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + ret = scnprintf(buf, PAGE_SIZE, "%d\n", kbdev->js_data.softstop_always); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** + * By default, soft-stops are disabled when only a single context is present. The ability to + * enable soft-stop when only a single context is present can be used for debug and unit-testing purposes. + * (see CL t6xx_stress_1 unit-test as an example whereby this feature is used.) + */ +static DEVICE_ATTR(js_softstop_always, S_IRUGO | S_IWUSR, show_js_softstop_always, set_js_softstop_always); +#endif /* CONFIG_MALI_DEBUG */ + +#ifdef CONFIG_MALI_DEBUG +typedef void (kbasep_debug_command_func) (struct kbase_device *); + +enum kbasep_debug_command_code { + KBASEP_DEBUG_COMMAND_DUMPTRACE, + + /* This must be the last enum */ + KBASEP_DEBUG_COMMAND_COUNT +}; + +struct kbasep_debug_command { + char *str; + kbasep_debug_command_func *func; +}; + +/** Debug commands supported by the driver */ +static const struct kbasep_debug_command debug_commands[] = { + { + .str = "dumptrace", + .func = &kbasep_trace_dump, + } +}; + +/** Show callback for the @c debug_command sysfs file. + * + * This function is called to get the contents of the @c debug_command sysfs + * file. This is a list of the available debug commands, separated by newlines. + * + * @param dev The device this sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The output buffer for the sysfs file contents + * + * @return The number of bytes output to @c buf. + */ +static ssize_t show_debug(struct device *dev, struct device_attribute *attr, char * const buf) +{ + struct kbase_device *kbdev; + int i; + ssize_t ret = 0; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + for (i = 0; i < KBASEP_DEBUG_COMMAND_COUNT && ret < PAGE_SIZE; i++) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s\n", debug_commands[i].str); + + if (ret >= PAGE_SIZE) { + buf[PAGE_SIZE - 2] = '\n'; + buf[PAGE_SIZE - 1] = '\0'; + ret = PAGE_SIZE - 1; + } + + return ret; +} + +/** Store callback for the @c debug_command sysfs file. + * + * This function is called when the @c debug_command sysfs file is written to. + * It matches the requested command against the available commands, and if + * a matching command is found calls the associated function from + * @ref debug_commands to issue the command. + * + * @param dev The device with sysfs file is for + * @param attr The attributes of the sysfs file + * @param buf The value written to the sysfs file + * @param count The number of bytes written to the sysfs file + * + * @return @c count if the function succeeded. An error code on failure. + */ +static ssize_t issue_debug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct kbase_device *kbdev; + int i; + + kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + for (i = 0; i < KBASEP_DEBUG_COMMAND_COUNT; i++) { + if (sysfs_streq(debug_commands[i].str, buf)) { + debug_commands[i].func(kbdev); + return count; + } + } + + /* Debug Command not found */ + dev_err(dev, "debug_command: command not known\n"); + return -EINVAL; +} + +/** The sysfs file @c debug_command. + * + * This is used to issue general debug commands to the device driver. + * Reading it will produce a list of debug commands, separated by newlines. + * Writing to it with one of those commands will issue said command. + */ +static DEVICE_ATTR(debug_command, S_IRUGO | S_IWUSR, show_debug, issue_debug); +#endif /* CONFIG_MALI_DEBUG */ + + +#ifdef CONFIG_MALI_NO_MALI +static int kbase_common_reg_map(struct kbase_device *kbdev) +{ + return 0; +} +static void kbase_common_reg_unmap(struct kbase_device * const kbdev) +{ +} +#else /* CONFIG_MALI_NO_MALI */ +static int kbase_common_reg_map(struct kbase_device *kbdev) +{ + int err = -ENOMEM; + + kbdev->reg_res = request_mem_region(kbdev->reg_start, kbdev->reg_size, dev_name(kbdev->dev)); + if (!kbdev->reg_res) { + dev_err(kbdev->dev, "Register window unavailable\n"); + err = -EIO; + goto out_region; + } + + kbdev->reg = ioremap(kbdev->reg_start, kbdev->reg_size); + if (!kbdev->reg) { + dev_err(kbdev->dev, "Can't remap register window\n"); + err = -EINVAL; + goto out_ioremap; + } + + return 0; + + out_ioremap: + release_resource(kbdev->reg_res); + kfree(kbdev->reg_res); + out_region: + return err; +} + +static void kbase_common_reg_unmap(struct kbase_device * const kbdev) +{ + iounmap(kbdev->reg); + release_resource(kbdev->reg_res); + kfree(kbdev->reg_res); +} +#endif /* CONFIG_MALI_NO_MALI */ + +static int kbase_common_device_init(struct kbase_device *kbdev) +{ + int err = -ENOMEM; + mali_error mali_err; + enum { + inited_mem = (1u << 0), + inited_job_slot = (1u << 1), + inited_pm = (1u << 2), + inited_js = (1u << 3), + inited_irqs = (1u << 4), + inited_debug = (1u << 5), + inited_js_softstop = (1u << 6), +#if !MALI_CUSTOMER_RELEASE + inited_js_timeouts = (1u << 7), + inited_force_replay = (1u << 13), +#endif /* !MALI_CUSTOMER_RELEASE */ + inited_pm_runtime_init = (1u << 8), +#ifdef CONFIG_DEBUG_FS + inited_gpu_memory = (1u << 9), +#endif /* CONFIG_DEBUG_FS */ +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + inited_sc_split = (1u << 11), +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ +#ifdef CONFIG_MALI_TRACE_TIMELINE + inited_timeline = (1u << 12), +#endif /* CONFIG_MALI_TRACE_LINE */ + inited_pm_powerup = (1u << 14), + }; + + int inited = 0; + + dev_set_drvdata(kbdev->dev, kbdev); + + kbdev->mdev.minor = MISC_DYNAMIC_MINOR; + kbdev->mdev.name = kbdev->devname; + kbdev->mdev.fops = &kbase_fops; + kbdev->mdev.parent = get_device(kbdev->dev); + + kbase_disjoint_init(kbdev); + + scnprintf(kbdev->devname, DEVNAME_SIZE, "%s%d", kbase_drv_name, kbase_dev_nr++); + + if (misc_register(&kbdev->mdev)) { + dev_err(kbdev->dev, "Couldn't register misc dev %s\n", kbdev->devname); + err = -EINVAL; + goto out_misc; + } +#if KBASE_PM_EN + if (device_create_file(kbdev->dev, &dev_attr_power_policy)) { + dev_err(kbdev->dev, "Couldn't create power_policy sysfs file\n"); + goto out_file; + } + + if (device_create_file(kbdev->dev, &dev_attr_core_availability_policy)) { + dev_err(kbdev->dev, "Couldn't create core_availability_policy sysfs file\n"); + goto out_file_core_availability_policy; + } + + if (device_create_file(kbdev->dev, &dev_attr_core_mask)) { + dev_err(kbdev->dev, "Couldn't create core_mask sysfs file\n"); + goto out_file_core_mask; + } +#endif /* KBASE_PM_EN */ + down(&kbase_dev_list_lock); + list_add(&kbdev->entry, &kbase_dev_list); + up(&kbase_dev_list_lock); + dev_info(kbdev->dev, "Probed as %s\n", dev_name(kbdev->mdev.this_device)); + + mali_err = kbase_pm_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_pm; + + if (kbdev->pm.callback_power_runtime_init) { + mali_err = kbdev->pm.callback_power_runtime_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_pm_runtime_init; + } + + mali_err = kbase_mem_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_mem; + + mali_err = kbase_job_slot_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_job_slot; + + mali_err = kbasep_js_devdata_init(kbdev); + if (MALI_ERROR_NONE != mali_err) + goto out_partial; + + inited |= inited_js; + + err = kbase_install_interrupts(kbdev); + if (err) + goto out_partial; + + inited |= inited_irqs; + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + if (device_create_file(kbdev->dev, &dev_attr_sc_split)) { + dev_err(kbdev->dev, "Couldn't create sc_split sysfs file\n"); + goto out_partial; + } + + inited |= inited_sc_split; +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ + +#ifdef CONFIG_DEBUG_FS + if (kbasep_gpu_memory_debugfs_init(kbdev)) { + dev_err(kbdev->dev, "Couldn't create gpu_memory debugfs file\n"); + goto out_partial; + } + inited |= inited_gpu_memory; + +#endif /* CONFIG_DEBUG_FS */ + + mtk_get_gpu_memory_usage_fp = kbase_report_gpu_memory_usage; + +#ifdef CONFIG_PROC_FS + proc_mali_register(); +#endif + +#ifdef CONFIG_MALI_DEBUG + + if (device_create_file(kbdev->dev, &dev_attr_debug_command)) { + dev_err(kbdev->dev, "Couldn't create debug_command sysfs file\n"); + goto out_partial; + } + inited |= inited_debug; + + if (device_create_file(kbdev->dev, &dev_attr_js_softstop_always)) { + dev_err(kbdev->dev, "Couldn't create js_softstop_always sysfs file\n"); + goto out_partial; + } + inited |= inited_js_softstop; +#endif /* CONFIG_MALI_DEBUG */ + +#if !MALI_CUSTOMER_RELEASE + if (device_create_file(kbdev->dev, &dev_attr_js_timeouts)) { + dev_err(kbdev->dev, "Couldn't create js_timeouts sysfs file\n"); + goto out_partial; + } + inited |= inited_js_timeouts; + + if (device_create_file(kbdev->dev, &dev_attr_force_replay)) { + dev_err(kbdev->dev, "Couldn't create force_replay sysfs file\n"); + goto out_partial; + } + inited |= inited_force_replay; +#endif /* !MALI_CUSTOMER_RELEASE */ + +#ifdef CONFIG_MALI_TRACE_TIMELINE + if (kbasep_trace_timeline_debugfs_init(kbdev)) { + dev_err(kbdev->dev, "Couldn't create mali_timeline_defs debugfs file\n"); + goto out_partial; + } + inited |= inited_timeline; +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +#ifdef CONFIG_MALI_DEVFREQ + kbase_devfreq_init(kbdev); +#endif + + mali_err = kbase_pm_powerup(kbdev); + if (MALI_ERROR_NONE == mali_err) { + inited |= inited_pm_powerup; +#ifdef CONFIG_MALI_DEBUG +#if !defined(CONFIG_MALI_NO_MALI) + if (MALI_ERROR_NONE != kbasep_common_test_interrupt_handlers(kbdev)) { + dev_err(kbdev->dev, "Interrupt assigment check failed.\n"); + err = -EINVAL; + goto out_partial; + } +#endif /* CONFIG_MALI_NO_MALI */ +#endif /* CONFIG_MALI_DEBUG */ + /* intialise the kctx list */ + mutex_init(&kbdev->kctx_list_lock); + INIT_LIST_HEAD(&kbdev->kctx_list); + return 0; + } else { + /* Failed to power up the GPU. */ + dev_err(kbdev->dev, "GPU power up failed.\n"); + err = -ENODEV; + } + + out_partial: +#ifdef CONFIG_MALI_TRACE_TIMELINE + if (inited & inited_timeline) + kbasep_trace_timeline_debugfs_term(kbdev); +#endif /* CONFIG_MALI_TRACE_TIMELINE */ +#if !MALI_CUSTOMER_RELEASE + if (inited & inited_force_replay) + device_remove_file(kbdev->dev, &dev_attr_force_replay); + if (inited & inited_js_timeouts) + device_remove_file(kbdev->dev, &dev_attr_js_timeouts); +#endif /* !MALI_CUSTOMER_RELEASE */ +#ifdef CONFIG_MALI_DEBUG + if (inited & inited_js_softstop) + device_remove_file(kbdev->dev, &dev_attr_js_softstop_always); + + if (inited & inited_debug) + device_remove_file(kbdev->dev, &dev_attr_debug_command); + +#endif /* CONFIG_MALI_DEBUG */ + +#ifdef CONFIG_DEBUG_FS + if (inited & inited_gpu_memory) + kbasep_gpu_memory_debugfs_term(kbdev); +#endif /* CONFIG_DEBUG_FS */ + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + if (inited & inited_sc_split) + device_remove_file(kbdev->dev, &dev_attr_sc_split); +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ + + if (inited & inited_js) + kbasep_js_devdata_halt(kbdev); + + if (inited & inited_job_slot) + kbase_job_slot_halt(kbdev); + + if (inited & inited_mem) + kbase_mem_halt(kbdev); + + if (inited & inited_pm_powerup) + kbase_pm_halt(kbdev); + + if (inited & inited_irqs) + kbase_release_interrupts(kbdev); + + if (inited & inited_js) + kbasep_js_devdata_term(kbdev); + + if (inited & inited_job_slot) + kbase_job_slot_term(kbdev); + + if (inited & inited_mem) + kbase_mem_term(kbdev); + + if (inited & inited_pm_runtime_init) { + if (kbdev->pm.callback_power_runtime_term) + kbdev->pm.callback_power_runtime_term(kbdev); + } + + if (inited & inited_pm) + kbase_pm_term(kbdev); + + down(&kbase_dev_list_lock); + list_del(&kbdev->entry); + up(&kbase_dev_list_lock); +#if KBASE_PM_EN + device_remove_file(kbdev->dev, &dev_attr_core_mask); + out_file_core_mask: + device_remove_file(kbdev->dev, &dev_attr_core_availability_policy); + out_file_core_availability_policy: + device_remove_file(kbdev->dev, &dev_attr_power_policy); + out_file: +#endif /*KBASE_PM_EN*/ + misc_deregister(&kbdev->mdev); + out_misc: + put_device(kbdev->dev); + return err; +} + + +static int kbase_platform_device_probe(struct platform_device *pdev) +{ + struct kbase_device *kbdev; + struct resource *reg_res; + struct kbase_attribute *platform_data; + int err; + int i; + struct mali_base_gpu_core_props *core_props; +#ifdef CONFIG_MALI_NO_MALI + mali_error mali_err; +#endif /* CONFIG_MALI_NO_MALI */ +#ifdef CONFIG_OF +#ifdef CONFIG_MALI_PLATFORM_FAKE + struct kbase_platform_config *config; + int attribute_count; + + + pr_debug("[MALI]Using mali midgard r5p0-EAC DDK kernel device driver. GPU probe() begin\n"); + + config = kbase_get_platform_config(); + attribute_count = kbasep_get_config_attribute_count(config->attributes); + + err = platform_device_add_data(pdev, config->attributes, + attribute_count * sizeof(config->attributes[0])); + if (err) + return err; +#endif /* CONFIG_MALI_PLATFORM_FAKE */ +#endif /* CONFIG_OF */ + + kbdev = kbase_device_alloc(); + if (!kbdev) { + dev_err(&pdev->dev, "Can't allocate device\n"); + err = -ENOMEM; + goto out; + } +#ifdef CONFIG_MALI_NO_MALI + mali_err = midg_device_create(kbdev); + if (MALI_ERROR_NONE != mali_err) { + dev_err(&pdev->dev, "Can't initialize dummy model\n"); + err = -ENOMEM; + goto out_midg; + } +#endif /* CONFIG_MALI_NO_MALI */ + + kbdev->dev = &pdev->dev; + platform_data = (struct kbase_attribute *)kbdev->dev->platform_data; + + if (NULL == platform_data) { + dev_err(kbdev->dev, "Platform data not specified\n"); + err = -ENOENT; + goto out_free_dev; + } + + if (MALI_TRUE != kbasep_validate_configuration_attributes(kbdev, platform_data)) { + dev_err(kbdev->dev, "Configuration attributes failed to validate\n"); + err = -EINVAL; + goto out_free_dev; + } + kbdev->config_attributes = platform_data; + + /* 3 IRQ resources */ + for (i = 0; i < 3; i++) { + struct resource *irq_res; + int irqtag; + + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + if (!irq_res) { + dev_err(kbdev->dev, "No IRQ resource at index %d\n", i); + err = -ENOENT; + goto out_free_dev; + } + +#ifdef CONFIG_OF + if (!strcmp(irq_res->name, "JOB")) { + irqtag = JOB_IRQ_TAG; + } else if (!strcmp(irq_res->name, "MMU")) { + irqtag = MMU_IRQ_TAG; + } else if (!strcmp(irq_res->name, "GPU")) { + irqtag = GPU_IRQ_TAG; + } else { + dev_err(&pdev->dev, "Invalid irq res name: '%s'\n", + irq_res->name); + err = -EINVAL; + goto out_free_dev; + } +#else + irqtag = i; +#endif /* CONFIG_OF */ + kbdev->irqs[irqtag].irq = irq_res->start; + kbdev->irqs[irqtag].flags = (irq_res->flags & IRQF_TRIGGER_MASK); + } + + /* the first memory resource is the physical address of the GPU registers */ + reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!reg_res) { + dev_err(kbdev->dev, "Invalid register resource\n"); + err = -ENOENT; + goto out_free_dev; + } + + kbdev->reg_start = reg_res->start; + kbdev->reg_size = resource_size(reg_res); + + err = kbase_common_reg_map(kbdev); + if (err) + goto out_free_dev; + +#ifdef CONFIG_HAVE_CLK // MTK + kbdev->clock = clk_get(kbdev->dev, "clk_mali"); + if (IS_ERR_OR_NULL(kbdev->clock)) { + dev_info(kbdev->dev, "Continuing without Mali clock control\n"); + kbdev->clock = NULL; + /* Allow probe to continue without clock. */ + } else { + err = clk_prepare_enable(kbdev->clock); + if (err) { + dev_err(kbdev->dev, + "Failed to prepare and enable clock (%d)\n", err); + goto out_clock_get; + } + } +#endif /* CONFIG_HAVE_CLK */ + +#ifdef CONFIG_DEBUG_FS + kbdev->mali_debugfs_directory = debugfs_create_dir("mali", NULL); + if (NULL == kbdev->mali_debugfs_directory) { + dev_err(kbdev->dev, "Couldn't create mali debugfs directory\n"); + goto out_clock_enable; + } + kbdev->memory_profile_directory = debugfs_create_dir("mem", + kbdev->mali_debugfs_directory); + if (NULL == kbdev->memory_profile_directory) { + dev_err(kbdev->dev, "Couldn't create mali mem debugfs directory\n"); + goto out_mali_debugfs_remove; + } + if (kbasep_jd_debugfs_init(kbdev)) { + dev_err(kbdev->dev, "Couldn't create mali jd debugfs entries\n"); + goto out_mem_profile_remove; + } +#endif /* CONFIG_DEBUG_FS */ + +#if defined(CONFIG_MTK_CLKMGR) +#else + kbdev->clk_mfg = devm_clk_get(&pdev->dev, "mfg-main"); + if (IS_ERR(kbdev->clk_mfg)) { + dev_err(kbdev->dev, "cannot get mfg main clock\n"); + return PTR_ERR(kbdev->clk_mfg); + } + kbdev->clk_smi_common = devm_clk_get(&pdev->dev, "mfg-smi-common"); + if (IS_ERR(kbdev->clk_smi_common)) { + dev_err(kbdev->dev, "cannot get smi common clock\n"); + return PTR_ERR(kbdev->clk_smi_common); + } + kbdev->clk_mfg_scp = devm_clk_get(&pdev->dev, "mtcmos-mfg"); + if (IS_ERR(kbdev->clk_mfg_scp)) { + dev_err(kbdev->dev, "cannot get mtcmos mfg\n"); + return PTR_ERR(kbdev->clk_mfg_scp); + } + kbdev->clk_display_scp = devm_clk_get(&pdev->dev, "mtcmos-display"); + if (IS_ERR(kbdev->clk_display_scp)) { + dev_err(kbdev->dev, "cannot get mtcmos display\n"); + return PTR_ERR(kbdev->clk_display_scp); + } +#endif + + if (MALI_ERROR_NONE != kbase_device_init(kbdev)) { + dev_err(kbdev->dev, "Can't initialize device\n"); + + err = -ENOMEM; + goto out_debugfs_remove; + } + + /* obtain min/max configured gpu frequencies */ + core_props = &(kbdev->gpu_props.props.core_props); + core_props->gpu_freq_khz_min = GPU_FREQ_KHZ_MIN; + core_props->gpu_freq_khz_max = GPU_FREQ_KHZ_MAX; + kbdev->gpu_props.irq_throttle_time_us = DEFAULT_IRQ_THROTTLE_TIME_US; + + err = kbase_common_device_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Failed kbase_common_device_init\n"); + goto out_term_dev; + } + + + pr_debug("[MALI]Using mali midgard r5p0-EAC DDK kernel device driver. GPU probe() end\n"); + + return 0; + +out_term_dev: + kbase_device_term(kbdev); +out_debugfs_remove: +#ifdef CONFIG_DEBUG_FS + kbasep_jd_debugfs_term(kbdev); +out_mem_profile_remove: + debugfs_remove(kbdev->memory_profile_directory); +out_mali_debugfs_remove: + debugfs_remove(kbdev->mali_debugfs_directory); +out_clock_enable: +#endif /* CONFIG_DEBUG_FS */ +#ifdef CONFIG_HAVE_CLK + clk_disable_unprepare(kbdev->clock); +out_clock_get: + clk_put(kbdev->clock); + kbase_common_reg_unmap(kbdev); +#endif /* CONFIG_HAVE_CLK */ +out_free_dev: +#ifdef CONFIG_MALI_NO_MALI + midg_device_destroy(kbdev); +out_midg: +#endif /* CONFIG_MALI_NO_MALI */ + kbase_device_free(kbdev); +out: + return err; +} + +static int kbase_common_device_remove(struct kbase_device *kbdev) +{ + mtk_get_gpu_memory_usage_fp = NULL; + +#ifdef CONFIG_MALI_DEVFREQ + kbase_devfreq_term(kbdev); +#endif + + if (kbdev->pm.callback_power_runtime_term) + kbdev->pm.callback_power_runtime_term(kbdev); +#if KBASE_PM_EN + /* Remove the sys power policy file */ + device_remove_file(kbdev->dev, &dev_attr_power_policy); + device_remove_file(kbdev->dev, &dev_attr_core_availability_policy); + device_remove_file(kbdev->dev, &dev_attr_core_mask); +#endif +#ifdef CONFIG_MALI_TRACE_TIMELINE + kbasep_trace_timeline_debugfs_term(kbdev); +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +#ifdef CONFIG_MALI_DEBUG + device_remove_file(kbdev->dev, &dev_attr_js_softstop_always); + device_remove_file(kbdev->dev, &dev_attr_debug_command); +#endif /* CONFIG_MALI_DEBUG */ +#if !MALI_CUSTOMER_RELEASE + device_remove_file(kbdev->dev, &dev_attr_js_timeouts); + device_remove_file(kbdev->dev, &dev_attr_force_replay); +#endif /* !MALI_CUSTOMER_RELEASE */ +#ifdef CONFIG_DEBUG_FS + kbasep_gpu_memory_debugfs_term(kbdev); +#endif + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + device_remove_file(kbdev->dev, &dev_attr_sc_split); +#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */ + + kbasep_js_devdata_halt(kbdev); + kbase_job_slot_halt(kbdev); + kbase_mem_halt(kbdev); + kbase_pm_halt(kbdev); + + kbase_release_interrupts(kbdev); + + kbasep_js_devdata_term(kbdev); + kbase_job_slot_term(kbdev); + kbase_mem_term(kbdev); + kbase_pm_term(kbdev); + + down(&kbase_dev_list_lock); + list_del(&kbdev->entry); + up(&kbase_dev_list_lock); + + misc_deregister(&kbdev->mdev); + put_device(kbdev->dev); + kbase_common_reg_unmap(kbdev); + kbase_device_term(kbdev); +#ifdef CONFIG_DEBUG_FS + kbasep_jd_debugfs_term(kbdev); + debugfs_remove(kbdev->memory_profile_directory); + debugfs_remove(kbdev->mali_debugfs_directory); +#endif /* CONFIG_DEBUG_FS */ +#ifdef CONFIG_HAVE_CLK // MTK + if (kbdev->clock) { + clk_disable_unprepare(kbdev->clock); + clk_put(kbdev->clock); + kbdev->clock = NULL; + } +#endif /* CONFIG_HAVE_CLK */ +#ifdef CONFIG_MALI_NO_MALI + midg_device_destroy(kbdev); +#endif /* CONFIG_MALI_NO_MALI */ + kbase_device_free(kbdev); + + return 0; +} + +static int kbase_platform_device_remove(struct platform_device *pdev) +{ + struct kbase_device *kbdev = to_kbase_device(&pdev->dev); + + if (!kbdev) + return -ENODEV; + + return kbase_common_device_remove(kbdev); +} + +/** Suspend callback from the OS. + * + * This is called by Linux when the device should suspend. + * + * @param dev The device to suspend + * + * @return A standard Linux error code + */ +static int kbase_device_suspend(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + +#if defined(CONFIG_PM_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + devfreq_suspend_device(kbdev->devfreq); +#endif + + kbase_pm_suspend(kbdev); + return 0; +} + +/** Resume callback from the OS. + * + * This is called by Linux when the device should resume from suspension. + * + * @param dev The device to resume + * + * @return A standard Linux error code + */ +static int kbase_device_resume(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + kbase_pm_resume(kbdev); + +#if defined(CONFIG_PM_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + devfreq_resume_device(kbdev->devfreq); +#endif + return 0; +} + +/** Runtime suspend callback from the OS. + * + * This is called by Linux when the device should prepare for a condition in which it will + * not be able to communicate with the CPU(s) and RAM due to power management. + * + * @param dev The device to suspend + * + * @return A standard Linux error code + */ +#ifdef CONFIG_PM_RUNTIME +static int kbase_device_runtime_suspend(struct device *dev) +{ + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + +#if defined(CONFIG_PM_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + devfreq_suspend_device(kbdev->devfreq); +#endif + + if (kbdev->pm.callback_power_runtime_off) { + kbdev->pm.callback_power_runtime_off(kbdev); + dev_dbg(dev, "runtime suspend\n"); + } + return 0; +} +#endif /* CONFIG_PM_RUNTIME */ + +/** Runtime resume callback from the OS. + * + * This is called by Linux when the device should go into a fully active state. + * + * @param dev The device to suspend + * + * @return A standard Linux error code + */ + +#ifdef CONFIG_PM_RUNTIME +int kbase_device_runtime_resume(struct device *dev) +{ + int ret = 0; + struct kbase_device *kbdev = to_kbase_device(dev); + + if (!kbdev) + return -ENODEV; + + if (kbdev->pm.callback_power_runtime_on) { + ret = kbdev->pm.callback_power_runtime_on(kbdev); + dev_dbg(dev, "runtime resume\n"); + } + +#if defined(CONFIG_PM_DEVFREQ) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + devfreq_resume_device(kbdev->devfreq); +#endif + + return ret; +} +#endif /* CONFIG_PM_RUNTIME */ + +/** Runtime idle callback from the OS. + * + * This is called by Linux when the device appears to be inactive and it might be + * placed into a low power state + * + * @param dev The device to suspend + * + * @return A standard Linux error code + */ + +#ifdef CONFIG_PM_RUNTIME +static int kbase_device_runtime_idle(struct device *dev) +{ + /* Avoid pm_runtime_suspend being called */ + return 1; +} +#endif /* CONFIG_PM_RUNTIME */ + +/** The power management operations for the platform driver. + */ +static const struct dev_pm_ops kbase_pm_ops = { + .suspend = kbase_device_suspend, + .resume = kbase_device_resume, +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = kbase_device_runtime_suspend, + .runtime_resume = kbase_device_runtime_resume, + .runtime_idle = kbase_device_runtime_idle, +#endif /* CONFIG_PM_RUNTIME */ +}; + +#ifdef CONFIG_OF +static const struct of_device_id kbase_dt_ids[] = { + { .compatible = "arm,malit6xx" }, + { .compatible = "arm,mali-midgard" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, kbase_dt_ids); +#endif + +static struct platform_driver kbase_platform_driver = { + .probe = kbase_platform_device_probe, + .remove = kbase_platform_device_remove, + .driver = { + .name = kbase_drv_name, + .owner = THIS_MODULE, + .pm = &kbase_pm_ops, + .of_match_table = of_match_ptr(kbase_dt_ids), + }, +}; + +/* + * The driver will not provide a shortcut to create the Mali platform device + * anymore when using Device Tree. + */ +#ifdef CONFIG_OF +module_platform_driver(kbase_platform_driver); +#else /* CONFIG_MALI_PLATFORM_FAKE */ + +extern int kbase_platform_early_init(void); + +#ifdef CONFIG_MALI_PLATFORM_FAKE +extern int kbase_platform_fake_register(void); +extern void kbase_platform_fake_unregister(void); +#endif + +static int __init kbase_driver_init(void) +{ + int ret; + + ret = kbase_platform_early_init(); + if (ret) + return ret; + +#ifdef CONFIG_MALI_PLATFORM_FAKE + ret = kbase_platform_fake_register(); + if (ret) + return ret; +#endif + ret = platform_driver_register(&kbase_platform_driver); +#ifdef CONFIG_MALI_PLATFORM_FAKE + if (ret) + kbase_platform_fake_unregister(); +#endif + + return ret; +} + +static void __exit kbase_driver_exit(void) +{ + platform_driver_unregister(&kbase_platform_driver); +#ifdef CONFIG_MALI_PLATFORM_FAKE + kbase_platform_fake_unregister(); +#endif +} + +module_init(kbase_driver_init); +module_exit(kbase_driver_exit); + +#endif /* CONFIG_OF */ + +MODULE_LICENSE("GPL"); +MODULE_VERSION(MALI_RELEASE_NAME); + +#if defined(CONFIG_MALI_GATOR_SUPPORT) || defined(CONFIG_MALI_SYSTEM_TRACE) +#define CREATE_TRACE_POINTS +#endif + +#ifdef CONFIG_MALI_GATOR_SUPPORT +/* Create the trace points (otherwise we just get code to call a tracepoint) */ +#include "mali_linux_trace.h" + +#define MET_USER_EVENT_SUPPORT +#include + +void kbase_trace_mali_pm_status(u32 event, u64 value) +{ + switch (event) { + case KBASE_PM_CORE_SHADER: + met_tag_oneshot(0, "MALI_SHADER_STATUS", (unsigned int)value); + break; + case KBASE_PM_CORE_TILER: + met_tag_oneshot(0, "MALI_TILER_STATUS", (unsigned int)value); + break; + case KBASE_PM_CORE_L2: + met_tag_oneshot(0, "MALI_L2_STATUS", (unsigned int)value); + break; + } + trace_mali_pm_status(event, value); +} + +void kbase_trace_mali_pm_power_off(u32 event, u64 value) +{ + switch (event) { + case KBASE_PM_CORE_SHADER: + met_tag_oneshot(0, "MALI_SHADER_OFF", (unsigned int)value); + break; + case KBASE_PM_CORE_TILER: + met_tag_oneshot(0, "MALI_TILER_OFF", (unsigned int)value); + break; + case KBASE_PM_CORE_L2: + met_tag_oneshot(0, "MALI_L2_OFF", (unsigned int)value); + break; + } + trace_mali_pm_power_off(event, value); +} + +void kbase_trace_mali_pm_power_on(u32 event, u64 value) +{ + switch (event) { + case KBASE_PM_CORE_SHADER: + met_tag_oneshot(0, "MALI_SHADER_ON", (unsigned int)value); + break; + case KBASE_PM_CORE_TILER: + met_tag_oneshot(0, "MALI_TILER_ON", (unsigned int)value); + break; + case KBASE_PM_CORE_L2: + met_tag_oneshot(0, "MALI_L2_ON", (unsigned int)value); + break; + } + trace_mali_pm_power_on(event, value); +} + +void kbase_trace_mali_job_slots_event(u32 event, const struct kbase_context *kctx, u8 atom_id) +{ + trace_mali_job_slots_event(event, (kctx != NULL ? kctx->tgid : 0), (kctx != NULL ? kctx->pid : 0), atom_id, \ + (kctx != NULL ? kctx->jctx.atoms[atom_id].work_id : 0)); +} + +void kbase_trace_mali_page_fault_insert_pages(int event, u32 value) +{ + trace_mali_page_fault_insert_pages(event, value); +} + +void kbase_trace_mali_mmu_as_in_use(int event) +{ + trace_mali_mmu_as_in_use(event); +} + +void kbase_trace_mali_mmu_as_released(int event) +{ + trace_mali_mmu_as_released(event); +} + +void kbase_trace_mali_total_alloc_pages_change(long long int event) +{ + trace_mali_total_alloc_pages_change(event); +} +#endif /* CONFIG_MALI_GATOR_SUPPORT */ +#ifdef CONFIG_MALI_SYSTEM_TRACE +#include "mali_linux_kbase_trace.h" +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.c new file mode 100644 index 0000000000000000000000000000000000000000..a1ef0109d2b4a94396eb91a834d91c5d01a799f9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.c @@ -0,0 +1,124 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_cpuprops.c + * Base kernel property query APIs + */ + +#include "mali_kbase.h" +#ifdef BASE_LEGACY_UK7_SUPPORT + +#include "mali_kbase_cpuprops.h" +#include "mali_kbase_uku.h" +#include +#include +#include +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +#include +#endif + +#define KBASE_DEFAULT_CPU_NUM 0 + +#define L1_DCACHE_LINE_SIZE_LOG2 L1_CACHE_SHIFT + +/** + * @brief Macros used to extract cpu id info + * @see Doc's for Main ID register + */ +#define KBASE_CPUPROPS_ID_GET_REV(cpuid) ((cpuid) & 0x0F) /* [3:0] Revision */ +#define KBASE_CPUPROPS_ID_GET_PART_NR(cpuid)(((cpuid) >> 4) & 0xFFF) /* [15:4] Part number */ +#define KBASE_CPUPROPS_ID_GET_ARCH(cpuid) (((cpuid) >> 16) & 0x0F) /* [19:16] Architecture */ +#define KBASE_CPUPROPS_ID_GET_VARIANT(cpuid)(((cpuid) >> 20) & 0x0F) /* [23:20] Variant */ +#define KBASE_CPUPROPS_ID_GET_CODE(cpuid) (((cpuid) >> 24) & 0xFF) /* [31:23] ASCII code of implementer trademark */ + +/*Below value sourced from OSK*/ +#define L1_DCACHE_SIZE ((u32)0x00008000) + +/** + * @brief Retrieves detailed CPU info from given cpu_val ( ID reg ) + * + * @param kbase_props CPU props to be filled-in with cpu id info + * + */ +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +static void kbasep_cpuprops_uk_get_cpu_id_info(struct kbase_uk_cpuprops * const kbase_props) +{ + kbase_props->props.cpu_id.id = read_cpuid_id(); + + kbase_props->props.cpu_id.valid = 1; + kbase_props->props.cpu_id.rev = KBASE_CPUPROPS_ID_GET_REV(kbase_props->props.cpu_id.id); + kbase_props->props.cpu_id.part = KBASE_CPUPROPS_ID_GET_PART_NR(kbase_props->props.cpu_id.id); + kbase_props->props.cpu_id.arch = KBASE_CPUPROPS_ID_GET_ARCH(kbase_props->props.cpu_id.id); + kbase_props->props.cpu_id.variant = KBASE_CPUPROPS_ID_GET_VARIANT(kbase_props->props.cpu_id.id); + kbase_props->props.cpu_id.implementer = KBASE_CPUPROPS_ID_GET_CODE(kbase_props->props.cpu_id.id); +} +#else +static void kbasep_cpuprops_uk_get_cpu_id_info(struct kbase_uk_cpuprops * const kbase_props) +{ + kbase_props->props.cpu_id.id = 0; + kbase_props->props.cpu_id.valid = 0; + kbase_props->props.cpu_id.rev = 0; + kbase_props->props.cpu_id.part = 0; + kbase_props->props.cpu_id.arch = 0; + kbase_props->props.cpu_id.variant = 0; + kbase_props->props.cpu_id.implementer = 'N'; +} +#endif + +/** + * This function (and file!) is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ + +mali_error kbase_cpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_cpuprops * const kbase_props) +{ + unsigned int max_cpu_freq; + + kbase_props->props.cpu_l1_dcache_line_size_log2 = L1_DCACHE_LINE_SIZE_LOG2; + kbase_props->props.cpu_l1_dcache_size = L1_DCACHE_SIZE; + kbase_props->props.cpu_flags = BASE_CPU_PROPERTY_FLAG_LITTLE_ENDIAN; + + kbase_props->props.nr_cores = NR_CPUS; + kbase_props->props.cpu_page_size_log2 = PAGE_SHIFT; + kbase_props->props.available_memory_size = totalram_pages << PAGE_SHIFT; + + kbasep_cpuprops_uk_get_cpu_id_info(kbase_props); + + /* check if kernel supports dynamic frequency scaling */ + max_cpu_freq = cpufreq_quick_get_max(KBASE_DEFAULT_CPU_NUM); + if (max_cpu_freq != 0) { + /* convert from kHz to mHz */ + kbase_props->props.max_cpu_clock_speed_mhz = max_cpu_freq / 1000; + } else { + /* fallback if CONFIG_CPU_FREQ turned off */ + int result; + kbase_cpuprops_clock_speed_function kbase_cpuprops_uk_get_clock_speed; + + kbase_cpuprops_uk_get_clock_speed = (kbase_cpuprops_clock_speed_function) kbasep_get_config_value(kctx->kbdev, kctx->kbdev->config_attributes, KBASE_CONFIG_ATTR_CPU_SPEED_FUNC); + result = kbase_cpuprops_uk_get_clock_speed(&kbase_props->props.max_cpu_clock_speed_mhz); + if (result != 0) + return MALI_ERROR_FUNCTION_FAILED; + } + + return MALI_ERROR_NONE; +} + +#endif /* BASE_LEGACY_UK7_SUPPORT */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.h new file mode 100644 index 0000000000000000000000000000000000000000..b107f4ac5a292d831122d48d175d9e40c541075f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_cpuprops.h @@ -0,0 +1,55 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase.h" +#ifdef BASE_LEGACY_UK7_SUPPORT + +/** + * @file mali_kbase_cpuprops.h + * Base kernel property query APIs + */ + +#ifndef _KBASE_CPUPROPS_H_ +#define _KBASE_CPUPROPS_H_ + +#include + +/* Forward declarations */ +struct kbase_uk_cpuprops; + +/** + * This file is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ + +/** + * @brief Provides CPU properties data. + * + * Fill the struct kbase_uk_cpuprops with values from CPU configuration. + * + * @param kctx The kbase context + * @param kbase_props A copy of the struct kbase_uk_cpuprops structure from userspace + * + * @return MALI_ERROR_NONE on success. Any other value indicates failure. + */ +mali_error kbase_cpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_cpuprops * const kbase_props); + +#endif /*_KBASE_CPUPROPS_H_*/ +#endif /* BASE_LEGACY_UK7_SUPPORT */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..ce571c9970be08f235122a714eae82379785fa63 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.c @@ -0,0 +1,39 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +static struct kbasep_debug_assert_cb kbasep_debug_assert_registered_cb = { + NULL, + NULL +}; + +void kbase_debug_assert_register_hook(kbase_debug_assert_hook *func, void *param) +{ + kbasep_debug_assert_registered_cb.func = func; + kbasep_debug_assert_registered_cb.param = param; +} + +void kbasep_debug_assert_call_hook(void) +{ + if (kbasep_debug_assert_registered_cb.func != NULL) + kbasep_debug_assert_registered_cb.func(kbasep_debug_assert_registered_cb.param); +} +KBASE_EXPORT_SYMBOL(kbasep_debug_assert_call_hook); + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..e4ced8c76145507fdae6ec633a136cd9e02e79c9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_debug.h @@ -0,0 +1,164 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_DEBUG_H +#define _KBASE_DEBUG_H + +#include + +/** @brief If equals to 0, a trace containing the file, line, and function will be displayed before each message. */ +#define KBASE_DEBUG_SKIP_TRACE 0 + +/** @brief If different from 0, the trace will only contain the file and line. */ +#define KBASE_DEBUG_SKIP_FUNCTION_NAME 0 + +/** @brief Disable the asserts tests if set to 1. Default is to disable the asserts in release. */ +#ifndef KBASE_DEBUG_DISABLE_ASSERTS +#ifdef CONFIG_MALI_DEBUG +#define KBASE_DEBUG_DISABLE_ASSERTS 0 +#else +#define KBASE_DEBUG_DISABLE_ASSERTS 1 +#endif +#endif /* KBASE_DEBUG_DISABLE_ASSERTS */ + +/** Function type that is called on an KBASE_DEBUG_ASSERT() or KBASE_DEBUG_ASSERT_MSG() */ +typedef void (kbase_debug_assert_hook) (void *); + +typedef struct kbasep_debug_assert_cb { + kbase_debug_assert_hook *func; + void *param; +} kbasep_debug_assert_cb; + +/** + * @def KBASEP_DEBUG_PRINT_TRACE + * @brief Private macro containing the format of the trace to display before every message + * @sa KBASE_DEBUG_SKIP_TRACE, KBASE_DEBUG_SKIP_FUNCTION_NAME + */ +#if !KBASE_DEBUG_SKIP_TRACE +#define KBASEP_DEBUG_PRINT_TRACE \ + "In file: " __FILE__ " line: " CSTD_STR2(__LINE__) +#if !KBASE_DEBUG_SKIP_FUNCTION_NAME +#define KBASEP_DEBUG_PRINT_FUNCTION CSTD_FUNC +#else +#define KBASEP_DEBUG_PRINT_FUNCTION "" +#endif +#else +#define KBASEP_DEBUG_PRINT_TRACE "" +#endif + +/** + * @def KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) + * @brief (Private) system printing function associated to the @see KBASE_DEBUG_ASSERT_MSG event. + * @param trace location in the code from where the message is printed + * @param function function from where the message is printed + * @param ... Format string followed by format arguments. + * @note function parameter cannot be concatenated with other strings + */ +/* Select the correct system output function*/ +#ifdef CONFIG_MALI_DEBUG +#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...)\ + do { \ + pr_err("Mali: %s function:%s ", trace, function);\ + pr_err(__VA_ARGS__);\ + pr_err("\n");\ + } while (MALI_FALSE) +#else +#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) CSTD_NOP() +#endif + +#ifdef CONFIG_MALI_DEBUG +#define KBASE_CALL_ASSERT_HOOK() kbasep_debug_assert_call_hook(); +#else +#define KBASE_CALL_ASSERT_HOOK() CSTD_NOP(); +#endif + +/** + * @def KBASE_DEBUG_ASSERT(expr) + * @brief Calls @see KBASE_PRINT_ASSERT and prints the expression @a expr if @a expr is false + * + * @note This macro does nothing if the flag @see KBASE_DEBUG_DISABLE_ASSERTS is set to 1 + * + * @param expr Boolean expression + */ +#define KBASE_DEBUG_ASSERT(expr) \ + KBASE_DEBUG_ASSERT_MSG(expr, #expr) + +#if KBASE_DEBUG_DISABLE_ASSERTS +#define KBASE_DEBUG_ASSERT_MSG(expr, ...) CSTD_NOP() +#else + /** + * @def KBASE_DEBUG_ASSERT_MSG(expr, ...) + * @brief Calls @see KBASEP_DEBUG_ASSERT_OUT and prints the given message if @a expr is false + * + * @note This macro does nothing if the flag @see KBASE_DEBUG_DISABLE_ASSERTS is set to 1 + * + * @param expr Boolean expression + * @param ... Message to display when @a expr is false, as a format string followed by format arguments. + */ +#define KBASE_DEBUG_ASSERT_MSG(expr, ...) \ + do { \ + if (!(expr)) { \ + KBASEP_DEBUG_ASSERT_OUT(KBASEP_DEBUG_PRINT_TRACE, KBASEP_DEBUG_PRINT_FUNCTION, __VA_ARGS__);\ + KBASE_CALL_ASSERT_HOOK();\ + BUG();\ + } \ + } while (MALI_FALSE) +#endif /* KBASE_DEBUG_DISABLE_ASSERTS */ + +/** + * @def KBASE_DEBUG_CODE( X ) + * @brief Executes the code inside the macro only in debug mode + * + * @param X Code to compile only in debug mode. + */ +#ifdef CONFIG_MALI_DEBUG +#define KBASE_DEBUG_CODE(X) X +#else +#define KBASE_DEBUG_CODE(X) CSTD_NOP() +#endif /* CONFIG_MALI_DEBUG */ + +/** @} */ + +/** + * @brief Register a function to call on ASSERT + * + * Such functions will \b only be called during Debug mode, and for debugging + * features \b only. Do not rely on them to be called in general use. + * + * To disable the hook, supply NULL to \a func. + * + * @note This function is not thread-safe, and should only be used to + * register/deregister once in the module's lifetime. + * + * @param[in] func the function to call when an assert is triggered. + * @param[in] param the parameter to pass to \a func when calling it + */ +void kbase_debug_assert_register_hook(kbase_debug_assert_hook *func, void *param); + +/** + * @brief Call a debug assert hook previously registered with kbase_debug_assert_register_hook() + * + * @note This function is not thread-safe with respect to multiple threads + * registering functions and parameters with + * kbase_debug_assert_register_hook(). Otherwise, thread safety is the + * responsibility of the registered hook. + */ +void kbasep_debug_assert_call_hook(void); + +#endif /* _KBASE_DEBUG_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_defs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..a14f200aee5ae936581fa2262f77016d454c6d25 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_defs.h @@ -0,0 +1,980 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_defs.h + * + * Defintions (types, defines, etcs) common to Kbase. They are placed here to + * allow the hierarchy of header files to work. + */ + +#ifndef _KBASE_DEFS_H_ +#define _KBASE_DEFS_H_ + +#include +#include +#include +#include +#include + + +#include +#include +#include + +#ifdef CONFIG_KDS +#include +#endif /* CONFIG_KDS */ + +#ifdef CONFIG_SYNC +#include "sync.h" +#endif /* CONFIG_SYNC */ + +#ifdef CONFIG_DEBUG_FS +#include +#endif /* CONFIG_DEBUG_FS */ + +#ifdef CONFIG_PM_DEVFREQ +#include +#endif /* CONFIG_DEVFREQ */ + +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif /* !defined(CONFIG_MTK_CLKMGR) */ +/** Enable SW tracing when set */ +#ifdef CONFIG_MALI_MIDGARD_ENABLE_TRACE +#define KBASE_TRACE_ENABLE 1 +#endif + +#ifndef KBASE_TRACE_ENABLE +#ifdef CONFIG_MALI_DEBUG +#define KBASE_TRACE_ENABLE 1 +#else +#define KBASE_TRACE_ENABLE 0 +#endif /* CONFIG_MALI_DEBUG */ +#endif /* KBASE_TRACE_ENABLE */ + +/** Dump Job slot trace on error (only active if KBASE_TRACE_ENABLE != 0) */ +#define KBASE_TRACE_DUMP_ON_JOB_SLOT_ERROR 1 + +/** + * Number of milliseconds before resetting the GPU when a job cannot be "zapped" from the hardware. + * Note that the time is actually ZAP_TIMEOUT+SOFT_STOP_RESET_TIMEOUT between the context zap starting and the GPU + * actually being reset to give other contexts time for their jobs to be soft-stopped and removed from the hardware + * before resetting. + */ +#define ZAP_TIMEOUT 1000 + +/** Number of milliseconds before we time out on a GPU soft/hard reset */ +#define RESET_TIMEOUT 500 + +/** + * Prevent soft-stops from occuring in scheduling situations + * + * This is not due to HW issues, but when scheduling is desired to be more predictable. + * + * Therefore, soft stop may still be disabled due to HW issues. + * + * @note Soft stop will still be used for non-scheduling purposes e.g. when terminating a context. + * + * @note if not in use, define this value to 0 instead of \#undef'ing it + */ +#define KBASE_DISABLE_SCHEDULING_SOFT_STOPS 0 +/** + * Prevent hard-stops from occuring in scheduling situations + * + * This is not due to HW issues, but when scheduling is desired to be more predictable. + * + * @note Hard stop will still be used for non-scheduling purposes e.g. when terminating a context. + * + * @note if not in use, define this value to 0 instead of \#undef'ing it + */ +#define KBASE_DISABLE_SCHEDULING_HARD_STOPS 0 + +/** + * The maximum number of Job Slots to support in the Hardware. + * + * You can optimize this down if your target devices will only ever support a + * small number of job slots. + */ +#define BASE_JM_MAX_NR_SLOTS 16 + +/** + * The maximum number of Address Spaces to support in the Hardware. + * + * You can optimize this down if your target devices will only ever support a + * small number of Address Spaces + */ +#define BASE_MAX_NR_AS 16 + +/* mmu */ +#define ENTRY_IS_ATE 1ULL +#define ENTRY_IS_INVAL 2ULL +#define ENTRY_IS_PTE 3ULL + +#define MIDGARD_MMU_VA_BITS 48 + +#define ENTRY_ATTR_BITS (7ULL << 2) /* bits 4:2 */ +#define ENTRY_RD_BIT (1ULL << 6) +#define ENTRY_WR_BIT (1ULL << 7) +#define ENTRY_SHARE_BITS (3ULL << 8) /* bits 9:8 */ +#define ENTRY_ACCESS_BIT (1ULL << 10) +#define ENTRY_NX_BIT (1ULL << 54) + +#define ENTRY_FLAGS_MASK (ENTRY_ATTR_BITS | ENTRY_RD_BIT | ENTRY_WR_BIT | ENTRY_SHARE_BITS | ENTRY_ACCESS_BIT | ENTRY_NX_BIT) + +#if MIDGARD_MMU_VA_BITS > 39 +#define MIDGARD_MMU_TOPLEVEL 0 +#else +#define MIDGARD_MMU_TOPLEVEL 1 +#endif + +#define GROWABLE_FLAGS_REQUIRED (KBASE_REG_PF_GROW) + +/** setting in kbase_context::as_nr that indicates it's invalid */ +#define KBASEP_AS_NR_INVALID (-1) + +#define KBASE_LOCK_REGION_MAX_SIZE (63) +#define KBASE_LOCK_REGION_MIN_SIZE (11) + +#define KBASE_TRACE_SIZE_LOG2 8 /* 256 entries */ +#define KBASE_TRACE_SIZE (1 << KBASE_TRACE_SIZE_LOG2) +#define KBASE_TRACE_MASK ((1 << KBASE_TRACE_SIZE_LOG2)-1) + +#include "mali_kbase_js_defs.h" + +#define KBASEP_FORCE_REPLAY_DISABLED 0 + +/* Maximum force replay limit when randomization is enabled */ +#define KBASEP_FORCE_REPLAY_RANDOM_LIMIT 16 + +/** Atom has been previously soft-stoppped */ +#define KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED (1<<1) +/** Atom has been previously retried to execute */ +#define KBASE_KATOM_FLAGS_RERUN (1<<2) +#define KBASE_KATOM_FLAGS_JOBCHAIN (1<<3) +/** Atom has been previously hard-stopped. */ +#define KBASE_KATOM_FLAG_BEEN_HARD_STOPPED (1<<4) +/** Atom has caused us to enter disjoint state */ +#define KBASE_KATOM_FLAG_IN_DISJOINT (1<<5) + +/* SW related flags about types of JS_COMMAND action + * NOTE: These must be masked off by JS_COMMAND_MASK */ + +/** This command causes a disjoint event */ +#define JS_COMMAND_SW_CAUSES_DISJOINT 0x100 + +/** Bitmask of all SW related flags */ +#define JS_COMMAND_SW_BITS (JS_COMMAND_SW_CAUSES_DISJOINT) + +#if (JS_COMMAND_SW_BITS & JS_COMMAND_MASK) +#error JS_COMMAND_SW_BITS not masked off by JS_COMMAND_MASK. Must update JS_COMMAND_SW_<..> bitmasks +#endif + +/** Soft-stop command that causes a Disjoint event. This of course isn't + * entirely masked off by JS_COMMAND_MASK */ +#define JS_COMMAND_SOFT_STOP_WITH_SW_DISJOINT \ + (JS_COMMAND_SW_CAUSES_DISJOINT | JS_COMMAND_SOFT_STOP) + + +struct kbase_jd_atom_dependency +{ + struct kbase_jd_atom *atom; + u8 dep_type; +}; + +/** + * @brief The function retrieves a read-only reference to the atom field from + * the kbase_jd_atom_dependency structure + * + * @param[in] dep kbase jd atom dependency. + * + * @return readonly reference to dependent ATOM. + */ +static INLINE const struct kbase_jd_atom* const kbase_jd_katom_dep_atom(const struct kbase_jd_atom_dependency* dep) +{ + LOCAL_ASSERT(dep != NULL); + + return (const struct kbase_jd_atom* const )(dep->atom); +} + +/** + * @brief The function retrieves a read-only reference to the dependency type field from + * the kbase_jd_atom_dependency structure + * + * @param[in] dep kbase jd atom dependency. + * + * @return A dependency type value. + */ +static INLINE const u8 kbase_jd_katom_dep_type(const struct kbase_jd_atom_dependency* dep) +{ + LOCAL_ASSERT(dep != NULL); + + return dep->dep_type; +} + +/** + * @brief Setter macro for dep_atom array entry in kbase_jd_atom + * + * @param[in] dep The kbase jd atom dependency. + * @param[in] a The ATOM to be set as a dependency. + * @param type The ATOM dependency type to be set. + * + */ +static INLINE void kbase_jd_katom_dep_set(const struct kbase_jd_atom_dependency* const_dep, + struct kbase_jd_atom * a, + u8 type) +{ + struct kbase_jd_atom_dependency* dep; + + LOCAL_ASSERT(const_dep != NULL); + + dep = (REINTERPRET_CAST(struct kbase_jd_atom_dependency* )const_dep); + + dep->atom = a; + dep->dep_type = type; +} + +/** + * @brief Setter macro for dep_atom array entry in kbase_jd_atom + * + * @param[in] dep The kbase jd atom dependency to be cleared. + * + */ +static INLINE void kbase_jd_katom_dep_clear(const struct kbase_jd_atom_dependency* const_dep) +{ + struct kbase_jd_atom_dependency* dep; + + LOCAL_ASSERT(const_dep != NULL); + + dep = (REINTERPRET_CAST(struct kbase_jd_atom_dependency* )const_dep); + + dep->atom = NULL; + dep->dep_type = BASE_JD_DEP_TYPE_INVALID; +} + +struct kbase_ext_res +{ + mali_addr64 gpu_address; + struct kbase_mem_phy_alloc * alloc; +}; + +struct kbase_jd_atom { + struct work_struct work; + ktime_t start_timestamp; + u64 time_spent_us; /**< Total time spent on the GPU in microseconds */ + + struct base_jd_udata udata; + struct kbase_context *kctx; + + struct list_head dep_head[2]; + struct list_head dep_item[2]; + const struct kbase_jd_atom_dependency dep[2]; + + u16 nr_extres; + struct kbase_ext_res * extres; + + u32 device_nr; + u64 affinity; + u64 jc; + enum kbase_atom_coreref_state coreref_state; +#ifdef CONFIG_KDS + struct list_head node; + struct kds_resource_set *kds_rset; + mali_bool kds_dep_satisfied; +#endif /* CONFIG_KDS */ +#ifdef CONFIG_SYNC + struct sync_fence *fence; + struct sync_fence_waiter sync_waiter; +#endif /* CONFIG_SYNC */ + + /* Note: refer to kbasep_js_atom_retained_state, which will take a copy of some of the following members */ + enum base_jd_event_code event_code; + base_jd_core_req core_req; /**< core requirements */ + /** Job Slot to retry submitting to if submission from IRQ handler failed + * + * NOTE: see if this can be unified into the another member e.g. the event */ + int retry_submit_on_slot; + + union kbasep_js_policy_job_info sched_info; + /* atom priority scaled to nice range with +20 offset 0..39 */ + int nice_prio; + + int poking; /* BASE_HW_ISSUE_8316 */ + + wait_queue_head_t completed; + enum kbase_jd_atom_state status; +#ifdef CONFIG_GPU_TRACEPOINTS + int work_id; +#endif + /* Assigned after atom is completed. Used to check whether PRLAM-10676 workaround should be applied */ + int slot_nr; + + u32 atom_flags; + + /* Number of times this atom has been retried. Used by replay soft job. + */ + int retry_count; +}; + +/* + * Theory of operations: + * + * Atom objects are statically allocated within the context structure. + * + * Each atom is the head of two lists, one for the "left" set of dependencies, one for the "right" set. + */ + +#define KBASE_JD_DEP_QUEUE_SIZE 256 + +struct kbase_jd_context { + struct mutex lock; + struct kbasep_js_kctx_info sched_info; + struct kbase_jd_atom atoms[BASE_JD_ATOM_COUNT]; + + /** Tracks all job-dispatch jobs. This includes those not tracked by + * the scheduler: 'not ready to run' and 'dependency-only' jobs. */ + u32 job_nr; + + /** Waitq that reflects whether there are no jobs (including SW-only + * dependency jobs). This is set when no jobs are present on the ctx, + * and clear when there are jobs. + * + * @note: Job Dispatcher knows about more jobs than the Job Scheduler: + * the Job Scheduler is unaware of jobs that are blocked on dependencies, + * and SW-only dependency jobs. + * + * This waitq can be waited upon to find out when the context jobs are all + * done/cancelled (including those that might've been blocked on + * dependencies) - and so, whether it can be terminated. However, it should + * only be terminated once it is neither present in the policy-queue (see + * kbasep_js_policy_try_evict_ctx() ) nor the run-pool (see + * kbasep_js_kctx_info::ctx::is_scheduled). + * + * Since the waitq is only set under kbase_jd_context::lock, + * the waiter should also briefly obtain and drop kbase_jd_context::lock to + * guarentee that the setter has completed its work on the kbase_context + * + * This must be updated atomically with: + * - kbase_jd_context::job_nr */ + wait_queue_head_t zero_jobs_wait; + + /** Job Done workqueue. */ + struct workqueue_struct *job_done_wq; + + spinlock_t tb_lock; + u32 *tb; + size_t tb_wrap_offset; + +#ifdef CONFIG_KDS + struct kds_callback kds_cb; +#endif /* CONFIG_KDS */ +#ifdef CONFIG_GPU_TRACEPOINTS + atomic_t work_id; +#endif +}; + +struct kbase_jm_slot { + /* The number of slots must be a power of two */ +#define BASE_JM_SUBMIT_SLOTS 16 +#define BASE_JM_SUBMIT_SLOTS_MASK (BASE_JM_SUBMIT_SLOTS - 1) + + struct kbase_jd_atom *submitted[BASE_JM_SUBMIT_SLOTS]; + + struct kbase_context *last_context; + + u8 submitted_head; + u8 submitted_nr; + u8 job_chain_flag; + +}; + +struct kbase_device_info { + u32 features; +}; + +/** Poking state for BASE_HW_ISSUE_8316 */ +enum { + KBASE_AS_POKE_STATE_IN_FLIGHT = 1<<0, + KBASE_AS_POKE_STATE_KILLING_POKE = 1<<1 +}; + +/** Poking state for BASE_HW_ISSUE_8316 */ +typedef u32 kbase_as_poke_state; + +struct kbase_mmu_setup { + u64 transtab; + u64 memattr; +}; + +/** + * Important: Our code makes assumptions that a struct kbase_as structure is always at + * kbase_device->as[number]. This is used to recover the containing + * struct kbase_device from a struct kbase_as structure. + * + * Therefore, struct kbase_as structures must not be allocated anywhere else. + */ +struct kbase_as { + int number; + + struct workqueue_struct *pf_wq; + struct work_struct work_pagefault; + struct work_struct work_busfault; + enum kbase_mmu_fault_type fault_type; + u32 fault_status; + mali_addr64 fault_addr; + struct mutex transaction_mutex; + + struct kbase_mmu_setup current_setup; + + /* BASE_HW_ISSUE_8316 */ + struct workqueue_struct *poke_wq; + struct work_struct poke_work; + /** Protected by kbasep_js_device_data::runpool_irq::lock */ + int poke_refcount; + /** Protected by kbasep_js_device_data::runpool_irq::lock */ + kbase_as_poke_state poke_state; + struct hrtimer poke_timer; +}; + +static inline int kbase_as_has_bus_fault(struct kbase_as *as) +{ + return as->fault_type == KBASE_MMU_FAULT_TYPE_BUS; +} + +static inline int kbase_as_has_page_fault(struct kbase_as *as) +{ + return as->fault_type == KBASE_MMU_FAULT_TYPE_PAGE; +} + +/** + * Instrumentation State Machine States + */ +enum kbase_instr_state { + /** State where instrumentation is not active */ + KBASE_INSTR_STATE_DISABLED = 0, + /** State machine is active and ready for a command. */ + KBASE_INSTR_STATE_IDLE, + /** Hardware is currently dumping a frame. */ + KBASE_INSTR_STATE_DUMPING, + /** We've requested a clean to occur on a workqueue */ + KBASE_INSTR_STATE_REQUEST_CLEAN, + /** Hardware is currently cleaning and invalidating caches. */ + KBASE_INSTR_STATE_CLEANING, + /** Cache clean completed, and either a) a dump is complete, or + * b) instrumentation can now be setup. */ + KBASE_INSTR_STATE_CLEANED, + /** kbasep_reset_timeout_worker() has started (but not compelted) a + * reset. This generally indicates the current action should be aborted, and + * kbasep_reset_timeout_worker() will handle the cleanup */ + KBASE_INSTR_STATE_RESETTING, + /** An error has occured during DUMPING (page fault). */ + KBASE_INSTR_STATE_FAULT +}; + +void kbasep_reset_timeout_worker(struct work_struct *data); +enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *data); + +struct kbasep_mem_device { + atomic_t used_pages; /* Tracks usage of OS shared memory. Updated + when OS memory is allocated/freed. */ + +}; + + + +#define KBASE_TRACE_CODE(X) KBASE_TRACE_CODE_ ## X + +enum kbase_trace_code { + /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE + * THIS MUST BE USED AT THE START OF THE ENUM */ +#define KBASE_TRACE_CODE_MAKE_CODE(X) KBASE_TRACE_CODE(X) +#include "mali_kbase_trace_defs.h" +#undef KBASE_TRACE_CODE_MAKE_CODE + /* Comma on its own, to extend the list */ + , + /* Must be the last in the enum */ + KBASE_TRACE_CODE_COUNT +}; + +#define KBASE_TRACE_FLAG_REFCOUNT (((u8)1) << 0) +#define KBASE_TRACE_FLAG_JOBSLOT (((u8)1) << 1) + +struct kbase_trace { + struct timespec timestamp; + u32 thread_id; + u32 cpu; + void *ctx; + mali_bool katom; + int atom_number; + u64 atom_udata[2]; + u64 gpu_addr; + unsigned long info_val; + u8 code; + u8 jobslot; + u8 refcount; + u8 flags; +}; + +/** Event IDs for the power management framework. + * + * Any of these events might be missed, so they should not be relied upon to + * find the precise state of the GPU at a particular time in the + * trace. Overall, we should get a high percentage of these events for + * statisical purposes, and so a few missing should not be a problem */ +enum kbase_timeline_pm_event { + /* helper for tests */ + KBASEP_TIMELINE_PM_EVENT_FIRST, + + /** Event reserved for backwards compatibility with 'init' events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_0 = KBASEP_TIMELINE_PM_EVENT_FIRST, + + /** The power state of the device has changed. + * + * Specifically, the device has reached a desired or available state. + */ + KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED, + + /** The GPU is becoming active. + * + * This event is sent when the first context is about to use the GPU. + */ + KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE, + + /** The GPU is becoming idle. + * + * This event is sent when the last context has finished using the GPU. + */ + KBASE_TIMELINE_PM_EVENT_GPU_IDLE, + + /** Event reserved for backwards compatibility with 'policy_change' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_4, + + /** Event reserved for backwards compatibility with 'system_suspend' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_5, + + /** Event reserved for backwards compatibility with 'system_resume' + * events */ + KBASE_TIMELINE_PM_EVENT_RESERVED_6, + + /** The job scheduler is requesting to power up/down cores. + * + * This event is sent when: + * - powered down cores are needed to complete a job + * - powered up cores are not needed anymore + */ + KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE, + + KBASEP_TIMELINE_PM_EVENT_LAST = KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE, +}; + +#ifdef CONFIG_MALI_TRACE_TIMELINE +struct kbase_trace_kctx_timeline { + atomic_t jd_atoms_in_flight; + u32 owner_tgid; +}; + +struct kbase_trace_kbdev_timeline { + /** DebugFS entry */ + struct dentry *dentry; + + /* Note: strictly speaking, not needed, because it's in sync with + * kbase_device::jm_slots[]::submitted_nr + * + * But it's kept as an example of how to add global timeline tracking + * information + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock when + * accessing this */ + u8 slot_atoms_submitted[BASE_JM_SUBMIT_SLOTS]; + + /* Last UID for each PM event */ + atomic_t pm_event_uid[KBASEP_TIMELINE_PM_EVENT_LAST+1]; + /* Counter for generating PM event UIDs */ + atomic_t pm_event_uid_counter; + /* + * L2 transition state - MALI_TRUE indicates that the transition is ongoing + * Expected to be protected by pm.power_change_lock */ + mali_bool l2_transitioning; +}; +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + + +struct kbasep_kctx_list_element { + struct list_head link; + struct kbase_context *kctx; +}; + +#define DEVNAME_SIZE 16 + +struct kbase_device { + /** jm_slots is protected by kbasep_js_device_data::runpool_irq::lock */ + struct kbase_jm_slot jm_slots[BASE_JM_MAX_NR_SLOTS]; + s8 slot_submit_count_irq[BASE_JM_MAX_NR_SLOTS]; + + struct list_head entry; + struct device *dev; + struct miscdevice mdev; + u64 reg_start; + size_t reg_size; + void __iomem *reg; + struct resource *reg_res; + struct { + int irq; + int flags; + } irqs[3]; +#ifdef CONFIG_HAVE_CLK + struct clk *clock; +#endif + char devname[DEVNAME_SIZE]; + +#ifdef CONFIG_MALI_NO_MALI + void *model; + struct kmem_cache *irq_slab; + struct workqueue_struct *irq_workq; + atomic_t serving_job_irq; + atomic_t serving_gpu_irq; + atomic_t serving_mmu_irq; + spinlock_t reg_op_lock; +#endif /* CONFIG_MALI_NO_MALI */ + + struct kbase_pm_device_data pm; + struct kbasep_js_device_data js_data; + struct kbasep_mem_device memdev; + struct kbase_as as[BASE_MAX_NR_AS]; + + spinlock_t mmu_mask_change; + + kbase_gpu_props gpu_props; + + /** List of SW workarounds for HW issues */ + unsigned long hw_issues_mask[(BASE_HW_ISSUE_END + BITS_PER_LONG - 1) / BITS_PER_LONG]; + /** List of features available */ + unsigned long hw_features_mask[(BASE_HW_FEATURE_END + BITS_PER_LONG - 1) / BITS_PER_LONG]; + + /* Cached present bitmaps - these are the same as the corresponding hardware registers */ + u64 shader_present_bitmap; + u64 tiler_present_bitmap; + u64 l2_present_bitmap; + u64 l3_present_bitmap; + + /* Bitmaps of cores that are currently in use (running jobs). + * These should be kept up to date by the job scheduler. + * + * pm.power_change_lock should be held when accessing these members. + * + * kbase_pm_check_transitions_nolock() should be called when bits are + * cleared to update the power management system and allow transitions to + * occur. */ + u64 shader_inuse_bitmap; + + /* Refcount for cores in use */ + u32 shader_inuse_cnt[64]; + + /* Bitmaps of cores the JS needs for jobs ready to run */ + u64 shader_needed_bitmap; + + /* Refcount for cores needed */ + u32 shader_needed_cnt[64]; + + u32 tiler_inuse_cnt; + + u32 tiler_needed_cnt; + + /* struct for keeping track of the disjoint information + * + * The state is > 0 if the GPU is in a disjoint state. Otherwise 0 + * The count is the number of disjoint events that have occurred on the GPU + */ + struct { + atomic_t count; + atomic_t state; + } disjoint_event; + + /* Refcount for tracking users of the l2 cache, e.g. when using hardware counter instrumentation. */ + u32 l2_users_count; + + /* Bitmaps of cores that are currently available (powered up and the power policy is happy for jobs to be + * submitted to these cores. These are updated by the power management code. The job scheduler should avoid + * submitting new jobs to any cores that are not marked as available. + * + * pm.power_change_lock should be held when accessing these members. + */ + u64 shader_available_bitmap; + u64 tiler_available_bitmap; + u64 l2_available_bitmap; + + u64 shader_ready_bitmap; + u64 shader_transitioning_bitmap; + + s8 nr_hw_address_spaces; /**< Number of address spaces in the GPU (constant after driver initialisation) */ + s8 nr_user_address_spaces; /**< Number of address spaces available to user contexts */ + + /* Structure used for instrumentation and HW counters dumping */ + struct { + /* The lock should be used when accessing any of the following members */ + spinlock_t lock; + + struct kbase_context *kctx; + u64 addr; + wait_queue_head_t wait; + int triggered; + enum kbase_instr_state state; + wait_queue_head_t cache_clean_wait; + struct workqueue_struct *cache_clean_wq; + struct work_struct cache_clean_work; + + struct kbase_context *suspended_kctx; + struct kbase_uk_hwcnt_setup suspended_state; + } hwcnt; + + /* Set when we're about to reset the GPU */ + atomic_t reset_gpu; +#define KBASE_RESET_GPU_NOT_PENDING 0 /* The GPU reset isn't pending */ +#define KBASE_RESET_GPU_PREPARED 1 /* kbase_prepare_to_reset_gpu has been called */ +#define KBASE_RESET_GPU_COMMITTED 2 /* kbase_reset_gpu has been called - the reset will now definitely happen + * within the timeout period */ +#define KBASE_RESET_GPU_HAPPENING 3 /* The GPU reset process is currently occuring (timeout has expired or + * kbasep_try_reset_gpu_early was called) */ + + /* Work queue and work item for performing the reset in */ + struct workqueue_struct *reset_workq; + struct work_struct reset_work; + wait_queue_head_t reset_wait; + struct hrtimer reset_timer; + + /*value to be written to the irq_throttle register each time an irq is served */ + atomic_t irq_throttle_cycles; + + const struct kbase_attribute *config_attributes; + +#if KBASE_TRACE_ENABLE + spinlock_t trace_lock; + u16 trace_first_out; + u16 trace_next_in; + struct kbase_trace *trace_rbuf; +#endif + +#if !MALI_CUSTOMER_RELEASE + /* This is used to override the current job scheduler values for + * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_SS + * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_CL + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL + * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL + * KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS. + * + * These values are set via the js_timeouts sysfs file. + */ + u32 js_soft_stop_ticks; + u32 js_soft_stop_ticks_cl; + u32 js_hard_stop_ticks_ss; + u32 js_hard_stop_ticks_cl; + u32 js_hard_stop_ticks_nss; + u32 js_reset_ticks_ss; + u32 js_reset_ticks_cl; + u32 js_reset_ticks_nss; +#endif + + struct mutex cacheclean_lock; + + /* Platform specific private data to be accessed by mali_kbase_config_xxx.c only */ + void *platform_context; + + /** Count of contexts keeping the GPU powered */ + atomic_t keep_gpu_powered_count; + + /* List of kbase_contexts created */ + struct list_head kctx_list; + struct mutex kctx_list_lock; + +#ifdef CONFIG_MALI_MIDGARD_RT_PM + struct delayed_work runtime_pm_workqueue; +#endif + +#ifdef CONFIG_PM_DEVFREQ + struct devfreq_dev_profile devfreq_profile; + struct devfreq *devfreq; + unsigned long freq; +#ifdef CONFIG_DEVFREQ_THERMAL + struct devfreq_cooling_device *devfreq_cooling; +#ifdef CONFIG_MALI_POWER_ACTOR + struct power_actor *power_actor; +#endif +#endif +#endif + +#ifdef CONFIG_MALI_TRACE_TIMELINE + struct kbase_trace_kbdev_timeline timeline; +#endif + +#ifdef CONFIG_DEBUG_FS + /* directory for debugfs entries */ + struct dentry *mali_debugfs_directory; + /* debugfs entry for gpu_memory */ + struct dentry *gpu_memory_dentry; + /* debugfs entry for trace */ + struct dentry *trace_dentry; + /* directory for per-ctx memory profiling data */ + struct dentry *memory_profile_directory; + /* Root directory for job dispatcher data */ + struct dentry *jd_directory; +#endif /* CONFIG_DEBUG_FS */ + + /* fbdump profiling controls set by gator */ + u32 kbase_profiling_controls[FBDUMP_CONTROL_MAX]; + + +#if MALI_CUSTOMER_RELEASE == 0 + /* Number of jobs that are run before a job is forced to fail and + * replay. May be KBASEP_FORCE_REPLAY_DISABLED, to disable forced + * failures. */ + int force_replay_limit; + /* Count of jobs between forced failures. Incremented on each job. A + * job is forced to fail once this is greater than or equal to + * force_replay_limit. */ + int force_replay_count; + /* Core requirement for jobs to be failed and replayed. May be zero. */ + base_jd_core_req force_replay_core_req; + /* MALI_TRUE if force_replay_limit should be randomized. The random + * value will be in the range of 1 - KBASEP_FORCE_REPLAY_RANDOM_LIMIT. + */ + mali_bool force_replay_random; +#endif + + /* Total number of created contexts */ + atomic_t ctx_num; + +#if !defined(CONFIG_MTK_CLKMGR) + struct clk *clk_mfg; /* main clock for gpu */ + struct clk *clk_smi_common; /* smi clock */ + struct clk *clk_mfg_scp; /* mfg MTCMOS */ + struct clk *clk_display_scp; /* display MTCMOS */ +#endif /* !defined(CONFIG_MTK_CLKMGR) */ +}; + +struct kbase_context { + struct kbase_device *kbdev; + int id; /* System wide unique id */ + phys_addr_t pgd; + struct list_head event_list; + struct mutex event_mutex; + mali_bool event_closed; + struct workqueue_struct *event_workq; + + u64 mem_attrs; + bool is_compat; + + atomic_t setup_complete; + atomic_t setup_in_progress; + + mali_bool keep_gpu_powered; + + u64 *mmu_teardown_pages; + + phys_addr_t aliasing_sink_page; + + struct mutex reg_lock; /* To be converted to a rwlock? */ + struct rb_root reg_rbtree; /* Red-Black tree of GPU regions (live regions) */ + + unsigned long cookies; + struct kbase_va_region *pending_regions[BITS_PER_LONG]; + + wait_queue_head_t event_queue; + pid_t tgid; + pid_t pid; + + struct kbase_jd_context jctx; + atomic_t used_pages; + atomic_t nonmapped_pages; + + struct kbase_mem_allocator osalloc; + struct kbase_mem_allocator * pgd_allocator; + + struct list_head waiting_soft_jobs; +#ifdef CONFIG_KDS + struct list_head waiting_kds_resource; +#endif + /** This is effectively part of the Run Pool, because it only has a valid + * setting (!=KBASEP_AS_NR_INVALID) whilst the context is scheduled in + * + * The kbasep_js_device_data::runpool_irq::lock must be held whilst accessing + * this. + * + * If the context relating to this as_nr is required, you must use + * kbasep_js_runpool_retain_ctx() to ensure that the context doesn't disappear + * whilst you're using it. Alternatively, just hold the kbasep_js_device_data::runpool_irq::lock + * to ensure the context doesn't disappear (but this has restrictions on what other locks + * you can take whilst doing this) */ + int as_nr; + + /* NOTE: + * + * Flags are in jctx.sched_info.ctx.flags + * Mutable flags *must* be accessed under jctx.sched_info.ctx.jsctx_mutex + * + * All other flags must be added there */ + spinlock_t mm_update_lock; + struct mm_struct * process_mm; + +#ifdef CONFIG_MALI_TRACE_TIMELINE + struct kbase_trace_kctx_timeline timeline; +#endif +#ifdef CONFIG_DEBUG_FS + /* debugfs entry for memory profile */ + struct dentry *mem_dentry; + /* Content of mem_profile file */ + char *mem_profile_data; + /* Size of @c mem_profile_data */ + size_t mem_profile_size; + /* Spinlock guarding data */ + spinlock_t mem_profile_lock; + /* Per-context directory for JD data */ + struct dentry *jd_ctx_dir; +#endif /* CONFIG_DEBUG_FS */ +}; + +enum kbase_reg_access_type { + REG_READ, + REG_WRITE +}; + +enum kbase_share_attr_bits { + /* (1ULL << 8) bit is reserved */ + SHARE_BOTH_BITS = (2ULL << 8), /* inner and outer shareable coherency */ + SHARE_INNER_BITS = (3ULL << 8) /* inner shareable coherency */ +}; + +/* Conversion helpers for setting up high resolution timers */ +#define HR_TIMER_DELAY_MSEC(x) (ns_to_ktime((x)*1000000U)) +#define HR_TIMER_DELAY_NSEC(x) (ns_to_ktime(x)) + +/* Maximum number of loops polling the GPU for a cache flush before we assume it must have completed */ +#define KBASE_CLEAN_CACHE_MAX_LOOPS 100000 +/* Maximum number of loops polling the GPU for an AS command to complete before we assume the GPU has hung */ +#define KBASE_AS_INACTIVE_MAX_LOOPS 100000 + +/* Maximum number of times a job can be replayed */ +#define BASEP_JD_REPLAY_LIMIT 15 + +#endif /* _KBASE_DEFS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.c new file mode 100644 index 0000000000000000000000000000000000000000..7847556a2707df6cac7437a1c7cdbdecc585e532 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.c @@ -0,0 +1,247 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include + +#include +#ifdef CONFIG_DEVFREQ_THERMAL +#include +#endif + +#include "mali_kbase_power_actor.h" + +static int +kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + struct dev_pm_opp *opp; + unsigned long freq = 0; + int err; + + freq = *target_freq; + + rcu_read_lock(); + opp = devfreq_recommended_opp(dev, &freq, flags); + rcu_read_unlock(); + if (IS_ERR_OR_NULL(opp)) { + dev_err(dev, "Failed to get opp (%ld)\n", PTR_ERR(opp)); + return PTR_ERR(opp); + } + + /* + * Only update if there is a change of frequency + */ + if (kbdev->freq == freq) { + *target_freq = freq; + return 0; + } + + err = clk_set_rate(kbdev->clock, freq); + if (err) { + dev_err(dev, "Failed to set clock %lu (target %lu)\n", + freq, *target_freq); + return err; + } + + kbdev->freq = freq; + *target_freq = freq; + + kbase_pm_reset_dvfs_utilisation(kbdev); + + return 0; +} + +static int +kbase_devfreq_cur_freq(struct device *dev, unsigned long *freq) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + *freq = kbdev->freq; + + return 0; +} + +static int +kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *stat) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + stat->current_frequency = kbdev->freq; + + kbase_pm_get_dvfs_utilisation(kbdev, + &stat->total_time, &stat->busy_time); + + stat->private_data = NULL; + + return 0; +} + +static int kbase_devfreq_init_freq_table(struct kbase_device *kbdev, + struct devfreq_dev_profile *dp) +{ + int count; + int i = 0; + unsigned long freq = 0; + struct dev_pm_opp *opp; + + rcu_read_lock(); + count = dev_pm_opp_get_opp_count(kbdev->dev); + if (count < 0) { + rcu_read_unlock(); + return count; + } + rcu_read_unlock(); + + dp->freq_table = kmalloc_array(count, sizeof(dp->freq_table[0]), + GFP_KERNEL); + if (!dp->freq_table) + return -ENOMEM; + + rcu_read_lock(); + for (i = 0; i < count; i++, freq++) { + opp = dev_pm_opp_find_freq_ceil(kbdev->dev, &freq); + if (IS_ERR(opp)) + break; + + dp->freq_table[i] = freq; + } + rcu_read_unlock(); + + if (count != i) + dev_warn(kbdev->dev, "Unable to enumerate all OPPs (%d!=%d\n", + count, i); + + dp->max_state = i; + + return 0; +} + +static void kbase_devfreq_term_freq_table(struct kbase_device *kbdev) +{ + struct devfreq_dev_profile *dp = kbdev->devfreq->profile; + + kfree(dp->freq_table); +} + +static void kbase_devfreq_exit(struct device *dev) +{ + struct kbase_device *kbdev = dev_get_drvdata(dev); + + kbase_devfreq_term_freq_table(kbdev); +} + +int kbase_devfreq_init(struct kbase_device *kbdev) +{ + struct devfreq_dev_profile *dp; + int err; + + dev_dbg(kbdev->dev, "Init Mali devfreq\n"); + + if (!kbdev->clock) + return -ENODEV; + + kbdev->freq = clk_get_rate(kbdev->clock); + + dp = &kbdev->devfreq_profile; + + dp->initial_freq = kbdev->freq; + dp->polling_ms = 100; + dp->target = kbase_devfreq_target; + dp->get_dev_status = kbase_devfreq_status; + dp->get_cur_freq = kbase_devfreq_cur_freq; + dp->exit = kbase_devfreq_exit; + + if (kbase_devfreq_init_freq_table(kbdev, dp)) + return -EFAULT; + + kbdev->devfreq = devfreq_add_device(kbdev->dev, dp, + "simple_ondemand", NULL); + if (IS_ERR_OR_NULL(kbdev->devfreq)) { + kbase_devfreq_term_freq_table(kbdev); + return PTR_ERR(kbdev->devfreq); + } + + err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq); + if (err) { + dev_err(kbdev->dev, + "Failed to register OPP notifier (%d)\n", err); + goto opp_notifier_failed; + } + +#ifdef CONFIG_DEVFREQ_THERMAL + kbdev->devfreq_cooling = of_devfreq_cooling_register( + kbdev->dev->of_node, + kbdev->devfreq); + if (IS_ERR_OR_NULL(kbdev->devfreq_cooling)) { + err = PTR_ERR(kbdev->devfreq_cooling); + dev_err(kbdev->dev, + "Failed to register cooling device (%d)\n", err); + goto cooling_failed; + } + +#ifdef CONFIG_MALI_POWER_ACTOR + err = mali_pa_init(kbdev); + if (err) { + dev_err(kbdev->dev, "Failed to init power actor\n"); + goto pa_failed; + } +#endif +#endif + + return 0; + +#ifdef CONFIG_DEVFREQ_THERMAL +#ifdef CONFIG_MALI_POWER_ACTOR +pa_failed: + devfreq_cooling_unregister(kbdev->devfreq_cooling); +#endif /* CONFIG_MALI_POWER_ACTOR */ +cooling_failed: + devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq); +#endif /* CONFIG_DEVFREQ_THERMAL */ +opp_notifier_failed: + err = devfreq_remove_device(kbdev->devfreq); + if (err) + dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err); + else + kbdev->devfreq = NULL; + + return err; +} + +void kbase_devfreq_term(struct kbase_device *kbdev) +{ + int err; + + dev_dbg(kbdev->dev, "Term Mali devfreq\n"); + +#ifdef CONFIG_DEVFREQ_THERMAL +#ifdef CONFIG_MALI_POWER_ACTOR + mali_pa_term(kbdev); +#endif + + devfreq_cooling_unregister(kbdev->devfreq_cooling); +#endif + + devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq); + + err = devfreq_remove_device(kbdev->devfreq); + if (err) + dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err); + else + kbdev->devfreq = NULL; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.h new file mode 100644 index 0000000000000000000000000000000000000000..e3b333ac35505642dccfc04427b7e0be13d79122 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_devfreq.h @@ -0,0 +1,24 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _BASE_DEVFREQ_H_ +#define _BASE_DEVFREQ_H_ + +int kbase_devfreq_init(struct kbase_device *kbdev); +void kbase_devfreq_term(struct kbase_device *kbdev); + +#endif /* _BASE_DEVFREQ_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_device.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_device.c new file mode 100644 index 0000000000000000000000000000000000000000..39043c96dbbbe3ac6866db31ec9b4031dd50e1b7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_device.c @@ -0,0 +1,817 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_device.c + * Base kernel device APIs + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* NOTE: Magic - 0x45435254 (TRCE in ASCII). + * Supports tracing feature provided in the base module. + * Please keep it in sync with the value of base module. + */ +#define TRACE_BUFFER_HEADER_SPECIAL 0x45435254 + +#if defined(CONFIG_MALI_PLATFORM_VEXPRESS) || defined(CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ) +#ifdef CONFIG_MALI_PLATFORM_FAKE +extern struct kbase_attribute config_attributes_hw_issue_8408[]; +#endif /* CONFIG_MALI_PLATFORM_FAKE */ +#endif /* CONFIG_MALI_PLATFORM_VEXPRESS || CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ */ + +#if KBASE_TRACE_ENABLE +STATIC CONST char *kbasep_trace_code_string[] = { + /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE + * THIS MUST BE USED AT THE START OF THE ARRAY */ +#define KBASE_TRACE_CODE_MAKE_CODE(X) # X +#include "mali_kbase_trace_defs.h" +#undef KBASE_TRACE_CODE_MAKE_CODE +}; +#endif + +#define DEBUG_MESSAGE_SIZE 256 + +STATIC mali_error kbasep_trace_init(struct kbase_device *kbdev); +STATIC void kbasep_trace_term(struct kbase_device *kbdev); +STATIC void kbasep_trace_hook_wrapper(void *param); +#if KBASE_TRACE_ENABLE +STATIC void kbasep_trace_debugfs_init(struct kbase_device *kbdev); +STATIC void kbasep_trace_debugfs_term(struct kbase_device *kbdev); +#endif + +struct kbase_device *kbase_device_alloc(void) +{ + return kzalloc(sizeof(struct kbase_device), GFP_KERNEL); +} + +mali_error kbase_device_init(struct kbase_device * const kbdev) +{ + int i; /* i used after the for loop, don't reuse ! */ + + spin_lock_init(&kbdev->mmu_mask_change); + + /* Initialize platform specific context */ + if (MALI_FALSE == kbasep_platform_device_init(kbdev)) + goto fail; + + /* Ensure we can access the GPU registers */ + kbase_pm_register_access_enable(kbdev); + + /* Find out GPU properties based on the GPU feature registers */ + kbase_gpuprops_set(kbdev); + + /* Get the list of workarounds for issues on the current HW (identified by the GPU_ID register) */ + if (MALI_ERROR_NONE != kbase_hw_set_issues_mask(kbdev)) { + kbase_pm_register_access_disable(kbdev); + goto free_platform; + } + /* Set the list of features available on the current HW (identified by the GPU_ID register) */ + kbase_hw_set_features_mask(kbdev); + +#if defined(CONFIG_ARM64) + set_dma_ops(kbdev->dev, &noncoherent_swiotlb_dma_ops); +#endif + + /* Workaround a pre-3.13 Linux issue, where dma_mask is NULL when our + * device structure was created by device-tree + */ + if (!kbdev->dev->dma_mask) + kbdev->dev->dma_mask = &kbdev->dev->coherent_dma_mask; + + if (dma_set_mask(kbdev->dev, + DMA_BIT_MASK(kbdev->gpu_props.mmu.pa_bits))) + goto dma_set_mask_failed; + + if (dma_set_coherent_mask(kbdev->dev, + DMA_BIT_MASK(kbdev->gpu_props.mmu.pa_bits))) + goto dma_set_mask_failed; + + if (kbase_mem_lowlevel_init(kbdev)) + goto mem_lowlevel_init_failed; + + kbdev->nr_hw_address_spaces = kbdev->gpu_props.num_address_spaces; + + /* We're done accessing the GPU registers for now. */ + kbase_pm_register_access_disable(kbdev); + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { + const char format[] = "mali_mmu%d"; + char name[sizeof(format)]; + const char poke_format[] = "mali_mmu%d_poker"; /* BASE_HW_ISSUE_8316 */ + char poke_name[sizeof(poke_format)]; /* BASE_HW_ISSUE_8316 */ + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) { + if (0 > snprintf(poke_name, sizeof(poke_name), poke_format, i)) + goto free_workqs; + } + + if (0 > snprintf(name, sizeof(name), format, i)) + goto free_workqs; + + kbdev->as[i].number = i; + kbdev->as[i].fault_addr = 0ULL; + + kbdev->as[i].pf_wq = alloc_workqueue(name, 0, 1); + if (NULL == kbdev->as[i].pf_wq) + goto free_workqs; + + mutex_init(&kbdev->as[i].transaction_mutex); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) { + struct hrtimer *poking_timer = &kbdev->as[i].poke_timer; + + kbdev->as[i].poke_wq = alloc_workqueue(poke_name, 0, 1); + if (NULL == kbdev->as[i].poke_wq) { + destroy_workqueue(kbdev->as[i].pf_wq); + goto free_workqs; + } + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&kbdev->as[i].poke_work)); + INIT_WORK(&kbdev->as[i].poke_work, kbasep_as_do_poke); + + hrtimer_init(poking_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + + poking_timer->function = kbasep_as_poke_timer_callback; + + kbdev->as[i].poke_refcount = 0; + kbdev->as[i].poke_state = 0u; + } + } + /* don't change i after this point */ + + spin_lock_init(&kbdev->hwcnt.lock); + + kbdev->hwcnt.state = KBASE_INSTR_STATE_DISABLED; + init_waitqueue_head(&kbdev->reset_wait); + init_waitqueue_head(&kbdev->hwcnt.wait); + init_waitqueue_head(&kbdev->hwcnt.cache_clean_wait); + INIT_WORK(&kbdev->hwcnt.cache_clean_work, kbasep_cache_clean_worker); + kbdev->hwcnt.triggered = 0; + + kbdev->hwcnt.cache_clean_wq = alloc_workqueue("Mali cache cleaning workqueue", + 0, 1); + if (NULL == kbdev->hwcnt.cache_clean_wq) + goto free_workqs; + +#if KBASE_GPU_RESET_EN + kbdev->reset_workq = alloc_workqueue("Mali reset workqueue", 0, 1); + if (NULL == kbdev->reset_workq) + goto free_cache_clean_workq; + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&kbdev->reset_work)); + INIT_WORK(&kbdev->reset_work, kbasep_reset_timeout_worker); + + hrtimer_init(&kbdev->reset_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->reset_timer.function = kbasep_reset_timer_callback; + + if (kbasep_trace_init(kbdev) != MALI_ERROR_NONE) + goto free_reset_workq; +#else + if (kbasep_trace_init(kbdev) != MALI_ERROR_NONE) + goto free_cache_clean_workq; +#endif /* KBASE_GPU_RESET_EN */ + + mutex_init(&kbdev->cacheclean_lock); + atomic_set(&kbdev->keep_gpu_powered_count, 0); + +#ifdef CONFIG_MALI_TRACE_TIMELINE + for (i = 0; i < BASE_JM_SUBMIT_SLOTS; ++i) + kbdev->timeline.slot_atoms_submitted[i] = 0; + + for (i = 0; i <= KBASEP_TIMELINE_PM_EVENT_LAST; ++i) + atomic_set(&kbdev->timeline.pm_event_uid[i], 0); +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + + /* fbdump profiling controls set to 0 - fbdump not enabled until changed by gator */ + for (i = 0; i < FBDUMP_CONTROL_MAX; i++) + kbdev->kbase_profiling_controls[i] = 0; + + kbase_debug_assert_register_hook(&kbasep_trace_hook_wrapper, kbdev); + +#if defined(CONFIG_MALI_PLATFORM_VEXPRESS) || defined(CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ) +#ifdef CONFIG_MALI_PLATFORM_FAKE + /* BASE_HW_ISSUE_8408 requires a configuration with different timeouts for + * the vexpress platform */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + kbdev->config_attributes = config_attributes_hw_issue_8408; +#endif /* CONFIG_MALI_PLATFORM_FAKE */ +#endif /* CONFIG_MALI_PLATFORM_VEXPRESS || CONFIG_MALI_PLATFORM_VEXPRESS_VIRTEX7_40MHZ */ + + atomic_set(&kbdev->ctx_num, 0); + + return MALI_ERROR_NONE; +#if KBASE_GPU_RESET_EN +free_reset_workq: + destroy_workqueue(kbdev->reset_workq); +#endif /* KBASE_GPU_RESET_EN */ +free_cache_clean_workq: + destroy_workqueue(kbdev->hwcnt.cache_clean_wq); + free_workqs: + while (i > 0) { + i--; + destroy_workqueue(kbdev->as[i].pf_wq); + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + destroy_workqueue(kbdev->as[i].poke_wq); + } + kbase_mem_lowlevel_term(kbdev); +mem_lowlevel_init_failed: +dma_set_mask_failed: +free_platform: + kbasep_platform_device_term(kbdev); +fail: + return MALI_ERROR_FUNCTION_FAILED; +} + +void kbase_device_term(struct kbase_device *kbdev) +{ + int i; + + KBASE_DEBUG_ASSERT(kbdev); + +#if KBASE_TRACE_ENABLE + kbase_debug_assert_register_hook(NULL, NULL); +#endif + + kbasep_trace_term(kbdev); + +#if KBASE_GPU_RESET_EN + destroy_workqueue(kbdev->reset_workq); +#endif + + destroy_workqueue(kbdev->hwcnt.cache_clean_wq); + + for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { + destroy_workqueue(kbdev->as[i].pf_wq); + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + destroy_workqueue(kbdev->as[i].poke_wq); + } + + kbase_mem_lowlevel_term(kbdev); + kbasep_platform_device_term(kbdev); +} + +void kbase_device_free(struct kbase_device *kbdev) +{ + kfree(kbdev); +} + +void kbase_device_trace_buffer_install(struct kbase_context *kctx, u32 *tb, size_t size) +{ + unsigned long flags; + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(tb); + + /* set up the header */ + /* magic number in the first 4 bytes */ + tb[0] = TRACE_BUFFER_HEADER_SPECIAL; + /* Store (write offset = 0, wrap counter = 0, transaction active = no) + * write offset 0 means never written. + * Offsets 1 to (wrap_offset - 1) used to store values when trace started + */ + tb[1] = 0; + + /* install trace buffer */ + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + kctx->jctx.tb_wrap_offset = size / 8; + kctx->jctx.tb = tb; + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); +} + +void kbase_device_trace_buffer_uninstall(struct kbase_context *kctx) +{ + unsigned long flags; + KBASE_DEBUG_ASSERT(kctx); + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + kctx->jctx.tb = NULL; + kctx->jctx.tb_wrap_offset = 0; + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); +} + +void kbase_device_trace_register_access(struct kbase_context *kctx, enum kbase_reg_access_type type, u16 reg_offset, u32 reg_value) +{ + unsigned long flags; + spin_lock_irqsave(&kctx->jctx.tb_lock, flags); + if (kctx->jctx.tb) { + u16 wrap_count; + u16 write_offset; + u32 *tb = kctx->jctx.tb; + u32 header_word; + + header_word = tb[1]; + KBASE_DEBUG_ASSERT(0 == (header_word & 0x1)); + + wrap_count = (header_word >> 1) & 0x7FFF; + write_offset = (header_word >> 16) & 0xFFFF; + + /* mark as transaction in progress */ + tb[1] |= 0x1; + mb(); + + /* calculate new offset */ + write_offset++; + if (write_offset == kctx->jctx.tb_wrap_offset) { + /* wrap */ + write_offset = 1; + wrap_count++; + wrap_count &= 0x7FFF; /* 15bit wrap counter */ + } + + /* store the trace entry at the selected offset */ + tb[write_offset * 2 + 0] = (reg_offset & ~0x3) | ((type == REG_WRITE) ? 0x1 : 0x0); + tb[write_offset * 2 + 1] = reg_value; + mb(); + + /* new header word */ + header_word = (write_offset << 16) | (wrap_count << 1) | 0x0; /* transaction complete */ + tb[1] = header_word; + } + spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags); +} + +void kbase_reg_write(struct kbase_device *kbdev, u16 offset, u32 value, struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered); + KBASE_DEBUG_ASSERT(kctx == NULL || kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbdev->dev != NULL); + dev_dbg(kbdev->dev, "w: reg %04x val %08x", offset, value); + kbase_os_reg_write(kbdev, offset, value); + if (kctx && kctx->jctx.tb) + kbase_device_trace_register_access(kctx, REG_WRITE, offset, value); +} + +KBASE_EXPORT_TEST_API(kbase_reg_write) + +u32 kbase_reg_read(struct kbase_device *kbdev, u16 offset, struct kbase_context *kctx) +{ + u32 val; + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered); + KBASE_DEBUG_ASSERT(kctx == NULL || kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kbdev->dev != NULL); + val = kbase_os_reg_read(kbdev, offset); + dev_dbg(kbdev->dev, "r: reg %04x val %08x", offset, val); + if (kctx && kctx->jctx.tb) + kbase_device_trace_register_access(kctx, REG_READ, offset, val); + return val; +} + +KBASE_EXPORT_TEST_API(kbase_reg_read) + +#if KBASE_PM_EN +void kbase_report_gpu_fault(struct kbase_device *kbdev, int multiple) +{ + u32 status; + u64 address; + + status = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS), NULL); + address = (u64) kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTADDRESS_HI), NULL) << 32; + address |= kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTADDRESS_LO), NULL); + + dev_warn(kbdev->dev, "GPU Fault 0x%08x (%s) at 0x%016llx", status & 0xFF, kbase_exception_name(status), address); + if (multiple) + dev_warn(kbdev->dev, "There were multiple GPU faults - some have not been reported\n"); +} + +void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) +{ + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, NULL, 0u, val); + if (val & GPU_FAULT) + kbase_report_gpu_fault(kbdev, val & MULTIPLE_GPU_FAULTS); + + if (val & RESET_COMPLETED) + kbase_pm_reset_done(kbdev); + + if (val & PRFCNT_SAMPLE_COMPLETED) + kbase_instr_hwcnt_sample_done(kbdev); + + if (val & CLEAN_CACHES_COMPLETED) + kbase_clean_caches_done(kbdev); + + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, NULL, 0u, val); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), val, NULL); + + /* kbase_pm_check_transitions must be called after the IRQ has been cleared. This is because it might trigger + * further power transitions and we don't want to miss the interrupt raised to notify us that these further + * transitions have finished. + */ + if (val & POWER_CHANGED_ALL) { + mali_bool cores_are_available; + unsigned long flags; + + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_START); + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_END); + + if (cores_are_available) { + /* Fast-path Job Scheduling on PM IRQ */ + int js; + /* Log timelining information that a change in state has completed */ + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + + spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags); + /* A simplified check to ensure the last context hasn't exited + * after dropping the PM lock whilst doing a PM IRQ: any bits set + * in 'submit_allowed' indicate that we have a context in the + * runpool (which can't leave whilst we hold this lock). It is + * sometimes zero even when we have a context in the runpool, but + * that's no problem because we'll be unable to submit jobs + * anyway */ + if (kbdev->js_data.runpool_irq.submit_allowed) + for (js = 0; js < kbdev->gpu_props.num_job_slots; ++js) { + mali_bool needs_retry; + s8 submitted_count = 0; + needs_retry = kbasep_js_try_run_next_job_on_slot_irq_nolock(kbdev, js, &submitted_count); + /* Don't need to retry outside of IRQ context - this can + * only happen if we submitted too many in one IRQ, such + * that they were completing faster than we could + * submit. In this case, a job IRQ will fire to cause more + * work to be submitted in some way */ + CSTD_UNUSED(needs_retry); + } + spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags); + } + } + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_DONE, NULL, NULL, 0u, val); +} +#endif /* KBASE_PM_EN */ +/* + * Device trace functions + */ +#if KBASE_TRACE_ENABLE + +STATIC mali_error kbasep_trace_init(struct kbase_device *kbdev) +{ + void *rbuf; + + rbuf = kmalloc(sizeof(struct kbase_trace) * KBASE_TRACE_SIZE, GFP_KERNEL); + + if (!rbuf) + return MALI_ERROR_FUNCTION_FAILED; + + kbdev->trace_rbuf = rbuf; + spin_lock_init(&kbdev->trace_lock); + kbasep_trace_debugfs_init(kbdev); + return MALI_ERROR_NONE; +} + +STATIC void kbasep_trace_term(struct kbase_device *kbdev) +{ + kbasep_trace_debugfs_term(kbdev); + kfree(kbdev->trace_rbuf); +} + +static void kbasep_trace_format_msg(struct kbase_trace *trace_msg, char *buffer, int len) +{ + s32 written = 0; + + /* Initial part of message */ + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d.%.6d,%d,%d,%s,%p,", (int)trace_msg->timestamp.tv_sec, (int)(trace_msg->timestamp.tv_nsec / 1000), trace_msg->thread_id, trace_msg->cpu, kbasep_trace_code_string[trace_msg->code], trace_msg->ctx), 0); + + if (trace_msg->katom != MALI_FALSE) { + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "atom %d (ud: 0x%llx 0x%llx)", trace_msg->atom_number, trace_msg->atom_udata[0], trace_msg->atom_udata[1]), 0); + } + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ",%.8llx,", trace_msg->gpu_addr), 0); + + /* NOTE: Could add function callbacks to handle different message types */ + /* Jobslot present */ + if ((trace_msg->flags & KBASE_TRACE_FLAG_JOBSLOT) != MALI_FALSE) + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->jobslot), 0); + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0); + + /* Refcount present */ + if ((trace_msg->flags & KBASE_TRACE_FLAG_REFCOUNT) != MALI_FALSE) + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->refcount), 0); + + written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0); + + /* Rest of message */ + written += MAX(snprintf(buffer + written, MAX(len - written, 0), "0x%.8lx", trace_msg->info_val), 0); + +} + +static void kbasep_trace_dump_msg(struct kbase_device *kbdev, struct kbase_trace *trace_msg) +{ + char buffer[DEBUG_MESSAGE_SIZE]; + + kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE); + dev_dbg(kbdev->dev, "%s", buffer); +} + +void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val) +{ + unsigned long irqflags; + struct kbase_trace *trace_msg; + + spin_lock_irqsave(&kbdev->trace_lock, irqflags); + + trace_msg = &kbdev->trace_rbuf[kbdev->trace_next_in]; + + /* Fill the message */ + trace_msg->thread_id = task_pid_nr(current); + trace_msg->cpu = task_cpu(current); + + getnstimeofday(&trace_msg->timestamp); + + trace_msg->code = code; + trace_msg->ctx = ctx; + + if (NULL == katom) { + trace_msg->katom = MALI_FALSE; + } else { + trace_msg->katom = MALI_TRUE; + trace_msg->atom_number = kbase_jd_atom_id(katom->kctx, katom); + trace_msg->atom_udata[0] = katom->udata.blob[0]; + trace_msg->atom_udata[1] = katom->udata.blob[1]; + } + + trace_msg->gpu_addr = gpu_addr; + trace_msg->jobslot = jobslot; + trace_msg->refcount = MIN((unsigned int)refcount, 0xFF); + trace_msg->info_val = info_val; + trace_msg->flags = flags; + + /* Update the ringbuffer indices */ + kbdev->trace_next_in = (kbdev->trace_next_in + 1) & KBASE_TRACE_MASK; + if (kbdev->trace_next_in == kbdev->trace_first_out) + kbdev->trace_first_out = (kbdev->trace_first_out + 1) & KBASE_TRACE_MASK; + + /* Done */ + + spin_unlock_irqrestore(&kbdev->trace_lock, irqflags); +} + +void kbasep_trace_clear(struct kbase_device *kbdev) +{ + unsigned long flags; + spin_lock_irqsave(&kbdev->trace_lock, flags); + kbdev->trace_first_out = kbdev->trace_next_in; + spin_unlock_irqrestore(&kbdev->trace_lock, flags); +} + +void kbasep_trace_dump(struct kbase_device *kbdev) +{ + unsigned long flags; + u32 start; + u32 end; + + dev_dbg(kbdev->dev, "Dumping trace:\nsecs,nthread,cpu,code,ctx,katom,gpu_addr,jobslot,refcount,info_val"); + spin_lock_irqsave(&kbdev->trace_lock, flags); + start = kbdev->trace_first_out; + end = kbdev->trace_next_in; + + while (start != end) { + struct kbase_trace *trace_msg = &kbdev->trace_rbuf[start]; + kbasep_trace_dump_msg(kbdev, trace_msg); + + start = (start + 1) & KBASE_TRACE_MASK; + } + dev_dbg(kbdev->dev, "TRACE_END"); + + spin_unlock_irqrestore(&kbdev->trace_lock, flags); + + KBASE_TRACE_CLEAR(kbdev); +} + +STATIC void kbasep_trace_hook_wrapper(void *param) +{ + struct kbase_device *kbdev = (struct kbase_device *)param; + kbasep_trace_dump(kbdev); +} + +#ifdef CONFIG_DEBUG_FS +struct trace_seq_state { + struct kbase_trace trace_buf[KBASE_TRACE_SIZE]; + u32 start; + u32 end; +}; + +static void *kbasep_trace_seq_start(struct seq_file *s, loff_t *pos) +{ + struct trace_seq_state *state = s->private; + int i; + + if (*pos > KBASE_TRACE_SIZE) + return NULL; + i = state->start + *pos; + if ((state->end >= state->start && i >= state->end) || + i >= state->end + KBASE_TRACE_SIZE) + return NULL; + + i &= KBASE_TRACE_MASK; + + return &state->trace_buf[i]; +} + +static void kbasep_trace_seq_stop(struct seq_file *s, void *data) +{ +} + +static void *kbasep_trace_seq_next(struct seq_file *s, void *data, loff_t *pos) +{ + struct trace_seq_state *state = s->private; + int i; + + (*pos)++; + + i = (state->start + *pos) & KBASE_TRACE_MASK; + if (i == state->end) + return NULL; + + return &state->trace_buf[i]; +} + +static int kbasep_trace_seq_show(struct seq_file *s, void *data) +{ + struct kbase_trace *trace_msg = data; + char buffer[DEBUG_MESSAGE_SIZE]; + + kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE); + seq_printf(s, "%s\n", buffer); + return 0; +} + +static const struct seq_operations kbasep_trace_seq_ops = { + .start = kbasep_trace_seq_start, + .next = kbasep_trace_seq_next, + .stop = kbasep_trace_seq_stop, + .show = kbasep_trace_seq_show, +}; + +static int kbasep_trace_debugfs_open(struct inode *inode, struct file *file) +{ + struct kbase_device *kbdev = inode->i_private; + unsigned long flags; + + struct trace_seq_state *state; + + state = __seq_open_private(file, &kbasep_trace_seq_ops, sizeof(*state)); + if (!state) + return -ENOMEM; + + spin_lock_irqsave(&kbdev->trace_lock, flags); + state->start = kbdev->trace_first_out; + state->end = kbdev->trace_next_in; + memcpy(state->trace_buf, kbdev->trace_rbuf, sizeof(state->trace_buf)); + spin_unlock_irqrestore(&kbdev->trace_lock, flags); + + return 0; +} + +static const struct file_operations kbasep_trace_debugfs_fops = { + .open = kbasep_trace_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +STATIC void kbasep_trace_debugfs_init(struct kbase_device *kbdev) +{ + kbdev->trace_dentry = debugfs_create_file("mali_trace", S_IRUGO, + kbdev->mali_debugfs_directory, kbdev, + &kbasep_trace_debugfs_fops); +} + +STATIC void kbasep_trace_debugfs_term(struct kbase_device *kbdev) +{ + debugfs_remove(kbdev->trace_dentry); + kbdev->trace_dentry = NULL; +} +#else +STATIC void kbasep_trace_debugfs_init(struct kbase_device *kbdev) +{ + +} +STATIC void kbasep_trace_debugfs_term(struct kbase_device *kbdev) +{ + +} +#endif /* CONFIG_DEBUG_FS */ + +#else /* KBASE_TRACE_ENABLE */ +STATIC mali_error kbasep_trace_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); + return MALI_ERROR_NONE; +} + +STATIC void kbasep_trace_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +STATIC void kbasep_trace_hook_wrapper(void *param) +{ + CSTD_UNUSED(param); +} + +void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(code); + CSTD_UNUSED(ctx); + CSTD_UNUSED(katom); + CSTD_UNUSED(gpu_addr); + CSTD_UNUSED(flags); + CSTD_UNUSED(refcount); + CSTD_UNUSED(jobslot); + CSTD_UNUSED(info_val); +} + +void kbasep_trace_clear(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbasep_trace_dump(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} +#endif /* KBASE_TRACE_ENABLE */ + +void kbase_set_profiling_control(struct kbase_device *kbdev, u32 control, u32 value) +{ + switch (control) { + case FBDUMP_CONTROL_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RATE: + /* fall through */ + case SW_COUNTER_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RESIZE_FACTOR: + kbdev->kbase_profiling_controls[control] = value; + break; + default: + dev_err(kbdev->dev, "Profiling control %d not found\n", control); + break; + } +} + +u32 kbase_get_profiling_control(struct kbase_device *kbdev, u32 control) +{ + u32 ret_value = 0; + + switch (control) { + case FBDUMP_CONTROL_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RATE: + /* fall through */ + case SW_COUNTER_ENABLE: + /* fall through */ + case FBDUMP_CONTROL_RESIZE_FACTOR: + ret_value = kbdev->kbase_profiling_controls[control]; + break; + default: + dev_err(kbdev->dev, "Profiling control %d not found\n", control); + break; + } + + return ret_value; +} + +/* + * Called by gator to control the production of + * profiling information at runtime + * */ + +void _mali_profiling_control(u32 action, u32 value) +{ + struct kbase_device *kbdev = NULL; + + /* find the first i.e. call with -1 */ + kbdev = kbase_find_device(-1); + + if (NULL != kbdev) { + kbase_set_profiling_control(kbdev, action, value); + } +} + +KBASE_EXPORT_SYMBOL(_mali_profiling_control); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c new file mode 100644 index 0000000000000000000000000000000000000000..22b62277cc924e8bbc70e948cd942bb68e5d9133 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c @@ -0,0 +1,77 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_disjoint_events.c + * Base kernel disjoint events helper functions + */ + +#include + +void kbase_disjoint_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_set(&kbdev->disjoint_event.count, 0); + atomic_set(&kbdev->disjoint_event.state, 0); +} + +/* increment the disjoint event count */ +void kbase_disjoint_event(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_inc(&kbdev->disjoint_event.count); +} + +/* increment the state and the event counter */ +void kbase_disjoint_state_up(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + atomic_inc(&kbdev->disjoint_event.state); + + kbase_disjoint_event(kbdev); +} + +/* decrement the state */ +void kbase_disjoint_state_down(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->disjoint_event.state) > 0); + + kbase_disjoint_event(kbdev); + + atomic_dec(&kbdev->disjoint_event.state); +} + +/* increments the count only if the state is > 0 */ +void kbase_disjoint_event_potential(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + if (atomic_read(&kbdev->disjoint_event.state)) + kbase_disjoint_event(kbdev); +} + +u32 kbase_disjoint_event_get(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return atomic_read(&kbdev->disjoint_event.count); +} +KBASE_EXPORT_TEST_API(kbase_disjoint_event_get) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_event.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_event.c new file mode 100644 index 0000000000000000000000000000000000000000..27312ca7a1252713723bf90af3af08018863099f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_event.c @@ -0,0 +1,186 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include + +STATIC struct base_jd_udata kbase_event_process(struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct base_jd_udata data; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED); + + data = katom->udata; + + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_sub_return(1, &kctx->timeline.jd_atoms_in_flight)); + + mutex_lock(&kctx->jctx.lock); + katom->status = KBASE_JD_ATOM_STATE_UNUSED; + mutex_unlock(&kctx->jctx.lock); + + wake_up(&katom->completed); + + return data; +} + +int kbase_event_pending(struct kbase_context *ctx) +{ + int ret; + + KBASE_DEBUG_ASSERT(ctx); + + mutex_lock(&ctx->event_mutex); + ret = (!list_empty(&ctx->event_list)) || (MALI_TRUE == ctx->event_closed); + mutex_unlock(&ctx->event_mutex); + + return ret; +} + +KBASE_EXPORT_TEST_API(kbase_event_pending) + +int kbase_event_dequeue(struct kbase_context *ctx, struct base_jd_event_v2 *uevent) +{ + struct kbase_jd_atom *atom; + + KBASE_DEBUG_ASSERT(ctx); + + mutex_lock(&ctx->event_mutex); + + if (list_empty(&ctx->event_list)) { + if (ctx->event_closed) { + /* generate the BASE_JD_EVENT_DRV_TERMINATED message on the fly */ + mutex_unlock(&ctx->event_mutex); + uevent->event_code = BASE_JD_EVENT_DRV_TERMINATED; + memset(&uevent->udata, 0, sizeof(uevent->udata)); + dev_dbg(ctx->kbdev->dev, + "event system closed, returning BASE_JD_EVENT_DRV_TERMINATED(0x%X)\n", + BASE_JD_EVENT_DRV_TERMINATED); + return 0; + } else { + mutex_unlock(&ctx->event_mutex); + return -1; + } + } + + /* normal event processing */ + atom = list_entry(ctx->event_list.next, struct kbase_jd_atom, dep_item[0]); + list_del(ctx->event_list.next); + + mutex_unlock(&ctx->event_mutex); + + dev_dbg(ctx->kbdev->dev, "event dequeuing %p\n", (void *)atom); + uevent->event_code = atom->event_code; + uevent->atom_number = (atom - ctx->jctx.atoms); + uevent->udata = kbase_event_process(ctx, atom); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_event_dequeue) + +static void kbase_event_post_worker(struct work_struct *data) +{ + struct kbase_jd_atom *atom = container_of(data, struct kbase_jd_atom, work); + struct kbase_context *ctx = atom->kctx; + + if (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) + kbase_jd_free_external_resources(atom); + + if (atom->core_req & BASE_JD_REQ_EVENT_ONLY_ON_FAILURE) { + if (atom->event_code == BASE_JD_EVENT_DONE) { + /* Don't report the event */ + kbase_event_process(ctx, atom); + return; + } + } + + if (atom->core_req & BASEP_JD_REQ_EVENT_NEVER) { + /* Don't report the event */ + kbase_event_process(ctx, atom); + return; + } + + mutex_lock(&ctx->event_mutex); + list_add_tail(&atom->dep_item[0], &ctx->event_list); + mutex_unlock(&ctx->event_mutex); + + kbase_event_wakeup(ctx); +} + +void kbase_event_post(struct kbase_context *ctx, struct kbase_jd_atom *atom) +{ + KBASE_DEBUG_ASSERT(ctx); + KBASE_DEBUG_ASSERT(ctx->event_workq); + KBASE_DEBUG_ASSERT(atom); + + INIT_WORK(&atom->work, kbase_event_post_worker); + queue_work(ctx->event_workq, &atom->work); +} + +KBASE_EXPORT_TEST_API(kbase_event_post) + +void kbase_event_close(struct kbase_context *kctx) +{ + mutex_lock(&kctx->event_mutex); + kctx->event_closed = MALI_TRUE; + mutex_unlock(&kctx->event_mutex); + kbase_event_wakeup(kctx); +} + +mali_error kbase_event_init(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + + INIT_LIST_HEAD(&kctx->event_list); + mutex_init(&kctx->event_mutex); + kctx->event_closed = MALI_FALSE; + kctx->event_workq = alloc_workqueue("kbase_event", WQ_MEM_RECLAIM, 1); + + if (NULL == kctx->event_workq) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_event_init) + +void kbase_event_cleanup(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(kctx->event_workq); + + flush_workqueue(kctx->event_workq); + destroy_workqueue(kctx->event_workq); + + /* We use kbase_event_dequeue to remove the remaining events as that + * deals with all the cleanup needed for the atoms. + * + * Note: use of kctx->event_list without a lock is safe because this must be the last + * thread using it (because we're about to terminate the lock) + */ + while (!list_empty(&kctx->event_list)) { + struct base_jd_event_v2 event; + + kbase_event_dequeue(kctx, &event); + } +} + +KBASE_EXPORT_TEST_API(kbase_event_cleanup) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator.h new file mode 100644 index 0000000000000000000000000000000000000000..30a52efcd3a8ba8c5be802c83cdd9231ea3ab60b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator.h @@ -0,0 +1,45 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/* NB taken from gator */ +/* + * List of possible actions to be controlled by DS-5 Streamline. + * The following numbers are used by gator to control the frame buffer dumping + * and s/w counter reporting. We cannot use the enums in mali_uk_types.h because + * they are unknown inside gator. + */ +#ifndef _KBASE_GATOR_H_ +#define _KBASE_GATOR_H_ + +#ifdef CONFIG_MALI_GATOR_SUPPORT +#define GATOR_MAKE_EVENT(type, number) (((type) << 24) | ((number) << 16)) +#define GATOR_JOB_SLOT_START 1 +#define GATOR_JOB_SLOT_STOP 2 +#define GATOR_JOB_SLOT_SOFT_STOPPED 3 + +void kbase_trace_mali_job_slots_event(u32 event, const struct kbase_context *kctx, u8 atom_id); +void kbase_trace_mali_pm_status(u32 event, u64 value); +void kbase_trace_mali_pm_power_off(u32 event, u64 value); +void kbase_trace_mali_pm_power_on(u32 event, u64 value); +void kbase_trace_mali_page_fault_insert_pages(int event, u32 value); +void kbase_trace_mali_mmu_as_in_use(int event); +void kbase_trace_mali_mmu_as_released(int event); +void kbase_trace_mali_total_alloc_pages_change(long long int event); + +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + +#endif /* _KBASE_GATOR_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.c new file mode 100644 index 0000000000000000000000000000000000000000..c4329a44522f1165efa613179524cab23adabb11 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.c @@ -0,0 +1,311 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include "mali_kbase.h" +#include "mali_kbase_mem_linux.h" +#include "mali_kbase_gator_api.h" +#include "mali_kbase_gator_hwcnt_names.h" + +#define MALI_MAX_CORES_PER_GROUP 4 +#define MALI_MAX_NUM_BLOCKS_PER_GROUP 8 +#define MALI_COUNTERS_PER_BLOCK 64 +#define MALI_BYTES_PER_COUNTER 4 + +struct kbase_gator_hwcnt_handles { + struct kbase_device *kbdev; + struct kbase_context *kctx; + mali_addr64 hwcnt_gpu_va; + void *hwcnt_cpu_va; + struct kbase_vmap_struct hwcnt_map; +}; + +const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters) +{ + uint32_t gpu_id; + const char * const *hardware_counters; + struct kbase_device *kbdev; + + if (!total_counters) + return NULL; + + /* Get the first device - it doesn't matter in this case */ + kbdev = kbase_find_device(-1); + if (!kbdev) + return NULL; + + gpu_id = kbdev->gpu_props.props.core_props.product_id; + + switch (gpu_id) { + /* If we are using a Mali-T60x device */ + case GPU_ID_PI_T60X: + hardware_counters = hardware_counters_mali_t60x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t60x); + break; + /* If we are using a Mali-T62x device */ + case GPU_ID_PI_T62X: + hardware_counters = hardware_counters_mali_t62x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t62x); + break; + /* If we are using a Mali-T72x device */ + case GPU_ID_PI_T72X: + hardware_counters = hardware_counters_mali_t72x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t72x); + break; + /* If we are using a Mali-T76x device */ + case GPU_ID_PI_T76X: + hardware_counters = hardware_counters_mali_t76x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t76x); + break; + /* If we are using a Mali-T86x device */ + case GPU_ID_PI_T86X: + hardware_counters = hardware_counters_mali_t86x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t86x); + break; + /* If we are using a Mali-T88x device */ + case GPU_ID_PI_TFRX: + hardware_counters = hardware_counters_mali_t88x; + *total_counters = ARRAY_SIZE(hardware_counters_mali_t88x); + break; + default: + hardware_counters = NULL; + *total_counters = 0; + dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n", gpu_id); + break; + } + + /* Release the kbdev reference. */ + kbase_release_device(kbdev); + + /* If we return a string array take a reference on the module (or fail). */ + if (hardware_counters && !try_module_get(THIS_MODULE)) + return NULL; + + return hardware_counters; +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init_names) + +void kbase_gator_hwcnt_term_names(void) +{ + /* Release the module reference. */ + module_put(THIS_MODULE); +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term_names) + +struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info) +{ + struct kbase_gator_hwcnt_handles *hand; + struct kbase_uk_hwcnt_setup setup; + mali_error err; + uint32_t dump_size = 0, i = 0; + struct kbase_va_region *reg; + u64 flags; + u64 nr_pages; + u16 va_alignment = 0; + + if (!in_out_info) + return NULL; + + hand = kzalloc(sizeof(*hand), GFP_KERNEL); + if (!hand) + return NULL; + + /* Get the first device */ + hand->kbdev = kbase_find_device(-1); + if (!hand->kbdev) + goto free_hand; + + /* Create a kbase_context */ + hand->kctx = kbase_create_context(hand->kbdev, true); + if (!hand->kctx) + goto release_device; + + in_out_info->nr_cores = hand->kbdev->gpu_props.num_cores; + in_out_info->nr_core_groups = hand->kbdev->gpu_props.num_core_groups; + in_out_info->gpu_id = hand->kbdev->gpu_props.props.core_props.product_id; + + /* If we are using a Mali-T6xx or Mali-T72x device */ + if (in_out_info->gpu_id == GPU_ID_PI_T60X || + in_out_info->gpu_id == GPU_ID_PI_T62X || + in_out_info->gpu_id == GPU_ID_PI_T72X) { + uint32_t cg, j; + uint64_t core_mask; + + /* There are 8 hardware counters blocks per core group */ + in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * + MALI_MAX_NUM_BLOCKS_PER_GROUP * + in_out_info->nr_core_groups, GFP_KERNEL); + + if (!in_out_info->hwc_layout) + goto destroy_context; + + dump_size = in_out_info->nr_core_groups * + MALI_MAX_NUM_BLOCKS_PER_GROUP * + MALI_COUNTERS_PER_BLOCK * + MALI_BYTES_PER_COUNTER; + + for (cg = 0; cg < in_out_info->nr_core_groups; cg++) { + core_mask = hand->kbdev->gpu_props.props.coherency_info.group[cg].core_mask; + + for (j = 0; j < MALI_MAX_CORES_PER_GROUP; j++) { + if (core_mask & (1u << j)) + in_out_info->hwc_layout[i++] = SHADER_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + } + + in_out_info->hwc_layout[i++] = TILER_BLOCK; + in_out_info->hwc_layout[i++] = MMU_L2_BLOCK; + + /* There are no implementation with L3 cache */ + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + + if (0 == cg) + in_out_info->hwc_layout[i++] = JM_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + } + /* If we are using a Mali-T76x device */ + } else if ( + (in_out_info->gpu_id == GPU_ID_PI_T76X) + || (in_out_info->gpu_id == GPU_ID_PI_TFRX) + || (in_out_info->gpu_id == GPU_ID_PI_T86X) +#ifdef MALI_INCLUDE_TGAL + || (in_out_info->gpu_id == GPU_ID_PI_TGAL) +#endif + ) { + uint32_t nr_l2, nr_sc, j; + uint64_t core_mask; + + nr_l2 = hand->kbdev->gpu_props.props.l2_props.num_l2_slices; + + core_mask = hand->kbdev->gpu_props.props.coherency_info.group[0].core_mask; + + nr_sc = hand->kbdev->gpu_props.props.coherency_info.group[0].num_cores; + + /* For Mali-T76x, the job manager and tiler sets of counters are always present */ + in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc + nr_l2), GFP_KERNEL); + + if (!in_out_info->hwc_layout) + goto destroy_context; + + dump_size = (2 + nr_sc + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER; + + in_out_info->hwc_layout[i++] = JM_BLOCK; + in_out_info->hwc_layout[i++] = TILER_BLOCK; + + for (j = 0; j < nr_l2; j++) + in_out_info->hwc_layout[i++] = MMU_L2_BLOCK; + + while (core_mask != 0ull) { + if ((core_mask & 1ull) != 0ull) + in_out_info->hwc_layout[i++] = SHADER_BLOCK; + else + in_out_info->hwc_layout[i++] = RESERVED_BLOCK; + core_mask >>= 1; + } + } + + in_out_info->nr_hwc_blocks = i; + + in_out_info->size = dump_size; + + flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_WR; + nr_pages = PFN_UP(dump_size); + reg = kbase_mem_alloc(hand->kctx, nr_pages, nr_pages, 0, + &flags, &hand->hwcnt_gpu_va, &va_alignment); + if (!reg) + goto free_layout; + + hand->hwcnt_cpu_va = kbase_vmap(hand->kctx, hand->hwcnt_gpu_va, + dump_size, &hand->hwcnt_map); + + if (!hand->hwcnt_cpu_va) + goto free_buffer; + + in_out_info->kernel_dump_buffer = hand->hwcnt_cpu_va; + + /*setup.dump_buffer = (uintptr_t)in_out_info->kernel_dump_buffer;*/ + setup.dump_buffer = hand->hwcnt_gpu_va; + setup.jm_bm = in_out_info->bitmask[0]; + setup.tiler_bm = in_out_info->bitmask[1]; + setup.shader_bm = in_out_info->bitmask[2]; + setup.mmu_l2_bm = in_out_info->bitmask[3]; + + /* There are no implementations with L3 cache */ + setup.l3_cache_bm = 0; + + err = kbase_instr_hwcnt_enable(hand->kctx, &setup); + if (err != MALI_ERROR_NONE) + goto free_unmap; + + kbase_instr_hwcnt_clear(hand->kctx); + + return hand; + +free_unmap: + kbase_vunmap(hand->kctx, &hand->hwcnt_map); + +free_buffer: + kbase_mem_free(hand->kctx, hand->hwcnt_gpu_va); + +free_layout: + kfree(in_out_info->hwc_layout); + +destroy_context: + kbase_destroy_context(hand->kctx); + +release_device: + kbase_release_device(hand->kbdev); + +free_hand: + kfree(hand); + + return NULL; +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init) + +void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles) +{ + if (in_out_info) + kfree(in_out_info->hwc_layout); + + if (opaque_handles) { + kbase_instr_hwcnt_disable(opaque_handles->kctx); + kbase_vunmap(opaque_handles->kctx, &opaque_handles->hwcnt_map); + kbase_mem_free(opaque_handles->kctx, opaque_handles->hwcnt_gpu_va); + kbase_destroy_context(opaque_handles->kctx); + kbase_release_device(opaque_handles->kbdev); + kfree(opaque_handles); + } +} +KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term) + +uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success) +{ + if (opaque_handles && success) + return (kbase_instr_hwcnt_dump_complete(opaque_handles->kctx, success) != 0); + return 0; +} +KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_complete) + +uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles) +{ + if (opaque_handles) + return (kbase_instr_hwcnt_dump_irq(opaque_handles->kctx) == MALI_ERROR_NONE); + return 0; +} +KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_irq) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.h new file mode 100644 index 0000000000000000000000000000000000000000..6941ce5400059e105b8a581c02b10d5df711712e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_api.h @@ -0,0 +1,220 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_GATOR_API_H_ +#define _KBASE_GATOR_API_H_ + +/** + * @brief This file describes the API used by Gator to fetch hardware counters. + */ + +/* This define is used by the gator kernel module compile to select which DDK + * API calling convention to use. If not defined (legacy DDK) gator assumes + * version 1. The version to DDK release mapping is: + * Version 1 API: DDK versions r1px, r2px + * Version 2 API: DDK versions r3px, r4px + * Version 3 API: DDK version r5p0 and newer + * + * API Usage + * ========= + * + * 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter + * names for the GPU present in this device. + * + * 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for + * the counters you want enabled. The enables can all be set for simplicity in + * most use cases, but disabling some will let you minimize bandwidth impact. + * + * 3] Call kbase_gator_hwcnt_init() using the above structure, to create a + * counter context. On successful return the DDK will have populated the + * structure with a variety of useful information. + * + * 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a + * counter dump. If this returns a non-zero value the request has been queued, + * otherwise the driver has been unable to do so (typically because of another + * user of the instrumentation exists concurrently). + * + * 5] Call kbase_gator_hwcnt_dump_complete() to test whether the previously + * requested dump has been succesful. If this returns non-zero the counter dump + * has resolved, but the value of *success must also be tested as the dump + * may have not been successful. If it returns zero the counter dump was + * abandoned due to the device being busy (typically because of another + * user of the instrumentation exists concurrently). + * + * 6] Process the counters stored in the buffer pointed to by ... + * + * kbase_gator_hwcnt_info->kernel_dump_buffer + * + * In pseudo code you can find all of the counters via this approach: + * + * + * hwcnt_info # pointer to kbase_gator_hwcnt_info structure + * hwcnt_name # pointer to name list + * + * u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer + * + * # Iterate over each 64-counter block in this GPU configuration + * for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) { + * hwc_type type = hwcnt_info->hwc_layout[i]; + * + * # Skip reserved type blocks - they contain no counters at all + * if( type == RESERVED_BLOCK ) { + * continue; + * } + * + * size_t name_offset = type * 64; + * size_t data_offset = i * 64; + * + * # Iterate over the names of the counters in this block type + * for( j = 0; j < 64; j++) { + * const char * name = hwcnt_name[name_offset+j]; + * + * # Skip empty name strings - there is no counter here + * if( name[0] == '\0' ) { + * continue; + * } + * + * u32 data = hwcnt_data[data_offset+j]; + * + * pr_debug( "COUNTER: %s DATA: %u\n", name, data ); + * } + * } + * + * + * Note that in most implementations you typically want to either SUM or + * AVERAGE multiple instances of the same counter if, for example, you have + * multiple shader cores or multiple L2 caches. The most sensible view for + * analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU + * counters. + * + * 7] Goto 4, repeating until you want to stop collecting counters. + * + * 8] Release the dump resources by calling kbase_gator_hwcnt_term(). + * + * 9] Release the name table resources by calling + * kbase_gator_hwcnt_term_names(). This function must only be called if + * init_names() returned a non-NULL value. + **/ + +#define MALI_DDK_GATOR_API_VERSION 3 + +enum hwc_type { + JM_BLOCK = 0, + TILER_BLOCK, + SHADER_BLOCK, + MMU_L2_BLOCK, + RESERVED_BLOCK +}; + +struct kbase_gator_hwcnt_info { + + /* Passed from Gator to kbase */ + + /* the bitmask of enabled hardware counters for each counter block */ + uint16_t bitmask[4]; + + /* Passed from kbase to Gator */ + + /* ptr to counter dump memory */ + void *kernel_dump_buffer; + + /* size of counter dump memory */ + uint32_t size; + + /* the ID of the Mali device */ + uint32_t gpu_id; + + /* the number of shader cores in the GPU */ + uint32_t nr_cores; + + /* the number of core groups */ + uint32_t nr_core_groups; + + /* the memory layout of the performance counters */ + enum hwc_type *hwc_layout; + + /* the total number of hardware couter blocks */ + uint32_t nr_hwc_blocks; +}; + +/** + * @brief Opaque block of Mali data which Gator needs to return to the API later. + */ +struct kbase_gator_hwcnt_handles; + +/** + * @brief Initialize the resources Gator needs for performance profiling. + * + * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the Mali + * specific information that will be returned to Gator. On entry Gator must have populated the + * 'bitmask' field with the counters it wishes to enable for each class of counter block. + * Each entry in the array corresponds to a single counter class based on the "hwc_type" + * enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables + * the first 4 counters in the block, and so on). See the GPU counter array as returned by + * kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU. + * + * @return Pointer to an opaque handle block on success, NULL on error. + */ +extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info); + +/** + * @brief Free all resources once Gator has finished using performance counters. + * + * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the + * Mali specific information that will be returned to Gator. + * @param opaque_handles A wrapper structure for kbase structures. + */ +extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles); + +/** + * @brief Poll whether a counter dump is successful. + * + * @param opaque_handles A wrapper structure for kbase structures. + * @param[out] success Non-zero on success, zero on failure. + * + * @return Zero if the dump is still pending, non-zero if the dump has completed. Note that a + * completed dump may not have dumped succesfully, so the caller must test for both + * a completed and successful dump before processing counters. + */ +extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success); + +/** + * @brief Request the generation of a new counter dump. + * + * @param opaque_handles A wrapper structure for kbase structures. + * + * @return Zero if the hardware device is busy and cannot handle the request, non-zero otherwise. + */ +extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles); + +/** + * @brief This function is used to fetch the names table based on the Mali device in use. + * + * @param[out] total_counters The total number of counters short names in the Mali devices' list. + * + * @return Pointer to an array of strings of length *total_counters. + */ +extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters); + +/** + * @brief This function is used to terminate the use of the names table. + * + * This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value. + */ +extern void kbase_gator_hwcnt_term_names(void); + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_hwcnt_names.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_hwcnt_names.h new file mode 100644 index 0000000000000000000000000000000000000000..c68daab5873e4bdb6bd8f48225e9a48e3510a252 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gator_hwcnt_names.h @@ -0,0 +1,1627 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_GATOR_HWCNT_NAMES_H_ +#define _KBASE_GATOR_HWCNT_NAMES_H_ + +/* + * "Short names" for hardware counters used by Streamline. Counters names are + * stored in accordance with their memory layout in the binary counter block + * emitted by the Mali GPU. Each "master" in the GPU emits a fixed-size block + * of 64 counters, and each GPU implements the same set of "masters" although + * the counters each master exposes within its block of 64 may vary. + * + * Counters which are an empty string are simply "holes" in the counter memory + * where no counter exists. + */ + +static const char * const hardware_counters_mali_t60x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T60x_MESSAGES_SENT", + "T60x_MESSAGES_RECEIVED", + "T60x_GPU_ACTIVE", + "T60x_IRQ_ACTIVE", + "T60x_JS0_JOBS", + "T60x_JS0_TASKS", + "T60x_JS0_ACTIVE", + "", + "T60x_JS0_WAIT_READ", + "T60x_JS0_WAIT_ISSUE", + "T60x_JS0_WAIT_DEPEND", + "T60x_JS0_WAIT_FINISH", + "T60x_JS1_JOBS", + "T60x_JS1_TASKS", + "T60x_JS1_ACTIVE", + "", + "T60x_JS1_WAIT_READ", + "T60x_JS1_WAIT_ISSUE", + "T60x_JS1_WAIT_DEPEND", + "T60x_JS1_WAIT_FINISH", + "T60x_JS2_JOBS", + "T60x_JS2_TASKS", + "T60x_JS2_ACTIVE", + "", + "T60x_JS2_WAIT_READ", + "T60x_JS2_WAIT_ISSUE", + "T60x_JS2_WAIT_DEPEND", + "T60x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T60x_TI_JOBS_PROCESSED", + "T60x_TI_TRIANGLES", + "T60x_TI_QUADS", + "T60x_TI_POLYGONS", + "T60x_TI_POINTS", + "T60x_TI_LINES", + "T60x_TI_VCACHE_HIT", + "T60x_TI_VCACHE_MISS", + "T60x_TI_FRONT_FACING", + "T60x_TI_BACK_FACING", + "T60x_TI_PRIM_VISIBLE", + "T60x_TI_PRIM_CULLED", + "T60x_TI_PRIM_CLIPPED", + "T60x_TI_LEVEL0", + "T60x_TI_LEVEL1", + "T60x_TI_LEVEL2", + "T60x_TI_LEVEL3", + "T60x_TI_LEVEL4", + "T60x_TI_LEVEL5", + "T60x_TI_LEVEL6", + "T60x_TI_LEVEL7", + "T60x_TI_COMMAND_1", + "T60x_TI_COMMAND_2", + "T60x_TI_COMMAND_3", + "T60x_TI_COMMAND_4", + "T60x_TI_COMMAND_4_7", + "T60x_TI_COMMAND_8_15", + "T60x_TI_COMMAND_16_63", + "T60x_TI_COMMAND_64", + "T60x_TI_COMPRESS_IN", + "T60x_TI_COMPRESS_OUT", + "T60x_TI_COMPRESS_FLUSH", + "T60x_TI_TIMESTAMPS", + "T60x_TI_PCACHE_HIT", + "T60x_TI_PCACHE_MISS", + "T60x_TI_PCACHE_LINE", + "T60x_TI_PCACHE_STALL", + "T60x_TI_WRBUF_HIT", + "T60x_TI_WRBUF_MISS", + "T60x_TI_WRBUF_LINE", + "T60x_TI_WRBUF_PARTIAL", + "T60x_TI_WRBUF_STALL", + "T60x_TI_ACTIVE", + "T60x_TI_LOADING_DESC", + "T60x_TI_INDEX_WAIT", + "T60x_TI_INDEX_RANGE_WAIT", + "T60x_TI_VERTEX_WAIT", + "T60x_TI_PCACHE_WAIT", + "T60x_TI_WRBUF_WAIT", + "T60x_TI_BUS_READ", + "T60x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T60x_TI_UTLB_STALL", + "T60x_TI_UTLB_REPLAY_MISS", + "T60x_TI_UTLB_REPLAY_FULL", + "T60x_TI_UTLB_NEW_MISS", + "T60x_TI_UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "", + "T60x_FRAG_ACTIVE", + "T60x_FRAG_PRIMITIVES", + "T60x_FRAG_PRIMITIVES_DROPPED", + "T60x_FRAG_CYCLES_DESC", + "T60x_FRAG_CYCLES_PLR", + "T60x_FRAG_CYCLES_VERT", + "T60x_FRAG_CYCLES_TRISETUP", + "T60x_FRAG_CYCLES_RAST", + "T60x_FRAG_THREADS", + "T60x_FRAG_DUMMY_THREADS", + "T60x_FRAG_QUADS_RAST", + "T60x_FRAG_QUADS_EZS_TEST", + "T60x_FRAG_QUADS_EZS_KILLED", + "T60x_FRAG_THREADS_LZS_TEST", + "T60x_FRAG_THREADS_LZS_KILLED", + "T60x_FRAG_CYCLES_NO_TILE", + "T60x_FRAG_NUM_TILES", + "T60x_FRAG_TRANS_ELIM", + "T60x_COMPUTE_ACTIVE", + "T60x_COMPUTE_TASKS", + "T60x_COMPUTE_THREADS", + "T60x_COMPUTE_CYCLES_DESC", + "T60x_TRIPIPE_ACTIVE", + "T60x_ARITH_WORDS", + "T60x_ARITH_CYCLES_REG", + "T60x_ARITH_CYCLES_L0", + "T60x_ARITH_FRAG_DEPEND", + "T60x_LS_WORDS", + "T60x_LS_ISSUES", + "T60x_LS_RESTARTS", + "T60x_LS_REISSUES_MISS", + "T60x_LS_REISSUES_VD", + "T60x_LS_REISSUE_ATTRIB_MISS", + "T60x_LS_NO_WB", + "T60x_TEX_WORDS", + "T60x_TEX_BUBBLES", + "T60x_TEX_WORDS_L0", + "T60x_TEX_WORDS_DESC", + "T60x_TEX_ISSUES", + "T60x_TEX_RECIRC_FMISS", + "T60x_TEX_RECIRC_DESC", + "T60x_TEX_RECIRC_MULTI", + "T60x_TEX_RECIRC_PMISS", + "T60x_TEX_RECIRC_CONF", + "T60x_LSC_READ_HITS", + "T60x_LSC_READ_MISSES", + "T60x_LSC_WRITE_HITS", + "T60x_LSC_WRITE_MISSES", + "T60x_LSC_ATOMIC_HITS", + "T60x_LSC_ATOMIC_MISSES", + "T60x_LSC_LINE_FETCHES", + "T60x_LSC_DIRTY_LINE", + "T60x_LSC_SNOOPS", + "T60x_AXI_TLB_STALL", + "T60x_AXI_TLB_MIESS", + "T60x_AXI_TLB_TRANSACTION", + "T60x_LS_TLB_MISS", + "T60x_LS_TLB_HIT", + "T60x_AXI_BEATS_READ", + "T60x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T60x_MMU_HIT", + "T60x_MMU_NEW_MISS", + "T60x_MMU_REPLAY_FULL", + "T60x_MMU_REPLAY_MISS", + "T60x_MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "T60x_UTLB_HIT", + "T60x_UTLB_NEW_MISS", + "T60x_UTLB_REPLAY_FULL", + "T60x_UTLB_REPLAY_MISS", + "T60x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T60x_L2_EXT_WRITE_BEATS", + "T60x_L2_EXT_READ_BEATS", + "T60x_L2_ANY_LOOKUP", + "T60x_L2_READ_LOOKUP", + "T60x_L2_SREAD_LOOKUP", + "T60x_L2_READ_REPLAY", + "T60x_L2_READ_SNOOP", + "T60x_L2_READ_HIT", + "T60x_L2_CLEAN_MISS", + "T60x_L2_WRITE_LOOKUP", + "T60x_L2_SWRITE_LOOKUP", + "T60x_L2_WRITE_REPLAY", + "T60x_L2_WRITE_SNOOP", + "T60x_L2_WRITE_HIT", + "T60x_L2_EXT_READ_FULL", + "T60x_L2_EXT_READ_HALF", + "T60x_L2_EXT_WRITE_FULL", + "T60x_L2_EXT_WRITE_HALF", + "T60x_L2_EXT_READ", + "T60x_L2_EXT_READ_LINE", + "T60x_L2_EXT_WRITE", + "T60x_L2_EXT_WRITE_LINE", + "T60x_L2_EXT_WRITE_SMALL", + "T60x_L2_EXT_BARRIER", + "T60x_L2_EXT_AR_STALL", + "T60x_L2_EXT_R_BUF_FULL", + "T60x_L2_EXT_RD_BUF_FULL", + "T60x_L2_EXT_R_RAW", + "T60x_L2_EXT_W_STALL", + "T60x_L2_EXT_W_BUF_FULL", + "T60x_L2_EXT_R_W_HAZARD", + "T60x_L2_TAG_HAZARD", + "T60x_L2_SNOOP_FULL", + "T60x_L2_REPLAY_FULL" +}; +static const char * const hardware_counters_mali_t62x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T62x_MESSAGES_SENT", + "T62x_MESSAGES_RECEIVED", + "T62x_GPU_ACTIVE", + "T62x_IRQ_ACTIVE", + "T62x_JS0_JOBS", + "T62x_JS0_TASKS", + "T62x_JS0_ACTIVE", + "", + "T62x_JS0_WAIT_READ", + "T62x_JS0_WAIT_ISSUE", + "T62x_JS0_WAIT_DEPEND", + "T62x_JS0_WAIT_FINISH", + "T62x_JS1_JOBS", + "T62x_JS1_TASKS", + "T62x_JS1_ACTIVE", + "", + "T62x_JS1_WAIT_READ", + "T62x_JS1_WAIT_ISSUE", + "T62x_JS1_WAIT_DEPEND", + "T62x_JS1_WAIT_FINISH", + "T62x_JS2_JOBS", + "T62x_JS2_TASKS", + "T62x_JS2_ACTIVE", + "", + "T62x_JS2_WAIT_READ", + "T62x_JS2_WAIT_ISSUE", + "T62x_JS2_WAIT_DEPEND", + "T62x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T62x_TI_JOBS_PROCESSED", + "T62x_TI_TRIANGLES", + "T62x_TI_QUADS", + "T62x_TI_POLYGONS", + "T62x_TI_POINTS", + "T62x_TI_LINES", + "T62x_TI_VCACHE_HIT", + "T62x_TI_VCACHE_MISS", + "T62x_TI_FRONT_FACING", + "T62x_TI_BACK_FACING", + "T62x_TI_PRIM_VISIBLE", + "T62x_TI_PRIM_CULLED", + "T62x_TI_PRIM_CLIPPED", + "T62x_TI_LEVEL0", + "T62x_TI_LEVEL1", + "T62x_TI_LEVEL2", + "T62x_TI_LEVEL3", + "T62x_TI_LEVEL4", + "T62x_TI_LEVEL5", + "T62x_TI_LEVEL6", + "T62x_TI_LEVEL7", + "T62x_TI_COMMAND_1", + "T62x_TI_COMMAND_2", + "T62x_TI_COMMAND_3", + "T62x_TI_COMMAND_4", + "T62x_TI_COMMAND_5_7", + "T62x_TI_COMMAND_8_15", + "T62x_TI_COMMAND_16_63", + "T62x_TI_COMMAND_64", + "T62x_TI_COMPRESS_IN", + "T62x_TI_COMPRESS_OUT", + "T62x_TI_COMPRESS_FLUSH", + "T62x_TI_TIMESTAMPS", + "T62x_TI_PCACHE_HIT", + "T62x_TI_PCACHE_MISS", + "T62x_TI_PCACHE_LINE", + "T62x_TI_PCACHE_STALL", + "T62x_TI_WRBUF_HIT", + "T62x_TI_WRBUF_MISS", + "T62x_TI_WRBUF_LINE", + "T62x_TI_WRBUF_PARTIAL", + "T62x_TI_WRBUF_STALL", + "T62x_TI_ACTIVE", + "T62x_TI_LOADING_DESC", + "T62x_TI_INDEX_WAIT", + "T62x_TI_INDEX_RANGE_WAIT", + "T62x_TI_VERTEX_WAIT", + "T62x_TI_PCACHE_WAIT", + "T62x_TI_WRBUF_WAIT", + "T62x_TI_BUS_READ", + "T62x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T62x_TI_UTLB_STALL", + "T62x_TI_UTLB_REPLAY_MISS", + "T62x_TI_UTLB_REPLAY_FULL", + "T62x_TI_UTLB_NEW_MISS", + "T62x_TI_UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "T62x_SHADER_CORE_ACTIVE", + "T62x_FRAG_ACTIVE", + "T62x_FRAG_PRIMITIVES", + "T62x_FRAG_PRIMITIVES_DROPPED", + "T62x_FRAG_CYCLES_DESC", + "T62x_FRAG_CYCLES_FPKQ_ACTIVE", + "T62x_FRAG_CYCLES_VERT", + "T62x_FRAG_CYCLES_TRISETUP", + "T62x_FRAG_CYCLES_EZS_ACTIVE", + "T62x_FRAG_THREADS", + "T62x_FRAG_DUMMY_THREADS", + "T62x_FRAG_QUADS_RAST", + "T62x_FRAG_QUADS_EZS_TEST", + "T62x_FRAG_QUADS_EZS_KILLED", + "T62x_FRAG_THREADS_LZS_TEST", + "T62x_FRAG_THREADS_LZS_KILLED", + "T62x_FRAG_CYCLES_NO_TILE", + "T62x_FRAG_NUM_TILES", + "T62x_FRAG_TRANS_ELIM", + "T62x_COMPUTE_ACTIVE", + "T62x_COMPUTE_TASKS", + "T62x_COMPUTE_THREADS", + "T62x_COMPUTE_CYCLES_DESC", + "T62x_TRIPIPE_ACTIVE", + "T62x_ARITH_WORDS", + "T62x_ARITH_CYCLES_REG", + "T62x_ARITH_CYCLES_L0", + "T62x_ARITH_FRAG_DEPEND", + "T62x_LS_WORDS", + "T62x_LS_ISSUES", + "T62x_LS_RESTARTS", + "T62x_LS_REISSUES_MISS", + "T62x_LS_REISSUES_VD", + "T62x_LS_REISSUE_ATTRIB_MISS", + "T62x_LS_NO_WB", + "T62x_TEX_WORDS", + "T62x_TEX_BUBBLES", + "T62x_TEX_WORDS_L0", + "T62x_TEX_WORDS_DESC", + "T62x_TEX_ISSUES", + "T62x_TEX_RECIRC_FMISS", + "T62x_TEX_RECIRC_DESC", + "T62x_TEX_RECIRC_MULTI", + "T62x_TEX_RECIRC_PMISS", + "T62x_TEX_RECIRC_CONF", + "T62x_LSC_READ_HITS", + "T62x_LSC_READ_MISSES", + "T62x_LSC_WRITE_HITS", + "T62x_LSC_WRITE_MISSES", + "T62x_LSC_ATOMIC_HITS", + "T62x_LSC_ATOMIC_MISSES", + "T62x_LSC_LINE_FETCHES", + "T62x_LSC_DIRTY_LINE", + "T62x_LSC_SNOOPS", + "T62x_AXI_TLB_STALL", + "T62x_AXI_TLB_MIESS", + "T62x_AXI_TLB_TRANSACTION", + "T62x_LS_TLB_MISS", + "T62x_LS_TLB_HIT", + "T62x_AXI_BEATS_READ", + "T62x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T62x_MMU_HIT", + "T62x_MMU_NEW_MISS", + "T62x_MMU_REPLAY_FULL", + "T62x_MMU_REPLAY_MISS", + "T62x_MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "T62x_UTLB_HIT", + "T62x_UTLB_NEW_MISS", + "T62x_UTLB_REPLAY_FULL", + "T62x_UTLB_REPLAY_MISS", + "T62x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T62x_L2_EXT_WRITE_BEATS", + "T62x_L2_EXT_READ_BEATS", + "T62x_L2_ANY_LOOKUP", + "T62x_L2_READ_LOOKUP", + "T62x_L2_SREAD_LOOKUP", + "T62x_L2_READ_REPLAY", + "T62x_L2_READ_SNOOP", + "T62x_L2_READ_HIT", + "T62x_L2_CLEAN_MISS", + "T62x_L2_WRITE_LOOKUP", + "T62x_L2_SWRITE_LOOKUP", + "T62x_L2_WRITE_REPLAY", + "T62x_L2_WRITE_SNOOP", + "T62x_L2_WRITE_HIT", + "T62x_L2_EXT_READ_FULL", + "T62x_L2_EXT_READ_HALF", + "T62x_L2_EXT_WRITE_FULL", + "T62x_L2_EXT_WRITE_HALF", + "T62x_L2_EXT_READ", + "T62x_L2_EXT_READ_LINE", + "T62x_L2_EXT_WRITE", + "T62x_L2_EXT_WRITE_LINE", + "T62x_L2_EXT_WRITE_SMALL", + "T62x_L2_EXT_BARRIER", + "T62x_L2_EXT_AR_STALL", + "T62x_L2_EXT_R_BUF_FULL", + "T62x_L2_EXT_RD_BUF_FULL", + "T62x_L2_EXT_R_RAW", + "T62x_L2_EXT_W_STALL", + "T62x_L2_EXT_W_BUF_FULL", + "T62x_L2_EXT_R_W_HAZARD", + "T62x_L2_TAG_HAZARD", + "T62x_L2_SNOOP_FULL", + "T62x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t72x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T72x_GPU_ACTIVE", + "T72x_IRQ_ACTIVE", + "T72x_JS0_JOBS", + "T72x_JS0_TASKS", + "T72x_JS0_ACTIVE", + "T72x_JS1_JOBS", + "T72x_JS1_TASKS", + "T72x_JS1_ACTIVE", + "T72x_JS2_JOBS", + "T72x_JS2_TASKS", + "T72x_JS2_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T72x_TI_JOBS_PROCESSED", + "T72x_TI_TRIANGLES", + "T72x_TI_QUADS", + "T72x_TI_POLYGONS", + "T72x_TI_POINTS", + "T72x_TI_LINES", + "T72x_TI_FRONT_FACING", + "T72x_TI_BACK_FACING", + "T72x_TI_PRIM_VISIBLE", + "T72x_TI_PRIM_CULLED", + "T72x_TI_PRIM_CLIPPED", + "", + "", + "", + "", + "", + "", + "", + "", + "T72x_TI_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Shader Core */ + "", + "", + "", + "", + "T72x_FRAG_ACTIVE", + "T72x_FRAG_PRIMITIVES", + "T72x_FRAG_PRIMITIVES_DROPPED", + "T72x_FRAG_THREADS", + "T72x_FRAG_DUMMY_THREADS", + "T72x_FRAG_QUADS_RAST", + "T72x_FRAG_QUADS_EZS_TEST", + "T72x_FRAG_QUADS_EZS_KILLED", + "T72x_FRAG_THREADS_LZS_TEST", + "T72x_FRAG_THREADS_LZS_KILLED", + "T72x_FRAG_CYCLES_NO_TILE", + "T72x_FRAG_NUM_TILES", + "T72x_FRAG_TRANS_ELIM", + "T72x_COMPUTE_ACTIVE", + "T72x_COMPUTE_TASKS", + "T72x_COMPUTE_THREADS", + "T72x_TRIPIPE_ACTIVE", + "T72x_ARITH_WORDS", + "T72x_ARITH_CYCLES_REG", + "T72x_LS_WORDS", + "T72x_LS_ISSUES", + "T72x_LS_RESTARTS", + "T72x_LS_REISSUES_MISS", + "T72x_TEX_WORDS", + "T72x_TEX_BUBBLES", + "T72x_TEX_ISSUES", + "T72x_LSC_READ_HITS", + "T72x_LSC_READ_MISSES", + "T72x_LSC_WRITE_HITS", + "T72x_LSC_WRITE_MISSES", + "T72x_LSC_ATOMIC_HITS", + "T72x_LSC_ATOMIC_MISSES", + "T72x_LSC_LINE_FETCHES", + "T72x_LSC_DIRTY_LINE", + "T72x_LSC_SNOOPS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*L2 and MMU */ + "", + "", + "", + "", + "T72x_L2_EXT_WRITE_BEAT", + "T72x_L2_EXT_READ_BEAT", + "T72x_L2_READ_SNOOP", + "T72x_L2_READ_HIT", + "T72x_L2_WRITE_SNOOP", + "T72x_L2_WRITE_HIT", + "T72x_L2_EXT_WRITE_SMALL", + "T72x_L2_EXT_BARRIER", + "T72x_L2_EXT_AR_STALL", + "T72x_L2_EXT_W_STALL", + "T72x_L2_SNOOP_FULL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" +}; + +static const char * const hardware_counters_mali_t76x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T76x_MESSAGES_SENT", + "T76x_MESSAGES_RECEIVED", + "T76x_GPU_ACTIVE", + "T76x_IRQ_ACTIVE", + "T76x_JS0_JOBS", + "T76x_JS0_TASKS", + "T76x_JS0_ACTIVE", + "", + "T76x_JS0_WAIT_READ", + "T76x_JS0_WAIT_ISSUE", + "T76x_JS0_WAIT_DEPEND", + "T76x_JS0_WAIT_FINISH", + "T76x_JS1_JOBS", + "T76x_JS1_TASKS", + "T76x_JS1_ACTIVE", + "", + "T76x_JS1_WAIT_READ", + "T76x_JS1_WAIT_ISSUE", + "T76x_JS1_WAIT_DEPEND", + "T76x_JS1_WAIT_FINISH", + "T76x_JS2_JOBS", + "T76x_JS2_TASKS", + "T76x_JS2_ACTIVE", + "", + "T76x_JS2_WAIT_READ", + "T76x_JS2_WAIT_ISSUE", + "T76x_JS2_WAIT_DEPEND", + "T76x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T76x_TI_JOBS_PROCESSED", + "T76x_TI_TRIANGLES", + "T76x_TI_QUADS", + "T76x_TI_POLYGONS", + "T76x_TI_POINTS", + "T76x_TI_LINES", + "T76x_TI_VCACHE_HIT", + "T76x_TI_VCACHE_MISS", + "T76x_TI_FRONT_FACING", + "T76x_TI_BACK_FACING", + "T76x_TI_PRIM_VISIBLE", + "T76x_TI_PRIM_CULLED", + "T76x_TI_PRIM_CLIPPED", + "T76x_TI_LEVEL0", + "T76x_TI_LEVEL1", + "T76x_TI_LEVEL2", + "T76x_TI_LEVEL3", + "T76x_TI_LEVEL4", + "T76x_TI_LEVEL5", + "T76x_TI_LEVEL6", + "T76x_TI_LEVEL7", + "T76x_TI_COMMAND_1", + "T76x_TI_COMMAND_2", + "T76x_TI_COMMAND_3", + "T76x_TI_COMMAND_4", + "T76x_TI_COMMAND_5_7", + "T76x_TI_COMMAND_8_15", + "T76x_TI_COMMAND_16_63", + "T76x_TI_COMMAND_64", + "T76x_TI_COMPRESS_IN", + "T76x_TI_COMPRESS_OUT", + "T76x_TI_COMPRESS_FLUSH", + "T76x_TI_TIMESTAMPS", + "T76x_TI_PCACHE_HIT", + "T76x_TI_PCACHE_MISS", + "T76x_TI_PCACHE_LINE", + "T76x_TI_PCACHE_STALL", + "T76x_TI_WRBUF_HIT", + "T76x_TI_WRBUF_MISS", + "T76x_TI_WRBUF_LINE", + "T76x_TI_WRBUF_PARTIAL", + "T76x_TI_WRBUF_STALL", + "T76x_TI_ACTIVE", + "T76x_TI_LOADING_DESC", + "T76x_TI_INDEX_WAIT", + "T76x_TI_INDEX_RANGE_WAIT", + "T76x_TI_VERTEX_WAIT", + "T76x_TI_PCACHE_WAIT", + "T76x_TI_WRBUF_WAIT", + "T76x_TI_BUS_READ", + "T76x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T76x_TI_UTLB_HIT", + "T76x_TI_UTLB_NEW_MISS", + "T76x_TI_UTLB_REPLAY_FULL", + "T76x_TI_UTLB_REPLAY_MISS", + "T76x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T76x_FRAG_ACTIVE", + "T76x_FRAG_PRIMITIVES", + "T76x_FRAG_PRIMITIVES_DROPPED", + "T76x_FRAG_CYCLES_DESC", + "T76x_FRAG_CYCLES_FPKQ_ACTIVE", + "T76x_FRAG_CYCLES_VERT", + "T76x_FRAG_CYCLES_TRISETUP", + "T76x_FRAG_CYCLES_EZS_ACTIVE", + "T76x_FRAG_THREADS", + "T76x_FRAG_DUMMY_THREADS", + "T76x_FRAG_QUADS_RAST", + "T76x_FRAG_QUADS_EZS_TEST", + "T76x_FRAG_QUADS_EZS_KILLED", + "T76x_FRAG_THREADS_LZS_TEST", + "T76x_FRAG_THREADS_LZS_KILLED", + "T76x_FRAG_CYCLES_NO_TILE", + "T76x_FRAG_NUM_TILES", + "T76x_FRAG_TRANS_ELIM", + "T76x_COMPUTE_ACTIVE", + "T76x_COMPUTE_TASKS", + "T76x_COMPUTE_THREADS", + "T76x_COMPUTE_CYCLES_DESC", + "T76x_TRIPIPE_ACTIVE", + "T76x_ARITH_WORDS", + "T76x_ARITH_CYCLES_REG", + "T76x_ARITH_CYCLES_L0", + "T76x_ARITH_FRAG_DEPEND", + "T76x_LS_WORDS", + "T76x_LS_ISSUES", + "T76x_LS_REISSUE_ATTR", + "T76x_LS_REISSUES_VARY", + "T76x_LS_VARY_RV_MISS", + "T76x_LS_VARY_RV_HIT", + "T76x_LS_NO_UNPARK", + "T76x_TEX_WORDS", + "T76x_TEX_BUBBLES", + "T76x_TEX_WORDS_L0", + "T76x_TEX_WORDS_DESC", + "T76x_TEX_ISSUES", + "T76x_TEX_RECIRC_FMISS", + "T76x_TEX_RECIRC_DESC", + "T76x_TEX_RECIRC_MULTI", + "T76x_TEX_RECIRC_PMISS", + "T76x_TEX_RECIRC_CONF", + "T76x_LSC_READ_HITS", + "T76x_LSC_READ_OP", + "T76x_LSC_WRITE_HITS", + "T76x_LSC_WRITE_OP", + "T76x_LSC_ATOMIC_HITS", + "T76x_LSC_ATOMIC_OP", + "T76x_LSC_LINE_FETCHES", + "T76x_LSC_DIRTY_LINE", + "T76x_LSC_SNOOPS", + "T76x_AXI_TLB_STALL", + "T76x_AXI_TLB_MIESS", + "T76x_AXI_TLB_TRANSACTION", + "T76x_LS_TLB_MISS", + "T76x_LS_TLB_HIT", + "T76x_AXI_BEATS_READ", + "T76x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T76x_MMU_HIT", + "T76x_MMU_NEW_MISS", + "T76x_MMU_REPLAY_FULL", + "T76x_MMU_REPLAY_MISS", + "T76x_MMU_TABLE_WALK", + "T76x_MMU_REQUESTS", + "", + "", + "T76x_UTLB_HIT", + "T76x_UTLB_NEW_MISS", + "T76x_UTLB_REPLAY_FULL", + "T76x_UTLB_REPLAY_MISS", + "T76x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T76x_L2_EXT_WRITE_BEATS", + "T76x_L2_EXT_READ_BEATS", + "T76x_L2_ANY_LOOKUP", + "T76x_L2_READ_LOOKUP", + "T76x_L2_SREAD_LOOKUP", + "T76x_L2_READ_REPLAY", + "T76x_L2_READ_SNOOP", + "T76x_L2_READ_HIT", + "T76x_L2_CLEAN_MISS", + "T76x_L2_WRITE_LOOKUP", + "T76x_L2_SWRITE_LOOKUP", + "T76x_L2_WRITE_REPLAY", + "T76x_L2_WRITE_SNOOP", + "T76x_L2_WRITE_HIT", + "T76x_L2_EXT_READ_FULL", + "", + "T76x_L2_EXT_WRITE_FULL", + "T76x_L2_EXT_R_W_HAZARD", + "T76x_L2_EXT_READ", + "T76x_L2_EXT_READ_LINE", + "T76x_L2_EXT_WRITE", + "T76x_L2_EXT_WRITE_LINE", + "T76x_L2_EXT_WRITE_SMALL", + "T76x_L2_EXT_BARRIER", + "T76x_L2_EXT_AR_STALL", + "T76x_L2_EXT_R_BUF_FULL", + "T76x_L2_EXT_RD_BUF_FULL", + "T76x_L2_EXT_R_RAW", + "T76x_L2_EXT_W_STALL", + "T76x_L2_EXT_W_BUF_FULL", + "T76x_L2_EXT_R_BUF_FULL", + "T76x_L2_TAG_HAZARD", + "T76x_L2_SNOOP_FULL", + "T76x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t86x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T86x_MESSAGES_SENT", + "T86x_MESSAGES_RECEIVED", + "T86x_GPU_ACTIVE", + "T86x_IRQ_ACTIVE", + "T86x_JS0_JOBS", + "T86x_JS0_TASKS", + "T86x_JS0_ACTIVE", + "", + "T86x_JS0_WAIT_READ", + "T86x_JS0_WAIT_ISSUE", + "T86x_JS0_WAIT_DEPEND", + "T86x_JS0_WAIT_FINISH", + "T86x_JS1_JOBS", + "T86x_JS1_TASKS", + "T86x_JS1_ACTIVE", + "", + "T86x_JS1_WAIT_READ", + "T86x_JS1_WAIT_ISSUE", + "T86x_JS1_WAIT_DEPEND", + "T86x_JS1_WAIT_FINISH", + "T86x_JS2_JOBS", + "T86x_JS2_TASKS", + "T86x_JS2_ACTIVE", + "", + "T86x_JS2_WAIT_READ", + "T86x_JS2_WAIT_ISSUE", + "T86x_JS2_WAIT_DEPEND", + "T86x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T86x_TI_JOBS_PROCESSED", + "T86x_TI_TRIANGLES", + "T86x_TI_QUADS", + "T86x_TI_POLYGONS", + "T86x_TI_POINTS", + "T86x_TI_LINES", + "T86x_TI_VCACHE_HIT", + "T86x_TI_VCACHE_MISS", + "T86x_TI_FRONT_FACING", + "T86x_TI_BACK_FACING", + "T86x_TI_PRIM_VISIBLE", + "T86x_TI_PRIM_CULLED", + "T86x_TI_PRIM_CLIPPED", + "T86x_TI_LEVEL0", + "T86x_TI_LEVEL1", + "T86x_TI_LEVEL2", + "T86x_TI_LEVEL3", + "T86x_TI_LEVEL4", + "T86x_TI_LEVEL5", + "T86x_TI_LEVEL6", + "T86x_TI_LEVEL7", + "T86x_TI_COMMAND_1", + "T86x_TI_COMMAND_2", + "T86x_TI_COMMAND_3", + "T86x_TI_COMMAND_4", + "T86x_TI_COMMAND_5_7", + "T86x_TI_COMMAND_8_15", + "T86x_TI_COMMAND_16_63", + "T86x_TI_COMMAND_64", + "T86x_TI_COMPRESS_IN", + "T86x_TI_COMPRESS_OUT", + "T86x_TI_COMPRESS_FLUSH", + "T86x_TI_TIMESTAMPS", + "T86x_TI_PCACHE_HIT", + "T86x_TI_PCACHE_MISS", + "T86x_TI_PCACHE_LINE", + "T86x_TI_PCACHE_STALL", + "T86x_TI_WRBUF_HIT", + "T86x_TI_WRBUF_MISS", + "T86x_TI_WRBUF_LINE", + "T86x_TI_WRBUF_PARTIAL", + "T86x_TI_WRBUF_STALL", + "T86x_TI_ACTIVE", + "T86x_TI_LOADING_DESC", + "T86x_TI_INDEX_WAIT", + "T86x_TI_INDEX_RANGE_WAIT", + "T86x_TI_VERTEX_WAIT", + "T86x_TI_PCACHE_WAIT", + "T86x_TI_WRBUF_WAIT", + "T86x_TI_BUS_READ", + "T86x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T86x_TI_UTLB_HIT", + "T86x_TI_UTLB_NEW_MISS", + "T86x_TI_UTLB_REPLAY_FULL", + "T86x_TI_UTLB_REPLAY_MISS", + "T86x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T86x_FRAG_ACTIVE", + "T86x_FRAG_PRIMITIVES", + "T86x_FRAG_PRIMITIVES_DROPPED", + "T86x_FRAG_CYCLES_DESC", + "T86x_FRAG_CYCLES_FPKQ_ACTIVE", + "T86x_FRAG_CYCLES_VERT", + "T86x_FRAG_CYCLES_TRISETUP", + "T86x_FRAG_CYCLES_EZS_ACTIVE", + "T86x_FRAG_THREADS", + "T86x_FRAG_DUMMY_THREADS", + "T86x_FRAG_QUADS_RAST", + "T86x_FRAG_QUADS_EZS_TEST", + "T86x_FRAG_QUADS_EZS_KILLED", + "T86x_FRAG_THREADS_LZS_TEST", + "T86x_FRAG_THREADS_LZS_KILLED", + "T86x_FRAG_CYCLES_NO_TILE", + "T86x_FRAG_NUM_TILES", + "T86x_FRAG_TRANS_ELIM", + "T86x_COMPUTE_ACTIVE", + "T86x_COMPUTE_TASKS", + "T86x_COMPUTE_THREADS", + "T86x_COMPUTE_CYCLES_DESC", + "T86x_TRIPIPE_ACTIVE", + "T86x_ARITH_WORDS", + "T86x_ARITH_CYCLES_REG", + "T86x_ARITH_CYCLES_L0", + "T86x_ARITH_FRAG_DEPEND", + "T86x_LS_WORDS", + "T86x_LS_ISSUES", + "T86x_LS_REISSUE_ATTR", + "T86x_LS_REISSUES_VARY", + "T86x_LS_VARY_RV_MISS", + "T86x_LS_VARY_RV_HIT", + "T86x_LS_NO_UNPARK", + "T86x_TEX_WORDS", + "T86x_TEX_BUBBLES", + "T86x_TEX_WORDS_L0", + "T86x_TEX_WORDS_DESC", + "T86x_TEX_ISSUES", + "T86x_TEX_RECIRC_FMISS", + "T86x_TEX_RECIRC_DESC", + "T86x_TEX_RECIRC_MULTI", + "T86x_TEX_RECIRC_PMISS", + "T86x_TEX_RECIRC_CONF", + "T86x_LSC_READ_HITS", + "T86x_LSC_READ_OP", + "T86x_LSC_WRITE_HITS", + "T86x_LSC_WRITE_OP", + "T86x_LSC_ATOMIC_HITS", + "T86x_LSC_ATOMIC_OP", + "T86x_LSC_LINE_FETCHES", + "T86x_LSC_DIRTY_LINE", + "T86x_LSC_SNOOPS", + "T86x_AXI_TLB_STALL", + "T86x_AXI_TLB_MIESS", + "T86x_AXI_TLB_TRANSACTION", + "T86x_LS_TLB_MISS", + "T86x_LS_TLB_HIT", + "T86x_AXI_BEATS_READ", + "T86x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T86x_MMU_HIT", + "T86x_MMU_NEW_MISS", + "T86x_MMU_REPLAY_FULL", + "T86x_MMU_REPLAY_MISS", + "T86x_MMU_TABLE_WALK", + "T86x_MMU_REQUESTS", + "", + "", + "T86x_UTLB_HIT", + "T86x_UTLB_NEW_MISS", + "T86x_UTLB_REPLAY_FULL", + "T86x_UTLB_REPLAY_MISS", + "T86x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T86x_L2_EXT_WRITE_BEATS", + "T86x_L2_EXT_READ_BEATS", + "T86x_L2_ANY_LOOKUP", + "T86x_L2_READ_LOOKUP", + "T86x_L2_SREAD_LOOKUP", + "T86x_L2_READ_REPLAY", + "T86x_L2_READ_SNOOP", + "T86x_L2_READ_HIT", + "T86x_L2_CLEAN_MISS", + "T86x_L2_WRITE_LOOKUP", + "T86x_L2_SWRITE_LOOKUP", + "T86x_L2_WRITE_REPLAY", + "T86x_L2_WRITE_SNOOP", + "T86x_L2_WRITE_HIT", + "T86x_L2_EXT_READ_FULL", + "", + "T86x_L2_EXT_WRITE_FULL", + "T86x_L2_EXT_R_W_HAZARD", + "T86x_L2_EXT_READ", + "T86x_L2_EXT_READ_LINE", + "T86x_L2_EXT_WRITE", + "T86x_L2_EXT_WRITE_LINE", + "T86x_L2_EXT_WRITE_SMALL", + "T86x_L2_EXT_BARRIER", + "T86x_L2_EXT_AR_STALL", + "T86x_L2_EXT_R_BUF_FULL", + "T86x_L2_EXT_RD_BUF_FULL", + "T86x_L2_EXT_R_RAW", + "T86x_L2_EXT_W_STALL", + "T86x_L2_EXT_W_BUF_FULL", + "T86x_L2_EXT_R_BUF_FULL", + "T86x_L2_TAG_HAZARD", + "T86x_L2_SNOOP_FULL", + "T86x_L2_REPLAY_FULL" +}; + +static const char * const hardware_counters_mali_t88x[] = { + /* Job Manager */ + "", + "", + "", + "", + "T88x_MESSAGES_SENT", + "T88x_MESSAGES_RECEIVED", + "T88x_GPU_ACTIVE", + "T88x_IRQ_ACTIVE", + "T88x_JS0_JOBS", + "T88x_JS0_TASKS", + "T88x_JS0_ACTIVE", + "", + "T88x_JS0_WAIT_READ", + "T88x_JS0_WAIT_ISSUE", + "T88x_JS0_WAIT_DEPEND", + "T88x_JS0_WAIT_FINISH", + "T88x_JS1_JOBS", + "T88x_JS1_TASKS", + "T88x_JS1_ACTIVE", + "", + "T88x_JS1_WAIT_READ", + "T88x_JS1_WAIT_ISSUE", + "T88x_JS1_WAIT_DEPEND", + "T88x_JS1_WAIT_FINISH", + "T88x_JS2_JOBS", + "T88x_JS2_TASKS", + "T88x_JS2_ACTIVE", + "", + "T88x_JS2_WAIT_READ", + "T88x_JS2_WAIT_ISSUE", + "T88x_JS2_WAIT_DEPEND", + "T88x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T88x_TI_JOBS_PROCESSED", + "T88x_TI_TRIANGLES", + "T88x_TI_QUADS", + "T88x_TI_POLYGONS", + "T88x_TI_POINTS", + "T88x_TI_LINES", + "T88x_TI_VCACHE_HIT", + "T88x_TI_VCACHE_MISS", + "T88x_TI_FRONT_FACING", + "T88x_TI_BACK_FACING", + "T88x_TI_PRIM_VISIBLE", + "T88x_TI_PRIM_CULLED", + "T88x_TI_PRIM_CLIPPED", + "T88x_TI_LEVEL0", + "T88x_TI_LEVEL1", + "T88x_TI_LEVEL2", + "T88x_TI_LEVEL3", + "T88x_TI_LEVEL4", + "T88x_TI_LEVEL5", + "T88x_TI_LEVEL6", + "T88x_TI_LEVEL7", + "T88x_TI_COMMAND_1", + "T88x_TI_COMMAND_2", + "T88x_TI_COMMAND_3", + "T88x_TI_COMMAND_4", + "T88x_TI_COMMAND_5_7", + "T88x_TI_COMMAND_8_15", + "T88x_TI_COMMAND_16_63", + "T88x_TI_COMMAND_64", + "T88x_TI_COMPRESS_IN", + "T88x_TI_COMPRESS_OUT", + "T88x_TI_COMPRESS_FLUSH", + "T88x_TI_TIMESTAMPS", + "T88x_TI_PCACHE_HIT", + "T88x_TI_PCACHE_MISS", + "T88x_TI_PCACHE_LINE", + "T88x_TI_PCACHE_STALL", + "T88x_TI_WRBUF_HIT", + "T88x_TI_WRBUF_MISS", + "T88x_TI_WRBUF_LINE", + "T88x_TI_WRBUF_PARTIAL", + "T88x_TI_WRBUF_STALL", + "T88x_TI_ACTIVE", + "T88x_TI_LOADING_DESC", + "T88x_TI_INDEX_WAIT", + "T88x_TI_INDEX_RANGE_WAIT", + "T88x_TI_VERTEX_WAIT", + "T88x_TI_PCACHE_WAIT", + "T88x_TI_WRBUF_WAIT", + "T88x_TI_BUS_READ", + "T88x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T88x_TI_UTLB_HIT", + "T88x_TI_UTLB_NEW_MISS", + "T88x_TI_UTLB_REPLAY_FULL", + "T88x_TI_UTLB_REPLAY_MISS", + "T88x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T88x_FRAG_ACTIVE", + "T88x_FRAG_PRIMITIVES", + "T88x_FRAG_PRIMITIVES_DROPPED", + "T88x_FRAG_CYCLES_DESC", + "T88x_FRAG_CYCLES_FPKQ_ACTIVE", + "T88x_FRAG_CYCLES_VERT", + "T88x_FRAG_CYCLES_TRISETUP", + "T88x_FRAG_CYCLES_EZS_ACTIVE", + "T88x_FRAG_THREADS", + "T88x_FRAG_DUMMY_THREADS", + "T88x_FRAG_QUADS_RAST", + "T88x_FRAG_QUADS_EZS_TEST", + "T88x_FRAG_QUADS_EZS_KILLED", + "T88x_FRAG_THREADS_LZS_TEST", + "T88x_FRAG_THREADS_LZS_KILLED", + "T88x_FRAG_CYCLES_NO_TILE", + "T88x_FRAG_NUM_TILES", + "T88x_FRAG_TRANS_ELIM", + "T88x_COMPUTE_ACTIVE", + "T88x_COMPUTE_TASKS", + "T88x_COMPUTE_THREADS", + "T88x_COMPUTE_CYCLES_DESC", + "T88x_TRIPIPE_ACTIVE", + "T88x_ARITH_WORDS", + "T88x_ARITH_CYCLES_REG", + "T88x_ARITH_CYCLES_L0", + "T88x_ARITH_FRAG_DEPEND", + "T88x_LS_WORDS", + "T88x_LS_ISSUES", + "T88x_LS_REISSUE_ATTR", + "T88x_LS_REISSUES_VARY", + "T88x_LS_VARY_RV_MISS", + "T88x_LS_VARY_RV_HIT", + "T88x_LS_NO_UNPARK", + "T88x_TEX_WORDS", + "T88x_TEX_BUBBLES", + "T88x_TEX_WORDS_L0", + "T88x_TEX_WORDS_DESC", + "T88x_TEX_ISSUES", + "T88x_TEX_RECIRC_FMISS", + "T88x_TEX_RECIRC_DESC", + "T88x_TEX_RECIRC_MULTI", + "T88x_TEX_RECIRC_PMISS", + "T88x_TEX_RECIRC_CONF", + "T88x_LSC_READ_HITS", + "T88x_LSC_READ_OP", + "T88x_LSC_WRITE_HITS", + "T88x_LSC_WRITE_OP", + "T88x_LSC_ATOMIC_HITS", + "T88x_LSC_ATOMIC_OP", + "T88x_LSC_LINE_FETCHES", + "T88x_LSC_DIRTY_LINE", + "T88x_LSC_SNOOPS", + "T88x_AXI_TLB_STALL", + "T88x_AXI_TLB_MIESS", + "T88x_AXI_TLB_TRANSACTION", + "T88x_LS_TLB_MISS", + "T88x_LS_TLB_HIT", + "T88x_AXI_BEATS_READ", + "T88x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T88x_MMU_HIT", + "T88x_MMU_NEW_MISS", + "T88x_MMU_REPLAY_FULL", + "T88x_MMU_REPLAY_MISS", + "T88x_MMU_TABLE_WALK", + "T88x_MMU_REQUESTS", + "", + "", + "T88x_UTLB_HIT", + "T88x_UTLB_NEW_MISS", + "T88x_UTLB_REPLAY_FULL", + "T88x_UTLB_REPLAY_MISS", + "T88x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T88x_L2_EXT_WRITE_BEATS", + "T88x_L2_EXT_READ_BEATS", + "T88x_L2_ANY_LOOKUP", + "T88x_L2_READ_LOOKUP", + "T88x_L2_SREAD_LOOKUP", + "T88x_L2_READ_REPLAY", + "T88x_L2_READ_SNOOP", + "T88x_L2_READ_HIT", + "T88x_L2_CLEAN_MISS", + "T88x_L2_WRITE_LOOKUP", + "T88x_L2_SWRITE_LOOKUP", + "T88x_L2_WRITE_REPLAY", + "T88x_L2_WRITE_SNOOP", + "T88x_L2_WRITE_HIT", + "T88x_L2_EXT_READ_FULL", + "", + "T88x_L2_EXT_WRITE_FULL", + "T88x_L2_EXT_R_W_HAZARD", + "T88x_L2_EXT_READ", + "T88x_L2_EXT_READ_LINE", + "T88x_L2_EXT_WRITE", + "T88x_L2_EXT_WRITE_LINE", + "T88x_L2_EXT_WRITE_SMALL", + "T88x_L2_EXT_BARRIER", + "T88x_L2_EXT_AR_STALL", + "T88x_L2_EXT_R_BUF_FULL", + "T88x_L2_EXT_RD_BUF_FULL", + "T88x_L2_EXT_R_RAW", + "T88x_L2_EXT_W_STALL", + "T88x_L2_EXT_W_BUF_FULL", + "T88x_L2_EXT_R_BUF_FULL", + "T88x_L2_TAG_HAZARD", + "T88x_L2_SNOOP_FULL", + "T88x_L2_REPLAY_FULL" +}; + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..6a9781ffd29d90b2838bd27f0dab5f41f3c0ae76 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c @@ -0,0 +1,112 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#ifdef CONFIG_DEBUG_FS +/** Show callback for the @c gpu_memory debugfs file. + * + * This function is called to get the contents of the @c gpu_memory debugfs + * file. This is a report of current gpu memory usage. + * + * @param sfile The debugfs entry + * @param data Data associated with the entry + * + * @return 0 if successfully prints data in debugfs entry file + * -1 if it encountered an error + */ + +static int kbasep_gpu_memory_seq_show(struct seq_file *sfile, void *data) +{ + ssize_t ret = 0; + struct list_head *entry; + const struct list_head *kbdev_list; + kbdev_list = kbase_dev_list_get(); + list_for_each(entry, kbdev_list) { + struct kbase_device *kbdev = NULL; + struct kbasep_kctx_list_element *element; + + kbdev = list_entry(entry, struct kbase_device, entry); + /* output the total memory usage and cap for this device */ + ret = seq_printf(sfile, "%-16s %10u\n", \ + kbdev->devname, \ + atomic_read(&(kbdev->memdev.used_pages))); + mutex_lock(&kbdev->kctx_list_lock); + list_for_each_entry(element, &kbdev->kctx_list, link) { + /* output the memory usage and cap for each kctx + * opened on this device */ + ret = seq_printf(sfile, " %s-0x%p %10u\n", \ + "kctx", + element->kctx, \ + atomic_read(&(element->kctx->used_pages))); + } + mutex_unlock(&kbdev->kctx_list_lock); + } + kbase_dev_list_put(kbdev_list); + return ret; +} + +/* + * File operations related to debugfs entry for gpu_memory + */ +STATIC int kbasep_gpu_memory_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_gpu_memory_seq_show , NULL); +} + +static const struct file_operations kbasep_gpu_memory_debugfs_fops = { + .open = kbasep_gpu_memory_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +/* + * Initialize debugfs entry for gpu_memory + */ +mali_error kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev) +{ + kbdev->gpu_memory_dentry = debugfs_create_file("gpu_memory", \ + S_IRUGO, \ + kbdev->mali_debugfs_directory, \ + NULL, \ + &kbasep_gpu_memory_debugfs_fops); + if (IS_ERR(kbdev->gpu_memory_dentry)) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +/* + * Terminate debugfs entry for gpu_memory + */ +void kbasep_gpu_memory_debugfs_term(struct kbase_device *kbdev) +{ + debugfs_remove(kbdev->gpu_memory_dentry); +} +#else +/* + * Stub functions for when debugfs is disabled + */ +mali_error kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev) +{ + return MALI_ERROR_NONE; +} +void kbasep_gpu_memory_debugfs_term(struct kbase_device *kbdev) +{ +} +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..7ceb380a2653aa94c492b5b9e4f3bff91429ef99 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h @@ -0,0 +1,43 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpu_memory_debugfs.h + * Header file for gpu_memory entry in debugfs + * + */ + +#ifndef _KBASE_GPU_MEMORY_H +#define _KBASE_GPU_MEMORY_H + +#include +#include +#include + +/** + * @brief Initialize gpu_memory debugfs entry + */ +mali_error kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev); + +/** + * @brief Terminate gpu_memory debugfs entry + */ +void kbasep_gpu_memory_debugfs_term(struct kbase_device *kbdev); + +#endif /*_KBASE_GPU_MEMORY_H*/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c new file mode 100644 index 0000000000000000000000000000000000000000..2d2ff64b90cfcc18f1b881909d5e1cc843117d07 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c @@ -0,0 +1,335 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpuprops.c + * Base kernel property query APIs + */ + +#include +#include +#include + +/** + * @brief Extracts bits from a 32-bit bitfield. + * @hideinitializer + * + * @param[in] value The value from which to extract bits. + * @param[in] offset The first bit to extract (0 being the LSB). + * @param[in] size The number of bits to extract. + * @return Bits [@a offset, @a offset + @a size) from @a value. + * + * @pre offset + size <= 32. + */ +/* from mali_cdsb.h */ +#define KBASE_UBFX32(value, offset, size) \ + (((u32)(value) >> (u32)(offset)) & (u32)((1ULL << (u32)(size)) - 1)) + +mali_error kbase_gpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_gpuprops * const kbase_props) +{ + kbase_gpuprops_clock_speed_function get_gpu_speed_mhz; + u32 gpu_speed_mhz; + int rc = 1; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kbase_props); + + /* Current GPU speed is requested from the system integrator via the KBASE_CONFIG_ATTR_GPU_SPEED_FUNC function. + * If that function fails, or the function is not provided by the system integrator, we report the maximum + * GPU speed as specified by GPU_FREQ_KHZ_MAX. + */ + get_gpu_speed_mhz = (kbase_gpuprops_clock_speed_function) kbasep_get_config_value(kctx->kbdev, kctx->kbdev->config_attributes, KBASE_CONFIG_ATTR_GPU_SPEED_FUNC); + if (get_gpu_speed_mhz != NULL) { + rc = get_gpu_speed_mhz(&gpu_speed_mhz); +#ifdef CONFIG_MALI_DEBUG + /* Issue a warning message when the reported GPU speed falls outside the min/max range */ + if (rc == 0) { + u32 gpu_speed_khz = gpu_speed_mhz * 1000; + if (gpu_speed_khz < kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min || gpu_speed_khz > kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max) + dev_warn(kctx->kbdev->dev, "GPU Speed is outside of min/max range (got %lu Khz, min %lu Khz, max %lu Khz)\n", (unsigned long)gpu_speed_khz, (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min, (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max); + } +#endif /* CONFIG_MALI_DEBUG */ + } + if (rc != 0) + gpu_speed_mhz = kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max / 1000; + + kctx->kbdev->gpu_props.props.core_props.gpu_speed_mhz = gpu_speed_mhz; + + memcpy(&kbase_props->props, &kctx->kbdev->gpu_props.props, sizeof(kbase_props->props)); + + return MALI_ERROR_NONE; +} + +STATIC void kbase_gpuprops_dump_registers(struct kbase_device *kbdev, struct kbase_gpuprops_regdump *regdump) +{ + int i; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != regdump); + + /* Fill regdump with the content of the relevant registers */ + regdump->gpu_id = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID)); + + regdump->l2_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_FEATURES)); + regdump->l3_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_FEATURES)); + regdump->tiler_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_FEATURES)); + regdump->mem_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(MEM_FEATURES)); + regdump->mmu_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(MMU_FEATURES)); + regdump->as_present = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(AS_PRESENT)); + regdump->js_present = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(JS_PRESENT)); + + for (i = 0; i < MIDG_MAX_JOB_SLOTS; i++) + regdump->js_features[i] = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(JS_FEATURES_REG(i))); + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + regdump->texture_features[i] = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TEXTURE_FEATURES_REG(i))); + + regdump->thread_max_threads = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_THREADS)); + regdump->thread_max_workgroup_size = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_WORKGROUP_SIZE)); + regdump->thread_max_barrier_size = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_BARRIER_SIZE)); + regdump->thread_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_FEATURES)); + + regdump->shader_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(SHADER_PRESENT_LO)); + regdump->shader_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(SHADER_PRESENT_HI)); + + regdump->tiler_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_PRESENT_LO)); + regdump->tiler_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_PRESENT_HI)); + + regdump->l2_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_PRESENT_LO)); + regdump->l2_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_PRESENT_HI)); + + regdump->l3_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_PRESENT_LO)); + regdump->l3_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_PRESENT_HI)); +} + +STATIC void kbase_gpuprops_construct_coherent_groups(base_gpu_props * const props) +{ + struct mali_base_gpu_coherent_group *current_group; + u64 group_present; + u64 group_mask; + u64 first_set, first_set_prev; + u32 num_groups = 0; + + KBASE_DEBUG_ASSERT(NULL != props); + + props->coherency_info.coherency = props->raw_props.mem_features; + props->coherency_info.num_core_groups = hweight64(props->raw_props.l2_present); + + if (props->coherency_info.coherency & GROUPS_L3_COHERENT) { + /* Group is l3 coherent */ + group_present = props->raw_props.l3_present; + } else if (props->coherency_info.coherency & GROUPS_L2_COHERENT) { + /* Group is l2 coherent */ + group_present = props->raw_props.l2_present; + } else { + /* Group is l1 coherent */ + group_present = props->raw_props.shader_present; + } + + /* + * The coherent group mask can be computed from the l2/l3 present + * register. + * + * For the coherent group n: + * group_mask[n] = (first_set[n] - 1) & ~(first_set[n-1] - 1) + * where first_set is group_present with only its nth set-bit kept + * (i.e. the position from where a new group starts). + * + * For instance if the groups are l2 coherent and l2_present=0x0..01111: + * The first mask is: + * group_mask[1] = (first_set[1] - 1) & ~(first_set[0] - 1) + * = (0x0..010 - 1) & ~(0x0..01 - 1) + * = 0x0..00f + * The second mask is: + * group_mask[2] = (first_set[2] - 1) & ~(first_set[1] - 1) + * = (0x0..100 - 1) & ~(0x0..010 - 1) + * = 0x0..0f0 + * And so on until all the bits from group_present have been cleared + * (i.e. there is no group left). + */ + + current_group = props->coherency_info.group; + first_set = group_present & ~(group_present - 1); + + while (group_present != 0 && num_groups < BASE_MAX_COHERENT_GROUPS) { + group_present -= first_set; /* Clear the current group bit */ + first_set_prev = first_set; + + first_set = group_present & ~(group_present - 1); + group_mask = (first_set - 1) & ~(first_set_prev - 1); + + /* Populate the coherent_group structure for each group */ + current_group->core_mask = group_mask & props->raw_props.shader_present; + current_group->num_cores = hweight64(current_group->core_mask); + + num_groups++; + current_group++; + } + + if (group_present != 0) + pr_warn("Too many coherent groups (keeping only %d groups).\n", BASE_MAX_COHERENT_GROUPS); + + props->coherency_info.num_groups = num_groups; +} + +/** + * @brief Get the GPU configuration + * + * Fill the base_gpu_props structure with values from the GPU configuration registers. + * Only the raw properties are filled in this function + * + * @param gpu_props The base_gpu_props structure + * @param kbdev The struct kbase_device structure for the device + */ +static void kbase_gpuprops_get_props(base_gpu_props * const gpu_props, struct kbase_device *kbdev) +{ + struct kbase_gpuprops_regdump regdump; + int i; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != gpu_props); + + /* Dump relevant registers */ + kbase_gpuprops_dump_registers(kbdev, ®dump); + gpu_props->raw_props.gpu_id = regdump.gpu_id; + gpu_props->raw_props.tiler_features = regdump.tiler_features; + gpu_props->raw_props.mem_features = regdump.mem_features; + gpu_props->raw_props.mmu_features = regdump.mmu_features; + gpu_props->raw_props.l2_features = regdump.l2_features; + gpu_props->raw_props.l3_features = regdump.l3_features; + + gpu_props->raw_props.as_present = regdump.as_present; + gpu_props->raw_props.js_present = regdump.js_present; + gpu_props->raw_props.shader_present = ((u64) regdump.shader_present_hi << 32) + regdump.shader_present_lo; + gpu_props->raw_props.tiler_present = ((u64) regdump.tiler_present_hi << 32) + regdump.tiler_present_lo; + gpu_props->raw_props.l2_present = ((u64) regdump.l2_present_hi << 32) + regdump.l2_present_lo; + gpu_props->raw_props.l3_present = ((u64) regdump.l3_present_hi << 32) + regdump.l3_present_lo; + + for (i = 0; i < MIDG_MAX_JOB_SLOTS; i++) + gpu_props->raw_props.js_features[i] = regdump.js_features[i]; + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + gpu_props->raw_props.texture_features[i] = regdump.texture_features[i]; + + gpu_props->raw_props.thread_max_barrier_size = regdump.thread_max_barrier_size; + gpu_props->raw_props.thread_max_threads = regdump.thread_max_threads; + gpu_props->raw_props.thread_max_workgroup_size = regdump.thread_max_workgroup_size; + gpu_props->raw_props.thread_features = regdump.thread_features; +} + +/** + * @brief Calculate the derived properties + * + * Fill the base_gpu_props structure with values derived from the GPU configuration registers + * + * @param gpu_props The base_gpu_props structure + * @param kbdev The struct kbase_device structure for the device + */ +static void kbase_gpuprops_calculate_props(base_gpu_props * const gpu_props, struct kbase_device *kbdev) +{ + int i; + + /* Populate the base_gpu_props structure */ + gpu_props->core_props.version_status = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 0U, 4); + gpu_props->core_props.minor_revision = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 4U, 8); + gpu_props->core_props.major_revision = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 12U, 4); + gpu_props->core_props.product_id = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 16U, 16); + gpu_props->core_props.log2_program_counter_size = KBASE_GPU_PC_SIZE_LOG2; + gpu_props->core_props.gpu_available_memory_size = totalram_pages << PAGE_SHIFT; + + for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) + gpu_props->core_props.texture_features[i] = gpu_props->raw_props.texture_features[i]; + + gpu_props->l2_props.log2_line_size = KBASE_UBFX32(gpu_props->raw_props.l2_features, 0U, 8); + gpu_props->l2_props.log2_cache_size = KBASE_UBFX32(gpu_props->raw_props.l2_features, 16U, 8); + gpu_props->l2_props.num_l2_slices = 1; + if (gpu_props->core_props.product_id == GPU_ID_PI_T76X) { + gpu_props->l2_props.num_l2_slices = KBASE_UBFX32(gpu_props->raw_props.mem_features, 8U, 4) + 1; + } + + gpu_props->l3_props.log2_line_size = KBASE_UBFX32(gpu_props->raw_props.l3_features, 0U, 8); + gpu_props->l3_props.log2_cache_size = KBASE_UBFX32(gpu_props->raw_props.l3_features, 16U, 8); + + gpu_props->tiler_props.bin_size_bytes = 1 << KBASE_UBFX32(gpu_props->raw_props.tiler_features, 0U, 6); + gpu_props->tiler_props.max_active_levels = KBASE_UBFX32(gpu_props->raw_props.tiler_features, 8U, 4); + + if (gpu_props->raw_props.thread_max_threads == 0) + gpu_props->thread_props.max_threads = THREAD_MT_DEFAULT; + else + gpu_props->thread_props.max_threads = gpu_props->raw_props.thread_max_threads; + + if (gpu_props->raw_props.thread_max_workgroup_size == 0) + gpu_props->thread_props.max_workgroup_size = THREAD_MWS_DEFAULT; + else + gpu_props->thread_props.max_workgroup_size = gpu_props->raw_props.thread_max_workgroup_size; + + if (gpu_props->raw_props.thread_max_barrier_size == 0) + gpu_props->thread_props.max_barrier_size = THREAD_MBS_DEFAULT; + else + gpu_props->thread_props.max_barrier_size = gpu_props->raw_props.thread_max_barrier_size; + + gpu_props->thread_props.max_registers = KBASE_UBFX32(gpu_props->raw_props.thread_features, 0U, 16); + gpu_props->thread_props.max_task_queue = KBASE_UBFX32(gpu_props->raw_props.thread_features, 16U, 8); + gpu_props->thread_props.max_thread_group_split = KBASE_UBFX32(gpu_props->raw_props.thread_features, 24U, 6); + gpu_props->thread_props.impl_tech = KBASE_UBFX32(gpu_props->raw_props.thread_features, 30U, 2); + + /* If values are not specified, then use defaults */ + if (gpu_props->thread_props.max_registers == 0) { + gpu_props->thread_props.max_registers = THREAD_MR_DEFAULT; + gpu_props->thread_props.max_task_queue = THREAD_MTQ_DEFAULT; + gpu_props->thread_props.max_thread_group_split = THREAD_MTGS_DEFAULT; + } + /* Initialize the coherent_group structure for each group */ + kbase_gpuprops_construct_coherent_groups(gpu_props); +} + +void kbase_gpuprops_set(struct kbase_device *kbdev) +{ + kbase_gpu_props *gpu_props; + struct midg_raw_gpu_props *raw; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + gpu_props = &kbdev->gpu_props; + raw = &gpu_props->props.raw_props; + + /* Initialize the base_gpu_props structure from the hardware */ + kbase_gpuprops_get_props(&gpu_props->props, kbdev); + + /* Populate the derived properties */ + kbase_gpuprops_calculate_props(&gpu_props->props, kbdev); + + /* Populate kbase-only fields */ + gpu_props->l2_props.associativity = KBASE_UBFX32(raw->l2_features, 8U, 8); + gpu_props->l2_props.external_bus_width = KBASE_UBFX32(raw->l2_features, 24U, 8); + + gpu_props->l3_props.associativity = KBASE_UBFX32(raw->l3_features, 8U, 8); + gpu_props->l3_props.external_bus_width = KBASE_UBFX32(raw->l3_features, 24U, 8); + + gpu_props->mem.core_group = KBASE_UBFX32(raw->mem_features, 0U, 1); + gpu_props->mem.supergroup = KBASE_UBFX32(raw->mem_features, 1U, 1); + + gpu_props->mmu.va_bits = KBASE_UBFX32(raw->mmu_features, 0U, 8); + gpu_props->mmu.pa_bits = KBASE_UBFX32(raw->mmu_features, 8U, 8); + + gpu_props->num_cores = hweight64(raw->shader_present); + gpu_props->num_core_groups = hweight64(raw->l2_present); + gpu_props->num_supergroups = hweight64(raw->l3_present); + gpu_props->num_address_spaces = hweight32(raw->as_present); + gpu_props->num_job_slots = hweight32(raw->js_present); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h new file mode 100644 index 0000000000000000000000000000000000000000..fe2676cd9b998089cf49f051dec2702519a4ab95 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h @@ -0,0 +1,54 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpuprops.h + * Base kernel property query APIs + */ + +#ifndef _KBASE_GPUPROPS_H_ +#define _KBASE_GPUPROPS_H_ + +#include "mali_kbase_gpuprops_types.h" + +/* Forward definition - see mali_kbase.h */ +struct kbase_device; + +/** + * @brief Set up Kbase GPU properties. + * + * Set up Kbase GPU properties with information from the GPU registers + * + * @param kbdev The struct kbase_device structure for the device + */ +void kbase_gpuprops_set(struct kbase_device *kbdev); + +/** + * @brief Provide GPU properties to userside through UKU call. + * + * Fill the struct kbase_uk_gpuprops with values from GPU configuration registers. + * + * @param kctx The struct kbase_context structure + * @param kbase_props A copy of the struct kbase_uk_gpuprops structure from userspace + * + * @return MALI_ERROR_NONE on success. Any other value indicates failure. + */ +mali_error kbase_gpuprops_uk_get_props(struct kbase_context *kctx, struct kbase_uk_gpuprops * const kbase_props); + +#endif /* _KBASE_GPUPROPS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h new file mode 100644 index 0000000000000000000000000000000000000000..6ae5a20d5d4e9b90d05464a335e41ef2fabf7779 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h @@ -0,0 +1,96 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_gpuprops_types.h + * Base kernel property query APIs + */ + +#ifndef _KBASE_GPUPROPS_TYPES_H_ +#define _KBASE_GPUPROPS_TYPES_H_ + +#include "mali_base_kernel.h" + +#define KBASE_GPU_SPEED_MHZ 123 +#define KBASE_GPU_PC_SIZE_LOG2 24U + +typedef struct kbase_gpuprops_regdump { + u32 gpu_id; + u32 l2_features; + u32 l3_features; + u32 tiler_features; + u32 mem_features; + u32 mmu_features; + u32 as_present; + u32 js_present; + u32 thread_max_threads; + u32 thread_max_workgroup_size; + u32 thread_max_barrier_size; + u32 thread_features; + u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + u32 js_features[MIDG_MAX_JOB_SLOTS]; + u32 shader_present_lo; + u32 shader_present_hi; + u32 tiler_present_lo; + u32 tiler_present_hi; + u32 l2_present_lo; + u32 l2_present_hi; + u32 l3_present_lo; + u32 l3_present_hi; +} kbase_gpuprops_regdump; + +typedef struct kbase_gpu_cache_props { + u8 associativity; + u8 external_bus_width; +} kbase_gpu_cache_props; + +typedef struct kbase_gpu_mem_props { + u8 core_group; + u8 supergroup; +} kbase_gpu_mem_props; + +typedef struct kbase_gpu_mmu_props { + u8 va_bits; + u8 pa_bits; +} kbase_gpu_mmu_props; + +typedef struct mali_kbase_gpu_props { + /* kernel-only properties */ + u8 num_cores; + u8 num_core_groups; + u8 num_supergroups; + u8 num_address_spaces; + u8 num_job_slots; + + struct kbase_gpu_cache_props l2_props; + struct kbase_gpu_cache_props l3_props; + + struct kbase_gpu_mem_props mem; + struct kbase_gpu_mmu_props mmu; + + /** + * Implementation specific irq throttle value (us), should be adjusted during integration. + */ + int irq_throttle_time_us; + + /* Properties shared with userspace */ + base_gpu_props props; +} kbase_gpu_props; + +#endif /* _KBASE_GPUPROPS_TYPES_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..818133b7f493567f3a9e0f7cd29db5bcdbcc5a15 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.c @@ -0,0 +1,185 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Run-time work-arounds helpers + */ + +#include +#include +#include "mali_kbase.h" +#include "mali_kbase_hw.h" + +void kbase_hw_set_features_mask(struct kbase_device *kbdev) +{ + const enum base_hw_feature *features; + u32 gpu_id; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + gpu_id &= GPU_ID_VERSION_PRODUCT_ID; + gpu_id = gpu_id >> GPU_ID_VERSION_PRODUCT_ID_SHIFT; + + switch (gpu_id) { + case GPU_ID_PI_T76X: + features = base_hw_features_t76x; + break; + case GPU_ID_PI_TFRX: + /* Fall through */ + case GPU_ID_PI_T86X: + features = base_hw_features_tFxx; + break; + case GPU_ID_PI_T72X: + features = base_hw_features_t72x; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 0, 1, 0): + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 1, 0): + features = base_hw_features_t62x; + break; + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_15DEV0): + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_EAC): + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 1, 0): + features = base_hw_features_t60x; + break; + default: + features = base_hw_features_generic; + break; + } + + for (; *features != BASE_HW_FEATURE_END; features++) + set_bit(*features, &kbdev->hw_features_mask[0]); +} + +mali_error kbase_hw_set_issues_mask(struct kbase_device *kbdev) +{ + const enum base_hw_issue *issues; + u32 gpu_id; + u32 impl_tech; + + gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + impl_tech = kbdev->gpu_props.props.thread_props.impl_tech; + + if (impl_tech != IMPLEMENTATION_MODEL) { + switch (gpu_id) { + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_15DEV0): + issues = base_hw_issues_t60x_r0p0_15dev0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_EAC): + issues = base_hw_issues_t60x_r0p0_eac; + break; + case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 1, 0): + issues = base_hw_issues_t60x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 0, 1, 0): + issues = base_hw_issues_t62x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 1): + issues = base_hw_issues_t62x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 1, 0): + issues = base_hw_issues_t62x_r1p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 0, 0): + issues = base_hw_issues_t76x_r0p0_beta; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 0, 1): + issues = base_hw_issues_t76x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 1, 1): + issues = base_hw_issues_t76x_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 1, 9): + issues = base_hw_issues_t76x_r0p1_50rel0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 2, 1): + issues = base_hw_issues_t76x_r0p2; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 0, 3, 1): + issues = base_hw_issues_t76x_r0p3; + break; + case GPU_ID_MAKE(GPU_ID_PI_T76X, 1, 0, 0): + issues = base_hw_issues_t76x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 1): + case GPU_ID_MAKE(GPU_ID_PI_T72X, 0, 0, 2): + issues = base_hw_issues_t72x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 1, 0, 0): + issues = base_hw_issues_t72x_r1p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T72X, 1, 1, 0): + issues = base_hw_issues_t72x_r1p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 0, 0): + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 0, 1): + issues = base_hw_issues_tFRx_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 1, 2): + issues = base_hw_issues_tFRx_r0p1; + break; + case GPU_ID_MAKE(GPU_ID_PI_TFRX, 0, 2, 0): + issues = base_hw_issues_tFRx_r0p2; + break; + case GPU_ID_MAKE(GPU_ID_PI_T86X, 0, 0, 1): + issues = base_hw_issues_t86x_r0p0; + break; + case GPU_ID_MAKE(GPU_ID_PI_T86X, 0, 2, 0): + issues = base_hw_issues_t86x_r0p2; + break; + default: + dev_err(kbdev->dev, "Unknown GPU ID %x", gpu_id); + return MALI_ERROR_FUNCTION_FAILED; + } + } else { + /* Software model */ + switch (gpu_id >> GPU_ID_VERSION_PRODUCT_ID_SHIFT) { + case GPU_ID_PI_T60X: + issues = base_hw_issues_model_t60x; + break; + case GPU_ID_PI_T62X: + issues = base_hw_issues_model_t62x; + break; + case GPU_ID_PI_T72X: + issues = base_hw_issues_model_t72x; + break; + case GPU_ID_PI_T76X: + issues = base_hw_issues_model_t76x; + break; + case GPU_ID_PI_TFRX: + issues = base_hw_issues_model_tFRx; + break; + case GPU_ID_PI_T86X: + issues = base_hw_issues_model_t86x; + break; + default: + dev_err(kbdev->dev, "Unknown GPU ID %x", gpu_id); + return MALI_ERROR_FUNCTION_FAILED; + } + } + + dev_info(kbdev->dev, "GPU identified as 0x%04x r%dp%d status %d", (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >> GPU_ID_VERSION_PRODUCT_ID_SHIFT, (gpu_id & GPU_ID_VERSION_MAJOR) >> GPU_ID_VERSION_MAJOR_SHIFT, (gpu_id & GPU_ID_VERSION_MINOR) >> GPU_ID_VERSION_MINOR_SHIFT, (gpu_id & GPU_ID_VERSION_STATUS) >> GPU_ID_VERSION_STATUS_SHIFT); + + for (; *issues != BASE_HW_ISSUE_END; issues++) + set_bit(*issues, &kbdev->hw_issues_mask[0]); + + return MALI_ERROR_NONE; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..1074290702ae455e3d7c080e21421f3951ba29c5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_hw.h @@ -0,0 +1,52 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * Run-time work-arounds helpers + */ + +#ifndef _KBASE_HW_H_ +#define _KBASE_HW_H_ + +#include "mali_kbase_defs.h" + +/** + * @brief Tell whether a work-around should be enabled + */ +#define kbase_hw_has_issue(kbdev, issue)\ + test_bit(issue, &(kbdev)->hw_issues_mask[0]) + +/** + * @brief Tell whether a feature is supported + */ +#define kbase_hw_has_feature(kbdev, feature)\ + test_bit(feature, &(kbdev)->hw_features_mask[0]) + +/** + * @brief Set the HW issues mask depending on the GPU ID + */ +mali_error kbase_hw_set_issues_mask(struct kbase_device *kbdev); + +/** + * @brief Set the features mask depending on the GPU ID + */ +void kbase_hw_set_features_mask(struct kbase_device *kbdev); + +#endif /* _KBASE_HW_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_instr.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_instr.c new file mode 100644 index 0000000000000000000000000000000000000000..a5cdba6fa6bd655039830904ce22f50f13aa7bef --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_instr.c @@ -0,0 +1,619 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_instr.c + * Base kernel instrumentation APIs. + */ + +#include +#include + +/** + * @brief Issue Cache Clean & Invalidate command to hardware + */ +static void kbasep_instr_hwcnt_cacheclean(struct kbase_device *kbdev) +{ + unsigned long flags; + unsigned long pm_flags; + u32 irq_mask; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Wait for any reset to complete */ + while (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.cache_clean_wait, + kbdev->hwcnt.state != KBASE_INSTR_STATE_RESETTING); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_REQUEST_CLEAN); + + /* Enable interrupt */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask | CLEAN_CACHES_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags); + + /* clean&invalidate the caches so we're sure the mmu tables for the dump buffer is valid */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CLEAN_INV_CACHES, NULL); + kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANING; + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); +} + +STATIC mali_error kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup) +{ + unsigned long flags, pm_flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbasep_js_device_data *js_devdata; + u32 irq_mask; + int ret; + u64 shader_cores_needed; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != setup); + KBASE_DEBUG_ASSERT(NULL == kbdev->hwcnt.suspended_kctx); + + shader_cores_needed = kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER); + + js_devdata = &kbdev->js_data; + + /* alignment failure */ + if ((setup->dump_buffer == 0ULL) || (setup->dump_buffer & (2048 - 1))) + goto out_err; + + /* Override core availability policy to ensure all cores are available */ + kbase_pm_ca_instr_enable(kbdev); + + /* Mark the context as active so the GPU is kept turned on */ + /* A suspend won't happen here, because we're in a syscall from a userspace + * thread. */ + kbase_pm_context_active(kbdev); + + /* Request the cores early on synchronously - we'll release them on any errors + * (e.g. instrumentation already active) */ + kbase_pm_request_cores_sync(kbdev, MALI_TRUE, shader_cores_needed); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + + if (kbdev->hwcnt.state != KBASE_INSTR_STATE_DISABLED) { + /* Instrumentation is already enabled */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out_unrequest_cores; + } + + /* Enable interrupt */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask | PRFCNT_SAMPLE_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags); + + /* In use, this context is the owner */ + kbdev->hwcnt.kctx = kctx; + /* Remember the dump address so we can reprogram it later */ + kbdev->hwcnt.addr = setup->dump_buffer; + /* Remember all the settings for suspend/resume */ + if (&kbdev->hwcnt.suspended_state != setup) + memcpy(&kbdev->hwcnt.suspended_state, setup, sizeof(kbdev->hwcnt.suspended_state)); + + /* Request the clean */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_REQUEST_CLEAN; + kbdev->hwcnt.triggered = 0; + /* Clean&invalidate the caches so we're sure the mmu tables for the dump buffer is valid */ + ret = queue_work(kbdev->hwcnt.cache_clean_wq, &kbdev->hwcnt.cache_clean_work); + KBASE_DEBUG_ASSERT(ret); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Wait for cacheclean to complete */ + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + + KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE); + + /* Schedule the context in */ + kbasep_js_schedule_privileged_ctx(kbdev, kctx); + + /* Configure */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_OFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), setup->dump_buffer & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), setup->dump_buffer >> 32, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), setup->jm_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), setup->shader_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), setup->l3_cache_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), setup->mmu_l2_bm, kctx); + /* Due to PRLAM-8186 we need to disable the Tiler before we enable the HW counter dump. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), 0, kctx); + else + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), setup->tiler_bm, kctx); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_MANUAL, kctx); + + /* If HW has PRLAM-8186 we can now re-enable the tiler HW counters dump */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), setup->tiler_bm, kctx); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + err = MALI_ERROR_NONE; + + dev_dbg(kbdev->dev, "HW counters dumping set-up for context %p", kctx); + return err; + out_unrequest_cores: + kbase_pm_unrequest_cores(kbdev, MALI_TRUE, shader_cores_needed); + kbase_pm_context_idle(kbdev); + out_err: + return err; +} + +/** + * @brief Enable HW counters collection + * + * Note: will wait for a cache clean to complete + */ +mali_error kbase_instr_hwcnt_enable(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup) +{ + struct kbase_device *kbdev; + mali_bool access_allowed; + + kbdev = kctx->kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + /* Determine if the calling task has access to this capability */ + access_allowed = kbase_security_has_capability(kctx, KBASE_SEC_INSTR_HW_COUNTERS_COLLECT, KBASE_SEC_FLAG_NOAUDIT); + if (MALI_FALSE == access_allowed) + return MALI_ERROR_FUNCTION_FAILED; + + return kbase_instr_hwcnt_enable_internal(kbdev, kctx, setup); +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_enable) + +/** + * @brief Disable HW counters collection + * + * Note: might sleep, waiting for an ongoing dump to complete + */ +mali_error kbase_instr_hwcnt_disable(struct kbase_context *kctx) +{ + unsigned long flags, pm_flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + u32 irq_mask; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + while (1) { + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_DISABLED) { + /* Instrumentation is not enabled */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out; + } + + if (kbdev->hwcnt.kctx != kctx) { + /* Instrumentation has been setup for another context */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + goto out; + } + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE) + break; + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Ongoing dump/setup - wait for its completion */ + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + } + + kbdev->hwcnt.state = KBASE_INSTR_STATE_DISABLED; + kbdev->hwcnt.triggered = 0; + + /* Disable interrupt */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask & ~PRFCNT_SAMPLE_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags); + + /* Disable the counters */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), 0, kctx); + + kbdev->hwcnt.kctx = NULL; + kbdev->hwcnt.addr = 0ULL; + + kbase_pm_ca_instr_disable(kbdev); + + kbase_pm_unrequest_cores(kbdev, MALI_TRUE, kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER)); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Release the context. This had its own Power Manager Active reference */ + kbasep_js_release_privileged_ctx(kbdev, kctx); + + /* Also release our Power Manager Active reference */ + kbase_pm_context_idle(kbdev); + + dev_dbg(kbdev->dev, "HW counters dumping disabled for context %p", kctx); + + err = MALI_ERROR_NONE; + + out: + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_disable) + +/** + * @brief Configure HW counters collection + */ +mali_error kbase_instr_hwcnt_setup(struct kbase_context *kctx, struct kbase_uk_hwcnt_setup *setup) +{ + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + if (NULL == setup) { + /* Bad parameter - abort */ + goto out; + } + + if (setup->dump_buffer != 0ULL) { + /* Enable HW counters */ + err = kbase_instr_hwcnt_enable(kctx, setup); + } else { + /* Disable HW counters */ + err = kbase_instr_hwcnt_disable(kctx); + } + + out: + return err; +} + +/** + * @brief Issue Dump command to hardware + * + * Notes: + * - does not sleep + */ +mali_error kbase_instr_hwcnt_dump_irq(struct kbase_context *kctx) +{ + unsigned long flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.kctx != kctx) { + /* The instrumentation has been setup for another context */ + goto unlock; + } + + if (kbdev->hwcnt.state != KBASE_INSTR_STATE_IDLE) { + /* HW counters are disabled or another dump is ongoing, or we're resetting */ + goto unlock; + } + + kbdev->hwcnt.triggered = 0; + + /* Mark that we're dumping - the PF handler can signal that we faulted */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_DUMPING; + + /* Reconfigure the dump address */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), kbdev->hwcnt.addr & 0xFFFFFFFF, NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), kbdev->hwcnt.addr >> 32, NULL); + + /* Start dumping */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_PRFCNT_SAMPLE, NULL, NULL, kbdev->hwcnt.addr, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_PRFCNT_SAMPLE, kctx); + + dev_dbg(kbdev->dev, "HW counters dumping done for context %p", kctx); + + err = MALI_ERROR_NONE; + + unlock: + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_irq) + +/** + * @brief Tell whether the HW counters dump has completed + * + * Notes: + * - does not sleep + * - success will be set to MALI_TRUE if the dump succeeded or + * MALI_FALSE on failure + */ +mali_bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx, mali_bool * const success) +{ + unsigned long flags; + mali_bool complete = MALI_FALSE; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != success); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE) { + *success = MALI_TRUE; + complete = MALI_TRUE; + } else if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) { + *success = MALI_FALSE; + complete = MALI_TRUE; + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + } + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + return complete; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_complete) + +/** + * @brief Issue Dump command to hardware and wait for completion + */ +mali_error kbase_instr_hwcnt_dump(struct kbase_context *kctx) +{ + unsigned long flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + err = kbase_instr_hwcnt_dump_irq(kctx); + if (MALI_ERROR_NONE != err) { + /* Can't dump HW counters */ + goto out; + } + + /* Wait for dump & cacheclean to complete */ + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) { + err = MALI_ERROR_FUNCTION_FAILED; + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + } else { + /* Dump done */ + KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE); + err = MALI_ERROR_NONE; + } + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + out: + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump) + +/** + * @brief Clear the HW counters + */ +mali_error kbase_instr_hwcnt_clear(struct kbase_context *kctx) +{ + unsigned long flags; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(NULL != kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + + /* Check it's the context previously set up and we're not already dumping */ + if (kbdev->hwcnt.kctx != kctx || kbdev->hwcnt.state != KBASE_INSTR_STATE_IDLE) + goto out; + + /* Clear the counters */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_PRFCNT_CLEAR, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_PRFCNT_CLEAR, kctx); + + err = MALI_ERROR_NONE; + + out: + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + return err; +} +KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_clear) + +/** + * Workqueue for handling cache cleaning + */ +void kbasep_cache_clean_worker(struct work_struct *data) +{ + struct kbase_device *kbdev; + unsigned long flags; + + kbdev = container_of(data, struct kbase_device, hwcnt.cache_clean_work); + + mutex_lock(&kbdev->cacheclean_lock); + kbasep_instr_hwcnt_cacheclean(kbdev); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Wait for our condition, and any reset to complete */ + while (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING || + kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANING) { + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.cache_clean_wait, + (kbdev->hwcnt.state != KBASE_INSTR_STATE_RESETTING + && kbdev->hwcnt.state != KBASE_INSTR_STATE_CLEANING)); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANED); + + /* All finished and idle */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + mutex_unlock(&kbdev->cacheclean_lock); +} + +/** + * @brief Dump complete interrupt received + */ +void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) { + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + } else if (kbdev->hwcnt.state == KBASE_INSTR_STATE_DUMPING) { + int ret; + /* Always clean and invalidate the cache after a successful dump */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_REQUEST_CLEAN; + ret = queue_work(kbdev->hwcnt.cache_clean_wq, &kbdev->hwcnt.cache_clean_work); + KBASE_DEBUG_ASSERT(ret); + } + /* NOTE: In the state KBASE_INSTR_STATE_RESETTING, We're in a reset, + * and the instrumentation state hasn't been restored yet - + * kbasep_reset_timeout_worker() will do the rest of the work */ + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); +} + +/** + * @brief Cache clean interrupt received + */ +void kbase_clean_caches_done(struct kbase_device *kbdev) +{ + u32 irq_mask; + + if (kbdev->hwcnt.state != KBASE_INSTR_STATE_DISABLED) { + unsigned long flags; + unsigned long pm_flags; + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Disable interrupt */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags); + irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask & ~CLEAN_CACHES_COMPLETED, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags); + + /* Wakeup... */ + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANING) { + /* Only wake if we weren't resetting */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANED; + wake_up(&kbdev->hwcnt.cache_clean_wait); + } + /* NOTE: In the state KBASE_INSTR_STATE_RESETTING, We're in a reset, + * and the instrumentation state hasn't been restored yet - + * kbasep_reset_timeout_worker() will do the rest of the work */ + + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + } +} + + +/* Disable instrumentation and wait for any existing dump to complete + * It's assumed that there's only one privileged context + * Safe to do this without lock when doing an OS suspend, because it only + * changes in response to user-space IOCTLs */ +void kbase_instr_hwcnt_suspend(struct kbase_device *kbdev) +{ + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(!kbdev->hwcnt.suspended_kctx); + + kctx = kbdev->hwcnt.kctx; + kbdev->hwcnt.suspended_kctx = kctx; + + /* Relevant state was saved into hwcnt.suspended_state when enabling the + * counters */ + + if (kctx) { + KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED); + kbase_instr_hwcnt_disable(kctx); + } +} + +void kbase_instr_hwcnt_resume(struct kbase_device *kbdev) +{ + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(kbdev); + + kctx = kbdev->hwcnt.suspended_kctx; + kbdev->hwcnt.suspended_kctx = NULL; + + if (kctx) { + mali_error err; + err = kbase_instr_hwcnt_enable_internal(kbdev, kctx, &kbdev->hwcnt.suspended_state); + WARN(err != MALI_ERROR_NONE, + "Failed to restore instrumented hardware counters on resume\n"); + } +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd.c new file mode 100644 index 0000000000000000000000000000000000000000..11c43ad60b72453810388ad4ec050cb314510597 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd.c @@ -0,0 +1,1727 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#if defined(CONFIG_DMA_SHARED_BUFFER) +#include +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ +#ifdef CONFIG_COMPAT +#include +#endif +#include +#include +#include +#include +#ifdef CONFIG_UMP +#include +#endif /* CONFIG_UMP */ +#include + +#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) +/* random32 was renamed to prandom_u32 in 3.8 */ +#define prandom_u32 random32 +#endif + +/* + * This is the kernel side of the API. Only entry points are: + * - kbase_jd_submit(): Called from userspace to submit a single bag + * - kbase_jd_done(): Called from interrupt context to track the + * completion of a job. + * Callouts: + * - to the job manager (enqueue a job) + * - to the event subsystem (signals the completion/failure of bag/job-chains). + */ + +static void __user * +get_compat_pointer(struct kbase_context *kctx, const union kbase_pointer *p) +{ +#ifdef CONFIG_COMPAT + if (kctx->is_compat) + return compat_ptr(p->compat_value); + else +#endif + return p->value; +} + +/* Runs an atom, either by handing to the JS or by immediately running it in the case of soft-jobs + * + * Returns whether the JS needs a reschedule. + * + * Note that the caller must also check the atom status and + * if it is KBASE_JD_ATOM_STATE_COMPLETED must call jd_done_nolock + */ +static int jd_run_atom(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED); + + if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) == BASE_JD_REQ_DEP) { + /* Dependency only atom */ + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + return 0; + } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { + /* Soft-job */ + if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (!kbase_replay_process(katom)) + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + } else if (kbase_process_soft_job(katom) == 0) { + kbase_finish_soft_job(katom); + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + } else { + /* The job has not completed */ + list_add_tail(&katom->dep_item[0], &kctx->waiting_soft_jobs); + } + return 0; + } + + katom->status = KBASE_JD_ATOM_STATE_IN_JS; + /* Queue an action about whether we should try scheduling a context */ + return kbasep_js_add_job(kctx, katom); +} + +#ifdef CONFIG_KDS + +/* Add the katom to the kds waiting list. + * Atoms must be added to the waiting list after a successful call to kds_async_waitall. + * The caller must hold the kbase_jd_context.lock */ + +static void kbase_jd_kds_waiters_add(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(katom); + + kctx = katom->kctx; + + list_add_tail(&katom->node, &kctx->waiting_kds_resource); +} + +/* Remove the katom from the kds waiting list. + * Atoms must be removed from the waiting list before a call to kds_resource_set_release_sync. + * The supplied katom must first have been added to the list with a call to kbase_jd_kds_waiters_add. + * The caller must hold the kbase_jd_context.lock */ + +static void kbase_jd_kds_waiters_remove(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + list_del(&katom->node); +} + +static void kds_dep_clear(void *callback_parameter, void *callback_extra_parameter) +{ + struct kbase_jd_atom *katom; + struct kbase_jd_context *ctx; + struct kbase_device *kbdev; + + katom = (struct kbase_jd_atom *)callback_parameter; + KBASE_DEBUG_ASSERT(katom); + ctx = &katom->kctx->jctx; + kbdev = katom->kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev); + + mutex_lock(&ctx->lock); + + /* KDS resource has already been satisfied (e.g. due to zapping) */ + if (katom->kds_dep_satisfied) + goto out; + + /* This atom's KDS dependency has now been met */ + katom->kds_dep_satisfied = MALI_TRUE; + + /* Check whether the atom's other dependencies were already met */ + if (!kbase_jd_katom_dep_atom(&katom->dep[0]) && + !kbase_jd_katom_dep_atom(&katom->dep[1])) { + /* katom dep complete, attempt to run it */ + mali_bool resched = MALI_FALSE; + + resched = jd_run_atom(katom); + + if (katom->status == KBASE_JD_ATOM_STATE_COMPLETED) { + /* The atom has already finished */ + resched |= jd_done_nolock(katom); + } + + if (resched) + kbasep_js_try_schedule_head_ctx(kbdev); + } + out: + mutex_unlock(&ctx->lock); +} + +static void kbase_cancel_kds_wait_job(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + + /* Prevent job_done_nolock from being called twice on an atom when + * there is a race between job completion and cancellation */ + + if (katom->status == KBASE_JD_ATOM_STATE_QUEUED) { + /* Wait was cancelled - zap the atom */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + if (jd_done_nolock(katom)) + kbasep_js_try_schedule_head_ctx(katom->kctx->kbdev); + } +} +#endif /* CONFIG_KDS */ + +#ifdef CONFIG_DMA_SHARED_BUFFER +static mali_error kbase_jd_umm_map(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + struct sg_table *sgt; + struct scatterlist *s; + int i; + phys_addr_t *pa; + mali_error err; + size_t count = 0; + + KBASE_DEBUG_ASSERT(reg->alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM); + KBASE_DEBUG_ASSERT(NULL == reg->alloc->imported.umm.sgt); + sgt = dma_buf_map_attachment(reg->alloc->imported.umm.dma_attachment, DMA_BIDIRECTIONAL); + + if (IS_ERR_OR_NULL(sgt)) + return MALI_ERROR_FUNCTION_FAILED; + + /* save for later */ + reg->alloc->imported.umm.sgt = sgt; + + pa = kbase_get_phy_pages(reg); + KBASE_DEBUG_ASSERT(pa); + + for_each_sg(sgt->sgl, s, sgt->nents, i) { + int j; + size_t pages = PFN_UP(sg_dma_len(s)); + + WARN_ONCE(sg_dma_len(s) & (PAGE_SIZE-1), + "sg_dma_len(s)=%u is not a multiple of PAGE_SIZE\n", + sg_dma_len(s)); + + WARN_ONCE(sg_dma_address(s) & (PAGE_SIZE-1), + "sg_dma_address(s)=%llx is not aligned to PAGE_SIZE\n", + (unsigned long long) sg_dma_address(s)); + + for (j = 0; (j < pages) && (count < reg->nr_pages); j++, count++) + *pa++ = sg_dma_address(s) + (j << PAGE_SHIFT); + WARN_ONCE(j < pages, + "sg list from dma_buf_map_attachment > dma_buf->size=%zu\n", + reg->alloc->imported.umm.dma_buf->size); + } + + if (WARN_ONCE(count < reg->nr_pages, + "sg list from dma_buf_map_attachment < dma_buf->size=%zu\n", + reg->alloc->imported.umm.dma_buf->size)) { + err = MALI_ERROR_FUNCTION_FAILED; + goto out; + } + + /* Update nents as we now have pages to map */ + reg->alloc->nents = count; + + err = kbase_mmu_insert_pages(kctx, reg->start_pfn, kbase_get_phy_pages(reg), kbase_reg_current_backed_size(reg), reg->flags | KBASE_REG_GPU_WR | KBASE_REG_GPU_RD); + +out: + if (MALI_ERROR_NONE != err) { + dma_buf_unmap_attachment(reg->alloc->imported.umm.dma_attachment, reg->alloc->imported.umm.sgt, DMA_BIDIRECTIONAL); + reg->alloc->imported.umm.sgt = NULL; + } + + return err; +} + +static void kbase_jd_umm_unmap(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(alloc); + KBASE_DEBUG_ASSERT(alloc->imported.umm.dma_attachment); + KBASE_DEBUG_ASSERT(alloc->imported.umm.sgt); + dma_buf_unmap_attachment(alloc->imported.umm.dma_attachment, + alloc->imported.umm.sgt, DMA_BIDIRECTIONAL); + alloc->imported.umm.sgt = NULL; + alloc->nents = 0; +} +#endif /* CONFIG_DMA_SHARED_BUFFER */ + +void kbase_jd_free_external_resources(struct kbase_jd_atom *katom) +{ +#ifdef CONFIG_KDS + if (katom->kds_rset) { + struct kbase_jd_context *jctx = &katom->kctx->jctx; + + /* + * As the atom is no longer waiting, remove it from + * the waiting list. + */ + + mutex_lock(&jctx->lock); + kbase_jd_kds_waiters_remove(katom); + mutex_unlock(&jctx->lock); + + /* Release the kds resource or cancel if zapping */ + kds_resource_set_release_sync(&katom->kds_rset); + } +#endif /* CONFIG_KDS */ +} + +static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); + +#ifdef CONFIG_KDS + /* Prevent the KDS resource from triggering the atom in case of zapping */ + if (katom->kds_rset) + katom->kds_dep_satisfied = MALI_TRUE; +#endif /* CONFIG_KDS */ + + kbase_gpu_vm_lock(katom->kctx); + /* only roll back if extres is non-NULL */ + if (katom->extres) { + u32 res_no; + + res_no = katom->nr_extres; + while (res_no-- > 0) { + struct kbase_mem_phy_alloc *alloc = katom->extres[res_no].alloc; +#ifdef CONFIG_DMA_SHARED_BUFFER + if (alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) { + alloc->imported.umm.current_mapping_usage_count--; + + if (0 == alloc->imported.umm.current_mapping_usage_count) { + struct kbase_va_region *reg; + + reg = kbase_region_tracker_find_region_base_address( + katom->kctx, + katom->extres[res_no].gpu_address); + + if (reg && reg->alloc == alloc) + kbase_mmu_teardown_pages( + katom->kctx, + reg->start_pfn, + kbase_reg_current_backed_size(reg)); + + kbase_jd_umm_unmap(katom->kctx, alloc); + } + } +#endif /* CONFIG_DMA_SHARED_BUFFER */ + kbase_mem_phy_alloc_put(katom->extres[res_no].alloc); + } + kfree(katom->extres); + katom->extres = NULL; + } + kbase_gpu_vm_unlock(katom->kctx); +} + +#if (defined(CONFIG_KDS) && defined(CONFIG_UMP)) || defined(CONFIG_DMA_SHARED_BUFFER_USES_KDS) +static void add_kds_resource(struct kds_resource *kds_res, struct kds_resource **kds_resources, u32 *kds_res_count, unsigned long *kds_access_bitmap, mali_bool exclusive) +{ + u32 i; + + for (i = 0; i < *kds_res_count; i++) { + /* Duplicate resource, ignore */ + if (kds_resources[i] == kds_res) + return; + } + + kds_resources[*kds_res_count] = kds_res; + if (exclusive) + set_bit(*kds_res_count, kds_access_bitmap); + (*kds_res_count)++; +} +#endif + +/* + * Set up external resources needed by this job. + * + * jctx.lock must be held when this is called. + */ + +static mali_error kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const struct base_jd_atom_v2 *user_atom) +{ + mali_error err_ret_val = MALI_ERROR_FUNCTION_FAILED; + u32 res_no; +#ifdef CONFIG_KDS + u32 kds_res_count = 0; + struct kds_resource **kds_resources = NULL; + unsigned long *kds_access_bitmap = NULL; +#endif /* CONFIG_KDS */ + struct base_external_resource *input_extres; + + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); + + /* no resources encoded, early out */ + if (!katom->nr_extres) + return MALI_ERROR_FUNCTION_FAILED; + + katom->extres = kmalloc_array(katom->nr_extres, sizeof(*katom->extres), GFP_KERNEL); + if (NULL == katom->extres) { + err_ret_val = MALI_ERROR_OUT_OF_MEMORY; + goto early_err_out; + } + + /* copy user buffer to the end of our real buffer. + * Make sure the struct sizes haven't changed in a way + * we don't support */ + BUILD_BUG_ON(sizeof(*input_extres) > sizeof(*katom->extres)); + input_extres = (struct base_external_resource *) + (((unsigned char *)katom->extres) + + (sizeof(*katom->extres) - sizeof(*input_extres)) * + katom->nr_extres); + + if (copy_from_user(input_extres, + get_compat_pointer(katom->kctx, &user_atom->extres_list), + sizeof(*input_extres) * katom->nr_extres) != 0) { + err_ret_val = MALI_ERROR_FUNCTION_FAILED; + goto early_err_out; + } +#ifdef CONFIG_KDS + /* assume we have to wait for all */ + KBASE_DEBUG_ASSERT(0 != katom->nr_extres); + kds_resources = kmalloc_array(katom->nr_extres, sizeof(struct kds_resource *), GFP_KERNEL); + + if (NULL == kds_resources) { + err_ret_val = MALI_ERROR_OUT_OF_MEMORY; + goto early_err_out; + } + + KBASE_DEBUG_ASSERT(0 != katom->nr_extres); + kds_access_bitmap = kzalloc(sizeof(unsigned long) * ((katom->nr_extres + BITS_PER_LONG - 1) / BITS_PER_LONG), GFP_KERNEL); + + if (NULL == kds_access_bitmap) { + err_ret_val = MALI_ERROR_OUT_OF_MEMORY; + goto early_err_out; + } +#endif /* CONFIG_KDS */ + + /* need to keep the GPU VM locked while we set up UMM buffers */ + kbase_gpu_vm_lock(katom->kctx); + for (res_no = 0; res_no < katom->nr_extres; res_no++) { + struct base_external_resource *res; + struct kbase_va_region *reg; + + res = &input_extres[res_no]; + reg = kbase_region_tracker_find_region_enclosing_address(katom->kctx, + res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE); + /* did we find a matching region object? */ + if (NULL == reg || (reg->flags & KBASE_REG_FREE)) { + /* roll back */ + goto failed_loop; + } + + /* decide what needs to happen for this resource */ + switch (reg->alloc->type) { + case BASE_TMEM_IMPORT_TYPE_UMP: + { +#if defined(CONFIG_KDS) && defined(CONFIG_UMP) + struct kds_resource *kds_res; + + kds_res = ump_dd_kds_resource_get(reg->alloc->imported.ump_handle); + if (kds_res) + add_kds_resource(kds_res, kds_resources, &kds_res_count, + kds_access_bitmap, + res->ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE); +#endif /*defined(CONFIG_KDS) && defined(CONFIG_UMP) */ + break; + } +#ifdef CONFIG_DMA_SHARED_BUFFER + case BASE_TMEM_IMPORT_TYPE_UMM: + { +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct kds_resource *kds_res; + + kds_res = get_dma_buf_kds_resource(reg->alloc->imported.umm.dma_buf); + if (kds_res) + add_kds_resource(kds_res, kds_resources, &kds_res_count, kds_access_bitmap, res->ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE); +#endif + reg->alloc->imported.umm.current_mapping_usage_count++; + if (1 == reg->alloc->imported.umm.current_mapping_usage_count) { + /* use a local variable to not pollute err_ret_val + * with a potential success value as some other gotos depend + * on the default error code stored in err_ret_val */ + mali_error tmp; + tmp = kbase_jd_umm_map(katom->kctx, reg); + if (MALI_ERROR_NONE != tmp) { + /* failed to map this buffer, roll back */ + err_ret_val = tmp; + reg->alloc->imported.umm.current_mapping_usage_count--; + goto failed_loop; + } + } + break; + } +#endif + default: + goto failed_loop; + } + + /* finish with updating out array with the data we found */ + /* NOTE: It is important that this is the last thing we do (or + * at least not before the first write) as we overwrite elements + * as we loop and could be overwriting ourself, so no writes + * until the last read for an element. + * */ + katom->extres[res_no].gpu_address = reg->start_pfn << PAGE_SHIFT; /* save the start_pfn (as an address, not pfn) to use fast lookup later */ + katom->extres[res_no].alloc = kbase_mem_phy_alloc_get(reg->alloc); + } + /* successfully parsed the extres array */ + /* drop the vm lock before we call into kds */ + kbase_gpu_vm_unlock(katom->kctx); + +#ifdef CONFIG_KDS + if (kds_res_count) { + int wait_failed; + + /* We have resources to wait for with kds */ + katom->kds_dep_satisfied = MALI_FALSE; + + wait_failed = kds_async_waitall(&katom->kds_rset, + &katom->kctx->jctx.kds_cb, katom, NULL, + kds_res_count, kds_access_bitmap, + kds_resources); + + if (wait_failed) + goto failed_kds_setup; + else + kbase_jd_kds_waiters_add(katom); + } else { + /* Nothing to wait for, so kds dep met */ + katom->kds_dep_satisfied = MALI_TRUE; + } + kfree(kds_resources); + kfree(kds_access_bitmap); +#endif /* CONFIG_KDS */ + + /* all done OK */ + return MALI_ERROR_NONE; + +/* error handling section */ + +#ifdef CONFIG_KDS + failed_kds_setup: + + /* lock before we unmap */ + kbase_gpu_vm_lock(katom->kctx); +#endif /* CONFIG_KDS */ + + failed_loop: + /* undo the loop work */ + while (res_no-- > 0) { + struct kbase_mem_phy_alloc *alloc = katom->extres[res_no].alloc; +#ifdef CONFIG_DMA_SHARED_BUFFER + if (alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) { + alloc->imported.umm.current_mapping_usage_count--; + + if (0 == alloc->imported.umm.current_mapping_usage_count) { + struct kbase_va_region *reg; + + reg = kbase_region_tracker_find_region_base_address( + katom->kctx, + katom->extres[res_no].gpu_address); + + if (reg && reg->alloc == alloc) + kbase_mmu_teardown_pages(katom->kctx, + reg->start_pfn, + kbase_reg_current_backed_size(reg)); + + kbase_jd_umm_unmap(katom->kctx, alloc); + } + } +#endif /* CONFIG_DMA_SHARED_BUFFER */ + kbase_mem_phy_alloc_put(alloc); + } + kbase_gpu_vm_unlock(katom->kctx); + + early_err_out: + kfree(katom->extres); + katom->extres = NULL; +#ifdef CONFIG_KDS + kfree(kds_resources); + kfree(kds_access_bitmap); +#endif /* CONFIG_KDS */ + return err_ret_val; +} + +STATIC INLINE void jd_resolve_dep(struct list_head *out_list, struct kbase_jd_atom *katom, u8 d, bool ctx_is_dying) +{ + u8 other_d = !d; + + while (!list_empty(&katom->dep_head[d])) { + struct kbase_jd_atom *dep_atom; + u8 dep_type; + + dep_atom = list_entry(katom->dep_head[d].next, + struct kbase_jd_atom, dep_item[d]); + dep_type = kbase_jd_katom_dep_type(&dep_atom->dep[d]); + + list_del(katom->dep_head[d].next); + + kbase_jd_katom_dep_clear(&dep_atom->dep[d]); + + if (katom->event_code != BASE_JD_EVENT_DONE && + (dep_type != BASE_JD_DEP_TYPE_ORDER || ctx_is_dying)) { + /* Atom failed, so remove the other dependencies and immediately fail the atom */ + if (kbase_jd_katom_dep_atom(&dep_atom->dep[other_d])) { + list_del(&dep_atom->dep_item[other_d]); + kbase_jd_katom_dep_clear(&dep_atom->dep[other_d]); + } +#ifdef CONFIG_KDS + if (!dep_atom->kds_dep_satisfied) { + /* Just set kds_dep_satisfied to true. If the callback happens after this then it will early out and + * do nothing. If the callback doesn't happen then kbase_jd_post_external_resources will clean up + */ + dep_atom->kds_dep_satisfied = MALI_TRUE; + } +#endif + /* at this point a dependency to the failed job is already removed */ + dep_atom->event_code = katom->event_code; + KBASE_DEBUG_ASSERT(dep_atom->status != KBASE_JD_ATOM_STATE_UNUSED); + dep_atom->status = KBASE_JD_ATOM_STATE_COMPLETED; + + list_add_tail(&dep_atom->dep_item[0], out_list); + } else if (!kbase_jd_katom_dep_atom(&dep_atom->dep[other_d])) { +#ifdef CONFIG_KDS + if (dep_atom->kds_dep_satisfied) +#endif + list_add_tail(&dep_atom->dep_item[0], out_list); + } + } +} + +KBASE_EXPORT_TEST_API(jd_resolve_dep) + +#if MALI_CUSTOMER_RELEASE == 0 +static void jd_force_failure(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + kbdev->force_replay_count++; + + if (kbdev->force_replay_count >= kbdev->force_replay_limit) { + kbdev->force_replay_count = 0; + katom->event_code = BASE_JD_EVENT_FORCE_REPLAY; + + if (kbdev->force_replay_random) + kbdev->force_replay_limit = + (prandom_u32() % KBASEP_FORCE_REPLAY_RANDOM_LIMIT) + 1; + + dev_info(kbdev->dev, "force_replay : promoting to error\n"); + } +} + +/** Test to see if atom should be forced to fail. + * + * This function will check if an atom has a replay job as a dependent. If so + * then it will be considered for forced failure. */ +static void jd_check_force_failure(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct kbase_device *kbdev = kctx->kbdev; + int i; + + if ((kbdev->force_replay_limit == KBASEP_FORCE_REPLAY_DISABLED) || + (katom->core_req & BASEP_JD_REQ_EVENT_NEVER)) + return; + + for (i = 1; i < BASE_JD_ATOM_COUNT; i++) { + if (kbase_jd_katom_dep_atom(&kctx->jctx.atoms[i].dep[0]) == katom || + kbase_jd_katom_dep_atom(&kctx->jctx.atoms[i].dep[1]) == katom) { + struct kbase_jd_atom *dep_atom = &kctx->jctx.atoms[i]; + + if ((dep_atom->core_req & BASEP_JD_REQ_ATOM_TYPE) == + BASE_JD_REQ_SOFT_REPLAY && + (dep_atom->core_req & kbdev->force_replay_core_req) + == kbdev->force_replay_core_req) { + jd_force_failure(kbdev, katom); + return; + } + } + } +} +#endif + +/* + * Perform the necessary handling of an atom that has finished running + * on the GPU. + * + * Note that if this is a soft-job that has had kbase_prepare_soft_job called on it then the caller + * is responsible for calling kbase_finish_soft_job *before* calling this function. + * + * The caller must hold the kbase_jd_context.lock. + */ +mali_bool jd_done_nolock(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info; + struct kbase_device *kbdev = kctx->kbdev; + struct list_head completed_jobs; + struct list_head runnable_jobs; + mali_bool need_to_try_schedule_context = MALI_FALSE; + int i; + + INIT_LIST_HEAD(&completed_jobs); + INIT_LIST_HEAD(&runnable_jobs); + + KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED); + +#if MALI_CUSTOMER_RELEASE == 0 + jd_check_force_failure(katom); +#endif + + + /* This is needed in case an atom is failed due to being invalid, this + * can happen *before* the jobs that the atom depends on have completed */ + for (i = 0; i < 2; i++) { + if (kbase_jd_katom_dep_atom(&katom->dep[i])) { + list_del(&katom->dep_item[i]); + kbase_jd_katom_dep_clear(&katom->dep[i]); + } + } + + /* With PRLAM-10817 or PRLAM-10959 the last tile of a fragment job being soft-stopped can fail with + * BASE_JD_EVENT_TILE_RANGE_FAULT. + * + * So here if the fragment job failed with TILE_RANGE_FAULT and it has been soft-stopped, then we promote the + * error code to BASE_JD_EVENT_DONE + */ + + if ((kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10817) || kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10959)) && + katom->event_code == BASE_JD_EVENT_TILE_RANGE_FAULT) { + if ((katom->core_req & BASE_JD_REQ_FS) && (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED)) { + /* Promote the failure to job done */ + katom->event_code = BASE_JD_EVENT_DONE; + katom->atom_flags = katom->atom_flags & (~KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED); + } + } + + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + list_add_tail(&katom->dep_item[0], &completed_jobs); + + while (!list_empty(&completed_jobs)) { + katom = list_entry(completed_jobs.prev, struct kbase_jd_atom, dep_item[0]); + list_del(completed_jobs.prev); + + KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED); + + for (i = 0; i < 2; i++) + jd_resolve_dep(&runnable_jobs, katom, i, + js_kctx_info->ctx.is_dying); + + if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) + kbase_jd_post_external_resources(katom); + + while (!list_empty(&runnable_jobs)) { + struct kbase_jd_atom *node; + + node = list_entry(runnable_jobs.prev, struct kbase_jd_atom, dep_item[0]); + + list_del(runnable_jobs.prev); + + KBASE_DEBUG_ASSERT(node->status != KBASE_JD_ATOM_STATE_UNUSED); + + if (node->status != KBASE_JD_ATOM_STATE_COMPLETED) { + need_to_try_schedule_context |= jd_run_atom(node); + } else { + node->event_code = katom->event_code; + + if ((node->core_req & BASEP_JD_REQ_ATOM_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(node)) + /* Don't complete this atom */ + continue; + } else if (node->core_req & + BASE_JD_REQ_SOFT_JOB) { + /* If this is a fence wait then remove it from the list of sync waiters. */ + if (BASE_JD_REQ_SOFT_FENCE_WAIT == node->core_req) + list_del(&node->dep_item[0]); + + kbase_finish_soft_job(node); + } + node->status = KBASE_JD_ATOM_STATE_COMPLETED; + } + + if (node->status == KBASE_JD_ATOM_STATE_COMPLETED) + list_add_tail(&node->dep_item[0], &completed_jobs); + } + + /* Register a completed job as a disjoint event when the GPU + * is in a disjoint state (ie. being reset or replaying jobs). + */ + kbase_disjoint_event_potential(kctx->kbdev); + kbase_event_post(kctx, katom); + + /* Decrement and check the TOTAL number of jobs. This includes + * those not tracked by the scheduler: 'not ready to run' and + * 'dependency-only' jobs. */ + if (--kctx->jctx.job_nr == 0) + wake_up(&kctx->jctx.zero_jobs_wait); /* All events are safely queued now, and we can signal any waiter + * that we've got no more jobs (so we can be safely terminated) */ + } + + return need_to_try_schedule_context; +} + +KBASE_EXPORT_TEST_API(jd_done_nolock) + +#ifdef CONFIG_GPU_TRACEPOINTS +enum { + CORE_REQ_DEP_ONLY, + CORE_REQ_SOFT, + CORE_REQ_COMPUTE, + CORE_REQ_FRAGMENT, + CORE_REQ_VERTEX, + CORE_REQ_TILER, + CORE_REQ_FRAGMENT_VERTEX, + CORE_REQ_FRAGMENT_VERTEX_TILER, + CORE_REQ_FRAGMENT_TILER, + CORE_REQ_VERTEX_TILER, + CORE_REQ_UNKNOWN +}; +static const char * const core_req_strings[] = { + "Dependency Only Job", + "Soft Job", + "Compute Shader Job", + "Fragment Shader Job", + "Vertex/Geometry Shader Job", + "Tiler Job", + "Fragment Shader + Vertex/Geometry Shader Job", + "Fragment Shader + Vertex/Geometry Shader Job + Tiler Job", + "Fragment Shader + Tiler Job", + "Vertex/Geometry Shader Job + Tiler Job", + "Unknown Job" +}; +static const char *kbasep_map_core_reqs_to_string(base_jd_core_req core_req) +{ + if (core_req & BASE_JD_REQ_SOFT_JOB) + return core_req_strings[CORE_REQ_SOFT]; + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) + return core_req_strings[CORE_REQ_COMPUTE]; + switch (core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) { + case BASE_JD_REQ_DEP: + return core_req_strings[CORE_REQ_DEP_ONLY]; + case BASE_JD_REQ_FS: + return core_req_strings[CORE_REQ_FRAGMENT]; + case BASE_JD_REQ_CS: + return core_req_strings[CORE_REQ_VERTEX]; + case BASE_JD_REQ_T: + return core_req_strings[CORE_REQ_TILER]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_CS): + return core_req_strings[CORE_REQ_FRAGMENT_VERTEX]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_FRAGMENT_TILER]; + case (BASE_JD_REQ_CS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_VERTEX_TILER]; + case (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T): + return core_req_strings[CORE_REQ_FRAGMENT_VERTEX_TILER]; + } + return core_req_strings[CORE_REQ_UNKNOWN]; +} +#endif + +mali_bool jd_submit_atom(struct kbase_context *kctx, + const struct base_jd_atom_v2 *user_atom, + struct kbase_jd_atom *katom) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + base_jd_core_req core_req; + int queued = 0; + int i; + mali_bool ret; + + /* Update the TOTAL number of jobs. This includes those not tracked by + * the scheduler: 'not ready to run' and 'dependency-only' jobs. */ + jctx->job_nr++; + + core_req = user_atom->core_req; + + katom->start_timestamp.tv64 = 0; + katom->time_spent_us = 0; + katom->udata = user_atom->udata; + katom->kctx = kctx; + katom->nr_extres = user_atom->nr_extres; + katom->extres = NULL; + katom->device_nr = user_atom->device_nr; + katom->affinity = 0; + katom->jc = user_atom->jc; + katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED; + katom->core_req = core_req; + katom->nice_prio = user_atom->prio; + katom->atom_flags = 0; + katom->retry_count = 0; + +#ifdef CONFIG_KDS + /* Start by assuming that the KDS dependencies are satisfied, + * kbase_jd_pre_external_resources will correct this if there are dependencies */ + katom->kds_dep_satisfied = MALI_TRUE; + katom->kds_rset = NULL; +#endif /* CONFIG_KDS */ + + /* Don't do anything if there is a mess up with dependencies. + This is done in a separate cycle to check both the dependencies at ones, otherwise + it will be extra complexity to deal with 1st dependency ( just added to the list ) + if only the 2nd one has invalid config. + */ + for (i = 0; i < 2; i++) { + int dep_atom_number = user_atom->pre_dep[i].atom_id; + base_jd_dep_type dep_atom_type = user_atom->pre_dep[i].dependency_type; + + if (dep_atom_number) { + if ( dep_atom_type != BASE_JD_DEP_TYPE_ORDER && + dep_atom_type != BASE_JD_DEP_TYPE_DATA ) { + katom->event_code = BASE_JD_EVENT_JOB_CONFIG_FAULT; + katom->status = KBASE_JD_ATOM_STATE_COMPLETED; + ret = jd_done_nolock(katom); + goto out; + } + } + } + + /* Add dependencies */ + for (i = 0; i < 2; i++) { + int dep_atom_number = user_atom->pre_dep[i].atom_id; + base_jd_dep_type dep_atom_type = user_atom->pre_dep[i].dependency_type; + + kbase_jd_katom_dep_clear(&katom->dep[i]); + + if (dep_atom_number) { + struct kbase_jd_atom *dep_atom = &jctx->atoms[dep_atom_number]; + + if (dep_atom->status == KBASE_JD_ATOM_STATE_UNUSED || dep_atom->status == KBASE_JD_ATOM_STATE_COMPLETED) { + if (dep_atom->event_code != BASE_JD_EVENT_DONE) { + /* don't stop this atom if it has an order dependency only to the failed one, + try to submit it throught the normal path */ + if ( dep_atom_type == BASE_JD_DEP_TYPE_ORDER && + dep_atom->event_code > BASE_JD_EVENT_ACTIVE) { + continue; + } + + if (i == 1 && kbase_jd_katom_dep_atom(&katom->dep[0])) { + /* Remove the previous dependency */ + list_del(&katom->dep_item[0]); + kbase_jd_katom_dep_clear(&katom->dep[0]); + } + + /* Atom has completed, propagate the error code if any */ + katom->event_code = dep_atom->event_code; + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + if ((katom->core_req & + BASEP_JD_REQ_ATOM_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(katom)) { + ret = MALI_FALSE; + goto out; + } + } + ret = jd_done_nolock(katom); + + goto out; + } + } else { + /* Atom is in progress, add this atom to the list */ + list_add_tail(&katom->dep_item[i], &dep_atom->dep_head[i]); + kbase_jd_katom_dep_set(&katom->dep[i], dep_atom, dep_atom_type); + queued = 1; + } + } + } + + /* These must occur after the above loop to ensure that an atom that + * depends on a previous atom with the same number behaves as expected */ + katom->event_code = BASE_JD_EVENT_DONE; + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + + /* Reject atoms with job chain = NULL, as these cause issues with soft-stop */ + if (0 == katom->jc && (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) { + dev_warn(kctx->kbdev->dev, "Rejecting atom with jc = NULL"); + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + + /* Reject atoms with an invalid device_nr */ + if ((katom->core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) && + (katom->device_nr >= kctx->kbdev->gpu_props.num_core_groups)) { + dev_warn(kctx->kbdev->dev, "Rejecting atom with invalid device_nr %d", katom->device_nr); + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + + /* + * If the priority is increased we need to check the caller has security caps to do this, if + * priority is decreased then this is ok as the result will have no negative impact on other + * processes running. + */ + if (0 > katom->nice_prio) { + mali_bool access_allowed; + + access_allowed = kbase_security_has_capability(kctx, + KBASE_SEC_MODIFY_PRIORITY, KBASE_SEC_FLAG_NOAUDIT); + + if (!access_allowed) { + /* For unprivileged processes - a negative priority is interpreted as zero */ + katom->nice_prio = 0; + } + } + + /* Scale priority range to use NICE range */ + if (katom->nice_prio) { + /* Remove sign for calculation */ + int nice_priority = katom->nice_prio + 128; + + /* Fixed point maths to scale from ..255 to 0..39 (NICE range with +20 offset) */ + katom->nice_prio = (((20 << 16) / 128) * nice_priority) >> 16; + } + + if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { + /* handle what we need to do to access the external resources */ + if (MALI_ERROR_NONE != kbase_jd_pre_external_resources(katom, user_atom)) { + /* setup failed (no access, bad resource, unknown resource types, etc.) */ + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + } + + /* Initialize the jobscheduler policy for this atom. Function will + * return error if the atom is malformed. + * + * Soft-jobs never enter the job scheduler but have their own initialize method. + * + * If either fail then we immediately complete the atom with an error. + */ + if ((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0) { + union kbasep_js_policy *js_policy = &(kctx->kbdev->js_data.policy); + + if (MALI_ERROR_NONE != kbasep_js_policy_init_job(js_policy, kctx, katom)) { + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + } else { + /* Soft-job */ + if (MALI_ERROR_NONE != kbase_prepare_soft_job(katom)) { + katom->event_code = BASE_JD_EVENT_JOB_INVALID; + ret = jd_done_nolock(katom); + goto out; + } + } + +#ifdef CONFIG_GPU_TRACEPOINTS + katom->work_id = atomic_inc_return(&jctx->work_id); + trace_gpu_job_enqueue((u32)kctx->id, katom->work_id, kbasep_map_core_reqs_to_string(katom->core_req)); +#endif + + if (queued) { + ret = MALI_FALSE; + goto out; + } +#ifdef CONFIG_KDS + if (!katom->kds_dep_satisfied) { + /* Queue atom due to KDS dependency */ + ret = MALI_FALSE; + goto out; + } +#endif /* CONFIG_KDS */ + + if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) + == BASE_JD_REQ_SOFT_REPLAY) { + if (kbase_replay_process(katom)) + ret = MALI_FALSE; + else + ret = jd_done_nolock(katom); + + goto out; + } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { + if (kbase_process_soft_job(katom) == 0) { + kbase_finish_soft_job(katom); + ret = jd_done_nolock(katom); + goto out; + } + /* The job has not yet completed */ + list_add_tail(&katom->dep_item[0], &kctx->waiting_soft_jobs); + ret = MALI_FALSE; + } else if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) { + katom->status = KBASE_JD_ATOM_STATE_IN_JS; + ret = kbasep_js_add_job(kctx, katom); + } else { + /* This is a pure dependency. Resolve it immediately */ + ret = jd_done_nolock(katom); + } + + out: + return ret; +} + +#ifdef BASE_LEGACY_UK6_SUPPORT +mali_error kbase_jd_submit(struct kbase_context *kctx, + const struct kbase_uk_job_submit *submit_data, + int uk6_atom) +#else +mali_error kbase_jd_submit(struct kbase_context *kctx, + const struct kbase_uk_job_submit *submit_data) +#endif /* BASE_LEGACY_UK6_SUPPORT */ +{ + struct kbase_jd_context *jctx = &kctx->jctx; + mali_error err = MALI_ERROR_NONE; + int i; + mali_bool need_to_try_schedule_context = MALI_FALSE; + struct kbase_device *kbdev; + void __user *user_addr; + + /* + * kbase_jd_submit isn't expected to fail and so all errors with the jobs + * are reported by immediately falling them (through event system) + */ + kbdev = kctx->kbdev; + + beenthere(kctx, "%s", "Enter"); + + if ((kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) != 0) { + dev_err(kbdev->dev, "Attempt to submit to a context that has SUBMIT_DISABLED set on it"); + return MALI_ERROR_FUNCTION_FAILED; + } + +#ifdef BASE_LEGACY_UK6_SUPPORT + if ((uk6_atom && submit_data->stride != + sizeof(struct base_jd_atom_v2_uk6)) || + submit_data->stride != sizeof(base_jd_atom_v2)) { +#else + if (submit_data->stride != sizeof(base_jd_atom_v2)) { +#endif /* BASE_LEGACY_UK6_SUPPORT */ + dev_err(kbdev->dev, "Stride passed to job_submit doesn't match kernel"); + return MALI_ERROR_FUNCTION_FAILED; + } + + user_addr = get_compat_pointer(kctx, &submit_data->addr); + + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_add_return(submit_data->nr_atoms, &kctx->timeline.jd_atoms_in_flight)); + + for (i = 0; i < submit_data->nr_atoms; i++) { + struct base_jd_atom_v2 user_atom; + struct kbase_jd_atom *katom; + +#ifdef BASE_LEGACY_UK6_SUPPORT + if (uk6_atom) { + struct base_jd_atom_v2_uk6 user_atom_v6; + base_jd_dep_type dep_types[2] = {BASE_JD_DEP_TYPE_DATA, BASE_JD_DEP_TYPE_DATA}; + + if (copy_from_user(&user_atom_v6, user_addr, + sizeof(user_atom_v6))) { + err = MALI_ERROR_FUNCTION_FAILED; + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, + atomic_sub_return( + submit_data->nr_atoms - i, + &kctx->timeline.jd_atoms_in_flight)); + break; + } + /* Convert from UK6 atom format to UK7 format */ + user_atom.jc = user_atom_v6.jc; + user_atom.udata = user_atom_v6.udata; + user_atom.extres_list = user_atom_v6.extres_list; + user_atom.nr_extres = user_atom_v6.nr_extres; + user_atom.core_req = user_atom_v6.core_req; + + /* atom number 0 is used for no dependency atoms */ + if (!user_atom_v6.pre_dep[0]) + dep_types[0] = BASE_JD_DEP_TYPE_INVALID; + + base_jd_atom_dep_set(&user_atom.pre_dep[0], + user_atom_v6.pre_dep[0], + dep_types[0]); + + /* atom number 0 is used for no dependency atoms */ + if (!user_atom_v6.pre_dep[1]) + dep_types[1] = BASE_JD_DEP_TYPE_INVALID; + + base_jd_atom_dep_set(&user_atom.pre_dep[1], + user_atom_v6.pre_dep[1], + dep_types[1]); + + user_atom.atom_number = user_atom_v6.atom_number; + user_atom.prio = user_atom_v6.prio; + user_atom.device_nr = user_atom_v6.device_nr; + } else { +#endif /* BASE_LEGACY_UK6_SUPPORT */ + if (copy_from_user(&user_atom, user_addr, sizeof(user_atom)) != 0) { + err = MALI_ERROR_FUNCTION_FAILED; + KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_sub_return(submit_data->nr_atoms - i, &kctx->timeline.jd_atoms_in_flight)); + break; + } +#ifdef BASE_LEGACY_UK6_SUPPORT + } +#endif /* BASE_LEGACY_UK6_SUPPORT */ + + user_addr = (void __user *)((uintptr_t) user_addr + submit_data->stride); + + mutex_lock(&jctx->lock); + katom = &jctx->atoms[user_atom.atom_number]; + + while (katom->status != KBASE_JD_ATOM_STATE_UNUSED) { + /* Atom number is already in use, wait for the atom to + * complete + */ + mutex_unlock(&jctx->lock); + + /* This thread will wait for the atom to complete. Due + * to thread scheduling we are not sure that the other + * thread that owns the atom will also schedule the + * context, so we force the scheduler to be active and + * hence eventually schedule this context at some point + * later. + */ + kbasep_js_try_schedule_head_ctx(kctx->kbdev); + if (wait_event_killable(katom->completed, + katom->status == KBASE_JD_ATOM_STATE_UNUSED)) { + /* We're being killed so the result code + * doesn't really matter + */ + return MALI_ERROR_NONE; + } + mutex_lock(&jctx->lock); + } + + need_to_try_schedule_context |= + jd_submit_atom(kctx, &user_atom, katom); + + /* Register a completed job as a disjoint event when the GPU is in a disjoint state + * (ie. being reset or replaying jobs). + */ + kbase_disjoint_event_potential(kbdev); + + mutex_unlock(&jctx->lock); + } + + if (need_to_try_schedule_context) + kbasep_js_try_schedule_head_ctx(kbdev); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_jd_submit) + +static void kbasep_jd_cacheclean(struct kbase_device *kbdev) +{ + /* Limit the number of loops to avoid a hang if the interrupt is missed */ + u32 max_loops = KBASE_CLEAN_CACHE_MAX_LOOPS; + + mutex_lock(&kbdev->cacheclean_lock); + + /* use GPU_COMMAND completion solution */ + /* clean & invalidate the caches */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CLEAN_INV_CACHES, NULL); + + /* wait for cache flush to complete before continuing */ + while (--max_loops && (kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL) & CLEAN_CACHES_COMPLETED) == 0) + ; + + /* clear the CLEAN_CACHES_COMPLETED irq */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, NULL, 0u, CLEAN_CACHES_COMPLETED); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), CLEAN_CACHES_COMPLETED, NULL); + KBASE_DEBUG_ASSERT_MSG(kbdev->hwcnt.state != KBASE_INSTR_STATE_CLEANING, + "Instrumentation code was cleaning caches, but Job Management code cleared their IRQ - Instrumentation code will now hang."); + + mutex_unlock(&kbdev->cacheclean_lock); +} + +/** + * This function: + * - requeues the job from the runpool (if it was soft-stopped/removed from NEXT registers) + * - removes it from the system if it finished/failed/was cancelled. + * - resolves dependencies to add dependent jobs to the context, potentially starting them if necessary (which may add more references to the context) + * - releases the reference to the context from the no-longer-running job. + * - Handles retrying submission outside of IRQ context if it failed from within IRQ context. + */ +static void jd_done_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); + struct kbase_jd_context *jctx; + struct kbase_context *kctx; + struct kbasep_js_kctx_info *js_kctx_info; + union kbasep_js_policy *js_policy; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + u64 cache_jc = katom->jc; + struct kbasep_js_atom_retained_state katom_retained_state; + + /* Soft jobs should never reach this function */ + KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); + + kctx = katom->kctx; + jctx = &kctx->jctx; + kbdev = kctx->kbdev; + js_kctx_info = &kctx->jctx.sched_info; + + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + + KBASE_TRACE_ADD(kbdev, JD_DONE_WORKER, kctx, katom, katom->jc, 0); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6787) && katom->event_code != BASE_JD_EVENT_DONE && !(katom->event_code & BASE_JD_SW_EVENT)) + kbasep_jd_cacheclean(kbdev); /* cache flush when jobs complete with non-done codes */ + else if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10676)) { + if (kbdev->gpu_props.num_core_groups > 1 && + !(katom->affinity & kbdev->gpu_props.props.coherency_info.group[0].core_mask) && + (katom->affinity & kbdev->gpu_props.props.coherency_info.group[1].core_mask)) { + dev_dbg(kbdev->dev, "JD: Flushing cache due to PRLAM-10676\n"); + kbasep_jd_cacheclean(kbdev); + } + } + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10969) && + (katom->core_req & BASE_JD_REQ_FS) && + katom->event_code == BASE_JD_EVENT_TILE_RANGE_FAULT && + (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED) && + !(katom->atom_flags & KBASE_KATOM_FLAGS_RERUN)) { + dev_dbg(kbdev->dev, "Soft-stopped fragment shader job got a TILE_RANGE_FAULT. Possible HW issue, trying SW workaround\n"); + if (kbasep_10969_workaround_clamp_coordinates(katom)) { + /* The job had a TILE_RANGE_FAULT after was soft-stopped. + * Due to an HW issue we try to execute the job + * again. + */ + dev_dbg(kbdev->dev, "Clamping has been executed, try to rerun the job\n"); + katom->event_code = BASE_JD_EVENT_STOPPED; + katom->atom_flags |= KBASE_KATOM_FLAGS_RERUN; + + /* The atom will be requeued, but requeing does not submit more + * jobs. If this was the last job, we must also ensure that more + * jobs will be run on slot 0 - this is a Fragment job. */ + kbasep_js_set_job_retry_submit_slot(katom, 0); + } + } + + /* + * Begin transaction on JD context and JS context + */ + mutex_lock(&jctx->lock); + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + + /* This worker only gets called on contexts that are scheduled *in*. This is + * because it only happens in response to an IRQ from a job that was + * running. + */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE); + + /* If job was rejected due to BASE_JD_EVENT_PM_EVENT but was not + * specifically targeting core group 1, then re-submit targeting core + * group 0 */ + if (katom->event_code == BASE_JD_EVENT_PM_EVENT && !(katom->core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) { + katom->event_code = BASE_JD_EVENT_STOPPED; + /* Don't need to worry about any previously set retry-slot - it's + * impossible for it to have been set previously, because we guarantee + * kbase_jd_done() was called with done_code==0 on this atom */ + kbasep_js_set_job_retry_submit_slot(katom, 1); + } + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) + kbase_as_poking_timer_release_atom(kbdev, kctx, katom); + + /* Release cores this job was using (this might power down unused cores, and + * cause extra latency if a job submitted here - such as depenedent jobs - + * would use those cores) */ + kbasep_js_job_check_deref_cores(kbdev, katom); + + /* Retain state before the katom disappears */ + kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); + + if (!kbasep_js_has_atom_finished(&katom_retained_state)) { + unsigned long flags; + + /* Requeue the atom on soft-stop / removed from NEXT registers */ + dev_dbg(kbdev->dev, "JS: Soft Stopped/Removed from next on Ctx %p; Requeuing", kctx); + + mutex_lock(&js_devdata->runpool_mutex); + kbasep_js_clear_job_retry_submit(katom); + /* An atom that has been hard-stopped might have previously + * been soft-stopped and has just finished before the hard-stop + * occurred. For this reason, clear the hard-stopped flag */ + katom->atom_flags &= ~(KBASE_KATOM_FLAG_BEEN_HARD_STOPPED); + + KBASE_TIMELINE_ATOM_READY(kctx, kbase_jd_atom_id(kctx, katom)); + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_policy_enqueue_job(js_policy, katom); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + /* A STOPPED/REMOVED job must cause a re-submit to happen, in case it + * was the last job left. Crucially, work items on work queues can run + * out of order e.g. on different CPUs, so being able to submit from + * the IRQ handler is not a good indication that we don't need to run + * jobs; the submitted job could be processed on the work-queue + * *before* the stopped job, even though it was submitted after. */ + { + int tmp; + KBASE_DEBUG_ASSERT(kbasep_js_get_atom_retry_submit_slot(&katom_retained_state, &tmp) != MALI_FALSE); + CSTD_UNUSED(tmp); + } + + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + } else { + /* Remove the job from the system for all other reasons */ + mali_bool need_to_try_schedule_context; + + kbasep_js_remove_job(kbdev, kctx, katom); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + /* jd_done_nolock() requires the jsctx_mutex lock to be dropped */ + + need_to_try_schedule_context = jd_done_nolock(katom); + + /* This ctx is already scheduled in, so return value guarenteed FALSE */ + KBASE_DEBUG_ASSERT(need_to_try_schedule_context == MALI_FALSE); + } + /* katom may have been freed now, do not use! */ + + /* + * Transaction complete + */ + mutex_unlock(&jctx->lock); + + /* Job is now no longer running, so can now safely release the context + * reference, and handle any actions that were logged against the atom's retained state */ + kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state); + + KBASE_TRACE_ADD(kbdev, JD_DONE_WORKER_END, kctx, NULL, cache_jc, 0); +} + +/** + * Work queue job cancel function + * Only called as part of 'Zapping' a context (which occurs on termination) + * Operates serially with the jd_done_worker() on the work queue. + * + * This can only be called on contexts that aren't scheduled. + * + * @note We don't need to release most of the resources that would occur on + * kbase_jd_done() or jd_done_worker(), because the atoms here must not be + * running (by virtue of only being called on contexts that aren't + * scheduled). The only resources that are an exception to this are: + * - those held by kbasep_js_job_check_ref_cores(), because these resources are + * held for non-running atoms as well as running atoms. + */ +static void jd_cancel_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); + struct kbase_jd_context *jctx; + struct kbase_context *kctx; + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool need_to_try_schedule_context; + struct kbase_device *kbdev; + + /* Soft jobs should never reach this function */ + KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); + + kctx = katom->kctx; + kbdev = kctx->kbdev; + jctx = &kctx->jctx; + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TRACE_ADD(kbdev, JD_CANCEL_WORKER, kctx, katom, katom->jc, 0); + + /* This only gets called on contexts that are scheduled out. Hence, we must + * make sure we don't de-ref the number of running jobs (there aren't + * any), nor must we try to schedule out the context (it's already + * scheduled out). + */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + + /* Release cores this job was using (this might power down unused cores) */ + kbasep_js_job_check_deref_cores(kctx->kbdev, katom); + + /* Scheduler: Remove the job from the system */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + kbasep_js_remove_cancelled_job(kbdev, kctx, katom); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + mutex_lock(&jctx->lock); + + need_to_try_schedule_context = jd_done_nolock(katom); + /* Because we're zapping, we're not adding any more jobs to this ctx, so no need to + * schedule the context. There's also no need for the jsctx_mutex to have been taken + * around this too. */ + KBASE_DEBUG_ASSERT(need_to_try_schedule_context == MALI_FALSE); + + /* katom may have been freed now, do not use! */ + mutex_unlock(&jctx->lock); +} + +/** + * @brief Complete a job that has been removed from the Hardware + * + * This must be used whenever a job has been removed from the Hardware, e.g.: + * - An IRQ indicates that the job finished (for both error and 'done' codes) + * - The job was evicted from the JS_HEAD_NEXT registers during a Soft/Hard stop. + * + * Some work is carried out immediately, and the rest is deferred onto a workqueue + * + * This can be called safely from atomic context. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock + * + */ +void kbase_jd_done(struct kbase_jd_atom *katom, int slot_nr, ktime_t *end_timestamp, + kbasep_js_atom_done_code done_code) +{ + struct kbase_context *kctx; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(katom); + kctx = katom->kctx; + KBASE_DEBUG_ASSERT(kctx); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev); + + if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT) + katom->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; + + kbase_timeline_job_slot_done(kbdev, kctx, katom, slot_nr, done_code); + + KBASE_TRACE_ADD(kbdev, JD_DONE, kctx, katom, katom->jc, 0); + + kbase_job_check_leave_disjoint(kbdev, katom); + kbasep_js_job_done_slot_irq(katom, slot_nr, end_timestamp, done_code); + + katom->slot_nr = slot_nr; + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, jd_done_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +KBASE_EXPORT_TEST_API(kbase_jd_done) + +void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + KBASE_DEBUG_ASSERT(NULL != katom); + kctx = katom->kctx; + KBASE_DEBUG_ASSERT(NULL != kctx); + + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TRACE_ADD(kbdev, JD_CANCEL, kctx, katom, katom->jc, 0); + + /* This should only be done from a context that is not scheduled */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, jd_cancel_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +struct zap_reset_data { + /* The stages are: + * 1. The timer has never been called + * 2. The zap has timed out, all slots are soft-stopped - the GPU reset will happen. + * The GPU has been reset when kbdev->reset_waitq is signalled + * + * (-1 - The timer has been cancelled) + */ + int stage; + struct kbase_device *kbdev; + struct hrtimer timer; + spinlock_t lock; /* protects updates to stage member */ +}; + +static enum hrtimer_restart zap_timeout_callback(struct hrtimer *timer) +{ + struct zap_reset_data *reset_data = container_of(timer, struct zap_reset_data, timer); + struct kbase_device *kbdev = reset_data->kbdev; + unsigned long flags; + + spin_lock_irqsave(&reset_data->lock, flags); + + if (reset_data->stage == -1) + goto out; + +#if KBASE_GPU_RESET_EN + if (kbase_prepare_to_reset_gpu(kbdev)) { + dev_err(kbdev->dev, "Issueing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", ZAP_TIMEOUT); + kbase_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + reset_data->stage = 2; + + out: + spin_unlock_irqrestore(&reset_data->lock, flags); + + return HRTIMER_NORESTART; +} + +void kbase_jd_zap_context(struct kbase_context *kctx) +{ + struct kbase_jd_atom *katom; + struct list_head *entry, *tmp; + struct kbase_device *kbdev; + struct zap_reset_data reset_data; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kctx); + + kbdev = kctx->kbdev; + + KBASE_TRACE_ADD(kbdev, JD_ZAP_CONTEXT, kctx, NULL, 0u, 0u); + kbase_job_zap_context(kctx); + + mutex_lock(&kctx->jctx.lock); + + /* + * While holding the struct kbase_jd_context lock clean up jobs which are known to kbase but are + * queued outside the job scheduler. + */ + + list_for_each_safe(entry, tmp, &kctx->waiting_soft_jobs) { + katom = list_entry(entry, struct kbase_jd_atom, dep_item[0]); + kbase_cancel_soft_job(katom); + } + + +#ifdef CONFIG_KDS + + /* For each job waiting on a kds resource, cancel the wait and force the job to + * complete early, this is done so that we don't leave jobs outstanding waiting + * on kds resources which may never be released when contexts are zapped, resulting + * in a hang. + * + * Note that we can safely iterate over the list as the struct kbase_jd_context lock is held, + * this prevents items being removed when calling job_done_nolock in kbase_cancel_kds_wait_job. + */ + + list_for_each(entry, &kctx->waiting_kds_resource) { + katom = list_entry(entry, struct kbase_jd_atom, node); + + kbase_cancel_kds_wait_job(katom); + } +#endif + + mutex_unlock(&kctx->jctx.lock); + + hrtimer_init_on_stack(&reset_data.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + reset_data.timer.function = zap_timeout_callback; + + spin_lock_init(&reset_data.lock); + + reset_data.kbdev = kbdev; + reset_data.stage = 1; + + hrtimer_start(&reset_data.timer, HR_TIMER_DELAY_MSEC(ZAP_TIMEOUT), HRTIMER_MODE_REL); + + /* Wait for all jobs to finish, and for the context to be not-scheduled + * (due to kbase_job_zap_context(), we also guarentee it's not in the JS + * policy queue either */ + wait_event(kctx->jctx.zero_jobs_wait, kctx->jctx.job_nr == 0); + wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, kctx->jctx.sched_info.ctx.is_scheduled == MALI_FALSE); + + spin_lock_irqsave(&reset_data.lock, flags); + if (reset_data.stage == 1) { + /* The timer hasn't run yet - so cancel it */ + reset_data.stage = -1; + } + spin_unlock_irqrestore(&reset_data.lock, flags); + + hrtimer_cancel(&reset_data.timer); + + if (reset_data.stage == 2) { + /* The reset has already started. + * Wait for the reset to complete + */ + wait_event(kbdev->reset_wait, atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_NOT_PENDING); + } + destroy_hrtimer_on_stack(&reset_data.timer); + + dev_dbg(kbdev->dev, "Zap: Finished Context %p", kctx); + + /* Ensure that the signallers of the waitqs have finished */ + mutex_lock(&kctx->jctx.lock); + mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); + mutex_unlock(&kctx->jctx.lock); +} + +KBASE_EXPORT_TEST_API(kbase_jd_zap_context) + +mali_error kbase_jd_init(struct kbase_context *kctx) +{ + int i; + mali_error mali_err = MALI_ERROR_NONE; +#ifdef CONFIG_KDS + int err; +#endif /* CONFIG_KDS */ + + KBASE_DEBUG_ASSERT(kctx); + + kctx->jctx.job_done_wq = alloc_workqueue("mali_jd", 0, 1); + if (NULL == kctx->jctx.job_done_wq) { + mali_err = MALI_ERROR_OUT_OF_MEMORY; + goto out1; + } + + for (i = 0; i < BASE_JD_ATOM_COUNT; i++) { + init_waitqueue_head(&kctx->jctx.atoms[i].completed); + + INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[0]); + INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[1]); + + /* Catch userspace attempting to use an atom which doesn't exist as a pre-dependency */ + kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_INVALID; + kctx->jctx.atoms[i].status = KBASE_JD_ATOM_STATE_UNUSED; + } + + mutex_init(&kctx->jctx.lock); + + init_waitqueue_head(&kctx->jctx.zero_jobs_wait); + + spin_lock_init(&kctx->jctx.tb_lock); + +#ifdef CONFIG_KDS + err = kds_callback_init(&kctx->jctx.kds_cb, 0, kds_dep_clear); + if (0 != err) { + mali_err = MALI_ERROR_FUNCTION_FAILED; + goto out2; + } +#endif /* CONFIG_KDS */ + + kctx->jctx.job_nr = 0; + + return MALI_ERROR_NONE; + +#ifdef CONFIG_KDS + out2: + destroy_workqueue(kctx->jctx.job_done_wq); +#endif /* CONFIG_KDS */ + out1: + return mali_err; +} + +KBASE_EXPORT_TEST_API(kbase_jd_init) + +void kbase_jd_exit(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx); + +#ifdef CONFIG_KDS + kds_callback_term(&kctx->jctx.kds_cb); +#endif /* CONFIG_KDS */ + /* Work queue is emptied by this */ + destroy_workqueue(kctx->jctx.job_done_wq); +} + +KBASE_EXPORT_TEST_API(kbase_jd_exit) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..bd063343fc7914290cbec6d24d7b7dfb07412e44 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c @@ -0,0 +1,192 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#include + +#ifdef CONFIG_DEBUG_FS + +/** + * @brief Show callback for the @c JD atoms debugfs file. + * + * This function is called to get the contents of the @c JD atoms debugfs file. + * This is a report of all atoms managed by kbase_jd_context::atoms . + * + * @param sfile The debugfs entry + * @param data Data associated with the entry + * + * @return 0 if successfully prints data in debugfs entry file, failure + * otherwise + */ +static int kbasep_jd_debugfs_atoms_show(struct seq_file *sfile, void *data) +{ + struct kbase_context *kctx = sfile->private; + struct kbase_jd_atom *atoms; + unsigned long irq_flags; + int i; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* Print table heading */ + seq_puts(sfile, "atom id,core reqs,status,coreref status,predeps,start time,time on gpu\n"); + + atoms = kctx->jctx.atoms; + /* General atom states */ + mutex_lock(&kctx->jctx.lock); + /* JS-related states */ + spin_lock_irqsave(&kctx->kbdev->js_data.runpool_irq.lock, irq_flags); + for (i = 0; i != BASE_JD_ATOM_COUNT; ++i) { + struct kbase_jd_atom *atom = &atoms[i]; + s64 start_timestamp = 0; + + if (atom->status == KBASE_JD_ATOM_STATE_UNUSED) + continue; + + /* start_timestamp is cleared as soon as the atom leaves UNUSED state + * and set before a job is submitted to the h/w, a non-zero value means + * it is valid */ + if (ktime_to_ns(atom->start_timestamp)) + start_timestamp = ktime_to_ns( + ktime_sub(ktime_get(), atom->start_timestamp)); + +#ifdef CONFIG_64BIT + seq_printf(sfile, + "%i,%u,%u,%u,%lu %lu,%lli,%llu\n", + i, atom->core_req, atom->status, atom->coreref_state, + atom->dep[0].atom ? atom->dep[0].atom - atoms : 0, + atom->dep[1].atom ? atom->dep[1].atom - atoms : 0, + (signed long long)start_timestamp, + (unsigned long long)(atom->time_spent_us ? + atom->time_spent_us * 1000 : start_timestamp) + ); +#else + seq_printf(sfile, + "%i,%u,%u,%u,%u %u,%lli,%llu\n", + i, atom->core_req, atom->status, atom->coreref_state, + atom->dep[0].atom ? atom->dep[0].atom - atoms : 0, + atom->dep[1].atom ? atom->dep[1].atom - atoms : 0, + (signed long long)start_timestamp, + (unsigned long long)(atom->time_spent_us ? + atom->time_spent_us * 1000 : start_timestamp) + ); +#endif + } + spin_unlock_irqrestore(&kctx->kbdev->js_data.runpool_irq.lock, irq_flags); + mutex_unlock(&kctx->jctx.lock); + + return 0; +} + + +/** + * @brief File operations related to debugfs entry for atoms + */ +static int kbasep_jd_debugfs_atoms_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_jd_debugfs_atoms_show, in->i_private); +} + +static const struct file_operations kbasep_jd_debugfs_atoms_fops = { + .open = kbasep_jd_debugfs_atoms_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + +int kbasep_jd_debugfs_init(struct kbase_device *kbdev) +{ + kbdev->jd_directory = debugfs_create_dir( + "jd", kbdev->mali_debugfs_directory); + if (IS_ERR(kbdev->jd_directory)) { + dev_err(kbdev->dev, "Couldn't create mali jd debugfs directory\n"); + goto err; + } + + return 0; + +err: + return -1; +} + + +void kbasep_jd_debugfs_term(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + if (!IS_ERR(kbdev->jd_directory)) + debugfs_remove_recursive(kbdev->jd_directory); +} + + +int kbasep_jd_debugfs_ctx_add(struct kbase_context *kctx) +{ + /* Refer below for format string, %u is 10 chars max */ + char dir_name[10 * 2 + 2]; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* Create per-context directory */ + scnprintf(dir_name, sizeof(dir_name), "%u_%u", kctx->pid, kctx->id); + kctx->jd_ctx_dir = debugfs_create_dir(dir_name, kctx->kbdev->jd_directory); + if (IS_ERR(kctx->jd_ctx_dir)) + goto err; + + /* Expose all atoms */ + if (IS_ERR(debugfs_create_file("atoms", S_IRUGO, + kctx->jd_ctx_dir, kctx, &kbasep_jd_debugfs_atoms_fops))) + goto err_jd_ctx_dir; + + return 0; + +err_jd_ctx_dir: + debugfs_remove_recursive(kctx->jd_ctx_dir); +err: + return -1; +} + + +void kbasep_jd_debugfs_ctx_remove(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + + if (!IS_ERR(kctx->jd_ctx_dir)) + debugfs_remove_recursive(kctx->jd_ctx_dir); +} + +#else /* CONFIG_DEBUG_FS */ + +/** + * @brief Stub functions for when debugfs is disabled + */ +int kbasep_jd_debugfs_init(struct kbase_device *kbdev) +{ + return 0; +} +void kbasep_jd_debugfs_term(struct kbase_device *kbdev) +{ +} +int kbasep_jd_debugfs_ctx_add(struct kbase_context *ctx) +{ + return 0; +} +void kbasep_jd_debugfs_ctx_remove(struct kbase_context *ctx) +{ +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..c045736139b64fa633b22471369b1bf53879c871 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h @@ -0,0 +1,66 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_jd_debugfs.h + * Header file for job dispatcher-related entries in debugfs + */ + +#ifndef _KBASE_JD_DEBUGFS_H +#define _KBASE_JD_DEBUGFS_H + +#include + +#include + +/** + * @brief Initialize JD debugfs entries + * + * This should be called during device probing after the main mali debugfs + * directory has been created. + * + * @param[in] kbdev Pointer to kbase_device + */ +int kbasep_jd_debugfs_init(struct kbase_device *kbdev); + +/** + * @brief Clean up all JD debugfs entries and related data + * + * This should be called during device removal before the main mali debugfs + * directory will be removed. + * + * @param[in] kbdev Pointer to kbase_device + */ +void kbasep_jd_debugfs_term(struct kbase_device *kbdev); + +/** + * @brief Add new entry to JD debugfs + * + * @param[in] kctx Pointer to kbase_context + * + * @return 0 on success, failure otherwise + */ +int kbasep_jd_debugfs_ctx_add(struct kbase_context *kctx); + +/** + * @brief Remove entry from JD debugfs + * + * param[in] kctx Pointer to kbase_context + */ +void kbasep_jd_debugfs_ctx_remove(struct kbase_context *kctx); + +#endif /*_KBASE_JD_DEBUGFS_H*/ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.c new file mode 100644 index 0000000000000000000000000000000000000000..b04f5967f7f5d688e0ab91ade43646e5bc9cc16c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.c @@ -0,0 +1,1532 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_jm.c + * Base kernel job manager APIs + */ + +#include +#include +#include +#include +#include +#include + +#include "mali_kbase_jm.h" + +#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS +u64 mali_js0_affinity_mask = 0xFFFFFFFFFFFFFFFFULL; +u64 mali_js1_affinity_mask = 0xFFFFFFFFFFFFFFFFULL; +u64 mali_js2_affinity_mask = 0xFFFFFFFFFFFFFFFFULL; +#endif + +#if KBASE_GPU_RESET_EN +static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev); +#endif /* KBASE_GPU_RESET_EN */ + +#ifdef CONFIG_GPU_TRACEPOINTS +static char *kbasep_make_job_slot_string(int js, char *js_string) +{ + sprintf(js_string, "job_slot_%i", js); + return js_string; +} +#endif + +static void kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js) +{ + struct kbase_context *kctx; + u32 cfg; + u64 jc_head = katom->jc; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(katom); + + kctx = katom->kctx; + + /* Command register must be available */ + KBASE_DEBUG_ASSERT(kbasep_jm_is_js_free(kbdev, js, kctx)); + /* Affinity is not violating */ + kbase_js_debug_log_current_affinities(kbdev); + KBASE_DEBUG_ASSERT(!kbase_js_affinity_would_violate(kbdev, js, katom->affinity)); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), jc_head & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), jc_head >> 32, kctx); + +#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS + { + u64 mask; + u32 value; + + if (0 == js) + { + mask = mali_js0_affinity_mask; + } + else if (1 == js) + { + mask = mali_js1_affinity_mask; + } + else + { + mask = mali_js2_affinity_mask; + } + + value = katom->affinity & (mask & 0xFFFFFFFF); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_LO), value, kctx); + + value = (katom->affinity >> 32) & ((mask>>32) & 0xFFFFFFFF); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_HI), value, kctx); + } +#else + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_LO), katom->affinity & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_HI), katom->affinity >> 32, kctx); +#endif + + /* start MMU, medium priority, cache clean/flush on end, clean/flush on start */ + cfg = kctx->as_nr | JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE | JS_CONFIG_START_MMU | JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE | JS_CONFIG_THREAD_PRI(8); + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { + if (!kbdev->jm_slots[js].job_chain_flag) { + cfg |= JS_CONFIG_JOB_CHAIN_FLAG; + katom->atom_flags |= KBASE_KATOM_FLAGS_JOBCHAIN; + kbdev->jm_slots[js].job_chain_flag = MALI_TRUE; + } else { + katom->atom_flags &= ~KBASE_KATOM_FLAGS_JOBCHAIN; + kbdev->jm_slots[js].job_chain_flag = MALI_FALSE; + } + } + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_CONFIG_NEXT), cfg, kctx); + + /* Write an approximate start timestamp. + * It's approximate because there might be a job in the HEAD register. In + * such cases, we'll try to make a better approximation in the IRQ handler + * (up to the KBASE_JS_IRQ_THROTTLE_TIME_US). */ + katom->start_timestamp = ktime_get(); + + /* GO ! */ + dev_dbg(kbdev->dev, "JS: Submitting atom %p from ctx %p to js[%d] with head=0x%llx, affinity=0x%llx", katom, kctx, js, jc_head, katom->affinity); + + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_SUBMIT, kctx, katom, jc_head, js, (u32) katom->affinity); + +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_START, js), kctx, kbase_jd_atom_id(kctx, katom)); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ +#ifdef CONFIG_GPU_TRACEPOINTS + if (kbasep_jm_nr_jobs_submitted(&kbdev->jm_slots[js]) == 1) + { + /* If this is the only job on the slot, trace it as starting */ + char js_string[16]; + trace_gpu_sched_switch(kbasep_make_job_slot_string(js, js_string), ktime_to_ns(katom->start_timestamp), (u32)katom->kctx->id, 0, katom->work_id); + kbdev->jm_slots[js].last_context = katom->kctx; + } +#endif + kbase_timeline_job_slot_submit(kbdev, kctx, katom, js); + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_START, katom->kctx); +} + +void kbase_job_submit_nolock(struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js) +{ + struct kbase_jm_slot *jm_slots; +#if KBASE_PM_EN + base_jd_core_req core_req; +#endif + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(katom); + + jm_slots = kbdev->jm_slots; + +#if KBASE_PM_EN + core_req = katom->core_req; + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) { + unsigned long flags; + int device_nr = (core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) ? katom->device_nr : 0; + KBASE_DEBUG_ASSERT(device_nr < 2); + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbasep_pm_record_job_status(kbdev); + kbdev->pm.metrics.active_cl_ctx[device_nr]++; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + } else { + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbasep_pm_record_job_status(kbdev); + kbdev->pm.metrics.active_gl_ctx++; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + } +#endif + + /* + * We can have: + * - one job already done (pending interrupt), + * - one running, + * - one ready to be run. + * Hence a maximum of 3 inflight jobs. We have a 4 job + * queue, which I hope will be enough... + */ + kbasep_jm_enqueue_submit_slot(&jm_slots[js], katom); + kbase_job_hw_submit(kbdev, katom, js); +} + +void kbase_job_done_slot(struct kbase_device *kbdev, int s, u32 completion_code, u64 job_tail, ktime_t *end_timestamp) +{ + struct kbase_jm_slot *slot; + struct kbase_jd_atom *katom; + mali_addr64 jc_head; + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(kbdev); + + if (completion_code != BASE_JD_EVENT_DONE && completion_code != BASE_JD_EVENT_STOPPED) + dev_err(kbdev->dev, "GPU fault 0x%02lx from job slot %d\n", (unsigned long)completion_code, s); + + /* IMPORTANT: this function must only contain work necessary to complete a + * job from a Real IRQ (and not 'fake' completion, e.g. from + * Soft-stop). For general work that must happen no matter how the job was + * removed from the hardware, place it in kbase_jd_done() */ + + slot = &kbdev->jm_slots[s]; + katom = kbasep_jm_dequeue_submit_slot(slot); + + /* If the katom completed is because it's a dummy job for HW workarounds, then take no further action */ + if (kbasep_jm_is_dummy_workaround_job(kbdev, katom)) { + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_JOB_DONE, NULL, NULL, 0, s, completion_code); + return; + } + + jc_head = katom->jc; + kctx = katom->kctx; + + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_JOB_DONE, kctx, katom, jc_head, s, completion_code); + + if (completion_code != BASE_JD_EVENT_DONE && completion_code != BASE_JD_EVENT_STOPPED) { + +#if KBASE_TRACE_DUMP_ON_JOB_SLOT_ERROR != 0 + KBASE_TRACE_DUMP(kbdev); +#endif + } + if (job_tail != 0) { + mali_bool was_updated = (job_tail != jc_head); + /* Some of the job has been executed, so we update the job chain address to where we should resume from */ + katom->jc = job_tail; + if (was_updated) + KBASE_TRACE_ADD_SLOT(kbdev, JM_UPDATE_HEAD, kctx, katom, job_tail, s); + } + + /* Only update the event code for jobs that weren't cancelled */ + if (katom->event_code != BASE_JD_EVENT_JOB_CANCELLED) + katom->event_code = (base_jd_event_code) completion_code; + + kbase_device_trace_register_access(kctx, REG_WRITE, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 1 << s); + + /* Complete the job, and start new ones + * + * Also defer remaining work onto the workqueue: + * - Re-queue Soft-stopped jobs + * - For any other jobs, queue the job back into the dependency system + * - Schedule out the parent context if necessary, and schedule a new one in. + */ +#ifdef CONFIG_GPU_TRACEPOINTS + if (kbasep_jm_nr_jobs_submitted(slot) != 0) { + struct kbase_jd_atom *katom; + char js_string[16]; + katom = kbasep_jm_peek_idx_submit_slot(slot, 0); /* The atom in the HEAD */ + trace_gpu_sched_switch(kbasep_make_job_slot_string(s, js_string), ktime_to_ns(*end_timestamp), (u32)katom->kctx->id, 0, katom->work_id); + slot->last_context = katom->kctx; + } else { + char js_string[16]; + trace_gpu_sched_switch(kbasep_make_job_slot_string(s, js_string), ktime_to_ns(ktime_get()), 0, 0, 0); + slot->last_context = 0; + } +#endif + kbase_jd_done(katom, s, end_timestamp, KBASE_JS_ATOM_DONE_START_NEW_ATOMS); +} + +/** + * Update the start_timestamp of the job currently in the HEAD, based on the + * fact that we got an IRQ for the previous set of completed jobs. + * + * The estimate also takes into account the KBASE_JS_IRQ_THROTTLE_TIME_US and + * the time the job was submitted, to work out the best estimate (which might + * still result in an over-estimate to the calculated time spent) + */ +STATIC void kbasep_job_slot_update_head_start_timestamp(struct kbase_device *kbdev, struct kbase_jm_slot *slot, ktime_t end_timestamp) +{ + KBASE_DEBUG_ASSERT(slot); + + if (kbasep_jm_nr_jobs_submitted(slot) > 0) { + struct kbase_jd_atom *katom; + ktime_t new_timestamp; + ktime_t timestamp_diff; + katom = kbasep_jm_peek_idx_submit_slot(slot, 0); /* The atom in the HEAD */ + + KBASE_DEBUG_ASSERT(katom != NULL); + + if (kbasep_jm_is_dummy_workaround_job(kbdev, katom) != MALI_FALSE) { + /* Don't access the members of HW workaround 'dummy' jobs */ + return; + } + + /* Account for any IRQ Throttle time - makes an overestimate of the time spent by the job */ + new_timestamp = ktime_sub_ns(end_timestamp, KBASE_JS_IRQ_THROTTLE_TIME_US * 1000); + timestamp_diff = ktime_sub(new_timestamp, katom->start_timestamp); + if (ktime_to_ns(timestamp_diff) >= 0) { + /* Only update the timestamp if it's a better estimate than what's currently stored. + * This is because our estimate that accounts for the throttle time may be too much + * of an overestimate */ + katom->start_timestamp = new_timestamp; + } + } +} + +void kbase_job_done(struct kbase_device *kbdev, u32 done) +{ + unsigned long flags; + int i; + u32 count = 0; + ktime_t end_timestamp = ktime_get(); + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + KBASE_TRACE_ADD(kbdev, JM_IRQ, NULL, NULL, 0, done); + + memset(&kbdev->slot_submit_count_irq[0], 0, sizeof(kbdev->slot_submit_count_irq)); + + /* write irq throttle register, this will prevent irqs from occurring until + * the given number of gpu clock cycles have passed */ + { + int irq_throttle_cycles = atomic_read(&kbdev->irq_throttle_cycles); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_THROTTLE), irq_throttle_cycles, NULL); + } + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + while (done) { + struct kbase_jm_slot *slot; + u32 failed = done >> 16; + + /* treat failed slots as finished slots */ + u32 finished = (done & 0xFFFF) | failed; + + /* Note: This is inherently unfair, as we always check + * for lower numbered interrupts before the higher + * numbered ones.*/ + i = ffs(finished) - 1; + KBASE_DEBUG_ASSERT(i >= 0); + + slot = &kbdev->jm_slots[i]; + + do { + int nr_done; + u32 active; + u32 completion_code = BASE_JD_EVENT_DONE; /* assume OK */ + u64 job_tail = 0; + + if (failed & (1u << i)) { + /* read out the job slot status code if the job slot reported failure */ + completion_code = kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_STATUS), NULL); + + switch (completion_code) { + case BASE_JD_EVENT_STOPPED: +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_SOFT_STOPPED, i), NULL, 0); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + /* Soft-stopped job - read the value of JS_TAIL so that the job chain can be resumed */ + job_tail = (u64) kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_TAIL_LO), NULL) | ((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_TAIL_HI), NULL) << 32); + break; + case BASE_JD_EVENT_NOT_STARTED: + /* PRLAM-10673 can cause a TERMINATED job to come back as NOT_STARTED, but the error interrupt helps us detect it */ + completion_code = BASE_JD_EVENT_TERMINATED; + /* fall throught */ + default: + dev_warn(kbdev->dev, "error detected from slot %d, job status 0x%08x (%s)", i, completion_code, kbase_exception_name(completion_code)); + } + } + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), done & ((1 << i) | (1 << (i + 16))), NULL); + active = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_JS_STATE), NULL); + + if (((active >> i) & 1) == 0 && (((done >> (i + 16)) & 1) == 0)) { + /* There is a potential race we must work around: + * + * 1. A job slot has a job in both current and next registers + * 2. The job in current completes successfully, the IRQ handler reads RAWSTAT + * and calls this function with the relevant bit set in "done" + * 3. The job in the next registers becomes the current job on the GPU + * 4. Sometime before the JOB_IRQ_CLEAR line above the job on the GPU _fails_ + * 5. The IRQ_CLEAR clears the done bit but not the failed bit. This atomically sets + * JOB_IRQ_JS_STATE. However since both jobs have now completed the relevant bits + * for the slot are set to 0. + * + * If we now did nothing then we'd incorrectly assume that _both_ jobs had completed + * successfully (since we haven't yet observed the fail bit being set in RAWSTAT). + * + * So at this point if there are no active jobs left we check to see if RAWSTAT has a failure + * bit set for the job slot. If it does we know that there has been a new failure that we + * didn't previously know about, so we make sure that we record this in active (but we wait + * for the next loop to deal with it). + * + * If we were handling a job failure (i.e. done has the relevant high bit set) then we know that + * the value read back from JOB_IRQ_JS_STATE is the correct number of remaining jobs because + * the failed job will have prevented any futher jobs from starting execution. + */ + u32 rawstat = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL); + + if ((rawstat >> (i + 16)) & 1) { + /* There is a failed job that we've missed - add it back to active */ + active |= (1u << i); + } + } + + dev_dbg(kbdev->dev, "Job ended with status 0x%08X\n", completion_code); + + nr_done = kbasep_jm_nr_jobs_submitted(slot); + nr_done -= (active >> i) & 1; + nr_done -= (active >> (i + 16)) & 1; + + if (nr_done <= 0) { + dev_warn(kbdev->dev, "Spurious interrupt on slot %d", i); + goto spurious; + } + + count += nr_done; + + while (nr_done) { + if (nr_done == 1) { + kbase_job_done_slot(kbdev, i, completion_code, job_tail, &end_timestamp); + } else { + /* More than one job has completed. Since this is not the last job being reported this time it + * must have passed. This is because the hardware will not allow further jobs in a job slot to + * complete until the faile job is cleared from the IRQ status. + */ + kbase_job_done_slot(kbdev, i, BASE_JD_EVENT_DONE, 0, &end_timestamp); + } + nr_done--; + } + + spurious: + done = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10883)) { + /* Workaround for missing interrupt caused by PRLAM-10883 */ + if (((active >> i) & 1) && (0 == kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_STATUS), NULL))) { + /* Force job slot to be processed again */ + done |= (1u << i); + } + } + + failed = done >> 16; + finished = (done & 0xFFFF) | failed; + } while (finished & (1 << i)); + + kbasep_job_slot_update_head_start_timestamp(kbdev, slot, end_timestamp); + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); +#if KBASE_GPU_RESET_EN + if (atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_COMMITTED) { + /* If we're trying to reset the GPU then we might be able to do it early + * (without waiting for a timeout) because some jobs have completed + */ + kbasep_try_reset_gpu_early(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + KBASE_TRACE_ADD(kbdev, JM_IRQ_END, NULL, NULL, 0, count); +} +KBASE_EXPORT_TEST_API(kbase_job_done) + +static mali_bool kbasep_soft_stop_allowed(struct kbase_device *kbdev, u16 core_reqs) +{ + mali_bool soft_stops_allowed = MALI_TRUE; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) { + if ((core_reqs & BASE_JD_REQ_T) != 0) + soft_stops_allowed = MALI_FALSE; + } + return soft_stops_allowed; +} + +static mali_bool kbasep_hard_stop_allowed(struct kbase_device *kbdev, u16 core_reqs) +{ + mali_bool hard_stops_allowed = MALI_TRUE; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8394)) { + if ((core_reqs & BASE_JD_REQ_T) != 0) + hard_stops_allowed = MALI_FALSE; + } + return hard_stops_allowed; +} + +static void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, int js, u32 action, u16 core_reqs, struct kbase_jd_atom *target_katom) +{ + struct kbase_context *kctx = target_katom->kctx; +#if KBASE_TRACE_ENABLE + u32 status_reg_before; + u64 job_in_head_before; + u32 status_reg_after; + + KBASE_DEBUG_ASSERT(!(action & (~JS_COMMAND_MASK))); + + /* Check the head pointer */ + job_in_head_before = ((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_LO), NULL)) + | (((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_HI), NULL)) << 32); + status_reg_before = kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_STATUS), NULL); +#endif + + if (action == JS_COMMAND_SOFT_STOP) { + mali_bool soft_stop_allowed = kbasep_soft_stop_allowed(kbdev, core_reqs); + if (!soft_stop_allowed) { +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kbdev->dev, "Attempt made to soft-stop a job that cannot be soft-stopped. core_reqs = 0x%X", (unsigned int)core_reqs); +#endif /* CONFIG_MALI_DEBUG */ + return; + } + + /* We are about to issue a soft stop, so mark the atom as having been soft stopped */ + target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED; + } + + if (action == JS_COMMAND_HARD_STOP) { + mali_bool hard_stop_allowed = kbasep_hard_stop_allowed(kbdev, core_reqs); + if (!hard_stop_allowed) { + /* Jobs can be hard-stopped for the following reasons: + * * CFS decides the job has been running too long (and soft-stop has not occurred). + * In this case the GPU will be reset by CFS if the job remains on the GPU. + * + * * The context is destroyed, kbase_jd_zap_context will attempt to hard-stop the job. However + * it also has a watchdog which will cause the GPU to be reset if the job remains on the GPU. + * + * * An (unhandled) MMU fault occurred. As long as BASE_HW_ISSUE_8245 is defined then + * the GPU will be reset. + * + * All three cases result in the GPU being reset if the hard-stop fails, + * so it is safe to just return and ignore the hard-stop request. + */ + dev_warn(kbdev->dev, "Attempt made to hard-stop a job that cannot be hard-stopped. core_reqs = 0x%X", (unsigned int)core_reqs); + return; + } + target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_HARD_STOPPED; + } + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316) && action == JS_COMMAND_SOFT_STOP) { + int i; + struct kbase_jm_slot *slot; + slot = &kbdev->jm_slots[js]; + + for (i = 0; i < kbasep_jm_nr_jobs_submitted(slot); i++) { + struct kbase_jd_atom *katom; + + katom = kbasep_jm_peek_idx_submit_slot(slot, i); + + KBASE_DEBUG_ASSERT(katom); + + if (kbasep_jm_is_dummy_workaround_job(kbdev, katom) != MALI_FALSE) { + /* Don't access the members of HW workaround 'dummy' jobs + * + * This assumes that such jobs can't cause HW_ISSUE_8316, and could only be blocked + * by other jobs causing HW_ISSUE_8316 (which will get poked/or eventually get killed) */ + continue; + } + + /* For HW_ISSUE_8316, only 'bad' jobs attacking the system can + * cause this issue: normally, all memory should be allocated in + * multiples of 4 pages, and growable memory should be changed size + * in multiples of 4 pages. + * + * Whilst such 'bad' jobs can be cleared by a GPU reset, the + * locking up of a uTLB entry caused by the bad job could also + * stall other ASs, meaning that other ASs' jobs don't complete in + * the 'grace' period before the reset. We don't want to lose other + * ASs' jobs when they would normally complete fine, so we must + * 'poke' the MMU regularly to help other ASs complete */ + kbase_as_poking_timer_retain_atom(kbdev, katom->kctx, katom); + } + } + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) { + if (action == JS_COMMAND_SOFT_STOP) + action = (target_katom->atom_flags & KBASE_KATOM_FLAGS_JOBCHAIN) ? + JS_COMMAND_SOFT_STOP_1 : + JS_COMMAND_SOFT_STOP_0; + else + action = (target_katom->atom_flags & KBASE_KATOM_FLAGS_JOBCHAIN) ? + JS_COMMAND_HARD_STOP_1 : + JS_COMMAND_HARD_STOP_0; + } + + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND), action, kctx); + +#if KBASE_TRACE_ENABLE + status_reg_after = kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_STATUS), NULL); + if (status_reg_after == BASE_JD_EVENT_ACTIVE) { + struct kbase_jm_slot *slot; + struct kbase_jd_atom *head; + struct kbase_context *head_kctx; + + slot = &kbdev->jm_slots[js]; + head = kbasep_jm_peek_idx_submit_slot(slot, slot->submitted_nr - 1); + head_kctx = head->kctx; + + /* We don't need to check kbasep_jm_is_dummy_workaround_job( head ) here: + * - Members are not indirected through + * - The members will all be zero anyway + */ + if (status_reg_before == BASE_JD_EVENT_ACTIVE) + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, head_kctx, head, job_in_head_before, js); + else + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, 0, js); + + switch (action) { + case JS_COMMAND_SOFT_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_SOFT_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_0, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_SOFT_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_1, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_0, head_kctx, head, head->jc, js); + break; + case JS_COMMAND_HARD_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_1, head_kctx, head, head->jc, js); + break; + default: + BUG(); + break; + } + } else { + if (status_reg_before == BASE_JD_EVENT_ACTIVE) + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, job_in_head_before, js); + else + KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, 0, js); + + switch (action) { + case JS_COMMAND_SOFT_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP, NULL, NULL, 0, js); + break; + case JS_COMMAND_SOFT_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_0, NULL, NULL, 0, js); + break; + case JS_COMMAND_SOFT_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP_1, NULL, NULL, 0, js); + break; + case JS_COMMAND_HARD_STOP: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP, NULL, NULL, 0, js); + break; + case JS_COMMAND_HARD_STOP_0: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_0, NULL, NULL, 0, js); + break; + case JS_COMMAND_HARD_STOP_1: + KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP_1, NULL, NULL, 0, js); + break; + default: + BUG(); + break; + } + } +#endif +} + +/* Helper macros used by kbasep_job_slot_soft_or_hard_stop */ +#define JM_SLOT_MAX_JOB_SUBMIT_REGS 2 +#define JM_JOB_IS_CURRENT_JOB_INDEX(n) (1 == n) /* Index of the last job to process */ +#define JM_JOB_IS_NEXT_JOB_INDEX(n) (2 == n) /* Index of the prior to last job to process */ + +/** Soft or hard-stop a slot + * + * This function safely ensures that the correct job is either hard or soft-stopped. + * It deals with evicting jobs from the next registers where appropriate. + * + * This does not attempt to stop or evict jobs that are 'dummy' jobs for HW workarounds. + * + * @param kbdev The kbase device + * @param kctx The context to soft/hard-stop job(s) from (or NULL is all jobs should be targeted) + * @param js The slot that the job(s) are on + * @param target_katom The atom that should be targeted (or NULL if all jobs from the context should be targeted) + * @param action The action to perform, either JS_COMMAND_HARD_STOP or JS_COMMAND_SOFT_STOP + */ +static void kbasep_job_slot_soft_or_hard_stop(struct kbase_device *kbdev, struct kbase_context *kctx, int js, struct kbase_jd_atom *target_katom, u32 action) +{ + struct kbase_jd_atom *katom; + u8 i; + u8 jobs_submitted; + struct kbase_jm_slot *slot; + u16 core_reqs; + struct kbasep_js_device_data *js_devdata; + mali_bool can_safely_stop = kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION); + u32 hw_action = action & JS_COMMAND_MASK; + + KBASE_DEBUG_ASSERT(hw_action == JS_COMMAND_HARD_STOP || + hw_action == JS_COMMAND_SOFT_STOP); + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + slot = &kbdev->jm_slots[js]; + KBASE_DEBUG_ASSERT(slot); + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + jobs_submitted = kbasep_jm_nr_jobs_submitted(slot); + + KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 1); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_SLOT_SOFT_OR_HARD_STOP, kctx, NULL, 0u, js, jobs_submitted); + + if (jobs_submitted > JM_SLOT_MAX_JOB_SUBMIT_REGS) + i = jobs_submitted - JM_SLOT_MAX_JOB_SUBMIT_REGS; + else + i = 0; + + /* Loop through all jobs that have been submitted to the slot and haven't completed */ + for (; i < jobs_submitted; i++) { + katom = kbasep_jm_peek_idx_submit_slot(slot, i); + + if (kctx && katom->kctx != kctx) + continue; + + if (target_katom && katom != target_katom) + continue; + + if (kbasep_jm_is_dummy_workaround_job(kbdev, katom)) + continue; + + core_reqs = katom->core_req; + + /* This will be repeated for anything removed from the next + * registers, since their normal flow was also interrupted, and + * this function might not enter disjoint state e.g. if we + * don't actually do a hard stop on the head atom + */ + kbase_job_check_enter_disjoint(kbdev, action, core_reqs, katom); + + if (JM_JOB_IS_CURRENT_JOB_INDEX(jobs_submitted - i)) { + /* The last job in the slot, check if there is a job in the next register */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), NULL) == 0) { + kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, + js, hw_action, core_reqs, katom); + } else { + /* The job is in the next registers */ + beenthere(kctx, "clearing job from next registers on slot %d", js); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_NOP, NULL); + /* Check to see if we did remove a job from the next registers */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), NULL) != 0) { + /* The job was successfully cleared from the next registers, requeue it */ + struct kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot); + KBASE_DEBUG_ASSERT(dequeued_katom == katom); + jobs_submitted--; + + /* Set the next registers to NULL */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), 0, NULL); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), 0, NULL); + + /* As the job is removed from the next registers we undo the associated + * update to the job_chain_flag for the job slot. */ + if (can_safely_stop) + slot->job_chain_flag = !slot->job_chain_flag; + + KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js); + + kbase_job_check_enter_disjoint(kbdev, action, 0u, dequeued_katom); + /* Complete the job, indicate it took no time, but don't submit any more at this point */ + kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT); + } else { + /* The job transitioned into the current registers before we managed to evict it, + * in this case we fall back to soft/hard-stopping the job */ + beenthere(kctx, "missed job in next register, soft/hard-stopping slot %d", js); + kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, + js, hw_action, core_reqs, katom); + } + } + } else if (JM_JOB_IS_NEXT_JOB_INDEX(jobs_submitted - i)) { + /* There's a job after this one, check to see if that + * job is in the next registers. If so, we need to pay + * attention to not accidently stop that one when + * issueing the command to stop the one pointed to by + * the head registers (as the one in the head may + * finish in the mean time and the one in the next + * moves to the head). Either the hardware has support + * for this using job chain disambiguation or we need + * to evict the job from the next registers first to + * ensure we can safely stop the one pointed to by the + * head registers. + */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), NULL) != 0) { + struct kbase_jd_atom *check_next_atom; + /* It is - we should remove that job and soft/hard-stop the slot */ + + /* Only proceed when the next job isn't a HW workaround 'dummy' job + * + * This can't be an ASSERT due to MMU fault code: + * - This first hard-stops the job that caused the fault + * - Under HW Issue 8245, it will then reset the GPU + * - This causes a Soft-stop to occur on all slots + * - By the time of the soft-stop, we may (depending on timing) still have: + * - The original job in HEAD, if it's not finished the hard-stop + * - The dummy workaround job in NEXT + * + * Other cases could be coded in future that cause back-to-back Soft/Hard + * stops with dummy workaround jobs in place, e.g. MMU handler code and Job + * Scheduler watchdog timer running in parallel. + * + * Note, the index i+1 is valid to peek from: i == jobs_submitted-2, therefore + * i+1 == jobs_submitted-1 */ + check_next_atom = kbasep_jm_peek_idx_submit_slot(slot, i + 1); + if (kbasep_jm_is_dummy_workaround_job(kbdev, check_next_atom) != MALI_FALSE) + continue; + + if (!can_safely_stop) { + beenthere(kctx, "clearing job from next registers on slot %d", js); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_NOP, NULL); + + /* Check to see if we did remove a job from the next registers */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), NULL) != 0) { + /* We did remove a job from the next registers, requeue it */ + struct kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot); + KBASE_DEBUG_ASSERT(dequeued_katom != NULL); + jobs_submitted--; + + /* Set the next registers to NULL */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), 0, NULL); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), 0, NULL); + + KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js); + + kbase_job_check_enter_disjoint(kbdev, action, 0u, dequeued_katom); + /* Complete the job, indicate it took no time, but don't submit any more at this point */ + kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT); + } else { + /* We missed the job, that means the job we're interested in left the hardware before + * we managed to do anything, so we can proceed to the next job */ + continue; + } + } + + /* Next is now free, so we can soft/hard-stop the slot */ + beenthere(kctx, "soft/hard-stopped slot %d (there was a job in next which was successfully cleared)\n", js); + kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, + js, hw_action, core_reqs, katom); + } + /* If there was no job in the next registers, then the job we were + * interested in has finished, so we need not take any action + */ + } + } + + KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 0); +} + +void kbase_job_kill_jobs_from_context(struct kbase_context *kctx) +{ + unsigned long flags; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + int i; + + KBASE_DEBUG_ASSERT(kctx != NULL); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + /* Cancel any remaining running jobs for this kctx */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* Invalidate all jobs in context, to prevent re-submitting */ + for (i = 0; i < BASE_JD_ATOM_COUNT; i++) + kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_CANCELLED; + + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbase_job_slot_hardstop(kctx, i, NULL); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); +} + +void kbase_job_zap_context(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + int i; + mali_bool evict_success; + + KBASE_DEBUG_ASSERT(kctx != NULL); + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + /* + * Critical assumption: No more submission is possible outside of the + * workqueue. This is because the OS *must* prevent U/K calls (IOCTLs) + * whilst the struct kbase_context is terminating. + */ + + /* First, atomically do the following: + * - mark the context as dying + * - try to evict it from the policy queue */ + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + js_kctx_info->ctx.is_dying = MALI_TRUE; + + dev_dbg(kbdev->dev, "Zap: Try Evict Ctx %p", kctx); + mutex_lock(&js_devdata->queue_mutex); + evict_success = kbasep_js_policy_try_evict_ctx(&js_devdata->policy, kctx); + mutex_unlock(&js_devdata->queue_mutex); + + /* + * At this point we know: + * - If eviction succeeded, it was in the policy queue, but now no longer is + * - We must cancel the jobs here. No Power Manager active reference to + * release. + * - This happens asynchronously - kbase_jd_zap_context() will wait for + * those jobs to be killed. + * - If eviction failed, then it wasn't in the policy queue. It is one of + * the following: + * - a. it didn't have any jobs, and so is not in the Policy Queue or the + * Run Pool (not scheduled) + * - Hence, no more work required to cancel jobs. No Power Manager active + * reference to release. + * - b. it was in the middle of a scheduling transaction (and thus must + * have at least 1 job). This can happen from a syscall or a kernel thread. + * We still hold the jsctx_mutex, and so the thread must be waiting inside + * kbasep_js_try_schedule_head_ctx(), before checking whether the runpool + * is full. That thread will continue after we drop the mutex, and will + * notice the context is dying. It will rollback the transaction, killing + * all jobs at the same time. kbase_jd_zap_context() will wait for those + * jobs to be killed. + * - Hence, no more work required to cancel jobs, or to release the Power + * Manager active reference. + * - c. it is scheduled, and may or may not be running jobs + * - We must cause it to leave the runpool by stopping it from submitting + * any more jobs. When it finally does leave, + * kbasep_js_runpool_requeue_or_kill_ctx() will kill all remaining jobs + * (because it is dying), release the Power Manager active reference, and + * will not requeue the context in the policy queue. kbase_jd_zap_context() + * will wait for those jobs to be killed. + * - Hence, work required just to make it leave the runpool. Cancelling + * jobs and releasing the Power manager active reference will be handled + * when it leaves the runpool. + */ + + if (evict_success != MALI_FALSE || js_kctx_info->ctx.is_scheduled == MALI_FALSE) { + /* The following events require us to kill off remaining jobs and + * update PM book-keeping: + * - we evicted it correctly (it must have jobs to be in the Policy Queue) + * + * These events need no action, but take this path anyway: + * - Case a: it didn't have any jobs, and was never in the Queue + * - Case b: scheduling transaction will be partially rolled-back (this + * already cancels the jobs) + */ + + KBASE_TRACE_ADD(kbdev, JM_ZAP_NON_SCHEDULED, kctx, NULL, 0u, js_kctx_info->ctx.is_scheduled); + + dev_dbg(kbdev->dev, "Zap: Ctx %p evict_success=%d, scheduled=%d", kctx, evict_success, js_kctx_info->ctx.is_scheduled); + + if (evict_success != MALI_FALSE) { + /* Only cancel jobs when we evicted from the policy queue. No Power + * Manager active reference was held. + * + * Having is_dying set ensures that this kills, and doesn't requeue */ + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_FALSE); + } + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + } else { + unsigned long flags; + mali_bool was_retained; + /* Case c: didn't evict, but it is scheduled - it's in the Run Pool */ + KBASE_TRACE_ADD(kbdev, JM_ZAP_SCHEDULED, kctx, NULL, 0u, js_kctx_info->ctx.is_scheduled); + dev_dbg(kbdev->dev, "Zap: Ctx %p is in RunPool", kctx); + + /* Disable the ctx from submitting any more jobs */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_clear_submit_allowed(js_devdata, kctx); + + /* Retain and (later) release the context whilst it is is now disallowed from submitting + * jobs - ensures that someone somewhere will be removing the context later on */ + was_retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + + /* Since it's scheduled and we have the jsctx_mutex, it must be retained successfully */ + KBASE_DEBUG_ASSERT(was_retained != MALI_FALSE); + + dev_dbg(kbdev->dev, "Zap: Ctx %p Kill Any Running jobs", kctx); + /* Cancel any remaining running jobs for this kctx - if any. Submit is disallowed + * which takes effect immediately, so no more new jobs will appear after we do this. */ + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbase_job_slot_hardstop(kctx, i, NULL); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + dev_dbg(kbdev->dev, "Zap: Ctx %p Release (may or may not schedule out immediately)", kctx); + kbasep_js_runpool_release_ctx(kbdev, kctx); + } + KBASE_TRACE_ADD(kbdev, JM_ZAP_DONE, kctx, NULL, 0u, 0u); + + /* After this, you must wait on both the kbase_jd_context::zero_jobs_wait + * and the kbasep_js_kctx_info::ctx::is_scheduled_waitq - to wait for the + * jobs to be destroyed, and the context to be de-scheduled (if it was on + * the runpool). + * + * kbase_jd_zap_context() will do this. */ +} +KBASE_EXPORT_TEST_API(kbase_job_zap_context) + +mali_error kbase_job_slot_init(struct kbase_device *kbdev) +{ + int i; + KBASE_DEBUG_ASSERT(kbdev); + + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbasep_jm_init_submit_slot(&kbdev->jm_slots[i]); + + return MALI_ERROR_NONE; +} +KBASE_EXPORT_TEST_API(kbase_job_slot_init) + +void kbase_job_slot_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbase_job_slot_term(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev); +} +KBASE_EXPORT_TEST_API(kbase_job_slot_term) + +/** + * Soft-stop the specified job slot, with extra information about the stop + * + * The job slot lock must be held when calling this function. + * The job slot must not already be in the process of being soft-stopped. + * + * Where possible any job in the next register is evicted before the soft-stop. + * + * @param kbdev The kbase device + * @param js The job slot to soft-stop + * @param target_katom The job that should be soft-stopped (or NULL for any job) + * @param sw_flags Flags to pass in about the soft-stop + */ +void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js, + struct kbase_jd_atom *target_katom, u32 sw_flags) +{ + KBASE_DEBUG_ASSERT(!(sw_flags & JS_COMMAND_MASK)); + kbasep_job_slot_soft_or_hard_stop(kbdev, NULL, js, target_katom, + JS_COMMAND_SOFT_STOP | sw_flags); +} + +/** + * Soft-stop the specified job slot + * + * The job slot lock must be held when calling this function. + * The job slot must not already be in the process of being soft-stopped. + * + * Where possible any job in the next register is evicted before the soft-stop. + * + * @param kbdev The kbase device + * @param js The job slot to soft-stop + * @param target_katom The job that should be soft-stopped (or NULL for any job) + */ +void kbase_job_slot_softstop(struct kbase_device *kbdev, int js, struct kbase_jd_atom *target_katom) +{ + kbase_job_slot_softstop_swflags(kbdev, js, target_katom, 0u); +} + +/** + * Hard-stop the specified job slot + * + * The job slot lock must be held when calling this function. + * + * @param kctx The kbase context that contains the job(s) that should + * be hard-stopped + * @param js The job slot to hard-stop + * @param target_katom The job that should be hard-stopped (or NULL for all + * jobs from the context) + */ +void kbase_job_slot_hardstop(struct kbase_context *kctx, int js, + struct kbase_jd_atom *target_katom) +{ + struct kbase_device *kbdev = kctx->kbdev; + + kbasep_job_slot_soft_or_hard_stop(kbdev, kctx, js, target_katom, + JS_COMMAND_HARD_STOP); +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_8401) || + kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_9510) || + (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_T76X_3542) && + (target_katom == NULL || target_katom->core_req & BASE_JD_REQ_FS_AFBC))) { + /* MIDBASE-2916 if a fragment job with AFBC encoding is + * hardstopped, ensure to do a soft reset also in order to + * clear the GPU status. + * Workaround for HW issue 8401 has an issue,so after + * hard-stopping just reset the GPU. This will ensure that the + * jobs leave the GPU.*/ + if (kbase_prepare_to_reset_gpu_locked(kbdev)) { + dev_err(kbdev->dev, "Issueing GPU\ + soft-reset after hard stopping due to hardware issue"); + kbase_reset_gpu_locked(kbdev); + } + } +#endif +} + +/** + * For a certain soft/hard-stop action, work out whether to enter disjoint + * state. + * + * This does not register multiple disjoint events if the atom has already + * started a disjoint period + * + * core_reqs can be supplied as 0 if the atom had not started on the hardware + * (and so a 'real' soft/hard-stop was not required, but it still interrupted + * flow, perhaps on another context) + * + * kbase_job_check_leave_disjoint() should be used to end the disjoint + * state when the soft/hard-stop action is complete + */ +void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, + u16 core_reqs, struct kbase_jd_atom *target_katom) +{ + u32 hw_action = action & JS_COMMAND_MASK; + + /* For hard-stop, don't enter if hard-stop not allowed */ + if (hw_action == JS_COMMAND_HARD_STOP && + !kbasep_hard_stop_allowed(kbdev, core_reqs)) + return; + + /* For soft-stop, don't enter if soft-stop not allowed, or isn't + * causing disjoint */ + if (hw_action == JS_COMMAND_SOFT_STOP && + !(kbasep_soft_stop_allowed(kbdev, core_reqs) && + (action & JS_COMMAND_SW_CAUSES_DISJOINT))) + return; + + /* Nothing to do if already logged disjoint state on this atom */ + if (target_katom->atom_flags & KBASE_KATOM_FLAG_IN_DISJOINT) + return; + + target_katom->atom_flags |= KBASE_KATOM_FLAG_IN_DISJOINT; + kbase_disjoint_state_up(kbdev); +} + +/** + * Work out whether to leave disjoint state when finishing an atom that was + * originated by kbase_job_check_enter_disjoint(). + */ +void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, + struct kbase_jd_atom *target_katom) +{ + if (target_katom->atom_flags & KBASE_KATOM_FLAG_IN_DISJOINT) { + target_katom->atom_flags &= ~KBASE_KATOM_FLAG_IN_DISJOINT; + kbase_disjoint_state_down(kbdev); + } +} + + +#if KBASE_GPU_RESET_EN +static void kbase_debug_dump_registers(struct kbase_device *kbdev) +{ + int i; + dev_err(kbdev->dev, "Register state:"); + dev_err(kbdev->dev, " GPU_IRQ_RAWSTAT=0x%08x GPU_STATUS=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS), NULL)); + dev_err(kbdev->dev, " JOB_IRQ_RAWSTAT=0x%08x JOB_IRQ_JS_STATE=0x%08x JOB_IRQ_THROTTLE=0x%08x", + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_JS_STATE), NULL), + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_THROTTLE), NULL)); + for (i = 0; i < 3; i++) { + dev_err(kbdev->dev, " JS%d_STATUS=0x%08x JS%d_HEAD_LO=0x%08x", + i, kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_STATUS), + NULL), + i, kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_HEAD_LO), + NULL)); + } + dev_err(kbdev->dev, " MMU_IRQ_RAWSTAT=0x%08x GPU_FAULTSTATUS=0x%08x", + kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_RAWSTAT), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS), NULL)); + dev_err(kbdev->dev, " GPU_IRQ_MASK=0x%08x JOB_IRQ_MASK=0x%08x MMU_IRQ_MASK=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL), + kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), NULL), + kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL)); + dev_err(kbdev->dev, " PWR_OVERRIDE0=0x%08x PWR_OVERRIDE1=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE0), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE1), NULL)); + dev_err(kbdev->dev, " SHADER_CONFIG=0x%08x L2_MMU_CONFIG=0x%08x", + kbase_reg_read(kbdev, GPU_CONTROL_REG(SHADER_CONFIG), NULL), + kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), NULL)); +} + +void kbasep_reset_timeout_worker(struct work_struct *data) +{ + unsigned long flags; + struct kbase_device *kbdev; + int i; + ktime_t end_timestamp = ktime_get(); + struct kbasep_js_device_data *js_devdata; + struct kbase_uk_hwcnt_setup hwcnt_setup = { {0} }; + enum kbase_instr_state bckp_state; + + KBASE_DEBUG_ASSERT(data); + + kbdev = container_of(data, struct kbase_device, reset_work); + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + KBASE_TRACE_ADD(kbdev, JM_BEGIN_RESET_WORKER, NULL, NULL, 0u, 0); + + /* Make sure the timer has completed - this cannot be done from interrupt context, + * so this cannot be done within kbasep_try_reset_gpu_early. */ + hrtimer_cancel(&kbdev->reset_timer); + + if (kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + /* This would re-activate the GPU. Since it's already idle, there's no + * need to reset it */ + atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING); + kbase_disjoint_state_down(kbdev); + wake_up(&kbdev->reset_wait); + return; + } + + mutex_lock(&kbdev->pm.lock); + /* We hold the pm lock, so there ought to be a current policy */ + KBASE_DEBUG_ASSERT(kbdev->pm.pm_current_policy); + + /* All slot have been soft-stopped and we've waited SOFT_STOP_RESET_TIMEOUT for the slots to clear, at this point + * we assume that anything that is still left on the GPU is stuck there and we'll kill it when we reset the GPU */ + + dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)", RESET_TIMEOUT); + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + + if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { /*the same interrupt handler preempted itself */ + /* GPU is being reset */ + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0); + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + } + /* Save the HW counters setup */ + if (kbdev->hwcnt.kctx != NULL) { + struct kbase_context *kctx = kbdev->hwcnt.kctx; + hwcnt_setup.dump_buffer = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), kctx) & 0xffffffff; + hwcnt_setup.dump_buffer |= (mali_addr64) kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), kctx) << 32; + hwcnt_setup.jm_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), kctx); + hwcnt_setup.shader_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), kctx); + hwcnt_setup.tiler_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), kctx); + hwcnt_setup.l3_cache_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), kctx); + hwcnt_setup.mmu_l2_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), kctx); + } + + /* Output the state of some interesting registers to help in the + * debugging of GPU resets */ + kbase_debug_dump_registers(kbdev); + + bckp_state = kbdev->hwcnt.state; + kbdev->hwcnt.state = KBASE_INSTR_STATE_RESETTING; + kbdev->hwcnt.triggered = 0; + /* Disable IRQ to avoid IRQ handlers to kick in after releaseing the spinlock; + * this also clears any outstanding interrupts */ + kbase_pm_disable_interrupts(kbdev); + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Ensure that any IRQ handlers have finished + * Must be done without any locks IRQ handlers will take */ + kbase_synchronize_irqs(kbdev); + + /* Reset the GPU */ + kbase_pm_init_hw(kbdev, MALI_TRUE); + /* IRQs were re-enabled by kbase_pm_init_hw, and GPU is still powered */ + + spin_lock_irqsave(&kbdev->hwcnt.lock, flags); + /* Restore the HW counters setup */ + if (kbdev->hwcnt.kctx != NULL) { + struct kbase_context *kctx = kbdev->hwcnt.kctx; + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_OFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), hwcnt_setup.dump_buffer & 0xFFFFFFFF, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), hwcnt_setup.dump_buffer >> 32, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), hwcnt_setup.jm_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), hwcnt_setup.shader_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), hwcnt_setup.l3_cache_bm, kctx); + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), hwcnt_setup.mmu_l2_bm, kctx); + + /* Due to PRLAM-8186 we need to disable the Tiler before we enable the HW counter dump. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), 0, kctx); + else + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), hwcnt_setup.tiler_bm, kctx); + + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_MANUAL, kctx); + + /* If HW has PRLAM-8186 we can now re-enable the tiler HW counters dump */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186)) + kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), hwcnt_setup.tiler_bm, kctx); + } + kbdev->hwcnt.state = bckp_state; + switch (kbdev->hwcnt.state) { + /* Cases for waking kbasep_cache_clean_worker worker */ + case KBASE_INSTR_STATE_CLEANED: + /* Cache-clean IRQ occurred, but we reset: + * Wakeup incase the waiter saw RESETTING */ + case KBASE_INSTR_STATE_REQUEST_CLEAN: + /* After a clean was requested, but before the regs were written: + * Wakeup incase the waiter saw RESETTING */ + wake_up(&kbdev->hwcnt.cache_clean_wait); + break; + case KBASE_INSTR_STATE_CLEANING: + /* Either: + * 1) We've not got the Cache-clean IRQ yet: it was lost, or: + * 2) We got it whilst resetting: it was voluntarily lost + * + * So, move to the next state and wakeup: */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANED; + wake_up(&kbdev->hwcnt.cache_clean_wait); + break; + + /* Cases for waking anyone else */ + case KBASE_INSTR_STATE_DUMPING: + /* If dumping, abort the dump, because we may've lost the IRQ */ + kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE; + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + break; + case KBASE_INSTR_STATE_DISABLED: + case KBASE_INSTR_STATE_IDLE: + case KBASE_INSTR_STATE_FAULT: + /* Every other reason: wakeup in that state */ + kbdev->hwcnt.triggered = 1; + wake_up(&kbdev->hwcnt.wait); + break; + + /* Unhandled cases */ + case KBASE_INSTR_STATE_RESETTING: + default: + BUG(); + break; + } + spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); + + /* Complete any jobs that were still on the GPU */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) { + int nr_done; + struct kbase_jm_slot *slot = &kbdev->jm_slots[i]; + + nr_done = kbasep_jm_nr_jobs_submitted(slot); + while (nr_done) { + dev_err(kbdev->dev, "Job stuck in slot %d on the GPU was cancelled", i); + kbase_job_done_slot(kbdev, i, BASE_JD_EVENT_JOB_CANCELLED, 0, &end_timestamp); + nr_done--; + } + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + mutex_lock(&js_devdata->runpool_mutex); + + /* Reprogram the GPU's MMU */ + for (i = 0; i < BASE_MAX_NR_AS; i++) { + if (js_devdata->runpool_irq.per_as_data[i].kctx) { + struct kbase_as *as = &kbdev->as[i]; + mutex_lock(&as->transaction_mutex); + kbase_mmu_update(js_devdata->runpool_irq.per_as_data[i].kctx); + mutex_unlock(&as->transaction_mutex); + } + } + + atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING); + + kbase_disjoint_state_down(kbdev); + wake_up(&kbdev->reset_wait); + dev_err(kbdev->dev, "Reset complete"); + + /* Find out what cores are required now */ + kbase_pm_update_cores_state(kbdev); + + /* Synchronously request and wait for those cores, because if + * instrumentation is enabled it would need them immediately. */ + kbase_pm_check_transitions_sync(kbdev); + + /* Try submitting some jobs to restart processing */ + if (js_devdata->nr_user_contexts_running > 0) { + KBASE_TRACE_ADD(kbdev, JM_SUBMIT_AFTER_RESET, NULL, NULL, 0u, 0); + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_try_run_next_job_nolock(kbdev); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + } + + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&kbdev->pm.lock); + + kbase_pm_context_idle(kbdev); + KBASE_TRACE_ADD(kbdev, JM_END_RESET_WORKER, NULL, NULL, 0u, 0); +} + +enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *timer) +{ + struct kbase_device *kbdev = container_of(timer, struct kbase_device, reset_timer); + + KBASE_DEBUG_ASSERT(kbdev); + + /* Reset still pending? */ + if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) == KBASE_RESET_GPU_COMMITTED) + queue_work(kbdev->reset_workq, &kbdev->reset_work); + + return HRTIMER_NORESTART; +} + +/* + * If all jobs are evicted from the GPU then we can reset the GPU + * immediately instead of waiting for the timeout to elapse + */ + +static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev) +{ + int i; + int pending_jobs = 0; + + KBASE_DEBUG_ASSERT(kbdev); + + /* Count the number of jobs */ + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) { + struct kbase_jm_slot *slot = &kbdev->jm_slots[i]; + pending_jobs += kbasep_jm_nr_jobs_submitted(slot); + } + + if (pending_jobs > 0) { + /* There are still jobs on the GPU - wait */ + return; + } + + /* Check that the reset has been committed to (i.e. kbase_reset_gpu has been called), and that no other + * thread beat this thread to starting the reset */ + if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) != KBASE_RESET_GPU_COMMITTED) { + /* Reset has already occurred */ + return; + } + queue_work(kbdev->reset_workq, &kbdev->reset_work); +} + +static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + + js_devdata = &kbdev->js_data; + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_try_reset_gpu_early_locked(kbdev); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); +} + +/* + * Prepare for resetting the GPU. + * This function just soft-stops all the slots to ensure that as many jobs as possible are saved. + * + * The function returns a boolean which should be interpreted as follows: + * - MALI_TRUE - Prepared for reset, kbase_reset_gpu should be called. + * - MALI_FALSE - Another thread is performing a reset, kbase_reset_gpu should not be called. + * + * @return See description + */ +mali_bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev) +{ + int i; + + KBASE_DEBUG_ASSERT(kbdev); + + if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING, KBASE_RESET_GPU_PREPARED) != KBASE_RESET_GPU_NOT_PENDING) { + /* Some other thread is already resetting the GPU */ + return MALI_FALSE; + } + + kbase_disjoint_state_up(kbdev); + + for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) + kbase_job_slot_softstop(kbdev, i, NULL); + + return MALI_TRUE; +} + +mali_bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev) +{ + unsigned long flags; + mali_bool ret; + struct kbasep_js_device_data *js_devdata; + + js_devdata = &kbdev->js_data; + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + ret = kbase_prepare_to_reset_gpu_locked(kbdev); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return ret; +} +KBASE_EXPORT_TEST_API(kbase_prepare_to_reset_gpu) + +/* + * This function should be called after kbase_prepare_to_reset_gpu iff it returns MALI_TRUE. + * It should never be called without a corresponding call to kbase_prepare_to_reset_gpu. + * + * After this function is called (or not called if kbase_prepare_to_reset_gpu returned MALI_FALSE), + * the caller should wait for kbdev->reset_waitq to be signalled to know when the reset has completed. + */ +void kbase_reset_gpu(struct kbase_device *kbdev) +{ + u32 timeout_ms; + + KBASE_DEBUG_ASSERT(kbdev); + + /* Note this is an assert/atomic_set because it is a software issue for a race to be occuring here */ + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_PREPARED); + atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED); + + timeout_ms = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS); + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", timeout_ms); + hrtimer_start(&kbdev->reset_timer, HR_TIMER_DELAY_MSEC(timeout_ms), HRTIMER_MODE_REL); + + /* Try resetting early */ + kbasep_try_reset_gpu_early(kbdev); +} +KBASE_EXPORT_TEST_API(kbase_reset_gpu) + +void kbase_reset_gpu_locked(struct kbase_device *kbdev) +{ + u32 timeout_ms; + + KBASE_DEBUG_ASSERT(kbdev); + + /* Note this is an assert/atomic_set because it is a software issue for a race to be occuring here */ + KBASE_DEBUG_ASSERT(atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_PREPARED); + atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED); + + timeout_ms = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS); + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", timeout_ms); + hrtimer_start(&kbdev->reset_timer, HR_TIMER_DELAY_MSEC(timeout_ms), HRTIMER_MODE_REL); + + /* Try resetting early */ + kbasep_try_reset_gpu_early_locked(kbdev); +} +#endif /* KBASE_GPU_RESET_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.h new file mode 100644 index 0000000000000000000000000000000000000000..d171833813113f4da7b78a8e388b98ec9f762245 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_jm.h @@ -0,0 +1,199 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_jm.h + * Job Manager Low-level APIs. + */ + +#ifndef _KBASE_JM_H_ +#define _KBASE_JM_H_ + +#include +#include +#include + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_jm Job Manager Low-level APIs + * @{ + * + */ + +static INLINE int kbasep_jm_is_js_free(struct kbase_device *kbdev, int js, struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= js && js < kbdev->gpu_props.num_job_slots); + + return !kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), kctx); +} + +/** + * This checks that: + * - there is enough space in the GPU's buffers (JS_NEXT and JS_HEAD registers) to accomodate the job. + * - there is enough space to track the job in a our Submit Slots. Note that we have to maintain space to + * requeue one job in case the next registers on the hardware need to be cleared. + */ +static INLINE mali_bool kbasep_jm_is_submit_slots_free(struct kbase_device *kbdev, int js, struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= js && js < kbdev->gpu_props.num_job_slots); + + if (atomic_read(&kbdev->reset_gpu) != KBASE_RESET_GPU_NOT_PENDING) { + /* The GPU is being reset - so prevent submission */ + return MALI_FALSE; + } + + return (mali_bool) (kbasep_jm_is_js_free(kbdev, js, kctx) + && kbdev->jm_slots[js].submitted_nr < (BASE_JM_SUBMIT_SLOTS - 2)); +} + +/** + * Initialize a submit slot + */ +static INLINE void kbasep_jm_init_submit_slot(struct kbase_jm_slot *slot) +{ + slot->submitted_nr = 0; + slot->submitted_head = 0; +} + +/** + * Find the atom at the idx'th element in the queue without removing it, starting at the head with idx==0. + */ +static INLINE struct kbase_jd_atom *kbasep_jm_peek_idx_submit_slot(struct kbase_jm_slot *slot, u8 idx) +{ + u8 pos; + struct kbase_jd_atom *katom; + + KBASE_DEBUG_ASSERT(idx < BASE_JM_SUBMIT_SLOTS); + + pos = (slot->submitted_head + idx) & BASE_JM_SUBMIT_SLOTS_MASK; + katom = slot->submitted[pos]; + + return katom; +} + +/** + * Pop front of the submitted + */ +static INLINE struct kbase_jd_atom *kbasep_jm_dequeue_submit_slot(struct kbase_jm_slot *slot) +{ + u8 pos; + struct kbase_jd_atom *katom; + + pos = slot->submitted_head & BASE_JM_SUBMIT_SLOTS_MASK; + katom = slot->submitted[pos]; + slot->submitted[pos] = NULL; /* Just to catch bugs... */ + KBASE_DEBUG_ASSERT(katom); + + /* rotate the buffers */ + slot->submitted_head = (slot->submitted_head + 1) & BASE_JM_SUBMIT_SLOTS_MASK; + slot->submitted_nr--; + + dev_dbg(katom->kctx->kbdev->dev, "katom %p new head %u", (void *)katom, (unsigned int)slot->submitted_head); + + return katom; +} + +/* Pop back of the submitted queue (unsubmit a job) + */ +static INLINE struct kbase_jd_atom *kbasep_jm_dequeue_tail_submit_slot(struct kbase_jm_slot *slot) +{ + u8 pos; + + slot->submitted_nr--; + + pos = (slot->submitted_head + slot->submitted_nr) & BASE_JM_SUBMIT_SLOTS_MASK; + + return slot->submitted[pos]; +} + +static INLINE u8 kbasep_jm_nr_jobs_submitted(struct kbase_jm_slot *slot) +{ + return slot->submitted_nr; +} + +/** + * Push back of the submitted + */ +static INLINE void kbasep_jm_enqueue_submit_slot(struct kbase_jm_slot *slot, struct kbase_jd_atom *katom) +{ + u8 nr; + u8 pos; + nr = slot->submitted_nr++; + KBASE_DEBUG_ASSERT(nr < BASE_JM_SUBMIT_SLOTS); + + pos = (slot->submitted_head + nr) & BASE_JM_SUBMIT_SLOTS_MASK; + slot->submitted[pos] = katom; +} + +/** + * @brief Query whether a job peeked/dequeued from the submit slots is a + * 'dummy' job that is used for hardware workaround purposes. + * + * Any time a job is peeked/dequeued from the submit slots, this should be + * queried on that job. + * + * If a \a atom is indicated as being a dummy job, then you must not attempt + * to use \a atom. This is because its members will not necessarily be + * initialized, and so could lead to a fault if they were used. + * + * @param[in] kbdev kbase device pointer + * @param[in] atom The atom to query + * + * @return MALI_TRUE if \a atom is for a dummy job, in which case you must not + * attempt to use it. + * @return MALI_FALSE otherwise, and \a atom is safe to use. + */ +static INLINE mali_bool kbasep_jm_is_dummy_workaround_job(struct kbase_device *kbdev, struct kbase_jd_atom *atom) +{ + /* Query the set of workaround jobs here */ + /* none exists today */ + return MALI_FALSE; +} + +/** + * @brief Submit a job to a certain job-slot + * + * The caller must check kbasep_jm_is_submit_slots_free() != MALI_FALSE before calling this. + * + * The following locking conditions are made on the caller: + * - it must hold the kbasep_js_device_data::runpoool_irq::lock + */ +void kbase_job_submit_nolock(struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js); + +/** + * @brief Complete the head job on a particular job-slot + */ +void kbase_job_done_slot(struct kbase_device *kbdev, int s, u32 completion_code, u64 job_tail, ktime_t *end_timestamp); + + /** @} *//* end group kbase_jm */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js.c new file mode 100644 index 0000000000000000000000000000000000000000..0e9071eaf4970ac9d952762fa559d975b043cc60 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js.c @@ -0,0 +1,2156 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Job Scheduler Implementation + */ +#include +#include +#include +#include +#include + +#include "mali_kbase_jm.h" +#include +#include + +/* + * Private types + */ + +/** Bitpattern indicating the result of releasing a context */ +enum { + /** The context was descheduled - caller should try scheduling in a new one + * to keep the runpool full */ + KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED = (1u << 0), +}; + +typedef u32 kbasep_js_release_result; + +/* + * Private function prototypes + */ +STATIC INLINE void kbasep_js_deref_permon_check_and_disable_cycle_counter(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +STATIC INLINE void kbasep_js_ref_permon_check_and_enable_cycle_counter(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +STATIC kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state); + +/** Helper for trace subcodes */ +#if KBASE_TRACE_ENABLE +STATIC int kbasep_js_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int as_nr; + int refcnt = 0; + + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + as_nr = kctx->as_nr; + if (as_nr != KBASEP_AS_NR_INVALID) { + struct kbasep_js_per_as_data *js_per_as_data; + + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + refcnt = js_per_as_data->as_busy_refcount; + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return refcnt; +} +#else /* KBASE_TRACE_ENABLE */ +STATIC int kbasep_js_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(kctx); + return 0; +} +#endif /* KBASE_TRACE_ENABLE */ + +/* + * Private types + */ +enum { + JS_DEVDATA_INIT_NONE = 0, + JS_DEVDATA_INIT_CONSTANTS = (1 << 0), + JS_DEVDATA_INIT_POLICY = (1 << 1), + JS_DEVDATA_INIT_ALL = ((1 << 2) - 1) +}; + +enum { + JS_KCTX_INIT_NONE = 0, + JS_KCTX_INIT_CONSTANTS = (1 << 0), + JS_KCTX_INIT_POLICY = (1 << 1), + JS_KCTX_INIT_ALL = ((1 << 2) - 1) +}; + +/* + * Private functions + */ + +/** + * Check if the job had performance monitoring enabled and decrement the count. If no jobs require + * performance monitoring, then the cycle counters will be disabled in the GPU. + * + * No locks need to be held - locking is handled further down + * + * This function does not sleep. + */ + +STATIC INLINE void kbasep_js_deref_permon_check_and_disable_cycle_counter(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + if (katom->core_req & BASE_JD_REQ_PERMON) + kbase_pm_release_gpu_cycle_counter(kbdev); +} + +/** + * Check if the job has performance monitoring enabled and keep a count of it. If at least one + * job requires performance monitoring, then the cycle counters will be enabled in the GPU. + * + * No locks need to be held - locking is handled further down + * + * The L2 Cache must be ON when this function is called + * + * This function does not sleep. + */ + +STATIC INLINE void kbasep_js_ref_permon_check_and_enable_cycle_counter(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + if (katom->core_req & BASE_JD_REQ_PERMON) + kbase_pm_request_gpu_cycle_counter_l2_is_on(kbdev); +} + +/* + * The following locking conditions are made on the caller: + * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. + * - The caller must hold the kbasep_js_device_data::runpool_mutex + */ +STATIC INLINE void runpool_inc_context_count(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex)); + + /* Track total contexts */ + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running < S8_MAX); + ++(js_devdata->nr_all_contexts_running); + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) { + /* Track contexts that can submit jobs */ + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running < S8_MAX); + ++(js_devdata->nr_user_contexts_running); + } +} + +/* + * The following locking conditions are made on the caller: + * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. + * - The caller must hold the kbasep_js_device_data::runpool_mutex + */ +STATIC INLINE void runpool_dec_context_count(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex)); + + /* Track total contexts */ + --(js_devdata->nr_all_contexts_running); + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running >= 0); + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) { + /* Track contexts that can submit jobs */ + --(js_devdata->nr_user_contexts_running); + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running >= 0); + } +} + +/** + * @brief check whether the runpool is full for a specified context + * + * If kctx == NULL, then this makes the least restrictive check on the + * runpool. A specific context that is supplied immediately after could fail + * the check, even under the same conditions. + * + * Therefore, once a context is obtained you \b must re-check it with this + * function, since the return value could change to MALI_FALSE. + * + * The following locking conditions are made on the caller: + * - In all cases, the caller must hold kbasep_js_device_data::runpool_mutex + * - When kctx != NULL the caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. + * - When kctx == NULL, then the caller need not hold any jsctx_mutex locks (but it doesn't do any harm to do so). + */ +STATIC mali_bool check_is_runpool_full(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + mali_bool is_runpool_full; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex)); + + /* Regardless of whether a context is submitting or not, can't have more than there + * are HW address spaces */ + is_runpool_full = (mali_bool) (js_devdata->nr_all_contexts_running >= kbdev->nr_hw_address_spaces); + + if (kctx != NULL && (kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) { + BUG_ON(!mutex_is_locked(&kctx->jctx.sched_info.ctx.jsctx_mutex)); + /* Contexts that submit might use less of the address spaces available, due to HW + * workarounds. In which case, the runpool is also full when the number of + * submitting contexts exceeds the number of submittable address spaces. + * + * Both checks must be made: can have nr_user_address_spaces == nr_hw_address spaces, + * and at the same time can have nr_user_contexts_running < nr_all_contexts_running. */ + is_runpool_full |= (mali_bool) (js_devdata->nr_user_contexts_running >= kbdev->nr_user_address_spaces); + } + + return is_runpool_full; +} + +STATIC base_jd_core_req core_reqs_from_jsn_features(u16 features) /* JS_FEATURE register value */ +{ + base_jd_core_req core_req = 0u; + + if ((features & JS_FEATURE_SET_VALUE_JOB) != 0) + core_req |= BASE_JD_REQ_V; + + if ((features & JS_FEATURE_CACHE_FLUSH_JOB) != 0) + core_req |= BASE_JD_REQ_CF; + + if ((features & JS_FEATURE_COMPUTE_JOB) != 0) + core_req |= BASE_JD_REQ_CS; + + if ((features & JS_FEATURE_TILER_JOB) != 0) + core_req |= BASE_JD_REQ_T; + + if ((features & JS_FEATURE_FRAGMENT_JOB) != 0) + core_req |= BASE_JD_REQ_FS; + + return core_req; +} + +/** + * Picks and reserves an address space. + * + * When this function returns, the address space returned is reserved and + * cannot be picked for another context until it is released. + * + * The caller must ensure there \b is a free address space before calling this. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + * + * @return a non-NULL pointer to a struct kbase_as that is not in use by any other context + */ +STATIC struct kbase_as *pick_free_addr_space(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + struct kbase_as *current_as; + long ffs_result; + + js_devdata = &kbdev->js_data; + + lockdep_assert_held(&js_devdata->runpool_mutex); + + /* Find the free address space */ + ffs_result = ffs(js_devdata->as_free) - 1; + + /* ASSERT that we should've found a free one */ + KBASE_DEBUG_ASSERT(0 <= ffs_result && ffs_result < kbdev->nr_hw_address_spaces); + /* Ensure no-one else picks this one */ + js_devdata->as_free &= ~((u16) (1u << ffs_result)); + + current_as = &kbdev->as[ffs_result]; + + return current_as; +} + +/** + * Release an address space, making it available for being picked again. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + */ +STATIC INLINE void release_addr_space(struct kbase_device *kbdev, int kctx_as_nr) +{ + struct kbasep_js_device_data *js_devdata; + u16 as_bit = (1u << kctx_as_nr); + + js_devdata = &kbdev->js_data; + lockdep_assert_held(&js_devdata->runpool_mutex); + + /* The address space must not already be free */ + KBASE_DEBUG_ASSERT(!(js_devdata->as_free & as_bit)); + + js_devdata->as_free |= as_bit; +} + +/** + * Assign an Address Space (AS) to a context, and add the context to the Policy. + * + * This includes: + * - setting up the global runpool_irq structure and the context on the AS + * - Activating the MMU on the AS + * - Allowing jobs to be submitted on the AS + * + * Locking conditions: + * - Caller must hold the kbasep_js_kctx_info::jsctx_mutex + * - Caller must hold the kbasep_js_device_data::runpool_mutex + * - Caller must hold AS transaction mutex + * - Caller must hold Runpool IRQ lock + */ +STATIC void assign_and_activate_kctx_addr_space(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_as *current_as) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_per_as_data *js_per_as_data; + int as_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(current_as != NULL); + + js_devdata = &kbdev->js_data; + as_nr = current_as->number; + + lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex); + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(¤t_as->transaction_mutex); + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + /* Attribute handling */ + kbasep_js_ctx_attr_runpool_retain_ctx(kbdev, kctx); + + /* Assign addr space */ + kctx->as_nr = as_nr; +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_mmu_as_in_use(kctx->as_nr); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + /* Activate this address space on the MMU */ + kbase_mmu_update(kctx); + + /* Allow it to run jobs */ + kbasep_js_set_submit_allowed(js_devdata, kctx); + + /* Book-keeping */ + js_per_as_data->kctx = kctx; + js_per_as_data->as_busy_refcount = 0; + + /* Lastly, add the context to the policy's runpool - this really allows it to run jobs */ + kbasep_js_policy_runpool_add_ctx(&js_devdata->policy, kctx); +} + +void kbasep_js_try_run_next_job_nolock(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + int js; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + /* It's cheap and simple to retest this here - otherwise we burden the + * caller with it. In some cases, we do this higher up to optimize out the + * spinlock. */ + if (js_devdata->nr_user_contexts_running == 0) + return; /* No contexts present - the GPU might be powered off, so just return */ + + for (js = 0; js < kbdev->gpu_props.num_job_slots; ++js) + kbasep_js_try_run_next_job_on_slot_nolock(kbdev, js); +} + +/** Hold the kbasep_js_device_data::runpool_irq::lock for this */ +mali_bool kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_per_as_data *js_per_as_data; + mali_bool result = MALI_FALSE; + int as_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_devdata = &kbdev->js_data; + + as_nr = kctx->as_nr; + if (as_nr != KBASEP_AS_NR_INVALID) { + int new_refcnt; + + KBASE_DEBUG_ASSERT(as_nr >= 0); + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + KBASE_DEBUG_ASSERT(js_per_as_data->kctx != NULL); + + new_refcnt = ++(js_per_as_data->as_busy_refcount); + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RETAIN_CTX_NOLOCK, kctx, NULL, 0u, new_refcnt); + result = MALI_TRUE; + } + + return result; +} + +/* + * Functions private to KBase ('Protected' functions) + */ +void kbase_js_try_run_jobs(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + mutex_lock(&js_devdata->runpool_mutex); + if (js_devdata->nr_user_contexts_running != 0) { + /* Only try running jobs when we have contexts present, otherwise the GPU might be powered off. */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + kbasep_js_try_run_next_job_nolock(kbdev); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + } + mutex_unlock(&js_devdata->runpool_mutex); +} + +void kbase_js_try_run_jobs_on_slot(struct kbase_device *kbdev, int js) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + mutex_lock(&js_devdata->runpool_mutex); + if (js_devdata->nr_user_contexts_running != 0) { + /* Only try running jobs when we have contexts present, otherwise the GPU might be powered off. */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + kbasep_js_try_run_next_job_on_slot_nolock(kbdev, js); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + } + mutex_unlock(&js_devdata->runpool_mutex); +} + +mali_error kbasep_js_devdata_init(struct kbase_device * const kbdev) +{ + struct kbasep_js_device_data *js_devdata; + mali_error err; + int i; + u16 as_present; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(js_devdata->init_status == JS_DEVDATA_INIT_NONE); + + /* These two must be recalculated if nr_hw_address_spaces changes (e.g. for HW workarounds) */ + as_present = (1U << kbdev->nr_hw_address_spaces) - 1; + kbdev->nr_user_address_spaces = kbdev->nr_hw_address_spaces; + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + mali_bool use_workaround_for_security; + + use_workaround_for_security = DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE; + if (use_workaround_for_security != MALI_FALSE) { + dev_dbg(kbdev->dev, "GPU has HW ISSUE 8987, and driver configured for security workaround: 1 address space only"); + kbdev->nr_user_address_spaces = 1; + } + } +#ifdef CONFIG_MALI_DEBUG + /* Soft-stop will be disabled on a single context by default unless softstop_always is set */ + js_devdata->softstop_always = MALI_FALSE; +#endif /* CONFIG_MALI_DEBUG */ + js_devdata->nr_all_contexts_running = 0; + js_devdata->nr_user_contexts_running = 0; + js_devdata->as_free = as_present; /* All ASs initially free */ + js_devdata->runpool_irq.submit_allowed = 0u; /* No ctx allowed to submit */ + memset(js_devdata->runpool_irq.ctx_attr_ref_count, 0, sizeof(js_devdata->runpool_irq.ctx_attr_ref_count)); + memset(js_devdata->runpool_irq.slot_affinities, 0, sizeof(js_devdata->runpool_irq.slot_affinities)); + js_devdata->runpool_irq.slots_blocked_on_affinity = 0u; + memset(js_devdata->runpool_irq.slot_affinity_refcount, 0, sizeof(js_devdata->runpool_irq.slot_affinity_refcount)); + INIT_LIST_HEAD(&js_devdata->suspended_soft_jobs_list); + + /* Config attributes */ + js_devdata->scheduling_tick_ns = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS); + js_devdata->soft_stop_ticks = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS); + js_devdata->soft_stop_ticks_cl = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL); + js_devdata->hard_stop_ticks_ss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS); + js_devdata->hard_stop_ticks_cl = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL); + js_devdata->hard_stop_ticks_nss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS); + js_devdata->gpu_reset_ticks_ss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS); + js_devdata->gpu_reset_ticks_cl = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL); + js_devdata->gpu_reset_ticks_nss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS); + js_devdata->ctx_timeslice_ns = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS); + js_devdata->cfs_ctx_runtime_init_slices = DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES; + js_devdata->cfs_ctx_runtime_min_slices = DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES; + + dev_dbg(kbdev->dev, "JS Config Attribs: "); + dev_dbg(kbdev->dev, "\tscheduling_tick_ns:%u", js_devdata->scheduling_tick_ns); + dev_dbg(kbdev->dev, "\tsoft_stop_ticks:%u", js_devdata->soft_stop_ticks); + dev_dbg(kbdev->dev, "\tsoft_stop_ticks_cl:%u", js_devdata->soft_stop_ticks_cl); + dev_dbg(kbdev->dev, "\thard_stop_ticks_ss:%u", js_devdata->hard_stop_ticks_ss); + dev_dbg(kbdev->dev, "\thard_stop_ticks_cl:%u", js_devdata->hard_stop_ticks_cl); + dev_dbg(kbdev->dev, "\thard_stop_ticks_nss:%u", js_devdata->hard_stop_ticks_nss); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_ss:%u", js_devdata->gpu_reset_ticks_ss); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_cl:%u", js_devdata->gpu_reset_ticks_cl); + dev_dbg(kbdev->dev, "\tgpu_reset_ticks_nss:%u", js_devdata->gpu_reset_ticks_nss); + dev_dbg(kbdev->dev, "\tctx_timeslice_ns:%u", js_devdata->ctx_timeslice_ns); + dev_dbg(kbdev->dev, "\tcfs_ctx_runtime_init_slices:%u", js_devdata->cfs_ctx_runtime_init_slices); + dev_dbg(kbdev->dev, "\tcfs_ctx_runtime_min_slices:%u", js_devdata->cfs_ctx_runtime_min_slices); + +#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS + dev_dbg(kbdev->dev, "Job Scheduling Policy Soft-stops disabled, ignoring value for soft_stop_ticks==%u at %uns per tick. Other soft-stops may still occur.", js_devdata->soft_stop_ticks, js_devdata->scheduling_tick_ns); +#endif +#if KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_dbg(kbdev->dev, "Job Scheduling Policy Hard-stops disabled, ignoring values for hard_stop_ticks_ss==%d and hard_stop_ticks_nss==%u at %uns per tick. Other hard-stops may still occur.", js_devdata->hard_stop_ticks_ss, js_devdata->hard_stop_ticks_nss, js_devdata->scheduling_tick_ns); +#endif +#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS && KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_dbg(kbdev->dev, "Note: The JS policy's tick timer (if coded) will still be run, but do nothing."); +#endif + + /* setup the number of irq throttle cycles base on given time */ + { + int irq_throttle_time_us = kbdev->gpu_props.irq_throttle_time_us; + int irq_throttle_cycles = kbasep_js_convert_us_to_gpu_ticks_max_freq(kbdev, irq_throttle_time_us); + + atomic_set(&kbdev->irq_throttle_cycles, irq_throttle_cycles); + } + + /* Clear the AS data, including setting NULL pointers */ + memset(&js_devdata->runpool_irq.per_as_data[0], 0, sizeof(js_devdata->runpool_irq.per_as_data)); + + for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) + js_devdata->js_reqs[i] = core_reqs_from_jsn_features(kbdev->gpu_props.props.raw_props.js_features[i]); + + js_devdata->init_status |= JS_DEVDATA_INIT_CONSTANTS; + + /* On error, we could continue on: providing none of the below resources + * rely on the ones above */ + + mutex_init(&js_devdata->runpool_mutex); + mutex_init(&js_devdata->queue_mutex); + spin_lock_init(&js_devdata->runpool_irq.lock); + + err = kbasep_js_policy_init(kbdev); + if (err == MALI_ERROR_NONE) + js_devdata->init_status |= JS_DEVDATA_INIT_POLICY; + + /* On error, do no cleanup; this will be handled by the caller(s), since + * we've designed this resource to be safe to terminate on init-fail */ + if (js_devdata->init_status != JS_DEVDATA_INIT_ALL) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +void kbasep_js_devdata_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbasep_js_devdata_term(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + if ((js_devdata->init_status & JS_DEVDATA_INIT_CONSTANTS)) { + s8 zero_ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT] = { 0, }; + /* The caller must de-register all contexts before calling this */ + KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running == 0); + KBASE_DEBUG_ASSERT(memcmp(js_devdata->runpool_irq.ctx_attr_ref_count, zero_ctx_attr_ref_count, sizeof(js_devdata->runpool_irq.ctx_attr_ref_count)) == 0); + CSTD_UNUSED(zero_ctx_attr_ref_count); + } + if ((js_devdata->init_status & JS_DEVDATA_INIT_POLICY)) + kbasep_js_policy_term(&js_devdata->policy); + + js_devdata->init_status = JS_DEVDATA_INIT_NONE; +} + +mali_error kbasep_js_kctx_init(struct kbase_context * const kctx) +{ + struct kbase_device *kbdev; + struct kbasep_js_kctx_info *js_kctx_info; + mali_error err; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_kctx_info = &kctx->jctx.sched_info; + KBASE_DEBUG_ASSERT(js_kctx_info->init_status == JS_KCTX_INIT_NONE); + + js_kctx_info->ctx.nr_jobs = 0; + js_kctx_info->ctx.is_scheduled = MALI_FALSE; + js_kctx_info->ctx.is_dying = MALI_FALSE; + memset(js_kctx_info->ctx.ctx_attr_ref_count, 0, sizeof(js_kctx_info->ctx.ctx_attr_ref_count)); + + /* Initially, the context is disabled from submission until the create flags are set */ + js_kctx_info->ctx.flags = KBASE_CTX_FLAG_SUBMIT_DISABLED; + + js_kctx_info->init_status |= JS_KCTX_INIT_CONSTANTS; + + /* On error, we could continue on: providing none of the below resources + * rely on the ones above */ + mutex_init(&js_kctx_info->ctx.jsctx_mutex); + + init_waitqueue_head(&js_kctx_info->ctx.is_scheduled_wait); + + err = kbasep_js_policy_init_ctx(kbdev, kctx); + if (err == MALI_ERROR_NONE) + js_kctx_info->init_status |= JS_KCTX_INIT_POLICY; + + /* On error, do no cleanup; this will be handled by the caller(s), since + * we've designed this resource to be safe to terminate on init-fail */ + if (js_kctx_info->init_status != JS_KCTX_INIT_ALL) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +void kbasep_js_kctx_term(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbasep_js_kctx_info *js_kctx_info; + union kbasep_js_policy *js_policy; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbdev = kctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_policy = &kbdev->js_data.policy; + js_kctx_info = &kctx->jctx.sched_info; + + if ((js_kctx_info->init_status & JS_KCTX_INIT_CONSTANTS)) { + /* The caller must de-register all jobs before calling this */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs == 0); + } + + if ((js_kctx_info->init_status & JS_KCTX_INIT_POLICY)) + kbasep_js_policy_term_ctx(js_policy, kctx); + + js_kctx_info->init_status = JS_KCTX_INIT_NONE; +} + +/* Evict jobs from the NEXT registers + * + * The caller must hold: + * - kbasep_js_kctx_info::ctx::jsctx_mutex + * - kbasep_js_device_data::runpool_mutex + */ +STATIC void kbasep_js_runpool_evict_next_jobs(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + int js; + struct kbasep_js_device_data *js_devdata; + + js_devdata = &kbdev->js_data; + + BUG_ON(!mutex_is_locked(&kctx->jctx.sched_info.ctx.jsctx_mutex)); + BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex)); + + /* Prevent contexts in the runpool from submitting jobs */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* There's no need to prevent contexts in the runpool from submitting jobs, + * because we complete this operation by the time we release the + * runpool_irq.lock */ + + /* Evict jobs from the NEXT registers */ + for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { + struct kbase_jm_slot *slot; + struct kbase_jd_atom *tail; + + if (!kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), NULL)) { + /* No job in the NEXT register */ + continue; + } + + slot = &kbdev->jm_slots[js]; + tail = kbasep_jm_peek_idx_submit_slot(slot, slot->submitted_nr - 1); + + KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 1); + /* Clearing job from next registers */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_NOP, NULL); + + /* Check to see if we did remove a job from the next registers */ + if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), NULL) != 0) { + /* The job was successfully cleared from the next registers, requeue it */ + struct kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot); + + KBASE_DEBUG_ASSERT(dequeued_katom == tail); + + /* Set the next registers to NULL */ + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO), 0, NULL); + kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI), 0, NULL); + + KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js); + + /* Complete the job, indicate that it took no time, and don't start + * new atoms */ + kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT); + } + KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 0); + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); +} + +/** + * Fast start a higher priority job + * If the runpool is full, the lower priority contexts with no running jobs + * will be evicted from the runpool + * + * If \a kctx_new is NULL, the first context with no running jobs will be evicted + * + * The following locking conditions are made on the caller: + * - The caller must \b not hold \a kctx_new's + * kbasep_js_kctx_info::ctx::jsctx_mutex, or that mutex of any ctx in the + * runpool. This is because \a kctx_new's jsctx_mutex and one of the other + * scheduled ctx's jsctx_mutex will be obtained internally. + * - it must \em not hold kbasep_js_device_data::runpool_irq::lock (as this will be + * obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used + * internally). + */ +STATIC void kbasep_js_runpool_attempt_fast_start_ctx(struct kbase_device *kbdev, struct kbase_context *kctx_new) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_new; + union kbasep_js_policy *js_policy; + struct kbasep_js_per_as_data *js_per_as_data; + int evict_as_nr; + struct kbasep_js_atom_retained_state katom_retained_state; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + + if (kctx_new != NULL) { + js_kctx_new = &kctx_new->jctx.sched_info; + mutex_lock(&js_kctx_new->ctx.jsctx_mutex); + } else { + js_kctx_new = NULL; + CSTD_UNUSED(js_kctx_new); + } + + /* Setup a dummy katom_retained_state */ + kbasep_js_atom_retained_state_init_invalid(&katom_retained_state); + + mutex_lock(&js_devdata->runpool_mutex); + + /* If the runpool is full and either there is no specified context or the specified context is not dying, then + attempt to fast start the specified context or evict the first context with no running jobs. */ + if (check_is_runpool_full(kbdev, kctx_new) && + (!js_kctx_new || (js_kctx_new && + !js_kctx_new->ctx.is_dying))) { + /* No free address spaces - attempt to evict non-running lower priority context */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + for (evict_as_nr = 0; evict_as_nr < kbdev->nr_hw_address_spaces; evict_as_nr++) { + struct kbase_context *kctx_evict; + + js_per_as_data = &js_devdata->runpool_irq.per_as_data[evict_as_nr]; + kctx_evict = js_per_as_data->kctx; + + /* Look for the AS which is not currently running */ + if (0 == js_per_as_data->as_busy_refcount && kctx_evict != NULL) { + /* Now compare the scheduled priority we are considering evicting with the new ctx priority + * and take into consideration if the scheduled priority is a realtime policy or not. + * Note that the lower the number, the higher the priority + */ + if ((kctx_new == NULL) || kbasep_js_policy_ctx_has_priority(js_policy, kctx_evict, kctx_new)) { + mali_bool retain_result; + kbasep_js_release_result release_result; + + KBASE_TRACE_ADD(kbdev, JS_FAST_START_EVICTS_CTX, kctx_evict, NULL, 0u, (uintptr_t)kctx_new); + + /* Retain the ctx to work on it - this shouldn't be able to fail */ + retain_result = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx_evict); + KBASE_DEBUG_ASSERT(retain_result != MALI_FALSE); + CSTD_UNUSED(retain_result); + + /* This will cause the context to be scheduled out on the next runpool_release_ctx(), + * and also stop its refcount increasing */ + kbasep_js_clear_submit_allowed(js_devdata, kctx_evict); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(&js_devdata->runpool_mutex); + if (kctx_new != NULL) + mutex_unlock(&js_kctx_new->ctx.jsctx_mutex); + + /* Stop working on the target context, start working on the kctx_evict context */ + + mutex_lock(&kctx_evict->jctx.sched_info.ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx_evict, &katom_retained_state); + mutex_unlock(&js_devdata->runpool_mutex); + /* Only requeue if actually descheduled, which is more robust in case + * something else retains it (e.g. two high priority contexts racing + * to evict the same lower priority context) */ + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx_evict, MALI_TRUE); + + mutex_unlock(&kctx_evict->jctx.sched_info.ctx.jsctx_mutex); + + /* release_result isn't propogated further: + * - the caller will be scheduling in a context anyway + * - which will also cause new jobs to run */ + + /* ctx fast start has taken place */ + return; + } + } + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + } + + /* ctx fast start has not taken place */ + mutex_unlock(&js_devdata->runpool_mutex); + if (kctx_new != NULL) + mutex_unlock(&js_kctx_new->ctx.jsctx_mutex); +} + +mali_bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom) +{ + unsigned long flags; + struct kbasep_js_kctx_info *js_kctx_info; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + union kbasep_js_policy *js_policy; + + mali_bool policy_queue_updated = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(atom != NULL); + lockdep_assert_held(&kctx->jctx.lock); + + kbdev = kctx->kbdev; + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TIMELINE_ATOM_READY(kctx, kbase_jd_atom_id(kctx, atom)); + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + /* Policy-specific initialization of atoms (which cannot fail). Anything that + * could've failed must've been done at kbasep_jd_policy_init_job() time. */ + kbasep_js_policy_register_job(js_policy, kctx, atom); + + /* + * Begin Runpool transaction + */ + mutex_lock(&js_devdata->runpool_mutex); + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_ADD_JOB, kctx, atom, atom->jc, kbasep_js_trace_get_refcnt(kbdev, kctx)); + + /* Refcount ctx.nr_jobs */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs < U32_MAX); + ++(js_kctx_info->ctx.nr_jobs); + + /* Setup any scheduling information */ + kbasep_js_clear_job_retry_submit(atom); + + /* Lock for state available during IRQ */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* Context Attribute Refcounting */ + kbasep_js_ctx_attr_ctx_retain_atom(kbdev, kctx, atom); + + /* Enqueue the job in the policy, causing it to be scheduled if the + * parent context gets scheduled */ + kbasep_js_policy_enqueue_job(js_policy, atom); + + if (js_kctx_info->ctx.is_scheduled != MALI_FALSE) { + /* Handle an already running context - try to run the new job, in case it + * matches requirements that aren't matched by any other job in the Run + * Pool */ + kbasep_js_try_run_next_job_nolock(kbdev); + } + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(&js_devdata->runpool_mutex); + /* End runpool transaction */ + + if (js_kctx_info->ctx.is_scheduled == MALI_FALSE) { + if (js_kctx_info->ctx.is_dying) { + /* A job got added while/after kbase_job_zap_context() was called + * on a non-scheduled context (e.g. KDS dependency resolved). Kill + * that job by killing the context. */ + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_FALSE); + } else if (js_kctx_info->ctx.nr_jobs == 1) { + /* Handle Refcount going from 0 to 1: schedule the context on the Policy Queue */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + dev_dbg(kbdev->dev, "JS: Enqueue Context %p", kctx); + + mutex_lock(&js_devdata->queue_mutex); + kbasep_js_policy_enqueue_ctx(js_policy, kctx); + mutex_unlock(&js_devdata->queue_mutex); + + /* Policy Queue was updated - caller must try to schedule the head context + * We also try to encourage a fast-start from here. */ + policy_queue_updated = MALI_TRUE; + } + } + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + /* If the runpool is full and this job has a higher priority than the + * non-running job in the runpool - evict it so this higher priority job + * starts faster. Fast-starting requires the jsctx_mutex to be dropped, + * because it works on multiple ctxs + * + * Note: If the context is being killed with kbase_job_zap_context(), then + * kctx can't disappear after the jsctx_mutex was dropped. This is because + * the caller holds kctx->jctx.lock */ + if (policy_queue_updated) + kbasep_js_runpool_attempt_fast_start_ctx(kbdev, kctx); + + return policy_queue_updated; +} + +void kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *atom) +{ + struct kbasep_js_kctx_info *js_kctx_info; + struct kbasep_js_device_data *js_devdata; + union kbasep_js_policy *js_policy; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(atom != NULL); + + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + js_kctx_info = &kctx->jctx.sched_info; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_REMOVE_JOB, kctx, atom, atom->jc, kbasep_js_trace_get_refcnt(kbdev, kctx)); + + /* De-refcount ctx.nr_jobs */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs > 0); + --(js_kctx_info->ctx.nr_jobs); + + /* De-register the job from the system */ + kbasep_js_policy_deregister_job(js_policy, kctx, atom); +} + +void kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + unsigned long flags; + struct kbasep_js_atom_retained_state katom_retained_state; + struct kbasep_js_device_data *js_devdata; + mali_bool attr_state_changed; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + js_devdata = &kbdev->js_data; + + kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); + kbasep_js_remove_job(kbdev, kctx, katom); + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* The atom has 'finished' (will not be re-run), so no need to call + * kbasep_js_has_atom_finished(). + * + * This is because it returns MALI_FALSE for soft-stopped atoms, but we + * want to override that, because we're cancelling an atom regardless of + * whether it was soft-stopped or not */ + attr_state_changed = kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, &katom_retained_state); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + if (attr_state_changed != MALI_FALSE) { + /* A change in runpool ctx attributes might mean we can run more jobs + * than before. */ + kbase_js_try_run_jobs(kbdev); + } +} + +mali_bool kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + mali_bool result; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + /* KBASE_TRACE_ADD_REFCOUNT( kbdev, JS_RETAIN_CTX, kctx, NULL, 0, + kbasep_js_trace_get_refcnt(kbdev, kctx)); */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + result = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return result; +} + +struct kbase_context *kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev, int as_nr) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbase_context *found_kctx = NULL; + struct kbasep_js_per_as_data *js_per_as_data; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS); + js_devdata = &kbdev->js_data; + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + found_kctx = js_per_as_data->kctx; + + if (found_kctx != NULL) + ++(js_per_as_data->as_busy_refcount); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return found_kctx; +} + +/** + * @brief Try running more jobs after releasing a context and/or atom + * + * This collates a set of actions that must happen whilst + * kbasep_js_device_data::runpool_irq::lock is held. + * + * This includes running more jobs when: + * - The previously released kctx caused a ctx attribute change + * - The released atom caused a ctx attribute change + * - Slots were previously blocked due to affinity restrictions + * - Submission during IRQ handling failed + */ +STATIC void kbasep_js_run_jobs_after_ctx_and_atom_release(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state, mali_bool runpool_ctx_attr_change) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(katom_retained_state != NULL); + js_devdata = &kbdev->js_data; + + lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex); + lockdep_assert_held(&js_devdata->runpool_mutex); + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + if (js_devdata->nr_user_contexts_running != 0) { + mali_bool retry_submit; + int retry_jobslot; + + retry_submit = kbasep_js_get_atom_retry_submit_slot(katom_retained_state, &retry_jobslot); + + if (runpool_ctx_attr_change != MALI_FALSE) { + /* A change in runpool ctx attributes might mean we can run more jobs + * than before */ + kbasep_js_try_run_next_job_nolock(kbdev); + + /* A retry submit on all slots has now happened, so don't need to do it again */ + retry_submit = MALI_FALSE; + } + + /* Submit on any slots that might've had atoms blocked by the affinity of + * a completed atom. + * + * If no atom has recently completed, then this is harmelss */ + kbase_js_affinity_submit_to_blocked_slots(kbdev); + + /* If the IRQ handler failed to get a job from the policy, try again from + * outside the IRQ handler + * NOTE: We may've already cleared retry_submit from submitting above */ + if (retry_submit != MALI_FALSE) { + KBASE_TRACE_ADD_SLOT(kbdev, JD_DONE_TRY_RUN_NEXT_JOB, kctx, NULL, 0u, retry_jobslot); + kbasep_js_try_run_next_job_on_slot_nolock(kbdev, retry_jobslot); + } + } +} + +/** + * Internal function to release the reference on a ctx and an atom's "retained + * state", only taking the runpool and as transaction mutexes + * + * This also starts more jobs running in the case of an ctx-attribute state change + * + * This does none of the followup actions for scheduling: + * - It does not schedule in a new context + * - It does not requeue or handle dying contexts + * + * For those tasks, just call kbasep_js_runpool_release_ctx() instead + * + * Requires: + * - Context is scheduled in, and kctx->as_nr matches kctx_as_nr + * - Context has a non-zero refcount + * - Caller holds js_kctx_info->ctx.jsctx_mutex + * - Caller holds js_devdata->runpool_mutex + */ +STATIC kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + union kbasep_js_policy *js_policy; + struct kbasep_js_per_as_data *js_per_as_data; + + kbasep_js_release_result release_result = 0u; + mali_bool runpool_ctx_attr_change = MALI_FALSE; + int kctx_as_nr; + struct kbase_as *current_as; + int new_ref_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE); + + /* kctx->as_nr and js_per_as_data are only read from here. The caller's + * js_ctx_mutex provides a barrier that ensures they are up-to-date. + * + * They will not change whilst we're reading them, because the refcount + * is non-zero (and we ASSERT on that last fact). + */ + kctx_as_nr = kctx->as_nr; + KBASE_DEBUG_ASSERT(kctx_as_nr != KBASEP_AS_NR_INVALID); + js_per_as_data = &js_devdata->runpool_irq.per_as_data[kctx_as_nr]; + KBASE_DEBUG_ASSERT(js_per_as_data->as_busy_refcount > 0); + + /* + * Transaction begins on AS and runpool_irq + * + * Assert about out calling contract + */ + current_as = &kbdev->as[kctx_as_nr]; + mutex_lock(¤t_as->transaction_mutex); + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + KBASE_DEBUG_ASSERT(kctx_as_nr == kctx->as_nr); + KBASE_DEBUG_ASSERT(js_per_as_data->as_busy_refcount > 0); + + /* Update refcount */ + new_ref_count = --(js_per_as_data->as_busy_refcount); + + /* Release the atom if it finished (i.e. wasn't soft-stopped) */ + if (kbasep_js_has_atom_finished(katom_retained_state) != MALI_FALSE) + runpool_ctx_attr_change |= kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, katom_retained_state); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RELEASE_CTX, kctx, NULL, 0u, new_ref_count); + + if (new_ref_count == 1 && kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED && + !kbase_pm_is_suspending(kbdev)) { + /* Context is kept scheduled into an address space even when there are no jobs, in this case we have + * to handle the situation where all jobs have been evicted from the GPU and submission is disabled. + * + * At this point we re-enable submission to allow further jobs to be executed + */ + kbasep_js_set_submit_allowed(js_devdata, kctx); + } + + /* Make a set of checks to see if the context should be scheduled out */ + if (new_ref_count == 0 && (kctx->jctx.sched_info.ctx.nr_jobs == 0 || kbasep_js_is_submit_allowed(js_devdata, kctx) == MALI_FALSE)) { + /* Last reference, and we've been told to remove this context from the Run Pool */ + dev_dbg(kbdev->dev, "JS: RunPool Remove Context %p because as_busy_refcount=%d, jobs=%d, allowed=%d", kctx, new_ref_count, js_kctx_info->ctx.nr_jobs, kbasep_js_is_submit_allowed(js_devdata, kctx)); + + kbasep_js_policy_runpool_remove_ctx(js_policy, kctx); + + /* Stop any more refcounts occuring on the context */ + js_per_as_data->kctx = NULL; + + /* Ensure we prevent the context from submitting any new jobs + * e.g. from kbasep_js_try_run_next_job_on_slot_irq_nolock() */ + kbasep_js_clear_submit_allowed(js_devdata, kctx); + + /* Disable the MMU on the affected address space, and indicate it's invalid */ + kbase_mmu_disable(kctx); + +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_mmu_as_released(kctx->as_nr); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + + kctx->as_nr = KBASEP_AS_NR_INVALID; + + /* Ctx Attribute handling + * + * Releasing atoms attributes must either happen before this, or after + * 'is_scheduled' is changed, otherwise we double-decount the attributes*/ + runpool_ctx_attr_change |= kbasep_js_ctx_attr_runpool_release_ctx(kbdev, kctx); + + /* Early update of context count, to optimize the + * kbasep_js_run_jobs_after_ctx_and_atom_release() call */ + runpool_dec_context_count(kbdev, kctx); + + /* Releasing the context and katom retained state can allow more jobs to run */ + kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx, katom_retained_state, runpool_ctx_attr_change); + + /* + * Transaction ends on AS and runpool_irq: + * + * By this point, the AS-related data is now clear and ready for re-use. + * + * Since releases only occur once for each previous successful retain, and no more + * retains are allowed on this context, no other thread will be operating in this + * code whilst we are + */ + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(¤t_as->transaction_mutex); + + /* Free up the address space */ + release_addr_space(kbdev, kctx_as_nr); + /* Note: Don't reuse kctx_as_nr now */ + + /* Synchronize with any policy timers */ + kbasep_js_policy_runpool_timers_sync(js_policy); + + /* update book-keeping info */ + js_kctx_info->ctx.is_scheduled = MALI_FALSE; + /* Signal any waiter that the context is not scheduled, so is safe for + * termination - once the jsctx_mutex is also dropped, and jobs have + * finished. */ + wake_up(&js_kctx_info->ctx.is_scheduled_wait); + + /* Queue an action to occur after we've dropped the lock */ + release_result |= KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED; + + } else { + kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx, katom_retained_state, runpool_ctx_attr_change); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(¤t_as->transaction_mutex); + } + + return release_result; +} + +void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, mali_bool has_pm_ref) +{ + struct kbasep_js_device_data *js_devdata; + union kbasep_js_policy *js_policy; + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_policy = &kbdev->js_data.policy; + js_devdata = &kbdev->js_data; + + /* This is called if and only if you've you've detached the context from + * the Runpool or the Policy Queue, and not added it back to the Runpool */ + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE); + + if (js_kctx_info->ctx.is_dying != MALI_FALSE) { + /* Dying: don't requeue, but kill all jobs on the context. This happens + * asynchronously */ + dev_dbg(kbdev->dev, "JS: ** Killing Context %p on RunPool Remove **", kctx); + kbasep_js_policy_foreach_ctx_job(js_policy, kctx, &kbase_jd_cancel, MALI_TRUE); + } else if (js_kctx_info->ctx.nr_jobs > 0) { + /* Not dying, has jobs: de-ref core counts from each job before addding + * back to the queue */ + kbasep_js_policy_foreach_ctx_job(js_policy, kctx, &kbasep_js_job_check_deref_cores, MALI_FALSE); + + dev_dbg(kbdev->dev, "JS: Requeue Context %p", kctx); + mutex_lock(&js_devdata->queue_mutex); + kbasep_js_policy_enqueue_ctx(js_policy, kctx); + mutex_unlock(&js_devdata->queue_mutex); + } else { + /* Not dying, no jobs: don't add back to the queue */ + dev_dbg(kbdev->dev, "JS: Idling Context %p (not requeued)", kctx); + } + + if (has_pm_ref) { + /* In all cases where we had a pm active refcount, release it */ + kbase_pm_context_idle(kbdev); + } +} + +void kbasep_js_runpool_release_ctx_and_katom_retained_state(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + kbasep_js_release_result release_result; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, katom_retained_state); + + /* Drop the runpool mutex to allow requeing kctx */ + mutex_unlock(&js_devdata->runpool_mutex); + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_TRUE); + + /* Drop the jsctx_mutex to allow scheduling in a new context */ + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) { + /* We've freed up an address space, so let's try to schedule in another + * context + * + * Note: if there's a context to schedule in, then it also tries to run + * another job, in case the new context has jobs satisfying requirements + * that no other context/job in the runpool does */ + kbasep_js_try_schedule_head_ctx(kbdev); + } +} + +void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_atom_retained_state katom_retained_state; + + kbasep_js_atom_retained_state_init_invalid(&katom_retained_state); + + kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state); +} + +/** Variant of kbasep_js_runpool_release_ctx() that doesn't call into + * kbasep_js_try_schedule_head_ctx() */ +STATIC void kbasep_js_runpool_release_ctx_no_schedule(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + kbasep_js_release_result release_result; + struct kbasep_js_atom_retained_state katom_retained_state_struct; + struct kbasep_js_atom_retained_state *katom_retained_state = &katom_retained_state_struct; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + js_devdata = &kbdev->js_data; + kbasep_js_atom_retained_state_init_invalid(katom_retained_state); + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, katom_retained_state); + + /* Drop the runpool mutex to allow requeing kctx */ + mutex_unlock(&js_devdata->runpool_mutex); + if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_TRUE); + + /* Drop the jsctx_mutex to allow scheduling in a new context */ + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + /* NOTE: could return release_result if the caller would like to know + * whether it should schedule a new context, but currently no callers do */ +} + + +/** + * @brief Handle retaining cores for power management and affinity management, + * ensuring that cores are powered up and won't violate affinity restrictions. + * + * This function enters at the following @ref enum kbase_atom_coreref_state states: + * + * - NO_CORES_REQUESTED, + * - WAITING_FOR_REQUESTED_CORES, + * - RECHECK_AFFINITY, + * + * The transitions are as folows: + * - NO_CORES_REQUESTED -> WAITING_FOR_REQUESTED_CORES + * - WAITING_FOR_REQUESTED_CORES -> ( WAITING_FOR_REQUESTED_CORES or RECHECK_AFFINITY ) + * - RECHECK_AFFINITY -> ( WAITING_FOR_REQUESTED_CORES or CHECK_AFFINITY_VIOLATIONS ) + * - CHECK_AFFINITY_VIOLATIONS -> ( RECHECK_AFFINITY or READY ) + * + * The caller must hold: + * - kbasep_js_device_data::runpool_irq::lock + * + * @return MALI_FALSE when the function makes a transition to the same or lower state, indicating + * that the cores are not ready. + * @return MALI_TRUE once READY state is reached, indicating that the cores are 'ready' and won't + * violate affinity restrictions. + * + */ +STATIC mali_bool kbasep_js_job_check_ref_cores(struct kbase_device *kbdev, int js, struct kbase_jd_atom *katom) +{ + /* The most recently checked affinity. Having this at this scope allows us + * to guarantee that we've checked the affinity in this function call. */ + u64 recently_chosen_affinity = 0; + mali_bool chosen_affinity = MALI_FALSE; + mali_bool retry; + + do { + retry = MALI_FALSE; + + /* NOTE: The following uses a number of FALLTHROUGHs to optimize the + * calls to this function. Ending of the function is indicated by BREAK OUT */ + switch (katom->coreref_state) { + /* State when job is first attempted to be run */ + case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED: + KBASE_DEBUG_ASSERT(katom->affinity == 0); + + /* Compute affinity */ + if (MALI_FALSE == kbase_js_choose_affinity(&recently_chosen_affinity, kbdev, katom, js)) { + /* No cores are currently available */ + /* *** BREAK OUT: No state transition *** */ + break; + } + + chosen_affinity = MALI_TRUE; + + /* Request the cores */ + kbase_pm_request_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity); + + katom->affinity = recently_chosen_affinity; + + /* Proceed to next state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES: + { + enum kbase_pm_cores_ready cores_ready; + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + + cores_ready = kbase_pm_register_inuse_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity); + if (cores_ready == KBASE_NEW_AFFINITY) { + /* Affinity no longer valid - return to previous state */ + kbasep_js_job_check_deref_cores(kbdev, katom); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + /* *** BREAK OUT: Return to previous state, retry *** */ + retry = MALI_TRUE; + break; + } + if (cores_ready == KBASE_CORES_NOT_READY) { + /* Stay in this state and return, to retry at this state later */ + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + /* *** BREAK OUT: No state transition *** */ + break; + } + /* Proceed to next state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + } + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + + case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY: + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + + /* Optimize out choosing the affinity twice in the same function call */ + if (chosen_affinity == MALI_FALSE) { + /* See if the affinity changed since a previous call. */ + if (MALI_FALSE == kbase_js_choose_affinity(&recently_chosen_affinity, kbdev, katom, js)) { + /* No cores are currently available */ + kbasep_js_job_check_deref_cores(kbdev, katom); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REQUEST_ON_RECHECK_FAILED, katom->kctx, katom, katom->jc, js, (u32) recently_chosen_affinity); + /* *** BREAK OUT: Transition to lower state *** */ + break; + } + chosen_affinity = MALI_TRUE; + } + + /* Now see if this requires a different set of cores */ + if (recently_chosen_affinity != katom->affinity) { + enum kbase_pm_cores_ready cores_ready; + + kbase_pm_request_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity); + + /* Register new cores whilst we still hold the old ones, to minimize power transitions */ + cores_ready = kbase_pm_register_inuse_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity); + kbasep_js_job_check_deref_cores(kbdev, katom); + + /* Fixup the state that was reduced by deref_cores: */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + katom->affinity = recently_chosen_affinity; + if (cores_ready == KBASE_NEW_AFFINITY) { + /* Affinity no longer valid - return to previous state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + kbasep_js_job_check_deref_cores(kbdev, katom); + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + /* *** BREAK OUT: Return to previous state, retry *** */ + retry = MALI_TRUE; + break; + } + /* Now might be waiting for powerup again, with a new affinity */ + if (cores_ready == KBASE_CORES_NOT_READY) { + /* Return to previous state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES; + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_ON_RECHECK_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + /* *** BREAK OUT: Transition to lower state *** */ + break; + } + } + /* Proceed to next state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS; + + /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */ + case KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS: + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + KBASE_DEBUG_ASSERT(katom->affinity == recently_chosen_affinity); + + /* Note: this is where the caller must've taken the runpool_irq.lock */ + + /* Check for affinity violations - if there are any, then we just ask + * the caller to requeue and try again later */ + if (kbase_js_affinity_would_violate(kbdev, js, katom->affinity) != MALI_FALSE) { + /* Cause a re-attempt to submit from this slot on the next job complete */ + kbase_js_affinity_slot_blocked_an_atom(kbdev, js); + /* Return to previous state */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY; + /* *** BREAK OUT: Transition to lower state *** */ + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_AFFINITY_WOULD_VIOLATE, katom->kctx, katom, katom->jc, js, (u32) katom->affinity); + break; + } + + /* No affinity violations would result, so the cores are ready */ + katom->coreref_state = KBASE_ATOM_COREREF_STATE_READY; + /* *** BREAK OUT: Cores Ready *** */ + break; + + default: + KBASE_DEBUG_ASSERT_MSG(MALI_FALSE, "Unhandled kbase_atom_coreref_state %d", katom->coreref_state); + break; + } + } while (retry != MALI_FALSE); + + return (katom->coreref_state == KBASE_ATOM_COREREF_STATE_READY); +} + +void kbasep_js_job_check_deref_cores(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + + switch (katom->coreref_state) { + case KBASE_ATOM_COREREF_STATE_READY: + /* State where atom was submitted to the HW - just proceed to power-down */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + + /* *** FALLTHROUGH *** */ + + case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY: + /* State where cores were registered */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + kbase_pm_release_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity); + + /* Note: We do not clear the state for kbase_js_affinity_slot_blocked_an_atom(). + * That is handled after finishing the job. This might be slightly + * suboptimal for some corner cases, but is otherwise not a problem + * (and resolves itself after the next job completes). */ + + break; + + case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES: + /* State where cores were requested, but not registered */ + KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T)); + kbase_pm_unrequest_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity); + break; + + case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED: + /* Initial state - nothing required */ + KBASE_DEBUG_ASSERT(katom->affinity == 0); + break; + + default: + KBASE_DEBUG_ASSERT_MSG(MALI_FALSE, "Unhandled coreref_state: %d", katom->coreref_state); + break; + } + + katom->affinity = 0; + katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED; +} + +/* + * Note: this function is quite similar to kbasep_js_try_run_next_job_on_slot() + */ +mali_bool kbasep_js_try_run_next_job_on_slot_irq_nolock(struct kbase_device *kbdev, int js, s8 *submit_count) +{ + struct kbasep_js_device_data *js_devdata; + mali_bool cores_ready; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + /* The caller of this function may not be aware of Ctx Attribute state changes so we + * must recheck if the given slot is still valid. Otherwise do not try to run. + */ + if (kbase_js_can_run_job_on_slot_no_lock(kbdev, js)) { + /* Keep submitting while there's space to run a job on this job-slot, + * and there are jobs to get that match its requirements (see 'break' + * statement below) */ + while (*submit_count < KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ && kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE) { + struct kbase_jd_atom *dequeued_atom; + mali_bool has_job = MALI_FALSE; + + /* Dequeue a job that matches the requirements */ + has_job = kbasep_js_policy_dequeue_job(kbdev, js, &dequeued_atom); + + if (has_job != MALI_FALSE) { + /* NOTE: since the runpool_irq lock is currently held and acts across + * all address spaces, any context whose busy refcount has reached + * zero won't yet be scheduled out whilst we're trying to run jobs + * from it */ + struct kbase_context *parent_ctx = dequeued_atom->kctx; + mali_bool retain_success; + + /* Retain/power up the cores it needs, check if cores are ready */ + cores_ready = kbasep_js_job_check_ref_cores(kbdev, js, dequeued_atom); + + if (dequeued_atom->event_code == BASE_JD_EVENT_PM_EVENT || cores_ready != MALI_TRUE) { + /* The job either can't be submitted until the cores are ready, or + * the job will fail due to the specified core group being unavailable. + * To avoid recursion this will be handled outside of IRQ content by + * kbasep_js_try_run_next_job_on_slot_nolock */ + kbasep_js_policy_enqueue_job(&kbdev->js_data.policy, dequeued_atom); + return MALI_TRUE; + } + + /* ASSERT that the Policy picked a job from an allowed context */ + KBASE_DEBUG_ASSERT(kbasep_js_is_submit_allowed(js_devdata, parent_ctx)); + + /* Retain the context to stop it from being scheduled out + * This is released when the job finishes */ + retain_success = kbasep_js_runpool_retain_ctx_nolock(kbdev, parent_ctx); + KBASE_DEBUG_ASSERT(retain_success != MALI_FALSE); + CSTD_UNUSED(retain_success); + + /* Retain the affinity on the slot */ + kbase_js_affinity_retain_slot_cores(kbdev, js, dequeued_atom->affinity); + + /* Check if this job needs the cycle counter enabled before submission */ + kbasep_js_ref_permon_check_and_enable_cycle_counter(kbdev, dequeued_atom); + + /* Submit the job */ + kbase_job_submit_nolock(kbdev, dequeued_atom, js); + + ++(*submit_count); + } else { + /* No more jobs - stop submitting for this slot */ + break; + } + } + } + + /* Indicate whether a retry in submission should be tried on a different + * dequeue function. These are the reasons why it *must* happen: + * - the KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ threshold was reached + * and new scheduling must be performed outside of IRQ mode. + * + * Failure to indicate this correctly could stop further jobs being processed. + * + * However, we do not _need_ to indicate a retry for the following: + * - kbasep_js_policy_dequeue_job() couldn't get a job. In which case, + * there's no point re-trying outside of IRQ, because the result will be + * the same until job dependencies are resolved, or user-space provides + * more jobs. In both those cases, we try to run jobs anyway, so + * processing does not stop. + * - kbasep_jm_is_submit_slots_free() was MALI_FALSE, indicating jobs were + * already running. When those jobs complete, that will still cause events + * that cause us to resume job submission. + * - kbase_js_can_run_job_on_slot_no_lock() was MALI_FALSE - this is for + * Ctx Attribute handling. That _can_ change outside of IRQ context, but + * is handled explicitly by kbasep_js_runpool_release_ctx_and_katom_retained_state(). + */ + return (mali_bool) (*submit_count >= KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ); +} + +void kbasep_js_try_run_next_job_on_slot_nolock(struct kbase_device *kbdev, int js) +{ + struct kbasep_js_device_data *js_devdata; + mali_bool has_job; + mali_bool cores_ready; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running > 0); + + /* Keep submitting while there's space to run a job on this job-slot, + * and there are jobs to get that match its requirements (see 'break' + * statement below) */ + if (kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE) { + /* The caller of this function may not be aware of Ctx Attribute state changes so we + * must recheck if the given slot is still valid. Otherwise do not try to run. + */ + if (kbase_js_can_run_job_on_slot_no_lock(kbdev, js)) { + do { + struct kbase_jd_atom *dequeued_atom; + + /* Dequeue a job that matches the requirements */ + has_job = kbasep_js_policy_dequeue_job(kbdev, js, &dequeued_atom); + + if (has_job != MALI_FALSE) { + /* NOTE: since the runpool_irq lock is currently held and acts across + * all address spaces, any context whose busy refcount has reached + * zero won't yet be scheduled out whilst we're trying to run jobs + * from it */ + struct kbase_context *parent_ctx = dequeued_atom->kctx; + mali_bool retain_success; + + /* Retain/power up the cores it needs, check if cores are ready */ + cores_ready = kbasep_js_job_check_ref_cores(kbdev, js, dequeued_atom); + + if (cores_ready != MALI_TRUE && dequeued_atom->event_code != BASE_JD_EVENT_PM_EVENT) { + /* The job can't be submitted until the cores are ready, requeue the job */ + kbasep_js_policy_enqueue_job(&kbdev->js_data.policy, dequeued_atom); + break; + } + /* ASSERT that the Policy picked a job from an allowed context */ + KBASE_DEBUG_ASSERT(kbasep_js_is_submit_allowed(js_devdata, parent_ctx)); + + /* Retain the context to stop it from being scheduled out + * This is released when the job finishes */ + retain_success = kbasep_js_runpool_retain_ctx_nolock(kbdev, parent_ctx); + KBASE_DEBUG_ASSERT(retain_success != MALI_FALSE); + CSTD_UNUSED(retain_success); + + /* Retain the affinity on the slot */ + kbase_js_affinity_retain_slot_cores(kbdev, js, dequeued_atom->affinity); + + /* Check if this job needs the cycle counter enabled before submission */ + kbasep_js_ref_permon_check_and_enable_cycle_counter(kbdev, dequeued_atom); + + if (dequeued_atom->event_code == BASE_JD_EVENT_PM_EVENT) { + dev_warn(kbdev->dev, "Rejecting atom due to BASE_JD_EVENT_PM_EVENT\n"); + /* The job has failed due to the specified core group being unavailable */ + kbase_jd_done(dequeued_atom, js, NULL, 0); + } else { + /* Submit the job */ + kbase_job_submit_nolock(kbdev, dequeued_atom, js); + } + } + + } while (kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE && has_job != MALI_FALSE); + } + } +} + +void kbasep_js_try_schedule_head_ctx(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + mali_bool has_kctx; + struct kbase_context *head_kctx; + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool is_runpool_full; + struct kbase_as *new_address_space; + unsigned long flags; + mali_bool head_kctx_suspended = MALI_FALSE; + int pm_active_err; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + js_devdata = &kbdev->js_data; + + /* We *don't* make a speculative check on whether we can fit a context in the + * runpool, because most of our use-cases assume 2 or fewer contexts, and + * so we will usually have enough address spaces free. + * + * In any case, the check will be done later on once we have a context */ + + /* Grab the context off head of queue - if there is one */ + mutex_lock(&js_devdata->queue_mutex); + has_kctx = kbasep_js_policy_dequeue_head_ctx(&js_devdata->policy, &head_kctx); + mutex_unlock(&js_devdata->queue_mutex); + + if (has_kctx == MALI_FALSE) { + /* No ctxs to run - nothing to do */ + return; + } + js_kctx_info = &head_kctx->jctx.sched_info; + + dev_dbg(kbdev->dev, "JS: Dequeue Context %p", head_kctx); + + pm_active_err = kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE); + + /* + * Atomic transaction on the Context and Run Pool begins + */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + mutex_lock(&js_devdata->runpool_mutex); + + /* Check to see if we shouldn't add the context to run Run Pool: + * - it can't take the specified context, and so is 'full'. This may be + * 'full' even when there are addres spaces available, since some contexts + * are allowed in whereas others may not due to HW workarounds + * - A suspend is taking place + * - The context is dying due to kbase_job_zap_context() */ + is_runpool_full = check_is_runpool_full(kbdev, head_kctx); + if (is_runpool_full || pm_active_err || js_kctx_info->ctx.is_dying) { + /* Roll back the transaction so far and return */ + mutex_unlock(&js_devdata->runpool_mutex); + + /* Note: If a Power Management active reference was taken, it's released by + * this: */ + kbasep_js_runpool_requeue_or_kill_ctx(kbdev, head_kctx, !pm_active_err); + + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + return; + } + + /* From the point on, the Power Management active reference is released + * only if kbasep_js_runpool_release_ctx() causes the context to be removed + * from the runpool */ + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_TRY_SCHEDULE_HEAD_CTX, head_kctx, NULL, 0u, kbasep_js_trace_get_refcnt(kbdev, head_kctx)); + +#if !MALI_CUSTOMER_RELEASE + if (js_devdata->nr_user_contexts_running == 0) { + /* Only when there are no other contexts submitting jobs: + * Latch in run-time job scheduler timeouts that were set through js_timeouts sysfs file */ + if (kbdev->js_soft_stop_ticks != 0) + js_devdata->soft_stop_ticks = kbdev->js_soft_stop_ticks; + + if (kbdev->js_soft_stop_ticks_cl != 0) + js_devdata->soft_stop_ticks_cl = kbdev->js_soft_stop_ticks_cl; + + if (kbdev->js_hard_stop_ticks_ss != 0) + js_devdata->hard_stop_ticks_ss = kbdev->js_hard_stop_ticks_ss; + + if (kbdev->js_hard_stop_ticks_cl != 0) + js_devdata->hard_stop_ticks_cl = kbdev->js_hard_stop_ticks_cl; + + if (kbdev->js_hard_stop_ticks_nss != 0) + js_devdata->hard_stop_ticks_nss = kbdev->js_hard_stop_ticks_nss; + + if (kbdev->js_reset_ticks_ss != 0) + js_devdata->gpu_reset_ticks_ss = kbdev->js_reset_ticks_ss; + + if (kbdev->js_reset_ticks_cl != 0) + js_devdata->gpu_reset_ticks_cl = kbdev->js_reset_ticks_cl; + + if (kbdev->js_reset_ticks_nss != 0) + js_devdata->gpu_reset_ticks_nss = kbdev->js_reset_ticks_nss; + } +#endif + + runpool_inc_context_count(kbdev, head_kctx); + /* Cause any future waiter-on-termination to wait until the context is + * descheduled */ + js_kctx_info->ctx.is_scheduled = MALI_TRUE; + wake_up(&js_kctx_info->ctx.is_scheduled_wait); + + /* Pick the free address space (guaranteed free by check_is_runpool_full() ) */ + new_address_space = pick_free_addr_space(kbdev); + + /* Lock the address space whilst working on it */ + mutex_lock(&new_address_space->transaction_mutex); + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* Do all the necessaries to assign the address space (inc. update book-keeping info) + * Add the context to the Run Pool, and allow it to run jobs */ + assign_and_activate_kctx_addr_space(kbdev, head_kctx, new_address_space); + + /* NOTE: If Linux allows, then we can drop the new_address_space->transaction mutex here */ + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) != 0) { + /* We need to retain it to keep the corresponding address space */ + kbasep_js_runpool_retain_ctx_nolock(kbdev, head_kctx); + } + + /* Re-check for suspending: a suspend could've occurred after we + * pm_context_active'd, and all the contexts could've been removed from the + * runpool before we took this lock. In this case, we don't want to allow + * this context to run jobs, we just want it out immediately. + * + * The DMB required to read the suspend flag was issued recently as part of + * the runpool_irq locking. If a suspend occurs *after* that lock was taken + * (i.e. this condition doesn't execute), then the kbasep_js_suspend() code + * will cleanup this context instead (by virtue of it being called strictly + * after the suspend flag is set, and will wait for this lock to drop) */ + if (kbase_pm_is_suspending(kbdev)) { + /* Cause it to leave at some later point */ + mali_bool retained; + + retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, head_kctx); + KBASE_DEBUG_ASSERT(retained); + kbasep_js_clear_submit_allowed(js_devdata, head_kctx); + head_kctx_suspended = MALI_TRUE; + } + + /* Try to run the next job, in case this context has jobs that match the + * job slot requirements, but none of the other currently running contexts + * do */ + kbasep_js_try_run_next_job_nolock(kbdev); + + /* Transaction complete */ + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + mutex_unlock(&new_address_space->transaction_mutex); + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + /* Note: after this point, the context could potentially get scheduled out immediately */ + + if (head_kctx_suspended) { + /* Finishing forcing out the context due to a suspend. Use a variant of + * kbasep_js_runpool_release_ctx() that doesn't schedule a new context, + * to prevent a risk of recursion back into this function */ + kbasep_js_runpool_release_ctx_no_schedule(kbdev, head_kctx); + } +} + +void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_kctx_info *js_kctx_info; + struct kbasep_js_device_data *js_devdata; + mali_bool is_scheduled; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + /* This must never be attempted whilst suspending - i.e. it should only + * happen in response to a syscall from a user-space thread */ + BUG_ON(kbase_pm_is_suspending(kbdev)); + + kbase_pm_request_l2_caches(kbdev); + + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + /* Mark the context as privileged */ + js_kctx_info->ctx.flags |= KBASE_CTX_FLAG_PRIVILEGED; + + is_scheduled = js_kctx_info->ctx.is_scheduled; + if (is_scheduled == MALI_FALSE) { + mali_bool is_runpool_full; + + /* Add the context to the runpool */ + mutex_lock(&js_devdata->queue_mutex); + kbasep_js_policy_enqueue_ctx(&js_devdata->policy, kctx); + mutex_unlock(&js_devdata->queue_mutex); + + mutex_lock(&js_devdata->runpool_mutex); + { + is_runpool_full = check_is_runpool_full(kbdev, kctx); + if (is_runpool_full != MALI_FALSE) { + /* Evict jobs from the NEXT registers to free an AS asap */ + kbasep_js_runpool_evict_next_jobs(kbdev, kctx); + } + } + mutex_unlock(&js_devdata->runpool_mutex); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + /* Fast-starting requires the jsctx_mutex to be dropped, because it works on multiple ctxs */ + + if (is_runpool_full != MALI_FALSE) { + /* Evict non-running contexts from the runpool */ + kbasep_js_runpool_attempt_fast_start_ctx(kbdev, NULL); + } + /* Try to schedule the context in */ + kbasep_js_try_schedule_head_ctx(kbdev); + + /* Wait for the context to be scheduled in */ + wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, kctx->jctx.sched_info.ctx.is_scheduled == MALI_TRUE); + } else { + /* Already scheduled in - We need to retain it to keep the corresponding address space */ + kbasep_js_runpool_retain_ctx(kbdev, kctx); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + } +} + +void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + + /* We don't need to use the address space anymore */ + mutex_lock(&js_kctx_info->ctx.jsctx_mutex); + js_kctx_info->ctx.flags &= (~KBASE_CTX_FLAG_PRIVILEGED); + mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); + + kbase_pm_release_l2_caches(kbdev); + + /* Release the context - it will be scheduled out if there is no pending job */ + kbasep_js_runpool_release_ctx(kbdev, kctx); +} + +void kbasep_js_job_done_slot_irq(struct kbase_jd_atom *katom, int slot_nr, + ktime_t *end_timestamp, kbasep_js_atom_done_code done_code) +{ + struct kbase_device *kbdev; + union kbasep_js_policy *js_policy; + struct kbasep_js_device_data *js_devdata; + mali_bool submit_retry_needed = MALI_TRUE; /* If we don't start jobs here, start them from the workqueue */ + ktime_t tick_diff; + u64 microseconds_spent = 0u; + struct kbase_context *parent_ctx; + + KBASE_DEBUG_ASSERT(katom); + parent_ctx = katom->kctx; + KBASE_DEBUG_ASSERT(parent_ctx); + kbdev = parent_ctx->kbdev; + KBASE_DEBUG_ASSERT(kbdev); + + js_devdata = &kbdev->js_data; + js_policy = &kbdev->js_data.policy; + + lockdep_assert_held(&js_devdata->runpool_irq.lock); + + /* + * Release resources before submitting new jobs (bounds the refcount of + * the resource to BASE_JM_SUBMIT_SLOTS) + */ +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_STOP, slot_nr), NULL, 0); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + + /* Check if submitted jobs no longer require the cycle counter to be enabled */ + kbasep_js_deref_permon_check_and_disable_cycle_counter(kbdev, katom); + + /* Release the affinity from the slot - must happen before next submission to this slot */ + kbase_js_affinity_release_slot_cores(kbdev, slot_nr, katom->affinity); + kbase_js_debug_log_current_affinities(kbdev); + /* Calculate the job's time used */ + if (end_timestamp != NULL) { + /* Only calculating it for jobs that really run on the HW (e.g. removed + * from next jobs never actually ran, so really did take zero time) */ + tick_diff = ktime_sub(*end_timestamp, katom->start_timestamp); + + microseconds_spent = ktime_to_ns(tick_diff); + do_div(microseconds_spent, 1000); + + /* Round up time spent to the minimum timer resolution */ + if (microseconds_spent < KBASEP_JS_TICK_RESOLUTION_US) + microseconds_spent = KBASEP_JS_TICK_RESOLUTION_US; + } + + /* Log the result of the job (completion status, and time spent). */ + kbasep_js_policy_log_job_result(js_policy, katom, microseconds_spent); + /* Determine whether the parent context's timeslice is up */ + if (kbasep_js_policy_should_remove_ctx(js_policy, parent_ctx) != MALI_FALSE) + kbasep_js_clear_submit_allowed(js_devdata, parent_ctx); + + if (done_code & KBASE_JS_ATOM_DONE_START_NEW_ATOMS) { + /* Submit a new job (if there is one) to help keep the GPU's HEAD and NEXT registers full */ + KBASE_TRACE_ADD_SLOT(kbdev, JS_JOB_DONE_TRY_RUN_NEXT_JOB, parent_ctx, katom, katom->jc, slot_nr); + + submit_retry_needed = kbasep_js_try_run_next_job_on_slot_irq_nolock(kbdev, slot_nr, &kbdev->slot_submit_count_irq[slot_nr]); + } + + if (submit_retry_needed != MALI_FALSE || katom->event_code == BASE_JD_EVENT_STOPPED) { + /* The extra condition on STOPPED jobs is needed because they may be + * the only job present, but they won't get re-run until the JD work + * queue activates. Crucially, work queues can run items out of order + * e.g. on different CPUs, so being able to submit from the IRQ handler + * is not a good indication that we don't need to run jobs; the + * submitted job could be processed on the work-queue *before* the + * stopped job, even though it was submitted after. + * + * Therefore, we must try to run it, otherwise it might not get run at + * all after this. */ + + KBASE_TRACE_ADD_SLOT(kbdev, JS_JOB_DONE_RETRY_NEEDED, parent_ctx, katom, katom->jc, slot_nr); + kbasep_js_set_job_retry_submit_slot(katom, slot_nr); + } +} + +void kbasep_js_suspend(struct kbase_device *kbdev) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int i; + u16 retained = 0u; + int nr_privileged_ctx = 0; + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kbase_pm_is_suspending(kbdev)); + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + /* Prevent all contexts from submitting */ + js_devdata->runpool_irq.submit_allowed = 0; + + /* Retain each of the contexts, so we can cause it to leave even if it had + * no refcount to begin with */ + for (i = BASE_MAX_NR_AS - 1; i >= 0; --i) { + struct kbasep_js_per_as_data *js_per_as_data = &js_devdata->runpool_irq.per_as_data[i]; + struct kbase_context *kctx = js_per_as_data->kctx; + + retained = retained << 1; + + if (kctx) { + ++(js_per_as_data->as_busy_refcount); + retained |= 1u; + /* We can only cope with up to 1 privileged context - the + * instrumented context. It'll be suspended by disabling + * instrumentation */ + if (kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) + KBASE_DEBUG_ASSERT(++nr_privileged_ctx == 1); + } + } + CSTD_UNUSED(nr_privileged_ctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + /* De-ref the previous retain to ensure each context gets pulled out + * sometime later. */ + for (i = 0; + i < BASE_MAX_NR_AS; + ++i, retained = retained >> 1) { + struct kbasep_js_per_as_data *js_per_as_data = &js_devdata->runpool_irq.per_as_data[i]; + struct kbase_context *kctx = js_per_as_data->kctx; + + if (retained & 1u) + kbasep_js_runpool_release_ctx(kbdev, kctx); + } + + /* Caller must wait for all Power Manager active references to be dropped */ +} + +void kbasep_js_resume(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + int i; + + KBASE_DEBUG_ASSERT(kbdev); + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + + /* Schedule in as many contexts as address spaces. This also starts atoms. */ + for (i = 0 ; i < kbdev->nr_hw_address_spaces; ++i) + kbasep_js_try_schedule_head_ctx(kbdev); + + /* JS Resume complete */ +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js.h new file mode 100644 index 0000000000000000000000000000000000000000..3eb01c38e0572e2e217b63f4b6d8ee9aace8f905 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js.h @@ -0,0 +1,931 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js.h + * Job Scheduler APIs. + */ + +#ifndef _KBASE_JS_H_ +#define _KBASE_JS_H_ + +#include + +#include "mali_kbase_js_defs.h" +#include "mali_kbase_js_policy.h" +#include "mali_kbase_defs.h" +#include "mali_kbase_debug.h" + +#include "mali_kbase_js_ctx_attr.h" + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js Job Scheduler Internal APIs + * @{ + * + * These APIs are Internal to KBase and are available for use by the + * @ref kbase_js_policy "Job Scheduler Policy APIs" + */ + +/** + * @brief Initialize the Job Scheduler + * + * The struct kbasep_js_device_data sub-structure of \a kbdev must be zero + * initialized before passing to the kbasep_js_devdata_init() function. This is + * to give efficient error path code. + */ +mali_error kbasep_js_devdata_init(struct kbase_device * const kbdev); + +/** + * @brief Halt the Job Scheduler. + * + * It is safe to call this on \a kbdev even if it the kbasep_js_device_data + * sub-structure was never initialized/failed initialization, to give efficient + * error-path code. + * + * For this to work, the struct kbasep_js_device_data sub-structure of \a kbdev must + * be zero initialized before passing to the kbasep_js_devdata_init() + * function. This is to give efficient error path code. + * + * It is a Programming Error to call this whilst there are still kbase_context + * structures registered with this scheduler. + * + */ +void kbasep_js_devdata_halt(struct kbase_device *kbdev); + +/** + * @brief Terminate the Job Scheduler + * + * It is safe to call this on \a kbdev even if it the kbasep_js_device_data + * sub-structure was never initialized/failed initialization, to give efficient + * error-path code. + * + * For this to work, the struct kbasep_js_device_data sub-structure of \a kbdev must + * be zero initialized before passing to the kbasep_js_devdata_init() + * function. This is to give efficient error path code. + * + * It is a Programming Error to call this whilst there are still kbase_context + * structures registered with this scheduler. + */ +void kbasep_js_devdata_term(struct kbase_device *kbdev); + +/** + * @brief Initialize the Scheduling Component of a struct kbase_context on the Job Scheduler. + * + * This effectively registers a struct kbase_context with a Job Scheduler. + * + * It does not register any jobs owned by the struct kbase_context with the scheduler. + * Those must be separately registered by kbasep_js_add_job(). + * + * The struct kbase_context must be zero intitialized before passing to the + * kbase_js_init() function. This is to give efficient error path code. + */ +mali_error kbasep_js_kctx_init(struct kbase_context * const kctx); + +/** + * @brief Terminate the Scheduling Component of a struct kbase_context on the Job Scheduler + * + * This effectively de-registers a struct kbase_context from its Job Scheduler + * + * It is safe to call this on a struct kbase_context that has never had or failed + * initialization of its jctx.sched_info member, to give efficient error-path + * code. + * + * For this to work, the struct kbase_context must be zero intitialized before passing + * to the kbase_js_init() function. + * + * It is a Programming Error to call this whilst there are still jobs + * registered with this context. + */ +void kbasep_js_kctx_term(struct kbase_context *kctx); + +/** + * @brief Add a job chain to the Job Scheduler, and take necessary actions to + * schedule the context/run the job. + * + * This atomically does the following: + * - Update the numbers of jobs information + * - Add the job to the run pool if necessary (part of init_job) + * + * Once this is done, then an appropriate action is taken: + * - If the ctx is scheduled, it attempts to start the next job (which might be + * this added job) + * - Otherwise, and if this is the first job on the context, it enqueues it on + * the Policy Queue + * + * The Policy's Queue can be updated by this in the following ways: + * - In the above case that this is the first job on the context + * - If the job is high priority and the context is not scheduled, then it + * could cause the Policy to schedule out a low-priority context, allowing + * this context to be scheduled in. + * + * If the context is already scheduled on the RunPool, then adding a job to it + * is guarenteed not to update the Policy Queue. And so, the caller is + * guarenteed to not need to try scheduling a context from the Run Pool - it + * can safely assert that the result is MALI_FALSE. + * + * It is a programming error to have more than U32_MAX jobs in flight at a time. + * + * The following locking conditions are made on the caller: + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_js_device_data::runpool_irq::lock (as this will be + * obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). + * + * @return MALI_TRUE indicates that the Policy Queue was updated, and so the + * caller will need to try scheduling a context onto the Run Pool. + * @return MALI_FALSE indicates that no updates were made to the Policy Queue, + * so no further action is required from the caller. This is \b always returned + * when the context is currently scheduled. + */ +mali_bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom); + +/** + * @brief Remove a job chain from the Job Scheduler, except for its 'retained state'. + * + * Completely removing a job requires several calls: + * - kbasep_js_copy_atom_retained_state(), to capture the 'retained state' of + * the atom + * - kbasep_js_remove_job(), to partially remove the atom from the Job Scheduler + * - kbasep_js_runpool_release_ctx_and_katom_retained_state(), to release the + * remaining state held as part of the job having been run. + * + * In the common case of atoms completing normally, this set of actions is more optimal for spinlock purposes than having kbasep_js_remove_job() handle all of the actions. + * + * In the case of cancelling atoms, it is easier to call kbasep_js_remove_cancelled_job(), which handles all the necessary actions. + * + * It is a programming error to call this when: + * - \a atom is not a job belonging to kctx. + * - \a atom has already been removed from the Job Scheduler. + * - \a atom is still in the runpool: + * - it has not been removed with kbasep_js_policy_dequeue_job() + * - or, it has not been removed with kbasep_js_policy_dequeue_job_irq() + * + * Do not use this for removing jobs being killed by kbase_jd_cancel() - use + * kbasep_js_remove_cancelled_job() instead. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * + */ +void kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *atom); + +/** + * @brief Completely remove a job chain from the Job Scheduler, in the case + * where the job chain was cancelled. + * + * This is a variant of kbasep_js_remove_job() that takes care of removing all + * of the retained state too. This is generally useful for cancelled atoms, + * which need not be handled in an optimal way. + * + * It is a programming error to call this when: + * - \a atom is not a job belonging to kctx. + * - \a atom has already been removed from the Job Scheduler. + * - \a atom is still in the runpool: + * - it is not being killed with kbasep_jd_cancel() + * - or, it has not been removed with kbasep_js_policy_dequeue_job() + * - or, it has not been removed with kbasep_js_policy_dequeue_job_irq() + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, (as this will be + * obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this could be + * obtained internally) + */ +void kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief Refcount a context as being busy, preventing it from being scheduled + * out. + * + * @note This function can safely be called from IRQ context. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * + * @return value != MALI_FALSE if the retain succeeded, and the context will not be scheduled out. + * @return MALI_FALSE if the retain failed (because the context is being/has been scheduled out). + */ +mali_bool kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Refcount a context as being busy, preventing it from being scheduled + * out. + * + * @note This function can safely be called from IRQ context. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + * + * @return value != MALI_FALSE if the retain succeeded, and the context will not be scheduled out. + * @return MALI_FALSE if the retain failed (because the context is being/has been scheduled out). + */ +mali_bool kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Lookup a context in the Run Pool based upon its current address space + * and ensure that is stays scheduled in. + * + * The context is refcounted as being busy to prevent it from scheduling + * out. It must be released with kbasep_js_runpool_release_ctx() when it is no + * longer required to stay scheduled in. + * + * @note This function can safely be called from IRQ context. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpoool_irq::lock, because + * it will be used internally. + * + * @return a valid struct kbase_context on success, which has been refcounted as being busy. + * @return NULL on failure, indicating that no context was found in \a as_nr + */ +struct kbase_context *kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev, int as_nr); + +/** + * @brief Handling the requeuing/killing of a context that was evicted from the + * policy queue or runpool. + * + * This should be used whenever handing off a context that has been evicted + * from the policy queue or the runpool: + * - If the context is not dying and has jobs, it gets re-added to the policy + * queue + * - Otherwise, it is not added + * + * In addition, if the context is dying the jobs are killed asynchronously. + * + * In all cases, the Power Manager active reference is released + * (kbase_pm_context_idle()) whenever the has_pm_ref parameter is true. \a + * has_pm_ref must be set to false whenever the context was not previously in + * the runpool and does not hold a Power Manager active refcount. Note that + * contexts in a rollback of kbasep_js_try_schedule_head_ctx() might have an + * active refcount even though they weren't in the runpool. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_jd_device_data::queue_mutex (as this will be + * obtained internally) + */ +void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, mali_bool has_pm_ref); + +/** + * @brief Release a refcount of a context being busy, allowing it to be + * scheduled out. + * + * When the refcount reaches zero and the context \em might be scheduled out + * (depending on whether the Scheudling Policy has deemed it so, or if it has run + * out of jobs). + * + * If the context does get scheduled out, then The following actions will be + * taken as part of deschduling a context: + * - For the context being descheduled: + * - If the context is in the processing of dying (all the jobs are being + * removed from it), then descheduling also kills off any jobs remaining in the + * context. + * - If the context is not dying, and any jobs remain after descheduling the + * context then it is re-enqueued to the Policy's Queue. + * - Otherwise, the context is still known to the scheduler, but remains absent + * from the Policy Queue until a job is next added to it. + * - In all descheduling cases, the Power Manager active reference (obtained + * during kbasep_js_try_schedule_head_ctx()) is released (kbase_pm_context_idle()). + * + * Whilst the context is being descheduled, this also handles actions that + * cause more atoms to be run: + * - Attempt submitting atoms when the Context Attributes on the Runpool have + * changed. This is because the context being scheduled out could mean that + * there are more opportunities to run atoms. + * - Attempt submitting to a slot that was previously blocked due to affinity + * restrictions. This is usually only necessary when releasing a context + * happens as part of completing a previous job, but is harmless nonetheless. + * - Attempt scheduling in a new context (if one is available), and if necessary, + * running a job from that new context. + * + * Unlike retaining a context in the runpool, this function \b cannot be called + * from IRQ context. + * + * It is a programming error to call this on a \a kctx that is not currently + * scheduled, or that already has a zero refcount. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::as[n].transaction_mutex (as this will be obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (as this will be + * obtained internally) + * + */ +void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Variant of kbasep_js_runpool_release_ctx() that handles additional + * actions from completing an atom. + * + * This is usually called as part of completing an atom and releasing the + * refcount on the context held by the atom. + * + * Therefore, the extra actions carried out are part of handling actions queued + * on a completed atom, namely: + * - Releasing the atom's context attributes + * - Retrying the submission on a particular slot, because we couldn't submit + * on that slot from an IRQ handler. + * + * The locking conditions of this function are the same as those for + * kbasep_js_runpool_release_ctx() + */ +void kbasep_js_runpool_release_ctx_and_katom_retained_state(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state); + +/** + * @brief Try to submit the next job on a \b particular slot whilst in IRQ + * context, and whilst the caller already holds the runpool IRQ spinlock. + * + * \a *submit_count will be checked against + * KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ to see whether too many jobs have + * been submitted. This is to prevent the IRQ handler looping over lots of GPU + * NULL jobs, which may complete whilst the IRQ handler is still processing. \a + * submit_count itself should point to kbase_device::slot_submit_count_irq[ \a js ], + * which is initialized to zero on entry to the IRQ handler. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + * + * @return truthful (i.e. != MALI_FALSE) if too many jobs were submitted from + * IRQ. Therefore, this indicates that submission should be retried from a + * work-queue, by using + * kbasep_js_try_run_next_job_on_slot_nolock()/kbase_js_try_run_jobs_on_slot(). + * @return MALI_FALSE if submission had no problems: the GPU is either already + * full of jobs in the HEAD and NEXT registers, or we were able to get enough + * jobs from the Run Pool to fill the GPU's HEAD and NEXT registers. + */ +mali_bool kbasep_js_try_run_next_job_on_slot_irq_nolock(struct kbase_device *kbdev, int js, s8 *submit_count); + +/** + * @brief Try to submit the next job on a particular slot, outside of IRQ context + * + * This obtains the Job Slot lock for the duration of the call only. + * + * Unlike kbasep_js_try_run_next_job_on_slot_irq_nolock(), there is no limit on + * submission, because eventually IRQ_THROTTLE will kick in to prevent us + * getting stuck in a loop of submitting GPU NULL jobs. This is because the IRQ + * handler will be delayed, and so this function will eventually fill up the + * space in our software 'submitted' slot (kbase_jm_slot::submitted). + * + * In addition, there's no return value - we'll run the maintenence functions + * on the Policy's Run Pool, but if there's nothing there after that, then the + * Run Pool is truely empty, and so no more action need be taken. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + * - it must hold kbasep_js_device_data::runpool_irq::lock + * + * This must only be called whilst the GPU is powered - for example, when + * kbdev->jsdata.nr_user_contexts_running > 0. + * + * @note The caller \em might be holding one of the + * kbasep_js_kctx_info::ctx::jsctx_mutex locks. + * + */ +void kbasep_js_try_run_next_job_on_slot_nolock(struct kbase_device *kbdev, int js); + +/** + * @brief Try to submit the next job for each slot in the system, outside of IRQ context + * + * This will internally call kbasep_js_try_run_next_job_on_slot_nolock(), so similar + * locking conditions on the caller are required. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + * - it must hold kbasep_js_device_data::runpool_irq::lock + * + * @note The caller \em might be holding one of the + * kbasep_js_kctx_info::ctx::jsctx_mutex locks. + * + */ +void kbasep_js_try_run_next_job_nolock(struct kbase_device *kbdev); + +/** + * @brief Try to schedule the next context onto the Run Pool + * + * This checks whether there's space in the Run Pool to accommodate a new + * context. If so, it attempts to dequeue a context from the Policy Queue, and + * submit this to the Run Pool. + * + * If the scheduling succeeds, then it also makes a call to + * kbasep_js_try_run_next_job_nolock(), in case the new context has jobs + * matching the job slot requirements, but no other currently scheduled context + * has such jobs. + * + * Whilst attempting to obtain a context from the policy queue, or add a + * context to the runpool, this function takes a Power Manager active + * reference. If for any reason a context cannot be added to the runpool, any + * reference obtained is released once the context is safely back in the policy + * queue. If no context was available on the policy queue, any reference + * obtained is released too. + * + * Only if the context gets placed in the runpool does the Power Manager active + * reference stay held (and is effectively now owned by the + * context/runpool). It is only released once the context is removed + * completely, or added back to the policy queue + * (e.g. kbasep_js_runpool_release_ctx(), + * kbasep_js_runpool_requeue_or_kill_ctx(), etc) + * + * If any of these actions fail (Run Pool Full, Policy Queue empty, can't get + * PM active reference due to a suspend, etc) then any actions taken are rolled + * back and the function just returns normally. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::as[n].transaction_mutex (as this will be obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex, because it will + * be used internally. + * + */ +void kbasep_js_try_schedule_head_ctx(struct kbase_device *kbdev); + +/** + * @brief Schedule in a privileged context + * + * This schedules a context in regardless of the context priority. + * If the runpool is full, a context will be forced out of the runpool and the function will wait + * for the new context to be scheduled in. + * The context will be kept scheduled in (and the corresponding address space reserved) until + * kbasep_js_release_privileged_ctx is called). + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::as[n].transaction_mutex (as this will be obtained internally) + * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex, because it will + * be used internally. + * + */ +void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Release a privileged context, allowing it to be scheduled out. + * + * See kbasep_js_runpool_release_ctx for potential side effects. + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpool_irq::lock, because + * it will be used internally. + * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold the kbase_device::as[n].transaction_mutex (as this will be obtained internally) + * + */ +void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Handle the Job Scheduler component for the IRQ of a job finishing + * + * This does the following: + * -# Releases resources held by the atom + * -# if \a end_timestamp != NULL, updates the runpool's notion of time spent by a running ctx + * -# determines whether a context should be marked for scheduling out + * -# examines done_code to determine whether to submit the next job on the slot + * (picking from all ctxs in the runpool) + * + * In addition, if submission didn't happen (the submit-from-IRQ function + * failed or done_code didn't specify to start new jobs), then this sets a + * message on katom that submission needs to be retried from the worker thread. + * + * Normally, the time calculated from end_timestamp is rounded up to the + * minimum time precision. Therefore, to ensure the job is recorded as not + * spending any time, then set end_timestamp to NULL. For example, this is necessary when + * evicting jobs from JS_HEAD_NEXT (because they didn't actually run). + * + * NOTE: It's possible to move the steps (2) and (3) (inc calculating job's time + * used) into the worker (outside of IRQ context), but this may allow a context + * to use up to twice as much timeslice as is allowed by the policy. For + * policies that order by time spent, this is not a problem for overall + * 'fairness', but can still increase latency between contexts. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpoool_irq::lock + */ +void kbasep_js_job_done_slot_irq(struct kbase_jd_atom *katom, int slot_nr, + ktime_t *end_timestamp, + kbasep_js_atom_done_code done_code); + +/** + * @brief Try to submit the next job on each slot + * + * The following locks may be used: + * - kbasep_js_device_data::runpool_mutex + * - kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_try_run_jobs(struct kbase_device *kbdev); + +/** + * @brief Try to submit the next job on a specfic slot + * + * The following locking conditions are made on the caller: + * + * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be + * obtained internally) + * - it must \em not hold kbasep_js_device_data::runpool_irq::lock (as this + * will be obtained internally) + * + */ +void kbase_js_try_run_jobs_on_slot(struct kbase_device *kbdev, int js); + +/** + * @brief Handle releasing cores for power management and affinity management, + * ensuring that cores are powered down and affinity tracking is updated. + * + * This must only be called on an atom that is not currently running, and has + * not been re-queued onto the context (and so does not need locking) + * + * This function enters at the following @ref enum kbase_atom_coreref_state states: + * - NO_CORES_REQUESTED + * - WAITING_FOR_REQUESTED_CORES + * - RECHECK_AFFINITY + * - READY + * + * It transitions the above states back to NO_CORES_REQUESTED by the end of the + * function call (possibly via intermediate states). + * + * No locks need be held by the caller, since this takes the necessary Power + * Management locks itself. The runpool_irq.lock is not taken (the work that + * requires it is handled by kbase_js_affinity_submit_to_blocked_slots() ). + * + * @note The corresponding kbasep_js_job_check_ref_cores() is private to the + * Job Scheduler, and is called automatically when running the next job. + */ +void kbasep_js_job_check_deref_cores(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +/** + * @brief Suspend the job scheduler during a Power Management Suspend event. + * + * Causes all contexts to be removed from the runpool, and prevents any + * contexts from (re)entering the runpool. + * + * This does not handle suspending the one privileged context: the caller must + * instead do this by by suspending the GPU HW Counter Instrumentation. + * + * This will eventually cause all Power Management active references held by + * contexts on the runpool to be released, without running any more atoms. + * + * The caller must then wait for all Power Mangement active refcount to become + * zero before completing the suspend. + * + * The emptying mechanism may take some time to complete, since it can wait for + * jobs to complete naturally instead of forcing them to end quickly. However, + * this is bounded by the Job Scheduling Policy's Job Timeouts. Hence, this + * function is guaranteed to complete in a finite time whenever the Job + * Scheduling Policy implements Job Timeouts (such as those done by CFS). + */ +void kbasep_js_suspend(struct kbase_device *kbdev); + +/** + * @brief Resume the Job Scheduler after a Power Management Resume event. + * + * This restores the actions from kbasep_js_suspend(): + * - Schedules contexts back into the runpool + * - Resumes running atoms on the GPU + */ +void kbasep_js_resume(struct kbase_device *kbdev); + + +/* + * Helpers follow + */ + +/** + * @brief Check that a context is allowed to submit jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * As with any mali_bool, never test the return value with MALI_TRUE. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock. + */ +static INLINE mali_bool kbasep_js_is_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 test_bit; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.is_scheduled != MALI_FALSE); + + test_bit = (u16) (1u << kctx->as_nr); + + return (mali_bool) (js_devdata->runpool_irq.submit_allowed & test_bit); +} + +/** + * @brief Allow a context to submit jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock. + */ +static INLINE void kbasep_js_set_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 set_bit; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.is_scheduled != MALI_FALSE); + + set_bit = (u16) (1u << kctx->as_nr); + + dev_dbg(kctx->kbdev->dev, "JS: Setting Submit Allowed on %p (as=%d)", kctx, kctx->as_nr); + + js_devdata->runpool_irq.submit_allowed |= set_bit; +} + +/** + * @brief Prevent a context from submitting more jobs on this policy + * + * The purpose of this abstraction is to hide the underlying data size, and wrap up + * the long repeated line of code. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock. + */ +static INLINE void kbasep_js_clear_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) +{ + u16 clear_bit; + u16 clear_mask; + + /* Ensure context really is scheduled in */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.is_scheduled != MALI_FALSE); + + clear_bit = (u16) (1u << kctx->as_nr); + clear_mask = ~clear_bit; + + dev_dbg(kctx->kbdev->dev, "JS: Clearing Submit Allowed on %p (as=%d)", kctx, kctx->as_nr); + + js_devdata->runpool_irq.submit_allowed &= clear_mask; +} + +/** + * @brief Manage the 'retry_submit_on_slot' part of a kbase_jd_atom + */ +static INLINE void kbasep_js_clear_job_retry_submit(struct kbase_jd_atom *atom) +{ + atom->retry_submit_on_slot = KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID; +} + +/** + * Mark a slot as requiring resubmission by carrying that information on a + * completing atom. + * + * @note This can ASSERT in debug builds if the submit slot has been set to + * something other than the current value for @a js. This is because you might + * be unintentionally stopping more jobs being submitted on the old submit + * slot, and that might cause a scheduling-hang. + * + * @note If you can guarantee that the atoms for the original slot will be + * submitted on some other slot, then call kbasep_js_clear_job_retry_submit() + * first to silence the ASSERT. + */ +static INLINE void kbasep_js_set_job_retry_submit_slot(struct kbase_jd_atom *atom, int js) +{ + KBASE_DEBUG_ASSERT(0 <= js && js <= BASE_JM_MAX_NR_SLOTS); + KBASE_DEBUG_ASSERT(atom->retry_submit_on_slot == KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID + || atom->retry_submit_on_slot == js); + + atom->retry_submit_on_slot = js; +} + +/** + * Create an initial 'invalid' atom retained state, that requires no + * atom-related work to be done on releasing with + * kbasep_js_runpool_release_ctx_and_katom_retained_state() + */ +static INLINE void kbasep_js_atom_retained_state_init_invalid(struct kbasep_js_atom_retained_state *retained_state) +{ + retained_state->event_code = BASE_JD_EVENT_NOT_STARTED; + retained_state->core_req = KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID; + retained_state->retry_submit_on_slot = KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID; +} + +/** + * Copy atom state that can be made available after jd_done_nolock() is called + * on that atom. + */ +static INLINE void kbasep_js_atom_retained_state_copy(struct kbasep_js_atom_retained_state *retained_state, const struct kbase_jd_atom *katom) +{ + retained_state->event_code = katom->event_code; + retained_state->core_req = katom->core_req; + retained_state->retry_submit_on_slot = katom->retry_submit_on_slot; + retained_state->device_nr = katom->device_nr; +} + +/** + * @brief Determine whether an atom has finished (given its retained state), + * and so should be given back to userspace/removed from the system. + * + * Reasons for an atom not finishing include: + * - Being soft-stopped (and so, the atom should be resubmitted sometime later) + * + * @param[in] katom_retained_state the retained state of the atom to check + * @return MALI_FALSE if the atom has not finished + * @return !=MALI_FALSE if the atom has finished + */ +static INLINE mali_bool kbasep_js_has_atom_finished(const struct kbasep_js_atom_retained_state *katom_retained_state) +{ + return (mali_bool) (katom_retained_state->event_code != BASE_JD_EVENT_STOPPED && katom_retained_state->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT); +} + +/** + * @brief Determine whether a struct kbasep_js_atom_retained_state is valid + * + * An invalid struct kbasep_js_atom_retained_state is allowed, and indicates that the + * code should just ignore it. + * + * @param[in] katom_retained_state the atom's retained state to check + * @return MALI_FALSE if the retained state is invalid, and can be ignored + * @return !=MALI_FALSE if the retained state is valid + */ +static INLINE mali_bool kbasep_js_atom_retained_state_is_valid(const struct kbasep_js_atom_retained_state *katom_retained_state) +{ + return (mali_bool) (katom_retained_state->core_req != KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID); +} + +static INLINE mali_bool kbasep_js_get_atom_retry_submit_slot(const struct kbasep_js_atom_retained_state *katom_retained_state, int *res) +{ + int js = katom_retained_state->retry_submit_on_slot; + *res = js; + return (mali_bool) (js >= 0); +} + +#if KBASE_DEBUG_DISABLE_ASSERTS == 0 +/** + * Debug Check the refcount of a context. Only use within ASSERTs + * + * Obtains kbasep_js_device_data::runpool_irq::lock + * + * @return negative value if the context is not scheduled in + * @return current refcount of the context if it is scheduled in. The refcount + * is not guarenteed to be kept constant. + */ +static INLINE int kbasep_js_debug_check_ctx_refcount(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int result = -1; + int as_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + as_nr = kctx->as_nr; + if (as_nr != KBASEP_AS_NR_INVALID) + result = js_devdata->runpool_irq.per_as_data[as_nr].as_busy_refcount; + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return result; +} +#endif /* KBASE_DEBUG_DISABLE_ASSERTS == 0 */ + +/** + * @brief Variant of kbasep_js_runpool_lookup_ctx() that can be used when the + * context is guarenteed to be already previously retained. + * + * It is a programming error to supply the \a as_nr of a context that has not + * been previously retained/has a busy refcount of zero. The only exception is + * when there is no ctx in \a as_nr (NULL returned). + * + * The following locking conditions are made on the caller: + * - it must \em not hold the kbasep_js_device_data::runpoool_irq::lock, because + * it will be used internally. + * + * @return a valid struct kbase_context on success, with a refcount that is guarenteed + * to be non-zero and unmodified by this function. + * @return NULL on failure, indicating that no context was found in \a as_nr + */ +static INLINE struct kbase_context *kbasep_js_runpool_lookup_ctx_noretain(struct kbase_device *kbdev, int as_nr) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + struct kbase_context *found_kctx; + struct kbasep_js_per_as_data *js_per_as_data; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS); + js_devdata = &kbdev->js_data; + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + + found_kctx = js_per_as_data->kctx; + KBASE_DEBUG_ASSERT(found_kctx == NULL || js_per_as_data->as_busy_refcount > 0); + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return found_kctx; +} + +/** + * This will provide a conversion from time (us) to ticks of the gpu clock + * based on the minimum available gpu frequency. + * This is usually good to compute best/worst case (where the use of current + * frequency is not valid due to DVFS). + * e.g.: when you need the number of cycles to guarantee you won't wait for + * longer than 'us' time (you might have a shorter wait). + */ +static INLINE u32 kbasep_js_convert_us_to_gpu_ticks_min_freq(struct kbase_device *kbdev, u32 us) +{ + u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_min; + KBASE_DEBUG_ASSERT(0 != gpu_freq); + return us * (gpu_freq / 1000); +} + +/** + * This will provide a conversion from time (us) to ticks of the gpu clock + * based on the maximum available gpu frequency. + * This is usually good to compute best/worst case (where the use of current + * frequency is not valid due to DVFS). + * e.g.: When you need the number of cycles to guarantee you'll wait at least + * 'us' amount of time (but you might wait longer). + */ +static INLINE u32 kbasep_js_convert_us_to_gpu_ticks_max_freq(struct kbase_device *kbdev, u32 us) +{ + u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_max; + KBASE_DEBUG_ASSERT(0 != gpu_freq); + return us * (u32) (gpu_freq / 1000); +} + +/** + * This will provide a conversion from ticks of the gpu clock to time (us) + * based on the minimum available gpu frequency. + * This is usually good to compute best/worst case (where the use of current + * frequency is not valid due to DVFS). + * e.g.: When you need to know the worst-case wait that 'ticks' cycles will + * take (you guarantee that you won't wait any longer than this, but it may + * be shorter). + */ +static INLINE u32 kbasep_js_convert_gpu_ticks_to_us_min_freq(struct kbase_device *kbdev, u32 ticks) +{ + u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_min; + KBASE_DEBUG_ASSERT(0 != gpu_freq); + return ticks / gpu_freq * 1000; +} + +/** + * This will provide a conversion from ticks of the gpu clock to time (us) + * based on the maximum available gpu frequency. + * This is usually good to compute best/worst case (where the use of current + * frequency is not valid due to DVFS). + * e.g.: When you need to know the best-case wait for 'tick' cycles (you + * guarantee to be waiting for at least this long, but it may be longer). + */ +static INLINE u32 kbasep_js_convert_gpu_ticks_to_us_max_freq(struct kbase_device *kbdev, u32 ticks) +{ + u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_max; + KBASE_DEBUG_ASSERT(0 != gpu_freq); + return ticks / gpu_freq * 1000; +} + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.c new file mode 100644 index 0000000000000000000000000000000000000000..7a4cae3be870bfad6261fc84fb14d6e853af4df0 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.c @@ -0,0 +1,382 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_affinity.c + * Base kernel affinity manager APIs + */ + +#include +#include "mali_kbase_js_affinity.h" + + +STATIC INLINE mali_bool affinity_job_uses_high_cores(struct kbase_device *kbdev, struct kbase_jd_atom *katom) +{ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + struct kbase_context *kctx; + kbase_context_flags ctx_flags; + + kctx = katom->kctx; + ctx_flags = kctx->jctx.sched_info.ctx.flags; + + /* In this HW Workaround, compute-only jobs/contexts use the high cores + * during a core-split, all other contexts use the low cores. */ + return (mali_bool) ((katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) != 0 || (ctx_flags & KBASE_CTX_FLAG_HINT_ONLY_COMPUTE) != 0); + } + return MALI_FALSE; +} + +/** + * @brief Decide whether a split in core affinity is required across job slots + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_irq::lock + * + * @param kbdev The kbase device structure of the device + * @return MALI_FALSE if a core split is not required + * @return != MALI_FALSE if a core split is required. + */ +STATIC INLINE mali_bool kbase_affinity_requires_split(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + s8 nr_compute_ctxs = kbasep_js_ctx_attr_count_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_COMPUTE); + s8 nr_noncompute_ctxs = kbasep_js_ctx_attr_count_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_NON_COMPUTE); + + /* In this case, a mix of Compute+Non-Compute determines whether a + * core-split is required, to ensure jobs with different numbers of RMUs + * don't use the same cores. + * + * When it's entirely compute, or entirely non-compute, then no split is + * required. + * + * A context can be both Compute and Non-compute, in which case this will + * correctly decide that a core-split is required. */ + + return (mali_bool) (nr_compute_ctxs > 0 && nr_noncompute_ctxs > 0); + } + return MALI_FALSE; +} + +mali_bool kbase_js_can_run_job_on_slot_no_lock(struct kbase_device *kbdev, int js) +{ + /* + * Here are the reasons for using job slot 2: + * - BASE_HW_ISSUE_8987 (which is entirely used for that purpose) + * - In absence of the above, then: + * - Atoms with BASE_JD_REQ_COHERENT_GROUP + * - But, only when there aren't contexts with + * KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES, because the atoms that run on + * all cores on slot 1 could be blocked by those using a coherent group + * on slot 2 + * - And, only when you actually have 2 or more coregroups - if you only + * have 1 coregroup, then having jobs for slot 2 implies they'd also be + * for slot 1, meaning you'll get interference from them. Jobs able to + * run on slot 2 could also block jobs that can only run on slot 1 + * (tiler jobs) + */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) + return MALI_TRUE; + + if (js != 2) + return MALI_TRUE; + + /* Only deal with js==2 now: */ + if (kbdev->gpu_props.num_core_groups > 1) { + /* Only use slot 2 in the 2+ coregroup case */ + if (kbasep_js_ctx_attr_is_attr_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES) == MALI_FALSE) { + /* ...But only when we *don't* have atoms that run on all cores */ + + /* No specific check for BASE_JD_REQ_COHERENT_GROUP atoms - the policy will sort that out */ + return MALI_TRUE; + } + } + + /* Above checks failed mean we shouldn't use slot 2 */ + return MALI_FALSE; +} + +/* + * As long as it has been decided to have a deeper modification of + * what job scheduler, power manager and affinity manager will + * implement, this function is just an intermediate step that + * assumes: + * - all working cores will be powered on when this is called. + * - largest current configuration is 2 core groups. + * - It has been decided not to have hardcoded values so the low + * and high cores in a core split will be evently distributed. + * - Odd combinations of core requirements have been filtered out + * and do not get to this function (e.g. CS+T+NSS is not + * supported here). + * - This function is frequently called and can be optimized, + * (see notes in loops), but as the functionallity will likely + * be modified, optimization has not been addressed. +*/ +mali_bool kbase_js_choose_affinity(u64 * const affinity, struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js) +{ + base_jd_core_req core_req = katom->core_req; + unsigned int num_core_groups = kbdev->gpu_props.num_core_groups; + u64 core_availability_mask; + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + core_availability_mask = kbase_pm_ca_get_core_mask(kbdev); + + /* + * If no cores are currently available (core availability policy is + * transitioning) then fail. + */ + if (0 == core_availability_mask) { + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + *affinity = 0; + return MALI_FALSE; + } + + KBASE_DEBUG_ASSERT(js >= 0); + + if ((core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) == BASE_JD_REQ_T) { + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + /* Tiler only job, bit 0 needed to enable tiler but no shader cores required */ + *affinity = 1; + return MALI_TRUE; + } + + if (1 == kbdev->gpu_props.num_cores) { + /* trivial case only one core, nothing to do */ + *affinity = core_availability_mask; + } else if (kbase_affinity_requires_split(kbdev) == MALI_FALSE) { + if ((core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP))) { + if (js == 0 || num_core_groups == 1) { + /* js[0] and single-core-group systems just get the first core group */ + *affinity = kbdev->gpu_props.props.coherency_info.group[0].core_mask & core_availability_mask; + } else { + /* js[1], js[2] use core groups 0, 1 for dual-core-group systems */ + u32 core_group_idx = ((u32) js) - 1; + + KBASE_DEBUG_ASSERT(core_group_idx < num_core_groups); + *affinity = kbdev->gpu_props.props.coherency_info.group[core_group_idx].core_mask & core_availability_mask; + + /* If the job is specifically targeting core group 1 and the core + * availability policy is keeping that core group off, then fail */ + if (*affinity == 0 && core_group_idx == 1 && kbdev->pm.cg1_disabled == MALI_TRUE) + katom->event_code = BASE_JD_EVENT_PM_EVENT; + } + } else { + /* All cores are available when no core split is required */ + *affinity = core_availability_mask; + } + } else { + /* Core split required - divide cores in two non-overlapping groups */ + u64 low_bitmap, high_bitmap; + int n_high_cores = kbdev->gpu_props.num_cores >> 1; + KBASE_DEBUG_ASSERT(1 == num_core_groups); + KBASE_DEBUG_ASSERT(0 != n_high_cores); + + /* compute the reserved high cores bitmap */ + high_bitmap = ~0; + /* note: this can take a while, optimization desirable */ + while (n_high_cores != hweight32(high_bitmap & kbdev->shader_present_bitmap)) + high_bitmap = high_bitmap << 1; + + high_bitmap &= core_availability_mask; + low_bitmap = core_availability_mask ^ high_bitmap; + + if (affinity_job_uses_high_cores(kbdev, katom)) + *affinity = high_bitmap; + else + *affinity = low_bitmap; + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* + * If no cores are currently available in the desired core group(s) + * (core availability policy is transitioning) then fail. + */ + if (*affinity == 0) + return MALI_FALSE; + + /* Enable core 0 if tiler required */ + if (core_req & BASE_JD_REQ_T) + *affinity = *affinity | 1; + + return MALI_TRUE; +} + +STATIC INLINE mali_bool kbase_js_affinity_is_violating(struct kbase_device *kbdev, u64 *affinities) +{ + /* This implementation checks whether the two slots involved in Generic thread creation + * have intersecting affinity. This is due to micro-architectural issues where a job in + * slot A targetting cores used by slot B could prevent the job in slot B from making + * progress until the job in slot A has completed. + * + * @note It just so happens that this restriction also allows + * BASE_HW_ISSUE_8987 to be worked around by placing on job slot 2 the + * atoms from ctxs with KBASE_CTX_FLAG_HINT_ONLY_COMPUTE flag set + */ + u64 affinity_set_left; + u64 affinity_set_right; + u64 intersection; + + KBASE_DEBUG_ASSERT(affinities != NULL); + + affinity_set_left = affinities[1]; + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + /* The left set also includes those on the Fragment slot when + * we are using the HW workaround for BASE_HW_ISSUE_8987 */ + affinity_set_left |= affinities[0]; + } + + affinity_set_right = affinities[2]; + + /* A violation occurs when any bit in the left_set is also in the right_set */ + intersection = affinity_set_left & affinity_set_right; + + return (mali_bool) (intersection != (u64) 0u); +} + +mali_bool kbase_js_affinity_would_violate(struct kbase_device *kbdev, int js, u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 new_affinities[BASE_JM_MAX_NR_SLOTS]; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + memcpy(new_affinities, js_devdata->runpool_irq.slot_affinities, sizeof(js_devdata->runpool_irq.slot_affinities)); + + new_affinities[js] |= affinity; + + return kbase_js_affinity_is_violating(kbdev, new_affinities); +} + +void kbase_js_affinity_retain_slot_cores(struct kbase_device *kbdev, int js, u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 cores; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(kbase_js_affinity_would_violate(kbdev, js, affinity) == MALI_FALSE); + + cores = affinity; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + s8 cnt; + + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum] < BASE_JM_SUBMIT_SLOTS); + + cnt = ++(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum]); + + if (cnt == 1) + js_devdata->runpool_irq.slot_affinities[js] |= bit; + + cores &= ~bit; + } +} + +void kbase_js_affinity_release_slot_cores(struct kbase_device *kbdev, int js, u64 affinity) +{ + struct kbasep_js_device_data *js_devdata; + u64 cores; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + cores = affinity; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + s8 cnt; + + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum] > 0); + + cnt = --(js_devdata->runpool_irq.slot_affinity_refcount[js][bitnum]); + + if (0 == cnt) + js_devdata->runpool_irq.slot_affinities[js] &= ~bit; + + cores &= ~bit; + } + +} + +void kbase_js_affinity_slot_blocked_an_atom(struct kbase_device *kbdev, int js) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(js < BASE_JM_MAX_NR_SLOTS); + js_devdata = &kbdev->js_data; + + js_devdata->runpool_irq.slots_blocked_on_affinity |= 1u << js; +} + +void kbase_js_affinity_submit_to_blocked_slots(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + u16 slots; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running != 0); + + /* Must take a copy because submitting jobs will update this member. */ + slots = js_devdata->runpool_irq.slots_blocked_on_affinity; + + while (slots) { + int bitnum = fls(slots) - 1; + + u16 bit = 1u << bitnum; + slots &= ~bit; + + KBASE_TRACE_ADD_SLOT(kbdev, JS_AFFINITY_SUBMIT_TO_BLOCKED, NULL, NULL, 0u, bitnum); + + /* must update this before we submit, incase it's set again */ + js_devdata->runpool_irq.slots_blocked_on_affinity &= ~bit; + + kbasep_js_try_run_next_job_on_slot_nolock(kbdev, bitnum); + + /* Don't re-read slots_blocked_on_affinity after this - it could loop for a long time */ + } +} + +#if KBASE_TRACE_ENABLE +void kbase_js_debug_log_current_affinities(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + int slot_nr; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + for (slot_nr = 0; slot_nr < 3; ++slot_nr) + KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_AFFINITY_CURRENT, NULL, NULL, 0u, slot_nr, (u32) js_devdata->runpool_irq.slot_affinities[slot_nr]); +} +#endif /* KBASE_TRACE_ENABLE */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.h new file mode 100644 index 0000000000000000000000000000000000000000..83da812802dc8eaa66f2cf10281bb215f2077ac7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_affinity.h @@ -0,0 +1,157 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_affinity.h + * Affinity Manager internal APIs. + */ + +#ifndef _KBASE_JS_AFFINITY_H_ +#define _KBASE_JS_AFFINITY_H_ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js_affinity Affinity Manager internal APIs. + * @{ + * + */ + +/** + * @brief Decide whether it is possible to submit a job to a particular job slot in the current status + * + * Will check if submitting to the given job slot is allowed in the current + * status. For example using job slot 2 while in soft-stoppable state and only + * having 1 coregroup is not allowed by the policy. This function should be + * called prior to submitting a job to a slot to make sure policy rules are not + * violated. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_irq::lock + * + * @param kbdev The kbase device structure of the device + * @param js Job slot number to check for allowance + */ +mali_bool kbase_js_can_run_job_on_slot_no_lock(struct kbase_device *kbdev, int js); + +/** + * @brief Compute affinity for a given job. + * + * Currently assumes an all-on/all-off power management policy. + * Also assumes there is at least one core with tiler available. + * + * Returns MALI_TRUE if a valid affinity was chosen, MALI_FALSE if + * no cores were available. + * + * @param[out] affinity Affinity bitmap computed + * @param kbdev The kbase device structure of the device + * @param katom Job chain of which affinity is going to be found + * @param js Slot the job chain is being submitted + + */ +mali_bool kbase_js_choose_affinity(u64 * const affinity, struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js); + +/** + * @brief Determine whether a proposed \a affinity on job slot \a js would + * cause a violation of affinity restrictions. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + */ +mali_bool kbase_js_affinity_would_violate(struct kbase_device *kbdev, int js, u64 affinity); + +/** + * @brief Affinity tracking: retain cores used by a slot + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_affinity_retain_slot_cores(struct kbase_device *kbdev, int js, u64 affinity); + +/** + * @brief Affinity tracking: release cores used by a slot + * + * Cores \b must be released as soon as a job is dequeued from a slot's 'submit + * slots', and before another job is submitted to those slots. Otherwise, the + * refcount could exceed the maximum number submittable to a slot, + * BASE_JM_SUBMIT_SLOTS. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_affinity_release_slot_cores(struct kbase_device *kbdev, int js, u64 affinity); + +/** + * @brief Register a slot as blocking atoms due to affinity violations + * + * Once a slot has been registered, we must check after every atom completion + * (including those on different slots) to see if the slot can be + * unblocked. This is done by calling + * kbase_js_affinity_submit_to_blocked_slots(), which will also deregister the + * slot if it no long blocks atoms due to affinity violations. + * + * The following locks must be held by the caller: + * - kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_affinity_slot_blocked_an_atom(struct kbase_device *kbdev, int js); + +/** + * @brief Submit to job slots that have registered that an atom was blocked on + * the slot previously due to affinity violations. + * + * This submits to all slots registered by + * kbase_js_affinity_slot_blocked_an_atom(). If submission succeeded, then the + * slot is deregistered as having blocked atoms due to affinity + * violations. Otherwise it stays registered, and the next atom to complete + * must attempt to submit to the blocked slots again. + * + * This must only be called whilst the GPU is powered - for example, when + * kbdev->jsdata.nr_user_contexts_running > 0. + * + * The following locking conditions are made on the caller: + * - it must hold kbasep_js_device_data::runpool_mutex + * - it must hold kbasep_js_device_data::runpool_irq::lock + */ +void kbase_js_affinity_submit_to_blocked_slots(struct kbase_device *kbdev); + +/** + * @brief Output to the Trace log the current tracked affinities on all slots + */ +#if KBASE_TRACE_ENABLE +void kbase_js_debug_log_current_affinities(struct kbase_device *kbdev); +#else /* KBASE_TRACE_ENABLE */ +static INLINE void kbase_js_debug_log_current_affinities(struct kbase_device *kbdev) +{ +} +#endif /* KBASE_TRACE_ENABLE */ + + /** @} *//* end group kbase_js_affinity */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + + +#endif /* _KBASE_JS_AFFINITY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c new file mode 100644 index 0000000000000000000000000000000000000000..aa13bdb7fda3e0092341bd9b7f054308dc39cb3b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c @@ -0,0 +1,329 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#include +#include + +/* + * Private functions follow + */ + +/** + * @brief Check whether a ctx has a certain attribute, and if so, retain that + * attribute on the runpool. + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx is scheduled on the runpool + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +STATIC mali_bool kbasep_js_ctx_attr_runpool_retain_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE); + + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != MALI_FALSE) { + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] < S8_MAX); + ++(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]); + + if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 1) { + /* First refcount indicates a state change */ + runpool_state_changed = MALI_TRUE; + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_ON_RUNPOOL, kctx, NULL, 0u, attribute); + } + } + + return runpool_state_changed; +} + +/** + * @brief Check whether a ctx has a certain attribute, and if so, release that + * attribute on the runpool. + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx is scheduled on the runpool + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +STATIC mali_bool kbasep_js_ctx_attr_runpool_release_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE); + + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != MALI_FALSE) { + KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] > 0); + --(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]); + + if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 0) { + /* Last de-refcount indicates a state change */ + runpool_state_changed = MALI_TRUE; + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_OFF_RUNPOOL, kctx, NULL, 0u, attribute); + } + } + + return runpool_state_changed; +} + +/** + * @brief Retain a certain attribute on a ctx, also retaining it on the runpool + * if the context is scheduled. + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * This may allow the scheduler to submit more jobs than previously. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +STATIC mali_bool kbasep_js_ctx_attr_ctx_retain_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] < U32_MAX); + + ++(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); + + if (js_kctx_info->ctx.is_scheduled != MALI_FALSE && js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) { + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + /* Only ref-count the attribute on the runpool for the first time this contexts sees this attribute */ + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_ON_CTX, kctx, NULL, 0u, attribute); + runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, attribute); + } + + return runpool_state_changed; +} + +/** + * @brief Release a certain attribute on a ctx, also releasign it from the runpool + * if the context is scheduled. + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * This may allow the scheduler to submit more jobs than previously. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +STATIC mali_bool kbasep_js_ctx_attr_ctx_release_attr(struct kbase_device *kbdev, struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex)); + KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] > 0); + + if (js_kctx_info->ctx.is_scheduled != MALI_FALSE && js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) { + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + /* Only de-ref-count the attribute on the runpool when this is the last ctx-reference to it */ + runpool_state_changed = kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, attribute); + KBASE_TRACE_ADD(kbdev, JS_CTX_ATTR_NOW_OFF_CTX, kctx, NULL, 0u, attribute); + } + + /* De-ref must happen afterwards, because kbasep_js_ctx_attr_runpool_release() needs to check it too */ + --(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); + + return runpool_state_changed; +} + +/* + * More commonly used public functions + */ + +void kbasep_js_ctx_attr_set_initial_attrs(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_kctx_info *js_kctx_info; + mali_bool runpool_state_changed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + js_kctx_info = &kctx->jctx.sched_info; + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) != MALI_FALSE) { + /* This context never submits, so don't track any scheduling attributes */ + return; + } + + /* Transfer attributes held in the context flags for contexts that have submit enabled */ + + if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_HINT_ONLY_COMPUTE) != MALI_FALSE) { + /* Compute context */ + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); + } + /* NOTE: Whether this is a non-compute context depends on the jobs being + * run, e.g. it might be submitting jobs with BASE_JD_REQ_ONLY_COMPUTE */ + + /* ... More attributes can be added here ... */ + + /* The context should not have been scheduled yet, so ASSERT if this caused + * runpool state changes (note that other threads *can't* affect the value + * of runpool_state_changed, due to how it's calculated) */ + KBASE_DEBUG_ASSERT(runpool_state_changed == MALI_FALSE); + CSTD_UNUSED(runpool_state_changed); +} + +void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + mali_bool runpool_state_changed; + int i; + + /* Retain any existing attributes */ + for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) { + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr) i) != MALI_FALSE) { + /* The context is being scheduled in, so update the runpool with the new attributes */ + runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, (enum kbasep_js_ctx_attr) i); + + /* We don't need to know about state changed, because retaining a + * context occurs on scheduling it, and that itself will also try + * to run new atoms */ + CSTD_UNUSED(runpool_state_changed); + } + } +} + +mali_bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + mali_bool runpool_state_changed = MALI_FALSE; + int i; + + /* Release any existing attributes */ + for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) { + if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr) i) != MALI_FALSE) { + /* The context is being scheduled out, so update the runpool on the removed attributes */ + runpool_state_changed |= kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, (enum kbasep_js_ctx_attr) i); + } + } + + return runpool_state_changed; +} + +void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + mali_bool runpool_state_changed = MALI_FALSE; + base_jd_core_req core_req; + + KBASE_DEBUG_ASSERT(katom); + core_req = katom->core_req; + + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); + else + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE); + + if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) { + /* Atom that can run on slot1 or slot2, and can use all cores */ + runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES); + } + + /* We don't need to know about state changed, because retaining an + * atom occurs on adding it, and that itself will also try to run + * new atoms */ + CSTD_UNUSED(runpool_state_changed); +} + +mali_bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state) +{ + mali_bool runpool_state_changed = MALI_FALSE; + base_jd_core_req core_req; + + KBASE_DEBUG_ASSERT(katom_retained_state); + core_req = katom_retained_state->core_req; + + /* No-op for invalid atoms */ + if (kbasep_js_atom_retained_state_is_valid(katom_retained_state) == MALI_FALSE) + return MALI_FALSE; + + if (core_req & BASE_JD_REQ_ONLY_COMPUTE) { +#if KBASE_PM_EN + unsigned long flags; + int device_nr = (core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) ? katom_retained_state->device_nr : 0; + KBASE_DEBUG_ASSERT(device_nr < 2); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbasep_pm_record_job_status(kbdev); + kbdev->pm.metrics.active_cl_ctx[device_nr]--; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +#endif + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); + } else { +#if KBASE_PM_EN + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbasep_pm_record_job_status(kbdev); + kbdev->pm.metrics.active_gl_ctx--; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +#endif + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE); + } + + if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) { + /* Atom that can run on slot1 or slot2, and can use all cores */ + runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES); + } + + return runpool_state_changed; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h new file mode 100644 index 0000000000000000000000000000000000000000..6a57538298d0b3f0f47380e03c51b6063b99939b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h @@ -0,0 +1,158 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_ctx_attr.h + * Job Scheduler Context Attribute APIs + */ + +#ifndef _KBASE_JS_CTX_ATTR_H_ +#define _KBASE_JS_CTX_ATTR_H_ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js + * @{ + */ + +/** + * Set the initial attributes of a context (when context create flags are set) + * + * Requires: + * - Hold the jsctx_mutex + */ +void kbasep_js_ctx_attr_set_initial_attrs(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Retain all attributes of a context + * + * This occurs on scheduling in the context on the runpool (but after + * is_scheduled is set) + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx->is_scheduled is true + */ +void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Release all attributes of a context + * + * This occurs on scheduling out the context from the runpool (but before + * is_scheduled is cleared) + * + * Requires: + * - jsctx mutex + * - runpool_irq spinlock + * - ctx->is_scheduled is true + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +mali_bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * Retain all attributes of an atom + * + * This occurs on adding an atom to a context + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + */ +void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * Release all attributes of an atom, given its retained state. + * + * This occurs after (permanently) removing an atom from a context + * + * Requires: + * - jsctx mutex + * - If the context is scheduled, then runpool_irq spinlock must also be held + * + * This is a no-op when \a katom_retained_state is invalid. + * + * @return MALI_TRUE indicates a change in ctx attributes state of the runpool. + * In this state, the scheduler might be able to submit more jobs than + * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() + * or similar is called sometime later. + * @return MALI_FALSE indicates no change in ctx attributes state of the runpool. + */ +mali_bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state); + +/** + * Requires: + * - runpool_irq spinlock + */ +static INLINE s8 kbasep_js_ctx_attr_count_on_runpool(struct kbase_device *kbdev, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_devdata = &kbdev->js_data; + + return js_devdata->runpool_irq.ctx_attr_ref_count[attribute]; +} + +/** + * Requires: + * - runpool_irq spinlock + */ +static INLINE mali_bool kbasep_js_ctx_attr_is_attr_on_runpool(struct kbase_device *kbdev, enum kbasep_js_ctx_attr attribute) +{ + /* In general, attributes are 'on' when they have a non-zero refcount (note: the refcount will never be < 0) */ + return (mali_bool) kbasep_js_ctx_attr_count_on_runpool(kbdev, attribute); +} + +/** + * Requires: + * - jsctx mutex + */ +static INLINE mali_bool kbasep_js_ctx_attr_is_attr_on_ctx(struct kbase_context *kctx, enum kbasep_js_ctx_attr attribute) +{ + struct kbasep_js_kctx_info *js_kctx_info; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); + js_kctx_info = &kctx->jctx.sched_info; + + /* In general, attributes are 'on' when they have a refcount (which should never be < 0) */ + return (mali_bool) (js_kctx_info->ctx.ctx_attr_ref_count[attribute]); +} + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_DEFS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_defs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..e9572ba754a9bc637a6492f6a9affe882e2baac1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_defs.h @@ -0,0 +1,481 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js.h + * Job Scheduler Type Definitions + */ + +#ifndef _KBASE_JS_DEFS_H_ +#define _KBASE_JS_DEFS_H_ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js + * @{ + */ +/* Forward decls */ +struct kbase_device; +struct kbase_jd_atom; + + +/* Types used by the policies must go here */ +enum { + /** Context will not submit any jobs */ + KBASE_CTX_FLAG_SUBMIT_DISABLED = (1u << 0), + + /** Set if the context uses an address space and should be kept scheduled in */ + KBASE_CTX_FLAG_PRIVILEGED = (1u << 1), + + /** Kernel-side equivalent of BASE_CONTEXT_HINT_ONLY_COMPUTE. Non-mutable after creation flags set */ + KBASE_CTX_FLAG_HINT_ONLY_COMPUTE = (1u << 2) + + /* NOTE: Add flags for other things, such as 'is scheduled', and 'is dying' */ +}; + +typedef u32 kbase_context_flags; + +struct kbasep_atom_req { + base_jd_core_req core_req; + kbase_context_flags ctx_req; + u32 device_nr; +}; + +#include "mali_kbase_js_policy_cfs.h" + +/* Wrapper Interface - doxygen is elsewhere */ +union kbasep_js_policy { +#ifdef KBASE_JS_POLICY_AVAILABLE_FCFS + struct kbasep_js_policy_fcfs fcfs; +#endif +#ifdef KBASE_JS_POLICY_AVAILABLE_CFS + struct kbasep_js_policy_cfs cfs; +#endif +}; + +/* Wrapper Interface - doxygen is elsewhere */ +union kbasep_js_policy_ctx_info { +#ifdef KBASE_JS_POLICY_AVAILABLE_FCFS + struct kbasep_js_policy_fcfs_ctx fcfs; +#endif +#ifdef KBASE_JS_POLICY_AVAILABLE_CFS + struct kbasep_js_policy_cfs_ctx cfs; +#endif +}; + +/* Wrapper Interface - doxygen is elsewhere */ +union kbasep_js_policy_job_info { +#ifdef KBASE_JS_POLICY_AVAILABLE_FCFS + struct kbasep_js_policy_fcfs_job fcfs; +#endif +#ifdef KBASE_JS_POLICY_AVAILABLE_CFS + struct kbasep_js_policy_cfs_job cfs; +#endif +}; + + +/** Callback function run on all of a context's jobs registered with the Job + * Scheduler */ +typedef void (*kbasep_js_policy_ctx_job_cb)(struct kbase_device *kbdev, struct kbase_jd_atom *katom); + +/** + * @brief Maximum number of jobs that can be submitted to a job slot whilst + * inside the IRQ handler. + * + * This is important because GPU NULL jobs can complete whilst the IRQ handler + * is running. Otherwise, it potentially allows an unlimited number of GPU NULL + * jobs to be submitted inside the IRQ handler, which increases IRQ latency. + */ +#define KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ 2 + +/** + * @brief the IRQ_THROTTLE time in microseconds + * + * This will be converted via the GPU's clock frequency into a cycle-count. + * + * @note we can make an estimate of the GPU's frequency by periodically + * sampling its CYCLE_COUNT register + */ +#define KBASE_JS_IRQ_THROTTLE_TIME_US 20 + +/** + * @brief Context attributes + * + * Each context attribute can be thought of as a boolean value that caches some + * state information about either the runpool, or the context: + * - In the case of the runpool, it is a cache of "Do any contexts owned by + * the runpool have attribute X?" + * - In the case of a context, it is a cache of "Do any atoms owned by the + * context have attribute X?" + * + * The boolean value of the context attributes often affect scheduling + * decisions, such as affinities to use and job slots to use. + * + * To accomodate changes of state in the context, each attribute is refcounted + * in the context, and in the runpool for all running contexts. Specifically: + * - The runpool holds a refcount of how many contexts in the runpool have this + * attribute. + * - The context holds a refcount of how many atoms have this attribute. + * + * Examples of use: + * - Finding out when there are a mix of @ref BASE_CONTEXT_HINT_ONLY_COMPUTE + * and ! @ref BASE_CONTEXT_HINT_ONLY_COMPUTE contexts in the runpool + */ +enum kbasep_js_ctx_attr { + /** Attribute indicating a context that contains Compute jobs. That is, + * @ref BASE_CONTEXT_HINT_ONLY_COMPUTE is \b set and/or the context has jobs of type + * @ref BASE_JD_REQ_ONLY_COMPUTE + * + * @note A context can be both 'Compute' and 'Non Compute' if it contains + * both types of jobs. + */ + KBASEP_JS_CTX_ATTR_COMPUTE, + + /** Attribute indicating a context that contains Non-Compute jobs. That is, + * the context has some jobs that are \b not of type @ref + * BASE_JD_REQ_ONLY_COMPUTE. The context usually has + * BASE_CONTEXT_HINT_COMPUTE \b clear, but this depends on the HW + * workarounds in use in the Job Scheduling Policy. + * + * @note A context can be both 'Compute' and 'Non Compute' if it contains + * both types of jobs. + */ + KBASEP_JS_CTX_ATTR_NON_COMPUTE, + + /** Attribute indicating that a context contains compute-job atoms that + * aren't restricted to a coherent group, and can run on all cores. + * + * Specifically, this is when the atom's \a core_req satisfy: + * - (\a core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T) // uses slot 1 or slot 2 + * - && !(\a core_req & BASE_JD_REQ_COHERENT_GROUP) // not restricted to coherent groups + * + * Such atoms could be blocked from running if one of the coherent groups + * is being used by another job slot, so tracking this context attribute + * allows us to prevent such situations. + * + * @note This doesn't take into account the 1-coregroup case, where all + * compute atoms would effectively be able to run on 'all cores', but + * contexts will still not always get marked with this attribute. Instead, + * it is the caller's responsibility to take into account the number of + * coregroups when interpreting this attribute. + * + * @note Whilst Tiler atoms are normally combined with + * BASE_JD_REQ_COHERENT_GROUP, it is possible to send such atoms without + * BASE_JD_REQ_COHERENT_GROUP set. This is an unlikely case, but it's easy + * enough to handle anyway. + */ + KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES, + + /** Must be the last in the enum */ + KBASEP_JS_CTX_ATTR_COUNT +}; + +enum { + /** Bit indicating that new atom should be started because this atom completed */ + KBASE_JS_ATOM_DONE_START_NEW_ATOMS = (1u << 0), + /** Bit indicating that the atom was evicted from the JS_NEXT registers */ + KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT = (1u << 1) +}; + +/** Combination of KBASE_JS_ATOM_DONE_<...> bits */ +typedef u32 kbasep_js_atom_done_code; + +/** + * Data used by the scheduler that is unique for each Address Space. + * + * This is used in IRQ context and kbasep_js_device_data::runpoool_irq::lock + * must be held whilst accessing this data (inculding reads and atomic + * decisions based on the read). + */ +struct kbasep_js_per_as_data { + /** + * Ref count of whether this AS is busy, and must not be scheduled out + * + * When jobs are running this is always positive. However, it can still be + * positive when no jobs are running. If all you need is a heuristic to + * tell you whether jobs might be running, this should be sufficient. + */ + int as_busy_refcount; + + /** Pointer to the current context on this address space, or NULL for no context */ + struct kbase_context *kctx; +}; + +/** + * @brief KBase Device Data Job Scheduler sub-structure + * + * This encapsulates the current context of the Job Scheduler on a particular + * device. This context is global to the device, and is not tied to any + * particular struct kbase_context running on the device. + * + * nr_contexts_running and as_free are optimized for packing together (by making + * them smaller types than u32). The operations on them should rarely involve + * masking. The use of signed types for arithmetic indicates to the compiler that + * the value will not rollover (which would be undefined behavior), and so under + * the Total License model, it is free to make optimizations based on that (i.e. + * to remove masking). + */ +struct kbasep_js_device_data { + /** Sub-structure to collect together Job Scheduling data used in IRQ context */ + struct runpool_irq { + /** + * Lock for accessing Job Scheduling data used in IRQ context + * + * This lock must be held whenever this data is accessed (read, or + * write). Even for read-only access, memory barriers would be needed. + * In any case, it is likely that decisions based on only reading must + * also be atomic with respect to data held here and elsewhere in the + * Job Scheduler. + * + * This lock must also be held for accessing: + * - kbase_context::as_nr + * - kbase_device::jm_slots + * - Parts of the kbasep_js_policy, dependent on the policy (refer to + * the policy in question for more information) + * - Parts of kbasep_js_policy_ctx_info, dependent on the policy (refer to + * the policy in question for more information) + */ + spinlock_t lock; + + /** Bitvector indicating whether a currently scheduled context is allowed to submit jobs. + * When bit 'N' is set in this, it indicates whether the context bound to address space + * 'N' (per_as_data[N].kctx) is allowed to submit jobs. + * + * It is placed here because it's much more memory efficient than having a mali_bool8 in + * struct kbasep_js_per_as_data to store this flag */ + u16 submit_allowed; + + /** Context Attributes: + * Each is large enough to hold a refcount of the number of contexts + * that can fit into the runpool. This is currently BASE_MAX_NR_AS + * + * Note that when BASE_MAX_NR_AS==16 we need 5 bits (not 4) to store + * the refcount. Hence, it's not worthwhile reducing this to + * bit-manipulation on u32s to save space (where in contrast, 4 bit + * sub-fields would be easy to do and would save space). + * + * Whilst this must not become negative, the sign bit is used for: + * - error detection in debug builds + * - Optimization: it is undefined for a signed int to overflow, and so + * the compiler can optimize for that never happening (thus, no masking + * is required on updating the variable) */ + s8 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT]; + + /** Data that is unique for each AS */ + struct kbasep_js_per_as_data per_as_data[BASE_MAX_NR_AS]; + + /* + * Affinity management and tracking + */ + /** Bitvector to aid affinity checking. Element 'n' bit 'i' indicates + * that slot 'n' is using core i (i.e. slot_affinity_refcount[n][i] > 0) */ + u64 slot_affinities[BASE_JM_MAX_NR_SLOTS]; + /** Bitvector indicating which slots \em might have atoms blocked on + * them because otherwise they'd violate affinity restrictions */ + u16 slots_blocked_on_affinity; + /** Refcount for each core owned by each slot. Used to generate the + * slot_affinities array of bitvectors + * + * The value of the refcount will not exceed BASE_JM_SUBMIT_SLOTS, + * because it is refcounted only when a job is definitely about to be + * submitted to a slot, and is de-refcounted immediately after a job + * finishes */ + s8 slot_affinity_refcount[BASE_JM_MAX_NR_SLOTS][64]; + } runpool_irq; + + /** + * Run Pool mutex, for managing contexts within the runpool. + * Unless otherwise specified, you must hold this lock whilst accessing any + * members that follow + * + * In addition, this is used to access: + * - the kbasep_js_kctx_info::runpool substructure + */ + struct mutex runpool_mutex; + + /** + * Queue Lock, used to access the Policy's queue of contexts independently + * of the Run Pool. + * + * Of course, you don't need the Run Pool lock to access this. + */ + struct mutex queue_mutex; + + u16 as_free; /**< Bitpattern of free Address Spaces */ + + /** Number of currently scheduled user contexts (excluding ones that are not submitting jobs) */ + s8 nr_user_contexts_running; + /** Number of currently scheduled contexts (including ones that are not submitting jobs) */ + s8 nr_all_contexts_running; + + /** + * Policy-specific information. + * + * Refer to the structure defined by the current policy to determine which + * locks must be held when accessing this. + */ + union kbasep_js_policy policy; + + /** Core Requirements to match up with base_js_atom's core_req memeber + * @note This is a write-once member, and so no locking is required to read */ + base_jd_core_req js_reqs[BASE_JM_MAX_NR_SLOTS]; + + u32 scheduling_tick_ns; /**< Value for KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS */ + u32 soft_stop_ticks; /**< Value for KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS */ + u32 soft_stop_ticks_cl; /**< Value for KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL */ + u32 hard_stop_ticks_ss; /**< Value for KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS */ + u32 hard_stop_ticks_cl; /**< Value for KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL */ + u32 hard_stop_ticks_nss; /**< Value for KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS */ + u32 gpu_reset_ticks_ss; /**< Value for KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS */ + u32 gpu_reset_ticks_cl; /**< Value for KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL */ + u32 gpu_reset_ticks_nss; /**< Value for KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS */ + u32 ctx_timeslice_ns; /**< Value for KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS */ + u32 cfs_ctx_runtime_init_slices; /**< Value for DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES */ + u32 cfs_ctx_runtime_min_slices; /**< Value for DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES */ + + /** List of suspended soft jobs */ + struct list_head suspended_soft_jobs_list; + +#ifdef CONFIG_MALI_DEBUG + /* Support soft-stop on a single context */ + mali_bool softstop_always; +#endif /* CONFIG_MALI_DEBUG */ + /** The initalized-flag is placed at the end, to avoid cache-pollution (we should + * only be using this during init/term paths). + * @note This is a write-once member, and so no locking is required to read */ + int init_status; +}; + +/** + * @brief KBase Context Job Scheduling information structure + * + * This is a substructure in the struct kbase_context that encapsulates all the + * scheduling information. + */ +struct kbasep_js_kctx_info { + /** + * Runpool substructure. This must only be accessed whilst the Run Pool + * mutex ( kbasep_js_device_data::runpool_mutex ) is held. + * + * In addition, the kbasep_js_device_data::runpool_irq::lock may need to be + * held for certain sub-members. + * + * @note some of the members could be moved into struct kbasep_js_device_data for + * improved d-cache/tlb efficiency. + */ + struct { + union kbasep_js_policy_ctx_info policy_ctx; /**< Policy-specific context */ + } runpool; + + /** + * Job Scheduler Context information sub-structure. These members are + * accessed regardless of whether the context is: + * - In the Policy's Run Pool + * - In the Policy's Queue + * - Not queued nor in the Run Pool. + * + * You must obtain the jsctx_mutex before accessing any other members of + * this substructure. + * + * You may not access any of these members from IRQ context. + */ + struct { + struct mutex jsctx_mutex; /**< Job Scheduler Context lock */ + + /** Number of jobs ready to run - does \em not include the jobs waiting in + * the dispatcher, and dependency-only jobs. See kbase_jd_context::job_nr + * for such jobs*/ + u32 nr_jobs; + + /** Context Attributes: + * Each is large enough to hold a refcount of the number of atoms on + * the context. **/ + u32 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT]; + + kbase_context_flags flags; + /* NOTE: Unify the following flags into kbase_context_flags */ + /** + * Is the context scheduled on the Run Pool? + * + * This is only ever updated whilst the jsctx_mutex is held. + */ + mali_bool is_scheduled; + /** + * Wait queue to wait for is_scheduled state changes. + * */ + wait_queue_head_t is_scheduled_wait; + + mali_bool is_dying; /**< Is the context in the process of being evicted? */ + } ctx; + + /* The initalized-flag is placed at the end, to avoid cache-pollution (we should + * only be using this during init/term paths) */ + int init_status; +}; + +/** Subset of atom state that can be available after jd_done_nolock() is called + * on that atom. A copy must be taken via kbasep_js_atom_retained_state_copy(), + * because the original atom could disappear. */ +struct kbasep_js_atom_retained_state { + /** Event code - to determine whether the atom has finished */ + enum base_jd_event_code event_code; + /** core requirements */ + base_jd_core_req core_req; + /** Job Slot to retry submitting to if submission from IRQ handler failed */ + int retry_submit_on_slot; + /* Core group atom was executed on */ + u32 device_nr; + +}; + +/** + * Value signifying 'no retry on a slot required' for: + * - kbase_js_atom_retained_state::retry_submit_on_slot + * - kbase_jd_atom::retry_submit_on_slot + */ +#define KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID (-1) + +/** + * base_jd_core_req value signifying 'invalid' for a kbase_jd_atom_retained_state. + * + * @see kbase_atom_retained_state_is_valid() + */ +#define KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID BASE_JD_REQ_DEP + +/** + * @brief The JS timer resolution, in microseconds + * + * Any non-zero difference in time will be at least this size. + */ +#define KBASEP_JS_TICK_RESOLUTION_US 1 + +#endif /* _KBASE_JS_DEFS_H_ */ + + /** @} *//* end group kbase_js */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy.h new file mode 100644 index 0000000000000000000000000000000000000000..6c777a92000dfaa396a4ea4340ac68231a0a8be1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy.h @@ -0,0 +1,767 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_policy.h + * Job Scheduler Policy APIs. + */ + +#ifndef _KBASE_JS_POLICY_H_ +#define _KBASE_JS_POLICY_H_ + +/** + * @page page_kbase_js_policy Job Scheduling Policies + * The Job Scheduling system is described in the following: + * - @subpage page_kbase_js_policy_overview + * - @subpage page_kbase_js_policy_operation + * + * The API details are as follows: + * - @ref kbase_jm + * - @ref kbase_js + * - @ref kbase_js_policy + */ + +/** + * @page page_kbase_js_policy_overview Overview of the Policy System + * + * The Job Scheduler Policy manages: + * - The assigning of KBase Contexts to GPU Address Spaces (\em ASs) + * - The choosing of Job Chains (\em Jobs) from a KBase context, to run on the + * GPU's Job Slots (\em JSs). + * - The amount of \em time a context is assigned to (scheduled on) an + * Address Space + * - The amount of \em time a Job spends running on the GPU + * + * The Policy implements this management via 2 components: + * - A Policy Queue, which manages a set of contexts that are ready to run, + * but not currently running. + * - A Policy Run Pool, which manages the currently running contexts (one per Address + * Space) and the jobs to run on the Job Slots. + * + * Each Graphics Process in the system has at least one KBase Context. Therefore, + * the Policy Queue can be seen as a queue of Processes waiting to run Jobs on + * the GPU. + * + * + * @dotfile policy_overview.dot "Diagram showing a very simplified overview of the Policy System. IRQ handling, soft/hard-stopping, contexts re-entering the system and Policy details are omitted" + * + * The main operations on the queue are: + * - Enqueuing a Context to it + * - Dequeuing a Context from it, to run it. + * - Note: requeuing a context is much the same as enqueuing a context, but + * occurs when a context is scheduled out of the system to allow other contexts + * to run. + * + * These operations have much the same meaning for the Run Pool - Jobs are + * dequeued to run on a Jobslot, and requeued when they are scheduled out of + * the GPU. + * + * @note This is an over-simplification of the Policy APIs - there are more + * operations than 'Enqueue'/'Dequeue', and a Dequeue from the Policy Queue + * takes at least two function calls: one to Dequeue from the Queue, one to add + * to the Run Pool. + * + * As indicated on the diagram, Jobs permanently leave the scheduling system + * when they are completed, otherwise they get dequeued/requeued until this + * happens. Similarly, Contexts leave the scheduling system when their jobs + * have all completed. However, Contexts may later return to the scheduling + * system (not shown on the diagram) if more Bags of Jobs are submitted to + * them. + */ + +/** + * @page page_kbase_js_policy_operation Policy Operation + * + * We describe the actions that the Job Scheduler Core takes on the Policy in + * the following cases: + * - The IRQ Path + * - The Job Submission Path + * - The High Priority Job Submission Path + * + * This shows how the Policy APIs will be used by the Job Scheduler core. + * + * The following diagram shows an example Policy that contains a Low Priority + * queue, and a Real-time (High Priority) Queue. The RT queue is examined + * before the LowP one on dequeuing from the head. The Low Priority Queue is + * ordered by time, and the RT queue is ordered by RT-priority, and then by + * time. In addition, it shows that the Job Scheduler Core will start a + * Soft-Stop Timer (SS-Timer) when it dequeue's and submits a job. The + * Soft-Stop time is set by a global configuration value, and must be a value + * appropriate for the policy. For example, this could include "don't run a + * soft-stop timer" for a First-Come-First-Served (FCFS) policy. + * + * + * @dotfile policy_operation_diagram.dot "Diagram showing the objects managed by an Example Policy, and the operations made upon these objects by the Job Scheduler Core." + * + * @section sec_kbase_js_policy_operation_prio Dealing with Priority + * + * Priority applies both to a context as a whole, and to the jobs within a + * context. The jobs specify a priority in the base_jd_atom::prio member, which + * is relative to that of the context. A positive setting indicates a reduction + * in priority, whereas a negative setting indicates a boost in priority. Of + * course, the boost in priority should only be honoured when the originating + * process has sufficient priviledges, and should be ignored for unpriviledged + * processes. The meaning of the combined priority value is up to the policy + * itself, and could be a logarithmic scale instead of a linear scale (e.g. the + * policy could implement an increase/decrease in priority by 1 results in an + * increase/decrease in \em proportion of time spent scheduled in by 25%, an + * effective change in timeslice by 11%). + * + * It is up to the policy whether a boost in priority boosts the priority of + * the entire context (e.g. to such an extent where it may pre-empt other + * running contexts). If it chooses to do this, the Policy must make sure that + * only the high-priority jobs are run, and that the context is scheduled out + * once only low priority jobs remain. This ensures that the low priority jobs + * within the context do not gain from the priority boost, yet they still get + * scheduled correctly with respect to other low priority contexts. + * + * + * @section sec_kbase_js_policy_operation_irq IRQ Path + * + * The following happens on the IRQ path from the Job Scheduler Core: + * - Note the slot that completed (for later) + * - Log the time spent by the job (and implicitly, the time spent by the + * context) + * - call kbasep_js_policy_log_job_result() in the context of the irq + * handler. + * - This must happen regardless of whether the job completed successfully or + * not (otherwise the context gets away with DoS'ing the system with faulty jobs) + * - What was the result of the job? + * - If Completed: job is just removed from the system + * - If Hard-stop or failure: job is removed from the system + * - If Soft-stop: queue the book-keeping work onto a work-queue: have a + * work-queue call kbasep_js_policy_enqueue_job() + * - Check the timeslice used by the owning context + * - call kbasep_js_policy_should_remove_ctx() in the context of the irq + * handler. + * - If this returns true, clear the "allowed" flag. + * - Check the ctx's flags for "allowed", "has jobs to run" and "is running + * jobs" + * - And so, should the context stay scheduled in? + * - If No, push onto a work-queue the work of scheduling out the old context, + * and getting a new one. That is: + * - kbasep_js_policy_runpool_remove_ctx() on old_ctx + * - kbasep_js_policy_enqueue_ctx() on old_ctx + * - kbasep_js_policy_dequeue_head_ctx() to get new_ctx + * - kbasep_js_policy_runpool_add_ctx() on new_ctx + * - (all of this work is deferred on a work-queue to keep the IRQ handler quick) + * - If there is space in the completed job slots' HEAD/NEXT registers, run the next job: + * - kbasep_js_policy_dequeue_job() in the context of the irq + * handler with core_req set to that of the completing slot + * - if this returned MALI_TRUE, submit the job to the completed slot. + * - This is repeated until kbasep_js_policy_dequeue_job() returns + * MALI_FALSE, or the job slot has a job queued on both the HEAD and NEXT registers. + * - If kbasep_js_policy_dequeue_job() returned false, submit some work to + * the work-queue to retry from outside of IRQ context (calling + * kbasep_js_policy_dequeue_job() from a work-queue). + * + * Since the IRQ handler submits new jobs \em and re-checks the IRQ_RAWSTAT, + * this sequence could loop a large number of times: this could happen if + * the jobs submitted completed on the GPU very quickly (in a few cycles), such + * as GPU NULL jobs. Then, the HEAD/NEXT registers will always be free to take + * more jobs, causing us to loop until we run out of jobs. + * + * To mitigate this, we must limit the number of jobs submitted per slot during + * the IRQ handler - for example, no more than 2 jobs per slot per IRQ should + * be sufficient (to fill up the HEAD + NEXT registers in normal cases). For + * Mali-T600 with 3 job slots, this means that up to 6 jobs could be submitted per + * slot. Note that IRQ Throttling can make this situation commonplace: 6 jobs + * could complete but the IRQ for each of them is delayed by the throttling. By + * the time you get the IRQ, all 6 jobs could've completed, meaning you can + * submit jobs to fill all 6 HEAD+NEXT registers again. + * + * @note As much work is deferred as possible, which includes the scheduling + * out of a context and scheduling in a new context. However, we can still make + * starting a single high-priorty context quick despite this: + * - On Mali-T600 family, there is one more AS than JSs. + * - This means we can very quickly schedule out one AS, no matter what the + * situation (because there will always be one AS that's not currently running + * on the job slot - it can only have a job in the NEXT register). + * - Even with this scheduling out, fair-share can still be guaranteed e.g. by + * a timeline-based Completely Fair Scheduler. + * - When our high-priority context comes in, we can do this quick-scheduling + * out immediately, and then schedule in the high-priority context without having to block. + * - This all assumes that the context to schedule out is of lower + * priority. Otherwise, we will have to block waiting for some other low + * priority context to finish its jobs. Note that it's likely (but not + * impossible) that the high-priority context \b is running jobs, by virtue of + * it being high priority. + * - Therefore, we can give a high liklihood that on Mali-T600 at least one + * high-priority context can be started very quickly. For the general case, we + * can guarantee starting (no. ASs) - (no. JSs) high priority contexts + * quickly. In any case, there is a high likelihood that we're able to start + * more than one high priority context quickly. + * + * In terms of the functions used in the IRQ handler directly, these are the + * perfomance considerations: + * - kbase_js_policy_log_job_result(): + * - This is just adding to a 64-bit value (possibly even a 32-bit value if we + * only store the time the job's recently spent - see below on 'priority weighting') + * - For priority weighting, a divide operation ('div') could happen, but + * this can happen in a deferred context (outside of IRQ) when scheduling out + * the ctx; as per our Engineering Specification, the contexts of different + * priority still stay scheduled in for the same timeslice, but higher priority + * ones scheduled back in more often. + * - That is, the weighted and unweighted times must be stored separately, and + * the weighted time is only updated \em outside of IRQ context. + * - Of course, this divide is more likely to be a 'multiply by inverse of the + * weight', assuming that the weight (priority) doesn't change. + * - kbasep_js_policy_should_remove_ctx(): + * - This is usually just a comparison of the stored time value against some + * maximum value. + * + * @note all deferred work can be wrapped up into one call - we usually need to + * indicate that a job/bag is done outside of IRQ context anyway. + * + * + * + * @section sec_kbase_js_policy_operation_submit Submission path + * + * Start with a Context with no jobs present, and assume equal priority of all + * contexts in the system. The following work all happens outside of IRQ + * Context : + * - As soon as job is made 'ready to 'run', then is must be registerd with the Job + * Scheduler Policy: + * - 'Ready to run' means they've satisified their dependencies in the + * Kernel-side Job Dispatch system. + * - Call kbasep_js_policy_enqueue_job() + * - This indicates that the job should be scheduled (it is ready to run). + * - As soon as a ctx changes from having 0 jobs 'ready to run' to >0 jobs + * 'ready to run', we enqueue the context on the policy queue: + * - Call kbasep_js_policy_enqueue_ctx() + * - This indicates that the \em ctx should be scheduled (it is ready to run) + * + * Next, we need to handle adding a context to the Run Pool - if it's sensible + * to do so. This can happen due to two reasons: + * -# A context is enqueued as above, and there are ASs free for it to run on + * (e.g. it is the first context to be run, in which case it can be added to + * the Run Pool immediately after enqueuing on the Policy Queue) + * -# A previous IRQ caused another ctx to be scheduled out, requiring that the + * context at the head of the queue be scheduled in. Such steps would happen in + * a work queue (work deferred from the IRQ context). + * + * In both cases, we'd handle it as follows: + * - Get the context at the Head of the Policy Queue: + * - Call kbasep_js_policy_dequeue_head_ctx() + * - Assign the Context an Address Space (Assert that there will be one free, + * given the above two reasons) + * - Add this context to the Run Pool: + * - Call kbasep_js_policy_runpool_add_ctx() + * - Now see if a job should be run: + * - Mostly, this will be done in the IRQ handler at the completion of a + * previous job. + * - However, there are two cases where this cannot be done: a) The first job + * enqueued to the system (there is no previous IRQ to act upon) b) When jobs + * are submitted at a low enough rate to not fill up all Job Slots (or, not to + * fill both the 'HEAD' and 'NEXT' registers in the job-slots) + * - Hence, on each ctx and job submission we should try to see if we + * can run a job: + * - For each job slot that has free space (in NEXT or HEAD+NEXT registers): + * - Call kbasep_js_policy_dequeue_job() with core_req set to that of the + * slot + * - if we got one, submit it to the job slot. + * - This is repeated until kbasep_js_policy_dequeue_job() returns + * MALI_FALSE, or the job slot has a job queued on both the HEAD and NEXT registers. + * + * The above case shows that we should attempt to run jobs in cases where a) a ctx + * has been added to the Run Pool, and b) new jobs have been added to a context + * in the Run Pool: + * - In the latter case, the context is in the runpool because it's got a job + * ready to run, or is already running a job + * - We could just wait until the IRQ handler fires, but for certain types of + * jobs this can take comparatively a long time to complete, e.g. GLES FS jobs + * generally take much longer to run that GLES CS jobs, which are vertex shader + * jobs. + * - Therefore, when a new job appears in the ctx, we must check the job-slots + * to see if they're free, and run the jobs as before. + * + * + * + * @section sec_kbase_js_policy_operation_submit_hipri Submission path for High Priority Contexts + * + * For High Priority Contexts on Mali-T600, we can make sure that at least 1 of + * them can be scheduled in immediately to start high prioriy jobs. In general, + * (no. ASs) - (no JSs) high priority contexts may be started immediately. The + * following describes how this happens: + * + * Similar to the previous section, consider what happens with a high-priority + * context (a context with a priority higher than that of any in the Run Pool) + * that starts out with no jobs: + * - A job becomes ready to run on the context, and so we enqueue the context + * on the Policy's Queue. + * - However, we'd like to schedule in this context immediately, instead of + * waiting for one of the Run Pool contexts' timeslice to expire + * - The policy's Enqueue function must detect this (because it is the policy + * that embodies the concept of priority), and take appropriate action + * - That is, kbasep_js_policy_enqueue_ctx() should check the Policy's Run + * Pool to see if a lower priority context should be scheduled out, and then + * schedule in the High Priority context. + * - For Mali-T600, we can always pick a context to schedule out immediately + * (because there are more ASs than JSs), and so scheduling out a victim context + * and scheduling in the high priority context can happen immediately. + * - If a policy implements fair-sharing, then this can still ensure the + * victim later on gets a fair share of the GPU. + * - As a note, consider whether the victim can be of equal/higher priority + * than the incoming context: + * - Usually, higher priority contexts will be the ones currently running + * jobs, and so the context with the lowest priority is usually not running + * jobs. + * - This makes it likely that the victim context is low priority, but + * it's not impossible for it to be a high priority one: + * - Suppose 3 high priority contexts are submitting only FS jobs, and one low + * priority context submitting CS jobs. Then, the context not running jobs will + * be one of the hi priority contexts (because only 2 FS jobs can be + * queued/running on the GPU HW for Mali-T600). + * - The problem can be mitigated by extra action, but it's questionable + * whether we need to: we already have a high likelihood that there's at least + * one high priority context - that should be good enough. + * - And so, this method makes sure that at least one high priority context + * can be started very quickly, but more than one high priority contexts could be + * delayed (up to one timeslice). + * - To improve this, use a GPU with a higher number of Address Spaces vs Job + * Slots. + * - At this point, let's assume this high priority context has been scheduled + * in immediately. The next step is to ensure it can start some jobs quickly. + * - It must do this by Soft-Stopping jobs on any of the Job Slots that it can + * submit to. + * - The rest of the logic for starting the jobs is taken care of by the IRQ + * handler. All the policy needs to do is ensure that + * kbasep_js_policy_dequeue_job() will return the jobs from the high priority + * context. + * + * @note in SS state, we currently only use 2 job-slots (even for T608, but + * this might change in future). In this case, it's always possible to schedule + * out 2 ASs quickly (their jobs won't be in the HEAD registers). At the same + * time, this maximizes usage of the job-slots (only 2 are in use), because you + * can guarantee starting of the jobs from the High Priority contexts immediately too. + * + * + * + * @section sec_kbase_js_policy_operation_notes Notes + * + * - In this design, a separate 'init' is needed from dequeue/requeue, so that + * information can be retained between the dequeue/requeue calls. For example, + * the total time spent for a context/job could be logged between + * dequeue/requeuing, to implement Fair Sharing. In this case, 'init' just + * initializes that information to some known state. + * + * + * + */ + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup kbase_js_policy Job Scheduler Policy APIs + * @{ + * + * Refer to @ref page_kbase_js_policy for an overview and detailed operation of + * the Job Scheduler Policy and its use from the Job Scheduler Core. + */ + +/** + * @brief Job Scheduler Policy structure + */ +union kbasep_js_policy; + +/** + * @brief Initialize the Job Scheduler Policy + */ +mali_error kbasep_js_policy_init(struct kbase_device *kbdev); + +/** + * @brief Terminate the Job Scheduler Policy + */ +void kbasep_js_policy_term(union kbasep_js_policy *js_policy); + +/** + * @addtogroup kbase_js_policy_ctx Job Scheduler Policy, Context Management API + * @{ + * + * Refer to @ref page_kbase_js_policy for an overview and detailed operation of + * the Job Scheduler Policy and its use from the Job Scheduler Core. + */ + +/** + * @brief Job Scheduler Policy Ctx Info structure + * + * This structure is embedded in the struct kbase_context structure. It is used to: + * - track information needed for the policy to schedule the context (e.g. time + * used, OS priority etc.) + * - link together kbase_contexts into a queue, so that a struct kbase_context can be + * obtained as the container of the policy ctx info. This allows the API to + * return what "the next context" should be. + * - obtain other information already stored in the struct kbase_context for + * scheduling purposes (e.g process ID to get the priority of the originating + * process) + */ +union kbasep_js_policy_ctx_info; + +/** + * @brief Initialize a ctx for use with the Job Scheduler Policy + * + * This effectively initializes the union kbasep_js_policy_ctx_info structure within + * the struct kbase_context (itself located within the kctx->jctx.sched_info structure). + */ +mali_error kbasep_js_policy_init_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); + +/** + * @brief Terminate resources associated with using a ctx in the Job Scheduler + * Policy. + */ +void kbasep_js_policy_term_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Enqueue a context onto the Job Scheduler Policy Queue + * + * If the context enqueued has a priority higher than any in the Run Pool, then + * it is the Policy's responsibility to decide whether to schedule out a low + * priority context from the Run Pool to allow the high priority context to be + * scheduled in. + * + * If the context has the privileged flag set, it will always be kept at the + * head of the queue. + * + * The caller will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + * The caller will be holding kbasep_js_device_data::queue_mutex. + */ +void kbasep_js_policy_enqueue_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Dequeue a context from the Head of the Job Scheduler Policy Queue + * + * The caller will be holding kbasep_js_device_data::queue_mutex. + * + * @return MALI_TRUE if a context was available, and *kctx_ptr points to + * the kctx dequeued. + * @return MALI_FALSE if no contexts were available. + */ +mali_bool kbasep_js_policy_dequeue_head_ctx(union kbasep_js_policy *js_policy, struct kbase_context ** const kctx_ptr); + +/** + * @brief Evict a context from the Job Scheduler Policy Queue + * + * This is only called as part of destroying a kbase_context. + * + * There are many reasons why this might fail during the lifetime of a + * context. For example, the context is in the process of being scheduled. In + * that case a thread doing the scheduling might have a pointer to it, but the + * context is neither in the Policy Queue, nor is it in the Run + * Pool. Crucially, neither the Policy Queue, Run Pool, or the Context itself + * are locked. + * + * Hence to find out where in the system the context is, it is important to do + * more than just check the kbasep_js_kctx_info::ctx::is_scheduled member. + * + * The caller will be holding kbasep_js_device_data::queue_mutex. + * + * @return MALI_TRUE if the context was evicted from the Policy Queue + * @return MALI_FALSE if the context was not found in the Policy Queue + */ +mali_bool kbasep_js_policy_try_evict_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Call a function on all jobs belonging to a non-queued, non-running + * context, optionally detaching the jobs from the context as it goes. + * + * At the time of the call, the context is guarenteed to be not-currently + * scheduled on the Run Pool (is_scheduled == MALI_FALSE), and not present in + * the Policy Queue. This is because one of the following functions was used + * recently on the context: + * - kbasep_js_policy_evict_ctx() + * - kbasep_js_policy_runpool_remove_ctx() + * + * In both cases, no subsequent call was made on the context to any of: + * - kbasep_js_policy_runpool_add_ctx() + * - kbasep_js_policy_enqueue_ctx() + * + * Due to the locks that might be held at the time of the call, the callback + * may need to defer work on a workqueue to complete its actions (e.g. when + * cancelling jobs) + * + * \a detach_jobs must only be set when cancelling jobs (which occurs as part + * of context destruction). + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + */ +void kbasep_js_policy_foreach_ctx_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, + kbasep_js_policy_ctx_job_cb callback, mali_bool detach_jobs); + +/** + * @brief Add a context to the Job Scheduler Policy's Run Pool + * + * If the context enqueued has a priority higher than any in the Run Pool, then + * it is the Policy's responsibility to decide whether to schedule out low + * priority jobs that are currently running on the GPU. + * + * The number of contexts present in the Run Pool will never be more than the + * number of Address Spaces. + * + * The following guarentees are made about the state of the system when this + * is called: + * - kctx->as_nr member is valid + * - the context has its submit_allowed flag set + * - kbasep_js_device_data::runpool_irq::per_as_data[kctx->as_nr] is valid + * - The refcount of the context is guarenteed to be zero. + * - kbasep_js_kctx_info::ctx::is_scheduled will be MALI_TRUE. + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it will be holding kbasep_js_device_data::runpool_mutex. + * - it will be holding kbasep_js_device_data::runpool_irq::lock (a spinlock) + * + * Due to a spinlock being held, this function must not call any APIs that sleep. + */ +void kbasep_js_policy_runpool_add_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Remove a context from the Job Scheduler Policy's Run Pool + * + * The kctx->as_nr member is valid and the context has its submit_allowed flag + * set when this is called. The state of + * kbasep_js_device_data::runpool_irq::per_as_data[kctx->as_nr] is also + * valid. The refcount of the context is guarenteed to be zero. + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it will be holding kbasep_js_device_data::runpool_mutex. + * - it will be holding kbasep_js_device_data::runpool_irq::lock (a spinlock) + * + * Due to a spinlock being held, this function must not call any APIs that sleep. + */ +void kbasep_js_policy_runpool_remove_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Indicate whether a context should be removed from the Run Pool + * (should be scheduled out). + * + * The kbasep_js_device_data::runpool_irq::lock will be held by the caller. + * + * @note This API is called from IRQ context. + */ +mali_bool kbasep_js_policy_should_remove_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx); + +/** + * @brief Synchronize with any timers acting upon the runpool + * + * The policy should check whether any timers it owns should be running. If + * they should not, the policy must cancel such timers and ensure they are not + * re-run by the time this function finishes. + * + * In particular, the timers must not be running when there are no more contexts + * on the runpool, because the GPU could be powered off soon after this call. + * + * The locking conditions on the caller are as follows: + * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. + * - it will be holding kbasep_js_device_data::runpool_mutex. + */ +void kbasep_js_policy_runpool_timers_sync(union kbasep_js_policy *js_policy); + + +/** + * @brief Indicate whether a new context has an higher priority than the current context. + * + * + * The caller has the following conditions on locking: + * - kbasep_js_kctx_info::ctx::jsctx_mutex will be held for \a new_ctx + * + * This function must not sleep, because an IRQ spinlock might be held whilst + * this is called. + * + * @note There is nothing to stop the priority of \a current_ctx changing + * during or immediately after this function is called (because its jsctx_mutex + * cannot be held). Therefore, this function should only be seen as a heuristic + * guide as to whether \a new_ctx is higher priority than \a current_ctx + */ +mali_bool kbasep_js_policy_ctx_has_priority(union kbasep_js_policy *js_policy, struct kbase_context *current_ctx, struct kbase_context *new_ctx); + + /** @} *//* end group kbase_js_policy_ctx */ + +/** + * @addtogroup kbase_js_policy_job Job Scheduler Policy, Job Chain Management API + * @{ + * + * Refer to @ref page_kbase_js_policy for an overview and detailed operation of + * the Job Scheduler Policy and its use from the Job Scheduler Core. + */ + +/** + * @brief Job Scheduler Policy Job Info structure + * + * This structure is embedded in the struct kbase_jd_atom structure. It is used to: + * - track information needed for the policy to schedule the job (e.g. time + * used, OS priority etc.) + * - link together jobs into a queue/buffer, so that a struct kbase_jd_atom can be + * obtained as the container of the policy job info. This allows the API to + * return what "the next job" should be. + * - obtain other information already stored in the struct kbase_context for + * scheduling purposes (e.g user-side relative priority) + */ +union kbasep_js_policy_job_info; + +/** + * @brief Initialize a job for use with the Job Scheduler Policy + * + * This function initializes the union kbasep_js_policy_job_info structure within the + * kbase_jd_atom. It will only initialize/allocate resources that are specific + * to the job. + * + * That is, this function makes \b no attempt to: + * - initialize any context/policy-wide information + * - enqueue the job on the policy. + * + * At some later point, the following functions must be called on the job, in this order: + * - kbasep_js_policy_register_job() to register the job and initialize policy/context wide data. + * - kbasep_js_policy_enqueue_job() to enqueue the job + * + * A job must only ever be initialized on the Policy once, and must be + * terminated on the Policy before the job is freed. + * + * The caller will not be holding any locks, and so this function will not + * modify any information in \a kctx or \a js_policy. + * + * @return MALI_ERROR_NONE if initialization was correct. + */ +mali_error kbasep_js_policy_init_job(const union kbasep_js_policy *js_policy, const struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief Register context/policy-wide information for a job on the Job Scheduler Policy. + * + * Registers the job with the policy. This is used to track the job before it + * has been enqueued/requeued by kbasep_js_policy_enqueue_job(). Specifically, + * it is used to update information under a lock that could not be updated at + * kbasep_js_policy_init_job() time (such as context/policy-wide data). + * + * @note This function will not fail, and hence does not allocate any + * resources. Any failures that could occur on registration will be caught + * during kbasep_js_policy_init_job() instead. + * + * A job must only ever be registerd on the Policy once, and must be + * deregistered on the Policy on completion (whether or not that completion was + * success/failure). + * + * The caller has the following conditions on locking: + * - kbasep_js_kctx_info::ctx::jsctx_mutex will be held. + */ +void kbasep_js_policy_register_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief De-register context/policy-wide information for a on the Job Scheduler Policy. + * + * This must be used before terminating the resources associated with using a + * job in the Job Scheduler Policy. This function does not itself terminate any + * resources, at most it just updates information in the policy and context. + * + * The caller has the following conditions on locking: + * - kbasep_js_kctx_info::ctx::jsctx_mutex will be held. + */ +void kbasep_js_policy_deregister_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** + * @brief Dequeue a Job for a job slot from the Job Scheduler Policy Run Pool + * + * The job returned by the policy will match at least one of the bits in the + * job slot's core requirements (but it may match more than one, or all @ref + * base_jd_core_req bits supported by the job slot). + * + * In addition, the requirements of the job returned will be a subset of those + * requested - the job returned will not have requirements that \a job_slot_idx + * cannot satisfy. + * + * The caller will submit the job to the GPU as soon as the GPU's NEXT register + * for the corresponding slot is empty. Of course, the GPU will then only run + * this new job when the currently executing job (in the jobslot's HEAD + * register) has completed. + * + * @return MALI_TRUE if a job was available, and *kctx_ptr points to + * the kctx dequeued. + * @return MALI_FALSE if no jobs were available among all ctxs in the Run Pool. + * + * @note base_jd_core_req is currently a u8 - beware of type conversion. + * + * The caller has the following conditions on locking: + * - kbasep_js_device_data::runpool_lock::irq will be held. + * - kbasep_js_device_data::runpool_mutex will be held. + * - kbasep_js_kctx_info::ctx::jsctx_mutex. will be held + */ +mali_bool kbasep_js_policy_dequeue_job(struct kbase_device *kbdev, int job_slot_idx, struct kbase_jd_atom ** const katom_ptr); + +/** + * @brief Requeue a Job back into the the Job Scheduler Policy Run Pool + * + * This will be used to enqueue a job after its creation and also to requeue + * a job into the Run Pool that was previously dequeued (running). It notifies + * the policy that the job should be run again at some point later. + * + * The caller has the following conditions on locking: + * - kbasep_js_device_data::runpool_irq::lock (a spinlock) will be held. + * - kbasep_js_device_data::runpool_mutex will be held. + * - kbasep_js_kctx_info::ctx::jsctx_mutex will be held. + */ +void kbasep_js_policy_enqueue_job(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom); + +/** + * @brief Log the result of a job: the time spent on a job/context, and whether + * the job failed or not. + * + * Since a struct kbase_jd_atom contains a pointer to the struct kbase_context owning it, + * then this can also be used to log time on either/both the job and the + * containing context. + * + * The completion state of the job can be found by examining \a katom->event.event_code + * + * If the Job failed and the policy is implementing fair-sharing, then the + * policy must penalize the failing job/context: + * - At the very least, it should penalize the time taken by the amount of + * time spent processing the IRQ in SW. This because a job in the NEXT slot + * waiting to run will be delayed until the failing job has had the IRQ + * cleared. + * - \b Optionally, the policy could apply other penalties. For example, based + * on a threshold of a number of failing jobs, after which a large penalty is + * applied. + * + * The kbasep_js_device_data::runpool_mutex will be held by the caller. + * + * @note This API is called from IRQ context. + * + * The caller has the following conditions on locking: + * - kbasep_js_device_data::runpool_irq::lock will be held. + * + * @param js_policy job scheduler policy + * @param katom job dispatch atom + * @param time_spent_us the time spent by the job, in microseconds (10^-6 seconds). + */ +void kbasep_js_policy_log_job_result(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom, u64 time_spent_us); + + /** @} *//* end group kbase_js_policy_job */ + + /** @} *//* end group kbase_js_policy */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif /* _KBASE_JS_POLICY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.c new file mode 100644 index 0000000000000000000000000000000000000000..78ec5f1fb5519ad543250a7817345760b11c23f3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.c @@ -0,0 +1,1482 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* + * Job Scheduler: Completely Fair Policy Implementation + */ + +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) +#include +#endif + +/** + * Define for when dumping is enabled. + * This should not be based on the instrumentation level as whether dumping is enabled for a particular level is down to the integrator. + * However this is being used for now as otherwise the cinstr headers would be needed. + */ +#define CINSTR_DUMPING_ENABLED (2 == MALI_INSTRUMENTATION_LEVEL) + +/** Fixed point constants used for runtime weight calculations */ +#define WEIGHT_FIXEDPOINT_SHIFT 10 +#define WEIGHT_TABLE_SIZE 40 +#define WEIGHT_0_NICE (WEIGHT_TABLE_SIZE/2) +#define WEIGHT_0_VAL (1 << WEIGHT_FIXEDPOINT_SHIFT) + +#define LOOKUP_VARIANT_MASK ((1u<process_priority + ctx_info->bag_priority; + + /* Adjust runtime_us using priority weight if required */ + if (priority != 0 && time_us != 0) { + int clamped_priority; + + /* Clamp values to min..max weights */ + if (priority > PROCESS_PRIORITY_MAX) + clamped_priority = PROCESS_PRIORITY_MAX; + else if (priority < PROCESS_PRIORITY_MIN) + clamped_priority = PROCESS_PRIORITY_MIN; + else + clamped_priority = priority; + + /* Fixed point multiplication */ + time_delta_us = (time_us * weight_of_priority[WEIGHT_0_NICE + clamped_priority]); + /* Remove fraction */ + time_delta_us = time_delta_us >> WEIGHT_FIXEDPOINT_SHIFT; + /* Make sure the time always increases */ + if (0 == time_delta_us) + time_delta_us++; + } else { + time_delta_us = time_us; + } + + return time_delta_us; +} + +#if KBASE_TRACE_ENABLE +STATIC int kbasep_js_policy_trace_get_refcnt_nolock(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + int as_nr; + int refcnt = 0; + + js_devdata = &kbdev->js_data; + + as_nr = kctx->as_nr; + if (as_nr != KBASEP_AS_NR_INVALID) { + struct kbasep_js_per_as_data *js_per_as_data; + js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr]; + + refcnt = js_per_as_data->as_busy_refcount; + } + + return refcnt; +} + +STATIC INLINE int kbasep_js_policy_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + unsigned long flags; + struct kbasep_js_device_data *js_devdata; + int refcnt = 0; + + js_devdata = &kbdev->js_data; + + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + refcnt = kbasep_js_policy_trace_get_refcnt_nolock(kbdev, kctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return refcnt; +} +#else /* KBASE_TRACE_ENABLE */ +STATIC int kbasep_js_policy_trace_get_refcnt_nolock(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(kctx); + return 0; +} + +STATIC INLINE int kbasep_js_policy_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(kctx); + return 0; +} +#endif /* KBASE_TRACE_ENABLE */ + +#ifdef CONFIG_MALI_DEBUG +STATIC void kbasep_js_debug_check(struct kbasep_js_policy_cfs *policy_info, struct kbase_context *kctx, kbasep_js_check check_flag) +{ + /* This function uses the ternary operator and non-explicit comparisons, + * because it makes for much shorter, easier to read code */ + + if (check_flag & KBASEP_JS_CHECKFLAG_QUEUED) { + mali_bool is_queued; + mali_bool expect_queued; + + is_queued = (kbasep_list_member_of( + &policy_info->ctx_queue_head, + &kctx->jctx.sched_info.runpool.policy_ctx.cfs.list)) ? + MALI_TRUE : MALI_FALSE; + + if (!is_queued) + is_queued = (kbasep_list_member_of(&policy_info->ctx_rt_queue_head, &kctx->jctx.sched_info.runpool.policy_ctx.cfs.list)) ? MALI_TRUE : MALI_FALSE; + + expect_queued = (check_flag & KBASEP_JS_CHECKFLAG_IS_QUEUED) ? MALI_TRUE : MALI_FALSE; + + KBASE_DEBUG_ASSERT_MSG(expect_queued == is_queued, "Expected context %p to be %s but it was %s\n", kctx, (expect_queued) ? "queued" : "not queued", (is_queued) ? "queued" : "not queued"); + + } + + if (check_flag & KBASEP_JS_CHECKFLAG_SCHEDULED) { + mali_bool is_scheduled; + mali_bool expect_scheduled; + + is_scheduled = (kbasep_list_member_of( + &policy_info->scheduled_ctxs_head, + &kctx->jctx.sched_info.runpool.policy_ctx.cfs.list)) ? + MALI_TRUE : MALI_FALSE; + + expect_scheduled = (check_flag & KBASEP_JS_CHECKFLAG_IS_SCHEDULED) ? MALI_TRUE : MALI_FALSE; + KBASE_DEBUG_ASSERT_MSG(expect_scheduled == is_scheduled, "Expected context %p to be %s but it was %s\n", kctx, (expect_scheduled) ? "scheduled" : "not scheduled", (is_scheduled) ? "scheduled" : "not scheduled"); + } + +} +#else /* CONFIG_MALI_DEBUG */ +STATIC void kbasep_js_debug_check(struct kbasep_js_policy_cfs *policy_info, struct kbase_context *kctx, kbasep_js_check check_flag) +{ + CSTD_UNUSED(policy_info); + CSTD_UNUSED(kctx); + CSTD_UNUSED(check_flag); +} +#endif /* CONFIG_MALI_DEBUG */ + +STATIC INLINE void set_slot_to_variant_lookup(u32 *bit_array, u32 slot_idx, u32 variants_supported) +{ + u32 overall_bit_idx = slot_idx * KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS; + u32 word_idx = overall_bit_idx / 32; + u32 bit_idx = overall_bit_idx % 32; + + KBASE_DEBUG_ASSERT(slot_idx < BASE_JM_MAX_NR_SLOTS); + KBASE_DEBUG_ASSERT((variants_supported & ~LOOKUP_VARIANT_MASK) == 0); + + bit_array[word_idx] |= variants_supported << bit_idx; +} + +STATIC INLINE u32 get_slot_to_variant_lookup(u32 *bit_array, u32 slot_idx) +{ + u32 overall_bit_idx = slot_idx * KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS; + u32 word_idx = overall_bit_idx / 32; + u32 bit_idx = overall_bit_idx % 32; + + u32 res; + + KBASE_DEBUG_ASSERT(slot_idx < BASE_JM_MAX_NR_SLOTS); + + res = bit_array[word_idx] >> bit_idx; + res &= LOOKUP_VARIANT_MASK; + + return res; +} + +/* Check the core_req_variants: make sure that every job slot is satisifed by + * one of the variants. This checks that cached_variant_idx_init will produce a + * valid result for jobs that make maximum use of the job slots. + * + * @note The checks are limited to the job slots - this does not check that + * every context requirement is covered (because some are intentionally not + * supported, such as KBASE_CTX_FLAG_SUBMIT_DISABLED) */ +#ifdef CONFIG_MALI_DEBUG +STATIC void debug_check_core_req_variants(struct kbase_device *kbdev, struct kbasep_js_policy_cfs *policy_info) +{ + struct kbasep_js_device_data *js_devdata; + u32 i; + int j; + + js_devdata = &kbdev->js_data; + + for (j = 0; j < kbdev->gpu_props.num_job_slots; ++j) { + base_jd_core_req job_core_req; + mali_bool found = MALI_FALSE; + + job_core_req = js_devdata->js_reqs[j]; + for (i = 0; i < policy_info->num_core_req_variants; ++i) { + base_jd_core_req var_core_req; + + var_core_req = policy_info->core_req_variants[i].core_req; + + if ((var_core_req & job_core_req) == job_core_req) { + found = MALI_TRUE; + break; + } + } + + /* Early-out on any failure */ + KBASE_DEBUG_ASSERT_MSG(found != MALI_FALSE, "Job slot %d features 0x%x not matched by core_req_variants. " "Rework core_req_variants and vairants_supported_<...>_state[] to match\n", j, job_core_req); + } +} +#endif + +STATIC void build_core_req_variants(struct kbase_device *kbdev, struct kbasep_js_policy_cfs *policy_info) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(policy_info != NULL); + CSTD_UNUSED(kbdev); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) { + KBASE_DEBUG_ASSERT(NUM_CORE_REQ_VARIANTS_8987 <= KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS); + + /* Assume a static set of variants */ + memcpy(policy_info->core_req_variants, core_req_variants_8987, sizeof(core_req_variants_8987)); + + policy_info->num_core_req_variants = NUM_CORE_REQ_VARIANTS_8987; + } else { + KBASE_DEBUG_ASSERT(NUM_CORE_REQ_VARIANTS <= KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS); + + /* Assume a static set of variants */ + memcpy(policy_info->core_req_variants, core_req_variants, sizeof(core_req_variants)); + + policy_info->num_core_req_variants = NUM_CORE_REQ_VARIANTS; + } + + KBASE_DEBUG_CODE(debug_check_core_req_variants(kbdev, policy_info)); +} + +STATIC void build_slot_lookups(struct kbase_device *kbdev, struct kbasep_js_policy_cfs *policy_info) +{ + u8 i; + const u32 *variants_supported_ss_for_this_hw = variants_supported_ss_state; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(policy_info != NULL); + + KBASE_DEBUG_ASSERT(kbdev->gpu_props.num_job_slots <= NELEMS(variants_supported_ss_state)); + KBASE_DEBUG_ASSERT(kbdev->gpu_props.num_job_slots <= NELEMS(variants_supported_ss_allcore_state)); + KBASE_DEBUG_ASSERT(kbdev->gpu_props.num_job_slots <= NELEMS(variants_supported_ss_state_8987)); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) + variants_supported_ss_for_this_hw = variants_supported_ss_state_8987; + + /* Given the static set of variants, provide a static set of lookups */ + for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) { + set_slot_to_variant_lookup(policy_info->slot_to_variant_lookup_ss_state, i, variants_supported_ss_for_this_hw[i]); + + set_slot_to_variant_lookup(policy_info->slot_to_variant_lookup_ss_allcore_state, i, variants_supported_ss_allcore_state[i]); + } + +} + +STATIC mali_error cached_variant_idx_init(const struct kbasep_js_policy_cfs *policy_info, const struct kbase_context *kctx, struct kbase_jd_atom *atom) +{ + struct kbasep_js_policy_cfs_job *job_info; + u32 i; + base_jd_core_req job_core_req; + u32 job_device_nr; + kbase_context_flags ctx_flags; + const struct kbasep_js_kctx_info *js_kctx_info; + const struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(policy_info != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(atom != NULL); + + kbdev = container_of(policy_info, const struct kbase_device, js_data.policy.cfs); + job_info = &atom->sched_info.cfs; + job_core_req = atom->core_req; + job_device_nr = atom->device_nr; + js_kctx_info = &kctx->jctx.sched_info; + ctx_flags = js_kctx_info->ctx.flags; + + /* Initial check for atoms targetting a specific coregroup */ + if ((job_core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) != MALI_FALSE && job_device_nr >= kbdev->gpu_props.num_core_groups) { + /* device_nr exceeds the number of coregroups - not allowed by + * @ref struct base_jd_atom_v2 API contract */ + return MALI_ERROR_FUNCTION_FAILED; + } + + /* Pick a core_req variant that matches us. Since they're ordered by least + * restrictive first, it picks the least restrictive variant */ + for (i = 0; i < policy_info->num_core_req_variants; ++i) { + base_jd_core_req var_core_req; + kbase_context_flags var_ctx_req; + u32 var_device_nr; + var_core_req = policy_info->core_req_variants[i].core_req; + var_ctx_req = policy_info->core_req_variants[i].ctx_req; + var_device_nr = policy_info->core_req_variants[i].device_nr; + + if ((var_core_req & job_core_req) == job_core_req && (var_ctx_req & ctx_flags) == ctx_flags && ((var_core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) == MALI_FALSE || var_device_nr == job_device_nr)) { + job_info->cached_variant_idx = i; + return MALI_ERROR_NONE; + } + } + + /* Could not find a matching requirement, this should only be caused by an + * attempt to attack the driver. */ + return MALI_ERROR_FUNCTION_FAILED; +} + +STATIC mali_bool dequeue_job(struct kbase_device *kbdev, + struct kbase_context *kctx, + u32 variants_supported, + struct kbase_jd_atom ** const katom_ptr, + int job_slot_idx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_policy_cfs_ctx *ctx_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom_ptr != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + policy_info = &js_devdata->policy.cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + /* Only submit jobs from contexts that are allowed */ + if (kbasep_js_is_submit_allowed(js_devdata, kctx) != MALI_FALSE) { + /* Check each variant in turn */ + while (variants_supported != 0) { + long variant_idx; + struct list_head *job_list; + + variant_idx = ffs(variants_supported) - 1; + job_list = &ctx_info->job_list_head[variant_idx]; + + if (!list_empty(job_list)) { + /* Found a context with a matching job */ + { + struct kbase_jd_atom *front_atom = + list_entry(job_list->next, struct kbase_jd_atom, sched_info.cfs.list); + + KBASE_TRACE_ADD_SLOT(kbdev, JS_POLICY_DEQUEUE_JOB, front_atom->kctx, front_atom, front_atom->jc, job_slot_idx); + } + *katom_ptr = list_entry(job_list->next, struct kbase_jd_atom, sched_info.cfs.list); + list_del(job_list->next); + + (*katom_ptr)->sched_info.cfs.ticks = 0; + + /* Put this context at the back of the Run Pool */ + list_del(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); + list_add_tail(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list, &policy_info->scheduled_ctxs_head); + + return MALI_TRUE; + } + + variants_supported &= ~(1u << variant_idx); + } + /* All variants checked by here */ + } + + /* The context does not have a matching job */ + + return MALI_FALSE; +} + +/** + * Hold the runpool_irq spinlock for this + */ +STATIC INLINE mali_bool timer_callback_should_run(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + s8 nr_running_ctxs; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + + /* nr_user_contexts_running is updated with the runpool_mutex. However, the + * locking in the caller gives us a barrier that ensures nr_user_contexts is + * up-to-date for reading */ + nr_running_ctxs = js_devdata->nr_user_contexts_running; + +#ifdef CONFIG_MALI_DEBUG + if (js_devdata->softstop_always && nr_running_ctxs > 0) { + /* Debug support for allowing soft-stop on a single context */ + return MALI_TRUE; + } +#endif /* CONFIG_MALI_DEBUG */ + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_9435)) { + /* Timeouts would have to be 4x longer (due to micro-architectural design) + * to support OpenCL conformance tests, so only run the timer when there's: + * - 2 or more CL contexts + * - 1 or more GLES contexts + * + * NOTE: We will treat a context that has both Compute and Non-Compute jobs + * will be treated as an OpenCL context (hence, we don't check + * KBASEP_JS_CTX_ATTR_NON_COMPUTE). + */ + { + s8 nr_compute_ctxs = kbasep_js_ctx_attr_count_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_COMPUTE); + s8 nr_noncompute_ctxs = nr_running_ctxs - nr_compute_ctxs; + + return (mali_bool) (nr_compute_ctxs >= 2 || nr_noncompute_ctxs > 0); + } + } else { + /* Run the timer callback whenever you have at least 1 context */ + return (mali_bool) (nr_running_ctxs > 0); + } +} + +static enum hrtimer_restart timer_callback(struct hrtimer *timer) +{ + unsigned long flags; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs *policy_info; + int s; + mali_bool reset_needed = MALI_FALSE; + + KBASE_DEBUG_ASSERT(timer != NULL); + + policy_info = container_of(timer, struct kbasep_js_policy_cfs, scheduling_timer); + kbdev = container_of(policy_info, struct kbase_device, js_data.policy.cfs); + js_devdata = &kbdev->js_data; + + /* Loop through the slots */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + for (s = 0; s < kbdev->gpu_props.num_job_slots; s++) { + struct kbase_jm_slot *slot = &kbdev->jm_slots[s]; + struct kbase_jd_atom *atom = NULL; + + if (kbasep_jm_nr_jobs_submitted(slot) > 0) { + atom = kbasep_jm_peek_idx_submit_slot(slot, 0); + KBASE_DEBUG_ASSERT(atom != NULL); + + if (kbasep_jm_is_dummy_workaround_job(kbdev, atom) != MALI_FALSE) { + /* Prevent further use of the atom - never cause a soft-stop, hard-stop, or a GPU reset due to it. */ + atom = NULL; + } + } + + if (atom != NULL) { + /* The current version of the model doesn't support Soft-Stop */ + if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_5736)) { + u32 ticks = atom->sched_info.cfs.ticks++; + +#if !CINSTR_DUMPING_ENABLED + u32 soft_stop_ticks, hard_stop_ticks, gpu_reset_ticks; + if (atom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { + soft_stop_ticks = js_devdata->soft_stop_ticks_cl; + hard_stop_ticks = js_devdata->hard_stop_ticks_cl; + gpu_reset_ticks = js_devdata->gpu_reset_ticks_cl; + } else { + soft_stop_ticks = js_devdata->soft_stop_ticks; + hard_stop_ticks = js_devdata->hard_stop_ticks_ss; + gpu_reset_ticks = js_devdata->gpu_reset_ticks_ss; + } + + /* Job is Soft-Stoppable */ + if (ticks == soft_stop_ticks) { + int disjoint_threshold = + KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD; + u32 softstop_flags = 0u; + /* Job has been scheduled for at least js_devdata->soft_stop_ticks ticks. + * Soft stop the slot so we can run other jobs. + */ + dev_dbg(kbdev->dev, "Soft-stop"); + +#if !KBASE_DISABLE_SCHEDULING_SOFT_STOPS + /* nr_user_contexts_running is updated with the runpool_mutex, + * but we can't take that here. + * + * However, if it's about to be increased then the new context + * can't run any jobs until they take the runpool_irq lock, so + * it's OK to observe the older value. + * + * Similarly, if it's about to be decreased, the last job from + * another context has already finished, so it's not too bad + * that we observe the older value and register a disjoint + * event when we try soft-stopping */ + if (js_devdata->nr_user_contexts_running >= disjoint_threshold) + softstop_flags |= JS_COMMAND_SW_CAUSES_DISJOINT; + kbase_job_slot_softstop_swflags(kbdev, + s, atom, softstop_flags); +#endif + } else if (ticks == hard_stop_ticks) { + /* Job has been scheduled for at least js_devdata->hard_stop_ticks_ss ticks. + * It should have been soft-stopped by now. Hard stop the slot. + */ +#if !KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_warn(kbdev->dev, "JS: Job Hard-Stopped (took more than %lu ticks at %lu ms/tick)", (unsigned long)ticks, (unsigned long)(js_devdata->scheduling_tick_ns / 1000000u)); + kbase_job_slot_hardstop(atom->kctx, s, atom); +#endif + } else if (ticks == gpu_reset_ticks) { + /* Job has been scheduled for at least js_devdata->gpu_reset_ticks_ss ticks. + * It should have left the GPU by now. Signal that the GPU needs to be reset. + */ + reset_needed = MALI_TRUE; + } +#else /* !CINSTR_DUMPING_ENABLED */ + /* NOTE: During CINSTR_DUMPING_ENABLED, we use the alternate timeouts, which + * makes the hard-stop and GPU reset timeout much longer. We also ensure that + * we don't soft-stop at all. */ + if (ticks == js_devdata->soft_stop_ticks) { + /* Job has been scheduled for at least js_devdata->soft_stop_ticks. + * We do not soft-stop during CINSTR_DUMPING_ENABLED, however. + */ + dev_dbg(kbdev->dev, "Soft-stop"); + } else if (ticks == js_devdata->hard_stop_ticks_nss) { + /* Job has been scheduled for at least js_devdata->hard_stop_ticks_nss ticks. + * Hard stop the slot. + */ +#if !KBASE_DISABLE_SCHEDULING_HARD_STOPS + dev_warn(kbdev->dev, "JS: Job Hard-Stopped (took more than %lu ticks at %lu ms/tick)", (unsigned long)ticks, (unsigned long)(js_devdata->scheduling_tick_ns / 1000000u)); + kbase_job_slot_hardstop(atom->kctx, s, atom); +#endif + } else if (ticks == js_devdata->gpu_reset_ticks_nss) { + /* Job has been scheduled for at least js_devdata->gpu_reset_ticks_nss ticks. + * It should have left the GPU by now. Signal that the GPU needs to be reset. + */ + reset_needed = MALI_TRUE; + } +#endif /* !CINSTR_DUMPING_ENABLED */ + } + } + } +#if KBASE_GPU_RESET_EN + if (reset_needed) { + dev_err(kbdev->dev, "JS: Job has been on the GPU for too long (KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS/NSS timeout hit). Issueing GPU soft-reset to resolve."); + + if (kbase_prepare_to_reset_gpu_locked(kbdev)) + kbase_reset_gpu_locked(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* the timer is re-issued if there is contexts in the run-pool */ + + if (timer_callback_should_run(kbdev) != MALI_FALSE) { + hrtimer_start(&policy_info->scheduling_timer, HR_TIMER_DELAY_NSEC(js_devdata->scheduling_tick_ns), HRTIMER_MODE_REL); + } else { + KBASE_TRACE_ADD(kbdev, JS_POLICY_TIMER_END, NULL, NULL, 0u, 0u); + /* timer_running state is updated by kbasep_js_policy_runpool_timers_sync() */ + } + + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + return HRTIMER_NORESTART; +} + +/* + * Non-private functions + */ + +mali_error kbasep_js_policy_init(struct kbase_device *kbdev) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs *policy_info; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + js_devdata = &kbdev->js_data; + policy_info = &js_devdata->policy.cfs; + + INIT_LIST_HEAD(&policy_info->ctx_queue_head); + INIT_LIST_HEAD(&policy_info->scheduled_ctxs_head); + INIT_LIST_HEAD(&policy_info->ctx_rt_queue_head); + + atomic64_set(&policy_info->least_runtime_us, KBASEP_JS_RUNTIME_EMPTY); + atomic64_set(&policy_info->rt_least_runtime_us, KBASEP_JS_RUNTIME_EMPTY); + + hrtimer_init(&policy_info->scheduling_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + policy_info->scheduling_timer.function = timer_callback; + + policy_info->timer_running = MALI_FALSE; + policy_info->head_runtime_us = 0; + + /* Build up the core_req variants */ + build_core_req_variants(kbdev, policy_info); + /* Build the slot to variant lookups */ + build_slot_lookups(kbdev, policy_info); + + return MALI_ERROR_NONE; +} + +void kbasep_js_policy_term(union kbasep_js_policy *js_policy) +{ + struct kbasep_js_policy_cfs *policy_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + policy_info = &js_policy->cfs; + + /* ASSERT that there are no contexts queued */ + KBASE_DEBUG_ASSERT(list_empty(&policy_info->ctx_queue_head)); + KBASE_DEBUG_ASSERT(KBASEP_JS_RUNTIME_EMPTY == atomic64_read(&policy_info->least_runtime_us)); + + /* ASSERT that there are no contexts scheduled */ + KBASE_DEBUG_ASSERT(list_empty(&policy_info->scheduled_ctxs_head)); + + /* ASSERT that there are no contexts queued */ + KBASE_DEBUG_ASSERT(list_empty(&policy_info->ctx_rt_queue_head)); + KBASE_DEBUG_ASSERT(KBASEP_JS_RUNTIME_EMPTY == atomic64_read(&policy_info->rt_least_runtime_us)); + + hrtimer_cancel(&policy_info->scheduling_timer); +} + +mali_error kbasep_js_policy_init_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbasep_js_policy_cfs *policy_info; + u32 i; + int policy; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + js_devdata = &kbdev->js_data; + policy_info = &kbdev->js_data.policy.cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_INIT_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx)); + + for (i = 0; i < policy_info->num_core_req_variants; ++i) + INIT_LIST_HEAD(&ctx_info->job_list_head[i]); + + policy = current->policy; + if (policy == SCHED_FIFO || policy == SCHED_RR) { + ctx_info->process_rt_policy = MALI_TRUE; + ctx_info->process_priority = (((MAX_RT_PRIO - 1) - current->rt_priority) / 5) - 20; + } else { + ctx_info->process_rt_policy = MALI_FALSE; + ctx_info->process_priority = (current->static_prio - MAX_RT_PRIO) - 20; + } + + ctx_info->bag_total_priority = 0; + ctx_info->bag_total_nr_atoms = 0; + + /* Initial runtime (relative to least-run context runtime) + * + * This uses the Policy Queue's most up-to-date head_runtime_us by using the + * queue mutex to issue memory barriers - also ensure future updates to + * head_runtime_us occur strictly after this context is initialized */ + mutex_lock(&js_devdata->queue_mutex); + + /* No need to hold the the runpool_irq.lock here, because we're initializing + * the value, and the context is definitely not being updated in the + * runpool at this point. The queue_mutex ensures the memory barrier. */ + ctx_info->runtime_us = policy_info->head_runtime_us + priority_weight(ctx_info, (u64) js_devdata->cfs_ctx_runtime_init_slices * (u64) (js_devdata->ctx_timeslice_ns / 1000u)); + + mutex_unlock(&js_devdata->queue_mutex); + + return MALI_ERROR_NONE; +} + +void kbasep_js_policy_term_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbasep_js_policy_cfs *policy_info; + u32 i; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + { + struct kbase_device *kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_TERM_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx)); + } + + /* ASSERT that no jobs are present */ + for (i = 0; i < policy_info->num_core_req_variants; ++i) + KBASE_DEBUG_ASSERT(list_empty(&ctx_info->job_list_head[i])); + + /* No work to do */ +} + +/* + * Context Management + */ + +void kbasep_js_policy_enqueue_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbase_context *head_ctx; + struct kbase_context *list_kctx = NULL; + struct kbasep_js_device_data *js_devdata; + struct list_head *queue_head; + struct list_head *pos; + struct kbase_device *kbdev; + atomic64_t *least_runtime_us; + u64 head_runtime; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + js_devdata = &kbdev->js_data; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_ENQUEUE_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx)); + + /* ASSERT about scheduled-ness/queued-ness */ + kbasep_js_debug_check(policy_info, kctx, KBASEP_JS_CHECK_NOTQUEUED); + + /* Clamp the runtime to prevent DoS attacks through "stored-up" runtime */ + if (policy_info->head_runtime_us > ctx_info->runtime_us + (u64) js_devdata->cfs_ctx_runtime_min_slices * (u64) (js_devdata->ctx_timeslice_ns / 1000u)) { + /* No need to hold the the runpool_irq.lock here, because we're essentially + * initializing the value, and the context is definitely not being updated in the + * runpool at this point. The queue_mutex held by the caller ensures the memory + * barrier. */ + ctx_info->runtime_us = policy_info->head_runtime_us - (u64) js_devdata->cfs_ctx_runtime_min_slices * (u64) (js_devdata->ctx_timeslice_ns / 1000u); + } + + /* Find the position where the context should be enqueued */ + if (ctx_info->process_rt_policy) { + queue_head = &policy_info->ctx_rt_queue_head; + least_runtime_us = &policy_info->rt_least_runtime_us; + } else { + queue_head = &policy_info->ctx_queue_head; + least_runtime_us = &policy_info->least_runtime_us; + } + + if (list_empty(queue_head)) { + list_add_tail(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list, queue_head); + } else { + list_for_each(pos, queue_head) { + struct kbasep_js_policy_cfs_ctx *list_ctx_info; + + list_kctx = list_entry(pos, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + list_ctx_info = &list_kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + if ((kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) != 0) + break; + + if ((list_ctx_info->runtime_us > ctx_info->runtime_us) && ((list_kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) == 0)) + break; + } + + /* Add the context to the queue */ + list_add_tail(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list, &list_kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); + } + + /* Ensure least_runtime_us is up to date*/ + head_ctx = list_entry(queue_head->next, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + head_runtime = head_ctx->jctx.sched_info.runpool.policy_ctx.cfs.runtime_us; + atomic64_set(least_runtime_us, head_runtime); +} + +mali_bool kbasep_js_policy_dequeue_head_ctx(union kbasep_js_policy *js_policy, struct kbase_context ** const kctx_ptr) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbase_context *head_ctx; + struct list_head *queue_head; + atomic64_t *least_runtime_us; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx_ptr != NULL); + + policy_info = &js_policy->cfs; + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + + /* attempt to dequeue from the 'realttime' queue first */ + if (list_empty(&policy_info->ctx_rt_queue_head)) { + if (list_empty(&policy_info->ctx_queue_head)) { + /* Nothing to dequeue */ + return MALI_FALSE; + } else { + queue_head = &policy_info->ctx_queue_head; + least_runtime_us = &policy_info->least_runtime_us; + } + } else { + queue_head = &policy_info->ctx_rt_queue_head; + least_runtime_us = &policy_info->rt_least_runtime_us; + } + + /* Contexts are dequeued from the front of the queue */ + *kctx_ptr = list_entry(queue_head->next, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + /* If dequeuing will empty the list, then set least_runtime_us prior to deletion */ + if (queue_head->next->next == queue_head) + atomic64_set(least_runtime_us, KBASEP_JS_RUNTIME_EMPTY); + list_del(queue_head->next); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_DEQUEUE_HEAD_CTX, *kctx_ptr, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, *kctx_ptr)); + + /* Update the head runtime */ + if (!list_empty(queue_head)) { + u64 head_runtime; + + head_ctx = list_entry(queue_head->next, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + + /* No need to hold the the runpool_irq.lock here for reading - the + * context is definitely not being updated in the runpool at this + * point. The queue_mutex held by the caller ensures the memory barrier. */ + head_runtime = head_ctx->jctx.sched_info.runpool.policy_ctx.cfs.runtime_us; + + if (head_runtime > policy_info->head_runtime_us) + policy_info->head_runtime_us = head_runtime; + + atomic64_set(least_runtime_us, head_runtime); + } + + return MALI_TRUE; +} + +mali_bool kbasep_js_policy_try_evict_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbasep_js_policy_cfs *policy_info; + mali_bool is_present; + struct list_head *queue_head; + atomic64_t *least_runtime_us; + struct list_head *qhead; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + + if (ctx_info->process_rt_policy) { + queue_head = &policy_info->ctx_rt_queue_head; + least_runtime_us = &policy_info->rt_least_runtime_us; + } else { + queue_head = &policy_info->ctx_queue_head; + least_runtime_us = &policy_info->least_runtime_us; + } + + qhead = queue_head; + + is_present = kbasep_list_member_of(qhead, &kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); + + KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, JS_POLICY_TRY_EVICT_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx), is_present); + + if (is_present != MALI_FALSE) { + struct kbase_context *head_ctx; + + qhead = queue_head; + + /* If dequeuing will empty the list, then set least_runtime_us prior to deletion */ + if (queue_head->next->next == queue_head) + atomic64_set(least_runtime_us, KBASEP_JS_RUNTIME_EMPTY); + + /* Remove the context */ + list_del(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); + + qhead = queue_head; + /* Update the head runtime */ + if (!list_empty(qhead)) { + u64 head_runtime; + + head_ctx = list_entry(qhead->next, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + + /* No need to hold the the runpool_irq.lock here for reading - the + * context is definitely not being updated in the runpool at this + * point. The queue_mutex held by the caller ensures the memory barrier. */ + head_runtime = head_ctx->jctx.sched_info.runpool.policy_ctx.cfs.runtime_us; + + if (head_runtime > policy_info->head_runtime_us) + policy_info->head_runtime_us = head_runtime; + + atomic64_set(least_runtime_us, head_runtime); + } + } + + return is_present; +} + +void kbasep_js_policy_foreach_ctx_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, + kbasep_js_policy_ctx_job_cb callback, mali_bool detach_jobs) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbase_device *kbdev; + u32 i; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_FOREACH_CTX_JOBS, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx)); + + /* Invoke callback on jobs on each variant in turn */ + for (i = 0; i < policy_info->num_core_req_variants; ++i) { + struct list_head *job_list; + struct kbase_jd_atom *atom; + struct kbase_jd_atom *tmp_iter; + job_list = &ctx_info->job_list_head[i]; + /* Invoke callback on all kbase_jd_atoms in this list, optionally + * removing them from the list */ + list_for_each_entry_safe(atom, tmp_iter, job_list, sched_info.cfs.list) { + if (detach_jobs) + list_del(&atom->sched_info.cfs.list); + callback(kbdev, atom); + } + } + +} + +void kbasep_js_policy_runpool_add_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_device_data *js_devdata; + struct kbase_device *kbdev; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + js_devdata = container_of(js_policy, struct kbasep_js_device_data, policy); + + kbdev = kctx->kbdev; + + { + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_RUNPOOL_ADD_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt_nolock(kbdev, kctx)); + } + + /* ASSERT about scheduled-ness/queued-ness */ + kbasep_js_debug_check(policy_info, kctx, KBASEP_JS_CHECK_NOTSCHEDULED); + + /* All enqueued contexts go to the back of the runpool */ + list_add_tail(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list, &policy_info->scheduled_ctxs_head); + + if (timer_callback_should_run(kbdev) != MALI_FALSE && policy_info->timer_running == MALI_FALSE) { + hrtimer_start(&policy_info->scheduling_timer, HR_TIMER_DELAY_NSEC(js_devdata->scheduling_tick_ns), HRTIMER_MODE_REL); + + KBASE_TRACE_ADD(kbdev, JS_POLICY_TIMER_START, NULL, NULL, 0u, 0u); + policy_info->timer_running = MALI_TRUE; + } +} + +void kbasep_js_policy_runpool_remove_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs *policy_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + + { + struct kbase_device *kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_RUNPOOL_REMOVE_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt_nolock(kbdev, kctx)); + } + + /* ASSERT about scheduled-ness/queued-ness */ + kbasep_js_debug_check(policy_info, kctx, KBASEP_JS_CHECK_SCHEDULED); + + /* No searching or significant list maintenance required to remove this context */ + list_del(&kctx->jctx.sched_info.runpool.policy_ctx.cfs.list); +} + +mali_bool kbasep_js_policy_should_remove_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbasep_js_policy_cfs *policy_info; + struct kbasep_js_device_data *js_devdata; + u64 least_runtime_us; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + js_devdata = container_of(js_policy, struct kbasep_js_device_data, policy); + + if (ctx_info->process_rt_policy) + least_runtime_us = atomic64_read(&policy_info->rt_least_runtime_us); + else + least_runtime_us = atomic64_read(&policy_info->least_runtime_us); + + if (KBASEP_JS_RUNTIME_EMPTY == least_runtime_us) { + /* Queue is empty */ + return MALI_FALSE; + } + + if ((least_runtime_us + priority_weight(ctx_info, (u64) (js_devdata->ctx_timeslice_ns / 1000u))) + < ctx_info->runtime_us) { + /* The context is scheduled out if it's not the least-run context anymore. + * The "real" head runtime is used instead of the cached runtime so the current + * context is not scheduled out when there is less contexts than address spaces. + */ + return MALI_TRUE; + } + + return MALI_FALSE; +} + +void kbasep_js_policy_runpool_timers_sync(union kbasep_js_policy *js_policy) +{ + struct kbasep_js_policy_cfs *policy_info; + struct kbase_device *kbdev; + struct kbasep_js_device_data *js_devdata; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + + policy_info = &js_policy->cfs; + kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + js_devdata = &kbdev->js_data; + + if (!timer_callback_should_run(kbdev)) { + unsigned long flags; + + /* If the timer is running now, synchronize with it by + * locking/unlocking its spinlock, to ensure it's not using an old value + * from timer_callback_should_run() */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + /* From now on, return value of timer_callback_should_run() will also + * cause the timer to not requeue itself. Its return value cannot + * change, because it depends on variables updated with the + * runpool_mutex held, which the caller of this must also hold */ + hrtimer_cancel(&policy_info->scheduling_timer); + + policy_info->timer_running = MALI_FALSE; + } +} + +/* + * Job Chain Management + */ + +mali_error kbasep_js_policy_init_job(const union kbasep_js_policy *js_policy, const struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + const struct kbasep_js_policy_cfs *policy_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + policy_info = &js_policy->cfs; + + /* Determine the job's index into the job list head, will return error if the + * atom is malformed and so is reported. */ + return cached_variant_idx_init(policy_info, kctx, katom); +} + +void kbasep_js_policy_register_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + /* Adjust context priority to include the new job */ + ctx_info->bag_total_nr_atoms++; + ctx_info->bag_total_priority += katom->nice_prio; + + /* Get average priority and convert to NICE range -20..19 */ + if (ctx_info->bag_total_nr_atoms) + ctx_info->bag_priority = (ctx_info->bag_total_priority / ctx_info->bag_total_nr_atoms) - 20; +} + +void kbasep_js_policy_deregister_job(union kbasep_js_policy *js_policy, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + CSTD_UNUSED(js_policy); + KBASE_DEBUG_ASSERT(katom != NULL); + KBASE_DEBUG_ASSERT(kctx != NULL); + + ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs; + + /* Adjust context priority to no longer include removed job */ + KBASE_DEBUG_ASSERT(ctx_info->bag_total_nr_atoms > 0); + ctx_info->bag_total_nr_atoms--; + ctx_info->bag_total_priority -= katom->nice_prio; + KBASE_DEBUG_ASSERT(ctx_info->bag_total_priority >= 0); + + /* Get average priority and convert to NICE range -20..19 */ + if (ctx_info->bag_total_nr_atoms) + ctx_info->bag_priority = (ctx_info->bag_total_priority / ctx_info->bag_total_nr_atoms) - 20; +} +KBASE_EXPORT_TEST_API(kbasep_js_policy_deregister_job) + +mali_bool kbasep_js_policy_dequeue_job(struct kbase_device *kbdev, + int job_slot_idx, + struct kbase_jd_atom ** const katom_ptr) +{ + struct kbasep_js_device_data *js_devdata; + struct kbasep_js_policy_cfs *policy_info; + struct kbase_context *kctx; + u32 variants_supported; + struct list_head *pos; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(katom_ptr != NULL); + KBASE_DEBUG_ASSERT(job_slot_idx < BASE_JM_MAX_NR_SLOTS); + + js_devdata = &kbdev->js_data; + policy_info = &js_devdata->policy.cfs; + + /* Get the variants for this slot */ + if (kbdev->gpu_props.num_core_groups > 1 && kbasep_js_ctx_attr_is_attr_on_runpool(kbdev, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES) != MALI_FALSE) { + /* SS-allcore state, and there's more than one coregroup */ + variants_supported = get_slot_to_variant_lookup(policy_info->slot_to_variant_lookup_ss_allcore_state, job_slot_idx); + } else { + /* SS-state */ + variants_supported = get_slot_to_variant_lookup(policy_info->slot_to_variant_lookup_ss_state, job_slot_idx); + } + + /* First pass through the runpool we consider the realtime priority jobs */ + list_for_each(pos, &policy_info->scheduled_ctxs_head) { + kctx = list_entry(pos, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + if (kctx->jctx.sched_info.runpool.policy_ctx.cfs.process_rt_policy) { + if (dequeue_job(kbdev, kctx, variants_supported, katom_ptr, job_slot_idx)) { + /* Realtime policy job matched */ + return MALI_TRUE; + } + } + } + + /* Second pass through the runpool we consider the non-realtime priority jobs */ + list_for_each(pos, &policy_info->scheduled_ctxs_head) { + kctx = list_entry(pos, struct kbase_context, jctx.sched_info.runpool.policy_ctx.cfs.list); + if (kctx->jctx.sched_info.runpool.policy_ctx.cfs.process_rt_policy == MALI_FALSE) { + if (dequeue_job(kbdev, kctx, variants_supported, katom_ptr, job_slot_idx)) { + /* Non-realtime policy job matched */ + return MALI_TRUE; + } + } + } + + /* By this point, no contexts had a matching job */ + return MALI_FALSE; +} + +void kbasep_js_policy_enqueue_job(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom) +{ + struct kbasep_js_policy_cfs_job *job_info; + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbase_context *parent_ctx; + + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + parent_ctx = katom->kctx; + KBASE_DEBUG_ASSERT(parent_ctx != NULL); + + job_info = &katom->sched_info.cfs; + ctx_info = &parent_ctx->jctx.sched_info.runpool.policy_ctx.cfs; + + { + struct kbase_device *kbdev = container_of(js_policy, struct kbase_device, js_data.policy); + KBASE_TRACE_ADD(kbdev, JS_POLICY_ENQUEUE_JOB, katom->kctx, katom, katom->jc, 0); + } + list_add_tail(&katom->sched_info.cfs.list, &ctx_info->job_list_head[job_info->cached_variant_idx]); +} + +void kbasep_js_policy_log_job_result(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom, u64 time_spent_us) +{ + struct kbasep_js_policy_cfs_ctx *ctx_info; + struct kbase_context *parent_ctx; + KBASE_DEBUG_ASSERT(js_policy != NULL); + KBASE_DEBUG_ASSERT(katom != NULL); + CSTD_UNUSED(js_policy); + + parent_ctx = katom->kctx; + KBASE_DEBUG_ASSERT(parent_ctx != NULL); + + ctx_info = &parent_ctx->jctx.sched_info.runpool.policy_ctx.cfs; + + ctx_info->runtime_us += priority_weight(ctx_info, time_spent_us); + + katom->time_spent_us += time_spent_us; +} + +mali_bool kbasep_js_policy_ctx_has_priority(union kbasep_js_policy *js_policy, struct kbase_context *current_ctx, struct kbase_context *new_ctx) +{ + struct kbasep_js_policy_cfs_ctx *current_ctx_info; + struct kbasep_js_policy_cfs_ctx *new_ctx_info; + + KBASE_DEBUG_ASSERT(current_ctx != NULL); + KBASE_DEBUG_ASSERT(new_ctx != NULL); + CSTD_UNUSED(js_policy); + + current_ctx_info = ¤t_ctx->jctx.sched_info.runpool.policy_ctx.cfs; + new_ctx_info = &new_ctx->jctx.sched_info.runpool.policy_ctx.cfs; + + if ((current_ctx_info->process_rt_policy == MALI_FALSE) && (new_ctx_info->process_rt_policy == MALI_TRUE)) + return MALI_TRUE; + + if ((current_ctx_info->process_rt_policy == new_ctx_info->process_rt_policy) && (current_ctx_info->bag_priority > new_ctx_info->bag_priority)) + return MALI_TRUE; + + return MALI_FALSE; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.h new file mode 100644 index 0000000000000000000000000000000000000000..099f25799b4b8daa152337900cd1a30b3a8cdedc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_js_policy_cfs.h @@ -0,0 +1,167 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_js_policy_cfs.h + * Completely Fair Job Scheduler Policy structure definitions + */ + +#ifndef _KBASE_JS_POLICY_CFS_H_ +#define _KBASE_JS_POLICY_CFS_H_ + +#define KBASE_JS_POLICY_AVAILABLE_CFS + +/** @addtogroup base_api + * @{ */ +/** @addtogroup base_kbase_api + * @{ */ +/** @addtogroup kbase_js_policy + * @{ */ + +/** + * Internally, this policy keeps a few internal queues for different variants + * of core requirements, which are used to decide how to schedule onto the + * different job slots. + * + * Must be a power of 2 to keep the lookup math simple + */ +#define KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS_LOG2 3 +#define KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS (1u << KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS_LOG2) + +/** Bits needed in the lookup to support all slots */ +#define KBASEP_JS_VARIANT_LOOKUP_BITS_NEEDED (BASE_JM_MAX_NR_SLOTS * KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS) +/** Number of u32s needed in the lookup array to support all slots */ +#define KBASEP_JS_VARIANT_LOOKUP_WORDS_NEEDED ((KBASEP_JS_VARIANT_LOOKUP_BITS_NEEDED + 31) / 32) + +#define KBASEP_JS_RUNTIME_EMPTY ((u64)-1) + +typedef struct kbasep_js_policy_cfs { + /** List of all contexts in the context queue. Hold + * kbasep_js_device_data::queue_mutex whilst accessing. */ + struct list_head ctx_queue_head; + + /** List of all contexts in the realtime (priority) context queue */ + struct list_head ctx_rt_queue_head; + + /** List of scheduled contexts. Hold kbasep_jd_device_data::runpool_irq::lock + * whilst accessing, which is a spinlock */ + struct list_head scheduled_ctxs_head; + + /** Number of valid elements in the core_req_variants member, and the + * kbasep_js_policy_rr_ctx::job_list_head array */ + u32 num_core_req_variants; + + /** Variants of the core requirements */ + struct kbasep_atom_req core_req_variants[KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS]; + + /* Lookups per job slot against which core_req_variants match it */ + u32 slot_to_variant_lookup_ss_state[KBASEP_JS_VARIANT_LOOKUP_WORDS_NEEDED]; + u32 slot_to_variant_lookup_ss_allcore_state[KBASEP_JS_VARIANT_LOOKUP_WORDS_NEEDED]; + + /* The timer tick used for rescheduling jobs */ + struct hrtimer scheduling_timer; + + /* Is the timer running? + * + * The kbasep_js_device_data::runpool_mutex must be held whilst modifying this. */ + mali_bool timer_running; + + /* Number of us the least-run context has been running for + * + * The kbasep_js_device_data::queue_mutex must be held whilst updating this + * Reads are possible without this mutex, but an older value might be read + * if no memory barriers are issued beforehand. */ + u64 head_runtime_us; + + /* Number of us the least-run context in the context queue has been running for. + * -1 if context queue is empty. */ + atomic64_t least_runtime_us; + + /* Number of us the least-run context in the realtime (priority) context queue + * has been running for. -1 if realtime context queue is empty. */ + atomic64_t rt_least_runtime_us; +} kbasep_js_policy_cfs; + +/** + * This policy contains a single linked list of all contexts. + */ +typedef struct kbasep_js_policy_cfs_ctx { + /** Link implementing the Policy's Queue, and Currently Scheduled list */ + struct list_head list; + + /** Job lists for use when in the Run Pool - only using + * kbasep_js_policy_fcfs::num_unique_slots of them. We still need to track + * the jobs when we're not in the runpool, so this member is accessed from + * outside the policy queue (for the first job), inside the policy queue, + * and inside the runpool. + * + * If the context is in the runpool, then this must only be accessed with + * kbasep_js_device_data::runpool_irq::lock held + * + * Jobs are still added to this list even when the context is not in the + * runpool. In that case, the kbasep_js_kctx_info::ctx::jsctx_mutex must be + * held before accessing this. */ + struct list_head job_list_head[KBASEP_JS_MAX_NR_CORE_REQ_VARIANTS]; + + /** Number of us this context has been running for + * + * The kbasep_js_device_data::runpool_irq::lock (a spinlock) must be held + * whilst updating this. Initializing will occur on context init and + * context enqueue (which can only occur in one thread at a time), but + * multi-thread access only occurs while the context is in the runpool. + * + * Reads are possible without this spinlock, but an older value might be read + * if no memory barriers are issued beforehand */ + u64 runtime_us; + + /* Calling process policy scheme is a realtime scheduler and will use the priority queue + * Non-mutable after ctx init */ + mali_bool process_rt_policy; + /* Calling process NICE priority */ + int process_priority; + /* Average NICE priority of all atoms in bag: + * Hold the kbasep_js_kctx_info::ctx::jsctx_mutex when accessing */ + int bag_priority; + /* Total NICE priority of all atoms in bag + * Hold the kbasep_js_kctx_info::ctx::jsctx_mutex when accessing */ + int bag_total_priority; + /* Total number of atoms in the bag + * Hold the kbasep_js_kctx_info::ctx::jsctx_mutex when accessing */ + int bag_total_nr_atoms; + +} kbasep_js_policy_cfs_ctx; + +/** + * In this policy, each Job is part of at most one of the per_corereq lists + */ +typedef struct kbasep_js_policy_cfs_job { + struct list_head list; /**< Link implementing the Run Pool list/Jobs owned by the ctx */ + u32 cached_variant_idx; /**< Cached index of the list this should be entered into on re-queue */ + + /** Number of ticks that this job has been executing for + * + * To access this, the kbasep_js_device_data::runpool_irq::lock must be held */ + u32 ticks; +} kbasep_js_policy_cfs_job; + + /** @} *//* end group kbase_js_policy */ + /** @} *//* end group base_kbase_api */ + /** @} *//* end group base_api */ + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_linux.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_linux.h new file mode 100644 index 0000000000000000000000000000000000000000..0d024f27976125afb449a7fccdd1888ce301d46f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_linux.h @@ -0,0 +1,47 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_linux.h + * Base kernel APIs, Linux implementation. + */ + +#ifndef _KBASE_LINUX_H_ +#define _KBASE_LINUX_H_ + +/* All things that are needed for the Linux port. */ +#include +#include +#include +#include +#include + +#if defined(MALI_KERNEL_TEST_API) +#if (1 == MALI_KERNEL_TEST_API) +#define KBASE_EXPORT_TEST_API(func) EXPORT_SYMBOL(func); +#else +#define KBASE_EXPORT_TEST_API(func) +#endif +#else +#define KBASE_EXPORT_TEST_API(func) +#endif + +#define KBASE_EXPORT_SYMBOL(func) EXPORT_SYMBOL(func); + +#endif /* _KBASE_LINUX_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.c new file mode 100644 index 0000000000000000000000000000000000000000..2e1233a05a509646619c068e54d2f9695572362e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.c @@ -0,0 +1,1358 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem.c + * Base kernel memory APIs + */ +#ifdef CONFIG_DMA_SHARED_BUFFER +#include +#endif /* CONFIG_DMA_SHARED_BUFFER */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +atomic_t g_mtk_gpu_total_memory_usage_in_pages; +atomic_t g_mtk_gpu_peak_memory_usage_in_pages; + +KBASE_EXPORT_TEST_API(kbase_report_gpu_memory_usage) +int kbase_report_gpu_memory_usage() +{ +#if 0 + ssize_t ret = 0; + struct list_head *entry; + const struct list_head *kbdev_list; + int pages = 0; + kbdev_list = kbase_dev_list_get(); + list_for_each(entry, kbdev_list) { + struct kbase_device *kbdev = NULL; + kbasep_kctx_list_element *element; + kbdev = list_entry(entry, struct kbase_device, entry); + pages = atomic_read(&(kbdev->memdev.used_pages)); + } + kbase_dev_list_put(kbdev_list); +#endif + + return (atomic_read(&g_mtk_gpu_total_memory_usage_in_pages)*4096); +} + +int kbase_report_gpu_memory_peak() +{ + return (atomic_read(&g_mtk_gpu_peak_memory_usage_in_pages)*4096); +} + +/** + * @brief Check the zone compatibility of two regions. + */ +STATIC int kbase_region_tracker_match_zone(struct kbase_va_region *reg1, struct kbase_va_region *reg2) +{ + return ((reg1->flags & KBASE_REG_ZONE_MASK) == (reg2->flags & KBASE_REG_ZONE_MASK)); +} + +KBASE_EXPORT_TEST_API(kbase_region_tracker_match_zone) + +/* This function inserts a region into the tree. */ +static void kbase_region_tracker_insert(struct kbase_context *kctx, struct kbase_va_region *new_reg) +{ + u64 start_pfn = new_reg->start_pfn; + struct rb_node **link = &(kctx->reg_rbtree.rb_node); + struct rb_node *parent = NULL; + + /* Find the right place in the tree using tree search */ + while (*link) { + struct kbase_va_region *old_reg; + + parent = *link; + old_reg = rb_entry(parent, struct kbase_va_region, rblink); + + /* RBTree requires no duplicate entries. */ + KBASE_DEBUG_ASSERT(old_reg->start_pfn != start_pfn); + + if (old_reg->start_pfn > start_pfn) + link = &(*link)->rb_left; + else + link = &(*link)->rb_right; + } + + /* Put the new node there, and rebalance tree */ + rb_link_node(&(new_reg->rblink), parent, link); + rb_insert_color(&(new_reg->rblink), &(kctx->reg_rbtree)); +} + +/* Find allocated region enclosing free range. */ +static struct kbase_va_region *kbase_region_tracker_find_region_enclosing_range_free( + struct kbase_context *kctx, u64 start_pfn, size_t nr_pages) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + + u64 end_pfn = start_pfn + nr_pages; + + rbnode = kctx->reg_rbtree.rb_node; + while (rbnode) { + u64 tmp_start_pfn, tmp_end_pfn; + + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + tmp_start_pfn = reg->start_pfn; + tmp_end_pfn = reg->start_pfn + reg->nr_pages; + + /* If start is lower than this, go left. */ + if (start_pfn < tmp_start_pfn) + rbnode = rbnode->rb_left; + /* If end is higher than this, then go right. */ + else if (end_pfn > tmp_end_pfn) + rbnode = rbnode->rb_right; + else /* Enclosing */ + return reg; + } + + return NULL; +} + +/* Find region enclosing given address. */ +struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(struct kbase_context *kctx, mali_addr64 gpu_addr) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + u64 gpu_pfn = gpu_addr >> PAGE_SHIFT; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + rbnode = kctx->reg_rbtree.rb_node; + while (rbnode) { + u64 tmp_start_pfn, tmp_end_pfn; + + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + tmp_start_pfn = reg->start_pfn; + tmp_end_pfn = reg->start_pfn + reg->nr_pages; + + /* If start is lower than this, go left. */ + if (gpu_pfn < tmp_start_pfn) + rbnode = rbnode->rb_left; + /* If end is higher than this, then go right. */ + else if (gpu_pfn >= tmp_end_pfn) + rbnode = rbnode->rb_right; + else /* Enclosing */ + return reg; + } + + return NULL; +} + +KBASE_EXPORT_TEST_API(kbase_region_tracker_find_region_enclosing_address) + +/* Find region with given base address */ +struct kbase_va_region *kbase_region_tracker_find_region_base_address(struct kbase_context *kctx, mali_addr64 gpu_addr) +{ + u64 gpu_pfn = gpu_addr >> PAGE_SHIFT; + struct rb_node *rbnode; + struct kbase_va_region *reg; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + rbnode = kctx->reg_rbtree.rb_node; + while (rbnode) { + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + if (reg->start_pfn > gpu_pfn) + rbnode = rbnode->rb_left; + else if (reg->start_pfn < gpu_pfn) + rbnode = rbnode->rb_right; + else if (gpu_pfn == reg->start_pfn) + return reg; + else + rbnode = NULL; + } + + return NULL; +} + +KBASE_EXPORT_TEST_API(kbase_region_tracker_find_region_base_address) + +/* Find region meeting given requirements */ +static struct kbase_va_region *kbase_region_tracker_find_region_meeting_reqs(struct kbase_context *kctx, struct kbase_va_region *reg_reqs, size_t nr_pages, size_t align) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + + /* Note that this search is a linear search, as we do not have a target + address in mind, so does not benefit from the rbtree search */ + rbnode = rb_first(&(kctx->reg_rbtree)); + while (rbnode) { + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + if ((reg->nr_pages >= nr_pages) && + (reg->flags & KBASE_REG_FREE) && + kbase_region_tracker_match_zone(reg, reg_reqs)) { + /* Check alignment */ + u64 start_pfn = (reg->start_pfn + align - 1) & ~(align - 1); + + if ((start_pfn >= reg->start_pfn) && + (start_pfn <= (reg->start_pfn + reg->nr_pages - 1)) && + ((start_pfn + nr_pages - 1) <= (reg->start_pfn + reg->nr_pages - 1))) + return reg; + } + rbnode = rb_next(rbnode); + } + + return NULL; +} + +/** + * @brief Remove a region object from the global list. + * + * The region reg is removed, possibly by merging with other free and + * compatible adjacent regions. It must be called with the context + * region lock held. The associated memory is not released (see + * kbase_free_alloced_region). Internal use only. + */ +STATIC mali_error kbase_remove_va_region(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + struct rb_node *rbprev; + struct kbase_va_region *prev = NULL; + struct rb_node *rbnext; + struct kbase_va_region *next = NULL; + + int merged_front = 0; + int merged_back = 0; + mali_error err = MALI_ERROR_NONE; + + /* Try to merge with the previous block first */ + rbprev = rb_prev(&(reg->rblink)); + if (rbprev) { + prev = rb_entry(rbprev, struct kbase_va_region, rblink); + if ((prev->flags & KBASE_REG_FREE) && kbase_region_tracker_match_zone(prev, reg)) { + /* We're compatible with the previous VMA, merge with it */ + prev->nr_pages += reg->nr_pages; + rb_erase(&(reg->rblink), &kctx->reg_rbtree); + reg = prev; + merged_front = 1; + } + } + + /* Try to merge with the next block second */ + /* Note we do the lookup here as the tree may have been rebalanced. */ + rbnext = rb_next(&(reg->rblink)); + if (rbnext) { + /* We're compatible with the next VMA, merge with it */ + next = rb_entry(rbnext, struct kbase_va_region, rblink); + if ((next->flags & KBASE_REG_FREE) && kbase_region_tracker_match_zone(next, reg)) { + next->start_pfn = reg->start_pfn; + next->nr_pages += reg->nr_pages; + rb_erase(&(reg->rblink), &kctx->reg_rbtree); + merged_back = 1; + if (merged_front) { + /* We already merged with prev, free it */ + kbase_free_alloced_region(reg); + } + } + } + + /* If we failed to merge then we need to add a new block */ + if (!(merged_front || merged_back)) { + /* + * We didn't merge anything. Add a new free + * placeholder and remove the original one. + */ + struct kbase_va_region *free_reg; + + free_reg = kbase_alloc_free_region(kctx, reg->start_pfn, reg->nr_pages, reg->flags & KBASE_REG_ZONE_MASK); + if (!free_reg) { + err = MALI_ERROR_OUT_OF_MEMORY; + goto out; + } + + rb_replace_node(&(reg->rblink), &(free_reg->rblink), &(kctx->reg_rbtree)); + } + + out: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_remove_va_region) + +/** + * @brief Insert a VA region to the list, replacing the current at_reg. + */ +static mali_error kbase_insert_va_region_nolock(struct kbase_context *kctx, struct kbase_va_region *new_reg, struct kbase_va_region *at_reg, u64 start_pfn, size_t nr_pages) +{ + mali_error err = MALI_ERROR_NONE; + + /* Must be a free region */ + KBASE_DEBUG_ASSERT((at_reg->flags & KBASE_REG_FREE) != 0); + /* start_pfn should be contained within at_reg */ + KBASE_DEBUG_ASSERT((start_pfn >= at_reg->start_pfn) && (start_pfn < at_reg->start_pfn + at_reg->nr_pages)); + /* at least nr_pages from start_pfn should be contained within at_reg */ + KBASE_DEBUG_ASSERT(start_pfn + nr_pages <= at_reg->start_pfn + at_reg->nr_pages); + + new_reg->start_pfn = start_pfn; + new_reg->nr_pages = nr_pages; + + /* Regions are a whole use, so swap and delete old one. */ + if (at_reg->start_pfn == start_pfn && at_reg->nr_pages == nr_pages) { + rb_replace_node(&(at_reg->rblink), &(new_reg->rblink), &(kctx->reg_rbtree)); + kbase_free_alloced_region(at_reg); + } + /* New region replaces the start of the old one, so insert before. */ + else if (at_reg->start_pfn == start_pfn) { + at_reg->start_pfn += nr_pages; + KBASE_DEBUG_ASSERT(at_reg->nr_pages >= nr_pages); + at_reg->nr_pages -= nr_pages; + + kbase_region_tracker_insert(kctx, new_reg); + } + /* New region replaces the end of the old one, so insert after. */ + else if ((at_reg->start_pfn + at_reg->nr_pages) == (start_pfn + nr_pages)) { + at_reg->nr_pages -= nr_pages; + + kbase_region_tracker_insert(kctx, new_reg); + } + /* New region splits the old one, so insert and create new */ + else { + struct kbase_va_region *new_front_reg; + + new_front_reg = kbase_alloc_free_region(kctx, + at_reg->start_pfn, + start_pfn - at_reg->start_pfn, + at_reg->flags & KBASE_REG_ZONE_MASK); + + if (new_front_reg) { + at_reg->nr_pages -= nr_pages + new_front_reg->nr_pages; + at_reg->start_pfn = start_pfn + nr_pages; + + kbase_region_tracker_insert(kctx, new_front_reg); + kbase_region_tracker_insert(kctx, new_reg); + } else { + err = MALI_ERROR_OUT_OF_MEMORY; + } + } + + return err; +} + +/** + * @brief Add a VA region to the list. + */ +mali_error kbase_add_va_region(struct kbase_context *kctx, + struct kbase_va_region *reg, mali_addr64 addr, + size_t nr_pages, size_t align) +{ + struct kbase_va_region *tmp; + u64 gpu_pfn = addr >> PAGE_SHIFT; + mali_error err = MALI_ERROR_NONE; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + + lockdep_assert_held(&kctx->reg_lock); + + if (!align) + align = 1; + + /* must be a power of 2 */ + KBASE_DEBUG_ASSERT((align & (align - 1)) == 0); + KBASE_DEBUG_ASSERT(nr_pages > 0); + + /* Path 1: Map a specific address. Find the enclosing region, which *must* be free. */ + if (gpu_pfn) { + struct device *dev = kctx->kbdev->dev; + + KBASE_DEBUG_ASSERT(!(gpu_pfn & (align - 1))); + + tmp = kbase_region_tracker_find_region_enclosing_range_free(kctx, gpu_pfn, nr_pages); + if (!tmp) { + dev_warn(dev, "Enclosing region not found: 0x%08llx gpu_pfn, %zu nr_pages", gpu_pfn, nr_pages); + err = MALI_ERROR_OUT_OF_GPU_MEMORY; + goto exit; + } + + if ((!kbase_region_tracker_match_zone(tmp, reg)) || + (!(tmp->flags & KBASE_REG_FREE))) { + dev_warn(dev, "Zone mismatch: %lu != %lu", tmp->flags & KBASE_REG_ZONE_MASK, reg->flags & KBASE_REG_ZONE_MASK); + dev_warn(dev, "!(tmp->flags & KBASE_REG_FREE): tmp->start_pfn=0x%llx tmp->flags=0x%lx tmp->nr_pages=0x%zx gpu_pfn=0x%llx nr_pages=0x%zx\n", tmp->start_pfn, tmp->flags, tmp->nr_pages, gpu_pfn, nr_pages); + dev_warn(dev, "in function %s (%p, %p, 0x%llx, 0x%zx, 0x%zx)\n", __func__, kctx, reg, addr, nr_pages, align); + err = MALI_ERROR_OUT_OF_GPU_MEMORY; + goto exit; + } + + err = kbase_insert_va_region_nolock(kctx, reg, tmp, gpu_pfn, nr_pages); + if (err) { + dev_warn(dev, "Failed to insert va region"); + err = MALI_ERROR_OUT_OF_GPU_MEMORY; + goto exit; + } + + goto exit; + } + + /* Path 2: Map any free address which meets the requirements. */ + { + u64 start_pfn; + + tmp = kbase_region_tracker_find_region_meeting_reqs(kctx, reg, nr_pages, align); + if (!tmp) { + err = MALI_ERROR_OUT_OF_GPU_MEMORY; + goto exit; + } + start_pfn = (tmp->start_pfn + align - 1) & ~(align - 1); + err = kbase_insert_va_region_nolock(kctx, reg, tmp, start_pfn, nr_pages); + } + + exit: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_add_va_region) + +/** + * @brief Initialize the internal region tracker data structure. + */ +static void kbase_region_tracker_ds_init(struct kbase_context *kctx, struct kbase_va_region *same_va_reg, struct kbase_va_region *exec_reg, struct kbase_va_region *custom_va_reg) +{ + kctx->reg_rbtree = RB_ROOT; + kbase_region_tracker_insert(kctx, same_va_reg); + + /* exec and custom_va_reg doesn't always exist */ + if (exec_reg && custom_va_reg) { + kbase_region_tracker_insert(kctx, exec_reg); + kbase_region_tracker_insert(kctx, custom_va_reg); + } +} + +void kbase_region_tracker_term(struct kbase_context *kctx) +{ + struct rb_node *rbnode; + struct kbase_va_region *reg; + + do { + rbnode = rb_first(&(kctx->reg_rbtree)); + if (rbnode) { + rb_erase(rbnode, &(kctx->reg_rbtree)); + reg = rb_entry(rbnode, struct kbase_va_region, rblink); + kbase_free_alloced_region(reg); + } + } while (rbnode); +} + +/** + * Initialize the region tracker data structure. + */ +mali_error kbase_region_tracker_init(struct kbase_context *kctx) +{ + struct kbase_va_region *same_va_reg; + struct kbase_va_region *exec_reg = NULL; + struct kbase_va_region *custom_va_reg = NULL; + size_t same_va_bits = sizeof(void *) * BITS_PER_BYTE; + u64 custom_va_size = KBASE_REG_ZONE_CUSTOM_VA_SIZE; + u64 gpu_va_limit = (1ULL << kctx->kbdev->gpu_props.mmu.va_bits) >> PAGE_SHIFT; + +#if defined(CONFIG_ARM64) + same_va_bits = VA_BITS; +#elif defined(CONFIG_X86_64) + same_va_bits = 47; +#elif defined(CONFIG_64BIT) +#error Unsupported 64-bit architecture +#endif + +#ifdef CONFIG_64BIT + if (kctx->is_compat) + same_va_bits = 32; + else if (kbase_hw_has_feature(kctx->kbdev, BASE_HW_FEATURE_33BIT_VA)) + same_va_bits = 33; +#endif + + if (kctx->kbdev->gpu_props.mmu.va_bits < same_va_bits) + return MALI_ERROR_FUNCTION_FAILED; + + /* all have SAME_VA */ + same_va_reg = kbase_alloc_free_region(kctx, 1, + (1ULL << (same_va_bits - PAGE_SHIFT)) - 2, + KBASE_REG_ZONE_SAME_VA); + + if (!same_va_reg) + return MALI_ERROR_OUT_OF_MEMORY; + +#ifdef CONFIG_64BIT + /* only 32-bit clients have the other two zones */ + if (kctx->is_compat) { +#endif + if (gpu_va_limit <= KBASE_REG_ZONE_CUSTOM_VA_BASE) { + kbase_free_alloced_region(same_va_reg); + return MALI_ERROR_FUNCTION_FAILED; + } + /* If the current size of TMEM is out of range of the + * virtual address space addressable by the MMU then + * we should shrink it to fit + */ + if ((KBASE_REG_ZONE_CUSTOM_VA_BASE + KBASE_REG_ZONE_CUSTOM_VA_SIZE) >= gpu_va_limit) + custom_va_size = gpu_va_limit - KBASE_REG_ZONE_CUSTOM_VA_BASE; + + exec_reg = kbase_alloc_free_region(kctx, + KBASE_REG_ZONE_EXEC_BASE, + KBASE_REG_ZONE_EXEC_SIZE, + KBASE_REG_ZONE_EXEC); + + if (!exec_reg) { + kbase_free_alloced_region(same_va_reg); + return MALI_ERROR_OUT_OF_MEMORY; + } + + custom_va_reg = kbase_alloc_free_region(kctx, + KBASE_REG_ZONE_CUSTOM_VA_BASE, + custom_va_size, KBASE_REG_ZONE_CUSTOM_VA); + + if (!custom_va_reg) { + kbase_free_alloced_region(same_va_reg); + kbase_free_alloced_region(exec_reg); + return MALI_ERROR_OUT_OF_MEMORY; + } +#ifdef CONFIG_64BIT + } +#endif + + kbase_region_tracker_ds_init(kctx, same_va_reg, exec_reg, custom_va_reg); + + return MALI_ERROR_NONE; +} + +mali_error kbase_mem_init(struct kbase_device *kbdev) +{ + struct kbasep_mem_device *memdev; + + KBASE_DEBUG_ASSERT(kbdev); + + memdev = &kbdev->memdev; + + /* Initialize memory usage */ + atomic_set(&memdev->used_pages, 0); + + atomic_set(&g_mtk_gpu_total_memory_usage_in_pages, 0); + + atomic_set(&g_mtk_gpu_peak_memory_usage_in_pages, 0); + + /* nothing to do, zero-inited when struct kbase_device was created */ + return MALI_ERROR_NONE; +} + +void kbase_mem_halt(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +void kbase_mem_term(struct kbase_device *kbdev) +{ + struct kbasep_mem_device *memdev; + int pages; + + KBASE_DEBUG_ASSERT(kbdev); + + memdev = &kbdev->memdev; + + pages = atomic_read(&memdev->used_pages); + if (pages != 0) + dev_warn(kbdev->dev, "%s: %d pages in use!\n", __func__, pages); +} + +KBASE_EXPORT_TEST_API(kbase_mem_term) + +/** + * @brief Wait for GPU write flush - only in use for BASE_HW_ISSUE_6367 + * + * Wait 1000 GPU clock cycles. This delay is known to give the GPU time to flush its write buffer. + * @note If GPU resets occur then the counters are reset to zero, the delay may not be as expected. + */ +#ifndef CONFIG_MALI_NO_MALI +void kbase_wait_write_flush(struct kbase_context *kctx) +{ + u32 base_count = 0; + + /* A suspend won't happen here, because we're in a syscall from a userspace thread */ + kbase_pm_context_active(kctx->kbdev); + kbase_pm_request_gpu_cycle_counter(kctx->kbdev); + + while (MALI_TRUE) { + u32 new_count; + + new_count = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(CYCLE_COUNT_LO), NULL); + /* First time around, just store the count. */ + if (base_count == 0) { + base_count = new_count; + continue; + } + + /* No need to handle wrapping, unsigned maths works for this. */ + if ((new_count - base_count) > 1000) + break; + } + + kbase_pm_release_gpu_cycle_counter(kctx->kbdev); + kbase_pm_context_idle(kctx->kbdev); +} +#endif /* CONFIG_MALI_NO_MALI */ + + + +/** + * @brief Allocate a free region object. + * + * The allocated object is not part of any list yet, and is flagged as + * KBASE_REG_FREE. No mapping is allocated yet. + * + * zone is KBASE_REG_ZONE_CUSTOM_VA, KBASE_REG_ZONE_SAME_VA, or KBASE_REG_ZONE_EXEC + * + */ +struct kbase_va_region *kbase_alloc_free_region(struct kbase_context *kctx, u64 start_pfn, size_t nr_pages, int zone) +{ + struct kbase_va_region *new_reg; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + /* zone argument should only contain zone related region flags */ + KBASE_DEBUG_ASSERT((zone & ~KBASE_REG_ZONE_MASK) == 0); + KBASE_DEBUG_ASSERT(nr_pages > 0); + KBASE_DEBUG_ASSERT(start_pfn + nr_pages <= (UINT64_MAX / PAGE_SIZE)); /* 64-bit address range is the max */ + + new_reg = kzalloc(sizeof(*new_reg), GFP_KERNEL); + + if (!new_reg) { + dev_warn(kctx->kbdev->dev, "kzalloc failed"); + return NULL; + } + + new_reg->alloc = NULL; /* no alloc bound yet */ + new_reg->kctx = kctx; + new_reg->flags = zone | KBASE_REG_FREE; + + new_reg->flags |= KBASE_REG_GROWABLE; + + /* Set up default MEMATTR usage */ + new_reg->flags |= KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_DEFAULT); + + new_reg->start_pfn = start_pfn; + new_reg->nr_pages = nr_pages; + + return new_reg; +} + +KBASE_EXPORT_TEST_API(kbase_alloc_free_region) + +/** + * @brief Free a region object. + * + * The described region must be freed of any mapping. + * + * If the region is not flagged as KBASE_REG_FREE, the region's + * alloc object will be released. + * It is a bug if no alloc object exists for non-free regions. + * + */ +void kbase_free_alloced_region(struct kbase_va_region *reg) +{ + KBASE_DEBUG_ASSERT(NULL != reg); + if (!(reg->flags & KBASE_REG_FREE)) { + kbase_mem_phy_alloc_put(reg->alloc); + /* To detect use-after-free in debug builds */ + KBASE_DEBUG_CODE(reg->flags |= KBASE_REG_FREE); + } + kfree(reg); +} + +KBASE_EXPORT_TEST_API(kbase_free_alloced_region) + +void kbase_mmu_update(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbase_as *as; + struct kbase_mmu_setup *current_setup; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + /* ASSERT that the context has a valid as_nr, which is only the case + * when it's scheduled in. + * + * as_nr won't change because the caller has the runpool_irq lock */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + kbdev = kctx->kbdev; + as = &kbdev->as[kctx->as_nr]; + current_setup = &as->current_setup; + + /* Use GPU implementation-defined caching policy. */ + current_setup->memattr = kctx->mem_attrs; + + current_setup->transtab = (u64) kctx->pgd & ((0xFFFFFFFFULL << 32) | AS_TRANSTAB_ADDR_SPACE_MASK); + current_setup->transtab |= AS_TRANSTAB_READ_INNER | + AS_TRANSTAB_ADRMODE_TABLE; + + /* Apply the address space setting */ + kbase_mmu_hw_configure(kbdev, as, kctx); +} + +KBASE_EXPORT_TEST_API(kbase_mmu_update) + +void kbase_mmu_disable(struct kbase_context *kctx) +{ + struct kbase_device *kbdev; + struct kbase_as *as; + struct kbase_mmu_setup *current_setup; + + KBASE_DEBUG_ASSERT(NULL != kctx); + /* ASSERT that the context has a valid as_nr, which is only the case + * when it's scheduled in. + * + * as_nr won't change because the caller has the runpool_irq lock */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + kbdev = kctx->kbdev; + as = &kbdev->as[kctx->as_nr]; + current_setup = &as->current_setup; + + current_setup->transtab = 0ULL; + + /* Apply the address space setting */ + kbase_mmu_hw_configure(kbdev, as, kctx); +} + +KBASE_EXPORT_TEST_API(kbase_mmu_disable) + +mali_error kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, mali_addr64 addr, size_t nr_pages, size_t align) +{ + mali_error err; + size_t i = 0; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + + err = kbase_add_va_region(kctx, reg, addr, nr_pages, align); + if (MALI_ERROR_NONE != err) + return err; + + if (reg->alloc->type == KBASE_MEM_TYPE_ALIAS) { + u64 stride; + + stride = reg->alloc->imported.alias.stride; + KBASE_DEBUG_ASSERT(reg->alloc->imported.alias.aliased); + for (i = 0; i < reg->alloc->imported.alias.nents; i++) { + if (reg->alloc->imported.alias.aliased[i].alloc) { + err = kbase_mmu_insert_pages(kctx, + reg->start_pfn + (i * stride), + reg->alloc->imported.alias.aliased[i].alloc->pages + reg->alloc->imported.alias.aliased[i].offset, + reg->alloc->imported.alias.aliased[i].length, + reg->flags); + if (MALI_ERROR_NONE != err) + goto bad_insert; + + kbase_mem_phy_alloc_gpu_mapped(reg->alloc->imported.alias.aliased[i].alloc); + } else { + err = kbase_mmu_insert_single_page(kctx, + reg->start_pfn + i * stride, + kctx->aliasing_sink_page, + reg->alloc->imported.alias.aliased[i].length, + (reg->flags & ~KBASE_REG_MEMATTR_MASK) | KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_WRITE_ALLOC) + ); + if (MALI_ERROR_NONE != err) + goto bad_insert; + } + } + } else { + err = kbase_mmu_insert_pages(kctx, reg->start_pfn, + kbase_get_phy_pages(reg), + kbase_reg_current_backed_size(reg), + reg->flags); + if (MALI_ERROR_NONE != err) + goto bad_insert; + kbase_mem_phy_alloc_gpu_mapped(reg->alloc); + } + + return err; + +bad_insert: + if (reg->alloc->type == KBASE_MEM_TYPE_ALIAS) { + u64 stride; + + stride = reg->alloc->imported.alias.stride; + KBASE_DEBUG_ASSERT(reg->alloc->imported.alias.aliased); + while (i--) + if (reg->alloc->imported.alias.aliased[i].alloc) { + kbase_mmu_teardown_pages(kctx, reg->start_pfn + (i * stride), reg->alloc->imported.alias.aliased[i].length); + kbase_mem_phy_alloc_gpu_unmapped(reg->alloc->imported.alias.aliased[i].alloc); + } + } + + kbase_remove_va_region(kctx, reg); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_gpu_mmap) + +mali_error kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + mali_error err; + + if (reg->start_pfn == 0) + return MALI_ERROR_NONE; + + if (reg->alloc && reg->alloc->type == KBASE_MEM_TYPE_ALIAS) { + size_t i; + + err = kbase_mmu_teardown_pages(kctx, reg->start_pfn, reg->nr_pages); + KBASE_DEBUG_ASSERT(reg->alloc->imported.alias.aliased); + for (i = 0; i < reg->alloc->imported.alias.nents; i++) + if (reg->alloc->imported.alias.aliased[i].alloc) + kbase_mem_phy_alloc_gpu_unmapped(reg->alloc->imported.alias.aliased[i].alloc); + } else { + err = kbase_mmu_teardown_pages(kctx, reg->start_pfn, kbase_reg_current_backed_size(reg)); + kbase_mem_phy_alloc_gpu_unmapped(reg->alloc); + } + + if (MALI_ERROR_NONE != err) + return err; + + err = kbase_remove_va_region(kctx, reg); + return err; +} + +STATIC struct kbase_cpu_mapping *kbasep_find_enclosing_cpu_mapping_of_region(const struct kbase_va_region *reg, unsigned long uaddr, size_t size) +{ + struct kbase_cpu_mapping *map; + struct list_head *pos; + + KBASE_DEBUG_ASSERT(NULL != reg); + KBASE_DEBUG_ASSERT(reg->alloc); + + if ((uintptr_t) uaddr + size < (uintptr_t) uaddr) /* overflow check */ + return NULL; + + list_for_each(pos, ®->alloc->mappings) { + map = list_entry(pos, kbase_cpu_mapping, mappings_list); + if (map->vm_start <= uaddr && map->vm_end >= uaddr + size) + return map; + } + + return NULL; +} + +KBASE_EXPORT_TEST_API(kbasep_find_enclosing_cpu_mapping_of_region) + +mali_error kbasep_find_enclosing_cpu_mapping_offset( + struct kbase_context *kctx, mali_addr64 gpu_addr, + unsigned long uaddr, size_t size, mali_size64 *offset) +{ + struct kbase_cpu_mapping *map = NULL; + const struct kbase_va_region *reg; + mali_error err = MALI_ERROR_FUNCTION_FAILED; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + kbase_gpu_vm_lock(kctx); + + reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); + if (reg && !(reg->flags & KBASE_REG_FREE)) { + map = kbasep_find_enclosing_cpu_mapping_of_region(reg, uaddr, + size); + if (map) { + *offset = (uaddr - PTR_TO_U64(map->vm_start)) + + (map->page_off << PAGE_SHIFT); + err = MALI_ERROR_NONE; + } + } + + kbase_gpu_vm_unlock(kctx); + + return err; +} + +KBASE_EXPORT_TEST_API(kbasep_find_enclosing_cpu_mapping_offset) + +void kbase_sync_single(struct kbase_context *kctx, + phys_addr_t pa, size_t size, kbase_sync_kmem_fn sync_fn) +{ + struct page *p = pfn_to_page(PFN_DOWN(pa)); + off_t offset = pa & ~PAGE_MASK; + dma_addr_t dma_addr; + + BUG_ON(!p); + BUG_ON(offset + size > PAGE_SIZE); + + dma_addr = kbase_dma_addr(p) + offset; + + sync_fn(kctx->kbdev->dev, dma_addr, size, DMA_BIDIRECTIONAL); +} + +static mali_error kbase_do_syncset(struct kbase_context *kctx, struct base_syncset *set, kbase_sync_kmem_fn sync_fn) +{ + mali_error err = MALI_ERROR_NONE; + struct basep_syncset *sset = &set->basep_sset; + struct kbase_va_region *reg; + struct kbase_cpu_mapping *map; + unsigned long start; + size_t size; + phys_addr_t *pa; + u64 page_off, page_count; + u64 i; + unsigned int offset; + + kbase_os_mem_map_lock(kctx); + kbase_gpu_vm_lock(kctx); + + /* find the region where the virtual address is contained */ + reg = kbase_region_tracker_find_region_enclosing_address(kctx, sset->mem_handle); + if (!reg) { + dev_warn(kctx->kbdev->dev, "Can't find region at VA 0x%016llX", sset->mem_handle); + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + if (!(reg->flags & KBASE_REG_CPU_CACHED)) + goto out_unlock; + + start = (uintptr_t)sset->user_addr; + size = (size_t)sset->size; + + map = kbasep_find_enclosing_cpu_mapping_of_region(reg, start, size); + if (!map) { + dev_warn(kctx->kbdev->dev, "Can't find CPU mapping 0x%016lX for VA 0x%016llX", start, sset->mem_handle); + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + offset = start & (PAGE_SIZE - 1); + page_off = map->page_off + ((start - map->vm_start) >> PAGE_SHIFT); + page_count = (size + offset + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pa = kbase_get_phy_pages(reg); + + /* Sync first page */ + if (pa[page_off]) { + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + + kbase_sync_single(kctx, pa[page_off] + offset, sz, sync_fn); + } + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + /* we grow upwards, so bail on first non-present page */ + if (!pa[page_off + i]) + break; + + kbase_sync_single(kctx, pa[page_off + i], PAGE_SIZE, sync_fn); + } + + /* Sync last page (if any) */ + if (page_count > 1 && pa[page_off + page_count - 1]) { + size_t sz = ((start + size - 1) & ~PAGE_MASK) + 1; + + kbase_sync_single(kctx, pa[page_off + page_count - 1], sz, + sync_fn); + } + +out_unlock: + kbase_gpu_vm_unlock(kctx); + kbase_os_mem_map_unlock(kctx); + return err; +} + +mali_error kbase_sync_now(struct kbase_context *kctx, struct base_syncset *syncset) +{ + mali_error err = MALI_ERROR_FUNCTION_FAILED; + struct basep_syncset *sset; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != syncset); + + sset = &syncset->basep_sset; + + switch (sset->type) { + case BASE_SYNCSET_OP_MSYNC: + err = kbase_do_syncset(kctx, syncset, dma_sync_single_for_device); + break; + + case BASE_SYNCSET_OP_CSYNC: + err = kbase_do_syncset(kctx, syncset, dma_sync_single_for_cpu); + break; + + default: + dev_warn(kctx->kbdev->dev, "Unknown msync op %d\n", sset->type); + break; + } + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_sync_now) + +/* vm lock must be held */ +mali_error kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *reg) +{ + mali_error err; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != reg); + BUG_ON(!mutex_is_locked(&kctx->reg_lock)); + err = kbase_gpu_munmap(kctx, reg); + if (err) { + dev_warn(reg->kctx->kbdev->dev, "Could not unmap from the GPU...\n"); + goto out; + } + + if (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_6367)) { + /* Wait for GPU to flush write buffer before freeing physical pages */ + kbase_wait_write_flush(kctx); + } + + /* This will also free the physical pages */ + kbase_free_alloced_region(reg); + + out: + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mem_free_region) + +/** + * @brief Free the region from the GPU and unregister it. + * + * This function implements the free operation on a memory segment. + * It will loudly fail if called with outstanding mappings. + */ +mali_error kbase_mem_free(struct kbase_context *kctx, mali_addr64 gpu_addr) +{ + mali_error err = MALI_ERROR_NONE; + struct kbase_va_region *reg; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + if (0 == gpu_addr) { + dev_warn(kctx->kbdev->dev, "gpu_addr 0 is reserved for the ringbuffer and it's an error to try to free it using kbase_mem_free\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + kbase_gpu_vm_lock(kctx); + + if (gpu_addr >= BASE_MEM_COOKIE_BASE && + gpu_addr < BASE_MEM_FIRST_FREE_ADDRESS) { + int cookie = PFN_DOWN(gpu_addr - BASE_MEM_COOKIE_BASE); + + reg = kctx->pending_regions[cookie]; + if (!reg) { + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + /* ask to unlink the cookie as we'll free it */ + + kctx->pending_regions[cookie] = NULL; + kctx->cookies |= (1UL << cookie); + + kbase_free_alloced_region(reg); + } else { + /* A real GPU va */ + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) { + dev_warn(kctx->kbdev->dev, "kbase_mem_free called with nonexistent gpu_addr 0x%llX", + gpu_addr); + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + if ((reg->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_SAME_VA) { + /* SAME_VA must be freed through munmap */ + dev_warn(kctx->kbdev->dev, "%s called on SAME_VA memory 0x%llX", __func__, + gpu_addr); + err = MALI_ERROR_FUNCTION_FAILED; + goto out_unlock; + } + + err = kbase_mem_free_region(kctx, reg); + } + + out_unlock: + kbase_gpu_vm_unlock(kctx); + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mem_free) + +void kbase_update_region_flags(struct kbase_va_region *reg, unsigned long flags) +{ + KBASE_DEBUG_ASSERT(NULL != reg); + KBASE_DEBUG_ASSERT((flags & ~((1ul << BASE_MEM_FLAGS_NR_BITS) - 1)) == 0); + + reg->flags |= kbase_cache_enabled(flags, reg->nr_pages); + /* all memory is now growable */ + reg->flags |= KBASE_REG_GROWABLE; + + if (flags & BASE_MEM_GROW_ON_GPF) + reg->flags |= KBASE_REG_PF_GROW; + + if (flags & BASE_MEM_PROT_CPU_WR) + reg->flags |= KBASE_REG_CPU_WR; + + if (flags & BASE_MEM_PROT_CPU_RD) + reg->flags |= KBASE_REG_CPU_RD; + + if (flags & BASE_MEM_PROT_GPU_WR) + reg->flags |= KBASE_REG_GPU_WR; + + if (flags & BASE_MEM_PROT_GPU_RD) + reg->flags |= KBASE_REG_GPU_RD; + + if (0 == (flags & BASE_MEM_PROT_GPU_EX)) + reg->flags |= KBASE_REG_GPU_NX; + + if (flags & BASE_MEM_COHERENT_LOCAL) + reg->flags |= KBASE_REG_SHARE_IN; + else if (flags & BASE_MEM_COHERENT_SYSTEM) + reg->flags |= KBASE_REG_SHARE_BOTH; +} +KBASE_EXPORT_TEST_API(kbase_update_region_flags) + +int kbase_alloc_phy_pages_helper( + struct kbase_mem_phy_alloc *alloc, + size_t nr_pages_requested) +{ + int curr; + int peak; + + KBASE_DEBUG_ASSERT(alloc); + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_NATIVE); + KBASE_DEBUG_ASSERT(alloc->imported.kctx); + + if (nr_pages_requested == 0) + goto done; /*nothing to do*/ + + kbase_atomic_add_pages(nr_pages_requested, &alloc->imported.kctx->used_pages); + kbase_atomic_add_pages(nr_pages_requested, &alloc->imported.kctx->kbdev->memdev.used_pages); + + kbase_atomic_add_pages(nr_pages_requested, &g_mtk_gpu_total_memory_usage_in_pages); + + /* Increase mm counters before we allocate pages so that this + * allocation is visible to the OOM killer */ + kbase_process_page_usage_inc(alloc->imported.kctx, nr_pages_requested); + + curr = atomic_read(&g_mtk_gpu_total_memory_usage_in_pages); + peak = atomic_read(&g_mtk_gpu_peak_memory_usage_in_pages); + if (curr > peak) + atomic_set(&g_mtk_gpu_peak_memory_usage_in_pages, curr); + + if (MALI_ERROR_NONE != kbase_mem_allocator_alloc(&alloc->imported.kctx->osalloc, nr_pages_requested, alloc->pages + alloc->nents)) + goto no_alloc; + + alloc->nents += nr_pages_requested; + +done: + return 0; + +no_alloc: + kbase_process_page_usage_dec(alloc->imported.kctx, nr_pages_requested); + kbase_atomic_sub_pages(nr_pages_requested, &alloc->imported.kctx->used_pages); + kbase_atomic_sub_pages(nr_pages_requested, &alloc->imported.kctx->kbdev->memdev.used_pages); + + kbase_atomic_sub_pages(nr_pages_requested, &g_mtk_gpu_total_memory_usage_in_pages); + + return -ENOMEM; +} + +int kbase_free_phy_pages_helper( + struct kbase_mem_phy_alloc *alloc, + size_t nr_pages_to_free) +{ + mali_bool syncback; + phys_addr_t *start_free; + + KBASE_DEBUG_ASSERT(alloc); + KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_NATIVE); + KBASE_DEBUG_ASSERT(alloc->imported.kctx); + KBASE_DEBUG_ASSERT(alloc->nents >= nr_pages_to_free); + + /* early out if nothing to do */ + if (0 == nr_pages_to_free) + return 0; + + start_free = alloc->pages + alloc->nents - nr_pages_to_free; + + syncback = (alloc->properties & KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED) ? MALI_TRUE : MALI_FALSE; + + kbase_mem_allocator_free(&alloc->imported.kctx->osalloc, + nr_pages_to_free, + start_free, + syncback); + + alloc->nents -= nr_pages_to_free; + kbase_process_page_usage_dec(alloc->imported.kctx, nr_pages_to_free); + kbase_atomic_sub_pages(nr_pages_to_free, &alloc->imported.kctx->used_pages); + kbase_atomic_sub_pages(nr_pages_to_free, &alloc->imported.kctx->kbdev->memdev.used_pages); + + kbase_atomic_sub_pages(nr_pages_to_free, &g_mtk_gpu_total_memory_usage_in_pages); + + return 0; +} + +void kbase_mem_kref_free(struct kref *kref) +{ + struct kbase_mem_phy_alloc *alloc; + + alloc = container_of(kref, struct kbase_mem_phy_alloc, kref); + + switch (alloc->type) { + case KBASE_MEM_TYPE_NATIVE: { + KBASE_DEBUG_ASSERT(alloc->imported.kctx); + kbase_free_phy_pages_helper(alloc, alloc->nents); + break; + } + case KBASE_MEM_TYPE_ALIAS: { + /* just call put on the underlying phy allocs */ + size_t i; + struct kbase_aliased *aliased; + + aliased = alloc->imported.alias.aliased; + if (aliased) { + for (i = 0; i < alloc->imported.alias.nents; i++) + if (aliased[i].alloc) + kbase_mem_phy_alloc_put(aliased[i].alloc); + vfree(aliased); + } + break; + } + case KBASE_MEM_TYPE_RAW: + /* raw pages, external cleanup */ + break; + #ifdef CONFIG_UMP + case KBASE_MEM_TYPE_IMPORTED_UMP: + ump_dd_release(alloc->imported.ump_handle); + break; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: + dma_buf_detach(alloc->imported.umm.dma_buf, + alloc->imported.umm.dma_attachment); + dma_buf_put(alloc->imported.umm.dma_buf); + break; +#endif + case KBASE_MEM_TYPE_TB:{ + void *tb; + + tb = alloc->imported.kctx->jctx.tb; + kbase_device_trace_buffer_uninstall(alloc->imported.kctx); + vfree(tb); + break; + } + default: + WARN(1, "Unexecpted free of type %d\n", alloc->type); + break; + } + + /* Free based on allocation type */ + if (alloc->properties & KBASE_MEM_PHY_ALLOC_LARGE) + vfree(alloc); + else + kfree(alloc); +} + +KBASE_EXPORT_TEST_API(kbase_mem_kref_free); + +int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size) +{ + KBASE_DEBUG_ASSERT(NULL != reg); + KBASE_DEBUG_ASSERT(vsize > 0); + + /* validate user provided arguments */ + if (size > vsize || vsize > reg->nr_pages) + goto out_term; + + /* Prevent vsize*sizeof from wrapping around. + * For instance, if vsize is 2**29+1, we'll allocate 1 byte and the alloc won't fail. + */ + if ((size_t) vsize > ((size_t) -1 / sizeof(*reg->alloc->pages))) + goto out_term; + + KBASE_DEBUG_ASSERT(0 != vsize); + + if (MALI_ERROR_NONE != kbase_alloc_phy_pages_helper(reg->alloc, size)) + goto out_term; + + return 0; + + out_term: + return -1; +} + +KBASE_EXPORT_TEST_API(kbase_alloc_phy_pages) + +mali_bool kbase_check_alloc_flags(unsigned long flags) +{ + /* Only known flags should be set. */ + if (flags & ~((1ul << BASE_MEM_FLAGS_NR_INPUT_BITS) - 1)) + return MALI_FALSE; + + /* At least one flag should be set */ + if (flags == 0) + return MALI_FALSE; + + /* Either the GPU or CPU must be reading from the allocated memory */ + if ((flags & (BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD)) == 0) + return MALI_FALSE; + + /* Either the GPU or CPU must be writing to the allocated memory */ + if ((flags & (BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR)) == 0) + return MALI_FALSE; + + /* GPU cannot be writing to GPU executable memory and cannot grow the memory on page fault. */ + if ((flags & BASE_MEM_PROT_GPU_EX) && (flags & (BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF))) + return MALI_FALSE; + + /* GPU should have at least read or write access otherwise there is no + reason for allocating. */ + if ((flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR)) == 0) + return MALI_FALSE; + + return MALI_TRUE; +} + +/** + * @brief Acquire the per-context region list lock + */ +void kbase_gpu_vm_lock(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + mutex_lock(&kctx->reg_lock); +} + +KBASE_EXPORT_TEST_API(kbase_gpu_vm_lock) + +/** + * @brief Release the per-context region list lock + */ +void kbase_gpu_vm_unlock(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + mutex_unlock(&kctx->reg_lock); +} + +KBASE_EXPORT_TEST_API(kbase_gpu_vm_unlock) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.h new file mode 100644 index 0000000000000000000000000000000000000000..9e982924af513e4dae430ef9e584c38ddc85fbc6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem.h @@ -0,0 +1,699 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem.h + * Base kernel memory APIs + */ + +#ifndef _KBASE_MEM_H_ +#define _KBASE_MEM_H_ + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +#include +#include + +#ifdef CONFIG_UMP +#include +#endif /* CONFIG_UMP */ +#include "mali_base_kernel.h" +#include +#include "mali_kbase_pm.h" +#include "mali_kbase_defs.h" +#ifdef CONFIG_MALI_GATOR_SUPPORT +#include "mali_kbase_gator.h" +#endif /*CONFIG_MALI_GATOR_SUPPORT*/ + +/* Part of the workaround for uTLB invalid pages is to ensure we grow/shrink tmem by 4 pages at a time */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_8316 (2) /* round to 4 pages */ + +/* Part of the workaround for PRLAM-9630 requires us to grow/shrink memory by 8 pages. +The MMU reads in 8 page table entries from memory at a time, if we have more than one page fault within the same 8 pages and +page tables are updated accordingly, the MMU does not re-read the page table entries from memory for the subsequent page table +updates and generates duplicate page faults as the page table information used by the MMU is not valid. */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_9630 (3) /* round to 8 pages */ + +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2 (0) /* round to 1 page */ + +/* This must always be a power of 2 */ +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2) +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_HW_ISSUE_8316 (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_8316) +#define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_HW_ISSUE_9630 (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_9630) +/** + * A CPU mapping + */ +typedef struct kbase_cpu_mapping { + struct list_head mappings_list; + struct kbase_mem_phy_alloc *alloc; + struct kbase_context *kctx; + struct kbase_va_region *region; + pgoff_t page_off; + int count; + unsigned long vm_start; + unsigned long vm_end; +} kbase_cpu_mapping; + +enum kbase_memory_type { + KBASE_MEM_TYPE_NATIVE, + KBASE_MEM_TYPE_IMPORTED_UMP, + KBASE_MEM_TYPE_IMPORTED_UMM, + KBASE_MEM_TYPE_ALIAS, + KBASE_MEM_TYPE_TB, + KBASE_MEM_TYPE_RAW +}; + +/* internal structure, mirroring base_mem_aliasing_info, + * but with alloc instead of a gpu va (handle) */ +struct kbase_aliased { + struct kbase_mem_phy_alloc *alloc; /* NULL for special, non-NULL for native */ + u64 offset; /* in pages */ + u64 length; /* in pages */ +}; + +/** + * @brief Physical pages tracking object properties + */ +#define KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED (1ul << 0) +#define KBASE_MEM_PHY_ALLOC_LARGE (1ul << 1) + +/* physical pages tracking object. + * Set up to track N pages. + * N not stored here, the creator holds that info. + * This object only tracks how many elements are actually valid (present). + * Changing of nents or *pages should only happen if the kbase_mem_phy_alloc is not + * shared with another region or client. CPU mappings are OK to exist when changing, as + * long as the tracked mappings objects are updated as part of the change. + */ +struct kbase_mem_phy_alloc +{ + struct kref kref; /* number of users of this alloc */ + atomic_t gpu_mappings; + size_t nents; /* 0..N */ + phys_addr_t * pages; /* N elements, only 0..nents are valid */ + + /* kbase_cpu_mappings */ + struct list_head mappings; + + /* type of buffer */ + enum kbase_memory_type type; + + unsigned long properties; + + /* member in union valid based on @a type */ + union { +#ifdef CONFIG_UMP + ump_dd_handle ump_handle; +#endif /* CONFIG_UMP */ +#if defined(CONFIG_DMA_SHARED_BUFFER) + struct { + struct dma_buf *dma_buf; + struct dma_buf_attachment *dma_attachment; + unsigned int current_mapping_usage_count; + struct sg_table *sgt; + } umm; +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ + struct { + mali_size64 stride; + size_t nents; + struct kbase_aliased *aliased; + } alias; + /* Used by type = (KBASE_MEM_TYPE_NATIVE, KBASE_MEM_TYPE_TB) */ + struct kbase_context *kctx; + } imported; +}; + +static inline void kbase_mem_phy_alloc_gpu_mapped(struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(alloc); + /* we only track mappings of NATIVE buffers */ + if (alloc->type == KBASE_MEM_TYPE_NATIVE) + atomic_inc(&alloc->gpu_mappings); +} + +static inline void kbase_mem_phy_alloc_gpu_unmapped(struct kbase_mem_phy_alloc *alloc) +{ + KBASE_DEBUG_ASSERT(alloc); + /* we only track mappings of NATIVE buffers */ + if (alloc->type == KBASE_MEM_TYPE_NATIVE) + if (0 > atomic_dec_return(&alloc->gpu_mappings)) { + pr_err("Mismatched %s:\n", __func__); + dump_stack(); + } +} + +void kbase_mem_kref_free(struct kref * kref); + +mali_error kbase_mem_init(struct kbase_device * kbdev); +void kbase_mem_halt(struct kbase_device * kbdev); +void kbase_mem_term(struct kbase_device * kbdev); + +static inline struct kbase_mem_phy_alloc * kbase_mem_phy_alloc_get(struct kbase_mem_phy_alloc * alloc) +{ + kref_get(&alloc->kref); + return alloc; +} + +static inline struct kbase_mem_phy_alloc * kbase_mem_phy_alloc_put(struct kbase_mem_phy_alloc * alloc) +{ + kref_put(&alloc->kref, kbase_mem_kref_free); + return NULL; +} + +/** + * A GPU memory region, and attributes for CPU mappings. + */ +typedef struct kbase_va_region { + struct rb_node rblink; + struct list_head link; + + struct kbase_context *kctx; /* Backlink to base context */ + + u64 start_pfn; /* The PFN in GPU space */ + size_t nr_pages; + +/* Free region */ +#define KBASE_REG_FREE (1ul << 0) +/* CPU write access */ +#define KBASE_REG_CPU_WR (1ul << 1) +/* GPU write access */ +#define KBASE_REG_GPU_WR (1ul << 2) +/* No eXecute flag */ +#define KBASE_REG_GPU_NX (1ul << 3) +/* Is CPU cached? */ +#define KBASE_REG_CPU_CACHED (1ul << 4) +/* Is GPU cached? */ +#define KBASE_REG_GPU_CACHED (1ul << 5) + +#define KBASE_REG_GROWABLE (1ul << 6) +/* Can grow on pf? */ +#define KBASE_REG_PF_GROW (1ul << 7) + +/* VA managed by us */ +#define KBASE_REG_CUSTOM_VA (1ul << 8) + +/* inner shareable coherency */ +#define KBASE_REG_SHARE_IN (1ul << 9) +/* inner & outer shareable coherency */ +#define KBASE_REG_SHARE_BOTH (1ul << 10) + +/* Space for 4 different zones */ +#define KBASE_REG_ZONE_MASK (3ul << 11) +#define KBASE_REG_ZONE(x) (((x) & 3) << 11) + +/* GPU read access */ +#define KBASE_REG_GPU_RD (1ul<<13) +/* CPU read access */ +#define KBASE_REG_CPU_RD (1ul<<14) + +/* Aligned for GPU EX in SAME_VA */ +#define KBASE_REG_ALIGNED (1ul<<15) + +/* Index of chosen MEMATTR for this region (0..7) */ +#define KBASE_REG_MEMATTR_MASK (7ul << 16) +#define KBASE_REG_MEMATTR_INDEX(x) (((x) & 7) << 16) +#define KBASE_REG_MEMATTR_VALUE(x) (((x) & KBASE_REG_MEMATTR_MASK) >> 16) + +#define KBASE_REG_ZONE_SAME_VA KBASE_REG_ZONE(0) + +/* only used with 32-bit clients */ +/* + * On a 32bit platform, custom VA should be wired from (4GB + shader region) + * to the VA limit of the GPU. Unfortunately, the Linux mmap() interface + * limits us to 2^32 pages (2^44 bytes, see mmap64 man page for reference). + * So we put the default limit to the maximum possible on Linux and shrink + * it down, if required by the GPU, during initialization. + */ +#define KBASE_REG_ZONE_EXEC KBASE_REG_ZONE(1) /* Dedicated 16MB region for shader code */ +#define KBASE_REG_ZONE_EXEC_BASE ((1ULL << 32) >> PAGE_SHIFT) +#define KBASE_REG_ZONE_EXEC_SIZE ((16ULL * 1024 * 1024) >> PAGE_SHIFT) + +#define KBASE_REG_ZONE_CUSTOM_VA KBASE_REG_ZONE(2) +#define KBASE_REG_ZONE_CUSTOM_VA_BASE (KBASE_REG_ZONE_EXEC_BASE + KBASE_REG_ZONE_EXEC_SIZE) /* Starting after KBASE_REG_ZONE_EXEC */ +#define KBASE_REG_ZONE_CUSTOM_VA_SIZE (((1ULL << 44) >> PAGE_SHIFT) - KBASE_REG_ZONE_CUSTOM_VA_BASE) +/* end 32-bit clients only */ + + unsigned long flags; + + size_t extent; /* nr of pages alloc'd on PF */ + + struct kbase_mem_phy_alloc * alloc; /* the one alloc object we mmap to the GPU and CPU when mapping this region */ + + /* non-NULL if this memory object is a kds_resource */ + struct kds_resource *kds_res; + +} kbase_va_region; + +/* Common functions */ +static INLINE phys_addr_t *kbase_get_phy_pages(struct kbase_va_region *reg) +{ + KBASE_DEBUG_ASSERT(reg); + KBASE_DEBUG_ASSERT(reg->alloc); + + return reg->alloc->pages; +} + +static INLINE size_t kbase_reg_current_backed_size(struct kbase_va_region * reg) +{ + KBASE_DEBUG_ASSERT(reg); + /* if no alloc object the backed size naturally is 0 */ + if (reg->alloc) + return reg->alloc->nents; + else + return 0; +} + +#define KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD ((size_t)(4*1024)) /* size above which vmalloc is used over kmalloc */ + +static INLINE struct kbase_mem_phy_alloc * kbase_alloc_create(size_t nr_pages, enum kbase_memory_type type) +{ + struct kbase_mem_phy_alloc *alloc; + const size_t alloc_size = + sizeof(*alloc) + sizeof(*alloc->pages) * nr_pages; + + /* Prevent nr_pages*sizeof + sizeof(*alloc) from wrapping around. */ + if (nr_pages > ((((size_t) -1) - sizeof(*alloc)) + / sizeof(*alloc->pages))) + return ERR_PTR(-ENOMEM); + + /* Allocate based on the size to reduce internal fragmentation of vmem */ + if (alloc_size > KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD) + alloc = vzalloc(alloc_size); + else + alloc = kzalloc(alloc_size, GFP_KERNEL); + + if (!alloc) + return ERR_PTR(-ENOMEM); + + /* Store allocation method */ + if (alloc_size > KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD) + alloc->properties |= KBASE_MEM_PHY_ALLOC_LARGE; + + kref_init(&alloc->kref); + atomic_set(&alloc->gpu_mappings, 0); + alloc->nents = 0; + alloc->pages = (void*)(alloc + 1); + INIT_LIST_HEAD(&alloc->mappings); + alloc->type = type; + + return alloc; +} + +static INLINE int kbase_reg_prepare_native(struct kbase_va_region * reg, struct kbase_context * kctx) +{ + KBASE_DEBUG_ASSERT(reg); + KBASE_DEBUG_ASSERT(!reg->alloc); + KBASE_DEBUG_ASSERT(reg->flags & KBASE_REG_FREE); + + reg->alloc = kbase_alloc_create(reg->nr_pages, KBASE_MEM_TYPE_NATIVE); + if (IS_ERR(reg->alloc)) + return PTR_ERR(reg->alloc); + else if (!reg->alloc) + return -ENOMEM; + reg->alloc->imported.kctx = kctx; + reg->flags &= ~KBASE_REG_FREE; + return 0; +} + +static inline int kbase_atomic_add_pages(int num_pages, atomic_t *used_pages) +{ + int new_val = atomic_add_return(num_pages, used_pages); +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_total_alloc_pages_change((long long int)new_val); +#endif + return new_val; +} + +static inline int kbase_atomic_sub_pages(int num_pages, atomic_t *used_pages) +{ + int new_val = atomic_sub_return(num_pages, used_pages); +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_total_alloc_pages_change((long long int)new_val); +#endif + return new_val; +} + +/** + * @brief Initialize low-level memory access for a kbase device + * + * Performs any low-level setup needed for a kbase device to access memory on + * the device. + * + * @param kbdev kbase device to initialize memory access for + * @return 0 on success, Linux error code on failure + */ +int kbase_mem_lowlevel_init(struct kbase_device *kbdev); + + +/** + * @brief Terminate low-level memory access for a kbase device + * + * Perform any low-level cleanup needed to clean + * after @ref kbase_mem_lowlevel_init + * + * @param kbdev kbase device to clean up for + */ +void kbase_mem_lowlevel_term(struct kbase_device *kbdev); + +/** + * @brief Initialize an OS based memory allocator. + * + * Initializes a allocator. + * Must be called before any allocation is attempted. + * \a kbase_mem_allocator_alloc and \a kbase_mem_allocator_free is used + * to allocate and free memory. + * \a kbase_mem_allocator_term must be called to clean up the allocator. + * All memory obtained via \a kbase_mem_allocator_alloc must have been + * \a kbase_mem_allocator_free before \a kbase_mem_allocator_term is called. + * + * @param allocator Allocator object to initialize + * @param max_size Maximum number of pages to keep on the freelist. + * @param kbdev The kbase device this allocator is used with + * @return MALI_ERROR_NONE on success, an error code indicating what failed on + * error. + */ +mali_error kbase_mem_allocator_init(struct kbase_mem_allocator *allocator, + unsigned int max_size, + struct kbase_device *kbdev); + +/** + * @brief Allocate memory via an OS based memory allocator. + * + * @param[in] allocator Allocator to obtain the memory from + * @param nr_pages Number of pages to allocate + * @param[out] pages Pointer to an array where the physical address of the allocated pages will be stored + * @return MALI_ERROR_NONE if the pages were allocated, an error code indicating what failed on error + */ +mali_error kbase_mem_allocator_alloc(struct kbase_mem_allocator * allocator, size_t nr_pages, phys_addr_t *pages); + +/** + * @brief Free memory obtained for an OS based memory allocator. + * + * @param[in] allocator Allocator to free the memory back to + * @param nr_pages Number of pages to free + * @param[in] pages Pointer to an array holding the physical address of the paghes to free. + * @param[in] sync_back MALI_TRUE case the memory should be synced back + */ +void kbase_mem_allocator_free(struct kbase_mem_allocator * allocator, size_t nr_pages, phys_addr_t *pages, mali_bool sync_back); + +/** + * @brief Terminate an OS based memory allocator. + * + * Frees all cached allocations and clean up internal state. + * All allocate pages must have been \a kbase_mem_allocator_free before + * this function is called. + * + * @param[in] allocator Allocator to terminate + */ +void kbase_mem_allocator_term(struct kbase_mem_allocator * allocator); + + + +mali_error kbase_region_tracker_init(struct kbase_context *kctx); +void kbase_region_tracker_term(struct kbase_context *kctx); + +struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(struct kbase_context *kctx, mali_addr64 gpu_addr); + +/** + * @brief Check that a pointer is actually a valid region. + * + * Must be called with context lock held. + */ +struct kbase_va_region *kbase_region_tracker_find_region_base_address(struct kbase_context *kctx, mali_addr64 gpu_addr); + +struct kbase_va_region *kbase_alloc_free_region(struct kbase_context *kctx, u64 start_pfn, size_t nr_pages, int zone); +void kbase_free_alloced_region(struct kbase_va_region *reg); +mali_error kbase_add_va_region(struct kbase_context *kctx, struct kbase_va_region *reg, mali_addr64 addr, size_t nr_pages, size_t align); + +mali_error kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, mali_addr64 addr, size_t nr_pages, size_t align); +mali_bool kbase_check_alloc_flags(unsigned long flags); +void kbase_update_region_flags(struct kbase_va_region *reg, unsigned long flags); + +void kbase_gpu_vm_lock(struct kbase_context *kctx); +void kbase_gpu_vm_unlock(struct kbase_context *kctx); + +int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size); + +mali_error kbase_mmu_init(struct kbase_context *kctx); +void kbase_mmu_term(struct kbase_context *kctx); + +phys_addr_t kbase_mmu_alloc_pgd(struct kbase_context *kctx); +void kbase_mmu_free_pgd(struct kbase_context *kctx); +mali_error kbase_mmu_insert_pages(struct kbase_context *kctx, u64 vpfn, + phys_addr_t *phys, size_t nr, + unsigned long flags); +mali_error kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, + phys_addr_t phys, size_t nr, + unsigned long flags); + +mali_error kbase_mmu_teardown_pages(struct kbase_context *kctx, u64 vpfn, size_t nr); +mali_error kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, phys_addr_t* phys, size_t nr, unsigned long flags); + +/** + * @brief Register region and map it on the GPU. + * + * Call kbase_add_va_region() and map the region on the GPU. + */ +mali_error kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, mali_addr64 addr, size_t nr_pages, size_t align); + +/** + * @brief Remove the region from the GPU and unregister it. + * + * Must be called with context lock held. + */ +mali_error kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg); + +/** + * The caller has the following locking conditions: + * - It must hold kbase_as::transaction_mutex on kctx's address space + * - It must hold the kbasep_js_device_data::runpool_irq::lock + */ +void kbase_mmu_update(struct kbase_context *kctx); + +/** + * The caller has the following locking conditions: + * - It must hold kbase_as::transaction_mutex on kctx's address space + * - It must hold the kbasep_js_device_data::runpool_irq::lock + */ +void kbase_mmu_disable(struct kbase_context *kctx); + +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat); + +/** Dump the MMU tables to a buffer + * + * This function allocates a buffer (of @c nr_pages pages) to hold a dump of the MMU tables and fills it. If the + * buffer is too small then the return value will be NULL. + * + * The GPU vm lock must be held when calling this function. + * + * The buffer returned should be freed with @ref vfree when it is no longer required. + * + * @param[in] kctx The kbase context to dump + * @param[in] nr_pages The number of pages to allocate for the buffer. + * + * @return The address of the buffer containing the MMU dump or NULL on error (including if the @c nr_pages is too + * small) + */ +void *kbase_mmu_dump(struct kbase_context *kctx, int nr_pages); + +mali_error kbase_sync_now(struct kbase_context *kctx, struct base_syncset *syncset); +void kbase_sync_single(struct kbase_context *kctx, phys_addr_t pa, + size_t size, kbase_sync_kmem_fn sync_fn); +void kbase_pre_job_sync(struct kbase_context *kctx, struct base_syncset *syncsets, size_t nr); +void kbase_post_job_sync(struct kbase_context *kctx, struct base_syncset *syncsets, size_t nr); + +/** + * Set attributes for imported tmem region + * + * This function sets (extends with) requested attributes for given region + * of imported external memory + * + * @param[in] kctx The kbase context which the tmem belongs to + * @param[in] gpu_addr The base address of the tmem region + * @param[in] attributes The attributes of tmem region to be set + * + * @return MALI_ERROR_NONE on success. Any other value indicates failure. + */ +mali_error kbase_tmem_set_attributes(struct kbase_context *kctx, mali_addr64 gpu_addr, u32 attributes); + +/** + * Get attributes of imported tmem region + * + * This function retrieves the attributes of imported external memory + * + * @param[in] kctx The kbase context which the tmem belongs to + * @param[in] gpu_addr The base address of the tmem region + * @param[out] attributes The actual attributes of tmem region + * + * @return MALI_ERROR_NONE on success. Any other value indicates failure. + */ +mali_error kbase_tmem_get_attributes(struct kbase_context *kctx, mali_addr64 gpu_addr, u32 * const attributes); + +/* OS specific functions */ +mali_error kbase_mem_free(struct kbase_context *kctx, mali_addr64 gpu_addr); +mali_error kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *reg); +void kbase_os_mem_map_lock(struct kbase_context *kctx); +void kbase_os_mem_map_unlock(struct kbase_context *kctx); + +/** + * @brief Update the memory allocation counters for the current process + * + * OS specific call to updates the current memory allocation counters for the current process with + * the supplied delta. + * + * @param[in] kctx The kbase context + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +void kbasep_os_process_page_usage_update(struct kbase_context *kctx, int pages); + +/** + * @brief Add to the memory allocation counters for the current process + * + * OS specific call to add to the current memory allocation counters for the current process by + * the supplied amount. + * + * @param[in] kctx The kernel base context used for the allocation. + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +static INLINE void kbase_process_page_usage_inc(struct kbase_context *kctx, int pages) +{ + kbasep_os_process_page_usage_update(kctx, pages); +} + +/** + * @brief Subtract from the memory allocation counters for the current process + * + * OS specific call to subtract from the current memory allocation counters for the current process by + * the supplied amount. + * + * @param[in] kctx The kernel base context used for the allocation. + * @param[in] pages The desired delta to apply to the memory usage counters. + */ + +static INLINE void kbase_process_page_usage_dec(struct kbase_context *kctx, int pages) +{ + kbasep_os_process_page_usage_update(kctx, 0 - pages); +} + +/** + * @brief Find the offset of the CPU mapping of a memory allocation containing + * a given address range + * + * Searches for a CPU mapping of any part of the region starting at @p gpu_addr + * that fully encloses the CPU virtual address range specified by @p uaddr and + * @p size. Returns a failure indication if only part of the address range lies + * within a CPU mapping, or the address range lies within a CPU mapping of a + * different region. + * + * @param[in,out] kctx The kernel base context used for the allocation. + * @param[in] gpu_addr GPU address of the start of the allocated region + * within which to search. + * @param[in] uaddr Start of the CPU virtual address range. + * @param[in] size Size of the CPU virtual address range (in bytes). + * @param[out] offset The offset from the start of the allocation to the + * specified CPU virtual address. + * + * @return MALI_ERROR_NONE if offset was obtained successfully. Error code + * otherwise. + */ +mali_error kbasep_find_enclosing_cpu_mapping_offset(struct kbase_context *kctx, + mali_addr64 gpu_addr, + unsigned long uaddr, + size_t size, + mali_size64 *offset); + +enum hrtimer_restart kbasep_as_poke_timer_callback(struct hrtimer *timer); +void kbase_as_poking_timer_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); +void kbase_as_poking_timer_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom); + +/** +* @brief Allocates physical pages. +* +* Allocates \a nr_pages_requested and updates the alloc object. +* +* @param[in] alloc allocation object to add pages to +* @param[in] nr_pages_requested number of physical pages to allocate +* +* @return 0 if all pages have been successfully allocated. Error code otherwise +*/ +int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc * alloc, size_t nr_pages_requested); + +/** +* @brief Free physical pages. +* +* Frees \a nr_pages and updates the alloc object. +* +* @param[in] alloc allocation object to free pages from +* @param[in] nr_pages_to_free number of physical pages to free +*/ +int kbase_free_phy_pages_helper(struct kbase_mem_phy_alloc * alloc, size_t nr_pages_to_free); + +#ifdef CONFIG_MALI_NO_MALI +static inline void kbase_wait_write_flush(struct kbase_context *kctx) +{ +} +#else +void kbase_wait_write_flush(struct kbase_context *kctx); +#endif + +static inline void kbase_set_dma_addr(struct page *p, dma_addr_t dma_addr) +{ + SetPagePrivate(p); + if (sizeof(dma_addr_t) > sizeof(p->private)) { + /* on 32-bit ARM with LPAE dma_addr_t becomes larger, but the + * private filed stays the same. So we have to be clever and + * use the fact that we only store DMA addresses of whole pages, + * so the low bits should be zero */ + KBASE_DEBUG_ASSERT(!(dma_addr & (PAGE_SIZE - 1))); + set_page_private(p, dma_addr >> PAGE_SHIFT); + } else { + set_page_private(p, dma_addr); + } +} + +static inline dma_addr_t kbase_dma_addr(struct page *p) +{ + if (sizeof(dma_addr_t) > sizeof(p->private)) + return ((dma_addr_t)page_private(p)) << PAGE_SHIFT; + + return (dma_addr_t)page_private(p); +} + +/** +* @brief Process a bus or page fault. +* +* This function will process a fault on a specific address space +* +* @param[in] kbdev The @ref kbase_device the fault happened on +* @param[in] kctx The @ref kbase_context for the faulting address space if +* one was found. +* @param[in] as The address space that has the fault +*/ +void kbase_mmu_interrupt_process(struct kbase_device *kbdev, + struct kbase_context *kctx, struct kbase_as *as); + +int kbase_report_gpu_memory_usage(); + +int kbase_report_gpu_memory_peak(); + +#endif /* _KBASE_MEM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..248eb549f5205d0b4a82569f6050eabf6183f991 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.c @@ -0,0 +1,304 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem.c + * Base kernel memory APIs + */ +#include +#include +#include +#include +#include +#include +#include + +int kbase_mem_lowlevel_init(struct kbase_device *kbdev) +{ + return 0; +} + +void kbase_mem_lowlevel_term(struct kbase_device *kbdev) +{ + return; +} + +static unsigned long kbase_mem_allocator_count(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_mem_allocator *allocator; + + allocator = container_of(s, struct kbase_mem_allocator, free_list_reclaimer); + return atomic_read(&allocator->free_list_size); +} + +static unsigned long kbase_mem_allocator_scan(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_mem_allocator *allocator; + int i; + int freed; + + allocator = container_of(s, struct kbase_mem_allocator, free_list_reclaimer); + + might_sleep(); + + mutex_lock(&allocator->free_list_lock); + i = MIN(atomic_read(&allocator->free_list_size), sc->nr_to_scan); + freed = i; + + atomic_sub(i, &allocator->free_list_size); + + while (i--) { + struct page *p; + + BUG_ON(list_empty(&allocator->free_list_head)); + p = list_first_entry(&allocator->free_list_head, + struct page, lru); + list_del(&p->lru); + ClearPagePrivate(p); + __free_page(p); + } + mutex_unlock(&allocator->free_list_lock); + return atomic_read(&allocator->free_list_size); + +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) +static int kbase_mem_allocator_shrink(struct shrinker *s, + struct shrink_control *sc) +{ + if (sc->nr_to_scan == 0) + return kbase_mem_allocator_count(s, sc); + else + return kbase_mem_allocator_scan(s, sc); +} +#endif + +mali_error kbase_mem_allocator_init(struct kbase_mem_allocator *const allocator, + unsigned int max_size, struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(NULL != allocator); + KBASE_DEBUG_ASSERT(kbdev); + + INIT_LIST_HEAD(&allocator->free_list_head); + + allocator->kbdev = kbdev; + + mutex_init(&allocator->free_list_lock); + + atomic_set(&allocator->free_list_size, 0); + + allocator->free_list_max_size = max_size; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) + allocator->free_list_reclaimer.shrink = kbase_mem_allocator_shrink; +#else + allocator->free_list_reclaimer.count_objects = + kbase_mem_allocator_count; + allocator->free_list_reclaimer.scan_objects = kbase_mem_allocator_scan; +#endif + allocator->free_list_reclaimer.seeks = DEFAULT_SEEKS; + /* Kernel versions prior to 3.1 : + * struct shrinker does not define batch */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) + allocator->free_list_reclaimer.batch = 0; +#endif + + register_shrinker(&allocator->free_list_reclaimer); + + return MALI_ERROR_NONE; +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_init) + +void kbase_mem_allocator_term(struct kbase_mem_allocator *allocator) +{ + KBASE_DEBUG_ASSERT(NULL != allocator); + + unregister_shrinker(&allocator->free_list_reclaimer); + mutex_lock(&allocator->free_list_lock); + while (!list_empty(&allocator->free_list_head)) { + struct page *p; + + p = list_first_entry(&allocator->free_list_head, struct page, + lru); + list_del(&p->lru); + dma_unmap_page(allocator->kbdev->dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + __free_page(p); + } + atomic_set(&allocator->free_list_size, 0); + mutex_unlock(&allocator->free_list_lock); + mutex_destroy(&allocator->free_list_lock); +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_term) + +mali_error kbase_mem_allocator_alloc(struct kbase_mem_allocator *allocator, size_t nr_pages, phys_addr_t *pages) +{ + struct page *p; + void *mp; + int i; + int num_from_free_list; + struct list_head from_free_list = LIST_HEAD_INIT(from_free_list); + gfp_t gfp; + + might_sleep(); + + KBASE_DEBUG_ASSERT(NULL != allocator); + + /* take from the free list first */ + mutex_lock(&allocator->free_list_lock); + num_from_free_list = MIN(nr_pages, atomic_read(&allocator->free_list_size)); + atomic_sub(num_from_free_list, &allocator->free_list_size); + for (i = 0; i < num_from_free_list; i++) + { + BUG_ON(list_empty(&allocator->free_list_head)); + p = list_first_entry(&allocator->free_list_head, struct page, lru); + list_move(&p->lru, &from_free_list); + } + mutex_unlock(&allocator->free_list_lock); + i = 0; + + /* Allocate as many pages from the pool of already allocated pages. */ + list_for_each_entry(p, &from_free_list, lru) { + pages[i] = PFN_PHYS(page_to_pfn(p)); + i++; + } + + if (i == nr_pages) + return MALI_ERROR_NONE; + +#if defined(CONFIG_ARM) && !defined(CONFIG_HAVE_DMA_ATTRS) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) + /* DMA cache sync fails for HIGHMEM before 3.5 on ARM */ + gfp = GFP_USER; +#else + gfp = GFP_HIGHUSER; +#endif + + if (current->flags & PF_KTHREAD) { + /* Don't trigger OOM killer from kernel threads, e.g. when + * growing memory on GPU page fault */ + gfp |= __GFP_NORETRY; + } + + /* If not all pages were sourced from the pool, request new ones. */ + for (; i < nr_pages; i++) { + dma_addr_t dma_addr; + p = alloc_page(gfp); + if (NULL == p) + goto err_out_roll_back; + mp = kmap(p); + if (NULL == mp) { + __free_page(p); + goto err_out_roll_back; + } + memset(mp, 0x00, PAGE_SIZE); /* instead of __GFP_ZERO, so we can do cache maintenance */ + kunmap(p); + + dma_addr = dma_map_page(allocator->kbdev->dev, p, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(allocator->kbdev->dev, dma_addr)) { + __free_page(p); + goto err_out_roll_back; + } + + SetPagePrivate(p); + kbase_set_dma_addr(p, dma_addr); + pages[i] = PFN_PHYS(page_to_pfn(p)); + BUG_ON(dma_addr != pages[i]); + } + + return MALI_ERROR_NONE; + +err_out_roll_back: + while (i--) { + struct page *p; + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + dma_unmap_page(allocator->kbdev->dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + __free_page(p); + } + + return MALI_ERROR_OUT_OF_MEMORY; +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_alloc) + +void kbase_mem_allocator_free(struct kbase_mem_allocator *allocator, size_t nr_pages, phys_addr_t *pages, mali_bool sync_back) +{ + int i = 0; + int page_count = 0; + int tofree; + + LIST_HEAD(new_free_list_items); + + KBASE_DEBUG_ASSERT(NULL != allocator); + + might_sleep(); + + /* Starting by just freeing the overspill. + * As we do this outside of the lock we might spill too many pages + * or get too many on the free list, but the max_size is just a ballpark so it is ok + * providing that tofree doesn't exceed nr_pages + */ + tofree = MAX((int)allocator->free_list_max_size - atomic_read(&allocator->free_list_size), 0); + tofree = nr_pages - MIN(tofree, nr_pages); + for (; i < tofree; i++) { + if (likely(0 != pages[i])) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + dma_unmap_page(allocator->kbdev->dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + pages[i] = (phys_addr_t)0; + __free_page(p); + } + } + + for (; i < nr_pages; i++) { + if (likely(0 != pages[i])) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + /* Sync back the memory to ensure that future cache + * invalidations don't trample on memory. + */ + if (sync_back) + dma_sync_single_for_cpu(allocator->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + + list_add(&p->lru, &new_free_list_items); + page_count++; + } + } + mutex_lock(&allocator->free_list_lock); + list_splice(&new_free_list_items, &allocator->free_list_head); + atomic_add(page_count, &allocator->free_list_size); + mutex_unlock(&allocator->free_list_lock); +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_free) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.h new file mode 100644 index 0000000000000000000000000000000000000000..cb0e153b13bf4e00e6a3179596b275342a2bd9db --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include + +/* raw page handling */ +struct kbase_mem_allocator +{ + struct kbase_device *kbdev; + atomic_t free_list_size; + unsigned int free_list_max_size; + struct mutex free_list_lock; + struct list_head free_list_head; + struct shrinker free_list_reclaimer; +}; diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc_carveout.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc_carveout.c new file mode 100644 index 0000000000000000000000000000000000000000..8fa93b91430224517efa224d16293ab2d697837c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_alloc_carveout.c @@ -0,0 +1,410 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_mem.c + * Base kernel memory APIs + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* This code does not support having multiple kbase devices, or rmmod/insmod */ + +static unsigned long kbase_carveout_start_pfn = ~0UL; +static unsigned long kbase_carveout_end_pfn; +static LIST_HEAD(kbase_carveout_free_list); +static DEFINE_MUTEX(kbase_carveout_free_list_lock); +static unsigned int kbase_carveout_pages; +static atomic_t kbase_carveout_used_pages; +static atomic_t kbase_carveout_system_pages; + +static struct page *kbase_carveout_get_page(struct kbase_mem_allocator *allocator) +{ + struct page *p = NULL; + gfp_t gfp; + + mutex_lock(&kbase_carveout_free_list_lock); + if (!list_empty(&kbase_carveout_free_list)) { + p = list_first_entry(&kbase_carveout_free_list, struct page, lru); + list_del(&p->lru); + atomic_inc(&kbase_carveout_used_pages); + } + mutex_unlock(&kbase_carveout_free_list_lock); + + if (!p) { + dma_addr_t dma_addr; +#if defined(CONFIG_ARM) && !defined(CONFIG_HAVE_DMA_ATTRS) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) + /* DMA cache sync fails for HIGHMEM before 3.5 on ARM */ + gfp = GFP_USER; +#else + gfp = GFP_HIGHUSER; +#endif + + if (current->flags & PF_KTHREAD) { + /* Don't trigger OOM killer from kernel threads, e.g. + * when growing memory on GPU page fault */ + gfp |= __GFP_NORETRY; + } + + p = alloc_page(gfp); + if (!p) + goto out; + + dma_addr = dma_map_page(allocator->kbdev->dev, p, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(allocator->kbdev->dev, dma_addr)) { + __free_page(p); + p = NULL; + goto out; + } + + kbase_set_dma_addr(p, dma_addr); + BUG_ON(dma_addr != PFN_PHYS(page_to_pfn(p))); + atomic_inc(&kbase_carveout_system_pages); + } +out: + return p; +} + +static void kbase_carveout_put_page(struct page *p, + struct kbase_mem_allocator *allocator) +{ + if (page_to_pfn(p) >= kbase_carveout_start_pfn && + page_to_pfn(p) <= kbase_carveout_end_pfn) { + mutex_lock(&kbase_carveout_free_list_lock); + list_add(&p->lru, &kbase_carveout_free_list); + atomic_dec(&kbase_carveout_used_pages); + mutex_unlock(&kbase_carveout_free_list_lock); + } else { + dma_unmap_page(allocator->kbdev->dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + __free_page(p); + atomic_dec(&kbase_carveout_system_pages); + } +} + +static int kbase_carveout_seq_show(struct seq_file *s, void *data) +{ + seq_printf(s, "carveout pages: %u\n", kbase_carveout_pages); + seq_printf(s, "used carveout pages: %u\n", + atomic_read(&kbase_carveout_used_pages)); + seq_printf(s, "used system pages: %u\n", + atomic_read(&kbase_carveout_system_pages)); + return 0; +} + +static int kbasep_carveout_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, kbase_carveout_seq_show, NULL); +} + +static const struct file_operations kbase_carveout_debugfs_fops = { + .open = kbasep_carveout_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +static int kbase_carveout_init(struct device *dev) +{ + unsigned long pfn; + static int once; + + mutex_lock(&kbase_carveout_free_list_lock); + BUG_ON(once); + once = 1; + + for (pfn = kbase_carveout_start_pfn; pfn <= kbase_carveout_end_pfn; pfn++) { + struct page *p = pfn_to_page(pfn); + dma_addr_t dma_addr; + + dma_addr = dma_map_page(dev, p, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_addr)) + goto out_rollback; + + kbase_set_dma_addr(p, dma_addr); + BUG_ON(dma_addr != PFN_PHYS(page_to_pfn(p))); + + list_add_tail(&p->lru, &kbase_carveout_free_list); + } + + mutex_unlock(&kbase_carveout_free_list_lock); + + debugfs_create_file("kbase_carveout", S_IRUGO, NULL, NULL, + &kbase_carveout_debugfs_fops); + + return 0; + +out_rollback: + while (!list_empty(&kbase_carveout_free_list)) { + struct page *p; + + p = list_first_entry(&kbase_carveout_free_list, struct page, lru); + dma_unmap_page(dev, kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + ClearPagePrivate(p); + list_del(&p->lru); + } + + mutex_unlock(&kbase_carveout_free_list_lock); + return -ENOMEM; +} + +int __init kbase_carveout_mem_reserve(phys_addr_t size) +{ + phys_addr_t mem; + +#if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) + /* DMA cache sync fails for HIGHMEM before 3.5 on ARM */ + mem = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ACCESSIBLE); +#else + mem = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); +#endif + if (mem == 0) { + pr_warn("%s: Failed to allocate %d for kbase carveout\n", + __func__, size); + return -ENOMEM; + } + + kbase_carveout_start_pfn = PFN_DOWN(mem); + kbase_carveout_end_pfn = PFN_DOWN(mem + size - 1); + kbase_carveout_pages = kbase_carveout_end_pfn - kbase_carveout_start_pfn + 1; + + return 0; +} + +int kbase_mem_lowlevel_init(struct kbase_device *kbdev) +{ + return kbase_carveout_init(kbdev->dev); +} + +void kbase_mem_lowlevel_term(struct kbase_device *kbdev) +{ +} + +STATIC int kbase_mem_allocator_shrink(struct shrinker *s, struct shrink_control *sc) +{ + struct kbase_mem_allocator *allocator; + int i; + int freed; + + allocator = container_of(s, struct kbase_mem_allocator, free_list_reclaimer); + + if (sc->nr_to_scan == 0) + return atomic_read(&allocator->free_list_size); + + might_sleep(); + + mutex_lock(&allocator->free_list_lock); + i = MIN(atomic_read(&allocator->free_list_size), sc->nr_to_scan); + freed = i; + + atomic_sub(i, &allocator->free_list_size); + + while (i--) { + struct page *p; + + BUG_ON(list_empty(&allocator->free_list_head)); + p = list_first_entry(&allocator->free_list_head, struct page, lru); + list_del(&p->lru); + kbase_carveout_put_page(p, allocator); + } + mutex_unlock(&allocator->free_list_lock); + return atomic_read(&allocator->free_list_size); +} + +mali_error kbase_mem_allocator_init(struct kbase_mem_allocator * const allocator, + unsigned int max_size, struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(NULL != allocator); + KBASE_DEBUG_ASSERT(kbdev); + + INIT_LIST_HEAD(&allocator->free_list_head); + + allocator->kbdev = kbdev; + + mutex_init(&allocator->free_list_lock); + + atomic_set(&allocator->free_list_size, 0); + + allocator->free_list_max_size = max_size; + allocator->free_list_reclaimer.shrink = kbase_mem_allocator_shrink; + allocator->free_list_reclaimer.seeks = DEFAULT_SEEKS; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) /* Kernel versions prior to 3.1 : struct shrinker does not define batch */ + allocator->free_list_reclaimer.batch = 0; +#endif + + register_shrinker(&allocator->free_list_reclaimer); + + return MALI_ERROR_NONE; +} + +void kbase_mem_allocator_term(struct kbase_mem_allocator *allocator) +{ + KBASE_DEBUG_ASSERT(NULL != allocator); + + unregister_shrinker(&allocator->free_list_reclaimer); + + while (!list_empty(&allocator->free_list_head)) { + struct page *p; + + p = list_first_entry(&allocator->free_list_head, struct page, + lru); + list_del(&p->lru); + + kbase_carveout_put_page(p, allocator); + } + mutex_destroy(&allocator->free_list_lock); +} + + +mali_error kbase_mem_allocator_alloc(struct kbase_mem_allocator *allocator, size_t nr_pages, phys_addr_t *pages) +{ + struct page *p; + void *mp; + int i; + int num_from_free_list; + struct list_head from_free_list = LIST_HEAD_INIT(from_free_list); + + might_sleep(); + + KBASE_DEBUG_ASSERT(NULL != allocator); + + /* take from the free list first */ + mutex_lock(&allocator->free_list_lock); + num_from_free_list = MIN(nr_pages, atomic_read(&allocator->free_list_size)); + atomic_sub(num_from_free_list, &allocator->free_list_size); + for (i = 0; i < num_from_free_list; i++) { + BUG_ON(list_empty(&allocator->free_list_head)); + p = list_first_entry(&allocator->free_list_head, struct page, lru); + list_move(&p->lru, &from_free_list); + } + mutex_unlock(&allocator->free_list_lock); + i = 0; + + /* Allocate as many pages from the pool of already allocated pages. */ + list_for_each_entry(p, &from_free_list, lru) + { + pages[i] = PFN_PHYS(page_to_pfn(p)); + i++; + } + + if (i == nr_pages) + return MALI_ERROR_NONE; + + /* If not all pages were sourced from the pool, request new ones. */ + for (; i < nr_pages; i++) { + p = kbase_carveout_get_page(allocator); + if (NULL == p) + goto err_out_roll_back; + + mp = kmap(p); + if (NULL == mp) { + kbase_carveout_put_page(p, allocator); + goto err_out_roll_back; + } + memset(mp, 0x00, PAGE_SIZE); /* instead of __GFP_ZERO, so we can + do cache maintenance */ + dma_sync_single_for_device(allocator->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + kunmap(p); + pages[i] = PFN_PHYS(page_to_pfn(p)); + } + + return MALI_ERROR_NONE; + +err_out_roll_back: + while (i--) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + kbase_carveout_put_page(p, allocator); + } + + return MALI_ERROR_OUT_OF_MEMORY; +} + +void kbase_mem_allocator_free(struct kbase_mem_allocator *allocator, u32 nr_pages, phys_addr_t *pages, mali_bool sync_back) +{ + int i = 0; + int page_count = 0; + int tofree; + + LIST_HEAD(new_free_list_items); + + KBASE_DEBUG_ASSERT(NULL != allocator); + + might_sleep(); + + /* Starting by just freeing the overspill. + * As we do this outside of the lock we might spill too many pages + * or get too many on the free list, but the max_size is just a ballpark so it is ok + * providing that tofree doesn't exceed nr_pages + */ + tofree = MAX((int)allocator->free_list_max_size - atomic_read(&allocator->free_list_size), 0); + tofree = nr_pages - MIN(tofree, nr_pages); + for (; i < tofree; i++) { + if (likely(0 != pages[i])) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + kbase_carveout_put_page(p, allocator); + } + } + + for (; i < nr_pages; i++) { + if (likely(0 != pages[i])) { + struct page *p; + + p = pfn_to_page(PFN_DOWN(pages[i])); + pages[i] = (phys_addr_t)0; + /* Sync back the memory to ensure that future cache + * invalidations don't trample on memory. + */ + if (sync_back) + dma_sync_single_for_cpu(allocator->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_BIDIRECTIONAL); + list_add(&p->lru, &new_free_list_items); + page_count++; + } + } + mutex_lock(&allocator->free_list_lock); + list_splice(&new_free_list_items, &allocator->free_list_head); + atomic_add(page_count, &allocator->free_list_size); + mutex_unlock(&allocator->free_list_lock); +} +KBASE_EXPORT_TEST_API(kbase_mem_allocator_free) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..e17e2df2a812c58375bae36cd930911bfd42f051 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c @@ -0,0 +1,1828 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_linux.c + * Base kernel memory APIs, Linux implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + #include +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER +#include +#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */ + +#include +#include +#include + +static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma); +static const struct vm_operations_struct kbase_vm_ops; + +struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages, u64 commit_pages, u64 extent, u64 *flags, u64 *gpu_va, u16 *va_alignment) +{ + int zone; + int gpu_pc_bits; + int cpu_va_bits; + struct kbase_va_region *reg; + struct device *dev; + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(flags); + KBASE_DEBUG_ASSERT(gpu_va); + KBASE_DEBUG_ASSERT(va_alignment); + + dev = kctx->kbdev->dev; + *va_alignment = 0; /* no alignment by default */ + *gpu_va = 0; /* return 0 on failure */ + + gpu_pc_bits = kctx->kbdev->gpu_props.props.core_props.log2_program_counter_size; + cpu_va_bits = BITS_PER_LONG; + + if (0 == va_pages) { + dev_warn(dev, "kbase_mem_alloc called with 0 va_pages!"); + goto bad_size; + } + + if (va_pages > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + +#if defined(CONFIG_64BIT) + if (kctx->is_compat) + cpu_va_bits = 32; + else + /* force SAME_VA if a 64-bit client */ + *flags |= BASE_MEM_SAME_VA; +#endif + + if (!kbase_check_alloc_flags(*flags)) { + dev_warn(dev, + "kbase_mem_alloc called with bad flags (%llx)", + (unsigned long long)*flags); + goto bad_flags; + } + + /* Limit GPU executable allocs to GPU PC size */ + if ((*flags & BASE_MEM_PROT_GPU_EX) && + (va_pages > (1ULL << gpu_pc_bits >> PAGE_SHIFT))) + goto bad_ex_size; + + /* find out which VA zone to use */ + if (*flags & BASE_MEM_SAME_VA) + zone = KBASE_REG_ZONE_SAME_VA; + else if (*flags & BASE_MEM_PROT_GPU_EX) + zone = KBASE_REG_ZONE_EXEC; + else + zone = KBASE_REG_ZONE_CUSTOM_VA; + + reg = kbase_alloc_free_region(kctx, 0, va_pages, zone); + if (!reg) { + dev_err(dev, "Failed to allocate free region"); + goto no_region; + } + + if (MALI_ERROR_NONE != kbase_reg_prepare_native(reg, kctx)) { + dev_err(dev, "Failed to prepare region"); + goto prepare_failed; + } + + kbase_update_region_flags(reg, *flags); + + if (*flags & BASE_MEM_GROW_ON_GPF) + reg->extent = extent; + else + reg->extent = 0; + + if (kbase_alloc_phy_pages(reg, va_pages, commit_pages)) { + dev_warn(dev, "Failed to allocate %lld pages (va_pages=%lld)", + (unsigned long long)commit_pages, + (unsigned long long)va_pages); + goto no_mem; + } + + kbase_gpu_vm_lock(kctx); + + /* mmap needed to setup VA? */ + if (*flags & BASE_MEM_SAME_VA) { + /* Bind to a cookie */ + if (!kctx->cookies) { + dev_err(dev, "No cookies available for allocation!"); + goto no_cookie; + } + /* return a cookie */ + *gpu_va = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << *gpu_va); + BUG_ON(kctx->pending_regions[*gpu_va]); + kctx->pending_regions[*gpu_va] = reg; + + /* relocate to correct base */ + *gpu_va += PFN_DOWN(BASE_MEM_COOKIE_BASE); + *gpu_va <<= PAGE_SHIFT; + + /* See if we must align memory due to GPU PC bits vs CPU VA */ + if ((*flags & BASE_MEM_PROT_GPU_EX) && + (cpu_va_bits > gpu_pc_bits)) { + *va_alignment = gpu_pc_bits; + reg->flags |= KBASE_REG_ALIGNED; + } + } else /* we control the VA */ { + if (MALI_ERROR_NONE != kbase_gpu_mmap(kctx, reg, 0, va_pages, 1)) { + dev_warn(dev, "Failed to map memory on GPU"); + goto no_mmap; + } + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + } + + kbase_gpu_vm_unlock(kctx); + return reg; + +no_mmap: +no_cookie: + kbase_gpu_vm_unlock(kctx); +no_mem: + kbase_mem_phy_alloc_put(reg->alloc); +prepare_failed: + kfree(reg); +no_region: +bad_ex_size: +bad_flags: +bad_size: + return NULL; +} + +mali_error kbase_mem_query(struct kbase_context *kctx, mali_addr64 gpu_addr, int query, u64 * const out) +{ + struct kbase_va_region *reg; + mali_error ret = MALI_ERROR_FUNCTION_FAILED; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(out); + + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + switch (query) { + case KBASE_MEM_QUERY_COMMIT_SIZE: + if (reg->alloc->type != KBASE_MEM_TYPE_ALIAS) { + *out = kbase_reg_current_backed_size(reg); + } else { + size_t i; + struct kbase_aliased *aliased; + *out = 0; + aliased = reg->alloc->imported.alias.aliased; + for (i = 0; i < reg->alloc->imported.alias.nents; i++) + *out += aliased[i].length; + } + break; + case KBASE_MEM_QUERY_VA_SIZE: + *out = reg->nr_pages; + break; + case KBASE_MEM_QUERY_FLAGS: + { + *out = 0; + if (KBASE_REG_CPU_WR & reg->flags) + *out |= BASE_MEM_PROT_CPU_WR; + if (KBASE_REG_CPU_RD & reg->flags) + *out |= BASE_MEM_PROT_CPU_RD; + if (KBASE_REG_CPU_CACHED & reg->flags) + *out |= BASE_MEM_CACHED_CPU; + if (KBASE_REG_GPU_WR & reg->flags) + *out |= BASE_MEM_PROT_GPU_WR; + if (KBASE_REG_GPU_RD & reg->flags) + *out |= BASE_MEM_PROT_GPU_RD; + if (!(KBASE_REG_GPU_NX & reg->flags)) + *out |= BASE_MEM_PROT_GPU_EX; + if (KBASE_REG_SHARE_BOTH & reg->flags) + *out |= BASE_MEM_COHERENT_SYSTEM; + if (KBASE_REG_SHARE_IN & reg->flags) + *out |= BASE_MEM_COHERENT_LOCAL; + break; + } + default: + *out = 0; + goto out_unlock; + } + + ret = MALI_ERROR_NONE; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + return ret; +} + +mali_error kbase_mem_flags_change(struct kbase_context *kctx, mali_addr64 gpu_addr, unsigned int flags, unsigned int mask) +{ + struct kbase_va_region *reg; + mali_error ret = MALI_ERROR_FUNCTION_FAILED; + unsigned int real_flags = 0; + unsigned int prev_flags = 0; + + KBASE_DEBUG_ASSERT(kctx); + + if (!gpu_addr) + return MALI_ERROR_FUNCTION_FAILED; + + /* nuke other bits */ + flags &= mask; + + /* check for only supported flags */ + if (flags & ~(BASE_MEM_COHERENT_SYSTEM | BASE_MEM_COHERENT_LOCAL)) + goto out; + + /* mask covers bits we don't support? */ + if (mask & ~(BASE_MEM_COHERENT_SYSTEM | BASE_MEM_COHERENT_LOCAL)) + goto out; + + /* convert flags */ + if (BASE_MEM_COHERENT_SYSTEM & flags) + real_flags |= KBASE_REG_SHARE_BOTH; + else if (BASE_MEM_COHERENT_LOCAL & flags) + real_flags |= KBASE_REG_SHARE_IN; + + /* now we can lock down the context, and find the region */ + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + /* limit to imported memory */ + if ((reg->alloc->type != KBASE_MEM_TYPE_IMPORTED_UMP) && + (reg->alloc->type != KBASE_MEM_TYPE_IMPORTED_UMM)) + goto out_unlock; + + /* no change? */ + if (real_flags == (reg->flags & (KBASE_REG_SHARE_IN | KBASE_REG_SHARE_BOTH))) { + ret = MALI_ERROR_NONE; + goto out_unlock; + } + + /* save for roll back */ + prev_flags = reg->flags; + reg->flags &= ~(KBASE_REG_SHARE_IN | KBASE_REG_SHARE_BOTH); + reg->flags |= real_flags; + + /* Currently supporting only imported memory */ + switch (reg->alloc->type) { +#ifdef CONFIG_UMP + case KBASE_MEM_TYPE_IMPORTED_UMP: + ret = kbase_mmu_update_pages(kctx, reg->start_pfn, kbase_get_phy_pages(reg), reg->alloc->nents, reg->flags); + break; +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER + case KBASE_MEM_TYPE_IMPORTED_UMM: + /* Future use will use the new flags, existing mapping will NOT be updated + * as memory should not be in use by the GPU when updating the flags. + */ + ret = MALI_ERROR_NONE; + WARN_ON(reg->alloc->imported.umm.current_mapping_usage_count); + break; +#endif + default: + break; + } + + /* roll back on error, i.e. not UMP */ + if (ret != MALI_ERROR_NONE) + reg->flags = prev_flags; + +out_unlock: + kbase_gpu_vm_unlock(kctx); +out: + return ret; +} + +#define KBASE_MEM_IMPORT_HAVE_PAGES (1UL << BASE_MEM_FLAGS_NR_TOTAL_BITS) + +#ifdef CONFIG_UMP +static struct kbase_va_region *kbase_mem_from_ump(struct kbase_context *kctx, ump_secure_id id, u64 *va_pages, u64 *flags) +{ + struct kbase_va_region *reg; + ump_dd_handle umph; + u64 block_count; + const ump_dd_physical_block_64 *block_array; + u64 i, j; + int page = 0; + ump_alloc_flags ump_flags; + ump_alloc_flags cpu_flags; + ump_alloc_flags gpu_flags; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(va_pages); + KBASE_DEBUG_ASSERT(flags); + + umph = ump_dd_from_secure_id(id); + if (UMP_DD_INVALID_MEMORY_HANDLE == umph) + goto bad_id; + + ump_flags = ump_dd_allocation_flags_get(umph); + cpu_flags = (ump_flags >> UMP_DEVICE_CPU_SHIFT) & UMP_DEVICE_MASK; + gpu_flags = (ump_flags >> DEFAULT_UMP_GPU_DEVICE_SHIFT) & + UMP_DEVICE_MASK; + + *va_pages = ump_dd_size_get_64(umph); + *va_pages >>= PAGE_SHIFT; + + if (!*va_pages) + goto bad_size; + + if (*va_pages > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + if (*flags & BASE_MEM_SAME_VA) + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_SAME_VA); + else + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_CUSTOM_VA); + + if (!reg) + goto no_region; + + /* we've got pages to map now, and support SAME_VA */ + *flags |= KBASE_MEM_IMPORT_HAVE_PAGES; + + reg->alloc = kbase_alloc_create(*va_pages, KBASE_MEM_TYPE_IMPORTED_UMP); + if (IS_ERR_OR_NULL(reg->alloc)) + goto no_alloc_obj; + + reg->alloc->imported.ump_handle = umph; + + reg->flags &= ~KBASE_REG_FREE; + reg->flags |= KBASE_REG_GPU_NX; /* UMP is always No eXecute */ + reg->flags &= ~KBASE_REG_GROWABLE; /* UMP cannot be grown */ + + /* Override import flags based on UMP flags */ + *flags &= ~(BASE_MEM_CACHED_CPU); + *flags &= ~(BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR); + *flags &= ~(BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR); + + if ((cpu_flags & (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) == + (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) { + reg->flags |= KBASE_REG_CPU_CACHED; + *flags |= BASE_MEM_CACHED_CPU; + } + + if (cpu_flags & UMP_PROT_CPU_WR) { + reg->flags |= KBASE_REG_CPU_WR; + *flags |= BASE_MEM_PROT_CPU_WR; + } + + if (cpu_flags & UMP_PROT_CPU_RD) { + reg->flags |= KBASE_REG_CPU_RD; + *flags |= BASE_MEM_PROT_CPU_RD; + } + + if ((gpu_flags & (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) == + (UMP_HINT_DEVICE_RD | UMP_HINT_DEVICE_WR)) + reg->flags |= KBASE_REG_GPU_CACHED; + + if (gpu_flags & UMP_PROT_DEVICE_WR) { + reg->flags |= KBASE_REG_GPU_WR; + *flags |= BASE_MEM_PROT_GPU_WR; + } + + if (gpu_flags & UMP_PROT_DEVICE_RD) { + reg->flags |= KBASE_REG_GPU_RD; + *flags |= BASE_MEM_PROT_GPU_RD; + } + + /* ump phys block query */ + ump_dd_phys_blocks_get_64(umph, &block_count, &block_array); + + for (i = 0; i < block_count; i++) { + for (j = 0; j < (block_array[i].size >> PAGE_SHIFT); j++) { + reg->alloc->pages[page] = block_array[i].addr + (j << PAGE_SHIFT); + page++; + } + } + reg->alloc->nents = *va_pages; + reg->extent = 0; + + return reg; + +no_alloc_obj: + kfree(reg); +no_region: +bad_size: + ump_dd_release(umph); +bad_id: + return NULL; +} +#endif /* CONFIG_UMP */ + +#ifdef CONFIG_DMA_SHARED_BUFFER +static struct kbase_va_region *kbase_mem_from_umm(struct kbase_context *kctx, int fd, u64 *va_pages, u64 *flags) +{ + struct kbase_va_region *reg; + struct dma_buf *dma_buf; + struct dma_buf_attachment *dma_attachment; + + dma_buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(dma_buf)) + goto no_buf; + + dma_attachment = dma_buf_attach(dma_buf, kctx->kbdev->dev); + if (!dma_attachment) + goto no_attachment; + + *va_pages = PAGE_ALIGN(dma_buf->size) >> PAGE_SHIFT; + if (!*va_pages) + goto bad_size; + + if (*va_pages > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + /* ignore SAME_VA */ + *flags &= ~BASE_MEM_SAME_VA; + +#ifdef CONFIG_64BIT + if (!kctx->is_compat) { + /* 64-bit tasks must MMAP anyway, but not expose this address to clients */ + *flags |= BASE_MEM_NEED_MMAP; + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_SAME_VA); + } else { +#else + if (1) { +#endif + reg = kbase_alloc_free_region(kctx, 0, *va_pages, KBASE_REG_ZONE_CUSTOM_VA); + } + + if (!reg) + goto no_region; + + reg->alloc = kbase_alloc_create(*va_pages, KBASE_MEM_TYPE_IMPORTED_UMM); + if (IS_ERR_OR_NULL(reg->alloc)) + goto no_alloc_obj; + + /* No pages to map yet */ + reg->alloc->nents = 0; + + reg->flags &= ~KBASE_REG_FREE; + reg->flags |= KBASE_REG_GPU_NX; /* UMM is always No eXecute */ + reg->flags &= ~KBASE_REG_GROWABLE; /* UMM cannot be grown */ + reg->flags |= KBASE_REG_GPU_CACHED; + + if (*flags & BASE_MEM_PROT_CPU_WR) + reg->flags |= KBASE_REG_CPU_WR; + + if (*flags & BASE_MEM_PROT_CPU_RD) + reg->flags |= KBASE_REG_CPU_RD; + + if (*flags & BASE_MEM_PROT_GPU_WR) + reg->flags |= KBASE_REG_GPU_WR; + + if (*flags & BASE_MEM_PROT_GPU_RD) + reg->flags |= KBASE_REG_GPU_RD; + + /* no read or write permission given on import, only on run do we give the right permissions */ + + reg->alloc->type = BASE_TMEM_IMPORT_TYPE_UMM; + reg->alloc->imported.umm.sgt = NULL; + reg->alloc->imported.umm.dma_buf = dma_buf; + reg->alloc->imported.umm.dma_attachment = dma_attachment; + reg->alloc->imported.umm.current_mapping_usage_count = 0; + reg->extent = 0; + + return reg; + +no_alloc_obj: + kfree(reg); +no_region: +bad_size: + dma_buf_detach(dma_buf, dma_attachment); +no_attachment: + dma_buf_put(dma_buf); +no_buf: + return NULL; +} +#endif /* CONFIG_DMA_SHARED_BUFFER */ + +u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, + u64 nents, struct base_mem_aliasing_info *ai, + u64 *num_pages) +{ + struct kbase_va_region *reg; + u64 gpu_va; + size_t i; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(flags); + KBASE_DEBUG_ASSERT(ai); + KBASE_DEBUG_ASSERT(num_pages); + + /* mask to only allowed flags */ + *flags &= (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | + BASE_MEM_HINT_GPU_RD | BASE_MEM_HINT_GPU_WR | + BASE_MEM_COHERENT_SYSTEM | BASE_MEM_COHERENT_LOCAL); + + if (!(*flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR))) { + dev_warn(kctx->kbdev->dev, + "kbase_mem_alias called with bad flags (%llx)", + (unsigned long long)*flags); + goto bad_flags; + } + + if (!stride) + goto bad_stride; + + if (!nents) + goto bad_nents; + + if ((nents * stride) > (UINT64_MAX / PAGE_SIZE)) + /* 64-bit address range is the max */ + goto bad_size; + + /* calculate the number of pages this alias will cover */ + *num_pages = nents * stride; + +#ifdef CONFIG_64BIT + if (!kctx->is_compat) { + /* 64-bit tasks must MMAP anyway, but not expose this address to + * clients */ + *flags |= BASE_MEM_NEED_MMAP; + reg = kbase_alloc_free_region(kctx, 0, *num_pages, + KBASE_REG_ZONE_SAME_VA); + } else { +#else + if (1) { +#endif + reg = kbase_alloc_free_region(kctx, 0, *num_pages, + KBASE_REG_ZONE_CUSTOM_VA); + } + + if (!reg) + goto no_reg; + + /* zero-sized page array, as we don't need one/can support one */ + reg->alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_ALIAS); + if (IS_ERR_OR_NULL(reg->alloc)) + goto no_alloc_obj; + + kbase_update_region_flags(reg, *flags); + + reg->alloc->imported.alias.nents = nents; + reg->alloc->imported.alias.stride = stride; + reg->alloc->imported.alias.aliased = vzalloc(sizeof(*reg->alloc->imported.alias.aliased) * nents); + if (!reg->alloc->imported.alias.aliased) + goto no_aliased_array; + + kbase_gpu_vm_lock(kctx); + + /* validate and add src handles */ + for (i = 0; i < nents; i++) { + if (ai[i].handle < BASE_MEM_FIRST_FREE_ADDRESS) { + if (ai[i].handle != BASE_MEM_WRITE_ALLOC_PAGES_HANDLE) + goto bad_handle; /* unsupported magic handle */ + if (!ai[i].length) + goto bad_handle; /* must be > 0 */ + if (ai[i].length > stride) + goto bad_handle; /* can't be larger than the + stride */ + reg->alloc->imported.alias.aliased[i].length = ai[i].length; + } else { + struct kbase_va_region *aliasing_reg; + struct kbase_mem_phy_alloc *alloc; + + aliasing_reg = kbase_region_tracker_find_region_base_address(kctx, (ai[i].handle >> PAGE_SHIFT) << PAGE_SHIFT); + + /* validate found region */ + if (!aliasing_reg) + goto bad_handle; /* Not found */ + if (aliasing_reg->flags & KBASE_REG_FREE) + goto bad_handle; /* Free region */ + if (!aliasing_reg->alloc) + goto bad_handle; /* No alloc */ + if (aliasing_reg->alloc->type != KBASE_MEM_TYPE_NATIVE) + goto bad_handle; /* Not a native alloc */ + + /* check size against stride */ + if (!ai[i].length) + goto bad_handle; /* must be > 0 */ + if (ai[i].length > stride) + goto bad_handle; /* can't be larger than the + stride */ + + alloc = aliasing_reg->alloc; + + /* check against the alloc's size */ + if (ai[i].offset > alloc->nents) + goto bad_handle; /* beyond end */ + if (ai[i].offset + ai[i].length > alloc->nents) + goto bad_handle; /* beyond end */ + + reg->alloc->imported.alias.aliased[i].alloc = kbase_mem_phy_alloc_get(alloc); + reg->alloc->imported.alias.aliased[i].length = ai[i].length; + reg->alloc->imported.alias.aliased[i].offset = ai[i].offset; + } + } + +#ifdef CONFIG_64BIT + if (!kctx->is_compat) { + /* Bind to a cookie */ + if (!kctx->cookies) { + dev_err(kctx->kbdev->dev, "No cookies available for allocation!"); + goto no_cookie; + } + /* return a cookie */ + gpu_va = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << gpu_va); + BUG_ON(kctx->pending_regions[gpu_va]); + kctx->pending_regions[gpu_va] = reg; + + /* relocate to correct base */ + gpu_va += PFN_DOWN(BASE_MEM_COOKIE_BASE); + gpu_va <<= PAGE_SHIFT; + } else /* we control the VA */ { +#else + if (1) { +#endif + if (MALI_ERROR_NONE != kbase_gpu_mmap(kctx, reg, 0, + *num_pages, 1)) { + dev_warn(kctx->kbdev->dev, + "Failed to map memory on GPU"); + goto no_mmap; + } + /* return real GPU VA */ + gpu_va = reg->start_pfn << PAGE_SHIFT; + } + + reg->flags &= ~KBASE_REG_FREE; + reg->flags &= ~KBASE_REG_GROWABLE; + + kbase_gpu_vm_unlock(kctx); + + return gpu_va; + +#ifdef CONFIG_64BIT +no_cookie: +#endif +no_mmap: +bad_handle: + kbase_gpu_vm_unlock(kctx); +no_aliased_array: + kbase_mem_phy_alloc_put(reg->alloc); +no_alloc_obj: + kfree(reg); +no_reg: +bad_size: +bad_nents: +bad_stride: +bad_flags: + return 0; +} + +int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type, int handle, mali_addr64 *gpu_va, u64 *va_pages, u64 *flags) +{ + struct kbase_va_region *reg; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(gpu_va); + KBASE_DEBUG_ASSERT(va_pages); + KBASE_DEBUG_ASSERT(flags); + +#ifdef CONFIG_64BIT + if (!kctx->is_compat) + *flags |= BASE_MEM_SAME_VA; +#endif + + switch (type) { +#ifdef CONFIG_UMP + case BASE_MEM_IMPORT_TYPE_UMP: + reg = kbase_mem_from_ump(kctx, (ump_secure_id)handle, va_pages, flags); + break; +#endif /* CONFIG_UMP */ +#ifdef CONFIG_DMA_SHARED_BUFFER + case BASE_MEM_IMPORT_TYPE_UMM: + reg = kbase_mem_from_umm(kctx, handle, va_pages, flags); + break; +#endif /* CONFIG_DMA_SHARED_BUFFER */ + default: + reg = NULL; + break; + } + + if (!reg) + goto no_reg; + + kbase_gpu_vm_lock(kctx); + + /* mmap needed to setup VA? */ + if (*flags & (BASE_MEM_SAME_VA | BASE_MEM_NEED_MMAP)) { + /* Bind to a cookie */ + if (!kctx->cookies) + goto no_cookie; + /* return a cookie */ + *gpu_va = __ffs(kctx->cookies); + kctx->cookies &= ~(1UL << *gpu_va); + BUG_ON(kctx->pending_regions[*gpu_va]); + kctx->pending_regions[*gpu_va] = reg; + + /* relocate to correct base */ + *gpu_va += PFN_DOWN(BASE_MEM_COOKIE_BASE); + *gpu_va <<= PAGE_SHIFT; + + } else if (*flags & KBASE_MEM_IMPORT_HAVE_PAGES) { + /* we control the VA, mmap now to the GPU */ + if (MALI_ERROR_NONE != kbase_gpu_mmap(kctx, reg, 0, *va_pages, 1)) + goto no_gpu_va; + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + } else { + /* we control the VA, but nothing to mmap yet */ + if (MALI_ERROR_NONE != kbase_add_va_region(kctx, reg, 0, *va_pages, 1)) + goto no_gpu_va; + /* return real GPU VA */ + *gpu_va = reg->start_pfn << PAGE_SHIFT; + } + + /* clear out private flags */ + *flags &= ((1UL << BASE_MEM_FLAGS_NR_TOTAL_BITS) - 1); + + kbase_gpu_vm_unlock(kctx); + + return 0; + +no_gpu_va: +no_cookie: + kbase_gpu_vm_unlock(kctx); + kbase_mem_phy_alloc_put(reg->alloc); + kfree(reg); +no_reg: + *gpu_va = 0; + *va_pages = 0; + *flags = 0; + return -ENOMEM; +} + + +static int zap_range_nolock(struct mm_struct *mm, + const struct vm_operations_struct *vm_ops, + unsigned long start, unsigned long end) +{ + struct vm_area_struct *vma; + int err = -EINVAL; /* in case end < start */ + + while (start < end) { + unsigned long local_end; + + vma = find_vma_intersection(mm, start, end); + if (!vma) + break; + + /* is it ours? */ + if (vma->vm_ops != vm_ops) + goto try_next; + + local_end = vma->vm_end; + + if (end < local_end) + local_end = end; + + err = zap_vma_ptes(vma, start, local_end - start); + if (unlikely(err)) + break; + +try_next: + /* go to next vma, if any */ + start = vma->vm_end; + } + + return err; +} + +int kbase_mem_commit(struct kbase_context *kctx, mali_addr64 gpu_addr, u64 new_pages, enum base_backing_threshold_status *failure_reason) +{ + u64 old_pages; + u64 delta; + int res = -EINVAL; + struct kbase_va_region *reg; + phys_addr_t *phy_pages; + + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(failure_reason); + KBASE_DEBUG_ASSERT(gpu_addr != 0); + + down_read(¤t->mm->mmap_sem); + kbase_gpu_vm_lock(kctx); + + /* Validate the region */ + reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS; + goto out_unlock; + } + + KBASE_DEBUG_ASSERT(reg->alloc); + + if (reg->alloc->type != KBASE_MEM_TYPE_NATIVE) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE; + goto out_unlock; + } + + if (0 == (reg->flags & KBASE_REG_GROWABLE)) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE; + goto out_unlock; + } + + if (new_pages > reg->nr_pages) { + /* Would overflow the VA region */ + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS; + goto out_unlock; + } + + /* can't be mapped more than once on the GPU */ + if (atomic_read(®->alloc->gpu_mappings) > 1) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE; + goto out_unlock; + } + + if (new_pages == reg->alloc->nents) { + /* no change */ + res = 0; + goto out_unlock; + } + + phy_pages = kbase_get_phy_pages(reg); + old_pages = kbase_reg_current_backed_size(reg); + + if (new_pages > old_pages) { + /* growing */ + mali_error err; + delta = new_pages - old_pages; + /* Allocate some more pages */ + if (MALI_ERROR_NONE != kbase_alloc_phy_pages_helper(reg->alloc, delta)) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_OOM; + goto out_unlock; + } + err = kbase_mmu_insert_pages(kctx, reg->start_pfn + old_pages, phy_pages + old_pages, delta, reg->flags); + if (MALI_ERROR_NONE != err) { + kbase_free_phy_pages_helper(reg->alloc, delta); + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_OOM; + goto out_unlock; + } + } else { + /* shrinking */ + struct kbase_cpu_mapping *mapping; + mali_error err; + + /* first, unmap from any mappings affected */ + list_for_each_entry(mapping, ®->alloc->mappings, mappings_list) { + unsigned long mapping_size = (mapping->vm_end - mapping->vm_start) >> PAGE_SHIFT; + + /* is this mapping affected ?*/ + if ((mapping->page_off + mapping_size) > new_pages) { + unsigned long first_bad = 0; + int zap_res; + + if (new_pages > mapping->page_off) + first_bad = new_pages - mapping->page_off; + + zap_res = zap_range_nolock(current->mm, + &kbase_vm_ops, + mapping->vm_start + + (first_bad << PAGE_SHIFT), + mapping->vm_end); + WARN(zap_res, + "Failed to zap VA range (0x%lx - 0x%lx);\n", + mapping->vm_start + + (first_bad << PAGE_SHIFT), + mapping->vm_end + ); + } + } + + /* Free some pages */ + delta = old_pages - new_pages; + err = kbase_mmu_teardown_pages(kctx, reg->start_pfn + new_pages, delta); + if (MALI_ERROR_NONE != err) { + *failure_reason = BASE_BACKING_THRESHOLD_ERROR_OOM; + goto out_unlock; + } + + if (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_6367)) { + /* Wait for GPU to flush write buffer before freeing physical pages */ + kbase_wait_write_flush(kctx); + } + + kbase_free_phy_pages_helper(reg->alloc, delta); + } + + res = 0; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + up_read(¤t->mm->mmap_sem); + + return res; +} + +STATIC void kbase_cpu_vm_open(struct vm_area_struct *vma) +{ + struct kbase_cpu_mapping *map = vma->vm_private_data; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + /* non-atomic as we're under Linux' mm lock */ + map->count++; +} + +STATIC void kbase_cpu_vm_close(struct vm_area_struct *vma) +{ + struct kbase_cpu_mapping *map = vma->vm_private_data; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + + /* non-atomic as we're under Linux' mm lock */ + if (--map->count) + return; + + KBASE_DEBUG_ASSERT(map->kctx); + KBASE_DEBUG_ASSERT(map->alloc); + + kbase_gpu_vm_lock(map->kctx); + + if (map->region) { + KBASE_DEBUG_ASSERT((map->region->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_SAME_VA); + kbase_mem_free_region(map->kctx, map->region); + } + + list_del(&map->mappings_list); + + kbase_gpu_vm_unlock(map->kctx); + + kbase_mem_phy_alloc_put(map->alloc); + kfree(map); +} + +KBASE_EXPORT_TEST_API(kbase_cpu_vm_close) + + +STATIC int kbase_cpu_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct kbase_cpu_mapping *map = vma->vm_private_data; + pgoff_t rel_pgoff; + size_t i; + + KBASE_DEBUG_ASSERT(map); + KBASE_DEBUG_ASSERT(map->count > 0); + KBASE_DEBUG_ASSERT(map->kctx); + KBASE_DEBUG_ASSERT(map->alloc); + + /* we don't use vmf->pgoff as it's affected by our mmap with + * offset being a GPU VA or a cookie */ + rel_pgoff = ((unsigned long)vmf->virtual_address - map->vm_start) + >> PAGE_SHIFT; + + kbase_gpu_vm_lock(map->kctx); + if (map->page_off + rel_pgoff >= map->alloc->nents) + goto locked_bad_fault; + + /* insert all valid pages from the fault location */ + for (i = rel_pgoff; + i < MIN((vma->vm_end - vma->vm_start) >> PAGE_SHIFT, + map->alloc->nents - map->page_off); i++) { + int ret = vm_insert_pfn(vma, map->vm_start + (i << PAGE_SHIFT), + PFN_DOWN(map->alloc->pages[map->page_off + i])); + if (ret < 0 && ret != -EBUSY) + goto locked_bad_fault; + } + + kbase_gpu_vm_unlock(map->kctx); + /* we resolved it, nothing for VM to do */ + return VM_FAULT_NOPAGE; + +locked_bad_fault: + kbase_gpu_vm_unlock(map->kctx); + send_sig(SIGSEGV, current, 1); + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct kbase_vm_ops = { + .open = kbase_cpu_vm_open, + .close = kbase_cpu_vm_close, + .fault = kbase_cpu_vm_fault +}; + +static int kbase_cpu_mmap(struct kbase_va_region *reg, struct vm_area_struct *vma, void *kaddr, size_t nr_pages, unsigned long aligned_offset, int free_on_close) +{ + struct kbase_cpu_mapping *map; + u64 start_off = vma->vm_pgoff - reg->start_pfn; + phys_addr_t *page_array; + int err = 0; + int i; + + map = kzalloc(sizeof(*map), GFP_KERNEL); + + if (!map) { + WARN_ON(1); + err = -ENOMEM; + goto out; + } + + /* + * VM_DONTCOPY - don't make this mapping available in fork'ed processes + * VM_DONTEXPAND - disable mremap on this region + * VM_IO - disables paging + * VM_DONTDUMP - Don't include in core dumps (3.7 only) + * VM_MIXEDMAP - Support mixing struct page*s and raw pfns. + * This is needed to support using the dedicated and + * the OS based memory backends together. + */ + /* + * This will need updating to propagate coherency flags + * See MIDBASE-1057 + */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_DONTCOPY | VM_DONTDUMP | VM_DONTEXPAND | VM_IO; +#else + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO; +#endif + vma->vm_ops = &kbase_vm_ops; + vma->vm_private_data = map; + + page_array = kbase_get_phy_pages(reg); + + if (!(reg->flags & KBASE_REG_CPU_CACHED) && + (reg->flags & (KBASE_REG_CPU_WR|KBASE_REG_CPU_RD))) { + /* We can't map vmalloc'd memory uncached. + * Other memory will have been returned from + * kbase_mem_allocator_alloc which would be + * suitable for mapping uncached. + */ + BUG_ON(kaddr); + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + } + + if (!kaddr) { + vma->vm_flags |= VM_PFNMAP; + for (i = 0; i < nr_pages; i++) { + err = vm_insert_pfn(vma, vma->vm_start + (i << PAGE_SHIFT), page_array[i + start_off] >> PAGE_SHIFT); + if (WARN_ON(err)) + break; + } + } else { + /* MIXEDMAP so we can vfree the kaddr early and not track it after map time */ + vma->vm_flags |= VM_MIXEDMAP; + /* vmalloc remaping is easy... */ + err = remap_vmalloc_range(vma, kaddr, 0); + WARN_ON(err); + } + + if (err) { + kfree(map); + goto out; + } + + map->page_off = start_off; + map->region = free_on_close ? reg : NULL; + map->kctx = reg->kctx; + map->vm_start = vma->vm_start + aligned_offset; + if (aligned_offset) { + KBASE_DEBUG_ASSERT(!start_off); + map->vm_end = map->vm_start + (reg->nr_pages << PAGE_SHIFT); + } else { + map->vm_end = vma->vm_end; + } + map->alloc = kbase_mem_phy_alloc_get(reg->alloc); + map->count = 1; /* start with one ref */ + + if (reg->flags & KBASE_REG_CPU_CACHED) + map->alloc->properties |= KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED; + + list_add(&map->mappings_list, &map->alloc->mappings); + + out: + return err; +} + +static int kbase_trace_buffer_mmap(struct kbase_context *kctx, struct vm_area_struct *vma, struct kbase_va_region **const reg, void **const kaddr) +{ + struct kbase_va_region *new_reg; + u32 nr_pages; + size_t size; + int err = 0; + u32 *tb; + int owns_tb = 1; + + dev_dbg(kctx->kbdev->dev, "in %s\n", __func__); + size = (vma->vm_end - vma->vm_start); + nr_pages = size >> PAGE_SHIFT; + + if (!kctx->jctx.tb) { + KBASE_DEBUG_ASSERT(0 != size); + tb = vmalloc_user(size); + + if (NULL == tb) { + err = -ENOMEM; + goto out; + } + + kbase_device_trace_buffer_install(kctx, tb, size); + } else { + err = -EINVAL; + goto out; + } + + *kaddr = kctx->jctx.tb; + + new_reg = kbase_alloc_free_region(kctx, 0, nr_pages, KBASE_REG_ZONE_SAME_VA); + if (!new_reg) { + err = -ENOMEM; + WARN_ON(1); + goto out_no_region; + } + + new_reg->alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_TB); + if (IS_ERR_OR_NULL(new_reg->alloc)) { + err = -ENOMEM; + new_reg->alloc = NULL; + WARN_ON(1); + goto out_no_alloc; + } + + new_reg->alloc->imported.kctx = kctx; + new_reg->flags &= ~KBASE_REG_FREE; + new_reg->flags |= KBASE_REG_CPU_CACHED; + + /* alloc now owns the tb */ + owns_tb = 0; + + if (MALI_ERROR_NONE != kbase_add_va_region(kctx, new_reg, vma->vm_start, nr_pages, 1)) { + err = -ENOMEM; + WARN_ON(1); + goto out_no_va_region; + } + + *reg = new_reg; + + /* map read only, noexec */ + vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE | VM_EXEC | VM_MAYEXEC); + /* the rest of the flags is added by the cpu_mmap handler */ + + dev_dbg(kctx->kbdev->dev, "%s done\n", __func__); + return 0; + +out_no_va_region: +out_no_alloc: + kbase_free_alloced_region(new_reg); +out_no_region: + if (owns_tb) { + kbase_device_trace_buffer_uninstall(kctx); + vfree(tb); + } +out: + return err; +} + +static int kbase_mmu_dump_mmap(struct kbase_context *kctx, struct vm_area_struct *vma, struct kbase_va_region **const reg, void **const kmap_addr) +{ + struct kbase_va_region *new_reg; + void *kaddr; + u32 nr_pages; + size_t size; + int err = 0; + + dev_dbg(kctx->kbdev->dev, "in kbase_mmu_dump_mmap\n"); + size = (vma->vm_end - vma->vm_start); + nr_pages = size >> PAGE_SHIFT; + + kaddr = kbase_mmu_dump(kctx, nr_pages); + + if (!kaddr) { + err = -ENOMEM; + goto out; + } + + new_reg = kbase_alloc_free_region(kctx, 0, nr_pages, KBASE_REG_ZONE_SAME_VA); + if (!new_reg) { + err = -ENOMEM; + WARN_ON(1); + goto out; + } + + new_reg->alloc = kbase_alloc_create(0, KBASE_MEM_TYPE_RAW); + if (IS_ERR_OR_NULL(new_reg->alloc)) { + err = -ENOMEM; + new_reg->alloc = NULL; + WARN_ON(1); + goto out_no_alloc; + } + + new_reg->flags &= ~KBASE_REG_FREE; + new_reg->flags |= KBASE_REG_CPU_CACHED; + if (MALI_ERROR_NONE != kbase_add_va_region(kctx, new_reg, vma->vm_start, nr_pages, 1)) { + err = -ENOMEM; + WARN_ON(1); + goto out_va_region; + } + + *kmap_addr = kaddr; + *reg = new_reg; + + dev_dbg(kctx->kbdev->dev, "kbase_mmu_dump_mmap done\n"); + return 0; + +out_no_alloc: +out_va_region: + kbase_free_alloced_region(new_reg); +out: + return err; +} + + +void kbase_os_mem_map_lock(struct kbase_context *kctx) +{ + struct mm_struct *mm = current->mm; + (void)kctx; + down_read(&mm->mmap_sem); +} + +void kbase_os_mem_map_unlock(struct kbase_context *kctx) +{ + struct mm_struct *mm = current->mm; + (void)kctx; + up_read(&mm->mmap_sem); +} + +int kbase_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct kbase_context *kctx = file->private_data; + struct kbase_va_region *reg; + void *kaddr = NULL; + size_t nr_pages; + int err = 0; + int free_on_close = 0; + struct device *dev = kctx->kbdev->dev; + size_t aligned_offset = 0; + + dev_dbg(dev, "kbase_mmap\n"); + nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + + /* strip away corresponding VM_MAY% flags to the VM_% flags requested */ + vma->vm_flags &= ~((vma->vm_flags & (VM_READ | VM_WRITE)) << 4); + + if (0 == nr_pages) { + err = -EINVAL; + goto out; + } + + if (!(vma->vm_flags & VM_SHARED)) { + err = -EINVAL; + goto out; + } + + kbase_gpu_vm_lock(kctx); + + if (vma->vm_pgoff == PFN_DOWN(BASE_MEM_MAP_TRACKING_HANDLE)) { + /* The non-mapped tracking helper page */ + err = kbase_tracking_page_setup(kctx, vma); + goto out_unlock; + } + + /* if not the MTP, verify that the MTP has been mapped */ + rcu_read_lock(); + /* catches both when the special page isn't present or + * when we've forked */ + if (rcu_dereference(kctx->process_mm) != current->mm) { + err = -EINVAL; + rcu_read_unlock(); + goto out_unlock; + } + rcu_read_unlock(); + + switch (vma->vm_pgoff) { + case PFN_DOWN(BASE_MEM_INVALID_HANDLE): + case PFN_DOWN(BASE_MEM_WRITE_ALLOC_PAGES_HANDLE): + /* Illegal handle for direct map */ + err = -EINVAL; + goto out_unlock; + case PFN_DOWN(BASE_MEM_TRACE_BUFFER_HANDLE): + err = kbase_trace_buffer_mmap(kctx, vma, ®, &kaddr); + if (0 != err) + goto out_unlock; + dev_dbg(dev, "kbase_trace_buffer_mmap ok\n"); + /* free the region on munmap */ + free_on_close = 1; + goto map; + case PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE): + /* MMU dump */ + err = kbase_mmu_dump_mmap(kctx, vma, ®, &kaddr); + if (0 != err) + goto out_unlock; + /* free the region on munmap */ + free_on_close = 1; + goto map; + case PFN_DOWN(BASE_MEM_COOKIE_BASE) ... + PFN_DOWN(BASE_MEM_FIRST_FREE_ADDRESS) - 1: { + /* SAME_VA stuff, fetch the right region */ + int gpu_pc_bits; + int cookie = vma->vm_pgoff - PFN_DOWN(BASE_MEM_COOKIE_BASE); + + gpu_pc_bits = kctx->kbdev->gpu_props.props.core_props.log2_program_counter_size; + reg = kctx->pending_regions[cookie]; + if (NULL != reg) { + if (reg->flags & KBASE_REG_ALIGNED) { + /* nr_pages must be able to hold alignment pages + * plus actual pages */ + if (nr_pages != ((1UL << gpu_pc_bits >> + PAGE_SHIFT) + + reg->nr_pages)) { + /* incorrect mmap size */ + /* leave the cookie for a potential + * later mapping, or to be reclaimed + * later when the context is freed */ + err = -ENOMEM; + goto out_unlock; + } + + aligned_offset = (vma->vm_start + + (1UL << gpu_pc_bits) - 1) & + ~((1UL << gpu_pc_bits) - 1); + aligned_offset -= vma->vm_start; + } else if (reg->nr_pages != nr_pages) { + /* incorrect mmap size */ + /* leave the cookie for a potential later + * mapping, or to be reclaimed later when the + * context is freed */ + err = -ENOMEM; + goto out_unlock; + } + + if ((vma->vm_flags & VM_READ && + !(reg->flags & KBASE_REG_CPU_RD)) || + (vma->vm_flags & VM_WRITE && + !(reg->flags & KBASE_REG_CPU_WR))) { + /* VM flags inconsistent with region flags */ + err = -EPERM; + dev_err(dev, "%s:%d inconsistent VM flags\n", + __FILE__, __LINE__); + goto out_unlock; + } + + /* adjust down nr_pages to what we have physically */ + nr_pages = kbase_reg_current_backed_size(reg); + + if (MALI_ERROR_NONE != kbase_gpu_mmap(kctx, reg, + vma->vm_start + + aligned_offset, + reg->nr_pages, + 1)) { + dev_err(dev, "%s:%d\n", __FILE__, __LINE__); + /* Unable to map in GPU space. */ + WARN_ON(1); + err = -ENOMEM; + goto out_unlock; + } + + /* no need for the cookie anymore */ + kctx->pending_regions[cookie] = NULL; + kctx->cookies |= (1UL << cookie); + + /* + * Overwrite the offset with the + * region start_pfn, so we effectively + * map from offset 0 in the region. + */ + vma->vm_pgoff = reg->start_pfn; + + /* free the region on munmap */ + free_on_close = 1; + goto map; + } + + err = -ENOMEM; + goto out_unlock; + } + default: { + reg = kbase_region_tracker_find_region_enclosing_address(kctx, (u64)vma->vm_pgoff << PAGE_SHIFT); + + if (reg && !(reg->flags & KBASE_REG_FREE)) { + /* will this mapping overflow the size of the region? */ + if (nr_pages > (reg->nr_pages - (vma->vm_pgoff - reg->start_pfn))) + goto overflow; + + if ((vma->vm_flags & VM_READ && + !(reg->flags & KBASE_REG_CPU_RD)) || + (vma->vm_flags & VM_WRITE && + !(reg->flags & KBASE_REG_CPU_WR))) { + /* VM flags inconsistent with region flags */ + err = -EPERM; + dev_err(dev, "%s:%d inconsistent VM flags\n", + __FILE__, __LINE__); + goto out_unlock; + } + +#ifdef CONFIG_DMA_SHARED_BUFFER + if (reg->alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) + goto dma_map; +#endif /* CONFIG_DMA_SHARED_BUFFER */ + + /* limit what we map to the amount currently backed */ + if (reg->alloc->nents < (vma->vm_pgoff - reg->start_pfn + nr_pages)) { + if ((vma->vm_pgoff - reg->start_pfn) >= reg->alloc->nents) + nr_pages = 0; + else + nr_pages = reg->alloc->nents - (vma->vm_pgoff - reg->start_pfn); + } + + goto map; + } + +overflow: + err = -ENOMEM; + goto out_unlock; + } /* default */ + } /* switch */ +map: + err = kbase_cpu_mmap(reg, vma, kaddr, nr_pages, aligned_offset, free_on_close); + + if (vma->vm_pgoff == PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE)) { + /* MMU dump - userspace should now have a reference on + * the pages, so we can now free the kernel mapping */ + vfree(kaddr); + } + goto out_unlock; + +#ifdef CONFIG_DMA_SHARED_BUFFER +dma_map: + err = dma_buf_mmap(reg->alloc->imported.umm.dma_buf, vma, vma->vm_pgoff - reg->start_pfn); +#endif /* CONFIG_DMA_SHARED_BUFFER */ +out_unlock: + kbase_gpu_vm_unlock(kctx); +out: + if (err) + dev_err(dev, "mmap failed %d\n", err); + + return err; +} + +KBASE_EXPORT_TEST_API(kbase_mmap) + +void *kbase_vmap(struct kbase_context *kctx, mali_addr64 gpu_addr, size_t size, + struct kbase_vmap_struct *map) +{ + struct kbase_va_region *reg; + unsigned long page_index; + unsigned int offset = gpu_addr & ~PAGE_MASK; + size_t page_count = PFN_UP(offset + size); + phys_addr_t *page_array; + struct page **pages; + void *cpu_addr = NULL; + pgprot_t prot; + size_t i; + + if (!size || !map) + return NULL; + + /* check if page_count calculation will wrap */ + if (size > ((size_t)-1 / PAGE_SIZE)) + return NULL; + + kbase_gpu_vm_lock(kctx); + + reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); + if (!reg || (reg->flags & KBASE_REG_FREE)) + goto out_unlock; + + page_index = (gpu_addr >> PAGE_SHIFT) - reg->start_pfn; + + /* check if page_index + page_count will wrap */ + if (-1UL - page_count < page_index) + goto out_unlock; + + if (page_index + page_count > kbase_reg_current_backed_size(reg)) + goto out_unlock; + + page_array = kbase_get_phy_pages(reg); + if (!page_array) + goto out_unlock; + + pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); + if (!pages) + goto out_unlock; + + for (i = 0; i < page_count; i++) + pages[i] = pfn_to_page(PFN_DOWN(page_array[page_index + i])); + + prot = PAGE_KERNEL; + if (!(reg->flags & KBASE_REG_CPU_CACHED)) { + /* Map uncached */ + prot = pgprot_writecombine(prot); + } + + cpu_addr = vmap(pages, page_count, VM_MAP, prot); + + kfree(pages); + + if (!cpu_addr) + goto out_unlock; + + map->gpu_addr = gpu_addr; + map->alloc = kbase_mem_phy_alloc_get(reg->alloc); + map->pages = &kbase_get_phy_pages(reg)[page_index]; + map->addr = (void *)((uintptr_t)cpu_addr + offset); + map->size = size; + map->is_cached = (reg->flags & KBASE_REG_CPU_CACHED) != 0; + + if (map->is_cached) { + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + phys_addr_t pa = map->pages[0] + offset; + + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_cpu); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + pa = map->pages[i]; + kbase_sync_single(kctx, pa, PAGE_SIZE, dma_sync_single_for_cpu); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + pa = map->pages[page_count - 1]; + sz = ((offset + size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_cpu); + } + } + + kbase_gpu_vm_unlock(kctx); + + return map->addr; + +out_unlock: + kbase_gpu_vm_unlock(kctx); + return NULL; +} + +void kbase_vunmap(struct kbase_context *kctx, struct kbase_vmap_struct *map) +{ + void *addr = (void *)((uintptr_t)map->addr & PAGE_MASK); + + vunmap(addr); + + if (map->is_cached) { + off_t offset = (uintptr_t)map->addr & ~PAGE_MASK; + size_t size = map->size; + size_t page_count = PFN_UP(offset + size); + size_t i; + + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + phys_addr_t pa = map->pages[0] + offset; + + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_device); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + pa = map->pages[i]; + kbase_sync_single(kctx, pa, PAGE_SIZE, dma_sync_single_for_device); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + pa = map->pages[page_count - 1]; + sz = ((offset + size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_device); + } + } + + map->gpu_addr = 0; + map->alloc = kbase_mem_phy_alloc_put(map->alloc); + map->pages = NULL; + map->addr = NULL; + map->size = 0; + map->is_cached = false; +} + +void kbasep_os_process_page_usage_update(struct kbase_context *kctx, int pages) +{ + struct mm_struct *mm; + + rcu_read_lock(); + mm = rcu_dereference(kctx->process_mm); + if (mm) { + atomic_add(pages, &kctx->nonmapped_pages); +#ifdef SPLIT_RSS_COUNTING + add_mm_counter(mm, MM_FILEPAGES, pages); +#else + spin_lock(&mm->page_table_lock); + add_mm_counter(mm, MM_FILEPAGES, pages); + spin_unlock(&mm->page_table_lock); +#endif + } + rcu_read_unlock(); +} + +static void kbasep_os_process_page_usage_drain(struct kbase_context *kctx) +{ + int pages; + struct mm_struct *mm; + + spin_lock(&kctx->mm_update_lock); + mm = rcu_dereference_protected(kctx->process_mm, lockdep_is_held(&kctx->mm_update_lock)); + if (!mm) { + spin_unlock(&kctx->mm_update_lock); + return; + } + + rcu_assign_pointer(kctx->process_mm, NULL); + spin_unlock(&kctx->mm_update_lock); + synchronize_rcu(); + + pages = atomic_xchg(&kctx->nonmapped_pages, 0); +#ifdef SPLIT_RSS_COUNTING + add_mm_counter(mm, MM_FILEPAGES, -pages); +#else + spin_lock(&mm->page_table_lock); + add_mm_counter(mm, MM_FILEPAGES, -pages); + spin_unlock(&mm->page_table_lock); +#endif +} + +static void kbase_special_vm_close(struct vm_area_struct *vma) +{ + struct kbase_context *kctx; + + kctx = vma->vm_private_data; + kbasep_os_process_page_usage_drain(kctx); +} + +static const struct vm_operations_struct kbase_vm_special_ops = { + .close = kbase_special_vm_close, +}; + +static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma) +{ + /* check that this is the only tracking page */ + spin_lock(&kctx->mm_update_lock); + if (rcu_dereference_protected(kctx->process_mm, lockdep_is_held(&kctx->mm_update_lock))) { + spin_unlock(&kctx->mm_update_lock); + return -EFAULT; + } + + rcu_assign_pointer(kctx->process_mm, current->mm); + + spin_unlock(&kctx->mm_update_lock); + + /* no real access */ + vma->vm_flags &= ~(VM_READ | VM_MAYREAD | VM_WRITE | VM_MAYWRITE | VM_EXEC | VM_MAYEXEC); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP | VM_IO; +#else + vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO; +#endif + vma->vm_ops = &kbase_vm_special_ops; + vma->vm_private_data = kctx; + + return 0; +} +void *kbase_va_alloc(struct kbase_context *kctx, u32 size, struct kbase_hwc_dma_mapping *handle) +{ + int i; + int res; + void *va; + dma_addr_t dma_pa; + struct kbase_va_region *reg; + phys_addr_t *page_array; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + //DEFINE_DMA_ATTRS(attrs); +#endif + + u32 pages = ((size - 1) >> PAGE_SHIFT) + 1; + u32 flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR | + BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR; + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(0 != size); + KBASE_DEBUG_ASSERT(0 != pages); + + if (size == 0) + goto err; + + /* All the alloc calls return zeroed memory */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + //dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + //va = dma_alloc_attrs(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL, &attrs); + va = dma_alloc_coherent(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL); +#else + va = dma_alloc_writecombine(kctx->kbdev->dev, size, &dma_pa, GFP_KERNEL); +#endif + if (!va) + goto err; + + /* Store the state so we can free it later. */ + handle->cpu_va = va; + handle->dma_pa = dma_pa; + handle->size = size; + + + reg = kbase_alloc_free_region(kctx, 0, pages, KBASE_REG_ZONE_SAME_VA); + if (!reg) + goto no_reg; + + reg->flags &= ~KBASE_REG_FREE; + kbase_update_region_flags(reg, flags); + + reg->alloc = kbase_alloc_create(pages, KBASE_MEM_TYPE_RAW); + if (IS_ERR_OR_NULL(reg->alloc)) + goto no_alloc; + + page_array = kbase_get_phy_pages(reg); + + for (i = 0; i < pages; i++) + page_array[i] = dma_pa + (i << PAGE_SHIFT); + + reg->alloc->nents = pages; + + kbase_gpu_vm_lock(kctx); + res = kbase_gpu_mmap(kctx, reg, (uintptr_t) va, pages, 1); + kbase_gpu_vm_unlock(kctx); + if (res) + goto no_mmap; + + return va; + +no_mmap: + kbase_mem_phy_alloc_put(reg->alloc); +no_alloc: + kfree(reg); +no_reg: +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + //dma_free_attrs(kctx->kbdev->dev, size, va, dma_pa, &attrs); + dma_free_coherent(kctx->kbdev->dev, size, va, dma_pa); +#else + dma_free_writecombine(kctx->kbdev->dev, size, va, dma_pa); +#endif +err: + return NULL; +} +KBASE_EXPORT_SYMBOL(kbase_va_alloc); + +void kbase_va_free(struct kbase_context *kctx, struct kbase_hwc_dma_mapping *handle) +{ + struct kbase_va_region *reg; + mali_error err; + +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) +// DEFINE_DMA_ATTRS(attrs); +//#endif + + KBASE_DEBUG_ASSERT(kctx != NULL); + KBASE_DEBUG_ASSERT(handle->cpu_va != NULL); + + kbase_gpu_vm_lock(kctx); + reg = kbase_region_tracker_find_region_base_address(kctx, (uintptr_t)handle->cpu_va); + KBASE_DEBUG_ASSERT(reg); + err = kbase_gpu_munmap(kctx, reg); + kbase_gpu_vm_unlock(kctx); + KBASE_DEBUG_ASSERT(err == MALI_ERROR_NONE); + + kbase_mem_phy_alloc_put(reg->alloc); + kfree(reg); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + //dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + //dma_free_attrs(kctx->kbdev->dev, handle->size, + // handle->cpu_va, handle->dma_pa, &attrs); + dma_free_coherent(kctx->kbdev->dev, handle->size, + handle->cpu_va, handle->dma_pa); +#else + dma_free_writecombine(kctx->kbdev->dev, handle->size, + handle->cpu_va, handle->dma_pa); +#endif +} +KBASE_EXPORT_SYMBOL(kbase_va_free); + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h new file mode 100644 index 0000000000000000000000000000000000000000..6bd1d0d86d06ae1b866d8106a98dc7d64eacd679 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h @@ -0,0 +1,71 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_linux.h + * Base kernel memory APIs, Linux implementation. + */ + +#ifndef _KBASE_MEM_LINUX_H_ +#define _KBASE_MEM_LINUX_H_ + +/** A HWC dump mapping */ +typedef struct kbase_hwc_dma_mapping { + void *cpu_va; + dma_addr_t dma_pa; + size_t size; +} kbase_hwc_dma_mapping; + +struct kbase_va_region * kbase_mem_alloc(struct kbase_context * kctx, u64 va_pages, u64 commit_pages, u64 extent, u64 * flags, u64 * gpu_va, u16 * va_alignment); +mali_error kbase_mem_query(struct kbase_context *kctx, mali_addr64 gpu_addr, int query, u64 * const pages); +int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type, int handle, mali_addr64 * gpu_va, u64 * va_pages, u64 * flags); +u64 kbase_mem_alias(struct kbase_context *kctx, u64* flags, u64 stride, u64 nents, struct base_mem_aliasing_info* ai, u64 * num_pages); +mali_error kbase_mem_flags_change(struct kbase_context *kctx, mali_addr64 gpu_addr, unsigned int flags, unsigned int mask); +int kbase_mem_commit(struct kbase_context * kctx, mali_addr64 gpu_addr, u64 new_pages, enum base_backing_threshold_status * failure_reason); +int kbase_mmap(struct file *file, struct vm_area_struct *vma); + +struct kbase_vmap_struct { + mali_addr64 gpu_addr; + struct kbase_mem_phy_alloc *alloc; + phys_addr_t *pages; + void *addr; + size_t size; + bool is_cached; +}; +void *kbase_vmap(struct kbase_context *kctx, mali_addr64 gpu_addr, size_t size, + struct kbase_vmap_struct *map); +void kbase_vunmap(struct kbase_context *kctx, struct kbase_vmap_struct *map); + +/** @brief Allocate memory from kernel space and map it onto the GPU + * + * @param kctx The context used for the allocation/mapping + * @param size The size of the allocation in bytes + * @param handle An opaque structure used to contain the state needed to free the memory + * @return the VA for kernel space and GPU MMU + */ +void *kbase_va_alloc(struct kbase_context *kctx, u32 size, struct kbase_hwc_dma_mapping *handle); + +/** @brief Free/unmap memory allocated by kbase_va_alloc + * + * @param kctx The context used for the allocation/mapping + * @param handle An opaque structure returned by the kbase_va_alloc function. + */ +void kbase_va_free(struct kbase_context *kctx, struct kbase_hwc_dma_mapping *handle); + +#endif /* _KBASE_MEM_LINUX_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h new file mode 100644 index 0000000000000000000000000000000000000000..2b3985ea4fca6320abc4fa459a39c2d7dc34a89f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h @@ -0,0 +1,48 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_MEM_LOWLEVEL_H +#define _KBASE_MEM_LOWLEVEL_H + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +#include + +/** + * @brief Flags for kbase_phy_allocator_pages_alloc + */ +#define KBASE_PHY_PAGES_FLAG_DEFAULT (0) /** Default allocation flag */ +#define KBASE_PHY_PAGES_FLAG_CLEAR (1 << 0) /** Clear the pages after allocation */ +#define KBASE_PHY_PAGES_FLAG_POISON (1 << 1) /** Fill the memory with a poison value */ + +#define KBASE_PHY_PAGES_SUPPORTED_FLAGS (KBASE_PHY_PAGES_FLAG_DEFAULT|KBASE_PHY_PAGES_FLAG_CLEAR|KBASE_PHY_PAGES_FLAG_POISON) + +#define KBASE_PHY_PAGES_POISON_VALUE 0xFD /** Value to fill the memory with when KBASE_PHY_PAGES_FLAG_POISON is set */ + +/** + * A pointer to a cache synchronization function, either dma_sync_single_for_cpu + * or dma_sync_single_for_device. + */ +typedef void (*kbase_sync_kmem_fn) (struct device *, dma_addr_t, size_t size, + enum dma_data_direction); + + +#endif /* _KBASE_LOWLEVEL_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..b7d709e8696d7c2ad465df71941b61cf9d70c87b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c @@ -0,0 +1,137 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#ifdef CONFIG_DEBUG_FS + +/* mam_profile file name max length 22 based on format _\0 */ +#define KBASEP_DEBUGFS_FNAME_SIZE_MAX (10+1+10+1) + +void kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size) +{ + spin_lock(&kctx->mem_profile_lock); + kfree(kctx->mem_profile_data); + kctx->mem_profile_data = data; + kctx->mem_profile_size = size; + spin_unlock(&kctx->mem_profile_lock); +} + +/** Show callback for the @c mem_profile debugfs file. + * + * This function is called to get the contents of the @c mem_profile debugfs + * file. This is a report of current memory usage and distribution in userspace. + * + * @param sfile The debugfs entry + * @param data Data associated with the entry + * + * @return 0 if successfully prints data in debugfs entry file + * -1 if it encountered an error + */ +static int kbasep_mem_profile_seq_show(struct seq_file *sfile, void *data) +{ + struct kbase_context *kctx = sfile->private; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + spin_lock(&kctx->mem_profile_lock); + seq_write(sfile, kctx->mem_profile_data, kctx->mem_profile_size); + seq_putc(sfile, '\n'); + spin_unlock(&kctx->mem_profile_lock); + + return 0; +} + +/* + * File operations related to debugfs entry for mem_profile + */ +STATIC int kbasep_mem_profile_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, kbasep_mem_profile_seq_show, in->i_private); +} + +static const struct file_operations kbasep_mem_profile_debugfs_fops = { + .open = kbasep_mem_profile_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +mali_error kbasep_mem_profile_debugfs_add(struct kbase_context *kctx) +{ + char name[KBASEP_DEBUGFS_FNAME_SIZE_MAX]; + + KBASE_DEBUG_ASSERT(kctx != NULL); + + spin_lock_init(&kctx->mem_profile_lock); + + scnprintf(name, KBASEP_DEBUGFS_FNAME_SIZE_MAX, "%d_%d", kctx->pid, + kctx->id); + + kctx->mem_dentry = debugfs_create_file(name, S_IRUGO, + kctx->kbdev->memory_profile_directory, + kctx, &kbasep_mem_profile_debugfs_fops); + if (IS_ERR(kctx->mem_dentry)) + goto error_out; + + return MALI_ERROR_NONE; + +error_out: + return MALI_ERROR_FUNCTION_FAILED; +} + +void kbasep_mem_profile_debugfs_remove(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(kctx != NULL); + + spin_lock(&kctx->mem_profile_lock); + kfree(kctx->mem_profile_data); + kctx->mem_profile_data = NULL; + spin_unlock(&kctx->mem_profile_lock); + + if (IS_ERR(kctx->mem_dentry)) + return; + debugfs_remove(kctx->mem_dentry); +} + +#else /* CONFIG_DEBUG_FS */ + +/** + * @brief Stub function for when debugfs is disabled + */ +mali_error kbasep_mem_profile_debugfs_add(struct kbase_context *ctx) +{ + return MALI_ERROR_NONE; +} + +/** + * @brief Stub function for when debugfs is disabled + */ +void kbasep_mem_profile_debugfs_remove(struct kbase_context *ctx) +{ +} + +/** + * @brief Stub function for when debugfs is disabled + */ +void kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size) +{ + kfree(data); +} +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..ef908c84247556d820d8e29fa9e1ed20492cf52f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h @@ -0,0 +1,58 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mem_profile_debugfs.h + * Header file for mem profiles entries in debugfs + * + */ + +#ifndef _KBASE_MEM_PROFILE_DEBUGFS_H +#define _KBASE_MEM_PROFILE_DEBUGFS_H + +#include +#include +#include + +/** + * @brief Add new entry to Mali memory profile debugfs + */ +mali_error kbasep_mem_profile_debugfs_add(struct kbase_context *kctx); + +/** + * @brief Remove entry from Mali memory profile debugfs + */ +void kbasep_mem_profile_debugfs_remove(struct kbase_context *kctx); + +/** + * @brief Insert data to debugfs file, so it can be read by userspce + * + * Function takes ownership of @c data and frees it later when new data + * are inserted. + * + * @param kctx Context to which file data should be inserted + * @param data NULL-terminated string to be inserted to mem_profile file, + without trailing new line character + * @param size @c buf length + */ +void kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, + size_t size); + +#endif /*_KBASE_MEM_PROFILE_DEBUGFS_H*/ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h new file mode 100644 index 0000000000000000000000000000000000000000..176392115997b6e3e6278f3626f4473df32a4ef1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_mem_profile_debugfs_buf_size.h + * Header file for the size of the buffer to accumulate the histogram report text in + */ + +#ifndef _KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ +#define _KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ + +/** + * The size of the buffer to accumulate the histogram report text in + * @see @ref CCTXP_HIST_BUF_SIZE_MAX_LENGTH_REPORT + */ +#define KBASE_MEM_PROFILE_MAX_BUF_SIZE ( ( size_t ) ( 64 + ( ( 80 + ( 56 * 64 ) ) * 15 ) + 56 ) ) + +#endif /*_KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_*/ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..49cc90ab3901e0cf1af3c2abf104212220238398 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu.c @@ -0,0 +1,1666 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_mmu.c + * Base kernel MMU management. + */ + +/* #define DEBUG 1 */ +#include +#include +#include +#include +#include + +#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a) + +#include +#include +#include + +#define KBASE_MMU_PAGE_ENTRIES 512 + +extern atomic_t g_mtk_gpu_total_memory_usage_in_pages; +/* + * Definitions: + * - PGD: Page Directory. + * - PTE: Page Table Entry. A 64bit value pointing to the next + * level of translation + * - ATE: Address Transation Entry. A 64bit value pointing to + * a 4kB physical page. + */ + +static void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, + struct kbase_as *as, const char *reason_str); + + +/* Helper Function to perform assignment of page table entries, to ensure the use of + * strd, which is required on LPAE systems. + */ + +static inline void page_table_entry_set(struct kbase_device *kbdev, u64 *pte, u64 phy) +{ +#ifdef CONFIG_64BIT + *pte = phy; +#elif defined(CONFIG_ARM) + /* + * + * In order to prevent the compiler keeping cached copies of memory, we have to explicitly + * say that we have updated memory. + * + * Note: We could manually move the data ourselves into R0 and R1 by specifying + * register variables that are explicitly given registers assignments, the down side of + * this is that we have to assume cpu endianess. To avoid this we can use the ldrd to read the + * data from memory into R0 and R1 which will respect the cpu endianess, we then use strd to + * make the 64 bit assignment to the page table entry. + * + */ + + asm volatile("ldrd r0, r1, [%[ptemp]]\n\t" + "strd r0, r1, [%[pte]]\n\t" + : "=m" (*pte) + : [ptemp] "r" (&phy), [pte] "r" (pte), "m" (phy) + : "r0", "r1"); +#else +#error "64-bit atomic write must be implemented for your architecture" +#endif +} + +static size_t make_multiple(size_t minimum, size_t multiple) +{ + size_t remainder = minimum % multiple; + if (remainder == 0) + return minimum; + else + return minimum + multiple - remainder; +} + +static void page_fault_worker(struct work_struct *data) +{ + u64 fault_pfn; + u32 fault_access; + size_t new_pages; + size_t fault_rel_pfn; + struct kbase_as *faulting_as; + int as_no; + struct kbase_context *kctx; + struct kbase_device *kbdev; + struct kbase_va_region *region; + mali_error err; + + faulting_as = container_of(data, struct kbase_as, work_pagefault); + fault_pfn = faulting_as->fault_addr >> PAGE_SHIFT; + as_no = faulting_as->number; + + kbdev = container_of(faulting_as, struct kbase_device, as[as_no]); + + /* Grab the context that was already refcounted in kbase_mmu_interrupt(). + * Therefore, it cannot be scheduled out of this AS until we explicitly release it + * + * NOTE: NULL can be returned here if we're gracefully handling a spurious interrupt */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as_no); + + if (kctx == NULL) { + /* Only handle this if not already suspended */ + if (!kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + struct kbase_mmu_setup *current_setup = &faulting_as->current_setup; + + /* Address space has no context, terminate the work */ + + /* AS transaction begin */ + mutex_lock(&faulting_as->transaction_mutex); + + /* Switch to unmapped mode */ + current_setup->transtab &= ~(u64)MMU_TRANSTAB_ADRMODE_MASK; + current_setup->transtab |= AS_TRANSTAB_ADRMODE_UNMAPPED; + + /* Apply new address space settings */ + kbase_mmu_hw_configure(kbdev, faulting_as, kctx); + + mutex_unlock(&faulting_as->transaction_mutex); + /* AS transaction end */ + + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_pm_context_idle(kbdev); + } + return; + } + + KBASE_DEBUG_ASSERT(kctx->kbdev == kbdev); + + kbase_gpu_vm_lock(kctx); + + region = kbase_region_tracker_find_region_enclosing_address(kctx, faulting_as->fault_addr); + if (NULL == region || region->flags & KBASE_REG_FREE) { + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Memory is not mapped on the GPU"); + goto fault_done; + } + + fault_access = faulting_as->fault_status & AS_FAULTSTATUS_ACCESS_TYPE_MASK; + if (((fault_access == AS_FAULTSTATUS_ACCESS_TYPE_READ) && + !(region->flags & KBASE_REG_GPU_RD)) || + ((fault_access == AS_FAULTSTATUS_ACCESS_TYPE_WRITE) && + !(region->flags & KBASE_REG_GPU_WR)) || + ((fault_access == AS_FAULTSTATUS_ACCESS_TYPE_EX) && + (region->flags & KBASE_REG_GPU_NX))) { + dev_warn(kbdev->dev, "Access permissions don't match: region->flags=0x%lx", region->flags); + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Access permissions mismatch"); + goto fault_done; + } + + if (!(region->flags & GROWABLE_FLAGS_REQUIRED)) { + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Memory is not growable"); + goto fault_done; + } + + /* find the size we need to grow it by */ + /* we know the result fit in a size_t due to kbase_region_tracker_find_region_enclosing_address + * validating the fault_adress to be within a size_t from the start_pfn */ + fault_rel_pfn = fault_pfn - region->start_pfn; + + if (fault_rel_pfn < kbase_reg_current_backed_size(region)) { + dev_dbg(kbdev->dev, "Page fault @ 0x%llx in allocated region 0x%llx-0x%llx of growable TMEM: Ignoring", + faulting_as->fault_addr, region->start_pfn, + region->start_pfn + + kbase_reg_current_backed_size(region)); + + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + /* [1] in case another page fault occurred while we were + * handling the (duplicate) page fault we need to ensure we + * don't loose the other page fault as result of us clearing + * the MMU IRQ. Therefore, after we clear the MMU IRQ we send + * an UNLOCK command that will retry any stalled memory + * transaction (which should cause the other page fault to be + * raised again). + */ + kbase_mmu_hw_do_operation(kbdev, faulting_as, 0, 0, 0, + AS_COMMAND_UNLOCK, 1); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + + goto fault_done; + } + + new_pages = make_multiple(fault_rel_pfn - + kbase_reg_current_backed_size(region) + 1, + region->extent); + + /* cap to max vsize */ + if (new_pages + kbase_reg_current_backed_size(region) > + region->nr_pages) + new_pages = region->nr_pages - + kbase_reg_current_backed_size(region); + + if (0 == new_pages) { + /* Duplicate of a fault we've already handled, nothing to do */ + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + /* See comment [1] about UNLOCK usage */ + kbase_mmu_hw_do_operation(kbdev, faulting_as, 0, 0, 0, + AS_COMMAND_UNLOCK, 1); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + goto fault_done; + } + + if (MALI_ERROR_NONE == kbase_alloc_phy_pages_helper(region->alloc, new_pages)) { + u32 op; + + /* alloc success */ + KBASE_DEBUG_ASSERT(kbase_reg_current_backed_size(region) <= region->nr_pages); + + /* AS transaction begin */ + mutex_lock(&faulting_as->transaction_mutex); + + /* set up the new pages */ + err = kbase_mmu_insert_pages(kctx, region->start_pfn + kbase_reg_current_backed_size(region) - new_pages, &kbase_get_phy_pages(region)[kbase_reg_current_backed_size(region) - new_pages], new_pages, region->flags); + if (MALI_ERROR_NONE != err) { + /* failed to insert pages, handle as a normal PF */ + mutex_unlock(&faulting_as->transaction_mutex); + kbase_free_phy_pages_helper(region->alloc, new_pages); + kbase_gpu_vm_unlock(kctx); + /* The locked VA region will be unlocked and the cache invalidated in here */ + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Page table update failure"); + goto fault_done; + } +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_page_fault_insert_pages(as_no, new_pages); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + + /* flush L2 and unlock the VA (resumes the MMU) */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6367)) + op = AS_COMMAND_FLUSH; + else + op = AS_COMMAND_FLUSH_PT; + + /* clear MMU interrupt - this needs to be done after updating + * the page tables but before issuing a FLUSH command. The + * FLUSH cmd has a side effect that it restarts stalled memory + * transactions in other address spaces which may cause + * another fault to occur. If we didn't clear the interrupt at + * this stage a new IRQ might not be raised when the GPU finds + * a MMU IRQ is already pending. + */ + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + + kbase_mmu_hw_do_operation(kbdev, faulting_as, kctx, + faulting_as->fault_addr >> PAGE_SHIFT, + new_pages, + op, 1); + + mutex_unlock(&faulting_as->transaction_mutex); + /* AS transaction end */ + + /* reenable this in the mask */ + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_PAGE); + kbase_gpu_vm_unlock(kctx); + } else { + /* failed to extend, handle as a normal PF */ + kbase_gpu_vm_unlock(kctx); + kbase_mmu_report_fault_and_kill(kctx, faulting_as, + "Page allocation failure"); + } + +fault_done: + /* + * By this point, the fault was handled in some way, + * so release the ctx refcount + */ + kbasep_js_runpool_release_ctx(kbdev, kctx); +} + +phys_addr_t kbase_mmu_alloc_pgd(struct kbase_context *kctx) +{ + phys_addr_t pgd; + u64 *page; + int i; + struct page *p; + + KBASE_DEBUG_ASSERT(NULL != kctx); + kbase_atomic_add_pages(1, &kctx->used_pages); + kbase_atomic_add_pages(1, &kctx->kbdev->memdev.used_pages); + kbase_atomic_add_pages(1, &g_mtk_gpu_total_memory_usage_in_pages); + + if (MALI_ERROR_NONE != kbase_mem_allocator_alloc(kctx->pgd_allocator, 1, &pgd)) + goto sub_pages; + + p = pfn_to_page(PFN_DOWN(pgd)); + page = kmap(p); + if (NULL == page) + goto alloc_free; + + kbase_process_page_usage_inc(kctx, 1); + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) + page_table_entry_set(kctx->kbdev, &page[i], ENTRY_IS_INVAL); + + /* Clean the full page */ + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_TO_DEVICE); + kunmap(pfn_to_page(PFN_DOWN(pgd))); + return pgd; + +alloc_free: + kbase_mem_allocator_free(kctx->pgd_allocator, 1, &pgd, MALI_FALSE); +sub_pages: + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); + kbase_atomic_sub_pages(1, &g_mtk_gpu_total_memory_usage_in_pages); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_alloc_pgd) + +static phys_addr_t mmu_pte_to_phy_addr(u64 entry) +{ + if (!(entry & 1)) + return 0; + + return entry & ~0xFFF; +} + +static u64 mmu_phyaddr_to_pte(phys_addr_t phy) +{ + return (phy & ~0xFFF) | ENTRY_IS_PTE; +} + +static u64 mmu_phyaddr_to_ate(phys_addr_t phy, u64 flags) +{ + return (phy & ~0xFFF) | (flags & ENTRY_FLAGS_MASK) | ENTRY_IS_ATE; +} + +/* Given PGD PFN for level N, return PGD PFN for level N+1 */ +static phys_addr_t mmu_get_next_pgd(struct kbase_context *kctx, phys_addr_t pgd, u64 vpfn, int level) +{ + u64 *page; + phys_addr_t target_pgd; + struct page *p; + + KBASE_DEBUG_ASSERT(pgd); + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + /* + * Architecture spec defines level-0 as being the top-most. + * This is a bit unfortunate here, but we keep the same convention. + */ + vpfn >>= (3 - level) * 9; + vpfn &= 0x1FF; + + p = pfn_to_page(PFN_DOWN(pgd)); + page = kmap(p); + if (NULL == page) { + dev_warn(kctx->kbdev->dev, "mmu_get_next_pgd: kmap failure\n"); + return 0; + } + + target_pgd = mmu_pte_to_phy_addr(page[vpfn]); + + if (!target_pgd) { + target_pgd = kbase_mmu_alloc_pgd(kctx); + if (!target_pgd) { + dev_warn(kctx->kbdev->dev, "mmu_get_next_pgd: kbase_mmu_alloc_pgd failure\n"); + kunmap(p); + return 0; + } + + page_table_entry_set(kctx->kbdev, &page[vpfn], + mmu_phyaddr_to_pte(target_pgd)); + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, + DMA_TO_DEVICE); + /* Rely on the caller to update the address space flags. */ + } + + kunmap(p); + return target_pgd; +} + +static phys_addr_t mmu_get_bottom_pgd(struct kbase_context *kctx, u64 vpfn) +{ + phys_addr_t pgd; + int l; + + pgd = kctx->pgd; + + for (l = MIDGARD_MMU_TOPLEVEL; l < 3; l++) { + pgd = mmu_get_next_pgd(kctx, pgd, vpfn, l); + /* Handle failure condition */ + if (!pgd) { + dev_warn(kctx->kbdev->dev, "mmu_get_bottom_pgd: mmu_get_next_pgd failure\n"); + return 0; + } + } + + return pgd; +} + +static phys_addr_t mmu_insert_pages_recover_get_next_pgd(struct kbase_context *kctx, phys_addr_t pgd, u64 vpfn, int level) +{ + u64 *page; + phys_addr_t target_pgd; + + KBASE_DEBUG_ASSERT(pgd); + KBASE_DEBUG_ASSERT(NULL != kctx); + + lockdep_assert_held(&kctx->reg_lock); + + /* + * Architecture spec defines level-0 as being the top-most. + * This is a bit unfortunate here, but we keep the same convention. + */ + vpfn >>= (3 - level) * 9; + vpfn &= 0x1FF; + + page = kmap_atomic(pfn_to_page(PFN_DOWN(pgd))); + /* kmap_atomic should NEVER fail */ + KBASE_DEBUG_ASSERT(NULL != page); + + target_pgd = mmu_pte_to_phy_addr(page[vpfn]); + /* As we are recovering from what has already been set up, we should have a target_pgd */ + KBASE_DEBUG_ASSERT(0 != target_pgd); + + kunmap_atomic(page); + return target_pgd; +} + +static phys_addr_t mmu_insert_pages_recover_get_bottom_pgd(struct kbase_context *kctx, u64 vpfn) +{ + phys_addr_t pgd; + int l; + + pgd = kctx->pgd; + + for (l = MIDGARD_MMU_TOPLEVEL; l < 3; l++) { + pgd = mmu_insert_pages_recover_get_next_pgd(kctx, pgd, vpfn, l); + /* Should never fail */ + KBASE_DEBUG_ASSERT(0 != pgd); + } + + return pgd; +} + +static void mmu_insert_pages_failure_recovery(struct kbase_context *kctx, u64 vpfn, + size_t nr) +{ + phys_addr_t pgd; + u64 *pgd_page; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(vpfn <= (UINT64_MAX / PAGE_SIZE)); + + lockdep_assert_held(&kctx->reg_lock); + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + pgd = mmu_insert_pages_recover_get_bottom_pgd(kctx, vpfn); + KBASE_DEBUG_ASSERT(0 != pgd); + + p = pfn_to_page(PFN_DOWN(pgd)); + + pgd_page = kmap_atomic(p); + KBASE_DEBUG_ASSERT(NULL != pgd_page); + + /* Invalidate the entries we added */ + for (i = 0; i < count; i++) + page_table_entry_set(kctx->kbdev, &pgd_page[index + i], + ENTRY_IS_INVAL); + + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p), + PAGE_SIZE, DMA_TO_DEVICE); + kunmap_atomic(pgd_page); + } +} + +/** + * Map KBASE_REG flags to MMU flags + */ +static u64 kbase_mmu_get_mmu_flags(unsigned long flags) +{ + u64 mmu_flags; + + /* store mem_attr index as 4:2 (macro called ensures 3 bits already) */ + mmu_flags = KBASE_REG_MEMATTR_VALUE(flags) << 2; + + /* write perm if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_WR) ? ENTRY_WR_BIT : 0; + /* read perm if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_RD) ? ENTRY_RD_BIT : 0; + /* nx if requested */ + mmu_flags |= (flags & KBASE_REG_GPU_NX) ? ENTRY_NX_BIT : 0; + + if (flags & KBASE_REG_SHARE_BOTH) { + /* inner and outer shareable */ + mmu_flags |= SHARE_BOTH_BITS; + } else if (flags & KBASE_REG_SHARE_IN) { + /* inner shareable coherency */ + mmu_flags |= SHARE_INNER_BITS; + } + + return mmu_flags; +} + +/* + * Map the single page 'phys' 'nr' of times, starting at GPU PFN 'vpfn' + */ +mali_error kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, + phys_addr_t phys, size_t nr, + unsigned long flags) +{ + phys_addr_t pgd; + u64 *pgd_page; + u64 pte_entry; + /* In case the insert_single_page only partially completes we need to be + * able to recover */ + mali_bool recover_required = MALI_FALSE; + u64 recover_vpfn = vpfn; + size_t recover_count = 0; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(vpfn <= (UINT64_MAX / PAGE_SIZE)); + + lockdep_assert_held(&kctx->reg_lock); + + /* the one entry we'll populate everywhere */ + pte_entry = mmu_phyaddr_to_ate(phys, kbase_mmu_get_mmu_flags(flags)); + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + /* + * Repeatedly calling mmu_get_bottom_pte() is clearly + * suboptimal. We don't have to re-parse the whole tree + * each time (just cache the l0-l2 sequence). + * On the other hand, it's only a gain when we map more than + * 256 pages at once (on average). Do we really care? + */ + pgd = mmu_get_bottom_pgd(kctx, vpfn); + if (!pgd) { + dev_warn(kctx->kbdev->dev, + "kbase_mmu_insert_pages: " + "mmu_get_bottom_pgd failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_count); + } + return MALI_ERROR_FUNCTION_FAILED; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, + "kbase_mmu_insert_pages: " + "kmap failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_count); + } + return MALI_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; i++) { + unsigned int ofs = index + i; + KBASE_DEBUG_ASSERT(0 == (pgd_page[ofs] & 1UL)); + page_table_entry_set(kctx->kbdev, &pgd_page[ofs], + pte_entry); + } + + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p) + + (index * sizeof(u64)), + count * sizeof(u64), + DMA_TO_DEVICE); + + + kunmap(p); + /* We have started modifying the page table. + * If further pages need inserting and fail we need to undo what + * has already taken place */ + recover_required = MALI_TRUE; + recover_count += count; + } + return MALI_ERROR_NONE; +} + +/* + * Map 'nr' pages pointed to by 'phys' at GPU PFN 'vpfn' + */ +mali_error kbase_mmu_insert_pages(struct kbase_context *kctx, u64 vpfn, + phys_addr_t *phys, size_t nr, + unsigned long flags) +{ + phys_addr_t pgd; + u64 *pgd_page; + u64 mmu_flags = 0; + /* In case the insert_pages only partially completes we need to be able + * to recover */ + mali_bool recover_required = MALI_FALSE; + u64 recover_vpfn = vpfn; + size_t recover_count = 0; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + /* 64-bit address range is the max */ + KBASE_DEBUG_ASSERT(vpfn <= (UINT64_MAX / PAGE_SIZE)); + + lockdep_assert_held(&kctx->reg_lock); + + mmu_flags = kbase_mmu_get_mmu_flags(flags); + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + /* + * Repeatedly calling mmu_get_bottom_pte() is clearly + * suboptimal. We don't have to re-parse the whole tree + * each time (just cache the l0-l2 sequence). + * On the other hand, it's only a gain when we map more than + * 256 pages at once (on average). Do we really care? + */ + pgd = mmu_get_bottom_pgd(kctx, vpfn); + if (!pgd) { + dev_warn(kctx->kbdev->dev, + "kbase_mmu_insert_pages: " + "mmu_get_bottom_pgd failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_count); + } + return MALI_ERROR_FUNCTION_FAILED; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, + "kbase_mmu_insert_pages: " + "kmap failure\n"); + if (recover_required) { + /* Invalidate the pages we have partially + * completed */ + mmu_insert_pages_failure_recovery(kctx, + recover_vpfn, + recover_count); + } + return MALI_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; i++) { + unsigned int ofs = index + i; + KBASE_DEBUG_ASSERT(0 == (pgd_page[ofs] & 1UL)); + page_table_entry_set(kctx->kbdev, &pgd_page[ofs], + mmu_phyaddr_to_ate(phys[i], + mmu_flags) + ); + } + + phys += count; + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p) + + (index * sizeof(u64)), + count * sizeof(u64), + DMA_TO_DEVICE); + + kunmap(p); + /* We have started modifying the page table. If further pages + * need inserting and fail we need to undo what has already + * taken place */ + recover_required = MALI_TRUE; + recover_count += count; + } + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_insert_pages) + +/** + * This function is responsible for validating the MMU PTs + * triggering reguired flushes. + * + * * IMPORTANT: This uses kbasep_js_runpool_release_ctx() when the context is + * currently scheduled into the runpool, and so potentially uses a lot of locks. + * These locks must be taken in the correct order with respect to others + * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more + * information. + */ +static void kbase_mmu_flush(struct kbase_context *kctx, u64 vpfn, size_t nr) +{ + struct kbase_device *kbdev; + mali_bool ctx_is_in_runpool; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + kbdev = kctx->kbdev; + + /* We must flush if we're currently running jobs. At the very least, we need to retain the + * context to ensure it doesn't schedule out whilst we're trying to flush it */ + ctx_is_in_runpool = kbasep_js_runpool_retain_ctx(kbdev, kctx); + + if (ctx_is_in_runpool) { + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + /* Second level check is to try to only do this when jobs are running. The refcount is + * a heuristic for this. */ + if (kbdev->js_data.runpool_irq.per_as_data[kctx->as_nr].as_busy_refcount >= 2) { + int ret; + u32 op; + + /* AS transaction begin */ + mutex_lock(&kbdev->as[kctx->as_nr].transaction_mutex); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6367)) + op = AS_COMMAND_FLUSH; + else + op = AS_COMMAND_FLUSH_MEM; + + ret = kbase_mmu_hw_do_operation(kbdev, + &kbdev->as[kctx->as_nr], + kctx, vpfn, nr, + op, 0); +#if KBASE_GPU_RESET_EN + if (ret) { + /* Flush failed to complete, assume the GPU has hung and perform a reset to recover */ + dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issueing GPU soft-reset to recover\n"); + if (kbase_prepare_to_reset_gpu(kbdev)) + kbase_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + + mutex_unlock(&kbdev->as[kctx->as_nr].transaction_mutex); + /* AS transaction end */ + } + kbasep_js_runpool_release_ctx(kbdev, kctx); + } +} + +/* + * We actually only discard the ATE, and not the page table + * pages. There is a potential DoS here, as we'll leak memory by + * having PTEs that are potentially unused. Will require physical + * page accounting, so MMU pages are part of the process allocation. + * + * IMPORTANT: This uses kbasep_js_runpool_release_ctx() when the context is + * currently scheduled into the runpool, and so potentially uses a lot of locks. + * These locks must be taken in the correct order with respect to others + * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more + * information. + */ +mali_error kbase_mmu_teardown_pages(struct kbase_context *kctx, u64 vpfn, size_t nr) +{ + phys_addr_t pgd; + u64 *pgd_page; + struct kbase_device *kbdev; + size_t requested_nr = nr; + + KBASE_DEBUG_ASSERT(NULL != kctx); + beenthere(kctx, "kctx %p vpfn %lx nr %zd", (void *)kctx, (unsigned long)vpfn, nr); + + lockdep_assert_held(&kctx->reg_lock); + + if (0 == nr) { + /* early out if nothing to do */ + return MALI_ERROR_NONE; + } + + kbdev = kctx->kbdev; + + while (nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + if (count > nr) + count = nr; + + pgd = mmu_get_bottom_pgd(kctx, vpfn); + if (!pgd) { + dev_warn(kbdev->dev, "kbase_mmu_teardown_pages: mmu_get_bottom_pgd failure\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kbdev->dev, "kbase_mmu_teardown_pages: kmap failure\n"); + return MALI_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; i++) { + page_table_entry_set(kctx->kbdev, &pgd_page[index + i], ENTRY_IS_INVAL); + } + + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p) + + (index * sizeof(u64)), + count * sizeof(u64), + DMA_TO_DEVICE); + + kunmap(p); + } + + kbase_mmu_flush(kctx, vpfn, requested_nr); + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_mmu_teardown_pages) + +/** + * Update the entries for specified number of pages pointed to by 'phys' at GPU PFN 'vpfn'. + * This call is being triggered as a response to the changes of the mem attributes + * + * @pre : The caller is responsible for validating the memory attributes + * + * IMPORTANT: This uses kbasep_js_runpool_release_ctx() when the context is + * currently scheduled into the runpool, and so potentially uses a lot of locks. + * These locks must be taken in the correct order with respect to others + * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more + * information. + */ +mali_error kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, phys_addr_t* phys, size_t nr, unsigned long flags) +{ + phys_addr_t pgd; + u64* pgd_page; + u64 mmu_flags = 0; + size_t requested_nr = nr; + + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(0 != vpfn); + KBASE_DEBUG_ASSERT(vpfn <= (UINT64_MAX / PAGE_SIZE)); + + lockdep_assert_held(&kctx->reg_lock); + + mmu_flags = kbase_mmu_get_mmu_flags(flags); + + dev_warn(kctx->kbdev->dev, "kbase_mmu_update_pages(): updating page share flags "\ + "on GPU PFN 0x%llx from phys %p, %zu pages", + vpfn, phys, nr); + + + while(nr) { + unsigned int i; + unsigned int index = vpfn & 0x1FF; + size_t count = KBASE_MMU_PAGE_ENTRIES - index; + struct page *p; + + if (count > nr) + count = nr; + + pgd = mmu_get_bottom_pgd(kctx, vpfn); + if (!pgd) { + dev_warn(kctx->kbdev->dev, "mmu_get_bottom_pgd failure\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + p = pfn_to_page(PFN_DOWN(pgd)); + pgd_page = kmap(p); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, "kmap failure\n"); + return MALI_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; i++) { + page_table_entry_set(kctx->kbdev, &pgd_page[index + i], mmu_phyaddr_to_ate(phys[i], mmu_flags)); + } + + phys += count; + vpfn += count; + nr -= count; + + dma_sync_single_for_device(kctx->kbdev->dev, + kbase_dma_addr(p) + + (index * sizeof(u64)), + count * sizeof(u64), + DMA_TO_DEVICE); + + kunmap(pfn_to_page(PFN_DOWN(pgd))); + } + + kbase_mmu_flush(kctx, vpfn, requested_nr); + + return MALI_ERROR_NONE; +} + +static int mmu_pte_is_valid(u64 pte) +{ + return ((pte & 3) == ENTRY_IS_ATE); +} + +/* This is a debug feature only */ +static void mmu_check_unused(struct kbase_context *kctx, phys_addr_t pgd) +{ + u64 *page; + int i; + + page = kmap_atomic(pfn_to_page(PFN_DOWN(pgd))); + /* kmap_atomic should NEVER fail. */ + KBASE_DEBUG_ASSERT(NULL != page); + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { + if (mmu_pte_is_valid(page[i])) + beenthere(kctx, "live pte %016lx", (unsigned long)page[i]); + } + kunmap_atomic(page); +} + +static void mmu_teardown_level(struct kbase_context *kctx, phys_addr_t pgd, int level, int zap, u64 *pgd_page_buffer) +{ + phys_addr_t target_pgd; + u64 *pgd_page; + int i; + + KBASE_DEBUG_ASSERT(NULL != kctx); + lockdep_assert_held(&kctx->reg_lock); + + pgd_page = kmap_atomic(pfn_to_page(PFN_DOWN(pgd))); + /* kmap_atomic should NEVER fail. */ + KBASE_DEBUG_ASSERT(NULL != pgd_page); + /* Copy the page to our preallocated buffer so that we can minimize kmap_atomic usage */ + memcpy(pgd_page_buffer, pgd_page, PAGE_SIZE); + kunmap_atomic(pgd_page); + pgd_page = pgd_page_buffer; + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { + target_pgd = mmu_pte_to_phy_addr(pgd_page[i]); + + if (target_pgd) { + if (level < 2) { + mmu_teardown_level(kctx, target_pgd, level + 1, zap, pgd_page_buffer + (PAGE_SIZE / sizeof(u64))); + } else { + /* + * So target_pte is a level-3 page. + * As a leaf, it is safe to free it. + * Unless we have live pages attached to it! + */ + mmu_check_unused(kctx, target_pgd); + } + + beenthere(kctx, "pte %lx level %d", (unsigned long)target_pgd, level + 1); + if (zap) { + kbase_mem_allocator_free(kctx->pgd_allocator, 1, &target_pgd, MALI_TRUE); + kbase_process_page_usage_dec(kctx, 1); + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); + kbase_atomic_sub_pages(1, &g_mtk_gpu_total_memory_usage_in_pages); + } + } + } +} + +mali_error kbase_mmu_init(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL == kctx->mmu_teardown_pages); + + /* Preallocate MMU depth of four pages for mmu_teardown_level to use */ + kctx->mmu_teardown_pages = kmalloc(PAGE_SIZE * 4, GFP_KERNEL); + + kctx->mem_attrs = (AS_MEMATTR_IMPL_DEF_CACHE_POLICY << + (AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY * 8)) | + (AS_MEMATTR_FORCE_TO_CACHE_ALL << + (AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL * 8)) | + (AS_MEMATTR_WRITE_ALLOC << + (AS_MEMATTR_INDEX_WRITE_ALLOC * 8)) | + 0; /* The other indices are unused for now */ + + if (NULL == kctx->mmu_teardown_pages) + return MALI_ERROR_OUT_OF_MEMORY; + + return MALI_ERROR_NONE; +} + +void kbase_mmu_term(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kctx->mmu_teardown_pages); + + kfree(kctx->mmu_teardown_pages); + kctx->mmu_teardown_pages = NULL; +} + +void kbase_mmu_free_pgd(struct kbase_context *kctx) +{ + KBASE_DEBUG_ASSERT(NULL != kctx); + KBASE_DEBUG_ASSERT(NULL != kctx->mmu_teardown_pages); + + lockdep_assert_held(&kctx->reg_lock); + + mmu_teardown_level(kctx, kctx->pgd, MIDGARD_MMU_TOPLEVEL, 1, kctx->mmu_teardown_pages); + + beenthere(kctx, "pgd %lx", (unsigned long)kctx->pgd); + kbase_mem_allocator_free(kctx->pgd_allocator, 1, &kctx->pgd, MALI_TRUE); + kbase_process_page_usage_dec(kctx, 1); + kbase_atomic_sub_pages(1, &kctx->used_pages); + kbase_atomic_sub_pages(1, &kctx->kbdev->memdev.used_pages); + kbase_atomic_sub_pages(1, &g_mtk_gpu_total_memory_usage_in_pages); +} + +KBASE_EXPORT_TEST_API(kbase_mmu_free_pgd) + +static size_t kbasep_mmu_dump_level(struct kbase_context *kctx, phys_addr_t pgd, int level, char ** const buffer, size_t *size_left) +{ + phys_addr_t target_pgd; + u64 *pgd_page; + int i; + size_t size = KBASE_MMU_PAGE_ENTRIES * sizeof(u64) + sizeof(u64); + size_t dump_size; + + KBASE_DEBUG_ASSERT(NULL != kctx); + lockdep_assert_held(&kctx->reg_lock); + + pgd_page = kmap(pfn_to_page(PFN_DOWN(pgd))); + if (!pgd_page) { + dev_warn(kctx->kbdev->dev, "kbasep_mmu_dump_level: kmap failure\n"); + return 0; + } + + if (*size_left >= size) { + /* A modified physical address that contains the page table level */ + u64 m_pgd = pgd | level; + + /* Put the modified physical address in the output buffer */ + memcpy(*buffer, &m_pgd, sizeof(m_pgd)); + *buffer += sizeof(m_pgd); + + /* Followed by the page table itself */ + memcpy(*buffer, pgd_page, sizeof(u64) * KBASE_MMU_PAGE_ENTRIES); + *buffer += sizeof(u64) * KBASE_MMU_PAGE_ENTRIES; + + *size_left -= size; + } + + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { + if ((pgd_page[i] & ENTRY_IS_PTE) == ENTRY_IS_PTE) { + target_pgd = mmu_pte_to_phy_addr(pgd_page[i]); + + dump_size = kbasep_mmu_dump_level(kctx, target_pgd, level + 1, buffer, size_left); + if (!dump_size) { + kunmap(pfn_to_page(PFN_DOWN(pgd))); + return 0; + } + size += dump_size; + } + } + + kunmap(pfn_to_page(PFN_DOWN(pgd))); + + return size; +} + +void *kbase_mmu_dump(struct kbase_context *kctx, int nr_pages) +{ + void *kaddr; + size_t size_left; + + KBASE_DEBUG_ASSERT(kctx); + + lockdep_assert_held(&kctx->reg_lock); + + if (0 == nr_pages) { + /* can't find in a 0 sized buffer, early out */ + return NULL; + } + + size_left = nr_pages * PAGE_SIZE; + + KBASE_DEBUG_ASSERT(0 != size_left); + kaddr = vmalloc_user(size_left); + + if (kaddr) { + u64 end_marker = 0xFFULL; + char *buffer = (char *)kaddr; + + size_t size = kbasep_mmu_dump_level(kctx, kctx->pgd, MIDGARD_MMU_TOPLEVEL, &buffer, &size_left); + if (!size) { + vfree(kaddr); + return NULL; + } + + /* Add on the size for the end marker */ + size += sizeof(u64); + + if (size > nr_pages * PAGE_SIZE || size_left < sizeof(u64)) { + /* The buffer isn't big enough - free the memory and return failure */ + vfree(kaddr); + return NULL; + } + + /* Add the end marker */ + memcpy(buffer, &end_marker, sizeof(u64)); + } + + return kaddr; +} +KBASE_EXPORT_TEST_API(kbase_mmu_dump) + +static void bus_fault_worker(struct work_struct *data) +{ + struct kbase_as *faulting_as; + int as_no; + struct kbase_context *kctx; + struct kbase_device *kbdev; +#if KBASE_GPU_RESET_EN + mali_bool reset_status = MALI_FALSE; +#endif /* KBASE_GPU_RESET_EN */ + + faulting_as = container_of(data, struct kbase_as, work_busfault); + + as_no = faulting_as->number; + + kbdev = container_of(faulting_as, struct kbase_device, as[as_no]); + + /* Grab the context that was already refcounted in kbase_mmu_interrupt(). + * Therefore, it cannot be scheduled out of this AS until we explicitly release it + * + * NOTE: NULL can be returned here if we're gracefully handling a spurious interrupt */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as_no); +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245)) { + /* Due to H/W issue 8245 we need to reset the GPU after using UNMAPPED mode. + * We start the reset before switching to UNMAPPED to ensure that unrelated jobs + * are evicted from the GPU before the switch. + */ + dev_err(kbdev->dev, "GPU bus error occurred. For this GPU version we now soft-reset as part of bus error recovery\n"); + reset_status = kbase_prepare_to_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* NOTE: If GPU already powered off for suspend, we don't need to switch to unmapped */ + if (!kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + struct kbase_mmu_setup *current_setup = &faulting_as->current_setup; + + /* switch to UNMAPPED mode, will abort all jobs and stop any hw counter dumping */ + /* AS transaction begin */ + mutex_lock(&kbdev->as[as_no].transaction_mutex); + + /* Set the MMU into unmapped mode */ + current_setup->transtab &= ~(u64)MMU_TRANSTAB_ADRMODE_MASK; + current_setup->transtab |= AS_TRANSTAB_ADRMODE_UNMAPPED; + + /* Apply the new settings */ + kbase_mmu_hw_configure(kbdev, faulting_as, kctx); + + mutex_unlock(&kbdev->as[as_no].transaction_mutex); + /* AS transaction end */ + + kbase_mmu_hw_clear_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_BUS); + kbase_mmu_hw_enable_fault(kbdev, faulting_as, kctx, + KBASE_MMU_FAULT_TYPE_BUS); + + kbase_pm_context_idle(kbdev); + } +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245) && reset_status) + kbase_reset_gpu(kbdev); +#endif /* KBASE_GPU_RESET_EN */ + /* By this point, the fault was handled in some way, so release the ctx refcount */ + if (kctx != NULL) + kbasep_js_runpool_release_ctx(kbdev, kctx); +} + +const char *kbase_exception_name(u32 exception_code) +{ + const char *e; + + switch (exception_code) { + /* Non-Fault Status code */ + case 0x00: + e = "NOT_STARTED/IDLE/OK"; + break; + case 0x01: + e = "DONE"; + break; + case 0x02: + e = "INTERRUPTED"; + break; + case 0x03: + e = "STOPPED"; + break; + case 0x04: + e = "TERMINATED"; + break; + case 0x08: + e = "ACTIVE"; + break; + /* Job exceptions */ + case 0x40: + e = "JOB_CONFIG_FAULT"; + break; + case 0x41: + e = "JOB_POWER_FAULT"; + break; + case 0x42: + e = "JOB_READ_FAULT"; + break; + case 0x43: + e = "JOB_WRITE_FAULT"; + break; + case 0x44: + e = "JOB_AFFINITY_FAULT"; + break; + case 0x48: + e = "JOB_BUS_FAULT"; + break; + case 0x50: + e = "INSTR_INVALID_PC"; + break; + case 0x51: + e = "INSTR_INVALID_ENC"; + break; + case 0x52: + e = "INSTR_TYPE_MISMATCH"; + break; + case 0x53: + e = "INSTR_OPERAND_FAULT"; + break; + case 0x54: + e = "INSTR_TLS_FAULT"; + break; + case 0x55: + e = "INSTR_BARRIER_FAULT"; + break; + case 0x56: + e = "INSTR_ALIGN_FAULT"; + break; + case 0x58: + e = "DATA_INVALID_FAULT"; + break; + case 0x59: + e = "TILE_RANGE_FAULT"; + break; + case 0x5A: + e = "ADDR_RANGE_FAULT"; + break; + case 0x60: + e = "OUT_OF_MEMORY"; + break; + /* GPU exceptions */ + case 0x80: + e = "DELAYED_BUS_FAULT"; + break; + case 0x88: + e = "SHAREABILITY_FAULT"; + break; + /* MMU exceptions */ + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + e = "TRANSLATION_FAULT"; + break; + case 0xC8: + e = "PERMISSION_FAULT"; + break; + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + e = "TRANSTAB_BUS_FAULT"; + break; + case 0xD8: + e = "ACCESS_FLAG"; + break; + default: + e = "UNKNOWN"; + break; + }; + + return e; +} + +/** + * The caller must ensure it's retained the ctx to prevent it from being scheduled out whilst it's being worked on. + */ +static void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, + struct kbase_as *as, const char *reason_str) +{ + unsigned long flags; + int exception_type; + int access_type; + int source_id; + int as_no; + struct kbase_device *kbdev; + struct kbase_mmu_setup *current_setup; + struct kbasep_js_device_data *js_devdata; + +#if KBASE_GPU_RESET_EN + mali_bool reset_status = MALI_FALSE; +#endif + static const char * const access_type_names[] = { "RESERVED", "EXECUTE", "READ", "WRITE" }; + + as_no = as->number; + kbdev = kctx->kbdev; + js_devdata = &kbdev->js_data; + + /* ASSERT that the context won't leave the runpool */ + KBASE_DEBUG_ASSERT(kbasep_js_debug_check_ctx_refcount(kbdev, kctx) > 0); + + /* decode the fault status */ + exception_type = as->fault_status & 0xFF; + access_type = (as->fault_status >> 8) & 0x3; + source_id = (as->fault_status >> 16); + + /* terminal fault, print info about the fault */ + dev_err(kbdev->dev, + "Unhandled Page fault in AS%d at VA 0x%016llX\n" + "Reason: %s\n" + "raw fault status 0x%X\n" + "decoded fault status: %s\n" + "exception type 0x%X: %s\n" + "access type 0x%X: %s\n" + "source id 0x%X\n", + as_no, as->fault_addr, + reason_str, + as->fault_status, + (as->fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"), + exception_type, kbase_exception_name(exception_type), + access_type, access_type_names[access_type], + source_id); + + /* hardware counters dump fault handling */ + if ((kbdev->hwcnt.kctx) && (kbdev->hwcnt.kctx->as_nr == as_no) && (kbdev->hwcnt.state == KBASE_INSTR_STATE_DUMPING)) { + unsigned int num_core_groups = kbdev->gpu_props.num_core_groups; + if ((as->fault_addr >= kbdev->hwcnt.addr) && (as->fault_addr < (kbdev->hwcnt.addr + (num_core_groups * 2048)))) + kbdev->hwcnt.state = KBASE_INSTR_STATE_FAULT; + } + + /* Stop the kctx from submitting more jobs and cause it to be scheduled + * out/rescheduled - this will occur on releasing the context's refcount */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_clear_submit_allowed(js_devdata, kctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags); + + /* Kill any running jobs from the context. Submit is disallowed, so no more jobs from this + * context can appear in the job slots from this point on */ + kbase_job_kill_jobs_from_context(kctx); + /* AS transaction begin */ + mutex_lock(&as->transaction_mutex); +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245)) { + /* Due to H/W issue 8245 we need to reset the GPU after using UNMAPPED mode. + * We start the reset before switching to UNMAPPED to ensure that unrelated jobs + * are evicted from the GPU before the switch. + */ + dev_err(kbdev->dev, "Unhandled page fault. For this GPU version we now soft-reset the GPU as part of page fault recovery."); + reset_status = kbase_prepare_to_reset_gpu(kbdev); + } +#endif /* KBASE_GPU_RESET_EN */ + /* switch to UNMAPPED mode, will abort all jobs and stop any hw counter dumping */ + current_setup = &as->current_setup; + + current_setup->transtab &= ~(u64)MMU_TRANSTAB_ADRMODE_MASK; + current_setup->transtab |= AS_TRANSTAB_ADRMODE_UNMAPPED; + + /* Apply the new address space setting */ + kbase_mmu_hw_configure(kbdev, as, kctx); + + mutex_unlock(&as->transaction_mutex); + /* AS transaction end */ + + /* Clear down the fault */ + kbase_mmu_hw_clear_fault(kbdev, as, kctx, KBASE_MMU_FAULT_TYPE_PAGE); + kbase_mmu_hw_enable_fault(kbdev, as, kctx, KBASE_MMU_FAULT_TYPE_PAGE); + +#if KBASE_GPU_RESET_EN + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8245) && reset_status) + kbase_reset_gpu(kbdev); +#endif /* KBASE_GPU_RESET_EN */ +} + +void kbasep_as_do_poke(struct work_struct *work) +{ + struct kbase_as *as; + struct kbase_device *kbdev; + struct kbase_context *kctx; + unsigned long flags; + + KBASE_DEBUG_ASSERT(work); + as = container_of(work, struct kbase_as, poke_work); + kbdev = container_of(as, struct kbase_device, as[as->number]); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + /* GPU power will already be active by virtue of the caller holding a JS + * reference on the address space, and will not release it until this worker + * has finished */ + + /* Further to the comment above, we know that while this function is running + * the AS will not be released as before the atom is released this workqueue + * is flushed (in kbase_as_poking_timer_release_atom) + */ + kctx = kbasep_js_runpool_lookup_ctx_noretain(kbdev, as->number); + + /* AS transaction begin */ + mutex_lock(&as->transaction_mutex); + /* Force a uTLB invalidate */ + kbase_mmu_hw_do_operation(kbdev, as, kctx, 0, 0, + AS_COMMAND_UNLOCK, 0); + mutex_unlock(&as->transaction_mutex); + /* AS transaction end */ + + spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags); + if (as->poke_refcount && + !(as->poke_state & KBASE_AS_POKE_STATE_KILLING_POKE)) { + /* Only queue up the timer if we need it, and we're not trying to kill it */ + hrtimer_start(&as->poke_timer, HR_TIMER_DELAY_MSEC(5), HRTIMER_MODE_REL); + } + spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags); + +} + +enum hrtimer_restart kbasep_as_poke_timer_callback(struct hrtimer *timer) +{ + struct kbase_as *as; + int queue_work_ret; + + KBASE_DEBUG_ASSERT(NULL != timer); + as = container_of(timer, struct kbase_as, poke_timer); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + queue_work_ret = queue_work(as->poke_wq, &as->poke_work); + KBASE_DEBUG_ASSERT(queue_work_ret); + return HRTIMER_NORESTART; +} + +/** + * Retain the poking timer on an atom's context (if the atom hasn't already + * done so), and start the timer (if it's not already started). + * + * This must only be called on a context that's scheduled in, and an atom + * that's running on the GPU. + * + * The caller must hold kbasep_js_device_data::runpool_irq::lock + * + * This can be called safely from atomic context + */ +void kbase_as_poking_timer_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbase_as *as; + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + if (katom->poking) + return; + + katom->poking = 1; + + /* It's safe to work on the as/as_nr without an explicit reference, + * because the caller holds the runpool_irq lock, and the atom itself + * was also running and had already taken a reference */ + as = &kbdev->as[kctx->as_nr]; + + if (++(as->poke_refcount) == 1) { + /* First refcount for poke needed: check if not already in flight */ + if (!as->poke_state) { + /* need to start poking */ + as->poke_state |= KBASE_AS_POKE_STATE_IN_FLIGHT; + queue_work(as->poke_wq, &as->poke_work); + } + } +} + +/** + * If an atom holds a poking timer, release it and wait for it to finish + * + * This must only be called on a context that's scheduled in, and an atom + * that still has a JS reference on the context + * + * This must \b not be called from atomic context, since it can sleep. + */ +void kbase_as_poking_timer_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom) +{ + struct kbase_as *as; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev); + KBASE_DEBUG_ASSERT(kctx); + KBASE_DEBUG_ASSERT(katom); + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + if (!katom->poking) + return; + + as = &kbdev->as[kctx->as_nr]; + + spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags); + KBASE_DEBUG_ASSERT(as->poke_refcount > 0); + KBASE_DEBUG_ASSERT(as->poke_state & KBASE_AS_POKE_STATE_IN_FLIGHT); + + if (--(as->poke_refcount) == 0) { + as->poke_state |= KBASE_AS_POKE_STATE_KILLING_POKE; + spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags); + + hrtimer_cancel(&as->poke_timer); + flush_workqueue(as->poke_wq); + + spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags); + + /* Re-check whether it's still needed */ + if (as->poke_refcount) { + int queue_work_ret; + /* Poking still needed: + * - Another retain will not be starting the timer or queueing work, + * because it's still marked as in-flight + * - The hrtimer has finished, and has not started a new timer or + * queued work because it's been marked as killing + * + * So whatever happens now, just queue the work again */ + as->poke_state &= ~((kbase_as_poke_state)KBASE_AS_POKE_STATE_KILLING_POKE); + queue_work_ret = queue_work(as->poke_wq, &as->poke_work); + KBASE_DEBUG_ASSERT(queue_work_ret); + } else { + /* It isn't - so mark it as not in flight, and not killing */ + as->poke_state = 0u; + + /* The poke associated with the atom has now finished. If this is + * also the last atom on the context, then we can guarentee no more + * pokes (and thus no more poking register accesses) will occur on + * the context until new atoms are run */ + } + } + spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags); + + katom->poking = 0; +} + +void kbase_mmu_interrupt_process(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_as *as) +{ + struct kbasep_js_device_data *js_devdata = &kbdev->js_data; + unsigned long flags; + + if (kctx == NULL) { + dev_warn(kbdev->dev, "%s in AS%d at 0x%016llx with no context present! Suprious IRQ or SW Design Error?\n", + kbase_as_has_bus_fault(as) ? "Bus error" : "Page fault", + as->number, as->fault_addr); + } + + if (kbase_as_has_bus_fault(as)) { + if (kctx) { + /* + * hw counters dumping in progress, signal the + * other thread that it failed + */ + if ((kbdev->hwcnt.kctx == kctx) && + (kbdev->hwcnt.state == KBASE_INSTR_STATE_DUMPING)) + kbdev->hwcnt.state = KBASE_INSTR_STATE_FAULT; + + /* + * Stop the kctx from submitting more jobs and cause it + * to be scheduled out/rescheduled when all references + * to it are released + */ + spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags); + kbasep_js_clear_submit_allowed(js_devdata, kctx); + spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, + flags); + + dev_warn(kbdev->dev, "Bus error in AS%d at 0x%016llx\n", + as->number, as->fault_addr); + } + + /* + * We need to switch to UNMAPPED mode - but we do this in a + * worker so that we can sleep + */ + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&as->work_busfault)); + INIT_WORK(&as->work_busfault, bus_fault_worker); + queue_work(as->pf_wq, &as->work_busfault); + } else { + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&as->work_pagefault)); + INIT_WORK(&as->work_pagefault, page_fault_worker); + queue_work(as->pf_wq, &as->work_pagefault); + } +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..876eae8abd7fc65ff84f65a7b2ba998427ca6c3e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw.h @@ -0,0 +1,121 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file + * Interface file for accessing MMU hardware functionality + */ + +/** + * @page mali_kbase_mmu_hw_page MMU hardware interface + * + * @section mali_kbase_mmu_hw_intro_sec Introduction + * This module provides an abstraction for accessing the functionality provided + * by the midgard MMU and thus allows all MMU HW access to be contained within + * one common place and allows for different backends (implementations) to + * be provided. + */ + +#ifndef _MALI_KBASE_MMU_HW_H_ +#define _MALI_KBASE_MMU_HW_H_ + +/* Forward declarations */ +struct kbase_device; +struct kbase_as; +struct kbase_context; + +/** + * @addtogroup base_kbase_api + * @{ + */ + +/** + * @addtogroup mali_kbase_mmu_hw MMU access APIs + * @{ + */ + +/** @brief MMU fault type descriptor. + */ +enum kbase_mmu_fault_type { + KBASE_MMU_FAULT_TYPE_UNKNOWN = 0, + KBASE_MMU_FAULT_TYPE_PAGE, + KBASE_MMU_FAULT_TYPE_BUS +}; + +/** @brief Configure an address space for use. + * + * Configure the MMU using the address space details setup in the + * @ref kbase_context structure. + * + * @param[in] kbdev kbase device to configure. + * @param[in] as address space to configure. + * @param[in] kctx kbase context to configure. + */ +void kbase_mmu_hw_configure(struct kbase_device *kbdev, + struct kbase_as *as, struct kbase_context *kctx); + +/** @brief Issue an operation to the MMU. + * + * Issue an operation (MMU invalidate, MMU flush, etc) on the address space that + * is associated with the provided @ref kbase_context over the specified range + * + * @param[in] kbdev kbase device to issue the MMU operation on. + * @param[in] as address space to issue the MMU operation on. + * @param[in] kctx kbase context to issue the MMU operation on. + * @param[in] vpfn MMU Virtual Page Frame Number to start the + * operation on. + * @param[in] nr Number of pages to work on. + * @param[in] type Operation type (written to ASn_COMMAND). + * @param[in] handling_irq Is this operation being called during the handling + * of an interrupt? + * + * @return Zero if the operation was successful, non-zero otherwise. + */ +int kbase_mmu_hw_do_operation(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, u64 vpfn, u32 nr, u32 type, + unsigned int handling_irq); + +/** @brief Clear a fault that has been previously reported by the MMU. + * + * Clear a bus error or page fault that has been reported by the MMU. + * + * @param[in] kbdev kbase device to clear the fault from. + * @param[in] as address space to clear the fault from. + * @param[in] kctx kbase context to clear the fault from or NULL. + * @param[in] type The type of fault that needs to be cleared. + */ +void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type); + +/** @brief Enable fault that has been previously reported by the MMU. + * + * After a page fault or bus error has been reported by the MMU these + * will be disabled. After these are handled this function needs to be + * called to enable the page fault or bus error fault again. + * + * @param[in] kbdev kbase device to again enable the fault from. + * @param[in] as address space to again enable the fault from. + * @param[in] kctx kbase context to again enable the fault from. + * @param[in] type The type of fault that needs to be enabled again. + */ +void kbase_mmu_hw_enable_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type); + +/** @} *//* end group mali_kbase_mmu_hw */ +/** @} *//* end group base_kbase_api */ + +#endif /* _MALI_KBASE_MMU_HW_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.c new file mode 100644 index 0000000000000000000000000000000000000000..7ce94e922584c55d14f65f6586284933d169f1e5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.c @@ -0,0 +1,294 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include + +#include +#include +#include +#include + +#if KBASE_MMU_HW_BACKEND + +static inline u64 lock_region(struct kbase_device *kbdev, u64 pfn, + u32 num_pages) +{ + u64 region; + + /* can't lock a zero sized range */ + KBASE_DEBUG_ASSERT(num_pages); + + region = pfn << PAGE_SHIFT; + /* + * fls returns (given the ASSERT above): + * 1 .. 32 + * + * 10 + fls(num_pages) + * results in the range (11 .. 42) + */ + + /* gracefully handle num_pages being zero */ + if (0 == num_pages) { + region |= 11; + } else { + u8 region_width; + + region_width = 10 + fls(num_pages); + if (num_pages != (1ul << (region_width - 11))) { + /* not pow2, so must go up to the next pow2 */ + region_width += 1; + } + KBASE_DEBUG_ASSERT(region_width <= KBASE_LOCK_REGION_MAX_SIZE); + KBASE_DEBUG_ASSERT(region_width >= KBASE_LOCK_REGION_MIN_SIZE); + region |= region_width; + } + + return region; +} + +static int wait_ready(struct kbase_device *kbdev, + unsigned int as_nr, struct kbase_context *kctx) +{ + unsigned int max_loops = KBASE_AS_INACTIVE_MAX_LOOPS; + + /* Wait for the MMU status to indicate there is no active command. */ + while (--max_loops && kbase_reg_read(kbdev, + MMU_AS_REG(as_nr, AS_STATUS), + kctx) & AS_STATUS_AS_ACTIVE) { + ; + } + + if (max_loops == 0) { + dev_err(kbdev->dev, "AS_ACTIVE bit stuck\n"); + return -1; + } + + return 0; +} + +static int write_cmd(struct kbase_device *kbdev, int as_nr, u32 cmd, + struct kbase_context *kctx) +{ + int status; + + /* write AS_COMMAND when MMU is ready to accept another command */ + status = wait_ready(kbdev, as_nr, kctx); + if (status == 0) + kbase_reg_write(kbdev, MMU_AS_REG(as_nr, AS_COMMAND), cmd, kctx); + + return status; +} + +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat) +{ + const int num_as = 16; + const int busfault_shift = MMU_PAGE_FAULT_FLAGS; + const int pf_shift = 0; + const unsigned long as_bit_mask = (1UL << num_as) - 1; + unsigned long flags; + u32 new_mask; + u32 tmp; + + /* bus faults */ + u32 bf_bits = (irq_stat >> busfault_shift) & as_bit_mask; + /* page faults (note: Ignore ASes with both pf and bf) */ + u32 pf_bits = ((irq_stat >> pf_shift) & as_bit_mask) & ~bf_bits; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + + /* remember current mask */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + new_mask = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL); + /* mask interrupts for now */ + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0, NULL); + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); + + while (bf_bits | pf_bits) { + struct kbase_as *as; + int as_no; + struct kbase_context *kctx; + + /* + * the while logic ensures we have a bit set, no need to check + * for not-found here + */ + as_no = ffs(bf_bits | pf_bits) - 1; + as = &kbdev->as[as_no]; + + /* + * Refcount the kctx ASAP - it shouldn't disappear anyway, since + * Bus/Page faults _should_ only occur whilst jobs are running, + * and a job causing the Bus/Page fault shouldn't complete until + * the MMU is updated + */ + kctx = kbasep_js_runpool_lookup_ctx(kbdev, as_no); + + /* find faulting address */ + as->fault_addr = kbase_reg_read(kbdev, + MMU_AS_REG(as_no, AS_FAULTADDRESS_HI), + kctx); + as->fault_addr <<= 32; + as->fault_addr |= kbase_reg_read(kbdev, + MMU_AS_REG(as_no, AS_FAULTADDRESS_LO), + kctx); + + /* record the fault status */ + as->fault_status = kbase_reg_read(kbdev, + MMU_AS_REG(as_no, AS_FAULTSTATUS), + kctx); + + /* find the fault type */ + as->fault_type = (bf_bits & (1 << as_no)) ? + KBASE_MMU_FAULT_TYPE_BUS : + KBASE_MMU_FAULT_TYPE_PAGE; + + if (kbase_as_has_bus_fault(as)) { + /* Mark bus fault as handled. + * Note that a bus fault is processed first in case + * where both a bus fault and page fault occur. + */ + bf_bits &= ~(1UL << as_no); + + /* remove the queued BF (and PF) from the mask */ + new_mask &= ~(MMU_BUS_ERROR(as_no) | + MMU_PAGE_FAULT(as_no)); + } else { + /* Mark page fault as handled */ + pf_bits &= ~(1UL << as_no); + + /* remove the queued PF from the mask */ + new_mask &= ~MMU_PAGE_FAULT(as_no); + } + + /* Process the interrupt for this address space */ + kbase_mmu_interrupt_process(kbdev, kctx, as); + } + + /* reenable interrupts */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + tmp = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), NULL); + new_mask |= tmp; + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), new_mask, NULL); + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); +} + +void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx) +{ + struct kbase_mmu_setup *current_setup = &as->current_setup; + + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSTAB_LO), + current_setup->transtab & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSTAB_HI), + (current_setup->transtab >> 32) & 0xFFFFFFFFUL, kctx); + + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_MEMATTR_LO), + current_setup->memattr & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_MEMATTR_HI), + (current_setup->memattr >> 32) & 0xFFFFFFFFUL, kctx); + write_cmd(kbdev, as->number, AS_COMMAND_UPDATE, kctx); +} + +int kbase_mmu_hw_do_operation(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, u64 vpfn, u32 nr, u32 op, + unsigned int handling_irq) +{ + int ret; + + if (op == AS_COMMAND_UNLOCK) { + /* Unlock doesn't require a lock first */ + ret = write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + } else { + u64 lock_addr = lock_region(kbdev, vpfn, nr); + + /* Lock the region that needs to be updated */ + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_LOCKADDR_LO), + lock_addr & 0xFFFFFFFFUL, kctx); + kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_LOCKADDR_HI), + (lock_addr >> 32) & 0xFFFFFFFFUL, kctx); + write_cmd(kbdev, as->number, AS_COMMAND_LOCK, kctx); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_3285) && + handling_irq) { + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), + (1UL << as->number), NULL); + write_cmd(kbdev, as->number, AS_COMMAND_LOCK, kctx); + } + + /* Run the MMU operation */ + write_cmd(kbdev, as->number, op, kctx); + + /* Wait for the flush to complete */ + ret = wait_ready(kbdev, as->number, kctx); + + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_9630)) { + /* Issue an UNLOCK command to ensure that valid page + tables are re-read by the GPU after an update. + Note that, the FLUSH command should perform all the + actions necessary, however the bus logs show that if + multiple page faults occur within an 8 page region + the MMU does not always re-read the updated page + table entries for later faults or is only partially + read, it subsequently raises the page fault IRQ for + the same addresses, the unlock ensures that the MMU + cache is flushed, so updates can be re-read. As the + region is now unlocked we need to issue 2 UNLOCK + commands in order to flush the MMU/uTLB, + see PRLAM-8812. + */ + write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK, kctx); + } + } + + return ret; +} + +void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type) +{ + u32 pf_bf_mask; + + /* Clear the page (and bus fault IRQ as well in case one occurred) */ + pf_bf_mask = MMU_PAGE_FAULT(as->number); + if (type == KBASE_MMU_FAULT_TYPE_BUS) + pf_bf_mask |= MMU_BUS_ERROR(as->number); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), pf_bf_mask, kctx); +} + +void kbase_mmu_hw_enable_fault(struct kbase_device *kbdev, struct kbase_as *as, + struct kbase_context *kctx, enum kbase_mmu_fault_type type) +{ + unsigned long flags; + u32 irq_mask; + + /* Enable the page fault IRQ (and bus fault IRQ as well in case one + * occurred) */ + spin_lock_irqsave(&kbdev->mmu_mask_change, flags); + + irq_mask = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK), kctx) | + MMU_PAGE_FAULT(as->number); + + if (type == KBASE_MMU_FAULT_TYPE_BUS) + irq_mask |= MMU_BUS_ERROR(as->number); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), irq_mask, kctx); + + spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); +} +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.h new file mode 100644 index 0000000000000000000000000000000000000000..9737dbb9aa2e22aad707ea0edab0fcf464dc9402 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_mmu_hw_direct.h @@ -0,0 +1,59 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file + * Interface file for the direct implementation for MMU hardware access + */ + +/** + * @page mali_kbase_mmu_hw_direct_page Direct MMU hardware interface + * + * @section mali_kbase_mmu_hw_direct_intro_sec Introduction + * This module provides the interface(s) that are required by the direct + * register access implementation of the MMU hardware interface + * @ref mali_kbase_mmu_hw_page . + */ + +#ifndef _MALI_KBASE_MMU_HW_DIRECT_H_ +#define _MALI_KBASE_MMU_HW_DIRECT_H_ + +#include + +/** + * @addtogroup mali_kbase_mmu_hw + * @{ + */ + +/** + * @addtogroup mali_kbase_mmu_hw_direct Direct register access to MMU + * @{ + */ + +/** @brief Process an MMU interrupt. + * + * Process the MMU interrupt that was reported by the @ref kbase_device. + * + * @param[in] kbdev kbase context to clear the fault from. + * @param[in] irq_stat Value of the MMU_IRQ_STATUS register + */ +void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat); + +/** @} *//* end group mali_kbase_mmu_hw_direct */ +/** @} *//* end group mali_kbase_mmu_hw */ + +#endif /* _MALI_KBASE_MMU_HW_DIRECT_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c new file mode 100644 index 0000000000000000000000000000000000000000..c36b9358949722c430eedc020839f3d9483b6ea4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c @@ -0,0 +1,142 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifdef CONFIG_MALI_PLATFORM_FAKE + +#include +#include +#include +#include +#include + +#ifdef CONFIG_MACH_MANTA +#include +#endif + +/* + * This file is included only for type definitions and functions belonging to + * specific platform folders. Do not add dependencies with symbols that are + * defined somewhere else. + */ +#include + +#define PLATFORM_CONFIG_RESOURCE_COUNT 4 +#define PLATFORM_CONFIG_IRQ_RES_COUNT 3 + +static struct platform_device *mali_device; + +#ifndef CONFIG_OF +/** + * @brief Convert data in struct kbase_io_resources struct to Linux-specific resources + * + * Function converts data in struct kbase_io_resources struct to an array of Linux resource structures. Note that function + * assumes that size of linux_resource array is at least PLATFORM_CONFIG_RESOURCE_COUNT. + * Resources are put in fixed order: I/O memory region, job IRQ, MMU IRQ, GPU IRQ. + * + * @param[in] io_resource Input IO resource data + * @param[out] linux_resources Pointer to output array of Linux resource structures + */ +static void kbasep_config_parse_io_resources(const struct kbase_io_resources *io_resources, struct resource *const linux_resources) +{ + if (!io_resources || !linux_resources) { + pr_err("%s: couldn't find proper resources\n", __func__); + return; + } + + memset(linux_resources, 0, PLATFORM_CONFIG_RESOURCE_COUNT * sizeof(struct resource)); + + linux_resources[0].start = io_resources->io_memory_region.start; + linux_resources[0].end = io_resources->io_memory_region.end; + linux_resources[0].flags = IORESOURCE_MEM; + linux_resources[1].start = io_resources->job_irq_number; + linux_resources[1].end = io_resources->job_irq_number; + linux_resources[1].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; + + linux_resources[2].start = io_resources->mmu_irq_number; + linux_resources[2].end = io_resources->mmu_irq_number; + linux_resources[2].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; + + linux_resources[3].start = io_resources->gpu_irq_number; + linux_resources[3].end = io_resources->gpu_irq_number; + linux_resources[3].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; +} +#endif /* CONFIG_OF */ + +int kbase_platform_fake_register(void) +{ + struct kbase_platform_config *config; + int attribute_count; +#ifndef CONFIG_OF + struct resource resources[PLATFORM_CONFIG_RESOURCE_COUNT]; +#endif + int err; + + config = kbase_get_platform_config(); /* declared in midgard/mali_kbase_config.h but defined in platform folder */ + if (config == NULL) { + pr_err("%s: couldn't get platform config\n", __func__); + return -ENODEV; + } + + attribute_count = kbasep_get_config_attribute_count(config->attributes); +#ifdef CONFIG_MACH_MANTA + err = platform_device_add_data(&exynos5_device_g3d, config->attributes, attribute_count * sizeof(config->attributes[0])); + if (err) + return err; +#else + + mali_device = platform_device_alloc("mali", 0); + if (mali_device == NULL) + return -ENOMEM; + +#ifndef CONFIG_OF + kbasep_config_parse_io_resources(config->io_resources, resources); + err = platform_device_add_resources(mali_device, resources, PLATFORM_CONFIG_RESOURCE_COUNT); + if (err) { + platform_device_put(mali_device); + mali_device = NULL; + return err; + } +#endif /* CONFIG_OF */ + + err = platform_device_add_data(mali_device, config->attributes, attribute_count * sizeof(config->attributes[0])); + if (err) { + platform_device_unregister(mali_device); + mali_device = NULL; + return err; + } + + err = platform_device_add(mali_device); + if (err) { + platform_device_unregister(mali_device); + mali_device = NULL; + return err; + } +#endif /* CONFIG_CONFIG_MACH_MANTA */ + + return 0; +} +EXPORT_SYMBOL(kbase_platform_fake_register); + +void kbase_platform_fake_unregister(void) +{ + if (mali_device) + platform_device_unregister(mali_device); +} +EXPORT_SYMBOL(kbase_platform_fake_unregister); + +#endif /* CONFIG_MALI_PLATFORM_FAKE */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.c new file mode 100644 index 0000000000000000000000000000000000000000..dd5dc0263f2dba67d14bd6be2d9500641513a984 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.c @@ -0,0 +1,521 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm.c + * Base kernel power management APIs + */ + +#include +#include + +#include + +#if KBASE_PM_EN + +/* MTK GPU DVFS */ +#include "mach/mt_gpufreq.h" + +unsigned int g_current_gpu_platform_id = 0; + +mtk_gpu_freq_limit_data mt6755_gpu_freq_limit_data[MTK_MT6752_GPU_LIMIT_COUNT]= +{ {6, 3, (const int[]){0,3,5}}, // MT6752; no limit + {4, 3, (const int[]){0,1,3}}, // MT6752M, MT6751, MT6733; limit@600MHz + {3, 2, (const int[]){0,2}} // MT6732, MT6732M; limit@500MHz +}; + +extern unsigned int (*mtk_get_gpu_loading_fp)(void); +extern void (*mtk_boost_gpu_freq_fp)(void); +extern void (*mtk_custom_boost_gpu_freq_fp)(unsigned int ui32FreqLevel); +extern void (*mtk_set_bottom_gpu_freq_fp)(unsigned int ui32FreqLevel); +extern unsigned int (*mtk_custom_get_gpu_freq_level_count_fp)(void); + +/* for MTK GPU boost and power limit */ +extern void mt_gpufreq_input_boost_notify_registerCB(gpufreq_input_boost_notify pCB); +extern void mt_gpufreq_power_limit_notify_registerCB(gpufreq_power_limit_notify pCB); + +unsigned int mtk_get_current_gpu_platform_id() +{ + return g_current_gpu_platform_id; +} + +void _mtk_gpu_dvfs_init() +{ + int i; + unsigned int iCurrentFreqCount; + pr_debug("[MALI] _mtk_gpu_dvfs_init\n"); + + iCurrentFreqCount = mt_gpufreq_get_dvfs_table_num(); + + // get curent platform index + for(i=0 ; iconfig_attributes, KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS); + + if (callbacks) + callbacks->power_on_callback(kbdev); +} + +void kbase_pm_register_access_disable(struct kbase_device *kbdev) +{ + struct kbase_pm_callback_conf *callbacks; + + callbacks = (struct kbase_pm_callback_conf *)kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS); + + if (callbacks) + callbacks->power_off_callback(kbdev); +} + +mali_error kbase_pm_init(struct kbase_device *kbdev) +{ + mali_error ret = MALI_ERROR_NONE; + struct kbase_pm_callback_conf *callbacks; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_init(&kbdev->pm.lock); + + kbdev->pm.gpu_powered = MALI_FALSE; + kbdev->pm.suspending = MALI_FALSE; +#ifdef CONFIG_MALI_DEBUG + kbdev->pm.driver_ready_for_irqs = MALI_FALSE; +#endif /* CONFIG_MALI_DEBUG */ + kbdev->pm.gpu_in_desired_state = MALI_TRUE; + init_waitqueue_head(&kbdev->pm.gpu_in_desired_state_wait); + + callbacks = (struct kbase_pm_callback_conf *)kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS); + if (callbacks) { + kbdev->pm.callback_power_on = callbacks->power_on_callback; + kbdev->pm.callback_power_off = callbacks->power_off_callback; + kbdev->pm.callback_power_suspend = + callbacks->power_suspend_callback; + kbdev->pm.callback_power_resume = + callbacks->power_resume_callback; + kbdev->pm.callback_power_runtime_init = callbacks->power_runtime_init_callback; + kbdev->pm.callback_power_runtime_term = callbacks->power_runtime_term_callback; + kbdev->pm.callback_power_runtime_on = callbacks->power_runtime_on_callback; + kbdev->pm.callback_power_runtime_off = callbacks->power_runtime_off_callback; + } else { + kbdev->pm.callback_power_on = NULL; + kbdev->pm.callback_power_off = NULL; + kbdev->pm.callback_power_suspend = NULL; + kbdev->pm.callback_power_resume = NULL; + kbdev->pm.callback_power_runtime_init = NULL; + kbdev->pm.callback_power_runtime_term = NULL; + kbdev->pm.callback_power_runtime_on = NULL; + kbdev->pm.callback_power_runtime_off = NULL; + } + + /* MTK GPU DVFS init */ + _mtk_gpu_dvfs_init(); + + /* MTK Register input boost and power limit call back function */ + mt_gpufreq_input_boost_notify_registerCB(mtk_gpu_input_boost_CB); + mt_gpufreq_power_limit_notify_registerCB(mtk_gpu_power_limit_CB); + + /* Register gpu boost function to MTK HAL */ + mtk_boost_gpu_freq_fp = mtk_kbase_boost_gpu_freq; + mtk_custom_boost_gpu_freq_fp = mtk_kbase_custom_boost_gpu_freq; /* used for for performance service boost */ + mtk_set_bottom_gpu_freq_fp = mtk_kbase_ged_bottom_gpu_freq; /* used for GED boost */ + mtk_custom_get_gpu_freq_level_count_fp = mtk_kbase_custom_get_gpu_freq_level_count; + + /* MTK MET use */ + mtk_get_gpu_loading_fp = kbasep_get_gl_utilization; + + kbdev->pm.platform_dvfs_frequency = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ); + + /* Initialise the metrics subsystem */ + ret = kbasep_pm_metrics_init(kbdev); + if (MALI_ERROR_NONE != ret) + return ret; + + init_waitqueue_head(&kbdev->pm.l2_powered_wait); + kbdev->pm.l2_powered = 0; + + init_waitqueue_head(&kbdev->pm.reset_done_wait); + kbdev->pm.reset_done = MALI_FALSE; + + init_waitqueue_head(&kbdev->pm.zero_active_count_wait); + kbdev->pm.active_count = 0; + + spin_lock_init(&kbdev->pm.power_change_lock); + spin_lock_init(&kbdev->pm.gpu_cycle_counter_requests_lock); + spin_lock_init(&kbdev->pm.gpu_powered_lock); + + if (MALI_ERROR_NONE != kbase_pm_ca_init(kbdev)) + goto workq_fail; + + if (MALI_ERROR_NONE != kbase_pm_policy_init(kbdev)) + goto pm_policy_fail; + + return MALI_ERROR_NONE; + +pm_policy_fail: + kbase_pm_ca_term(kbdev); +workq_fail: + kbasep_pm_metrics_term(kbdev); + return MALI_ERROR_FUNCTION_FAILED; +} + +KBASE_EXPORT_TEST_API(kbase_pm_init) + +void kbase_pm_do_poweron(struct kbase_device *kbdev, mali_bool is_resume) +{ + lockdep_assert_held(&kbdev->pm.lock); + + /* Turn clocks and interrupts on - no-op if we haven't done a previous + * kbase_pm_clock_off() */ + kbase_pm_clock_on(kbdev, is_resume); + + /* Update core status as required by the policy */ + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_START); + kbase_pm_update_cores_state(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_END); + + /* NOTE: We don't wait to reach the desired state, since running atoms + * will wait for that state to be reached anyway */ +} + +void kbase_pm_do_poweroff(struct kbase_device *kbdev, mali_bool is_suspend) +{ + unsigned long flags; + mali_bool cores_are_available; + + lockdep_assert_held(&kbdev->pm.lock); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + /* Force all cores off */ + kbdev->pm.desired_shader_state = 0; + + /* Force all cores to be unavailable, in the situation where + * transitions are in progress for some cores but not others, + * and kbase_pm_check_transitions_nolock can not immediately + * power off the cores */ + kbdev->shader_available_bitmap = 0; + kbdev->tiler_available_bitmap = 0; + kbdev->l2_available_bitmap = 0; + + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_START); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_END); + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* NOTE: We won't wait to reach the core's desired state, even if we're + * powering off the GPU itself too. It's safe to cut the power whilst + * they're transitioning to off, because the cores should be idle and all + * cache flushes should already have occurred */ + + /* Consume any change-state events */ + kbase_timeline_pm_check_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + /* Disable interrupts and turn the clock off */ + kbase_pm_clock_off(kbdev, is_suspend); +} + +mali_error kbase_pm_powerup(struct kbase_device *kbdev) +{ + unsigned long flags; + mali_error ret; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_lock(&kbdev->pm.lock); + + /* A suspend won't happen during startup/insmod */ + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + + /* Power up the GPU, don't enable IRQs as we are not ready to receive them. */ + ret = kbase_pm_init_hw(kbdev, MALI_FALSE); + if (ret != MALI_ERROR_NONE) { + mutex_unlock(&kbdev->pm.lock); + return ret; + } + + kbasep_pm_read_present_cores(kbdev); + + kbdev->pm.debug_core_mask = kbdev->shader_present_bitmap; + + /* Pretend the GPU is active to prevent a power policy turning the GPU cores off */ + kbdev->pm.active_count = 1; + + spin_lock_irqsave(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + /* Ensure cycle counter is off */ + kbdev->pm.gpu_cycle_counter_requests = 0; + spin_unlock_irqrestore(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + /* We are ready to receive IRQ's now as power policy is set up, so enable them now. */ +#ifdef CONFIG_MALI_DEBUG + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + kbdev->pm.driver_ready_for_irqs = MALI_TRUE; + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); +#endif + kbase_pm_enable_interrupts(kbdev); + + /* Turn on the GPU and any cores needed by the policy */ + kbase_pm_do_poweron(kbdev, MALI_FALSE); + mutex_unlock(&kbdev->pm.lock); + + /* Idle the GPU and/or cores, if the policy wants it to */ + kbase_pm_context_idle(kbdev); + + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_pm_powerup) + +void kbase_pm_context_active(struct kbase_device *kbdev) +{ + (void)kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE); +} + +int kbase_pm_context_active_handle_suspend(struct kbase_device *kbdev, enum kbase_pm_suspend_handler suspend_handler) +{ + int c; + int old_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* Trace timeline information about how long it took to handle the decision + * to powerup. Sometimes the event might be missed due to reading the count + * outside of mutex, but this is necessary to get the trace timing + * correct. */ + old_count = kbdev->pm.active_count; + if (old_count == 0) + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + + mutex_lock(&kbdev->pm.lock); + if (kbase_pm_is_suspending(kbdev)) { + switch (suspend_handler) { + case KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE: + if (kbdev->pm.active_count != 0) + break; + /* FALLTHROUGH */ + case KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE: + mutex_unlock(&kbdev->pm.lock); + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + return 1; + + case KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE: + /* FALLTHROUGH */ + default: + KBASE_DEBUG_ASSERT_MSG(MALI_FALSE, "unreachable"); + break; + } + } + c = ++kbdev->pm.active_count; + KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, c); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, PM_CONTEXT_ACTIVE, NULL, NULL, 0u, c); + + /* Trace the event being handled */ + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE); + + if (c == 1) { + /* First context active: Power on the GPU and any cores requested by + * the policy */ + kbase_pm_update_active(kbdev); + + kbasep_pm_record_gpu_active(kbdev); + } + + mutex_unlock(&kbdev->pm.lock); + + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_pm_context_active) + +void kbase_pm_context_idle(struct kbase_device *kbdev) +{ + int c; + int old_count; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* Trace timeline information about how long it took to handle the decision + * to powerdown. Sometimes the event might be missed due to reading the + * count outside of mutex, but this is necessary to get the trace timing + * correct. */ + old_count = kbdev->pm.active_count; + if (old_count == 0) + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_IDLE); + + mutex_lock(&kbdev->pm.lock); + + c = --kbdev->pm.active_count; + KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, c); + + KBASE_TRACE_ADD_REFCOUNT(kbdev, PM_CONTEXT_IDLE, NULL, NULL, 0u, c); + + KBASE_DEBUG_ASSERT(c >= 0); + + /* Trace the event being handled */ + if (old_count == 0) + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_IDLE); + + if (c == 0) { + /* Last context has gone idle */ + kbase_pm_update_active(kbdev); + + kbasep_pm_record_gpu_idle(kbdev); + + /* Wake up anyone waiting for this to become 0 (e.g. suspend). The + * waiters must synchronize with us by locking the pm.lock after + * waiting */ + wake_up(&kbdev->pm.zero_active_count_wait); + } + + mutex_unlock(&kbdev->pm.lock); +} + +KBASE_EXPORT_TEST_API(kbase_pm_context_idle) + +void kbase_pm_halt(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + mutex_lock(&kbdev->pm.lock); + kbase_pm_cancel_deferred_poweroff(kbdev); + kbase_pm_do_poweroff(kbdev, MALI_FALSE); + mutex_unlock(&kbdev->pm.lock); +} + +KBASE_EXPORT_TEST_API(kbase_pm_halt) + +void kbase_pm_term(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(kbdev->pm.active_count == 0); + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_cycle_counter_requests == 0); + + /* Free any resources the policy allocated */ + kbase_pm_policy_term(kbdev); + kbase_pm_ca_term(kbdev); + + /* Shut down the metrics subsystem */ + kbasep_pm_metrics_term(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_term) + +void kbase_pm_suspend(struct kbase_device *kbdev) +{ + int nr_keep_gpu_powered_ctxs; + + KBASE_DEBUG_ASSERT(kbdev); + + mutex_lock(&kbdev->pm.lock); + KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); + kbdev->pm.suspending = MALI_TRUE; + mutex_unlock(&kbdev->pm.lock); + + /* From now on, the active count will drop towards zero. Sometimes, it'll + * go up briefly before going down again. However, once it reaches zero it + * will stay there - guaranteeing that we've idled all pm references */ + + /* Suspend job scheduler and associated components, so that it releases all + * the PM active count references */ + kbasep_js_suspend(kbdev); + + /* Suspend any counter collection that might be happening */ + kbase_instr_hwcnt_suspend(kbdev); + + /* Cancel the keep_gpu_powered calls */ + for (nr_keep_gpu_powered_ctxs = atomic_read(&kbdev->keep_gpu_powered_count); + nr_keep_gpu_powered_ctxs > 0; + --nr_keep_gpu_powered_ctxs) { + kbase_pm_context_idle(kbdev); + } + + /* Wait for the active count to reach zero. This is not the same as + * waiting for a power down, since not all policies power down when this + * reaches zero. */ + wait_event(kbdev->pm.zero_active_count_wait, kbdev->pm.active_count == 0); + + /* NOTE: We synchronize with anything that was just finishing a + * kbase_pm_context_idle() call by locking the pm.lock below */ + + /* Force power off the GPU and all cores (regardless of policy), only after + * the PM active count reaches zero (otherwise, we risk turning it off + * prematurely) */ + mutex_lock(&kbdev->pm.lock); + kbase_pm_cancel_deferred_poweroff(kbdev); + kbase_pm_do_poweroff(kbdev, MALI_TRUE); + mutex_unlock(&kbdev->pm.lock); +} + +void kbase_pm_resume(struct kbase_device *kbdev) +{ + int nr_keep_gpu_powered_ctxs; + + /* MUST happen before any pm_context_active calls occur */ + mutex_lock(&kbdev->pm.lock); + kbdev->pm.suspending = MALI_FALSE; + kbase_pm_do_poweron(kbdev, MALI_TRUE); + mutex_unlock(&kbdev->pm.lock); + + /* Initial active call, to power on the GPU/cores if needed */ + kbase_pm_context_active(kbdev); + + /* Restore the keep_gpu_powered calls */ + for (nr_keep_gpu_powered_ctxs = atomic_read(&kbdev->keep_gpu_powered_count); + nr_keep_gpu_powered_ctxs > 0; + --nr_keep_gpu_powered_ctxs) { + kbase_pm_context_active(kbdev); + } + + /* Re-enable instrumentation, if it was previously disabled */ + kbase_instr_hwcnt_resume(kbdev); + + /* Resume any blocked atoms (which may cause contexts to be scheduled in + * and dependent atoms to run) */ + kbase_resume_suspended_soft_jobs(kbdev); + + /* Resume the Job Scheduler and associated components, and start running + * atoms */ + kbasep_js_resume(kbdev); + + /* Matching idle call, to power off the GPU/cores if we didn't actually + * need it and the policy doesn't want it on */ + kbase_pm_context_idle(kbdev); +} +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.h new file mode 100644 index 0000000000000000000000000000000000000000..ea0147e87413ddb74f60f6021940eaebc90f5e27 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm.h @@ -0,0 +1,934 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm.h + * Power management API definitions + */ + +#ifndef _KBASE_PM_H_ +#define _KBASE_PM_H_ + +#include +#include + +/* Forward definition - see mali_kbase.h */ +struct kbase_device; + +#include "mali_kbase_pm_ca.h" +#include "mali_kbase_pm_policy.h" + +#include "mali_kbase_pm_ca_fixed.h" +#if !MALI_CUSTOMER_RELEASE +#include "mali_kbase_pm_ca_random.h" +#endif + +#include "mali_kbase_pm_always_on.h" +#include "mali_kbase_pm_coarse_demand.h" +#include "mali_kbase_pm_demand.h" +#if !MALI_CUSTOMER_RELEASE +#include "mali_kbase_pm_demand_always_powered.h" +#include "mali_kbase_pm_fast_start.h" +#endif + +/** The types of core in a GPU. + * + * These enumerated values are used in calls to: + * - @ref kbase_pm_get_present_cores + * - @ref kbase_pm_get_active_cores + * - @ref kbase_pm_get_trans_cores + * - @ref kbase_pm_get_ready_cores. + * + * They specify which type of core should be acted on. These values are set in + * a manner that allows @ref core_type_to_reg function to be simpler and more + * efficient. + */ +enum kbase_pm_core_type { + KBASE_PM_CORE_L3 = L3_PRESENT_LO, /**< The L3 cache */ + KBASE_PM_CORE_L2 = L2_PRESENT_LO, /**< The L2 cache */ + KBASE_PM_CORE_SHADER = SHADER_PRESENT_LO, /**< Shader cores */ + KBASE_PM_CORE_TILER = TILER_PRESENT_LO /**< Tiler cores */ +}; +/* MTK DVFS */ +#define MTK_MT6752_GPU_LIMIT_COUNT 3 + +typedef struct _mtk_gpu_freq_limit_data{ + const int actual_freq_index_count; + const int virtual_freq_index_count; + const int *virtual_freq_index; +}mtk_gpu_freq_limit_data; + +extern mtk_gpu_freq_limit_data mt6755_gpu_freq_limit_data[]; + + +/** Initialize the power management framework. + * + * Must be called before any other power management function + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE if the power management framework was successfully initialized. + */ +mali_error kbase_pm_init(struct kbase_device *kbdev); + +/** Power up GPU after all modules have been initialized and interrupt handlers installed. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE if powerup was successful. + */ +mali_error kbase_pm_powerup(struct kbase_device *kbdev); + +/** + * Halt the power management framework. + * Should ensure that no new interrupts are generated, + * but allow any currently running interrupt handlers to complete successfully. + * The GPU is forced off by the time this function returns, regardless of + * whether or not the active power policy asks for the GPU to be powered off. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_halt(struct kbase_device *kbdev); + +/** Terminate the power management framework. + * + * No power management functions may be called after this + * (except @ref kbase_pm_init) + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_term(struct kbase_device *kbdev); + +/** Metrics data collected for use by the power management framework. + * + */ +struct kbasep_pm_metrics_data { + int vsync_hit; + int utilisation; + int util_gl_share; + int util_cl_share[2]; /* 2 is a max number of core groups we can have */ + ktime_t time_period_start; + u32 time_busy; + u32 time_idle; + u32 prev_busy; + u32 prev_idle; + mali_bool gpu_active; + u32 busy_cl[2]; + u32 busy_gl; + u32 active_cl_ctx[2]; + u32 active_gl_ctx; + + spinlock_t lock; + +#ifdef CONFIG_MALI_MIDGARD_DVFS + struct hrtimer timer; + mali_bool timer_active; +#endif + + void *platform_data; + struct kbase_device *kbdev; +}; + +/** Actions for DVFS. + * + * kbase_pm_get_dvfs_action will return one of these enumerated values to + * describe the action that the DVFS system should take. + */ +enum kbase_pm_dvfs_action { + KBASE_PM_DVFS_NOP, /**< No change in clock frequency is requested */ + KBASE_PM_DVFS_CLOCK_UP, /**< The clock frequency should be increased if possible */ + KBASE_PM_DVFS_CLOCK_DOWN, /**< The clock frequency should be decreased if possible */ + KBASE_PM_DVFS_NONSENSE /* [MTK] clear state, no need to do dvfs action */ +}; + +union kbase_pm_policy_data { + struct kbasep_pm_policy_always_on always_on; + struct kbasep_pm_policy_coarse_demand coarse_demand; + struct kbasep_pm_policy_demand demand; +#if !MALI_CUSTOMER_RELEASE + struct kbasep_pm_policy_demand_always_powered demand_always_powered; + struct kbasep_pm_policy_fast_start fast_start; +#endif +}; + +union kbase_pm_ca_policy_data { + struct kbasep_pm_ca_policy_fixed fixed; +#if !MALI_CUSTOMER_RELEASE + struct kbasep_pm_ca_policy_random random; +#endif +}; + +/** Data stored per device for power management. + * + * This structure contains data for the power management framework. There is one instance of this structure per device + * in the system. + */ +struct kbase_pm_device_data { + /** The lock protecting Power Management structures accessed + * outside of IRQ. + * + * This lock must also be held whenever the GPU is being powered on or off. + */ + struct mutex lock; + + /** The policy that is currently actively controlling core availability. + * + * @note: During an IRQ, this can be NULL when the policy is being changed + * with kbase_pm_ca_set_policy(). The change is protected under + * kbase_device::pm::power_change_lock. Direct access to this from IRQ + * context must therefore check for NULL. If NULL, then + * kbase_pm_ca_set_policy() will re-issue the policy functions that would've + * been done under IRQ. + */ + const struct kbase_pm_ca_policy *ca_current_policy; + + /** The policy that is currently actively controlling the power state. + * + * @note: During an IRQ, this can be NULL when the policy is being changed + * with kbase_pm_set_policy(). The change is protected under + * kbase_device::pm::power_change_lock. Direct access to this from IRQ + * context must therefore check for NULL. If NULL, then + * kbase_pm_set_policy() will re-issue the policy functions that would've + * been done under IRQ. + */ + const struct kbase_pm_policy *pm_current_policy; + + /** Private data for current CA policy */ + union kbase_pm_ca_policy_data ca_policy_data; + + /** Private data for current PM policy */ + union kbase_pm_policy_data pm_policy_data; + + /** Flag indicating when core availability policy is transitioning cores. + * The core availability policy must set this when a change in core availability + * is occuring. + * + * power_change_lock must be held when accessing this. */ + mali_bool ca_in_transition; + + /** Waiting for reset and a queue to wait for changes */ + mali_bool reset_done; + wait_queue_head_t reset_done_wait; + + /** Wait queue for whether the l2 cache has been powered as requested */ + wait_queue_head_t l2_powered_wait; + /** State indicating whether all the l2 caches are powered. + * Non-zero indicates they're *all* powered + * Zero indicates that some (or all) are not powered */ + int l2_powered; + + /** The reference count of active contexts on this device. */ + int active_count; + /** Flag indicating suspending/suspended */ + mali_bool suspending; + /* Wait queue set when active_count == 0 */ + wait_queue_head_t zero_active_count_wait; + + /** The reference count of active gpu cycle counter users */ + int gpu_cycle_counter_requests; + /** Lock to protect gpu_cycle_counter_requests */ + spinlock_t gpu_cycle_counter_requests_lock; + + /** A bit mask identifying the shader cores that the power policy would like to be on. + * The current state of the cores may be different, but there should be transitions in progress that will + * eventually achieve this state (assuming that the policy doesn't change its mind in the mean time. + */ + u64 desired_shader_state; + /** bit mask indicating which shader cores are currently in a power-on transition */ + u64 powering_on_shader_state; + /** A bit mask identifying the tiler cores that the power policy would like to be on. + * @see kbase_pm_device_data:desired_shader_state */ + u64 desired_tiler_state; + /** bit mask indicating which tiler core are currently in a power-on transition */ + u64 powering_on_tiler_state; + + /** bit mask indicating which l2-caches are currently in a power-on transition */ + u64 powering_on_l2_state; + /** bit mask indicating which l3-caches are currently in a power-on transition */ + u64 powering_on_l3_state; + + /** Lock protecting the power state of the device. + * + * This lock must be held when accessing the shader_available_bitmap, tiler_available_bitmap, l2_available_bitmap, + * shader_inuse_bitmap and tiler_inuse_bitmap fields of kbase_device, and the ca_in_transition and shader_poweroff_pending + * fields of kbase_pm_device_data. It is also held when the hardware power registers are being written to, to ensure + * that two threads do not conflict over the power transitions that the hardware should make. + */ + spinlock_t power_change_lock; + + /** This flag is set iff the GPU is powered as requested by the + * desired_xxx_state variables */ + mali_bool gpu_in_desired_state; + /* Wait queue set when gpu_in_desired_state != 0 */ + wait_queue_head_t gpu_in_desired_state_wait; + + /** Set to true when the GPU is powered and register accesses are possible, false otherwise */ + mali_bool gpu_powered; + + /** A bit mask identifying the available shader cores that are specified via sysfs */ + u64 debug_core_mask; + + /** Set to true when instrumentation is enabled, false otherwise */ + mali_bool instr_enabled; + + mali_bool cg1_disabled; + +#ifdef CONFIG_MALI_DEBUG + /** Debug state indicating whether sufficient initialization of the driver + * has occurred to handle IRQs */ + mali_bool driver_ready_for_irqs; +#endif /* CONFIG_MALI_DEBUG */ + + /** Spinlock that must be held when: + * - writing gpu_powered + * - accessing driver_ready_for_irqs (in CONFIG_MALI_DEBUG builds) */ + spinlock_t gpu_powered_lock; + + /** Time in milliseconds between each dvfs sample */ + + u32 platform_dvfs_frequency; + + /** Structure to hold metrics for the GPU */ + + struct kbasep_pm_metrics_data metrics; + + /** Set to the number of poweroff timer ticks until the GPU is powered off */ + int gpu_poweroff_pending; + + /** Set to the number of poweroff timer ticks until shaders are powered off */ + int shader_poweroff_pending_time; + + /** Timer for powering off GPU */ + struct hrtimer gpu_poweroff_timer; + + struct workqueue_struct *gpu_poweroff_wq; + + struct work_struct gpu_poweroff_work; + + /** Period of GPU poweroff timer */ + ktime_t gpu_poweroff_time; + + /** Bit mask of shaders to be powered off on next timer callback */ + u64 shader_poweroff_pending; + + /** Set to MALI_TRUE if the poweroff timer is currently running, MALI_FALSE otherwise */ + mali_bool poweroff_timer_needed; + + int poweroff_shader_ticks; + + int poweroff_gpu_ticks; + + /** Callback when the GPU needs to be turned on. See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + * + * @return 1 if GPU state was lost, 0 otherwise + */ + int (*callback_power_on)(struct kbase_device *kbdev); + + /** Callback when the GPU may be turned off. See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + */ + void (*callback_power_off)(struct kbase_device *kbdev); + + /** Callback when a suspend occurs and the GPU needs to be turned off. + * See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + */ + void (*callback_power_suspend)(struct kbase_device *kbdev); + + /** Callback when a resume occurs and the GPU needs to be turned on. + * See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + */ + void (*callback_power_resume)(struct kbase_device *kbdev); + + /** Callback for initializing the runtime power management. + * + * @param kbdev The kbase device + * + * @return MALI_ERROR_NONE on success, else error code + */ + mali_error (*callback_power_runtime_init)(struct kbase_device *kbdev); + + /** Callback for terminating the runtime power management. + * + * @param kbdev The kbase device + */ + void (*callback_power_runtime_term)(struct kbase_device *kbdev); + + /** Callback when the GPU needs to be turned on. See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + * + * @return 1 if GPU state was lost, 0 otherwise + */ + int (*callback_power_runtime_on)(struct kbase_device *kbdev); + + /** Callback when the GPU may be turned off. See @ref kbase_pm_callback_conf + * + * @param kbdev The kbase device + */ + void (*callback_power_runtime_off)(struct kbase_device *kbdev); + +}; + +/** The GPU is idle. + * + * The OS may choose to turn off idle devices + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_dev_idle(struct kbase_device *kbdev); + +/** The GPU is active. + * + * The OS should avoid opportunistically turning off the GPU while it is active + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_dev_activate(struct kbase_device *kbdev); + +/** Get details of the cores that are present in the device. + * + * This function can be called by the active power policy to return a bitmask of the cores (of a specified type) + * present in the GPU device and also a count of the number of cores. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param type The type of core (see the @ref enum kbase_pm_core_type enumeration) + * + * @return The bit mask of cores present + */ +u64 kbase_pm_get_present_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); + +/** Get details of the cores that are currently active in the device. + * + * This function can be called by the active power policy to return a bitmask of the cores (of a specified type) that + * are actively processing work (i.e. turned on *and* busy). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param type The type of core (see the @ref enum kbase_pm_core_type enumeration) + * + * @return The bit mask of active cores + */ +u64 kbase_pm_get_active_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); + +/** Get details of the cores that are currently transitioning between power states. + * + * This function can be called by the active power policy to return a bitmask of the cores (of a specified type) that + * are currently transitioning between power states. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param type The type of core (see the @ref enum kbase_pm_core_type enumeration) + * + * @return The bit mask of transitioning cores + */ +u64 kbase_pm_get_trans_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); + +/** Get details of the cores that are currently powered and ready for jobs. + * + * This function can be called by the active power policy to return a bitmask of the cores (of a specified type) that + * are powered and ready for jobs (they may or may not be currently executing jobs). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param type The type of core (see the @ref enum kbase_pm_core_type enumeration) + * + * @return The bit mask of ready cores + */ +u64 kbase_pm_get_ready_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); + +/** Turn the clock for the device on, and enable device interrupts. + * + * This function can be used by a power policy to turn the clock for the GPU on. It should be modified during + * integration to perform the necessary actions to ensure that the GPU is fully powered and clocked. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param is_resume MALI_TRUE if clock on due to resume after suspend, + * MALI_FALSE otherwise + */ +void kbase_pm_clock_on(struct kbase_device *kbdev, mali_bool is_resume); + +/** Disable device interrupts, and turn the clock for the device off. + * + * This function can be used by a power policy to turn the clock for the GPU off. It should be modified during + * integration to perform the necessary actions to turn the clock off (if this is possible in the integration). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param is_suspend MALI_TRUE if clock off due to suspend, MALI_FALSE otherwise + */ +void kbase_pm_clock_off(struct kbase_device *kbdev, mali_bool is_suspend); + +/** Enable interrupts on the device. + * + * Interrupts are also enabled after a call to kbase_pm_clock_on(). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_enable_interrupts(struct kbase_device *kbdev); + +/** Disable interrupts on the device. + * + * This prevents delivery of Power Management interrupts to the CPU so that + * kbase_pm_check_transitions_nolock() will not be called from the IRQ handler + * until @ref kbase_pm_enable_interrupts or kbase_pm_clock_on() is called. + * + * Interrupts are also disabled after a call to kbase_pm_clock_off(). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_disable_interrupts(struct kbase_device *kbdev); + +/** Initialize the hardware + * + * This function checks the GPU ID register to ensure that the GPU is supported by the driver and performs a reset on + * the device so that it is in a known state before the device is used. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param enable_irqs When set to MALI_TRUE gpu irqs will be enabled after this call, else + * they will be left disabled. + * + * @return MALI_ERROR_NONE if the device is supported and successfully reset. + */ +mali_error kbase_pm_init_hw(struct kbase_device *kbdev, mali_bool enable_irqs); + +/** The GPU has been reset successfully. + * + * This function must be called by the GPU interrupt handler when the RESET_COMPLETED bit is set. It signals to the + * power management initialization code that the GPU has been successfully reset. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_reset_done(struct kbase_device *kbdev); + +/** Increment the count of active contexts. + * + * This function should be called when a context is about to submit a job. It informs the active power policy that the + * GPU is going to be in use shortly and the policy is expected to start turning on the GPU. + * + * This function will block until the GPU is available. + * + * This function ASSERTS if a suspend is occuring/has occurred whilst this is + * in use. Use kbase_pm_contect_active_unless_suspending() instead. + * + * @note a Suspend is only visible to Kernel threads; user-space threads in a + * syscall cannot witness a suspend, because they are frozen before the suspend + * begins. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_context_active(struct kbase_device *kbdev); + + +/** Handler codes for doing kbase_pm_context_active_handle_suspend() */ +enum kbase_pm_suspend_handler { + /** A suspend is not expected/not possible - this is the same as + * kbase_pm_context_active() */ + KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE, + /** If we're suspending, fail and don't increase the active count */ + KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE, + /** If we're suspending, succeed and allow the active count to increase iff + * it didn't go from 0->1 (i.e., we didn't re-activate the GPU). + * + * This should only be used when there is a bounded time on the activation + * (e.g. guarantee it's going to be idled very soon after) */ + KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE +}; + +/** Suspend 'safe' variant of kbase_pm_context_active() + * + * If a suspend is in progress, this allows for various different ways of + * handling the suspend. Refer to @ref enum kbase_pm_suspend_handler for details. + * + * We returns a status code indicating whether we're allowed to keep the GPU + * active during the suspend, depending on the handler code. If the status code + * indicates a failure, the caller must abort whatever operation it was + * attempting, and potentially queue it up for after the OS has resumed. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param suspend_handler The handler code for how to handle a suspend that might occur + * @return zero Indicates success + * @return non-zero Indicates failure due to the system being suspending/suspended. + */ +int kbase_pm_context_active_handle_suspend(struct kbase_device *kbdev, enum kbase_pm_suspend_handler suspend_handler); + +/** Decrement the reference count of active contexts. + * + * This function should be called when a context becomes idle. After this call the GPU may be turned off by the power + * policy so the calling code should ensure that it does not access the GPU's registers. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_context_idle(struct kbase_device *kbdev); + +/** Check if there are any power transitions to make, and if so start them. + * + * This function will check the desired_xx_state members of struct kbase_pm_device_data and the actual status of the + * hardware to see if any power transitions can be made at this time to make the hardware state closer to the state + * desired by the power policy. + * + * The return value can be used to check whether all the desired cores are + * available, and so whether it's worth submitting a job (e.g. from a Power + * Management IRQ). + * + * Note that this still returns MALI_TRUE when desired_xx_state has no + * cores. That is: of the no cores desired, none were unavailable. In + * this case, the caller may still need to try submitting jobs. This is because + * the Core Availability Policy might have taken us to an intermediate state + * where no cores are powered, before powering on more cores (e.g. for core + * rotation) + * + * The caller must hold kbase_device::pm::power_change_lock + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @return non-zero when all desired cores are available. That is, + * it's worthwhile for the caller to submit a job. + * @return MALI_FALSE otherwise + */ +mali_bool kbase_pm_check_transitions_nolock(struct kbase_device *kbdev); + +/** Synchronous and locking variant of kbase_pm_check_transitions_nolock() + * + * On returning, the desired state at the time of the call will have been met. + * + * @note There is nothing to stop the core being switched off by calls to + * kbase_pm_release_cores() or kbase_pm_unrequest_cores(). Therefore, the + * caller must have already made a call to + * kbase_pm_request_cores()/kbase_pm_request_cores_sync() previously. + * + * The usual use-case for this is to ensure cores are 'READY' after performing + * a GPU Reset. + * + * Unlike kbase_pm_check_transitions_nolock(), the caller must not hold + * kbase_device::pm::power_change_lock, because this function will take that + * lock itself. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_check_transitions_sync(struct kbase_device *kbdev); + +/** Variant of kbase_pm_update_cores_state() where the caller must hold + * kbase_device::pm::power_change_lock + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev); + +/** Update the desired state of shader cores from the Power Policy, and begin + * any power transitions. + * + * This function will update the desired_xx_state members of + * struct kbase_pm_device_data by calling into the current Power Policy. It will then + * begin power transitions to make the hardware acheive the desired shader core + * state. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_pm_update_cores_state(struct kbase_device *kbdev); + +/** Cancel any pending requests to power off the GPU and/or shader cores. + * + * This should be called by any functions which directly power off the GPU. + * + * @param kbdev The kbase device structure for the device (must be a valid + * pointer) + */ +void kbase_pm_cancel_deferred_poweroff(struct kbase_device *kbdev); + +/** Read the bitmasks of present cores. + * + * This information is cached to avoid having to perform register reads whenever the information is required. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_read_present_cores(struct kbase_device *kbdev); + +/** Initialize the metrics gathering framework. + * + * This must be called before other metric gathering APIs are called. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE on success, MALI_ERROR_FUNCTION_FAILED on error + */ +mali_error kbasep_pm_metrics_init(struct kbase_device *kbdev); + +/** Terminate the metrics gathering framework. + * + * This must be called when metric gathering is no longer required. It is an error to call any metrics gathering + * function (other than kbasep_pm_metrics_init) after calling this function. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_metrics_term(struct kbase_device *kbdev); + +/** Record state of jobs currently active on GPU. + * + * This function record time spent executing jobs split per GL and CL + * contexts, per core group (only CL jobs). + * + * @param kbdev The kbase device structure for the device + * (must be a valid pointer) + */ +void kbasep_pm_record_job_status(struct kbase_device *kbdev); + +/** Record that the GPU is active. + * + * This records that the GPU is now active. The previous GPU state must have been idle, the function will assert if + * this is not true in a debug build. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_record_gpu_active(struct kbase_device *kbdev); + +/** Record that the GPU is idle. + * + * This records that the GPU is now idle. The previous GPU state must have been active, the function will assert if + * this is not true in a debug build. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbasep_pm_record_gpu_idle(struct kbase_device *kbdev); + +/** Function to be called by the frame buffer driver to update the vsync metric. + * + * This function should be called by the frame buffer driver to update whether the system is hitting the vsync target + * or not. buffer_updated should be true if the vsync corresponded with a new frame being displayed, otherwise it + * should be false. This function does not need to be called every vsync, but only when the value of buffer_updated + * differs from a previous call. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param buffer_updated True if the buffer has been updated on this VSync, false otherwise + */ +void kbase_pm_report_vsync(struct kbase_device *kbdev, int buffer_updated); + +/** Configure the frame buffer device to set the vsync callback. + * + * This function should do whatever is necessary for this integration to ensure that kbase_pm_report_vsync is + * called appropriately. + * + * This function will need porting as part of the integration for a device. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_register_vsync_callback(struct kbase_device *kbdev); + +/** Free any resources that kbase_pm_register_vsync_callback allocated. + * + * This function should perform any cleanup required from the call to kbase_pm_register_vsync_callback. + * No call backs should occur after this function has returned. + * + * This function will need porting as part of the integration for a device. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_unregister_vsync_callback(struct kbase_device *kbdev); + +/** Determine whether the DVFS system should change the clock speed of the GPU. + * + * This function should be called regularly by the DVFS system to check whether the clock speed of the GPU needs + * updating. It will return one of three enumerated values of kbase_pm_dvfs_action: + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @retval KBASE_PM_DVFS_NOP The clock does not need changing + * @retval KBASE_PM_DVFS_CLOCK_UP, The clock frequency should be increased if possible. + * @retval KBASE_PM_DVFS_CLOCK_DOWN The clock frequency should be decreased if possible. + */ +enum kbase_pm_dvfs_action kbase_pm_get_dvfs_action(struct kbase_device *kbdev); + +/** Mark that the GPU cycle counter is needed, if the caller is the first caller + * then the GPU cycle counters will be enabled along with the l2 cache + * + * The GPU must be powered when calling this function (i.e. @ref kbase_pm_context_active must have been called). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_gpu_cycle_counter(struct kbase_device *kbdev); + +/** This is a version of the above function (@ref kbase_pm_request_gpu_cycle_counter) suitable for being + * called when the l2 cache is known to be on and assured to be on until the subsequent call of + * kbase_pm_release_gpu_cycle_counter such as when a job is submitted. + * It does not sleep and can be called from atomic functions. + * + * The GPU must be powered when calling this function (i.e. @ref kbase_pm_context_active must have been called). + * and the l2 cache must be powered on + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_gpu_cycle_counter_l2_is_on(struct kbase_device *kbdev); + +/** Mark that the GPU cycle counter is no longer in use, if the caller is the last + * caller then the GPU cycle counters will be disabled. A request must have been made + * before a call to this. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + +void kbase_pm_release_gpu_cycle_counter(struct kbase_device *kbdev); + +/** Enables access to the GPU registers before power management has powered up the GPU + * with kbase_pm_powerup(). + * + * Access to registers should be done using kbase_os_reg_read/write() at this stage, + * not kbase_reg_read/write(). + * + * This results in the power management callbacks provided in the driver configuration + * to get called to turn on power and/or clocks to the GPU. + * See @ref kbase_pm_callback_conf. + * + * This should only be used before power management is powered up with kbase_pm_powerup() + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_register_access_enable(struct kbase_device *kbdev); + +/** Disables access to the GPU registers enabled earlier by a call to + * kbase_pm_register_access_enable(). + * + * This results in the power management callbacks provided in the driver configuration + * to get called to turn off power and/or clocks to the GPU. + * See @ref kbase_pm_callback_conf + * + * This should only be used before power management is powered up with kbase_pm_powerup() + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_register_access_disable(struct kbase_device *kbdev); + +/** + * Suspend the GPU and prevent any further register accesses to it from Kernel + * threads. + * + * This is called in response to an OS suspend event, and calls into the various + * kbase components to complete the suspend. + * + * @note the mechanisms used here rely on all user-space threads being frozen + * by the OS before we suspend. Otherwise, an IOCTL could occur that powers up + * the GPU e.g. via atom submission. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_suspend(struct kbase_device *kbdev); + +/** + * Resume the GPU, allow register accesses to it, and resume running atoms on + * the GPU. + * + * This is called in response to an OS resume event, and calls into the various + * kbase components to complete the resume. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_resume(struct kbase_device *kbdev); + +/* NOTE: kbase_pm_is_suspending is in mali_kbase.h, because it is an inline function */ + +/** + * Check if the power management metrics collection is active. + * + * Note that this returns if the power management metrics collection was + * active at the time of calling, it is possible that after the call the metrics + * collection enable may have changed state. + * + * The caller must handle the consequence that the state may have changed. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @return MALI_TRUE if metrics collection was active else MALI_FALSE. + */ + +mali_bool kbase_pm_metrics_is_active(struct kbase_device *kbdev); + +/** + * Power on the GPU, and any cores that are requested. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param is_resume MALI_TRUE if power on due to resume after suspend, + * MALI_FALSE otherwise + */ +void kbase_pm_do_poweron(struct kbase_device *kbdev, mali_bool is_resume); + +/** + * Power off the GPU, and any cores that have been requested. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param is_suspend MALI_TRUE if power off due to suspend, + * MALI_FALSE otherwise + */ +void kbase_pm_do_poweroff(struct kbase_device *kbdev, mali_bool is_suspend); + +#ifdef CONFIG_PM_DEVFREQ +void kbase_pm_get_dvfs_utilisation(struct kbase_device *kbdev, + unsigned long *total, unsigned long *busy); +void kbase_pm_reset_dvfs_utilisation(struct kbase_device *kbdev); +#endif + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +/** + * Function provided by platform specific code when DVFS is enabled to allow + * the power management metrics system to report utilisation. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param utilisation The current calculated utilisation by the metrics system. + * @param util_gl_share The current calculated gl share of utilisation. + * @param util_cl_share The current calculated cl share of utilisation per core group. + * @return Returns 0 on failure and non zero on success. + */ + +int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, + u32 util_gl_share, u32 util_cl_share[2]); +#endif + +void proc_mali_register(void); +void proc_mali_unregister(void); + +u32 kbasep_get_gl_utilization(void); +u32 kbasep_get_cl_js0_utilization(void); +u32 kbasep_get_cl_js1_utilization(void); + +enum kbase_pm_dvfs_action mtk_get_dvfs_action(void); + +void mtk_clear_dvfs_action(void); +int mtk_get_dvfs_enabled(void); +unsigned int mtk_get_current_gpu_platform_id(void); + +void mtk_gpu_input_boost_CB(unsigned int ui32BoostFreqID); +void mtk_gpu_power_limit_CB(unsigned int ui32LimitFreqID); + +int mtk_get_input_boost_enabled(void); + +void mtk_kbase_boost_gpu_freq(void); + +void mtk_kbase_custom_boost_gpu_freq(unsigned int ui32FreqLevel); +void mtk_kbase_ged_bottom_gpu_freq(unsigned int ui32FreqLevel); +unsigned int mtk_kbase_custom_get_gpu_freq_level_count(void); + +int mtk_get_dvfs_freq(void); +int mtk_get_dvfs_threshold_max(void); +int mtk_get_dvfs_threshold_min(void); +int mtk_get_dvfs_deferred_count(void); + +void mtk_get_touch_boost_flag(int *touch_boost_flag, int *touch_boost_id); +void mtk_set_touch_boost_flag(int boost_id); +void mtk_clear_touch_boost_flag(void); + +#endif /* _KBASE_PM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.c new file mode 100644 index 0000000000000000000000000000000000000000..4d3878b50937fc4cea2d80da64c5ccdebb98f0e7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.c @@ -0,0 +1,64 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_always_on.c + * "Always on" power management policy + */ + +#include +#include + +#if KBASE_PM_EN +static u64 always_on_get_core_mask(struct kbase_device *kbdev) +{ + return kbdev->shader_present_bitmap; +} + +static mali_bool always_on_get_core_active(struct kbase_device *kbdev) +{ + return MALI_TRUE; +} + +static void always_on_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void always_on_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/** The @ref struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback and name. + */ +const struct kbase_pm_policy kbase_pm_always_on_policy_ops = { + "always_on", /* name */ + always_on_init, /* init */ + always_on_term, /* term */ + always_on_get_core_mask, /* get_core_mask */ + always_on_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_ALWAYS_ON, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_always_on_policy_ops) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.h new file mode 100644 index 0000000000000000000000000000000000000000..a3858045bd0c235bab3a49fece49c50fa2ca04f2 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_always_on.h @@ -0,0 +1,68 @@ + +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_always_on.h + * "Always on" power management policy + */ + +#ifndef MALI_KBASE_PM_ALWAYS_ON_H +#define MALI_KBASE_PM_ALWAYS_ON_H + +/** + * The "Always on" power management policy has the following + * characteristics: + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * - All Shader Cores are powered up, regardless of whether or not they will + * be needed later. + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * - All Shader Cores are kept powered, regardless of whether or not they will + * be needed + * - When KBase indicates that the GPU need not be powered: + * - The Shader Cores are kept powered, regardless of whether or not they will + * be needed. The GPU itself is also kept powered, even though it is not + * needed. + * + * This policy is automatically overridden during system suspend: the desired + * core state is ignored, and the cores are forced off regardless of what the + * policy requests. After resuming from suspend, new changes to the desired + * core state made by the policy are honored. + * + * @note: + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * Private structure for policy instance data. + * + * This contains data that is private to the particular power policy that is active. + */ +typedef struct kbasep_pm_policy_always_on { + /** No state needed - just have a dummy variable here */ + int dummy; +} kbasep_pm_policy_always_on; + +#endif /* MALI_KBASE_PM_ALWAYS_ON_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.c new file mode 100644 index 0000000000000000000000000000000000000000..9d5fb94c8218dd619b97be195e700828ebc22e0e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.c @@ -0,0 +1,173 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_ca.c + * Base kernel core availability APIs + */ + +#include +#include +#if KBASE_PM_EN +extern const struct kbase_pm_ca_policy kbase_pm_ca_fixed_policy_ops; +#if !MALI_CUSTOMER_RELEASE +extern const struct kbase_pm_ca_policy kbase_pm_ca_random_policy_ops; +#endif + +static const struct kbase_pm_ca_policy *const policy_list[] = { + &kbase_pm_ca_fixed_policy_ops, +#if !MALI_CUSTOMER_RELEASE + &kbase_pm_ca_random_policy_ops +#endif +}; + +/** The number of policies available in the system. + * This is derived from the number of functions listed in policy_get_functions. + */ +#define POLICY_COUNT (sizeof(policy_list)/sizeof(*policy_list)) + +mali_error kbase_pm_ca_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + kbdev->pm.ca_current_policy = policy_list[0]; + + kbdev->pm.ca_current_policy->init(kbdev); + + return MALI_ERROR_NONE; +} + +void kbase_pm_ca_term(struct kbase_device *kbdev) +{ + kbdev->pm.ca_current_policy->term(kbdev); +} + +int kbase_pm_ca_list_policies(const struct kbase_pm_ca_policy * const **list) +{ + if (!list) + return POLICY_COUNT; + + *list = policy_list; + + return POLICY_COUNT; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_list_policies) + +const struct kbase_pm_ca_policy *kbase_pm_ca_get_policy(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return kbdev->pm.ca_current_policy; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_get_policy) + +void kbase_pm_ca_set_policy(struct kbase_device *kbdev, const struct kbase_pm_ca_policy *new_policy) +{ + const struct kbase_pm_ca_policy *old_policy; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(new_policy != NULL); + + KBASE_TRACE_ADD(kbdev, PM_CA_SET_POLICY, NULL, NULL, 0u, new_policy->id); + + /* During a policy change we pretend the GPU is active */ + /* A suspend won't happen here, because we're in a syscall from a userspace thread */ + kbase_pm_context_active(kbdev); + + mutex_lock(&kbdev->pm.lock); + + /* Remove the policy to prevent IRQ handlers from working on it */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + old_policy = kbdev->pm.ca_current_policy; + kbdev->pm.ca_current_policy = NULL; + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + if (old_policy->term) + old_policy->term(kbdev); + + if (new_policy->init) + new_policy->init(kbdev); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbdev->pm.ca_current_policy = new_policy; + + /* If any core power state changes were previously attempted, but couldn't + * be made because the policy was changing (current_policy was NULL), then + * re-try them here. */ + kbase_pm_update_cores_state_nolock(kbdev); + + kbdev->pm.ca_current_policy->update_core_status(kbdev, kbdev->shader_ready_bitmap, kbdev->shader_transitioning_bitmap); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + mutex_unlock(&kbdev->pm.lock); + + /* Now the policy change is finished, we release our fake context active reference */ + kbase_pm_context_idle(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_set_policy) + +u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.power_change_lock); + + /* All cores must be enabled when instrumentation is in use */ + if (kbdev->pm.instr_enabled == MALI_TRUE) + return kbdev->shader_present_bitmap & kbdev->pm.debug_core_mask; + + if (kbdev->pm.ca_current_policy == NULL) + return kbdev->shader_present_bitmap & kbdev->pm.debug_core_mask; + + return kbdev->pm.ca_current_policy->get_core_mask(kbdev) & kbdev->pm.debug_core_mask; +} + +KBASE_EXPORT_TEST_API(kbase_pm_ca_get_core_mask) + +void kbase_pm_ca_update_core_status(struct kbase_device *kbdev, u64 cores_ready, u64 cores_transitioning) +{ + lockdep_assert_held(&kbdev->pm.power_change_lock); + + if (kbdev->pm.ca_current_policy != NULL) + kbdev->pm.ca_current_policy->update_core_status(kbdev, cores_ready, cores_transitioning); +} + +void kbase_pm_ca_instr_enable(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbdev->pm.instr_enabled = MALI_TRUE; + + kbase_pm_update_cores_state_nolock(kbdev); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +void kbase_pm_ca_instr_disable(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbdev->pm.instr_enabled = MALI_FALSE; + + kbase_pm_update_cores_state_nolock(kbdev); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.h new file mode 100644 index 0000000000000000000000000000000000000000..e073470e085501e1ae4531f9b36a8319cd5c2780 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca.h @@ -0,0 +1,170 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_ca.h + * Base kernel core availability APIs + */ + +#ifndef _KBASE_PM_CA_H_ +#define _KBASE_PM_CA_H_ + +enum kbase_pm_ca_policy_id { + KBASE_PM_CA_POLICY_ID_FIXED = 1, + KBASE_PM_CA_POLICY_ID_RANDOM +}; + +typedef u32 kbase_pm_ca_policy_flags; + +/** Core availability policy structure. + * + * Each core availability policy exposes a (static) instance of this structure which contains function pointers to the + * policy's methods. + */ +struct kbase_pm_ca_policy { + /** The name of this policy */ + char *name; + + /** Function called when the policy is selected + * + * This should initialize the kbdev->pm.ca_policy_data structure. It should not attempt + * to make any changes to hardware state. + * + * It is undefined what state the cores are in when the function is called. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + void (*init)(struct kbase_device *kbdev); + + /** Function called when the policy is unselected. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + void (*term)(struct kbase_device *kbdev); + + /** Function called to get the current shader core availability mask + * + * When a change in core availability is occuring, the policy must set kbdev->pm.ca_in_transition + * to MALI_TRUE. This is to indicate that reporting changes in power state cannot be optimized out, + * even if kbdev->pm.desired_shader_state remains unchanged. This must be done by any functions + * internal to the Core Availability Policy that change the return value of + * kbase_pm_ca_policy::get_core_mask. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The current core availability mask */ + u64 (*get_core_mask)(struct kbase_device *kbdev); + + /** Function called to update the current core status + * + * If none of the cores in core group 0 are ready or transitioning, then the policy must + * ensure that the next call to get_core_mask does not return 0 for all cores in core group + * 0. It is an error to disable core group 0 through the core availability policy. + * + * When a change in core availability has finished, the policy must set kbdev->pm.ca_in_transition + * to MALI_FALSE. This is to indicate that changes in power state can once again be optimized out + * when kbdev->pm.desired_shader_state is unchanged. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param cores_ready The mask of cores currently powered and ready to run jobs + * @param cores_transitioning The mask of cores currently transitioning power state */ + void (*update_core_status)(struct kbase_device *kbdev, u64 cores_ready, u64 cores_transitioning); + + /** Field indicating flags for this policy */ + kbase_pm_ca_policy_flags flags; + + /** Field indicating an ID for this policy. This is not necessarily the + * same as its index in the list returned by kbase_pm_list_policies(). + * It is used purely for debugging. */ + enum kbase_pm_ca_policy_id id; +}; + +/** Initialize core availability framework + * + * Must be called before calling any other core availability function + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE if the core availability framework was successfully initialized. + */ +mali_error kbase_pm_ca_init(struct kbase_device *kbdev); + +/** Terminate core availability framework + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_ca_term(struct kbase_device *kbdev); + +/** Return mask of currently available shaders cores + * Calls into the core availability policy + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The bit mask of available cores + */ +u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev); + +/** Update core availability policy with current core power status + * Calls into the core availability policy + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param cores_ready The bit mask of cores ready for job submission + * @param cores_transitioning The bit mask of cores that are transitioning power state + */ +void kbase_pm_ca_update_core_status(struct kbase_device *kbdev, u64 cores_ready, u64 cores_transitioning); + +/** Enable override for instrumentation + * + * This overrides the output of the core availability policy, ensuring that all cores are available + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_ca_instr_enable(struct kbase_device *kbdev); + +/** Disable override for instrumentation + * + * This disables any previously enabled override, and resumes normal policy functionality + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_ca_instr_disable(struct kbase_device *kbdev); + +/** Get the current policy. + * Returns the policy that is currently active. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The current policy + */ +const struct kbase_pm_ca_policy *kbase_pm_ca_get_policy(struct kbase_device *kbdev); + +/** Change the policy to the one specified. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param policy The policy to change to (valid pointer returned from @ref kbase_pm_ca_list_policies) + */ +void kbase_pm_ca_set_policy(struct kbase_device *kbdev, const struct kbase_pm_ca_policy *policy); + +/** Retrieve a static list of the available policies. + * @param[out] policies An array pointer to take the list of policies. This may be NULL. + * The contents of this array must not be modified. + * + * @return The number of policies + */ +int kbase_pm_ca_list_policies(const struct kbase_pm_ca_policy * const **policies); + +#endif /* _KBASE_PM_CA_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.c new file mode 100644 index 0000000000000000000000000000000000000000..d81cdbd42e7cf0d0fd89aca6f78c13724de00996 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.c @@ -0,0 +1,63 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_ca_fixed.c + * A power policy implementing fixed core availability + */ + +#include +#include +#if KBASE_PM_EN +static void fixed_init(struct kbase_device *kbdev) +{ + kbdev->pm.ca_in_transition = MALI_FALSE; +} + +static void fixed_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static u64 fixed_get_core_mask(struct kbase_device *kbdev) +{ + return kbdev->shader_present_bitmap; +} + +static void fixed_update_core_status(struct kbase_device *kbdev, u64 cores_ready, u64 cores_transitioning) +{ + CSTD_UNUSED(kbdev); + CSTD_UNUSED(cores_ready); + CSTD_UNUSED(cores_transitioning); +} + +/** The @ref struct kbase_pm_policy structure for the fixed power policy. + * + * This is the static structure that defines the fixed power policy's callback and name. + */ +const struct kbase_pm_ca_policy kbase_pm_ca_fixed_policy_ops = { + "fixed", /* name */ + fixed_init, /* init */ + fixed_term, /* term */ + fixed_get_core_mask, /* get_core_mask */ + fixed_update_core_status, /* update_core_status */ + 0u, /* flags */ + KBASE_PM_CA_POLICY_ID_FIXED, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_ca_fixed_policy_ops) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.h new file mode 100644 index 0000000000000000000000000000000000000000..9d95e07a2d524e266ae3c794ce48a2c7c8b75a56 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_ca_fixed.h @@ -0,0 +1,37 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_ca_fixed.h + * A power policy implementing fixed core availability + */ + +#ifndef MALI_KBASE_PM_CA_FIXED_H +#define MALI_KBASE_PM_CA_FIXED_H + +/** + * Private structure for policy instance data. + * + * This contains data that is private to the particular power policy that is active. + */ +typedef struct kbasep_pm_ca_policy_fixed { + /** No state needed - just have a dummy variable here */ + int dummy; +} kbasep_pm_ca_policy_fixed; + +#endif /* MALI_KBASE_PM_CA_FIXED_H */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.c new file mode 100644 index 0000000000000000000000000000000000000000..8093e32e4dcd29a02ef582cac7005223a074631c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.c @@ -0,0 +1,70 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_coarse_demand.c + * "Coarse Demand" power management policy + */ + +#include +#include + +#if KBASE_PM_EN +static u64 coarse_demand_get_core_mask(struct kbase_device *kbdev) +{ + if (kbdev->pm.active_count == 0) + return 0; + + return kbdev->shader_present_bitmap; +} + +static mali_bool coarse_demand_get_core_active(struct kbase_device *kbdev) +{ + if (kbdev->pm.active_count == 0) + return MALI_FALSE; + + return MALI_TRUE; +} + +static void coarse_demand_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void coarse_demand_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/** The @ref struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback and name. + */ +const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops = { + "coarse_demand", /* name */ + coarse_demand_init, /* init */ + coarse_demand_term, /* term */ + coarse_demand_get_core_mask, /* get_core_mask */ + coarse_demand_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_COARSE_DEMAND, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_coarse_demand_policy_ops) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.h new file mode 100644 index 0000000000000000000000000000000000000000..afe3fc93b42deaa36d77e843c07d4458f47c2264 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_coarse_demand.h @@ -0,0 +1,60 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_coarse_demand.h + * "Coarse Demand" power management policy + */ + +#ifndef MALI_KBASE_PM_COARSE_DEMAND_H +#define MALI_KBASE_PM_COARSE_DEMAND_H + +/** + * The "Coarse" demand power management policy has the following + * characteristics: + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * - All Shader Cores are powered up, regardless of whether or not they will + * be needed later. + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * - All Shader Cores are kept powered, regardless of whether or not they will + * be needed + * - When KBase indicates that the GPU need not be powered: + * - The Shader Cores are powered off, and the GPU itself is powered off too. + * + * @note: + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * Private structure for policy instance data. + * + * This contains data that is private to the particular power policy that is active. + */ +typedef struct kbasep_pm_policy_coarse_demand { + /** No state needed - just have a dummy variable here */ + int dummy; +} kbasep_pm_policy_coarse_demand; + +#endif /* MALI_KBASE_PM_COARSE_DEMAND_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.c new file mode 100644 index 0000000000000000000000000000000000000000..0e322924c7ef14eccb6761dfc23d1d2a35651ddd --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.c @@ -0,0 +1,73 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_demand.c + * A simple demand based power management policy + */ + +#include +#include + +#if KBASE_PM_EN + +static u64 demand_get_core_mask(struct kbase_device *kbdev) +{ + u64 desired = kbdev->shader_needed_bitmap | kbdev->shader_inuse_bitmap; + + if (0 == kbdev->pm.active_count) + return 0; + + return desired; +} + +static mali_bool demand_get_core_active(struct kbase_device *kbdev) +{ + if (0 == kbdev->pm.active_count) + return MALI_FALSE; + + return MALI_TRUE; +} + +static void demand_init(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +static void demand_term(struct kbase_device *kbdev) +{ + CSTD_UNUSED(kbdev); +} + +/** The @ref struct kbase_pm_policy structure for the demand power policy. + * + * This is the static structure that defines the demand power policy's callback and name. + */ +const struct kbase_pm_policy kbase_pm_demand_policy_ops = { + "demand", /* name */ + demand_init, /* init */ + demand_term, /* term */ + demand_get_core_mask, /* get_core_mask */ + demand_get_core_active, /* get_core_active */ + 0u, /* flags */ + KBASE_PM_POLICY_ID_DEMAND, /* id */ +}; + +KBASE_EXPORT_TEST_API(kbase_pm_demand_policy_ops) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.h new file mode 100644 index 0000000000000000000000000000000000000000..8579181d7dd0909d8cf85cda42ee7ea9630e7c27 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_demand.h @@ -0,0 +1,57 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_demand.h + * A simple demand based power management policy + */ + +#ifndef MALI_KBASE_PM_DEMAND_H +#define MALI_KBASE_PM_DEMAND_H + +/** + * The demand power management policy has the following characteristics: + * - When KBase indicates that the GPU will be powered up, but we don't yet + * know which Job Chains are to be run: + * - The Shader Cores are not powered up + * - When KBase indicates that a set of Shader Cores are needed to submit the + * currently queued Job Chains: + * - Only those Shader Cores are powered up + * - When KBase indicates that the GPU need not be powered: + * - The Shader Cores are powered off, and the GPU itself is powered off too. + * + * @note: + * - KBase indicates the GPU will be powered up when it has a User Process that + * has just started to submit Job Chains. + * - KBase indicates the GPU need not be powered when all the Job Chains from + * User Processes have finished, and it is waiting for a User Process to + * submit some more Job Chains. + */ + +/** + * Private structure for policy instance data. + * + * This contains data that is private to the particular power policy that is active. + */ +typedef struct kbasep_pm_policy_demand { + /** No state needed - just have a dummy variable here */ + int dummy; +} kbasep_pm_policy_demand; + +#endif /* MALI_KBASE_PM_DEMAND_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_driver.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_driver.c new file mode 100644 index 0000000000000000000000000000000000000000..32b24b104b48bc25e6da91d19160da4d19142dad --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_driver.c @@ -0,0 +1,1013 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_driver.c + * Base kernel Power Management hardware control + */ + +#include +#include +#include +#include +#include +#include + +#if KBASE_PM_EN + +#if MALI_MOCK_TEST +#define MOCKABLE(function) function##_original +#else +#define MOCKABLE(function) function +#endif /* MALI_MOCK_TEST */ + +/** Actions that can be performed on a core. + * + * This enumeration is private to the file. Its values are set to allow @ref core_type_to_reg function, + * which decodes this enumeration, to be simpler and more efficient. + */ +enum kbasep_pm_action { + ACTION_PRESENT = 0, + ACTION_READY = (SHADER_READY_LO - SHADER_PRESENT_LO), + ACTION_PWRON = (SHADER_PWRON_LO - SHADER_PRESENT_LO), + ACTION_PWROFF = (SHADER_PWROFF_LO - SHADER_PRESENT_LO), + ACTION_PWRTRANS = (SHADER_PWRTRANS_LO - SHADER_PRESENT_LO), + ACTION_PWRACTIVE = (SHADER_PWRACTIVE_LO - SHADER_PRESENT_LO) +}; + +/** Decode a core type and action to a register. + * + * Given a core type (defined by @ref kbase_pm_core_type) and an action (defined by @ref kbasep_pm_action) this + * function will return the register offset that will perform the action on the core type. The register returned is + * the \c _LO register and an offset must be applied to use the \c _HI register. + * + * @param core_type The type of core + * @param action The type of action + * + * @return The register offset of the \c _LO register that performs an action of type \c action on a core of type \c + * core_type. + */ +static u32 core_type_to_reg(enum kbase_pm_core_type core_type, enum kbasep_pm_action action) +{ + return (u32)core_type + (u32)action; +} + +/** Invokes an action on a core set + * + * This function performs the action given by \c action on a set of cores of a type given by \c core_type. It is a + * static function used by @ref kbase_pm_transition_core_type + * + * @param kbdev The kbase device structure of the device + * @param core_type The type of core that the action should be performed on + * @param cores A bit mask of cores to perform the action on (low 32 bits) + * @param action The action to perform on the cores + */ +STATIC void kbase_pm_invoke(struct kbase_device *kbdev, enum kbase_pm_core_type core_type, u64 cores, enum kbasep_pm_action action) +{ + u32 reg; + u32 lo = cores & 0xFFFFFFFF; + u32 hi = (cores >> 32) & 0xFFFFFFFF; + + lockdep_assert_held(&kbdev->pm.power_change_lock); + + reg = core_type_to_reg(core_type, action); + + KBASE_DEBUG_ASSERT(reg); +#ifdef CONFIG_MALI_GATOR_SUPPORT + if (cores) { + if (action == ACTION_PWRON) + kbase_trace_mali_pm_power_on(core_type, cores); + else if (action == ACTION_PWROFF) + kbase_trace_mali_pm_power_off(core_type, cores); + } +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + /* Tracing */ + if (cores) { + if (action == ACTION_PWRON) + switch (core_type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_PWRON, NULL, NULL, 0u, lo); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_PWRON_TILER, NULL, NULL, 0u, lo); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_PWRON_L2, NULL, NULL, 0u, lo); + break; + default: + /* L3 not handled */ + break; + } + else if (action == ACTION_PWROFF) + switch (core_type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_PWROFF, NULL, NULL, 0u, lo); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_PWROFF_TILER, NULL, NULL, 0u, lo); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_PWROFF_L2, NULL, NULL, 0u, lo); + break; + default: + /* L3 not handled */ + break; + } + } + + if (lo != 0) + kbase_reg_write(kbdev, GPU_CONTROL_REG(reg), lo, NULL); + + if (hi != 0) + kbase_reg_write(kbdev, GPU_CONTROL_REG(reg + 4), hi, NULL); +} + +/** Get information about a core set + * + * This function gets information (chosen by \c action) about a set of cores of a type given by \c core_type. It is a + * static function used by @ref kbase_pm_get_present_cores, @ref kbase_pm_get_active_cores, @ref + * kbase_pm_get_trans_cores and @ref kbase_pm_get_ready_cores. + * + * @param kbdev The kbase device structure of the device + * @param core_type The type of core that the should be queried + * @param action The property of the cores to query + * + * @return A bit mask specifying the state of the cores + */ +static u64 kbase_pm_get_state(struct kbase_device *kbdev, enum kbase_pm_core_type core_type, enum kbasep_pm_action action) +{ + u32 reg; + u32 lo, hi; + + reg = core_type_to_reg(core_type, action); + + KBASE_DEBUG_ASSERT(reg); + + lo = kbase_reg_read(kbdev, GPU_CONTROL_REG(reg), NULL); + hi = kbase_reg_read(kbdev, GPU_CONTROL_REG(reg + 4), NULL); + + return (((u64) hi) << 32) | ((u64) lo); +} + +void kbasep_pm_read_present_cores(struct kbase_device *kbdev) +{ + kbdev->shader_present_bitmap = kbase_pm_get_state(kbdev, KBASE_PM_CORE_SHADER, ACTION_PRESENT); + kbdev->tiler_present_bitmap = kbase_pm_get_state(kbdev, KBASE_PM_CORE_TILER, ACTION_PRESENT); + kbdev->l2_present_bitmap = kbase_pm_get_state(kbdev, KBASE_PM_CORE_L2, ACTION_PRESENT); + kbdev->l3_present_bitmap = kbase_pm_get_state(kbdev, KBASE_PM_CORE_L3, ACTION_PRESENT); + + kbdev->shader_inuse_bitmap = 0; + kbdev->shader_needed_bitmap = 0; + kbdev->shader_available_bitmap = 0; + kbdev->tiler_available_bitmap = 0; + kbdev->l2_users_count = 0; + kbdev->l2_available_bitmap = 0; + kbdev->tiler_needed_cnt = 0; + kbdev->tiler_inuse_cnt = 0; + + memset(kbdev->shader_needed_cnt, 0, sizeof(kbdev->shader_needed_cnt)); +} + +KBASE_EXPORT_TEST_API(kbasep_pm_read_present_cores) + +/** Get the cores that are present + */ +u64 kbase_pm_get_present_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + switch (type) { + case KBASE_PM_CORE_L3: + return kbdev->l3_present_bitmap; + break; + case KBASE_PM_CORE_L2: + return kbdev->l2_present_bitmap; + break; + case KBASE_PM_CORE_SHADER: + return kbdev->shader_present_bitmap; + break; + case KBASE_PM_CORE_TILER: + return kbdev->tiler_present_bitmap; + break; + } + KBASE_DEBUG_ASSERT(0); + return 0; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_present_cores) + +/** Get the cores that are "active" (busy processing work) + */ +u64 kbase_pm_get_active_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type) +{ + return kbase_pm_get_state(kbdev, type, ACTION_PWRACTIVE); +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_active_cores) + +/** Get the cores that are transitioning between power states + */ +u64 kbase_pm_get_trans_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type) +{ + return kbase_pm_get_state(kbdev, type, ACTION_PWRTRANS); +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_trans_cores) +/** Get the cores that are powered on + */ +u64 kbase_pm_get_ready_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type) +{ + u64 result; + + result = kbase_pm_get_state(kbdev, type, ACTION_READY); + + switch (type) { + case KBASE_PM_CORE_SHADER: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED, NULL, NULL, 0u, (u32) result); + break; + case KBASE_PM_CORE_TILER: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED_TILER, NULL, NULL, 0u, (u32) result); + break; + case KBASE_PM_CORE_L2: + KBASE_TRACE_ADD(kbdev, PM_CORES_POWERED_L2, NULL, NULL, 0u, (u32) result); + break; + default: + /* NB: L3 not currently traced */ + break; + } + + return result; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_ready_cores) + +/** Perform power transitions for a particular core type. + * + * This function will perform any available power transitions to make the actual hardware state closer to the desired + * state. If a core is currently transitioning then changes to the power state of that call cannot be made until the + * transition has finished. Cores which are not present in the hardware are ignored if they are specified in the + * desired_state bitmask, however the return value will always be 0 in this case. + * + * @param kbdev The kbase device + * @param type The core type to perform transitions for + * @param desired_state A bit mask of the desired state of the cores + * @param in_use A bit mask of the cores that are currently running jobs. + * These cores have to be kept powered up because there are jobs + * running (or about to run) on them. + * @param[out] available Receives a bit mask of the cores that the job scheduler can use to submit jobs to. + * May be NULL if this is not needed. + * @param[in,out] powering_on Bit mask to update with cores that are transitioning to a power-on state. + * + * @return MALI_TRUE if the desired state has been reached, MALI_FALSE otherwise + */ +STATIC mali_bool kbase_pm_transition_core_type(struct kbase_device *kbdev, enum kbase_pm_core_type type, u64 desired_state, + u64 in_use, u64 * const available, u64 *powering_on) +{ + u64 present; + u64 ready; + u64 trans; + u64 powerup; + u64 powerdown; + u64 powering_on_trans; + u64 desired_state_in_use; + + lockdep_assert_held(&kbdev->pm.power_change_lock); + + /* Get current state */ + present = kbase_pm_get_present_cores(kbdev, type); + trans = kbase_pm_get_trans_cores(kbdev, type); + ready = kbase_pm_get_ready_cores(kbdev, type); + /* mask off ready from trans in case transitions finished between the register reads */ + trans &= ~ready; + + powering_on_trans = trans & *powering_on; + *powering_on = powering_on_trans; + + if (available != NULL) + *available = (ready | powering_on_trans) & desired_state; + + /* Update desired state to include the in-use cores. These have to be kept powered up because there are jobs + * running or about to run on these cores + */ + desired_state_in_use = desired_state | in_use; + + /* Update state of whether l2 caches are powered */ + if (type == KBASE_PM_CORE_L2) { + if ((ready == present) && (desired_state_in_use == ready) && (trans == 0)) { + /* All are ready, none will be turned off, and none are transitioning */ + kbdev->pm.l2_powered = 1; + if (kbdev->l2_users_count > 0) { + /* Notify any registered l2 cache users (optimized out when no users waiting) */ + wake_up(&kbdev->pm.l2_powered_wait); + } + } else { + kbdev->pm.l2_powered = 0; + } + } + + if (desired_state_in_use == ready && (trans == 0)) + return MALI_TRUE; + + /* Restrict the cores to those that are actually present */ + powerup = desired_state_in_use & present; + powerdown = (~desired_state_in_use) & present; + + /* Restrict to cores that are not already in the desired state */ + powerup &= ~ready; + powerdown &= ready; + + /* Don't transition any cores that are already transitioning, except for + * Mali cores that support the following case: + * + * If the SHADER_PWRON or TILER_PWRON registers are written to turn on + * a core that is currently transitioning to power off, then this is + * remembered and the shader core is automatically powered up again once + * the original transition completes. Once the automatic power on is + * complete any job scheduled on the shader core should start. + */ + powerdown &= ~trans; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS)) + if (KBASE_PM_CORE_SHADER == type || KBASE_PM_CORE_TILER == type) + trans = powering_on_trans; /* for exception cases, only mask off cores in power on transitions */ + + powerup &= ~trans; + + /* Perform transitions if any */ + kbase_pm_invoke(kbdev, type, powerup, ACTION_PWRON); + kbase_pm_invoke(kbdev, type, powerdown, ACTION_PWROFF); + + /* Recalculate cores transitioning on, and re-evaluate our state */ + powering_on_trans |= powerup; + *powering_on = powering_on_trans; + if (available != NULL) + *available = (ready | powering_on_trans) & desired_state; + + return MALI_FALSE; +} + +KBASE_EXPORT_TEST_API(kbase_pm_transition_core_type) + +/** Determine which caches should be on for a particular core state. + * + * This function takes a bit mask of the present caches and the cores (or caches) that are attached to the caches that + * will be powered. It then computes which caches should be turned on to allow the cores requested to be powered up. + * + * @param present The bit mask of present caches + * @param cores_powered A bit mask of cores (or L2 caches) that are desired to be powered + * + * @return A bit mask of the caches that should be turned on + */ +STATIC u64 get_desired_cache_status(u64 present, u64 cores_powered) +{ + u64 desired = 0; + + while (present) { + /* Find out which is the highest set bit */ + u64 bit = fls64(present) - 1; + u64 bit_mask = 1ull << bit; + /* Create a mask which has all bits from 'bit' upwards set */ + + u64 mask = ~(bit_mask - 1); + + /* If there are any cores powered at this bit or above (that haven't previously been processed) then we need + * this core on */ + if (cores_powered & mask) + desired |= bit_mask; + + /* Remove bits from cores_powered and present */ + cores_powered &= ~mask; + present &= ~bit_mask; + } + + return desired; +} + +KBASE_EXPORT_TEST_API(get_desired_cache_status) + +mali_bool MOCKABLE(kbase_pm_check_transitions_nolock) (struct kbase_device *kbdev) +{ + mali_bool cores_are_available = MALI_FALSE; + mali_bool in_desired_state = MALI_TRUE; + u64 desired_l2_state; + u64 desired_l3_state; + u64 cores_powered; + u64 tiler_available_bitmap; + u64 shader_available_bitmap; + u64 shader_ready_bitmap; + u64 shader_transitioning_bitmap; + u64 l2_available_bitmap; + u64 prev_l2_available_bitmap; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.power_change_lock); + + spin_lock(&kbdev->pm.gpu_powered_lock); + if (kbdev->pm.gpu_powered == MALI_FALSE) { + spin_unlock(&kbdev->pm.gpu_powered_lock); + if (kbdev->pm.desired_shader_state == 0 && kbdev->pm.desired_tiler_state == 0) + return MALI_TRUE; + return MALI_FALSE; + } + + /* Trace that a change-state is being requested, and that it took + * (effectively) no time to start it. This is useful for counting how many + * state changes occurred, in a way that's backwards-compatible with + * processing the trace data */ + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE); + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE); + + /* If any cores are already powered then, we must keep the caches on */ + cores_powered = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); + + cores_powered |= kbdev->pm.desired_shader_state; + + /* If there are l2 cache users registered, keep all l2s powered even if all other cores are off. */ + if (kbdev->l2_users_count > 0) + cores_powered |= kbdev->l2_present_bitmap; + + desired_l2_state = get_desired_cache_status(kbdev->l2_present_bitmap, cores_powered); + + /* If any l2 cache is on, then enable l2 #0, for use by job manager */ + if (0 != desired_l2_state) { + desired_l2_state |= 1; + /* Also enable tiler if l2 cache is powered */ + kbdev->pm.desired_tiler_state = kbdev->tiler_present_bitmap; + } else { + kbdev->pm.desired_tiler_state = 0; + } + + desired_l3_state = get_desired_cache_status(kbdev->l3_present_bitmap, desired_l2_state); + prev_l2_available_bitmap = kbdev->l2_available_bitmap; + in_desired_state &= kbase_pm_transition_core_type(kbdev, KBASE_PM_CORE_L3, desired_l3_state, 0, NULL, &kbdev->pm.powering_on_l3_state); + in_desired_state &= kbase_pm_transition_core_type(kbdev, KBASE_PM_CORE_L2, desired_l2_state, 0, &l2_available_bitmap, &kbdev->pm.powering_on_l2_state); + + if (kbdev->l2_available_bitmap != l2_available_bitmap) { + KBASE_TIMELINE_POWER_L2(kbdev, l2_available_bitmap); + } + + kbdev->l2_available_bitmap = l2_available_bitmap; + + if (in_desired_state) { + in_desired_state &= kbase_pm_transition_core_type(kbdev, KBASE_PM_CORE_TILER, kbdev->pm.desired_tiler_state, 0, &tiler_available_bitmap, &kbdev->pm.powering_on_tiler_state); + in_desired_state &= kbase_pm_transition_core_type(kbdev, KBASE_PM_CORE_SHADER, kbdev->pm.desired_shader_state, kbdev->shader_inuse_bitmap, &shader_available_bitmap, &kbdev->pm.powering_on_shader_state); + + if (kbdev->shader_available_bitmap != shader_available_bitmap) { + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, NULL, 0u, (u32) shader_available_bitmap); + KBASE_TIMELINE_POWER_SHADER(kbdev, shader_available_bitmap); + } + + kbdev->shader_available_bitmap = shader_available_bitmap; + + if (kbdev->tiler_available_bitmap != tiler_available_bitmap) { + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, NULL, 0u, (u32) tiler_available_bitmap); + KBASE_TIMELINE_POWER_TILER(kbdev, tiler_available_bitmap); + } + + kbdev->tiler_available_bitmap = tiler_available_bitmap; + + } else if ((l2_available_bitmap & kbdev->tiler_present_bitmap) != kbdev->tiler_present_bitmap) { + tiler_available_bitmap = 0; + + if (kbdev->tiler_available_bitmap != tiler_available_bitmap) { + KBASE_TIMELINE_POWER_TILER(kbdev, tiler_available_bitmap); + } + + kbdev->tiler_available_bitmap = tiler_available_bitmap; + } + + /* State updated for slow-path waiters */ + kbdev->pm.gpu_in_desired_state = in_desired_state; + + shader_ready_bitmap = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); + shader_transitioning_bitmap = kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_SHADER); + + /* Determine whether the cores are now available (even if the set of + * available cores is empty). Note that they can be available even if we've + * not finished transitioning to the desired state */ + if ((kbdev->shader_available_bitmap & kbdev->pm.desired_shader_state) == kbdev->pm.desired_shader_state && + (kbdev->tiler_available_bitmap & kbdev->pm.desired_tiler_state) == kbdev->pm.desired_tiler_state) { + cores_are_available = MALI_TRUE; + + KBASE_TRACE_ADD(kbdev, PM_CORES_AVAILABLE, NULL, NULL, 0u, (u32)(kbdev->shader_available_bitmap & kbdev->pm.desired_shader_state)); + KBASE_TRACE_ADD(kbdev, PM_CORES_AVAILABLE_TILER, NULL, NULL, 0u, (u32)(kbdev->tiler_available_bitmap & kbdev->pm.desired_tiler_state)); + + /* Log timelining information about handling events that power up + * cores, to match up either with immediate submission either because + * cores already available, or from PM IRQ */ + if (!in_desired_state) + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + } + + if (in_desired_state) { + KBASE_DEBUG_ASSERT(cores_are_available); + +#ifdef CONFIG_MALI_GATOR_SUPPORT + kbase_trace_mali_pm_status(KBASE_PM_CORE_L3, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L3)); + kbase_trace_mali_pm_status(KBASE_PM_CORE_L2, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2)); + kbase_trace_mali_pm_status(KBASE_PM_CORE_SHADER, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER)); + kbase_trace_mali_pm_status(KBASE_PM_CORE_TILER, kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_TILER)); +#endif /* CONFIG_MALI_GATOR_SUPPORT */ + + KBASE_TRACE_ADD(kbdev, PM_DESIRED_REACHED, NULL, NULL, kbdev->pm.gpu_in_desired_state, (u32)kbdev->pm.desired_shader_state); + KBASE_TRACE_ADD(kbdev, PM_DESIRED_REACHED_TILER, NULL, NULL, 0u, (u32)kbdev->pm.desired_tiler_state); + + /* Log timelining information for synchronous waiters */ + kbase_timeline_pm_send_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); + /* Wake slow-path waiters. Job scheduler does not use this. */ + KBASE_TRACE_ADD(kbdev, PM_WAKE_WAITERS, NULL, NULL, 0u, 0); + wake_up(&kbdev->pm.gpu_in_desired_state_wait); + } + + spin_unlock(&kbdev->pm.gpu_powered_lock); + + /* kbase_pm_ca_update_core_status can cause one-level recursion into + * this function, so it must only be called once all changes to kbdev + * have been committed, and after the gpu_powered_lock has been + * dropped. */ + if (kbdev->shader_ready_bitmap != shader_ready_bitmap || + kbdev->shader_transitioning_bitmap != shader_transitioning_bitmap) { + kbdev->shader_ready_bitmap = shader_ready_bitmap; + kbdev->shader_transitioning_bitmap = shader_transitioning_bitmap; + + kbase_pm_ca_update_core_status(kbdev, shader_ready_bitmap, shader_transitioning_bitmap); + } + + /* The core availability policy is not allowed to keep core group 0 turned off (unless it was changing the l2 power state) */ + if (!((shader_ready_bitmap | shader_transitioning_bitmap) & kbdev->gpu_props.props.coherency_info.group[0].core_mask) && + (prev_l2_available_bitmap == desired_l2_state) && + !(kbase_pm_ca_get_core_mask(kbdev) & kbdev->gpu_props.props.coherency_info.group[0].core_mask)) + BUG(); + + /* The core availability policy is allowed to keep core group 1 off, + * but all jobs specifically targeting CG1 must fail */ + if (!((shader_ready_bitmap | shader_transitioning_bitmap) & kbdev->gpu_props.props.coherency_info.group[1].core_mask) && + !(kbase_pm_ca_get_core_mask(kbdev) & kbdev->gpu_props.props.coherency_info.group[1].core_mask)) + kbdev->pm.cg1_disabled = MALI_TRUE; + else + kbdev->pm.cg1_disabled = MALI_FALSE; + + return cores_are_available; +} +KBASE_EXPORT_TEST_API(kbase_pm_check_transitions_nolock) + +void kbase_pm_check_transitions_sync(struct kbase_device *kbdev) +{ + unsigned long flags; + mali_bool cores_are_available; + /* Force the transition to be checked and reported - the cores may be + * 'available' (for job submission) but not fully powered up. */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* Wait for cores */ + wait_event(kbdev->pm.gpu_in_desired_state_wait, kbdev->pm.gpu_in_desired_state); + + /* Log timelining information that a change in state has completed */ + kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); +} +KBASE_EXPORT_TEST_API(kbase_pm_check_transitions_sync) + +void kbase_pm_enable_interrupts(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + /* + * Clear all interrupts, + * and unmask them all. + */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), GPU_IRQ_REG_ALL, NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), GPU_IRQ_REG_ALL, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 0xFFFFFFFF, NULL); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), 0xFFFFFFFF, NULL); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), 0xFFFFFFFF, NULL); + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0xFFFFFFFF, NULL); +} + +KBASE_EXPORT_TEST_API(kbase_pm_enable_interrupts) + +void kbase_pm_disable_interrupts(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + /* + * Mask all interrupts, + * and clear them all. + */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), GPU_IRQ_REG_ALL, NULL); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 0xFFFFFFFF, NULL); + + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0, NULL); + kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), 0xFFFFFFFF, NULL); +} + +KBASE_EXPORT_TEST_API(kbase_pm_disable_interrupts) + +/* + * pmu layout: + * 0x0000: PMU TAG (RO) (0xCAFECAFE) + * 0x0004: PMU VERSION ID (RO) (0x00000000) + * 0x0008: CLOCK ENABLE (RW) (31:1 SBZ, 0 CLOCK STATE) + */ +void kbase_pm_clock_on(struct kbase_device *kbdev, mali_bool is_resume) +{ + mali_bool reset_required = is_resume; + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.lock); + + if (kbdev->pm.gpu_powered) { + /* Already turned on */ + KBASE_DEBUG_ASSERT(!is_resume); + return; + } + + KBASE_TRACE_ADD(kbdev, PM_GPU_ON, NULL, NULL, 0u, 0u); + + if (is_resume && kbdev->pm.callback_power_resume) { + kbdev->pm.callback_power_resume(kbdev); + } else if (kbdev->pm.callback_power_on) { + kbdev->pm.callback_power_on(kbdev); + /* If your platform properly keeps the GPU state you may use the return + * value of the callback_power_on function to conditionally reset the + * GPU on power up. Currently we are conservative and always reset the + * GPU. */ + reset_required = MALI_TRUE; + } + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + kbdev->pm.gpu_powered = MALI_TRUE; + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (reset_required) { + /* GPU state was lost, reset GPU to ensure it is in a + * consistent state */ + kbase_pm_init_hw(kbdev, MALI_TRUE); + } + + /* Lastly, enable the interrupts */ + kbase_pm_enable_interrupts(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_clock_on) + +void kbase_pm_clock_off(struct kbase_device *kbdev, mali_bool is_suspend) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.lock); + + /* ASSERT that the cores should now be unavailable. No lock needed. */ + KBASE_DEBUG_ASSERT(kbdev->shader_available_bitmap == 0u); + + if (!kbdev->pm.gpu_powered) { + /* Already turned off */ + if (is_suspend && kbdev->pm.callback_power_suspend) + kbdev->pm.callback_power_suspend(kbdev); + return; + } + + KBASE_TRACE_ADD(kbdev, PM_GPU_OFF, NULL, NULL, 0u, 0u); + + /* Disable interrupts. This also clears any outstanding interrupts */ + kbase_pm_disable_interrupts(kbdev); + /* Ensure that any IRQ handlers have finished */ + kbase_synchronize_irqs(kbdev); + + /* The GPU power may be turned off from this point */ + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + kbdev->pm.gpu_powered = MALI_FALSE; + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + + if (is_suspend && kbdev->pm.callback_power_suspend) + kbdev->pm.callback_power_suspend(kbdev); + else if (kbdev->pm.callback_power_off) + kbdev->pm.callback_power_off(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_clock_off) + +struct kbasep_reset_timeout_data { + struct hrtimer timer; + mali_bool timed_out; + struct kbase_device *kbdev; +}; + +void kbase_pm_reset_done(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + kbdev->pm.reset_done = MALI_TRUE; + wake_up(&kbdev->pm.reset_done_wait); +} + +/** + * Wait for the RESET_COMPLETED IRQ to occur, then reset the waiting state. + */ +STATIC void kbase_pm_wait_for_reset(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.lock); + + wait_event(kbdev->pm.reset_done_wait, (kbdev->pm.reset_done)); + kbdev->pm.reset_done = MALI_FALSE; +} + +KBASE_EXPORT_TEST_API(kbase_pm_reset_done) + +static enum hrtimer_restart kbasep_reset_timeout(struct hrtimer *timer) +{ + struct kbasep_reset_timeout_data *rtdata = container_of(timer, struct kbasep_reset_timeout_data, timer); + + rtdata->timed_out = 1; + + /* Set the wait queue to wake up kbase_pm_init_hw even though the reset hasn't completed */ + kbase_pm_reset_done(rtdata->kbdev); + + return HRTIMER_NORESTART; +} + +static void kbase_pm_hw_issues(struct kbase_device *kbdev) +{ + u32 value = 0; + + /* Needed due to MIDBASE-1494: LS_PAUSEBUFFER_DISABLE. See PRLAM-8443. + * and + * needed due to MIDGLES-3539. See PRLAM-11035 */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8443) || + kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_11035)) + value |= SC_LS_PAUSEBUFFER_DISABLE; + + /* Needed due to MIDBASE-2054: SDC_DISABLE_OQ_DISCARD. See PRLAM-10327. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10327)) + value |= SC_SDC_DISABLE_OQ_DISCARD; + + /* Enable alternative hardware counter selection if configured. */ + if (DEFAULT_ALTERNATIVE_HWC) + value |= SC_ALT_COUNTERS; + + /* Use software control of forward pixel kill when needed. See MIDEUR-174. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_2121)) + value |= SC_OVERRIDE_FWD_PIXEL_KILL; + + /* Needed due to MIDBASE-2795. ENABLE_TEXGRD_FLAGS. See PRLAM-10797. */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10797)) + value |= SC_ENABLE_TEXGRD_FLAGS; + + if (value != 0) + kbase_reg_write(kbdev, GPU_CONTROL_REG(SHADER_CONFIG), value, NULL); + + /* Set tiler clock gate override if required */ + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_3953)) { + value = kbase_reg_read(kbdev, GPU_CONTROL_REG(TILER_CONFIG), NULL); + value |= TC_CLOCK_GATE_OVERRIDE; + kbase_reg_write(kbdev, GPU_CONTROL_REG(TILER_CONFIG), value, NULL); + } + + /* Limit the GPU bus bandwidth if the platform needs this. */ + value = kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), NULL); + + /* Limit read ID width for AXI */ + value &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_READS); + value |= (DEFAULT_ARID_LIMIT & 0x3) << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT; + + /* Limit write ID width for AXI */ + value &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES); + value |= (DEFAULT_AWID_LIMIT & 0x3) << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT; + + kbase_reg_write(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), value, NULL); +} + +mali_error kbase_pm_init_hw(struct kbase_device *kbdev, mali_bool enable_irqs) +{ + unsigned long flags; + struct kbasep_reset_timeout_data rtdata; + + KBASE_DEBUG_ASSERT(NULL != kbdev); + lockdep_assert_held(&kbdev->pm.lock); + + /* Ensure the clock is on before attempting to access the hardware */ + if (!kbdev->pm.gpu_powered) { + if (kbdev->pm.callback_power_on) + kbdev->pm.callback_power_on(kbdev); + + spin_lock_irqsave(&kbdev->pm.gpu_powered_lock, flags); + kbdev->pm.gpu_powered = MALI_TRUE; + spin_unlock_irqrestore(&kbdev->pm.gpu_powered_lock, flags); + } + + /* Ensure interrupts are off to begin with, this also clears any outstanding interrupts */ + kbase_pm_disable_interrupts(kbdev); + + /* Prepare for the soft-reset */ + kbdev->pm.reset_done = MALI_FALSE; + + /* The cores should be made unavailable due to the reset */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + if (kbdev->shader_available_bitmap != 0u) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, NULL, 0u, (u32)0u); + if (kbdev->tiler_available_bitmap != 0u) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, NULL, 0u, (u32)0u); + kbdev->shader_available_bitmap = 0u; + kbdev->tiler_available_bitmap = 0u; + kbdev->l2_available_bitmap = 0u; + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* Soft reset the GPU */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_SOFT_RESET, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_SOFT_RESET, NULL); + + /* Unmask the reset complete interrupt only */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), RESET_COMPLETED, NULL); + + /* Initialize a structure for tracking the status of the reset */ + rtdata.kbdev = kbdev; + rtdata.timed_out = 0; + + /* Create a timer to use as a timeout on the reset */ + hrtimer_init_on_stack(&rtdata.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + rtdata.timer.function = kbasep_reset_timeout; + + hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT), HRTIMER_MODE_REL); + + /* Wait for the RESET_COMPLETED interrupt to be raised */ + kbase_pm_wait_for_reset(kbdev); + + if (rtdata.timed_out == 0) { + /* GPU has been reset */ + hrtimer_cancel(&rtdata.timer); + destroy_hrtimer_on_stack(&rtdata.timer); + goto out; + } + + /* No interrupt has been received - check if the RAWSTAT register says the reset has completed */ + if (kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL) & RESET_COMPLETED) { + /* The interrupt is set in the RAWSTAT; this suggests that the interrupts are not getting to the CPU */ + dev_warn(kbdev->dev, "Reset interrupt didn't reach CPU. Check interrupt assignments.\n"); + /* If interrupts aren't working we can't continue. */ + destroy_hrtimer_on_stack(&rtdata.timer); + goto out; + } + + /* The GPU doesn't seem to be responding to the reset so try a hard reset */ + dev_err(kbdev->dev, "Failed to soft-reset GPU (timed out after %d ms), now attempting a hard reset\n", RESET_TIMEOUT); + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET, NULL); + + /* Restart the timer to wait for the hard reset to complete */ + rtdata.timed_out = 0; + + hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT), HRTIMER_MODE_REL); + + /* Wait for the RESET_COMPLETED interrupt to be raised */ + kbase_pm_wait_for_reset(kbdev); + + if (rtdata.timed_out == 0) { + /* GPU has been reset */ + hrtimer_cancel(&rtdata.timer); + destroy_hrtimer_on_stack(&rtdata.timer); + goto out; + } + + destroy_hrtimer_on_stack(&rtdata.timer); + + dev_err(kbdev->dev, "Failed to hard-reset the GPU (timed out after %d ms)\n", RESET_TIMEOUT); + + /* The GPU still hasn't reset, give up */ + return MALI_ERROR_FUNCTION_FAILED; + + out: + + /* If cycle counter was in use-re enable it enable_irqs will only be false when called from kbase_pm_powerup */ + if (kbdev->pm.gpu_cycle_counter_requests && enable_irqs) { + /* enable interrupts as the L2 may have to be powered on */ + kbase_pm_enable_interrupts(kbdev); + kbase_pm_request_l2_caches(kbdev); + + /* Re-enable the counters if we need to */ + spin_lock_irqsave(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + if (kbdev->pm.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CYCLE_COUNT_START, NULL); + spin_unlock_irqrestore(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + kbase_pm_release_l2_caches(kbdev); + kbase_pm_disable_interrupts(kbdev); + } + + if (enable_irqs) + kbase_pm_enable_interrupts(kbdev); + + kbase_pm_hw_issues(kbdev); + + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbase_pm_init_hw) + +/** Increase the count of cycle counter users and turn the cycle counters on if they were previously off + * + * this function is designed to be called by @ref kbase_pm_request_gpu_cycle_counter or + * @ref kbase_pm_request_gpu_cycle_counter_l2_is_on only + * + * When this function is called the l2 cache must be on and the l2 cache users count must + * have been incremented by a call to (@ref kbase_pm_request_l2_caches or @ref kbase_pm_request_l2_caches_l2_on) + * + * @param kbdev The kbase device structure of the device + * + */ +static void kbase_pm_request_gpu_cycle_counter_do_request(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + ++kbdev->pm.gpu_cycle_counter_requests; + + if (1 == kbdev->pm.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CYCLE_COUNT_START, NULL); + + spin_unlock_irqrestore(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); +} + +void kbase_pm_request_gpu_cycle_counter(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_cycle_counter_requests < INT_MAX); + + kbase_pm_request_l2_caches(kbdev); + + kbase_pm_request_gpu_cycle_counter_do_request(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_gpu_cycle_counter) + +void kbase_pm_request_gpu_cycle_counter_l2_is_on(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_cycle_counter_requests < INT_MAX); + + kbase_pm_request_l2_caches_l2_is_on(kbdev); + + kbase_pm_request_gpu_cycle_counter_do_request(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_gpu_cycle_counter_l2_is_on) + +void kbase_pm_release_gpu_cycle_counter(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_cycle_counter_requests > 0); + + --kbdev->pm.gpu_cycle_counter_requests; + + if (0 == kbdev->pm.gpu_cycle_counter_requests) + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CYCLE_COUNT_STOP, NULL); + + spin_unlock_irqrestore(&kbdev->pm.gpu_cycle_counter_requests_lock, flags); + + kbase_pm_release_l2_caches(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_gpu_cycle_counter) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics.c new file mode 100644 index 0000000000000000000000000000000000000000..343d65ec30df1fb3758dce74be6c3615208e2818 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics.c @@ -0,0 +1,994 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_metrics.c + * Metrics for power management + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#if KBASE_PM_EN +/* When VSync is being hit aim for utilisation between 70-90% */ +#define KBASE_PM_VSYNC_MIN_UTILISATION 30//70 +#define KBASE_PM_VSYNC_MAX_UTILISATION 50//90 +/* Otherwise aim for 10-40% */ +#define KBASE_PM_NO_VSYNC_MIN_UTILISATION 10 +#define KBASE_PM_NO_VSYNC_MAX_UTILISATION 40 + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +int g_current_sample_gl_utilization = 0; +int g_current_sample_cl_utilization[2] = {0}; + +/* MTK GPU DVFS */ +#include "mach/mt_gpufreq.h" +#include "random.h" + +int g_dvfs_enabled = 1; +int g_input_boost_enabled = 1; +enum kbase_pm_dvfs_action g_current_action = KBASE_PM_DVFS_NOP; +int g_dvfs_freq = DEFAULT_PM_DVFS_FREQ; +int g_dvfs_threshold_max = KBASE_PM_VSYNC_MAX_UTILISATION; +int g_dvfs_threshold_min = KBASE_PM_VSYNC_MIN_UTILISATION; +int g_dvfs_deferred_count = 4; +#endif // CONFIG_MALI_MIDGARD_DVFS +int g_touch_boost_flag = 0; +int g_touch_boost_id = 0; + + +/* Shift used for kbasep_pm_metrics_data.time_busy/idle - units of (1 << 8) ns + This gives a maximum period between samples of 2^(32+8)/100 ns = slightly under 11s. + Exceeding this will cause overflow */ +#define KBASE_PM_TIME_SHIFT 8 + +/* Maximum time between sampling of utilization data, without resetting the + * counters. */ +#define MALI_UTILIZATION_MAX_PERIOD 100000 /* ns = 100ms */ + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +void mtk_get_touch_boost_flag(int *touch_boost_flag, int *touch_boost_id) +{ + *touch_boost_flag = g_touch_boost_flag; + *touch_boost_id = g_touch_boost_id; + return; +} + +void mtk_set_touch_boost_flag(int touch_boost_id) +{ + g_touch_boost_flag = 1; + g_touch_boost_id = touch_boost_id; + return; +} + +void mtk_clear_touch_boost_flag(void) +{ + g_touch_boost_flag = 0; + return; +} + +int mtk_get_input_boost_enabled() +{ + return g_input_boost_enabled; +} + +int mtk_get_dvfs_enabled() +{ + return g_dvfs_enabled; +} + +int mtk_get_dvfs_freq() +{ + return g_dvfs_freq; +} + +int mtk_get_dvfs_threshold_max() +{ + return g_dvfs_threshold_max; +} + +int mtk_get_dvfs_threshold_min() +{ + return g_dvfs_threshold_min; +} + +int mtk_get_dvfs_deferred_count() +{ + return g_dvfs_deferred_count; +} + +enum kbase_pm_dvfs_action mtk_get_dvfs_action() +{ + return g_current_action; +} + +void mtk_clear_dvfs_action() +{ + g_current_action = KBASE_PM_DVFS_NONSENSE; +} + +static enum hrtimer_restart dvfs_callback(struct hrtimer *timer) +{ + unsigned long flags; + enum kbase_pm_dvfs_action action; + struct kbasep_pm_metrics_data *metrics; + + KBASE_DEBUG_ASSERT(timer != NULL); + + metrics = container_of(timer, struct kbasep_pm_metrics_data, timer); + action = kbase_pm_get_dvfs_action(metrics->kbdev); + + g_current_action = action; + spin_lock_irqsave(&metrics->lock, flags); + metrics->kbdev->pm.platform_dvfs_frequency = mtk_get_dvfs_freq(); + + if (metrics->timer_active) + hrtimer_start(timer, + HR_TIMER_DELAY_MSEC(metrics->kbdev->pm.platform_dvfs_frequency), + HRTIMER_MODE_REL); + + spin_unlock_irqrestore(&metrics->lock, flags); + + return HRTIMER_NORESTART; +} +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + +mali_error kbasep_pm_metrics_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + kbdev->pm.metrics.kbdev = kbdev; + kbdev->pm.metrics.vsync_hit = 1; /* [MTK] vsync notifiy is not implemented yet, assumed always hit. */ + kbdev->pm.metrics.utilisation = 0; + kbdev->pm.metrics.util_cl_share[0] = 0; + kbdev->pm.metrics.util_cl_share[1] = 0; + kbdev->pm.metrics.util_gl_share = 0; + + kbdev->pm.metrics.time_period_start = ktime_get(); + kbdev->pm.metrics.time_busy = 0; + kbdev->pm.metrics.time_idle = 0; + kbdev->pm.metrics.prev_busy = 0; + kbdev->pm.metrics.prev_idle = 0; + kbdev->pm.metrics.gpu_active = MALI_TRUE; + kbdev->pm.metrics.active_cl_ctx[0] = 0; + kbdev->pm.metrics.active_cl_ctx[1] = 0; + kbdev->pm.metrics.active_gl_ctx = 0; + kbdev->pm.metrics.busy_cl[0] = 0; + kbdev->pm.metrics.busy_cl[1] = 0; + kbdev->pm.metrics.busy_gl = 0; + + spin_lock_init(&kbdev->pm.metrics.lock); + +#ifdef CONFIG_MALI_MIDGARD_DVFS + kbdev->pm.metrics.timer_active = MALI_TRUE; + hrtimer_init(&kbdev->pm.metrics.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->pm.metrics.timer.function = dvfs_callback; + + hrtimer_start(&kbdev->pm.metrics.timer, HR_TIMER_DELAY_MSEC(kbdev->pm.platform_dvfs_frequency), HRTIMER_MODE_REL); +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + + kbase_pm_register_vsync_callback(kbdev); + + return MALI_ERROR_NONE; +} + +KBASE_EXPORT_TEST_API(kbasep_pm_metrics_init) + +void kbasep_pm_metrics_term(struct kbase_device *kbdev) +{ +#ifdef CONFIG_MALI_MIDGARD_DVFS + unsigned long flags; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbdev->pm.metrics.timer_active = MALI_FALSE; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + + hrtimer_cancel(&kbdev->pm.metrics.timer); +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + + kbase_pm_unregister_vsync_callback(kbdev); +} + +KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term) + +/*caller needs to hold kbdev->pm.metrics.lock before calling this function*/ +void kbasep_pm_record_job_status(struct kbase_device *kbdev) +{ + ktime_t now; + ktime_t diff; + u32 ns_time; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + now = ktime_get(); + diff = ktime_sub(now, kbdev->pm.metrics.time_period_start); + + ns_time = (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + kbdev->pm.metrics.time_busy += ns_time; + kbdev->pm.metrics.busy_gl += ns_time * kbdev->pm.metrics.active_gl_ctx; + kbdev->pm.metrics.busy_cl[0] += ns_time * kbdev->pm.metrics.active_cl_ctx[0]; + kbdev->pm.metrics.busy_cl[1] += ns_time * kbdev->pm.metrics.active_cl_ctx[1]; + kbdev->pm.metrics.time_period_start = now; +} + +KBASE_EXPORT_TEST_API(kbasep_pm_record_job_status) + +void kbasep_pm_record_gpu_idle(struct kbase_device *kbdev) +{ + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + + KBASE_DEBUG_ASSERT(kbdev->pm.metrics.gpu_active == MALI_TRUE); + + kbdev->pm.metrics.gpu_active = MALI_FALSE; + + kbasep_pm_record_job_status(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +KBASE_EXPORT_TEST_API(kbasep_pm_record_gpu_idle) + +void kbasep_pm_record_gpu_active(struct kbase_device *kbdev) +{ + unsigned long flags; + ktime_t now; + ktime_t diff; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + + KBASE_DEBUG_ASSERT(kbdev->pm.metrics.gpu_active == MALI_FALSE); + + kbdev->pm.metrics.gpu_active = MALI_TRUE; + + now = ktime_get(); + diff = ktime_sub(now, kbdev->pm.metrics.time_period_start); + + kbdev->pm.metrics.time_idle += (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + kbdev->pm.metrics.time_period_start = now; + + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +KBASE_EXPORT_TEST_API(kbasep_pm_record_gpu_active) + +void kbase_pm_report_vsync(struct kbase_device *kbdev, int buffer_updated) +{ + unsigned long flags; + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbdev->pm.metrics.vsync_hit = buffer_updated; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_report_vsync) + +/*caller needs to hold kbdev->pm.metrics.lock before calling this function*/ +static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev, ktime_t now) +{ + ktime_t diff; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + diff = ktime_sub(now, kbdev->pm.metrics.time_period_start); + + if (kbdev->pm.metrics.gpu_active) { + u32 ns_time = (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + kbdev->pm.metrics.time_busy += ns_time; + kbdev->pm.metrics.busy_cl[0] += ns_time * kbdev->pm.metrics.active_cl_ctx[0]; + kbdev->pm.metrics.busy_cl[1] += ns_time * kbdev->pm.metrics.active_cl_ctx[1]; + kbdev->pm.metrics.busy_gl += ns_time * kbdev->pm.metrics.active_gl_ctx; + } else { + kbdev->pm.metrics.time_idle += (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); + } +} + +/* Caller needs to hold kbdev->pm.metrics.lock before calling this function. */ +static void kbase_pm_reset_dvfs_utilisation_unlocked(struct kbase_device *kbdev, ktime_t now) +{ + /* Store previous value */ + kbdev->pm.metrics.prev_idle = kbdev->pm.metrics.time_idle; + kbdev->pm.metrics.prev_busy = kbdev->pm.metrics.time_busy; + + /* Reset current values */ + kbdev->pm.metrics.time_period_start = now; + kbdev->pm.metrics.time_idle = 0; + kbdev->pm.metrics.time_busy = 0; + kbdev->pm.metrics.busy_cl[0] = 0; + kbdev->pm.metrics.busy_cl[1] = 0; + kbdev->pm.metrics.busy_gl = 0; +} + +void kbase_pm_reset_dvfs_utilisation(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbase_pm_reset_dvfs_utilisation_unlocked(kbdev, ktime_get()); + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +void kbase_pm_get_dvfs_utilisation(struct kbase_device *kbdev, unsigned long *total_out, unsigned long *busy_out, bool reset) +{ + ktime_t now = ktime_get(); + unsigned long tmp, flags; + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + kbase_pm_get_dvfs_utilisation_calc(kbdev, now); + + tmp = kbdev->pm.metrics.busy_gl; + tmp += kbdev->pm.metrics.busy_cl[0]; + tmp += kbdev->pm.metrics.busy_cl[1]; + + *busy_out = tmp; + *total_out = tmp + kbdev->pm.metrics.time_idle; + + if (reset) + kbase_pm_reset_dvfs_utilisation_unlocked(kbdev, now); + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); +} + +#ifdef CONFIG_MALI_MIDGARD_DVFS + +/*caller needs to hold kbdev->pm.metrics.lock before calling this function*/ +int kbase_pm_get_dvfs_utilisation_old(struct kbase_device *kbdev, int *util_gl_share, int util_cl_share[2]) +{ + int utilisation; + int busy; + ktime_t now = ktime_get(); + + kbase_pm_get_dvfs_utilisation_calc(kbdev, now); + + if (kbdev->pm.metrics.time_idle + kbdev->pm.metrics.time_busy == 0) { + /* No data - so we return NOP */ + utilisation = -1; + if (util_gl_share) + *util_gl_share = -1; + if (util_cl_share) { + util_cl_share[0] = -1; + util_cl_share[1] = -1; + } + goto out; + } + + utilisation = (100 * kbdev->pm.metrics.time_busy) / + (kbdev->pm.metrics.time_idle + + kbdev->pm.metrics.time_busy); + + busy = kbdev->pm.metrics.busy_gl + + kbdev->pm.metrics.busy_cl[0] + + kbdev->pm.metrics.busy_cl[1]; + + if (busy != 0) { + if (util_gl_share) + *util_gl_share = + (100 * kbdev->pm.metrics.busy_gl) / busy; + if (util_cl_share) { + util_cl_share[0] = + (100 * kbdev->pm.metrics.busy_cl[0]) / busy; + util_cl_share[1] = + (100 * kbdev->pm.metrics.busy_cl[1]) / busy; + } + } else { + if (util_gl_share) + *util_gl_share = -1; + if (util_cl_share) { + util_cl_share[0] = -1; + util_cl_share[1] = -1; + } + } + +out: + kbase_pm_reset_dvfs_utilisation_unlocked(kbdev, now); + + return utilisation; +} + +enum kbase_pm_dvfs_action kbase_pm_get_dvfs_action(struct kbase_device *kbdev) +{ + unsigned long flags; + int utilisation, util_gl_share; + int util_cl_share[2]; + int random_action; + enum kbase_pm_dvfs_action action; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + + utilisation = kbase_pm_get_dvfs_utilisation_old(kbdev, &util_gl_share, util_cl_share); + + if (utilisation < 0 || util_gl_share < 0 || util_cl_share[0] < 0 || util_cl_share[1] < 0) { + action = KBASE_PM_DVFS_NOP; + utilisation = 0; + util_gl_share = 0; + util_cl_share[0] = 0; + util_cl_share[1] = 0; + goto out; + } + + if (kbdev->pm.metrics.vsync_hit) { + /* VSync is being met */ + if (utilisation < mtk_get_dvfs_threshold_min()) + action = KBASE_PM_DVFS_CLOCK_DOWN; + else if (utilisation > mtk_get_dvfs_threshold_max()) + action = KBASE_PM_DVFS_CLOCK_UP; + else + action = KBASE_PM_DVFS_NOP; + } else { + /* VSync is being missed */ + if (utilisation < KBASE_PM_NO_VSYNC_MIN_UTILISATION) + action = KBASE_PM_DVFS_CLOCK_DOWN; + else if (utilisation > KBASE_PM_NO_VSYNC_MAX_UTILISATION) + action = KBASE_PM_DVFS_CLOCK_UP; + else + action = KBASE_PM_DVFS_NOP; + } + + // get a radom action for stress test + if (mtk_get_dvfs_enabled() == 2) + { + get_random_bytes( &random_action, sizeof(random_action)); + random_action = random_action%3; + pr_debug("[MALI] GPU DVFS stress test - genereate random action here: action = %d", random_action); + action = random_action; + } + + kbdev->pm.metrics.utilisation = utilisation; + kbdev->pm.metrics.util_cl_share[0] = util_cl_share[0]; + kbdev->pm.metrics.util_cl_share[1] = util_cl_share[1]; + kbdev->pm.metrics.util_gl_share = util_gl_share; + + g_current_sample_gl_utilization = utilisation; + g_current_sample_cl_utilization[0] = util_cl_share[0]; + g_current_sample_cl_utilization[1] = util_cl_share[1]; + +out: +#if 0 /// def CONFIG_MALI_MIDGARD_DVFS + kbase_platform_dvfs_event(kbdev, utilisation, util_gl_share, util_cl_share); +#endif /*CONFIG_MALI_MIDGARD_DVFS */ + kbdev->pm.metrics.time_idle = 0; + kbdev->pm.metrics.time_busy = 0; + kbdev->pm.metrics.busy_cl[0] = 0; + kbdev->pm.metrics.busy_cl[1] = 0; + kbdev->pm.metrics.busy_gl = 0; + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + + return action; +} +KBASE_EXPORT_TEST_API(kbase_pm_get_dvfs_action) + +mali_bool kbase_pm_metrics_is_active(struct kbase_device *kbdev) +{ + mali_bool isactive; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.metrics.lock, flags); + isactive = (kbdev->pm.metrics.timer_active == MALI_TRUE); + spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags); + + return isactive; +} + +KBASE_EXPORT_TEST_API(kbase_pm_metrics_is_active) + +u32 kbasep_get_gl_utilization(void) +{ + return g_current_sample_gl_utilization; +} +KBASE_EXPORT_TEST_API(kbasep_get_gl_utilization) + +u32 kbasep_get_cl_js0_utilization(void) +{ + return g_current_sample_cl_utilization[0]; +} +KBASE_EXPORT_TEST_API(kbasep_get_cl_js0_utilization) + +u32 kbasep_get_cl_js1_utilization(void) +{ + return g_current_sample_cl_utilization[1]; +} +KBASE_EXPORT_TEST_API(kbasep_get_cl_js1_utilization) + + +//extern unsigned int (*mtk_get_gpu_loading_fp)(void) = kbasep_get_gl_utilization; + +static unsigned int _mtk_gpu_dvfs_index_to_frequency(int iFreq) +{ + unsigned int iCurrentFreqCount; + iCurrentFreqCount =mt_gpufreq_get_dvfs_table_num(); + if(iCurrentFreqCount == 6) // MT6752 + { + switch(iFreq) + { + case 0: + return 728000; + case 1: + return 650000; + case 2: + return 598000; + case 3: + return 520000; + case 4: + return 416000; + case 5: + return 312000; + } + } + else if(iCurrentFreqCount == 4) // MT6752M, 6751, 6733 + { + switch(iFreq) + { + case 0: + return 598000; + case 1: + return 520000; + case 2: + return 416000; + case 3: + return 312000; + } + } + else if(iCurrentFreqCount == 3) // MT6732, 6732M + { + switch(iFreq) + { + case 0: + return 494000; + case 1: + return 416000; + case 2: + return 312000; + } + } + +} + +///===================================================================================== +/// The below function is added by Mediatek +/// In order to provide the debug sysfs command for change parameter dynamiically +///===================================================================================== + +/// 1. For GPU memory usage +static int proc_gpu_memoryusage_show(struct seq_file *m, void *v) +{ + ssize_t ret = 0; + int total_size_in_bytes; + int peak_size_in_bytes; + + total_size_in_bytes = kbase_report_gpu_memory_usage(); + peak_size_in_bytes = kbase_report_gpu_memory_peak(); + + ret = seq_printf(m, "curr: %10u, peak %10u\n", total_size_in_bytes, peak_size_in_bytes); + + return ret; +} + +static int kbasep_gpu_memoryusage_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_memoryusage_show, NULL); +} + +static const struct file_operations kbasep_gpu_memory_usage_debugfs_open = { + .open = kbasep_gpu_memoryusage_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + + +/// 2. For GL/CL utilization +static int proc_gpu_utilization_show(struct seq_file *m, void *v) +{ + unsigned long gl, cl0, cl1; + unsigned int iCurrentFreq; + + iCurrentFreq = mt_gpufreq_get_cur_freq_index(); + + gl = kbasep_get_gl_utilization(); + cl0 = kbasep_get_cl_js0_utilization(); + cl1 = kbasep_get_cl_js1_utilization(); + + seq_printf(m, "gpu/cljs0/cljs1=%lu/%lu/%lu, frequency=%d(kHz)\n", gl, cl0, cl1, _mtk_gpu_dvfs_index_to_frequency(iCurrentFreq)); + + return 0; +} + +static int kbasep_gpu_utilization_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_utilization_show , NULL); +} + +static const struct file_operations kbasep_gpu_utilization_debugfs_fops = { + .open = kbasep_gpu_utilization_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + + + +/// 3. For query GPU frequency +static int proc_gpu_frequency_show(struct seq_file *m, void *v) +{ + + unsigned int iCurrentFreq; + + iCurrentFreq = mt_gpufreq_get_cur_freq_index(); + + seq_printf(m, "GPU Frequency: %u(kHz)\n", _mtk_gpu_dvfs_index_to_frequency(iCurrentFreq)); + + return 0; +} + +static int kbasep_gpu_frequency_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_frequency_show , NULL); +} + +static const struct file_operations kbasep_gpu_frequency_debugfs_fops = { + .open = kbasep_gpu_frequency_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + + + +/// 4. For query GPU dynamically enable DVFS +static int proc_gpu_dvfs_enabled_show(struct seq_file *m, void *v) +{ + + int dvfs_enabled; + + dvfs_enabled = mtk_get_dvfs_enabled(); + + seq_printf(m, "dvfs_enabled: %d\n", dvfs_enabled); + + return 0; +} + +static int kbasep_gpu_dvfs_enable_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_dvfs_enabled_show , NULL); +} + +static int kbasep_gpu_dvfs_enable_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(!strncmp(desc, "1", 1)) + g_dvfs_enabled = 1; + else if(!strncmp(desc, "0", 1)) + g_dvfs_enabled = 0; + else if(!strncmp(desc, "2", 1)) + g_dvfs_enabled = 2; + + return count; +} + +static const struct file_operations kbasep_gpu_dvfs_enable_debugfs_fops = { + .open = kbasep_gpu_dvfs_enable_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_dvfs_enable_write, +}; + + + +/// 5. For query GPU dynamically enable input boost +static int proc_gpu_input_boost_show(struct seq_file *m, void *v) +{ + + int input_boost_enabled; + + input_boost_enabled = mtk_get_input_boost_enabled(); + + seq_printf(m, "GPU input boost enabled: %d\n", input_boost_enabled); + + return 0; +} + +static int kbasep_gpu_input_boost_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_input_boost_show , NULL); +} + +static int kbasep_gpu_input_boost_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(!strncmp(desc, "1", 1)) + g_input_boost_enabled = 1; + else if(!strncmp(desc, "0", 1)) + g_input_boost_enabled = 0; + + return count; +} + +static const struct file_operations kbasep_gpu_input_boost_debugfs_fops = { + .open = kbasep_gpu_input_boost_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_input_boost_write, +}; + + + +/// 6. For query GPU dynamically set dvfs frequency (ms) +static int proc_gpu_dvfs_freq_show(struct seq_file *m, void *v) +{ + + int dvfs_freq; + + dvfs_freq = mtk_get_dvfs_freq(); + + seq_printf(m, "GPU DVFS freq : %d(ms)\n", dvfs_freq); + + return 0; +} + +static int kbasep_gpu_dvfs_freq_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_dvfs_freq_show , NULL); +} + +static int kbasep_gpu_dvfs_freq_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + int dvfs_freq = 0; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(sscanf(desc, "%d", &dvfs_freq) == 1) + g_dvfs_freq = dvfs_freq; + else + pr_debug("[MALI] warning! echo [dvfs_freq(ms)] > /proc/mali/dvfs_freq\n"); + + return count; +} + +static const struct file_operations kbasep_gpu_dvfs_freq_debugfs_fops = { + .open = kbasep_gpu_dvfs_freq_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_dvfs_freq_write, +}; + + + +/// 7.For query GPU dynamically set dvfs threshold +static int proc_gpu_dvfs_threshold_show(struct seq_file *m, void *v) +{ + + int threshold_max, threshold_min; + + threshold_max = mtk_get_dvfs_threshold_max(); + threshold_min = mtk_get_dvfs_threshold_min(); + + seq_printf(m, "GPU DVFS threshold : max:%d min:%d\n", threshold_max, threshold_min); + + return 0; +} + +static int kbasep_gpu_dvfs_threshold_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_dvfs_threshold_show , NULL); +} + +static int kbasep_gpu_dvfs_threshold_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + int threshold_max, threshold_min; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(sscanf(desc, "%d %d", &threshold_max, &threshold_min) == 2) + { + g_dvfs_threshold_max = threshold_max; + g_dvfs_threshold_min = threshold_min; + } + else + pr_debug("[MALI] warning! echo [dvfs_threshold_max] [dvfs_threshold_min] > /proc/mali/dvfs_threshold\n"); + + return count; +} + +static const struct file_operations kbasep_gpu_dvfs_threshold_debugfs_fops = { + .open = kbasep_gpu_dvfs_threshold_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_dvfs_threshold_write, +}; + + + +/// 8.For query GPU dynamically set dvfs deferred count +static int proc_gpu_dvfs_deferred_count_show(struct seq_file *m, void *v) +{ + + int deferred_count; + + deferred_count = mtk_get_dvfs_deferred_count(); + + seq_printf(m, "GPU DVFS deferred_count : %d\n", deferred_count); + + return 0; +} + +static int kbasep_gpu_dvfs_deferred_count_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_dvfs_deferred_count_show , NULL); +} + +static int kbasep_gpu_dvfs_deferred_count_write(struct file *file, const char __user *buffer, + size_t count, loff_t *data) +{ + char desc[32]; + int len = 0; + int dvfs_deferred_count; + + len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); + if (copy_from_user(desc, buffer, len)) { + return 0; + } + desc[len] = '\0'; + + if(sscanf(desc, "%d", &dvfs_deferred_count) == 1) + g_dvfs_deferred_count = dvfs_deferred_count; + else + pr_debug("[MALI] warning! echo [dvfs_deferred_count] > /proc/mali/dvfs_deferred_count\n"); + + return count; +} + +static const struct file_operations kbasep_gpu_dvfs_deferred_count_debugfs_fops = { + .open = kbasep_gpu_dvfs_deferred_count_debugfs_open, + .read = seq_read, + .write = kbasep_gpu_dvfs_deferred_count_write, +}; + + +/// 9. For query the support command +static int proc_gpu_help_show(struct seq_file *m, void *v) +{ + seq_printf(m, "======================================================================\n"); + seq_printf(m, "A.For Query GPU/CPU related Command:\n"); + seq_printf(m, " cat /proc/mali/utilization\n"); + seq_printf(m, " cat /proc/mali/frequency\n"); + seq_printf(m, " cat /proc/mali/memory_usage\n"); + seq_printf(m, " cat /proc/gpufreq/gpufreq_var_dump\n"); + seq_printf(m, " cat /proc/pm_init/ckgen_meter_test\n"); + seq_printf(m, " cat /proc/cpufreq/cpufreq_cur_freq\n"); + seq_printf(m, "======================================================================\n"); + seq_printf(m, "B.For Fix GPU Frequency:\n"); + seq_printf(m, " echo > (728000, 520000, 312000) /proc/gpufreq/gpufreq_opp_freq\n"); + seq_printf(m, " echo 0 > /proc/gpufreq/gpufreq_opp_freq(re-enable GPU DVFS)\n"); + seq_printf(m, "C.For Turn On/Off CPU core number:\n"); + seq_printf(m, " echo (1, 0) > /sys/devices/system/cpu/cpu1/online\n"); + seq_printf(m, " echo (1, 0) > /sys/devices/system/cpu/cpu2/online\n"); + seq_printf(m, " echo (1, 0) > /sys/devices/system/cpu/cpuN/online\n"); + seq_printf(m, "D.For CPU Performance mode(Force CPU to run at highest speed:\n"); + seq_printf(m, " echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor\n"); + seq_printf(m, " echo interactive > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor(re-enable CPU DVFS)\n"); + seq_printf(m, "==============================================================================================\n"); + seq_printf(m, "E.For GPU advanced debugging command:\n"); + seq_printf(m, " echo [dvfs_freq(ms)] > /proc/mali/dvfs_freq\n"); + seq_printf(m, " echo [dvfs_thr_max] [dvfs_thr_min] > /proc/mali/dvfs_threshold\n"); + seq_printf(m, " echo [dvfs_deferred_count] > /proc/mali/dvfs_deferred_count\n"); + seq_printf(m, "==============================================================================================\n"); + + return 0; +} + +static int kbasep_gpu_help_debugfs_open(struct inode *in, struct file *file) +{ + return single_open(file, proc_gpu_help_show , NULL); +} + +static const struct file_operations kbasep_gpu_help_debugfs_fops = { + .open = kbasep_gpu_help_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *mali_pentry; + +void proc_mali_register(void) +{ + mali_pentry = proc_mkdir("mali", NULL); + + if (!mali_pentry) + return; + + proc_create("help", 0, mali_pentry, &kbasep_gpu_help_debugfs_fops); + proc_create("memory_usage", 0, mali_pentry, &kbasep_gpu_memory_usage_debugfs_open); + proc_create("utilization", 0, mali_pentry, &kbasep_gpu_utilization_debugfs_fops); + proc_create("frequency", 0, mali_pentry, &kbasep_gpu_frequency_debugfs_fops); + proc_create("dvfs_enable", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_dvfs_enable_debugfs_fops); + proc_create("input_boost", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_input_boost_debugfs_fops); + proc_create("dvfs_freq", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_dvfs_freq_debugfs_fops); + proc_create("dvfs_threshold", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_dvfs_threshold_debugfs_fops); + proc_create("dvfs_deferred_count", S_IRUGO | S_IWUSR, mali_pentry, &kbasep_gpu_dvfs_deferred_count_debugfs_fops); +} +void proc_mali_unregister(void) +{ + if (!mali_pentry) + return; + + remove_proc_entry("help", mali_pentry); + remove_proc_entry("memory_usage", mali_pentry); + remove_proc_entry("utilization", mali_pentry); + remove_proc_entry("frequency", mali_pentry); + remove_proc_entry("mali", NULL); + mali_pentry = NULL; +} +#else +#define proc_mali_register() do{}while(0) +#define proc_mali_unregister() do{}while(0) +#endif /// CONFIG_PROC_FS + +#endif /* CONFIG_MALI_MIDGARD_DVFS */ + +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics_dummy.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics_dummy.c new file mode 100644 index 0000000000000000000000000000000000000000..7823d824f5a32888b0367904681b96013ad8ffbb --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_metrics_dummy.c @@ -0,0 +1,41 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_pm_metrics_dummy.c + * Dummy Metrics for power management. + */ + +#include +#include + +#if KBASE_PM_EN +void kbase_pm_register_vsync_callback(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + /* no VSync metrics will be available */ + kbdev->pm.metrics.platform_data = NULL; +} + +void kbase_pm_unregister_vsync_callback(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); +} +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.c new file mode 100644 index 0000000000000000000000000000000000000000..06f033c595238c7683848ac08bf286addb839a42 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.c @@ -0,0 +1,822 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_policy.c + * Power policy API implementations + */ + +#include +#include +#include +#include + +#if KBASE_PM_EN + +extern const struct kbase_pm_policy kbase_pm_always_on_policy_ops; +extern const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops; +extern const struct kbase_pm_policy kbase_pm_demand_policy_ops; + +#if !MALI_CUSTOMER_RELEASE +extern const struct kbase_pm_policy kbase_pm_fast_start_policy_ops; +extern const struct kbase_pm_policy kbase_pm_demand_always_powered_policy_ops; +#endif + +static const struct kbase_pm_policy *const policy_list[] = { +#ifdef CONFIG_MALI_NO_MALI + &kbase_pm_always_on_policy_ops, + &kbase_pm_demand_policy_ops, + &kbase_pm_coarse_demand_policy_ops, +#if !MALI_CUSTOMER_RELEASE + &kbase_pm_demand_always_powered_policy_ops, + &kbase_pm_fast_start_policy_ops, +#endif +#else /* CONFIG_MALI_NO_MALI */ + &kbase_pm_demand_policy_ops, + &kbase_pm_always_on_policy_ops, + &kbase_pm_coarse_demand_policy_ops, +#if !MALI_CUSTOMER_RELEASE + &kbase_pm_demand_always_powered_policy_ops, + &kbase_pm_fast_start_policy_ops, +#endif +#endif /* CONFIG_MALI_NO_MALI */ +}; + +/** The number of policies available in the system. + * This is derived from the number of functions listed in policy_get_functions. + */ +#define POLICY_COUNT (sizeof(policy_list)/sizeof(*policy_list)) + + +/* Function IDs for looking up Timeline Trace codes in kbase_pm_change_state_trace_code */ +enum kbase_pm_func_id { + KBASE_PM_FUNC_ID_REQUEST_CORES_START, + KBASE_PM_FUNC_ID_REQUEST_CORES_END, + KBASE_PM_FUNC_ID_RELEASE_CORES_START, + KBASE_PM_FUNC_ID_RELEASE_CORES_END, + /* Note: kbase_pm_unrequest_cores() is on the slow path, and we neither + * expect to hit it nor tend to hit it very much anyway. We can detect + * whether we need more instrumentation by a difference between + * PM_CHECKTRANS events and PM_SEND/HANDLE_EVENT. */ + + /* Must be the last */ + KBASE_PM_FUNC_ID_COUNT +}; + + +/* State changes during request/unrequest/release-ing cores */ +enum { + KBASE_PM_CHANGE_STATE_SHADER = (1u << 0), + KBASE_PM_CHANGE_STATE_TILER = (1u << 1), + + /* These two must be last */ + KBASE_PM_CHANGE_STATE_MASK = (KBASE_PM_CHANGE_STATE_TILER|KBASE_PM_CHANGE_STATE_SHADER), + KBASE_PM_CHANGE_STATE_COUNT = KBASE_PM_CHANGE_STATE_MASK + 1 +}; +typedef u32 kbase_pm_change_state; + + +#ifdef CONFIG_MALI_TRACE_TIMELINE +/* Timeline Trace code lookups for each function */ +static u32 kbase_pm_change_state_trace_code[KBASE_PM_FUNC_ID_COUNT][KBASE_PM_CHANGE_STATE_COUNT] = { + /* kbase_pm_request_cores */ + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][0] = 0, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_START, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_START, + [KBASE_PM_FUNC_ID_REQUEST_CORES_START][KBASE_PM_CHANGE_STATE_SHADER|KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_START, + + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][0] = 0, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_END, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_END, + [KBASE_PM_FUNC_ID_REQUEST_CORES_END][KBASE_PM_CHANGE_STATE_SHADER|KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_END, + + /* kbase_pm_release_cores */ + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][0] = 0, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_START, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_START, + [KBASE_PM_FUNC_ID_RELEASE_CORES_START][KBASE_PM_CHANGE_STATE_SHADER|KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_START, + + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][0] = 0, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_SHADER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_END, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_END, + [KBASE_PM_FUNC_ID_RELEASE_CORES_END][KBASE_PM_CHANGE_STATE_SHADER|KBASE_PM_CHANGE_STATE_TILER] = + SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_END +}; + +STATIC INLINE void kbase_timeline_pm_cores_func(struct kbase_device *kbdev, + enum kbase_pm_func_id func_id, + kbase_pm_change_state state) +{ + int trace_code; + + KBASE_DEBUG_ASSERT(func_id >= 0 && func_id < KBASE_PM_FUNC_ID_COUNT); + KBASE_DEBUG_ASSERT(state != 0 && (state & KBASE_PM_CHANGE_STATE_MASK) == state); + + trace_code = kbase_pm_change_state_trace_code[func_id][state]; + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code); +} + +#else /* CONFIG_MALI_TRACE_TIMELINE */ +STATIC INLINE void kbase_timeline_pm_cores_func(struct kbase_device *kbdev, + enum kbase_pm_func_id func_id, kbase_pm_change_state state) +{ +} + +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +static enum hrtimer_restart kbasep_pm_do_gpu_poweroff_callback(struct hrtimer *timer) +{ + struct kbase_device *kbdev; + + kbdev = container_of(timer, struct kbase_device, pm.gpu_poweroff_timer); + + /* It is safe for this call to do nothing if the work item is already queued. + * The worker function will read the must up-to-date state of kbdev->pm.gpu_poweroff_pending + * under lock. + * + * If a state change occurs while the worker function is processing, this + * call will succeed as a work item can be requeued once it has started + * processing. + */ + if (kbdev->pm.gpu_poweroff_pending) + queue_work(kbdev->pm.gpu_poweroff_wq, &kbdev->pm.gpu_poweroff_work); + + if (kbdev->pm.shader_poweroff_pending) { + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + if (kbdev->pm.shader_poweroff_pending) { + kbdev->pm.shader_poweroff_pending_time--; + + KBASE_DEBUG_ASSERT(kbdev->pm.shader_poweroff_pending_time >= 0); + + if (kbdev->pm.shader_poweroff_pending_time == 0) { + u64 prev_shader_state = kbdev->pm.desired_shader_state; + + kbdev->pm.desired_shader_state &= ~kbdev->pm.shader_poweroff_pending; + kbdev->pm.shader_poweroff_pending = 0; + + if (prev_shader_state != kbdev->pm.desired_shader_state || + kbdev->pm.ca_in_transition != MALI_FALSE) { + mali_bool cores_are_available; + + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_START); + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_END); + + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); + } + } + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + } + + if (kbdev->pm.poweroff_timer_needed) { + hrtimer_add_expires(timer, kbdev->pm.gpu_poweroff_time); + + return HRTIMER_RESTART; + } + + return HRTIMER_NORESTART; +} + +static void kbasep_pm_do_gpu_poweroff_wq(struct work_struct *data) +{ + unsigned long flags; + struct kbase_device *kbdev; + mali_bool do_poweroff = MALI_FALSE; + + kbdev = container_of(data, struct kbase_device, pm.gpu_poweroff_work); + + mutex_lock(&kbdev->pm.lock); + + if (kbdev->pm.gpu_poweroff_pending == 0) { + mutex_unlock(&kbdev->pm.lock); + return; + } + + kbdev->pm.gpu_poweroff_pending--; + + if (kbdev->pm.gpu_poweroff_pending > 0) { + mutex_unlock(&kbdev->pm.lock); + return; + } + + KBASE_DEBUG_ASSERT(kbdev->pm.gpu_poweroff_pending == 0); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + /* Only power off the GPU if a request is still pending */ + if (kbdev->pm.pm_current_policy->get_core_active(kbdev) == MALI_FALSE) + do_poweroff = MALI_TRUE; + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + if (do_poweroff != MALI_FALSE) { + kbdev->pm.poweroff_timer_needed = MALI_FALSE; + /* Power off the GPU */ + kbase_pm_do_poweroff(kbdev, MALI_FALSE); + hrtimer_cancel(&kbdev->pm.gpu_poweroff_timer); + } + + mutex_unlock(&kbdev->pm.lock); +} + +mali_error kbase_pm_policy_init(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + kbdev->pm.gpu_poweroff_wq = alloc_workqueue("kbase_pm_do_poweroff", WQ_HIGHPRI | WQ_UNBOUND, 1); + if (NULL == kbdev->pm.gpu_poweroff_wq) + return MALI_ERROR_OUT_OF_MEMORY; + INIT_WORK(&kbdev->pm.gpu_poweroff_work, kbasep_pm_do_gpu_poweroff_wq); + + hrtimer_init(&kbdev->pm.gpu_poweroff_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kbdev->pm.gpu_poweroff_timer.function = kbasep_pm_do_gpu_poweroff_callback; + + kbdev->pm.pm_current_policy = policy_list[0]; + + kbdev->pm.pm_current_policy->init(kbdev); + + kbdev->pm.gpu_poweroff_time = HR_TIMER_DELAY_NSEC(kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS)); + + kbdev->pm.poweroff_shader_ticks = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER); + kbdev->pm.poweroff_gpu_ticks = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU); + + return MALI_ERROR_NONE; +} + +void kbase_pm_policy_term(struct kbase_device *kbdev) +{ + kbdev->pm.pm_current_policy->term(kbdev); +} + +void kbase_pm_cancel_deferred_poweroff(struct kbase_device *kbdev) +{ + unsigned long flags; + + lockdep_assert_held(&kbdev->pm.lock); + + kbdev->pm.poweroff_timer_needed = MALI_FALSE; + hrtimer_cancel(&kbdev->pm.gpu_poweroff_timer); + + /* If wq is already running but is held off by pm.lock, make sure it has no effect */ + kbdev->pm.gpu_poweroff_pending = 0; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + kbdev->pm.shader_poweroff_pending = 0; + kbdev->pm.shader_poweroff_pending_time = 0; + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +void kbase_pm_update_active(struct kbase_device *kbdev) +{ + unsigned long flags; + mali_bool active; + + lockdep_assert_held(&kbdev->pm.lock); + + /* pm_current_policy will never be NULL while pm.lock is held */ + KBASE_DEBUG_ASSERT(kbdev->pm.pm_current_policy); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + active = kbdev->pm.pm_current_policy->get_core_active(kbdev); + + if (active != MALI_FALSE) { + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + if (kbdev->pm.gpu_poweroff_pending) { + /* Cancel any pending power off request */ + kbdev->pm.gpu_poweroff_pending = 0; + + /* If a request was pending then the GPU was still powered, so no need to continue */ + return; + } + + if (!kbdev->pm.poweroff_timer_needed && !kbdev->pm.gpu_powered) { + kbdev->pm.poweroff_timer_needed = MALI_TRUE; + hrtimer_start(&kbdev->pm.gpu_poweroff_timer, kbdev->pm.gpu_poweroff_time, HRTIMER_MODE_REL); + } + + /* Power on the GPU and any cores requested by the policy */ + kbase_pm_do_poweron(kbdev, MALI_FALSE); + } else { + /* It is an error for the power policy to power off the GPU + * when there are contexts active */ + KBASE_DEBUG_ASSERT(kbdev->pm.active_count == 0); + + if (kbdev->pm.shader_poweroff_pending) { + kbdev->pm.shader_poweroff_pending = 0; + kbdev->pm.shader_poweroff_pending_time = 0; + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + + /* Request power off */ + if (kbdev->pm.gpu_powered) { + kbdev->pm.gpu_poweroff_pending = kbdev->pm.poweroff_gpu_ticks; + if (!kbdev->pm.poweroff_timer_needed) { + /* Start timer if not running (eg if power policy has been changed from always_on + * to something else). This will ensure the GPU is actually powered off */ + kbdev->pm.poweroff_timer_needed = MALI_TRUE; + hrtimer_start(&kbdev->pm.gpu_poweroff_timer, kbdev->pm.gpu_poweroff_time, HRTIMER_MODE_REL); + } + } + } +} + +void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev) +{ + u64 desired_bitmap; + mali_bool cores_are_available; + + lockdep_assert_held(&kbdev->pm.power_change_lock); + + if (kbdev->pm.pm_current_policy == NULL) + return; + + desired_bitmap = kbdev->pm.pm_current_policy->get_core_mask(kbdev); + desired_bitmap &= kbase_pm_ca_get_core_mask(kbdev); + + /* Enable core 0 if tiler required, regardless of core availability */ + if (kbdev->tiler_needed_cnt > 0 || kbdev->tiler_inuse_cnt > 0) + desired_bitmap |= 1; + + if (kbdev->pm.desired_shader_state != desired_bitmap) + KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_DESIRED, NULL, NULL, 0u, (u32)desired_bitmap); + + /* Are any cores being powered on? */ + if (~kbdev->pm.desired_shader_state & desired_bitmap || + kbdev->pm.ca_in_transition != MALI_FALSE) { + /* Check if we are powering off any cores before updating shader state */ + if (kbdev->pm.desired_shader_state & ~desired_bitmap) { + /* Start timer to power off cores */ + kbdev->pm.shader_poweroff_pending |= (kbdev->pm.desired_shader_state & ~desired_bitmap); + kbdev->pm.shader_poweroff_pending_time = kbdev->pm.poweroff_shader_ticks; + } + + kbdev->pm.desired_shader_state = desired_bitmap; + + /* If any cores are being powered on, transition immediately */ + cores_are_available = kbase_pm_check_transitions_nolock(kbdev); + } else if (kbdev->pm.desired_shader_state & ~desired_bitmap) { + /* Start timer to power off cores */ + kbdev->pm.shader_poweroff_pending |= (kbdev->pm.desired_shader_state & ~desired_bitmap); + kbdev->pm.shader_poweroff_pending_time = kbdev->pm.poweroff_shader_ticks; + } else if (kbdev->pm.active_count == 0 && desired_bitmap != 0 && kbdev->pm.poweroff_timer_needed) { + /* If power policy is keeping cores on despite there being no + * active contexts then disable poweroff timer as it isn't + * required. + * Only reset poweroff_timer_needed if we're not in the middle + * of the power off callback */ + kbdev->pm.poweroff_timer_needed = MALI_FALSE; + hrtimer_try_to_cancel(&kbdev->pm.gpu_poweroff_timer); + } + + /* Ensure timer does not power off wanted cores and make sure to power off unwanted cores */ + if (kbdev->pm.shader_poweroff_pending != 0) { + kbdev->pm.shader_poweroff_pending &= ~(kbdev->pm.desired_shader_state & desired_bitmap); + if (kbdev->pm.shader_poweroff_pending == 0) + kbdev->pm.shader_poweroff_pending_time = 0; + } + + /* Don't need 'cores_are_available', because we don't return anything */ + CSTD_UNUSED(cores_are_available); +} + +void kbase_pm_update_cores_state(struct kbase_device *kbdev) +{ + unsigned long flags; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + kbase_pm_update_cores_state_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +int kbase_pm_list_policies(const struct kbase_pm_policy * const **list) +{ + if (!list) + return POLICY_COUNT; + + *list = policy_list; + + return POLICY_COUNT; +} + +KBASE_EXPORT_TEST_API(kbase_pm_list_policies) + +const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev) +{ + KBASE_DEBUG_ASSERT(kbdev != NULL); + + return kbdev->pm.pm_current_policy; +} + +KBASE_EXPORT_TEST_API(kbase_pm_get_policy) + +void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_policy *new_policy) +{ + const struct kbase_pm_policy *old_policy; + unsigned long flags; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + KBASE_DEBUG_ASSERT(new_policy != NULL); + + KBASE_TRACE_ADD(kbdev, PM_SET_POLICY, NULL, NULL, 0u, new_policy->id); + + /* During a policy change we pretend the GPU is active */ + /* A suspend won't happen here, because we're in a syscall from a userspace thread */ + kbase_pm_context_active(kbdev); + + mutex_lock(&kbdev->pm.lock); + + /* Remove the policy to prevent IRQ handlers from working on it */ + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + old_policy = kbdev->pm.pm_current_policy; + kbdev->pm.pm_current_policy = NULL; + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + KBASE_TRACE_ADD(kbdev, PM_CURRENT_POLICY_TERM, NULL, NULL, 0u, old_policy->id); + if (old_policy->term) + old_policy->term(kbdev); + + KBASE_TRACE_ADD(kbdev, PM_CURRENT_POLICY_INIT, NULL, NULL, 0u, new_policy->id); + if (new_policy->init) + new_policy->init(kbdev); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + kbdev->pm.pm_current_policy = new_policy; + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + /* If any core power state changes were previously attempted, but couldn't + * be made because the policy was changing (current_policy was NULL), then + * re-try them here. */ + kbase_pm_update_active(kbdev); + kbase_pm_update_cores_state(kbdev); + + mutex_unlock(&kbdev->pm.lock); + + /* Now the policy change is finished, we release our fake context active reference */ + kbase_pm_context_idle(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_set_policy) + +/** Check whether a state change has finished, and trace it as completed */ +STATIC void kbase_pm_trace_check_and_finish_state_change(struct kbase_device *kbdev) +{ + if ((kbdev->shader_available_bitmap & kbdev->pm.desired_shader_state) == kbdev->pm.desired_shader_state && + (kbdev->tiler_available_bitmap & kbdev->pm.desired_tiler_state) == kbdev->pm.desired_tiler_state) + kbase_timeline_pm_check_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED); +} + +void kbase_pm_request_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + unsigned long flags; + u64 cores; + + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + cores = shader_cores; + while (cores) { + int bitnum = fls64(cores) - 1; + u64 bit = 1ULL << bitnum; + + /* It should be almost impossible for this to overflow. It would require 2^32 atoms + * to request a particular core, which would require 2^24 contexts to submit. This + * would require an amount of memory that is impossible on a 32-bit system and + * extremely unlikely on a 64-bit system. */ + int cnt = ++kbdev->shader_needed_cnt[bitnum]; + + if (1 == cnt) { + kbdev->shader_needed_bitmap |= bit; + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + cores &= ~bit; + } + + if (tiler_required != MALI_FALSE) { + ++kbdev->tiler_needed_cnt; + + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt != 0); + + /* For tiler jobs, we must make sure that core 0 is not turned off if it's already on. + * However, it's safe for core 0 to be left off and turned on later whilst a tiler job + * is running. Hence, we don't need to update the cores state immediately. Also, + * attempts to turn off cores will always check the tiler_needed/inuse state first anyway. + * + * Finally, kbase_js_choose_affinity() ensures core 0 is always requested for tiler jobs + * anyway. Hence when there's only a tiler job in the system, this will still cause + * kbase_pm_update_cores_state_nolock() to be called. + * + * Note that we still need to keep track of tiler_needed/inuse_cnt, to ensure that + * kbase_pm_update_cores_state_nolock() can override the core availability policy and + * force core 0 to be powered when a tiler job is in the system. */ + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_REQUEST_CHANGE_SHADER_NEEDED, NULL, NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + kbase_timeline_pm_cores_func(kbdev, KBASE_PM_FUNC_ID_REQUEST_CORES_START, change_gpu_state); + kbase_pm_update_cores_state_nolock(kbdev); + kbase_timeline_pm_cores_func(kbdev, KBASE_PM_FUNC_ID_REQUEST_CORES_END, change_gpu_state); + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_cores) + +void kbase_pm_unrequest_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + unsigned long flags; + + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_needed_cnt[bitnum] > 0); + + cnt = --kbdev->shader_needed_cnt[bitnum]; + + if (0 == cnt) { + kbdev->shader_needed_bitmap &= ~bit; + + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + shader_cores &= ~bit; + } + + if (tiler_required != MALI_FALSE) { + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt > 0); + + --kbdev->tiler_needed_cnt; + + /* Whilst tiler jobs must not allow core 0 to be turned off, we don't need to make an + * extra call to kbase_pm_update_cores_state_nolock() to ensure core 0 is turned off + * when the last tiler job unrequests cores: kbase_js_choose_affinity() ensures core 0 + * was originally requested for tiler jobs. Hence when there's only a tiler job in the + * system, this will still cause kbase_pm_update_cores_state_nolock() to be called. */ + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_UNREQUEST_CHANGE_SHADER_NEEDED, NULL, NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + kbase_pm_update_cores_state_nolock(kbdev); + + /* Trace that any state change effectively completes immediately - + * no-one will wait on the state change */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_unrequest_cores) + +enum kbase_pm_cores_ready kbase_pm_register_inuse_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + unsigned long flags; + u64 prev_shader_needed; /* Just for tracing */ + u64 prev_shader_inuse; /* Just for tracing */ + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + prev_shader_needed = kbdev->shader_needed_bitmap; + prev_shader_inuse = kbdev->shader_inuse_bitmap; + + /* If desired_shader_state does not contain the requested cores, then power + * management is not attempting to powering those cores (most likely + * due to core availability policy) and a new job affinity must be + * chosen */ + if ((kbdev->pm.desired_shader_state & shader_cores) != shader_cores) { + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + return KBASE_NEW_AFFINITY; + } + + if ((kbdev->shader_available_bitmap & shader_cores) != shader_cores || + (tiler_required != MALI_FALSE && !kbdev->tiler_available_bitmap)) { + /* Trace ongoing core transition */ + kbase_timeline_pm_l2_transition_start(kbdev); + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + return KBASE_CORES_NOT_READY; + } + + /* If we started to trace a state change, then trace it has being finished + * by now, at the very latest */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + /* Trace core transition done */ + kbase_timeline_pm_l2_transition_done(kbdev); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_needed_cnt[bitnum] > 0); + + cnt = --kbdev->shader_needed_cnt[bitnum]; + + if (0 == cnt) + kbdev->shader_needed_bitmap &= ~bit; + + /* shader_inuse_cnt should not overflow because there can only be a + * very limited number of jobs on the h/w at one time */ + + kbdev->shader_inuse_cnt[bitnum]++; + kbdev->shader_inuse_bitmap |= bit; + + shader_cores &= ~bit; + } + + if (tiler_required != MALI_FALSE) { + KBASE_DEBUG_ASSERT(kbdev->tiler_needed_cnt > 0); + + --kbdev->tiler_needed_cnt; + + kbdev->tiler_inuse_cnt++; + + KBASE_DEBUG_ASSERT(kbdev->tiler_inuse_cnt != 0); + } + + if (prev_shader_needed != kbdev->shader_needed_bitmap) + KBASE_TRACE_ADD(kbdev, PM_REGISTER_CHANGE_SHADER_NEEDED, NULL, NULL, 0u, (u32) kbdev->shader_needed_bitmap); + + if (prev_shader_inuse != kbdev->shader_inuse_bitmap) + KBASE_TRACE_ADD(kbdev, PM_REGISTER_CHANGE_SHADER_INUSE, NULL, NULL, 0u, (u32) kbdev->shader_inuse_bitmap); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + + return KBASE_CORES_READY; +} + +KBASE_EXPORT_TEST_API(kbase_pm_register_inuse_cores) + +void kbase_pm_release_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + unsigned long flags; + kbase_pm_change_state change_gpu_state = 0u; + + KBASE_DEBUG_ASSERT(kbdev != NULL); + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + while (shader_cores) { + int bitnum = fls64(shader_cores) - 1; + u64 bit = 1ULL << bitnum; + int cnt; + + KBASE_DEBUG_ASSERT(kbdev->shader_inuse_cnt[bitnum] > 0); + + cnt = --kbdev->shader_inuse_cnt[bitnum]; + + if (0 == cnt) { + kbdev->shader_inuse_bitmap &= ~bit; + change_gpu_state |= KBASE_PM_CHANGE_STATE_SHADER; + } + + shader_cores &= ~bit; + } + + if (tiler_required != MALI_FALSE) { + KBASE_DEBUG_ASSERT(kbdev->tiler_inuse_cnt > 0); + + --kbdev->tiler_inuse_cnt; + + /* Whilst tiler jobs must not allow core 0 to be turned off, we don't need to make an + * extra call to kbase_pm_update_cores_state_nolock() to ensure core 0 is turned off + * when the last tiler job finishes: kbase_js_choose_affinity() ensures core 0 was + * originally requested for tiler jobs. Hence when there's only a tiler job in the + * system, this will still cause kbase_pm_update_cores_state_nolock() to be called */ + } + + if (change_gpu_state) { + KBASE_TRACE_ADD(kbdev, PM_RELEASE_CHANGE_SHADER_INUSE, NULL, NULL, 0u, (u32) kbdev->shader_inuse_bitmap); + + kbase_timeline_pm_cores_func(kbdev, KBASE_PM_FUNC_ID_RELEASE_CORES_START, change_gpu_state); + kbase_pm_update_cores_state_nolock(kbdev); + kbase_timeline_pm_cores_func(kbdev, KBASE_PM_FUNC_ID_RELEASE_CORES_END, change_gpu_state); + + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_cores) + +void kbase_pm_request_cores_sync(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores) +{ + kbase_pm_request_cores(kbdev, tiler_required, shader_cores); + + kbase_pm_check_transitions_sync(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_cores_sync) + +void kbase_pm_request_l2_caches(struct kbase_device *kbdev) +{ + unsigned long flags; + u32 prior_l2_users_count; + + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + prior_l2_users_count = kbdev->l2_users_count++; + + KBASE_DEBUG_ASSERT(kbdev->l2_users_count != 0); + + /* if the GPU is reset while the l2 is on, l2 will be off but prior_l2_users_count will be > 0 + * l2_available_bitmap will have been set to 0 though by kbase_pm_init_hw */ + if (!prior_l2_users_count || !kbdev->l2_available_bitmap) + kbase_pm_check_transitions_nolock(kbdev); + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); + wait_event(kbdev->pm.l2_powered_wait, kbdev->pm.l2_powered == 1); + + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_l2_caches) + +void kbase_pm_request_l2_caches_l2_is_on(struct kbase_device *kbdev) +{ + unsigned long flags; + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + kbdev->l2_users_count++; + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_request_l2_caches_l2_is_on) + +void kbase_pm_release_l2_caches(struct kbase_device *kbdev) +{ + unsigned long flags; + spin_lock_irqsave(&kbdev->pm.power_change_lock, flags); + + KBASE_DEBUG_ASSERT(kbdev->l2_users_count > 0); + + --kbdev->l2_users_count; + + if (!kbdev->l2_users_count) { + kbase_pm_check_transitions_nolock(kbdev); + /* Trace that any state change completed immediately */ + kbase_pm_trace_check_and_finish_state_change(kbdev); + } + + spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags); +} + +KBASE_EXPORT_TEST_API(kbase_pm_release_l2_caches) +#endif /* KBASE_PM_EN */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.h new file mode 100644 index 0000000000000000000000000000000000000000..4a8cc44b6308fc6cedc78e96d071b00eea0c7e1c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_pm_policy.h @@ -0,0 +1,277 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_pm_policy.h + * Power policy API definitions + */ + +#ifndef _KBASE_PM_POLICY_H_ +#define _KBASE_PM_POLICY_H_ + +/** List of policy IDs */ +enum kbase_pm_policy_id { + KBASE_PM_POLICY_ID_DEMAND = 1, + KBASE_PM_POLICY_ID_ALWAYS_ON, + KBASE_PM_POLICY_ID_COARSE_DEMAND, +#if !MALI_CUSTOMER_RELEASE + KBASE_PM_POLICY_ID_DEMAND_ALWAYS_POWERED, + KBASE_PM_POLICY_ID_FAST_START +#endif +}; + +typedef u32 kbase_pm_policy_flags; + +/** Power policy structure. + * + * Each power policy exposes a (static) instance of this structure which contains function pointers to the + * policy's methods. + */ +typedef struct kbase_pm_policy { + /** The name of this policy */ + char *name; + + /** Function called when the policy is selected + * + * This should initialize the kbdev->pm.pm_policy_data structure. It should not attempt + * to make any changes to hardware state. + * + * It is undefined what state the cores are in when the function is called. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + void (*init)(struct kbase_device *kbdev); + + /** Function called when the policy is unselected. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ + void (*term)(struct kbase_device *kbdev); + + /** Function called to get the current shader core mask + * + * The returned mask should meet or exceed (kbdev->shader_needed_bitmap | kbdev->shader_inuse_bitmap). + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The mask of shader cores to be powered */ + u64 (*get_core_mask)(struct kbase_device *kbdev); + + /** Function called to get the current overall GPU power state + * + * This function should consider the state of kbdev->pm.active_count. If this count is greater than 0 then + * there is at least one active context on the device and the GPU should be powered. If it is equal to 0 + * then there are no active contexts and the GPU could be powered off if desired. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_TRUE if the GPU should be powered, MALI_FALSE otherwise */ + mali_bool (*get_core_active) (struct kbase_device *kbdev); + + /** Field indicating flags for this policy */ + kbase_pm_policy_flags flags; + + /** Field indicating an ID for this policy. This is not necessarily the + * same as its index in the list returned by kbase_pm_list_policies(). + * It is used purely for debugging. */ + enum kbase_pm_policy_id id; +} kbase_pm_policy; + +/** Initialize power policy framework + * + * Must be called before calling any other policy function + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return MALI_ERROR_NONE if the power policy framework was successfully initialized. + */ +mali_error kbase_pm_policy_init(struct kbase_device *kbdev); + +/** Terminate power policy framework + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_policy_term(struct kbase_device *kbdev); + +/** Update the active power state of the GPU + * Calls into the current power policy + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_update_active(struct kbase_device *kbdev); + +/** Update the desired core state of the GPU + * Calls into the current power policy + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_update_cores(struct kbase_device *kbdev); + +/** Get the current policy. + * Returns the policy that is currently active. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * + * @return The current policy + */ +const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev); + +/** Change the policy to the one specified. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + * @param policy The policy to change to (valid pointer returned from @ref kbase_pm_list_policies) + */ +void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_policy *policy); + +/** Retrieve a static list of the available policies. + * @param[out] policies An array pointer to take the list of policies. This may be NULL. + * The contents of this array must not be modified. + * + * @return The number of policies + */ +int kbase_pm_list_policies(const struct kbase_pm_policy * const **policies); + + +enum kbase_pm_cores_ready { + KBASE_CORES_NOT_READY = 0, + KBASE_NEW_AFFINITY = 1, + KBASE_CORES_READY = 2 +}; + + +/** Synchronous variant of kbase_pm_request_cores() + * + * When this function returns, the @a shader_cores will be in the READY state. + * + * This is safe variant of kbase_pm_check_transitions_sync(): it handles the + * work of ensuring the requested cores will remain powered until a matching + * call to kbase_pm_unrequest_cores()/kbase_pm_release_cores() (as appropriate) + * is made. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores which are necessary for the job + */ + +void kbase_pm_request_cores_sync(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Mark one or more cores as being required for jobs to be submitted. + * + * This function is called by the job scheduler to mark one or more cores + * as being required to submit jobs that are ready to run. + * + * The cores requested are reference counted and a subsequent call to @ref kbase_pm_register_inuse_cores or + * @ref kbase_pm_unrequest_cores should be made to dereference the cores as being 'needed'. + * + * The active power policy will meet or exceed the requirements of the + * requested cores in the system. Any core transitions needed will be begun + * immediately, but they might not complete/the cores might not be available + * until a Power Management IRQ. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores which are necessary for the job + * + * @return MALI_ERROR_NONE if the cores were successfully requested. + */ +void kbase_pm_request_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Unmark one or more cores as being required for jobs to be submitted. + * + * This function undoes the effect of @ref kbase_pm_request_cores. It should be used when a job is not + * going to be submitted to the hardware (e.g. the job is cancelled before it is enqueued). + * + * The active power policy will meet or exceed the requirements of the + * requested cores in the system. Any core transitions needed will be begun + * immediately, but they might not complete until a Power Management IRQ. + * + * The policy may use this as an indication that it can power down cores. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores (as given to @ref kbase_pm_request_cores) + */ +void kbase_pm_unrequest_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Register a set of cores as in use by a job. + * + * This function should be called after @ref kbase_pm_request_cores when the job is about to be submitted to + * the hardware. It will check that the necessary cores are available and if so update the 'needed' and 'inuse' + * bitmasks to reflect that the job is now committed to being run. + * + * If the necessary cores are not currently available then the function will return MALI_FALSE and have no effect. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores (as given to @ref kbase_pm_request_cores) + * + * @return MALI_TRUE if the job can be submitted to the hardware or MALI_FALSE if the job is not ready to run. + */ +enum kbase_pm_cores_ready kbase_pm_register_inuse_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Release cores after a job has run. + * + * This function should be called when a job has finished running on the hardware. A call to @ref + * kbase_pm_register_inuse_cores must have previously occurred. The reference counts of the specified cores will be + * decremented which may cause the bitmask of 'inuse' cores to be reduced. The power policy may then turn off any + * cores which are no longer 'inuse'. + * + * @param kbdev The kbase device structure for the device + * @param tiler_required MALI_TRUE if the tiler is required, MALI_FALSE otherwise + * @param shader_cores A bitmask of shader cores (as given to @ref kbase_pm_register_inuse_cores) + */ +void kbase_pm_release_cores(struct kbase_device *kbdev, mali_bool tiler_required, u64 shader_cores); + +/** Request the use of l2 caches for all core groups, power up, wait and prevent the power manager from + * powering down the l2 caches. + * + * This tells the power management that the caches should be powered up, and they + * should remain powered, irrespective of the usage of shader cores. This does not + * return until the l2 caches are powered up. + * + * The caller must call @ref kbase_pm_release_l2_caches when they are finished to + * allow normal power management of the l2 caches to resume. + * + * This should only be used when power management is active. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_l2_caches(struct kbase_device *kbdev); + +/** Increment the count of l2 users but do not attempt to power on the l2 + * It is the callers responsibility to ensure that the l2 is already powered up + * and to eventually call @ref kbase_pm_release_l2_caches + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_request_l2_caches_l2_is_on(struct kbase_device *kbdev); + +/** Release the use of l2 caches for all core groups and allow the power manager to + * power them down when necessary. + * + * This tells the power management that the caches can be powered down if necessary, with respect + * to the usage of shader cores. + * + * The caller must have called @ref kbase_pm_request_l2_caches prior to a call to this. + * + * This should only be used when power management is active. + * + * @param kbdev The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_release_l2_caches(struct kbase_device *kbdev); + +#endif /* _KBASE_PM_POLICY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.c new file mode 100644 index 0000000000000000000000000000000000000000..b781b939ed0ad32a53ebc419770c6be0459d3c4b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.c @@ -0,0 +1,260 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include + +#include +#include +#include + +#include "mali_kbase_power_actor.h" + + +static u32 mali_pa_get_req_power(struct power_actor *actor, struct thermal_zone_device *zone) +{ + struct mali_power_actor *mali_actor = actor->data; + struct kbase_device *kbdev = mali_actor->kbdev; + unsigned long total_time, busy_time; + unsigned long power, temperature; + struct dev_pm_opp *opp; + unsigned long voltage; + unsigned long freq; + + kbase_pm_get_dvfs_utilisation(kbdev, &total_time, &busy_time); + + freq = clk_get_rate(kbdev->clock); + + rcu_read_lock(); + opp = dev_pm_opp_find_freq_floor(kbdev->dev, &freq); + if (IS_ERR_OR_NULL(opp)) { + rcu_read_unlock(); + return 0; + } + + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + rcu_read_unlock(); + + power = mali_actor->ops->get_dynamic_power(freq, voltage); + power = (power * busy_time) / total_time; + + temperature = zone->temperature; + + /* Assume all cores are always powered */ + power += mali_actor->ops->get_static_power(voltage, temperature); + + dev_dbg(kbdev->dev, "get req power = %lu\n", power); + + return (u32)power; +} + +static u32 mali_pa_get_max_power(struct power_actor *actor, struct thermal_zone_device *zone) +{ + struct mali_power_actor *mali_actor = actor->data; + struct kbase_device *kbdev = mali_actor->kbdev; + struct dev_pm_opp *opp; + unsigned long voltage, temperature; + unsigned long freq = ULONG_MAX; + u32 power; + + rcu_read_lock(); + opp = dev_pm_opp_find_freq_floor(kbdev->dev, &freq); + if (IS_ERR_OR_NULL(opp)) { + rcu_read_unlock(); + dev_err(kbdev->dev, "Failed to get OPP for max freq\n"); + return 0; + } + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + rcu_read_unlock(); + + temperature = zone->temperature; + + power = mali_actor->ops->get_static_power(voltage, temperature) + + mali_actor->ops->get_dynamic_power(freq, voltage); + + dev_dbg(kbdev->dev, "get max power = %u\n", power); + + return power; +} + +static int mali_pa_set_power(struct power_actor *actor, struct thermal_zone_device *zone, u32 power) +{ + struct mali_power_actor *mali_actor = actor->data; + struct kbase_device *kbdev = mali_actor->kbdev; + struct thermal_cooling_device *cdev; + unsigned long total_time, busy_time; + unsigned long freq, state; + unsigned long static_power, normalized_power; + unsigned long voltage, temperature; + struct dev_pm_opp *opp; + int err, i; + + dev_dbg(kbdev->dev, "Setting max power %u\n", power); + + kbase_pm_get_dvfs_utilisation(kbdev, &total_time, &busy_time); + + freq = clk_get_rate(kbdev->clock); + + rcu_read_lock(); + opp = dev_pm_opp_find_freq_exact(kbdev->dev, freq, true); + if (IS_ERR_OR_NULL(opp)) { + rcu_read_unlock(); + return -ENOENT; + } + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + rcu_read_unlock(); + + temperature = zone->temperature; + + static_power = mali_actor->ops->get_static_power(voltage, temperature); + + if (power < static_power) { + normalized_power = 0; + } else { + unsigned long dyn_power = power - static_power; + + if (!busy_time) + normalized_power = dyn_power; + else + normalized_power = (dyn_power * total_time) / busy_time; + } + + /* Find target frequency. Use the lowest OPP if allocated power is too + * low. */ + freq = mali_actor->dyn_table[0].freq; + for (i = 1; i < mali_actor->dyn_table_count; i++) { + if (mali_actor->dyn_table[i].power > normalized_power) + break; + else + freq = mali_actor->dyn_table[i].freq; + } + + state = devfreq_cooling_get_level(kbdev->devfreq, freq); + if (state == THERMAL_CSTATE_INVALID) { + dev_err(kbdev->dev, + "Failed to lookup cooling level for freq %ld\n", freq); + return -EINVAL; + } + + cdev = kbdev->devfreq_cooling->cdev; + err = cdev->ops->set_cur_state(cdev, state); + + dev_dbg(kbdev->dev, + "Max power set to %u using frequency %ld (cooling level %ld) (%d)\n", + power, freq, state, err); + + return err; +} + +static struct power_actor_ops mali_pa_ops = { + .get_req_power = mali_pa_get_req_power, + .get_max_power = mali_pa_get_max_power, + .set_power = mali_pa_set_power, +}; + +int mali_pa_init(struct kbase_device *kbdev) +{ + struct power_actor *actor; + struct mali_power_actor *mali_actor; + struct mali_pa_model_ops *callbacks; + struct mali_pa_power_table *table; + unsigned long freq; + int i, num_opps; + + callbacks = (void *)kbasep_get_config_value(kbdev, kbdev->config_attributes, + KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS); + if (!callbacks) + return -ENODEV; + + mali_actor = kzalloc(sizeof(*mali_actor), GFP_KERNEL); + if (!mali_actor) + return -ENOMEM; + + mali_actor->ops = callbacks; + mali_actor->kbdev = kbdev; + + rcu_read_lock(); + num_opps = dev_pm_opp_get_opp_count(kbdev->dev); + rcu_read_unlock(); + + table = kcalloc(num_opps, sizeof(table[0]), GFP_KERNEL); + if (!table) { + kfree(mali_actor); + return -ENOMEM; + } + + rcu_read_lock(); + for (i = 0, freq = 0; i < num_opps; i++, freq++) { + unsigned long power_static, power_dyn, voltage; + struct dev_pm_opp *opp; + + opp = dev_pm_opp_find_freq_ceil(kbdev->dev, &freq); + if (IS_ERR(opp)) + break; + + voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + + table[i].freq = freq; + + power_dyn = callbacks->get_dynamic_power(freq, voltage); + power_static = callbacks->get_static_power(voltage, 85000); + + dev_info(kbdev->dev, "Power table: %lu MHz @ %lu mV: %lu + %lu = %lu mW\n", + freq / 1000000, voltage, + power_dyn, power_static, power_dyn + power_static); + + table[i].power = power_dyn; + } + rcu_read_unlock(); + + if (i != num_opps) + dev_warn(kbdev->dev, "Power actor: Unable to enumerate all OPPs (%d != %d)\n", + i, num_opps); + + mali_actor->dyn_table = table; + mali_actor->dyn_table_count = i; + + /* Register power actor. + * Set default actor weight to 1 (8-bit fixed point). */ + actor = power_actor_register(1 * 256, &mali_pa_ops, mali_actor); + if (IS_ERR_OR_NULL(actor)) { + kfree(mali_actor->dyn_table); + kfree(mali_actor); + return PTR_ERR(actor); + } + + kbdev->power_actor = actor; + + dev_info(kbdev->dev, "Initalized power actor\n"); + + return 0; +} + +void mali_pa_term(struct kbase_device *kbdev) +{ + struct mali_power_actor *mali_actor; + + if (kbdev->power_actor) { + mali_actor = kbdev->power_actor->data; + + power_actor_unregister(kbdev->power_actor); + kbdev->power_actor = NULL; + + kfree(mali_actor->dyn_table); + kfree(mali_actor); + } +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.h new file mode 100644 index 0000000000000000000000000000000000000000..17f52e7718015f8de1e8bcfed048b5c35ace0a72 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_power_actor.h @@ -0,0 +1,58 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#ifndef _KBASE_POWER_ACTOR_H_ +#define _KBASE_POWER_ACTOR_H_ + +#include + +#include + +/** struct mali_pa_model_ops - Function pointer for power model + * + * @get_static_power: Pointer to a function that returns the estimated static + * power usage in mW, based on the input voltage in mV and + * temperature in millidegrees Celsius. + * @get_dynamic_power: Pointer to a function that returns the estimated dynamic power + * usage in mW, based on the input voltage in mV and + * frequency in Hz. + */ +struct mali_pa_model_ops { + unsigned long (*get_static_power)(unsigned long voltage, + unsigned long temperature); + unsigned long (*get_dynamic_power)(unsigned long freq, + unsigned long voltage); +}; + +struct mali_pa_power_table { + unsigned long freq; + unsigned long power; +}; + +struct mali_power_actor { + struct kbase_device *kbdev; + struct mali_pa_model_ops *ops; + struct mali_pa_power_table *dyn_table; + int dyn_table_count; +}; + +int mali_pa_init(struct kbase_device *kbdev); +void mali_pa_term(struct kbase_device *kbdev); + + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_profiling_gator_api.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_profiling_gator_api.h new file mode 100644 index 0000000000000000000000000000000000000000..6f9db71f7a0641c7ac84a9e75e588a8dfca0bac3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_profiling_gator_api.h @@ -0,0 +1,40 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_profiling_gator_api.h + * Model interface + */ + +#ifndef _KBASE_PROFILING_GATOR_API_H_ +#define _KBASE_PROFILING_GATOR_API_H_ + +/* + * List of possible actions to be controlled by Streamline. + * The following numbers are used by gator to control + * the frame buffer dumping and s/w counter reporting. + */ +#define FBDUMP_CONTROL_ENABLE (1) +#define FBDUMP_CONTROL_RATE (2) +#define SW_COUNTER_ENABLE (3) +#define FBDUMP_CONTROL_RESIZE_FACTOR (4) +#define FBDUMP_CONTROL_MAX (5) +#define FBDUMP_CONTROL_MIN FBDUMP_CONTROL_ENABLE + +void _mali_profiling_control(u32 action, u32 value); + +#endif /* _KBASE_PROFILING_GATOR_API */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_replay.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_replay.c new file mode 100644 index 0000000000000000000000000000000000000000..e47d865601c896614ee365a43adfde0e5436110b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_replay.c @@ -0,0 +1,1284 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @file mali_kbase_replay.c + * Replay soft job handlers + */ + +#include +#include +#include +#include + +#define JOB_NOT_STARTED 0 +#define JOB_TYPE_MASK 0xfe +#define JOB_TYPE_NULL (1 << 1) +#define JOB_TYPE_VERTEX (5 << 1) +#define JOB_TYPE_TILER (7 << 1) +#define JOB_TYPE_FUSED (8 << 1) +#define JOB_TYPE_FRAGMENT (9 << 1) + +#define JOB_FLAG_DESC_SIZE (1 << 0) +#define JOB_FLAG_PERFORM_JOB_BARRIER (1 << 8) + +#define JOB_HEADER_32_FBD_OFFSET (31*4) +#define JOB_HEADER_64_FBD_OFFSET (44*4) + +#define FBD_POINTER_MASK (~0x3f) + +#define SFBD_TILER_OFFSET (48*4) + +#define MFBD_TILER_OFFSET (14*4) + +#define FBD_HIERARCHY_WEIGHTS 8 +#define FBD_HIERARCHY_MASK_MASK 0x1fff + +#define FBD_TYPE 1 + +#define HIERARCHY_WEIGHTS 13 + +#define JOB_HEADER_ID_MAX 0xffff + +#define JOB_SOURCE_ID(status) (((status) >> 16) & 0xFFFF) +#define JOB_POLYGON_LIST (0x03) + +struct job_head { + u32 status; + u32 not_complete_index; + u64 fault_addr; + u16 flags; + u16 index; + u16 dependencies[2]; + union { + u64 _64; + u32 _32; + } next; + u32 x[2]; + union { + u64 _64; + u32 _32; + } fragment_fbd; +}; + +static void dump_job_head(struct kbase_context *kctx, char *head_str, + struct job_head *job) +{ +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "%s\n", head_str); + dev_dbg(kctx->kbdev->dev, "addr = %p\n" + "status = %x\n" + "not_complete_index = %x\n" + "fault_addr = %llx\n" + "flags = %x\n" + "index = %x\n" + "dependencies = %x,%x\n", + job, job->status, job->not_complete_index, + job->fault_addr, job->flags, job->index, + job->dependencies[0], + job->dependencies[1]); + + if (job->flags & JOB_FLAG_DESC_SIZE) + dev_dbg(kctx->kbdev->dev, "next = %llx\n", + job->next._64); + else + dev_dbg(kctx->kbdev->dev, "next = %x\n", + job->next._32); +#endif +} + +struct kbasep_map_struct { + mali_addr64 gpu_addr; + struct kbase_mem_phy_alloc *alloc; + struct page **pages; + void *addr; + size_t size; + mali_bool is_cached; +}; + +static void *kbasep_map(struct kbase_context *kctx, mali_addr64 gpu_addr, + size_t size, struct kbasep_map_struct *map) +{ + struct kbase_va_region *region; + unsigned long page_index; + unsigned int offset = gpu_addr & ~PAGE_MASK; + size_t page_count = PFN_UP(offset + size); + phys_addr_t *page_array; + struct page **pages; + void *cpu_addr = NULL; + pgprot_t prot; + size_t i; + + if (!size || !map) + return NULL; + + /* check if page_count calculation will wrap */ + if (size > ((size_t)-1 / PAGE_SIZE)) + return NULL; + + region = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); + if (!region || (region->flags & KBASE_REG_FREE)) + return NULL; + + page_index = (gpu_addr >> PAGE_SHIFT) - region->start_pfn; + + /* check if page_index + page_count will wrap */ + if (-1UL - page_count < page_index) + return NULL; + + if (page_index + page_count > kbase_reg_current_backed_size(region)) + return NULL; + + page_array = kbase_get_phy_pages(region); + if (!page_array) + return NULL; + + pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); + if (!pages) + return NULL; + + for (i = 0; i < page_count; i++) + pages[i] = pfn_to_page(PFN_DOWN(page_array[page_index + i])); + + prot = PAGE_KERNEL; + if (!(region->flags & KBASE_REG_CPU_CACHED)) { + /* Map uncached */ + prot = pgprot_writecombine(prot); + } + + cpu_addr = vmap(pages, page_count, VM_MAP, prot); + if (!cpu_addr) + goto vmap_failed; + + map->gpu_addr = gpu_addr; + map->alloc = kbase_mem_phy_alloc_get(region->alloc); + map->pages = pages; + map->addr = (void *)((uintptr_t)cpu_addr + offset); + map->size = size; + map->is_cached = (region->flags & KBASE_REG_CPU_CACHED) != 0; + + if (map->is_cached) { + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + phys_addr_t pa = page_to_phys(map->pages[0]) + offset; + + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_cpu); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + pa = page_to_phys(map->pages[i]); + kbase_sync_single(kctx, pa, PAGE_SIZE, + dma_sync_single_for_cpu); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + pa = page_to_phys(map->pages[page_count - 1]); + sz = ((offset + size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, pa, sz, + dma_sync_single_for_cpu); + } + } + + return map->addr; + +vmap_failed: + kfree(pages); + + return NULL; +} + +static void kbasep_unmap(struct kbase_context *kctx, + struct kbasep_map_struct *map) +{ + void *addr = (void *)((uintptr_t)map->addr & PAGE_MASK); + + vunmap(addr); + + if (map->is_cached) { + off_t offset = (uintptr_t)map->addr & ~PAGE_MASK; + size_t size = map->size; + size_t page_count = PFN_UP(offset + size); + size_t i; + + /* Sync first page */ + size_t sz = MIN(((size_t) PAGE_SIZE - offset), size); + phys_addr_t pa = page_to_phys(map->pages[0]) + offset; + + kbase_sync_single(kctx, pa, sz, dma_sync_single_for_device); + + /* Sync middle pages (if any) */ + for (i = 1; page_count > 2 && i < page_count - 1; i++) { + pa = page_to_phys(map->pages[i]); + kbase_sync_single(kctx, pa, PAGE_SIZE, + dma_sync_single_for_device); + } + + /* Sync last page (if any) */ + if (page_count > 1) { + pa = page_to_phys(map->pages[page_count - 1]); + sz = ((offset + size - 1) & ~PAGE_MASK) + 1; + kbase_sync_single(kctx, pa, sz, + dma_sync_single_for_device); + } + } + + kfree(map->pages); + + map->gpu_addr = 0; + map->alloc = kbase_mem_phy_alloc_put(map->alloc); + map->pages = NULL; + map->addr = NULL; + map->size = 0; + map->is_cached = MALI_FALSE; +} + +static mali_error kbasep_replay_reset_sfbd(struct kbase_context *kctx, + mali_addr64 fbd_address, mali_addr64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight) +{ + struct { + u32 padding_1[1]; + u32 flags; + u64 padding_2[2]; + u64 heap_free_address; + u32 padding[8]; + u32 weights[FBD_HIERARCHY_WEIGHTS]; + } *fbd_tiler; + struct kbasep_map_struct map; + + dev_dbg(kctx->kbdev->dev, "fbd_address: %llx\n", fbd_address); + + fbd_tiler = kbasep_map(kctx, fbd_address + SFBD_TILER_OFFSET, + sizeof(*fbd_tiler), &map); + if (!fbd_tiler) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_fbd: failed to map fbd\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, + "FBD tiler:\n" + "flags = %x\n" + "heap_free_address = %llx\n", + fbd_tiler->flags, fbd_tiler->heap_free_address); +#endif + if (hierarchy_mask) { + u32 weights[HIERARCHY_WEIGHTS]; + u16 old_hierarchy_mask = fbd_tiler->flags & + FBD_HIERARCHY_MASK_MASK; + int i, j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (old_hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + weights[i] = fbd_tiler->weights[j++]; + } else { + weights[i] = default_weight; + } + } + + + dev_dbg(kctx->kbdev->dev, "Old hierarchy mask=%x New hierarchy mask=%x\n", + old_hierarchy_mask, hierarchy_mask); + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) + dev_dbg(kctx->kbdev->dev, " Hierarchy weight %02d: %08x\n", + i, weights[i]); + + j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + + dev_dbg(kctx->kbdev->dev, " Writing hierarchy level %02d (%08x) to %d\n", + i, weights[i], j); + + fbd_tiler->weights[j++] = weights[i]; + } + } + + for (; j < FBD_HIERARCHY_WEIGHTS; j++) + fbd_tiler->weights[j] = 0; + + fbd_tiler->flags = hierarchy_mask | (1 << 16); + } + + fbd_tiler->heap_free_address = tiler_heap_free; + + dev_dbg(kctx->kbdev->dev, "heap_free_address=%llx flags=%x\n", + fbd_tiler->heap_free_address, fbd_tiler->flags); + + kbasep_unmap(kctx, &map); + + return MALI_ERROR_NONE; +} + +static mali_error kbasep_replay_reset_mfbd(struct kbase_context *kctx, + mali_addr64 fbd_address, mali_addr64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight) +{ + struct kbasep_map_struct map; + struct { + u32 padding_0; + u32 flags; + u64 padding_1[2]; + u64 heap_free_address; + u64 padding_2; + u32 weights[FBD_HIERARCHY_WEIGHTS]; + } *fbd_tiler; + + dev_dbg(kctx->kbdev->dev, "fbd_address: %llx\n", fbd_address); + + fbd_tiler = kbasep_map(kctx, fbd_address + MFBD_TILER_OFFSET, + sizeof(*fbd_tiler), &map); + if (!fbd_tiler) { + dev_err(kctx->kbdev->dev, + "kbasep_replay_reset_fbd: failed to map fbd\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "FBD tiler:\n" + "flags = %x\n" + "heap_free_address = %llx\n", + fbd_tiler->flags, + fbd_tiler->heap_free_address); +#endif + if (hierarchy_mask) { + u32 weights[HIERARCHY_WEIGHTS]; + u16 old_hierarchy_mask = (fbd_tiler->flags) & + FBD_HIERARCHY_MASK_MASK; + int i, j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (old_hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + weights[i] = fbd_tiler->weights[j++]; + } else { + weights[i] = default_weight; + } + } + + + dev_dbg(kctx->kbdev->dev, "Old hierarchy mask=%x New hierarchy mask=%x\n", + old_hierarchy_mask, hierarchy_mask); + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) + dev_dbg(kctx->kbdev->dev, " Hierarchy weight %02d: %08x\n", + i, weights[i]); + + j = 0; + + for (i = 0; i < HIERARCHY_WEIGHTS; i++) { + if (hierarchy_mask & (1 << i)) { + KBASE_DEBUG_ASSERT(j < FBD_HIERARCHY_WEIGHTS); + + dev_dbg(kctx->kbdev->dev, + " Writing hierarchy level %02d (%08x) to %d\n", + i, weights[i], j); + + fbd_tiler->weights[j++] = weights[i]; + } + } + + for (; j < FBD_HIERARCHY_WEIGHTS; j++) + fbd_tiler->weights[j] = 0; + + fbd_tiler->flags = hierarchy_mask | (1 << 16); + } + + fbd_tiler->heap_free_address = tiler_heap_free; + + kbasep_unmap(kctx, &map); + + return MALI_ERROR_NONE; +} + +/** + * @brief Reset the status of an FBD pointed to by a tiler job + * + * This performs two functions : + * - Set the hierarchy mask + * - Reset the tiler free heap address + * + * @param[in] kctx Context pointer + * @param[in] job_header Address of job header to reset. + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] job_64 MALI_TRUE if this job is using 64-bit + * descriptors + * + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_reset_tiler_job(struct kbase_context *kctx, + mali_addr64 job_header, mali_addr64 tiler_heap_free, + u16 hierarchy_mask, u32 default_weight, mali_bool job_64) +{ + struct kbasep_map_struct map; + mali_addr64 fbd_address; + + if (job_64) { + u64 *job_ext; + + job_ext = kbasep_map(kctx, + job_header + JOB_HEADER_64_FBD_OFFSET, + sizeof(*job_ext), &map); + + if (!job_ext) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_tiler_job: failed to map jc\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + fbd_address = *job_ext; + + kbasep_unmap(kctx, &map); + } else { + u32 *job_ext; + + job_ext = kbasep_map(kctx, + job_header + JOB_HEADER_32_FBD_OFFSET, + sizeof(*job_ext), &map); + + if (!job_ext) { + dev_err(kctx->kbdev->dev, "kbasep_replay_reset_tiler_job: failed to map jc\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + fbd_address = *job_ext; + + kbasep_unmap(kctx, &map); + } + + if (fbd_address & FBD_TYPE) { + return kbasep_replay_reset_mfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight); + } else { + return kbasep_replay_reset_sfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight); + } +} + +/** + * @brief Reset the status of a job + * + * This performs the following functions : + * + * - Reset the Job Status field of each job to NOT_STARTED. + * - Set the Job Type field of any Vertex Jobs to Null Job. + * - For any jobs using an FBD, set the Tiler Heap Free field to the value of + * the tiler_heap_free parameter, and set the hierarchy level mask to the + * hier_mask parameter. + * - Offset HW dependencies by the hw_job_id_offset parameter + * - Set the Perform Job Barrier flag if this job is the first in the chain + * - Read the address of the next job header + * + * @param[in] kctx Context pointer + * @param[in,out] job_header Address of job header to reset. Set to address + * of next job header on exit. + * @param[in] prev_jc Previous job chain to link to, if this job is + * the last in the chain. + * @param[in] hw_job_id_offset Offset for HW job IDs + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] first_in_chain MALI_TRUE if this job is the first in the chain + * @param[in] fragment_chain MALI_TRUE if this job is in the fragment chain + * + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_reset_job(struct kbase_context *kctx, + mali_addr64 *job_header, mali_addr64 prev_jc, + mali_addr64 tiler_heap_free, u16 hierarchy_mask, + u32 default_weight, u16 hw_job_id_offset, + mali_bool first_in_chain, mali_bool fragment_chain) +{ + struct job_head *job; + mali_addr64 new_job_header; + struct kbasep_map_struct map; + + job = kbasep_map(kctx, *job_header, sizeof(*job), &map); + if (!job) { + dev_err(kctx->kbdev->dev, + "kbasep_replay_parse_jc: failed to map jc\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + dump_job_head(kctx, "Job header:", job); + + if (job->status == JOB_NOT_STARTED && !fragment_chain) { + dev_err(kctx->kbdev->dev, "Job already not started\n"); + goto out_unmap; + } + job->status = JOB_NOT_STARTED; + + if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_VERTEX) + job->flags = (job->flags & ~JOB_TYPE_MASK) | JOB_TYPE_NULL; + + if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_FUSED) { + dev_err(kctx->kbdev->dev, "Fused jobs can not be replayed\n"); + goto out_unmap; + } + + if (first_in_chain) + job->flags |= JOB_FLAG_PERFORM_JOB_BARRIER; + + if ((job->dependencies[0] + hw_job_id_offset) > JOB_HEADER_ID_MAX || + (job->dependencies[1] + hw_job_id_offset) > JOB_HEADER_ID_MAX || + (job->index + hw_job_id_offset) > JOB_HEADER_ID_MAX) { + dev_err(kctx->kbdev->dev, + "Job indicies/dependencies out of valid range\n"); + goto out_unmap; + } + + if (job->dependencies[0]) + job->dependencies[0] += hw_job_id_offset; + if (job->dependencies[1]) + job->dependencies[1] += hw_job_id_offset; + + job->index += hw_job_id_offset; + + if (job->flags & JOB_FLAG_DESC_SIZE) { + new_job_header = job->next._64; + if (!job->next._64) + job->next._64 = prev_jc; + } else { + new_job_header = job->next._32; + if (!job->next._32) + job->next._32 = prev_jc; + } + dump_job_head(kctx, "Updated to:", job); + + if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_TILER) { + mali_bool job_64 = (job->flags & JOB_FLAG_DESC_SIZE) != 0; + + if (kbasep_replay_reset_tiler_job(kctx, *job_header, + tiler_heap_free, hierarchy_mask, + default_weight, job_64) != MALI_ERROR_NONE) + goto out_unmap; + + } else if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_FRAGMENT) { + u64 fbd_address; + + if (job->flags & JOB_FLAG_DESC_SIZE) + fbd_address = job->fragment_fbd._64; + else + fbd_address = (u64)job->fragment_fbd._32; + + if (fbd_address & FBD_TYPE) { + if (kbasep_replay_reset_mfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight) != MALI_ERROR_NONE) + goto out_unmap; + } else { + if (kbasep_replay_reset_sfbd(kctx, + fbd_address & FBD_POINTER_MASK, + tiler_heap_free, + hierarchy_mask, + default_weight) != MALI_ERROR_NONE) + goto out_unmap; + } + } + + kbasep_unmap(kctx, &map); + + *job_header = new_job_header; + + return MALI_ERROR_NONE; + +out_unmap: + kbasep_unmap(kctx, &map); + return MALI_ERROR_FUNCTION_FAILED; +} + +/** + * @brief Find the highest job ID in a job chain + * + * @param[in] kctx Context pointer + * @param[in] jc Job chain start address + * @param[out] hw_job_id Highest job ID in chain + * + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_find_hw_job_id(struct kbase_context *kctx, + mali_addr64 jc, u16 *hw_job_id) +{ + while (jc) { + struct job_head *job; + struct kbasep_map_struct map; + + dev_dbg(kctx->kbdev->dev, + "kbasep_replay_find_hw_job_id: parsing jc=%llx\n", jc); + + job = kbasep_map(kctx, jc, sizeof(*job), &map); + if (!job) { + dev_err(kctx->kbdev->dev, "failed to map jc\n"); + + return MALI_ERROR_FUNCTION_FAILED; + } + + if (job->index > *hw_job_id) + *hw_job_id = job->index; + + if (job->flags & JOB_FLAG_DESC_SIZE) + jc = job->next._64; + else + jc = job->next._32; + + kbasep_unmap(kctx, &map); + } + + return MALI_ERROR_NONE; +} + +/** + * @brief Reset the status of a number of jobs + * + * This function walks the provided job chain, and calls + * kbasep_replay_reset_job for each job. It also links the job chain to the + * provided previous job chain. + * + * The function will fail if any of the jobs passed already have status of + * NOT_STARTED. + * + * @param[in] kctx Context pointer + * @param[in] jc Job chain to be processed + * @param[in] prev_jc Job chain to be added to. May be NULL + * @param[in] tiler_heap_free The value to reset Tiler Heap Free to + * @param[in] hierarchy_mask The hierarchy mask to use + * @param[in] default_weight Default hierarchy weight to write when no other + * weight is given in the FBD + * @param[in] hw_job_id_offset Offset for HW job IDs + * @param[in] fragment_chain MAIL_TRUE if this chain is the fragment chain + * + * @return MALI_ERROR_NONE on success, error code otherwise + */ +static mali_error kbasep_replay_parse_jc(struct kbase_context *kctx, + mali_addr64 jc, mali_addr64 prev_jc, + mali_addr64 tiler_heap_free, u16 hierarchy_mask, + u32 default_weight, u16 hw_job_id_offset, + mali_bool fragment_chain) +{ + mali_bool first_in_chain = MALI_TRUE; + int nr_jobs = 0; + + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_jc: jc=%llx hw_job_id=%x\n", + jc, hw_job_id_offset); + + while (jc) { + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_jc: parsing jc=%llx\n", jc); + + if (kbasep_replay_reset_job(kctx, &jc, prev_jc, + tiler_heap_free, hierarchy_mask, + default_weight, hw_job_id_offset, + first_in_chain, fragment_chain) != MALI_ERROR_NONE) + return MALI_ERROR_FUNCTION_FAILED; + + first_in_chain = MALI_FALSE; + + nr_jobs++; + if (fragment_chain && + nr_jobs >= BASE_JD_REPLAY_F_CHAIN_JOB_LIMIT) { + dev_err(kctx->kbdev->dev, + "Exceeded maximum number of jobs in fragment chain\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + } + + return MALI_ERROR_NONE; +} + +/** + * @brief Reset the status of a replay job, and set up dependencies + * + * This performs the actions to allow the replay job to be re-run following + * completion of the passed dependency. + * + * @param[in] katom The atom to be reset + * @param[in] dep_atom The dependency to be attached to the atom + */ +static void kbasep_replay_reset_softjob(struct kbase_jd_atom *katom, + struct kbase_jd_atom *dep_atom) +{ + katom->status = KBASE_JD_ATOM_STATE_QUEUED; + kbase_jd_katom_dep_set(&katom->dep[0], dep_atom, BASE_JD_DEP_TYPE_DATA); + list_add_tail(&katom->dep_item[0], &dep_atom->dep_head[0]); +} + +/** + * @brief Allocate an unused katom + * + * This will search the provided context for an unused katom, and will mark it + * as KBASE_JD_ATOM_STATE_QUEUED. + * + * If no atoms are available then the function will fail. + * + * @param[in] kctx Context pointer + * @return An atom ID, or -1 on failure + */ +static int kbasep_allocate_katom(struct kbase_context *kctx) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + int i; + + for (i = BASE_JD_ATOM_COUNT-1; i > 0; i--) { + if (jctx->atoms[i].status == KBASE_JD_ATOM_STATE_UNUSED) { + jctx->atoms[i].status = KBASE_JD_ATOM_STATE_QUEUED; + dev_dbg(kctx->kbdev->dev, + "kbasep_allocate_katom: Allocated atom %d\n", + i); + return i; + } + } + + return -1; +} + +/** + * @brief Release a katom + * + * This will mark the provided atom as available, and remove any dependencies. + * + * For use on error path. + * + * @param[in] kctx Context pointer + * @param[in] atom_id ID of atom to release + */ +static void kbasep_release_katom(struct kbase_context *kctx, int atom_id) +{ + struct kbase_jd_context *jctx = &kctx->jctx; + + dev_dbg(kctx->kbdev->dev, "kbasep_release_katom: Released atom %d\n", + atom_id); + + while (!list_empty(&jctx->atoms[atom_id].dep_head[0])) + list_del(jctx->atoms[atom_id].dep_head[0].next); + + while (!list_empty(&jctx->atoms[atom_id].dep_head[1])) + list_del(jctx->atoms[atom_id].dep_head[1].next); + + jctx->atoms[atom_id].status = KBASE_JD_ATOM_STATE_UNUSED; +} + +static void kbasep_replay_create_atom(struct kbase_context *kctx, + struct base_jd_atom_v2 *atom, + int atom_nr, + int prio) +{ + atom->nr_extres = 0; + atom->extres_list.value = NULL; + atom->device_nr = 0; + /* Convert priority back from NICE range */ + atom->prio = ((prio << 16) / ((20 << 16) / 128)) - 128; + atom->atom_number = atom_nr; + + base_jd_atom_dep_set(&atom->pre_dep[0], 0 , BASE_JD_DEP_TYPE_INVALID); + base_jd_atom_dep_set(&atom->pre_dep[1], 0 , BASE_JD_DEP_TYPE_INVALID); + + atom->udata.blob[0] = 0; + atom->udata.blob[1] = 0; +} + +/** + * @brief Create two atoms for the purpose of replaying jobs + * + * Two atoms are allocated and created. The jc pointer is not set at this + * stage. The second atom has a dependency on the first. The remaining fields + * are set up as follows : + * + * - No external resources. Any required external resources will be held by the + * replay atom. + * - device_nr is set to 0. This is not relevant as + * BASE_JD_REQ_SPECIFIC_COHERENT_GROUP should not be set. + * - Priority is inherited from the replay job. + * + * @param[out] t_atom Atom to use for tiler jobs + * @param[out] f_atom Atom to use for fragment jobs + * @param[in] prio Priority of new atom (inherited from replay soft + * job) + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_create_atoms(struct kbase_context *kctx, + struct base_jd_atom_v2 *t_atom, + struct base_jd_atom_v2 *f_atom, int prio) +{ + int t_atom_nr, f_atom_nr; + + t_atom_nr = kbasep_allocate_katom(kctx); + if (t_atom_nr < 0) { + dev_err(kctx->kbdev->dev, "Failed to allocate katom\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + + f_atom_nr = kbasep_allocate_katom(kctx); + if (f_atom_nr < 0) { + dev_err(kctx->kbdev->dev, "Failed to allocate katom\n"); + kbasep_release_katom(kctx, t_atom_nr); + return MALI_ERROR_FUNCTION_FAILED; + } + + kbasep_replay_create_atom(kctx, t_atom, t_atom_nr, prio); + kbasep_replay_create_atom(kctx, f_atom, f_atom_nr, prio); + + base_jd_atom_dep_set(&f_atom->pre_dep[0], t_atom_nr , BASE_JD_DEP_TYPE_DATA); + + return MALI_ERROR_NONE; +} + +#ifdef CONFIG_MALI_DEBUG +static void payload_dump(struct kbase_context *kctx, base_jd_replay_payload *payload) +{ + mali_addr64 next; + + dev_dbg(kctx->kbdev->dev, "Tiler jc list :\n"); + next = payload->tiler_jc_list; + + while (next) { + struct kbasep_map_struct map; + base_jd_replay_jc *jc_struct; + + jc_struct = kbasep_map(kctx, next, sizeof(*jc_struct), &map); + + if (!jc_struct) + return; + + dev_dbg(kctx->kbdev->dev, "* jc_struct=%p jc=%llx next=%llx\n", + jc_struct, jc_struct->jc, jc_struct->next); + + next = jc_struct->next; + + kbasep_unmap(kctx, &map); + } +} +#endif + +/** + * @brief Parse a base_jd_replay_payload provided by userspace + * + * This will read the payload from userspace, and parse the job chains. + * + * @param[in] kctx Context pointer + * @param[in] replay_atom Replay soft job atom + * @param[in] t_atom Atom to use for tiler jobs + * @param[in] f_atom Atom to use for fragment jobs + * @return MALI_ERROR_NONE on success, error code on failure + */ +static mali_error kbasep_replay_parse_payload(struct kbase_context *kctx, + struct kbase_jd_atom *replay_atom, + struct base_jd_atom_v2 *t_atom, + struct base_jd_atom_v2 *f_atom) +{ + base_jd_replay_payload *payload; + mali_addr64 next; + mali_addr64 prev_jc = 0; + u16 hw_job_id_offset = 0; + mali_error ret = MALI_ERROR_FUNCTION_FAILED; + struct kbasep_map_struct map; + + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_payload: replay_atom->jc = %llx sizeof(payload) = %zu\n", + replay_atom->jc, sizeof(payload)); + + kbase_gpu_vm_lock(kctx); + + payload = kbasep_map(kctx, replay_atom->jc, sizeof(*payload), &map); + + if (!payload) { + kbase_gpu_vm_unlock(kctx); + dev_err(kctx->kbdev->dev, "kbasep_replay_parse_payload: failed to map payload into kernel space\n"); + return MALI_ERROR_FUNCTION_FAILED; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_payload: payload=%p\n", payload); + dev_dbg(kctx->kbdev->dev, "Payload structure:\n" + "tiler_jc_list = %llx\n" + "fragment_jc = %llx\n" + "tiler_heap_free = %llx\n" + "fragment_hierarchy_mask = %x\n" + "tiler_hierarchy_mask = %x\n" + "hierarchy_default_weight = %x\n" + "tiler_core_req = %x\n" + "fragment_core_req = %x\n", + payload->tiler_jc_list, + payload->fragment_jc, + payload->tiler_heap_free, + payload->fragment_hierarchy_mask, + payload->tiler_hierarchy_mask, + payload->hierarchy_default_weight, + payload->tiler_core_req, + payload->fragment_core_req); + payload_dump(kctx, payload); +#endif + + t_atom->core_req = payload->tiler_core_req | BASEP_JD_REQ_EVENT_NEVER; + f_atom->core_req = payload->fragment_core_req | BASEP_JD_REQ_EVENT_NEVER; + + /* Sanity check core requirements*/ + if ((t_atom->core_req & BASEP_JD_REQ_ATOM_TYPE & + ~BASE_JD_REQ_COHERENT_GROUP) != BASE_JD_REQ_T || + (f_atom->core_req & BASEP_JD_REQ_ATOM_TYPE & + ~BASE_JD_REQ_COHERENT_GROUP) != BASE_JD_REQ_FS || + t_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES || + f_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { + dev_err(kctx->kbdev->dev, "Invalid core requirements\n"); + goto out; + } + + /* Process tiler job chains */ + next = payload->tiler_jc_list; + if (!next) { + dev_err(kctx->kbdev->dev, "Invalid tiler JC list\n"); + goto out; + } + + while (next) { + base_jd_replay_jc *jc_struct; + struct kbasep_map_struct jc_map; + mali_addr64 jc; + + jc_struct = kbasep_map(kctx, next, sizeof(*jc_struct), &jc_map); + + if (!jc_struct) { + dev_err(kctx->kbdev->dev, "Failed to map jc struct\n"); + goto out; + } + + jc = jc_struct->jc; + next = jc_struct->next; + if (next) + jc_struct->jc = 0; + + kbasep_unmap(kctx, &jc_map); + + if (jc) { + u16 max_hw_job_id = 0; + + if (kbasep_replay_find_hw_job_id(kctx, jc, + &max_hw_job_id) != MALI_ERROR_NONE) + goto out; + + if (kbasep_replay_parse_jc(kctx, jc, prev_jc, + payload->tiler_heap_free, + payload->tiler_hierarchy_mask, + payload->hierarchy_default_weight, + hw_job_id_offset, MALI_FALSE) != + MALI_ERROR_NONE) { + goto out; + } + + hw_job_id_offset += max_hw_job_id; + + prev_jc = jc; + } + } + t_atom->jc = prev_jc; + + /* Process fragment job chain */ + f_atom->jc = payload->fragment_jc; + if (kbasep_replay_parse_jc(kctx, payload->fragment_jc, 0, + payload->tiler_heap_free, + payload->fragment_hierarchy_mask, + payload->hierarchy_default_weight, 0, + MALI_TRUE) != MALI_ERROR_NONE) { + goto out; + } + + if (!t_atom->jc || !f_atom->jc) { + dev_err(kctx->kbdev->dev, "Invalid payload\n"); + goto out; + } + + dev_dbg(kctx->kbdev->dev, "t_atom->jc=%llx f_atom->jc=%llx\n", + t_atom->jc, f_atom->jc); + ret = MALI_ERROR_NONE; + +out: + kbasep_unmap(kctx, &map); + + kbase_gpu_vm_unlock(kctx); + + return ret; +} + +static void kbase_replay_process_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom; + struct kbase_context *kctx; + struct kbase_jd_context *jctx; + bool need_to_try_schedule_context = false; + + struct base_jd_atom_v2 t_atom, f_atom; + struct kbase_jd_atom *t_katom, *f_katom; + + katom = container_of(data, struct kbase_jd_atom, work); + kctx = katom->kctx; + jctx = &kctx->jctx; + + mutex_lock(&jctx->lock); + + if (kbasep_replay_create_atoms(kctx, &t_atom, &f_atom, + katom->nice_prio) != MALI_ERROR_NONE) { + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + t_katom = &jctx->atoms[t_atom.atom_number]; + f_katom = &jctx->atoms[f_atom.atom_number]; + + if (kbasep_replay_parse_payload(kctx, katom, &t_atom, &f_atom) != + MALI_ERROR_NONE) { + kbasep_release_katom(kctx, t_atom.atom_number); + kbasep_release_katom(kctx, f_atom.atom_number); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + kbasep_replay_reset_softjob(katom, f_katom); + + need_to_try_schedule_context |= jd_submit_atom(kctx, &t_atom, t_katom); + if (t_katom->event_code == BASE_JD_EVENT_JOB_INVALID) { + dev_err(kctx->kbdev->dev, "Replay failed to submit atom\n"); + kbasep_release_katom(kctx, f_atom.atom_number); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + need_to_try_schedule_context |= jd_submit_atom(kctx, &f_atom, f_katom); + if (f_katom->event_code == BASE_JD_EVENT_JOB_INVALID) { + dev_err(kctx->kbdev->dev, "Replay failed to submit atom\n"); + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + goto out; + } + + katom->event_code = BASE_JD_EVENT_DONE; + +out: + if (katom->event_code != BASE_JD_EVENT_DONE) + need_to_try_schedule_context |= jd_done_nolock(katom); + + if (need_to_try_schedule_context) + kbasep_js_try_schedule_head_ctx(kctx->kbdev); + mutex_unlock(&jctx->lock); +} + +/** + * @brief Check job replay fault + * + * This will read the job payload, checks fault type and source, then decides + * whether replay is required. + * + * @param[in] katom The atom to be processed + * @return true (success) if replay required or false on failure. + */ +static bool kbase_replay_fault_check(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct device *dev = kctx->kbdev->dev; + base_jd_replay_payload *payload; + mali_addr64 job_header; + mali_addr64 job_loop_detect; + struct job_head *job; + struct kbasep_map_struct job_map; + struct kbasep_map_struct map; + bool err = false; + + /* Replay job if fault is of type BASE_JD_EVENT_JOB_WRITE_FAULT or + * if force_replay is enabled. + */ + if (BASE_JD_EVENT_TERMINATED == katom->event_code) { + return false; + } else if (BASE_JD_EVENT_JOB_WRITE_FAULT == katom->event_code) { + return true; + } else if (BASE_JD_EVENT_FORCE_REPLAY == katom->event_code) { + katom->event_code = BASE_JD_EVENT_DATA_INVALID_FAULT; + return true; + } else if (BASE_JD_EVENT_DATA_INVALID_FAULT != katom->event_code) { + /* No replay for faults of type other than + * BASE_JD_EVENT_DATA_INVALID_FAULT. + */ + return false; + } + + /* Job fault is BASE_JD_EVENT_DATA_INVALID_FAULT, now scan fragment jc + * to find out whether the source of exception is POLYGON_LIST. Replay + * is required if the source of fault is POLYGON_LIST. + */ + kbase_gpu_vm_lock(kctx); + + payload = kbasep_map(kctx, katom->jc, sizeof(*payload), &map); + if (!payload) { + kbase_gpu_vm_unlock(kctx); + dev_err(dev, "kbase_replay_fault_check: failed to map payload.\n"); + return false; + } + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(dev, "kbase_replay_fault_check: payload=%p\n", payload); + dev_dbg(dev, "\nPayload structure:\n" + "fragment_jc = 0x%llx\n" + "fragment_hierarchy_mask = 0x%x\n" + "fragment_core_req = 0x%x\n", + payload->fragment_jc, + payload->fragment_hierarchy_mask, + payload->fragment_core_req); +#endif + /* Process fragment job chain */ + job_header = (mali_addr64) payload->fragment_jc; + job_loop_detect = job_header; + while (job_header) { + job = kbasep_map(kctx, job_header, sizeof(*job), &job_map); + if (!job) { + dev_err(dev, "failed to map jc\n"); + /* unmap payload*/ + kbasep_unmap(kctx, &map); + kbase_gpu_vm_unlock(kctx); + return false; + } + + +#ifdef CONFIG_MALI_DEBUG + dev_dbg(dev, "\njob_head structure:\n" + "Source ID:0x%x Access:0x%x Exception:0x%x\n" + "at job addr = %p\n" + "not_complete_index = 0x%x\n" + "fault_addr = 0x%llx\n" + "flags = 0x%x\n" + "index = 0x%x\n" + "dependencies = 0x%x,0x%x\n", + JOB_SOURCE_ID(job->status), + ((job->status >> 8) & 0x3), + (job->status & 0xFF), + job, + job->not_complete_index, + job->fault_addr, + job->flags, + job->index, + job->dependencies[0], + job->dependencies[1]); +#endif + + /* Replay only when the polygon list reader caused the + * DATA_INVALID_FAULT */ + if ((BASE_JD_EVENT_DATA_INVALID_FAULT == katom->event_code) && + (JOB_POLYGON_LIST == JOB_SOURCE_ID(job->status))) { + err = true; + kbasep_unmap(kctx, &job_map); + break; + } + + /* Move on to next fragment job in the list */ + if (job->flags & JOB_FLAG_DESC_SIZE) + job_header = job->next._64; + else + job_header = job->next._32; + + kbasep_unmap(kctx, &job_map); + + /* Job chain loop detected */ + if (job_header == job_loop_detect) + break; + } + + /* unmap payload*/ + kbasep_unmap(kctx, &map); + kbase_gpu_vm_unlock(kctx); + + return err; +} + + +/** + * @brief Process a replay job + * + * Called from kbase_process_soft_job. + * + * On exit, if the job has completed, katom->event_code will have been updated. + * If the job has not completed, and is replaying jobs, then the atom status + * will have been reset to KBASE_JD_ATOM_STATE_QUEUED. + * + * @param[in] katom The atom to be processed + * @return false if the atom has completed + * true if the atom is replaying jobs + */ +bool kbase_replay_process(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + struct kbase_jd_context *jctx = &kctx->jctx; + + if (katom->event_code == BASE_JD_EVENT_DONE) { + dev_dbg(kctx->kbdev->dev, "Previous job succeeded - not replaying\n"); + + if (katom->retry_count) + kbase_disjoint_state_down(kctx->kbdev); + + return false; + } + + if (jctx->sched_info.ctx.is_dying) { + dev_dbg(kctx->kbdev->dev, "Not replaying; context is dying\n"); + + if (katom->retry_count) + kbase_disjoint_state_down(kctx->kbdev); + + return false; + } + + /* Check job exception type and source before replaying. */ + if (false == kbase_replay_fault_check(katom)) { + dev_dbg(kctx->kbdev->dev, + "Replay cancelled on event %x\n", katom->event_code); + /* katom->event_code is already set to the failure code of the + * previous job. + */ + return false; + } + + dev_warn(kctx->kbdev->dev, "Replaying jobs retry=%d\n", + katom->retry_count); + + katom->retry_count++; + + if (katom->retry_count > BASEP_JD_REPLAY_LIMIT) { + dev_err(kctx->kbdev->dev, "Replay exceeded limit - failing jobs\n"); + + kbase_disjoint_state_down(kctx->kbdev); + + /* katom->event_code is already set to the failure code of the + previous job */ + return false; + } + + /* only enter the disjoint state once for the whole time while the replay is ongoing */ + if (katom->retry_count == 1) + kbase_disjoint_state_up(kctx->kbdev); + + INIT_WORK(&katom->work, kbase_replay_process_worker); + queue_work(kctx->event_workq, &katom->work); + + return true; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_security.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_security.c new file mode 100644 index 0000000000000000000000000000000000000000..e7916374ffefc8dc28a76a42a6e5d4d6ded57e46 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_security.c @@ -0,0 +1,78 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_security.c + * Base kernel security capability API + */ + +#include + +static inline mali_bool kbasep_am_i_root(void) +{ +#if KBASE_HWCNT_DUMP_BYPASS_ROOT + return MALI_TRUE; +#else + /* Check if root */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + if (uid_eq(current_euid(), GLOBAL_ROOT_UID)) + return MALI_TRUE; +#else + if (current_euid() == 0) + return MALI_TRUE; +#endif /*LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)*/ + return MALI_FALSE; +#endif /*KBASE_HWCNT_DUMP_BYPASS_ROOT*/ +} + +/** + * kbase_security_has_capability - see mali_kbase_caps.h for description. + */ + +mali_bool kbase_security_has_capability(struct kbase_context *kctx, enum kbase_security_capability cap, u32 flags) +{ + /* Assume failure */ + mali_bool access_allowed = MALI_FALSE; + mali_bool audit = (KBASE_SEC_FLAG_AUDIT & flags) ? MALI_TRUE : MALI_FALSE; + + KBASE_DEBUG_ASSERT(NULL != kctx); + CSTD_UNUSED(kctx); + + /* Detect unsupported flags */ + KBASE_DEBUG_ASSERT(((~KBASE_SEC_FLAG_MASK) & flags) == 0); + + /* Determine if access is allowed for the given cap */ + switch (cap) { + case KBASE_SEC_MODIFY_PRIORITY: + case KBASE_SEC_INSTR_HW_COUNTERS_COLLECT: + /* Access is granted only if the caller is privileged */ + access_allowed = kbasep_am_i_root(); + break; + } + + /* Report problem if requested */ + if (MALI_FALSE == access_allowed) { + if (MALI_FALSE != audit) + dev_warn(kctx->kbdev->dev, "Security capability failure: %d, %p", cap, (void *)kctx); + } + + return access_allowed; +} + +KBASE_EXPORT_TEST_API(kbase_security_has_capability) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_security.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_security.h new file mode 100644 index 0000000000000000000000000000000000000000..c8d4e53ae3b0b03ce648e7fbed70a5933231b7a6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_security.h @@ -0,0 +1,52 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_security.h + * Base kernel security capability APIs + */ + +#ifndef _KBASE_SECURITY_H_ +#define _KBASE_SECURITY_H_ + +/* Security flags */ +#define KBASE_SEC_FLAG_NOAUDIT (0u << 0) /* Silently handle privilege failure */ +#define KBASE_SEC_FLAG_AUDIT (1u << 0) /* Write audit message on privilege failure */ +#define KBASE_SEC_FLAG_MASK (KBASE_SEC_FLAG_AUDIT) /* Mask of all valid flag bits */ + +/* List of unique capabilities that have security access privileges */ +enum kbase_security_capability { + /* Instrumentation Counters access privilege */ + KBASE_SEC_INSTR_HW_COUNTERS_COLLECT = 1, + KBASE_SEC_MODIFY_PRIORITY + /* Add additional access privileges here */ +}; + +/** + * kbase_security_has_capability - determine whether a task has a particular effective capability + * @param[in] kctx The task context. + * @param[in] cap The capability to check for. + * @param[in] flags Additional configuration information + * Such as whether to write an audit message or not. + * @return MALI_TRUE if success (capability is allowed), MALI_FALSE otherwise. + */ + +mali_bool kbase_security_has_capability(struct kbase_context *kctx, enum kbase_security_capability cap, u32 flags); + +#endif /* _KBASE_SECURITY_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_softjobs.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_softjobs.c new file mode 100644 index 0000000000000000000000000000000000000000..f762996cfdd4ada4ec7568e6ae09e0cd6853bd5d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_softjobs.c @@ -0,0 +1,442 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +#include +#ifdef CONFIG_SYNC +#include "sync.h" +#include +#include "mali_kbase_sync.h" +#endif + + +/* Mask to check cache alignment of data structures */ +#define KBASE_CACHE_ALIGNMENT_MASK ((1<jc; + struct kbase_context *kctx = katom->kctx; + int pm_active_err; + + u32 hi1, hi2; + + memset(&data, 0, sizeof(data)); + + /* Take the PM active reference as late as possible - otherwise, it could + * delay suspend until we process the atom (which may be at the end of a + * long chain of dependencies */ + pm_active_err = kbase_pm_context_active_handle_suspend(kctx->kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE); + if (pm_active_err) { + struct kbasep_js_device_data *js_devdata = &kctx->kbdev->js_data; + + /* We're suspended - queue this on the list of suspended jobs + * Use dep_item[1], because dep_item[0] is in use for 'waiting_soft_jobs' */ + mutex_lock(&js_devdata->runpool_mutex); + list_add_tail(&katom->dep_item[1], &js_devdata->suspended_soft_jobs_list); + mutex_unlock(&js_devdata->runpool_mutex); + + return pm_active_err; + } + + kbase_pm_request_gpu_cycle_counter(kctx->kbdev); + + /* Read hi, lo, hi to ensure that overflow from lo to hi is handled correctly */ + do { + hi1 = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(CYCLE_COUNT_HI), NULL); + cycle_counter = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(CYCLE_COUNT_LO), NULL); + hi2 = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(CYCLE_COUNT_HI), NULL); + cycle_counter |= (((u64) hi1) << 32); + } while (hi1 != hi2); + + /* Read hi, lo, hi to ensure that overflow from lo to hi is handled correctly */ + do { + hi1 = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(TIMESTAMP_HI), NULL); + system_time = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(TIMESTAMP_LO), NULL); + hi2 = kbase_reg_read(kctx->kbdev, GPU_CONTROL_REG(TIMESTAMP_HI), NULL); + system_time |= (((u64) hi1) << 32); + } while (hi1 != hi2); + + /* Record the CPU's idea of current time */ + getrawmonotonic(&ts); + + kbase_pm_release_gpu_cycle_counter(kctx->kbdev); + + kbase_pm_context_idle(kctx->kbdev); + + data.sec = ts.tv_sec; + data.usec = ts.tv_nsec / 1000; + data.system_time = system_time; + data.cycle_counter = cycle_counter; + + pfn = jc >> PAGE_SHIFT; + offset = jc & ~PAGE_MASK; + + /* Assume this atom will be cancelled until we know otherwise */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + if (offset > 0x1000 - sizeof(data)) { + /* Wouldn't fit in the page */ + return 0; + } + + kbase_gpu_vm_lock(kctx); + reg = kbase_region_tracker_find_region_enclosing_address(kctx, jc); + if (reg && + (reg->flags & KBASE_REG_GPU_WR) && + reg->alloc && reg->alloc->pages) + addr = reg->alloc->pages[pfn - reg->start_pfn]; + + kbase_gpu_vm_unlock(kctx); + if (!addr) + return 0; + + page = kmap(pfn_to_page(PFN_DOWN(addr))); + if (!page) + return 0; + + dma_sync_single_for_cpu(katom->kctx->kbdev->dev, + kbase_dma_addr(pfn_to_page(PFN_DOWN(addr))) + + offset, sizeof(data), + DMA_BIDIRECTIONAL); + memcpy(page + offset, &data, sizeof(data)); + dma_sync_single_for_device(katom->kctx->kbdev->dev, + kbase_dma_addr(pfn_to_page(PFN_DOWN(addr))) + + offset, sizeof(data), + DMA_BIDIRECTIONAL); + kunmap(pfn_to_page(PFN_DOWN(addr))); + + /* Atom was fine - mark it as done */ + katom->event_code = BASE_JD_EVENT_DONE; + + return 0; +} + +#ifdef CONFIG_SYNC + +/* Complete an atom that has returned '1' from kbase_process_soft_job (i.e. has waited) + * + * @param katom The atom to complete + */ +static void complete_soft_job(struct kbase_jd_atom *katom) +{ + struct kbase_context *kctx = katom->kctx; + + mutex_lock(&kctx->jctx.lock); + list_del(&katom->dep_item[0]); + kbase_finish_soft_job(katom); + if (jd_done_nolock(katom)) + kbasep_js_try_schedule_head_ctx(kctx->kbdev); + mutex_unlock(&kctx->jctx.lock); +} + +static enum base_jd_event_code kbase_fence_trigger(struct kbase_jd_atom *katom, int result) +{ + struct sync_pt *pt; + struct sync_timeline *timeline; + + if (!list_is_singular(&katom->fence->pt_list_head)) { + /* Not exactly one item in the list - so it didn't (directly) come from us */ + return BASE_JD_EVENT_JOB_CANCELLED; + } + + pt = list_first_entry(&katom->fence->pt_list_head, struct sync_pt, pt_list); + timeline = pt->parent; + + if (!kbase_sync_timeline_is_ours(timeline)) { + /* Fence has a sync_pt which isn't ours! */ + return BASE_JD_EVENT_JOB_CANCELLED; + } + + kbase_sync_signal_pt(pt, result); + + sync_timeline_signal(timeline); + + return (result < 0) ? BASE_JD_EVENT_JOB_CANCELLED : BASE_JD_EVENT_DONE; +} + +static void kbase_fence_wait_worker(struct work_struct *data) +{ + struct kbase_jd_atom *katom; + struct kbase_context *kctx; + + katom = container_of(data, struct kbase_jd_atom, work); + kctx = katom->kctx; + + complete_soft_job(katom); +} + +static void kbase_fence_wait_callback(struct sync_fence *fence, struct sync_fence_waiter *waiter) +{ + struct kbase_jd_atom *katom = container_of(waiter, struct kbase_jd_atom, sync_waiter); + struct kbase_context *kctx; + + KBASE_DEBUG_ASSERT(NULL != katom); + + kctx = katom->kctx; + + KBASE_DEBUG_ASSERT(NULL != kctx); + + /* Propagate the fence status to the atom. + * If negative then cancel this atom and its dependencies. + */ + if (fence->status < 0) + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + /* To prevent a potential deadlock we schedule the work onto the job_done_wq workqueue + * + * The issue is that we may signal the timeline while holding kctx->jctx.lock and + * the callbacks are run synchronously from sync_timeline_signal. So we simply defer the work. + */ + + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, kbase_fence_wait_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); +} + +static int kbase_fence_wait(struct kbase_jd_atom *katom) +{ + int ret; + + KBASE_DEBUG_ASSERT(NULL != katom); + KBASE_DEBUG_ASSERT(NULL != katom->kctx); + + sync_fence_waiter_init(&katom->sync_waiter, kbase_fence_wait_callback); + + ret = sync_fence_wait_async(katom->fence, &katom->sync_waiter); + + if (ret == 1) { + /* Already signalled */ + return 0; + } else if (ret < 0) { + goto cancel_atom; + } + return 1; + + cancel_atom: + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + /* We should cause the dependant jobs in the bag to be failed, + * to do this we schedule the work queue to complete this job */ + KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work)); + INIT_WORK(&katom->work, kbase_fence_wait_worker); + queue_work(katom->kctx->jctx.job_done_wq, &katom->work); + return 1; +} + +static void kbase_fence_cancel_wait(struct kbase_jd_atom *katom) +{ + if (sync_fence_cancel_async(katom->fence, &katom->sync_waiter) != 0) { + /* The wait wasn't cancelled - leave the cleanup for kbase_fence_wait_callback */ + return; + } + + /* Wait was cancelled - zap the atoms */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + kbase_finish_soft_job(katom); + + if (jd_done_nolock(katom)) + kbasep_js_try_schedule_head_ctx(katom->kctx->kbdev); +} +#endif /* CONFIG_SYNC */ + +int kbase_process_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + return kbase_dump_cpu_gpu_time(katom); +#ifdef CONFIG_SYNC + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + KBASE_DEBUG_ASSERT(katom->fence != NULL); + katom->event_code = kbase_fence_trigger(katom, katom->event_code == BASE_JD_EVENT_DONE ? 0 : -EFAULT); + /* Release the reference as we don't need it any more */ + sync_fence_put(katom->fence); + katom->fence = NULL; + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + return kbase_fence_wait(katom); +#endif /* CONFIG_SYNC */ + case BASE_JD_REQ_SOFT_REPLAY: + return kbase_replay_process(katom); + } + + /* Atom is complete */ + return 0; +} + +void kbase_cancel_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) { +#ifdef CONFIG_SYNC + case BASE_JD_REQ_SOFT_FENCE_WAIT: + kbase_fence_cancel_wait(katom); + break; +#endif + default: + /* This soft-job doesn't support cancellation! */ + KBASE_DEBUG_ASSERT(0); + } +} + +mali_error kbase_prepare_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + { + if (0 != (katom->jc & KBASE_CACHE_ALIGNMENT_MASK)) + return MALI_ERROR_FUNCTION_FAILED; + } + break; +#ifdef CONFIG_SYNC + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + { + struct base_fence fence; + int fd; + + if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence))) + return MALI_ERROR_FUNCTION_FAILED; + + fd = kbase_stream_create_fence(fence.basep.stream_fd); + if (fd < 0) + return MALI_ERROR_FUNCTION_FAILED; + + katom->fence = sync_fence_fdget(fd); + + if (katom->fence == NULL) { + /* The only way the fence can be NULL is if userspace closed it for us. + * So we don't need to clear it up */ + return MALI_ERROR_FUNCTION_FAILED; + } + fence.basep.fd = fd; + if (0 != copy_to_user((__user void *)(uintptr_t) katom->jc, &fence, sizeof(fence))) { + katom->fence = NULL; + sys_close(fd); + return MALI_ERROR_FUNCTION_FAILED; + } + } + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + { + struct base_fence fence; + + if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence))) + return MALI_ERROR_FUNCTION_FAILED; + + /* Get a reference to the fence object */ + katom->fence = sync_fence_fdget(fence.basep.fd); + if (katom->fence == NULL) + return MALI_ERROR_FUNCTION_FAILED; + } + break; +#endif /* CONFIG_SYNC */ + case BASE_JD_REQ_SOFT_REPLAY: + break; + default: + /* Unsupported soft-job */ + return MALI_ERROR_FUNCTION_FAILED; + } + return MALI_ERROR_NONE; +} + +void kbase_finish_soft_job(struct kbase_jd_atom *katom) +{ + switch (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) { + case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: + /* Nothing to do */ + break; +#ifdef CONFIG_SYNC + case BASE_JD_REQ_SOFT_FENCE_TRIGGER: + if (katom->fence) { + /* The fence has not yet been signalled, so we do it now */ + kbase_fence_trigger(katom, katom->event_code == BASE_JD_EVENT_DONE ? 0 : -EFAULT); + sync_fence_put(katom->fence); + katom->fence = NULL; + } + break; + case BASE_JD_REQ_SOFT_FENCE_WAIT: + /* Release the reference to the fence object */ + sync_fence_put(katom->fence); + katom->fence = NULL; + break; +#endif /* CONFIG_SYNC */ + } +} + +void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev) +{ + LIST_HEAD(local_suspended_soft_jobs); + struct kbase_jd_atom *tmp_iter; + struct kbase_jd_atom *katom_iter; + struct kbasep_js_device_data *js_devdata; + mali_bool resched = MALI_FALSE; + + KBASE_DEBUG_ASSERT(kbdev); + + js_devdata = &kbdev->js_data; + + /* Move out the entire list */ + mutex_lock(&js_devdata->runpool_mutex); + list_splice_init(&js_devdata->suspended_soft_jobs_list, &local_suspended_soft_jobs); + mutex_unlock(&js_devdata->runpool_mutex); + + /* Each atom must be detached from the list and ran separately - it could + * be re-added to the old list, but this is unlikely */ + list_for_each_entry_safe(katom_iter, tmp_iter, &local_suspended_soft_jobs, dep_item[1]) + { + struct kbase_context *kctx = katom_iter->kctx; + + mutex_lock(&kctx->jctx.lock); + + /* Remove from the global list */ + list_del(&katom_iter->dep_item[1]); + /* Remove from the context's list of waiting soft jobs */ + list_del(&katom_iter->dep_item[0]); + + if (kbase_process_soft_job(katom_iter) == 0) { + kbase_finish_soft_job(katom_iter); + resched |= jd_done_nolock(katom_iter); + } else { + /* The job has not completed */ + KBASE_DEBUG_ASSERT((katom_iter->core_req & BASEP_JD_REQ_ATOM_TYPE) + != BASE_JD_REQ_SOFT_REPLAY); + list_add_tail(&katom_iter->dep_item[0], &kctx->waiting_soft_jobs); + } + + mutex_unlock(&kctx->jctx.lock); + } + + if (resched) + kbasep_js_try_schedule_head_ctx(kbdev); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.c new file mode 100644 index 0000000000000000000000000000000000000000..506b397176f6986bdfde2ab13adbe88d30f18c70 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.c @@ -0,0 +1,189 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_sync.c + * + */ + +#ifdef CONFIG_SYNC + +#include "sync.h" +#include + +struct mali_sync_timeline { + struct sync_timeline timeline; + atomic_t counter; + atomic_t signalled; +}; + +struct mali_sync_pt { + struct sync_pt pt; + int order; + int result; +}; + +static struct mali_sync_timeline *to_mali_sync_timeline(struct sync_timeline *timeline) +{ + return container_of(timeline, struct mali_sync_timeline, timeline); +} + +static struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt) +{ + return container_of(pt, struct mali_sync_pt, pt); +} + +static struct sync_pt *timeline_dup(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_pt *new_mpt; + struct sync_pt *new_pt = sync_pt_create(pt->parent, sizeof(struct mali_sync_pt)); + + if (!new_pt) + return NULL; + + new_mpt = to_mali_sync_pt(new_pt); + new_mpt->order = mpt->order; + new_mpt->result = mpt->result; + + return new_pt; +} + +static int timeline_has_signaled(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent); + int result = mpt->result; + + int diff = atomic_read(&mtl->signalled) - mpt->order; + + if (diff >= 0) + return result < 0 ? result : 1; + else + return 0; +} + +static int timeline_compare(struct sync_pt *a, struct sync_pt *b) +{ + struct mali_sync_pt *ma = container_of(a, struct mali_sync_pt, pt); + struct mali_sync_pt *mb = container_of(b, struct mali_sync_pt, pt); + + int diff = ma->order - mb->order; + + if (diff < 0) + return -1; + else if (diff == 0) + return 0; + else + return 1; +} + +static void timeline_value_str(struct sync_timeline *timeline, char *str, + int size) +{ + struct mali_sync_timeline *mtl = to_mali_sync_timeline(timeline); + + snprintf(str, size, "%d", atomic_read(&mtl->signalled)); +} + +static void pt_value_str(struct sync_pt *pt, char *str, int size) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + + snprintf(str, size, "%d(%d)", mpt->order, mpt->result); +} + +static struct sync_timeline_ops mali_timeline_ops = { + .driver_name = "Mali", + .dup = timeline_dup, + .has_signaled = timeline_has_signaled, + .compare = timeline_compare, + .timeline_value_str = timeline_value_str, + .pt_value_str = pt_value_str, +}; + +int kbase_sync_timeline_is_ours(struct sync_timeline *timeline) +{ + return timeline->ops == &mali_timeline_ops; +} + +struct sync_timeline *kbase_sync_timeline_alloc(const char *name) +{ + struct sync_timeline *tl; + struct mali_sync_timeline *mtl; + + tl = sync_timeline_create(&mali_timeline_ops, sizeof(struct mali_sync_timeline), name); + if (!tl) + return NULL; + + /* Set the counter in our private struct */ + mtl = to_mali_sync_timeline(tl); + atomic_set(&mtl->counter, 0); + atomic_set(&mtl->signalled, 0); + + return tl; +} + +struct sync_pt *kbase_sync_pt_alloc(struct sync_timeline *parent) +{ + struct sync_pt *pt = sync_pt_create(parent, sizeof(struct mali_sync_pt)); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(parent); + struct mali_sync_pt *mpt; + + if (!pt) + return NULL; + + mpt = to_mali_sync_pt(pt); + mpt->order = atomic_inc_return(&mtl->counter); + mpt->result = 0; + + return pt; +} + +void kbase_sync_signal_pt(struct sync_pt *pt, int result) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent); + int signalled; + int diff; + + mpt->result = result; + + do { + signalled = atomic_read(&mtl->signalled); + + diff = signalled - mpt->order; + + if (diff > 0) { + /* The timeline is already at or ahead of this point. + * This should not happen unless userspace has been + * signalling fences out of order, so warn but don't + * violate the sync_pt API. + * The warning is only in debug builds to prevent + * a malicious user being able to spam dmesg. + */ +#ifdef CONFIG_MALI_DEBUG + pr_err("Fences were triggered in a different order to allocation!"); +#endif /* CONFIG_MALI_DEBUG */ + return; + } + } while (atomic_cmpxchg(&mtl->signalled, signalled, mpt->order) != signalled); +} + +#endif /* CONFIG_SYNC */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.h new file mode 100644 index 0000000000000000000000000000000000000000..b9f295146c7c3aa2449e9ad6a0d9c709a04e02a9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync.h @@ -0,0 +1,83 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_sync.h + * + */ + +#ifndef MALI_KBASE_SYNC_H +#define MALI_KBASE_SYNC_H + +#include "sync.h" +#include + +/* + * Create a stream object. + * Built on top of timeline object. + * Exposed as a file descriptor. + * Life-time controlled via the file descriptor: + * - dup to add a ref + * - close to remove a ref + */ +mali_error kbase_stream_create(const char *name, int *const out_fd); + +/* + * Create a fence in a stream object + */ +int kbase_stream_create_fence(int tl_fd); + +/* + * Validate a fd to be a valid fence + * No reference is taken. + * + * This function is only usable to catch unintentional user errors early, + * it does not stop malicious code changing the fd after this function returns. + */ +mali_error kbase_fence_validate(int fd); + +/* Returns true if the specified timeline is allocated by Mali */ +int kbase_sync_timeline_is_ours(struct sync_timeline *timeline); + +/* Allocates a timeline for Mali + * + * One timeline should be allocated per API context. + */ +struct sync_timeline *kbase_sync_timeline_alloc(const char *name); + +/* Allocates a sync point within the timeline. + * + * The timeline must be the one allocated by kbase_sync_timeline_alloc + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + */ +struct sync_pt *kbase_sync_pt_alloc(struct sync_timeline *parent); + +/* Signals a particular sync point + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + * + * If they are signalled in the wrong order then a message will be printed in debug + * builds and otherwise attempts to signal order sync_pts will be ignored. + * + * result can be negative to indicate error, any other value is interpreted as success. + */ +void kbase_sync_signal_pt(struct sync_pt *pt, int result); + +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync_user.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync_user.c new file mode 100644 index 0000000000000000000000000000000000000000..c823226e151a0bb1bac2773ff87af606b07e41a9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_sync_user.c @@ -0,0 +1,158 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_kbase_sync_user.c + * + */ + +#ifdef CONFIG_SYNC + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int kbase_stream_close(struct inode *inode, struct file *file) +{ + struct sync_timeline *tl; + + tl = (struct sync_timeline *)file->private_data; + BUG_ON(!tl); + sync_timeline_destroy(tl); + return 0; +} + +static const struct file_operations stream_fops = { + .owner = THIS_MODULE, + .release = kbase_stream_close, +}; + +mali_error kbase_stream_create(const char *name, int *const out_fd) +{ + struct sync_timeline *tl; + + BUG_ON(!out_fd); + + tl = kbase_sync_timeline_alloc(name); + if (!tl) + return MALI_ERROR_FUNCTION_FAILED; + + *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC); + + if (*out_fd < 0) { + sync_timeline_destroy(tl); + return MALI_ERROR_FUNCTION_FAILED; + } else { + return MALI_ERROR_NONE; + } +} + +int kbase_stream_create_fence(int tl_fd) +{ + struct sync_timeline *tl; + struct sync_pt *pt; + struct sync_fence *fence; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) + struct files_struct *files; + struct fdtable *fdt; +#endif + int fd; + struct file *tl_file; + + tl_file = fget(tl_fd); + if (tl_file == NULL) + return -EBADF; + + if (tl_file->f_op != &stream_fops) { + fd = -EBADF; + goto out; + } + + tl = tl_file->private_data; + + pt = kbase_sync_pt_alloc(tl); + if (!pt) { + fd = -EFAULT; + goto out; + } + + fence = sync_fence_create("mali_fence", pt); + if (!fence) { + sync_pt_free(pt); + fd = -EFAULT; + goto out; + } + + /* from here the fence owns the sync_pt */ + + /* create a fd representing the fence */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC); + if (fd < 0) { + sync_fence_put(fence); + goto out; + } +#else + fd = get_unused_fd(); + if (fd < 0) { + sync_fence_put(fence); + goto out; + } + + files = current->files; + spin_lock(&files->file_lock); + fdt = files_fdtable(files); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + __set_close_on_exec(fd, fdt); +#else + FD_SET(fd, fdt->close_on_exec); +#endif + spin_unlock(&files->file_lock); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */ + + /* bind fence to the new fd */ + sync_fence_install(fence, fd); + + out: + fput(tl_file); + + return fd; +} + +mali_error kbase_fence_validate(int fd) +{ + struct sync_fence *fence; + + fence = sync_fence_fdget(fd); + if (NULL != fence) { + sync_fence_put(fence); + return MALI_ERROR_NONE; + } else { + return MALI_ERROR_FUNCTION_FAILED; + } +} + +#endif /* CONFIG_SYNC */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_defs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..e492ff2ca4815baf332fb4666b0605511e6362b5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_defs.h @@ -0,0 +1,264 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* ***** IMPORTANT: THIS IS NOT A NORMAL HEADER FILE ***** + * ***** DO NOT INCLUDE DIRECTLY ***** + * ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ + +/* + * The purpose of this header file is just to contain a list of trace code idenitifers + * + * Each identifier is wrapped in a macro, so that its string form and enum form can be created + * + * Each macro is separated with a comma, to allow insertion into an array initializer or enum definition block. + * + * This allows automatic creation of an enum and a corresponding array of strings + * + * Before #including, the includer MUST #define KBASE_TRACE_CODE_MAKE_CODE. + * After #including, the includer MUST #under KBASE_TRACE_CODE_MAKE_CODE. + * + * e.g.: + * #define KBASE_TRACE_CODE( X ) KBASE_TRACE_CODE_ ## X + * typedef enum + * { + * #define KBASE_TRACE_CODE_MAKE_CODE( X ) KBASE_TRACE_CODE( X ) + * #include "mali_kbase_trace_defs.h" + * #undef KBASE_TRACE_CODE_MAKE_CODE + * } kbase_trace_code; + * + * IMPORTANT: THIS FILE MUST NOT BE USED FOR ANY OTHER PURPOSE OTHER THAN THE ABOVE + * + * + * The use of the macro here is: + * - KBASE_TRACE_CODE_MAKE_CODE( X ) + * + * Which produces: + * - For an enum, KBASE_TRACE_CODE_X + * - For a string, "X" + * + * + * For example: + * - KBASE_TRACE_CODE_MAKE_CODE( JM_JOB_COMPLETE ) expands to: + * - KBASE_TRACE_CODE_JM_JOB_COMPLETE for the enum + * - "JM_JOB_COMPLETE" for the string + * - To use it to trace an event, do: + * - KBASE_TRACE_ADD( kbdev, JM_JOB_COMPLETE, subcode, kctx, uatom, val ); + */ + +#if 0 /* Dummy section to avoid breaking formatting */ +int dummy_array[] = { +#endif + +/* + * Core events + */ + /* no info_val, no gpu_addr, no atom */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_CTX_DESTROY), + /* no info_val, no gpu_addr, no atom */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_CTX_HWINSTR_TERM), + /* info_val == GPU_IRQ_STATUS register */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ), + /* info_val == bits cleared */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ_CLEAR), + /* info_val == GPU_IRQ_STATUS register */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_IRQ_DONE), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_SOFT_RESET), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_HARD_RESET), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_PRFCNT_CLEAR), + /* GPU addr==dump address */ + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_PRFCNT_SAMPLE), + KBASE_TRACE_CODE_MAKE_CODE(CORE_GPU_CLEAN_INV_CACHES), +/* + * Job Slot management events + */ + /* info_val==irq rawstat at start */ + KBASE_TRACE_CODE_MAKE_CODE(JM_IRQ), + /* info_val==jobs processed */ + KBASE_TRACE_CODE_MAKE_CODE(JM_IRQ_END), +/* In the following: + * + * - ctx is set if a corresponding job found (NULL otherwise, e.g. some soft-stop cases) + * - uatom==kernel-side mapped uatom address (for correlation with user-side) + */ + /* info_val==exit code; gpu_addr==chain gpuaddr */ + KBASE_TRACE_CODE_MAKE_CODE(JM_JOB_DONE), + /* gpu_addr==JS_HEAD_NEXT written, info_val==lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SUBMIT), + /* gpu_addr is as follows: + * - If JS_STATUS active after soft-stop, val==gpu addr written to + * JS_HEAD on submit + * - otherwise gpu_addr==0 */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP), + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP_0), + KBASE_TRACE_CODE_MAKE_CODE(JM_SOFTSTOP_1), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP_0), + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_HARDSTOP_1), + /* gpu_addr==JS_TAIL read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_UPDATE_HEAD), +/* gpu_addr is as follows: + * - If JS_STATUS active before soft-stop, val==JS_HEAD + * - otherwise gpu_addr==0 + */ + /* gpu_addr==JS_HEAD read */ + KBASE_TRACE_CODE_MAKE_CODE(JM_CHECK_HEAD), + KBASE_TRACE_CODE_MAKE_CODE(JM_FLUSH_WORKQS), + KBASE_TRACE_CODE_MAKE_CODE(JM_FLUSH_WORKQS_DONE), + /* info_val == is_scheduled */ + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_NON_SCHEDULED), + /* info_val == is_scheduled */ + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_SCHEDULED), + KBASE_TRACE_CODE_MAKE_CODE(JM_ZAP_DONE), + /* info_val == nr jobs submitted */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SLOT_SOFT_OR_HARD_STOP), + /* gpu_addr==JS_HEAD_NEXT last written */ + KBASE_TRACE_CODE_MAKE_CODE(JM_SLOT_EVICT), + KBASE_TRACE_CODE_MAKE_CODE(JM_SUBMIT_AFTER_RESET), + KBASE_TRACE_CODE_MAKE_CODE(JM_BEGIN_RESET_WORKER), + KBASE_TRACE_CODE_MAKE_CODE(JM_END_RESET_WORKER), +/* + * Job dispatch events + */ + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_WORKER), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_WORKER_END), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_DONE_TRY_RUN_NEXT_JOB), + /* gpu_addr==0, info_val==0, uatom==0 */ + KBASE_TRACE_CODE_MAKE_CODE(JD_ZAP_CONTEXT), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_CANCEL), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JD_CANCEL_WORKER), +/* + * Scheduler Core events + */ + KBASE_TRACE_CODE_MAKE_CODE(JS_RETAIN_CTX_NOLOCK), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_ADD_JOB), + /* gpu_addr==last value written/would be written to JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_REMOVE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_RETAIN_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_RELEASE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_TRY_SCHEDULE_HEAD_CTX), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_JOB_DONE_TRY_RUN_NEXT_JOB), + /* gpu_addr==value to write into JS_HEAD */ + KBASE_TRACE_CODE_MAKE_CODE(JS_JOB_DONE_RETRY_NEEDED), + /* kctx is the one being evicted, info_val == kctx to put in */ + KBASE_TRACE_CODE_MAKE_CODE(JS_FAST_START_EVICTS_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_AFFINITY_SUBMIT_TO_BLOCKED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_AFFINITY_CURRENT), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REQUEST_CORES_FAILED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REGISTER_INUSE_FAILED), + /* info_val == lower 32 bits of rechecked affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REQUEST_ON_RECHECK_FAILED), + /* info_val == lower 32 bits of rechecked affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_REGISTER_ON_RECHECK_FAILED), + /* info_val == lower 32 bits of affinity */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CORE_REF_AFFINITY_WOULD_VIOLATE), + /* info_val == the ctx attribute now on ctx */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_ON_CTX), + /* info_val == the ctx attribute now on runpool */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_ON_RUNPOOL), + /* info_val == the ctx attribute now off ctx */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_OFF_CTX), + /* info_val == the ctx attribute now off runpool */ + KBASE_TRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_OFF_RUNPOOL), +/* + * Scheduler Policy events + */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_INIT_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TERM_CTX), + /* info_val == whether it was evicted */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TRY_EVICT_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_FOREACH_CTX_JOBS), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_ENQUEUE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_HEAD_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_RUNPOOL_ADD_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_RUNPOOL_REMOVE_CTX), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_JOB_IRQ), + /* gpu_addr==JS_HEAD to write if the job were run */ + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_ENQUEUE_JOB), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TIMER_START), + KBASE_TRACE_CODE_MAKE_CODE(JS_POLICY_TIMER_END), +/* + * Power Management Events + */ + KBASE_TRACE_CODE_MAKE_CODE(PM_JOB_SUBMIT_AFTER_POWERING_UP), + KBASE_TRACE_CODE_MAKE_CODE(PM_JOB_SUBMIT_AFTER_POWERED_UP), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWRON_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_PWROFF_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_POWERED_L2), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_DESIRED), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_DESIRED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_AVAILABLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CORES_AVAILABLE_TILER), + /* PM_DESIRED_REACHED: gpu_addr == pm.gpu_in_desired_state */ + KBASE_TRACE_CODE_MAKE_CODE(PM_DESIRED_REACHED), + KBASE_TRACE_CODE_MAKE_CODE(PM_DESIRED_REACHED_TILER), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_SHADER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_TILER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REGISTER_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_RELEASE_CHANGE_SHADER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_RELEASE_CHANGE_TILER_INUSE), + KBASE_TRACE_CODE_MAKE_CODE(PM_UNREQUEST_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_UNREQUEST_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REQUEST_CHANGE_SHADER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_REQUEST_CHANGE_TILER_NEEDED), + KBASE_TRACE_CODE_MAKE_CODE(PM_WAKE_WAITERS), + KBASE_TRACE_CODE_MAKE_CODE(PM_CONTEXT_ACTIVE), + KBASE_TRACE_CODE_MAKE_CODE(PM_CONTEXT_IDLE), + KBASE_TRACE_CODE_MAKE_CODE(PM_GPU_ON), + KBASE_TRACE_CODE_MAKE_CODE(PM_GPU_OFF), + /* info_val == policy number, or -1 for "Already changing" */ + KBASE_TRACE_CODE_MAKE_CODE(PM_SET_POLICY), + KBASE_TRACE_CODE_MAKE_CODE(PM_CA_SET_POLICY), + /* info_val == policy number */ + KBASE_TRACE_CODE_MAKE_CODE(PM_CURRENT_POLICY_INIT), + /* info_val == policy number */ + KBASE_TRACE_CODE_MAKE_CODE(PM_CURRENT_POLICY_TERM), +/* Unused code just to make it easier to not have a comma at the end. + * All other codes MUST come before this */ + KBASE_TRACE_CODE_MAKE_CODE(DUMMY) + +#if 0 /* Dummy section to avoid breaking formatting */ +}; +#endif + +/* ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.c new file mode 100644 index 0000000000000000000000000000000000000000..49f5035a913e31e921abdad1171178565d1cdf98 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.c @@ -0,0 +1,231 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include + +#define CREATE_TRACE_POINTS + +#ifdef CONFIG_MALI_TRACE_TIMELINE +#include "mali_timeline.h" + +#include +#include + +struct kbase_trace_timeline_desc +{ + char *enum_str; + char *desc; + char *format; + char *format_desc; +}; + +struct kbase_trace_timeline_desc kbase_trace_timeline_desc_table[] = +{ + #define KBASE_TIMELINE_TRACE_CODE(enum_val, desc, format, format_desc) { #enum_val, desc, format, format_desc } + #include "mali_kbase_trace_timeline_defs.h" + #undef KBASE_TIMELINE_TRACE_CODE +}; + +#define KBASE_NR_TRACE_CODES ARRAY_SIZE(kbase_trace_timeline_desc_table) + +STATIC void *kbasep_trace_timeline_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos >= KBASE_NR_TRACE_CODES) + return NULL; + + return &kbase_trace_timeline_desc_table[*pos]; +} + +STATIC void kbasep_trace_timeline_seq_stop(struct seq_file *s, void *data) +{ +} + +STATIC void *kbasep_trace_timeline_seq_next(struct seq_file *s, void *data, loff_t *pos) +{ + (*pos)++; + + if (*pos == KBASE_NR_TRACE_CODES) + return NULL; + + return &kbase_trace_timeline_desc_table[*pos]; +} + +STATIC int kbasep_trace_timeline_seq_show(struct seq_file *s, void *data) +{ + struct kbase_trace_timeline_desc *trace_desc = data; + + seq_printf(s, "%s#%s#%s#%s\n", trace_desc->enum_str, trace_desc->desc, trace_desc->format, trace_desc->format_desc); + return 0; +} + + +static const struct seq_operations kbasep_trace_timeline_seq_ops = { + .start = kbasep_trace_timeline_seq_start, + .next = kbasep_trace_timeline_seq_next, + .stop = kbasep_trace_timeline_seq_stop, + .show = kbasep_trace_timeline_seq_show, +}; + +STATIC int kbasep_trace_timeline_debugfs_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &kbasep_trace_timeline_seq_ops); +} + +static const struct file_operations kbasep_trace_timeline_debugfs_fops = { + .open = kbasep_trace_timeline_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +mali_error kbasep_trace_timeline_debugfs_init(struct kbase_device *kbdev) +{ + kbdev->timeline.dentry = debugfs_create_file("mali_timeline_defs", + S_IRUGO, kbdev->mali_debugfs_directory, NULL, + &kbasep_trace_timeline_debugfs_fops); + if (IS_ERR(kbdev->timeline.dentry)) + return MALI_ERROR_FUNCTION_FAILED; + + return MALI_ERROR_NONE; +} + +void kbasep_trace_timeline_debugfs_term(struct kbase_device *kbdev) +{ + debugfs_remove(kbdev->timeline.dentry); +} + +void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js) +{ + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + if (kbdev->timeline.slot_atoms_submitted[js] > 0) { + KBASE_TIMELINE_JOB_START_NEXT(kctx, js, 1); + } else { + base_atom_id atom_number = kbase_jd_atom_id(kctx, katom); + KBASE_TIMELINE_JOB_START_HEAD(kctx, js, 1); + KBASE_TIMELINE_JOB_START(kctx, js, atom_number); + } + ++kbdev->timeline.slot_atoms_submitted[js]; + + KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, kbdev->timeline.slot_atoms_submitted[js]); +} + +void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code) +{ + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); + + if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT) { + KBASE_TIMELINE_JOB_START_NEXT(kctx, js, 0); + } else { + /* Job finished in JS_HEAD */ + base_atom_id atom_number = kbase_jd_atom_id(kctx, katom); + KBASE_TIMELINE_JOB_START_HEAD(kctx, js, 0); + KBASE_TIMELINE_JOB_STOP(kctx, js, atom_number); + /* see if we need to trace the job in JS_NEXT moving to JS_HEAD */ + if (kbdev->timeline.slot_atoms_submitted[js] > 1) { + /* Tag events with next_katom's kctx */ + struct kbase_jm_slot *slot = &kbdev->jm_slots[js]; + struct kbase_jd_atom *next_katom; + struct kbase_context *next_kctx; + KBASE_DEBUG_ASSERT(kbasep_jm_nr_jobs_submitted(slot) > 0); + + /* Peek the next atom - note that the atom in JS_HEAD will already + * have been dequeued */ + next_katom = kbasep_jm_peek_idx_submit_slot(slot, 0); + next_kctx = next_katom->kctx; + KBASE_TIMELINE_JOB_START_NEXT(next_kctx, js, 0); + KBASE_TIMELINE_JOB_START_HEAD(next_kctx, js, 1); + KBASE_TIMELINE_JOB_START(next_kctx, js, kbase_jd_atom_id(next_kctx, next_katom)); + } + } + + --kbdev->timeline.slot_atoms_submitted[js]; + + KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, kbdev->timeline.slot_atoms_submitted[js]); +} + +void kbase_timeline_pm_send_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event_sent) +{ + int uid = 0; + int old_uid; + + /* If a producer already exists for the event, try to use their UID (multiple-producers) */ + uid = atomic_read(&kbdev->timeline.pm_event_uid[event_sent]); + old_uid = uid; + + /* Get a new non-zero UID if we don't have one yet */ + while (!uid) + uid = atomic_inc_return(&kbdev->timeline.pm_event_uid_counter); + + /* Try to use this UID */ + if (old_uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event_sent], old_uid, uid)) + /* If it changed, raced with another producer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_sent, uid); +} + +void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ + int uid = atomic_read(&kbdev->timeline.pm_event_uid[event]); + + if (uid != 0) { + if (uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event], uid, 0)) + /* If it changed, raced with another consumer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event, uid); + } +} + +void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ + int uid = atomic_read(&kbdev->timeline.pm_event_uid[event]); + + if (uid != atomic_cmpxchg(&kbdev->timeline.pm_event_uid[event], uid, 0)) + /* If it changed, raced with another consumer: we've lost this UID */ + uid = 0; + + KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event, uid); +} + +void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.power_change_lock); + /* Simply log the start of the transition */ + kbdev->timeline.l2_transitioning = MALI_TRUE; + KBASE_TIMELINE_POWERING_L2(kbdev); +} + +void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->pm.power_change_lock); + /* Simply log the end of the transition */ + if (MALI_FALSE != kbdev->timeline.l2_transitioning) + { + kbdev->timeline.l2_transitioning = MALI_FALSE; + KBASE_TIMELINE_POWERED_L2(kbdev); + } +} + +#endif /* CONFIG_MALI_TRACE_TIMELINE */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.h new file mode 100644 index 0000000000000000000000000000000000000000..63cacff66e1c36c4fe8729a7b5a47ddb5305de08 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline.h @@ -0,0 +1,380 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#if !defined(_KBASE_TRACE_TIMELINE_H) +#define _KBASE_TRACE_TIMELINE_H + +#ifdef CONFIG_MALI_TRACE_TIMELINE + +typedef enum +{ + #define KBASE_TIMELINE_TRACE_CODE(enum_val, desc, format, format_desc) enum_val + #include "mali_kbase_trace_timeline_defs.h" + #undef KBASE_TIMELINE_TRACE_CODE +} kbase_trace_timeline_code; + +/** Initialize Timeline DebugFS entries */ +mali_error kbasep_trace_timeline_debugfs_init(struct kbase_device *kbdev); +/** Terminate Timeline DebugFS entries */ +void kbasep_trace_timeline_debugfs_term(struct kbase_device *kbdev); + +/* mali_timeline.h defines kernel tracepoints used by the KBASE_TIMELINE + * functions. + * Output is timestamped by either sched_clock() (default), local_clock(), or + * cpu_clock(), depending on /sys/kernel/debug/tracing/trace_clock */ +#include "mali_timeline.h" + +/* Trace number of atoms in flight for kctx (atoms either not completed, or in + process of being returned to user */ +#define KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_atoms_in_flight(ts.tv_sec, ts.tv_nsec, \ + (int)kctx->timeline.owner_tgid, \ + count); \ + } while (0) + +/* Trace atom_id being Ready to Run */ +#define KBASE_TIMELINE_ATOM_READY(kctx, atom_id) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_atom(ts.tv_sec, ts.tv_nsec, \ + CTX_FLOW_ATOM_READY, \ + (int)kctx->timeline.owner_tgid, \ + atom_id); \ + } while (0) + +/* Trace number of atoms submitted to job slot js + * + * NOTE: This uses a different tracepoint to the head/next/soft-stop actions, + * so that those actions can be filtered out separately from this + * + * This is because this is more useful, as we can use it to calculate general + * utilization easily and accurately */ +#define KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_slot_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_ACTIVE, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + + +/* Trace atoms present in JS_NEXT */ +#define KBASE_TIMELINE_JOB_START_NEXT(kctx, js, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_NEXT, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + +/* Trace atoms present in JS_HEAD */ +#define KBASE_TIMELINE_JOB_START_HEAD(kctx, js, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_HEAD, \ + (int)kctx->timeline.owner_tgid, \ + js, count); \ + } while (0) + +/* Trace that a soft stop/evict from next is being attempted on a slot */ +#define KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_slot_action(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_SLOT_STOPPING, \ + (kctx) ? (int)kctx->timeline.owner_tgid : 0, \ + js, count); \ + } while (0) + + + +/* Trace state of overall GPU power */ +#define KBASE_TIMELINE_GPU_POWER(kbdev, active) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_ACTIVE, active); \ + } while (0) + +/* Trace state of tiler power */ +#define KBASE_TIMELINE_POWER_TILER(kbdev, bitmap) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_TILER_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace number of shaders currently powered */ +#define KBASE_TIMELINE_POWER_SHADER(kbdev, bitmap) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_SHADER_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace state of L2 power */ +#define KBASE_TIMELINE_POWER_L2(kbdev, bitmap) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_gpu_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_SET_GPU_POWER_L2_ACTIVE, \ + hweight64(bitmap)); \ + } while (0) + +/* Trace state of L2 cache*/ +#define KBASE_TIMELINE_POWERING_L2(kbdev) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_l2_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_GPU_POWER_L2_POWERING, \ + 1); \ + } while (0) + +#define KBASE_TIMELINE_POWERED_L2(kbdev) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_l2_power_active(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_GPU_POWER_L2_ACTIVE, \ + 1); \ + } while (0) + +/* Trace kbase_pm_send_event message send */ +#define KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_type, pm_event_id) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_pm_event(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_PM_SEND_EVENT, \ + event_type, pm_event_id); \ + } while (0) + +/* Trace kbase_pm_worker message receive */ +#define KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event_type, pm_event_id) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_pm_event(ts.tv_sec, ts.tv_nsec, \ + SW_FLOW_PM_HANDLE_EVENT, \ + event_type, pm_event_id); \ + } while (0) + + +/* Trace atom_id starting in JS_HEAD */ +#define KBASE_TIMELINE_JOB_START(kctx, js, _consumerof_atom_number) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_slot_atom(ts.tv_sec, ts.tv_nsec, \ + HW_START_GPU_JOB_CHAIN_SW_APPROX, \ + (int)kctx->timeline.owner_tgid, \ + js, _consumerof_atom_number); \ + } while (0) + +/* Trace atom_id stopping on JS_HEAD */ +#define KBASE_TIMELINE_JOB_STOP(kctx, js, _producerof_atom_number_completed) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_slot_atom(ts.tv_sec, ts.tv_nsec, \ + HW_STOP_GPU_JOB_CHAIN_SW_APPROX, \ + (int)kctx->timeline.owner_tgid, \ + js, _producerof_atom_number_completed); \ + } while (0) + +/** Trace beginning/end of a call to kbase_pm_check_transitions_nolock from a + * certin caller */ +#define KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_pm_checktrans(ts.tv_sec, ts.tv_nsec, \ + trace_code, \ + 1); \ + } while (0) + +/* Trace number of contexts active */ +#define KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, count) \ + do \ + { \ + struct timespec ts; \ + getnstimeofday(&ts); \ + trace_mali_timeline_context_active(ts.tv_sec, ts.tv_nsec, \ + count); \ + } while (0) + + +/* NOTE: kbase_timeline_pm_cores_func() is in mali_kbase_pm_policy.c */ + +/** + * Trace that an atom is starting on a job slot + * + * The caller must be holding kbasep_js_device_data::runpool_irq::lock + */ +void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js); + +/** + * Trace that an atom has done on a job slot + * + * 'Done' in this sense can occur either because: + * - the atom in JS_HEAD finished + * - the atom in JS_NEXT was evicted + * + * Whether the atom finished or was evicted is passed in @a done_code + * + * It is assumed that the atom has already been removed from the submit slot, + * with either: + * - kbasep_jm_dequeue_submit_slot() + * - kbasep_jm_dequeue_tail_submit_slot() + * + * The caller must be holding kbasep_js_device_data::runpool_irq::lock + */ +void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code); + + +/** Trace a pm event starting */ +void kbase_timeline_pm_send_event(struct kbase_device *kbdev, + enum kbase_timeline_pm_event event_sent); + +/** Trace a pm event finishing */ +void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event); + +/** Check whether a pm event was present, and if so trace finishing it */ +void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event); + +/** Trace L2 power-up start */ +void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev); + +/** Trace L2 power-up done */ +void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev); + +#else + +#define KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, count) CSTD_NOP() + +#define KBASE_TIMELINE_ATOM_READY(kctx, atom_id) CSTD_NOP() + +#define KBASE_TIMELINE_ATOMS_SUBMITTED(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START_NEXT(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START_HEAD(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, count) CSTD_NOP() + +#define KBASE_TIMELINE_GPU_POWER(kbdev, active) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_TILER(kbdev, bitmap) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_SHADER(kbdev, bitmap) CSTD_NOP() + +#define KBASE_TIMELINE_POWER_L2(kbdev, active) CSTD_NOP() + +#define KBASE_TIMELINE_POWERING_L2(kbdev) CSTD_NOP() + +#define KBASE_TIMELINE_POWERED_L2(kbdev) CSTD_NOP() + +#define KBASE_TIMELINE_PM_SEND_EVENT(kbdev, event_type, pm_event_id) CSTD_NOP() + +#define KBASE_TIMELINE_PM_HANDLE_EVENT(kbdev, event_type, pm_event_id) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_START(kctx, js, _consumerof_atom_number) CSTD_NOP() + +#define KBASE_TIMELINE_JOB_STOP(kctx, js, _producerof_atom_number_completed) CSTD_NOP() + +#define KBASE_TIMELINE_PM_CHECKTRANS(kbdev, trace_code) CSTD_NOP() + +#define KBASE_TIMELINE_CONTEXT_ACTIVE(kbdev, count) CSTD_NOP() + +static INLINE void kbase_timeline_job_slot_submit(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js) +{ + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); +} + +static INLINE void kbase_timeline_job_slot_done(struct kbase_device *kbdev, struct kbase_context *kctx, + struct kbase_jd_atom *katom, int js, + kbasep_js_atom_done_code done_code) +{ + lockdep_assert_held(&kbdev->js_data.runpool_irq.lock); +} + +static INLINE void kbase_timeline_pm_send_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event_sent) +{ +} + +static INLINE void kbase_timeline_pm_check_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ +} + +static INLINE void kbase_timeline_pm_handle_event(struct kbase_device *kbdev, enum kbase_timeline_pm_event event) +{ +} + +static INLINE void kbase_timeline_pm_l2_transition_start(struct kbase_device *kbdev) +{ + +} + +static INLINE void kbase_timeline_pm_l2_transition_done(struct kbase_device *kbdev) +{ + +} +#endif /* CONFIG_MALI_TRACE_TIMELINE */ + +#endif /* _KBASE_TRACE_TIMELINE_H */ + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline_defs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..04d414cd0db95f9a619461f0d6f0d488cc92aed4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_trace_timeline_defs.h @@ -0,0 +1,134 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/* ***** IMPORTANT: THIS IS NOT A NORMAL HEADER FILE ***** + * ***** DO NOT INCLUDE DIRECTLY ***** + * ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ + +/* + * Conventions on Event Names: + * + * - The prefix determines something about how the timeline should be + * displayed, and is split up into various parts, separated by underscores: + * - 'SW' and 'HW' as the first part will be used to determine whether a + * timeline is to do with Software or Hardware - effectively, separate + * 'channels' for Software and Hardware + * - 'START', 'STOP', 'ENTER', 'LEAVE' can be used in the second part, and + * signify related pairs of events - these are optional. + * - 'FLOW' indicates a generic event, which can use dependencies + * - This gives events such as: + * - 'SW_ENTER_FOO' + * - 'SW_LEAVE_FOO' + * - 'SW_FLOW_BAR_1' + * - 'SW_FLOW_BAR_2' + * - 'HW_START_BAZ' + * - 'HW_STOP_BAZ' + * - And an unadorned HW event: + * - 'HW_BAZ_FROZBOZ' + */ + +/* + * Conventions on parameter names: + * - anything with 'instance' in the name will have a separate timeline based + * on that instances. + * - underscored-prefixed parameters will by hidden by default on timelines + * + * Hence: + * - Different job slots have their own 'instance', based on the instance value + * - Per-context info (e.g. atoms on a context) have their own 'instance' + * (i.e. each context should be on a different timeline) + * + * Note that globally-shared resources can be tagged with a tgid, but we don't + * want an instance per context: + * - There's no point having separate Job Slot timelines for each context, that + * would be confusing - there's only really 3 job slots! + * - There's no point having separate Shader-powered timelines for each + * context, that would be confusing - all shader cores (whether it be 4, 8, + * etc) are shared in the system. + */ + + /* + * CTX events + */ + /* Separate timelines for each context 'instance'*/ + KBASE_TIMELINE_TRACE_CODE(CTX_SET_NR_ATOMS_IN_FLIGHT, "CTX: Atoms in flight", "%d,%d", "_instance_tgid,_value_number_of_atoms"), + KBASE_TIMELINE_TRACE_CODE(CTX_FLOW_ATOM_READY, "CTX: Atoms Ready to Run", "%d,%d,%d", "_instance_tgid,_consumerof_atom_number,_producerof_atom_number_ready"), + + /* + * SW Events + */ + /* Separate timelines for each slot 'instance' */ + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_ACTIVE, "SW: GPU slot active", "%d,%d,%d", "_tgid,_instance_slot,_value_number_of_atoms"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_NEXT, "SW: GPU atom in NEXT", "%d,%d,%d", "_tgid,_instance_slot,_value_is_an_atom_in_next"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_HEAD, "SW: GPU atom in HEAD", "%d,%d,%d", "_tgid,_instance_slot,_value_is_an_atom_in_head"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_SLOT_STOPPING, "SW: Try Soft-Stop on GPU slot", "%d,%d,%d", "_tgid,_instance_slot,_value_is_slot_stopping"), + /* Shader and overall power is shared - can't have separate instances of + * it, just tagging with the context */ + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_ACTIVE, "SW: GPU power active", "%d,%d", "_tgid,_value_is_power_active"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_TILER_ACTIVE, "SW: GPU tiler powered", "%d,%d", "_tgid,_value_number_of_tilers"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_SHADER_ACTIVE, "SW: GPU shaders powered", "%d,%d", "_tgid,_value_number_of_shaders"), + KBASE_TIMELINE_TRACE_CODE(SW_SET_GPU_POWER_L2_ACTIVE, "SW: GPU L2 powered", "%d,%d", "_tgid,_value_number_of_l2"), + + /* SW Power event messaging. _event_type is one from the kbase_pm_event enum */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_SEND_EVENT, "SW: PM Send Event", "%d,%d,%d", "_tgid,_event_type,_writerof_pm_event_id"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_HANDLE_EVENT, "SW: PM Handle Event", "%d,%d,%d", "_tgid,_event_type,_finalconsumerof_pm_event_id"), + /* SW L2 power events */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_GPU_POWER_L2_POWERING, "SW: GPU L2 powering", "%d,%d", "_tgid,_writerof_l2_transitioning"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_GPU_POWER_L2_ACTIVE, "SW: GPU L2 powering done", "%d,%d", "_tgid,_finalconsumerof_l2_transitioning"), + + KBASE_TIMELINE_TRACE_CODE(SW_SET_CONTEXT_ACTIVE, "SW: Context Active", "%d,%d", "_tgid,_value_active"), + + /* + * BEGIN: Significant SW Functions that call kbase_pm_check_transitions_nolock() + */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_START, "SW: PM CheckTrans from kbase_pm_do_poweroff", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_poweroff"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWEROFF_END, "SW: PM CheckTrans from kbase_pm_do_poweroff", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_poweroff"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_START, "SW: PM CheckTrans from kbase_pm_do_poweron", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_poweron"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_DO_POWERON_END, "SW: PM CheckTrans from kbase_pm_do_poweron", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_poweron"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_START, "SW: PM CheckTrans from kbase_gpu_interrupt", "%d,%d", "_tgid,_writerof_pm_checktrans_gpu_interrupt"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_END, "SW: PM CheckTrans from kbase_gpu_interrupt", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_gpu_interrupt"), + + /* + * Significant Indirect callers of kbase_pm_check_transitions_nolock() + */ + /* kbase_pm_request_cores */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_START, "SW: PM CheckTrans from kbase_pm_request_cores(shader)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_END, "SW: PM CheckTrans from kbase_pm_request_cores(shader)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_START, "SW: PM CheckTrans from kbase_pm_request_cores(tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_TILER_END, "SW: PM CheckTrans from kbase_pm_request_cores(tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_START, "SW: PM CheckTrans from kbase_pm_request_cores(shader+tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_request_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_REQUEST_CORES_SHADER_TILER_END, "SW: PM CheckTrans from kbase_pm_request_cores(shader+tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_request_cores_shader_tiler"), + /* kbase_pm_release_cores */ + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_START, "SW: PM CheckTrans from kbase_pm_release_cores(shader)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_END, "SW: PM CheckTrans from kbase_pm_release_cores(shader)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_shader"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_START, "SW: PM CheckTrans from kbase_pm_release_cores(tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_TILER_END, "SW: PM CheckTrans from kbase_pm_release_cores(tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_START, "SW: PM CheckTrans from kbase_pm_release_cores(shader+tiler)", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_release_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_SHADER_TILER_END, "SW: PM CheckTrans from kbase_pm_release_cores(shader+tiler)", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_release_cores_shader_tiler"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_START, "SW: PM CheckTrans from kbasep_pm_do_shader_poweroff_callback", "%d,%d", "_tgid,_writerof_pm_checktrans_pm_do_shader_poweroff_callback"), + KBASE_TIMELINE_TRACE_CODE(SW_FLOW_PM_CHECKTRANS_PM_RELEASE_CORES_DEFERRED_END, "SW: PM CheckTrans from kbasep_pm_do_shader_poweroff_callback", "%d,%d", "_tgid,_finalconsumerof_pm_checktrans_pm_do_shader_poweroff_callback"), + /* + * END: SW Functions that call kbase_pm_check_transitions_nolock() + */ + + /* + * HW Events + */ + KBASE_TIMELINE_TRACE_CODE(HW_START_GPU_JOB_CHAIN_SW_APPROX, "HW: Job Chain start (SW approximated)", "%d,%d,%d", "_tgid,job_slot,_consumerof_atom_number_ready"), + KBASE_TIMELINE_TRACE_CODE(HW_STOP_GPU_JOB_CHAIN_SW_APPROX, "HW: Job Chain stop (SW approximated)", "%d,%d,%d", "_tgid,job_slot,_producerof_atom_number_completed") diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_uku.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_uku.h new file mode 100644 index 0000000000000000000000000000000000000000..0e2fecf33d77c8accabb1a615024b387b12a2c1b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_uku.h @@ -0,0 +1,477 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_UKU_H_ +#define _KBASE_UKU_H_ + +#include "mali_uk.h" +#include +#include "mali_base_kernel.h" + +/* This file needs to support being included from kernel and userside (which use different defines) */ +#if defined(CONFIG_MALI_ERROR_INJECT) +#define SUPPORT_MALI_ERROR_INJECT +#elif defined(MALI_ERROR_INJECT) +#if MALI_ERROR_INJECT +#define SUPPORT_MALI_ERROR_INJECT +#endif +#endif +#if defined(CONFIG_MALI_NO_MALI) +#define SUPPORT_MALI_NO_MALI +#elif defined(MALI_NO_MALI) +#if MALI_NO_MALI +#define SUPPORT_MALI_NO_MALI +#endif +#endif + +#if defined(SUPPORT_MALI_NO_MALI) || defined(SUPPORT_MALI_ERROR_INJECT) +#include "mali_kbase_model_dummy.h" +#endif + +#include "mali_kbase_gpuprops_types.h" + +#define BASE_UK_VERSION_MAJOR 8 +#define BASE_UK_VERSION_MINOR 0 + +struct kbase_uk_mem_alloc { + union uk_header header; + /* IN */ + u64 va_pages; + u64 commit_pages; + u64 extent; + /* IN/OUT */ + u64 flags; + /* OUT */ + u64 gpu_va; + u16 va_alignment; + u8 padding[6]; +}; + +struct kbase_uk_mem_free { + union uk_header header; + /* IN */ + mali_addr64 gpu_addr; + /* OUT */ +}; + +struct kbase_uk_mem_alias { + union uk_header header; + /* IN/OUT */ + u64 flags; + /* IN */ + u64 stride; + u64 nents; + union kbase_pointer ai; + /* OUT */ + u64 gpu_va; + u64 va_pages; +}; + +struct kbase_uk_mem_import { + union uk_header header; + /* IN */ + union kbase_pointer phandle; + u32 type; + u32 padding; + /* IN/OUT */ + u64 flags; + /* OUT */ + mali_addr64 gpu_va; + u64 va_pages; +}; + +struct kbase_uk_mem_flags_change { + union uk_header header; + /* IN */ + mali_addr64 gpu_va; + u64 flags; + u64 mask; +}; + +struct kbase_uk_job_submit { + union uk_header header; + /* IN */ + union kbase_pointer addr; + u32 nr_atoms; + u32 stride; /* bytes between atoms, i.e. sizeof(base_jd_atom_v2) */ + /* OUT */ +}; + +struct kbase_uk_post_term { + union uk_header header; +}; + +struct kbase_uk_sync_now { + union uk_header header; + + /* IN */ + struct base_syncset sset; + + /* OUT */ +}; + +struct kbase_uk_hwcnt_setup { + union uk_header header; + + /* IN */ + mali_addr64 dump_buffer; + u32 jm_bm; + u32 shader_bm; + u32 tiler_bm; + u32 l3_cache_bm; + u32 mmu_l2_bm; + u32 padding; + /* OUT */ +}; + +struct kbase_uk_hwcnt_dump { + union uk_header header; +}; + +struct kbase_uk_hwcnt_clear { + union uk_header header; +}; + +struct kbase_uk_fence_validate { + union uk_header header; + /* IN */ + s32 fd; + u32 padding; + /* OUT */ +}; + +struct kbase_uk_stream_create { + union uk_header header; + /* IN */ + char name[32]; + /* OUT */ + s32 fd; + u32 padding; +}; + +#ifdef BASE_LEGACY_UK7_SUPPORT +/** + * This structure is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ +#define BASE_CPU_PROPERTY_FLAG_LITTLE_ENDIAN F_BIT_0 +struct base_cpu_id_props { + /** + * CPU ID + */ + u32 id; + + /** + * CPU Part number + */ + u16 part; + /** + * ASCII code of implementer trademark + */ + u8 implementer; + + /** + * CPU Variant + */ + u8 variant; + /** + * CPU Architecture + */ + u8 arch; + + /** + * CPU revision + */ + u8 rev; + + /** + * Validity of CPU id where 0-invalid and + * 1-valid only if ALL the cpu_id props are valid + */ + u8 valid; + + u8 padding[1]; +}; + +/** + * This structure is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ +struct base_cpu_props { + u32 nr_cores; /**< Number of CPU cores */ + + /** + * CPU page size as a Logarithm to Base 2. The compile-time + * equivalent is @ref OSU_CONFIG_CPU_PAGE_SIZE_LOG2 + */ + u32 cpu_page_size_log2; + + /** + * CPU L1 Data cache line size as a Logarithm to Base 2. The compile-time + * equivalent is @ref OSU_CONFIG_CPU_L1_DCACHE_LINE_SIZE_LOG2. + */ + u32 cpu_l1_dcache_line_size_log2; + + /** + * CPU L1 Data cache size, in bytes. The compile-time equivalient is + * @ref OSU_CONFIG_CPU_L1_DCACHE_SIZE. + * + * This CPU Property is mainly provided to implement OpenCL's + * clGetDeviceInfo(), which allows the CL_DEVICE_GLOBAL_MEM_CACHE_SIZE + * hint to be queried. + */ + u32 cpu_l1_dcache_size; + + /** + * CPU Property Flags bitpattern. + * + * This is a combination of bits as specified by the macros prefixed with + * 'BASE_CPU_PROPERTY_FLAG_'. + */ + u32 cpu_flags; + + /** + * Maximum clock speed in MHz. + * @usecase 'Maximum' CPU Clock Speed information is required by OpenCL's + * clGetDeviceInfo() function for the CL_DEVICE_MAX_CLOCK_FREQUENCY hint. + */ + u32 max_cpu_clock_speed_mhz; + + /** + * @brief Total memory, in bytes. + * + * This is the theoretical maximum memory available to the CPU. It is + * unlikely that a client will be able to allocate all of this memory for + * their own purposes, but this at least provides an upper bound on the + * memory available to the CPU. + * + * This is required for OpenCL's clGetDeviceInfo() call when + * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL CPU devices. + */ + u64 available_memory_size; + + /** + * CPU ID detailed info + */ + struct base_cpu_id_props cpu_id; + + u32 padding; +}; + +/** + * This structure is kept for the backward compatibility reasons. + * It shall be removed as soon as KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE + * (previously KBASE_FUNC_CPU_PROPS_REG_DUMP) ioctl call + * is removed. Removal of KBASE_FUNC_CPU_PROPS_REG_DUMP is part of having + * the function for reading cpu properties moved from base to osu. + */ +struct kbase_uk_cpuprops { + union uk_header header; + + /* IN */ + struct base_cpu_props props; + /* OUT */ +}; +#endif /* BASE_LEGACY_UK7_SUPPORT */ + +struct kbase_uk_gpuprops { + union uk_header header; + + /* IN */ + struct mali_base_gpu_props props; + /* OUT */ +}; + +struct kbase_uk_mem_query { + union uk_header header; + /* IN */ + mali_addr64 gpu_addr; +#define KBASE_MEM_QUERY_COMMIT_SIZE 1 +#define KBASE_MEM_QUERY_VA_SIZE 2 +#define KBASE_MEM_QUERY_FLAGS 3 + u64 query; + /* OUT */ + u64 value; +}; + +struct kbase_uk_mem_commit { + union uk_header header; + /* IN */ + mali_addr64 gpu_addr; + u64 pages; + /* OUT */ + u32 result_subcode; + u32 padding; +}; + +struct kbase_uk_find_cpu_offset { + union uk_header header; + /* IN */ + mali_addr64 gpu_addr; + u64 cpu_addr; + u64 size; + /* OUT */ + mali_size64 offset; +}; + +#define KBASE_GET_VERSION_BUFFER_SIZE 64 +struct kbase_uk_get_ddk_version { + union uk_header header; + /* OUT */ + char version_buffer[KBASE_GET_VERSION_BUFFER_SIZE]; + u32 version_string_size; + u32 padding; +}; + +struct kbase_uk_disjoint_query { + union uk_header header; + /* OUT */ + u32 counter; + u32 padding; +}; + +struct kbase_uk_set_flags { + union uk_header header; + /* IN */ + u32 create_flags; + u32 padding; +}; + +#if MALI_UNIT_TEST +#define TEST_ADDR_COUNT 4 +#define KBASE_TEST_BUFFER_SIZE 128 +typedef struct kbase_exported_test_data { + mali_addr64 test_addr[TEST_ADDR_COUNT]; /**< memory address */ + u32 test_addr_pages[TEST_ADDR_COUNT]; /**< memory size in pages */ + union kbase_pointer kctx; /**< base context created by process */ + union kbase_pointer mm; /**< pointer to process address space */ + u8 buffer1[KBASE_TEST_BUFFER_SIZE]; /**< unit test defined parameter */ + u8 buffer2[KBASE_TEST_BUFFER_SIZE]; /**< unit test defined parameter */ +} kbase_exported_test_data; + +struct kbase_uk_set_test_data { + union uk_header header; + /* IN */ + struct kbase_exported_test_data test_data; +}; + +#endif /* MALI_UNIT_TEST */ + +#ifdef SUPPORT_MALI_ERROR_INJECT +struct kbase_uk_error_params { + union uk_header header; + /* IN */ + struct kbase_error_params params; +}; +#endif /* SUPPORT_MALI_ERROR_INJECT */ + +#ifdef SUPPORT_MALI_NO_MALI +struct kbase_uk_model_control_params { + union uk_header header; + /* IN */ + struct kbase_model_control_params params; +}; +#endif /* SUPPORT_MALI_NO_MALI */ + +#define KBASE_MAXIMUM_EXT_RESOURCES 255 + +struct kbase_uk_ext_buff_kds_data { + union uk_header header; + union kbase_pointer external_resource; + union kbase_pointer file_descriptor; + u32 num_res; /* limited to KBASE_MAXIMUM_EXT_RESOURCES */ + u32 padding; +}; + +struct kbase_uk_keep_gpu_powered { + union uk_header header; + u32 enabled; + u32 padding; +}; + +struct kbase_uk_profiling_controls { + union uk_header header; + u32 profiling_controls[FBDUMP_CONTROL_MAX]; +}; + +struct kbase_uk_debugfs_mem_profile_add { + union uk_header header; + u32 len; + union kbase_pointer buf; +}; + +enum kbase_uk_function_id { + KBASE_FUNC_MEM_ALLOC = (UK_FUNC_ID + 0), + KBASE_FUNC_MEM_IMPORT = (UK_FUNC_ID + 1), + KBASE_FUNC_MEM_COMMIT = (UK_FUNC_ID + 2), + KBASE_FUNC_MEM_QUERY = (UK_FUNC_ID + 3), + KBASE_FUNC_MEM_FREE = (UK_FUNC_ID + 4), + KBASE_FUNC_MEM_FLAGS_CHANGE = (UK_FUNC_ID + 5), + KBASE_FUNC_MEM_ALIAS = (UK_FUNC_ID + 6), + +#ifdef BASE_LEGACY_UK6_SUPPORT + KBASE_FUNC_JOB_SUBMIT_UK6 = (UK_FUNC_ID + 7), +#endif /* BASE_LEGACY_UK6_SUPPORT */ + + KBASE_FUNC_SYNC = (UK_FUNC_ID + 8), + + KBASE_FUNC_POST_TERM = (UK_FUNC_ID + 9), + + KBASE_FUNC_HWCNT_SETUP = (UK_FUNC_ID + 10), + KBASE_FUNC_HWCNT_DUMP = (UK_FUNC_ID + 11), + KBASE_FUNC_HWCNT_CLEAR = (UK_FUNC_ID + 12), + +#ifdef BASE_LEGACY_UK7_SUPPORT + KBASE_FUNC_CPU_PROPS_REG_DUMP_OBSOLETE = (UK_FUNC_ID + 13), +#endif /* BASE_LEGACY_UK7_SUPPORT */ + KBASE_FUNC_GPU_PROPS_REG_DUMP = (UK_FUNC_ID + 14), + + KBASE_FUNC_FIND_CPU_OFFSET = (UK_FUNC_ID + 15), + + KBASE_FUNC_GET_VERSION = (UK_FUNC_ID + 16), + KBASE_FUNC_EXT_BUFFER_LOCK = (UK_FUNC_ID + 17), + KBASE_FUNC_SET_FLAGS = (UK_FUNC_ID + 18), + + KBASE_FUNC_SET_TEST_DATA = (UK_FUNC_ID + 19), + KBASE_FUNC_INJECT_ERROR = (UK_FUNC_ID + 20), + KBASE_FUNC_MODEL_CONTROL = (UK_FUNC_ID + 21), + + KBASE_FUNC_KEEP_GPU_POWERED = (UK_FUNC_ID + 22), + + KBASE_FUNC_FENCE_VALIDATE = (UK_FUNC_ID + 23), + KBASE_FUNC_STREAM_CREATE = (UK_FUNC_ID + 24), + KBASE_FUNC_GET_PROFILING_CONTROLS = (UK_FUNC_ID + 25), + KBASE_FUNC_SET_PROFILING_CONTROLS = (UK_FUNC_ID + 26), + /* to be used only for testing + * purposes, otherwise these controls + * are set through gator API */ + + KBASE_FUNC_DEBUGFS_MEM_PROFILE_ADD = (UK_FUNC_ID + 27), + KBASE_FUNC_JOB_SUBMIT = (UK_FUNC_ID + 28), + KBASE_FUNC_DISJOINT_QUERY = (UK_FUNC_ID + 29) + +}; + +#endif /* _KBASE_UKU_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.c new file mode 100644 index 0000000000000000000000000000000000000000..d159872306c5ccbf6059b9b62718819c191af5a7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.c @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include + +mali_bool kbasep_list_member_of(const struct list_head *base, struct list_head *entry) +{ + struct list_head *pos = base->next; + + while (pos != base) { + if (pos == entry) + return MALI_TRUE; + + pos = pos->next; + } + return MALI_FALSE; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.h new file mode 100644 index 0000000000000000000000000000000000000000..59988163fd2eb1fa2f70d0af6f67f36e6aa8fcb9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_kbase_utility.h @@ -0,0 +1,37 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_UTILITY_H +#define _KBASE_UTILITY_H + +#ifndef _KBASE_H_ +#error "Don't include this file directly, use mali_kbase.h instead" +#endif + +/** Test whether the given list entry is a member of the given list. + * + * @param base The head of the list to be tested + * @param entry The list entry to be tested + * + * @return MALI_TRUE if entry is a member of base + * MALI_FALSE otherwise + */ +mali_bool kbasep_list_member_of(const struct list_head *base, struct list_head *entry); + +#endif /* _KBASE_UTILITY_H */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_linux_kbase_trace.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_linux_kbase_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..20250592dd632c9965175209c74bbc0549b76e80 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_linux_kbase_trace.h @@ -0,0 +1,201 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#if !defined(_TRACE_MALI_KBASE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MALI_KBASE_H + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali + +#include + +DECLARE_EVENT_CLASS(mali_slot_template, + TP_PROTO(int jobslot, unsigned int info_val), + TP_ARGS(jobslot, info_val), + TP_STRUCT__entry( + __field(unsigned int, jobslot) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->jobslot = jobslot; + __entry->info_val = info_val; + ), + TP_printk("jobslot=%u info=%u", __entry->jobslot, __entry->info_val) +); + +#define DEFINE_MALI_SLOT_EVENT(name) \ +DEFINE_EVENT(mali_slot_template, mali_##name, \ + TP_PROTO(int jobslot, unsigned int info_val), \ + TP_ARGS(jobslot, info_val)) +DEFINE_MALI_SLOT_EVENT(JM_SUBMIT); +DEFINE_MALI_SLOT_EVENT(JM_JOB_DONE); +DEFINE_MALI_SLOT_EVENT(JM_UPDATE_HEAD); +DEFINE_MALI_SLOT_EVENT(JM_CHECK_HEAD); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP_0); +DEFINE_MALI_SLOT_EVENT(JM_SOFTSTOP_1); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP_0); +DEFINE_MALI_SLOT_EVENT(JM_HARDSTOP_1); +DEFINE_MALI_SLOT_EVENT(JM_SLOT_SOFT_OR_HARD_STOP); +DEFINE_MALI_SLOT_EVENT(JM_SLOT_EVICT); +DEFINE_MALI_SLOT_EVENT(JM_BEGIN_RESET_WORKER); +DEFINE_MALI_SLOT_EVENT(JM_END_RESET_WORKER); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REGISTER_ON_RECHECK_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_AFFINITY_SUBMIT_TO_BLOCKED); +DEFINE_MALI_SLOT_EVENT(JS_AFFINITY_CURRENT); +DEFINE_MALI_SLOT_EVENT(JD_DONE_TRY_RUN_NEXT_JOB); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REQUEST_CORES_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REGISTER_INUSE_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_REQUEST_ON_RECHECK_FAILED); +DEFINE_MALI_SLOT_EVENT(JS_CORE_REF_AFFINITY_WOULD_VIOLATE); +DEFINE_MALI_SLOT_EVENT(JS_JOB_DONE_TRY_RUN_NEXT_JOB); +DEFINE_MALI_SLOT_EVENT(JS_JOB_DONE_RETRY_NEEDED); +DEFINE_MALI_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB); +DEFINE_MALI_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB_IRQ); +#undef DEFINE_MALI_SLOT_EVENT + +DECLARE_EVENT_CLASS(mali_refcount_template, + TP_PROTO(int refcount, unsigned int info_val), + TP_ARGS(refcount, info_val), + TP_STRUCT__entry( + __field(unsigned int, refcount) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->refcount = refcount; + __entry->info_val = info_val; + ), + TP_printk("refcount=%u info=%u", __entry->refcount, __entry->info_val) +); + +#define DEFINE_MALI_REFCOUNT_EVENT(name) \ +DEFINE_EVENT(mali_refcount_template, mali_##name, \ + TP_PROTO(int refcount, unsigned int info_val), \ + TP_ARGS(refcount, info_val)) +DEFINE_MALI_REFCOUNT_EVENT(JS_RETAIN_CTX_NOLOCK); +DEFINE_MALI_REFCOUNT_EVENT(JS_ADD_JOB); +DEFINE_MALI_REFCOUNT_EVENT(JS_REMOVE_JOB); +DEFINE_MALI_REFCOUNT_EVENT(JS_RETAIN_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_RELEASE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_TRY_SCHEDULE_HEAD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_INIT_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_TERM_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_ENQUEUE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_DEQUEUE_HEAD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_TRY_EVICT_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_RUNPOOL_ADD_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_RUNPOOL_REMOVE_CTX); +DEFINE_MALI_REFCOUNT_EVENT(JS_POLICY_FOREACH_CTX_JOBS); +DEFINE_MALI_REFCOUNT_EVENT(PM_CONTEXT_ACTIVE); +DEFINE_MALI_REFCOUNT_EVENT(PM_CONTEXT_IDLE); +#undef DEFINE_MALI_REFCOUNT_EVENT + +DECLARE_EVENT_CLASS(mali_add_template, + TP_PROTO(int gpu_addr, unsigned int info_val), + TP_ARGS(gpu_addr, info_val), + TP_STRUCT__entry( + __field(unsigned int, gpu_addr) + __field(unsigned int, info_val) + ), + TP_fast_assign( + __entry->gpu_addr = gpu_addr; + __entry->info_val = info_val; + ), + TP_printk("gpu_addr=%u info=%u", __entry->gpu_addr, __entry->info_val) +); + +#define DEFINE_MALI_ADD_EVENT(name) \ +DEFINE_EVENT(mali_add_template, mali_##name, \ + TP_PROTO(int gpu_addr, unsigned int info_val), \ + TP_ARGS(gpu_addr, info_val)) +DEFINE_MALI_ADD_EVENT(CORE_CTX_DESTROY); +DEFINE_MALI_ADD_EVENT(CORE_CTX_HWINSTR_TERM); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ_CLEAR); +DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ_DONE); +DEFINE_MALI_ADD_EVENT(CORE_GPU_SOFT_RESET); +DEFINE_MALI_ADD_EVENT(CORE_GPU_HARD_RESET); +DEFINE_MALI_ADD_EVENT(CORE_GPU_PRFCNT_SAMPLE); +DEFINE_MALI_ADD_EVENT(CORE_GPU_PRFCNT_CLEAR); +DEFINE_MALI_ADD_EVENT(CORE_GPU_CLEAN_INV_CACHES); +DEFINE_MALI_ADD_EVENT(JD_DONE_WORKER); +DEFINE_MALI_ADD_EVENT(JD_DONE_WORKER_END); +DEFINE_MALI_ADD_EVENT(JD_CANCEL_WORKER); +DEFINE_MALI_ADD_EVENT(JD_DONE); +DEFINE_MALI_ADD_EVENT(JD_CANCEL); +DEFINE_MALI_ADD_EVENT(JD_ZAP_CONTEXT); +DEFINE_MALI_ADD_EVENT(JM_IRQ); +DEFINE_MALI_ADD_EVENT(JM_IRQ_END); +DEFINE_MALI_ADD_EVENT(JM_FLUSH_WORKQS); +DEFINE_MALI_ADD_EVENT(JM_FLUSH_WORKQS_DONE); +DEFINE_MALI_ADD_EVENT(JM_ZAP_NON_SCHEDULED); +DEFINE_MALI_ADD_EVENT(JM_ZAP_SCHEDULED); +DEFINE_MALI_ADD_EVENT(JM_ZAP_DONE); +DEFINE_MALI_ADD_EVENT(JM_SUBMIT_AFTER_RESET); +DEFINE_MALI_ADD_EVENT(JM_JOB_COMPLETE); +DEFINE_MALI_ADD_EVENT(JS_FAST_START_EVICTS_CTX); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_ON_RUNPOOL); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_OFF_RUNPOOL); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_ON_CTX); +DEFINE_MALI_ADD_EVENT(JS_CTX_ATTR_NOW_OFF_CTX); +DEFINE_MALI_ADD_EVENT(JS_POLICY_TIMER_END); +DEFINE_MALI_ADD_EVENT(JS_POLICY_TIMER_START); +DEFINE_MALI_ADD_EVENT(JS_POLICY_ENQUEUE_JOB); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_DESIRED); +DEFINE_MALI_ADD_EVENT(PM_JOB_SUBMIT_AFTER_POWERING_UP); +DEFINE_MALI_ADD_EVENT(PM_JOB_SUBMIT_AFTER_POWERED_UP); +DEFINE_MALI_ADD_EVENT(PM_PWRON); +DEFINE_MALI_ADD_EVENT(PM_PWRON_TILER); +DEFINE_MALI_ADD_EVENT(PM_PWRON_L2); +DEFINE_MALI_ADD_EVENT(PM_PWROFF); +DEFINE_MALI_ADD_EVENT(PM_PWROFF_TILER); +DEFINE_MALI_ADD_EVENT(PM_PWROFF_L2); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED_TILER); +DEFINE_MALI_ADD_EVENT(PM_CORES_POWERED_L2); +DEFINE_MALI_ADD_EVENT(PM_DESIRED_REACHED); +DEFINE_MALI_ADD_EVENT(PM_DESIRED_REACHED_TILER); +DEFINE_MALI_ADD_EVENT(PM_UNREQUEST_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REQUEST_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REGISTER_CHANGE_SHADER_NEEDED); +DEFINE_MALI_ADD_EVENT(PM_REGISTER_CHANGE_SHADER_INUSE); +DEFINE_MALI_ADD_EVENT(PM_RELEASE_CHANGE_SHADER_INUSE); +DEFINE_MALI_ADD_EVENT(PM_CORES_AVAILABLE); +DEFINE_MALI_ADD_EVENT(PM_CORES_AVAILABLE_TILER); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE); +DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE_TILER); +DEFINE_MALI_ADD_EVENT(PM_GPU_ON); +DEFINE_MALI_ADD_EVENT(PM_GPU_OFF); +DEFINE_MALI_ADD_EVENT(PM_SET_POLICY); +DEFINE_MALI_ADD_EVENT(PM_CURRENT_POLICY_INIT); +DEFINE_MALI_ADD_EVENT(PM_CURRENT_POLICY_TERM); +DEFINE_MALI_ADD_EVENT(PM_CA_SET_POLICY); +DEFINE_MALI_ADD_EVENT(PM_WAKE_WAITERS); +#undef DEFINE_MALI_ADD_EVENT + +#endif /* _TRACE_MALI_KBASE_H */ + +#undef TRACE_INCLUDE_PATH +#undef linux +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mali_linux_kbase_trace + +/* This part must be outside protection */ +#include diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_linux_trace.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_linux_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..62207a45a898e77754d342e8f8a981b6b1a7b7ab --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_linux_trace.h @@ -0,0 +1,129 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#if !defined(_TRACE_MALI_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MALI_H + +#include +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali +#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM) +#define TRACE_INCLUDE_FILE mali_linux_trace + +#define MALI_JOB_SLOTS_EVENT_CHANGED + +/** + * mali_job_slots_event - called from mali_kbase_core_linux.c + * @event_id: ORed together bitfields representing a type of event, made with the GATOR_MAKE_EVENT() macro. + */ +TRACE_EVENT(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char atom_id, u32 job_id), TP_ARGS(event_id, tgid, pid, atom_id, job_id), TP_STRUCT__entry(__field(unsigned int, event_id) + __field(unsigned int, tgid) + __field(unsigned int, pid) + __field(unsigned char, job_id) + ), TP_fast_assign(__entry->event_id = event_id; __entry->tgid = tgid; __entry->pid = pid; __entry->atom_id = atom_id; __entry->job_id = job_id;), TP_printk("event=%u tgid=%u pid=%u atom_id=%u job_id=%u", __entry->event_id, __entry->tgid, __entry->pid, __entry->atom_id, __entry->job_id) + ); + +/** + * mali_pm_status - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache, l3 cache) + * @value: 64bits bitmask reporting either power status of the cores (1-ON, 0-OFF) + */ +TRACE_EVENT(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(unsigned int, event_id) + __field(unsigned long long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %u = %llu", __entry->event_id, __entry->value) + ); + +/** + * mali_pm_power_on - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache, l3 cache) + * @value: 64bits bitmask reporting the cores to power up + */ +TRACE_EVENT(mali_pm_power_on, TP_PROTO(unsigned int event_id, unsigned long long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(unsigned int, event_id) + __field(unsigned long long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %u = %llu", __entry->event_id, __entry->value) + ); + +/** + * mali_pm_power_off - Called by mali_kbase_pm_driver.c + * @event_id: core type (shader, tiler, l2 cache, l3 cache) + * @value: 64bits bitmask reporting the cores to power down + */ +TRACE_EVENT(mali_pm_power_off, TP_PROTO(unsigned int event_id, unsigned long long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(unsigned int, event_id) + __field(unsigned long long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %u = %llu", __entry->event_id, __entry->value) + ); + +/** + * mali_page_fault_insert_pages - Called by page_fault_worker() + * it reports an MMU page fault resulting in new pages being mapped. + * @event_id: MMU address space number. + * @value: number of newly allocated pages + */ +TRACE_EVENT(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(int, event_id) + __field(unsigned long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %d = %lu", __entry->event_id, __entry->value) + ); + +/** + * mali_mmu_as_in_use - Called by assign_and_activate_kctx_addr_space() + * it reports that a certain MMU address space is in use now. + * @event_id: MMU address space number. + */ +TRACE_EVENT(mali_mmu_as_in_use, TP_PROTO(int event_id), TP_ARGS(event_id), TP_STRUCT__entry(__field(int, event_id) + ), TP_fast_assign(__entry->event_id = event_id;), TP_printk("event=%d", __entry->event_id) + ); + +/** + * mali_mmu_as_released - Called by kbasep_js_runpool_release_ctx_internal() + * it reports that a certain MMU address space has been released now. + * @event_id: MMU address space number. + */ +TRACE_EVENT(mali_mmu_as_released, TP_PROTO(int event_id), TP_ARGS(event_id), TP_STRUCT__entry(__field(int, event_id) + ), TP_fast_assign(__entry->event_id = event_id;), TP_printk("event=%d", __entry->event_id) + ); + +/** + * mali_total_alloc_pages_change - Called by kbase_atomic_add_pages() + * and by kbase_atomic_sub_pages() + * it reports that the total number of allocated pages is changed. + * @event_id: number of pages to be added or subtracted (according to the sign). + */ +TRACE_EVENT(mali_total_alloc_pages_change, TP_PROTO(long long int event_id), TP_ARGS(event_id), TP_STRUCT__entry(__field(long long int, event_id) + ), TP_fast_assign(__entry->event_id = event_id;), TP_printk("event=%lld", __entry->event_id) + ); + +/** + * mali_sw_counter - not currently used + * @event_id: counter id + */ +TRACE_EVENT(mali_sw_counter, TP_PROTO(unsigned int event_id, signed long long value), TP_ARGS(event_id, value), TP_STRUCT__entry(__field(int, event_id) + __field(long long, value) + ), TP_fast_assign(__entry->event_id = event_id; __entry->value = value;), TP_printk("event %d = %lld", __entry->event_id, __entry->value) + ); + +#endif /* _TRACE_MALI_H */ + +#undef TRACE_INCLUDE_PATH +#undef linux +#define TRACE_INCLUDE_PATH . + +/* This part must be outside protection */ +#include diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_midg_regmap.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_midg_regmap.h new file mode 100644 index 0000000000000000000000000000000000000000..0fe90770ddcbd2ab414971bcfa77ba4329fc2b2e --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_midg_regmap.h @@ -0,0 +1,525 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _MIDGARD_REGMAP_H_ +#define _MIDGARD_REGMAP_H_ + +/* + * Begin Register Offsets + */ + +#define GPU_CONTROL_BASE 0x0000 +#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r)) +#define GPU_ID 0x000 /* (RO) GPU and revision identifier */ +#define L2_FEATURES 0x004 /* (RO) Level 2 cache features */ +#define L3_FEATURES 0x008 /* (RO) Level 3 cache features */ +#define TILER_FEATURES 0x00C /* (RO) Tiler Features */ +#define MEM_FEATURES 0x010 /* (RO) Memory system features */ +#define MMU_FEATURES 0x014 /* (RO) MMU features */ +#define AS_PRESENT 0x018 /* (RO) Address space slots present */ +#define JS_PRESENT 0x01C /* (RO) Job slots present */ +#define GPU_IRQ_RAWSTAT 0x020 /* (RW) */ +#define GPU_IRQ_CLEAR 0x024 /* (WO) */ +#define GPU_IRQ_MASK 0x028 /* (RW) */ +#define GPU_IRQ_STATUS 0x02C /* (RO) */ + +/* IRQ flags */ +#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */ +#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */ +#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. Intended to use with SOFT_RESET + commands which may take time. */ +#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */ +#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down + and the power manager is idle. */ + +#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */ +#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */ + +#define GPU_IRQ_REG_ALL (GPU_FAULT | MULTIPLE_GPU_FAULTS | RESET_COMPLETED \ + | POWER_CHANGED_ALL | PRFCNT_SAMPLE_COMPLETED) + +#define GPU_COMMAND 0x030 /* (WO) */ +#define GPU_STATUS 0x034 /* (RO) */ + +#define GROUPS_L2_COHERENT (1 << 0) /* Cores groups are l2 coherent */ +#define GROUPS_L3_COHERENT (1 << 1) /* Cores groups are l3 coherent */ + +#define GPU_FAULTSTATUS 0x03C /* (RO) GPU exception type and fault status */ +#define GPU_FAULTADDRESS_LO 0x040 /* (RO) GPU exception fault address, low word */ +#define GPU_FAULTADDRESS_HI 0x044 /* (RO) GPU exception fault address, high word */ + +#define PWR_KEY 0x050 /* (WO) Power manager key register */ +#define PWR_OVERRIDE0 0x054 /* (RW) Power manager override settings */ +#define PWR_OVERRIDE1 0x058 /* (RW) Power manager override settings */ + +#define PRFCNT_BASE_LO 0x060 /* (RW) Performance counter memory region base address, low word */ +#define PRFCNT_BASE_HI 0x064 /* (RW) Performance counter memory region base address, high word */ +#define PRFCNT_CONFIG 0x068 /* (RW) Performance counter configuration */ +#define PRFCNT_JM_EN 0x06C /* (RW) Performance counter enable flags for Job Manager */ +#define PRFCNT_SHADER_EN 0x070 /* (RW) Performance counter enable flags for shader cores */ +#define PRFCNT_TILER_EN 0x074 /* (RW) Performance counter enable flags for tiler */ +#define PRFCNT_L3_CACHE_EN 0x078 /* (RW) Performance counter enable flags for L3 cache */ +#define PRFCNT_MMU_L2_EN 0x07C /* (RW) Performance counter enable flags for MMU/L2 cache */ + +#define CYCLE_COUNT_LO 0x090 /* (RO) Cycle counter, low word */ +#define CYCLE_COUNT_HI 0x094 /* (RO) Cycle counter, high word */ +#define TIMESTAMP_LO 0x098 /* (RO) Global time stamp counter, low word */ +#define TIMESTAMP_HI 0x09C /* (RO) Global time stamp counter, high word */ + +#define THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */ +#define THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */ +#define THREAD_MAX_BARRIER_SIZE 0x0A8 /* (RO) Maximum threads waiting at a barrier */ +#define THREAD_FEATURES 0x0AC /* (RO) Thread features */ + +#define TEXTURE_FEATURES_0 0x0B0 /* (RO) Support flags for indexed texture formats 0..31 */ +#define TEXTURE_FEATURES_1 0x0B4 /* (RO) Support flags for indexed texture formats 32..63 */ +#define TEXTURE_FEATURES_2 0x0B8 /* (RO) Support flags for indexed texture formats 64..95 */ + +#define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2)) + +#define JS0_FEATURES 0x0C0 /* (RO) Features of job slot 0 */ +#define JS1_FEATURES 0x0C4 /* (RO) Features of job slot 1 */ +#define JS2_FEATURES 0x0C8 /* (RO) Features of job slot 2 */ +#define JS3_FEATURES 0x0CC /* (RO) Features of job slot 3 */ +#define JS4_FEATURES 0x0D0 /* (RO) Features of job slot 4 */ +#define JS5_FEATURES 0x0D4 /* (RO) Features of job slot 5 */ +#define JS6_FEATURES 0x0D8 /* (RO) Features of job slot 6 */ +#define JS7_FEATURES 0x0DC /* (RO) Features of job slot 7 */ +#define JS8_FEATURES 0x0E0 /* (RO) Features of job slot 8 */ +#define JS9_FEATURES 0x0E4 /* (RO) Features of job slot 9 */ +#define JS10_FEATURES 0x0E8 /* (RO) Features of job slot 10 */ +#define JS11_FEATURES 0x0EC /* (RO) Features of job slot 11 */ +#define JS12_FEATURES 0x0F0 /* (RO) Features of job slot 12 */ +#define JS13_FEATURES 0x0F4 /* (RO) Features of job slot 13 */ +#define JS14_FEATURES 0x0F8 /* (RO) Features of job slot 14 */ +#define JS15_FEATURES 0x0FC /* (RO) Features of job slot 15 */ + +#define JS_FEATURES_REG(n) GPU_CONTROL_REG(JS0_FEATURES + ((n) << 2)) + +#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ +#define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */ + +#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ +#define TILER_PRESENT_HI 0x114 /* (RO) Tiler core present bitmap, high word */ + +#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ +#define L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */ + +#define L3_PRESENT_LO 0x130 /* (RO) Level 3 cache present bitmap, low word */ +#define L3_PRESENT_HI 0x134 /* (RO) Level 3 cache present bitmap, high word */ + +#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */ +#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */ + +#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */ +#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */ + +#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */ +#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */ + +#define L3_READY_LO 0x170 /* (RO) Level 3 cache ready bitmap, low word */ +#define L3_READY_HI 0x174 /* (RO) Level 3 cache ready bitmap, high word */ + +#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */ +#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */ + +#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */ +#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */ + +#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */ +#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */ + +#define L3_PWRON_LO 0x1B0 /* (WO) Level 3 cache power on bitmap, low word */ +#define L3_PWRON_HI 0x1B4 /* (WO) Level 3 cache power on bitmap, high word */ + +#define SHADER_PWROFF_LO 0x1C0 /* (WO) Shader core power off bitmap, low word */ +#define SHADER_PWROFF_HI 0x1C4 /* (WO) Shader core power off bitmap, high word */ + +#define TILER_PWROFF_LO 0x1D0 /* (WO) Tiler core power off bitmap, low word */ +#define TILER_PWROFF_HI 0x1D4 /* (WO) Tiler core power off bitmap, high word */ + +#define L2_PWROFF_LO 0x1E0 /* (WO) Level 2 cache power off bitmap, low word */ +#define L2_PWROFF_HI 0x1E4 /* (WO) Level 2 cache power off bitmap, high word */ + +#define L3_PWROFF_LO 0x1F0 /* (WO) Level 3 cache power off bitmap, low word */ +#define L3_PWROFF_HI 0x1F4 /* (WO) Level 3 cache power off bitmap, high word */ + +#define SHADER_PWRTRANS_LO 0x200 /* (RO) Shader core power transition bitmap, low word */ +#define SHADER_PWRTRANS_HI 0x204 /* (RO) Shader core power transition bitmap, high word */ + +#define TILER_PWRTRANS_LO 0x210 /* (RO) Tiler core power transition bitmap, low word */ +#define TILER_PWRTRANS_HI 0x214 /* (RO) Tiler core power transition bitmap, high word */ + +#define L2_PWRTRANS_LO 0x220 /* (RO) Level 2 cache power transition bitmap, low word */ +#define L2_PWRTRANS_HI 0x224 /* (RO) Level 2 cache power transition bitmap, high word */ + +#define L3_PWRTRANS_LO 0x230 /* (RO) Level 3 cache power transition bitmap, low word */ +#define L3_PWRTRANS_HI 0x234 /* (RO) Level 3 cache power transition bitmap, high word */ + +#define SHADER_PWRACTIVE_LO 0x240 /* (RO) Shader core active bitmap, low word */ +#define SHADER_PWRACTIVE_HI 0x244 /* (RO) Shader core active bitmap, high word */ + +#define TILER_PWRACTIVE_LO 0x250 /* (RO) Tiler core active bitmap, low word */ +#define TILER_PWRACTIVE_HI 0x254 /* (RO) Tiler core active bitmap, high word */ + +#define L2_PWRACTIVE_LO 0x260 /* (RO) Level 2 cache active bitmap, low word */ +#define L2_PWRACTIVE_HI 0x264 /* (RO) Level 2 cache active bitmap, high word */ + +#define L3_PWRACTIVE_LO 0x270 /* (RO) Level 3 cache active bitmap, low word */ +#define L3_PWRACTIVE_HI 0x274 /* (RO) Level 3 cache active bitmap, high word */ + +#define SHADER_CONFIG 0xF04 /* (RW) Shader core configuration settings (Implementation specific register) */ +#define TILER_CONFIG 0xF08 /* (RW) Tiler core configuration settings (Implementation specific register) */ +#define L2_MMU_CONFIG 0xF0C /* (RW) Configuration of the L2 cache and MMU (Implementation specific register) */ + +#define JOB_CONTROL_BASE 0x1000 + +#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r)) + +#define JOB_IRQ_RAWSTAT 0x000 /* Raw interrupt status register */ +#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */ +#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */ +#define JOB_IRQ_STATUS 0x00C /* Interrupt status register */ +#define JOB_IRQ_JS_STATE 0x010 /* status==active and _next == busy snapshot from last JOB_IRQ_CLEAR */ +#define JOB_IRQ_THROTTLE 0x014 /* cycles to delay delivering an interrupt externally. The JOB_IRQ_STATUS is NOT affected by this, just the delivery of the interrupt. */ + +#define JOB_SLOT0 0x800 /* Configuration registers for job slot 0 */ +#define JOB_SLOT1 0x880 /* Configuration registers for job slot 1 */ +#define JOB_SLOT2 0x900 /* Configuration registers for job slot 2 */ +#define JOB_SLOT3 0x980 /* Configuration registers for job slot 3 */ +#define JOB_SLOT4 0xA00 /* Configuration registers for job slot 4 */ +#define JOB_SLOT5 0xA80 /* Configuration registers for job slot 5 */ +#define JOB_SLOT6 0xB00 /* Configuration registers for job slot 6 */ +#define JOB_SLOT7 0xB80 /* Configuration registers for job slot 7 */ +#define JOB_SLOT8 0xC00 /* Configuration registers for job slot 8 */ +#define JOB_SLOT9 0xC80 /* Configuration registers for job slot 9 */ +#define JOB_SLOT10 0xD00 /* Configuration registers for job slot 10 */ +#define JOB_SLOT11 0xD80 /* Configuration registers for job slot 11 */ +#define JOB_SLOT12 0xE00 /* Configuration registers for job slot 12 */ +#define JOB_SLOT13 0xE80 /* Configuration registers for job slot 13 */ +#define JOB_SLOT14 0xF00 /* Configuration registers for job slot 14 */ +#define JOB_SLOT15 0xF80 /* Configuration registers for job slot 15 */ + +#define JOB_SLOT_REG(n, r) (JOB_CONTROL_REG(JOB_SLOT0 + ((n) << 7)) + (r)) + +#define JS_HEAD_LO 0x00 /* (RO) Job queue head pointer for job slot n, low word */ +#define JS_HEAD_HI 0x04 /* (RO) Job queue head pointer for job slot n, high word */ +#define JS_TAIL_LO 0x08 /* (RO) Job queue tail pointer for job slot n, low word */ +#define JS_TAIL_HI 0x0C /* (RO) Job queue tail pointer for job slot n, high word */ +#define JS_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */ +#define JS_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */ +#define JS_CONFIG 0x18 /* (RO) Configuration settings for job slot n */ + +#define JS_COMMAND 0x20 /* (WO) Command register for job slot n */ +#define JS_STATUS 0x24 /* (RO) Status register for job slot n */ + +#define JS_HEAD_NEXT_LO 0x40 /* (RW) Next job queue head pointer for job slot n, low word */ +#define JS_HEAD_NEXT_HI 0x44 /* (RW) Next job queue head pointer for job slot n, high word */ + +#define JS_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */ +#define JS_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */ +#define JS_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */ + +#define JS_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */ + +#define MEMORY_MANAGEMENT_BASE 0x2000 +#define MMU_REG(r) (MEMORY_MANAGEMENT_BASE + (r)) + +#define MMU_IRQ_RAWSTAT 0x000 /* (RW) Raw interrupt status register */ +#define MMU_IRQ_CLEAR 0x004 /* (WO) Interrupt clear register */ +#define MMU_IRQ_MASK 0x008 /* (RW) Interrupt mask register */ +#define MMU_IRQ_STATUS 0x00C /* (RO) Interrupt status register */ + +#define MMU_AS0 0x400 /* Configuration registers for address space 0 */ +#define MMU_AS1 0x440 /* Configuration registers for address space 1 */ +#define MMU_AS2 0x480 /* Configuration registers for address space 2 */ +#define MMU_AS3 0x4C0 /* Configuration registers for address space 3 */ +#define MMU_AS4 0x500 /* Configuration registers for address space 4 */ +#define MMU_AS5 0x540 /* Configuration registers for address space 5 */ +#define MMU_AS6 0x580 /* Configuration registers for address space 6 */ +#define MMU_AS7 0x5C0 /* Configuration registers for address space 7 */ +#define MMU_AS8 0x600 /* Configuration registers for address space 8 */ +#define MMU_AS9 0x640 /* Configuration registers for address space 9 */ +#define MMU_AS10 0x680 /* Configuration registers for address space 10 */ +#define MMU_AS11 0x6C0 /* Configuration registers for address space 11 */ +#define MMU_AS12 0x700 /* Configuration registers for address space 12 */ +#define MMU_AS13 0x740 /* Configuration registers for address space 13 */ +#define MMU_AS14 0x780 /* Configuration registers for address space 14 */ +#define MMU_AS15 0x7C0 /* Configuration registers for address space 15 */ + +#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r)) + +#define AS_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */ +#define AS_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */ +#define AS_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */ +#define AS_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */ +#define AS_LOCKADDR_LO 0x10 /* (RW) Lock region address for address space n, low word */ +#define AS_LOCKADDR_HI 0x14 /* (RW) Lock region address for address space n, high word */ +#define AS_COMMAND 0x18 /* (WO) MMU command register for address space n */ +#define AS_FAULTSTATUS 0x1C /* (RO) MMU fault status register for address space n */ +#define AS_FAULTADDRESS_LO 0x20 /* (RO) Fault Address for address space n, low word */ +#define AS_FAULTADDRESS_HI 0x24 /* (RO) Fault Address for address space n, high word */ +#define AS_STATUS 0x28 /* (RO) Status flags for address space n */ + +/* End Register Offsets */ + +/* + * MMU_IRQ_RAWSTAT register values. Values are valid also for + MMU_IRQ_CLEAR, MMU_IRQ_MASK, MMU_IRQ_STATUS registers. + */ + +#define MMU_PAGE_FAULT_FLAGS 16 + +/* Macros returning a bitmask to retrieve page fault or bus error flags from + * MMU registers */ +#define MMU_PAGE_FAULT(n) (1UL << (n)) +#define MMU_BUS_ERROR(n) (1UL << ((n) + MMU_PAGE_FAULT_FLAGS)) + +/* + * Begin MMU TRANSTAB register values + */ +#define AS_TRANSTAB_ADDR_SPACE_MASK 0xfffff000 +#define AS_TRANSTAB_ADRMODE_UNMAPPED (0u << 0) +#define AS_TRANSTAB_ADRMODE_IDENTITY (1u << 1) +#define AS_TRANSTAB_ADRMODE_TABLE (3u << 0) +#define AS_TRANSTAB_READ_INNER (1u << 2) +#define AS_TRANSTAB_SHARE_OUTER (1u << 4) + +#define MMU_TRANSTAB_ADRMODE_MASK 0x00000003 + +/* + * Begin MMU STATUS register values + */ +#define AS_STATUS_AS_ACTIVE 0x01 + +#define AS_FAULTSTATUS_ACCESS_TYPE_MASK (0x3<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_EX (0x1<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_READ (0x2<<8) +#define AS_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3<<8) + +/* + * Begin Command Values + */ + +/* JS_COMMAND register commands */ +#define JS_COMMAND_NOP 0x00 /* NOP Operation. Writing this value is ignored */ +#define JS_COMMAND_START 0x01 /* Start processing a job chain. Writing this value is ignored */ +#define JS_COMMAND_SOFT_STOP 0x02 /* Gently stop processing a job chain */ +#define JS_COMMAND_HARD_STOP 0x03 /* Rudely stop processing a job chain */ +#define JS_COMMAND_SOFT_STOP_0 0x04 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 0 */ +#define JS_COMMAND_HARD_STOP_0 0x05 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 0 */ +#define JS_COMMAND_SOFT_STOP_1 0x06 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 1 */ +#define JS_COMMAND_HARD_STOP_1 0x07 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 1 */ + +#define JS_COMMAND_MASK 0x07 /* Mask of bits currently in use by the HW */ + +/* AS_COMMAND register commands */ +#define AS_COMMAND_NOP 0x00 /* NOP Operation */ +#define AS_COMMAND_UPDATE 0x01 /* Broadcasts the values in AS_TRANSTAB and ASn_MEMATTR to all MMUs */ +#define AS_COMMAND_LOCK 0x02 /* Issue a lock region command to all MMUs */ +#define AS_COMMAND_UNLOCK 0x03 /* Issue a flush region command to all MMUs */ +#define AS_COMMAND_FLUSH 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs + (deprecated - only for use with T60x) */ +#define AS_COMMAND_FLUSH_PT 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs */ +#define AS_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then + flush all L2 caches then issue a flush region command to all MMUs */ + +/* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */ +#define JS_CONFIG_START_FLUSH_NO_ACTION (0u << 0) +#define JS_CONFIG_START_FLUSH_CLEAN (1u << 8) +#define JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE (3u << 8) +#define JS_CONFIG_START_MMU (1u << 10) +#define JS_CONFIG_JOB_CHAIN_FLAG (1u << 11) +#define JS_CONFIG_END_FLUSH_NO_ACTION JS_CONFIG_START_FLUSH_NO_ACTION +#define JS_CONFIG_END_FLUSH_CLEAN (1u << 12) +#define JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE (3u << 12) +#define JS_CONFIG_THREAD_PRI(n) ((n) << 16) + +/* JS_STATUS register values */ + +/* NOTE: Please keep this values in sync with enum base_jd_event_code in mali_base_kernel.h. + * The values are separated to avoid dependency of userspace and kernel code. + */ + +/* Group of values representing the job status insead a particular fault */ +#define JS_STATUS_NO_EXCEPTION_BASE 0x00 +#define JS_STATUS_INTERRUPTED (JS_STATUS_NO_EXCEPTION_BASE + 0x02) /* 0x02 means INTERRUPTED */ +#define JS_STATUS_STOPPED (JS_STATUS_NO_EXCEPTION_BASE + 0x03) /* 0x03 means STOPPED */ +#define JS_STATUS_TERMINATED (JS_STATUS_NO_EXCEPTION_BASE + 0x04) /* 0x04 means TERMINATED */ + +/* General fault values */ +#define JS_STATUS_FAULT_BASE 0x40 +#define JS_STATUS_CONFIG_FAULT (JS_STATUS_FAULT_BASE) /* 0x40 means CONFIG FAULT */ +#define JS_STATUS_POWER_FAULT (JS_STATUS_FAULT_BASE + 0x01) /* 0x41 means POWER FAULT */ +#define JS_STATUS_READ_FAULT (JS_STATUS_FAULT_BASE + 0x02) /* 0x42 means READ FAULT */ +#define JS_STATUS_WRITE_FAULT (JS_STATUS_FAULT_BASE + 0x03) /* 0x43 means WRITE FAULT */ +#define JS_STATUS_AFFINITY_FAULT (JS_STATUS_FAULT_BASE + 0x04) /* 0x44 means AFFINITY FAULT */ +#define JS_STATUS_BUS_FAULT (JS_STATUS_FAULT_BASE + 0x08) /* 0x48 means BUS FAULT */ + +/* Instruction or data faults */ +#define JS_STATUS_INSTRUCTION_FAULT_BASE 0x50 +#define JS_STATUS_INSTR_INVALID_PC (JS_STATUS_INSTRUCTION_FAULT_BASE) /* 0x50 means INSTR INVALID PC */ +#define JS_STATUS_INSTR_INVALID_ENC (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x01) /* 0x51 means INSTR INVALID ENC */ +#define JS_STATUS_INSTR_TYPE_MISMATCH (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x02) /* 0x52 means INSTR TYPE MISMATCH */ +#define JS_STATUS_INSTR_OPERAND_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x03) /* 0x53 means INSTR OPERAND FAULT */ +#define JS_STATUS_INSTR_TLS_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x04) /* 0x54 means INSTR TLS FAULT */ +#define JS_STATUS_INSTR_BARRIER_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x05) /* 0x55 means INSTR BARRIER FAULT */ +#define JS_STATUS_INSTR_ALIGN_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x06) /* 0x56 means INSTR ALIGN FAULT */ +/* NOTE: No fault with 0x57 code defined in spec. */ +#define JS_STATUS_DATA_INVALID_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x08) /* 0x58 means DATA INVALID FAULT */ +#define JS_STATUS_TILE_RANGE_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x09) /* 0x59 means TILE RANGE FAULT */ +#define JS_STATUS_ADDRESS_RANGE_FAULT (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x0A) /* 0x5A means ADDRESS RANGE FAULT */ + +/* Other faults */ +#define JS_STATUS_MEMORY_FAULT_BASE 0x60 +#define JS_STATUS_OUT_OF_MEMORY (JS_STATUS_MEMORY_FAULT_BASE) /* 0x60 means OUT OF MEMORY */ +#define JS_STATUS_UNKNOWN 0x7F /* 0x7F means UNKNOWN */ + +/* GPU_COMMAND values */ +#define GPU_COMMAND_NOP 0x00 /* No operation, nothing happens */ +#define GPU_COMMAND_SOFT_RESET 0x01 /* Stop all external bus interfaces, and then reset the entire GPU. */ +#define GPU_COMMAND_HARD_RESET 0x02 /* Immediately reset the entire GPU. */ +#define GPU_COMMAND_PRFCNT_CLEAR 0x03 /* Clear all performance counters, setting them all to zero. */ +#define GPU_COMMAND_PRFCNT_SAMPLE 0x04 /* Sample all performance counters, writing them out to memory */ +#define GPU_COMMAND_CYCLE_COUNT_START 0x05 /* Starts the cycle counter, and system timestamp propagation */ +#define GPU_COMMAND_CYCLE_COUNT_STOP 0x06 /* Stops the cycle counter, and system timestamp propagation */ +#define GPU_COMMAND_CLEAN_CACHES 0x07 /* Clean all caches */ +#define GPU_COMMAND_CLEAN_INV_CACHES 0x08 /* Clean and invalidate all caches */ + +/* End Command Values */ + +/* GPU_STATUS values */ +#define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */ + +/* PRFCNT_CONFIG register values */ +#define PRFCNT_CONFIG_AS_SHIFT 4 /* address space bitmap starts from bit 4 of the register */ +#define PRFCNT_CONFIG_MODE_OFF 0 /* The performance counters are disabled. */ +#define PRFCNT_CONFIG_MODE_MANUAL 1 /* The performance counters are enabled, but are only written out when a PRFCNT_SAMPLE command is issued using the GPU_COMMAND register. */ +#define PRFCNT_CONFIG_MODE_TILE 2 /* The performance counters are enabled, and are written out each time a tile finishes rendering. */ + +/* AS_MEMATTR values: */ +/* Use GPU implementation-defined caching policy. */ +#define AS_MEMATTR_IMPL_DEF_CACHE_POLICY 0x48 +/* The attribute set to force all resources to be cached. */ +#define AS_MEMATTR_FORCE_TO_CACHE_ALL 0x4F +/* Inner write-alloc cache setup, no outer caching */ +#define AS_MEMATTR_WRITE_ALLOC 0x4D +/* symbol for default MEMATTR to use */ +#define AS_MEMATTR_INDEX_DEFAULT 0 +/* HW implementation defined caching */ +#define AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY 0 +/* Force cache on */ +#define AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL 1 +/* Write-alloc inner */ +#define AS_MEMATTR_INDEX_WRITE_ALLOC 2 + +/* GPU_ID register */ +#define GPU_ID_VERSION_STATUS_SHIFT 0 +#define GPU_ID_VERSION_MINOR_SHIFT 4 +#define GPU_ID_VERSION_MAJOR_SHIFT 12 +#define GPU_ID_VERSION_PRODUCT_ID_SHIFT 16 +#define GPU_ID_VERSION_STATUS (0xF << GPU_ID_VERSION_STATUS_SHIFT) +#define GPU_ID_VERSION_MINOR (0xFF << GPU_ID_VERSION_MINOR_SHIFT) +#define GPU_ID_VERSION_MAJOR (0xF << GPU_ID_VERSION_MAJOR_SHIFT) +#define GPU_ID_VERSION_PRODUCT_ID (0xFFFF << GPU_ID_VERSION_PRODUCT_ID_SHIFT) + +/* Values for GPU_ID_VERSION_PRODUCT_ID bitfield */ +#define GPU_ID_PI_T60X 0x6956 +#define GPU_ID_PI_T62X 0x0620 +#define GPU_ID_PI_T76X 0x0750 +#define GPU_ID_PI_T72X 0x0720 +#define GPU_ID_PI_TFRX 0x0880 +#define GPU_ID_PI_T86X 0x0860 + +/* Values for GPU_ID_VERSION_STATUS field for PRODUCT_ID GPU_ID_PI_T60X */ +#define GPU_ID_S_15DEV0 0x1 +#define GPU_ID_S_EAC 0x2 + +/* Helper macro to create a GPU_ID assuming valid values for id, major, minor, status */ +#define GPU_ID_MAKE(id, major, minor, status) \ + (((id) << GPU_ID_VERSION_PRODUCT_ID_SHIFT) | \ + ((major) << GPU_ID_VERSION_MAJOR_SHIFT) | \ + ((minor) << GPU_ID_VERSION_MINOR_SHIFT) | \ + ((status) << GPU_ID_VERSION_STATUS_SHIFT)) + +/* End GPU_ID register */ + +/* JS_FEATURES register */ + +#define JS_FEATURE_NULL_JOB (1u << 1) +#define JS_FEATURE_SET_VALUE_JOB (1u << 2) +#define JS_FEATURE_CACHE_FLUSH_JOB (1u << 3) +#define JS_FEATURE_COMPUTE_JOB (1u << 4) +#define JS_FEATURE_VERTEX_JOB (1u << 5) +#define JS_FEATURE_GEOMETRY_JOB (1u << 6) +#define JS_FEATURE_TILER_JOB (1u << 7) +#define JS_FEATURE_FUSED_JOB (1u << 8) +#define JS_FEATURE_FRAGMENT_JOB (1u << 9) + +/* End JS_FEATURES register */ + +/* L2_MMU_CONFIG register */ +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT (24) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT) + +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT (26) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_OCTANT (0x1 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_QUARTER (0x2 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +#define L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_HALF (0x3 << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT) +/* End L2_MMU_CONFIG register */ + +/* THREAD_* registers */ + +/* THREAD_FEATURES IMPLEMENTATION_TECHNOLOGY values */ +#define IMPLEMENTATION_UNSPECIFIED 0 +#define IMPLEMENTATION_SILICON 1 +#define IMPLEMENTATION_FPGA 2 +#define IMPLEMENTATION_MODEL 3 + +/* Default values when registers are not supported by the implemented hardware */ +#define THREAD_MT_DEFAULT 256 +#define THREAD_MWS_DEFAULT 256 +#define THREAD_MBS_DEFAULT 256 +#define THREAD_MR_DEFAULT 1024 +#define THREAD_MTQ_DEFAULT 4 +#define THREAD_MTGS_DEFAULT 10 + +/* End THREAD_* registers */ + +/* SHADER_CONFIG register */ + +#define SC_ALT_COUNTERS (1ul << 3) +#define SC_OVERRIDE_FWD_PIXEL_KILL (1ul << 4) +#define SC_SDC_DISABLE_OQ_DISCARD (1ul << 6) +#define SC_LS_PAUSEBUFFER_DISABLE (1ul << 16) +#define SC_ENABLE_TEXGRD_FLAGS (1ul << 25) +/* End SHADER_CONFIG register */ + +/* TILER_CONFIG register */ + +#define TC_CLOCK_GATE_OVERRIDE (1ul << 0) + +/* End TILER_CONFIG register */ + + +#endif /* _MIDGARD_REGMAP_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_timeline.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_timeline.h new file mode 100644 index 0000000000000000000000000000000000000000..83a29cd304fb96667ebb86b0651fe64477f31ae6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_timeline.h @@ -0,0 +1,396 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mali_timeline + +#if !defined(_MALI_TIMELINE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _MALI_TIMELINE_H + +#include + +TRACE_EVENT(mali_timeline_atoms_in_flight, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int tgid, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + tgid, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, tgid) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->tgid = tgid; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i", CTX_SET_NR_ATOMS_IN_FLIGHT, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->count) +); + + +TRACE_EVENT(mali_timeline_atom, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int atom_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + atom_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, atom_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->atom_id = atom_id; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->atom_id, + __entry->atom_id) +); + +TRACE_EVENT(mali_timeline_gpu_slot_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->count) +); + +TRACE_EVENT(mali_timeline_gpu_slot_action, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->count) +); + +TRACE_EVENT(mali_timeline_gpu_power_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int active), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + active), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, active) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->active = active; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->active) + +); + +TRACE_EVENT(mali_timeline_l2_power_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int state), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + state), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, state) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->state = state; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->state) + +); +TRACE_EVENT(mali_timeline_pm_event, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int pm_event_type, + unsigned int pm_event_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + pm_event_type, + pm_event_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, pm_event_type) + __field(unsigned int, pm_event_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->pm_event_type = pm_event_type; + __entry->pm_event_id = pm_event_id; + ), + + TP_printk("%i,%i.%.9i,0,%i,%u", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->pm_event_type, __entry->pm_event_id) + +); + +TRACE_EVENT(mali_timeline_slot_atom, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int event_type, + int tgid, + int js, + int atom_id), + + TP_ARGS(ts_sec, + ts_nsec, + event_type, + tgid, + js, + atom_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, event_type) + __field(int, tgid) + __field(int, js) + __field(int, atom_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->event_type = event_type; + __entry->tgid = tgid; + __entry->js = js; + __entry->atom_id = atom_id; + ), + + TP_printk("%i,%i.%.9i,%i,%i,%i", __entry->event_type, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->tgid, + __entry->js, + __entry->atom_id) +); + +TRACE_EVENT(mali_timeline_pm_checktrans, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int trans_code, + int trans_id), + + TP_ARGS(ts_sec, + ts_nsec, + trans_code, + trans_id), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, trans_code) + __field(int, trans_id) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->trans_code = trans_code; + __entry->trans_id = trans_id; + ), + + TP_printk("%i,%i.%.9i,0,%i", __entry->trans_code, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->trans_id) + +); + +TRACE_EVENT(mali_timeline_context_active, + + TP_PROTO(u64 ts_sec, + u32 ts_nsec, + int count), + + TP_ARGS(ts_sec, + ts_nsec, + count), + + TP_STRUCT__entry( + __field(u64, ts_sec) + __field(u32, ts_nsec) + __field(int, count) + ), + + TP_fast_assign( + __entry->ts_sec = ts_sec; + __entry->ts_nsec = ts_nsec; + __entry->count = count; + ), + + TP_printk("%i,%i.%.9i,0,%i", SW_SET_CONTEXT_ACTIVE, + (int)__entry->ts_sec, + (int)__entry->ts_nsec, + __entry->count) +); + +#endif /* _MALI_TIMELINE_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +/* This part must be outside protection */ +#include + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_uk.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_uk.h new file mode 100644 index 0000000000000000000000000000000000000000..5d9e0dd218ecb8966b4dfba94a098bba07993def --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/mali_uk.h @@ -0,0 +1,143 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_uk.h + * Types and definitions that are common across OSs for both the user + * and kernel side of the User-Kernel interface. + */ + +#ifndef _UK_H_ +#define _UK_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +/** + * @addtogroup base_api + * @{ + */ + +/** + * @defgroup uk_api User-Kernel Interface API + * + * The User-Kernel Interface abstracts the communication mechanism between the user and kernel-side code of device + * drivers developed as part of the Midgard DDK. Currently that includes the Base driver and the UMP driver. + * + * It exposes an OS independent API to user-side code (UKU) which routes functions calls to an OS-independent + * kernel-side API (UKK) via an OS-specific communication mechanism. + * + * This API is internal to the Midgard DDK and is not exposed to any applications. + * + * @{ + */ + +/** + * These are identifiers for kernel-side drivers implementing a UK interface, aka UKK clients. The + * UK module maps this to an OS specific device name, e.g. "gpu_base" -> "GPU0:". Specify this + * identifier to select a UKK client to the uku_open() function. + * + * When a new UKK client driver is created a new identifier needs to be added to the uk_client_id + * enumeration and the uku_open() implemenation for the various OS ports need to be updated to + * provide a mapping of the identifier to the OS specific device name. + * + */ +enum uk_client_id { + /** + * Value used to identify the Base driver UK client. + */ + UK_CLIENT_MALI_T600_BASE, + + /** The number of uk clients supported. This must be the last member of the enum */ + UK_CLIENT_COUNT +}; + +/** + * Each function callable through the UK interface has a unique number. + * Functions provided by UK clients start from number UK_FUNC_ID. + * Numbers below UK_FUNC_ID are used for internal UK functions. + */ +enum uk_func { + UKP_FUNC_ID_CHECK_VERSION, /**< UKK Core internal function */ + /** + * Each UK client numbers the functions they provide starting from + * number UK_FUNC_ID. This number is then eventually assigned to the + * id field of the union uk_header structure when preparing to make a + * UK call. See your UK client for a list of their function numbers. + */ + UK_FUNC_ID = 512 +}; + +/** + * Arguments for a UK call are stored in a structure. This structure consists + * of a fixed size header and a payload. The header carries a 32-bit number + * identifying the UK function to be called (see uk_func). When the UKK client + * receives this header and executed the requested UK function, it will use + * the same header to store the result of the function in the form of a + * mali_error return code. The size of this structure is such that the + * first member of the payload following the header can be accessed efficiently + * on a 32 and 64-bit kernel and the structure has the same size regardless + * of a 32 or 64-bit kernel. The uk_kernel_size_type type should be defined + * accordingly in the OS specific mali_uk_os.h header file. + */ +union uk_header { + /** + * 32-bit number identifying the UK function to be called. + * Also see uk_func. + */ + u32 id; + /** + * The mali_error return code returned by the called UK function. + * See the specification of the particular UK function you are + * calling for the meaning of the error codes returned. All + * UK functions return MALI_ERROR_NONE on success. + */ + u32 ret; + /* + * Used to ensure 64-bit alignment of this union. Do not remove. + * This field is used for padding and does not need to be initialized. + */ + u64 sizer; +}; + +/** + * This structure carries a 16-bit major and minor number and is sent along with an internal UK call + * used during uku_open to identify the versions of the UK module in use by the user-side and kernel-side. + */ +struct uku_version_check_args { + union uk_header header; + /**< UK call header */ + u16 major; + /**< This field carries the user-side major version on input and the kernel-side major version on output */ + u16 minor; + /**< This field carries the user-side minor version on input and the kernel-side minor version on output. */ + u8 padding[4]; +}; + +/** @} end group uk_api */ + +/** @} *//* end group base_api */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _UK_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd.h new file mode 100644 index 0000000000000000000000000000000000000000..9226d977f7a5fd7ca27959d1b43238da665e12d9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd.h @@ -0,0 +1,481 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @addtogroup malisw + * @{ + */ + +/* ============================================================================ + Description +============================================================================ */ +/** + * @defgroup arm_cstd_coding_standard ARM C standard types and constants + * The common files are a set of standard headers which are used by all parts + * of this development, describing types, and generic constants. + * + * Files in group: + * - arm_cstd.h + * - arm_cstd_compilers.h + * - arm_cstd_types.h + * - arm_cstd_types_rvct.h + * - arm_cstd_types_gcc.h + * - arm_cstd_types_msvc.h + * - arm_cstd_pack_push.h + * - arm_cstd_pack_pop.h + */ + +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +#ifndef _ARM_CSTD_ +#define _ARM_CSTD_ + +/* ============================================================================ + Import standard C99 types +============================================================================ */ +#include "arm_cstd_compilers.h" +#include "arm_cstd_types.h" + +/* ============================================================================ + Min and Max Values +============================================================================ */ +#if !defined(INT8_MAX) + #define INT8_MAX ((int8_t) 0x7F) +#endif +#if !defined(INT8_MIN) + #define INT8_MIN (-INT8_MAX - 1) +#endif + +#if !defined(INT16_MAX) + #define INT16_MAX ((int16_t)0x7FFF) +#endif +#if !defined(INT16_MIN) + #define INT16_MIN (-INT16_MAX - 1) +#endif + +#if !defined(INT32_MAX) + #define INT32_MAX ((int32_t)0x7FFFFFFF) +#endif +#if !defined(INT32_MIN) + #define INT32_MIN (-INT32_MAX - 1) +#endif + +#if !defined(INT64_MAX) + #define INT64_MAX ((int64_t)0x7FFFFFFFFFFFFFFFLL) +#endif +#if !defined(INT64_MIN) + #define INT64_MIN (-INT64_MAX - 1) +#endif + +#if !defined(UINT8_MAX) + #define UINT8_MAX ((uint8_t) 0xFF) +#endif + +#if !defined(UINT16_MAX) + #define UINT16_MAX ((uint16_t)0xFFFF) +#endif + +#if !defined(UINT32_MAX) + #define UINT32_MAX ((uint32_t)0xFFFFFFFF) +#endif + +#if !defined(UINT64_MAX) + #define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFFULL) +#endif + +/* fallbacks if limits.h wasn't available */ +#if !defined(UCHAR_MAX) + #define UCHAR_MAX ((unsigned char)~0U) +#endif + +#if !defined(SCHAR_MAX) + #define SCHAR_MAX ((signed char)(UCHAR_MAX >> 1)) +#endif +#if !defined(SCHAR_MIN) + #define SCHAR_MIN ((signed char)(-SCHAR_MAX - 1)) +#endif + +#if !defined(USHRT_MAX) + #define USHRT_MAX ((unsigned short)~0U) +#endif + +#if !defined(SHRT_MAX) + #define SHRT_MAX ((signed short)(USHRT_MAX >> 1)) +#endif +#if !defined(SHRT_MIN) + #define SHRT_MIN ((signed short)(-SHRT_MAX - 1)) +#endif + +#if !defined(UINT_MAX) + #define UINT_MAX ((unsigned int)~0U) +#endif + +#if !defined(INT_MAX) + #define INT_MAX ((signed int)(UINT_MAX >> 1)) +#endif +#if !defined(INT_MIN) + #define INT_MIN ((signed int)(-INT_MAX - 1)) +#endif + +#if !defined(ULONG_MAX) + #define ULONG_MAX ((unsigned long)~0UL) +#endif + +#if !defined(LONG_MAX) + #define LONG_MAX ((signed long)(ULONG_MAX >> 1)) +#endif +#if !defined(LONG_MIN) + #define LONG_MIN ((signed long)(-LONG_MAX - 1)) +#endif + +#if !defined(ULLONG_MAX) + #define ULLONG_MAX ((unsigned long long)~0ULL) +#endif + +#if !defined(LLONG_MAX) + #define LLONG_MAX ((signed long long)(ULLONG_MAX >> 1)) +#endif +#if !defined(LLONG_MIN) + #define LLONG_MIN ((signed long long)(-LLONG_MAX - 1)) +#endif + +#if !defined(SIZE_MAX) + #if 1 == CSTD_CPU_32BIT + #define SIZE_MAX UINT32_MAX + #elif 1 == CSTD_CPU_64BIT + #define SIZE_MAX UINT64_MAX + #endif +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/* Portable keywords. */ + +#if !defined(CONST) +/** + * @hideinitializer + * Variable is a C @c const, which can be made non-const for testing purposes. + */ + #define CONST const +#endif + +#if !defined(STATIC) +/** + * @hideinitializer + * Variable is a C @c static, which can be made non-static for testing + * purposes. + */ + #define STATIC static +#endif + +/** + * Specifies a function as being exported outside of a logical module. + */ +#define PUBLIC + +/** + * @def PROTECTED + * Specifies a a function which is internal to an logical module, but which + * should not be used outside of that module. This cannot be enforced by the + * compiler, as a module is typically more than one translation unit. + */ +#define PROTECTED + +/** + * Specifies a function as being internal to a translation unit. Private + * functions would typically be declared as STATIC, unless they are being + * exported for unit test purposes. + */ +#define PRIVATE STATIC + +/** + * Specify an assertion value which is evaluated at compile time. Recommended + * usage is specification of a @c static @c INLINE function containing all of + * the assertions thus: + * + * @code + * static INLINE [module]_compile_time_assertions( void ) + * { + * COMPILE_TIME_ASSERT( sizeof(uintptr_t) == sizeof(intptr_t) ); + * } + * @endcode + * + * @note Use @c static not @c STATIC. We never want to turn off this @c static + * specification for testing purposes. + */ +#define CSTD_COMPILE_TIME_ASSERT( expr ) \ + do { switch(0){case 0: case (expr):;} } while( FALSE ) + +/** + * @hideinitializer + * @deprecated Prefered form is @c CSTD_UNUSED + * Function-like macro for suppressing unused variable warnings. Where possible + * such variables should be removed; this macro is present for cases where we + * much support API backwards compatibility. + */ +#define UNUSED( x ) ((void)(x)) + +/** + * @hideinitializer + * Function-like macro for suppressing unused variable warnings. Where possible + * such variables should be removed; this macro is present for cases where we + * much support API backwards compatibility. + */ +#define CSTD_UNUSED( x ) ((void)(x)) + +/** + * @hideinitializer + * Function-like macro for use where "no behavior" is desired. This is useful + * when compile time macros turn a function-like macro in to a no-op, but + * where having no statement is otherwise invalid. + */ +#define CSTD_NOP( ... ) ((void)#__VA_ARGS__) + +/** + * @hideinitializer + * Function-like macro for converting a pointer in to a u64 for storing into + * an external data structure. This is commonly used when pairing a 32-bit + * CPU with a 64-bit peripheral, such as a Midgard GPU. C's type promotion + * is complex and a straight cast does not work reliably as pointers are + * often considered as signed. + */ +#define CSTD_PTR_TO_U64( x ) ((uint64_t)((uintptr_t)(x))) + +/** + * @hideinitializer + * Function-like macro for stringizing a single level macro. + * @code + * #define MY_MACRO 32 + * CSTD_STR1( MY_MACRO ) + * > "MY_MACRO" + * @endcode + */ +#define CSTD_STR1( x ) #x + +/** + * @hideinitializer + * Function-like macro for stringizing a macro's value. This should not be used + * if the macro is defined in a way which may have no value; use the + * alternative @c CSTD_STR2N macro should be used instead. + * @code + * #define MY_MACRO 32 + * CSTD_STR2( MY_MACRO ) + * > "32" + * @endcode + */ +#define CSTD_STR2( x ) CSTD_STR1( x ) + +/** + * @hideinitializer + * Utility function for stripping the first character off a string. + */ +static INLINE char* arm_cstd_strstrip( char * string ) +{ + return ++string; +} + +/** + * @hideinitializer + * Function-like macro for stringizing a single level macro where the macro + * itself may not have a value. Parameter @c a should be set to any single + * character which is then stripped by the macro via an inline function. This + * should only be used via the @c CSTD_STR2N macro; for printing a single + * macro only the @c CSTD_STR1 macro is a better alternative. + * + * This macro requires run-time code to handle the case where the macro has + * no value (you can't concat empty strings in the preprocessor). + */ +#define CSTD_STR1N( a, x ) arm_cstd_strstrip( CSTD_STR1( a##x ) ) + +/** + * @hideinitializer + * Function-like macro for stringizing a two level macro where the macro itself + * may not have a value. + * @code + * #define MY_MACRO 32 + * CSTD_STR2N( MY_MACRO ) + * > "32" + * + * #define MY_MACRO 32 + * CSTD_STR2N( MY_MACRO ) + * > "32" + * @endcode + */ +#define CSTD_STR2N( x ) CSTD_STR1N( _, x ) + +/* ============================================================================ + Validate portability constructs +============================================================================ */ +static INLINE void arm_cstd_compile_time_assertions( void ) +{ + CSTD_COMPILE_TIME_ASSERT( sizeof(uint8_t) == 1 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int8_t) == 1 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint16_t) == 2 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int16_t) == 2 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint32_t) == 4 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int32_t) == 4 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(uint64_t) == 8 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(int64_t) == 8 ); + CSTD_COMPILE_TIME_ASSERT( sizeof(intptr_t) == sizeof(uintptr_t) ); + + CSTD_COMPILE_TIME_ASSERT( 1 == TRUE ); + CSTD_COMPILE_TIME_ASSERT( 0 == FALSE ); + +#if 1 == CSTD_CPU_32BIT + CSTD_COMPILE_TIME_ASSERT( sizeof(uintptr_t) == 4 ); +#elif 1 == CSTD_CPU_64BIT + CSTD_COMPILE_TIME_ASSERT( sizeof(uintptr_t) == 8 ); +#endif + +} + +/* ============================================================================ + Useful function-like macro +============================================================================ */ +/** + * @brief Return the lesser of two values. + * As a macro it may evaluate its arguments more than once. + * @see CSTD_MAX + */ +#define CSTD_MIN( x, y ) ((x) < (y) ? (x) : (y)) + +/** + * @brief Return the greater of two values. + * As a macro it may evaluate its arguments more than once. + * If called on the same two arguments as CSTD_MIN it is guaranteed to return + * the one that CSTD_MIN didn't return. This is significant for types where not + * all values are comparable e.g. NaNs in floating-point types. But if you want + * to retrieve the min and max of two values, consider using a conditional swap + * instead. + */ +#define CSTD_MAX( x, y ) ((x) < (y) ? (y) : (x)) + +/** + * @brief Clamp value @c x to within @c min and @c max inclusive. + */ +#define CSTD_CLAMP( x, min, max ) ((x)<(min) ? (min):((x)>(max) ? (max):(x))) + +/** + * Flag a cast as a reinterpretation, usually of a pointer type. + */ +#define CSTD_REINTERPRET_CAST(type) (type) + +/** + * Flag a cast as casting away const, usually of a pointer type. + */ +#define CSTD_CONST_CAST(type) (type) + +/** + * Flag a cast as a (potentially complex) value conversion, usually of a + * numerical type. + */ +#define CSTD_STATIC_CAST(type) (type) + +/* ============================================================================ + Useful bit constants +============================================================================ */ +/** + * @cond arm_cstd_utilities + */ + +/* Common bit constant values, useful in embedded programming. */ +#define F_BIT_0 ((uint32_t)0x00000001) +#define F_BIT_1 ((uint32_t)0x00000002) +#define F_BIT_2 ((uint32_t)0x00000004) +#define F_BIT_3 ((uint32_t)0x00000008) +#define F_BIT_4 ((uint32_t)0x00000010) +#define F_BIT_5 ((uint32_t)0x00000020) +#define F_BIT_6 ((uint32_t)0x00000040) +#define F_BIT_7 ((uint32_t)0x00000080) +#define F_BIT_8 ((uint32_t)0x00000100) +#define F_BIT_9 ((uint32_t)0x00000200) +#define F_BIT_10 ((uint32_t)0x00000400) +#define F_BIT_11 ((uint32_t)0x00000800) +#define F_BIT_12 ((uint32_t)0x00001000) +#define F_BIT_13 ((uint32_t)0x00002000) +#define F_BIT_14 ((uint32_t)0x00004000) +#define F_BIT_15 ((uint32_t)0x00008000) +#define F_BIT_16 ((uint32_t)0x00010000) +#define F_BIT_17 ((uint32_t)0x00020000) +#define F_BIT_18 ((uint32_t)0x00040000) +#define F_BIT_19 ((uint32_t)0x00080000) +#define F_BIT_20 ((uint32_t)0x00100000) +#define F_BIT_21 ((uint32_t)0x00200000) +#define F_BIT_22 ((uint32_t)0x00400000) +#define F_BIT_23 ((uint32_t)0x00800000) +#define F_BIT_24 ((uint32_t)0x01000000) +#define F_BIT_25 ((uint32_t)0x02000000) +#define F_BIT_26 ((uint32_t)0x04000000) +#define F_BIT_27 ((uint32_t)0x08000000) +#define F_BIT_28 ((uint32_t)0x10000000) +#define F_BIT_29 ((uint32_t)0x20000000) +#define F_BIT_30 ((uint32_t)0x40000000) +#define F_BIT_31 ((uint32_t)0x80000000) + +/* Common 2^n size values, useful in embedded programming. */ +#define C_SIZE_1B ((uint32_t)0x00000001) +#define C_SIZE_2B ((uint32_t)0x00000002) +#define C_SIZE_4B ((uint32_t)0x00000004) +#define C_SIZE_8B ((uint32_t)0x00000008) +#define C_SIZE_16B ((uint32_t)0x00000010) +#define C_SIZE_32B ((uint32_t)0x00000020) +#define C_SIZE_64B ((uint32_t)0x00000040) +#define C_SIZE_128B ((uint32_t)0x00000080) +#define C_SIZE_256B ((uint32_t)0x00000100) +#define C_SIZE_512B ((uint32_t)0x00000200) +#define C_SIZE_1KB ((uint32_t)0x00000400) +#define C_SIZE_2KB ((uint32_t)0x00000800) +#define C_SIZE_4KB ((uint32_t)0x00001000) +#define C_SIZE_8KB ((uint32_t)0x00002000) +#define C_SIZE_16KB ((uint32_t)0x00004000) +#define C_SIZE_32KB ((uint32_t)0x00008000) +#define C_SIZE_64KB ((uint32_t)0x00010000) +#define C_SIZE_128KB ((uint32_t)0x00020000) +#define C_SIZE_256KB ((uint32_t)0x00040000) +#define C_SIZE_512KB ((uint32_t)0x00080000) +#define C_SIZE_1MB ((uint32_t)0x00100000) +#define C_SIZE_2MB ((uint32_t)0x00200000) +#define C_SIZE_4MB ((uint32_t)0x00400000) +#define C_SIZE_8MB ((uint32_t)0x00800000) +#define C_SIZE_16MB ((uint32_t)0x01000000) +#define C_SIZE_32MB ((uint32_t)0x02000000) +#define C_SIZE_64MB ((uint32_t)0x04000000) +#define C_SIZE_128MB ((uint32_t)0x08000000) +#define C_SIZE_256MB ((uint32_t)0x10000000) +#define C_SIZE_512MB ((uint32_t)0x20000000) +#define C_SIZE_1GB ((uint32_t)0x40000000) +#define C_SIZE_2GB ((uint32_t)0x80000000) + +/** + * @endcond + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_compilers.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_compilers.h new file mode 100644 index 0000000000000000000000000000000000000000..55637cf8afc030d5600e0535040cc462cfb328fc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_compilers.h @@ -0,0 +1,617 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_COMPILERS_H_ +#define _ARM_CSTD_COMPILERS_H_ + +/* ============================================================================ + Document default definitions - assuming nothing set at this point. +============================================================================ */ +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is Microsoft Visual Studio, 0 + * otherwise. + */ +#define CSTD_TOOLCHAIN_MSVC 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is the GNU Compiler Collection, 0 + * otherwise. + */ +#define CSTD_TOOLCHAIN_GCC 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is ARM RealView Compiler Tools, 0 + * otherwise. Note - if running RVCT in GCC mode this define will be set to 0; + * @c CSTD_TOOLCHAIN_GCC and @c CSTD_TOOLCHAIN_RVCT_GCC_MODE will both be + * defined as 1. + */ +#define CSTD_TOOLCHAIN_RVCT 0 + +/** + * @hideinitializer + * Defined with value of 1 if toolchain is ARM RealView Compiler Tools running + * in GCC mode, 0 otherwise. + */ +#define CSTD_TOOLCHAIN_RVCT_GCC_MODE 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an x86 32-bit machine, 0 otherwise. + */ +#define CSTD_CPU_X86_32 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an x86-64 (AMD64) machine, 0 + * otherwise. + */ +#define CSTD_CPU_X86_64 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an ARM machine, 0 otherwise. + */ +#define CSTD_CPU_ARM 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor is an AARCH64 machine, 0 otherwise. + */ +#define CSTD_CPU_AARCH64 0 + + +/** + * @hideinitializer + * Defined with value of 1 if processor is a MIPS machine, 0 otherwise. + */ +#define CSTD_CPU_MIPS 0 + +/** + * @hideinitializer + * Defined with value of 1 if CPU is 32-bit, 0 otherwise. + */ +#define CSTD_CPU_32BIT 0 + +/** + * @hideinitializer + * Defined with value of 1 if CPU is 64-bit, 0 otherwise. + */ +#define CSTD_CPU_64BIT 0 + +/** + * @hideinitializer + * Defined with value of 1 if processor configured as big-endian, 0 if it + * is little-endian. + */ +#define CSTD_CPU_BIG_ENDIAN 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a version of Windows, 0 if + * it is not. + */ +#define CSTD_OS_WINDOWS 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Windows, + * 0 if it is not. + */ +#define CSTD_OS_WIN32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Windows, + * 0 if it is not. + */ +#define CSTD_OS_WIN64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is Linux, 0 if it is not. + */ +#define CSTD_OS_LINUX 0 + +/** + * @hideinitializer + * Defined with value of 1 if we are compiling Linux kernel code, 0 otherwise. + */ +#define CSTD_OS_LINUX_KERNEL 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Linux, + * 0 if it is not. + */ +#define CSTD_OS_LINUX32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Linux, + * 0 if it is not. + */ +#define CSTD_OS_LINUX64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is Android, 0 if it is not. + */ +#define CSTD_OS_ANDROID 0 + +/** + * @hideinitializer + * Defined with value of 1 if we are compiling Android kernel code, 0 otherwise. + */ +#define CSTD_OS_ANDROID_KERNEL 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Android, + * 0 if it is not. + */ +#define CSTD_OS_ANDROID32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Android, + * 0 if it is not. + */ +#define CSTD_OS_ANDROID64 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 32-bit version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS32 0 + +/** + * @hideinitializer + * Defined with value of 1 if operating system is a 64-bit version of Apple OS, + * 0 if it is not. + */ +#define CSTD_OS_APPLEOS64 0 + +/** + * @def CSTD_OS_SYMBIAN + * @hideinitializer + * Defined with value of 1 if operating system is Symbian, 0 if it is not. + */ +#define CSTD_OS_SYMBIAN 0 + +/** + * @def CSTD_OS_NONE + * @hideinitializer + * Defined with value of 1 if there is no operating system (bare metal), 0 + * otherwise + */ +#define CSTD_OS_NONE 0 + +/* ============================================================================ + Determine the compiler in use +============================================================================ */ + +/* Default empty definitions of compiler-specific option enable/disable. This will be overridden + * if applicable by preprocessor defines below. */ +#define CSTD_PUSH_WARNING_GCC_WADDRESS +#define CSTD_POP_WARNING_GCC_WADDRESS + +#if defined(_MSC_VER) + #undef CSTD_TOOLCHAIN_MSVC + #define CSTD_TOOLCHAIN_MSVC 1 + +#elif defined(__GNUC__) + #undef CSTD_TOOLCHAIN_GCC + #define CSTD_TOOLCHAIN_GCC 1 + + /* Detect RVCT pretending to be GCC. */ + #if defined(__ARMCC_VERSION) + #undef CSTD_TOOLCHAIN_RVCT_GCC_MODE + #define CSTD_TOOLCHAIN_RVCT_GCC_MODE 1 + #endif + + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && MALI_GCC_WORKAROUND_MIDCOM_4598 == 0) + /* As a workaround to MIDCOM-4598 (GCC internal defect), these pragmas are not compiled if the GCC version + * is within a certain range, or if a #define is enabled by the build system. For more, see a comment + * in the build system also referring to the MIDCOM issue mentioned, where the environment is updated + * for the GNU toolchain. */ + #undef CSTD_PUSH_WARNING_GCC_WADDRESS + #define CSTD_PUSH_WARNING_GCC_WADDRESS \ + do\ + {\ + _Pragma("GCC diagnostic push")\ + _Pragma("GCC diagnostic ignored \"-Waddress\"")\ + }while(MALI_FALSE) + + #undef CSTD_POP_WARNING_GCC_WADDRESS + #define CSTD_POP_WARNING_GCC_WADDRESS \ + do\ + {\ + _Pragma("GCC diagnostic pop")\ + }while(MALI_FALSE) + #endif + +#elif defined(__ARMCC_VERSION) + #undef CSTD_TOOLCHAIN_RVCT + #define CSTD_TOOLCHAIN_RVCT 1 + +#else + #warning "Unsupported or unknown toolchain" + +#endif + +/* ============================================================================ + Determine the processor +============================================================================ */ +#if 1 == CSTD_TOOLCHAIN_MSVC + #if defined(_M_IX86) + #undef CSTD_CPU_X86_32 + #define CSTD_CPU_X86_32 1 + + #elif defined(_M_X64) || defined(_M_AMD64) + #undef CSTD_CPU_X86_64 + #define CSTD_CPU_X86_64 1 + + #elif defined(_M_ARM) + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + + #elif defined(_M_MIPS) + #undef CSTD_CPU_MIPS + #define CSTD_CPU_MIPS 1 + + #else + #warning "Unsupported or unknown host CPU for MSVC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_GCC + #if defined(__amd64__) + #undef CSTD_CPU_X86_64 + #define CSTD_CPU_X86_64 1 + + #elif defined(__i386__) + #undef CSTD_CPU_X86_32 + #define CSTD_CPU_X86_32 1 + + #elif defined(__arm__) + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + + #elif defined(__aarch64__) + #undef CSTD_CPU_AARCH64 + #define CSTD_CPU_AARCH64 1 + + #elif defined(__mips__) + #undef CSTD_CPU_MIPS + #define CSTD_CPU_MIPS 1 + + #else + #warning "Unsupported or unknown host CPU for GCC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_RVCT + #undef CSTD_CPU_ARM + #define CSTD_CPU_ARM 1 + +#else + #warning "Unsupported or unknown toolchain" + +#endif + +/* ============================================================================ + Determine the Processor Endianness +============================================================================ */ + +#if ((1 == CSTD_CPU_X86_32) || (1 == CSTD_CPU_X86_64)) + /* Note: x86 and x86-64 are always little endian, so leave at default. */ + +#elif 1 == CSTD_CPU_AARCH64 + /* No big endian support? */ + +#elif 1 == CSTD_TOOLCHAIN_RVCT + #if defined(__BIG_ENDIAN) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif ((1 == CSTD_TOOLCHAIN_GCC) && (1 == CSTD_CPU_ARM)) + #if defined(__ARMEB__) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif ((1 == CSTD_TOOLCHAIN_GCC) && (1 == CSTD_CPU_MIPS)) + #if defined(__MIPSEB__) + #undef CSTD_ENDIAN_BIG + #define CSTD_ENDIAN_BIG 1 + #endif + +#elif 1 == CSTD_TOOLCHAIN_MSVC + /* Note: Microsoft only support little endian, so leave at default. */ + +#else + #warning "Unsupported or unknown CPU" + +#endif + +/* ============================================================================ + Determine the operating system and addressing width +============================================================================ */ +#if 1 == CSTD_TOOLCHAIN_MSVC + #if defined(_WIN32) && !defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN32 + #define CSTD_OS_WIN32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #elif defined(_WIN32) && defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN64 + #define CSTD_OS_WIN64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + + #else + #warning "Unsupported or unknown host OS for MSVC tools" + + #endif + +#elif 1 == CSTD_TOOLCHAIN_GCC + #if defined(_WIN32) && defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN64 + #define CSTD_OS_WIN64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + + #elif defined(_WIN32) && !defined(_WIN64) + #undef CSTD_OS_WINDOWS + #define CSTD_OS_WINDOWS 1 + #undef CSTD_OS_WIN32 + #define CSTD_OS_WIN32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #elif defined(ANDROID) + #undef CSTD_OS_ANDROID + #define CSTD_OS_ANDROID 1 + + #if defined(__KERNEL__) + #undef CSTD_OS_ANDROID_KERNEL + #define CSTD_OS_ANDROID_KERNEL 1 + #endif + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_ANDROID64 + #define CSTD_OS_ANDROID64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_ANDROID32 + #define CSTD_OS_ANDROID32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__KERNEL__) || defined(__linux) + #undef CSTD_OS_LINUX + #define CSTD_OS_LINUX 1 + + #if defined(__KERNEL__) + #undef CSTD_OS_LINUX_KERNEL + #define CSTD_OS_LINUX_KERNEL 1 + #endif + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_LINUX64 + #define CSTD_OS_LINUX64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_LINUX32 + #define CSTD_OS_LINUX32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__APPLE__) + #undef CSTD_OS_APPLEOS + #define CSTD_OS_APPLEOS 1 + + #if defined(__LP64__) || defined(_LP64) + #undef CSTD_OS_APPLEOS64 + #define CSTD_OS_APPLEOS64 1 + #undef CSTD_CPU_64BIT + #define CSTD_CPU_64BIT 1 + #else + #undef CSTD_OS_APPLEOS32 + #define CSTD_OS_APPLEOS32 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + #endif + + #elif defined(__SYMBIAN32__) + #undef CSTD_OS_SYMBIAN + #define CSTD_OS_SYMBIAN 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + + #else + #undef CSTD_OS_NONE + #define CSTD_OS_NONE 1 + #undef CSTD_CPU_32BIT + #define CSTD_CPU_32BIT 1 + +#endif + +#elif 1 == CSTD_TOOLCHAIN_RVCT + + #if defined(ANDROID) + #undef CSTD_OS_ANDROID + #undef CSTD_OS_ANDROID32 + #define CSTD_OS_ANDROID 1 + #define CSTD_OS_ANDROID32 1 + + #elif defined(__linux) + #undef CSTD_OS_LINUX + #undef CSTD_OS_LINUX32 + #define CSTD_OS_LINUX 1 + #define CSTD_OS_LINUX32 1 + + #elif defined(__SYMBIAN32__) + #undef CSTD_OS_SYMBIAN + #define CSTD_OS_SYMBIAN 1 + + #else + #undef CSTD_OS_NONE + #define CSTD_OS_NONE 1 + +#endif + +#else + #warning "Unsupported or unknown host OS" + +#endif + +/* ============================================================================ + Determine the correct linker symbol Import and Export Macros +============================================================================ */ +/** + * @defgroup arm_cstd_linkage_specifiers Linkage Specifiers + * @{ + * + * This set of macros contain system-dependent linkage specifiers which + * determine the visibility of symbols across DLL boundaries. A header for a + * particular DLL should define a set of local macros derived from these, + * and should not use these macros to decorate functions directly as there may + * be multiple DLLs being used. + * + * These DLL library local macros should be (with appropriate library prefix) + * [MY_LIBRARY]_API, [MY_LIBRARY]_IMPL, and + * [MY_LIBRARY]_LOCAL. + * + * - [MY_LIBRARY]_API should be use to decorate the function + * declarations in the header. It should be defined as either + * @c CSTD_LINK_IMPORT or @c CSTD_LINK_EXPORT, depending whether the + * current situation is a compile of the DLL itself (use export) or a + * compile of an external user of the DLL (use import). + * - [MY_LIBRARY]_IMPL should be defined as @c CSTD_LINK_IMPL + * and should be used to decorate the definition of functions in the C + * file. + * - [MY_LIBRARY]_LOCAL should be used to decorate function + * declarations which are exported across translation units within the + * DLL, but which are not exported outside of the DLL boundary. + * + * Functions which are @c static in either a C file or in a header file do not + * need any form of linkage decoration, and should therefore have no linkage + * macro applied to them. + */ + +/** + * @def CSTD_LINK_IMPORT + * Specifies a function as being imported to a translation unit across a DLL + * boundary. + */ + +/** + * @def CSTD_LINK_EXPORT + * Specifies a function as being exported across a DLL boundary by a + * translation unit. + */ + +/** + * @def CSTD_LINK_IMPL + * Specifies a function which will be exported across a DLL boundary as + * being implemented by a translation unit. + */ + +/** + * @def CSTD_LINK_LOCAL + * Specifies a function which is internal to a DLL, and which should not be + * exported outside of it. + */ + +/** + * @} + */ + +#if 1 == CSTD_OS_LINUX + #define CSTD_LINK_IMPORT __attribute__((visibility("default"))) + #define CSTD_LINK_EXPORT __attribute__((visibility("default"))) + #define CSTD_LINK_IMPL __attribute__((visibility("default"))) + #define CSTD_LINK_LOCAL __attribute__((visibility("hidden"))) + +#elif 1 == CSTD_OS_WINDOWS + #define CSTD_LINK_IMPORT __declspec(dllimport) + #define CSTD_LINK_EXPORT __declspec(dllexport) + #define CSTD_LINK_IMPL __declspec(dllexport) + #define CSTD_LINK_LOCAL + +#elif 1 == CSTD_OS_SYMBIAN + #define CSTD_LINK_IMPORT IMPORT_C + #define CSTD_LINK_EXPORT IMPORT_C + #define CSTD_LINK_IMPL EXPORT_C + #define CSTD_LINK_LOCAL + +#elif 1 == CSTD_OS_APPLEOS + #define CSTD_LINK_IMPORT __attribute__((visibility("default"))) + #define CSTD_LINK_EXPORT __attribute__((visibility("default"))) + #define CSTD_LINK_IMPL __attribute__((visibility("default"))) + #define CSTD_LINK_LOCAL __attribute__((visibility("hidden"))) + +#elif 1 == CSTD_OS_ANDROID + #define CSTD_LINK_IMPORT __attribute__((visibility("default"))) + #define CSTD_LINK_EXPORT __attribute__((visibility("default"))) + #define CSTD_LINK_IMPL __attribute__((visibility("default"))) + #define CSTD_LINK_LOCAL __attribute__((visibility("hidden"))) + +#else /* CSTD_OS_NONE */ + #define CSTD_LINK_IMPORT + #define CSTD_LINK_EXPORT + #define CSTD_LINK_IMPL + #define CSTD_LINK_LOCAL + +#endif + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_COMPILERS_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_pop.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_pop.h new file mode 100644 index 0000000000000000000000000000000000000000..20862ec1fa79e6bcb9c1cf5c4f0d2f1ed2bc19b1 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_pop.h @@ -0,0 +1,27 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_PACK_POP_H_ +#define _ARM_CSTD_PACK_POP_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include +#endif + +#endif /* End (_ARM_CSTD_PACK_POP_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_push.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_push.h new file mode 100644 index 0000000000000000000000000000000000000000..bc24e6942b11d0cddd056fbe55b36800f36a81be --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_pack_push.h @@ -0,0 +1,27 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_PACK_PUSH_H_ +#define _ARM_CSTD_PACK_PUSH_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include +#endif + +#endif /* End (_ARM_CSTD_PACK_PUSH_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types.h new file mode 100644 index 0000000000000000000000000000000000000000..efeefa590c6527e2e270a75c454b21e001d3a042 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_TYPES_H_ +#define _ARM_CSTD_TYPES_H_ + +#if 1 == CSTD_TOOLCHAIN_MSVC + #include "arm_cstd_types_msvc.h" +#elif 1 == CSTD_TOOLCHAIN_GCC + #include "arm_cstd_types_gcc.h" +#elif 1 == CSTD_TOOLCHAIN_RVCT + #include "arm_cstd_types_rvct.h" +#else + #error "Toolchain not recognized" +#endif + +#endif /* End (_ARM_CSTD_TYPES_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_gcc.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_gcc.h new file mode 100644 index 0000000000000000000000000000000000000000..679819655002f928a65f8a22aff6517aa0990ec9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_gcc.h @@ -0,0 +1,92 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_TYPES_GCC_H_ +#define _ARM_CSTD_TYPES_GCC_H_ + +/* ============================================================================ + Type definitions +============================================================================ */ +/* All modern versions of GCC support stdint outside of C99 Mode. */ +/* However, Linux kernel limits what headers are available! */ +#if 1 == CSTD_OS_LINUX_KERNEL + #include + #include + #include + #include + + /* Fix up any types which CSTD provdes but which Linux is missing. */ + /* Note Linux assumes pointers are "long", so this is safe. */ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + typedef unsigned long uintptr_t; + #endif + typedef long intptr_t; + +#else + #include + #include + #include +#endif + +typedef uint32_t bool_t; + +#if !defined(TRUE) + #define TRUE ((bool_t)1) +#endif + +#if !defined(FALSE) + #define FALSE ((bool_t)0) +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/* Doxygen documentation for these is in the RVCT header. */ +#define ASM __asm__ + +#define INLINE __inline__ + +#define FORCE_INLINE __attribute__((__always_inline__)) __inline__ + +#define NEVER_INLINE __attribute__((__noinline__)) + +#define PURE __attribute__((__pure__)) + +#define PACKED __attribute__((__packed__)) + +/* GCC does not support pointers to UNALIGNED data, so we do not define it to + * force a compile error if this macro is used. */ + +#define RESTRICT __restrict__ + +/* RVCT in GCC mode does not support the CHECK_RESULT attribute. */ +#if 0 == CSTD_TOOLCHAIN_RVCT_GCC_MODE + #define CHECK_RESULT __attribute__((__warn_unused_result__)) +#else + #define CHECK_RESULT +#endif + +/* RVCT in GCC mode does not support the __func__ name outside of C99. */ +#if (0 == CSTD_TOOLCHAIN_RVCT_GCC_MODE) + #define CSTD_FUNC __func__ +#else + #define CSTD_FUNC __FUNCTION__ +#endif + +#endif /* End (_ARM_CSTD_TYPES_GCC_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_rvct.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_rvct.h new file mode 100644 index 0000000000000000000000000000000000000000..a8efda0040a148da5230cf0fef2735f52e04db1d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/arm_cstd/arm_cstd_types_rvct.h @@ -0,0 +1,192 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _ARM_CSTD_TYPES_RVCT_H_ +#define _ARM_CSTD_TYPES_RVCT_H_ + +/* ============================================================================ + Type definitions +============================================================================ */ +#include +#include + +#if 199901L <= __STDC_VERSION__ + #include +#else + typedef unsigned char uint8_t; + typedef signed char int8_t; + typedef unsigned short uint16_t; + typedef signed short int16_t; + typedef unsigned int uint32_t; + typedef signed int int32_t; + typedef unsigned __int64 uint64_t; + typedef signed __int64 int64_t; + typedef ptrdiff_t intptr_t; + typedef size_t uintptr_t; +#endif + +typedef uint32_t bool_t; + +#if !defined(TRUE) + #define TRUE ((bool_t)1) +#endif + +#if !defined(FALSE) + #define FALSE ((bool_t)0) +#endif + +/* ============================================================================ + Keywords +============================================================================ */ +/** + * @addtogroup arm_cstd_coding_standard + * @{ + */ + +/** + * @def ASM + * @hideinitializer + * Mark an assembler block. Such blocks are often compiler specific, so often + * need to be surrounded in appropriate @c ifdef and @c endif blocks + * using the relevant @c CSTD_TOOLCHAIN macro. + */ +#define ASM __asm + +/** + * @def INLINE + * @hideinitializer + * Mark a definition as something which should be inlined. This is not always + * possible on a given compiler, and may be disabled at lower optimization + * levels. + */ +#define INLINE __inline + +/** + * @def FORCE_INLINE + * @hideinitializer + * Mark a definition as something which should be inlined. This provides a much + * stronger hint to the compiler than @c INLINE, and if supported should always + * result in an inlined function being emitted. If not supported this falls + * back to using the @c INLINE definition. + */ +#define FORCE_INLINE __forceinline + +/** + * @def NEVER_INLINE + * @hideinitializer + * Mark a definition as something which should not be inlined. This provides a + * stronger hint to the compiler than the function should not be inlined, + * bypassing any heuristic rules the compiler normally applies. If not + * supported by a toolchain this falls back to being an empty macro. + */ +#define NEVER_INLINE __declspec(noinline) + +/** + * @def PURE + * @hideinitializer + * Denotes that a function's return is only dependent on its inputs, enabling + * more efficient optimizations. Falls back to an empty macro if not supported. + */ +#define PURE __pure + +/** + * @def PACKED + * @hideinitializer + * Denotes that a structure should be stored in a packed form. This macro must + * be used in conjunction with the @c arm_cstd_pack_* headers for portability: + * + * @code + * #include + * + * struct PACKED myStruct { + * ... + * }; + * + * #include + * PACKED + * @endcode + */ +#define PACKED __packed + +/** + * @def UNALIGNED + * @hideinitializer + * Denotes that a pointer points to a buffer with lower alignment than the + * natural alignment required by the C standard. This should only be used + * in extreme cases, as the emitted code is normally more efficient if memory + * is aligned. + * + * @warning This is \b NON-PORTABLE. The GNU tools are anti-unaligned pointers + * and have no support for such a construction. + */ +#define UNALIGNED __packed + +/** + * @def RESTRICT + * @hideinitializer + * Denotes that a pointer does not overlap with any other points currently in + * scope, increasing the range of optimizations which can be performed by the + * compiler. + * + * @warning Specification of @c RESTRICT is a contract between the programmer + * and the compiler. If you place @c RESTICT on buffers which do actually + * overlap the behavior is undefined, and likely to vary at different + * optimization levels.! + */ +#define RESTRICT __restrict + +/** + * @def CHECK_RESULT + * @hideinitializer + * Function attribute which causes a warning to be emitted if the compiler's + * return value is not used by the caller. Compiles to an empty macro if + * there is no supported mechanism for this check in the underlying compiler. + * + * @note At the time of writing this is only supported by GCC. RVCT does not + * support this attribute, even in GCC mode, so engineers are encouraged to + * compile their code using GCC even if primarily working with another + * compiler. + * + * @code + * CHECK_RESULT int my_func( void ); + * @endcode + */ +#define CHECK_RESULT + +/** + * @def CSTD_FUNC + * Specify the @c CSTD_FUNC macro, a portable construct containing the name of + * the current function. On most compilers it is illegal to use this macro + * outside of a function scope. If not supported by the compiler we define + * @c CSTD_FUNC as an empty string. + * + * @warning Due to the implementation of this on most modern compilers this + * expands to a magically defined "static const" variable, not a constant + * string. This makes injecting @c CSTD_FUNC directly in to compile-time + * strings impossible, so if you want to make the function name part of a + * larger string you must use a printf-like function with a @c @%s template + * which is populated with @c CSTD_FUNC + */ +#define CSTD_FUNC __FUNCTION__ + +/** + * @} + */ + +#endif /* End (_ARM_CSTD_TYPES_RVCT_H_) */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/mali_malisw.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/mali_malisw.h new file mode 100644 index 0000000000000000000000000000000000000000..15faf15bf13afb74ad3c99a6b962ecbca4da5c12 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/mali_malisw.h @@ -0,0 +1,242 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _MALISW_H_ +#define _MALISW_H_ + +/** + * @file mali_malisw.h + * Driver-wide include for common macros and types. + */ + +/** + * @defgroup malisw Mali software definitions and types + * @{ + */ + +#include + +#include "mali_stdtypes.h" + +/** @brief Gets the container object when given a pointer to a member of an object. */ +#define CONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type,member))) + +/** @brief Gets the number of elements of type s in a fixed length array of s */ +#define NELEMS(s) (sizeof(s)/sizeof((s)[0])) + +/** + * @brief The lesser of two values. + * May evaluate its arguments more than once. + * @see CSTD_MIN + */ +#define MIN(x,y) CSTD_MIN(x,y) + +/** + * @brief The greater of two values. + * May evaluate its arguments more than once. + * @see CSTD_MAX + */ +#define MAX(x,y) CSTD_MAX(x,y) + +/** + * @brief Clamp value x to within min and max inclusive + * May evaluate its arguments more than once. + * @see CSTD_CLAMP + */ +#define CLAMP( x, min, max ) CSTD_CLAMP( x, min, max ) + +/** + * @brief Convert a pointer into a u64 for storing in a data structure. + * This is commonly used when pairing a 32-bit CPU with a 64-bit peripheral, + * such as a Midgard GPU. C's type promotion is complex and a straight cast + * does not work reliably as pointers are often considered as signed. + */ +#define PTR_TO_U64( x ) CSTD_PTR_TO_U64( x ) + +/** + * @name Mali library linkage specifiers + * These directly map to the cstd versions described in detail here: @ref arm_cstd_linkage_specifiers + * @{ + */ +#define MALI_IMPORT CSTD_LINK_IMPORT +#define MALI_EXPORT CSTD_LINK_EXPORT +#define MALI_IMPL CSTD_LINK_IMPL +#if defined(CONFIG_MALI_DEBUG) || !MALI_CUSTOMER_RELEASE +#define MALI_LOCAL CSTD_LINK_EXPORT +#else +#define MALI_LOCAL CSTD_LINK_LOCAL +#endif + +/** @brief Decorate exported function prototypes. + * + * The file containing the implementation of the function should define this to be MALI_EXPORT before including + * malisw/mali_malisw.h. + */ +#ifndef MALI_API +#define MALI_API MALI_IMPORT +#endif +/** @} */ + +/** @name Testable static functions + * @{ + * + * These macros can be used to allow functions to be static in release builds but exported from a shared library in unit + * test builds, allowing them to be tested or used to assist testing. + * + * Example mali_foo_bar.c containing the function to test: + * + * @code + * #define MALI_API MALI_EXPORT + * + * #include + * #include "mali_foo_testable_statics.h" + * + * MALI_TESTABLE_STATIC_IMPL void my_func() + * { + * //Implementation + * } + * @endcode + * + * Example mali_foo_testable_statics.h: + * + * @code + * #if 1 == MALI_UNIT_TEST + * #include + * + * MALI_TESTABLE_STATIC_API void my_func(); + * + * #endif + * @endcode + * + * Example mali_foo_tests.c: + * + * @code + * #include + * + * void my_test_func() + * { + * my_func(); + * } + * @endcode + */ + +/** @brief Decorate testable static function implementations. + * + * A header file containing a MALI_TESTABLE_STATIC_API-decorated prototype for each static function will be required + * when MALI_UNIT_TEST == 1 in order to link the function from the test. + */ +#if 1 == MALI_UNIT_TEST +#define MALI_TESTABLE_STATIC_IMPL MALI_IMPL +#else +#define MALI_TESTABLE_STATIC_IMPL static +#endif + +/** @brief Decorate testable static function prototypes. + * + * @note Prototypes should @em only be declared when MALI_UNIT_TEST == 1 + */ +#define MALI_TESTABLE_STATIC_API MALI_API +/** @} */ + +/** @name Testable local functions + * @{ + * + * These macros can be used to allow functions to be local to a shared library in release builds but be exported in unit + * test builds, allowing them to be tested or used to assist testing. + * + * Example mali_foo_bar.c containing the function to test: + * + * @code + * #define MALI_API MALI_EXPORT + * + * #include + * #include "mali_foo_bar.h" + * + * MALI_TESTABLE_LOCAL_IMPL void my_func() + * { + * //Implementation + * } + * @endcode + * + * Example mali_foo_bar.h: + * + * @code + * #include + * + * MALI_TESTABLE_LOCAL_API void my_func(); + * + * @endcode + * + * Example mali_foo_tests.c: + * + * @code + * #include + * + * void my_test_func() + * { + * my_func(); + * } + * @endcode + */ + +/** @brief Decorate testable local function implementations. + * + * This can be used to have a function normally local to the shared library except in debug builds where it will be + * exported. + */ +#ifdef CONFIG_MALI_DEBUG +#define MALI_TESTABLE_LOCAL_IMPL MALI_IMPL +#else +#define MALI_TESTABLE_LOCAL_IMPL MALI_LOCAL +#endif /* CONFIG_MALI_DEBUG */ + +/** @brief Decorate testable local function prototypes. + * + * This can be used to have a function normally local to the shared library except in debug builds where it will be + * exported. + */ +#ifdef CONFIG_MALI_DEBUG +#define MALI_TESTABLE_LOCAL_API MALI_API +#else +#define MALI_TESTABLE_LOCAL_API MALI_LOCAL +#endif /* CONFIG_MALI_DEBUG */ +/** @} */ + +/** + * Flag a cast as a reinterpretation, usually of a pointer type. + * @see CSTD_REINTERPRET_CAST + */ +#define REINTERPRET_CAST(type) CSTD_REINTERPRET_CAST(type) + +/** + * Flag a cast as casting away const, usually of a pointer type. + * @see CSTD_CONST_CAST + */ +#define CONST_CAST(type) (type) CSTD_CONST_CAST(type) + +/** + * Flag a cast as a (potentially complex) value conversion, usually of a numerical type. + * @see CSTD_STATIC_CAST + */ +#define STATIC_CAST(type) (type) CSTD_STATIC_CAST(type) + + +/** @} */ + +#endif /* _MALISW_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/mali_stdtypes.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/mali_stdtypes.h new file mode 100644 index 0000000000000000000000000000000000000000..5dabe26ec01c29f82c57fbe2c19472853e0a22c4 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/malisw/mali_stdtypes.h @@ -0,0 +1,265 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _MALISW_STDTYPES_H_ +#define _MALISW_STDTYPES_H_ + +/** + * @file mali_stdtypes.h + * This file defines the standard types used by the Mali codebase. + */ + +/** + * @addtogroup malisw + * @{ + */ + +/** + * @defgroup malisw_stdtypes Mali software standard types + * + * Basic driver-wide types. + */ + +/** + * @addtogroup malisw_stdtypes + * @{ + */ + +#include "arm_cstd/arm_cstd.h" + +/** + * @name Scalar types. + * These are the scalar types used within the mali driver. + * @{ + */ +/* Note: if compiling the Linux kernel then avoid redefining these. */ +#if 0 == CSTD_OS_LINUX_KERNEL + typedef uint64_t u64; + typedef uint32_t u32; + typedef uint16_t u16; + typedef uint8_t u8; + + typedef int64_t s64; + typedef int32_t s32; + typedef int16_t s16; + typedef int8_t s8; +#endif + +typedef double f64; +typedef float f32; +typedef u16 f16; + +typedef u32 mali_fixed16_16; +/* @} */ + +/** + * @name Boolean types. + * The intended use is for bool8 to be used when storing boolean values in + * structures, casting to mali_bool to be used in code sections. + * @{ + */ +typedef bool_t mali_bool; +typedef u8 mali_bool8; + +#define MALI_FALSE FALSE +#define MALI_TRUE TRUE +/* @} */ + +/** + * @name Integer bounding values + * Maximum and minimum values for integer types + * @{ + */ +#ifndef U64_MAX +#define U64_MAX UINT64_MAX +#endif + +#ifndef U32_MAX +#define U32_MAX UINT32_MAX +#endif + +#ifndef U16_MAX +#define U16_MAX UINT16_MAX +#endif + +#ifndef U8_MAX +#define U8_MAX UINT8_MAX +#endif + +#ifndef S64_MAX +#define S64_MAX INT64_MAX +#endif + +#ifndef S64_MIN +#define S64_MIN INT64_MIN +#endif + +#ifndef S32_MAX +#define S32_MAX INT32_MAX +#endif + +#ifndef S32_MIN +#define S32_MIN INT32_MIN +#endif + +#ifndef S16_MAX +#define S16_MAX INT16_MAX +#endif + +#ifndef S16_MIN +#define S16_MIN INT16_MIN +#endif + +#ifndef S8_MAX +#define S8_MAX INT8_MAX +#endif + +#ifndef S8_MIN +#define S8_MIN INT8_MIN +#endif + +/* @} */ + +/** + * @name GPU address types + * Types for integers which hold a GPU pointer or GPU pointer offsets. + * @{ + */ +typedef u64 mali_addr64; +typedef u32 mali_addr32; +typedef u64 mali_size64; +typedef s64 mali_offset64; +/* 32 bit offsets and sizes are always for native types and so use ptrdiff_t and size_t respectively */ +/* @} */ + +/** + * @name Mali error types + * @brief The common error type for the mali drivers + * The mali_error type, all driver error handling should be of this type unless + * it must deal with a specific APIs error type. + * @{ + */ +typedef enum +{ + /** + * @brief Common Mali errors for the entire driver + * MALI_ERROR_NONE is guaranteed to be 0. + * @{ + */ + MALI_ERROR_NONE = 0, + MALI_ERROR_OUT_OF_GPU_MEMORY, + MALI_ERROR_OUT_OF_MEMORY, + MALI_ERROR_FUNCTION_FAILED, + /* @} */ + /** + * @brief Mali errors for Client APIs to pass to EGL when creating EGLImages + * These errors must only be returned to EGL from one of the Client APIs as part of the + * (clientapi)_egl_image_interface.h + * @{ + */ + MALI_ERROR_EGLP_BAD_ACCESS, + MALI_ERROR_EGLP_BAD_PARAMETER, + /* @} */ + /** + * @brief Mali errors for the MCL module. + * These errors must only be used within the private components of the OpenCL implementation that report + * directly to API functions for cases where errors cannot be detected in the entrypoints file. They must + * not be passed between driver components. + * These are errors in the mali error space specifically for the MCL module, hence the MCLP prefix. + * @{ + */ + MALI_ERROR_MCLP_DEVICE_NOT_FOUND, + MALI_ERROR_MCLP_DEVICE_NOT_AVAILABLE, + MALI_ERROR_MCLP_COMPILER_NOT_AVAILABLE, + MALI_ERROR_MCLP_MEM_OBJECT_ALLOCATION_FAILURE, + MALI_ERROR_MCLP_PROFILING_INFO_NOT_AVAILABLE, + MALI_ERROR_MCLP_MEM_COPY_OVERLAP, + MALI_ERROR_MCLP_IMAGE_FORMAT_MISMATCH, + MALI_ERROR_MCLP_IMAGE_FORMAT_NOT_SUPPORTED, + MALI_ERROR_MCLP_BUILD_PROGRAM_FAILURE, + MALI_ERROR_MCLP_MAP_FAILURE, + MALI_ERROR_MCLP_MISALIGNED_SUB_BUFFER_OFFSET, + MALI_ERROR_MCLP_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, + MALI_ERROR_MCLP_INVALID_VALUE, + MALI_ERROR_MCLP_INVALID_DEVICE_TYPE, + MALI_ERROR_MCLP_INVALID_PLATFORM, + MALI_ERROR_MCLP_INVALID_DEVICE, + MALI_ERROR_MCLP_INVALID_CONTEXT, + MALI_ERROR_MCLP_INVALID_QUEUE_PROPERTIES, + MALI_ERROR_MCLP_INVALID_COMMAND_QUEUE, + MALI_ERROR_MCLP_INVALID_HOST_PTR, + MALI_ERROR_MCLP_INVALID_MEM_OBJECT, + MALI_ERROR_MCLP_INVALID_IMAGE_FORMAT_DESCRIPTOR, + MALI_ERROR_MCLP_INVALID_IMAGE_SIZE, + MALI_ERROR_MCLP_INVALID_SAMPLER, + MALI_ERROR_MCLP_INVALID_BINARY, + MALI_ERROR_MCLP_INVALID_BUILD_OPTIONS, + MALI_ERROR_MCLP_INVALID_PROGRAM, + MALI_ERROR_MCLP_INVALID_PROGRAM_EXECUTABLE, + MALI_ERROR_MCLP_INVALID_KERNEL_NAME, + MALI_ERROR_MCLP_INVALID_KERNEL_DEFINITION, + MALI_ERROR_MCLP_INVALID_KERNEL, + MALI_ERROR_MCLP_INVALID_ARG_INDEX, + MALI_ERROR_MCLP_INVALID_ARG_VALUE, + MALI_ERROR_MCLP_INVALID_ARG_SIZE, + MALI_ERROR_MCLP_INVALID_KERNEL_ARGS, + MALI_ERROR_MCLP_INVALID_WORK_DIMENSION, + MALI_ERROR_MCLP_INVALID_WORK_GROUP_SIZE, + MALI_ERROR_MCLP_INVALID_WORK_ITEM_SIZE, + MALI_ERROR_MCLP_INVALID_GLOBAL_OFFSET, + MALI_ERROR_MCLP_INVALID_EVENT_WAIT_LIST, + MALI_ERROR_MCLP_INVALID_EVENT, + MALI_ERROR_MCLP_INVALID_OPERATION, + MALI_ERROR_MCLP_INVALID_GL_OBJECT, + MALI_ERROR_MCLP_INVALID_BUFFER_SIZE, + MALI_ERROR_MCLP_INVALID_MIP_LEVEL, + MALI_ERROR_MCLP_INVALID_GLOBAL_WORK_SIZE, + MALI_ERROR_MCLP_INVALID_GL_SHAREGROUP_REFERENCE_KHR, + MALI_ERROR_MCLP_INVALID_EGL_OBJECT, + /* @} */ + /** + * @brief Mali errors for the BASE module + * These errors must only be used within the private components of the Base implementation. They will not + * passed to other modules by the base driver. + * These are errors in the mali error space specifically for the BASE module, hence the BASEP prefix. + * @{ + */ + MALI_ERROR_BASEP_INVALID_FUNCTION, + /* @} */ + /** A dependency exists upon a resource that the client application wants to modify, so the driver must either + * create a copy of the resource (if possible) or block until the dependency has been satisfied. + */ + MALI_ERROR_RESOURCE_IN_USE, + + /** + * @brief A stride value was too big. + * + * A surface descriptor can store strides of up to 231-1 bytes but strides greater than + * 228-1 bytes cannot be expressed in bits without overflow. + */ + MALI_ERROR_STRIDE_TOO_BIG + +} mali_error; +/* @} */ + +/* @} */ + +/* @} */ + +#endif /* _MALISW_STDTYPES_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..558657bbced900f03f3b2532c14a8d33b29fb377 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/Kbuild @@ -0,0 +1,21 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y) +# remove begin and end quotes from the Kconfig string type + platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)) + obj-y += $(platform_name)/ +endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..8fb4e917c4fa37407c5c11e707ba019910e0e184 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/Kconfig @@ -0,0 +1,24 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +# Add your platform specific Kconfig file here +# +# "drivers/gpu/arm/midgard/platform/xxx/Kconfig" +# +# Where xxx is the platform name is the name set in MALI_PLATFORM_THIRDPARTY_NAME +# + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..f6af6220be12a503fafe4a387465f43af65b3912 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/Kbuild @@ -0,0 +1,19 @@ +# +# (C) COPYRIGHT 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +obj-y += mali_kbase_config_juno_soc.o + + +obj-m += juno_mali_opp.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/juno_mali_opp.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/juno_mali_opp.c new file mode 100644 index 0000000000000000000000000000000000000000..f137226f409aee9742551821a044cd47e3994003 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/juno_mali_opp.c @@ -0,0 +1,73 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include +#include + + +static int init_juno_opps_from_scpi(struct device *dev) +{ + struct scpi_opp *sopp; + int i; + + /* Hard coded for Juno. 2 is GPU domain */ + sopp = scpi_dvfs_get_opps(2); + if (IS_ERR_OR_NULL(sopp)) + return PTR_ERR(sopp); + + for (i = 0; i < sopp->count; i++) { + struct scpi_opp_entry *e = &sopp->opp[i]; + dev_info(dev, "Mali OPP from SCPI: %u Hz @ %u mV\n", + e->freq_hz, e->volt_mv); + + dev_pm_opp_add(dev, e->freq_hz, e->volt_mv * 1000); + } + + return 0; +} + +static int juno_setup_opps(void) +{ + struct device_node *np; + struct platform_device *pdev; + int err; + + np = of_find_node_by_name(NULL, "gpu"); + if (!np) { + pr_err("Failed to find DT entry for Mali\n"); + return -EFAULT; + } + + pdev = of_find_device_by_node(np); + if (!pdev) { + pr_err("Failed to find device for Mali\n"); + of_node_put(np); + return -EFAULT; + } + + err = init_juno_opps_from_scpi(&pdev->dev); + + of_node_put(np); + + return err; +} + +module_init(juno_setup_opps); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_juno_soc.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_juno_soc.c new file mode 100644 index 0000000000000000000000000000000000000000..d8f14330528030afc6b091a2a5b16ef16f52df8b --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_juno_soc.c @@ -0,0 +1,134 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include + +#include "../mali_kbase_power_actor.h" + +/* Versatile Express (VE) Juno Development Platform */ + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 65, + .mmu_irq_number = 66, + .gpu_irq_number = 64, + .io_memory_region = { + .start = 0x2D000000, + .end = 0x2D000000 + (4096 * 4) - 1} +}; +#endif + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +static unsigned long juno_model_static_power(unsigned long voltage, unsigned long temperature) +{ + /* Calculate power, corrected for voltage. + * Shifts are done to avoid overflow. */ + const unsigned long coefficient = (410UL << 20) / (729000000UL >> 10); + const unsigned long voltage_cubed = (voltage * voltage * voltage) >> 10; + + /* Calculate the temperature scaling factor. To be applied to the + * voltage scaled power. */ + const unsigned long temp = temperature / 1000; + const unsigned long temp_squared = temp * temp; + const unsigned long temp_cubed = temp_squared * temp; + const unsigned long temp_scaling_factor = + (2 * temp_cubed) + - (80 * temp_squared) + + (4700 * temp) + + 32000; + + return (((coefficient * voltage_cubed) >> 20) * temp_scaling_factor) / 1000000; +} + +static unsigned long juno_model_dynamic_power(unsigned long freq, + unsigned long voltage) +{ + /* The inputs: freq (f) is in Hz, and voltage (v) in mV. + * The coefficient (c) is in mW/(MHz mV mV). + * + * This function calculates the dynamic power after this formula: + * Pdyn (mW) = c (mW/(MHz*mV*mV)) * v (mV) * v (mV) * f (MHz) + */ + const unsigned long v2 = (voltage * voltage) / 1000; /* m*(V*V) */ + const unsigned long f_mhz = freq / 1000000; /* MHz */ + const unsigned long coefficient = 3600; /* mW/(MHz*mV*mV) */ + + return (coefficient * v2 * f_mhz) / 1000000; /* mW */ +} + +static struct mali_pa_model_ops juno_model_ops = { + .get_static_power = juno_model_static_power, + .get_dynamic_power = juno_model_dynamic_power, +}; + +static struct kbase_attribute config_attributes[] = { + { KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, 500 }, + { KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, ((uintptr_t)&pm_callbacks) }, + { KBASE_CONFIG_ATTR_POWER_MODEL_CALLBACKS, ((uintptr_t)&juno_model_ops) }, + + { KBASE_CONFIG_ATTR_END, 0 } +}; + +static struct kbase_platform_config versatile_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..196de7129a578f6f2c4d2cc7a4d0be0ed2bcdbb9 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/juno_soc/mali_kbase_config_platform.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 600000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 600000 diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h new file mode 100644 index 0000000000000000000000000000000000000000..b0d8e3249b8058904a3e5d55ffa085a25d87533d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * @brief Entry point to transfer control to a platform for early initialization + * + * This function is called early on in the initialization during execution of + * @ref kbase_driver_init. + * + * @return Zero to indicate success non-zero for failure. + */ +int kbase_platform_early_init(void); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..084a156134363034dd636be4671b9c49dbb6b4a3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +obj-y += mali_kbase_config_vexpress.o +obj-y += mali_kbase_cpu_vexpress.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..81259485ee00b3c7662d976c06472612a14bba0f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 5000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 5000 diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..09389910cdbeadb08c66b27567547bfbe89e49c7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c @@ -0,0 +1,337 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#if defined(CONFIG_MTK_CLKMGR) +#include "mach/mt_clkmgr.h" +#endif /* defined(CONFIG_MTK_CLKMGR) */ +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif /* !defined(CONFIG_MTK_CLKMGR) */ +/* Versatile Express (VE) configuration defaults shared between config_attributes[] + * and config_attributes_hw_issue_8408[]. Settings are not shared for + * JS_HARD_STOP_TICKS_SS and JS_RESET_TICKS_SS. + */ +#define KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG 15000000u /* 15ms, an agressive tick for testing purposes. This will reduce performance significantly */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG 1 /* between 15ms and 30ms before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG 1 /* between 15ms and 30ms before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG 333 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG 2000 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG 166 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG 100000 /* 1500s (25mins) before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS_DEBUG 500 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG 3000 /* 7.5s before resetting GPU - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL_DEBUG 500 /* 45s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS_DEBUG 100166 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_SCHEDULING_TICK_NS 1250000000u /* 1.25s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS 2 /* 2.5s before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL 1 /* 1.25s before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS 4 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401 24 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL 2 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS 1200 /* 1500s before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS 6 /* 7.5s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401 36 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL 3 /* 7.5s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS 1201 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_RESET_TIMEOUT_MS 3000 /* 3s before cancelling stuck jobs */ +#define KBASE_VE_JS_CTX_TIMESLICE_NS 1000000 /* 1ms - an agressive timeslice for testing purposes (causes lots of scheduling out for >4 ctxs) */ +#define KBASE_VE_POWER_MANAGEMENT_CALLBACKS ((uintptr_t)&pm_callbacks) +#define KBASE_VE_CPU_SPEED_FUNC ((uintptr_t)&kbase_get_vexpress_cpu_clock_speed) + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0xFC010000, + .end = 0xFC010000 + (4096 * 4) - 1 + } +}; +#endif /* CONFIG_OF */ + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + int ret; +#if defined(CONFIG_MTK_CLKMGR) + enable_clock( MT_CG_DISP0_SMI_COMMON, "GPU"); + enable_clock( MT_CG_MFG_BG3D, "GPU"); +#else + ret = clk_prepare_enable(kbdev->clk_display_scp); + if (ret) + { + pr_debug("MALI: clk_prepare_enable failed when enabling display MTCMOS"); + } + + ret = clk_prepare_enable(kbdev->clk_smi_common); + if (ret) + { + pr_debug("MALI: clk_prepare_enable failed when enabling display smi_common clock"); + } + + ret = clk_prepare_enable(kbdev->clk_mfg_scp); + if (ret) + { + pr_debug("MALI: clk_prepare_enable failed when enabling mfg MTCMOS"); + } + + ret = clk_prepare_enable(kbdev->clk_mfg); + if (ret) + { + pr_debug("MALI: clk_prepare_enable failed when enabling mfg clock"); + } +#endif + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif + /* MTK clock modified */ +#if defined(CONFIG_MTK_CLKMGR) + disable_clock( MT_CG_MFG_BG3D, "GPU"); + disable_clock( MT_CG_DISP0_SMI_COMMON, "GPU"); +#else + clk_disable_unprepare(kbdev->clk_mfg); + clk_disable_unprepare(kbdev->clk_mfg_scp); + clk_disable_unprepare(kbdev->clk_smi_common); + clk_disable_unprepare(kbdev->clk_display_scp); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +/* Please keep table config_attributes in sync with config_attributes_hw_issue_8408 */ +static struct kbase_attribute config_attributes[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +/* as config_attributes array above except with different settings for + * JS_HARD_STOP_TICKS_SS, JS_RESET_TICKS_SS that + * are needed for BASE_HW_ISSUE_8408. + */ +struct kbase_attribute config_attributes_hw_issue_8408[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +static struct kbase_platform_config versatile_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..3dd6c0f5504604ee3b184d8dfa45bb4f007cdde8 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.c @@ -0,0 +1,180 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HZ_IN_MHZ (1000000) + +#define CORETILE_EXPRESS_A9X4_SCC_START (0x100E2000) +#define MOTHERBOARD_SYS_CFG_START (0x10000000) +#define SYS_CFGDATA_OFFSET (0x000000A0) +#define SYS_CFGCTRL_OFFSET (0x000000A4) +#define SYS_CFGSTAT_OFFSET (0x000000A8) + +#define SYS_CFGCTRL_START_BIT_VALUE (1 << 31) +#define READ_REG_BIT_VALUE (0 << 30) +#define DCC_DEFAULT_BIT_VALUE (0 << 26) +#define SYS_CFG_OSC_FUNC_BIT_VALUE (1 << 20) +#define SITE_DEFAULT_BIT_VALUE (1 << 16) +#define BOARD_STACK_POS_DEFAULT_BIT_VALUE (0 << 12) +#define DEVICE_DEFAULT_BIT_VALUE (2 << 0) +#define SYS_CFG_COMPLETE_BIT_VALUE (1 << 0) +#define SYS_CFG_ERROR_BIT_VALUE (1 << 1) + +#define FEED_REG_BIT_MASK (0x0F) +#define FCLK_PA_DIVIDE_BIT_SHIFT (0x03) +#define FCLK_PB_DIVIDE_BIT_SHIFT (0x07) +#define FCLK_PC_DIVIDE_BIT_SHIFT (0x0B) +#define AXICLK_PA_DIVIDE_BIT_SHIFT (0x0F) +#define AXICLK_PB_DIVIDE_BIT_SHIFT (0x13) + +#define IS_SINGLE_BIT_SET(val, pos) (val&(1<> FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[10:7] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PB_DIVIDE_BIT_SHIFT)) >> FCLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + if (IS_SINGLE_BIT_SET(reg_val, 1)) { /*CFGRW0[1] - CLKOC */ + /* CFGRW0[6:3] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PA_DIVIDE_BIT_SHIFT)) >> FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[14:11] */ + pc_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PC_DIVIDE_BIT_SHIFT)) >> FCLK_PC_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pc_divide + 1); + } else if (IS_SINGLE_BIT_SET(reg_val, 2)) { /*CFGRW0[2] - FACLK */ + /* CFGRW0[18:15] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << AXICLK_PA_DIVIDE_BIT_SHIFT)) >> AXICLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[22:19] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << AXICLK_PB_DIVIDE_BIT_SHIFT)) >> AXICLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + result = 1; + } + } + } + } else { + result = 1; + } + raw_spin_unlock(&syscfg_lock); + /* Convert result expressed in Hz to Mhz units. */ + *cpu_clock /= HZ_IN_MHZ; + if (!result) + { + cpu_clock_speed = *cpu_clock; + } + + /* Unmap memory */ + iounmap(pSCCReg); + + pSCCReg_map_failed: + iounmap(pSysCfgReg); + + pSysCfgReg_map_failed: + + return result; + } +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.h new file mode 100644 index 0000000000000000000000000000000000000000..f607d1800a72ccebf372fa01079fe50e0aa57d62 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.h @@ -0,0 +1,28 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KBASE_CPU_VEXPRESS_H_ +#define _KBASE_CPU_VEXPRESS_H_ + +/** + * Versatile Express implementation of @ref kbase_cpuprops_clock_speed_function. + */ +int kbase_get_vexpress_cpu_clock_speed(u32 *cpu_clock); + +#endif /* _KBASE_CPU_VEXPRESS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..d9bfabc28b6bcb9bbded96b4441610a8f8ce9592 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild @@ -0,0 +1,16 @@ +# +# (C) COPYRIGHT 2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +obj-y += mali_kbase_config_vexpress.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..81259485ee00b3c7662d976c06472612a14bba0f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 5000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 5000 diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..0ec2821d256f0920328a4d318789534a26c803d7 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c @@ -0,0 +1,279 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include +#include + +/* Versatile Express (VE) configuration defaults shared between config_attributes[] + * and config_attributes_hw_issue_8408[]. Settings are not shared for + * JS_HARD_STOP_TICKS_SS and JS_RESET_TICKS_SS. + */ +#define KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG 3000000000u /* 3s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG 10 /* 30s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG 5 /* 15s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG 20 /* 60s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG 120 /* 360s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG 10 /* 30s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG 6000 /* 18000s */ +#define KBASE_VE_JS_RESET_TICKS_SS_DEBUG 30 /* 180s */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG 180 /* 540s */ +#define KBASE_VE_JS_RESET_TICKS_CL_DEBUG 30 /* 180s */ +#define KBASE_VE_JS_RESET_TICKS_NSS_DEBUG 6010 /* 18030s*/ + +#define KBASE_VE_JS_SCHEDULING_TICK_NS 3000000000u /* 3s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS 10 /* 30s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL 5 /* 15s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS 20 /* 60s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401 120 /* 360s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL 10 /* 30s */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS 6000 /* 18000s */ +#define KBASE_VE_JS_RESET_TICKS_SS 30 /* 180s */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401 180 /* 540s */ +#define KBASE_VE_JS_RESET_TICKS_CL 30 /* 180s */ +#define KBASE_VE_JS_RESET_TICKS_NSS 6010 /* 18030s*/ + +#define KBASE_VE_JS_RESET_TIMEOUT_MS 3000 /* 3s before cancelling stuck jobs */ +#define KBASE_VE_JS_CTX_TIMESLICE_NS 1000000 /* 1ms - an agressive timeslice for testing purposes (causes lots of scheduling out for >4 ctxs) */ +#define KBASE_VE_POWER_MANAGEMENT_CALLBACKS ((uintptr_t)&pm_callbacks) + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0x2f010000, + .end = 0x2f010000 + (4096 * 4) - 1} +}; +#endif + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +/* Please keep table config_attributes in sync with config_attributes_hw_issue_8408 */ +static struct kbase_attribute config_attributes[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +/* as config_attributes array above except with different settings for + * JS_HARD_STOP_TICKS_SS, JS_RESET_TICKS_SS that + * are needed for BASE_HW_ISSUE_8408. + */ +struct kbase_attribute config_attributes_hw_issue_8408[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +static struct kbase_platform_config versatile_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..0cb41ce8952d462a7f9ee0842368ba76837d218c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +obj-y += mali_kbase_config_vexpress.o +obj-y += mali_kbase_cpu_vexpress.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..ad6bfb2d59a8f44eef823ced6414d35cf758b27f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h @@ -0,0 +1,33 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * Maximum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MAX 10000 +/** + * Minimum frequency GPU will be clocked at. Given in kHz. + * This must be specified as there is no default value. + * + * Attached value: number in kHz + * Default value: NA + */ +#define GPU_FREQ_KHZ_MIN 10000 diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..f1921c02bb8c583f7a94d5443308d1b94f0c2519 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c @@ -0,0 +1,292 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +/* Versatile Express (VE) configuration defaults shared between config_attributes[] + * and config_attributes_hw_issue_8408[]. Settings are not shared for + * JS_HARD_STOP_TICKS_SS and JS_RESET_TICKS_SS. + */ +#define KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG 15000000u /* 15ms, an agressive tick for testing purposes. This will reduce performance significantly */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG 1 /* between 15ms and 30ms before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG 1 /* between 15ms and 30ms before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG 333 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG 2000 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG 166 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG 100000 /* 1500s (25mins) before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS_DEBUG 500 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG 3000 /* 7.5s before resetting GPU - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL_DEBUG 500 /* 45s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS_DEBUG 100166 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_SCHEDULING_TICK_NS 1250000000u /* 1.25s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS 2 /* 2.5s before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL 1 /* 1.25s before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS 4 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401 24 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL 2 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS 1200 /* 1500s before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS 6 /* 7.5s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401 36 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL 3 /* 3.75s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS 1201 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_RESET_TIMEOUT_MS 3000 /* 3s before cancelling stuck jobs */ +#define KBASE_VE_JS_CTX_TIMESLICE_NS 1000000 /* 1ms - an agressive timeslice for testing purposes (causes lots of scheduling out for >4 ctxs) */ +#define KBASE_VE_POWER_MANAGEMENT_CALLBACKS ((uintptr_t)&pm_callbacks) +#define KBASE_VE_CPU_SPEED_FUNC ((uintptr_t)&kbase_get_vexpress_cpu_clock_speed) + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static struct kbase_io_resources io_resources = { + .job_irq_number = 75, + .mmu_irq_number = 76, + .gpu_irq_number = 77, + .io_memory_region = { + .start = 0x2F000000, + .end = 0x2F000000 + (4096 * 4) - 1} +}; +#endif + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +/* Please keep table config_attributes in sync with config_attributes_hw_issue_8408 */ +static struct kbase_attribute config_attributes[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +/* as config_attributes array above except with different settings for + * JS_HARD_STOP_TICKS_SS, JS_RESET_TICKS_SS that + * are needed for BASE_HW_ISSUE_8408. + */ +struct kbase_attribute config_attributes_hw_issue_8408[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +static struct kbase_platform_config versatile_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &versatile_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..1577f8cef7877e638193d54e4a7eb5361b0d77f6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c @@ -0,0 +1,71 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HZ_IN_MHZ (1000000) + +#define CORETILE_EXPRESS_A9X4_SCC_START (0x100E2000) +#define MOTHERBOARD_SYS_CFG_START (0x10000000) +#define SYS_CFGDATA_OFFSET (0x000000A0) +#define SYS_CFGCTRL_OFFSET (0x000000A4) +#define SYS_CFGSTAT_OFFSET (0x000000A8) + +#define SYS_CFGCTRL_START_BIT_VALUE (1 << 31) +#define READ_REG_BIT_VALUE (0 << 30) +#define DCC_DEFAULT_BIT_VALUE (0 << 26) +#define SYS_CFG_OSC_FUNC_BIT_VALUE (1 << 20) +#define SITE_DEFAULT_BIT_VALUE (1 << 16) +#define BOARD_STACK_POS_DEFAULT_BIT_VALUE (0 << 12) +#define DEVICE_DEFAULT_BIT_VALUE (2 << 0) +#define SYS_CFG_COMPLETE_BIT_VALUE (1 << 0) +#define SYS_CFG_ERROR_BIT_VALUE (1 << 1) + +#define FEED_REG_BIT_MASK (0x0F) +#define FCLK_PA_DIVIDE_BIT_SHIFT (0x03) +#define FCLK_PB_DIVIDE_BIT_SHIFT (0x07) +#define FCLK_PC_DIVIDE_BIT_SHIFT (0x0B) +#define AXICLK_PA_DIVIDE_BIT_SHIFT (0x0F) +#define AXICLK_PB_DIVIDE_BIT_SHIFT (0x13) + +#define IS_SINGLE_BIT_SET(val, pos) (val&(1< +#include +#include +#include + +#include "mali_kbase_cpu_vexpress.h" + +/* Versatile Express (VE) configuration defaults shared between config_attributes[] + * and config_attributes_hw_issue_8408[]. Settings are not shared for + * JS_HARD_STOP_TICKS_SS and JS_RESET_TICKS_SS. + */ +#define KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG 15000000u /* 15ms, an agressive tick for testing purposes. This will reduce performance significantly */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG 1 /* between 15ms and 30ms before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG 1 /* between 15ms and 30ms before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG 333 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG 2000 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG 166 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG 100000 /* 1500s (25mins) before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS_DEBUG 500 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG 3000 /* 7.5s before resetting GPU - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL_DEBUG 500 /* 45s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS_DEBUG 100166 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_SCHEDULING_TICK_NS 1250000000u /* 1.25s */ +#define KBASE_VE_JS_SOFT_STOP_TICKS 2 /* 2.5s before soft-stop a job */ +#define KBASE_VE_JS_SOFT_STOP_TICKS_CL 1 /* 1.25s before soft-stop a CL job */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS 4 /* 5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_SS_8401 24 /* 30s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_HARD_STOP_TICKS_CL 2 /* 2.5s before hard-stop */ +#define KBASE_VE_JS_HARD_STOP_TICKS_NSS 1200 /* 1500s before NSS hard-stop */ +#define KBASE_VE_JS_RESET_TICKS_SS 6 /* 7.5s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_SS_8401 36 /* 45s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) - for issue 8401 */ +#define KBASE_VE_JS_RESET_TICKS_CL 3 /* 3.75s before resetting GPU */ +#define KBASE_VE_JS_RESET_TICKS_NSS 1201 /* 1502s before resetting GPU */ + +#define KBASE_VE_JS_RESET_TIMEOUT_MS 3000 /* 3s before cancelling stuck jobs */ +#define KBASE_VE_JS_CTX_TIMESLICE_NS 1000000 /* 1ms - an agressive timeslice for testing purposes (causes lots of scheduling out for >4 ctxs) */ +#define KBASE_VE_POWER_MANAGEMENT_CALLBACKS ((uintptr_t)&pm_callbacks) +#define KBASE_VE_CPU_SPEED_FUNC ((uintptr_t)&kbase_get_vexpress_cpu_clock_speed) + +#define HARD_RESET_AT_POWER_OFF 0 + +#ifndef CONFIG_OF +static kbase_io_resources io_resources = { + .job_irq_number = 68, + .mmu_irq_number = 69, + .gpu_irq_number = 70, + .io_memory_region = { + .start = 0xFC010000, + .end = 0xFC010000 + (4096 * 4) - 1 + } + +}; +#endif /* CONFIG_OF */ + +static int pm_callback_power_on(struct kbase_device *kbdev) +{ + /* Nothing is needed on VExpress, but we may have destroyed GPU state (if the below HARD_RESET code is active) */ + return 1; +} + +static void pm_callback_power_off(struct kbase_device *kbdev) +{ +#if HARD_RESET_AT_POWER_OFF + /* Cause a GPU hard reset to test whether we have actually idled the GPU + * and that we properly reconfigure the GPU on power up. + * Usually this would be dangerous, but if the GPU is working correctly it should + * be completely safe as the GPU should not be active at this point. + * However this is disabled normally because it will most likely interfere with + * bus logging etc. + */ + KBASE_TRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, NULL, 0u, 0); + kbase_os_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_HARD_RESET); +#endif +} + +static struct kbase_pm_callback_conf pm_callbacks = { + .power_on_callback = pm_callback_power_on, + .power_off_callback = pm_callback_power_off, + .power_suspend_callback = NULL, + .power_resume_callback = NULL +}; + +/* Please keep table config_attributes in sync with config_attributes_hw_issue_8408 */ +static struct kbase_attribute config_attributes[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL, + KBASE_VE_JS_SOFT_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL, + KBASE_VE_JS_HARD_STOP_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL, + KBASE_VE_JS_RESET_TICKS_CL}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +/* as config_attributes array above except with different settings for + * JS_HARD_STOP_TICKS_SS, JS_RESET_TICKS_SS that + * are needed for BASE_HW_ISSUE_8408. + */ +struct kbase_attribute config_attributes_hw_issue_8408[] = { +#ifdef CONFIG_MALI_DEBUG +/* Use more aggressive scheduling timeouts in debug builds for testing purposes */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401_DEBUG}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS_DEBUG}, +#else /* CONFIG_MALI_DEBUG */ +/* In release builds same as the defaults but scaled for 5MHz FPGA */ + { + KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS, + KBASE_VE_JS_SCHEDULING_TICK_NS}, + + { + KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS, + KBASE_VE_JS_SOFT_STOP_TICKS}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS, + KBASE_VE_JS_HARD_STOP_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS, + KBASE_VE_JS_HARD_STOP_TICKS_NSS}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS, + KBASE_VE_JS_RESET_TICKS_SS_8401}, + + { + KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS, + KBASE_VE_JS_RESET_TICKS_NSS}, +#endif /* CONFIG_MALI_DEBUG */ + { + KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS, + KBASE_VE_JS_RESET_TIMEOUT_MS}, + + { + KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS, + KBASE_VE_JS_CTX_TIMESLICE_NS}, + + { + KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS, + KBASE_VE_POWER_MANAGEMENT_CALLBACKS}, + + { + KBASE_CONFIG_ATTR_CPU_SPEED_FUNC, + KBASE_VE_CPU_SPEED_FUNC}, + + { + KBASE_CONFIG_ATTR_END, + 0} +}; + +static struct kbase_platform_config virtex7_platform_config = { + .attributes = config_attributes, +#ifndef CONFIG_OF + .io_resources = &io_resources +#endif +}; + +struct kbase_platform_config *kbase_get_platform_config(void) +{ + return &virtex7_platform_config; +} + +int kbase_platform_early_init(void) +{ + /* Nothing needed at this stage */ + return 0; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.c new file mode 100644 index 0000000000000000000000000000000000000000..f0036a34545374744b2afd8e5b376a6adc91fe42 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.c @@ -0,0 +1,178 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include "mali_kbase_cpu_vexpress.h" + +#define HZ_IN_MHZ (1000000) + +#define CORETILE_EXPRESS_A9X4_SCC_START (0x100E2000) +#define MOTHERBOARD_SYS_CFG_START (0x10000000) +#define SYS_CFGDATA_OFFSET (0x000000A0) +#define SYS_CFGCTRL_OFFSET (0x000000A4) +#define SYS_CFGSTAT_OFFSET (0x000000A8) + +#define SYS_CFGCTRL_START_BIT_VALUE (1 << 31) +#define READ_REG_BIT_VALUE (0 << 30) +#define DCC_DEFAULT_BIT_VALUE (0 << 26) +#define SYS_CFG_OSC_FUNC_BIT_VALUE (1 << 20) +#define SITE_DEFAULT_BIT_VALUE (1 << 16) +#define BOARD_STACK_POS_DEFAULT_BIT_VALUE (0 << 12) +#define DEVICE_DEFAULT_BIT_VALUE (2 << 0) +#define SYS_CFG_COMPLETE_BIT_VALUE (1 << 0) +#define SYS_CFG_ERROR_BIT_VALUE (1 << 1) + +#define FEED_REG_BIT_MASK (0x0F) +#define FCLK_PA_DIVIDE_BIT_SHIFT (0x03) +#define FCLK_PB_DIVIDE_BIT_SHIFT (0x07) +#define FCLK_PC_DIVIDE_BIT_SHIFT (0x0B) +#define AXICLK_PA_DIVIDE_BIT_SHIFT (0x0F) +#define AXICLK_PB_DIVIDE_BIT_SHIFT (0x13) + +#define IS_SINGLE_BIT_SET(val, pos) (val&(1<> FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[10:7] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PB_DIVIDE_BIT_SHIFT)) >> FCLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + if (IS_SINGLE_BIT_SET(reg_val, 1)) { /*CFGRW0[1] - CLKOC */ + /* CFGRW0[6:3] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PA_DIVIDE_BIT_SHIFT)) >> FCLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[14:11] */ + pc_divide = ((reg_val & (FEED_REG_BIT_MASK << FCLK_PC_DIVIDE_BIT_SHIFT)) >> FCLK_PC_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pc_divide + 1); + } else if (IS_SINGLE_BIT_SET(reg_val, 2)) { /*CFGRW0[2] - FACLK */ + /* CFGRW0[18:15] */ + pa_divide = ((reg_val & (FEED_REG_BIT_MASK << AXICLK_PA_DIVIDE_BIT_SHIFT)) >> AXICLK_PA_DIVIDE_BIT_SHIFT); + /* CFGRW0[22:19] */ + pb_divide = ((reg_val & (FEED_REG_BIT_MASK << AXICLK_PB_DIVIDE_BIT_SHIFT)) >> AXICLK_PB_DIVIDE_BIT_SHIFT); + *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1); + } else { + result = 1; + } + } + } + } else { + result = 1; + } + raw_spin_unlock(&syscfg_lock); + /* Convert result expressed in Hz to Mhz units. */ + *cpu_clock /= HZ_IN_MHZ; + if (!result) + { + cpu_clock_speed = *cpu_clock; + } + + /* Unmap memory */ + iounmap(pSCCReg); + + pSCCReg_map_failed: + iounmap(pSysCfgReg); + + pSysCfgReg_map_failed: + + return result; + } +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.h new file mode 100644 index 0000000000000000000000000000000000000000..3f6c68ece3928a718a22674be5a14399be9c2771 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform/vexpress_virtex7_40mhz/mali_kbase_cpu_vexpress.h @@ -0,0 +1,26 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _KBASE_CPU_VEXPRESS_H_ +#define _KBASE_CPU_VEXPRESS_H_ + +/** + * Versatile Express implementation of @ref kbase_cpuprops_clock_speed_function. + */ +int kbase_get_vexpress_cpu_clock_speed(u32 *cpu_clock); + +#endif /* _KBASE_CPU_VEXPRESS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform_dummy/mali_ukk_os.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform_dummy/mali_ukk_os.h new file mode 100644 index 0000000000000000000000000000000000000000..daaa8c0198a50c04b1fac6f4875bb701abeb830a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/platform_dummy/mali_ukk_os.h @@ -0,0 +1,54 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file mali_ukk_os.h + * Types and definitions that are common for Linux OSs for the kernel side of the + * User-Kernel interface. + */ + +#ifndef _UKK_OS_H_ /* Linux version */ +#define _UKK_OS_H_ + +#include + +/** + * @addtogroup uk_api User-Kernel Interface API + * @{ + */ + +/** + * @addtogroup uk_api_kernel UKK (Kernel side) + * @{ + */ + +/** + * Internal OS specific data structure associated with each UKK session. Part + * of a ukk_session object. + */ +typedef struct ukkp_session +{ + int dummy; /**< No internal OS specific data at this time */ +} ukkp_session; + +/** @} end group uk_api_kernel */ + +/** @} end group uk_api */ + +#endif /* _UKK_OS_H__ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..230ce4b7a23403ed13f7764d0de3b2e90a0d2c62 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/sconscript @@ -0,0 +1,114 @@ +# +# (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +import os +import re +import sys +Import('env') + +if Glob('tests/sconscript'): + SConscript( 'tests/sconscript' ) + +mock_test = 0 + +if env['v'] != '1': + env['MAKECOMSTR'] = '[MAKE] ${SOURCE.dir}' + +# Fake platform is a transient solution for GPL drivers running in kernel that does not provide configuration via platform data. +# For such kernels fake_platform_device should be set to 1. For kernels providing platform data fake_platform_device should be set to 0. +fake_platform_device = 1 + +# Source files required for kbase. +kbase_src = [Glob('#kernel/drivers/gpu/arm/midgard/*.c'), + Glob('#kernel/drivers/gpu/arm/midgard/*.c'), + Glob('#kernel/drivers/gpu/arm/midgard/platform/%s/*.c' % (env['platform_config'])), + Glob('#kernel/drivers/gpu/arm/midgard/*.h'), + Glob('#kernel/drivers/gpu/arm/midgard/*.h'), + ] + +kbase_src += [Glob('#kernel/drivers/gpu/arm/midgard/internal/*/*.c')] + +if Glob('#kernel/drivers/gpu/arm/midgard/tests/internal/src/mock') and env['unit'] == '1': + kbase_src += [Glob('#kernel/drivers/gpu/arm/midgard/tests/internal/src/mock/*.c')] + mock_test = 1 + +# we need platform config for GPL version using fake platform +if fake_platform_device==1: + # Check if we are compiling for PBX + linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' + search_term = '^[\ ]*CONFIG_MACH_REALVIEW_PBX[\ ]*=[\ ]*y' + REALVIEW_PBX = 0 + for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + REALVIEW_PBX = 1 + break + if REALVIEW_PBX == 1 and (env['platform_config'] == 'vexpress' or env['platform_config'] == 'vexpress_virtex7_40mhz' or env['platform_config'] == 'vexpress_6xvirtex7_10mhz'): + sys.stderr.write("WARNING: Building for a PBX kernel but with platform_config=vexpress*\n") + # if the file platform config file is in the tpip directory then use that, otherwise use the default config directory + if Glob('#kernel/drivers/gpu/arm/midgard/config/tpip/*%s.c' % (env['platform_config'])): + kbase_src += Glob('#kernel/drivers/gpu/arm/midgard/config/tpip/*%s.c' % (env['platform_config'])) + else: + kbase_src += Glob('#kernel/drivers/gpu/arm/midgard/config/*%s.c' % (env['platform_config'])) + +# Note: cleaning via the Linux kernel build system does not yet work +if env.GetOption('clean') : + makeAction=Action("cd ${SOURCE.dir} && make clean", '$MAKECOMSTR') + cmd = env.Command(['$STATIC_LIB_PATH/mali_kbase.ko', '$STATIC_LIB_PATH/mali_platform_fake.ko'], kbase_src, [makeAction]) +else: + if env['os'] == 'android': + env['android'] = 1 + else: + env['android'] = 0 + + if env['unit'] == '1': + env['kernel_test'] = 1 + else: + env['kernel_test'] = 0 + + makeAction=Action("cd ${SOURCE.dir} && make PLATFORM=${platform} MALI_ERROR_INJECT_ON=${error_inject} MALI_ANDROID=${android} MALI_KERNEL_TEST_API=${kernel_test} MALI_UNIT_TEST=${unit} MALI_RELEASE_NAME=\"${mali_release_name}\" MALI_MOCK_TEST=%s MALI_CUSTOMER_RELEASE=${release} MALI_INSTRUMENTATION_LEVEL=${instr} MALI_COVERAGE=${coverage} %s && cp mali_kbase.ko $STATIC_LIB_PATH/mali_kbase.ko" % (mock_test, env.kernel_get_config_defines(fake_platform_device)), '$MAKECOMSTR') + cmd = env.Command('$STATIC_LIB_PATH/mali_kbase.ko', kbase_src, [makeAction]) + +# Add a dependency on kds.ko. +# Only necessary when KDS is not built into the kernel. +# +if env['os'] != 'android': + linux_config_file = os.path.normpath(os.environ['KDIR']) + '/.config' + search_term = '^[\ ]*CONFIG_KDS[\ ]*=[\ ]*y' + kds_in_kernel = 0 + for line in open(linux_config_file, 'r'): + if re.search(search_term, line): + # KDS in kernel. + kds_in_kernel = 1 + if not kds_in_kernel: + env.Depends('$STATIC_LIB_PATH/mali_kbase.ko', '$STATIC_LIB_PATH/kds.ko') + +# need Module.symvers from ump.ko build +if int(env['ump']) == 1: + env.Depends('$STATIC_LIB_PATH/mali_kbase.ko', '$STATIC_LIB_PATH/ump.ko') + +# Until we fathom out how the invoke the Linux build system to clean, we can use Clean +# to remove generated files. +patterns = ['*.mod.c', '*.o', '*.ko', '*.a', '.*.cmd', 'modules.order', '.tmp_versions', 'Module.symvers'] + +for p in patterns: + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/config/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/tests/internal/src/mock/%s' % p)) + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/platform/%s/%s' % ((env['platform_config']), p) )) + Clean(cmd, Glob('#kernel/drivers/gpu/arm/midgard/internal/*/%s' % p)) +env.ProgTarget('kbase', cmd) + +env.AppendUnique(BASE=['cutils_list']) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/tests/customer/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/tests/customer/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..508e3724e9baeba5405a1dc517f0fcb4801e4258 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/tests/customer/sconscript @@ -0,0 +1,8 @@ +# This confidential and proprietary software may be used only as +# authorised by a licensing agreement from ARM Limited +# (C) COPYRIGHT 2010-2011, 2013 ARM Limited +# ALL RIGHTS RESERVED +# The entire notice above must be reproduced on all authorised +# copies and copies may only be made to the extent permitted +# by a licensing agreement from ARM Limited. + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/tests/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/tests/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..67040eecd036af46cf0dac2f8c110499140c0096 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/midgard/tests/sconscript @@ -0,0 +1,11 @@ +# This confidential and proprietary software may be used only as +# authorised by a licensing agreement from ARM Limited +# (C) COPYRIGHT 2010-2011, 2013 ARM Limited +# ALL RIGHTS RESERVED +# The entire notice above must be reproduced on all authorised +# copies and copies may only be made to the extent permitted +# by a licensing agreement from ARM Limited. + +SConscript( 'customer/sconscript' ) +if Glob('internal/sconscript'): + SConscript( 'internal/sconscript' ) diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..c31eec7cc1708ff68215b16443bc6b598a90da61 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/sconscript @@ -0,0 +1,18 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +SConscript('midgard/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/t6xx/license.txt b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/t6xx/license.txt new file mode 100755 index 0000000000000000000000000000000000000000..77c14bdc45b8c8ae9daa55c279a09296363aab30 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/arm/t6xx/license.txt @@ -0,0 +1,198 @@ +GPLV2 LICENCE AGREEMENT FOR MALI GPUS LINUX KERNEL DEVICE DRIVERS SOURCE CODE + +THE USE OF THE SOFTWARE ACCOMPANYING THIS DOCUMENT IS EXPRESSLY SUBJECT TO THE TERMS OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION AND SET OUT BELOW FOR REFERENCE (?GPL LICENCE?). ARM IS ONLY WILLING TO DISTRIBUTE THE SOFTWARE TO YOU ON CONDITION THAT YOU ACCEPT ALL OF THE TERMS IN THE GPL LICENCE PRIOR TO MODIFYING OR DISTRIBUTING THE SOFTWARE. + + + +Further for the period of three (3) years, ARM hereby offers to make available the source code of any part of the software program that is supplied as object code or in executable form. + + + +GPL Licence + + + +GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + + + +Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + + + +Preamble + + + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + + + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + + + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + + + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + + + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + + + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + + + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + + + +The precise terms and conditions for copying, distribution and modification follow. + + + +GNU GENERAL PUBLIC LICENSE + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + + + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). + +Whether that is true depends on what the Program does. + + + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; + +and give any other recipients of the Program a copy of this License along with the Program. + + + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + + +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + + +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + + +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + + + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + + + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + + + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + + + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + + +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + + +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + + +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + + + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + + + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + + + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + + + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the + +Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + + + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. + +You are not responsible for enforcing compliance by third parties to this License. + + + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + + + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + + + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + + + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + + + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + + + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + + + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + + + +NO WARRANTY + + + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +/end + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Kbuild b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Kbuild new file mode 100755 index 0000000000000000000000000000000000000000..f10d58c70dff212a6b00fbf0e6dbb0e415ec8d51 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Kbuild @@ -0,0 +1,28 @@ +# +# (C) COPYRIGHT ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +pl111_drm-y += pl111_drm_device.o \ + pl111_drm_connector.o \ + pl111_drm_crtc.o \ + pl111_drm_cursor.o \ + pl111_drm_dma_buf.o \ + pl111_drm_encoder.o \ + pl111_drm_fb.o \ + pl111_drm_gem.o \ + pl111_drm_pl111.o \ + pl111_drm_platform.o \ + pl111_drm_suspend.o \ + pl111_drm_vma.o + +obj-$(CONFIG_DRM_PL111) += pl111_drm.o diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Kconfig b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Kconfig new file mode 100755 index 0000000000000000000000000000000000000000..60b465c56c5137a3f06e2ca057d4fc6f29071bfc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Kconfig @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + +config DRM_PL111 + tristate "DRM Support for PL111 CLCD Controller" + depends on DRM + select DRM_KMS_HELPER + select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE + help + Choose this option for DRM support for the PL111 CLCD controller. + If M is selected the module will be called pl111_drm. + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Makefile b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..2869f587266b96eb0793ab0168aa1d24341ffb2c --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/Makefile @@ -0,0 +1,32 @@ +# +# (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +# linux build system bootstrap for out-of-tree module + +# default to building for the host +ARCH ?= $(shell uname -m) + +ifeq ($(KDIR),) +$(error Must specify KDIR to point to the kernel to target)) +endif + +all: pl111_drm + +pl111_drm: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_DMA_SHARED_BUFFER_USES_KDS=y CONFIG_DRM_PL111=m + +clean: + $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_clcd_ext.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_clcd_ext.h new file mode 100644 index 0000000000000000000000000000000000000000..43f212efac6b8cf40066a731daef41ee8c50bbd3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_clcd_ext.h @@ -0,0 +1,95 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +/** + * pl111_clcd_ext.h + * Extended CLCD register definitions + */ + +#ifndef PL111_CLCD_EXT_H_ +#define PL111_CLCD_EXT_H_ + +/* + * PL111 cursor register definitions not defined in the kernel's clcd header. + * + * TODO MIDEGL-1718: move to include/linux/amba/clcd.h + */ + +#define CLCD_CRSR_IMAGE 0x00000800 +#define CLCD_CRSR_IMAGE_MAX_WORDS 256 +#define CLCD_CRSR_IMAGE_WORDS_PER_LINE 4 +#define CLCD_CRSR_IMAGE_PIXELS_PER_WORD 16 + +#define CLCD_CRSR_LBBP_COLOR_MASK 0x00000003 +#define CLCD_CRSR_LBBP_BACKGROUND 0x0 +#define CLCD_CRSR_LBBP_FOREGROUND 0x1 +#define CLCD_CRSR_LBBP_TRANSPARENT 0x2 +#define CLCD_CRSR_LBBP_INVERSE 0x3 + + +#define CLCD_CRSR_CTRL 0x00000c00 +#define CLCD_CRSR_CONFIG 0x00000c04 +#define CLCD_CRSR_PALETTE_0 0x00000c08 +#define CLCD_CRSR_PALETTE_1 0x00000c0c +#define CLCD_CRSR_XY 0x00000c10 +#define CLCD_CRSR_CLIP 0x00000c14 +#define CLCD_CRSR_IMSC 0x00000c20 +#define CLCD_CRSR_ICR 0x00000c24 +#define CLCD_CRSR_RIS 0x00000c28 +#define CLCD_MIS 0x00000c2c + +#define CRSR_CTRL_CRSR_ON (1 << 0) +#define CRSR_CTRL_CRSR_MAX 3 +#define CRSR_CTRL_CRSR_NUM_SHIFT 4 +#define CRSR_CTRL_CRSR_NUM_MASK \ + (CRSR_CTRL_CRSR_MAX << CRSR_CTRL_CRSR_NUM_SHIFT) +#define CRSR_CTRL_CURSOR_0 0 +#define CRSR_CTRL_CURSOR_1 1 +#define CRSR_CTRL_CURSOR_2 2 +#define CRSR_CTRL_CURSOR_3 3 + +#define CRSR_CONFIG_CRSR_SIZE (1 << 0) +#define CRSR_CONFIG_CRSR_FRAME_SYNC (1 << 1) + +#define CRSR_PALETTE_RED_SHIFT 0 +#define CRSR_PALETTE_GREEN_SHIFT 8 +#define CRSR_PALETTE_BLUE_SHIFT 16 + +#define CRSR_PALETTE_RED_MASK 0x000000ff +#define CRSR_PALETTE_GREEN_MASK 0x0000ff00 +#define CRSR_PALETTE_BLUE_MASK 0x00ff0000 +#define CRSR_PALETTE_MASK (~0xff000000) + +#define CRSR_XY_MASK 0x000003ff +#define CRSR_XY_X_SHIFT 0 +#define CRSR_XY_Y_SHIFT 16 + +#define CRSR_XY_X_MASK CRSR_XY_MASK +#define CRSR_XY_Y_MASK (CRSR_XY_MASK << CRSR_XY_Y_SHIFT) + +#define CRSR_CLIP_MASK 0x3f +#define CRSR_CLIP_X_SHIFT 0 +#define CRSR_CLIP_Y_SHIFT 8 + +#define CRSR_CLIP_X_MASK CRSR_CLIP_MASK +#define CRSR_CLIP_Y_MASK (CRSR_CLIP_MASK << CRSR_CLIP_Y_SHIFT) + +#define CRSR_IMSC_CRSR_IM (1<<0) +#define CRSR_ICR_CRSR_IC (1<<0) +#define CRSR_RIS_CRSR_RIS (1<<0) +#define CRSR_MIS_CRSR_MIS (1<<0) + +#endif /* PL111_CLCD_EXT_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm.h new file mode 100644 index 0000000000000000000000000000000000000000..e151e8c02b117887b7fb88a7acf625d0459dcb5a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm.h @@ -0,0 +1,270 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +#ifndef _PL111_DRM_H_ +#define _PL111_DRM_H_ + +#define DRIVER_AUTHOR "ARM Ltd." +#define DRIVER_NAME "pl111_drm" +#define DRIVER_DESC "DRM module for PL111" +#define DRIVER_LICENCE "GPL" +#define DRIVER_ALIAS "platform:pl111_drm" +#define DRIVER_DATE "20101111" +#define DRIVER_VERSION "0.2" +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 1 + +/* + * Number of flips allowed in flight at any one time. Any more flips requested + * beyond this value will cause the caller to block until earlier flips have + * completed. + * + * For performance reasons, this must be greater than the number of buffers + * used in the rendering pipeline. Note that the rendering pipeline can contain + * different types of buffer, e.g.: + * - 2 final framebuffers + * - >2 geometry buffers for GPU use-cases + * - >2 vertex buffers for GPU use-cases + * + * For example, a system using 5 geometry buffers could have 5 flips in flight, + * and so NR_FLIPS_IN_FLIGHT_THRESHOLD must be 5 or greater. + * + * Whilst there may be more intermediate buffers (such as vertex/geometry) than + * final framebuffers, KDS is used to ensure that GPU rendering waits for the + * next off-screen buffer, so it doesn't overwrite an on-screen buffer and + * produce tearing. + */ + +/* + * Here, we choose a conservative value. A lower value is most likely + * suitable for GPU use-cases. + */ +#define NR_FLIPS_IN_FLIGHT_THRESHOLD 16 + +#define CLCD_IRQ_NEXTBASE_UPDATE (1u<<2) + +struct pl111_drm_flip_resource; + +struct pl111_gem_bo_dma { + dma_addr_t fb_dev_addr; + void *fb_cpu_addr; +}; + +struct pl111_gem_bo_shm { + struct page **pages; + dma_addr_t *dma_addrs; +}; + +struct pl111_gem_bo { + struct drm_gem_object gem_object; + u32 type; + union { + struct pl111_gem_bo_dma dma; + struct pl111_gem_bo_shm shm; + } backing_data; + struct sg_table *sgt; +}; + +extern struct pl111_drm_dev_private priv; + +struct pl111_drm_framebuffer { + struct drm_framebuffer fb; + struct pl111_gem_bo *bo; +}; + +struct pl111_drm_flip_resource { +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* This is the kds set associated to the dma_buf we want to flip */ + struct kds_resource_set *kds_res_set; +#endif + struct drm_framebuffer *fb; + struct drm_crtc *crtc; + struct list_head link; + bool page_flip; + struct drm_pending_vblank_event *event; +}; + +struct pl111_drm_crtc { + struct drm_crtc crtc; + int crtc_index; + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* This protects "old_kds_res_set" and "displaying_fb" */ + spinlock_t current_displaying_lock; + /* + * When a buffer is displayed its associated kds resource + * will be obtained and stored here. Every time a buffer + * flip is completed this old kds set is released and assigned + * the kds set of the new buffer. + */ + struct kds_resource_set *old_kds_res_set; + /* + * Stores which frame buffer is currently being displayed by + * this CRTC or NULL if nothing is being displayed. It is used + * to tell whether we need to obtain a set of kds resources for + * exported buffer objects. + */ + struct drm_framebuffer *displaying_fb; +#endif + struct drm_display_mode *new_mode; + struct drm_display_mode *current_mode; + int last_bpp; + + /* + * This spinlock protects "update_queue", "current_update_res" + * and calls to do_flip_to_res() which updates the CLCD base + * registers. + */ + spinlock_t base_update_lock; + /* + * The resource that caused a base address update. Only one can be + * pending, hence it's != NULL if there's a pending update + */ + struct pl111_drm_flip_resource *current_update_res; + /* Queue of things waiting to update the base address */ + struct list_head update_queue; + + void (*show_framebuffer_cb)(struct pl111_drm_flip_resource *flip_res, + struct drm_framebuffer *fb); +}; + +struct pl111_drm_connector { + struct drm_connector connector; +}; + +struct pl111_drm_encoder { + struct drm_encoder encoder; +}; + +struct pl111_drm_dev_private { + struct pl111_drm_crtc *pl111_crtc; + + struct amba_device *amba_dev; + unsigned long mmio_start; + __u32 mmio_len; + void *regs; + struct clk *clk; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct kds_callback kds_cb; + struct kds_callback kds_obtain_current_cb; +#endif + /* + * Number of flips that were started in show_framebuffer_on_crtc(), + * but haven't completed yet - because we do deferred flipping + */ + atomic_t nr_flips_in_flight; + wait_queue_head_t wait_for_flips; + + /* + * Used to prevent race between pl111_dma_buf_release and + * drm_gem_prime_handle_to_fd + */ + struct mutex export_dma_buf_lock; + + uint32_t number_crtcs; + + /* Cache for flip resources used to avoid kmalloc on each page flip */ + struct kmem_cache *page_flip_slab; +}; + +enum pl111_cursor_size { + CURSOR_32X32, + CURSOR_64X64 +}; + +enum pl111_cursor_sync { + CURSOR_SYNC_NONE, + CURSOR_SYNC_VSYNC +}; + + +/** + * Buffer allocation function which is more flexible than dumb_create(), + * it allows passing driver specific flags to control the kind of buffer + * to be allocated. + */ +int pl111_drm_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +/****** TODO MIDEGL-1718: this should be moved to uapi/include/drm/pl111_drm.h ********/ + +/* + * Parameters for different buffer objects: + * bit [0]: backing storage + * (0 -> SHM) + * (1 -> DMA) + * bit [2:1]: kind of mapping + * (0x0 -> uncached) + * (0x1 -> write combine) + * (0x2 -> cached) + */ +#define PL111_BOT_MASK (0x7) +#define PL111_BOT_SHM (0x0 << 0) +#define PL111_BOT_DMA (0x1 << 0) +#define PL111_BOT_UNCACHED (0x0 << 1) +#define PL111_BOT_WC (0x1 << 1) +#define PL111_BOT_CACHED (0x2 << 1) + +/** + * User-desired buffer creation information structure. + * + * @size: user-desired memory allocation size. + * - this size value would be page-aligned internally. + * @flags: user request for setting memory type or cache attributes as a bit op + * - PL111_BOT_DMA / PL111_BOT_SHM + * - PL111_BOT_UNCACHED / PL111_BOT_WC / PL111_BOT_CACHED + * @handle: returned a handle to created gem object. + * - this handle will be set by gem module of kernel side. + */ +struct drm_pl111_gem_create { + uint32_t height; + uint32_t width; + uint32_t bpp; + uint32_t flags; + /* handle, pitch, size will be returned */ + uint32_t handle; + uint32_t pitch; + uint64_t size; +}; + +#define DRM_PL111_GEM_CREATE 0x00 + +#define DRM_IOCTL_PL111_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_PL111_GEM_CREATE, struct drm_pl111_gem_create) +/****************************************************************************/ + +#define PL111_FB_FROM_FRAMEBUFFER(drm_fb) \ + (container_of(drm_fb, struct pl111_drm_framebuffer, fb)) + +#define PL111_BO_FROM_FRAMEBUFFER(drm_fb) \ + (container_of(drm_fb, struct pl111_drm_framebuffer, fb)->bo) + +#define PL111_BO_FROM_GEM(gem_obj) \ + container_of(gem_obj, struct pl111_gem_bo, gem_object) + +#define to_pl111_crtc(x) container_of(x, struct pl111_drm_crtc, crtc) + +#define PL111_ENCODER_FROM_ENCODER(x) \ + container_of(x, struct pl111_drm_encoder, encoder) + +#define PL111_CONNECTOR_FROM_CONNECTOR(x) \ + container_of(x, struct pl111_drm_connector, connector) + +#include "pl111_drm_funcs.h" + +#endif /* _PL111_DRM_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_connector.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_connector.c new file mode 100644 index 0000000000000000000000000000000000000000..5d9cf80de6189126284dcbec953bdc4ed2e5996f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_connector.c @@ -0,0 +1,170 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_connector.c + * Implementation of the connector functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + + +static struct { + int w, h, type; +} pl111_drm_modes[] = { + { 640, 480, DRM_MODE_TYPE_PREFERRED}, + { 800, 600, 0}, + {1024, 768, 0}, + { -1, -1, -1} +}; + +void pl111_connector_destroy(struct drm_connector *connector) +{ + struct pl111_drm_connector *pl111_connector = + PL111_CONNECTOR_FROM_CONNECTOR(connector); + + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(pl111_connector); +} + +enum drm_connector_status pl111_connector_detect(struct drm_connector + *connector, bool force) +{ + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + return connector_status_connected; +} + +void pl111_connector_dpms(struct drm_connector *connector, int mode) +{ + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); +} + +struct drm_encoder * +pl111_connector_helper_best_encoder(struct drm_connector *connector) +{ + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + + if (connector->encoder != NULL) { + return connector->encoder; /* Return attached encoder */ + } else { + /* + * If there is no attached encoder we choose the best candidate + * from the list. + * For PL111 there is only one encoder so we return the first + * one we find. + * Other h/w would require a suitable criterion below. + */ + struct drm_encoder *encoder = NULL; + struct drm_device *dev = connector->dev; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, + head) { + if (1) { /* criterion ? */ + break; + } + } + return encoder; /* return best candidate encoder */ + } +} + +int pl111_connector_helper_get_modes(struct drm_connector *connector) +{ + int i = 0; + int count = 0; + + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + + while (pl111_drm_modes[i].w != -1) { + struct drm_display_mode *mode = + drm_mode_find_dmt(connector->dev, + pl111_drm_modes[i].w, + pl111_drm_modes[i].h, + 60 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + , false +#endif + ); + + if (mode != NULL) { + mode->type |= pl111_drm_modes[i].type; + drm_mode_probed_add(connector, mode); + count++; + } + + i++; + } + + DRM_DEBUG_KMS("found %d modes\n", count); + + return count; +} + +int pl111_connector_helper_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + DRM_DEBUG_KMS("DRM %s on connector=%p\n", __func__, connector); + return MODE_OK; +} + +const struct drm_connector_funcs connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = pl111_connector_destroy, + .detect = pl111_connector_detect, + .dpms = pl111_connector_dpms, +}; + +const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = pl111_connector_helper_get_modes, + .mode_valid = pl111_connector_helper_mode_valid, + .best_encoder = pl111_connector_helper_best_encoder, +}; + +struct pl111_drm_connector *pl111_connector_create(struct drm_device *dev) +{ + struct pl111_drm_connector *pl111_connector; + + pl111_connector = kzalloc(sizeof(struct pl111_drm_connector), + GFP_KERNEL); + + if (pl111_connector == NULL) { + pr_err("Failed to allocated pl111_drm_connector\n"); + return NULL; + } + + drm_connector_init(dev, &pl111_connector->connector, &connector_funcs, + DRM_MODE_CONNECTOR_DVII); + + drm_connector_helper_add(&pl111_connector->connector, + &connector_helper_funcs); + + drm_sysfs_connector_add(&pl111_connector->connector); + + return pl111_connector; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_crtc.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_crtc.c new file mode 100644 index 0000000000000000000000000000000000000000..a06c991dbf23d164cfb6729c9ed9bacd2ea9cc37 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_crtc.c @@ -0,0 +1,421 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_crtc.c + * Implementation of the CRTC functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + +static int pl111_crtc_num; + +void pl111_common_irq(struct pl111_drm_crtc *pl111_crtc) +{ + struct drm_device *dev = pl111_crtc->crtc.dev; + struct pl111_drm_flip_resource *old_flip_res; + struct pl111_gem_bo *bo; + unsigned long irq_flags; + int flips_in_flight; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + unsigned long flags; +#endif + + spin_lock_irqsave(&pl111_crtc->base_update_lock, irq_flags); + + /* + * Cache the flip resource that caused the IRQ since it will be + * dispatched later. Early return if the IRQ isn't associated to + * a base register update. + * + * TODO MIDBASE-2790: disable IRQs when a flip is not pending. + */ + old_flip_res = pl111_crtc->current_update_res; + if (!old_flip_res) { + spin_unlock_irqrestore(&pl111_crtc->base_update_lock, irq_flags); + return; + } + pl111_crtc->current_update_res = NULL; + + /* Prepare the next flip (if any) of the queue as soon as possible. */ + if (!list_empty(&pl111_crtc->update_queue)) { + struct pl111_drm_flip_resource *flip_res; + /* Remove the head of the list */ + flip_res = list_first_entry(&pl111_crtc->update_queue, + struct pl111_drm_flip_resource, link); + list_del(&flip_res->link); + do_flip_to_res(flip_res); + /* + * current_update_res will be set, so guarentees that + * another flip_res coming in gets queued instead of + * handled immediately + */ + } + spin_unlock_irqrestore(&pl111_crtc->base_update_lock, irq_flags); + + /* Finalize properly the flip that caused the IRQ */ + DRM_DEBUG_KMS("DRM Finalizing old_flip_res=%p\n", old_flip_res); + + bo = PL111_BO_FROM_FRAMEBUFFER(old_flip_res->fb); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + release_kds_resource_and_display(old_flip_res); + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, flags); +#endif + /* Release DMA buffer on this flip */ + if (bo->gem_object.export_dma_buf != NULL) + dma_buf_put(bo->gem_object.export_dma_buf); + + drm_handle_vblank(dev, pl111_crtc->crtc_index); + + /* Wake up any processes waiting for page flip event */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + if (old_flip_res->event) { + spin_lock_bh(&dev->event_lock); + drm_send_vblank_event(dev, pl111_crtc->crtc_index, + old_flip_res->event); + spin_unlock_bh(&dev->event_lock); + } +#else + if (old_flip_res->event) { + struct drm_pending_vblank_event *e = old_flip_res->event; + struct timeval now; + unsigned int seq; + + DRM_DEBUG_KMS("%s: wake up page flip event (%p)\n", __func__, + old_flip_res->event); + + spin_lock_bh(&dev->event_lock); + seq = drm_vblank_count_and_time(dev, pl111_crtc->crtc_index, + &now); + e->pipe = pl111_crtc->crtc_index; + e->event.sequence = seq; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + + list_add_tail(&e->base.link, + &e->base.file_priv->event_list); + + wake_up_interruptible(&e->base.file_priv->event_wait); + spin_unlock_bh(&dev->event_lock); + } +#endif + + drm_vblank_put(dev, pl111_crtc->crtc_index); + + /* + * workqueue.c:process_one_work(): + * "It is permissible to free the struct work_struct from + * inside the function that is called from it" + */ + kmem_cache_free(priv.page_flip_slab, old_flip_res); + + flips_in_flight = atomic_dec_return(&priv.nr_flips_in_flight); + if (flips_in_flight == 0 || + flips_in_flight == (NR_FLIPS_IN_FLIGHT_THRESHOLD - 1)) + wake_up(&priv.wait_for_flips); + + DRM_DEBUG_KMS("DRM release flip_res=%p\n", old_flip_res); +} + +void show_framebuffer_on_crtc_cb(void *cb1, void *cb2) +{ + struct pl111_drm_flip_resource *flip_res = cb1; + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(flip_res->crtc); + + pl111_crtc->show_framebuffer_cb(cb1, cb2); +} + +int show_framebuffer_on_crtc(struct drm_crtc *crtc, + struct drm_framebuffer *fb, bool page_flip, + struct drm_pending_vblank_event *event) +{ + struct pl111_gem_bo *bo; + struct pl111_drm_flip_resource *flip_res; + int flips_in_flight; + int old_flips_in_flight; + + crtc->fb = fb; + + bo = PL111_BO_FROM_FRAMEBUFFER(fb); + if (bo == NULL) { + DRM_DEBUG_KMS("Failed to get pl111_gem_bo object\n"); + return -EINVAL; + } + + /* If this is a full modeset, wait for all outstanding flips to complete + * before continuing. This avoids unnecessary complication from being + * able to queue up multiple modesets and queues of mixed modesets and + * page flips. + * + * Modesets should be uncommon and will not be performant anyway, so + * making them synchronous should have negligible performance impact. + */ + if (!page_flip) { + int ret = wait_event_killable(priv.wait_for_flips, + atomic_read(&priv.nr_flips_in_flight) == 0); + if (ret) + return ret; + } + + /* + * There can be more 'early display' flips in flight than there are + * buffers, and there is (currently) no explicit bound on the number of + * flips. Hence, we need a new allocation for each one. + * + * Note: this could be optimized down if we knew a bound on the flips, + * since an application can only have so many buffers in flight to be + * useful/not hog all the memory + */ + flip_res = kmem_cache_alloc(priv.page_flip_slab, GFP_KERNEL); + if (flip_res == NULL) { + pr_err("kmem_cache_alloc failed to alloc - flip ignored\n"); + return -ENOMEM; + } + + /* + * increment flips in flight, whilst blocking when we reach + * NR_FLIPS_IN_FLIGHT_THRESHOLD + */ + do { + /* + * Note: use of assign-and-then-compare in the condition to set + * flips_in_flight + */ + int ret = wait_event_killable(priv.wait_for_flips, + (flips_in_flight = + atomic_read(&priv.nr_flips_in_flight)) + < NR_FLIPS_IN_FLIGHT_THRESHOLD); + if (ret != 0) { + kmem_cache_free(priv.page_flip_slab, flip_res); + return ret; + } + + old_flips_in_flight = atomic_cmpxchg(&priv.nr_flips_in_flight, + flips_in_flight, flips_in_flight + 1); + } while (old_flips_in_flight != flips_in_flight); + + flip_res->fb = fb; + flip_res->crtc = crtc; + flip_res->page_flip = page_flip; + flip_res->event = event; + INIT_LIST_HEAD(&flip_res->link); + DRM_DEBUG_KMS("DRM alloc flip_res=%p\n", flip_res); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + if (bo->gem_object.export_dma_buf != NULL) { + struct dma_buf *buf = bo->gem_object.export_dma_buf; + unsigned long shared[1] = { 0 }; + struct kds_resource *resource_list[1] = { + get_dma_buf_kds_resource(buf) }; + int err; + + get_dma_buf(buf); + DRM_DEBUG_KMS("Got dma_buf %p\n", buf); + + /* Wait for the KDS resource associated with this buffer */ + err = kds_async_waitall(&flip_res->kds_res_set, + &priv.kds_cb, flip_res, fb, 1, shared, + resource_list); + BUG_ON(err); + } else { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + + DRM_DEBUG_KMS("No dma_buf for this flip\n"); + + /* No dma-buf attached so just call the callback directly */ + flip_res->kds_res_set = NULL; + pl111_crtc->show_framebuffer_cb(flip_res, fb); + } +#else + if (bo->gem_object.export_dma_buf != NULL) { + struct dma_buf *buf = bo->gem_object.export_dma_buf; + + get_dma_buf(buf); + DRM_DEBUG_KMS("Got dma_buf %p\n", buf); + } else { + DRM_DEBUG_KMS("No dma_buf for this flip\n"); + } + + /* No dma-buf attached to this so just call the callback directly */ + { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + pl111_crtc->show_framebuffer_cb(flip_res, fb); + } +#endif + + /* For the same reasons as the wait at the start of this function, + * wait for the modeset to complete before continuing. + */ + if (!page_flip) { + int ret = wait_event_killable(priv.wait_for_flips, + flips_in_flight == 0); + if (ret) + return ret; + } + + return 0; +} + +int pl111_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + DRM_DEBUG_KMS("%s: crtc=%p, fb=%p, event=%p\n", + __func__, crtc, fb, event); + return show_framebuffer_on_crtc(crtc, fb, true, event); +} + +int pl111_crtc_helper_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb) +{ + int ret; + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + struct drm_display_mode *duplicated_mode; + + DRM_DEBUG_KMS("DRM crtc_helper_mode_set, x=%d y=%d bpp=%d\n", + adjusted_mode->hdisplay, adjusted_mode->vdisplay, + crtc->fb->bits_per_pixel); + + duplicated_mode = drm_mode_duplicate(crtc->dev, adjusted_mode); + if (!duplicated_mode) + return -ENOMEM; + + pl111_crtc->new_mode = duplicated_mode; + ret = show_framebuffer_on_crtc(crtc, crtc->fb, false, NULL); + if (ret != 0) { + pl111_crtc->new_mode = pl111_crtc->current_mode; + drm_mode_destroy(crtc->dev, duplicated_mode); + } + + return ret; +} + +void pl111_crtc_helper_prepare(struct drm_crtc *crtc) +{ + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); +} + +void pl111_crtc_helper_commit(struct drm_crtc *crtc) +{ + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); +} + +bool pl111_crtc_helper_mode_fixup(struct drm_crtc *crtc, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + const struct drm_display_mode *mode, +#else + struct drm_display_mode *mode, +#endif + struct drm_display_mode *adjusted_mode) +{ + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); + +#ifdef CONFIG_ARCH_VEXPRESS + /* + * 1024x768 with more than 16 bits per pixel may not work + * correctly on Versatile Express due to bandwidth issues + */ + if (mode->hdisplay == 1024 && mode->vdisplay == 768 && + crtc->fb->bits_per_pixel > 16) { + DRM_INFO("*WARNING* 1024x768 at > 16 bpp may suffer corruption\n"); + } +#endif + + return true; +} + +void pl111_crtc_helper_disable(struct drm_crtc *crtc) +{ + int ret; + + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); + + /* don't disable crtc until no flips in flight as irq will be disabled */ + ret = wait_event_killable(priv.wait_for_flips, atomic_read(&priv.nr_flips_in_flight) == 0); + if(ret) { + pr_err("pl111_crtc_helper_disable failed\n"); + return; + } + clcd_disable(crtc); +} + +void pl111_crtc_destroy(struct drm_crtc *crtc) +{ + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + + DRM_DEBUG_KMS("DRM %s on crtc=%p\n", __func__, crtc); + + drm_crtc_cleanup(crtc); + kfree(pl111_crtc); +} + +const struct drm_crtc_funcs crtc_funcs = { + .cursor_set = pl111_crtc_cursor_set, + .cursor_move = pl111_crtc_cursor_move, + .set_config = drm_crtc_helper_set_config, + .page_flip = pl111_crtc_page_flip, + .destroy = pl111_crtc_destroy +}; + +const struct drm_crtc_helper_funcs crtc_helper_funcs = { + .mode_set = pl111_crtc_helper_mode_set, + .prepare = pl111_crtc_helper_prepare, + .commit = pl111_crtc_helper_commit, + .mode_fixup = pl111_crtc_helper_mode_fixup, + .disable = pl111_crtc_helper_disable, +}; + +struct pl111_drm_crtc *pl111_crtc_create(struct drm_device *dev) +{ + struct pl111_drm_crtc *pl111_crtc; + + pl111_crtc = kzalloc(sizeof(struct pl111_drm_crtc), GFP_KERNEL); + if (pl111_crtc == NULL) { + pr_err("Failed to allocated pl111_drm_crtc\n"); + return NULL; + } + + drm_crtc_init(dev, &pl111_crtc->crtc, &crtc_funcs); + drm_crtc_helper_add(&pl111_crtc->crtc, &crtc_helper_funcs); + + pl111_crtc->crtc_index = pl111_crtc_num; + pl111_crtc_num++; + pl111_crtc->crtc.enabled = 0; + pl111_crtc->last_bpp = 0; + pl111_crtc->current_update_res = NULL; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + pl111_crtc->displaying_fb = NULL; + pl111_crtc->old_kds_res_set = NULL; + spin_lock_init(&pl111_crtc->current_displaying_lock); +#endif + pl111_crtc->show_framebuffer_cb = show_framebuffer_on_crtc_cb_internal; + INIT_LIST_HEAD(&pl111_crtc->update_queue); + spin_lock_init(&pl111_crtc->base_update_lock); + + return pl111_crtc; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_cursor.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_cursor.c new file mode 100644 index 0000000000000000000000000000000000000000..87f1007d16dd5bc48f4ad510d657501b4a122523 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_cursor.c @@ -0,0 +1,331 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_cursor.c + * Implementation of cursor functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "pl111_clcd_ext.h" +#include "pl111_drm.h" + +#define PL111_MAX_CURSOR_WIDTH (64) +#define PL111_MAX_CURSOR_HEIGHT (64) + +#define ARGB_2_LBBP_BINARY_THRESHOLD (1 << 7) +#define ARGB_ALPHA_SHIFT 24 +#define ARGB_ALPHA_MASK (0xff << ARGB_ALPHA_SHIFT) +#define ARGB_RED_SHIFT 16 +#define ARGB_RED_MASK (0xff << ARGB_RED_SHIFT) +#define ARGB_GREEN_SHIFT 8 +#define ARGB_GREEN_MASK (0xff << ARGB_GREEN_SHIFT) +#define ARGB_BLUE_SHIFT 0 +#define ARGB_BLUE_MASK (0xff << ARGB_BLUE_SHIFT) + + +void pl111_set_cursor_size(enum pl111_cursor_size size) +{ + u32 reg_data = readl(priv.regs + CLCD_CRSR_CONFIG); + + if (size == CURSOR_64X64) + reg_data |= CRSR_CONFIG_CRSR_SIZE; + else + reg_data &= ~CRSR_CONFIG_CRSR_SIZE; + + writel(reg_data, priv.regs + CLCD_CRSR_CONFIG); +} + +void pl111_set_cursor_sync(enum pl111_cursor_sync sync) +{ + u32 reg_data = readl(priv.regs + CLCD_CRSR_CONFIG); + + if (sync == CURSOR_SYNC_VSYNC) + reg_data |= CRSR_CONFIG_CRSR_FRAME_SYNC; + else + reg_data &= ~CRSR_CONFIG_CRSR_FRAME_SYNC; + + writel(reg_data, priv.regs + CLCD_CRSR_CONFIG); +} + +void pl111_set_cursor(u32 cursor) +{ + u32 reg_data = readl(priv.regs + CLCD_CRSR_CTRL); + + reg_data &= ~(CRSR_CTRL_CRSR_MAX << CRSR_CTRL_CRSR_NUM_SHIFT); + reg_data |= (cursor & CRSR_CTRL_CRSR_MAX) << CRSR_CTRL_CRSR_NUM_SHIFT; + + writel(reg_data, priv.regs + CLCD_CRSR_CTRL); +} + +void pl111_set_cursor_enable(bool enable) +{ + u32 reg_data = readl(priv.regs + CLCD_CRSR_CTRL); + + if (enable) + reg_data |= CRSR_CTRL_CRSR_ON; + else + reg_data &= ~CRSR_CTRL_CRSR_ON; + + writel(reg_data, priv.regs + CLCD_CRSR_CTRL); +} + +void pl111_set_cursor_position(u32 x, u32 y) +{ + u32 reg_data = (x & CRSR_XY_MASK) | + ((y & CRSR_XY_MASK) << CRSR_XY_Y_SHIFT); + + writel(reg_data, priv.regs + CLCD_CRSR_XY); +} + +void pl111_set_cursor_clipping(u32 x, u32 y) +{ + u32 reg_data; + + /* + * Do not allow setting clipping values larger than + * the cursor size since the cursor is already fully hidden + * when x,y = PL111_MAX_CURSOR_WIDTH. + */ + if (x > PL111_MAX_CURSOR_WIDTH) + x = PL111_MAX_CURSOR_WIDTH; + if (y > PL111_MAX_CURSOR_WIDTH) + y = PL111_MAX_CURSOR_WIDTH; + + reg_data = (x & CRSR_CLIP_MASK) | + ((y & CRSR_CLIP_MASK) << CRSR_CLIP_Y_SHIFT); + + writel(reg_data, priv.regs + CLCD_CRSR_CLIP); +} + +void pl111_set_cursor_palette(u32 color0, u32 color1) +{ + writel(color0 & CRSR_PALETTE_MASK, priv.regs + CLCD_CRSR_PALETTE_0); + writel(color1 & CRSR_PALETTE_MASK, priv.regs + CLCD_CRSR_PALETTE_1); +} + +void pl111_cursor_enable(void) +{ + pl111_set_cursor_sync(CURSOR_SYNC_VSYNC); + pl111_set_cursor_size(CURSOR_64X64); + pl111_set_cursor_palette(0x0, 0x00ffffff); + pl111_set_cursor_enable(true); +} + +void pl111_cursor_disable(void) +{ + pl111_set_cursor_enable(false); +} + +/* shift required to locate pixel into the correct position in + * a cursor LBBP word, indexed by x mod 16. + */ +static const unsigned char +x_mod_16_to_value_shift[CLCD_CRSR_IMAGE_PIXELS_PER_WORD] = { + 6, 4, 2, 0, 14, 12, 10, 8, 22, 20, 18, 16, 30, 28, 26, 24 +}; + +/* Pack the pixel value into its correct position in the buffer as specified + * for LBBP */ +static inline void +set_lbbp_pixel(uint32_t *buffer, unsigned int x, unsigned int y, + uint32_t value) +{ + u32 *cursor_ram = priv.regs + CLCD_CRSR_IMAGE; + uint32_t shift; + uint32_t data; + + shift = x_mod_16_to_value_shift[x % CLCD_CRSR_IMAGE_PIXELS_PER_WORD]; + + /* Get the word containing this pixel */ + cursor_ram = cursor_ram + (x >> CLCD_CRSR_IMAGE_WORDS_PER_LINE) + (y << 2); + + /* Update pixel in cursor RAM */ + data = readl(cursor_ram); + data &= ~(CLCD_CRSR_LBBP_COLOR_MASK << shift); + data |= value << shift; + writel(data, cursor_ram); +} + +static u32 pl111_argb_to_lbbp(u32 argb_pix) +{ + u32 lbbp_pix = CLCD_CRSR_LBBP_TRANSPARENT; + u32 alpha = (argb_pix & ARGB_ALPHA_MASK) >> ARGB_ALPHA_SHIFT; + u32 red = (argb_pix & ARGB_RED_MASK) >> ARGB_RED_SHIFT; + u32 green = (argb_pix & ARGB_GREEN_MASK) >> ARGB_GREEN_SHIFT; + u32 blue = (argb_pix & ARGB_BLUE_MASK) >> ARGB_BLUE_SHIFT; + + /* + * Converting from 8 pixel transparency to binary transparency + * it's the best we can achieve. + */ + if (alpha & ARGB_2_LBBP_BINARY_THRESHOLD) { + u32 gray, max, min; + + /* + * Convert to gray using the lightness method: + * gray = [max(R,G,B) + min(R,G,B)]/2 + */ + min = min(red, green); + min = min(min, blue); + max = max(red, green); + max = max(max, blue); + gray = (min + max) >> 1; /* divide by 2 */ + /* Apply binary threshold to the gray value calculated */ + if (gray & ARGB_2_LBBP_BINARY_THRESHOLD) + lbbp_pix = CLCD_CRSR_LBBP_FOREGROUND; + else + lbbp_pix = CLCD_CRSR_LBBP_BACKGROUND; + } + + return lbbp_pix; +} + +/* + * The PL111 hardware cursor supports only LBBP which is a 2bpp format but + * the cursor format from userspace is ARGB8888 so we need to convert + * to LBBP here. + */ +static void pl111_set_cursor_image(u32 *data) +{ +#ifdef ARGB_LBBP_CONVERSION_DEBUG + /* Add 1 on width to insert trailing NULL */ + char string_cursor[PL111_MAX_CURSOR_WIDTH + 1]; +#endif /* ARGB_LBBP_CONVERSION_DEBUG */ + unsigned int x; + unsigned int y; + + for (y = 0; y < PL111_MAX_CURSOR_HEIGHT; y++) { + for (x = 0; x < PL111_MAX_CURSOR_WIDTH; x++) { + u32 value = pl111_argb_to_lbbp(*data); + +#ifdef ARGB_LBBP_CONVERSION_DEBUG + if (value == CLCD_CRSR_LBBP_TRANSPARENT) + string_cursor[x] = 'T'; + else if (value == CLCD_CRSR_LBBP_FOREGROUND) + string_cursor[x] = 'F'; + else if (value == CLCD_CRSR_LBBP_INVERSE) + string_cursor[x] = 'I'; + else + string_cursor[x] = 'B'; + +#endif /* ARGB_LBBP_CONVERSION_DEBUG */ + set_lbbp_pixel(data, x, y, value); + ++data; + } +#ifdef ARGB_LBBP_CONVERSION_DEBUG + string_cursor[PL111_MAX_CURSOR_WIDTH] = '\0'; + DRM_INFO("%s\n", string_cursor); +#endif /* ARGB_LBBP_CONVERSION_DEBUG */ + } +} + +int pl111_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height) +{ + struct drm_gem_object *obj; + struct pl111_gem_bo *bo; + + DRM_DEBUG_KMS("handle = %u, width = %u, height = %u\n", + handle, width, height); + + if (!handle) { + pl111_cursor_disable(); + return 0; + } + + if ((width != PL111_MAX_CURSOR_WIDTH) || + (height != PL111_MAX_CURSOR_HEIGHT)) + return -EINVAL; + + obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); + if (!obj) { + DRM_ERROR("Cannot find cursor object for handle = %d\n", + handle); + return -ENOENT; + } + + /* + * We expect a PL111_MAX_CURSOR_WIDTH x PL111_MAX_CURSOR_HEIGHT + * ARGB888 buffer object in the input. + * + */ + if (obj->size < (PL111_MAX_CURSOR_WIDTH * PL111_MAX_CURSOR_HEIGHT * 4)) { + DRM_ERROR("Cannot set cursor with an obj size = %d\n", + obj->size); + drm_gem_object_unreference_unlocked(obj); + return -EINVAL; + } + + bo = PL111_BO_FROM_GEM(obj); + if (!(bo->type & PL111_BOT_DMA)) { + DRM_ERROR("Tried to set cursor with non DMA backed obj = %p\n", + obj); + drm_gem_object_unreference_unlocked(obj); + return -EINVAL; + } + + pl111_set_cursor_image(bo->backing_data.dma.fb_cpu_addr); + + /* + * Since we copy the contents of the buffer to the HW cursor internal + * memory this GEM object is not needed anymore. + */ + drm_gem_object_unreference_unlocked(obj); + + pl111_cursor_enable(); + + return 0; +} + +int pl111_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + int x_clip = 0; + int y_clip = 0; + + DRM_DEBUG("x %d y %d\n", x, y); + + /* + * The cursor image is clipped automatically at the screen limits when + * it extends beyond the screen image to the right or bottom but + * we must clip it using pl111 HW features for negative values. + */ + if (x < 0) { + x_clip = -x; + x = 0; + } + if (y < 0) { + y_clip = -y; + y = 0; + } + + pl111_set_cursor_clipping(x_clip, y_clip); + pl111_set_cursor_position(x, y); + + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_device.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_device.c new file mode 100644 index 0000000000000000000000000000000000000000..b8ea5f6725ecda4b17c312cf3ceadfadd4690ea5 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_device.c @@ -0,0 +1,326 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_device.c + * Implementation of the Linux device driver entrypoints for PL111 DRM + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + +struct pl111_drm_dev_private priv; + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS +static void initial_kds_obtained(void *cb1, void *cb2) +{ + wait_queue_head_t *wait = (wait_queue_head_t *) cb1; + bool *cb_has_called = (bool *) cb2; + + *cb_has_called = true; + wake_up(wait); +} + +/* Must be called from within current_displaying_lock spinlock */ +void release_kds_resource_and_display(struct pl111_drm_flip_resource *flip_res) +{ + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(flip_res->crtc); + pl111_crtc->displaying_fb = flip_res->fb; + + /* Release the previous buffer */ + if (pl111_crtc->old_kds_res_set != NULL) { + /* + * Can flip to the same buffer, but must not release the current + * resource set + */ + BUG_ON(pl111_crtc->old_kds_res_set == flip_res->kds_res_set); + kds_resource_set_release(&pl111_crtc->old_kds_res_set); + } + /* Record the current buffer, to release on the next buffer flip */ + pl111_crtc->old_kds_res_set = flip_res->kds_res_set; +} +#endif + +void pl111_drm_preclose(struct drm_device *dev, struct drm_file *file_priv) +{ + DRM_DEBUG_KMS("DRM %s on dev=%p\n", __func__, dev); +} + +void pl111_drm_lastclose(struct drm_device *dev) +{ + DRM_DEBUG_KMS("DRM %s on dev=%p\n", __func__, dev); +} + +/* + * pl111 does not have a proper HW counter for vblank IRQs so enable_vblank + * and disable_vblank are just no op callbacks. + */ +static int pl111_enable_vblank(struct drm_device *dev, int crtc) +{ + DRM_DEBUG_KMS("%s: dev=%p, crtc=%d", __func__, dev, crtc); + return 0; +} + +static void pl111_disable_vblank(struct drm_device *dev, int crtc) +{ + DRM_DEBUG_KMS("%s: dev=%p, crtc=%d", __func__, dev, crtc); +} + +struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = pl111_fb_create, +}; + +static int pl111_modeset_init(struct drm_device *dev) +{ + struct drm_mode_config *mode_config; + struct pl111_drm_dev_private *priv = dev->dev_private; + struct pl111_drm_connector *pl111_connector; + struct pl111_drm_encoder *pl111_encoder; + int ret = 0; + + if (priv == NULL) + return -EINVAL; + + drm_mode_config_init(dev); + mode_config = &dev->mode_config; + mode_config->funcs = &mode_config_funcs; + mode_config->min_width = 1; + mode_config->max_width = 1024; + mode_config->min_height = 1; + mode_config->max_height = 768; + + priv->pl111_crtc = pl111_crtc_create(dev); + if (priv->pl111_crtc == NULL) { + pr_err("Failed to create pl111_drm_crtc\n"); + ret = -ENOMEM; + goto out_config; + } + + priv->number_crtcs = 1; + + pl111_connector = pl111_connector_create(dev); + if (pl111_connector == NULL) { + pr_err("Failed to create pl111_drm_connector\n"); + ret = -ENOMEM; + goto out_config; + } + + pl111_encoder = pl111_encoder_create(dev, 1); + if (pl111_encoder == NULL) { + pr_err("Failed to create pl111_drm_encoder\n"); + ret = -ENOMEM; + goto out_config; + } + + ret = drm_mode_connector_attach_encoder(&pl111_connector->connector, + &pl111_encoder->encoder); + if (ret != 0) { + DRM_ERROR("Failed to attach encoder\n"); + goto out_config; + } + + pl111_connector->connector.encoder = &pl111_encoder->encoder; + + goto finish; + +out_config: + drm_mode_config_cleanup(dev); +finish: + DRM_DEBUG("%s returned %d\n", __func__, ret); + return ret; +} + +static void pl111_modeset_fini(struct drm_device *dev) +{ + drm_mode_config_cleanup(dev); +} + +static int pl111_drm_load(struct drm_device *dev, unsigned long chipset) +{ + int ret = 0; + + pr_info("DRM %s\n", __func__); + + mutex_init(&priv.export_dma_buf_lock); + atomic_set(&priv.nr_flips_in_flight, 0); + init_waitqueue_head(&priv.wait_for_flips); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + ret = kds_callback_init(&priv.kds_cb, 1, show_framebuffer_on_crtc_cb); + if (ret != 0) { + pr_err("Failed to initialise KDS callback\n"); + goto finish; + } + + ret = kds_callback_init(&priv.kds_obtain_current_cb, 1, + initial_kds_obtained); + if (ret != 0) { + pr_err("Failed to init KDS obtain callback\n"); + kds_callback_term(&priv.kds_cb); + goto finish; + } +#endif + + /* Create a cache for page flips */ + priv.page_flip_slab = kmem_cache_create("page flip slab", + sizeof(struct pl111_drm_flip_resource), 0, 0, NULL); + if (priv.page_flip_slab == NULL) { + DRM_ERROR("Failed to create slab\n"); + ret = -ENOMEM; + goto out_kds_callbacks; + } + + dev->dev_private = &priv; + + ret = pl111_modeset_init(dev); + if (ret != 0) { + pr_err("Failed to init modeset\n"); + goto out_slab; + } + + ret = pl111_device_init(dev); + if (ret != 0) { + DRM_ERROR("Failed to init MMIO and IRQ\n"); + goto out_modeset; + } + + ret = drm_vblank_init(dev, 1); + if (ret != 0) { + DRM_ERROR("Failed to init vblank\n"); + goto out_vblank; + } + + goto finish; + +out_vblank: + pl111_device_fini(dev); +out_modeset: + pl111_modeset_fini(dev); +out_slab: + kmem_cache_destroy(priv.page_flip_slab); +out_kds_callbacks: +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + kds_callback_term(&priv.kds_obtain_current_cb); + kds_callback_term(&priv.kds_cb); +#endif +finish: + DRM_DEBUG_KMS("pl111_drm_load returned %d\n", ret); + return ret; +} + +static int pl111_drm_unload(struct drm_device *dev) +{ + pr_info("DRM %s\n", __func__); + + kmem_cache_destroy(priv.page_flip_slab); + + drm_vblank_cleanup(dev); + pl111_modeset_fini(dev); + pl111_device_fini(dev); + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + kds_callback_term(&priv.kds_obtain_current_cb); + kds_callback_term(&priv.kds_cb); +#endif + return 0; +} + +static struct vm_operations_struct pl111_gem_vm_ops = { + .fault = pl111_gem_fault, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +#else + .open = pl111_gem_vm_open, + .close = pl111_gem_vm_close, +#endif +}; + +static const struct file_operations drm_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = pl111_gem_mmap, + .poll = drm_poll, + .read = drm_read, + .fasync = drm_fasync, +}; + +static struct drm_ioctl_desc pl111_ioctls[] = { + DRM_IOCTL_DEF_DRV(PL111_GEM_CREATE, pl111_drm_gem_create_ioctl, + DRM_CONTROL_ALLOW | DRM_UNLOCKED), +}; + +static struct drm_driver driver = { + .driver_features = + DRIVER_MODESET | DRIVER_FB_DMA | DRIVER_GEM | DRIVER_PRIME, + .load = pl111_drm_load, + .unload = pl111_drm_unload, + .context_dtor = NULL, + .preclose = pl111_drm_preclose, + .lastclose = pl111_drm_lastclose, + .suspend = pl111_drm_suspend, + .resume = pl111_drm_resume, + .get_vblank_counter = drm_vblank_count, + .enable_vblank = pl111_enable_vblank, + .disable_vblank = pl111_disable_vblank, + .ioctls = pl111_ioctls, + .fops = &drm_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, + .dumb_create = pl111_dumb_create, + .dumb_destroy = pl111_dumb_destroy, + .dumb_map_offset = pl111_dumb_map_offset, + .gem_free_object = pl111_gem_free_object, + .gem_vm_ops = &pl111_gem_vm_ops, + .prime_handle_to_fd = &pl111_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_export = &pl111_gem_prime_export, + .gem_prime_import = &pl111_gem_prime_import, +}; + +int pl111_drm_init(struct platform_device *dev) +{ + int ret; + pr_info("DRM %s\n", __func__); + pr_info("PL111 DRM initialize, driver name: %s, version %d.%d\n", + DRIVER_NAME, DRIVER_MAJOR, DRIVER_MINOR); + driver.num_ioctls = DRM_ARRAY_SIZE(pl111_ioctls); + ret = 0; + driver.kdriver.platform_device = dev; + return drm_platform_init(&driver, dev); + +} + +void pl111_drm_exit(struct platform_device *dev) +{ + pr_info("DRM %s\n", __func__); + drm_platform_exit(&driver, dev); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_dma_buf.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_dma_buf.c new file mode 100644 index 0000000000000000000000000000000000000000..a0d65f1d5faf4e7cb5ae14c71f319ff53815bfdb --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_dma_buf.c @@ -0,0 +1,615 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_dma_buf.c + * Implementation of the dma_buf functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS +static void obtain_kds_if_currently_displayed(struct drm_device *dev, + struct pl111_gem_bo *bo, + struct dma_buf *dma_buf) +{ + unsigned long shared[1] = { 0 }; + struct kds_resource *resource_list[1]; + struct kds_resource_set *kds_res_set; + struct drm_crtc *crtc; + bool cb_has_called = false; + unsigned long flags; + int err; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + + DRM_DEBUG_KMS("Obtaining initial KDS res for bo:%p dma_buf:%p\n", + bo, dma_buf); + + resource_list[0] = get_dma_buf_kds_resource(dma_buf); + get_dma_buf(dma_buf); + + /* + * Can't use kds_waitall(), because kbase will be let through due to + * locked ignore' + */ + err = kds_async_waitall(&kds_res_set, + &priv.kds_obtain_current_cb, &wake, + &cb_has_called, 1, shared, resource_list); + BUG_ON(err); + wait_event(wake, cb_has_called == true); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + if (pl111_crtc->displaying_fb) { + struct pl111_drm_framebuffer *pl111_fb; + struct drm_framebuffer *fb = pl111_crtc->displaying_fb; + + pl111_fb = PL111_FB_FROM_FRAMEBUFFER(fb); + + if (pl111_fb->bo == bo) { + DRM_DEBUG_KMS("Initial KDS resource for bo %p", bo); + DRM_DEBUG_KMS(" is being displayed, keeping\n"); + /* There shouldn't be a previous buffer to release */ + BUG_ON(pl111_crtc->old_kds_res_set); + + if (kds_res_set == NULL) { + err = kds_async_waitall(&kds_res_set, + &priv.kds_obtain_current_cb, + &wake, &cb_has_called, + 1, shared, resource_list); + BUG_ON(err); + wait_event(wake, cb_has_called == true); + } + + /* Current buffer will need releasing on next flip */ + pl111_crtc->old_kds_res_set = kds_res_set; + + /* + * Clear kds_res_set, so a new kds_res_set is allocated + * for additional CRTCs + */ + kds_res_set = NULL; + } + } + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, flags); + } + + /* kds_res_set will be NULL here if any CRTCs are displaying fb */ + if (kds_res_set != NULL) { + DRM_DEBUG_KMS("Initial KDS resource for bo %p", bo); + DRM_DEBUG_KMS(" not being displayed, discarding\n"); + /* They're not being displayed, release them */ + kds_resource_set_release(&kds_res_set); + } + + dma_buf_put(dma_buf); +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) + +static int pl111_dma_buf_mmap(struct dma_buf *buffer, + struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = buffer->priv; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + struct drm_device *dev = obj->dev; + int ret; + + DRM_DEBUG_KMS("DRM %s on dma_buf=%p\n", __func__, buffer); + + mutex_lock(&dev->struct_mutex); + ret = drm_gem_mmap_obj(obj, obj->size, vma); + mutex_unlock(&dev->struct_mutex); + if (ret) + return ret; + + return pl111_bo_mmap(obj, bo, vma, buffer->size); +} + +#else + +static int pl111_dma_buf_mmap(struct dma_buf *buffer, + struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = buffer->priv; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + struct drm_device *dev = obj->dev; + + DRM_DEBUG_KMS("DRM %s on dma_buf=%p\n", __func__, buffer); + + mutex_lock(&dev->struct_mutex); + + /* Check for valid size. */ + if (obj->size < vma->vm_end - vma->vm_start) + return -EINVAL; + + BUG_ON(!dev->driver->gem_vm_ops); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; +#else + vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND; +#endif + + vma->vm_ops = dev->driver->gem_vm_ops; + vma->vm_private_data = obj; + + /* Take a ref for this mapping of the object, so that the fault + * handler can dereference the mmap offset's pointer to the object. + * This reference is cleaned up by the corresponding vm_close + * (which should happen whether the vma was created by this call, or + * by a vm_open due to mremap or partial unmap or whatever). + */ + drm_gem_object_reference(obj); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) + pl111_drm_vm_open_locked(dev, vma); +#else + drm_vm_open_locked(dev, vma); +#endif + + mutex_unlock(&dev->struct_mutex); + + return pl111_bo_mmap(obj, bo, vma, buffer->size); +} + +#endif /* KERNEL_VERSION */ + +static void pl111_dma_buf_release(struct dma_buf *buf) +{ + /* + * Need to release the dma_buf's reference on the gem object it was + * exported from, and also clear the gem object's export_dma_buf + * pointer to this dma_buf as it no longer exists + */ + struct drm_gem_object *obj = (struct drm_gem_object *)buf->priv; + struct pl111_gem_bo *bo; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct drm_crtc *crtc; + unsigned long flags; +#endif + bo = PL111_BO_FROM_GEM(obj); + + DRM_DEBUG_KMS("Releasing dma_buf %p, drm_gem_obj=%p\n", buf, obj); + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + list_for_each_entry(crtc, &bo->gem_object.dev->mode_config.crtc_list, + head) { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + if (pl111_crtc->displaying_fb) { + struct pl111_drm_framebuffer *pl111_fb; + struct drm_framebuffer *fb = pl111_crtc->displaying_fb; + + pl111_fb = PL111_FB_FROM_FRAMEBUFFER(fb); + if (pl111_fb->bo == bo) { + kds_resource_set_release(&pl111_crtc->old_kds_res_set); + pl111_crtc->old_kds_res_set = NULL; + } + } + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, flags); + } +#endif + mutex_lock(&priv.export_dma_buf_lock); + + obj->export_dma_buf = NULL; + drm_gem_object_unreference_unlocked(obj); + + mutex_unlock(&priv.export_dma_buf_lock); +} + +static int pl111_dma_buf_attach(struct dma_buf *buf, struct device *dev, + struct dma_buf_attachment *attach) +{ + DRM_DEBUG_KMS("Attaching dma_buf %p to device %p attach=%p\n", buf, + dev, attach); + + attach->priv = dev; + + return 0; +} + +static void pl111_dma_buf_detach(struct dma_buf *buf, + struct dma_buf_attachment *attach) +{ + DRM_DEBUG_KMS("Detaching dma_buf %p attach=%p\n", attach->dmabuf, + attach); +} + +/* Heavily from exynos_drm_dmabuf.c */ +static struct sg_table *pl111_dma_buf_map_dma_buf(struct dma_buf_attachment + *attach, + enum dma_data_direction + direction) +{ + struct drm_gem_object *obj = attach->dmabuf->priv; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + struct drm_device *dev = obj->dev; + int size, n_pages, nents; + struct scatterlist *s, *sg; + struct sg_table *sgt; + int ret, i; + + DRM_DEBUG_KMS("Mapping dma_buf %p from attach=%p (bo=%p)\n", attach->dmabuf, + attach, bo); + + /* + * Nothing to do, if we are trying to map a dmabuf that has been imported. + * Just return the existing sgt. + */ + if (obj->import_attach) { + BUG_ON(!bo->sgt); + return bo->sgt; + } + + size = obj->size; + n_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; + + if (bo->type & PL111_BOT_DMA) { + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) { + DRM_ERROR("Failed to allocate sg_table\n"); + return ERR_PTR(-ENOMEM); + } + + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); + if (ret < 0) { + DRM_ERROR("Failed to allocate page table\n"); + return ERR_PTR(-ENOMEM); + } + sg_dma_len(sgt->sgl) = size; + /* We use DMA coherent mappings for PL111_BOT_DMA so we must + * use the virtual address returned at buffer allocation */ + sg_set_buf(sgt->sgl, bo->backing_data.dma.fb_cpu_addr, size); + sg_dma_address(sgt->sgl) = bo->backing_data.dma.fb_dev_addr; + } else { /* PL111_BOT_SHM */ + struct page **pages; + int pg = 0; + + mutex_lock(&dev->struct_mutex); + pages = get_pages(obj); + if (IS_ERR(pages)) { + dev_err(obj->dev->dev, "could not get pages: %ld\n", + PTR_ERR(pages)); + return ERR_CAST(pages); + } + sgt = drm_prime_pages_to_sg(pages, n_pages); + if (sgt == NULL) + return ERR_PTR(-ENOMEM); + + pl111_gem_sync_to_dma(bo); + + /* + * At this point the pages have been dma-mapped by either + * get_pages() for non cached maps or pl111_gem_sync_to_dma() + * for cached. So the physical addresses can be assigned + * to the sg entries. + * drm_prime_pages_to_sg() may have combined contiguous pages + * into chunks so we assign the physical address of the first + * page of a chunk to the chunk and check that the physical + * addresses of the rest of the pages in that chunk are also + * contiguous. + */ + sg = sgt->sgl; + nents = sgt->nents; + + for_each_sg(sg, s, nents, i) { + int j, n_pages_in_chunk = sg_dma_len(s) >> PAGE_SHIFT; + + sg_dma_address(s) = bo->backing_data.shm.dma_addrs[pg]; + + for (j = pg+1; j < pg+n_pages_in_chunk; j++) { + BUG_ON(bo->backing_data.shm.dma_addrs[j] != + bo->backing_data.shm.dma_addrs[j-1]+PAGE_SIZE); + } + + pg += n_pages_in_chunk; + } + + mutex_unlock(&dev->struct_mutex); + } + bo->sgt = sgt; + return sgt; +} + +static void pl111_dma_buf_unmap_dma_buf(struct dma_buf_attachment *attach, + struct sg_table *sgt, + enum dma_data_direction direction) +{ + struct drm_gem_object *obj = attach->dmabuf->priv; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + + DRM_DEBUG_KMS("Unmapping dma_buf %p from attach=%p (bo=%p)\n", attach->dmabuf, + attach, bo); + + sg_free_table(sgt); + kfree(sgt); + bo->sgt = NULL; +} + +/* + * There isn't any operation here that can sleep or fail so this callback can + * be used for both kmap and kmap_atomic implementations. + */ +static void *pl111_dma_buf_kmap(struct dma_buf *dma_buf, unsigned long pageno) +{ + struct pl111_gem_bo *bo = dma_buf->priv; + void *vaddr = NULL; + + /* Make sure we cannot access outside the memory range */ + if (((pageno + 1) << PAGE_SHIFT) > bo->gem_object.size) + return NULL; + + if (bo->type & PL111_BOT_DMA) { + vaddr = (bo->backing_data.dma.fb_cpu_addr + + (pageno << PAGE_SHIFT)); + } else { + vaddr = page_address(bo->backing_data.shm.pages[pageno]); + } + + return vaddr; +} + +/* + * Find a scatterlist that starts in "start" and has "len" + * or return a NULL dma_handle. + */ +static dma_addr_t pl111_find_matching_sg(struct sg_table *sgt, size_t start, + size_t len) +{ + struct scatterlist *sg; + unsigned int count; + size_t size = 0; + dma_addr_t dma_handle = 0; + + /* Find a scatterlist that starts in "start" and has "len" + * or return error */ + for_each_sg(sgt->sgl, sg, sgt->nents, count) { + if ((size == start) && (len == sg_dma_len(sg))) { + dma_handle = sg_dma_address(sg); + break; + } + size += sg_dma_len(sg); + } + return dma_handle; +} + +static int pl111_dma_buf_begin_cpu(struct dma_buf *dma_buf, + size_t start, size_t len, + enum dma_data_direction dir) +{ + struct pl111_gem_bo *bo = dma_buf->priv; + struct sg_table *sgt = bo->sgt; + dma_addr_t dma_handle; + + if ((start + len) > bo->gem_object.size) + return -EINVAL; + + if (!(bo->type & PL111_BOT_SHM)) { + struct device *dev = bo->gem_object.dev->dev; + + dma_handle = pl111_find_matching_sg(sgt, start, len); + if (!dma_handle) + return -EINVAL; + + dma_sync_single_range_for_cpu(dev, dma_handle, 0, len, dir); + } + /* PL111_BOT_DMA uses coherents mappings, no need to sync */ + return 0; +} + +static void pl111_dma_buf_end_cpu(struct dma_buf *dma_buf, + size_t start, size_t len, + enum dma_data_direction dir) +{ + struct pl111_gem_bo *bo = dma_buf->priv; + struct sg_table *sgt = bo->sgt; + dma_addr_t dma_handle; + + if ((start + len) > bo->gem_object.size) + return; + + if (!(bo->type & PL111_BOT_DMA)) { + struct device *dev = bo->gem_object.dev->dev; + + dma_handle = pl111_find_matching_sg(sgt, start, len); + if (!dma_handle) + return; + + dma_sync_single_range_for_device(dev, dma_handle, 0, len, dir); + } + /* PL111_BOT_DMA uses coherents mappings, no need to sync */ +} + +static struct dma_buf_ops pl111_dma_buf_ops = { + .release = &pl111_dma_buf_release, + .attach = &pl111_dma_buf_attach, + .detach = &pl111_dma_buf_detach, + .map_dma_buf = &pl111_dma_buf_map_dma_buf, + .unmap_dma_buf = &pl111_dma_buf_unmap_dma_buf, + .kmap_atomic = &pl111_dma_buf_kmap, + .kmap = &pl111_dma_buf_kmap, + .begin_cpu_access = &pl111_dma_buf_begin_cpu, + .end_cpu_access = &pl111_dma_buf_end_cpu, + .mmap = &pl111_dma_buf_mmap, +}; + +struct drm_gem_object *pl111_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf) +{ + struct dma_buf_attachment *attachment; + struct drm_gem_object *obj; + struct pl111_gem_bo *bo; + struct scatterlist *sgl; + struct sg_table *sgt; + dma_addr_t cont_phys; + int ret = 0; + int i; + + DRM_DEBUG_KMS("DRM %s on dev=%p dma_buf=%p\n", __func__, dev, dma_buf); + + /* is this one of own objects? */ + if (dma_buf->ops == &pl111_dma_buf_ops) { + obj = dma_buf->priv; + /* is it from our device? */ + if (obj->dev == dev) { + /* + * Importing dmabuf exported from our own gem increases + * refcount on gem itself instead of f_count of dmabuf. + */ + drm_gem_object_reference(obj); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) + /* before v3.10.0 we assume the caller has taken a ref on the dma_buf + * we don't want it for self-imported buffers so drop it here */ + dma_buf_put(dma_buf); +#endif + + return obj; + } + } + + attachment = dma_buf_attach(dma_buf, dev->dev); + if (IS_ERR(attachment)) + return ERR_CAST(attachment); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) + /* from 3.10.0 we assume the caller has not taken a ref so we take one here */ + get_dma_buf(dma_buf); +#endif + + sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(sgt)) { + ret = PTR_ERR(sgt); + goto err_buf_detach; + } + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); + if (!bo) { + DRM_ERROR("%s: failed to allocate buffer object.\n", __func__); + ret = -ENOMEM; + goto err_unmap_attach; + } + + /* Find out whether the buffer is contiguous or not */ + sgl = sgt->sgl; + cont_phys = sg_phys(sgl); + bo->type |= PL111_BOT_DMA; + for_each_sg(sgt->sgl, sgl, sgt->nents, i) { + dma_addr_t real_phys = sg_phys(sgl); + if (real_phys != cont_phys) { + bo->type &= ~PL111_BOT_DMA; + break; + } + cont_phys += (PAGE_SIZE - sgl->offset); + } + + ret = drm_gem_private_object_init(dev, &bo->gem_object, + dma_buf->size); + if (ret != 0) { + DRM_ERROR("DRM could not import DMA GEM obj\n"); + goto err_free_buffer; + } + + if (bo->type & PL111_BOT_DMA) { + bo->backing_data.dma.fb_cpu_addr = sg_virt(sgt->sgl); + bo->backing_data.dma.fb_dev_addr = sg_phys(sgt->sgl); + DRM_DEBUG_KMS("DRM %s pl111_gem_bo=%p, contiguous import\n", __func__, bo); + } else { /* PL111_BOT_SHM */ + DRM_DEBUG_KMS("DRM %s pl111_gem_bo=%p, non contiguous import\n", __func__, bo); + } + + bo->gem_object.import_attach = attachment; + bo->sgt = sgt; + + return &bo->gem_object; + +err_free_buffer: + kfree(bo); + bo = NULL; +err_unmap_attach: + dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL); +err_buf_detach: + dma_buf_detach(dma_buf, attachment); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) + /* from 3.10.0 we will have taken a ref so drop it here */ + dma_buf_put(dma_buf); +#endif + return ERR_PTR(ret); +} + +struct dma_buf *pl111_gem_prime_export(struct drm_device *dev, + struct drm_gem_object *obj, int flags) +{ + struct dma_buf *new_buf; + struct pl111_gem_bo *bo; + size_t size; + + DRM_DEBUG("DRM %s on dev=%p drm_gem_obj=%p\n", __func__, dev, obj); + size = obj->size; + + new_buf = dma_buf_export(obj /*priv */ , &pl111_dma_buf_ops, size, + flags | O_RDWR); + bo = PL111_BO_FROM_GEM(new_buf->priv); + + /* + * bo->gem_object.export_dma_buf not setup until after gem_prime_export + * finishes + */ + +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* + * Ensure that we hold the kds resource if it's the currently + * displayed buffer. + */ + obtain_kds_if_currently_displayed(dev, bo, new_buf); +#endif + + DRM_DEBUG("Created dma_buf %p\n", new_buf); + + return new_buf; +} + +int pl111_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, + uint32_t handle, uint32_t flags, int *prime_fd) +{ + int result; + /* + * This will re-use any existing exports, and calls + * driver->gem_prime_export to do the first export when needed + */ + DRM_DEBUG_KMS("DRM %s on file_priv=%p, handle=0x%.8x\n", __func__, + file_priv, handle); + + mutex_lock(&priv.export_dma_buf_lock); + result = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, + prime_fd); + mutex_unlock(&priv.export_dma_buf_lock); + + return result; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_encoder.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_encoder.c new file mode 100644 index 0000000000000000000000000000000000000000..b7dbbf2794ab896a3a59bd76aa730d022f0c3c3a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_encoder.c @@ -0,0 +1,107 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_encoder.c + * Implementation of the encoder functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pl111_drm.h" + +bool pl111_encoder_helper_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); + return true; +} + +void pl111_encoder_helper_prepare(struct drm_encoder *encoder) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); +} + +void pl111_encoder_helper_commit(struct drm_encoder *encoder) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); +} + +void pl111_encoder_helper_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); +} + +void pl111_encoder_helper_disable(struct drm_encoder *encoder) +{ + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); +} + +void pl111_encoder_destroy(struct drm_encoder *encoder) +{ + struct pl111_drm_encoder *pl111_encoder = + PL111_ENCODER_FROM_ENCODER(encoder); + + DRM_DEBUG_KMS("DRM %s on encoder=%p\n", __func__, encoder); + + drm_encoder_cleanup(encoder); + kfree(pl111_encoder); +} + +const struct drm_encoder_funcs encoder_funcs = { + .destroy = pl111_encoder_destroy, +}; + +const struct drm_encoder_helper_funcs encoder_helper_funcs = { + .mode_fixup = pl111_encoder_helper_mode_fixup, + .prepare = pl111_encoder_helper_prepare, + .commit = pl111_encoder_helper_commit, + .mode_set = pl111_encoder_helper_mode_set, + .disable = pl111_encoder_helper_disable, +}; + +struct pl111_drm_encoder *pl111_encoder_create(struct drm_device *dev, + int possible_crtcs) +{ + struct pl111_drm_encoder *pl111_encoder; + + pl111_encoder = kzalloc(sizeof(struct pl111_drm_encoder), GFP_KERNEL); + if (pl111_encoder == NULL) { + pr_err("Failed to allocated pl111_drm_encoder\n"); + return NULL; + } + + drm_encoder_init(dev, &pl111_encoder->encoder, &encoder_funcs, + DRM_MODE_ENCODER_DAC); + + drm_encoder_helper_add(&pl111_encoder->encoder, &encoder_helper_funcs); + + pl111_encoder->encoder.possible_crtcs = possible_crtcs; + + return pl111_encoder; +} + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_fb.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_fb.c new file mode 100644 index 0000000000000000000000000000000000000000..546e4d45f4c95842c82cffaadcf3a0607f022178 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_fb.c @@ -0,0 +1,202 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_fb.c + * Implementation of the framebuffer functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "pl111_drm.h" + +static void pl111_fb_destroy(struct drm_framebuffer *framebuffer) +{ + struct pl111_drm_framebuffer *pl111_fb; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct drm_crtc *crtc; + unsigned long flags; +#endif + DRM_DEBUG_KMS("Destroying framebuffer 0x%p...\n", framebuffer); + + pl111_fb = PL111_FB_FROM_FRAMEBUFFER(framebuffer); + + /* + * Because flips are deferred, wait for all previous flips to complete + */ + wait_event(priv.wait_for_flips, + atomic_read(&priv.nr_flips_in_flight) == 0); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* + * Release KDS resources if it's currently being displayed. Only occurs + * when the last framebuffer is destroyed. + */ + list_for_each_entry(crtc, &framebuffer->dev->mode_config.crtc_list, + head) { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + if (pl111_crtc->displaying_fb == framebuffer) { + /* Release the current buffers */ + if (pl111_crtc->old_kds_res_set != NULL) { + DRM_DEBUG_KMS("Releasing KDS resources for "); + DRM_DEBUG_KMS("displayed 0x%p\n", framebuffer); + kds_resource_set_release( + &pl111_crtc->old_kds_res_set); + } + pl111_crtc->old_kds_res_set = NULL; + } + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, + flags); + } +#endif + drm_framebuffer_cleanup(framebuffer); + + if ((pl111_fb->bo != NULL) && (&pl111_fb->bo->gem_object != NULL)) + drm_gem_object_unreference_unlocked(&pl111_fb->bo->gem_object); + + kfree(pl111_fb); + + DRM_DEBUG_KMS("Destroyed framebuffer 0x%p\n", framebuffer); +} + +static int pl111_fb_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + struct pl111_gem_bo *bo = PL111_BO_FROM_FRAMEBUFFER(fb); + DRM_DEBUG_KMS("DRM %s on fb=%p\n", __func__, fb); + + if (bo == NULL) + return -EINVAL; + + return drm_gem_handle_create(file_priv, &bo->gem_object, handle); +} + +const struct drm_framebuffer_funcs fb_funcs = { + .destroy = pl111_fb_destroy, + .create_handle = pl111_fb_create_handle, +}; + +struct drm_framebuffer *pl111_fb_create(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct pl111_drm_framebuffer *pl111_fb = NULL; + struct drm_framebuffer *fb = NULL; + struct drm_gem_object *gem_obj; + struct pl111_gem_bo *bo; + int err = 0; + size_t min_size; + int bpp; + int depth; + + pr_info("DRM %s\n", __func__); + gem_obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (gem_obj == NULL) { + DRM_ERROR("Could not get gem obj from handle to create fb\n"); + err = -ENOENT; + goto error; + } + + bo = PL111_BO_FROM_GEM(gem_obj); + drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + if (mode_cmd->pitches[0] < mode_cmd->width * (bpp >> 3)) { + DRM_ERROR("bad pitch %u for plane 0\n", mode_cmd->pitches[0]); + err = -EINVAL; + goto error; + } + + min_size = (mode_cmd->height - 1) * mode_cmd->pitches[0] + + mode_cmd->width * (bpp >> 3); + + if (bo->gem_object.size < min_size) { + DRM_ERROR("gem obj size < min size\n"); + err = -EINVAL; + goto error; + } + + /* We can't scan out SHM so we can't create an fb for it */ + if (!(bo->type & PL111_BOT_DMA)) { + DRM_ERROR("Can't create FB for non-scanout buffer\n"); + err = -EINVAL; + goto error; + } + + switch ((char)(mode_cmd->pixel_format & 0xFF)) { + case 'Y': + case 'U': + case 'V': + case 'N': + case 'T': + DRM_ERROR("YUV formats not supported\n"); + err = -EINVAL; + goto error; + } + + pl111_fb = kzalloc(sizeof(struct pl111_drm_framebuffer), GFP_KERNEL); + if (pl111_fb == NULL) { + DRM_ERROR("Could not allocate pl111_drm_framebuffer\n"); + err = -ENOMEM; + goto error; + } + fb = &pl111_fb->fb; + + err = drm_framebuffer_init(dev, fb, &fb_funcs); + if (err) { + DRM_ERROR("drm_framebuffer_init failed\n"); + kfree(fb); + fb = NULL; + goto error; + } + + drm_helper_mode_fill_fb_struct(fb, mode_cmd); + + /* The only framebuffer formats supported by pl111 + * are 16 bpp or 32 bpp with 24 bit depth. + * See clcd_enable() + */ + if (!((fb->bits_per_pixel == 16) || + (fb->bits_per_pixel == 32 && fb->depth == 24))) { + DRM_DEBUG_KMS("unsupported pixel format bpp=%d, depth=%d\n", fb->bits_per_pixel, fb->depth); + drm_framebuffer_cleanup(fb); + kfree(fb); + fb = NULL; + err = -EINVAL; + goto error; + } + + pl111_fb->bo = bo; + + DRM_DEBUG_KMS("Created fb 0x%p with gem_obj 0x%p physaddr=0x%.8x\n", + fb, gem_obj, bo->backing_data.dma.fb_dev_addr); + + return fb; + +error: + if (gem_obj != NULL) + drm_gem_object_unreference_unlocked(gem_obj); + + return ERR_PTR(err); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_funcs.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_funcs.h new file mode 100644 index 0000000000000000000000000000000000000000..34e0bad994d7667846a96952166eeeb59dd37e2a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_funcs.h @@ -0,0 +1,130 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_funcs.h + * Function prototypes for PL111 DRM + */ + +#ifndef PL111_DRM_FUNCS_H_ +#define PL111_DRM_FUNCS_H_ + +/* Platform Initialisation */ +int pl111_drm_init(struct platform_device *dev); +void pl111_drm_exit(struct platform_device *dev); + +/* KDS Callbacks */ +void show_framebuffer_on_crtc_cb(void *cb1, void *cb2); +void release_kds_resource_and_display(struct pl111_drm_flip_resource *flip_res); + +/* CRTC Functions */ +struct pl111_drm_crtc *pl111_crtc_create(struct drm_device *dev); +struct pl111_drm_crtc *pl111_crtc_dummy_create(struct drm_device *dev); +void pl111_crtc_destroy(struct drm_crtc *crtc); + +bool pl111_crtc_is_fb_currently_displayed(struct drm_device *dev, + struct drm_framebuffer *fb); + +int show_framebuffer_on_crtc(struct drm_crtc *crtc, + struct drm_framebuffer *fb, bool page_flip, + struct drm_pending_vblank_event *event); + +/* Common IRQ handler */ +void pl111_common_irq(struct pl111_drm_crtc *pl111_crtc); + +int pl111_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height); +int pl111_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y); + +/* Connector Functions */ +struct pl111_drm_connector *pl111_connector_create(struct drm_device *dev); +void pl111_connector_destroy(struct drm_connector *connector); +struct pl111_drm_connector *pl111_connector_dummy_create(struct drm_device + *dev); + +/* Encoder Functions */ +struct pl111_drm_encoder *pl111_encoder_create(struct drm_device *dev, + int possible_crtcs); +struct pl111_drm_encoder *pl111_encoder_dummy_create(struct drm_device *dev, + int possible_crtcs); +void pl111_encoder_destroy(struct drm_encoder *encoder); + +/* Frame Buffer Functions */ +struct drm_framebuffer *pl111_fb_create(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_mode_fb_cmd2 *mode_cmd); + +/* VMA Functions */ +int pl111_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); +int pl111_gem_mmap(struct file *file_priv, struct vm_area_struct *vma); +struct page **get_pages(struct drm_gem_object *obj); +void put_pages(struct drm_gem_object *obj, struct page **pages); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) +void pl111_drm_vm_open_locked(struct drm_device *dev, + struct vm_area_struct *vma); +void pl111_gem_vm_open(struct vm_area_struct *vma); +void pl111_gem_vm_close(struct vm_area_struct *vma); +#endif + +/* Suspend Functions */ +int pl111_drm_resume(struct drm_device *dev); +int pl111_drm_suspend(struct drm_device *dev, pm_message_t state); + +/* GEM Functions */ +int pl111_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); +int pl111_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle); +int pl111_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); +void pl111_gem_free_object(struct drm_gem_object *obj); + +int pl111_bo_mmap(struct drm_gem_object *obj, struct pl111_gem_bo *bo, + struct vm_area_struct *vma, size_t size); +void pl111_gem_sync_to_cpu(struct pl111_gem_bo *bo, int pgoff); +void pl111_gem_sync_to_dma(struct pl111_gem_bo *bo); + +/* DMA BUF Functions */ +struct drm_gem_object *pl111_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf); +int pl111_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, + uint32_t handle, uint32_t flags, int *prime_fd); +struct dma_buf *pl111_gem_prime_export(struct drm_device *dev, + struct drm_gem_object *obj, int flags); + +/* Pl111 Functions */ +void show_framebuffer_on_crtc_cb_internal(struct pl111_drm_flip_resource + *flip_res, struct drm_framebuffer *fb); +int clcd_disable(struct drm_crtc *crtc); +void do_flip_to_res(struct pl111_drm_flip_resource *flip_res); +int pl111_amba_probe(struct amba_device *dev, const struct amba_id *id); +int pl111_amba_remove(struct amba_device *dev); + +int pl111_device_init(struct drm_device *dev); +void pl111_device_fini(struct drm_device *dev); + +void pl111_convert_drm_mode_to_timing(struct drm_display_mode *mode, + struct clcd_regs *timing); +void pl111_convert_timing_to_drm_mode(struct clcd_regs *timing, + struct drm_display_mode *mode); +#endif /* PL111_DRM_FUNCS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_gem.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_gem.c new file mode 100644 index 0000000000000000000000000000000000000000..ed5dcabe0082af3b9c35434e6e20b3512d030a0d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_gem.c @@ -0,0 +1,401 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_gem.c + * Implementation of the GEM functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pl111_drm.h" + +void pl111_gem_free_object(struct drm_gem_object *obj) +{ + struct pl111_gem_bo *bo; + struct drm_device *dev = obj->dev; + DRM_DEBUG_KMS("DRM %s on drm_gem_object=%p\n", __func__, obj); + + bo = PL111_BO_FROM_GEM(obj); + + if (obj->import_attach) + drm_prime_gem_destroy(obj, bo->sgt); + + if (obj->map_list.map != NULL) + drm_gem_free_mmap_offset(obj); + + /* + * Only free the backing memory if the object has not been imported. + * If it has been imported, the exporter is in charge to free that + * once dmabuf's refcount becomes 0. + */ + if (obj->import_attach) + goto imported_out; + + if (bo->type & PL111_BOT_DMA) { + dma_free_writecombine(dev->dev, obj->size, + bo->backing_data.dma.fb_cpu_addr, + bo->backing_data.dma.fb_dev_addr); + } else if (bo->backing_data.shm.pages != NULL) { + put_pages(obj, bo->backing_data.shm.pages); + } + +imported_out: + drm_gem_object_release(obj); + + kfree(bo); + + DRM_DEBUG_KMS("Destroyed dumb_bo handle 0x%p\n", bo); +} + +static int pl111_gem_object_create(struct drm_device *dev, u64 size, + u32 flags, struct drm_file *file_priv, + u32 *handle) +{ + int ret = 0; + struct pl111_gem_bo *bo = NULL; + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); + if (bo == NULL) { + ret = -ENOMEM; + goto finish; + } + + bo->type = flags; + +#ifndef ARCH_HAS_SG_CHAIN + /* + * If the ARCH can't chain we can't have non-contiguous allocs larger + * than a single sg can hold. + * In this case we fall back to using contiguous memory + */ + if (!(bo->type & PL111_BOT_DMA)) { + long unsigned int n_pages = + PAGE_ALIGN(size) >> PAGE_SHIFT; + if (n_pages > SG_MAX_SINGLE_ALLOC) { + bo->type |= PL111_BOT_DMA; + /* + * Non-contiguous allocation request changed to + * contigous + */ + DRM_INFO("non-contig alloc to contig %lu > %lu pages.", + n_pages, SG_MAX_SINGLE_ALLOC); + } + } +#endif + if (bo->type & PL111_BOT_DMA) { + /* scanout compatible - use physically contiguous buffer */ + bo->backing_data.dma.fb_cpu_addr = + dma_alloc_writecombine(dev->dev, size, + &bo->backing_data.dma.fb_dev_addr, + GFP_KERNEL); + if (bo->backing_data.dma.fb_cpu_addr == NULL) { + DRM_ERROR("dma_alloc_writecombine failed\n"); + ret = -ENOMEM; + goto free_bo; + } + + ret = drm_gem_private_object_init(dev, &bo->gem_object, + size); + if (ret != 0) { + DRM_ERROR("DRM could not initialise GEM object\n"); + goto free_dma; + } + } else { /* PL111_BOT_SHM */ + /* not scanout compatible - use SHM backed object */ + ret = drm_gem_object_init(dev, &bo->gem_object, size); + if (ret != 0) { + DRM_ERROR("DRM could not init SHM backed GEM obj\n"); + ret = -ENOMEM; + goto free_bo; + } + DRM_DEBUG_KMS("Num bytes: %d\n", bo->gem_object.size); + } + + DRM_DEBUG("s=%llu, flags=0x%x, %s 0x%.8lx, type=%d\n", + size, flags, + (bo->type & PL111_BOT_DMA) ? "physaddr" : "shared page array", + (bo->type & PL111_BOT_DMA) ? + (unsigned long)bo->backing_data.dma.fb_dev_addr: + (unsigned long)bo->backing_data.shm.pages, + bo->type); + + ret = drm_gem_handle_create(file_priv, &bo->gem_object, handle); + if (ret != 0) { + DRM_ERROR("DRM failed to create GEM handle\n"); + goto obj_release; + } + + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(&bo->gem_object); + + return 0; + +obj_release: + drm_gem_object_release(&bo->gem_object); +free_dma: + if (bo->type & PL111_BOT_DMA) + dma_free_writecombine(dev->dev, size, + bo->backing_data.dma.fb_cpu_addr, + bo->backing_data.dma.fb_dev_addr); +free_bo: + kfree(bo); +finish: + return ret; +} + +int pl111_drm_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_pl111_gem_create *args = data; + uint32_t bytes_pp; + + /* Round bpp up, to allow for case where bpp<8 */ + bytes_pp = args->bpp >> 3; + if (args->bpp & ((1 << 3) - 1)) + bytes_pp++; + + if (args->flags & ~PL111_BOT_MASK) { + DRM_ERROR("wrong flags: 0x%x\n", args->flags); + return -EINVAL; + } + + args->pitch = ALIGN(args->width * bytes_pp, 64); + args->size = PAGE_ALIGN(args->pitch * args->height); + + DRM_DEBUG_KMS("gem_create w=%d h=%d p=%d bpp=%d b=%d s=%llu f=0x%x\n", + args->width, args->height, args->pitch, args->bpp, + bytes_pp, args->size, args->flags); + + return pl111_gem_object_create(dev, args->size, args->flags, file_priv, + &args->handle); +} + +int pl111_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, struct drm_mode_create_dumb *args) +{ + uint32_t bytes_pp; + + /* Round bpp up, to allow for case where bpp<8 */ + bytes_pp = args->bpp >> 3; + if (args->bpp & ((1 << 3) - 1)) + bytes_pp++; + + if (args->flags) { + DRM_ERROR("flags must be zero: 0x%x\n", args->flags); + return -EINVAL; + } + + args->pitch = ALIGN(args->width * bytes_pp, 64); + args->size = PAGE_ALIGN(args->pitch * args->height); + + DRM_DEBUG_KMS("dumb_create w=%d h=%d p=%d bpp=%d b=%d s=%llu f=0x%x\n", + args->width, args->height, args->pitch, args->bpp, + bytes_pp, args->size, args->flags); + + return pl111_gem_object_create(dev, args->size, + PL111_BOT_DMA | PL111_BOT_UNCACHED, + file_priv, &args->handle); +} + +int pl111_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, + uint32_t handle) +{ + DRM_DEBUG_KMS("DRM %s on file_priv=%p handle=0x%.8x\n", __func__, + file_priv, handle); + return drm_gem_handle_delete(file_priv, handle); +} + +int pl111_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset) +{ + struct drm_gem_object *obj; + int ret = 0; + DRM_DEBUG_KMS("DRM %s on file_priv=%p handle=0x%.8x\n", __func__, + file_priv, handle); + + /* GEM does all our handle to object mapping */ + obj = drm_gem_object_lookup(dev, file_priv, handle); + if (obj == NULL) { + ret = -ENOENT; + goto fail; + } + + if (obj->map_list.map == NULL) { + ret = drm_gem_create_mmap_offset(obj); + if (ret != 0) { + drm_gem_object_unreference_unlocked(obj); + goto fail; + } + } + + *offset = (uint64_t) obj->map_list.hash.key << PAGE_SHIFT; + + drm_gem_object_unreference_unlocked(obj); +fail: + return ret; +} + +/* sync the buffer for DMA access */ +void pl111_gem_sync_to_dma(struct pl111_gem_bo *bo) +{ + struct drm_device *dev = bo->gem_object.dev; + + if (!(bo->type & PL111_BOT_DMA) && (bo->type & PL111_BOT_CACHED)) { + int i, npages = bo->gem_object.size >> PAGE_SHIFT; + struct page **pages = bo->backing_data.shm.pages; + bool dirty = false; + + for (i = 0; i < npages; i++) { + if (!bo->backing_data.shm.dma_addrs[i]) { + DRM_DEBUG("%s: dma map page=%d bo=%p\n", __func__, i, bo); + bo->backing_data.shm.dma_addrs[i] = + dma_map_page(dev->dev, pages[i], 0, + PAGE_SIZE, DMA_BIDIRECTIONAL); + dirty = true; + } + } + + if (dirty) { + DRM_DEBUG("%s: zap ptes (and flush cache) bo=%p\n", __func__, bo); + /* + * TODO MIDEGL-1813 + * + * Use flush_cache_page() and outer_flush_range() to + * flush only the user space mappings of the dirty pages + */ + flush_cache_all(); + outer_flush_all(); + unmap_mapping_range(bo->gem_object.filp->f_mapping, 0, + bo->gem_object.size, 1); + } + } +} + +void pl111_gem_sync_to_cpu(struct pl111_gem_bo *bo, int pgoff) +{ + struct drm_device *dev = bo->gem_object.dev; + + /* + * TODO MIDEGL-1808 + * + * The following check was meant to detect if the CPU is trying to access + * a buffer that is currently mapped for DMA accesses, which is illegal + * as described by the DMA-API. + * + * However, some of our tests are trying to do that, which triggers the message + * below and avoids dma-unmapping the pages not to annoy the DMA device but that + * leads to the test failing because of caches not being properly flushed. + */ + + /* + if (bo->sgt) { + DRM_ERROR("%s: the CPU is trying to access a dma-mapped buffer\n", __func__); + return; + } + */ + + if (!(bo->type & PL111_BOT_DMA) && (bo->type & PL111_BOT_CACHED) && + bo->backing_data.shm.dma_addrs[pgoff]) { + DRM_DEBUG("%s: unmap bo=%p (s=%d), paddr=%08x\n", + __func__, bo, bo->gem_object.size, + bo->backing_data.shm.dma_addrs[pgoff]); + dma_unmap_page(dev->dev, bo->backing_data.shm.dma_addrs[pgoff], + PAGE_SIZE, DMA_BIDIRECTIONAL); + bo->backing_data.shm.dma_addrs[pgoff] = 0; + } +} + +/* Based on omapdrm driver */ +int pl111_bo_mmap(struct drm_gem_object *obj, struct pl111_gem_bo *bo, + struct vm_area_struct *vma, size_t size) +{ + DRM_DEBUG("DRM %s on drm_gem_object=%p, pl111_gem_bo=%p type=%08x\n", + __func__, obj, bo, bo->type); + + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_flags |= VM_MIXEDMAP; + + if (bo->type & PL111_BOT_WC) { + vma->vm_page_prot = + pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + } else if (bo->type & PL111_BOT_CACHED) { + /* + * Objects that do not have a filp (DMA backed) can't be + * mapped as cached now. Write-combine should be enough. + */ + if (WARN_ON(!obj->filp)) + return -EINVAL; + + /* + * As explained in Documentation/dma-buf-sharing.txt + * we need this trick so that we can manually zap ptes + * in order to fake coherency. + */ + fput(vma->vm_file); + vma->vm_pgoff = 0; + get_file(obj->filp); + vma->vm_file = obj->filp; + + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + } else { /* PL111_BOT_UNCACHED */ + vma->vm_page_prot = + pgprot_noncached(vm_get_page_prot(vma->vm_flags)); + } + return 0; +} + +int pl111_gem_mmap(struct file *file_priv, struct vm_area_struct *vma) +{ + int ret; + struct drm_file *priv = file_priv->private_data; + struct drm_device *dev = priv->minor->dev; + struct drm_gem_mm *mm = dev->mm_private; + struct drm_local_map *map = NULL; + struct drm_hash_item *hash; + struct drm_gem_object *obj; + struct pl111_gem_bo *bo; + + DRM_DEBUG_KMS("DRM %s\n", __func__); + + drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash); + map = drm_hash_entry(hash, struct drm_map_list, hash)->map; + obj = map->handle; + bo = PL111_BO_FROM_GEM(obj); + + DRM_DEBUG_KMS("DRM %s on pl111_gem_bo %p bo->type 0x%08x\n", __func__, bo, bo->type); + + /* for an imported buffer we let the exporter handle the mmap */ + if (obj->import_attach) + return dma_buf_mmap(obj->import_attach->dmabuf, vma, 0); + + ret = drm_gem_mmap(file_priv, vma); + if (ret < 0) { + DRM_ERROR("failed to mmap\n"); + return ret; + } + + return pl111_bo_mmap(obj, bo, vma, vma->vm_end - vma->vm_start); +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_pl111.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_pl111.c new file mode 100644 index 0000000000000000000000000000000000000000..0b3c6813b36cce9bc33e07bc9a3acf4388d369e6 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_pl111.c @@ -0,0 +1,417 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_pl111.c + * PL111 specific functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pl111_drm.h" + +/* This can't be called from IRQ context, due to clk_get() and board->enable */ +static int clcd_enable(struct drm_framebuffer *fb) +{ + __u32 cntl; + struct clcd_board *board; + + pr_info("DRM %s\n", __func__); + + clk_prepare_enable(priv.clk); + + /* Enable and Power Up */ + cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDPWR | CNTL_LCDVCOMP(1); + DRM_DEBUG_KMS("fb->bits_per_pixel = %d\n", fb->bits_per_pixel); + if (fb->bits_per_pixel == 16) + cntl |= CNTL_LCDBPP16_565; + else if (fb->bits_per_pixel == 32 && fb->depth == 24) + cntl |= CNTL_LCDBPP24; + else + BUG_ON(1); + + cntl |= CNTL_BGR; + + writel(cntl, priv.regs + CLCD_PL111_CNTL); + + if (priv.amba_dev->dev.platform_data) { + board = priv.amba_dev->dev.platform_data; + + if (board->enable) + board->enable(NULL); + } + + /* Enable Interrupts */ + writel(CLCD_IRQ_NEXTBASE_UPDATE, priv.regs + CLCD_PL111_IENB); + + return 0; +} + +int clcd_disable(struct drm_crtc *crtc) +{ + struct clcd_board *board; + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + unsigned long flags; +#endif + + pr_info("DRM %s\n", __func__); + + /* Disable Interrupts */ + writel(0x00000000, priv.regs + CLCD_PL111_IENB); + + if (priv.amba_dev->dev.platform_data) { + board = priv.amba_dev->dev.platform_data; + + if (board->disable) + board->disable(NULL); + } + + /* Disable and Power Down */ + writel(0, priv.regs + CLCD_PL111_CNTL); + + /* Disable clock */ + clk_disable_unprepare(priv.clk); + + pl111_crtc->last_bpp = 0; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + /* Release the previous buffers */ + if (pl111_crtc->old_kds_res_set != NULL) + kds_resource_set_release(&pl111_crtc->old_kds_res_set); + + pl111_crtc->old_kds_res_set = NULL; + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, flags); +#endif + return 0; +} + +/* + * To avoid a possible race where "pl111_crtc->current_update_res" has + * been updated (non NULL) but the corresponding scanout buffer has not been + * written to the base registers we must always call this function holding + * the "base_update_lock" spinlock with IRQs disabled (spin_lock_irqsave()). + */ +void do_flip_to_res(struct pl111_drm_flip_resource *flip_res) +{ + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(flip_res->crtc); + struct drm_framebuffer *fb; + struct pl111_gem_bo *bo; + size_t min_size; + fb = flip_res->fb; + bo = PL111_BO_FROM_FRAMEBUFFER(fb); + + + + min_size = (fb->height - 1) * fb->pitches[0] + + fb->width * (fb->bits_per_pixel >> 3); + + BUG_ON(bo->gem_object.size < min_size); + + /* Don't even attempt PL111_BOT_SHM, it's not contiguous */ + BUG_ON(bo->type != PL111_BOT_DMA); + + /* + * Note the buffer for releasing after IRQ, and don't allow any more + * updates until then. + * + * This clcd controller latches the new address on next vsync. Address + * latching is indicated by CLCD_IRQ_NEXTBASE_UPDATE, and so we must + * wait for that before releasing the previous buffer's kds + * resources. Otherwise, we'll allow writers to write to the old buffer + * whilst it is still being displayed + */ + pl111_crtc->current_update_res = flip_res; + + DRM_DEBUG_KMS("Displaying fb 0x%p, dumb_bo 0x%p, physaddr %.8x\n", + fb, bo, bo->backing_data.dma.fb_dev_addr); + + if (drm_vblank_get(pl111_crtc->crtc.dev, pl111_crtc->crtc_index) < 0) + DRM_ERROR("Could not get vblank reference for crtc %d\n", + pl111_crtc->crtc_index); + + /* Set the scanout buffer */ + writel(bo->backing_data.dma.fb_dev_addr, priv.regs + CLCD_UBAS); + writel(bo->backing_data.dma.fb_dev_addr + + ((fb->height - 1) * fb->pitches[0]), priv.regs + CLCD_LBAS); +} + +void +show_framebuffer_on_crtc_cb_internal(struct pl111_drm_flip_resource *flip_res, + struct drm_framebuffer *fb) +{ + unsigned long irq_flags; + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(flip_res->crtc); + + spin_lock_irqsave(&pl111_crtc->base_update_lock, irq_flags); + if (list_empty(&pl111_crtc->update_queue) && + !pl111_crtc->current_update_res) { + do_flip_to_res(flip_res); + } else { + /* + * Enqueue the update to occur on a future IRQ + * This only happens on triple-or-greater buffering + */ + DRM_DEBUG_KMS("Deferring 3+ buffered flip to fb %p to IRQ\n", + fb); + list_add_tail(&flip_res->link, &pl111_crtc->update_queue); + } + spin_unlock_irqrestore(&pl111_crtc->base_update_lock, irq_flags); + + if (!flip_res->page_flip && (pl111_crtc->last_bpp == 0 || + pl111_crtc->last_bpp != fb->bits_per_pixel || + !drm_mode_equal(pl111_crtc->new_mode, + pl111_crtc->current_mode))) { + struct clcd_regs timing; + + pl111_convert_drm_mode_to_timing(pl111_crtc->new_mode, &timing); + + DRM_DEBUG_KMS("Set timing: %08X:%08X:%08X:%08X clk=%ldHz\n", + timing.tim0, timing.tim1, timing.tim2, + timing.tim3, timing.pixclock); + + /* This is the actual mode setting part */ + clk_set_rate(priv.clk, timing.pixclock); + + writel(timing.tim0, priv.regs + CLCD_TIM0); + writel(timing.tim1, priv.regs + CLCD_TIM1); + writel(timing.tim2, priv.regs + CLCD_TIM2); + writel(timing.tim3, priv.regs + CLCD_TIM3); + + clcd_enable(fb); + pl111_crtc->last_bpp = fb->bits_per_pixel; + } + + if (!flip_res->page_flip) { + drm_mode_destroy(flip_res->crtc->dev, pl111_crtc->current_mode); + pl111_crtc->current_mode = pl111_crtc->new_mode; + pl111_crtc->new_mode = NULL; + } + + BUG_ON(!pl111_crtc->current_mode); + + /* + * If IRQs weren't enabled before, they are now. This will eventually + * cause flip_res to be released via pl111_common_irq, which updates + * every time the Base Address is latched (i.e. every frame, regardless + * of whether we update the base address or not) + */ +} + +irqreturn_t pl111_irq(int irq, void *data) +{ + u32 irq_stat; + struct pl111_drm_crtc *pl111_crtc = priv.pl111_crtc; + + irq_stat = readl(priv.regs + CLCD_PL111_MIS); + + if (!irq_stat) + return IRQ_NONE; + + if (irq_stat & CLCD_IRQ_NEXTBASE_UPDATE) + pl111_common_irq(pl111_crtc); + + /* Clear the interrupt once done */ + writel(irq_stat, priv.regs + CLCD_PL111_ICR); + + return IRQ_HANDLED; +} + +int pl111_device_init(struct drm_device *dev) +{ + struct pl111_drm_dev_private *priv = dev->dev_private; + int ret; + + if (priv == NULL) { + pr_err("%s no private data\n", __func__); + return -EINVAL; + } + + if (priv->amba_dev == NULL) { + pr_err("%s no amba device found\n", __func__); + return -EINVAL; + } + + /* set up MMIO for register access */ + priv->mmio_start = priv->amba_dev->res.start; + priv->mmio_len = resource_size(&priv->amba_dev->res); + + DRM_DEBUG_KMS("mmio_start=%lu, mmio_len=%u\n", priv->mmio_start, + priv->mmio_len); + + priv->regs = ioremap(priv->mmio_start, priv->mmio_len); + if (priv->regs == NULL) { + pr_err("%s failed mmio\n", __func__); + return -EINVAL; + } + + /* turn off interrupts */ + writel(0, priv->regs + CLCD_PL111_IENB); + + ret = request_irq(priv->amba_dev->irq[0], pl111_irq, 0, + "pl111_irq_handler", NULL); + if (ret != 0) { + pr_err("%s failed %d\n", __func__, ret); + goto out_mmio; + } + + goto finish; + +out_mmio: + iounmap(priv->regs); +finish: + DRM_DEBUG_KMS("pl111_device_init returned %d\n", ret); + return ret; +} + +void pl111_device_fini(struct drm_device *dev) +{ + struct pl111_drm_dev_private *priv = dev->dev_private; + u32 cntl; + + if (priv == NULL || priv->regs == NULL) + return; + + free_irq(priv->amba_dev->irq[0], NULL); + + cntl = readl(priv->regs + CLCD_PL111_CNTL); + + cntl &= ~CNTL_LCDEN; + writel(cntl, priv->regs + CLCD_PL111_CNTL); + + cntl &= ~CNTL_LCDPWR; + writel(cntl, priv->regs + CLCD_PL111_CNTL); + + iounmap(priv->regs); +} + +int pl111_amba_probe(struct amba_device *dev, const struct amba_id *id) +{ + struct clcd_board *board = dev->dev.platform_data; + int ret; + pr_info("DRM %s\n", __func__); + + if (!board) + dev_warn(&dev->dev, "board data not available\n"); + + ret = amba_request_regions(dev, NULL); + if (ret != 0) { + DRM_ERROR("CLCD: unable to reserve regs region\n"); + goto out; + } + + priv.amba_dev = dev; + + priv.clk = clk_get(&priv.amba_dev->dev, NULL); + if (IS_ERR(priv.clk)) { + DRM_ERROR("CLCD: unable to get clk.\n"); + ret = PTR_ERR(priv.clk); + goto clk_err; + } + + return 0; + +clk_err: + amba_release_regions(dev); +out: + return ret; +} + +int pl111_amba_remove(struct amba_device *dev) +{ + DRM_DEBUG_KMS("DRM %s\n", __func__); + + clk_put(priv.clk); + + amba_release_regions(dev); + + priv.amba_dev = NULL; + + return 0; +} + +void pl111_convert_drm_mode_to_timing(struct drm_display_mode *mode, + struct clcd_regs *timing) +{ + unsigned int ppl, hsw, hfp, hbp; + unsigned int lpp, vsw, vfp, vbp; + unsigned int cpl; + + memset(timing, 0, sizeof(struct clcd_regs)); + + ppl = (mode->hdisplay / 16) - 1; + hsw = mode->hsync_end - mode->hsync_start - 1; + hfp = mode->hsync_start - mode->hdisplay - 1; + hbp = mode->htotal - mode->hsync_end - 1; + + lpp = mode->vdisplay - 1; + vsw = mode->vsync_end - mode->vsync_start - 1; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + + cpl = mode->hdisplay - 1; + + timing->tim0 = (ppl << 2) | (hsw << 8) | (hfp << 16) | (hbp << 24); + timing->tim1 = lpp | (vsw << 10) | (vfp << 16) | (vbp << 24); + timing->tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC | TIM2_BCD | (cpl << 16); + timing->tim3 = 0; + + timing->pixclock = mode->clock * 1000; +} + +void pl111_convert_timing_to_drm_mode(struct clcd_regs *timing, + struct drm_display_mode *mode) +{ + unsigned int ppl, hsw, hfp, hbp; + unsigned int lpp, vsw, vfp, vbp; + + ppl = (timing->tim0 >> 2) & 0x3f; + hsw = (timing->tim0 >> 8) & 0xff; + hfp = (timing->tim0 >> 16) & 0xff; + hbp = (timing->tim0 >> 24) & 0xff; + + lpp = timing->tim1 & 0x3ff; + vsw = (timing->tim1 >> 10) & 0x3f; + vfp = (timing->tim1 >> 16) & 0xff; + vbp = (timing->tim1 >> 24) & 0xff; + + mode->hdisplay = (ppl + 1) * 16; + mode->hsync_start = ((ppl + 1) * 16) + hfp + 1; + mode->hsync_end = ((ppl + 1) * 16) + hfp + hsw + 2; + mode->htotal = ((ppl + 1) * 16) + hfp + hsw + hbp + 3; + mode->hskew = 0; + + mode->vdisplay = lpp + 1; + mode->vsync_start = lpp + vfp + 1; + mode->vsync_end = lpp + vfp + vsw + 2; + mode->vtotal = lpp + vfp + vsw + vbp + 2; + + mode->flags = 0; + + mode->width_mm = 0; + mode->height_mm = 0; + + mode->clock = timing->pixclock / 1000; + mode->hsync = timing->pixclock / mode->htotal; + mode->vrefresh = mode->hsync / mode->vtotal; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_platform.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..fe7db7392792a77d5031e28cad6cd5c9aa4cd6b3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_platform.c @@ -0,0 +1,151 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_platform.c + * Implementation of the Linux platform device entrypoints for PL111 DRM + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pl111_drm.h" + +static int pl111_platform_drm_suspend(struct platform_device *dev, + pm_message_t state) +{ + pr_info("DRM %s\n", __func__); + return 0; +} + +static int pl111_platform_drm_resume(struct platform_device *dev) +{ + pr_info("DRM %s\n", __func__); + return 0; +} + +int pl111_platform_drm_probe(struct platform_device *dev) +{ + pr_info("DRM %s\n", __func__); + return pl111_drm_init(dev); +} + +static int pl111_platform_drm_remove(struct platform_device *dev) +{ + pr_info("DRM %s\n", __func__); + pl111_drm_exit(dev); + + return 0; +} + +static struct amba_id pl111_id_table[] = { + { + .id = 0x00041110, + .mask = 0x000ffffe, + }, + {0, 0}, +}; + +static struct amba_driver pl111_amba_driver = { + .drv = { + .name = "clcd-pl11x", + }, + .probe = pl111_amba_probe, + .remove = pl111_amba_remove, + .id_table = pl111_id_table, +}; + +static struct platform_driver platform_drm_driver = { + .probe = pl111_platform_drm_probe, + .remove = pl111_platform_drm_remove, + .suspend = pl111_platform_drm_suspend, + .resume = pl111_platform_drm_resume, + .driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME, + }, +}; + +static const struct platform_device_info pl111_drm_pdevinfo = { + .name = DRIVER_NAME, + .id = -1, + .dma_mask = ~0UL +}; + +static struct platform_device *pl111_drm_device; + +static int __init pl111_platform_drm_init(void) +{ + int ret; + + pr_info("DRM %s\n", __func__); + + pl111_drm_device = platform_device_register_full(&pl111_drm_pdevinfo); + if (pl111_drm_device == NULL) { + pr_err("DRM platform_device_register_full() failed\n"); + return -ENOMEM; + } + + ret = amba_driver_register(&pl111_amba_driver); + if (ret != 0) { + pr_err("DRM amba_driver_register() failed %d\n", ret); + goto err_amba_reg; + } + + ret = platform_driver_register(&platform_drm_driver); + if (ret != 0) { + pr_err("DRM platform_driver_register() failed %d\n", ret); + goto err_pdrv_reg; + } + + return 0; + +err_pdrv_reg: + amba_driver_unregister(&pl111_amba_driver); +err_amba_reg: + platform_device_unregister(pl111_drm_device); + + return ret; +} + +static void __exit pl111_platform_drm_exit(void) +{ + pr_info("DRM %s\n", __func__); + + platform_device_unregister(pl111_drm_device); + amba_driver_unregister(&pl111_amba_driver); + platform_driver_unregister(&platform_drm_driver); +} + +#ifdef MODULE +module_init(pl111_platform_drm_init); +#else +late_initcall(pl111_platform_drm_init); +#endif +module_exit(pl111_platform_drm_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE(DRIVER_LICENCE); +MODULE_ALIAS(DRIVER_ALIAS); diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_suspend.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_suspend.c new file mode 100644 index 0000000000000000000000000000000000000000..a61636f8424ff7389855437d3cb34b6b71a849cc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_suspend.c @@ -0,0 +1,43 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_suspend.c + * Implementation of the suspend/resume functions for PL111 DRM + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pl111_drm.h" + +int pl111_drm_suspend(struct drm_device *dev, pm_message_t state) +{ + pr_info("DRM %s\n", __func__); + return 0; +} + +int pl111_drm_resume(struct drm_device *dev) +{ + pr_info("DRM %s\n", __func__); + return 0; +} diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_vma.c b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_vma.c new file mode 100644 index 0000000000000000000000000000000000000000..c9918f79e939f36c89cb1555e3f00ad099b3b395 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/pl111_drm_vma.c @@ -0,0 +1,307 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_vma.c + * Implementation of the VM functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "pl111_drm.h" + +/* BEGIN drivers/staging/omapdrm/omap_gem_helpers.c */ +/** + * drm_gem_put_pages - helper to free backing pages for a GEM object + * @obj: obj in question + * @pages: pages to free + */ +static void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, + bool dirty, bool accessed) +{ + int i, npages; + struct pl111_gem_bo *bo; + npages = obj->size >> PAGE_SHIFT; + bo = PL111_BO_FROM_GEM(obj); + for (i = 0; i < npages; i++) { + if (dirty) + set_page_dirty(pages[i]); + if (accessed) + mark_page_accessed(pages[i]); + /* Undo the reference we took when populating the table */ + page_cache_release(pages[i]); + } + drm_free_large(pages); +} + +void put_pages(struct drm_gem_object *obj, struct page **pages) +{ + int i, npages; + struct pl111_gem_bo *bo; + npages = obj->size >> PAGE_SHIFT; + bo = PL111_BO_FROM_GEM(obj); + _drm_gem_put_pages(obj, pages, true, true); + if (bo->backing_data.shm.dma_addrs) { + for (i = 0; i < npages; i++) { + /* Filter pages unmapped because of CPU accesses */ + if (!bo->backing_data.shm.dma_addrs[i]) + continue; + if (!dma_mapping_error(obj->dev->dev, + bo->backing_data.shm.dma_addrs[i])) { + dma_unmap_page(obj->dev->dev, + bo->backing_data.shm.dma_addrs[i], + PAGE_SIZE, + DMA_BIDIRECTIONAL); + } + } + kfree(bo->backing_data.shm.dma_addrs); + bo->backing_data.shm.dma_addrs = NULL; + } +} + +/** + * drm_gem_get_pages - helper to allocate backing pages for a GEM object + * @obj: obj in question + * @gfpmask: gfp mask of requested pages + */ +static struct page **_drm_gem_get_pages(struct drm_gem_object *obj, + gfp_t gfpmask) +{ + struct inode *inode; + struct address_space *mapping; + struct page *p, **pages; + int i, npages; + + /* This is the shared memory object that backs the GEM resource */ + inode = obj->filp->f_path.dentry->d_inode; + mapping = inode->i_mapping; + + npages = obj->size >> PAGE_SHIFT; + + pages = drm_malloc_ab(npages, sizeof(struct page *)); + if (pages == NULL) + return ERR_PTR(-ENOMEM); + + gfpmask |= mapping_gfp_mask(mapping); + + for (i = 0; i < npages; i++) { + p = shmem_read_mapping_page_gfp(mapping, i, gfpmask); + if (IS_ERR(p)) + goto fail; + pages[i] = p; + + /* + * There is a hypothetical issue w/ drivers that require + * buffer memory in the low 4GB.. if the pages are un- + * pinned, and swapped out, they can end up swapped back + * in above 4GB. If pages are already in memory, then + * shmem_read_mapping_page_gfp will ignore the gfpmask, + * even if the already in-memory page disobeys the mask. + * + * It is only a theoretical issue today, because none of + * the devices with this limitation can be populated with + * enough memory to trigger the issue. But this BUG_ON() + * is here as a reminder in case the problem with + * shmem_read_mapping_page_gfp() isn't solved by the time + * it does become a real issue. + * + * See this thread: http://lkml.org/lkml/2011/7/11/238 + */ + BUG_ON((gfpmask & __GFP_DMA32) && + (page_to_pfn(p) >= 0x00100000UL)); + } + + return pages; + +fail: + while (i--) + page_cache_release(pages[i]); + + drm_free_large(pages); + return ERR_PTR(PTR_ERR(p)); +} + +struct page **get_pages(struct drm_gem_object *obj) +{ + struct pl111_gem_bo *bo; + bo = PL111_BO_FROM_GEM(obj); + + if (bo->backing_data.shm.pages == NULL) { + struct page **p; + int npages = obj->size >> PAGE_SHIFT; + int i; + + p = _drm_gem_get_pages(obj, GFP_KERNEL); + if (IS_ERR(p)) + return ERR_PTR(-ENOMEM); + + bo->backing_data.shm.pages = p; + + if (bo->backing_data.shm.dma_addrs == NULL) { + bo->backing_data.shm.dma_addrs = + kzalloc(npages * sizeof(dma_addr_t), + GFP_KERNEL); + if (bo->backing_data.shm.dma_addrs == NULL) + goto error_out; + } + + if (!(bo->type & PL111_BOT_CACHED)) { + for (i = 0; i < npages; ++i) { + bo->backing_data.shm.dma_addrs[i] = + dma_map_page(obj->dev->dev, p[i], 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(obj->dev->dev, + bo->backing_data.shm.dma_addrs[i])) + goto error_out; + } + } + } + + return bo->backing_data.shm.pages; + +error_out: + put_pages(obj, bo->backing_data.shm.pages); + bo->backing_data.shm.pages = NULL; + return ERR_PTR(-ENOMEM); +} + +/* END drivers/staging/omapdrm/omap_gem_helpers.c */ +int pl111_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct page **pages; + pgoff_t pgoff; + unsigned long pfn; + struct drm_gem_object *obj = vma->vm_private_data; + struct pl111_gem_bo *bo = PL111_BO_FROM_GEM(obj); + struct drm_device *dev = obj->dev; + int ret; + + mutex_lock(&dev->struct_mutex); + + /* We don't use vmf->pgoff since that has the fake offset: */ + pgoff = ((unsigned long)vmf->virtual_address - + vma->vm_start) >> PAGE_SHIFT; + + if (bo->type & PL111_BOT_DMA) { + pfn = (bo->backing_data.dma.fb_dev_addr >> PAGE_SHIFT) + pgoff; + } else { /* PL111_BOT_SHM */ + pages = get_pages(obj); + if (IS_ERR(pages)) { + dev_err(obj->dev->dev, + "could not get pages: %ld\n", PTR_ERR(pages)); + ret = PTR_ERR(pages); + goto error; + } + pfn = page_to_pfn(pages[pgoff]); + pl111_gem_sync_to_cpu(bo, pgoff); + } + + DRM_DEBUG("bo=%p physaddr=0x%.8x for offset 0x%x\n", + bo, PFN_PHYS(pfn), PFN_PHYS(pgoff)); + + ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); + +error: + mutex_unlock(&dev->struct_mutex); + + switch (ret) { + case 0: + case -ERESTARTSYS: + case -EINTR: + case -EBUSY: + return VM_FAULT_NOPAGE; + case -ENOMEM: + return VM_FAULT_OOM; + default: + return VM_FAULT_SIGBUS; + } +} + +/* + * The core drm_vm_ functions in kernel 3.4 are not ready + * to handle dma_buf cases where vma->vm_file->private_data + * cannot be accessed to get the device. + * + * We use these functions from 3.5 instead where the device + * pointer is passed explicitly. + * + * However they aren't exported from the kernel until 3.10 + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)) +void pl111_drm_vm_open_locked(struct drm_device *dev, + struct vm_area_struct *vma) +{ + struct drm_vma_entry *vma_entry; + + DRM_DEBUG("0x%08lx,0x%08lx\n", + vma->vm_start, vma->vm_end - vma->vm_start); + atomic_inc(&dev->vma_count); + + vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL); + if (vma_entry) { + vma_entry->vma = vma; + vma_entry->pid = current->pid; + list_add(&vma_entry->head, &dev->vmalist); + } +} + +void pl111_drm_vm_close_locked(struct drm_device *dev, + struct vm_area_struct *vma) +{ + struct drm_vma_entry *pt, *temp; + + DRM_DEBUG("0x%08lx,0x%08lx\n", + vma->vm_start, vma->vm_end - vma->vm_start); + atomic_dec(&dev->vma_count); + + list_for_each_entry_safe(pt, temp, &dev->vmalist, head) { + if (pt->vma == vma) { + list_del(&pt->head); + kfree(pt); + break; + } + } +} + +void pl111_gem_vm_open(struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = vma->vm_private_data; + + drm_gem_object_reference(obj); + + mutex_lock(&obj->dev->struct_mutex); + pl111_drm_vm_open_locked(obj->dev, vma); + mutex_unlock(&obj->dev->struct_mutex); +} + +void pl111_gem_vm_close(struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = vma->vm_private_data; + struct drm_device *dev = obj->dev; + + mutex_lock(&dev->struct_mutex); + pl111_drm_vm_close_locked(obj->dev, vma); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); +} +#endif diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..dd274f5492d26ecd4e874bab87bc6deb97ef8cb3 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/pl111/sconscript @@ -0,0 +1,59 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +import os +import shutil +Import('env') + +# Generate a build environment for the integration tests, taking a copy of the top-level build environment +# (env) as a start. +drm_env = env.Clone() + +# Xorg uses C++ style comments and 'inline' keyword +if '-std=c89' in drm_env['CFLAGS']: + drm_env['CFLAGS'].remove('-std=c89') + +# X11 generates a lot of warnings +if '-Werror' in drm_env['CCFLAGS']: + drm_env['CCFLAGS'].remove('-Werror') + +#remove the 'lib'prefix +drm_env['LIBPREFIX'] = '' + +src = Glob('*.c') + +# Note: cleaning via the Linux kernel build system does not yet work +if drm_env.GetOption('clean') : + makeAction=Action("cd ${SOURCE.dir} && make clean", '$MAKECOMSTR') +else: + makeAction=Action("cd ${SOURCE.dir} && make MALI_DEBUG=${debug} && cp pl111_drm.ko $STATIC_LIB_PATH/mali_drm.ko", '$MAKECOMSTR') + +# The target is mali_drm.ko, built from the source in pl111_drm/pl111, via the action makeAction +# mali_drm.ko will be copied to $STATIC_LIB_PATH after being built by the standard Linux +# kernel build system, after which it can be installed to the directory specified if +# "libs_install" is set; this is done by LibTarget. +cmd = drm_env.Command('$STATIC_LIB_PATH/mali_drm.ko', src, [makeAction]) + +# need Module.symvers from drm.ko +#drm_env.Depends('$STATIC_LIB_PATH/pl111_drm.ko', '$STATIC_LIB_PATH/drm.ko') + +# Until we fathom out how the invoke the Linux build system to clean, we can use Clean +# to remove generated files. +patterns = ['*.mod.c', '*.o', '*.ko', '*.a', '.*.cmd', 'modules.order', '.tmp_versions', 'Module.symvers'] +for p in patterns: + Clean(cmd, Glob('#kernel/drivers/gpu/drm/pl111/%s' % p)) + +env.ProgTarget('x11', cmd) + diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..d2bff1fa22d3278842f4ef65312e6d64bd4ba073 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/drm/sconscript @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + +Import('env') + +if env['winsys'] == 'x11': + # pl111_drm isn't released so only try to build it if it's there + if Glob('pl111/sconscript') and (env['platform_config'] == 'vexpress' or env['platform_config'] == 'vexpress_virtex7_40mhz' or env['platform_config'] == 'vexpress_6xvirtex7_10mhz'): + SConscript('pl111/sconscript') + +#SConscript('dummy_drm/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..729dbda13c197516644805eff621bdb7ca9ea39f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/gpu/sconscript @@ -0,0 +1,21 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + + +SConscript('arm/sconscript') + +if Glob('drm/sconscript'): + SConscript('drm/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..dd6a637ccacd5238a89d4eee66cb184ab438d31a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/drivers/sconscript @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +if Glob('base/sconscript'): + SConscript('base/sconscript') + +if Glob('video/sconscript'): + SConscript('video/sconscript') + +SConscript('gpu/sconscript') diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/dma-buf-test-exporter.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/dma-buf-test-exporter.h new file mode 100644 index 0000000000000000000000000000000000000000..db0e93898133043113745593488f85ac68e55cbc --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/dma-buf-test-exporter.h @@ -0,0 +1,78 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + +#ifndef _LINUX_DMA_BUF_TEST_EXPORTER_H_ +#define _LINUX_DMA_BUF_TEST_EXPORTER_H_ + +#include +#include + +#define DMA_BUF_TE_VER_MAJOR 1 +#define DMA_BUF_TE_VER_MINOR 0 +#define DMA_BUF_TE_ENQ 0x642d7465 +#define DMA_BUF_TE_ACK 0x68692100 + +struct dma_buf_te_ioctl_version +{ + int op; /**< Must be set to DMA_BUF_TE_ENQ by client, driver will set it to DMA_BUF_TE_ACK */ + int major; /**< Major version */ + int minor; /**< Minor version */ +}; + +struct dma_buf_te_ioctl_alloc +{ + __u64 size; /* size of buffer to allocate, in pages */ +}; + +struct dma_buf_te_ioctl_status +{ + /* in */ + int fd; /* the dma_buf to query, only dma_buf objects exported by this driver is supported */ + /* out */ + int attached_devices; /* number of devices attached (active 'dma_buf_attach's) */ + int device_mappings; /* number of device mappings (active 'dma_buf_map_attachment's) */ + int cpu_mappings; /* number of cpu mappings (active 'mmap's) */ +}; + +struct dma_buf_te_ioctl_set_failing +{ + /* in */ + int fd; /* the dma_buf to set failure mode for, only dma_buf objects exported by this driver is supported */ + + /* zero = no fail injection, non-zero = inject failure */ + int fail_attach; + int fail_map; + int fail_mmap; +}; + +struct dma_buf_te_ioctl_fill +{ + int fd; + unsigned int value; +}; + +#define DMA_BUF_TE_IOCTL_BASE 'E' +/* Below all returning 0 if successful or -errcode except DMA_BUF_TE_ALLOC which will return fd or -errcode */ +#define DMA_BUF_TE_VERSION _IOR(DMA_BUF_TE_IOCTL_BASE, 0x00, struct dma_buf_te_ioctl_version) +#define DMA_BUF_TE_ALLOC _IOR(DMA_BUF_TE_IOCTL_BASE, 0x01, struct dma_buf_te_ioctl_alloc) +#define DMA_BUF_TE_QUERY _IOR(DMA_BUF_TE_IOCTL_BASE, 0x02, struct dma_buf_te_ioctl_status) +#define DMA_BUF_TE_SET_FAILING _IOW(DMA_BUF_TE_IOCTL_BASE, 0x03, struct dma_buf_te_ioctl_set_failing) +#define DMA_BUF_TE_ALLOC_CONT _IOR(DMA_BUF_TE_IOCTL_BASE, 0x04, struct dma_buf_te_ioctl_alloc) +#define DMA_BUF_TE_FILL _IOR(DMA_BUF_TE_IOCTL_BASE, 0x05, struct dma_buf_te_ioctl_fill) + +#endif /* _LINUX_DMA_BUF_TEST_EXPORTER_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/kds.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/kds.h new file mode 100644 index 0000000000000000000000000000000000000000..0ba994db08e7cc1b279fc27e0676b9eb8f487940 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/kds.h @@ -0,0 +1,173 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _KDS_H_ +#define _KDS_H_ + +#include +#include + +#define KDS_WAIT_BLOCKING (ULONG_MAX) + +struct kds_resource_set; + +typedef void (*kds_callback_fn) (void *callback_parameter, void *callback_extra_parameter); + +struct kds_callback +{ + kds_callback_fn user_cb; /* real cb */ + int direct; /* do direct or queued call? */ + struct workqueue_struct *wq; +}; + +struct kds_link +{ + struct kds_resource_set *parent; + struct list_head link; + unsigned long state; +}; + +struct kds_resource +{ + struct kds_link waiters; +}; + +/* callback API */ + +/* Initialize a callback object. + * + * Typically created per context or per hw resource. + * + * Callbacks can be performed directly if no nested locking can + * happen in the client. + * + * Nested locking can occur when a lock is held during the kds_async_waitall or + * kds_resource_set_release call. If the callback needs to take the same lock + * nested locking will happen. + * + * If nested locking could happen non-direct callbacks can be requested. + * Callbacks will then be called asynchronous to the triggering call. + */ +int kds_callback_init(struct kds_callback *cb, int direct, kds_callback_fn user_cb); + +/* Terminate the use of a callback object. + * + * If the callback object was set up as non-direct + * any pending callbacks will be flushed first. + * Note that to avoid a deadlock the lock callbacks needs + * can't be held when a callback object is terminated. + */ +void kds_callback_term(struct kds_callback *cb); + + +/* resource object API */ + +/* initialize a resource handle for a shared resource */ +void kds_resource_init(struct kds_resource * const resource); + +/* + * Will return 0 on success. + * If the resource is being used or waited -EBUSY is returned. + * The caller should NOT try to terminate a resource that could still have clients. + * After the function returns the resource is no longer known by kds. + */ +int kds_resource_term(struct kds_resource *resource); + +/* Asynchronous wait for a set of resources. + * Callback will be called when all resources are available. + * If all the resources was available the callback will be called before kds_async_waitall returns. + * So one must not hold any locks the callback code-flow can take when calling kds_async_waitall. + * Caller considered to own/use the resources until \a kds_rset_release is called. + * exclusive_access_bitmap is a bitmap where a high bit means exclusive access while a low bit means shared access. + * Use the Linux __set_bit API, where the index of the buffer to control is used as the bit index. + * + * Standard Linux error return value. + */ +int kds_async_waitall( + struct kds_resource_set ** const pprset, + struct kds_callback *cb, + void *callback_parameter, + void *callback_extra_parameter, + int number_resources, + unsigned long *exclusive_access_bitmap, + struct kds_resource **resource_list); + +/* Synchronous wait for a set of resources. + * Function will return when one of these have happened: + * - all resources have been obtained + * - timeout lapsed while waiting + * - a signal was received while waiting + * + * To wait without a timeout, specify KDS_WAIT_BLOCKING for \a jifies_timeout, otherwise + * the timeout in jiffies. A zero timeout attempts to obtain all resources and returns + * immediately with a timeout if all resources could not be obtained. + * + * Caller considered to own/use the resources when the function returns. + * Caller must release the resources using \a kds_rset_release. + * + * Calling this function while holding already locked resources or other locking primitives is dangerous. + * One must if this is needed decide on a lock order of the resources and/or the other locking primitives + * and always take the resources/locking primitives in the specific order. + * + * Use the ERR_PTR framework to decode the return value. + * NULL = time out + * If IS_ERR then PTR_ERR gives: + * ERESTARTSYS = signal received, retry call after signal + * all other values = internal error, lock failed + * Other values = successful wait, now the owner, must call kds_resource_set_release + */ +struct kds_resource_set *kds_waitall( + int number_resources, + unsigned long *exclusive_access_bitmap, + struct kds_resource **resource_list, + unsigned long jifies_timeout); + +/* Release resources after use. + * Caller must handle that other async callbacks will trigger, + * so must avoid holding any locks a callback will take. + * + * The function takes a pointer to your poiner to handle a race + * between a cancelation and a completion. + * + * If the caller can't guarantee that a race can't occur then + * the passed in pointer must be the same in both call paths + * to allow kds to manage the potential race. + */ +void kds_resource_set_release(struct kds_resource_set **pprset); + +/* Release resources after use and wait callbacks to complete. + * Caller must handle that other async callbacks will trigger, + * so must avoid holding any locks a callback will take. + * + * The function takes a pointer to your poiner to handle a race + * between a cancelation and a completion. + * + * If the caller can't guarantee that a race can't occur then + * the passed in pointer must be the same in both call paths + * to allow kds to manage the potential race. + * + * This should be used to cancel waits which are pending on a kds + * resource. + * + * It is a bug to call this from atomic contexts and from within + * a kds callback that now owns the kds_rseource. + */ + +void kds_resource_set_release_sync(struct kds_resource_set **pprset); +#endif /* _KDS_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-common.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-common.h new file mode 100644 index 0000000000000000000000000000000000000000..1deefd84381f1e5d44af83d8c256d7b59810d13d --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-common.h @@ -0,0 +1,252 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file ump-common.h + * + * This file contains some common enum values used both in both the user and kernel space side of UMP. + */ + +#ifndef _UMP_COMMON_H_ +#define _UMP_COMMON_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#define UMP_UINT32_MAX (4294967295U) +#define UMP_UINT64_MAX (18446744073709551615ULL) + +#ifdef __GNUC__ + #define CHECK_RESULT __attribute__((__warn_unused_result__)) + #define INLINE __inline__ +#else + #define CHECK_RESULT + #define INLINE __inline +#endif + +#ifndef STATIC + #define STATIC static +#endif + +/** + * Values to identify major and minor version of UMP + */ +#define UMP_VERSION_MAJOR 2 +#define UMP_VERSION_MINOR 0 + +/** + * Typedef for a secure ID, a system wide identifier for UMP memory buffers. + */ +typedef int32_t ump_secure_id; + +/** + * Value to indicate an invalid secure Id. + */ +#define UMP_INVALID_SECURE_ID ((ump_secure_id)0) + +/** + * UMP error codes. + */ +typedef enum +{ + UMP_OK = 0, /**< indicates success */ + UMP_ERROR = 1 /**< indicates failure */ +} ump_result; + +/** + * Allocation flag bits. + * + * ump_allocate accepts zero or more flags to specify the type of memory to allocate and how to expose it to devices. + * + * For each supported device there are 4 flags to control access permissions and give usage characteristic hints to optimize the allocation/mapping. + * They are; + * @li @a UMP_PROT__RD read permission + * @li @a UMP_PROT__WR write permission + * @li @a UMP_HINT__RD read often + * @li @a UMP_HINT__WR written often + * + * 5 devices are currently supported, with a device being the CPU itself. + * The other 4 devices will be mapped to real devices per SoC design. + * They are just named W,X,Y,Z by UMP as it has no knowledge of their real names/identifiers. + * As an example device W could be a camera device while device Z could be an ARM GPU device, leaving X and Y unused. + * + * 2 additional flags control the allocation; + * @li @a UMP_CONSTRAINT_PHYSICALLY_LINEAR the allocation must be physical linear. Typical for devices without an MMU and no IOMMU to help it. + * @li @a UMP_PROT_SHAREABLE the allocation can be shared with other processes on the system. Without this flag the returned allocation won't be resolvable in other processes. + * + * All UMP allocation are growable unless they're @a UMP_PROT_SHAREABLE. + * The hint bits should be used to indicate the access pattern so the driver can select the most optimal memory type and cache settings based on the what the system supports. + */ +typedef enum +{ + /* Generic helpers */ + UMP_PROT_DEVICE_RD = (1u << 0), + UMP_PROT_DEVICE_WR = (1u << 1), + UMP_HINT_DEVICE_RD = (1u << 2), + UMP_HINT_DEVICE_WR = (1u << 3), + UMP_DEVICE_MASK = 0xF, + UMP_DEVICE_CPU_SHIFT = 0, + UMP_DEVICE_W_SHIFT = 4, + UMP_DEVICE_X_SHIFT = 8, + UMP_DEVICE_Y_SHIFT = 12, + UMP_DEVICE_Z_SHIFT = 16, + + /* CPU protection and hints. */ + UMP_PROT_CPU_RD = (1u << 0), + UMP_PROT_CPU_WR = (1u << 1), + UMP_HINT_CPU_RD = (1u << 2), + UMP_HINT_CPU_WR = (1u << 3), + + /* device W */ + UMP_PROT_W_RD = (1u << 4), + UMP_PROT_W_WR = (1u << 5), + UMP_HINT_W_RD = (1u << 6), + UMP_HINT_W_WR = (1u << 7), + + /* device X */ + UMP_PROT_X_RD = (1u << 8), + UMP_PROT_X_WR = (1u << 9), + UMP_HINT_X_RD = (1u << 10), + UMP_HINT_X_WR = (1u << 11), + + /* device Y */ + UMP_PROT_Y_RD = (1u << 12), + UMP_PROT_Y_WR = (1u << 13), + UMP_HINT_Y_RD = (1u << 14), + UMP_HINT_Y_WR = (1u << 15), + + /* device Z */ + UMP_PROT_Z_RD = (1u << 16), + UMP_PROT_Z_WR = (1u << 17), + UMP_HINT_Z_RD = (1u << 18), + UMP_HINT_Z_WR = (1u << 19), + + /* 20-26 reserved for future use */ + UMPP_ALLOCBITS_UNUSED = (0x7Fu << 20), + /** Allocations marked as @ UMP_CONSTRAINT_UNCACHED won't be mapped as cached by the cpu */ + UMP_CONSTRAINT_UNCACHED = (1u << 27), + /** Require 32-bit physically addressable memory */ + UMP_CONSTRAINT_32BIT_ADDRESSABLE = (1u << 28), + /** For devices without an MMU and with no IOMMU assistance. */ + UMP_CONSTRAINT_PHYSICALLY_LINEAR = (1u << 29), + /** Shareable must be set to allow the allocation to be used by other processes, the default is non-shared */ + UMP_PROT_SHAREABLE = (1u << 30) + /* (1u << 31) should not be used to ensure compiler portability */ +} ump_allocation_bits; + +/** + * ump_allocation_bits combination argument type. + * + * Type used to pass zero or more bits from the @ref ump_allocation_bits enum + */ +typedef uint32_t ump_alloc_flags; + + +/** + * Default allocation flags for UMP v1 compatible allocations. + */ +#define UMP_V1_API_DEFAULT_ALLOCATION_FLAGS UMP_PROT_CPU_RD | UMP_PROT_CPU_WR | \ + UMP_PROT_W_RD | UMP_PROT_W_WR | \ + UMP_PROT_X_RD | UMP_PROT_X_WR | \ + UMP_PROT_Y_RD | UMP_PROT_Y_WR | \ + UMP_PROT_Z_RD | UMP_PROT_Z_WR | \ + UMP_PROT_SHAREABLE | \ + UMP_CONSTRAINT_32BIT_ADDRESSABLE + +/** + * CPU cache sync operations. + * + * Cache synchronization operations to pass to @ref ump_cpu_msync_now + */ +enum +{ + /** + * Cleans any dirty cache lines to main memory, but the data will still be available in the cache. + * After a clean the contents of memory is considered to be "owned" by the device. + * */ + UMP_MSYNC_CLEAN = 1, + + /** Cleans any dirty cache lines to main memory and Ejects all lines from the cache. + * After an clean&invalidate the contents of memory is considered to be "owned" by the CPU. + * Any subsequent access will fetch data from main memory. + * + * @note Due to CPUs doing speculative prefetching a UMP_MSYNC_CLEAN_AND_INVALIDATE must be done before and after interacting with hardware. + * */ + UMP_MSYNC_CLEAN_AND_INVALIDATE + +}; + +typedef uint32_t ump_cpu_msync_op; + +/** + * Memory import types supported. + * If new import types are added they will appear here. + * They must be added before UMPP_EXTERNAL_MEM_COUNT and + * must be assigned an explicit sequantial number. + * + * @li UMP_EXTERNAL_MEM_TYPE_ION - Import an ION allocation + * Takes a int* (pointer to a file descriptor) + * Another ION reference is taken which is released on the final ump_release + */ +enum ump_external_memory_type +{ + UMPP_EXTERNAL_MEM_TYPE_UNUSED = 0, /* reserve type 0 */ + UMP_EXTERNAL_MEM_TYPE_ION = 1, + UMPP_EXTERNAL_MEM_COUNT +}; + +/** @name UMP v1 API + * + *@{ + */ + +/** + * Allocation constraints. + * + * Allocation flags to pass @ref ump_ref_drv_allocate + * + * UMP v1 API only. + */ +typedef enum +{ + /** the allocation is mapped as noncached. */ + UMP_REF_DRV_CONSTRAINT_NONE = 0, + /** not supported. */ + UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1, + /** the allocation is mapped as cached by the cpu. */ + UMP_REF_DRV_CONSTRAINT_USE_CACHE = 4 +} ump_alloc_constraints; + +/* @} */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _UMP_COMMON_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-import.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-import.h new file mode 100644 index 0000000000000000000000000000000000000000..0641111afb6e9211c74ca389cd593154a804165f --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-import.h @@ -0,0 +1,99 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_IMPORT_H_ +#define _UMP_IMPORT_H_ + +#include +#include + +/** + * UMP import module info. + * Contains information about the Linux module providing the import module, + * used to block unloading of the Linux module while imported memory exists. + * Lists the functions implementing the UMP import functions. + */ +struct ump_import_handler +{ + /** + * Linux module of the import handler + */ + struct module * linux_module; + + /** + * UMP session usage begin. + * + * Called when a UMP session first is bound to the handler. + * Typically used to set up any import module specific per-session data. + * The function returns a pointer to this data in the output pointer custom_session_data + * which will be passed to \a session_end and \a import. + * + * Note: custom_session_data must be set to non-NULL if successful. + * If no pointer is needed set it a magic value to validate instead. + * + * @param[out] custom_session_data Pointer to a generic pointer where any data can be stored + * @return 0 on success, error code if the session could not be initiated. + */ + int (*session_begin)(void ** custom_session_data); + + /** + * UMP session usage end. + * + * Called when a UMP session is no longer using the handler. + * Only called if @a session_begin returned OK. + * + * @param[in] custom_session_data The value set by the session_begin handler + */ + void (*session_end)(void * custom_session_data); + + /** + * Import request. + * + * Called when a client has asked to import a resource of the type the import module was installed for. + * Only called if @a session_begin returned OK. + * + * The requested flags must be verified to be valid to apply to the imported memory. + * If not valid return UMP_DD_INVALID_MEMORY_HANDLE. + * If the flags are found to be valid call \a ump_dd_create_from_phys_blocks_64 to create a handle. + * + * @param[in] custom_session_data The value set by the session_begin handler + * @param[in] phandle Pointer to the handle to import + * @param flags The requested UMPv2 flags to assign to the imported handle + * @return UMP_DD_INVALID_MEMORY_HANDLE if the import failed, a valid ump handle on success + */ + ump_dd_handle (*import)(void * custom_session_data, void * phandle, ump_alloc_flags flags); +}; + +/** + * Import module registration. + * Registers a ump_import_handler structure for a memory type. + * @param type Type of the memory to register a handler for + * @param[in] handler Handler strcture to install + * @return 0 on success, a Linux error code on failure + */ +int ump_import_module_register(enum ump_external_memory_type type, struct ump_import_handler * handler); + +/** + * Import module deregistration. + * Uninstalls the handler for the given memory type. + * @param type Type of the memory to unregister the handler for + */ +void ump_import_module_unregister(enum ump_external_memory_type type); + +#endif /* _UMP_IMPORT_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-ioctl.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-ioctl.h new file mode 100644 index 0000000000000000000000000000000000000000..a6219566ebb4febbde77ea32f89da609068ad21a --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump-ioctl.h @@ -0,0 +1,152 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#ifndef _UMP_IOCTL_H_ +#define _UMP_IOCTL_H + +#include + +/* + * The order and size of the members of these have been chosen so the structures look the same in 32-bit and 64-bit builds. + * If any changes are done build the ump_struct_size_checker test for 32-bit and 64-bit targets. Both must compile successfully to commit. + */ + +/** 32/64-bit neutral way to represent pointers */ +typedef union ump_pointer +{ + void * value; /**< client should store their pointers here */ + uint32_t compat_value; /**< 64-bit kernels should fetch value here when handling 32-bit clients */ + uint64_t sizer; /**< Force 64-bit storage for all clients regardless */ +} ump_pointer; + +/** + * UMP allocation request. + * Used when performing ump_allocate + */ +typedef struct ump_k_allocate +{ + uint64_t size; /**< [in] Size in bytes to allocate */ + ump_secure_id secure_id; /**< [out] Secure ID of allocation on success */ + ump_alloc_flags alloc_flags; /**< [in] Flags to use when allocating */ +} ump_k_allocate; + +/** + * UMP size query request. + * Used when performing ump_size_get + */ +typedef struct ump_k_sizequery +{ + uint64_t size; /**< [out] Size of allocation */ + ump_secure_id secure_id; /**< [in] ID of allocation to query the size of */ + uint32_t padding; /* don't remove */ +} ump_k_sizequery; + +/** + * UMP cache synchronization request. + * Used when performing ump_cpu_msync_now + */ +typedef struct ump_k_msync +{ + ump_pointer mapped_ptr; /**< [in] CPU VA to perform cache operation on */ + ump_secure_id secure_id; /**< [in] ID of allocation to perform cache operation on */ + ump_cpu_msync_op cache_operation; /**< [in] Cache operation to perform */ + uint64_t size; /**< [in] Size in bytes of the range to synchronize */ +} ump_k_msync; + +/** + * UMP memory retain request. + * Used when performing ump_retain + */ +typedef struct ump_k_retain +{ + ump_secure_id secure_id; /**< [in] ID of allocation to retain a reference to */ + uint32_t padding; /* don't remove */ +} ump_k_retain; + +/** + * UMP memory release request. + * Used when performing ump_release + */ +typedef struct ump_k_release +{ + ump_secure_id secure_id; /**< [in] ID of allocation to release a reference to */ + uint32_t padding; /* don't remove */ +} ump_k_release; + +typedef struct ump_k_import +{ + ump_pointer phandle; /**< [in] Pointer to handle to import */ + uint32_t type; /**< [in] Type of handle to import */ + ump_alloc_flags alloc_flags; /**< [in] Flags to assign to the imported memory */ + ump_secure_id secure_id; /**< [out] UMP ID representing the imported memory */ + uint32_t padding; /* don't remove */ +} ump_k_import; + +/** + * UMP allocation flags request. + * Used when performing umpp_get_allocation_flags + * + * used only by v1 API + */ +typedef struct ump_k_allocation_flags +{ + ump_secure_id secure_id; /**< [in] Secure ID of allocation on success */ + ump_alloc_flags alloc_flags; /**< [out] Flags to use when allocating */ +} ump_k_allocation_flags; + +#define UMP_CALL_MAX_SIZE 512 +/* + * Ioctl definitions + */ + +/* Use '~' as magic number */ + +#define UMP_IOC_MAGIC '~' + +#define UMP_FUNC_ALLOCATE _IOWR(UMP_IOC_MAGIC, 1, ump_k_allocate) +#define UMP_FUNC_SIZEQUERY _IOWR(UMP_IOC_MAGIC, 2, ump_k_sizequery) +#define UMP_FUNC_MSYNC _IOWR(UMP_IOC_MAGIC, 3, ump_k_msync) +#define UMP_FUNC_RETAIN _IOW(UMP_IOC_MAGIC, 4, ump_k_retain) +#define UMP_FUNC_RELEASE _IOW(UMP_IOC_MAGIC, 5, ump_k_release) +#define UMP_FUNC_ALLOCATION_FLAGS_GET _IOWR(UMP_IOC_MAGIC, 6, ump_k_allocation_flags) +#define UMP_FUNC_IMPORT _IOWR(UMP_IOC_MAGIC, 7, ump_k_import) + +/*max ioctl sequential number*/ +#define UMP_IOC_MAXNR 7 + +/* 15 bits for the UMP ID (allowing 32768 IDs) */ +#define UMP_LINUX_ID_BITS 15 +#define UMP_LINUX_ID_MASK ((1ULL << UMP_LINUX_ID_BITS) - 1ULL) + +/* 64-bit (really 52 bits) encoding: 15 bits for the ID, 37 bits for the offset */ +#define UMP_LINUX_OFFSET_BITS_64 37 +#define UMP_LINUX_OFFSET_MASK_64 ((1ULL << UMP_LINUX_OFFSET_BITS_64)-1) +/* 32-bit encoding: 15 bits for the ID, 17 bits for the offset */ +#define UMP_LINUX_OFFSET_BITS_32 17 +#define UMP_LINUX_OFFSET_MASK_32 ((1ULL << UMP_LINUX_OFFSET_BITS_32)-1) + +#if __SIZEOF_LONG__ == 8 +#define UMP_LINUX_OFFSET_BITS UMP_LINUX_OFFSET_BITS_64 +#define UMP_LINUX_OFFSET_MASK UMP_LINUX_OFFSET_MASK_64 +#else +#define UMP_LINUX_OFFSET_BITS UMP_LINUX_OFFSET_BITS_32 +#define UMP_LINUX_OFFSET_MASK UMP_LINUX_OFFSET_MASK_32 +#endif + +#endif /* _UMP_IOCTL_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump.h b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump.h new file mode 100644 index 0000000000000000000000000000000000000000..423ba852a84109671723f6ddc6f10491dc67b110 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/include/linux/ump.h @@ -0,0 +1,481 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +/** + * @file + * + * This file contains the kernel space part of the UMP API. + * + */ + +#ifndef _UMP_KERNEL_INTERFACE_H_ +#define _UMP_KERNEL_INTERFACE_H_ + +/** + * @addtogroup ump_api + * @{ + */ + +/** @defgroup ump_kernel_space_api UMP Kernel Space API + * @{ */ + +/** + * External representation of a UMP handle in kernel space. + */ +typedef void * ump_dd_handle; + +#ifdef CONFIG_KDS +#include +#endif + +#include + +#define UMP_KERNEL_API_EXPORT + +#if defined(__KERNEL__) +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Value to indicate an invalid UMP memory handle. + */ +#define UMP_DD_INVALID_MEMORY_HANDLE ((ump_dd_handle)0) + +/** + * Struct used to describe a physical block used by UMP memory + */ +typedef struct ump_dd_physical_block_64 +{ + uint64_t addr; /**< The physical address of the block */ + uint64_t size; /**< The length of the block, in bytes, typically page aligned */ +} ump_dd_physical_block_64; + +/** + * Security filter hook. + * + * Each allocation can have a security filter attached to it.@n + * The hook receives + * @li the secure ID + * @li a handle to the allocation + * @li the callback_data argument provided to @ref ump_dd_allocate_64 or @ref ump_dd_create_from_phys_blocks_64 + * + * The hook must return @a MALI_TRUE to indicate that access to the handle is allowed or @n + * @a MALI_FALSE to state that no access is permitted.@n + * This hook is guaranteed to be called in the context of the requesting process/address space. + * + * The arguments provided to the hook are; + * @li the secure ID + * @li handle to the allocation + * @li the callback_data set when registering the hook + * + * Return value; + * @li @a TRUE to permit access + * @li @a FALSE to deny access + */ +typedef bool (*ump_dd_security_filter)(ump_secure_id, ump_dd_handle, void *); + +/** + * Final release notify hook. + * + * Allocations can have a hook attached to them which is called when the last reference to the allocation is released. + * No reference count manipulation is allowed on the provided handle, just property querying (ID get, size get, phys block get). + * This is similar to finalizers in OO languages. + * + * The arguments provided to the hook are; + * * handle to the allocation + * * the callback_data set when registering the hook + */ +typedef void (*ump_dd_final_release_callback)(const ump_dd_handle, void *); + +/** + * Allocate a buffer. + * The lifetime of the allocation is controlled by a reference count. + * The reference count of the returned buffer is set to 1. + * The memory will be freed once the reference count reaches 0. + * Use @ref ump_dd_retain and @ref ump_dd_release to control the reference count. + * @param size Number of bytes to allocate. Will be padded up to a multiple of the page size. + * @param flags Bit-wise OR of zero or more of the allocation flag bits. + * @param[in] filter_func Pointer to a function which will be called when an allocation is required from a + * secure id before the allocation itself is returned to user-space. + * NULL permitted if no need for a callback. + * @param[in] final_release_func Pointer to a function which will be called when the last reference is removed, + * just before the allocation is freed. NULL permitted if no need for a callback. + * @param[in] callback_data An opaque pointer which will be provided to @a filter_func and @a final_release_func + * @return Handle to the new allocation, or @a UMP_DD_INVALID_MEMORY_HANDLE on allocation failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_allocate_64(uint64_t size, ump_alloc_flags flags, ump_dd_security_filter filter_func, ump_dd_final_release_callback final_release_func, void* callback_data); + + +/** + * Allocation bits getter. + * Retrieves the allocation flags used when instantiating the given handle. + * Just a copy of the flag given to @ref ump_dd_allocate_64 and @ref ump_dd_create_from_phys_blocks_64 + * @param mem The handle retrieve the bits for + * @return The allocation bits used to instantiate the allocation + */ +UMP_KERNEL_API_EXPORT ump_alloc_flags ump_dd_allocation_flags_get(const ump_dd_handle mem); + + +/** + * Retrieves the secure ID for the specified UMP memory. + * + * This identifier is unique across the entire system, and uniquely identifies + * the specified UMP memory allocation. This identifier can later be used through the + * @ref ump_dd_from_secure_id or + * @ref ump_from_secure_id + * functions in order to access this UMP memory, for instance from another process (if shared of course). + * Unless the allocation was marked as shared the returned ID will only be resolvable in the same process as did the allocation. + * + * Calling on an @a UMP_DD_INVALID_MEMORY_HANDLE will result in undefined behavior. + * Debug builds will assert on this. + * + * @note There is a user space equivalent function called @ref ump_secure_id_get + * + * @see ump_dd_from_secure_id + * @see ump_from_secure_id + * @see ump_secure_id_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the secure ID for the specified UMP memory. + */ +UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(const ump_dd_handle mem); + +#ifdef CONFIG_KDS +/** + * Retrieve the KDS resource for the specified UMP memory. + * + * The KDS resource should be used to synchronize access to the UMP allocation. + * See the KDS API for how to do that. + * + * @param mem Handle to the UMP memory to query. + * @return Pointer to the KDS resource controlling access to the UMP memory. + */ +UMP_KERNEL_API_EXPORT struct kds_resource * ump_dd_kds_resource_get(const ump_dd_handle mem); +#endif + +/** + * Retrieves a handle to allocated UMP memory. + * + * The usage of UMP memory is reference counted, so this will increment the reference + * count by one for the specified UMP memory. + * Use @ref ump_dd_release when there is no longer any + * use for the retrieved handle. + * + * If called on an non-shared allocation and this is a different process @a UMP_DD_INVALID_MEMORY_HANDLE will be returned. + * + * Calling on an @a UMP_INVALID_SECURE_ID will return @a UMP_DD_INVALID_MEMORY_HANDLE + * + * @note There is a user space equivalent function called @ref ump_from_secure_id + * + * @see ump_dd_release + * @see ump_from_secure_id + * + * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get function. + * + * @return @a UMP_DD_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_from_secure_id(ump_secure_id secure_id); + + +/** + * Retrieves all physical memory block information for specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * This function will return a pointer to an array of @ref ump_dd_physical_block_64 in @a pArray and the number of array elements in @a pCount + * + * Calling on an @a UMP_DD_INVALID_MEMORY_HANDLE results in undefined behavior. + * Debug builds will assert on this. + * + * @param mem Handle to UMP memory. + * @param[out] pCount Pointer to where to store the number of items in the returned array + * @param[out] pArray Pointer to where to store a pointer to the physical blocks array + */ +UMP_KERNEL_API_EXPORT void ump_dd_phys_blocks_get_64(const ump_dd_handle mem, uint64_t * const pCount, const ump_dd_physical_block_64 ** const pArray); + +/** + * Retrieves the actual size of the specified UMP memory. + * + * The size is reported in bytes, and is typically page aligned. + * + * Calling on an @a UMP_DD_INVALID_MEMORY_HANDLE results in undefined behavior. + * Debug builds will assert on this. + * + * @note There is a user space equivalent function called @ref ump_size_get + * + * @see ump_size_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the allocated size of the specified UMP memory, in bytes. + */ +UMP_KERNEL_API_EXPORT uint64_t ump_dd_size_get_64(const ump_dd_handle mem); + + +/** + * Adds an extra reference to the specified UMP memory allocation. + * + * The function @ref ump_dd_release must then be used + * to release each copy of the UMP memory handle. + * + * Calling on an @a UMP_DD_INVALID_MEMORY_HANDLE results in undefined behavior. + * Debug builds will assert on this. + * + * @note You are not required to call @ref ump_dd_retain + * for UMP handles returned from + * @ref ump_dd_from_secure_id, + * because these handles are already reference counted by this function. + * + * @note There is a user space equivalent function called @ref ump_retain + * + * @see ump_retain + * + * @param mem Handle to UMP memory. + * @return 0 indicates success, any other value indicates failure. + */ +UMP_KERNEL_API_EXPORT int ump_dd_retain(ump_dd_handle mem); + + +/** + * Releases a reference from the specified UMP memory. + * + * This function must be called once for every reference to the UMP memory handle. + * When the last reference is released, all resources associated with this UMP memory + * handle are freed. + * + * One can only call ump_release when matched with a successful ump_dd_retain, ump_dd_allocate_64 or ump_dd_from_secure_id + * If called on an @a UMP_DD_INVALID_MEMORY_HANDLE the function will early out. + * + * @note There is a user space equivalent function called @ref ump_release + * + * @see ump_release + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_release(ump_dd_handle mem); + +/** + * Create an ump allocation handle based on externally managed memory. + * Used to wrap an existing allocation as an UMP memory handle. + * Once wrapped the memory acts just like a normal allocation coming from @ref ump_dd_allocate_64. + * The only exception is that the freed physical memory is not put into the pool of free memory, but instead considered returned to the caller once @a final_release_func returns. + * The blocks array will be copied, so no need to hold on to it after this function returns. + * @param[in] blocks Array of @ref ump_dd_physical_block_64 + * @param num_blocks Number of elements in the array pointed to by @a blocks + * @param flags Allocation flags to mark the handle with + * @param[in] filter_func Pointer to a function which will be called when an allocation is required from a secure id before the allocation itself is returned to user-space. + * NULL permitted if no need for a callback. + * @param[in] final_release_func Pointer to a function which will be called when the last reference is removed, just before the allocation is freed. NULL permitted if no need for a callback. + * @param[in] callback_data An opaque pointer which will be provided to @a filter_func and @a final_release_func + * @return Handle to the UMP allocation handle created, or @a UMP_DD_INVALID_MEMORY_HANDLE if no such handle could be created. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_create_from_phys_blocks_64(const ump_dd_physical_block_64 * blocks, uint64_t num_blocks, ump_alloc_flags flags, ump_dd_security_filter filter_func, ump_dd_final_release_callback final_release_func, void* callback_data); + + +/** @name UMP v1 API + * Functions provided to support compatibility with UMP v1 API + * + *@{ + */ + +/** + * Value to indicate an invalid UMP memory handle. + */ +#define UMP_DD_HANDLE_INVALID UMP_DD_INVALID_MEMORY_HANDLE + +/** + * UMP error codes for kernel space. + */ +typedef enum +{ + UMP_DD_SUCCESS, /**< indicates success */ + UMP_DD_INVALID /**< indicates failure */ +} ump_dd_status_code; + + +/** + * Struct used to describe a physical block used by UMP memory + */ +typedef struct ump_dd_physical_block +{ + unsigned long addr; /**< The physical address of the block */ + unsigned long size; /**< The length of the block, typically page aligned */ +} ump_dd_physical_block; + + +/** + * Retrieves a handle to allocated UMP memory. + * + * The usage of UMP memory is reference counted, so this will increment the reference + * count by one for the specified UMP memory. + * Use @ref ump_dd_reference_release "ump_dd_reference_release" when there is no longer any + * use for the retrieved handle. + * + * @note There is a user space equivalent function called @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" + * + * @see ump_dd_reference_release + * @see ump_handle_create_from_secure_id + * + * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function. + * + * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id); + + + +/** + * Create an ump allocation handle based on externally managed memory. + * Used to wrap an existing allocation as an UMP memory handle. + * + * @param[in] blocks Array of @ref ump_dd_physical_block + * @param num_blocks Number of elements in the array pointed to by @a blocks + * + * @return Handle to the UMP allocation handle created, or @a UMP_DD_INVALID_MEMORY_HANDLE if no such handle could be created. + */ +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks); + + +/** + * Retrieves the number of physical blocks used by the specified UMP memory. + * + * This function retrieves the number of @ref ump_dd_physical_block "ump_dd_physical_block" structs needed + * to describe the physical memory layout of the given UMP memory. This can later be used when calling + * the functions @ref ump_dd_phys_blocks_get "ump_dd_phys_blocks_get" and + * @ref ump_dd_phys_block_get "ump_dd_phys_block_get". + * + * @see ump_dd_phys_blocks_get + * @see ump_dd_phys_block_get + * + * @param mem Handle to UMP memory. + * + * @return The number of ump_dd_physical_block structs required to describe the physical memory layout of the specified UMP memory. + */ +UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem); + + +/** + * Retrieves all physical memory block information for specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * + * @note This function will fail if the num_blocks parameter is either to large or to small. + * + * @see ump_dd_phys_block_get + * + * @param mem Handle to UMP memory. + * @param blocks An array of @ref ump_dd_physical_block "ump_dd_physical_block" structs that will receive the physical description. + * @param num_blocks The number of blocks to return in the blocks array. Use the function + * @ref ump_dd_phys_block_count_get "ump_dd_phys_block_count_get" first to determine the number of blocks required. + * + * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block * const blocks, unsigned long num_blocks); + + +/** + * Retrieves the physical memory block information for specified block for the specified UMP memory. + * + * This function can be used by other device drivers in order to create MMU tables. + * + * @note This function will return UMP_DD_INVALID if the specified index is out of range. + * + * @see ump_dd_phys_blocks_get + * + * @param mem Handle to UMP memory. + * @param index Which physical info block to retrieve. + * @param block Pointer to a @ref ump_dd_physical_block "ump_dd_physical_block" struct which will receive the requested information. + * + * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure. + */ +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block * const block); + + +/** + * Retrieves the actual size of the specified UMP memory. + * + * The size is reported in bytes, and is typically page aligned. + * + * @note There is a user space equivalent function called @ref ump_size_get "ump_size_get" + * + * @see ump_size_get + * + * @param mem Handle to UMP memory. + * + * @return Returns the allocated size of the specified UMP memory, in bytes. + */ +UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle mem); + + +/** + * Adds an extra reference to the specified UMP memory. + * + * This function adds an extra reference to the specified UMP memory. This function should + * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_dd_handle + * variable. The function @ref ump_dd_reference_release "ump_dd_reference_release" must then be used + * to release each copy of the UMP memory handle. + * + * @note You are not required to call @ref ump_dd_reference_add "ump_dd_reference_add" + * for UMP handles returned from + * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id", + * because these handles are already reference counted by this function. + * + * @note There is a user space equivalent function called @ref ump_reference_add "ump_reference_add" + * + * @see ump_reference_add + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle mem); + + +/** + * Releases a reference from the specified UMP memory. + * + * This function should be called once for every reference to the UMP memory handle. + * When the last reference is released, all resources associated with this UMP memory + * handle are freed. + * + * @note There is a user space equivalent function called @ref ump_reference_release "ump_reference_release" + * + * @see ump_reference_release + * + * @param mem Handle to UMP memory. + */ +UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle mem); + +/* @} */ + +#ifdef __cplusplus +} +#endif + + +/** @} */ /* end group ump_kernel_space_api */ + +/** @} */ /* end group ump_api */ + +#endif /* _UMP_KERNEL_INTERFACE_H_ */ diff --git a/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/sconscript b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/sconscript new file mode 100755 index 0000000000000000000000000000000000000000..0fa60e2da7cf59ab0a744d383014826b43df5e22 --- /dev/null +++ b/drivers/misc/mediatek/gpu/mt6755/mali-r5p1-EAC/sconscript @@ -0,0 +1,23 @@ +# +# (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU licence. +# +# A copy of the licence is included with the program, and can also be obtained +# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# + + + +Import('env') + +if env['backend'] == 'kernel' and int(env['kernel_modules']) == 1: + SConscript('drivers/sconscript') + + if Glob('tests/sconscript'): + SConscript('tests/sconscript') diff --git a/drivers/misc/mediatek/gud/302a/gud/TlcTui/tui-hal_mt6755.c b/drivers/misc/mediatek/gud/302a/gud/TlcTui/tui-hal_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..242bc88d4fe7024d4495878b47fd08ef5aaefdb0 --- /dev/null +++ b/drivers/misc/mediatek/gud/302a/gud/TlcTui/tui-hal_mt6755.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2014 TRUSTONIC LIMITED + * 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 + * version 2 as published by the Free Software Foundation. + * + * 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 +#include +#include + +#include + +#include "tui_ioctl.h" +#include "dciTui.h" +#include "tlcTui.h" +#include "tui-hal.h" +#include + +#include + + +#define TUI_MEMPOOL_SIZE 0 + +/* Extrac memory size required for TUI driver */ +#define TUI_EXTRA_MEM_SIZE (0x200000) + +struct tui_mempool { + void *va; + unsigned long pa; + size_t size; +}; + +/* for TUI EINT mepping to Security World */ +extern void gt1x_power_reset(void); +extern int mt_eint_set_deint(int eint_num, int irq_num); +extern int mt_eint_clr_deint(int eint_num); +extern int tpd_reregister_from_tui(void); +extern int tpd_enter_tui(void); +extern int tpd_exit_tui(void); +extern int i2c_tui_enable_clock(void); +extern int i2c_tui_disable_clock(void); +extern int secmem_api_alloc(u32 alignment, u32 size, u32 *refcount, u32 *sec_handle, + uint8_t *owner, uint32_t id); +extern int secmem_api_unref(u32 sec_handle, uint8_t *owner, uint32_t id); +extern int tui_region_offline(phys_addr_t *pa, unsigned long *size); +extern int tui_region_online(void); +static struct tui_mempool g_tui_mem_pool; +static int g_tui_secmem_handle; +extern int display_enter_tui(void); +extern int display_exit_tui(void); + + +/* basic implementation of a memory pool for TUI framebuffer. This + * implementation is using kmalloc, for the purpose of demonstration only. + * A real implementation might prefer using more advanced allocator, like ION, + * in order not to exhaust memory available to kmalloc + */ +static bool allocate_tui_memory_pool(struct tui_mempool *pool, size_t size) +{ + bool ret = false; + void *tui_mem_pool = NULL; + + pr_info("%s %s:%d\n", __func__, __FILE__, __LINE__); + if (!size) { + pr_debug("TUI frame buffer: nothing to allocate."); + return true; + } + + tui_mem_pool = kmalloc(size, GFP_KERNEL); + if (!tui_mem_pool) { + pr_debug("ERROR Could not allocate TUI memory pool"); + } else if (ksize(tui_mem_pool) < size) { + pr_debug("ERROR TUI memory pool allocated size is too small."\ + " required=%zd allocated=%zd", + size, ksize(tui_mem_pool)); + kfree(tui_mem_pool); + } else { + pool->va = tui_mem_pool; + pool->pa = virt_to_phys(tui_mem_pool); + pool->size = ksize(tui_mem_pool); + ret = true; + } + return ret; +} + +static void free_tui_memory_pool(struct tui_mempool *pool) +{ + kfree(pool->va); + memset(pool, 0, sizeof(*pool)); +} + +/** + * hal_tui_init() - integrator specific initialization for kernel module + * + * This function is called when the kernel module is initialized, either at + * boot time, if the module is built statically in the kernel, or when the + * kernel is dynamically loaded if the module is built as a dynamic kernel + * module. This function may be used by the integrator, for instance, to get a + * memory pool that will be used to allocate the secure framebuffer and work + * buffer for TUI sessions. + * + * Return: must return 0 on success, or non-zero on error. If the function + * returns an error, the module initialization will fail. + */ +uint32_t hal_tui_init(void) +{ + /* Allocate memory pool for the framebuffer + */ + if (!allocate_tui_memory_pool(&g_tui_mem_pool, TUI_MEMPOOL_SIZE)) + return TUI_DCI_ERR_INTERNAL_ERROR; + + return TUI_DCI_OK; +} + +/** + * hal_tui_exit() - integrator specific exit code for kernel module + * + * This function is called when the kernel module exit. It is called when the + * kernel module is unloaded, for a dynamic kernel module, and never called for + * a module built into the kernel. It can be used to free any resources + * allocated by hal_tui_init(). + */ +void hal_tui_exit(void) +{ + /* delete memory pool if any */ + if (g_tui_mem_pool.va) + free_tui_memory_pool(&g_tui_mem_pool); +} + +/** + * hal_tui_alloc() - allocator for secure framebuffer and working buffer + * @allocbuffer: putput parameter that the allocator fills with the physical + * addresses of the allocated buffers + * @allocsize: size of the buffer to allocate. All the buffer are of the + * same size + * @number: Number to allocate. + * + * This function is called when the module receives a CMD_TUI_SW_OPEN_SESSION + * message from the secure driver. The function must allocate 'number' + * buffer(s) of physically contiguous memory, where the length of each buffer + * is at least 'allocsize' bytes. The physical address of each buffer must be + * stored in the array of structure 'allocbuffer' which is provided as + * arguments. + * + * Physical address of the first buffer must be put in allocate[0].pa , the + * second one on allocbuffer[1].pa, and so on. The function must return 0 on + * success, non-zero on error. For integrations where the framebuffer is not + * allocated by the Normal World, this function should do nothing and return + * success (zero). + */ +uint32_t hal_tui_alloc( + tuiAllocBuffer_t *allocbuffer, size_t allocsize, uint32_t number) +{ + uint32_t ret = TUI_DCI_ERR_INTERNAL_ERROR; + phys_addr_t pa; + u32 sec_handle = 0; + unsigned long size = 0; + + if (!allocbuffer) { + pr_debug("%s(%d): allocbuffer is null\n", __func__, __LINE__); + return TUI_DCI_ERR_INTERNAL_ERROR; + } + + pr_debug("%s(%d): Requested size=0x%zx x %u chunks\n", + __func__, __LINE__, allocsize, number); + + if ((size_t)allocsize == 0) { + pr_debug("%s(%d): Nothing to allocate\n", __func__, __LINE__); + return TUI_DCI_OK; + } + + if (number != 2) { + pr_debug("%s(%d): Unexpected number of buffers requested\n", + __func__, __LINE__); + return TUI_DCI_ERR_INTERNAL_ERROR; + } + + ret = tui_region_offline(&pa, &size); + if (ret) { + pr_err("%s(%d): tui_region_offline failed!\n", + __func__, __LINE__); + return TUI_DCI_ERR_INTERNAL_ERROR; + } + + if (ret == 0) { + g_tui_secmem_handle = pa; + allocbuffer[0].pa = (uint64_t) pa; + allocbuffer[1].pa = (uint64_t) (pa + allocsize); + } else { + return TUI_DCI_ERR_INTERNAL_ERROR; + } + pr_debug("tui pa=0x%x, size=0x%lx", (uint32_t)pa, size); + + pr_debug("tui-hal allocasize=%ld number=%d, extra=%d\n", allocsize, number, TUI_EXTRA_MEM_SIZE); + pr_debug("%s(%d): allocated at %llx\n", __func__, __LINE__, + allocbuffer[0].pa); + pr_debug("%s(%d): allocated at %llx\n", __func__, __LINE__, + allocbuffer[1].pa); + + pr_debug("%s: sec_handle=%x ret=%d", __func__, sec_handle, (int)ret); + return TUI_DCI_OK; + +#if 0 + if ((size_t)(allocsize*number) <= g_tui_mem_pool.size) { + /* requested buffer fits in the memory pool */ + allocbuffer[0].pa = (uint64_t) g_tui_mem_pool.pa; + allocbuffer[1].pa = (uint64_t) (g_tui_mem_pool.pa + + g_tui_mem_pool.size/2); + pr_debug("%s(%d): allocated at %llx\n", __func__, __LINE__, + allocbuffer[0].pa); + pr_debug("%s(%d): allocated at %llx\n", __func__, __LINE__, + allocbuffer[1].pa); + ret = TUI_DCI_OK; + } else { + /* requested buffer is bigger than the memory pool, return an + error */ + pr_debug("%s(%d): Memory pool too small\n", __func__, __LINE__); + ret = TUI_DCI_ERR_INTERNAL_ERROR; + } + + return ret; +#endif +} + +/** + * hal_tui_free() - free memory allocated by hal_tui_alloc() + * + * This function is called at the end of the TUI session, when the TUI module + * receives the CMD_TUI_SW_CLOSE_SESSION message. The function should free the + * buffers allocated by hal_tui_alloc(...). + */ +void hal_tui_free(void) +{ + pr_info("[TUI-HAL] hal_tui_free()\n"); + if (g_tui_secmem_handle) { + //secmem_api_unref(g_tui_secmem_handle, __func__, __LINE__); + tui_region_online(); + g_tui_secmem_handle = 0; + } +} + +/** + * hal_tui_deactivate() - deactivate Normal World display and input + * + * This function should stop the Normal World display and, if necessary, Normal + * World input. It is called when a TUI session is opening, before the Secure + * World takes control of display and input. + * + * Return: must return 0 on success, non-zero otherwise. + */ + +uint32_t hal_tui_deactivate(void) +{ + int ret = TUI_DCI_OK, tmp; + pr_info("[TUI-HAL] hal_tui_deactivate()\n"); + /* Set linux TUI flag */ + trustedui_set_mask(TRUSTEDUI_MODE_TUI_SESSION); + pr_info("TDDP/[TUI-HAL] %s()\n", __func__); + /* + * Stop NWd display here. After this function returns, SWd will take + * control of the display and input. Therefore the NWd should no longer + * access it + * This can be done by calling the fb_blank(FB_BLANK_POWERDOWN) function + * on the appropriate framebuffer device + */ + + tpd_enter_tui(); +#if 0 + enable_clock(MT_CG_PERI_I2C0, "i2c"); + enable_clock(MT_CG_PERI_I2C1, "i2c"); + enable_clock(MT_CG_PERI_I2C2, "i2c"); + enable_clock(MT_CG_PERI_I2C3, "i2c"); + enable_clock(MT_CG_PERI_APDMA, "i2c"); +#endif + i2c_tui_enable_clock(); + + //gt1x_power_reset(); + + tmp = display_enter_tui(); + if(tmp) { + pr_debug("TDDP/[TUI-HAL] %s() failed because display\n", __func__); + ret = TUI_DCI_ERR_OUT_OF_DISPLAY; + } + + + trustedui_set_mask(TRUSTEDUI_MODE_VIDEO_SECURED| + TRUSTEDUI_MODE_INPUT_SECURED); + + pr_info("TDDP/[TUI-HAL] %s()\n", __func__); + + return ret; +} + +/** + * hal_tui_activate() - restore Normal World display and input after a TUI + * session + * + * This function should enable Normal World display and, if necessary, Normal + * World input. It is called after a TUI session, after the Secure World has + * released the display and input. + * + * Return: must return 0 on success, non-zero otherwise. + */ +uint32_t hal_tui_activate(void) +{ + pr_info("[TUI-HAL] hal_tui_activate()\n"); + /* Protect NWd */ + trustedui_clear_mask(TRUSTEDUI_MODE_VIDEO_SECURED| + TRUSTEDUI_MODE_INPUT_SECURED); + + pr_info("TDDP %s()\n", __func__); + + /* + * Restart NWd display here. TUI session has ended, and therefore the + * SWd will no longer use display and input. + * This can be done by calling the fb_blank(FB_BLANK_UNBLANK) function + * on the appropriate framebuffer device + */ + /* Clear linux TUI flag */ + + tpd_exit_tui(); +#if 0 + disable_clock(MT_CG_PERI_I2C0, "i2c"); + disable_clock(MT_CG_PERI_I2C1, "i2c"); + disable_clock(MT_CG_PERI_I2C2, "i2c"); + disable_clock(MT_CG_PERI_I2C3, "i2c"); + disable_clock(MT_CG_PERI_APDMA, "i2c"); +#endif + i2c_tui_disable_clock(); + + display_exit_tui(); + + + trustedui_set_mode(TRUSTEDUI_MODE_OFF); + + return TUI_DCI_OK; +} + +int __weak tui_region_offline(phys_addr_t *pa, unsigned long *size) +{ + return -1; +} + +int __weak tui_region_online(void) +{ + return 0; +} + +int __weak tpd_reregister_from_tui(void) +{ + return 0; +} + +int __weak tpd_enter_tui(void) +{ + return 0; +} + +int __weak tpd_exit_tui(void) +{ + return 0; +} + +int __weak display_enter_tui(void) +{ + return 0; +} + +int __weak display_exit_tui(void) +{ + return 0; +} + +int __weak i2c_tui_enable_clock(void) +{ + return 0; +} + +int __weak i2c_tui_disable_clock(void) +{ + return 0; +} diff --git a/drivers/misc/mediatek/gud/302c/gud/TlcTui/tui-hal_mt6755.c b/drivers/misc/mediatek/gud/302c/gud/TlcTui/tui-hal_mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..3dbce90a677d796aa16786341519c297c5ebe911 --- /dev/null +++ b/drivers/misc/mediatek/gud/302c/gud/TlcTui/tui-hal_mt6755.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2014 TRUSTONIC LIMITED + * 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 + * version 2 as published by the Free Software Foundation. + * + * 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 +#include +#include + +#include + +#include "tui_ioctl.h" +#include "dciTui.h" +#include "tlcTui.h" +#include "tui-hal.h" +#include + +#include + + +#define TUI_MEMPOOL_SIZE 0 + +/* Extrac memory size required for TUI driver */ +#define TUI_EXTRA_MEM_SIZE (0x200000) + +struct tui_mempool { + void *va; + unsigned long pa; + size_t size; +}; + +/* for TUI EINT mepping to Security World */ +extern void gt1x_power_reset(void); +extern int mt_eint_set_deint(int eint_num, int irq_num); +extern int mt_eint_clr_deint(int eint_num); +extern int tpd_reregister_from_tui(void); +extern int tpd_enter_tui(void); +extern int tpd_exit_tui(void); +extern int i2c_tui_enable_clock(void); +extern int i2c_tui_disable_clock(void); +extern int secmem_api_alloc(u32 alignment, u32 size, u32 *refcount, u32 *sec_handle, + uint8_t *owner, uint32_t id); +extern int secmem_api_unref(u32 sec_handle, uint8_t *owner, uint32_t id); +extern int tui_region_offline(phys_addr_t *pa, unsigned long *size); +extern int tui_region_online(void); +static struct tui_mempool g_tui_mem_pool; +static int g_tui_secmem_handle; +extern int display_enter_tui(void); +extern int display_exit_tui(void); + + +/* basic implementation of a memory pool for TUI framebuffer. This + * implementation is using kmalloc, for the purpose of demonstration only. + * A real implementation might prefer using more advanced allocator, like ION, + * in order not to exhaust memory available to kmalloc + */ +static bool allocate_tui_memory_pool(struct tui_mempool *pool, size_t size) +{ + bool ret = false; + void *tui_mem_pool = NULL; + + pr_info("%s %s:%d\n", __func__, __FILE__, __LINE__); + if (!size) { + pr_debug("TUI frame buffer: nothing to allocate."); + return true; + } + + tui_mem_pool = kmalloc(size, GFP_KERNEL); + if (!tui_mem_pool) { + pr_debug("ERROR Could not allocate TUI memory pool"); + } else if (ksize(tui_mem_pool) < size) { + pr_debug("ERROR TUI memory pool allocated size is too small."\ + " required=%zd allocated=%zd", + size, ksize(tui_mem_pool)); + kfree(tui_mem_pool); + } else { + pool->va = tui_mem_pool; + pool->pa = virt_to_phys(tui_mem_pool); + pool->size = ksize(tui_mem_pool); + ret = true; + } + return ret; +} + +static void free_tui_memory_pool(struct tui_mempool *pool) +{ + kfree(pool->va); + memset(pool, 0, sizeof(*pool)); +} + +/** + * hal_tui_init() - integrator specific initialization for kernel module + * + * This function is called when the kernel module is initialized, either at + * boot time, if the module is built statically in the kernel, or when the + * kernel is dynamically loaded if the module is built as a dynamic kernel + * module. This function may be used by the integrator, for instance, to get a + * memory pool that will be used to allocate the secure framebuffer and work + * buffer for TUI sessions. + * + * Return: must return 0 on success, or non-zero on error. If the function + * returns an error, the module initialization will fail. + */ +uint32_t hal_tui_init(void) +{ + /* Allocate memory pool for the framebuffer + */ + if (!allocate_tui_memory_pool(&g_tui_mem_pool, TUI_MEMPOOL_SIZE)) + return TUI_DCI_ERR_INTERNAL_ERROR; + + return TUI_DCI_OK; +} + +/** + * hal_tui_exit() - integrator specific exit code for kernel module + * + * This function is called when the kernel module exit. It is called when the + * kernel module is unloaded, for a dynamic kernel module, and never called for + * a module built into the kernel. It can be used to free any resources + * allocated by hal_tui_init(). + */ +void hal_tui_exit(void) +{ + /* delete memory pool if any */ + if (g_tui_mem_pool.va) + free_tui_memory_pool(&g_tui_mem_pool); +} + +/** + * hal_tui_alloc() - allocator for secure framebuffer and working buffer + * @allocbuffer: putput parameter that the allocator fills with the physical + * addresses of the allocated buffers + * @allocsize: size of the buffer to allocate. All the buffer are of the + * same size + * @number: Number to allocate. + * + * This function is called when the module receives a CMD_TUI_SW_OPEN_SESSION + * message from the secure driver. The function must allocate 'number' + * buffer(s) of physically contiguous memory, where the length of each buffer + * is at least 'allocsize' bytes. The physical address of each buffer must be + * stored in the array of structure 'allocbuffer' which is provided as + * arguments. + * + * Physical address of the first buffer must be put in allocate[0].pa , the + * second one on allocbuffer[1].pa, and so on. The function must return 0 on + * success, non-zero on error. For integrations where the framebuffer is not + * allocated by the Normal World, this function should do nothing and return + * success (zero). + */ +uint32_t hal_tui_alloc( + tuiAllocBuffer_t *allocbuffer, size_t allocsize, uint32_t number) +{ + uint32_t ret = TUI_DCI_ERR_INTERNAL_ERROR; + phys_addr_t pa; + u32 sec_handle = 0; + unsigned long size = 0; + + if (!allocbuffer) { + pr_debug("%s(%d): allocbuffer is null\n", __func__, __LINE__); + return TUI_DCI_ERR_INTERNAL_ERROR; + } + + pr_debug("%s(%d): Requested size=0x%zx x %u chunks\n", + __func__, __LINE__, allocsize, number); + + if ((size_t)allocsize == 0) { + pr_debug("%s(%d): Nothing to allocate\n", __func__, __LINE__); + return TUI_DCI_OK; + } + + if (number != 2) { + pr_debug("%s(%d): Unexpected number of buffers requested\n", + __func__, __LINE__); + return TUI_DCI_ERR_INTERNAL_ERROR; + } + + ret = tui_region_offline(&pa, &size); + if (ret) { + pr_err("%s(%d): tui_region_offline failed!\n", + __func__, __LINE__); + return TUI_DCI_ERR_INTERNAL_ERROR; + } + + if (ret == 0) { + g_tui_secmem_handle = pa; + allocbuffer[0].pa = (uint64_t) pa; + allocbuffer[1].pa = (uint64_t) (pa + allocsize); + } + pr_debug("tui pa=0x%x, size=0x%lx", (uint32_t)pa, size); + + pr_debug("tui-hal allocasize=%zu number=%d, extra=%d\n", allocsize, number, TUI_EXTRA_MEM_SIZE); + pr_debug("%s(%d): allocated at %llx\n", __func__, __LINE__, + allocbuffer[0].pa); + pr_debug("%s(%d): allocated at %llx\n", __func__, __LINE__, + allocbuffer[1].pa); + + pr_debug("%s: sec_handle=%x ret=%d", __func__, sec_handle, (int)ret); + return TUI_DCI_OK; + +#if 0 + if ((size_t)(allocsize*number) <= g_tui_mem_pool.size) { + /* requested buffer fits in the memory pool */ + allocbuffer[0].pa = (uint64_t) g_tui_mem_pool.pa; + allocbuffer[1].pa = (uint64_t) (g_tui_mem_pool.pa + + g_tui_mem_pool.size/2); + pr_debug("%s(%d): allocated at %llx\n", __func__, __LINE__, + allocbuffer[0].pa); + pr_debug("%s(%d): allocated at %llx\n", __func__, __LINE__, + allocbuffer[1].pa); + ret = TUI_DCI_OK; + } else { + /* requested buffer is bigger than the memory pool, return an + error */ + pr_debug("%s(%d): Memory pool too small\n", __func__, __LINE__); + ret = TUI_DCI_ERR_INTERNAL_ERROR; + } + + return ret; +#endif +} + +/** + * hal_tui_free() - free memory allocated by hal_tui_alloc() + * + * This function is called at the end of the TUI session, when the TUI module + * receives the CMD_TUI_SW_CLOSE_SESSION message. The function should free the + * buffers allocated by hal_tui_alloc(...). + */ +void hal_tui_free(void) +{ + pr_info("[TUI-HAL] hal_tui_free()\n"); + if (g_tui_secmem_handle) { + //secmem_api_unref(g_tui_secmem_handle, __func__, __LINE__); + tui_region_online(); + g_tui_secmem_handle = 0; + } +} + +/** + * hal_tui_deactivate() - deactivate Normal World display and input + * + * This function should stop the Normal World display and, if necessary, Normal + * World input. It is called when a TUI session is opening, before the Secure + * World takes control of display and input. + * + * Return: must return 0 on success, non-zero otherwise. + */ + +uint32_t hal_tui_deactivate(void) +{ + int ret = TUI_DCI_OK, tmp; + pr_info("[TUI-HAL] hal_tui_deactivate()\n"); + /* Set linux TUI flag */ + trustedui_set_mask(TRUSTEDUI_MODE_TUI_SESSION); + pr_info("TDDP/[TUI-HAL] %s()\n", __func__); + /* + * Stop NWd display here. After this function returns, SWd will take + * control of the display and input. Therefore the NWd should no longer + * access it + * This can be done by calling the fb_blank(FB_BLANK_POWERDOWN) function + * on the appropriate framebuffer device + */ + + tpd_enter_tui(); +#if 0 + enable_clock(MT_CG_PERI_I2C0, "i2c"); + enable_clock(MT_CG_PERI_I2C1, "i2c"); + enable_clock(MT_CG_PERI_I2C2, "i2c"); + enable_clock(MT_CG_PERI_I2C3, "i2c"); + enable_clock(MT_CG_PERI_APDMA, "i2c"); +#endif + i2c_tui_enable_clock(); + + //gt1x_power_reset(); + + tmp = display_enter_tui(); + if(tmp) { + pr_debug("TDDP/[TUI-HAL] %s() failed because display\n", __func__); + ret = TUI_DCI_ERR_OUT_OF_DISPLAY; + } + + + trustedui_set_mask(TRUSTEDUI_MODE_VIDEO_SECURED| + TRUSTEDUI_MODE_INPUT_SECURED); + + pr_info("TDDP/[TUI-HAL] %s()\n", __func__); + + return ret; +} + +/** + * hal_tui_activate() - restore Normal World display and input after a TUI + * session + * + * This function should enable Normal World display and, if necessary, Normal + * World input. It is called after a TUI session, after the Secure World has + * released the display and input. + * + * Return: must return 0 on success, non-zero otherwise. + */ +uint32_t hal_tui_activate(void) +{ + pr_info("[TUI-HAL] hal_tui_activate()\n"); + /* Protect NWd */ + trustedui_clear_mask(TRUSTEDUI_MODE_VIDEO_SECURED| + TRUSTEDUI_MODE_INPUT_SECURED); + + pr_info("TDDP %s()\n", __func__); + + /* + * Restart NWd display here. TUI session has ended, and therefore the + * SWd will no longer use display and input. + * This can be done by calling the fb_blank(FB_BLANK_UNBLANK) function + * on the appropriate framebuffer device + */ + /* Clear linux TUI flag */ + + tpd_exit_tui(); +#if 0 + disable_clock(MT_CG_PERI_I2C0, "i2c"); + disable_clock(MT_CG_PERI_I2C1, "i2c"); + disable_clock(MT_CG_PERI_I2C2, "i2c"); + disable_clock(MT_CG_PERI_I2C3, "i2c"); + disable_clock(MT_CG_PERI_APDMA, "i2c"); +#endif + i2c_tui_disable_clock(); + + display_exit_tui(); + + + trustedui_set_mode(TRUSTEDUI_MODE_OFF); + + return TUI_DCI_OK; +} + +int __weak tui_region_offline(phys_addr_t *pa, unsigned long *size) +{ + return -1; +} + +int __weak tui_region_online(void) +{ + return 0; +} + +int __weak tpd_reregister_from_tui(void) +{ + return 0; +} + +int __weak tpd_enter_tui(void) +{ + return 0; +} + +int __weak tpd_exit_tui(void) +{ + return 0; +} + +int __weak display_enter_tui(void) +{ + return 0; +} + +int __weak display_exit_tui(void) +{ + return 0; +} + +int __weak i2c_tui_enable_clock(void) +{ + return 0; +} + +int __weak i2c_tui_disable_clock(void) +{ + return 0; +} diff --git a/drivers/misc/mediatek/i2c/mt6755/Makefile b/drivers/misc/mediatek/i2c/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f738863c9cf609c837f9d5703435d0ba46c28a05 --- /dev/null +++ b/drivers/misc/mediatek/i2c/mt6755/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/ + +obj-$(CONFIG_MTK_I2C) := i2c.o i2c_common.o diff --git a/drivers/misc/mediatek/i2c/mt6755/i2c.c b/drivers/misc/mediatek/i2c/mt6755/i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..94203fcbf4bf18b75463d04809486880ea00689b --- /dev/null +++ b/drivers/misc/mediatek/i2c/mt6755/i2c.c @@ -0,0 +1,1733 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#endif +#include +#include +#include +#include +#include +#ifdef CONFIG_MTK_CLKMGR +#include +#endif +#include "mt_i2c.h" +#include + +#define TAG "MT_I2C" + +#define DMA_LOG_LEN 7 +static struct i2c_dma_info g_dma_data[DMA_LOG_LEN]; + +/* extern unsigned int mt_get_bus_freq(void); */ + +typedef int (*pmaster_xfer) (struct i2c_adapter *adap, struct i2c_msg *msgs, int num); + +/* define ONLY_KERNEL */ +/******************************internal API********************************************************/ +void i2c_writel(struct mt_i2c_t *i2c, u8 offset, u16 value) +{ + /* __raw_writew(value, (i2c->base) + (offset)); */ + mt_reg_sync_writel(value, (i2c->base) + (offset)); +} + +u32 i2c_readl(struct mt_i2c_t *i2c, u8 offset) +{ + return __raw_readl((void *)((i2c->base) + (offset))); +} + +/***********************************declare API**************************/ +static void mt_i2c_clock_enable(struct mt_i2c_t *i2c); +static void mt_i2c_clock_disable(struct mt_i2c_t *i2c); + +/***********************************I2C common Param **************************/ +u32 I2C_TIMING_REG_BACKUP[7] = {0}; +u32 I2C_HIGHSP_REG_BACKUP[7] = {0}; + +#ifdef CONFIG_OF +static void __iomem *ap_dma_base; +#endif +/********************************I2C Param only used in kernel*****************/ +/*this field is only for 3d camera*/ +#ifdef I2C_DRIVER_IN_KERNEL +static struct mt_i2c_msg g_msg[2]; +static struct mt_i2c_t *g_i2c[2]; +#define I2C_DRV_NAME "mt-i2c" +#endif +/***********************************i2c debug**********************************/ +/* #define I2C_DEBUG_FS */ +#ifdef I2C_DEBUG_FS +#define PORT_COUNT 7 +#define MESSAGE_COUNT 16 +#define I2C_T_DMA 1 +#define I2C_T_TRANSFERFLOW 2 +#define I2C_T_SPEED 3 +/*7 ports,16 types of message */ +u8 i2c_port[PORT_COUNT][MESSAGE_COUNT]; +#if 0 +#define I2CINFO(type, format, arg...) \ +do { \ + if (type < MESSAGE_COUNT && type >= 0) { \ + if (i2c_port[i2c->id][0] != 0 && (i2c_port[i2c->id][type] != 0 || \ + i2c_port[i2c->id][MESSAGE_COUNT - 1] != 0)) { \ + I2CLOG(format, ##arg); \ + } \ + } \ +} while (0) +#endif +#define I2CINFO(type, format, arg...) I2CLOG(format, ##arg) + +#ifdef I2C_DRIVER_IN_KERNEL +static ssize_t show_config(struct device *dev, struct device_attribute *attr, char *buff) +{ + s32 i = 0; + s32 j = 0; + char *buf = buff; + + for (i = 0; i < PORT_COUNT; i++) { + for (j = 0; j < MESSAGE_COUNT; j++) + i2c_port[i][j] += '0'; + strncpy(buf, (char *)i2c_port[i], MESSAGE_COUNT); + buf += MESSAGE_COUNT; + *buf = '\n'; + buf++; + for (j = 0; j < MESSAGE_COUNT; j++) + i2c_port[i][j] -= '0'; + } + return buf - buff; +} + +static ssize_t set_config(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + s32 port, type, status; + + if (sscanf(buf, "%d %d %d", &port, &type, &status) == 3) { + if (port >= PORT_COUNT || port < 0 || type >= MESSAGE_COUNT || type < 0) { + /*Invalid param */ + I2CERR("i2c debug system: Parameter overflowed!\n"); + } else { + if (status != 0) + i2c_port[port][type] = 1; + else + i2c_port[port][type] = 0; + + I2CLOG("port:%d type:%d status:%s\ni2c debug system: Parameter accepted!\n", + port, type, status ? "on" : "off"); + } + } else { + /*parameter invalid */ + I2CERR("i2c debug system: Parameter invalid!\n"); + } + return count; +} + +static DEVICE_ATTR(debug, S_IRUGO | S_IWUSR, show_config, set_config); +#endif +#else +#define I2CINFO(type, format, arg...) +#endif +/***********************************common API********************************************************/ +#if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) +static int i2c_get_semaphore(struct mt_i2c_t *i2c) +{ + if (i2c->id != 3) + return 0; + + if (cpuhvfs_get_dvfsp_semaphore(SEMA_I2C_DRV) != 0) { + I2CERR("sema time out 2ms\n"); + if (cpuhvfs_get_dvfsp_semaphore(SEMA_I2C_DRV) != 0) { + I2CERR("sema time out 4ms\n"); + BUG_ON(1); + return -EBUSY; + } + } + + return 0; +} + +static int i2c_release_semaphore(struct mt_i2c_t *i2c) +{ + if (i2c->id != 3) + return 0; + + cpuhvfs_release_dvfsp_semaphore(SEMA_I2C_DRV); + + return 0; +} +#endif + +/* +add this function for cast pointer from PA to VA +1 32bit, but open 4G RAM +2 64bit + -32-bit/64-bit is ok + -32-bit with open 4G DRAM config will lose high 32bit ([63:32]) +Note: this function will cast 64 bit address to 32 bit, so, must need to confirm [63:32] of address +is 0. need flag GFP_DMA32 for dma_alloc_coherent() +*/ +char *mt_i2c_bus_to_virt(unsigned long address) +{ + return (char *)address; +} + +/*Set i2c port speed*/ +static s32 i2c_set_speed(struct mt_i2c_t *i2c) +{ + s32 ret = 0; + s32 mode = 0; + u32 khz = 0; + + /* u32 base = i2c->base; */ + u16 step_cnt_div = 0; + u16 sample_cnt_div = 0; + u32 tmp, sclk, hclk = i2c->clk; + u16 max_step_cnt_div = 0; + u32 diff, min_diff = i2c->clk; + u16 sample_div = MAX_SAMPLE_CNT_DIV; + u16 step_div = 0; + /* I2CFUC(); */ + /* I2CLOG("i2c_set_speed=================\n"); */ + /* compare the current speed with the latest mode */ + + if ((i2c->speed == i2c->last_speed) && (i2c->mode == i2c->last_mode)) { + /* I2CLOG( " i2c_set_speed,i2c->speed=%d, i2c->last_speed=%d, + i2c->timing_reg =0x%x\n",i2c->speed, i2c->last_speed,i2c->timing_reg); */ + /* I2CLOG( " i2c_set_speed,i2c->mode=%d, i2c->last_mode=%d, + high_speed_reg =0x%x\n",i2c->mode, i2c->last_mode,i2c->high_speed_reg); */ + ret = 0; + goto end; + } + + mode = i2c->mode; + khz = i2c->speed; + + max_step_cnt_div = (mode == HS_MODE) ? MAX_HS_STEP_CNT_DIV : MAX_STEP_CNT_DIV; + step_div = max_step_cnt_div; + + if ((mode == FS_MODE && khz > MAX_FS_MODE_SPEED) + || (mode == HS_MODE && khz > MAX_HS_MODE_SPEED)) { + I2CERR(" the speed is too fast for this mode.\n"); + I2C_BUG_ON((mode == FS_MODE && khz > MAX_FS_MODE_SPEED) + || (mode == HS_MODE && khz > MAX_HS_MODE_SPEED)); + ret = -EINVAL_I2C; + goto end; + } +/* I2CERR("first:khz=%d,mode=%d sclk=%d,min_diff=%d,max_step_cnt_div=%d\n",khz,mode,sclk,min_diff,max_step_cnt_div); */ + /*Find the best combination */ + for (sample_cnt_div = 1; sample_cnt_div <= MAX_SAMPLE_CNT_DIV; sample_cnt_div++) { + for (step_cnt_div = 1; step_cnt_div <= max_step_cnt_div; step_cnt_div++) { + sclk = (hclk >> 1) / (sample_cnt_div * step_cnt_div); + if (sclk > khz) + continue; + diff = khz - sclk; + if (diff < min_diff) { + min_diff = diff; + sample_div = sample_cnt_div; + step_div = step_cnt_div; + } + } + } + sample_cnt_div = sample_div; + step_cnt_div = step_div; + sclk = hclk / (2 * sample_cnt_div * step_cnt_div); + /* I2CERR("second:sclk=%d khz=%d,i2c->speed=%d hclk=%d sample_cnt_div=%d, + step_cnt_div=%d.\n",sclk,khz,i2c->speed,hclk,sample_cnt_div,step_cnt_div); */ + if (sclk > khz) { + I2CERR("%s mode: unsupported speed (%ldkhz)\n", (mode == HS_MODE) ? "HS" : "ST/FT", + (long int)khz); + I2CLOG + ("i2c->clk=%d,sclk=%d khz=%d,i2c->speed=%d hclk=%d sample_cnt_div=%d,step_cnt_div=%d.\n", + i2c->clk, sclk, khz, i2c->speed, hclk, sample_cnt_div, step_cnt_div); + I2C_BUG_ON(sclk > khz); + ret = -ENOTSUPP_I2C; + goto end; + } + + step_cnt_div--; + sample_cnt_div--; + + /* spin_lock(&i2c->lock); */ + + if (mode == HS_MODE) { + + /*Set the hignspeed timing control register */ + tmp = i2c_readl(i2c, OFFSET_TIMING) & ~((0x7 << 8) | (0x3f << 0)); + tmp = (0 & 0x7) << 8 | (16 & 0x3f) << 0 | tmp; + i2c->timing_reg = tmp; + if (0 == i2c->timing_reg) { + I2CLOG("hs base address 0x%p,tmp =0x%x\n", i2c->base, tmp); + /* aee_kernel_warning(TAG, "@%s():%d,\n", __func__, __LINE__); */ + } + /* i2c_writel(i2c, OFFSET_TIMING, tmp); */ + /* I2C_TIMING_REG_BACKUP[i2c->id]=tmp; */ + + /*Set the hign speed mode register */ + tmp = i2c_readl(i2c, OFFSET_HS) & ~((0x7 << 12) | (0x7 << 8)); + tmp = (sample_cnt_div & 0x7) << 12 | (step_cnt_div & 0x7) << 8 | tmp; + /*Enable the hign speed transaction */ + tmp |= 0x0001; + i2c->high_speed_reg = tmp; + /* I2C_HIGHSP_REG_BACKUP[i2c->id]=tmp; */ + /* i2c_writel(i2c, OFFSET_HS, tmp); */ + } else { + /*Set non-highspeed timing */ + tmp = i2c_readl(i2c, OFFSET_TIMING) & ~((0x7 << 8) | (0x3f << 0)); + tmp = (sample_cnt_div & 0x7) << 8 | (step_cnt_div & 0x3f) << 0 | tmp; + i2c->timing_reg = tmp; + if (0 == i2c->timing_reg) { + I2CLOG + ("n-hs base address 0x%p, tmp=0x%x, sample_cnt_div=0x%x, step_cnt_div=0x%x\n", + i2c->base, tmp, sample_cnt_div, step_cnt_div); + /* aee_kernel_warning(TAG, "@%s():%d,\n", __func__, __LINE__); */ + } + /* I2C_TIMING_REG_BACKUP[i2c->id]=tmp; */ + /* i2c_writel(i2c, OFFSET_TIMING, tmp); */ + /*Disable the high speed transaction */ + /* I2CERR("NOT HS_MODE============================1\n"); */ + tmp = i2c_readl(i2c, OFFSET_HS) & ~(0x0001); + /* I2CERR("NOT HS_MODE============================2\n"); */ + i2c->high_speed_reg = tmp; + /* I2C_HIGHSP_REG_BACKUP[i2c->id]=tmp; */ + /* i2c_writel(i2c, OFFSET_HS, tmp); */ + /* I2CERR("NOT HS_MODE============================3\n"); */ + } + /* spin_unlock(&i2c->lock); */ + I2CINFO(I2C_T_SPEED, " set sclk to %ldkhz(orig:%ldkhz), sample=%d,step=%d\n", sclk, khz, + sample_cnt_div, step_cnt_div); +end: + /* last_id = i2c->id; */ + i2c->last_speed = i2c->speed; + i2c->last_mode = i2c->mode; + return ret; +} + +void _i2c_dump_info(struct mt_i2c_t *i2c) +{ + /* I2CFUC(); */ + I2CLOG("I2C structure:\n" + I2CTAG "Clk=%d,Id=%d,Speed mode=%x,St_rs=%x,Dma_en=%x,Op=%x,Poll_en=%x,Irq_stat=%x\n" + I2CTAG "Trans_len=%x,Trans_num=%x,Trans_auxlen=%x,Data_size=%x,speed=%d\n" + I2CTAG "Trans_stop=%u,Trans_comp=%u,Trans_error=%u\n", + i2c->clk, i2c->id, i2c->mode, i2c->st_rs, i2c->dma_en, i2c->op, i2c->poll_en, + i2c->irq_stat, i2c->trans_data.trans_len, i2c->trans_data.trans_num, + i2c->trans_data.trans_auxlen, i2c->trans_data.data_size, i2c->speed, + atomic_read(&i2c->trans_stop), atomic_read(&i2c->trans_comp), + atomic_read(&i2c->trans_err)); + + I2CLOG("base address 0x%p\n", i2c->base); + I2CLOG("I2C register:\n" + I2CTAG "SLAVE_ADDR=%x,INTR_MASK=%x,INTR_STAT=%x,CONTROL=%x,TRANSFER_LEN=%x\n" + I2CTAG "TRANSAC_LEN=%x,DELAY_LEN=%x,TIMING=%x,START=%x,FIFO_STAT=%x\n" + I2CTAG "IO_CONFIG=%x,HS=%x,DCM_EN=%x,DEBUGSTAT=%x,EXT_CONF=%x,TRANSFER_LEN_AUX=%x\n", + (i2c_readl(i2c, OFFSET_SLAVE_ADDR)), + (i2c_readl(i2c, OFFSET_INTR_MASK)), + (i2c_readl(i2c, OFFSET_INTR_STAT)), + (i2c_readl(i2c, OFFSET_CONTROL)), + (i2c_readl(i2c, OFFSET_TRANSFER_LEN)), + (i2c_readl(i2c, OFFSET_TRANSAC_LEN)), + (i2c_readl(i2c, OFFSET_DELAY_LEN)), + (i2c_readl(i2c, OFFSET_TIMING)), + (i2c_readl(i2c, OFFSET_START)), + (i2c_readl(i2c, OFFSET_FIFO_STAT)), + (i2c_readl(i2c, OFFSET_IO_CONFIG)), + (i2c_readl(i2c, OFFSET_HS)), + (i2c_readl(i2c, OFFSET_DCM_EN)), + (i2c_readl(i2c, OFFSET_DEBUGSTAT)), + (i2c_readl(i2c, OFFSET_EXT_CONF)), (i2c_readl(i2c, OFFSET_TRANSFER_LEN_AUX))); + + I2CLOG("before enable DMA register(0x%p):\n" + I2CTAG "INT_FLAG=%x,INT_EN=%x,EN=%x,RST=%x,\n" + I2CTAG "STOP=%x,FLUSH=%x,CON=%x,TX_MEM_ADDR=%x, RX_MEM_ADDR=%x\n" + I2CTAG "TX_LEN=%x,RX_LEN=%x,INT_BUF_SIZE=%x,DEBUG_STATUS=%x\n" + I2CTAG "ARHP=%x,AWHP=%x\n", + g_dma_data[i2c->id].base, g_dma_data[i2c->id].int_flag, + g_dma_data[i2c->id].int_en, g_dma_data[i2c->id].en, + g_dma_data[i2c->id].rst, g_dma_data[i2c->id].stop, + g_dma_data[i2c->id].flush, g_dma_data[i2c->id].con, + g_dma_data[i2c->id].tx_mem_addr, g_dma_data[i2c->id].rx_mem_addr, + g_dma_data[i2c->id].tx_len, g_dma_data[i2c->id].rx_len, + g_dma_data[i2c->id].int_buf_size, g_dma_data[i2c->id].debug_sta, + g_dma_data[i2c->id].arhp, g_dma_data[i2c->id].awhp); + + if (i2c->dma_en) { + I2CLOG("DMA register(0x%p):\n" + I2CTAG "INT_FLAG=%x,INT_EN=%x,EN=%x,RST=%x,CON=%x\n" + I2CTAG "TX_MEM_ADDR=%x,RX_MEM_ADDR=%x,TX_LEN=%x,RX_LEN=%x\n" + I2CTAG "INT_BUF_SIZE=%x,DEBUG_STATUS=%x,ARHP=%x,AWHP=%x\n" + I2CTAG "STOP=%x,FLUSH=%x\n", + i2c->pdmabase, + (__raw_readl(i2c->pdmabase + OFFSET_INT_FLAG)), + (__raw_readl(i2c->pdmabase + OFFSET_INT_EN)), + (__raw_readl(i2c->pdmabase + OFFSET_EN)), + (__raw_readl(i2c->pdmabase + OFFSET_RST)), + (__raw_readl(i2c->pdmabase + OFFSET_CON)), + (__raw_readl(i2c->pdmabase + OFFSET_TX_MEM_ADDR)), + (__raw_readl(i2c->pdmabase + OFFSET_RX_MEM_ADDR)), + (__raw_readl(i2c->pdmabase + OFFSET_TX_LEN)), + (__raw_readl(i2c->pdmabase + OFFSET_RX_LEN)), + (__raw_readl(i2c->pdmabase + OFFSET_INT_BUF_SIZE)), + (__raw_readl(i2c->pdmabase + OFFSET_DEBUG_STATUS)), + (__raw_readl(i2c->pdmabase + OFFSET_ARHP)), + (__raw_readl(i2c->pdmabase + OFFSET_AWHP)), + (__raw_readl(i2c->pdmabase + OFFSET_STOP)), + (__raw_readl(i2c->pdmabase + OFFSET_FLUSH))); + + I2CLOG("AP_DMA global: 0x8: 0x%x, 0xC: 0x%x, 0x70: 0x%x\n", + __raw_readl(ap_dma_base + 0x08), + __raw_readl(ap_dma_base + 0x0C), + __raw_readl(ap_dma_base + 0x70)); + } + +} + +#define DMA_POLL_THRES 10 +static int dma_busy_wait_ready(struct mt_i2c_t *i2c) +{ + int dma_tmo_poll = DMA_POLL_THRES; + + if (NULL == i2c) { + I2CERR("dma_busy_wait_ready NULL pointer error\n"); + return -1; + } + + /* Wait for EN bit back to 0 */ + while (1 == (__raw_readl(i2c->pdmabase + OFFSET_EN))) { + /* I2CERR("wait dma transfer complete, dma_tmo_poll=%ld\n", dma_tmo_poll); */ + udelay(5); + dma_tmo_poll--; + if (dma_tmo_poll == 0) + return -1; + } + return 0; +} + +static void dma_reset(struct mt_i2c_t *i2c) +{ + int dma_tmo_poll = DMA_POLL_THRES; + + if (NULL == i2c) { + I2CERR("dma_reset NULL pointer error\n"); + return; + } + + /* warm reset DMA to wait for transfer done */ + mt_reg_sync_writel(0x0001, i2c->pdmabase + OFFSET_RST); + + /* Wait for RST bit back to 0 */ + while (1 == (__raw_readl(i2c->pdmabase + OFFSET_RST))) { + /* I2CERR("Wait DMA warm reset: %d\n", dma_tmo_poll); */ + udelay(5); + dma_tmo_poll--; + if (dma_tmo_poll == 0) { + I2CERR("Wait for DMA warm reset error\n"); + return; + } + } +} + +static s32 _i2c_deal_result(struct mt_i2c_t *i2c) +{ +#ifdef I2C_DRIVER_IN_KERNEL + long tmo = i2c->adap.timeout; +#else + long tmo = 1; +#endif + u16 data_size = 0; + u8 *ptr = i2c->msg_buf; + s32 ret = i2c->msg_len; + long tmo_poll = 0xffff; + int dma_err = 0; + /* I2CFUC(); */ + /* addr_reg = i2c->read_flag ? ((i2c->addr << 1) | 0x1) : ((i2c->addr << 1) & ~0x1); */ + + if (i2c->poll_en) { /*master read && poll mode */ + for (;;) { /*check the interrupt status register */ + i2c->irq_stat = i2c_readl(i2c, OFFSET_INTR_STAT); + /* I2CLOG("irq_stat = 0x%x\n", i2c->irq_stat); */ + if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP)) { + atomic_set(&i2c->trans_stop, 1); + spin_lock(&i2c->lock); + /*Clear interrupt status,write 1 clear */ + i2c_writel(i2c, OFFSET_INTR_STAT, + (I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP)); + spin_unlock(&i2c->lock); + break; + } + tmo_poll--; + if (tmo_poll == 0) { + tmo = 0; + break; + } + } + } else { /*Interrupt mode,wait for interrupt wake up */ + tmo = wait_event_timeout(i2c->wait, atomic_read(&i2c->trans_stop), tmo); + } + + /*Save status register status to i2c struct */ +#ifdef I2C_DRIVER_IN_KERNEL + if (i2c->irq_stat & I2C_TRANSAC_COMP) { + atomic_set(&i2c->trans_err, 0); + atomic_set(&i2c->trans_comp, 1); + } + atomic_set(&i2c->trans_err, i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)); +#endif + + /*Check the transfer status */ + if (!(tmo == 0 || atomic_read(&i2c->trans_err))) { + /*Transfer success, we need to get data from fifo */ + if ((!i2c->dma_en) && (i2c->op == I2C_MASTER_RD || i2c->op == I2C_MASTER_WRRD)) { + data_size = (i2c_readl(i2c, OFFSET_FIFO_STAT) >> 4) & 0x000F; + + if (i2c->op == I2C_MASTER_RD && data_size > i2c->msg_len) { + I2CERR("data_size=%d, msg_len=%d\n", data_size, i2c->msg_len); + _i2c_dump_info(i2c); + BUG_ON(data_size > i2c->msg_len); + } + + if (i2c->op == I2C_MASTER_WRRD && data_size > i2c->trans_data.trans_auxlen) { + I2CERR("data_size=%d, msg_len=%d\n", data_size, i2c->msg_len); + _i2c_dump_info(i2c); + BUG_ON(data_size > i2c->trans_data.trans_auxlen); + } + + while (data_size--) { + *ptr = i2c_readl(i2c, OFFSET_DATA_PORT); + /* I2CLOG("addr %x read byte = 0x%x\n", i2c->addr, *ptr); */ + ptr++; + } + } + if (i2c->dma_en) { + dma_err = dma_busy_wait_ready(i2c); + if (dma_err) { + I2CERR("i2c ok wait dma ready err\n"); + _i2c_dump_info(i2c); + dma_reset(i2c); + } + } +#ifdef I2C_DEBUG_FS + _i2c_dump_info(i2c); +#endif + } else { + /*Timeout or ACKERR */ + if (tmo == 0) { + I2CERR("id=%d,addr: %x, transfer timeout\n", i2c->id, i2c->addr); + ret = -ETIMEDOUT_I2C; + } else { + I2CERR("id=%d,addr: %x, transfer error\n", i2c->id, i2c->addr); + ret = -EREMOTEIO_I2C; + } + if (i2c->irq_stat & I2C_HS_NACKERR) + I2CERR("I2C_HS_NACKERR\n"); + if (i2c->irq_stat & I2C_ACKERR) + I2CERR("I2C_ACKERR\n"); + if (i2c->filter_msg == false) /* TEST */ + _i2c_dump_info(i2c); + + spin_lock(&i2c->lock); + /*Reset i2c port */ + i2c_writel(i2c, OFFSET_SOFTRESET, 0x0001); + /*Set slave address */ + i2c_writel(i2c, OFFSET_SLAVE_ADDR, 0x0000); + /*Clear interrupt status */ + i2c_writel(i2c, OFFSET_INTR_STAT, (I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP)); + /*Clear fifo address */ + i2c_writel(i2c, OFFSET_FIFO_ADDR_CLR, 0x0001); + /* clear last mode & last speed */ + i2c->last_mode = -1; + i2c->last_speed = 0; + spin_unlock(&i2c->lock); + if (i2c->dma_en) + dma_reset(i2c); + + } + return ret; +} + +static void record_i2c_dma_info(struct mt_i2c_t *i2c) +{ + if (i2c->id >= DMA_LOG_LEN) { + I2CERR(" no space to record i2c dma log\n"); + return; + } + g_dma_data[i2c->id].base = i2c->pdmabase; + g_dma_data[i2c->id].int_flag = (__raw_readl(i2c->pdmabase + OFFSET_INT_FLAG)); + g_dma_data[i2c->id].int_en = (__raw_readl(i2c->pdmabase + OFFSET_INT_EN)); + g_dma_data[i2c->id].en = (__raw_readl(i2c->pdmabase + OFFSET_EN)); + g_dma_data[i2c->id].rst = (__raw_readl(i2c->pdmabase + OFFSET_RST)); + g_dma_data[i2c->id].stop = (__raw_readl(i2c->pdmabase + OFFSET_STOP)); + g_dma_data[i2c->id].flush = (__raw_readl(i2c->pdmabase + OFFSET_FLUSH)); + g_dma_data[i2c->id].con = (__raw_readl(i2c->pdmabase + OFFSET_CON)); + g_dma_data[i2c->id].tx_mem_addr = (__raw_readl(i2c->pdmabase + OFFSET_TX_MEM_ADDR)); + g_dma_data[i2c->id].rx_mem_addr = (__raw_readl(i2c->pdmabase + OFFSET_RX_MEM_ADDR)); + g_dma_data[i2c->id].tx_len = (__raw_readl(i2c->pdmabase + OFFSET_TX_LEN)); + g_dma_data[i2c->id].rx_len = (__raw_readl(i2c->pdmabase + OFFSET_RX_LEN)); + g_dma_data[i2c->id].int_buf_size = (__raw_readl(i2c->pdmabase + OFFSET_INT_BUF_SIZE)); + g_dma_data[i2c->id].debug_sta = (__raw_readl(i2c->pdmabase + OFFSET_DEBUG_STATUS)); + g_dma_data[i2c->id].arhp = (__raw_readl(i2c->pdmabase + OFFSET_ARHP)); + g_dma_data[i2c->id].awhp = (__raw_readl(i2c->pdmabase + OFFSET_AWHP)); +} + +static void _i2c_write_reg(struct mt_i2c_t *i2c) +{ + u8 *ptr = i2c->msg_buf; + u32 data_size = i2c->trans_data.data_size; + u32 addr_reg = 0; + /* I2CFUC(); */ + + i2c_writel(i2c, OFFSET_CONTROL, i2c->control_reg); + + /*set start condition */ + if (i2c->speed <= 100) + i2c_writel(i2c, OFFSET_EXT_CONF, 0x8001); + else + i2c_writel(i2c, OFFSET_EXT_CONF, 0x1800); + + /* set timing reg */ + i2c_writel(i2c, OFFSET_TIMING, i2c->timing_reg); + i2c_writel(i2c, OFFSET_HS, i2c->high_speed_reg); + + if (0 == i2c->delay_len) + i2c->delay_len = 2; + if (~i2c->control_reg & I2C_CONTROL_RS) { /* bit is set to 1, i.e.,use repeated stop */ + i2c_writel(i2c, OFFSET_DELAY_LEN, i2c->delay_len); + } + + /*Set ioconfig */ + if (i2c->pushpull) + i2c_writel(i2c, OFFSET_IO_CONFIG, 0x0000); + else + i2c_writel(i2c, OFFSET_IO_CONFIG, 0x0003); + + /*Set slave address */ + + addr_reg = i2c->read_flag ? ((i2c->addr << 1) | 0x1) : ((i2c->addr << 1) & ~0x1); + i2c_writel(i2c, OFFSET_SLAVE_ADDR, addr_reg); + /*Clear interrupt status */ + i2c_writel(i2c, OFFSET_INTR_STAT, (I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP)); + /*Clear fifo address */ + i2c_writel(i2c, OFFSET_FIFO_ADDR_CLR, 0x0001); + /*Setup the interrupt mask flag */ + if (i2c->poll_en) { + /* Disable interrupt */ + i2c_writel(i2c, OFFSET_INTR_MASK, i2c_readl(i2c, OFFSET_INTR_MASK) + & ~(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP)); + } else { + /* Enable interrupt */ + i2c_writel(i2c, OFFSET_INTR_MASK, i2c_readl(i2c, OFFSET_INTR_MASK) + | (I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP)); + } + /*Set transfer len */ + i2c_writel(i2c, OFFSET_TRANSFER_LEN, i2c->trans_data.trans_len & 0xFFFF); + i2c_writel(i2c, OFFSET_TRANSFER_LEN_AUX, i2c->trans_data.trans_auxlen & 0xFFFF); + /*Set transaction len */ + i2c_writel(i2c, OFFSET_TRANSAC_LEN, i2c->trans_data.trans_num & 0xFF); + + /*Prepare buffer data to start transfer */ + + if (i2c->dma_en) { + /* Warm reset I2C DMA status */ + dma_reset(i2c); + if (I2C_MASTER_RD == i2c->op) { + mt_reg_sync_writel(0x0000, i2c->pdmabase + OFFSET_INT_FLAG); + mt_reg_sync_writel(0x0001, i2c->pdmabase + OFFSET_CON); + mt_reg_sync_writel((u32) ((long)i2c->msg_buf), + i2c->pdmabase + OFFSET_RX_MEM_ADDR); + mt_reg_sync_writel(i2c->trans_data.data_size, + i2c->pdmabase + OFFSET_RX_LEN); + if (enable_4G()) + mt_reg_sync_writel(0x1, i2c->pdmabase + OFFSET_AWHP); + } else if (I2C_MASTER_WR == i2c->op) { + mt_reg_sync_writel(0x0000, i2c->pdmabase + OFFSET_INT_FLAG); + mt_reg_sync_writel(0x0000, i2c->pdmabase + OFFSET_CON); + mt_reg_sync_writel((u32) ((long)i2c->msg_buf), + i2c->pdmabase + OFFSET_TX_MEM_ADDR); + mt_reg_sync_writel(i2c->trans_data.data_size, + i2c->pdmabase + OFFSET_TX_LEN); + if (enable_4G()) + mt_reg_sync_writel(0x1, i2c->pdmabase + OFFSET_ARHP); + } else { + mt_reg_sync_writel(0x0000, i2c->pdmabase + OFFSET_INT_FLAG); + mt_reg_sync_writel(0x0000, i2c->pdmabase + OFFSET_CON); + mt_reg_sync_writel((u32) ((long)i2c->msg_buf), + i2c->pdmabase + OFFSET_TX_MEM_ADDR); + mt_reg_sync_writel((u32) ((long)i2c->msg_buf), + i2c->pdmabase + OFFSET_RX_MEM_ADDR); + mt_reg_sync_writel(i2c->trans_data.trans_len, + i2c->pdmabase + OFFSET_TX_LEN); + mt_reg_sync_writel(i2c->trans_data.trans_auxlen, + i2c->pdmabase + OFFSET_RX_LEN); + if (enable_4G()) { + mt_reg_sync_writel(0x1, i2c->pdmabase + OFFSET_AWHP); + mt_reg_sync_writel(0x1, i2c->pdmabase + OFFSET_ARHP); + } + } + /* record dma info for debug */ + record_i2c_dma_info(i2c); + + /*All register must be prepared before setting the start bit [SMP] */ + mb(); + mt_reg_sync_writel(0x0001, i2c->pdmabase + OFFSET_EN); + + I2CINFO(I2C_T_DMA, "addr %.2x dma %.2X byte\n", i2c->addr, + i2c->trans_data.data_size); + I2CINFO(I2C_T_DMA, "DMA Register:INT_FLAG:0x%x,CON:0x%x,TX_MEM_ADDR:0x%x", + readl(i2c->pdmabase + OFFSET_INT_FLAG), + readl(i2c->pdmabase + OFFSET_CON), + readl(i2c->pdmabase + OFFSET_TX_MEM_ADDR)); + I2CINFO(I2C_T_DMA, "RX_MEM_ADDR:0x%x,TX_LEN:0x%x,RX_LEN:0x%x,EN:0x%x\n", + readl(i2c->pdmabase + OFFSET_RX_MEM_ADDR), + readl(i2c->pdmabase + OFFSET_TX_LEN), + readl(i2c->pdmabase + OFFSET_RX_LEN), + readl(i2c->pdmabase + OFFSET_EN)); + } else { + /*Set fifo mode data */ + if (I2C_MASTER_RD == i2c->op) { + /*do not need set fifo data */ + } else { /*both write && write_read mode */ + while (data_size--) { + i2c_writel(i2c, OFFSET_DATA_PORT, *ptr); + /* dev_info(i2c->dev, "addr %.2x write byte = 0x%.2X\n", addr, *ptr); */ + ptr++; + } + } + } + /*Set trans_data */ + i2c->trans_data.data_size = data_size; + + if (0x0 == (i2c_readl(i2c, OFFSET_TIMING))) { + /* set timing reg */ + i2c_writel(i2c, OFFSET_TIMING, 0x1410); + aee_kernel_warning(I2CTAG, "@%s():%d,\n", __func__, __LINE__); + /* i2c_writel(i2c, OFFSET_HS, i2c->high_speed_reg); */ + } +} + +static s32 _i2c_get_transfer_len(struct mt_i2c_t *i2c) +{ + s32 ret = I2C_OK; + u16 trans_num = 0; + u16 data_size = 0; + u16 trans_len = 0; + u16 trans_auxlen = 0; + /* I2CFUC(); */ + /*Get Transfer len and transaux len */ + if (false == i2c->dma_en) { /*non-DMA mode */ + if (I2C_MASTER_WRRD != i2c->op) { + trans_len = (i2c->msg_len) & 0xFFFF; + trans_num = (i2c->msg_len >> 16) & 0xFF; + if (0 == trans_num) + trans_num = 1; + trans_auxlen = 0; + data_size = trans_len * trans_num; + + if (!trans_len || !trans_num || data_size > I2C_FIFO_SIZE) { + I2CERR("non-WRRD trans_len is wrong. trans_len=%x, tans_num=%x, trans_auxlen=%x\n", + trans_len, trans_num, trans_auxlen); + I2C_BUG_ON(!trans_len || !trans_num || data_size > I2C_FIFO_SIZE); + ret = -EINVAL_I2C; + } + } else { + trans_len = (i2c->msg_len) & 0xFF; + trans_auxlen = (i2c->msg_len >> 8) & 0xFF; + trans_num = 2; + data_size = trans_len; + if (!trans_len || !trans_auxlen || trans_len > I2C_FIFO_SIZE + || trans_auxlen > I2C_FIFO_SIZE) { + I2CERR("WRRD trans_len is wrong. trans_len=%x, tans_num=%x, trans_auxlen=%x\n", + trans_len, trans_num, trans_auxlen); + I2C_BUG_ON(!trans_len || !trans_auxlen || trans_len > I2C_FIFO_SIZE + || trans_auxlen > I2C_FIFO_SIZE); + ret = -EINVAL_I2C; + } + } + } else { /*DMA mode */ + if (I2C_MASTER_WRRD != i2c->op) { + trans_len = (i2c->msg_len) & 0xFFFF; + trans_num = (i2c->msg_len >> 16) & 0xFF; + if (0 == trans_num) + trans_num = 1; + trans_auxlen = 0; + data_size = trans_len * trans_num; + + if (!trans_len || !trans_num || trans_len > MAX_DMA_TRANS_SIZE + || trans_num > MAX_DMA_TRANS_NUM) { + I2CERR("DMA non-WRRD trans_len is wrong. trans_len=%x, tans_num=%x, trans_auxlen=%x\n", + trans_len, trans_num, trans_auxlen); + I2C_BUG_ON(!trans_len || !trans_num + || trans_len > MAX_DMA_TRANS_SIZE + || trans_num > MAX_DMA_TRANS_NUM); + ret = -EINVAL_I2C; + } + I2CINFO(I2C_T_DMA, + "DMA non-WRRD mode!trans_len=%x, tans_num=%x, trans_auxlen=%x\n", + trans_len, trans_num, trans_auxlen); + } else { + trans_len = (i2c->msg_len) & 0xFF; + trans_auxlen = (i2c->msg_len >> 8) & 0xFF; + trans_num = 2; + data_size = trans_len; + if (!trans_len || !trans_auxlen || trans_len > MAX_DMA_TRANS_SIZE + || trans_auxlen > MAX_DMA_TRANS_NUM) { + I2CERR("DMA WRRD trans_len is wrong. trans_len=%x, tans_num=%x, trans_auxlen=%x\n", + trans_len, trans_num, trans_auxlen); + I2C_BUG_ON(!trans_len || !trans_auxlen + || trans_len > MAX_DMA_TRANS_SIZE + || trans_auxlen > MAX_DMA_TRANS_NUM); + ret = -EINVAL_I2C; + } + I2CINFO(I2C_T_DMA, + "DMA WRRD mode!trans_len=%x, tans_num=%x, trans_auxlen=%x\n", + trans_len, trans_num, trans_auxlen); + } + } + + i2c->trans_data.trans_num = trans_num; + i2c->trans_data.trans_len = trans_len; + i2c->trans_data.data_size = data_size; + i2c->trans_data.trans_auxlen = trans_auxlen; + + return ret; +} + +static s32 _i2c_transfer_interface(struct mt_i2c_t *i2c) +{ + s32 return_value = 0; + s32 ret = 0; + u8 *ptr = i2c->msg_buf; + /* I2CFUC(); */ + + if (i2c->dma_en) { + I2CINFO(I2C_T_DMA, "DMA Transfer mode!\n"); + if (i2c->pdmabase == 0) { + I2CERR(" I2C%d doesnot support DMA mode!\n", i2c->id); + I2C_BUG_ON(i2c->pdmabase == NULL); + ret = -EINVAL_I2C; + goto err; + } + /* DMA mode shouldn't use virtual memory address */ + if (virt_addr_valid(ptr)) { + I2CERR(" DMA mode should use physical buffer address!\n"); + I2C_BUG_ON(virt_addr_valid(ptr)); + ret = -EINVAL_I2C; + goto err; + } + } +#ifdef I2C_DRIVER_IN_KERNEL + atomic_set(&i2c->trans_stop, 0); + atomic_set(&i2c->trans_comp, 0); + atomic_set(&i2c->trans_err, 0); +#endif + i2c->irq_stat = 0; + + return_value = _i2c_get_transfer_len(i2c); + if (return_value < 0) { + I2CERR("_i2c_get_transfer_len fail,return_value=%d\n", return_value); + ret = -EINVAL_I2C; + goto err; + } + /* get clock */ +#ifdef CONFIG_MT_I2C_FPGA_ENABLE + i2c->clk = I2C_CLK_RATE; +#else + /* i2c->clk = mt_get_bus_freq() / I2C_CLK_DIV; */ + i2c->clk = I2C_CLK_RATE; +#endif + + return_value = i2c_set_speed(i2c); + if (return_value < 0) { + I2CERR("i2c_set_speed fail,return_value=%d\n", return_value); + ret = -EINVAL_I2C; + goto err; + } + /*Set Control Register */ + i2c->control_reg = I2C_CONTROL_ACKERR_DET_EN | I2C_CONTROL_CLK_EXT_EN; + if (i2c->dma_en) + i2c->control_reg |= I2C_CONTROL_DMA_EN; + + if (I2C_MASTER_WRRD == i2c->op) + i2c->control_reg |= I2C_CONTROL_DIR_CHANGE; + + if (HS_MODE == i2c->mode + || (i2c->trans_data.trans_num > 1 && I2C_TRANS_REPEATED_START == i2c->st_rs)) { + i2c->control_reg |= I2C_CONTROL_RS; + } + +#if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* Use HW semaphore to protect mt6311 access between AP and SPM */ + if (i2c_get_semaphore(i2c) != 0) + return -EBUSY; +#endif + + spin_lock(&i2c->lock); + _i2c_write_reg(i2c); + + /*All register must be prepared before setting the start bit [SMP] */ + mb(); +#ifdef I2C_DRIVER_IN_KERNEL + /*This is only for 3D CAMERA */ + if (i2c->i2c_3dcamera_flag) { + spin_unlock(&i2c->lock); + if (g_i2c[0] == NULL) + g_i2c[0] = i2c; + else + g_i2c[1] = i2c; + + goto end; + } +#endif + I2CINFO(I2C_T_TRANSFERFLOW, "Before start .....\n"); + + /*Start the transfer */ + i2c_writel(i2c, OFFSET_START, 0x0001); + spin_unlock(&i2c->lock); + ret = _i2c_deal_result(i2c); + +#if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* Use HW semaphore to protect mt6311 access between AP and SPM */ + if (i2c_release_semaphore(i2c) != 0) + ret = -EBUSY; +#endif + + I2CINFO(I2C_T_TRANSFERFLOW, "After i2c transfer .....\n"); +err: +end: + return ret; +} + +/*=========API in kernel=====================================================================*/ +static void _i2c_translate_msg(struct mt_i2c_t *i2c, struct mt_i2c_msg *msg) +{ + /*-------------compatible with 77/75 driver------*/ + if (msg->addr & 0xFF00) + msg->ext_flag |= msg->addr & 0xFF00; + I2CINFO(I2C_T_TRANSFERFLOW, "Before i2c transfer .....\n"); + + i2c->msg_buf = msg->buf; + i2c->msg_len = msg->len; + if (msg->ext_flag & I2C_RS_FLAG) + i2c->st_rs = I2C_TRANS_REPEATED_START; + else + i2c->st_rs = I2C_TRANS_STOP; + + if (msg->ext_flag & I2C_DMA_FLAG) + i2c->dma_en = true; + else + i2c->dma_en = false; + + if (msg->ext_flag & I2C_WR_FLAG) + i2c->op = I2C_MASTER_WRRD; + else { + if (msg->flags & I2C_M_RD) + i2c->op = I2C_MASTER_RD; + else + i2c->op = I2C_MASTER_WR; + } + if (msg->ext_flag & I2C_POLLING_FLAG) + i2c->poll_en = true; + else + i2c->poll_en = false; + + if (msg->ext_flag & I2C_A_FILTER_MSG) + i2c->filter_msg = true; + else + i2c->filter_msg = false; + i2c->delay_len = (msg->timing & 0xff0000) >> 16; + + /* Set device speed,set it before set_control register */ + if (0 == (msg->timing & 0xFFFF)) { + i2c->mode = ST_MODE; + i2c->speed = MAX_ST_MODE_SPEED; + } else { + if (msg->ext_flag & I2C_HS_FLAG) + i2c->mode = HS_MODE; + else + i2c->mode = FS_MODE; + + i2c->speed = msg->timing & 0xFFFF; + } + + /*Set ioconfig */ + if (msg->ext_flag & I2C_PUSHPULL_FLAG) + i2c->pushpull = true; + else + i2c->pushpull = false; + + if (msg->ext_flag & I2C_3DCAMERA_FLAG) + i2c->i2c_3dcamera_flag = true; + else + i2c->i2c_3dcamera_flag = false; + +} + +static s32 mt_i2c_start_xfer(struct mt_i2c_t *i2c, struct mt_i2c_msg *msg) +{ + s32 return_value = 0; + s32 ret = msg->len; + /* start=========================Check param valid===================================== */ + /* I2CLOG(" mt_i2c_start_xfer.\n"); */ + /* get the read/write flag */ + i2c->read_flag = (msg->flags & I2C_M_RD); + i2c->addr = msg->addr; + if (i2c->addr == 0) { + I2CERR(" addr is invalid.\n"); + I2C_BUG_ON(i2c->addr == NULL); + ret = -EINVAL_I2C; + goto err; + } + + if (msg->buf == NULL) { + I2CERR(" data buffer is NULL.\n"); + I2C_BUG_ON(msg->buf == NULL); + ret = -EINVAL_I2C; + goto err; + } + if (g_i2c[0] == i2c || g_i2c[1] == i2c) { + I2CERR("mt-i2c%d: Current I2C Adapter is busy.\n", i2c->id); + ret = -EINVAL_I2C; + goto err; + } + /* start=========================translate msg to mt_i2c=============================== */ + _i2c_translate_msg(i2c, msg); +#ifdef I2C_DRIVER_IN_KERNEL + /*This is only for 3D CAMERA. Save address information for 3d camera */ + if (i2c->i2c_3dcamera_flag) { + if (g_msg[0].buf == NULL) + memcpy((void *)&g_msg[0], msg, sizeof(struct mt_i2c_msg)); + else + memcpy((void *)&g_msg[1], msg, sizeof(struct mt_i2c_msg)); + } +#endif + /* end=========================translate msg to mt_i2c=============================== */ + mt_i2c_clock_enable(i2c); + return_value = _i2c_transfer_interface(i2c); + if (!(msg->ext_flag & I2C_3DCAMERA_FLAG)) + mt_i2c_clock_disable(i2c); + if (return_value < 0) { + ret = -EINVAL_I2C; + goto err; + } +err: + return ret; +} + +static s32 mt_i2c_do_transfer(struct mt_i2c_t *i2c, struct mt_i2c_msg *msgs, s32 num) +{ + s32 ret = 0; + s32 left_num = num; + + while (left_num--) { + ret = mt_i2c_start_xfer(i2c, msgs++); + if (ret < 0) { + if (ret != -EINVAL_I2C) /*We never try again when the param is invalid */ + return -EAGAIN; + else + return -EINVAL_I2C; + } + } + /*the return value is number of executed messages */ + return num; +} + +#ifndef CONFIG_MTK_I2C_EXTENSION +static s32 standard_i2c_start_xfer(struct mt_i2c_t *i2c, struct i2c_msg *msg) +{ + s32 return_value = 0; + s32 ret = msg->len; + u8 *temp_for_dma = 0; + bool dma_need_copy_back = false; + struct mt_i2c_msg msg_ext; + /* struct mt_i2c_data *pdata = dev_get_platdata(i2c->adap.dev.parent); */ + /* start=========================Check param valid===================================== */ + /* I2CLOG(" mt_i2c_start_xfer.\n"); */ + /* merge mt_i2c_msg */ + + msg_ext.addr = msg->addr; + msg_ext.flags = msg->flags; + msg_ext.len = msg->len; + msg_ext.buf = msg->buf; +#ifdef COMPATIBLE_WITH_AOSP + msg_ext.ext_flag = msg->ext_flag; + if (msg->timing <= 0) { + msg_ext.timing = i2c->default_speed; + /* I2CLOG("fwq (%d) default speed=%d......\n",i2c->id,msg_ext.timing); */ + } else { + msg_ext.timing = msg->timing; + /* I2CLOG("fwq (%d) speed=%d......\n",i2c->id,msg_ext.timing); */ + } +#else + msg_ext.ext_flag = 0; + msg_ext.timing = i2c->default_speed; +#endif + /* I2CLOG("fwq (%d) dmaflag=%x......\n",i2c->id,msg->ext_flag); */ +#ifdef COMPATIBLE_WITH_AOSP + if (((msg->ext_flag & 0xffff) & I2C_DMA_FLAG) && (msg->ext_flag >> 16 == 0xdead)) { + /* do nothing */ + /* I2CLOG("fwq (%d)use mtk dma......\n",i2c->id); */ + } else { + /* check if need to use DMA */ + if (msg->len > I2C_FIFO_SIZE) { + /* I2CLOG("fwq copy to dma(%d) len=0x%x......\n",i2c->id,msg_ext.len); */ + /* i2c->dma_en = true; */ + dma_need_copy_back = true; + msg_ext.ext_flag |= I2C_DMA_FLAG; + temp_for_dma = msg_ext.buf; + memcpy(i2c->dma_buf.vaddr, (msg_ext.buf), (msg_ext.len & 0x00FF)); + msg_ext.buf = (u8 *) i2c->dma_buf.paddr; + /* I2CLOG("fwq copy to dma done(%d)......\n",i2c->id); */ + } + } +#else + /* check if need to use DMA */ + if (msg->len > I2C_FIFO_SIZE) { + /* i2c->dma_en = true; */ + dma_need_copy_back = true; + msg_ext.ext_flag |= I2C_DMA_FLAG; + temp_for_dma = msg_ext.buf; + memcpy(i2c->dma_buf.vaddr, (msg_ext.buf), (msg_ext.len & 0x00FF)); + msg_ext.buf = (u8 *) mt_i2c_bus_to_virt(i2c->dma_buf.paddr); + } +#endif + /* get the read/write flag */ + + i2c->read_flag = (msg_ext.flags & I2C_M_RD); + i2c->addr = msg_ext.addr; + + if (i2c->addr == 0) { + I2CERR(" addr is invalid.\n"); + I2C_BUG_ON(i2c->addr == NULL); + ret = -EINVAL_I2C; + goto err; + } + + + if (msg->buf == NULL) { + I2CERR(" data buffer is NULL.\n"); + I2C_BUG_ON(msg->buf == NULL); + ret = -EINVAL_I2C; + goto err; + } + + if (g_i2c[0] == i2c || g_i2c[1] == i2c) { + I2CERR("mt-i2c%d: Current I2C Adapter is busy.\n", i2c->id); + ret = -EINVAL_I2C; + goto err; + } + /* start=========================translate msg to mt_i2c=============================== */ + _i2c_translate_msg(i2c, &msg_ext); + /* end=========================translate msg to mt_i2c=============================== */ + mt_i2c_clock_enable(i2c); + return_value = _i2c_transfer_interface(i2c); + + if (true == dma_need_copy_back) { + /* I2CLOG("fwq from to dma......\n"); */ + memcpy(temp_for_dma, i2c->dma_buf.vaddr, msg->len & 0xFF); + msg->buf = temp_for_dma; + /* I2CLOG("fwq from to dma over......\n"); */ + } + + if (!(msg_ext.ext_flag & I2C_3DCAMERA_FLAG)) + mt_i2c_clock_disable(i2c); + if (return_value < 0) { + ret = -EINVAL_I2C; + goto err; + } +err: + return ret; +} + +static s32 standard_i2c_do_transfer(struct mt_i2c_t *i2c, struct i2c_msg *msgs, s32 num) +{ + s32 ret = 0; + s32 left_num = num; + + while (left_num--) { + ret = standard_i2c_start_xfer(i2c, msgs++); + if (ret < 0) { + if (ret != -EINVAL_I2C) /*We never try again when the param is invalid */ + return -EAGAIN; + else + return -EINVAL_I2C; + } + } + /*the return value is number of executed messages */ + return num; +} + +static s32 standard_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msgs[], s32 num) +{ + s32 ret = 0; + s32 retry; + struct mt_i2c_t *i2c = i2c_get_adapdata(adap); + + mutex_lock(&i2c->mutex); + for (retry = 0; retry < adap->retries; retry++) { + ret = standard_i2c_do_transfer(i2c, msgs, num); + if (ret != -EAGAIN) + break; + if (retry < adap->retries - 1) + udelay(100); + } + mutex_unlock(&i2c->mutex); + + if (ret != -EAGAIN) + return ret; + else + return -EREMOTEIO; +} +#endif + +int mtk_i2c_transfer(struct i2c_adapter *adap, struct mt_i2c_msg msgs[], s32 num) +{ + s32 ret = 0; + s32 retry; + struct mt_i2c_t *i2c = i2c_get_adapdata(adap); + + mutex_lock(&i2c->mutex); + for (retry = 0; retry < adap->retries; retry++) { + ret = mt_i2c_do_transfer(i2c, msgs, num); + if (ret != -EAGAIN) + break; + if (retry < adap->retries - 1) + udelay(100); + } + mutex_unlock(&i2c->mutex); + + if (ret != -EAGAIN) + return ret; + else + return -EREMOTEIO; +} + +int mtk_i2c_master_send(const struct i2c_client *client, + const char *buf, int count, u32 ext_flag, u32 timing) +{ + int ret; + struct i2c_adapter *adap = client->adapter; + struct mt_i2c_msg msg; + + msg.addr = client->addr; + msg.flags = client->flags & I2C_M_TEN; + msg.len = count; + msg.timing = timing; + msg.buf = (char *)buf; + msg.ext_flag = ext_flag; + ret = mtk_i2c_transfer(adap, &msg, 1); + + /* + * If everything went ok (i.e. 1 msg transmitted), return #bytes + * transmitted, else error code. + */ + return (ret == 1) ? count : ret; +} +EXPORT_SYMBOL(mtk_i2c_master_send); + +/** + * i2c_master_recv - issue a single I2C message in master receive mode + * @client: Handle to slave device + * @buf: Where to store data read from slave + * @count: How many bytes to read, must be less than 64k since msg.len is u16 + * @ext_flag: Controller special flags + * + * Returns negative errno, or else the number of bytes read. + */ +int mtk_i2c_master_recv(const struct i2c_client *client, + char *buf, int count, u32 ext_flag, u32 timing) +{ + struct i2c_adapter *adap = client->adapter; + struct mt_i2c_msg msg; + int ret; + + msg.addr = client->addr; + msg.flags = client->flags & I2C_M_TEN; + msg.timing = timing; + msg.flags |= I2C_M_RD; + msg.len = count; + msg.buf = buf; + msg.ext_flag = ext_flag; + ret = mtk_i2c_transfer(adap, &msg, 1); + + /* + * If everything went ok (i.e. 1 msg received), return #bytes received, + * else error code. + */ + return (ret == 1) ? count : ret; +} +EXPORT_SYMBOL(mtk_i2c_master_recv); + +#ifdef I2C_DRIVER_IN_KERNEL +static s32 _i2c_deal_result_3dcamera(struct mt_i2c_t *i2c, struct mt_i2c_msg *msg) +{ + u16 addr = msg->addr; + u16 read = (msg->flags & I2C_M_RD); + + i2c->msg_buf = msg->buf; + i2c->msg_len = msg->len; + i2c->addr = read ? ((addr << 1) | 0x1) : ((addr << 1) & ~0x1); + return _i2c_deal_result(i2c); +} +#endif + +static void mt_i2c_clock_enable(struct mt_i2c_t *i2c) +{ +#if (!defined(CONFIG_MT_I2C_FPGA_ENABLE)) + if (i2c->dma_en) { + I2CINFO(I2C_T_TRANSFERFLOW, "Before dma clock enable .....\n"); +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_APDMA_SW_CG, "i2c"); +#else + clk_prepare_enable(i2c->clk_dma); +#endif + } + I2CINFO(I2C_T_TRANSFERFLOW, "Before i2c clock enable .....\n"); +#ifdef CONFIG_MTK_CLKMGR + enable_clock(i2c->pdn, "i2c"); +#else + clk_prepare_enable(i2c->clk_main); +#endif + I2CINFO(I2C_T_TRANSFERFLOW, "clock enable done.....\n"); +#endif +} + +static void mt_i2c_clock_disable(struct mt_i2c_t *i2c) +{ +#if (!defined(CONFIG_MT_I2C_FPGA_ENABLE)) + if (i2c->dma_en) { + I2CINFO(I2C_T_TRANSFERFLOW, "Before dma clock disable .....\n"); +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_APDMA_SW_CG, "i2c"); +#else + clk_disable_unprepare(i2c->clk_dma); +#endif + } + I2CINFO(I2C_T_TRANSFERFLOW, "Before i2c clock disable .....\n"); +#ifdef CONFIG_MTK_CLKMGR + disable_clock(i2c->pdn, "i2c"); +#else + clk_disable_unprepare(i2c->clk_main); +#endif + I2CINFO(I2C_T_TRANSFERFLOW, "clock disable done.....\n"); +#endif +} + +#ifdef CONFIG_TRUSTONIC_TEE_SUPPORT +int i2c_tui_enable_clock(void) +{ + struct i2c_adapter *adap; + struct mt_i2c_t *i2c; + + adap = i2c_get_adapter(0); + if (!adap) { + I2CERR("Cannot get adapter\n"); + return -1; + } + + i2c = i2c_get_adapdata(adap); + clk_prepare_enable(i2c->clk_main); + clk_prepare_enable(i2c->clk_dma); + + return 0; +} + +int i2c_tui_disable_clock(void) +{ + struct i2c_adapter *adap; + struct mt_i2c_t *i2c; + + adap = i2c_get_adapter(0); + if (!adap) { + I2CERR("Cannot get adapter\n"); + return -1; + } + + i2c = i2c_get_adapdata(adap); + clk_disable_unprepare(i2c->clk_dma); + clk_disable_unprepare(i2c->clk_main); + + return 0; +} +#endif + +static irqreturn_t mt_i2c_irq(s32 irqno, void *dev_id) +{ + struct mt_i2c_t *i2c = (struct mt_i2c_t *) dev_id; + /* u32 base = i2c->base; */ + + I2CINFO(I2C_T_TRANSFERFLOW, "i2c interrupt coming.....\n"); + /* I2CLOG("mt_i2c_irq\n"); */ + /*Clear interrupt mask */ + i2c_writel(i2c, OFFSET_INTR_MASK, + i2c_readl(i2c, + OFFSET_INTR_MASK) & ~(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP)); + /*Save interrupt status */ + i2c->irq_stat = i2c_readl(i2c, OFFSET_INTR_STAT); + /*Clear interrupt status,write 1 clear */ + i2c_writel(i2c, OFFSET_INTR_STAT, (I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP)); + /* dev_info(i2c->dev, "I2C interrupt status 0x%04X\n", i2c->irq_stat); */ + + /*Wake up process */ + atomic_set(&i2c->trans_stop, 1); + wake_up(&i2c->wait); + return IRQ_HANDLED; +} + +/*This function is only for 3d camera*/ + +s32 mt_wait4_i2c_complete(void) +{ + struct mt_i2c_t *i2c0 = g_i2c[0]; + struct mt_i2c_t *i2c1 = g_i2c[1]; + s32 result0, result1; + s32 ret = 0; + + if ((i2c0 == NULL) || (i2c1 == NULL)) { + /*What's wrong? */ + ret = -EINVAL_I2C; + goto end; + } + + result0 = _i2c_deal_result_3dcamera(i2c0, &g_msg[0]); + result1 = _i2c_deal_result_3dcamera(i2c1, &g_msg[1]); + + if (result0 < 0 || result1 < 0) + ret = -EINVAL_I2C; + if (NULL != i2c0) + mt_i2c_clock_disable(i2c0); + if (NULL != i2c1) + mt_i2c_clock_disable(i2c1); + +end: + g_i2c[0] = NULL; + g_i2c[1] = NULL; + + g_msg[0].buf = NULL; + g_msg[1].buf = NULL; + + return ret; +} + +static u32 mt_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm mt_i2c_algorithm = { +#ifdef CONFIG_MTK_I2C_EXTENSION + .master_xfer = (pmaster_xfer)mtk_i2c_transfer, +#else + .master_xfer = standard_i2c_transfer, +#endif + .functionality = mt_i2c_functionality, +}; + +static inline void mt_i2c_init_hw(struct mt_i2c_t *i2c) +{ + i2c_writel(i2c, OFFSET_SOFTRESET, 0x0001); + i2c_writel(i2c, OFFSET_DCM_EN, 0x0); +} + +static void mt_i2c_free(struct mt_i2c_t *i2c) +{ + if (!i2c) + return; + + free_irq(i2c->irqnr, i2c); + i2c_del_adapter(&i2c->adap); + kfree(i2c); +} + +static s32 mt_i2c_probe(struct platform_device *pdev) +{ + int ret, irq = 0; + struct mt_i2c_t *i2c = NULL; + struct resource *res; + + /* Request platform_device IO resource */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) + return -ENODEV; + + /* Request IO memory */ + if (!request_mem_region(res->start, resource_size(res), pdev->name)) + return -ENOMEM; + + i2c = kzalloc(sizeof(struct mt_i2c_t), GFP_KERNEL); + if (NULL == i2c) + return -ENOMEM; + +#ifdef CONFIG_OF + i2c->base = of_iomap(pdev->dev.of_node, 0); + if (!i2c->base) { + I2CERR("I2C iomap failed\n"); + kfree(i2c); + return -ENODEV; + } + + if (of_property_read_u32(pdev->dev.of_node, "cell-index", &pdev->id)) { + I2CERR("I2C get cell-index failed\n"); + kfree(i2c); + return -ENODEV; + } + i2c->id = pdev->id; + + irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (!irq) { + I2CERR("I2C get irq failed\n"); + kfree(i2c); + return -ENODEV; + } + + if (of_property_read_u32(pdev->dev.of_node, "def_speed", &pdev->id)) { + /* I2CERR("I2C get def_speed failed\n"); */ + i2c->default_speed = 100; + } else { + i2c->default_speed = pdev->id; + } +#else + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -ENODEV; + + /* initialize struct mt_i2c_t structure */ + i2c->id = pdev->id; + i2c->base = IO_PHYS_TO_VIRT(res->start); + +#endif + i2c->irqnr = irq; + +#ifdef CONFIG_MTK_CLKMGR + +#if (defined(CONFIG_MT_I2C_FPGA_ENABLE)) + i2c->clk = I2C_CLK_RATE; +#else + /* i2c->clk = mt_get_bus_freq() / I2C_CLK_DIV; */ + i2c->clk = I2C_CLK_RATE; + + switch (i2c->id) { + case 0: + i2c->pdn = MT_CG_I2C0_SW_CG; + break; + case 1: + i2c->pdn = MT_CG_I2C1_SW_CG; + break; + case 2: + i2c->pdn = MT_CG_I2C2_SW_CG; + break; + case 3: + i2c->pdn = MT_CG_I2C3_SW_CG; + break; + case 4: + i2c->pdn = MT_CG_I2C4_SW_CG; + break; + default: + dev_err(&pdev->dev, "Error id %d\n", i2c->id); + break; + } +#endif + +#else + i2c->clk = I2C_CLK_RATE; + /* of_property_read_u32(pdev->dev.of_node, "clock-frequency", &speed_hz); */ + /* of_property_read_u32(pdev->dev.of_node, "clock-div", &clk_src_div); */ + + i2c->clk_main = devm_clk_get(&pdev->dev, "main"); + if (IS_ERR(i2c->clk_main)) { + I2CERR("cannot get main clock, err=%ld\n", PTR_ERR(i2c->clk_main)); + kfree(i2c); + return PTR_ERR(i2c->clk_main); + } + + i2c->clk_dma = devm_clk_get(&pdev->dev, "dma"); + if (IS_ERR(i2c->clk_dma)) { + I2CERR("cannot get dma clock, err=%ld\n", PTR_ERR(i2c->clk_dma)); + kfree(i2c); + return PTR_ERR(i2c->clk_dma); + } +#endif + + i2c->dev = &i2c->adap.dev; + + i2c->adap.dev.parent = &pdev->dev; +#ifdef CONFIG_OF + i2c->adap.dev.of_node = pdev->dev.of_node; +#endif + i2c->adap.nr = i2c->id; + i2c->adap.owner = THIS_MODULE; + i2c->adap.algo = &mt_i2c_algorithm; + i2c->adap.algo_data = NULL; + i2c->adap.timeout = 2 * HZ; /*2s */ + i2c->adap.retries = 1; /*DO NOT TRY */ + /*need GFP_DMA32 flag to confirm DMA alloc PA is 32bit range */ + i2c->dma_buf.vaddr = + dma_alloc_coherent(&pdev->dev, MAX_DMA_TRANS_NUM, + &i2c->dma_buf.paddr, GFP_KERNEL | GFP_DMA32); + + + if (!i2c->dma_buf.vaddr) + I2CLOG("mt-i2c:[Error] Allocate DMA I2C Buffer failed!\n"); + memset(i2c->dma_buf.vaddr, 0, MAX_DMA_TRANS_NUM); + snprintf(i2c->adap.name, sizeof(i2c->adap.name), dev_name(&pdev->dev)); + +#ifdef CONFIG_OF + i2c->pdmabase = DMA_I2C_BASE(i2c->id, ap_dma_base); +#else + i2c->pdmabase = DMA_I2C_BASE_CH(i2c->id); +#endif + + I2CLOG(" id: %d, reg: 0x%p, dma_reg: 0x%p, irq: %d\n", i2c->id, i2c->base, i2c->pdmabase, + i2c->irqnr); + + spin_lock_init(&i2c->lock); + mutex_init(&i2c->mutex); + init_waitqueue_head(&i2c->wait); + + mt_i2c_clock_enable(i2c); + mt_i2c_init_hw(i2c); + mt_i2c_clock_disable(i2c); + + ret = request_irq(i2c->irqnr, mt_i2c_irq, IRQF_TRIGGER_LOW, + dev_name(&pdev->dev), i2c); + + if (ret) { + dev_err(&pdev->dev, "Can Not request I2C IRQ %d\n", i2c->irqnr); + goto free; + } + /* pdata= dev_get_platdata(i2c->adap.dev.parent); */ + I2CLOG("i2c-bus%d speed is %dKhz\n", i2c->id, i2c->default_speed); + + i2c_set_adapdata(&i2c->adap, i2c); + ret = i2c_add_numbered_adapter(&i2c->adap); + if (ret) { + dev_err(&pdev->dev, "failed to add i2c bus to i2c core\n"); + goto free; + } + platform_set_drvdata(pdev, i2c); + +#ifdef I2C_DEBUG_FS + ret = device_create_file(i2c->dev, &dev_attr_debug); + if (ret) + I2CERR("i2c create attr file failed\n"); +#endif + + return ret; + +free: + mt_i2c_free(i2c); + I2CERR("i2c probe fail\n"); + return ret; +} + + +static s32 mt_i2c_remove(struct platform_device *pdev) +{ + struct mt_i2c_t *i2c = platform_get_drvdata(pdev); + + if (i2c) { + platform_set_drvdata(pdev, NULL); + mt_i2c_free(i2c); + } + return 0; +} + +#ifdef CONFIG_PM +static s32 mt_i2c_suspend(struct platform_device *pdev, pm_message_t state) +{ + /* struct struct mt_i2c_t *i2c = platform_get_drvdata(pdev); */ + /* dev_dbg(i2c->dev,"[I2C %d] Suspend!\n", i2c->id); */ + return 0; +} + +static s32 mt_i2c_resume(struct platform_device *pdev) +{ + /* struct struct mt_i2c_t *i2c = platform_get_drvdata(pdev); */ + /* dev_dbg(i2c->dev,"[I2C %d] Resume!\n", i2c->id); */ + return 0; +} +#else +#define mt_i2c_suspend NULL +#define mt_i2c_resume NULL +#endif + +static const struct of_device_id mt_i2c_of_match[] = { + {.compatible = "mediatek,mt6755-i2c",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, mt_i2c_of_match); + +static struct platform_driver mt_i2c_driver = { + .probe = mt_i2c_probe, + .remove = mt_i2c_remove, + .suspend = mt_i2c_suspend, + .resume = mt_i2c_resume, + .driver = { + .name = I2C_DRV_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = mt_i2c_of_match, +#endif + }, +}; + +static s32 __init mt_i2c_init(void) +{ +#ifdef CONFIG_OF + struct device_node *ap_dma_node; + + /* ioremap the AP_DMA base and use offset get the I2C DMA base */ + ap_dma_node = of_find_compatible_node(NULL, NULL, "mediatek,ap_dma"); + if (!ap_dma_node) { + I2CERR("Cannot find AP_DMA node\n"); + return -ENODEV; + } + + ap_dma_base = of_iomap(ap_dma_node, 0); + if (!ap_dma_base) { + I2CERR("AP_DMA iomap failed\n"); + return -ENOMEM; + } +#endif + + return platform_driver_register(&mt_i2c_driver); +} + +static void __exit mt_i2c_exit(void) +{ + platform_driver_unregister(&mt_i2c_driver); +} + +module_init(mt_i2c_init); +module_exit(mt_i2c_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek I2C Bus Driver"); +MODULE_AUTHOR("Infinity Chen "); diff --git a/drivers/misc/mediatek/i2c/mt6755/i2c_common.c b/drivers/misc/mediatek/i2c/mt6755/i2c_common.c new file mode 100644 index 0000000000000000000000000000000000000000..cdc31267ad1f728bd56c6c5994655430629d37a4 --- /dev/null +++ b/drivers/misc/mediatek/i2c/mt6755/i2c_common.c @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include "mt_i2c.h" + +static char data_buffer[256 * 4]; + +static ssize_t show_config(struct device *dev, struct device_attribute *attr, char *buff) +{ + int len = strlen(data_buffer); + + memcpy(buff, data_buffer, len); + I2CLOG("Return Value:%s\n", data_buffer); + return len; +} + +static int pows(int x, int y) +{ + int result = 1; + + while (y--) + result *= x; + return result; +} + +int string2hex(const char *buffer, int cnt) +{ + int c = 0; + char t = 0; + int count = cnt; + + while (count--) { + t = *(buffer + cnt - count - 1); + if (t >= 'A' && t <= 'F') + c += ((t - 'A') + 10) * pows(16, count); + else if (t >= '0' && t <= '9') + c += (t - '0') * pows(16, count); + else + c = -1; + } + return c; +} + +char *get_hexbuffer(char *data_buffer, char *hex_buffer) +{ + char *ptr = data_buffer; + int index = 0; + + while (*ptr && *++ptr) { + *(hex_buffer + index++) = string2hex(ptr - 1, 2); + ptr++; + } + *(hex_buffer + index) = 0; + return hex_buffer; +} + +int i2c_trans_data(int bus_id, int address, char *buf, int count, unsigned int ext_flag, int timing, + int op) +{ + int ret; + + struct i2c_msg msg; + struct i2c_adapter *adap; + + adap = i2c_get_adapter(bus_id); + if (!adap) + return -1; + + msg.addr = address; + switch (op) { + case 1: + msg.flags = I2C_M_RD; + break; + default: + msg.flags = 0; + break; + } + /* msg.flags = ((ext_flag & 0x80000000)?I2C_M_RD:0); */ + msg.len = count; + msg.buf = (char *)buf; +#ifdef CONFIG_MTK_I2C_EXTENSION + msg.timing = timing; + msg.ext_flag = ext_flag; +#endif +/* msg.ext_flag = (ext_flag & 0x7FFF00FF); */ +/* msg.addr |= ext_flag & 0x0000FF00; */ + ret = i2c_transfer(adap, &msg, 1); + + /* If everything went ok (i.e. 1 msg transmitted), return #bytes + transmitted, else error code. */ + i2c_put_adapter(adap); + return (ret == 1) ? count : ret; +} + +int mt_i2c_test(int id, int addr) +{ + int ret = 0; + /* unsigned int flag; */ + /* unsigned char buffer[]={0x55}; */ + /* flag |= 0x80000000; */ + /* ret = i2c_trans_data(id, addr,buffer,1,flag,200); */ + return ret; +} +EXPORT_SYMBOL(mt_i2c_test); + +/* extern struct mt_i2c_t ; */ +static int i2c_test_reg(int bus_id, int val) +{ + int ret = 0; + struct i2c_adapter *adap; + struct mt_i2c_t *i2c; + + adap = i2c_get_adapter(bus_id); + if (!adap) + return -1; + i2c = container_of(adap, struct mt_i2c_t, adap); + I2CLOG("I2C%d base address 0x%p\n", bus_id, i2c->base); + /* write i2c writable register with 0 */ + i2c_writel(i2c, OFFSET_SLAVE_ADDR, val); + i2c_writel(i2c, OFFSET_INTR_MASK, val); + i2c_writel(i2c, OFFSET_INTR_STAT, val); + i2c_writel(i2c, OFFSET_CONTROL, val); + i2c_writel(i2c, OFFSET_TRANSFER_LEN, val); + i2c_writel(i2c, OFFSET_TRANSAC_LEN, val); + i2c_writel(i2c, OFFSET_DELAY_LEN, val); + i2c_writel(i2c, OFFSET_TIMING, val); + i2c_writel(i2c, OFFSET_EXT_CONF, val); + i2c_writel(i2c, OFFSET_IO_CONFIG, val); + i2c_writel(i2c, OFFSET_HS, val); + /* If everything went ok (i.e. 1 msg transmitted), return #bytes + transmitted, else error code. */ + i2c_put_adapter(adap); + return ret; +} + +static int i2c_soft_reset(int bus_id) +{ + int ret = 0; + struct i2c_adapter *adap; + struct mt_i2c_t *i2c; + + adap = i2c_get_adapter(bus_id); + if (!adap) + return -1; + i2c = container_of(adap, struct mt_i2c_t, adap); + I2CLOG("I2C%d base address 0x%p\n", bus_id, i2c->base); + /* write i2c writable register with 0 */ + i2c_writel(i2c, OFFSET_SOFTRESET, 1); + /* If everything went ok (i.e. 1 msg transmitted), return #bytes + transmitted, else error code. */ + i2c_put_adapter(adap); + return ret; +} + +static int i2c_ext_conf_test(int bus_id, int val) +{ + int ret = 0; + struct i2c_adapter *adap; + struct mt_i2c_t *i2c; + + adap = i2c_get_adapter(bus_id); + if (!adap) + return -1; + i2c = container_of(adap, struct mt_i2c_t, adap); + I2CLOG("I2C%d base address 0x%p\n", bus_id, i2c->base); + /* write i2c writable register with 0 */ + i2c_writel(i2c, OFFSET_EXT_CONF, val); + I2CLOG("EXT_CONF 0x%x", i2c_readl(i2c, OFFSET_EXT_CONF)); + /* If everything went ok (i.e. 1 msg transmitted), return #bytes + transmitted, else error code. */ + i2c_put_adapter(adap); + return ret; +} + +static void hex2string(unsigned char *in, unsigned char *out, int length) +{ + unsigned char *ptr = in; + unsigned char *ptrout = out; + unsigned char t; + + while (length--) { + t = (*ptr & 0xF0) >> 4; + if (t < 10) + *ptrout = t + '0'; + else + *ptrout = t + 'A' - 10; + + ptrout++; + + t = (*ptr & 0x0F); + if (t < 10) + *ptrout = t + '0'; + else + *ptrout = t + 'A' - 10; + + ptr++; + ptrout++; + } + *ptrout = 0; +} + +static ssize_t set_config(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + int bus_id; + int address; + int operation; + int trans_mode; + int trans_stop; + int speed_mode; + int pushpull_mode; + int query_mode; + int timing; + int trans_num; + int trans_auxlen; + + int number = 0; + int length = 0; + unsigned int ext_flag = 0; + dma_addr_t dma_addr = 0; + void *vir_addr = NULL; + /* int status; */ + int ret = 0; + unsigned char tmpbuffer[128]; + + I2CLOG("%s\n", buf); + /* if (sscanf(buf, "%d %d %d %d %d %d %d %d %d %d %d %d %s", &bus_id, &address, + * &operation, &trans_mode, &trans_stop, &speed_mode, &pushpull_mode, + * &query_mode, &timing, &trans_num, &trans_auxlen,&dir, data_buffer)) { + */ + if (sscanf(buf, "%d %x %d %d %d %d %d %d %d %d %d %1023s", &bus_id, &address, + &operation, &trans_mode, &trans_stop, &speed_mode, &pushpull_mode, + &query_mode, &timing, &trans_num, &trans_auxlen, data_buffer) == 12) { + if ((address != 0) && (operation <= 2)) { + length = strlen(data_buffer); + if (operation == 0) { + ext_flag |= I2C_WR_FLAG; + number = (trans_auxlen << 8) | (length >> 1); + } else if (operation == 1) { + /* ext_flag |= 0x80000000; */ + number = (trans_num << 16) | (length >> 1); + } else if (operation == 2) { + /* ext_flag &= 0x7FFFFFFF; */ + number = (trans_num << 16) | (length >> 1); + } else { + + I2CERR("invalid operation\n"); + goto err; + } + + if (trans_mode == 0) { + /* default is fifo */ + } else if (trans_mode == 1) { + ext_flag |= I2C_DMA_FLAG; + } else { + + I2CERR("invalid trans_mod fifo/dma\n"); + goto err; + } + + if (trans_stop == 0) { + /* default */ + } else if (trans_stop == 1) { + ext_flag |= I2C_RS_FLAG; + } else { + + I2CERR("invalid trans_stop\n"); + goto err; + } + + if (speed_mode == 0) { + timing = 0; /* ST mode */ + } else if (speed_mode == 1) { + /* ext_flag |= I2C_FS_FLAG;//FS MODE */ + } else if (speed_mode == 2) { + ext_flag |= I2C_HS_FLAG; /* HS mode */ + } else { + I2CERR("invalid speed_mode\n"); + goto err; + } + + if (pushpull_mode == 0) { + /* default */ + } else if (pushpull_mode == 1) { + ext_flag |= I2C_PUSHPULL_FLAG; + } else { + + I2CERR("invalid pushpull mode\n"); + goto err; + } + + if (query_mode == 0) { + /* */ + } else if (query_mode == 1) { + ext_flag |= I2C_POLLING_FLAG; + } else { + + I2CERR("invalid query mode interrupt/polling\n"); + goto err; + } + + if (trans_mode == 1) { /*DMA MODE */ + vir_addr = dma_alloc_coherent(dev, (length >> 1) + 1, &dma_addr, + GFP_KERNEL | GFP_DMA32); + if (vir_addr == NULL) { + + I2CERR("alloc dma memory failed\n"); + goto err; + } + } else { + vir_addr = kzalloc((length >> 1) + 1, GFP_KERNEL); + if (vir_addr == NULL) { + + I2CERR("alloc virtual memory failed\n"); + goto err; + } + } + + get_hexbuffer(data_buffer, vir_addr); + I2CLOG("bus_id:%d,address:%x,count:%x,ext_flag:0x%x,timing:%d\n", + bus_id, address, number, ext_flag, timing); + I2CLOG("data_buffer:%s\n", data_buffer); + + if (trans_mode == 1) { +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + I2CLOG("phys_addr: 0x%llx\n", dma_addr); +#else + I2CLOG("phys_addr: 0x%x\n", dma_addr); +#endif + ret = i2c_trans_data(bus_id, address, (void *)(uintptr_t)dma_addr, + number, ext_flag, timing, operation); + } else { + ret = i2c_trans_data(bus_id, address, vir_addr, number, + ext_flag, timing, operation); + } + + /* dealing */ + + if (ret >= 0) { + if (operation == 1) { + hex2string(vir_addr, tmpbuffer, length >> 1); + snprintf(data_buffer, sizeof(data_buffer), "1 %s", tmpbuffer); + I2CLOG("received data: %s\n", tmpbuffer); + } else if (operation == 0) { + hex2string(vir_addr, tmpbuffer, trans_auxlen); + snprintf(data_buffer, sizeof(data_buffer), "1 %s", tmpbuffer); + I2CLOG("received data: %s\n", tmpbuffer); + } else { + snprintf(data_buffer, sizeof(data_buffer), "1 %s", "00"); + } + I2CLOG("Actual return Value:%d 0x%p\n", ret, vir_addr); + } else if (ret < 0) { + if (ret == -EINVAL) + snprintf(data_buffer, sizeof(data_buffer), "0 %s", "Invalid Parameter"); + else if (ret == -ETIMEDOUT) + snprintf(data_buffer, sizeof(data_buffer), "0 %s", "Transfer Timeout"); + else if (ret == -EREMOTEIO) + snprintf(data_buffer, sizeof(data_buffer), "0 %s", "Ack Error"); + else + snprintf(data_buffer, sizeof(data_buffer), "0 %s", "unknown error"); + I2CLOG("Actual return Value:%d 0x%p\n", ret, vir_addr); + } + + if (trans_mode == 1 && vir_addr != NULL) { + /*DMA MODE */ + dma_free_coherent(dev, length >> 1, vir_addr, dma_addr); + } else { + kfree(vir_addr); + } + /* log for UT test. */ + { + struct i2c_adapter *adap = i2c_get_adapter(bus_id); + struct mt_i2c_t *i2c = i2c_get_adapdata(adap); + + _i2c_dump_info(i2c); + } + } else { + struct i2c_adapter *adap = i2c_get_adapter(bus_id); + struct mt_i2c_t *i2c = i2c_get_adapdata(adap); + + if (operation == 3) { + _i2c_dump_info(i2c); + } else if (operation == 4) { + i2c_test_reg(bus_id, 0); + _i2c_dump_info(i2c); + i2c_test_reg(bus_id, 0xFFFFFFFF); + _i2c_dump_info(i2c); + } else if (operation == 5) { + i2c_ext_conf_test(bus_id, address); + } else if (operation == 9) { + i2c_soft_reset(bus_id); + _i2c_dump_info(i2c); + } else if (operation == 6) { + if (bus_id == 0) { + /* I2C0 PINMUX2 power on */ + /* hwPowerOn(MT65XX_POWER_LDO_VMC1,VOL_DEFAULT,"i2c_pinmux"); */ + /* hwPowerOn(MT65XX_POWER_LDO_VMCH1,VOL_DEFAULT,"i2c_pinmux"); */ + } + + } else if (operation == 7) { + mt_i2c_test(1, 0x50); + } else { + dev_err(dev, "i2c debug system: Parameter invalid!\n"); + } + _i2c_dump_info(i2c); + + } + } else { + /*parameter invalid */ + dev_err(dev, "i2c debug system: Parameter invalid!\n"); + } + + return count; +err: + I2CERR("analyze failed\n"); + return -1; +} + +static DEVICE_ATTR(ut, 0660, show_config, set_config); + +static int i2c_common_probe(struct platform_device *pdev) +{ + int ret = 0; + /* your code here, your should save client in your own way */ + I2CLOG("i2c_common device probe\n"); + ret = device_create_file(&pdev->dev, &dev_attr_ut); + return ret; +} + +static int i2c_common_remove(struct platform_device *pdev) +{ + int ret = 0; + /* your code here */ + device_remove_file(&pdev->dev, &dev_attr_ut); + return ret; +} + +static struct platform_driver i2c_common_driver = { + .driver = { + .name = "mt-i2cd", + .owner = THIS_MODULE, + }, + + .probe = i2c_common_probe, + .remove = i2c_common_remove, +}; + + +/* platform device */ +static struct platform_device i2c_common_device = { + .name = "mt-i2cd", + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +static int __init xxx_init(void) +{ + int err = 0; + + I2CLOG("i2c_common device init\n"); + err = platform_device_register(&i2c_common_device); + if (err) + return err; + + err = platform_driver_register(&i2c_common_driver); + if (err) + platform_device_unregister(&i2c_common_device); + + return err; +} + +static void __exit xxx_exit(void) +{ + platform_driver_unregister(&i2c_common_driver); + platform_device_unregister(&i2c_common_device); +} + +module_init(xxx_init); +module_exit(xxx_exit); + + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek I2C Bus Driver Test Driver"); +MODULE_AUTHOR("Ranran Lu"); diff --git a/drivers/misc/mediatek/i2c/mt6755/mt_i2c.h b/drivers/misc/mediatek/i2c/mt6755/mt_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..ba308f729bbb965e160b9f0d0b36b5cd7c04af62 --- /dev/null +++ b/drivers/misc/mediatek/i2c/mt6755/mt_i2c.h @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_I2C_H__ +#define __MT_I2C_H__ +#include +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif + +#define I2CTAG "[I2C]" +/* #define pr_fmt(fmt) "[I2C]"fmt */ +#define I2CLOG(fmt, arg...) pr_debug(fmt, ##arg) +#define I2CMSG(fmt, arg...) pr_debug(fmt, ##arg) +#define I2CERR(fmt, arg...) pr_err("ERROR,%d: "fmt, __LINE__, ##arg) +#define I2CFUC(fmt, arg...) pr_debug("%s\n", __func__) + +#define I2C_DRV_NAME "mt-i2c" +#define I2C_NR 5 + + +#define I2C_DRIVER_IN_KERNEL +#ifdef I2C_DRIVER_IN_KERNEL + +/* #define I2C_DEBUG */ +#ifdef I2C_DEBUG +#define I2C_BUG_ON(a) BUG_ON(a) +#else +#define I2C_BUG_ON(a) +#endif + +#ifdef CONFIG_MTK_FPGA +#define CONFIG_MT_I2C_FPGA_ENABLE +#endif + +#if (defined(CONFIG_MT_I2C_FPGA_ENABLE)) +#define FPGA_CLOCK 12000 /* FPGA crystal frequency (KHz) */ +#define I2C_CLK_DIV 5 /* frequency divider */ +#define I2C_CLK_RATE (FPGA_CLOCK / I2C_CLK_DIV) /* kHz for FPGA I2C work frequency */ +#else +#define I2C_CLK_DIV 10 /* frequency divider */ +#define I2C_CLK_RATE 13600 +#endif + +#else + +#define I2C_MB() +#define I2C_BUG_ON(a) +#define I2C_M_RD 0x0001 + +#endif + + +#define I2C_OK 0x0000 +#define EAGAIN_I2C 11 /* Try again */ +#define EINVAL_I2C 22 /* Invalid argument */ +#define EOPNOTSUPP_I2C 95 /* Operation not supported on transport endpoint */ +#define ETIMEDOUT_I2C 110 /* Connection timed out */ +#define EREMOTEIO_I2C 121 /* Remote I/O error */ +#define ENOTSUPP_I2C 524 /* Remote I/O error */ +#define I2C_WRITE_FAIL_HS_NACKERR 0xA013 +#define I2C_WRITE_FAIL_ACKERR 0xA014 +#define I2C_WRITE_FAIL_TIMEOUT 0xA015 + +/* enum for different I2C pins */ +enum { + I2C0, + I2C1, + I2C2, + I2C_APPM, + I2C3, +}; + +/******************************************register operation***********************************/ +enum I2C_REGS_OFFSET { + OFFSET_DATA_PORT = 0x0, + OFFSET_SLAVE_ADDR = 0x04, + OFFSET_INTR_MASK = 0x08, + OFFSET_INTR_STAT = 0x0C, + OFFSET_CONTROL = 0x10, + OFFSET_TRANSFER_LEN = 0x14, + OFFSET_TRANSAC_LEN = 0x18, + OFFSET_DELAY_LEN = 0x1C, + OFFSET_TIMING = 0x20, + OFFSET_START = 0x24, + OFFSET_EXT_CONF = 0x28, + OFFSET_FIFO_STAT = 0x30, + OFFSET_FIFO_THRESH = 0x34, + OFFSET_FIFO_ADDR_CLR = 0x38, + OFFSET_IO_CONFIG = 0x40, + OFFSET_RSV_DEBUG = 0x44, + OFFSET_HS = 0x48, + OFFSET_SOFTRESET = 0x50, + OFFSET_DCM_EN = 0x54, + OFFSET_DEBUGSTAT = 0x64, + OFFSET_DEBUGCTRL = 0x68, + OFFSET_TRANSFER_LEN_AUX = 0x6C, +}; + +#define I2C_HS_NACKERR (1 << 2) +#define I2C_ACKERR (1 << 1) +#define I2C_TRANSAC_COMP (1 << 0) + +#define I2C_FIFO_SIZE 8 + +#define MAX_ST_MODE_SPEED 100 /* khz */ +#define MAX_FS_MODE_SPEED 400 /* khz */ +#define MAX_HS_MODE_SPEED 3400 /* khz */ + +#define MAX_DMA_TRANS_SIZE 65532 /* Max(65535) aligned to 4 bytes = 65532 */ +#define MAX_DMA_TRANS_NUM 256 + +#define MAX_SAMPLE_CNT_DIV 8 +#define MAX_STEP_CNT_DIV 64 +#define MAX_HS_STEP_CNT_DIV 8 + +#define DMA_ADDRESS_HIGH (0xC0000000) + +/* refer to AP_DMA register address */ +#define DMA_I2C_BASE_CH(id) (AP_DMA_BASE + 0x100 + (0x80 * (id))) +#define DMA_I2C_BASE(id, base) ((base) + 0x100 + (0x80 * (id))) + +enum DMA_REGS_OFFSET { + OFFSET_INT_FLAG = 0x0, + OFFSET_INT_EN = 0x04, + OFFSET_EN = 0x08, + OFFSET_RST = 0x0C, + OFFSET_STOP = 0x10, + OFFSET_FLUSH = 0x14, + OFFSET_CON = 0x18, + OFFSET_TX_MEM_ADDR = 0x1C, + OFFSET_RX_MEM_ADDR = 0x20, + OFFSET_TX_LEN = 0x24, + OFFSET_RX_LEN = 0x28, + OFFSET_INT_BUF_SIZE = 0x38, + OFFSET_DEBUG_STATUS = 0x50, + OFFSET_ARHP = 0x54, + OFFSET_AWHP = 0x58, +}; + +struct i2c_dma_info { + void __iomem *base; + unsigned int int_flag; + unsigned int int_en; + unsigned int en; + unsigned int rst; + unsigned int stop; + unsigned int flush; + unsigned int con; + unsigned int tx_mem_addr; + unsigned int rx_mem_addr; + unsigned int tx_len; + unsigned int rx_len; + unsigned int int_buf_size; + unsigned int debug_sta; + unsigned int arhp; + unsigned int awhp; +}; + +enum i2c_trans_st_rs { + I2C_TRANS_STOP = 0, + I2C_TRANS_REPEATED_START, +}; + +enum i2c_speed_mode { + ST_MODE, + FS_MODE, + HS_MODE, +}; + +enum mt_trans_op { + I2C_MASTER_NONE = 0, + I2C_MASTER_WR = 1, + I2C_MASTER_RD, + I2C_MASTER_WRRD, +}; + +/* CONTROL */ +#define I2C_CONTROL_RS (0x1 << 1) +#define I2C_CONTROL_DMA_EN (0x1 << 2) +#define I2C_CONTROL_CLK_EXT_EN (0x1 << 3) +#define I2C_CONTROL_DIR_CHANGE (0x1 << 4) +#define I2C_CONTROL_ACKERR_DET_EN (0x1 << 5) +#define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6) +/***********************************end of register operation**************************************/ +/***********************************I2C Param******************************************************/ +struct mt_trans_data { + u16 trans_num; + u16 data_size; + u16 trans_len; + u16 trans_auxlen; +}; +struct i2c_dma_buf { + u8 *vaddr; + dma_addr_t paddr; +}; + +struct mt_i2c_t { +#ifdef I2C_DRIVER_IN_KERNEL + /* ==========only used in kernel================ */ + struct i2c_adapter adap; /* i2c host adapter */ + struct device *dev; /* the device object of i2c host adapter */ + atomic_t trans_err; /* i2c transfer error */ + atomic_t trans_comp; /* i2c transfer completion */ + atomic_t trans_stop; /* i2c transfer stop */ + spinlock_t lock; /* for struct mt_i2c_t protection */ + struct mutex mutex; /* protect from different API */ + wait_queue_head_t wait; /* i2c transfer wait queue */ +#endif + /* ==========set in i2c probe============ */ + void __iomem *base; /* i2c base addr */ + u16 id; + u32 irqnr; /* i2c interrupt number */ + u16 irq_stat; /* i2c interrupt status */ + u32 clk; /* host clock speed in khz */ + u32 pdn; /*clock number */ + /* ==========common data define============ */ + enum i2c_trans_st_rs st_rs; + enum mt_trans_op op; + void __iomem *pdmabase; + u32 speed; /* The speed (khz) */ + u16 delay_len; /* number of half pulse between transfers in a trasaction */ + u32 msg_len; /* number of bytes for transaction */ + u8 *msg_buf; /* pointer to msg data */ + u8 addr; /* The 7-bit address of the slave device */ + u8 master_code; /* master code in HS mode */ + u8 mode; /* ST/FS/HS mode */ + /* ==========reserved function============ */ + u8 is_push_pull_enable; /* IO push-pull or open-drain */ + u8 is_clk_ext_disable; /* clk entend default enable */ + u8 is_dma_enabled; /* Transaction via DMA instead of 8-byte FIFO */ + u8 read_flag; /* read,write,read_write */ + bool dma_en; + bool poll_en; + bool pushpull; /* open drain */ + bool filter_msg; /* filter msg error log */ + bool i2c_3dcamera_flag; /* flag for 3dcamera */ + + /* ==========define reg============ */ + u16 timing_reg; + u16 high_speed_reg; + u16 control_reg; + u32 last_speed; + u8 last_mode; + u32 default_speed; + struct mt_trans_data trans_data; + struct i2c_dma_buf dma_buf; +#if !defined(CONFIG_MTK_CLKMGR) + struct clk *clk_main; /* main clock for i2c bus */ + struct clk *clk_dma; /* DMA clock for i2c via DMA */ +#endif +}; + +struct mt_i2c_msg { + u16 addr; /* slave address */ + u16 flags; +#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ +#define I2C_M_RD 0x0001 /* read data, from slave to master */ +#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */ +#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ + u16 len; /* msg length */ + u8 *buf; /* pointer to msg data */ + u32 timing; + u32 ext_flag; +}; + +#define I2C_A_FILTER_MSG 0x8000 /* filer out error messages */ +#define I2C_A_CHANGE_TIMING 0x4000 /* change timing parameters */ +#define I2C_MASK_FLAG (0x00ff) +#define I2C_DMA_FLAG (0xdead2000) +#define I2C_WR_FLAG (0x1000) +#define I2C_RS_FLAG (0x0800) +#define I2C_HS_FLAG (0x0400) +#define I2C_ENEXT_FLAG (0x0200) +#define I2C_DISEXT_FLAG (0x0000) +#define I2C_POLL_FLAG (0x4000) +#define I2C_CH2_FLAG (0x8000) +#define I2C_POLLING_FLAG (0x00000001) +#define I2C_PUSHPULL_FLAG (0x00000002) +#define I2C_3DCAMERA_FLAG (0x00000004) +#define I2C_DIRECTION_FLAG (0x00000008) + +/* external API */ + +extern char *mt_i2c_bus_to_virt(unsigned long address); +void _i2c_dump_info(struct mt_i2c_t *i2c); +void i2c_writel(struct mt_i2c_t *i2c, u8 offset, u16 value); +u32 i2c_readl(struct mt_i2c_t *i2c, u8 offset); + +#endif /* __MT_I2C_H__ */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..82e031043abb8471deff81c4f2f564da0eeff98a --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/Makefile @@ -0,0 +1,67 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +# +# Makefile for misc devices that really don't fit anywhere else. +# +# Vanzo:yucheng on: Sun, 24 Jan 2016 18:13:26 +0800 +# Modified for vanzo customization +#include $(srctree)/drivers/misc/mediatek/Makefile.custom +# End of Vanzo: yucheng +define FILTER_PROJECT_DRV +ifeq ($(wildcard $(srctree)/drivers/misc/mediatek/imgsensor/src/$(MTK_PLATFORM)/camera_project/$(ARCH_MTK_PROJECT)/$(1)),) +platform_drv += $(1) +else +project_drv += camera_project/$(ARCH_MTK_PROJECT)/$(1) +endif +endef + +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +ARCH_MTK_PROJECT := $(subst ",,$(CONFIG_ARCH_MTK_PROJECT)) + +obj-y += kd_sensorlist.o + +$(info -= project path $(srctree)/drivers/misc/mediatek/imgsensor/src/$(MTK_PLATFORM)/camera_project/$(ARCH_MTK_PROJECT)/ =-) + +ifneq ($(wildcard $(srctree)/drivers/misc/mediatek/imgsensor/src/$(MTK_PLATFORM)/camera_project/$(ARCH_MTK_PROJECT)/camera_hw),) +obj-y += camera_project/$(ARCH_MTK_PROJECT)/camera_hw/ +$(info by porject kd_camera_hw) +else +obj-y += camera_hw/ +endif + +$(foreach drv,$(subst $\",,$(CONFIG_CUSTOM_KERNEL_IMGSENSOR)),$(eval $(call FILTER_PROJECT_DRV,$(drv)))) +custom_kernel_imgsensor_by_platform := $(addsuffix /, $(shell echo $(platform_drv))) +custom_kernel_imgsensor_by_project := $(addsuffix /, $(shell echo $(project_drv))) + +# Vanzo:wangfei on: Wed, 12 Nov 2014 21:06:42 +0800 +# for compatible the old style ,so use CUSTOM_KERNEL_IMGSENSOR +custom_kernel_imgsensor := $(addsuffix /, $(shell echo $(CUSTOM_KERNEL_IMGSENSOR))) + +ifeq ($(custom_kernel_imgsensor),) +# End of Vanzo:wangfei + $(foreach drv,$(subst $\",,$(CONFIG_CUSTOM_KERNEL_IMGSENSOR)),$(eval $(call FILTER_PROJECT_DRV,$(drv)))) + custom_kernel_imgsensor := $(addsuffix /, $(shell echo $(platform_drv))) +# Vanzo:wangfei on: Thu, 13 Nov 2014 16:15:59 +0800 +# added for project config prio the defconfig +endif +# End of Vanzo:wangfei +# Vanzo:yucheng on: Sat, 16 Jan 2016 17:58:29 +0800 +# Modified for camera customization +#obj-y += $(custom_kernel_imgsensor_by_platform) +#obj-y += $(custom_kernel_imgsensor_by_project) + +obj-y += $(custom_kernel_imgsensor) +# End of Vanzo: yucheng +$(info imgsensor drv by platform $(platform_drv)) +$(info imgsensor drv by project $(project_drv)) diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..65642aaca1bce91283708921da53810040856402 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += kd_camera_hw.o diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/kd_camera_hw.c b/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/kd_camera_hw.c new file mode 100755 index 0000000000000000000000000000000000000000..278abc35d4a07ae5fbb696b4d941d4ffe77d1c4c --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/kd_camera_hw.c @@ -0,0 +1,2328 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + + +#include "kd_camera_hw.h" + + +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_camera_feature.h" + + + + +/****************************************************************************** + * Debug configuration +******************************************************************************/ +#define PFX "[kd_camera_hw]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(PFX fmt, ##arg) + +#define DEBUG_CAMERA_HW_K +#define CONTROL_AF_POWER 1 +#ifdef DEBUG_CAMERA_HW_K +#define PK_DBG PK_DBG_FUNC +#define PK_ERR(fmt, arg...) pr_err(fmt, ##arg) +#define PK_XLOG_INFO(fmt, args...) \ + do { \ + pr_debug(PFX fmt, ##arg); \ + } while (0) +#else +#define PK_DBG(a, ...) +#define PK_ERR(a, ...) +#define PK_XLOG_INFO(fmt, args...) +#endif + + +#define IDX_PS_MODE 1 +#define IDX_PS_ON 2 +#define IDX_PS_OFF 3 + + +#define IDX_PS_CMRST 0 +#define IDX_PS_CMPDN 4 + + +extern void ISP_MCLK1_EN(BOOL En); +extern void ISP_MCLK2_EN(BOOL En); +extern void ISP_MCLK3_EN(BOOL En); + + +u32 pinSetIdx = 0; /* default main sensor */ +u32 pinSet[3][8] = { + /* for main sensor */ + {CAMERA_CMRST_PIN, + CAMERA_CMRST_PIN_M_GPIO, /* mode */ + GPIO_OUT_ONE, /* ON state */ + GPIO_OUT_ZERO, /* OFF state */ + CAMERA_CMPDN_PIN, + CAMERA_CMPDN_PIN_M_GPIO, + GPIO_OUT_ONE, + GPIO_OUT_ZERO, + }, + /* for sub sensor */ + {CAMERA_CMRST1_PIN, + CAMERA_CMRST1_PIN_M_GPIO, + GPIO_OUT_ONE, + GPIO_OUT_ZERO, + CAMERA_CMPDN1_PIN, + CAMERA_CMPDN1_PIN_M_GPIO, + GPIO_OUT_ONE, + GPIO_OUT_ZERO, + }, + /* for main2 sensor */ + {CAMERA_CMRST2_PIN, + CAMERA_CMRST2_PIN_M_GPIO, + GPIO_OUT_ONE, + GPIO_OUT_ZERO, + CAMERA_CMPDN2_PIN, + CAMERA_CMPDN2_PIN_M_GPIO, + GPIO_OUT_ONE, + GPIO_OUT_ZERO, + }, +}; +#ifndef CONFIG_MTK_LEGACY +#define CUST_AVDD AVDD - AVDD +#define CUST_DVDD DVDD - AVDD +#define CUST_DOVDD DOVDD - AVDD +#define CUST_AFVDD AFVDD - AVDD +#define CUST_SUB_AVDD SUB_AVDD - AVDD +#define CUST_SUB_DVDD SUB_DVDD - AVDD +#define CUST_MAIN2_DVDD MAIN2_DVDD - AVDD +#endif + + +PowerCust PowerCustList = { + { + {GPIO_SUPPORTED, GPIO_MODE_GPIO, Vol_High}, /* for AVDD; */ + {GPIO_UNSUPPORTED, GPIO_MODE_GPIO, Vol_Low}, /* for DVDD; */ + {GPIO_UNSUPPORTED, GPIO_MODE_GPIO, Vol_Low}, /* for DOVDD; */ + {GPIO_UNSUPPORTED, GPIO_MODE_GPIO, Vol_Low}, /* for AFVDD; */ + {GPIO_SUPPORTED, GPIO_MODE_GPIO, Vol_High}, /* for SUB_AVDD; */ + {GPIO_UNSUPPORTED, GPIO_MODE_GPIO, Vol_Low}, /* for SUB_DVDD; */ + {GPIO_UNSUPPORTED, GPIO_MODE_GPIO, Vol_Low}, /* MAIN2_DVDD; */ + /*{GPIO_SUPPORTED, GPIO_MODE_GPIO, Vol_Low}, */ + } +}; + + + +PowerUp PowerOnList = { + { +#if defined(S5K5E2YA_MIPI_RAW) + {SENSOR_DRVNAME_S5K5E2YA_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {DOVDD, Vol_1800, 0}, + {AVDD, Vol_2800, 0}, + {DVDD, Vol_1200, 0}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 4}, + {PDN, Vol_High, 0}, + {RST, Vol_Low, 1}, + {RST, Vol_High, 0}, + }, + }, +#endif +#if defined(S5K2P8_MIPI_RAW) + {SENSOR_DRVNAME_S5K2P8_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {DOVDD, Vol_1800, 0}, + {AVDD, Vol_2800, 0}, + {DVDD, Vol_1200, 0}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 4}, + {PDN, Vol_High, 0}, + {RST, Vol_Low, 1}, + {RST, Vol_High, 0}, + }, + }, +#endif +#if defined(HI553_MIPI_RAW) + {SENSOR_DRVNAME_HI553_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {PDN, Vol_Low, 5}, + {RST, Vol_Low, 5}, + {DOVDD, Vol_1800, 1}, + {AVDD, Vol_2800, 1}, + {DVDD, Vol_1200, 1}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_High, 5}, + {RST, Vol_High, 5} + }, + }, +#endif + #if defined(OV5648_MIPI_RAW) + {SENSOR_DRVNAME_OV5648_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {DOVDD, Vol_1800, 1}, + {AVDD, Vol_2800, 1}, + {DVDD, Vol_1500, 1}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 1}, + {RST, Vol_Low, 1}, + {PDN, Vol_High, 0}, + {RST, Vol_High, 0} + }, + }, +#endif +#if defined(OV16825_MIPI_RAW) + {SENSOR_DRVNAME_OV16825_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {DOVDD, Vol_1800, 0}, + {AVDD, Vol_2800, 0}, + {DVDD, Vol_1200, 0}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 0}, + {RST, Vol_Low, 0}, + {RST, Vol_High, 0}, + }, + }, +#endif +#if defined(OV12830_MIPI_RAW) + {SENSOR_DRVNAME_OV12830_MIPI_RAW, + { + {SensorMCLK,Vol_High, 0}, + {PDN, Vol_Low, 0}, + {RST, Vol_Low, 0}, + {AVDD, Vol_2800, 10}, + {DOVDD, Vol_1800, 10}, + {DVDD, Vol_1200, 10}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_High, 0}, + {RST, Vol_High, 0} + }, + }, +#endif +#if defined(OV13850_MIPI_RAW) + {SENSOR_DRVNAME_OV13850_MIPI_RAW, + { + {SensorMCLK,Vol_High, 0}, + {PDN, Vol_Low, 0}, + {RST, Vol_Low, 0}, + {AVDD, Vol_2800, 10}, + {DOVDD, Vol_1800, 10}, + {DVDD, Vol_1200, 10}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_High, 0}, + {RST, Vol_High, 0} + }, + }, +#endif +#if defined(IMX135_MIPI_RAW) + {SENSOR_DRVNAME_IMX135_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {AVDD, Vol_2800, 10}, + {DOVDD, Vol_1800, 10}, + {DVDD, Vol_1000, 10}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 0}, + {PDN, Vol_High, 0}, + {RST, Vol_Low, 0}, + {RST, Vol_High, 0} + }, + }, +#endif +#if defined(OV8858_MIPI_RAW) + {SENSOR_DRVNAME_OV8858_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {PDN, Vol_Low, 0}, + {RST, Vol_Low, 0}, + {DOVDD, Vol_1800, 1}, + {AVDD, Vol_2800, 1}, + {DVDD, Vol_1200, 5}, + {AFVDD, Vol_2800, 1}, + {PDN, Vol_High, 1}, + {RST, Vol_High, 2} + }, + }, +#endif +#if defined(OV8856_MIPI_RAW) + {SENSOR_DRVNAME_OV8856_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {PDN, Vol_Low, 0}, + {RST, Vol_Low, 0}, + {DOVDD, Vol_1800, 1}, + {AVDD, Vol_2800, 1}, + {DVDD, Vol_1200, 5}, + {AFVDD, Vol_2800, 1}, + {PDN, Vol_High, 1}, + {RST, Vol_High, 2} + }, + }, +#endif +#if defined(IMX258_MIPI_RAW) + {SENSOR_DRVNAME_IMX258_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {PDN, Vol_Low, 0}, + {RST, Vol_Low, 0}, + {DOVDD, Vol_1800, 0}, + {AVDD, Vol_2800, 0}, + {DVDD, Vol_1200, 0}, + {AFVDD, Vol_2800, 1}, + {PDN, Vol_High, 0}, + {RST, Vol_High, 0} + }, + }, +#endif +#if defined(IMX214_MIPI_RAW) + {SENSOR_DRVNAME_IMX214_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {AVDD, Vol_2800, 10}, + {DOVDD, Vol_1800, 10}, + {DVDD, Vol_1000, 10}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 0}, + {PDN, Vol_High, 0}, + {RST, Vol_Low, 0}, + {RST, Vol_High, 0} + }, + }, +#endif +#if defined(S5K3P3SX_MIPI_RAW) + {SENSOR_DRVNAME_S5K3P3SX_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {DOVDD, Vol_1800, 0}, + {AVDD, Vol_2800, 0}, + {DVDD, Vol_1200, 0}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 4}, + {PDN, Vol_High, 0}, + {RST, Vol_Low, 1}, + {RST, Vol_High, 0}, + }, + }, +#endif + #if defined(S5K3P3SQ_MIPI_RAW) + {SENSOR_DRVNAME_S5K3P3SQ_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {DOVDD, Vol_1800, 0}, + {AVDD, Vol_2800, 0}, + {DVDD, Vol_1200, 0}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 4}, + {PDN, Vol_High, 0}, + {RST, Vol_Low, 1}, + {RST, Vol_High, 0}, + }, + }, +#endif +#if defined(S5K3L8_MIPI_RAW) + {SENSOR_DRVNAME_S5K3L8_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {DOVDD, Vol_1800, 0}, + {AVDD, Vol_2800, 0}, + {DVDD, Vol_1200, 0}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 4}, + {PDN, Vol_High, 0}, + {RST, Vol_Low, 1}, + {RST, Vol_High, 0}, + }, + }, +#endif +#if defined(GC5005_MIPI_RAW) + {SENSOR_DRVNAME_GC5005_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {PDN, Vol_High, 5}, + {RST, Vol_Low, 5}, + {AVDD, Vol_2800, 5}, + {DOVDD, Vol_1800, 5}, + {DVDD, Vol_1200, 5}, + {AFVDD, Vol_2800, 5}, + {PDN, Vol_Low, 5}, + {RST, Vol_High, 5}, + }, + }, +#endif +#if defined(GC5025MIPI_RAW) + {SENSOR_DRVNAME_GC5025_MIPI_RAW, + { + {SensorMCLK, Vol_High, 0}, + {PDN, Vol_Low, 5}, + {RST, Vol_Low, 5}, + {DOVDD, Vol_1800, 5}, + {DVDD, Vol_1200, 5}, + {AVDD, Vol_2800, 5}, + {PDN, Vol_High, 5}, + {RST, Vol_High, 5}, + }, + }, +#endif + /* add new sensor before this line */ + {NULL,}, + } +}; + + + +#ifndef CONFIG_MTK_LEGACY + +#define VOL_2800 2800000 +#define VOL_1800 1800000 +#define VOL_1500 1500000 +#define VOL_1200 1200000 +#define VOL_1220 1220000 +#define VOL_1000 1000000 + +/* GPIO Pin control*/ +struct platform_device *cam_plt_dev = NULL; +struct pinctrl *camctrl = NULL; +struct pinctrl_state *cam0_pnd_h = NULL;/* main cam */ +struct pinctrl_state *cam0_pnd_l = NULL; +struct pinctrl_state *cam0_rst_h = NULL; +struct pinctrl_state *cam0_rst_l = NULL; +struct pinctrl_state *cam1_pnd_h = NULL;/* sub cam */ +struct pinctrl_state *cam1_pnd_l = NULL; +struct pinctrl_state *cam1_rst_h = NULL; +struct pinctrl_state *cam1_rst_l = NULL; +struct pinctrl_state *cam2_pnd_h = NULL;/* main2 cam */ +struct pinctrl_state *cam2_pnd_l = NULL; +struct pinctrl_state *cam2_rst_h = NULL; +struct pinctrl_state *cam2_rst_l = NULL; +struct pinctrl_state *cam_ldo_vcama_h = NULL;/* for AVDD */ +struct pinctrl_state *cam_ldo_vcama_l = NULL; +struct pinctrl_state *cam_ldo_vcamd_h = NULL;/* for DVDD */ +struct pinctrl_state *cam_ldo_vcamd_l = NULL; +struct pinctrl_state *cam_ldo_vcamio_h = NULL;/* for DOVDD */ +struct pinctrl_state *cam_ldo_vcamio_l = NULL; +struct pinctrl_state *cam_ldo_vcamaf_h = NULL;/* for AFVDD */ +struct pinctrl_state *cam_ldo_vcamaf_l = NULL; +struct pinctrl_state *cam_ldo_sub_vcama_h = NULL;/* for SUB_AVDD */ +struct pinctrl_state *cam_ldo_sub_vcama_l = NULL; +struct pinctrl_state *cam_ldo_sub_vcamd_h = NULL;/* for SUB_DVDD */ +struct pinctrl_state *cam_ldo_sub_vcamd_l = NULL; +struct pinctrl_state *cam_ldo_main2_vcamd_h = NULL;/* for MAIN2_DVDD */ +struct pinctrl_state *cam_ldo_main2_vcamd_l = NULL; +struct pinctrl_state *cam_mipi_switch_en_h = NULL;/* for mipi switch enable */ +struct pinctrl_state *cam_mipi_switch_en_l = NULL; +struct pinctrl_state *cam_mipi_switch_sel_h = NULL;/* for mipi switch select */ +struct pinctrl_state *cam_mipi_switch_sel_l = NULL; +int has_mipi_switch = 0; + +int mtkcam_gpio_init(struct platform_device *pdev) +{ + int ret = 0; + has_mipi_switch = 1; + + camctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(camctrl)) { + dev_err(&pdev->dev, "Cannot find camera pinctrl!"); + ret = PTR_ERR(camctrl); + } + /*Cam0 Power/Rst Ping initialization */ + cam0_pnd_h = pinctrl_lookup_state(camctrl, "cam0_pnd1"); + if (IS_ERR(cam0_pnd_h)) { + ret = PTR_ERR(cam0_pnd_h); + PK_DBG("%s : pinctrl err, cam0_pnd_h\n", __func__); + } + + cam0_pnd_l = pinctrl_lookup_state(camctrl, "cam0_pnd0"); + if (IS_ERR(cam0_pnd_l)) { + ret = PTR_ERR(cam0_pnd_l); + PK_DBG("%s : pinctrl err, cam0_pnd_l\n", __func__); + } + + + cam0_rst_h = pinctrl_lookup_state(camctrl, "cam0_rst1"); + if (IS_ERR(cam0_rst_h)) { + ret = PTR_ERR(cam0_rst_h); + PK_DBG("%s : pinctrl err, cam0_rst_h\n", __func__); + } + + cam0_rst_l = pinctrl_lookup_state(camctrl, "cam0_rst0"); + if (IS_ERR(cam0_rst_l)) { + ret = PTR_ERR(cam0_rst_l); + PK_DBG("%s : pinctrl err, cam0_rst_l\n", __func__); + } + + /*Cam1 Power/Rst Ping initialization */ + cam1_pnd_h = pinctrl_lookup_state(camctrl, "cam1_pnd1"); + if (IS_ERR(cam1_pnd_h)) { + ret = PTR_ERR(cam1_pnd_h); + PK_DBG("%s : pinctrl err, cam1_pnd_h\n", __func__); + } + + cam1_pnd_l = pinctrl_lookup_state(camctrl, "cam1_pnd0"); + if (IS_ERR(cam1_pnd_l)) { + ret = PTR_ERR(cam1_pnd_l); + PK_DBG("%s : pinctrl err, cam1_pnd_l\n", __func__); + } + + + cam1_rst_h = pinctrl_lookup_state(camctrl, "cam1_rst1"); + if (IS_ERR(cam1_rst_h)) { + ret = PTR_ERR(cam1_rst_h); + PK_DBG("%s : pinctrl err, cam1_rst_h\n", __func__); + } + + + cam1_rst_l = pinctrl_lookup_state(camctrl, "cam1_rst0"); + if (IS_ERR(cam1_rst_l)) { + ret = PTR_ERR(cam1_rst_l); + PK_DBG("%s : pinctrl err, cam1_rst_l\n", __func__); + } + /*Cam2 Power/Rst Ping initialization */ + cam2_pnd_h = pinctrl_lookup_state(camctrl, "cam2_pnd1"); + if (IS_ERR(cam2_pnd_h)) { + ret = PTR_ERR(cam2_pnd_h); + PK_DBG("%s : pinctrl err, cam2_pnd_h\n", __func__); + } + + cam2_pnd_l = pinctrl_lookup_state(camctrl, "cam2_pnd0"); + if (IS_ERR(cam2_pnd_l)) { + ret = PTR_ERR(cam2_pnd_l); + PK_DBG("%s : pinctrl err, cam2_pnd_l\n", __func__); + } + + + cam2_rst_h = pinctrl_lookup_state(camctrl, "cam2_rst1"); + if (IS_ERR(cam2_rst_h)) { + ret = PTR_ERR(cam2_rst_h); + PK_DBG("%s : pinctrl err, cam2_rst_h\n", __func__); + } + + + cam2_rst_l = pinctrl_lookup_state(camctrl, "cam2_rst0"); + if (IS_ERR(cam2_rst_l)) { + ret = PTR_ERR(cam2_rst_l); + PK_DBG("%s : pinctrl err, cam2_rst_l\n", __func__); + } + + /*externel LDO enable */ + cam_ldo_vcama_h = pinctrl_lookup_state(camctrl, "cam_ldo_vcama_1"); + if (IS_ERR(cam_ldo_vcama_h)) { + ret = PTR_ERR(cam_ldo_vcama_h); + PK_DBG("%s : pinctrl err, cam_ldo_vcama_h\n", __func__); + } + + cam_ldo_vcama_l = pinctrl_lookup_state(camctrl, "cam_ldo_vcama_0"); + if (IS_ERR(cam_ldo_vcama_l)) { + ret = PTR_ERR(cam_ldo_vcama_l); + PK_DBG("%s : pinctrl err, cam_ldo_vcama_l\n", __func__); + } + + cam_ldo_vcamd_h = pinctrl_lookup_state(camctrl, "cam_ldo_vcamd_1"); + if (IS_ERR(cam_ldo_vcamd_h)) { + ret = PTR_ERR(cam_ldo_vcamd_h); + PK_DBG("%s : pinctrl err, cam_ldo_vcamd_h\n", __func__); + } + + cam_ldo_vcamd_l = pinctrl_lookup_state(camctrl, "cam_ldo_vcamd_0"); + if (IS_ERR(cam_ldo_vcamd_l)) { + ret = PTR_ERR(cam_ldo_vcamd_l); + PK_DBG("%s : pinctrl err, cam_ldo_vcamd_l\n", __func__); + } + + cam_ldo_vcamio_h = pinctrl_lookup_state(camctrl, "cam_ldo_vcamio_1"); + if (IS_ERR(cam_ldo_vcamio_h)) { + ret = PTR_ERR(cam_ldo_vcamio_h); + PK_DBG("%s : pinctrl err, cam_ldo_vcamio_h\n", __func__); + } + + cam_ldo_vcamio_l = pinctrl_lookup_state(camctrl, "cam_ldo_vcamio_0"); + if (IS_ERR(cam_ldo_vcamio_l)) { + ret = PTR_ERR(cam_ldo_vcamio_l); + PK_DBG("%s : pinctrl err, cam_ldo_vcamio_l\n", __func__); + } + + cam_ldo_vcamaf_h = pinctrl_lookup_state(camctrl, "cam_ldo_vcamaf_1"); + if (IS_ERR(cam_ldo_vcamaf_h)) { + ret = PTR_ERR(cam_ldo_vcamaf_h); + PK_DBG("%s : pinctrl err, cam_ldo_vcamaf_h\n", __func__); + } + + cam_ldo_vcamaf_l = pinctrl_lookup_state(camctrl, "cam_ldo_vcamaf_0"); + if (IS_ERR(cam_ldo_vcamaf_l)) { + ret = PTR_ERR(cam_ldo_vcamaf_l); + PK_DBG("%s : pinctrl err, cam_ldo_vcamaf_l\n", __func__); + } + + cam_ldo_sub_vcama_h = pinctrl_lookup_state(camctrl, "cam_ldo_sub_vcama_1"); + if (IS_ERR(cam_ldo_sub_vcama_h)) { + ret = PTR_ERR(cam_ldo_sub_vcama_h); + PK_DBG("%s : pinctrl err, cam_ldo_sub_vcama_h\n", __func__); + } + + cam_ldo_sub_vcama_l = pinctrl_lookup_state(camctrl, "cam_ldo_sub_vcama_0"); + if (IS_ERR(cam_ldo_sub_vcama_l)) { + ret = PTR_ERR(cam_ldo_sub_vcama_l); + PK_DBG("%s : pinctrl err, cam_ldo_sub_vcama_l\n", __func__); + } + + cam_ldo_sub_vcamd_h = pinctrl_lookup_state(camctrl, "cam_ldo_sub_vcamd_1"); + if (IS_ERR(cam_ldo_sub_vcamd_h)) { + ret = PTR_ERR(cam_ldo_sub_vcamd_h); + PK_DBG("%s : pinctrl err, cam_ldo_sub_vcamd_h\n", __func__); + } + + cam_ldo_sub_vcamd_l = pinctrl_lookup_state(camctrl, "cam_ldo_sub_vcamd_0"); + if (IS_ERR(cam_ldo_sub_vcamd_l)) { + ret = PTR_ERR(cam_ldo_sub_vcamd_l); + PK_DBG("%s : pinctrl err, cam_ldo_sub_vcamd_l\n", __func__); + } + + cam_ldo_main2_vcamd_h = pinctrl_lookup_state(camctrl, "cam_ldo_main2_vcamd_1"); + if (IS_ERR(cam_ldo_main2_vcamd_h)) { + ret = PTR_ERR(cam_ldo_main2_vcamd_h); + PK_DBG("%s : pinctrl err, cam_ldo_main2_vcamd_h\n", __func__); + } + + cam_ldo_main2_vcamd_l = pinctrl_lookup_state(camctrl, "cam_ldo_main2_vcamd_0"); + if (IS_ERR(cam_ldo_main2_vcamd_l)) { + ret = PTR_ERR(cam_ldo_main2_vcamd_l); + PK_DBG("%s : pinctrl err, cam_ldo_main2_vcamd_l\n", __func__); + } + + cam_mipi_switch_en_h = pinctrl_lookup_state(camctrl, "cam_mipi_switch_en_1"); + if (IS_ERR(cam_mipi_switch_en_h)) { + has_mipi_switch = 0; + ret = PTR_ERR(cam_mipi_switch_en_h); + PK_DBG("%s : pinctrl err, cam_mipi_switch_en_h\n", __func__); + } + + cam_mipi_switch_en_l = pinctrl_lookup_state(camctrl, "cam_mipi_switch_en_0"); + if (IS_ERR(cam_mipi_switch_en_l)) { + has_mipi_switch = 0; + ret = PTR_ERR(cam_mipi_switch_en_l); + PK_DBG("%s : pinctrl err, cam_mipi_switch_en_l\n", __func__); + } + cam_mipi_switch_sel_h = pinctrl_lookup_state(camctrl, "cam_mipi_switch_sel_1"); + if (IS_ERR(cam_mipi_switch_sel_h)) { + has_mipi_switch = 0; + ret = PTR_ERR(cam_mipi_switch_sel_h); + PK_DBG("%s : pinctrl err, cam_mipi_switch_sel_h\n", __func__); + } + + cam_mipi_switch_sel_l = pinctrl_lookup_state(camctrl, "cam_mipi_switch_sel_0"); + if (IS_ERR(cam_mipi_switch_sel_l)) { + has_mipi_switch = 0; + ret = PTR_ERR(cam_mipi_switch_sel_l); + PK_DBG("%s : pinctrl err, cam_mipi_switch_sel_l\n", __func__); + } + return ret; +} + +int mtkcam_gpio_set(int PinIdx, int PwrType, int Val) +{ + int ret = 0; + if (IS_ERR(camctrl)) { + return -1; + } + switch (PwrType) { + case RST: + if (PinIdx == 0) { + if (Val == 0 && !IS_ERR(cam0_rst_l)) + pinctrl_select_state(camctrl, cam0_rst_l); + else if (Val == 1 && !IS_ERR(cam0_rst_h)) + pinctrl_select_state(camctrl, cam0_rst_h); + else + PK_ERR("%s : pinctrl err, PinIdx %d, Val %d, RST\n", __func__,PinIdx ,Val); + } else if (PinIdx == 1) { + if (Val == 0 && !IS_ERR(cam1_rst_l)) + pinctrl_select_state(camctrl, cam1_rst_l); + else if (Val == 1 && !IS_ERR(cam1_rst_h)) + pinctrl_select_state(camctrl, cam1_rst_h); + else + PK_ERR("%s : pinctrl err, PinIdx %d, Val %d, RST\n", __func__,PinIdx ,Val); + } else { + if (Val == 0 && !IS_ERR(cam2_rst_l)) + pinctrl_select_state(camctrl, cam2_rst_l); + else if (Val == 1 && !IS_ERR(cam2_rst_h)) + pinctrl_select_state(camctrl, cam2_rst_h); + else + PK_ERR("%s : pinctrl err, PinIdx %d, Val %d, RST\n", __func__,PinIdx ,Val); + } + break; + case PDN: + if (PinIdx == 0) { + if (Val == 0 && !IS_ERR(cam0_pnd_l)) + pinctrl_select_state(camctrl, cam0_pnd_l); + else if (Val == 1 && !IS_ERR(cam0_pnd_h)) + pinctrl_select_state(camctrl, cam0_pnd_h); + else + PK_ERR("%s : pinctrl err, PinIdx %d, Val %d, PDN\n", __func__,PinIdx ,Val); + } else if (PinIdx == 1) { + if (Val == 0 && !IS_ERR(cam1_pnd_l)) + pinctrl_select_state(camctrl, cam1_pnd_l); + else if (Val == 1 && !IS_ERR(cam1_pnd_h)) + pinctrl_select_state(camctrl, cam1_pnd_h); + else + PK_ERR("%s : pinctrl err, PinIdx %d, Val %d, PDN\n", __func__,PinIdx ,Val); + } else { + if (Val == 0 && !IS_ERR(cam2_pnd_l)) + pinctrl_select_state(camctrl, cam2_pnd_l); + else if (Val == 1 && !IS_ERR(cam2_pnd_h)) + pinctrl_select_state(camctrl, cam2_pnd_h); + else + PK_ERR("%s : pinctrl err, PinIdx %d, Val %d, PDN\n", __func__,PinIdx ,Val); + } + break; + case AVDD: + if (Val == 0 && !IS_ERR(cam_ldo_vcama_l)) + pinctrl_select_state(camctrl, cam_ldo_vcama_l); + else if (Val == 1 && !IS_ERR(cam0_rst_h)) + pinctrl_select_state(camctrl, cam_ldo_vcama_h); + break; + case DVDD: + if (Val == 0 && !IS_ERR(cam_ldo_vcamd_l)) + pinctrl_select_state(camctrl, cam_ldo_vcamd_l); + else if (Val == 1 && !IS_ERR(cam_ldo_vcamd_h)) + pinctrl_select_state(camctrl, cam_ldo_vcamd_h); + break; + case DOVDD: + if (Val == 0 && !IS_ERR(cam_ldo_vcamio_l)) + pinctrl_select_state(camctrl, cam_ldo_vcamio_l); + else if (Val == 1 && !IS_ERR(cam_ldo_vcamio_h)) + pinctrl_select_state(camctrl, cam_ldo_vcamio_h); + break; + case AFVDD: + if (Val == 0 && !IS_ERR(cam_ldo_vcamaf_l)) + pinctrl_select_state(camctrl, cam_ldo_vcamaf_l); + else if (Val == 1 && !IS_ERR(cam_ldo_vcamaf_h)) + pinctrl_select_state(camctrl, cam_ldo_vcamaf_h); + break; + case SUB_AVDD: + if (Val == 0 && !IS_ERR(cam_ldo_sub_vcama_l)) { + PK_ERR("yangbinbin sub_AVDD low\n"); + pinctrl_select_state(camctrl, cam_ldo_sub_vcama_l); + } else if (Val == 1 && !IS_ERR(cam_ldo_sub_vcama_h)) { + PK_ERR("yangbinbin sub_AVDD high\n"); + pinctrl_select_state(camctrl, cam_ldo_sub_vcama_h); + } + break; + case SUB_DVDD: + if (Val == 0 && !IS_ERR(cam_ldo_sub_vcamd_l)) + pinctrl_select_state(camctrl, cam_ldo_sub_vcamd_l); + else if (Val == 1 && !IS_ERR(cam_ldo_sub_vcamd_h)) + pinctrl_select_state(camctrl, cam_ldo_sub_vcamd_h); + break; + case MAIN2_DVDD: + if (Val == 0 && !IS_ERR(cam_ldo_main2_vcamd_l)) + pinctrl_select_state(camctrl, cam_ldo_main2_vcamd_l); + else if (Val == 1 && !IS_ERR(cam_ldo_main2_vcamd_h)) + pinctrl_select_state(camctrl, cam_ldo_main2_vcamd_h); + break; + default: + PK_DBG("PwrType(%d) is invalid !!\n", PwrType); + break; + }; + + /* PK_DBG("PinIdx(%d) PwrType(%d) val(%d)\n", PinIdx, PwrType, Val); */ + + return ret; +} + +BOOL hwpoweron(PowerInformation pwInfo, char *mode_name) +{ + if (pwInfo.PowerType == AVDD) { + if (pinSetIdx == 1) { + if (PowerCustList.PowerCustInfo[CUST_SUB_AVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerOn(SUB_AVDD, pwInfo.Voltage)) { + PK_ERR("[CAMERA SENSOR] Fail to enable analog power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, SUB_AVDD, PowerCustList.PowerCustInfo[CUST_SUB_AVDD].Voltage)) { + PK_ERR("[CAMERA CUST_SUB_AVDD] set gpio failed!!\n"); + } + } + } else { + if (PowerCustList.PowerCustInfo[CUST_AVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerOn(pwInfo.PowerType, pwInfo.Voltage)) { + PK_ERR("[CAMERA SENSOR] Fail to enable analog power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, pwInfo.PowerType, PowerCustList.PowerCustInfo[CUST_AVDD].Voltage)) { + PK_ERR("[CAMERA CUST_AVDD] set gpio failed!!\n"); + } + } + } + } else if (pwInfo.PowerType == DVDD) { + if (pinSetIdx == 2) { + if (PowerCustList.PowerCustInfo[CUST_MAIN2_DVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + /*PK_DBG("[CAMERA SENSOR] main2 camera VCAM_D power on");*/ + if (pwInfo.Voltage == Vol_1200) { + pwInfo.Voltage = Vol_1220; + PK_DBG("[CAMERA SENSOR] Main2 camera VCAM_D power 1.2V to 1.22V\n"); + } + if (TRUE != _hwPowerOn(MAIN2_DVDD, pwInfo.Voltage)) { + PK_ERR("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, MAIN2_DVDD, PowerCustList.PowerCustInfo[CUST_MAIN2_DVDD].Voltage)) { + PK_ERR("[CAMERA CUST_MAIN2_DVDD] set gpio failed!!\n"); + } + } + } else if (pinSetIdx == 1) { + if (PowerCustList.PowerCustInfo[CUST_SUB_DVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + /* PK_DBG("[CAMERA SENSOR] Sub camera VCAM_D power on"); */ + if (pwInfo.Voltage == Vol_1200) { + pwInfo.Voltage = Vol_1220; + PK_DBG("[CAMERA SENSOR] Sub camera VCAM_D power 1.2V to 1.22V\n"); + } + if (TRUE != _hwPowerOn(SUB_DVDD, pwInfo.Voltage)) { + PK_ERR("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, SUB_DVDD, PowerCustList.PowerCustInfo[CUST_SUB_DVDD].Voltage)) { + PK_ERR("[CAMERA CUST_SUB_DVDD] set gpio failed!!\n"); + } + } + } else { + if (PowerCustList.PowerCustInfo[CUST_DVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + /* PK_DBG("[CAMERA SENSOR] Main camera VCAM_D power on"); */ + if (TRUE != _hwPowerOn(pwInfo.PowerType, pwInfo.Voltage)) { + PK_ERR("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, pwInfo.PowerType, PowerCustList.PowerCustInfo[CUST_DVDD].Voltage)) { + PK_ERR("[CAMERA CUST_DVDD] set gpio failed!!\n"); + } + } + } + } else if (pwInfo.PowerType == DOVDD) { + if (PowerCustList.PowerCustInfo[CUST_DOVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerOn(pwInfo.PowerType, pwInfo.Voltage)) { + PK_ERR("[CAMERA SENSOR] Fail to enable io power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, pwInfo.PowerType, PowerCustList.PowerCustInfo[CUST_DOVDD].Voltage)) { + PK_ERR("[CAMERA CUST_DOVDD] set gpio failed!!\n"); + } + + } + } else if (pwInfo.PowerType == AFVDD) { +#if CONTROL_AF_POWER + if (PowerCustList.PowerCustInfo[CUST_AFVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerOn(pwInfo.PowerType, pwInfo.Voltage)) { + PK_ERR("[CAMERA SENSOR] Fail to enable af power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, pwInfo.PowerType, PowerCustList.PowerCustInfo[CUST_AFVDD].Voltage)) { + PK_ERR("[CAMERA CUST_AFVDD] set gpio failed!!\n"); + } + } +#endif + } else if (pwInfo.PowerType == PDN) { + /* PK_DBG("hwPowerOn: PDN %d\n", pwInfo.Voltage); */ + mtkcam_gpio_set(pinSetIdx, PDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]); + + + if (pwInfo.Voltage == Vol_High) { + if (mtkcam_gpio_set(pinSetIdx, PDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON])) { + PK_ERR("[CAMERA SENSOR] set gpio failed!!\n"); + } + } else { + if (mtkcam_gpio_set(pinSetIdx, PDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { + + PK_ERR("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == RST) { + mtkcam_gpio_set(pinSetIdx, RST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]); + if (pwInfo.Voltage == Vol_High) { + if (mtkcam_gpio_set(pinSetIdx, RST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_ERR("[CAMERA SENSOR] set gpio failed!!\n"); + } + } else { + if (mtkcam_gpio_set(pinSetIdx, RST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + + PK_ERR("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + + } else if (pwInfo.PowerType == SensorMCLK) { + if (pinSetIdx == 0) { + /* PK_DBG("Sensor MCLK1 On"); */ + ISP_MCLK1_EN(TRUE); + } else { + /* PK_DBG("Sensor MCLK2 On"); */ + ISP_MCLK2_EN(TRUE); + } + } else { + } + if (pwInfo.Delay > 0) + mdelay(pwInfo.Delay); + return TRUE; +} + + + +BOOL hwpowerdown(PowerInformation pwInfo, char *mode_name) +{ + if (pwInfo.PowerType == AVDD) { + if (pinSetIdx == 1) { + if (PowerCustList.PowerCustInfo[CUST_SUB_AVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerDown(SUB_AVDD)) { + PK_ERR("[CAMERA SENSOR] Fail to disable analog power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, SUB_AVDD, 1-PowerCustList.PowerCustInfo[CUST_SUB_AVDD].Voltage)) { + PK_ERR("[CAMERA CUST_SUB_AVDD] set gpio failed!!\n");/* 1-voltage for reverse*/ + } + } + } else { + if (PowerCustList.PowerCustInfo[CUST_AVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerDown(pwInfo.PowerType)) { + PK_ERR("[CAMERA SENSOR] Fail to disable analog power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, AVDD, 1-PowerCustList.PowerCustInfo[CUST_AVDD].Voltage)) { + PK_ERR("[CAMERA CUST_AVDD] set gpio failed!!\n");/* 1-voltage for reverse*/ + } + } + } + } else if (pwInfo.PowerType == DVDD) { + if (pinSetIdx == 2) { + if (PowerCustList.PowerCustInfo[CUST_MAIN2_DVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerDown(MAIN2_DVDD)) { + PK_ERR("[CAMERA SENSOR] Fail to disable main2 digital power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, MAIN2_DVDD, 1-PowerCustList.PowerCustInfo[CUST_MAIN2_DVDD].Voltage)) { + PK_ERR("[CAMERA CUST_MAIN2_DVDD] off set gpio failed!!\n"); + } + } + } else if (pinSetIdx == 1) { + if (PowerCustList.PowerCustInfo[CUST_SUB_DVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerDown(SUB_DVDD)) { + PK_ERR("[CAMERA SENSOR] Fail to enable sub digital power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, SUB_DVDD, 1-PowerCustList.PowerCustInfo[CUST_SUB_DVDD].Voltage)) { + PK_ERR("[CAMERA CUST_SUB_DVDD] off set gpio failed!!\n"); + } + } + } else { + if (PowerCustList.PowerCustInfo[CUST_DVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerDown(DVDD)) { + PK_ERR("[CAMERA SENSOR] Fail to disable main digital power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, DVDD, 1-PowerCustList.PowerCustInfo[CUST_DVDD].Voltage)) { + PK_ERR("[CAMERA CUST_DVDD] off set gpio failed!!\n"); + } + } + } + + } else if (pwInfo.PowerType == DOVDD) { + if (PowerCustList.PowerCustInfo[CUST_DOVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerDown(DOVDD)) { + PK_ERR("[CAMERA SENSOR] Fail to disable io power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, DOVDD, 1-PowerCustList.PowerCustInfo[CUST_DOVDD].Voltage)) { + PK_ERR("[CAMERA CUST_DOVDD] set gpio failed!!\n");/* 1-voltage for reverse*/ + } + } + } else if (pwInfo.PowerType == AFVDD) { +#if CONTROL_AF_POWER + if (PowerCustList.PowerCustInfo[CUST_AFVDD].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != _hwPowerDown(AFVDD)) { + PK_ERR("[CAMERA SENSOR] Fail to disable af power\n"); + return FALSE; + } + } else { + if (mtkcam_gpio_set(pinSetIdx, AFVDD, 1-PowerCustList.PowerCustInfo[CUST_AFVDD].Voltage)) { + PK_ERR("[CAMERA CUST_AFVDD] set gpio failed!!\n");/* 1-voltage for reverse*/ + } + } +#endif + } else if (pwInfo.PowerType == PDN) { + //PK_DBG("hwPowerDown: PDN %d\n", pwInfo.Voltage); + + + if (pwInfo.Voltage == Vol_High) { + if (mtkcam_gpio_set(pinSetIdx, PDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON])) { + PK_ERR("[CAMERA SENSOR] set gpio failed!!\n"); + } + } else { + if (mtkcam_gpio_set(pinSetIdx, PDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { + + PK_ERR("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == RST) { + //PK_DBG("hwPowerDown: RST %d\n", pwInfo.Voltage); + if (pwInfo.Voltage == Vol_High) { + if (mtkcam_gpio_set(pinSetIdx, RST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_ERR("[CAMERA SENSOR] set gpio failed!!\n"); + } + } else { + if (mtkcam_gpio_set(pinSetIdx, RST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + + PK_ERR("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + + } else if (pwInfo.PowerType == SensorMCLK) { + if (pinSetIdx == 0) { + ISP_MCLK1_EN(FALSE); + } else { + ISP_MCLK2_EN(FALSE); + } + } else { + } + return TRUE; +} + + + + +int kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On, + char *mode_name) +{ + + int pwListIdx, pwIdx; + BOOL sensorInPowerList = KAL_FALSE; + + if (DUAL_CAMERA_MAIN_SENSOR == SensorIdx) { + pinSetIdx = 0; + } else if (DUAL_CAMERA_SUB_SENSOR == SensorIdx) { + pinSetIdx = 1; + } else if (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx) { + pinSetIdx = 2; + } + /* power ON */ + if (On) { + PK_DBG("kdCISModulePowerOn -on:currSensorName=%s pinSetIdx=%d\n", currSensorName, pinSetIdx); + + + /* MIPI SWITCH */ + if(has_mipi_switch){ + if (DUAL_CAMERA_SUB_SENSOR == SensorIdx) { + pinctrl_select_state(camctrl, cam_mipi_switch_en_l); + pinctrl_select_state(camctrl, cam_mipi_switch_sel_h); + + } else if (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx) { + pinctrl_select_state(camctrl, cam_mipi_switch_en_l); + pinctrl_select_state(camctrl, cam_mipi_switch_sel_l); + } + } + + for (pwListIdx = 0; pwListIdx < 16; pwListIdx++) { + if (currSensorName && (PowerOnList.PowerSeq[pwListIdx].SensorName != NULL) + && (0 == + strcmp(PowerOnList.PowerSeq[pwListIdx].SensorName, + currSensorName))) { + //PK_DBG("sensorIdx:%d\n", SensorIdx); + + sensorInPowerList = KAL_TRUE; + + for (pwIdx = 0; pwIdx < 10; pwIdx++) { + if (PowerOnList.PowerSeq[pwListIdx].PowerInfo[pwIdx]. + PowerType != VDD_None) { + if (hwpoweron + (PowerOnList.PowerSeq[pwListIdx]. + PowerInfo[pwIdx], mode_name) == FALSE) + goto _kdCISModulePowerOn_exit_; + } else { + /* PK_DBG("pwIdx=%d\n", pwIdx); */ + break; + } + } + break; + } else if (PowerOnList.PowerSeq[pwListIdx].SensorName == NULL) { + break; + } else { + } + } +#if 0 + /* Temp solution: default power on/off sequence */ + if (KAL_FALSE == sensorInPowerList) { + PK_DBG("Default power on sequence"); + + if (pinSetIdx == 0) { + ISP_MCLK1_EN(1); + } else if (pinSetIdx == 1) { + ISP_MCLK2_EN(1); + } + /* First Power Pin low and Reset Pin Low */ + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { + PK_DBG("[CAMERA LENS] set gpio mode failed!! (CMPDN)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!! (CMPDN)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { + PK_DBG("[CAMERA LENS] set gpio failed!! (CMPDN)\n"); + } + } + + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) { + if (0 == pinSetIdx) { +#ifndef CONFIG_MTK_MT6306_SUPPORT + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#else + if (mt6306_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#endif + } else { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } + } + /* VCAM_IO */ + if (TRUE != hwPowerOn(CAMERA_POWER_VCAM_D2, VOL_1800*1000, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to enable digital power (VCAM_IO), power id = %d\n", + CAMERA_POWER_VCAM_D2); + goto _kdCISModulePowerOn_exit_; + } + /* VCAM_A */ + if (TRUE != hwPowerOn(CAMERA_POWER_VCAM_A, VOL_2800*1000, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to enable analog power (VCAM_A), power id = %d\n", + CAMERA_POWER_VCAM_A); + goto _kdCISModulePowerOn_exit_; + } + + if (TRUE != hwPowerOn(CAMERA_POWER_VCAM_D, VOL_1800*1000, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to enable digital power (VCAM_D), power id = %d\n", + CAMERA_POWER_VCAM_D); + goto _kdCISModulePowerOn_exit_; + } + /* AF_VCC */ + if (TRUE != hwPowerOn(CAMERA_POWER_VCAM_A2, VOL_2800*1000, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to enable analog power (VCAM_AF), power id = %d\n", + CAMERA_POWER_VCAM_A2); + goto _kdCISModulePowerOn_exit_; + } + + mdelay(5); + + /* enable active sensor */ + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { + PK_DBG("[CAMERA LENS] set gpio mode failed!! (CMPDN)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!! (CMPDN)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON])) { + PK_DBG("[CAMERA LENS] set gpio failed!! (CMPDN)\n"); + } + } + + mdelay(1); + + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) { + if (0 == pinSetIdx) { +#ifndef CONFIG_MTK_MT6306_SUPPORT + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#else + if (mt6306_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#endif + + } else { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } + } + + + + + } + /* + if(pinSetIdx==0) + for(;;) + {} + */ + /* + if(pinSetIdx==1) + for(;;) + {} + */ + #endif + } else { /* power OFF */ + if(has_mipi_switch){ + if (DUAL_CAMERA_SUB_SENSOR == SensorIdx || DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx) { + pinctrl_select_state(camctrl, cam_mipi_switch_en_h); + } + } + for (pwListIdx = 0; pwListIdx < 16; pwListIdx++) { + if (currSensorName && (PowerOnList.PowerSeq[pwListIdx].SensorName != NULL) + && (0 == + strcmp(PowerOnList.PowerSeq[pwListIdx].SensorName, + currSensorName))) { + PK_DBG("kdCISModulePowerOn -off:currSensorName=%s pinSetIdx=%d\n", currSensorName, pinSetIdx); + + sensorInPowerList = KAL_TRUE; + + for (pwIdx = 9; pwIdx >= 0; pwIdx--) { + if (PowerOnList.PowerSeq[pwListIdx].PowerInfo[pwIdx]. + PowerType != VDD_None) { + if (hwpowerdown + (PowerOnList.PowerSeq[pwListIdx]. + PowerInfo[pwIdx], mode_name) == FALSE) + goto _kdCISModulePowerOn_exit_; + if (pwIdx > 0) { + if (PowerOnList.PowerSeq[pwListIdx]. + PowerInfo[pwIdx - 1].Delay > 0) + mdelay(PowerOnList. + PowerSeq[pwListIdx]. + PowerInfo[pwIdx - 1].Delay); + } + } else { + /*PK_DBG("pwIdx=%d\n", pwIdx);*/ + } + } + } else if (PowerOnList.PowerSeq[pwListIdx].SensorName == NULL) { + break; + } else { + } + } +#if 0 + /* Temp solution: default power on/off sequence */ + if (KAL_FALSE == sensorInPowerList) { + PK_DBG("Default power off sequence"); + + if (pinSetIdx == 0) { + ISP_MCLK1_EN(0); + } else if (pinSetIdx == 1) { + ISP_MCLK2_EN(0); + } + /* Set Power Pin low and Reset Pin Low */ + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { + PK_DBG("[CAMERA LENS] set gpio mode failed!! (CMPDN)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!! (CMPDN)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { + PK_DBG("[CAMERA LENS] set gpio failed!! (CMPDN)\n"); + } + } + + + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) { + if (0 == pinSetIdx) { +#ifndef CONFIG_MTK_MT6306_SUPPORT + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#else + if (mt6306_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#endif + } else { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } + } + + + if (TRUE != hwPowerDown(CAMERA_POWER_VCAM_D, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to OFF core power (VCAM_D), power id = %d\n", + CAMERA_POWER_VCAM_D); + goto _kdCISModulePowerOn_exit_; + } + /* VCAM_A */ + if (TRUE != hwPowerDown(CAMERA_POWER_VCAM_A, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to OFF analog power (VCAM_A), power id= (%d)\n", + CAMERA_POWER_VCAM_A); + /* return -EIO; */ + goto _kdCISModulePowerOn_exit_; + } + /* VCAM_IO */ + if (TRUE != hwPowerDown(CAMERA_POWER_VCAM_D2, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to OFF digital power (VCAM_IO), power id = %d\n", + CAMERA_POWER_VCAM_D2); + /* return -EIO; */ + goto _kdCISModulePowerOn_exit_; + } + /* AF_VCC */ + if (TRUE != hwPowerDown(CAMERA_POWER_VCAM_A2, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to OFF AF power (VCAM_AF), power id = %d\n", + CAMERA_POWER_VCAM_A2); + /* return -EIO; */ + goto _kdCISModulePowerOn_exit_; + } + + + + + + + + } +#endif + } /* */ + + return 0; + +_kdCISModulePowerOn_exit_: + return -EIO; +} + +#else +BOOL hwpoweron(PowerInformation pwInfo, char *mode_name) +{ + if (pwInfo.PowerType == AVDD) { + if (PowerCustList.PowerCustInfo[0].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != hwPowerOn(pwInfo.PowerType, pwInfo.Voltage * 1000, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } else { + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[0].Gpio_Pin, + PowerCustList.PowerCustInfo[0].Gpio_Mode)) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(PowerCustList.PowerCustInfo[0].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[0].Gpio_Pin, + PowerCustList.PowerCustInfo[0].Voltage)) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == DVDD) { + if (PowerCustList.PowerCustInfo[1].Gpio_Pin == GPIO_UNSUPPORTED) { + if (pinSetIdx == 1) { + /* PK_DBG("[CAMERA SENSOR] Sub camera VCAM_D power on"); */ + if (pwInfo.Voltage == Vol_1200) { + pwInfo.Voltage = Vol_1220; + PK_DBG("[CAMERA SENSOR] Sub camera VCAM_D power 1.2V to 1.22V\n"); + } + if (TRUE != + hwPowerOn(SUB_CAMERA_POWER_VCAM_D, pwInfo.Voltage * 1000, + mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } else { + /* PK_DBG("[CAMERA SENSOR] Main camera VCAM_D power on"); */ + if (TRUE != + hwPowerOn(pwInfo.PowerType, pwInfo.Voltage * 1000, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } + } else { + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[1].Gpio_Pin, + PowerCustList.PowerCustInfo[1].Gpio_Mode)) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(PowerCustList.PowerCustInfo[1].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[1].Gpio_Pin, + PowerCustList.PowerCustInfo[1].Voltage)) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == DOVDD) { + if (PowerCustList.PowerCustInfo[2].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != hwPowerOn(pwInfo.PowerType, pwInfo.Voltage * 1000, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } else { + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[2].Gpio_Pin, + PowerCustList.PowerCustInfo[2].Gpio_Mode)) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(PowerCustList.PowerCustInfo[2].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[2].Gpio_Pin, + PowerCustList.PowerCustInfo[2].Voltage)) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == AFVDD) { +#if 0 + PK_DBG("[CAMERA SENSOR] Skip AFVDD setting\n"); + if (PowerCustList.PowerCustInfo[3].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != hwPowerOn(pwInfo.PowerType, pwInfo.Voltage * 1000, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } else { + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[3].Gpio_Pin, + PowerCustList.PowerCustInfo[3].Gpio_Mode)) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(PowerCustList.PowerCustInfo[3].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[3].Gpio_Pin, + PowerCustList.PowerCustInfo[3].Voltage)) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + + if (PowerCustList.PowerCustInfo[4].Gpio_Pin != GPIO_UNSUPPORTED) { + mdelay(5); + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[3].Gpio_Pin, + PowerCustList.PowerCustInfo[3].Gpio_Mode)) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir + (PowerCustList.PowerCustInfo[3].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[3].Gpio_Pin, + PowerCustList.PowerCustInfo[3].Voltage)) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + } +#endif + } else if (pwInfo.PowerType == PDN) { + /* PK_DBG("hwPowerOn: PDN %d\n", pwInfo.Voltage); */ + + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!!\n"); + } + if (pwInfo.Voltage == Vol_High) { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + } else { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == RST) { + /* PK_DBG("hwPowerOn: RST %d\n", pwInfo.Voltage); */ + + if (pinSetIdx == 0) { +#ifndef CONFIG_MTK_MT6306_SUPPORT + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + if (pwInfo.Voltage == Vol_High) { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } else { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } +#else + if (mt6306_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (pwInfo.Voltage == Vol_High) { + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } else { + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } +#endif + } else if (pinSetIdx == 1) { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + if (pwInfo.Voltage == Vol_High) { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + } else { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!!\n"); + } + } + } + + + } else if (pwInfo.PowerType == SensorMCLK) { + if (pinSetIdx == 0) { + /* PK_DBG("Sensor MCLK1 On"); */ + ISP_MCLK1_EN(TRUE); + } else if (pinSetIdx == 1) { + /* PK_DBG("Sensor MCLK2 On"); */ + ISP_MCLK2_EN(TRUE); + } + } else { + } + if (pwInfo.Delay > 0) + mdelay(pwInfo.Delay); + return TRUE; +} + + + +BOOL hwpowerdown(PowerInformation pwInfo, char *mode_name) +{ + if (pwInfo.PowerType == AVDD) { + if (PowerCustList.PowerCustInfo[0].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != hwPowerDown(pwInfo.PowerType, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to disable digital power\n"); + return FALSE; + } + } else { + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[0].Gpio_Pin, + PowerCustList.PowerCustInfo[0].Gpio_Mode)) { + PK_DBG("[CAMERA LENS] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(PowerCustList.PowerCustInfo[0].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[0].Gpio_Pin, + PowerCustList.PowerCustInfo[0].Voltage)) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == DVDD) { + if (PowerCustList.PowerCustInfo[1].Gpio_Pin == GPIO_UNSUPPORTED) { + if (pinSetIdx == 1) { + if (TRUE != hwPowerDown(PMIC_APP_SUB_CAMERA_POWER_D, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to disable digital power\n"); + return FALSE; + } + } else if (TRUE != hwPowerDown(pwInfo.PowerType, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to disable digital power\n"); + return FALSE; + } else { + } + } else { + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[1].Gpio_Pin, + PowerCustList.PowerCustInfo[1].Gpio_Mode)) { + PK_DBG("[CAMERA LENS] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(PowerCustList.PowerCustInfo[1].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[1].Gpio_Pin, + PowerCustList.PowerCustInfo[1].Voltage)) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == DOVDD) { + if (PowerCustList.PowerCustInfo[2].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != hwPowerDown(pwInfo.PowerType, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to disable digital power\n"); + return FALSE; + } + } else { + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[2].Gpio_Pin, + PowerCustList.PowerCustInfo[2].Gpio_Mode)) { + PK_DBG("[CAMERA LENS] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(PowerCustList.PowerCustInfo[2].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[2].Gpio_Pin, + PowerCustList.PowerCustInfo[2].Voltage)) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } + } else if (pwInfo.PowerType == AFVDD) { +#if 0 + PK_DBG("[CAMERA SENSOR] Skip AFVDD setting\n"); + if (PowerCustList.PowerCustInfo[3].Gpio_Pin == GPIO_UNSUPPORTED) { + if (TRUE != hwPowerDown(pwInfo.PowerType, mode_name)) { + PK_DBG("[CAMERA SENSOR] Fail to enable digital power\n"); + return FALSE; + } + } else { + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[3].Gpio_Pin, + PowerCustList.PowerCustInfo[3].Gpio_Mode)) { + PK_DBG("[CAMERA LENS] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(PowerCustList.PowerCustInfo[3].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[3].Gpio_Pin, + PowerCustList.PowerCustInfo[3].Voltage)) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + + if (PowerCustList.PowerCustInfo[4].Gpio_Pin != GPIO_UNSUPPORTED) { + mdelay(5); + if (mt_set_gpio_mode + (PowerCustList.PowerCustInfo[3].Gpio_Pin, + PowerCustList.PowerCustInfo[3].Gpio_Mode)) { + PK_DBG("[CAMERA LENS] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir + (PowerCustList.PowerCustInfo[3].Gpio_Pin, GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!!\n"); + } + if (mt_set_gpio_out + (PowerCustList.PowerCustInfo[3].Gpio_Pin, + PowerCustList.PowerCustInfo[3].Voltage)) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } + } +#endif + } else if (pwInfo.PowerType == PDN) { + PK_DBG("hwPowerDown: PDN %d\n", pwInfo.Voltage); + + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { + PK_DBG("[CAMERA LENS] set gpio mode failed!!\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!!\n"); + } + if (pwInfo.Voltage == Vol_High) { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON])) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + msleep(1); + } else { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + msleep(1); + } + } else if (pwInfo.PowerType == RST) { + PK_DBG("hwPowerDown: RST %d\n", pwInfo.Voltage); + if (pinSetIdx == 0) { +#ifndef CONFIG_MTK_MT6306_SUPPORT + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + if (pwInfo.Voltage == Vol_High) { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } else { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } +#else + if (mt6306_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (pwInfo.Voltage == Vol_High) { + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } else { + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } +#endif + } else if (pinSetIdx == 1) { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + if (pwInfo.Voltage == Vol_High) { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } else { + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG("[CAMERA LENS] set gpio failed!!\n"); + } + } + } + + } else if (pwInfo.PowerType == SensorMCLK) { + if (pinSetIdx == 0) { + ISP_MCLK1_EN(FALSE); + } else if (pinSetIdx == 1) { + ISP_MCLK2_EN(FALSE); + } + } else { + } + return TRUE; +} + + + + +int kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On, + char *mode_name) +{ + + int pwListIdx, pwIdx; + BOOL sensorInPowerList = KAL_FALSE; + + if (DUAL_CAMERA_MAIN_SENSOR == SensorIdx) { + pinSetIdx = 0; + } else if (DUAL_CAMERA_SUB_SENSOR == SensorIdx) { + pinSetIdx = 1; + } else if (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx) { + pinSetIdx = 2; + } + /* power ON */ + if (On) { + PK_DBG("kdCISModulePowerOn -on:currSensorName=%s pinSetIdx=%d\n", currSensorName, pinSetIdx); + + for (pwListIdx = 0; pwListIdx < 16; pwListIdx++) { + if (currSensorName && (PowerOnList.PowerSeq[pwListIdx].SensorName != NULL) + && (0 == + strcmp(PowerOnList.PowerSeq[pwListIdx].SensorName, + currSensorName))) { + //PK_DBG("sensorIdx:%d\n", SensorIdx); + + sensorInPowerList = KAL_TRUE; + + for (pwIdx = 0; pwIdx < 10; pwIdx++) { + if (PowerOnList.PowerSeq[pwListIdx].PowerInfo[pwIdx]. + PowerType != VDD_None) { + if (hwpoweron + (PowerOnList.PowerSeq[pwListIdx]. + PowerInfo[pwIdx], mode_name) == FALSE) + goto _kdCISModulePowerOn_exit_; + } else { + /* PK_DBG("pwIdx=%d\n", pwIdx); */ + break; + } + } + break; + } else if (PowerOnList.PowerSeq[pwListIdx].SensorName == NULL) { + break; + } else { + } + } + + /* Temp solution: default power on/off sequence */ + if (KAL_FALSE == sensorInPowerList) { + PK_DBG("Default power on sequence"); + + if (pinSetIdx == 0) { + ISP_MCLK1_EN(1); + } else if (pinSetIdx == 1) { + ISP_MCLK2_EN(1); + } + /* First Power Pin low and Reset Pin Low */ + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { + PK_DBG("[CAMERA LENS] set gpio mode failed!! (CMPDN)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!! (CMPDN)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { + PK_DBG("[CAMERA LENS] set gpio failed!! (CMPDN)\n"); + } + } + + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) { + if (0 == pinSetIdx) { +#ifndef CONFIG_MTK_MT6306_SUPPORT + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#else + if (mt6306_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#endif + } else { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } + } + /* VCAM_IO */ + if (TRUE != hwPowerOn(CAMERA_POWER_VCAM_D2, VOL_1800*1000, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to enable digital power (VCAM_IO), power id = %d\n", + CAMERA_POWER_VCAM_D2); + goto _kdCISModulePowerOn_exit_; + } + /* VCAM_A */ + if (TRUE != hwPowerOn(CAMERA_POWER_VCAM_A, VOL_2800*1000, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to enable analog power (VCAM_A), power id = %d\n", + CAMERA_POWER_VCAM_A); + goto _kdCISModulePowerOn_exit_; + } + + if (TRUE != hwPowerOn(CAMERA_POWER_VCAM_D, VOL_1800*1000, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to enable digital power (VCAM_D), power id = %d\n", + CAMERA_POWER_VCAM_D); + goto _kdCISModulePowerOn_exit_; + } + /* AF_VCC */ + if (TRUE != hwPowerOn(CAMERA_POWER_VCAM_A2, VOL_2800*1000, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to enable analog power (VCAM_AF), power id = %d\n", + CAMERA_POWER_VCAM_A2); + goto _kdCISModulePowerOn_exit_; + } + + mdelay(5); + + /* enable active sensor */ + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { + PK_DBG("[CAMERA LENS] set gpio mode failed!! (CMPDN)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!! (CMPDN)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON])) { + PK_DBG("[CAMERA LENS] set gpio failed!! (CMPDN)\n"); + } + } + + mdelay(1); + + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) { + if (0 == pinSetIdx) { +#ifndef CONFIG_MTK_MT6306_SUPPORT + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#else + if (mt6306_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#endif + + } else { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } + } + + + + + } + /* + if(pinSetIdx==0) + for(;;) + {} + */ + /* + if(pinSetIdx==1) + for(;;) + {} + */ + } else { /* power OFF */ + for (pwListIdx = 0; pwListIdx < 16; pwListIdx++) { + if (currSensorName && (PowerOnList.PowerSeq[pwListIdx].SensorName != NULL) + && (0 == + strcmp(PowerOnList.PowerSeq[pwListIdx].SensorName, + currSensorName))) { + PK_DBG("kdCISModulePowerOn -off:currSensorName=%s pinSetIdx=%d\n", currSensorName, pinSetIdx); + + sensorInPowerList = KAL_TRUE; + + for (pwIdx = 9; pwIdx >= 0; pwIdx--) { + if (PowerOnList.PowerSeq[pwListIdx].PowerInfo[pwIdx]. + PowerType != VDD_None) { + if (hwpowerdown + (PowerOnList.PowerSeq[pwListIdx]. + PowerInfo[pwIdx], mode_name) == FALSE) + goto _kdCISModulePowerOn_exit_; + if (pwIdx > 0) { + if (PowerOnList.PowerSeq[pwListIdx]. + PowerInfo[pwIdx - 1].Delay > 0) + mdelay(PowerOnList. + PowerSeq[pwListIdx]. + PowerInfo[pwIdx - 1].Delay); + } + } else { + //PK_DBG("pwIdx=%d\n", pwIdx); + } + } + } else if (PowerOnList.PowerSeq[pwListIdx].SensorName == NULL) { + break; + } else { + } + } + + /* Temp solution: default power on/off sequence */ + if (KAL_FALSE == sensorInPowerList) { + PK_DBG("Default power off sequence"); + + if (pinSetIdx == 0) { + ISP_MCLK1_EN(0); + } else if (pinSetIdx == 1) { + ISP_MCLK2_EN(0); + } + /* Set Power Pin low and Reset Pin Low */ + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { + PK_DBG("[CAMERA LENS] set gpio mode failed!! (CMPDN)\n"); + } + if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { + PK_DBG("[CAMERA LENS] set gpio dir failed!! (CMPDN)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMPDN], + pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { + PK_DBG("[CAMERA LENS] set gpio failed!! (CMPDN)\n"); + } + } + + + if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) { + if (0 == pinSetIdx) { +#ifndef CONFIG_MTK_MT6306_SUPPORT + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#else + if (mt6306_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt6306_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } +#endif + } else { + if (mt_set_gpio_mode + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_MODE])) { + PK_DBG + ("[CAMERA SENSOR] set gpio mode failed!! (CMRST)\n"); + } + if (mt_set_gpio_dir + (pinSet[pinSetIdx][IDX_PS_CMRST], GPIO_DIR_OUT)) { + PK_DBG + ("[CAMERA SENSOR] set gpio dir failed!! (CMRST)\n"); + } + if (mt_set_gpio_out + (pinSet[pinSetIdx][IDX_PS_CMRST], + pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF])) { + PK_DBG + ("[CAMERA SENSOR] set gpio failed!! (CMRST)\n"); + } + } + } + + + if (TRUE != hwPowerDown(CAMERA_POWER_VCAM_D, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to OFF core power (VCAM_D), power id = %d\n", + CAMERA_POWER_VCAM_D); + goto _kdCISModulePowerOn_exit_; + } + /* VCAM_A */ + if (TRUE != hwPowerDown(CAMERA_POWER_VCAM_A, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to OFF analog power (VCAM_A), power id= (%d)\n", + CAMERA_POWER_VCAM_A); + /* return -EIO; */ + goto _kdCISModulePowerOn_exit_; + } + /* VCAM_IO */ + if (TRUE != hwPowerDown(CAMERA_POWER_VCAM_D2, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to OFF digital power (VCAM_IO), power id = %d\n", + CAMERA_POWER_VCAM_D2); + /* return -EIO; */ + goto _kdCISModulePowerOn_exit_; + } + /* AF_VCC */ + if (TRUE != hwPowerDown(CAMERA_POWER_VCAM_A2, mode_name)) { + PK_DBG + ("[CAMERA SENSOR] Fail to OFF AF power (VCAM_AF), power id = %d\n", + CAMERA_POWER_VCAM_A2); + /* return -EIO; */ + goto _kdCISModulePowerOn_exit_; + } + + + + + + + + } + } /* */ + + return 0; + +_kdCISModulePowerOn_exit_: + return -EIO; +} +#endif +EXPORT_SYMBOL(kdCISModulePowerOn); + + +/* !-- */ +/* */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/kd_camera_hw.h b/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/kd_camera_hw.h new file mode 100755 index 0000000000000000000000000000000000000000..7afb34980e19fef925d1667e5de478c34695554a --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/camera_hw/kd_camera_hw.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _KD_CAMERA_HW_H_ +#define _KD_CAMERA_HW_H_ + +#include +#include "kd_camera_typedef.h" + +#ifdef CONFIG_MTK_LEGACY +#include + +#ifdef CONFIG_MTK_MT6306_SUPPORT +#include +#endif + + +#include +#include +#include "pmic_drv.h" + + + +/* */ +/* Power */ +#define CAMERA_POWER_VCAM_A PMIC_APP_MAIN_CAMERA_POWER_A +#define CAMERA_POWER_VCAM_D PMIC_APP_MAIN_CAMERA_POWER_D +#define CAMERA_POWER_VCAM_A2 PMIC_APP_MAIN_CAMERA_POWER_AF +#define CAMERA_POWER_VCAM_D2 PMIC_APP_MAIN_CAMERA_POWER_IO + +#define SUB_CAMERA_POWER_VCAM_D PMIC_APP_SUB_CAMERA_POWER_D + + +/* FIXME, should defined in DCT tool */ + +/* Main sensor */ +#ifdef CONFIG_MTK_MT6306_SUPPORT + /* Common phone's reset pin uses extension GPIO10 of mt6306 */ +#define CAMERA_CMRST_PIN GPIO10 +#define CAMERA_CMRST_PIN_M_GPIO GPIO_CAMERA_INVALID +#else +#ifdef GPIO_CAMERA_CMRST_PIN +#define CAMERA_CMRST_PIN GPIO_CAMERA_CMRST_PIN +#define CAMERA_CMRST_PIN_M_GPIO GPIO_CAMERA_CMRST_PIN_M_GPIO +#else /* For the case: both GPIO_CAMERA_CMRST_PIN & CONFIG_MTK_MT6306_SUPPORT is undefined */ +#define CAMERA_CMRST_PIN GPIO_CAMERA_INVALID +#define CAMERA_CMRST_PIN_M_GPIO GPIO_CAMERA_INVALID +#endif +#endif + + +#define CAMERA_CMPDN_PIN GPIO_CAMERA_CMPDN_PIN +#define CAMERA_CMPDN_PIN_M_GPIO GPIO_CAMERA_CMPDN_PIN_M_GPIO + +/* FRONT sensor */ +#define CAMERA_CMRST1_PIN GPIO_CAMERA_CMRST1_PIN +#define CAMERA_CMRST1_PIN_M_GPIO GPIO_CAMERA_CMRST1_PIN_M_GPIO + +#define CAMERA_CMPDN1_PIN GPIO_CAMERA_CMPDN1_PIN +#define CAMERA_CMPDN1_PIN_M_GPIO GPIO_CAMERA_CMPDN1_PIN_M_GPIO + + + +/* Define I2C Bus Num */ +#define SUPPORT_I2C_BUS_NUM1 I2C_CAMERA_MAIN_CHANNEL +#define SUPPORT_I2C_BUS_NUM2 I2C_CAMERA_SUB_CHANNEL + + +typedef enum { + VDD_None, + PDN, + RST, + SensorMCLK, + AVDD = CAMERA_POWER_VCAM_A, + DVDD = CAMERA_POWER_VCAM_D, + DOVDD = CAMERA_POWER_VCAM_D2, + AFVDD = CAMERA_POWER_VCAM_A2 +} PowerType; + +typedef enum { + Vol_Low = 0, + Vol_High = 1, + Vol_900 = VOL_0900, + Vol_1000 = VOL_1000, + Vol_1100 = VOL_1100, + Vol_1200 = VOL_1200, + Vol_1220 = VOL_1220, + Vol_1300 = VOL_1300, + Vol_1350 = VOL_1350, + Vol_1500 = VOL_1500, + Vol_1800 = VOL_1800, + Vol_2000 = VOL_2000, + Vol_2100 = VOL_2100, + Vol_2500 = VOL_2500, + Vol_2800 = VOL_2800, + Vol_3000 = VOL_3000, + Vol_3300 = VOL_3300, + Vol_3400 = VOL_3400, + Vol_3500 = VOL_3500, + Vol_3600 = VOL_3600 +} Voltage; +#else + +#define VOL2800 2800000 +#define VOL1800 1800000 +#define VOL1500 1500000 +#define VOL1200 1200000 +#define VOL1220 1220000 +#define VOL1000 1000000 +#define VOL1100 1100000 + +typedef enum { + VDD_None, + PDN, + RST, + SensorMCLK, + AVDD, + DVDD, + DOVDD, + AFVDD, + SUB_AVDD, + SUB_DVDD, + MAIN2_DVDD, +} PowerType; + +typedef enum { + Vol_Low = 0, + Vol_High = 1, + Vol_1000 = VOL1000, + Vol_1100 = VOL1100, + Vol_1200 = VOL1200, + Vol_1220 = VOL1220, + Vol_1500 = VOL1500, + Vol_1800 = VOL1800, + Vol_2800 = VOL2800, +} Voltage; +#define CAMERA_CMRST_PIN 0 +#define CAMERA_CMRST_PIN_M_GPIO 0 + +#define CAMERA_CMPDN_PIN 0 +#define CAMERA_CMPDN_PIN_M_GPIO 0 + +/* FRONT sensor */ +#define CAMERA_CMRST1_PIN 0 +#define CAMERA_CMRST1_PIN_M_GPIO 0 + +#define CAMERA_CMPDN1_PIN 0 +#define CAMERA_CMPDN1_PIN_M_GPIO 0 + +#define CAMERA_CMRST2_PIN 0 +#define CAMERA_CMRST2_PIN_M_GPIO 0 +#define CAMERA_CMPDN2_PIN 0 +#define CAMERA_CMPDN2_PIN_M_GPIO 0 + +#define GPIO_OUT_ONE 1 +#define GPIO_OUT_ZERO 0 +#define GPIO_UNSUPPORTED 0xff +#define GPIO_SUPPORTED 0 +#define GPIO_MODE_GPIO 0 + +#endif + + +typedef struct { + PowerType PowerType; + Voltage Voltage; + u32 Delay; +} PowerInformation; + + +typedef struct { + char *SensorName; + PowerInformation PowerInfo[12]; +} PowerSequence; + +typedef struct { + PowerSequence PowerSeq[16]; +} PowerUp; + +typedef struct { + u32 Gpio_Pin; + u32 Gpio_Mode; + Voltage Voltage; +} PowerCustInfo; + +typedef struct { + PowerCustInfo PowerCustInfo[7]; +} PowerCust; + +extern bool _hwPowerDown(PowerType type); +extern bool _hwPowerOn(PowerType type, int powerVolt); + +int mtkcam_gpio_set(int PinIdx, int PwrType, int Val); +int mtkcam_gpio_init(struct platform_device *pdev); + + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4ced1ce39da963ed32add6be58a1b8d5848255d3 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += gc0310_yuv_Sensor.o + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/gc0310_yuv_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/gc0310_yuv_Sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..8d57b62f84c8e9238387449b553ad30adb1b379c --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/gc0310_yuv_Sensor.c @@ -0,0 +1,2337 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * gc0310yuv_Sensor.c + * + * Project: + * -------- + * MAUI + * + * Description: + * ------------ + * Image sensor driver function + * V1.2.3 + * + * Author: + * ------- + * Leo + * + *============================================================= + * HISTORY + * Below this line, this part is controlled by GCoreinc. DO NOT MODIFY!! + *------------------------------------------------------------------------------ + * $Log$ + * 2012.02.29 kill bugs + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by GCoreinc. DO NOT MODIFY!! + *============================================================= + ******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" +#include "kd_camera_feature.h" + +#include "gc0310_yuv_Sensor.h" + + +static DEFINE_SPINLOCK(GC0310_drv_lock); + + +#define GC0310YUV_DEBUG + +#ifdef GC0310YUV_DEBUG +#define SENSORDB LOG_INF +#else +#define SENSORDB(x,...) +#endif + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "GC0310SPIYUV" +#define LOG_1 LOG_INF("GC0310,SERIAL CAM\n") +/**************************** Modify end *******************************************/ + +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +#define GC0310_TEST_PATTERN_CHECKSUM (0xb6e34f39) +#define GC0310_BANDING_50HZ 0 +#define GC0310_BANDING_60HZ 1 +#define I2C_SPEED 200 +kal_bool GC0310_night_mode_enable = KAL_FALSE; +kal_uint16 GC0310_CurStatus_AWB = 0; +kal_bool GC0310_banding_state = GC0310_BANDING_50HZ; // 0~50hz; 1~60hz + +static void GC0310_awb_enable(kal_bool enalbe); + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); + + +kal_uint16 GC0310_write_cmos_sensor(kal_uint8 addr, kal_uint8 para) +{ + char puSendCmd[2] = {(char)(addr & 0xFF) , (char)(para & 0xFF)}; + kdSetI2CSpeed(I2C_SPEED); + iWriteRegI2C(puSendCmd , 2, GC0310_WRITE_ID); + +} +/*kal_uint16 GC0310_read_cmos_sensor(kal_uint8 addr) +{ + kal_uint16 get_byte=0; + char puSendCmd = { (char)(addr & 0xFF) }; + iReadRegI2C(&puSendCmd , 1, (u8*)&get_byte, 1, GC0310_READ_ID); + + return get_byte; +}*/ + +kal_uint16 CamWriteCmosSensor(kal_uint8 addr, kal_uint8 para) +{ + char puSendCmd[2] = {(char)(addr & 0xFF) , (char)(para & 0xFF)}; + kdSetI2CSpeed(I2C_SPEED); + iWriteRegI2C(puSendCmd , 2, GC0310_WRITE_ID); +} + +static void write_cmos_sensor2(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[2] = {(char)(addr & 0xFF), (char)(para & 0xFF)}; + kdSetI2CSpeed(I2C_SPEED); + iWriteRegI2C(pu_send_cmd, 2, GC0310_WRITE_ID); + +} + + + +static kal_uint16 GC0310_read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[1] = {(char)(addr & 0xFF) }; + kdSetI2CSpeed(I2C_SPEED); + iReadRegI2C(pu_send_cmd, 1, (u8*)&get_byte, 1, GC0310_WRITE_ID); + + return get_byte; + +} + +/******************************************************************************* + * // Adapter for Winmo typedef + ********************************************************************************/ +#define WINMO_USE 0 + +#define Sleep(ms) mdelay(ms) +#define RETAILMSG(x,...) +#define TEXT + +kal_bool GC0310_MPEG4_encode_mode = KAL_FALSE; +kal_uint16 GC0310_dummy_pixels = 0, GC0310_dummy_lines = 0; +kal_bool GC0310_NIGHT_MODE = KAL_FALSE; + +kal_uint32 MINFramerate = 0; +kal_uint32 MAXFramerate = 0; + +kal_uint32 GC0310_isp_master_clock; +static kal_uint32 GC0310_g_fPV_PCLK = 30 * 1000000; + +kal_uint8 GC0310_sensor_write_I2C_address = GC0310_WRITE_ID; +kal_uint8 GC0310_sensor_read_I2C_address = GC0310_READ_ID; + +UINT8 GC0310PixelClockDivider=0; + +MSDK_SENSOR_CONFIG_STRUCT GC0310SensorConfigData; + +#define GC0310_SET_PAGE0 GC0310_write_cmos_sensor(0xfe, 0x00) +#define GC0310_SET_PAGE1 GC0310_write_cmos_sensor(0xfe, 0x01) +#define GC0310_SET_PAGE2 GC0310_write_cmos_sensor(0xfe, 0x02) +#define GC0310_SET_PAGE3 GC0310_write_cmos_sensor(0xfe, 0x03) + +/************************************************************************* + * FUNCTION + * GC0310_SetShutter + * + * DESCRIPTION + * This function set e-shutter of GC0310 to change exposure time. + * + * PARAMETERS + * iShutter : exposured lines + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +void GC0310_Set_Shutter(kal_uint16 iShutter) +{ +} /* Set_GC0310_Shutter */ + + +/************************************************************************* + * FUNCTION + * GC0310_read_Shutter + * + * DESCRIPTION + * This function read e-shutter of GC0310 . + * + * PARAMETERS + * None + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +kal_uint16 GC0310_Read_Shutter(void) +{ + kal_uint8 temp_reg1, temp_reg2; + kal_uint16 shutter; + + temp_reg1 = GC0310_read_cmos_sensor(0x04); + temp_reg2 = GC0310_read_cmos_sensor(0x03); + + shutter = (temp_reg1 & 0xFF) | (temp_reg2 << 8); + + return shutter; +} /* GC0310_read_shutter */ + +static void GC0310_Set_Mirrorflip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + switch (image_mirror) + { + case IMAGE_NORMAL://IMAGE_NORMAL: + GC0310_write_cmos_sensor(0x17,0x14);//bit[1][0] + // write_cmos_sensor(0x92,0x03); + // write_cmos_sensor(0x94,0x0b); + break; + case IMAGE_H_MIRROR://IMAGE_H_MIRROR: + GC0310_write_cmos_sensor(0x17,0x15); + // GC2355_write_cmos_sensor(0x92,0x03); + // GC2355_write_cmos_sensor(0x94,0x0b); + break; + case IMAGE_V_MIRROR://IMAGE_V_MIRROR: + GC0310_write_cmos_sensor(0x17,0x16); + // GC2355_write_cmos_sensor(0x92,0x02); + // GC2355_write_cmos_sensor(0x94,0x0b); + break; + case IMAGE_HV_MIRROR://IMAGE_HV_MIRROR: + GC0310_write_cmos_sensor(0x17,0x17); + // GC2355_write_cmos_sensor(0x92,0x02); + // GC2355_write_cmos_sensor(0x94,0x0b); + break; + } + + +} + +static void GC0310_set_AE_mode(kal_bool AE_enable) +{ + + LOG_INF("[GC0310]enter GC0310_set_AE_mode function, AE_enable = %d\n ", AE_enable); + if (AE_enable == KAL_TRUE) + { + // turn on AEC/AGC + LOG_INF("[GC0310]enter GC0310_set_AE_mode function 1\n "); + GC0310_write_cmos_sensor(0xfe, 0x00); + GC0310_write_cmos_sensor(0x4f, 0x01); + } + else + { + // turn off AEC/AGC + LOG_INF("[GC0310]enter GC0310_set_AE_mode function 2\n "); + GC0310_write_cmos_sensor(0xfe, 0x00); + GC0310_write_cmos_sensor(0x4f, 0x00); + } +} + + +void GC0310_set_contrast(UINT16 para) +{ + LOG_INF("[GC0310]CONTROLFLOW enter GC0310_set_contrast function:\n "); +#if 1 + switch (para) + { + case ISP_CONTRAST_LOW: + GC0310_write_cmos_sensor(0xd3, 0x30); + break; + case ISP_CONTRAST_HIGH: + GC0310_write_cmos_sensor(0xd3, 0x60); + break; + case ISP_CONTRAST_MIDDLE: + default: + GC0310_write_cmos_sensor(0xd3, 0x40); + break; + + } + LOG_INF("[GC0310]exit GC0310_set_contrast function:\n "); + return; +#endif +} + +UINT32 GC0310_MIPI_SetMaxFramerateByScenario( + MSDK_SCENARIO_ID_ENUM scenarioId, MUINT32 frameRate) +{ + LOG_INF("scenarioId = %d\n", scenarioId); +} + + +UINT32 GC0310SetTestPatternMode(kal_bool bEnable) +{ + LOG_INF("[GC0310SetTestPatternMode]test pattern bEnable:=%d\n",bEnable); + + if(bEnable) + { + GC0310_write_cmos_sensor(0xfe,0x00); + GC0310_write_cmos_sensor(0x40,0x08); + GC0310_write_cmos_sensor(0x41,0x00); + GC0310_write_cmos_sensor(0x42,0x00); + GC0310_write_cmos_sensor(0x4f,0x00); + GC0310_write_cmos_sensor(0xfe,0x00); + GC0310_write_cmos_sensor(0x03,0x03); + GC0310_write_cmos_sensor(0x04,0x9c); + GC0310_write_cmos_sensor(0x71,0x20); + GC0310_write_cmos_sensor(0x72,0x40); + GC0310_write_cmos_sensor(0x73,0x80); + GC0310_write_cmos_sensor(0x74,0x80); + GC0310_write_cmos_sensor(0x75,0x80); + GC0310_write_cmos_sensor(0x76,0x80); + GC0310_write_cmos_sensor(0x7a,0x80); + GC0310_write_cmos_sensor(0x7b,0x80); + GC0310_write_cmos_sensor(0x7c,0x80); + GC0310_write_cmos_sensor(0x77,0x40); + GC0310_write_cmos_sensor(0x78,0x40); + GC0310_write_cmos_sensor(0x79,0x40); + GC0310_write_cmos_sensor(0xfe,0x00); + GC0310_write_cmos_sensor(0xfe,0x01); + GC0310_write_cmos_sensor(0x12,0x00); + GC0310_write_cmos_sensor(0x13,0x30); + GC0310_write_cmos_sensor(0x44,0x00); + GC0310_write_cmos_sensor(0x45,0x00); + GC0310_write_cmos_sensor(0xfe,0x00); + GC0310_write_cmos_sensor(0xd0,0x40); + GC0310_write_cmos_sensor(0xd1,0x20); + GC0310_write_cmos_sensor(0xd2,0x20); + GC0310_write_cmos_sensor(0xd3,0x40); + GC0310_write_cmos_sensor(0xd5,0x00); + GC0310_write_cmos_sensor(0xd8,0x00); + GC0310_write_cmos_sensor(0xdd,0x00); + GC0310_write_cmos_sensor(0xde,0x00); + GC0310_write_cmos_sensor(0xe4,0x00); + GC0310_write_cmos_sensor(0xeb,0x00); + GC0310_write_cmos_sensor(0xa4,0x00); + GC0310_write_cmos_sensor(0x4c,0x21); + + GC0310_write_cmos_sensor(0xfe,0x00); + + + } + else + { + GC0310_write_cmos_sensor(0xfe, 0x00); + GC0310_write_cmos_sensor(0x4c, 0x20); + GC0310_write_cmos_sensor(0xfe, 0x00); + } + + return ERROR_NONE; +} + + +void GC0310_set_brightness(UINT16 para) +{ + + LOG_INF("[GC0310]CONTROLFLOW enter GC0310_set_brightness function:\n "); +#if 1 + //return; + switch (para) + { + case ISP_BRIGHT_LOW: + GC0310_SET_PAGE0; + GC0310_write_cmos_sensor(0xd5, 0xc0); + break; + case ISP_BRIGHT_HIGH: + GC0310_SET_PAGE0; + GC0310_write_cmos_sensor(0xd5, 0x40); + break; + case ISP_BRIGHT_MIDDLE: + default: + GC0310_SET_PAGE0; + GC0310_write_cmos_sensor(0xd5, 0x00); + break; + } + LOG_INF("[GC0310]exit GC0310_set_brightness function:\n "); + return; +#endif +} +void GC0310_set_saturation(UINT16 para) +{ + LOG_INF("[GC0310]CONTROLFLOW enter GC0310_set_saturation function:\n "); + + switch (para) + { + case ISP_SAT_HIGH: + GC0310_write_cmos_sensor(0xfe, 0x00); + GC0310_write_cmos_sensor(0xd1, 0x45); + GC0310_write_cmos_sensor(0xd2, 0x45); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + case ISP_SAT_LOW: + GC0310_write_cmos_sensor(0xfe, 0x00); + GC0310_write_cmos_sensor(0xd1, 0x28); + GC0310_write_cmos_sensor(0xd2, 0x28); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + case ISP_SAT_MIDDLE: + default: + GC0310_write_cmos_sensor(0xfe, 0x00); + GC0310_write_cmos_sensor(0xd1, 0x34); + GC0310_write_cmos_sensor(0xd2, 0x34); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + // return KAL_FALSE; + // break; + } + LOG_INF("[GC0310]exit GC0310_set_saturation function:\n "); + return; + +} + +void GC0310_set_iso(UINT16 para) +{ + + LOG_INF("[GC0310]CONTROLFLOW GC0310_set_iso AEC p0:0x4f %d: shutter %d\n",GC0310_read_cmos_sensor(0x4f),GC0310_Read_Shutter()); + switch (para) + { + case AE_ISO_100: + //ISO 100 + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x1f, 0x20); + GC0310_write_cmos_sensor(0x20, 0x40); + GC0310_write_cmos_sensor(0x44, 0x00); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + case AE_ISO_200: + //ISO 200 + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x1f, 0x20); + GC0310_write_cmos_sensor(0x20, 0x80); + GC0310_write_cmos_sensor(0x44, 0x02); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + case AE_ISO_400: + //ISO 400 + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x1f, 0x30); + GC0310_write_cmos_sensor(0x20, 0xc0); + GC0310_write_cmos_sensor(0x44, 0x02); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + case AE_ISO_AUTO: + default: + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x1f, 0x30); + GC0310_write_cmos_sensor(0x20, 0xc0); + GC0310_write_cmos_sensor(0x44, 0x03); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + } + return; +} + + + +void GC0310StreamOn(void) +{ +return; + GC0310_write_cmos_sensor(0xfe,0x03); + GC0310_write_cmos_sensor(0xf3,0x83); + GC0310_write_cmos_sensor(0xfe,0x00); + Sleep(50); +} + +void GC0310_MIPI_GetDelayInfo(uintptr_t delayAddr) +{ + SENSOR_DELAY_INFO_STRUCT* pDelayInfo = (SENSOR_DELAY_INFO_STRUCT*)delayAddr; + pDelayInfo->InitDelay = 2; + pDelayInfo->EffectDelay = 2; + pDelayInfo->AwbDelay = 2; + pDelayInfo->AFSwitchDelayFrame = 50; + pDelayInfo->ContrastDelay = 1; + pDelayInfo->EvDelay = 0; + pDelayInfo->BrightDelay = 1; + pDelayInfo->SatDelay = 0; +} + +UINT32 GC0310_MIPI_GetDefaultFramerateByScenario( + MSDK_SCENARIO_ID_ENUM scenarioId, MUINT32 *pframeRate) +{ + switch (scenarioId) + { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *pframeRate = 300; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + case MSDK_SCENARIO_ID_CAMERA_ZSD: + *pframeRate = 300; + break; + case MSDK_SCENARIO_ID_CAMERA_3D_PREVIEW: //added + case MSDK_SCENARIO_ID_CAMERA_3D_VIDEO: + case MSDK_SCENARIO_ID_CAMERA_3D_CAPTURE: //added + *pframeRate = 300; + break; + default: + *pframeRate = 300; + break; + } + + return ERROR_NONE; +} + +void GC0310_MIPI_SetMaxMinFps(UINT32 u2MinFrameRate, UINT32 u2MaxFrameRate) +{ + LOG_INF("GC0310_MIPI_SetMaxMinFps+ :FrameRate= %d %d\n",u2MinFrameRate,u2MaxFrameRate); + spin_lock(&GC0310_drv_lock); + MINFramerate = u2MinFrameRate; + MAXFramerate = u2MaxFrameRate; + spin_unlock(&GC0310_drv_lock); + return; +} + +void GC0310_3ACtrl(ACDK_SENSOR_3A_LOCK_ENUM action) +{ + LOG_INF("[GC0329]enter ACDK_SENSOR_3A_LOCK_ENUM function:action=%d\n",action); + switch (action) + { + case SENSOR_3A_AE_LOCK: + GC0310_set_AE_mode(KAL_FALSE); + break; + case SENSOR_3A_AE_UNLOCK: + GC0310_set_AE_mode(KAL_TRUE); + break; + + case SENSOR_3A_AWB_LOCK: + GC0310_awb_enable(KAL_FALSE); + break; + + case SENSOR_3A_AWB_UNLOCK: + if (((AWB_MODE_OFF == GC0310_CurStatus_AWB) || + (AWB_MODE_AUTO == GC0310_CurStatus_AWB))) + { + GC0310_awb_enable(KAL_TRUE); + } + break; + default: + break; + } + LOG_INF("[GC0329]exit ACDK_SENSOR_3A_LOCK_ENUM function:action=%d\n",action); + return; +} + + +void GC0310_MIPI_GetExifInfo(uintptr_t exifAddr) +{ + SENSOR_EXIF_INFO_STRUCT* pExifInfo = (SENSOR_EXIF_INFO_STRUCT*)exifAddr; + pExifInfo->FNumber = 28; + GC0310_write_cmos_sensor(0xfe, 0x00); + + int preGain =GC0310_read_cmos_sensor(0x71); + int postGain =GC0310_read_cmos_sensor(0x72); + + + if(!(postGain>0x40)){ + pExifInfo->RealISOValue = AE_ISO_100; + }else if(!(postGain>0x80)){ + pExifInfo->RealISOValue = AE_ISO_200; + }else if(!(postGain>0xc0)){ + pExifInfo->RealISOValue = AE_ISO_400; + }else { + pExifInfo->RealISOValue = AE_ISO_400; + } + LOG_INF("[GC0310]GC0310_MIPI_GetExifInfo preGain=0x%x postGain=0x%x iso=%d\n",preGain,postGain,pExifInfo->RealISOValue); +// pExifInfo->AEISOSpeed = GC0310_Driver.isoSpeed; +// pExifInfo->AWBMode = S5K4ECGX_Driver.awbMode; +// pExifInfo->CapExposureTime = S5K4ECGX_Driver.capExposureTime; +// pExifInfo->FlashLightTimeus = 0; +// pExifInfo->RealISOValue = (S5K4ECGX_MIPI_ReadGain()*57) >> 8; + //S5K4ECGX_Driver.isoSpeed; +} + +#if 0 +void GC0310_MIPI_get_AEAWB_lock(uintptr_t pAElockRet32, uintptr_t pAWBlockRet32) +{ + *pAElockRet32 = 1; + *pAWBlockRet32 = 1; + LOG_INF("[GC0310]GetAEAWBLock,AE=%d ,AWB=%d\n,",(int)*pAElockRet32, (int)*pAWBlockRet32); +} +#endif + +/************************************************************************* + * FUNCTION + * GC0310_write_reg + * + * DESCRIPTION + * This function set the register of GC0310. + * + * PARAMETERS + * addr : the register index of GC0310 + * para : setting parameter of the specified register of GC0310 + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +void GC0310_write_reg(kal_uint32 addr, kal_uint32 para) +{ + GC0310_write_cmos_sensor(addr, para); +} /* GC0310_write_reg() */ + + +/************************************************************************* + * FUNCTION + * GC0310_read_cmos_sensor + * + * DESCRIPTION + * This function read parameter of specified register from GC0310. + * + * PARAMETERS + * addr : the register index of GC0310 + * + * RETURNS + * the data that read from GC0310 + * + * GLOBALS AFFECTED + * + *************************************************************************/ +kal_uint32 GC0310_read_reg(kal_uint32 addr) +{ + return GC0310_read_cmos_sensor(addr); +} /* OV7670_read_reg() */ + + +/************************************************************************* +* FUNCTION +* GC0310_awb_enable +* +* DESCRIPTION +* This function enable or disable the awb (Auto White Balance). +* +* PARAMETERS +* 1. kal_bool : KAL_TRUE - enable awb, KAL_FALSE - disable awb. +* +* RETURNS +* kal_bool : It means set awb right or not. +* +*************************************************************************/ +static void GC0310_awb_enable(kal_bool enalbe) +{ + kal_uint16 temp_AWB_reg = 0; + + GC0310_write_cmos_sensor(0xfe, 0x00); + temp_AWB_reg = GC0310_read_cmos_sensor(0x42); + + if (enalbe) + { + GC0310_write_cmos_sensor(0x42, (temp_AWB_reg |0x02)); + } + else + { + GC0310_write_cmos_sensor(0x42, (temp_AWB_reg & (~0x02))); + } + GC0310_write_cmos_sensor(0xfe, 0x00); + +} + + +/************************************************************************* +* FUNCTION +* GC0310_GAMMA_Select +* +* DESCRIPTION +* This function is served for FAE to select the appropriate GAMMA curve. +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +void GC0310GammaSelect(kal_uint32 GammaLvl) +{ + switch(GammaLvl) + { + case GC0310_RGB_Gamma_m1: //smallest gamma curve + GC0310_write_cmos_sensor(0xfe, 0x00); + GC0310_write_cmos_sensor(0xbf, 0x06); + GC0310_write_cmos_sensor(0xc0, 0x12); + GC0310_write_cmos_sensor(0xc1, 0x22); + GC0310_write_cmos_sensor(0xc2, 0x35); + GC0310_write_cmos_sensor(0xc3, 0x4b); + GC0310_write_cmos_sensor(0xc4, 0x5f); + GC0310_write_cmos_sensor(0xc5, 0x72); + GC0310_write_cmos_sensor(0xc6, 0x8d); + GC0310_write_cmos_sensor(0xc7, 0xa4); + GC0310_write_cmos_sensor(0xc8, 0xb8); + GC0310_write_cmos_sensor(0xc9, 0xc8); + GC0310_write_cmos_sensor(0xca, 0xd4); + GC0310_write_cmos_sensor(0xcb, 0xde); + GC0310_write_cmos_sensor(0xcc, 0xe6); + GC0310_write_cmos_sensor(0xcd, 0xf1); + GC0310_write_cmos_sensor(0xce, 0xf8); + GC0310_write_cmos_sensor(0xcf, 0xfd); + break; + case GC0310_RGB_Gamma_m2: + GC0310_write_cmos_sensor(0xBF, 0x08); + GC0310_write_cmos_sensor(0xc0, 0x0F); + GC0310_write_cmos_sensor(0xc1, 0x21); + GC0310_write_cmos_sensor(0xc2, 0x32); + GC0310_write_cmos_sensor(0xc3, 0x43); + GC0310_write_cmos_sensor(0xc4, 0x50); + GC0310_write_cmos_sensor(0xc5, 0x5E); + GC0310_write_cmos_sensor(0xc6, 0x78); + GC0310_write_cmos_sensor(0xc7, 0x90); + GC0310_write_cmos_sensor(0xc8, 0xA6); + GC0310_write_cmos_sensor(0xc9, 0xB9); + GC0310_write_cmos_sensor(0xcA, 0xC9); + GC0310_write_cmos_sensor(0xcB, 0xD6); + GC0310_write_cmos_sensor(0xcC, 0xE0); + GC0310_write_cmos_sensor(0xcD, 0xEE); + GC0310_write_cmos_sensor(0xcE, 0xF8); + GC0310_write_cmos_sensor(0xcF, 0xFF); + break; + + case GC0310_RGB_Gamma_m3: + GC0310_write_cmos_sensor(0xbf , 0x0b); + GC0310_write_cmos_sensor(0xc0 , 0x17); + GC0310_write_cmos_sensor(0xc1 , 0x2a); + GC0310_write_cmos_sensor(0xc2 , 0x41); + GC0310_write_cmos_sensor(0xc3 , 0x54); + GC0310_write_cmos_sensor(0xc4 , 0x66); + GC0310_write_cmos_sensor(0xc5 , 0x74); + GC0310_write_cmos_sensor(0xc6 , 0x8c); + GC0310_write_cmos_sensor(0xc7 , 0xa3); + GC0310_write_cmos_sensor(0xc8 , 0xb5); + GC0310_write_cmos_sensor(0xc9 , 0xc4); + GC0310_write_cmos_sensor(0xca , 0xd0); + GC0310_write_cmos_sensor(0xcb , 0xdb); + GC0310_write_cmos_sensor(0xcc , 0xe5); + GC0310_write_cmos_sensor(0xcd , 0xf0); + GC0310_write_cmos_sensor(0xce , 0xf7); + GC0310_write_cmos_sensor(0xcf , 0xff); + break; + + case GC0310_RGB_Gamma_m4: + GC0310_write_cmos_sensor(0xBF, 0x0E); + GC0310_write_cmos_sensor(0xc0, 0x1C); + GC0310_write_cmos_sensor(0xc1, 0x34); + GC0310_write_cmos_sensor(0xc2, 0x48); + GC0310_write_cmos_sensor(0xc3, 0x5A); + GC0310_write_cmos_sensor(0xc4, 0x6B); + GC0310_write_cmos_sensor(0xc5, 0x7B); + GC0310_write_cmos_sensor(0xc6, 0x95); + GC0310_write_cmos_sensor(0xc7, 0xAB); + GC0310_write_cmos_sensor(0xc8, 0xBF); + GC0310_write_cmos_sensor(0xc9, 0xCE); + GC0310_write_cmos_sensor(0xcA, 0xD9); + GC0310_write_cmos_sensor(0xcB, 0xE4); + GC0310_write_cmos_sensor(0xcC, 0xEC); + GC0310_write_cmos_sensor(0xcD, 0xF7); + GC0310_write_cmos_sensor(0xcE, 0xFD); + GC0310_write_cmos_sensor(0xcF, 0xFF); + break; + + case GC0310_RGB_Gamma_m5: + GC0310_write_cmos_sensor(0xBF, 0x10); + GC0310_write_cmos_sensor(0xc0, 0x20); + GC0310_write_cmos_sensor(0xc1, 0x38); + GC0310_write_cmos_sensor(0xc2, 0x4E); + GC0310_write_cmos_sensor(0xc3, 0x63); + GC0310_write_cmos_sensor(0xc4, 0x76); + GC0310_write_cmos_sensor(0xc5, 0x87); + GC0310_write_cmos_sensor(0xc6, 0xA2); + GC0310_write_cmos_sensor(0xc7, 0xB8); + GC0310_write_cmos_sensor(0xc8, 0xCA); + GC0310_write_cmos_sensor(0xc9, 0xD8); + GC0310_write_cmos_sensor(0xcA, 0xE3); + GC0310_write_cmos_sensor(0xcB, 0xEB); + GC0310_write_cmos_sensor(0xcC, 0xF0); + GC0310_write_cmos_sensor(0xcD, 0xF8); + GC0310_write_cmos_sensor(0xcE, 0xFD); + GC0310_write_cmos_sensor(0xcF, 0xFF); + break; + + case GC0310_RGB_Gamma_m6: // largest gamma curve + GC0310_write_cmos_sensor(0xBF, 0x14); + GC0310_write_cmos_sensor(0xc0, 0x28); + GC0310_write_cmos_sensor(0xc1, 0x44); + GC0310_write_cmos_sensor(0xc2, 0x5D); + GC0310_write_cmos_sensor(0xc3, 0x72); + GC0310_write_cmos_sensor(0xc4, 0x86); + GC0310_write_cmos_sensor(0xc5, 0x95); + GC0310_write_cmos_sensor(0xc6, 0xB1); + GC0310_write_cmos_sensor(0xc7, 0xC6); + GC0310_write_cmos_sensor(0xc8, 0xD5); + GC0310_write_cmos_sensor(0xc9, 0xE1); + GC0310_write_cmos_sensor(0xcA, 0xEA); + GC0310_write_cmos_sensor(0xcB, 0xF1); + GC0310_write_cmos_sensor(0xcC, 0xF5); + GC0310_write_cmos_sensor(0xcD, 0xFB); + GC0310_write_cmos_sensor(0xcE, 0xFE); + GC0310_write_cmos_sensor(0xcF, 0xFF); + break; + case GC0310_RGB_Gamma_night: //Gamma for night mode + GC0310_write_cmos_sensor(0xBF, 0x0B); + GC0310_write_cmos_sensor(0xc0, 0x16); + GC0310_write_cmos_sensor(0xc1, 0x29); + GC0310_write_cmos_sensor(0xc2, 0x3C); + GC0310_write_cmos_sensor(0xc3, 0x4F); + GC0310_write_cmos_sensor(0xc4, 0x5F); + GC0310_write_cmos_sensor(0xc5, 0x6F); + GC0310_write_cmos_sensor(0xc6, 0x8A); + GC0310_write_cmos_sensor(0xc7, 0x9F); + GC0310_write_cmos_sensor(0xc8, 0xB4); + GC0310_write_cmos_sensor(0xc9, 0xC6); + GC0310_write_cmos_sensor(0xcA, 0xD3); + GC0310_write_cmos_sensor(0xcB, 0xDD); + GC0310_write_cmos_sensor(0xcC, 0xE5); + GC0310_write_cmos_sensor(0xcD, 0xF1); + GC0310_write_cmos_sensor(0xcE, 0xFA); + GC0310_write_cmos_sensor(0xcF, 0xFF); + break; + default: + //GC0310_RGB_Gamma_m1 + GC0310_write_cmos_sensor(0xfe, 0x00); + GC0310_write_cmos_sensor(0xbf , 0x0b); + GC0310_write_cmos_sensor(0xc0 , 0x17); + GC0310_write_cmos_sensor(0xc1 , 0x2a); + GC0310_write_cmos_sensor(0xc2 , 0x41); + GC0310_write_cmos_sensor(0xc3 , 0x54); + GC0310_write_cmos_sensor(0xc4 , 0x66); + GC0310_write_cmos_sensor(0xc5 , 0x74); + GC0310_write_cmos_sensor(0xc6 , 0x8c); + GC0310_write_cmos_sensor(0xc7 , 0xa3); + GC0310_write_cmos_sensor(0xc8 , 0xb5); + GC0310_write_cmos_sensor(0xc9 , 0xc4); + GC0310_write_cmos_sensor(0xca , 0xd0); + GC0310_write_cmos_sensor(0xcb , 0xdb); + GC0310_write_cmos_sensor(0xcc , 0xe5); + GC0310_write_cmos_sensor(0xcd , 0xf0); + GC0310_write_cmos_sensor(0xce , 0xf7); + GC0310_write_cmos_sensor(0xcf , 0xff); + break; + } +} + + +/************************************************************************* + * FUNCTION + * GC0310_config_window + * + * DESCRIPTION + * This function config the hardware window of GC0310 for getting specified + * data of that window. + * + * PARAMETERS + * start_x : start column of the interested window + * start_y : start row of the interested window + * width : column widht of the itnerested window + * height : row depth of the itnerested window + * + * RETURNS + * the data that read from GC0310 + * + * GLOBALS AFFECTED + * + *************************************************************************/ +void GC0310_config_window(kal_uint16 startx, kal_uint16 starty, kal_uint16 width, kal_uint16 height) +{ +} /* GC0310_config_window */ + + +/************************************************************************* + * FUNCTION + * GC0310_SetGain + * + * DESCRIPTION + * This function is to set global gain to sensor. + * + * PARAMETERS + * iGain : sensor global gain(base: 0x40) + * + * RETURNS + * the actually gain set to sensor. + * + * GLOBALS AFFECTED + * + *************************************************************************/ +kal_uint16 GC0310_SetGain(kal_uint16 iGain) +{ + return iGain; +} +/************************************************************************* +* FUNCTION +* GC0310_Sensor_Init +* +* DESCRIPTION +* This function apply all of the initial setting to sensor. +* +* PARAMETERS +* None +* +* RETURNS +* None +* +*************************************************************************/ +void GC0310_Sensor_Init(void) +{ + //VGA setting +///////////////////////////////////////////////// +///////////////// system reg ///////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0xfe,0xf0); +CamWriteCmosSensor(0xfe,0xf0); +CamWriteCmosSensor(0xfe,0x00); + +CamWriteCmosSensor(0xfc,0x16); //4e +CamWriteCmosSensor(0xfc,0x16); //4e // [0]apwd [6]regf_clk_gate +CamWriteCmosSensor(0xf2,0x07); //sync output +CamWriteCmosSensor(0xf3,0x83); //ff//1f//01 data output +CamWriteCmosSensor(0xf5,0x07); //sck_dely +CamWriteCmosSensor(0xf7,0x88); //f8//fd +CamWriteCmosSensor(0xf8,0x00); +CamWriteCmosSensor(0xf9,0x4f); //0f//01 +CamWriteCmosSensor(0xfa,0x10); //10: 2-lane, 32:1-lane ,ic.hsu +CamWriteCmosSensor(0xfc,0xce); +CamWriteCmosSensor(0xfd,0x00); + +///////////////////////////////////////////////// + ///////////////// CISCTL reg ///////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0x00,0x2f); //2f//0f//02//01gA1U2DOX +CamWriteCmosSensor(0x01,0x0f); //06 +CamWriteCmosSensor(0x02,0x04); +#if 1 +CamWriteCmosSensor(0x03,0x01); +CamWriteCmosSensor(0x04,0x89); +CamWriteCmosSensor(0x05,0x00); +CamWriteCmosSensor(0x06,0x6a); //HB +CamWriteCmosSensor(0x07,0x00); +CamWriteCmosSensor(0x08,0x0A); //VB + +#else + +CamWriteCmosSensor(0x03,0x01); +CamWriteCmosSensor(0x04,0xea); +CamWriteCmosSensor(0x05,0x00); +CamWriteCmosSensor(0x06,0xa3); //HB +CamWriteCmosSensor(0x07,0x00); +CamWriteCmosSensor(0x08,0x12); //VB +#endif +CamWriteCmosSensor(0x09,0x00); //row start +CamWriteCmosSensor(0x0a,0x00); // +CamWriteCmosSensor(0x0b,0x00); //col start +CamWriteCmosSensor(0x0c,0x06); +CamWriteCmosSensor(0x0d,0x01); //height +CamWriteCmosSensor(0x0e,0xe8); //height +CamWriteCmosSensor(0x0f,0x02); //width +CamWriteCmosSensor(0x10,0x88); //height +CamWriteCmosSensor(0x11,0x10); //0x10 : 66.62ms, 0x11 : 66.75ms +CamWriteCmosSensor(0x12,0x02); //ST +CamWriteCmosSensor(0x13,0x02); //ET +CamWriteCmosSensor(0x17,0x14); +CamWriteCmosSensor(0x18,0x0a); //0a//[4]double reset +CamWriteCmosSensor(0x19,0x14); //AD pipeline +CamWriteCmosSensor(0x1b,0x48); +CamWriteCmosSensor(0x1e,0x6b); //3b//col bias +CamWriteCmosSensor(0x1f,0x28); //20//00//08//txlow +CamWriteCmosSensor(0x20,0x89); //88//0c//[3:2]DA15 +CamWriteCmosSensor(0x21,0x49); //48//[3] txhigh +CamWriteCmosSensor(0x22,0xb0); +CamWriteCmosSensor(0x23,0x04); //[1:0]vcm_r +CamWriteCmosSensor(0x24,0xff); //Cy?AUA|//15 +CamWriteCmosSensor(0x34,0x20); //[6:4] rsg high//Oo?Orange + +///////////////////////////////////////////////// +//////////////////// BLK //////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0x26,0x23); //[1]dark_current_en [0]offset_en +CamWriteCmosSensor(0x28,0xff); //BLK_limie_value +CamWriteCmosSensor(0x29,0x00); //global offset +CamWriteCmosSensor(0x33,0x18); //offset_ratio +CamWriteCmosSensor(0x37,0x20); //dark_current_ratio +CamWriteCmosSensor(0x47,0x80); //a7 +CamWriteCmosSensor(0x4e,0x66); //select_row +CamWriteCmosSensor(0xa8,0x02); //win_width_dark, same with crop_win_width +CamWriteCmosSensor(0xa9,0x80); + +///////////////////////////////////////////////// +////////////////// ISP reg /////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0x40,0x7f);//48 +CamWriteCmosSensor(0x41,0x21);//00//[0]curve_en +CamWriteCmosSensor(0x42,0xcf); //0a//[1]awn_en +CamWriteCmosSensor(0x44,0x02); +CamWriteCmosSensor(0x46,0x02); //03//sync +CamWriteCmosSensor(0x4a,0x11); +CamWriteCmosSensor(0x4b,0x01); +CamWriteCmosSensor(0x4c,0x20);//00[5]pretect exp +CamWriteCmosSensor(0x4d,0x05);//update gain mode +CamWriteCmosSensor(0x4f,0x01); +CamWriteCmosSensor(0x50,0x01);//crop enable +CamWriteCmosSensor(0x55,0x01);//crop window height +CamWriteCmosSensor(0x56,0xe0); +CamWriteCmosSensor(0x57,0x02);//crop window width +CamWriteCmosSensor(0x58,0x80); + +///////////////////////////////////////////////// +/////////////////// GAIN //////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0x70,0x50); //70 //80//global gain +CamWriteCmosSensor(0x5a,0x98);//84//analog gain 0 +CamWriteCmosSensor(0x5b,0xdc);//c9 +CamWriteCmosSensor(0x5c,0xfe);//ed//not use pga gain highest level + +//CamWriteCmosSensor(0x77,0x74);//awb gain +//CamWriteCmosSensor(0x78,0x40); +//CamWriteCmosSensor(0x79,0x5f); + +CamWriteCmosSensor(0x7a,0x80); //R ratio///////////////////////////////////////////////// +/////////////////// DNDD ///////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0x82,0x05); //05 +CamWriteCmosSensor(0x83,0x0b); + +///////////////////////////////////////////////// + ////////////////// EEINTP //////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0x8f,0xff);//skin th +CamWriteCmosSensor(0x90,0x8c); +CamWriteCmosSensor(0x92,0x08);//10//05 +CamWriteCmosSensor(0x93,0x03);//10//00 +CamWriteCmosSensor(0x95,0x53);//88 +CamWriteCmosSensor(0x96,0x56);//88 + +///////////////////////////////////////////////// + ///////////////////// ASDE //////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0xfe,0x00); + +CamWriteCmosSensor(0x9a,0x20); //Y_limit +CamWriteCmosSensor(0x9b,0xb0); //Y_slope +CamWriteCmosSensor(0x9c,0x40); //LSC_th +CamWriteCmosSensor(0x9d,0xa0); //80//LSC_slope + +CamWriteCmosSensor(0xa1,0xf0);//00 +CamWriteCmosSensor(0xa2,0x32); //12 +CamWriteCmosSensor(0xa4,0x30); //Sat_slope +CamWriteCmosSensor(0xa5,0x30); //Sat_limit +CamWriteCmosSensor(0xaa,0x50); //OT_th +CamWriteCmosSensor(0xac,0x22); //DN_slope_low + +///////////////////////////////////////////////// + /////////////////// YCP ////////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0xd0,0x40); +CamWriteCmosSensor(0xd1,0x2b);//28//38 +CamWriteCmosSensor(0xd2,0x2b);//28//38 +CamWriteCmosSensor(0xd3,0x40);//3c +CamWriteCmosSensor(0xd6,0xf2); +CamWriteCmosSensor(0xd7,0x1b); +CamWriteCmosSensor(0xd8,0x18); +CamWriteCmosSensor(0xdd,0x73);//no edge dec saturation + +///////////////////////////////////////////////// + //////////////////// AEC //////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0xfe,0x01); +CamWriteCmosSensor(0x05,0x30); //40//AEC_center-x1 X16 +CamWriteCmosSensor(0x06,0x75); //70//X2 +CamWriteCmosSensor(0x07,0x40); //60//Y1 X8 +CamWriteCmosSensor(0x08,0xb0); //90//Y2 +CamWriteCmosSensor(0x0a,0xc5);//c1//81//81//01//f +CamWriteCmosSensor(0x12,0x52); +CamWriteCmosSensor(0x13,0x35); //28 //78//Y target + +CamWriteCmosSensor(0x1f,0x30); //QQ +CamWriteCmosSensor(0x20,0xc0); //QQ 80 +GC0310_write_cmos_sensor(0x25,0x00); //step +GC0310_write_cmos_sensor(0x26,0x96); + +CamWriteCmosSensor(0x27,0x01); //30fps +CamWriteCmosSensor(0x28,0xc2); +CamWriteCmosSensor(0x29,0x02); //25fps +CamWriteCmosSensor(0x2a,0x58); +CamWriteCmosSensor(0x2b,0x02); //20fps +CamWriteCmosSensor(0x2c,0xee); +CamWriteCmosSensor(0x2d,0x04); //15fps +CamWriteCmosSensor(0x2e,0x1a); +CamWriteCmosSensor(0x3c,0x00); +CamWriteCmosSensor(0x3e,0x40); //40 +CamWriteCmosSensor(0x3f,0x5c); //57 +CamWriteCmosSensor(0x40,0x7b); //7d +CamWriteCmosSensor(0x41,0xbd); //a7 +CamWriteCmosSensor(0x42,0xf6); //01 +CamWriteCmosSensor(0x43,0x63); //4e +//CamWriteCmosSensor(0x04,0xe3); +CamWriteCmosSensor(0x03,0x60); //70 + +CamWriteCmosSensor(0x44,0x03);//04 +///////////////////////////////////////////////// + //////////////////// AWB //////////////////// +///////////////////////////////////////////////// + +CamWriteCmosSensor(0x1c,0x91);//21 //luma_level_for_awb_select + +CamWriteCmosSensor(0x61,0x9e); +CamWriteCmosSensor(0x62,0xa5); +CamWriteCmosSensor(0x63,0xd0);//a0//d0//a0//a0 x1-th +CamWriteCmosSensor(0x64,0x20); +CamWriteCmosSensor(0x65,0x06);//60 +CamWriteCmosSensor(0x66,0x02);//02//04 +CamWriteCmosSensor(0x67,0x84);//82//82 +CamWriteCmosSensor(0x6b,0x20);//40//00//40 +CamWriteCmosSensor(0x6c,0x10);//00 +CamWriteCmosSensor(0x6d,0x32);//00 +CamWriteCmosSensor(0x6e,0x38);//f8//38//indoor mode +CamWriteCmosSensor(0x6f,0x62);//80//a0//indoor-th +CamWriteCmosSensor(0x70,0x00); +CamWriteCmosSensor(0x78,0xb0); + +CamWriteCmosSensor(0xfe,0x01);// gain limit +CamWriteCmosSensor(0x0c,0x01); + +CamWriteCmosSensor(0xfe,0x01);// G gain limit +CamWriteCmosSensor(0x78,0xa0); + +CamWriteCmosSensor(0xfe,0x01); +CamWriteCmosSensor(0x1c,0x21); + +CamWriteCmosSensor(0xfe,0x01); +CamWriteCmosSensor(0x90,0x00); +CamWriteCmosSensor(0x91,0x00); +CamWriteCmosSensor(0x92,0xf0); +CamWriteCmosSensor(0x93,0xd1); +CamWriteCmosSensor(0x94,0x50); +CamWriteCmosSensor(0x95,0xfd); +CamWriteCmosSensor(0x96,0xdf); +CamWriteCmosSensor(0x97,0x1f); +CamWriteCmosSensor(0x98,0x00); +CamWriteCmosSensor(0x99,0xa5); +CamWriteCmosSensor(0x9a,0x23); +CamWriteCmosSensor(0x9b,0x0c); +CamWriteCmosSensor(0x9c,0x55); +CamWriteCmosSensor(0x9d,0x3b); +CamWriteCmosSensor(0x9e,0xaa); +CamWriteCmosSensor(0x9f,0x00); +CamWriteCmosSensor(0xa0,0x00); +CamWriteCmosSensor(0xa1,0x00); +CamWriteCmosSensor(0xa2,0x00); +CamWriteCmosSensor(0xa3,0x00); +CamWriteCmosSensor(0xa4,0x00); +CamWriteCmosSensor(0xa5,0x00); +CamWriteCmosSensor(0xa6,0xcc); +CamWriteCmosSensor(0xa7,0xb7); +CamWriteCmosSensor(0xa8,0x50); +CamWriteCmosSensor(0xa9,0xb6); +CamWriteCmosSensor(0xaa,0x8d); +CamWriteCmosSensor(0xab,0xa8); +CamWriteCmosSensor(0xac,0x85); +CamWriteCmosSensor(0xad,0x55); +CamWriteCmosSensor(0xae,0xbb); +CamWriteCmosSensor(0xaf,0xa9); +CamWriteCmosSensor(0xb0,0xba); +CamWriteCmosSensor(0xb1,0xa2); +CamWriteCmosSensor(0xb2,0x55); +CamWriteCmosSensor(0xb3,0x00); +CamWriteCmosSensor(0xb4,0x00); +CamWriteCmosSensor(0xb5,0x00); +CamWriteCmosSensor(0xb6,0x00); +CamWriteCmosSensor(0xb7,0x00); +CamWriteCmosSensor(0xb8,0x9e); +CamWriteCmosSensor(0xb9,0xc9); + +///////////////////////////////////////////////// + //////////////////// CC //////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0xfe,0x01); +CamWriteCmosSensor(0xd0,0x44); +CamWriteCmosSensor(0xd1,0xFb); +CamWriteCmosSensor(0xd2,0x00); +CamWriteCmosSensor(0xd3,0x08); +CamWriteCmosSensor(0xd4,0x40); +CamWriteCmosSensor(0xd5,0x0d); +CamWriteCmosSensor(0xfe,0x00); +///////////////////////////////////////////////// + //////////////////// LSC //////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0xfe,0x01); +CamWriteCmosSensor(0x76,0x60);//R_gain_limit +CamWriteCmosSensor(0xc1,0x3c);//row center +CamWriteCmosSensor(0xc2,0x50);//col center +CamWriteCmosSensor(0xc3,0x00);//b4 sign +CamWriteCmosSensor(0xc4,0x4b);// b2 R +CamWriteCmosSensor(0xc5,0x38);//G +CamWriteCmosSensor(0xc6,0x38);//B +CamWriteCmosSensor(0xc7,0x10);//b4 R +CamWriteCmosSensor(0xc8,0x00);//G +CamWriteCmosSensor(0xc9,0x00);//b +CamWriteCmosSensor(0xdc,0x20);//lsc_Y_dark_th +CamWriteCmosSensor(0xdd,0x10);//lsc_Y_dark_slope +CamWriteCmosSensor(0xdf,0x00); +CamWriteCmosSensor(0xde,0x00); + +///////////////////////////////////////////////// + /////////////////// Histogram ///////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0x01,0x10); //precision +CamWriteCmosSensor(0x0b,0x31); //close fix_target_mode +CamWriteCmosSensor(0x0e,0x6c); //th_low +CamWriteCmosSensor(0x0f,0x0f); //color_diff_th +CamWriteCmosSensor(0x10,0x6e); //th_high +CamWriteCmosSensor(0x12,0xa0); //a1//enable +CamWriteCmosSensor(0x15,0x40); //target_Y_limit +CamWriteCmosSensor(0x16,0x60); //th_for_disable_hist +CamWriteCmosSensor(0x17,0x20); //luma_slope + +///////////////////////////////////////////////// + ////////////// Measure Window /////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0xcc,0x0c);//aec window size +CamWriteCmosSensor(0xcd,0x10); +CamWriteCmosSensor(0xce,0xa0); +CamWriteCmosSensor(0xcf,0xe6); + +///////////////////////////////////////////////// + ///////////////// dark sun ////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0x45,0xf7); +CamWriteCmosSensor(0x46,0xff); //f0//sun vaule th +CamWriteCmosSensor(0x47,0x15); +CamWriteCmosSensor(0x48,0x03); //sun mode +CamWriteCmosSensor(0x4f,0x60); //sun_clamp + +///////////////////////////////////////////////// + ///////////////////// SPI //////////////////// +///////////////////////////////////////////////// +CamWriteCmosSensor(0xfe,0x03); +CamWriteCmosSensor(0x01,0x00); +CamWriteCmosSensor(0x02,0x00); +CamWriteCmosSensor(0x10,0x00); +CamWriteCmosSensor(0x15,0x00); +CamWriteCmosSensor(0x17,0x00); //01:2-lqne, 03:1-lane, ic.hsu +CamWriteCmosSensor(0x04,0x01); +CamWriteCmosSensor(0x05,0x00); +CamWriteCmosSensor(0x40,0x00); +CamWriteCmosSensor(0x51,0x03); +CamWriteCmosSensor(0x52,0x20); //a2 //a0//80//00 +CamWriteCmosSensor(0x53,0xa4); //24 +CamWriteCmosSensor(0x54,0x20); +CamWriteCmosSensor(0x55,0x20); //QQ//01 +CamWriteCmosSensor(0x5a,0x40); //00 //yuv +CamWriteCmosSensor(0x5b,0x80); +CamWriteCmosSensor(0x5c,0x02); +CamWriteCmosSensor(0x5d,0xe0); +CamWriteCmosSensor(0x5e,0x01); + +write_cmos_sensor2(0x64,GC0310_read_cmos_sensor(0x64)|0x02); // always clock +SENSORDB("always csk 0x64= 0x%04x\n", GC0310_read_cmos_sensor(0x64)); + +CamWriteCmosSensor(0xfe,0x00); +Sleep(60);//delay 2 frame for stable data for calibration + +} + +UINT32 GC0310GetSensorID(UINT32 *sensorID) +{ + int retry = 3; + // check if sensor ID correct + do { + *sensorID=((GC0310_read_cmos_sensor(0xf0)<< 8)|GC0310_read_cmos_sensor(0xf1)); + if (*sensorID == GC0310_SENSOR_ID) + break; + LOG_INF("Read Sensor ID Fail = 0x%04x\n", *sensorID); + retry--; + } while (retry > 0); + + if (*sensorID != GC0310_SENSOR_ID) { + *sensorID = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + LOG_INF("GC0310 Sensor Read ID(0x%x)\r\n", *sensorID); + return ERROR_NONE; +} + + + + +/************************************************************************* +* FUNCTION +* GC0310_Write_More_Registers +* +* DESCRIPTION +* This function is served for FAE to modify the necessary Init Regs. Do not modify the regs +* in init_GC0310() directly. +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +void GC0310_Write_More_Registers(void) +{ + +} + +/************************************************************************* + * FUNCTION + * GC0310Open + * + * DESCRIPTION + * This function initialize the registers of CMOS sensor + * + * PARAMETERS + * None + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +UINT32 GC0310Open(void) +{ + volatile signed char i; + kal_uint16 sensor_id=0; + + LOG_INF(" Entry GC0310Open!!!\r\n"); + + Sleep(10); + + //Read sensor ID to adjust I2C is OK? + for(i=0;i<3;i++) + { + sensor_id = ((GC0310_read_cmos_sensor(0xf0) << 8) | GC0310_read_cmos_sensor(0xf1)); + if(sensor_id != GC0310_SENSOR_ID) + { + LOG_INF("GC0310mipi Read Sensor ID Fail[open] = 0x%x\n", sensor_id); + return ERROR_SENSOR_CONNECT_FAIL; + } + } + Sleep(10); + + LOG_INF("GC0310 Sensor Read ID(0x%x)\r\n",sensor_id); + GC0310_Sensor_Init(); + //GC0310_Write_More_Registers(); + + spin_lock(&GC0310_drv_lock); + GC0310_night_mode_enable = KAL_FALSE; + GC0310_MPEG4_encode_mode = KAL_FALSE; + spin_unlock(&GC0310_drv_lock); + + return ERROR_NONE; +} /* GC0310Open */ + + +/************************************************************************* + * FUNCTION + * GC0310Close + * + * DESCRIPTION + * This function is to turn off sensor module power. + * + * PARAMETERS + * None + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +UINT32 GC0310Close(void) +{ + return ERROR_NONE; +} /* GC0310Close */ + + +/************************************************************************* + * FUNCTION + * GC0310Preview + * + * DESCRIPTION + * This function start the sensor preview. + * + * PARAMETERS + * *image_window : address pointer of pixel numbers in one period of HSYNC + * *sensor_config_data : address pointer of line numbers in one period of VSYNC + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +UINT32 GC0310Preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) + +{ + kal_uint32 iTemp; + kal_uint16 iStartX = 0, iStartY = 1; + + LOG_INF("Enter GC0310Preview function!!!\r\n"); + + GC0310StreamOn(); + + image_window->GrabStartX= IMAGE_SENSOR_VGA_GRAB_PIXELS; + image_window->GrabStartY= IMAGE_SENSOR_VGA_GRAB_LINES; + image_window->ExposureWindowWidth = IMAGE_SENSOR_PV_WIDTH; + image_window->ExposureWindowHeight =IMAGE_SENSOR_PV_HEIGHT; + + //GC0310_Set_Mirrorflip(IMAGE_HV_MIRROR); + + // copy sensor_config_data + memcpy(&GC0310SensorConfigData, sensor_config_data, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + +// GC0310NightMode(GC0310_night_mode_enable); + return ERROR_NONE; +} /* GC0310Preview */ + + +/************************************************************************* + * FUNCTION + * GC0310Capture + * + * DESCRIPTION + * This function setup the CMOS sensor in capture MY_OUTPUT mode + * + * PARAMETERS + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +UINT32 GC0310Capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) + +{ + image_window->GrabStartX = IMAGE_SENSOR_VGA_GRAB_PIXELS; + image_window->GrabStartY = IMAGE_SENSOR_VGA_GRAB_LINES; + image_window->ExposureWindowWidth= IMAGE_SENSOR_FULL_WIDTH; + image_window->ExposureWindowHeight = IMAGE_SENSOR_FULL_HEIGHT; + + // copy sensor_config_data + memcpy(&GC0310SensorConfigData, sensor_config_data, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + GC0310StreamOn(); + return ERROR_NONE; +} /* GC0310_Capture() */ + +UINT32 GC0310Video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) + +{ + + image_window->GrabStartX = IMAGE_SENSOR_VGA_GRAB_PIXELS; + image_window->GrabStartY = IMAGE_SENSOR_VGA_GRAB_LINES; + image_window->ExposureWindowWidth= IMAGE_SENSOR_FULL_WIDTH; + image_window->ExposureWindowHeight = IMAGE_SENSOR_FULL_HEIGHT; + + // copy sensor_config_data + memcpy(&GC0310SensorConfigData, sensor_config_data, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + GC0310StreamOn(); + return ERROR_NONE; +} /* GC0310_Capture() */ + + + +UINT32 GC0310GetResolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *pSensorResolution) +{ + pSensorResolution->SensorFullWidth=IMAGE_SENSOR_FULL_WIDTH; + pSensorResolution->SensorFullHeight=IMAGE_SENSOR_FULL_HEIGHT; + pSensorResolution->SensorPreviewWidth=IMAGE_SENSOR_PV_WIDTH; + pSensorResolution->SensorPreviewHeight=IMAGE_SENSOR_PV_HEIGHT; + pSensorResolution->SensorVideoWidth=IMAGE_SENSOR_PV_WIDTH; + pSensorResolution->SensorVideoHeight=IMAGE_SENSOR_PV_HEIGHT; + + pSensorResolution->SensorHighSpeedVideoWidth=IMAGE_SENSOR_PV_WIDTH; + pSensorResolution->SensorHighSpeedVideoHeight=IMAGE_SENSOR_PV_HEIGHT; + + pSensorResolution->SensorSlimVideoWidth=IMAGE_SENSOR_PV_WIDTH; + pSensorResolution->SensorSlimVideoHeight=IMAGE_SENSOR_PV_HEIGHT; + return ERROR_NONE; +} /* GC0310GetResolution() */ + + +UINT32 GC0310GetInfo(MSDK_SCENARIO_ID_ENUM ScenarioId, + MSDK_SENSOR_INFO_STRUCT *pSensorInfo, + MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData) +{ + pSensorInfo->SensorPreviewResolutionX=IMAGE_SENSOR_PV_WIDTH; + pSensorInfo->SensorPreviewResolutionY=IMAGE_SENSOR_PV_HEIGHT; + pSensorInfo->SensorFullResolutionX=IMAGE_SENSOR_FULL_WIDTH; + pSensorInfo->SensorFullResolutionY=IMAGE_SENSOR_FULL_HEIGHT; + + pSensorInfo->SensorCameraPreviewFrameRate=30; + pSensorInfo->SensorVideoFrameRate=30; + pSensorInfo->SensorStillCaptureFrameRate=10; + pSensorInfo->SensorWebCamCaptureFrameRate=15; + pSensorInfo->SensorResetActiveHigh=FALSE; + pSensorInfo->SensorResetDelayCount=1; +// pSensorInfo->SensorOutputDataFormat=SENSOR_OUTPUT_FORMAT_VYUY; + pSensorInfo->SensorOutputDataFormat=SENSOR_OUTPUT_FORMAT_YUYV; + + pSensorInfo->SensorClockPolarity=SENSOR_CLOCK_POLARITY_LOW; + pSensorInfo->SensorClockFallingPolarity=SENSOR_CLOCK_POLARITY_LOW; + pSensorInfo->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + pSensorInfo->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + pSensorInfo->SensorInterruptDelayLines = 1; + pSensorInfo->SensroInterfaceType=SENSOR_INTERFACE_TYPE_SERIAL;//MIPI setting + pSensorInfo->CaptureDelayFrame = 2; + pSensorInfo->PreviewDelayFrame = 2; + pSensorInfo->VideoDelayFrame = 4; + + pSensorInfo->SensorMasterClockSwitch = 0; + pSensorInfo->SensorDrivingCurrent = ISP_DRIVING_6MA; + + pSensorInfo->HighSpeedVideoDelayFrame = 4; + pSensorInfo->SlimVideoDelayFrame = 4; + pSensorInfo->SensorModeNum = 5; + + switch (ScenarioId) + { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + default: + pSensorInfo->SensorClockFreq=48; + pSensorInfo->SensorClockDividCount= 3; + pSensorInfo->SensorClockRisingCount=0; + pSensorInfo->SensorClockFallingCount=2; + pSensorInfo->SensorPixelClockCount=3; + pSensorInfo->SensorDataLatchCount=2; + pSensorInfo->SensorGrabStartX = IMAGE_SENSOR_VGA_GRAB_PIXELS; + pSensorInfo->SensorGrabStartY = IMAGE_SENSOR_VGA_GRAB_LINES; + //MIPI setting + pSensorInfo->SensorMIPILaneNumber = SENSOR_MIPI_1_LANE; + pSensorInfo->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + pSensorInfo->MIPIDataLowPwr2HighSpeedSettleDelayCount = 14; + pSensorInfo->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + pSensorInfo->SensorWidthSampling = 0; // 0 is default 1x + pSensorInfo->SensorHightSampling = 0; // 0 is default 1x + pSensorInfo->SensorPacketECCOrder = 1; + /*SCAM setting*/ + pSensorInfo->SCAM_DataNumber = SCAM_2_DATA_CHANNEL; + pSensorInfo->SCAM_DDR_En = 1; + pSensorInfo->SCAM_CLK_INV = 0; + pSensorInfo->SCAM_DEFAULT_DELAY = 64;//0~31 negtive delay, 32~63 postive delay,should be 64 to keep always auto calibration + pSensorInfo->SCAM_CRC_En = 1; + pSensorInfo->SCAM_SOF_src = 1; + pSensorInfo->SCAM_Timout_Cali=0x34BC0;// 34BC0//30fps + // 0x3D9DEA//14.5fps + break; + } + GC0310PixelClockDivider=pSensorInfo->SensorPixelClockCount; + memcpy(pSensorConfigData, &GC0310SensorConfigData, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + return ERROR_NONE; +} /* GC0310GetInfo() */ + + +UINT32 GC0310Control(MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow, + MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData) +{ + + LOG_INF("Entry GC0310Control, ScenarioId = %d!!!\r\n", ScenarioId); +//return ERROR_NONE; + switch (ScenarioId) + { + + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + GC0310Preview(pImageWindow, pSensorConfigData); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + GC0310Capture(pImageWindow, pSensorConfigData); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + GC0310Video(pImageWindow, pSensorConfigData); + break; + + default: + LOG_INF("Error ScenarioId setting"); + GC0310Preview(pImageWindow, pSensorConfigData); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* GC0310Control() */ + +BOOL GC0310_set_param_wb(UINT16 para) +{ + LOG_INF("GC0310_set_param_wb para = %d\n", para); + spin_lock(&GC0310_drv_lock); + GC0310_CurStatus_AWB = para; + spin_unlock(&GC0310_drv_lock); + + GC0310_write_cmos_sensor(0xfe, 0x00); + switch (para) + { + case AWB_MODE_OFF: + GC0310_awb_enable(KAL_FALSE); + GC0310_write_cmos_sensor(0x77,0x74); + GC0310_write_cmos_sensor(0x78,0x40); + GC0310_write_cmos_sensor(0x79,0x5f); + break; + + case AWB_MODE_AUTO: + GC0310_write_cmos_sensor(0x77,0x74); + GC0310_write_cmos_sensor(0x78,0x40); + GC0310_write_cmos_sensor(0x79,0x5f); + GC0310_awb_enable(KAL_TRUE); + break; + + case AWB_MODE_CLOUDY_DAYLIGHT: //cloudy + GC0310_awb_enable(KAL_FALSE); + GC0310_write_cmos_sensor(0x77, 0x8c); + GC0310_write_cmos_sensor(0x78, 0x50); + GC0310_write_cmos_sensor(0x79, 0x40); + break; + + case AWB_MODE_DAYLIGHT: //sunny + GC0310_awb_enable(KAL_FALSE); + GC0310_write_cmos_sensor(0x77, 0x74); + GC0310_write_cmos_sensor(0x78, 0x52); + GC0310_write_cmos_sensor(0x79, 0x40); + break; + + case AWB_MODE_INCANDESCENT: //office + GC0310_awb_enable(KAL_FALSE); + GC0310_write_cmos_sensor(0x77, 0x48); + GC0310_write_cmos_sensor(0x78, 0x40); + GC0310_write_cmos_sensor(0x79, 0x5c); + break; + + case AWB_MODE_TUNGSTEN: //home + GC0310_awb_enable(KAL_FALSE); + GC0310_write_cmos_sensor(0x77, 0x40); //WB_manual_gain + GC0310_write_cmos_sensor(0x78, 0x54); + GC0310_write_cmos_sensor(0x79, 0x70); + break; + + case AWB_MODE_FLUORESCENT: + GC0310_awb_enable(KAL_FALSE); + GC0310_write_cmos_sensor(0x77, 0x40); + GC0310_write_cmos_sensor(0x78, 0x42); + GC0310_write_cmos_sensor(0x79, 0x50); + break; + + default: + return FALSE; + } + GC0310_write_cmos_sensor(0xfe, 0x00); + + return TRUE; +} /* GC0310_set_param_wb */ + + +BOOL GC0310_set_param_effect(UINT16 para) +{ + kal_uint32 ret = KAL_TRUE; + + switch (para) + { + case MEFFECT_OFF: + GC0310_write_cmos_sensor(0x43 , 0x00); + break; + + case MEFFECT_SEPIA: + GC0310_write_cmos_sensor(0x43 , 0x00); + Sleep(50); + GC0310_write_cmos_sensor(0xda , 0xd0); + GC0310_write_cmos_sensor(0xdb , 0x28); + GC0310_write_cmos_sensor(0x43 , 0x02); + break; + + case MEFFECT_NEGATIVE: + GC0310_write_cmos_sensor(0x43 , 0x01); + break; + + case MEFFECT_SEPIAGREEN: + GC0310_write_cmos_sensor(0x43 , 0x00); + Sleep(50); + GC0310_write_cmos_sensor(0xda , 0xc0); + GC0310_write_cmos_sensor(0xdb , 0xc0); + GC0310_write_cmos_sensor(0x43 , 0x02); + break; + + case MEFFECT_SEPIABLUE: + GC0310_write_cmos_sensor(0x43 , 0x00); + Sleep(50); + GC0310_write_cmos_sensor(0xda , 0x28); + GC0310_write_cmos_sensor(0xdb , 0xa0); + GC0310_write_cmos_sensor(0x43 , 0x02); + break; + + case MEFFECT_MONO: + GC0310_write_cmos_sensor(0x43 , 0x00); + Sleep(50); + GC0310_write_cmos_sensor(0xda , 0x00); + GC0310_write_cmos_sensor(0xdb , 0x00); + GC0310_write_cmos_sensor(0x43 , 0x02); + break; + default: + ret = FALSE; + } + + return ret; + +} /* GC0310_set_param_effect */ + + +BOOL GC0310_set_param_banding(UINT16 para) +{ + + LOG_INF("Enter GC0310_set_param_banding!, para = %d\r\n", para); + switch (para) + { + case AE_FLICKER_MODE_AUTO: + case AE_FLICKER_MODE_OFF: + case AE_FLICKER_MODE_50HZ: + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x00); + CamWriteCmosSensor(0x08,0x0a); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x96); + + CamWriteCmosSensor(0x27,0x01); //30fps + CamWriteCmosSensor(0x28,0xc2); + CamWriteCmosSensor(0x29,0x02); //20fps + CamWriteCmosSensor(0x2a,0xee); + CamWriteCmosSensor(0x2b,0x05); //10fps + CamWriteCmosSensor(0x2c,0xdc); + CamWriteCmosSensor(0x2d,0x05); //10fps + CamWriteCmosSensor(0x2e,0xdc); + CamWriteCmosSensor(0x3c,0x30); + CamWriteCmosSensor(0xfe,0x00); + GC0310_banding_state = GC0310_BANDING_50HZ; // 0~50hz; 1~60hz + break; + + case AE_FLICKER_MODE_60HZ: + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x00); + CamWriteCmosSensor(0x08,0x0a); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x7d); + + CamWriteCmosSensor(0x27,0x01); //30fps + CamWriteCmosSensor(0x28,0x77); + CamWriteCmosSensor(0x29,0x02); //20fps + CamWriteCmosSensor(0x2a,0xee); + CamWriteCmosSensor(0x2b,0x05); //10fps + CamWriteCmosSensor(0x2c,0xdc); + CamWriteCmosSensor(0x2d,0x05); //10fps + CamWriteCmosSensor(0x2e,0xdc); + CamWriteCmosSensor(0x3c,0x30); + CamWriteCmosSensor(0xfe,0x00); + GC0310_banding_state = GC0310_BANDING_60HZ; // 0~50hz; 1~60hz + break; + default: + return FALSE; + } + GC0310_write_cmos_sensor(0xfe, 0x00); + LOG_INF("shutter %d\n",GC0310_Read_Shutter()); + + return TRUE; +} /* GC0310_set_param_banding */ + +BOOL GC0310_set_param_exposure(UINT16 para) +{ + + switch (para) + { + + case AE_EV_COMP_n20: + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x13, 0x20); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + + case AE_EV_COMP_n10: + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x13, 0x28); // 28 to 10 + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + + case AE_EV_COMP_00: + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x13, 0x38);//35 + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + + case AE_EV_COMP_15: + case AE_EV_COMP_10: + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x13, 0x48); // 48 to 60 + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + + case AE_EV_COMP_20: + GC0310_write_cmos_sensor(0xfe, 0x01); + GC0310_write_cmos_sensor(0x13, 0x50); + GC0310_write_cmos_sensor(0xfe, 0x00); + break; + default: + return FALSE; + } + + return TRUE; +} /* GC0310_set_param_exposure */ + +void set_fixframerate_by_banding(UINT16 u2FrameRate, kal_bool bBanding) +{ + if ( 30 == u2FrameRate){ + LOG_INF("fix 30 fps"); + + if ( GC0310_BANDING_50HZ == bBanding ) + { + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x00); + CamWriteCmosSensor(0x08,0x0a); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x96); + + CamWriteCmosSensor(0x27,0x01); //30fps + CamWriteCmosSensor(0x28,0xc2); + CamWriteCmosSensor(0x29,0x02); //20fps + CamWriteCmosSensor(0x2a,0xee); + CamWriteCmosSensor(0x2b,0x05); //10fps + CamWriteCmosSensor(0x2c,0xdc); + CamWriteCmosSensor(0x2d,0x0b); //5fps + CamWriteCmosSensor(0x2e,0xb8); + CamWriteCmosSensor(0x3c,0x00); + CamWriteCmosSensor(0xfe,0x00); + + } + else if ( GC0310_BANDING_60HZ == bBanding ) + { + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x00); + CamWriteCmosSensor(0x08,0x0a); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x7d); + + CamWriteCmosSensor(0x27,0x01); //30fps + CamWriteCmosSensor(0x28,0x77); + CamWriteCmosSensor(0x29,0x02); //20fps + CamWriteCmosSensor(0x2a,0xee); + CamWriteCmosSensor(0x2b,0x05); //10fps + CamWriteCmosSensor(0x2c,0xdc); + CamWriteCmosSensor(0x2d,0x0b); //5fps + CamWriteCmosSensor(0x2e,0xb8); + CamWriteCmosSensor(0x3c,0x00); + CamWriteCmosSensor(0xfe,0x00); + + } + else + { + LOG_INF("sensor do not support the banding"); + } + } + else if ( 15 == u2FrameRate) + { + LOG_INF(" fix 15 fps"); + + if ( GC0310_BANDING_50HZ == bBanding ) + { + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x01); + CamWriteCmosSensor(0x08,0xfe); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x96); + + CamWriteCmosSensor(0x27,0x03); //15fps + CamWriteCmosSensor(0x28,0x84); + CamWriteCmosSensor(0x29,0x03); //14.5fps + CamWriteCmosSensor(0x2a,0x84); + CamWriteCmosSensor(0x2b,0x03); //14.5fps + CamWriteCmosSensor(0x2c,0x84); + CamWriteCmosSensor(0x2d,0x03); //14.5fps + CamWriteCmosSensor(0x2e,0x84); + CamWriteCmosSensor(0x3c,0x00); + CamWriteCmosSensor(0xfe,0x00); + + } + else if ( GC0310_BANDING_60HZ == bBanding ) + { + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x02); + CamWriteCmosSensor(0x08,0x00); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x7d); + + CamWriteCmosSensor(0x27,0x03); //15fps + CamWriteCmosSensor(0x28,0xe8); + CamWriteCmosSensor(0x29,0x03); //15fps + CamWriteCmosSensor(0x2a,0xe8); + CamWriteCmosSensor(0x2b,0x03); //15fps + CamWriteCmosSensor(0x2c,0xe8); + CamWriteCmosSensor(0x2d,0x03); //15fps + CamWriteCmosSensor(0x2e,0xe8); + CamWriteCmosSensor(0x3c,0x00); + CamWriteCmosSensor(0xfe,0x00); + + + } + else + { + LOG_INF("sensor do not support the banding"); + } + } + else + { + LOG_INF("sensor do not support the Frame Rate"); + + }; + LOG_INF("shutter %d\n",GC0310_Read_Shutter()); + +} +void set_freeframerate_by_banding(UINT16 u2minFrameRate, UINT16 u2maxFrameRate, kal_bool bBanding) +{ + if ((5 == u2minFrameRate) && (30 == u2maxFrameRate)) + { + if ( GC0310_BANDING_50HZ == bBanding ) + { + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x00); + CamWriteCmosSensor(0x08,0x0a); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x96); + + CamWriteCmosSensor(0x27,0x01); //30fps + CamWriteCmosSensor(0x28,0xc2); + CamWriteCmosSensor(0x29,0x02); //20fps + CamWriteCmosSensor(0x2a,0xee); + CamWriteCmosSensor(0x2b,0x05); //10fps + CamWriteCmosSensor(0x2c,0xdc); + CamWriteCmosSensor(0x2d,0x0b); //5fps + CamWriteCmosSensor(0x2e,0xb8); + CamWriteCmosSensor(0x3c,0x30); + CamWriteCmosSensor(0xfe,0x00); + } + else if ( GC0310_BANDING_60HZ == bBanding ) + { + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x00); + CamWriteCmosSensor(0x08,0x0a); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x7d); + + CamWriteCmosSensor(0x27,0x01); //30fps + CamWriteCmosSensor(0x28,0x77); + CamWriteCmosSensor(0x29,0x02); //20fps + CamWriteCmosSensor(0x2a,0xee); + CamWriteCmosSensor(0x2b,0x05); //10fps + CamWriteCmosSensor(0x2c,0xdc); + CamWriteCmosSensor(0x2d,0x0b); //5fps + CamWriteCmosSensor(0x2e,0xb8); + CamWriteCmosSensor(0x3c,0x30); + CamWriteCmosSensor(0xfe,0x00); + } + else + { + LOG_INF("sensor do not support the banding"); + } + } + else if ((10 == u2minFrameRate) && (30 == u2maxFrameRate)) + { + if ( GC0310_BANDING_50HZ == bBanding ) + { + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x00); + CamWriteCmosSensor(0x08,0x0a); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x96); + + CamWriteCmosSensor(0x27,0x01); //30fps + CamWriteCmosSensor(0x28,0xc2); + CamWriteCmosSensor(0x29,0x02); //20fps + CamWriteCmosSensor(0x2a,0xee); + CamWriteCmosSensor(0x2b,0x05); //10fps + CamWriteCmosSensor(0x2c,0xdc); + CamWriteCmosSensor(0x2d,0x05); //10fps + CamWriteCmosSensor(0x2e,0xdc); + CamWriteCmosSensor(0x3c,0x30); + CamWriteCmosSensor(0xfe,0x00); + } + else if ( GC0310_BANDING_60HZ == bBanding ) + { + CamWriteCmosSensor(0xfe,0x00); + CamWriteCmosSensor(0x05,0x00); + CamWriteCmosSensor(0x06,0x6a); + CamWriteCmosSensor(0x07,0x00); + CamWriteCmosSensor(0x08,0x0a); + + CamWriteCmosSensor(0xfe,0x01); + CamWriteCmosSensor(0x25,0x00); //step + CamWriteCmosSensor(0x26,0x7d); + + CamWriteCmosSensor(0x27,0x01); //30fps + CamWriteCmosSensor(0x28,0x77); + CamWriteCmosSensor(0x29,0x02); //20fps + CamWriteCmosSensor(0x2a,0xee); + CamWriteCmosSensor(0x2b,0x05); //10fps + CamWriteCmosSensor(0x2c,0xdc); + CamWriteCmosSensor(0x2d,0x05); //10fps + CamWriteCmosSensor(0x2e,0xdc); + CamWriteCmosSensor(0x3c,0x30); + CamWriteCmosSensor(0xfe,0x00); + } + else + { + LOG_INF("sensor do not support the banding"); + + } + } + LOG_INF("shutter %d\n",GC0310_Read_Shutter()); +} + +UINT32 GC0310YUVSetVideoMode(UINT16 u2FrameRate) // lanking add +{ + + LOG_INF(" GC0310YUVSetVideoMode, u2FrameRate = %d\n", u2FrameRate); + + + if (u2FrameRate == 30) + { + LOG_INF(" fix30fps,GC0310_banding_state = %d\n", GC0310_banding_state); + + set_fixframerate_by_banding(30, GC0310_banding_state); + + } + else if (u2FrameRate == 15) + { + LOG_INF("fix15fps, GC0310_banding_state = %d\n", GC0310_banding_state); + + set_fixframerate_by_banding(15, GC0310_banding_state); + + } + else + { + + LOG_INF("Wrong Frame Rate"); + + } + LOG_INF("GC0310YUVSetVideoMode EXIT\n"); + + return TRUE; + +} + + +/************************************************************************* + * FUNCTION + * GC0310_NightMode + * + * DESCRIPTION + * This function night mode of GC0310. + * + * PARAMETERS + * bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +void GC0310NightMode(kal_bool bEnable) +{ + LOG_INF("GC0310Night, Modeenable(%d)\n", bEnable); + LOG_INF("GC0310_banding_state = %d\n", GC0310_banding_state); + + + if(bEnable) // night mode for preview and video + { + LOG_INF("set_night_mode for preview\n"); + set_freeframerate_by_banding(5, 30, GC0310_banding_state); + } + else // normal mode for preview and video (not night) + { + LOG_INF("set_normal_mode for preview\n"); + set_freeframerate_by_banding(10, 30, GC0310_banding_state); + } + + LOG_INF("set_night_mode end \n"); +} + + +UINT32 GC0310YUVSensorSetting(FEATURE_ID iCmd, UINT16 iPara) +{ + switch (iCmd) { + case FID_AWB_MODE: + GC0310_set_param_wb(iPara); + break; + case FID_COLOR_EFFECT: + GC0310_set_param_effect(iPara); + break; + case FID_AE_EV: + GC0310_set_param_exposure(iPara); + break; + case FID_AE_FLICKER: + GC0310_set_param_banding(iPara); + break; + case FID_SCENE_MODE: + GC0310NightMode(iPara); + break; + + case FID_ISP_CONTRAST: + GC0310_set_contrast(iPara); + break; + case FID_ISP_BRIGHT: + GC0310_set_brightness(iPara); + break; + case FID_ISP_SAT: + GC0310_set_saturation(iPara); + break; + case FID_AE_ISO: + GC0310_set_iso(iPara); + break; + case FID_AE_SCENE_MODE: + GC0310_set_AE_mode(iPara); + break; + + default: + break; + } + return TRUE; +} /* GC0310YUVSensorSetting */ + + +UINT32 GC0310FeatureControl(MSDK_SENSOR_FEATURE_ENUM FeatureId, + UINT8 *pFeaturePara,UINT32 *pFeatureParaLen) +{ + UINT16 *pFeatureReturnPara16=(UINT16 *) pFeaturePara; + UINT16 *pFeatureData16=(UINT16 *) pFeaturePara; + UINT32 *pFeatureReturnPara32=(UINT32 *) pFeaturePara; + UINT32 *pFeatureData32=(UINT32 *) pFeaturePara; + UINT32 **ppFeatureData=(UINT32 **) pFeaturePara; + unsigned long long *feature_data=(unsigned long long *) pFeaturePara; + unsigned long long *feature_return_para=(unsigned long long *) pFeaturePara; + + UINT32 GC0310SensorRegNumber; + UINT32 i; + MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData=(MSDK_SENSOR_CONFIG_STRUCT *) pFeaturePara; + MSDK_SENSOR_REG_INFO_STRUCT *pSensorRegData=(MSDK_SENSOR_REG_INFO_STRUCT *) pFeaturePara; + LOG_INF("FeatureId = %d", FeatureId); + + switch (FeatureId) + { + case SENSOR_FEATURE_GET_RESOLUTION: + *pFeatureReturnPara16++=IMAGE_SENSOR_FULL_WIDTH; + *pFeatureReturnPara16=IMAGE_SENSOR_FULL_HEIGHT; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_GET_PERIOD: + *pFeatureReturnPara16++=(VGA_PERIOD_PIXEL_NUMS)+GC0310_dummy_pixels; + *pFeatureReturnPara16=(VGA_PERIOD_LINE_NUMS)+GC0310_dummy_lines; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *pFeatureReturnPara32 = GC0310_g_fPV_PCLK; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + // GC0310NightMode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + GC0310_isp_master_clock=*pFeatureData32; + break; + case SENSOR_FEATURE_SET_REGISTER: + GC0310_write_cmos_sensor(pSensorRegData->RegAddr, pSensorRegData->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + pSensorRegData->RegData = GC0310_read_cmos_sensor(pSensorRegData->RegAddr); + break; + case SENSOR_FEATURE_GET_CONFIG_PARA: + memcpy(pSensorConfigData, &GC0310SensorConfigData, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + *pFeatureParaLen=sizeof(MSDK_SENSOR_CONFIG_STRUCT); + break; + case SENSOR_FEATURE_SET_CCT_REGISTER: + case SENSOR_FEATURE_GET_CCT_REGISTER: + case SENSOR_FEATURE_SET_ENG_REGISTER: + case SENSOR_FEATURE_GET_ENG_REGISTER: + case SENSOR_FEATURE_GET_REGISTER_DEFAULT: + case SENSOR_FEATURE_CAMERA_PARA_TO_SENSOR: + case SENSOR_FEATURE_SENSOR_TO_CAMERA_PARA: + case SENSOR_FEATURE_GET_GROUP_COUNT: + case SENSOR_FEATURE_GET_GROUP_INFO: + case SENSOR_FEATURE_GET_ITEM_INFO: + case SENSOR_FEATURE_SET_ITEM_INFO: + case SENSOR_FEATURE_GET_ENG_INFO: + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *pFeatureReturnPara32=LENS_DRIVER_ID_DO_NOT_CARE; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_SET_YUV_CMD: + GC0310YUVSensorSetting((FEATURE_ID)*feature_data, *(feature_data+1)); + + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: // lanking + GC0310YUVSetVideoMode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + GC0310GetSensorID(pFeatureData32); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: + *pFeatureReturnPara32=GC0310_TEST_PATTERN_CHECKSUM; + *pFeatureParaLen=4; + break; + + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + LOG_INF("[GC0310] F_SET_MAX_FRAME_RATE_BY_SCENARIO.\n"); + GC0310_MIPI_SetMaxFramerateByScenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + +// case SENSOR_CMD_SET_VIDEO_FRAME_RATE: +// LOG_INF("[GC0310] Enter SENSOR_CMD_SET_VIDEO_FRAME_RATE\n"); +// //GC0310_MIPI_SetVideoFrameRate(*pFeatureData32); +// break; + + case SENSOR_FEATURE_SET_TEST_PATTERN: + GC0310SetTestPatternMode((BOOL)*feature_data); + break; + + case SENSOR_FEATURE_GET_DELAY_INFO: + LOG_INF("[GC0310] F_GET_DELAY_INFO\n"); + GC0310_MIPI_GetDelayInfo((uintptr_t)*feature_data); + break; + + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + LOG_INF("[GC0310] F_GET_DEFAULT_FRAME_RATE_BY_SCENARIO\n"); + GC0310_MIPI_GetDefaultFramerateByScenario((MSDK_SCENARIO_ID_ENUM)*feature_data, (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + + case SENSOR_FEATURE_SET_YUV_3A_CMD: + LOG_INF("[GC0310] SENSOR_FEATURE_SET_YUV_3A_CMD ID:%d\n", *pFeatureData32); + GC0310_3ACtrl((ACDK_SENSOR_3A_LOCK_ENUM)*feature_data); + break; + + + case SENSOR_FEATURE_GET_EXIF_INFO: + //LOG_INF("[4EC] F_GET_EXIF_INFO\n"); + GC0310_MIPI_GetExifInfo((uintptr_t)*feature_data); + break; + + + case SENSOR_FEATURE_GET_AE_AWB_LOCK_INFO: + LOG_INF("[GC0310] F_GET_AE_AWB_LOCK_INFO\n"); + //GC0310_MIPI_get_AEAWB_lock((uintptr_t)(*feature_data), (uintptr_t)*(feature_data+1)); + break; + + case SENSOR_FEATURE_SET_MIN_MAX_FPS: + LOG_INF("SENSOR_FEATURE_SET_MIN_MAX_FPS:[%d,%d]\n",*pFeatureData32,*(pFeatureData32+1)); + GC0310_MIPI_SetMaxMinFps((UINT32)*feature_data, (UINT32)*(feature_data+1)); + break; + + default: + break; + } +return ERROR_NONE; +} /* GC0310FeatureControl() */ + + +SENSOR_FUNCTION_STRUCT SensorFuncGC0310YUV= +{ + GC0310Open, + GC0310GetInfo, + GC0310GetResolution, + GC0310FeatureControl, + GC0310Control, + GC0310Close +}; + + +UINT32 GC0310_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&SensorFuncGC0310YUV; + return ERROR_NONE; +} /* SensorInit() */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/gc0310_yuv_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/gc0310_yuv_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..4c610dbc349f6e8db5547caa0bbb9298ee645247 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc0310_yuv/gc0310_yuv_Sensor.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +/***************************************************************************** + * + * Filename: + * --------- + * gc0310_yuv_Sensor.h + * + * Project: + * -------- + * MAUI + * + * Description: + * ------------ + * Image sensor driver declare and macro define in the header file. + * + * Author: + * ------- + * Mormo + * + *============================================================= + * HISTORY + * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! + *------------------------------------------------------------------------------ + * $Log$ + * 2011/10/25 Firsty Released By Mormo; + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! + *============================================================= + ******************************************************************************/ + +#ifndef __GC0310_SENSOR_H +#define __GC0310_SENSOR_H + + +#define VGA_PERIOD_PIXEL_NUMS 694 +#define VGA_PERIOD_LINE_NUMS 488 + +#define IMAGE_SENSOR_VGA_GRAB_PIXELS 0 +#define IMAGE_SENSOR_VGA_GRAB_LINES 0 + +#define IMAGE_SENSOR_VGA_WIDTH (640) +#define IMAGE_SENSOR_VGA_HEIGHT (480) + +#define IMAGE_SENSOR_PV_WIDTH (IMAGE_SENSOR_VGA_WIDTH) +#define IMAGE_SENSOR_PV_HEIGHT (IMAGE_SENSOR_VGA_HEIGHT) + +#define IMAGE_SENSOR_FULL_WIDTH (IMAGE_SENSOR_VGA_WIDTH) +#define IMAGE_SENSOR_FULL_HEIGHT (IMAGE_SENSOR_VGA_HEIGHT) + +#define GC0310_WRITE_ID 0x42 +#define GC0310_READ_ID 0x43 + +// GC0310 SENSOR Chip ID: 0xd0 + +typedef enum +{ + GC0310_RGB_Gamma_m1 = 0, + GC0310_RGB_Gamma_m2, + GC0310_RGB_Gamma_m3, + GC0310_RGB_Gamma_m4, + GC0310_RGB_Gamma_m5, + GC0310_RGB_Gamma_m6, + GC0310_RGB_Gamma_night +}GC0310_GAMMA_TAG; + + + +UINT32 GC0310Open(void); +UINT32 GC0310Control(MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow, MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData); +UINT32 GC0310FeatureControl(MSDK_SENSOR_FEATURE_ENUM FeatureId, UINT8 *pFeaturePara,UINT32 *pFeatureParaLen); +UINT32 GC0310GetInfo(MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_INFO_STRUCT *pSensorInfo, MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData); +UINT32 GC0310GetResolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *pSensorResolution); +UINT32 GC0310Close(void); + +#endif /* __SENSOR_H */ + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..0476f9f99e24b1904f25e5d88e422fb59e24d32a --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/Makefile @@ -0,0 +1,4 @@ +#include $(srctree)/drivers/misc/mediatek/imgsensor/src/Makefile.custom +obj-y += gc5005mipi_Sensor.o + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/gc5005mipi_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/gc5005mipi_Sensor.c new file mode 100755 index 0000000000000000000000000000000000000000..52d20e80dcbd9bfa8dce304e5066799898c41bd3 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/gc5005mipi_Sensor.c @@ -0,0 +1,1981 @@ +/***************************************************************************** + * + * Filename: + * --------- + * GC5005mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "gc5005mipi_Sensor.h" + + + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "GC5005_camera_sensor" +#define LOG_1 LOG_INF("GC5005,MIPI 2LANE\n") +/**************************** Modify end *******************************************/ + +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +#define GC5005_MIPI_USE_OTP + +static DEFINE_SPINLOCK(imgsensor_drv_lock); +kal_bool GC5005DuringTestPattern = KAL_FALSE; + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = GC5005MIPI_SENSOR_ID, //record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0xf7375923, //checksum value for Camera Auto Test + + .pre = { + .pclk = 54000000, //record different mode's pclk + .linelength = 906, //record different mode's linelength + .framelength = 1984, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2592, //record different mode's width of grabwindow + .grabwindow_height = 1944, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 100, + }, + .cap = { + .pclk = 54000000, + .linelength = 906, + .framelength = 1984, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 100, + }, + .cap1 = { //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 54000000, + .linelength = 906, + .framelength = 1984, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 100, + }, + .normal_video = { + .pclk = 54000000, + .linelength = 906, + .framelength = 1480, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 100, + }, + .hs_video = { + .pclk = 54000000, + .linelength = 906, + .framelength = 1480, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 100, + }, + .slim_video = { + .pclk = 54000000, + .linelength = 906, + .framelength = 1480, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 100, + }, + .margin = 0, //sensor framelength & shutter margin + .min_shutter = 1, //min shutter + .max_frame_length = 0x3fff,//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 3, //support sensor mode num + + .cap_delay_frame = 2, //enter capture delay frame num + .pre_delay_frame = 2, //enter preview delay frame num + .video_delay_frame = 2, //enter video delay frame num + .hs_video_delay_frame = 2, //enter high speed video delay frame num + .slim_video_delay_frame = 2,//enter slim video delay frame num + + .isp_driving_current = ISP_DRIVING_6MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_2_LANE,//mipi lane num + .i2c_addr_table = {0x6e, 0xff},//record sensor support all write id addr, only supprt 4must end with 0xff +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3ED, //current shutter + .gain = 0x40, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 300, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x6e,//record current sensor's i2c write id +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{ + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}, // Preview + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}, // capture + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}, // video + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}, //hight speed video + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}};// slim video + + + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[1] = {(char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 1, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; + +} + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ +#if 1 + char pu_send_cmd[2] = {(char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 2, imgsensor.i2c_write_id); +#else + iWriteReg((u16)addr, (u32)para, 2, imgsensor.i2c_write_id); +#endif + +} + +#ifdef GC5005_MIPI_USE_OTP + +#define DD_PARAM_QTY 200 +#define WINDOW_WIDTH 0x0a30 //2608 max effective pixels +#define WINDOW_HEIGHT 0x07a0 //1952 +#define RG_TYPICAL 0x0090 +#define BG_TYPICAL 0x0095 +#define INFO_ROM_START 0x01 +#define INFO_WIDTH 0x07 +#define WB_ROM_START 0x0f +#define WB_WIDTH 0x02 +#define GOLDEN_ROM_START 0x14 +#define GOLDEN_WIDTH 0x02 + +typedef struct otp_gc5005{ + kal_uint16 module_id; + kal_uint16 lens_id; + kal_uint16 vcm_id; + kal_uint16 vcm_driver_id; + kal_uint16 year; + kal_uint16 month; + kal_uint16 day; + kal_uint16 rg_gain; + kal_uint16 bg_gain; + kal_uint16 wb_flag; + kal_uint16 golden_flag; + kal_uint16 dd_param_x[DD_PARAM_QTY]; + kal_uint16 dd_param_y[DD_PARAM_QTY]; + kal_uint16 dd_param_type[DD_PARAM_QTY]; + kal_uint16 dd_cnt; + kal_uint16 dd_flag; + kal_uint16 golden_rg; + kal_uint16 golden_bg; + //kal_uint16 gc_flag; + //kal_uint16 Vald1; + //kal_uint16 Val21; + //kal_uint16 Val29; +}gc5005_otp; + +static gc5005_otp gc5005_otp_info; + +typedef enum{ + otp_page0=0, + otp_page1, +}otp_page; + +typedef enum{ + otp_close=0, + otp_open, +}otp_state; + +static kal_uint8 gc5005_read_otp(kal_uint8 addr) +{ + kal_uint8 value; + + write_cmos_sensor(0xfe,0x00); + write_cmos_sensor(0xd5,addr); + write_cmos_sensor(0xf3,0x20); + value = read_cmos_sensor(0xd7); + + return value; +} + +static void gc5005_select_page_otp(otp_page otp_select_page) +{ + kal_uint8 page; + + write_cmos_sensor(0xfe,0x00); + page = read_cmos_sensor(0xd4); + + switch(otp_select_page) + { + case otp_page0: + page = page & 0xfb; + break; + case otp_page1: + page = page | 0x04; + break; + default: + break; + } + + mdelay(5); + write_cmos_sensor(0xd4,page); + +} + +static void gc5005_gcore_read_otp_info(void) +{ + kal_uint8 flag0,flag1,flag_golden; + kal_uint8 index,i,j,cnt=0; + kal_uint8 info_start_add,wb_start_add,golden_start_add; + kal_uint8 total_number0=0,total_number1=0,total_number=0; + kal_uint8 check_dd_flag,type; + kal_uint8 dd0=0,dd1=0,dd2=0; + kal_uint16 x,y; + kal_uint8 dd_rom_start,offset; + memset(&gc5005_otp_info,0,sizeof(gc5005_otp)); + + /*TODO*/ + gc5005_select_page_otp(otp_page0); + flag0 = gc5005_read_otp(0x00); + total_number0 = gc5005_read_otp(0x01) + gc5005_read_otp(0x02); + LOG_INF("GC5005_OTP : flag0 = 0x%x , total_number0 = %d\n",flag0,total_number0); + + gc5005_select_page_otp(otp_page1); + total_number1 = gc5005_read_otp(0x28) + gc5005_read_otp(0x29); + LOG_INF("GC5005_OTP : total_number1 = %d\n",total_number1); +/* +//For GC + gc5005_otp_info.gc_flag = (flag0>>2)&0x03; + LOG_INF("GC5005_OTP : gc5005_otp_info.gc_flag = 0x%x \n",gc5005_otp_info.gc_flag); + + if(gc5005_otp_info.gc_flag==0x01) + { + gc5005_otp_info.Vald1=0xb0; + gc5005_otp_info.Val21=0x08; + gc5005_otp_info.Val29=0x14; + } + else + { + gc5005_otp_info.Vald1=0xa0; + gc5005_otp_info.Val21=0x0a; + gc5005_otp_info.Val29=0x22; + } +*/ +//DD + switch(flag0&0x03) + { + case 0x00: + LOG_INF("GC5005_OTP_DD is Empty !!\n"); + gc5005_otp_info.dd_flag = 0x00; + break; + case 0x01: + LOG_INF("GC5005_OTP_DD is Valid!!\n"); + + gc5005_select_page_otp(otp_page0); + dd_rom_start=0x03; + offset = 0; + + total_number = (total_number1>=total_number0) ? total_number1 : total_number0; + LOG_INF("GC5005_OTP_DD total_number=%d!!\n",total_number); + + for(i=0; i>4); + LOG_INF("GC5005_OTP_DD : type = %d , x = %d , y = %d \n",type,x,y); + LOG_INF("GC5005_OTP_DD : dd0 = %d , dd1 = %d , dd2 = %d \n",dd0,dd1,dd2); + + if(type == 3) + { + for(j=0; j<4; j++) + { + gc5005_otp_info.dd_param_x[cnt] = x; + gc5005_otp_info.dd_param_y[cnt] = y + j; + gc5005_otp_info.dd_param_type[cnt++] = 2; + } + } +/* + else if(type == 2) + { + y = ((y-1)/4)*4+1; + for(j=0; j<4; j++) + { + gc5005_otp_info.dd_param_x[cnt] = x; + gc5005_otp_info.dd_param_y[cnt] = y + j; + gc5005_otp_info.dd_param_type[cnt++] = 2; + } + } +*/ + else + { + gc5005_otp_info.dd_param_x[cnt] = x; + gc5005_otp_info.dd_param_y[cnt] = y; + gc5005_otp_info.dd_param_type[cnt++] = type; + } + } + else + { + LOG_INF("GC5005_OTP_DD:check_id[%d] = %x,checkid error!!\n",i,check_dd_flag); + } + } + gc5005_otp_info.dd_cnt = cnt; + gc5005_otp_info.dd_flag = 0x01; + break; + case 0x02: + case 0x03: + LOG_INF("GC5005_OTP_DD is Invalid !!\n"); + gc5005_otp_info.dd_flag = 0x02; + break; + default : + break; + } + + gc5005_select_page_otp(otp_page1); + flag1 = gc5005_read_otp(0x00); + flag_golden = gc5005_read_otp(0x13); + LOG_INF("GC5005_OTP : flag1 = 0x%x , flag_golden = 0x%x\n",flag1,flag_golden); + +//INFO&WB + for(index=0;index<2;index++) + { + switch((flag1>>(4 + 2 * index))&0x03) + { + case 0x00: + LOG_INF("GC5005_OTP_INFO group%d is Empty !!\n", index + 1); + break; + case 0x01: + info_start_add = INFO_ROM_START + index * INFO_WIDTH; + gc5005_otp_info.module_id = gc5005_read_otp(info_start_add); + gc5005_otp_info.lens_id = gc5005_read_otp(info_start_add + 1); + gc5005_otp_info.vcm_driver_id = gc5005_read_otp(info_start_add + 2); + gc5005_otp_info.vcm_id = gc5005_read_otp(info_start_add + 3); + gc5005_otp_info.year = gc5005_read_otp(info_start_add + 4); + gc5005_otp_info.month = gc5005_read_otp(info_start_add + 5); + gc5005_otp_info.day = gc5005_read_otp(info_start_add + 6); + break; + case 0x02: + case 0x03: + LOG_INF("GC5005_OTP_INFO group%d is Invalid !!\n", index + 1); + break; + default : + break; + } + + switch((flag1>>(2 * index))&0x03) + { + case 0x00: + LOG_INF("GC5005_OTP_WB group%d is Empty !!\n", index + 1); + gc5005_otp_info.wb_flag = gc5005_otp_info.wb_flag|0x00; + break; + case 0x01: + LOG_INF("GC5005_OTP_WB group%d is Valid !!\n", index + 1); + wb_start_add = WB_ROM_START + index * WB_WIDTH; + gc5005_otp_info.rg_gain = gc5005_read_otp(wb_start_add); + gc5005_otp_info.bg_gain = gc5005_read_otp(wb_start_add + 1); + + if((0==gc5005_otp_info.rg_gain)||(0==gc5005_otp_info.bg_gain)) + { + gc5005_otp_info.wb_flag = gc5005_otp_info.wb_flag|0x02; + LOG_INF("GC5005_OTP_WB group%d is Error ,wb rg or bg = 0!!\n", index + 1); + } + else + { + gc5005_otp_info.wb_flag = gc5005_otp_info.wb_flag|0x01; + } + + break; + case 0x02: + case 0x03: + LOG_INF("GC5005_OTP_WB group%d is Invalid !!\n", index + 1); + gc5005_otp_info.wb_flag = gc5005_otp_info.wb_flag|0x02; + break; + default : + break; + } + + switch((flag_golden>>(2 * index))&0x03) + { + case 0x00: + LOG_INF("GC5005_OTP_GOLDEN group%d is Empty !!\n", index + 1); + gc5005_otp_info.golden_flag = gc5005_otp_info.golden_flag|0x00; + break; + case 0x01: + LOG_INF("GC5005_OTP_GOLDEN group%d is Valid !!\n", index + 1); + golden_start_add = GOLDEN_ROM_START + index * GOLDEN_WIDTH; + gc5005_otp_info.golden_rg= gc5005_read_otp(golden_start_add); + gc5005_otp_info.golden_bg = gc5005_read_otp(golden_start_add + 1); + + if((0==gc5005_otp_info.golden_rg)||(0==gc5005_otp_info.golden_bg)) + { + gc5005_otp_info.golden_flag = gc5005_otp_info.golden_flag|0x02; + LOG_INF("GC5005_OTP_GOLDEN group%d is Error,golden rg or bg = 0!!\n", index + 1); + } + else + { + gc5005_otp_info.golden_flag = gc5005_otp_info.golden_flag|0x01; + } + + break; + case 0x02: + case 0x03: + LOG_INF("GC5005_OTP_GOLDEN group%d is Invalid !!\n", index + 1); + gc5005_otp_info.golden_flag = gc5005_otp_info.golden_flag|0x02; + break; + default : + break; + } + } + + /*print otp information*/ + LOG_INF("GC5005_OTP_INFO:module_id=0x%x\n",gc5005_otp_info.module_id); + LOG_INF("GC5005_OTP_INFO:lens_id=0x%x\n",gc5005_otp_info.lens_id); + LOG_INF("GC5005_OTP_INFO:vcm_id=0x%x\n",gc5005_otp_info.vcm_id); + LOG_INF("GC5005_OTP_INFO:vcm_driver_id=0x%x\n",gc5005_otp_info.vcm_driver_id); + LOG_INF("GC5005_OTP_INFO:data=%d-%d-%d\n",gc5005_otp_info.year,gc5005_otp_info.month,gc5005_otp_info.day); + LOG_INF("GC5005_OTP_WB:r/g=0x%x\n",gc5005_otp_info.rg_gain); + LOG_INF("GC5005_OTP_WB:b/g=0x%x\n",gc5005_otp_info.bg_gain); + LOG_INF("GC5005_OTP_GOLDEN:golden_rg=0x%x\n",gc5005_otp_info.golden_rg); + LOG_INF("GC5005_OTP_GOLDEN:golden_bg=0x%x\n",gc5005_otp_info.golden_bg); +} + +static void gc5005_gcore_update_dd(void) +{ + kal_uint16 i=0,j=0,n=0,m=0,s=0,e=0; + kal_uint16 temp_x=0,temp_y=0; + kal_uint8 temp_type=0; + kal_uint8 temp_val0,temp_val1,temp_val2; + /*TODO*/ + + if(0x01 ==gc5005_otp_info.dd_flag) + { +#if defined(IMAGE_NORMAL_MIRROR) + for(i=0; i gc5005_otp_info.dd_param_y[j]) + { + temp_x = gc5005_otp_info.dd_param_x[i] ; gc5005_otp_info.dd_param_x[i] = gc5005_otp_info.dd_param_x[j] ; gc5005_otp_info.dd_param_x[j] = temp_x; + temp_y = gc5005_otp_info.dd_param_y[i] ; gc5005_otp_info.dd_param_y[i] = gc5005_otp_info.dd_param_y[j] ; gc5005_otp_info.dd_param_y[j] = temp_y; + temp_type = gc5005_otp_info.dd_param_type[i] ; gc5005_otp_info.dd_param_type[i] = gc5005_otp_info.dd_param_type[j]; gc5005_otp_info.dd_param_type[j]= temp_type; + } + } + + } + + //x + for(i=0; i gc5005_otp_info.dd_param_x[m]) + { + temp_x = gc5005_otp_info.dd_param_x[n] ; gc5005_otp_info.dd_param_x[n] = gc5005_otp_info.dd_param_x[m] ; gc5005_otp_info.dd_param_x[m] = temp_x; + temp_y = gc5005_otp_info.dd_param_y[n] ; gc5005_otp_info.dd_param_y[n] = gc5005_otp_info.dd_param_y[m] ; gc5005_otp_info.dd_param_y[m] = temp_y; + temp_type = gc5005_otp_info.dd_param_type[n] ; gc5005_otp_info.dd_param_type[n] = gc5005_otp_info.dd_param_type[m]; gc5005_otp_info.dd_param_type[m]= temp_type; + } + } + } + + } + + } + + + //write SRAM + write_cmos_sensor(0xfe,0x01); + write_cmos_sensor(0xbe,0x00); + write_cmos_sensor(0xa9,0x01); + + for(i=0; i>8)&0X000f); + temp_val2 = (gc5005_otp_info.dd_param_y[i]>>4) & 0xff; + write_cmos_sensor(0xaa,i); + write_cmos_sensor(0xac,temp_val0); + write_cmos_sensor(0xac,temp_val1); + write_cmos_sensor(0xac,temp_val2); + write_cmos_sensor(0xac,gc5005_otp_info.dd_param_type[i]); + LOG_INF("GC5005_OTP_GC val0 = 0x%x , val1 = 0x%x , val2 = 0x%x \n",temp_val0,temp_val1,temp_val2); + LOG_INF("GC5005_OTP_GC x = %d , y = %d \n",((temp_val1&0x0f)<<8) + temp_val0,(temp_val2<<4) + ((temp_val1&0xf0)>>4)); + } + + write_cmos_sensor(0xbe,0x01); + write_cmos_sensor(0xfe,0x00); + } + +} + + +static void gc5005_gcore_update_awb(void) +{ + kal_uint16 r_gain_current = 0 , g_gain_current = 0 , b_gain_current = 0 , base_gain = 0; + kal_uint16 r_gain = 128 , g_gain = 128 , b_gain = 128 ; + kal_uint16 rg_typical,bg_typical; + + rg_typical=RG_TYPICAL; + bg_typical=BG_TYPICAL; + + if(0x01==(gc5005_otp_info.golden_flag&0x01)) + { + rg_typical=gc5005_otp_info.golden_rg; + bg_typical=gc5005_otp_info.golden_bg; + LOG_INF("GC5005_OTP_UPDATE_AWB:rg_typical = 0x%x , bg_typical = 0x%x\n",rg_typical,bg_typical); + } + + if(0x01==(gc5005_otp_info.wb_flag&0x01)) + { + r_gain_current = 256 * rg_typical/gc5005_otp_info.rg_gain; + b_gain_current = 256 * bg_typical/gc5005_otp_info.bg_gain; + g_gain_current = 256; + + base_gain = (r_gain_current imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; +// kal_uint16 realtime_fps = 0; + // kal_uint32 frame_length = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + // Update Shutter + if(shutter > 16383) shutter = 16383; + if(shutter < 4) shutter = 4; + if(shutter <= 30) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x32, 0xfc); + write_cmos_sensor(0xb0, 0x58); + } + else + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x32, 0xf8); + write_cmos_sensor(0xb0, 0x50); + } +/* + if(shutter <= 500) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x32, 0x78); + write_cmos_sensor(0xb0, 0x68); + } + else if(shutter > 550) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x32, 0xf8); + write_cmos_sensor(0xb0, 0x50); + } +*/ + //Update Shutter + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x03, (shutter>>8) & 0x3F); + write_cmos_sensor(0x04, shutter & 0xFF); + + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} /* set_shutter */ + + +/* +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0000; + + reg_gain = ((gain / BASEGAIN) << 4) + ((gain % BASEGAIN) * 16 / BASEGAIN); + reg_gain = reg_gain & 0xFFFF; + return (kal_uint16)reg_gain; +}*/ + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ + +#define ANALOG_GAIN_1 64 // 1.000x +#define ANALOG_GAIN_2 96 // 1.497x +#define ANALOG_GAIN_3 138 // 2.156x +#define ANALOG_GAIN_4 198 // 3.094x +#define ANALOG_GAIN_5 282 // 4.406x +#define ANALOG_GAIN_6 395 // 6.172x +#define ANALOG_GAIN_7 548 // 8.563x +#define ANALOG_GAIN_8 757 // 11.828x + +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 iReg,temp; + + iReg = gain; + + if(iReg < 0x40) + iReg = 0x40; + if((ANALOG_GAIN_1<= iReg)&&(iReg < ANALOG_GAIN_2)) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x21, 0x0f);//gc5005_otp_info.Val21 + write_cmos_sensor(0x29, 0x22);//gc5005_otp_info.Val29 + write_cmos_sensor(0xd8, 0x0b);//04 + //write_cmos_sensor(0xe8, 0x00); + //write_cmos_sensor(0xec, 0x00); + + //analog gain + write_cmos_sensor(0xb6, 0x00); + temp = iReg; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5005MIPI analogic gain 1x, GC5005MIPI add pregain = %d\n",temp); + } + else if((ANALOG_GAIN_2<= iReg)&&(iReg < ANALOG_GAIN_3)) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x21, 0x16);//0a + write_cmos_sensor(0x29, 0x28);//22 + write_cmos_sensor(0xd8, 0x12);//04 + //write_cmos_sensor(0xe8, 0x01); + //write_cmos_sensor(0xec, 0x01); + + //analog gain + write_cmos_sensor(0xb6, 0x01);// + temp = 64*iReg/ANALOG_GAIN_2; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5005MIPI analogic gain 1.469x , GC5005MIPI add pregain = %d\n",temp); + } + else if((ANALOG_GAIN_3<= iReg)&&(iReg < ANALOG_GAIN_4)) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x21, 0x16); + write_cmos_sensor(0x29, 0x28); + write_cmos_sensor(0xd8, 0x12); + //write_cmos_sensor(0xe8, 0x01); + //write_cmos_sensor(0xec, 0x01); + + //analog gain + write_cmos_sensor(0xb6, 0x02);// + temp = 64*iReg/ANALOG_GAIN_3; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5005MIPI analogic gain 2.165x , GC5005MIPI add pregain = %d\n",temp); + } + else if((ANALOG_GAIN_4<= iReg)&&(iReg < ANALOG_GAIN_5)) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x21, 0x16); + write_cmos_sensor(0x29, 0x28); + write_cmos_sensor(0xd8, 0x12); + //write_cmos_sensor(0xe8, 0x01); + //write_cmos_sensor(0xec, 0x01); + + //analog gain + write_cmos_sensor(0xb6, 0x03);// + temp = 64*iReg/ANALOG_GAIN_4; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5005MIPI analogic gain 3.105x , GC5005MIPI add pregain = %d\n",temp); + } + else if((ANALOG_GAIN_5<= iReg)&&(iReg < ANALOG_GAIN_6)) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x21, 0x16); + write_cmos_sensor(0x29, 0x28); + write_cmos_sensor(0xd8, 0x12); + //write_cmos_sensor(0xe8, 0x01); + //write_cmos_sensor(0xec, 0x01); + + //analog gain + write_cmos_sensor(0xb6, 0x04);// + temp = 64*iReg/ANALOG_GAIN_5; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5005MIPI analogic gain 3.632x , GC5005MIPI add pregain = %d\n",temp); + } + else if((ANALOG_GAIN_6<= iReg)&&(iReg < ANALOG_GAIN_7)) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x21, 0x16); + write_cmos_sensor(0x29, 0x28); + write_cmos_sensor(0xd8, 0x12); + //write_cmos_sensor(0xe8, 0x01); + //write_cmos_sensor(0xec, 0x01); + + //analog gain + write_cmos_sensor(0xb6, 0x05);// + temp = 64*iReg/ANALOG_GAIN_6; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5005MIPI analogic gain 4.750x , GC5005MIPI add pregain = %d\n",temp); + } + else if((ANALOG_GAIN_7<= iReg)&&(iReg < ANALOG_GAIN_8)) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x21, 0x16); + write_cmos_sensor(0x29, 0x28); + write_cmos_sensor(0xd8, 0x12); + //write_cmos_sensor(0xe8, 0x01); + //write_cmos_sensor(0xec, 0x01); + + //analog gain + write_cmos_sensor(0xb6, 0x06);// + temp = 64*iReg/ANALOG_GAIN_7; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5005MIPI analogic gain 8.569x , GC5005MIPI add pregain = %d\n",temp); + } + else + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x21, 0x16); + write_cmos_sensor(0x29, 0x28); + write_cmos_sensor(0xd8, 0x12); + //write_cmos_sensor(0xe8, 0x01); + //write_cmos_sensor(0xec, 0x01); + + //analog gain + write_cmos_sensor(0xb6, 0x07);// + temp = 64*iReg/ANALOG_GAIN_8; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5005MIPI analogic gain 11.69x , GC5005MIPI add pregain = %d\n",temp); + } + + return gain; + +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + +} + + +/* +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + +} +*/ +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + +static void sensor_init(void) +{ + LOG_INF("E"); + /*SYS*/ + write_cmos_sensor(0xfe, 0x00); //reset related + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0xfe, 0x00); //modify 1117 + write_cmos_sensor(0xf7, 0x01); + write_cmos_sensor(0xf8, 0x11); //PLL mode2 + write_cmos_sensor(0xf9, 0xaa); + write_cmos_sensor(0xfa, 0x84); + write_cmos_sensor(0xfc, 0x8a); + write_cmos_sensor(0xfe, 0x03); + write_cmos_sensor(0x10, 0x01); + write_cmos_sensor(0xfc, 0x8e); + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x88, 0x03); + write_cmos_sensor(0xe7, 0xc0); + + /*Analog*/ + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x03, 0x06); + write_cmos_sensor(0x04, 0xfc); + write_cmos_sensor(0x05, 0x01); + write_cmos_sensor(0x06, 0xc5); + write_cmos_sensor(0x07, 0x00); + write_cmos_sensor(0x08, 0x10); + write_cmos_sensor(0x09, 0x00); + write_cmos_sensor(0x0a, 0x14); // row start[7:0] + write_cmos_sensor(0x0b, 0x00); + write_cmos_sensor(0x0c, 0x10); + write_cmos_sensor(0x0d, 0x07); + write_cmos_sensor(0x0e, 0xa0); + write_cmos_sensor(0x0f, 0x0a); + write_cmos_sensor(0x10, 0x30); + write_cmos_sensor(0x17, MIRROR);//Don't Change Here!!! + write_cmos_sensor(0x18, 0x02); + write_cmos_sensor(0x19, 0x0a); + write_cmos_sensor(0x1a, 0x1b); + write_cmos_sensor(0x1c, 0x0c); + write_cmos_sensor(0x1d, 0x19); + write_cmos_sensor(0x21, 0x16); + write_cmos_sensor(0x24, 0xb0); + write_cmos_sensor(0x25, 0xc1); + write_cmos_sensor(0x27, 0x64); + write_cmos_sensor(0x29, 0x28); + write_cmos_sensor(0x2a, 0xc3); + write_cmos_sensor(0x31, 0x40); + write_cmos_sensor(0x32, 0xf8); + write_cmos_sensor(0xcd, 0xca); + write_cmos_sensor(0xce, 0xff); + write_cmos_sensor(0xcf, 0x70); + write_cmos_sensor(0xd0, 0xd2); + write_cmos_sensor(0xd1, 0xa0);//gc5005_otp_info.Vald1 + write_cmos_sensor(0xd3, 0x23); + write_cmos_sensor(0xd8, 0x12); + write_cmos_sensor(0xdc, 0xb3); + write_cmos_sensor(0xe1, 0x1b); + write_cmos_sensor(0xe2, 0x00); //20 modify 1123 + write_cmos_sensor(0xe4, 0x78); + write_cmos_sensor(0xe6, 0x1f); + write_cmos_sensor(0xe7, 0xc0); + write_cmos_sensor(0xe8, 0x01); + write_cmos_sensor(0xe9, 0x02); + write_cmos_sensor(0xec, 0x01); + write_cmos_sensor(0xed, 0x02); + + + /*ISP*/ + write_cmos_sensor(0x80, 0x50); + write_cmos_sensor(0x90, 0x01); + write_cmos_sensor(0x92, STARTY);//Don't Change Here!!! crop_win_y1[7:0] + write_cmos_sensor(0x94, STARTX);//Don't Change Here!!! crop_win_x1[7:0] + write_cmos_sensor(0x95, 0x07); + write_cmos_sensor(0x96, 0x98); + write_cmos_sensor(0x97, 0x0a); + write_cmos_sensor(0x98, 0x20); + + /*Gain*/ + write_cmos_sensor(0x99, 0x00); + write_cmos_sensor(0x9a, 0x08); + write_cmos_sensor(0x9b, 0x10); + write_cmos_sensor(0x9c, 0x18); + write_cmos_sensor(0x9d, 0x19); + write_cmos_sensor(0x9e, 0x1a); + write_cmos_sensor(0x9f, 0x1b); + write_cmos_sensor(0xa0, 0x1c); + write_cmos_sensor(0xb0, 0x50); + write_cmos_sensor(0xb1, 0x01); + write_cmos_sensor(0xb2, 0x00); + write_cmos_sensor(0xb6, 0x00); + + /*DD*/ + write_cmos_sensor(0xfe, 0x01); + write_cmos_sensor(0xc2, 0x02); + write_cmos_sensor(0xc3, 0xe0); + write_cmos_sensor(0xc4, 0xd9); + write_cmos_sensor(0xc5, 0x00); + write_cmos_sensor(0xfe, 0x00); + + /*BLK*/ + write_cmos_sensor(0x40, 0x22); + write_cmos_sensor(0x4e, 0x3c); + write_cmos_sensor(0x4f, 0x3c); + write_cmos_sensor(0x60, 0x00); + write_cmos_sensor(0x61, 0x80); + write_cmos_sensor(0xab, 0x00); + write_cmos_sensor(0xac, 0x30); + + /*Dark Sun*/ + write_cmos_sensor(0x68, 0xf4); + write_cmos_sensor(0x6a, 0x00); + write_cmos_sensor(0x6b, 0x00); + write_cmos_sensor(0x6c, 0x50);//f4 + write_cmos_sensor(0x6e, 0xc9);//c1 + + /*MIPI*/ + write_cmos_sensor(0xfe, 0x03); + write_cmos_sensor(0x01, 0x07); + write_cmos_sensor(0x02, 0x33); + write_cmos_sensor(0x03, 0x93); + write_cmos_sensor(0x04, 0x04); + write_cmos_sensor(0x05, 0x00); + write_cmos_sensor(0x06, 0x00); + write_cmos_sensor(0x10, 0x91);//win_width[7:1] + write_cmos_sensor(0x11, 0x2b); + write_cmos_sensor(0x12, 0xa8); + write_cmos_sensor(0x13, 0x0c); + write_cmos_sensor(0x15, 0x00); + write_cmos_sensor(0x18, 0x01); + write_cmos_sensor(0x1b, 0x14); + write_cmos_sensor(0x1c, 0x14); + write_cmos_sensor(0x21, 0x10); + write_cmos_sensor(0x22, 0x05); + write_cmos_sensor(0x23, 0x30); + write_cmos_sensor(0x24, 0x02); + write_cmos_sensor(0x25, 0x16); + write_cmos_sensor(0x26, 0x09); + write_cmos_sensor(0x29, 0x06); + write_cmos_sensor(0x2a, 0x0d); + write_cmos_sensor(0x2b, 0x09); + write_cmos_sensor(0xfe, 0x00); + +} /* sensor_init */ + + +static void preview_setting(void) +{ + LOG_INF("E!\n"); + write_cmos_sensor(0xfe,0x03); + write_cmos_sensor(0x10,0x91); + write_cmos_sensor(0xfe,0x00); +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + write_cmos_sensor(0xfe,0x03); + write_cmos_sensor(0x10,0x91); + write_cmos_sensor(0xfe,0x00); +} + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + write_cmos_sensor(0xfe,0x03); + write_cmos_sensor(0x10,0x91); + write_cmos_sensor(0xfe,0x00); +} + +static void hs_video_setting(void) +{ + LOG_INF("E\n"); + + write_cmos_sensor(0xfe,0x03); + write_cmos_sensor(0x10,0x91); + write_cmos_sensor(0xfe,0x00); +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + write_cmos_sensor(0xfe,0x03); + write_cmos_sensor(0x10,0x91); + write_cmos_sensor(0xfe,0x00); +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x8c, 0x11); + } else { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x8c, 0x10); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* GC5005 OTP */ +#ifdef GC5005_MIPI_USE_OTP + gc5005_gcore_identify_otp(); +#endif + + /* initail sequence write in */ + sensor_init(); + + /*write registers from sram*/ +#ifdef GC5005_MIPI_USE_OTP + gc5005_gcore_update_otp(); +#endif + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + GC5005DuringTestPattern = KAL_FALSE; + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{//This Function not used after ROME + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + + + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + //unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 GC5005MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* GC5005MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/gc5005mipi_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/gc5005mipi_Sensor.h new file mode 100755 index 0000000000000000000000000000000000000000..95e9ebd70ed49f10a727564efc0b8c78f0bd8908 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5005_mipi_raw/gc5005mipi_Sensor.h @@ -0,0 +1,148 @@ +/***************************************************************************** + * + * Filename: + * --------- + * GC5005mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +//#define IMAGE_NORMAL_MIRROR +//#define IMAGE_H_MIRROR +#define IMAGE_V_MIRROR +//#define IMAGE_HV_MIRROR + +#ifdef IMAGE_NORMAL_MIRROR +#define MIRROR 0x54 +#define STARTX 0x05 +#define STARTY 0x05 +#endif + +#ifdef IMAGE_H_MIRROR +#define MIRROR 0x55 +#define STARTX 0x04 +#define STARTY 0x03 +#endif + +#ifdef IMAGE_V_MIRROR +#define MIRROR 0x56 +#define STARTX 0x05 +#define STARTY 0x04 +#endif + +#ifdef IMAGE_HV_MIRROR +#define MIRROR 0x57 +#define STARTX 0x04 +#define STARTY 0x04 +#endif +#ifndef _GC5005MIPI_SENSOR_H +#define _GC5005MIPI_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint32 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + + + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..d826c2b0a8d50c653c1d8ac3a26b22daad582124 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/Makefile @@ -0,0 +1,4 @@ +#include $(srctree)/drivers/misc/mediatek/imgsensor/src/Makefile.custom +obj-y += gc5025mipi_Sensor.o + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/gc5025mipi_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/gc5025mipi_Sensor.c new file mode 100755 index 0000000000000000000000000000000000000000..f9aab7f20dbb6339f48c8739ea9291fee2e4798f --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/gc5025mipi_Sensor.c @@ -0,0 +1,1913 @@ +/***************************************************************************** + * + * Filename: + * --------- + * GC5025mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "gc5025mipi_Sensor.h" + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "GC5025_camera_sensor" +#define LOG_1 LOG_INF("GC5025,MIPI 2LANE\n") +/**************************** Modify end *******************************************/ + +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +#define GC5025OTP_FOR_CUSTOMER + +static DEFINE_SPINLOCK(imgsensor_drv_lock); +kal_bool GC5025DuringTestPattern = KAL_FALSE; + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = GC5025MIPI_SENSOR_ID, //record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0xf7375923, //checksum value for Camera Auto Test + + .pre = { + .pclk = 72000000, //record different mode's pclk + .linelength = 2400, //record different mode's linelength + .framelength = 988, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2592, //record different mode's width of grabwindow //1296 + .grabwindow_height = 1944, //record different mode's height of grabwindow //972 + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk = 72000000, //record different mode's pclk + .linelength = 2400, //record different mode's linelength + .framelength = 988, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .cap1 = { //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 72000000, //record different mode's pclk + .linelength = 2400, //record different mode's linelength + .framelength = 988, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 240, //less than 13M(include 13M),cap1 max framerate is 24fps,16M max framerate is 20fps, 20M max framerate is 15fps + }, + .normal_video = { + .pclk = 72000000, //record different mode's pclk + .linelength = 2400, //record different mode's linelength + .framelength = 988, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .hs_video = { + .pclk = 72000000, //record different mode's pclk + .linelength = 2400, //record different mode's linelength + .framelength = 988, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .slim_video = { + .pclk = 72000000, //record different mode's pclk + .linelength = 2400, //record different mode's linelength + .framelength = 988, + .startx = 0, + .starty = 0, + .grabwindow_width = 2592, + .grabwindow_height = 1944, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .margin = 0, //sensor framelength & shutter margin + .min_shutter = 1, //min shutter + .max_frame_length = 0x3fff,//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, // 1 support; 0 not support + .ihdr_le_firstline = 0, // 1 le first ; 0, se first + .sensor_mode_num = 3, //support sensor mode num + + .cap_delay_frame = 2, //enter capture delay frame num + .pre_delay_frame = 2, //enter preview delay frame num + .video_delay_frame = 2, //enter video delay frame num + .hs_video_delay_frame = 2, //enter high speed video delay frame num + .slim_video_delay_frame = 2,//enter slim video delay frame num + + .isp_driving_current = ISP_DRIVING_6MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_R,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_2_LANE,//mipi lane num + .i2c_addr_table = {0x6e, 0xff},//record sensor support all write id addr, only supprt 4must end with 0xff +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3ED, //current shutter + .gain = 0x40, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 300, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x6e,//record current sensor's i2c write id +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{ + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}, // Preview + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}, // capture + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}, // video + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}, //hight speed video + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0000, 0000, 2592, 1944, 0, 0, 2592, 1944}};// slim video + + + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[1] = {(char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 1, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; + +} + + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ +#if 1 + char pu_send_cmd[2] = {(char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 2, imgsensor.i2c_write_id); +#else + iWriteReg((u16)addr, (u32)para, 2, imgsensor.i2c_write_id); +#endif + +} + + + +#define DD_PARAM_QTY 200 +#define WINDOW_WIDTH 0x0a30 //2608 max effective pixels +#define WINDOW_HEIGHT 0x079c //1948 +#define REG_ROM_START 0x62 +#ifdef GC5025OTP_FOR_CUSTOMER +#define RG_TYPICAL 0x0400 +#define BG_TYPICAL 0x0400 +#define INFO_ROM_START 0x01 +#define INFO_WIDTH 0x08 +#define WB_ROM_START 0x11 +#define WB_WIDTH 0x05 +#define GOLDEN_ROM_START 0x1c +#define GOLDEN_WIDTH 0x05 +#endif + +typedef struct otp_gc5025 +{ + kal_uint16 dd_param_x[DD_PARAM_QTY]; + kal_uint16 dd_param_y[DD_PARAM_QTY]; + kal_uint16 dd_param_type[DD_PARAM_QTY]; + kal_uint16 dd_cnt; + kal_uint16 dd_flag; + kal_uint16 reg_addr[10]; + kal_uint16 reg_value[10]; + kal_uint16 reg_num; +#ifdef GC5025OTP_FOR_CUSTOMER + kal_uint16 module_id; + kal_uint16 lens_id; + kal_uint16 vcm_id; + kal_uint16 vcm_driver_id; + kal_uint16 year; + kal_uint16 month; + kal_uint16 day; + kal_uint16 rg_gain; + kal_uint16 bg_gain; + kal_uint16 wb_flag; + kal_uint16 golden_flag; + kal_uint16 golden_rg; + kal_uint16 golden_bg; +#endif + +}gc5025_otp; + +static gc5025_otp gc5025_otp_info; + +typedef enum{ + otp_page0=0, + otp_page1, +}otp_page; + +typedef enum{ + otp_close=0, + otp_open, +}otp_state; + +static kal_uint8 gc5025_read_otp(kal_uint8 addr) +{ + kal_uint8 value; + kal_uint8 regd4; + kal_uint16 realaddr = addr * 8; + regd4 = read_cmos_sensor(0xd4); + + write_cmos_sensor(0xfe,0x00); + write_cmos_sensor(0xd4,(regd4&0xfc)+((realaddr>>8)&0x03)); + write_cmos_sensor(0xd5,realaddr&0xff); + write_cmos_sensor(0xf3,0x20); + value = read_cmos_sensor(0xd7); + + return value; +} + +static void gc5025_read_otp_group(kal_uint8 addr,kal_uint8* buff,int size) +{ + kal_uint8 i; + kal_uint8 regd4; + kal_uint16 realaddr = addr * 8; + regd4 = read_cmos_sensor(0xd4); + + write_cmos_sensor(0xfe,0x00); + write_cmos_sensor(0xd4,(regd4&0xfc)+((realaddr>>8)&0x03)); + write_cmos_sensor(0xd5,realaddr); + write_cmos_sensor(0xf3,0x20); + write_cmos_sensor(0xf3,0x88); + + for(i=0;i> 4) + j; + gc5025_otp_info.dd_param_type[cnt++] = 2; + } + break; + case 4: + for (j = 0; j < 2; j++) + { + gc5025_otp_info.dd_param_x[cnt] = (((kal_uint16)ddtempbuff[4 * i + 1] & 0x0f) << 8) + ddtempbuff[4 * i]; + gc5025_otp_info.dd_param_y[cnt] = ((kal_uint16)ddtempbuff[4 * i + 2] << 4) + ((ddtempbuff[4 * i + 1] & 0xf0) >> 4) + j; + gc5025_otp_info.dd_param_type[cnt++] = 2; + } + break; + default: + gc5025_otp_info.dd_param_x[cnt] = (((kal_uint16)ddtempbuff[4 * i + 1] & 0x0f) << 8) + ddtempbuff[4 * i]; + gc5025_otp_info.dd_param_y[cnt] = ((kal_uint16)ddtempbuff[4 * i + 2] << 4) + ((ddtempbuff[4 * i + 1] & 0xf0) >> 4); + gc5025_otp_info.dd_param_type[cnt++] = ddtempbuff[4 * i + 3] & 0x0f; + break; + } + } + else + { + LOG_INF("GC5025_OTP_DD:check_id[%d] = %x,checkid error!!\n", i, ddtempbuff[4 * i + 3] & 0xf0); + } + } + + gc5025_otp_info.dd_cnt = cnt; + gc5025_otp_info.dd_flag = 0x01; + break; + case 0x02: + case 0x03: + LOG_INF("GC5025_OTP_DD is Invalid !!\n"); + gc5025_otp_info.dd_flag = 0x02; + break; + default : + break; + } + +/*For Chip Version*/ + LOG_INF("GC5025_OTP_CHIPVESION : flag_chipversion = 0x%x\n",flag_chipversion); + + switch((flag_chipversion>>4)&0x03) + { + case 0x00: + LOG_INF("GC5025_OTP_CHIPVERSION is Empty !!\n"); + break; + case 0x01: + LOG_INF("GC5025_OTP_CHIPVERSION is Valid !!\n"); + gc5025_select_page_otp(otp_page1); + i = 0; + do{ + gc5025_otp_info.reg_addr[i] = gc5025_read_otp(REG_ROM_START + i*2 ) ; + gc5025_otp_info.reg_value[i] = gc5025_read_otp(REG_ROM_START + i*2 + 1 ) ; + LOG_INF("GC5025_OTP_CHIPVERSION reg_addr[%d] = 0x%x,reg_value[%d] = 0x%x\n",i,gc5025_otp_info.reg_addr[i],i,gc5025_otp_info.reg_value[i]); + i++; + }while((gc5025_otp_info.reg_addr[i-1]!=0)&&(i<10)); + gc5025_otp_info.reg_num = i - 1; + break; + case 0x02: + LOG_INF("GC5025_OTP_CHIPVERSION is Invalid !!\n"); + break; + default : + break; + } + +#ifdef GC5025OTP_FOR_CUSTOMER + gc5025_select_page_otp(otp_page1); + flag1 = gc5025_read_otp(0x00); + flag_golden = gc5025_read_otp(0x1b); + LOG_INF("GC5025_OTP : flag1 = 0x%x , flag_golden = 0x%x\n",flag1,flag_golden); + +//INFO&WB + for(index=0;index<2;index++) + { + switch((flag1>>(4 + 2 * index))&0x03) + { + case 0x00: + LOG_INF("GC5025_OTP_INFO group %d is Empty !!\n", index + 1); + break; + case 0x01: + LOG_INF("GC5025_OTP_INFO group %d is Valid !!\n", index + 1); + check = 0; + gc5025_read_otp_group(INFO_ROM_START + index * INFO_WIDTH, &info[0], INFO_WIDTH); + for (i = 0; i < INFO_WIDTH - 1; i++) + { + check += info[i]; + } + if ((check % 255 + 1) == info[INFO_WIDTH-1]) + { + gc5025_otp_info.module_id = info[0]; + gc5025_otp_info.lens_id = info[1]; + gc5025_otp_info.vcm_driver_id = info[2]; + gc5025_otp_info.vcm_id = info[3]; + gc5025_otp_info.year = info[4]; + gc5025_otp_info.month = info[5]; + gc5025_otp_info.day = info[6]; + } + else + { + LOG_INF("GC5025_OTP_INFO Check sum %d Error !!\n", index + 1); + } + break; + case 0x02: + case 0x03: + LOG_INF("GC5025_OTP_INFO group %d is Invalid !!\n", index + 1); + break; + default : + break; + } + + switch((flag1>>(2 * index))&0x03) + { + case 0x00: + LOG_INF("GC5025_OTP_WB group %d is Empty !!\n", index + 1); + gc5025_otp_info.wb_flag = gc5025_otp_info.wb_flag|0x00; + break; + case 0x01: + LOG_INF("GC5025_OTP_WB group %d is Valid !!\n", index + 1); + check = 0; + gc5025_read_otp_group(WB_ROM_START + index * WB_WIDTH, &wb[0], WB_WIDTH); + for (i = 0; i < WB_WIDTH - 1; i++) + { + check += wb[i]; + } + if ((check % 255 + 1) == wb[WB_WIDTH - 1]) + { + gc5025_otp_info.rg_gain = (((wb[0]<<8)&0xff00)|wb[1]) > 0 ? (((wb[0]<<8)&0xff00)|wb[1]) : 0x400; + gc5025_otp_info.bg_gain = (((wb[2]<<8)&0xff00)|wb[3]) > 0 ? (((wb[2]<<8)&0xff00)|wb[3]) : 0x400; + gc5025_otp_info.wb_flag = gc5025_otp_info.wb_flag|0x01; + } + else + { + LOG_INF("GC5025_OTP_WB Check sum %d Error !!\n", index + 1); + } + break; + case 0x02: + case 0x03: + LOG_INF("GC5025_OTP_WB group %d is Invalid !!\n", index + 1); + gc5025_otp_info.wb_flag = gc5025_otp_info.wb_flag|0x02; + break; + default : + break; + } + + switch((flag_golden>>(2 * index))&0x03) + { + case 0x00: + LOG_INF("GC5025_OTP_GOLDEN group %d is Empty !!\n", index + 1); + gc5025_otp_info.golden_flag = gc5025_otp_info.golden_flag|0x00; + break; + case 0x01: + LOG_INF("GC5025_OTP_GOLDEN group %d is Valid !!\n", index + 1); + check = 0; + gc5025_read_otp_group(GOLDEN_ROM_START + index * GOLDEN_WIDTH, &golden[0], GOLDEN_WIDTH); + for (i = 0; i < GOLDEN_WIDTH - 1; i++) + { + check += golden[i]; + } + if ((check % 255 + 1) == golden[GOLDEN_WIDTH - 1]) + { + gc5025_otp_info.golden_rg = (((golden[0]<<8)&0xff00)|golden[1]) > 0 ? (((golden[0]<<8)&0xff00)|golden[1]) : RG_TYPICAL; + gc5025_otp_info.golden_bg = (((golden[2]<<8)&0xff00)|golden[3]) > 0 ? (((golden[2]<<8)&0xff00)|golden[3]) : BG_TYPICAL; + gc5025_otp_info.golden_flag = gc5025_otp_info.golden_flag|0x01; + } + else + { + LOG_INF("GC5025_OTP_GOLDEN Check sum %d Error !!\n", index + 1); + } + break; + case 0x02: + case 0x03: + LOG_INF("GC5025_OTP_GOLDEN group %d is Invalid !!\n", index + 1); + gc5025_otp_info.golden_flag = gc5025_otp_info.golden_flag|0x02; + break; + default : + break; + } + } + + /*print otp information*/ + LOG_INF("GC5025_OTP_INFO:module_id=0x%x\n",gc5025_otp_info.module_id); + LOG_INF("GC5025_OTP_INFO:lens_id=0x%x\n",gc5025_otp_info.lens_id); + LOG_INF("GC5025_OTP_INFO:vcm_id=0x%x\n",gc5025_otp_info.vcm_id); + LOG_INF("GC5025_OTP_INFO:vcm_driver_id=0x%x\n",gc5025_otp_info.vcm_driver_id); + LOG_INF("GC5025_OTP_INFO:data=%d-%d-%d\n",gc5025_otp_info.year,gc5025_otp_info.month,gc5025_otp_info.day); + LOG_INF("GC5025_OTP_WB:r/g=0x%x\n",gc5025_otp_info.rg_gain); + LOG_INF("GC5025_OTP_WB:b/g=0x%x\n",gc5025_otp_info.bg_gain); + LOG_INF("GC5025_OTP_GOLDEN:golden_rg=0x%x\n",gc5025_otp_info.golden_rg); + LOG_INF("GC5025_OTP_GOLDEN:golden_bg=0x%x\n",gc5025_otp_info.golden_bg); +#endif + + +} + + +static void gc5025_gcore_update_dd(void) +{ + kal_uint16 i=0,j=0,n=0,m=0,s=0,e=0; + kal_uint16 temp_x=0,temp_y=0; + kal_uint8 temp_type=0; + kal_uint8 temp_val0,temp_val1,temp_val2; + /*TODO*/ + + if(0x01 ==gc5025_otp_info.dd_flag) + { +#if defined(IMAGE_NORMAL_MIRROR) + //do nothing +#elif defined(IMAGE_H_MIRROR) + for(i=0; i gc5025_otp_info.dd_param_y[j]) + { + temp_x = gc5025_otp_info.dd_param_x[i] ; gc5025_otp_info.dd_param_x[i] = gc5025_otp_info.dd_param_x[j] ; gc5025_otp_info.dd_param_x[j] = temp_x; + temp_y = gc5025_otp_info.dd_param_y[i] ; gc5025_otp_info.dd_param_y[i] = gc5025_otp_info.dd_param_y[j] ; gc5025_otp_info.dd_param_y[j] = temp_y; + temp_type = gc5025_otp_info.dd_param_type[i] ; gc5025_otp_info.dd_param_type[i] = gc5025_otp_info.dd_param_type[j]; gc5025_otp_info.dd_param_type[j]= temp_type; + } + } + + } + + //x + for(i=0; i gc5025_otp_info.dd_param_x[m]) + { + temp_x = gc5025_otp_info.dd_param_x[n] ; gc5025_otp_info.dd_param_x[n] = gc5025_otp_info.dd_param_x[m] ; gc5025_otp_info.dd_param_x[m] = temp_x; + temp_y = gc5025_otp_info.dd_param_y[n] ; gc5025_otp_info.dd_param_y[n] = gc5025_otp_info.dd_param_y[m] ; gc5025_otp_info.dd_param_y[m] = temp_y; + temp_type = gc5025_otp_info.dd_param_type[n] ; gc5025_otp_info.dd_param_type[n] = gc5025_otp_info.dd_param_type[m]; gc5025_otp_info.dd_param_type[m]= temp_type; + } + } + } + + } + + } + + + //write SRAM + write_cmos_sensor(0xfe, 0x01); + write_cmos_sensor(0xa8, 0x00); + write_cmos_sensor(0x9d, 0x04); + write_cmos_sensor(0xbe, 0x00); + write_cmos_sensor(0xa9, 0x01); + + for(i=0; i>8)&0X000f); + temp_val2 = (gc5025_otp_info.dd_param_y[i]>>4) & 0xff; + write_cmos_sensor(0xaa,i); + write_cmos_sensor(0xac,temp_val0); + write_cmos_sensor(0xac,temp_val1); + write_cmos_sensor(0xac,temp_val2); + write_cmos_sensor(0xac,gc5025_otp_info.dd_param_type[i]); + LOG_INF("GC5025_OTP_GC val0 = 0x%x , val1 = 0x%x , val2 = 0x%x \n",temp_val0,temp_val1,temp_val2); + LOG_INF("GC5025_OTP_GC x = %d , y = %d \n",((temp_val1&0x0f)<<8) + temp_val0,(temp_val2<<4) + ((temp_val1&0xf0)>>4)); + } + + write_cmos_sensor(0xbe,0x01); + write_cmos_sensor(0xfe,0x00); + } + +} + +#ifdef GC5025OTP_FOR_CUSTOMER +static void gc5025_gcore_update_wb(void) +{ + kal_uint16 r_gain_current = 0 , g_gain_current = 0 , b_gain_current = 0 , base_gain = 0; + kal_uint16 r_gain = 1024 , g_gain = 1024 , b_gain = 1024 ; + kal_uint16 rg_typical,bg_typical; + + if(0x02==gc5025_otp_info.golden_flag) + { + return; + } + if(0x00==(gc5025_otp_info.golden_flag&0x01)) + { + rg_typical=RG_TYPICAL; + bg_typical=BG_TYPICAL; + } + if(0x01==(gc5025_otp_info.golden_flag&0x01)) + { + rg_typical=gc5025_otp_info.golden_rg; + bg_typical=gc5025_otp_info.golden_bg; + LOG_INF("GC5025_OTP_UPDATE_AWB:rg_typical = 0x%x , bg_typical = 0x%x\n",rg_typical,bg_typical); + } + + if(0x01==(gc5025_otp_info.wb_flag&0x01)) + { + r_gain_current = 1024 * rg_typical/gc5025_otp_info.rg_gain; + b_gain_current = 1024 * bg_typical/gc5025_otp_info.bg_gain; + g_gain_current = 1024; + + base_gain = (r_gain_current>3); + write_cmos_sensor(0xc7,r_gain>>3); + write_cmos_sensor(0xc8,b_gain>>3); + write_cmos_sensor(0xc9,g_gain>>3); + write_cmos_sensor(0xc4,((g_gain&0x07) << 4) + (r_gain&0x07)); + write_cmos_sensor(0xc5,((b_gain&0x07) << 4) + (g_gain&0x07)); + + } + +} +#endif + +static void gc5025_gcore_update_chipversion(void) +{ + kal_uint8 i; + + LOG_INF("GC5025_OTP_UPDATE_CHIPVERSION:reg_num = %d\n",gc5025_otp_info.reg_num); + + write_cmos_sensor(0xfe,0x00); + + for(i=0;i> 8) & 0xFF); + write_cmos_sensor(0x08, vb & 0xFF); + //mdelay(50);*/ + +} /* set_dummy */ + +static kal_uint32 return_sensor_id(void) +{ + return ((read_cmos_sensor(0xf0) << 8) | read_cmos_sensor(0xf1)); +} + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + //kal_int16 dummy_line; + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; +// kal_uint16 realtime_fps = 0; + // kal_uint32 frame_length = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + // Update Shutter + if(shutter > 8191) shutter = 8191; + if(shutter <1) shutter = 1; + + //shutter=shutter/2; + shutter=shutter*2; + + //Update Shutter + write_cmos_sensor(0xfe,0x00); + write_cmos_sensor(0x03,(shutter>>8) & 0x3F); + write_cmos_sensor(0x04,shutter & 0xFF); + + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} /* set_shutter */ + + +/* +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0000; + + reg_gain = ((gain / BASEGAIN) << 4) + ((gain % BASEGAIN) * 16 / BASEGAIN); + reg_gain = reg_gain & 0xFFFF; + return (kal_uint16)reg_gain; +}*/ + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ + +#define ANALOG_GAIN_1 64 // 1.00x +#define ANALOG_GAIN_2 92 // 1.445x + +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 iReg,temp; + + iReg = gain; + + if(iReg < 0x40) + iReg = 0x40; + + if((ANALOG_GAIN_1<= iReg)&&(iReg < ANALOG_GAIN_2)) + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0xb6, 0x00); + temp = iReg; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5025MIPI analogic gain 1x, GC5025MIPI add pregain = %d\n",temp); + } + else + { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0xb6, 0x01); + temp = 64*iReg/ANALOG_GAIN_2; + write_cmos_sensor(0xb1, temp>>6); + write_cmos_sensor(0xb2, (temp<<2)&0xfc); + LOG_INF("GC5025MIPI analogic gain 1.4x, GC5025MIPI add pregain = %d\n",temp); + } + + return gain; + +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + +} + + +/* +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + +} +*/ +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + + +static void sensor_init(void) +{ + LOG_INF("E"); + /*SYS*/ + write_cmos_sensor(0xfe, 0x80); + write_cmos_sensor(0xfe, 0x80); + write_cmos_sensor(0xfe, 0x80); + write_cmos_sensor(0xf7, 0x01); + write_cmos_sensor(0xf8, 0x11); + write_cmos_sensor(0xf9, 0x00); + write_cmos_sensor(0xfa, 0xa0); + write_cmos_sensor(0xfc, 0x2a); + write_cmos_sensor(0xfe, 0x03); + write_cmos_sensor(0x01, 0x07); + write_cmos_sensor(0xfc, 0x2e); + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x88, 0x03); + write_cmos_sensor(0xe7, 0xcc); + + /*Cisctl&Analog*/ + write_cmos_sensor(0x03, 0x07); + write_cmos_sensor(0x04, 0x08); + write_cmos_sensor(0x05, 0x02); + write_cmos_sensor(0x06, 0x58); + write_cmos_sensor(0x08, 0x08); + write_cmos_sensor(0x0a, 0x1c); + write_cmos_sensor(0x0c, 0x04); + write_cmos_sensor(0x0d, 0x07); + write_cmos_sensor(0x0e, 0x9c); + write_cmos_sensor(0x0f, 0x0a); + write_cmos_sensor(0x10, 0x30); + write_cmos_sensor(0x17, MIRROR); + write_cmos_sensor(0x18, 0x02); + write_cmos_sensor(0x19, 0x17); + write_cmos_sensor(0x1a, 0x1a); + write_cmos_sensor(0x1c, 0x1c); + write_cmos_sensor(0x1d, 0x13); + write_cmos_sensor(0x1e, 0x90); + write_cmos_sensor(0x1f, 0xb0); + write_cmos_sensor(0x20, 0x2b); + write_cmos_sensor(0x21, 0x2b); + write_cmos_sensor(0x26, 0x2b); + write_cmos_sensor(0x25, 0xc1); + write_cmos_sensor(0x27, 0x64); + write_cmos_sensor(0x28, 0x00); + write_cmos_sensor(0x29, 0x3f); + write_cmos_sensor(0x2b, 0x80); + write_cmos_sensor(0x2f, 0x4a); + write_cmos_sensor(0x30, 0x11); + write_cmos_sensor(0x31, 0x20); + write_cmos_sensor(0x32, 0xa0); + write_cmos_sensor(0x33, 0x00); + write_cmos_sensor(0x34, 0x55); + write_cmos_sensor(0x38, 0x02); + write_cmos_sensor(0x39, 0x00); + write_cmos_sensor(0x3a, 0x00); + write_cmos_sensor(0x3b, 0x00); + write_cmos_sensor(0x3c, 0x02); + write_cmos_sensor(0x3d, 0x02); + write_cmos_sensor(0x81, 0x60); + write_cmos_sensor(0xcb, 0x02); + write_cmos_sensor(0xcd, 0xad); + write_cmos_sensor(0xcf, 0x50); + write_cmos_sensor(0xd0, 0xb3); + write_cmos_sensor(0xd1, 0x18); + write_cmos_sensor(0xd3, 0xcc); + write_cmos_sensor(0xd9, 0xaa); + write_cmos_sensor(0xdc, 0x03); + write_cmos_sensor(0xdd, 0xaa); + write_cmos_sensor(0xe0, 0x00); + write_cmos_sensor(0xe1, 0x0a);//06 20161205 + write_cmos_sensor(0xe3, 0x2a); + write_cmos_sensor(0xe4, 0xa0); + write_cmos_sensor(0xe5, 0x06); + write_cmos_sensor(0xe6, 0x10); + write_cmos_sensor(0xe7, 0xc2); + + /*ISP*/ + write_cmos_sensor(0x80, 0x10); + write_cmos_sensor(0x89, 0x03); + write_cmos_sensor(0xfe, 0x01); + write_cmos_sensor(0x88, 0xf7); + write_cmos_sensor(0x8a, 0x03); + write_cmos_sensor(0x8e, 0xc7); + + /*BLK*/ + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x40, 0x22); + write_cmos_sensor(0x43, 0x03); + write_cmos_sensor(0xae, 0x40); + write_cmos_sensor(0x60, 0x00); + write_cmos_sensor(0x61, 0x80); + + /*gain*/ + write_cmos_sensor(0xb0, 0x58); + write_cmos_sensor(0xb1, 0x01); + write_cmos_sensor(0xb2, 0x00); + write_cmos_sensor(0xb6, 0x00); + + /*Crop window*/ + write_cmos_sensor(0x91, 0x00); + write_cmos_sensor(0x92, STARTY); + write_cmos_sensor(0x94, STARTX); + + /*MIPI*/ + write_cmos_sensor(0xfe, 0x03); + write_cmos_sensor(0x02, 0x01); + write_cmos_sensor(0x03, 0x8e); + write_cmos_sensor(0x06, 0x80); + write_cmos_sensor(0x15, 0x00); + write_cmos_sensor(0x16, 0x09); + write_cmos_sensor(0x18, 0x0a); + write_cmos_sensor(0x21, 0x10); + write_cmos_sensor(0x22, 0x05); + write_cmos_sensor(0x23, 0x20); + write_cmos_sensor(0x24, 0x02); + write_cmos_sensor(0x25, 0x20); + write_cmos_sensor(0x26, 0x08); + write_cmos_sensor(0x29, 0x06); + write_cmos_sensor(0x2a, 0x0a); + write_cmos_sensor(0x2b, 0x08); + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x3f, 0x91); +} /* sensor_init */ + + +static void preview_setting(void) +{ + LOG_INF("E!\n"); +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); +} + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); +} + +static void hs_video_setting(void) +{ + LOG_INF("E\n"); +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x8c, 0x11); + } else { + write_cmos_sensor(0xfe, 0x00); + write_cmos_sensor(0x8c, 0x10); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /*Don't Remove!!*/ + gc5025_gcore_identify_otp(); + + /* initail sequence write in */ + sensor_init(); + + /*write registers from sram*/ + gc5025_gcore_update_otp(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + GC5025DuringTestPattern = KAL_FALSE; + + return ERROR_NONE; +} /* open */ + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + return ERROR_NONE; +} /* preview */ + + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + return ERROR_NONE; +} /* capture() */ + + +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + return ERROR_NONE; +} /* normal_video */ + + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + return ERROR_NONE; +} /* hs_video */ + + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + return ERROR_NONE; +} /* slim_video */ + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + +static kal_uint32 set_video_mode(UINT16 framerate) +{//This Function not used after ROME + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + //unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + + +UINT32 GC5025MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* GC5025MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/gc5025mipi_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/gc5025mipi_Sensor.h new file mode 100755 index 0000000000000000000000000000000000000000..afd9dfa4de80694b3100d700e33a1ac3dadfc002 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/gc5025mipi_raw/gc5025mipi_Sensor.h @@ -0,0 +1,162 @@ +/***************************************************************************** + * + * Filename: + * --------- + * GC5025mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#define IMAGE_NORMAL_MIRROR +//#define IMAGE_H_MIRROR +//#define IMAGE_V_MIRROR +//#define IMAGE_HV_MIRROR + +#ifdef IMAGE_NORMAL_MIRROR +#define MIRROR 0xc0 +#define STARTY 0x02 +#define STARTX 0x01 +#endif + +#ifdef IMAGE_H_MIRROR +#define MIRROR 0xc1 +#define STARTY 0x02 +#define STARTX 0x02 +#endif + +#ifdef IMAGE_V_MIRROR +#define MIRROR 0xc2 +#define STARTY 0x01 +#define STARTX 0x01 +#endif + +#ifdef IMAGE_HV_MIRROR +#define MIRROR 0xc3 +#define STARTY 0x01 +#define STARTX 0x02 +#endif + +#ifndef _GC5025MIPI_SENSOR_H +#define _GC5025MIPI_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint32 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + +#if 1 +//#define GC5025_VALID_IXEL_NUMS 1080 +//#define GC5025_VALID_LINE_NUMS 2448 +//#define GC5025_DEFAULT_DUMMY_PIXEL_NUMS 0x2d0 // HB +//#define GC5025_DEFAULT_DUMMY_LINE_NUMS 0x08 //VB + +//#define GC5025_INTERNAL_DUMMY_PIXEL_NUMS 0 +//#define GC5025_INTERNAL_DUMMY_LINE_NUMS 28 + +//#define GC5025_VIDEO_PERIOD_PIXEL_NUMS (2160) +//#define GC5025_VIDEO_PERIOD_LINE_NUMS (623) +//#define GC5025_PV_PERIOD_PIXEL_NUMS (2384) +//#define GC5025_PV_PERIOD_LINE_NUMS (496) + +#endif +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..8266019dfb3498214ac09ee85d8ce614465d71a1 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/Makefile @@ -0,0 +1,2 @@ +obj-y += hi553mipiraw_Sensor.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/hi553mipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/hi553mipiraw_Sensor.c new file mode 100755 index 0000000000000000000000000000000000000000..e93bc5ff06467b7cf9baac9a35363d19bddd44e7 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/hi553mipiraw_Sensor.c @@ -0,0 +1,3601 @@ +/***************************************************************************** + * + * Filename: + * --------- + * hi553mipiraw_sensor.c + * + * Project: + * -------- + * ALPS MT6735 + * 20150820: mirror flip not setting,so preview fuction can can use it ,to resolv it. + * 20150914: 逿µ‹å®Œäº†fae è¦æ±‚修改settingï¼Œé‡æ–°åˆsetting. + ------------------------------- + @DateTime: 20151021163817 + modify the winsize info,last time foroget to modity it. + * Description: + ------------------------------- + @DateTime: 20150925173104 move to mt6735 + modify winsizeinfo,add pip setting ,add high speed video setting------------------------------- + @DateTime: 20151119155951 + add group hold fuction at shutter gain setting, for ae peak + * ------------ + * Source code of Sensor driver + * + * PengtaoFan + + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include + +#include "kd_camera_typedef.h" + + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "hi553mipiraw_Sensor.h" + + +/*===FEATURE SWITH===*/ + // #define FPTPDAFSUPPORT //for pdaf switch + // #define FANPENGTAO //for debug log + //#define NONCONTINUEMODE +/*===FEATURE SWITH===*/ + +/****************************Modify Following Strings for Debug****************************/ +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) +#define PFX "hi553" +#define LOG_1 LOG_INF("hi553,MIPI 2LANE\n") +#define SENSORDB LOG_INF +/**************************** Modify end *******************************************/ + + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = HI553_SENSOR_ID, //Sensor ID Value: 0x30C8//record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0xe48556a, //checksum value for Camera Auto Test + + .pre = { + .pclk = 176000000, //record different mode's pclk + .linelength = 2816, //record different mode's linelength + .framelength = 2049, //record different mode's framelength + .startx= 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1296, //record different mode's width of grabwindow + .grabwindow_height = 972, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 14, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, +#ifdef NONCONTINUEMODE + .cap = { + .pclk = 176000000, //record different mode's pclk + .linelength = 2816,//5808, //record different mode's linelength + .framelength = 2083, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2592, //record different mode's width of grabwindow + .grabwindow_height = 1944, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 14, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, +#else //CONTINUEMODE + .cap = { + .pclk = 176000000, //record different mode's pclk + .linelength = 2816,//5808, //record different mode's linelength + .framelength = 2049, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2592, //record different mode's width of grabwindow + .grabwindow_height = 1944, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 14, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, +#endif +#if 0 //fps =24 + .cap1 = { //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 448000000, //record different mode's pclk + .linelength = 5808, //record different mode's linelength + .framelength = 3206, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 4208, //record different mode's width of grabwindow + .grabwindow_height = 3120, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 240, + }, +#endif +#if 1 //fps 15 + .cap1 = { //capture for PIP 15ps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 176000000, //record different mode's pclk + .linelength = 2816,//, //record different mode's linelength + .framelength = 4166, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2592, //record different mode's width of grabwindow + .grabwindow_height = 1944, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 14, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 150, + }, +#endif + .normal_video = { + .pclk = 176000000, //record different mode's pclk + .linelength = 2816,//5808, //record different mode's linelength + .framelength = 2083, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2592, //record different mode's width of grabwindow + .grabwindow_height = 1944, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 14, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .hs_video = { + .pclk = 176000000, //record different mode's pclk + .linelength = 2816, //record different mode's linelength + .framelength = 520, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 640, //record different mode's width of grabwindow + .grabwindow_height = 480, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 19, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 1200, + }, + .slim_video = { + .pclk = 176000000, //record different mode's pclk + .linelength = 2816, //record different mode's linelength + .framelength = 2049, //record different mode's framelength + .startx= 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1296, //record different mode's width of grabwindow + .grabwindow_height = 972, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 14, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom1 = { + .pclk = 176000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom2 = { + .pclk = 176000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom3 = { + .pclk = 176000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom4 = { + .pclk = 176000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom5 = { + .pclk = 440000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + + .margin = 4, //sensor framelength & shutter margin + .min_shutter = 4, //min shutter + .max_frame_length = 0x7FFF,//REG0x0202 <=REG0x0340-5//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 3, //support sensor mode num ,don't support Slow motion + + .cap_delay_frame = 3, //enter capture delay frame num + .pre_delay_frame = 3, //enter preview delay frame num + .video_delay_frame = 3, //enter video delay frame num + .hs_video_delay_frame = 3, //enter high speed video delay frame num + .slim_video_delay_frame = 3,//enter slim video delay frame num + .custom1_delay_frame = 2, + .custom2_delay_frame = 2, + .custom3_delay_frame = 2, + .custom4_delay_frame = 2, + .custom5_delay_frame = 2, + + .isp_driving_current = ISP_DRIVING_8MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = 1,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_2_LANE,//mipi lane num + .i2c_addr_table = {0x40, 0x50, 0xff},//record sensor support all write id addr, only supprt 4must end with 0xff + .i2c_speed = 300, // i2c read/write speed +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_HV_MIRROR,//IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x200, //current shutter + .gain = 0x200, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = KAL_FALSE, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0,//record current sensor's i2c write id +}; + + +/* Sensor output window information*/ + +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{ + { 2592, 1944, 0, 0, 2592, 1944, 1296, 972, 0, 0, 1296, 972, 0, 0, 1296, 972}, // Preview + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0, 0, 2592, 1944, 0, 0, 2592, 1944}, // capture + { 2592, 1944, 0, 0, 2592, 1944, 2592, 1944, 0, 0, 2592, 1944, 0, 0, 2592, 1944}, // capture + { 2592, 1944, 0, 0, 2592, 1944, 1296, 972, 0, 0, 640, 480, 0, 0, 640, 480}, // hight speed video + { 2592, 1944, 0, 0, 2592, 1944, 1296, 972, 0, 0, 1296, 972, 0, 0, 1296, 972}, // slim +}; + +#if 0 +static kal_uint16 read_cmos_sensor_byte(kal_uint16 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iReadRegI2C(pu_send_cmd , 2, (u8*)&get_byte,1,imgsensor.i2c_write_id); + return get_byte; +} +#endif + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 2, imgsensor.i2c_write_id); + return ((get_byte<<8)&0xFF00)|((get_byte>>8)&0x00FF); +} + +#if 0 +static void write_cmos_sensor_byte(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} +#endif + +static void write_cmos_sensor(kal_uint16 addr, kal_uint16 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para >> 8),(char)(para & 0xFF)}; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pusendcmd , 4, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + /* you can set dummy by imgsensor.dummy_line and imgsensor.dummy_pixel, or you can set dummy by imgsensor.frame_length and imgsensor.line_length */ + write_cmos_sensor(0x0006, imgsensor.frame_length & 0xFFFF); + write_cmos_sensor(0x0008, imgsensor.line_length & 0xFFFF); +} /* set_dummy */ + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable(%d) \n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + +#if 0 +static void write_shutter(kal_uint16 shutter) +{ + kal_uint16 realtime_fps = 0; + + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + } else { + // Extend frame length + write_cmos_sensor(0X0006, imgsensor.frame_length & 0xFFFF); + } + + // Update Shutter + write_cmos_sensor(0x0004, (shutter) & 0xFFFF); + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + + //LOG_INF("frame_length = %d ", frame_length); + +} /* write_shutter */ +#endif + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + kal_uint16 realtime_fps = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + //write_shutter(shutter); + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x0046, 0x0100); //group para hold on + write_cmos_sensor(0x0006, imgsensor.frame_length & 0xFFFF); + } + } else { + write_cmos_sensor(0x0046, 0x0100); //group para hold on + // Extend frame length + write_cmos_sensor(0x0006, imgsensor.frame_length & 0xFFFF); + } + + // Update Shutter + write_cmos_sensor(0X0004, shutter & 0xFFFF); + write_cmos_sensor(0x0046, 0x0000); //group para hold off + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0000; + //gain = 64 = 1x real gain. + reg_gain = gain / 4 - 16; + //reg_gain = reg_gain & 0xFFFF; + return (kal_uint16)reg_gain; +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + LOG_INF("set_gain %d \n", gain); + //gain = 64 = 1x real gain. + if (gain < BASEGAIN || gain > 16 * BASEGAIN) { + LOG_INF("Error gain setting"); + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 16 * BASEGAIN) + gain = 16 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + write_cmos_sensor(0x0046, 0x0100); //group para hold o + write_cmos_sensor(0x003A, (reg_gain&0xFFFF)); + write_cmos_sensor(0x0046, 0x0000); //group para hold off + return gain; +} /* set_gain */ + +//[TODO]ihdr_write_shutter_gain not support for hi553 +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length first + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + + write_cmos_sensor(0x3502, (le << 4) & 0xFF); + write_cmos_sensor(0x3501, (le >> 4) & 0xFF); + write_cmos_sensor(0x3500, (le >> 12) & 0x0F); + + write_cmos_sensor(0x3512, (se << 4) & 0xFF); + write_cmos_sensor(0x3511, (se >> 4) & 0xFF); + write_cmos_sensor(0x3510, (se >> 12) & 0x0F); + + set_gain(gain); + } + +} + + +//[TODO] +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + spin_lock(&imgsensor_drv_lock); + imgsensor.mirror= image_mirror; + spin_unlock(&imgsensor_drv_lock); + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor(0x0000,0X00); //GR + break; + case IMAGE_H_MIRROR: + write_cmos_sensor(0x0000,0X01); //R + break; + case IMAGE_V_MIRROR: + write_cmos_sensor(0x0000,0X02); //B + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x0000,0X03); //GB + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} + +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ +static void sensor_init(void) +{ + LOG_INF("E\n"); +//Sensor Information//////////////////////////// +//Sensor : Hi-553 +//Date : 2015-09-05 +//Customer : LGE +//Image size : 2592x1944 +//MCLK : 24MHz +//MIPI speed(Mbps): 880Mbps x 2Lane +//Frame Length : 2049 +//Line Length : 2816 +//Max Fps : 30.5fps +//Pixel order : Green 1st (=GB) +//X/Y-flip : X-flip +//BLC offset : 64code +//////////////////////////////////////////////// + write_cmos_sensor(0x0e00, 0x0102); + write_cmos_sensor(0x0e02, 0x0102); + write_cmos_sensor(0x0e0c, 0x0100); + write_cmos_sensor(0x2000, 0x7400); + write_cmos_sensor(0x2002, 0x1303); + write_cmos_sensor(0x2004, 0x7006); + write_cmos_sensor(0x2006, 0x1303); + write_cmos_sensor(0x2008, 0x0bd2); + write_cmos_sensor(0x200a, 0x5001); + write_cmos_sensor(0x200c, 0x7000); + write_cmos_sensor(0x200e, 0x16c6); + write_cmos_sensor(0x2010, 0x0044); + write_cmos_sensor(0x2012, 0x0307); + write_cmos_sensor(0x2014, 0x0008); + write_cmos_sensor(0x2016, 0x00c4); + write_cmos_sensor(0x2018, 0x0009); + write_cmos_sensor(0x201a, 0x207e); + write_cmos_sensor(0x201c, 0x7001); + write_cmos_sensor(0x201e, 0x0fd0); + write_cmos_sensor(0x2020, 0x00d1); + write_cmos_sensor(0x2022, 0x00a1); + write_cmos_sensor(0x2024, 0x00c9); + write_cmos_sensor(0x2026, 0x030b); + write_cmos_sensor(0x2028, 0x7008); + write_cmos_sensor(0x202a, 0x81c0); + write_cmos_sensor(0x202c, 0x01d7); + write_cmos_sensor(0x202e, 0x0022); + write_cmos_sensor(0x2030, 0x0016); + write_cmos_sensor(0x2032, 0x7006); + write_cmos_sensor(0x2034, 0x0fe2); + write_cmos_sensor(0x2036, 0x0016); + write_cmos_sensor(0x2038, 0x20d0); + write_cmos_sensor(0x203a, 0x15c8); + write_cmos_sensor(0x203c, 0x0007); + write_cmos_sensor(0x203e, 0x0000); + write_cmos_sensor(0x2040, 0x0540); + write_cmos_sensor(0x2042, 0x0007); + write_cmos_sensor(0x2044, 0x0008); + write_cmos_sensor(0x2046, 0x0ec5); + write_cmos_sensor(0x2048, 0x00cc); + write_cmos_sensor(0x204a, 0x00c5); + write_cmos_sensor(0x204c, 0x00cc); + write_cmos_sensor(0x204e, 0x04d7); + write_cmos_sensor(0x2050, 0x18e2); + write_cmos_sensor(0x2052, 0x0016); + write_cmos_sensor(0x2054, 0x70e1); + write_cmos_sensor(0x2056, 0x18e2); + write_cmos_sensor(0x2058, 0x16d6); + write_cmos_sensor(0x205a, 0x0022); + write_cmos_sensor(0x205c, 0x8251); + write_cmos_sensor(0x205e, 0x2128); + write_cmos_sensor(0x2060, 0x2100); + write_cmos_sensor(0x2062, 0x702f); + write_cmos_sensor(0x2064, 0x2f06); + write_cmos_sensor(0x2066, 0x2300); + write_cmos_sensor(0x2068, 0x7800); + write_cmos_sensor(0x206a, 0x7400); + write_cmos_sensor(0x206c, 0x1303); + write_cmos_sensor(0x206e, 0x7006); + write_cmos_sensor(0x2070, 0x1303); + write_cmos_sensor(0x2072, 0x0bd2); + write_cmos_sensor(0x2074, 0x5061); + write_cmos_sensor(0x2076, 0x7000); + write_cmos_sensor(0x2078, 0x16c6); + write_cmos_sensor(0x207a, 0x0044); + write_cmos_sensor(0x207c, 0x0307); + write_cmos_sensor(0x207e, 0x0008); + write_cmos_sensor(0x2080, 0x00c4); + write_cmos_sensor(0x2082, 0x0009); + write_cmos_sensor(0x2084, 0x207e); + write_cmos_sensor(0x2086, 0x7001); + write_cmos_sensor(0x2088, 0x0fd0); + write_cmos_sensor(0x208a, 0x00d1); + write_cmos_sensor(0x208c, 0x00a1); + write_cmos_sensor(0x208e, 0x00c9); + write_cmos_sensor(0x2090, 0x030b); + write_cmos_sensor(0x2092, 0x7008); + write_cmos_sensor(0x2094, 0x84c0); + write_cmos_sensor(0x2096, 0x01d7); + write_cmos_sensor(0x2098, 0x0022); + write_cmos_sensor(0x209a, 0x0016); + write_cmos_sensor(0x209c, 0x7006); + write_cmos_sensor(0x209e, 0x0fe2); + write_cmos_sensor(0x20a0, 0x0016); + write_cmos_sensor(0x20a2, 0x20d0); + write_cmos_sensor(0x20a4, 0x15c8); + write_cmos_sensor(0x20a6, 0x0007); + write_cmos_sensor(0x20a8, 0x0000); + write_cmos_sensor(0x20aa, 0x0540); + write_cmos_sensor(0x20ac, 0x0007); + write_cmos_sensor(0x20ae, 0x0008); + write_cmos_sensor(0x20b0, 0x0ec5); + write_cmos_sensor(0x20b2, 0x00cc); + write_cmos_sensor(0x20b4, 0x00c5); + write_cmos_sensor(0x20b6, 0x00cc); + write_cmos_sensor(0x20b8, 0x04d7); + write_cmos_sensor(0x20ba, 0x18e2); + write_cmos_sensor(0x20bc, 0x0016); + write_cmos_sensor(0x20be, 0x70e1); + write_cmos_sensor(0x20c0, 0x18e2); + write_cmos_sensor(0x20c2, 0x16d6); + write_cmos_sensor(0x20c4, 0x0022); + write_cmos_sensor(0x20c6, 0x8551); + write_cmos_sensor(0x20c8, 0x2128); + write_cmos_sensor(0x20ca, 0x2100); + write_cmos_sensor(0x20cc, 0x2006); + write_cmos_sensor(0x20ce, 0x2300); + write_cmos_sensor(0x20d0, 0x7800); + write_cmos_sensor(0x20d2, 0x7400); + write_cmos_sensor(0x20d4, 0x0005); + write_cmos_sensor(0x20d6, 0x7002); + write_cmos_sensor(0x20d8, 0x1303); + write_cmos_sensor(0x20da, 0x00c5); + write_cmos_sensor(0x20dc, 0x7002); + write_cmos_sensor(0x20de, 0x1303); + write_cmos_sensor(0x20e0, 0x0bd2); + write_cmos_sensor(0x20e2, 0x50c1); + write_cmos_sensor(0x20e4, 0x7000); + write_cmos_sensor(0x20e6, 0x16c6); + write_cmos_sensor(0x20e8, 0x0044); + write_cmos_sensor(0x20ea, 0x0307); + write_cmos_sensor(0x20ec, 0x0008); + write_cmos_sensor(0x20ee, 0x00c4); + write_cmos_sensor(0x20f0, 0x0009); + write_cmos_sensor(0x20f2, 0x207e); + write_cmos_sensor(0x20f4, 0x7001); + write_cmos_sensor(0x20f6, 0x0fd0); + write_cmos_sensor(0x20f8, 0x00d1); + write_cmos_sensor(0x20fa, 0x00a1); + write_cmos_sensor(0x20fc, 0x00c9); + write_cmos_sensor(0x20fe, 0x030b); + write_cmos_sensor(0x2100, 0x7008); + write_cmos_sensor(0x2102, 0x87c0); + write_cmos_sensor(0x2104, 0x01d7); + write_cmos_sensor(0x2106, 0x0022); + write_cmos_sensor(0x2108, 0x0016); + write_cmos_sensor(0x210a, 0x08a2); + write_cmos_sensor(0x210c, 0x0016); + write_cmos_sensor(0x210e, 0x20d0); + write_cmos_sensor(0x2110, 0x15c8); + write_cmos_sensor(0x2112, 0x0007); + write_cmos_sensor(0x2114, 0x0000); + write_cmos_sensor(0x2116, 0x0540); + write_cmos_sensor(0x2118, 0x0007); + write_cmos_sensor(0x211a, 0x0008); + write_cmos_sensor(0x211c, 0x0d45); + write_cmos_sensor(0x211e, 0x00cc); + write_cmos_sensor(0x2120, 0x00c5); + write_cmos_sensor(0x2122, 0x00cc); + write_cmos_sensor(0x2124, 0x04d7); + write_cmos_sensor(0x2126, 0x18e2); + write_cmos_sensor(0x2128, 0x0016); + write_cmos_sensor(0x212a, 0x706f); + write_cmos_sensor(0x212c, 0x18e2); + write_cmos_sensor(0x212e, 0x16d6); + write_cmos_sensor(0x2130, 0x0022); + write_cmos_sensor(0x2132, 0x8857); + write_cmos_sensor(0x2134, 0x2128); + write_cmos_sensor(0x2136, 0x2100); + write_cmos_sensor(0x2138, 0x7800); + write_cmos_sensor(0x213a, 0x3100); + write_cmos_sensor(0x213c, 0x01c6); + write_cmos_sensor(0x213e, 0x01c4); + write_cmos_sensor(0x2140, 0x01c0); + write_cmos_sensor(0x2142, 0x01c6); + write_cmos_sensor(0x2144, 0x2700); + write_cmos_sensor(0x2146, 0x7007); + write_cmos_sensor(0x2148, 0x3f00); + write_cmos_sensor(0x214a, 0x7800); + write_cmos_sensor(0x214c, 0x4031); + write_cmos_sensor(0x214e, 0x83ce); + write_cmos_sensor(0x2150, 0x4346); + write_cmos_sensor(0x2152, 0x40f2); + write_cmos_sensor(0x2154, 0x0006); + write_cmos_sensor(0x2156, 0x81fe); + write_cmos_sensor(0x2158, 0x40f2); + write_cmos_sensor(0x215a, 0x0042); + write_cmos_sensor(0x215c, 0x81ff); + write_cmos_sensor(0x215e, 0x40f2); + write_cmos_sensor(0x2160, 0xff84); + write_cmos_sensor(0x2162, 0x8200); + write_cmos_sensor(0x2164, 0x43c2); + write_cmos_sensor(0x2166, 0x8201); + write_cmos_sensor(0x2168, 0x40b2); + write_cmos_sensor(0x216a, 0x0230); + write_cmos_sensor(0x216c, 0x8030); + write_cmos_sensor(0x216e, 0x40b2); + write_cmos_sensor(0x2170, 0x0032); + write_cmos_sensor(0x2172, 0x8032); + write_cmos_sensor(0x2174, 0x40b2); + write_cmos_sensor(0x2176, 0x01e0); + write_cmos_sensor(0x2178, 0x81d2); + write_cmos_sensor(0x217a, 0x40b2); + write_cmos_sensor(0x217c, 0x03c0); + write_cmos_sensor(0x217e, 0x81d4); + write_cmos_sensor(0x2180, 0x40b2); + write_cmos_sensor(0x2182, 0x05a0); + write_cmos_sensor(0x2184, 0x81d6); + write_cmos_sensor(0x2186, 0x40b2); + write_cmos_sensor(0x2188, 0x0281); + write_cmos_sensor(0x218a, 0x81d8); + write_cmos_sensor(0x218c, 0x40b2); + write_cmos_sensor(0x218e, 0x02c0); + write_cmos_sensor(0x2190, 0x81da); + write_cmos_sensor(0x2192, 0x40b2); + write_cmos_sensor(0x2194, 0x0064); + write_cmos_sensor(0x2196, 0x81e6); + write_cmos_sensor(0x2198, 0x93d2); + write_cmos_sensor(0x219a, 0x003d); + write_cmos_sensor(0x219c, 0x2002); + write_cmos_sensor(0x219e, 0x4030); + write_cmos_sensor(0x21a0, 0xf91e); + write_cmos_sensor(0x21a2, 0x0900); + write_cmos_sensor(0x21a4, 0x7312); + write_cmos_sensor(0x21a6, 0x43d2); + write_cmos_sensor(0x21a8, 0x003d); + write_cmos_sensor(0x21aa, 0x40b2); + write_cmos_sensor(0x21ac, 0x9887); + write_cmos_sensor(0x21ae, 0x0b82); + write_cmos_sensor(0x21b0, 0x40b2); + write_cmos_sensor(0x21b2, 0xc540); + write_cmos_sensor(0x21b4, 0x0b84); + write_cmos_sensor(0x21b6, 0x40b2); + write_cmos_sensor(0x21b8, 0xb540); + write_cmos_sensor(0x21ba, 0x0b86); + write_cmos_sensor(0x21bc, 0x40b2); + write_cmos_sensor(0x21be, 0x0085); + write_cmos_sensor(0x21c0, 0x0b88); + write_cmos_sensor(0x21c2, 0x40b2); + write_cmos_sensor(0x21c4, 0xd304); + write_cmos_sensor(0x21c6, 0x0b8a); + write_cmos_sensor(0x21c8, 0x40b2); + write_cmos_sensor(0x21ca, 0x0420); + write_cmos_sensor(0x21cc, 0x0b8c); + write_cmos_sensor(0x21ce, 0x40b2); + write_cmos_sensor(0x21d0, 0xc200); + write_cmos_sensor(0x21d2, 0x0b8e); + write_cmos_sensor(0x21d4, 0x4392); + write_cmos_sensor(0x21d6, 0x0ba6); + write_cmos_sensor(0x21d8, 0x43d2); + write_cmos_sensor(0x21da, 0x01a0); + write_cmos_sensor(0x21dc, 0x40f2); + write_cmos_sensor(0x21de, 0x0003); + write_cmos_sensor(0x21e0, 0x01a2); + write_cmos_sensor(0x21e2, 0x43d2); + write_cmos_sensor(0x21e4, 0x019d); + write_cmos_sensor(0x21e6, 0x43d2); + write_cmos_sensor(0x21e8, 0x0f82); + write_cmos_sensor(0x21ea, 0x0cff); + write_cmos_sensor(0x21ec, 0x0cff); + write_cmos_sensor(0x21ee, 0x0cff); + write_cmos_sensor(0x21f0, 0x0cff); + write_cmos_sensor(0x21f2, 0x0cff); + write_cmos_sensor(0x21f4, 0x0cff); + write_cmos_sensor(0x21f6, 0x0c32); + write_cmos_sensor(0x21f8, 0x40f2); + write_cmos_sensor(0x21fa, 0x000e); + write_cmos_sensor(0x21fc, 0x0f90); + write_cmos_sensor(0x21fe, 0x4392); + write_cmos_sensor(0x2200, 0x7326); + write_cmos_sensor(0x2202, 0x90f2); + write_cmos_sensor(0x2204, 0x0010); + write_cmos_sensor(0x2206, 0x00bf); + write_cmos_sensor(0x2208, 0x2002); + write_cmos_sensor(0x220a, 0x4030); + write_cmos_sensor(0x220c, 0xf772); + write_cmos_sensor(0x220e, 0x403b); + write_cmos_sensor(0x2210, 0x7f10); + write_cmos_sensor(0x2212, 0x439b); + write_cmos_sensor(0x2214, 0x0000); + write_cmos_sensor(0x2216, 0x403f); + write_cmos_sensor(0x2218, 0xf13a); + write_cmos_sensor(0x221a, 0x12b0); + write_cmos_sensor(0x221c, 0xe12a); + write_cmos_sensor(0x221e, 0x438b); + write_cmos_sensor(0x2220, 0x0000); + write_cmos_sensor(0x2222, 0x4392); + write_cmos_sensor(0x2224, 0x81de); + write_cmos_sensor(0x2226, 0x40b2); + write_cmos_sensor(0x2228, 0x02bc); + write_cmos_sensor(0x222a, 0x731e); + write_cmos_sensor(0x222c, 0x43a2); + write_cmos_sensor(0x222e, 0x81dc); + write_cmos_sensor(0x2230, 0xb3e2); + write_cmos_sensor(0x2232, 0x00b4); + write_cmos_sensor(0x2234, 0x2402); + write_cmos_sensor(0x2236, 0x4392); + write_cmos_sensor(0x2238, 0x81dc); + write_cmos_sensor(0x223a, 0x4325); + write_cmos_sensor(0x223c, 0xb3d2); + write_cmos_sensor(0x223e, 0x00b4); + write_cmos_sensor(0x2240, 0x2002); + write_cmos_sensor(0x2242, 0x4030); + write_cmos_sensor(0x2244, 0xf762); + write_cmos_sensor(0x2246, 0x4305); + write_cmos_sensor(0x2248, 0x12b0); + write_cmos_sensor(0x224a, 0xe16a); + write_cmos_sensor(0x224c, 0x40b2); + write_cmos_sensor(0x224e, 0x012c); + write_cmos_sensor(0x2250, 0x8036); + write_cmos_sensor(0x2252, 0x40b2); + write_cmos_sensor(0x2254, 0x0030); + write_cmos_sensor(0x2256, 0x8034); + write_cmos_sensor(0x2258, 0x12b0); + write_cmos_sensor(0x225a, 0xe238); + write_cmos_sensor(0x225c, 0x4382); + write_cmos_sensor(0x225e, 0x81e4); + write_cmos_sensor(0x2260, 0x40b2); + write_cmos_sensor(0x2262, 0x0005); + write_cmos_sensor(0x2264, 0x7320); + write_cmos_sensor(0x2266, 0x4392); + write_cmos_sensor(0x2268, 0x7326); + write_cmos_sensor(0x226a, 0x425f); + write_cmos_sensor(0x226c, 0x00be); + write_cmos_sensor(0x226e, 0xf07f); + write_cmos_sensor(0x2270, 0x0010); + write_cmos_sensor(0x2272, 0x4f0e); + write_cmos_sensor(0x2274, 0xf03e); + write_cmos_sensor(0x2276, 0x0010); + write_cmos_sensor(0x2278, 0x4e82); + write_cmos_sensor(0x227a, 0x81e2); + write_cmos_sensor(0x227c, 0x425f); + write_cmos_sensor(0x227e, 0x008c); + write_cmos_sensor(0x2280, 0x4fc2); + write_cmos_sensor(0x2282, 0x81e0); + write_cmos_sensor(0x2284, 0x43c2); + write_cmos_sensor(0x2286, 0x81e1); + write_cmos_sensor(0x2288, 0x425f); + write_cmos_sensor(0x228a, 0x00cb); + write_cmos_sensor(0x228c, 0x4f49); + write_cmos_sensor(0x228e, 0x425f); + write_cmos_sensor(0x2290, 0x009e); + write_cmos_sensor(0x2292, 0xf07f); + write_cmos_sensor(0x2294, 0x000f); + write_cmos_sensor(0x2296, 0x4f47); + write_cmos_sensor(0x2298, 0x425f); + write_cmos_sensor(0x229a, 0x009f); + write_cmos_sensor(0x229c, 0xf07f); + write_cmos_sensor(0x229e, 0x000f); + write_cmos_sensor(0x22a0, 0xf37f); + write_cmos_sensor(0x22a2, 0x5f07); + write_cmos_sensor(0x22a4, 0x1107); + write_cmos_sensor(0x22a6, 0x425f); + write_cmos_sensor(0x22a8, 0x00b2); + write_cmos_sensor(0x22aa, 0xf07f); + write_cmos_sensor(0x22ac, 0x000f); + write_cmos_sensor(0x22ae, 0x4f48); + write_cmos_sensor(0x22b0, 0x425f); + write_cmos_sensor(0x22b2, 0x00b3); + write_cmos_sensor(0x22b4, 0xf07f); + write_cmos_sensor(0x22b6, 0x000f); + write_cmos_sensor(0x22b8, 0xf37f); + write_cmos_sensor(0x22ba, 0x5f08); + write_cmos_sensor(0x22bc, 0x1108); + write_cmos_sensor(0x22be, 0x421f); + write_cmos_sensor(0x22c0, 0x0098); + write_cmos_sensor(0x22c2, 0x821f); + write_cmos_sensor(0x22c4, 0x0092); + write_cmos_sensor(0x22c6, 0x531f); + write_cmos_sensor(0x22c8, 0x4f0c); + write_cmos_sensor(0x22ca, 0x470a); + write_cmos_sensor(0x22cc, 0x12b0); + write_cmos_sensor(0x22ce, 0xfb7c); + write_cmos_sensor(0x22d0, 0x4c82); + write_cmos_sensor(0x22d2, 0x0a86); + write_cmos_sensor(0x22d4, 0x9309); + write_cmos_sensor(0x22d6, 0x2002); + write_cmos_sensor(0x22d8, 0x4030); + write_cmos_sensor(0x22da, 0xf750); + write_cmos_sensor(0x22dc, 0x9318); + write_cmos_sensor(0x22de, 0x2002); + write_cmos_sensor(0x22e0, 0x4030); + write_cmos_sensor(0x22e2, 0xf750); + write_cmos_sensor(0x22e4, 0x421f); + write_cmos_sensor(0x22e6, 0x00ac); + write_cmos_sensor(0x22e8, 0x821f); + write_cmos_sensor(0x22ea, 0x00a6); + write_cmos_sensor(0x22ec, 0x531f); + write_cmos_sensor(0x22ee, 0x480e); + write_cmos_sensor(0x22f0, 0x533e); + write_cmos_sensor(0x22f2, 0x4f0c); + write_cmos_sensor(0x22f4, 0x4e0a); + write_cmos_sensor(0x22f6, 0x12b0); + write_cmos_sensor(0x22f8, 0xfb7c); + write_cmos_sensor(0x22fa, 0x4c82); + write_cmos_sensor(0x22fc, 0x0a88); + write_cmos_sensor(0x22fe, 0x484f); + write_cmos_sensor(0x2300, 0x5f4f); + write_cmos_sensor(0x2302, 0x5f4f); + write_cmos_sensor(0x2304, 0x5f4f); + write_cmos_sensor(0x2306, 0x5f4f); + write_cmos_sensor(0x2308, 0x474e); + write_cmos_sensor(0x230a, 0x5e4e); + write_cmos_sensor(0x230c, 0xde4f); + write_cmos_sensor(0x230e, 0x403b); + write_cmos_sensor(0x2310, 0x81e0); + write_cmos_sensor(0x2312, 0xdb6f); + write_cmos_sensor(0x2314, 0x4fc2); + write_cmos_sensor(0x2316, 0x0a8e); + write_cmos_sensor(0x2318, 0x40b2); + write_cmos_sensor(0x231a, 0x0034); + write_cmos_sensor(0x231c, 0x7900); + write_cmos_sensor(0x231e, 0x4292); + write_cmos_sensor(0x2320, 0x0092); + write_cmos_sensor(0x2322, 0x0a8c); + write_cmos_sensor(0x2324, 0x4292); + write_cmos_sensor(0x2326, 0x0098); + write_cmos_sensor(0x2328, 0x0a9e); + write_cmos_sensor(0x232a, 0x4292); + write_cmos_sensor(0x232c, 0x00a6); + write_cmos_sensor(0x232e, 0x0a8a); + write_cmos_sensor(0x2330, 0x40b2); + write_cmos_sensor(0x2332, 0x0c01); + write_cmos_sensor(0x2334, 0x7500); + write_cmos_sensor(0x2336, 0x40b2); + write_cmos_sensor(0x2338, 0x0c01); + write_cmos_sensor(0x233a, 0x8268); + write_cmos_sensor(0x233c, 0x40b2); + write_cmos_sensor(0x233e, 0x0803); + write_cmos_sensor(0x2340, 0x7502); + write_cmos_sensor(0x2342, 0x40b2); + write_cmos_sensor(0x2344, 0x0807); + write_cmos_sensor(0x2346, 0x7504); + write_cmos_sensor(0x2348, 0x40b2); + write_cmos_sensor(0x234a, 0x5803); + write_cmos_sensor(0x234c, 0x7506); + write_cmos_sensor(0x234e, 0x40b2); + write_cmos_sensor(0x2350, 0x0801); + write_cmos_sensor(0x2352, 0x7508); + write_cmos_sensor(0x2354, 0x40b2); + write_cmos_sensor(0x2356, 0x0805); + write_cmos_sensor(0x2358, 0x750a); + write_cmos_sensor(0x235a, 0x40b2); + write_cmos_sensor(0x235c, 0x5801); + write_cmos_sensor(0x235e, 0x750c); + write_cmos_sensor(0x2360, 0x40b2); + write_cmos_sensor(0x2362, 0x0803); + write_cmos_sensor(0x2364, 0x750e); + write_cmos_sensor(0x2366, 0x40b2); + write_cmos_sensor(0x2368, 0x0802); + write_cmos_sensor(0x236a, 0x7510); + write_cmos_sensor(0x236c, 0x40b2); + write_cmos_sensor(0x236e, 0x0800); + write_cmos_sensor(0x2370, 0x7512); + write_cmos_sensor(0x2372, 0x403f); + write_cmos_sensor(0x2374, 0x8268); + write_cmos_sensor(0x2376, 0x12b0); + write_cmos_sensor(0x2378, 0xe2dc); + write_cmos_sensor(0x237a, 0x4392); + write_cmos_sensor(0x237c, 0x7f06); + write_cmos_sensor(0x237e, 0x43a2); + write_cmos_sensor(0x2380, 0x7f0a); + write_cmos_sensor(0x2382, 0x938b); + write_cmos_sensor(0x2384, 0x0000); + write_cmos_sensor(0x2386, 0x2002); + write_cmos_sensor(0x2388, 0x4030); + write_cmos_sensor(0x238a, 0xf71e); + write_cmos_sensor(0x238c, 0x42a2); + write_cmos_sensor(0x238e, 0x7f0a); + write_cmos_sensor(0x2390, 0x40b2); + write_cmos_sensor(0x2392, 0x000a); + write_cmos_sensor(0x2394, 0x8260); + write_cmos_sensor(0x2396, 0x40b2); + write_cmos_sensor(0x2398, 0x01ea); + write_cmos_sensor(0x239a, 0x8262); + write_cmos_sensor(0x239c, 0x40b2); + write_cmos_sensor(0x239e, 0x03ca); + write_cmos_sensor(0x23a0, 0x8264); + write_cmos_sensor(0x23a2, 0x40b2); + write_cmos_sensor(0x23a4, 0x05aa); + write_cmos_sensor(0x23a6, 0x8266); + write_cmos_sensor(0x23a8, 0x40b2); + write_cmos_sensor(0x23aa, 0xf0d2); + write_cmos_sensor(0x23ac, 0x826a); + write_cmos_sensor(0x23ae, 0x4382); + write_cmos_sensor(0x23b0, 0x81d0); + write_cmos_sensor(0x23b2, 0x9382); + write_cmos_sensor(0x23b4, 0x7f0a); + write_cmos_sensor(0x23b6, 0x2413); + write_cmos_sensor(0x23b8, 0x430e); + write_cmos_sensor(0x23ba, 0x421d); + write_cmos_sensor(0x23bc, 0x826a); + write_cmos_sensor(0x23be, 0x0800); + write_cmos_sensor(0x23c0, 0x7f08); + write_cmos_sensor(0x23c2, 0x4e0f); + write_cmos_sensor(0x23c4, 0x5f0f); + write_cmos_sensor(0x23c6, 0x4f92); + write_cmos_sensor(0x23c8, 0x8260); + write_cmos_sensor(0x23ca, 0x7f00); + write_cmos_sensor(0x23cc, 0x4d82); + write_cmos_sensor(0x23ce, 0x7f02); + write_cmos_sensor(0x23d0, 0x531e); + write_cmos_sensor(0x23d2, 0x421f); + write_cmos_sensor(0x23d4, 0x7f0a); + write_cmos_sensor(0x23d6, 0x9f0e); + write_cmos_sensor(0x23d8, 0x2bf2); + write_cmos_sensor(0x23da, 0x4e82); + write_cmos_sensor(0x23dc, 0x81d0); + write_cmos_sensor(0x23de, 0x407a); + write_cmos_sensor(0x23e0, 0xff8b); + write_cmos_sensor(0x23e2, 0x4392); + write_cmos_sensor(0x23e4, 0x731c); + write_cmos_sensor(0x23e6, 0x40b2); + write_cmos_sensor(0x23e8, 0x8038); + write_cmos_sensor(0x23ea, 0x7a00); + write_cmos_sensor(0x23ec, 0x40b2); + write_cmos_sensor(0x23ee, 0x0064); + write_cmos_sensor(0x23f0, 0x7a02); + write_cmos_sensor(0x23f2, 0x40b2); + write_cmos_sensor(0x23f4, 0x0304); + write_cmos_sensor(0x23f6, 0x7a08); + write_cmos_sensor(0x23f8, 0x9382); + write_cmos_sensor(0x23fa, 0x81de); + write_cmos_sensor(0x23fc, 0x2411); + write_cmos_sensor(0x23fe, 0x4382); + write_cmos_sensor(0x2400, 0x81d0); + write_cmos_sensor(0x2402, 0x421d); + write_cmos_sensor(0x2404, 0x81d0); + write_cmos_sensor(0x2406, 0x4d0e); + write_cmos_sensor(0x2408, 0x5e0e); + write_cmos_sensor(0x240a, 0x4e0f); + write_cmos_sensor(0x240c, 0x510f); + write_cmos_sensor(0x240e, 0x4e9f); + write_cmos_sensor(0x2410, 0x0b00); + write_cmos_sensor(0x2412, 0x0000); + write_cmos_sensor(0x2414, 0x531d); + write_cmos_sensor(0x2416, 0x4d82); + write_cmos_sensor(0x2418, 0x81d0); + write_cmos_sensor(0x241a, 0x903d); + write_cmos_sensor(0x241c, 0x0016); + write_cmos_sensor(0x241e, 0x2bf1); + write_cmos_sensor(0x2420, 0xb3d2); + write_cmos_sensor(0x2422, 0x00ce); + write_cmos_sensor(0x2424, 0x2412); + write_cmos_sensor(0x2426, 0x4382); + write_cmos_sensor(0x2428, 0x81d0); + write_cmos_sensor(0x242a, 0x421e); + write_cmos_sensor(0x242c, 0x81d0); + write_cmos_sensor(0x242e, 0x903e); + write_cmos_sensor(0x2430, 0x0009); + write_cmos_sensor(0x2432, 0x2405); + write_cmos_sensor(0x2434, 0x5e0e); + write_cmos_sensor(0x2436, 0x4e0f); + write_cmos_sensor(0x2438, 0x510f); + write_cmos_sensor(0x243a, 0x4fae); + write_cmos_sensor(0x243c, 0x0b80); + write_cmos_sensor(0x243e, 0x5392); + write_cmos_sensor(0x2440, 0x81d0); + write_cmos_sensor(0x2442, 0x90b2); + write_cmos_sensor(0x2444, 0x0016); + write_cmos_sensor(0x2446, 0x81d0); + write_cmos_sensor(0x2448, 0x2bf0); + write_cmos_sensor(0x244a, 0xb3e2); + write_cmos_sensor(0x244c, 0x00ce); + write_cmos_sensor(0x244e, 0x242d); + write_cmos_sensor(0x2450, 0x4292); + write_cmos_sensor(0x2452, 0x0126); + write_cmos_sensor(0x2454, 0x0580); + write_cmos_sensor(0x2456, 0x4292); + write_cmos_sensor(0x2458, 0x01a8); + write_cmos_sensor(0x245a, 0x0582); + write_cmos_sensor(0x245c, 0x4292); + write_cmos_sensor(0x245e, 0x01aa); + write_cmos_sensor(0x2460, 0x0584); + write_cmos_sensor(0x2462, 0x4292); + write_cmos_sensor(0x2464, 0x01ac); + write_cmos_sensor(0x2466, 0x0586); + write_cmos_sensor(0x2468, 0x9382); + write_cmos_sensor(0x246a, 0x003a); + write_cmos_sensor(0x246c, 0x2542); + write_cmos_sensor(0x246e, 0x90b2); + write_cmos_sensor(0x2470, 0x0011); + write_cmos_sensor(0x2472, 0x003a); + write_cmos_sensor(0x2474, 0x2d3e); + write_cmos_sensor(0x2476, 0x403e); + write_cmos_sensor(0x2478, 0x012e); + write_cmos_sensor(0x247a, 0x4e6f); + write_cmos_sensor(0x247c, 0xf37f); + write_cmos_sensor(0x247e, 0x521f); + write_cmos_sensor(0x2480, 0x0126); + write_cmos_sensor(0x2482, 0x4f82); + write_cmos_sensor(0x2484, 0x0580); + write_cmos_sensor(0x2486, 0x4e6f); + write_cmos_sensor(0x2488, 0xf37f); + write_cmos_sensor(0x248a, 0x521f); + write_cmos_sensor(0x248c, 0x01a8); + write_cmos_sensor(0x248e, 0x4f82); + write_cmos_sensor(0x2490, 0x0582); + write_cmos_sensor(0x2492, 0x4e6f); + write_cmos_sensor(0x2494, 0xf37f); + write_cmos_sensor(0x2496, 0x521f); + write_cmos_sensor(0x2498, 0x01aa); + write_cmos_sensor(0x249a, 0x4f82); + write_cmos_sensor(0x249c, 0x0584); + write_cmos_sensor(0x249e, 0x4e6f); + write_cmos_sensor(0x24a0, 0xf37f); + write_cmos_sensor(0x24a2, 0x521f); + write_cmos_sensor(0x24a4, 0x01ac); + write_cmos_sensor(0x24a6, 0x4f82); + write_cmos_sensor(0x24a8, 0x0586); + write_cmos_sensor(0x24aa, 0x9382); + write_cmos_sensor(0x24ac, 0x81de); + write_cmos_sensor(0x24ae, 0x200b); + write_cmos_sensor(0x24b0, 0x0b00); + write_cmos_sensor(0x24b2, 0x7302); + write_cmos_sensor(0x24b4, 0x0258); + write_cmos_sensor(0x24b6, 0x4382); + write_cmos_sensor(0x24b8, 0x7904); + write_cmos_sensor(0x24ba, 0x0900); + write_cmos_sensor(0x24bc, 0x7308); + write_cmos_sensor(0x24be, 0x403f); + write_cmos_sensor(0x24c0, 0x8268); + write_cmos_sensor(0x24c2, 0x12b0); + write_cmos_sensor(0x24c4, 0xe2dc); + write_cmos_sensor(0x24c6, 0x42a2); + write_cmos_sensor(0x24c8, 0x81ea); + write_cmos_sensor(0x24ca, 0x40b2); + write_cmos_sensor(0x24cc, 0x0262); + write_cmos_sensor(0x24ce, 0x81ec); + write_cmos_sensor(0x24d0, 0x40b2); + write_cmos_sensor(0x24d2, 0x02c4); + write_cmos_sensor(0x24d4, 0x81ee); + write_cmos_sensor(0x24d6, 0x40b2); + write_cmos_sensor(0x24d8, 0x0532); + write_cmos_sensor(0x24da, 0x81f0); + write_cmos_sensor(0x24dc, 0x40b2); + write_cmos_sensor(0x24de, 0x03b6); + write_cmos_sensor(0x24e0, 0x81f2); + write_cmos_sensor(0x24e2, 0x40b2); + write_cmos_sensor(0x24e4, 0x03c4); + write_cmos_sensor(0x24e6, 0x81f4); + write_cmos_sensor(0x24e8, 0x40b2); + write_cmos_sensor(0x24ea, 0x03de); + write_cmos_sensor(0x24ec, 0x81f6); + write_cmos_sensor(0x24ee, 0x40b2); + write_cmos_sensor(0x24f0, 0x0596); + write_cmos_sensor(0x24f2, 0x81f8); + write_cmos_sensor(0x24f4, 0x40b2); + write_cmos_sensor(0x24f6, 0x05c4); + write_cmos_sensor(0x24f8, 0x81fa); + write_cmos_sensor(0x24fa, 0x40b2); + write_cmos_sensor(0x24fc, 0x0776); + write_cmos_sensor(0x24fe, 0x81fc); + write_cmos_sensor(0x2500, 0x9382); + write_cmos_sensor(0x2502, 0x81e2); + write_cmos_sensor(0x2504, 0x24e9); + write_cmos_sensor(0x2506, 0x40b2); + write_cmos_sensor(0x2508, 0x0289); + write_cmos_sensor(0x250a, 0x81ee); + write_cmos_sensor(0x250c, 0x40b2); + write_cmos_sensor(0x250e, 0x04e7); + write_cmos_sensor(0x2510, 0x81f0); + write_cmos_sensor(0x2512, 0x12b0); + write_cmos_sensor(0x2514, 0xea88); + write_cmos_sensor(0x2516, 0x0900); + write_cmos_sensor(0x2518, 0x7328); + write_cmos_sensor(0x251a, 0x4582); + write_cmos_sensor(0x251c, 0x7114); + write_cmos_sensor(0x251e, 0x421f); + write_cmos_sensor(0x2520, 0x7316); + write_cmos_sensor(0x2522, 0xc312); + write_cmos_sensor(0x2524, 0x100f); + write_cmos_sensor(0x2526, 0x503f); + write_cmos_sensor(0x2528, 0xff9c); + write_cmos_sensor(0x252a, 0x4f82); + write_cmos_sensor(0x252c, 0x7334); + write_cmos_sensor(0x252e, 0x0f00); + write_cmos_sensor(0x2530, 0x7302); + write_cmos_sensor(0x2532, 0x4392); + write_cmos_sensor(0x2534, 0x7f0c); + write_cmos_sensor(0x2536, 0x4392); + write_cmos_sensor(0x2538, 0x7f10); + write_cmos_sensor(0x253a, 0x4392); + write_cmos_sensor(0x253c, 0x770a); + write_cmos_sensor(0x253e, 0x4392); + write_cmos_sensor(0x2540, 0x770e); + write_cmos_sensor(0x2542, 0x9392); + write_cmos_sensor(0x2544, 0x7114); + write_cmos_sensor(0x2546, 0x207b); + write_cmos_sensor(0x2548, 0x0b00); + write_cmos_sensor(0x254a, 0x7302); + write_cmos_sensor(0x254c, 0x0258); + write_cmos_sensor(0x254e, 0x4382); + write_cmos_sensor(0x2550, 0x7904); + write_cmos_sensor(0x2552, 0x0800); + write_cmos_sensor(0x2554, 0x7118); + write_cmos_sensor(0x2556, 0x403e); + write_cmos_sensor(0x2558, 0x732a); + write_cmos_sensor(0x255a, 0x4e2f); + write_cmos_sensor(0x255c, 0x4f4b); + write_cmos_sensor(0x255e, 0xf35b); + write_cmos_sensor(0x2560, 0xd25b); + write_cmos_sensor(0x2562, 0x81de); + write_cmos_sensor(0x2564, 0x4e2f); + write_cmos_sensor(0x2566, 0xf36f); + write_cmos_sensor(0x2568, 0xdf4b); + write_cmos_sensor(0x256a, 0x1246); + write_cmos_sensor(0x256c, 0x1230); + write_cmos_sensor(0x256e, 0x0cce); + write_cmos_sensor(0x2570, 0x1230); + write_cmos_sensor(0x2572, 0x0cf0); + write_cmos_sensor(0x2574, 0x410f); + write_cmos_sensor(0x2576, 0x503f); + write_cmos_sensor(0x2578, 0x0030); + write_cmos_sensor(0x257a, 0x120f); + write_cmos_sensor(0x257c, 0x421c); + write_cmos_sensor(0x257e, 0x0ca0); + write_cmos_sensor(0x2580, 0x421d); + write_cmos_sensor(0x2582, 0x0caa); + write_cmos_sensor(0x2584, 0x421e); + write_cmos_sensor(0x2586, 0x0cb4); + write_cmos_sensor(0x2588, 0x421f); + write_cmos_sensor(0x258a, 0x0cb2); + write_cmos_sensor(0x258c, 0x12b0); + write_cmos_sensor(0x258e, 0xf96c); + write_cmos_sensor(0x2590, 0x1246); + write_cmos_sensor(0x2592, 0x1230); + write_cmos_sensor(0x2594, 0x0cd0); + write_cmos_sensor(0x2596, 0x1230); + write_cmos_sensor(0x2598, 0x0cf2); + write_cmos_sensor(0x259a, 0x410f); + write_cmos_sensor(0x259c, 0x503f); + write_cmos_sensor(0x259e, 0x003a); + write_cmos_sensor(0x25a0, 0x120f); + write_cmos_sensor(0x25a2, 0x421c); + write_cmos_sensor(0x25a4, 0x0ca2); + write_cmos_sensor(0x25a6, 0x421d); + write_cmos_sensor(0x25a8, 0x0cac); + write_cmos_sensor(0x25aa, 0x421e); + write_cmos_sensor(0x25ac, 0x0cb8); + write_cmos_sensor(0x25ae, 0x421f); + write_cmos_sensor(0x25b0, 0x0cb6); + write_cmos_sensor(0x25b2, 0x12b0); + write_cmos_sensor(0x25b4, 0xf96c); + write_cmos_sensor(0x25b6, 0x1246); + write_cmos_sensor(0x25b8, 0x1230); + write_cmos_sensor(0x25ba, 0x0cd2); + write_cmos_sensor(0x25bc, 0x1230); + write_cmos_sensor(0x25be, 0x0cf4); + write_cmos_sensor(0x25c0, 0x410f); + write_cmos_sensor(0x25c2, 0x503f); + write_cmos_sensor(0x25c4, 0x0044); + write_cmos_sensor(0x25c6, 0x120f); + write_cmos_sensor(0x25c8, 0x421c); + write_cmos_sensor(0x25ca, 0x0ca4); + write_cmos_sensor(0x25cc, 0x421d); + write_cmos_sensor(0x25ce, 0x0cae); + write_cmos_sensor(0x25d0, 0x421e); + write_cmos_sensor(0x25d2, 0x0cbc); + write_cmos_sensor(0x25d4, 0x421f); + write_cmos_sensor(0x25d6, 0x0cba); + write_cmos_sensor(0x25d8, 0x12b0); + write_cmos_sensor(0x25da, 0xf96c); + write_cmos_sensor(0x25dc, 0x1246); + write_cmos_sensor(0x25de, 0x1230); + write_cmos_sensor(0x25e0, 0x0cd4); + write_cmos_sensor(0x25e2, 0x1230); + write_cmos_sensor(0x25e4, 0x0cf6); + write_cmos_sensor(0x25e6, 0x410f); + write_cmos_sensor(0x25e8, 0x503f); + write_cmos_sensor(0x25ea, 0x004e); + write_cmos_sensor(0x25ec, 0x120f); + write_cmos_sensor(0x25ee, 0x421c); + write_cmos_sensor(0x25f0, 0x0ca6); + write_cmos_sensor(0x25f2, 0x421d); + write_cmos_sensor(0x25f4, 0x0cb0); + write_cmos_sensor(0x25f6, 0x421e); + write_cmos_sensor(0x25f8, 0x0cc0); + write_cmos_sensor(0x25fa, 0x421f); + write_cmos_sensor(0x25fc, 0x0cbe); + write_cmos_sensor(0x25fe, 0x12b0); + write_cmos_sensor(0x2600, 0xf96c); + write_cmos_sensor(0x2602, 0x425f); + write_cmos_sensor(0x2604, 0x0c80); + write_cmos_sensor(0x2606, 0xf35f); + write_cmos_sensor(0x2608, 0x5031); + write_cmos_sensor(0x260a, 0x0020); + write_cmos_sensor(0x260c, 0x934f); + write_cmos_sensor(0x260e, 0x2008); + write_cmos_sensor(0x2610, 0x4382); + write_cmos_sensor(0x2612, 0x0cce); + write_cmos_sensor(0x2614, 0x4382); + write_cmos_sensor(0x2616, 0x0cd0); + write_cmos_sensor(0x2618, 0x4382); + write_cmos_sensor(0x261a, 0x0cd2); + write_cmos_sensor(0x261c, 0x4382); + write_cmos_sensor(0x261e, 0x0cd4); + write_cmos_sensor(0x2620, 0xdb46); + write_cmos_sensor(0x2622, 0x464f); + write_cmos_sensor(0x2624, 0x934b); + write_cmos_sensor(0x2626, 0x2001); + write_cmos_sensor(0x2628, 0x5f0f); + write_cmos_sensor(0x262a, 0x4f46); + write_cmos_sensor(0x262c, 0x0900); + write_cmos_sensor(0x262e, 0x7112); + write_cmos_sensor(0x2630, 0x4a4f); + write_cmos_sensor(0x2632, 0x12b0); + write_cmos_sensor(0x2634, 0xfa74); + write_cmos_sensor(0x2636, 0x0b00); + write_cmos_sensor(0x2638, 0x7302); + write_cmos_sensor(0x263a, 0x0036); + write_cmos_sensor(0x263c, 0x3f82); + write_cmos_sensor(0x263e, 0x0b00); + write_cmos_sensor(0x2640, 0x7302); + write_cmos_sensor(0x2642, 0x0036); + write_cmos_sensor(0x2644, 0x4392); + write_cmos_sensor(0x2646, 0x7904); + write_cmos_sensor(0x2648, 0x421e); + write_cmos_sensor(0x264a, 0x7100); + write_cmos_sensor(0x264c, 0x9382); + write_cmos_sensor(0x264e, 0x7114); + write_cmos_sensor(0x2650, 0x2009); + write_cmos_sensor(0x2652, 0x421f); + write_cmos_sensor(0x2654, 0x00a2); + write_cmos_sensor(0x2656, 0x9f0e); + write_cmos_sensor(0x2658, 0x2803); + write_cmos_sensor(0x265a, 0x9e82); + write_cmos_sensor(0x265c, 0x00a8); + write_cmos_sensor(0x265e, 0x2c02); + write_cmos_sensor(0x2660, 0x4382); + write_cmos_sensor(0x2662, 0x7904); + write_cmos_sensor(0x2664, 0x93a2); + write_cmos_sensor(0x2666, 0x7114); + write_cmos_sensor(0x2668, 0x2424); + write_cmos_sensor(0x266a, 0x903e); + write_cmos_sensor(0x266c, 0x0038); + write_cmos_sensor(0x266e, 0x2815); + write_cmos_sensor(0x2670, 0x503e); + write_cmos_sensor(0x2672, 0xffd8); + write_cmos_sensor(0x2674, 0x4e82); + write_cmos_sensor(0x2676, 0x7a04); + write_cmos_sensor(0x2678, 0x43b2); + write_cmos_sensor(0x267a, 0x7a06); + write_cmos_sensor(0x267c, 0x9382); + write_cmos_sensor(0x267e, 0x81e0); + write_cmos_sensor(0x2680, 0x2408); + write_cmos_sensor(0x2682, 0x9382); + write_cmos_sensor(0x2684, 0x81e4); + write_cmos_sensor(0x2686, 0x2411); + write_cmos_sensor(0x2688, 0x421f); + write_cmos_sensor(0x268a, 0x7a04); + write_cmos_sensor(0x268c, 0x832f); + write_cmos_sensor(0x268e, 0x4f82); + write_cmos_sensor(0x2690, 0x7a06); + write_cmos_sensor(0x2692, 0x4392); + write_cmos_sensor(0x2694, 0x7a0a); + write_cmos_sensor(0x2696, 0x0800); + write_cmos_sensor(0x2698, 0x7a0a); + write_cmos_sensor(0x269a, 0x4a4f); + write_cmos_sensor(0x269c, 0x12b0); + write_cmos_sensor(0x269e, 0xfa74); + write_cmos_sensor(0x26a0, 0x930f); + write_cmos_sensor(0x26a2, 0x274f); + write_cmos_sensor(0x26a4, 0x4382); + write_cmos_sensor(0x26a6, 0x81de); + write_cmos_sensor(0x26a8, 0x3ea7); + write_cmos_sensor(0x26aa, 0x421f); + write_cmos_sensor(0x26ac, 0x7a04); + write_cmos_sensor(0x26ae, 0x532f); + write_cmos_sensor(0x26b0, 0x3fee); + write_cmos_sensor(0x26b2, 0x421f); + write_cmos_sensor(0x26b4, 0x00a6); + write_cmos_sensor(0x26b6, 0x9f0e); + write_cmos_sensor(0x26b8, 0x2803); + write_cmos_sensor(0x26ba, 0x9e82); + write_cmos_sensor(0x26bc, 0x00ac); + write_cmos_sensor(0x26be, 0x2c02); + write_cmos_sensor(0x26c0, 0x4382); + write_cmos_sensor(0x26c2, 0x7904); + write_cmos_sensor(0x26c4, 0x4a4f); + write_cmos_sensor(0x26c6, 0xc312); + write_cmos_sensor(0x26c8, 0x104f); + write_cmos_sensor(0x26ca, 0xf35a); + write_cmos_sensor(0x26cc, 0xe37a); + write_cmos_sensor(0x26ce, 0x535a); + write_cmos_sensor(0x26d0, 0xf07a); + write_cmos_sensor(0x26d2, 0xffb8); + write_cmos_sensor(0x26d4, 0xef4a); + write_cmos_sensor(0x26d6, 0x3fc9); + write_cmos_sensor(0x26d8, 0x9382); + write_cmos_sensor(0x26da, 0x81e0); + write_cmos_sensor(0x26dc, 0x271a); + write_cmos_sensor(0x26de, 0x40b2); + write_cmos_sensor(0x26e0, 0x001e); + write_cmos_sensor(0x26e2, 0x81ec); + write_cmos_sensor(0x26e4, 0x40b2); + write_cmos_sensor(0x26e6, 0x01d6); + write_cmos_sensor(0x26e8, 0x81ee); + write_cmos_sensor(0x26ea, 0x40b2); + write_cmos_sensor(0x26ec, 0x0205); + write_cmos_sensor(0x26ee, 0x81f0); + write_cmos_sensor(0x26f0, 0x3f10); + write_cmos_sensor(0x26f2, 0x90b2); + write_cmos_sensor(0x26f4, 0x0011); + write_cmos_sensor(0x26f6, 0x003a); + write_cmos_sensor(0x26f8, 0x2807); + write_cmos_sensor(0x26fa, 0x90b2); + write_cmos_sensor(0x26fc, 0x0080); + write_cmos_sensor(0x26fe, 0x003a); + write_cmos_sensor(0x2700, 0x2c03); + write_cmos_sensor(0x2702, 0x403e); + write_cmos_sensor(0x2704, 0x012f); + write_cmos_sensor(0x2706, 0x3eb9); + write_cmos_sensor(0x2708, 0x90b2); + write_cmos_sensor(0x270a, 0x0080); + write_cmos_sensor(0x270c, 0x003a); + write_cmos_sensor(0x270e, 0x2acd); + write_cmos_sensor(0x2710, 0x90b2); + write_cmos_sensor(0x2712, 0x0100); + write_cmos_sensor(0x2714, 0x003a); + write_cmos_sensor(0x2716, 0x2ec9); + write_cmos_sensor(0x2718, 0x403e); + write_cmos_sensor(0x271a, 0x0130); + write_cmos_sensor(0x271c, 0x3eae); + write_cmos_sensor(0x271e, 0x9382); + write_cmos_sensor(0x2720, 0x81e2); + write_cmos_sensor(0x2722, 0x240b); + write_cmos_sensor(0x2724, 0x40b2); + write_cmos_sensor(0x2726, 0x000e); + write_cmos_sensor(0x2728, 0x8260); + write_cmos_sensor(0x272a, 0x40b2); + write_cmos_sensor(0x272c, 0x028f); + write_cmos_sensor(0x272e, 0x8262); + write_cmos_sensor(0x2730, 0x40b2); + write_cmos_sensor(0x2732, 0xf06a); + write_cmos_sensor(0x2734, 0x826a); + write_cmos_sensor(0x2736, 0x4030); + write_cmos_sensor(0x2738, 0xf3ae); + write_cmos_sensor(0x273a, 0x40b2); + write_cmos_sensor(0x273c, 0x000e); + write_cmos_sensor(0x273e, 0x8260); + write_cmos_sensor(0x2740, 0x40b2); + write_cmos_sensor(0x2742, 0x02ce); + write_cmos_sensor(0x2744, 0x8262); + write_cmos_sensor(0x2746, 0x40b2); + write_cmos_sensor(0x2748, 0xf000); + write_cmos_sensor(0x274a, 0x826a); + write_cmos_sensor(0x274c, 0x4030); + write_cmos_sensor(0x274e, 0xf3ae); + write_cmos_sensor(0x2750, 0x421f); + write_cmos_sensor(0x2752, 0x00ac); + write_cmos_sensor(0x2754, 0x821f); + write_cmos_sensor(0x2756, 0x00a6); + write_cmos_sensor(0x2758, 0x531f); + write_cmos_sensor(0x275a, 0x4f0c); + write_cmos_sensor(0x275c, 0x480a); + write_cmos_sensor(0x275e, 0x4030); + write_cmos_sensor(0x2760, 0xf2f6); + write_cmos_sensor(0x2762, 0xb3e2); + write_cmos_sensor(0x2764, 0x00b4); + write_cmos_sensor(0x2766, 0x2002); + write_cmos_sensor(0x2768, 0x4030); + write_cmos_sensor(0x276a, 0xf248); + write_cmos_sensor(0x276c, 0x4315); + write_cmos_sensor(0x276e, 0x4030); + write_cmos_sensor(0x2770, 0xf248); + write_cmos_sensor(0x2772, 0x43d2); + write_cmos_sensor(0x2774, 0x0180); + write_cmos_sensor(0x2776, 0x4392); + write_cmos_sensor(0x2778, 0x760e); + write_cmos_sensor(0x277a, 0x9382); + write_cmos_sensor(0x277c, 0x760c); + write_cmos_sensor(0x277e, 0x2002); + write_cmos_sensor(0x2780, 0x0c64); + write_cmos_sensor(0x2782, 0x3ffb); + write_cmos_sensor(0x2784, 0x421f); + write_cmos_sensor(0x2786, 0x760a); + write_cmos_sensor(0x2788, 0x932f); + write_cmos_sensor(0x278a, 0x2012); + write_cmos_sensor(0x278c, 0x421b); + write_cmos_sensor(0x278e, 0x018a); + write_cmos_sensor(0x2790, 0x4b82); + write_cmos_sensor(0x2792, 0x7600); + write_cmos_sensor(0x2794, 0x12b0); + write_cmos_sensor(0x2796, 0xfaec); + write_cmos_sensor(0x2798, 0x903b); + write_cmos_sensor(0x279a, 0x1000); + write_cmos_sensor(0x279c, 0x2806); + write_cmos_sensor(0x279e, 0x403f); + write_cmos_sensor(0x27a0, 0x8028); + write_cmos_sensor(0x27a2, 0x12b0); + write_cmos_sensor(0x27a4, 0xfb00); + write_cmos_sensor(0x27a6, 0x4b0d); + write_cmos_sensor(0x27a8, 0x3fe6); + write_cmos_sensor(0x27aa, 0x403f); + write_cmos_sensor(0x27ac, 0x0028); + write_cmos_sensor(0x27ae, 0x3ff9); + write_cmos_sensor(0x27b0, 0x903f); + write_cmos_sensor(0x27b2, 0x0003); + write_cmos_sensor(0x27b4, 0x28af); + write_cmos_sensor(0x27b6, 0x903f); + write_cmos_sensor(0x27b8, 0x0102); + write_cmos_sensor(0x27ba, 0x208a); + write_cmos_sensor(0x27bc, 0x43c2); + write_cmos_sensor(0x27be, 0x018c); + write_cmos_sensor(0x27c0, 0x425f); + write_cmos_sensor(0x27c2, 0x0186); + write_cmos_sensor(0x27c4, 0x4f49); + write_cmos_sensor(0x27c6, 0x93d2); + write_cmos_sensor(0x27c8, 0x018f); + write_cmos_sensor(0x27ca, 0x2480); + write_cmos_sensor(0x27cc, 0x425f); + write_cmos_sensor(0x27ce, 0x018f); + write_cmos_sensor(0x27d0, 0x4f4a); + write_cmos_sensor(0x27d2, 0x4b0e); + write_cmos_sensor(0x27d4, 0x108e); + write_cmos_sensor(0x27d6, 0xf37e); + write_cmos_sensor(0x27d8, 0xc312); + write_cmos_sensor(0x27da, 0x100e); + write_cmos_sensor(0x27dc, 0x110e); + write_cmos_sensor(0x27de, 0x110e); + write_cmos_sensor(0x27e0, 0x110e); + write_cmos_sensor(0x27e2, 0x4d0f); + write_cmos_sensor(0x27e4, 0x108f); + write_cmos_sensor(0x27e6, 0xf37f); + write_cmos_sensor(0x27e8, 0xc312); + write_cmos_sensor(0x27ea, 0x100f); + write_cmos_sensor(0x27ec, 0x110f); + write_cmos_sensor(0x27ee, 0x110f); + write_cmos_sensor(0x27f0, 0x110f); + write_cmos_sensor(0x27f2, 0x9f0e); + write_cmos_sensor(0x27f4, 0x240d); + write_cmos_sensor(0x27f6, 0x0261); + write_cmos_sensor(0x27f8, 0x0000); + write_cmos_sensor(0x27fa, 0x4b82); + write_cmos_sensor(0x27fc, 0x7600); + write_cmos_sensor(0x27fe, 0x12b0); + write_cmos_sensor(0x2800, 0xfaec); + write_cmos_sensor(0x2802, 0x903b); + write_cmos_sensor(0x2804, 0x1000); + write_cmos_sensor(0x2806, 0x285f); + write_cmos_sensor(0x2808, 0x403f); + write_cmos_sensor(0x280a, 0x8028); + write_cmos_sensor(0x280c, 0x12b0); + write_cmos_sensor(0x280e, 0xfb00); + write_cmos_sensor(0x2810, 0x4382); + write_cmos_sensor(0x2812, 0x81d0); + write_cmos_sensor(0x2814, 0x430c); + write_cmos_sensor(0x2816, 0x4c0d); + write_cmos_sensor(0x2818, 0x431f); + write_cmos_sensor(0x281a, 0x4c0e); + write_cmos_sensor(0x281c, 0x930e); + write_cmos_sensor(0x281e, 0x2403); + write_cmos_sensor(0x2820, 0x5f0f); + write_cmos_sensor(0x2822, 0x831e); + write_cmos_sensor(0x2824, 0x23fd); + write_cmos_sensor(0x2826, 0xf90f); + write_cmos_sensor(0x2828, 0x2444); + write_cmos_sensor(0x282a, 0x430f); + write_cmos_sensor(0x282c, 0x9a0f); + write_cmos_sensor(0x282e, 0x2c2c); + write_cmos_sensor(0x2830, 0x4c0e); + write_cmos_sensor(0x2832, 0x4b82); + write_cmos_sensor(0x2834, 0x7600); + write_cmos_sensor(0x2836, 0x4e82); + write_cmos_sensor(0x2838, 0x7602); + write_cmos_sensor(0x283a, 0x4982); + write_cmos_sensor(0x283c, 0x7604); + write_cmos_sensor(0x283e, 0x0264); + write_cmos_sensor(0x2840, 0x0000); + write_cmos_sensor(0x2842, 0x0224); + write_cmos_sensor(0x2844, 0x0000); + write_cmos_sensor(0x2846, 0x0264); + write_cmos_sensor(0x2848, 0x0000); + write_cmos_sensor(0x284a, 0x0260); + write_cmos_sensor(0x284c, 0x0000); + write_cmos_sensor(0x284e, 0x0268); + write_cmos_sensor(0x2850, 0x0000); + write_cmos_sensor(0x2852, 0x0c5a); + write_cmos_sensor(0x2854, 0x02e8); + write_cmos_sensor(0x2856, 0x0000); + write_cmos_sensor(0x2858, 0x0cb5); + write_cmos_sensor(0x285a, 0x02a8); + write_cmos_sensor(0x285c, 0x0000); + write_cmos_sensor(0x285e, 0x0cb5); + write_cmos_sensor(0x2860, 0x0cb5); + write_cmos_sensor(0x2862, 0x0cb5); + write_cmos_sensor(0x2864, 0x0cb5); + write_cmos_sensor(0x2866, 0x0cb5); + write_cmos_sensor(0x2868, 0x0cb5); + write_cmos_sensor(0x286a, 0x0cb5); + write_cmos_sensor(0x286c, 0x0cb5); + write_cmos_sensor(0x286e, 0x0c00); + write_cmos_sensor(0x2870, 0x02e8); + write_cmos_sensor(0x2872, 0x0000); + write_cmos_sensor(0x2874, 0x0cb5); + write_cmos_sensor(0x2876, 0x0268); + write_cmos_sensor(0x2878, 0x0000); + write_cmos_sensor(0x287a, 0x0c64); + write_cmos_sensor(0x287c, 0x0260); + write_cmos_sensor(0x287e, 0x0000); + write_cmos_sensor(0x2880, 0x0c64); + write_cmos_sensor(0x2882, 0x531f); + write_cmos_sensor(0x2884, 0x9a0f); + write_cmos_sensor(0x2886, 0x2bd5); + write_cmos_sensor(0x2888, 0x4c82); + write_cmos_sensor(0x288a, 0x7602); + write_cmos_sensor(0x288c, 0x4b82); + write_cmos_sensor(0x288e, 0x7600); + write_cmos_sensor(0x2890, 0x0270); + write_cmos_sensor(0x2892, 0x0000); + write_cmos_sensor(0x2894, 0x0c1c); + write_cmos_sensor(0x2896, 0x0270); + write_cmos_sensor(0x2898, 0x0001); + write_cmos_sensor(0x289a, 0x421f); + write_cmos_sensor(0x289c, 0x7606); + write_cmos_sensor(0x289e, 0x4f4e); + write_cmos_sensor(0x28a0, 0x431f); + write_cmos_sensor(0x28a2, 0x930d); + write_cmos_sensor(0x28a4, 0x2403); + write_cmos_sensor(0x28a6, 0x5f0f); + write_cmos_sensor(0x28a8, 0x831d); + write_cmos_sensor(0x28aa, 0x23fd); + write_cmos_sensor(0x28ac, 0xff4e); + write_cmos_sensor(0x28ae, 0xdec2); + write_cmos_sensor(0x28b0, 0x018c); + write_cmos_sensor(0x28b2, 0x531c); + write_cmos_sensor(0x28b4, 0x923c); + write_cmos_sensor(0x28b6, 0x2baf); + write_cmos_sensor(0x28b8, 0x4c82); + write_cmos_sensor(0x28ba, 0x81d0); + write_cmos_sensor(0x28bc, 0x0260); + write_cmos_sensor(0x28be, 0x0000); + write_cmos_sensor(0x28c0, 0x4b0d); + write_cmos_sensor(0x28c2, 0x531b); + write_cmos_sensor(0x28c4, 0x3f58); + write_cmos_sensor(0x28c6, 0x403f); + write_cmos_sensor(0x28c8, 0x0028); + write_cmos_sensor(0x28ca, 0x3fa0); + write_cmos_sensor(0x28cc, 0x432a); + write_cmos_sensor(0x28ce, 0x3f81); + write_cmos_sensor(0x28d0, 0x903f); + write_cmos_sensor(0x28d2, 0x0201); + write_cmos_sensor(0x28d4, 0x2350); + write_cmos_sensor(0x28d6, 0x531b); + write_cmos_sensor(0x28d8, 0x4b0e); + write_cmos_sensor(0x28da, 0x108e); + write_cmos_sensor(0x28dc, 0xf37e); + write_cmos_sensor(0x28de, 0xc312); + write_cmos_sensor(0x28e0, 0x100e); + write_cmos_sensor(0x28e2, 0x110e); + write_cmos_sensor(0x28e4, 0x110e); + write_cmos_sensor(0x28e6, 0x110e); + write_cmos_sensor(0x28e8, 0x4d0f); + write_cmos_sensor(0x28ea, 0x108f); + write_cmos_sensor(0x28ec, 0xf37f); + write_cmos_sensor(0x28ee, 0xc312); + write_cmos_sensor(0x28f0, 0x100f); + write_cmos_sensor(0x28f2, 0x110f); + write_cmos_sensor(0x28f4, 0x110f); + write_cmos_sensor(0x28f6, 0x110f); + write_cmos_sensor(0x28f8, 0x9f0e); + write_cmos_sensor(0x28fa, 0x2406); + write_cmos_sensor(0x28fc, 0x0261); + write_cmos_sensor(0x28fe, 0x0000); + write_cmos_sensor(0x2900, 0x4b82); + write_cmos_sensor(0x2902, 0x7600); + write_cmos_sensor(0x2904, 0x12b0); + write_cmos_sensor(0x2906, 0xfaec); + write_cmos_sensor(0x2908, 0x4b0f); + write_cmos_sensor(0x290a, 0x12b0); + write_cmos_sensor(0x290c, 0xfb2a); + write_cmos_sensor(0x290e, 0x4fc2); + write_cmos_sensor(0x2910, 0x0188); + write_cmos_sensor(0x2912, 0x3f49); + write_cmos_sensor(0x2914, 0x931f); + write_cmos_sensor(0x2916, 0x232f); + write_cmos_sensor(0x2918, 0x421b); + write_cmos_sensor(0x291a, 0x018a); + write_cmos_sensor(0x291c, 0x3ff1); + write_cmos_sensor(0x291e, 0x40b2); + write_cmos_sensor(0x2920, 0x1807); + write_cmos_sensor(0x2922, 0x0b82); + write_cmos_sensor(0x2924, 0x40b2); + write_cmos_sensor(0x2926, 0x3540); + write_cmos_sensor(0x2928, 0x0b84); + write_cmos_sensor(0x292a, 0x40b2); + write_cmos_sensor(0x292c, 0x3540); + write_cmos_sensor(0x292e, 0x0b86); + write_cmos_sensor(0x2930, 0x4382); + write_cmos_sensor(0x2932, 0x0b88); + write_cmos_sensor(0x2934, 0x4382); + write_cmos_sensor(0x2936, 0x0b8a); + write_cmos_sensor(0x2938, 0x4382); + write_cmos_sensor(0x293a, 0x0b8c); + write_cmos_sensor(0x293c, 0x40b2); + write_cmos_sensor(0x293e, 0x8200); + write_cmos_sensor(0x2940, 0x0b8e); + write_cmos_sensor(0x2942, 0x4382); + write_cmos_sensor(0x2944, 0x0ba6); + write_cmos_sensor(0x2946, 0x43c2); + write_cmos_sensor(0x2948, 0x01a0); + write_cmos_sensor(0x294a, 0x43c2); + write_cmos_sensor(0x294c, 0x01a2); + write_cmos_sensor(0x294e, 0x43c2); + write_cmos_sensor(0x2950, 0x019d); + write_cmos_sensor(0x2952, 0x40f2); + write_cmos_sensor(0x2954, 0x000a); + write_cmos_sensor(0x2956, 0x0f90); + write_cmos_sensor(0x2958, 0x43c2); + write_cmos_sensor(0x295a, 0x0f82); + write_cmos_sensor(0x295c, 0x43c2); + write_cmos_sensor(0x295e, 0x003d); + write_cmos_sensor(0x2960, 0x4030); + write_cmos_sensor(0x2962, 0xf1a2); + write_cmos_sensor(0x2964, 0x5031); + write_cmos_sensor(0x2966, 0x0032); + write_cmos_sensor(0x2968, 0x4030); + write_cmos_sensor(0x296a, 0xfb3e); + write_cmos_sensor(0x296c, 0x120b); + write_cmos_sensor(0x296e, 0x120a); + write_cmos_sensor(0x2970, 0x1209); + write_cmos_sensor(0x2972, 0x1208); + write_cmos_sensor(0x2974, 0x1207); + write_cmos_sensor(0x2976, 0x1206); + write_cmos_sensor(0x2978, 0x1205); + write_cmos_sensor(0x297a, 0x1204); + write_cmos_sensor(0x297c, 0x8321); + write_cmos_sensor(0x297e, 0x4039); + write_cmos_sensor(0x2980, 0x0014); + write_cmos_sensor(0x2982, 0x5109); + write_cmos_sensor(0x2984, 0x4d07); + write_cmos_sensor(0x2986, 0x4c0d); + write_cmos_sensor(0x2988, 0x4926); + write_cmos_sensor(0x298a, 0x4991); + write_cmos_sensor(0x298c, 0x0002); + write_cmos_sensor(0x298e, 0x0000); + write_cmos_sensor(0x2990, 0x4915); + write_cmos_sensor(0x2992, 0x0004); + write_cmos_sensor(0x2994, 0x4954); + write_cmos_sensor(0x2996, 0x0006); + write_cmos_sensor(0x2998, 0x4f0b); + write_cmos_sensor(0x299a, 0x430a); + write_cmos_sensor(0x299c, 0x4e08); + write_cmos_sensor(0x299e, 0x4309); + write_cmos_sensor(0x29a0, 0xda08); + write_cmos_sensor(0x29a2, 0xdb09); + write_cmos_sensor(0x29a4, 0x570d); + write_cmos_sensor(0x29a6, 0x432e); + write_cmos_sensor(0x29a8, 0x421f); + write_cmos_sensor(0x29aa, 0x0a86); + write_cmos_sensor(0x29ac, 0x821e); + write_cmos_sensor(0x29ae, 0x81e0); + write_cmos_sensor(0x29b0, 0x930e); + write_cmos_sensor(0x29b2, 0x2403); + write_cmos_sensor(0x29b4, 0x5f0f); + write_cmos_sensor(0x29b6, 0x831e); + write_cmos_sensor(0x29b8, 0x23fd); + write_cmos_sensor(0x29ba, 0x8f0d); + write_cmos_sensor(0x29bc, 0x425f); + write_cmos_sensor(0x29be, 0x0ce1); + write_cmos_sensor(0x29c0, 0xf37f); + write_cmos_sensor(0x29c2, 0x421e); + write_cmos_sensor(0x29c4, 0x00ba); + write_cmos_sensor(0x29c6, 0x4f0a); + write_cmos_sensor(0x29c8, 0x4e0c); + write_cmos_sensor(0x29ca, 0x12b0); + write_cmos_sensor(0x29cc, 0xfb42); + write_cmos_sensor(0x29ce, 0x4e0f); + write_cmos_sensor(0x29d0, 0x108f); + write_cmos_sensor(0x29d2, 0x4f47); + write_cmos_sensor(0x29d4, 0xc312); + write_cmos_sensor(0x29d6, 0x1007); + write_cmos_sensor(0x29d8, 0x5808); + write_cmos_sensor(0x29da, 0x6909); + write_cmos_sensor(0x29dc, 0x5808); + write_cmos_sensor(0x29de, 0x6909); + write_cmos_sensor(0x29e0, 0x5808); + write_cmos_sensor(0x29e2, 0x6909); + write_cmos_sensor(0x29e4, 0x5808); + write_cmos_sensor(0x29e6, 0x6909); + write_cmos_sensor(0x29e8, 0x5808); + write_cmos_sensor(0x29ea, 0x6909); + write_cmos_sensor(0x29ec, 0x5808); + write_cmos_sensor(0x29ee, 0x6909); + write_cmos_sensor(0x29f0, 0x4d0e); + write_cmos_sensor(0x29f2, 0x430f); + write_cmos_sensor(0x29f4, 0x480c); + write_cmos_sensor(0x29f6, 0x490d); + write_cmos_sensor(0x29f8, 0x4e0a); + write_cmos_sensor(0x29fa, 0x4f0b); + write_cmos_sensor(0x29fc, 0x12b0); + write_cmos_sensor(0x29fe, 0xfb98); + write_cmos_sensor(0x2a00, 0x5c07); + write_cmos_sensor(0x2a02, 0x474e); + write_cmos_sensor(0x2a04, 0xf07e); + write_cmos_sensor(0x2a06, 0x003f); + write_cmos_sensor(0x2a08, 0xb392); + write_cmos_sensor(0x2a0a, 0x732a); + write_cmos_sensor(0x2a0c, 0x2015); + write_cmos_sensor(0x2a0e, 0xb3a2); + write_cmos_sensor(0x2a10, 0x732a); + write_cmos_sensor(0x2a12, 0x2012); + write_cmos_sensor(0x2a14, 0x9382); + write_cmos_sensor(0x2a16, 0x81de); + write_cmos_sensor(0x2a18, 0x200f); + write_cmos_sensor(0x2a1a, 0x9344); + write_cmos_sensor(0x2a1c, 0x200d); + write_cmos_sensor(0x2a1e, 0x470c); + write_cmos_sensor(0x2a20, 0x430d); + write_cmos_sensor(0x2a22, 0x462e); + write_cmos_sensor(0x2a24, 0x430f); + write_cmos_sensor(0x2a26, 0x5e0c); + write_cmos_sensor(0x2a28, 0x6f0d); + write_cmos_sensor(0x2a2a, 0xc312); + write_cmos_sensor(0x2a2c, 0x100d); + write_cmos_sensor(0x2a2e, 0x100c); + write_cmos_sensor(0x2a30, 0x4c07); + write_cmos_sensor(0x2a32, 0x4c4e); + write_cmos_sensor(0x2a34, 0xf07e); + write_cmos_sensor(0x2a36, 0x003f); + write_cmos_sensor(0x2a38, 0x4786); + write_cmos_sensor(0x2a3a, 0x0000); + write_cmos_sensor(0x2a3c, 0xb0f2); + write_cmos_sensor(0x2a3e, 0x0010); + write_cmos_sensor(0x2a40, 0x0c83); + write_cmos_sensor(0x2a42, 0x2409); + write_cmos_sensor(0x2a44, 0x4e4f); + write_cmos_sensor(0x2a46, 0x5f0f); + write_cmos_sensor(0x2a48, 0x5f0f); + write_cmos_sensor(0x2a4a, 0x5f0f); + write_cmos_sensor(0x2a4c, 0x5f0f); + write_cmos_sensor(0x2a4e, 0x5f0f); + write_cmos_sensor(0x2a50, 0x4f85); + write_cmos_sensor(0x2a52, 0x0000); + write_cmos_sensor(0x2a54, 0x3c02); + write_cmos_sensor(0x2a56, 0x4385); + write_cmos_sensor(0x2a58, 0x0000); + write_cmos_sensor(0x2a5a, 0x412f); + write_cmos_sensor(0x2a5c, 0x478f); + write_cmos_sensor(0x2a5e, 0x0000); + write_cmos_sensor(0x2a60, 0x5321); + write_cmos_sensor(0x2a62, 0x4134); + write_cmos_sensor(0x2a64, 0x4135); + write_cmos_sensor(0x2a66, 0x4136); + write_cmos_sensor(0x2a68, 0x4137); + write_cmos_sensor(0x2a6a, 0x4138); + write_cmos_sensor(0x2a6c, 0x4139); + write_cmos_sensor(0x2a6e, 0x413a); + write_cmos_sensor(0x2a70, 0x413b); + write_cmos_sensor(0x2a72, 0x4130); + write_cmos_sensor(0x2a74, 0x4f4e); + write_cmos_sensor(0x2a76, 0x421f); + write_cmos_sensor(0x2a78, 0x7316); + write_cmos_sensor(0x2a7a, 0xc312); + write_cmos_sensor(0x2a7c, 0x100f); + write_cmos_sensor(0x2a7e, 0x821f); + write_cmos_sensor(0x2a80, 0x81e6); + write_cmos_sensor(0x2a82, 0x4f82); + write_cmos_sensor(0x2a84, 0x7334); + write_cmos_sensor(0x2a86, 0x0f00); + write_cmos_sensor(0x2a88, 0x7302); + write_cmos_sensor(0x2a8a, 0xb0b2); + write_cmos_sensor(0x2a8c, 0x000f); + write_cmos_sensor(0x2a8e, 0x7300); + write_cmos_sensor(0x2a90, 0x200e); + write_cmos_sensor(0x2a92, 0x403f); + write_cmos_sensor(0x2a94, 0x0cd8); + write_cmos_sensor(0x2a96, 0x43df); + write_cmos_sensor(0x2a98, 0x0000); + write_cmos_sensor(0x2a9a, 0x43cf); + write_cmos_sensor(0x2a9c, 0x0000); + write_cmos_sensor(0x2a9e, 0x4ec2); + write_cmos_sensor(0x2aa0, 0x0c5a); + write_cmos_sensor(0x2aa2, 0x4ec2); + write_cmos_sensor(0x2aa4, 0x0c5c); + write_cmos_sensor(0x2aa6, 0x4ec2); + write_cmos_sensor(0x2aa8, 0x0c5e); + write_cmos_sensor(0x2aaa, 0x4ec2); + write_cmos_sensor(0x2aac, 0x0c60); + write_cmos_sensor(0x2aae, 0x421f); + write_cmos_sensor(0x2ab0, 0x7112); + write_cmos_sensor(0x2ab2, 0x93a2); + write_cmos_sensor(0x2ab4, 0x7114); + write_cmos_sensor(0x2ab6, 0x2408); + write_cmos_sensor(0x2ab8, 0x9382); + write_cmos_sensor(0x2aba, 0x7112); + write_cmos_sensor(0x2abc, 0x2403); + write_cmos_sensor(0x2abe, 0x5292); + write_cmos_sensor(0x2ac0, 0x81dc); + write_cmos_sensor(0x2ac2, 0x7114); + write_cmos_sensor(0x2ac4, 0x430f); + write_cmos_sensor(0x2ac6, 0x4130); + write_cmos_sensor(0x2ac8, 0xf31f); + write_cmos_sensor(0x2aca, 0x27f6); + write_cmos_sensor(0x2acc, 0x4382); + write_cmos_sensor(0x2ace, 0x7f10); + write_cmos_sensor(0x2ad0, 0x40b2); + write_cmos_sensor(0x2ad2, 0x0003); + write_cmos_sensor(0x2ad4, 0x7114); + write_cmos_sensor(0x2ad6, 0x40b2); + write_cmos_sensor(0x2ad8, 0x000a); + write_cmos_sensor(0x2ada, 0x7334); + write_cmos_sensor(0x2adc, 0x0f00); + write_cmos_sensor(0x2ade, 0x7302); + write_cmos_sensor(0x2ae0, 0x4392); + write_cmos_sensor(0x2ae2, 0x7708); + write_cmos_sensor(0x2ae4, 0x4382); + write_cmos_sensor(0x2ae6, 0x770e); + write_cmos_sensor(0x2ae8, 0x431f); + write_cmos_sensor(0x2aea, 0x4130); + write_cmos_sensor(0x2aec, 0x0260); + write_cmos_sensor(0x2aee, 0x0000); + write_cmos_sensor(0x2af0, 0x0c64); + write_cmos_sensor(0x2af2, 0x0c64); + write_cmos_sensor(0x2af4, 0x0240); + write_cmos_sensor(0x2af6, 0x0000); + write_cmos_sensor(0x2af8, 0x0260); + write_cmos_sensor(0x2afa, 0x0000); + write_cmos_sensor(0x2afc, 0x0c1e); + write_cmos_sensor(0x2afe, 0x4130); + write_cmos_sensor(0x2b00, 0x4f0e); + write_cmos_sensor(0x2b02, 0xc312); + write_cmos_sensor(0x2b04, 0x100f); + write_cmos_sensor(0x2b06, 0x110f); + write_cmos_sensor(0x2b08, 0xc312); + write_cmos_sensor(0x2b0a, 0x100f); + write_cmos_sensor(0x2b0c, 0x4f82); + write_cmos_sensor(0x2b0e, 0x7600); + write_cmos_sensor(0x2b10, 0xf03e); + write_cmos_sensor(0x2b12, 0x0007); + write_cmos_sensor(0x2b14, 0x4e82); + write_cmos_sensor(0x2b16, 0x7602); + write_cmos_sensor(0x2b18, 0x0262); + write_cmos_sensor(0x2b1a, 0x0000); + write_cmos_sensor(0x2b1c, 0x0222); + write_cmos_sensor(0x2b1e, 0x0000); + write_cmos_sensor(0x2b20, 0x0262); + write_cmos_sensor(0x2b22, 0x0000); + write_cmos_sensor(0x2b24, 0x0260); + write_cmos_sensor(0x2b26, 0x0000); + write_cmos_sensor(0x2b28, 0x4130); + write_cmos_sensor(0x2b2a, 0x4f82); + write_cmos_sensor(0x2b2c, 0x7600); + write_cmos_sensor(0x2b2e, 0x0270); + write_cmos_sensor(0x2b30, 0x0000); + write_cmos_sensor(0x2b32, 0x0c1c); + write_cmos_sensor(0x2b34, 0x0270); + write_cmos_sensor(0x2b36, 0x0001); + write_cmos_sensor(0x2b38, 0x421f); + write_cmos_sensor(0x2b3a, 0x7606); + write_cmos_sensor(0x2b3c, 0x4130); + write_cmos_sensor(0x2b3e, 0xdf02); + write_cmos_sensor(0x2b40, 0x3ffe); + write_cmos_sensor(0x2b42, 0x430e); + write_cmos_sensor(0x2b44, 0x930a); + write_cmos_sensor(0x2b46, 0x2407); + write_cmos_sensor(0x2b48, 0xc312); + write_cmos_sensor(0x2b4a, 0x100c); + write_cmos_sensor(0x2b4c, 0x2801); + write_cmos_sensor(0x2b4e, 0x5a0e); + write_cmos_sensor(0x2b50, 0x5a0a); + write_cmos_sensor(0x2b52, 0x930c); + write_cmos_sensor(0x2b54, 0x23f7); + write_cmos_sensor(0x2b56, 0x4130); + write_cmos_sensor(0x2b58, 0x430e); + write_cmos_sensor(0x2b5a, 0x430f); + write_cmos_sensor(0x2b5c, 0x3c08); + write_cmos_sensor(0x2b5e, 0xc312); + write_cmos_sensor(0x2b60, 0x100d); + write_cmos_sensor(0x2b62, 0x100c); + write_cmos_sensor(0x2b64, 0x2802); + write_cmos_sensor(0x2b66, 0x5a0e); + write_cmos_sensor(0x2b68, 0x6b0f); + write_cmos_sensor(0x2b6a, 0x5a0a); + write_cmos_sensor(0x2b6c, 0x6b0b); + write_cmos_sensor(0x2b6e, 0x930c); + write_cmos_sensor(0x2b70, 0x23f6); + write_cmos_sensor(0x2b72, 0x930d); + write_cmos_sensor(0x2b74, 0x23f4); + write_cmos_sensor(0x2b76, 0x4130); + write_cmos_sensor(0x2b78, 0x4030); + write_cmos_sensor(0x2b7a, 0xfb58); + write_cmos_sensor(0x2b7c, 0xee0e); + write_cmos_sensor(0x2b7e, 0x403b); + write_cmos_sensor(0x2b80, 0x0011); + write_cmos_sensor(0x2b82, 0x3c05); + write_cmos_sensor(0x2b84, 0x100d); + write_cmos_sensor(0x2b86, 0x6e0e); + write_cmos_sensor(0x2b88, 0x9a0e); + write_cmos_sensor(0x2b8a, 0x2801); + write_cmos_sensor(0x2b8c, 0x8a0e); + write_cmos_sensor(0x2b8e, 0x6c0c); + write_cmos_sensor(0x2b90, 0x6d0d); + write_cmos_sensor(0x2b92, 0x831b); + write_cmos_sensor(0x2b94, 0x23f7); + write_cmos_sensor(0x2b96, 0x4130); + write_cmos_sensor(0x2b98, 0xef0f); + write_cmos_sensor(0x2b9a, 0xee0e); + write_cmos_sensor(0x2b9c, 0x4039); + write_cmos_sensor(0x2b9e, 0x0021); + write_cmos_sensor(0x2ba0, 0x3c0a); + write_cmos_sensor(0x2ba2, 0x1008); + write_cmos_sensor(0x2ba4, 0x6e0e); + write_cmos_sensor(0x2ba6, 0x6f0f); + write_cmos_sensor(0x2ba8, 0x9b0f); + write_cmos_sensor(0x2baa, 0x2805); + write_cmos_sensor(0x2bac, 0x2002); + write_cmos_sensor(0x2bae, 0x9a0e); + write_cmos_sensor(0x2bb0, 0x2802); + write_cmos_sensor(0x2bb2, 0x8a0e); + write_cmos_sensor(0x2bb4, 0x7b0f); + write_cmos_sensor(0x2bb6, 0x6c0c); + write_cmos_sensor(0x2bb8, 0x6d0d); + write_cmos_sensor(0x2bba, 0x6808); + write_cmos_sensor(0x2bbc, 0x8319); + write_cmos_sensor(0x2bbe, 0x23f1); + write_cmos_sensor(0x2bc0, 0x4130); + write_cmos_sensor(0x2bc2, 0x4130); + write_cmos_sensor(0x2ffe, 0xf14c); + write_cmos_sensor(0x3000, 0x01fc); + write_cmos_sensor(0x3002, 0x320f); + write_cmos_sensor(0x3004, 0x0001); + write_cmos_sensor(0x3006, 0x01fc); + write_cmos_sensor(0x3008, 0x320f); + write_cmos_sensor(0x300a, 0x0001); + write_cmos_sensor(0x300c, 0x01fc); + write_cmos_sensor(0x300e, 0x320f); + write_cmos_sensor(0x3010, 0x0001); + write_cmos_sensor(0x4000, 0x2500); + write_cmos_sensor(0x4002, 0xfc2c); + write_cmos_sensor(0x4004, 0xc004); + write_cmos_sensor(0x4006, 0x2500); + write_cmos_sensor(0x4008, 0xfc2c); + write_cmos_sensor(0x400a, 0xc004); + write_cmos_sensor(0x400c, 0x2500); + write_cmos_sensor(0x400e, 0xfc2c); + write_cmos_sensor(0x4010, 0xc004); + write_cmos_sensor(0x0a00, 0x0000); //stream off + write_cmos_sensor(0x0b00, 0x0000); + write_cmos_sensor(0x0b02, 0x9887); + write_cmos_sensor(0x0b04, 0xc540); + write_cmos_sensor(0x0b06, 0xb540); + write_cmos_sensor(0x0b08, 0x0085); + write_cmos_sensor(0x0b0a, 0xd304); + write_cmos_sensor(0x0b0c, 0x0420); + write_cmos_sensor(0x0b0e, 0xc200); + write_cmos_sensor(0x0b10, 0xac20); + write_cmos_sensor(0x0b12, 0x0000); + write_cmos_sensor(0x0b14, 0x404c); + write_cmos_sensor(0x0b16, 0x6e0b); + write_cmos_sensor(0x0b18, 0xf20b); + write_cmos_sensor(0x0b1a, 0x0000); + write_cmos_sensor(0x0b1c, 0x0000); + write_cmos_sensor(0x0b1e, 0x0081); + write_cmos_sensor(0x0b20, 0x0000); + write_cmos_sensor(0x0b22, 0xcc80); + write_cmos_sensor(0x0b24, 0x0400); + write_cmos_sensor(0x0b26, 0x0001); + write_cmos_sensor(0x0b28, 0x0807); + write_cmos_sensor(0x0c00, 0x1190); //blc enable + write_cmos_sensor(0x0c02, 0x0011); + write_cmos_sensor(0x0c04, 0x0000); + write_cmos_sensor(0x0c06, 0x0200); + write_cmos_sensor(0x0c10, 0x0040); + write_cmos_sensor(0x0c12, 0x0040); + write_cmos_sensor(0x0c14, 0x0040); + write_cmos_sensor(0x0c16, 0x0040); + write_cmos_sensor(0x0a10, 0x4000); + write_cmos_sensor(0x0c18, 0x80ff); + write_cmos_sensor(0x0c60, 0x0600); + write_cmos_sensor(0x0000, 0x0100); //image orient + write_cmos_sensor(0x0f0a, 0x0000); + write_cmos_sensor(0x0e0a, 0x0001); + write_cmos_sensor(0x004a, 0x0100); + write_cmos_sensor(0x000c, 0x0022); + write_cmos_sensor(0x0008, 0x0b00); //line length pck + write_cmos_sensor(0x000a, 0x0f00); + write_cmos_sensor(0x005a, 0x0202); + write_cmos_sensor(0x0012, 0x000e); + write_cmos_sensor(0x0018, 0x0a31); + write_cmos_sensor(0x0034, 0x0700); + write_cmos_sensor(0x0022, 0x0008); + write_cmos_sensor(0x0028, 0x0017); + write_cmos_sensor(0x0024, 0x0038); + write_cmos_sensor(0x002a, 0x003d); + write_cmos_sensor(0x0026, 0x0040); + write_cmos_sensor(0x002c, 0x07d7); + write_cmos_sensor(0x002e, 0x1111); + write_cmos_sensor(0x0030, 0x1111); + write_cmos_sensor(0x0032, 0x1111); + write_cmos_sensor(0x001a, 0x1111); + write_cmos_sensor(0x001c, 0x1111); + write_cmos_sensor(0x001e, 0x1111); + write_cmos_sensor(0x0006, 0x0801); //frame length lines + write_cmos_sensor(0x0a22, 0x0000); + write_cmos_sensor(0x0a12, 0x0a20); //x output size + write_cmos_sensor(0x0a14, 0x0798); //y output size + write_cmos_sensor(0x003e, 0x0000); + write_cmos_sensor(0x0004, 0x07fb); //coarse int. time + write_cmos_sensor(0x0052, 0x019c); + write_cmos_sensor(0x0002, 0x0000); + write_cmos_sensor(0x0a02, 0x0100); + write_cmos_sensor(0x0a04, 0x014a); //isp_en + write_cmos_sensor(0x0508, 0x0100); + write_cmos_sensor(0x0046, 0x0000); + write_cmos_sensor(0x003a, 0x0000); //analog gain 1x + write_cmos_sensor(0x0036, 0x0070); + write_cmos_sensor(0x0038, 0x7000); + write_cmos_sensor(0x004c, 0x7070); + write_cmos_sensor(0x0122, 0x0301); + write_cmos_sensor(0x0804, 0x0002); + write_cmos_sensor(0x004e, 0x0300); + write_cmos_sensor(0x0a1a, 0x0800); + write_cmos_sensor(0x0126, 0x0100); //Dgain_gr + write_cmos_sensor(0x0128, 0x0100); //Dgain_gb + write_cmos_sensor(0x012a, 0x0100); //Dgain_r + write_cmos_sensor(0x012c, 0x0100); //Dgain_b + write_cmos_sensor(0x012e, 0x0203); + write_cmos_sensor(0x0130, 0x0600); + write_cmos_sensor(0x090c, 0x0a38); + write_cmos_sensor(0x090e, 0x002a); +//=============================================== +// mipi 2 lane 880Mbps +//=============================================== + write_cmos_sensor(0x0902, 0x431a); + write_cmos_sensor(0x0914, 0xc10b); + write_cmos_sensor(0x0916, 0x071f); + write_cmos_sensor(0x091c, 0x0e09); + write_cmos_sensor(0x0918, 0x0307); + write_cmos_sensor(0x091a, 0x0c0c); + write_cmos_sensor(0x091e, 0x0a00); + write_cmos_sensor(0x0a00, 0x0100); //stream on + +} /* sensor_init */ + + +static void preview_setting(void) +{ + LOG_INF("E\n"); + +//Sensor Information//////////////////////////// +//Sensor : Hi-553 +//Date : 2015-09-05 +//Customer : LGE +//Image size : 1296x972 +//MCLK : 24MHz +//MIPI speed(Mbps): 440Mbps x 2Lane +//Frame Length : 2049 +//Line Length : 2816 +//Max Fps : 30.5fps +//Pixel order : Green 1st (=GB) +//X/Y-flip : X-flip +//BLC offset : 64code +//////////////////////////////////////////////// + +write_cmos_sensor(0x0a00, 0x0000); //stream on +write_cmos_sensor(0x0b14, 0x404c); +write_cmos_sensor(0x0b16, 0x6e0b); +write_cmos_sensor(0x0b18, 0xf24b); +write_cmos_sensor(0x004a, 0x0100); +write_cmos_sensor(0x000c, 0x0022); +write_cmos_sensor(0x0008, 0x0b00); +write_cmos_sensor(0x005a, 0x0204); +write_cmos_sensor(0x0012, 0x000e); +write_cmos_sensor(0x0018, 0x0a31); +write_cmos_sensor(0x0024, 0x0038); +write_cmos_sensor(0x002a, 0x003d); +write_cmos_sensor(0x0026, 0x0040); +write_cmos_sensor(0x002c, 0x07d7); +write_cmos_sensor(0x002e, 0x1111); +write_cmos_sensor(0x0030, 0x1111); +write_cmos_sensor(0x0032, 0x3311); +write_cmos_sensor(0x001a, 0x1111); +write_cmos_sensor(0x001c, 0x1111); +write_cmos_sensor(0x001e, 0x1111); +write_cmos_sensor(0x0006, 0x0801); //frame length lines +write_cmos_sensor(0x0a22, 0x0000); +write_cmos_sensor(0x0a12, 0x0510); //x output size +write_cmos_sensor(0x0a14, 0x03cc); //y output size +write_cmos_sensor(0x003e, 0x0000); +write_cmos_sensor(0x0004, 0x07fb); //coarse int. time +write_cmos_sensor(0x0a04, 0x016a); //isp_en +write_cmos_sensor(0x0a1a, 0x0800); +write_cmos_sensor(0x090c, 0x0514); +write_cmos_sensor(0x090e, 0x0018); +//=============================================== +// mipi 2 lane 440Mbps +//=============================================== +write_cmos_sensor(0x0902, 0x431a); +write_cmos_sensor(0x0914, 0xc106); +write_cmos_sensor(0x0916, 0x040f); +write_cmos_sensor(0x091c, 0x0e05); +write_cmos_sensor(0x0918, 0x0304); +write_cmos_sensor(0x091a, 0x0609); +write_cmos_sensor(0x091e, 0x0300); +write_cmos_sensor(0x0a00, 0x0100); //stream on + +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + if (currefps == 300) { +//Sensor Information//////////////////////////// +//Sensor : Hi-553 +//Date : 2015-09-05 +//Customer : LGE +//Image size : 2592x1944 +//MCLK : 24MHz +//MIPI speed(Mbps): 880Mbps x 2Lane +//Frame Length : 2049 +//Line Length : 2816 +//Max Fps : 30.5fps +//Pixel order : Green 1st (=GB) +//X/Y-flip : X-flip +//BLC offset : 64code +//////////////////////////////////////////////// + +write_cmos_sensor(0x0a00, 0x0000); //stream on +write_cmos_sensor(0x0b14, 0x404c); +write_cmos_sensor(0x0b16, 0x6e0b); +write_cmos_sensor(0x0b18, 0xf20b); +write_cmos_sensor(0x004a, 0x0100); +write_cmos_sensor(0x000c, 0x0022); +write_cmos_sensor(0x0008, 0x0b00); +write_cmos_sensor(0x005a, 0x0202); +write_cmos_sensor(0x0012, 0x000e); +write_cmos_sensor(0x0018, 0x0a31); +write_cmos_sensor(0x0024, 0x0038); +write_cmos_sensor(0x002a, 0x003d); +write_cmos_sensor(0x0026, 0x0040); +write_cmos_sensor(0x002c, 0x07d7); +write_cmos_sensor(0x002e, 0x1111); +write_cmos_sensor(0x0030, 0x1111); +write_cmos_sensor(0x0032, 0x1111); +write_cmos_sensor(0x001a, 0x1111); +write_cmos_sensor(0x001c, 0x1111); +write_cmos_sensor(0x001e, 0x1111); +write_cmos_sensor(0x0006, 0x0801); //frame length lines +write_cmos_sensor(0x0a22, 0x0000); +write_cmos_sensor(0x0a12, 0x0a20); //x output size +write_cmos_sensor(0x0a14, 0x0798); //y output size +write_cmos_sensor(0x003e, 0x0000); +write_cmos_sensor(0x0004, 0x07fb); //coarse int. time +write_cmos_sensor(0x0a04, 0x014a); //isp_en +write_cmos_sensor(0x0a1a, 0x0800); +write_cmos_sensor(0x090c, 0x0a38); +write_cmos_sensor(0x090e, 0x002a); +//=============================================== +// mipi 2 lane 880Mbps +//=============================================== +write_cmos_sensor(0x0902, 0x431a); +write_cmos_sensor(0x0914, 0xc10b); +write_cmos_sensor(0x0916, 0x071f); +write_cmos_sensor(0x091c, 0x0e09); +write_cmos_sensor(0x0918, 0x0307); +write_cmos_sensor(0x091a, 0x0c0c); +write_cmos_sensor(0x091e, 0x0a00); +write_cmos_sensor(0x0a00, 0x0100); //stream on + } + //else if (currefps == 240) {} + else if (currefps == 150) { + write_cmos_sensor(0x0a00, 0x0000); //stream on + write_cmos_sensor(0x0b14, 0x404c); + write_cmos_sensor(0x0b16, 0x6e0b); + write_cmos_sensor(0x0b18, 0xf20b); + write_cmos_sensor(0x004a, 0x0100); + write_cmos_sensor(0x000c, 0x0022); + write_cmos_sensor(0x0008, 0x0b00); + write_cmos_sensor(0x005a, 0x0202); + write_cmos_sensor(0x0012, 0x000e); + write_cmos_sensor(0x0018, 0x0a31); + write_cmos_sensor(0x0024, 0x0038); + write_cmos_sensor(0x002a, 0x003d); + write_cmos_sensor(0x0026, 0x0040); + write_cmos_sensor(0x002c, 0x07d7); + write_cmos_sensor(0x002e, 0x1111); + write_cmos_sensor(0x0030, 0x1111); + write_cmos_sensor(0x0032, 0x1111); + write_cmos_sensor(0x001a, 0x1111); + write_cmos_sensor(0x001c, 0x1111); + write_cmos_sensor(0x001e, 0x1111); + write_cmos_sensor(0x0006, 0x1046); //frame length lines + write_cmos_sensor(0x0a22, 0x0000); + write_cmos_sensor(0x0a12, 0x0a20); //x output size + write_cmos_sensor(0x0a14, 0x0798); //y output size + write_cmos_sensor(0x003e, 0x0000); + write_cmos_sensor(0x0004, 0x1041); //coarse int. time + write_cmos_sensor(0x0a04, 0x014a); //isp_en + write_cmos_sensor(0x0a1a, 0x0800); + write_cmos_sensor(0x090c, 0x0a38); + write_cmos_sensor(0x090e, 0x002a); + //=============================================== + // mipi 2 lane 880Mbps + //=============================================== + write_cmos_sensor(0x0902, 0x431a); + write_cmos_sensor(0x0914, 0xc10b); + write_cmos_sensor(0x0916, 0x071f); + write_cmos_sensor(0x091c, 0x0e09); + write_cmos_sensor(0x0918, 0x0307); + write_cmos_sensor(0x091a, 0x0c0c); + write_cmos_sensor(0x091e, 0x0a00); + write_cmos_sensor(0x0a00, 0x0100); //stream on + } + + else { +//Sensor Information//////////////////////////// +//Sensor : Hi-553 +//Date : 2015-09-05 +//Customer : LGE +//Image size : 2592x1944 +//MCLK : 24MHz +//MIPI speed(Mbps): 880Mbps x 2Lane +//Frame Length : 2049 +//Line Length : 2816 +//Max Fps : 30.5fps +//Pixel order : Green 1st (=GB) +//X/Y-flip : X-flip +//BLC offset : 64code +//////////////////////////////////////////////// + +write_cmos_sensor(0x0a00, 0x0000); //stream on +write_cmos_sensor(0x0b14, 0x404c); +write_cmos_sensor(0x0b16, 0x6e0b); +write_cmos_sensor(0x0b18, 0xf20b); +write_cmos_sensor(0x004a, 0x0100); +write_cmos_sensor(0x000c, 0x0022); +write_cmos_sensor(0x0008, 0x0b00); +write_cmos_sensor(0x005a, 0x0202); +write_cmos_sensor(0x0012, 0x000e); +write_cmos_sensor(0x0018, 0x0a31); +write_cmos_sensor(0x0024, 0x0038); +write_cmos_sensor(0x002a, 0x003d); +write_cmos_sensor(0x0026, 0x0040); +write_cmos_sensor(0x002c, 0x07d7); +write_cmos_sensor(0x002e, 0x1111); +write_cmos_sensor(0x0030, 0x1111); +write_cmos_sensor(0x0032, 0x1111); +write_cmos_sensor(0x001a, 0x1111); +write_cmos_sensor(0x001c, 0x1111); +write_cmos_sensor(0x001e, 0x1111); +write_cmos_sensor(0x0006, 0x0801); //frame length lines +write_cmos_sensor(0x0a22, 0x0000); +write_cmos_sensor(0x0a12, 0x0a20); //x output size +write_cmos_sensor(0x0a14, 0x0798); //y output size +write_cmos_sensor(0x003e, 0x0000); +write_cmos_sensor(0x0004, 0x07fb); //coarse int. time +write_cmos_sensor(0x0a04, 0x014a); //isp_en +write_cmos_sensor(0x0a1a, 0x0800); +write_cmos_sensor(0x090c, 0x0a38); +write_cmos_sensor(0x090e, 0x002a); +//=============================================== +// mipi 2 lane 880Mbps +//=============================================== +write_cmos_sensor(0x0902, 0x431a); +write_cmos_sensor(0x0914, 0xc10b); +write_cmos_sensor(0x0916, 0x071f); +write_cmos_sensor(0x091c, 0x0e09); +write_cmos_sensor(0x0918, 0x0307); +write_cmos_sensor(0x091a, 0x0c0c); +write_cmos_sensor(0x091e, 0x0a00); +write_cmos_sensor(0x0a00, 0x0100); //stream on + } +} + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + capture_setting(currefps); +} + +static void hs_video_setting(void) +{ + LOG_INF("E\n"); +//////////////////////////////////////////////// + + write_cmos_sensor(0x0a00, 0x0000); //stream on + write_cmos_sensor(0x0b14, 0x404c); + write_cmos_sensor(0x0b16, 0x6e0b); + write_cmos_sensor(0x0b18, 0xf28b); + write_cmos_sensor(0x004a, 0x0100); + write_cmos_sensor(0x000c, 0x0022); + write_cmos_sensor(0x0008, 0x0b00); + write_cmos_sensor(0x005a, 0x0208); + write_cmos_sensor(0x0012, 0x001E); + write_cmos_sensor(0x0018, 0x0a21); + write_cmos_sensor(0x0024, 0x0044); + write_cmos_sensor(0x002a, 0x0049); + write_cmos_sensor(0x0026, 0x004c); + write_cmos_sensor(0x002c, 0x07cb); + write_cmos_sensor(0x002e, 0x1111); + write_cmos_sensor(0x0030, 0x1111); + write_cmos_sensor(0x0032, 0x7711); + write_cmos_sensor(0x001a, 0x1111); + write_cmos_sensor(0x001c, 0x1111); + write_cmos_sensor(0x001e, 0x1111); + write_cmos_sensor(0x0006, 0x0208); //frame length lines + write_cmos_sensor(0x0a22, 0x0100); + write_cmos_sensor(0x0a12, 0x0280); //x output size + write_cmos_sensor(0x0a14, 0x01e0); //y output size + write_cmos_sensor(0x003e, 0x0000); + write_cmos_sensor(0x0004, 0x0202); //coarse int. time + write_cmos_sensor(0x0a04, 0x016a); //isp_en + write_cmos_sensor(0x0a1A, 0x0800); + write_cmos_sensor(0x090c, 0x0270); + write_cmos_sensor(0x090e, 0x0010); + //=============================================== + // mipi 2 lane 220Mbps + //=============================================== + write_cmos_sensor(0x0902, 0x431a); + write_cmos_sensor(0x0914, 0xc103); + write_cmos_sensor(0x0916, 0x0207); + write_cmos_sensor(0x091c, 0x0903); + write_cmos_sensor(0x0918, 0x0302); + write_cmos_sensor(0x091a, 0x0406); + write_cmos_sensor(0x091e, 0x0300); + write_cmos_sensor(0x0a00, 0x0100); //stream on + +} + + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + preview_setting(); +} + + +static kal_uint32 return_sensor_id(void) +{ + return read_cmos_sensor(0x0f16); +} + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { +#ifdef CONFIG_MTK_CAM_CAL + //read_imx135_otp_mtk_fmt(); +#endif + LOG_INF("i2c write id: 0x%x, ReadOut sensor id: 0x%x, imgsensor_info.sensor_id:0x%x.\n", imgsensor.i2c_write_id,*sensor_id,imgsensor_info.sensor_id); + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, i2c write id: 0x%x, ReadOut sensor id: 0x%x, imgsensor_info.sensor_id:0x%x.\n", imgsensor.i2c_write_id,*sensor_id,imgsensor_info.sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 1; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.shutter = 0x3D0; + imgsensor.gain = 0x100; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + set_mirror_flip(imgsensor.mirror); + mdelay(10); + #ifdef FANPENGTAO + int i=0; + for(i=0; i<10; i++){ + LOG_INF("delay time = %d, the frame no = %d\n", i*10, read_cmos_sensor(0x0005)); + mdelay(10); + } + #endif + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap.max_framerate) { + LOG_INF("capture30fps: use cap30FPS's setting: %d fps!\n",imgsensor.current_fps/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + else + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + //PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + LOG_INF("cap115fps: use cap1's setting: %d fps!\n",imgsensor.current_fps/10); + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + else { //PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + LOG_INF("Warning:=== current_fps %d fps is not support, so use cap1's setting\n",imgsensor.current_fps/10); + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + mdelay(10); + +#if 1 + if(imgsensor.test_pattern == KAL_TRUE) + { + write_cmos_sensor(0x0a04, 0x0141); + write_cmos_sensor(0x0200, 0x0001); + write_cmos_sensor(0x0206, 0x000a); + write_cmos_sensor(0x0208, 0x0a0a); + write_cmos_sensor(0x020a, 0x000a); + write_cmos_sensor(0x020c, 0x0a0a); + } +#endif + + return ERROR_NONE; +} /* capture() */ + +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + + + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} + +/************************************************************************* +* FUNCTION +* Custom1 +* +* DESCRIPTION +* This function start the sensor Custom1. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 Custom1(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM1; + imgsensor.pclk = imgsensor_info.custom1.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom1.linelength; + imgsensor.frame_length = imgsensor_info.custom1.framelength; + imgsensor.min_frame_length = imgsensor_info.custom1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom1 */ + +static kal_uint32 Custom2(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM2; + imgsensor.pclk = imgsensor_info.custom2.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom2.linelength; + imgsensor.frame_length = imgsensor_info.custom2.framelength; + imgsensor.min_frame_length = imgsensor_info.custom2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom2 */ + +static kal_uint32 Custom3(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM3; + imgsensor.pclk = imgsensor_info.custom3.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom3.linelength; + imgsensor.frame_length = imgsensor_info.custom3.framelength; + imgsensor.min_frame_length = imgsensor_info.custom3.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom3 */ + +static kal_uint32 Custom4(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM4; + imgsensor.pclk = imgsensor_info.custom4.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom4.linelength; + imgsensor.frame_length = imgsensor_info.custom4.framelength; + imgsensor.min_frame_length = imgsensor_info.custom4.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom4 */ +static kal_uint32 Custom5(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM5; + imgsensor.pclk = imgsensor_info.custom5.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom5.linelength; + imgsensor.frame_length = imgsensor_info.custom5.framelength; + imgsensor.min_frame_length = imgsensor_info.custom5.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom5 */ +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + sensor_resolution->SensorCustom1Width = imgsensor_info.custom1.grabwindow_width; + sensor_resolution->SensorCustom1Height = imgsensor_info.custom1.grabwindow_height; + + sensor_resolution->SensorCustom2Width = imgsensor_info.custom2.grabwindow_width; + sensor_resolution->SensorCustom2Height = imgsensor_info.custom2.grabwindow_height; + + sensor_resolution->SensorCustom3Width = imgsensor_info.custom3.grabwindow_width; + sensor_resolution->SensorCustom3Height = imgsensor_info.custom3.grabwindow_height; + + sensor_resolution->SensorCustom4Width = imgsensor_info.custom4.grabwindow_width; + sensor_resolution->SensorCustom4Height = imgsensor_info.custom4.grabwindow_height; + + sensor_resolution->SensorCustom5Width = imgsensor_info.custom5.grabwindow_width; + sensor_resolution->SensorCustom5Height = imgsensor_info.custom5.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + sensor_info->Custom1DelayFrame = imgsensor_info.custom1_delay_frame; + sensor_info->Custom2DelayFrame = imgsensor_info.custom2_delay_frame; + sensor_info->Custom3DelayFrame = imgsensor_info.custom3_delay_frame; + sensor_info->Custom4DelayFrame = imgsensor_info.custom4_delay_frame; + sensor_info->Custom5DelayFrame = imgsensor_info.custom5_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + #ifdef FPTPDAFSUPPORT + sensor_info->PDAF_Support = 1; + #else + sensor_info->PDAF_Support = 0; + #endif + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM1: + sensor_info->SensorGrabStartX = imgsensor_info.custom1.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom1.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM2: + sensor_info->SensorGrabStartX = imgsensor_info.custom2.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom2.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM3: + sensor_info->SensorGrabStartX = imgsensor_info.custom3.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom3.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM4: + sensor_info->SensorGrabStartX = imgsensor_info.custom4.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom4.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM5: + sensor_info->SensorGrabStartX = imgsensor_info.custom5.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom5.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CUSTOM1: + Custom1(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM2: + Custom2(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM3: + Custom3(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM4: + Custom4(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM5: + Custom5(image_window, sensor_config_data); // Custom1 + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if(framerate==300) + { + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + else + { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + case MSDK_SCENARIO_ID_CUSTOM1: + frame_length = imgsensor_info.custom1.pclk / framerate * 10 / imgsensor_info.custom1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom1.framelength) ? (frame_length - imgsensor_info.custom1.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + case MSDK_SCENARIO_ID_CUSTOM2: + frame_length = imgsensor_info.custom2.pclk / framerate * 10 / imgsensor_info.custom2.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom2.framelength) ? (frame_length - imgsensor_info.custom2.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + case MSDK_SCENARIO_ID_CUSTOM3: + frame_length = imgsensor_info.custom3.pclk / framerate * 10 / imgsensor_info.custom3.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom3.framelength) ? (frame_length - imgsensor_info.custom3.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom3.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + case MSDK_SCENARIO_ID_CUSTOM4: + frame_length = imgsensor_info.custom4.pclk / framerate * 10 / imgsensor_info.custom4.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom4.framelength) ? (frame_length - imgsensor_info.custom4.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom4.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + case MSDK_SCENARIO_ID_CUSTOM5: + frame_length = imgsensor_info.custom5.pclk / framerate * 10 / imgsensor_info.custom5.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom5.framelength) ? (frame_length - imgsensor_info.custom5.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM1: + *framerate = imgsensor_info.custom1.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM2: + *framerate = imgsensor_info.custom2.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM3: + *framerate = imgsensor_info.custom3.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM4: + *framerate = imgsensor_info.custom4.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM5: + *framerate = imgsensor_info.custom5.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0a04, 0x0141); + write_cmos_sensor(0x0200, 0x0001); + write_cmos_sensor(0x0206, 0x000a); + write_cmos_sensor(0x0208, 0x0a0a); + write_cmos_sensor(0x020a, 0x000a); + write_cmos_sensor(0x020c, 0x0a0a); + LOG_INF(">>crc enable>> reg: %d\n", enable); + } else { + write_cmos_sensor(0x0a04, 0x0140); + write_cmos_sensor(0x0200, 0x0000); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + + +UINT32 HI553_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* hi553_MIPI_RAW_SensorInit */ + + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/hi553mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/hi553mipiraw_Sensor.h new file mode 100755 index 0000000000000000000000000000000000000000..82b201662b3bd69fa6d444b82432fef5a13d4331 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/hi553_mipi_raw/hi553mipiraw_Sensor.h @@ -0,0 +1,154 @@ +/***************************************************************************** + * + * Filename: + * --------- + * hi553mipiraw_Sensor.h + * + * Project: + * -------- + * ALPS + * PengtaoFan + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _HI553MIPI_SENSOR_H +#define _HI553MIPI_SENSOR_H + +//±íʾsensorµÄ¼¸ÖÖ¹¤×÷ģʽ״̬£ºinit preview capture video hvideo svideo +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, + IMGSENSOR_MODE_CUSTOM1, + IMGSENSOR_MODE_CUSTOM2, + IMGSENSOR_MODE_CUSTOM3, + IMGSENSOR_MODE_CUSTOM4, + IMGSENSOR_MODE_CUSTOM5, +} IMGSENSOR_MODE; + +//±íʾ¼¸ÖÖ£¨²»Ã¬¹¤×÷ģʽ״̬㩵Äsensor²ÎÊýÃÅâ +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +//±íʾ£¨µ±Ç°×´Ì¬¹¤×÷ģʽ£©Ã嵀sensor²ÎÊýÃÅâ +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_bool ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +//sensor»ù±¾ÃÅ⣬datasheetÉõÄÃÅâ +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint16 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + imgsensor_mode_struct custom1; //custom1 scenario relative information + imgsensor_mode_struct custom2; //custom2 scenario relative information + imgsensor_mode_struct custom3; //custom3 scenario relative information + imgsensor_mode_struct custom4; //custom4 scenario relative information + imgsensor_mode_struct custom5; //custom5 scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + kal_uint8 custom1_delay_frame; //enter custom1 delay frame num + kal_uint8 custom2_delay_frame; //enter custom1 delay frame num + kal_uint8 custom3_delay_frame; //enter custom1 delay frame num + kal_uint8 custom4_delay_frame; //enter custom1 delay frame num + kal_uint8 custom5_delay_frame; //enter custom1 delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff + kal_uint32 i2c_speed; //i2c speed +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +//extern bool hi553_read_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size); + +#endif + +/* +PREVIEW:¾¡Ã¿ÓÃbinning mode£¬ ²¢¸æÖªÊÇBinning average»¹ÊÇBinning sum£¿AVERAGE +ʹÓÃGP·½Ê½£¬ shutterµ±Ç°èåÉèÖúó£¬ÃÂÃÂèåÉú磩 +Static DPC ON +slim video ²»Óõ½120fps°É¡£ +get sensor id and Open() has more code need to reused. need to modify the two place +20150513 µÚÒ»´ÎºÃÈëPDAF²ÎÊý + +*/ \ No newline at end of file diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a59d63fcce98bdca380d102a30797fb8d307d8b4 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += imx135_otp.o +obj-y += imx135mipiraw_Sensor.o + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135_otp.c b/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135_otp.c new file mode 100644 index 0000000000000000000000000000000000000000..615b9475f82a2b59ad8c52111639c742316150c3 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135_otp.c @@ -0,0 +1,664 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/************************************************************************************************* +imx135_otp.c +--------------------------------------------------------- +OTP Application file From Truly for imx135 +2013.01.14 +--------------------------------------------------------- +NOTE: +The modification is appended to initialization of image sensor. +After sensor initialization, use the function , and get the id value. +bool otp_wb_update(BYTE zone) +and +bool otp_lenc_update(BYTE zone), +then the calibration of AWB and LSC will be applied. +After finishing the OTP written, we will provide you the golden_rg and golden_bg settings. +**************************************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "imx135mipiraw_Sensor.h" + + +#define PFX "imx135_otp" +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +//#include "imx135_otp.h" + +//extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +//extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +//extern BYTE imx135_byteread_cmos_sensor(kal_uint32 addr); +extern kal_uint16 read_cmos_sensor(kal_uint32 addr); +extern void write_cmos_sensor(kal_uint32 addr, kal_uint32 para); +extern void write_cmos_sensor_16(kal_uint16 addr,kal_uint16 para); +extern void write_cmos_sensor_8(kal_uint16 addr, kal_uint8 para); + + +#if 0 +BYTE imx135_byteread_cmos_sensor(kal_uint32 addr) +{ + BYTE get_byte=0; + char puSendCmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + iReadRegI2C(puSendCmd , 2, (u8*)&get_byte,1,IMX135MIPI_WRITE_ID); + return get_byte; +} +extern void imx135_wordwrite_cmos_sensor(u16 addr, u32 para); +extern void imx135_bytewrite_cmos_sensor(u16 addr, u32 para); +#endif + + +#define USHORT unsigned short +#define BYTE unsigned char +#define Sleep(ms) mdelay(ms) + +#define TRULY_ID 0x02 + +enum LENS +{ + LARGEN_LENS = 1, + KT_LENS, + KM_LENS, + GENIUS_LENS, + SUNNY_LENS, + OTHER_LENS, +}; +enum DRIVER_IC +{ + DONGWOOK = 1, + ADI, + ASM, + ROHM, + OTHER_DRIVER, +}; +enum VCM +{ + TDK = 1, + MISTUMIS, + SIKAO, + MWT, + ALPS, + OTHER_VCM, +}; +#define VALID_OTP 0x40 + +#define GAIN_DEFAULT 0x0100 +#define GAIN_GREEN1_ADDR_H 0x020E +#define GAIN_GREEN1_ADDR_L 0x020F + +#define GAIN_BLUE_ADDR_H 0x0212 +#define GAIN_BLUE_ADDR_L 0x0213 + +#define GAIN_RED_ADDR_H 0x0210 +#define GAIN_RED_ADDR_L 0x0211 + +#define GAIN_GREEN2_ADDR_H 0x0214 +#define GAIN_GREEN2_ADDR_L 0x0214 + + +USHORT golden_r; +USHORT golden_gr; +USHORT golden_gb; +USHORT golden_b; + +USHORT current_r; +USHORT current_gr; +USHORT current_gb; +USHORT current_b; + +kal_uint32 r_ratio; +kal_uint32 b_ratio; + + +//kal_uint32 golden_r = 0, golden_gr = 0, golden_gb = 0, golden_b = 0; +//kal_uint32 current_r = 0, current_gr = 0, current_gb = 0, current_b = 0; +/************************************************************************************************* +* Function : start_read_otp +* Description : before read otp , set the reading block setting +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +* Return : 0, reading block setting err + 1, reading block setting ok +**************************************************************************************************/ +bool start_read_otp(BYTE zone) +{ + BYTE val = 0; + int i; + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x3B02, zone); //PAGE + write_cmos_sensor(0x3B00, 0x01); + write_cmos_sensor_8(0x0104, 0x00); + Sleep(5); + for(i=0;i<100;i++) + { + val = read_cmos_sensor(0x3B01); + if((val & 0x01) == 0x01) + break; + Sleep(2); + } + if(i == 100) + { + LOG_INF("Read Page %d Err!\n", zone); // print log + return 0; + } + return 1; +} + + +/************************************************************************************************* +* Function : get_otp_flag +* Description : get otp WRITTEN_FLAG +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +* Return : [BYTE], if 0x40 , this type has valid otp data, otherwise, invalid otp data +**************************************************************************************************/ +BYTE get_otp_flag(BYTE zone) +{ + BYTE flag = 0; + if(!start_read_otp(zone)) + { + LOG_INF("Start read Page %d Fail!\n", zone); + return 0; + } + flag = read_cmos_sensor(0x3B04); + flag = flag & 0xc0; + LOG_INF("OTP Flag:0x%02x\n",flag ); + return flag; +} + +/************************************************************************************************* +* Function : get_otp_date +* Description : get otp date value +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +**************************************************************************************************/ +bool get_otp_date(BYTE zone) +{ + BYTE year = 0; + BYTE month = 0; + BYTE day = 0; + if(!start_read_otp(zone)) + { + LOG_INF("Start read Page %d Fail!\n", zone); + return 0; + } + year = read_cmos_sensor(0x3B06); + month = read_cmos_sensor(0x3B07); + day = read_cmos_sensor(0x3B08); + LOG_INF("OTP date=%02d.%02d.%02d", year,month,day); + return 1; +} + + +/************************************************************************************************* +* Function : get_otp_module_id +* Description : get otp MID value +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +* Return : [BYTE] 0 : OTP data fail + other value : module ID data , TRULY ID is 0x0001 +**************************************************************************************************/ +BYTE get_otp_module_id(BYTE zone) +{ + BYTE module_id = 0; + if(!start_read_otp(zone)) + { + LOG_INF("OTP Start read Page %d Fail!\n", zone); + return 0; + } + module_id = read_cmos_sensor(0x3B05); + LOG_INF("OTP_Module ID: 0x%02x.\n",module_id); + return module_id; +} + + +/************************************************************************************************* +* Function : get_otp_lens_id +* Description : get otp LENS_ID value +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +* Return : [BYTE] 0 : OTP data fail + other value : LENS ID data +**************************************************************************************************/ +BYTE get_otp_lens_id(BYTE zone) +{ + BYTE lens_id = 0; + if(!start_read_otp(zone)) + { + LOG_INF("Start read Page %d Fail!\n", zone); + return 0; + } + lens_id = read_cmos_sensor(0x3B09); + LOG_INF("OTP_Lens ID: 0x%02x.\n",lens_id); + return lens_id; +} + + +/************************************************************************************************* +* Function : get_otp_vcm_id +* Description : get otp VCM_ID value +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +* Return : [BYTE] 0 : OTP data fail + other value : VCM ID data +**************************************************************************************************/ +BYTE get_otp_vcm_id(BYTE zone) +{ + BYTE vcm_id = 0; + if(!start_read_otp(zone)) + { + LOG_INF("Start read Page %d Fail!\n", zone); + return 0; + } + vcm_id = read_cmos_sensor(0x3B0A); + LOG_INF("OTP_VCM ID: 0x%02x.\n",vcm_id); + return vcm_id; +} + + +/************************************************************************************************* +* Function : get_otp_driver_id +* Description : get otp driver id value +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +* Return : [BYTE] 0 : OTP data fail + other value : driver ID data +**************************************************************************************************/ +BYTE get_otp_driver_id(BYTE zone) +{ + BYTE driver_id = 0; + if(!start_read_otp(zone)) + { + LOG_INF("Start read Page %d Fail!\n", zone); + return 0; + } + driver_id = read_cmos_sensor(0x3B0B); + LOG_INF("OTP_Driver ID: 0x%02x.\n",driver_id); + return driver_id; +} + +/************************************************************************************************* +* Function : get_light_id +* Description : get otp environment light temperature value +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +* Return : [BYTE] 0 : OTP data fail + other value : driver ID data + BIT0:D65(6500K) EN + BIT1:D50(5100K) EN + BIT2:CWF(4000K) EN + BIT3:A Light(2800K) EN +**************************************************************************************************/ +BYTE get_light_id(BYTE zone) +{ + BYTE light_id = 0; + if(!start_read_otp(zone)) + { + LOG_INF("Start read Page %d Fail!\n", zone); + return 0; + } + light_id = read_cmos_sensor(0x3B0C); + LOG_INF("OTP_Light ID: 0x%02x.\n",light_id); + return light_id; +} + +/************************************************************************************************* +* Function : get_lsc_flag +* Description : get LSC WRITTEN_FLAG +* Return : [BYTE], if 0x40 , this type has valid lsc data, otherwise, invalid otp data +**************************************************************************************************/ +BYTE get_lsc_flag(void) +{ + BYTE flag = 0; + if(!start_read_otp(0x0B)) + { + LOG_INF("Start read Page 0x0B Fail!\n"); + return 0; + } + flag = read_cmos_sensor(0x3B43); + flag = flag & 0xc0; + LOG_INF("OTP Flag:0x%02x",flag ); + return flag; +} + +/************************************************************************************************* +* Function : otp_lenc_update +* Description : Update lens correction +* Return : [bool] 0 : OTP data fail + 1 : otp_lenc update success +**************************************************************************************************/ +bool otp_lenc_update(void) +{ + BYTE lsc_flag; + int i, j; + BYTE temp1, temp2; + BYTE lsc_data[64 * 8] ={0}; + + lsc_flag = get_lsc_flag(); + if(lsc_flag == 0xC0 || lsc_flag == 0x80) + { + LOG_INF("OTP lsc data invalid\n"); + return 0; + } + else if(lsc_flag == 0x00) + { + LOG_INF("OTP no lsc data\n"); + return 0; + } + + for(i=0;i<8;i++) + { + if(!start_read_otp(0x04+i)) + { + LOG_INF("OTP Start read Page %d Fail!\n", 0x04+i); + return 0; + } + for(j=0;j<64;j++) + lsc_data[i*64+j] = read_cmos_sensor(0x3B04+j); + } +#ifdef DEBUG_IMX135_OTP + for (i=0;i<504;i++) + { + LOG_INF("%0x ",lsc_data[i]); + if((i+1)%64==0) + LOG_INF("\n"); + } +#endif + + write_cmos_sensor_8(0x0104, 0x01); + for(i=0;i<504;i++) //LSC SIZE is 504 BYTES + write_cmos_sensor(0x4800+i, lsc_data[i]); + write_cmos_sensor_8(0x0104, 0x00); + + //Enable LSC + temp1 = read_cmos_sensor(0x0700); + temp2 = read_cmos_sensor(0x3A63); + temp1 = temp1 | 0x01; + temp2 = temp2 | 0x01; + write_cmos_sensor_8(0x0104, 0x00); + write_cmos_sensor(0x0700, temp1); + write_cmos_sensor(0x3A63, temp2); + write_cmos_sensor_8(0x0104, 0x00); + + LOG_INF("OTP Update lsc finished\n"); + + return 1; +} + +/************************************************************************************************* +* Function : wb_gain_set +* Description : Set WB ratio to register gain setting 512x +* Parameters : [int] r_ratio : R ratio data compared with golden module R + b_ratio : B ratio data compared with golden module B +* Return : [bool] 0 : set wb fail + 1 : WB set success +**************************************************************************************************/ + +bool wb_gain_set(void) +{ + USHORT R_GAIN; + USHORT B_GAIN; + USHORT Gr_GAIN; + USHORT Gb_GAIN; + USHORT G_GAIN; + + if(!r_ratio || !b_ratio) + { + LOG_INF("OTP WB ratio Data Err!\n"); + return 0; + } + + if(r_ratio >= 512 ) + { + if(b_ratio>=512) + { + R_GAIN = (USHORT)(GAIN_DEFAULT * r_ratio / 512); + G_GAIN = GAIN_DEFAULT; + B_GAIN = (USHORT)(GAIN_DEFAULT * b_ratio / 512); + } + else + { + R_GAIN = (USHORT)(GAIN_DEFAULT*r_ratio / b_ratio ); + G_GAIN = (USHORT)(GAIN_DEFAULT*512 / b_ratio ); + B_GAIN = GAIN_DEFAULT; + } + } + else + { + if(b_ratio >= 512) + { + R_GAIN = GAIN_DEFAULT; + G_GAIN = (USHORT)(GAIN_DEFAULT*512 /r_ratio); + B_GAIN = (USHORT)(GAIN_DEFAULT*b_ratio / r_ratio ); + } + else + { + Gr_GAIN = (USHORT)(GAIN_DEFAULT*512/ r_ratio ); + Gb_GAIN = (USHORT)(GAIN_DEFAULT*512/b_ratio ); + if(Gr_GAIN >= Gb_GAIN) + { + R_GAIN = GAIN_DEFAULT; + G_GAIN = (USHORT)(GAIN_DEFAULT *512/ r_ratio ); + B_GAIN = (USHORT)(GAIN_DEFAULT*b_ratio / r_ratio ); + } + else + { + R_GAIN = (USHORT)(GAIN_DEFAULT*r_ratio / b_ratio); + G_GAIN = (USHORT)(GAIN_DEFAULT*512 / b_ratio ); + B_GAIN = GAIN_DEFAULT; + } + } + } + + //R_GAIN = 0x0FFF; // For testing, use this gain the image will become red. + + LOG_INF("OTP_golden_r=%d,golden_gr=%d,golden_gb=%d,golden_b=%d \n",golden_r,golden_gr,golden_gb,golden_b); + LOG_INF("OTP_current_r=%d,current_gr=%d,current_gb=%d,current_b=%d \n",current_r,current_gr,current_gb,current_b); + LOG_INF("OTP_r_ratio=%d,b_ratio=%d \n",r_ratio,b_ratio); + LOG_INF("R_GAIN=0x%0x,G_GAIN=0x%0x,B_GAIN=0x%0x.\n",R_GAIN,G_GAIN,B_GAIN); +#if 0 + IMX135MIPI_write_cmos_sensor(GAIN_RED_ADDR_H, (R_GAIN>>8)&0xff); + IMX135MIPI_write_cmos_sensor(GAIN_RED_ADDR_L, (R_GAIN)&0xff); + IMX135MIPI_write_cmos_sensor(GAIN_BLUE_ADDR_H, (B_GAIN>>8)&0xff); + IMX135MIPI_write_cmos_sensor(GAIN_BLUE_ADDR_L, (B_GAIN)&0xff); + IMX135MIPI_write_cmos_sensor(GAIN_GREEN1_ADDR_H, (G_GAIN>>8)&0xff); //Green 1 default gain 1x + IMX135MIPI_write_cmos_sensor(GAIN_GREEN1_ADDR_L, (G_GAIN)&0xff); + IMX135MIPI_write_cmos_sensor(GAIN_GREEN2_ADDR_H, (G_GAIN>>8)&0xff);//Green 2 default gain 1x + IMX135MIPI_write_cmos_sensor(GAIN_GREEN2_ADDR_H, (G_GAIN)&0xff); //Green 2 default gain 1x +#endif + + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor_16(GAIN_RED_ADDR_H,R_GAIN); + write_cmos_sensor_16(GAIN_BLUE_ADDR_H,B_GAIN); + write_cmos_sensor_16(GAIN_GREEN1_ADDR_H,G_GAIN); + write_cmos_sensor_16(GAIN_GREEN2_ADDR_H,G_GAIN); + write_cmos_sensor_8(0x0104, 0x00); + + LOG_INF("OTP WB Update Finished! \n"); + return 1; +} + +/************************************************************************************************* +* Function : get_otp_wb +* Description : Get WB data +* Parameters : [BYTE] zone : OTP PAGE index , 0x00~0x0f +**************************************************************************************************/ +bool get_otp_wb(BYTE zone) +{ + BYTE temph = 0; + BYTE templ = 0; + golden_r = 0, golden_gr = 0, golden_gb = 0, golden_b = 0; + current_r = 0, current_gr = 0, current_gb = 0, current_b = 0; + + if(!start_read_otp(zone)) + { + LOG_INF("Start read Page %d Fail!\n", zone); + return 0; + } + + temph = read_cmos_sensor(0x3B18); + templ = read_cmos_sensor(0x3B19); + golden_r = (USHORT)templ + (((USHORT)temph & 0x03) << 8); + + temph = read_cmos_sensor(0x3B1A); + templ = read_cmos_sensor(0x3B1B); + golden_gr = (USHORT)templ + (((USHORT)temph & 0x03) << 8); + + temph = read_cmos_sensor(0x3B1C); + templ = read_cmos_sensor(0x3B1D); + golden_gb = (USHORT)templ + (((USHORT)temph & 0x03) << 8); + + temph = read_cmos_sensor(0x3B1E); + templ = read_cmos_sensor(0x3B1F); + golden_b = (USHORT)templ + (((USHORT)temph & 0x03) << 8); + + temph = read_cmos_sensor(0x3B10); + templ = read_cmos_sensor(0x3B11); + current_r = (USHORT)templ + (((USHORT)temph & 0x03) << 8); + + temph = read_cmos_sensor(0x3B12); + templ = read_cmos_sensor(0x3B13); + current_gr = (USHORT)templ + (((USHORT)temph & 0x03) << 8); + + temph = read_cmos_sensor(0x3B14); + templ = read_cmos_sensor(0x3B15); + current_gb = (USHORT)templ + (((USHORT)temph & 0x03) << 8); + + temph = read_cmos_sensor(0x3B16); + templ = read_cmos_sensor(0x3B17); + current_b = (USHORT)templ + (((USHORT)temph & 0x03) << 8); + + return 1; +} + + +/************************************************************************************************* +* Function : otp_wb_update +* Description : Update WB correction +* Return : [bool] 0 : OTP data fail + 1 : otp_WB update success +**************************************************************************************************/ +bool otp_wb_update(BYTE zone) +{ + USHORT golden_g, current_g; + + + if(!get_otp_wb(zone)) // get wb data from otp + { + LOG_INF("Get OTP WB data Err!\n"); + return 0; + } + + golden_g = (golden_gr + golden_gb) / 2; + current_g = (current_gr + current_gb) / 2; + + if(!golden_g || !current_g || !golden_r || !golden_b || !current_r || !current_b) + { + LOG_INF("WB update Err !\n"); + return 0; + } + + r_ratio = 512 * golden_r * current_g /( golden_g * current_r ); + b_ratio = 512 * golden_b * current_g /( golden_g * current_b ); + + wb_gain_set(); + + LOG_INF("OTP WB update finished! \n"); + + return 1; +} +static BYTE _otp_awb_set = 0; +static BYTE _otp_lsc_set = 0; +static DEFINE_SPINLOCK(imx135_otp_lock); + +void otp_clear_flag(void){ + spin_lock(&imx135_otp_lock); + _otp_awb_set = 0; + _otp_lsc_set = 0; + spin_unlock(&imx135_otp_lock); +} + +/************************************************************************************************* +* Function : otp_update() +* Description : update otp data from otp , it otp data is valid, + it include get ID and WB update function +* Return : [bool] 0 : update fail + 1 : update success +**************************************************************************************************/ +bool otp_update(BYTE update_sensor_otp_awb, BYTE update_sensor_otp_lsc) +{ + BYTE zone = 0x01; + BYTE FLG = 0x00; + BYTE MID = 0x00; + int i; + + LOG_INF("update_sensor_otp_awb: %d, update_sensor_otp_lsc: %d _otp_awb_set %d _otp_lsc_set%d\n", + update_sensor_otp_awb, update_sensor_otp_lsc, _otp_awb_set, _otp_lsc_set); + if(_otp_awb_set ==1 &&_otp_lsc_set ==1) + return 1; + + for(i=0;i<3;i++) + { + FLG = get_otp_flag(zone); + if(FLG == VALID_OTP) + break; + else + zone++; + } + if(i==3) + { + LOG_INF("No OTP Data or OTP data is invalid!!!\n"); + return 0; + } + + MID = get_otp_module_id(zone); +#ifdef DEBUG_IMX135_OTP + get_otp_lens_id(zone); + get_otp_vcm_id(zone); +#endif + + if(MID != TRULY_ID) //Select + { + LOG_INF("No Truly Module !!!!\n"); + return 0; + } + + if(0 != update_sensor_otp_awb && _otp_awb_set == 0) { + spin_lock(&imx135_otp_lock); + _otp_awb_set = 1; + spin_unlock(&imx135_otp_lock); + if(otp_wb_update(zone)){ + return 0; + } + } + + + if(0 != update_sensor_otp_lsc && _otp_lsc_set == 0) + { + spin_lock(&imx135_otp_lock); + _otp_lsc_set = 1; + spin_unlock(&imx135_otp_lock); + if(!otp_lenc_update()) + { + LOG_INF("OTP Update LSC Err\n"); + return 0; + } + } + return 1; +} diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135mipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135mipiraw_Sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..3320bbf0e613161f0edff5b9183dbffa9ec57e1c --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135mipiraw_Sensor.c @@ -0,0 +1,3216 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * IMX135mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "imx135mipiraw_Sensor.h" + + + +/****************************Modify following Strings for debug****************************/ +#define PFX "IMX135_camera_sensor" + +#define LOG_1 LOG_INF("IMX135,MIPI 4LANE\n") +#define LOG_2 LOG_INF("preview 2096*1554@30fps,864Mbps/lane; video 4196*3108@30fps,864Mbps/lane; capture 13M@30fps,864Mbps/lane\n") +/**************************** Modify end *******************************************/ + +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + +#define MIPI_SETTLEDELAY_AUTO 0 +#define MIPI_SETTLEDELAY_MANNUAL 1 +#define IHDR_USED +static imgsensor_info_struct imgsensor_info = { + .sensor_id = IMX135_SENSOR_ID, + + //.checksum_value = 0x215125a0, + .checksum_value = 0x4ff3b7e6, + + .pre = { + .pclk = 231270000, //record different mode's pclk + .linelength = 4572, //record different mode's linelength + .framelength = 1640, //record different mode's framelength + .startx = 2, //record different mode's startx of grabwindow + .starty = 2, //record different mode's starty of grabwindow + .grabwindow_width = 2088,//2096, //record different mode's width of grabwindow + .grabwindow_height = 1544,//1552, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { // 30 fps capture + .pclk = 432000000, + .linelength = 4572, + .framelength = 3146, + .startx = 4, + .starty = 4, + .grabwindow_width = 4176,//4192, + .grabwindow_height = 3088,//3104, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 300, + }, + .cap1 = { // 24 fps capture + .pclk = 348000000, + .linelength = 4572, + .framelength = 3146, + .startx = 4, + .starty = 4, + .grabwindow_width = 4176,//4192, + .grabwindow_height = 3088,//3104, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 240, + }, + .cap2 = { //15 fps capture + .pclk = 231000000, + .linelength = 4572, + .framelength = 3146, + .startx = 4, + .starty = 4, + .grabwindow_width = 4176,//4192, + .grabwindow_height = 3088,//3104, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 150, + }, + #ifdef IHDR_USED + .normal_video = { + .pclk = 432000000, + .linelength = 4572, + .framelength = 3144, + .startx = 2, + .starty = 2, + .grabwindow_width = 4192,//4192, + .grabwindow_height = 3104,//3104, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 300, + }, + #else + .normal_video = { + .pclk = 432000000, + .linelength = 4572, + .framelength = 3144, + .startx = 2, + .starty = 2, + .grabwindow_width = 4176,//4192, + .grabwindow_height = 3088,//3104, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 300, + }, + #endif + .hs_video = { // 120 fps + .pclk = 432000000, + .linelength = 4572, + .framelength = 786, + .startx = 0, + .starty = 0, + .grabwindow_width = 1280, + .grabwindow_height = 720, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 1200, + }, + /*.hs_video = { // 120 fps + .pclk = 432000000, + .linelength = 4572, + .framelength = 786, + .startx = 0, + .starty = 0, + .grabwindow_width = 640, + .grabwindow_height = 480, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 1200, + },*/ + .slim_video = { + .pclk = 184000000,//231270000, + .linelength = 4572, + .framelength = 1312,//1640, + .startx = 0, + .starty = 0, + .grabwindow_width = 1280, + .grabwindow_height = 720, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 300, + }, + .custom1 = { + .pclk = 231270000, //record different mode's pclk + .linelength = 4572, //record different mode's linelength + .framelength = 1640, //record different mode's framelength + .startx = 2, //record different mode's startx of grabwindow + .starty = 2, //record different mode's starty of grabwindow + .grabwindow_width = 2088,//2096, //record different mode's width of grabwindow + .grabwindow_height = 1544,//1552, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + + }, + .custom2 = { + .pclk = 231270000, //record different mode's pclk + .linelength = 4572, //record different mode's linelength + .framelength = 1640, //record different mode's framelength + .startx = 2, //record different mode's startx of grabwindow + .starty = 2, //record different mode's starty of grabwindow + .grabwindow_width = 2088,//2096, //record different mode's width of grabwindow + .grabwindow_height = 1544,//1552, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + + }, + .custom3 = { + .pclk = 231270000, //record different mode's pclk + .linelength = 4572, //record different mode's linelength + .framelength = 1640, //record different mode's framelength + .startx = 2, //record different mode's startx of grabwindow + .starty = 2, //record different mode's starty of grabwindow + .grabwindow_width = 2088,//2096, //record different mode's width of grabwindow + .grabwindow_height = 1544,//1552, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + + }, + .custom4 = { + .pclk = 231270000, //record different mode's pclk + .linelength = 4572, //record different mode's linelength + .framelength = 1640, //record different mode's framelength + .startx = 2, //record different mode's startx of grabwindow + .starty = 2, //record different mode's starty of grabwindow + .grabwindow_width = 2088,//2096, //record different mode's width of grabwindow + .grabwindow_height = 1544,//1552, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + + }, + .custom5 = { + .pclk = 231270000, //record different mode's pclk + .linelength = 4572, //record different mode's linelength + .framelength = 1640, //record different mode's framelength + .startx = 2, //record different mode's startx of grabwindow + .starty = 2, //record different mode's starty of grabwindow + .grabwindow_width = 2088,//2096, //record different mode's width of grabwindow + .grabwindow_height = 1544,//1552, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + + }, + .margin = 10, + .min_shutter = 1, + .max_frame_length = 0xffff, + .ae_shut_delay_frame = 0, + .ae_sensor_gain_delay_frame = 0, + .ae_ispGain_delay_frame = 2, + .ihdr_support = 1, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 10, //support sensor mode num + + .cap_delay_frame = 2, + .pre_delay_frame = 2, + .video_delay_frame = 5, + .hs_video_delay_frame = 5, + .slim_video_delay_frame = 5, + .custom1_delay_frame = 2, + .custom2_delay_frame = 2, + .custom3_delay_frame = 2, + .custom4_delay_frame = 2, + .custom5_delay_frame = 2, + + .isp_driving_current = ISP_DRIVING_4MA, + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI, + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO, + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_R, + .mclk = 24, + .mipi_lane_num = SENSOR_MIPI_4_LANE, + .i2c_addr_table = {0x20, 0x40, 0xff}, + .i2c_speed = 200, // i2c read/write speed +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter // Danbo ?? + .gain = 0x100, //current gain // Danbo ?? + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 300, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x20, + .update_sensor_otp_awb = 0, + .update_sensor_otp_lsc = 0, +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[10] = +{{ 4208, 3120, 0000, 0000, 4208, 3120, 2104, 1560, 0000, 0000, 2104, 1560, 0007, 0007, 2088, 1544}, // Preview 2112*1558 + { 4208, 3120, 0000, 0000, 4208, 3120, 4208, 3120, 0000, 0000, 4208, 3120, 0015, 0015, 4176, 3088}, // capture 4206*3128 + { 4208, 3120, 0000, 0000, 4208, 3120, 4208, 3120, 0000, 0000, 4208, 3120, 0015, 0015, 4176, 3088}, // video + { 4208, 3120, 824, 840, 2560, 1440, 1280, 720, 0000, 0000, 1280, 720, 0000, 0000, 1280, 720}, //hight speed video + { 4208, 3120, 824, 840, 2560, 1440, 1280, 720, 0000, 0000, 1280, 720, 0000, 0000, 1280, 720},// slim video + { 4208, 3120, 0000, 0000, 4208, 3120, 2104, 1560, 0000, 0000, 2104, 1560, 0007, 0007, 2088, 1544}, // Custom1 (defaultuse preview) + { 4208, 3120, 0000, 0000, 4208, 3120, 2104, 1560, 0000, 0000, 2104, 1560, 0007, 0007, 2088, 1544}, // Custom2 + { 4208, 3120, 0000, 0000, 4208, 3120, 2104, 1560, 0000, 0000, 2104, 1560, 0007, 0007, 2088, 1544}, // Custom3 + { 4208, 3120, 0000, 0000, 4208, 3120, 2104, 1560, 0000, 0000, 2104, 1560, 0007, 0007, 2088, 1544}, // Custom4 + { 4208, 3120, 0000, 0000, 4208, 3120, 2104, 1560, 0000, 0000, 2104, 1560, 0007, 0007, 2088, 1544}, // Custom5 + };// slim video +#define IMX135_OTP_Enable 1 +SENSOR_DPCM_TYPE_ENUM imgsensor_dpcm_info[10] = +{COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE}; + +// Gain Index +#define MaxGainIndex (71) +static kal_uint16 sensorGainMapping[MaxGainIndex][2] ={ + {71 ,25 }, + {76 ,42 }, + {83 ,59 }, + {89 ,73 }, + {96 ,85 }, + {102 ,96 }, + {108 ,105}, + {115 ,114}, + {121 ,121}, + {128 ,128}, + {134 ,134}, + {140 ,140}, + {147 ,145}, + {153 ,149}, + {160 ,154}, + {166 ,158}, + {172 ,161}, + {179 ,164}, + {185 ,168}, + {192 ,171}, + {200 ,174}, + {208 ,177}, + {216 ,180}, + {224 ,183}, + {232 ,185}, + {240 ,188}, + {248 ,190}, + {256 ,192}, + {264 ,194}, + {272 ,196}, + {280 ,197}, + {288 ,199}, + {296 ,201}, + {304 ,202}, + {312 ,203}, + {320 ,205}, + {328 ,206}, + {336 ,207}, + {344 ,208}, + {352 ,209}, + {360 ,210}, + {368 ,211}, + {376 ,212}, + {384 ,213}, + {390 ,214}, + {399 ,215}, + {409 ,216}, + {419 ,217}, + {431 ,218}, + {442 ,219}, + {455 ,220}, + {467 ,221}, + {481 ,222}, + {496 ,223}, + {512 ,224}, + {528 ,225}, + {545 ,226}, + {565 ,227}, + {584 ,228}, + {606 ,229}, + {630 ,230}, + {655 ,231}, + {682 ,232}, + {712 ,233}, + {744 ,234}, + {780 ,235}, + {819 ,236}, + {862 ,237}, + {910 ,238}, + {963 ,239}, + {1024,240} +}; + +/*********************************** + * Please be notified that CONFIG_MTK_CAM_CAL will decide that what kind of shading is used. + * if CONFIG_MTK_CAM_CAL is NOT set (Default), OTP sensor shading will be available + * if CONFIG_MTK_CAM_CAL IS SET (k35v1) , OTP data will be readed as input for shaing and calibration by backend (i.e. ISP) + **********************************/ +#undef CONFIG_MTK_CAM_CAL +#ifdef CONFIG_MTK_CAM_CAL +extern int read_imx135_otp_mtk_fmt(void); +#else +extern bool otp_update(BYTE update_sensor_otp_awb, BYTE update_sensor_otp_lsc); +extern void otp_clear_flag(void); +#endif + +//#if IMX135_OTP_Enable +void write_cmos_sensor_16(kal_uint16 addr, kal_uint16 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para >> 8),(char)(para & 0xFF)}; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pusendcmd , 4, imgsensor.i2c_write_id); +} +//#endif + +kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + return get_byte; +} + +void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static kal_uint16 read_cmos_sensor_8(kal_uint16 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iReadRegI2C(pu_send_cmd , 2, (u8*)&get_byte,1,imgsensor.i2c_write_id); + return get_byte; +} + +void write_cmos_sensor_8(kal_uint16 addr, kal_uint8 para) +{ + char pu_send_cmd[4] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x0340, (imgsensor.frame_length >> 8) & 0xFF); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0342, (imgsensor.line_length >> 8) & 0xFF); + write_cmos_sensor(0x0343, imgsensor.line_length & 0xFF); + write_cmos_sensor_8(0x0104, 0x00); + +} /* set_dummy */ + +kal_uint32 return_sensor_id(void) +{ + return ((read_cmos_sensor_8(0x0016) << 8) | read_cmos_sensor_8(0x0017)); +} + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable = %d\n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); +} /* set_max_framerate */ + + +static void write_shutter(kal_uint16 shutter) +{ + kal_uint16 realtime_fps = 0; + //kal_uint32 frame_length = 0; + + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + // Framelength should be an even number + shutter = (shutter >> 1) << 1; + imgsensor.frame_length = (imgsensor.frame_length >> 1) << 1; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + { + set_max_framerate(296,0); + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x0340, (imgsensor.frame_length >> 8) & 0xFF); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0342, (imgsensor.line_length >> 8) & 0xFF); + write_cmos_sensor(0x0343, imgsensor.line_length & 0xFF); + write_cmos_sensor(0x0202, (shutter >> 8) & 0xFF); + write_cmos_sensor(0x0203, shutter & 0xFF); + write_cmos_sensor_8(0x0104, 0x00); + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + //set_dummy(); + } + else if(realtime_fps >= 147 && realtime_fps <= 150) + { + set_max_framerate(146,0); + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x0340, (imgsensor.frame_length >> 8) & 0xFF); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0342, (imgsensor.line_length >> 8) & 0xFF); + write_cmos_sensor(0x0343, imgsensor.line_length & 0xFF); + write_cmos_sensor(0x0202, (shutter >> 8) & 0xFF); + write_cmos_sensor(0x0203, shutter & 0xFF); + write_cmos_sensor_8(0x0104, 0x00); + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + //set_dummy(); + } + else { + // Extend frame length + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x0340, (imgsensor.frame_length >> 8) & 0xFF); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0202, (shutter >> 8) & 0xFF); + write_cmos_sensor(0x0203, shutter & 0xFF); + write_cmos_sensor_8(0x0104, 0x00); + } + } else { + // Extend frame length + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x0340, (imgsensor.frame_length >> 8) & 0xFF); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0202, (shutter >> 8) & 0xFF); + write_cmos_sensor(0x0203, shutter & 0xFF); + write_cmos_sensor_8(0x0104, 0x00); + } + + // Update Shutter + //write_cmos_sensor_8(0x0104, 0x01); + //write_cmos_sensor(0x0202, (shutter >> 8) & 0xFF); + //write_cmos_sensor(0x0203, shutter & 0xFF); + //write_cmos_sensor_8(0x0104, 0x00); + LOG_INF("shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + //LOG_INF("frame_length = %d ", frame_length); + +} /* write_shutter */ + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + write_shutter(shutter); +} /* set_shutter */ + + + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint8 iI; + + for (iI = 0; iI < (MaxGainIndex-1); iI++) { + if(gain <= sensorGainMapping[iI][0]){ + break; + } + } +/* + if(gain != sensorGainMapping[iI][0]) + { + //SENSORDB("Gain mapping don't correctly:%d %d \n", gain, sensorGainMapping[iI][0]); + return sensorGainMapping[iI][1]; + } + else return (kal_uint16)gain; +*/ + return sensorGainMapping[iI][1]; + +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + /* 0x350A[0:1], 0x350B[0:7] AGC real gain */ + /* [0:3] = N meams N /16 X */ + /* [4:9] = M meams M X */ + /* Total gain = M + N /16 X */ + + // + if (gain < BASEGAIN || gain > 32 * BASEGAIN) { + LOG_INF("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 32 * BASEGAIN) + gain = 32 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor_8(0x0104, 0x01); + // LE Gain + write_cmos_sensor(0x0204, (reg_gain>>8)& 0xFF); + write_cmos_sensor(0x0205, reg_gain & 0xFF); + // SE Gain + //write_cmos_sensor(0x0233, reg_gain & 0xFF); + write_cmos_sensor_8(0x0104, 0x00); + + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + kal_uint8 iRation; + kal_uint8 iReg; + + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + // Framelength should be an even number + le = (le >> 1) << 1; + se = (se >> 1) << 1; + imgsensor.frame_length = (imgsensor.frame_length >> 1) << 1; + + // Extend frame length + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x0340, (imgsensor.frame_length >> 8)& 0xFF); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + //long exporsure + write_cmos_sensor(0x0202, (le >> 8) & 0xFF); + write_cmos_sensor(0x0203, le & 0xFF); + //short exporsure + write_cmos_sensor(0x0230, (se >> 8) & 0xFF); + write_cmos_sensor(0x0231, se & 0xFF); + + iReg = gain2reg(gain); + + // LE Gain + write_cmos_sensor(0x0205, (kal_uint8)iReg); + // SE Gain + write_cmos_sensor(0x0233, (kal_uint8)iReg); + + + //SET LE/SE ration + //iRation = (((LE + SE/2)/SE) >> 1 ) << 1 ; + iRation = ((10 * le / se) + 5) / 10; + if(iRation < 2) + iRation = 0; + else if(iRation < 4) + iRation = 1; + else if(iRation < 8) + iRation = 2; + else if(iRation < 16) + iRation = 4; + else if(iRation < 32) + iRation = 8; + else + iRation = 0; + write_cmos_sensor(0x0239,iRation);// exposure ratio --> 2 : 1/4 + write_cmos_sensor_8(0x0104, 0x00); + LOG_INF("[IMX135MIPI_IHDR_write_shutter_gain ] iRation:%d\n", iRation); + + } + + +} + +static void ihdr_write_shutter(kal_uint16 le, kal_uint16 se) +{ + kal_uint8 iRation; + //kal_uint8 iReg; + + LOG_INF("le:0x%x, se:0x%x\n",le,se); + + + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x0340, (imgsensor.frame_length >> 8)& 0xFF); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + //long exporsure + write_cmos_sensor(0x0202, (le >> 8) & 0xFF); + write_cmos_sensor(0x0203, le & 0xFF); + //short exporsure + write_cmos_sensor(0x0230, (se >> 8) & 0xFF); + write_cmos_sensor(0x0231, se & 0xFF); + + //SET LE/SE ration + //iRation = (((LE + SE/2)/SE) >> 1 ) << 1 ; + iRation = ((10 * le / se) + 5) / 10; + if(iRation < 2) + iRation = 0; + else if(iRation < 4) + iRation = 1; + else if(iRation < 8) + iRation = 2; + else if(iRation < 16) + iRation = 4; + else if(iRation < 32) + iRation = 8; + else + iRation = 0; + write_cmos_sensor(0x0239,iRation);// exposure ratio --> 2 : 1/4 + write_cmos_sensor_8(0x0104, 0x00); + LOG_INF("[IMX135MIPI_IHDR_write_shutter_gain ] iRation:%d\n", iRation); + + } + + +} + +#if 0 +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x0101 Sensor mirror flip + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + kal_uint8 iTemp; + + iTemp = read_cmos_sensor(0x0101); + iTemp&= ~0x03; //Clear the mirror and flip bits. + + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor_8(0x0101, iTemp); //Set normal + break; + case IMAGE_H_MIRROR: + write_cmos_sensor_8(0x0101, iTemp | 0x01); //Set mirror + break; + case IMAGE_V_MIRROR: + write_cmos_sensor_8(0x0101, iTemp | 0x02); //Set flip + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor_8(0x0101, iTemp | 0x03); //Set mirror and flip + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} +#endif + +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + +static void sensor_init(void) +{ + LOG_INF("E\n"); + + /***************************************************************************** + 0x3098[0:1] pll3_prediv + pll3_prediv_map[] = {2, 3, 4, 6} + + 0x3099[0:4] pll3_multiplier + pll3_multiplier + + 0x309C[0] pll3_rdiv + pll3_rdiv + 1 + + 0x309A[0:3] pll3_sys_div + pll3_sys_div + 1 + + 0x309B[0:1] pll3_div + pll3_div[] = {2, 2, 4, 5} + + VCO = XVCLK * 2 / pll3_prediv * pll3_multiplier * pll3_rdiv + sysclk = VCO * 2 * 2 / pll3_sys_div / pll3_div + + XVCLK = 24 MHZ + 0x3098, 0x03 + 0x3099, 0x1e + 0x309a, 0x02 + 0x309b, 0x01 + 0x309c, 0x00 + + + VCO = 24 * 2 / 6 * 31 * 1 + sysclk = VCO * 2 * 2 / 3 / 2 + sysclk = 160 MHZ + */ + + write_cmos_sensor(0x0103, 0x01);// + write_cmos_sensor(0x0101, 0x00);// + write_cmos_sensor(0x0105, 0x01);// + write_cmos_sensor(0x0110, 0x00);// + write_cmos_sensor(0x0220, 0x01);// + write_cmos_sensor(0x3302, 0x11);// + write_cmos_sensor(0x3833, 0x20);// + write_cmos_sensor(0x3893, 0x00);// + write_cmos_sensor(0x3906, 0x08);// + write_cmos_sensor(0x3907, 0x01);// + write_cmos_sensor(0x391B, 0x01);// + write_cmos_sensor(0x3C09, 0x01);// + write_cmos_sensor(0x600A, 0x00);// + write_cmos_sensor(0x3008, 0xB0);// + write_cmos_sensor(0x320A, 0x01);// + write_cmos_sensor(0x320D, 0x10);// + write_cmos_sensor(0x3216, 0x2E);// + write_cmos_sensor(0x322C, 0x02);// + write_cmos_sensor(0x3409, 0x0C);// + write_cmos_sensor(0x340C, 0x2D);// + write_cmos_sensor(0x3411, 0x39);// + write_cmos_sensor(0x3414, 0x1E);// + write_cmos_sensor(0x3427, 0x04);// + write_cmos_sensor(0x3480, 0x1E);// + write_cmos_sensor(0x3484, 0x1E);// + write_cmos_sensor(0x3488, 0x1E);// + write_cmos_sensor(0x348C, 0x1E);// + write_cmos_sensor(0x3490, 0x1E);// + write_cmos_sensor(0x3494, 0x1E);// + write_cmos_sensor(0x3511, 0x8F);// + write_cmos_sensor(0x364F, 0x2D);// + + //quality + + //defect forrection recommended setting + + write_cmos_sensor(0x380A, 0x00);// + write_cmos_sensor(0x380B, 0x00);// + write_cmos_sensor(0x4103, 0x00);// + + //color artifact recommended setting + + write_cmos_sensor(0x4243, 0x9A);// + write_cmos_sensor(0x4330, 0x01);// + write_cmos_sensor(0x4331, 0x90);// + write_cmos_sensor(0x4332, 0x02);// + write_cmos_sensor(0x4333, 0x58);// + write_cmos_sensor(0x4334, 0x03);// + write_cmos_sensor(0x4335, 0x20);// + write_cmos_sensor(0x4336, 0x03);// + write_cmos_sensor(0x4337, 0x84);// + write_cmos_sensor(0x433C, 0x01);// + write_cmos_sensor(0x4340, 0x02);// + write_cmos_sensor(0x4341, 0x58);// + write_cmos_sensor(0x4342, 0x03);// + write_cmos_sensor(0x4343, 0x52);// + + + /////Moire reduction parameter setting + + write_cmos_sensor(0x4364, 0x0B);// + write_cmos_sensor(0x4368, 0x00);// + write_cmos_sensor(0x4369, 0x0F);// + write_cmos_sensor(0x436A, 0x03);// + write_cmos_sensor(0x436B, 0xA8);// + write_cmos_sensor(0x436C, 0x00);// + write_cmos_sensor(0x436D, 0x00);// + write_cmos_sensor(0x436E, 0x00);// + write_cmos_sensor(0x436F, 0x06);// + + //CNR parameter setting + + write_cmos_sensor(0x4281, 0x21);// + write_cmos_sensor(0x4282, 0x18);// + write_cmos_sensor(0x4283, 0x04);// + write_cmos_sensor(0x4284, 0x08);// + write_cmos_sensor(0x4287, 0x7F);// + write_cmos_sensor(0x4288, 0x08);// + write_cmos_sensor(0x428B, 0x7F);// + write_cmos_sensor(0x428C, 0x08);// + write_cmos_sensor(0x428F, 0x7F);// + write_cmos_sensor(0x4297, 0x00);// + write_cmos_sensor(0x4298, 0x7E);// + write_cmos_sensor(0x4299, 0x7E);// + write_cmos_sensor(0x429A, 0x7E);// + write_cmos_sensor(0x42A4, 0xFB);// + write_cmos_sensor(0x42A5, 0x7E);// + write_cmos_sensor(0x42A6, 0xDF);// + write_cmos_sensor(0x42A7, 0xB7);// + write_cmos_sensor(0x42AF, 0x03);// + + // ARNR Parameter setting + write_cmos_sensor(0x4207, 0x03);// + write_cmos_sensor(0x4216, 0x08);// + write_cmos_sensor(0x4217, 0x08);// + + //DLC Parammeter setting + write_cmos_sensor(0x4218, 0x00);// + write_cmos_sensor(0x421B, 0x20);// + write_cmos_sensor(0x421F, 0x04);// + write_cmos_sensor(0x4222, 0x02);// + write_cmos_sensor(0x4223, 0x22);// + write_cmos_sensor(0x422E, 0x54);// + write_cmos_sensor(0x422F, 0xFB);// + write_cmos_sensor(0x4230, 0xFF);// + write_cmos_sensor(0x4231, 0xFE);// + write_cmos_sensor(0x4232, 0xFF);// + write_cmos_sensor(0x4235, 0x58);// + write_cmos_sensor(0x4236, 0xF7);// + write_cmos_sensor(0x4237, 0xFD);// + write_cmos_sensor(0x4239, 0x4E);// + write_cmos_sensor(0x423A, 0xFC);// + write_cmos_sensor(0x423B, 0xFD);// + + //HDR + + + //LSC setting + write_cmos_sensor(0x452A, 0x02);// + + + //white balance setting + write_cmos_sensor(0x0712, 0x01);// + write_cmos_sensor(0x0713, 0x00);// + write_cmos_sensor(0x0714, 0x01);// + write_cmos_sensor(0x0715, 0x00);// + write_cmos_sensor(0x0716, 0x01);// + write_cmos_sensor(0x0717, 0x00);// + write_cmos_sensor(0x0718, 0x01);// + write_cmos_sensor(0x0719, 0x00);// + + //shading setting + write_cmos_sensor(0x4500, 0x1F);// + //Disable AE statistics + write_cmos_sensor(0x33B3, 0x00); + //Disable Embeded lines + write_cmos_sensor(0x3314, 0x00); +#if 0 + #if IMX135_OTP_Enable + otp_update(); + #endif +#endif + spin_lock(&imgsensor_drv_lock); + imgsensor.update_sensor_otp_awb = 0; // Init to 0 + imgsensor.update_sensor_otp_lsc = 0; // Init to 0 + spin_unlock(&imgsensor_drv_lock); +} /* sensor_init */ + + + +static void preview_setting(void) //PreviewSetting +{ + //5.1.2 FQPreview 1296x972 30fps 24M MCLK 2lane 864Mbps/lane + //PLL setting + write_cmos_sensor(0x0100,0x00);// STREAM STop + + //PLL setting + write_cmos_sensor(0x011E,0x18);// + write_cmos_sensor(0x011F,0x00);// + write_cmos_sensor(0x0301,0x05);// + write_cmos_sensor(0x0303,0x01);// + write_cmos_sensor(0x0305,0x0B);// + write_cmos_sensor(0x0309,0x05);// + write_cmos_sensor(0x030B,0x01);// + write_cmos_sensor(0x030C,0x01);// + write_cmos_sensor(0x030D,0x09);// + write_cmos_sensor(0x030E,0x01);// + write_cmos_sensor(0x3A06,0x11);// + + //Mode setting + mdelay(10); + write_cmos_sensor(0x0108,0x03);// + write_cmos_sensor(0x0112,0x0A);// + write_cmos_sensor(0x0113,0x0A);// + write_cmos_sensor(0x0381,0x01);// + write_cmos_sensor(0x0383,0x01);// + write_cmos_sensor(0x0385,0x01);// + write_cmos_sensor(0x0387,0x01);// + write_cmos_sensor(0x0390,0x01);// + write_cmos_sensor(0x0391,0x22);// + write_cmos_sensor(0x0392,0x00);// + write_cmos_sensor(0x0401,0x00);// + write_cmos_sensor(0x0404,0x00);// + write_cmos_sensor(0x0405,0x10);// + write_cmos_sensor(0x4082,0x01);// + write_cmos_sensor(0x4083,0x01);// + write_cmos_sensor(0x7006,0x04);// + + //Optionnal function setting +if(imgsensor.update_sensor_otp_lsc != 0){} +else { + write_cmos_sensor(0x0700,0x00);// + write_cmos_sensor(0x3A63,0x00);// +} + write_cmos_sensor(0x4100,0xF8);// + write_cmos_sensor(0x4203,0xFF);// + write_cmos_sensor(0x4344,0x00);// + write_cmos_sensor(0x441C,0x01);// + + //Size setting + write_cmos_sensor(0x0340,(imgsensor_info.pre.framelength>>8)&0xFF);// + write_cmos_sensor(0x0341,(imgsensor_info.pre.framelength>>0)&0xFF);// + write_cmos_sensor(0x0342,(imgsensor_info.pre.linelength>>8)&0xFF);// + write_cmos_sensor(0x0343,(imgsensor_info.pre.linelength>>0)&0xFF);// + write_cmos_sensor(0x0344,0x00);// + write_cmos_sensor(0x0345,0x00);// + write_cmos_sensor(0x0346,0x00);// + write_cmos_sensor(0x0347,0x00);// + write_cmos_sensor(0x0348,0x10);// + write_cmos_sensor(0x0349,0x6F);// + write_cmos_sensor(0x034A,0x0C);// + write_cmos_sensor(0x034B,0x2F);// + write_cmos_sensor(0x034C,0x08);// + write_cmos_sensor(0x034D,0x38);// + write_cmos_sensor(0x034E,0x06);// + write_cmos_sensor(0x034F,0x18);// + write_cmos_sensor(0x0350,0x00);// + write_cmos_sensor(0x0351,0x00);// + write_cmos_sensor(0x0352,0x00);// + write_cmos_sensor(0x0353,0x00);// + write_cmos_sensor(0x0354,0x08);// + write_cmos_sensor(0x0355,0x38);// + write_cmos_sensor(0x0356,0x06);// + write_cmos_sensor(0x0357,0x18);// + write_cmos_sensor(0x301D,0x30);// + write_cmos_sensor(0x3310,0x08);// + write_cmos_sensor(0x3311,0x38);// + write_cmos_sensor(0x3312,0x06);// + write_cmos_sensor(0x3313,0x18);// + write_cmos_sensor(0x331C,0x04);// + write_cmos_sensor(0x331D,0xAB);// + write_cmos_sensor(0x4084,0x00);// + write_cmos_sensor(0x4085,0x00);// + write_cmos_sensor(0x4086,0x00);// + write_cmos_sensor(0x4087,0x00);// + write_cmos_sensor(0x4400,0x00);// + + //global timing setting + write_cmos_sensor(0x0830,0x6F);// + write_cmos_sensor(0x0831,0x27);// + write_cmos_sensor(0x0832,0x4F);// + write_cmos_sensor(0x0833,0x2F);// + write_cmos_sensor(0x0834,0x2F);// + write_cmos_sensor(0x0835,0x2F);// + write_cmos_sensor(0x0836,0x9F);// + write_cmos_sensor(0x0837,0x37);// + write_cmos_sensor(0x0839,0x1F);// + write_cmos_sensor(0x083A,0x17);// + write_cmos_sensor(0x083B,0x02);// + + // integration time setting + write_cmos_sensor(0x0202,0x06);// + write_cmos_sensor(0x0203,0x64);// + + //gain setting +if(imgsensor.update_sensor_otp_awb != 0) {} +else { + write_cmos_sensor(0x0205,0xe0);// + write_cmos_sensor(0x020E,0x01);// + write_cmos_sensor(0x020F,0x00);// + write_cmos_sensor(0x0210,0x01);// + write_cmos_sensor(0x0211,0x00);// + write_cmos_sensor(0x0212,0x01);// + write_cmos_sensor(0x0213,0x00);// + write_cmos_sensor(0x0214,0x01);// + write_cmos_sensor(0x0215,0x00);// +} + if(imgsensor.ihdr_en ){ + //hdr setting + write_cmos_sensor(0x0230,0x00);// + write_cmos_sensor(0x0231,0x00);// + //write_cmos_sensor(0x0233,0x00);// + write_cmos_sensor(0x0234,0x00);// + write_cmos_sensor(0x0235,0x40);// + write_cmos_sensor(0x0236,0x00);// + write_cmos_sensor(0x0238,0x00);// 0: auto mode 1: direct mode + write_cmos_sensor(0x0239,0x04);// exposure ratio --> 2 : 1/4 + write_cmos_sensor(0x023B,0x03);// + write_cmos_sensor(0x023C,0x01);// + write_cmos_sensor(0x33B0,0x08);// + write_cmos_sensor(0x33B1,0x38);// + //write_cmos_sensor(0x33B3,0x01);// don't send AE statistics + write_cmos_sensor(0x33B4,0x01);// + write_cmos_sensor(0x3873,0x00);// + write_cmos_sensor(0x3800,0x00);// + write_cmos_sensor(0x391b,0x01);// + write_cmos_sensor(0x446c,0x00);// + } + + write_cmos_sensor(0x3A43,0x01);// + write_cmos_sensor(0x0100,0x01);// STREAM START + +} /* preview_setting */ +static void capture_setting_15fps(kal_uint16 currefps) // IMX135MIPI_set_13M +{ + + write_cmos_sensor(0x0100,0x00);// STREAM STop + write_cmos_sensor(0x011E,0x18); + write_cmos_sensor(0x011F,0x00); + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x01); + write_cmos_sensor(0x0305,0x0B); + write_cmos_sensor(0x0309,0x05); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030C,0x01); + write_cmos_sensor(0x030D,0x09); + write_cmos_sensor(0x030E,0x01); + write_cmos_sensor(0x3A06,0x11); + + //Modesetting + mdelay(10); + write_cmos_sensor(0x0108,0x03); + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0390,0x00); + write_cmos_sensor(0x0391,0x11); + write_cmos_sensor(0x0392,0x00); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x4082,0x01); + write_cmos_sensor(0x4083,0x01); + write_cmos_sensor(0x7006,0x04); + + //OptionnalFunctionsetting + write_cmos_sensor(0x0700,0x00);// + write_cmos_sensor(0x3A63,0x00);// + write_cmos_sensor(0x4100,0xF8); + write_cmos_sensor(0x4203,0xFF); + write_cmos_sensor(0x4344,0x00); + write_cmos_sensor(0x441C,0x01); + + //Sizesetting + write_cmos_sensor(0x0340,(imgsensor_info.cap.framelength>>8)&0xFF);// + write_cmos_sensor(0x0341,(imgsensor_info.cap.framelength>>0)&0xFF);// + write_cmos_sensor(0x0342,(imgsensor_info.cap.linelength>>8)&0xFF);// + write_cmos_sensor(0x0343,(imgsensor_info.cap.linelength>>0)&0xFF);// + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + write_cmos_sensor(0x0350,0x00); + write_cmos_sensor(0x0351,0x00); + write_cmos_sensor(0x0352,0x00); + write_cmos_sensor(0x0353,0x00); + write_cmos_sensor(0x0354,0x10); + write_cmos_sensor(0x0355,0x70); + write_cmos_sensor(0x0356,0x0C); + write_cmos_sensor(0x0357,0x30); + write_cmos_sensor(0x301D,0x30); + write_cmos_sensor(0x3310,0x10); + write_cmos_sensor(0x3311,0x70); + write_cmos_sensor(0x3312,0x0C); + write_cmos_sensor(0x3313,0x30); + write_cmos_sensor(0x331C,0x01); + write_cmos_sensor(0x331D,0x68); + write_cmos_sensor(0x4084,0x00); + write_cmos_sensor(0x4085,0x00); + write_cmos_sensor(0x4086,0x00); + write_cmos_sensor(0x4087,0x00); + write_cmos_sensor(0x4400,0x00); + //GlobalTimingSetting + write_cmos_sensor(0x0830,0x6f); + write_cmos_sensor(0x0831,0x27); + write_cmos_sensor(0x0832,0x4F); + write_cmos_sensor(0x0833,0x2F); + write_cmos_sensor(0x0834,0x2F); + write_cmos_sensor(0x0835,0x2F); + write_cmos_sensor(0x0836,0x9f); + write_cmos_sensor(0x0837,0x37); + write_cmos_sensor(0x0839,0x1F); + write_cmos_sensor(0x083A,0x17); + write_cmos_sensor(0x083B,0x02); + //IntegrationTimeSetting + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0xCC); + //GainSetting + write_cmos_sensor(0x0205,0x00); // e0 + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x3A43,0x01);// + write_cmos_sensor(0x0100,0x01);//STREAM START +} + + +static void capture_setting(kal_uint16 currefps) // IMX135MIPI_set_13M +{ +LOG_INF("E! currefps:%d\n",currefps); + write_cmos_sensor(0x0100,0x00);// STREAM STop + //ClockSetting + if(currefps == 300) // default 30.0 fps + { + write_cmos_sensor(0x011E,0x18); + write_cmos_sensor(0x011F,0x00); + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x01); + write_cmos_sensor(0x0305,0x0C); + write_cmos_sensor(0x0309,0x05); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030C,0x02); // 1 + write_cmos_sensor(0x030D,0x1c); // b3 + write_cmos_sensor(0x030E,0x01); + write_cmos_sensor(0x3A06,0x11); + } + else + { + write_cmos_sensor(0x011E,0x18); + write_cmos_sensor(0x011F,0x00); + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x01); + write_cmos_sensor(0x0305,0x0C); + write_cmos_sensor(0x0309,0x05); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030C,0x01); + write_cmos_sensor(0x030D,0xb3); + write_cmos_sensor(0x030E,0x01); // 1 + write_cmos_sensor(0x3A06,0x11); // 11 + } + + mdelay(10); + //Modesetting + write_cmos_sensor(0x0108,0x03); + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0390,0x00); + write_cmos_sensor(0x0391,0x11); + write_cmos_sensor(0x0392,0x00); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x4082,0x01); + write_cmos_sensor(0x4083,0x01); + write_cmos_sensor(0x7006,0x04); + + //OptionnalFunctionsetting +if(imgsensor.update_sensor_otp_lsc != 0){} +else { + write_cmos_sensor(0x0700,0x00);// + write_cmos_sensor(0x3A63,0x00);// +} + write_cmos_sensor(0x4100,0xF8); + write_cmos_sensor(0x4203,0xFF); + write_cmos_sensor(0x4344,0x00); + write_cmos_sensor(0x441C,0x01); + + //Sizesetting + write_cmos_sensor(0x0340,(imgsensor_info.cap.framelength>>8)&0xFF);// + write_cmos_sensor(0x0341,(imgsensor_info.cap.framelength>>0)&0xFF);// + write_cmos_sensor(0x0342,(imgsensor_info.cap.linelength>>8)&0xFF);// + write_cmos_sensor(0x0343,(imgsensor_info.cap.linelength>>0)&0xFF);// + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + write_cmos_sensor(0x0350,0x00); + write_cmos_sensor(0x0351,0x00); + write_cmos_sensor(0x0352,0x00); + write_cmos_sensor(0x0353,0x00); + write_cmos_sensor(0x0354,0x10); + write_cmos_sensor(0x0355,0x70); + write_cmos_sensor(0x0356,0x0C); + write_cmos_sensor(0x0357,0x30); + write_cmos_sensor(0x301D,0x30); + write_cmos_sensor(0x3310,0x10); + write_cmos_sensor(0x3311,0x70); + write_cmos_sensor(0x3312,0x0C); + write_cmos_sensor(0x3313,0x30); + write_cmos_sensor(0x331C,0x01); + write_cmos_sensor(0x331D,0x68); + write_cmos_sensor(0x4084,0x00); + write_cmos_sensor(0x4085,0x00); + write_cmos_sensor(0x4086,0x00); + write_cmos_sensor(0x4087,0x00); + write_cmos_sensor(0x4400,0x00); + if(currefps == 300) + { + write_cmos_sensor(0x0830,0x8f); // 7f + write_cmos_sensor(0x0831,0x47); // 37 + write_cmos_sensor(0x0832,0x7f); // 67 + write_cmos_sensor(0x0833,0x4F); // 3f + write_cmos_sensor(0x0834,0x47); // 3f + write_cmos_sensor(0x0835,0x5f); // 47 + write_cmos_sensor(0x0836,0xff); // df + write_cmos_sensor(0x0837,0x4f); // 47 + write_cmos_sensor(0x0839,0x1F); // 1f + write_cmos_sensor(0x083A,0x17); // 17 + write_cmos_sensor(0x083B,0x02); // 2 + //write_cmos_sensor(0x0202,0x0C); + //write_cmos_sensor(0x0203,0x42);// 46 + write_cmos_sensor(0x0202,0x06);// set as preview shutter + write_cmos_sensor(0x0203,0x64);// + } + else // for PIP + { + //GlobalTimingSetting + write_cmos_sensor(0x0830,0x7f); + write_cmos_sensor(0x0831,0x37); + write_cmos_sensor(0x0832,0x67); + write_cmos_sensor(0x0833,0x3f); + write_cmos_sensor(0x0834,0x3f); + write_cmos_sensor(0x0835,0x47); + write_cmos_sensor(0x0836,0xdf); + write_cmos_sensor(0x0837,0x47); + write_cmos_sensor(0x0839,0x1F); + write_cmos_sensor(0x083A,0x17); + write_cmos_sensor(0x083B,0x02); + //IntegrationTimeSetting + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x46); + + //GlobalTimingSetting + //IntegrationTimeSetting + } + //GainSetting +if(imgsensor.update_sensor_otp_awb != 0){} +else { + write_cmos_sensor(0x0205,0x00); // e0 + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); +} + //HDRSetting +#if 0 + write_cmos_sensor(0x0230,0x00); + write_cmos_sensor(0x0231,0x00); + write_cmos_sensor(0x0233,0x00); + write_cmos_sensor(0x0234,0x00); + write_cmos_sensor(0x0235,0x40); + write_cmos_sensor(0x0238,0x00); + write_cmos_sensor(0x0239,0x04); + write_cmos_sensor(0x023B,0x00); + write_cmos_sensor(0x023C,0x01); + write_cmos_sensor(0x33B0,0x04); + write_cmos_sensor(0x33B1,0x00); + write_cmos_sensor(0x33B3,0x00); + write_cmos_sensor(0x33B4,0x01); + write_cmos_sensor(0x3800,0x00); +#endif//HDRSetting + + write_cmos_sensor(0x3A43,0x01);// + write_cmos_sensor(0x0100,0x01);//STREAM START + +} +#if 0 +static void normal_video_setting(kal_uint16 currefps) // VideoFullSizeSetting +{ + LOG_INF("E! currefps:%d\n",currefps); + + write_cmos_sensor(0x0100,0x00);// STREAM STop + //ClockSetting + write_cmos_sensor(0x011E,0x18); + write_cmos_sensor(0x011F,0x00); + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x01); + write_cmos_sensor(0x0305,0x0C); + write_cmos_sensor(0x0309,0x05); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030C,0x02); // 1 + write_cmos_sensor(0x030D,0x1c); // b3 + write_cmos_sensor(0x030E,0x01); // 1 + write_cmos_sensor(0x3A06,0x11); // 11 + //Modesetting + mdelay(10); + write_cmos_sensor(0x0108,0x03); + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0390,0x00); + write_cmos_sensor(0x0391,0x11); + write_cmos_sensor(0x0392,0x00); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x4082,0x01); + write_cmos_sensor(0x4083,0x01); + write_cmos_sensor(0x7006,0x04); + + //OptionnalFunctionsetting +if(imgsensor.update_sensor_otp_lsc != 0){} +else { + write_cmos_sensor(0x0700,0x00);// + write_cmos_sensor(0x3A63,0x00);// +} + write_cmos_sensor(0x4100,0xF8); + write_cmos_sensor(0x4203,0xFF); + write_cmos_sensor(0x4344,0x00); + write_cmos_sensor(0x441C,0x01); + + //Size setting + write_cmos_sensor(0x0340,(imgsensor_info.normal_video.framelength>>8)&0xFF);// + write_cmos_sensor(0x0341,(imgsensor_info.normal_video.framelength>>0)&0xFF);// + write_cmos_sensor(0x0342,(imgsensor_info.normal_video.linelength>>8)&0xFF);// + write_cmos_sensor(0x0343,(imgsensor_info.normal_video.linelength>>0)&0xFF);// + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + write_cmos_sensor(0x0350,0x00); + write_cmos_sensor(0x0351,0x00); + write_cmos_sensor(0x0352,0x00); + write_cmos_sensor(0x0353,0x00); + write_cmos_sensor(0x0354,0x10); + write_cmos_sensor(0x0355,0x70); + write_cmos_sensor(0x0356,0x0C); + write_cmos_sensor(0x0357,0x30); + write_cmos_sensor(0x301D,0x30); + write_cmos_sensor(0x3310,0x10); + write_cmos_sensor(0x3311,0x70); + write_cmos_sensor(0x3312,0x0C); + write_cmos_sensor(0x3313,0x30); + write_cmos_sensor(0x331C,0x01); + write_cmos_sensor(0x331D,0x68); + write_cmos_sensor(0x4084,0x00); + write_cmos_sensor(0x4085,0x00); + write_cmos_sensor(0x4086,0x00); + write_cmos_sensor(0x4087,0x00); + write_cmos_sensor(0x4400,0x00); + + //GlobalTimingSetting + write_cmos_sensor(0x0830,0x8f); // 7f + write_cmos_sensor(0x0831,0x47); // 37 + write_cmos_sensor(0x0832,0x7f); // 67 + write_cmos_sensor(0x0833,0x4F); // 3f + write_cmos_sensor(0x0834,0x47); // 3f + write_cmos_sensor(0x0835,0x5f); // 47 + write_cmos_sensor(0x0836,0xff); // df + write_cmos_sensor(0x0837,0x4f); // 47 + write_cmos_sensor(0x0839,0x1F); // 1f + write_cmos_sensor(0x083A,0x17); // 17 + write_cmos_sensor(0x083B,0x02); // 2 + //IntegrationTimeSetting + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x42);// 46 + + //GainSetting +if(imgsensor.update_sensor_otp_awb != 0){} +else { + write_cmos_sensor(0x0205,0x00); // e0 + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); +} + //HDRSetting +#if 0 + write_cmos_sensor(0x0230,0x00); + write_cmos_sensor(0x0231,0x00); + write_cmos_sensor(0x0233,0x00); + write_cmos_sensor(0x0234,0x00); + write_cmos_sensor(0x0235,0x40); + write_cmos_sensor(0x0238,0x00); + write_cmos_sensor(0x0239,0x04); + write_cmos_sensor(0x023B,0x00); + write_cmos_sensor(0x023C,0x01); + write_cmos_sensor(0x33B0,0x04); + write_cmos_sensor(0x33B1,0x00); + write_cmos_sensor(0x33B3,0x00); + write_cmos_sensor(0x33B4,0x01); + write_cmos_sensor(0x3800,0x00); + #endif + + write_cmos_sensor(0x3A43,0x01);// + write_cmos_sensor(0x0100,0x01);// STREAM START + +} +#endif +void IMX135MIPI_set_Video_IHDR(kal_uint16 IHDR_En) +{ + + write_cmos_sensor(0x0100,0x00);// STREAM STop + //PLL setting + write_cmos_sensor(0x011E,0x18);// + write_cmos_sensor(0x011F,0x00);// + write_cmos_sensor(0x0301,0x05);// + write_cmos_sensor(0x0303,0x01);// + write_cmos_sensor(0x0305,0x0B);// + write_cmos_sensor(0x0309,0x05);// + write_cmos_sensor(0x030B,0x01);// + write_cmos_sensor(0x030C,0x01);// + write_cmos_sensor(0x030D,0xEF);// + write_cmos_sensor(0x030E,0x01);// + write_cmos_sensor(0x3A06,0x11);// + + //Mode setting + mdelay(10); + write_cmos_sensor(0x0108,0x03);// + write_cmos_sensor(0x0112,0x0E);// + write_cmos_sensor(0x0113,0x0A);// + write_cmos_sensor(0x0381,0x01);// + write_cmos_sensor(0x0383,0x01);// + write_cmos_sensor(0x0385,0x01);// + write_cmos_sensor(0x0387,0x01);// + write_cmos_sensor(0x0390,0x00);// + write_cmos_sensor(0x0391,0x11);// + write_cmos_sensor(0x0392,0x00);// + write_cmos_sensor(0x0401,0x00);// + write_cmos_sensor(0x0404,0x00);// + write_cmos_sensor(0x0405,0x10);// + write_cmos_sensor(0x4082,0x01);// + write_cmos_sensor(0x4083,0x01);// + write_cmos_sensor(0x7006,0x04);// + //Optionnal function setting + write_cmos_sensor(0x0700,0x00);// + write_cmos_sensor(0x3A63,0x00);// + write_cmos_sensor(0x4100,0xF8);// + write_cmos_sensor(0x4203,0xFF);// + write_cmos_sensor(0x4344,0x00);// + write_cmos_sensor(0x441C,0x01);// + //Size setting + write_cmos_sensor(0x0340,(imgsensor_info.normal_video.framelength>>8)&0xFF);// + write_cmos_sensor(0x0341,(imgsensor_info.normal_video.framelength>>0)&0xFF);// + write_cmos_sensor(0x0342,(imgsensor_info.normal_video.linelength>>8)&0xFF);// + write_cmos_sensor(0x0343,(imgsensor_info.normal_video.linelength>>0)&0xFF);// + write_cmos_sensor(0x0344,0x00);// + write_cmos_sensor(0x0345,0x00);// + write_cmos_sensor(0x0346,0x00);// + write_cmos_sensor(0x0347,0x00);// + write_cmos_sensor(0x0348,0x10);// + write_cmos_sensor(0x0349,0x6F);// + write_cmos_sensor(0x034A,0x0C);// + write_cmos_sensor(0x034B,0x2F);// + write_cmos_sensor(0x034C,0x10);// + write_cmos_sensor(0x034D,0x70);// + write_cmos_sensor(0x034E,0x0C);// + write_cmos_sensor(0x034F,0x30);// + write_cmos_sensor(0x0350,0x00);// + write_cmos_sensor(0x0351,0x00);// + write_cmos_sensor(0x0352,0x00);// + write_cmos_sensor(0x0353,0x00);// + write_cmos_sensor(0x0354,0x10);// + write_cmos_sensor(0x0355,0x70);// + write_cmos_sensor(0x0356,0x0C);// + write_cmos_sensor(0x0357,0x30);// + write_cmos_sensor(0x301D,0x30);// + write_cmos_sensor(0x3310,0x10);// + write_cmos_sensor(0x3311,0x70);// + write_cmos_sensor(0x3312,0x0C);// + write_cmos_sensor(0x3313,0x30);// + write_cmos_sensor(0x331C,0x01);// + write_cmos_sensor(0x331D,0x68);// + write_cmos_sensor(0x4084,0x00);// + write_cmos_sensor(0x4085,0x00);// + write_cmos_sensor(0x4086,0x00);// + write_cmos_sensor(0x4087,0x00);// + write_cmos_sensor(0x4400,0x00);// + //global timing setting + write_cmos_sensor(0x0830,0x8F);// + write_cmos_sensor(0x0831,0x47);// + write_cmos_sensor(0x0832,0x7F);// + write_cmos_sensor(0x0833,0x4F);// + write_cmos_sensor(0x0834,0x47);// + write_cmos_sensor(0x0835,0x5F);// + write_cmos_sensor(0x0836,0xFF);// + write_cmos_sensor(0x0837,0x4F);// + write_cmos_sensor(0x0839,0x1F);// + write_cmos_sensor(0x083A,0x17);// + write_cmos_sensor(0x083B,0x02);// + + // integration time setting + write_cmos_sensor(0x0202,0x0C);// + write_cmos_sensor(0x0203,0x44);// + //gain setting + write_cmos_sensor(0x0205,0x00);// + write_cmos_sensor(0x020E,0x01);// + write_cmos_sensor(0x020F,0x00);// + write_cmos_sensor(0x0210,0x01);// + write_cmos_sensor(0x0211,0x00);// + write_cmos_sensor(0x0212,0x01);// + write_cmos_sensor(0x0213,0x00);// + write_cmos_sensor(0x0214,0x01);// + write_cmos_sensor(0x0215,0x00);// + + if(IHDR_En) + { + LOG_INF("VIDEO IHDR\n"); + //hdr setting + write_cmos_sensor(0x0230,0x00);// + write_cmos_sensor(0x0231,0x00);// + //write_cmos_sensor(0x0233,0x00);// + write_cmos_sensor(0x0234,0x00);// + write_cmos_sensor(0x0235,0x40);// + write_cmos_sensor(0x0238,0x01);// 0: auto mode 1: direct mode + write_cmos_sensor(0x0239,0x00);// exposure ratio --> 1:1/2 , 2 : 1/4, 4:1/8 + write_cmos_sensor(0x023B,0x00);// + write_cmos_sensor(0x023C,0x01);// + write_cmos_sensor(0x33B0,0x10);// + write_cmos_sensor(0x33B1,0x70);// + //write_cmos_sensor(0x33B3,0x01);// don't send AE statistics + write_cmos_sensor(0x33B4,0x01);// + write_cmos_sensor(0x3873,0x03);// + write_cmos_sensor(0x3800,0x00);// + write_cmos_sensor(0x391b,0x00);// + write_cmos_sensor(0x446c,0x01);// + //IMX135MIPI_IHDR_write_shutter_gain(1100,128); + } + else + { + //Raw Mode + write_cmos_sensor(0x0112,0x0a);// + write_cmos_sensor(0x0113,0x0a);// + write_cmos_sensor(0x4100,0xF8);// + write_cmos_sensor(0x4101,0x00);// + write_cmos_sensor(0x3873,0x00);// + write_cmos_sensor(0x446c,0x00);// + } + + write_cmos_sensor(0x3A43,0x01);// + write_cmos_sensor(0x0100,0x01);// STREAM START +} +/* +static void hs_video_setting_vga_120fps(void) // VideoHDSetting_120fps +{ + LOG_INF("E\n VGA 120fps "); + //PLL setting + write_cmos_sensor(0x0100,0x00);// STREAM STop + + //PLL setting + write_cmos_sensor(0x011E,0x18);// + write_cmos_sensor(0x011F,0x00);// + write_cmos_sensor(0x0301,0x05);// + write_cmos_sensor(0x0303,0x01);// + write_cmos_sensor(0x0305,0x0C);// + write_cmos_sensor(0x0309,0x05);// + write_cmos_sensor(0x030B,0x02);// + write_cmos_sensor(0x030C,0x02);// + write_cmos_sensor(0x030D,0x1C);// + write_cmos_sensor(0x030E,0x01);// + write_cmos_sensor(0x3A06,0x12);// + + //Mode setting + mdelay(10); + write_cmos_sensor(0x0108,0x03);// + write_cmos_sensor(0x0112,0x0A);// + write_cmos_sensor(0x0113,0x0A);// + write_cmos_sensor(0x0381,0x01);// + write_cmos_sensor(0x0383,0x01);// + write_cmos_sensor(0x0385,0x01);// + write_cmos_sensor(0x0387,0x01);// + write_cmos_sensor(0x0390,0x01);// + write_cmos_sensor(0x0391,0x44);// + write_cmos_sensor(0x0392,0x00);// + write_cmos_sensor(0x0401,0x02);// + write_cmos_sensor(0x0404,0x00);// + write_cmos_sensor(0x0405,0x1A);// + write_cmos_sensor(0x4082,0x00);// + write_cmos_sensor(0x4083,0x00);// + write_cmos_sensor(0x7006,0x04);// + + //Optionnal function setting +if(imgsensor.update_sensor_otp_lsc != 0){} +else { + write_cmos_sensor(0x0700,0x00);// + write_cmos_sensor(0x3A63,0x00);// +} + write_cmos_sensor(0x4100,0xF8);// + write_cmos_sensor(0x4203,0xFF);// + write_cmos_sensor(0x4344,0x00);// + write_cmos_sensor(0x441C,0x01);// + + //Size setting + write_cmos_sensor(0x0340,(imgsensor_info.hs_video.framelength>>8)&0xFF);// + write_cmos_sensor(0x0341,(imgsensor_info.hs_video.framelength>>0)&0xFF);// + write_cmos_sensor(0x0342,(imgsensor_info.hs_video.linelength>>8)&0xFF);// + write_cmos_sensor(0x0343,(imgsensor_info.hs_video.linelength>>0)&0xFF);// + write_cmos_sensor(0x0344,0x00);// + write_cmos_sensor(0x0345,0x18);// + write_cmos_sensor(0x0346,0x00);// + write_cmos_sensor(0x0347,0x00);// + write_cmos_sensor(0x0348,0x10);// + write_cmos_sensor(0x0349,0x57);// + write_cmos_sensor(0x034A,0x0C);// + write_cmos_sensor(0x034B,0x2F);// + write_cmos_sensor(0x034C,0x02);// + write_cmos_sensor(0x034D,0x80);// + write_cmos_sensor(0x034E,0x01);// + write_cmos_sensor(0x034F,0xE0);// + write_cmos_sensor(0x0350,0x00);// + write_cmos_sensor(0x0351,0x00);// + write_cmos_sensor(0x0352,0x00);// + write_cmos_sensor(0x0353,0x00);// + write_cmos_sensor(0x0354,0x04);// + write_cmos_sensor(0x0355,0x10);// + write_cmos_sensor(0x0356,0x03);// + write_cmos_sensor(0x0357,0x0C);// + write_cmos_sensor(0x301D,0x30);// + write_cmos_sensor(0x3310,0x02);// + write_cmos_sensor(0x3311,0x80);// + write_cmos_sensor(0x3312,0x01);// + write_cmos_sensor(0x3313,0xE0);// + write_cmos_sensor(0x331C,0x01);// + write_cmos_sensor(0x331D,0xE4);// + write_cmos_sensor(0x4084,0x02);// + write_cmos_sensor(0x4085,0x80);// + write_cmos_sensor(0x4086,0x01);// + write_cmos_sensor(0x4087,0xE0);// + write_cmos_sensor(0x4400,0x00);// + + //global timing setting + write_cmos_sensor(0x0830,0x6F);// + write_cmos_sensor(0x0831,0x27);// + write_cmos_sensor(0x0832,0x47);// + write_cmos_sensor(0x0833,0x27);// + write_cmos_sensor(0x0834,0x27);// + write_cmos_sensor(0x0835,0x27);// + write_cmos_sensor(0x0836,0x8F);// + write_cmos_sensor(0x0837,0x37);// + write_cmos_sensor(0x0839,0x1F);// + write_cmos_sensor(0x083A,0x17);// + write_cmos_sensor(0x083B,0x02);// + + // integration time setting + write_cmos_sensor(0x0202,0x03);// + write_cmos_sensor(0x0203,0x1E);// + + //gain setting +if(imgsensor.update_sensor_otp_awb != 0){} +else { + write_cmos_sensor(0x0205,0x00);// + write_cmos_sensor(0x020E,0x01);// + write_cmos_sensor(0x020F,0x00);// + write_cmos_sensor(0x0210,0x01);// + write_cmos_sensor(0x0211,0x00);// + write_cmos_sensor(0x0212,0x01);// + write_cmos_sensor(0x0213,0x00);// + write_cmos_sensor(0x0214,0x01);// + write_cmos_sensor(0x0215,0x00);// +} +#if 0 + //hdr setting + write_cmos_sensor(0x0230,0x00);// + write_cmos_sensor(0x0231,0x00);// + write_cmos_sensor(0x0233,0x00);// + write_cmos_sensor(0x0234,0x00);// + write_cmos_sensor(0x0235,0x40);// + write_cmos_sensor(0x0236,0x00);// + write_cmos_sensor(0x0238,0x00);// + write_cmos_sensor(0x0239,0x04);// + write_cmos_sensor(0x023B,0x00);// + write_cmos_sensor(0x023C,0x01);// + write_cmos_sensor(0x33B0,0x04);// + write_cmos_sensor(0x33B1,0x00);// + write_cmos_sensor(0x33B3,0x00);// + write_cmos_sensor(0x33B4,0x01);// + write_cmos_sensor(0x3800,0x00);// +#endif + + write_cmos_sensor(0x3A43,0x01);// + write_cmos_sensor(0x0100,0x01);// STREAM START + +} +*/ +static void hs_video_setting(void) // VideoHDSetting_120fps +{ + LOG_INF("E\n Video 120fps "); + //PLL setting + write_cmos_sensor(0x0100,0x00);// STREAM STop + + //PLL setting + write_cmos_sensor(0x011E,0x18);// + write_cmos_sensor(0x011F,0x00);// + write_cmos_sensor(0x0301,0x05);// + write_cmos_sensor(0x0303,0x01);// + write_cmos_sensor(0x0305,0x0C);// + write_cmos_sensor(0x0309,0x05);// + write_cmos_sensor(0x030B,0x01);// + write_cmos_sensor(0x030C,0x02);// + write_cmos_sensor(0x030D,0x1C);// + write_cmos_sensor(0x030E,0x01);// + write_cmos_sensor(0x3A06,0x11);// + + //Mode setting + mdelay(10); + write_cmos_sensor(0x0108,0x03);// + write_cmos_sensor(0x0112,0x0A);// + write_cmos_sensor(0x0113,0x0A);// + write_cmos_sensor(0x0381,0x01);// + write_cmos_sensor(0x0383,0x01);// + write_cmos_sensor(0x0385,0x01);// + write_cmos_sensor(0x0387,0x01);// + write_cmos_sensor(0x0390,0x01);// + write_cmos_sensor(0x0391,0x22);// + write_cmos_sensor(0x0392,0x00);// + write_cmos_sensor(0x0401,0x00);// + write_cmos_sensor(0x0404,0x00);// + write_cmos_sensor(0x0405,0x10);// + write_cmos_sensor(0x4082,0x01);// + write_cmos_sensor(0x4083,0x01);// + write_cmos_sensor(0x7006,0x04);// + + //Optionnal function setting +if(imgsensor.update_sensor_otp_lsc != 0){} +else { + write_cmos_sensor(0x0700,0x00);// + write_cmos_sensor(0x3A63,0x00);// +} + write_cmos_sensor(0x4100,0xF8);// + write_cmos_sensor(0x4203,0xFF);// + write_cmos_sensor(0x4344,0x00);// + write_cmos_sensor(0x441C,0x01);// + + //Size setting + write_cmos_sensor(0x0340,(imgsensor_info.hs_video.framelength>>8)&0xFF);// + write_cmos_sensor(0x0341,(imgsensor_info.hs_video.framelength>>0)&0xFF);// + write_cmos_sensor(0x0342,(imgsensor_info.hs_video.linelength>>8)&0xFF);// + write_cmos_sensor(0x0343,(imgsensor_info.hs_video.linelength>>0)&0xFF);// + write_cmos_sensor(0x0344,0x03);// + write_cmos_sensor(0x0345,0x38);// + write_cmos_sensor(0x0346,0x03);// + write_cmos_sensor(0x0347,0x48);// + write_cmos_sensor(0x0348,0x0D);// + write_cmos_sensor(0x0349,0x37);// + write_cmos_sensor(0x034A,0x08);// + write_cmos_sensor(0x034B,0xE7);// + write_cmos_sensor(0x034C,0x05);// + write_cmos_sensor(0x034D,0x00);// + write_cmos_sensor(0x034E,0x02);// + write_cmos_sensor(0x034F,0xD0);// + write_cmos_sensor(0x0350,0x00);// + write_cmos_sensor(0x0351,0x00);// + write_cmos_sensor(0x0352,0x00);// + write_cmos_sensor(0x0353,0x00);// + write_cmos_sensor(0x0354,0x05);// + write_cmos_sensor(0x0355,0x00);// + write_cmos_sensor(0x0356,0x02);// + write_cmos_sensor(0x0357,0xD0);// + write_cmos_sensor(0x301D,0x30);// + write_cmos_sensor(0x3310,0x05);// + write_cmos_sensor(0x3311,0x00);// + write_cmos_sensor(0x3312,0x02);// + write_cmos_sensor(0x3313,0xD0);// + write_cmos_sensor(0x331C,0x03);// + write_cmos_sensor(0x331D,0xE8);// + write_cmos_sensor(0x4084,0x00);// + write_cmos_sensor(0x4085,0x00);// + write_cmos_sensor(0x4086,0x00);// + write_cmos_sensor(0x4087,0x00);// + write_cmos_sensor(0x4400,0x00);// + + //global timing setting + write_cmos_sensor(0x0830,0x6F);// + write_cmos_sensor(0x0831,0x27);// + write_cmos_sensor(0x0832,0x47);// + write_cmos_sensor(0x0833,0x27);// + write_cmos_sensor(0x0834,0x27);// + write_cmos_sensor(0x0835,0x27);// + write_cmos_sensor(0x0836,0x8F);// + write_cmos_sensor(0x0837,0x37);// + write_cmos_sensor(0x0839,0x1F);// + write_cmos_sensor(0x083A,0x17);// + write_cmos_sensor(0x083B,0x02);// + + // integration time setting + write_cmos_sensor(0x0202,0x03);// + write_cmos_sensor(0x0203,0x0E);// + + //gain setting +if(imgsensor.update_sensor_otp_awb != 0){} +else { + write_cmos_sensor(0x0205,0x00);// + write_cmos_sensor(0x020E,0x01);// + write_cmos_sensor(0x020F,0x00);// + write_cmos_sensor(0x0210,0x01);// + write_cmos_sensor(0x0211,0x00);// + write_cmos_sensor(0x0212,0x01);// + write_cmos_sensor(0x0213,0x00);// + write_cmos_sensor(0x0214,0x01);// + write_cmos_sensor(0x0215,0x00);// +} +#if 0 + //hdr setting + write_cmos_sensor(0x0230,0x00);// + write_cmos_sensor(0x0231,0x00);// + write_cmos_sensor(0x0233,0x00);// + write_cmos_sensor(0x0234,0x00);// + write_cmos_sensor(0x0235,0x40);// + write_cmos_sensor(0x0236,0x00);// + write_cmos_sensor(0x0238,0x00);// + write_cmos_sensor(0x0239,0x04);// + write_cmos_sensor(0x023B,0x00);// + write_cmos_sensor(0x023C,0x00);// + write_cmos_sensor(0x33B0,0x04);// + write_cmos_sensor(0x33B1,0x00);// + write_cmos_sensor(0x33B3,0X00);// + write_cmos_sensor(0x33B4,0X01);// + write_cmos_sensor(0x3800,0X00);// +#endif + + write_cmos_sensor(0x3A43,0x01);// + write_cmos_sensor(0x0100,0x01);// STREAM START + +} + +static void slim_video_setting(void) // VideoHDSetting +{ + LOG_INF("E\n Video 120fps "); + //PLL setting + write_cmos_sensor(0x0100,0x00);// STREAM STop + + //PLL setting + write_cmos_sensor(0x011E,0x18);// + write_cmos_sensor(0x011F,0x00);// + write_cmos_sensor(0x0301,0x05);// + write_cmos_sensor(0x0303,0x01);// + write_cmos_sensor(0x0305,0x0C);// + write_cmos_sensor(0x0309,0x05);// + write_cmos_sensor(0x030B,0x01);// + write_cmos_sensor(0x030C,0x00);// + write_cmos_sensor(0x030D,0xE6);// + write_cmos_sensor(0x030E,0x01);// + write_cmos_sensor(0x3A06,0x11);// + + //Mode setting + mdelay(10); + write_cmos_sensor(0x0108,0x03);// + write_cmos_sensor(0x0112,0x0A);// + write_cmos_sensor(0x0113,0x0A);// + write_cmos_sensor(0x0381,0x01);// + write_cmos_sensor(0x0383,0x01);// + write_cmos_sensor(0x0385,0x01);// + write_cmos_sensor(0x0387,0x01);// + write_cmos_sensor(0x0390,0x01);// + write_cmos_sensor(0x0391,0x22);// + write_cmos_sensor(0x0392,0x00);// + write_cmos_sensor(0x0401,0x02);// + write_cmos_sensor(0x0404,0x00);// + write_cmos_sensor(0x0405,0x1A);// + write_cmos_sensor(0x4082,0x00);// + write_cmos_sensor(0x4083,0x00);// + write_cmos_sensor(0x7006,0x04);// +if(imgsensor.update_sensor_otp_lsc != 0){} +else { + //Optionnal function setting + write_cmos_sensor(0x0700,0x00);// + write_cmos_sensor(0x3A63,0x00);// +} + write_cmos_sensor(0x4100,0xF8);// + write_cmos_sensor(0x4203,0xFF);// + write_cmos_sensor(0x4344,0x00);// + write_cmos_sensor(0x441C,0x01);// + + //Size setting + write_cmos_sensor(0x0340,(imgsensor_info.slim_video.framelength>>8)&0xFF);// + write_cmos_sensor(0x0341,(imgsensor_info.slim_video.framelength>>0)&0xFF);// + write_cmos_sensor(0x0342,(imgsensor_info.slim_video.linelength>>8)&0xFF);// + write_cmos_sensor(0x0343,(imgsensor_info.slim_video.linelength>>0)&0xFF);// + write_cmos_sensor(0x0344,0x00);// + write_cmos_sensor(0x0345,0x18);// + write_cmos_sensor(0x0346,0x01);// + write_cmos_sensor(0x0347,0x88);// + write_cmos_sensor(0x0348,0x10);// + write_cmos_sensor(0x0349,0x57);// + write_cmos_sensor(0x034A,0x0A);// + write_cmos_sensor(0x034B,0xAB);// + write_cmos_sensor(0x034C,0x05);// + write_cmos_sensor(0x034D,0x00);// + write_cmos_sensor(0x034E,0x02);// + write_cmos_sensor(0x034F,0xD0);// + write_cmos_sensor(0x0350,0x00);// + write_cmos_sensor(0x0351,0x00);// + write_cmos_sensor(0x0352,0x00);// + write_cmos_sensor(0x0353,0x00);// + write_cmos_sensor(0x0354,0x08);// + write_cmos_sensor(0x0355,0x20);// + write_cmos_sensor(0x0356,0x04);// + write_cmos_sensor(0x0357,0x92);// + write_cmos_sensor(0x301D,0x30);// + write_cmos_sensor(0x3310,0x05);// + write_cmos_sensor(0x3311,0x00);// + write_cmos_sensor(0x3312,0x02);// + write_cmos_sensor(0x3313,0xD0);// + write_cmos_sensor(0x331C,0x03);// + write_cmos_sensor(0x331D,0xE8);// + write_cmos_sensor(0x4084,0x05);// + write_cmos_sensor(0x4085,0x00);// + write_cmos_sensor(0x4086,0x02);// + write_cmos_sensor(0x4087,0xD0);// + write_cmos_sensor(0x4400,0x00);// + + //global timing setting + write_cmos_sensor(0x0830,0x67);// + write_cmos_sensor(0x0831,0x27);// + write_cmos_sensor(0x0832,0x47);// + write_cmos_sensor(0x0833,0x27);// + write_cmos_sensor(0x0834,0x27);// + write_cmos_sensor(0x0835,0x1F);// + write_cmos_sensor(0x0836,0x87);// + write_cmos_sensor(0x0837,0x2F);// + write_cmos_sensor(0x0839,0x1F);// + write_cmos_sensor(0x083A,0x17);// + write_cmos_sensor(0x083B,0x02);// + + // integration time setting + write_cmos_sensor(0x0202,0x05);// + write_cmos_sensor(0x0203,0x1C);// +if(imgsensor.update_sensor_otp_awb != 0){} +else { + //gain setting + write_cmos_sensor(0x0205,0x00);// + write_cmos_sensor(0x020E,0x01);// + write_cmos_sensor(0x020F,0x00);// + write_cmos_sensor(0x0210,0x01);// + write_cmos_sensor(0x0211,0x00);// + write_cmos_sensor(0x0212,0x01);// + write_cmos_sensor(0x0213,0x00);// + write_cmos_sensor(0x0214,0x01);// + write_cmos_sensor(0x0215,0x00);// +} + //HDRSetting +#if 0 + //hdr setting + write_cmos_sensor(0x0230,0x00);// + write_cmos_sensor(0x0231,0x00);// + write_cmos_sensor(0x0233,0x00);// + write_cmos_sensor(0x0234,0x00);// + write_cmos_sensor(0x0235,0x40);// + write_cmos_sensor(0x0238,0x00);// + write_cmos_sensor(0x0239,0x04);// + write_cmos_sensor(0x023B,0x00);// + write_cmos_sensor(0x023C,0x01);// + write_cmos_sensor(0x33B0,0x04);// + write_cmos_sensor(0x33B1,0x00);// + write_cmos_sensor(0x33B3,0x00);// + write_cmos_sensor(0x33B4,0x01);// + write_cmos_sensor(0x3800,0x00);// +#endif + + write_cmos_sensor(0x3A43,0x01);// + write_cmos_sensor(0x0100,0x01);// STREAM START + +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x30D8, 0x10); + write_cmos_sensor(0x0600, 0x00); + write_cmos_sensor(0x0601, 0x02); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x30D8, 0x00); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { +#ifdef CONFIG_MTK_CAM_CAL + read_imx135_otp_mtk_fmt(); +#endif + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + return ERROR_NONE; + } + retry--; + } while(retry > 0); + LOG_INF("Read sensor id fail, write id:0x%x id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + LOG_2; + + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id:0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = KAL_FALSE; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ +#ifndef CONFIG_MTK_CAM_CAL + LOG_INF("E reset otp flag\n"); + otp_clear_flag();//clear otp flag +#endif + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + LOG_INF("L\n"); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == 300) { + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + }else if (imgsensor.current_fps == 150) { //317Mhz PIP capture: 15fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap2.pclk; + imgsensor.line_length = imgsensor_info.cap2.linelength; + imgsensor.frame_length = imgsensor_info.cap2.framelength; + imgsensor.min_frame_length = imgsensor_info.cap2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + }else { //400Mhz PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + LOG_INF("Caputre fps:%d\n",imgsensor.current_fps); + if(imgsensor.current_fps == 150) + capture_setting_15fps(imgsensor.current_fps); + else + capture_setting(imgsensor.current_fps); + + LOG_INF("L\n"); + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); +#ifdef IHDR_USED + if(imgsensor.ihdr_en) + IMX135MIPI_set_Video_IHDR(1); + else + IMX135MIPI_set_Video_IHDR(0); +#else + normal_video_setting(imgsensor.current_fps); +#endif + + LOG_INF("L\n"); + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + //hs_video_setting_vga_120fps(); + LOG_INF("L\n"); + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + LOG_INF("L\n"); + return ERROR_NONE; +} /* slim_video */ + +/************************************************************************* +* FUNCTION +* Custom1 +* +* DESCRIPTION +* This function start the sensor Custom1. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 Custom1(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM1; + imgsensor.pclk = imgsensor_info.custom1.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom1.linelength; + imgsensor.frame_length = imgsensor_info.custom1.framelength; + imgsensor.min_frame_length = imgsensor_info.custom1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom1 */ + +static kal_uint32 Custom2(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM2; + imgsensor.pclk = imgsensor_info.custom2.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom2.linelength; + imgsensor.frame_length = imgsensor_info.custom2.framelength; + imgsensor.min_frame_length = imgsensor_info.custom2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom2 */ + +static kal_uint32 Custom3(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM3; + imgsensor.pclk = imgsensor_info.custom3.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom3.linelength; + imgsensor.frame_length = imgsensor_info.custom3.framelength; + imgsensor.min_frame_length = imgsensor_info.custom3.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom3 */ + +static kal_uint32 Custom4(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM4; + imgsensor.pclk = imgsensor_info.custom4.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom4.linelength; + imgsensor.frame_length = imgsensor_info.custom4.framelength; + imgsensor.min_frame_length = imgsensor_info.custom4.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom4 */ + + +static kal_uint32 Custom5(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM5; + imgsensor.pclk = imgsensor_info.custom5.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom5.linelength; + imgsensor.frame_length = imgsensor_info.custom5.framelength; + imgsensor.min_frame_length = imgsensor_info.custom5.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom5 */ + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + /*LOG_INF("E\n");*/ + + LOG_INF("imgsensor_info.cap.grabwindow_width: %d\n", imgsensor_info.cap.grabwindow_width); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + + sensor_resolution->SensorCustom1Width = imgsensor_info.custom1.grabwindow_width; + sensor_resolution->SensorCustom1Height = imgsensor_info.custom1.grabwindow_height; + + sensor_resolution->SensorCustom2Width = imgsensor_info.custom2.grabwindow_width; + sensor_resolution->SensorCustom2Height = imgsensor_info.custom2.grabwindow_height; + + sensor_resolution->SensorCustom3Width = imgsensor_info.custom3.grabwindow_width; + sensor_resolution->SensorCustom3Height = imgsensor_info.custom3.grabwindow_height; + + sensor_resolution->SensorCustom4Width = imgsensor_info.custom4.grabwindow_width; + sensor_resolution->SensorCustom4Height = imgsensor_info.custom4.grabwindow_height; + + sensor_resolution->SensorCustom5Width = imgsensor_info.custom5.grabwindow_width; + sensor_resolution->SensorCustom5Height = imgsensor_info.custom5.grabwindow_height; + + /*LOG_INF("L\n");*/ + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + if(scenario_id == 0) + LOG_INF("scenario_id = %d\n", scenario_id); + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 1; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + sensor_info->Custom1DelayFrame = imgsensor_info.custom1_delay_frame; + sensor_info->Custom2DelayFrame = imgsensor_info.custom2_delay_frame; + sensor_info->Custom3DelayFrame = imgsensor_info.custom3_delay_frame; + sensor_info->Custom4DelayFrame = imgsensor_info.custom4_delay_frame; + sensor_info->Custom5DelayFrame = imgsensor_info.custom5_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 5; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + sensor_info->PerFrameCTL_Support = 1; + sensor_info->SensorHorFOV = 62; + sensor_info->SensorVerFOV = 49; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[0]; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[1]; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[2]; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[3]; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[4]; + break; + case MSDK_SCENARIO_ID_CUSTOM1: + sensor_info->SensorGrabStartX = imgsensor_info.custom1.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom1.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[5]; + break; + case MSDK_SCENARIO_ID_CUSTOM2: + sensor_info->SensorGrabStartX = imgsensor_info.custom2.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom2.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[6]; + break; + case MSDK_SCENARIO_ID_CUSTOM3: + sensor_info->SensorGrabStartX = imgsensor_info.custom3.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom3.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[7]; + break; + case MSDK_SCENARIO_ID_CUSTOM4: + sensor_info->SensorGrabStartX = imgsensor_info.custom4.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom4.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[8]; + break; + case MSDK_SCENARIO_ID_CUSTOM5: + sensor_info->SensorGrabStartX = imgsensor_info.custom5.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom5.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[9]; + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + sensor_info->DPCM_INFO = imgsensor_dpcm_info[0]; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); // VideoFullSizeSetting + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); // VideoHDSetting_120fps + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); // VideoHDSetting + break; + case MSDK_SCENARIO_ID_CUSTOM1: + Custom1(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM2: + Custom2(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM3: + Custom3(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM4: + Custom4(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM5: + Custom5(image_window, sensor_config_data); // Custom1 + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + set_dummy(); + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == 300){ + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + else if (imgsensor.current_fps == 150) { //317Mhz, PIP capture: 15fps for less than 13M, 20fps for 16M,15fps for 20M + frame_length = imgsensor_info.cap2.pclk / framerate * 10 / imgsensor_info.cap2.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap2.framelength) ? (frame_length - imgsensor_info.cap2.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap2.framelength + imgsensor.dummy_line; + spin_unlock(&imgsensor_drv_lock); + } + else{ + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + spin_unlock(&imgsensor_drv_lock); + } + //set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM1: + frame_length = imgsensor_info.custom1.pclk / framerate * 10 / imgsensor_info.custom1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom1.framelength) ? (frame_length - imgsensor_info.custom1.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM2: + frame_length = imgsensor_info.custom2.pclk / framerate * 10 / imgsensor_info.custom2.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom2.framelength) ? (frame_length - imgsensor_info.custom2.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM3: + frame_length = imgsensor_info.custom3.pclk / framerate * 10 / imgsensor_info.custom3.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom3.framelength) ? (frame_length - imgsensor_info.custom3.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom3.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM4: + frame_length = imgsensor_info.custom4.pclk / framerate * 10 / imgsensor_info.custom4.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom4.framelength) ? (frame_length - imgsensor_info.custom4.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom4.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM5: + frame_length = imgsensor_info.custom5.pclk / framerate * 10 / imgsensor_info.custom5.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom5.framelength) ? (frame_length - imgsensor_info.custom5.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + /*LOG_INF("scenario_id = %d\n", scenario_id);*/ + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM1: + *framerate = imgsensor_info.custom1.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM2: + *framerate = imgsensor_info.custom2.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM3: + *framerate = imgsensor_info.custom3.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM4: + *framerate = imgsensor_info.custom4.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM5: + *framerate = imgsensor_info.custom5.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + //unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + LOG_INF("feature_Control imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_SENSOR_OTP_AWB_CMD: + LOG_INF("Update sensor awb from otp :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.update_sensor_otp_awb = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); +#ifndef CONFIG_MTK_CAM_CAL + if(0 != imgsensor.update_sensor_otp_awb || 0 != imgsensor.update_sensor_otp_lsc) { + otp_update(imgsensor.update_sensor_otp_awb, imgsensor.update_sensor_otp_lsc); + } +#endif + break; + case SENSOR_FEATURE_SET_SENSOR_OTP_LSC_CMD: + LOG_INF("Update sensor lsc from otp :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.update_sensor_otp_lsc = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); +#ifndef CONFIG_MTK_CAM_CAL + if(0 != imgsensor.update_sensor_otp_awb || 0 != imgsensor.update_sensor_otp_lsc) { + otp_update(imgsensor.update_sensor_otp_awb, imgsensor.update_sensor_otp_lsc); + } +#endif + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + //LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + case SENSOR_FEATURE_SET_HDR_SHUTTER: + LOG_INF("SENSOR_FEATURE_SET_HDR_SHUTTER LE=%d, SE=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1)); + ihdr_write_shutter((UINT16)*feature_data,(UINT16)*(feature_data+1)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 IMX135_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* IMX135_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135mipiraw_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..e14d000bad0e48b81c630a9b838161627c0eb9d8 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx135_mipi_raw/imx135mipiraw_Sensor.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * IMX135mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _IMX135mipi_SENSOR_H +#define _IMX135mipi_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, + IMGSENSOR_MODE_CUSTOM1, + IMGSENSOR_MODE_CUSTOM2, + IMGSENSOR_MODE_CUSTOM3, + IMGSENSOR_MODE_CUSTOM4, + IMGSENSOR_MODE_CUSTOM5, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id + kal_uint8 update_sensor_otp_awb; // Update sensor awb from otp or not + kal_uint8 update_sensor_otp_lsc; // Update sensor lsc from otp or not +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint32 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information + imgsensor_mode_struct cap2; //capture for PIP 15fps relative information + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + imgsensor_mode_struct custom1; //custom1 scenario relative information + imgsensor_mode_struct custom2; //custom2 scenario relative information + imgsensor_mode_struct custom3; //custom3 scenario relative information + imgsensor_mode_struct custom4; //custom4 scenario relative information + imgsensor_mode_struct custom5; //custom5 scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + kal_uint8 custom1_delay_frame; //enter custom1 delay frame num + kal_uint8 custom2_delay_frame; //enter custom1 delay frame num + kal_uint8 custom3_delay_frame; //enter custom1 delay frame num + kal_uint8 custom4_delay_frame; //enter custom1 delay frame num + kal_uint8 custom5_delay_frame; //enter custom1 delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat; + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff + kal_uint32 i2c_speed; //i2c speed +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); + + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2e20e8330cc2640d0c9ee97234e6a74ddb1efba8 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +#obj-y += imx214otp.o +obj-y += imx214mipiraw_Sensor.o + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214mipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214mipiraw_Sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..dbd5770a2c732e7c0bb985d013a06ba5a4b4a0a4 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214mipiraw_Sensor.c @@ -0,0 +1,2747 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * IMX214mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "imx214mipiraw_Sensor.h" + +#define PFX "IMX214_camera_sensor" +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +static DEFINE_SPINLOCK(imgsensor_drv_lock); +/*LukeHu--150812 +#define OTP_SIZE 452 +u8 OTPData[OTP_SIZE]; +extern int iReadData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char * pinputdata); +*/ + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = IMX214_SENSOR_ID, + + .checksum_value =0xc15d2913, + + .pre = { + .pclk = 320000000, //record different mode's pclk + .linelength = 5008, //record different mode's linelength + .framelength = 2110, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2104, //record different mode's width of grabwindow + .grabwindow_height = 1560, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk =480000000, + .linelength = 5008, + .framelength = 3160, + .startx =0, + .starty = 0, + .grabwindow_width = 4208, + .grabwindow_height = 3120, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 300, + }, + .cap1 = { + .pclk =387200000, + .linelength = 5008, + .framelength = 3220, + .startx = 0, + .starty =0, + .grabwindow_width = 4208, + .grabwindow_height = 3120, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 240, + }, + .cap2 = { + .pclk =243200000, + .linelength = 5008, + .framelength = 3220, + .startx = 0, + .starty =0, + .grabwindow_width = 4208, + .grabwindow_height = 3120, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 150, + }, + .normal_video = { + .pclk = 480000000, + .linelength = 5008, + .framelength = 3160, + .startx = 0, + .starty = 0, + .grabwindow_width = 4208, + .grabwindow_height = 3120, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 300, + }, + .hs_video = { + .pclk = 387200000, + .linelength = 5008, + .framelength =1288, + .startx = 0, + .starty = 0, + .grabwindow_width = 2104, + .grabwindow_height = 1184, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 600, + }, + .slim_video = { + .pclk =387200000, + .linelength = 5008, + .framelength = 1288, + .startx = 0, + .starty =0, + .grabwindow_width = 2104, + .grabwindow_height = 1184, + .mipi_data_lp2hs_settle_dc =85, + .max_framerate = 600, + }, + .margin = 10, + .min_shutter = 1, + .max_frame_length = 0xffff, + .ae_shut_delay_frame = 0, + .ae_sensor_gain_delay_frame =1, + .ae_ispGain_delay_frame = 2, + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num + + .cap_delay_frame = 3, + .pre_delay_frame = 3, + .video_delay_frame = 3, + .hs_video_delay_frame = 3, + .slim_video_delay_frame = 3, + + .isp_driving_current = ISP_DRIVING_2MA, + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI, + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO, //0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B, + .mclk = 24, + .mipi_lane_num = SENSOR_MIPI_4_LANE, + .i2c_addr_table = {0x34,0x20,0xff}, +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter + .gain = 0x100, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_mode = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x34, +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{{ 4208, 3120, 0, 0, 4208, 3120, 2104, 1560, 0000, 0000, 2104, 1560, 0, 0, 2104, 1560}, // Preview + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0000, 0000, 4208, 3120, 0, 0, 4208, 3120}, // capture + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0000, 0000, 4208, 3120, 0, 0, 4208, 3120}, // video + { 4208, 3120, 0, 0, 4208, 3120, 2104, 1560, 0000, 376, 2104, 1184, 0, 0, 2104, 1184}, //hight speed video + { 4208, 3120, 0, 0, 4208, 3120, 2104, 1560, 0000, 376, 2104, 1184, 0, 0, 2104, 1184}};// slim video + +SENSOR_VC_INFO_STRUCT SENSOR_VC_INFO[3]= +{/* Preview mode setting */ + {0x02, 0x0a, 0x01, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x0838, 0x0618, 0x01, 0x35, 0x0200, 0x0001, + 0x02, 0x00, 0x0000, 0x0000, 0x03, 0x00, 0x0000, 0x0000}, + /* Video mode setting */ + {0x02, 0x0a, 0x01, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x1070, 0x0c30, 0x01, 0x35, 0x0200, 0x0001, + 0x02, 0x00, 0x0000, 0x0000, 0x03, 0x00, 0x0000, 0x0000}, + /* Capture mode setting */ + {0x02, 0x0a, 0x01, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x1070, 0x0c30, 0x01, 0x35, 0x0200, 0x0001, + 0x02, 0x00, 0x0000, 0x0000, 0x03, 0x00, 0x0000, 0x0000}}; + +typedef struct +{ + MUINT16 DarkLimit_H; + MUINT16 DarkLimit_L; + MUINT16 OverExp_Min_H; + MUINT16 OverExp_Min_L; + MUINT16 OverExp_Max_H; + MUINT16 OverExp_Max_L; +}SENSOR_ATR_INFO, *pSENSOR_ATR_INFO; + +SENSOR_ATR_INFO sensorATR_Info[4]= +{/* Strength Range Min */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + /* Strength Range Std */ + {0x00, 0x32, 0x00, 0x3c, 0x03, 0xff}, + /* Strength Range Max */ + {0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xff}, + /* Strength Range Custom */ + {0x3F, 0xFF, 0x00, 0x0, 0x3F, 0xFF}}; + +#define MIPI_MaxGainIndex 159 + +static kal_uint16 sensorGainMapping[MIPI_MaxGainIndex][2] = { + + {64 , 1 }, + {65 , 8 }, + {66 , 13 }, + {67 , 23 }, + {68 , 27 }, + {69 , 36 }, + {70 , 41 }, + {71 , 49 }, + {72 , 53 }, + {73 , 61 }, + {74 , 69 }, + {75 , 73 }, + {76 , 80 }, + {77 , 88 }, + {78 , 91 }, + {79 , 98 }, + {80 , 101}, + {81 , 108}, + {82 , 111}, + {83 , 117}, + {84 , 120}, + {85 , 126}, + {86 , 132}, + {87 , 135}, + {88 , 140}, + {89 , 143}, + {90 , 148}, + {91 , 151}, + {92 , 156}, + {93 , 161}, + {94 , 163}, + {95 , 168}, + {96 , 170}, + {97 , 175}, + {98 , 177}, + {99 , 181}, + {100, 185}, + {101, 187}, + {102, 191}, + {103, 193}, + {104, 197}, + {105, 199}, + {106, 203}, + {107, 205}, + {108, 207}, + {109, 212}, + {110, 214}, + {111, 217}, + {112, 219}, + {113, 222}, + {114, 224}, + {115, 227}, + {116, 230}, + {117, 232}, + {118, 234}, + {119, 236}, + {120, 239}, + {122, 244}, + {123, 245}, + {124, 248}, + {125, 249}, + {126, 252}, + {127, 253}, + {128, 256}, + {129, 258}, + {130, 260}, + {131, 262}, + {132, 263}, + {133, 266}, + {134, 268}, + {136, 272}, + {138, 274}, + {139, 276}, + {140, 278}, + {141, 280}, + {143, 282}, + {144, 284}, + {145, 286}, + {147, 288}, + {148, 290}, + {149, 292}, + {150, 294}, + {152, 296}, + {153, 298}, + {155, 300}, + {156, 302}, + {157, 304}, + {159, 306}, + {161, 308}, + {162, 310}, + {164, 312}, + {166, 314}, + {167, 316}, + {169, 318}, + {171, 320}, + {172, 322}, + {174, 324}, + {176, 326}, + {178, 328}, + {180, 330}, + {182, 332}, + {184, 334}, + {186, 336}, + {188, 338}, + {191, 340}, + {193, 342}, + {195, 344}, + {197, 346}, + {200, 348}, + {202, 350}, + {205, 352}, + {207, 354}, + {210, 356}, + {212, 358}, + {216, 360}, + {218, 362}, + {221, 364}, + {225, 366}, + {228, 368}, + {231, 370}, + {234, 372}, + {237, 374}, + {241, 376}, + {244, 378}, + {248, 380}, + {252, 382}, + {256, 384}, + {260, 386}, + {264, 388}, + {269, 390}, + {273, 392}, + {278, 394}, + {282, 396}, + {287, 398}, + {292, 400}, + {298, 402}, + {303, 404}, + {309, 406}, + {315, 408}, + {321, 410}, + {328, 412}, + {334, 414}, + {341, 416}, + {349, 418}, + {356, 420}, + {364, 422}, + {372, 424}, + {381, 426}, + {390, 428}, + {399, 430}, + {410, 432}, + {420, 434}, + {431, 436}, + {443, 438}, + {455, 440}, + {468, 442}, + {482, 444}, + {497, 446}, + {512, 448} +}; + +extern int iReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + iReadReg((u16) addr ,(u8*)&get_byte, imgsensor.i2c_write_id); + return get_byte; +} + +#define write_cmos_sensor(addr, para) iWriteReg((u16) addr , (u32) para , 1, imgsensor.i2c_write_id) + +static kal_uint32 imx214_ATR(UINT16 DarkLimit, UINT16 OverExp) +{ + write_cmos_sensor(0x6e50,sensorATR_Info[DarkLimit].DarkLimit_H); + write_cmos_sensor(0x6e51,sensorATR_Info[DarkLimit].DarkLimit_L); + write_cmos_sensor(0x9340,sensorATR_Info[OverExp].OverExp_Min_H); + write_cmos_sensor(0x9341,sensorATR_Info[OverExp].OverExp_Min_L); + write_cmos_sensor(0x9342,sensorATR_Info[OverExp].OverExp_Max_H); + write_cmos_sensor(0x9343,sensorATR_Info[OverExp].OverExp_Max_L); + write_cmos_sensor(0x9706,0x10); + write_cmos_sensor(0x9707,0x03); + write_cmos_sensor(0x9708,0x03); + write_cmos_sensor(0x9e24,0x00); + write_cmos_sensor(0x9e25,0x8c); + write_cmos_sensor(0x9e26,0x00); + write_cmos_sensor(0x9e27,0x94); + write_cmos_sensor(0x9e28,0x00); + write_cmos_sensor(0x9e29,0x96); + LOG_INF("DarkLimit 0x6e50(0x%x), 0x6e51(0x%x)\n",sensorATR_Info[DarkLimit].DarkLimit_H, + sensorATR_Info[DarkLimit].DarkLimit_L); + LOG_INF("OverExpMin 0x9340(0x%x), 0x9341(0x%x)\n",sensorATR_Info[OverExp].OverExp_Min_H, + sensorATR_Info[OverExp].OverExp_Min_L); + LOG_INF("OverExpMin 0x9342(0x%x), 0x9343(0x%x)\n",sensorATR_Info[OverExp].OverExp_Max_H, + sensorATR_Info[OverExp].OverExp_Max_L); + return ERROR_NONE; +} +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + write_cmos_sensor(0x0104, 1); + + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0342, imgsensor.line_length >> 8); + write_cmos_sensor(0x0343, imgsensor.line_length & 0xFF); + + write_cmos_sensor(0x0104, 0); + +} /* set_dummy */ + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable = %d\n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + if (frame_length >= imgsensor.min_frame_length) + imgsensor.frame_length = frame_length; + else + imgsensor.frame_length = imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + + +static void write_shutter(kal_uint16 shutter) +{ + kal_uint16 realtime_fps = 0; + + + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (shutter < imgsensor_info.min_shutter) shutter = imgsensor_info.min_shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x0104, 1); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0); + } + } else { + // Extend frame length + write_cmos_sensor(0x0104, 1); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0); + } + + // Update Shutter + write_cmos_sensor(0x0104, 1); + write_cmos_sensor(0x0202, (shutter >> 8) & 0xFF); + write_cmos_sensor(0x0203, shutter & 0xFF); + write_cmos_sensor(0x0104, 0); + + LOG_INF("shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + + //LOG_INF("frame_length = %d ", frame_length); + +} /* write_shutter */ + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + write_shutter(shutter); +} /* set_shutter */ + + + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint8 iI; + + for (iI = 0; iI < (MIPI_MaxGainIndex-1); iI++) { + if(gain <= sensorGainMapping[iI][0]){ + break; + } + } + + return sensorGainMapping[iI][1]; +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + if (gain < BASEGAIN || gain > 32 * BASEGAIN) { + LOG_INF("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 32 * BASEGAIN) + gain = 32 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor(0x0104, 1); + /* Global analog Gain for Long expo*/ + write_cmos_sensor(0x0204, (reg_gain>>8)& 0xFF); + write_cmos_sensor(0x0205, reg_gain & 0xFF); + /* Global analog Gain for Short expo*/ + write_cmos_sensor(0x0216, (reg_gain>>8)& 0xFF); + write_cmos_sensor(0x0217, reg_gain & 0xFF); + write_cmos_sensor(0x0104, 0); + + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + kal_uint16 realtime_fps = 0; + + kal_uint16 reg_gain; + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + write_cmos_sensor(0x0104, 1); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0); + } + } else { + write_cmos_sensor(0x0104, 1); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0); + } + write_cmos_sensor(0x0104, 1); + /* Long exposure */ + write_cmos_sensor(0x0202, (le >> 8) & 0xFF); + write_cmos_sensor(0x0203, le & 0xFF); + /* Short exposure */ + write_cmos_sensor(0x0224, (se >> 8) & 0xFF); + write_cmos_sensor(0x0225, se & 0xFF); + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + /* Global analog Gain for Long expo*/ + write_cmos_sensor(0x0204, (reg_gain>>8)& 0xFF); + write_cmos_sensor(0x0205, reg_gain & 0xFF); + /* Global analog Gain for Short expo*/ + write_cmos_sensor(0x0216, (reg_gain>>8)& 0xFF); + write_cmos_sensor(0x0217, reg_gain & 0xFF); + write_cmos_sensor(0x0104, 0); + +} + +static void ihdr_write_shutter(kal_uint16 le, kal_uint16 se) +{ + + kal_uint16 realtime_fps = 0; + LOG_INF("le:0x%x, se:0x%x\n",le,se); + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + write_cmos_sensor(0x0104, 1); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0); + } + } else { + write_cmos_sensor(0x0104, 1); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0); + } + write_cmos_sensor(0x0104, 1); + /* Long exposure */ + write_cmos_sensor(0x0202, (le >> 8) & 0xFF); + write_cmos_sensor(0x0203, le & 0xFF); + /* Short exposure */ + write_cmos_sensor(0x0224, (se >> 8) & 0xFF); + write_cmos_sensor(0x0225, se & 0xFF); + + write_cmos_sensor(0x0104, 0); + +} + + +#if 0 +static void set_mirror_flip(kal_uint8 image_mirror) +{ + + kal_uint8 itemp; + LOG_INF("image_mirror = %d\n", image_mirror); + itemp=read_cmos_sensor(0x0101); + itemp &= ~0x03; + + switch(image_mirror) + { + + case IMAGE_NORMAL: + write_cmos_sensor(0x0101, itemp); + break; + + case IMAGE_V_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x02); + break; + + case IMAGE_H_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x01); + break; + + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x03); + break; + } +} +#endif +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + +static void sensor_init(void) +{ + LOG_INF("E\n"); + //init setting + write_cmos_sensor(0x0136,0x18); + write_cmos_sensor(0x0137,0x00); + + write_cmos_sensor(0x0101,0x00); + write_cmos_sensor(0x0105,0x01); + write_cmos_sensor(0x0106,0x01); + write_cmos_sensor(0x4550,0x02); + write_cmos_sensor(0x4601,0x00); + write_cmos_sensor(0x4642,0x05); + write_cmos_sensor(0x6276,0x00); + write_cmos_sensor(0x900E,0x06); + write_cmos_sensor(0xA802,0x90); + write_cmos_sensor(0xA803,0x11); + write_cmos_sensor(0xA804,0x62); + write_cmos_sensor(0xA805,0x77); + write_cmos_sensor(0xA806,0xAE); + write_cmos_sensor(0xA807,0x34); + write_cmos_sensor(0xA808,0xAE); + write_cmos_sensor(0xA809,0x35); + write_cmos_sensor(0xA80A,0x62); + write_cmos_sensor(0xA80B,0x83); + write_cmos_sensor(0xAE33,0x00); + + write_cmos_sensor(0x4174,0x00); + write_cmos_sensor(0x4175,0x11); + write_cmos_sensor(0x4612,0x29); + write_cmos_sensor(0x461B,0x12); + write_cmos_sensor(0x461F,0x06); + write_cmos_sensor(0x4635,0x07); + write_cmos_sensor(0x4637,0x30); + write_cmos_sensor(0x463F,0x18); + write_cmos_sensor(0x4641,0x0D); + write_cmos_sensor(0x465B,0x12); + write_cmos_sensor(0x465F,0x11); + write_cmos_sensor(0x4663,0x11); + write_cmos_sensor(0x4667,0x0F); + write_cmos_sensor(0x466F,0x0F); + write_cmos_sensor(0x470E,0x09); + write_cmos_sensor(0x4909,0xAB); + write_cmos_sensor(0x490B,0x95); + write_cmos_sensor(0x4915,0x5D); + write_cmos_sensor(0x4A5F,0xFF); + write_cmos_sensor(0x4A61,0xFF); + write_cmos_sensor(0x4A73,0x62); + write_cmos_sensor(0x4A85,0x00); + write_cmos_sensor(0x4A87,0xFF); + write_cmos_sensor(0x583C,0x04); + write_cmos_sensor(0x620E,0x04); + write_cmos_sensor(0x6EB2,0x01); + write_cmos_sensor(0x6EB3,0x00); + write_cmos_sensor(0x9300,0x02); + + write_cmos_sensor(0x3001,0x07); + write_cmos_sensor(0x6D12,0x3F); + write_cmos_sensor(0x6D13,0xFF); + write_cmos_sensor(0x9344,0x03); + write_cmos_sensor(0x9706,0x10); + write_cmos_sensor(0x9707,0x03); + write_cmos_sensor(0x9708,0x03); + write_cmos_sensor(0x9E04,0x01); + write_cmos_sensor(0x9E05,0x00); + write_cmos_sensor(0x9E0C,0x01); + write_cmos_sensor(0x9E0D,0x02); + write_cmos_sensor(0x9E24,0x00); + write_cmos_sensor(0x9E25,0x8C); + write_cmos_sensor(0x9E26,0x00); + write_cmos_sensor(0x9E27,0x94); + write_cmos_sensor(0x9E28,0x00); + write_cmos_sensor(0x9E29,0x96); + //write_cmos_sensor(0x5041,0x00);//no embedded data + + write_cmos_sensor(0x69DB,0x01); + write_cmos_sensor(0x6957,0x01); + write_cmos_sensor(0x6987,0x17); + write_cmos_sensor(0x698A,0x03); + write_cmos_sensor(0x698B,0x03); + write_cmos_sensor(0x0B8E,0x01); + write_cmos_sensor(0x0B8F,0x00); + write_cmos_sensor(0x0B90,0x01); + write_cmos_sensor(0x0B91,0x00); + write_cmos_sensor(0x0B92,0x01); + write_cmos_sensor(0x0B93,0x00); + write_cmos_sensor(0x0B94,0x01); + write_cmos_sensor(0x0B95,0x00); + write_cmos_sensor(0x6E50,0x00); + write_cmos_sensor(0x6E51,0x32); + write_cmos_sensor(0x9340,0x00); + write_cmos_sensor(0x9341,0x3C); + write_cmos_sensor(0x9342,0x03); + write_cmos_sensor(0x9343,0xFF); + write_cmos_sensor(0x0101,0x03); +} /* sensor_init */ + + +static void preview_setting(void) +{ + //Preview 2104*1560 30fps 24M MCLK 4lane 608Mbps/lane + // preview 30.01fps + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x0114,0x03); + write_cmos_sensor(0x0220,0x00); + write_cmos_sensor(0x0221,0x11); + write_cmos_sensor(0x0222,0x01); + write_cmos_sensor(0x0340,0x08); + write_cmos_sensor(0x0341,0x3E); + write_cmos_sensor(0x0342,0x13); + write_cmos_sensor(0x0343,0x90); + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x01); + write_cmos_sensor(0x0901,0x22); + write_cmos_sensor(0x0902,0x02); + write_cmos_sensor(0x3000,0x35); + write_cmos_sensor(0x3054,0x01); + write_cmos_sensor(0x305C,0x11); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x034C,0x08); + write_cmos_sensor(0x034D,0x38); + write_cmos_sensor(0x034E,0x06); + write_cmos_sensor(0x034F,0x18); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x08); + write_cmos_sensor(0x040D,0x38); + write_cmos_sensor(0x040E,0x06); + write_cmos_sensor(0x040F,0x18); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x03); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x64); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x0310,0x00); + + write_cmos_sensor(0x0820,0x0C); + write_cmos_sensor(0x0821,0x80); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x3A03,0x06); + write_cmos_sensor(0x3A04,0x68); + write_cmos_sensor(0x3A05,0x01); + + write_cmos_sensor(0x0B06,0x01); + write_cmos_sensor(0x30A2,0x00); + + write_cmos_sensor(0x30B4,0x00); + + write_cmos_sensor(0x3A02,0xFF); + + write_cmos_sensor(0x3011,0x00); + write_cmos_sensor(0x3013,0x00); + + write_cmos_sensor(0x0202,0x08); + write_cmos_sensor(0x0203,0x34); + write_cmos_sensor(0x0224,0x01); + write_cmos_sensor(0x0225,0xF4); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x0216,0x00); + write_cmos_sensor(0x0217,0x00); + + write_cmos_sensor(0x4170,0x00); + write_cmos_sensor(0x4171,0x10); + write_cmos_sensor(0x4176,0x00); + write_cmos_sensor(0x4177,0x3C); + write_cmos_sensor(0xAE20,0x04); + write_cmos_sensor(0xAE21,0x5C); + + write_cmos_sensor(0x0138,0x01); + write_cmos_sensor(0x0100,0x01); +} /* preview_setting */ + +static void preview_setting_HDR(void) +{ + LOG_INF("preview_setting_mHDR\n"); + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x0114,0x03); + write_cmos_sensor(0x0220,0x21); + write_cmos_sensor(0x0221,0x22); + write_cmos_sensor(0x0222,0x08); + write_cmos_sensor(0x0340,0x08); + write_cmos_sensor(0x0341,0x3E); + write_cmos_sensor(0x0342,0x13); + write_cmos_sensor(0x0343,0x90); + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x00); + write_cmos_sensor(0x0902,0x00); + write_cmos_sensor(0x3000,0x35); + write_cmos_sensor(0x3054,0x01); + write_cmos_sensor(0x305C,0x11); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x034C,0x08); + write_cmos_sensor(0x034D,0x38); + write_cmos_sensor(0x034E,0x06); + write_cmos_sensor(0x034F,0x18); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x08); + write_cmos_sensor(0x040D,0x38); + write_cmos_sensor(0x040E,0x06); + write_cmos_sensor(0x040F,0x18); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x03); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x64); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x0310,0x00); + + write_cmos_sensor(0x0820,0x0C); + write_cmos_sensor(0x0821,0x80); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x3A03,0x06); + write_cmos_sensor(0x3A04,0xE8); + write_cmos_sensor(0x3A05,0x01); + + write_cmos_sensor(0x0B06,0x01); + write_cmos_sensor(0x30A2,0x00); + + write_cmos_sensor(0x30B4,0x00); + + write_cmos_sensor(0x3A02,0x06); + + write_cmos_sensor(0x3011,0x00); + write_cmos_sensor(0x3013,0x01); + + write_cmos_sensor(0x0202,0x08); + write_cmos_sensor(0x0203,0x34); + write_cmos_sensor(0x0224,0x01); + write_cmos_sensor(0x0225,0x06); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x0216,0x00); + write_cmos_sensor(0x0217,0x00); + + write_cmos_sensor(0x4170,0x00); + write_cmos_sensor(0x4171,0x10); + write_cmos_sensor(0x4176,0x00); + write_cmos_sensor(0x4177,0x3C); + write_cmos_sensor(0xAE20,0x04); + write_cmos_sensor(0xAE21,0x5C); + //mHDR relation setting + write_cmos_sensor(0x3010,0x00); + write_cmos_sensor(0x6D3A,0x00); // 0: 16X16, 1:8X8 + write_cmos_sensor(0x3011,0x00); + write_cmos_sensor(0x3013,0x01); // STATS output Enable + write_cmos_sensor(0x5068,0x35); + write_cmos_sensor(0x5069,0x01); + write_cmos_sensor(0x30C2,0x00); + write_cmos_sensor(0x30C3,0x40); + write_cmos_sensor(0x610A,0x08); + //[0]:1 hdr enable, [1]:0 LE/SE use same gain, 1 LE/SE separate gain + //[5]:0 auto, 1:direct + write_cmos_sensor(0x0220,0x21); + // hdr binning mode + write_cmos_sensor(0x0221,0x22); + //LE/SE ration 1,2,4,8 + write_cmos_sensor(0x0222,0x08); + //ATR + imx214_ATR(3,3); +#if 0 + /* + * FAE PROVIDIE + */ + write_cmos_sensor(0x9313,0x40); + write_cmos_sensor(0x9318,0x0C); + write_cmos_sensor(0x9319,0x00); + write_cmos_sensor(0x9344,0x00); + write_cmos_sensor(0x9348,0x01); + write_cmos_sensor(0x9349,0xC2); + write_cmos_sensor(0x934A,0x2); + write_cmos_sensor(0x934B,0xE4); + write_cmos_sensor(0x934E,0x0); + + /* + * DIFF for RATIO:1 & 8 + */ + //write_cmos_sensor(0x934F,0x47); // RATIO: 1 + write_cmos_sensor(0x934F,0xC7); // RATIO: 8 + + write_cmos_sensor(0x9354,0x01); + write_cmos_sensor(0x9355,0x80); + write_cmos_sensor(0x9356,0x2); + write_cmos_sensor(0x9357,0x1C); + + // General + write_cmos_sensor(0x6939,0x3); + write_cmos_sensor(0x693b,0x3); + write_cmos_sensor(0x4550,0x2); + write_cmos_sensor(0x6227,0x11); +#endif + /* + * END OF FAE PROVIDIE + */ + // Normal: 0x00, ZigZag: 0x01 + if(imgsensor.ihdr_mode == 9) + { + write_cmos_sensor(0x30b2,0x01); + write_cmos_sensor(0x30b3,0x01); + write_cmos_sensor(0x30b4,0x01); + write_cmos_sensor(0x30b5,0x01); + write_cmos_sensor(0x30b6,0x01); + write_cmos_sensor(0x30b7,0x01); + write_cmos_sensor(0x30b8,0x01); + write_cmos_sensor(0x30b9,0x01); + write_cmos_sensor(0x30ba,0x01); + write_cmos_sensor(0x30bb,0x01); + write_cmos_sensor(0x30bc,0x01); + } + else + { + write_cmos_sensor(0x30b2,0x00); + write_cmos_sensor(0x30b3,0x00); + write_cmos_sensor(0x30b4,0x00); + write_cmos_sensor(0x30b5,0x00); + write_cmos_sensor(0x30b6,0x00); + write_cmos_sensor(0x30b7,0x00); + write_cmos_sensor(0x30b8,0x00); + write_cmos_sensor(0x30b9,0x00); + write_cmos_sensor(0x30ba,0x00); + write_cmos_sensor(0x30bb,0x00); + write_cmos_sensor(0x30bc,0x00); + } + + write_cmos_sensor(0x0138,0x01); + write_cmos_sensor(0x0100,0x01); + LOG_INF("preview_setting_mHDR mode 0x0220(0x21), Ratio 0x0222(0x08)\n"); + +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + // full size 29.76fps + // capture setting 4208*3120 480MCLK 1.2Gp/lane + + if(currefps==300) + { + // full size 30.33ps + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x0114,0x03); + write_cmos_sensor(0x0220,0x00); + write_cmos_sensor(0x0221,0x11); + write_cmos_sensor(0x0222,0x01); + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x58); + write_cmos_sensor(0x0342,0x13); + write_cmos_sensor(0x0343,0x90); + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x00); + write_cmos_sensor(0x0902,0x00); + write_cmos_sensor(0x3000,0x35); + write_cmos_sensor(0x3054,0x01); + write_cmos_sensor(0x305C,0x11); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x03); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x96); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x0310,0x00); + + write_cmos_sensor(0x0820,0x12); + write_cmos_sensor(0x0821,0xC0); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x3A03,0x09); + write_cmos_sensor(0x3A04,0x20); + write_cmos_sensor(0x3A05,0x01); + + write_cmos_sensor(0x0B06,0x01); + write_cmos_sensor(0x30A2,0x00); + + write_cmos_sensor(0x30B4,0x00); + + write_cmos_sensor(0x3A02,0xff); + + write_cmos_sensor(0x3011,0x00); + write_cmos_sensor(0x3013,0x01); + + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x4E); + write_cmos_sensor(0x0224,0x01); + write_cmos_sensor(0x0225,0xF4); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x0216,0x00); + write_cmos_sensor(0x0217,0x00); + + write_cmos_sensor(0x4170,0x00); + write_cmos_sensor(0x4171,0x10); + write_cmos_sensor(0x4176,0x00); + write_cmos_sensor(0x4177,0x3C); + write_cmos_sensor(0xAE20,0x04); + write_cmos_sensor(0xAE21,0x5C); + + write_cmos_sensor(0x0138,0x01); + write_cmos_sensor(0x0100,0x01); + + } + else if(currefps==240){ + // full siez 24pfs + write_cmos_sensor(0x0100,0x00); + + write_cmos_sensor(0x0114,0x03); + write_cmos_sensor(0x0220,0x00); + write_cmos_sensor(0x0221,0x11); + write_cmos_sensor(0x0222,0x01); + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x94); + write_cmos_sensor(0x0342,0x13); + write_cmos_sensor(0x0343,0x90); + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x00); + write_cmos_sensor(0x0902,0x00); + write_cmos_sensor(0x3000,0x35); + write_cmos_sensor(0x3054,0x01); + write_cmos_sensor(0x305C,0x11); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x03); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x79); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x0310,0x00); + + write_cmos_sensor(0x0820,0x0F); + write_cmos_sensor(0x0821,0x20); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x3A03,0x08); + write_cmos_sensor(0x3A04,0xC0); + write_cmos_sensor(0x3A05,0x02); + + write_cmos_sensor(0x0B06,0x01); + write_cmos_sensor(0x30A2,0x00); + write_cmos_sensor(0x30B4,0x00); + write_cmos_sensor(0x3A02,0xFF); + write_cmos_sensor(0x3013,0x00); + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x8A); + write_cmos_sensor(0x0224,0x01); + write_cmos_sensor(0x0225,0xF4); + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x0216,0x00); + write_cmos_sensor(0x0217,0x00); + write_cmos_sensor(0x4170,0x00); + write_cmos_sensor(0x4171,0x10); + write_cmos_sensor(0x4176,0x00); + write_cmos_sensor(0x4177,0x3C); + write_cmos_sensor(0xAE20,0x04); + write_cmos_sensor(0xAE21,0x5C); + + write_cmos_sensor(0x0138,0x01); + write_cmos_sensor(0x0100,0x01); + } + else{ + // full siez 15pfs + write_cmos_sensor(0x0100,0x00); + + write_cmos_sensor(0x0114,0x03); + write_cmos_sensor(0x0220,0x00); + write_cmos_sensor(0x0221,0x11); + write_cmos_sensor(0x0222,0x01); + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x94); + write_cmos_sensor(0x0342,0x13); + write_cmos_sensor(0x0343,0x90); + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x00); + write_cmos_sensor(0x0902,0x00); + write_cmos_sensor(0x3000,0x35); + write_cmos_sensor(0x3054,0x01); + write_cmos_sensor(0x305C,0x11); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x03); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x4c); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x0310,0x00); + + write_cmos_sensor(0x0820,0x09); + write_cmos_sensor(0x0821,0x80); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x3A03,0x08); + write_cmos_sensor(0x3A04,0xC0); + write_cmos_sensor(0x3A05,0x02); + + write_cmos_sensor(0x0B06,0x01); + write_cmos_sensor(0x30A2,0x00); + write_cmos_sensor(0x30B4,0x00); + write_cmos_sensor(0x3A02,0xFF); + write_cmos_sensor(0x3013,0x00); + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x8A); + write_cmos_sensor(0x0224,0x01); + write_cmos_sensor(0x0225,0xF4); + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x0216,0x00); + write_cmos_sensor(0x0217,0x00); + write_cmos_sensor(0x4170,0x00); + write_cmos_sensor(0x4171,0x10); + write_cmos_sensor(0x4176,0x00); + write_cmos_sensor(0x4177,0x3C); + write_cmos_sensor(0xAE20,0x04); + write_cmos_sensor(0xAE21,0x5C); + + write_cmos_sensor(0x0138,0x01); + write_cmos_sensor(0x0100,0x01); + } +} + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + // full size 30.33ps + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x0114,0x03); + write_cmos_sensor(0x0220,0x00); + write_cmos_sensor(0x0221,0x11); + write_cmos_sensor(0x0222,0x01); + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x58); + write_cmos_sensor(0x0342,0x13); + write_cmos_sensor(0x0343,0x90); + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x00); + write_cmos_sensor(0x0902,0x00); + write_cmos_sensor(0x3000,0x35); + write_cmos_sensor(0x3054,0x01); + write_cmos_sensor(0x305C,0x11); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x03); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x96); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x0310,0x00); + + write_cmos_sensor(0x0820,0x12); + write_cmos_sensor(0x0821,0xC0); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x3A03,0x09); + write_cmos_sensor(0x3A04,0x20); + write_cmos_sensor(0x3A05,0x01); + + write_cmos_sensor(0x0B06,0x01); + write_cmos_sensor(0x30A2,0x00); + + write_cmos_sensor(0x30B4,0x00); + + write_cmos_sensor(0x3A02,0xff); + + write_cmos_sensor(0x3011,0x00); + write_cmos_sensor(0x3013,0x01); + + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x4E); + write_cmos_sensor(0x0224,0x01); + write_cmos_sensor(0x0225,0xF4); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x0216,0x00); + write_cmos_sensor(0x0217,0x00); + + write_cmos_sensor(0x4170,0x00); + write_cmos_sensor(0x4171,0x10); + write_cmos_sensor(0x4176,0x00); + write_cmos_sensor(0x4177,0x3C); + write_cmos_sensor(0xAE20,0x04); + write_cmos_sensor(0xAE21,0x5C); + + write_cmos_sensor(0x0138,0x01); + write_cmos_sensor(0x0100,0x01); + +} + +static void fullsize_setting_HDR(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + // full size 30.33ps + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x0114,0x03); + write_cmos_sensor(0x0220,0x21); + write_cmos_sensor(0x0221,0x11); + write_cmos_sensor(0x0222,0x08); + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x58); + write_cmos_sensor(0x0342,0x13); + write_cmos_sensor(0x0343,0x90); + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x00); + write_cmos_sensor(0x0902,0x00); + write_cmos_sensor(0x3000,0x35); + write_cmos_sensor(0x3054,0x01); + write_cmos_sensor(0x305C,0x11); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x03); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x96); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x0310,0x00); + + write_cmos_sensor(0x0820,0x12); + write_cmos_sensor(0x0821,0xC0); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x3A03,0x08); + write_cmos_sensor(0x3A04,0x90); + write_cmos_sensor(0x3A05,0x01); + + write_cmos_sensor(0x0B06,0x01); + write_cmos_sensor(0x30A2,0x00); + + write_cmos_sensor(0x30B4,0x00); + + write_cmos_sensor(0x3A02,0x06); + + write_cmos_sensor(0x3011,0x00); + write_cmos_sensor(0x3013,0x01); + + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x4E); + write_cmos_sensor(0x0224,0x01); + write_cmos_sensor(0x0225,0x89); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x0216,0x00); + write_cmos_sensor(0x0217,0x00); + + write_cmos_sensor(0x4170,0x00); + write_cmos_sensor(0x4171,0x10); + write_cmos_sensor(0x4176,0x00); + write_cmos_sensor(0x4177,0x3C); + write_cmos_sensor(0xAE20,0x04); + write_cmos_sensor(0xAE21,0x5C); + //mHDR relation setting + write_cmos_sensor(0x3010,0x00); + write_cmos_sensor(0x6D3A,0x00); // 0: 16X16, 1:8X8 + write_cmos_sensor(0x3011,0x00); + write_cmos_sensor(0x3013,0x01); // STATS output Enable + write_cmos_sensor(0x5068,0x35); + write_cmos_sensor(0x5069,0x01); + write_cmos_sensor(0x30C2,0x00); + write_cmos_sensor(0x30C3,0x40); + write_cmos_sensor(0x610A,0x08); + //[0]:1 hdr enable, [1]:0 LE/SE use same gain, 1 LE/SE separate gain + //[5]:0 auto, 1:direct + write_cmos_sensor(0x0220,0x21); + // hdr binning mode + write_cmos_sensor(0x0221,0x11); + //LE/SE ration 1,2,4,8 + write_cmos_sensor(0x0222,0x08); + //ATR + imx214_ATR(3,3); + + // Normal: 0x00, ZigZag: 0x01 + if(imgsensor.ihdr_mode == 9) + { + write_cmos_sensor(0x30b2,0x01); + write_cmos_sensor(0x30b3,0x01); + write_cmos_sensor(0x30b4,0x01); + write_cmos_sensor(0x30b5,0x01); + write_cmos_sensor(0x30b6,0x01); + write_cmos_sensor(0x30b7,0x01); + write_cmos_sensor(0x30b8,0x01); + write_cmos_sensor(0x30b9,0x01); + write_cmos_sensor(0x30ba,0x01); + write_cmos_sensor(0x30bb,0x01); + write_cmos_sensor(0x30bc,0x01); + } + else + { + write_cmos_sensor(0x30b2,0x00); + write_cmos_sensor(0x30b3,0x00); + write_cmos_sensor(0x30b4,0x00); + write_cmos_sensor(0x30b5,0x00); + write_cmos_sensor(0x30b6,0x00); + write_cmos_sensor(0x30b7,0x00); + write_cmos_sensor(0x30b8,0x00); + write_cmos_sensor(0x30b9,0x00); + write_cmos_sensor(0x30ba,0x00); + write_cmos_sensor(0x30bb,0x00); + write_cmos_sensor(0x30bc,0x00); + } + write_cmos_sensor(0x0138,0x01); + write_cmos_sensor(0x0100,0x01); + +} + +static void hs_video_setting(void) +{ + LOG_INF("E\n"); + //1080p 60fps + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x0114,0x03); + write_cmos_sensor(0x0220,0x00); + write_cmos_sensor(0x0221,0x11); + write_cmos_sensor(0x0222,0x01); + write_cmos_sensor(0x0340,0x05); + write_cmos_sensor(0x0341,0x08); + write_cmos_sensor(0x0342,0x13); + write_cmos_sensor(0x0343,0x90); + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x01); + write_cmos_sensor(0x0347,0x78); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0A); + write_cmos_sensor(0x034B,0xB7); + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x01); + write_cmos_sensor(0x0901,0x22); + write_cmos_sensor(0x0902,0x02); + write_cmos_sensor(0x3000,0x35); + write_cmos_sensor(0x3054,0x01); + write_cmos_sensor(0x305C,0x11); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x034C,0x08); + write_cmos_sensor(0x034D,0x38); + write_cmos_sensor(0x034E,0x04); + write_cmos_sensor(0x034F,0xA0); + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x08); + write_cmos_sensor(0x040D,0x38); + write_cmos_sensor(0x040E,0x04); + write_cmos_sensor(0x040F,0xA0); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x03); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x79);//79 + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x0310,0x00); + + write_cmos_sensor(0x0820,0x0F);//0F + write_cmos_sensor(0x0821,0x20);// 20 + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + write_cmos_sensor(0x3A03,0x06); + write_cmos_sensor(0x3A04,0x68); + write_cmos_sensor(0x3A05,0x01); + write_cmos_sensor(0x0B06,0x01); + write_cmos_sensor(0x30A2,0x00); + write_cmos_sensor(0x30B4,0x00); + write_cmos_sensor(0x3A02,0xFF); + write_cmos_sensor(0x3013,0x00); + write_cmos_sensor(0x0202,0x04); + write_cmos_sensor(0x0203,0xFE); + write_cmos_sensor(0x0224,0x01); + write_cmos_sensor(0x0225,0xF4); + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + write_cmos_sensor(0x0210,0x01); + write_cmos_sensor(0x0211,0x00); + write_cmos_sensor(0x0212,0x01); + write_cmos_sensor(0x0213,0x00); + write_cmos_sensor(0x0214,0x01); + write_cmos_sensor(0x0215,0x00); + write_cmos_sensor(0x0216,0x00); + write_cmos_sensor(0x0217,0x00); + write_cmos_sensor(0x4170,0x00); + write_cmos_sensor(0x4171,0x10); + write_cmos_sensor(0x4176,0x00); + write_cmos_sensor(0x4177,0x3C); + write_cmos_sensor(0xAE20,0x04); + write_cmos_sensor(0xAE21,0x5C); + + write_cmos_sensor(0x0138,0x01); + write_cmos_sensor(0x0100,0x01); + +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + hs_video_setting(); +} +#if 0 +static void vhdr_setting(void) +{ + LOG_INF("E\n"); +write_cmos_sensor(0x0114,0x03); +write_cmos_sensor(0x0220,0x21); +write_cmos_sensor(0x0221,0x22); +write_cmos_sensor(0x0222,0x10); +write_cmos_sensor(0x0340,0x06); +write_cmos_sensor(0x0341,0x68); +write_cmos_sensor(0x0342,0x13); +write_cmos_sensor(0x0343,0x90); +write_cmos_sensor(0x0344,0x00); +write_cmos_sensor(0x0345,0x00); +write_cmos_sensor(0x0346,0x01); +write_cmos_sensor(0x0347,0x78); +write_cmos_sensor(0x0348,0x10); +write_cmos_sensor(0x0349,0x6F); +write_cmos_sensor(0x034A,0x0A); +write_cmos_sensor(0x034B,0xB7); +write_cmos_sensor(0x0381,0x01); +write_cmos_sensor(0x0383,0x01); +write_cmos_sensor(0x0385,0x01); +write_cmos_sensor(0x0387,0x01); +write_cmos_sensor(0x0900,0x00); +write_cmos_sensor(0x0901,0x00); +write_cmos_sensor(0x0902,0x00); +write_cmos_sensor(0x3000,0x35); +write_cmos_sensor(0x3054,0x01); +write_cmos_sensor(0x305C,0x11); + +write_cmos_sensor(0x0112,0x0A); +write_cmos_sensor(0x0113,0x0A); +write_cmos_sensor(0x034C,0x08); +write_cmos_sensor(0x034D,0x38); +write_cmos_sensor(0x034E,0x04); +write_cmos_sensor(0x034F,0xA0); +write_cmos_sensor(0x0401,0x00); +write_cmos_sensor(0x0404,0x00); +write_cmos_sensor(0x0405,0x10); +write_cmos_sensor(0x0408,0x00); +write_cmos_sensor(0x0409,0x00); +write_cmos_sensor(0x040A,0x00); +write_cmos_sensor(0x040B,0x00); +write_cmos_sensor(0x040C,0x08); +write_cmos_sensor(0x040D,0x38); +write_cmos_sensor(0x040E,0x04); +write_cmos_sensor(0x040F,0xA0); + +write_cmos_sensor(0x0301,0x05); +write_cmos_sensor(0x0303,0x02); +write_cmos_sensor(0x0305,0x03); +write_cmos_sensor(0x0306,0x00); +write_cmos_sensor(0x0307,0x4D); +write_cmos_sensor(0x0309,0x0A); +write_cmos_sensor(0x030B,0x01); +write_cmos_sensor(0x0310,0x00); +write_cmos_sensor(0x0820,0x09); +write_cmos_sensor(0x0821,0xA0); +write_cmos_sensor(0x0822,0x00); +write_cmos_sensor(0x0823,0x00); +write_cmos_sensor(0x3A03,0x06); +write_cmos_sensor(0x3A04,0xE8); +write_cmos_sensor(0x3A05,0x01); +write_cmos_sensor(0x0B06,0x01); +write_cmos_sensor(0x30A2,0x00); +write_cmos_sensor(0x30B4,0x00); +write_cmos_sensor(0x3A02,0x06); +write_cmos_sensor(0x3013,0x01); +write_cmos_sensor(0x0202,0x06); +write_cmos_sensor(0x0203,0x5E); +write_cmos_sensor(0x0224,0x00); +write_cmos_sensor(0x0225,0xCB); +write_cmos_sensor(0x0204,0x00); +write_cmos_sensor(0x0205,0x00); +write_cmos_sensor(0x020E,0x01); +write_cmos_sensor(0x020F,0x00); +write_cmos_sensor(0x0210,0x01); +write_cmos_sensor(0x0211,0x00); +write_cmos_sensor(0x0212,0x01); +write_cmos_sensor(0x0213,0x00); +write_cmos_sensor(0x0214,0x01); +write_cmos_sensor(0x0215,0x00); +write_cmos_sensor(0x0216,0x00); +write_cmos_sensor(0x0217,0x00); +write_cmos_sensor(0x4170,0x00); +write_cmos_sensor(0x4171,0x10); +write_cmos_sensor(0x4176,0x00); +write_cmos_sensor(0x4177,0x3C); +write_cmos_sensor(0xAE20,0x04); +write_cmos_sensor(0xAE21,0x5C); + +write_cmos_sensor(0x0138,0x01); +write_cmos_sensor(0x0100,0x01); + +} +#endif +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = ((read_cmos_sensor(0x0016) << 8) | read_cmos_sensor(0x0017)); + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + /*iReadData(0x00,452,OTPData);*//*LukeHu--150810*/ + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, write id:0x%x id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint16 sensor_id = 0; + LOG_INF("PLATFORM:MT6595,MIPI 2LANE\n"); + LOG_INF("preview 1280*960@30fps,864Mbps/lane; video 1280*960@30fps,864Mbps/lane; capture 5M@30fps,864Mbps/lane\n"); + + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = ((read_cmos_sensor(0x0016) << 8) | read_cmos_sensor(0x0017)); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id:0x%x id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.shutter = 0x3D0; + imgsensor.gain = 0x100; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_mode = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + if((imgsensor.ihdr_mode == 2) || (imgsensor.ihdr_mode == 9)) + preview_setting_HDR(); + else + preview_setting(); + //hs_video_setting(); + + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else if(imgsensor.current_fps == imgsensor_info.cap2.max_framerate){ + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap1's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap1.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap2.pclk; + imgsensor.line_length = imgsensor_info.cap2.linelength; + imgsensor.frame_length = imgsensor_info.cap2.framelength; + imgsensor.min_frame_length = imgsensor_info.cap2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + }else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap1's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap1.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + // + if((imgsensor.ihdr_mode == 2) || (imgsensor.ihdr_mode == 9)) + fullsize_setting_HDR(imgsensor.current_fps); + else + capture_setting(imgsensor.current_fps); + + + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + if(imgsensor.ihdr_mode == 2) + fullsize_setting_HDR(imgsensor.current_fps); + else + normal_video_setting(imgsensor.current_fps); + + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + //sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + //sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else if (imgsensor.current_fps == imgsensor_info.cap2.max_framerate) { + frame_length = imgsensor_info.cap2.pclk / framerate * 10 / imgsensor_info.cap2.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap2.framelength) ? (frame_length - imgsensor_info.cap2.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + //set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0601,0x0002); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0601,0x0000); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 imx214_awb_gain(SET_SENSOR_AWB_GAIN *pSetSensorAWB) +{ + + UINT32 rgain_32, grgain_32, gbgain_32, bgain_32; + LOG_INF("imx214_awb_gain\n"); + grgain_32 = (pSetSensorAWB->ABS_GAIN_GR << 8) >> 9; + rgain_32 = (pSetSensorAWB->ABS_GAIN_R << 8) >> 9; + bgain_32 = (pSetSensorAWB->ABS_GAIN_B << 8) >> 9; + gbgain_32 = (pSetSensorAWB->ABS_GAIN_GB << 8) >> 9; + + LOG_INF("[imx214_awb_gain] ABS_GAIN_GR:%d, grgain_32:%d\n", pSetSensorAWB->ABS_GAIN_GR, grgain_32); + LOG_INF("[imx214_awb_gain] ABS_GAIN_R:%d, rgain_32:%d\n", pSetSensorAWB->ABS_GAIN_R, rgain_32); + LOG_INF("[imx214_awb_gain] ABS_GAIN_B:%d, bgain_32:%d\n", pSetSensorAWB->ABS_GAIN_B, bgain_32); + LOG_INF("[imx214_awb_gain] ABS_GAIN_GB:%d, gbgain_32:%d\n", pSetSensorAWB->ABS_GAIN_GB, gbgain_32); + + write_cmos_sensor(0x0b8e, (grgain_32 >> 8) & 0xFF); + write_cmos_sensor(0x0b8f, grgain_32 & 0xFF); + write_cmos_sensor(0x0b90, (rgain_32 >> 8) & 0xFF); + write_cmos_sensor(0x0b91, rgain_32 & 0xFF); + write_cmos_sensor(0x0b92, (bgain_32 >> 8) & 0xFF); + write_cmos_sensor(0x0b93, bgain_32 & 0xFF); + write_cmos_sensor(0x0b94, (gbgain_32 >> 8) & 0xFF); + write_cmos_sensor(0x0b95, gbgain_32 & 0xFF); + return ERROR_NONE; +} +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; +// unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + SENSOR_VC_INFO_STRUCT *pvcinfo; + SET_SENSOR_AWB_GAIN *pSetSensorAWB=(SET_SENSOR_AWB_GAIN *)feature_para; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + LOG_INF("feature_Control imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_mode = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + case SENSOR_FEATURE_GET_VC_INFO: + LOG_INF("SENSOR_FEATURE_GET_VC_INFO %d\n", (UINT16)*feature_data); + pvcinfo = (SENSOR_VC_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO[1],sizeof(SENSOR_VC_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO[2],sizeof(SENSOR_VC_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO[0],sizeof(SENSOR_VC_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_AWB_GAIN: + imx214_awb_gain(pSetSensorAWB); + break; + case SENSOR_FEATURE_SET_HDR_SHUTTER: + LOG_INF("SENSOR_FEATURE_SET_HDR_SHUTTER LE=%d, SE=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1)); + ihdr_write_shutter((UINT16)*feature_data,(UINT16)*(feature_data+1)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +//kin0603 +UINT32 IMX214_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +//UINT32 IMX214_MIPI_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV5693_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214mipiraw_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..06b928028603af847101780e8d0220d481be7bd3 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214mipiraw_Sensor.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * imx214mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _IMX214MIPI_SENSOR_H +#define _IMX214MIPI_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_mode; //ihdr mode 0: disable, 1: ihdr, 2:mVHDR, 9:zigzag + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint16 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information + imgsensor_mode_struct cap2; //capture for PIP 24fps relative information + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat; + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214otp.c b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214otp.c new file mode 100644 index 0000000000000000000000000000000000000000..ee9bdbc9b88fe35c073129d80eb4d0b4715fc3ec --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214otp.c @@ -0,0 +1,803 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * Driver for CAM_CAL + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#include "cam_cal.h" +#include "cam_cal_define.h" +#include "imx214otp.h" +//#include // for SMP +#include + + +#define CAM_CALGETDLT_DEBUG +//#define CAM_CAL_DEBUG +#ifdef CAM_CAL_DEBUG +#define CAM_CALDB printk +#else +#define CAM_CALDB(x,...) +#endif + +static DEFINE_SPINLOCK(g_CAM_CALLock); // for SMP +#define CAM_CAL_I2C_BUSNUM 0 +extern u8 OTPData[]; + +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_ICS_REVISION 1 //seanlin111208 +/******************************************************************************* +* +********************************************************************************/ +#define CAM_CAL_DRVNAME "CAM_CAL_DRV" +#define CAM_CAL_I2C_GROUP_ID 0 +/******************************************************************************* +* +********************************************************************************/ +static struct i2c_board_info __initdata kd_cam_cal_dev={ I2C_BOARD_INFO(CAM_CAL_DRVNAME, 0x6d>>1)}; + +static struct i2c_client * g_pstI2Cclient = NULL; + +//81 is used for V4L driver +static dev_t g_CAM_CALdevno = MKDEV(CAM_CAL_DEV_MAJOR_NUMBER,0); +static struct cdev * g_pCAM_CAL_CharDrv = NULL; +//static spinlock_t g_CAM_CALLock; +//spin_lock(&g_CAM_CALLock); +//spin_unlock(&g_CAM_CALLock); + +static struct class *CAM_CAL_class = NULL; +static atomic_t g_CAM_CALatomic; +//static DEFINE_SPINLOCK(kdcam_cal_drv_lock); +//spin_lock(&kdcam_cal_drv_lock); +//spin_unlock(&kdcam_cal_drv_lock); + +#define LSCOTPDATASIZE 512 + +int otp_flag=0; + +static kal_uint8 lscotpdata[LSCOTPDATASIZE]; +extern int iReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); + +#if 0 +#define iWriteCAM_CAL(addr, bytes, para,) iWriteReg((u16) addr , (u32) para , 1, IMX214OTP_DEVICE_ID) +#else + +/******************************************************************************* +* +********************************************************************************/ +//Address: 2Byte, Data: 1Byte +static int iWriteCAM_CAL(u16 a_u2Addr , u32 a_u4Bytes, u8 puDataInBytes) +{ + #if 0 + int i4RetValue = 0; + int retry = 3; + char puSendCmd[3] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF) ,puDataInBytes}; + g_pstI2Cclient->addr = (IMX214OTP_DEVICE_ID>> 1); + + do { + CAM_CALDB("[CAM_CAL][iWriteCAM_CAL] Write 0x%x=0x%x \n",a_u2Addr, puDataInBytes); + i4RetValue = i2c_master_send(g_pstI2Cclient, puSendCmd, 3); + if (i4RetValue != 3) { + CAM_CALDB("[CAM_CAL] I2C send failed!!\n"); + } + else { + break; + } + mdelay(10); + } while ((retry--) > 0); + //CAM_CALDB("[CAM_CAL] iWriteCAM_CAL done!! \n"); + #else + CAM_CALDB("[CAM_CAL][iWriteCAM_CAL] Write 0x%x=0x%x \n",a_u2Addr, puDataInBytes); + iWriteReg(a_u2Addr,puDataInBytes,1,IMX214OTP_DEVICE_ID); + #endif + return 0; +} +#endif + +//Address: 2Byte, Data: 1Byte +static int iReadCAM_CAL(u16 a_u2Addr, u32 ui4_length, u8 * a_puBuff) +{ + #if 0 + int i4RetValue = 0; + char puReadCmd[2] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF)}; + g_pstI2Cclient->addr = (IMX214OTP_DEVICE_ID>> 1); + + //CAM_CALDB("[CAM_CAL] iReadCAM_CAL!! \n"); + //CAM_CALDB("[CAM_CAL] i2c_master_send \n"); + i4RetValue = i2c_master_send(g_pstI2Cclient, puReadCmd, 2); + + if (i4RetValue != 2) + { + CAM_CALDB("[CAM_CAL] I2C send read address failed!! \n"); + return -1; + } + + //CAM_CALDB("[CAM_CAL] i2c_master_recv \n"); + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_puBuff, ui4_length); + CAM_CALDB("[CAM_CAL][iReadCAM_CAL] Read 0x%x=0x%x \n", a_u2Addr, a_puBuff[0]); + if (i4RetValue != ui4_length) + { + CAM_CALDB("[CAM_CAL] I2C read data failed!! \n"); + return -1; + } + + //CAM_CALDB("[CAM_CAL] iReadCAM_CAL done!! \n"); + #else + int i4RetValue = 0; + + i4RetValue=iReadReg(a_u2Addr,a_puBuff,IMX214OTP_DEVICE_ID); + + if (i4RetValue !=0) + { + CAM_CALDB("[CAM_CAL] I2C read data failed!! \n"); + return -1; + } + CAM_CALDB("[CAM_CAL][iReadCAM_CAL] Read 0x%x=0x%x \n", a_u2Addr, a_puBuff[0]); + #endif + return 0; +} + +int iReadCAM_CAL_8(u8 a_u2Addr, u8 * a_puBuff, u16 i2c_id) +{ + int i4RetValue = 0; + char puReadCmd[1] = {(char)(a_u2Addr)}; + + spin_lock(&g_CAM_CALLock); //for SMP + g_pstI2Cclient->addr = i2c_id>>1; + g_pstI2Cclient->timing=400; + g_pstI2Cclient->addr = g_pstI2Cclient->addr & (I2C_MASK_FLAG | I2C_WR_FLAG); + spin_unlock(&g_CAM_CALLock); // for SMP + + i4RetValue = i2c_master_send(g_pstI2Cclient, puReadCmd, 1); + + if (i4RetValue != 1) + { + CAM_CALDB("[CAM_CAL] I2C send read address failed!! \n"); + CAM_CALDB("[CAMERA SENSOR] I2C send failed, addr = 0x%x, data = 0x%x !! \n", a_u2Addr, *a_puBuff ); + return -1; + } + + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_puBuff, 1); + CAM_CALDB("[CAM_CAL][iReadCAM_CAL] Read 0x%x=0x%x \n", a_u2Addr, a_puBuff[0]); + if (i4RetValue != 1) + { + CAM_CALDB("[CAM_CAL] I2C read data failed!! \n"); + return -1; + } + + return 0; +} + +//go to page +#if 1 +static kal_uint8 IMX214_GotoPage(kal_uint8 page) +{ + return 1; +} + + +static kal_uint8 check_IMX214_otp_valid_AFPage(void) +{ + + kal_uint8 AF_OK = 0x00; + u8 readbuff, i; + + iReadCAM_CAL_8(0x28,&readbuff,0xA0); + + AF_OK = readbuff; + + if (AF_OK==1) + { + CAM_CALDB("can read AF otp from page\n"); + } + else + return KAL_FALSE; + + return KAL_TRUE; + +} + + +static kal_uint8 check_IMX214_otp_valid_AWBPage(void) +{ + kal_uint8 AWB_OK = 0x00; + u8 readbuff, i; + kal_uint16 LSC_lengthL,LSC_lengthH; + + iReadCAM_CAL_8(0x11,&readbuff,0xA0); + + AWB_OK = readbuff; + + if (AWB_OK==1) + { + CAM_CALDB("can read AWB otp from page\n"); + } + else + return KAL_FALSE; + + return KAL_TRUE; + +} + +#endif + +kal_bool check_IMX214_otp_valid_LSC_Page(kal_uint8 page) +{ + kal_uint8 LSC_OK = 0x00; + u8 readbuff, i; + + iReadCAM_CAL_8(0x30,&readbuff,0xA0); + + LSC_OK = readbuff; + + if (LSC_OK==1) + { + CAM_CALDB("can read LSC otp from page0~page5\n"); + CAM_CALDB("page number %d is valid\n",LSC_OK); + } + else + return KAL_FALSE; + + return KAL_TRUE; +} + +#if 1 + kal_bool IMX214_Read_LSC_Otp(kal_uint8 pagestart,kal_uint8 pageend,u16 Outdatalen,unsigned char * pOutputdata) + { + + kal_uint8 page = 0; + kal_uint16 byteperpage = 256; + kal_uint16 number = 0; + kal_uint16 LSCOTPaddress = 0x00 ; + u8 readbuff; + int i = 0; + + if(otp_flag){ + + for(i=0;iu4Length,GFP_KERNEL); + if(NULL == pWorkingBuff) + { + kfree(pBuff); + CAM_CALDB("[S24CAM_CAL] ioctl allocate mem failed\n"); + return -ENOMEM; + } + CAM_CALDB("[S24CAM_CAL] init Working buffer address 0x%8x command is 0x%8x\n", (u32)pWorkingBuff, (u32)a_u4Command); + + + if(copy_from_user((u8*)pWorkingBuff , (u8*)ptempbuf->pu1Params, ptempbuf->u4Length)) + { + kfree(pBuff); + kfree(pWorkingBuff); + CAM_CALDB("[S24CAM_CAL] ioctl copy from user failed\n"); + return -EFAULT; + } + + switch(a_u4Command) + { + case CAM_CALIOC_S_WRITE: + CAM_CALDB("[S24CAM_CAL] Write CMD \n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + i4RetValue = iWriteData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if(ktv2.tv_sec > ktv1.tv_sec) + { + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + } + else + { + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + } + printk("Write data %d bytes take %lu us\n",ptempbuf->u4Length, TimeIntervalUS); +#endif + break; + case CAM_CALIOC_G_READ: + CAM_CALDB("[S24CAM_CAL] Read CMD \n"); +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv1); +#endif + CAM_CALDB("[CAM_CAL] offset %d \n", ptempbuf->u4Offset); + CAM_CALDB("[CAM_CAL] length %d \n", ptempbuf->u4Length); + CAM_CALDB("[CAM_CAL] Before read Working buffer address 0x%8x \n", (u32)pWorkingBuff); + otp_flag=1; + i4RetValue = iReadData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff); + + CAM_CALDB("[S24CAM_CAL] After read Working buffer data 0x%4x \n", *pWorkingBuff); + + +#ifdef CAM_CALGETDLT_DEBUG + do_gettimeofday(&ktv2); + if(ktv2.tv_sec > ktv1.tv_sec) + { + TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec; + } + else + { + TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec; + } + printk("Read data %d bytes take %lu us\n",ptempbuf->u4Length, TimeIntervalUS); +#endif + + break; + default : + CAM_CALDB("[S24CAM_CAL] No CMD \n"); + i4RetValue = -EPERM; + break; + } + + if(_IOC_READ & _IOC_DIR(a_u4Command)) + { + //copy data to user space buffer, keep other input paremeter unchange. + CAM_CALDB("[S24CAM_CAL] to user length %d \n", ptempbuf->u4Length); + CAM_CALDB("[S24CAM_CAL] to user Working buffer address 0x%8x \n", (u32)pWorkingBuff); + if(copy_to_user((u8 __user *) ptempbuf->pu1Params , (u8 *)pWorkingBuff , ptempbuf->u4Length)) + { + kfree(pBuff); + kfree(pWorkingBuff); + CAM_CALDB("[S24CAM_CAL] ioctl copy to user failed\n"); + return -EFAULT; + } + } + + kfree(pBuff); + kfree(pWorkingBuff); + return i4RetValue; +} + + +static u32 g_u4Opened = 0; +//#define +//Main jobs: +// 1.check for device-specified errors, device not ready. +// 2.Initialize the device if it is opened for the first time. +static int CAM_CAL_Open(struct inode * a_pstInode, struct file * a_pstFile) +{ + CAM_CALDB("[S24CAM_CAL] CAM_CAL_Open\n"); + spin_lock(&g_CAM_CALLock); + if(g_u4Opened) + { + spin_unlock(&g_CAM_CALLock); + CAM_CALDB("[S24CAM_CAL] Opened, return -EBUSY\n"); + return -EBUSY; + } + else + { + g_u4Opened = 1; + atomic_set(&g_CAM_CALatomic,0); + } + spin_unlock(&g_CAM_CALLock); + + return 0; +} + +//Main jobs: +// 1.Deallocate anything that "open" allocated in private_data. +// 2.Shut down the device on last close. +// 3.Only called once on last time. +// Q1 : Try release multiple times. +static int CAM_CAL_Release(struct inode * a_pstInode, struct file * a_pstFile) +{ + spin_lock(&g_CAM_CALLock); + + g_u4Opened = 0; + + atomic_set(&g_CAM_CALatomic,0); + + spin_unlock(&g_CAM_CALLock); + + return 0; +} + +static const struct file_operations g_stCAM_CAL_fops = +{ + .owner = THIS_MODULE, + .open = CAM_CAL_Open, + .release = CAM_CAL_Release, + //.ioctl = CAM_CAL_Ioctl + .unlocked_ioctl = CAM_CAL_Ioctl +}; + +#define CAM_CAL_DYNAMIC_ALLOCATE_DEVNO 1 +inline static int RegisterCAM_CALCharDrv(void) +{ + struct device* CAM_CAL_device = NULL; + +#if CAM_CAL_DYNAMIC_ALLOCATE_DEVNO + if( alloc_chrdev_region(&g_CAM_CALdevno, 0, 1,CAM_CAL_DRVNAME) ) + { + CAM_CALDB("[S24CAM_CAL] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if( register_chrdev_region( g_CAM_CALdevno , 1 , CAM_CAL_DRVNAME) ) + { + CAM_CALDB("[S24CAM_CAL] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + //Allocate driver + g_pCAM_CAL_CharDrv = cdev_alloc(); + + if(NULL == g_pCAM_CAL_CharDrv) + { + unregister_chrdev_region(g_CAM_CALdevno, 1); + + CAM_CALDB("[S24CAM_CAL] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + //Attatch file operation. + cdev_init(g_pCAM_CAL_CharDrv, &g_stCAM_CAL_fops); + + g_pCAM_CAL_CharDrv->owner = THIS_MODULE; + + //Add to system + if(cdev_add(g_pCAM_CAL_CharDrv, g_CAM_CALdevno, 1)) + { + CAM_CALDB("[S24CAM_CAL] Attatch file operation failed\n"); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + return -EAGAIN; + } + + CAM_CAL_class = class_create(THIS_MODULE, "CAM_CALdrv"); + if (IS_ERR(CAM_CAL_class)) { + int ret = PTR_ERR(CAM_CAL_class); + CAM_CALDB("Unable to create class, err = %d\n", ret); + return ret; + } + CAM_CAL_device = device_create(CAM_CAL_class, NULL, g_CAM_CALdevno, NULL, CAM_CAL_DRVNAME); + + return 0; +} + +inline static void UnregisterCAM_CALCharDrv(void) +{ + //Release char driver + cdev_del(g_pCAM_CAL_CharDrv); + + unregister_chrdev_region(g_CAM_CALdevno, 1); + + device_destroy(CAM_CAL_class, g_CAM_CALdevno); + class_destroy(CAM_CAL_class); +} + + +////////////////////////////////////////////////////////////////////// +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); +#elif 0 +static int CAM_CAL_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); +#else +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int CAM_CAL_i2c_remove(struct i2c_client *); + +static const struct i2c_device_id CAM_CAL_i2c_id[] = {{CAM_CAL_DRVNAME,0},{}}; +#if 0 //test110314 Please use the same I2C Group ID as Sensor +static unsigned short force[] = {CAM_CAL_I2C_GROUP_ID, IMX214OTP_DEVICE_ID, I2C_CLIENT_END, I2C_CLIENT_END}; +#else +//static unsigned short force[] = {IMG_SENSOR_I2C_GROUP_ID, OV5647OTP_DEVICE_ID, I2C_CLIENT_END, I2C_CLIENT_END}; +#endif +//static const unsigned short * const forces[] = { force, NULL }; +//static struct i2c_client_address_data addr_data = { .forces = forces,}; + + +static struct i2c_driver CAM_CAL_i2c_driver = { + .probe = CAM_CAL_i2c_probe, + .remove = CAM_CAL_i2c_remove, +// .detect = CAM_CAL_i2c_detect, + .driver.name = CAM_CAL_DRVNAME, + .id_table = CAM_CAL_i2c_id, +}; + +#ifndef CAM_CAL_ICS_REVISION +static int CAM_CAL_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) { + strcpy(info->type, CAM_CAL_DRVNAME); + return 0; +} +#endif +static int CAM_CAL_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { +int i4RetValue = 0; + CAM_CALDB("[S24CAM_CAL] Attach I2C \n"); +// spin_lock_init(&g_CAM_CALLock); + + //get sensor i2c client + spin_lock(&g_CAM_CALLock); //for SMP + g_pstI2Cclient = client; + g_pstI2Cclient->addr = IMX214OTP_DEVICE_ID>>1; + spin_unlock(&g_CAM_CALLock); // for SMP + + CAM_CALDB("[CAM_CAL] g_pstI2Cclient->addr = 0x%8x \n",g_pstI2Cclient->addr); + //Register char driver + i4RetValue = RegisterCAM_CALCharDrv(); + + if(i4RetValue){ + CAM_CALDB("[S24CAM_CAL] register char device failed!\n"); + return i4RetValue; + } + + + CAM_CALDB("[S24CAM_CAL] Attached!! \n"); + return 0; +} + +static int CAM_CAL_i2c_remove(struct i2c_client *client) +{ + return 0; +} + +static int CAM_CAL_probe(struct platform_device *pdev) +{ + return i2c_add_driver(&CAM_CAL_i2c_driver); +} + +static int CAM_CAL_remove(struct platform_device *pdev) +{ + i2c_del_driver(&CAM_CAL_i2c_driver); + return 0; +} + +// platform structure +static struct platform_driver g_stCAM_CAL_Driver = { + .probe = CAM_CAL_probe, + .remove = CAM_CAL_remove, + .driver = { + .name = CAM_CAL_DRVNAME, + .owner = THIS_MODULE, + } +}; + + +static struct platform_device g_stCAM_CAL_Device = { + .name = CAM_CAL_DRVNAME, + .id = 0, + .dev = { + } +}; + +static int __init CAM_CAL_i2C_init(void) +{ + i2c_register_board_info(CAM_CAL_I2C_BUSNUM, &kd_cam_cal_dev, 1); + if(platform_driver_register(&g_stCAM_CAL_Driver)){ + CAM_CALDB("failed to register S24CAM_CAL driver\n"); + return -ENODEV; + } + + if (platform_device_register(&g_stCAM_CAL_Device)) + { + CAM_CALDB("failed to register S24CAM_CAL driver, 2nd time\n"); + return -ENODEV; + } + + return 0; +} + +static void __exit CAM_CAL_i2C_exit(void) +{ + platform_driver_unregister(&g_stCAM_CAL_Driver); +} + +module_init(CAM_CAL_i2C_init); +module_exit(CAM_CAL_i2C_exit); + +MODULE_DESCRIPTION("CAM_CAL driver"); +MODULE_AUTHOR("Sean Lin "); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214otp.h b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214otp.h new file mode 100644 index 0000000000000000000000000000000000000000..4b60c8d053148de03d19ea0c067f88386209c8d1 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx214_mipi_raw/imx214otp.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * S-24CS64A.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Header file of CAM_CAL driver + * + * + * Author: + * ------- + * Ronnie Lai (MTK01420) + * + *============================================================================*/ +#ifndef __CAM_CAL_H +#define __CAM_CAL_H + +#define CAM_CAL_DEV_MAJOR_NUMBER 226 + +/* CAM_CAL READ/WRITE ID */ +#define IMX214OTP_DEVICE_ID 0xA0 +#define I2C_UNIT_SIZE 1 //in byte +#define OTP_START_ADDR 0x0A04 +#define OTP_SIZE 24 + + +#endif /* __CAM_CAL_H */ + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..fb9b2594ec4860c5c66aecf230dbd26ea80cc228 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += imx258_pdafotp.o +obj-y += imx258mipiraw_Sensor.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258_pdafotp.c b/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258_pdafotp.c new file mode 100644 index 0000000000000000000000000000000000000000..d20aaf1371ebe531f7f45310f28b1f4a9d7294ef --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258_pdafotp.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef IMX258_PDAFOTP_DEBUG +#define PFX "IMX258_pdafotp" +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) +#else +#define LOG_INF(format, args...) +#endif + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +//extern int iBurstWriteReg_multi(u8 *pData, u32 bytes, u16 i2cId, u16 transfer_length); +extern int iMultiReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId, u8 number); + + +#define USHORT unsigned short +#define BYTE unsigned char +#define Sleep(ms) mdelay(ms) + +#define IMX258_EEPROM_READ_ID 0xA0 +#define IMX258_EEPROM_WRITE_ID 0xA1 +#define IMX258_I2C_SPEED 100 +#define IMX258_MAX_OFFSET 0xFFFF + +#define DATA_SIZE 2048 +BYTE imx258_eeprom_data[DATA_SIZE]= {0}; +static bool get_done = false; +static int last_size = 0; +static int last_offset = 0; + + +static bool selective_read_eeprom(kal_uint16 addr, BYTE* data) +{ + char pu_send_cmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + if(addr > IMX258_MAX_OFFSET) + return false; + + kdSetI2CSpeed(IMX258_I2C_SPEED); + + if(iReadRegI2C(pu_send_cmd, 2, (u8*)data, 1, IMX258_EEPROM_READ_ID)<0) + return false; + return true; +} + +static bool _read_imx258_eeprom(kal_uint16 addr, BYTE* data, kal_uint32 size ){ + int i = 0; + int offset = addr; + for(i = 0; i < size; i++) { + if(!selective_read_eeprom(offset, &data[i])){ + return false; + } + LOG_INF("read_eeprom 0x%0x %d\n",offset, data[i]); + offset++; + } + get_done = true; + last_size = size; + last_offset = addr; + return true; +} + +bool read_imx258_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size){ + addr = 0x0763; + size = 1404; + + LOG_INF("read imx258 eeprom, size = %d\n", size); + + if(!get_done || last_size != size || last_offset != addr) { + if(!_read_imx258_eeprom(addr, imx258_eeprom_data, size)){ + get_done = 0; + last_size = 0; + last_offset = 0; + return false; + } + } + + memcpy(data, imx258_eeprom_data, size); + return true; +} + +bool read_imx258_eeprom_SPC( kal_uint16 addr, BYTE* data, kal_uint32 size){ + + addr = 0x0F73;//0x0F73; + size = 126; + + LOG_INF("read imx258 eeprom, size = %d\n", size); + + if(!get_done || last_size != size || last_offset != addr) { + if(!_read_imx258_eeprom(addr, imx258_eeprom_data, size)){ + get_done = 0; + last_size = 0; + last_offset = 0; + return false; + } + } + + memcpy(data, imx258_eeprom_data, size); + return true; +} + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258mipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258mipiraw_Sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..7c79623ccf2dffaefd2da9741b3d2fbf0de5ca29 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258mipiraw_Sensor.c @@ -0,0 +1,3000 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * IMX258mipiraw_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "imx258mipiraw_Sensor.h" + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "IMX258_camera_sensor" +#define LOG_1 LOG_INF("IMX258,MIPI 1LANE\n") +#define LOG_2 LOG_INF("preview 1600*1200@30fps,600Mbps/lane; video 1600*1200@30fps,600Mbps/lane; 1600*1200@30fps,600Mbps/lane\n") +/**************************** Modify end *******************************************/ +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) +#define LOGE(format, args...) pr_err(PFX "[%s] " format, __FUNCTION__, ##args) + + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = IMX258_SENSOR_ID, //IMX258MIPI_SENSOR_ID, /*sensor_id = 0x2680*/ //record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0x16d8abef, //checksum value for Camera Auto Test + + .pre = { + .pclk = 259200000, //record different mode's pclk + .linelength = 5352, //record different mode's linelength + .framelength = 1614, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2100, //record different mode's width of grabwindow + .grabwindow_height = 1560, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = {/*normal capture*/ + .pclk = 518400000, + .linelength = 5352, + .framelength = 3228,//1332, + .startx = 0, + .starty = 0, + .grabwindow_width = 4208, + .grabwindow_height = 3120, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300,//300, + }, + .cap1 = {/*PIP capture*/ //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 259200000, + .linelength = 5352, + .framelength = 3228, + .startx = 0, + .starty = 0, + .grabwindow_width = 4208, + .grabwindow_height = 3120, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 150, //less than 13M(include 13M),cap1 max framerate is 24fps,16M max framerate is 20fps, 20M max framerate is 15fps + }, + #if 0 + .cap2 = {/*PIP capture*/ //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 415200000, + .linelength = 5352, + .framelength = 3228, + .startx = 0, + .starty = 0, + .grabwindow_width = 4208, + .grabwindow_height = 3120, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 240, //less than 13M(include 13M),cap1 max framerate is 24fps,16M max framerate is 20fps, 20M max framerate is 15fps + }, + #endif + .normal_video = { + .pclk = 518400000, + .linelength = 5352, + .framelength = 3228, + .startx = 0, + .starty = 0, + .grabwindow_width = 4208, + .grabwindow_height = 3120, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300,//modify + }, + .hs_video = {/*slow motion*/ + .pclk = 480000000,//518400000, + .linelength = 5352, + .framelength = 746,//806, + .startx = 0, + .starty = 0, + .grabwindow_width = 1048,//1400, + .grabwindow_height = 480,//752, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 1200,//modify + + }, + .slim_video = {/*VT Call*/ + .pclk = 259200000,//158400000, + .linelength = 5352, + .framelength = 1614,//986, //1236 + .startx = 0, + .starty = 0, + .grabwindow_width = 2100,//1400, + .grabwindow_height = 1560,//752, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + + .margin = 4, //sensor framelength & shutter margin + .min_shutter = 1, //1, //min shutter + .max_frame_length = 0x7fff,//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 1, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num + + .cap_delay_frame = 2, //enter capture delay frame num + .pre_delay_frame = 2, //enter preview delay frame num + .video_delay_frame = 2, //enter video delay frame num + .hs_video_delay_frame = 2, //enter high speed video delay frame num + .slim_video_delay_frame = 2,//enter slim video delay frame num + + .isp_driving_current = ISP_DRIVING_4MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_MANUAL,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_R,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_4_LANE,//mipi lane num + .i2c_addr_table = {0x34, 0x20, 0xff},//record sensor support all write id addr, only supprt 4must end with 0xff +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_HV_MIRROR, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x14d, //current shutter + .gain = 0xe000, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 300, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x34,//record current sensor's i2c write id +}; + +#define IMX258_HDR_TYPE (0x00) +#define IMX258_BINNING_TYPE (0x10) +static kal_uint16 imx258_type = 0;/*0x00=HDR type, 0x10=binning type*/ +/* Sensor output window information */ +/*according toIMX258 datasheet p53 image cropping*/ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[10] = + {{ 4208, 3120, 0, 0, 4208, 3120, 2100, 1560, 0000, 0000, 2100, 1560, 0, 0, 2100, 1560}, // Preview + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0000, 0000, 4208, 3120, 0, 0, 4208, 3120}, // capture + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0000, 0000, 4208, 3120, 0, 0, 4208, 3120}, // video +#if 0 + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0000, 0000, 4208, 3120, 0, 0, 4208, 3120}, // capture2 +#endif + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0000, 0000, 4208, 3120, 0, 0, 4208, 3120}, // video + { 4208, 3120, 0, 592, 4208, 1920, 1048, 480 , 0000, 0000, 1048, 480, 0, 0, 1048, 480}, //hight speed video + //{ 4208, 2688, 0, 432, 4208, 2256, 1400, 752 , 0000, 0000, 1400, 752, 0, 0, 1400, 752}, //hight speed video + { 4208, 3120, 0, 0, 4208, 3120, 2100, 1560, 0000, 0000, 2100, 1560, 0, 0, 2100, 1560}};// slim video + //{ 4208, 2688, 0, 432, 4208, 2256, 1400, 752 , 0000, 0000, 1400, 752, 0, 0, 1400, 752}};// slim video + +/*VC1 for HDR(DT=0X35) , VC2 for PDAF(DT=0X36), unit : 8bit*/ +static SENSOR_VC_INFO_STRUCT SENSOR_VC_INFO[3]= +{ + /* Preview mode setting */ + {0x03, 0x0a, 0x00, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x0834, 0x0618, 0x00, 0x35, 0x0280, 0x0001, + 0x00, 0x2f, 0x0000, 0x0000, 0x03, 0x00, 0x0000, 0x0000}, + /* Capture mode setting */ + {0x03, 0x0a, 0x00, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x1070, 0x0C30, 0x00, 0x35, 0x0280, 0x0001, + 0x00, 0x2f, 0x00A0, 0x0780, 0x03, 0x00, 0x0000, 0x0000}, + /* Video mode setting */ + {0x02, 0x0a, 0x00, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x1070, 0x0C30, 0x01, 0x00, 0x0000, 0x0000, + 0x02, 0x2f, 0x0000, 0x0000, 0x03, 0x00, 0x0000, 0x0000} +}; + +static SET_PD_BLOCK_INFO_T imgsensor_pd_info = +{ + .i4OffsetX = 24, + .i4OffsetY = 24, + .i4PitchX = 32, + .i4PitchY = 32, + .i4PairNum =4, + .i4SubBlkW =16, + .i4SubBlkH =16, + .i4PosL = {{27,30},{43,30},{34,49},{50,49}}, + .i4PosR = {{26,33},{42,33},{35,46},{51,46}}, +}; + +/* Binning Type VC information*/ +static SENSOR_VC_INFO_STRUCT SENSOR_VC_INFO_Binning[3]= +{ + /* Preview mode setting */ + {0x03, 0x0a, 0x00, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x0834, 0x0618, 0x00, 0x35, 0x0280, 0x0001, + 0x00, 0x2f, 0x00A0, 0x0602, 0x03, 0x00, 0x0000, 0x0000}, + /* Capture mode setting */ + {0x03, 0x0a, 0x00, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x1070, 0x0C30, 0x00, 0x35, 0x0280, 0x0001, + 0x00, 0x2f, 0x00A0, 0x0C02, 0x03, 0x00, 0x0000, 0x0000},//0x0780 + /* Video mode setting */ + {0x02, 0x0a, 0x00, 0x08, 0x40, 0x00, + 0x00, 0x2b, 0x1070, 0x0C30, 0x01, 0x00, 0x0000, 0x0000, + 0x02, 0x2f, 0x0000, 0x0000, 0x03, 0x00, 0x0000, 0x0000} +}; +/*HDR mode PD position information*/ +static SET_PD_BLOCK_INFO_T imgsensor_pd_info_Binning = +{ + .i4OffsetX = 24, + .i4OffsetY = 24, + .i4PitchX = 32, + .i4PitchY = 32, + .i4PairNum = 4,//8,//4, + .i4SubBlkW =16, + .i4SubBlkH =16, + .i4PosL = {{30,31},{46,31},{37,52},{53,52}},//{{30,29},{46,29},{30,31},{46,31},{37,52},{53,52},{37,54},{53,54}},//{{27,30},{43,30},{34,49},{50,49}}, + .i4PosR = {{29,36},{45,36},{38,47},{54,47}},//{{29,36},{45,36},{29,38},{45,38},{38,45},{54,45},{38,47},{54,47}},//{{26,33},{42,33},{35,46},{51,46}}, +}; + + +#define IMX258MIPI_MaxGainIndex (154) +kal_uint16 IMX258MIPI_sensorGainMapping[IMX258MIPI_MaxGainIndex][2] ={ + {64 ,0 }, + {65 ,8 }, + {66 ,16 }, + {67 ,25 }, + {68 ,30 }, + {69 ,37 }, + {70 ,45 }, + {71 ,51 }, + {72 ,57 }, + {73 ,63 }, + {74 ,67 }, + {75 ,75 }, + {76 ,81 }, + {77 ,85 }, + {78 ,92 }, + {79 ,96 }, + {80 ,103}, + {81 ,107}, + {82 ,112}, + {83 ,118}, + {84 ,122}, + {86 ,133}, + {88 ,140}, + {89 ,144}, + {90 ,148}, + {93 ,159}, + {96 ,171}, + {97 ,175}, + {99 ,182}, + {101,188}, + {102,192}, + {104,197}, + {106,202}, + {107,206}, + {109,211}, + {112,220}, + {113,222}, + {115,228}, + {118,235}, + {120,239}, + {125,250}, + {126,252}, + {128,256}, + {129,258}, + {130,260}, + {132,264}, + {133,266}, + {135,269}, + {136,271}, + {138,274}, + {139,276}, + {141,279}, + {142,282}, + {144,285}, + {145,286}, + {147,290}, + {149,292}, + {150,294}, + {155,300}, + {157,303}, + {158,305}, + {161,309}, + {163,311}, + {170,319}, + {172,322}, + {174,324}, + {176,326}, + {179,329}, + {181,331}, + {185,335}, + {189,339}, + {193,342}, + {195,344}, + {196,345}, + {200,348}, + {202,350}, + {205,352}, + {207,354}, + {210,356}, + {211,357}, + {214,359}, + {217,361}, + {218,362}, + {221,364}, + {224,366}, + {231,370}, + {237,374}, + {246,379}, + {250,381}, + {252,382}, + {256,384}, + {260,386}, + {262,387}, + {273,392}, + {275,393}, + {280,395}, + {290,399}, + {306,405}, + {312,407}, + {321,410}, + {331,413}, + {345,417}, + {352,419}, + {360,421}, + {364,422}, + {372,424}, + {386,427}, + {400,430}, + {410,432}, + {420,434}, + {431,436}, + {437,437}, + {449,439}, + {455,440}, + {461,441}, + {468,442}, + {475,443}, + {482,444}, + {489,445}, + {496,446}, + {504,447}, + {512,448}, + {520,449}, + {529,450}, + {537,451}, + {546,452}, + {555,453}, + {565,454}, + {575,455}, + {585,456}, + {596,457}, + {607,458}, + {618,459}, + {630,460}, + {642,461}, + {655,462}, + {669,463}, + {683,464}, + {697,465}, + {713,466}, + {728,467}, + {745,468}, + {762,469}, + {780,470}, + {799,471}, + {819,472}, + {840,473}, + {862,474}, + {886,475}, + {910,476}, + {936,477}, + {964,478}, + {993,479}, + {1024,480} +}; + + +/* +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[1] = {(char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 1, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; +} + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[2] = {(char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 2, imgsensor.i2c_write_id); + //iWriteReg((u16)addr, (u32)para, 2, imgsensor.i2c_write_id); +}*/ + +extern int iReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + iReadReg((u16) addr ,(u8*)&get_byte, imgsensor.i2c_write_id); + return get_byte; +} + +#define write_cmos_sensor(addr, para) iWriteReg((u16) addr , (u32) para , 1, imgsensor.i2c_write_id) + + +extern bool read_imx258_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size); +extern bool read_imx258_eeprom_SPC( kal_uint16 addr, BYTE* data, kal_uint32 size); + +static kal_uint8 IMX258MIPI_SPC_Data[126]; +static kal_uint8 SPC_data_done = false; +static void load_imx258_SPC_Data(void) +{ + kal_uint16 i; + if ( SPC_data_done == false ) { + if (!read_imx258_eeprom_SPC(0x0F73,IMX258MIPI_SPC_Data,126)) { + LOG_INF("imx258 load spc fail\n"); + return; + } + SPC_data_done = true; + } + + for(i=0; i<63; i++) + { + write_cmos_sensor(0xD04C+i, IMX258MIPI_SPC_Data[i]); + //LOG_INF("SPC_Data[%d] = %d\n", i, IMX258MIPI_SPC_Data[i]); + } + for(i=0; i<63; i++) + { + write_cmos_sensor(0xD08C+i, IMX258MIPI_SPC_Data[i+63]); + //LOG_INF("SPC_Data[%d] = %d\n", i+63, IMX258MIPI_SPC_Data[i+63]); + } +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + /* you can set dummy by imgsensor.dummy_line and imgsensor.dummy_pixel, or you can set dummy by imgsensor.frame_length and imgsensor.line_length */ + write_cmos_sensor(0x0104, 0x01); + + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0342, imgsensor.line_length >> 8); + write_cmos_sensor(0x0343, imgsensor.line_length & 0xFF); + + write_cmos_sensor(0x0104, 0x00); +} + +static kal_uint32 return_sensor_id(void) +{ +// kal_uint32 tmp = 0; + int retry = 10; + + if(write_cmos_sensor(0x0A02, 0x0F)==0){ + write_cmos_sensor(0x0A00, 0x01); + while(retry--) + { + if(read_cmos_sensor(0x0A01) == 0x01) + { + imx258_type = read_cmos_sensor(0x0A2E); + LOG_INF("imx258 type = 0x%x(0x00=HDR,0x10=binning)", imx258_type); + return (kal_uint16)((read_cmos_sensor(0x0A26) << 4) | (read_cmos_sensor(0x0A27) >> 4)); + } + } + } + + return 0x00; + +} +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + //kal_int16 dummy_line; + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable %d \n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + // imgsensor.dummy_line = 0; + //else + // imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + + +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + kal_uint16 realtime_fps = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + //write_shutter(shutter); + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x0104, 0x01); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0x00); + } + } else { + // Extend frame length + write_cmos_sensor(0x0104, 0x01); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0x00); + } + + // Update Shutter + write_cmos_sensor(0x0104, 0x01); + write_cmos_sensor(0x0202, (shutter >> 8) & 0xFF); + write_cmos_sensor(0x0203, shutter & 0xFF); + write_cmos_sensor(0x0104, 0x00); + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} /* set_shutter */ + + + + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint8 i; + + for (i = 0; i < IMX258MIPI_MaxGainIndex; i++) { + if(gain <= IMX258MIPI_sensorGainMapping[i][0]){ + break; + } + } + if(gain != IMX258MIPI_sensorGainMapping[i][0]) + LOG_INF("Gain mapping don't correctly:%d %d \n", gain, IMX258MIPI_sensorGainMapping[i][0]); + return IMX258MIPI_sensorGainMapping[i][1]; +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + /* 0x350A[0:1], 0x350B[0:7] AGC real gain */ + /* [0:3] = N meams N /16 X */ + /* [4:9] = M meams M X */ + /* Total gain = M + N /16 X */ + + // + if (gain < BASEGAIN || gain > 16 * BASEGAIN) { + LOG_INF("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 16 * BASEGAIN) + gain = 16 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor(0x0104, 0x01); + write_cmos_sensor(0x0204, (reg_gain>>8)& 0xFF); + write_cmos_sensor(0x0205, reg_gain & 0xFF); + write_cmos_sensor(0x0104, 0x00); + + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + + kal_uint16 realtime_fps = 0; + kal_uint16 reg_gain; + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + write_cmos_sensor(0x0104, 0x01); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0x00); + } + } else { + write_cmos_sensor(0x0104, 0x01); + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0104, 0x00); + } + write_cmos_sensor(0x0104, 0x01); + /* Long exposure */ + write_cmos_sensor(0x0202, (le >> 8) & 0xFF); + write_cmos_sensor(0x0203, le & 0xFF); + /* Short exposure */ + write_cmos_sensor(0x0224, (se >> 8) & 0xFF); + write_cmos_sensor(0x0225, se & 0xFF); + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + /* Global analog Gain for Long expo*/ + write_cmos_sensor(0x0204, (reg_gain>>8)& 0xFF); + write_cmos_sensor(0x0205, reg_gain & 0xFF); + /* Global analog Gain for Short expo*/ + //write_cmos_sensor(0x0216, (reg_gain>>8)& 0xFF); + //write_cmos_sensor(0x0217, reg_gain & 0xFF); + write_cmos_sensor(0x0104, 0x00); +} + +#if 0 +static void set_mirror_flip(kal_uint8 image_mirror) +{ + kal_uint8 iTemp; + LOG_INF("image_mirror = %d\n", image_mirror); + iTemp = read_cmos_sensor(0x0101); + iTemp&= ~0x03; //Clear the mirror and flip bits. + + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor(0x0101, iTemp|0x00); + break; + case IMAGE_H_MIRROR: + write_cmos_sensor(0x0101, iTemp|0x01); + break; + case IMAGE_V_MIRROR: + write_cmos_sensor(0x0101, iTemp|0x02); + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x0101, iTemp|0x03); + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} +#endif +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + + /* preview_setting */ +static void imx258_ImageQuality_Setting(void) +{ + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94C7,0xFF); + write_cmos_sensor(0x94C8,0xFF); + write_cmos_sensor(0x94C9,0xFF); + write_cmos_sensor(0x95C7,0xFF); + write_cmos_sensor(0x95C8,0xFF); + write_cmos_sensor(0x95C9,0xFF); + write_cmos_sensor(0x94C4,0x3F); + write_cmos_sensor(0x94C5,0x3F); + write_cmos_sensor(0x94C6,0x3F); + write_cmos_sensor(0x95C4,0x3F); + write_cmos_sensor(0x95C5,0x3F); + write_cmos_sensor(0x95C6,0x3F); + write_cmos_sensor(0x94C1,0x02); + write_cmos_sensor(0x94C2,0x02); + write_cmos_sensor(0x94C3,0x02); + write_cmos_sensor(0x95C1,0x02); + write_cmos_sensor(0x95C2,0x02); + write_cmos_sensor(0x95C3,0x02); + write_cmos_sensor(0x94BE,0x0C); + write_cmos_sensor(0x94BF,0x0C); + write_cmos_sensor(0x94C0,0x0C); + write_cmos_sensor(0x95BE,0x0C); + write_cmos_sensor(0x95BF,0x0C); + write_cmos_sensor(0x95C0,0x0C); + write_cmos_sensor(0x94D0,0x74); + write_cmos_sensor(0x94D1,0x74); + write_cmos_sensor(0x94D2,0x74); + write_cmos_sensor(0x95D0,0x74); + write_cmos_sensor(0x95D1,0x74); + write_cmos_sensor(0x95D2,0x74); + write_cmos_sensor(0x94CD,0x2E); + write_cmos_sensor(0x94CE,0x2E); + write_cmos_sensor(0x94CF,0x2E); + write_cmos_sensor(0x95CD,0x2E); + write_cmos_sensor(0x95CE,0x2E); + write_cmos_sensor(0x95CF,0x2E); + write_cmos_sensor(0x94CA,0x4C); + write_cmos_sensor(0x94CB,0x4C); + write_cmos_sensor(0x94CC,0x4C); + write_cmos_sensor(0x95CA,0x4C); + write_cmos_sensor(0x95CB,0x4C); + write_cmos_sensor(0x95CC,0x4C); + write_cmos_sensor(0x900E,0x32); + write_cmos_sensor(0x94E2,0xFF); + write_cmos_sensor(0x94E3,0xFF); + write_cmos_sensor(0x94E4,0xFF); + write_cmos_sensor(0x95E2,0xFF); + write_cmos_sensor(0x95E3,0xFF); + write_cmos_sensor(0x95E4,0xFF); + write_cmos_sensor(0x94DF,0x6E); + write_cmos_sensor(0x94E0,0x6E); + write_cmos_sensor(0x94E1,0x6E); + write_cmos_sensor(0x95DF,0x6E); + write_cmos_sensor(0x95E0,0x6E); + write_cmos_sensor(0x95E1,0x6E); + write_cmos_sensor(0x7FCC,0x01); + write_cmos_sensor(0x7B78,0x00); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x94C7,0xFF); + write_cmos_sensor(0x94C8,0xFF); + write_cmos_sensor(0x94C9,0xFF); + write_cmos_sensor(0x95C7,0xFF); + write_cmos_sensor(0x95C8,0xFF); + write_cmos_sensor(0x95C9,0xFF); + write_cmos_sensor(0x94C4,0x3F); + write_cmos_sensor(0x94C5,0x3F); + write_cmos_sensor(0x94C6,0x3F); + write_cmos_sensor(0x95C4,0x3F); + + write_cmos_sensor(0x95C5,0x3F); + write_cmos_sensor(0x95C6,0x3F); + write_cmos_sensor(0x94C1,0x02); + write_cmos_sensor(0x94C2,0x02); + write_cmos_sensor(0x94C3,0x02); + write_cmos_sensor(0x95C1,0x02); + write_cmos_sensor(0x95C2,0x02); + write_cmos_sensor(0x95C3,0x02); + write_cmos_sensor(0x94BE,0x0C); + write_cmos_sensor(0x94BF,0x0C); + write_cmos_sensor(0x94C0,0x0C); + write_cmos_sensor(0x95BE,0x0C); + write_cmos_sensor(0x95BF,0x0C); + write_cmos_sensor(0x95C0,0x0C); + write_cmos_sensor(0x94D0,0x74); + write_cmos_sensor(0x94D1,0x74); + write_cmos_sensor(0x94D2,0x74); + write_cmos_sensor(0x95D0,0x74); + write_cmos_sensor(0x95D1,0x74); + write_cmos_sensor(0x95D2,0x74); + write_cmos_sensor(0x94CD,0x16); + write_cmos_sensor(0x94CE,0x16); + write_cmos_sensor(0x94CF,0x16); + write_cmos_sensor(0x95CD,0x16); + write_cmos_sensor(0x95CE,0x16); + write_cmos_sensor(0x95CF,0x16); + write_cmos_sensor(0x94CA,0x28); + write_cmos_sensor(0x94CB,0x28); + write_cmos_sensor(0x94CC,0x28); + write_cmos_sensor(0x95CA,0x28); + write_cmos_sensor(0x95CB,0x28); + write_cmos_sensor(0x95CC,0x28); + write_cmos_sensor(0x900E,0x32); + write_cmos_sensor(0x94E2,0xFF); + write_cmos_sensor(0x94E3,0xFF); + write_cmos_sensor(0x94E4,0xFF); + write_cmos_sensor(0x95E2,0xFF); + write_cmos_sensor(0x95E3,0xFF); + write_cmos_sensor(0x95E4,0xFF); + write_cmos_sensor(0x94DF,0x6E); + write_cmos_sensor(0x94E0,0x6E); + write_cmos_sensor(0x94E1,0x6E); + write_cmos_sensor(0x95DF,0x6E); + write_cmos_sensor(0x95E0,0x6E); + write_cmos_sensor(0x95E1,0x6E); + write_cmos_sensor(0x7FCC,0x01); + write_cmos_sensor(0x7B78,0x00); + write_cmos_sensor(0x9401,0x35); + write_cmos_sensor(0x9403,0x23); + write_cmos_sensor(0x9405,0x23); + write_cmos_sensor(0x9406,0x00); + write_cmos_sensor(0x9407,0x31); + write_cmos_sensor(0x9408,0x00); + write_cmos_sensor(0x9409,0x1B); + write_cmos_sensor(0x940A,0x00); + write_cmos_sensor(0x940B,0x15); + write_cmos_sensor(0x940D,0x3F); + write_cmos_sensor(0x940F,0x3F); + write_cmos_sensor(0x9411,0x3F); + write_cmos_sensor(0x9413,0x64); + write_cmos_sensor(0x9415,0x64); + write_cmos_sensor(0x9417,0x64); + write_cmos_sensor(0x941D,0x34); + write_cmos_sensor(0x941F,0x01); + write_cmos_sensor(0x9421,0x01); + write_cmos_sensor(0x9423,0x01); + write_cmos_sensor(0x9425,0x23); + write_cmos_sensor(0x9427,0x23); + write_cmos_sensor(0x9429,0x23); + write_cmos_sensor(0x942B,0x2F); + write_cmos_sensor(0x942D,0x1A); + write_cmos_sensor(0x942F,0x14); + write_cmos_sensor(0x9431,0x3F); + write_cmos_sensor(0x9433,0x3F); + write_cmos_sensor(0x9435,0x3F); + write_cmos_sensor(0x9437,0x6B); + write_cmos_sensor(0x9439,0x7C); + write_cmos_sensor(0x943B,0x81); + write_cmos_sensor(0x9443,0x0F); + write_cmos_sensor(0x9445,0x0F); + write_cmos_sensor(0x9447,0x0F); + write_cmos_sensor(0x9449,0x0F); + write_cmos_sensor(0x944B,0x0F); + write_cmos_sensor(0x944D,0x0F); + write_cmos_sensor(0x944F,0x1E); + write_cmos_sensor(0x9451,0x0F); + write_cmos_sensor(0x9453,0x0B); + write_cmos_sensor(0x9455,0x28); + write_cmos_sensor(0x9457,0x13); + write_cmos_sensor(0x9459,0x0C); + write_cmos_sensor(0x945D,0x00); + write_cmos_sensor(0x945E,0x00); + write_cmos_sensor(0x945F,0x00); + write_cmos_sensor(0x946D,0x00); + write_cmos_sensor(0x946F,0x10); + write_cmos_sensor(0x9471,0x10); + write_cmos_sensor(0x9473,0x40); + write_cmos_sensor(0x9475,0x2E); + write_cmos_sensor(0x9477,0x10); + write_cmos_sensor(0x9478,0x0A); + write_cmos_sensor(0x947B,0xE0); + write_cmos_sensor(0x947C,0xE0); + write_cmos_sensor(0x947D,0xE0); + write_cmos_sensor(0x947E,0xE0); + write_cmos_sensor(0x947F,0xE0); + write_cmos_sensor(0x9480,0xE0); + write_cmos_sensor(0x9483,0x14); + write_cmos_sensor(0x9485,0x14); + write_cmos_sensor(0x9487,0x14); + write_cmos_sensor(0x9501,0x35); + write_cmos_sensor(0x9503,0x14); + write_cmos_sensor(0x9505,0x14); + write_cmos_sensor(0x9507,0x31); + write_cmos_sensor(0x9509,0x1B); + write_cmos_sensor(0x950B,0x15); + write_cmos_sensor(0x950D,0x1E); + write_cmos_sensor(0x950F,0x1E); + write_cmos_sensor(0x9511,0x1E); + write_cmos_sensor(0x9513,0x64); + write_cmos_sensor(0x9515,0x64); + write_cmos_sensor(0x9517,0x64); + write_cmos_sensor(0x951D,0x34); + write_cmos_sensor(0x951F,0x01); + write_cmos_sensor(0x9521,0x01); + write_cmos_sensor(0x9523,0x01); + write_cmos_sensor(0x9525,0x14); + write_cmos_sensor(0x9527,0x14); + write_cmos_sensor(0x9529,0x14); + write_cmos_sensor(0x952B,0x2F); + write_cmos_sensor(0x952D,0x1A); + write_cmos_sensor(0x952F,0x14); + write_cmos_sensor(0x9531,0x1E); + write_cmos_sensor(0x9533,0x1E); + write_cmos_sensor(0x9535,0x1E); + write_cmos_sensor(0x9537,0x6B); + write_cmos_sensor(0x9539,0x7C); + write_cmos_sensor(0x953B,0x81); + write_cmos_sensor(0x9543,0x0F); + write_cmos_sensor(0x9545,0x0F); + write_cmos_sensor(0x9547,0x0F); + write_cmos_sensor(0x9549,0x0F); + write_cmos_sensor(0x954B,0x0F); + write_cmos_sensor(0x954D,0x0F); + write_cmos_sensor(0x954F,0x15); + write_cmos_sensor(0x9551,0x0B); + write_cmos_sensor(0x9553,0x08); + write_cmos_sensor(0x9555,0x1C); + write_cmos_sensor(0x9557,0x0D); + write_cmos_sensor(0x9559,0x08); + write_cmos_sensor(0x955D,0x00); + write_cmos_sensor(0x955E,0x00); + write_cmos_sensor(0x955F,0x00); + write_cmos_sensor(0x956D,0x00); + write_cmos_sensor(0x956F,0x10); + write_cmos_sensor(0x9571,0x10); + write_cmos_sensor(0x9573,0x40); + write_cmos_sensor(0x9575,0x2E); + write_cmos_sensor(0x9577,0x10); + write_cmos_sensor(0x9578,0x0A); + write_cmos_sensor(0x957B,0xE0); + write_cmos_sensor(0x957C,0xE0); + write_cmos_sensor(0x957D,0xE0); + write_cmos_sensor(0x957E,0xE0); + write_cmos_sensor(0x957F,0xE0); + write_cmos_sensor(0x9580,0xE0); + write_cmos_sensor(0x9583,0x14); + write_cmos_sensor(0x9585,0x14); + write_cmos_sensor(0x9587,0x14); + write_cmos_sensor(0x7F78,0x00); + write_cmos_sensor(0x7F89,0x00); + write_cmos_sensor(0x7F93,0x00); + write_cmos_sensor(0x924B,0x1B); + write_cmos_sensor(0x924C,0x0A); + write_cmos_sensor(0x9304,0x04); + write_cmos_sensor(0x9315,0x04); + write_cmos_sensor(0x9250,0x50); + write_cmos_sensor(0x9251,0x3C); + write_cmos_sensor(0x9252,0x14); + write_cmos_sensor(0x7B5F,0x01); + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x01); + write_cmos_sensor(0x9010,0x48); + write_cmos_sensor(0x9419,0x50); + write_cmos_sensor(0x941B,0x50); + write_cmos_sensor(0x9519,0x50); + write_cmos_sensor(0x951B,0x50); + + + write_cmos_sensor(0xD000,0x00); + write_cmos_sensor(0xD001,0x18); + write_cmos_sensor(0xD002,0x00); + write_cmos_sensor(0xD003,0x18); + write_cmos_sensor(0xD004,0x10); + write_cmos_sensor(0xD005,0x57); + write_cmos_sensor(0xD006,0x0C); + write_cmos_sensor(0xD007,0x17); + write_cmos_sensor(0xD00A,0x01); + write_cmos_sensor(0xD00B,0x02); + write_cmos_sensor(0xD00D,0x06); + write_cmos_sensor(0xD00E,0x05); + write_cmos_sensor(0xD00F,0x01); + write_cmos_sensor(0xD011,0x06); + write_cmos_sensor(0xD012,0x07); + write_cmos_sensor(0xD013,0x01); + write_cmos_sensor(0xD015,0x05); + write_cmos_sensor(0xD016,0x0C); + write_cmos_sensor(0xD017,0x02); + write_cmos_sensor(0xD019,0x05); + write_cmos_sensor(0xD01A,0x0E); + write_cmos_sensor(0xD01B,0x02); + write_cmos_sensor(0xD01D,0x0E); + write_cmos_sensor(0xD01E,0x15); + write_cmos_sensor(0xD01F,0x02); + write_cmos_sensor(0xD021,0x0E); + write_cmos_sensor(0xD022,0x17); + write_cmos_sensor(0xD023,0x02); + write_cmos_sensor(0xD025,0x0D); + write_cmos_sensor(0xD026,0x1C); + write_cmos_sensor(0xD027,0x01); + write_cmos_sensor(0xD029,0x0D); + write_cmos_sensor(0xD02A,0x1E); + write_cmos_sensor(0xD02B,0x01); + } +} + + +static void sensor_init(void) +{ + LOG_INF("E\n"); + //init setting + //imx258 + write_cmos_sensor(0x0136,0x18); + write_cmos_sensor(0x0137,0x00); + + write_cmos_sensor(0x3051,0x00); + write_cmos_sensor(0x6B11,0xCF); + write_cmos_sensor(0x7FF0,0x08); + write_cmos_sensor(0x7FF1,0x0F); + write_cmos_sensor(0x7FF2,0x08); + write_cmos_sensor(0x7FF3,0x1B); + write_cmos_sensor(0x7FF4,0x23); + write_cmos_sensor(0x7FF5,0x60); + write_cmos_sensor(0x7FF6,0x00); + write_cmos_sensor(0x7FF7,0x01); + write_cmos_sensor(0x7FF8,0x00); + write_cmos_sensor(0x7FF9,0x78); + write_cmos_sensor(0x7FFA,0x01); + write_cmos_sensor(0x7FFB,0x00); + write_cmos_sensor(0x7FFC,0x00); + write_cmos_sensor(0x7FFD,0x00); + write_cmos_sensor(0x7FFE,0x00); + write_cmos_sensor(0x7FFF,0x03); + write_cmos_sensor(0x7F76,0x03); + write_cmos_sensor(0x7F77,0xFE); + write_cmos_sensor(0x7FA8,0x03); + write_cmos_sensor(0x7FA9,0xFE); + write_cmos_sensor(0x7B24,0x81); + write_cmos_sensor(0x7B25,0x01); + write_cmos_sensor(0x6564,0x07); + write_cmos_sensor(0x6B0D,0x41); + write_cmos_sensor(0x653D,0x04); + write_cmos_sensor(0x6B05,0x8C); + write_cmos_sensor(0x6B06,0xF9); + write_cmos_sensor(0x6B08,0x65); + write_cmos_sensor(0x6B09,0xFC); + write_cmos_sensor(0x6B0A,0xCF); + write_cmos_sensor(0x6B0B,0xD2); + write_cmos_sensor(0x6700,0x0E); + write_cmos_sensor(0x6707,0x0E); + write_cmos_sensor(0x9104,0x00); + write_cmos_sensor(0x7421,0x1C); + write_cmos_sensor(0x7423,0xD7); + write_cmos_sensor(0x5F04,0x00); + write_cmos_sensor(0x5F05,0xED); + + imx258_ImageQuality_Setting(); + + load_imx258_SPC_Data(); + write_cmos_sensor(0x7BC8,0x01); + + write_cmos_sensor(0x0100,0x00); +} /* sensor_init */ + +static void preview_setting(void) +{ + LOG_INF("preview E\n"); + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x6C); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x0A); + write_cmos_sensor(0x0821,0x20); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x06); + write_cmos_sensor(0x0341,0x4E); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x01); + write_cmos_sensor(0x0901,0x12); + write_cmos_sensor(0x0902,0x02); + + write_cmos_sensor(0x0401,0x01); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x20); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x06); + write_cmos_sensor(0x040F,0x18); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x00); + + write_cmos_sensor(0x034C,0x08); + write_cmos_sensor(0x034D,0x34); + write_cmos_sensor(0x034E,0x06); + write_cmos_sensor(0x034F,0x18); + + write_cmos_sensor(0x0202,0x06); + write_cmos_sensor(0x0203,0x44); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x7BCD,0x01); + } + + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + write_cmos_sensor(0x0220,0x00); + + write_cmos_sensor(0x0100,0x01); + mdelay(10); + +} + +static void capture_setting(kal_uint16 curretfps, kal_uint8 pdaf_mode) +{ + LOG_INF("capture E\n"); + LOG_INF("E! currefps:%d\n",curretfps); + if(curretfps == 150) + { + LOG_INF("PIP15fps capture E\n"); + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x6C); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x0A); + write_cmos_sensor(0x0821,0x20); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x9C); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x11); + write_cmos_sensor(0x0902,0x00); + + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x00); + + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x92); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x7BCD,0x00); + } + + if(pdaf_mode == 1) { + LOG_INF("read 0x3030\n"); + write_cmos_sensor(0x3030,0x01);//pdaf enable + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x01); /* 0:raw10, 1:BYTE2 */ + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + + } else { + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + } + write_cmos_sensor(0x0220,0x00); + write_cmos_sensor(0x0100,0x01); + mdelay(10); + } + else if(curretfps == 240) + { + LOG_INF("PIP24fps capture E\n"); + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xAD); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x10); + write_cmos_sensor(0x0821,0x38); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x9C); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x11); + write_cmos_sensor(0x0902,0x00); + + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x00); + + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x92); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x7BCD,0x00); + } + + if(pdaf_mode == 1) { + LOG_INF("read 0x3030\n"); + write_cmos_sensor(0x3030,0x01);//pdaf enable + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x01); /* 0:raw10, 1:BYTE2 */ + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + + } else { + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + } + + write_cmos_sensor(0x0220,0x00); + write_cmos_sensor(0x0100,0x01); + mdelay(10); + + } + else + { + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xD8); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x14); + write_cmos_sensor(0x0821,0x40); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x9C); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x11); + write_cmos_sensor(0x0902,0x00); + + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x00); + + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x92); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x7BCD,0x00); + } + + if(pdaf_mode == 1) { + LOG_INF("read 0x3030\n"); + write_cmos_sensor(0x3030,0x01);//pdaf enable + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x01); /* 0:raw10, 1:BYTE2 */ + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + + } else { + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + } + + write_cmos_sensor(0x0220,0x00); + + write_cmos_sensor(0x0100,0x01); + mdelay(10); + } +} +#if 0 +static void PIP24fps_capture_setting() +{ + LOG_INF("PIP24fps capture E\n"); + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xAD); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x10); + write_cmos_sensor(0x0821,0x38); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x9C); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x11); + write_cmos_sensor(0x0902,0x00); + + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x00); + + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x92); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + write_cmos_sensor(0x0220,0x00); + + write_cmos_sensor(0x0100,0x01); + mdelay(10); + +} + + +static void PIP15fps_capture_setting() +{ + LOG_INF("PIP15fps capture E\n"); + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x6C); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x0A); + write_cmos_sensor(0x0821,0x20); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x0C); + write_cmos_sensor(0x0341,0x9C); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x11); + write_cmos_sensor(0x0902,0x00); + + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x00); + + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + + write_cmos_sensor(0x0202,0x0C); + write_cmos_sensor(0x0203,0x92); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + write_cmos_sensor(0x0220,0x00); + + write_cmos_sensor(0x0100,0x01); + mdelay(10); + +} +#endif +static void normal_video_setting(kal_uint16 currefps, kal_uint8 pdaf_mode) +{ + LOG_INF("normal video E\n"); + LOG_INF("E! currefps:%d\n",currefps); + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xD8); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x14); + write_cmos_sensor(0x0821,0x40); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x0C); + if(imx258_type == IMX258_HDR_TYPE) + write_cmos_sensor(0x0341,0x9C);// + else if(imx258_type == IMX258_BINNING_TYPE) + write_cmos_sensor(0x0341,0x98); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x00); + write_cmos_sensor(0x0901,0x11); + write_cmos_sensor(0x0902,0x00); + + write_cmos_sensor(0x0401,0x00); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x10); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x0C); + write_cmos_sensor(0x040F,0x30); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x00); + + write_cmos_sensor(0x034C,0x10); + write_cmos_sensor(0x034D,0x70); + write_cmos_sensor(0x034E,0x0C); + write_cmos_sensor(0x034F,0x30); + + write_cmos_sensor(0x0202,0x0C); + if(imx258_type == IMX258_HDR_TYPE) + write_cmos_sensor(0x0203,0x92);// + else if(imx258_type == IMX258_BINNING_TYPE) + write_cmos_sensor(0x0203,0x8E); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + if(imgsensor.ihdr_en == 1) + { + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94DC,0x53); + write_cmos_sensor(0x94DD,0x53); + write_cmos_sensor(0x94DE,0x53); + write_cmos_sensor(0x95DC,0x53); + write_cmos_sensor(0x95DD,0x53); + write_cmos_sensor(0x95DE,0x53); + write_cmos_sensor(0x7FB0,0x01); + write_cmos_sensor(0x9010,0x52); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x7BCD,0x00); + } + + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + write_cmos_sensor(0x0220,0x21); //0x03 + //write_cmos_sensor(0x0222,0x08); + } + else + { + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x7BCD,0x00); + } + + if(pdaf_mode == 1) + { + write_cmos_sensor(0x3030,0x01); + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x01); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + write_cmos_sensor(0x0220,0x00); + } + else + { + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + write_cmos_sensor(0x0220,0x00); + } + } + LOG_INF("imgsensor.ihdr_en in video mode:%d\n",imgsensor.ihdr_en); + + + write_cmos_sensor(0x0100,0x01); + mdelay(10); + +} +static void hs_video_setting(void) +{ + LOG_INF("hs_video E\n"); + + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xC8); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x12); + write_cmos_sensor(0x0821,0xC0); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x02); + write_cmos_sensor(0x0341,0xEA); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x02); + write_cmos_sensor(0x0347,0x50); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x09); + write_cmos_sensor(0x034B,0xCF); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x03); + write_cmos_sensor(0x0387,0x03); + write_cmos_sensor(0x0900,0x01); + write_cmos_sensor(0x0901,0x12); + write_cmos_sensor(0x0902,0x02); + + write_cmos_sensor(0x0401,0x01); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x40); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x02); + write_cmos_sensor(0x040F,0x80); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x01); + + write_cmos_sensor(0x034C,0x04); + write_cmos_sensor(0x034D,0x18); + write_cmos_sensor(0x034E,0x01); + write_cmos_sensor(0x034F,0xE0); + + write_cmos_sensor(0x0202,0x02); + write_cmos_sensor(0x0203,0xE0); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x7BCD,0x01); + } + + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + write_cmos_sensor(0x0220,0x00); + + write_cmos_sensor(0x0100,0x01); + mdelay(10); + + +} + +static void slim_video_setting(void) +{ + LOG_INF("slim video E\n"); + write_cmos_sensor(0x0100,0x00); + mdelay(10); + + write_cmos_sensor(0x0112,0x0A); + write_cmos_sensor(0x0113,0x0A); + write_cmos_sensor(0x0114,0x03); + + write_cmos_sensor(0x0301,0x05); + write_cmos_sensor(0x0303,0x02); + write_cmos_sensor(0x0305,0x04); + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0x6C); + write_cmos_sensor(0x0309,0x0A); + write_cmos_sensor(0x030B,0x01); + write_cmos_sensor(0x030D,0x02); + write_cmos_sensor(0x030E,0x00); + write_cmos_sensor(0x030F,0xD8); + write_cmos_sensor(0x0310,0x00); + write_cmos_sensor(0x0820,0x0A); + write_cmos_sensor(0x0821,0x20); + write_cmos_sensor(0x0822,0x00); + write_cmos_sensor(0x0823,0x00); + + write_cmos_sensor(0x0342,0x14); + write_cmos_sensor(0x0343,0xE8); + + write_cmos_sensor(0x0340,0x06); + write_cmos_sensor(0x0341,0x4E); + + write_cmos_sensor(0x0344,0x00); + write_cmos_sensor(0x0345,0x00); + write_cmos_sensor(0x0346,0x00); + write_cmos_sensor(0x0347,0x00); + write_cmos_sensor(0x0348,0x10); + write_cmos_sensor(0x0349,0x6F); + write_cmos_sensor(0x034A,0x0C); + write_cmos_sensor(0x034B,0x2F); + + write_cmos_sensor(0x0381,0x01); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0385,0x01); + write_cmos_sensor(0x0387,0x01); + write_cmos_sensor(0x0900,0x01); + write_cmos_sensor(0x0901,0x12); + write_cmos_sensor(0x0902,0x02); + + write_cmos_sensor(0x0401,0x01); + write_cmos_sensor(0x0404,0x00); + write_cmos_sensor(0x0405,0x20); + write_cmos_sensor(0x0408,0x00); + write_cmos_sensor(0x0409,0x00); + write_cmos_sensor(0x040A,0x00); + write_cmos_sensor(0x040B,0x00); + write_cmos_sensor(0x040C,0x10); + write_cmos_sensor(0x040D,0x70); + write_cmos_sensor(0x040E,0x06); + write_cmos_sensor(0x040F,0x18); + write_cmos_sensor(0x3038,0x00); + write_cmos_sensor(0x303A,0x00); + write_cmos_sensor(0x303B,0x10); + write_cmos_sensor(0x300D,0x00); + + write_cmos_sensor(0x034C,0x08); + write_cmos_sensor(0x034D,0x34); + write_cmos_sensor(0x034E,0x06); + write_cmos_sensor(0x034F,0x18); + + write_cmos_sensor(0x0202,0x06); + write_cmos_sensor(0x0203,0x44); + + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x00); + write_cmos_sensor(0x020E,0x01); + write_cmos_sensor(0x020F,0x00); + + if(imx258_type == IMX258_HDR_TYPE) + { + write_cmos_sensor(0x94DC,0x20); + write_cmos_sensor(0x94DD,0x20); + write_cmos_sensor(0x94DE,0x20); + write_cmos_sensor(0x95DC,0x20); + write_cmos_sensor(0x95DD,0x20); + write_cmos_sensor(0x95DE,0x20); + write_cmos_sensor(0x7FB0,0x00); + write_cmos_sensor(0x9010,0x3E); + } + else if(imx258_type == IMX258_BINNING_TYPE) + { + write_cmos_sensor(0x7BCD,0x01); + } + + write_cmos_sensor(0x3030,0x00); + LOG_INF("0x3030=%d\n",read_cmos_sensor(0x3030)); + write_cmos_sensor(0x3032,0x00); + LOG_INF("0x3032=%d\n",read_cmos_sensor(0x3032)); + write_cmos_sensor(0x0220,0x00); + + write_cmos_sensor(0x0100,0x01); + mdelay(10); + +} + + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +//#define SLT_DEVINFO_CMM +#ifdef SLT_DEVINFO_CMM +#include +static struct devinfo_struct *s_DEVINFO_ccm; //suppose 10 max lcm device +#endif +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry_total = 1; + kal_uint8 retry_cnt = retry_total; +#ifdef SLT_DEVINFO_CMM + s_DEVINFO_ccm =(struct devinfo_struct*) kmalloc(sizeof(struct devinfo_struct), GFP_KERNEL); + s_DEVINFO_ccm->device_type = "CCM"; + s_DEVINFO_ccm->device_module = "PC0FB0002B";//can change if got module id + s_DEVINFO_ccm->device_vendor = "Sunrise"; + s_DEVINFO_ccm->device_ic = "IMX258"; + s_DEVINFO_ccm->device_version = "HI"; + s_DEVINFO_ccm->device_info = "200W"; +#endif + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + #ifdef SLT_DEVINFO_CMM + s_DEVINFO_ccm->device_used = DEVINFO_USED; + devinfo_check_add_device(s_DEVINFO_ccm); + #endif + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry_cnt--; + } while(retry_cnt > 0); + i++; + retry_cnt = retry_total; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + #ifdef SLT_DEVINFO_CMM + s_DEVINFO_ccm->device_used = DEVINFO_UNUSED; + devinfo_check_add_device(s_DEVINFO_ccm); + #endif + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + LOG_2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.shutter = 0x3D0; + imgsensor.gain = 0xe000; //0x100; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + #if 0 + else if (imgsensor.current_fps == imgsensor_info.cap2.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap2.pclk; + imgsensor.line_length = imgsensor_info.cap2.linelength; + imgsensor.frame_length = imgsensor_info.cap2.framelength; + imgsensor.min_frame_length = imgsensor_info.cap2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + #endif + else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps,imgsensor.pdaf_mode); + mdelay(100); + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("ihdr enable :%d\n", imgsensor.ihdr_en); + normal_video_setting(imgsensor.current_fps,imgsensor.pdaf_mode); + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 600; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 1200; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + if(imx258_type == IMX258_HDR_TYPE) + sensor_info->PDAF_Support = 2; /*0: NO PDAF, 1: PDAF Raw Data mode, 2:PDAF VC mode(HDR), 3:PDAF VC mode(Binning)*/ + else + sensor_info->PDAF_Support = 3; /*0: NO PDAF, 1: PDAF Raw Data mode, 2:PDAF VC mode(HDR), 3:PDAF VC mode(Binning)*/ + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + write_cmos_sensor(0x0601, 0x02); + } else { + write_cmos_sensor(0x0601, 0x00); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; +// unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SET_PD_BLOCK_INFO_T *PDAFinfo; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + SENSOR_VC_INFO_STRUCT *pvcinfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter((UINT16)*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_GET_PDAF_DATA: + LOG_INF("SENSOR_FEATURE_GET_PDAF_DATA\n"); + read_imx258_eeprom((kal_uint16 )(*feature_data),(char*)(uintptr_t)(*(feature_data+1)),(kal_uint32)(*(feature_data+2))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + LOG_INF("ihdr enable :%d\n", imgsensor.ihdr_en); + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + #if 1 + case SENSOR_FEATURE_GET_PDAF_INFO: + LOG_INF("SENSOR_FEATURE_GET_PDAF_INFO scenarioId:%llu\n", *feature_data); + PDAFinfo= (SET_PD_BLOCK_INFO_T *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if(imx258_type == IMX258_HDR_TYPE) + memcpy((void *)PDAFinfo,(void *)&imgsensor_pd_info,sizeof(SET_PD_BLOCK_INFO_T)); + else + memcpy((void *)PDAFinfo,(void *)&imgsensor_pd_info_Binning,sizeof(SET_PD_BLOCK_INFO_T)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + case MSDK_SCENARIO_ID_SLIM_VIDEO: + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + break; + } + break; + #endif + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + case SENSOR_FEATURE_GET_VC_INFO: + LOG_INF("SENSOR_FEATURE_GET_VC_INFO %d\n", (UINT16)*feature_data); + pvcinfo = (SENSOR_VC_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if(imx258_type == IMX258_HDR_TYPE) + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO[1],sizeof(SENSOR_VC_INFO_STRUCT)); + else + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO_Binning[1],sizeof(SENSOR_VC_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(imx258_type == IMX258_HDR_TYPE) + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO[2],sizeof(SENSOR_VC_INFO_STRUCT)); + else + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO_Binning[2],sizeof(SENSOR_VC_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + if(imx258_type == IMX258_HDR_TYPE) + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO[0],sizeof(SENSOR_VC_INFO_STRUCT)); + else + memcpy((void *)pvcinfo,(void *)&SENSOR_VC_INFO_Binning[0],sizeof(SENSOR_VC_INFO_STRUCT)); + break; + } + break; + /*PDAF CMD*/ + case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: + LOG_INF("SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY scenarioId:%llu\n", *feature_data); + //PDAF capacity enable or not, 2p8 only full size support PDAF + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 1; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + default: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + } + break; + case SENSOR_FEATURE_SET_PDAF: + LOG_INF("PDAF mode :%d\n", *feature_data_16); + imgsensor.pdaf_mode= *feature_data_16; + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 IMX258_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +/*UINT32 IMX258_MIPI_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)*/ + +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* IMX258_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258mipiraw_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..c3582446148570b04dbe4872cbc73be330bf18a6 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/imx258_mipi_raw/imx258mipiraw_Sensor.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * IMX258mipiraw_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _IMX258MIPIRAW_SENSOR_H +#define _IMX258MIPIRAW_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + kal_uint8 pdaf_mode; //ihdr enable or disable + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint32 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff + kal_uint32 i2c_speed; //i2c speed +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/kd_sensorlist.c b/drivers/misc/mediatek/imgsensor/src/mt6755/kd_sensorlist.c new file mode 100755 index 0000000000000000000000000000000000000000..63e0fddb052d654d4e1d9afbd88020f49fc47b0c --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/kd_sensorlist.c @@ -0,0 +1,4611 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include /* proc file use */ +#include +#include +#include +#include +#include +#include "kd_camera_hw.h" +#include "kd_camera_typedef.h" +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include +#endif +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#include +#endif + + +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_camera_feature.h" +#include "kd_imgsensor_errcode.h" + +#include "kd_sensorlist.h" + +#ifdef CONFIG_MTK_SMI_EXT +#include "mmdvfs_mgr.h" +#endif +#ifdef CONFIG_OF +/* device tree */ +#include +#include +#include +#endif +/* #define CONFIG_COMPAT */ +#ifdef CONFIG_COMPAT +/* 64 bit */ +#include +#include +#endif + +#ifndef CONFIG_MTK_CLKMGR +/*CCF*/ +struct clk *g_camclk_camtg_sel; +struct clk *g_camclk_scam_sel; +struct clk *g_camclk_univpll_d26; +struct clk *g_camclk_univpll2_d2; +#endif +/* kernel standard for PMIC*/ +#if !defined(CONFIG_MTK_LEGACY) +/* PMIC */ +#include +#endif + +#define PROC_CAMERA_INFO "driver/camera_info" +#define camera_info_size 128 +#define PDAF_DATA_SIZE 4096 +char mtk_ccm_name[camera_info_size] = {0}; +static unsigned int gDrvIndex = 0; +#ifdef CONFIG_MTK_SMI_EXT +static int current_mmsys_clk = MMSYS_CLK_MEDIUM; +#endif + +static DEFINE_SPINLOCK(kdsensor_drv_lock); + +/* Move these defines to kd_camera_hw.h, so they can be project-dependent //Jessy @2014/06/04 +#define SUPPORT_I2C_BUS_NUM1 0 +#define SUPPORT_I2C_BUS_NUM2 2 +*/ + +/* The following is to avoid build error of project: mt6755_fpga related //Jessy @2014/06/04 */ +#ifndef SUPPORT_I2C_BUS_NUM1 + #define SUPPORT_I2C_BUS_NUM1 0 +#endif +#ifndef SUPPORT_I2C_BUS_NUM2 + #define SUPPORT_I2C_BUS_NUM2 2 +#endif + +//Main2 support +#ifndef SUPPORT_I2C_BUS_NUM3 + #define SUPPORT_I2C_BUS_NUM3 SUPPORT_I2C_BUS_NUM2 +#endif + +#define CAMERA_HW_DRVNAME1 "kd_camera_hw" +#define CAMERA_HW_DRVNAME2 "kd_camera_hw_bus2" + +#if defined(CONFIG_MTK_LEGACY) +static struct i2c_board_info i2c_devs1 __initdata = {I2C_BOARD_INFO(CAMERA_HW_DRVNAME1, 0xfe>>1)}; +static struct i2c_board_info i2c_devs2 __initdata = {I2C_BOARD_INFO(CAMERA_HW_DRVNAME2, 0xfe>>1)}; +#endif + +#if !defined(CONFIG_MTK_LEGACY) + /*PMIC*/ + struct regulator *regVCAMA = NULL; + struct regulator *regVCAMD = NULL; + struct regulator *regVCAMIO = NULL; + struct regulator *regVCAMAF = NULL; + struct regulator *regSubVCAMA = NULL; + struct regulator *regSubVCAMD = NULL; + struct regulator *regMain2VCAMD = NULL; +#endif + +struct device *sensor_device = NULL; +#define SENSOR_WR32(addr, data) mt65xx_reg_sync_writel(data, addr) /* For 89 Only. // NEED_TUNING_BY_PROJECT */ +/* #define SENSOR_WR32(addr, data) iowrite32(data, addr) // For 89 Only. // NEED_TUNING_BY_PROJECT */ +#define SENSOR_RD32(addr) ioread32(addr) +/****************************************************************************** + * Debug configuration +******************************************************************************/ +#define PFX "[kd_sensorlist]" +#define PK_DBG_NONE(fmt, arg...) do {} while (0) +#define PK_DBG_FUNC(fmt, arg...) pr_debug(fmt, ##arg) +#define PK_INF(fmt, args...) pr_debug(PFX "[%s] " fmt, __FUNCTION__, ##args) + +#undef DEBUG_CAMERA_HW_K +/* #define DEBUG_CAMERA_HW_K */ +#ifdef DEBUG_CAMERA_HW_K +#define PK_DBG PK_DBG_FUNC +#define PK_ERR(fmt, arg...) pr_err(fmt, ##arg) +#define PK_XLOG_INFO(fmt, args...) \ + do { \ + pr_debug(fmt, ##args); \ + } while (0) +#else +#define PK_DBG(a, ...) +#define PK_ERR(fmt, arg...) pr_err(fmt, ##arg) +#define PK_XLOG_INFO(fmt, args...) + +#endif + +/******************************************************************************* +* Proifling +********************************************************************************/ +#define PROFILE 1 +#if PROFILE +static struct timeval tv1, tv2; +/******************************************************************************* +* +********************************************************************************/ +inline void KD_IMGSENSOR_PROFILE_INIT(void) +{ + do_gettimeofday(&tv1); +} + +/******************************************************************************* +* +********************************************************************************/ +inline void KD_IMGSENSOR_PROFILE(char *tag) +{ + unsigned long TimeIntervalUS; + + spin_lock(&kdsensor_drv_lock); + + do_gettimeofday(&tv2); + TimeIntervalUS = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec); + tv1 = tv2; + + spin_unlock(&kdsensor_drv_lock); + PK_DBG("[%s]Profile = %lu\n", tag, TimeIntervalUS); +} +#else +inline static void KD_IMGSENSOR_PROFILE_INIT(void) {} +inline static void KD_IMGSENSOR_PROFILE(char *tag) {} +#endif + +/******************************************************************************* +* +********************************************************************************/ +extern int kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On, char *mode_name); +/* extern ssize_t strobe_VDIrq(void); //cotta : add for high current solution */ + +/******************************************************************************* +* +********************************************************************************/ +#ifndef CONFIG_OF +static struct platform_device camerahw_platform_device = { + .name = "image_sensor", + .id = 0, + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + } +}; +#endif +struct platform_device* pCamerahw_platform_device; +static struct i2c_client *g_pstI2Cclient; +static struct i2c_client *g_pstI2Cclient2; + +/* 81 is used for V4L driver */ +static dev_t g_CAMERA_HWdevno = MKDEV(250, 0); +static dev_t g_CAMERA_HWdevno2; +static struct cdev *g_pCAMERA_HW_CharDrv; +static struct cdev *g_pCAMERA_HW_CharDrv2; +static struct class *sensor_class; +static struct class *sensor2_class; + +static atomic_t g_CamHWOpend; +static atomic_t g_CamHWOpend2; +static atomic_t g_CamHWOpening; +static atomic_t g_CamDrvOpenCnt; +static atomic_t g_CamDrvOpenCnt2; + +/* static u32 gCurrI2CBusEnableFlag = 0; */ +static u32 gI2CBusNum = SUPPORT_I2C_BUS_NUM1; + +#define SET_I2CBUS_FLAG(_x_) ((1<<_x_)|(gCurrI2CBusEnableFlag)) +#define CLEAN_I2CBUS_FLAG(_x_) ((~(1<<_x_))&(gCurrI2CBusEnableFlag)) + +static DEFINE_MUTEX(kdCam_Mutex); +static BOOL bSesnorVsyncFlag = FALSE; +static ACDK_KD_SENSOR_SYNC_STRUCT g_NewSensorExpGain = {128, 128, 128, 128, 1000, 640, 0xFF, 0xFF, 0xFF, 0}; + + +extern MULTI_SENSOR_FUNCTION_STRUCT2 kd_MultiSensorFunc; +static MULTI_SENSOR_FUNCTION_STRUCT2 *g_pSensorFunc = &kd_MultiSensorFunc; +/* static SENSOR_FUNCTION_STRUCT *g_pInvokeSensorFunc[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {NULL,NULL}; */ +/* static BOOL g_bEnableDriver[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {FALSE,FALSE}; */ +BOOL g_bEnableDriver[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {FALSE, FALSE}; +SENSOR_FUNCTION_STRUCT *g_pInvokeSensorFunc[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {NULL, NULL}; +/* static CAMERA_DUAL_CAMERA_SENSOR_ENUM g_invokeSocketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {DUAL_CAMERA_NONE_SENSOR,DUAL_CAMERA_NONE_SENSOR}; */ +/* static char g_invokeSensorNameStr[KDIMGSENSOR_MAX_INVOKE_DRIVERS][32] = {KDIMGSENSOR_NOSENSOR,KDIMGSENSOR_NOSENSOR}; */ +CAMERA_DUAL_CAMERA_SENSOR_ENUM g_invokeSocketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {DUAL_CAMERA_NONE_SENSOR, DUAL_CAMERA_NONE_SENSOR}; +char g_invokeSensorNameStr[KDIMGSENSOR_MAX_INVOKE_DRIVERS][32] = {KDIMGSENSOR_NOSENSOR, KDIMGSENSOR_NOSENSOR}; +/* static int g_SensorExistStatus[3]={0,0,0}; */ +static wait_queue_head_t kd_sensor_wait_queue; +bool setExpGainDoneFlag = 0; +static unsigned int g_CurrentSensorIdx; +static unsigned int g_IsSearchSensor; +/*============================================================================= + +=============================================================================*/ +/******************************************************************************* +* i2c relative start +* migrate new style i2c driver interfaces required by Kirby 20100827 +********************************************************************************/ +static const struct i2c_device_id CAMERA_HW_i2c_id[] = {{CAMERA_HW_DRVNAME1, 0}, {} }; +static const struct i2c_device_id CAMERA_HW_i2c_id2[] = {{CAMERA_HW_DRVNAME2, 0}, {} }; + + + +/******************************************************************************* +* general camera image sensor kernel driver +*******************************************************************************/ +UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList) +{ + if (NULL == ppSensorList) + { + PK_ERR("[kdGetSensorInitFuncList]ERROR: NULL ppSensorList\n"); + return 1; + } + *ppSensorList = &kdSensorList[0]; + return 0; +} /* kdGetSensorInitFuncList() */ + + +/******************************************************************************* +*iMultiReadReg +********************************************************************************/ +int iMultiReadReg(u16 a_u2Addr , u8 *a_puBuff , u16 i2cId, u8 number) +{ + int i4RetValue = 0; + char puReadCmd[2] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF)}; + + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + spin_lock(&kdsensor_drv_lock); + + g_pstI2Cclient->addr = (i2cId >> 1); + + spin_unlock(&kdsensor_drv_lock); + + /* */ + i4RetValue = i2c_master_send(g_pstI2Cclient, puReadCmd, 2); + if (i4RetValue != 2) { + PK_ERR("[CAMERA SENSOR] I2C send failed, addr = 0x%x, data = 0x%x !!\n", a_u2Addr, *a_puBuff); + return -1; + } + /* */ + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_puBuff, number); + if (i4RetValue != 1) { + PK_ERR("[CAMERA SENSOR] I2C read failed!!\n"); + return -1; + } + } + else { + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient2->addr = (i2cId >> 1); + spin_unlock(&kdsensor_drv_lock); + /* */ + i4RetValue = i2c_master_send(g_pstI2Cclient2, puReadCmd, 2); + if (i4RetValue != 2) { + PK_ERR("[CAMERA SENSOR] I2C send failed, addr = 0x%x, data = 0x%x !!\n", a_u2Addr, *a_puBuff); + return -1; + } + /* */ + i4RetValue = i2c_master_recv(g_pstI2Cclient2, (char *)a_puBuff, number); + if (i4RetValue != 1) { + PK_ERR("[CAMERA SENSOR] I2C read failed!!\n"); + return -1; + } + } + return 0; +} + + +/******************************************************************************* +* iReadReg +********************************************************************************/ +int iReadReg(u16 a_u2Addr , u8 *a_puBuff , u16 i2cId) +{ + int i4RetValue = 0; + char puReadCmd[2] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF)}; + + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + spin_lock(&kdsensor_drv_lock); + + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_DMA_FLAG); + + /* Remove i2c ack error log during search sensor */ + if (g_IsSearchSensor == 1) + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) | I2C_A_FILTER_MSG; + else + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_A_FILTER_MSG); + + + spin_unlock(&kdsensor_drv_lock); + + /* */ + i4RetValue = i2c_master_send(g_pstI2Cclient, puReadCmd, 2); + if (i4RetValue != 2) { + PK_ERR("[CAMERA SENSOR] I2C send failed, addr = 0x%x, data = 0x%x !!\n", a_u2Addr, *a_puBuff); + return -1; + } + /* */ + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_puBuff, 1); + if (i4RetValue != 1) { + PK_ERR("[CAMERA SENSOR] I2C read failed!!\n"); + return -1; + } + } + else { + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient2->addr = (i2cId >> 1); + + /* Remove i2c ack error log during search sensor */ + if (g_IsSearchSensor == 1) + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) | I2C_A_FILTER_MSG; + else + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag)&(~I2C_A_FILTER_MSG); + spin_unlock(&kdsensor_drv_lock); + /* */ + i4RetValue = i2c_master_send(g_pstI2Cclient2, puReadCmd, 2); + if (i4RetValue != 2) { + PK_ERR("[CAMERA SENSOR] I2C send failed, addr = 0x%x, data = 0x%x !!\n", a_u2Addr, *a_puBuff); + return -1; + } + /* */ + i4RetValue = i2c_master_recv(g_pstI2Cclient2, (char *)a_puBuff, 1); + if (i4RetValue != 1) { + PK_ERR("[CAMERA SENSOR] I2C read failed!!\n"); + return -1; + } + } + return 0; +} + +/******************************************************************************* +* iReadRegI2C +********************************************************************************/ +int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData, u16 i2cId) +{ + int i4RetValue = 0; + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_DMA_FLAG); + + /* Remove i2c ack error log during search sensor */ + /* PK_ERR("g_pstI2Cclient->ext_flag: %d", g_IsSearchSensor); */ + if (g_IsSearchSensor == 1) + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) | I2C_A_FILTER_MSG; + else + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_A_FILTER_MSG); + + spin_unlock(&kdsensor_drv_lock); + /* */ + i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData); + if (i4RetValue != a_sizeSendData) { + PK_ERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n", a_pSendData[0]); + return -1; + } + + i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_pRecvData, a_sizeRecvData); + if (i4RetValue != a_sizeRecvData) { + PK_ERR("[CAMERA SENSOR] I2C read failed!!\n"); + return -1; + } + } + else{ + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient2->addr = (i2cId >> 1); + + /* Remove i2c ack error log during search sensor */ + /* PK_ERR("g_pstI2Cclient2->ext_flag: %d", g_IsSearchSensor); */ + if (g_IsSearchSensor == 1) + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) | I2C_A_FILTER_MSG; + else + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag)&(~I2C_A_FILTER_MSG); + spin_unlock(&kdsensor_drv_lock); + i4RetValue = i2c_master_send(g_pstI2Cclient2, a_pSendData, a_sizeSendData); + if (i4RetValue != a_sizeSendData) { + PK_ERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n", a_pSendData[0]); + return -1; + } + + i4RetValue = i2c_master_recv(g_pstI2Cclient2, (char *)a_pRecvData, a_sizeRecvData); + if (i4RetValue != a_sizeRecvData) { + PK_ERR("[CAMERA SENSOR] I2C read failed!!\n"); + return -1; + } + } + return 0; +} + + +/******************************************************************************* +* iWriteReg +********************************************************************************/ +int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId) +{ + int i4RetValue = 0; + int u4Index = 0; + u8 *puDataInBytes = (u8 *)&a_u4Data; + int retry = 3; + + char puSendCmd[6] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF) , + 0 , 0 , 0 , 0}; + +/* PK_DBG("Addr : 0x%x,Val : 0x%x\n",a_u2Addr,a_u4Data); */ + + /* KD_IMGSENSOR_PROFILE_INIT(); */ + spin_lock(&kdsensor_drv_lock); + + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_DMA_FLAG); + } + else { + g_pstI2Cclient2->addr = (i2cId >> 1); + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag)&(~I2C_DMA_FLAG); + } + spin_unlock(&kdsensor_drv_lock); + + + if (a_u4Bytes > 2) + { + PK_ERR("[CAMERA SENSOR] exceed 2 bytes\n"); + return -1; + } + + if (a_u4Data >> (a_u4Bytes << 3)) + { + PK_DBG("[CAMERA SENSOR] warning!! some data is not sent!!\n"); + } + + for (u4Index = 0; u4Index < a_u4Bytes; u4Index += 1) + { + puSendCmd[(u4Index + 2)] = puDataInBytes[(a_u4Bytes - u4Index-1)]; + } + /* */ + do { + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + i4RetValue = i2c_master_send(g_pstI2Cclient, puSendCmd, (a_u4Bytes + 2)); + } + else { + i4RetValue = i2c_master_send(g_pstI2Cclient2, puSendCmd, (a_u4Bytes + 2)); + } + if (i4RetValue != (a_u4Bytes + 2)) { + PK_ERR("[CAMERA SENSOR] I2C send failed addr = 0x%x, data = 0x%x !!\n", a_u2Addr, a_u4Data); + i4RetValue = -1; + } + else { + i4RetValue = 0; + break; + } + uDELAY(50); + } while ((retry--) > 0); + /* KD_IMGSENSOR_PROFILE("iWriteReg"); */ + return i4RetValue; +} + +int kdSetI2CBusNum(u32 i2cBusNum) { + //Main2 Support + //if ((i2cBusNum != SUPPORT_I2C_BUS_NUM2) && (i2cBusNum != SUPPORT_I2C_BUS_NUM1)) { + if ((i2cBusNum != SUPPORT_I2C_BUS_NUM3) && (i2cBusNum != SUPPORT_I2C_BUS_NUM2) && (i2cBusNum != SUPPORT_I2C_BUS_NUM1)) { + PK_ERR("[kdSetI2CBusNum] i2c bus number is not correct(%d)\n", i2cBusNum); + return -1; + } + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = i2cBusNum; + spin_unlock(&kdsensor_drv_lock); + + return 0; +} + +void kdSetI2CSpeed(u32 i2cSpeed) +{ + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient->timing = i2cSpeed; + spin_unlock(&kdsensor_drv_lock); + } + else{ + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient2->timing = i2cSpeed; + spin_unlock(&kdsensor_drv_lock); + } + +} + +/******************************************************************************* +* kdReleaseI2CTriggerLock +********************************************************************************/ +int kdReleaseI2CTriggerLock(void) +{ + int ret = 0; + + /* ret = mt_wait4_i2c_complete(); */ + + /* if (ret < 0 ) { */ + /* PK_DBG("[error]wait i2c fail\n"); */ + /* } */ + + return ret; +} +/******************************************************************************* +* iBurstWriteReg +********************************************************************************/ +#define MAX_CMD_LEN 255 +int iBurstWriteReg_multi(u8 *pData, u32 bytes, u16 i2cId, u16 transfer_length) +{ + + dma_addr_t phyAddr; + u8 *buf = NULL; + u32 old_addr = 0; + int ret = 0; + int retry = 0; + + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + if (bytes > MAX_CMD_LEN) { + PK_ERR("[iBurstWriteReg] exceed the max write length\n"); + return 1; + } + + phyAddr = 0; + + buf = dma_alloc_coherent(&(pCamerahw_platform_device->dev) , bytes, (dma_addr_t *)&phyAddr, GFP_KERNEL); + + if (NULL == buf) { + PK_ERR("[iBurstWriteReg] Not enough memory\n"); + return -1; + } + memset(buf, 0, bytes); + memcpy(buf, pData, bytes); + /* PK_DBG("[iBurstWriteReg] bytes = %d, phy addr = 0x%x\n", bytes, phyAddr ); */ + PK_DBG("transfer_length %d\n",bytes == transfer_length ? transfer_length : (((bytes/transfer_length)<<16)|transfer_length)); + + old_addr = g_pstI2Cclient->addr; + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_POLLING_FLAG); + spin_unlock(&kdsensor_drv_lock); + + ret = 0; + retry = 3; + do { + ret = i2c_master_send(g_pstI2Cclient, (u8 *)((uintptr_t)phyAddr), + bytes == transfer_length ? transfer_length : ((bytes/transfer_length)<<16)|transfer_length); + retry--; + if ((ret&0xffff) != transfer_length) { + PK_ERR("Error sent I2C ret = %d\n", ret); + } + } while (((ret&0xffff) != transfer_length) && (retry > 0)); + + dma_free_coherent(&(pCamerahw_platform_device->dev), bytes, buf, phyAddr); + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient->addr = old_addr; + spin_unlock(&kdsensor_drv_lock); + } + else + { + if (bytes > MAX_CMD_LEN) { + PK_DBG("[iBurstWriteReg] exceed the max write length\n"); + return 1; + } + phyAddr = 0; + buf = dma_alloc_coherent(&(pCamerahw_platform_device->dev), bytes, (dma_addr_t *)&phyAddr, GFP_KERNEL); + + if (NULL == buf) { + PK_ERR("[iBurstWriteReg] Not enough memory\n"); + return -1; + } + memset(buf, 0, bytes); + memcpy(buf, pData, bytes); + /* PK_DBG("[iBurstWriteReg] bytes = %d, phy addr = 0x%x\n", bytes, phyAddr ); */ + + old_addr = g_pstI2Cclient2->addr; + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient2->addr = (i2cId >> 1); + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG); + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag)&(~I2C_POLLING_FLAG); + spin_unlock(&kdsensor_drv_lock); + ret = 0; + retry = 3; + do { + ret = i2c_master_send(g_pstI2Cclient2, (u8 *)((uintptr_t)phyAddr), + bytes == transfer_length ? transfer_length : ((bytes/transfer_length)<<16)|transfer_length); + retry--; + if ((ret&0xffff) != transfer_length) { + PK_ERR("Error sent I2C ret = %d\n", ret); + } + } while (((ret&0xffff) != transfer_length) && (retry > 0)); + + + dma_free_coherent(&(pCamerahw_platform_device->dev), bytes, buf, phyAddr); + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient2->addr = old_addr; + spin_unlock(&kdsensor_drv_lock); + } + return 0; +} + +int iBurstWriteReg(u8 *pData, u32 bytes, u16 i2cId) { + return iBurstWriteReg_multi(pData, bytes, i2cId, bytes); +} + + +/******************************************************************************* +* iMultiWriteReg +********************************************************************************/ + +int iMultiWriteReg(u8 *pData, u16 lens, u16 i2cId) +{ + int ret = 0; + + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)|(I2C_DMA_FLAG); + ret = i2c_master_send(g_pstI2Cclient, pData, lens); + } + else { + g_pstI2Cclient2->addr = (i2cId >> 1); + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag)|(I2C_DMA_FLAG); + ret = i2c_master_send(g_pstI2Cclient2, pData, lens); + } + + if (ret != lens) { + PK_ERR("Error sent I2C ret = %d\n", ret); + } + return 0; +} + + +/******************************************************************************* +* iWriteRegI2C +********************************************************************************/ +int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId) +{ + int i4RetValue = 0; + int retry = 3; + +/* PK_DBG("Addr : 0x%x,Val : 0x%x\n",a_u2Addr,a_u4Data); */ + + /* KD_IMGSENSOR_PROFILE_INIT(); */ + spin_lock(&kdsensor_drv_lock); + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + g_pstI2Cclient->addr = (i2cId >> 1); + g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag)&(~I2C_DMA_FLAG); + } + else { + g_pstI2Cclient2->addr = (i2cId >> 1); + g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag)&(~I2C_DMA_FLAG); + } + spin_unlock(&kdsensor_drv_lock); + /* */ + + do { + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData); + } + else { + i4RetValue = i2c_master_send(g_pstI2Cclient2, a_pSendData, a_sizeSendData); + } + if (i4RetValue != a_sizeSendData) { + PK_ERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x, Data = 0x%x\n", a_pSendData[0], a_pSendData[1]); + } + else { + break; + } + uDELAY(50); + } while ((retry--) > 0); + /* KD_IMGSENSOR_PROFILE("iWriteRegI2C"); */ + return 0; +} + +/******************************************************************************* +* sensor function adapter +********************************************************************************/ +#define KD_MULTI_FUNCTION_ENTRY() /* PK_XLOG_INFO("[%s]:E\n",__FUNCTION__) */ +#define KD_MULTI_FUNCTION_EXIT() /* PK_XLOG_INFO("[%s]:X\n",__FUNCTION__) */ +/* */ +MUINT32 +kdSetI2CSlaveID(MINT32 i, MUINT32 socketIdx, MUINT32 firstSet) { +unsigned long long FeaturePara[4]; +MUINT32 FeatureParaLen = 0; + FeaturePara[0] = socketIdx; + FeaturePara[1] = firstSet; + FeatureParaLen = sizeof(unsigned long long)*2; + return g_pInvokeSensorFunc[i]->SensorFeatureControl(SENSOR_FEATURE_SET_SLAVE_I2C_ID, (MUINT8 *)FeaturePara, (MUINT32 *)&FeatureParaLen); +} + +/* */ +MUINT32 +kd_MultiSensorOpen(void) +{ +MUINT32 ret = ERROR_NONE; +MINT32 i = 0; + + KD_MULTI_FUNCTION_ENTRY(); + /* from hear to tail */ + /* for ( i = KDIMGSENSOR_INVOKE_DRIVER_0 ; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS ; i++ ) { */ + /* from tail to head. */ + for (i = (KDIMGSENSOR_MAX_INVOKE_DRIVERS-1); i >= KDIMGSENSOR_INVOKE_DRIVER_0; i--) { + if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) { + if (0 != (g_CurrentSensorIdx & g_invokeSocketIdx[i])) { + /* turn on power */ + ret = kdCISModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_invokeSocketIdx[i], (char *)g_invokeSensorNameStr[i], true, CAMERA_HW_DRVNAME1); + if (ERROR_NONE != ret) { + PK_ERR("[%s]", __func__); + return ret; + } + /* wait for power stable */ + mDELAY(10); + KD_IMGSENSOR_PROFILE("kdModulePowerOn"); + +#if 0 + if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SENSOR_I2C_BUS_NUM[g_invokeSocketIdx[i]]; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum); + } +#else + if (DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM3; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum); + } + + else if (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM2; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum); + } + else { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM1; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum); + } +#endif + /* */ + /* set i2c slave ID */ + /* KD_SET_I2C_SLAVE_ID(i,g_invokeSocketIdx[i],IMGSENSOR_SET_I2C_ID_STATE); */ + /* */ + ret = g_pInvokeSensorFunc[i]->SensorOpen(); + if (ERROR_NONE != ret) { + kdCISModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_invokeSocketIdx[i], (char *)g_invokeSensorNameStr[i], false, CAMERA_HW_DRVNAME1); + PK_ERR("SensorOpen"); + return ret; + } + /* set i2c slave ID */ + /* SensorOpen() will reset i2c slave ID */ + /* KD_SET_I2C_SLAVE_ID(i,g_invokeSocketIdx[i],IMGSENSOR_SET_I2C_ID_FORCE); */ + } + } + } + KD_MULTI_FUNCTION_EXIT(); + return ERROR_NONE; +} +/* */ + +MUINT32 +kd_MultiSensorGetInfo( +MUINT32 *pScenarioId[2], +MSDK_SENSOR_INFO_STRUCT *pSensorInfo[2], +MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData[2]) +{ + MUINT32 ret = ERROR_NONE; + u32 i = 0; + + KD_MULTI_FUNCTION_ENTRY(); + for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { + if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) { + if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i]) { + ret = g_pInvokeSensorFunc[i]->SensorGetInfo((MSDK_SCENARIO_ID_ENUM)(*pScenarioId[0]), pSensorInfo[0], pSensorConfigData[0]); + } + else if ((DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) || (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i])) { + ret = g_pInvokeSensorFunc[i]->SensorGetInfo((MSDK_SCENARIO_ID_ENUM)(*pScenarioId[1]), pSensorInfo[1], pSensorConfigData[1]); + } + + if (ERROR_NONE != ret) { + PK_ERR("[%s]\n", __func__); + return ret; + } + + } + } + KD_MULTI_FUNCTION_EXIT(); + return ERROR_NONE; +} + +/* */ + +MUINT32 +kd_MultiSensorGetResolution( +MSDK_SENSOR_RESOLUTION_INFO_STRUCT *pSensorResolution[2]) +{ + MUINT32 ret = ERROR_NONE; + u32 i = 0; + KD_MULTI_FUNCTION_ENTRY(); + PK_INF("g_bEnableDriver[%d][%d]\n", g_bEnableDriver[0], g_bEnableDriver[1]); + for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { + if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) { + if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i]) { + ret = g_pInvokeSensorFunc[i]->SensorGetResolution(pSensorResolution[0]); + } + else if ((DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) || (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i])) { + ret = g_pInvokeSensorFunc[i]->SensorGetResolution(pSensorResolution[1]); + } + + if (ERROR_NONE != ret) { + PK_ERR("[%s]\n", __func__); + return ret; + } + } + } + + KD_MULTI_FUNCTION_EXIT(); + return ERROR_NONE; +} + + +/* */ +MUINT32 +kd_MultiSensorFeatureControl( +CAMERA_DUAL_CAMERA_SENSOR_ENUM InvokeCamera, +MSDK_SENSOR_FEATURE_ENUM FeatureId, +MUINT8 *pFeaturePara, +MUINT32 *pFeatureParaLen) +{ + MUINT32 ret = ERROR_NONE; + u32 i = 0; + KD_MULTI_FUNCTION_ENTRY(); + for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { + if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) { + + if (InvokeCamera == g_invokeSocketIdx[i]) { + +#if 0 + if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SENSOR_I2C_BUS_NUM[g_invokeSocketIdx[i]]; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum); + } +#else + //Main2 Support + if (DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM3; + spin_unlock(&kdsensor_drv_lock); + } + else if (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM2; + spin_unlock(&kdsensor_drv_lock); + /* PK_XLOG_INFO("kd_MultiSensorFeatureControl: switch I2C BUS2\n"); */ + } + else { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM1; + spin_unlock(&kdsensor_drv_lock); + /* PK_XLOG_INFO("kd_MultiSensorFeatureControl: switch I2C BUS1\n"); */ + } +#endif + /* */ + /* set i2c slave ID */ + /* KD_SET_I2C_SLAVE_ID(i,g_invokeSocketIdx[i],IMGSENSOR_SET_I2C_ID_STATE); */ + /* */ + ret = g_pInvokeSensorFunc[i]->SensorFeatureControl(FeatureId, pFeaturePara, pFeatureParaLen); + if (ERROR_NONE != ret) { + PK_ERR("[%s]\n", __func__); + return ret; + } + } + } + } + KD_MULTI_FUNCTION_EXIT(); + return ERROR_NONE; +} + +/* */ +MUINT32 +kd_MultiSensorControl( +CAMERA_DUAL_CAMERA_SENSOR_ENUM InvokeCamera, +MSDK_SCENARIO_ID_ENUM ScenarioId, +MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow, +MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData) +{ + MUINT32 ret = ERROR_NONE; + u32 i = 0; + KD_MULTI_FUNCTION_ENTRY(); + for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { + if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) { + if (InvokeCamera == g_invokeSocketIdx[i]) { + +#if 0 + if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SENSOR_I2C_BUS_NUM[g_invokeSocketIdx[i]]; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum); + } +#else + if (DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM3; + spin_unlock(&kdsensor_drv_lock); + } + else if (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM2; + spin_unlock(&kdsensor_drv_lock); + /* PK_XLOG_INFO("kd_MultiSensorControl: switch I2C BUS2\n"); */ + } + else { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM1; + spin_unlock(&kdsensor_drv_lock); + /* PK_XLOG_INFO("kd_MultiSensorControl: switch I2C BUS1\n"); */ + } +#endif + /* */ + /* set i2c slave ID */ + /* KD_SET_I2C_SLAVE_ID(i,g_invokeSocketIdx[i],IMGSENSOR_SET_I2C_ID_STATE); */ + /* */ + g_pInvokeSensorFunc[i]->ScenarioId = ScenarioId; + memcpy(&g_pInvokeSensorFunc[i]->imageWindow, pImageWindow, sizeof(ACDK_SENSOR_EXPOSURE_WINDOW_STRUCT)); + memcpy(&g_pInvokeSensorFunc[i]->sensorConfigData, pSensorConfigData, sizeof(ACDK_SENSOR_CONFIG_STRUCT)); + ret = g_pInvokeSensorFunc[i]->SensorControl(ScenarioId, pImageWindow, pSensorConfigData); + if (ERROR_NONE != ret) { + PK_ERR("ERR:SensorControl(), i =%d\n", i); + return ret; + } + } + } + } + KD_MULTI_FUNCTION_EXIT(); + + + /* js_tst FIXME */ + /* if (DUAL_CHANNEL_I2C) { */ + /* trigger dual channel i2c */ + /* } */ + /* else { */ + if (g_bEnableDriver[1]) { /* drive 2 or more sensor simultaneously */ + MUINT8 frameSync = 0; + MUINT32 frameSyncSize = 0; + kd_MultiSensorFeatureControl(g_invokeSocketIdx[1], SENSOR_FEATURE_SUSPEND, &frameSync, &frameSyncSize); + mDELAY(10); + kd_MultiSensorFeatureControl(g_invokeSocketIdx[1], SENSOR_FEATURE_RESUME, &frameSync, &frameSyncSize); + } + /* } */ + + + return ERROR_NONE; +} +/* */ +MUINT32 +kd_MultiSensorClose(void) +{ + MUINT32 ret = ERROR_NONE; + u32 i = 0; + KD_MULTI_FUNCTION_ENTRY(); + for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { + if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) { + if (0 != (g_CurrentSensorIdx & g_invokeSocketIdx[i])) { +#if 0 + if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SENSOR_I2C_BUS_NUM[g_invokeSocketIdx[i]]; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum); + } +#else + + + if (DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM3; + spin_unlock(&kdsensor_drv_lock); + } + else if (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM2; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorClose: switch I2C BUS2\n"); + } + else { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM1; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorClose: switch I2C BUS1\n"); + } +#endif + ret = g_pInvokeSensorFunc[i]->SensorClose(); + + /* Change the close power flow to close power in this function & */ + /* directly call kdCISModulePowerOn to close the specific sensor */ + /* The original flow will close all opened sensors at once */ + kdCISModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_invokeSocketIdx[i], (char *)g_invokeSensorNameStr[i], false, CAMERA_HW_DRVNAME1); + + if (ERROR_NONE != ret) { + PK_ERR("[%s]", __func__); + return ret; + } + } + } + } + KD_MULTI_FUNCTION_EXIT(); + return ERROR_NONE; +} +/* */ +MULTI_SENSOR_FUNCTION_STRUCT2 kd_MultiSensorFunc = +{ + kd_MultiSensorOpen, + kd_MultiSensorGetInfo, + kd_MultiSensorGetResolution, + kd_MultiSensorFeatureControl, + kd_MultiSensorControl, + kd_MultiSensorClose +}; + + +/******************************************************************************* +* kdModulePowerOn +********************************************************************************/ +int +kdModulePowerOn( +CAMERA_DUAL_CAMERA_SENSOR_ENUM socketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS], +char sensorNameStr[KDIMGSENSOR_MAX_INVOKE_DRIVERS][32], +BOOL On, +char *mode_name) +{ +MINT32 ret = ERROR_NONE; +u32 i = 0; + + for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { + if (g_bEnableDriver[i]) { + /* PK_XLOG_INFO("[%s][%d][%d][%s][%s]\r\n",__FUNCTION__,g_bEnableDriver[i],socketIdx[i],sensorNameStr[i],mode_name); */ + ret = kdCISModulePowerOn(socketIdx[i], sensorNameStr[i], On, mode_name); + if (ERROR_NONE != ret) { + PK_ERR("[%s]", __func__); + return ret; + } + } + } + return ERROR_NONE; +} + +/******************************************************************************* +* kdSetDriver +********************************************************************************/ +int kdSetDriver(unsigned int *pDrvIndex) +{ + ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL; + u32 drvIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0, 0}; + u32 i; + + /* set driver for MAIN or SUB sensor */ + PK_INF("pDrvIndex:0x%08x/0x%08x\n", pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_0], pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_1]); + gDrvIndex = pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_0]; + + if (0 != kdGetSensorInitFuncList(&pSensorList)) + { + PK_ERR("ERROR:kdGetSensorInitFuncList()\n"); + return -EIO; + } + + for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { + /* */ + spin_lock(&kdsensor_drv_lock); + g_bEnableDriver[i] = FALSE; + g_invokeSocketIdx[i] = (CAMERA_DUAL_CAMERA_SENSOR_ENUM)((pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_MSB)>>KDIMGSENSOR_DUAL_SHIFT); + spin_unlock(&kdsensor_drv_lock); + drvIdx[i] = (pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_LSB); + /* */ + if (DUAL_CAMERA_NONE_SENSOR == g_invokeSocketIdx[i]) { continue; } +#if 0 + if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SENSOR_I2C_BUS_NUM[g_invokeSocketIdx[i]]; + spin_unlock(&kdsensor_drv_lock); + PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum); + } +#else + + if (DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM3; + spin_unlock(&kdsensor_drv_lock); + } + else if (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i]) { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM2; + spin_unlock(&kdsensor_drv_lock); + /* PK_XLOG_INFO("kdSetDriver: switch I2C BUS2\n"); */ + } + else { + spin_lock(&kdsensor_drv_lock); + gI2CBusNum = SUPPORT_I2C_BUS_NUM1; + spin_unlock(&kdsensor_drv_lock); + /* PK_XLOG_INFO("kdSetDriver: switch I2C BUS1\n"); */ + } +#endif + PK_XLOG_INFO("[kdSetDriver]g_invokeSocketIdx[%d] = %d\n", i, g_invokeSocketIdx[i]); + PK_XLOG_INFO("[kdSetDriver]drvIdx[%d] = %d\n", i, drvIdx[i]); + /* */ + if (MAX_NUM_OF_SUPPORT_SENSOR > drvIdx[i]) { + if (NULL == pSensorList[drvIdx[i]].SensorInit) { + PK_ERR("ERROR:kdSetDriver()\n"); + return -EIO; + } + + pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]); + if (NULL == g_pInvokeSensorFunc[i]) { + PK_ERR("ERROR:NULL g_pSensorFunc[%d]\n", i); + return -EIO; + } + /* */ + spin_lock(&kdsensor_drv_lock); + g_bEnableDriver[i] = TRUE; + spin_unlock(&kdsensor_drv_lock); + /* get sensor name */ + memcpy((char *)g_invokeSensorNameStr[i], (char *)pSensorList[drvIdx[i]].drvname, sizeof(pSensorList[drvIdx[i]].drvname)); + /* return sensor ID */ + /* pDrvIndex[0] = (unsigned int)pSensorList[drvIdx].SensorId; */ + PK_XLOG_INFO("[kdSetDriver] :[%d][%d][%d][%s][%lu]\n", i, g_bEnableDriver[i], g_invokeSocketIdx[i], g_invokeSensorNameStr[i], sizeof(pSensorList[drvIdx[i]].drvname)); + } + } + return 0; +} + +int kdSetCurrentSensorIdx(unsigned int idx) +{ + g_CurrentSensorIdx = idx; + return 0; +} +/******************************************************************************* +* kdGetSocketPostion +********************************************************************************/ +int +kdGetSocketPostion(unsigned int *pSocketPos) { + PK_XLOG_INFO("[%s][%d] \r\n", __func__, *pSocketPos); + switch (*pSocketPos) { + case DUAL_CAMERA_MAIN_SENSOR: + /* ->this is a HW layout dependent */ + /* ToDo */ + *pSocketPos = IMGSENSOR_SOCKET_POS_RIGHT; + break; + case DUAL_CAMERA_MAIN_2_SENSOR: + *pSocketPos = IMGSENSOR_SOCKET_POS_LEFT; + break; + default: + case DUAL_CAMERA_SUB_SENSOR: + *pSocketPos = IMGSENSOR_SOCKET_POS_NONE; + break; + } + return 0; +} +/******************************************************************************* +* kdSetSensorSyncFlag +********************************************************************************/ +int kdSetSensorSyncFlag(BOOL bSensorSync) +{ + spin_lock(&kdsensor_drv_lock); + + bSesnorVsyncFlag = bSensorSync; + spin_unlock(&kdsensor_drv_lock); +/* PK_DBG("[Sensor] kdSetSensorSyncFlag:%d\n", bSesnorVsyncFlag); */ + + /* strobe_VDIrq(); //cotta : added for high current solution */ + + return 0; +} + +/******************************************************************************* +* kdCheckSensorPowerOn +********************************************************************************/ +int kdCheckSensorPowerOn(void) +{ + if (atomic_read(&g_CamHWOpening) == 0) { + return 0; + } + else {/* sensor power on */ + return 1; + } +} + +/******************************************************************************* +* kdSensorSyncFunctionPtr +********************************************************************************/ +/* ToDo: How to separate main/main2....who is caller? */ +int kdSensorSyncFunctionPtr(void) +{ + unsigned int FeatureParaLen = 0; + /* PK_DBG("[Sensor] kdSensorSyncFunctionPtr1:%d %d %d\n", g_NewSensorExpGain.uSensorExpDelayFrame, g_NewSensorExpGain.uSensorGainDelayFrame, g_NewSensorExpGain.uISPGainDelayFrame); */ + mutex_lock(&kdCam_Mutex); + if (NULL == g_pSensorFunc) { + PK_ERR("ERROR:NULL g_pSensorFunc\n"); + mutex_unlock(&kdCam_Mutex); + return -EIO; + } + /* PK_DBG("[Sensor] Exposure time:%d, Gain = %d\n", g_NewSensorExpGain.u2SensorNewExpTime,g_NewSensorExpGain.u2SensorNewGain ); */ + /* exposure time */ + if (g_NewSensorExpGain.uSensorExpDelayFrame == 0) { + FeatureParaLen = 2; + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_MAIN_SENSOR, SENSOR_FEATURE_SET_ESHUTTER, (unsigned char *)&g_NewSensorExpGain.u2SensorNewExpTime, (unsigned int *) &FeatureParaLen); + g_NewSensorExpGain.uSensorExpDelayFrame = 0xFF; /* disable */ + } + else if (g_NewSensorExpGain.uSensorExpDelayFrame != 0xFF) { + g_NewSensorExpGain.uSensorExpDelayFrame--; + } + + /* exposure gain */ + if (g_NewSensorExpGain.uSensorGainDelayFrame == 0) { + FeatureParaLen = 2; + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_MAIN_SENSOR, SENSOR_FEATURE_SET_GAIN, (unsigned char *)&g_NewSensorExpGain.u2SensorNewGain, (unsigned int *) &FeatureParaLen); + g_NewSensorExpGain.uSensorGainDelayFrame = 0xFF; /* disable */ + } + else if (g_NewSensorExpGain.uSensorGainDelayFrame != 0xFF) { + g_NewSensorExpGain.uSensorGainDelayFrame--; + } + + /* if the delay frame is 0 or 0xFF, stop to count */ + if ((g_NewSensorExpGain.uISPGainDelayFrame != 0xFF) && (g_NewSensorExpGain.uISPGainDelayFrame != 0)) { + spin_lock(&kdsensor_drv_lock); + g_NewSensorExpGain.uISPGainDelayFrame--; + spin_unlock(&kdsensor_drv_lock); + } + mutex_unlock(&kdCam_Mutex); + return 0; +} + +/******************************************************************************* +* kdGetRawGainInfo +********************************************************************************/ +int kdGetRawGainInfoPtr(UINT16 *pRAWGain) +{ + *pRAWGain = 0x00; + *(pRAWGain+1) = 0x00; + *(pRAWGain+2) = 0x00; + *(pRAWGain+3) = 0x00; + + if (g_NewSensorExpGain.uISPGainDelayFrame == 0) { /* synchronize the isp gain */ + *pRAWGain = g_NewSensorExpGain.u2ISPNewRGain; + *(pRAWGain+1) = g_NewSensorExpGain.u2ISPNewGrGain; + *(pRAWGain+2) = g_NewSensorExpGain.u2ISPNewGbGain; + *(pRAWGain+3) = g_NewSensorExpGain.u2ISPNewBGain; +/* PK_DBG("[Sensor] ISP Gain:%d\n", g_NewSensorExpGain.u2ISPNewRGain, g_NewSensorExpGain.u2ISPNewGrGain, */ +/* g_NewSensorExpGain.u2ISPNewGbGain, g_NewSensorExpGain.u2ISPNewBGain); */ + spin_lock(&kdsensor_drv_lock); + g_NewSensorExpGain.uISPGainDelayFrame = 0xFF; /* disable */ + spin_unlock(&kdsensor_drv_lock); + } + + return 0; +} + + + + +int kdSetExpGain(CAMERA_DUAL_CAMERA_SENSOR_ENUM InvokeCamera) +{ + unsigned int FeatureParaLen = 0; + PK_DBG("[kd_sensorlist]enter kdSetExpGain\n"); + if (NULL == g_pSensorFunc) { + PK_ERR("ERROR:NULL g_pSensorFunc\n"); + + return -EIO; + } + + setExpGainDoneFlag = 0; + FeatureParaLen = 2; + g_pSensorFunc->SensorFeatureControl(InvokeCamera, SENSOR_FEATURE_SET_ESHUTTER, (unsigned char *)&g_NewSensorExpGain.u2SensorNewExpTime, (unsigned int *) &FeatureParaLen); + g_pSensorFunc->SensorFeatureControl(InvokeCamera, SENSOR_FEATURE_SET_GAIN, (unsigned char *)&g_NewSensorExpGain.u2SensorNewGain, (unsigned int *) &FeatureParaLen); + + setExpGainDoneFlag = 1; + PK_DBG("[kd_sensorlist]before wake_up_interruptible\n"); + wake_up_interruptible(&kd_sensor_wait_queue); + PK_DBG("[kd_sensorlist]after wake_up_interruptible\n"); + + return 0; /* No error. */ + +} + +/******************************************************************************* +* +********************************************************************************/ +static UINT32 ms_to_jiffies(MUINT32 ms) +{ + return ((ms * HZ + 512) >> 10); +} + + +int kdSensorSetExpGainWaitDone(int *ptime) +{ + int timeout; + PK_DBG("[kd_sensorlist]enter kdSensorSetExpGainWaitDone: time: %d\n", *ptime); + timeout = wait_event_interruptible_timeout( + kd_sensor_wait_queue, + (setExpGainDoneFlag & 1), + ms_to_jiffies(*ptime)); + + PK_DBG("[kd_sensorlist]after wait_event_interruptible_timeout\n"); + if (timeout == 0) { + PK_ERR("[kd_sensorlist] kdSensorSetExpGainWait: timeout=%d\n", *ptime); + + return -EAGAIN; + } + + return 0; /* No error. */ + +} + + + + +/******************************************************************************* +* adopt_CAMERA_HW_Open +********************************************************************************/ +inline static int adopt_CAMERA_HW_Open(void) +{ + UINT32 err = 0; + + KD_IMGSENSOR_PROFILE_INIT(); + /* power on sensor */ + /* if (atomic_read(&g_CamHWOpend) == 0 ) { */ + /* move into SensorOpen() for 2on1 driver */ + /* turn on power */ + /* kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM*) g_invokeSocketIdx, g_invokeSensorNameStr,true, CAMERA_HW_DRVNAME); */ + /* wait for power stable */ + /* mDELAY(10); */ + /* KD_IMGSENSOR_PROFILE("kdModulePowerOn"); */ + /* */ + if (g_pSensorFunc) { + err = g_pSensorFunc->SensorOpen(); + if (ERROR_NONE != err) { + /*Multiopen fail would close power.*/ + //kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *) g_invokeSocketIdx, g_invokeSensorNameStr, false, CAMERA_HW_DRVNAME1); + PK_ERR("ERROR:SensorOpen(), turn off power\n"); + } + } + else { + PK_DBG(" ERROR:NULL g_pSensorFunc\n"); + } + + KD_IMGSENSOR_PROFILE("SensorOpen"); + /* } */ + /* else { */ + /* PK_ERR("adopt_CAMERA_HW_Open Fail, g_CamHWOpend = %d\n ",atomic_read(&g_CamHWOpend) ); */ + /* } */ + + /* if (err == 0 ) { */ + /* atomic_set(&g_CamHWOpend, 1); */ + + /* } */ + + return err ? -EIO:err; +} /* adopt_CAMERA_HW_Open() */ + +/******************************************************************************* +* adopt_CAMERA_HW_CheckIsAlive +********************************************************************************/ +inline static int adopt_CAMERA_HW_CheckIsAlive(void) +{ + UINT32 err = 0; + UINT32 err1 = 0; + UINT32 i = 0; + MUINT32 sensorID = 0; + MUINT32 retLen = 0; + + KD_IMGSENSOR_PROFILE_INIT(); + /* power on sensor */ + kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *)g_invokeSocketIdx, g_invokeSensorNameStr, true, CAMERA_HW_DRVNAME1); + /* wait for power stable */ + mDELAY(10); + KD_IMGSENSOR_PROFILE("kdModulePowerOn"); + + g_CurrentSensorIdx = 0; + g_IsSearchSensor = 1; + if(gDrvIndex == 0x10000) + { + memset(mtk_ccm_name,0,camera_info_size); + } + + if (g_pSensorFunc) { + for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { + if (DUAL_CAMERA_NONE_SENSOR != g_invokeSocketIdx[i]) { + err = g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i], SENSOR_FEATURE_CHECK_SENSOR_ID, (MUINT8 *)&sensorID, &retLen); + if (sensorID == 0) { /* not implement this feature ID */ + PK_DBG(" Not implement!!, use old open function to check\n"); + err = ERROR_SENSOR_CONNECT_FAIL; + } + else if (sensorID == 0xFFFFFFFF) { /* fail to open the sensor */ + PK_DBG(" No Sensor Found"); + err = ERROR_SENSOR_CONNECT_FAIL; + } + else { + + PK_INF(" Sensor found ID = 0x%x\n", sensorID); + snprintf(mtk_ccm_name,sizeof(mtk_ccm_name),"%s CAM[%d]:%s;",mtk_ccm_name,g_invokeSocketIdx[i],g_invokeSensorNameStr[i]); + err = ERROR_NONE; + } + if (ERROR_NONE != err) + { + PK_DBG("ERROR:adopt_CAMERA_HW_CheckIsAlive(), No imgsensor alive\n"); + } +/* Vanzo:maxiaojun on: Mon, 26 Aug 2013 17:04:18 +0800 + * board device name support. + */ +#ifdef VANZO_DEVICE_NAME_SUPPORT + { + extern void v_set_dev_name(int id, char *name); + if(ERROR_NONE == err){ + if(DUAL_CAMERA_MAIN_SENSOR==g_invokeSocketIdx[i]){ + v_set_dev_name(3, (char *)g_invokeSensorNameStr[i]); + }else if(DUAL_CAMERA_SUB_SENSOR==g_invokeSocketIdx[i]){ + v_set_dev_name(4, (char *)g_invokeSensorNameStr[i]); + } + } + } +#endif +// End of Vanzo:maxiaojun + + } + } + } + else { + PK_DBG("ERROR:NULL g_pSensorFunc\n"); + } + + /* reset sensor state after power off */ + if (g_pSensorFunc) + err1 = g_pSensorFunc->SensorClose(); + if (ERROR_NONE != err1) { + PK_DBG("SensorClose\n"); + } + /* */ + kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *)g_invokeSocketIdx, g_invokeSensorNameStr, false, CAMERA_HW_DRVNAME1); + /* */ + KD_IMGSENSOR_PROFILE("CheckIsAlive"); + + g_IsSearchSensor = 0; + + return err ? -EIO:err; +} /* adopt_CAMERA_HW_Open() */ + + +/******************************************************************************* +* adopt_CAMERA_HW_GetResolution +********************************************************************************/ +inline static int adopt_CAMERA_HW_GetResolution(void *pBuf) +{ + /* ToDo: remove print */ + ACDK_SENSOR_PRESOLUTION_STRUCT *pBufResolution = (ACDK_SENSOR_PRESOLUTION_STRUCT *)pBuf; + ACDK_SENSOR_RESOLUTION_INFO_STRUCT* pRes[2] = { NULL, NULL }; + PK_XLOG_INFO("[CAMERA_HW] adopt_CAMERA_HW_GetResolution, pBuf: %p\n", pBuf); + pRes[0] = (ACDK_SENSOR_RESOLUTION_INFO_STRUCT* )kmalloc(sizeof(MSDK_SENSOR_RESOLUTION_INFO_STRUCT), GFP_KERNEL); + if (pRes[0] == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + return -ENOMEM; + } + pRes[1] = (ACDK_SENSOR_RESOLUTION_INFO_STRUCT* )kmalloc(sizeof(MSDK_SENSOR_RESOLUTION_INFO_STRUCT), GFP_KERNEL); + if (pRes[1] == NULL) { + kfree(pRes[0]); + PK_ERR(" ioctl allocate mem failed\n"); + return -ENOMEM; + } + + + if (g_pSensorFunc) { + g_pSensorFunc->SensorGetResolution(pRes); + if (copy_to_user((void __user *) (pBufResolution->pResolution[0]) , (void *)pRes[0] , sizeof(MSDK_SENSOR_RESOLUTION_INFO_STRUCT))) { + PK_ERR("copy to user failed\n"); + } + if (copy_to_user((void __user *) (pBufResolution->pResolution[1]) , (void *)pRes[1] , sizeof(MSDK_SENSOR_RESOLUTION_INFO_STRUCT))) { + PK_ERR("copy to user failed\n"); + } + } + else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + if (pRes[0] != NULL) { + kfree(pRes[0]); + } + if (pRes[1] != NULL) { + kfree(pRes[1]); + } + + return 0; +} /* adopt_CAMERA_HW_GetResolution() */ + + +/******************************************************************************* +* adopt_CAMERA_HW_GetInfo +********************************************************************************/ +inline static int adopt_CAMERA_HW_GetInfo(void *pBuf) +{ + ACDK_SENSOR_GETINFO_STRUCT *pSensorGetInfo = (ACDK_SENSOR_GETINFO_STRUCT *)pBuf; + MSDK_SENSOR_INFO_STRUCT *pInfo[2]; + MSDK_SENSOR_CONFIG_STRUCT *pConfig[2]; + MUINT32 *pScenarioId[2]; + u32 i,j = 0; + + for (i = 0; i < 2; i++) { + pInfo[i] = NULL; + pConfig[i] = NULL; + pScenarioId[i] = &(pSensorGetInfo->ScenarioId[i]); + } + + + pInfo[0] = kmalloc(sizeof(MSDK_SENSOR_INFO_STRUCT), GFP_KERNEL); + pInfo[1] = kmalloc(sizeof(MSDK_SENSOR_INFO_STRUCT), GFP_KERNEL); + pConfig[0] = kmalloc(sizeof(MSDK_SENSOR_CONFIG_STRUCT), GFP_KERNEL); + pConfig[1] = kmalloc(sizeof(MSDK_SENSOR_CONFIG_STRUCT), GFP_KERNEL); + + if (pInfo[0] == NULL || pInfo[1] == NULL || pConfig[0] == NULL || pConfig[1] == NULL){ + PK_ERR(" ioctl allocate mem failed\n"); + return -ENOMEM; + } + + memset(pInfo[0], 0, sizeof(MSDK_SENSOR_INFO_STRUCT)); + memset(pInfo[1], 0, sizeof(MSDK_SENSOR_INFO_STRUCT)); + memset(pConfig[0], 0, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + memset(pConfig[1], 0, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + + if (NULL == pSensorGetInfo) { + PK_DBG("[CAMERA_HW] NULL arg.\n"); + return -EFAULT; + } + + if ((NULL == pSensorGetInfo->pInfo[0]) || (NULL == pSensorGetInfo->pInfo[1]) || + (NULL == pSensorGetInfo->pConfig[0]) || (NULL == pSensorGetInfo->pConfig[1])) { + PK_DBG("[CAMERA_HW] NULL arg.\n"); + return -EFAULT; + } + + if (g_pSensorFunc) { + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo, pConfig); + } + else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + + + for (i = 0; i < 2; i++) { + /* SenorInfo */ + if (copy_to_user((void __user *)(pSensorGetInfo->pInfo[i]), (void *)pInfo[i] , sizeof(MSDK_SENSOR_INFO_STRUCT))) { + PK_DBG("[CAMERA_HW][info] ioctl copy to user failed\n"); + for (j = 0; j < 2; j++) { + if (pInfo[j] != NULL) kfree(pInfo[j]); + if (pConfig[j] != NULL) kfree(pConfig[j]); + pInfo[j] = NULL; + pConfig[j] = NULL; + } + return -EFAULT; + } + + /* SensorConfig */ + if (copy_to_user((void __user *) (pSensorGetInfo->pConfig[i]) , (void *)pConfig[i] , sizeof(MSDK_SENSOR_CONFIG_STRUCT))) { + PK_DBG("[CAMERA_HW][config] ioctl copy to user failed\n"); + for (j = 0; j < 2; j++) { + if (pInfo[j] != NULL) kfree(pInfo[j]); + if (pConfig[j] != NULL) kfree(pConfig[j]); + pInfo[j] = NULL; + pConfig[j] = NULL; + } + return -EFAULT; + } + } + for (j = 0; j < 2; j++) { + if (pInfo[j] != NULL) kfree(pInfo[j]); + if (pConfig[j] != NULL) kfree(pConfig[j]); + pInfo[j] = NULL; + pConfig[j] = NULL; + } + + return 0; +} /* adopt_CAMERA_HW_GetInfo() */ + +/******************************************************************************* +* adopt_CAMERA_HW_GetInfo +********************************************************************************/ +MSDK_SENSOR_INFO_STRUCT ginfo[2]; +MSDK_SENSOR_INFO_STRUCT ginfo1[2]; +MSDK_SENSOR_INFO_STRUCT ginfo2[2]; +MSDK_SENSOR_INFO_STRUCT ginfo3[2]; +MSDK_SENSOR_INFO_STRUCT ginfo4[2]; +/* adopt_CAMERA_HW_GetInfo() */ +inline static int adopt_CAMERA_HW_GetInfo2(void *pBuf) +{ + IMAGESENSOR_GETINFO_STRUCT *pSensorGetInfo = (IMAGESENSOR_GETINFO_STRUCT *)pBuf; + ACDK_SENSOR_INFO2_STRUCT *pSensorInfo = NULL;//{0}; + MUINT32 IDNum = 0; + MSDK_SENSOR_INFO_STRUCT *pInfo[2] = {NULL,NULL}; + MSDK_SENSOR_CONFIG_STRUCT *pConfig[2] = {NULL,NULL}; + MSDK_SENSOR_INFO_STRUCT *pInfo1[2] = {NULL,NULL}; + MSDK_SENSOR_CONFIG_STRUCT *pConfig1[2]= {NULL,NULL}; + MSDK_SENSOR_INFO_STRUCT *pInfo2[2] = {NULL,NULL}; + MSDK_SENSOR_CONFIG_STRUCT *pConfig2[2]= {NULL,NULL}; + MSDK_SENSOR_INFO_STRUCT *pInfo3[2] = {NULL,NULL}; + MSDK_SENSOR_CONFIG_STRUCT *pConfig3[2] = {NULL,NULL}; + MSDK_SENSOR_INFO_STRUCT *pInfo4[2] = {NULL,NULL}; + MSDK_SENSOR_CONFIG_STRUCT *pConfig4[2]= {NULL,NULL}; + MSDK_SENSOR_RESOLUTION_INFO_STRUCT *psensorResolution[2] = {NULL,NULL}; + + MUINT32 ScenarioId[2], *pScenarioId[2]; + u32 i = 0; + PK_DBG("[adopt_CAMERA_HW_GetInfo2]Entry\n"); + + + if (NULL == pSensorGetInfo) { + PK_DBG("[CAMERA_HW] NULL arg.\n"); + return -EFAULT; + } + if (NULL == g_pSensorFunc) { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + return -EFAULT; + } + + for (i = 0; i < 2; i++) { + pInfo[i] = &ginfo[i]; + pInfo[i]->SensorHorFOV = 0; + pInfo[i]->SensorVerFOV = 0; + pConfig[i] = kmalloc(sizeof(MSDK_SENSOR_CONFIG_STRUCT), GFP_KERNEL); + pInfo1[i] = &ginfo1[i]; + pConfig1[i] = kmalloc(sizeof(MSDK_SENSOR_CONFIG_STRUCT), GFP_KERNEL); + pInfo2[i] = &ginfo2[i]; + pConfig2[i] = kmalloc(sizeof(MSDK_SENSOR_CONFIG_STRUCT), GFP_KERNEL); + pInfo3[i] = &ginfo3[i]; + pConfig3[i] = kmalloc(sizeof(MSDK_SENSOR_CONFIG_STRUCT), GFP_KERNEL); + pInfo4[i] = &ginfo4[i]; + pConfig4[i] = kmalloc(sizeof(MSDK_SENSOR_CONFIG_STRUCT), GFP_KERNEL); + psensorResolution[i] = kmalloc(sizeof(MSDK_SENSOR_RESOLUTION_INFO_STRUCT), GFP_KERNEL); + pScenarioId[i] = &ScenarioId[i]; + } + pSensorInfo = kmalloc(sizeof(ACDK_SENSOR_INFO2_STRUCT), GFP_KERNEL); + + if (pConfig[0] == NULL || pConfig[1] == NULL || pConfig1[0] == NULL || pConfig1[1] == NULL || + pConfig2[0] == NULL || pConfig2[1] == NULL || pConfig3[0] == NULL || pConfig3[1] == NULL || + pConfig4[0] == NULL || pConfig4[1] == NULL || pSensorInfo ==NULL || + psensorResolution[0] == NULL || psensorResolution[1]==NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + for (i = 0; i < 2; i++) { + if(pConfig[i] != NULL) kfree(pConfig[i]); + if(pConfig1[i] != NULL) kfree(pConfig1[i]); + if(pConfig2[i] != NULL) kfree(pConfig2[i]); + if(pConfig3[i] != NULL) kfree(pConfig3[i]); + if(pConfig4[i] != NULL) kfree(pConfig4[i]); + if(psensorResolution[i] != NULL) kfree(psensorResolution[i]); + pConfig[i] = NULL; + pConfig1[i] = NULL; + pConfig2[i] = NULL; + pConfig3[i] = NULL; + pConfig4[i] = NULL; + psensorResolution[i] = NULL; + } + kfree(pSensorInfo); + pSensorInfo = NULL; + return -ENOMEM; + } + + PK_DBG("[CAMERA_HW][Resolution] %p\n", pSensorGetInfo->pSensorResolution); + + /* TO get preview value */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_CAMERA_PREVIEW; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo, pConfig); + /* */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo1, pConfig1); + /* */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_VIDEO_PREVIEW; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo2, pConfig2); + /* */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo3, pConfig3); + /* */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_SLIM_VIDEO; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo4, pConfig4); + /* To set sensor information */ + if (DUAL_CAMERA_MAIN_SENSOR == pSensorGetInfo->SensorId) { + IDNum = 0; + } + else + { + IDNum = 1; + } + /* Basic information */ + pSensorInfo->SensorPreviewResolutionX = pInfo[IDNum]->SensorPreviewResolutionX; + pSensorInfo->SensorPreviewResolutionY = pInfo[IDNum]->SensorPreviewResolutionY; + pSensorInfo->SensorFullResolutionX = pInfo[IDNum]->SensorFullResolutionX; + pSensorInfo->SensorFullResolutionY = pInfo[IDNum]->SensorFullResolutionY; + pSensorInfo->SensorClockFreq = pInfo[IDNum]->SensorClockFreq; + pSensorInfo->SensorCameraPreviewFrameRate = pInfo[IDNum]->SensorCameraPreviewFrameRate; + pSensorInfo->SensorVideoFrameRate = pInfo[IDNum]->SensorVideoFrameRate; + pSensorInfo->SensorStillCaptureFrameRate = pInfo[IDNum]->SensorStillCaptureFrameRate; + pSensorInfo->SensorWebCamCaptureFrameRate = pInfo[IDNum]->SensorWebCamCaptureFrameRate; + pSensorInfo->SensorClockPolarity = pInfo[IDNum]->SensorClockPolarity; + pSensorInfo->SensorClockFallingPolarity = pInfo[IDNum]->SensorClockFallingPolarity; + pSensorInfo->SensorClockRisingCount = pInfo[IDNum]->SensorClockRisingCount; + pSensorInfo->SensorClockFallingCount = pInfo[IDNum]->SensorClockFallingCount; + pSensorInfo->SensorClockDividCount = pInfo[IDNum]->SensorClockDividCount; + pSensorInfo->SensorPixelClockCount = pInfo[IDNum]->SensorPixelClockCount; + pSensorInfo->SensorDataLatchCount = pInfo[IDNum]->SensorDataLatchCount; + pSensorInfo->SensorHsyncPolarity = pInfo[IDNum]->SensorHsyncPolarity; + pSensorInfo->SensorVsyncPolarity = pInfo[IDNum]->SensorVsyncPolarity; + pSensorInfo->SensorInterruptDelayLines = pInfo[IDNum]->SensorInterruptDelayLines; + pSensorInfo->SensorResetActiveHigh = pInfo[IDNum]->SensorResetActiveHigh; + pSensorInfo->SensorResetDelayCount = pInfo[IDNum]->SensorResetDelayCount; + pSensorInfo->SensroInterfaceType = pInfo[IDNum]->SensroInterfaceType; + pSensorInfo->SensorOutputDataFormat = pInfo[IDNum]->SensorOutputDataFormat; + pSensorInfo->SensorMIPILaneNumber = pInfo[IDNum]->SensorMIPILaneNumber; + pSensorInfo->CaptureDelayFrame = pInfo[IDNum]->CaptureDelayFrame; + pSensorInfo->PreviewDelayFrame = pInfo[IDNum]->PreviewDelayFrame; + pSensorInfo->VideoDelayFrame = pInfo[IDNum]->VideoDelayFrame; + pSensorInfo->HighSpeedVideoDelayFrame = pInfo[IDNum]->HighSpeedVideoDelayFrame; + pSensorInfo->SlimVideoDelayFrame = pInfo[IDNum]->SlimVideoDelayFrame; + pSensorInfo->Custom1DelayFrame = pInfo[IDNum]->Custom1DelayFrame; + pSensorInfo->Custom2DelayFrame = pInfo[IDNum]->Custom2DelayFrame; + pSensorInfo->Custom3DelayFrame = pInfo[IDNum]->Custom3DelayFrame; + pSensorInfo->Custom4DelayFrame = pInfo[IDNum]->Custom4DelayFrame; + pSensorInfo->Custom5DelayFrame = pInfo[IDNum]->Custom5DelayFrame; + pSensorInfo->YUVAwbDelayFrame = pInfo[IDNum]->YUVAwbDelayFrame; + pSensorInfo->YUVEffectDelayFrame = pInfo[IDNum]->YUVEffectDelayFrame; + pSensorInfo->SensorGrabStartX_PRV = pInfo[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_PRV = pInfo[IDNum]->SensorGrabStartY; + pSensorInfo->SensorGrabStartX_CAP = pInfo1[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_CAP = pInfo1[IDNum]->SensorGrabStartY; + pSensorInfo->SensorGrabStartX_VD = pInfo2[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_VD = pInfo2[IDNum]->SensorGrabStartY; + pSensorInfo->SensorGrabStartX_VD1 = pInfo3[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_VD1 = pInfo3[IDNum]->SensorGrabStartY; + pSensorInfo->SensorGrabStartX_VD2 = pInfo4[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_VD2 = pInfo4[IDNum]->SensorGrabStartY; + pSensorInfo->SensorDrivingCurrent = pInfo[IDNum]->SensorDrivingCurrent; + pSensorInfo->SensorMasterClockSwitch = pInfo[IDNum]->SensorMasterClockSwitch; + pSensorInfo->AEShutDelayFrame = pInfo[IDNum]->AEShutDelayFrame; + pSensorInfo->AESensorGainDelayFrame = pInfo[IDNum]->AESensorGainDelayFrame; + pSensorInfo->AEISPGainDelayFrame = pInfo[IDNum]->AEISPGainDelayFrame; + pSensorInfo->MIPIDataLowPwr2HighSpeedTermDelayCount = pInfo[IDNum]->MIPIDataLowPwr2HighSpeedTermDelayCount; + pSensorInfo->MIPIDataLowPwr2HighSpeedSettleDelayCount = pInfo[IDNum]->MIPIDataLowPwr2HighSpeedSettleDelayCount; + pSensorInfo->MIPIDataLowPwr2HSSettleDelayM0 = pInfo[IDNum]->MIPIDataLowPwr2HighSpeedSettleDelayCount; + pSensorInfo->MIPIDataLowPwr2HSSettleDelayM1 = pInfo1[IDNum]->MIPIDataLowPwr2HighSpeedSettleDelayCount; + pSensorInfo->MIPIDataLowPwr2HSSettleDelayM2 = pInfo2[IDNum]->MIPIDataLowPwr2HighSpeedSettleDelayCount; + pSensorInfo->MIPIDataLowPwr2HSSettleDelayM3 = pInfo3[IDNum]->MIPIDataLowPwr2HighSpeedSettleDelayCount; + pSensorInfo->MIPIDataLowPwr2HSSettleDelayM4 = pInfo4[IDNum]->MIPIDataLowPwr2HighSpeedSettleDelayCount; + pSensorInfo->MIPICLKLowPwr2HighSpeedTermDelayCount = pInfo[IDNum]->MIPICLKLowPwr2HighSpeedTermDelayCount; + pSensorInfo->SensorWidthSampling = pInfo[IDNum]->SensorWidthSampling; + pSensorInfo->SensorHightSampling = pInfo[IDNum]->SensorHightSampling; + pSensorInfo->SensorPacketECCOrder = pInfo[IDNum]->SensorPacketECCOrder; + pSensorInfo->MIPIsensorType = pInfo[IDNum]->MIPIsensorType; + pSensorInfo->IHDR_LE_FirstLine = pInfo[IDNum]->IHDR_LE_FirstLine; + pSensorInfo->IHDR_Support = pInfo[IDNum]->IHDR_Support; + pSensorInfo->SensorModeNum = pInfo[IDNum]->SensorModeNum; + pSensorInfo->SettleDelayMode = pInfo[IDNum]->SettleDelayMode; + pSensorInfo->PDAF_Support = pInfo[IDNum]->PDAF_Support; + pSensorInfo->IMGSENSOR_DPCM_TYPE_PRE = pInfo[IDNum]->DPCM_INFO; + pSensorInfo->IMGSENSOR_DPCM_TYPE_CAP = pInfo1[IDNum]->DPCM_INFO; + pSensorInfo->IMGSENSOR_DPCM_TYPE_VD = pInfo2[IDNum]->DPCM_INFO; + pSensorInfo->IMGSENSOR_DPCM_TYPE_VD1 = pInfo3[IDNum]->DPCM_INFO; + pSensorInfo->IMGSENSOR_DPCM_TYPE_VD2 = pInfo4[IDNum]->DPCM_INFO; + /*Per-Frame conrol suppport or not */ + pSensorInfo->PerFrameCTL_Support = pInfo[IDNum]->PerFrameCTL_Support; + /*SCAM number*/ + pSensorInfo->SCAM_DataNumber = pInfo[IDNum]->SCAM_DataNumber; + pSensorInfo->SCAM_DDR_En = pInfo[IDNum]->SCAM_DDR_En; + pSensorInfo->SCAM_CLK_INV = pInfo[IDNum]->SCAM_CLK_INV; + pSensorInfo->SCAM_DEFAULT_DELAY = pInfo[IDNum]->SCAM_DEFAULT_DELAY; + pSensorInfo->SCAM_CRC_En = pInfo[IDNum]->SCAM_CRC_En; + pSensorInfo->SCAM_SOF_src = pInfo[IDNum]->SCAM_SOF_src; + pSensorInfo->SCAM_Timout_Cali = pInfo[IDNum]->SCAM_Timout_Cali; + pSensorInfo->SensorHorFOV = pInfo[IDNum]->SensorHorFOV; + pSensorInfo->SensorVerFOV = pInfo[IDNum]->SensorVerFOV; + + /* TO get preview value */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_CUSTOM1; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo, pConfig); + /* */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_CUSTOM2; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo1, pConfig1); + /* */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_CUSTOM3; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo2, pConfig2); + /* */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_CUSTOM4; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo3, pConfig3); + /* */ + ScenarioId[0] = ScenarioId[1] = MSDK_SCENARIO_ID_CUSTOM5; + g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo4, pConfig4); + /* To set sensor information */ + if (DUAL_CAMERA_MAIN_SENSOR == pSensorGetInfo->SensorId) { + IDNum = 0; + } + else + { + IDNum = 1; + } + pSensorInfo->SensorGrabStartX_CST1 = pInfo[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_CST1 = pInfo[IDNum]->SensorGrabStartY; + pSensorInfo->SensorGrabStartX_CST2 = pInfo1[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_CST2 = pInfo1[IDNum]->SensorGrabStartY; + pSensorInfo->SensorGrabStartX_CST3 = pInfo2[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_CST3 = pInfo2[IDNum]->SensorGrabStartY; + pSensorInfo->SensorGrabStartX_CST4 = pInfo3[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_CST4 = pInfo3[IDNum]->SensorGrabStartY; + pSensorInfo->SensorGrabStartX_CST5 = pInfo4[IDNum]->SensorGrabStartX; + pSensorInfo->SensorGrabStartY_CST5 = pInfo4[IDNum]->SensorGrabStartY; + + if (copy_to_user((void __user *)(pSensorGetInfo->pInfo), (void *)(pSensorInfo), sizeof(ACDK_SENSOR_INFO2_STRUCT))) { + PK_DBG("[CAMERA_HW][info] ioctl copy to user failed\n"); + for (i = 0; i < 2; i++) { + if(pConfig[i] != NULL) kfree(pConfig[i]); + if(pConfig1[i] != NULL) kfree(pConfig1[i]); + if(pConfig2[i] != NULL) kfree(pConfig2[i]); + if(pConfig3[i] != NULL) kfree(pConfig3[i]); + if(pConfig4[i] != NULL) kfree(pConfig4[i]); + if(psensorResolution[i] != NULL) kfree(psensorResolution[i]); + pConfig[i] = NULL; + pConfig1[i] = NULL; + pConfig2[i] = NULL; + pConfig3[i] = NULL; + pConfig4[i] = NULL; + psensorResolution[i] = NULL; + } + kfree(pSensorInfo); + pSensorInfo = NULL; + + return -EFAULT; + } + + /* Step2 : Get Resolution */ + g_pSensorFunc->SensorGetResolution(psensorResolution); + PK_DBG("[CAMERA_HW][Pre]w=0x%x, h = 0x%x\n", psensorResolution[0]->SensorPreviewWidth, psensorResolution[0]->SensorPreviewHeight); + PK_DBG("[CAMERA_HW][Full]w=0x%x, h = 0x%x\n", psensorResolution[0]->SensorFullWidth, psensorResolution[0]->SensorFullHeight); + PK_DBG("[CAMERA_HW][VD]w=0x%x, h = 0x%x\n", psensorResolution[0]->SensorVideoWidth, psensorResolution[0]->SensorVideoHeight); + + if (DUAL_CAMERA_MAIN_SENSOR == pSensorGetInfo->SensorId) { + /* Resolution */ + PK_DBG("[adopt_CAMERA_HW_GetInfo2]Resolution\n"); + if (copy_to_user((void __user *) (pSensorGetInfo->pSensorResolution) , (void *)psensorResolution[0] , sizeof(MSDK_SENSOR_RESOLUTION_INFO_STRUCT))) { + PK_DBG("[CAMERA_HW][Resolution] ioctl copy to user failed\n"); + for (i = 0; i < 2; i++) { + if(pConfig[i] != NULL) kfree(pConfig[i]); + if(pConfig1[i] != NULL) kfree(pConfig1[i]); + if(pConfig2[i] != NULL) kfree(pConfig2[i]); + if(pConfig3[i] != NULL) kfree(pConfig3[i]); + if(pConfig4[i] != NULL) kfree(pConfig4[i]); + if(psensorResolution[i] != NULL) kfree(psensorResolution[i]); + pConfig[i] = NULL; + pConfig1[i] = NULL; + pConfig2[i] = NULL; + pConfig3[i] = NULL; + pConfig4[i] = NULL; + psensorResolution[i] = NULL; + } + kfree(pSensorInfo); + pSensorInfo = NULL; + return -EFAULT; + } + } else{ + /* Resolution */ + if (copy_to_user((void __user *) (pSensorGetInfo->pSensorResolution) , (void *)psensorResolution[1] , sizeof(MSDK_SENSOR_RESOLUTION_INFO_STRUCT))) { + PK_DBG("[CAMERA_HW][Resolution] ioctl copy to user failed\n"); + for (i = 0; i < 2; i++) { + if(pConfig[i] != NULL) kfree(pConfig[i]); + if(pConfig1[i] != NULL) kfree(pConfig1[i]); + if(pConfig2[i] != NULL) kfree(pConfig2[i]); + if(pConfig3[i] != NULL) kfree(pConfig3[i]); + if(pConfig4[i] != NULL) kfree(pConfig4[i]); + if(psensorResolution[i] != NULL) kfree(psensorResolution[i]); + pConfig[i] = NULL; + pConfig1[i] = NULL; + pConfig2[i] = NULL; + pConfig3[i] = NULL; + pConfig4[i] = NULL; + psensorResolution[i] = NULL; + } + kfree(pSensorInfo); + pSensorInfo = NULL; + return -EFAULT; + } + } + + for (i = 0; i < 2; i++) { + if(pConfig[i] != NULL) kfree(pConfig[i]); + if(pConfig1[i] != NULL) kfree(pConfig1[i]); + if(pConfig2[i] != NULL) kfree(pConfig2[i]); + if(pConfig3[i] != NULL) kfree(pConfig3[i]); + if(pConfig4[i] != NULL) kfree(pConfig4[i]); + if(psensorResolution[i] != NULL) kfree(psensorResolution[i]); + pConfig[i] = NULL; + pConfig1[i] = NULL; + pConfig2[i] = NULL; + pConfig3[i] = NULL; + pConfig4[i] = NULL; + psensorResolution[i] = NULL; + } + kfree(pSensorInfo); + pSensorInfo = NULL; + + return 0; +} /* adopt_CAMERA_HW_GetInfo() */ + + +/******************************************************************************* +* adopt_CAMERA_HW_Control +********************************************************************************/ +inline static int adopt_CAMERA_HW_Control(void *pBuf) +{ + int ret = 0; + ACDK_SENSOR_CONTROL_STRUCT *pSensorCtrl = (ACDK_SENSOR_CONTROL_STRUCT *)pBuf; + MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT imageWindow; + MSDK_SENSOR_CONFIG_STRUCT sensorConfigData; + memset(&imageWindow, 0, sizeof(ACDK_SENSOR_EXPOSURE_WINDOW_STRUCT)); + memset(&sensorConfigData, 0, sizeof(ACDK_SENSOR_CONFIG_STRUCT)); + + if (NULL == pSensorCtrl) { + PK_DBG("[CAMERA_HW] NULL arg.\n"); + return -EFAULT; + } + + if (NULL == pSensorCtrl->pImageWindow || NULL == pSensorCtrl->pSensorConfigData) { + PK_DBG("[CAMERA_HW] NULL arg.\n"); + return -EFAULT; + } + + if (copy_from_user((void *)&imageWindow , (void *) pSensorCtrl->pImageWindow, sizeof(ACDK_SENSOR_EXPOSURE_WINDOW_STRUCT))) { + PK_DBG("[CAMERA_HW][pFeatureData32] ioctl copy from user failed\n"); + return -EFAULT; + } + + if (copy_from_user((void *)&sensorConfigData , (void *) pSensorCtrl->pSensorConfigData, sizeof(ACDK_SENSOR_CONFIG_STRUCT))) { + PK_DBG("[CAMERA_HW][pFeatureData32] ioctl copy from user failed\n"); + return -EFAULT; + } + + /* */ + if (g_pSensorFunc) { + ret = g_pSensorFunc->SensorControl(pSensorCtrl->InvokeCamera, pSensorCtrl->ScenarioId, &imageWindow, &sensorConfigData); + } + else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + /* */ + if (copy_to_user((void __user *) pSensorCtrl->pImageWindow, (void *)&imageWindow , sizeof(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT))) { + PK_DBG("[CAMERA_HW][imageWindow] ioctl copy to user failed\n"); + return -EFAULT; + } + + /* */ + if (copy_to_user((void __user *) pSensorCtrl->pSensorConfigData, (void *)&sensorConfigData , sizeof(MSDK_SENSOR_CONFIG_STRUCT))) { + PK_DBG("[CAMERA_HW][imageWindow] ioctl copy to user failed\n"); + return -EFAULT; + } + return ret; +} /* adopt_CAMERA_HW_Control */ + +/******************************************************************************* +* adopt_CAMERA_HW_FeatureControl +********************************************************************************/ +inline static int adopt_CAMERA_HW_FeatureControl(void *pBuf) +{ + ACDK_SENSOR_FEATURECONTROL_STRUCT *pFeatureCtrl = (ACDK_SENSOR_FEATURECONTROL_STRUCT *)pBuf; + unsigned int FeatureParaLen = 0; + void *pFeaturePara = NULL; +#if 0 + ACDK_SENSOR_GROUP_INFO_STRUCT *pSensorGroupInfo = NULL; + char kernelGroupNamePtr[128]; + unsigned char *pUserGroupNamePtr = NULL; +#endif + ACDK_KD_SENSOR_SYNC_STRUCT *pSensorSyncInfo = NULL; + signed int ret = 0; + + + + if (NULL == pFeatureCtrl) { + PK_ERR(" NULL arg.\n"); + return -EFAULT; + } + + if (SENSOR_FEATURE_SINGLE_FOCUS_MODE == pFeatureCtrl->FeatureId || SENSOR_FEATURE_CANCEL_AF == pFeatureCtrl->FeatureId + || SENSOR_FEATURE_CONSTANT_AF == pFeatureCtrl->FeatureId || SENSOR_FEATURE_INFINITY_AF == pFeatureCtrl->FeatureId) {/* YUV AF_init and AF_constent and AF_single has no params */ + } + else + { + if (NULL == pFeatureCtrl->pFeaturePara || NULL == pFeatureCtrl->pFeatureParaLen) { + PK_ERR(" NULL arg.\n"); + return -EFAULT; + } + if (copy_from_user((void *)&FeatureParaLen , (void *) pFeatureCtrl->pFeatureParaLen, sizeof(unsigned int))) { + PK_ERR(" ioctl copy from user failed\n"); + return -EFAULT; + } + + pFeaturePara = kmalloc(FeatureParaLen, GFP_KERNEL); + if (NULL == pFeaturePara) { + PK_ERR(" ioctl allocate mem failed\n"); + return -ENOMEM; + } + memset(pFeaturePara, 0x0, FeatureParaLen); + } + + /* copy from user */ + switch (pFeatureCtrl->FeatureId) + { + case SENSOR_FEATURE_SET_ESHUTTER: + case SENSOR_FEATURE_SET_GAIN: + /* reset the delay frame flag */ + spin_lock(&kdsensor_drv_lock); + g_NewSensorExpGain.uSensorExpDelayFrame = 0xFF; + g_NewSensorExpGain.uSensorGainDelayFrame = 0xFF; + g_NewSensorExpGain.uISPGainDelayFrame = 0xFF; + spin_unlock(&kdsensor_drv_lock); + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + case SENSOR_FEATURE_SET_REGISTER: + case SENSOR_FEATURE_GET_REGISTER: + case SENSOR_FEATURE_SET_CCT_REGISTER: + case SENSOR_FEATURE_SET_ENG_REGISTER: + case SENSOR_FEATURE_SET_ITEM_INFO: + case SENSOR_FEATURE_GET_ITEM_INFO: + case SENSOR_FEATURE_GET_ENG_INFO: + case SENSOR_FEATURE_SET_VIDEO_MODE: + case SENSOR_FEATURE_SET_YUV_CMD: + case SENSOR_FEATURE_MOVE_FOCUS_LENS: + case SENSOR_FEATURE_SET_AF_WINDOW: + case SENSOR_FEATURE_SET_CALIBRATION_DATA: + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + case SENSOR_FEATURE_GET_EV_AWB_REF: + case SENSOR_FEATURE_GET_SHUTTER_GAIN_AWB_GAIN: + case SENSOR_FEATURE_SET_AE_WINDOW: + case SENSOR_FEATURE_GET_EXIF_INFO: + case SENSOR_FEATURE_GET_DELAY_INFO: + case SENSOR_FEATURE_GET_AE_AWB_LOCK_INFO: + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + case SENSOR_FEATURE_SET_TEST_PATTERN: + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: + case SENSOR_FEATURE_SET_OB_LOCK: + case SENSOR_FEATURE_SET_SENSOR_OTP_AWB_CMD: + case SENSOR_FEATURE_SET_SENSOR_OTP_LSC_CMD: + case SENSOR_FEATURE_GET_TEMPERATURE_VALUE: + case SENSOR_FEATURE_SET_FRAMERATE: + case SENSOR_FEATURE_SET_HDR: + case SENSOR_FEATURE_GET_CROP_INFO: + case SENSOR_FEATURE_GET_VC_INFO: + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + case SENSOR_FEATURE_SET_HDR_SHUTTER: + case SENSOR_FEATURE_GET_AE_FLASHLIGHT_INFO: + case SENSOR_FEATURE_GET_TRIGGER_FLASHLIGHT_INFO: /* return TRUE:play flashlight */ + case SENSOR_FEATURE_SET_YUV_3A_CMD: /* para: ACDK_SENSOR_3A_LOCK_ENUM */ + case SENSOR_FEATURE_SET_AWB_GAIN: + case SENSOR_FEATURE_SET_MIN_MAX_FPS: + case SENSOR_FEATURE_GET_PDAF_INFO: + case SENSOR_FEATURE_GET_PDAF_DATA: + case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: + case SENSOR_FEATURE_SET_PDAF: + /* */ + if (copy_from_user((void *)pFeaturePara , (void *) pFeatureCtrl->pFeaturePara, FeatureParaLen)) { + kfree(pFeaturePara); + PK_ERR("[CAMERA_HW][pFeaturePara] ioctl copy from user failed\n"); + return -EFAULT; + } + break; + case SENSOR_FEATURE_SET_SENSOR_SYNC: /* Update new sensor exposure time and gain to keep */ + if (copy_from_user((void *)pFeaturePara , (void *) pFeatureCtrl->pFeaturePara, FeatureParaLen)) { + kfree(pFeaturePara); + PK_ERR("[CAMERA_HW][pFeaturePara] ioctl copy from user failed\n"); + return -EFAULT; + } + /* keep the information to wait Vsync synchronize */ + pSensorSyncInfo = (ACDK_KD_SENSOR_SYNC_STRUCT *)pFeaturePara; + spin_lock(&kdsensor_drv_lock); + g_NewSensorExpGain.u2SensorNewExpTime = pSensorSyncInfo->u2SensorNewExpTime; + g_NewSensorExpGain.u2SensorNewGain = pSensorSyncInfo->u2SensorNewGain; + g_NewSensorExpGain.u2ISPNewRGain = pSensorSyncInfo->u2ISPNewRGain; + g_NewSensorExpGain.u2ISPNewGrGain = pSensorSyncInfo->u2ISPNewGrGain; + g_NewSensorExpGain.u2ISPNewGbGain = pSensorSyncInfo->u2ISPNewGbGain; + g_NewSensorExpGain.u2ISPNewBGain = pSensorSyncInfo->u2ISPNewBGain; + g_NewSensorExpGain.uSensorExpDelayFrame = pSensorSyncInfo->uSensorExpDelayFrame; + g_NewSensorExpGain.uSensorGainDelayFrame = pSensorSyncInfo->uSensorGainDelayFrame; + g_NewSensorExpGain.uISPGainDelayFrame = pSensorSyncInfo->uISPGainDelayFrame; + /* AE smooth not change shutter to speed up */ + if ((0 == g_NewSensorExpGain.u2SensorNewExpTime) || (0xFFFF == g_NewSensorExpGain.u2SensorNewExpTime)) { + g_NewSensorExpGain.uSensorExpDelayFrame = 0xFF; + } + + if (g_NewSensorExpGain.uSensorExpDelayFrame == 0) { + FeatureParaLen = 2; + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, SENSOR_FEATURE_SET_ESHUTTER, (unsigned char *)&g_NewSensorExpGain.u2SensorNewExpTime, (unsigned int *) &FeatureParaLen); + g_NewSensorExpGain.uSensorExpDelayFrame = 0xFF; /* disable */ + } + else if (g_NewSensorExpGain.uSensorExpDelayFrame != 0xFF) { + g_NewSensorExpGain.uSensorExpDelayFrame--; + } + /* exposure gain */ + if (g_NewSensorExpGain.uSensorGainDelayFrame == 0) { + FeatureParaLen = 2; + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, SENSOR_FEATURE_SET_GAIN, (unsigned char *)&g_NewSensorExpGain.u2SensorNewGain, (unsigned int *) &FeatureParaLen); + g_NewSensorExpGain.uSensorGainDelayFrame = 0xFF; /* disable */ + } + else if (g_NewSensorExpGain.uSensorGainDelayFrame != 0xFF) { + g_NewSensorExpGain.uSensorGainDelayFrame--; + } + /* if the delay frame is 0 or 0xFF, stop to count */ + if ((g_NewSensorExpGain.uISPGainDelayFrame != 0xFF) && (g_NewSensorExpGain.uISPGainDelayFrame != 0)) { + g_NewSensorExpGain.uISPGainDelayFrame--; + } + spin_unlock(&kdsensor_drv_lock); + + + + break; +#if 0 + case SENSOR_FEATURE_GET_GROUP_INFO: + if (copy_from_user((void *)pFeaturePara , (void *) pFeatureCtrl->pFeaturePara, FeatureParaLen)) { + kfree(pFeaturePara); + PK_DBG("[CAMERA_HW][pFeaturePara] ioctl copy from user failed\n"); + return -EFAULT; + } + pSensorGroupInfo = (ACDK_SENSOR_GROUP_INFO_STRUCT *)pFeaturePara; + pUserGroupNamePtr = pSensorGroupInfo->GroupNamePtr; + /* */ + if (NULL == pUserGroupNamePtr) { + kfree(pFeaturePara); + PK_DBG("[CAMERA_HW] NULL arg.\n"); + return -EFAULT; + } + pSensorGroupInfo->GroupNamePtr = kernelGroupNamePtr; + break; +#endif + case SENSOR_FEATURE_SET_ESHUTTER_GAIN: + if (copy_from_user((void *)pFeaturePara , (void *) pFeatureCtrl->pFeaturePara, FeatureParaLen)) { + PK_ERR("[CAMERA_HW][pFeaturePara] ioctl copy from user failed\n"); + kfree(pFeaturePara); + return -EFAULT; + } + /* keep the information to wait Vsync synchronize */ + pSensorSyncInfo = (ACDK_KD_SENSOR_SYNC_STRUCT *)pFeaturePara; + spin_lock(&kdsensor_drv_lock); + g_NewSensorExpGain.u2SensorNewExpTime = pSensorSyncInfo->u2SensorNewExpTime; + g_NewSensorExpGain.u2SensorNewGain = pSensorSyncInfo->u2SensorNewGain; + spin_unlock(&kdsensor_drv_lock); + kdSetExpGain(pFeatureCtrl->InvokeCamera); + break; + /* copy to user */ + case SENSOR_FEATURE_GET_RESOLUTION: + case SENSOR_FEATURE_GET_PERIOD: + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + case SENSOR_FEATURE_GET_REGISTER_DEFAULT: + case SENSOR_FEATURE_GET_CONFIG_PARA: + case SENSOR_FEATURE_GET_GROUP_COUNT: + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + /* do nothing */ + case SENSOR_FEATURE_CAMERA_PARA_TO_SENSOR: + case SENSOR_FEATURE_SENSOR_TO_CAMERA_PARA: + case SENSOR_FEATURE_SINGLE_FOCUS_MODE: + case SENSOR_FEATURE_CANCEL_AF: + case SENSOR_FEATURE_CONSTANT_AF: + default: + break; + } + + /*in case that some structure are passed from user sapce by ptr */ + switch (pFeatureCtrl->FeatureId) { + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: + { + MUINT32 *pValue = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + pValue = kmalloc(sizeof(MUINT32), GFP_KERNEL); + if (pValue == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + + memset(pValue, 0x0, sizeof(MUINT32)); + *(pFeaturePara_64 + 1) = (uintptr_t)pValue; + /*PK_DBG("[CAMERA_HW] %p %p %p\n", + (void *)(uintptr_t) (*(pFeaturePara_64 + 1)), + (void *)pFeaturePara_64, (void *)(pValue));*/ + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_ERR("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + *(pFeaturePara_64 + 1) = *pValue; + kfree(pValue); + } + break; + case SENSOR_FEATURE_GET_AE_STATUS: + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: + case SENSOR_FEATURE_GET_TEMPERATURE_VALUE: + case SENSOR_FEATURE_GET_AF_STATUS: + case SENSOR_FEATURE_GET_AWB_STATUS: + case SENSOR_FEATURE_GET_AF_MAX_NUM_FOCUS_AREAS: + case SENSOR_FEATURE_GET_AE_MAX_NUM_METERING_AREAS: + case SENSOR_FEATURE_GET_TRIGGER_FLASHLIGHT_INFO: + case SENSOR_FEATURE_GET_SENSOR_N3D_STREAM_TO_VSYNC_TIME: + case SENSOR_FEATURE_GET_PERIOD: + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + { + + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + } + break; + case SENSOR_FEATURE_GET_AE_AWB_LOCK_INFO: + case SENSOR_FEATURE_AUTOTEST_CMD: + { + MUINT32 *pValue0 = NULL; + MUINT32 *pValue1 = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + pValue0 = kmalloc(sizeof(MUINT32), GFP_KERNEL); + pValue1 = kmalloc(sizeof(MUINT32), GFP_KERNEL); + + if (pValue0 == NULL || pValue1 == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pValue0); + kfree(pValue1); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pValue1, 0x0, sizeof(MUINT32)); + memset(pValue0, 0x0, sizeof(MUINT32)); + *(pFeaturePara_64) = (uintptr_t)pValue0; + *(pFeaturePara_64 + 1) = (uintptr_t)pValue1; + PK_DBG("[CAMERA_HW] %p %p %p\n", + (void *)(uintptr_t) (*(pFeaturePara_64 + 1)), + (void *)pFeaturePara_64, (void *)(pValue0)); + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + *(pFeaturePara_64) = *pValue0; + *(pFeaturePara_64 + 1) = *pValue1; + kfree(pValue0); + kfree(pValue1); + } + break; + + + case SENSOR_FEATURE_GET_EV_AWB_REF: + { + SENSOR_AE_AWB_REF_STRUCT *pAeAwbRef = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void*)(uintptr_t)(*(pFeaturePara_64)); + pAeAwbRef = kmalloc(sizeof(SENSOR_AE_AWB_REF_STRUCT), GFP_KERNEL); + if (pAeAwbRef == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pAeAwbRef, 0x0, sizeof(SENSOR_AE_AWB_REF_STRUCT)); + *(pFeaturePara_64) = (uintptr_t)pAeAwbRef; + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + if (copy_to_user + ((void __user *)usr_ptr, (void *)pAeAwbRef, + sizeof(SENSOR_AE_AWB_REF_STRUCT))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pAeAwbRef); + *(pFeaturePara_64) = (uintptr_t)usr_ptr; + } + break; + + case SENSOR_FEATURE_GET_CROP_INFO: + { + SENSOR_WINSIZE_INFO_STRUCT *pCrop = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void *)(uintptr_t) (*(pFeaturePara_64 + 1)); + pCrop = kmalloc(sizeof(SENSOR_WINSIZE_INFO_STRUCT), GFP_KERNEL); + if (pCrop == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pCrop, 0x0, sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + *(pFeaturePara_64 + 1) = (uintptr_t)pCrop; + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + //PK_DBG("[CAMERA_HW]crop =%d\n",framerate); + + if (copy_to_user + ((void __user *)usr_ptr, (void *)pCrop, + sizeof(SENSOR_WINSIZE_INFO_STRUCT))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pCrop); + *(pFeaturePara_64 + 1) = (uintptr_t)usr_ptr; + } + break; + + case SENSOR_FEATURE_GET_VC_INFO: + { + SENSOR_VC_INFO_STRUCT *pVcInfo = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void *)(uintptr_t) (*(pFeaturePara_64 + 1)); + pVcInfo = kmalloc(sizeof(SENSOR_VC_INFO_STRUCT), GFP_KERNEL); + if (pVcInfo == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pVcInfo, 0x0, sizeof(SENSOR_VC_INFO_STRUCT)); + *(pFeaturePara_64 + 1) = (uintptr_t)pVcInfo; + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + if (copy_to_user + ((void __user *)usr_ptr, (void *)pVcInfo, + sizeof(SENSOR_VC_INFO_STRUCT))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pVcInfo); + *(pFeaturePara_64 + 1) = (uintptr_t)usr_ptr; + } + break; + + case SENSOR_FEATURE_GET_PDAF_INFO: + { + +#if 1 + SET_PD_BLOCK_INFO_T *pPdInfo = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void *)(uintptr_t) (*(pFeaturePara_64 + 1)); + pPdInfo = kmalloc(sizeof(SET_PD_BLOCK_INFO_T), GFP_KERNEL); + if (pPdInfo == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pPdInfo, 0x0, sizeof(SET_PD_BLOCK_INFO_T)); + *(pFeaturePara_64 + 1) = (uintptr_t)pPdInfo; + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + if (copy_to_user + ((void __user *)usr_ptr, (void *)pPdInfo, + sizeof(SET_PD_BLOCK_INFO_T))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pPdInfo); + *(pFeaturePara_64 + 1) = (uintptr_t)usr_ptr; +#endif + } + break; + + case SENSOR_FEATURE_SET_AF_WINDOW: + case SENSOR_FEATURE_SET_AE_WINDOW: + { + MUINT32 *pApWindows = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void *)(uintptr_t) (*(pFeaturePara_64)); + pApWindows = kmalloc(sizeof(MUINT32) * 6, GFP_KERNEL); + if (pApWindows == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pApWindows, 0x0, sizeof(MUINT32) * 6); + *(pFeaturePara_64) = (uintptr_t)pApWindows; + + if (copy_from_user + ((void *)pApWindows, (void *)usr_ptr, sizeof(MUINT32) * 6)) { + PK_ERR("[CAMERA_HW]ERROR: copy from user fail \n"); + } + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_ERR("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + kfree(pApWindows); + *(pFeaturePara_64) = (uintptr_t)usr_ptr; + } + break; + + case SENSOR_FEATURE_GET_EXIF_INFO: + { + SENSOR_EXIF_INFO_STRUCT *pExif = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void *)(uintptr_t) (*(pFeaturePara_64)); + pExif = kmalloc(sizeof(SENSOR_EXIF_INFO_STRUCT), GFP_KERNEL); + if (pExif == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pExif, 0x0, sizeof(SENSOR_EXIF_INFO_STRUCT)); + *(pFeaturePara_64) = (uintptr_t)pExif; + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + if (copy_to_user + ((void __user *)usr_ptr, (void *)pExif, + sizeof(SENSOR_EXIF_INFO_STRUCT))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pExif); + *(pFeaturePara_64) = (uintptr_t)usr_ptr; + } + break; + + + case SENSOR_FEATURE_GET_SHUTTER_GAIN_AWB_GAIN: + { + + SENSOR_AE_AWB_CUR_STRUCT *pCurAEAWB = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void *)(uintptr_t) (*(pFeaturePara_64)); + pCurAEAWB = kmalloc(sizeof(SENSOR_AE_AWB_CUR_STRUCT), GFP_KERNEL); + if (pCurAEAWB == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pCurAEAWB, 0x0, sizeof(SENSOR_AE_AWB_CUR_STRUCT)); + *(pFeaturePara_64) = (uintptr_t)pCurAEAWB; + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + if (copy_to_user + ((void __user *)usr_ptr, (void *)pCurAEAWB, + sizeof(SENSOR_AE_AWB_CUR_STRUCT))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pCurAEAWB); + *(pFeaturePara_64) = (uintptr_t)usr_ptr; + } + break; + + case SENSOR_FEATURE_GET_DELAY_INFO: + { + SENSOR_DELAY_INFO_STRUCT *pDelayInfo = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void *)(uintptr_t) (*(pFeaturePara_64)); + pDelayInfo = kmalloc(sizeof(SENSOR_DELAY_INFO_STRUCT), GFP_KERNEL); + + if (pDelayInfo == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pDelayInfo, 0x0, sizeof(SENSOR_DELAY_INFO_STRUCT)); + *(pFeaturePara_64) = (uintptr_t)pDelayInfo; + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + if (copy_to_user + ((void __user *)usr_ptr, (void *)pDelayInfo, + sizeof(SENSOR_DELAY_INFO_STRUCT))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pDelayInfo); + *(pFeaturePara_64) = (uintptr_t)usr_ptr; + + } + break; + + + case SENSOR_FEATURE_GET_AE_FLASHLIGHT_INFO: + { + SENSOR_FLASHLIGHT_AE_INFO_STRUCT *pFlashInfo = NULL; + unsigned long long *pFeaturePara_64 = (unsigned long long *)pFeaturePara; + void *usr_ptr = (void *)(uintptr_t) (*(pFeaturePara_64)); + pFlashInfo = kmalloc(sizeof(SENSOR_FLASHLIGHT_AE_INFO_STRUCT), GFP_KERNEL); + + if (pFlashInfo == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pFlashInfo, 0x0, sizeof(SENSOR_FLASHLIGHT_AE_INFO_STRUCT)); + *(pFeaturePara_64) = (uintptr_t)pFlashInfo; + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + if (copy_to_user + ((void __user *)usr_ptr, (void *)pFlashInfo, + sizeof(SENSOR_FLASHLIGHT_AE_INFO_STRUCT))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pFlashInfo); + *(pFeaturePara_64) = (uintptr_t)usr_ptr; + + } + break; + + + case SENSOR_FEATURE_GET_PDAF_DATA: + { + char *pPdaf_data = NULL; + + unsigned long long *pFeaturePara_64=(unsigned long long *) pFeaturePara; + void *usr_ptr = (void *)(uintptr_t)(*(pFeaturePara_64 + 1)); + #if 1 + pPdaf_data = kmalloc(sizeof(char) * PDAF_DATA_SIZE, GFP_KERNEL); + if (pPdaf_data == NULL) { + PK_ERR(" ioctl allocate mem failed\n"); + kfree(pFeaturePara); + return -ENOMEM; + } + memset(pPdaf_data, 0xff, sizeof(char) * PDAF_DATA_SIZE); + + if (pFeaturePara_64 != NULL) { + *(pFeaturePara_64 + 1) = (uintptr_t)pPdaf_data;//*(pFeaturePara_64 + 1) = (uintptr_t)pPdaf_data; + } + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *) + pFeaturePara, + (unsigned int *) + &FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + if (copy_to_user + ((void __user *)usr_ptr, (void *)pPdaf_data, + (kal_uint32) (*(pFeaturePara_64 + 2)))) { + PK_DBG("[CAMERA_HW]ERROR: copy_to_user fail \n"); + } + kfree(pPdaf_data); + *(pFeaturePara_64 + 1) =(uintptr_t) usr_ptr; + +#endif + } + break; + default: + + if (g_pSensorFunc) { + ret = + g_pSensorFunc->SensorFeatureControl(pFeatureCtrl->InvokeCamera, + pFeatureCtrl->FeatureId, + (unsigned char *)pFeaturePara, + (unsigned int *)&FeatureParaLen); + } else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + + break; + } + /* copy to user */ + switch (pFeatureCtrl->FeatureId) + { + case SENSOR_FEATURE_SET_ESHUTTER: + case SENSOR_FEATURE_SET_GAIN: + case SENSOR_FEATURE_SET_GAIN_AND_ESHUTTER: + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + case SENSOR_FEATURE_SET_REGISTER: + case SENSOR_FEATURE_SET_CCT_REGISTER: + case SENSOR_FEATURE_SET_ENG_REGISTER: + case SENSOR_FEATURE_SET_ITEM_INFO: + /* do nothing */ + case SENSOR_FEATURE_CAMERA_PARA_TO_SENSOR: + case SENSOR_FEATURE_SENSOR_TO_CAMERA_PARA: + case SENSOR_FEATURE_GET_PDAF_DATA: + break; + /* copy to user */ + case SENSOR_FEATURE_GET_EV_AWB_REF: + case SENSOR_FEATURE_GET_SHUTTER_GAIN_AWB_GAIN: + case SENSOR_FEATURE_GET_EXIF_INFO: + case SENSOR_FEATURE_GET_DELAY_INFO: + case SENSOR_FEATURE_GET_AE_AWB_LOCK_INFO: + case SENSOR_FEATURE_GET_RESOLUTION: + case SENSOR_FEATURE_GET_PERIOD: + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + case SENSOR_FEATURE_GET_REGISTER: + case SENSOR_FEATURE_GET_REGISTER_DEFAULT: + case SENSOR_FEATURE_GET_CONFIG_PARA: + case SENSOR_FEATURE_GET_GROUP_COUNT: + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + case SENSOR_FEATURE_GET_ITEM_INFO: + case SENSOR_FEATURE_GET_ENG_INFO: + case SENSOR_FEATURE_GET_AF_STATUS: + case SENSOR_FEATURE_GET_AE_STATUS: + case SENSOR_FEATURE_GET_AWB_STATUS: + case SENSOR_FEATURE_GET_AF_INF: + case SENSOR_FEATURE_GET_AF_MACRO: + case SENSOR_FEATURE_GET_AF_MAX_NUM_FOCUS_AREAS: + case SENSOR_FEATURE_GET_TRIGGER_FLASHLIGHT_INFO: /* return TRUE:play flashlight */ + case SENSOR_FEATURE_SET_YUV_3A_CMD: /* para: ACDK_SENSOR_3A_LOCK_ENUM */ + case SENSOR_FEATURE_GET_AE_FLASHLIGHT_INFO: + case SENSOR_FEATURE_GET_AE_MAX_NUM_METERING_AREAS: + case SENSOR_FEATURE_CHECK_SENSOR_ID: + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + case SENSOR_FEATURE_SET_TEST_PATTERN: + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: + case SENSOR_FEATURE_GET_TEMPERATURE_VALUE: + case SENSOR_FEATURE_SET_FRAMERATE: + case SENSOR_FEATURE_SET_HDR: + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + case SENSOR_FEATURE_GET_CROP_INFO: + case SENSOR_FEATURE_GET_VC_INFO: + case SENSOR_FEATURE_SET_MIN_MAX_FPS: + case SENSOR_FEATURE_GET_PDAF_INFO: + case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: + case SENSOR_FEATURE_SET_ISO: + case SENSOR_FEATURE_SET_PDAF: + /* */ + if (copy_to_user((void __user *) pFeatureCtrl->pFeaturePara, (void *)pFeaturePara , FeatureParaLen)) { + kfree(pFeaturePara); + PK_DBG("[CAMERA_HW][pSensorRegData] ioctl copy to user failed\n"); + return -EFAULT; + } + break; +#if 0 + /* copy from and to user */ + case SENSOR_FEATURE_GET_GROUP_INFO: + /* copy 32 bytes */ + if (copy_to_user((void __user *) pUserGroupNamePtr, (void *)kernelGroupNamePtr , sizeof(char)*32)) { + kfree(pFeaturePara); + PK_DBG("[CAMERA_HW][pFeatureReturnPara32] ioctl copy to user failed\n"); + return -EFAULT; + } + pSensorGroupInfo->GroupNamePtr = pUserGroupNamePtr; + if (copy_to_user((void __user *) pFeatureCtrl->pFeaturePara, (void *)pFeaturePara , FeatureParaLen)) { + kfree(pFeaturePara); + PK_DBG("[CAMERA_HW][pFeatureReturnPara32] ioctl copy to user failed\n"); + return -EFAULT; + } + break; +#endif + default: + break; + } + + kfree(pFeaturePara); + if (copy_to_user((void __user *) pFeatureCtrl->pFeatureParaLen, (void *)&FeatureParaLen , sizeof(unsigned int))) { + PK_DBG("[CAMERA_HW][pFeatureParaLen] ioctl copy to user failed\n"); + return -EFAULT; + } + return ret; +} /* adopt_CAMERA_HW_FeatureControl() */ + + +/******************************************************************************* +* adopt_CAMERA_HW_Close +********************************************************************************/ +inline static int adopt_CAMERA_HW_Close(void) +{ + /* if (atomic_read(&g_CamHWOpend) == 0) { */ + /* return 0; */ + /* } */ + /* else if(atomic_read(&g_CamHWOpend) == 1) { */ + if (g_pSensorFunc) { + g_pSensorFunc->SensorClose(); + } + else { + PK_DBG("[CAMERA_HW]ERROR:NULL g_pSensorFunc\n"); + } + /* power off sensor */ + /* Marked by Jessy Lee. Should close power in kd_MultiSensorClose function + * The following function will close all opened sensors. + */ + /* kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM*)g_invokeSocketIdx, g_invokeSensorNameStr, false, CAMERA_HW_DRVNAME1); */ + /* } */ + /* atomic_set(&g_CamHWOpend, 0); */ + + atomic_set(&g_CamHWOpening, 0); + + /* reset the delay frame flag */ + spin_lock(&kdsensor_drv_lock); + g_NewSensorExpGain.uSensorExpDelayFrame = 0xFF; + g_NewSensorExpGain.uSensorGainDelayFrame = 0xFF; + g_NewSensorExpGain.uISPGainDelayFrame = 0xFF; + spin_unlock(&kdsensor_drv_lock); + + return 0; +} /* adopt_CAMERA_HW_Close() */ + +#ifdef CONFIG_MTK_CLKMGR +inline static int kdSetSensorMclk(int *pBuf) +{ +/* #ifndef CONFIG_ARM64 */ + int ret = 0; + ACDK_SENSOR_MCLK_STRUCT *pSensorCtrl = (ACDK_SENSOR_MCLK_STRUCT *)pBuf; + + PK_DBG("[CAMERA SENSOR] kdSetSensorMclk on=%d, freq= %d\n", pSensorCtrl->on, pSensorCtrl->freq); + if (1 == pSensorCtrl->on) { + enable_mux(MT_MUX_CAMTG, "CAMERA_SENSOR"); + clkmux_sel(MT_MUX_CAMTG, pSensorCtrl->freq, "CAMERA_SENSOR"); + } + else { + + disable_mux(MT_MUX_CAMTG, "CAMERA_SENSOR"); + } + return ret; +/* #endif */ +} +#else + +/******************************************************************************* +* Common Clock Framework (CCF) +********************************************************************************/ +static inline void Get_ccf_clk(struct platform_device *pdev) +{ + if (pdev == NULL) { + PK_ERR("[%s] pdev is null\n", __func__); + return; + } + /* get all possible using clocks */ + g_camclk_camtg_sel = devm_clk_get(&pdev->dev, "TOP_CAMTG_SEL"); + BUG_ON(IS_ERR(g_camclk_camtg_sel)); + g_camclk_scam_sel = devm_clk_get(&pdev->dev, "TOP_MUX_SCAM"); + BUG_ON(IS_ERR(g_camclk_scam_sel)); + g_camclk_univpll_d26 = devm_clk_get(&pdev->dev, "TOP_UNIVPLL_D26"); + BUG_ON(IS_ERR(g_camclk_univpll_d26)); + g_camclk_univpll2_d2 = devm_clk_get(&pdev->dev, "TOP_UNIVPLL2_D2"); + BUG_ON(IS_ERR(g_camclk_univpll2_d2)); + + return; +} + +static inline void Check_ccf_clk(void) +{ + BUG_ON(IS_ERR(g_camclk_camtg_sel)); + BUG_ON(IS_ERR(g_camclk_univpll_d26)); + BUG_ON(IS_ERR(g_camclk_univpll2_d2)); + BUG_ON(IS_ERR(g_camclk_scam_sel)); + return; +} + +static inline int kdSetSensorMclk(int *pBuf) +{ + int ret = 0; +#ifndef CONFIG_MTK_FPGA + ACDK_SENSOR_MCLK_STRUCT *pSensorCtrl = (ACDK_SENSOR_MCLK_STRUCT *)pBuf; + + PK_DBG("[CAMERA SENSOR] CCF kdSetSensorMclk on=%d, freq= %d\n", pSensorCtrl->on, pSensorCtrl->freq); + + Check_ccf_clk(); + if (1 == pSensorCtrl->on) { + ret = clk_prepare_enable(g_camclk_camtg_sel); + if (pSensorCtrl->freq == 1 /*CAM_PLL_48_GROUP */) + ret = clk_set_parent(g_camclk_camtg_sel, g_camclk_univpll_d26); + else if (pSensorCtrl->freq == 2 /*CAM_PLL_52_GROUP */) + ret = clk_set_parent(g_camclk_camtg_sel, g_camclk_univpll2_d2); + ret = clk_prepare_enable(g_camclk_scam_sel); + } else { + clk_disable_unprepare(g_camclk_camtg_sel); + clk_disable_unprepare(g_camclk_scam_sel); + } +#endif + return ret; + +} + +#endif + +inline static int kdSetSensorGpio(int *pBuf) +{ + int ret = 0; +#if 0// serial cam DVT + unsigned int temp = 0; + IMGSENSOR_GPIO_STRUCT *pSensorgpio = (IMGSENSOR_GPIO_STRUCT *)pBuf; + +#define CAMERA_PIN_RDN0_A GPIO172 | 0x80000000 +#define CAMERA_PIN_RDP0_A GPIO173 | 0x80000000 +#define CAMERA_PIN_RDN1_A GPIO174 | 0x80000000 +#define CAMERA_PIN_RCN_A GPIO176 | 0x80000000 +#define CAMERA_PIN_RCP_A GPIO177 | 0x80000000 + + + + +#define CAMERA_PIN_CSI0_A_MODE_MIPI GPIO_MODE_01 +#define CAMERA_PIN_CSI0_A_MODE_SCAM GPIO_MODE_02 + + + PK_DBG("[CAMERA SENSOR] kdSetSensorGpio enable=%d, type=%d\n", + pSensorgpio->GpioEnable, pSensorgpio->SensroInterfaceType); + /* Please use DCT to set correct GPIO setting (below message only for debug) */ + if (pSensorgpio->SensroInterfaceType == SENSORIF_SERIAL) + { + if (pSensorgpio->GpioEnable == 1) + { + mt_set_gpio_mode(CAMERA_PIN_RDN0_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + mt_set_gpio_mode(CAMERA_PIN_RDP0_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + mt_set_gpio_mode(CAMERA_PIN_RDN1_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + mt_set_gpio_mode(CAMERA_PIN_RCN_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + mt_set_gpio_mode(CAMERA_PIN_RCP_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + + } + else + { + mt_set_gpio_mode(CAMERA_PIN_RDN0_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + mt_set_gpio_mode(CAMERA_PIN_RDP0_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + mt_set_gpio_mode(CAMERA_PIN_RDN1_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + mt_set_gpio_mode(CAMERA_PIN_RCN_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + mt_set_gpio_mode(CAMERA_PIN_RCP_A,CAMERA_PIN_CSI0_A_MODE_SCAM); + + } + } +#endif + return ret; +} + +/* PMIC */ +#if !defined(CONFIG_MTK_LEGACY) +bool Get_Cam_Regulator(void) +{ + struct device_node *node = NULL, *kd_node; + if (1) { + /* check if customer camera node defined */ + node = of_find_compatible_node(NULL, NULL, "mediatek,camera_hw"); + + if (node) { + kd_node = sensor_device->of_node; + sensor_device->of_node = node; + /* name = of_get_property(node, "MAIN_CAMERA_POWER_A", NULL); */ + regSubVCAMD = regulator_get(sensor_device, "vcamd_sub"); /*check customer definition*/ + if (regSubVCAMD == NULL) { + if (regVCAMA == NULL) { + regVCAMA = regulator_get(sensor_device, "vcama"); + } + if (regVCAMD == NULL) { + regVCAMD = regulator_get(sensor_device, "vcamd"); + } + if (regVCAMIO == NULL) { + regVCAMIO = regulator_get(sensor_device, "vcamio"); + } + if (regVCAMAF == NULL) { + regVCAMAF = regulator_get(sensor_device, "vcamaf"); + } + } else{ + PK_DBG("Camera customer regulator!\n"); + if (regVCAMA == NULL) { + regVCAMA = regulator_get(sensor_device, "vcama"); + } + if (regVCAMD == NULL) { + regVCAMD = regulator_get(sensor_device, "vcamd"); + } + if (regSubVCAMA == NULL) { + regSubVCAMA = regulator_get(sensor_device, "vcama_sub"); + } + if (regSubVCAMD == NULL) { + regSubVCAMD = regulator_get(sensor_device, "vcamd_sub"); + } + if (regVCAMIO == NULL) { + regVCAMIO = regulator_get(sensor_device, "vcamio"); + } + if (regVCAMAF == NULL) { + regVCAMAF = regulator_get(sensor_device, "vcamaf"); + } + if (regMain2VCAMD == NULL) { + regMain2VCAMD = regulator_get(sensor_device, "vcamd_main2"); + } + /* restore original dev.of_node */ + } + sensor_device->of_node = kd_node; + } else{ + PK_ERR("regulator get cust camera node failed!\n"); + return FALSE; + } + + return TRUE; + } + return FALSE; +} + + +bool _hwPowerOn(PowerType type, int powerVolt) +{ + bool ret = FALSE; + struct regulator *reg = NULL; + + PK_DBG("[_hwPowerOn]powertype:%d powerId:%d\n", type, powerVolt); + if (type == AVDD) { + reg = regVCAMA; + } else if (type == DVDD) { + reg = regVCAMD; + } else if (type == DOVDD) { + reg = regVCAMIO; + } else if (type == AFVDD) { + reg = regVCAMAF; + } else if (type == SUB_AVDD) { + reg = regSubVCAMA; + } else if (type == SUB_DVDD) { + reg = regSubVCAMD; + } else if (type == MAIN2_DVDD) { + reg = regMain2VCAMD; + } else + return ret; + + if (!IS_ERR(reg)) { +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + + if (type == DVDD && powerVolt == Vol_1200){ + PK_DBG("[_hwPowerOn] PMIC_CHIP_MT6353 DVDD 1.2v\n"); + powerVolt = Vol_1220; + if (regulator_set_voltage(reg , powerVolt, powerVolt) != 0) { + PK_ERR("[_hwPowerOn]fail to regulator_set_voltage, powertype:%d powerId:%d\n", type, powerVolt); + return ret; + } + if(pmic_set_register_value(PMIC_RG_VCAMD_CAL,0x1))//-20mv + { + PK_ERR("[_hwPowerOn]fail to set PMIC_RG_VCAMD_CAL, powertype:%d powerId:%d\n", type, powerVolt); + return ret; + } + } else { + if (regulator_set_voltage(reg , powerVolt, powerVolt) != 0) { + PK_ERR("[_hwPowerOn]fail to regulator_set_voltage, powertype:%d powerId:%d\n", type, powerVolt); + return ret; + } + } +#else + if (regulator_set_voltage(reg , powerVolt, powerVolt) != 0) { + PK_ERR("[_hwPowerOn]fail to regulator_set_voltage, powertype:%d powerId:%d\n", type, powerVolt); + return ret; + } +#endif + if (regulator_enable(reg) != 0) { + PK_ERR("[_hwPowerOn]fail to regulator_enable, powertype:%d powerId:%d\n", type, powerVolt); + return ret; + } + ret = true; + } else { + PK_ERR("[_hwPowerOn]IS_ERR_OR_NULL powertype:%d reg %p\n", type,reg); + return ret; + } + + return ret; +} + +bool _hwPowerDown(PowerType type) +{ + bool ret = FALSE; + struct regulator *reg = NULL; + + if (type == AVDD) { + reg = regVCAMA; + } else if (type == DVDD) { + reg = regVCAMD; + } else if (type == DOVDD) { + reg = regVCAMIO; + } else if (type == AFVDD) { + reg = regVCAMAF; + } else if (type == SUB_AVDD) { + reg = regSubVCAMA; + } else if (type == SUB_DVDD) { + reg = regSubVCAMD; + } else if (type == MAIN2_DVDD) { + reg = regMain2VCAMD; + } else + return ret; + + + + if (!IS_ERR(reg)) { + if (regulator_is_enabled(reg) != 0) { + PK_DBG("[_hwPowerDown]%d is enabled\n", type); + if (regulator_disable(reg) != 0) { + PK_ERR("[_hwPowerDown]fail to regulator_disable, powertype: %d\n\n", type); + return ret; + } + } + ret = true; + } else { + PK_ERR("[_hwPowerDown]%d fail to power down due to regVCAM == NULL\n", type); + return ret; + } + return ret; +} + + +#endif + +#ifdef CONFIG_COMPAT + +static int compat_get_acdk_sensor_getinfo_struct( + COMPAT_ACDK_SENSOR_GETINFO_STRUCT __user *data32, + ACDK_SENSOR_GETINFO_STRUCT __user *data) +{ + compat_uint_t i; + compat_uptr_t p; + int err; + + err = get_user(i, &data32->ScenarioId[0]); + err |= put_user(i, &data->ScenarioId[0]); + err = get_user(i, &data32->ScenarioId[1]); + err |= put_user(i, &data->ScenarioId[1]); + err = get_user(p, &data32->pInfo[0]); + err |= put_user(compat_ptr(p), &data->pInfo[0]); + err = get_user(p, &data32->pInfo[1]); + err |= put_user(compat_ptr(p), &data->pInfo[1]); + err = get_user(p, &data32->pInfo[0]); + err |= put_user(compat_ptr(p), &data->pConfig[0]); + err = get_user(p, &data32->pInfo[1]); + err |= put_user(compat_ptr(p), &data->pConfig[1]); + + return err; +} + +static int compat_put_acdk_sensor_getinfo_struct( + COMPAT_ACDK_SENSOR_GETINFO_STRUCT __user *data32, + ACDK_SENSOR_GETINFO_STRUCT __user *data) +{ + compat_uint_t i; + int err; + + err = get_user(i, &data->ScenarioId[0]); + err |= put_user(i, &data32->ScenarioId[0]); + err = get_user(i, &data->ScenarioId[1]); + err |= put_user(i, &data32->ScenarioId[1]); + return err; +} + +static int compat_get_imagesensor_getinfo_struct( + COMPAT_IMAGESENSOR_GETINFO_STRUCT __user *data32, + IMAGESENSOR_GETINFO_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data32->SensorId); + err |= put_user(i, &data->SensorId); + err |= get_user(p, &data32->pInfo); + err |= put_user(compat_ptr(p), &data->pInfo); + err |= get_user(p, &data32->pSensorResolution); + err |= put_user(compat_ptr(p), &data->pSensorResolution); + return err; +} + +static int compat_put_imagesensor_getinfo_struct( + COMPAT_IMAGESENSOR_GETINFO_STRUCT __user *data32, + IMAGESENSOR_GETINFO_STRUCT __user *data) +{ + /* compat_uptr_t p; */ + compat_uint_t i; + int err; + + err = get_user(i, &data->SensorId); + err |= put_user(i, &data32->SensorId); + /* Assume pointer is not change */ +#if 0 + err |= get_user(p, &data->pInfo); + err |= put_user(p, &data32->pInfo); + err |= get_user(p, &data->pSensorResolution); + err |= put_user(p, &data32->pSensorResolution); */ +#endif + return err; +} + +static int compat_get_acdk_sensor_featurecontrol_struct( + COMPAT_ACDK_SENSOR_FEATURECONTROL_STRUCT __user *data32, + ACDK_SENSOR_FEATURECONTROL_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data32->InvokeCamera); + err |= put_user(i, &data->InvokeCamera); + err |= get_user(i, &data32->FeatureId); + err |= put_user(i, &data->FeatureId); + err |= get_user(p, &data32->pFeaturePara); + err |= put_user(compat_ptr(p), &data->pFeaturePara); + err |= get_user(p, &data32->pFeatureParaLen); + err |= put_user(compat_ptr(p), &data->pFeatureParaLen); + return err; +} + +static int compat_put_acdk_sensor_featurecontrol_struct( + COMPAT_ACDK_SENSOR_FEATURECONTROL_STRUCT __user *data32, + ACDK_SENSOR_FEATURECONTROL_STRUCT __user *data) +{ + MUINT8 *p; + MUINT32 *q; + compat_uint_t i; + int err; + + err = get_user(i, &data->InvokeCamera); + err |= put_user(i, &data32->InvokeCamera); + err |= get_user(i, &data->FeatureId); + err |= put_user(i, &data32->FeatureId); + /* Assume pointer is not change */ + + err |= get_user(p, &data->pFeaturePara); + err |= put_user(ptr_to_compat(p), &data32->pFeaturePara); + err |= get_user(q, &data->pFeatureParaLen); + err |= put_user(ptr_to_compat(q), &data32->pFeatureParaLen); + + return err; +} + +static int compat_get_acdk_sensor_control_struct( + COMPAT_ACDK_SENSOR_CONTROL_STRUCT __user *data32, + ACDK_SENSOR_CONTROL_STRUCT __user *data) +{ + compat_uptr_t p; + compat_uint_t i; + int err; + + err = get_user(i, &data32->InvokeCamera); + err |= put_user(i, &data->InvokeCamera); + err |= get_user(i, &data32->ScenarioId); + err |= put_user(i, &data->ScenarioId); + err |= get_user(p, &data32->pImageWindow); + err |= put_user(compat_ptr(p), &data->pImageWindow); + err |= get_user(p, &data32->pSensorConfigData); + err |= put_user(compat_ptr(p), &data->pSensorConfigData); + return err; +} + +static int compat_put_acdk_sensor_control_struct( + COMPAT_ACDK_SENSOR_CONTROL_STRUCT __user *data32, + ACDK_SENSOR_CONTROL_STRUCT __user *data) +{ + /* compat_uptr_t p; */ + compat_uint_t i; + int err; + + err = get_user(i, &data->InvokeCamera); + err |= put_user(i, &data32->InvokeCamera); + err |= get_user(i, &data->ScenarioId); + err |= put_user(i, &data32->ScenarioId); + /* Assume pointer is not change */ +#if 0 + err |= get_user(p, &data->pImageWindow); + err |= put_user(p, &data32->pImageWindow); + err |= get_user(p, &data->pSensorConfigData); + err |= put_user(p, &data32->pSensorConfigData); +#endif + return err; +} + +static int compat_get_acdk_sensor_resolution_info_struct( + COMPAT_ACDK_SENSOR_PRESOLUTION_STRUCT __user *data32, + ACDK_SENSOR_PRESOLUTION_STRUCT __user *data) +{ + int err; + compat_uptr_t p; + err = get_user(p, &data32->pResolution[0]); + err |= put_user(compat_ptr(p), &data->pResolution[0]); + err = get_user(p, &data32->pResolution[1]); + err |= put_user(compat_ptr(p), &data->pResolution[1]); + + /* err = copy_from_user((void*)data, (void*)data32, sizeof(compat_uptr_t) * 2); */ + /* err = copy_from_user((void*)data[0], (void*)data32[0], sizeof(ACDK_SENSOR_RESOLUTION_INFO_STRUCT)); */ + /* err = copy_from_user((void*)data[1], (void*)data32[1], sizeof(ACDK_SENSOR_RESOLUTION_INFO_STRUCT)); */ + return err; +} + +static int compat_put_acdk_sensor_resolution_info_struct( + COMPAT_ACDK_SENSOR_PRESOLUTION_STRUCT __user *data32, + ACDK_SENSOR_PRESOLUTION_STRUCT __user *data) +{ + int err = 0; + /* err = copy_to_user((void*)data, (void*)data32, sizeof(compat_uptr_t) * 2); */ + /* err = copy_to_user((void*)data[0], (void*)data32[0], sizeof(ACDK_SENSOR_RESOLUTION_INFO_STRUCT)); */ + /* err = copy_to_user((void*)data[1], (void*)data32[1], sizeof(ACDK_SENSOR_RESOLUTION_INFO_STRUCT)); */ + return err; +} + + + +static long CAMERA_HW_Ioctl_Compat(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + if (!filp->f_op || !filp->f_op->unlocked_ioctl) + return -ENOTTY; + + switch (cmd) { + case COMPAT_KDIMGSENSORIOC_X_GETINFO: + { + COMPAT_ACDK_SENSOR_GETINFO_STRUCT __user *data32; + ACDK_SENSOR_GETINFO_STRUCT __user *data; + int err; + PK_DBG("[CAMERA SENSOR] CAOMPAT_KDIMGSENSORIOC_X_GETINFO E\n"); + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_acdk_sensor_getinfo_struct(data32, data); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, KDIMGSENSORIOC_X_GETINFO,(unsigned long)data); + err = compat_put_acdk_sensor_getinfo_struct(data32, data); + + if(err != 0) + PK_DBG("[CAMERA SENSOR] compat_put_acdk_sensor_getinfo_struct failed\n"); + return ret; + } + case COMPAT_KDIMGSENSORIOC_X_FEATURECONCTROL: + { + COMPAT_ACDK_SENSOR_FEATURECONTROL_STRUCT __user *data32; + ACDK_SENSOR_FEATURECONTROL_STRUCT __user *data; + int err; + PK_DBG("[CAMERA SENSOR] CAOMPAT_KDIMGSENSORIOC_X_FEATURECONCTROL\n"); + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_acdk_sensor_featurecontrol_struct(data32, data); + if (err) + return err; + + ret = filp->f_op->unlocked_ioctl(filp, KDIMGSENSORIOC_X_FEATURECONCTROL, (unsigned long)data); + err = compat_put_acdk_sensor_featurecontrol_struct(data32, data); + + + if (err != 0) + PK_ERR("[CAMERA SENSOR] compat_put_acdk_sensor_getinfo_struct failed\n"); + return ret; + } + case COMPAT_KDIMGSENSORIOC_X_CONTROL: + { + COMPAT_ACDK_SENSOR_CONTROL_STRUCT __user *data32; + ACDK_SENSOR_CONTROL_STRUCT __user *data; + int err; + PK_DBG("[CAMERA SENSOR] CAOMPAT_KDIMGSENSORIOC_X_CONTROL\n"); + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_acdk_sensor_control_struct(data32, data); + if (err) + return err; + ret = filp->f_op->unlocked_ioctl(filp, KDIMGSENSORIOC_X_CONTROL, (unsigned long)data); + err = compat_put_acdk_sensor_control_struct(data32, data); + + if (err != 0) + PK_ERR("[CAMERA SENSOR] compat_put_acdk_sensor_getinfo_struct failed\n"); + return ret; + } + case COMPAT_KDIMGSENSORIOC_X_GETINFO2: + { + COMPAT_IMAGESENSOR_GETINFO_STRUCT __user *data32; + IMAGESENSOR_GETINFO_STRUCT __user *data; + int err; + PK_DBG("[CAMERA SENSOR] CAOMPAT_KDIMGSENSORIOC_X_GETINFO2\n"); + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(*data)); + if (data == NULL) + return -EFAULT; + + err = compat_get_imagesensor_getinfo_struct(data32, data); + if (err) + return err; + ret = filp->f_op->unlocked_ioctl(filp, KDIMGSENSORIOC_X_GETINFO2, (unsigned long)data); + err = compat_put_imagesensor_getinfo_struct(data32, data); + + if (err != 0) + PK_ERR("[CAMERA SENSOR] compat_put_acdk_sensor_getinfo_struct failed\n"); + return ret; + } + case COMPAT_KDIMGSENSORIOC_X_GETRESOLUTION2: + { + COMPAT_ACDK_SENSOR_PRESOLUTION_STRUCT __user *data32; + ACDK_SENSOR_PRESOLUTION_STRUCT __user *data; + int err; + PK_DBG("[CAMERA SENSOR] KDIMGSENSORIOC_X_GETRESOLUTION2\n"); + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(data)); + if (data == NULL) + return -EFAULT; + PK_DBG("[CAMERA SENSOR] compat_get_acdk_sensor_resolution_info_struct\n"); + err = compat_get_acdk_sensor_resolution_info_struct(data32, data); + if (err) + return err; + PK_DBG("[CAMERA SENSOR] unlocked_ioctl\n"); + ret = filp->f_op->unlocked_ioctl(filp, KDIMGSENSORIOC_X_GETRESOLUTION2, (unsigned long)data); + + err = compat_put_acdk_sensor_resolution_info_struct(data32, data); + if (err != 0) + PK_ERR("[CAMERA SENSOR] compat_get_Acdk_sensor_resolution_info_struct failed\n"); + return ret; + } + /* Data in the following commands is not required to be converted to kernel 64-bit & user 32-bit */ + case KDIMGSENSORIOC_T_OPEN: + case KDIMGSENSORIOC_T_CLOSE: + case KDIMGSENSORIOC_T_CHECK_IS_ALIVE: + case KDIMGSENSORIOC_X_SET_DRIVER: + case KDIMGSENSORIOC_X_GET_SOCKET_POS: + case KDIMGSENSORIOC_X_SET_I2CBUS: + case KDIMGSENSORIOC_X_RELEASE_I2C_TRIGGER_LOCK: + case KDIMGSENSORIOC_X_SET_SHUTTER_GAIN_WAIT_DONE: + case KDIMGSENSORIOC_X_SET_MCLK_PLL: + case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR: + case KDIMGSENSORIOC_X_SET_GPIO: + case KDIMGSENSORIOC_X_GET_ISP_CLK: + return filp->f_op->unlocked_ioctl(filp, cmd, arg); + + default: + return -ENOIOCTLCMD; + } +} + + +#endif + +/******************************************************************************* +* CAMERA_HW_Ioctl +********************************************************************************/ + +static long CAMERA_HW_Ioctl( + struct file *a_pstFile, + unsigned int a_u4Command, + unsigned long a_u4Param +) +{ + + int i4RetValue = 0; + void *pBuff = NULL; + u32 *pIdx = NULL; + + mutex_lock(&kdCam_Mutex); + + + if (_IOC_NONE == _IOC_DIR(a_u4Command)) { + } + else { + pBuff = kmalloc(_IOC_SIZE(a_u4Command), GFP_KERNEL); + + if (NULL == pBuff) { + PK_DBG("[CAMERA SENSOR] ioctl allocate mem failed\n"); + i4RetValue = -ENOMEM; + goto CAMERA_HW_Ioctl_EXIT; + } + + if (_IOC_WRITE & _IOC_DIR(a_u4Command)) { + if (copy_from_user(pBuff , (void *) a_u4Param, _IOC_SIZE(a_u4Command))) { + kfree(pBuff); + PK_DBG("[CAMERA SENSOR] ioctl copy from user failed\n"); + i4RetValue = -EFAULT; + goto CAMERA_HW_Ioctl_EXIT; + } + } + } + + pIdx = (u32 *)pBuff; + switch (a_u4Command) { + +#if 0 + case KDIMGSENSORIOC_X_POWER_ON: + i4RetValue = kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) *pIdx, true, CAMERA_HW_DRVNAME); + break; + case KDIMGSENSORIOC_X_POWER_OFF: + i4RetValue = kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) *pIdx, false, CAMERA_HW_DRVNAME); + break; +#endif + case KDIMGSENSORIOC_X_SET_DRIVER: + i4RetValue = kdSetDriver((unsigned int *)pBuff); + break; + case KDIMGSENSORIOC_T_OPEN: + i4RetValue = adopt_CAMERA_HW_Open(); + break; + case KDIMGSENSORIOC_X_GETINFO: + i4RetValue = adopt_CAMERA_HW_GetInfo(pBuff); + break; + case KDIMGSENSORIOC_X_GETRESOLUTION2: + i4RetValue = adopt_CAMERA_HW_GetResolution(pBuff); + break; + case KDIMGSENSORIOC_X_GETINFO2: + i4RetValue = adopt_CAMERA_HW_GetInfo2(pBuff); + break; + case KDIMGSENSORIOC_X_FEATURECONCTROL: + i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff); + break; + case KDIMGSENSORIOC_X_CONTROL: + i4RetValue = adopt_CAMERA_HW_Control(pBuff); + break; + case KDIMGSENSORIOC_T_CLOSE: + i4RetValue = adopt_CAMERA_HW_Close(); + break; + case KDIMGSENSORIOC_T_CHECK_IS_ALIVE: + i4RetValue = adopt_CAMERA_HW_CheckIsAlive(); + break; + case KDIMGSENSORIOC_X_GET_SOCKET_POS: + i4RetValue = kdGetSocketPostion((unsigned int *)pBuff); + break; + case KDIMGSENSORIOC_X_SET_I2CBUS: + /* i4RetValue = kdSetI2CBusNum(*pIdx); */ + break; + case KDIMGSENSORIOC_X_RELEASE_I2C_TRIGGER_LOCK: + /* i4RetValue = kdReleaseI2CTriggerLock(); */ + break; + + case KDIMGSENSORIOC_X_SET_SHUTTER_GAIN_WAIT_DONE: + i4RetValue = kdSensorSetExpGainWaitDone((int *)pBuff); + break; + + case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR: + i4RetValue = kdSetCurrentSensorIdx(*pIdx); + break; + + case KDIMGSENSORIOC_X_SET_MCLK_PLL: + i4RetValue = kdSetSensorMclk(pBuff); + break; + + case KDIMGSENSORIOC_X_SET_GPIO: + i4RetValue = kdSetSensorGpio(pBuff); + break; + + case KDIMGSENSORIOC_X_GET_ISP_CLK: +#ifdef CONFIG_MTK_SMI_EXT + PK_DBG("KDIMGSENSORIOC_X_GET_ISP_CLK current_mmsys_clk=%d\n", current_mmsys_clk); + if(mmdvfs_get_stable_isp_clk() == MMSYS_CLK_HIGH) + *(unsigned int*)pBuff = 364; + else +#endif + *(unsigned int*)pBuff = 286; + break; + default: + PK_DBG("No such command %d\n",a_u4Command); + i4RetValue = -EPERM; + break; + + } + + if (_IOC_READ & _IOC_DIR(a_u4Command)) { + if (copy_to_user((void __user *) a_u4Param , pBuff , _IOC_SIZE(a_u4Command))) { + kfree(pBuff); + PK_DBG("[CAMERA SENSOR] ioctl copy to user failed\n"); + i4RetValue = -EFAULT; + goto CAMERA_HW_Ioctl_EXIT; + } + } + + kfree(pBuff); +CAMERA_HW_Ioctl_EXIT: + mutex_unlock(&kdCam_Mutex); + return i4RetValue; +} +#ifdef CONFIG_MTK_SMI_EXT +int mmsys_clk_change_cb(int ori_clk_mode, int new_clk_mode) +{ + PK_DBG("mmsys_clk_change_cb ori: %d, new: %d, current_mmsys_clk %d\n", ori_clk_mode, new_clk_mode, current_mmsys_clk); + current_mmsys_clk = new_clk_mode; + return 1; +} +#endif +/******************************************************************************* +* +********************************************************************************/ +/* */ +/* below is for linux driver system call */ +/* change prefix or suffix only */ +/* */ + +/******************************************************************************* + * RegisterCAMERA_HWCharDrv + * #define + * Main jobs: + * 1.check for device-specified errors, device not ready. + * 2.Initialize the device if it is opened for the first time. + * 3.Update f_op pointer. + * 4.Fill data structures into private_data + * CAM_RESET +********************************************************************************/ +static int CAMERA_HW_Open(struct inode *a_pstInode, struct file *a_pstFile) +{ + /* reset once in multi-open */ + if (atomic_read(&g_CamDrvOpenCnt) == 0) { + /* default OFF state */ + /* MUST have */ + /* kdCISModulePowerOn(DUAL_CAMERA_MAIN_SENSOR,"",true,CAMERA_HW_DRVNAME1); */ + /* kdCISModulePowerOn(DUAL_CAMERA_SUB_SENSOR,"",true,CAMERA_HW_DRVNAME1); */ + + /* kdCISModulePowerOn(DUAL_CAMERA_MAIN_SENSOR,"",false,CAMERA_HW_DRVNAME1); */ + /* kdCISModulePowerOn(DUAL_CAMERA_SUB_SENSOR,"",false,CAMERA_HW_DRVNAME1); */ +#ifdef CONFIG_MTK_SMI_EXT + mmdvfs_register_mmclk_switch_cb(mmsys_clk_change_cb, MMDVFS_CLIENT_ID_ISP); +#endif + } + + /* */ + atomic_inc(&g_CamDrvOpenCnt); + return 0; +} + +/******************************************************************************* + * RegisterCAMERA_HWCharDrv + * Main jobs: + * 1.Deallocate anything that "open" allocated in private_data. + * 2.Shut down the device on last close. + * 3.Only called once on last time. + * Q1 : Try release multiple times. +********************************************************************************/ +static int CAMERA_HW_Release(struct inode *a_pstInode, struct file *a_pstFile) +{ + atomic_dec(&g_CamDrvOpenCnt); +#ifdef CONFIG_MTK_SMI_EXT + current_mmsys_clk = MMSYS_CLK_MEDIUM; +#endif +return 0; +} + +static const struct file_operations g_stCAMERA_HW_fops = +{ + .owner = THIS_MODULE, + .open = CAMERA_HW_Open, + .release = CAMERA_HW_Release, + .unlocked_ioctl = CAMERA_HW_Ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = CAMERA_HW_Ioctl_Compat, +#endif + +}; + +#define CAMERA_HW_DYNAMIC_ALLOCATE_DEVNO 1 +/******************************************************************************* +* RegisterCAMERA_HWCharDrv +********************************************************************************/ +inline static int RegisterCAMERA_HWCharDrv(void) +{ + +#if CAMERA_HW_DYNAMIC_ALLOCATE_DEVNO + if (alloc_chrdev_region(&g_CAMERA_HWdevno, 0, 1, CAMERA_HW_DRVNAME1)) + { + PK_DBG("[CAMERA SENSOR] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if (register_chrdev_region(g_CAMERA_HWdevno , 1 , CAMERA_HW_DRVNAME1)) + { + PK_DBG("[CAMERA SENSOR] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + /* Allocate driver */ + g_pCAMERA_HW_CharDrv = cdev_alloc(); + + if (NULL == g_pCAMERA_HW_CharDrv) + { + unregister_chrdev_region(g_CAMERA_HWdevno, 1); + + PK_DBG("[CAMERA SENSOR] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + /* Attatch file operation. */ + cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops); + + g_pCAMERA_HW_CharDrv->owner = THIS_MODULE; + + /* Add to system */ + if (cdev_add(g_pCAMERA_HW_CharDrv, g_CAMERA_HWdevno, 1)) + { + PK_DBG("[mt6516_IDP] Attatch file operation failed\n"); + + unregister_chrdev_region(g_CAMERA_HWdevno, 1); + + return -EAGAIN; + } + + sensor_class = class_create(THIS_MODULE, "sensordrv"); + if (IS_ERR(sensor_class)) { + int ret = PTR_ERR(sensor_class); + PK_DBG("Unable to create class, err = %d\n", ret); + return ret; + } + sensor_device = device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1); + + return 0; +} + +/******************************************************************************* +* UnregisterCAMERA_HWCharDrv +********************************************************************************/ +inline static void UnregisterCAMERA_HWCharDrv(void) +{ + /* Release char driver */ + if(g_pCAMERA_HW_CharDrv != NULL) + cdev_del(g_pCAMERA_HW_CharDrv); + + unregister_chrdev_region(g_CAMERA_HWdevno, 1); + if (!IS_ERR(sensor_class)) { + device_destroy(sensor_class, g_CAMERA_HWdevno); + class_destroy(sensor_class); + } +} +/******************************************************************************* + * i2c relative start +********************************************************************************/ +/******************************************************************************* +* CAMERA_HW_i2c_probe +********************************************************************************/ +static int CAMERA_HW_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i4RetValue = 0; + PK_DBG("[CAMERA_HW] Attach I2C\n"); + + /* get sensor i2c client */ + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient = client; + /* set I2C clock rate */ +/* Vanzo:zhangqingzhan on: Fri, 16 Dec 2016 11:17:55 +0800 + *for i2c init timing + g_pstI2Cclient->timing = 100; + */ + g_pstI2Cclient->timing = 100;/* 200k */ +// End of Vanzo: zhangqingzhan + g_pstI2Cclient->ext_flag &= ~I2C_POLLING_FLAG; /* No I2C polling busy waiting */ + + spin_unlock(&kdsensor_drv_lock); + + /* Register char driver */ + i4RetValue = RegisterCAMERA_HWCharDrv(); + + if (i4RetValue) { + PK_ERR("[CAMERA_HW] register char device failed!\n"); + return i4RetValue; + } + + /* spin_lock_init(&g_CamHWLock); */ +#if !defined(CONFIG_MTK_LEGACY) + Get_Cam_Regulator(); +#endif + + PK_DBG("[CAMERA_HW] Attached!!\n"); + return 0; +} + + +/******************************************************************************* +* CAMERA_HW_i2c_remove +********************************************************************************/ +static int CAMERA_HW_i2c_remove(struct i2c_client *client) +{ + UnregisterCAMERA_HWCharDrv(); + return 0; +} + +#ifdef CONFIG_OF + static const struct of_device_id CAMERA_HW_i2c_of_ids[] = { + { .compatible = "mediatek,camera_main", }, + {} + }; +#endif + +struct i2c_driver CAMERA_HW_i2c_driver = { + .probe = CAMERA_HW_i2c_probe, + .remove = CAMERA_HW_i2c_remove, + .driver = { + .name = CAMERA_HW_DRVNAME1, + .owner = THIS_MODULE, + +#ifdef CONFIG_OF + .of_match_table = CAMERA_HW_i2c_of_ids, +#endif + }, + .id_table = CAMERA_HW_i2c_id, +}; + + +/******************************************************************************* +* i2c relative end +*****************************************************************************/ + + + +/******************************************************************************* + * RegisterCAMERA_HWCharDrv + * #define + * Main jobs: + * 1.check for device-specified errors, device not ready. + * 2.Initialize the device if it is opened for the first time. + * 3.Update f_op pointer. + * 4.Fill data structures into private_data + * CAM_RESET +********************************************************************************/ +static int CAMERA_HW_Open2(struct inode *a_pstInode, struct file *a_pstFile) +{ + /* */ + if (atomic_read(&g_CamDrvOpenCnt2) == 0) { + /* kdCISModulePowerOn(DUAL_CAMERA_MAIN_2_SENSOR,"",true,CAMERA_HW_DRVNAME2); */ + + /* kdCISModulePowerOn(DUAL_CAMERA_MAIN_2_SENSOR,"",false,CAMERA_HW_DRVNAME2); */ + } + atomic_inc(&g_CamDrvOpenCnt2); + return 0; +} + +/******************************************************************************* + * RegisterCAMERA_HWCharDrv + * Main jobs: + * 1.Deallocate anything that "open" allocated in private_data. + * 2.Shut down the device on last close. + * 3.Only called once on last time. + * Q1 : Try release multiple times. +********************************************************************************/ +static int CAMERA_HW_Release2(struct inode *a_pstInode, struct file *a_pstFile) +{ + atomic_dec(&g_CamDrvOpenCnt2); + + return 0; +} + + +static const struct file_operations g_stCAMERA_HW_fops0 = +{ + .owner = THIS_MODULE, + .open = CAMERA_HW_Open2, + .release = CAMERA_HW_Release2, + .unlocked_ioctl = CAMERA_HW_Ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = CAMERA_HW_Ioctl_Compat, +#endif + +}; + + + +/******************************************************************************* +* RegisterCAMERA_HWCharDrv +********************************************************************************/ +inline static int RegisterCAMERA_HWCharDrv2(void) +{ + struct device *sensor_device = NULL; + UINT32 major; + +#if CAMERA_HW_DYNAMIC_ALLOCATE_DEVNO + if (alloc_chrdev_region(&g_CAMERA_HWdevno2, 0, 1, CAMERA_HW_DRVNAME2)) + { + PK_DBG("[CAMERA SENSOR] Allocate device no failed\n"); + + return -EAGAIN; + } +#else + if (register_chrdev_region(g_CAMERA_HWdevno2 , 1 , CAMERA_HW_DRVNAME2)) + { + PK_DBG("[CAMERA SENSOR] Register device no failed\n"); + + return -EAGAIN; + } +#endif + + major = MAJOR(g_CAMERA_HWdevno2); + g_CAMERA_HWdevno2 = MKDEV(major, 0); + + /* Allocate driver */ + g_pCAMERA_HW_CharDrv2 = cdev_alloc(); + + if (NULL == g_pCAMERA_HW_CharDrv2) + { + unregister_chrdev_region(g_CAMERA_HWdevno2, 1); + + PK_DBG("[CAMERA SENSOR] Allocate mem for kobject failed\n"); + + return -ENOMEM; + } + + /* Attatch file operation. */ + cdev_init(g_pCAMERA_HW_CharDrv2, &g_stCAMERA_HW_fops0); + + g_pCAMERA_HW_CharDrv2->owner = THIS_MODULE; + + /* Add to system */ + if (cdev_add(g_pCAMERA_HW_CharDrv2, g_CAMERA_HWdevno2, 1)) + { + PK_DBG("[mt6516_IDP] Attatch file operation failed\n"); + + unregister_chrdev_region(g_CAMERA_HWdevno2, 1); + + return -EAGAIN; + } + + sensor2_class = class_create(THIS_MODULE, "sensordrv2"); + if (IS_ERR(sensor2_class)) { + int ret = PTR_ERR(sensor2_class); + PK_DBG("Unable to create class, err = %d\n", ret); + return ret; + } + sensor_device = device_create(sensor2_class, NULL, g_CAMERA_HWdevno2, NULL, CAMERA_HW_DRVNAME2); + + return 0; +} + +inline static void UnregisterCAMERA_HWCharDrv2(void) +{ + /* Release char driver */ + if(g_pCAMERA_HW_CharDrv2 != NULL) + cdev_del(g_pCAMERA_HW_CharDrv2); + + unregister_chrdev_region(g_CAMERA_HWdevno2, 1); + if (!IS_ERR(sensor2_class)) { + device_destroy(sensor2_class, g_CAMERA_HWdevno2); + class_destroy(sensor2_class); + } +} + + +/******************************************************************************* +* CAMERA_HW_i2c_probe +********************************************************************************/ +static int CAMERA_HW_i2c_probe2(struct i2c_client *client, const struct i2c_device_id *id) +{ + int i4RetValue = 0; + PK_DBG("[CAMERA_HW] Attach I2C0\n"); + + spin_lock(&kdsensor_drv_lock); + + /* get sensor i2c client */ + g_pstI2Cclient2 = client; + + /* set I2C clock rate */ +/* Vanzo:zhangqingzhan on: Fri, 16 Dec 2016 11:18:35 +0800 + *i2c timing + g_pstI2Cclient2->timing = 100; + */ + g_pstI2Cclient2->timing = 100; + +// End of Vanzo: zhangqingzhan + g_pstI2Cclient2->ext_flag &= ~I2C_POLLING_FLAG; /* No I2C polling busy waiting */ + spin_unlock(&kdsensor_drv_lock); + + /* Register char driver */ + i4RetValue = RegisterCAMERA_HWCharDrv2(); + + if (i4RetValue) { + PK_ERR("[CAMERA_HW] register char device failed!\n"); + return i4RetValue; + } + + /* spin_lock_init(&g_CamHWLock); */ + + PK_DBG("[CAMERA_HW] Attached!!\n"); + return 0; +} + +/******************************************************************************* +* CAMERA_HW_i2c_remove +********************************************************************************/ +static int CAMERA_HW_i2c_remove2(struct i2c_client *client) +{ + UnregisterCAMERA_HWCharDrv2(); + return 0; +} + + +/******************************************************************************* +* I2C Driver structure +********************************************************************************/ +#ifdef CONFIG_OF + static const struct of_device_id CAMERA_HW2_i2c_driver_of_ids[] = { + { .compatible = "mediatek,camera_sub", }, + {} + }; +#endif + +struct i2c_driver CAMERA_HW_i2c_driver2 = { + .probe = CAMERA_HW_i2c_probe2, + .remove = CAMERA_HW_i2c_remove2, + .driver = { + .name = CAMERA_HW_DRVNAME2, + .owner = THIS_MODULE, +#if 1 +#ifdef CONFIG_OF + .of_match_table = CAMERA_HW2_i2c_driver_of_ids, +#endif +#endif + }, + .id_table = CAMERA_HW_i2c_id2, +}; + +/******************************************************************************* +* CAMERA_HW_probe +********************************************************************************/ +static int CAMERA_HW_probe(struct platform_device *pdev) +{ +#ifndef CONFIG_MTK_CLKMGR + Get_ccf_clk(pdev); +#endif + +#if !defined(CONFIG_MTK_LEGACY)/*GPIO Pin control*/ + mtkcam_gpio_init(pdev); +#endif + + pCamerahw_platform_device = pdev; + return i2c_add_driver(&CAMERA_HW_i2c_driver); +} + +/******************************************************************************* +* CAMERA_HW_remove() +********************************************************************************/ +static int CAMERA_HW_remove(struct platform_device *pdev) +{ + i2c_del_driver(&CAMERA_HW_i2c_driver); + return 0; +} + +/******************************************************************************* +*CAMERA_HW_suspend() +********************************************************************************/ +static int CAMERA_HW_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + return 0; +} + +/******************************************************************************* + * CAMERA_HW_DumpReg_To_Proc() + * Used to dump some critical sensor register + ********************************************************************************/ +static int CAMERA_HW_resume(struct platform_device *pdev) +{ + return 0; +} + +/******************************************************************************* +* CAMERA_HW_remove +********************************************************************************/ +static int CAMERA_HW_probe2(struct platform_device *pdev) +{ + return i2c_add_driver(&CAMERA_HW_i2c_driver2); +} + +/******************************************************************************* +* CAMERA_HW_remove() +********************************************************************************/ +static int CAMERA_HW_remove2(struct platform_device *pdev) +{ + i2c_del_driver(&CAMERA_HW_i2c_driver2); + return 0; +} + +static int CAMERA_HW_suspend2(struct platform_device *pdev, pm_message_t mesg) +{ + return 0; +} + +/******************************************************************************* + * CAMERA_HW_DumpReg_To_Proc() + * Used to dump some critical sensor register + ********************************************************************************/ +static int CAMERA_HW_resume2(struct platform_device *pdev) +{ + return 0; +} + +/*======================================================================= + * platform driver + *=======================================================================*/ +/* It seems we don't need to use device tree to register device cause we just use i2C part */ +/* You can refer to CAMERA_HW_probe & CAMERA_HW_i2c_probe */ + +#if 1 +#ifdef CONFIG_OF +static const struct of_device_id CAMERA_HW2_of_ids[] = { + { .compatible = "mediatek,camera_hw2", }, + {} +}; +#endif +#endif + +static struct platform_driver g_stCAMERA_HW_Driver2 = { + .probe = CAMERA_HW_probe2, + .remove = CAMERA_HW_remove2, + .suspend = CAMERA_HW_suspend2, + .resume = CAMERA_HW_resume2, + .driver = { + .name = "image_sensor_bus2", + .owner = THIS_MODULE, +#if 1 +#ifdef CONFIG_OF + .of_match_table = CAMERA_HW2_of_ids, +#endif +#endif + + } +}; + +/******************************************************************************* +* iWriteTriggerReg +********************************************************************************/ +#if 0 +int iWriteTriggerReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId) +{ + int i4RetValue = 0; + int u4Index = 0; + u8 *puDataInBytes = (u8 *)&a_u4Data; + int retry = 3; + char puSendCmd[6] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF) , 0 , 0 , 0 , 0}; + + + + SET_I2CBUS_FLAG(gI2CBusNum); + + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient->addr = (i2cId >> 1); + spin_unlock(&kdsensor_drv_lock); + } + else { + spin_lock(&kdsensor_drv_lock); + g_pstI2Cclient2->addr = (i2cId >> 1); + spin_unlock(&kdsensor_drv_lock); + } + + + if (a_u4Bytes > 2) { + PK_DBG("[CAMERA SENSOR] exceed 2 bytes\n"); + return -1; + } + + if (a_u4Data >> (a_u4Bytes << 3)) { + PK_DBG("[CAMERA SENSOR] warning!! some data is not sent!!\n"); + } + + for (u4Index = 0; u4Index < a_u4Bytes; u4Index += 1) { + puSendCmd[(u4Index + 2)] = puDataInBytes[(a_u4Bytes - u4Index-1)]; + } + + do { + if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { + i4RetValue = mt_i2c_master_send(g_pstI2Cclient, puSendCmd, (a_u4Bytes + 2), I2C_3DCAMERA_FLAG); + if (i4RetValue < 0) { + PK_DBG("[CAMERA SENSOR][ERROR]set i2c bus 1 master fail\n"); + CLEAN_I2CBUS_FLAG(gI2CBusNum); + break; + } + } + else { + i4RetValue = mt_i2c_master_send(g_pstI2Cclient2, puSendCmd, (a_u4Bytes + 2), I2C_3DCAMERA_FLAG); + if (i4RetValue < 0) { + PK_DBG("[CAMERA SENSOR][ERROR]set i2c bus 0 master fail\n"); + CLEAN_I2CBUS_FLAG(gI2CBusNum); + break; + } + } + + if (i4RetValue != (a_u4Bytes + 2)) { + PK_DBG("[CAMERA SENSOR] I2C send failed addr = 0x%x, data = 0x%x !!\n", a_u2Addr, a_u4Data); + } + else { + break; + } + uDELAY(50); + } while ((retry--) > 0); + + return i4RetValue; +} +#endif +#if 0 /* linux-3.10 procfs API changed */ +/******************************************************************************* + * CAMERA_HW_Read_Main_Camera_Status() + * Used to detect main camera status + ********************************************************************************/ +static int CAMERA_HW_Read_Main_Camera_Status(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + int len = 0; + p += sprintf(page, "%d\n", g_SensorExistStatus[0]); + + PK_DBG("g_SensorExistStatus[0] = %d\n", g_SensorExistStatus[0]); + *start = page + off; + len = p - page; + if (len > off) + len -= off; + else + len = 0; + return len < count ? len : count; + +} +/******************************************************************************* + * CAMERA_HW_Read_Sub_Camera_Status() + * Used to detect main camera status + ********************************************************************************/ +static int CAMERA_HW_Read_Sub_Camera_Status(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + int len = 0; + p += sprintf(page, "%d\n", g_SensorExistStatus[1]); + + PK_DBG(" g_SensorExistStatus[1] = %d\n", g_SensorExistStatus[1]); + *start = page + off; + len = p - page; + if (len > off) + len -= off; + else + len = 0; + return len < count ? len : count; + +} +/******************************************************************************* + * CAMERA_HW_Read_3D_Camera_Status() + * Used to detect main camera status + ********************************************************************************/ +static int CAMERA_HW_Read_3D_Camera_Status(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + int len = 0; + p += sprintf(page, "%d\n", g_SensorExistStatus[2]); + + PK_DBG("g_SensorExistStatus[2] = %d\n", g_SensorExistStatus[2]); + *start = page + off; + len = p - page; + if (len > off) + len -= off; + else + len = 0; + return len < count ? len : count; + +} +#endif + + +/******************************************************************************* + * CAMERA_HW_DumpReg_To_Proc() + * Used to dump some critical sensor register + ********************************************************************************/ +static ssize_t CAMERA_HW_DumpReg_To_Proc(struct file *file, char __user *data, size_t len, loff_t *ppos) +{ + return 0; +} +static ssize_t CAMERA_HW_DumpReg_To_Proc2(struct file *file, char __user *data, size_t len, loff_t *ppos) +{ + return 0; +} + +static ssize_t CAMERA_HW_DumpReg_To_Proc3(struct file *file, char __user *data, size_t len, loff_t *ppos) +{ + return 0; +} + +/******************************************************************************* + * CAMERA_HW_Reg_Debug() + * Used for sensor register read/write by proc file + ********************************************************************************/ +static ssize_t CAMERA_HW_Reg_Debug(struct file *file, const char *buffer, size_t count, + loff_t *data) +{ + char regBuf[64] = {'\0'}; + u32 u4CopyBufSize = (count < (sizeof(regBuf) - 1)) ? (count) : (sizeof(regBuf) - 1); + + MSDK_SENSOR_REG_INFO_STRUCT sensorReg; + memset(&sensorReg, 0, sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + + if (copy_from_user(regBuf, buffer, u4CopyBufSize)) + return -EFAULT; + + if (sscanf(regBuf, "%x %x", &sensorReg.RegAddr, &sensorReg.RegData) == 2) { + if (g_pSensorFunc != NULL) { + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_MAIN_SENSOR, SENSOR_FEATURE_SET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_MAIN_SENSOR, SENSOR_FEATURE_GET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + PK_DBG("write addr = 0x%08x, data = 0x%08x\n", sensorReg.RegAddr, sensorReg.RegData); + } + } + else if (sscanf(regBuf, "%x", &sensorReg.RegAddr) == 1) { + if (g_pSensorFunc != NULL) { + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_MAIN_SENSOR, SENSOR_FEATURE_GET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + PK_DBG("read addr = 0x%08x, data = 0x%08x\n", sensorReg.RegAddr, sensorReg.RegData); + } + } + + return count; +} + + +static ssize_t CAMERA_HW_Reg_Debug2(struct file *file, const char *buffer, size_t count, + loff_t *data) +{ + char regBuf[64] = {'\0'}; + u32 u4CopyBufSize = (count < (sizeof(regBuf) - 1)) ? (count) : (sizeof(regBuf) - 1); + + MSDK_SENSOR_REG_INFO_STRUCT sensorReg; + memset(&sensorReg, 0, sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + + if (copy_from_user(regBuf, buffer, u4CopyBufSize)) + return -EFAULT; + + if (sscanf(regBuf, "%x %x", &sensorReg.RegAddr, &sensorReg.RegData) == 2) { + if (g_pSensorFunc != NULL) { + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_MAIN_2_SENSOR, SENSOR_FEATURE_SET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_MAIN_2_SENSOR, SENSOR_FEATURE_GET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + PK_DBG("write addr = 0x%08x, data = 0x%08x\n", sensorReg.RegAddr, sensorReg.RegData); + } + } + else if (sscanf(regBuf, "%x", &sensorReg.RegAddr) == 1) { + if (g_pSensorFunc != NULL) { + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_MAIN_2_SENSOR, SENSOR_FEATURE_GET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + PK_DBG("read addr = 0x%08x, data = 0x%08x\n", sensorReg.RegAddr, sensorReg.RegData); + } + } + + return count; +} + +static ssize_t CAMERA_HW_Reg_Debug3(struct file *file, const char *buffer, size_t count, + loff_t *data) +{ + char regBuf[64] = {'\0'}; + u32 u4CopyBufSize = (count < (sizeof(regBuf) - 1)) ? (count) : (sizeof(regBuf) - 1); + + MSDK_SENSOR_REG_INFO_STRUCT sensorReg; + memset(&sensorReg, 0, sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + + if (copy_from_user(regBuf, buffer, u4CopyBufSize)) + return -EFAULT; + + if (sscanf(regBuf, "%x %x", &sensorReg.RegAddr, &sensorReg.RegData) == 2) { + if (g_pSensorFunc != NULL) { + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_SUB_SENSOR, SENSOR_FEATURE_SET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_SUB_SENSOR, SENSOR_FEATURE_GET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + PK_DBG("write addr = 0x%08x, data = 0x%08x\n", sensorReg.RegAddr, sensorReg.RegData); + } + } + else if (sscanf(regBuf, "%x", &sensorReg.RegAddr) == 1) { + if (g_pSensorFunc != NULL) { + g_pSensorFunc->SensorFeatureControl(DUAL_CAMERA_SUB_SENSOR, SENSOR_FEATURE_GET_REGISTER, (MUINT8 *)&sensorReg, (MUINT32 *)sizeof(MSDK_SENSOR_REG_INFO_STRUCT)); + PK_DBG("read addr = 0x%08x, data = 0x%08x\n", sensorReg.RegAddr, sensorReg.RegData); + } + } + + return count; +} + +/*======================================================================= + * platform driver + *=======================================================================*/ + +/* It seems we don't need to use device tree to register device cause we just use i2C part */ +/* You can refer to CAMERA_HW_probe & CAMERA_HW_i2c_probe */ +#ifdef CONFIG_OF +static const struct of_device_id CAMERA_HW_of_ids[] = { + { .compatible = "mediatek,camera_hw", }, + {} +}; +#endif + +static struct platform_driver g_stCAMERA_HW_Driver = { + .probe = CAMERA_HW_probe, + .remove = CAMERA_HW_remove, + .suspend = CAMERA_HW_suspend, + .resume = CAMERA_HW_resume, + .driver = { + .name = "image_sensor", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = CAMERA_HW_of_ids, +#endif + } +}; + +#ifndef CONFIG_OF +static struct platform_device camerahw2_platform_device = { + .name = "image_sensor_bus2", + .id = 0, + .dev = { + } +}; +#endif + + +static struct file_operations fcamera_proc_fops = { + .read = CAMERA_HW_DumpReg_To_Proc, + .write = CAMERA_HW_Reg_Debug +}; +static struct file_operations fcamera_proc_fops2 = { + .read = CAMERA_HW_DumpReg_To_Proc2, + .write = CAMERA_HW_Reg_Debug2 +}; +static struct file_operations fcamera_proc_fops3 = { + .read = CAMERA_HW_DumpReg_To_Proc3, + .write = CAMERA_HW_Reg_Debug3 +}; + +/* Camera information */ +static int subsys_camera_info_read(struct seq_file *m, void *v) +{ + PK_ERR("subsys_camera_info_read %s\n",mtk_ccm_name); + seq_printf(m, "%s\n",mtk_ccm_name); + return 0; +}; + +static int proc_camera_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, subsys_camera_info_read, NULL); +}; + +static struct file_operations fcamera_proc_fops1 = { + .owner = THIS_MODULE, + .open = proc_camera_info_open, + .read = seq_read, +}; + +/*======================================================================= + * CAMERA_HW_i2C_init() + *=======================================================================*/ +static int __init CAMERA_HW_i2C_init(void) +{ + +#if 0 + struct proc_dir_entry *prEntry; +#endif +#if defined(CONFIG_MTK_LEGACY) + /* i2c_register_board_info(CAMERA_I2C_BUSNUM, &kd_camera_dev, 1); */ + if(SUPPORT_I2C_BUS_NUM1 != SUPPORT_I2C_BUS_NUM2) //Main2 Support + { + i2c_register_board_info(SUPPORT_I2C_BUS_NUM1, &i2c_devs1, 1); + i2c_register_board_info(SUPPORT_I2C_BUS_NUM2, &i2c_devs2, 1); + } + else + { + i2c_register_board_info(SUPPORT_I2C_BUS_NUM1, &i2c_devs1, 1); + i2c_register_board_info(SUPPORT_I2C_BUS_NUM3, &i2c_devs2, 1); + } +#endif + PK_DBG("[camerahw_probe] start\n"); + +#ifndef CONFIG_OF + int ret = 0; + ret = platform_device_register(&camerahw_platform_device); + if (ret) { + PK_ERR("[camerahw_probe] platform_device_register fail\n"); + return ret; + } + + ret = platform_device_register(&camerahw2_platform_device); + if (ret) { + PK_ERR("[camerahw2_probe] platform_device_register fail\n"); + return ret; + } +#endif + + if (platform_driver_register(&g_stCAMERA_HW_Driver)) { + PK_ERR("failed to register CAMERA_HW driver\n"); + return -ENODEV; + } + if (platform_driver_register(&g_stCAMERA_HW_Driver2)) { + PK_ERR("failed to register CAMERA_HW driver\n"); + return -ENODEV; + } +/* FIX-ME: linux-3.10 procfs API changed */ +#if 1 + proc_create("driver/camsensor", 0, NULL, &fcamera_proc_fops); + proc_create("driver/camsensor2", 0, NULL, &fcamera_proc_fops2); + proc_create("driver/camsensor3", 0, NULL, &fcamera_proc_fops3); + + /* Camera information */ + memset(mtk_ccm_name,0,camera_info_size); + proc_create(PROC_CAMERA_INFO, 0, NULL, &fcamera_proc_fops1); + +#else + /* Register proc file for main sensor register debug */ + prEntry = create_proc_entry("driver/camsensor", 0, NULL); + if (prEntry) { + prEntry->read_proc = CAMERA_HW_DumpReg_To_Proc; + prEntry->write_proc = CAMERA_HW_Reg_Debug; + } + else { + PK_ERR("add /proc/driver/camsensor entry fail\n"); + } + + /* Register proc file for main_2 sensor register debug */ + prEntry = create_proc_entry("driver/camsensor2", 0, NULL); + if (prEntry) { + prEntry->read_proc = CAMERA_HW_DumpReg_To_Proc; + prEntry->write_proc = CAMERA_HW_Reg_Debug2; + } + else { + PK_ERR("add /proc/driver/camsensor2 entry fail\n"); + } + + /* Register proc file for sub sensor register debug */ + prEntry = create_proc_entry("driver/camsensor3", 0, NULL); + if (prEntry) { + prEntry->read_proc = CAMERA_HW_DumpReg_To_Proc; + prEntry->write_proc = CAMERA_HW_Reg_Debug3; + } + else { + PK_ERR("add /proc/driver/camsensor entry fail\n"); + } + + /* Register proc file for main sensor register debug */ + prEntry = create_proc_entry("driver/maincam_status", 0, NULL); + if (prEntry) { + prEntry->read_proc = CAMERA_HW_Read_Main_Camera_Status; + prEntry->write_proc = NULL; + } + else { + PK_ERR("add /proc/driver/maincam_status entry fail\n"); + } + + /* Register proc file for sub sensor register debug */ + prEntry = create_proc_entry("driver/subcam_status", 0, NULL); + if (prEntry) { + prEntry->read_proc = CAMERA_HW_Read_Sub_Camera_Status; + prEntry->write_proc = NULL; + } + else { + PK_ERR("add /proc/driver/subcam_status entry fail\n"); + } + + /* Register proc file for 3d sensor register debug */ + prEntry = create_proc_entry("driver/3dcam_status", 0, NULL); + if (prEntry) { + prEntry->read_proc = CAMERA_HW_Read_3D_Camera_Status; + prEntry->write_proc = NULL; + } + else { + PK_ERR("add /proc/driver/3dcam_status entry fail\n"); + } + +#endif + atomic_set(&g_CamHWOpend, 0); + atomic_set(&g_CamHWOpend2, 0); + atomic_set(&g_CamDrvOpenCnt, 0); + atomic_set(&g_CamDrvOpenCnt2, 0); + atomic_set(&g_CamHWOpening, 0); + + + + return 0; +} + +/*======================================================================= + * CAMERA_HW_i2C_exit() + *=======================================================================*/ +static void __exit CAMERA_HW_i2C_exit(void) +{ + platform_driver_unregister(&g_stCAMERA_HW_Driver); + platform_driver_unregister(&g_stCAMERA_HW_Driver2); +} + + +EXPORT_SYMBOL(kdSetSensorSyncFlag); +EXPORT_SYMBOL(kdSensorSyncFunctionPtr); +EXPORT_SYMBOL(kdGetRawGainInfoPtr); + +module_init(CAMERA_HW_i2C_init); +module_exit(CAMERA_HW_i2C_exit); + +MODULE_DESCRIPTION("CAMERA_HW driver"); +MODULE_AUTHOR("Jackie Su "); +MODULE_LICENSE("GPL"); + + + + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/kd_sensorlist.h b/drivers/misc/mediatek/imgsensor/src/mt6755/kd_sensorlist.h new file mode 100755 index 0000000000000000000000000000000000000000..c2e75e378ae6a118432a79da607013adfaf413d2 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/kd_sensorlist.h @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +//s_add new sensor driver here +//export funtions +/*IMX*/ +UINT32 IMX220_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX219_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX214_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX179_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX178_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX132_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX135_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX105_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX073_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX258_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*OV*/ +UINT32 OV16825MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV13850_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV12830_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV9760MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV9740_MIPI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV9726_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT * pfFunc); +UINT32 OV9726MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT * pfFunc); +UINT32 OV8865_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV8856_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV8858_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV8830SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV8825_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV7675_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5693_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5670_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5650SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5650MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5648MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5647MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5647SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5645_MIPI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5642_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5642_MIPI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5642_MIPI_RGB_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5642_MIPI_JPG_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5642_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV5642_YUV_SWI2C_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV4688_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV3640SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV3640_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV2722MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV2680MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV2659_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV2655_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 OV2650SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*S5K*/ +UINT32 S5K2P8_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K3L8_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K3P3SX_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K3P3SQ_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K3M2_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K3H2YX_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K3H7Y_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K4H5YC_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K4H5YX_2LANE_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K5E2YA_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K5CAGX_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K4E1GA_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K4ECGX_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K4ECGX_MIPI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K4ECGX_MIPI_JPG_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K8AAYX_MIPI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 S5K8AAYX_PVI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*HI*/ +UINT32 HI841_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI707_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI704_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI551_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI553_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI545_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI544_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI542_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI542_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI253_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 HI191MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*MT*/ +UINT32 MT9P012SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9P015SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9P017SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9P017MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9T113_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9V113_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9T113MIPI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9V114_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9D115MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 MT9V115_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*GC*/ +UINT32 GC5025MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 GC5005MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 GC2355_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 GC2235_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 GC2035_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 GC0330_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 GC0329_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 GC0313MIPI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 GC0310_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 IMX215_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*SP*/ +UINT32 SP0A19_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 SP0A20_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*A*/ +UINT32 A5141_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 A5142_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*HM*/ +UINT32 HM3451SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*AR*/ +UINT32 AR0833_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*SIV*/ +UINT32 SIV120B_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 SIV121D_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*PAS (PixArt Image)*/ +UINT32 PAS6180_SERIAL_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*Panasoic*/ +UINT32 MN34152_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*Toshiba*/ +UINT32 T4K28_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 T4KA7_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +/*Others*/ +UINT32 ISX012_MIPI_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); +UINT32 T8EV5_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc); + +//! Add Sensor Init function here +//! Note: +//! 1. Add by the resolution from ""large to small"", due to large sensor +//! will be possible to be main sensor. +//! This can avoid I2C error during searching sensor. +//! 2. This file should be the same as mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp +ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] = +{ +/*IMX*/ +#if defined(IMX220_MIPI_RAW) + {IMX220_SENSOR_ID, SENSOR_DRVNAME_IMX220_MIPI_RAW, IMX220_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX219_MIPI_RAW) + {IMX219_SENSOR_ID, SENSOR_DRVNAME_IMX219_MIPI_RAW, IMX219_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX214_MIPI_RAW) + {IMX214_SENSOR_ID, SENSOR_DRVNAME_IMX214_MIPI_RAW, IMX214_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX215_MIPI_RAW) + {IMX215_SENSOR_ID, SENSOR_DRVNAME_IMX215_MIPI_RAW, IMX215_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX179_MIPI_RAW) + {IMX179_SENSOR_ID, SENSOR_DRVNAME_IMX179_MIPI_RAW,IMX179_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX178_MIPI_RAW) + {IMX178_SENSOR_ID, SENSOR_DRVNAME_IMX178_MIPI_RAW,IMX178_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX132_MIPI_RAW) + {IMX132MIPI_SENSOR_ID, SENSOR_DRVNAME_IMX132_MIPI_RAW, IMX132_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX135_MIPI_RAW) + {IMX135_SENSOR_ID, SENSOR_DRVNAME_IMX135_MIPI_RAW, IMX135_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX105_MIPI_RAW) + {IMX105_SENSOR_ID, SENSOR_DRVNAME_IMX105_MIPI_RAW, IMX105_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX073_MIPI_RAW) + {IMX073_SENSOR_ID, SENSOR_DRVNAME_IMX073_MIPI_RAW, IMX073_MIPI_RAW_SensorInit}, +#endif +#if defined(IMX258_MIPI_RAW) + {IMX258_SENSOR_ID, SENSOR_DRVNAME_IMX258_MIPI_RAW, IMX258_MIPI_RAW_SensorInit}, +#endif + +/*OV (OmniVision)*/ +#if defined(OV16825_MIPI_RAW) + {OV16825MIPI_SENSOR_ID, SENSOR_DRVNAME_OV16825_MIPI_RAW, OV16825MIPISensorInit}, +#endif +#if defined(OV13850_MIPI_RAW) + {OV13850_SENSOR_ID, SENSOR_DRVNAME_OV13850_MIPI_RAW,OV13850_MIPI_RAW_SensorInit}, +#endif +#if defined(OV12830_MIPI_RAW) + {OV12830_SENSOR_ID, SENSOR_DRVNAME_OV12830_MIPI_RAW, OV12830_MIPI_RAW_SensorInit}, +#endif +#if defined(OV9760_MIPI_RAW) + {OV9760MIPI_SENSOR_ID,SENSOR_DRVNAME_OV9760_MIPI_RAW,OV9760MIPI_RAW_SensorInit}, +#endif +#if defined(OV9740_MIPI_YUV) + {OV9740MIPI_SENSOR_ID, SENSOR_DRVNAME_OV9740_MIPI_YUV, OV9740_MIPI_YUV_SensorInit}, +#endif +#if defined(OV9726_RAW) + {OV9726_SENSOR_ID,SENSOR_DRVNAME_0V9726_RAW,OV9726_RAW_SensorInit}, +#endif +#if defined(OV9726_MIPI_RAW) + {OV9726MIPI_SENSOR_ID,SENSOR_DRVNAME_OV9726_MIPI_RAW,OV9726MIPI_RAW_SensorInit}, +#endif +#if defined(OV8865_MIPI_RAW) + {OV8865_SENSOR_ID, SENSOR_DRVNAME_OV8865_MIPI_RAW,OV8865_MIPI_RAW_SensorInit}, +#endif +#if defined(OV8856_MIPI_RAW) + {OV8856_SENSOR_ID, SENSOR_DRVNAME_OV8856_MIPI_RAW,OV8856_MIPI_RAW_SensorInit}, +#endif +#if defined(OV8858_MIPI_RAW) + {OV8858_SENSOR_ID, SENSOR_DRVNAME_OV8858_MIPI_RAW,OV8858_MIPI_RAW_SensorInit}, +#endif + +#if defined(OV8830_RAW) + {OV8830_SENSOR_ID, SENSOR_DRVNAME_OV8830_RAW, OV8830SensorInit}, +#endif + +#if defined(OV8825_MIPI_RAW) + {OV8825_SENSOR_ID, SENSOR_DRVNAME_OV8825_MIPI_RAW, OV8825_MIPI_RAW_SensorInit}, +#endif +#if defined(OV7675_YUV) + {OV7675_SENSOR_ID, SENSOR_DRVNAME_OV7675_YUV, OV7675_YUV_SensorInit}, +#endif +#if defined(OV5693_MIPI_RAW) + {OV5693_SENSOR_ID, SENSOR_DRVNAME_OV5693_MIPI_RAW, OV5693_MIPI_RAW_SensorInit}, +#endif +#if defined(OV5670_MIPI_RAW) + {OV5670MIPI_SENSOR_ID, SENSOR_DRVNAME_OV5670_MIPI_RAW, OV5670_MIPI_RAW_SensorInit}, +#endif +#if defined(OV5650_RAW) + {OV5650_SENSOR_ID, SENSOR_DRVNAME_OV5650_RAW,OV5650SensorInit}, +#endif +#if defined(OV5650MIPI_RAW) + {OV5650MIPI_SENSOR_ID, SENSOR_DRVNAME_OV5650MIPI_RAW,OV5650MIPISensorInit}, +#endif +#if defined(OV5648_MIPI_RAW) + {OV5648MIPI_SENSOR_ID, SENSOR_DRVNAME_OV5648_MIPI_RAW, OV5648MIPISensorInit}, +#endif +#if defined(OV5647_MIPI_RAW) + {OV5647MIPI_SENSOR_ID, SENSOR_DRVNAME_OV5647MIPI_RAW, OV5647MIPISensorInit}, +#endif +#if defined(OV5647_RAW) + {OV5647_SENSOR_ID, SENSOR_DRVNAME_OV5647_RAW, OV5647SensorInit}, +#endif +#if defined(OV5645_MIPI_YUV) + {OV5645MIPI_SENSOR_ID,SENSOR_DRVNAME_OV5645_MIPI_YUV, OV5645_MIPI_YUV_SensorInit}, +#endif +#if defined(OV5642_RAW) + {OV5642_SENSOR_ID, SENSOR_DRVNAME_OV5642_RAW, OV5642_RAW_SensorInit}, +#endif +#if defined(OV5642_MIPI_YUV) + {OV5642_SENSOR_ID, SENSOR_DRVNAME_OV5642_MIPI_YUV, OV5642_MIPI_YUV_SensorInit}, +#endif +#if defined(OV5642_MIPI_RGB) + {OV5642_SENSOR_ID, SENSOR_DRVNAME_OV5642_MIPI_RGB, OV5642_MIPI_RGB_SensorInit}, +#endif +#if defined(OV5642_MIPI_JPG) + {OV5642_SENSOR_ID, SENSOR_DRVNAME_OV5642_MIPI_JPG, OV5642_MIPI_JPG_SensorInit}, +#endif +#if defined(OV5642_YUV) + {OV5642_SENSOR_ID, SENSOR_DRVNAME_OV5642_YUV, OV5642_YUV_SensorInit}, +#endif +#if defined(OV4688_MIPI_RAW) + {OV4688MIPI_SENSOR_ID, SENSOR_DRVNAME_OV4688_MIPI_RAW, OV4688_MIPI_RAW_SensorInit}, +#endif +#if defined(OV3640_RAW) + {OV3640_SENSOR_ID, SENSOR_DRVNAME_OV3640_RAW,OV3640SensorInit}, +#endif +#if defined(OV3640_YUV) + {OV3640_SENSOR_ID, SENSOR_DRVNAME_OV3640_YUV, OV3640_YUV_SensorInit}, +#endif +#if defined(OV3640_YUV_AF) + {OV3640_SENSOR_ID, SENSOR_DRVNAME_OV3640_YUV, OV3640_YUV_SensorInit}, +#endif +#if defined(OV2680_MIPI_RAW) + {OV2680MIPI_SENSOR_ID, SENSOR_DRVNAME_OV2680_MIPI_RAW,OV2680MIPISensorInit}, +#endif +#if defined(OV2722_MIPI_RAW) + {OV2722MIPI_SENSOR_ID, SENSOR_DRVNAME_OV2722_MIPI_RAW, OV2722MIPI_RAW_SensorInit}, +#endif +#if defined(OV2659_YUV) + {OV2659_SENSOR_ID, SENSOR_DRVNAME_OV2659_YUV,OV2659_YUV_SensorInit}, +#endif +#if defined(OV2655_YUV) + {OV2650_SENSOR_ID, SENSOR_DRVNAME_OV2655_YUV,OV2655_YUV_SensorInit}, +#endif +#if defined(OV2650_RAW) + {OV2650_SENSOR_ID, SENSOR_DRVNAME_OV2650_RAW,OV2650SensorInit}, +#endif +/*S5K*/ +#if defined(S5K2P8_MIPI_RAW) + {S5K2P8_SENSOR_ID, SENSOR_DRVNAME_S5K2P8_MIPI_RAW, S5K2P8_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K3L8_MIPI_RAW) + {S5K3L8_SENSOR_ID, SENSOR_DRVNAME_S5K3L8_MIPI_RAW, S5K3L8_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K3M2_MIPI_RAW) + {S5K3M2_SENSOR_ID, SENSOR_DRVNAME_S5K3M2_MIPI_RAW, S5K3M2_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K3P3SX_MIPI_RAW) + {S5K3P3SX_SENSOR_ID, SENSOR_DRVNAME_S5K3P3SX_MIPI_RAW, S5K3P3SX_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K3P3SQ_MIPI_RAW) + {S5K3P3SQ_SENSOR_ID, SENSOR_DRVNAME_S5K3P3SQ_MIPI_RAW, S5K3P3SQ_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K3H2YX_MIPI_RAW) + {S5K3H2YX_SENSOR_ID, SENSOR_DRVNAME_S5K3H2YX_MIPI_RAW, S5K3H2YX_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K3H7Y_MIPI_RAW) + {S5K3H7Y_SENSOR_ID, SENSOR_DRVNAME_S5K3H7Y_MIPI_RAW, S5K3H7Y_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K4H5YC_MIPI_RAW) + {S5K4H5YC_SENSOR_ID, SENSOR_DRVNAME_S5K4H5YC_MIPI_RAW, S5K4H5YC_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K4H5YX_2LANE_MIPI_RAW) + {S5K4H5YX_2LANE_SENSOR_ID, SENSOR_DRVNAME_S5K4H5YX_2LANE_MIPI_RAW, S5K4H5YX_2LANE_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K5E2YA_MIPI_RAW) + {S5K5E2YA_SENSOR_ID, SENSOR_DRVNAME_S5K5E2YA_MIPI_RAW, S5K5E2YA_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K5CAGX_YUV) + {S5K5CAGX_SENSOR_ID, SENSOR_DRVNAME_S5K5CAGX_YUV, S5K5CAGX_YUV_SensorInit}, +#endif +#if defined(S5K4E1GA_MIPI_RAW) + {S5K4E1GA_SENSOR_ID, SENSOR_DRVNAME_S5K4E1GA_MIPI_RAW, S5K4E1GA_MIPI_RAW_SensorInit}, +#endif +#if defined(S5K4ECGX_YUV) + {S5K4ECGX_SENSOR_ID, SENSOR_DRVNAME_S5K4ECGX_YUV, S5K4ECGX_YUV_SensorInit}, +#endif +#if defined(S5K4ECGX_MIPI_YUV) + {S5K4ECGX_SENSOR_ID, SENSOR_DRVNAME_S5K4ECGX_MIPI_YUV, S5K4ECGX_MIPI_YUV_SensorInit}, +#endif +#if defined(S5K4ECGX_MIPI_JPG) + {S5K4ECGX_SENSOR_ID, SENSOR_DRVNAME_S5K4ECGX_MIPI_JPG, S5K4ECGX_MIPI_JPG_SensorInit}, +#endif +#if defined(S5K8AAYX_MIPI_YUV) + {S5K8AAYX_MIPI_SENSOR_ID, SENSOR_DRVNAME_S5K8AAYX_MIPI_YUV, S5K8AAYX_MIPI_YUV_SensorInit}, +#endif +#if defined(S5K8AAYX_YUV) + {S5K8AAYX_MIPI_SENSOR_ID, SENSOR_DRVNAME_S5K8AAYX_YUV, S5K8AAYX_PVI_YUV_SensorInit}, +#endif +/*HI*/ +#if defined(HI841_MIPI_RAW) + {HI841_SENSOR_ID, SENSOR_DRVNAME_HI841_MIPI_RAW,HI841_MIPI_RAW_SensorInit}, +#endif +#if defined(HI707_YUV) + {HI707_SENSOR_ID, SENSOR_DRVNAME_HI707_YUV, HI707_YUV_SensorInit}, +#endif +#if defined(HI704_YUV) + {HI704_SENSOR_ID, SENSOR_DRVNAME_HI704_YUV, HI704_YUV_SensorInit}, +#endif +#if defined(HI551_MIPI_RAW) + {HI551_SENSOR_ID, SENSOR_DRVNAME_HI551_MIPI_RAW,HI551_MIPI_RAW_SensorInit}, +#endif +#if defined(HI553_MIPI_RAW) + {HI553_SENSOR_ID, SENSOR_DRVNAME_HI553_MIPI_RAW,HI553_MIPI_RAW_SensorInit}, +#endif +#if defined(HI545_MIPI_RAW) + {HI545MIPI_SENSOR_ID, SENSOR_DRVNAME_HI545_MIPI_RAW, HI545_MIPI_RAW_SensorInit}, +#endif +#if defined(HI544_MIPI_RAW) + {HI544MIPI_SENSOR_ID, SENSOR_DRVNAME_HI544_MIPI_RAW, HI544_MIPI_RAW_SensorInit}, +#endif +#if defined(HI542_RAW) + {HI542_SENSOR_ID, SENSOR_DRVNAME_HI542_RAW, HI542_RAW_SensorInit}, +#endif +#if defined(HI542_MIPI_RAW) + {HI542MIPI_SENSOR_ID, SENSOR_DRVNAME_HI542MIPI_RAW, HI542_MIPI_RAW_SensorInit}, +#endif +#if defined(HI253_YUV) + {HI253_SENSOR_ID, SENSOR_DRVNAME_HI253_YUV, HI253_YUV_SensorInit}, +#endif +#if defined(HI191_MIPI_RAW) + {HI191MIPI_SENSOR_ID, SENSOR_DRVNAME_HI191_MIPI_RAW, HI191MIPI_RAW_SensorInit}, +#endif +/*MT*/ +#if defined(MT9P012_RAW) + {MT9P012_SENSOR_ID, SENSOR_DRVNAME_MT9P012_RAW,MT9P012SensorInit}, +#endif +#if defined(MT9P015_RAW) + {MT9P015_SENSOR_ID, SENSOR_DRVNAME_MT9P015_RAW,MT9P015SensorInit}, +#endif +#if defined(MT9P017_RAW) + {MT9P017_SENSOR_ID, SENSOR_DRVNAME_MT9P017_RAW,MT9P017SensorInit}, +#endif +#if defined(MT9P017_MIPI_RAW) + {MT9P017MIPI_SENSOR_ID, SENSOR_DRVNAME_MT9P017_MIPI_RAW,MT9P017MIPISensorInit}, +#endif +#if defined(MT9T113_YUV) + {MT9T113_SENSOR_ID, SENSOR_DRVNAME_MT9T113_YUV, MT9T113_YUV_SensorInit}, +#endif +#if defined(MT9T113_MIPI_YUV) + {MT9T113MIPI_SENSOR_ID, SENSOR_DRVNAME_MT9T113_MIPI_YUV,MT9T113MIPI_YUV_SensorInit}, +#endif +#if defined(MT9V113_YUV) + {MT9V113_SENSOR_ID, SENSOR_DRVNAME_MT9V113_YUV, MT9V113_YUV_SensorInit}, +#endif +#if defined(MT9V114_YUV) + {MT9V114_SENSOR_ID, SENSOR_DRVNAME_MT9V114_YUV, MT9V114_YUV_SensorInit}, +#endif +#if defined(MT9D115_MIPI_RAW) + {MT9D115_SENSOR_ID, SENSOR_DRVNAME_MT9D115_MIPI_RAW,MT9D115MIPISensorInit}, +#endif +#if defined(MT9V115_YUV) + {MT9V115_SENSOR_ID,SENSOR_DRVNAME_MT9V115_YUV,MT9V115_YUV_SensorInit}, +#endif +/*GC*/ +#if defined(GC5025MIPI_RAW) + {GC5025MIPI_SENSOR_ID, SENSOR_DRVNAME_GC5025_MIPI_RAW, GC5025MIPI_RAW_SensorInit}, +#endif +#if defined(GC5005_MIPI_RAW) + {GC5005MIPI_SENSOR_ID, SENSOR_DRVNAME_GC5005_MIPI_RAW, GC5005MIPI_RAW_SensorInit}, +#endif +#if defined(GC2355_MIPI_RAW) + {GC2355_SENSOR_ID, SENSOR_DRVNAME_GC2355_MIPI_RAW,GC2355_MIPI_RAW_SensorInit}, +#endif +#if defined(GC2235_RAW) + {GC2235_SENSOR_ID, SENSOR_DRVNAME_GC2235_RAW, GC2235_RAW_SensorInit}, +#endif +#if defined(GC2035_YUV) + {GC2035_SENSOR_ID, SENSOR_DRVNAME_GC2035_YUV, GC2035_YUV_SensorInit}, +#endif +#if defined(GC0330_YUV) + {GC0330_SENSOR_ID, SENSOR_DRVNAME_GC0330_YUV, GC0330_YUV_SensorInit}, +#endif +#if defined(GC0329_YUV) + {GC0329_SENSOR_ID, SENSOR_DRVNAME_GC0329_YUV, GC0329_YUV_SensorInit}, +#endif +#if defined(GC0313_MIPI_YUV) + {GC0313MIPI_YUV_SENSOR_ID, SENSOR_DRVNAME_GC0313MIPI_YUV, GC0313MIPI_YUV_SensorInit}, +#endif +#if defined(GC0310_YUV) + {GC0310_SENSOR_ID, SENSOR_DRVNAME_GC0310_YUV,GC0310_YUV_SensorInit}, +#endif +/*SP*/ +#if defined(SP0A19_YUV) + {SP0A19_YUV_SENSOR_ID, SENSOR_DRVNAME_SP0A19_YUV, SP0A19_YUV_SensorInit}, +#endif +#if defined(SP0A20_MIPI_YUV) + {SP0A20_SENSOR_ID, SENSOR_DRVNAME_SP0A20_YUV, SP0A20_YUV_SensorInit}, +#endif +/*A*/ +#if defined(A5141_MIPI_RAW) + {A5141MIPI_SENSOR_ID, SENSOR_DRVNAME_A5141_MIPI_RAW,A5141_MIPI_RAW_SensorInit}, +#endif +#if defined(A5142_MIPI_RAW) + {A5142MIPI_SENSOR_ID, SENSOR_DRVNAME_A5142_MIPI_RAW,A5142_MIPI_RAW_SensorInit}, +#endif +/*HM*/ +#if defined(HM3451_RAW) + {HM3451_SENSOR_ID, SENSOR_DRVNAME_HM3451_RAW, HM3451SensorInit}, +#endif +/*AR*/ +#if defined(AR0833_MIPI_RAW) + {AR0833_SENSOR_ID, SENSOR_DRVNAME_AR0833_MIPI_RAW,AR0833_MIPI_RAW_SensorInit}, +#endif +/*SIV*/ +#if defined(SIV120B_YUV) + {SIV120B_SENSOR_ID, SENSOR_DRVNAME_SIV120B_YUV, SIV120B_YUV_SensorInit}, +#endif +#if defined(SIV121D_YUV) + {SIV121D_SENSOR_ID, SENSOR_DRVNAME_SIV121D_YUV, SIV121D_YUV_SensorInit}, +#endif +/*PAS (PixArt Image)*/ +#if defined(PAS6180_SERIAL_YUV) + {PAS6180_SENSOR_ID, SENSOR_DRVNAME_PAS6180_SERIAL_YUV, PAS6180_SERIAL_YUV_SensorInit}, +#endif +/*Panasoic*/ +#if defined(MN34152_MIPI_RAW) + {MN34152_SENSOR_ID, SENSOR_DRVNAME_MN34152_MIPI_RAW, MN34152_MIPI_RAW_SensorInit}, +#endif +/*Toshiba*/ +#if defined(T4K28_YUV) + {T4K28_SENSOR_ID, SENSOR_DRVNAME_T4K28_YUV, T4K28_YUV_SensorInit}, +#endif +#if defined(T4KA7_MIPI_RAW) + {T4KA7_SENSOR_ID, SENSOR_DRVNAME_T4KA7_MIPI_RAW, T4KA7_MIPI_RAW_SensorInit}, +#endif +/*Others*/ +#if defined(ISX012_MIPI_YUV) + {ISX012MIPI_SENSOR_ID, SENSOR_DRVNAME_ISX012_MIPI_YUV, ISX012_MIPI_YUV_SensorInit}, +#endif +#if defined(T8EV5_YUV) + {T8EV5_SENSOR_ID, SENSOR_DRVNAME_T8EV5_YUV, T8EV5_YUV_SensorInit}, +#endif + +/* ADD sensor driver before this line */ + {0,{0},NULL}, //end of list +}; +//e_add new sensor driver here + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..cfb5f34b4846786b523bf064fc39071de5deca1d --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/Makefile @@ -0,0 +1,2 @@ +obj-y += ov12830mipiraw_Sensor.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_CameraCustomized.h b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_CameraCustomized.h new file mode 100755 index 0000000000000000000000000000000000000000..224f236ccd870f108a44d38f3e9071a11cdcdcee --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_CameraCustomized.h @@ -0,0 +1,65 @@ +/*******************************************************************************************/ + + +/*******************************************************************************************/ + + +#ifndef __CAMERA_CUSTOMIZED_H +#define __CAMERA_CUSTOMIZED_H + +// the angle between handset and sensor placement in clockwise, should be one of 0, 90, 270 +#define MAIN_SENSOR_ORIENTATION_ANGLE 90 +#define SUB_SENSOR_ORIENTATION_ANGLE 0 // do not care if the sub sensor does not exist + + +// First, we think you hold the cell phone vertical. +// Second, we suppose the direction of upward is 0 +// Third, it is 90, 180, 270 in clockwise +// here we define the main sensor and sub sensor angles to deal with the jpeg orientation +#define MAIN_SENSOR_TO_PHONE_ANGLE 90 +#define SUB_SENSOR_TO_PHONE_ANGLE 0 + + +#define CAM_SIZE_QVGA_WIDTH 320 +#define CAM_SIZE_QVGA_HEIGHT 240 +#define CAM_SIZE_VGA_WIDTH 640 +#define CAM_SIZE_VGA_HEIGHT 480 +#define CAM_SIZE_05M_WIDTH 800 +#define CAM_SIZE_05M_HEIGHT 600 +#define CAM_SIZE_1M_WIDTH 1280 +#define CAM_SIZE_1M_HEIGHT 960 +#define CAM_SIZE_2M_WIDTH 1600 +#define CAM_SIZE_2M_HEIGHT 1200 +#define CAM_SIZE_3M_WIDTH 2048 +#define CAM_SIZE_3M_HEIGHT 1536 +#define CAM_SIZE_5M_WIDTH 2592 +#define CAM_SIZE_5M_HEIGHT 1944 + +// for main sensor +#define MAIN_NUM_OF_PREVIEW_RESOLUTION 3 +#define MAIN_NUM_OF_VIDEO_RESOLUTION 4 +#define MAIN_NUM_OF_STILL_RESOLUTION 7 +#define MAIN_VIDEO_RESOLUTION_PROFILE {{176,144},{320,240},{640,480},{720,480}} +#define MAIN_PREVIEW_RESOLUTION_PROFILE {{232,174},{320,240},{240,320}} +#define MAIN_STILL_RESOLUTION_PROFILE {{CAM_SIZE_QVGA_WIDTH,CAM_SIZE_QVGA_HEIGHT}, \ + {CAM_SIZE_VGA_WIDTH,CAM_SIZE_VGA_HEIGHT}, \ + {CAM_SIZE_05M_WIDTH,CAM_SIZE_05M_HEIGHT}, \ + {CAM_SIZE_1M_WIDTH,CAM_SIZE_1M_HEIGHT}, \ + {CAM_SIZE_2M_WIDTH,CAM_SIZE_2M_HEIGHT}, \ + {CAM_SIZE_3M_WIDTH,CAM_SIZE_3M_HEIGHT}, \ + {CAM_SIZE_5M_WIDTH,CAM_SIZE_5M_HEIGHT}} + +// if sub sensor does not exist, set all the parameters as 0 +#define SUB_NUM_OF_PREVIEW_RESOLUTION 0 +#define SUB_NUM_OF_VIDEO_RESOLUTION 0 +#define SUB_NUM_OF_STILL_RESOLUTION 0 +#define SUB_VIDEO_RESOLUTION_PROFILE {{0,0}} +#define SUB_PREVIEW_RESOLUTION_PROFILE {{0,0}} +#define SUB_STILL_RESOLUTION_PROFILE {{0,0}} + +//#define NUM_OF_PREVIEW_RESOLUTION max(MAIN_NUM_OF_PREVIEW_RESOLUTION,SUB_NUM_OF_PREVIEW_RESOLUTION) +//#define NUM_OF_VIDEO_RESOLUTION max(MAIN_NUM_OF_VIDEO_RESOLUTION,SUB_NUM_OF_VIDEO_RESOLUTION) +//#define NUM_OF_STILL_RESOLUTION max(MAIN_NUM_OF_STILL_RESOLUTION,SUB_NUM_OF_STILL_RESOLUTION) + +#define NUM_OF_VIDEO_STREAM_BUFF 8 // Maximun is 8 +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Camera_Sensor_para.h b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Camera_Sensor_para.h new file mode 100755 index 0000000000000000000000000000000000000000..5bbdb9c98df9d443c6c0a31cb166c41cd4dd7f88 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Camera_Sensor_para.h @@ -0,0 +1,60 @@ +/*******************************************************************************************/ + + +/*******************************************************************************************/ + +/* SENSOR FULL SIZE */ +#ifndef __CAMERA_SENSOR_PARA_H +#define __CAMERA_SENSOR_PARA_H + +#define CAMERA_SENSOR_REG_DEFAULT_VALUE \ + /* ARRAY: SENSOR.reg[11] */\ + {\ + /* STRUCT: SENSOR.reg[0] */\ + {\ + /* SENSOR.reg[0].addr */ 0x00000304, /* SENSOR.reg[0].para */ 0x00000000\ + },\ + /* STRUCT: SENSOR.reg[1] */\ + {\ + /* SENSOR.reg[1].addr */ 0x00000305, /* SENSOR.reg[1].para */ 0x0000000D\ + },\ + /* STRUCT: SENSOR.reg[2] */\ + {\ + /* SENSOR.reg[2].addr */ 0x00000306, /* SENSOR.reg[2].para */ 0x00000000\ + },\ + /* STRUCT: SENSOR.reg[3] */\ + {\ + /* SENSOR.reg[3].addr */ 0x00000307, /* SENSOR.reg[3].para */ 0x000000C0\ + },\ + /* STRUCT: SENSOR.reg[4] */\ + {\ + /* SENSOR.reg[4].addr */ 0x00000300, /* SENSOR.reg[4].para */ 0x00000000\ + },\ + /* STRUCT: SENSOR.reg[5] */\ + {\ + /* SENSOR.reg[5].addr */ 0x00000301, /* SENSOR.reg[5].para */ 0x00000004\ + },\ + /* STRUCT: SENSOR.reg[6] */\ + {\ + /* SENSOR.reg[6].addr */ 0x0000030A, /* SENSOR.reg[6].para */ 0x00000000\ + },\ + /* STRUCT: SENSOR.reg[7] */\ + {\ + /* SENSOR.reg[7].addr */ 0x0000030B, /* SENSOR.reg[7].para */ 0x00000002\ + },\ + /* STRUCT: SENSOR.reg[8] */\ + {\ + /* SENSOR.reg[8].addr */ 0x00000308, /* SENSOR.reg[8].para */ 0x00000000\ + },\ + /* STRUCT: SENSOR.reg[9] */\ + {\ + /* SENSOR.reg[9].addr */ 0x00000309, /* SENSOR.reg[9].para */ 0x00000008\ + },\ + /* STRUCT: SENSOR.reg[10] */\ + {\ + /* SENSOR.reg[10].addr */ 0xFFFFFFFF, /* SENSOR.reg[10].para */ 0x00000001\ + }\ +} + +#define CAMERA_SENSOR_CCT_DEFAULT_VALUE {{ 0xFFFFFFFF, 0x08 } ,{ 0x0205, 0x20 } ,{ 0x020e, 0x01 } ,{ 0x0210, 0x01 } ,{ 0x0212, 0x01 }} +#endif /* __CAMERA_SENSOR_PARA_H */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Sensor.c new file mode 100755 index 0000000000000000000000000000000000000000..ccb20f60195af7063a01e9f1f1ef5884e9a3e02e --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Sensor.c @@ -0,0 +1,1795 @@ +/***************************************************************************** + * + * Filename: + * --------- + * OV12830mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include "kd_camera_typedef.h" + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "ov12830mipiraw_Sensor.h" + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "OV12830_camera_sensor" +#define LOG_1 LOG_INF("OV12830,MIPI 4LANE\n") +#define LOG_2 LOG_INF("preview 2096*1552@30fps,640Mbps/lane; video 4192*3104@30fps,1.2Gbps/lane; capture 13M@30fps,1.2Gbps/lane\n") +/**************************** Modify end *******************************************/ + +#if 0 +#define LOG_INF(format, args...) printk(PFX "[%s] " format, __FUNCTION__, ##args) +#else +#define LOG_INF(format, args...) +#endif + +extern u32 pinSetIdx; +static DEFINE_SPINLOCK(imgsensor_drv_lock); +#define MIPI_SETTLEDELAY_AUTO 0 +#define MIPI_SETTLEDELAY_MANNUAL 1 + +int ov12830_chip_ver = OV12830_R1A; + + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = OV12830_SENSOR_ID, //record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0xa261a12b,//0xf86cfdf4, //checksum value for Camera Auto Test + + .pre = { + .pclk = 168000000, //record different mode's pclk + .linelength = 1949, //record different mode's linelength + .framelength = 2816, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1500, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk = 324000000, + .linelength = 3044, + .framelength = 4432, + .startx = 0, + .starty = 0, + .grabwindow_width = 4000, //4192, + .grabwindow_height = 3000,//3104, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 240, + + }, + .cap1 = { //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 324000000, + .linelength = 3044, + .framelength = 4432, + .startx = 0, + .starty = 0, + .grabwindow_width = 4000, //4192, + .grabwindow_height = 3000,//3104, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 240, + }, + .normal_video = { + .pclk = 168000000, + .linelength = 1949, + .framelength = 2816, + .startx = 0, + .starty = 0, + .grabwindow_width = 2096, + .grabwindow_height = 1500, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 300, + }, + .hs_video = { + .pclk = 168000000, + .linelength = 2009, + .framelength = 2816, + .startx = 0, + .starty = 0, + .grabwindow_width = 640, + .grabwindow_height = 480, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 1200, + }, + .slim_video = { + .pclk = 168000000, + .linelength = 2009,//2400, + .framelength = 2816,//3328, + .startx = 0, + .starty = 0, + .grabwindow_width = 1280, + .grabwindow_height = 720, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 300, + + }, + .margin = 4, //sensor framelength & shutter margin + .min_shutter = 1, //min shutter + .max_frame_length = 0x7fff,//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num + + .cap_delay_frame = 2, //enter capture delay frame num + .pre_delay_frame = 2, //enter preview delay frame num + .video_delay_frame = 2, //enter video delay frame num + .hs_video_delay_frame = 2, //enter high speed video delay frame num + .slim_video_delay_frame = 2,//enter slim video delay frame num + + .isp_driving_current = ISP_DRIVING_8MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_2_LANE,//mipi lane num + .i2c_addr_table = {0x6c,0x20,0xff},//record sensor support all write id addr, only supprt 4must end with 0xff +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_V_MIRROR, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter + .gain = 0x100, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x6c,//record current sensor's i2c write id +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{{ 4000, 2996, 0, 0, 4000, 2996, 2104, 1560, 0, 0, 2104, 1560, 0, 0, 2096, 1500}, // Preview + { 4000, 2996, 0, 0, 4000, 2996, 4000, 2996, 0, 0, 4000, 2996, 0, 0, 4000, 2996}, // capture + { 4000, 2996, 0, 0, 4000, 2996, 2104, 1560, 0, 0, 2104, 1560, 0, 0, 2096, 1500}, // video + { 4000, 2996, 0, 0, 4000, 2996, 2104, 1560, 0, 0, 1056, 594, 0, 0, 640, 480}, //hight speed video + { 4000, 2996, 0, 0, 4000, 2996, 1296, 730, 0, 0, 1296, 730, 0, 0, 1280, 720}, + +}; + + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; +} + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + /* you can set dummy by imgsensor.dummy_line and imgsensor.dummy_pixel, or you can set dummy by imgsensor.frame_length and imgsensor.line_length */ + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)&0xFF); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x380c, (imgsensor.line_length >> 8)&0xFF); + write_cmos_sensor(0x380d, imgsensor.line_length & 0xFF); + +} /* set_dummy */ + +static kal_uint32 return_sensor_id(void) +{ + return ((read_cmos_sensor(0x300A) << 8) | read_cmos_sensor(0x300B)); +} +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + //kal_int16 dummy_line; + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min_framelength_en = %d \n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + kal_uint16 realtime_fps = 0; + //kal_uint32 frame_length = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + LOG_INF("Enter! shutter =%d \n", shutter); + + //write_shutter(shutter); + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + // Framelength should be an even number + shutter = (shutter >> 1) << 1; + imgsensor.frame_length = (imgsensor.frame_length >> 1) << 1; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)&0xff); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + } else { + // Extend frame length + //write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + //write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)&0xff); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + + // Update Shutter + // write_cmos_sensor(0x3502, (shutter << 4) & 0xFF); + // write_cmos_sensor(0x3501, (shutter >> 4) & 0xFF); + // write_cmos_sensor(0x3500, (shutter >> 12) & 0x0F); + write_cmos_sensor(0x3500, (shutter>>12) & 0x0F); + write_cmos_sensor(0x3501, (shutter>>4) & 0xFF); + write_cmos_sensor(0x3502, (shutter<<4) & 0xF0); + + + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} /* set_shutter */ + + + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + /*kal_uint16 iReg = 0x0000; + kal_uint16 iGain=gain; + ov12830_chip_ver=OV12830_R2A; + if (ov12830_chip_ver == OV12830_R1A) + { + iReg = gain*32/BASEGAIN; + if(iReg < 0x20) + { + iReg = 0x20; + } + if(iReg > 0xfc) + { + iReg = 0xfc; + } + //SENSORDB("[OV12830Gain2Reg]: isp gain:%d,sensor gain:0x%x\n",iGain,iReg); + } + else if(ov12830_chip_ver == OV12830_R2A) + { + iReg = gain*16/BASEGAIN; + if(iReg < 0x10) + { + iReg = 0x10; + } + if(iReg > 0xf8) + { + iReg = 0xf8; + } + }//*/ + + kal_uint16 iReg = 0x0000; + kal_uint16 iGain=gain; + + if(iGain < BASEGAIN) + { + iReg =0; + } + else if (iGain < 2 * BASEGAIN) + { + iReg = 16 * iGain / BASEGAIN - 16; + } + else if (iGain < 4 * BASEGAIN) + { + iReg |= 0x10; + iReg |= (8 *iGain / BASEGAIN - 16); + } + else if (iGain < 8 * BASEGAIN) + { + iReg |= 0x30; + iReg |= (4 * iGain / BASEGAIN - 16); + } + else if (iGain < 16 * BASEGAIN) + { + iReg |= 0x70; + iReg |= (2 * iGain /BASEGAIN - 16); + } + else if(iGain < 32 * BASEGAIN) + { + iReg |= 0xF0; + iReg |= (iGain /BASEGAIN - 16); + } + else if(iGain <= 62 * BASEGAIN) + { + iReg |= 0x1F0; + iReg |= (iGain /BASEGAIN/2 - 16); + } + + + + + return iReg;//ov12830. sensorGlobalGain +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor(0x350a, reg_gain >> 8); + write_cmos_sensor(0x350b, reg_gain & 0xFF); + + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length first + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + + write_cmos_sensor(0x3502, (le << 4) & 0xFF); + write_cmos_sensor(0x3501, (le >> 4) & 0xFF); + write_cmos_sensor(0x3500, (le >> 12) & 0x0F); + + write_cmos_sensor(0x3508, (se << 4) & 0xFF); + write_cmos_sensor(0x3507, (se >> 4) & 0xFF); + write_cmos_sensor(0x3506, (se >> 12) & 0x0F); + + set_gain(gain); + } + +} + + + +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xFB) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xFB) | 0x00)); + break; + case IMAGE_H_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xFB) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xFF) | 0x04)); + break; + case IMAGE_V_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xFF) | 0x04)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xFB) | 0x00)); + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xFF) | 0x04)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xFF) | 0x04)); + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} + +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + +static void sensor_init(void) +{ + LOG_INF("E\n"); + write_cmos_sensor(0x0103,0x01); + write_cmos_sensor(0x3001,0x06); + write_cmos_sensor(0x3002,0x80); + write_cmos_sensor(0x3011,0x21); + write_cmos_sensor(0x3012,0x08); + write_cmos_sensor(0x3014,0x16); + write_cmos_sensor(0x3015,0x0b); + write_cmos_sensor(0x3022,0x03); + write_cmos_sensor(0x3090,0x02); + write_cmos_sensor(0x3091,0x1b); + write_cmos_sensor(0x3092,0x00); + write_cmos_sensor(0x3093,0x00); + write_cmos_sensor(0x3098,0x03); + write_cmos_sensor(0x3099,0x11); + write_cmos_sensor(0x309c,0x01); + write_cmos_sensor(0x30b3,0x6e); + write_cmos_sensor(0x30b4,0x04); + write_cmos_sensor(0x30b5,0x04); + write_cmos_sensor(0x3093,0x02); + write_cmos_sensor(0x309b,0x02); + write_cmos_sensor(0x3106,0x01); + write_cmos_sensor(0x3304,0x28); + write_cmos_sensor(0x3305,0x41); + write_cmos_sensor(0x3306,0x30); + write_cmos_sensor(0x3308,0x00); + write_cmos_sensor(0x3309,0xc8); + write_cmos_sensor(0x330a,0x01); + write_cmos_sensor(0x330b,0x90); + write_cmos_sensor(0x330c,0x02); + write_cmos_sensor(0x330d,0x58); + write_cmos_sensor(0x330e,0x03); + write_cmos_sensor(0x330f,0x20); + write_cmos_sensor(0x3300,0x00); + write_cmos_sensor(0x3500,0x00); + write_cmos_sensor(0x3501,0xbd); + write_cmos_sensor(0x3502,0x40); + write_cmos_sensor(0x3503,0x07); + write_cmos_sensor(0x3508,0x00); + write_cmos_sensor(0x3509,0x08); + write_cmos_sensor(0x350a,0x00); + write_cmos_sensor(0x350b,0x00); + write_cmos_sensor(0x3602,0x28); + write_cmos_sensor(0x3612,0x80); + write_cmos_sensor(0x3622,0x0f); + write_cmos_sensor(0x3631,0xb3); + write_cmos_sensor(0x3634,0x04); + write_cmos_sensor(0x3660,0x80); + write_cmos_sensor(0x3662,0x10); + write_cmos_sensor(0x3663,0xf0); + write_cmos_sensor(0x3667,0x00); + write_cmos_sensor(0x366f,0x20); + write_cmos_sensor(0x3680,0xb5); + write_cmos_sensor(0x3682,0x00); + write_cmos_sensor(0x3701,0x12); + write_cmos_sensor(0x3708,0xe3); + write_cmos_sensor(0x3709,0xc3); + write_cmos_sensor(0x370b,0xa8); + write_cmos_sensor(0x370d,0x11); + write_cmos_sensor(0x370e,0x00); + write_cmos_sensor(0x371c,0x01); + write_cmos_sensor(0x371f,0x1b); + write_cmos_sensor(0x3726,0x00); + write_cmos_sensor(0x372a,0x09); + write_cmos_sensor(0x3739,0x80); + write_cmos_sensor(0x373c,0x40); + write_cmos_sensor(0x376b,0x44); + write_cmos_sensor(0x377b,0x44); + write_cmos_sensor(0x3780,0x22); + write_cmos_sensor(0x3781,0xc8); + write_cmos_sensor(0x3783,0x31); + write_cmos_sensor(0x3786,0x16); + write_cmos_sensor(0x3787,0x02); + write_cmos_sensor(0x3796,0x84); + write_cmos_sensor(0x379c,0x0c); + write_cmos_sensor(0x37c5,0x00); + write_cmos_sensor(0x37c6,0x00); + write_cmos_sensor(0x37c7,0x00); + write_cmos_sensor(0x37c9,0x00); + write_cmos_sensor(0x37ca,0x00); + write_cmos_sensor(0x37cb,0x00); + write_cmos_sensor(0x37cc,0x00); + write_cmos_sensor(0x37cd,0x00); + write_cmos_sensor(0x37ce,0x10); + write_cmos_sensor(0x37cf,0x00); + write_cmos_sensor(0x37d0,0x00); + write_cmos_sensor(0x37d1,0x00); + write_cmos_sensor(0x37d2,0x00); + write_cmos_sensor(0x37de,0x00); + write_cmos_sensor(0x37df,0x00); + write_cmos_sensor(0x3800,0x00); + write_cmos_sensor(0x3801,0x00); + write_cmos_sensor(0x3802,0x00); + write_cmos_sensor(0x3803,0x00); + write_cmos_sensor(0x3804,0x10); + write_cmos_sensor(0x3805,0x9f); + write_cmos_sensor(0x3806,0x0b); + write_cmos_sensor(0x3807,0xc7); + write_cmos_sensor(0x3808,0x10); + write_cmos_sensor(0x3809,0x80); + write_cmos_sensor(0x380a,0x0b); + write_cmos_sensor(0x380b,0xb8); + write_cmos_sensor(0x380c,0x11); + write_cmos_sensor(0x380d,0x50); + write_cmos_sensor(0x380e,0x0b); + write_cmos_sensor(0x380f,0xe4); + write_cmos_sensor(0x3810,0x00); + write_cmos_sensor(0x3811,0x10); + write_cmos_sensor(0x3812,0x00); + write_cmos_sensor(0x3813,0x08); + write_cmos_sensor(0x3814,0x11); + write_cmos_sensor(0x3815,0x11); + write_cmos_sensor(0x3820,0x10); + write_cmos_sensor(0x3821,0x0e); + write_cmos_sensor(0x3823,0x00); + write_cmos_sensor(0x3824,0x00); + write_cmos_sensor(0x3825,0x00); + write_cmos_sensor(0x3826,0x00); + write_cmos_sensor(0x3827,0x00); + write_cmos_sensor(0x3829,0x0b); + write_cmos_sensor(0x382b,0x6a); + write_cmos_sensor(0x4000,0x18); + write_cmos_sensor(0x4001,0x06); + write_cmos_sensor(0x4002,0x45); + write_cmos_sensor(0x4004,0x08); + write_cmos_sensor(0x4005,0x19); + write_cmos_sensor(0x4007,0x90); + write_cmos_sensor(0x4008,0x20); + write_cmos_sensor(0x4100,0x2d); + write_cmos_sensor(0x4101,0x22); + write_cmos_sensor(0x4102,0x04); + write_cmos_sensor(0x4104,0x5c); + write_cmos_sensor(0x4109,0xa3); + write_cmos_sensor(0x410a,0x03); + write_cmos_sensor(0x4300,0xff); + write_cmos_sensor(0x4303,0x00); + write_cmos_sensor(0x4304,0x08); + write_cmos_sensor(0x4307,0x30); + write_cmos_sensor(0x4311,0x04); + write_cmos_sensor(0x4511,0x05); + write_cmos_sensor(0x4816,0x52); + write_cmos_sensor(0x481f,0x30); + write_cmos_sensor(0x4826,0x2c); + write_cmos_sensor(0x4a00,0xaa); + write_cmos_sensor(0x4a03,0x01); + write_cmos_sensor(0x4a05,0x08); + write_cmos_sensor(0x4d00,0x05); + write_cmos_sensor(0x4d01,0x19); + write_cmos_sensor(0x4d02,0xfd); + write_cmos_sensor(0x4d03,0xd1); + write_cmos_sensor(0x4d04,0xff); + write_cmos_sensor(0x4d05,0xff); + write_cmos_sensor(0x4d07,0x04); + write_cmos_sensor(0x4837,0x09); + write_cmos_sensor(0x5000,0x06); + write_cmos_sensor(0x5001,0x01); + write_cmos_sensor(0x5002,0x00); + write_cmos_sensor(0x5003,0x21); + write_cmos_sensor(0x5043,0x48); + write_cmos_sensor(0x5013,0x80); + write_cmos_sensor(0x501f,0x00); + write_cmos_sensor(0x5e00,0x00); + write_cmos_sensor(0x5a01,0x00); + write_cmos_sensor(0x5a02,0x00); + write_cmos_sensor(0x5a03,0x00); + write_cmos_sensor(0x5a04,0x10); + write_cmos_sensor(0x5a05,0xa0); + write_cmos_sensor(0x5a06,0x0c); + write_cmos_sensor(0x5a07,0x78); + write_cmos_sensor(0x5a08,0x00); + write_cmos_sensor(0x5e00,0x00); + write_cmos_sensor(0x5e01,0x41); + write_cmos_sensor(0x5e11,0x30); + write_cmos_sensor(0x3501,0xa0); + write_cmos_sensor(0x0100,0x01); + +} + + +static void preview_setting(void) +{ + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x3501,0x70); + write_cmos_sensor(0x30b4,0x03); + write_cmos_sensor(0x30b3,0x54); + write_cmos_sensor(0x3106,0x21); + write_cmos_sensor(0x3090,0x01); + write_cmos_sensor(0x3091,0x38); + write_cmos_sensor(0x3708,0xe6); + write_cmos_sensor(0x3709,0xc7); + write_cmos_sensor(0x3801,0x00); + write_cmos_sensor(0x3802,0x00); + write_cmos_sensor(0x3803,0x00); + write_cmos_sensor(0x3805,0x9f); + write_cmos_sensor(0x3806,0x0b); + write_cmos_sensor(0x3807,0xc7); + write_cmos_sensor(0x3808,0x08); + write_cmos_sensor(0x3809,0x40); + write_cmos_sensor(0x380a,0x05); + write_cmos_sensor(0x380b,0xdc); + write_cmos_sensor(0x380c,0x0b); + write_cmos_sensor(0x380d,0x00); + write_cmos_sensor(0x380e,0x07); + write_cmos_sensor(0x380f,0x9D); + write_cmos_sensor(0x3811,0x08); + write_cmos_sensor(0x3813,0x02); + write_cmos_sensor(0x3814,0x31); + write_cmos_sensor(0x3815,0x31); + write_cmos_sensor(0x3820,0x14); + write_cmos_sensor(0x3821,0x0f); + write_cmos_sensor(0x4004,0x08); + write_cmos_sensor(0x4837,0x0b); + write_cmos_sensor(0x5002,0x00); + write_cmos_sensor(0x0100,0x01); + +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + write_cmos_sensor(0x0103,0x01); + write_cmos_sensor(0x3001,0x06); + write_cmos_sensor(0x3002,0x80); + write_cmos_sensor(0x3011,0x21); + write_cmos_sensor(0x3012,0x08); + write_cmos_sensor(0x3014,0x16); + write_cmos_sensor(0x3015,0x0b); + write_cmos_sensor(0x3022,0x03); + write_cmos_sensor(0x3090,0x02); + write_cmos_sensor(0x3091,0x1b); + write_cmos_sensor(0x3092,0x00); + write_cmos_sensor(0x3093,0x00); + write_cmos_sensor(0x3098,0x03); + write_cmos_sensor(0x3099,0x11); + write_cmos_sensor(0x309c,0x01); + write_cmos_sensor(0x30b3,0x6e); + write_cmos_sensor(0x30b4,0x04); + write_cmos_sensor(0x30b5,0x04); + write_cmos_sensor(0x3093,0x02); + write_cmos_sensor(0x309b,0x02); + write_cmos_sensor(0x3106,0x01); + write_cmos_sensor(0x3304,0x28); + write_cmos_sensor(0x3305,0x41); + write_cmos_sensor(0x3306,0x30); + write_cmos_sensor(0x3308,0x00); + write_cmos_sensor(0x3309,0xc8); + write_cmos_sensor(0x330a,0x01); + write_cmos_sensor(0x330b,0x90); + write_cmos_sensor(0x330c,0x02); + write_cmos_sensor(0x330d,0x58); + write_cmos_sensor(0x330e,0x03); + write_cmos_sensor(0x330f,0x20); + write_cmos_sensor(0x3300,0x00); + write_cmos_sensor(0x3500,0x00); + write_cmos_sensor(0x3501,0xbd); + write_cmos_sensor(0x3502,0x40); + write_cmos_sensor(0x3503,0x07); + write_cmos_sensor(0x3508,0x00); + write_cmos_sensor(0x3509,0x08); + write_cmos_sensor(0x350a,0x00); + write_cmos_sensor(0x350b,0x00); + write_cmos_sensor(0x3602,0x28); + write_cmos_sensor(0x3612,0x80); + write_cmos_sensor(0x3622,0x0f); + write_cmos_sensor(0x3631,0xb3); + write_cmos_sensor(0x3634,0x04); + write_cmos_sensor(0x3660,0x80); + write_cmos_sensor(0x3662,0x10); + write_cmos_sensor(0x3663,0xf0); + write_cmos_sensor(0x3667,0x00); + write_cmos_sensor(0x366f,0x20); + write_cmos_sensor(0x3680,0xb5); + write_cmos_sensor(0x3682,0x00); + write_cmos_sensor(0x3701,0x12); + write_cmos_sensor(0x3708,0xe3); + write_cmos_sensor(0x3709,0xc3); + write_cmos_sensor(0x370b,0xa8); + write_cmos_sensor(0x370d,0x11); + write_cmos_sensor(0x370e,0x00); + write_cmos_sensor(0x371c,0x01); + write_cmos_sensor(0x371f,0x1b); + write_cmos_sensor(0x3726,0x00); + write_cmos_sensor(0x372a,0x09); + write_cmos_sensor(0x3739,0x80); + write_cmos_sensor(0x373c,0x40); + write_cmos_sensor(0x376b,0x44); + write_cmos_sensor(0x377b,0x44); + write_cmos_sensor(0x3780,0x22); + write_cmos_sensor(0x3781,0xc8); + write_cmos_sensor(0x3783,0x31); + write_cmos_sensor(0x3786,0x16); + write_cmos_sensor(0x3787,0x02); + write_cmos_sensor(0x3796,0x84); + write_cmos_sensor(0x379c,0x0c); + write_cmos_sensor(0x37c5,0x00); + write_cmos_sensor(0x37c6,0x00); + write_cmos_sensor(0x37c7,0x00); + write_cmos_sensor(0x37c9,0x00); + write_cmos_sensor(0x37ca,0x00); + write_cmos_sensor(0x37cb,0x00); + write_cmos_sensor(0x37cc,0x00); + write_cmos_sensor(0x37cd,0x00); + write_cmos_sensor(0x37ce,0x10); + write_cmos_sensor(0x37cf,0x00); + write_cmos_sensor(0x37d0,0x00); + write_cmos_sensor(0x37d1,0x00); + write_cmos_sensor(0x37d2,0x00); + write_cmos_sensor(0x37de,0x00); + write_cmos_sensor(0x37df,0x00); + write_cmos_sensor(0x3800,0x00); + write_cmos_sensor(0x3801,0x00); + write_cmos_sensor(0x3802,0x00); + write_cmos_sensor(0x3803,0x00); + write_cmos_sensor(0x3804,0x10); + write_cmos_sensor(0x3805,0x9f); + write_cmos_sensor(0x3806,0x0b); + write_cmos_sensor(0x3807,0xc7); + write_cmos_sensor(0x3808,0x10); + write_cmos_sensor(0x3809,0x80); + write_cmos_sensor(0x380a,0x0b); + write_cmos_sensor(0x380b,0xb8); + write_cmos_sensor(0x380c,0x11); + write_cmos_sensor(0x380d,0x50); + write_cmos_sensor(0x380e,0x0b); + write_cmos_sensor(0x380f,0xe4); + write_cmos_sensor(0x3810,0x00); + write_cmos_sensor(0x3811,0x10); + write_cmos_sensor(0x3812,0x00); + write_cmos_sensor(0x3813,0x08); + write_cmos_sensor(0x3814,0x11); + write_cmos_sensor(0x3815,0x11); + write_cmos_sensor(0x3820,0x10); + write_cmos_sensor(0x3821,0x0e); + write_cmos_sensor(0x3823,0x00); + write_cmos_sensor(0x3824,0x00); + write_cmos_sensor(0x3825,0x00); + write_cmos_sensor(0x3826,0x00); + write_cmos_sensor(0x3827,0x00); + write_cmos_sensor(0x3829,0x0b); + write_cmos_sensor(0x382b,0x6a); + write_cmos_sensor(0x4000,0x18); + write_cmos_sensor(0x4001,0x06); + write_cmos_sensor(0x4002,0x45); + write_cmos_sensor(0x4004,0x08); + write_cmos_sensor(0x4005,0x19); + write_cmos_sensor(0x4007,0x90); + write_cmos_sensor(0x4008,0x20); + write_cmos_sensor(0x4100,0x2d); + write_cmos_sensor(0x4101,0x22); + write_cmos_sensor(0x4102,0x04); + write_cmos_sensor(0x4104,0x5c); + write_cmos_sensor(0x4109,0xa3); + write_cmos_sensor(0x410a,0x03); + write_cmos_sensor(0x4300,0xff); + write_cmos_sensor(0x4303,0x00); + write_cmos_sensor(0x4304,0x08); + write_cmos_sensor(0x4307,0x30); + write_cmos_sensor(0x4311,0x04); + write_cmos_sensor(0x4511,0x05); + write_cmos_sensor(0x4816,0x52); + write_cmos_sensor(0x481f,0x30); + write_cmos_sensor(0x4826,0x2c); + write_cmos_sensor(0x4a00,0xaa); + write_cmos_sensor(0x4a03,0x01); + write_cmos_sensor(0x4a05,0x08); + write_cmos_sensor(0x4d00,0x05); + write_cmos_sensor(0x4d01,0x19); + write_cmos_sensor(0x4d02,0xfd); + write_cmos_sensor(0x4d03,0xd1); + write_cmos_sensor(0x4d04,0xff); + write_cmos_sensor(0x4d05,0xff); + write_cmos_sensor(0x4d07,0x04); + write_cmos_sensor(0x4837,0x0c); + write_cmos_sensor(0x5000,0x06); + write_cmos_sensor(0x5001,0x01); + write_cmos_sensor(0x5002,0x00); + write_cmos_sensor(0x5003,0x21); + write_cmos_sensor(0x5043,0x48); + write_cmos_sensor(0x5013,0x80); + write_cmos_sensor(0x501f,0x00); + write_cmos_sensor(0x5e00,0x00); + write_cmos_sensor(0x5a01,0x00); + write_cmos_sensor(0x5a02,0x00); + write_cmos_sensor(0x5a03,0x00); + write_cmos_sensor(0x5a04,0x10); + write_cmos_sensor(0x5a05,0xa0); + write_cmos_sensor(0x5a06,0x0c); + write_cmos_sensor(0x5a07,0x78); + write_cmos_sensor(0x5a08,0x00); + write_cmos_sensor(0x5e00,0x00); + write_cmos_sensor(0x5e01,0x41); + write_cmos_sensor(0x5e11,0x30); + write_cmos_sensor(0x3501,0xa0); + write_cmos_sensor(0x0100,0x01); + +} + +static void normal_video_setting(kal_uint16 currefps) +{ + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x3501,0x70); + write_cmos_sensor(0x30b4,0x03); + write_cmos_sensor(0x30b3,0x54); + write_cmos_sensor(0x3106,0x21); + write_cmos_sensor(0x3090,0x01); + write_cmos_sensor(0x3091,0x38); + write_cmos_sensor(0x3708,0xe6); + write_cmos_sensor(0x3709,0xc7); + write_cmos_sensor(0x3801,0x00); + write_cmos_sensor(0x3802,0x00); + write_cmos_sensor(0x3803,0x00); + write_cmos_sensor(0x3805,0x9f); + write_cmos_sensor(0x3806,0x0b); + write_cmos_sensor(0x3807,0xc7); + write_cmos_sensor(0x3808,0x08); + write_cmos_sensor(0x3809,0x40); + write_cmos_sensor(0x380a,0x05); + write_cmos_sensor(0x380b,0xdc); + write_cmos_sensor(0x380c,0x0b); + write_cmos_sensor(0x380d,0x00); + write_cmos_sensor(0x380e,0x07); + write_cmos_sensor(0x380f,0x9D); + write_cmos_sensor(0x3811,0x08); + write_cmos_sensor(0x3813,0x02); + write_cmos_sensor(0x3814,0x31); + write_cmos_sensor(0x3815,0x31); + write_cmos_sensor(0x3820,0x14); + write_cmos_sensor(0x3821,0x0f); + write_cmos_sensor(0x4004,0x08); + write_cmos_sensor(0x4837,0x0b); + write_cmos_sensor(0x5002,0x00); + write_cmos_sensor(0x0100,0x01); + +} +static void hs_video_setting(void) +{ + LOG_INF("E\n"); + + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x3501,0x70); + write_cmos_sensor(0x30b4,0x03); + write_cmos_sensor(0x30b3,0x54); + write_cmos_sensor(0x3106,0x21); + write_cmos_sensor(0x3090,0x01); + write_cmos_sensor(0x3091,0x38); + write_cmos_sensor(0x3708,0xe6); + write_cmos_sensor(0x3709,0xc7); + write_cmos_sensor(0x3801,0x00); + write_cmos_sensor(0x3802,0x00); + write_cmos_sensor(0x3803,0x00); + write_cmos_sensor(0x3805,0x9f); + write_cmos_sensor(0x3806,0x0b); + write_cmos_sensor(0x3807,0xc7); + write_cmos_sensor(0x3808,0x08); + write_cmos_sensor(0x3809,0x40); + write_cmos_sensor(0x380a,0x05); + write_cmos_sensor(0x380b,0xdc); + write_cmos_sensor(0x380c,0x0b); + write_cmos_sensor(0x380d,0x00); + write_cmos_sensor(0x380e,0x07); + write_cmos_sensor(0x380f,0x9D); + write_cmos_sensor(0x3811,0x08); + write_cmos_sensor(0x3813,0x02); + write_cmos_sensor(0x3814,0x31); + write_cmos_sensor(0x3815,0x31); + write_cmos_sensor(0x3820,0x14); + write_cmos_sensor(0x3821,0x0f); + write_cmos_sensor(0x4004,0x08); + write_cmos_sensor(0x4837,0x0b); + write_cmos_sensor(0x5002,0x00); + write_cmos_sensor(0x0100,0x01); + +} + +static void slim_video_setting(void) +{ + write_cmos_sensor(0x0100,0x00); + write_cmos_sensor(0x3501,0x70); + write_cmos_sensor(0x30b4,0x03); + write_cmos_sensor(0x30b3,0x54); + write_cmos_sensor(0x3106,0x21); + write_cmos_sensor(0x3090,0x01); + write_cmos_sensor(0x3091,0x38); + write_cmos_sensor(0x3708,0xe6); + write_cmos_sensor(0x3709,0xc7); + write_cmos_sensor(0x3801,0x00); + write_cmos_sensor(0x3802,0x00); + write_cmos_sensor(0x3803,0x00); + write_cmos_sensor(0x3805,0x9f); + write_cmos_sensor(0x3806,0x0b); + write_cmos_sensor(0x3807,0xc7); + write_cmos_sensor(0x3808,0x08); + write_cmos_sensor(0x3809,0x40); + write_cmos_sensor(0x380a,0x05); + write_cmos_sensor(0x380b,0xdc); + write_cmos_sensor(0x380c,0x0b); + write_cmos_sensor(0x380d,0x00); + write_cmos_sensor(0x380e,0x07); + write_cmos_sensor(0x380f,0x9D); + write_cmos_sensor(0x3811,0x08); + write_cmos_sensor(0x3813,0x02); + write_cmos_sensor(0x3814,0x31); + write_cmos_sensor(0x3815,0x31); + write_cmos_sensor(0x3820,0x14); + write_cmos_sensor(0x3821,0x0f); + write_cmos_sensor(0x4004,0x08); + write_cmos_sensor(0x4837,0x0b); + write_cmos_sensor(0x5002,0x00); + write_cmos_sensor(0x0100,0x01); + +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x5E00, 0x80); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x5E00, 0x00); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id()+pinSetIdx; + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + LOG_2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id()+pinSetIdx; + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + if ((read_cmos_sensor(0x302a))==0xb1) + { + LOG_INF("----R1A---- \n"); + ov12830_chip_ver = OV12830_R1A; + }else if((read_cmos_sensor(0x302a))==0xb2) + { + LOG_INF("----R2A---- \n"); + ov12830_chip_ver = OV12830_R2A; + } + /* initail sequence write in */ + sensor_init(); + //for OTP + //otp_cali(imgsensor.i2c_write_id); + write_cmos_sensor(0x0100, 0x00); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + //for zsd multi capture setting + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + set_mirror_flip(imgsensor.mirror); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + //set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + + + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + //unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + //LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + LOG_INF("feature_Control imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", *feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", *feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 OV12830_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV12830_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Sensor.h new file mode 100755 index 0000000000000000000000000000000000000000..eaa9f6f4e06368600e7f165da8bbda3ba934f26f --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov12830_mipi_raw/ov12830mipiraw_Sensor.h @@ -0,0 +1,123 @@ +/***************************************************************************** + * + * Filename: + * --------- + * OV12830mipiraw_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _OV12830MIPIRAW_SENSOR_H +#define _OV12830MIPIRAW_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint32 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + +typedef enum{ + OV12830_R1A = 0, + OV12830_R2A, + OV12830_MAX, +}OV12830_CHIP_VER_ENUM; + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..ae33448a36552f26b506b4bae07a568914022754 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/Makefile @@ -0,0 +1,2 @@ +obj-y += ov13850mipiraw_Sensor.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850_otp.h b/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850_otp.h new file mode 100755 index 0000000000000000000000000000000000000000..79d8d7f0790d1f207cc02d90bfeb08f2e432950b --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850_otp.h @@ -0,0 +1,44 @@ +/*file discription : otp*/ +#define OTP_DRV_LSC_SIZE 186 + +struct otp_struct { +int flag;//bit[7]:info,bit[6]:wb,bit[5]:vcm,bit[4]:lenc +int module_integrator_id; +int lens_id; +int production_year; +int production_month; +int production_day; +int rg_ratio; +int bg_ratio; +//int light_rg; +//int light_bg; +//int typical_rg_ratio; +//int typical_bg_ratio; +unsigned char lenc[OTP_DRV_LSC_SIZE]; +int checksumLSC; +int checksumOTP; +int checksumTotal; +int VCM_start; +int VCM_end; +int VCM_dir; +}; + +#define RG_Ratio_Typical 0x125 +#define BG_Ratio_Typical 0x131 + +int read_otp(struct otp_struct *otp_ptr); +int apply_otp(struct otp_struct *otp_ptr); +int Decode_13850R2A(unsigned char*pInBuf, unsigned char* pOutBuf); +void otp_cali(unsigned char writeid); +void LumaDecoder(uint8_t *pData, uint8_t *pPara); +void ColorDecoder(uint8_t *pData, uint8_t *pPara); +//extern int read_otp_info(int index, struct otp_struct *otp_ptr); +//extern int update_otp_wb(void); +//extern int update_otp_lenc(void); + + + + + + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850_otp_cal.c b/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850_otp_cal.c new file mode 100755 index 0000000000000000000000000000000000000000..4ac47f3111de4b9fd9a50b5899b4a86b6beab719 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850_otp_cal.c @@ -0,0 +1,529 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + + +#include "ov13850mipiraw_Sensor.h" +#include "ov13850_otp.h" + +#if 1 +extern int iReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); + +//#define OV13850_R2A_write_i2c(addr, para) iWriteReg((u16) addr , (u32) para , 1, OV13850MIPI_WRITE_ID) +#define PFX "OV13850_R2A_OTP" +#define LOG_INF(format, args...) //xlog_printk(ANDROID_LOG_INFO , PFX, "[%s] " format, __FUNCTION__, ##args) + + +#define Delay(ms) mdelay(ms) +static unsigned char OV13850MIPI_WRITE_ID = 0X00; + +kal_uint16 OV13850_R2A_read_i2c(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + iReadReg((u16) addr ,(u8*)&get_byte,OV13850MIPI_WRITE_ID); + return get_byte; +} + +kal_uint16 OV13850_R2A_write_i2c(addr, para) +{ + iWriteReg((u16) addr , (u32) para , 1, OV13850MIPI_WRITE_ID); + return 1; +} +#endif + +void otp_cali(unsigned char writeid) +{ + struct otp_struct current_otp; + OV13850MIPI_WRITE_ID = writeid; + memset(¤t_otp, 0, sizeof(struct otp_struct)); + read_otp(¤t_otp); + apply_otp(¤t_otp); +} + +int Decode_13850R2A(unsigned char*pInBuf, unsigned char* pOutBuf) +{ + if(pInBuf != NULL) + { + LumaDecoder(pInBuf, pOutBuf); + ColorDecoder((pInBuf+86), (pOutBuf+120)); + ColorDecoder((pInBuf+136), (pOutBuf+240)); + LOG_INF(" OTP OK \n"); + return 1; + } + { + LOG_INF(" OTP FAIL \n"); + return 0; + } + +} +// return value: +// bit[7]: 0 no otp info, 1 valid otp info +// bit[6]: 0 no otp wb, 1 valib otp wb +// bit[5]: 0 no otp vcm, 1 valid otp vcm +// bit[4]: 0 no otp lenc, 1 valid otp lenc +int read_otp(struct otp_struct *otp_ptr) +{ + + int otp_flag=0; + int addr=0; + int temp=0; + int i=0; + int checksumLSC = 0; + int checksumOTP = 0; + int checksumTotal = 0; + //int Êý×é´óС360»á±àÒë²»¹ý + unsigned char lenc_out[360]; + //set 0x5002[1] to "0" + int temp1=0; + temp1 = OV13850_R2A_read_i2c(0x5002); + OV13850_R2A_write_i2c(0x5002, (0x00 & 0x02) | (temp1 & (~0x02))); + // read OTP into buffer + OV13850_R2A_write_i2c(0x3d84, 0xC0); + OV13850_R2A_write_i2c(0x3d88, 0x72); // OTP start address + OV13850_R2A_write_i2c(0x3d89, 0x20); + OV13850_R2A_write_i2c(0x3d8A, 0x73); // OTP end address + OV13850_R2A_write_i2c(0x3d8B, 0xBE); + OV13850_R2A_write_i2c(0x3d81, 0x01); // load otp into buffer + Delay(10); + // OTP base information and WB calibration data + otp_flag = OV13850_R2A_read_i2c(0x7220); + LOG_INF(" WB calibration data : %x \n", otp_flag); + addr = 0; + if((otp_flag & 0xc0) == 0x40) { + addr = 0x7221; // base address of info group 1 + } + else if((otp_flag & 0x30) == 0x10) { + addr = 0x7229; // base address of info group 2 + } + if(addr != 0) { + (*otp_ptr).flag = 0xC0; // valid info and AWB in OTP + (*otp_ptr).module_integrator_id = OV13850_R2A_read_i2c(addr); + (*otp_ptr).lens_id = OV13850_R2A_read_i2c( addr + 1); + (*otp_ptr).production_year = OV13850_R2A_read_i2c( addr + 2); + (*otp_ptr).production_month = OV13850_R2A_read_i2c( addr + 3); + (*otp_ptr).production_day = OV13850_R2A_read_i2c(addr + 4); + temp = OV13850_R2A_read_i2c(addr + 7); + (*otp_ptr).rg_ratio = (OV13850_R2A_read_i2c(addr + 5)<<2) + ((temp>>6) & 0x03); + (*otp_ptr).bg_ratio = (OV13850_R2A_read_i2c(addr + 6)<<2) + ((temp>>4) & 0x03); + } + else { + (*otp_ptr).flag = 0x00; // not info in OTP + (*otp_ptr).module_integrator_id = 0; + (*otp_ptr).lens_id = 0; + (*otp_ptr).production_year = 0; + (*otp_ptr).production_month = 0; + (*otp_ptr).production_day = 0; + } + // OTP VCM Calibration + otp_flag = OV13850_R2A_read_i2c(0x73ac); + LOG_INF(" VCM calibration data : %x \n", otp_flag); + addr = 0; + if((otp_flag & 0xc0) == 0x40) { + addr = 0x73ad; // base address of VCM Calibration group 1 + } + else if((otp_flag & 0x30) == 0x10) { + addr = 0x73b0; // base address of VCM Calibration group 2 + } + if(addr != 0) { + (*otp_ptr).flag |= 0x20; + temp = OV13850_R2A_read_i2c(addr + 2); + (* otp_ptr).VCM_start = (OV13850_R2A_read_i2c(addr)<<2) | ((temp>>6) & 0x03); + (* otp_ptr).VCM_end = (OV13850_R2A_read_i2c(addr + 1) << 2) | ((temp>>4) & 0x03); + (* otp_ptr).VCM_dir = (temp>>2) & 0x03; + } + else { + (* otp_ptr).VCM_start = 0; + (* otp_ptr).VCM_end = 0; + (* otp_ptr).VCM_dir = 0; + } + // OTP Lenc Calibration + otp_flag = OV13850_R2A_read_i2c(0x7231); + LOG_INF(" Lenc calibration data : %x \n", otp_flag); + addr = 0; + //int checksumLSC = 0, checksumOTP = 0, checksumTotal = 0; + if((otp_flag & 0xc0) == 0x40) { + addr = 0x7232; // base address of Lenc Calibration group 1 + } + else if((otp_flag & 0x30) == 0x10) { + addr = 0x72ef; // base address of Lenc Calibration group 2 + } + // + LOG_INF(" Lenc calibration addr : %x \n", addr); +if(addr != 0) { + for(i=0;i<186;i++) { + (* otp_ptr).lenc[i]= OV13850_R2A_read_i2c(addr + i); + checksumLSC += (* otp_ptr).lenc[i]; + LOG_INF(" Lenc (* otp_ptr).lenc[%d] : %x \n", i, (* otp_ptr).lenc[i]); + } + //Decode the lenc buffer from OTP , from 186 bytes to 360 bytes + //int lenc_out[360]; + + for(i=0;i<360;i++) + { + lenc_out[i] = 0; + } + if(Decode_13850R2A((*otp_ptr).lenc, lenc_out)) + { + for(i=0;i<360;i++) + { + LOG_INF(" from OTP lenc_out[%d]:%x \n", i, lenc_out[i]); + checksumOTP = checksumOTP + lenc_out[i]; + } + } + + checksumLSC = (checksumLSC)%255 +1; + checksumOTP = (checksumOTP)%255 +1; + checksumTotal = (checksumLSC) ^ (checksumOTP); + (* otp_ptr).checksumLSC=OV13850_R2A_read_i2c(addr + 186); + (* otp_ptr).checksumOTP=OV13850_R2A_read_i2c(addr + 187); + (* otp_ptr).checksumTotal=OV13850_R2A_read_i2c(addr + 188); + LOG_INF(" checksumLSC-OTP-Total:%x-%x-%x;read checksumLSC-OTP-Total:%x-%x-%x\n", checksumLSC, checksumOTP,checksumTotal,(* otp_ptr).checksumLSC,(* otp_ptr).checksumOTP,(* otp_ptr).checksumTotal); + if((* otp_ptr).checksumLSC == checksumLSC && (* otp_ptr).checksumOTP == checksumOTP){ + (*otp_ptr).flag |= 0x10; + } + else if((* otp_ptr).checksumTotal == checksumTotal){ + (*otp_ptr).flag |= 0x10; + } + } + else { + for(i=0;i<186;i++) { + (* otp_ptr).lenc[i]=0; + } + } + for(i=0x7220;i<=0x73be;i++) + { + OV13850_R2A_write_i2c(i,0); // clear OTP buffer, recommended use continuous write to accelarate + } + + //set 0x5002[1] to "1" + temp1 = OV13850_R2A_read_i2c(0x5002); + OV13850_R2A_write_i2c(0x5002, (0x02 & 0x02) | (temp1 & (~0x02))); + + return (*otp_ptr).flag; +} + + +// return value: +// bit[7]: 0 no otp info, 1 valid otp info +// bit[6]: 0 no otp wb, 1 valib otp wb +// bit[5]: 0 no otp vcm, 1 valid otp vcm +// bit[4]: 0 no otp lenc, 1 valid otp lenc +int apply_otp(struct otp_struct *otp_ptr) +{ + int rg=0; + int bg=0; + int R_gain=0; + int G_gain=0; + int B_gain=0; + int Base_gain=0; + int temp=0; + int i=0; + unsigned char lenc_out[360]; + LOG_INF(" apply_otp (*otp_ptr).flag : %x \n", (*otp_ptr).flag); + // apply OTP WB Calibration + if ((*otp_ptr).flag & 0x40) { + LOG_INF(" apply OTP WB Calibration : %x \n", (*otp_ptr).flag); + rg = (*otp_ptr).rg_ratio; + bg = (*otp_ptr).bg_ratio; + + //calculate G gain + R_gain = (RG_Ratio_Typical*1000) / rg; + B_gain = (BG_Ratio_Typical*1000) / bg; + G_gain = 1000; + + if (R_gain < 1000 || B_gain < 1000) + { + if (R_gain < B_gain) + Base_gain = R_gain; + else + Base_gain = B_gain; + } + else + { + Base_gain = G_gain; + } + + R_gain = 0x400 * R_gain / (Base_gain); + B_gain = 0x400 * B_gain / (Base_gain); + G_gain = 0x400 * G_gain / (Base_gain); + + // update sensor WB gain + if (R_gain>0x400) { + OV13850_R2A_write_i2c(0x5056, R_gain>>8); + OV13850_R2A_write_i2c(0x5057, R_gain & 0x00ff); + } + + if (G_gain>0x400) { + OV13850_R2A_write_i2c(0x5058, G_gain>>8); + OV13850_R2A_write_i2c(0x5059, G_gain & 0x00ff); + } + + if (B_gain>0x400) { + OV13850_R2A_write_i2c(0x505A, B_gain>>8); + OV13850_R2A_write_i2c(0x505B, B_gain & 0x00ff); + } + } + + // apply OTP Lenc Calibration + if ((*otp_ptr).flag & 0x10) { + + LOG_INF(" apply OTP Lenc Calibration : %x \n", (*otp_ptr).flag); + temp = OV13850_R2A_read_i2c(0x5000); + temp = 0x01 | temp; + OV13850_R2A_write_i2c(0x5000, temp); + + //Decode the lenc buffer from OTP , from 186 bytes to 360 bytes + + for(i=0;i<360;i++) + { + lenc_out[i] = 0; + } + /***For function Decode_13850R2A(unsigned char*pInBuf, unsigned char* pOutBuf),please refer to lc42.h***/ + if(Decode_13850R2A((*otp_ptr).lenc, lenc_out)) + { + for(i=0;i<360 ;i++) { + LOG_INF(" apply OTP lenc_out[%d]:%x \n", i, lenc_out[i]); + OV13850_R2A_write_i2c(0x5200 + i, lenc_out[i]); + } + } + } +} + +/***********Decode LENC Para Process Start*********************/ +void LumaDecoder(uint8_t *pData, uint8_t *pPara) +{ + + uint32_t Offset, Bit, Option; + uint32_t i, k; + uint8_t pCenter[16], pMiddle[32], pCorner[72]; + Offset = pData[0]; + Bit = pData[1]>>4; + Option = pData[1]&0xf; + LOG_INF("Offset:%x, Bit:%x, Option:%x \n",Offset, Bit, Option); + for (i=0; i<180; i++) + { + LOG_INF("data-pData[%d]:%x \n", i, pData[i]); + } + if(Bit <= 5) + { + for(i=0,k=2; i<120; i+=8,k+=5) + { + //LOG_INF("pData[%d]:%x \n", i, pData[i]); + pPara[i] = pData[k]>>3; // 7~3 (byte0) + pPara[i+1] = ((pData[k]&0x7)<<2)|(pData[k+1]>>6); // 2~0 (byte0) and 7~6(byte1) + pPara[i+2] = (pData[k+1]&0x3e)>>1; // 5~1 (byte1) + pPara[i+3] = ((pData[k+1]&0x1)<<4)|(pData[k+2]>>4); // 0 (byte1) and 7~4(byte2) + pPara[i+4] = ((pData[k+2]&0xf)<<1)|(pData[k+3]>>7); // 3~0 (byte2) and 7(byte3) + pPara[i+5] = (pData[k+3]&0x7c)>>2; // 6~2 (byte3) + pPara[i+6] = ((pData[k+3]&0x3)<<3)|(pData[k+4]>>5); // 1~0 (byte3) and 7~5(byte4) + pPara[i+7] = pData[k+4]&0x1f; // 4~0 (byte4) + + LOG_INF("bit-pData[%d]:%x \n", k, pData[k]); + LOG_INF("bit-pData[%d]:%x \n", k+1, pData[k+1]); + LOG_INF("bit-pData[%d]:%x \n", k+2, pData[k+2]); + LOG_INF("bit-pData[%d]:%x \n", k+3, pData[k+3]); + LOG_INF("bit-pData[%d]:%x \n", k+4, pData[k+4]); + + + LOG_INF("bit-pData[%d]:%x \n", i, pPara[i]); + LOG_INF("bit-pData[%d]:%x \n", i+1, pPara[i+1]); + LOG_INF("bit-pData[%d]:%x \n", i+2, pPara[i+2]); + LOG_INF("bit-pData[%d]:%x \n", i+3, pPara[i+3]); + LOG_INF("bit-pData[%d]:%x \n", i+4, pPara[i+4]); + LOG_INF("bit-pData[%d]:%x \n", i+5, pPara[i+5]); + LOG_INF("bit-pData[%d]:%x \n", i+6, pPara[i+6]); + LOG_INF("bit-pData[%d]:%x \n", i+7, pPara[i+7]); + } + } + else + { + for(i=0,k=2; i<48; i+=8,k+=5) + { + //LOG_INF(" apData[%d]:%x \n", i, pData[i]); + pPara[i] = pData[k]>>3; // 7~3 (byte0) + pPara[i+1] = ((pData[k]&0x7)<<2)|(pData[k+1]>>6); // 2~0 (byte0) and 7~6(byte1) + pPara[i+2] = (pData[k+1]&0x3e)>>1; // 5~1 (byte1) + pPara[i+3] = ((pData[k+1]&0x1)<<4)|(pData[k+2]>>4); // 0 (byte1) and 7~4(byte2) + pPara[i+4] = ((pData[k+2]&0xf)<<1)|(pData[k+3]>>7); // 3~0 (byte2) and 7(byte3) + pPara[i+5] = (pData[k+3]&0x7c)>>2; // 6~2 (byte3) + pPara[i+6] = ((pData[k+3]&0x3)<<3)|(pData[k+4]>>5); // 1~0 (byte3) and 7~5(byte4) + pPara[i+7] = pData[k+4]&0x1f; // 4~0 (byte4) + + LOG_INF("else -pData[%d]:%x \n", i, pData[i]); + LOG_INF("else -pData[%d]:%x \n", i+1, pData[i+1]); + LOG_INF("else -pData[%d]:%x \n", i+2, pData[i+2]); + LOG_INF("else -pData[%d]:%x \n", i+3, pData[i+3]); + LOG_INF("else -pData[%d]:%x \n", i+4, pData[i+4]); + LOG_INF("else -pData[%d]:%x \n", i+5, pData[i+5]); + LOG_INF("else -pData[%d]:%x \n", i+6, pData[i+6]); + LOG_INF("else -pData[%d]:%x \n", i+7, pData[i+7]); + } + for(i=48,k=32; i<120; i+=4,k+=3) + { + //LOG_INF(" 48--pData[%d]:%x \n", i, pData[i]); + pPara[i] = pData[k]>>2; // 7~2 (byte0) + pPara[i+1] = ((pData[k]&0x3)<<4)|(pData[k+1]>>4); //1~0 (byte0) and7~4(byte1) + pPara[i+2] = ((pData[k+1]&0xf)<<2)|(pData[k+2]>>6); //3~0 (byte1) and7~6(byte2) + pPara[i+3] = pData[k+2]&0x3f; // 5~0 (byte2) + + LOG_INF("48--pData[%d]:%x \n", i, pData[i]); + LOG_INF("48--pData[%d]:%x \n", i+1, pData[i+1]); + LOG_INF("48--pData[%d]:%x \n", i+2, pData[i+2]); + LOG_INF("48--pData[%d]:%x \n", i+3, pData[i+3]); + } + memcpy(pCenter, pPara, 16); + memcpy(pMiddle, pPara+16, 32); + memcpy(pCorner, pPara+48, 72); + for(i=0; i<32; i++) + { + pMiddle[i] <<= (Bit-6); + } + for(i=0; i<72; i++) + { + pCorner[i] <<= (Bit-6); + } + if(Option == 0) + { // 10x12 + memcpy(pPara, pCorner, 26); + memcpy(pPara+26, pMiddle, 8); + memcpy(pPara+34, pCorner+26, 4); + memcpy(pPara+38, pMiddle+8, 2); + memcpy(pPara+40, pCenter, 4); + memcpy(pPara+44, pMiddle+10, 2); + memcpy(pPara+46, pCorner+30, 4); + memcpy(pPara+50, pMiddle+12, 2); + memcpy(pPara+52, pCenter+4, 4); + memcpy(pPara+56, pMiddle+14, 2); + memcpy(pPara+58, pCorner+34, 4); + memcpy(pPara+62, pMiddle+16, 2); + memcpy(pPara+64, pCenter+8, 4); + memcpy(pPara+68, pMiddle+18, 2); + memcpy(pPara+70, pCorner+38, 4); + memcpy(pPara+74, pMiddle+20, 2); + memcpy(pPara+76, pCenter+12, 4); + memcpy(pPara+80, pMiddle+22, 2); + memcpy(pPara+82, pCorner+42, 4); + memcpy(pPara+86, pMiddle+24, 8); + memcpy(pPara+94, pCorner+46, 26); + } + else + { // 12x10 + memcpy(pPara, pCorner, 22); + memcpy(pPara+22, pMiddle, 6); + memcpy(pPara+28, pCorner+22, 4); + memcpy(pPara+32, pMiddle+6, 6); + memcpy(pPara+38, pCorner+26, 4); + memcpy(pPara+42, pMiddle+12, 1); + memcpy(pPara+43, pCenter, 4); + memcpy(pPara+47, pMiddle+13, 1); + memcpy(pPara+48, pCorner+30, 4); + memcpy(pPara+52, pMiddle+14, 1); + memcpy(pPara+53, pCenter+4, 4); + memcpy(pPara+57, pMiddle+15, 1); + memcpy(pPara+58, pCorner+34, 4); + memcpy(pPara+62, pMiddle+16, 1); + memcpy(pPara+63, pCenter+8, 4); + memcpy(pPara+67, pMiddle+17, 1); + memcpy(pPara+68, pCorner+38, 4); + memcpy(pPara+72, pMiddle+18, 1); + memcpy(pPara+73, pCenter+12, 4); + memcpy(pPara+77, pMiddle+19, 1); + memcpy(pPara+78, pCorner+42, 4); + memcpy(pPara+82, pMiddle+20, 6); + memcpy(pPara+88, pCorner+46, 4); + memcpy(pPara+92, pMiddle+26, 6); + memcpy(pPara+98, pCorner+50, 22); + } + } + for(i=0; i<120; i++) + { + LOG_INF(" pPara[%d]:%x \n", i, pPara[i]); + pPara[i] += Offset; + } + +} +// +void ColorDecoder(uint8_t *pData, uint8_t *pPara) +{ + + uint32_t Offset, Bit, Option; + uint32_t i, k; + uint8_t pBase[30]; + Offset = pData[0]; + Bit = pData[1]>>7; + Option = (pData[1]&0x40)>>6; + pPara[0] = (pData[1]&0x3e)>>1; // 5~1 (byte1) + pPara[1] = ((pData[1]&0x1)<<4)|(pData[2]>>4); // 0 (byte1) and 7~4 (byte2) + pPara[2] = ((pData[2]&0xf)<<1)|(pData[3]>>7); // 3~0 (byte2) and 7 (byte3) + pPara[3] = (pData[3]&0x7c)>>2; // 6~2 (byte3) + pPara[4] = ((pData[3]&0x3)<<3)|(pData[4]>>5); // 1~0 (byte3) and 7~5 (byte4) + pPara[5] = pData[4]&0x1f; // 4~0 (byte4) + for(i=6,k=5; i<30; i+=8,k+=5) + { + pPara[i] = pData[k]>>3; // 7~3 (byte0) + pPara[i+1] = ((pData[k]&0x7)<<2)|(pData[k+1]>>6); // 2~0 (byte0) and 7~6 (byte1) + pPara[i+2] = (pData[k+1]&0x3e)>>1; // 5~1 (byte1) + pPara[i+3] = ((pData[k+1]&0x1)<<4)|(pData[k+2]>>4); // 0 (byte1) and 7~4 (byte2) + pPara[i+4] = ((pData[k+2]&0xf)<<1)|(pData[k+3]>>7); // 3~0 (byte2) and 7 (byte3) + pPara[i+5] = (pData[k+3]&0x7c)>>2; // 6~2 (byte3) + pPara[i+6] = ((pData[k+3]&0x3)<<3)|(pData[k+4]>>5); // 1~0 (byte3) and 7~5 (byte4) + pPara[i+7] = pData[k+4]&0x1f; // 4~0 (byte4) + } + memcpy(pBase, pPara, 30); + for(i=0,k=20; i<120; i+=4,k++) + { + pPara[i] = pData[k]>>6; + pPara[i+1] = (pData[k]&0x30)>>4; + pPara[i+2] = (pData[k]&0xc)>>2; + pPara[i+3] = pData[k]&0x3; + } + if(Option == 0) + { // 10x12 + for(i=0; i<5; i++) + { + for(k=0; k<6; k++) + { + pPara[i*24+k*2] += pBase[i*6+k]; + pPara[i*24+k*2+1] += pBase[i*6+k]; + pPara[i*24+k*2+12] += pBase[i*6+k]; + pPara[i*24+k*2+13] += pBase[i*6+k]; + } + } + }else + { // 12x10 + for(i=0; i<6; i++) + { + for(k=0; k<5; k++) + { + pPara[i*20+k*2] += pBase[i*5+k]; + pPara[i*20+k*2+1] += pBase[i*5+k]; + pPara[i*20+k*2+10] += pBase[i*5+k]; + pPara[i*20+k*2+11] += pBase[i*5+k]; + } + } + } + for(i=0; i<120; i++) + { + pPara[i] = (pPara[i]< +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include "kd_camera_typedef.h" + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "ov13850mipiraw_Sensor.h" + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "OV13850_camera_sensor" +#define LOG_1 LOG_INF("OV13850,MIPI 4LANE\n") +#define LOG_2 LOG_INF("preview 2096*1552@30fps,640Mbps/lane; video 4192*3104@30fps,1.2Gbps/lane; capture 13M@30fps,1.2Gbps/lane\n") +/**************************** Modify end *******************************************/ + +#if 0 +#define LOG_INF(format, args...) printk(PFX "[%s] " format, __FUNCTION__, ##args) +#else +#define LOG_INF(format, args...) +#endif + +static DEFINE_SPINLOCK(imgsensor_drv_lock); +#define MIPI_SETTLEDELAY_AUTO 0 +#define MIPI_SETTLEDELAY_MANNUAL 1 + +int ov13850_chip_ver = OV13850_R2A; +//sensor otp +extern void otp_cali(unsigned char writeid); + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = OV13850_SENSOR_ID, //record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0xbde6b5f8,//0xf86cfdf4, //checksum value for Camera Auto Test + + .pre = { + .pclk = 240000000, //record different mode's pclk + .linelength = 2400, //record different mode's linelength + .framelength = 3328, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk = 480000000, + .linelength = 4800, + .framelength = 3328, + .startx = 0, + .starty = 0, + .grabwindow_width = 4192, //4192, + .grabwindow_height = 3104,//3104, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 300, + }, + .cap1 = { //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 384000000, + .linelength = 4800, + .framelength = 3328, + .startx = 0, + .starty = 0, + .grabwindow_width = 4192, + .grabwindow_height = 3104, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 150, //less than 13M(include 13M),cap1 max framerate is 24fps,16M max framerate is 20fps, 20M max framerate is 15fps + }, + .normal_video = { + .pclk = 480000000, + .linelength = 4800, + .framelength = 3328, + .startx = 0, + .starty = 0, + .grabwindow_width = 4192, + .grabwindow_height = 3104, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 300, + }, + .hs_video = { + .pclk = 240000000, + .linelength = 2968, + .framelength = 674, + .startx = 0, + .starty = 0, + .grabwindow_width = 640, + .grabwindow_height = 480, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 1200, + }, + .slim_video = { + .pclk = 240000000, + .linelength = 9600,//2400, + .framelength = 834,//3328, + .startx = 0, + .starty = 0, + .grabwindow_width = 1280, + .grabwindow_height = 720, + .mipi_data_lp2hs_settle_dc = 100,//unit , ns + .max_framerate = 300, + + }, + .margin = 8, //sensor framelength & shutter margin + .min_shutter = 0x3, //min shutter + .max_frame_length = 0x7fff,//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num + + .cap_delay_frame = 3, //enter capture delay frame num + .pre_delay_frame = 2, //enter preview delay frame num + .video_delay_frame = 2, //enter video delay frame num + .hs_video_delay_frame = 2, //enter high speed video delay frame num + .slim_video_delay_frame = 2,//enter slim video delay frame num + + .isp_driving_current = ISP_DRIVING_8MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_4_LANE,//mipi lane num + .i2c_addr_table = {0x6c, 0x20, 0xff},//record sensor support all write id addr, only supprt 4must end with 0xff +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_H_MIRROR, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter + .gain = 0x100, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x00,//record current sensor's i2c write id +}; + + +/* Sensor output window information */ +#if 0 +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{{ 4208, 3120, 0, 0, 4208, 3120, 2104, 1560, 0, 0, 2104, 1560, 0, 0, 2096, 1552}, // Preview + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0, 0, 4208, 3120, 0, 0, 4192, 3104}, // capture + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0, 0, 4208, 3120, 0, 0, 4192, 3104}, // video +{ 4208, 3120, 0, 0, 4208, 3120, 2104, 1560, 0, 0, 1056, 594, 0, 0, 640, 480}, //hight speed video + { 4208, 3120, 0, 0, 4208, 3120, 1296, 730, 0, 0, 1296, 730, 0, 0, 1280, 720}, + +}; +#else +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{{ 4256, 3152, 0, 4, 4256, 3152, 2128, 1572, 8, 2, 2112, 1568, 0, 0, 2096, 1552}, // Preview + { 4256, 3152, 12, 4, 4232, 3144, 4232, 3144, 4, 4, 4224, 3136, 0, 0, 4192, 3104}, // capture + { 4256, 3152, 20, 12, 4216, 3128, 4216, 3128, 4, 4, 4208, 3120, 0, 0, 4192, 3104}, // video + { 4256, 3152, 0, 376, 4256, 2392, 1064, 598, 8, 2, 1056, 594, 208, 56, 640, 480}, //hight speed video + { 4256, 3152, 824, 842, 2608, 1468, 1304, 734, 4, 2, 1296, 730, 0, 0, 1280, 720}};// slim video + +#endif + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; +} + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + /* you can set dummy by imgsensor.dummy_line and imgsensor.dummy_pixel, or you can set dummy by imgsensor.frame_length and imgsensor.line_length */ + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x380c, imgsensor.line_length >> 8); + write_cmos_sensor(0x380d, imgsensor.line_length & 0xFF); + +} /* set_dummy */ + +static kal_uint32 return_sensor_id(void) +{ + return ((read_cmos_sensor(0x300A) << 8) | read_cmos_sensor(0x300B)); +} +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + //kal_int16 dummy_line; + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable = %d \n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + kal_uint16 realtime_fps = 0; + //kal_uint32 frame_length = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + LOG_INF("Enter! shutter =%d \n", shutter); + + //write_shutter(shutter); + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)&0x7f); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + } else { + // Extend frame length + //write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + //write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)&0x7f); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + + // Update Shutter + // write_cmos_sensor(0x3502, (shutter << 4) & 0xFF); + // write_cmos_sensor(0x3501, (shutter >> 4) & 0xFF); + // write_cmos_sensor(0x3500, (shutter >> 12) & 0x0F); + write_cmos_sensor(0x3500, (shutter>>12) & 0x0F); + write_cmos_sensor(0x3501, (shutter>>4) & 0xFF); + write_cmos_sensor(0x3502, (shutter<<4) & 0xF0); + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} /* set_shutter */ + + + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 iReg = 0x0000; + //kal_uint16 iGain=gain; + + if (ov13850_chip_ver == OV13850_R1A) + { + iReg = gain*32/BASEGAIN; + if(iReg < 0x20) + { + iReg = 0x20; + } + if(iReg > 0xfc) + { + iReg = 0xfc; + } + //SENSORDB("[OV13850Gain2Reg]: isp gain:%d,sensor gain:0x%x\n",iGain,iReg); + } + else if(ov13850_chip_ver == OV13850_R2A) + { + iReg = gain*16/BASEGAIN; + if(iReg < 0x10) + { + iReg = 0x10; + } + if(iReg > 0xf8) + { + iReg = 0xf8; + } + } + return iReg;//ov13850. sensorGlobalGain +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor(0x350a, reg_gain >> 8); + write_cmos_sensor(0x350b, reg_gain & 0xFF); + + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length first + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + + write_cmos_sensor(0x3502, (le << 4) & 0xFF); + write_cmos_sensor(0x3501, (le >> 4) & 0xFF); + write_cmos_sensor(0x3500, (le >> 12) & 0x0F); + + write_cmos_sensor(0x3508, (se << 4) & 0xFF); + write_cmos_sensor(0x3507, (se >> 4) & 0xFF); + write_cmos_sensor(0x3506, (se >> 12) & 0x0F); + + set_gain(gain); + } + +} + + + +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xFB) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xFB) | 0x00)); + break; + case IMAGE_H_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xFB) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xFF) | 0x04)); + break; + case IMAGE_V_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xFF) | 0x04)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xFB) | 0x00)); + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xFF) | 0x04)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xFF) | 0x04)); + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} + +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + +static void sensor_init(void) +{ + LOG_INF("E\n"); + + /***************************************************************************** + 0x3098[0:1] pll3_prediv + pll3_prediv_map[] = {2, 3, 4, 6} + + 0x3099[0:4] pll3_multiplier + pll3_multiplier + + 0x309C[0] pll3_rdiv + pll3_rdiv + 1 + + 0x309A[0:3] pll3_sys_div + pll3_sys_div + 1 + + 0x309B[0:1] pll3_div + pll3_div[] = {2, 2, 4, 5} + + VCO = XVCLK * 2 / pll3_prediv * pll3_multiplier * pll3_rdiv + sysclk = VCO * 2 * 2 / pll3_sys_div / pll3_div + + XVCLK = 24 MHZ + 0x3098, 0x03 + 0x3099, 0x1e + 0x309a, 0x02 + 0x309b, 0x01 + 0x309c, 0x00 + + + VCO = 24 * 2 / 6 * 31 * 1 + sysclk = VCO * 2 * 2 / 3 / 2 + sysclk = 160 MHZ + */ +/* + //write_cmos_sensor(0x0103, 0x01);//, + write_cmos_sensor(0x351b, 0x00); + write_cmos_sensor(0x351d, 0x00); + write_cmos_sensor(0x351f, 0x00); + write_cmos_sensor(0x3521, 0x00); + write_cmos_sensor(0x3600, 0x40); + write_cmos_sensor(0x3603, 0x48); + write_cmos_sensor(0x3604, 0xa5); + write_cmos_sensor(0x3605, 0x9f); + write_cmos_sensor(0x3606, 0x03); + write_cmos_sensor(0x3607, 0x00); + write_cmos_sensor(0x3609, 0x00); + write_cmos_sensor(0x360a, 0x40); + write_cmos_sensor(0x360f, 0x8a); + write_cmos_sensor(0x3615, 0x08); + write_cmos_sensor(0x3616, 0x00); + write_cmos_sensor(0x366a, 0x00); + write_cmos_sensor(0x3705, 0x24); + write_cmos_sensor(0x3706, 0x50); + write_cmos_sensor(0x3720, 0x66); + write_cmos_sensor(0x3761, 0x34); + write_cmos_sensor(0x376f, 0x00); + write_cmos_sensor(0x3773, 0x00); + write_cmos_sensor(0x3827, 0x00); + write_cmos_sensor(0x510f, 0x00); + write_cmos_sensor(0x5110, 0x00); + write_cmos_sensor(0x5111, 0x00); + write_cmos_sensor(0x5243, 0xb8); + write_cmos_sensor(0x5245, 0xf9); + write_cmos_sensor(0x5247, 0xf6); + write_cmos_sensor(0x5249, 0xa6); + write_cmos_sensor(0x5300, 0xfc); + write_cmos_sensor(0x5301, 0xdf); + write_cmos_sensor(0x5302, 0x3f); + write_cmos_sensor(0x5303, 0x08); + write_cmos_sensor(0x5304, 0x0c); + write_cmos_sensor(0x5305, 0x10); + write_cmos_sensor(0x5306, 0x20); + write_cmos_sensor(0x5307, 0x40); + write_cmos_sensor(0x5308, 0x08); + write_cmos_sensor(0x5309, 0x08); + write_cmos_sensor(0x530a, 0x02); + write_cmos_sensor(0x530b, 0x01); + write_cmos_sensor(0x530c, 0x01); + write_cmos_sensor(0x530d, 0x0c); + write_cmos_sensor(0x530e, 0x02); + write_cmos_sensor(0x530f, 0x01); + write_cmos_sensor(0x5310, 0x01); + write_cmos_sensor(0x536d, 0x00); + write_cmos_sensor(0x536e, 0x00); + write_cmos_sensor(0x536f, 0x00); + write_cmos_sensor(0x5370, 0x00); + */ + ////////////////////////////////// + write_cmos_sensor(0x0103, 0x01); + write_cmos_sensor(0x0102, 0x01);//for debug xb.pang color line + write_cmos_sensor(0x0300, 0x01); + write_cmos_sensor(0x0301, 0x00); + write_cmos_sensor(0x0302, 0x28); + write_cmos_sensor(0x0303, 0x00); + write_cmos_sensor(0x030a, 0x00); + write_cmos_sensor(0x300f, 0x11); + write_cmos_sensor(0x3010, 0x01); + write_cmos_sensor(0x3011, 0x76); + write_cmos_sensor(0x3012, 0x41); + write_cmos_sensor(0x3013, 0x12); + write_cmos_sensor(0x3014, 0x11); + write_cmos_sensor(0x301f, 0x03); + write_cmos_sensor(0x3106, 0x00); + write_cmos_sensor(0x3210, 0x47); + write_cmos_sensor(0x3500, 0x00); + write_cmos_sensor(0x3501, 0x60); + write_cmos_sensor(0x3502, 0x00); + write_cmos_sensor(0x3506, 0x00); + write_cmos_sensor(0x3507, 0x02); + write_cmos_sensor(0x3508, 0x00); + write_cmos_sensor(0x350a, 0x00); + write_cmos_sensor(0x350b, 0x80); + write_cmos_sensor(0x350e, 0x00); + write_cmos_sensor(0x350f, 0x10); + write_cmos_sensor(0x351a, 0x00); + write_cmos_sensor(0x351b, 0x10); + write_cmos_sensor(0x351c, 0x00); + write_cmos_sensor(0x351d, 0x20); + write_cmos_sensor(0x351e, 0x00); + write_cmos_sensor(0x351f, 0x40); + write_cmos_sensor(0x3520, 0x00); + write_cmos_sensor(0x3521, 0x80); + write_cmos_sensor(0x3600, 0xc0); + write_cmos_sensor(0x3601, 0xfc); + write_cmos_sensor(0x3602, 0x02); + write_cmos_sensor(0x3603, 0x78); + write_cmos_sensor(0x3604, 0xb1); + write_cmos_sensor(0x3605, 0xb5); + write_cmos_sensor(0x3606, 0x73); + write_cmos_sensor(0x3607, 0x07); + write_cmos_sensor(0x3609, 0x40); + write_cmos_sensor(0x360a, 0x30); + write_cmos_sensor(0x360b, 0x91); + write_cmos_sensor(0x360c, 0x49); + write_cmos_sensor(0x360f, 0x02); + write_cmos_sensor(0x3611, 0x10); + write_cmos_sensor(0x3612, 0x27); + write_cmos_sensor(0x3613, 0x33); + write_cmos_sensor(0x3615, 0x0c); + write_cmos_sensor(0x3616, 0x0e); + write_cmos_sensor(0x3641, 0x02); + write_cmos_sensor(0x3660, 0x82); + write_cmos_sensor(0x3668, 0x54); + write_cmos_sensor(0x3669, 0x00); + write_cmos_sensor(0x366a, 0x3f); + write_cmos_sensor(0x3667, 0xa0); + write_cmos_sensor(0x3702, 0x40); + write_cmos_sensor(0x3703, 0x44); + write_cmos_sensor(0x3704, 0x2c); + write_cmos_sensor(0x3705, 0x01); + write_cmos_sensor(0x3706, 0x15); + write_cmos_sensor(0x3707, 0x44); + write_cmos_sensor(0x3708, 0x3c); + write_cmos_sensor(0x3709, 0x1f); + write_cmos_sensor(0x370a, 0x27); + write_cmos_sensor(0x370b, 0x3c); + write_cmos_sensor(0x3720, 0x55); + write_cmos_sensor(0x3722, 0x84); + write_cmos_sensor(0x3728, 0x40); + write_cmos_sensor(0x372a, 0x00); + write_cmos_sensor(0x372b, 0x02); + write_cmos_sensor(0x372e, 0x22); + write_cmos_sensor(0x372f, 0x90); + write_cmos_sensor(0x3730, 0x00); + write_cmos_sensor(0x3731, 0x00); + write_cmos_sensor(0x3732, 0x00); + write_cmos_sensor(0x3733, 0x00); + write_cmos_sensor(0x3710, 0x28); + write_cmos_sensor(0x3716, 0x03); + write_cmos_sensor(0x3718, 0x10); + write_cmos_sensor(0x3719, 0x08); + write_cmos_sensor(0x371a, 0x08); + write_cmos_sensor(0x371c, 0xfc); + write_cmos_sensor(0x3748, 0x00); + write_cmos_sensor(0x3760, 0x13); + write_cmos_sensor(0x3761, 0x33); + write_cmos_sensor(0x3762, 0x86); + write_cmos_sensor(0x3763, 0x16); + write_cmos_sensor(0x3767, 0x24); + write_cmos_sensor(0x3768, 0x06); + write_cmos_sensor(0x3769, 0x45); + write_cmos_sensor(0x376c, 0x23); + write_cmos_sensor(0x376f, 0x80); + write_cmos_sensor(0x3773, 0x06); + write_cmos_sensor(0x3d84, 0x00); + write_cmos_sensor(0x3d85, 0x17); + write_cmos_sensor(0x3d8c, 0x73); + write_cmos_sensor(0x3d8d, 0xbf); + write_cmos_sensor(0x3800, 0x00); + write_cmos_sensor(0x3801, 0x08); + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x04); + write_cmos_sensor(0x3804, 0x10); + write_cmos_sensor(0x3805, 0x97); + write_cmos_sensor(0x3806, 0x0c); + write_cmos_sensor(0x3807, 0x4b); + write_cmos_sensor(0x3808, 0x08); + write_cmos_sensor(0x3809, 0x40); + write_cmos_sensor(0x380a, 0x06); + write_cmos_sensor(0x380b, 0x20); + write_cmos_sensor(0x380c, 0x09); + write_cmos_sensor(0x380d, 0x60); + write_cmos_sensor(0x380e, 0x06); + write_cmos_sensor(0x380f, 0x80); + write_cmos_sensor(0x3810, 0x00); + write_cmos_sensor(0x3811, 0x04); + write_cmos_sensor(0x3812, 0x00); + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x31); + write_cmos_sensor(0x3815, 0x31); + write_cmos_sensor(0x3820, 0x02); + write_cmos_sensor(0x3821, 0x06); + write_cmos_sensor(0x3823, 0x00); + write_cmos_sensor(0x3826, 0x00); + write_cmos_sensor(0x3827, 0x02); + write_cmos_sensor(0x3834, 0x00); + write_cmos_sensor(0x3835, 0x1c); + write_cmos_sensor(0x3836, 0x08); + write_cmos_sensor(0x3837, 0x02); + write_cmos_sensor(0x4000, 0xf1); + write_cmos_sensor(0x4001, 0x00); + write_cmos_sensor(0x400b, 0x0c); + write_cmos_sensor(0x4011, 0x00); + write_cmos_sensor(0x401a, 0x00); + write_cmos_sensor(0x401b, 0x00); + write_cmos_sensor(0x401c, 0x00); + write_cmos_sensor(0x401d, 0x00); + write_cmos_sensor(0x4020, 0x00); + write_cmos_sensor(0x4021, 0xe4); + write_cmos_sensor(0x4022, 0x04); + write_cmos_sensor(0x4023, 0xd7); + write_cmos_sensor(0x4024, 0x05); + write_cmos_sensor(0x4025, 0xbc); + write_cmos_sensor(0x4026, 0x05); + write_cmos_sensor(0x4027, 0xbf); + write_cmos_sensor(0x4028, 0x00); + write_cmos_sensor(0x4029, 0x02); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x08); + write_cmos_sensor(0x402c, 0x02); + write_cmos_sensor(0x402d, 0x02); + write_cmos_sensor(0x402e, 0x0c); + write_cmos_sensor(0x402f, 0x08); + write_cmos_sensor(0x403d, 0x2c); + write_cmos_sensor(0x403f, 0x7f); + write_cmos_sensor(0x4041, 0x07); + write_cmos_sensor(0x4500, 0x82); + write_cmos_sensor(0x4501, 0x3c); + write_cmos_sensor(0x458b, 0x00); + write_cmos_sensor(0x459c, 0x00); + write_cmos_sensor(0x459d, 0x00); + write_cmos_sensor(0x459e, 0x00); + write_cmos_sensor(0x4601, 0x83); + write_cmos_sensor(0x4602, 0x22); + write_cmos_sensor(0x4603, 0x01); + write_cmos_sensor(0x4837, 0x19); + write_cmos_sensor(0x4d00, 0x04); + write_cmos_sensor(0x4d01, 0x42); + write_cmos_sensor(0x4d02, 0xd1); + write_cmos_sensor(0x4d03, 0x90); + write_cmos_sensor(0x4d04, 0x66); + write_cmos_sensor(0x4d05, 0x65); + write_cmos_sensor(0x4d0b, 0x00); + write_cmos_sensor(0x5000, 0x0e);//0e + write_cmos_sensor(0x5001, 0x03);//0x01-->0x03 for manual wb gain + write_cmos_sensor(0x5002, 0x07); + write_cmos_sensor(0x5013, 0x40); + write_cmos_sensor(0x501c, 0x00); + write_cmos_sensor(0x501d, 0x10); + write_cmos_sensor(0x510f, 0xfc); + write_cmos_sensor(0x5110, 0xf0); + write_cmos_sensor(0x5111, 0x10); + write_cmos_sensor(0x536d, 0x02); + write_cmos_sensor(0x536e, 0x67); + write_cmos_sensor(0x536f, 0x01); + write_cmos_sensor(0x5370, 0x4c); + write_cmos_sensor(0x5400, 0x00); + write_cmos_sensor(0x5400, 0x00); + write_cmos_sensor(0x5401, 0x61); + write_cmos_sensor(0x5402, 0x00); + write_cmos_sensor(0x5403, 0x00); + write_cmos_sensor(0x5404, 0x00); + write_cmos_sensor(0x5405, 0x40); + write_cmos_sensor(0x540c, 0x05); + write_cmos_sensor(0x5501, 0x00); + write_cmos_sensor(0x5b00, 0x00); + write_cmos_sensor(0x5b01, 0x00); + write_cmos_sensor(0x5b02, 0x01); + write_cmos_sensor(0x5b03, 0xff); + write_cmos_sensor(0x5b04, 0x02); + write_cmos_sensor(0x5b05, 0x6c); + write_cmos_sensor(0x5b09, 0x02); + write_cmos_sensor(0x5e00, 0x00); + write_cmos_sensor(0x5e10, 0x1c); + if (ov13850_chip_ver == OV13850_R1A) + { + write_cmos_sensor(0x351b, 0x00); + write_cmos_sensor(0x351d, 0x00); + write_cmos_sensor(0x351f, 0x00); + write_cmos_sensor(0x3521, 0x00); + write_cmos_sensor(0x3600, 0x40); + write_cmos_sensor(0x3603, 0x48); + write_cmos_sensor(0x3604, 0xa5); + write_cmos_sensor(0x3605, 0x9f); + write_cmos_sensor(0x3606, 0x03); + write_cmos_sensor(0x3607, 0x00); + write_cmos_sensor(0x3609, 0x00); + write_cmos_sensor(0x360a, 0x40); + write_cmos_sensor(0x360f, 0x8a); + write_cmos_sensor(0x3615, 0x08); + write_cmos_sensor(0x3616, 0x00); + write_cmos_sensor(0x366a, 0x00); + write_cmos_sensor(0x3705, 0x24); + write_cmos_sensor(0x3706, 0x50); + write_cmos_sensor(0x3720, 0x66); + write_cmos_sensor(0x3761, 0x34); + write_cmos_sensor(0x376f, 0x00); + write_cmos_sensor(0x3773, 0x00); + write_cmos_sensor(0x3827, 0x00); + write_cmos_sensor(0x510f, 0x00); + write_cmos_sensor(0x5110, 0x00); + write_cmos_sensor(0x5111, 0x00); + write_cmos_sensor(0x5243, 0xb8); + write_cmos_sensor(0x5245, 0xf9); + write_cmos_sensor(0x5247, 0xf6); + write_cmos_sensor(0x5249, 0xa6); + write_cmos_sensor(0x5300, 0xfc); + write_cmos_sensor(0x5301, 0xdf); + write_cmos_sensor(0x5302, 0x3f); + write_cmos_sensor(0x5303, 0x08); + write_cmos_sensor(0x5304, 0x0c); + write_cmos_sensor(0x5305, 0x10); + write_cmos_sensor(0x5306, 0x20); + write_cmos_sensor(0x5307, 0x40); + write_cmos_sensor(0x5308, 0x08); + write_cmos_sensor(0x5309, 0x08); + write_cmos_sensor(0x530a, 0x02); + write_cmos_sensor(0x530b, 0x01); + write_cmos_sensor(0x530c, 0x01); + write_cmos_sensor(0x530d, 0x0c); + write_cmos_sensor(0x530e, 0x02); + write_cmos_sensor(0x530f, 0x01); + write_cmos_sensor(0x5310, 0x01); + write_cmos_sensor(0x536d, 0x00); + write_cmos_sensor(0x536e, 0x00); + write_cmos_sensor(0x536f, 0x00); + write_cmos_sensor(0x5370, 0x00); + } + write_cmos_sensor(0x0100, 0x01);// +} /* sensor_init */ + + +static void preview_setting(void) +{ + write_cmos_sensor(0x0100, 0x00);// + write_cmos_sensor(0x0300, 0x01); + write_cmos_sensor(0x0302, 0x28); + write_cmos_sensor(0x0303, 0x00); + write_cmos_sensor(0x3612, 0x27); + write_cmos_sensor(0x3501, 0x60); + write_cmos_sensor(0x3702, 0x40); + write_cmos_sensor(0x370a, 0x27); + write_cmos_sensor(0x3718, 0x1c);//add new20140801 + write_cmos_sensor(0x372a, 0x00); + write_cmos_sensor(0x372f, 0xa0);//0x90 + write_cmos_sensor(0x3800, 0x0); + write_cmos_sensor(0x3801, 0x00);//0x08 + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x04); + write_cmos_sensor(0x3804, 0x10); + write_cmos_sensor(0x3805, 0x9f);//0x97 + write_cmos_sensor(0x3806, 0x0c); + write_cmos_sensor(0x3807, 0x4b); + write_cmos_sensor(0x3808, 0x08); + write_cmos_sensor(0x3809, 0x40); + write_cmos_sensor(0x380a, 0x06); + write_cmos_sensor(0x380b, 0x20); + write_cmos_sensor(0x380c, ((imgsensor_info.pre.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.pre.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.pre.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.pre.framelength & 0xFF)); // vts + write_cmos_sensor(0x3811, 0x08);//0x04 + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x31); + write_cmos_sensor(0x3815, 0x31); + write_cmos_sensor(0x3820, 0x01);//0x02 + write_cmos_sensor(0x3821, 0x06); + write_cmos_sensor(0x3834, 0x00); + write_cmos_sensor(0x3836, 0x08); + write_cmos_sensor(0x3837, 0x02); + write_cmos_sensor(0x4020, 0x00); + write_cmos_sensor(0x4021, 0xe4); + write_cmos_sensor(0x4022, 0x04); + write_cmos_sensor(0x4023, 0xd7); + write_cmos_sensor(0x4024, 0x05); + write_cmos_sensor(0x4025, 0xbc); + write_cmos_sensor(0x4026, 0x05); + write_cmos_sensor(0x4027, 0xbf); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x08); + write_cmos_sensor(0x402c, 0x02); + write_cmos_sensor(0x402e, 0x0c); + write_cmos_sensor(0x402f, 0x08); + write_cmos_sensor(0x4501, 0x3c); + write_cmos_sensor(0x4601, 0x83); + write_cmos_sensor(0x4603, 0x01); + write_cmos_sensor(0x4837, 0x19); + write_cmos_sensor(0x5401, 0x61); + write_cmos_sensor(0x5405, 0x40); + write_cmos_sensor(0x0100, 0x01);// + mdelay(10); +} /* preview_setting */ + +/*capture_first_flag & pre_currefps for resolve ov13850r2a +* low light zsd capture color-line issue +*/ +int capture_first_flag = 0; +int pre_currefps = 0; +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + +if (pre_currefps != currefps) +{ + capture_first_flag = 0; + pre_currefps = currefps; +} +else +{ + capture_first_flag = 1; +} +if (capture_first_flag == 0) +{ + + if (currefps == 150) { //15fps for PIP + //@@full_132PCLK_24.75 + write_cmos_sensor(0x0300, 0x01);// + write_cmos_sensor(0x0302, 0x28);// + write_cmos_sensor(0x0303, 0x00);// + write_cmos_sensor(0x3612, 0x27);// + write_cmos_sensor(0x3501, 0xc0);// + write_cmos_sensor(0x3702, 0x40);// ;add for VGA differences + write_cmos_sensor(0x370a, 0x24);// + //write_cmos_sensor(0x3718, 0x10);// + write_cmos_sensor(0x372a, 0x04);// + write_cmos_sensor(0x372f, 0xa0);// + write_cmos_sensor(0x3800, 0x0); + write_cmos_sensor(0x3801, 0x0C);// + write_cmos_sensor(0x3802, 0x00);// ;add for VGA differences + write_cmos_sensor(0x3803, 0x04);// + write_cmos_sensor(0x3804, 0x10); + write_cmos_sensor(0x3805, 0x93);// + write_cmos_sensor(0x3806, 0x0c);// ;add for VGA differences + write_cmos_sensor(0x3807, 0x4B);// + write_cmos_sensor(0x3808, 0x10);// + write_cmos_sensor(0x3809, 0x80);// + write_cmos_sensor(0x380a, 0x0c);// + write_cmos_sensor(0x380b, 0x40);// + write_cmos_sensor(0x380c, ((imgsensor_info.cap1.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.cap1.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.cap1.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.cap1.framelength & 0xFF)); // vts + write_cmos_sensor(0x3811, 0x04);// ;add for VGA differences + write_cmos_sensor(0x3813, 0x04);// + write_cmos_sensor(0x3814, 0x11);// + write_cmos_sensor(0x3815, 0x11);// + write_cmos_sensor(0x3820, 0x00);// + write_cmos_sensor(0x3821, 0x04);// + write_cmos_sensor(0x3834, 0x00);// ;add for VGA differences + write_cmos_sensor(0x3836, 0x04);// + write_cmos_sensor(0x3837, 0x01);// + write_cmos_sensor(0x4020, 0x02);// + write_cmos_sensor(0x4021, 0x4C);// + write_cmos_sensor(0x4022, 0x0E);// + write_cmos_sensor(0x4023, 0x37);// + write_cmos_sensor(0x4024, 0x0F);// + write_cmos_sensor(0x4025, 0x1C);// + write_cmos_sensor(0x4026, 0x0F);// + write_cmos_sensor(0x4027, 0x1F);// + write_cmos_sensor(0x402a, 0x04);//;add for VGA differences + write_cmos_sensor(0x402b, 0x08);//;add for VGA differences + write_cmos_sensor(0x402c, 0x02);//;add for VGA differences + write_cmos_sensor(0x402e, 0x0c);//;add for VGA differences + write_cmos_sensor(0x402f, 0x08);//;add for VGA differences + write_cmos_sensor(0x4501, 0x38);// + write_cmos_sensor(0x4601, 0x04);// + write_cmos_sensor(0x4603, 0x00);// + write_cmos_sensor(0x4837, 0x19);// + write_cmos_sensor(0x5401, 0x71);// + write_cmos_sensor(0x5405, 0x80);// + write_cmos_sensor(0x0100, 0x01);// + + + } else { //30fps //30fps for Normal capture & ZSD + + write_cmos_sensor(0x0300, 0x00);// + write_cmos_sensor(0x0302, 0x32);// + write_cmos_sensor(0x0303, 0x00);// + write_cmos_sensor(0x3612, 0x07);// + write_cmos_sensor(0x3501, 0xc0);// + write_cmos_sensor(0x3702, 0x40);// ;add for VGA differences + write_cmos_sensor(0x370a, 0x24);// + //write_cmos_sensor(0x3718, 0x10);// + write_cmos_sensor(0x372a, 0x04);// + write_cmos_sensor(0x372f, 0xa0);// + write_cmos_sensor(0x3800, 0x0); + write_cmos_sensor(0x3801, 0x0C);// + write_cmos_sensor(0x3802, 0x00);// ;add for VGA differences + write_cmos_sensor(0x3803, 0x04);// + write_cmos_sensor(0x3804, 0x10); + write_cmos_sensor(0x3805, 0x93);// + write_cmos_sensor(0x3806, 0x0c);// ;add for VGA differences + write_cmos_sensor(0x3807, 0x4B);// + write_cmos_sensor(0x3808, 0x10);// + write_cmos_sensor(0x3809, 0x80);// + write_cmos_sensor(0x380a, 0x0c);// + write_cmos_sensor(0x380b, 0x40);// + write_cmos_sensor(0x380c, ((imgsensor_info.cap.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.cap.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.cap.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.cap.framelength & 0xFF)); // vts + write_cmos_sensor(0x3811, 0x04);// ;add for VGA differences + write_cmos_sensor(0x3813, 0x04);// + write_cmos_sensor(0x3814, 0x11);// + write_cmos_sensor(0x3815, 0x11);// + write_cmos_sensor(0x3820, 0x00);// + write_cmos_sensor(0x3821, 0x04);// + write_cmos_sensor(0x3834, 0x00);// ;add for VGA differences + write_cmos_sensor(0x3836, 0x04);// + write_cmos_sensor(0x3837, 0x01);// + write_cmos_sensor(0x4020, 0x02);// + write_cmos_sensor(0x4021, 0x4C);// + write_cmos_sensor(0x4022, 0x0E);// + write_cmos_sensor(0x4023, 0x37);// + write_cmos_sensor(0x4024, 0x0F);// + write_cmos_sensor(0x4025, 0x1C);// + write_cmos_sensor(0x4026, 0x0F);// + write_cmos_sensor(0x4027, 0x1F);// + write_cmos_sensor(0x402a, 0x04);//;add for VGA differences + write_cmos_sensor(0x402b, 0x08);//;add for VGA differences + write_cmos_sensor(0x402c, 0x02);//;add for VGA differences + write_cmos_sensor(0x402e, 0x0c);//;add for VGA differences + write_cmos_sensor(0x402f, 0x08);//;add for VGA differences + write_cmos_sensor(0x4501, 0x38);// + write_cmos_sensor(0x4601, 0x04);// + write_cmos_sensor(0x4603, 0x00);// + write_cmos_sensor(0x4837, 0x0d);// + write_cmos_sensor(0x5401, 0x71);// + write_cmos_sensor(0x5405, 0x80);// + write_cmos_sensor(0x0100, 0x01);// + + + + if (imgsensor.ihdr_en) { + + } else { + + } + + } + mdelay(20); + capture_first_flag = 1; +} + +} + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + write_cmos_sensor(0x0100, 0x00);// + write_cmos_sensor(0x0300, 0x00); + write_cmos_sensor(0x0302, 0x32); + write_cmos_sensor(0x0303, 0x00); + write_cmos_sensor(0x3612, 0x07); + write_cmos_sensor(0x3501, 0xc0); + write_cmos_sensor(0x3702, 0x40); + write_cmos_sensor(0x370a, 0x24); + write_cmos_sensor(0x372a, 0x04); + write_cmos_sensor(0x372f, 0xa0); + write_cmos_sensor(0x3800, 0x0); + write_cmos_sensor(0x3801, 0x14); + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x0c); + write_cmos_sensor(0x3804, 0x10); + write_cmos_sensor(0x3805, 0x8b); + write_cmos_sensor(0x3806, 0x0c); + write_cmos_sensor(0x3807, 0x43); + write_cmos_sensor(0x3808, 0x10); + write_cmos_sensor(0x3809, 0x70); + write_cmos_sensor(0x380a, 0x0c); + write_cmos_sensor(0x380b, 0x30); + write_cmos_sensor(0x380c, ((imgsensor_info.normal_video.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.normal_video.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.normal_video.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.normal_video.framelength & 0xFF)); // vts + write_cmos_sensor(0x3811, 0x04); + write_cmos_sensor(0x3813, 0x04); + write_cmos_sensor(0x3814, 0x11); + write_cmos_sensor(0x3815, 0x11); + write_cmos_sensor(0x3820, 0x00); + write_cmos_sensor(0x3821, 0x04); + write_cmos_sensor(0x3834, 0x00); + write_cmos_sensor(0x3836, 0x04); + write_cmos_sensor(0x3837, 0x01); + write_cmos_sensor(0x4020, 0x02); + write_cmos_sensor(0x4021, 0x3C); + write_cmos_sensor(0x4022, 0x0E); + write_cmos_sensor(0x4023, 0x37); + write_cmos_sensor(0x4024, 0x0F); + write_cmos_sensor(0x4025, 0x1C); + write_cmos_sensor(0x4026, 0x0F); + write_cmos_sensor(0x4027, 0x1F); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x08); + write_cmos_sensor(0x402c, 0x02); + write_cmos_sensor(0x402e, 0x0c); + write_cmos_sensor(0x402f, 0x08); + write_cmos_sensor(0x4501, 0x38); + write_cmos_sensor(0x4601, 0x04); + write_cmos_sensor(0x4603, 0x00); + write_cmos_sensor(0x4837, 0x0d); + write_cmos_sensor(0x5401, 0x71); + write_cmos_sensor(0x5405, 0x80); + write_cmos_sensor(0x0100, 0x01);// + + mdelay(20); + if (imgsensor.ihdr_en) { + } else { + } + +} +static void hs_video_setting(void) +{ + LOG_INF("E\n"); + + write_cmos_sensor(0x0100, 0x00);// + write_cmos_sensor(0x0300, 0x01); + write_cmos_sensor(0x0302, 0x28); + write_cmos_sensor(0x0303, 0x00); + write_cmos_sensor(0x3612, 0x27); + write_cmos_sensor(0x3501, 0x20); + write_cmos_sensor(0x3702, 0x5a); + write_cmos_sensor(0x370a, 0xa9); + write_cmos_sensor(0x372a, 0x00); + write_cmos_sensor(0x372f, 0x88); + write_cmos_sensor(0x3800, 0x0); + write_cmos_sensor(0x3801, 0x00); + write_cmos_sensor(0x3802, 0x01); + write_cmos_sensor(0x3803, 0x78); + write_cmos_sensor(0x3804, 0x10); + write_cmos_sensor(0x3805, 0x9f); + write_cmos_sensor(0x3806, 0x0a); + write_cmos_sensor(0x3807, 0xcf); + write_cmos_sensor(0x3808, 0x04); + write_cmos_sensor(0x3809, 0x20); + write_cmos_sensor(0x380a, 0x02); + write_cmos_sensor(0x380b, 0x52); + write_cmos_sensor(0x380c, ((imgsensor_info.hs_video.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.hs_video.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.hs_video.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.hs_video.framelength & 0xFF)); // vts + write_cmos_sensor(0x3811, 0x08); + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x31); + write_cmos_sensor(0x3815, 0x35); + write_cmos_sensor(0x3820, 0x02); + write_cmos_sensor(0x3821, 0x06); + write_cmos_sensor(0x3834, 0x02); + write_cmos_sensor(0x3836, 0x08); + write_cmos_sensor(0x3837, 0x04); + write_cmos_sensor(0x4020, 0x00); + write_cmos_sensor(0x4021, 0xe4); + write_cmos_sensor(0x4022, 0x03); + write_cmos_sensor(0x4023, 0x3f); + write_cmos_sensor(0x4024, 0x04); + write_cmos_sensor(0x4025, 0x20); + write_cmos_sensor(0x4026, 0x04); + write_cmos_sensor(0x4027, 0x25); + write_cmos_sensor(0x402a, 0x02); + write_cmos_sensor(0x402b, 0x04); + write_cmos_sensor(0x402c, 0x06); + write_cmos_sensor(0x402e, 0x08); + write_cmos_sensor(0x402f, 0x04); + write_cmos_sensor(0x4501, 0x3c); + write_cmos_sensor(0x4601, 0x40); + write_cmos_sensor(0x4603, 0x01); + write_cmos_sensor(0x4837, 0x19); + write_cmos_sensor(0x5401, 0x51); + write_cmos_sensor(0x5405, 0x20); + + + if (imgsensor.ihdr_en) { + } else { + } + write_cmos_sensor(0x0100, 0x01);// + mdelay(10); +} + +static void slim_video_setting(void) +{ + + #if 0 //preview + LOG_INF("E\n"); + write_cmos_sensor(0x0100, 0x00);// + write_cmos_sensor(0x0300, 0x01); + write_cmos_sensor(0x0302, 0x28); + write_cmos_sensor(0x0303, 0x00); + write_cmos_sensor(0x3612, 0x27); + write_cmos_sensor(0x3501, 0x60); + write_cmos_sensor(0x3702, 0x40); + write_cmos_sensor(0x370a, 0x27); + write_cmos_sensor(0x372a, 0x00); + write_cmos_sensor(0x372f, 0x90); + write_cmos_sensor(0x3800, 0x00); + write_cmos_sensor(0x3801, 0x08); + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x04); + write_cmos_sensor(0x3804, 0x10); + write_cmos_sensor(0x3805, 0x97); + write_cmos_sensor(0x3806, 0x0c); + write_cmos_sensor(0x3807, 0x4b); + write_cmos_sensor(0x3808, 0x08); + write_cmos_sensor(0x3809, 0x40); + write_cmos_sensor(0x380a, 0x06); + write_cmos_sensor(0x380b, 0x20); + write_cmos_sensor(0x380c, ((imgsensor_info.slim_video.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.slim_video.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.slim_video.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.slim_video.framelength & 0xFF)); // vts + write_cmos_sensor(0x3811, 0x04);// + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x31); + write_cmos_sensor(0x3815, 0x31); + write_cmos_sensor(0x3820, 0x02); + write_cmos_sensor(0x3821, 0x06); + write_cmos_sensor(0x3834, 0x00); + write_cmos_sensor(0x3836, 0x08); + write_cmos_sensor(0x3837, 0x02); + write_cmos_sensor(0x4020, 0x00); + write_cmos_sensor(0x4021, 0xe4); + write_cmos_sensor(0x4022, 0x04); + write_cmos_sensor(0x4023, 0xd7); + write_cmos_sensor(0x4024, 0x05); + write_cmos_sensor(0x4025, 0xbc); + write_cmos_sensor(0x4026, 0x05); + write_cmos_sensor(0x4027, 0xbf); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x08); + write_cmos_sensor(0x402c, 0x02); + write_cmos_sensor(0x402e, 0x0c); + write_cmos_sensor(0x402f, 0x08); + write_cmos_sensor(0x4501, 0x3c); + write_cmos_sensor(0x4601, 0x83); + write_cmos_sensor(0x4603, 0x01); + write_cmos_sensor(0x4837, 0x19); + write_cmos_sensor(0x5401, 0x61); + write_cmos_sensor(0x5405, 0x40); +#else +//720P + write_cmos_sensor(0x0100, 0x00);// + write_cmos_sensor(0x0300, 0x01); + write_cmos_sensor(0x0301, 0x00); + write_cmos_sensor(0x0302, 0x28); + write_cmos_sensor(0x0303, 0x00); + write_cmos_sensor(0x3612, 0x27); + write_cmos_sensor(0x3612, 0x27); + write_cmos_sensor(0x3614, 0x28); + write_cmos_sensor(0x370a, 0x27); + write_cmos_sensor(0x372a, 0x00); + write_cmos_sensor(0x372f, 0x90); + write_cmos_sensor(0x3718, 0x10); + write_cmos_sensor(0x3767, 0x24); + write_cmos_sensor(0x3800, 0x03); + write_cmos_sensor(0x3801, 0x38); + write_cmos_sensor(0x3802, 0x03); + write_cmos_sensor(0x3803, 0x4a); + write_cmos_sensor(0x3804, 0x0d); + write_cmos_sensor(0x3805, 0x67); + write_cmos_sensor(0x3806, 0x09); + write_cmos_sensor(0x3807, 0x05); + write_cmos_sensor(0x3808, 0x05); + write_cmos_sensor(0x3809, 0x10);// + write_cmos_sensor(0x380A, 0x02);// + write_cmos_sensor(0x380B, 0xda);// + write_cmos_sensor(0x380C, ((imgsensor_info.slim_video.linelength >> 8) & 0xFF)); // hts = 9600 + write_cmos_sensor(0x380D, (imgsensor_info.slim_video.linelength & 0xFF)); // hts + write_cmos_sensor(0x380E, ((imgsensor_info.slim_video.framelength >> 8) & 0xFF)); // vts = 834 + write_cmos_sensor(0x380F, (imgsensor_info.slim_video.framelength & 0xFF)); // vts + write_cmos_sensor(0x3811, 0x04); + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x31); + write_cmos_sensor(0x3815, 0x31); + write_cmos_sensor(0x3820, 0x02); + write_cmos_sensor(0x3821, 0x05); + write_cmos_sensor(0x3836, 0x08); + write_cmos_sensor(0x3837, 0x02); + write_cmos_sensor(0x4001, 0x00); + write_cmos_sensor(0x4020, 0x1 ); + write_cmos_sensor(0x4021, 0xD4); + write_cmos_sensor(0x4022, 0x3 ); + write_cmos_sensor(0x4023, 0x43); + write_cmos_sensor(0x4024, 0x05); + write_cmos_sensor(0x4025, 0x14); + write_cmos_sensor(0x4026, 0x05); + write_cmos_sensor(0x4027, 0x17); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x08); + write_cmos_sensor(0x402c, 0x02); + write_cmos_sensor(0x402e, 0x0c); + write_cmos_sensor(0x402f, 0x08); + write_cmos_sensor(0x4501, 0x3c); + write_cmos_sensor(0x4600, 0x00); + write_cmos_sensor(0x4601, 0x50); + write_cmos_sensor(0x4837, 0x19); + write_cmos_sensor(0x5401, 0x61); + write_cmos_sensor(0x5405, 0x40); + write_cmos_sensor(0x350b, 0x40); + write_cmos_sensor(0x3500, 0x00); + write_cmos_sensor(0x3501, 0x33); + write_cmos_sensor(0x3502, 0x90); +#endif + if (imgsensor.ihdr_en) { + } else { + } + write_cmos_sensor(0x0100, 0x01);// + mdelay(10); + +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x5E00, 0x80); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x5E00, 0x00); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + LOG_2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + if ((read_cmos_sensor(0x302a))==0xb1) + { + LOG_INF("----R1A---- \n"); + ov13850_chip_ver = OV13850_R1A; + }else if((read_cmos_sensor(0x302a))==0xb2) + { + LOG_INF("----R2A---- \n"); + ov13850_chip_ver = OV13850_R2A; + } + /* initail sequence write in */ + sensor_init(); + //for OTP + //otp_cali(imgsensor.i2c_write_id); + write_cmos_sensor(0x0100, 0x00); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + //for zsd multi capture setting + capture_first_flag = 0; + pre_currefps = 0; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + set_mirror_flip(imgsensor.mirror); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + capture_first_flag = 0; + pre_currefps = 0; + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + capture_first_flag = 0; + pre_currefps = 0; + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + capture_first_flag = 0; + pre_currefps = 0; + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + capture_first_flag = 0; + pre_currefps = 0; + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + capture_first_flag = 0; + pre_currefps = 0; + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{//This Function not used after ROME + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + //set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + + + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + //unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + //LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + LOG_INF("feature_Control imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", *feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", *feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 OV13850_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV13850_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850mipiraw_Sensor.h new file mode 100755 index 0000000000000000000000000000000000000000..5c70215b9f660075f47e96427dc098118cc32290 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov13850_mipi_raw/ov13850mipiraw_Sensor.h @@ -0,0 +1,123 @@ +/***************************************************************************** + * + * Filename: + * --------- + * OV13850mipiraw_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _OV13850MIPIRAW_SENSOR_H +#define _OV13850MIPIRAW_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint32 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + +typedef enum{ + OV13850_R1A = 0, + OV13850_R2A, + OV13850_MAX, +}OV13850_CHIP_VER_ENUM; + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3511876ca6ae9b3514246e0b914eae2b42dca59c --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + + +obj-y += ov5648mipi_Sensor.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/ov5648mipi_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/ov5648mipi_Sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..04dc7395ccf68af167f7d13bdbbf99a79830a91b --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/ov5648mipi_Sensor.c @@ -0,0 +1,1831 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * OV5648mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "ov5648mipi_Sensor.h" + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "OV5648_camera_sensor" +#define LOG_1 LOG_INF("OV5648,MIPI 2LANE\n") +#define LOG_2 LOG_INF("preview 1280*960@30fps,420Mbps/lane; video 1280*960@30fps,420Mbps/lane; capture 5M@15fps,420Mbps/lane\n") +/**************************** Modify end *******************************************/ + +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = OV5648MIPI_SENSOR_ID, + + .checksum_value = 0xf7375923, //checksum value for Camera Auto Test + + .pre = { + .pclk = 84000000, //record different mode's pclk + .linelength = 2816, //record different mode's linelength + .framelength = 992, //record different mode's framelength + .startx = 2, //record different mode's startx of grabwindow + .starty = 2, //record different mode's starty of grabwindow + .grabwindow_width = 1280, //record different mode's width of grabwindow + .grabwindow_height = 960, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk = 84000000, + .linelength = 2816, + .framelength = 1984, + .startx = 2, + .starty = 6, + .grabwindow_width = 2560, + .grabwindow_height = 1920, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 150, + }, + .cap1 = { + .pclk = 84000000, + .linelength = 2816, + .framelength = 1984, + .startx = 2, + .starty = 2, + .grabwindow_width = 2560, + .grabwindow_height = 1920, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 150, + }, + .normal_video = { + .pclk = 84000000, + .linelength = 2816, + .framelength = 992, + .startx = 2, + .starty = 2, + .grabwindow_width = 1280, + .grabwindow_height = 960, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .hs_video = { + .pclk = 84000000, + .linelength = 2500, + .framelength = 1120, + .startx = 0, + .starty = 0, + .grabwindow_width = 1920, + .grabwindow_height = 1080, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .slim_video = { + .pclk = 84000000, + .linelength = 3728, + .framelength = 748, + .startx = 0, + .starty = 0, + .grabwindow_width = 1280, + .grabwindow_height = 720, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .margin = 4, //sensor framelength & shutter margin + .min_shutter = 1, //min shutter + .max_frame_length = 0x7fff,//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num + + .cap_delay_frame = 2, + .pre_delay_frame = 2, + .video_delay_frame = 2, + .hs_video_delay_frame = 2, + .slim_video_delay_frame = 2, + + .isp_driving_current = ISP_DRIVING_2MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_2_LANE,//mipi lane num + .i2c_addr_table = {0x6c, 0xff}, + .i2c_speed = 200, +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter + .gain = 0x100, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 300, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x6c,//record current sensor's i2c write id +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5]= +{{ 2624, 1956, 0, 0, 2624, 1956, 1312, 978, 8, 4, 1296, 972, 4, 8, 1280, 960}, // Preview + { 2624, 1956, 0, 0, 2624, 1956, 2624, 1956, 16, 6, 2592, 1944, 2, 2, 2560, 1920}, // capture + { 2624, 1956, 0, 0, 2624, 1956, 2592, 1944, 0, 0, 1296, 972, 4, 8, 1280, 960}, // video + { 2624, 1956, 336, 434, 1952, 1088, 1952, 1088, 16, 4, 1920, 1080, 0, 0, 1920, 1080}, //hight speed video + { 2624, 1956, 16, 254, 2592, 1448, 1296, 724, 8, 2, 1280, 720, 0, 0, 1280, 720}}; // slim video + + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; +} + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + /* you can set dummy by imgsensor.dummy_line and imgsensor.dummy_pixel, or you can set dummy by imgsensor.frame_length and imgsensor.line_length */ + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x380c, imgsensor.line_length >> 8); + write_cmos_sensor(0x380d, imgsensor.line_length & 0xFF); + +} /* set_dummy */ + +static kal_uint32 return_sensor_id(void) +{ + return ((read_cmos_sensor(0x300A) << 8) | read_cmos_sensor(0x300B)); +} +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + kal_uint32 frame_length = imgsensor.frame_length; + + LOG_INF("framerate = %d, min framelength should enable = %d\n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + + set_dummy(); +} /* set_max_framerate */ + +static void write_shutter(kal_uint16 shutter) +{ + kal_uint16 realtime_fps = 0; + + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + // Framelength should be an even number + shutter = (shutter >> 1) << 1; + imgsensor.frame_length = (imgsensor.frame_length >> 1) << 1; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + } else { + // Extend frame length + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + + // Update Shutter + write_cmos_sensor(0x3502, (shutter << 4) & 0xFF); + write_cmos_sensor(0x3501, (shutter >> 4) & 0xFF); + write_cmos_sensor(0x3500, (shutter >> 12) & 0x0F); + + LOG_INF("shutter =%d, framelength =%d\n", shutter, imgsensor.frame_length); +} + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + write_shutter(shutter); +} + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0000; + + reg_gain = ((gain / BASEGAIN) << 4) + ((gain % BASEGAIN) * 16 / BASEGAIN); + reg_gain = reg_gain & 0xFFFF; + + return (kal_uint16)reg_gain; +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + /* 0x350A[0:1], 0x350B[0:7] AGC real gain */ + /* [0:3] = N meams N /16 X */ + /* [4:9] = M meams M X */ + /* Total gain = M + N /16 X */ + + // + if (gain < BASEGAIN || gain > 32 * BASEGAIN) { + LOG_INF("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 32 * BASEGAIN) + gain = 32 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor(0x350a, reg_gain >> 8); + write_cmos_sensor(0x350b, reg_gain & 0xFF); + + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + //not support HDR + //LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); +} + +#if 0 +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xF9) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x06)); + break; + case IMAGE_H_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xF9) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x00)); + break; + case IMAGE_V_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xF9) | 0x06)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x06)); + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xF9) | 0x06)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x00)); + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} +#endif + +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + +static void sensor_init(void) +{ + LOG_INF("E\n"); + /***************************************************************************** + 0x3037 SC_CMMN_PLL_CTR13 + SC_CMMN_PLL_CTR13[4] pll_root_div 0: bypass 1: /2 + SC_CMMN_PLL_CTR13[3:0] pll_prediv 1, 2, 3, 4, 6, 8 + + 0x3036 SC_CMMN_PLL_MULTIPLIER + SC_CMMN_PLL_MULTIPLIER[7:0] PLL_multiplier(4~252) This can be any integer during 4~127 and only even integer during 128 ~ 252 + + 0x3035 SC_CMMN_PLL_CTR1 + SC_CMMN_PLL_CTR1[7:4] system_pll_div + SC_CMMN_PLL_CTR1[3:0] scale_divider_mipi + + 0x3034 SC_CMMN_PLL_CTR0 + SC_CMMN_PLL_CTR0[6:4] pll_charge_pump + SC_CMMN_PLL_CTR0[3:0] mipi_bit_mode + + 0x3106 SRB CTRL + SRB CTRL[3:2] PLL_clock_divider + SRB CTRL[1] rst_arb + SRB CTRL[0] sclk_arb + + pll_prediv_map[] = {2, 2, 4, 6, 8, 3, 12, 5, 16, 2, 2, 2, 2, 2, 2, 2}; + system_pll_div_map[] = {16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + pll_root_div_map[] = {1, 2}; + mipi_bit_mode_map[] = {2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 5, 2, 2, 2, 2, 2}; + PLL_clock_divider_map[] = {1, 2, 4, 1}; + + VCO = XVCLK * 2 / pll_prediv_map[pll_prediv] * PLL_multiplier; + sysclk = VCO * 2 / system_pll_div_map[system_pll_div] / pll_root_div_map[pll_root_div] / mipi_bit_mode_map[mipi_bit_mode] / PLL_clock_divider_map[PLL_clock_divider] + + Change Register + + VCO = XVCLK * 2 / pll_prediv_map[0x3037[3:0]] * 0x3036[7:0]; + sysclk = VCO * 2 / system_pll_div_map[0x3035[7:4]] / pll_root_div_map[0x3037[4]] / mipi_bit_mode_map[0x3034[3:0]] / PLL_clock_divider_map[0x3106[3:2]] + + XVCLK = 24 MHZ + 0x3106 0x05 + 0x3037 0x03 + 0x3036 0x69 + 0x3035 0x21 + 0x3034 0x1A + + VCO = 24 * 2 / 6 * 105 + sysclk = VCO * 2 / 2 / 1 / 5 / 2 + sysclk = 84 MHZ + */ + + //@@ global setting + write_cmos_sensor(0x0100, 0x00); // Software Standy + write_cmos_sensor(0x0103, 0x01); // Software Reset + + mDELAY(5); + + write_cmos_sensor(0x3001, 0x00); // D[7:0] set to input + write_cmos_sensor(0x3002, 0x00); // D[11:8] set to input + write_cmos_sensor(0x3011, 0x02); // Drive strength 2x + + write_cmos_sensor(0x3018, 0x4c); // MIPI 2 lane + write_cmos_sensor(0x3022, 0x00); + + write_cmos_sensor(0x3034, 0x1a); // 10-bit mode + write_cmos_sensor(0x3035, 0x21); // PLL + write_cmos_sensor(0x3036, 0x69); // PLL + + write_cmos_sensor(0x3037, 0x03); // PLL + + write_cmos_sensor(0x3038, 0x00); // PLL + write_cmos_sensor(0x3039, 0x00); // PLL + write_cmos_sensor(0x303a, 0x00); // PLLS + write_cmos_sensor(0x303b, 0x19); // PLLS + write_cmos_sensor(0x303c, 0x11); // PLLS + write_cmos_sensor(0x303d, 0x30); // PLLS + write_cmos_sensor(0x3105, 0x11); + write_cmos_sensor(0x3106, 0x05); // PLL + write_cmos_sensor(0x3304, 0x28); + write_cmos_sensor(0x3305, 0x41); + write_cmos_sensor(0x3306, 0x30); + write_cmos_sensor(0x3308, 0x00); + write_cmos_sensor(0x3309, 0xc8); + write_cmos_sensor(0x330a, 0x01); + write_cmos_sensor(0x330b, 0x90); + write_cmos_sensor(0x330c, 0x02); + write_cmos_sensor(0x330d, 0x58); + write_cmos_sensor(0x330e, 0x03); + write_cmos_sensor(0x330f, 0x20); + write_cmos_sensor(0x3300, 0x00); + + // exposure time + //write_cmos_sensor(0x3500, 0x00); // exposure [19:16] + //write_cmos_sensor(0x3501, 0x3d); // exposure [15:8] + //write_cmos_sensor(0x3502, 0x00); // exposure [7:0], exposure = 0x3d0 = 976 + + write_cmos_sensor(0x3503, 0x07); // gain has no delay, manual agc/aec + + // gain + write_cmos_sensor(0x350a, 0x00); // gain[9:8] + write_cmos_sensor(0x350b, 0x40); // gain[7:0], gain = 4x + + write_cmos_sensor(0x3601, 0x33); // analog control + write_cmos_sensor(0x3602, 0x00); // analog control + write_cmos_sensor(0x3611, 0x0e); // analog control + write_cmos_sensor(0x3612, 0x2b); // analog control + write_cmos_sensor(0x3614, 0x50); // analog control + write_cmos_sensor(0x3620, 0x33); // analog control + write_cmos_sensor(0x3622, 0x00); // analog control + write_cmos_sensor(0x3630, 0xad); // analog control + write_cmos_sensor(0x3631, 0x00); // analog control + write_cmos_sensor(0x3632, 0x94); // analog control + write_cmos_sensor(0x3633, 0x17); // analog control + write_cmos_sensor(0x3634, 0x14); // analog control + + // fix EV3 issue + write_cmos_sensor(0x3704, 0xc0); // analog control + + write_cmos_sensor(0x3705, 0x2a); // analog control + write_cmos_sensor(0x3708, 0x66); // analog control + write_cmos_sensor(0x3709, 0x52); // analog control + write_cmos_sensor(0x370b, 0x23); // analog control + write_cmos_sensor(0x370c, 0xc3); // analog control + write_cmos_sensor(0x370d, 0x00); // analog control + write_cmos_sensor(0x370e, 0x00); // analog control + write_cmos_sensor(0x371c, 0x07); // analog control + write_cmos_sensor(0x3739, 0xd2); // analog control + write_cmos_sensor(0x373c, 0x00); + + write_cmos_sensor(0x3800, 0x00); // xstart = 0 + write_cmos_sensor(0x3801, 0x00); // xstart + write_cmos_sensor(0x3802, 0x00); // ystart = 0 + write_cmos_sensor(0x3803, 0x00); // ystart + write_cmos_sensor(0x3804, 0x0a); // xend = 2623 + write_cmos_sensor(0x3805, 0x3f); // yend + write_cmos_sensor(0x3806, 0x07); // yend = 1955 + write_cmos_sensor(0x3807, 0xa3); // yend + write_cmos_sensor(0x3808, 0x05); // x output size = 1296 + write_cmos_sensor(0x3809, 0x10); // x output size + write_cmos_sensor(0x380a, 0x03); // y output size = 972 + write_cmos_sensor(0x380b, 0xcc); // y output size + write_cmos_sensor(0x380c, 0x0b); // hts = 2816 + write_cmos_sensor(0x380d, 0x00); // hts + write_cmos_sensor(0x380e, 0x03); // vts = 992 + write_cmos_sensor(0x380f, 0xe0); // vts + + write_cmos_sensor(0x3810, 0x00); // isp x win = 8 + write_cmos_sensor(0x3811, 0x08); // isp x win + write_cmos_sensor(0x3812, 0x00); // isp y win = 4 + write_cmos_sensor(0x3813, 0x04); // isp y win + write_cmos_sensor(0x3814, 0x31); // x inc + write_cmos_sensor(0x3815, 0x31); // y inc + write_cmos_sensor(0x3817, 0x00); // hsync start + + // Horizontal binning + write_cmos_sensor(0x3820, 0x08); // flip off, v bin off + write_cmos_sensor(0x3821, 0x07); // mirror on, h bin on + + write_cmos_sensor(0x3826, 0x03); + write_cmos_sensor(0x3829, 0x00); + write_cmos_sensor(0x382b, 0x0b); + write_cmos_sensor(0x3830, 0x00); + write_cmos_sensor(0x3836, 0x00); + write_cmos_sensor(0x3837, 0x00); + write_cmos_sensor(0x3838, 0x00); + write_cmos_sensor(0x3839, 0x04); + write_cmos_sensor(0x383a, 0x00); + write_cmos_sensor(0x383b, 0x01); + + write_cmos_sensor(0x3b00, 0x00); // strobe off + write_cmos_sensor(0x3b02, 0x08); // shutter delay + write_cmos_sensor(0x3b03, 0x00); // shutter delay + write_cmos_sensor(0x3b04, 0x04); // frex_exp + write_cmos_sensor(0x3b05, 0x00); // frex_exp + write_cmos_sensor(0x3b06, 0x04); + write_cmos_sensor(0x3b07, 0x08); // frex inv + write_cmos_sensor(0x3b08, 0x00); // frex exp req + write_cmos_sensor(0x3b09, 0x02); // frex end option + write_cmos_sensor(0x3b0a, 0x04); // frex rst length + write_cmos_sensor(0x3b0b, 0x00); // frex strobe width + write_cmos_sensor(0x3b0c, 0x3d); // frex strobe width + write_cmos_sensor(0x3f01, 0x0d); + write_cmos_sensor(0x3f0f, 0xf5); + + write_cmos_sensor(0x4000, 0x89); // blc enable + write_cmos_sensor(0x4001, 0x02); // blc start line + write_cmos_sensor(0x4002, 0x45); // blc auto, reset frame number = 5 + write_cmos_sensor(0x4004, 0x02); // black line number + write_cmos_sensor(0x4005, 0x18); // blc normal freeze + write_cmos_sensor(0x4006, 0x08); + write_cmos_sensor(0x4007, 0x10); + write_cmos_sensor(0x4008, 0x00); + write_cmos_sensor(0x4300, 0xf8); + write_cmos_sensor(0x4303, 0xff); + write_cmos_sensor(0x4304, 0x00); + write_cmos_sensor(0x4307, 0xff); + write_cmos_sensor(0x4520, 0x00); + write_cmos_sensor(0x4521, 0x00); + write_cmos_sensor(0x4511, 0x22); + + //update DPC settings + write_cmos_sensor(0x5780, 0xfc); + write_cmos_sensor(0x5781, 0x1f); + write_cmos_sensor(0x5782, 0x03); + write_cmos_sensor(0x5786, 0x20); + write_cmos_sensor(0x5787, 0x40); + write_cmos_sensor(0x5788, 0x08); + write_cmos_sensor(0x5789, 0x08); + write_cmos_sensor(0x578a, 0x02); + write_cmos_sensor(0x578b, 0x01); + write_cmos_sensor(0x578c, 0x01); + write_cmos_sensor(0x578d, 0x0c); + write_cmos_sensor(0x578e, 0x02); + write_cmos_sensor(0x578f, 0x01); + write_cmos_sensor(0x5790, 0x01); + + write_cmos_sensor(0x4800, 0x24); // MIPI line sync enable + + write_cmos_sensor(0x481f, 0x3c); // MIPI clk prepare min + write_cmos_sensor(0x4826, 0x00); // MIPI hs prepare min + write_cmos_sensor(0x4837, 0x18); // MIPI global timing + write_cmos_sensor(0x4b00, 0x06); + write_cmos_sensor(0x4b01, 0x0a); + write_cmos_sensor(0x5000, 0xff); // bpc on, wpc on + write_cmos_sensor(0x5001, 0x00); // awb disable + write_cmos_sensor(0x5002, 0x41); // win enable, awb gain enable + write_cmos_sensor(0x5003, 0x0a); // buf en, bin auto en + write_cmos_sensor(0x5004, 0x00); // size man off + write_cmos_sensor(0x5043, 0x00); + write_cmos_sensor(0x5013, 0x00); + write_cmos_sensor(0x501f, 0x03); // ISP output data + write_cmos_sensor(0x503d, 0x00); // test pattern off + write_cmos_sensor(0x5180, 0x08); // manual wb gain on + write_cmos_sensor(0x5a00, 0x08); + write_cmos_sensor(0x5b00, 0x01); + write_cmos_sensor(0x5b01, 0x40); + write_cmos_sensor(0x5b02, 0x00); + write_cmos_sensor(0x5b03, 0xf0); + + //write_cmos_sensor(0x350b, 0x80); // gain = 8x + write_cmos_sensor(0x4837, 0x17); // MIPI global timing + + write_cmos_sensor(0x0100, 0x01); // wake up from software sleep +} /* MIPI_sensor_Init */ + + +static void preview_setting(void) +{ + /******************************************************** + * + * 1296x972 30fps 2 lane MIPI 420Mbps/lane + * + ********************************************************/ + + write_cmos_sensor(0x0100, 0x00); //Stream Off + mDELAY(10); + + write_cmos_sensor(0x3500, 0x00); // exposure [19:16] + write_cmos_sensor(0x3501, 0x3d); // exposure + write_cmos_sensor(0x3502, 0x00); // exposure + + write_cmos_sensor(0x3708, 0x66); + + write_cmos_sensor(0x3709, 0x52); + write_cmos_sensor(0x370c, 0xc3); + write_cmos_sensor(0x3800, 0x00); // x start = 0 + write_cmos_sensor(0x3801, 0x00); // x start + write_cmos_sensor(0x3802, 0x00); // y start = 0 + write_cmos_sensor(0x3803, 0x00); // y start + write_cmos_sensor(0x3804, 0x0a); // xend = 2623 + write_cmos_sensor(0x3805, 0x3f); // xend + write_cmos_sensor(0x3806, 0x07); // yend = 1955 + write_cmos_sensor(0x3807, 0xa3); // yend + write_cmos_sensor(0x3808, 0x05); // x output size = 1296 + write_cmos_sensor(0x3809, 0x10); // x output size + write_cmos_sensor(0x380a, 0x03); // y output size = 972 + write_cmos_sensor(0x380b, 0xcc); // y output size + + + //write_cmos_sensor(0x380c, 0x0b); // hts = 2816 + //write_cmos_sensor(0x380d, 0x00); // hts + //write_cmos_sensor(0x380e, 0x03); // vts = 992 + //write_cmos_sensor(0x380f, 0xE0); // vts + write_cmos_sensor(0x380c, ((imgsensor_info.pre.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.pre.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.pre.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.pre.framelength & 0xFF)); // vts + + write_cmos_sensor(0x3810, 0x00); // isp x win = 8 + write_cmos_sensor(0x3811, 0x08); // isp x win + write_cmos_sensor(0x3812, 0x00); // isp y win = 4 + write_cmos_sensor(0x3813, 0x04); // isp y win + write_cmos_sensor(0x3814, 0x31); // x inc + write_cmos_sensor(0x3815, 0x31); // y inc + write_cmos_sensor(0x3817, 0x00); // hsync start + + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + write_cmos_sensor(0x3820, 0x08); // flip off, v bin off + write_cmos_sensor(0x3821, 0x07); // mirror on, h bin on + + + write_cmos_sensor(0x4004, 0x02); // black line number + //write_cmos_sensor(0x4005, 0x1a); // blc normal freeze + write_cmos_sensor(0x4005, 0x18); // blc normal freeze + //write_cmos_sensor(0x4050, 0x37); // blc normal freeze + write_cmos_sensor(0x4050, 0x6e); // blc normal freeze + write_cmos_sensor(0x4051, 0x8f); // blc normal freeze + + //write_cmos_sensor(0x350b, 0x80); // gain = 8x + write_cmos_sensor(0x4837, 0x17); // MIPI global timing + + write_cmos_sensor(0x0100, 0x01); //Stream On +} /* preview_setting */ + + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n", currefps); + + /******************************************************** + * + * 2592x1944 15fps 2 lane MIPI 420Mbps/lane + * + ********************************************************/ + + write_cmos_sensor(0x0100, 0x00); //Stream Off + + write_cmos_sensor(0x3500, 0x00); // exposure [19:16] + write_cmos_sensor(0x3501, 0x7b); // exposure + write_cmos_sensor(0x3502, 0x00); // exposure + write_cmos_sensor(0x3708, 0x63); + + write_cmos_sensor(0x3709, 0x12); + write_cmos_sensor(0x370c, 0xc0); + write_cmos_sensor(0x3800, 0x00); // xstart = 0 + write_cmos_sensor(0x3801, 0x00); // xstart + write_cmos_sensor(0x3802, 0x00); // ystart = 0 + write_cmos_sensor(0x3803, 0x00); // ystart + write_cmos_sensor(0x3804, 0x0a); // xend = 2623 + write_cmos_sensor(0x3805, 0x3f); // xend + write_cmos_sensor(0x3806, 0x07); // yend = 1955 + write_cmos_sensor(0x3807, 0xa3); // yend + write_cmos_sensor(0x3808, 0x0a); // x output size = 2592 + write_cmos_sensor(0x3809, 0x20); // x output size + write_cmos_sensor(0x380a, 0x07); // y output size = 1944 + write_cmos_sensor(0x380b, 0x98); // y output size + + //write_cmos_sensor(0x380c, 0x0b); // hts = 2816 + //write_cmos_sensor(0x380d, 0x00); // hts + //write_cmos_sensor(0x380e, 0x07); // vts = 1984 + //write_cmos_sensor(0x380f, 0xc0); // vts + write_cmos_sensor(0x380c, ((imgsensor_info.cap.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.cap.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.cap.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.cap.framelength & 0xFF)); // vts + + + write_cmos_sensor(0x3810, 0x00); // isp x win = 16 + write_cmos_sensor(0x3811, 0x10); // isp x win + write_cmos_sensor(0x3812, 0x00); // isp y win = 6 + write_cmos_sensor(0x3813, 0x06); // isp y win + write_cmos_sensor(0x3814, 0x11); // x inc + write_cmos_sensor(0x3815, 0x11); // y inc + write_cmos_sensor(0x3817, 0x00); // hsync start + + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + write_cmos_sensor(0x3820, 0x40); // flip off, v bin off + write_cmos_sensor(0x3821, 0x06); // mirror on, v bin off + + + write_cmos_sensor(0x4004, 0x04); // black line number + //0x4005[1]: 0 normal freeze 1 blc always update + write_cmos_sensor(0x4005, 0x18); // blc normal freeze + + write_cmos_sensor(0x350b, 0x40); // gain = 4x + write_cmos_sensor(0x4837, 0x17); // MIPI global timing + + write_cmos_sensor(0x0100, 0x01); //Stream On +} /* capture_setting */ + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n", currefps); + + /******************************************************** + * + * 1296x972 30fps 2 lane MIPI 420Mbps/lane + * + ********************************************************/ + + write_cmos_sensor(0x0100, 0x00); //Stream Off + + write_cmos_sensor(0x3500, 0x00); // exposure [19:16] + write_cmos_sensor(0x3501, 0x3d); // exposure + write_cmos_sensor(0x3502, 0x00); // exposure + + write_cmos_sensor(0x3708, 0x66); + + write_cmos_sensor(0x3709, 0x52); + write_cmos_sensor(0x370c, 0xc3); + write_cmos_sensor(0x3800, 0x00); // x start = 0 + write_cmos_sensor(0x3801, 0x00); // x start + write_cmos_sensor(0x3802, 0x00); // y start = 0 + write_cmos_sensor(0x3803, 0x00); // y start + write_cmos_sensor(0x3804, 0x0a); // xend = 2623 + write_cmos_sensor(0x3805, 0x3f); // xend + write_cmos_sensor(0x3806, 0x07); // yend = 1955 + write_cmos_sensor(0x3807, 0xa3); // yend + write_cmos_sensor(0x3808, 0x05); // x output size = 1296 + write_cmos_sensor(0x3809, 0x10); // x output size + write_cmos_sensor(0x380a, 0x03); // y output size = 972 + write_cmos_sensor(0x380b, 0xcc); // y output size + + + //write_cmos_sensor(0x380c, 0x0b); // hts = 2816 + //write_cmos_sensor(0x380d, 0x00); // hts + //write_cmos_sensor(0x380e, 0x03); // vts = 992 + //write_cmos_sensor(0x380f, 0xE0); // vts + write_cmos_sensor(0x380c, ((imgsensor_info.normal_video.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.normal_video.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.normal_video.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.normal_video.framelength & 0xFF)); // vts + + write_cmos_sensor(0x3810, 0x00); // isp x win = 8 + write_cmos_sensor(0x3811, 0x08); // isp x win + write_cmos_sensor(0x3812, 0x00); // isp y win = 4 + write_cmos_sensor(0x3813, 0x04); // isp y win + write_cmos_sensor(0x3814, 0x31); // x inc + write_cmos_sensor(0x3815, 0x31); // y inc + write_cmos_sensor(0x3817, 0x00); // hsync start + + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + write_cmos_sensor(0x3820, 0x08); // flip off, v bin off + write_cmos_sensor(0x3821, 0x07); // mirror on, h bin on + + + write_cmos_sensor(0x4004, 0x02); // black line number + //write_cmos_sensor(0x4005, 0x1a); // blc normal freeze + write_cmos_sensor(0x4005, 0x18); // blc normal freeze + //write_cmos_sensor(0x4050, 0x37); // blc normal freeze + write_cmos_sensor(0x4050, 0x6e); // blc normal freeze + write_cmos_sensor(0x4051, 0x8f); // blc normal freeze + + //write_cmos_sensor(0x350b, 0x80); // gain = 8x + write_cmos_sensor(0x4837, 0x17); // MIPI global timing + + write_cmos_sensor(0x0100, 0x01); //Stream On +} /* preview_setting */ + + +static void video_1080p_setting(void) +{ + + /******************************************************** + * + * 1080p 30fps 2 lane MIPI 420Mbps/lane + * @@1080p + * ;;pclk=84M,HTS=2500,VTS=1120 + ********************************************************/ + + write_cmos_sensor(0x0100, 0x00); //Stream Off + + write_cmos_sensor(0x3500, 0x00); // exposure [19:16] + write_cmos_sensor(0x3501, 0x45); // exposure + write_cmos_sensor(0x3502, 0xc0); // exposure + + write_cmos_sensor(0x3708, 0x63); + + write_cmos_sensor(0x3709, 0x12); + write_cmos_sensor(0x370c, 0xcc); + write_cmos_sensor(0x3800, 0x01); // x start = 336 + write_cmos_sensor(0x3801, 0x50); // x start + write_cmos_sensor(0x3802, 0x01); // y start = 434 + write_cmos_sensor(0x3803, 0xb2); // y start + write_cmos_sensor(0x3804, 0x08); // xend = 2287 + write_cmos_sensor(0x3805, 0xef); // xend + write_cmos_sensor(0x3806, 0x05); // yend = 1521 + write_cmos_sensor(0x3807, 0xf1); // yend + write_cmos_sensor(0x3808, 0x07); // x output size = 1920 + write_cmos_sensor(0x3809, 0x80); // x output size + write_cmos_sensor(0x380a, 0x04); // y output size = 1080 + write_cmos_sensor(0x380b, 0x38); // y output size + + + //write_cmos_sensor(0x380c, 0x09); // hts = 2500 + //write_cmos_sensor(0x380d, 0xc4); // hts + //write_cmos_sensor(0x380e, 0x04); // vts = 1120 + //write_cmos_sensor(0x380f, 0x60); // vts + write_cmos_sensor(0x380c, ((imgsensor_info.hs_video.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.hs_video.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.hs_video.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.hs_video.framelength & 0xFF)); // vts + + write_cmos_sensor(0x3810, 0x00); // isp x win = 16 + write_cmos_sensor(0x3811, 0x10); // isp x win + write_cmos_sensor(0x3812, 0x00); // isp y win = 4 + write_cmos_sensor(0x3813, 0x04); // isp y win + write_cmos_sensor(0x3814, 0x11); // x inc + write_cmos_sensor(0x3815, 0x11); // y inc + write_cmos_sensor(0x3817, 0x00); // hsync start + + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + write_cmos_sensor(0x3820, 0x40); // flip off, v bin off + write_cmos_sensor(0x3821, 0x06); // mirror on, h bin on + + + write_cmos_sensor(0x4004, 0x04); // black line number + write_cmos_sensor(0x4005, 0x18); // blc normal freeze + + + //write_cmos_sensor(0x350b, 0xf0); // gain = 8x + write_cmos_sensor(0x4837, 0x18); // MIPI global timing + + write_cmos_sensor(0x0100, 0x01); //Stream On + +} /* preview_setting */ + +static void video_720p_setting(void) +{ + /******************************************************** + * + * 720p 30fps 2 lane MIPI 420Mbps/lane + * @@720p_30fps + * ;;pclk=84M,HTS=3728,VTS=748 + ********************************************************/ + + write_cmos_sensor(0x0100, 0x00); //Stream Off + + mDELAY(10); + write_cmos_sensor(0x3500, 0x00); // exposure [19:16] + write_cmos_sensor(0x3501, 0x2d); // exposure + write_cmos_sensor(0x3502, 0xc0); // exposure + + write_cmos_sensor(0x3708, 0x66); + + write_cmos_sensor(0x3709, 0x52); + write_cmos_sensor(0x370c, 0xcf); + write_cmos_sensor(0x3800, 0x00); // x start = 16 + write_cmos_sensor(0x3801, 0x10); // x start + write_cmos_sensor(0x3802, 0x00); // y start = 254 + write_cmos_sensor(0x3803, 0xfe); // y start + write_cmos_sensor(0x3804, 0x0a); // xend = 2607 + write_cmos_sensor(0x3805, 0x2f); // xend + write_cmos_sensor(0x3806, 0x06); // yend = 1701 + write_cmos_sensor(0x3807, 0xa5); // yend + write_cmos_sensor(0x3808, 0x05); // x output size = 1280 + write_cmos_sensor(0x3809, 0x00); // x output size + write_cmos_sensor(0x380a, 0x02); // y output size = 720 + write_cmos_sensor(0x380b, 0xd0); // y output size + + + //write_cmos_sensor(0x380c, 0x0e); // hts = 3728 + //write_cmos_sensor(0x380d, 0x90); // hts + //write_cmos_sensor(0x380e, 0x02); // vts = 748 + //write_cmos_sensor(0x380f, 0xec); // vts + write_cmos_sensor(0x380c, ((imgsensor_info.slim_video.linelength >> 8) & 0xFF)); // hts = 2688 + write_cmos_sensor(0x380d, (imgsensor_info.slim_video.linelength & 0xFF)); // hts + write_cmos_sensor(0x380e, ((imgsensor_info.slim_video.framelength >> 8) & 0xFF)); // vts = 1984 + write_cmos_sensor(0x380f, (imgsensor_info.slim_video.framelength & 0xFF)); // vts + + write_cmos_sensor(0x3810, 0x00); // isp x win = 8 + write_cmos_sensor(0x3811, 0x08); // isp x win + write_cmos_sensor(0x3812, 0x00); // isp y win = 2 + write_cmos_sensor(0x3813, 0x02); // isp y win + write_cmos_sensor(0x3814, 0x31); // x inc + write_cmos_sensor(0x3815, 0x31); // y inc + write_cmos_sensor(0x3817, 0x00); // hsync start + + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + write_cmos_sensor(0x3820, 0x08); // flip off, v bin off + write_cmos_sensor(0x3821, 0x07); // mirror on, h bin on + + + write_cmos_sensor(0x4004, 0x02); // black line number + write_cmos_sensor(0x4005, 0x18); // blc normal freeze + + + //write_cmos_sensor(0x350b, 0x80); // gain = 8x + write_cmos_sensor(0x4837, 0x18); // MIPI global timing + + write_cmos_sensor(0x0100, 0x01); //Stream On + + LOG_INF("Exit!"); +} /* preview_setting */ + + +static void hs_video_setting(void) +{ + LOG_INF("E\n"); + + video_1080p_setting(); +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + + video_720p_setting(); +} + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, write id:0x%x id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + LOG_2; + + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id:0x%x id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap1's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap1.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + //set_mirror_flip(sensor_config_data->SensorImageMirror); + + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{// + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + + + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + // 0x503D[8]: 1 enable, 0 disable + // 0x503D[1:0]; 00 Color bar, 01 Random Data, 10 Square + if(enable) + write_cmos_sensor(0x503D, 0x80); + else + write_cmos_sensor(0x503D, 0x00); + + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + //unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + //printk("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + LOG_INF("feature_Control imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 OV5648MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV5648MIPISensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/ov5648mipi_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/ov5648mipi_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..c35b5d1153858f5fd21fbb8f4b4bb6bc1d6a66f6 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov5648_mipi_raw/ov5648mipi_Sensor.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * ov5648mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _OV5648MIPI_SENSOR_H +#define _OV5648MIPI_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint32 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff + kal_uint32 i2c_speed; //i2c speed +} imgsensor_info_struct; + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..b95e693744c81c959ef37898dc76cbd98cebc7f4 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/Makefile @@ -0,0 +1,4 @@ + +obj-y += ov8856mipiraw_Sensor.o +obj-y += ov8856_otp.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/ov8856_otp.c b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/ov8856_otp.c new file mode 100755 index 0000000000000000000000000000000000000000..9fc04c696855b62a521ffaf18e9a97eef004ce17 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/ov8856_otp.c @@ -0,0 +1,785 @@ +/* +NOTE: +The modification is appended to initialization of image sensor. +After sensor initialization, use the function +bool otp_update_wb() +and +bool otp_update_lenc(void) +and +then the calibration of AWB & LSC & BLC will be applied. +After finishing the OTP written, we will provide you the typical value of golden sample. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "ov8856mipiraw_Sensor.h" +//#include "ov8856mipiraw_Camera_Sensor_para.h" +//#include "ov8856mipiraw_CameraCustomized.h" + + +extern int iReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); + + + +//#define SUPPORT_FLOATING + +#define OTP_LOAD_ADDR 0x3D81 +#define OTP_BANK_ADDR 0x3D84 + +#define LENC_START_ADDR 0x5900 +#define LENC_REG_SIZE 240 + +#define OTP_LENC_GROUP_FLAG 0x7028 +#define OTP_LENC_GROUP_ADDR 0x7029 + +#define OTP_BASIC_GROUP_FLAG 0x7010 +#define OTP_BASIC_GROUP_ADDR 0x7011 + +#define OTP_H_START_ADDR 0x3D88 +#define OTP_L_START_ADDR 0x3D89 +#define OTP_H_END_ADDR 0x3D8A +#define OTP_L_END_ADDR 0x3D8B +#define OTP_GROUP_SIZE 8 + +#define GAIN_RH_ADDR 0x5019 +#define GAIN_RL_ADDR 0x501A +#define GAIN_GH_ADDR 0x501B +#define GAIN_GL_ADDR 0x501C +#define GAIN_BH_ADDR 0x501D +#define GAIN_BL_ADDR 0x501E + +#define GAIN_DEFAULT_VALUE 0x0400 // 1x gain + +#define OTP_MID 0x02 +#define TRULY_TYPICAL_RG 0x135 +#define TRULY_TYPICAL_BG 0x12F + +#define PFX "OV8856_OTP" +#define OV8856_OTP_DEBUG +#ifdef OV8856_OTP_DEBUG +#define LOG_INF(format, args...) printk(PFX "[%s] " format, __FUNCTION__, ##args) +#else +#define LOG_INF(format, args...) +#endif + + +static unsigned char OV8856MIPI_WRITE_ID = 0x42; + +#define Delay(ms) mdelay(ms) + +// R/G and B/G of current camera module +unsigned short rg_ratio = 0; +unsigned short bg_ratio = 0; +unsigned short golden_rg = 0; +unsigned short golden_bg = 0; +unsigned char otp_lenc_data[LENC_REG_SIZE]; +unsigned char otp_lenc_data2[LENC_REG_SIZE]; +void DPCFuncEnable(void); +void DPCFuncDisable(void); +// Enable OTP read function + + +kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + iReadReg((u16) addr ,(u8*)&get_byte,OV8856MIPI_WRITE_ID); + return get_byte; + +} + +void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + iWriteReg((u16) addr , (u32) para , 1, OV8856MIPI_WRITE_ID); +} + +void otp_read_enable(void) +{ + write_cmos_sensor(OTP_LOAD_ADDR, 0x01); + mdelay(15); // +} + +// Disable OTP read function +void otp_read_disable(void) +{ + write_cmos_sensor(OTP_LOAD_ADDR, 0x00); + mdelay(5); // +} + +void otp_read(unsigned short otp_addr, unsigned char* otp_data) +{ + otp_read_enable(); + *otp_data = read_cmos_sensor(otp_addr); +// otp_read_disable(); +} + +/******************************************************************************* +* Function : otp_clear +* Description : Clear OTP buffer +* Parameters : none +* Return : none +*******************************************************************************/ +void otp_clear(unsigned short star, unsigned short end) +{ + unsigned short i; + // After read/write operation, the OTP buffer should be cleared to avoid accident write + for ( i=star; i 2) + { + LOG_INF("OTP input wb group index %d error\n", index); + return -1; + } + + DPCFuncDisable(); + // select base information flag + + write_cmos_sensor(OTP_BANK_ADDR, 0xc0); + write_cmos_sensor(OTP_H_START_ADDR, (otp_addr>>8) & 0xff); + write_cmos_sensor(OTP_L_START_ADDR, otp_addr & 0xff); + write_cmos_sensor(OTP_H_END_ADDR, (otp_addr>>8) & 0xff); + write_cmos_sensor(OTP_L_END_ADDR, otp_addr & 0xff); + msleep(5); + otp_read(otp_addr, &flagBasic); + write_cmos_sensor(otp_addr, 0x00); + DPCFuncEnable(); + + // Check all bytes of a group. If all bytes are '0', then the group is empty. + // Check from group 1 to group 2, then group 3. + + if (index==0) + { + + flagBasic = (flagBasic>>6) & 0x03; + if (!flagBasic) + { + LOG_INF("wb group %d is empty", index); + return 0; + } + else if (flagBasic == 0x01 ) + { + LOG_INF("wb group %d has valid data", index);; + return 2; + } + else //if (flagBasic == 0x11) + { + LOG_INF("wb group %d has invalid data", index); + return 1; + } + } + + else + { + + flagBasic=(flagBasic>>4) & 0x03; + + if (!flagBasic) + { + LOG_INF("wb group %d is empty", index); + return 0; + } + else if (flagBasic == 0x01 ) + { + LOG_INF("wb group %d has valid data", index); + return 2; + } + else //if (flagBasic == 0x11) + { + LOG_INF("wb group %d has invalid data", index); + return 1; + } + } +} + +/******************************************************************************* +* Function : otp_read_wb_group +* Description : Read group value and store it in OTP Struct +* Parameters : [in] index : index of otp group (0, 1, 2) +* Return : group index (0, 1, 2) + -1, error +*******************************************************************************/ +signed char otp_read_wb_group(void) +{ + unsigned char mid, AWB_light_LSB, rg_ratio_MSB, bg_ratio_MSB,lens; + unsigned short otp_addr=0; + // Check first OTP with valid data + int index =0; + for (index=0; index<2; index++) + { + if (otp_check_wb_group(index) == 2) + { + LOG_INF("read wb from group %d\n", index); + break; + } + } + + if (index == 2) + { + LOG_INF("no group has valid data\n"); + return -1; + } + DPCFuncDisable(); + // select adress + otp_addr = OTP_BASIC_GROUP_ADDR + index * OTP_GROUP_SIZE; + + write_cmos_sensor(OTP_BANK_ADDR, 0xc0); + write_cmos_sensor(OTP_H_START_ADDR, (otp_addr>>8) & 0xff); + write_cmos_sensor(OTP_L_START_ADDR, otp_addr & 0xff); + write_cmos_sensor(OTP_H_END_ADDR, ((otp_addr+7)>>8) & 0xff); + write_cmos_sensor(OTP_L_END_ADDR, (otp_addr+7) & 0xff); + mdelay(5); + otp_read(otp_addr, &mid); + otp_read(otp_addr+1, &lens); + + if (mid == OTP_MID) + { + golden_rg = TRULY_TYPICAL_RG; + golden_bg = TRULY_TYPICAL_BG; + LOG_INF("This Module is Truly Module\n"); + } + else + { + LOG_INF("This Module is Other Module\n"); + //ÆäËû²Ù×÷ + return -1; + } +/* if (lens == 0x01) + { + LOG_INF("This LensID is Truly Module\n"); + } + else + { + LOG_INF("This LensID is Other Module\n"); + //ÆäËû²Ù×÷ + return -1; + }*/ + otp_read(otp_addr+5, &rg_ratio_MSB); + otp_read(otp_addr+6, &bg_ratio_MSB); + otp_read(otp_addr+7, &AWB_light_LSB); + otp_clear(otp_addr,otp_addr+7); + DPCFuncEnable(); + + rg_ratio = (rg_ratio_MSB<<2) | ((AWB_light_LSB & 0xC0)>>6); + bg_ratio = (bg_ratio_MSB<<2) | ((AWB_light_LSB & 0x30)>>4); + + + + LOG_INF("rg_ratio=0x%x, bg_ratio=0x%x\n", rg_ratio, bg_ratio); + + if ((rg_ratio_MSB == 0) || (bg_ratio_MSB == 0)) + { + DPCFuncDisable(); + // select adress + otp_addr = OTP_BASIC_GROUP_ADDR + index * OTP_GROUP_SIZE; + + write_cmos_sensor(OTP_BANK_ADDR, 0xc0); + write_cmos_sensor(OTP_H_START_ADDR, (otp_addr>>8) & 0xff); + write_cmos_sensor(OTP_L_START_ADDR, otp_addr & 0xff); + write_cmos_sensor(OTP_H_END_ADDR, ((otp_addr+7)>>8) & 0xff); + write_cmos_sensor(OTP_L_END_ADDR, (otp_addr+7) & 0xff); + mdelay(5); + otp_read(otp_addr+5, &rg_ratio_MSB); + otp_read(otp_addr+6, &bg_ratio_MSB); + otp_read(otp_addr+7, &AWB_light_LSB); + otp_clear(otp_addr,otp_addr+7); + DPCFuncEnable(); + + rg_ratio = (rg_ratio_MSB<<2) | ((AWB_light_LSB & 0xC0)>>6); + bg_ratio = (bg_ratio_MSB<<2) | ((AWB_light_LSB & 0x30)>>4); + LOG_INF("rg_ratio=0x%x, bg_ratio=0x%x\n", rg_ratio, bg_ratio); + + if ((rg_ratio_MSB == 0) || (bg_ratio_MSB == 0)) + { + return -1; + } + } + LOG_INF("read wb finished\n"); + return index; +} + +#ifdef SUPPORT_FLOATING //Use this if support floating point values +/******************************************************************************* +* Function : otp_apply_wb +* Description : Calcualte and apply R, G, B gain to module +* Parameters : [in] golden_rg : R/G of golden camera module + [in] golden_bg : B/G of golden camera module +* Return : 1, success; 0, fail +*******************************************************************************/ +bool otp_apply_wb() +{ + unsigned short gain_r = GAIN_DEFAULT_VALUE; + unsigned short gain_g = GAIN_DEFAULT_VALUE; + unsigned short gain_b = GAIN_DEFAULT_VALUE; + + double ratio_r, ratio_g, ratio_b; + double cmp_rg, cmp_bg; + + if (!golden_rg || !golden_bg) + { + LOG_INF("golden_rg / golden_bg can not be zero\n"); + return 0; + } + // Calcualte R, G, B gain of current module from R/G, B/G of golden module + // and R/G, B/G of current module + cmp_rg = 1.0 * rg_ratio / golden_rg; + cmp_bg = 1.0 * bg_ratio / golden_bg; + + if ((cmp_rg<1) && (cmp_bg<1)) + { + // R/G < R/G golden, B/G < B/G golden + ratio_g = 1; + ratio_r = 1 / cmp_rg; + ratio_b = 1 / cmp_bg; + } + else if (cmp_rg > cmp_bg) + { + // R/G >= R/G golden, B/G < B/G golden + // R/G >= R/G golden, B/G >= B/G golden + ratio_r = 1; + ratio_g = cmp_rg; + ratio_b = cmp_rg / cmp_bg; + } + else + { + // B/G >= B/G golden, R/G < R/G golden + // B/G >= B/G golden, R/G >= R/G golden + ratio_b = 1; + ratio_g = cmp_bg; + ratio_r = cmp_bg / cmp_rg; + } + + // write sensor wb gain to registers + // 0x0400 = 1x gain + if (ratio_r != 1) + { + gain_r = (unsigned short)(GAIN_DEFAULT_VALUE * ratio_r); + write_cmos_sensor(GAIN_RH_ADDR, gain_r >> 8); + write_cmos_sensor(GAIN_RL_ADDR, gain_r & 0x00ff); + } + + if (ratio_g != 1) + { + gain_g = (unsigned short)(GAIN_DEFAULT_VALUE * ratio_g); + write_cmos_sensor(GAIN_GH_ADDR, gain_g >> 8); + write_cmos_sensor(GAIN_GL_ADDR, gain_g & 0x00ff); + } + + if (ratio_b != 1) + { + gain_b = (unsigned short)(GAIN_DEFAULT_VALUE * ratio_b); + write_cmos_sensor(GAIN_BH_ADDR, gain_b >> 8); + write_cmos_sensor(GAIN_BL_ADDR, gain_b & 0x00ff); + } + + LOG_INF("cmp_rg=%f, cmp_bg=%f\n", cmp_rg, cmp_bg); + LOG_INF("ratio_r=%f, ratio_g=%f, ratio_b=%f\n", ratio_r, ratio_g, ratio_b); + LOG_INF("gain_r=0x%x, gain_g=0x%x, gain_b=0x%x\n", gain_r, gain_g, gain_b); + return 1; +} + +#else //Use this if not support floating point values + +#define OTP_MULTIPLE_FAC 10000 +bool otp_apply_wb(void) +{ + unsigned short gain_r = GAIN_DEFAULT_VALUE; + unsigned short gain_g = GAIN_DEFAULT_VALUE; + unsigned short gain_b = GAIN_DEFAULT_VALUE; + + unsigned short ratio_r, ratio_g, ratio_b; + unsigned short cmp_rg, cmp_bg; + bool is_rg_valid = KAL_FALSE; // default: false + bool is_bg_valid = KAL_FALSE; // default: false + + if (!golden_rg || !golden_bg) + { + LOG_INF("golden_rg / golden_bg can not be zero\n"); + return 0; + } + + // Calcualte R, G, B gain of current module from R/G, B/G of golden module + // and R/G, B/G of current module + cmp_rg = OTP_MULTIPLE_FAC * rg_ratio / golden_rg; + cmp_bg = OTP_MULTIPLE_FAC * bg_ratio / golden_bg; + +// heafei 20170213 ++ +// rg_ratio/golden_rg is in [0.8, 1.2], cmp_rg is in [8000, 12000] +// bg_ratio/golden_bg is in [0.8, 1.2], cmp_bg is in [8000, 12000] +/* Vanzo:yangbinbin on: Mon, 13 Feb 2017 21:15:08 +0800 + * validate cmp_rg&cmp_bg whether golden value 0.8 to 1.2 + is_rg_valid = (cmp_rg > OTP_MULTIPLE_FAC*0.8) && (cmp_rg < OTP_MULTIPLE_FAC*1.2); + is_bg_valid = (cmp_bg > OTP_MULTIPLE_FAC*0.8) && (cmp_bg < OTP_MULTIPLE_FAC*1.2); + */ + is_rg_valid = (cmp_rg > ((OTP_MULTIPLE_FAC*4)/5)) && (cmp_rg < ((OTP_MULTIPLE_FAC*6)/5)); + is_bg_valid = (cmp_bg > ((OTP_MULTIPLE_FAC*4)/5)) && (cmp_bg < ((OTP_MULTIPLE_FAC*6)/5)); +// End of Vanzo: yangbinbin + + if (!is_rg_valid|| !is_bg_valid) + { + LOG_INF("[heafei] rg_ratio / bg_ratio invalid\n"); + return KAL_FALSE; + } +// heafei 20170213 -- + + + if ((cmp_rg < 1 * OTP_MULTIPLE_FAC) && (cmp_bg < 1 * OTP_MULTIPLE_FAC)) + { + // R/G < R/G golden, B/G < B/G golden + ratio_g = 1 * OTP_MULTIPLE_FAC; + ratio_r = 1 * OTP_MULTIPLE_FAC * OTP_MULTIPLE_FAC / cmp_rg; + ratio_b = 1 * OTP_MULTIPLE_FAC * OTP_MULTIPLE_FAC / cmp_bg; + } + else if (cmp_rg > cmp_bg) + { + // R/G >= R/G golden, B/G < B/G golden + // R/G >= R/G golden, B/G >= B/G golden + ratio_r = 1 * OTP_MULTIPLE_FAC; + ratio_g = cmp_rg; + ratio_b = OTP_MULTIPLE_FAC * cmp_rg / cmp_bg; + } + else + { + // B/G >= B/G golden, R/G < R/G golden + // B/G >= B/G golden, R/G >= R/G golden + ratio_b = 1 * OTP_MULTIPLE_FAC; + ratio_g = cmp_bg; + ratio_r = OTP_MULTIPLE_FAC * cmp_bg / cmp_rg; + } + + // write sensor wb gain to registers + // 0x0400 = 1x gain + if (ratio_r != 1 * OTP_MULTIPLE_FAC) + { + gain_r = GAIN_DEFAULT_VALUE * ratio_r / OTP_MULTIPLE_FAC; + write_cmos_sensor(GAIN_RH_ADDR, gain_r >> 8); + write_cmos_sensor(GAIN_RL_ADDR, gain_r & 0x00ff); + } + + if (ratio_g != 1 * OTP_MULTIPLE_FAC) + { + gain_g = GAIN_DEFAULT_VALUE * ratio_g / OTP_MULTIPLE_FAC; + write_cmos_sensor(GAIN_GH_ADDR, gain_g >> 8); + write_cmos_sensor(GAIN_GL_ADDR, gain_g & 0x00ff); + } + + if (ratio_b != 1 * OTP_MULTIPLE_FAC) + { + gain_b = GAIN_DEFAULT_VALUE * ratio_b / OTP_MULTIPLE_FAC; + write_cmos_sensor(GAIN_BH_ADDR, gain_b >> 8); + write_cmos_sensor(GAIN_BL_ADDR, gain_b & 0x00ff); + } + + LOG_INF("cmp_rg=%d, cmp_bg=%d\n", cmp_rg, cmp_bg); + LOG_INF("ratio_r=%d, ratio_g=%d, ratio_b=%d\n", ratio_r, ratio_g, ratio_b); + LOG_INF("gain_r=0x%x, gain_g=0x%x, gain_b=0x%x\n", gain_r, gain_g, gain_b); + return 1; +} +#endif /* SUPPORT_FLOATING */ + +/******************************************************************************* +* Function : otp_update_wb +* Description : Update white balance settings from OTP +* Parameters : void +* Return : 1, success; 0, fail +*******************************************************************************/ +bool otp_update_wb(void) +{ + LOG_INF("start wb update\n"); + + if (otp_read_wb_group() != -1) + { + if (otp_apply_wb() == 1) + { + LOG_INF("wb update finished\n"); + return 1; + } + } + LOG_INF("wb update failed\n"); + return 0; +} + +/******************************************************************************* +* Function : otp_check_lenc_group +* Description : Check OTP Space Availability +* Parameters : [in] int index : index of otp group (0, 1, 2) +* Return : 0, group index is empty + 1, group index has invalid data + 2, group index has valid data + -1, group index error +*******************************************************************************/ +signed char otp_check_lenc_group(int index) +{ + unsigned char flag; + // select lenc flag + unsigned short otp_addr = OTP_LENC_GROUP_FLAG; + + DPCFuncDisable(); + + write_cmos_sensor(OTP_BANK_ADDR, 0xc0); + write_cmos_sensor(OTP_H_START_ADDR, (otp_addr>>8) & 0xff); + write_cmos_sensor(OTP_L_START_ADDR, otp_addr & 0xff); + write_cmos_sensor(OTP_H_END_ADDR, (otp_addr>>8) & 0xff); + write_cmos_sensor(OTP_L_END_ADDR, otp_addr & 0xff); + msleep(5); + otp_read(otp_addr, &flag); + // otp_read_disable(); + write_cmos_sensor(otp_addr, 0x00); + DPCFuncEnable(); + + // Check all bytes of a group. If all bytes are '0', then the group is empty. + // Check from group 1 to group 2, then group 3. + if (index==0) + { + flag=(flag>>6) & 0x03; + + if (!flag) + { + LOG_INF("lenc group %d is empty", index); + return 0; + } + else if (flag == 0x01) + { + LOG_INF("lenc group %d has valid data", index); + return 2; + } + else //if (flag == 0x11) + { + LOG_INF("lenc group %d has invalid data", index); + return 1; + } + } + + else + { + + flag=(flag>>4) & 0x03; + + if (!flag) + { + LOG_INF("lenc group %d is empty", index); + return 0; + } + else if (flag == 0x01) + { + LOG_INF("lenc group %d has valid data", index); + return 2; + } + else //if (flag == 0x11) + { + LOG_INF("lenc group %d has invalid data", index); + return 1; + } + + + } + +} + +void otp_check_lenc(void) +{ + int i; + for (i=0; i>8) & 0xff); + write_cmos_sensor(OTP_L_START_ADDR, otp_addr & 0xff); + write_cmos_sensor(OTP_H_END_ADDR, ((otp_addr+LENC_REG_SIZE)>>8) & 0xff); + write_cmos_sensor(OTP_L_END_ADDR, (otp_addr+LENC_REG_SIZE) & 0xff); + otp_read_enable(); + for (i=0; i>8) & 0xff); + write_cmos_sensor(OTP_L_START_ADDR, otp_addr & 0xff); + write_cmos_sensor(OTP_H_END_ADDR, ((otp_addr+LENC_REG_SIZE)>>8) & 0xff); + write_cmos_sensor(OTP_L_END_ADDR, (otp_addr+LENC_REG_SIZE) & 0xff); + otp_read_enable(); + for (i=0; i +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + + +#include "ov8856mipiraw_Sensor.h" + +#define PFX "OV8856" + +//#define OV8856R1AOTP + +#define LOG_INF(fmt, args...) pr_debug(PFX "[%s] " fmt, __FUNCTION__, ##args) +#define LOGE(format, args...) pr_err("[%s] " format, __FUNCTION__, ##args) +//#define LOG_WRN(format, args...) xlog_printk(ANDROID_LOG_WARN ,PFX, "[%S] " format, __FUNCTION__, ##args) +//#defineLOG_INF(format, args...) xlog_printk(ANDROID_LOG_INFO ,PFX, "[%s] " format, __FUNCTION__, ##args) +//#define LOG_DBG(format, args...) xlog_printk(ANDROID_LOG_DEBUG ,PFX, "[%S] " format, __FUNCTION__, ##args) +typedef enum { + OV8856R2A, + OV8856R1A +}OV8856_VERSION; + +OV8856_VERSION ov8856version = OV8856R1A; + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + +extern void ov8856_otp_update(void); + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = OV8856_SENSOR_ID, //record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0x10afc63, //checksum value for Camera Auto Test + + .pre = { + .pclk = 144000000, //record different mode's pclk + .linelength = 1932, //record different mode's linelength + .framelength = 2482, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1632, //record different mode's width of grabwindow + .grabwindow_height = 1224, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk = 144000000, + .linelength = 1932, + .framelength = 2482, + .startx = 0, + .starty = 0, + .grabwindow_width = 3264, + .grabwindow_height = 2448, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 300, + }, + .cap1 = { //capture for 15fps + .pclk = 144000000, + .linelength = 1932, + .framelength = 4964, + .startx = 0, + .starty = 0, + .grabwindow_width = 3264, + .grabwindow_height = 2448, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 150, + }, + .normal_video = { // cap + .pclk = 144000000, + .linelength = 1932, + .framelength = 2482, + .startx = 0, + .starty = 0, + .grabwindow_width = 3264, + .grabwindow_height = 2448, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 300, + }, + .hs_video = { + + .pclk = 144000000, //record different mode's pclk + .linelength = 1932, //record different mode's linelength + .framelength = 620, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 640, //record different mode's width of grabwindow + .grabwindow_height = 480, //record different mode's height of grabwindow + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 1200, + + }, + .slim_video = {//pre + .pclk = 144000000, //record different mode's pclk + .linelength = 1932, //record different mode's linelength + .framelength = 2482, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1632, //record different mode's width of grabwindow + .grabwindow_height = 1224, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + + }, + .margin = 6, //sensor framelength & shutter margin + .min_shutter = 6, //min shutter + .max_frame_length = 0x90f7,//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num ,don't support Slow motion + + .cap_delay_frame = 3, //enter capture delay frame num + .pre_delay_frame = 3, //enter preview delay frame num + .video_delay_frame = 1, //enter video delay frame num + .hs_video_delay_frame = 3, //enter high speed video delay frame num + .slim_video_delay_frame = 3,//enter slim video delay frame num + + .isp_driving_current = ISP_DRIVING_8MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_MANUAL,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_4_LANE,//mipi lane num + .i2c_addr_table = {0x42, 0xff},//record sensor support all write id addr, only supprt 4must end with 0xff +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_HV_MIRROR, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x4C00, //current shutter + .gain = 0x200, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 30, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x42,//record current sensor's i2c write id +}; + + +/* Sensor output window information*/ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{ +#if 0 + { 3296, 2480, 0, 12, 3296, 2456, 1648, 1228, 2, 2, 1632, 1224, 0, 0, 1632, 1224}, // Preview + { 3296, 2480, 0, 12, 3296, 2456, 3296, 2456, 4, 2, 3264, 2448, 0, 0, 3264, 2448}, // capture + { 3296, 2480, 0, 12, 3296, 2456, 3296, 2456, 4, 2, 3264, 2448, 0, 0, 3264, 2448}, // video + { 3296, 2480, 336, 272, 2624, 1936, 656, 484, 8, 2, 640, 480, 0, 0, 640, 480}, //hight speed video + { 3296, 2480, 0, 12, 3296, 2456, 1648, 1228, 2, 2, 1632, 1224, 0, 0, 1632, 1224} // slim video + #endif +{ 3296, 2480, 0, 12, 3296, 2456, 1648, 1228, 2, 2, 1632, 1224, 0, 0, 1632, 1224}, // Preview +{ 3296, 2480, 0, 12, 3296, 2456, 3296, 2456, 4, 2, 3264, 2448, 0, 0, 3264, 2448}, // capture +{ 3296, 2480, 0, 12, 3296, 2456, 3296, 2456, 4, 2, 3264, 2448, 0, 0, 3264, 2448}, // video +{ 3296, 2480, 336, 272, 2624, 1936, 656, 484, 8, 2, 640, 480, 0, 0, 640, 480}, //hight speed video +{ 3296, 2480, 0, 12, 3296, 2456, 1648, 1228, 2, 2, 1632, 1224, 0, 0, 1632, 1224}};// slim video + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; +} + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + /* you can set dummy by imgsensor.dummy_line and imgsensor.dummy_pixel, or you can set dummy by imgsensor.frame_length and imgsensor.line_length */ + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x380c, imgsensor.line_length >> 8); + write_cmos_sensor(0x380d, imgsensor.line_length & 0xFF); + +} /* set_dummy */ + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + //kal_int16 dummy_line; + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable? \n", framerate); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + +#if 0 +static void write_shutter(kal_uint16 shutter) +{ + kal_uint16 realtime_fps = 0; + //kal_uint32 frame_length = 0; + + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + } else { + // Extend frame length + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + + // Update Shutter + write_cmos_sensor(0x3500, (shutter>>12) & 0x0F); + write_cmos_sensor(0x3501, (shutter>>4) & 0xFF); + write_cmos_sensor(0x3502, (shutter<<4) & 0xF0); + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + + //LOG_INF("frame_length = %d ", frame_length); + +} /* write_shutter */ + +#endif + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + kal_uint16 realtime_fps = 0; + //kal_uint32 frame_length = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + //write_shutter(shutter); + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + } else { + // Extend frame length + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + + // Update Shutter + write_cmos_sensor(0x3502, (shutter << 4) & 0xFF); + write_cmos_sensor(0x3501, (shutter >> 4) & 0xFF); + write_cmos_sensor(0x3500, (shutter >> 12) & 0x0F); + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} +#if 0 +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0000; + + reg_gain = gain*2; + //reg_gain = reg_gain & 0xFFFF; + return (kal_uint16)reg_gain; +} +#endif +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + if (gain < BASEGAIN || gain > 15 * BASEGAIN) { + LOG_INF("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 15 * BASEGAIN) + gain = 15 * BASEGAIN; + } + + //reg_gain = gain2reg(gain); + reg_gain = gain*2; + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor(0x3508, (reg_gain>>8)); + write_cmos_sensor(0x3509, (reg_gain&0xFF)); + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length first + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + + write_cmos_sensor(0x3502, (le << 4) & 0xFF); + write_cmos_sensor(0x3501, (le >> 4) & 0xFF); + write_cmos_sensor(0x3500, (le >> 12) & 0x0F); + + write_cmos_sensor(0x3512, (se << 4) & 0xFF); + write_cmos_sensor(0x3511, (se >> 4) & 0xFF); + write_cmos_sensor(0x3510, (se >> 12) & 0x0F); + + set_gain(gain); + } + +} + + + +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xB9) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x06)); + write_cmos_sensor(0x502e,((read_cmos_sensor(0x502e) & 0xFC) | 0x03)); + write_cmos_sensor(0x5001,((read_cmos_sensor(0x5001) & 0xFB) | 0x00)); + write_cmos_sensor(0x5004,((read_cmos_sensor(0x5004) & 0xFB) | 0x04)); + write_cmos_sensor(0x376b,((read_cmos_sensor(0x376b) & 0xC0) | 0x30)); + + break; + case IMAGE_H_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xB9) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x00)); + write_cmos_sensor(0x502e,((read_cmos_sensor(0x502e) & 0xFC) | 0x03)); + write_cmos_sensor(0x5001,((read_cmos_sensor(0x5001) & 0xFB) | 0x00)); + write_cmos_sensor(0x5004,((read_cmos_sensor(0x5004) & 0xFB) | 0x00)); + write_cmos_sensor(0x376b,((read_cmos_sensor(0x376b) & 0xC0) | 0x30)); + break; + case IMAGE_V_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xB9) | 0x46)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x06)); + write_cmos_sensor(0x502e,((read_cmos_sensor(0x502e) & 0xFC) | 0x00)); + write_cmos_sensor(0x5001,((read_cmos_sensor(0x5001) & 0xFB) | 0x04)); + write_cmos_sensor(0x5004,((read_cmos_sensor(0x5004) & 0xFB) | 0x04)); + write_cmos_sensor(0x376b,((read_cmos_sensor(0x376b) & 0xC0) | 0x20)); + + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xB9) | 0x46)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x00)); + write_cmos_sensor(0x502e,((read_cmos_sensor(0x502e) & 0xFC) | 0x00)); + write_cmos_sensor(0x5001,((read_cmos_sensor(0x5001) & 0xFB) | 0x04)); + write_cmos_sensor(0x5004,((read_cmos_sensor(0x5004) & 0xFB) | 0x00)); + write_cmos_sensor(0x376b,((read_cmos_sensor(0x376b) & 0xC0) | 0x20)); + + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} + +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ + +static void sensor_init(void) +{ + LOG_INF("E\n"); + /* R1A_AM05, Ken Cui@2015/7/20 + ;Xclk 24Mhz + ;pclk 144Mhz + linelength = 1932(0x78C) + framelength = 2482(0x9b2) + grabwindow_width = 1632 + grabwindow_height = 1224 + max_framerate = 300, + mipi_data_lp2hs_settle_dc =23? + mipi_datarate = 720; Mbps + */ + write_cmos_sensor(0x0103, 0x01); + write_cmos_sensor(0x0302, 0x3c); + write_cmos_sensor(0x0303, 0x01); + write_cmos_sensor(0x031e, 0x0c); + write_cmos_sensor(0x3000, 0x00); + write_cmos_sensor(0x300e, 0x00); + write_cmos_sensor(0x3010, 0x00); + write_cmos_sensor(0x3015, 0x84); + write_cmos_sensor(0x3018, 0x72); + write_cmos_sensor(0x3033, 0x24); + write_cmos_sensor(0x3500, 0x00); + write_cmos_sensor(0x3501, 0x4c); + write_cmos_sensor(0x3502, 0xe0); + write_cmos_sensor(0x3503, 0x08); + write_cmos_sensor(0x3505, 0x83); + write_cmos_sensor(0x3508, 0x01); + write_cmos_sensor(0x3509, 0x80); + write_cmos_sensor(0x350c, 0x00); + write_cmos_sensor(0x350d, 0x80); + write_cmos_sensor(0x350e, 0x04); + write_cmos_sensor(0x350f, 0x00); + write_cmos_sensor(0x3510, 0x00); + write_cmos_sensor(0x3511, 0x02); + write_cmos_sensor(0x3512, 0x00); + write_cmos_sensor(0x3600, 0x72); + write_cmos_sensor(0x3601, 0x40); + write_cmos_sensor(0x3602, 0x30); + write_cmos_sensor(0x3610, 0xc5); + write_cmos_sensor(0x3611, 0x58); + write_cmos_sensor(0x3612, 0x5c); + write_cmos_sensor(0x3613, 0x5a); + write_cmos_sensor(0x3614, 0x60); + write_cmos_sensor(0x3628, 0xff); + write_cmos_sensor(0x3629, 0xff); + write_cmos_sensor(0x362a, 0xff); + write_cmos_sensor(0x3633, 0x10); + write_cmos_sensor(0x3634, 0x10); + write_cmos_sensor(0x3635, 0x10); + write_cmos_sensor(0x3636, 0x10); + write_cmos_sensor(0x3663, 0x08); + write_cmos_sensor(0x3669, 0x34); + write_cmos_sensor(0x366e, 0x08); + write_cmos_sensor(0x3706, 0x86); //new DB MODIFY + write_cmos_sensor(0x370b, 0x7E); //new DB MODIFY + write_cmos_sensor(0x59f8, 0x3d); //new DB MODIFY + write_cmos_sensor(0x3714, 0x27); + write_cmos_sensor(0x3730, 0x12); + write_cmos_sensor(0x3733, 0x10); + write_cmos_sensor(0x3764, 0x00); + write_cmos_sensor(0x3765, 0x00); + write_cmos_sensor(0x3769, 0x62); + write_cmos_sensor(0x376a, 0x2a); + write_cmos_sensor(0x376b, 0x30); + write_cmos_sensor(0x3780, 0x00); + write_cmos_sensor(0x3781, 0x24); + write_cmos_sensor(0x3782, 0x00); + write_cmos_sensor(0x3783, 0x23); + write_cmos_sensor(0x3798, 0x2f); + write_cmos_sensor(0x37a1, 0x60); + write_cmos_sensor(0x37a8, 0x6a); + write_cmos_sensor(0x37ab, 0x3f); + write_cmos_sensor(0x37c2, 0x14); + write_cmos_sensor(0x37c3, 0xf1); + write_cmos_sensor(0x37c9, 0x80); + write_cmos_sensor(0x37cb, 0x03); + write_cmos_sensor(0x37cc, 0x0a); + write_cmos_sensor(0x37cd, 0x16); + write_cmos_sensor(0x37ce, 0x1f); + write_cmos_sensor(0x3800, 0x00); + write_cmos_sensor(0x3801, 0x00); + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x0c); + write_cmos_sensor(0x3804, 0x0c); + write_cmos_sensor(0x3805, 0xdf); + write_cmos_sensor(0x3806, 0x09); + write_cmos_sensor(0x3807, 0xa3); + write_cmos_sensor(0x3808, 0x06); + write_cmos_sensor(0x3809, 0x60); + write_cmos_sensor(0x380a, 0x04); + write_cmos_sensor(0x380b, 0xc8); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0x8c); + write_cmos_sensor(0x380e, 0x09);//04 + write_cmos_sensor(0x380f, 0xb2);//de + write_cmos_sensor(0x3810, 0x00); + write_cmos_sensor(0x3811, 0x08); + write_cmos_sensor(0x3812, 0x00); + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x03); + write_cmos_sensor(0x3815, 0x01); + write_cmos_sensor(0x3816, 0x00); + write_cmos_sensor(0x3817, 0x00); + write_cmos_sensor(0x3818, 0x00); + write_cmos_sensor(0x3819, 0x00); + write_cmos_sensor(0x3820, 0x90); + write_cmos_sensor(0x3821, 0x67); + write_cmos_sensor(0x382a, 0x03); + write_cmos_sensor(0x382b, 0x01); + write_cmos_sensor(0x3830, 0x06); + write_cmos_sensor(0x3836, 0x02); + write_cmos_sensor(0x3862, 0x04); + write_cmos_sensor(0x3863, 0x08); + write_cmos_sensor(0x3cc0, 0x33); + write_cmos_sensor(0x3d85, 0x17); + write_cmos_sensor(0x3d8c, 0x73); + write_cmos_sensor(0x3d8d, 0xde); + write_cmos_sensor(0x4001, 0xe0); + write_cmos_sensor(0x4003, 0x40); + write_cmos_sensor(0x4008, 0x00); + write_cmos_sensor(0x4009, 0x05); + write_cmos_sensor(0x400f, 0x80); + write_cmos_sensor(0x4010, 0xf0); + write_cmos_sensor(0x4011, 0xff); + write_cmos_sensor(0x4012, 0x02); + write_cmos_sensor(0x4013, 0x01); + write_cmos_sensor(0x4014, 0x01); + write_cmos_sensor(0x4015, 0x01); + write_cmos_sensor(0x4042, 0x00); + write_cmos_sensor(0x4043, 0x80); + write_cmos_sensor(0x4044, 0x00); + write_cmos_sensor(0x4045, 0x80); + write_cmos_sensor(0x4046, 0x00); + write_cmos_sensor(0x4047, 0x80); + write_cmos_sensor(0x4048, 0x00); + write_cmos_sensor(0x4049, 0x80); + write_cmos_sensor(0x4041, 0x03); + write_cmos_sensor(0x404c, 0x20); + write_cmos_sensor(0x404d, 0x00); + write_cmos_sensor(0x404e, 0x20); + write_cmos_sensor(0x4203, 0x80); + write_cmos_sensor(0x4307, 0x30); + write_cmos_sensor(0x4317, 0x00); + write_cmos_sensor(0x4503, 0x08); + write_cmos_sensor(0x4601, 0x80); + write_cmos_sensor(0x4816, 0x53); + write_cmos_sensor(0x481b, 0x58); + write_cmos_sensor(0x481f, 0x27); + write_cmos_sensor(0x4837, 0x16); + write_cmos_sensor(0x5000, 0x77); + write_cmos_sensor(0x5001, 0x0a); + write_cmos_sensor(0x5004, 0x04); + write_cmos_sensor(0x502e, 0x03); + write_cmos_sensor(0x5030, 0x41); + write_cmos_sensor(0x5795, 0x00); + write_cmos_sensor(0x5796, 0x10); + write_cmos_sensor(0x5797, 0x10); + write_cmos_sensor(0x5798, 0x73); + write_cmos_sensor(0x5799, 0x73); + write_cmos_sensor(0x579a, 0x00); + write_cmos_sensor(0x579b, 0x28); + write_cmos_sensor(0x579c, 0x00); + write_cmos_sensor(0x579d, 0x16); + write_cmos_sensor(0x579e, 0x06); + write_cmos_sensor(0x579f, 0x20); + write_cmos_sensor(0x57a0, 0x04); + write_cmos_sensor(0x57a1, 0xa0); + //;DPC setting + write_cmos_sensor(0x5780, 0x14); + write_cmos_sensor(0x5781, 0x0f); + write_cmos_sensor(0x5782, 0x44); + write_cmos_sensor(0x5783, 0x02); + write_cmos_sensor(0x5784, 0x01); + write_cmos_sensor(0x5785, 0x01); + write_cmos_sensor(0x5786, 0x00); + write_cmos_sensor(0x5787, 0x04); + write_cmos_sensor(0x5788, 0x02); + write_cmos_sensor(0x5789, 0x0f); + write_cmos_sensor(0x578a, 0xfd); + write_cmos_sensor(0x578b, 0xf5); + write_cmos_sensor(0x578c, 0xf5); + write_cmos_sensor(0x578d, 0x03); + write_cmos_sensor(0x578e, 0x08); + write_cmos_sensor(0x578f, 0x0c); + write_cmos_sensor(0x5790, 0x08); + write_cmos_sensor(0x5791, 0x04); + write_cmos_sensor(0x5792, 0x00); + write_cmos_sensor(0x5793, 0x52); + write_cmos_sensor(0x5794, 0xa3); + //; + write_cmos_sensor(0x5a08, 0x02); + write_cmos_sensor(0x5b00, 0x02); + write_cmos_sensor(0x5b01, 0x10); + write_cmos_sensor(0x5b02, 0x03); + write_cmos_sensor(0x5b03, 0xcf); + write_cmos_sensor(0x5b05, 0x6c); + write_cmos_sensor(0x5e00, 0x00); + write_cmos_sensor(0x0100, 0x01); + +} /* sensor_init */ + + +static void preview_setting(void) +{ + LOG_INF("E\n"); + write_cmos_sensor(0x0100, 0x00); + write_cmos_sensor(0x3501, 0x4c); + write_cmos_sensor(0x3502, 0xe0); + write_cmos_sensor(0x366e, 0x08); + write_cmos_sensor(0x3714, 0x27); + write_cmos_sensor(0x37c2, 0x14); + write_cmos_sensor(0x3800, 0x00); + write_cmos_sensor(0x3801, 0x00); + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x0c); + write_cmos_sensor(0x3804, 0x0c); + write_cmos_sensor(0x3805, 0xdf); + write_cmos_sensor(0x3806, 0x09); + write_cmos_sensor(0x3807, 0xa3); + write_cmos_sensor(0x3808, 0x06); + write_cmos_sensor(0x3809, 0x60); + write_cmos_sensor(0x380a, 0x04); + write_cmos_sensor(0x380b, 0xc8); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0x8c); + write_cmos_sensor(0x380e, 0x09); //0x04); + write_cmos_sensor(0x380f, 0xb2); //0xde); + write_cmos_sensor(0x3810, 0x00); + write_cmos_sensor(0x3811, 0x02); //0x08); for FOV same with snapshot + write_cmos_sensor(0x3812, 0x00); + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x03); + write_cmos_sensor(0x3820, 0x80);//improve the normal luminance differences 90->80 11182015 + write_cmos_sensor(0x3821, 0x47);//improve the normal luminance differences67->47 11182015 + write_cmos_sensor(0x4502, 0x50);//improve the normal luminance differences new add for set back to default + write_cmos_sensor(0x382a, 0x03); + write_cmos_sensor(0x4009, 0x05); + write_cmos_sensor(0x4601, 0x80); + write_cmos_sensor(0x5795, 0x00); + write_cmos_sensor(0x5796, 0x10); + write_cmos_sensor(0x5797, 0x10); + write_cmos_sensor(0x5798, 0x73); + write_cmos_sensor(0x5799, 0x73); + write_cmos_sensor(0x579a, 0x00); + write_cmos_sensor(0x579b, 0x28); + write_cmos_sensor(0x579c, 0x00); + write_cmos_sensor(0x579d, 0x16); + write_cmos_sensor(0x579e, 0x06); + write_cmos_sensor(0x579f, 0x20); + write_cmos_sensor(0x57a0, 0x04); + write_cmos_sensor(0x57a1, 0xa0); + write_cmos_sensor(0x366d, 0x00); + write_cmos_sensor(0x5003, 0xc8); + write_cmos_sensor(0x5006, 0x00); + write_cmos_sensor(0x5007, 0x00); + write_cmos_sensor(0x5e10, 0xfc); + write_cmos_sensor(0x0100, 0x01); +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + if (currefps == 150) { + write_cmos_sensor(0x0100, 0x00); + write_cmos_sensor(0x3501, 0x9a); + write_cmos_sensor(0x3502, 0x20); + write_cmos_sensor(0x366e, 0x10); + write_cmos_sensor(0x3714, 0x23); + write_cmos_sensor(0x37c2, 0x04); + write_cmos_sensor(0x3800, 0x00); + write_cmos_sensor(0x3801, 0x00); + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x0c); + write_cmos_sensor(0x3804, 0x0c); + write_cmos_sensor(0x3805, 0xdf); + write_cmos_sensor(0x3806, 0x09); + write_cmos_sensor(0x3807, 0xa3); + write_cmos_sensor(0x3808, 0x0c); + write_cmos_sensor(0x3809, 0xc0); + write_cmos_sensor(0x380a, 0x09); + write_cmos_sensor(0x380b, 0x90); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0x8c); + write_cmos_sensor(0x380e, 0x13);//;09 + write_cmos_sensor(0x380f, 0x64);//;b2 + write_cmos_sensor(0x3810, 0x00); + write_cmos_sensor(0x3811, 0x04); + write_cmos_sensor(0x3812, 0x00); + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x01); + write_cmos_sensor(0x3820, 0x80); + write_cmos_sensor(0x3821, 0x46); + write_cmos_sensor(0x4502, 0x50);//improve the normal luminance differences new add for set back to default + write_cmos_sensor(0x382a, 0x01); + write_cmos_sensor(0x4009, 0x0b); + write_cmos_sensor(0x4601, 0x80); + write_cmos_sensor(0x5795, 0x02); + write_cmos_sensor(0x5796, 0x20); + write_cmos_sensor(0x5797, 0x20); + write_cmos_sensor(0x5798, 0xd5); + write_cmos_sensor(0x5799, 0xd5); + write_cmos_sensor(0x579a, 0x00); + write_cmos_sensor(0x579b, 0x50); + write_cmos_sensor(0x579c, 0x00); + write_cmos_sensor(0x579d, 0x2c); + write_cmos_sensor(0x579e, 0x0c); + write_cmos_sensor(0x579f, 0x40); + write_cmos_sensor(0x57a0, 0x09); + write_cmos_sensor(0x57a1, 0x40); + write_cmos_sensor(0x366d, 0x00); + write_cmos_sensor(0x5003, 0xc8); + write_cmos_sensor(0x5006, 0x00); + write_cmos_sensor(0x5007, 0x00); + write_cmos_sensor(0x5e10, 0xfc); + write_cmos_sensor(0x0100, 0x01); + + } + else + { + write_cmos_sensor(0x0100, 0x00); + write_cmos_sensor(0x3501, 0x9a); + write_cmos_sensor(0x3502, 0x20); + write_cmos_sensor(0x366e, 0x10); + write_cmos_sensor(0x3714, 0x23); + write_cmos_sensor(0x37c2, 0x04); + write_cmos_sensor(0x3800, 0x00); + write_cmos_sensor(0x3801, 0x00); + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x0c); + write_cmos_sensor(0x3804, 0x0c); + write_cmos_sensor(0x3805, 0xdf); + write_cmos_sensor(0x3806, 0x09); + write_cmos_sensor(0x3807, 0xa3); + write_cmos_sensor(0x3808, 0x0c); + write_cmos_sensor(0x3809, 0xc0); + write_cmos_sensor(0x380a, 0x09); + write_cmos_sensor(0x380b, 0x90); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0x8c); + write_cmos_sensor(0x380e, 0x09); + write_cmos_sensor(0x380f, 0xb2); + write_cmos_sensor(0x3810, 0x00); + write_cmos_sensor(0x3811, 0x04); + write_cmos_sensor(0x3812, 0x00); + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x01); + write_cmos_sensor(0x3820, 0x80); + write_cmos_sensor(0x3821, 0x46); + write_cmos_sensor(0x4502, 0x50);//improve the normal luminance differences new add for set back to default + write_cmos_sensor(0x382a, 0x01); + write_cmos_sensor(0x4009, 0x0b); + write_cmos_sensor(0x4601, 0x80); + write_cmos_sensor(0x5795, 0x02); + write_cmos_sensor(0x5796, 0x20); + write_cmos_sensor(0x5797, 0x20); + write_cmos_sensor(0x5798, 0xd5); + write_cmos_sensor(0x5799, 0xd5); + write_cmos_sensor(0x579a, 0x00); + write_cmos_sensor(0x579b, 0x50); + write_cmos_sensor(0x579c, 0x00); + write_cmos_sensor(0x579d, 0x2c); + write_cmos_sensor(0x579e, 0x0c); + write_cmos_sensor(0x579f, 0x40); + write_cmos_sensor(0x57a0, 0x09); + write_cmos_sensor(0x57a1, 0x40); + write_cmos_sensor(0x366d, 0x00); + write_cmos_sensor(0x5003, 0xc8); + write_cmos_sensor(0x5006, 0x00); + write_cmos_sensor(0x5007, 0x00); + write_cmos_sensor(0x5e10, 0xfc); + write_cmos_sensor(0x0100, 0x01); + } + +} +static void vga_setting_120fps(void) +{ + write_cmos_sensor(0x0100, 0x00); + + write_cmos_sensor(0x3501, 0x25); + write_cmos_sensor(0x3502, 0xc0); + write_cmos_sensor(0x366e, 0x08); + write_cmos_sensor(0x3714, 0x27); + write_cmos_sensor(0x37c2, 0x34); + write_cmos_sensor(0x3800, 0x01); + write_cmos_sensor(0x3801, 0x50); + write_cmos_sensor(0x3802, 0x01); + write_cmos_sensor(0x3803, 0x10); + write_cmos_sensor(0x3804, 0x0b); + write_cmos_sensor(0x3805, 0x8f); + write_cmos_sensor(0x3806, 0x08); + write_cmos_sensor(0x3807, 0x9f); + write_cmos_sensor(0x3808, 0x02); + write_cmos_sensor(0x3809, 0x80); + write_cmos_sensor(0x380a, 0x01); + write_cmos_sensor(0x380b, 0xe0); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0x8c); + write_cmos_sensor(0x380e, 0x02); + write_cmos_sensor(0x380f, 0x6c); + write_cmos_sensor(0x3810, 0x00); + write_cmos_sensor(0x3811, 0x07); + write_cmos_sensor(0x3812, 0x00); + write_cmos_sensor(0x3813, 0x03); + write_cmos_sensor(0x3814, 0x07); + write_cmos_sensor(0x3815, 0x01); + write_cmos_sensor(0x3820, 0x90); + write_cmos_sensor(0x3821, 0x67); + write_cmos_sensor(0x4502, 0x50);//improve the normal luminance differences new add for set back to default + write_cmos_sensor(0x382a, 0x07); + write_cmos_sensor(0x4009, 0x05); + write_cmos_sensor(0x4601, 0x40); + write_cmos_sensor(0x5795, 0x00); + write_cmos_sensor(0x5796, 0x10); + write_cmos_sensor(0x5797, 0x10); + write_cmos_sensor(0x5798, 0x73); + write_cmos_sensor(0x5799, 0x73); + write_cmos_sensor(0x579a, 0x00); + write_cmos_sensor(0x579b, 0x00); + write_cmos_sensor(0x579c, 0x00); + write_cmos_sensor(0x579d, 0x00); + write_cmos_sensor(0x579e, 0x05); + write_cmos_sensor(0x579f, 0xa0); + write_cmos_sensor(0x57a0, 0x03); + write_cmos_sensor(0x57a1, 0x20); + write_cmos_sensor(0x366d, 0x11); + write_cmos_sensor(0x5003, 0xc0); + write_cmos_sensor(0x5006, 0x02); + write_cmos_sensor(0x5007, 0x90); + write_cmos_sensor(0x5e10, 0x7c); + + write_cmos_sensor(0x0100, 0x01); + +} +#if 0 +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + capture_setting(currefps); +} +#endif +static void hs_video_setting(void) +{ + LOG_INF("E\n"); + vga_setting_120fps(); + +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + preview_setting(); +} + + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = ((read_cmos_sensor(0x300B) << 8) | read_cmos_sensor(0x300C)); + if (*sensor_id == imgsensor_info.sensor_id) { + if((read_cmos_sensor(0x302A)) == 0xB0){ + ov8856version = OV8856R1A; + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x, ov8856version = %d(0=r2a,1=r1a)\n", imgsensor.i2c_write_id,*sensor_id,ov8856version); + return ERROR_NONE; + } + else if((read_cmos_sensor(0x302A)) == 0xB1){ + ov8856version = OV8856R2A; + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x, ov8856version = %d(0=r2a,1=r1a)\n", imgsensor.i2c_write_id,*sensor_id,ov8856version); + return ERROR_NONE; + } + else{ + LOG_INF("read ov8856 R1A R2A bate fail\n"); + return ERROR_SENSOR_CONNECT_FAIL; + } + } + LOG_INF("Read sensor id fail,write_id:0x%x, id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint16 sensor_id = 0; + //LOG_INF("PLATFORM:MT6595,MIPI 4LANE\n"); + //LOG_INF("preview 1280*960@30fps,864Mbps/lane; video 1280*960@30fps,864Mbps/lane; capture 5M@30fps,864Mbps/lane\n"); + LOG_INF("read_cmos_sensor(0x302A): 0x%x\n", read_cmos_sensor(0x302A)); + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = ((read_cmos_sensor(0x300B) << 8) | read_cmos_sensor(0x300C)); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + mdelay(30); + #ifdef OV8856R1AOTP + // LOG_INF("Apply the sensor OTP\n"); + // struct otp_struct *otp_ptr = (struct otp_struct *)kzalloc(sizeof(struct otp_struct), GFP_KERNEL); + // read_otp(otp_ptr); + // apply_otp(otp_ptr); + // kfree(otp_ptr); + #endif + + ov8856_otp_update(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.shutter = 0x2D00; + imgsensor.gain = 0x100; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + set_mirror_flip(imgsensor.mirror); + mdelay(10); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//15fps + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap1's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap1.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + + capture_setting(imgsensor.current_fps); + mdelay(10); + + if(imgsensor.test_pattern == KAL_TRUE) + { + //write_cmos_sensor(0x5002,0x00); + write_cmos_sensor(0x5000,(read_cmos_sensor(0x5000)&0xBF)|0x00 ); + } + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + mdelay(10); + + + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + set_mirror_flip(imgsensor.mirror); + mdelay(10); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + set_mirror_flip(imgsensor.mirror); + mdelay(10); + + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + //case MSDK_SCENARIO_ID_CAMERA_ZSD: + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x5E00, 0x80); + write_cmos_sensor(0x5000,(read_cmos_sensor(0x5000)&0xBF)|0x00 ); + + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x5E00, 0x00); + write_cmos_sensor(0x5000,(read_cmos_sensor(0x5000)&0xBF)|0x040 ); + + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + //unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + + +UINT32 OV8856_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV5693_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/ov8856mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/ov8856mipiraw_Sensor.h new file mode 100755 index 0000000000000000000000000000000000000000..815af3986e63e0749f23b97af797c83c79c511e2 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8856_mipi_raw/ov8856mipiraw_Sensor.h @@ -0,0 +1,126 @@ +/***************************************************************************** + * + * Filename: + * --------- + * OV8856mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * PengtaoFan + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _OV8856MIPI_SENSOR_H +#define _OV8856MIPI_SENSOR_H + +//±íʾsensorµÄ¼¸ÖÖ¹¤×÷ģʽ״̬£ºinit preview capture video hvideo svideo +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +//±íʾ¼¸ÖÖ£¨²»Í¬¹¤×÷ģʽ״̬Ï£©µÄsensor²ÎÊýÐÅÏ¢ +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +//±íʾ£¨µ±Ç°×´Ì¬¹¤×÷ģʽ£©ÏµÄsensor²ÎÊýÐÅÏ¢ +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +//sensor»ù±¾ÐÅÏ¢£¬datasheetÉϵÄÐÅÏ¢ +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint16 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..05595bf71a4ab471720d7f12f37a6eb8295f728e --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + + +obj-y += ov8858mipiraw_Sensor.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/ov8858mipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/ov8858mipiraw_Sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..58859601205bcfeb43fbe7f1ad6fba674411e397 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/ov8858mipiraw_Sensor.c @@ -0,0 +1,2429 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * OV8858mipiraw_sensor.c + * + * Project: + * -------- + * ALPS MT6580 2lane ov8858r2a + * + * Description: + * ------------ + * Source code of Sensor driver + * PengtaoFan + * 0528:修改get_info,??mipi ??? * 0604:å¢?init preview 延时??0ms + * 0604:??­init settingä¸?stream on,?otp??è®? + * 0608:??°ov???setting + * 0703:for 修改?non continue mode 4800 + * 0703:for crc test 0x5002=00 + * ---RD ??????? * 0714 ??Â¥capture setting full size@30fps 24fps 15fps + * 15072115172729: ??Â¥nick??full size 30fps setting,for ???size ä¸???®é?? + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" +#include "kd_camera_feature.h" + +#include "ov8858mipiraw_Sensor.h" + + +#define SENSORDB LOG_INF + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "OV88582LANE" +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) +/**************************** Modify end *******************************************/ + +typedef enum { + OV8858R2A, + OV8858R1A +}OV8858_VERSION; + +OV8858_VERSION ov8858version = OV8858R2A; +enum boot_mode_t bm; + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = OV8858_SENSOR_ID, //record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0xc2ded17b, //checksum value for Camera Auto Test + + .pre = { + .pclk = 144000000, //record different mode's pclk + .linelength = 1928, //record different mode's linelength + .framelength = 2488, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1632, //record different mode's width of grabwindow + .grabwindow_height = 1224, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk = 144000000, + .linelength = 1956, + .framelength = 2530, + .startx = 0, + .starty = 0, + .grabwindow_width = 3264, + .grabwindow_height = 2448, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 300, + }, + .cap1 = { //capture for PIP 15fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 72000000, + .linelength = 1940, + .framelength = 2474, + .startx = 0, + .starty = 0, + .grabwindow_width = 3264, + .grabwindow_height = 2448, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 150, + }, + .cap2 = { //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 144000000, + .linelength = 2344, + .framelength = 2556, + .startx = 0, + .starty = 0, + .grabwindow_width = 3264, + .grabwindow_height = 2448, + .mipi_data_lp2hs_settle_dc = 30, + .max_framerate = 240, + }, + .normal_video = { + .pclk = 144000000, //record different mode's pclk + .linelength = 1928, //record different mode's linelength + .framelength = 2488, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1632, //record different mode's width of grabwindow + .grabwindow_height = 1224, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .hs_video = { + .pclk = 144000000, //record different mode's pclk,Pengtao Modify + .linelength = 2306, //record different mode's linelength + .framelength = 520, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 640, //record different mode's width of grabwindow + .grabwindow_height = 480, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 1200, + }, + .slim_video = { + .pclk = 144000000, //record different mode's pclk + .linelength = 1928, //record different mode's linelength + .framelength = 2488, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1632, //record different mode's width of grabwindow + .grabwindow_height = 1224, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 30, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .margin = 4, //sensor framelength & shutter margin + .min_shutter = 4, //min shutter + .max_frame_length = 0x90f7,//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num ,don't support Slow motion + + .cap_delay_frame = 3, //enter capture delay frame num + .pre_delay_frame = 3, //enter preview delay frame num + .video_delay_frame = 3, //enter video delay frame num + .hs_video_delay_frame = 3, //enter high speed video delay frame num + .slim_video_delay_frame = 3,//enter slim video delay frame num + + .isp_driving_current = ISP_DRIVING_4MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO, + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW8_B,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_2_LANE,//mipi lane num + .i2c_addr_table = {0x42, 0x6c, 0xff},//record sensor support all write id addr, only supprt 4must end with 0xff +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x4C00, //current shutter + .gain = 0x200, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0,//record current sensor's i2c write id +}; + + +/* Sensor output window information*/ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{{ 3296, 2480, 12, 12, 3272, 2456, 1632, 1228, 0, 0, 1632, 1224, 0, 0, 1632, 1224}, // Preview + { 3296, 2480, 12, 12, 3272, 2456, 3264, 2452, 0, 0, 3264, 2448, 0, 0, 3264, 2448}, // capture + { 3296, 2480, 12, 12, 3272, 2456, 3264, 2452, 0, 0, 3264, 2448, 0, 0, 3264, 2448}, // video + { 3296, 2480, 12, 12, 3272, 2456, 640, 480, 0, 0, 640, 480, 0, 0, 640, 480}, //hight speed video + { 3296, 2480, 12, 12, 3272, 2456, 3264, 2452, 0, 0, 1632, 1224, 0, 0, 1632, 1224}};// slim video + + +SENSOR_DPCM_TYPE_ENUM imgsensor_dpcm_info_ov8858[10] = +{COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE,COMP8_NONE}; + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; +} + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + /* you can set dummy by imgsensor.dummy_line and imgsensor.dummy_pixel, or you can set dummy by imgsensor.frame_length and imgsensor.line_length */ + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8) & 0xFF); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x380c, (imgsensor.line_length >> 8) & 0xFF); + write_cmos_sensor(0x380d, imgsensor.line_length & 0xFF); + +} /* set_dummy */ + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + SENSORDB("framerate = %d, min framelength should enable? %d\n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + +#if 0 +static void write_shutter(kal_uint16 shutter) +{ + kal_uint16 realtime_fps = 0; + + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + shutter = (shutter >> 1) << 1; + imgsensor.frame_length = (imgsensor.frame_length >> 1) << 1; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)& 0xFF); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + } else { + // Extend frame length + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)& 0xFF); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + + // Update Shutter + write_cmos_sensor(0x3500, (shutter>>12) & 0x0F); + write_cmos_sensor(0x3501, (shutter>>4) & 0xFF); + write_cmos_sensor(0x3502, (shutter<<4) & 0xF0); + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + + //SENSORDB("frame_length = %d ", frame_length); + +} /* write_shutter */ +#endif + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + kal_uint16 realtime_fps = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + //write_shutter(shutter); + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.frame_length = (imgsensor.frame_length>>1)<<1; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + shutter = (shutter>>1)<<1; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)& 0xFF); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + } else { + // Extend frame length + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)& 0xFF); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + } + + // Update Shutter + write_cmos_sensor(0x3502, (shutter << 4) & 0xF0); + write_cmos_sensor(0x3501, (shutter >> 4) & 0xFF); + write_cmos_sensor(0x3500, (shutter >> 12) & 0x0F); + LOG_INF("Exit! shutter =%d, framelength =%d, for flicker realtime_fps=%d\n", shutter,imgsensor.frame_length,realtime_fps); + +} +#if 0 +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0000; + + reg_gain = gain*2; + //reg_gain = reg_gain & 0xFFFF; + return (kal_uint16)reg_gain; +} +#endif +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; +// LOG_INF("set_gain %d \n", gain); + if (gain < BASEGAIN || gain > 10 * BASEGAIN) { + SENSORDB("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 10 * BASEGAIN) + gain = 10 * BASEGAIN; + } + + //reg_gain = gain2reg(gain); + reg_gain = gain*2; + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor(0x3508, (reg_gain>>8)); + write_cmos_sensor(0x3509, (reg_gain&0xFF)); + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length first + write_cmos_sensor(0x380e, (imgsensor.frame_length >> 8)& 0xFF); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + + write_cmos_sensor(0x3502, (le << 4) & 0xFF); + write_cmos_sensor(0x3501, (le >> 4) & 0xFF); + write_cmos_sensor(0x3500, (le >> 12) & 0x0F); + + write_cmos_sensor(0x3508, (se << 4) & 0xFF); + write_cmos_sensor(0x3507, (se >> 4) & 0xFF); + write_cmos_sensor(0x3506, (se >> 12) & 0x0F); + + set_gain(gain); + } + +} + + +#if 0 +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xF9) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x06)); + break; + case IMAGE_H_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xF9) | 0x00)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x00)); + break; + case IMAGE_V_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xF9) | 0x06)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x06)); + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x3820,((read_cmos_sensor(0x3820) & 0xF9) | 0x06)); + write_cmos_sensor(0x3821,((read_cmos_sensor(0x3821) & 0xF9) | 0x00)); + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} +#endif +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ +static void sensor_init(void) +{ + LOG_INF("E\n"); + //OV8858 R2A setting + //3.1 Initialization (Global Setting) + //XVCLK=24Mhz, SCLK=72Mhz, MIPI 720Mbps, DACCLK=180Mhz + write_cmos_sensor(0x103 , 0x01); + mdelay(5); + write_cmos_sensor(0x100 , 0x00); + write_cmos_sensor(0x302 , 0x1e); + write_cmos_sensor(0x303 , 0x00); + write_cmos_sensor(0x304 , 0x03); + write_cmos_sensor(0x30e , 0x02); + write_cmos_sensor(0x30f , 0x04); + write_cmos_sensor(0x312 , 0x03); + write_cmos_sensor(0x31e , 0x0c); + write_cmos_sensor(0x3600, 0x00); + write_cmos_sensor(0x3601, 0x00); + write_cmos_sensor(0x3602, 0x00); + write_cmos_sensor(0x3603, 0x00); + write_cmos_sensor(0x3604, 0x22); + write_cmos_sensor(0x3605, 0x20); + write_cmos_sensor(0x3606, 0x00); + write_cmos_sensor(0x3607, 0x20); + write_cmos_sensor(0x3608, 0x11); + write_cmos_sensor(0x3609, 0x28); + write_cmos_sensor(0x360a, 0x00); + write_cmos_sensor(0x360b, 0x05); + write_cmos_sensor(0x360c, 0xd4); + write_cmos_sensor(0x360d, 0x40); + write_cmos_sensor(0x360e, 0x0c); + write_cmos_sensor(0x360f, 0x20); + write_cmos_sensor(0x3610, 0x07); + write_cmos_sensor(0x3611, 0x20); + write_cmos_sensor(0x3612, 0x88); + write_cmos_sensor(0x3613, 0x80); + write_cmos_sensor(0x3614, 0x58); + write_cmos_sensor(0x3615, 0x00); + write_cmos_sensor(0x3616, 0x4a); + write_cmos_sensor(0x3617, 0x40); //90 + write_cmos_sensor(0x3618, 0x5a); + write_cmos_sensor(0x3619, 0x70); + write_cmos_sensor(0x361a, 0x99); + write_cmos_sensor(0x361b, 0x0a); + write_cmos_sensor(0x361c, 0x07); + write_cmos_sensor(0x361d, 0x00); + write_cmos_sensor(0x361e, 0x00); + write_cmos_sensor(0x361f, 0x00); + write_cmos_sensor(0x3638, 0xff); + write_cmos_sensor(0x3633, 0x0f); + write_cmos_sensor(0x3634, 0x0f); + write_cmos_sensor(0x3635, 0x0f); + write_cmos_sensor(0x3636, 0x12); + write_cmos_sensor(0x3645, 0x13); + write_cmos_sensor(0x3646, 0x83); + write_cmos_sensor(0x364a, 0x07); + write_cmos_sensor(0x3015, 0x00); + write_cmos_sensor(0x3018, 0x32); //32 : 2LANE , 72 : 4lane + write_cmos_sensor(0x3020, 0x93); + write_cmos_sensor(0x3022, 0x01); +if ( bm == FACTORY_BOOT || bm == ATE_FACTORY_BOOT ){ + write_cmos_sensor(0x3031, 0x0a); +}else { + write_cmos_sensor(0x3031, 0x08); +} + write_cmos_sensor(0x3034, 0x00); + write_cmos_sensor(0x3106, 0x01); + write_cmos_sensor(0x3305, 0xf1); + write_cmos_sensor(0x3308, 0x00); + write_cmos_sensor(0x3309, 0x28); + write_cmos_sensor(0x330a, 0x00); + write_cmos_sensor(0x330b, 0x20); + write_cmos_sensor(0x330c, 0x00); + write_cmos_sensor(0x330d, 0x00); + write_cmos_sensor(0x330e, 0x00); + write_cmos_sensor(0x330f, 0x40); + write_cmos_sensor(0x3307, 0x04); + write_cmos_sensor(0x3500, 0x00); + write_cmos_sensor(0x3501, 0x4d); + write_cmos_sensor(0x3502, 0x40); + write_cmos_sensor(0x3503, 0x80); + write_cmos_sensor(0x3505, 0x80); + write_cmos_sensor(0x3508, 0x02); + write_cmos_sensor(0x3509, 0x00); + write_cmos_sensor(0x350c, 0x00); + write_cmos_sensor(0x350d, 0x80); + write_cmos_sensor(0x3510, 0x00); + write_cmos_sensor(0x3511, 0x02); + write_cmos_sensor(0x3512, 0x00); + write_cmos_sensor(0x3700, 0x18); + write_cmos_sensor(0x3701, 0x0c); + write_cmos_sensor(0x3702, 0x28); + write_cmos_sensor(0x3703, 0x19); + write_cmos_sensor(0x3704, 0x14); + write_cmos_sensor(0x3705, 0x00); + write_cmos_sensor(0x3706, 0x82); + write_cmos_sensor(0x3707, 0x04); + write_cmos_sensor(0x3708, 0x24); + write_cmos_sensor(0x3709, 0x33); + write_cmos_sensor(0x370a, 0x01); + write_cmos_sensor(0x370b, 0x82); + write_cmos_sensor(0x370c, 0x04); + write_cmos_sensor(0x3718, 0x12); + write_cmos_sensor(0x3719, 0x31); + write_cmos_sensor(0x3712, 0x42); + write_cmos_sensor(0x3714, 0x24); + write_cmos_sensor(0x371e, 0x19); + write_cmos_sensor(0x371f, 0x40); + write_cmos_sensor(0x3720, 0x05); + write_cmos_sensor(0x3721, 0x05); + write_cmos_sensor(0x3724, 0x06); + write_cmos_sensor(0x3725, 0x01); + write_cmos_sensor(0x3726, 0x06); + write_cmos_sensor(0x3728, 0x05); + write_cmos_sensor(0x3729, 0x02); + write_cmos_sensor(0x372a, 0x03); + write_cmos_sensor(0x372b, 0x53); + write_cmos_sensor(0x372c, 0xa3); + write_cmos_sensor(0x372d, 0x53); + write_cmos_sensor(0x372e, 0x06); + write_cmos_sensor(0x372f, 0x10); + write_cmos_sensor(0x3730, 0x01); + write_cmos_sensor(0x3731, 0x06); + write_cmos_sensor(0x3732, 0x14); + write_cmos_sensor(0x3733, 0x10); + write_cmos_sensor(0x3734, 0x40); + write_cmos_sensor(0x3736, 0x20); + write_cmos_sensor(0x373a, 0x05); + write_cmos_sensor(0x373b, 0x06); + write_cmos_sensor(0x373c, 0x0a); + write_cmos_sensor(0x373e, 0x03); + write_cmos_sensor(0x3750, 0x0a); + write_cmos_sensor(0x3751, 0x0e); + write_cmos_sensor(0x3755, 0x10); + write_cmos_sensor(0x3758, 0x00); + write_cmos_sensor(0x3759, 0x4c); + write_cmos_sensor(0x375a, 0x06); + write_cmos_sensor(0x375b, 0x13); + write_cmos_sensor(0x375c, 0x20); + write_cmos_sensor(0x375d, 0x02); + write_cmos_sensor(0x375e, 0x00); + write_cmos_sensor(0x375f, 0x14); + write_cmos_sensor(0x3768, 0x22); + write_cmos_sensor(0x3769, 0x44); + write_cmos_sensor(0x376a, 0x44); + write_cmos_sensor(0x3761, 0x00); + write_cmos_sensor(0x3762, 0x00); + write_cmos_sensor(0x3763, 0x00); + write_cmos_sensor(0x3766, 0xff); + write_cmos_sensor(0x376b, 0x00); + write_cmos_sensor(0x3772, 0x23); + write_cmos_sensor(0x3773, 0x02); + write_cmos_sensor(0x3774, 0x16); + write_cmos_sensor(0x3775, 0x12); + write_cmos_sensor(0x3776, 0x04); + write_cmos_sensor(0x3777, 0x00); + write_cmos_sensor(0x3778, 0x17); + write_cmos_sensor(0x37a0, 0x44); + write_cmos_sensor(0x37a1, 0x3d); + write_cmos_sensor(0x37a2, 0x3d); + write_cmos_sensor(0x37a3, 0x00); + write_cmos_sensor(0x37a4, 0x00); + write_cmos_sensor(0x37a5, 0x00); + write_cmos_sensor(0x37a6, 0x00); + write_cmos_sensor(0x37a7, 0x44); + write_cmos_sensor(0x37a8, 0x4c); + write_cmos_sensor(0x37a9, 0x4c); + write_cmos_sensor(0x3760, 0x00); + write_cmos_sensor(0x376f, 0x01); + write_cmos_sensor(0x37aa, 0x44); + write_cmos_sensor(0x37ab, 0x2e); + write_cmos_sensor(0x37ac, 0x2e); + write_cmos_sensor(0x37ad, 0x33); + write_cmos_sensor(0x37ae, 0x0d); + write_cmos_sensor(0x37af, 0x0d); + write_cmos_sensor(0x37b0, 0x00); + write_cmos_sensor(0x37b1, 0x00); + write_cmos_sensor(0x37b2, 0x00); + write_cmos_sensor(0x37b3, 0x42); + write_cmos_sensor(0x37b4, 0x42); + write_cmos_sensor(0x37b5, 0x31); + write_cmos_sensor(0x37b6, 0x00); + write_cmos_sensor(0x37b7, 0x00); + write_cmos_sensor(0x37b8, 0x00); + write_cmos_sensor(0x37b9, 0xff); + write_cmos_sensor(0x3800, 0x00); + write_cmos_sensor(0x3801, 0x0c); + write_cmos_sensor(0x3802, 0x00); + write_cmos_sensor(0x3803, 0x0c); + write_cmos_sensor(0x3804, 0x0c); + write_cmos_sensor(0x3805, 0xd3); + write_cmos_sensor(0x3806, 0x09); + write_cmos_sensor(0x3807, 0xa3); + write_cmos_sensor(0x3808, 0x06); + write_cmos_sensor(0x3809, 0x60); + write_cmos_sensor(0x380a, 0x04); + write_cmos_sensor(0x380b, 0xc8); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0x88); + write_cmos_sensor(0x380e, 0x04); + write_cmos_sensor(0x380f, 0xdc); + write_cmos_sensor(0x3810, 0x00); + write_cmos_sensor(0x3811, 0x04); + write_cmos_sensor(0x3813, 0x02); + write_cmos_sensor(0x3814, 0x03); + write_cmos_sensor(0x3815, 0x01); + write_cmos_sensor(0x3820, 0x00); //mirror + write_cmos_sensor(0x3821, 0x67); //flip //0x67 + write_cmos_sensor(0x382a, 0x03); + write_cmos_sensor(0x382b, 0x01); + write_cmos_sensor(0x3830, 0x08); + write_cmos_sensor(0x3836, 0x02); + write_cmos_sensor(0x3837, 0x18); + write_cmos_sensor(0x3841, 0xff); + write_cmos_sensor(0x3846, 0x48); + write_cmos_sensor(0x3d85, 0x16); + write_cmos_sensor(0x3d8c, 0x73); + write_cmos_sensor(0x3d8d, 0xde); + write_cmos_sensor(0x3f08, 0x08); + write_cmos_sensor(0x3f0a, 0x00); + write_cmos_sensor(0x4000, 0xf1); + write_cmos_sensor(0x4001, 0x10); + write_cmos_sensor(0x4005, 0x10); + write_cmos_sensor(0x4002, 0x27); + write_cmos_sensor(0x4009, 0x81); + write_cmos_sensor(0x400b, 0x0c); + write_cmos_sensor(0x4011, 0x20); //add + write_cmos_sensor(0x401b, 0x00); + write_cmos_sensor(0x401d, 0x00); + write_cmos_sensor(0x4020, 0x00); + write_cmos_sensor(0x4021, 0x04); + write_cmos_sensor(0x4022, 0x06); + write_cmos_sensor(0x4023, 0x00); + write_cmos_sensor(0x4024, 0x0f); + write_cmos_sensor(0x4025, 0x2a); + write_cmos_sensor(0x4026, 0x0f); + write_cmos_sensor(0x4027, 0x2b); + write_cmos_sensor(0x4028, 0x00); + write_cmos_sensor(0x4029, 0x02); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x04); + write_cmos_sensor(0x402c, 0x00); + write_cmos_sensor(0x402d, 0x02); + write_cmos_sensor(0x402e, 0x04); + write_cmos_sensor(0x402f, 0x04); + write_cmos_sensor(0x401f, 0x00); + write_cmos_sensor(0x4034, 0x3f); + write_cmos_sensor(0x403d, 0x04); + write_cmos_sensor(0x4300, 0xff); + write_cmos_sensor(0x4301, 0x00); + write_cmos_sensor(0x4302, 0x0f); + write_cmos_sensor(0x4316, 0x00); + write_cmos_sensor(0x4500, 0x58); + write_cmos_sensor(0x4503, 0x18); + write_cmos_sensor(0x4600, 0x00); + write_cmos_sensor(0x4601, 0xcb); + + write_cmos_sensor(0x4800, 0x24); // MIPI line sync enable + + write_cmos_sensor(0x481f, 0x32); + write_cmos_sensor(0x4837, 0x16); + write_cmos_sensor(0x4850, 0x10); + write_cmos_sensor(0x4851, 0x32); + write_cmos_sensor(0x4b00, 0x2a); + write_cmos_sensor(0x4b0d, 0x00); + write_cmos_sensor(0x4d00, 0x04); + write_cmos_sensor(0x4d01, 0x18); + write_cmos_sensor(0x4d02, 0xc3); + write_cmos_sensor(0x4d03, 0xff); + write_cmos_sensor(0x4d04, 0xff); + write_cmos_sensor(0x4d05, 0xff); + write_cmos_sensor(0x5000, 0x7e); + write_cmos_sensor(0x5001, 0x01); + write_cmos_sensor(0x5002, 0x08); + write_cmos_sensor(0x5003, 0x20); + write_cmos_sensor(0x5046, 0x12); + write_cmos_sensor(0x5780, 0x3e); + write_cmos_sensor(0x5781, 0x0f); + write_cmos_sensor(0x5782, 0x44); + write_cmos_sensor(0x5783, 0x02); + write_cmos_sensor(0x5784, 0x01); + write_cmos_sensor(0x5785, 0x00); + write_cmos_sensor(0x5786, 0x00); + write_cmos_sensor(0x5787, 0x04); + write_cmos_sensor(0x5788, 0x02); + write_cmos_sensor(0x5789, 0x0f); + write_cmos_sensor(0x578a, 0xfd); + write_cmos_sensor(0x578b, 0xf5); + write_cmos_sensor(0x578c, 0xf5); + write_cmos_sensor(0x578d, 0x03); + write_cmos_sensor(0x578e, 0x08); + write_cmos_sensor(0x578f, 0x0c); + write_cmos_sensor(0x5790, 0x08); + write_cmos_sensor(0x5791, 0x04); + write_cmos_sensor(0x5792, 0x00); + write_cmos_sensor(0x5793, 0x52); + write_cmos_sensor(0x5794, 0xa3); + write_cmos_sensor(0x5871, 0x0d); + write_cmos_sensor(0x5870, 0x18); + write_cmos_sensor(0x586e, 0x10); + write_cmos_sensor(0x586f, 0x08); + write_cmos_sensor(0x58f8, 0x3d); //add + write_cmos_sensor(0x5901, 0x00); + write_cmos_sensor(0x5b00, 0x02); + write_cmos_sensor(0x5b01, 0x10); + write_cmos_sensor(0x5b02, 0x03); + write_cmos_sensor(0x5b03, 0xcf); + write_cmos_sensor(0x5b05, 0x6c); + write_cmos_sensor(0x5e00, 0x00); + write_cmos_sensor(0x5e01, 0x41); + write_cmos_sensor(0x382d, 0x7f); + write_cmos_sensor(0x4825, 0x3a); + write_cmos_sensor(0x4826, 0x40); + write_cmos_sensor(0x4808, 0x25); + write_cmos_sensor(0x3763, 0x18); + write_cmos_sensor(0x3768, 0xcc); + write_cmos_sensor(0x470b, 0x28); + write_cmos_sensor(0x4202, 0x00); + write_cmos_sensor(0x400d, 0x10); + write_cmos_sensor(0x4040, 0x07); //04 + write_cmos_sensor(0x403e, 0x08); //04 + write_cmos_sensor(0x4041, 0xc6); + write_cmos_sensor(0x3007, 0x80); + write_cmos_sensor(0x400a, 0x01); + /* + write_cmos_sensor(0x4009, 0x83); + write_cmos_sensor(0x4020, 0x00); + write_cmos_sensor(0x4021, 0x04); + write_cmos_sensor(0x4022, 0x04); + write_cmos_sensor(0x4023, 0xb9); + write_cmos_sensor(0x4024, 0x05); + write_cmos_sensor(0x4025, 0x2a); + write_cmos_sensor(0x4026, 0x05); + write_cmos_sensor(0x4027, 0x2b); + write_cmos_sensor(0x4028, 0x00); + write_cmos_sensor(0x4029, 0x02); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x04); + write_cmos_sensor(0x402c, 0x02); + write_cmos_sensor(0x402d, 0x02); + write_cmos_sensor(0x402e, 0x08); + write_cmos_sensor(0x402f, 0x02); + */ +// write_cmos_sensor(0x100 , 0x01); + +// mdelay(50); +} /* sensor_init */ + + +static void preview_setting(void) +{ + LOG_INF("E\n"); + +//3.2 Raw 10bit 1632x1224 30fps 2lane 720M bps/lane +//;XVCLK=24Mhz, SCLK=72Mhz, MIPI 720Mbps, DACCLK=180Mhz, Tline = 8.925926us + write_cmos_sensor(0x0100, 0x00); + mdelay(5); + write_cmos_sensor(0x0302, 0x1e); + write_cmos_sensor(0x030e, 0x00); + write_cmos_sensor(0x0312, 0x01); + write_cmos_sensor(0x3015, 0x01); + write_cmos_sensor(0x3501, 0x4d); + write_cmos_sensor(0x3502, 0x40); + write_cmos_sensor(0x3700, 0x30); + write_cmos_sensor(0x3701, 0x18); + write_cmos_sensor(0x3702, 0x50); + write_cmos_sensor(0x3703, 0x32); + write_cmos_sensor(0x3704, 0x28); + write_cmos_sensor(0x3707, 0x08); + write_cmos_sensor(0x3708, 0x48); + write_cmos_sensor(0x3709, 0x66); + write_cmos_sensor(0x370c, 0x07); + write_cmos_sensor(0x3718, 0x14); + write_cmos_sensor(0x3712, 0x44); + write_cmos_sensor(0x371e, 0x31); + write_cmos_sensor(0x371f, 0x7f); + write_cmos_sensor(0x3720, 0x0a); + write_cmos_sensor(0x3721, 0x0a); + write_cmos_sensor(0x3724, 0x0c); + write_cmos_sensor(0x3725, 0x02); + write_cmos_sensor(0x3726, 0x0c); + write_cmos_sensor(0x3728, 0x0a); + write_cmos_sensor(0x3729, 0x03); + write_cmos_sensor(0x372a, 0x06); + write_cmos_sensor(0x372b, 0xa6); + write_cmos_sensor(0x372c, 0xa6); + write_cmos_sensor(0x372d, 0xa6); + write_cmos_sensor(0x372e, 0x0c); + write_cmos_sensor(0x372f, 0x20); + write_cmos_sensor(0x3730, 0x02); + write_cmos_sensor(0x3731, 0x0c); + write_cmos_sensor(0x3732, 0x28); + write_cmos_sensor(0x3736, 0x30); + write_cmos_sensor(0x373a, 0x0a); + write_cmos_sensor(0x373b, 0x0b); + write_cmos_sensor(0x373c, 0x14); + write_cmos_sensor(0x373e, 0x06); + write_cmos_sensor(0x375a, 0x0c); + write_cmos_sensor(0x375b, 0x26); + write_cmos_sensor(0x375d, 0x04); + write_cmos_sensor(0x375f, 0x28); + write_cmos_sensor(0x3768, 0xcc); + write_cmos_sensor(0x3769, 0x44); + write_cmos_sensor(0x376a, 0x44); + write_cmos_sensor(0x3772, 0x46); + write_cmos_sensor(0x3773, 0x04); + write_cmos_sensor(0x3774, 0x2c); + write_cmos_sensor(0x3775, 0x13); + write_cmos_sensor(0x3776, 0x08); + write_cmos_sensor(0x3778, 0x17); + write_cmos_sensor(0x37a0, 0x88); + write_cmos_sensor(0x37a1, 0x7a); + write_cmos_sensor(0x37a2, 0x7a); + write_cmos_sensor(0x37a7, 0x88); + write_cmos_sensor(0x37a8, 0x98); + write_cmos_sensor(0x37a9, 0x98); + write_cmos_sensor(0x37aa, 0x88); + write_cmos_sensor(0x37ab, 0x5c); + write_cmos_sensor(0x37ac, 0x5c); + write_cmos_sensor(0x37ad, 0x55); + write_cmos_sensor(0x37ae, 0x19); + write_cmos_sensor(0x37af, 0x19); + write_cmos_sensor(0x37b3, 0x84); + write_cmos_sensor(0x37b4, 0x84); + write_cmos_sensor(0x37b5, 0x60); + write_cmos_sensor(0x3808, 0x06); + write_cmos_sensor(0x3809, 0x60); + write_cmos_sensor(0x380a, 0x04); + write_cmos_sensor(0x380b, 0xc8); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0x88); + write_cmos_sensor(0x380e, 0x09); + write_cmos_sensor(0x380f, 0xb8); + write_cmos_sensor(0x3814, 0x03); + write_cmos_sensor(0x3821, 0x67); + write_cmos_sensor(0x382a, 0x03); + write_cmos_sensor(0x382b, 0x01); + write_cmos_sensor(0x3830, 0x08); + write_cmos_sensor(0x3836, 0x02); + write_cmos_sensor(0x3f08, 0x10); + write_cmos_sensor(0x4001, 0x10); + write_cmos_sensor(0x4022, 0x06); + write_cmos_sensor(0x4023, 0x00); + write_cmos_sensor(0x4025, 0x2a); + write_cmos_sensor(0x4027, 0x2b); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x04); + write_cmos_sensor(0x402e, 0x04); + write_cmos_sensor(0x402f, 0x04); + write_cmos_sensor(0x4600, 0x00); + write_cmos_sensor(0x4601, 0xcb); + write_cmos_sensor(0x4837, 0x16); + write_cmos_sensor(0x5901, 0x00); + write_cmos_sensor(0x382d, 0x7f); + write_cmos_sensor(0x3031, 0x08);/* 8 bits */ + write_cmos_sensor(0x4316, 0x00);/* DPCM off */ + write_cmos_sensor(0x0100, 0x01); + mdelay(10); + +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + if (currefps == 300) { + +//@@3264*2448 30fps 2lane 1.25Gbps/lane +//;;MIPI=1.25Gbps/lane, SysClk=144Mhz,Dac Clock=360Mhz +//;;1940x2556x30 +//100 99 3264 2448 ; Resolution + write_cmos_sensor(0x0100, 0x00); + write_cmos_sensor(0x0302, 0x2e); + write_cmos_sensor(0x030e, 0x00); + write_cmos_sensor(0x0312, 0x01); + write_cmos_sensor(0x3015, 0x01); + write_cmos_sensor(0x3501, 0x9a); + write_cmos_sensor(0x3502, 0x20); + write_cmos_sensor(0x3700, 0x30); + write_cmos_sensor(0x3701, 0x18); + write_cmos_sensor(0x3702, 0x50); + write_cmos_sensor(0x3703, 0x32); + write_cmos_sensor(0x3704, 0x28); + write_cmos_sensor(0x3707, 0x08); + write_cmos_sensor(0x3708, 0x48); + write_cmos_sensor(0x3709, 0x66); + write_cmos_sensor(0x370c, 0x07); + write_cmos_sensor(0x3718, 0x14); + write_cmos_sensor(0x3712, 0x44); + write_cmos_sensor(0x371e, 0x31); + write_cmos_sensor(0x371f, 0x7f); + write_cmos_sensor(0x3720, 0x0a); + write_cmos_sensor(0x3721, 0x0a); + write_cmos_sensor(0x3724, 0x0c); + write_cmos_sensor(0x3725, 0x02); + write_cmos_sensor(0x3726, 0x0c); + write_cmos_sensor(0x3728, 0x0a); + write_cmos_sensor(0x3729, 0x03); + write_cmos_sensor(0x372a, 0x06); + write_cmos_sensor(0x372b, 0xa6); + write_cmos_sensor(0x372c, 0xa6); + write_cmos_sensor(0x372d, 0xa6); + write_cmos_sensor(0x372e, 0x0c); + write_cmos_sensor(0x372f, 0x20); + write_cmos_sensor(0x3730, 0x02); + write_cmos_sensor(0x3731, 0x0c); + write_cmos_sensor(0x3732, 0x28); + write_cmos_sensor(0x3736, 0x30); + write_cmos_sensor(0x373a, 0x0a); + write_cmos_sensor(0x373b, 0x0b); + write_cmos_sensor(0x373c, 0x14); + write_cmos_sensor(0x373e, 0x06); + write_cmos_sensor(0x375a, 0x0c); + write_cmos_sensor(0x375b, 0x26); + write_cmos_sensor(0x375d, 0x04); + write_cmos_sensor(0x375f, 0x28); + write_cmos_sensor(0x3768, 0xcc); + write_cmos_sensor(0x3769, 0x44); + write_cmos_sensor(0x376a, 0x44); + write_cmos_sensor(0x3772, 0x46); + write_cmos_sensor(0x3773, 0x04); + write_cmos_sensor(0x3774, 0x2c); + write_cmos_sensor(0x3775, 0x13); + write_cmos_sensor(0x3776, 0x08); + write_cmos_sensor(0x3778, 0x17); + write_cmos_sensor(0x37a0, 0x88); + write_cmos_sensor(0x37a1, 0x7a); + write_cmos_sensor(0x37a2, 0x7a); + write_cmos_sensor(0x37a7, 0x88); + write_cmos_sensor(0x37a8, 0x98); + write_cmos_sensor(0x37a9, 0x98); + write_cmos_sensor(0x37aa, 0x88); + write_cmos_sensor(0x37ab, 0x5c); + write_cmos_sensor(0x37ac, 0x5c); + write_cmos_sensor(0x37ad, 0x55); + write_cmos_sensor(0x37ae, 0x19); + write_cmos_sensor(0x37af, 0x19); + write_cmos_sensor(0x37b3, 0x84); + write_cmos_sensor(0x37b4, 0x84); + write_cmos_sensor(0x37b5, 0x60); + write_cmos_sensor(0x3808, 0x0c); + write_cmos_sensor(0x3809, 0xc0); + write_cmos_sensor(0x380a, 0x09); + write_cmos_sensor(0x380b, 0x90); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0xa4); + write_cmos_sensor(0x380e, 0x09); + write_cmos_sensor(0x380f, 0xe2); + write_cmos_sensor(0x3814, 0x01); + write_cmos_sensor(0x3821, 0x46); + write_cmos_sensor(0x382a, 0x01); + write_cmos_sensor(0x382b, 0x01); + write_cmos_sensor(0x3830, 0x06); + write_cmos_sensor(0x3836, 0x01); + write_cmos_sensor(0x3f08, 0x10); + write_cmos_sensor(0x4001, 0x00); + write_cmos_sensor(0x4022, 0x0c); + write_cmos_sensor(0x4023, 0x60); + write_cmos_sensor(0x4025, 0x36); + write_cmos_sensor(0x4027, 0x37); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x08); + write_cmos_sensor(0x402e, 0x04); + write_cmos_sensor(0x402f, 0x08); + write_cmos_sensor(0x4600, 0x01); + write_cmos_sensor(0x4601, 0x97); + write_cmos_sensor(0x4837, 0x0e); + write_cmos_sensor(0x5901, 0x00); + write_cmos_sensor(0x382d, 0xff); + write_cmos_sensor(0x3031, 0x08); + if ( bm == FACTORY_BOOT || bm == ATE_FACTORY_BOOT ) + write_cmos_sensor(0x4316, 0x01);//DPCM + else + write_cmos_sensor(0x4316, 0x00);//DPCM + write_cmos_sensor(0x0100, 0x01); + mdelay(10); +} + if (currefps == 150) { +// @@33264*2448 15fps 2lane 720Mbps/lane +// 100 99 3264 2448 ; Resolution +// ;;MIPI=720Mbps/lane, SysClk=72Mhz,Dac Clock=360Mhz +// ;;1940x2474x15 + + write_cmos_sensor(0x0100, 0x00); + mdelay(5); //PLEASE test and remove it; Pengtao + write_cmos_sensor(0x0302, 0x1e); + write_cmos_sensor(0x030e, 0x02); + write_cmos_sensor(0x0312, 0x03); + write_cmos_sensor(0x3015, 0x00); + write_cmos_sensor(0x3501, 0x9a); + write_cmos_sensor(0x3502, 0x20); + write_cmos_sensor(0x3700, 0x18); + write_cmos_sensor(0x3701, 0x0c); + write_cmos_sensor(0x3702, 0x28); + write_cmos_sensor(0x3703, 0x19); + write_cmos_sensor(0x3704, 0x14); + write_cmos_sensor(0x3707, 0x04); + write_cmos_sensor(0x3708, 0x24); + write_cmos_sensor(0x3709, 0x33); + write_cmos_sensor(0x370c, 0x04); + write_cmos_sensor(0x3718, 0x12); + write_cmos_sensor(0x3712, 0x42); + write_cmos_sensor(0x371e, 0x19); + write_cmos_sensor(0x371f, 0x40); + write_cmos_sensor(0x3720, 0x05); + write_cmos_sensor(0x3721, 0x05); + write_cmos_sensor(0x3724, 0x06); + write_cmos_sensor(0x3725, 0x01); + write_cmos_sensor(0x3726, 0x06); + write_cmos_sensor(0x3728, 0x05); + write_cmos_sensor(0x3729, 0x02); + write_cmos_sensor(0x372a, 0x03); + write_cmos_sensor(0x372b, 0x53); + write_cmos_sensor(0x372c, 0xa3); + write_cmos_sensor(0x372d, 0x53); + write_cmos_sensor(0x372e, 0x06); + write_cmos_sensor(0x372f, 0x10); + write_cmos_sensor(0x3730, 0x01); + write_cmos_sensor(0x3731, 0x06); + write_cmos_sensor(0x3732, 0x14); + write_cmos_sensor(0x3736, 0x20); + write_cmos_sensor(0x373a, 0x05); + write_cmos_sensor(0x373b, 0x06); + write_cmos_sensor(0x373c, 0x0a); + write_cmos_sensor(0x373e, 0x03); + write_cmos_sensor(0x375a, 0x06); + write_cmos_sensor(0x375b, 0x13); + write_cmos_sensor(0x375d, 0x02); + write_cmos_sensor(0x375f, 0x14); + write_cmos_sensor(0x3768, 0xcc); + write_cmos_sensor(0x3769, 0x44); + write_cmos_sensor(0x376a, 0x44); + write_cmos_sensor(0x3772, 0x23); + write_cmos_sensor(0x3773, 0x02); + write_cmos_sensor(0x3774, 0x16); + write_cmos_sensor(0x3775, 0x12); + write_cmos_sensor(0x3776, 0x04); + write_cmos_sensor(0x3778, 0x1a); + write_cmos_sensor(0x37a0, 0x44); + write_cmos_sensor(0x37a1, 0x3d); + write_cmos_sensor(0x37a2, 0x3d); + write_cmos_sensor(0x37a7, 0x44); + write_cmos_sensor(0x37a8, 0x4c); + write_cmos_sensor(0x37a9, 0x4c); + write_cmos_sensor(0x37aa, 0x44); + write_cmos_sensor(0x37ab, 0x2e); + write_cmos_sensor(0x37ac, 0x2e); + write_cmos_sensor(0x37ad, 0x33); + write_cmos_sensor(0x37ae, 0x0d); + write_cmos_sensor(0x37af, 0x0d); + write_cmos_sensor(0x37b3, 0x42); + write_cmos_sensor(0x37b4, 0x42); + write_cmos_sensor(0x37b5, 0x31); + write_cmos_sensor(0x3808, 0x0c); + write_cmos_sensor(0x3809, 0xc0); + write_cmos_sensor(0x380a, 0x09); + write_cmos_sensor(0x380b, 0x90); + write_cmos_sensor(0x380c, 0x07); + write_cmos_sensor(0x380d, 0x94); + write_cmos_sensor(0x380e, 0x09); + write_cmos_sensor(0x380f, 0xaa); + write_cmos_sensor(0x3814, 0x01); + write_cmos_sensor(0x3821, 0x46); + write_cmos_sensor(0x382a, 0x01); + write_cmos_sensor(0x382b, 0x01); + write_cmos_sensor(0x3830, 0x06); + write_cmos_sensor(0x3836, 0x01); + write_cmos_sensor(0x3f08, 0x08); + write_cmos_sensor(0x4001, 0x00); + write_cmos_sensor(0x4022, 0x0c); + write_cmos_sensor(0x4023, 0x60); + write_cmos_sensor(0x4025, 0x36); + write_cmos_sensor(0x4027, 0x37); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x08); + write_cmos_sensor(0x402e, 0x04); + write_cmos_sensor(0x402f, 0x08); + write_cmos_sensor(0x4600, 0x01); + write_cmos_sensor(0x4601, 0x97); + write_cmos_sensor(0x4837, 0x10); + write_cmos_sensor(0x5901, 0x00); + write_cmos_sensor(0x382d, 0xff); + + write_cmos_sensor(0x3031, 0x08); + if ( bm == FACTORY_BOOT || bm == ATE_FACTORY_BOOT ) + write_cmos_sensor(0x4316, 0x01);//DPCM + else + write_cmos_sensor(0x4316, 0x00);//DPCM + mdelay(5); //PLEASE test and remove it; Pengtao + write_cmos_sensor(0x0100, 0x01); +} + if (currefps == 240) { +// @@3264*2448 24fps 2lane 1.104Gbps/lane +// ;;MIPI=1.104Gbps/lane, SysClk=144Mhz,Dac Clock=360Mhz +// ;;2344x2556x24 +// 100 99 3264 2448 ; Resolution + write_cmos_sensor(0x0100, 0x00); + write_cmos_sensor(0x0302, 0x2e); + write_cmos_sensor(0x030e, 0x00); + write_cmos_sensor(0x0312, 0x01); + write_cmos_sensor(0x3015, 0x01); + write_cmos_sensor(0x3501, 0x9a); + write_cmos_sensor(0x3502, 0x20); + write_cmos_sensor(0x3700, 0x30); + write_cmos_sensor(0x3701, 0x18); + write_cmos_sensor(0x3702, 0x50); + write_cmos_sensor(0x3703, 0x32); + write_cmos_sensor(0x3704, 0x28); + write_cmos_sensor(0x3707, 0x08); + write_cmos_sensor(0x3708, 0x48); + write_cmos_sensor(0x3709, 0x66); + write_cmos_sensor(0x370c, 0x07); + write_cmos_sensor(0x3718, 0x14); + write_cmos_sensor(0x3712, 0x44); + write_cmos_sensor(0x371e, 0x31); + write_cmos_sensor(0x371f, 0x7f); + write_cmos_sensor(0x3720, 0x0a); + write_cmos_sensor(0x3721, 0x0a); + write_cmos_sensor(0x3724, 0x0c); + write_cmos_sensor(0x3725, 0x02); + write_cmos_sensor(0x3726, 0x0c); + write_cmos_sensor(0x3728, 0x0a); + write_cmos_sensor(0x3729, 0x03); + write_cmos_sensor(0x372a, 0x06); + write_cmos_sensor(0x372b, 0xa6); + write_cmos_sensor(0x372c, 0xa6); + write_cmos_sensor(0x372d, 0xa6); + write_cmos_sensor(0x372e, 0x0c); + write_cmos_sensor(0x372f, 0x20); + write_cmos_sensor(0x3730, 0x02); + write_cmos_sensor(0x3731, 0x0c); + write_cmos_sensor(0x3732, 0x28); + write_cmos_sensor(0x3736, 0x30); + write_cmos_sensor(0x373a, 0x0a); + write_cmos_sensor(0x373b, 0x0b); + write_cmos_sensor(0x373c, 0x14); + write_cmos_sensor(0x373e, 0x06); + write_cmos_sensor(0x375a, 0x0c); + write_cmos_sensor(0x375b, 0x26); + write_cmos_sensor(0x375d, 0x04); + write_cmos_sensor(0x375f, 0x28); + write_cmos_sensor(0x3768, 0xcc); + write_cmos_sensor(0x3769, 0x44); + write_cmos_sensor(0x376a, 0x44); + write_cmos_sensor(0x3772, 0x46); + write_cmos_sensor(0x3773, 0x04); + write_cmos_sensor(0x3774, 0x2c); + write_cmos_sensor(0x3775, 0x13); + write_cmos_sensor(0x3776, 0x08); + write_cmos_sensor(0x3778, 0x17); + write_cmos_sensor(0x37a0, 0x88); + write_cmos_sensor(0x37a1, 0x7a); + write_cmos_sensor(0x37a2, 0x7a); + write_cmos_sensor(0x37a7, 0x88); + write_cmos_sensor(0x37a8, 0x98); + write_cmos_sensor(0x37a9, 0x98); + write_cmos_sensor(0x37aa, 0x88); + write_cmos_sensor(0x37ab, 0x5c); + write_cmos_sensor(0x37ac, 0x5c); + write_cmos_sensor(0x37ad, 0x55); + write_cmos_sensor(0x37ae, 0x19); + write_cmos_sensor(0x37af, 0x19); + write_cmos_sensor(0x37b3, 0x84); + write_cmos_sensor(0x37b4, 0x84); + write_cmos_sensor(0x37b5, 0x60); + write_cmos_sensor(0x3808, 0x0c); + write_cmos_sensor(0x3809, 0xc0); + write_cmos_sensor(0x380a, 0x09); + write_cmos_sensor(0x380b, 0x90); + write_cmos_sensor(0x380c, 0x09); + write_cmos_sensor(0x380d, 0x28); + write_cmos_sensor(0x380e, 0x09); + write_cmos_sensor(0x380f, 0xfc); + write_cmos_sensor(0x3814, 0x01); + write_cmos_sensor(0x3821, 0x46); + write_cmos_sensor(0x382a, 0x01); + write_cmos_sensor(0x382b, 0x01); + write_cmos_sensor(0x3830, 0x06); + write_cmos_sensor(0x3836, 0x01); + write_cmos_sensor(0x3f08, 0x10); + write_cmos_sensor(0x4001, 0x00); + write_cmos_sensor(0x4022, 0x0c); + write_cmos_sensor(0x4023, 0x60); + write_cmos_sensor(0x4025, 0x36); + write_cmos_sensor(0x4027, 0x37); + write_cmos_sensor(0x402a, 0x04); + write_cmos_sensor(0x402b, 0x08); + write_cmos_sensor(0x402e, 0x04); + write_cmos_sensor(0x402f, 0x08); + write_cmos_sensor(0x4600, 0x01); + write_cmos_sensor(0x4601, 0x97); + write_cmos_sensor(0x4837, 0x0d); + write_cmos_sensor(0x5901, 0x00); + write_cmos_sensor(0x382d, 0xff); + + write_cmos_sensor(0x3031, 0x08); + if ( bm == FACTORY_BOOT || bm == ATE_FACTORY_BOOT ) + write_cmos_sensor(0x4316, 0x01);//DPCM + else + write_cmos_sensor(0x4316, 0x00);//DPCM + + write_cmos_sensor(0x0100, 0x01); + +} +} + + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + LOG_INF("E! video just has 30fps preview size setting ,NOT HAS 24FPS SETTING!\n"); + preview_setting(); +} +static void hs_video_setting(void) +{ + LOG_INF("E\n"); +//@@640x480 120fps 2lane 720M bps/lane +//;;MIPI=720Mbps, SysClk=144Mhz,Dac Clock=360Mhz +//;;2306x520x120 +//100 99 640 480 + write_cmos_sensor(0x0100, 0x00); + write_cmos_sensor(0x0302, 0x1e); + write_cmos_sensor(0x030e, 0x00); + write_cmos_sensor(0x0312, 0x01); + write_cmos_sensor(0x3015, 0x01); + write_cmos_sensor(0x3501, 0x20); + write_cmos_sensor(0x3502, 0x00); + write_cmos_sensor(0x3700, 0x30); + write_cmos_sensor(0x3701, 0x18); + write_cmos_sensor(0x3702, 0x50); + write_cmos_sensor(0x3703, 0x32); + write_cmos_sensor(0x3704, 0x28); + write_cmos_sensor(0x3707, 0x08); + write_cmos_sensor(0x3708, 0x48); + write_cmos_sensor(0x3709, 0x66); + write_cmos_sensor(0x370c, 0x07); + write_cmos_sensor(0x3718, 0x14); + write_cmos_sensor(0x3712, 0x44); + write_cmos_sensor(0x371e, 0x31); + write_cmos_sensor(0x371f, 0x7f); + write_cmos_sensor(0x3720, 0x0a); + write_cmos_sensor(0x3721, 0x0a); + write_cmos_sensor(0x3724, 0x0c); + write_cmos_sensor(0x3725, 0x02); + write_cmos_sensor(0x3726, 0x0c); + write_cmos_sensor(0x3728, 0x0a); + write_cmos_sensor(0x3729, 0x03); + write_cmos_sensor(0x372a, 0x06); + write_cmos_sensor(0x372b, 0xa6); + write_cmos_sensor(0x372c, 0xa6); + write_cmos_sensor(0x372d, 0xa6); + write_cmos_sensor(0x372e, 0x0c); + write_cmos_sensor(0x372f, 0x20); + write_cmos_sensor(0x3730, 0x02); + write_cmos_sensor(0x3731, 0x0c); + write_cmos_sensor(0x3732, 0x28); + write_cmos_sensor(0x3736, 0x30); + write_cmos_sensor(0x373a, 0x0a); + write_cmos_sensor(0x373b, 0x0b); + write_cmos_sensor(0x373c, 0x14); + write_cmos_sensor(0x373e, 0x06); + write_cmos_sensor(0x375a, 0x0c); + write_cmos_sensor(0x375b, 0x26); + write_cmos_sensor(0x375d, 0x04); + write_cmos_sensor(0x375f, 0x28); + write_cmos_sensor(0x3768, 0x00); + write_cmos_sensor(0x3769, 0xc0); + write_cmos_sensor(0x376a, 0x42); + write_cmos_sensor(0x3772, 0x46); + write_cmos_sensor(0x3773, 0x04); + write_cmos_sensor(0x3774, 0x2c); + write_cmos_sensor(0x3775, 0x13); + write_cmos_sensor(0x3776, 0x08); + write_cmos_sensor(0x3778, 0x17); + write_cmos_sensor(0x37a0, 0x88); + write_cmos_sensor(0x37a1, 0x7a); + write_cmos_sensor(0x37a2, 0x7a); + write_cmos_sensor(0x37a7, 0x88); + write_cmos_sensor(0x37a8, 0x98); + write_cmos_sensor(0x37a9, 0x98); + write_cmos_sensor(0x37aa, 0x88); + write_cmos_sensor(0x37ab, 0x5c); + write_cmos_sensor(0x37ac, 0x5c); + write_cmos_sensor(0x37ad, 0x55); + write_cmos_sensor(0x37ae, 0x19); + write_cmos_sensor(0x37af, 0x19); + write_cmos_sensor(0x37b3, 0x84); + write_cmos_sensor(0x37b4, 0x84); + write_cmos_sensor(0x37b5, 0x60); + write_cmos_sensor(0x3808, 0x02); + write_cmos_sensor(0x3809, 0x80); + write_cmos_sensor(0x380a, 0x01); + write_cmos_sensor(0x380b, 0xe0); + write_cmos_sensor(0x380c, 0x09); + write_cmos_sensor(0x380d, 0x02); + write_cmos_sensor(0x380e, 0x02); + write_cmos_sensor(0x380f, 0x08); + write_cmos_sensor(0x3814, 0x03); + write_cmos_sensor(0x3821, 0x6f); + write_cmos_sensor(0x382a, 0x05); + write_cmos_sensor(0x382b, 0x03); + write_cmos_sensor(0x3830, 0x0c); + write_cmos_sensor(0x3836, 0x02); + write_cmos_sensor(0x3f08, 0x10); + write_cmos_sensor(0x4001, 0x10); + write_cmos_sensor(0x4022, 0x02); + write_cmos_sensor(0x4023, 0x20); + write_cmos_sensor(0x4025, 0xe0); + write_cmos_sensor(0x4027, 0x5f); + write_cmos_sensor(0x402a, 0x02); + write_cmos_sensor(0x402b, 0x04); + write_cmos_sensor(0x402e, 0x02); + write_cmos_sensor(0x402f, 0x04); + write_cmos_sensor(0x4600, 0x00); + write_cmos_sensor(0x4601, 0x4f); + write_cmos_sensor(0x4837, 0x16); + write_cmos_sensor(0x5901, 0x04); + write_cmos_sensor(0x382d, 0x7f); + write_cmos_sensor(0x0100, 0x01); +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + preview_setting(); +} + + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = ((read_cmos_sensor(0x300B) << 8) | read_cmos_sensor(0x300C)); + if (*sensor_id == imgsensor_info.sensor_id) { + if((read_cmos_sensor(0x302A)) == 0XB2){ + ov8858version = OV8858R2A; + SENSORDB("i2c write id: 0x%x, sensor id: 0x%x, ov8858version = %d(0=r2a,1=r1a)\n", imgsensor.i2c_write_id,*sensor_id,ov8858version); + bm = get_boot_mode(); + LOG_INF("bm %d\n",bm); + if ( bm == FACTORY_BOOT || bm == ATE_FACTORY_BOOT ){ + imgsensor_info.sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_B; + imgsensor_dpcm_info_ov8858[1] = COMP8_DI_2A; + } + return ERROR_NONE; + } + else if((read_cmos_sensor(0x302A)) == 0XB1){ + LOG_INF("=================R1A sensor,contact OV please!====================\n"); + return ERROR_SENSOR_CONNECT_FAIL; + } + else{ + LOG_INF("read ov8858 R1A R2A bate fail\n"); + return ERROR_SENSOR_CONNECT_FAIL; + } + } + LOG_INF("Read sensor id fail, id: 0x%x,sensor_id=0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + +#ifdef OV8858R2AOTP + +struct otp_struct { +int flag; // bit[7]: info, bit[6]:wb, bit[5]:vcm, bit[4]:lenc +int module_integrator_id; +int lens_id; +int production_year; +int production_month; +int production_day; +int rg_ratio; +int bg_ratio; +int lenc[240]; +int checksum; +int VCM_start; +int VCM_end; +int VCM_dir; +}; + +// return value: +// bit[7]: 0 no otp info, 1 valid otp info +// bit[6]: 0 no otp wb, 1 valib otp wb +// bit[5]: 0 no otp vcm, 1 valid otp vcm +// bit[4]: 0 no otp lenc/invalid otp lenc, 1 valid otp lenc +int read_otp(struct otp_struct *otp_ptr) +{ + int otp_flag, addr, temp, i; + //set 0x5002[3] to ?0? + int temp1; + temp1 = read_cmos_sensor(0x5002); + write_cmos_sensor(0x5002, (0x00 & 0x08) | (temp1 & (~0x08))); + // read OTP into buffer + write_cmos_sensor(0x3d84, 0xC0); + write_cmos_sensor(0x3d88, 0x70); // OTP start address + write_cmos_sensor(0x3d89, 0x10); + write_cmos_sensor(0x3d8A, 0x72); // OTP end address + write_cmos_sensor(0x3d8B, 0x0a); + write_cmos_sensor(0x3d81, 0x01); // load otp into buffer + mdelay(10); + // OTP base information and WB calibration data + otp_flag = read_cmos_sensor(0x7010); + addr = 0; + if((otp_flag & 0xc0) == 0x40) { + addr = 0x7011; // base address of info group 1 + } + else if((otp_flag & 0x30) == 0x10) { + addr = 0x7019; // base address of info group 2 + } + if(addr != 0) { + (*otp_ptr).flag = 0xC0; // valid info and AWB in OTP + (*otp_ptr).module_integrator_id = read_cmos_sensor(addr); + (*otp_ptr).lens_id = read_cmos_sensor( addr + 1); + (*otp_ptr).production_year = read_cmos_sensor( addr + 2); + (*otp_ptr).production_month = read_cmos_sensor( addr + 3); + (*otp_ptr).production_day = read_cmos_sensor(addr + 4); + temp = read_cmos_sensor(addr + 7); + (*otp_ptr).rg_ratio = (read_cmos_sensor(addr + 5)<<2) + ((temp>>6) & 0x03); + (*otp_ptr).bg_ratio = (read_cmos_sensor(addr + 6)<<2) + ((temp>>4) & 0x03); + LOG_INF("rg_ratio: %d, bg_ratio: %d\n", (*otp_ptr).rg_ratio,(*otp_ptr).bg_ratio); + } + else { + (*otp_ptr).flag = 0x00; // not info and AWB in OTP + (*otp_ptr).module_integrator_id = 0; + (*otp_ptr).lens_id = 0; + (*otp_ptr).production_year = 0; + (*otp_ptr).production_month = 0; + (*otp_ptr).production_day = 0; + (*otp_ptr).rg_ratio = 0; + (*otp_ptr).bg_ratio = 0; + } + // OTP VCM Calibration + otp_flag = read_cmos_sensor(0x7021); + addr = 0; + if((otp_flag & 0xc0) == 0x40) { + addr = 0x7022; // base address of VCM Calibration group 1 + } + else if((otp_flag & 0x30) == 0x10) { + addr = 0x7025; // base address of VCM Calibration group 2 + } + if(addr != 0) { + (*otp_ptr).flag |= 0x20; + temp = read_cmos_sensor(addr + 2); + (* otp_ptr).VCM_start = (read_cmos_sensor(addr)<<2) | ((temp>>6) & 0x03); + (* otp_ptr).VCM_end = (read_cmos_sensor(addr + 1) << 2) | ((temp>>4) & 0x03); + (* otp_ptr).VCM_dir = (temp>>2) & 0x03; + } + else { + (* otp_ptr).VCM_start = 0; + (* otp_ptr).VCM_end = 0; + (* otp_ptr).VCM_dir = 0; + } + // OTP Lenc Calibration + otp_flag = read_cmos_sensor(0x7028); + addr = 0; + int checksum2=0; + if((otp_flag & 0xc0) == 0x40) { + addr = 0x7029; // base address of Lenc Calibration group 1 + } + else if((otp_flag & 0x30) == 0x10) { + addr = 0x711a; // base address of Lenc Calibration group 2 + } + if(addr != 0) { + for(i=0;i<240;i++) { + (* otp_ptr).lenc[i]=read_cmos_sensor(addr + i); + checksum2 += (* otp_ptr).lenc[i]; + } + checksum2 = (checksum2)%255 +1; + (*otp_ptr).checksum = read_cmos_sensor(addr + 240); + if((*otp_ptr).checksum == checksum2){ + (*otp_ptr).flag |= 0x10; + } + } + else { + for(i=0;i<240;i++) { + (* otp_ptr).lenc[i]=0; + } + } + for(i=0x7010;i<=0x720a;i++) { + write_cmos_sensor(i,0); // clear OTP buffer, recommended use continuous write to accelarate + } + //set 0x5002[3] to ?1? + temp1 = read_cmos_sensor(0x5002); + write_cmos_sensor(0x5002, (0x08 & 0x08) | (temp1 & (~0x08))); + return (*otp_ptr).flag; +} +// return value: +// bit[7]: 0 no otp info, 1 valid otp info +// bit[6]: 0 no otp wb, 1 valib otp wb +// bit[5]: 0 no otp vcm, 1 valid otp vcm +// bit[4]: 0 no otp lenc, 1 valid otp lenc + +int apply_otp(struct otp_struct *otp_ptr) +{ + int RG_Ratio_Typical = 0x137, BG_Ratio_Typical = 0x121; + int rg, bg, R_gain, G_gain, B_gain, Base_gain, temp, i; + // apply OTP WB Calibration + if ((*otp_ptr).flag & 0x40) { + rg = (*otp_ptr).rg_ratio; + bg = (*otp_ptr).bg_ratio; + //calculate G gain + R_gain = (RG_Ratio_Typical*1000) / rg; + B_gain = (BG_Ratio_Typical*1000) / bg; + G_gain = 1000; + if (R_gain < 1000 || B_gain < 1000) + { + if (R_gain < B_gain) + Base_gain = R_gain; + else + Base_gain = B_gain; + } + else + { + Base_gain = G_gain; + } + R_gain = 0x400 * R_gain / (Base_gain); + B_gain = 0x400 * B_gain / (Base_gain); + G_gain = 0x400 * G_gain / (Base_gain); + LOG_INF("R_gain: 0x%x, B_gain: 0x%x, G_gain: 0x%x\n", R_gain,B_gain,G_gain); + // update sensor WB gain + if (R_gain>0x400) { + write_cmos_sensor(0x5032, R_gain>>8); + write_cmos_sensor(0x5033, R_gain & 0x00ff); + } + if (G_gain>0x400) { + write_cmos_sensor(0x5034, G_gain>>8); + write_cmos_sensor(0x5035, G_gain & 0x00ff); + } + if (B_gain>0x400) { + write_cmos_sensor(0x5036, B_gain>>8); + write_cmos_sensor(0x5037, B_gain & 0x00ff); + } + } + // apply OTP Lenc Calibration + if ((*otp_ptr).flag & 0x10) { + temp = read_cmos_sensor(0x5000); + temp = 0x80 | temp; + write_cmos_sensor(0x5000, temp); + for(i=0;i<240;i++) { + write_cmos_sensor(0x5800 + i, (*otp_ptr).lenc[i]); + } + } + return (*otp_ptr).flag; +} + +#endif +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint16 sensor_id = 0; + SENSORDB("\nWARNING: \n===PengtaoFan== \nthe driver is ov88582lane for custom , not verify,just bring up.!\n"); + //SENSORDB("preview 1280*960@30fps,864Mbps/lane; video 1280*960@30fps,864Mbps/lane; capture 5M@30fps,864Mbps/lane\n"); + + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = ((read_cmos_sensor(0x300B) << 8) | read_cmos_sensor(0x300C)); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, id: 0x%x,sensor_id =0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + #ifdef OV8858R2AOTP + write_cmos_sensor(0x100 , 0x01); + mdelay(10); + + LOG_INF("Apply the sensor OTP\n"); + struct otp_struct *otp_ptr = (struct otp_struct *)kzalloc(sizeof(struct otp_struct), GFP_KERNEL); + read_otp(otp_ptr); + apply_otp(otp_ptr); + kfree(otp_ptr); + write_cmos_sensor(0x100 , 0x00); + mdelay(20); + #endif + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.shutter = 0x2D00; + imgsensor.gain = 0x100; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + mdelay(10); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else if (imgsensor.current_fps == imgsensor_info.cap2.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap2.pclk; + imgsensor.line_length = imgsensor_info.cap2.linelength; + imgsensor.frame_length = imgsensor_info.cap2.framelength; + imgsensor.min_frame_length = imgsensor_info.cap2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap1's setting: %d fps!\n",imgsensor_info.cap1.max_framerate/10,imgsensor_info.cap.max_framerate); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + + capture_setting(imgsensor.current_fps); + mdelay(10); + + return ERROR_NONE; +} /* capture() */ + +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(30); + mdelay(10); + + + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + mdelay(10); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + mdelay(10); + + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + sensor_info->DPCM_INFO = imgsensor_dpcm_info_ov8858[0]; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + sensor_info->DPCM_INFO = imgsensor_dpcm_info_ov8858[1]; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + sensor_info->DPCM_INFO = imgsensor_dpcm_info_ov8858[2]; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + sensor_info->DPCM_INFO = imgsensor_dpcm_info_ov8858[3]; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + sensor_info->DPCM_INFO = imgsensor_dpcm_info_ov8858[4]; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + sensor_info->DPCM_INFO = imgsensor_dpcm_info_ov8858[0]; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + //case MSDK_SCENARIO_ID_CAMERA_ZSD: + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + //LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x5E00, 0x80); + write_cmos_sensor(0x5000, 0x7e); + write_cmos_sensor(0x5002, 0x00); + write_cmos_sensor(0x3500, 0x00); + write_cmos_sensor(0x3501, 0x2f); + write_cmos_sensor(0x3502, 0xf0); + write_cmos_sensor(0x3508, 0x00); + write_cmos_sensor(0x3509, 0x80); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x5E00, 0x00); + } + + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; +// unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + // LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 OV8858_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV5693_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/ov8858mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/ov8858mipiraw_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..bd88aefadfd8034eeb0b16ddcc19e9f4d516c6a4 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/ov8858_mipi_raw/ov8858mipiraw_Sensor.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * OV8858mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * PengtaoFan + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _OV8858MIPI_SENSOR_H +#define _OV8858MIPI_SENSOR_H + +//±íʾsensorµÄ¼¸ÖÖ¹¤×÷ģʽ״̬£ºinit preview capture video hvideo svideo +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +//±íʾ¼¸ÖÖ£¨²»Í¬¹¤×÷ģʽ״̬Ï£©µÄsensor²ÎÊýÐÅÏ¢ +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +//±íʾ£¨µ±Ç°×´Ì¬¹¤×÷ģʽ£©ÏµÄsensor²ÎÊýÐÅÏ¢ +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint32 dummy_pixel; //current dummypixel + kal_uint32 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +//sensor»ù±¾ÐÅÏ¢£¬datasheetÉϵÄÐÅÏ¢ +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint16 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct cap2; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..34f615828ecb86b5085473171c458b9a5dcab106 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += s5k2p8_otp.o +obj-y += s5k2p8mipi_Sensor.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8_otp.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8_otp.c new file mode 100644 index 0000000000000000000000000000000000000000..b46238b657538a1844d80fd1a8ac66142ac1468f --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8_otp.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +//extern int iBurstWriteReg_multi(u8 *pData, u32 bytes, u16 i2cId, u16 transfer_length); +extern int iMultiReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId, u8 number); + + +#define USHORT unsigned short +#define BYTE unsigned char +#define Sleep(ms) mdelay(ms) + +#define EEPROM CAT24C512 +#define EEPROM_READ_ID 0xA0 +#define EEPROM_WRITE_ID 0xA1 +#define I2C_SPEED 400 //CAT24C512 can support 1Mhz + +#define START_OFFSET 0 +#define PAGE_NUM 512 +#define EEPROM_PAGE_SIZE 128 //EEPROM size 512x128=65536bytes +#define MAX_OFFSET 0xffff +#define DATA_SIZE 4096 +BYTE eeprom_data[DATA_SIZE]= {0}; +static bool get_done = false; +static int last_size = 0; +static int last_offset = 0; + +bool byte_write_eeprom(kal_uint16 addr, BYTE data ) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(data & 0xFF)}; + if(addr > MAX_OFFSET) + return false; + kdSetI2CSpeed(I2C_SPEED); + if(iWriteRegI2C(pu_send_cmd, 3, EEPROM_WRITE_ID)<0) { + /*printk("byte_write_eeprom fail, addr %x data %d\n",addr,data);*/ + return false; + } + Sleep(7); + return true; +} + + + +/******** +Be noted that once your addr are not page-algned, some data may be covered +*/ +bool page_write_eeprom(kal_uint16 addr, BYTE data[], kal_uint32 size) +{ + char pu_send_cmd[EEPROM_PAGE_SIZE+2]; + int i = 0; + + if( (addr+size) > MAX_OFFSET || size > EEPROM_PAGE_SIZE) + return false; + kdSetI2CSpeed(I2C_SPEED); + + + pu_send_cmd[0] = (char)(addr >> 8); + pu_send_cmd[1] = (char)(addr & 0xFF); + + for(i = 0; i< size; i++) { + pu_send_cmd[i+2] = (char)(data[i] & 0xFF); + } + pr_debug("before iBurstWriteReg_multi\n"); + /*iBurstWriteReg_multi(pu_send_cmd , size, EEPROM_WRITE_ID, size)<0) + //only support in K2 now*/ + if(1) + return false; + Sleep(10); + return true; +} + + +bool selective_read_eeprom(kal_uint16 addr, BYTE* data) +{ + char pu_send_cmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + if(addr > MAX_OFFSET) + return false; + kdSetI2CSpeed(I2C_SPEED); + + if(iReadRegI2C(pu_send_cmd, 2, (u8*)data, 1, EEPROM_READ_ID)<0) + return false; + return true; +} + +bool sequential_read_eeprom(kal_uint16 addr, BYTE* data, kal_uint32 size) +{ + + if( (addr+size) > MAX_OFFSET || size > EEPROM_PAGE_SIZE) + return false; + kdSetI2CSpeed(I2C_SPEED); + if( iMultiReadReg(addr , (u8*)data , EEPROM_READ_ID, size) <0) + return false; + return true; +} + +static bool _wrtie_eeprom(kal_uint16 addr, BYTE data[], kal_uint32 size ){ + int i = 0; + int offset = addr; + for(i = 0; i < size; i++) { + /*printk("wrtie_eeprom 0x%0x %d\n",offset, data[i]);*/ + if(!byte_write_eeprom( offset, data[i])){ + return false; + } + offset++; + } + get_done = false; + return true; +} +static bool _read_eeprom(kal_uint16 addr, BYTE* data, kal_uint32 size ){ + int i = 0; + int offset = addr; + for(i = 0; i < size; i++) { + if(!selective_read_eeprom(offset, &data[i])){ + return false; + } + /*printk("read_eeprom 0x%0x %d\n",offset, data[i]);*/ + offset++; + } + get_done = true; + last_size = size; + last_offset = addr; + return true; +} +bool read_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size){ + + if(!get_done || last_size != size || last_offset != addr) { + if(!_read_eeprom(addr, eeprom_data, size)){ + get_done = 0; + last_size = 0; + last_offset = 0; + return false; + } + } + memcpy(data, eeprom_data, size); + return true; +} +bool wrtie_eeprom(kal_uint16 addr, BYTE data[],kal_uint32 size ){ + return _wrtie_eeprom(addr, data, size); +} + +bool wrtie_eeprom_fast(kal_uint16 addr, BYTE data[],kal_uint32 size ){ + bool ret = false; + int size_to_send = size; + printk("wrtie_eeprom_fast\n"); + if( (addr&0xff) == 0 ){//align page + #if 0 + if(size < EEPROM_PAGE_SIZE+1) { + ret = page_write_eeprom(addr, data, size); + } else + #endif + { + printk("before page_write_eeprom\n"); + for(; size_to_send > 0; size_to_send -= EEPROM_PAGE_SIZE) { + ret = page_write_eeprom( addr, data, + size_to_send > EEPROM_PAGE_SIZE ? EEPROM_PAGE_SIZE : size_to_send); + if(!ret) + break; + data+=EEPROM_PAGE_SIZE; + printk("after page_write_eeprom %d\n",size_to_send); + } + printk("after page_write_eeprom\n"); + } + } else { + ret = _wrtie_eeprom(addr, data, size); + } + return ret; +} + + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8mipi_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8mipi_Sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..eeded9350cb731967f837591a5d60838dbee3157 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8mipi_Sensor.c @@ -0,0 +1,5717 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * S5K2P8mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "s5k2p8mipi_Sensor.h" + +#define PFX "S5K2P8_camera_sensor" +#define LOG_1 LOG_INF("S5K2P8,MIPI 4LANE\n") +#define LOG_2 LOG_INF("preview 2664*1500@30fps,888Mbps/lane; video 5328*3000@30fps,1390Mbps/lane; capture 16M@30fps,1390Mbps/lane\n") +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) +#define LOGE(format, args...) pr_err(PFX "[%s] " format, __FUNCTION__, ##args) + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + +#define SLOW_MOTION_120FPS +#define FIX_VIEW_ANGLE +#define MULTI_WRITE 0 + +extern bool read_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size); + +//#define PDAF_TEST 1 +#ifdef PDAF_TEST +extern bool wrtie_eeprom(kal_uint16 addr, BYTE data[],kal_uint32 size ); +char data[4096]= {0}; +char data2[4096]= {0}; +#endif +static imgsensor_info_struct imgsensor_info = { + .sensor_id = S5K2P8_SENSOR_ID, +#ifdef FIX_VIEW_ANGLE + .checksum_value = 0xfe9e1a79, +#else + .checksum_value = 0x33c8c938, +#endif + + .pre = { + .pclk = 371200000, //record different mode's pclk + .linelength = 5880, //record different mode's linelength + .framelength = 2052, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 2656, //record different mode's width of grabwindow + .grabwindow_height = 1488, //record different mode's height of grabwindow +#else + .grabwindow_width = 2664, //record different mode's width of grabwindow + .grabwindow_height = 1500, //record different mode's height of grabwindow +#endif + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk = 560000000, + .linelength =5880, + .framelength = 3174, + .startx = 0, + .starty = 0, +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 5312, + .grabwindow_height = 2976, +#else + .grabwindow_width = 5328,//5334, + .grabwindow_height = 3000, +#endif + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .cap1 = { + .pclk = 371200000, + .linelength = 5880, + .framelength = 3174, + .startx = 0, + .starty = 0, +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 5312, + .grabwindow_height = 2976, +#else + .grabwindow_width =5328, + .grabwindow_height = 3000, +#endif + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 200, + }, + .cap2 = { + .pclk = 560000000, + .linelength = 12224, + .framelength = 3174, + .startx = 0, + .starty = 0, +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 5312, + .grabwindow_height = 2976, +#else + .grabwindow_width = 5328,//5334, + .grabwindow_height = 3000, +#endif + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 150, + }, + .normal_video = { + .pclk = 560000000, + .linelength = 5880, + .framelength = 3174, + .startx = 0, + .starty = 0, +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 5312, + .grabwindow_height = 2976, +#else + .grabwindow_width = 5328,//5334, + .grabwindow_height = 3000, +#endif + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, +#ifdef SLOW_MOTION_120FPS + .hs_video = { + .pclk = 560000000, + .linelength = 5880, + .framelength = 793,//793, + .startx = 0, + .starty = 0, + .grabwindow_width =1328, //1920, + .grabwindow_height =748,// 1080, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 1200, + }, +#else + .hs_video = { + .pclk = 560000000, + .linelength = 5880, + .framelength = 1587, + .startx = 0, + .starty = 0, +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 2656, //record different mode's width of grabwindow + .grabwindow_height = 1488, //record different mode's height of grabwindow +#else + .grabwindow_width = 2664, //record different mode's width of grabwindow + .grabwindow_height = 1500, //record different mode's height of grabwindow + +#endif + + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 600, + }, +#endif + .slim_video = { + .pclk = 560000000, + .linelength = 5880, + .framelength = 3172, + .startx = 0, + .starty = 0, + .grabwindow_width = 1328,//1280, + .grabwindow_height =748,// 720, + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + .max_framerate = 300, + }, + .custom1= { + .pclk = 560000000, //record different mode's pclk + .linelength = 5880, //record different mode's linelength + .framelength = 3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 2656, //record different mode's width of grabwindow + .grabwindow_height = 1488, //record different mode's height of grabwindow +#else + .grabwindow_width = 2664, //record different mode's width of grabwindow + .grabwindow_height = 1500, //record different mode's height of grabwindow +#endif + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom2= { + .pclk = 560000000, //record different mode's pclk + .linelength = 5880, //record different mode's linelength + .framelength = 3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 2656, //record different mode's width of grabwindow + .grabwindow_height = 1488, //record different mode's height of grabwindow +#else + .grabwindow_width = 2664, //record different mode's width of grabwindow + .grabwindow_height = 1500, //record different mode's height of grabwindow +#endif + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom3= { + .pclk = 560000000, //record different mode's pclk + .linelength = 5880, //record different mode's linelength + .framelength = 3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 2656, //record different mode's width of grabwindow + .grabwindow_height = 1488, //record different mode's height of grabwindow +#else + .grabwindow_width = 2664, //record different mode's width of grabwindow + .grabwindow_height = 1500, //record different mode's height of grabwindow +#endif + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom4= { + .pclk = 560000000, //record different mode's pclk + .linelength = 5880, //record different mode's linelength + .framelength = 3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 2656, //record different mode's width of grabwindow + .grabwindow_height = 1488, //record different mode's height of grabwindow +#else + .grabwindow_width = 2664, //record different mode's width of grabwindow + .grabwindow_height = 1500, //record different mode's height of grabwindow +#endif + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom5= { + .pclk = 560000000, //record different mode's pclk + .linelength = 5880, //record different mode's linelength + .framelength = 3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow +#ifdef FIX_VIEW_ANGLE + .grabwindow_width = 2656, //record different mode's width of grabwindow + .grabwindow_height = 1488, //record different mode's height of grabwindow +#else + .grabwindow_width = 2664, //record different mode's width of grabwindow + .grabwindow_height = 1500, //record different mode's height of grabwindow +#endif + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + + .margin = 16, + .min_shutter = 1, + .max_frame_length = 0xffff, + .ae_shut_delay_frame = 0, + .ae_sensor_gain_delay_frame = 0, + .ae_ispGain_delay_frame = 2, + .ihdr_support = 1, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 10, //support sensor mode num + + .cap_delay_frame = 3, + .pre_delay_frame = 3, + .video_delay_frame = 2, + .hs_video_delay_frame = 2, + .slim_video_delay_frame = 2, + .custom1_delay_frame = 2, + .custom2_delay_frame = 2, + .custom3_delay_frame = 2, + .custom4_delay_frame = 2, + .custom5_delay_frame = 2, + + .isp_driving_current = ISP_DRIVING_6MA, + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI, + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO, + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gr, + .mclk = 24, + .mipi_lane_num = SENSOR_MIPI_4_LANE, + .i2c_addr_table = {0x20, 0x5A, 0xff}, + .i2c_speed = 300, // i2c read/write speed +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter + .gain = 0x100, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = KAL_FALSE, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x20, +}; + + +/* Sensor output window information */ +#ifndef FIX_VIEW_ANGLE +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[10] = +{{ 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2664, 1500}, // Preview + { 5343, 3007, 8, 8, 5343, 3007, 5336, 3000, 0000, 0000, 5336, 3000, 0, 0, 5328, 3000}, // capture + { 5343, 3007, 8, 8, 5343, 3007, 5336, 3000, 0000, 0000, 5336, 3000, 0, 0, 5328, 3000}, // video + #ifdef SLOW_MOTION_120FPS + { 5343, 3007, 8, 12, 5319, 3003, 1328, 748, 0000, 0000, 1328, 748, 0, 0, 1328, 748},// hight video 120 + #else + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2668, 1500}, //hight speed video + #endif + { 5343, 3007, 8, 12, 5319, 3003, 1328, 748, 0000, 0000, 1328, 748, 0, 0, 1328, 748},// slim video + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2664, 1500}, + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2664, 1500}, + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2664, 1500}, + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2664, 1500}, + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2664, 1500}}; + #else + static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[10] = +{{ 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2656, 1488}, // Preview + { 5343, 3007, 8, 8, 5343, 3007, 5336, 3000, 0000, 0000, 5336, 3000, 0, 0, 5312, 2976}, // capture + { 5343, 3007, 8, 8, 5343, 3007, 5336, 3000, 0000, 0000, 5336, 3000, 0, 0, 5312, 2976}, // video + #ifdef SLOW_MOTION_120FPS + { 5343, 3007, 8, 12, 5319, 3003, 1328, 748, 0000, 0000, 1328, 748, 0, 0, 1328, 748},// hight video 120 + #else + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2656, 1488}, //hight speed video + #endif + { 5343, 3007, 8, 12, 5319, 3003, 1328, 748, 0000, 0000, 1328, 748, 0, 0, 1328, 748},// slim video + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2656, 1488}, + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2656, 1488}, + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2656, 1488}, + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2656, 1488}, + { 5343, 3007, 8, 8, 5343, 3007, 2668, 1500, 0000, 0000, 2668, 1500, 0, 0, 2656, 1488}}; + #endif +static SET_PD_BLOCK_INFO_T imgsensor_pd_info = +{ + .i4OffsetX = 8, + .i4OffsetY = 35, + .i4PitchX = 64, + .i4PitchY = 64, + .i4PairNum =16, + .i4SubBlkW =16, + .i4SubBlkH =16, + .i4PosL = {{8,35},{60,35},{24,39},{44,39},{12,55},{56,55},{28,59},{40,59},{28,67},{40,67},{12,71},{56,71},{24,87},{44,87},{8,91},{60,91}}, + .i4PosR = {{8,39},{60,39},{24,43},{44,43},{12,51},{56,51},{28,55},{40,55},{28,71},{40,71},{12,75},{56,75},{24,83},{44,83},{8,87},{60,87}}, +}; + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pusendcmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iReadRegI2C(pusendcmd , 2, (u8*)&get_byte, 2, imgsensor.i2c_write_id); + return ((get_byte<<8)&0xff00)|((get_byte>>8)&0x00ff); +} + + +static void write_cmos_sensor(kal_uint16 addr, kal_uint16 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para >> 8),(char)(para & 0xFF)}; + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pusendcmd , 4, imgsensor.i2c_write_id); +} + +static int read_cmos_sensor_8(kal_uint16 addr) +{ + kal_int16 get_byte=0; + int ret = -1; + char pusendcmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + if(iReadRegI2C(pusendcmd , 2, (u8*)&get_byte,1,imgsensor.i2c_write_id)==0) + ret = get_byte; + return ret; +} + +static void write_cmos_sensor_8(kal_uint16 addr, kal_uint8 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para & 0xFF)}; + kdSetI2CSpeed(imgsensor_info.i2c_speed); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pusendcmd , 3, imgsensor.i2c_write_id); +} + +#if MULTI_WRITE +#define S5K2P8MIPI_table_write_cmos_sensor S5K2P8MIPI_table_write_cmos_sensor_multi +#define I2C_BUFFER_LEN 225 +static kal_uint16 S5K2P8MIPI_table_write_cmos_sensor_multi(kal_uint16* para, kal_uint32 len) +{ + + // LOG_INF("enter S5K2PP8MIPI_table_write_cmos_sensor_multi len %d\n",len); + + char puSendCmd[I2C_BUFFER_LEN]; + kal_uint32 tosend, IDX; + kal_uint16 addr = 0, addr_last = 0, data; + + tosend = 0; + IDX = 0; + + while(IDX < len) + { + addr = para[IDX]; + + { + puSendCmd[tosend++] = (char)(addr >> 8); + puSendCmd[tosend++] = (char)(addr & 0xFF); + data = para[IDX+1]; + puSendCmd[tosend++] = (char)(data >> 8); + puSendCmd[tosend++] = (char)(data & 0xFF); + IDX += 2; + addr_last = addr; + + } + + if (tosend >= I2C_BUFFER_LEN || IDX == len || addr != addr_last) + { + //LOG_INF("IDX %d,tosend %d addr_last 0x%x,addr 0x%x\n",IDX, tosend, addr_last, addr); + iBurstWriteReg_multi(puSendCmd , tosend, imgsensor.i2c_write_id, 4); + tosend = 0; + } + } + //LOG_INF("exit S5K2P8MIPI_table_write_cmos_sensor_multi\n"); + + return 0; +} +#if 0 +static kal_uint16 S5K2P8MIPI_table_write_cmos_sensor_burst(kal_uint16* para, kal_uint32 len) +{ + + LOG_INF("enter S5K2P8MIPI_table_write_cmos_sensor_burst len %d\n",len); + + char puSendCmd[I2C_BUFFER_LEN]; + kal_uint32 tosend, IDX, same_to_send; + kal_uint16 addr = 0, addr_last = 0, data; + + tosend = 0; + IDX = 0; + same_to_send = 0; + while(IDX < len) + { + addr = para[IDX]; + if (tosend == 0) // new (addr, data) to send + { + LOG_INF("tosend == 0"); + puSendCmd[tosend++] = (char)(addr >> 8); + puSendCmd[tosend++] = (char)(addr & 0xFF); + data = para[IDX+1]; + puSendCmd[tosend++] = (char)(data & 0xFF); + IDX += 2; + addr_last = addr; + + } + else if (addr == addr_last+1) // to multiple write the data to sequential register address + { + data = para[IDX+1]; + puSendCmd[tosend++] = (char)(data & 0xFF); + addr_last = addr; + IDX += 2; + } + if (tosend >= I2C_BUFFER_LEN || IDX == len || addr != addr_last)// ||same_to_send==1) + { + LOG_INF("IDX %d,tosend %d addr_last 0x%x,addr 0x%x\n",IDX, tosend, addr_last, addr); + iBurstWriteReg_multi(puSendCmd , tosend, imgsensor.i2c_write_id, tosend); + tosend = 0; + // same_to_send = 0; + } + } + LOG_INF("exit S5K2P8MIPI_table_write_cmos_sensor_burst\n"); + + return 0; +} +#endif +#endif + + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d ", imgsensor.dummy_line, imgsensor.dummy_pixel); + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor(0x0340, imgsensor.frame_length); + write_cmos_sensor(0x0342, imgsensor.line_length); + write_cmos_sensor_8(0x0104, 0x00); + +} /* set_dummy */ + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable = %d\n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + + +static void write_shutter(kal_uint16 shutter) +{ + kal_uint16 realtime_fps = 0; + + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + } else { + // Extend frame length + write_cmos_sensor_8(0x0104,0x01); + write_cmos_sensor(0x0340, imgsensor.frame_length); + write_cmos_sensor_8(0x0104,0x00); + } + + // Update Shutter + write_cmos_sensor_8(0x0104,0x01); + write_cmos_sensor(0x0340, imgsensor.frame_length); + write_cmos_sensor(0x0202, shutter); + write_cmos_sensor_8(0x0104,0x00); + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + + //LOG_INF("frame_length = %d ", frame_length); + +} /* write_shutter */ + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + write_shutter(shutter); +} /* set_shutter */ + + + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0; + + reg_gain = gain/2; + return (kal_uint16)reg_gain; +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + /* 0x350A[0:1], 0x350B[0:7] AGC real gain */ + /* [0:3] = N meams N /16 X */ + /* [4:9] = M meams M X */ + /* Total gain = M + N /16 X */ + + // + if (gain < BASEGAIN || gain > 32 * BASEGAIN) { + LOG_INF("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 32 * BASEGAIN) + gain = 32 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x ", gain, reg_gain); + + write_cmos_sensor_8(0x0104, 0x01); + write_cmos_sensor_8(0x0204,(reg_gain>>8)); + write_cmos_sensor_8(0x0205,(reg_gain&0xff)); + write_cmos_sensor_8(0x0104, 0x00); + + return gain; +} /* set_gain */ + +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ +#if 1 + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length first + write_cmos_sensor_8(0x0104,0x01); + write_cmos_sensor(0x0340, imgsensor.frame_length); + + //write_cmos_sensor(0x0202, se); + //write_cmos_sensor(0x021e,le); + write_cmos_sensor(0x602A,0x021e); + write_cmos_sensor(0x6f12,le); + write_cmos_sensor(0x602A,0x0202); + write_cmos_sensor(0x6f12,se); + write_cmos_sensor_8(0x0104,0x00); + LOG_INF("iHDR:imgsensor.frame_length=%d\n",imgsensor.frame_length); + set_gain(gain); + } + +#endif + + + + + +} + + + +static void set_mirror_flip(kal_uint8 image_mirror) +{ + /* LOG_INF("image_mirror = %d", image_mirror); */ + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + spin_lock(&imgsensor_drv_lock); + imgsensor.mirror= image_mirror; + spin_unlock(&imgsensor_drv_lock); + switch (image_mirror) { + + case IMAGE_NORMAL: + write_cmos_sensor_8(0x0101,0x00); // Gr + break; + case IMAGE_H_MIRROR: + write_cmos_sensor_8(0x0101,0x01); + break; + case IMAGE_V_MIRROR: + write_cmos_sensor_8(0x0101,0x02); + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor_8(0x0101,0x03);//Gb + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} +#if MULTI_WRITE +kal_uint16 addr_data_pair_init_RWB[] = +{ + 0x6214,0x7970, //open all clocks + 0x6218,0x7150, //open all clocks + 0x6028,0x2000, + 0x602A,0x2E00, + 0x6F12,0x0448, + 0x6F12,0x0349, + 0x6F12,0x0160, + 0x6F12,0xC26A, + 0x6F12,0x511A, + 0x6F12,0x8180, + 0x6F12,0x00F0, + 0x6F12,0x10B9, + 0x6F12,0x2000, + 0x6F12,0x315C, + 0x6F12,0x2000, + 0x6F12,0x1AE0, + 0x6F12,0x0000, + 0x6F12,0x0000, + 0x6F12,0x0000, + 0x6F12,0x0000, + 0x6F12,0x2DE9, + 0x6F12,0xF041, + 0x6F12,0x0646, + 0x6F12,0x9A48, + 0x6F12,0x0F46, + 0x6F12,0x9046, + 0x6F12,0x4068, + 0x6F12,0x0022, + 0x6F12,0x85B2, + 0x6F12,0x040C, + 0x6F12,0x2946, + 0x6F12,0x2046, + 0x6F12,0x00F0, + 0x6F12,0x4CF9, + 0x6F12,0x4246, + 0x6F12,0x3946, + 0x6F12,0x3046, + 0x6F12,0x00F0, + 0x6F12,0x4CF9, + 0x6F12,0x9348, + 0x6F12,0x807E, + 0x6F12,0x28B1, + 0x6F12,0x9248, + 0x6F12,0x90F8, + 0x6F12,0xFA00, + 0x6F12,0x08B1, + 0x6F12,0x0122, + 0x6F12,0x00E0, + 0x6F12,0x0022, + 0x6F12,0x9048, + 0x6F12,0x0280, + 0x6F12,0x2946, + 0x6F12,0x2046, + 0x6F12,0xBDE8, + 0x6F12,0xF041, + 0x6F12,0x0122, + 0x6F12,0x00F0, + 0x6F12,0x34B9, + 0x6F12,0x8C4A, + 0x6F12,0x10B5, + 0x6F12,0x1268, + 0x6F12,0xB2F8, + 0x6F12,0xC230, + 0x6F12,0x874A, + 0x6F12,0x546B, + 0x6F12,0xB2F8, + 0x6F12,0x2E21, + 0x6F12,0x6409, + 0x6F12,0x6343, + 0x6F12,0x4FF4, + 0x6F12,0x7A74, + 0x6F12,0x6243, + 0x6F12,0x5209, + 0x6F12,0xB3FB, + 0x6F12,0xF2F3, + 0x6F12,0x021D, + 0x6F12,0x8A42, + 0x6F12,0x02D2, + 0x6F12,0x0A1A, + 0x6F12,0x121F, + 0x6F12,0x00E0, + 0x6F12,0x0022, + 0x6F12,0x9A42, + 0x6F12,0x00D8, + 0x6F12,0x1A46, + 0x6F12,0x8048, + 0x6F12,0x0280, + 0x6F12,0x10BD, + 0x6F12,0x2DE9, + 0x6F12,0xF34F, + 0x6F12,0x0446, + 0x6F12,0x7848, + 0x6F12,0x83B0, + 0x6F12,0x0022, + 0x6F12,0xC068, + 0x6F12,0x010C, + 0x6F12,0x80B2, + 0x6F12,0xCDE9, + 0x6F12,0x0001, + 0x6F12,0x0146, + 0x6F12,0x0198, + 0x6F12,0x00F0, + 0x6F12,0x07F9, + 0x6F12,0xDFF8, + 0x6F12,0xE091, + 0x6F12,0xDFF8, + 0x6F12,0xD4B1, + 0x6F12,0x0021, + 0x6F12,0x99F8, + 0x6F12,0x2A70, + 0x6F12,0x89F8, + 0x6F12,0x2A10, + 0x6F12,0xDFF8, + 0x6F12,0xBCA1, + 0x6F12,0x734D, + 0x6F12,0xDBF8, + 0x6F12,0x0000, + 0x6F12,0x9AF8, + 0x6F12,0xFA80, + 0x6F12,0xAE8A, + 0x6F12,0xB0F8, + 0x6F12,0xC400, + 0x6F12,0x20B1, + 0x6F12,0xA08A, + 0x6F12,0x296E, + 0x6F12,0x4843, + 0x6F12,0x000B, + 0x6F12,0xA882, + 0x6F12,0x2046, + 0x6F12,0x0499, + 0x6F12,0x00F0, + 0x6F12,0xF4F8, + 0x6F12,0xAE82, + 0x6F12,0xB9F8, + 0x6F12,0x1C00, + 0x6F12,0x9AF8, + 0x6F12,0xFA50, + 0x6F12,0xC0F3, + 0x6F12,0x0030, + 0x6F12,0x4545, + 0x6F12,0x08D0, + 0x6F12,0x38B1, + 0x6F12,0xDBF8, + 0x6F12,0x0000, + 0x6F12,0xB0F8, + 0x6F12,0xC600, + 0x6F12,0x10B1, + 0x6F12,0x0020, + 0x6F12,0xCAF8, + 0x6F12,0x0001, + 0x6F12,0x17F0, + 0x6F12,0xFF00, + 0x6F12,0x89F8, + 0x6F12,0x2A00, + 0x6F12,0x03D0, + 0x6F12,0xA18A, + 0x6F12,0x2068, + 0x6F12,0x00F0, + 0x6F12,0xDEF8, + 0x6F12,0xDDE9, + 0x6F12,0x0010, + 0x6F12,0x05B0, + 0x6F12,0x0122, + 0x6F12,0xBDE8, + 0x6F12,0xF04F, + 0x6F12,0x00F0, + 0x6F12,0xC7B8, + 0x6F12,0x70B5, + 0x6F12,0x0446, + 0x6F12,0x5148, + 0x6F12,0x0022, + 0x6F12,0x0169, + 0x6F12,0x0D0C, + 0x6F12,0x8EB2, + 0x6F12,0x3146, + 0x6F12,0x2846, + 0x6F12,0x00F0, + 0x6F12,0xBCF8, + 0x6F12,0x2046, + 0x6F12,0x00F0, + 0x6F12,0xCDF8, + 0x6F12,0x94F8, + 0x6F12,0x6000, + 0x6F12,0x0128, + 0x6F12,0x07D1, + 0x6F12,0x5148, + 0x6F12,0x0068, + 0x6F12,0x8078, + 0x6F12,0xF528, + 0x6F12,0x02D0, + 0x6F12,0x0020, + 0x6F12,0x84F8, + 0x6F12,0x6000, + 0x6F12,0x3146, + 0x6F12,0x2846, + 0x6F12,0xBDE8, + 0x6F12,0x7040, + 0x6F12,0x0122, + 0x6F12,0x00F0, + 0x6F12,0xA6B8, + 0x6F12,0x70B5, + 0x6F12,0x0446, + 0x6F12,0x4048, + 0x6F12,0x0022, + 0x6F12,0x4069, + 0x6F12,0x86B2, + 0x6F12,0x050C, + 0x6F12,0x3146, + 0x6F12,0x2846, + 0x6F12,0x00F0, + 0x6F12,0x9BF8, + 0x6F12,0x2046, + 0x6F12,0x00F0, + 0x6F12,0xB1F8, + 0x6F12,0x207C, + 0x6F12,0x40B1, + 0x6F12,0x424A, + 0x6F12,0xA168, + 0x6F12,0x2068, + 0x6F12,0x92F8, + 0x6F12,0xB921, + 0x6F12,0x00F0, + 0x6F12,0xADF8, + 0x6F12,0x4049, + 0x6F12,0x0880, + 0x6F12,0x3146, + 0x6F12,0x2846, + 0x6F12,0xBDE8, + 0x6F12,0x7040, + 0x6F12,0x0122, + 0x6F12,0x00F0, + 0x6F12,0x86B8, + 0x6F12,0x2DE9, + 0x6F12,0xF041, + 0x6F12,0x304C, + 0x6F12,0x8046, + 0x6F12,0x0022, + 0x6F12,0xA069, + 0x6F12,0x87B2, + 0x6F12,0x060C, + 0x6F12,0x3946, + 0x6F12,0x3046, + 0x6F12,0x00F0, + 0x6F12,0x7AF8, + 0x6F12,0x2F4D, + 0x6F12,0xB8F1, + 0x6F12,0x000F, + 0x6F12,0x0BD1, + 0x6F12,0x3248, + 0x6F12,0x0078, + 0x6F12,0x40B1, + 0x6F12,0x2868, + 0x6F12,0xB0F8, + 0x6F12,0x6A00, + 0x6F12,0x20B1, + 0x6F12,0x2188, + 0x6F12,0x8842, + 0x6F12,0x01D0, + 0x6F12,0x0120, + 0x6F12,0x00E0, + 0x6F12,0x0020, + 0x6F12,0x38B1, + 0x6F12,0x2449, + 0x6F12,0x0020, + 0x6F12,0xC1F8, + 0x6F12,0xDC01, + 0x6F12,0x81F8, + 0x6F12,0xCC01, + 0x6F12,0x00F0, + 0x6F12,0x83F8, + 0x6F12,0x2868, + 0x6F12,0xB0F8, + 0x6F12,0x6A00, + 0x6F12,0x2080, + 0x6F12,0x4046, + 0x6F12,0x00F0, + 0x6F12,0x81F8, + 0x6F12,0x3946, + 0x6F12,0x3046, + 0x6F12,0xBDE8, + 0x6F12,0xF041, + 0x6F12,0x0122, + 0x6F12,0x00F0, + 0x6F12,0x52B8, + 0x6F12,0x10B5, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0x1721, + 0x6F12,0x2048, + 0x6F12,0x00F0, + 0x6F12,0x78F8, + 0x6F12,0x144C, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0xD711, + 0x6F12,0x6060, + 0x6F12,0x1D48, + 0x6F12,0x00F0, + 0x6F12,0x70F8, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0x0D11, + 0x6F12,0xA060, + 0x6F12,0x1B48, + 0x6F12,0x00F0, + 0x6F12,0x69F8, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0xB711, + 0x6F12,0x2061, + 0x6F12,0x1848, + 0x6F12,0x00F0, + 0x6F12,0x62F8, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0xE701, + 0x6F12,0xE060, + 0x6F12,0x1648, + 0x6F12,0x00F0, + 0x6F12,0x5BF8, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0xB301, + 0x6F12,0x6061, + 0x6F12,0x1348, + 0x6F12,0x00F0, + 0x6F12,0x54F8, + 0x6F12,0xA061, + 0x6F12,0x0020, + 0x6F12,0x2080, + 0x6F12,0x10BD, + 0x6F12,0x0000, + 0x6F12,0x2000, + 0x6F12,0x3140, + 0x6F12,0x2000, + 0x6F12,0x1B10, + 0x6F12,0x2000, + 0x6F12,0x2530, + 0x6F12,0x4000, + 0x6F12,0x9802, + 0x6F12,0x2000, + 0x6F12,0x0550, + 0x6F12,0x4000, + 0x6F12,0xF000, + 0x6F12,0x2000, + 0x6F12,0x1300, + 0x6F12,0x2000, + 0x6F12,0x2890, + 0x6F12,0x2000, + 0x6F12,0x02C0, + 0x6F12,0x2000, + 0x6F12,0x1410, + 0x6F12,0x4000, + 0x6F12,0xA358, + 0x6F12,0x0000, + 0x6F12,0x15F7, + 0x6F12,0x0000, + 0x6F12,0x7A4F, + 0x6F12,0x0000, + 0x6F12,0x4A69, + 0x6F12,0x0000, + 0x6F12,0x1349, + 0x6F12,0x0000, + 0x6F12,0x3091, + 0x6F12,0x0000, + 0x6F12,0x6057, + 0x6F12,0x40F2, + 0x6F12,0xE96C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x41F2, + 0x6F12,0xF75C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x41F2, + 0x6F12,0x493C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x41F2, + 0x6F12,0x9D1C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x44F6, + 0x6F12,0x692C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x43F2, + 0x6F12,0x910C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x40F2, + 0x6F12,0x156C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x42F2, + 0x6F12,0xC71C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x46F2, + 0x6F12,0x570C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x4AF6, + 0x6F12,0x850C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x3EA6,0xFFFF, //fe_isp_dadlc_analog_gain_thrshold_for_ladlc_low + 0x3EA8,0xFFFF, //fe_isp_dadlc_analog_gain_thrshold_for_ladlc_high + 0x3A56,0x3BB8, //Sampling enable + 0xF476,0x0040, //DBR + 0xF40C,0x1180, //CLP on, LDB off + 0xF480,0x0015, //CLP LVL + 0x39EE,0x0507, + 0x3A06,0x0605, + 0x39D0,0x0707, + 0xF432,0x0100, //DBS + 0xF4A6,0x00C0, //RDV + 0xF42E,0x0060, //CDS + 0xF49C,0x0000, //RMP + 0xF496,0x0000, //REF + 0xF49E,0x005E, //ADC_SAT + 0xF47A,0x0017, //VRD 3.2V + 0xF462,0x0000, //VPIX 2.92V + 0xF460,0x0020, //VTG 3.8V + 0x3A64,0x0010, + 0x3A66,0x0010, + 0x3A68,0x0010, + 0xF426,0x0007, //LAT START + 0xF428,0x0004, //LAT WIDTH + 0xF42A,0x0004, //HOLD START + 0xF42C,0x0004, //HOLD WIDTH + 0x32BC,0x000D, //pixel boost + 0x3298,0x005E, + 0x3880,0x010B, + 0x3886,0x010A, + 0x388C,0x021A, + 0x389E,0x021C, + 0x38A4,0x0000, + 0x38AA,0x015C, + 0x38B0,0x015B, + 0x38B6,0x021A, + 0x38C2,0x0070, + 0x38C8,0x021C, + 0x38CE,0x0000, + 0x3976,0x0006, + 0x31C0,0x0C40, //default 0004 + 0x31C2,0x0C48, //default 0B1C + 0x31B2,0x080C, + 0x31B4,0x0401, + 0x31B2,0x0804, + 0x39D6,0x0F0F, + 0x39DC,0x3030, + 0x39B0,0x0000, + 0x30C2,0x0300, + 0x3AF2,0x0000, + 0x3AF4,0x0000, + 0x3AF6,0x0000, + 0x3AF8,0x0000, + 0x3AFA,0x0000, + 0x3AFC,0x0000, + 0x3AFE,0x0000, + 0x3B00,0x0000, + 0x3B02,0x0000, + 0x3B04,0x0000, + 0x3B06,0x0000, + 0x3B08,0x0000, + 0x3B0A,0x0000, + 0x3B0C,0x0000, + 0x3B0E,0x0000, + 0x3B10,0x0000, + 0x3B12,0x0000, + 0x3B14,0x0000, + 0x3B16,0x0000, + 0x3B18,0x0000, + 0x3B1A,0x0000, + 0x3B1C,0x0000, + 0x3B1E,0x0000, + 0x3B20,0x0000, + 0x3B22,0x0000, + 0x3B24,0x0000, + 0x3B26,0x0000, + 0x3B28,0x0000, + 0x3B2A,0x0000, + 0x3B2C,0x0000, + 0x3B2E,0x0000, + 0x3B30,0x0000, + 0x3B32,0x0000, + 0x3B34,0x0000, + 0x3B36,0x0000, + 0x3B38,0x0000, + 0x3B3A,0x0000, + 0x3B3C,0x0000, + 0x3B3E,0x0000, + 0x3B40,0x0000, + 0x3B42,0x0000, + 0x3B44,0x0000, + 0x3B46,0x0000, + 0x3B48,0x0000, + 0x3B4A,0x0000, + 0x3B4C,0x0000, + 0x3B4E,0x0000, + 0x3B50,0x0000, + 0x3B52,0x0000, + 0x3B54,0x0000, + 0x3B56,0x0000, + 0x3B58,0x0000, + 0x3B5A,0x0000, + 0x3B5C,0x0000, + 0x3B5E,0x0000, + 0x3B60,0x0000, + 0x3B62,0x0000, + 0x3B64,0x0000, + 0x3B66,0x0000, + 0x3B68,0x0000, + 0x3B6A,0x0000, + 0x3B6C,0x0000, + 0x3B6E,0x0000, + 0x3B70,0x0000, + 0x3B72,0x0000, + 0x3B74,0x0000, + 0x3B76,0x0000, + 0x3B78,0x0000, + 0x3B7A,0x0000, + 0x3B7C,0x0000, + 0x3B7E,0x0000, + 0x3B80,0x0000, + 0x3B82,0x0000, + 0x3B84,0x0000, + 0x3B86,0x0000, + 0x3B88,0x0000, + 0x3B8A,0x0000, + 0x3B8C,0x0000, + 0x3B8E,0x0000, + 0x3B90,0x0000, + 0x3B92,0x0000, + 0x3B94,0x0000, + 0x3B96,0x0000, + 0x3B98,0x0000, + 0x3B9A,0x0000, + 0x3B9C,0x0000, + 0x3B9E,0x0000, + 0x3BA0,0x0000, + 0x3BA2,0x0000, + 0x3BA4,0x0000, + 0x3BA6,0x0000, + 0x3BA8,0x0000, + 0x3BAA,0x0000, + 0x3BAC,0x0000, + 0x3BAE,0x0000, + 0x3BB0,0x0000, + 0x3BB2,0x0000, + 0x3BB4,0x0000, + 0x3BB6,0x0000, + 0x3BB8,0x0000, + 0x3BBA,0x0000, + 0x3BBC,0x0000, + 0x3BBE,0x0000, + 0x3BC0,0x0000, + 0x3BC2,0x0000, + 0x3BC4,0x0000, + 0x3BC6,0x0000, + 0x3BC8,0x0000, + 0x3BCA,0x0000, + 0x3BCC,0x0000, + 0x3BCE,0x0000, + 0x3BD0,0x0000, + 0x3BD2,0x0000, + 0x3BD4,0x0000, + 0x3BD6,0x0000, + 0x3BD8,0x0000, + 0x3BDA,0x0000, + 0x3BDC,0x0000, + 0x3BDE,0x0000, + 0x3BE0,0x0000, + 0x3BE2,0x0000, + 0x3BE4,0x0000, + 0x3BE6,0x0000, + 0x3BE8,0x0000, + 0x3BEA,0x0000, + 0x3BEC,0x0000, + 0x3BEE,0x0000, + 0x3BF0,0x0000, + 0x3BF2,0x0000, + 0x3BF4,0x0000, + 0x3BF6,0x0000, + 0x3BF8,0x0000, + 0x3BFA,0x0000, + 0x3BFC,0x0000, + 0x3BFE,0x0000, + 0x3C00,0x0000, + 0x3C02,0x0000, + 0x3C04,0x0000, + 0x3C06,0x0000, + 0x3C08,0x0000, + 0x3C0A,0x0000, + 0x3C0C,0x0000, + 0x3C0E,0x0000, + 0x3C10,0x0000, + 0x3C12,0x0000, + 0x3C14,0x0000, + 0x3C16,0x0000, + 0x3C18,0x0000, + 0x3C1A,0x0000, + 0x3C1C,0x0000, + 0x3C1E,0x0000, + 0x3C20,0x0000, + 0x3C22,0x0000, + 0x3C24,0x0000, + 0x3C26,0x0000, + 0x3C28,0x0000, + 0x3C2A,0x0000, + 0x3C2C,0x0000, + 0x3C2E,0x0000, + 0x3C30,0x0000, + 0x3C32,0x0000, + 0x3C34,0x0000, + 0x3C36,0x0000, + 0x3C38,0x0000, + 0x3C3A,0x0000, + 0x3C3C,0x0000, + 0x3C3E,0x0000, + 0x3C40,0x0000, + 0x3C42,0x0000, + 0x3C44,0x0000, + 0x3C46,0x0000, + 0x3C48,0x0000, + 0x3C4A,0x0000, + 0x3C4C,0x0000, + 0x3C4E,0x0000, + 0x3C50,0x0000, + 0x3C52,0x0000, + 0x3C54,0x0000, + 0x3C56,0x0000, + 0x3C58,0x0000, + 0x3C5A,0x0000, + 0x3C5C,0x0000, + 0x3C5E,0x0000, + 0x3C60,0x0000, + 0x3C62,0x0000, + 0x3C64,0x0000, + 0x3C66,0x0000, + 0x3C68,0x0000, + 0x3C6A,0x0000, + 0x3C6C,0x0000, + 0x3C6E,0x0000, + 0x3C70,0x0000, + 0x3C72,0x0000, + 0x3C74,0x0000, + 0x3C76,0x0000, + 0x3C78,0x0000, + 0x3C7A,0x0000, + 0x3C7C,0x0000, + 0x3C7E,0x0000, + 0x3C80,0x0000, + 0x3C82,0x0000, + 0x3C84,0x0000, + 0x3C86,0x0000, + 0x3C88,0x0000, + 0x3C8A,0x0000, + 0x3C8C,0x0000, + 0x3C8E,0x0000, + 0x3C90,0x0000, + 0x3C92,0x0000, + 0x3C94,0x0000, + 0x3C96,0x0000, + 0x3C98,0x0000, + 0x3C9A,0x0000, + 0x3C9C,0x0000, + 0x3C9E,0x0000, + 0x3CA0,0x0000, + 0x3CA2,0x0000, + 0x3CA4,0x0000, + 0x3CA6,0x0000, + 0x3CA8,0x0000, + 0x3CAA,0x0000, + 0x3CAC,0x0000, + 0x3CAE,0x0000, + 0x3CB0,0x0000, + 0x3CB2,0x0000, + 0x3CB4,0x0000, + 0x3CB6,0x0000, + 0x3CB8,0x0000, + 0x3CBA,0x0000, + 0x3CBC,0x0000, + 0x3CBE,0x0000, + 0x3CC0,0x0000, + 0x3CC2,0x0000, + 0x3CC4,0x0000, + 0x3CC6,0x0000, + 0x3CC8,0x0000, + 0x3CCA,0x0000, + 0x3CCC,0x0000, + 0x3CCE,0x0000, + 0x3CD0,0x0000, + 0x3CD2,0x0000, + 0x3CD4,0x0000, + 0x3CD6,0x0000, + 0x3CD8,0x0000, + 0x3CDA,0x0000, + 0x3CDC,0x0000, + 0x3CDE,0x0000, + 0x3CE0,0x0000, + 0x3CE2,0x0000, + 0x3CE4,0x0000, + 0x3CE6,0x0000, + 0x3CE8,0x0000, + 0x3CEA,0x0000, + 0x3CEC,0x0000, + 0x3CEE,0x0000, + 0x3CF0,0x0000, + 0x3CF2,0x0000, + 0x3DD4,0x2000, + 0x3DD6,0x2000, + 0x3DDC,0x2000, // + 0x3DDE,0x2000, // + 0x3DF4,0x2000, // + 0x3DF6,0x2000, // + 0x3DFC,0x2000, // + 0x3DFE,0x2000, // + 0x3E14,0x2000, // + 0x3E16,0x2000, // + 0x3E1C,0x2000, // + 0x3E1E,0x2000, // + 0x3E76,0x0A04, + 0x6226,0x0001, //Open clock to access ELG memory + 0x70B6,0x0001, //Disable ELG + 0x3050,0x0002, + 0x3068,0x0000, + 0x6028,0x2000, + 0x602A,0x1410, + 0x6F12,0x0000, + 0x602A,0x1416, + 0x6F12,0x0108, + 0x6F12,0x0108, + 0x6F12,0x0A08, + 0x602A,0x141A, //modify address from 141B to 141A + 0x6F12,0x0A08, + //S6F120203 : delete this register + 0x6F12,0x0202, + 0x6F12,0x0603, + //S6F120603 : delete this register + + 0x602A,0x1412, + 0x6F12,0x0100, + 0x3E9E,0x0011, + 0x3EA2,0x0033, + //BPC + 0x6028,0x2000, + 0x602A,0x1748, + 0x6F12,0x0101, + 0x0B04,0x0101, + 0x306E,0x039C, //smiaRegs_vendor_bpc_otp_clusters_address + 0x3072,0x00FF, //smiaRegs_vendor_bpc_max_clusters_in_otp + 0x30C4,0x0001, //smiaRegs_vendor_tnp_use_dgains_for_ladlc_enable + 0x30C6,0x0001, //smiaRegs_vendor_tnp_reset_iir_on_ladlc_on_off + 0x3E86,0x0104, + 0x302E,0x0102, + //Immediate abort + 0x3028,0x0000, //smiaRegs_vendor_sensor_abort_timing_method_on_rolling_sh + 0x302A,0x0000, //smiaRegs_vendor_sensor_abort_timing_on_sw_stby + 0x3A70,0x0000, + 0x3A72,0xFB98, + 0x3A74,0x0000, + 0x3A76,0xFB98, + 0x3A78,0xFD32, + 0x3A7A,0x0000, + 0x3A7C,0xFB32, + 0x3A7E,0x0000, + 0x3A80,0x0000, + 0x3A82,0xFB98, + 0x3A84,0x0000, + 0x3A86,0xFB98, + 0x3A88,0xFD32, + 0x3A8A,0x0000, + 0x3A8C,0xFD32, + 0x3A8E,0x0000, + 0x3AB2,0x0000, + 0x3AB4,0x0000, + 0x3AB6,0x0000, + 0x3AB8,0x0000, + 0x3ABA,0x0000, + 0x3ABC,0x0000, + 0x3ABE,0x0000, + 0x3AC0,0x0000, + 0x3AC2,0x0000, + 0x3AC4,0x0000, + 0x3AC6,0x0000, + 0x3AC8,0x0000, + 0x3ACA,0x0000, + 0x3ACC,0x0000, + 0x3ACE,0x0000, +}; + + + kal_uint16 addr_data_pair_init[] = +{ + 0x6214,0x7970, //open all clocks + 0x6218,0x7150, //open all clocks + 0x6028,0x2000, + 0x602A,0x2E00, + 0x6F12,0x0448, + 0x6F12,0x0349, + 0x6F12,0x0160, + 0x6F12,0xC26A, + 0x6F12,0x511A, + 0x6F12,0x8180, + 0x6F12,0x00F0, + 0x6F12,0x10B9, + 0x6F12,0x2000, + 0x6F12,0x315C, + 0x6F12,0x2000, + 0x6F12,0x1AE0, + 0x6F12,0x0000, + 0x6F12,0x0000, + 0x6F12,0x0000, + 0x6F12,0x0000, + 0x6F12,0x2DE9, + 0x6F12,0xF041, + 0x6F12,0x0646, + 0x6F12,0x9A48, + 0x6F12,0x0F46, + 0x6F12,0x9046, + 0x6F12,0x4068, + 0x6F12,0x0022, + 0x6F12,0x85B2, + 0x6F12,0x040C, + 0x6F12,0x2946, + 0x6F12,0x2046, + 0x6F12,0x00F0, + 0x6F12,0x4CF9, + 0x6F12,0x4246, + 0x6F12,0x3946, + 0x6F12,0x3046, + 0x6F12,0x00F0, + 0x6F12,0x4CF9, + 0x6F12,0x9348, + 0x6F12,0x807E, + 0x6F12,0x28B1, + 0x6F12,0x9248, + 0x6F12,0x90F8, + 0x6F12,0xFA00, + 0x6F12,0x08B1, + 0x6F12,0x0122, + 0x6F12,0x00E0, + 0x6F12,0x0022, + 0x6F12,0x9048, + 0x6F12,0x0280, + 0x6F12,0x2946, + 0x6F12,0x2046, + 0x6F12,0xBDE8, + 0x6F12,0xF041, + 0x6F12,0x0122, + 0x6F12,0x00F0, + 0x6F12,0x34B9, + 0x6F12,0x8C4A, + 0x6F12,0x10B5, + 0x6F12,0x1268, + 0x6F12,0xB2F8, + 0x6F12,0xC230, + 0x6F12,0x874A, + 0x6F12,0x546B, + 0x6F12,0xB2F8, + 0x6F12,0x2E21, + 0x6F12,0x6409, + 0x6F12,0x6343, + 0x6F12,0x4FF4, + 0x6F12,0x7A74, + 0x6F12,0x6243, + 0x6F12,0x5209, + 0x6F12,0xB3FB, + 0x6F12,0xF2F3, + 0x6F12,0x021D, + 0x6F12,0x8A42, + 0x6F12,0x02D2, + 0x6F12,0x0A1A, + 0x6F12,0x121F, + 0x6F12,0x00E0, + 0x6F12,0x0022, + 0x6F12,0x9A42, + 0x6F12,0x00D8, + 0x6F12,0x1A46, + 0x6F12,0x8048, + 0x6F12,0x0280, + 0x6F12,0x10BD, + 0x6F12,0x2DE9, + 0x6F12,0xF34F, + 0x6F12,0x0446, + 0x6F12,0x7848, + 0x6F12,0x83B0, + 0x6F12,0x0022, + 0x6F12,0xC068, + 0x6F12,0x010C, + 0x6F12,0x80B2, + 0x6F12,0xCDE9, + 0x6F12,0x0001, + 0x6F12,0x0146, + 0x6F12,0x0198, + 0x6F12,0x00F0, + 0x6F12,0x07F9, + 0x6F12,0xDFF8, + 0x6F12,0xE091, + 0x6F12,0xDFF8, + 0x6F12,0xD4B1, + 0x6F12,0x0021, + 0x6F12,0x99F8, + 0x6F12,0x2A70, + 0x6F12,0x89F8, + 0x6F12,0x2A10, + 0x6F12,0xDFF8, + 0x6F12,0xBCA1, + 0x6F12,0x734D, + 0x6F12,0xDBF8, + 0x6F12,0x0000, + 0x6F12,0x9AF8, + 0x6F12,0xFA80, + 0x6F12,0xAE8A, + 0x6F12,0xB0F8, + 0x6F12,0xC400, + 0x6F12,0x20B1, + 0x6F12,0xA08A, + 0x6F12,0x296E, + 0x6F12,0x4843, + 0x6F12,0x000B, + 0x6F12,0xA882, + 0x6F12,0x2046, + 0x6F12,0x0499, + 0x6F12,0x00F0, + 0x6F12,0xF4F8, + 0x6F12,0xAE82, + 0x6F12,0xB9F8, + 0x6F12,0x1C00, + 0x6F12,0x9AF8, + 0x6F12,0xFA50, + 0x6F12,0xC0F3, + 0x6F12,0x0030, + 0x6F12,0x4545, + 0x6F12,0x08D0, + 0x6F12,0x38B1, + 0x6F12,0xDBF8, + 0x6F12,0x0000, + 0x6F12,0xB0F8, + 0x6F12,0xC600, + 0x6F12,0x10B1, + 0x6F12,0x0020, + 0x6F12,0xCAF8, + 0x6F12,0x0001, + 0x6F12,0x17F0, + 0x6F12,0xFF00, + 0x6F12,0x89F8, + 0x6F12,0x2A00, + 0x6F12,0x03D0, + 0x6F12,0xA18A, + 0x6F12,0x2068, + 0x6F12,0x00F0, + 0x6F12,0xDEF8, + 0x6F12,0xDDE9, + 0x6F12,0x0010, + 0x6F12,0x05B0, + 0x6F12,0x0122, + 0x6F12,0xBDE8, + 0x6F12,0xF04F, + 0x6F12,0x00F0, + 0x6F12,0xC7B8, + 0x6F12,0x70B5, + 0x6F12,0x0446, + 0x6F12,0x5148, + 0x6F12,0x0022, + 0x6F12,0x0169, + 0x6F12,0x0D0C, + 0x6F12,0x8EB2, + 0x6F12,0x3146, + 0x6F12,0x2846, + 0x6F12,0x00F0, + 0x6F12,0xBCF8, + 0x6F12,0x2046, + 0x6F12,0x00F0, + 0x6F12,0xCDF8, + 0x6F12,0x94F8, + 0x6F12,0x6000, + 0x6F12,0x0128, + 0x6F12,0x07D1, + 0x6F12,0x5148, + 0x6F12,0x0068, + 0x6F12,0x8078, + 0x6F12,0xF528, + 0x6F12,0x02D0, + 0x6F12,0x0020, + 0x6F12,0x84F8, + 0x6F12,0x6000, + 0x6F12,0x3146, + 0x6F12,0x2846, + 0x6F12,0xBDE8, + 0x6F12,0x7040, + 0x6F12,0x0122, + 0x6F12,0x00F0, + 0x6F12,0xA6B8, + 0x6F12,0x70B5, + 0x6F12,0x0446, + 0x6F12,0x4048, + 0x6F12,0x0022, + 0x6F12,0x4069, + 0x6F12,0x86B2, + 0x6F12,0x050C, + 0x6F12,0x3146, + 0x6F12,0x2846, + 0x6F12,0x00F0, + 0x6F12,0x9BF8, + 0x6F12,0x2046, + 0x6F12,0x00F0, + 0x6F12,0xB1F8, + 0x6F12,0x207C, + 0x6F12,0x40B1, + 0x6F12,0x424A, + 0x6F12,0xA168, + 0x6F12,0x2068, + 0x6F12,0x92F8, + 0x6F12,0xB921, + 0x6F12,0x00F0, + 0x6F12,0xADF8, + 0x6F12,0x4049, + 0x6F12,0x0880, + 0x6F12,0x3146, + 0x6F12,0x2846, + 0x6F12,0xBDE8, + 0x6F12,0x7040, + 0x6F12,0x0122, + 0x6F12,0x00F0, + 0x6F12,0x86B8, + 0x6F12,0x2DE9, + 0x6F12,0xF041, + 0x6F12,0x304C, + 0x6F12,0x8046, + 0x6F12,0x0022, + 0x6F12,0xA069, + 0x6F12,0x87B2, + 0x6F12,0x060C, + 0x6F12,0x3946, + 0x6F12,0x3046, + 0x6F12,0x00F0, + 0x6F12,0x7AF8, + 0x6F12,0x2F4D, + 0x6F12,0xB8F1, + 0x6F12,0x000F, + 0x6F12,0x0BD1, + 0x6F12,0x3248, + 0x6F12,0x0078, + 0x6F12,0x40B1, + 0x6F12,0x2868, + 0x6F12,0xB0F8, + 0x6F12,0x6A00, + 0x6F12,0x20B1, + 0x6F12,0x2188, + 0x6F12,0x8842, + 0x6F12,0x01D0, + 0x6F12,0x0120, + 0x6F12,0x00E0, + 0x6F12,0x0020, + 0x6F12,0x38B1, + 0x6F12,0x2449, + 0x6F12,0x0020, + 0x6F12,0xC1F8, + 0x6F12,0xDC01, + 0x6F12,0x81F8, + 0x6F12,0xCC01, + 0x6F12,0x00F0, + 0x6F12,0x83F8, + 0x6F12,0x2868, + 0x6F12,0xB0F8, + 0x6F12,0x6A00, + 0x6F12,0x2080, + 0x6F12,0x4046, + 0x6F12,0x00F0, + 0x6F12,0x81F8, + 0x6F12,0x3946, + 0x6F12,0x3046, + 0x6F12,0xBDE8, + 0x6F12,0xF041, + 0x6F12,0x0122, + 0x6F12,0x00F0, + 0x6F12,0x52B8, + 0x6F12,0x10B5, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0x1721, + 0x6F12,0x2048, + 0x6F12,0x00F0, + 0x6F12,0x78F8, + 0x6F12,0x144C, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0xD711, + 0x6F12,0x6060, + 0x6F12,0x1D48, + 0x6F12,0x00F0, + 0x6F12,0x70F8, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0x0D11, + 0x6F12,0xA060, + 0x6F12,0x1B48, + 0x6F12,0x00F0, + 0x6F12,0x69F8, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0xB711, + 0x6F12,0x2061, + 0x6F12,0x1848, + 0x6F12,0x00F0, + 0x6F12,0x62F8, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0xE701, + 0x6F12,0xE060, + 0x6F12,0x1648, + 0x6F12,0x00F0, + 0x6F12,0x5BF8, + 0x6F12,0x0022, + 0x6F12,0xAFF2, + 0x6F12,0xB301, + 0x6F12,0x6061, + 0x6F12,0x1348, + 0x6F12,0x00F0, + 0x6F12,0x54F8, + 0x6F12,0xA061, + 0x6F12,0x0020, + 0x6F12,0x2080, + 0x6F12,0x10BD, + 0x6F12,0x0000, + 0x6F12,0x2000, + 0x6F12,0x3140, + 0x6F12,0x2000, + 0x6F12,0x1B10, + 0x6F12,0x2000, + 0x6F12,0x2530, + 0x6F12,0x4000, + 0x6F12,0x9802, + 0x6F12,0x2000, + 0x6F12,0x0550, + 0x6F12,0x4000, + 0x6F12,0xF000, + 0x6F12,0x2000, + 0x6F12,0x1300, + 0x6F12,0x2000, + 0x6F12,0x2890, + 0x6F12,0x2000, + 0x6F12,0x02C0, + 0x6F12,0x2000, + 0x6F12,0x1410, + 0x6F12,0x4000, + 0x6F12,0xA358, + 0x6F12,0x0000, + 0x6F12,0x15F7, + 0x6F12,0x0000, + 0x6F12,0x7A4F, + 0x6F12,0x0000, + 0x6F12,0x4A69, + 0x6F12,0x0000, + 0x6F12,0x1349, + 0x6F12,0x0000, + 0x6F12,0x3091, + 0x6F12,0x0000, + 0x6F12,0x6057, + 0x6F12,0x40F2, + 0x6F12,0xE96C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x41F2, + 0x6F12,0xF75C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x41F2, + 0x6F12,0x493C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x41F2, + 0x6F12,0x9D1C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x44F6, + 0x6F12,0x692C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x43F2, + 0x6F12,0x910C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x40F2, + 0x6F12,0x156C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x42F2, + 0x6F12,0xC71C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x46F2, + 0x6F12,0x570C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x6F12,0x4AF6, + 0x6F12,0x850C, + 0x6F12,0xC0F2, + 0x6F12,0x000C, + 0x6F12,0x6047, + 0x3EA6,0xFFFF, //fe_isp_dadlc_analog_gain_thrshold_for_ladlc_low + 0x3EA8,0xFFFF, //fe_isp_dadlc_analog_gain_thrshold_for_ladlc_high + 0x3A56,0x3BB8, //Sampling enable + 0xF476,0x0040, //DBR + 0xF40C,0x1180, //CLP on, LDB off + 0xF480,0x0015, //CLP LVL + 0x39EE,0x0507, + 0x3A06,0x0605, + 0x39D0,0x0707, + 0xF432,0x0100, //DBS + 0xF4A6,0x00C0, //RDV + 0xF42E,0x0060, //CDS + 0xF49C,0x0000, //RMP + 0xF496,0x0000, //REF + 0xF49E,0x005E, //ADC_SAT + 0xF47A,0x0017, //VRD 3.2V + 0xF462,0x0000, //VPIX 2.92V + 0xF460,0x0020, //VTG 3.8V + 0x3A64,0x0010, + 0x3A66,0x0010, + 0x3A68,0x0010, + 0xF426,0x0007, //LAT START + 0xF428,0x0004, //LAT WIDTH + 0xF42A,0x0004, //HOLD START + 0xF42C,0x0004, //HOLD WIDTH + 0x32BC,0x000D, //pixel boost + 0x3298,0x005E, + 0x3880,0x010B, + 0x3886,0x010A, + 0x388C,0x021A, + 0x389E,0x021C, + 0x38A4,0x0000, + 0x38AA,0x015C, + 0x38B0,0x015B, + 0x38B6,0x021A, + 0x38C2,0x0070, + 0x38C8,0x021C, + 0x38CE,0x0000, + 0x3976,0x0006, + 0x31C0,0x0C40, //default 0004 + 0x31C2,0x0C48, //default 0B1C + 0x31B2,0x080C, + 0x31B4,0x0401, + 0x31B2,0x0804, + 0x39D6,0x0F0F, + 0x39DC,0x3030, + 0x39B0,0x0000, + 0x30C2,0x0300, + 0x3AF2,0x0000, + 0x3AF4,0x0000, + 0x3AF6,0x0000, + 0x3AF8,0x0000, + 0x3AFA,0x0000, + 0x3AFC,0x0000, + 0x3AFE,0x0000, + 0x3B00,0x0000, + 0x3B02,0x0000, + 0x3B04,0x0000, + 0x3B06,0x0000, + 0x3B08,0x0000, + 0x3B0A,0x0000, + 0x3B0C,0x0000, + 0x3B0E,0x0000, + 0x3B10,0x0000, + 0x3B12,0x0000, + 0x3B14,0x0000, + 0x3B16,0x0000, + 0x3B18,0x0000, + 0x3B1A,0x0000, + 0x3B1C,0x0000, + 0x3B1E,0x0000, + 0x3B20,0x0000, + 0x3B22,0x0000, + 0x3B24,0x0000, + 0x3B26,0x0000, + 0x3B28,0x0000, + 0x3B2A,0x0000, + 0x3B2C,0x0000, + 0x3B2E,0x0000, + 0x3B30,0x0000, + 0x3B32,0x0000, + 0x3B34,0x0000, + 0x3B36,0x0000, + 0x3B38,0x0000, + 0x3B3A,0x0000, + 0x3B3C,0x0000, + 0x3B3E,0x0000, + 0x3B40,0x0000, + 0x3B42,0x0000, + 0x3B44,0x0000, + 0x3B46,0x0000, + 0x3B48,0x0000, + 0x3B4A,0x0000, + 0x3B4C,0x0000, + 0x3B4E,0x0000, + 0x3B50,0x0000, + 0x3B52,0x0000, + 0x3B54,0x0000, + 0x3B56,0x0000, + 0x3B58,0x0000, + 0x3B5A,0x0000, + 0x3B5C,0x0000, + 0x3B5E,0x0000, + 0x3B60,0x0000, + 0x3B62,0x0000, + 0x3B64,0x0000, + 0x3B66,0x0000, + 0x3B68,0x0000, + 0x3B6A,0x0000, + 0x3B6C,0x0000, + 0x3B6E,0x0000, + 0x3B70,0x0000, + 0x3B72,0x0000, + 0x3B74,0x0000, + 0x3B76,0x0000, + 0x3B78,0x0000, + 0x3B7A,0x0000, + 0x3B7C,0x0000, + 0x3B7E,0x0000, + 0x3B80,0x0000, + 0x3B82,0x0000, + 0x3B84,0x0000, + 0x3B86,0x0000, + 0x3B88,0x0000, + 0x3B8A,0x0000, + 0x3B8C,0x0000, + 0x3B8E,0x0000, + 0x3B90,0x0000, + 0x3B92,0x0000, + 0x3B94,0x0000, + 0x3B96,0x0000, + 0x3B98,0x0000, + 0x3B9A,0x0000, + 0x3B9C,0x0000, + 0x3B9E,0x0000, + 0x3BA0,0x0000, + 0x3BA2,0x0000, + 0x3BA4,0x0000, + 0x3BA6,0x0000, + 0x3BA8,0x0000, + 0x3BAA,0x0000, + 0x3BAC,0x0000, + 0x3BAE,0x0000, + 0x3BB0,0x0000, + 0x3BB2,0x0000, + 0x3BB4,0x0000, + 0x3BB6,0x0000, + 0x3BB8,0x0000, + 0x3BBA,0x0000, + 0x3BBC,0x0000, + 0x3BBE,0x0000, + 0x3BC0,0x0000, + 0x3BC2,0x0000, + 0x3BC4,0x0000, + 0x3BC6,0x0000, + 0x3BC8,0x0000, + 0x3BCA,0x0000, + 0x3BCC,0x0000, + 0x3BCE,0x0000, + 0x3BD0,0x0000, + 0x3BD2,0x0000, + 0x3BD4,0x0000, + 0x3BD6,0x0000, + 0x3BD8,0x0000, + 0x3BDA,0x0000, + 0x3BDC,0x0000, + 0x3BDE,0x0000, + 0x3BE0,0x0000, + 0x3BE2,0x0000, + 0x3BE4,0x0000, + 0x3BE6,0x0000, + 0x3BE8,0x0000, + 0x3BEA,0x0000, + 0x3BEC,0x0000, + 0x3BEE,0x0000, + 0x3BF0,0x0000, + 0x3BF2,0x0000, + 0x3BF4,0x0000, + 0x3BF6,0x0000, + 0x3BF8,0x0000, + 0x3BFA,0x0000, + 0x3BFC,0x0000, + 0x3BFE,0x0000, + 0x3C00,0x0000, + 0x3C02,0x0000, + 0x3C04,0x0000, + 0x3C06,0x0000, + 0x3C08,0x0000, + 0x3C0A,0x0000, + 0x3C0C,0x0000, + 0x3C0E,0x0000, + 0x3C10,0x0000, + 0x3C12,0x0000, + 0x3C14,0x0000, + 0x3C16,0x0000, + 0x3C18,0x0000, + 0x3C1A,0x0000, + 0x3C1C,0x0000, + 0x3C1E,0x0000, + 0x3C20,0x0000, + 0x3C22,0x0000, + 0x3C24,0x0000, + 0x3C26,0x0000, + 0x3C28,0x0000, + 0x3C2A,0x0000, + 0x3C2C,0x0000, + 0x3C2E,0x0000, + 0x3C30,0x0000, + 0x3C32,0x0000, + 0x3C34,0x0000, + 0x3C36,0x0000, + 0x3C38,0x0000, + 0x3C3A,0x0000, + 0x3C3C,0x0000, + 0x3C3E,0x0000, + 0x3C40,0x0000, + 0x3C42,0x0000, + 0x3C44,0x0000, + 0x3C46,0x0000, + 0x3C48,0x0000, + 0x3C4A,0x0000, + 0x3C4C,0x0000, + 0x3C4E,0x0000, + 0x3C50,0x0000, + 0x3C52,0x0000, + 0x3C54,0x0000, + 0x3C56,0x0000, + 0x3C58,0x0000, + 0x3C5A,0x0000, + 0x3C5C,0x0000, + 0x3C5E,0x0000, + 0x3C60,0x0000, + 0x3C62,0x0000, + 0x3C64,0x0000, + 0x3C66,0x0000, + 0x3C68,0x0000, + 0x3C6A,0x0000, + 0x3C6C,0x0000, + 0x3C6E,0x0000, + 0x3C70,0x0000, + 0x3C72,0x0000, + 0x3C74,0x0000, + 0x3C76,0x0000, + 0x3C78,0x0000, + 0x3C7A,0x0000, + 0x3C7C,0x0000, + 0x3C7E,0x0000, + 0x3C80,0x0000, + 0x3C82,0x0000, + 0x3C84,0x0000, + 0x3C86,0x0000, + 0x3C88,0x0000, + 0x3C8A,0x0000, + 0x3C8C,0x0000, + 0x3C8E,0x0000, + 0x3C90,0x0000, + 0x3C92,0x0000, + 0x3C94,0x0000, + 0x3C96,0x0000, + 0x3C98,0x0000, + 0x3C9A,0x0000, + 0x3C9C,0x0000, + 0x3C9E,0x0000, + 0x3CA0,0x0000, + 0x3CA2,0x0000, + 0x3CA4,0x0000, + 0x3CA6,0x0000, + 0x3CA8,0x0000, + 0x3CAA,0x0000, + 0x3CAC,0x0000, + 0x3CAE,0x0000, + 0x3CB0,0x0000, + 0x3CB2,0x0000, + 0x3CB4,0x0000, + 0x3CB6,0x0000, + 0x3CB8,0x0000, + 0x3CBA,0x0000, + 0x3CBC,0x0000, + 0x3CBE,0x0000, + 0x3CC0,0x0000, + 0x3CC2,0x0000, + 0x3CC4,0x0000, + 0x3CC6,0x0000, + 0x3CC8,0x0000, + 0x3CCA,0x0000, + 0x3CCC,0x0000, + 0x3CCE,0x0000, + 0x3CD0,0x0000, + 0x3CD2,0x0000, + 0x3CD4,0x0000, + 0x3CD6,0x0000, + 0x3CD8,0x0000, + 0x3CDA,0x0000, + 0x3CDC,0x0000, + 0x3CDE,0x0000, + 0x3CE0,0x0000, + 0x3CE2,0x0000, + 0x3CE4,0x0000, + 0x3CE6,0x0000, + 0x3CE8,0x0000, + 0x3CEA,0x0000, + 0x3CEC,0x0000, + 0x3CEE,0x0000, + 0x3CF0,0x0000, + 0x3CF2,0x0000, + 0x3DD4,0x2000, + 0x3DD6,0x2000, + 0x3DDC,0x2000, // + 0x3DDE,0x2000, // + 0x3DF4,0x2000, // + 0x3DF6,0x2000, // + 0x3DFC,0x2000, // + 0x3DFE,0x2000, // + 0x3E14,0x2000, // + 0x3E16,0x2000, // + 0x3E1C,0x2000, // + 0x3E1E,0x2000, // + 0x3E76,0x0A04, + 0x6226,0x0001, //Open clock to access ELG memory + 0x70B6,0x0001, //Disable ELG + 0x3050,0x0002, + 0x3068,0x0000, + 0x6028,0x2000, + 0x602A,0x1410, + 0x6F12,0x0000, + 0x602A,0x1416, + 0x6F12,0x0108, + 0x6F12,0x0108, + 0x6F12,0x0A08, + 0x602A,0x141A, //modify address from 141B to 141A + 0x6F12,0x0A08, + //S6F120203 : delete this register + 0x6F12,0x0202, + 0x6F12,0x0603, + //S6F120603 : delete this register + + 0x602A,0x1412, + 0x6F12,0x0100, + 0x3E9E,0x0011, + 0x3EA2,0x0033, + //BPC + 0x6028,0x2000, + 0x602A,0x1748, + 0x6F12,0x0101, + 0x0B04,0x0101, + 0x306E,0x039C, //smiaRegs_vendor_bpc_otp_clusters_address + 0x3072,0x00FF, //smiaRegs_vendor_bpc_max_clusters_in_otp + 0x30C4,0x0001, //smiaRegs_vendor_tnp_use_dgains_for_ladlc_enable + 0x30C6,0x0001, //smiaRegs_vendor_tnp_reset_iir_on_ladlc_on_off + 0x3E86,0x0104, + 0x302E,0x0102, + //Immediate abort + 0x3028,0x0000, //smiaRegs_vendor_sensor_abort_timing_method_on_rolling_sh + 0x302A,0x0000, //smiaRegs_vendor_sensor_abort_timing_on_sw_stby + 0x3A70,0x0000, + 0x3A72,0x0000, + 0x3A74,0x0000, + 0x3A76,0x0000, + 0x3A78,0x0000, + 0x3A7A,0x0000, + 0x3A7C,0x0000, + 0x3A7E,0x0000, + 0x3A80,0x0000, + 0x3A82,0x0000, + 0x3A84,0x0000, + 0x3A86,0x0000, + 0x3A88,0x0000, + 0x3A8A,0x0000, + 0x3A8C,0x0000, + 0x3A8E,0x0000, + 0x3AB2,0x0000, + 0x3AB4,0x0000, + 0x3AB6,0x0000, + 0x3AB8,0x0000, + 0x3ABA,0x0000, + 0x3ABC,0x0000, + 0x3ABE,0x0000, + 0x3AC0,0x0000, + 0x3AC2,0x0000, + 0x3AC4,0x0000, + 0x3AC6,0x0000, + 0x3AC8,0x0000, + 0x3ACA,0x0000, + 0x3ACC,0x0000, + 0x3ACE,0x0000, + 0xB0CA,0xC000, +}; + +kal_uint16 addr_data_pair_capture_pip_15[] = +{ +#ifdef FIX_VIEW_ANGLE + 0x0344,0x0014, /* smiaRegs_rw_frame_timing_x_addr_start */ + 0x0346,0x0014, /*smiaRegs_rw_frame_timing_y_addr_start */ + 0x0348,0x14D3, /*smiaRegs_rw_frame_timing_x_addr_end*/ + 0x034A,0x0BB3, /*smiaRegs_rw_frame_timing_y_addr_end*/ + 0x034C,0x14C0, //smiaRegs_rw_frame_timing_x_output_size + 0x034E,0x0BA0, /*smiaRegs_rw_frame_timing_y_output_size*/ +#else + 0x0344,0x0010, /* smiaRegs_rw_frame_timing_x_addr_start */ + 0x0346,0x0008, /*smiaRegs_rw_frame_timing_y_addr_start */ + 0x0348,0x14DF, /*smiaRegs_rw_frame_timing_x_addr_end*/ + 0x034A,0x0BBF, /*smiaRegs_rw_frame_timing_y_addr_end*/ + 0x034C,0x14D0, //smiaRegs_rw_frame_timing_x_output_size + 0x034E,0x0BB8, /*smiaRegs_rw_frame_timing_y_output_size*/ +#endif + 0x0382,0x0001, /*smiaRegs_rw_sub_sample_x_odd_inc*/ + 0x0380,0x0001, /*smiaRegs_rw_sub_sample_x_even_inc*/ + 0x0386,0x0001, /*smiaRegs_rw_sub_sample_y_odd_inc*/ + 0x0384,0x0001, /*smiaRegs_rw_sub_sample_y_even_inc*/ + 0x0900,0x0011, /*smiaRegs_rw_binning_mode*/ +// write_cmos_sensor_8(0x0901,0x11, /*smiaRegs_rw_binning_type*/ + 0x0400,0x0000, /*smiaRegs_rw_scaling_scaling_mode*/ + 0x0404,0x0010, /*smiaRegs_rw_scaling_scale_m*/ + 0x0114,0x0300, + 0x0110,0x0002, /*smiaRegs_rw_output_signalling_mode*/ + 0x0136,0x1800, + 0x0304,0x0006, + 0x0306,0x00AF, //smiaRegs_rw_clocks_pll_multiplier // 175 + 0x0302,0x0001, //smiaRegs_rw_clocks_vt_pix_clk_div + 0x0300,0x0005, //smiaRegs_rw_clocks_vt_sys_clk_div + 0x030C,0x0004, //smiaRegs_rw_clocks_secnd_pre_pll_clk_div + 0x030E,0x003A, //smiaRegs_rw_clocks_secnd_pll_multiplier // 50 + 0x030A,0x0001, //smiaRegs_rw_clocks_op_sys_clk_div + 0x0308,0x0008, //smiaRegs_rw_clocks_op_pix_clk_div + 0x1118,0x4100, + 0x1124,0x4100, + 0x112C,0x4100, + 0x1164,0x4100, + 0x1170,0x4100, + 0x301C,0x4100, + 0x0342,0x2FC0, //smiaRegs_rw_frame_timing_line_length_pck // 3216 + 0x0340,0x0C66, //smiaRegs_rw_frame_timing_frame_length_lines // 580 + 0x0200,0x0100, //smiaRegs_rw_integration_time_fine_integration_time + 0x0202,0x0100, //smiaRegs_rw_integration_time_coarse_integration_time + 0x0216,0x0000, //smiaRegs_rw_wdr_multiple_exp_mode + 0x3054,0x0100, //smiaRegs_vendor_sensor_enable_af_pixels + 0x3A6A,0x8000, + 0x3A6A,0x0D00, + 0x39BA,0x0002, + 0x3004,0x0005, + 0x3A58,0x0061, + 0x39E2,0x0102, + 0x3238,0x0529, // SenAnalog_AIG_pDefaultNormalPtrs_3__1_ + 0x324A,0x00DE, // SenAnalog_AIG_pDefaultNormalPtrs_6__1_ + 0x3250,0x011F, //SenAnalog_AIG_pDefaultNormalPtrs_7__1_ + 0x3274,0x013E, //SenAnalog_AIG_pDefaultNormalPtrs_13__1_ + 0x32C2,0x011F, //SenAnalog_AIG_pDefaultNormalPtrs_26__1_ + 0x32C8,0x0140, // SenAnalog_AIG_pDefaultNormalPtrs_27__1_ + 0x32DA,0x011F, // SenAnalog_AIG_pDefaultNormalPtrs_30__1_ + 0x32E0,0x0120, // SenAnalog_AIG_pDefaultNormalPtrs_31__1_ + 0x35FE,0x0078, // SenAnalog_AIG_pDefaultNormalPtrs_164__1_ + 0x37C6,0x0083, // SenAnalog_AIG_pDefaultVdaAndShPtrs_30__1_ + 0x37CC,0x005D, //SenAnalog_AIG_pDefaultVdaAndShPtrs_31__1_ + 0x37D2,0x0057, // SenAnalog_AIG_pDefaultVdaAndShPtrs_32__1_ + 0x37DE,0x0081, // SenAnalog_AIG_pDefaultVdaAndShPtrs_34__1_ + 0x37E4,0x005F, // SenAnalog_AIG_pDefaultVdaAndShPtrs_35__1_ + 0x37EA,0x0055, // SenAnalog_AIG_pDefaultVdaAndShPtrs_36__1_ + 0x37F6,0x0081, // SenAnalog_AIG_pDefaultVdaAndShPtrs_38__1_ + 0x37FC,0x005F, // SenAnalog_AIG_pDefaultVdaAndShPtrs_39__1_ + 0x3802,0x0055, //SenAnalog_AIG_pDefaultVdaAndShPtrs_40__1_ + 0x6028,0x2000, + 0x602A,0x15b8, + 0x6F12,0x8011, + 0x3140,0x0FE2, + 0x31B4,0x0400, + 0x6028,0x2000, + 0x602A,0x1759, + 0x6F12,0x0001, + 0x6F12,0x0048, + 0x6F12,0x0050, + 0x6F12,0x0060, + 0x6F12,0x0060, + 0x6F12,0xF42E, + 0x6F12,0x006D, + 0x6F12,0x006A, + 0x6F12,0xF51E, + +}; + +kal_uint16 addr_data_pair_capture_pip[] = +{ +#ifdef FIX_VIEW_ANGLE + 0x0344,0x0018, //smiaRegs_rw_frame_timing_x_addr_start + 0x0346,0x0014, //smiaRegs_rw_frame_timing_y_addr_start + 0x0348,0x14D7, //smiaRegs_rw_frame_timing_x_addr_end + 0x034A,0x0BB3, //smiaRegs_rw_frame_timing_y_addr_end + 0x034C,0x14C0, //smiaRegs_rw_frame_timing_x_output_size + 0x034E,0x0BA0, //smiaRegs_rw_frame_timing_y_output_size +#else + 0x0344,0x0008, /* smiaRegs_rw_frame_timing_x_addr_start */ + 0x0346,0x0008, /*smiaRegs_rw_frame_timing_y_addr_start */ + 0x0348,0x14DF, /*smiaRegs_rw_frame_timing_x_addr_end*/ + 0x034A,0x0BBF, /*smiaRegs_rw_frame_timing_y_addr_end*/ + 0x034C,0x14D0, //smiaRegs_rw_frame_timing_x_output_size + 0x034E,0x0BB8, /*smiaRegs_rw_frame_timing_y_output_size*/ +#endif + 0x0382,0x0001, /*smiaRegs_rw_sub_sample_x_odd_inc*/ + 0x0380,0x0001, /*smiaRegs_rw_sub_sample_x_even_inc*/ + 0x0386,0x0001, /*smiaRegs_rw_sub_sample_y_odd_inc*/ + 0x0384,0x0001, /*smiaRegs_rw_sub_sample_y_even_inc*/ + 0x0900,0x0011, /*smiaRegs_rw_binning_mode*/ +// write_cmos_sensor_8(0x0901,0x11, /*smiaRegs_rw_binning_type*/ + 0x0400,0x0000, /*smiaRegs_rw_scaling_scaling_mode*/ + 0x0404,0x0010, /*smiaRegs_rw_scaling_scale_m*/ + 0x0114,0x0300, + 0x0110,0x0002, /*smiaRegs_rw_output_signalling_mode*/ + 0x0136,0x1800, + 0x0304,0x0006, + 0x0306,0x0074, //smiaRegs_rw_clocks_pll_multiplier // 175 + 0x0300,0x0005, //smiaRegs_rw_clocks_vt_pix_clk_div + 0x0302,0x0001, //smiaRegs_rw_clocks_vt_sys_clk_div + 0x030C,0x0004, //smiaRegs_rw_clocks_secnd_pre_pll_clk_div + 0x030E,0x004B, //smiaRegs_rw_clocks_secnd_pll_multiplier // 50 + 0x030A,0x0001, //smiaRegs_rw_clocks_op_sys_clk_div + 0x0308,0x0008, //smiaRegs_rw_clocks_op_pix_clk_div + 0x1118,0x4100, + 0x1124,0x4100, + 0x112C,0x4100, + 0x1164,0x4100, + 0x1170,0x4100, + 0x301C,0x4100, + 0x0342,0x16f8, //smiaRegs_rw_frame_timing_line_length_pck // 3216 + 0x0340,0x0C66, //smiaRegs_rw_frame_timing_frame_length_lines // 580 + 0x0200,0x0100, //smiaRegs_rw_integration_time_fine_integration_time + 0x0202,0x0100, //smiaRegs_rw_integration_time_coarse_integration_time + 0x0216,0x0000, //smiaRegs_rw_wdr_multiple_exp_mode + 0x3054,0x0100, //smiaRegs_vendor_sensor_enable_af_pixels + 0x3A6A,0x8000, + 0x3A6A,0x0D00, + 0x39BA,0x0002, + 0x3A58,0x0061, + 0x39E2,0x0102, + 0x3238,0x0529, // SenAnalog_AIG_pDefaultNormalPtrs_3__1_ + 0x324A,0x00DE, // SenAnalog_AIG_pDefaultNormalPtrs_6__1_ + 0x3250,0x011F, //SenAnalog_AIG_pDefaultNormalPtrs_7__1_ + 0x3274,0x013E, //SenAnalog_AIG_pDefaultNormalPtrs_13__1_ + 0x32C2,0x011F, //SenAnalog_AIG_pDefaultNormalPtrs_26__1_ + 0x32C8,0x0140, // SenAnalog_AIG_pDefaultNormalPtrs_27__1_ + 0x32DA,0x011F, // SenAnalog_AIG_pDefaultNormalPtrs_30__1_ + 0x32E0,0x0120, // SenAnalog_AIG_pDefaultNormalPtrs_31__1_ + 0x35FE,0x0078, // SenAnalog_AIG_pDefaultNormalPtrs_164__1_ + 0x37C6,0x0083, // SenAnalog_AIG_pDefaultVdaAndShPtrs_30__1_ + 0x37CC,0x005D, //SenAnalog_AIG_pDefaultVdaAndShPtrs_31__1_ + 0x37D2,0x0057, // SenAnalog_AIG_pDefaultVdaAndShPtrs_32__1_ + 0x37DE,0x0081, // SenAnalog_AIG_pDefaultVdaAndShPtrs_34__1_ + 0x37E4,0x005F, // SenAnalog_AIG_pDefaultVdaAndShPtrs_35__1_ + 0x37EA,0x0055, // SenAnalog_AIG_pDefaultVdaAndShPtrs_36__1_ + 0x37F6,0x0081, // SenAnalog_AIG_pDefaultVdaAndShPtrs_38__1_ + 0x37FC,0x005F, // SenAnalog_AIG_pDefaultVdaAndShPtrs_39__1_ + 0x3802,0x0055, //SenAnalog_AIG_pDefaultVdaAndShPtrs_40__1_ + 0x6028,0x2000, + 0x602A,0x15b8, + 0x6F12,0x8011, + 0x3140,0x0FE2, + 0x31B4,0X0400, + 0x6028,0x2000, + 0x602A,0x1759, + 0x6F12,0x0001, + 0x6F12,0x0048, + 0x6F12,0x0050, + 0x6F12,0x0060, + 0x6F12,0x0060, + 0x6F12,0xF42E, + 0x6F12,0x006D, + 0x6F12,0x006A, + 0x6F12,0xF51E, +}; + +kal_uint16 addr_data_pair_capture[] = +{ + +#ifdef FIX_VIEW_ANGLE + 0x0344,0x0018, //smiaRegs_rw_frame_timing_x_addr_start + 0x0346,0x0014, //smiaRegs_rw_frame_timing_y_addr_start + 0x0348,0x14D7, //smiaRegs_rw_frame_timing_x_addr_end + 0x034A,0x0BB3, //smiaRegs_rw_frame_timing_y_addr_end + 0x034C,0x14C0, //smiaRegs_rw_frame_timing_x_output_size + 0x034E,0x0BA0, //smiaRegs_rw_frame_timing_y_output_size +#else + 0x0344,0x0010, //smiaRegs_rw_frame_timing_x_addr_start + 0x0346,0x0008, //smiaRegs_rw_frame_timing_y_addr_start + 0x0348,0x14DF, //smiaRegs_rw_frame_timing_x_addr_end + 0x034A,0x0BBF, //smiaRegs_rw_frame_timing_y_addr_end + 0x034C,0x14D0, //smiaRegs_rw_frame_timing_x_output_size + 0x034E,0x0BB8, //smiaRegs_rw_frame_timing_y_output_size +#endif + 0x0382,0x0001, //smiaRegs_rw_sub_sample_x_odd_inc + 0x0380,0x0001, //smiaRegs_rw_sub_sample_x_even_inc + 0x0386,0x0001, //smiaRegs_rw_sub_sample_y_odd_inc + 0x0384,0x0001, //smiaRegs_rw_sub_sample_y_even_inc + 0x0900,0x0011, //smiaRegs_rw_binning_mode + //write_cmos_sensor_8(0x0901,0x11, //smiaRegs_rw_binning_type + 0x0400,0x0000, //smiaRegs_rw_scaling_scaling_mode + 0x0404,0x0010, //smiaRegs_rw_scaling_scale_m + 0x0114,0x0300, + 0x0110,0x0002, //smiaRegs_rw_output_signalling_mode + 0x0136,0x1800, //smiaRegs_rw_op_cond_extclk_frequency_mhz + 0x0304,0x0006, //smiaRegs_rw_clocks_pre_pll_clk_div + 0x0306,0x00AF, //smiaRegs_rw_clocks_pll_multiplier // 175 + 0x0300,0x0005, //smiaRegs_rw_clocks_vt_pix_clk_div + 0x0302,0x0001, //smiaRegs_rw_clocks_vt_sys_clk_div + 0x030C,0x0004, //smiaRegs_rw_clocks_secnd_pre_pll_clk_div + 0x030E,0x0074, //smiaRegs_rw_clocks_secnd_pll_multiplier // 50 + 0x030A,0x0001, //smiaRegs_rw_clocks_op_sys_clk_div + 0x0308,0x0008, //smiaRegs_rw_clocks_op_pix_clk_div + 0x1118,0x43FA, + 0x1124,0x43FA, + 0x112C,0x42C0, + 0x1164,0x4280, + 0x1170,0x4100, + 0x301C,0x4396, + 0x0342,0x16F8, //smiaRegs_rw_frame_timing_line_length_pck // 3216 + 0x0340,0x0C66, //smiaRegs_rw_frame_timing_frame_length_lines // 580 + 0x0200,0x0100, //smiaRegs_rw_integration_time_fine_integration_time + 0x0202,0x0100, //smiaRegs_rw_integration_time_coarse_integration_time + 0x0216,0x0000, //smiaRegs_rw_wdr_multiple_exp_mode + 0x3054,0x0100, //smiaRegs_vendor_sensor_enable_af_pixels + 0x306A,0x8000, + 0x3A6A,0x0D00, + 0x39BA,0x0002, + 0x3A58,0x0061, + 0x39E2,0x0102, + 0x3238,0x0219, // SenAnalog_AIG_pDefaultNormalPtrs_3__1_ + 0x324A,0x00DE, // SenAnalog_AIG_pDefaultNormalPtrs_6__1_ + 0x3250,0x011F, //SenAnalog_AIG_pDefaultNormalPtrs_7__1_ + 0x3274,0x013E, //SenAnalog_AIG_pDefaultNormalPtrs_13__1_ + 0x32C2,0x011F, //SenAnalog_AIG_pDefaultNormalPtrs_26__1_ + 0x32C8,0x0140, // SenAnalog_AIG_pDefaultNormalPtrs_27__1_ + 0x32DA,0x011F, // SenAnalog_AIG_pDefaultNormalPtrs_30__1_ + 0x32E0,0x0120, // SenAnalog_AIG_pDefaultNormalPtrs_31__1_ + 0x35FE,0x0078, // SenAnalog_AIG_pDefaultNormalPtrs_164__1_ + 0x37C6,0x0083, // SenAnalog_AIG_pDefaultVdaAndShPtrs_30__1_ + 0x37CC,0x005D, //SenAnalog_AIG_pDefaultVdaAndShPtrs_31__1_ + 0x37D2,0x0057, // SenAnalog_AIG_pDefaultVdaAndShPtrs_32__1_ + 0x37DE,0x0081, // SenAnalog_AIG_pDefaultVdaAndShPtrs_34__1_ + 0x37E4,0x005F, // SenAnalog_AIG_pDefaultVdaAndShPtrs_35__1_ + 0x37EA,0x0055, // SenAnalog_AIG_pDefaultVdaAndShPtrs_36__1_ + 0x37F6,0x0081, // SenAnalog_AIG_pDefaultVdaAndShPtrs_38__1_ + 0x37FC,0x005F, // SenAnalog_AIG_pDefaultVdaAndShPtrs_39__1_ + 0x3802,0x0055, //SenAnalog_AIG_pDefaultVdaAndShPtrs_40__1_ + 0x6028,0x2000, + 0x602A,0x15b8, + 0x6F12,0x8011, + 0x3140,0x0FE2, + 0x31B4,0x0400, + 0x6028,0x2000, + 0x602A,0x1759, + 0x6F12,0x0001, + 0x6F12,0x0048, + 0x6F12,0x0050, + 0x6F12,0x0060, + 0x6F12,0x0060, + 0x6F12,0xF42E, + 0x6F12,0x006D, + 0x6F12,0x006A, + 0x6F12,0xF51E, +}; + +kal_uint16 addr_data_pair_preview[] = +{ +#ifdef FIX_VIEW_ANGLE + 0x0344,0x0018, /*smiaRegs_rw_frame_timing_x_addr_start*/ + 0x0346,0x0014, /*smiaRegs_rw_frame_timing_y_addr_start*/ + 0x0348,0x14D7, /*smiaRegs_rw_frame_timing_x_addr_end*/ + 0x034A,0x0BB3, /*smiaRegs_rw_frame_timing_y_addr_end*/ + 0x034C,0x0A60, /*smiaRegs_rw_frame_timing_x_output_size*/ + 0x034E,0x05D0, /*smiaRegs_rw_frame_timing_y_output_size*/ +#else + 0x0344,0x0010, /*smiaRegs_rw_frame_timing_x_addr_start*/ + 0x0346,0x0008, /*smiaRegs_rw_frame_timing_y_addr_start*/ + 0x0348,0x14DF, /*smiaRegs_rw_frame_timing_x_addr_end*/ + 0x034A,0x0BBF, /*smiaRegs_rw_frame_timing_y_addr_end*/ + 0x034C,0x0A68, /*smiaRegs_rw_frame_timing_x_output_size*/ + 0x034E,0x05DC, /*smiaRegs_rw_frame_timing_y_output_size*/ +#endif + 0x0382,0x0003, /*smiaRegs_rw_sub_sample_x_odd_inc*/ + 0x0380,0x0001, /*smiaRegs_rw_sub_sample_x_even_inc*/ + 0x0386,0x0003, /*smiaRegs_rw_sub_sample_y_odd_inc*/ + 0x0384,0x0001, /*smiaRegs_rw_sub_sample_y_even_inc*/ + 0x0900,0x0122, /*smiaRegs_rw_binning_mode*/ + 0x0400,0x0000, /*smiaRegs_rw_scaling_scaling_mode*/ + 0x0404,0x0010, /*smiaRegs_rw_scaling_scale_m*/ + 0x0114,0x0300, + 0x0110,0x0002, /*smiaRegs_rw_output_signalling_mode*/ + 0x0136,0x1800, /*smiaRegs_rw_op_cond_extclk_frequency_mhz*/ + 0x0304,0x0006, /*smiaRegs_rw_clocks_pre_pll_clk_div*/ + 0x0306,0x0074, /*smiaRegs_rw_clocks_pll_multiplier // 175*/ + 0x0300,0x0005, /*smiaRegs_rw_clocks_vt_pix_clk_div*/ + 0x0302,0x0001, /*smiaRegs_rw_clocks_vt_sys_clk_div*/ + 0x030C,0x0004, /*smiaRegs_rw_clocks_secnd_pre_pll_clk_div*/ + 0x030E,0x004A, /*smiaRegs_rw_clocks_secnd_pll_multiplier 50*/ + 0x030A,0x0001, /*smiaRegs_rw_clocks_op_sys_clk_div*/ + 0x0308,0x0008, /*smiaRegs_rw_clocks_op_pix_clk_div*/ + 0x1118,0x4100, + 0x1124,0x4100, + 0x112C,0x4100, + 0x1164,0x4100, + 0x1170,0x4100, + 0x301C,0x4100, + 0x0342,0x16F8, /*smiaRegs_rw_frame_timing_line_length_pck // 3216*/ + 0x0340,0x0804, /*smiaRegs_rw_frame_timing_frame_length_lines // 580*/ + 0x0200,0x0100, /*smiaRegs_rw_integration_time_fine_integration_time*/ + 0x0202,0x0100, /*smiaRegs_rw_integration_time_coarse_integration_time*/ + 0x0216,0x0000, /*smiaRegs_rw_wdr_multiple_exp_mode*/ + 0x3054,0x0000, /*smiaRegs_vendor_sensor_enable_af_pixels*/ + 0x306A,0x8110, + 0x3A6A,0x0D00, + 0x39BA,0x0002, + 0x3A58,0x0060, + 0x39E2,0x0102, + 0x3238,0x0519, /* SenAnalog_AIG_pDefaultNormalPtrs_3__1_ */ + 0x324A,0x00DE, /* SenAnalog_AIG_pDefaultNormalPtrs_6__1_ */ + 0x3250,0x011F, /*SenAnalog_AIG_pDefaultNormalPtrs_7__1_ */ + 0x3274,0x013E, /*SenAnalog_AIG_pDefaultNormalPtrs_13__1_ */ + 0x32C2,0x011F, /*SenAnalog_AIG_pDefaultNormalPtrs_26__1_ */ + 0x32C8,0x0140, /* SenAnalog_AIG_pDefaultNormalPtrs_27__1_ */ + 0x32DA,0x011F, /* SenAnalog_AIG_pDefaultNormalPtrs_30__1_ */ + 0x32E0,0x0120, /* SenAnalog_AIG_pDefaultNormalPtrs_31__1_ */ + 0x35FE,0x0078, /* SenAnalog_AIG_pDefaultNormalPtrs_164__1_ */ + 0x37C6,0x0083, /* SenAnalog_AIG_pDefaultVdaAndShPtrs_30__1_ */ + 0x37CC,0x005D, /*SenAnalog_AIG_pDefaultVdaAndShPtrs_31__1_ */ + 0x37D2,0x0057, /* SenAnalog_AIG_pDefaultVdaAndShPtrs_32__1_ */ + 0x37DE,0x0081, /* SenAnalog_AIG_pDefaultVdaAndShPtrs_34__1_ */ + 0x37E4,0x005F, /* SenAnalog_AIG_pDefaultVdaAndShPtrs_35__1_ */ + 0x37EA,0x0055, /* SenAnalog_AIG_pDefaultVdaAndShPtrs_36__1_ */ + 0x37F6,0x0081, /* SenAnalog_AIG_pDefaultVdaAndShPtrs_38__1_ */ + 0x37FC,0x005F, /* SenAnalog_AIG_pDefaultVdaAndShPtrs_39__1_ */ + 0x3802,0x0055, /*SenAnalog_AIG_pDefaultVdaAndShPtrs_40__1_ */ + 0x6028,0x2000, + 0x602A,0x15b8, + 0x6F12,0x8011, + 0x3140,0x0FE2, + 0x31B4,0x0400, + 0x6028,0x2000, + 0x602A,0x1759, + 0x6F12,0x0001, + 0x6F12,0x0048, + 0x6F12,0x0050, + 0x6F12,0x0060, + 0x6F12,0x0060, + 0x6F12,0xF42E, + 0x6F12,0x006D, + 0x6F12,0x006A, + 0x6F12,0xF51E, +}; +#endif + +static void sensor_init(void) +{ +#if MULTI_WRITE + LOG_INF("multi-write E\n"); +#else + LOG_INF("E\n"); +#endif +#ifdef PDAF_TEST + //int j = 0; + int size=0x600; + //memset(data, (char)0x2, 1024); + //memset(data+1024, (char)0x3, 1024); + //memset(data+2048, (char)0x4, 2048); + //memset(data2, (char)0x0, 4096); + + wrtie_eeprom(0x0100, data, size); + //read_eeprom(0x0000, data2, size); + //LOG_INF("final data2 "); + //for(j=0;j 0); + i++; + retry = 2; + } + if ((*sensor_id != imgsensor_info.sensor_id) || (*sensor_id != 0x2102)) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint16 sensor_id = 0; + LOG_1; + LOG_2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = read_cmos_sensor(0x0000); + if ((sensor_id == imgsensor_info.sensor_id) || (sensor_id == 0x2102)) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, write id:0x%x id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if ((sensor_id == imgsensor_info.sensor_id) || (sensor_id == 0x2102)) + break; + retry = 2; + } + if ((imgsensor_info.sensor_id != sensor_id) && (0x2102 != sensor_id)) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = KAL_FALSE; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + /* LOG_INF("E\n"); */ + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + set_mirror_flip(IMAGE_NORMAL); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + + if (imgsensor.current_fps == imgsensor_info.cap.max_framerate) // 30fps + { + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + else if(imgsensor.current_fps == 240)//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + { + if (imgsensor.current_fps != imgsensor_info.cap1.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap1's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap1.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + else //PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + { + if (imgsensor.current_fps != imgsensor_info.cap2.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap1's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap1.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap2.pclk; + imgsensor.line_length = imgsensor_info.cap2.linelength; + imgsensor.frame_length = imgsensor_info.cap2.framelength; + imgsensor.min_frame_length = imgsensor_info.cap2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + set_mirror_flip(IMAGE_NORMAL); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + set_mirror_flip(IMAGE_NORMAL); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + set_mirror_flip(IMAGE_NORMAL); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* hs_video */ + + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + set_mirror_flip(IMAGE_NORMAL); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* slim_video */ + +/************************************************************************* +* FUNCTION +* Custom1 +* +* DESCRIPTION +* This function start the sensor Custom1. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 Custom1(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM1; + imgsensor.pclk = imgsensor_info.custom1.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom1.linelength; + imgsensor.frame_length = imgsensor_info.custom1.framelength; + imgsensor.min_frame_length = imgsensor_info.custom1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* Custom1 */ + +static kal_uint32 Custom2(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM2; + imgsensor.pclk = imgsensor_info.custom2.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom2.linelength; + imgsensor.frame_length = imgsensor_info.custom2.framelength; + imgsensor.min_frame_length = imgsensor_info.custom2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* Custom2 */ + +static kal_uint32 Custom3(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM3; + imgsensor.pclk = imgsensor_info.custom3.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom3.linelength; + imgsensor.frame_length = imgsensor_info.custom3.framelength; + imgsensor.min_frame_length = imgsensor_info.custom3.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* Custom3 */ + +static kal_uint32 Custom4(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM4; + imgsensor.pclk = imgsensor_info.custom4.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom4.linelength; + imgsensor.frame_length = imgsensor_info.custom4.framelength; + imgsensor.min_frame_length = imgsensor_info.custom4.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* Custom4 */ + + +static kal_uint32 Custom5(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM5; + imgsensor.pclk = imgsensor_info.custom5.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom5.linelength; + imgsensor.frame_length = imgsensor_info.custom5.framelength; + imgsensor.min_frame_length = imgsensor_info.custom5.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + LOG_INF("imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + return ERROR_NONE; +} /* Custom5 */ + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + + sensor_resolution->SensorCustom1Width = imgsensor_info.custom1.grabwindow_width; + sensor_resolution->SensorCustom1Height = imgsensor_info.custom1.grabwindow_height; + + sensor_resolution->SensorCustom2Width = imgsensor_info.custom2.grabwindow_width; + sensor_resolution->SensorCustom2Height = imgsensor_info.custom2.grabwindow_height; + + sensor_resolution->SensorCustom3Width = imgsensor_info.custom3.grabwindow_width; + sensor_resolution->SensorCustom3Height = imgsensor_info.custom3.grabwindow_height; + + sensor_resolution->SensorCustom4Width = imgsensor_info.custom4.grabwindow_width; + sensor_resolution->SensorCustom4Height = imgsensor_info.custom4.grabwindow_height; + + sensor_resolution->SensorCustom5Width = imgsensor_info.custom5.grabwindow_width; + sensor_resolution->SensorCustom5Height = imgsensor_info.custom5.grabwindow_height; + + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + sensor_info->Custom1DelayFrame = imgsensor_info.custom1_delay_frame; + sensor_info->Custom2DelayFrame = imgsensor_info.custom2_delay_frame; + sensor_info->Custom3DelayFrame = imgsensor_info.custom3_delay_frame; + sensor_info->Custom4DelayFrame = imgsensor_info.custom4_delay_frame; + sensor_info->Custom5DelayFrame = imgsensor_info.custom5_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + sensor_info->PDAF_Support = 0; + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM1: + sensor_info->SensorGrabStartX = imgsensor_info.custom1.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom1.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM2: + sensor_info->SensorGrabStartX = imgsensor_info.custom2.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom2.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM3: + sensor_info->SensorGrabStartX = imgsensor_info.custom3.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom3.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM4: + sensor_info->SensorGrabStartX = imgsensor_info.custom4.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom4.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM5: + sensor_info->SensorGrabStartX = imgsensor_info.custom5.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom5.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CUSTOM1: + Custom1(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM2: + Custom2(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM3: + Custom3(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM4: + Custom4(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM5: + Custom5(image_window, sensor_config_data); // Custom1 + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d ", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / imgsensor_info.pre.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / imgsensor_info.normal_video.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == 300){ + frame_length = imgsensor_info.cap.pclk / imgsensor_info.cap.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + else if (imgsensor.current_fps == 150) { //317Mhz, PIP capture: 15fps for less than 13M, 20fps for 16M,15fps for 20M + frame_length = imgsensor_info.cap2.pclk / imgsensor_info.cap2.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap2.framelength) ? (frame_length - imgsensor_info.cap2.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + else if (imgsensor.current_fps == 200){ + frame_length = imgsensor_info.cap1.pclk / imgsensor_info.cap1.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + else{ + frame_length = imgsensor_info.cap2.pclk / imgsensor_info.cap2.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap2.framelength) ? (frame_length - imgsensor_info.cap2.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / imgsensor_info.hs_video.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / imgsensor_info.slim_video.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM1: + frame_length = imgsensor_info.custom1.pclk / imgsensor_info.custom1.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom1.framelength) ? (frame_length - imgsensor_info.custom1.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM2: + frame_length = imgsensor_info.custom2.pclk / imgsensor_info.custom2.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom2.framelength) ? (frame_length - imgsensor_info.custom2.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM3: + frame_length = imgsensor_info.custom3.pclk / imgsensor_info.custom3.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom3.framelength) ? (frame_length - imgsensor_info.custom3.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom3.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM4: + frame_length = imgsensor_info.custom4.pclk / imgsensor_info.custom4.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom4.framelength) ? (frame_length - imgsensor_info.custom4.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom4.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM5: + frame_length = imgsensor_info.custom5.pclk / imgsensor_info.custom5.linelength / framerate * 10 ; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom5.framelength) ? (frame_length - imgsensor_info.custom5.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / imgsensor_info.pre.linelength / framerate * 10; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + //LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM1: + *framerate = imgsensor_info.custom1.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM2: + *framerate = imgsensor_info.custom2.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM3: + *framerate = imgsensor_info.custom3.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM4: + *framerate = imgsensor_info.custom4.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM5: + *framerate = imgsensor_info.custom5.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0600, 0x0002); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0600, 0x0000); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; +// unsigned long long *feature_return_para=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + SET_PD_BLOCK_INFO_T *PDAFinfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + //LOG_INF("feature_id = %d", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + if((sensor_reg_data->RegData>>8)>0) + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + else + write_cmos_sensor_8(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_GET_PDAF_DATA: /* For PDAF EEPROM Read Information*/ + //read_eeprom((kal_uint16 )(*feature_data),(char*)(uintptr_t)(*(feature_data+1)),(kal_uint32)(*(feature_data+2))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + //LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data_16); + LOG_INF("Warning! Not Support IHDR Feature"); + spin_lock(&imgsensor_drv_lock); + //imgsensor.ihdr_en = (BOOL)*feature_data_16; + imgsensor.ihdr_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_GET_PDAF_INFO: + LOG_INF("SENSOR_FEATURE_GET_PDAF_INFO scenarioId:%d\n", (UINT32)*feature_data); + PDAFinfo= (SET_PD_BLOCK_INFO_T *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)PDAFinfo,(void *)&imgsensor_pd_info,sizeof(SET_PD_BLOCK_INFO_T)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + case MSDK_SCENARIO_ID_SLIM_VIDEO: + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + break; + } + break; + case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: + LOG_INF("SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY scenarioId:%d\n", (UINT32)*feature_data); + //PDAF capacity enable or not, 2p8 only full size support PDAF + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 1; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 1; // video & capture use same setting + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + default: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 S5K2P8_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* s5k2p8_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8mipi_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8mipi_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..294db91d727038c9b612b743a050954b09bca9d1 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k2p8_mipi_raw/s5k2p8mipi_Sensor.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * OV5693mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _S5K2P8MIPI_SENSOR_H +#define _S5K2P8MIPI_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, + IMGSENSOR_MODE_CUSTOM1, + IMGSENSOR_MODE_CUSTOM2, + IMGSENSOR_MODE_CUSTOM3, + IMGSENSOR_MODE_CUSTOM4, + IMGSENSOR_MODE_CUSTOM5, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_int32 dummy_pixel; //current dummypixel + kal_int32 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_bool ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint16 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information + imgsensor_mode_struct cap2; //capture for PIP 15ps relative information + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + imgsensor_mode_struct custom1; //custom1 scenario relative information + imgsensor_mode_struct custom2; //custom2 scenario relative information + imgsensor_mode_struct custom3; //custom3 scenario relative information + imgsensor_mode_struct custom4; //custom4 scenario relative information + imgsensor_mode_struct custom5; //custom5 scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + kal_uint8 custom1_delay_frame; //enter custom1 delay frame num + kal_uint8 custom2_delay_frame; //enter custom1 delay frame num + kal_uint8 custom3_delay_frame; //enter custom1 delay frame num + kal_uint8 custom4_delay_frame; //enter custom1 delay frame num + kal_uint8 custom5_delay_frame; //enter custom1 delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat; + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff + kal_uint32 i2c_speed; //i2c speed +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +extern int iBurstWriteReg_multi(u8 *pData, u32 bytes, u16 i2cId, u16 transfer_length); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..2527061cf341e2d97acb035f6b366b785f4c0147 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/Makefile @@ -0,0 +1,5 @@ +#include $(srctree)/drivers/misc/mediatek/Makefile.custom + +obj-y += s5k3l8mipiraw_Sensor.o +obj-y += s5k3l8mipiraw_pdaf.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_Sensor.c new file mode 100755 index 0000000000000000000000000000000000000000..99771fecd9f6d98f1a4baa4d970602673afabe67 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_Sensor.c @@ -0,0 +1,2656 @@ +/***************************************************************************** + * + * Filename: + * --------- + * S5K3L8mipiraw_sensor.c + * + * Project: + * -------- + * ALPS MT6735 + * + * Description: + * ------------ + * Source code of Sensor driver + * + * PengtaoFan + * 1511041520 modify code style from 3l8@mt6755 and move to mt6797 + * 1512291720 update setting from samsung + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "s5k3l8mipiraw_Sensor.h" + +/*===FEATURE SWITH===*/ +#define FPTPDAFSUPPORT //for pdaf switch +// #define FANPENGTAO //for debug log + +//#define NONCONTINUEMODE +/*===FEATURE SWITH===*/ + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "S5K3L8" +#define LOG_INF_NEW(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) +#define LOG_INF LOG_INF_NEW +#define LOG_1 LOG_INF("S5K3L8,MIPI 4LANE\n") +#define SENSORDB LOG_INF +/**************************** Modify end *******************************************/ + +#define S5K3L8_USE_AWB_OTP +static DEFINE_SPINLOCK(imgsensor_drv_lock); + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = S5K3L8_SENSOR_ID, //Sensor ID Value: 0x30C8//record sensor id defined in Kd_imgsensor.h + + .checksum_value = 0xba395b5c, //0x49c09f86, //checksum value for Camera Auto Test + + .pre = { + .pclk = 560000000, //record different mode's pclk + .linelength = 5808, //record different mode's linelength + .framelength = 3206, //record different mode's framelength + .startx= 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2104, //record different mode's width of grabwindow + .grabwindow_height = 1560, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, +#ifdef NONCONTINUEMODE + .cap = { + .pclk = 560000000, //record different mode's pclk + .linelength = 5920,//5808, //record different mode's linelength + .framelength = 3206, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 4208, //record different mode's width of grabwindow + .grabwindow_height = 3120, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, +#else //CONTINUEMODE + .cap = { + .pclk = 560000000, //record different mode's pclk + .linelength = 5808, //record different mode's linelength + .framelength = 3206, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 4208, //record different mode's width of grabwindow + .grabwindow_height = 3120, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, +#endif +#if 0 //fps =24 + .cap1 = { //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 448000000, //record different mode's pclk + .linelength = 5808, //record different mode's linelength + .framelength = 3206, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 4208, //record different mode's width of grabwindow + .grabwindow_height = 3120, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 240, + }, +#endif +#if 1 //fps 15 + .cap1 = { //capture for PIP 15ps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + .pclk = 400000000, //record different mode's pclk + .linelength = 5808, //record different mode's linelength + .framelength = 4589, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 4208, //record different mode's width of grabwindow + .grabwindow_height = 3120, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 150, + }, +#endif + .normal_video = { + .pclk = 560000000, //record different mode's pclk + .linelength = 5808, //record different mode's linelength + .framelength = 3206, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 4208, //record different mode's width of grabwindow + .grabwindow_height = 3120, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .hs_video = { + .pclk = 560000000, //record different mode's pclk + .linelength = 5808, //record different mode's linelength + .framelength = 803, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 640, //record different mode's width of grabwindow + .grabwindow_height = 480, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 1200, + }, + .slim_video = { + .pclk = 560000000, //record different mode's pclk + .linelength = 5808, //record different mode's linelength + .framelength = 803, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1280, //record different mode's width of grabwindow + .grabwindow_height = 720, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 1200, + }, + .custom1 = { + .pclk = 440000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom2 = { + .pclk = 440000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom3 = { + .pclk = 440000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom4 = { + .pclk = 440000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .custom5 = { + .pclk = 440000000, //record different mode's pclk + .linelength = 4592, //record different mode's linelength + .framelength =3188, //3168, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2096, //record different mode's width of grabwindow + .grabwindow_height = 1552, //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85,//unit , ns + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + + .margin = 5, //sensor framelength & shutter margin + .min_shutter = 4, //min shutter + .max_frame_length = 0xFFFF,//REG0x0202 <=REG0x0340-5//max framelength by sensor register's limitation + .ae_shut_delay_frame = 0, //shutter delay frame for AE cycle, 2 frame with ispGain_delay-shut_delay=2-0=2 + .ae_sensor_gain_delay_frame = 0,//sensor gain delay frame for AE cycle,2 frame with ispGain_delay-sensor_gain_delay=2-0=2 + .ae_ispGain_delay_frame = 2,//isp gain delay frame for AE cycle + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num ,don't support Slow motion + + .cap_delay_frame = 3, //enter capture delay frame num + .pre_delay_frame = 3, //enter preview delay frame num + .video_delay_frame = 3, //enter video delay frame num + .hs_video_delay_frame = 3, //enter high speed video delay frame num + .slim_video_delay_frame = 3,//enter slim video delay frame num + .custom1_delay_frame = 2, + .custom2_delay_frame = 2, + .custom3_delay_frame = 2, + .custom4_delay_frame = 2, + .custom5_delay_frame = 2, + + .isp_driving_current = ISP_DRIVING_8MA, //mclk driving current + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI,//sensor_interface_type + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = 1,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gb,//sensor output first pixel color + .mclk = 24,//mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + .mipi_lane_num = SENSOR_MIPI_4_LANE,//mipi lane num + .i2c_addr_table = {0x5a, 0x20, 0xff},//record sensor support all write id addr, only supprt 4must end with 0xff + .i2c_speed = 300, // i2c read/write speed +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_HV_MIRROR, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x200, //current shutter + .gain = 0x200, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = KAL_FALSE, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0,//record current sensor's i2c write id +}; + + +/* Sensor output window information*/ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[10] = +{ + { 4208, 3120, 0, 0, 4208, 3120, 2104, 1560, 0, 0, 2104, 1560, 0, 0, 2104, 1560}, // Preview + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0, 0, 4208, 3120, 0, 0, 4208, 3120}, // capture + { 4208, 3120, 0, 0, 4208, 3120, 4208, 3120, 0, 0, 4208, 3120, 0, 0, 4208, 3120}, // video + { 4208, 3120, 184, 120, 3840, 2880, 640, 480, 0, 0, 640, 480, 0, 0, 640, 480}, //hight speed video + { 4208, 3120, 184, 480, 3840, 2160, 1280, 720, 0, 0, 1280, 720, 0, 0, 1280, 720},// slim video + { 4192, 3104, 0, 0, 4192, 3104, 2096, 1552, 0000, 0000, 2096, 1552, 0, 0, 2096, 1552},// Custom1 (defaultuse preview) + { 4192, 3104, 0, 0, 4192, 3104, 2096, 1552, 0000, 0000, 2096, 1552, 0, 0, 2096, 1552},// Custom2 + { 4192, 3104, 0, 0, 4192, 3104, 2096, 1552, 0000, 0000, 2096, 1552, 0, 0, 2096, 1552},// Custom3 + { 4192, 3104, 0, 0, 4192, 3104, 2096, 1552, 0000, 0000, 2096, 1552, 0, 0, 2096, 1552},// Custom4 + { 4192, 3104, 0, 0, 4192, 3104, 2096, 1552, 0000, 0000, 2096, 1552, 0, 0, 2096, 1552},// Custom5 +}; + +static SET_PD_BLOCK_INFO_T imgsensor_pd_info = +//for 3l8 +{ + + .i4OffsetX = 31, + + .i4OffsetY = 24, + + .i4PitchX = 64, + + .i4PitchY = 64, + + .i4PairNum = 16, + + .i4SubBlkW = 16, + + .i4SubBlkH = 16, + + .i4PosL = {{31,28},{83,28},{47,32},{67,32},{35,40},{79,40},{51,44},{63,44},{51,60},{63,60},{35,64},{79,64},{47,72},{67,72},{31,76},{83,76}}, + + .i4PosR = {{31,24},{83,24},{47,28},{67,28},{35,44},{79,44},{51,48},{63,48},{51,56},{63,56},{35,60},{79,60},{47,76},{67,76},{31,80},{83,80}}, + + //.iMirrorFlip = 0,//IMAGE_HV_MIRROR, + +}; +#define RWB_ID_OFFSET 0x0F73 +#define EEPROM_READ_ID 0xA0 +#define EEPROM_WRITE_ID 0xA1 + +static kal_uint16 is_RWB_sensor(void) +{ + kal_uint16 get_byte=0; + char pusendcmd[2] = {(char)(RWB_ID_OFFSET >> 8) , (char)(RWB_ID_OFFSET & 0xFF) }; + iReadRegI2C(pusendcmd , 2, (u8*)&get_byte,1,EEPROM_READ_ID); + return get_byte; + +} + +static kal_uint16 read_cmos_sensor_byte(kal_uint16 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + + + iReadRegI2C(pu_send_cmd , 2, (u8*)&get_byte,1,imgsensor.i2c_write_id); + return get_byte; +} + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + + + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + return get_byte; +} + +static void write_cmos_sensor_byte(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + + + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static void write_cmos_sensor(kal_uint16 addr, kal_uint16 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para >> 8),(char)(para & 0xFF)}; + + + iWriteRegI2C(pusendcmd , 4, imgsensor.i2c_write_id); +} + + +#ifdef S5K3L8_USE_AWB_OTP + +#define GAIN_DEFAULT 0x0100 +#define EEPROM_WRITE_ID1 0xA0 +#define RGr_ratio_Typical 544 +#define BGr_ratio_Typical 533 +#define GbGr_ratio_Typical 1026 + +struct S5K3L8_MIPI_otp_struct{ + kal_uint16 RGr_ratio; + kal_uint16 BGr_ratio; + kal_uint16 GbGr_ratio; +}S5K3L8_OTP_TYPE; + +static kal_uint16 eeprom_read(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 2, EEPROM_WRITE_ID1); + return ((get_byte<<8)&0xff00)|((get_byte>>8)&0x00ff); +} + +#if 0 +static void eeprom_write_byte(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 3, EEPROM_WRITE_ID); +} +#endif +void S5K3L8_MIPI_read_otp_wb(struct S5K3L8_MIPI_otp_struct *otp) +{ + kal_uint16 RGr_ratio, BGr_ratio, GbGr_ratio; + + RGr_ratio = eeprom_read(0x001D); + BGr_ratio = eeprom_read(0x001F); + GbGr_ratio = eeprom_read(0x0021); + + otp->RGr_ratio = RGr_ratio; + otp->BGr_ratio = BGr_ratio; + otp->GbGr_ratio = GbGr_ratio; +} + +void S5K3L8_MIPI_write_otp_wb(struct S5K3L8_MIPI_otp_struct *otp) +{ + int R_gain, B_gain, Gb_gain, Gr_gain, Base_gain; + kal_uint16 RGr_ratio, BGr_ratio, GbGr_ratio; + + RGr_ratio = otp->RGr_ratio; + BGr_ratio = otp->BGr_ratio; + GbGr_ratio = otp->GbGr_ratio; + + R_gain = (RGr_ratio_Typical*1000) / RGr_ratio; + B_gain = (BGr_ratio_Typical*1000) / BGr_ratio; + Gb_gain = (GbGr_ratio_Typical*1000) / GbGr_ratio; + Gr_gain = 1000; + Base_gain = R_gain; + if(Base_gain>B_gain) Base_gain = B_gain; + if(Base_gain>Gb_gain) Base_gain = Gb_gain; + if(Base_gain>Gr_gain) Base_gain = Gr_gain; + R_gain = 0x100 * R_gain / Base_gain; + B_gain = 0x100 * B_gain / Base_gain; + Gb_gain = 0x100 * Gb_gain / Base_gain; + Gr_gain = 0x100 * Gr_gain / Base_gain; + write_cmos_sensor_byte(0x3058,0x01); + if(Gr_gain>0x100) + { + write_cmos_sensor_byte(0x020E,Gr_gain>>8); + write_cmos_sensor_byte(0x020F,Gr_gain&0xff); + } + if(R_gain>0x100) + { + write_cmos_sensor_byte(0x0210,R_gain>>8); + write_cmos_sensor_byte(0x0211,R_gain&0xff); + } + if(B_gain>0x100) + { + write_cmos_sensor_byte(0x0212,B_gain>>8); + write_cmos_sensor_byte(0x0213,B_gain&0xff); + } + if(Gb_gain>0x100) + { + write_cmos_sensor_byte(0x0214,Gb_gain>>8); + write_cmos_sensor_byte(0x0215,Gb_gain&0xff); + } + + LOG_INF("S5K3L8_OTP:Gr_gain=0x%x\n",Gr_gain); + LOG_INF("S5K3L8_OTP:R_gain=0x%x\n",R_gain); + LOG_INF("S5K3L8_OTP:B_gain=0x%x\n",B_gain); + LOG_INF("S5K3L8_OTP:Gb_gain=0x%x\n",Gb_gain); + LOG_INF("S5K3L8_OTP:End.\n"); +} + +void S5K3L8_MIPI_update_wb_register_from_otp(void) +{ + struct S5K3L8_MIPI_otp_struct current_otp; + S5K3L8_MIPI_read_otp_wb(¤t_otp); + S5K3L8_MIPI_write_otp_wb(¤t_otp); +} +#endif + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + /* you can set dummy by imgsensor.dummy_line and imgsensor.dummy_pixel, or you can set dummy by imgsensor.frame_length and imgsensor.line_length */ + write_cmos_sensor(0x0340, imgsensor.frame_length & 0xFFFF); + write_cmos_sensor(0x0342, imgsensor.line_length & 0xFFFF); +} /* set_dummy */ + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable(%d) \n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + +/* + + static void write_shutter(kal_uint16 shutter) + { + kal_uint16 realtime_fps = 0; + + + +// if shutter bigger than frame_length, should extend frame length first +spin_lock(&imgsensor_drv_lock); +if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) +imgsensor.frame_length = shutter + imgsensor_info.margin; +else +imgsensor.frame_length = imgsensor.min_frame_length; +if (imgsensor.frame_length > imgsensor_info.max_frame_length) +imgsensor.frame_length = imgsensor_info.max_frame_length; +spin_unlock(&imgsensor_drv_lock); +shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; +shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + +if (imgsensor.autoflicker_en) { +realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; +if(realtime_fps >= 297 && realtime_fps <= 305) +set_max_framerate(296,0); +else if(realtime_fps >= 147 && realtime_fps <= 150) +set_max_framerate(146,0); +} else { +// Extend frame length +write_cmos_sensor(0x0340, imgsensor.frame_length & 0xFFFF); +} + +// Update Shutter +write_cmos_sensor(0x0202, (shutter) & 0xFFFF); +LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +//LOG_INF("frame_length = %d ", frame_length); + +} + */ + +/* write_shutter */ + + + +/************************************************************************* + * FUNCTION + * set_shutter + * + * DESCRIPTION + * This function set e-shutter of sensor to change exposure time. + * + * PARAMETERS + * iShutter : exposured lines + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + kal_uint16 realtime_fps = 0; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + //write_shutter(shutter); + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x0340, imgsensor.frame_length & 0xFFFF); + } + } else { + // Extend frame length + write_cmos_sensor(0x0340, imgsensor.frame_length & 0xFFFF); + } + + // Update Shutter + write_cmos_sensor(0X0202, shutter & 0xFFFF); + LOG_INF("Exit! shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0000; + //gain = 64 = 1x real gain. + reg_gain = gain/2; + //reg_gain = reg_gain & 0xFFFF; + return (kal_uint16)reg_gain; +} + +/************************************************************************* + * FUNCTION + * set_gain + * + * DESCRIPTION + * This function is to set global gain to sensor. + * + * PARAMETERS + * iGain : sensor global gain(base: 0x40) + * + * RETURNS + * the actually gain set to sensor. + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + LOG_INF("set_gain %d \n", gain); + //gain = 64 = 1x real gain. + + if (gain < BASEGAIN || gain > 16 * BASEGAIN) { + LOG_INF("Error gain setting"); + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 16 * BASEGAIN) + gain = 16 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + write_cmos_sensor(0x0204, (reg_gain&0xFFFF)); + return gain; +} /* set_gain */ + +//ihdr_write_shutter_gain not support for s5k3l8 +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length first + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + + write_cmos_sensor(0x3502, (le << 4) & 0xFF); + write_cmos_sensor(0x3501, (le >> 4) & 0xFF); + write_cmos_sensor(0x3500, (le >> 12) & 0x0F); + + write_cmos_sensor(0x3512, (se << 4) & 0xFF); + write_cmos_sensor(0x3511, (se >> 4) & 0xFF); + write_cmos_sensor(0x3510, (se >> 12) & 0x0F); + + set_gain(gain); + } + +} + + + +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + spin_lock(&imgsensor_drv_lock); + imgsensor.mirror= image_mirror; + spin_unlock(&imgsensor_drv_lock); + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor_byte(0x0101,0X00); //GR + break; + case IMAGE_H_MIRROR: + write_cmos_sensor_byte(0x0101,0X01); //R + break; + case IMAGE_V_MIRROR: + write_cmos_sensor_byte(0x0101,0X02); //B + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor_byte(0x0101,0X03); //GB + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} + +/************************************************************************* + * FUNCTION + * night_mode + * + * DESCRIPTION + * This function night mode of sensor. + * + * PARAMETERS + * bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static void night_mode(kal_bool enable) +{ + /*No Need to implement this function*/ +} /* night_mode */ +static void sensor_init(void) +{ + LOG_INF("E\n"); + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x6214, 0xFFFF); + write_cmos_sensor(0x6216, 0xFFFF); + write_cmos_sensor(0x6218, 0x0000); + write_cmos_sensor(0x621A, 0x0000); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x2450); + write_cmos_sensor(0x6F12, 0x0448); + write_cmos_sensor(0x6F12, 0x0349); + write_cmos_sensor(0x6F12, 0x0160); + write_cmos_sensor(0x6F12, 0xC26A); + write_cmos_sensor(0x6F12, 0x511A); + write_cmos_sensor(0x6F12, 0x8180); + write_cmos_sensor(0x6F12, 0x00F0); + write_cmos_sensor(0x6F12, 0x48B8); + write_cmos_sensor(0x6F12, 0x2000); + write_cmos_sensor(0x6F12, 0x2588); + write_cmos_sensor(0x6F12, 0x2000); + write_cmos_sensor(0x6F12, 0x16C0); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x10B5); + write_cmos_sensor(0x6F12, 0x00F0); + write_cmos_sensor(0x6F12, 0x5DF8); + write_cmos_sensor(0x6F12, 0x2748); + write_cmos_sensor(0x6F12, 0x4078); + write_cmos_sensor(0x6F12, 0x0028); + write_cmos_sensor(0x6F12, 0x0AD0); + write_cmos_sensor(0x6F12, 0x00F0); + write_cmos_sensor(0x6F12, 0x5CF8); + write_cmos_sensor(0x6F12, 0x2549); + write_cmos_sensor(0x6F12, 0xB1F8); + write_cmos_sensor(0x6F12, 0x1403); + write_cmos_sensor(0x6F12, 0x4200); + write_cmos_sensor(0x6F12, 0x2448); + write_cmos_sensor(0x6F12, 0x4282); + write_cmos_sensor(0x6F12, 0x91F8); + write_cmos_sensor(0x6F12, 0x9610); + write_cmos_sensor(0x6F12, 0x4187); + write_cmos_sensor(0x6F12, 0x10BD); + write_cmos_sensor(0x6F12, 0x70B5); + write_cmos_sensor(0x6F12, 0x0446); + write_cmos_sensor(0x6F12, 0x2148); + write_cmos_sensor(0x6F12, 0x0022); + write_cmos_sensor(0x6F12, 0x4068); + write_cmos_sensor(0x6F12, 0x86B2); + write_cmos_sensor(0x6F12, 0x050C); + write_cmos_sensor(0x6F12, 0x3146); + write_cmos_sensor(0x6F12, 0x2846); + write_cmos_sensor(0x6F12, 0x00F0); + write_cmos_sensor(0x6F12, 0x4CF8); + write_cmos_sensor(0x6F12, 0x2046); + write_cmos_sensor(0x6F12, 0x00F0); + write_cmos_sensor(0x6F12, 0x4EF8); + write_cmos_sensor(0x6F12, 0x14F8); + write_cmos_sensor(0x6F12, 0x680F); + write_cmos_sensor(0x6F12, 0x6178); + write_cmos_sensor(0x6F12, 0x40EA); + write_cmos_sensor(0x6F12, 0x4100); + write_cmos_sensor(0x6F12, 0x1749); + write_cmos_sensor(0x6F12, 0xC886); + write_cmos_sensor(0x6F12, 0x1848); + write_cmos_sensor(0x6F12, 0x2278); + write_cmos_sensor(0x6F12, 0x007C); + write_cmos_sensor(0x6F12, 0x4240); + write_cmos_sensor(0x6F12, 0x1348); + write_cmos_sensor(0x6F12, 0xA230); + write_cmos_sensor(0x6F12, 0x8378); + write_cmos_sensor(0x6F12, 0x43EA); + write_cmos_sensor(0x6F12, 0xC202); + write_cmos_sensor(0x6F12, 0x0378); + write_cmos_sensor(0x6F12, 0x4078); + write_cmos_sensor(0x6F12, 0x9B00); + write_cmos_sensor(0x6F12, 0x43EA); + write_cmos_sensor(0x6F12, 0x4000); + write_cmos_sensor(0x6F12, 0x0243); + write_cmos_sensor(0x6F12, 0xD0B2); + write_cmos_sensor(0x6F12, 0x0882); + write_cmos_sensor(0x6F12, 0x3146); + write_cmos_sensor(0x6F12, 0x2846); + write_cmos_sensor(0x6F12, 0xBDE8); + write_cmos_sensor(0x6F12, 0x7040); + write_cmos_sensor(0x6F12, 0x0122); + write_cmos_sensor(0x6F12, 0x00F0); + write_cmos_sensor(0x6F12, 0x2AB8); + write_cmos_sensor(0x6F12, 0x10B5); + write_cmos_sensor(0x6F12, 0x0022); + write_cmos_sensor(0x6F12, 0xAFF2); + write_cmos_sensor(0x6F12, 0x8701); + write_cmos_sensor(0x6F12, 0x0B48); + write_cmos_sensor(0x6F12, 0x00F0); + write_cmos_sensor(0x6F12, 0x2DF8); + write_cmos_sensor(0x6F12, 0x084C); + write_cmos_sensor(0x6F12, 0x0022); + write_cmos_sensor(0x6F12, 0xAFF2); + write_cmos_sensor(0x6F12, 0x6D01); + write_cmos_sensor(0x6F12, 0x2060); + write_cmos_sensor(0x6F12, 0x0848); + write_cmos_sensor(0x6F12, 0x00F0); + write_cmos_sensor(0x6F12, 0x25F8); + write_cmos_sensor(0x6F12, 0x6060); + write_cmos_sensor(0x6F12, 0x10BD); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x2000); + write_cmos_sensor(0x6F12, 0x0550); + write_cmos_sensor(0x6F12, 0x2000); + write_cmos_sensor(0x6F12, 0x0C60); + write_cmos_sensor(0x6F12, 0x4000); + write_cmos_sensor(0x6F12, 0xD000); + write_cmos_sensor(0x6F12, 0x2000); + write_cmos_sensor(0x6F12, 0x2580); + write_cmos_sensor(0x6F12, 0x2000); + write_cmos_sensor(0x6F12, 0x16F0); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x2221); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x2249); + write_cmos_sensor(0x6F12, 0x42F2); + write_cmos_sensor(0x6F12, 0x351C); + write_cmos_sensor(0x6F12, 0xC0F2); + write_cmos_sensor(0x6F12, 0x000C); + write_cmos_sensor(0x6F12, 0x6047); + write_cmos_sensor(0x6F12, 0x42F2); + write_cmos_sensor(0x6F12, 0xE11C); + write_cmos_sensor(0x6F12, 0xC0F2); + write_cmos_sensor(0x6F12, 0x000C); + write_cmos_sensor(0x6F12, 0x6047); + write_cmos_sensor(0x6F12, 0x40F2); + write_cmos_sensor(0x6F12, 0x077C); + write_cmos_sensor(0x6F12, 0xC0F2); + write_cmos_sensor(0x6F12, 0x000C); + write_cmos_sensor(0x6F12, 0x6047); + write_cmos_sensor(0x6F12, 0x42F2); + write_cmos_sensor(0x6F12, 0x492C); + write_cmos_sensor(0x6F12, 0xC0F2); + write_cmos_sensor(0x6F12, 0x000C); + write_cmos_sensor(0x6F12, 0x6047); + write_cmos_sensor(0x6F12, 0x4BF2); + write_cmos_sensor(0x6F12, 0x453C); + write_cmos_sensor(0x6F12, 0xC0F2); + write_cmos_sensor(0x6F12, 0x000C); + write_cmos_sensor(0x6F12, 0x6047); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x30C8); + write_cmos_sensor(0x6F12, 0x0157); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x6F12, 0x0003); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x1082); + write_cmos_sensor(0x6F12, 0x8010); + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x31CE, 0x0001); + write_cmos_sensor(0x0200, 0x00C6); + write_cmos_sensor(0x3734, 0x0010); + write_cmos_sensor(0x3736, 0x0001); + write_cmos_sensor(0x3738, 0x0001); + //write_cmos_sensor(0x37CC, 0x0000); //OLD SETTING + write_cmos_sensor(0x37CC, 0x0001); //NEW SETTING + write_cmos_sensor(0x3744, 0x0100); + write_cmos_sensor(0x3762, 0x0105); + write_cmos_sensor(0x3764, 0x0105); + write_cmos_sensor(0x376A, 0x00F0); + write_cmos_sensor(0x3058, 0x0100);//2016/01/08 + write_cmos_sensor(0x3442, 0x0100); //new setting + write_cmos_sensor(0x344A, 0x000F); + write_cmos_sensor(0x344C, 0x003D); + //write_cmos_sensor(0xF460, 0x0020); //OLD SETTING + write_cmos_sensor(0xF460, 0x0030); //NEW SETTING + write_cmos_sensor(0xF414, 0x24C2); + write_cmos_sensor(0xF416, 0x0183); + //write_cmos_sensor(0xF468, 0x0405); //old setting + write_cmos_sensor(0xF468, 0x4005); //new setting + //write_cmos_sensor(0x3424, 0x0807); //old setting + write_cmos_sensor(0x3424, 0x0A07); //NEW SETTING + write_cmos_sensor(0x3426, 0x0F07); + write_cmos_sensor(0x3428, 0x0F07); + write_cmos_sensor(0x341E, 0x0804); + write_cmos_sensor(0x3420, 0x0C0C); + write_cmos_sensor(0x3422, 0x2D2D); + write_cmos_sensor(0xF462, 0x003A); + write_cmos_sensor(0x3450, 0x0010); + write_cmos_sensor(0x3452, 0x0010); + write_cmos_sensor(0xF446, 0x0020); + write_cmos_sensor(0xF44E, 0x000C); + write_cmos_sensor(0x31FA, 0x0007); + write_cmos_sensor(0x31FC, 0x0161); + write_cmos_sensor(0x31FE, 0x0009); + write_cmos_sensor(0x3200, 0x000C); + write_cmos_sensor(0x3202, 0x007F); + write_cmos_sensor(0x3204, 0x00A2); + write_cmos_sensor(0x3206, 0x007D); + write_cmos_sensor(0x3208, 0x00A4); + write_cmos_sensor(0x3334, 0x00A7); + write_cmos_sensor(0x3336, 0x00A5); + write_cmos_sensor(0x3338, 0x0033); + write_cmos_sensor(0x333A, 0x0006); + write_cmos_sensor(0x333C, 0x009F); + write_cmos_sensor(0x333E, 0x008C); + write_cmos_sensor(0x3340, 0x002D); + write_cmos_sensor(0x3342, 0x000A); + write_cmos_sensor(0x3344, 0x002F); + write_cmos_sensor(0x3346, 0x0008); + write_cmos_sensor(0x3348, 0x009F); + write_cmos_sensor(0x334A, 0x008C); + write_cmos_sensor(0x334C, 0x002D); + write_cmos_sensor(0x334E, 0x000A); + write_cmos_sensor(0x3350, 0x000A); + write_cmos_sensor(0x320A, 0x007B); + write_cmos_sensor(0x320C, 0x0161); + write_cmos_sensor(0x320E, 0x007F); + write_cmos_sensor(0x3210, 0x015F); + write_cmos_sensor(0x3212, 0x007B); + write_cmos_sensor(0x3214, 0x00B0); + write_cmos_sensor(0x3216, 0x0009); + write_cmos_sensor(0x3218, 0x0038); + write_cmos_sensor(0x321A, 0x0009); + write_cmos_sensor(0x321C, 0x0031); + write_cmos_sensor(0x321E, 0x0009); + write_cmos_sensor(0x3220, 0x0038); + write_cmos_sensor(0x3222, 0x0009); + write_cmos_sensor(0x3224, 0x007B); + write_cmos_sensor(0x3226, 0x0001); + write_cmos_sensor(0x3228, 0x0010); + write_cmos_sensor(0x322A, 0x00A2); + write_cmos_sensor(0x322C, 0x00B1); + write_cmos_sensor(0x322E, 0x0002); + write_cmos_sensor(0x3230, 0x015D); + write_cmos_sensor(0x3232, 0x0001); + write_cmos_sensor(0x3234, 0x015D); + write_cmos_sensor(0x3236, 0x0001); + write_cmos_sensor(0x3238, 0x000B); + write_cmos_sensor(0x323A, 0x0016); + write_cmos_sensor(0x323C, 0x000D); + write_cmos_sensor(0x323E, 0x001C); + write_cmos_sensor(0x3240, 0x000D); + write_cmos_sensor(0x3242, 0x0054); + write_cmos_sensor(0x3244, 0x007B); + write_cmos_sensor(0x3246, 0x00CC); + write_cmos_sensor(0x3248, 0x015D); + write_cmos_sensor(0x324A, 0x007E); + write_cmos_sensor(0x324C, 0x0095); + write_cmos_sensor(0x324E, 0x0085); + write_cmos_sensor(0x3250, 0x009D); + write_cmos_sensor(0x3252, 0x008D); + write_cmos_sensor(0x3254, 0x009D); + write_cmos_sensor(0x3256, 0x007E); + write_cmos_sensor(0x3258, 0x0080); + write_cmos_sensor(0x325A, 0x0001); + write_cmos_sensor(0x325C, 0x0005); + write_cmos_sensor(0x325E, 0x0085); + write_cmos_sensor(0x3260, 0x009D); + write_cmos_sensor(0x3262, 0x0001); + write_cmos_sensor(0x3264, 0x0005); + write_cmos_sensor(0x3266, 0x007E); + write_cmos_sensor(0x3268, 0x0080); + write_cmos_sensor(0x326A, 0x0053); + write_cmos_sensor(0x326C, 0x007D); + write_cmos_sensor(0x326E, 0x00CB); + write_cmos_sensor(0x3270, 0x015E); + write_cmos_sensor(0x3272, 0x0001); + write_cmos_sensor(0x3274, 0x0005); + write_cmos_sensor(0x3276, 0x0009); + write_cmos_sensor(0x3278, 0x000C); + write_cmos_sensor(0x327A, 0x007E); + write_cmos_sensor(0x327C, 0x0098); + write_cmos_sensor(0x327E, 0x0009); + write_cmos_sensor(0x3280, 0x000C); + write_cmos_sensor(0x3282, 0x007E); + write_cmos_sensor(0x3284, 0x0080); + write_cmos_sensor(0x3286, 0x0044); + write_cmos_sensor(0x3288, 0x0163); + write_cmos_sensor(0x328A, 0x0045); + write_cmos_sensor(0x328C, 0x0047); + write_cmos_sensor(0x328E, 0x007D); + write_cmos_sensor(0x3290, 0x0080); + write_cmos_sensor(0x3292, 0x015F); + write_cmos_sensor(0x3294, 0x0162); + write_cmos_sensor(0x3296, 0x007D); + write_cmos_sensor(0x3298, 0x0000); + write_cmos_sensor(0x329A, 0x0000); + write_cmos_sensor(0x329C, 0x0000); + write_cmos_sensor(0x329E, 0x0000); + write_cmos_sensor(0x32A0, 0x0008); + write_cmos_sensor(0x32A2, 0x0010); + write_cmos_sensor(0x32A4, 0x0018); + write_cmos_sensor(0x32A6, 0x0020); + write_cmos_sensor(0x32A8, 0x0000); + write_cmos_sensor(0x32AA, 0x0008); + write_cmos_sensor(0x32AC, 0x0010); + write_cmos_sensor(0x32AE, 0x0018); + write_cmos_sensor(0x32B0, 0x0020); + write_cmos_sensor(0x32B2, 0x0020); + write_cmos_sensor(0x32B4, 0x0020); + write_cmos_sensor(0x32B6, 0x0020); + write_cmos_sensor(0x32B8, 0x0000); + write_cmos_sensor(0x32BA, 0x0000); + write_cmos_sensor(0x32BC, 0x0000); + write_cmos_sensor(0x32BE, 0x0000); + write_cmos_sensor(0x32C0, 0x0000); + write_cmos_sensor(0x32C2, 0x0000); + write_cmos_sensor(0x32C4, 0x0000); + write_cmos_sensor(0x32C6, 0x0000); + write_cmos_sensor(0x32C8, 0x0000); + write_cmos_sensor(0x32CA, 0x0000); + write_cmos_sensor(0x32CC, 0x0000); + write_cmos_sensor(0x32CE, 0x0000); + write_cmos_sensor(0x32D0, 0x0000); + write_cmos_sensor(0x32D2, 0x0000); + write_cmos_sensor(0x32D4, 0x0000); + write_cmos_sensor(0x32D6, 0x0000); + write_cmos_sensor(0x32D8, 0x0000); + write_cmos_sensor(0x32DA, 0x0000); + write_cmos_sensor(0x32DC, 0x0000); + write_cmos_sensor(0x32DE, 0x0000); + write_cmos_sensor(0x32E0, 0x0000); + write_cmos_sensor(0x32E2, 0x0000); + write_cmos_sensor(0x32E4, 0x0000); + write_cmos_sensor(0x32E6, 0x0000); + write_cmos_sensor(0x32E8, 0x0000); + write_cmos_sensor(0x32EA, 0x0000); + write_cmos_sensor(0x32EC, 0x0000); + write_cmos_sensor(0x32EE, 0x0000); + write_cmos_sensor(0x32F0, 0x0000); + write_cmos_sensor(0x32F2, 0x0000); + write_cmos_sensor(0x32F4, 0x000A); + write_cmos_sensor(0x32F6, 0x0002); + write_cmos_sensor(0x32F8, 0x0008); + write_cmos_sensor(0x32FA, 0x0010); + write_cmos_sensor(0x32FC, 0x0020); + write_cmos_sensor(0x32FE, 0x0028); + write_cmos_sensor(0x3300, 0x0038); + write_cmos_sensor(0x3302, 0x0040); + write_cmos_sensor(0x3304, 0x0050); + write_cmos_sensor(0x3306, 0x0058); + write_cmos_sensor(0x3308, 0x0068); + write_cmos_sensor(0x330A, 0x0070); + write_cmos_sensor(0x330C, 0x0080); + write_cmos_sensor(0x330E, 0x0088); + write_cmos_sensor(0x3310, 0x0098); + write_cmos_sensor(0x3312, 0x00A0); + write_cmos_sensor(0x3314, 0x00B0); + write_cmos_sensor(0x3316, 0x00B8); + write_cmos_sensor(0x3318, 0x00C8); + write_cmos_sensor(0x331A, 0x00D0); + write_cmos_sensor(0x331C, 0x00E0); + write_cmos_sensor(0x331E, 0x00E8); + write_cmos_sensor(0x3320, 0x0017); + write_cmos_sensor(0x3322, 0x002F); + write_cmos_sensor(0x3324, 0x0047); + write_cmos_sensor(0x3326, 0x005F); + write_cmos_sensor(0x3328, 0x0077); + write_cmos_sensor(0x332A, 0x008F); + write_cmos_sensor(0x332C, 0x00A7); + write_cmos_sensor(0x332E, 0x00BF); + write_cmos_sensor(0x3330, 0x00D7); + write_cmos_sensor(0x3332, 0x00EF); + write_cmos_sensor(0x3352, 0x00A5); + write_cmos_sensor(0x3354, 0x00AF); + write_cmos_sensor(0x3356, 0x0187); + write_cmos_sensor(0x3358, 0x0000); + write_cmos_sensor(0x335A, 0x009E); + write_cmos_sensor(0x335C, 0x016B); + write_cmos_sensor(0x335E, 0x0015); + write_cmos_sensor(0x3360, 0x00A5); + write_cmos_sensor(0x3362, 0x00AF); + write_cmos_sensor(0x3364, 0x01FB); + write_cmos_sensor(0x3366, 0x0000); + write_cmos_sensor(0x3368, 0x009E); + write_cmos_sensor(0x336A, 0x016B); + write_cmos_sensor(0x336C, 0x0015); + write_cmos_sensor(0x336E, 0x00A5); + write_cmos_sensor(0x3370, 0x00A6); + write_cmos_sensor(0x3372, 0x0187); + write_cmos_sensor(0x3374, 0x0000); + write_cmos_sensor(0x3376, 0x009E); + write_cmos_sensor(0x3378, 0x016B); + write_cmos_sensor(0x337A, 0x0015); + write_cmos_sensor(0x337C, 0x00A5); + write_cmos_sensor(0x337E, 0x00A6); + write_cmos_sensor(0x3380, 0x01FB); + write_cmos_sensor(0x3382, 0x0000); + write_cmos_sensor(0x3384, 0x009E); + write_cmos_sensor(0x3386, 0x016B); + write_cmos_sensor(0x3388, 0x0015); + write_cmos_sensor(0x319A, 0x0005); + write_cmos_sensor(0x1006, 0x0005); + write_cmos_sensor(0x3416, 0x0001); + write_cmos_sensor(0x308C, 0x0008); + write_cmos_sensor(0x307C, 0x0240); + write_cmos_sensor(0x375E, 0x0050); + write_cmos_sensor(0x31CE, 0x0101); + write_cmos_sensor(0x374E, 0x0007); + write_cmos_sensor(0x3460, 0x0001); + write_cmos_sensor(0x3052, 0x0002); + write_cmos_sensor(0x3058, 0x0001); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x108A); + write_cmos_sensor(0x6F12, 0x0359); + write_cmos_sensor(0x6F12, 0x0100); + //control continue mode use B0A0 is better +#ifdef NONCONTINUEMODE + write_cmos_sensor_byte(0xB0A0, 0x7C); //non continue mode +#else + write_cmos_sensor_byte(0xB0A0, 0x7D); //continue mode +#endif + write_cmos_sensor(0x0100, 0x0000); + +} /* sensor_init */ + + +static void preview_setting(void) +{ + LOG_INF("E\n"); + //$MV1[MCLK:24,Width:2104,Height:1560,Format:MIPI_Raw10,mipi_lane:4,mipi_datarate:1124,pvi_pclk_inverse:0] + write_cmos_sensor(0x0100, 0x0000); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x0F74); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x0344, 0x0008); + write_cmos_sensor(0x0346, 0x0008); + write_cmos_sensor(0x0348, 0x1077); + write_cmos_sensor(0x034A, 0x0C37); + write_cmos_sensor(0x034C, 0x0838); + write_cmos_sensor(0x034E, 0x0618); + write_cmos_sensor(0x0900, 0x0112); + write_cmos_sensor(0x0380, 0x0001); + write_cmos_sensor(0x0382, 0x0001); + write_cmos_sensor(0x0384, 0x0001); + write_cmos_sensor(0x0386, 0x0003); + write_cmos_sensor(0x0400, 0x0001); + write_cmos_sensor(0x0404, 0x0020); + write_cmos_sensor(0x0114, 0x0300); + write_cmos_sensor(0x0110, 0x0002); + write_cmos_sensor(0x0136, 0x1800); + write_cmos_sensor(0x0304, 0x0006); + write_cmos_sensor(0x0306, 0x00AF); + write_cmos_sensor(0x0302, 0x0001); + write_cmos_sensor(0x0300, 0x0005); + write_cmos_sensor(0x030C, 0x0006); + write_cmos_sensor(0x030E, 0x0119); + write_cmos_sensor(0x030A, 0x0001); + write_cmos_sensor(0x0308, 0x0008); +#ifdef NONCONTINUEMODE + write_cmos_sensor(0x0342, 0x1720); + LOG_INF("===NONCONTINUEMODE==="); +#else + write_cmos_sensor(0x0342, 0x16B0); +#endif + write_cmos_sensor(0x0340, 0x0C86); + write_cmos_sensor(0x0202, 0x0200); + write_cmos_sensor(0x0200, 0x00C6); + write_cmos_sensor(0x0B04, 0x0101); + write_cmos_sensor(0x0B08, 0x0000); + write_cmos_sensor(0x0B00, 0x0007); + write_cmos_sensor(0x316A, 0x00A0); + write_cmos_sensor(0x0100, 0x0100); + +#ifdef S5K3L8_USE_AWB_OTP + S5K3L8_MIPI_update_wb_register_from_otp(); +#endif + +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + if (currefps == 300) { + //$MV1[MCLK:24,Width:4208,Height:3120,Format:MIPI_Raw10,mipi_lane:4,mipi_datarate:1124,pvi_pclk_inverse:0] + write_cmos_sensor(0x0100, 0x0000); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x0F74); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x0344, 0x0008); + write_cmos_sensor(0x0346, 0x0008); + write_cmos_sensor(0x0348, 0x1077); + write_cmos_sensor(0x034A, 0x0C37); + write_cmos_sensor(0x034C, 0x1070); + write_cmos_sensor(0x034E, 0x0C30); + write_cmos_sensor(0x0900, 0x0011); + write_cmos_sensor(0x0380, 0x0001); + write_cmos_sensor(0x0382, 0x0001); + write_cmos_sensor(0x0384, 0x0001); + write_cmos_sensor(0x0386, 0x0001); + write_cmos_sensor(0x0400, 0x0000); + write_cmos_sensor(0x0404, 0x0010); + write_cmos_sensor(0x0114, 0x0300); + write_cmos_sensor(0x0110, 0x0002); + write_cmos_sensor(0x0136, 0x1800); + write_cmos_sensor(0x0304, 0x0006); + write_cmos_sensor(0x0306, 0x00AF); + write_cmos_sensor(0x0302, 0x0001); + write_cmos_sensor(0x0300, 0x0005); + write_cmos_sensor(0x030C, 0x0006); + write_cmos_sensor(0x030E, 0x0119); + write_cmos_sensor(0x030A, 0x0001); + write_cmos_sensor(0x0308, 0x0008); +#ifdef NONCONTINUEMODE + write_cmos_sensor(0x0342, 0x1720); +#else + write_cmos_sensor(0x0342, 0x16B0); +#endif + write_cmos_sensor(0x0340, 0x0C86); + write_cmos_sensor(0x0202, 0x0200); + write_cmos_sensor(0x0200, 0x00C6); + write_cmos_sensor(0x0B04, 0x0101); + write_cmos_sensor(0x0B08, 0x0000); + write_cmos_sensor(0x0B00, 0x0007); + write_cmos_sensor(0x316A, 0x00A0); + write_cmos_sensor(0x0100, 0x0100); + +#ifdef S5K3L8_USE_AWB_OTP + S5K3L8_MIPI_update_wb_register_from_otp(); +#endif + + } + else if (currefps == 240) { + LOG_INF("else if (currefps == 240)\n"); + //$MV1[MCLK:24,Width:4208,Height:3120,Format:MIPI_Raw10,mipi_lane:4,mipi_datarate:1124,pvi_pclk_inverse:0] + write_cmos_sensor(0x0100, 0x0000); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x0F74); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x0344, 0x0008); + write_cmos_sensor(0x0346, 0x0008); + write_cmos_sensor(0x0348, 0x1077); + write_cmos_sensor(0x034A, 0x0C37); + write_cmos_sensor(0x034C, 0x1070); + write_cmos_sensor(0x034E, 0x0C30); + write_cmos_sensor(0x0900, 0x0011); + write_cmos_sensor(0x0380, 0x0001); + write_cmos_sensor(0x0382, 0x0001); + write_cmos_sensor(0x0384, 0x0001); + write_cmos_sensor(0x0386, 0x0001); + write_cmos_sensor(0x0400, 0x0000); + write_cmos_sensor(0x0404, 0x0010); + write_cmos_sensor(0x0114, 0x0300); + write_cmos_sensor(0x0110, 0x0002); + write_cmos_sensor(0x0136, 0x1800); + write_cmos_sensor(0x0304, 0x0006); + write_cmos_sensor(0x0306, 0x008C); + write_cmos_sensor(0x0302, 0x0001); + write_cmos_sensor(0x0300, 0x0005); + write_cmos_sensor(0x030C, 0x0006); + write_cmos_sensor(0x030E, 0x0119); + write_cmos_sensor(0x030A, 0x0001); + write_cmos_sensor(0x0308, 0x0008); +#ifdef NONCONTINUEMODE + write_cmos_sensor(0x0342, 0x1720); +#else + write_cmos_sensor(0x0342, 0x16B0); +#endif + write_cmos_sensor(0x0340, 0x0C86); + write_cmos_sensor(0x0202, 0x0200); + write_cmos_sensor(0x0200, 0x00C6); + write_cmos_sensor(0x0B04, 0x0101); + write_cmos_sensor(0x0B08, 0x0000); + write_cmos_sensor(0x0B00, 0x0007); + write_cmos_sensor(0x316A, 0x00A0); + write_cmos_sensor(0x0100, 0x0100); + +#ifdef S5K3L8_USE_AWB_OTP + S5K3L8_MIPI_update_wb_register_from_otp(); +#endif + + } + else if (currefps == 150) { + //PIP 15fps settings,Ãà±ÈFull 30fps + // -VT : 560-> 400M + // -Frame length: 3206-> 4589 + // -Linelength: 5808²»×ƒ + // + //$MV1[MCLK:24,Width:4208,Height:3120,Format:MIPI_Raw10,mipi_lane:4,mipi_datarate:1124,pvi_pclk_inverse:0] + LOG_INF("else if (currefps == 150)\n"); + write_cmos_sensor(0x0100, 0x0000); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x0F74); + write_cmos_sensor(0x6F12, 0x0040); // 64 + write_cmos_sensor(0x6F12, 0x0040); // 64 + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x0344, 0x0008); // 8 + write_cmos_sensor(0x0346, 0x0008); // 8 + write_cmos_sensor(0x0348, 0x1077); // 4215 + write_cmos_sensor(0x034A, 0x0C37); // 3127 + write_cmos_sensor(0x034C, 0x1070); // 4208 + write_cmos_sensor(0x034E, 0x0C30); // 3120 + write_cmos_sensor(0x0900, 0x0011); + write_cmos_sensor(0x0380, 0x0001); + write_cmos_sensor(0x0382, 0x0001); + write_cmos_sensor(0x0384, 0x0001); + write_cmos_sensor(0x0386, 0x0001); + write_cmos_sensor(0x0400, 0x0000); + write_cmos_sensor(0x0404, 0x0010); + write_cmos_sensor(0x0114, 0x0300); + write_cmos_sensor(0x0110, 0x0002); + write_cmos_sensor(0x0136, 0x1800); // 24MHz + write_cmos_sensor(0x0304, 0x0006); // 6 + write_cmos_sensor(0x0306, 0x007D); // 125 + write_cmos_sensor(0x0302, 0x0001); // 1 + write_cmos_sensor(0x0300, 0x0005); // 5 + write_cmos_sensor(0x030C, 0x0006); // 6 + write_cmos_sensor(0x030E, 0x00c8); // 281 + write_cmos_sensor(0x030A, 0x0001); // 1 + write_cmos_sensor(0x0308, 0x0008); // 8 +#ifdef NONCONTINUEMODE + write_cmos_sensor(0x0342, 0x1720); +#else + write_cmos_sensor(0x0342, 0x16B0); +#endif + write_cmos_sensor(0x0340, 0x11ED); // 4589 + write_cmos_sensor(0x0202, 0x0200); // 512 + write_cmos_sensor(0x0200, 0x00C6); // 198 + write_cmos_sensor(0x0B04, 0x0101); //M.BPC_On + write_cmos_sensor(0x0B08, 0x0000); //D.BPC_Off + write_cmos_sensor(0x0B00, 0x0007); //LSC_Off + write_cmos_sensor(0x316A, 0x00A0); // OUTIF threshold + write_cmos_sensor(0x0100, 0x0100); + +#ifdef S5K3L8_USE_AWB_OTP + S5K3L8_MIPI_update_wb_register_from_otp(); +#endif + } + else { //default fps =15 + //PIP 15fps settings,Ãà±ÈFull 30fps + // -VT : 560-> 400M + // -Frame length: 3206-> 4589 + // -Linelength: 5808²»×ƒ + // + //$MV1[MCLK:24,Width:4208,Height:3120,Format:MIPI_Raw10,mipi_lane:4,mipi_datarate:1124,pvi_pclk_inverse:0] + LOG_INF("else 150fps\n"); + write_cmos_sensor_byte(0x0100, 0x00); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x0F74); + write_cmos_sensor(0x6F12, 0x0040); // 64 + write_cmos_sensor(0x6F12, 0x0040); // 64 + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x0344, 0x0008); // 8 + write_cmos_sensor(0x0346, 0x0008); // 8 + write_cmos_sensor(0x0348, 0x1077); // 4215 + write_cmos_sensor(0x034A, 0x0C37); // 3127 + write_cmos_sensor(0x034C, 0x1070); // 4208 + write_cmos_sensor(0x034E, 0x0C30); // 3120 + write_cmos_sensor(0x0900, 0x0011); + write_cmos_sensor(0x0380, 0x0001); + write_cmos_sensor(0x0382, 0x0001); + write_cmos_sensor(0x0384, 0x0001); + write_cmos_sensor(0x0386, 0x0001); + write_cmos_sensor(0x0400, 0x0000); + write_cmos_sensor(0x0404, 0x0010); + write_cmos_sensor(0x0114, 0x0300); + write_cmos_sensor(0x0110, 0x0002); + write_cmos_sensor(0x0136, 0x1800); // 24MHz + write_cmos_sensor(0x0304, 0x0006); // 6 + write_cmos_sensor(0x0306, 0x007D); // 125 + write_cmos_sensor(0x0302, 0x0001); // 1 + write_cmos_sensor(0x0300, 0x0005); // 5 + write_cmos_sensor(0x030C, 0x0006); // 6 + write_cmos_sensor(0x030E, 0x00c8); // 281 + write_cmos_sensor(0x030A, 0x0001); // 1 + write_cmos_sensor(0x0308, 0x0008); // 8 +#ifdef NONCONTINUEMODE + write_cmos_sensor(0x0342, 0x1720); +#else + write_cmos_sensor(0x0342, 0x16B0); +#endif + write_cmos_sensor(0x0340, 0x11ED); // 4589 + write_cmos_sensor(0x0202, 0x0200); // 512 + write_cmos_sensor(0x0200, 0x00C6); // 198 + write_cmos_sensor(0x0B04, 0x0101); //M.BPC_On + write_cmos_sensor(0x0B08, 0x0000); //D.BPC_Off + write_cmos_sensor(0x0B00, 0x0007); //LSC_Off + write_cmos_sensor(0x316A, 0x00A0); // OUTIF threshold + write_cmos_sensor_byte(0x0100, 0x01); + +#ifdef S5K3L8_USE_AWB_OTP + S5K3L8_MIPI_update_wb_register_from_otp(); +#endif + } +} + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + capture_setting(currefps); +} + +static void hs_video_setting(void) +{ + LOG_INF("E\n"); + //$MV1[MCLK:24,Width:640,Height:480,Format:MIPI_Raw10,mipi_lane:4,mipi_datarate:1124,pvi_pclk_inverse:0] + write_cmos_sensor(0x0100, 0x0000); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x0F74); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x0344, 0x00C0); + write_cmos_sensor(0x0346, 0x0080); + write_cmos_sensor(0x0348, 0x0FBF); + write_cmos_sensor(0x034A, 0x0BBF); + write_cmos_sensor(0x034C, 0x0280); + write_cmos_sensor(0x034E, 0x01E0); + write_cmos_sensor(0x0900, 0x0116); + write_cmos_sensor(0x0380, 0x0001); + write_cmos_sensor(0x0382, 0x0001); + write_cmos_sensor(0x0384, 0x0001); + write_cmos_sensor(0x0386, 0x000B); + write_cmos_sensor(0x0400, 0x0001); + write_cmos_sensor(0x0404, 0x0060); + write_cmos_sensor(0x0114, 0x0300); + write_cmos_sensor(0x0110, 0x0002); + write_cmos_sensor(0x0136, 0x1800); + write_cmos_sensor(0x0304, 0x0006); + write_cmos_sensor(0x0306, 0x00AF); + write_cmos_sensor(0x0302, 0x0001); + write_cmos_sensor(0x0300, 0x0005); + write_cmos_sensor(0x030C, 0x0006); + write_cmos_sensor(0x030E, 0x0119); + write_cmos_sensor(0x030A, 0x0001); + write_cmos_sensor(0x0308, 0x0008); +#ifdef NONCONTINUEMODE + write_cmos_sensor(0x0342, 0x1720); +#else + write_cmos_sensor(0x0342, 0x16B0); +#endif + write_cmos_sensor(0x0340, 0x0323); + write_cmos_sensor(0x0202, 0x0200); + write_cmos_sensor(0x0200, 0x00C6); + write_cmos_sensor(0x0B04, 0x0101); + write_cmos_sensor(0x0B08, 0x0000); + write_cmos_sensor(0x0B00, 0x0007); + write_cmos_sensor(0x316A, 0x00A0); + write_cmos_sensor(0x0100, 0x0100); + +#ifdef S5K3L8_USE_AWB_OTP + S5K3L8_MIPI_update_wb_register_from_otp(); +#endif + +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + //$MV1[MCLK:24,Width:1280,Height:720,Format:MIPI_Raw10,mipi_lane:4,mipi_datarate:1124,pvi_pclk_inverse:0] + write_cmos_sensor(0x0100, 0x0000); + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x0F74); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6F12, 0x0040); + write_cmos_sensor(0x6028, 0x4000); + write_cmos_sensor(0x0344, 0x00C0); + write_cmos_sensor(0x0346, 0x01E8); + write_cmos_sensor(0x0348, 0x0FBF); + write_cmos_sensor(0x034A, 0x0A57); + write_cmos_sensor(0x034C, 0x0500); + write_cmos_sensor(0x034E, 0x02D0); + write_cmos_sensor(0x0900, 0x0113); + write_cmos_sensor(0x0380, 0x0001); + write_cmos_sensor(0x0382, 0x0001); + write_cmos_sensor(0x0384, 0x0001); + write_cmos_sensor(0x0386, 0x0005); + write_cmos_sensor(0x0400, 0x0001); + write_cmos_sensor(0x0404, 0x0030); + write_cmos_sensor(0x0114, 0x0300); + write_cmos_sensor(0x0110, 0x0002); + write_cmos_sensor(0x0136, 0x1800); + write_cmos_sensor(0x0304, 0x0006); + write_cmos_sensor(0x0306, 0x00AF); + write_cmos_sensor(0x0302, 0x0001); + write_cmos_sensor(0x0300, 0x0005); + write_cmos_sensor(0x030C, 0x0006); + write_cmos_sensor(0x030E, 0x0119); + write_cmos_sensor(0x030A, 0x0001); + write_cmos_sensor(0x0308, 0x0008); +#ifdef NONCONTINUEMODE + write_cmos_sensor(0x0342, 0x1720); +#else + write_cmos_sensor(0x0342, 0x16B0); +#endif + write_cmos_sensor(0x0340, 0x0323); + write_cmos_sensor(0x0202, 0x0200); + write_cmos_sensor(0x0200, 0x00C6); + write_cmos_sensor(0x0B04, 0x0101); + write_cmos_sensor(0x0B08, 0x0000); + write_cmos_sensor(0x0B00, 0x0007); + write_cmos_sensor(0x316A, 0x00A0); + write_cmos_sensor(0x0100, 0x0100); + +#ifdef S5K3L8_USE_AWB_OTP + S5K3L8_MIPI_update_wb_register_from_otp(); +#endif + +} + + +static kal_uint32 return_sensor_id(void) +{ + return ((read_cmos_sensor_byte(0x0000) << 8) | read_cmos_sensor_byte(0x0001)); +} + +/************************************************************************* + * FUNCTION + * get_imgsensor_id + * + * DESCRIPTION + * This function get the sensor ID + * + * PARAMETERS + * *sensorID : return the sensor ID + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, ReadOut sensor id: 0x%x, imgsensor_info.sensor_id:0x%x.\n", imgsensor.i2c_write_id,*sensor_id,imgsensor_info.sensor_id); + if(is_RWB_sensor()==0x1){ + imgsensor_info.sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_RWB_Wr; + LOG_INF("RWB sensor of S5k3L8\n"); + } + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, i2c write id: 0x%x, ReadOut sensor id: 0x%x, imgsensor_info.sensor_id:0x%x.\n", imgsensor.i2c_write_id,*sensor_id,imgsensor_info.sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 1; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* + * FUNCTION + * open + * + * DESCRIPTION + * This function initialize the registers of CMOS sensor + * + * PARAMETERS + * None + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = KAL_FALSE; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* + * FUNCTION + * close + * + * DESCRIPTION + * + * + * PARAMETERS + * None + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* + * FUNCTION + * preview + * + * DESCRIPTION + * This function start the sensor preview. + * + * PARAMETERS + * *image_window : address pointer of pixel numbers in one period of HSYNC + * *sensor_config_data : address pointer of line numbers in one period of VSYNC + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + set_mirror_flip(imgsensor.mirror); + mdelay(10); +#ifdef FANPENGTAO + int i=0; + for(i=0; i<10; i++){ + LOG_INF("delay time = %d, the frame no = %d\n", i*10, read_cmos_sensor(0x0005)); + mdelay(10); + } +#endif + return ERROR_NONE; +} /* preview */ + +/************************************************************************* + * FUNCTION + * capture + * + * DESCRIPTION + * This function setup the CMOS sensor in capture MY_OUTPUT mode + * + * PARAMETERS + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap.max_framerate) { + LOG_INF("capture30fps: use cap30FPS's setting: %d fps!\n",imgsensor.current_fps/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + else + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + //PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + LOG_INF("cap115fps: use cap1's setting: %d fps!\n",imgsensor.current_fps/10); + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + else { //PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + LOG_INF("Warning:=== current_fps %d fps is not support, so use cap1's setting\n",imgsensor.current_fps/10); + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + capture_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + mdelay(10); + +#if 0 + if(imgsensor.test_pattern == KAL_TRUE) + { + //write_cmos_sensor(0x5002,0x00); + } +#endif + + return ERROR_NONE; +} /* capture() */ + +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + + + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + set_mirror_flip(imgsensor.mirror); + return ERROR_NONE; +} + +/************************************************************************* + * FUNCTION + * Custom1 + * + * DESCRIPTION + * This function start the sensor Custom1. + * + * PARAMETERS + * *image_window : address pointer of pixel numbers in one period of HSYNC + * *sensor_config_data : address pointer of line numbers in one period of VSYNC + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +static kal_uint32 Custom1(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM1; + imgsensor.pclk = imgsensor_info.custom1.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom1.linelength; + imgsensor.frame_length = imgsensor_info.custom1.framelength; + imgsensor.min_frame_length = imgsensor_info.custom1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom1 */ + +static kal_uint32 Custom2(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM2; + imgsensor.pclk = imgsensor_info.custom2.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom2.linelength; + imgsensor.frame_length = imgsensor_info.custom2.framelength; + imgsensor.min_frame_length = imgsensor_info.custom2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom2 */ + +static kal_uint32 Custom3(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM3; + imgsensor.pclk = imgsensor_info.custom3.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom3.linelength; + imgsensor.frame_length = imgsensor_info.custom3.framelength; + imgsensor.min_frame_length = imgsensor_info.custom3.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom3 */ + +static kal_uint32 Custom4(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM4; + imgsensor.pclk = imgsensor_info.custom4.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom4.linelength; + imgsensor.frame_length = imgsensor_info.custom4.framelength; + imgsensor.min_frame_length = imgsensor_info.custom4.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom4 */ +static kal_uint32 Custom5(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CUSTOM5; + imgsensor.pclk = imgsensor_info.custom5.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.custom5.linelength; + imgsensor.frame_length = imgsensor_info.custom5.framelength; + imgsensor.min_frame_length = imgsensor_info.custom5.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* Custom5 */ +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + sensor_resolution->SensorCustom1Width = imgsensor_info.custom1.grabwindow_width; + sensor_resolution->SensorCustom1Height = imgsensor_info.custom1.grabwindow_height; + + sensor_resolution->SensorCustom2Width = imgsensor_info.custom2.grabwindow_width; + sensor_resolution->SensorCustom2Height = imgsensor_info.custom2.grabwindow_height; + + sensor_resolution->SensorCustom3Width = imgsensor_info.custom3.grabwindow_width; + sensor_resolution->SensorCustom3Height = imgsensor_info.custom3.grabwindow_height; + + sensor_resolution->SensorCustom4Width = imgsensor_info.custom4.grabwindow_width; + sensor_resolution->SensorCustom4Height = imgsensor_info.custom4.grabwindow_height; + + sensor_resolution->SensorCustom5Width = imgsensor_info.custom5.grabwindow_width; + sensor_resolution->SensorCustom5Height = imgsensor_info.custom5.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + sensor_info->Custom1DelayFrame = imgsensor_info.custom1_delay_frame; + sensor_info->Custom2DelayFrame = imgsensor_info.custom2_delay_frame; + sensor_info->Custom3DelayFrame = imgsensor_info.custom3_delay_frame; + sensor_info->Custom4DelayFrame = imgsensor_info.custom4_delay_frame; + sensor_info->Custom5DelayFrame = imgsensor_info.custom5_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; +#ifdef FPTPDAFSUPPORT + sensor_info->PDAF_Support = 1; +#else + sensor_info->PDAF_Support = 0; +#endif + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM1: + sensor_info->SensorGrabStartX = imgsensor_info.custom1.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom1.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM2: + sensor_info->SensorGrabStartX = imgsensor_info.custom2.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom2.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM3: + sensor_info->SensorGrabStartX = imgsensor_info.custom3.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom3.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM4: + sensor_info->SensorGrabStartX = imgsensor_info.custom4.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom4.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CUSTOM5: + sensor_info->SensorGrabStartX = imgsensor_info.custom5.startx; + sensor_info->SensorGrabStartY = imgsensor_info.custom5.starty; + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.custom1.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CUSTOM1: + Custom1(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM2: + Custom2(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM3: + Custom3(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM4: + Custom4(image_window, sensor_config_data); // Custom1 + break; + case MSDK_SCENARIO_ID_CUSTOM5: + Custom5(image_window, sensor_config_data); // Custom1 + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if(framerate==300) + { + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + else + { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + case MSDK_SCENARIO_ID_CUSTOM1: + frame_length = imgsensor_info.custom1.pclk / framerate * 10 / imgsensor_info.custom1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom1.framelength) ? (frame_length - imgsensor_info.custom1.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM2: + frame_length = imgsensor_info.custom2.pclk / framerate * 10 / imgsensor_info.custom2.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom2.framelength) ? (frame_length - imgsensor_info.custom2.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + // set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM3: + frame_length = imgsensor_info.custom3.pclk / framerate * 10 / imgsensor_info.custom3.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom3.framelength) ? (frame_length - imgsensor_info.custom3.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom3.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM4: + frame_length = imgsensor_info.custom4.pclk / framerate * 10 / imgsensor_info.custom4.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom4.framelength) ? (frame_length - imgsensor_info.custom4.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom4.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CUSTOM5: + frame_length = imgsensor_info.custom5.pclk / framerate * 10 / imgsensor_info.custom5.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.custom5.framelength) ? (frame_length - imgsensor_info.custom5.framelength) : 0; + if (imgsensor.dummy_line < 0) + imgsensor.dummy_line = 0; + imgsensor.frame_length = imgsensor_info.custom1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM1: + *framerate = imgsensor_info.custom1.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM2: + *framerate = imgsensor_info.custom2.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM3: + *framerate = imgsensor_info.custom3.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM4: + *framerate = imgsensor_info.custom4.max_framerate; + break; + case MSDK_SCENARIO_ID_CUSTOM5: + *framerate = imgsensor_info.custom5.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x1082); + write_cmos_sensor(0x6F12, 0x0000); + write_cmos_sensor(0x3734, 0x0001); + write_cmos_sensor(0x0600, 0x0308); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x6028, 0x2000); + write_cmos_sensor(0x602A, 0x1082); + write_cmos_sensor(0x6F12, 0x8010); + write_cmos_sensor(0x3734, 0x0010); + write_cmos_sensor(0x0600, 0x0300); + } + + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + SET_PD_BLOCK_INFO_T *PDAFinfo; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_en = (BOOL)*feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + /******************** PDAF START >>> *********/ + case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: + LOG_INF("SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY scenarioId:%llu\n", *feature_data); + //PDAF capacity enable or not, 2p8 only full size support PDAF + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 1; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 1; // video & capture use same setting + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + default: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + } + break; + case SENSOR_FEATURE_GET_PDAF_INFO: + LOG_INF("SENSOR_FEATURE_GET_PDAF_INFO scenarioId:%llu\n", *feature_data); + PDAFinfo= (SET_PD_BLOCK_INFO_T *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)PDAFinfo,(void *)&imgsensor_pd_info,sizeof(SET_PD_BLOCK_INFO_T)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + case MSDK_SCENARIO_ID_SLIM_VIDEO: + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + break; + } + break; + case SENSOR_FEATURE_GET_PDAF_DATA: + LOG_INF("SENSOR_FEATURE_GET_PDAF_DATA\n"); + S5K3L8_read_eeprom((kal_uint16 )(*feature_data),(char*)(uintptr_t)(*(feature_data+1)),(kal_uint32)(*(feature_data+2))); + break; + /******************** PDAF END <<< *********/ + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + + +UINT32 S5K3L8_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* S5K3L8_MIPI_RAW_SensorInit */ + + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_Sensor.h new file mode 100755 index 0000000000000000000000000000000000000000..69c4917f8a8c34997bf18b21651788fac91bc2f6 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_Sensor.h @@ -0,0 +1,167 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +/***************************************************************************** + * + * Filename: + * --------- + * s5k3l8mipiraw_Sensor.h + * + * Project: + * -------- + * ALPS + * PengtaoFan + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _S5K3L8MIPI_SENSOR_H +#define _S5K3L8MIPI_SENSOR_H + +//±íʾsensorµÄ¼¸ÖÖ¹¤×÷ģʽ״̬£ºinit preview capture video hvideo svideo +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, + IMGSENSOR_MODE_CUSTOM1, + IMGSENSOR_MODE_CUSTOM2, + IMGSENSOR_MODE_CUSTOM3, + IMGSENSOR_MODE_CUSTOM4, + IMGSENSOR_MODE_CUSTOM5, +} IMGSENSOR_MODE; + +//±íʾ¼¸ÖÖ£¨²»Í¬¹¤×÷ģʽ״̬Ï£©µÄsensor²ÎÊýÐÅÏ¢ +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +//±íʾ£¨µ±Ç°×´Ì¬¹¤×÷ģʽ£©ÏµÄsensor²ÎÊýÐÅÏ¢ +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_bool ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +//sensor»ù±¾ÐÅÏ¢£¬datasheetÉϵÄÐÅÏ¢ +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint16 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + imgsensor_mode_struct custom1; //custom1 scenario relative information + imgsensor_mode_struct custom2; //custom2 scenario relative information + imgsensor_mode_struct custom3; //custom3 scenario relative information + imgsensor_mode_struct custom4; //custom4 scenario relative information + imgsensor_mode_struct custom5; //custom5 scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + kal_uint8 custom1_delay_frame; //enter custom1 delay frame num + kal_uint8 custom2_delay_frame; //enter custom1 delay frame num + kal_uint8 custom3_delay_frame; //enter custom1 delay frame num + kal_uint8 custom4_delay_frame; //enter custom1 delay frame num + kal_uint8 custom5_delay_frame; //enter custom1 delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff + kal_uint32 i2c_speed; //i2c speed +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +extern bool S5K3L8_read_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size); +extern int S5K3L8_read_eeprom_module_ID(kal_uint16 addr); + +#endif + +/* +PREVIEW:¾¡Á¿ÓÃbinning mode£¬ ²¢¸æÖªÊÇBinning average»¹ÊÇBinning sum£¿AVERAGE +ʹÓÃGP·½Ê½£¬ shutterµ±Ç°èåÉèÖúó£¬ÏÂÏÂèåÉúЧ£© +Static DPC ON +slim video ²»Óõ½120fps°É¡£ +get sensor id and Open() has more code need to reused. need to modify the two place +20150513 µÚÒ»´ÎºÏÈëPDAF²ÎÊý + +*/ \ No newline at end of file diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_pdaf.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_pdaf.c new file mode 100755 index 0000000000000000000000000000000000000000..4acba380a4f3f096f7559b98afca8f84899b9f2e --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3l8_mipi_raw/s5k3l8mipiraw_pdaf.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/*===FEATURE SWITH===*/ + // #define FPTPDAFSUPPORT //for pdaf switch + // #define FANPENGTAO //for debug log + +/*===FEATURE SWITH===*/ + +/****************************Modify Following Strings for Debug****************************/ +#define PFX "S5K3L8PDAF" +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) +/**************************** Modify end *******************************************/ + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +//extern int iBurstWriteReg_multi(u8 *pData, u32 bytes, u16 i2cId, u16 transfer_length); +extern int iMultiReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId, u8 number); + + +#define USHORT unsigned short +#define BYTE unsigned char +#define Sleep(ms) mdelay(ms) + +/************** CONFIG BY SENSOR >>> ************/ +#define EEPROM_WRITE_ID 0xA0 +#define I2C_SPEED 100 +#define MAX_OFFSET 0xFFFF +#define DATA_SIZE 1404 + +#define START_ADDR1 0x0791 +#define END_ADDR1 0x0980 //496 bytes +#define DATA_SIZE1 496 + +#define START_ADDR2 0x0983 +#define END_ADDR2 0x0D0E // 908 bytes +#define DATA_SIZE2 908 + + +BYTE S5K3L8_eeprom_data[DATA_SIZE]= {0}; + +/************** CONFIG BY SENSOR <<< ************/ + +static kal_uint16 read_cmos_sensor_byte(kal_uint16 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + + kdSetI2CSpeed(I2C_SPEED); // Add this func to set i2c speed by each sensor + iReadRegI2C(pu_send_cmd , 2, (u8*)&get_byte,1,EEPROM_WRITE_ID); + return get_byte; +} + +/* +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + + kdSetI2CSpeed(I2C_SPEED); // Add this func to set i2c speed by each sensor + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, EEPROM_WRITE_ID); + return get_byte; +} + +static void write_cmos_sensor_byte(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + + kdSetI2CSpeed(I2C_SPEED); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pu_send_cmd, 3, EEPROM_WRITE_ID); +} + +static void write_cmos_sensor(kal_uint16 addr, kal_uint16 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para >> 8),(char)(para & 0xFF)}; + + kdSetI2CSpeed(I2C_SPEED); // Add this func to set i2c speed by each sensor + iWriteRegI2C(pusendcmd , 4, EEPROM_WRITE_ID); +} +*/ + +static bool _read_eeprom(kal_uint16 addr, kal_uint32 size){ + //continue read reg by byte: + int i=0,j=0; +/* kal_uint16 addr1 = START_ADDR1; + kal_uint32 size1 = DATA_SIZE1; + + kal_uint16 addr2 = START_ADDR2; + kal_uint32 size2 = DATA_SIZE2;*/ + + for(i=0; i> 8) , (char)(addr & 0xFF) }; + kdSetI2CSpeed(I2C_SPEED); + + iReadRegI2C(pu_send_cmd, 2, (u8*)&data, 1, EEPROM_WRITE_ID); + + return data; +} + +bool S5K3L8_read_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size){ + addr = START_ADDR1; + size = DATA_SIZE; + + LOG_INF("bzl: Read EEPROM, addr = 0x%x, size = 0d%d\n", addr, size); + + if(!_read_eeprom(addr, size)){ + LOG_INF("error:read_eeprom fail!\n"); + return false; + } + + memcpy(data, S5K3L8_eeprom_data, size); + return true; +} + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..87232d1e45361e040b37ae5eef00932d576714eb --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/Makefile @@ -0,0 +1,4 @@ + +obj-y += s5k3p3sqmipiraw_Sensor.o +obj-y += s5k3p3sq_pdafotp.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sq_pdafotp.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sq_pdafotp.c new file mode 100755 index 0000000000000000000000000000000000000000..c96e8e1e4af975463501a882b30aab6556ff5f84 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sq_pdafotp.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PFX "S5K3P3SQ_pdafotp" +#define LOG_INF(format, args...) pr_warn(PFX "[%s] " format, __FUNCTION__, ##args) + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +//extern int iBurstWriteReg_multi(u8 *pData, u32 bytes, u16 i2cId, u16 transfer_length); +extern int iMultiReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId, u8 number); + + +#define USHORT unsigned short +#define BYTE unsigned char +#define Sleep(ms) mdelay(ms) + +#define S5K3P3_EEPROM_READ_ID 0xA1 +#define S5K3P3_EEPROM_WRITE_ID 0xA2 +#define S5K3P3_I2C_SPEED 100 +#define S5K3P3_MAX_OFFSET 0xFFFF + +#define DATA_SIZE 2048 +BYTE s5k3p3sq_eeprom_data[DATA_SIZE]= {0}; +static bool get_done = false; +static int last_size = 0; +static int last_offset = 0; + + +static bool selective_read_eeprom(kal_uint16 addr, BYTE* data) +{ + char pu_send_cmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + if(addr > S5K3P3_MAX_OFFSET) + return false; + kdSetI2CSpeed(S5K3P3_I2C_SPEED); + + if(iReadRegI2C(pu_send_cmd, 2, (u8*)data, 1, S5K3P3_EEPROM_WRITE_ID)<0) + return false; + return true; +} + +static bool _read_3P3_eeprom(kal_uint16 addr, BYTE* data, kal_uint32 size ){ + int i = 0; + int offset = addr; + for(i = 0; i < size; i++) { + if(!selective_read_eeprom(offset, &data[i])){ + return false; + } + LOG_INF("read_eeprom 0x%0x %d\n",offset, data[i]); + offset++; + } + get_done = true; + last_size = size; + last_offset = addr; + return true; +} + +bool read_3P3SQ_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size){ + addr = 0x801; + size = 1404; + //BYTE header[9]= {0}; + //_read_3P3_eeprom(0x0000, header, 9); + + LOG_INF("read 3P3 eeprom, size = %d\n", size); + + if(!get_done || last_size != size || last_offset != addr) { + if(!_read_3P3_eeprom(addr, s5k3p3sq_eeprom_data, size)){ + get_done = 0; + last_size = 0; + last_offset = 0; + return false; + } + } + + memcpy(data, s5k3p3sq_eeprom_data, size); + return true; +} + + +bool read_3P3SQ_eeprom_vendorinfo( kal_uint16 addr, BYTE* data, kal_uint32 size){ + + LOG_INF("read 3P3 eeprom, size = %d\n", size); + + if(!get_done || last_size != size || last_offset != addr) { + if(!_read_3P3_eeprom(addr, s5k3p3sq_eeprom_data, size)){ + get_done = 0; + last_size = 0; + last_offset = 0; + return false; + } + } + + memcpy(data, s5k3p3sq_eeprom_data, size); + return true; +} diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sqmipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sqmipiraw_Sensor.c new file mode 100755 index 0000000000000000000000000000000000000000..77b0964833c1e98787ed33a9d19f66e5f9d4de2f --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sqmipiraw_Sensor.c @@ -0,0 +1,1627 @@ +/***************************************************************************** + * + * Filename: + * --------- + * IMX214mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "s5k3p3sqmipiraw_Sensor.h" + +#define PFX "S5K3P3SQ_camera_sensor" +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = S5K3P3SQ_SENSOR_ID, + + .checksum_value =0xffb1ec31, + + .pre = { + .pclk = 560000000, //record different mode's pclk + .linelength = 7060, //record different mode's linelength + .framelength = 2640, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2304, //record different mode's width of grabwindow + .grabwindow_height = 1728, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk =560000000, + .linelength = 5148, + .framelength = 3626, + .startx =0, + .starty = 0, + .grabwindow_width = 4608, + .grabwindow_height = 3456, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 300, + }, + .cap1 = { + .pclk =560000000, + .linelength = 6416, + .framelength = 3626, + .startx = 0, + .starty = 0, + .grabwindow_width = 4608, + .grabwindow_height = 3456, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 240, + }, + .cap2 = { + .pclk =560000000, + .linelength = 10240, + .framelength = 3626, + .startx = 0, + .starty =0, + .grabwindow_width = 4608, + .grabwindow_height = 3456, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 150, + }, + .normal_video = { + .pclk =560000000, + .linelength = 5148, + .framelength = 3626, + .startx =0, + .starty = 0, + .grabwindow_width = 4608, + .grabwindow_height = 3456, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 300, + }, + .hs_video = { + .pclk = 560000000, + .linelength = 5148, + .framelength =904, + .startx = 0, + .starty = 0, + .grabwindow_width = 1152, + .grabwindow_height = 870, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 1200, + }, + .slim_video = { + .pclk = 560000000, //record different mode's pclk + .linelength = 7060, //record different mode's linelength + .framelength = 2640, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2304, //record different mode's width of grabwindow + .grabwindow_height = 1728, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + + }, + .margin = 5, + .min_shutter = 1, + .max_frame_length = 0xffff, + .ae_shut_delay_frame = 0, + .ae_sensor_gain_delay_frame =0, + .ae_ispGain_delay_frame = 2, + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num + + .cap_delay_frame = 3, + .pre_delay_frame = 3, + .video_delay_frame = 3, + .hs_video_delay_frame = 3, + .slim_video_delay_frame = 3, + + .isp_driving_current = ISP_DRIVING_2MA, + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI, + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = 0, //0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gr, + .mclk = 24, + .mipi_lane_num = SENSOR_MIPI_4_LANE, + .i2c_addr_table = {0x20,0x5a,0xff}, +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter + .gain = 0x100, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_mode = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x20, + +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{{ 4608, 3456, 0, 0, 4608, 3456, 2304, 1728, 0000, 0000, 2304, 1728, 0, 0, 2304, 1728}, // Preview + { 4608, 3456, 0, 0, 4608, 3456, 4608, 3456, 0000, 0000, 4608, 3456, 0, 0, 4608, 3456}, // capture + { 4608, 3456, 0, 0, 4608, 3456, 4608, 3456, 0000, 0000, 4608, 3456, 0, 0, 4608, 3456}, // video + { 4608, 3480, 0, 0, 4608, 3480, 1152, 870, 0000, 0000, 1152, 870, 0, 0, 1152, 870}, //hight speed video + { 4608, 3456, 0, 0, 4608, 3456, 2304, 1728, 0000, 0000, 2304, 1728, 0, 0, 2304, 1728}};// slim video + + +//no mirror flip +static SET_PD_BLOCK_INFO_T imgsensor_pd_info = +{ + .i4OffsetX = 0, + .i4OffsetY = 4, + .i4PitchX = 64, + .i4PitchY = 64, + .i4PairNum =16, + .i4SubBlkW =16, + .i4SubBlkH =16, +.i4PosL = {{8,7},{60,7},{24,11},{44,11},{12,27},{56,27},{28,31},{40,31},{28,39},{40,39},{12,43},{56,43},{24,59},{44,59},{8,63},{60,63}}, +.i4PosR = {{8,11},{60,11},{24,15},{44,15},{12,23},{56,23},{28,27},{40,27},{28,43},{40,43},{12,47},{56,47},{24,55},{44,55},{8,59},{60,59}}, +}; + +extern int iReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +extern bool read_3P3SQ_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size); +extern bool read_3P3SQ_eeprom_vendorinfo( kal_uint16 addr, BYTE* data, kal_uint32 size); + +#if 0 +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + iReadReg((u16) addr ,(u8*)&get_byte, imgsensor.i2c_write_id); + return get_byte; +} + +#define write_cmos_sensor(addr, para) iWriteReg((u16) addr , (u32) para , 1, imgsensor.i2c_write_id) +#endif +#define RWB_ID_OFFSET 0x0F73 +#define EEPROM_READ_ID 0xA0 +#define EEPROM_WRITE_ID 0xA1 + +static kal_uint16 is_RWB_sensor(void) +{ + kal_uint16 get_byte=0; + char pusendcmd[2] = {(char)(RWB_ID_OFFSET >> 8) , (char)(RWB_ID_OFFSET & 0xFF) }; + iReadRegI2C(pusendcmd , 2, (u8*)&get_byte,1,EEPROM_READ_ID); + return get_byte; + +} +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pusendcmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + iReadRegI2C(pusendcmd , 2, (u8*)&get_byte, 2, imgsensor.i2c_write_id); + return ((get_byte<<8)&0xff00)|((get_byte>>8)&0x00ff); +} + + +static void write_cmos_sensor(kal_uint16 addr, kal_uint16 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para >> 8),(char)(para & 0xFF)}; + iWriteRegI2C(pusendcmd , 4, imgsensor.i2c_write_id); +} + +static kal_uint16 read_cmos_sensor_8(kal_uint16 addr) +{ + kal_uint16 get_byte=0; + char pusendcmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + iReadRegI2C(pusendcmd , 2, (u8*)&get_byte,1,imgsensor.i2c_write_id); + return get_byte; +} + +static void write_cmos_sensor_8(kal_uint16 addr, kal_uint8 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para & 0xFF)}; + iWriteRegI2C(pusendcmd , 3, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + //return; //for test + write_cmos_sensor(0x0340, imgsensor.frame_length); + write_cmos_sensor(0x0342, imgsensor.line_length); +} /* set_dummy */ + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + + kal_uint32 frame_length = imgsensor.frame_length; + + LOG_INF("framerate = %d, min framelength should enable %d \n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + if (frame_length >= imgsensor.min_frame_length) + imgsensor.frame_length = frame_length; + else + imgsensor.frame_length = imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + +static void write_shutter(kal_uint16 shutter) +{ + + kal_uint16 realtime_fps = 0; + + + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (shutter < imgsensor_info.min_shutter) shutter = imgsensor_info.min_shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x0340, imgsensor.frame_length); + + } + } else { + // Extend frame length + write_cmos_sensor(0x0340, imgsensor.frame_length); + + } + // Update Shutter + write_cmos_sensor(0x0202, shutter); + LOG_INF("shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} /* write_shutter */ + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + write_shutter(shutter); +} /* set_shutter */ + + + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0; + + reg_gain = gain/2; + return (kal_uint16)reg_gain; +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + //gain=1024;//for test + //return; //for test + + if (gain < BASEGAIN || gain > 32 * BASEGAIN) { + LOG_INF("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 32 * BASEGAIN) + gain = 32 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + //write_cmos_sensor(0x0204,reg_gain); + write_cmos_sensor_8(0x0204,(reg_gain>>8)); + write_cmos_sensor_8(0x0205,(reg_gain&0xff)); + + return gain; +} /* set_gain */ + +static void set_mirror_flip(kal_uint8 image_mirror) +{ + + kal_uint8 itemp; + + LOG_INF("image_mirror = %d\n", image_mirror); + itemp=read_cmos_sensor(0x0101); + itemp &= ~0x03; + + switch(image_mirror) + { + + case IMAGE_NORMAL: + write_cmos_sensor(0x0101, itemp); + break; + + case IMAGE_V_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x02); + break; + + case IMAGE_H_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x01); + break; + + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x03); + break; + } +} + +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +#if 0 +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ +#endif +static void sensor_init(void) +{ + LOG_INF("E\n"); + +write_cmos_sensor(0x6010,0x0001); +mdelay(3); // Wait value must be at least 20000 MCLKs +write_cmos_sensor(0x6214,0x7971); +write_cmos_sensor(0x6218,0x0100); +write_cmos_sensor(0xF408,0x0048); +write_cmos_sensor(0xF40C,0x0000); +write_cmos_sensor(0xF4AA,0x0060); +write_cmos_sensor(0xF442,0x0800); +write_cmos_sensor(0xF43E,0x2020); +write_cmos_sensor(0xF440,0x0000); +write_cmos_sensor(0xF4AC,0x004B); +write_cmos_sensor(0xF492,0x0016); +write_cmos_sensor(0xF480,0x0040); +write_cmos_sensor(0xF4A4,0x0010); +write_cmos_sensor(0x3E58,0x004B); +write_cmos_sensor(0x3A38,0x006C); +write_cmos_sensor(0x3552,0x00D0); +write_cmos_sensor(0x3CD6,0x0100); +write_cmos_sensor(0x3CD8,0x017F); +write_cmos_sensor(0x3CDA,0x1000); +write_cmos_sensor(0x3CDC,0x104F); +write_cmos_sensor(0x3CDE,0x0180); +write_cmos_sensor(0x3CE0,0x01FF); +write_cmos_sensor(0x3CE2,0x104F); +write_cmos_sensor(0x3CE4,0x104F); +write_cmos_sensor(0x3CE6,0x0200); +write_cmos_sensor(0x3CE8,0x03FF); +write_cmos_sensor(0x3CEA,0x104F); +write_cmos_sensor(0x3CEC,0x1058); +write_cmos_sensor(0x3CEE,0x0400); +write_cmos_sensor(0x3CF0,0x07FF); +write_cmos_sensor(0x3CF2,0x1057); +write_cmos_sensor(0x3CF4,0x1073); +write_cmos_sensor(0x3CF6,0x0800); +write_cmos_sensor(0x3CF8,0x1000); +write_cmos_sensor(0x3CFA,0x1073); +write_cmos_sensor(0x3CFC,0x10A2); +write_cmos_sensor(0x3D16,0x0100); +write_cmos_sensor(0x3D18,0x017F); +write_cmos_sensor(0x3D1A,0x1000); +write_cmos_sensor(0x3D1C,0x104F); +write_cmos_sensor(0x3D1E,0x0180); +write_cmos_sensor(0x3D20,0x01FF); +write_cmos_sensor(0x3D22,0x104F); +write_cmos_sensor(0x3D24,0x104F); +write_cmos_sensor(0x3D26,0x0200); +write_cmos_sensor(0x3D28,0x03FF); +write_cmos_sensor(0x3D2A,0x104F); +write_cmos_sensor(0x3D2C,0x1058); +write_cmos_sensor(0x3D2E,0x0400); +write_cmos_sensor(0x3D30,0x07FF); +write_cmos_sensor(0x3D32,0x1057); +write_cmos_sensor(0x3D34,0x1073); +write_cmos_sensor(0x3D36,0x0800); +write_cmos_sensor(0x3D38,0x1000); +write_cmos_sensor(0x3D3A,0x1073); +write_cmos_sensor(0x3D3C,0x10A2); +write_cmos_sensor(0x3002,0x0001); +write_cmos_sensor(0x021B,0x0100); +write_cmos_sensor(0x0202,0x0100); +write_cmos_sensor(0x0200,0x0200); +write_cmos_sensor(0x021E,0x0100); +write_cmos_sensor(0x021C,0x0200); +write_cmos_sensor(0x3072,0x03C0); +write_cmos_sensor(0x6028,0x4000);//TnP v150721 +write_cmos_sensor(0x0B08,0x0000); +write_cmos_sensor(0x3058,0x0001); +write_cmos_sensor(0x316C,0x0084); +write_cmos_sensor(0x316E,0x1283); +write_cmos_sensor(0x3170,0x0060); +write_cmos_sensor(0x3172,0x0DDF); +write_cmos_sensor(0x3D66,0x0010); +write_cmos_sensor(0x3D68,0x1004); +write_cmos_sensor(0x3D6A,0x0404); +write_cmos_sensor(0x3D6C,0x0704); +write_cmos_sensor(0x3D6E,0x0B08); +write_cmos_sensor(0x3D70,0x0708); +write_cmos_sensor(0x3D72,0x0B08); +write_cmos_sensor(0x3D74,0x0B08); +write_cmos_sensor(0x3D76,0x0F00); +write_cmos_sensor(0x9920,0x0104); +write_cmos_sensor(0x9928,0x03CB); +write_cmos_sensor(0x3D78,0x396C); +write_cmos_sensor(0x3D7A,0x93C6); + +} /* sensor_init */ + + +static void preview_setting(void) +{ + //Preview 2104*1560 30fps 24M MCLK 4lane 608Mbps/lane + // preview 30.01fps +LOG_INF("E\n"); +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x0010); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x0900); +write_cmos_sensor(0x034E,0x06C0); +write_cmos_sensor(0x0408,0x0004); +write_cmos_sensor(0x0900,0x0122); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0003); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0003); +write_cmos_sensor(0x0400,0x0001); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0037); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x1B94); +write_cmos_sensor(0x0340,0x0A50); +write_cmos_sensor(0x0B0E,0x0100); +write_cmos_sensor(0x0216,0x0000); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); + + + +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + // full size 29.76fps + // capture setting 4208*3120 480MCLK 1.2Gp/lane +if(currefps==300){ +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x1110); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x1200); +write_cmos_sensor(0x034E,0x0D80); +write_cmos_sensor(0x0408,0x0008); +write_cmos_sensor(0x0900,0x0011); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0001); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0001); +write_cmos_sensor(0x0400,0x0000); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0074); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x141C); +write_cmos_sensor(0x0340,0x0E2A); +write_cmos_sensor(0x0B0E,0x0000); +write_cmos_sensor(0x0216,0x0101); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); + +} +else if(currefps==240){ +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x1110); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x1200); +write_cmos_sensor(0x034E,0x0D80); +write_cmos_sensor(0x0408,0x0008); +write_cmos_sensor(0x0900,0x0011); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0001); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0001); +write_cmos_sensor(0x0400,0x0000); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x005D); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x1910); +write_cmos_sensor(0x0340,0x0E2A); +write_cmos_sensor(0x0B0E,0x0000); +write_cmos_sensor(0x0216,0x0101); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); +} +else{ //15fps +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x1110); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x1200); +write_cmos_sensor(0x034E,0x0D80); +write_cmos_sensor(0x0408,0x0008); +write_cmos_sensor(0x0900,0x0011); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0001); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0001); +write_cmos_sensor(0x0400,0x0000); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0037); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x2800); +write_cmos_sensor(0x0340,0x0E2A); +write_cmos_sensor(0x0B0E,0x0000); +write_cmos_sensor(0x0216,0x0101); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); + +} +} +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + // full size 30fps +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x1110); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x1200); +write_cmos_sensor(0x034E,0x0D80); +write_cmos_sensor(0x0408,0x0008); +write_cmos_sensor(0x0900,0x0011); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0001); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0001); +write_cmos_sensor(0x0400,0x0000); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0074); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x141C); +write_cmos_sensor(0x0340,0x0E2A); +write_cmos_sensor(0x0B0E,0x0000); +write_cmos_sensor(0x0216,0x0101); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); +} +static void hs_video_setting(void) +{ + LOG_INF("E\n"); +//720p 120fps +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x0010); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0000); +write_cmos_sensor(0x0346,0x0008); +write_cmos_sensor(0x0348,0x121F); +write_cmos_sensor(0x034A,0x0D9F); +write_cmos_sensor(0x034C,0x0480); +write_cmos_sensor(0x034E,0x0366); +write_cmos_sensor(0x0408,0x0004); +write_cmos_sensor(0x0900,0x0144); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0007); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0007); +write_cmos_sensor(0x0400,0x0001); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0037); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x141C); +write_cmos_sensor(0x0340,0x0388); +write_cmos_sensor(0x0B0E,0x0100); +write_cmos_sensor(0x0216,0x0000); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); + +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + preview_setting(); +} + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + unsigned char vendorid[9] = {0}; + + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = ((read_cmos_sensor_8(0x0000) << 8) | read_cmos_sensor_8(0x0001)); + read_3P3SQ_eeprom_vendorinfo(0x01,vendorid,9); + (*sensor_id) += (UINT32)vendorid[8]; + LOG_INF("read_0x0000=0x%x, 0x0001=0x%x,0x0000_0001=0x%x\n",read_cmos_sensor_8(0x0000),read_cmos_sensor_8(0x0001),read_cmos_sensor(0x0000)); + if (*sensor_id ==imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + if(is_RWB_sensor()==0x1){ + imgsensor_info.sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_RWB_Wr; + LOG_INF("RWB sensor of S5k3p3\n"); + } + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, id: 0x%x\n", imgsensor.i2c_write_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint16 sensor_id = 0; + kal_uint8 vendorid[9] = {0}; + LOG_INF("PLATFORM:MT6595,MIPI 2LANE\n"); + LOG_INF("preview 1280*960@30fps,864Mbps/lane; video 1280*960@30fps,864Mbps/lane; capture 5M@30fps,864Mbps/lane\n"); + + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = ((read_cmos_sensor_8(0x0000) << 8) | read_cmos_sensor_8(0x0001)); + read_3P3SQ_eeprom_vendorinfo(0x01,vendorid,9); + sensor_id += vendorid[8]; + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, id: 0x%x\n", imgsensor.i2c_write_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.shutter = 0x3D0; + imgsensor.gain = 0x100; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_mode = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + + preview_setting(); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else if(imgsensor.current_fps == imgsensor_info.cap2.max_framerate){ + imgsensor.pclk = imgsensor_info.cap2.pclk; + imgsensor.line_length = imgsensor_info.cap2.linelength; + imgsensor.frame_length = imgsensor_info.cap2.framelength; + imgsensor.min_frame_length = imgsensor_info.cap2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + }else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + + capture_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + + normal_video_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + sensor_info->PDAF_Support = 1; + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else if (imgsensor.current_fps == imgsensor_info.cap2.max_framerate) { + frame_length = imgsensor_info.cap2.pclk / framerate * 10 / imgsensor_info.cap2.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap2.framelength) ? (frame_length - imgsensor_info.cap2.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + //set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0600, 0x0002); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0600,0x0000); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + + SET_PD_BLOCK_INFO_T *PDAFinfo; + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + LOG_INF("feature_Control imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + //night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_GET_PDAF_DATA: + LOG_INF("SENSOR_FEATURE_GET_PDAF_DATA\n"); + read_3P3SQ_eeprom((kal_uint16 )(*feature_data),(char*)(uintptr_t)(*(feature_data+1)),(kal_uint32)(*(feature_data+2))); + break; + + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_mode = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_GET_PDAF_INFO: + LOG_INF("SENSOR_FEATURE_GET_PDAF_INFO scenarioId:%d\n", (UINT32)*feature_data); + PDAFinfo= (SET_PD_BLOCK_INFO_T *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)PDAFinfo,(void *)&imgsensor_pd_info,sizeof(SET_PD_BLOCK_INFO_T)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + case MSDK_SCENARIO_ID_SLIM_VIDEO: + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + break; + } + break; + case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: + LOG_INF("SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY scenarioId:%d\n", (UINT32)*feature_data); + //PDAF capacity enable or not, 2p8 only full size support PDAF + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 1; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; // video & capture use same setting + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + default: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + } + break; + + + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + //ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + case SENSOR_FEATURE_SET_AWB_GAIN: + break; + case SENSOR_FEATURE_SET_HDR_SHUTTER: + LOG_INF("SENSOR_FEATURE_SET_HDR_SHUTTER LE=%d, SE=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1)); + //ihdr_write_shutter((UINT16)*feature_data,(UINT16)*(feature_data+1)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +//kin0603 +UINT32 S5K3P3SQ_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +//UINT32 IMX214_MIPI_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV5693_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sqmipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sqmipiraw_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..a8aa1d4c2b28622034700bafe1060e4da79d9e1d --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sq_mipi_raw/s5k3p3sqmipiraw_Sensor.h @@ -0,0 +1,125 @@ +/***************************************************************************** + * + * Filename: + * --------- + * imx214mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _S5K3P3SXMIPI_SENSOR_H +#define _S5K3P3SXMIPI_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_mode; //ihdr mode 0: disable, 1: ihdr, 2:mVHDR, 9:zigzag + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint16 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information + imgsensor_mode_struct cap2; //capture for PIP 24fps relative information + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat; + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern bool read_3P3_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a092aa1cae26671fb2c1d70fa0bca4e0a4f219aa --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/Makefile @@ -0,0 +1,4 @@ + +obj-y += s5k3p3sxmipiraw_Sensor.o +obj-y += s5k3P3_pdafotp.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3P3_pdafotp.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3P3_pdafotp.c new file mode 100755 index 0000000000000000000000000000000000000000..879941f1c57ef37633bc5299b7b17b7dbe26edfb --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3P3_pdafotp.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PFX "S5K3P3_pdafotp" +#define LOG_INF(format, args...) pr_warn(PFX "[%s] " format, __FUNCTION__, ##args) + +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +//extern int iBurstWriteReg_multi(u8 *pData, u32 bytes, u16 i2cId, u16 transfer_length); +extern int iMultiReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId, u8 number); + + +#define USHORT unsigned short +#define BYTE unsigned char +#define Sleep(ms) mdelay(ms) + +#define S5K3P3_EEPROM_READ_ID 0xA1 +#define S5K3P3_EEPROM_WRITE_ID 0xA2 +#define S5K3P3_I2C_SPEED 100 +#define S5K3P3_MAX_OFFSET 0xFFFF + +#define DATA_SIZE 2048 +BYTE s5k3P3_eeprom_data[DATA_SIZE]= {0}; +static bool get_done = false; +static int last_size = 0; +static int last_offset = 0; + + +static bool selective_read_eeprom(kal_uint16 addr, BYTE* data) +{ + char pu_send_cmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + if(addr > S5K3P3_MAX_OFFSET) + return false; + kdSetI2CSpeed(S5K3P3_I2C_SPEED); + + if(iReadRegI2C(pu_send_cmd, 2, (u8*)data, 1, S5K3P3_EEPROM_WRITE_ID)<0) + return false; + return true; +} + +static bool _read_3P3_eeprom(kal_uint16 addr, BYTE* data, kal_uint32 size ){ + int i = 0; + int offset = addr; + for(i = 0; i < size; i++) { + if(!selective_read_eeprom(offset, &data[i])){ + return false; + } + LOG_INF("read_eeprom 0x%0x %d\n",offset, data[i]); + offset++; + } + get_done = true; + last_size = size; + last_offset = addr; + return true; +} + +bool read_3P3_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size){ + addr = 0x801; + size = 1404; + //BYTE header[9]= {0}; + //_read_3P3_eeprom(0x0000, header, 9); + + LOG_INF("read 3P3 eeprom, size = %d\n", size); + + if(!get_done || last_size != size || last_offset != addr) { + if(!_read_3P3_eeprom(addr, s5k3P3_eeprom_data, size)){ + get_done = 0; + last_size = 0; + last_offset = 0; + return false; + } + } + + memcpy(data, s5k3P3_eeprom_data, size); + return true; +} + + +bool read_3P3_eeprom_vendorinfo( kal_uint16 addr, BYTE* data, kal_uint32 size){ + + LOG_INF("read 3P3 eeprom, size = %d\n", size); + + if(!get_done || last_size != size || last_offset != addr) { + if(!_read_3P3_eeprom(addr, s5k3P3_eeprom_data, size)){ + get_done = 0; + last_size = 0; + last_offset = 0; + return false; + } + } + + memcpy(data, s5k3P3_eeprom_data, size); + return true; +} diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3p3sxmipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3p3sxmipiraw_Sensor.c new file mode 100755 index 0000000000000000000000000000000000000000..3669ec82a861913e404af0ab7b6a042f356b000a --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3p3sxmipiraw_Sensor.c @@ -0,0 +1,1619 @@ +/***************************************************************************** + * + * Filename: + * --------- + * IMX214mipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "s5k3p3sxmipiraw_Sensor.h" + +#define PFX "S5K3P3SX_camera_sensor" +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = S5K3P3SX_SENSOR_ID, + + .checksum_value =0xffb1ec31, + + .pre = { + .pclk = 560000000, //record different mode's pclk + .linelength = 7060, //record different mode's linelength + .framelength = 2640, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2304, //record different mode's width of grabwindow + .grabwindow_height = 1728, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk =560000000, + .linelength = 5148, + .framelength = 3626, + .startx =0, + .starty = 0, + .grabwindow_width = 4608, + .grabwindow_height = 3456, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 300, + }, + .cap1 = { + .pclk =560000000, + .linelength = 6416, + .framelength = 3626, + .startx = 0, + .starty = 0, + .grabwindow_width = 4608, + .grabwindow_height = 3456, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 240, + }, + .cap2 = { + .pclk =560000000, + .linelength = 10240, + .framelength = 3626, + .startx = 0, + .starty =0, + .grabwindow_width = 4608, + .grabwindow_height = 3456, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 150, + }, + .normal_video = { + .pclk =560000000, + .linelength = 5148, + .framelength = 3626, + .startx =0, + .starty = 0, + .grabwindow_width = 4608, + .grabwindow_height = 3456, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 300, + }, + .hs_video = { + .pclk = 560000000, + .linelength = 5148, + .framelength =904, + .startx = 0, + .starty = 0, + .grabwindow_width = 1152, + .grabwindow_height = 870, + .mipi_data_lp2hs_settle_dc = 85, + .max_framerate = 1200, + }, + .slim_video = { + .pclk = 560000000, //record different mode's pclk + .linelength = 7060, //record different mode's linelength + .framelength = 2640, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 2304, //record different mode's width of grabwindow + .grabwindow_height = 1728, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 85, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + + }, + .margin = 5, + .min_shutter = 1, + .max_frame_length = 0xffff, + .ae_shut_delay_frame = 0, + .ae_sensor_gain_delay_frame =0, + .ae_ispGain_delay_frame = 2, + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num + + .cap_delay_frame = 3, + .pre_delay_frame = 3, + .video_delay_frame = 3, + .hs_video_delay_frame = 3, + .slim_video_delay_frame = 3, + + .isp_driving_current = ISP_DRIVING_2MA, + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI, + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = 0, //0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gr, + .mclk = 24, + .mipi_lane_num = SENSOR_MIPI_4_LANE, + .i2c_addr_table = {0x20,0x5a,0xff}, +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter + .gain = 0x100, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_mode = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x20, + +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{{ 4608, 3456, 0, 0, 4608, 3456, 2304, 1728, 0000, 0000, 2304, 1728, 0, 0, 2304, 1728}, // Preview + { 4608, 3456, 0, 0, 4608, 3456, 4608, 3456, 0000, 0000, 4608, 3456, 0, 0, 4608, 3456}, // capture + { 4608, 3456, 0, 0, 4608, 3456, 4608, 3456, 0000, 0000, 4608, 3456, 0, 0, 4608, 3456}, // video + { 4608, 3480, 0, 0, 4608, 3480, 1152, 870, 0000, 0000, 1152, 870, 0, 0, 1152, 870}, //hight speed video + { 4608, 3456, 0, 0, 4608, 3456, 2304, 1728, 0000, 0000, 2304, 1728, 0, 0, 2304, 1728}};// slim video + + +//no mirror flip +static SET_PD_BLOCK_INFO_T imgsensor_pd_info = +{ + .i4OffsetX = 0, + .i4OffsetY = 4, + .i4PitchX = 64, + .i4PitchY = 64, + .i4PairNum =16, + .i4SubBlkW =16, + .i4SubBlkH =16, +.i4PosL = {{8,7},{60,7},{24,11},{44,11},{12,27},{56,27},{28,31},{40,31},{28,39},{40,39},{12,43},{56,43},{24,59},{44,59},{8,63},{60,63}}, +.i4PosR = {{8,11},{60,11},{24,15},{44,15},{12,23},{56,23},{28,27},{40,27},{28,43},{40,43},{12,47},{56,47},{24,55},{44,55},{8,59},{60,59}}, +}; + +extern int iReadReg(u16 a_u2Addr , u8 * a_puBuff , u16 i2cId); +extern int iWriteReg(u16 a_u2Addr , u32 a_u4Data , u32 a_u4Bytes , u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); +extern bool read_3P3_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size); + +#if 0 +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + iReadReg((u16) addr ,(u8*)&get_byte, imgsensor.i2c_write_id); + return get_byte; +} + +#define write_cmos_sensor(addr, para) iWriteReg((u16) addr , (u32) para , 1, imgsensor.i2c_write_id) +#endif +#define RWB_ID_OFFSET 0x0F73 +#define EEPROM_READ_ID 0xA0 +#define EEPROM_WRITE_ID 0xA1 + +static kal_uint16 is_RWB_sensor(void) +{ + kal_uint16 get_byte=0; + char pusendcmd[2] = {(char)(RWB_ID_OFFSET >> 8) , (char)(RWB_ID_OFFSET & 0xFF) }; + iReadRegI2C(pusendcmd , 2, (u8*)&get_byte,1,EEPROM_READ_ID); + return get_byte; + +} +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + char pusendcmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + iReadRegI2C(pusendcmd , 2, (u8*)&get_byte, 2, imgsensor.i2c_write_id); + return ((get_byte<<8)&0xff00)|((get_byte>>8)&0x00ff); +} + + +static void write_cmos_sensor(kal_uint16 addr, kal_uint16 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para >> 8),(char)(para & 0xFF)}; + iWriteRegI2C(pusendcmd , 4, imgsensor.i2c_write_id); +} + +static kal_uint16 read_cmos_sensor_8(kal_uint16 addr) +{ + kal_uint16 get_byte=0; + char pusendcmd[2] = {(char)(addr >> 8) , (char)(addr & 0xFF) }; + iReadRegI2C(pusendcmd , 2, (u8*)&get_byte,1,imgsensor.i2c_write_id); + return get_byte; +} + +static void write_cmos_sensor_8(kal_uint16 addr, kal_uint8 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para & 0xFF)}; + iWriteRegI2C(pusendcmd , 3, imgsensor.i2c_write_id); +} + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + //return; //for test + write_cmos_sensor(0x0340, imgsensor.frame_length); + write_cmos_sensor(0x0342, imgsensor.line_length); +} /* set_dummy */ + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + + kal_uint32 frame_length = imgsensor.frame_length; + + LOG_INF("framerate = %d, min framelength should enable %d \n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + if (frame_length >= imgsensor.min_frame_length) + imgsensor.frame_length = frame_length; + else + imgsensor.frame_length = imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + +static void write_shutter(kal_uint16 shutter) +{ + + kal_uint16 realtime_fps = 0; + + + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (shutter < imgsensor_info.min_shutter) shutter = imgsensor_info.min_shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x0340, imgsensor.frame_length); + + } + } else { + // Extend frame length + write_cmos_sensor(0x0340, imgsensor.frame_length); + + } + // Update Shutter + write_cmos_sensor(0x0202, shutter); + LOG_INF("shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + +} /* write_shutter */ + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + write_shutter(shutter); +} /* set_shutter */ + + + +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + kal_uint16 reg_gain = 0x0; + + reg_gain = gain/2; + return (kal_uint16)reg_gain; +} + +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + //gain=1024;//for test + //return; //for test + + if (gain < BASEGAIN || gain > 32 * BASEGAIN) { + LOG_INF("Error gain setting"); + + if (gain < BASEGAIN) + gain = BASEGAIN; + else if (gain > 32 * BASEGAIN) + gain = 32 * BASEGAIN; + } + + reg_gain = gain2reg(gain); + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + //write_cmos_sensor(0x0204,reg_gain); + write_cmos_sensor_8(0x0204,(reg_gain>>8)); + write_cmos_sensor_8(0x0205,(reg_gain&0xff)); + + return gain; +} /* set_gain */ + +static void set_mirror_flip(kal_uint8 image_mirror) +{ + + kal_uint8 itemp; + + LOG_INF("image_mirror = %d\n", image_mirror); + itemp=read_cmos_sensor(0x0101); + itemp &= ~0x03; + + switch(image_mirror) + { + + case IMAGE_NORMAL: + write_cmos_sensor(0x0101, itemp); + break; + + case IMAGE_V_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x02); + break; + + case IMAGE_H_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x01); + break; + + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x0101, itemp | 0x03); + break; + } +} + +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +#if 0 +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ +#endif +static void sensor_init(void) +{ + LOG_INF("E\n"); + +write_cmos_sensor(0x6010,0x0001); +mdelay(3); // Wait value must be at least 20000 MCLKs +write_cmos_sensor(0x6214,0x7971); +write_cmos_sensor(0x6218,0x0100); +write_cmos_sensor(0xF408,0x0048); +write_cmos_sensor(0xF40C,0x0000); +write_cmos_sensor(0xF4AA,0x0060); +write_cmos_sensor(0xF442,0x0800); +write_cmos_sensor(0xF43E,0x2020); +write_cmos_sensor(0xF440,0x0000); +write_cmos_sensor(0xF4AC,0x004B); +write_cmos_sensor(0xF492,0x0016); +write_cmos_sensor(0xF480,0x0040); +write_cmos_sensor(0xF4A4,0x0010); +write_cmos_sensor(0x3E58,0x004B); +write_cmos_sensor(0x3A38,0x006C); +write_cmos_sensor(0x3552,0x00D0); +write_cmos_sensor(0x3CD6,0x0100); +write_cmos_sensor(0x3CD8,0x017F); +write_cmos_sensor(0x3CDA,0x1000); +write_cmos_sensor(0x3CDC,0x104F); +write_cmos_sensor(0x3CDE,0x0180); +write_cmos_sensor(0x3CE0,0x01FF); +write_cmos_sensor(0x3CE2,0x104F); +write_cmos_sensor(0x3CE4,0x104F); +write_cmos_sensor(0x3CE6,0x0200); +write_cmos_sensor(0x3CE8,0x03FF); +write_cmos_sensor(0x3CEA,0x104F); +write_cmos_sensor(0x3CEC,0x1058); +write_cmos_sensor(0x3CEE,0x0400); +write_cmos_sensor(0x3CF0,0x07FF); +write_cmos_sensor(0x3CF2,0x1057); +write_cmos_sensor(0x3CF4,0x1073); +write_cmos_sensor(0x3CF6,0x0800); +write_cmos_sensor(0x3CF8,0x1000); +write_cmos_sensor(0x3CFA,0x1073); +write_cmos_sensor(0x3CFC,0x10A2); +write_cmos_sensor(0x3D16,0x0100); +write_cmos_sensor(0x3D18,0x017F); +write_cmos_sensor(0x3D1A,0x1000); +write_cmos_sensor(0x3D1C,0x104F); +write_cmos_sensor(0x3D1E,0x0180); +write_cmos_sensor(0x3D20,0x01FF); +write_cmos_sensor(0x3D22,0x104F); +write_cmos_sensor(0x3D24,0x104F); +write_cmos_sensor(0x3D26,0x0200); +write_cmos_sensor(0x3D28,0x03FF); +write_cmos_sensor(0x3D2A,0x104F); +write_cmos_sensor(0x3D2C,0x1058); +write_cmos_sensor(0x3D2E,0x0400); +write_cmos_sensor(0x3D30,0x07FF); +write_cmos_sensor(0x3D32,0x1057); +write_cmos_sensor(0x3D34,0x1073); +write_cmos_sensor(0x3D36,0x0800); +write_cmos_sensor(0x3D38,0x1000); +write_cmos_sensor(0x3D3A,0x1073); +write_cmos_sensor(0x3D3C,0x10A2); +write_cmos_sensor(0x3002,0x0001); +write_cmos_sensor(0x021B,0x0100); +write_cmos_sensor(0x0202,0x0100); +write_cmos_sensor(0x0200,0x0200); +write_cmos_sensor(0x021E,0x0100); +write_cmos_sensor(0x021C,0x0200); +write_cmos_sensor(0x3072,0x03C0); +write_cmos_sensor(0x6028,0x4000);//TnP v150721 +write_cmos_sensor(0x0B08,0x0000); +write_cmos_sensor(0x3058,0x0001); +write_cmos_sensor(0x316C,0x0084); +write_cmos_sensor(0x316E,0x1283); +write_cmos_sensor(0x3170,0x0060); +write_cmos_sensor(0x3172,0x0DDF); +write_cmos_sensor(0x3D66,0x0010); +write_cmos_sensor(0x3D68,0x1004); +write_cmos_sensor(0x3D6A,0x0404); +write_cmos_sensor(0x3D6C,0x0704); +write_cmos_sensor(0x3D6E,0x0B08); +write_cmos_sensor(0x3D70,0x0708); +write_cmos_sensor(0x3D72,0x0B08); +write_cmos_sensor(0x3D74,0x0B08); +write_cmos_sensor(0x3D76,0x0F00); +write_cmos_sensor(0x9920,0x0104); +write_cmos_sensor(0x9928,0x03CB); +write_cmos_sensor(0x3D78,0x396C); +write_cmos_sensor(0x3D7A,0x93C6); + +} /* sensor_init */ + + +static void preview_setting(void) +{ + //Preview 2104*1560 30fps 24M MCLK 4lane 608Mbps/lane + // preview 30.01fps +LOG_INF("E\n"); +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x0010); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x0900); +write_cmos_sensor(0x034E,0x06C0); +write_cmos_sensor(0x0408,0x0004); +write_cmos_sensor(0x0900,0x0122); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0003); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0003); +write_cmos_sensor(0x0400,0x0001); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0037); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x1B94); +write_cmos_sensor(0x0340,0x0A50); +write_cmos_sensor(0x0B0E,0x0100); +write_cmos_sensor(0x0216,0x0000); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); + + + +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + // full size 29.76fps + // capture setting 4208*3120 480MCLK 1.2Gp/lane +if(currefps==300){ +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x1110); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x1200); +write_cmos_sensor(0x034E,0x0D80); +write_cmos_sensor(0x0408,0x0008); +write_cmos_sensor(0x0900,0x0011); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0001); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0001); +write_cmos_sensor(0x0400,0x0000); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0074); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x141C); +write_cmos_sensor(0x0340,0x0E2A); +write_cmos_sensor(0x0B0E,0x0000); +write_cmos_sensor(0x0216,0x0101); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); + +} +else if(currefps==240){ +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x1110); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x1200); +write_cmos_sensor(0x034E,0x0D80); +write_cmos_sensor(0x0408,0x0008); +write_cmos_sensor(0x0900,0x0011); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0001); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0001); +write_cmos_sensor(0x0400,0x0000); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x005D); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x1910); +write_cmos_sensor(0x0340,0x0E2A); +write_cmos_sensor(0x0B0E,0x0000); +write_cmos_sensor(0x0216,0x0101); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); +} +else{ //15fps +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x1110); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x1200); +write_cmos_sensor(0x034E,0x0D80); +write_cmos_sensor(0x0408,0x0008); +write_cmos_sensor(0x0900,0x0011); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0001); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0001); +write_cmos_sensor(0x0400,0x0000); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0037); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x2800); +write_cmos_sensor(0x0340,0x0E2A); +write_cmos_sensor(0x0B0E,0x0000); +write_cmos_sensor(0x0216,0x0101); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); + +} +} +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + // full size 30fps +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x1110); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0008); +write_cmos_sensor(0x0346,0x0014); +write_cmos_sensor(0x0348,0x1217); +write_cmos_sensor(0x034A,0x0D93); +write_cmos_sensor(0x034C,0x1200); +write_cmos_sensor(0x034E,0x0D80); +write_cmos_sensor(0x0408,0x0008); +write_cmos_sensor(0x0900,0x0011); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0001); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0001); +write_cmos_sensor(0x0400,0x0000); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0074); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x141C); +write_cmos_sensor(0x0340,0x0E2A); +write_cmos_sensor(0x0B0E,0x0000); +write_cmos_sensor(0x0216,0x0101); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); +} +static void hs_video_setting(void) +{ + LOG_INF("E\n"); +//720p 120fps +write_cmos_sensor_8(0x0100,0x00); +write_cmos_sensor(0x6028,0x4000); +write_cmos_sensor(0x3D7C,0x0010); +write_cmos_sensor(0x3D88,0x0064); +write_cmos_sensor(0x3D8A,0x0068); +write_cmos_sensor(0x0344,0x0000); +write_cmos_sensor(0x0346,0x0008); +write_cmos_sensor(0x0348,0x121F); +write_cmos_sensor(0x034A,0x0D9F); +write_cmos_sensor(0x034C,0x0480); +write_cmos_sensor(0x034E,0x0366); +write_cmos_sensor(0x0408,0x0004); +write_cmos_sensor(0x0900,0x0144); +write_cmos_sensor(0x0380,0x0001); +write_cmos_sensor(0x0382,0x0007); +write_cmos_sensor(0x0384,0x0001); +write_cmos_sensor(0x0386,0x0007); +write_cmos_sensor(0x0400,0x0001); +write_cmos_sensor(0x0404,0x0010); +write_cmos_sensor(0x0114,0x0300); +write_cmos_sensor(0x0110,0x0002); +write_cmos_sensor(0x0136,0x1800); +write_cmos_sensor(0x0304,0x0006); +write_cmos_sensor(0x0306,0x008C); +write_cmos_sensor(0x0302,0x0001); +write_cmos_sensor(0x0300,0x0004); +write_cmos_sensor(0x030C,0x0004); +write_cmos_sensor(0x030E,0x0037); +write_cmos_sensor(0x030A,0x0001); +write_cmos_sensor(0x0308,0x0008); +write_cmos_sensor(0x0342,0x141C); +write_cmos_sensor(0x0340,0x0388); +write_cmos_sensor(0x0B0E,0x0100); +write_cmos_sensor(0x0216,0x0000); +write_cmos_sensor(0x6214,0x7970); +write_cmos_sensor_8(0x0100,0x01); + +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + preview_setting(); +} + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = ((read_cmos_sensor_8(0x0000) << 8) | read_cmos_sensor_8(0x0001)); + LOG_INF("read_0x0000=0x%x, 0x0001=0x%x,0x0000_0001=0x%x\n",read_cmos_sensor_8(0x0000),read_cmos_sensor_8(0x0001),read_cmos_sensor(0x0000)); + if (*sensor_id ==imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + if(is_RWB_sensor()==0x1){ + imgsensor_info.sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_RWB_Wr; + LOG_INF("RWB sensor of S5k3p3\n"); + } + return ERROR_NONE; + } + LOG_INF("Read sensor id fail, id: 0x%x\n", imgsensor.i2c_write_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint16 sensor_id = 0; + LOG_INF("PLATFORM:MT6595,MIPI 2LANE\n"); + LOG_INF("preview 1280*960@30fps,864Mbps/lane; video 1280*960@30fps,864Mbps/lane; capture 5M@30fps,864Mbps/lane\n"); + + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = ((read_cmos_sensor_8(0x0000) << 8) | read_cmos_sensor_8(0x0001)); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail, id: 0x%x\n", imgsensor.i2c_write_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.shutter = 0x3D0; + imgsensor.gain = 0x100; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_mode = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + + preview_setting(); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else if(imgsensor.current_fps == imgsensor_info.cap2.max_framerate){ + imgsensor.pclk = imgsensor_info.cap2.pclk; + imgsensor.line_length = imgsensor_info.cap2.linelength; + imgsensor.frame_length = imgsensor_info.cap2.framelength; + imgsensor.min_frame_length = imgsensor_info.cap2.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + }else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + + capture_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + + normal_video_setting(imgsensor.current_fps); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + set_mirror_flip(imgsensor.mirror); + + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + sensor_info->PDAF_Support = 1; + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else if (imgsensor.current_fps == imgsensor_info.cap2.max_framerate) { + frame_length = imgsensor_info.cap2.pclk / framerate * 10 / imgsensor_info.cap2.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap2.framelength) ? (frame_length - imgsensor_info.cap2.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap2.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + //set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + //set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0600, 0x0002); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0600,0x0000); + } + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + + SET_PD_BLOCK_INFO_T *PDAFinfo; + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d\n", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + LOG_INF("feature_Control imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + //night_mode((BOOL) *feature_data); + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_GET_PDAF_DATA: + LOG_INF("SENSOR_FEATURE_GET_PDAF_DATA\n"); + read_3P3_eeprom((kal_uint16 )(*feature_data),(char*)(uintptr_t)(*(feature_data+1)),(kal_uint32)(*(feature_data+2))); + break; + + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.ihdr_mode = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_GET_PDAF_INFO: + LOG_INF("SENSOR_FEATURE_GET_PDAF_INFO scenarioId:%d\n", (UINT32)*feature_data); + PDAFinfo= (SET_PD_BLOCK_INFO_T *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)PDAFinfo,(void *)&imgsensor_pd_info,sizeof(SET_PD_BLOCK_INFO_T)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + case MSDK_SCENARIO_ID_SLIM_VIDEO: + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + break; + } + break; + case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: + LOG_INF("SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY scenarioId:%d\n", (UINT32)*feature_data); + //PDAF capacity enable or not, 2p8 only full size support PDAF + switch (*feature_data) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 1; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; // video & capture use same setting + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + default: + *(MUINT32 *)(uintptr_t)(*(feature_data+1)) = 0; + break; + } + break; + + + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + //ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + case SENSOR_FEATURE_SET_AWB_GAIN: + break; + case SENSOR_FEATURE_SET_HDR_SHUTTER: + LOG_INF("SENSOR_FEATURE_SET_HDR_SHUTTER LE=%d, SE=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1)); + //ihdr_write_shutter((UINT16)*feature_data,(UINT16)*(feature_data+1)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +//kin0603 +UINT32 S5K3P3SX_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +//UINT32 IMX214_MIPI_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV5693_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3p3sxmipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3p3sxmipiraw_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..a8aa1d4c2b28622034700bafe1060e4da79d9e1d --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k3p3sx_mipi_raw/s5k3p3sxmipiraw_Sensor.h @@ -0,0 +1,125 @@ +/***************************************************************************** + * + * Filename: + * --------- + * imx214mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _S5K3P3SXMIPI_SENSOR_H +#define _S5K3P3SXMIPI_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_mode; //ihdr mode 0: disable, 1: ihdr, 2:mVHDR, 9:zigzag + + kal_uint8 i2c_write_id; //record current sensor's i2c write id +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint16 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information + imgsensor_mode_struct cap2; //capture for PIP 24fps relative information + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat; + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern bool read_3P3_eeprom( kal_uint16 addr, BYTE* data, kal_uint32 size); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..71a99ab28f070562cde9df297eea2f010b81453a --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + + +obj-y += s5k5e2yamipiraw_Sensor.o + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/s5k5e2yamipiraw_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/s5k5e2yamipiraw_Sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..506925b95070029ca52f4eb44f473f8b7ae28efd --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/s5k5e2yamipiraw_Sensor.c @@ -0,0 +1,1877 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/* ***************************************************************************** + * + * Filename: + * --------- + * s5k5e2yamipi_Sensor.c + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * Source code of Sensor driver + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" + +#include "s5k5e2yamipiraw_Sensor.h" + +/****************************Modify following Strings for debug****************************/ +#define PFX "s5k5e2ya_camera_sensor" +#define LOG_1 LOG_INF("s5k5e2ya,MIPI 2LANE\n") +#define LOG_2 LOG_INF("preview 1280*960@30fps,864Mbps/lane; video 1280*960@30fps,864Mbps/lane; capture 5M@30fps,864Mbps/lane\n") +/**************************** Modify end *******************************************/ +#define LOG_INF(format, args...) pr_debug(PFX "[%s] " format, __FUNCTION__, ##args) + +static DEFINE_SPINLOCK(imgsensor_drv_lock); + +#define MIPI_SETTLEDELAY_AUTO 0 +#define MIPI_SETTLEDELAY_MANNUAL 1 + + +//#define CAPTURE_24FPS + + +static imgsensor_info_struct imgsensor_info = { + .sensor_id = S5K5E2YA_SENSOR_ID, + + .checksum_value = 0xa48ebf5d, + + .pre = { + .pclk = 179200000, //record different mode's pclk + .linelength = 2950, //record different mode's linelength + .framelength = 2000, //record different mode's framelength + .startx = 0, //record different mode's startx of grabwindow + .starty = 0, //record different mode's starty of grabwindow + .grabwindow_width = 1280, //record different mode's width of grabwindow + .grabwindow_height = 960, //record different mode's height of grabwindow + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + .mipi_data_lp2hs_settle_dc = 23, + /* following for GetDefaultFramerateByScenario() */ + .max_framerate = 300, + }, + .cap = { + .pclk = 179200000, + .linelength = 2950, + .framelength = 2025, + .startx = 0, + .starty = 0, + .grabwindow_width = 2560, + .grabwindow_height = 1920, + .mipi_data_lp2hs_settle_dc = 23, + .max_framerate = 300, + }, + .cap1 = { + .pclk = 89616000, + .linelength = 2950, + .framelength = 2025, + .startx = 0, + .starty = 0, + .grabwindow_width = 2560, + .grabwindow_height = 1920, + .mipi_data_lp2hs_settle_dc = 23, + .max_framerate = 150, + }, + .normal_video = { + .pclk = 179200000, + .linelength = 2950, + .framelength = 2000, + .startx = 0, + .starty = 0, + .grabwindow_width = 2560, + .grabwindow_height = 1440, + .mipi_data_lp2hs_settle_dc = 23, + .max_framerate = 300, + }, + .hs_video = { + .pclk = 179200000, + .linelength = 2950, + .framelength = 506, + .startx = 0, + .starty = 0, + .grabwindow_width = 640, + .grabwindow_height = 480, + .mipi_data_lp2hs_settle_dc = 23, + .max_framerate = 1200, + }, + .slim_video = { + .pclk = 179200000, + .linelength = 2950, + .framelength = 2000, + .startx = 0, + .starty = 0, + .grabwindow_width = 1280, + .grabwindow_height = 720, + .mipi_data_lp2hs_settle_dc = 23, + .max_framerate = 300, + }, + .margin = 4, + .min_shutter = 1, + .max_frame_length = 0xffff, + .ae_shut_delay_frame = 0, + .ae_sensor_gain_delay_frame = 1, + .ae_ispGain_delay_frame = 2, + .ihdr_support = 0, //1, support; 0,not support + .ihdr_le_firstline = 0, //1,le first ; 0, se first + .sensor_mode_num = 5, //support sensor mode num + + .cap_delay_frame = 3, + .pre_delay_frame = 3, + .video_delay_frame = 3, + .hs_video_delay_frame = 3, + .slim_video_delay_frame = 3, + + .isp_driving_current = ISP_DRIVING_6MA, + .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI, + .mipi_sensor_type = MIPI_OPHY_NCSI2, //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2 + .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO,//0,MIPI_SETTLEDELAY_AUTO; 1,MIPI_SETTLEDELAY_MANNUAL + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gr, + .mclk = 24, + .mipi_lane_num = SENSOR_MIPI_2_LANE, + .i2c_addr_table = {0x20, 0x6c, 0xff}, +}; + + +static imgsensor_struct imgsensor = { + .mirror = IMAGE_NORMAL, //mirrorflip information + .sensor_mode = IMGSENSOR_MODE_INIT, //IMGSENSOR_MODE enum value,record current sensor mode,such as: INIT, Preview, Capture, Video,High Speed Video, Slim Video + .shutter = 0x3D0, //current shutter + .gain = 0x100, //current gain + .dummy_pixel = 0, //current dummypixel + .dummy_line = 0, //current dummyline + .current_fps = 0, //full size current fps : 24fps for PIP, 30fps for Normal or ZSD + .autoflicker_en = KAL_FALSE, //auto flicker enable: KAL_FALSE for disable auto flicker, KAL_TRUE for enable auto flicker + .test_pattern = KAL_FALSE, //test pattern mode or not. KAL_FALSE for in test pattern mode, KAL_TRUE for normal output + .current_scenario_id = MSDK_SCENARIO_ID_CAMERA_PREVIEW,//current scenario id + .ihdr_en = 0, //sensor need support LE, SE with HDR feature + .i2c_write_id = 0x20, +}; + + +/* Sensor output window information */ +static SENSOR_WINSIZE_INFO_STRUCT imgsensor_winsize_info[5] = +{{ 2576, 1936, 8, 8, 2560, 1920, 1280, 960, 0000, 0000, 1280, 960, 0, 0, 1280, 960}, // Preview + { 2576, 1936, 8, 8, 2560, 1920, 2560, 1920, 0000, 0000, 2560, 1920, 0, 0, 2560, 1920}, // capture + { 2576, 1936, 8, 248, 2560, 1440, 2560, 1440, 0000, 0000, 2560, 1440, 0, 0, 2560, 1440}, // video + { 2576, 1936, 8, 8, 2560, 1440, 640, 480, 0000, 0000, 640, 480, 0, 0, 640, 480}, //hight speed video + { 2576, 1936, 8, 248, 2560, 1440, 1280, 720, 0000, 0000, 1280, 720, 0, 0, 1280, 720}};// slim video + + +static kal_uint16 read_cmos_sensor(kal_uint32 addr) +{ + kal_uint16 get_byte=0; + + char pu_send_cmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF) }; + iReadRegI2C(pu_send_cmd, 2, (u8*)&get_byte, 1, imgsensor.i2c_write_id); + + return get_byte; +} + +static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para) +{ + char pu_send_cmd[3] = {(char)(addr >> 8), (char)(addr & 0xFF), (char)(para & 0xFF)}; + iWriteRegI2C(pu_send_cmd, 3, imgsensor.i2c_write_id); +} + +static void write_cmos_sensor_8(kal_uint16 addr, kal_uint8 para) +{ + char pusendcmd[4] = {(char)(addr >> 8) , (char)(addr & 0xFF) ,(char)(para & 0xFF)}; + iWriteRegI2C(pusendcmd , 3, imgsensor.i2c_write_id); +} + + +static void set_dummy(void) +{ + LOG_INF("dummyline = %d, dummypixels = %d \n", imgsensor.dummy_line, imgsensor.dummy_pixel); + + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + write_cmos_sensor(0x0342, imgsensor.line_length >> 8); + write_cmos_sensor(0x0343, imgsensor.line_length & 0xFF); + +} /* set_dummy */ + +static kal_uint32 return_sensor_id(void) +{ + return ((read_cmos_sensor(0x0000) << 8) | read_cmos_sensor(0x0001)); + +} + + +static void set_max_framerate(UINT16 framerate,kal_bool min_framelength_en) +{ + + kal_uint32 frame_length = imgsensor.frame_length; + //unsigned long flags; + + LOG_INF("framerate = %d, min framelength should enable? %d \n", framerate,min_framelength_en); + + frame_length = imgsensor.pclk / framerate * 10 / imgsensor.line_length; + spin_lock(&imgsensor_drv_lock); + imgsensor.frame_length = (frame_length > imgsensor.min_frame_length) ? frame_length : imgsensor.min_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + //dummy_line = frame_length - imgsensor.min_frame_length; + //if (dummy_line < 0) + //imgsensor.dummy_line = 0; + //else + //imgsensor.dummy_line = dummy_line; + //imgsensor.frame_length = frame_length + imgsensor.dummy_line; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + { + imgsensor.frame_length = imgsensor_info.max_frame_length; + imgsensor.dummy_line = imgsensor.frame_length - imgsensor.min_frame_length; + } + if (min_framelength_en) + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); +} /* set_max_framerate */ + + +static void write_shutter(kal_uint16 shutter) +{ + kal_uint16 realtime_fps = 0; + + + /* 0x3500, 0x3501, 0x3502 will increase VBLANK to get exposure larger than frame exposure */ + /* AE doesn't update sensor gain at capture mode, thus extra exposure lines must be updated here. */ + + // OV Recommend Solution + // if shutter bigger than frame_length, should extend frame length first + spin_lock(&imgsensor_drv_lock); + if (shutter > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = shutter + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + shutter = (shutter < imgsensor_info.min_shutter) ? imgsensor_info.min_shutter : shutter; + shutter = (shutter > (imgsensor_info.max_frame_length - imgsensor_info.margin)) ? (imgsensor_info.max_frame_length - imgsensor_info.margin) : shutter; + + if (imgsensor.autoflicker_en) { + realtime_fps = imgsensor.pclk / imgsensor.line_length * 10 / imgsensor.frame_length; + if(realtime_fps >= 297 && realtime_fps <= 305) + set_max_framerate(296,0); + else if(realtime_fps >= 147 && realtime_fps <= 150) + set_max_framerate(146,0); + else { + // Extend frame length + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + } + } else { + // Extend frame length + write_cmos_sensor(0x0340, imgsensor.frame_length >> 8); + write_cmos_sensor(0x0341, imgsensor.frame_length & 0xFF); + } + + // Update Shutter + //write_cmos_sensor(0x0104, 0x01); //group hold + write_cmos_sensor(0x0202, shutter >> 8); + write_cmos_sensor(0x0203, shutter & 0xFF); + //write_cmos_sensor(0x0104, 0x00); //group hold + + LOG_INF("shutter =%d, framelength =%d\n", shutter,imgsensor.frame_length); + + //LOG_INF("frame_length = %d ", frame_length); + +} /* write_shutter */ + + + +/************************************************************************* +* FUNCTION +* set_shutter +* +* DESCRIPTION +* This function set e-shutter of sensor to change exposure time. +* +* PARAMETERS +* iShutter : exposured lines +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static void set_shutter(kal_uint16 shutter) +{ + unsigned long flags; + spin_lock_irqsave(&imgsensor_drv_lock, flags); + imgsensor.shutter = shutter; + spin_unlock_irqrestore(&imgsensor_drv_lock, flags); + + write_shutter(shutter); +} /* set_shutter */ + + +#if 0 +static kal_uint16 gain2reg(const kal_uint16 gain) +{ + return gain>>1; +} +#endif +/************************************************************************* +* FUNCTION +* set_gain +* +* DESCRIPTION +* This function is to set global gain to sensor. +* +* PARAMETERS +* iGain : sensor global gain(base: 0x40) +* +* RETURNS +* the actually gain set to sensor. +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint16 set_gain(kal_uint16 gain) +{ + kal_uint16 reg_gain; + + /* 0x350A[0:1], 0x350B[0:7] AGC real gain */ + /* [0:3] = N meams N /16 X */ + /* [4:9] = M meams M X */ + /* Total gain = M + N /16 X */ + + // + + + reg_gain = gain>>1; + spin_lock(&imgsensor_drv_lock); + imgsensor.gain = reg_gain; + spin_unlock(&imgsensor_drv_lock); + LOG_INF("gain = %d , reg_gain = 0x%x\n ", gain, reg_gain); + + //write_cmos_sensor(0x0104, 0x01); //group hold + write_cmos_sensor(0x0204, reg_gain >> 8); + write_cmos_sensor(0x0205, reg_gain & 0xFF); + //write_cmos_sensor(0x0104, 0x00); + + return gain; +} /* set_gain */ + + + +//defined but not used +static void ihdr_write_shutter_gain(kal_uint16 le, kal_uint16 se, kal_uint16 gain) +{ + LOG_INF("le:0x%x, se:0x%x, gain:0x%x\n",le,se,gain); + if (imgsensor.ihdr_en) { + + spin_lock(&imgsensor_drv_lock); + if (le > imgsensor.min_frame_length - imgsensor_info.margin) + imgsensor.frame_length = le + imgsensor_info.margin; + else + imgsensor.frame_length = imgsensor.min_frame_length; + if (imgsensor.frame_length > imgsensor_info.max_frame_length) + imgsensor.frame_length = imgsensor_info.max_frame_length; + spin_unlock(&imgsensor_drv_lock); + if (le < imgsensor_info.min_shutter) le = imgsensor_info.min_shutter; + if (se < imgsensor_info.min_shutter) se = imgsensor_info.min_shutter; + + + // Extend frame length first + write_cmos_sensor(0x380e, imgsensor.frame_length >> 8); + write_cmos_sensor(0x380f, imgsensor.frame_length & 0xFF); + + write_cmos_sensor(0x3502, (le << 4) & 0xFF); + write_cmos_sensor(0x3501, (le >> 4) & 0xFF); + write_cmos_sensor(0x3500, (le >> 12) & 0x0F); + + write_cmos_sensor(0x3508, (se << 4) & 0xFF); + write_cmos_sensor(0x3507, (se >> 4) & 0xFF); + write_cmos_sensor(0x3506, (se >> 12) & 0x0F); + + set_gain(gain); + } + +} + + +#if 0 +static void set_mirror_flip(kal_uint8 image_mirror) +{ + LOG_INF("image_mirror = %d\n", image_mirror); + + /******************************************************** + * + * 0x3820[2] ISP Vertical flip + * 0x3820[1] Sensor Vertical flip + * + * 0x3821[2] ISP Horizontal mirror + * 0x3821[1] Sensor Horizontal mirror + * + * ISP and Sensor flip or mirror register bit should be the same!! + * + ********************************************************/ + + switch (image_mirror) { + case IMAGE_NORMAL: + write_cmos_sensor(0x0101,0x00); + break; + case IMAGE_H_MIRROR: + write_cmos_sensor(0x0101,0x01); + break; + case IMAGE_V_MIRROR: + write_cmos_sensor(0x0101,0x02); + break; + case IMAGE_HV_MIRROR: + write_cmos_sensor(0x0101,0x03); + break; + default: + LOG_INF("Error image_mirror setting\n"); + } + +} +#endif +/************************************************************************* +* FUNCTION +* night_mode +* +* DESCRIPTION +* This function night mode of sensor. +* +* PARAMETERS +* bEnable: KAL_TRUE -> enable night mode, otherwise, disable night mode +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +#if 0 +static void night_mode(kal_bool enable) +{ +/*No Need to implement this function*/ +} /* night_mode */ +#endif +static void sensor_init(void) +{ + LOG_INF("E\n"); + + // +++++++++++++++++++++++++++// + // Reset for operation + write_cmos_sensor(0x0100,0x00); //stream off + + // Clock Setting + write_cmos_sensor(0x3000,0x04); // ct_ld_start + write_cmos_sensor(0x3002,0x03); // ct_sl_start + write_cmos_sensor(0x3003,0x04); // ct_sl_margin + write_cmos_sensor(0x3004,0x02); // ct_rx_start + write_cmos_sensor(0x3005,0x00); // ct_rx_margin (MSB) + write_cmos_sensor(0x3006,0x10); // ct_rx_margin (LSB) + write_cmos_sensor(0x3007,0x03); // ct_tx_start + write_cmos_sensor(0x3008,0x55); // ct_tx_width + write_cmos_sensor(0x3039,0x00); // cintc1_margin (10 --> 00) + write_cmos_sensor(0x303A,0x00); // cintc2_margin (10 --> 00) + write_cmos_sensor(0x303B,0x00); // offs_sh + write_cmos_sensor(0x3009,0x05); // ct_srx_margin + write_cmos_sensor(0x300A,0x55); // ct_stx_width + write_cmos_sensor(0x300B,0x38); // ct_dstx_width + write_cmos_sensor(0x300C,0x10); // ct_stx2dstx + write_cmos_sensor(0x3012,0x05); // ct_cds_start + write_cmos_sensor(0x3013,0x00); // ct_s1s_start + write_cmos_sensor(0x3014,0x22); // ct_s1s_end + write_cmos_sensor(0x300E,0x79); // ct_s3_width + write_cmos_sensor(0x3010,0x68); // ct_s4_width + write_cmos_sensor(0x3019,0x03); // ct_s4d_start + write_cmos_sensor(0x301A,0x00); // ct_pbr_start + write_cmos_sensor(0x301B,0x06); // ct_pbr_width + write_cmos_sensor(0x301C,0x00); // ct_pbs_start + write_cmos_sensor(0x301D,0x22); // ct_pbs_width + write_cmos_sensor(0x301E,0x00); // ct_pbr_ob_start + write_cmos_sensor(0x301F,0x10); // ct_pbr_ob_width + write_cmos_sensor(0x3020,0x00); // ct_pbs_ob_start + write_cmos_sensor(0x3021,0x00); // ct_pbs_ob_width + write_cmos_sensor(0x3022,0x0A); // ct_cds_lim_start + write_cmos_sensor(0x3023,0x1E); // ct_crs_start + write_cmos_sensor(0x3024,0x00); // ct_lp_hblk_cds_start (MSB) + write_cmos_sensor(0x3025,0x00); // ct_lp_hblk_cds_start (LSB) + write_cmos_sensor(0x3026,0x00); // ct_lp_hblk_cds_end (MSB) + write_cmos_sensor(0x3027,0x00); // ct_lp_hblk_cds_end (LSB) + write_cmos_sensor(0x3028,0x1A); // ct_rmp_off_start + write_cmos_sensor(0x3015,0x00); // ct_rmp_rst_start (MSB) + write_cmos_sensor(0x3016,0x84); // ct_rmp_rst_start (LSB) + write_cmos_sensor(0x3017,0x00); // ct_rmp_sig_start (MSB) + write_cmos_sensor(0x3018,0xA0); // ct_rmp_sig_start (LSB) + write_cmos_sensor(0x302B,0x10); // ct_cnt_margin + write_cmos_sensor(0x302C,0x0A); // ct_rmp_per + write_cmos_sensor(0x302D,0x06); // ct_cnt_ms_margin1 + write_cmos_sensor(0x302E,0x05); // ct_cnt_ms_margin2 + write_cmos_sensor(0x302F,0x0E); // rst_mx + write_cmos_sensor(0x3030,0x2F); // sig_mx + write_cmos_sensor(0x3031,0x08); // ct_latch_start + write_cmos_sensor(0x3032,0x05); // ct_latch_width + write_cmos_sensor(0x3033,0x09); // ct_hold_start + write_cmos_sensor(0x3034,0x05); // ct_hold_width + write_cmos_sensor(0x3035,0x00); // ct_lp_hblk_dbs_start (MSB) + write_cmos_sensor(0x3036,0x00); // ct_lp_hblk_dbs_start (LSB) + write_cmos_sensor(0x3037,0x00); // ct_lp_hblk_dbs_end (MSB) + write_cmos_sensor(0x3038,0x00); // ct_lp_hblk_dbs_end (LSB) + write_cmos_sensor(0x3088,0x06); // ct_lat_lsb_offset_start1 + write_cmos_sensor(0x308A,0x08); // ct_lat_lsb_offset_end1 + write_cmos_sensor(0x308C,0x05); // ct_lat_lsb_offset_start2 + write_cmos_sensor(0x308E,0x07); // ct_lat_lsb_offset_end2 + write_cmos_sensor(0x3090,0x06); // ct_conv_en_offset_start1 + write_cmos_sensor(0x3092,0x08); // ct_conv_en_offset_end1 + write_cmos_sensor(0x3094,0x05); // ct_conv_en_offset_start2 + write_cmos_sensor(0x3096,0x21); // ct_conv_en_offset_end2 + write_cmos_sensor(0x3099,0x0E); // cds_option ([3]:crs switch disable, s3,s4 streng + write_cmos_sensor(0x3070,0x10); // comp1_bias (default:77) + write_cmos_sensor(0x3085,0x11); // comp1_bias (gain1~4) + write_cmos_sensor(0x3086,0x01); // comp1_bias (gain4~8) modified 813 + + write_cmos_sensor(0x3064,0x00); // Multiple sampling(gainx8,x16) + write_cmos_sensor(0x3062,0x08); // off_rst + write_cmos_sensor(0x3061,0x11); // dbr_tune_rd (default :08) + write_cmos_sensor(0x307B,0x20); // dbr_tune_rgsl (default :08) + write_cmos_sensor(0x3068,0x00); // RMP BP bias sampling + write_cmos_sensor(0x3074,0x00); // Pixel bias sampling [2]:Default L + write_cmos_sensor(0x307D,0x00); // VREF sampling [1] + write_cmos_sensor(0x3045,0x01); // ct_opt_l1_start + write_cmos_sensor(0x3046,0x05); // ct_opt_l1_width + write_cmos_sensor(0x3047,0x78); + write_cmos_sensor(0x307F,0xB1); // RDV_OPTION[5:4], RG default high + write_cmos_sensor(0x3098,0x01); // CDS_OPTION[16] SPLA-II enable + write_cmos_sensor(0x305C,0xF6); // lob_extension[6] + write_cmos_sensor(0x306B,0x10); + write_cmos_sensor(0x3063,0x27); // ADC_SAT 490mV --> 610mV + write_cmos_sensor(0x3400,0x01); // GAS bypass + write_cmos_sensor(0x3235,0x49); // L/F-ADLC on + write_cmos_sensor(0x3233,0x00); // D-pedestal L/F ADLC off (1FC0h) + write_cmos_sensor(0x3234,0x00); + write_cmos_sensor(0x3300,0x0C); // BPC bypass + + write_cmos_sensor(0x3203,0x45); // ADC_OFFSET_EVEN + write_cmos_sensor(0x3205,0x4D); // ADC_OFFSET_ODD + write_cmos_sensor(0x320B,0x40); // ADC_DEFAULT + write_cmos_sensor(0x320C,0x06); // ADC_MAX + write_cmos_sensor(0x320D,0xC0); + + write_cmos_sensor(0x3929,0x07); //set mipi non-continue mode + + // streaming ON + write_cmos_sensor(0x0100,0x01); +} /* sensor_init */ + + +static void preview_setting(void) +{ + // +++++++++++++++++++++++++++// + // Reset for operation + write_cmos_sensor(0x0100,0x00); //stream off + + // Clock Setting + write_cmos_sensor(0x0305,0x06); //PLLP (def:5) + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xE0); //PLLM (def:CCh 204d --> B3h 179d) + write_cmos_sensor(0x3C1F,0x00); //PLLS + + write_cmos_sensor(0x0820,0x03); // requested link bit rate mbps : (def:3D3h 979d --> 35Bh 859d) + write_cmos_sensor(0x0821,0x80); + write_cmos_sensor(0x3C1C,0x58); //dbr_div + + write_cmos_sensor(0x0114,0x01); //Lane mode + + // Size Setting + write_cmos_sensor(0x0340,0x07); // frame_length_lines : def. 990d (--> 3C8 Mimnimum 22 lines) + write_cmos_sensor(0x0341,0xD0); + write_cmos_sensor(0x0342,0x0B); // line_length_pck : def. 2900d + write_cmos_sensor(0x0343,0x86); + + write_cmos_sensor(0x0344,0x00); // x_addr_start + write_cmos_sensor(0x0345,0x08); + write_cmos_sensor(0x0346,0x00); // y_addr_start + write_cmos_sensor(0x0347,0x08); + write_cmos_sensor(0x0348,0x0A); // x_addr_end : def. 2575d + write_cmos_sensor(0x0349,0x07); + write_cmos_sensor(0x034A,0x07); // y_addr_end : def. 1936d + write_cmos_sensor(0x034B,0x87); + write_cmos_sensor(0x034C,0x05); // x_output size : def. 1288d + write_cmos_sensor(0x034D,0x00); + write_cmos_sensor(0x034E,0x03); // y_output size : def. 968d + write_cmos_sensor(0x034F,0xC0); + + + //Digital Binning + write_cmos_sensor(0x0900,0x01); //2x2 Binning + write_cmos_sensor(0x0901,0x22); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0387,0x03); + + //Integration time + write_cmos_sensor(0x0202,0x02); // coarse integration + write_cmos_sensor(0x0203,0x00); + write_cmos_sensor(0x0200,0x04); // fine integration (AA8h --> AC4h) + write_cmos_sensor(0x0201,0x98); + + write_cmos_sensor(0x3407,0x00); + write_cmos_sensor(0x3408,0x00); + write_cmos_sensor(0x3409,0x00); + write_cmos_sensor(0x340A,0x00); + write_cmos_sensor(0x340B,0x00); + write_cmos_sensor(0x340C,0x00); + write_cmos_sensor(0x340D,0x00); + write_cmos_sensor(0x340E,0x00); + write_cmos_sensor(0x3401,0x50); + write_cmos_sensor(0x3402,0x3C); + write_cmos_sensor(0x3403,0x03); + write_cmos_sensor(0x3404,0x33); + write_cmos_sensor(0x3405,0x04); + write_cmos_sensor(0x3406,0x44); + write_cmos_sensor(0x3458,0x03); + write_cmos_sensor(0x3459,0x33); + write_cmos_sensor(0x345A,0x04); + write_cmos_sensor(0x345B,0x44); + write_cmos_sensor(0x3400,0x01); + + // streaming ON + write_cmos_sensor(0x0100,0x01); +} /* preview_setting */ + +static void capture_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + if (currefps == 150) { //15fps for PIP + // +++++++++++++++++++++++++++// + // Reset for operation + write_cmos_sensor(0x0100,0x00); //stream off + + + // Clock Setting + write_cmos_sensor(0x0305,0x06); //PLLP (def:5) + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xDA); //PLLM (def:CCh 204d --> B3h 179d) + write_cmos_sensor(0x3C1F,0x01); //PLLS + + //S30CCC0 //dphy_band_ctrl + + write_cmos_sensor(0x0820,0x01); // requested link bit rate mbps : (def:3D3h 979d --> 35Bh 859d) + write_cmos_sensor(0x0821,0xB4); + write_cmos_sensor(0x3C1C,0x54); //dbr_div + + write_cmos_sensor(0x0114,0x01); //Lane mode + + // Size Setting + write_cmos_sensor(0x0340,0x07); // frame_length_lines : def. 1962d (7C2 --> 7A6 Mimnimum 22 lines) + write_cmos_sensor(0x0341,0xE9); + write_cmos_sensor(0x0342,0x0B); // line_length_pck : def. 2900d + write_cmos_sensor(0x0343,0x86); + + write_cmos_sensor(0x0344,0x00); // x_addr_start + write_cmos_sensor(0x0345,0x08); + write_cmos_sensor(0x0346,0x00); // y_addr_start + write_cmos_sensor(0x0347,0x08); + write_cmos_sensor(0x0348,0x0A); // x_addr_end : def. 2575d + write_cmos_sensor(0x0349,0x07); + write_cmos_sensor(0x034A,0x07); // y_addr_end : def. 1936d + write_cmos_sensor(0x034B,0x87); + write_cmos_sensor(0x034C,0x0A); // x_output size : def. 2560d + write_cmos_sensor(0x034D,0x00); + write_cmos_sensor(0x034E,0x07); // y_output size : def. 1920d + write_cmos_sensor(0x034F,0x80); + + //Digital Binning(default) + write_cmos_sensor(0x0900,0x00); //0x0 Binning + write_cmos_sensor(0x0901,0x20); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0387,0x01); + + + //Integration time + write_cmos_sensor(0x0202,0x02); // coarse integration + write_cmos_sensor(0x0203,0x00); + write_cmos_sensor(0x0200,0x04); // fine integration (AA8h --> AC4h) + write_cmos_sensor(0x0201,0x98); + + write_cmos_sensor(0x3407,0x00); + write_cmos_sensor(0x3408,0x00); + write_cmos_sensor(0x3409,0x00); + write_cmos_sensor(0x340A,0x00); + write_cmos_sensor(0x340B,0x00); + write_cmos_sensor(0x340C,0x00); + write_cmos_sensor(0x340D,0x00); + write_cmos_sensor(0x340E,0x00); + write_cmos_sensor(0x3401,0x50); + write_cmos_sensor(0x3402,0x3C); + write_cmos_sensor(0x3403,0x03); + write_cmos_sensor(0x3404,0x33); + write_cmos_sensor(0x3405,0x04); + write_cmos_sensor(0x3406,0x44); + write_cmos_sensor(0x3458,0x03); + write_cmos_sensor(0x3459,0x33); + write_cmos_sensor(0x345A,0x04); + write_cmos_sensor(0x345B,0x44); + write_cmos_sensor(0x3400,0x01); + + // streaming ON + write_cmos_sensor(0x0100,0x01); + } + else{// Reset for operation 30fps for normal capture + write_cmos_sensor(0x0100,0x00); //stream off + mdelay(40); + + // Clock Setting + write_cmos_sensor(0x0305,0x06); //PLLP (def:5) + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xE0); //PLLM (def:CCh 204d --> B3h 179d) + write_cmos_sensor(0x3C1F,0x00); //PLLS + + //S3CC0 //dphy_band_ctrl + + write_cmos_sensor(0x0820,0x03); // requested link bit rate mbps : (def:3D3h 979d --> 35Bh 859d) + write_cmos_sensor(0x0821,0x80); + write_cmos_sensor(0x3C1C,0x58); //dbr_div + + write_cmos_sensor(0x0114,0x01); //Lane mode + + // Size Setting + write_cmos_sensor(0x0340,0x07); // frame_length_lines : def. 1962d (7C2 --> 7A6 Mimnimum 22 lines) + write_cmos_sensor(0x0341,0xE9); + write_cmos_sensor(0x0342,0x0B); // line_length_pck : def. 2900d + write_cmos_sensor(0x0343,0x86); + + write_cmos_sensor(0x0344,0x00); // x_addr_start + write_cmos_sensor(0x0345,0x08); + write_cmos_sensor(0x0346,0x00); // y_addr_start + write_cmos_sensor(0x0347,0x08); + write_cmos_sensor(0x0348,0x0A); // x_addr_end : def. 2575d + write_cmos_sensor(0x0349,0x07); + write_cmos_sensor(0x034A,0x07); // y_addr_end : def. 1936d + write_cmos_sensor(0x034B,0x87); + write_cmos_sensor(0x034C,0x0A); // x_output size : def. 2560d + write_cmos_sensor(0x034D,0x00); + write_cmos_sensor(0x034E,0x07); // y_output size : def. 1920d + write_cmos_sensor(0x034F,0x80); + + //Digital Binning(default) + write_cmos_sensor(0x0900,0x00); //0x0 Binning + write_cmos_sensor(0x0901,0x20); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0387,0x01); + + + //Integration time + write_cmos_sensor(0x0202,0x02); // coarse integration + write_cmos_sensor(0x0203,0x00); + write_cmos_sensor(0x0200,0x04); // fine integration (AA8h --> AC4h) + write_cmos_sensor(0x0201,0x98); + + write_cmos_sensor(0x3407,0x00); + write_cmos_sensor(0x3408,0x00); + write_cmos_sensor(0x3409,0x00); + write_cmos_sensor(0x340A,0x00); + write_cmos_sensor(0x340B,0x00); + write_cmos_sensor(0x340C,0x00); + write_cmos_sensor(0x340D,0x00); + write_cmos_sensor(0x340E,0x00); + write_cmos_sensor(0x3401,0x50); + write_cmos_sensor(0x3402,0x3C); + write_cmos_sensor(0x3403,0x03); + write_cmos_sensor(0x3404,0x33); + write_cmos_sensor(0x3405,0x04); + write_cmos_sensor(0x3406,0x44); + write_cmos_sensor(0x3458,0x03); + write_cmos_sensor(0x3459,0x33); + write_cmos_sensor(0x345A,0x04); + write_cmos_sensor(0x345B,0x44); + write_cmos_sensor(0x3400,0x01); + + // streaming ON + write_cmos_sensor(0x0100,0x01); + } +} + +static void normal_video_setting(kal_uint16 currefps) +{ + LOG_INF("E! currefps:%d\n",currefps); + + //5.1.3 Video 2592x1944 30fps 24M MCLK 2lane 864Mbps/lane + // +++++++++++++++++++++++++++// +// Reset for operation + write_cmos_sensor(0x0100,0x00); //stream off + + + // Clock Setting + write_cmos_sensor(0x0305,0x06); //PLLP (def:5) + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xE0); //PLLM (def:CCh 204d --> B3h 179d) + write_cmos_sensor(0x3C1F,0x00); //PLLS + + //S30C0 //dphy_band_ctrl + + write_cmos_sensor(0x0820,0x03); // requested link bit rate mbps : (def:3D3h 979d --> 35Bh 859d) + write_cmos_sensor(0x0821,0x80); + write_cmos_sensor(0x3C1C,0x58); //dbr_div + + write_cmos_sensor(0x0114,0x01); //Lane mode + + // Size Setting + write_cmos_sensor(0x0340,0x07); // frame_length_lines : def. 1962d (7C2 --> 7A6 Mimnimum 22 lines) + write_cmos_sensor(0x0341,0xD0); + write_cmos_sensor(0x0342,0x0B); // line_length_pck : def. 2900d + write_cmos_sensor(0x0343,0x86); + + write_cmos_sensor(0x0344,0x00); // x_addr_start + write_cmos_sensor(0x0345,0x08); + write_cmos_sensor(0x0346,0x00); // y_addr_start + write_cmos_sensor(0x0347,0xF8); + write_cmos_sensor(0x0348,0x0A); // x_addr_end : def. 2575d + write_cmos_sensor(0x0349,0x07); + write_cmos_sensor(0x034A,0x06); // y_addr_end : def. 1936d + write_cmos_sensor(0x034B,0x97); + write_cmos_sensor(0x034C,0x0A); // x_output size : def. 2560d + write_cmos_sensor(0x034D,0x00); + write_cmos_sensor(0x034E,0x05); // y_output size : def. 1920d + write_cmos_sensor(0x034F,0xA0); + + //Digital Binning(default) + write_cmos_sensor(0x0900,0x00); //0x0 Binning + write_cmos_sensor(0x0901,0x20); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0387,0x01); + + + //Integration time + write_cmos_sensor(0x0202,0x02); // coarse integration + write_cmos_sensor(0x0203,0x00); + write_cmos_sensor(0x0200,0x04); // fine integration (AA8h --> AC4h) + write_cmos_sensor(0x0201,0x98); + + write_cmos_sensor(0x3407,0x00); + write_cmos_sensor(0x3408,0x00); + write_cmos_sensor(0x3409,0x00); + write_cmos_sensor(0x340A,0x00); + write_cmos_sensor(0x340B,0x27); + write_cmos_sensor(0x340C,0x01); + write_cmos_sensor(0x340D,0xA3); + write_cmos_sensor(0x340E,0x9E); + write_cmos_sensor(0x3401,0x50); + write_cmos_sensor(0x3402,0x3C); + write_cmos_sensor(0x3403,0x03); + write_cmos_sensor(0x3404,0x33); + write_cmos_sensor(0x3405,0x04); + write_cmos_sensor(0x3406,0x44); + write_cmos_sensor(0x3458,0x03); + write_cmos_sensor(0x3459,0x33); + write_cmos_sensor(0x345A,0x04); + write_cmos_sensor(0x345B,0x44); + write_cmos_sensor(0x3400,0x01); + + // streaming ON + write_cmos_sensor(0x0100,0x01); + +} +static void hs_video_setting(void) +{ + LOG_INF("E\n"); + //VGA 120fps + + write_cmos_sensor(0x0100,0x00); //stream off + write_cmos_sensor(0x0136,0x18); + write_cmos_sensor(0x0137,0x00); + // Clock Setting + write_cmos_sensor(0x0305,0x06); //PLLP (def:5) + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xE0); //PLLM (def:CCh 204d --> B3h 179d) + write_cmos_sensor(0x3C1F,0x00); //PLLS + + //S30CCC0 //dphy_band_ctrl + + write_cmos_sensor(0x0820,0x03); // requested link bit rate mbps : (def:3D3h 979d --> 35Bh 859d) + write_cmos_sensor(0x0821,0x80); + write_cmos_sensor(0x3C1C,0x58); //dbr_div + + write_cmos_sensor(0x0114,0x01); //Lane mode + + // Size Setting + write_cmos_sensor(0x0340,0x01); // frame_length_lines : def. 1962d (7C2 --> 7A6 Mimnimum 22 lines) + write_cmos_sensor(0x0341,0xFA); + write_cmos_sensor(0x0342,0x0B); // line_length_pck : def. 2900d + write_cmos_sensor(0x0343,0x86); + + write_cmos_sensor(0x0344,0x00); // x_addr_start + write_cmos_sensor(0x0345,0x08); + write_cmos_sensor(0x0346,0x00); // y_addr_start + write_cmos_sensor(0x0347,0x08); + write_cmos_sensor(0x0348,0x0A); // x_addr_end : def. + write_cmos_sensor(0x0349,0x07); + write_cmos_sensor(0x034A,0x07); // y_addr_end : def. + write_cmos_sensor(0x034B,0x87); + write_cmos_sensor(0x034C,0x02); // x_output size : def. 640d + write_cmos_sensor(0x034D,0x80); + write_cmos_sensor(0x034E,0x01); // y_output size : def. 480d + write_cmos_sensor(0x034F,0xE0); + + //Digital Binning(default) + write_cmos_sensor(0x0900,0x01); //0x0 Binning + write_cmos_sensor(0x0901,0x44); + write_cmos_sensor(0x0383,0x03); + write_cmos_sensor(0x0387,0x07); + + + //Integration time + write_cmos_sensor(0x0204,0x00); + write_cmos_sensor(0x0205,0x20); + write_cmos_sensor(0x0202,0x01); // coarse integration + write_cmos_sensor(0x0203,0x00); + write_cmos_sensor(0x0200,0x04); // fine integration (AA8h --> AC4h) + write_cmos_sensor(0x0201,0x98); + + write_cmos_sensor(0x3407,0x00); + write_cmos_sensor(0x3408,0x00); + write_cmos_sensor(0x3409,0x00); + write_cmos_sensor(0x340A,0x00); + write_cmos_sensor(0x340B,0x00); + write_cmos_sensor(0x340C,0x00); + write_cmos_sensor(0x340D,0x00); + write_cmos_sensor(0x340E,0x00); + write_cmos_sensor(0x3401,0x50); + write_cmos_sensor(0x3402,0x3C); + write_cmos_sensor(0x3403,0x03); + write_cmos_sensor(0x3404,0x33); + write_cmos_sensor(0x3405,0x04); + write_cmos_sensor(0x3406,0x44); + write_cmos_sensor(0x3458,0x03); + write_cmos_sensor(0x3459,0x33); + write_cmos_sensor(0x345A,0x04); + write_cmos_sensor(0x345B,0x44); + write_cmos_sensor(0x3400,0x00); + + // streaming ON + write_cmos_sensor(0x0100,0x01); + + + + //full size 60fps +/* + // +++++++++++++++++++++++++++// + // Reset for operation + write_cmos_sensor(0x0100,0x00); //stream off + + // Clock Setting + write_cmos_sensor(0x0305,0x05); //PLLP (def:5) + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xCA); //PLLM (def:CCh 204d --> B3h 179d) + write_cmos_sensor(0x3C1F,0x00); //PLLS + + //S30CCC0 //dphy_band_ctrl + + write_cmos_sensor(0x0820,0x03); // requested link bit rate mbps : (def:3D3h 979d --> 35Bh 859d) + write_cmos_sensor(0x0821,0xC9); + write_cmos_sensor(0x3C1C,0x59); //dbr_div + + write_cmos_sensor(0x0114,0x01); //Lane mode + + // Size Setting + write_cmos_sensor(0x0340,0x04); // frame_length_lines : def. 1962d (7C2 --> 7A6 Mimnimum 22 lines) + write_cmos_sensor(0x0341,0x4F); + write_cmos_sensor(0x0342,0x0B); // line_length_pck : def. 2900d + write_cmos_sensor(0x0343,0x86); + + write_cmos_sensor(0x0344,0x01); // x_addr_start + write_cmos_sensor(0x0345,0x40); + write_cmos_sensor(0x0346,0x01); // y_addr_start + write_cmos_sensor(0x0347,0xA4); + write_cmos_sensor(0x0348,0x08); // x_addr_end : def. 2575d + write_cmos_sensor(0x0349,0xBF); + write_cmos_sensor(0x034A,0x05); // y_addr_end : def. 1936d + write_cmos_sensor(0x034B,0xDB); + write_cmos_sensor(0x034C,0x07); // x_output size : def. 2560d + write_cmos_sensor(0x034D,0x80); + write_cmos_sensor(0x034E,0x04); // y_output size : def. 1920d + write_cmos_sensor(0x034F,0x38); + + //Digital Binning(default) + write_cmos_sensor(0x0900,0x00); //0x0 Binning + write_cmos_sensor(0x0901,0x20); + write_cmos_sensor(0x0387,0x01); + + + //Integration time + write_cmos_sensor(0x0202,0x02); // coarse integration + write_cmos_sensor(0x0203,0x00); + write_cmos_sensor(0x0200,0x04); // fine integration (AA8h --> AC4h) + write_cmos_sensor(0x0201,0x98); + + write_cmos_sensor(0x3407,0x4C); + write_cmos_sensor(0x3408,0x01); + write_cmos_sensor(0x3409,0xF3); + write_cmos_sensor(0x340A,0x24); + write_cmos_sensor(0x340B,0x1A); + write_cmos_sensor(0x340C,0x03); + write_cmos_sensor(0x340D,0x6E); + write_cmos_sensor(0x340E,0xE8); + write_cmos_sensor(0x3401,0x50); + write_cmos_sensor(0x3402,0x3C); + write_cmos_sensor(0x3403,0x03); + write_cmos_sensor(0x3404,0x33); + write_cmos_sensor(0x3405,0x04); + write_cmos_sensor(0x3406,0x44); + write_cmos_sensor(0x3458,0x03); + write_cmos_sensor(0x3459,0x33); + write_cmos_sensor(0x345A,0x04); + write_cmos_sensor(0x345B,0x44); + write_cmos_sensor(0x3400,0x01); + + // streaming ON + write_cmos_sensor(0x0100,0x01); +*/ +} + +static void slim_video_setting(void) +{ + LOG_INF("E\n"); + // +++++++++++++++++++++++++++// +// Reset for operation + write_cmos_sensor(0x0100,0x00); //stream off + + // Clock Setting + write_cmos_sensor(0x0305,0x06); //PLLP (def:5) + write_cmos_sensor(0x0306,0x00); + write_cmos_sensor(0x0307,0xE0); //PLLM (def:CCh 204d --> B3h 179d) + write_cmos_sensor(0x3C1F,0x00); //PLLS + + //S30CCC0 //dphy_band_ctrl + + write_cmos_sensor(0x0820,0x03); // requested link bit rate mbps : (def:3D3h 979d --> 35Bh 859d) + write_cmos_sensor(0x0821,0x80); + write_cmos_sensor(0x3C1C,0x58); //dbr_div + + write_cmos_sensor(0x0114,0x01); //Lane mode + + // Size Setting + write_cmos_sensor(0x0340,0x07); // frame_length_lines : def. 1962d (7C2 --> 7A6 Mimnimum 22 lines) + write_cmos_sensor(0x0341,0xD0); + write_cmos_sensor(0x0342,0x0B); // line_length_pck : def. 2900d + write_cmos_sensor(0x0343,0x86); + + write_cmos_sensor(0x0344,0x00); // x_addr_start + write_cmos_sensor(0x0345,0x08); + write_cmos_sensor(0x0346,0x00); // y_addr_start + write_cmos_sensor(0x0347,0xF8); + write_cmos_sensor(0x0348,0x0A); // x_addr_end : def. 2575d + write_cmos_sensor(0x0349,0x07); + write_cmos_sensor(0x034A,0x06); // y_addr_end : def. 1936d + write_cmos_sensor(0x034B,0x97); + write_cmos_sensor(0x034C,0x05); // x_output size : def. 2560d + write_cmos_sensor(0x034D,0x00); + write_cmos_sensor(0x034E,0x02); // y_output size : def. 1920d + write_cmos_sensor(0x034F,0xD0); + + //Digital Binning(default) + write_cmos_sensor(0x0900,0x01); //2x2 Binning + write_cmos_sensor(0x0901,0x22); + write_cmos_sensor(0x0383,0x01); + write_cmos_sensor(0x0387,0x03); + + + //Integration time + write_cmos_sensor(0x0202,0x02); // coarse integration + write_cmos_sensor(0x0203,0x00); + write_cmos_sensor(0x0200,0x04); // fine integration (AA8h --> AC4h) + write_cmos_sensor(0x0201,0x98); + + write_cmos_sensor(0x3407,0x00); + write_cmos_sensor(0x3408,0x00); + write_cmos_sensor(0x3409,0x00); + write_cmos_sensor(0x340A,0x00); + write_cmos_sensor(0x340B,0x00); + write_cmos_sensor(0x340C,0x02); + write_cmos_sensor(0x340D,0x00); + write_cmos_sensor(0x340E,0x00); + write_cmos_sensor(0x3401,0x50); + write_cmos_sensor(0x3402,0x3C); + write_cmos_sensor(0x3403,0x03); + write_cmos_sensor(0x3404,0x33); + write_cmos_sensor(0x3405,0x04); + write_cmos_sensor(0x3406,0x44); + write_cmos_sensor(0x3458,0x03); + write_cmos_sensor(0x3459,0x33); + write_cmos_sensor(0x345A,0x04); + write_cmos_sensor(0x345B,0x44); + write_cmos_sensor(0x3400,0x01); + + // streaming ON + write_cmos_sensor(0x0100,0x01); + +} + + +/************************************************************************* +* FUNCTION +* get_imgsensor_id +* +* DESCRIPTION +* This function get the sensor ID +* +* PARAMETERS +* *sensorID : return the sensor ID +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 get_imgsensor_id(UINT32 *sensor_id) +{ + kal_uint8 i = 0; + kal_uint8 retry = 2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + *sensor_id = return_sensor_id(); + if (*sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + return ERROR_NONE; + } + LOG_INF("Read sensor id fail,i2c_write_id 0x%x id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id); + retry--; + } while(retry > 0); + i++; + retry = 2; + } + if (*sensor_id != imgsensor_info.sensor_id) { + // if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF + *sensor_id = 0xFFFFFFFF; + return ERROR_SENSOR_CONNECT_FAIL; + } + return ERROR_NONE; +} + + +/************************************************************************* +* FUNCTION +* open +* +* DESCRIPTION +* This function initialize the registers of CMOS sensor +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 open(void) +{ + //const kal_uint8 i2c_addr[] = {IMGSENSOR_WRITE_ID_1, IMGSENSOR_WRITE_ID_2}; + kal_uint8 i = 0; + kal_uint8 retry = 2; + kal_uint32 sensor_id = 0; + LOG_1; + LOG_2; + //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address + while (imgsensor_info.i2c_addr_table[i] != 0xff) { + spin_lock(&imgsensor_drv_lock); + imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; + spin_unlock(&imgsensor_drv_lock); + do { + sensor_id = return_sensor_id(); + if (sensor_id == imgsensor_info.sensor_id) { + LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + break; + } + LOG_INF("Read sensor id fail,i2c_write_id 0x%x id: 0x%x\n", imgsensor.i2c_write_id,sensor_id); + retry--; + } while(retry > 0); + i++; + if (sensor_id == imgsensor_info.sensor_id) + break; + retry = 2; + } + if (imgsensor_info.sensor_id != sensor_id) + return ERROR_SENSOR_CONNECT_FAIL; + + /* initail sequence write in */ + sensor_init(); + + spin_lock(&imgsensor_drv_lock); + + imgsensor.autoflicker_en= KAL_FALSE; + imgsensor.sensor_mode = IMGSENSOR_MODE_INIT; + imgsensor.shutter = 0x3D0; + imgsensor.gain = 0x100; + imgsensor.pclk = imgsensor_info.pre.pclk; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.dummy_pixel = 0; + imgsensor.dummy_line = 0; + imgsensor.ihdr_en = 0; + imgsensor.test_pattern = KAL_FALSE; + imgsensor.current_fps = imgsensor_info.pre.max_framerate; + spin_unlock(&imgsensor_drv_lock); + + return ERROR_NONE; +} /* open */ + + + +/************************************************************************* +* FUNCTION +* close +* +* DESCRIPTION +* +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 close(void) +{ + LOG_INF("E\n"); + + /*No Need to implement this function*/ + + return ERROR_NONE; +} /* close */ + + +/************************************************************************* +* FUNCTION +* preview +* +* DESCRIPTION +* This function start the sensor preview. +* +* PARAMETERS +* *image_window : address pointer of pixel numbers in one period of HSYNC +* *sensor_config_data : address pointer of line numbers in one period of VSYNC +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW; + imgsensor.pclk = imgsensor_info.pre.pclk; + //imgsensor.video_mode = KAL_FALSE; + imgsensor.line_length = imgsensor_info.pre.linelength; + imgsensor.frame_length = imgsensor_info.pre.framelength; + imgsensor.min_frame_length = imgsensor_info.pre.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + preview_setting(); + return ERROR_NONE; +} /* preview */ + +/************************************************************************* +* FUNCTION +* capture +* +* DESCRIPTION +* This function setup the CMOS sensor in capture MY_OUTPUT mode +* +* PARAMETERS +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +static kal_uint32 capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_CAPTURE; + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) {//PIP capture: 24fps for less than 13M, 20fps for 16M,15fps for 20M + imgsensor.pclk = imgsensor_info.cap1.pclk; + imgsensor.line_length = imgsensor_info.cap1.linelength; + imgsensor.frame_length = imgsensor_info.cap1.framelength; + imgsensor.min_frame_length = imgsensor_info.cap1.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap1's setting: %d fps!\n",imgsensor.current_fps,imgsensor_info.cap1.max_framerate/10); + imgsensor.pclk = imgsensor_info.cap.pclk; + imgsensor.line_length = imgsensor_info.cap.linelength; + imgsensor.frame_length = imgsensor_info.cap.framelength; + imgsensor.min_frame_length = imgsensor_info.cap.framelength; + imgsensor.autoflicker_en = KAL_FALSE; + } + spin_unlock(&imgsensor_drv_lock); + + capture_setting(imgsensor.current_fps); + + + return ERROR_NONE; +} /* capture() */ +static kal_uint32 normal_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_VIDEO; + imgsensor.pclk = imgsensor_info.normal_video.pclk; + imgsensor.line_length = imgsensor_info.normal_video.linelength; + imgsensor.frame_length = imgsensor_info.normal_video.framelength; + imgsensor.min_frame_length = imgsensor_info.normal_video.framelength; + //imgsensor.current_fps = 300; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + normal_video_setting(imgsensor.current_fps); + + + return ERROR_NONE; +} /* normal_video */ + +static kal_uint32 hs_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_HIGH_SPEED_VIDEO; + imgsensor.pclk = imgsensor_info.hs_video.pclk; + //imgsensor.video_mode = KAL_TRUE; + imgsensor.line_length = imgsensor_info.hs_video.linelength; + imgsensor.frame_length = imgsensor_info.hs_video.framelength; + imgsensor.min_frame_length = imgsensor_info.hs_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + hs_video_setting(); + + return ERROR_NONE; +} /* hs_video */ + +static kal_uint32 slim_video(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("E\n"); + + spin_lock(&imgsensor_drv_lock); + imgsensor.sensor_mode = IMGSENSOR_MODE_SLIM_VIDEO; + imgsensor.pclk = imgsensor_info.slim_video.pclk; + imgsensor.line_length = imgsensor_info.slim_video.linelength; + imgsensor.frame_length = imgsensor_info.slim_video.framelength; + imgsensor.min_frame_length = imgsensor_info.slim_video.framelength; + imgsensor.dummy_line = 0; + imgsensor.dummy_pixel = 0; + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + slim_video_setting(); + + return ERROR_NONE; +} /* slim_video */ + + + +static kal_uint32 get_resolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) +{ + LOG_INF("E\n"); + sensor_resolution->SensorFullWidth = imgsensor_info.cap.grabwindow_width; + sensor_resolution->SensorFullHeight = imgsensor_info.cap.grabwindow_height; + + sensor_resolution->SensorPreviewWidth = imgsensor_info.pre.grabwindow_width; + sensor_resolution->SensorPreviewHeight = imgsensor_info.pre.grabwindow_height; + + sensor_resolution->SensorVideoWidth = imgsensor_info.normal_video.grabwindow_width; + sensor_resolution->SensorVideoHeight = imgsensor_info.normal_video.grabwindow_height; + + + sensor_resolution->SensorHighSpeedVideoWidth = imgsensor_info.hs_video.grabwindow_width; + sensor_resolution->SensorHighSpeedVideoHeight = imgsensor_info.hs_video.grabwindow_height; + + sensor_resolution->SensorSlimVideoWidth = imgsensor_info.slim_video.grabwindow_width; + sensor_resolution->SensorSlimVideoHeight = imgsensor_info.slim_video.grabwindow_height; + return ERROR_NONE; +} /* get_resolution */ + +static kal_uint32 get_info(MSDK_SCENARIO_ID_ENUM scenario_id, + MSDK_SENSOR_INFO_STRUCT *sensor_info, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + + //sensor_info->SensorVideoFrameRate = imgsensor_info.normal_video.max_framerate/10; /* not use */ + //sensor_info->SensorStillCaptureFrameRate= imgsensor_info.cap.max_framerate/10; /* not use */ + //imgsensor_info->SensorWebCamCaptureFrameRate= imgsensor_info.v.max_framerate; /* not use */ + + sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; /* not use */ + sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; // inverse with datasheet + sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + sensor_info->SensorInterruptDelayLines = 4; /* not use */ + sensor_info->SensorResetActiveHigh = FALSE; /* not use */ + sensor_info->SensorResetDelayCount = 5; /* not use */ + + sensor_info->SensroInterfaceType = imgsensor_info.sensor_interface_type; + sensor_info->MIPIsensorType = imgsensor_info.mipi_sensor_type; + sensor_info->SettleDelayMode = imgsensor_info.mipi_settle_delay_mode; + sensor_info->SensorOutputDataFormat = imgsensor_info.sensor_output_dataformat; + + sensor_info->CaptureDelayFrame = imgsensor_info.cap_delay_frame; + sensor_info->PreviewDelayFrame = imgsensor_info.pre_delay_frame; + sensor_info->VideoDelayFrame = imgsensor_info.video_delay_frame; + sensor_info->HighSpeedVideoDelayFrame = imgsensor_info.hs_video_delay_frame; + sensor_info->SlimVideoDelayFrame = imgsensor_info.slim_video_delay_frame; + + sensor_info->SensorMasterClockSwitch = 0; /* not use */ + sensor_info->SensorDrivingCurrent = imgsensor_info.isp_driving_current; + + sensor_info->AEShutDelayFrame = imgsensor_info.ae_shut_delay_frame; /* The frame of setting shutter default 0 for TG int */ + sensor_info->AESensorGainDelayFrame = imgsensor_info.ae_sensor_gain_delay_frame; /* The frame of setting sensor gain */ + sensor_info->AEISPGainDelayFrame = imgsensor_info.ae_ispGain_delay_frame; + sensor_info->IHDR_Support = imgsensor_info.ihdr_support; + sensor_info->IHDR_LE_FirstLine = imgsensor_info.ihdr_le_firstline; + sensor_info->SensorModeNum = imgsensor_info.sensor_mode_num; + + sensor_info->SensorMIPILaneNumber = imgsensor_info.mipi_lane_num; + sensor_info->SensorClockFreq = imgsensor_info.mclk; + sensor_info->SensorClockDividCount = 3; /* not use */ + sensor_info->SensorClockRisingCount = 0; + sensor_info->SensorClockFallingCount = 2; /* not use */ + sensor_info->SensorPixelClockCount = 3; /* not use */ + sensor_info->SensorDataLatchCount = 2; /* not use */ + + sensor_info->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + sensor_info->SensorWidthSampling = 0; // 0 is default 1x + sensor_info->SensorHightSampling = 0; // 0 is default 1x + sensor_info->SensorPacketECCOrder = 1; + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + sensor_info->SensorGrabStartX = imgsensor_info.cap.startx; + sensor_info->SensorGrabStartY = imgsensor_info.cap.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.cap.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + + sensor_info->SensorGrabStartX = imgsensor_info.normal_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.normal_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.normal_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.hs_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.hs_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.hs_video.mipi_data_lp2hs_settle_dc; + + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + sensor_info->SensorGrabStartX = imgsensor_info.slim_video.startx; + sensor_info->SensorGrabStartY = imgsensor_info.slim_video.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.slim_video.mipi_data_lp2hs_settle_dc; + + break; + default: + sensor_info->SensorGrabStartX = imgsensor_info.pre.startx; + sensor_info->SensorGrabStartY = imgsensor_info.pre.starty; + + sensor_info->MIPIDataLowPwr2HighSpeedSettleDelayCount = imgsensor_info.pre.mipi_data_lp2hs_settle_dc; + break; + } + + return ERROR_NONE; +} /* get_info */ + + +static kal_uint32 control(MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_scenario_id = scenario_id; + spin_unlock(&imgsensor_drv_lock); + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + preview(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + capture(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + normal_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + hs_video(image_window, sensor_config_data); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + slim_video(image_window, sensor_config_data); + break; + default: + LOG_INF("Error ScenarioId setting"); + preview(image_window, sensor_config_data); + return ERROR_INVALID_SCENARIO_ID; + } + return ERROR_NONE; +} /* control() */ + + + +static kal_uint32 set_video_mode(UINT16 framerate) +{ + LOG_INF("framerate = %d\n ", framerate); + // SetVideoMode Function should fix framerate + if (framerate == 0) + // Dynamic frame rate + return ERROR_NONE; + spin_lock(&imgsensor_drv_lock); + if ((framerate == 300) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 296; + else if ((framerate == 150) && (imgsensor.autoflicker_en == KAL_TRUE)) + imgsensor.current_fps = 146; + else + imgsensor.current_fps = framerate; + spin_unlock(&imgsensor_drv_lock); + set_max_framerate(imgsensor.current_fps,1); + + return ERROR_NONE; +} + +static kal_uint32 set_auto_flicker_mode(kal_bool enable, UINT16 framerate) +{ + LOG_INF("enable = %d, framerate = %d \n", enable, framerate); + spin_lock(&imgsensor_drv_lock); + if (enable) //enable auto flicker + imgsensor.autoflicker_en = KAL_TRUE; + else //Cancel Auto flick + imgsensor.autoflicker_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + + +static kal_uint32 set_max_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate) +{ + kal_uint32 frame_length; + + LOG_INF("scenario_id = %d, framerate = %d\n", scenario_id, framerate); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + if(framerate == 0) + return ERROR_NONE; + frame_length = imgsensor_info.normal_video.pclk / framerate * 10 / imgsensor_info.normal_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.normal_video.framelength) ? (frame_length - imgsensor_info.normal_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.normal_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + if (imgsensor.current_fps == imgsensor_info.cap1.max_framerate) { + frame_length = imgsensor_info.cap1.pclk / framerate * 10 / imgsensor_info.cap1.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap1.framelength) ? (frame_length - imgsensor_info.cap1.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap1.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } else { + if (imgsensor.current_fps != imgsensor_info.cap.max_framerate) + LOG_INF("Warning: current_fps %d fps is not support, so use cap's setting: %d fps!\n",framerate,imgsensor_info.cap.max_framerate/10); + frame_length = imgsensor_info.cap.pclk / framerate * 10 / imgsensor_info.cap.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.cap.framelength) ? (frame_length - imgsensor_info.cap.framelength) : 0; + imgsensor.frame_length = imgsensor_info.cap.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + } + set_dummy(); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + frame_length = imgsensor_info.hs_video.pclk / framerate * 10 / imgsensor_info.hs_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.hs_video.framelength) ? (frame_length - imgsensor_info.hs_video.framelength) : 0; + imgsensor.frame_length = imgsensor_info.hs_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + frame_length = imgsensor_info.slim_video.pclk / framerate * 10 / imgsensor_info.slim_video.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.slim_video.framelength) ? (frame_length - imgsensor_info.slim_video.framelength): 0; + imgsensor.frame_length = imgsensor_info.slim_video.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + break; + default: //coding with preview scenario by default + frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength; + spin_lock(&imgsensor_drv_lock); + imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ? (frame_length - imgsensor_info.pre.framelength) : 0; + imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line; + imgsensor.min_frame_length = imgsensor.frame_length; + spin_unlock(&imgsensor_drv_lock); + set_dummy(); + LOG_INF("error scenario_id = %d, we use preview scenario \n", scenario_id); + break; + } + return ERROR_NONE; +} + + +static kal_uint32 get_default_framerate_by_scenario(MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 *framerate) +{ + LOG_INF("scenario_id = %d\n", scenario_id); + + switch (scenario_id) { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + *framerate = imgsensor_info.pre.max_framerate; + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + *framerate = imgsensor_info.normal_video.max_framerate; + break; + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + *framerate = imgsensor_info.cap.max_framerate; + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + *framerate = imgsensor_info.hs_video.max_framerate; + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + *framerate = imgsensor_info.slim_video.max_framerate; + break; + default: + break; + } + + return ERROR_NONE; +} + +static kal_uint32 set_test_pattern_mode(kal_bool enable) +{ + LOG_INF("enable: %d\n", enable); + + if (enable) { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0601, 0x02); + } else { + // 0x5E00[8]: 1 enable, 0 disable + // 0x5E00[1:0]; 00 Color bar, 01 Random Data, 10 Square, 11 BLACK + write_cmos_sensor(0x0601, 0x00); + } + write_cmos_sensor(0x3200, 0x00); + spin_lock(&imgsensor_drv_lock); + imgsensor.test_pattern = enable; + spin_unlock(&imgsensor_drv_lock); + return ERROR_NONE; +} + +static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, + UINT8 *feature_para,UINT32 *feature_para_len) +{ + UINT16 *feature_return_para_16=(UINT16 *) feature_para; + UINT16 *feature_data_16=(UINT16 *) feature_para; + UINT32 *feature_return_para_32=(UINT32 *) feature_para; + UINT32 *feature_data_32=(UINT32 *) feature_para; + unsigned long long *feature_data=(unsigned long long *) feature_para; + + + SENSOR_WINSIZE_INFO_STRUCT *wininfo; + MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para; + + LOG_INF("feature_id = %d", feature_id); + switch (feature_id) { + case SENSOR_FEATURE_GET_PERIOD: + *feature_return_para_16++ = imgsensor.line_length; + *feature_return_para_16 = imgsensor.frame_length; + *feature_para_len=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + LOG_INF("feature_Control imgsensor.pclk = %d,imgsensor.current_fps = %d\n", imgsensor.pclk,imgsensor.current_fps); + *feature_return_para_32 = imgsensor.pclk; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + set_shutter(*feature_data); + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + break; + case SENSOR_FEATURE_SET_GAIN: + set_gain((UINT16) *feature_data); + break; + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + break; + case SENSOR_FEATURE_SET_REGISTER: + if((sensor_reg_data->RegData>>8)>0) + write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + else + write_cmos_sensor_8(sensor_reg_data->RegAddr, sensor_reg_data->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr); + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: + set_video_mode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + get_imgsensor_id(feature_return_para_32); + break; + case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: + set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1)); + break; + case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: + set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: + get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1))); + break; + case SENSOR_FEATURE_SET_TEST_PATTERN: + set_test_pattern_mode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing + *feature_return_para_32 = imgsensor_info.checksum_value; + *feature_para_len=4; + break; + case SENSOR_FEATURE_SET_FRAMERATE: + LOG_INF("current fps :%d\n", (UINT32)*feature_data); + spin_lock(&imgsensor_drv_lock); + imgsensor.current_fps = *feature_data; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_SET_HDR: + //LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data_16); + LOG_INF("Warning! Not Support IHDR Feature"); + spin_lock(&imgsensor_drv_lock); + //imgsensor.ihdr_en = (BOOL)*feature_data_16; + imgsensor.ihdr_en = KAL_FALSE; + spin_unlock(&imgsensor_drv_lock); + break; + case SENSOR_FEATURE_GET_CROP_INFO: + LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data); + wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1)); + + switch (*feature_data_32) { + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_SLIM_VIDEO: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + default: + memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT)); + break; + } + break; + case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: + LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2)); + break; + default: + break; + } + + return ERROR_NONE; +} /* feature_control() */ + +static SENSOR_FUNCTION_STRUCT sensor_func = { + open, + get_info, + get_resolution, + feature_control, + control, + close +}; + +UINT32 S5K5E2YA_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&sensor_func; + return ERROR_NONE; +} /* OV5693_MIPI_RAW_SensorInit */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/s5k5e2yamipiraw_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/s5k5e2yamipiraw_Sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..3b4596945bb9563a98c181e429af9fc849b600f3 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/s5k5e2ya_mipi_raw/s5k5e2yamipiraw_Sensor.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * OV5693mipi_Sensor.h + * + * Project: + * -------- + * ALPS + * + * Description: + * ------------ + * CMOS sensor header file + * + ****************************************************************************/ +#ifndef _S5K5E2YAMIPI_SENSOR_H +#define _S5K5E2YAMIPI_SENSOR_H + + +typedef enum{ + IMGSENSOR_MODE_INIT, + IMGSENSOR_MODE_PREVIEW, + IMGSENSOR_MODE_CAPTURE, + IMGSENSOR_MODE_VIDEO, + IMGSENSOR_MODE_HIGH_SPEED_VIDEO, + IMGSENSOR_MODE_SLIM_VIDEO, +} IMGSENSOR_MODE; + +typedef struct imgsensor_mode_struct { + kal_uint32 pclk; //record different mode's pclk + kal_uint32 linelength; //record different mode's linelength + kal_uint32 framelength; //record different mode's framelength + + kal_uint8 startx; //record different mode's startx of grabwindow + kal_uint8 starty; //record different mode's startx of grabwindow + + kal_uint16 grabwindow_width; //record different mode's width of grabwindow + kal_uint16 grabwindow_height; //record different mode's height of grabwindow + + /* following for MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */ + kal_uint8 mipi_data_lp2hs_settle_dc; + + /* following for GetDefaultFramerateByScenario() */ + kal_uint16 max_framerate; + +} imgsensor_mode_struct; + +/* SENSOR PRIVATE STRUCT FOR VARIABLES*/ +typedef struct imgsensor_struct { + kal_uint8 mirror; //mirrorflip information + + kal_uint8 sensor_mode; //record IMGSENSOR_MODE enum value + + kal_uint32 shutter; //current shutter + kal_uint16 gain; //current gain + + kal_uint32 pclk; //current pclk + + kal_uint32 frame_length; //current framelength + kal_uint32 line_length; //current linelength + + kal_uint32 min_frame_length; //current min framelength to max framerate + kal_uint16 dummy_pixel; //current dummypixel + kal_uint16 dummy_line; //current dummline + + kal_uint16 current_fps; //current max fps + kal_bool autoflicker_en; //record autoflicker enable or disable + kal_bool test_pattern; //record test pattern mode or not + MSDK_SCENARIO_ID_ENUM current_scenario_id;//current scenario id + kal_uint8 ihdr_en; //ihdr enable or disable + + kal_uint8 i2c_write_id; //record current sensor's i2c write id + kal_uint8 update_sensor_otp_awb; // Update sensor awb from otp or not + kal_uint8 update_sensor_otp_lsc; // Update sensor lsc from otp or not +} imgsensor_struct; + +/* SENSOR PRIVATE STRUCT FOR CONSTANT*/ +typedef struct imgsensor_info_struct { + kal_uint32 sensor_id; //record sensor id defined in Kd_imgsensor.h + kal_uint32 checksum_value; //checksum value for Camera Auto Test + imgsensor_mode_struct pre; //preview scenario relative information + imgsensor_mode_struct cap; //capture scenario relative information + imgsensor_mode_struct cap1; //capture for PIP 24fps relative information, capture1 mode must use same framelength, linelength with Capture mode for shutter calculate + imgsensor_mode_struct normal_video;//normal video scenario relative information + imgsensor_mode_struct hs_video; //high speed video scenario relative information + imgsensor_mode_struct slim_video; //slim video for VT scenario relative information + + + kal_uint8 ae_shut_delay_frame; //shutter delay frame for AE cycle + kal_uint8 ae_sensor_gain_delay_frame; //sensor gain delay frame for AE cycle + kal_uint8 ae_ispGain_delay_frame; //isp gain delay frame for AE cycle + kal_uint8 ihdr_support; //1, support; 0,not support + kal_uint8 ihdr_le_firstline; //1,le first ; 0, se first + kal_uint8 sensor_mode_num; //support sensor mode num + + kal_uint8 cap_delay_frame; //enter capture delay frame num + kal_uint8 pre_delay_frame; //enter preview delay frame num + kal_uint8 video_delay_frame; //enter video delay frame num + kal_uint8 hs_video_delay_frame; //enter high speed video delay frame num + kal_uint8 slim_video_delay_frame; //enter slim video delay frame num + + + kal_uint8 margin; //sensor framelength & shutter margin + kal_uint32 min_shutter; //min shutter + kal_uint32 max_frame_length; //max framelength by sensor register's limitation + + kal_uint8 isp_driving_current; //mclk driving current + kal_uint8 sensor_interface_type;//sensor_interface_type + kal_uint8 mipi_sensor_type; //0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para + kal_uint8 mipi_settle_delay_mode; //0, high speed signal auto detect; 1, use settle delay,unit is ns, default is auto detect, don't modify this para + kal_uint8 sensor_output_dataformat;//sensor output first pixel color + kal_uint8 mclk; //mclk value, suggest 24 or 26 for 24Mhz or 26Mhz + + kal_uint8 mipi_lane_num; //mipi lane num + kal_uint8 i2c_addr_table[5]; //record sensor support all write id addr, only supprt 4must end with 0xff + +} imgsensor_info_struct; + +/* SENSOR READ/WRITE ID */ +//#define IMGSENSOR_WRITE_ID_1 (0x6c) +//#define IMGSENSOR_READ_ID_1 (0x6d) +//#define IMGSENSOR_WRITE_ID_2 (0x20) +//#define IMGSENSOR_READ_ID_2 (0x21) + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +extern void kdSetI2CSpeed(u16 i2cSpeed); + +#endif diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/Makefile b/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..04aae2d77ffce2991101f2e89ab0c2b1dc3ff1b7 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/Makefile @@ -0,0 +1,4 @@ +include $(srctree)/drivers/misc/mediatek/Makefile.custom +obj-y += sp0a20_yuv_Sensor.o + + diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/sp0a20_yuv_Sensor.c b/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/sp0a20_yuv_Sensor.c new file mode 100755 index 0000000000000000000000000000000000000000..4160fd03661a90aec11fa6d4d8976cc7de627c01 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/sp0a20_yuv_Sensor.c @@ -0,0 +1,2177 @@ +/***************************************************************************** + * Copyright Statement: + * -------------------- + * This software is protected by Copyright and the information contained + * herein is confidential. The software may not be copied and the information + * contained herein may not be used or disclosed except with the written + * permission of MediaTek Inc. (C) 2005 + * + * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO + * NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S + * SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. + * + * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE + * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE + * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF + * LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND + * RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER + * THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). + * + *****************************************************************************/ + +/***************************************************************************** + * + * Filename: + * --------- + * gc0310yuv_Sensor.c + * + * Project: + * -------- + * MAUI + * + * Description: + * ------------ + * Image sensor driver function + * V1.2.3 + * + * Author: + * ------- + * Leo + * + *============================================================= + * HISTORY + * Below this line, this part is controlled by GCoreinc. DO NOT MODIFY!! + *------------------------------------------------------------------------------ + * $Log$ + * 2012.02.29 kill bugs + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by GCoreinc. DO NOT MODIFY!! + *============================================================= + ******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kd_camera_typedef.h" +#include "kd_camera_hw.h" +#include "kd_imgsensor.h" +#include "kd_imgsensor_define.h" +#include "kd_imgsensor_errcode.h" +#include "kd_camera_feature.h" + +#include "sp0a20_yuv_Sensor.h" + +#define SP0A20YUV_DEBUG + +#ifdef SP0A20YUV_DEBUG +#define SENSORDB printk +#else +#define SENSORDB(x,...) +#endif +kal_bool SP0A20_TST_PATTEN = KAL_FALSE; //wxl +//#define DEBUG_SENSOR_SP0A20//T_flash Tuning +#define SP0A20_TEST_PATTERN_CHECKSUM (0xaf010c1c) + +#ifdef SLT_DEVINFO_CMM +#include +static struct devinfo_struct *s_DEVINFO_ccm; //suppose 10 max lcm device +#endif + +extern int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId); +extern int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId); +static struct SP0A20_Sensor_Struct SP0A20_Sensor_Driver; +kal_uint8 isBanding = 0; // 0: 50hz 1:60hz + +kal_uint16 SP0A20_write_cmos_sensor(kal_uint8 addr, kal_uint8 para) +{ + char puSendCmd[2] = {(char)(addr & 0xFF) , (char)(para & 0xFF)}; + + iWriteRegI2C(puSendCmd , 2, SP0A20_WRITE_ID); + return 0; + +} + +kal_uint16 SP0A20_read_cmos_sensor(kal_uint8 addr) +{ + kal_uint16 get_byte=0; + char puSendCmd = { (char)(addr & 0xFF) }; + iReadRegI2C(&puSendCmd , 1, (u8*)&get_byte, 1, SP0A20_WRITE_ID); + + return get_byte; +} + + +#ifdef DEBUG_SENSOR_SP0A20 +#define SP0A20_OP_CODE_INI 0x00 /* Initial value. */ +#define SP0A20_OP_CODE_REG 0x01 /* Register */ +#define SP0A20_OP_CODE_DLY 0x02 /* Delay */ +#define SP0A20_OP_CODE_END 0x03 /* End of initial setting. */ + kal_uint16 fromsd; + +typedef struct +{ + u16 init_reg; + u16 init_val; /* Save the register value and delay tick */ + u8 op_code; /* 0 - Initial value, 1 - Register, 2 - Delay, 3 - End of setting. */ +} SP0A20_initial_set_struct; + +SP0A20_initial_set_struct SP0A20_Init_Reg[5000]; + +static u32 strtol(const char *nptr, u8 base) +{ + + printk("SP0A20___%s____\n",__func__); + + u8 ret; + if(!nptr || (base!=16 && base!=10 && base!=8)) + { + printk("SP0A20 %s(): NULL pointer input\n", __FUNCTION__); + return -1; + } + for(ret=0; *nptr; nptr++) + { + if((base==16 && *nptr>='A' && *nptr<='F') || + (base==16 && *nptr>='a' && *nptr<='f') || + (base>=10 && *nptr>='0' && *nptr<='9') || + (base>=8 && *nptr>='0' && *nptr<='7') ) + { + ret *= base; + if(base==16 && *nptr>='A' && *nptr<='F') + ret += *nptr-'A'+10; + else if(base==16 && *nptr>='a' && *nptr<='f') + ret += *nptr-'a'+10; + else if(base>=10 && *nptr>='0' && *nptr<='9') + ret += *nptr-'0'; + else if(base>=8 && *nptr>='0' && *nptr<='7') + ret += *nptr-'0'; + } + else + return ret; + } + return ret; +} + +static u8 SP0A20_Initialize_from_T_Flash() +{ + //FS_HANDLE fp = -1; /* Default, no file opened. */ + //u8 *data_buff = NULL; + u8 *curr_ptr = NULL; + u32 file_size = 0; + //u32 bytes_read = 0; + u32 i = 0, j = 0; + u8 func_ind[4] = {0}; /* REG or DLY */ + + + struct file *fp; + mm_segment_t fs; + loff_t pos = 0; + static u8 data_buff[10*1024] ; + + fp = filp_open("/mnt/sdcard/sp0a20_sd", O_RDONLY , 0); + if (IS_ERR(fp)) { + printk("create file error\n"); + return -1; + } + fs = get_fs(); + set_fs(KERNEL_DS); + + file_size = vfs_llseek(fp, 0, SEEK_END); + vfs_read(fp, data_buff, file_size, &pos); + //printk("%s %d %d\n", buf,iFileLen,pos); + filp_close(fp, NULL); + set_fs(fs); + + /* Start parse the setting witch read from t-flash. */ + curr_ptr = data_buff; + while (curr_ptr < (data_buff + file_size)) + { + while ((*curr_ptr == ' ') || (*curr_ptr == '\t'))/* Skip the Space & TAB */ + curr_ptr++; + + if (((*curr_ptr) == '/') && ((*(curr_ptr + 1)) == '*')) + { + while (!(((*curr_ptr) == '*') && ((*(curr_ptr + 1)) == '/'))) + { + curr_ptr++; /* Skip block comment code. */ + } + + while (!((*curr_ptr == 0x0D) && (*(curr_ptr+1) == 0x0A))) + { + curr_ptr++; + } + + curr_ptr += 2; /* Skip the enter line */ + + continue ; + } + + if (((*curr_ptr) == '/') || ((*curr_ptr) == '{') || ((*curr_ptr) == '}')) /* Comment line, skip it. */ + { + while (!((*curr_ptr == 0x0D) && (*(curr_ptr+1) == 0x0A))) + { + curr_ptr++; + } + + curr_ptr += 2; /* Skip the enter line */ + + continue ; + } + /* This just content one enter line. */ + if (((*curr_ptr) == 0x0D) && ((*(curr_ptr + 1)) == 0x0A)) + { + curr_ptr += 2; + continue ; + } + //printk(" curr_ptr1 = %s\n",curr_ptr); + memcpy(func_ind, curr_ptr, 3); + + + if (strcmp((const char *)func_ind, "REG") == 0) /* REG */ + { + curr_ptr += 6; /* Skip "REG(0x" or "DLY(" */ + SP0A20_Init_Reg[i].op_code = SP0A20_OP_CODE_REG; + + SP0A20_Init_Reg[i].init_reg = strtol((const char *)curr_ptr, 16); + curr_ptr += 5; /* Skip "00, 0x" */ + + SP0A20_Init_Reg[i].init_val = strtol((const char *)curr_ptr, 16); + curr_ptr += 4; /* Skip "00);" */ + + } + else /* DLY */ + { + /* Need add delay for this setting. */ + curr_ptr += 4; + SP0A20_Init_Reg[i].op_code = SP0A20_OP_CODE_DLY; + + SP0A20_Init_Reg[i].init_reg = 0xFF; + SP0A20_Init_Reg[i].init_val = strtol((const char *)curr_ptr, 10); /* Get the delay ticks, the delay should less then 50 */ + } + i++; + + + /* Skip to next line directly. */ + while (!((*curr_ptr == 0x0D) && (*(curr_ptr+1) == 0x0A))) + { + curr_ptr++; + } + curr_ptr += 2; + } + + /* (0xFFFF, 0xFFFF) means the end of initial setting. */ + SP0A20_Init_Reg[i].op_code = SP0A20_OP_CODE_END; + SP0A20_Init_Reg[i].init_reg = 0xFF; + SP0A20_Init_Reg[i].init_val = 0xFF; + i++; + //for (j=0; j enable night mode, otherwise, disable night mode + * + * RETURNS + * None + * + * GLOBALS AFFECTED ///070312101020 + * + *************************************************************************/ +static void SP0A20_night_mode(kal_bool bEnable) +{ + if(SP0A20_TST_PATTEN==KAL_TRUE) + return; + if (!SP0A20_Sensor_Driver.MODE_CAPTURE) { + if(bEnable)//night mode + { + SP0A20_Sensor_Driver.bNight_mode = KAL_TRUE; + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xcd,0x20); + SP0A20_write_cmos_sensor(0xce,0x1f); + + if(SP0A20_Sensor_Driver.MPEG4_encode_mode == KAL_TRUE) + { + if(isBanding== 0) + { + printk("video 50Hz night\n"); +#if 0 + //Video record night 24M 50hz 10.02-10fps maxgain + SP0A20_write_cmos_sensor(0xfd , 0x00); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x04 , 0x2c); + SP0A20_write_cmos_sensor(0x05 , 0x00); + SP0A20_write_cmos_sensor(0x06 , 0x00); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x00); + SP0A20_write_cmos_sensor(0x09 , 0x06); + SP0A20_write_cmos_sensor(0x0a , 0x14); + SP0A20_write_cmos_sensor(0xfd , 0x01); + SP0A20_write_cmos_sensor(0xf0 , 0x00); + SP0A20_write_cmos_sensor(0xf7 , 0x32); + SP0A20_write_cmos_sensor(0x02 , 0x0a); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x06 , 0x32); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x01); + SP0A20_write_cmos_sensor(0x09 , 0x00); + SP0A20_write_cmos_sensor(0xfd , 0x02); + SP0A20_write_cmos_sensor(0xbe , 0xf4); + SP0A20_write_cmos_sensor(0xbf , 0x01); + SP0A20_write_cmos_sensor(0xd0 , 0xf4); + SP0A20_write_cmos_sensor(0xd1 , 0x01); +#else//Video record night 24M 50hz 10-10fps maxgain + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0x03,0x01); + SP0A20_write_cmos_sensor(0x04,0x2c); + SP0A20_write_cmos_sensor(0x05,0x00); + SP0A20_write_cmos_sensor(0x06,0x00); + SP0A20_write_cmos_sensor(0x07,0x00); + SP0A20_write_cmos_sensor(0x08,0x00); + SP0A20_write_cmos_sensor(0x09,0x06); + SP0A20_write_cmos_sensor(0x0a,0x14); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xf0,0x00); + SP0A20_write_cmos_sensor(0xf7,0x32); + SP0A20_write_cmos_sensor(0x02,0x0a); + SP0A20_write_cmos_sensor(0x03,0x01); + SP0A20_write_cmos_sensor(0x06,0x32); + SP0A20_write_cmos_sensor(0x07,0x00); + SP0A20_write_cmos_sensor(0x08,0x01); + SP0A20_write_cmos_sensor(0x09,0x00); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xbe,0xf4); + SP0A20_write_cmos_sensor(0xbf,0x01); + SP0A20_write_cmos_sensor(0xd0,0xf4); + SP0A20_write_cmos_sensor(0xd1,0x01); +#endif + + //dbg_print(" video 50Hz night\r\n"); + } + else if(isBanding == 1) + { + //Video record night 24M 60Hz 10-10FPS maxgain: + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0x03,0x00); + SP0A20_write_cmos_sensor(0x04,0xfc); + SP0A20_write_cmos_sensor(0x05,0x00); + SP0A20_write_cmos_sensor(0x06,0x00); + SP0A20_write_cmos_sensor(0x07,0x00); + SP0A20_write_cmos_sensor(0x08,0x00); + SP0A20_write_cmos_sensor(0x09,0x06); + SP0A20_write_cmos_sensor(0x0a,0x01); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xf0,0x00); + SP0A20_write_cmos_sensor(0xf7,0x2a); + SP0A20_write_cmos_sensor(0x02,0x0c); + SP0A20_write_cmos_sensor(0x03,0x01); + SP0A20_write_cmos_sensor(0x06,0x2a); + SP0A20_write_cmos_sensor(0x07,0x00); + SP0A20_write_cmos_sensor(0x08,0x01); + SP0A20_write_cmos_sensor(0x09,0x00); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xbe,0xf8); + SP0A20_write_cmos_sensor(0xbf,0x01); + SP0A20_write_cmos_sensor(0xd0,0xf8); + SP0A20_write_cmos_sensor(0xd1,0x01); + + + printk(" video 60Hz night\r\n"); + } + } + else + { + // dbg_print(" SP0A20_banding=%x\r\n",SP0A20_banding); + if(isBanding== 0) + { + //capture preview night 24M 50hz 8-12fps maxgain: + SP0A20_write_cmos_sensor(0xfd , 0x00); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x04 , 0x68); + SP0A20_write_cmos_sensor(0x05 , 0x00); + SP0A20_write_cmos_sensor(0x06 , 0x00); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x00); + SP0A20_write_cmos_sensor(0x09 , 0x04); + SP0A20_write_cmos_sensor(0x0a , 0x84); + SP0A20_write_cmos_sensor(0xfd , 0x01); + SP0A20_write_cmos_sensor(0xf0 , 0x00); + SP0A20_write_cmos_sensor(0xf7 , 0x3c); + SP0A20_write_cmos_sensor(0x02 , 0x0c); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x06 , 0x3c); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x01); + SP0A20_write_cmos_sensor(0x09 , 0x00); + SP0A20_write_cmos_sensor(0xfd , 0x02); + SP0A20_write_cmos_sensor(0xbe , 0xd0); + SP0A20_write_cmos_sensor(0xbf , 0x02); + SP0A20_write_cmos_sensor(0xd0 , 0xd0); + SP0A20_write_cmos_sensor(0xd1 , 0x02); + + printk(" priview 50Hz night\r\n"); + } + else if(isBanding== 1) + { + //capture preview night 24M 60hz 8-12FPS maxgain: + SP0A20_write_cmos_sensor(0xfd , 0x00); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x04 , 0x2c); + SP0A20_write_cmos_sensor(0x05 , 0x00); + SP0A20_write_cmos_sensor(0x06 , 0x00); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x00); + SP0A20_write_cmos_sensor(0x09 , 0x04); + SP0A20_write_cmos_sensor(0x0a , 0x84); + SP0A20_write_cmos_sensor(0xfd , 0x01); + SP0A20_write_cmos_sensor(0xf0 , 0x00); + SP0A20_write_cmos_sensor(0xf7 , 0x32); + SP0A20_write_cmos_sensor(0x02 , 0x0f); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x06 , 0x32); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x01); + SP0A20_write_cmos_sensor(0x09 , 0x00); + SP0A20_write_cmos_sensor(0xfd , 0x02); + SP0A20_write_cmos_sensor(0xbe , 0xee); + SP0A20_write_cmos_sensor(0xbf , 0x02); + SP0A20_write_cmos_sensor(0xd0 , 0xee); + SP0A20_write_cmos_sensor(0xd1 , 0x02); + + printk(" priview 60Hz night\r\n"); + } + } + } + else // daylight mode + { + SP0A20_Sensor_Driver.bNight_mode = KAL_FALSE; + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xcd,0x10); + SP0A20_write_cmos_sensor(0xce,0x1f); + if(SP0A20_Sensor_Driver.MPEG4_encode_mode == KAL_TRUE) + { + //dbg_print(" SP0A20_banding=%x\r\n",SP0A20_banding); + if(isBanding== 0) + { + //Video record daylight 24M 50hz 10-10FPS maxgain: + SP0A20_write_cmos_sensor(0xfd , 0x00); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x04 , 0x2c); + SP0A20_write_cmos_sensor(0x05 , 0x00); + SP0A20_write_cmos_sensor(0x06 , 0x00); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x00); + SP0A20_write_cmos_sensor(0x09 , 0x06); + SP0A20_write_cmos_sensor(0x0a , 0x14); + SP0A20_write_cmos_sensor(0xfd , 0x01); + SP0A20_write_cmos_sensor(0xf0 , 0x00); + SP0A20_write_cmos_sensor(0xf7 , 0x32); + SP0A20_write_cmos_sensor(0x02 , 0x0a); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x06 , 0x32); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x01); + SP0A20_write_cmos_sensor(0x09 , 0x00); + SP0A20_write_cmos_sensor(0xfd , 0x02); + SP0A20_write_cmos_sensor(0xbe , 0xf4); + SP0A20_write_cmos_sensor(0xbf , 0x01); + SP0A20_write_cmos_sensor(0xd0 , 0xf4); + SP0A20_write_cmos_sensor(0xd1 , 0x01); + + printk(" video 50Hz normal\r\n"); + } + else if(isBanding == 1) + { + //Video record daylight 24M 60Hz 10-10FPS maxgain: + SP0A20_write_cmos_sensor(0xfd , 0x00); + SP0A20_write_cmos_sensor(0x03 , 0x00); + SP0A20_write_cmos_sensor(0x04 , 0xfc); + SP0A20_write_cmos_sensor(0x05 , 0x00); + SP0A20_write_cmos_sensor(0x06 , 0x00); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x00); + SP0A20_write_cmos_sensor(0x09 , 0x06); + SP0A20_write_cmos_sensor(0x0a , 0x01); + SP0A20_write_cmos_sensor(0xfd , 0x01); + SP0A20_write_cmos_sensor(0xf0 , 0x00); + SP0A20_write_cmos_sensor(0xf7 , 0x2a); + SP0A20_write_cmos_sensor(0x02 , 0x0c); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x06 , 0x2a); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x01); + SP0A20_write_cmos_sensor(0x09 , 0x00); + SP0A20_write_cmos_sensor(0xfd , 0x02); + SP0A20_write_cmos_sensor(0xbe , 0xf8); + SP0A20_write_cmos_sensor(0xbf , 0x01); + SP0A20_write_cmos_sensor(0xd0 , 0xf8); + SP0A20_write_cmos_sensor(0xd1 , 0x01); + printk(" video 60Hz normal\r\n"); + } + } + else + { + if(isBanding== 0) + { + //capture preview daylight 24M 50hz 12-8FPS maxgain: + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0x03,0x01); + SP0A20_write_cmos_sensor(0x04,0x68); + SP0A20_write_cmos_sensor(0x05,0x00); + SP0A20_write_cmos_sensor(0x06,0x00); + SP0A20_write_cmos_sensor(0x07,0x00); + SP0A20_write_cmos_sensor(0x08,0x00); + SP0A20_write_cmos_sensor(0x09,0x04); + SP0A20_write_cmos_sensor(0x0a,0x84); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xf0,0x00); + SP0A20_write_cmos_sensor(0xf7,0x3c); + SP0A20_write_cmos_sensor(0x02,0x0c); + SP0A20_write_cmos_sensor(0x03,0x01); + SP0A20_write_cmos_sensor(0x06,0x3c); + SP0A20_write_cmos_sensor(0x07,0x00); + SP0A20_write_cmos_sensor(0x08,0x01); + SP0A20_write_cmos_sensor(0x09,0x00); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xbe,0xd0); + SP0A20_write_cmos_sensor(0xbf,0x02); + SP0A20_write_cmos_sensor(0xd0,0xd0); + SP0A20_write_cmos_sensor(0xd1,0x02); + + printk(" priview 50Hz normal\r\n"); + } + else if(isBanding== 1) + { + //capture preview daylight 24M 60hz 8-12FPS maxgain: + SP0A20_write_cmos_sensor(0xfd , 0x00); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x04 , 0x2c); + SP0A20_write_cmos_sensor(0x05 , 0x00); + SP0A20_write_cmos_sensor(0x06 , 0x00); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x00); + SP0A20_write_cmos_sensor(0x09 , 0x04); + SP0A20_write_cmos_sensor(0x0a , 0x84); + SP0A20_write_cmos_sensor(0xfd , 0x01); + SP0A20_write_cmos_sensor(0xf0 , 0x00); + SP0A20_write_cmos_sensor(0xf7 , 0x32); + SP0A20_write_cmos_sensor(0x02 , 0x0f); + SP0A20_write_cmos_sensor(0x03 , 0x01); + SP0A20_write_cmos_sensor(0x06 , 0x32); + SP0A20_write_cmos_sensor(0x07 , 0x00); + SP0A20_write_cmos_sensor(0x08 , 0x01); + SP0A20_write_cmos_sensor(0x09 , 0x00); + SP0A20_write_cmos_sensor(0xfd , 0x02); + SP0A20_write_cmos_sensor(0xbe , 0xee); + SP0A20_write_cmos_sensor(0xbf , 0x02); + SP0A20_write_cmos_sensor(0xd0 , 0xee); + SP0A20_write_cmos_sensor(0xd1 , 0x02); + + printk(" priview 60Hz normal\r\n"); + } + } + + } + } +} /* SP0A20_NightMode */ + +/************************************************************************* +* FUNCTION +* SP0A20_Sensor_Init +* +* DESCRIPTION +* This function apply all of the initial setting to sensor. +* +* PARAMETERS +* None +* +* RETURNS +* None +* +*************************************************************************/ +void SP0A20_Sensor_Init(void) + +{ + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x36,0x02); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0x0c,0x00); + SP0A20_write_cmos_sensor(0x12,0x02); + SP0A20_write_cmos_sensor(0x13,0x2f); + SP0A20_write_cmos_sensor(0x6d,0x32); + SP0A20_write_cmos_sensor(0x6c,0x32); + SP0A20_write_cmos_sensor(0x6f,0x33); + SP0A20_write_cmos_sensor(0x6e,0x34); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0x92,0x11); + SP0A20_write_cmos_sensor(0x99,0x05); + SP0A20_write_cmos_sensor(0x16,0x38); + SP0A20_write_cmos_sensor(0x17,0x38); + SP0A20_write_cmos_sensor(0x70,0x3a); + SP0A20_write_cmos_sensor(0x14,0x02); + SP0A20_write_cmos_sensor(0x15,0x20); + SP0A20_write_cmos_sensor(0x71,0x23); + SP0A20_write_cmos_sensor(0x69,0x25); + SP0A20_write_cmos_sensor(0x6a,0x1a); + SP0A20_write_cmos_sensor(0x72,0x1c); + SP0A20_write_cmos_sensor(0x75,0x1e); + SP0A20_write_cmos_sensor(0x73,0x3c); + SP0A20_write_cmos_sensor(0x74,0x21); + SP0A20_write_cmos_sensor(0x79,0x00); + SP0A20_write_cmos_sensor(0x77,0x10); + SP0A20_write_cmos_sensor(0x1a,0x4d); + SP0A20_write_cmos_sensor(0x1c,0x07); + SP0A20_write_cmos_sensor(0x1e,0x15); + SP0A20_write_cmos_sensor(0x21,0x08);//0x0e 2015-1-30 sp_miao + SP0A20_write_cmos_sensor(0x22,0x28); + SP0A20_write_cmos_sensor(0x26,0x66); + SP0A20_write_cmos_sensor(0x28,0x0b); +SP0A20_write_cmos_sensor(0x37,0x5a); //4a +SP0A20_write_cmos_sensor(0xfd,0x02); +SP0A20_write_cmos_sensor(0x01,0x80); + + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x41,0x00); + SP0A20_write_cmos_sensor(0x42,0x00); + SP0A20_write_cmos_sensor(0x43,0x00); + SP0A20_write_cmos_sensor(0x44,0x00); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0x03,0x01); + SP0A20_write_cmos_sensor(0x04,0x68); + SP0A20_write_cmos_sensor(0x05,0x00); + SP0A20_write_cmos_sensor(0x06,0x00); + SP0A20_write_cmos_sensor(0x07,0x00); + SP0A20_write_cmos_sensor(0x08,0x00); + SP0A20_write_cmos_sensor(0x09,0x04); + SP0A20_write_cmos_sensor(0x0a,0x84); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xf0,0x00); + SP0A20_write_cmos_sensor(0xf7,0x3c); + SP0A20_write_cmos_sensor(0x02,0x0c); + SP0A20_write_cmos_sensor(0x03,0x01); + SP0A20_write_cmos_sensor(0x06,0x3c); + SP0A20_write_cmos_sensor(0x07,0x00); + SP0A20_write_cmos_sensor(0x08,0x01); + SP0A20_write_cmos_sensor(0x09,0x00); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xbe,0xd0); + SP0A20_write_cmos_sensor(0xbf,0x02); + SP0A20_write_cmos_sensor(0xd0,0xd0); + SP0A20_write_cmos_sensor(0xd1,0x02); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x5a,0x40); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xbc,0x70); + SP0A20_write_cmos_sensor(0xbd,0x50); +SP0A20_write_cmos_sensor(0xb8,0x66); +SP0A20_write_cmos_sensor(0xb9,0x8f); + SP0A20_write_cmos_sensor(0xba,0x30); + SP0A20_write_cmos_sensor(0xbb,0x45); + // 2015-1-30 sp_miao RPC + SP0A20_write_cmos_sensor(0xfd,0x01); +SP0A20_write_cmos_sensor(0xe0,0x60); +SP0A20_write_cmos_sensor(0xe1,0x48); +SP0A20_write_cmos_sensor(0xe2,0x40); +SP0A20_write_cmos_sensor(0xe3,0x3a); +SP0A20_write_cmos_sensor(0xe4,0x3a); +SP0A20_write_cmos_sensor(0xe5,0x38); +SP0A20_write_cmos_sensor(0xe6,0x38); +SP0A20_write_cmos_sensor(0xe7,0x34); +SP0A20_write_cmos_sensor(0xe8,0x34); +SP0A20_write_cmos_sensor(0xe9,0x34); +SP0A20_write_cmos_sensor(0xea,0x32); +SP0A20_write_cmos_sensor(0xf3,0x32); +SP0A20_write_cmos_sensor(0xf4,0x32); + SP0A20_write_cmos_sensor(0xfd,0x01); +SP0A20_write_cmos_sensor(0x04,0xa0); +SP0A20_write_cmos_sensor(0x05,0x32); +SP0A20_write_cmos_sensor(0x0a,0xa0); +SP0A20_write_cmos_sensor(0x0b,0x32); + SP0A20_write_cmos_sensor(0xfd,0x01); +SP0A20_write_cmos_sensor(0xeb,0x7f); +SP0A20_write_cmos_sensor(0xec,0x7f); +SP0A20_write_cmos_sensor(0xed,0x05); +SP0A20_write_cmos_sensor(0xee,0x0a); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xf2,0x4d); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x5b,0x05); + SP0A20_write_cmos_sensor(0x5c,0xa0); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x26,0x80); + SP0A20_write_cmos_sensor(0x27,0x4f); + SP0A20_write_cmos_sensor(0x28,0x00); + SP0A20_write_cmos_sensor(0x29,0x20); + SP0A20_write_cmos_sensor(0x2a,0x00); + SP0A20_write_cmos_sensor(0x2b,0x03); + SP0A20_write_cmos_sensor(0x2c,0x00); + SP0A20_write_cmos_sensor(0x2d,0x20); + SP0A20_write_cmos_sensor(0x30,0x00); + SP0A20_write_cmos_sensor(0x31,0x00); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xa1,0x1a); + SP0A20_write_cmos_sensor(0xa2,0x1e); + SP0A20_write_cmos_sensor(0xa3,0x19); + SP0A20_write_cmos_sensor(0xa4,0x1b); + SP0A20_write_cmos_sensor(0xa5,0x10); + SP0A20_write_cmos_sensor(0xa6,0x12); + SP0A20_write_cmos_sensor(0xa7,0x13); + SP0A20_write_cmos_sensor(0xa8,0x13); + SP0A20_write_cmos_sensor(0xa9,0x10); + SP0A20_write_cmos_sensor(0xaa,0x10); + SP0A20_write_cmos_sensor(0xab,0x0d); + SP0A20_write_cmos_sensor(0xac,0x0d); + SP0A20_write_cmos_sensor(0xad,0x04); + SP0A20_write_cmos_sensor(0xae,0x00); + SP0A20_write_cmos_sensor(0xaf,0x00); + SP0A20_write_cmos_sensor(0xb0,0x08); + SP0A20_write_cmos_sensor(0xb1,0x04); + SP0A20_write_cmos_sensor(0xb2,0x00); + SP0A20_write_cmos_sensor(0xb3,0x00); + SP0A20_write_cmos_sensor(0xb4,0x0a); + SP0A20_write_cmos_sensor(0xb5,0x04); + SP0A20_write_cmos_sensor(0xb6,0x00); + SP0A20_write_cmos_sensor(0xb7,0x00); + SP0A20_write_cmos_sensor(0xb8,0x08); + SP0A20_write_cmos_sensor(0xfd,0x02); +SP0A20_write_cmos_sensor(0x09,0x09); +SP0A20_write_cmos_sensor(0x0d,0x1a); +SP0A20_write_cmos_sensor(0x1d,0x03); +SP0A20_write_cmos_sensor(0x1f,0x04); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x32,0x00); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0xb8); + SP0A20_write_cmos_sensor(0x27,0xa2); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x10,0x22); + SP0A20_write_cmos_sensor(0x11,0x00); + SP0A20_write_cmos_sensor(0x1b,0x80); + SP0A20_write_cmos_sensor(0x1a,0x80); + SP0A20_write_cmos_sensor(0x18,0x27); + SP0A20_write_cmos_sensor(0x19,0x26); + SP0A20_write_cmos_sensor(0x2a,0x01); + SP0A20_write_cmos_sensor(0x2b,0x08); + SP0A20_write_cmos_sensor(0x28,0xf8); + SP0A20_write_cmos_sensor(0x29,0x08); + SP0A20_write_cmos_sensor(0x66,0x50); + SP0A20_write_cmos_sensor(0x67,0x70); + SP0A20_write_cmos_sensor(0x68,0xdc); + SP0A20_write_cmos_sensor(0x69,0xf7); + SP0A20_write_cmos_sensor(0x6a,0xa5); + SP0A20_write_cmos_sensor(0x7c,0x2d); + SP0A20_write_cmos_sensor(0x7d,0x4a); + SP0A20_write_cmos_sensor(0x7e,0xf7); + SP0A20_write_cmos_sensor(0x7f,0x1f); + SP0A20_write_cmos_sensor(0x80,0xa6); + SP0A20_write_cmos_sensor(0x70,0x27); + SP0A20_write_cmos_sensor(0x71,0x40); + SP0A20_write_cmos_sensor(0x72,0x20); + SP0A20_write_cmos_sensor(0x73,0x49); + SP0A20_write_cmos_sensor(0x74,0xaa); + SP0A20_write_cmos_sensor(0x6b,0x0b); + SP0A20_write_cmos_sensor(0x6c,0x27); + SP0A20_write_cmos_sensor(0x6d,0x30); + SP0A20_write_cmos_sensor(0x6e,0x4b); + SP0A20_write_cmos_sensor(0x6f,0xaa); + SP0A20_write_cmos_sensor(0x61,0xf7); + SP0A20_write_cmos_sensor(0x62,0x14); + SP0A20_write_cmos_sensor(0x63,0x4b); + SP0A20_write_cmos_sensor(0x64,0x68); + SP0A20_write_cmos_sensor(0x65,0x6a); + SP0A20_write_cmos_sensor(0x75,0x80); + SP0A20_write_cmos_sensor(0x76,0x09); + SP0A20_write_cmos_sensor(0x77,0x02); + SP0A20_write_cmos_sensor(0x24,0x25); + SP0A20_write_cmos_sensor(0x0e,0x16); + SP0A20_write_cmos_sensor(0x3b,0x09); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xcb,0x20); + SP0A20_write_cmos_sensor(0xcc,0x2c); + SP0A20_write_cmos_sensor(0xcd,0x2c); + SP0A20_write_cmos_sensor(0xce,0x2c); + SP0A20_write_cmos_sensor(0xde,0x0f); + SP0A20_write_cmos_sensor(0xd7,0x08); + SP0A20_write_cmos_sensor(0xd8,0x08); + SP0A20_write_cmos_sensor(0xd9,0x10); + SP0A20_write_cmos_sensor(0xda,0x14); + SP0A20_write_cmos_sensor(0xe8,0x20); + SP0A20_write_cmos_sensor(0xe9,0x20); + SP0A20_write_cmos_sensor(0xea,0x20); + SP0A20_write_cmos_sensor(0xeb,0x20); + SP0A20_write_cmos_sensor(0xec,0x14); + SP0A20_write_cmos_sensor(0xed,0x18); + SP0A20_write_cmos_sensor(0xee,0x20); + SP0A20_write_cmos_sensor(0xef,0x20); + SP0A20_write_cmos_sensor(0xd3,0x20); + SP0A20_write_cmos_sensor(0xd4,0x38); + SP0A20_write_cmos_sensor(0xd5,0x20); + SP0A20_write_cmos_sensor(0xd6,0x08); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xd1,0x20); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xdc,0x05); + SP0A20_write_cmos_sensor(0x05,0x20); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x81,0x00); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xfc,0x00); + SP0A20_write_cmos_sensor(0x7d,0x05); + SP0A20_write_cmos_sensor(0x7e,0x05); + SP0A20_write_cmos_sensor(0x7f,0x09); + SP0A20_write_cmos_sensor(0x80,0x08); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xdd,0x0f); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x6d,0x0a); + SP0A20_write_cmos_sensor(0x6e,0x0e); + SP0A20_write_cmos_sensor(0x6f,0x20); + SP0A20_write_cmos_sensor(0x70,0x20); + SP0A20_write_cmos_sensor(0x86,0x18); + SP0A20_write_cmos_sensor(0x71,0x0c); + SP0A20_write_cmos_sensor(0x72,0x0e); + SP0A20_write_cmos_sensor(0x73,0x20); + SP0A20_write_cmos_sensor(0x74,0x20); + SP0A20_write_cmos_sensor(0x75,0x08); + SP0A20_write_cmos_sensor(0x76,0x0a); + SP0A20_write_cmos_sensor(0x77,0x06); + SP0A20_write_cmos_sensor(0x78,0x06); + SP0A20_write_cmos_sensor(0x79,0x56); + SP0A20_write_cmos_sensor(0x7a,0x45); + SP0A20_write_cmos_sensor(0x7b,0x34); + SP0A20_write_cmos_sensor(0x7c,0x22); + SP0A20_write_cmos_sensor(0x81,0x0d); + SP0A20_write_cmos_sensor(0x82,0x18); + SP0A20_write_cmos_sensor(0x83,0x20); + SP0A20_write_cmos_sensor(0x84,0x24); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x83,0x12); + SP0A20_write_cmos_sensor(0x84,0x14); + SP0A20_write_cmos_sensor(0x86,0x04); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x61,0x60); + SP0A20_write_cmos_sensor(0x62,0x28); + SP0A20_write_cmos_sensor(0x8a,0x10); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x8b,0x00); + SP0A20_write_cmos_sensor(0x8c,0x0a); + SP0A20_write_cmos_sensor(0x8d,0x18); + SP0A20_write_cmos_sensor(0x8e,0x29); + SP0A20_write_cmos_sensor(0x8f,0x39); + SP0A20_write_cmos_sensor(0x90,0x4f); + SP0A20_write_cmos_sensor(0x91,0x62); + SP0A20_write_cmos_sensor(0x92,0x71); + SP0A20_write_cmos_sensor(0x93,0x7f); + SP0A20_write_cmos_sensor(0x94,0x93); + SP0A20_write_cmos_sensor(0x95,0xa3); + SP0A20_write_cmos_sensor(0x96,0xb0); + SP0A20_write_cmos_sensor(0x97,0xbb); + SP0A20_write_cmos_sensor(0x98,0xc6); + SP0A20_write_cmos_sensor(0x99,0xce); + SP0A20_write_cmos_sensor(0x9a,0xd5); + SP0A20_write_cmos_sensor(0x9b,0xdc); + SP0A20_write_cmos_sensor(0x9c,0xe3); + SP0A20_write_cmos_sensor(0x9d,0xe8); + SP0A20_write_cmos_sensor(0x9e,0xec); + SP0A20_write_cmos_sensor(0x9f,0xf1); + SP0A20_write_cmos_sensor(0xa0,0xf6); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x15,0xc0); + SP0A20_write_cmos_sensor(0x16,0x8c); + SP0A20_write_cmos_sensor(0xa0,0x86); + SP0A20_write_cmos_sensor(0xa1,0xfa); + SP0A20_write_cmos_sensor(0xa2,0x00); + SP0A20_write_cmos_sensor(0xa3,0xdb); + SP0A20_write_cmos_sensor(0xa4,0xc0); + SP0A20_write_cmos_sensor(0xa5,0xe6); + SP0A20_write_cmos_sensor(0xa6,0xed); + SP0A20_write_cmos_sensor(0xa7,0xda); + SP0A20_write_cmos_sensor(0xa8,0xb9); + SP0A20_write_cmos_sensor(0xa9,0x0c); + SP0A20_write_cmos_sensor(0xaa,0x33); + SP0A20_write_cmos_sensor(0xab,0x0f); + SP0A20_write_cmos_sensor(0xac,0x80); + SP0A20_write_cmos_sensor(0xad,0xed); + SP0A20_write_cmos_sensor(0xae,0x13); + SP0A20_write_cmos_sensor(0xaf,0xcd); + SP0A20_write_cmos_sensor(0xb0,0x99); + SP0A20_write_cmos_sensor(0xb1,0x19); + SP0A20_write_cmos_sensor(0xb2,0xc7); + SP0A20_write_cmos_sensor(0xb3,0x9a); + SP0A20_write_cmos_sensor(0xb4,0x20); + SP0A20_write_cmos_sensor(0xb5,0x0c); + SP0A20_write_cmos_sensor(0xb6,0x03); + SP0A20_write_cmos_sensor(0xb7,0x1f); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xd3,0x70); + SP0A20_write_cmos_sensor(0xd4,0x6c); + SP0A20_write_cmos_sensor(0xd5,0x66); + SP0A20_write_cmos_sensor(0xd6,0x5e); + SP0A20_write_cmos_sensor(0xd7,0x70); + SP0A20_write_cmos_sensor(0xd8,0x6c); + SP0A20_write_cmos_sensor(0xd9,0x66); + SP0A20_write_cmos_sensor(0xda,0x5e); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xdd,0x30); + SP0A20_write_cmos_sensor(0xde,0x10); + SP0A20_write_cmos_sensor(0xdf,0xff); + SP0A20_write_cmos_sensor(0x00,0x00); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xc2,0x77); + SP0A20_write_cmos_sensor(0xc3,0x77); + SP0A20_write_cmos_sensor(0xc4,0x66); + SP0A20_write_cmos_sensor(0xc5,0x55); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xcd,0x10); + SP0A20_write_cmos_sensor(0xce,0x1f); + SP0A20_write_cmos_sensor(0xcf,0x30); + SP0A20_write_cmos_sensor(0xd0,0x45); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x31,0x60); + SP0A20_write_cmos_sensor(0x32,0x60); + SP0A20_write_cmos_sensor(0x33,0xc0); + SP0A20_write_cmos_sensor(0x35,0x60); + SP0A20_write_cmos_sensor(0x36,0x10); + SP0A20_write_cmos_sensor(0x37,0x13); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x0e,0x80); + SP0A20_write_cmos_sensor(0x0f,0x20); + SP0A20_write_cmos_sensor(0x10,0x80); + SP0A20_write_cmos_sensor(0x11,0x7c); + SP0A20_write_cmos_sensor(0x12,0x78); + SP0A20_write_cmos_sensor(0x13,0x70); + SP0A20_write_cmos_sensor(0x14,0x88); + SP0A20_write_cmos_sensor(0x15,0x84); + SP0A20_write_cmos_sensor(0x16,0x80); + SP0A20_write_cmos_sensor(0x17,0x7d); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0x31,0x00); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x32,0x15); + SP0A20_write_cmos_sensor(0x33,0xef); + SP0A20_write_cmos_sensor(0x34,0x07); + SP0A20_write_cmos_sensor(0xd2,0x01); + SP0A20_write_cmos_sensor(0xfb,0x25); + SP0A20_write_cmos_sensor(0xf2,0x49); + SP0A20_write_cmos_sensor(0x35,0x40); + SP0A20_write_cmos_sensor(0x5d,0x11); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x36,0x00); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x1b,0x20); +} + +//extern u32 pinSetIdx; +//extern u32 SensorID; +UINT32 SP0A20GetSensorID(UINT32 *sensorID) +{ + int retry = 3; +#ifdef SLT_DEVINFO_CMM + s_DEVINFO_ccm =(struct devinfo_struct*) kmalloc(sizeof(struct devinfo_struct), GFP_KERNEL); + s_DEVINFO_ccm->device_type = "CCM-S"; + s_DEVINFO_ccm->device_module = "PCOEJ0003A";//can change if got module id + s_DEVINFO_ccm->device_vendor = "Sanlaishi"; + s_DEVINFO_ccm->device_ic = "SP0A20"; + s_DEVINFO_ccm->device_version = "SuperPix"; + s_DEVINFO_ccm->device_info = "30W"; +#endif + + // check if sensor ID correct + do { +#if 1 + SP0A20_write_cmos_sensor(0xfd,0x00); + *sensorID = SP0A20_read_cmos_sensor(0x02); + SENSORDB("%s,Read Sensor ID = 0x%04x\n",__func__, *sensorID); +#else + if(SensorID==4) + { +// SP0A20_write_cmos_sensor(0xfd,0x00); +// *sensorID = SP0A20_read_cmos_sensor(0x02); +// SENSORDB("%s,Read Sensor ID = 0x%04x\n",__func__, *sensorID); + *sensorID = SP0A20_SENSOR_ID; + } + else + { + *sensorID = 0; + } + //SP0A20_write_cmos_sensor(0xfd,0x00); + //*sensorID = SP0A20_read_cmos_sensor(0x02); + //SENSORDB("%s,Read Sensor ID = 0x%04x\n",__func__, *sensorID); +#endif + if (*sensorID == SP0A20_SENSOR_ID) + break; + SENSORDB("Read Sensor ID Fail = 0x%04x\n", *sensorID); + retry--; + } while (retry > 0); + + if (*sensorID != SP0A20_SENSOR_ID) { + *sensorID = 0xFFFFFFFF; + #ifdef SLT_DEVINFO_CMM + s_DEVINFO_ccm->device_used = DEVINFO_UNUSED; + devinfo_check_add_device(s_DEVINFO_ccm); + #endif + return ERROR_SENSOR_CONNECT_FAIL; + } + +#ifdef SLT_DEVINFO_CMM + s_DEVINFO_ccm->device_used = DEVINFO_USED; + devinfo_check_add_device(s_DEVINFO_ccm); +#endif + return ERROR_NONE; +} + + + + +/************************************************************************* +* FUNCTION +* SP0A20_Write_More_Registers +* +* DESCRIPTION +* This function is served for FAE to modify the necessary Init Regs. Do not modify the regs +* in init_SP0A20() directly. +* +* PARAMETERS +* None +* +* RETURNS +* None +* +* GLOBALS AFFECTED +* +*************************************************************************/ +void SP0A20_Write_More_Registers(void) +{ + +} + + +/************************************************************************* + * FUNCTION + * SP0A20Open + * + * DESCRIPTION + * This function initialize the registers of CMOS sensor + * + * PARAMETERS + * None + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +UINT32 SP0A20Open(void) +{ + volatile signed char i; + kal_uint16 sensor_id=0; + + printk(" Entry SP0A20Open!!!\r\n"); + + //Sleep(10); + + + // Read sensor ID to adjust I2C is OK? +#if 1 +for(i=0;i<3;i++) +{ + SP0A20_write_cmos_sensor(0xfd,0x00); + sensor_id = SP0A20_read_cmos_sensor(0x02); + SENSORDB("%s,Read Sensor ID = 0x%x\n", __func__,sensor_id); + if(sensor_id == SP0A20_SENSOR_ID) + { + SENSORDB("SP0A20_ Sensor Read ID OK \r\n"); + break; + } +} +#else +if(SensorID==4) +{ +/* +for(i=0;i<3;i++) +{ + SP0A20_write_cmos_sensor(0xfd,0x00); + sensor_id = SP0A20_read_cmos_sensor(0x02); + SENSORDB("%s,Read Sensor ID = 0x%x\n", __func__,sensor_id); + if(sensor_id == SP0A20_SENSOR_ID) + { + SENSORDB("SP0A20_ Sensor Read ID OK \r\n"); + break; + } +} +*/ sensor_id = SP0A20_SENSOR_ID; +} +else +{ + sensor_id = 0; +} +#endif + if(sensor_id != SP0A20_SENSOR_ID) + { + SENSORDB("SP0A20 Read Sensor ID Fail[open] = 0x%x\n", sensor_id); + return ERROR_SENSOR_CONNECT_FAIL; + } + +#ifdef DEBUG_SENSOR_SP0A20 + struct file *fp; + mm_segment_t fs; + loff_t pos = 0; + static char buf[60*1024] ; + + + fp = filp_open("/mnt/sdcard/sp0a20_sd", O_RDONLY , 0); + + if (IS_ERR(fp)) { + + fromsd = 0; + printk("open file error\n"); + } + else + { + fromsd = 1; + printk("open file ok\n"); + + filp_close(fp, NULL); + set_fs(fs); + } + + if(fromsd == 1) + { + printk("________________from t!\n"); + SP0A20_Initialize_from_T_Flash(); + } + else + { + SP0A20_Sensor_Init(); + SP0A20_Write_More_Registers();//added for FAE to debut + } +#else + //RETAILMSG(1, (TEXT("Sensor Read ID OK \r\n"))); + // initail sequence write in + SP0A20_Sensor_Init(); + SP0A20_Write_More_Registers();//added for FAE to debut +#endif + return ERROR_NONE; +} /* SP0A20Open */ + + +/************************************************************************* + * FUNCTION + * SP0A20Close + * + * DESCRIPTION + * This function is to turn off sensor module power. + * + * PARAMETERS + * None + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +UINT32 SP0A20Close(void) +{ + return ERROR_NONE; +} /* SP0A20Close */ + + +/************************************************************************* + * FUNCTION + * SP0A20Preview + * + * DESCRIPTION + * This function start the sensor preview. + * + * PARAMETERS + * *image_window : address pointer of pixel numbers in one period of HSYNC + * *sensor_config_data : address pointer of line numbers in one period of VSYNC + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +UINT32 SP0A20Preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) + +{ +// kal_uint32 iTemp; +// kal_uint16 iStartX = 0, iStartY = 1; + + if(sensor_config_data->SensorOperationMode == MSDK_SENSOR_OPERATION_MODE_VIDEO) // MPEG4 Encode Mode + { + RETAILMSG(1, (TEXT("Camera Video preview\r\n"))); + SP0A20_MPEG4_encode_mode = KAL_TRUE; + + } + else + { + RETAILMSG(1, (TEXT("Camera preview\r\n"))); + SP0A20_MPEG4_encode_mode = KAL_FALSE; + } + + image_window->GrabStartX= IMAGE_SENSOR_VGA_GRAB_PIXELS; + image_window->GrabStartY= IMAGE_SENSOR_VGA_GRAB_LINES; + image_window->ExposureWindowWidth = IMAGE_SENSOR_PV_WIDTH; + image_window->ExposureWindowHeight =IMAGE_SENSOR_PV_HEIGHT; + + // copy sensor_config_data + memcpy(&SP0A20SensorConfigData, sensor_config_data, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + return ERROR_NONE; +} /* SP0A20Preview */ + + +/************************************************************************* + * FUNCTION + * SP0A20Capture + * + * DESCRIPTION + * This function setup the CMOS sensor in capture MY_OUTPUT mode + * + * PARAMETERS + * + * RETURNS + * None + * + * GLOBALS AFFECTED + * + *************************************************************************/ +UINT32 SP0A20Capture(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, + MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) + +{ + SP0A20_MODE_CAPTURE=KAL_TRUE; + + image_window->GrabStartX = IMAGE_SENSOR_VGA_GRAB_PIXELS; + image_window->GrabStartY = IMAGE_SENSOR_VGA_GRAB_LINES; + image_window->ExposureWindowWidth= IMAGE_SENSOR_FULL_WIDTH; + image_window->ExposureWindowHeight = IMAGE_SENSOR_FULL_HEIGHT; + + // copy sensor_config_data + memcpy(&SP0A20SensorConfigData, sensor_config_data, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + return ERROR_NONE; +} /* SP0A20_Capture() */ + +/*static UINT32 SP0A20GetExposureTime(void) +{ + UINT8 high_base,low_base,high_exp,low_exp = 0; + UINT32 EXP; +UINT32 temp1; + SP0A20_write_cmos_sensor(0xfd, 0x00); + + high_exp = SP0A20_read_cmos_sensor(0x03); + low_exp = SP0A20_read_cmos_sensor(0x04); + + SP0A20_write_cmos_sensor(0xfd, 0x01); + + high_base = SP0A20_read_cmos_sensor(0xf0); + + low_base = SP0A20_read_cmos_sensor(0xf7); + temp1 = (( (( high_exp << 8) | low_exp)) /( (high_base<<8) | low_base)); + EXP =(( (( high_exp << 8) | low_exp)) /( (high_base<<8) | low_base))* 10 *5000;//return us +printk("%s,EXP = %d,temp1 = %d\n",__func__,EXP,temp1); + return EXP; +} +*/ + +/*void SP0A20GetExifInfo(UINT32 exifAddr) +{ + SENSOR_EXIF_INFO_STRUCT* pExifInfo = (SENSOR_EXIF_INFO_STRUCT*)exifAddr; + + pExifInfo->CapExposureTime = SP0A20GetExposureTime(); + +}*/ + +UINT32 SP0A20GetResolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *pSensorResolution) +{ + pSensorResolution->SensorFullWidth=IMAGE_SENSOR_FULL_WIDTH; + pSensorResolution->SensorFullHeight=IMAGE_SENSOR_FULL_HEIGHT; + pSensorResolution->SensorPreviewWidth=IMAGE_SENSOR_PV_WIDTH; + pSensorResolution->SensorPreviewHeight=IMAGE_SENSOR_PV_HEIGHT; + pSensorResolution->SensorVideoWidth=IMAGE_SENSOR_PV_WIDTH; + + pSensorResolution->SensorVideoHeight=IMAGE_SENSOR_PV_HEIGHT; + return ERROR_NONE; +} /* SP0A20GetResolution() */ + + +UINT32 SP0A20GetInfo(MSDK_SCENARIO_ID_ENUM ScenarioId, + MSDK_SENSOR_INFO_STRUCT *pSensorInfo, + MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData) +{ + pSensorInfo->SensorPreviewResolutionX=IMAGE_SENSOR_PV_WIDTH; + pSensorInfo->SensorPreviewResolutionY=IMAGE_SENSOR_PV_HEIGHT; + pSensorInfo->SensorFullResolutionX=IMAGE_SENSOR_FULL_WIDTH; + pSensorInfo->SensorFullResolutionY=IMAGE_SENSOR_FULL_HEIGHT; + + pSensorInfo->SensorCameraPreviewFrameRate=30; + pSensorInfo->SensorVideoFrameRate=30; + pSensorInfo->SensorStillCaptureFrameRate=10; + pSensorInfo->SensorWebCamCaptureFrameRate=15; + pSensorInfo->SensorResetActiveHigh=FALSE; + pSensorInfo->SensorResetDelayCount=1; + pSensorInfo->SensorOutputDataFormat=SENSOR_OUTPUT_FORMAT_YUYV; + pSensorInfo->SensorClockPolarity=SENSOR_CLOCK_POLARITY_LOW; + pSensorInfo->SensorClockFallingPolarity=SENSOR_CLOCK_POLARITY_LOW; + pSensorInfo->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + pSensorInfo->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; + pSensorInfo->SensorInterruptDelayLines = 1; + pSensorInfo->SensroInterfaceType=SENSOR_INTERFACE_TYPE_MIPI;//MIPI setting + pSensorInfo->CaptureDelayFrame = 2; + pSensorInfo->PreviewDelayFrame = 1; + pSensorInfo->VideoDelayFrame = 4; + pSensorInfo->SensorMasterClockSwitch = 0; + pSensorInfo->SensorDrivingCurrent = ISP_DRIVING_2MA; + + switch (ScenarioId) + { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + default: + pSensorInfo->SensorClockFreq=24; + pSensorInfo->SensorClockDividCount= 3; + pSensorInfo->SensorClockRisingCount=0; + pSensorInfo->SensorClockFallingCount=2; + pSensorInfo->SensorPixelClockCount=3; + pSensorInfo->SensorDataLatchCount=2; + pSensorInfo->SensorGrabStartX = IMAGE_SENSOR_VGA_GRAB_PIXELS; + pSensorInfo->SensorGrabStartY = IMAGE_SENSOR_VGA_GRAB_LINES; + //MIPI setting + pSensorInfo->SensorMIPILaneNumber = SENSOR_MIPI_1_LANE; + pSensorInfo->MIPIDataLowPwr2HighSpeedTermDelayCount = 0; + pSensorInfo->MIPIDataLowPwr2HighSpeedSettleDelayCount = 14; + pSensorInfo->MIPICLKLowPwr2HighSpeedTermDelayCount = 0; + pSensorInfo->SensorWidthSampling = 0; // 0 is default 1x + pSensorInfo->SensorHightSampling = 0; // 0 is default 1x + pSensorInfo->SensorPacketECCOrder = 1; + + break; + } + SP0A20PixelClockDivider=pSensorInfo->SensorPixelClockCount; + memcpy(pSensorConfigData, &SP0A20SensorConfigData, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + return ERROR_NONE; +} /* SP0A20GetInfo() */ + + +UINT32 SP0A20Control(MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow, + MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData) +{ + printk("%s,MIPIControl start.\n",__func__); + switch (ScenarioId) + { + case MSDK_SCENARIO_ID_CAMERA_PREVIEW: + case MSDK_SCENARIO_ID_VIDEO_PREVIEW: + case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG: + default: + SP0A20Preview(pImageWindow, pSensorConfigData); + break; + } + + printk("%s,MIPIControl end.\n",__func__); + return TRUE; +} /* SP0A20Control() */ + +BOOL SP0A20_set_param_wb(UINT16 para) +{ + if(SP0A20_TST_PATTEN==KAL_TRUE) + return 0; + + printk("%s,enter, para = %x\n",__func__,para); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x36,0x02); + + switch (para) + { + case AWB_MODE_OFF: + printk("%s,AWB_MODE_OFF.\n",__func__); + break; + + case AWB_MODE_AUTO: + SP0A20_awb_enable(KAL_TRUE); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x32,0x15); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0xbf); + SP0A20_write_cmos_sensor(0x27,0xa3); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + break; + + case AWB_MODE_CLOUDY_DAYLIGHT: //cloudy + SP0A20_awb_enable(KAL_FALSE); + SP0A20_write_cmos_sensor(0xfd,0x01); //4200-5000K + + SP0A20_write_cmos_sensor(0x32,0x05); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0x95); + SP0A20_write_cmos_sensor(0x27,0xba); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + break; + + case AWB_MODE_DAYLIGHT: //sunny + SP0A20_awb_enable(KAL_FALSE); + // SP0A20_reg_WB_auto + SP0A20_write_cmos_sensor(0xfd,0x01); //2800K~3000K + SP0A20_write_cmos_sensor(0x32,0x05); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0x88); + SP0A20_write_cmos_sensor(0x27,0xb0); //d0 + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + break; + + case AWB_MODE_INCANDESCENT: //office + SP0A20_awb_enable(KAL_FALSE); + // SP0A20_reg_WB_auto + SP0A20_write_cmos_sensor(0xfd,0x01); //2800K~3000K + SP0A20_write_cmos_sensor(0x32,0x05); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0x88); + SP0A20_write_cmos_sensor(0x27,0xd0); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + break; + + case AWB_MODE_TUNGSTEN: //home + SP0A20_awb_enable(KAL_FALSE); + SP0A20_write_cmos_sensor(0xfd,0x01); //4000K + SP0A20_write_cmos_sensor(0x32,0x05); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0xac); + SP0A20_write_cmos_sensor(0x27,0xbe); + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + break; + case AWB_MODE_TWILIGHT: //5 + SP0A20_awb_enable(KAL_FALSE); + SP0A20_write_cmos_sensor(0xfd,0x01); //7000K + SP0A20_write_cmos_sensor(0x32,0x05); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0xdb); + SP0A20_write_cmos_sensor(0x27,0x80); //70 + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + break; + case AWB_MODE_FLUORESCENT: + SP0A20_awb_enable(KAL_FALSE); + SP0A20_write_cmos_sensor(0xfd,0x01); //4200-5000K + SP0A20_write_cmos_sensor(0x32,0x05); + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0xbf); //95 + SP0A20_write_cmos_sensor(0x27,0x89); //ba + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + break; + + default: + return FALSE; + } + + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + Sleep(10); + + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x36,0x00); + + printk("%s,exit.\n",__func__); + return TRUE; +} /* SP0A20_set_param_wb */ + + +BOOL SP0A20_set_param_effect(UINT16 para) +{ + kal_uint32 ret = KAL_TRUE; + SENSORDB("%s,para= %d.\n",__func__,para); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x36,0x02); + + switch (para) + { + case MEFFECT_OFF: + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x66,0x00); + SP0A20_write_cmos_sensor(0x67,0x80); + SP0A20_write_cmos_sensor(0x68,0x80); + break; + + case MEFFECT_SOLARIZE: + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x66,0x10); + SP0A20_write_cmos_sensor(0x67,0x98); + SP0A20_write_cmos_sensor(0x68,0x58); + break; + case MEFFECT_SEPIA: + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x66,0x10); + SP0A20_write_cmos_sensor(0x67,0x98); + SP0A20_write_cmos_sensor(0x68,0x58); + break; + case MEFFECT_NEGATIVE: + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x66,0x04); + SP0A20_write_cmos_sensor(0x67,0x80); + SP0A20_write_cmos_sensor(0x68,0x80); + break; + + case MEFFECT_SEPIAGREEN: + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x66,0x10); + SP0A20_write_cmos_sensor(0x67,0x50); + SP0A20_write_cmos_sensor(0x68,0x50); + break; + + case MEFFECT_SEPIABLUE: + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x66,0x10); + SP0A20_write_cmos_sensor(0x67,0x50); + SP0A20_write_cmos_sensor(0x68,0xc0); + break; + + case MEFFECT_MONO: //B&Wdan se + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x66,0x20); + SP0A20_write_cmos_sensor(0x67,0x80); + SP0A20_write_cmos_sensor(0x68,0x80); + break; + + default: + return FALSE; + } + + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0xe7,0x03); + SP0A20_write_cmos_sensor(0xe7,0x00); + Sleep(10); + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x36,0x00); + return ret; + +} /* SP0A20_set_param_effect */ + + +BOOL SP0A20_set_param_banding(UINT16 para) +{ + SP0A20_Sensor_Driver.bBanding_value = para; + switch (para) + { + case AE_FLICKER_MODE_50HZ: + isBanding = 0; + printk("SP0A20_set_param_banding_50hz\n"); + //SP0A20_set_banding_for_50Hz(); + break; + case AE_FLICKER_MODE_60HZ: + isBanding = 1; + printk("SP0A20_set_param_banding_60hz\n"); + //SP0A20_set_banding_for_60Hz(); + break; + default: + return FALSE; + } + + return TRUE; +} /* SP0A20_set_param_banding */ + + +BOOL SP0A20_set_param_exposure(UINT16 para) +{ + + + switch (para) + { + case AE_EV_COMP_n13: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0xc0); + break; + + case AE_EV_COMP_n10: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0xd0); + break; + + case AE_EV_COMP_n07: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0xe0); + break; + + case AE_EV_COMP_n03: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0xf0); + break; + + case AE_EV_COMP_00: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0x00);//0xfa before + break; + + + case AE_EV_COMP_03: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0x10); + break; + + case AE_EV_COMP_07: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0x20); + break; + + case AE_EV_COMP_10: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0x30); + break; + + case AE_EV_COMP_13: + SP0A20_write_cmos_sensor(0xfd, 0x01); + SP0A20_write_cmos_sensor(0xdb, 0x40); + break; + + default: + return FALSE; + } + + return TRUE; +} /* SP0A20_set_param_exposure */ + + + +UINT32 SP0A20YUVSetVideoMode(UINT16 u2FrameRate) // lanking add +{ + + SP0A20_MPEG4_encode_mode = KAL_TRUE; + if (u2FrameRate == 30) + { + + /*********video frame ************/ + + } + else if (u2FrameRate == 15) + { + + /*********video frame ************/ + + } + else + { + + SENSORDB("Wrong Frame Rate"); + + } + + return TRUE; + +} + + +kal_uint16 SP0A20SetTestPatternMode(kal_bool bEnable) +{ + kal_uint16 temp_tst_reg; + SENSORDB("%s, Test pattern enable:%d\n",__func__, bEnable); + + if(bEnable) // enable test pattern output + { + SP0A20_TST_PATTEN = KAL_TRUE; + + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x33,0x00); + SP0A20_write_cmos_sensor(0x34,0x00); + SP0A20_write_cmos_sensor(0x36,0x02); + + SP0A20_write_cmos_sensor(0xfd,0x00); + SP0A20_write_cmos_sensor(0x1c,0x00); + SP0A20_write_cmos_sensor(0x1d,0x00); + SP0A20_write_cmos_sensor(0x0a,0x50); + + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0xdd,0x00); + SP0A20_write_cmos_sensor(0xde,0x00); + + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0xf2,0x0a); + SP0A20_write_cmos_sensor(0xfb,0x00); + SP0A20_write_cmos_sensor(0xd2,0x00); + + + SP0A20_write_cmos_sensor(0xfd , 0x01);//sat u + SP0A20_write_cmos_sensor(0xd3 , 0x60);//6a + SP0A20_write_cmos_sensor(0xd4 , 0x60);//6a + SP0A20_write_cmos_sensor(0xd5 , 0x60);//56 + SP0A20_write_cmos_sensor(0xd6 , 0x60);//44 + //sat v + SP0A20_write_cmos_sensor(0xd7 , 0x60);//6a + SP0A20_write_cmos_sensor(0xd8 , 0x60);//6a + SP0A20_write_cmos_sensor(0xd9 , 0x60);//56 + SP0A20_write_cmos_sensor(0xda , 0x60);//44 + + + SP0A20_write_cmos_sensor(0x10 , 0x80);//ku_outdoor + SP0A20_write_cmos_sensor(0x11 , 0x80);//ku_nr + SP0A20_write_cmos_sensor(0x12 , 0x80);//ku_dummy + SP0A20_write_cmos_sensor(0x13 , 0x80);//ku_low + SP0A20_write_cmos_sensor(0x14 , 0x80);//88//kl_outdoor + SP0A20_write_cmos_sensor(0x15 , 0x80);//88//kl_nr + SP0A20_write_cmos_sensor(0x16 , 0x80);//88//kl_dummy + SP0A20_write_cmos_sensor(0x17 , 0x80);//88//kl_low + + SP0A20_write_cmos_sensor(0x00,0x12); + SP0A20_write_cmos_sensor(0x32,0x80); + + SP0A20_write_cmos_sensor(0xfd,0x02); + SP0A20_write_cmos_sensor(0x26,0x80); + SP0A20_write_cmos_sensor(0x27,0x80); + + SP0A20_write_cmos_sensor(0xfd,0x01); + SP0A20_write_cmos_sensor(0x36,0x00); + + Sleep(100); + } + else //disable test pattern output + { + SP0A20_TST_PATTEN = KAL_FALSE; + Sleep(100); + SP0A20_write_cmos_sensor(0xfd,0x01); + Sleep(100); + temp_tst_reg =SP0A20_read_cmos_sensor(0x32); + Sleep(100); + SP0A20_write_cmos_sensor(0x32, (temp_tst_reg &0x7f)); + Sleep(100); + } + return ERROR_NONE; +} + + +UINT32 SP0A20YUVSensorSetting(FEATURE_ID iCmd, UINT16 iPara) +{ + SENSORDB("%s,para= %d.\n",__func__,iPara); +#ifdef DEBUG_SENSOR_SP0A20 + printk("______%s______ Tflash debug \n",__func__); + return TRUE; +#endif + + switch (iCmd) { + case FID_AWB_MODE: + SP0A20_set_param_wb(iPara); + break; + case FID_COLOR_EFFECT: + SP0A20_set_param_effect(iPara); + break; + case FID_AE_EV: + SP0A20_set_param_exposure(iPara); + break; + case FID_AE_FLICKER: + SP0A20_set_param_banding(iPara); + if (SP0A20_Sensor_Driver.bNight_mode == KAL_FALSE){ + SP0A20_night_mode(FALSE); + }else if (SP0A20_Sensor_Driver.bNight_mode == KAL_TRUE){ + SP0A20_night_mode(TRUE); + } + break; + case FID_SCENE_MODE: + SP0A20_night_mode(iPara); + break; + default: + break; + } + return TRUE; +} /* SP0A20YUVSensorSetting */ + +static void SP0A20_MIPI_GetYUVSensorBV(UINT32 *val) +{ + SP0A20_write_cmos_sensor(0xfd,0x01); + *val = SP0A20_read_cmos_sensor(0xf1); + printk("SP0A20_MIPI_GetYUVSensorBV val:%d\n",*val); + SP0A20_write_cmos_sensor(0xfd,0x00); +} + +UINT32 SP0A20FeatureControl(MSDK_SENSOR_FEATURE_ENUM FeatureId, + UINT8 *pFeaturePara,UINT32 *pFeatureParaLen) +{ + UINT16 *pFeatureReturnPara16=(UINT16 *) pFeaturePara; + //UINT16 *pFeatureData16=(UINT16 *) pFeaturePara; + UINT32 *pFeatureReturnPara32=(UINT32 *) pFeaturePara; + UINT32 *pFeatureData32=(UINT32 *) pFeaturePara; + //UINT32 **ppFeatureData=(UINT32 **) pFeaturePara; + unsigned long long *feature_data=(unsigned long long *) pFeaturePara; + //unsigned long long *feature_return_para=(unsigned long long *) pFeaturePara; + //UINT32 SP0A20SensorRegNumber; + //UINT32 i; + MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData=(MSDK_SENSOR_CONFIG_STRUCT *) pFeaturePara; + MSDK_SENSOR_REG_INFO_STRUCT *pSensorRegData=(MSDK_SENSOR_REG_INFO_STRUCT *) pFeaturePara; + + RETAILMSG(1, (_T("gaiyang SP0A20FeatureControl FeatureId=%d\r\n"), FeatureId)); + + switch (FeatureId) + { + case SENSOR_FEATURE_GET_RESOLUTION: + *pFeatureReturnPara16++=IMAGE_SENSOR_FULL_WIDTH; + *pFeatureReturnPara16=IMAGE_SENSOR_FULL_HEIGHT; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_GET_PERIOD: + *pFeatureReturnPara16++=(VGA_PERIOD_PIXEL_NUMS)+SP0A20_dummy_pixels; + *pFeatureReturnPara16=(VGA_PERIOD_LINE_NUMS)+SP0A20_dummy_lines; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: + *pFeatureReturnPara32 = SP0A20_g_fPV_PCLK; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_SET_ESHUTTER: + break; + case SENSOR_FEATURE_SET_NIGHTMODE: + //SP0A20NightMode((BOOL) *pFeatureData16); + break; + case SENSOR_FEATURE_SET_GAIN: + case SENSOR_FEATURE_SET_FLASHLIGHT: + break; + case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: + SP0A20_isp_master_clock=*pFeatureData32; + break; + case SENSOR_FEATURE_SET_REGISTER: + SP0A20_write_cmos_sensor(pSensorRegData->RegAddr, pSensorRegData->RegData); + break; + case SENSOR_FEATURE_GET_REGISTER: + pSensorRegData->RegData = SP0A20_read_cmos_sensor(pSensorRegData->RegAddr); + break; + case SENSOR_FEATURE_GET_CONFIG_PARA: + memcpy(pSensorConfigData, &SP0A20SensorConfigData, sizeof(MSDK_SENSOR_CONFIG_STRUCT)); + *pFeatureParaLen=sizeof(MSDK_SENSOR_CONFIG_STRUCT); + break; + case SENSOR_FEATURE_SET_CCT_REGISTER: + case SENSOR_FEATURE_GET_CCT_REGISTER: + case SENSOR_FEATURE_SET_ENG_REGISTER: + case SENSOR_FEATURE_GET_ENG_REGISTER: + case SENSOR_FEATURE_GET_REGISTER_DEFAULT: + + case SENSOR_FEATURE_CAMERA_PARA_TO_SENSOR: + case SENSOR_FEATURE_SENSOR_TO_CAMERA_PARA: + case SENSOR_FEATURE_GET_GROUP_COUNT: + case SENSOR_FEATURE_GET_GROUP_INFO: + case SENSOR_FEATURE_GET_ITEM_INFO: + case SENSOR_FEATURE_SET_ITEM_INFO: + case SENSOR_FEATURE_GET_ENG_INFO: + break; + case SENSOR_FEATURE_GET_LENS_DRIVER_ID: + // get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE + // if EEPROM does not exist in camera module. + *pFeatureReturnPara32=LENS_DRIVER_ID_DO_NOT_CARE; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_SET_YUV_CMD: + SP0A20YUVSensorSetting((FEATURE_ID)*feature_data, *(feature_data+1)); + break; + case SENSOR_FEATURE_SET_VIDEO_MODE: // lanking + SP0A20YUVSetVideoMode(*feature_data); + break; + case SENSOR_FEATURE_CHECK_SENSOR_ID: + SP0A20GetSensorID(pFeatureData32); + break; +/* case SENSOR_FEATURE_GET_EXIF_INFO: + SP0A20GetExifInfo((uintptr_t)*feature_data); + break; + */ + case SENSOR_FEATURE_SET_TEST_PATTERN: + SP0A20SetTestPatternMode((BOOL)*feature_data); + break; + case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE://for factory mode auto testing + *pFeatureReturnPara32= SP0A20_TEST_PATTERN_CHECKSUM; + *pFeatureParaLen=4; + break; + case SENSOR_FEATURE_GET_TRIGGER_FLASHLIGHT_INFO: + printk("[SP0A20] SENSOR_FEATURE_GET_TRIGGER_FLASHLIGHT_INFO\n"); + SP0A20_MIPI_GetYUVSensorBV(pFeatureData32); + break; + default: + break; + } + +return ERROR_NONE; +} /* SP0A20FeatureControl() */ + + +SENSOR_FUNCTION_STRUCT SensorFuncSP0A20YUV= +{ + SP0A20Open, + SP0A20GetInfo, + SP0A20GetResolution, + SP0A20FeatureControl, + SP0A20Control, + SP0A20Close +}; + + +UINT32 SP0A20_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) +{ + /* To Do : Check Sensor status here */ + if (pfFunc!=NULL) + *pfFunc=&SensorFuncSP0A20YUV; + return ERROR_NONE; +} /* SensorInit() */ diff --git a/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/sp0a20_yuv_Sensor.h b/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/sp0a20_yuv_Sensor.h new file mode 100755 index 0000000000000000000000000000000000000000..7e049b31b2c05df453d278a96e7576dc7296a439 --- /dev/null +++ b/drivers/misc/mediatek/imgsensor/src/mt6755/sp0a20_mipi_yuv/sp0a20_yuv_Sensor.h @@ -0,0 +1,166 @@ +/***************************************************************************** + * Copyright Statement: + * -------------------- + * This software is protected by Copyright and the information contained + * herein is confidential. The software may not be copied and the information + * contained herein may not be used or disclosed except with the written + * permission of MediaTek Inc. (C) 2005 + * + * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO + * NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S + * SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. + * + * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE + * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE + * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF + * LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND + * RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER + * THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). + * + *****************************************************************************/ + +/***************************************************************************** + * + * Filename: + * --------- + * gc0310mipi_yuv_Sensor.h + * + * Project: + * -------- + * MAUI + * + * Description: + * ------------ + * Image sensor driver declare and macro define in the header file. + * + * Author: + * ------- + * Mormo + * + *============================================================= + * HISTORY + * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! + *------------------------------------------------------------------------------ + * $Log$ + * 2011/10/25 Firsty Released By Mormo; + * + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! + *============================================================= + ******************************************************************************/ + +#ifndef __SP0A20_SENSOR_H +#define __SP0A20_SENSOR_H + + + + //------------------------Engineer mode--------------------------------- +#define FACTORY_START_ADDR 0 +#define ENGINEER_START_ADDR 10 + + typedef enum group_enum { + PRE_GAIN=0, + CMMCLK_CURRENT, + FRAME_RATE_LIMITATION, + REGISTER_EDITOR, + GROUP_TOTAL_NUMS + } FACTORY_REGISTER_INDEX; + + typedef enum register_index { + SENSOR_BASEGAIN=FACTORY_START_ADDR, + PRE_GAIN_R_INDEX, + PRE_GAIN_Gr_INDEX, + PRE_GAIN_Gb_INDEX, + PRE_GAIN_B_INDEX, + FACTORY_END_ADDR + } CCT_REGISTER_INDEX; + +typedef enum engineer_index +{ + CMMCLK_CURRENT_INDEX=ENGINEER_START_ADDR, + ENGINEER_END +} FACTORY_ENGINEER_INDEX; + +//------------------------Engineer mode--------------------------------- +typedef struct { + SENSOR_REG_STRUCT Reg[ENGINEER_END]; + SENSOR_REG_STRUCT CCT[FACTORY_END_ADDR]; +} SENSOR_DATA_STRUCT,*PSENSOR_DATA_STRUCT; + + + +#define VGA_PERIOD_PIXEL_NUMS 784 +#define VGA_PERIOD_LINE_NUMS 510 + +#define IMAGE_SENSOR_VGA_GRAB_PIXELS 0 +#define IMAGE_SENSOR_VGA_GRAB_LINES 1 + +#define IMAGE_SENSOR_VGA_WIDTH (640) +#define IMAGE_SENSOR_VGA_HEIGHT (480) + +#define IMAGE_SENSOR_PV_WIDTH (IMAGE_SENSOR_VGA_WIDTH - 8) +#define IMAGE_SENSOR_PV_HEIGHT (IMAGE_SENSOR_VGA_HEIGHT - 6) + +#define IMAGE_SENSOR_FULL_WIDTH (IMAGE_SENSOR_VGA_WIDTH - 8) +#define IMAGE_SENSOR_FULL_HEIGHT (IMAGE_SENSOR_VGA_HEIGHT - 6) + +#define SP0A20_WRITE_ID 0x42 +#define SP0A20_READ_ID 0x43 + + +struct SP0A20_Sensor_Struct +{ + struct i2c_client *i2c_clit; + MSDK_SENSOR_CONFIG_STRUCT cfg_data; + SENSOR_DATA_STRUCT eng; /* engineer mode */ + MSDK_SENSOR_ENG_INFO_STRUCT eng_info; + + + kal_bool sensor_night_mode; + kal_bool MPEG4_encode_mode; + + kal_uint16 dummy_pixels; + kal_uint16 dummy_lines; + kal_uint16 extra_exposure_lines; + kal_uint16 exposure_lines; + + kal_bool MODE_CAPTURE; + kal_uint16 iBackupExtraExp; + + + + kal_uint32 fPV_PCLK; //26000000; + kal_uint16 iPV_Pixels_Per_Line; + + kal_bool bNight_mode; // to distinguish night mode or auto mode, default: auto mode setting + kal_bool bBanding_value; // to distinguish between 50HZ and 60HZ. + kal_uint8 u8Wb_value; + kal_uint8 u8Effect_value; + kal_uint8 u8Ev_value; +}; + + +UINT32 GC0310MIPIOpen(void); +UINT32 GC0310MIPIControl(MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow, MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData); +UINT32 GC0310MIPIFeatureControl(MSDK_SENSOR_FEATURE_ENUM FeatureId, UINT8 *pFeaturePara,UINT32 *pFeatureParaLen); +UINT32 GC0310MIPIGetInfo(MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_INFO_STRUCT *pSensorInfo, MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData); +UINT32 GC0310MIPIGetResolution(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *pSensorResolution); +UINT32 GC0310MIPIClose(void); + +#endif /* __SENSOR_H */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/fliper.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/fliper.h new file mode 100644 index 0000000000000000000000000000000000000000..28688ddbb32a666362d118aa16f1f5652359288e --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/fliper.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LPM_MAX_BW 5200 +#define HPM_MAX_BW 7200 +#define THRESHOLD_SCALE 64 + +#define CG_LPM_BW_THRESHOLD 2000 +#define CG_HPM_BW_THRESHOLD 1700 +#define TOTAL_LPM_BW_THRESHOLD 4680 +#define TOTAL_HPM_BW_THRESHOLD 3600 +#define BW_THRESHOLD_MAX 9000 +#define BW_THRESHOLD_MIN 100 +#define CG_DEFAULT_LPM 2000 +#define CG_DEFAULT_HPM 1700 +#define CG_JUST_MAKE_LPM 3000 +#define CG_JUST_MAKE_HPM 2700 +#define CG_PERFORMANCE_LPM 1800 +#define CG_PERFORMANCE_HPM 1500 +enum { + Default = 0, + Low_Power_Mode = 1, + Just_Make_Mode = 2, + Performance_Mode = 3, +}; + + +void enable_cg_fliper(int); +void enable_total_fliper(int); +int cg_set_threshold(int, int); +int total_set_threshold(int, int); +int cg_restore_threshold(void); +int total_restore_threshold(void); + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/con_sce_lpddr3_1800.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/con_sce_lpddr3_1800.h new file mode 100644 index 0000000000000000000000000000000000000000..9c64d47e52d58db9f55173b45c86cdcddca17b5a --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/con_sce_lpddr3_1800.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/* video snap shot*/ +X_CON_SCE(CON_SCE_VSS, 0x7f807043, 0xa0a070da, 0x80807043, +0x07007a49, 0x2015604f, 0xa0a07044, 0xa0a07044) + +/* MD_STDALN */ +X_CON_SCE(CON_SCE_MD_STDALN, 0x7f807C45, 0xa0a070d6, 0x80807043, +0x40007a49, 0x4040604f, 0xa0a0705a, 0xa0a0705a) + +/* VPWFD*/ +X_CON_SCE(CON_SCE_VPWFD, 0x7f807C46, 0xa0a070db, 0x80807043, +0x00007a49, 0x4040604f, 0xa0a07044, 0xa0a07044) + +/* normal */ +X_CON_SCE(CON_SCE_NORMAL, 0x7f807C46, 0xa0a070d5, 0x80807043, +0x40007a49, 0x4040604f, 0xa0a0704b, 0xa0a0704b) + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/emi_bwl.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/emi_bwl.h new file mode 100644 index 0000000000000000000000000000000000000000..e194f54d91e5fb5bc9bb9f26446260d7e4c4b298 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/emi_bwl.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_EMI_BW_LIMITER__ +#define __MT_EMI_BW_LIMITER__ + +/* + * Define EMI hardware registers. + */ + +#define EMI_CONA (EMI_BASE_ADDR + 0x0000) +#define EMI_CONB (EMI_BASE_ADDR + 0x0008) +#define EMI_CONC (EMI_BASE_ADDR + 0x0010) +#define EMI_COND (EMI_BASE_ADDR + 0x0018) +#define EMI_CONE (EMI_BASE_ADDR + 0x0020) +#define EMI_CONF (EMI_BASE_ADDR + 0x0028) +#define EMI_CONG (EMI_BASE_ADDR + 0x0030) +#define EMI_CONH (EMI_BASE_ADDR + 0x0038) +#define EMI_TESTB (EMI_BASE_ADDR + 0x0E8) +#define EMI_TESTD (EMI_BASE_ADDR + 0x0F8) +#define EMI_ARBA (EMI_BASE_ADDR + 0x0100) +#define EMI_ARBB (EMI_BASE_ADDR + 0x0108) +#define EMI_ARBC (EMI_BASE_ADDR + 0x0110) +#define EMI_ARBD (EMI_BASE_ADDR + 0x0118) +#define EMI_ARBE (EMI_BASE_ADDR + 0x0120) +#define EMI_ARBF (EMI_BASE_ADDR + 0x0128) +#define EMI_ARBG_2ND (EMI_BASE_ADDR + 0x0134) +#define EMI_ARBH (EMI_BASE_ADDR + 0x0138) +#define EMI_ARBI (EMI_BASE_ADDR + 0x0140) +#define EMI_ARBI_2ND (EMI_BASE_ADDR + 0x0144) +#define EMI_ARBJ (EMI_BASE_ADDR + 0x0148) +#define EMI_ARBJ_2ND (EMI_BASE_ADDR + 0x014C) +#define EMI_ARBK (EMI_BASE_ADDR + 0x0150) +#define EMI_ARBK_2ND (EMI_BASE_ADDR + 0x0154) +#define EMI_SLCT (EMI_BASE_ADDR + 0x0158) + +#define DRAMC_CONF1 (0x004) +#define DRAMC_LPDDR2 (0x1e0) +#define DRAMC_PADCTL4 (0x0e4) +#define DRAMC_ACTIM1 (0x1e8) +#define DRAMC_DQSCAL0 (0x1c0) + +#define DRAMC_READ(offset) ( \ + readl(IOMEM(DRAMC0_BASE + (offset)))| \ + readl(IOMEM(DDRPHY_BASE + (offset)))| \ + readl(IOMEM(DRAMC_NAO_BASE + (offset)))) + +#define DRAMC_WRITE(offset, data) do { \ + writel((unsigned int) (data), \ + (DRAMC0_BASE + (offset))); \ + writel((unsigned int) (data), \ + (DDRPHY_BASE + (offset))); \ + mt65xx_reg_sync_writel((unsigned int) (data), \ + (DRAMC_NAO_BASE + (offset))); \ +} while (0) + + + +/* + * Define constants. + */ + +/* define supported DRAM types */ +enum { + LPDDR2_1066 = 0, + LPDDR3_1800, + mDDR, +}; + +/* define concurrency scenario ID */ +enum { +#define X_CON_SCE(con_sce, arba, arbb, arbc, arbd, arbe, arbf, arbg2) con_sce, +#include "mach/con_sce_lpddr3_1800.h" +#undef X_CON_SCE + NR_CON_SCE +}; + +/* define control operation */ +enum { + ENABLE_CON_SCE = 0, + DISABLE_CON_SCE = 1 +}; + +#define EN_CON_SCE_STR "ON" +#define DIS_CON_SCE_STR "OFF" + +/* + * Define data structures. + */ + +/* define control table entry */ +struct emi_bwl_ctrl { + unsigned int ref_cnt; +}; + +/* + * Define function prototype. + */ + +extern int mtk_mem_bw_ctrl(int sce, int op); +extern int get_ddr_type(void); +extern unsigned int ucDram_Register_Read(unsigned long u4reg_addr); + +extern void __iomem *EMI_BASE_ADDR; +#endif /* !__MT_EMI_BWL_H__ */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/emi_mpu.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/emi_mpu.h new file mode 100644 index 0000000000000000000000000000000000000000..bbcf18c31ae39bfd8c735f04af77dd3aa37d36a0 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/emi_mpu.h @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_EMI_MPU_H +#define __MT_EMI_MPU_H + +#define EMI_MPUA (0x0160) +#define EMI_MPUB (0x0168) +#define EMI_MPUC (0x0170) +#define EMI_MPUD (0x0178) +#define EMI_MPUE (0x0180) +#define EMI_MPUF (0x0188) +#define EMI_MPUG (0x0190) +#define EMI_MPUH (0x0198) +#define EMI_MPUA2 (0x0260) +#define EMI_MPUB2 (0x0268) +#define EMI_MPUC2 (0x0270) +#define EMI_MPUD2 (0x0278) +#define EMI_MPUE2 (0x0280) +#define EMI_MPUF2 (0x0288) +#define EMI_MPUG2 (0x0290) +#define EMI_MPUH2 (0x0298) +#define EMI_MPUA3 (0x0360) +#define EMI_MPUB3 (0x0368) +#define EMI_MPUC3 (0x0370) +#define EMI_MPUD3 (0x0378) + +#define EMI_MPUI (0x01A0) +#define EMI_MPUI_2ND (0x01A4) +#define EMI_MPUJ (0x01A8) +#define EMI_MPUJ_2ND (0x01AC) +#define EMI_MPUK (0x01B0) +#define EMI_MPUK_2ND (0x01B4) +#define EMI_MPUL (0x01B8) +#define EMI_MPUL_2ND (0x01BC) +#define EMI_MPUI2 (0x02A0) +#define EMI_MPUI2_2ND (0x02A4) +#define EMI_MPUJ2 (0x02A8) +#define EMI_MPUJ2_2ND (0x02AC) +#define EMI_MPUK2 (0x02B0) +#define EMI_MPUK2_2ND (0x02B4) +#define EMI_MPUL2 (0x02B8) +#define EMI_MPUL2_2ND (0x02BC) +#define EMI_MPUI3 (0x03A0) +#define EMI_MPUJ3 (0x03A8) +#define EMI_MPUK3 (0x03B0) +#define EMI_MPUL3 (0x03B8) + +#define EMI_MPUM (0x01C0) +#define EMI_MPUN (0x01C8) +#define EMI_MPUO (0x01D0) +#define EMI_MPUU (0x0200) +#define EMI_MPUM2 (0x02C0) +#define EMI_MPUN2 (0x02C8) +#define EMI_MPUO2 (0x02D0) +#define EMI_MPUU2 (0x0300) + +#define EMI_MPUV (0x0208) +#define EMI_MPUW (0x0210) +#define EMI_MPUX (0x0218) +#define EMI_MPU_START (0x0160) +#define EMI_MPU_END (0x03B8) + +#define EMI_CONA (EMI_BASE_ADDR + 0x0000) +#define EMI_CONH (EMI_BASE_ADDR + 0x0038) + +#define EMI_MPUP (EMI_BASE_ADDR+0x01D8) +#define EMI_MPUQ (EMI_BASE_ADDR+0x01E0) +#define EMI_MPUR (EMI_BASE_ADDR+0x01E8) +#define EMI_MPUS (EMI_BASE_ADDR+0x01F0) +#define EMI_MPUT (EMI_BASE_ADDR+0x01F8) +#define EMI_MPUY (EMI_BASE_ADDR+0x0220) + +#define EMI_MPUP2 (EMI_BASE_ADDR+0x02D8) +#define EMI_MPUQ2 (EMI_BASE_ADDR+0x02E0) +#define EMI_MPUR2 (EMI_BASE_ADDR+0x02E8) +#define EMI_MPUY2 (EMI_BASE_ADDR+0x0320) + +#define EMI_WP_ADR (EMI_BASE_ADDR + 0x5E0) +#define EMI_WP_CTRL (EMI_BASE_ADDR + 0x5E8) +#define EMI_CHKER (EMI_BASE_ADDR + 0x5F0) +#define EMI_CHKER_TYPE (EMI_BASE_ADDR + 0x5F4) +#define EMI_CHKER_ADR (EMI_BASE_ADDR + 0x5F8) + +#define NO_PROTECTION 0 +#define SEC_RW 1 +#define SEC_RW_NSEC_R 2 +#define SEC_RW_NSEC_W 3 +#define SEC_R_NSEC_R 4 +#define FORBIDDEN 5 +#define SEC_R_NSEC_RW 6 + +#define EN_MPU_STR "ON" +#define DIS_MPU_STR "OFF" + +#define EN_WP_STR "ON" +#define DIS_WP_STR "OFF" + + +/*EMI memory protection align 64K*/ +#define EMI_MPU_ALIGNMENT 0x10000 +#define OOR_VIO 0x00000200 + +#define MAX_CHANNELS (2) +#define MAX_RANKS (2) + + +enum{ /* apmcu */ + MST_ID_APMCU_0, MST_ID_APMCU_1, + MST_ID_APMCU_2, MST_ID_APMCU_3, MST_ID_APMCU_4, + MST_ID_APMCU_5, MST_ID_APMCU_6, + MST_ID_APMCU_7, MST_ID_APMCU_8, MST_ID_APMCU_9, + MST_ID_APMCU_10, MST_ID_APMCU_11, + MST_ID_APMCU_12, MST_ID_APMCU_13, MST_ID_APMCU_14, + MST_ID_APMCU_15, MST_ID_APMCU_16, + MST_ID_APMCU_17, MST_ID_APMCU_18, MST_ID_APMCU_19, + + /* MM */ + MST_ID_MM_0, MST_ID_MM_1, MST_ID_MM_2, MST_ID_MM_3, MST_ID_MM_4, + + /* Periperal */ + MST_ID_PERI_0, MST_ID_PERI_1, + MST_ID_PERI_2, MST_ID_PERI_3, MST_ID_PERI_4, + MST_ID_PERI_5, MST_ID_PERI_6, + MST_ID_PERI_7, MST_ID_PERI_8, MST_ID_PERI_9, + MST_ID_PERI_10, MST_ID_PERI_11, + MST_ID_PERI_12, MST_ID_PERI_13, MST_ID_PERI_14, + MST_ID_PERI_15, MST_ID_PERI_16, + MST_ID_PERI_17, MST_ID_PERI_18, MST_ID_PERI_19, + MST_ID_PERI_20, MST_ID_PERI_21, + MST_ID_PERI_22, MST_ID_PERI_23, MST_ID_PERI_24, + MST_ID_PERI_25, + + /* Modem */ + MST_ID_MDMCU_0, MST_ID_MDMCU_1, MST_ID_MDMCU_2, + MST_ID_MD_L1MCU_0, MST_ID_MD_L1MCU_1, MST_ID_MD_L1MCU_2, + MST_ID_C2KMCU_0, + + /* Modem HW (2G/3G) */ + MST_ID_MDHW_0, MST_ID_MDHW_1, MST_ID_MDHW_2, + MST_ID_MDHW_3, MST_ID_MDHW_4, + MST_ID_MDHW_5, MST_ID_MDHW_6, MST_ID_MDHW_7, + MST_ID_MDHW_8, MST_ID_MDHW_9, + MST_ID_MDHW_10, MST_ID_MDHW_11, MST_ID_MDHW_12, + MST_ID_MDHW_13, MST_ID_MDHW_14, + MST_ID_MDHW_15, MST_ID_MDHW_16, MST_ID_MDHW_17, + MST_ID_MDHW_18, MST_ID_MDHW_19, + MST_ID_MDHW_20, MST_ID_MDHW_21, MST_ID_MDHW_22, + MST_ID_LTE_0, MST_ID_LTE_1, MST_ID_LTE_2, + MST_ID_LTE_3, MST_ID_LTE_4, MST_ID_LTE_5, + MST_ID_LTE_6, MST_ID_LTE_7, MST_ID_LTE_8, + MST_ID_LTE_9, MST_ID_LTE_10, MST_ID_LTE_11, + MST_ID_LTE_12, MST_ID_LTE_13, + + /* MFG */ + MST_ID_MFG_0, + + MST_INVALID, + NR_MST, +}; + +enum { + AXI_VIO_ID = 0, + AXI_ADR_CHK_EN = 16, + AXI_LOCK_CHK_EN = 17, + AXI_NON_ALIGN_CHK_EN = 18, + AXI_NON_ALIGN_CHK_MST = 20, + AXI_VIO_CLR = 24, + AXI_VIO_WR = 27, + AXI_ADR_VIO = 28, + AXI_LOCK_ISSUE = 29, + AXI_NON_ALIGN_ISSUE = 30 +}; + +#define EMI_WP_RANGE 0x0000003F +#define EMI_WP_AXI_ID 0x0000FFFF +#define EMI_WP_RW_MONITOR 0x000000C0 +#define EMI_WP_RW_DISABLE 0x00000300 +#define WP_BOTH_READ_WRITE 3 + +#define EMI_WP_RW_MONITOR_SHIFT 6 +#define EMI_WP_RW_DISABLE_SHIFT 8 +#define EMI_WP_SLVERR_SHIFT 10 +#define EMI_WP_INT_SHIFT 15 +#define EMI_WP_ENABLE_SHIFT 19 +#define EMI_WP_VIO_CLR_SHIFT 24 + + +enum { + MASTER_APMCU = 0, + MASTER_MM = 1, + MASTER_PERI, + MASTER_MDMCU, + MASTER_MDHW, + MASTER_MFG, + MASTER_ALL = 6 +}; + +/* Basic DRAM setting */ +struct basic_dram_setting { + /* Number of channels */ + unsigned channel_nr; + /* Per-channel information */ + struct { + /* Per-rank information */ + struct { + /* Does this rank exist */ + bool valid_rank; + /* Rank size - (in Gb)*/ + unsigned rank_size; + /* Number of segments */ + unsigned segment_nr; + } rank[MAX_RANKS]; + } channel[MAX_CHANNELS]; +}; + +typedef void (*emi_mpu_notifier)(u32 addr, int wr_vio); + +#define SET_ACCESS_PERMISSON(d7, d6, d5, d4, d3, d2, d1, d0) \ +(((d7) << 21) | ((d6) << 18) | ((d5) << 15) | \ +((d4) << 12) | ((d3) << 9) | ((d2) << 6) | ((d1) << 3) | (d0)) + +extern int emi_mpu_set_region_protection(unsigned long long start_addr, +unsigned long long end_addr, int region, unsigned int access_permission); +#if defined(CONFIG_MTKPASR) +extern void acquire_dram_setting(struct basic_dram_setting *pasrdpd); +#endif +extern void emi_wp_get_status(void); +extern void mt_emi_reg_write(unsigned int data, unsigned int offset); +extern unsigned int mt_emi_reg_read(unsigned int offset); +extern void mt_emi_reg_base_set(void *base); +extern void *mt_emi_reg_base_get(void); +extern int emi_mpu_get_violation_port(void); +extern phys_addr_t get_max_DRAM_size(void); +extern void __iomem *EMI_BASE_ADDR; +extern unsigned int mt_emi_reg_read(unsigned int offset); +extern void mt_emi_reg_write(unsigned int data, unsigned int offset); +extern int mt_emi_mpu_set_region_protection(unsigned long long start, +unsigned long long end, unsigned int region_permission); +#endif /* !__MT_EMI_MPU_H */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/fliper.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/fliper.h new file mode 100644 index 0000000000000000000000000000000000000000..281f83854dd070b1df756bc9a6c14a39199d339e --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/fliper.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define THRESHOLD_SCALE 64 + +#define CG_LPM_BW_THRESHOLD 2000 +#define CG_HPM_BW_THRESHOLD 1700 +#define BW_THRESHOLD_MAX 9000 +#define BW_THRESHOLD_MIN 100 +#define CG_DEFAULT_LPM 2000 +#define CG_DEFAULT_HPM 1700 +#define CG_LOW_POWER_LPM 3000 +#define CG_LOW_POWER_HPM 2700 +#define CG_JUST_MAKE_LPM 1500 +#define CG_JUST_MAKE_HPM 1200 +#define CG_PERFORMANCE_LPM 300 +#define CG_PERFORMANCE_HPM 200 +enum { + Default = 0, + Low_Power_Mode = 1, + Just_Make_Mode = 2, + Performance_Mode = 3, +}; + +int disable_cg_fliper(void); +void enable_cg_fliper(int); +void enable_total_fliper(int); +int cg_set_threshold(int, int); +int total_set_threshold(int, int); +int cg_restore_threshold(void); +int total_restore_threshold(void); +extern int dram_steps_freq(unsigned int step); diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/gpio_const.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/gpio_const.h new file mode 100644 index 0000000000000000000000000000000000000000..0ca7f63aee68bbcb183c16affe6a8db3fd952362 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/gpio_const.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _GPIO_CONST_H_ +#define _GPIO_CONST_H_ + +/* #include */ + +#define GPIO_MODE_BITS 3 +#define MAX_GPIO_MODE_PER_REG 10 +#define MAX_GPIO_REG_BITS 32 + +#if 0 +#define GPIO_BASE 0x10005000 +#define IOCFG_L_BASE 0x10002000 +#define IOCFG_B_BASE 0x10002400 +#define IOCFG_R_BASE 0x10002800 +#define IOCFG_T_BASE 0x10002C00 +#define MIPI_TX0_BASE 0x10215000 +#define MIPI_RX_ANA_CSI0_BASE 0x10217000 +#define MIPI_RX_ANA_CSI1_BASE 0x10218000 +#endif + +#define GPIO_BASE gpio_vbase.gpio_regs +#define IOCFG_BASE gpio_vbase.iocfg_regs +#define IOCFG_L_BASE_1 gpio_vbase.IOCFG_L_regs +#define IOCFG_B_BASE_1 gpio_vbase.IOCFG_B_regs +#define IOCFG_R_BASE_1 gpio_vbase.IOCFG_R_regs +#define IOCFG_T_BASE_1 gpio_vbase.IOCFG_T_regs +#define MIPI_TX0_BASE_1 gpio_vbase.MIPI_TX0_regs +#define MIPI_RX_ANA_CSI0_BASE_1 gpio_vbase.MIPI_RX_CSI0_regs +#define MIPI_RX_ANA_CSI1_BASE_1 gpio_vbase.MIPI_RX_CSI1_regs + +struct mt_gpio_vbase { + void __iomem *gpio_regs; + void __iomem *iocfg_regs; + void __iomem *IOCFG_L_regs; + void __iomem *IOCFG_B_regs; + void __iomem *IOCFG_R_regs; + void __iomem *IOCFG_T_regs; + void __iomem *MIPI_TX0_regs; + void __iomem *MIPI_RX_CSI0_regs; + void __iomem *MIPI_RX_CSI1_regs; +}; + +extern struct mt_gpio_vbase gpio_vbase; + +/****************************************************************************** +* Enumeration for GPIO pin +******************************************************************************/ +typedef enum GPIO_PIN { + GPIO_UNSUPPORTED = -1, + + GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, + GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15, + GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, + GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31, + GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39, + GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47, + GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55, + GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63, + GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71, + GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79, + GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87, + GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95, + GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103, + GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111, + GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119, + GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127, + GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135, + GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143, + GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151, + GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159, + GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167, + GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175, + GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182, GPIO183, + GPIO184, GPIO185, GPIO186, GPIO187, GPIO188, GPIO189, MT_GPIO_BASE_MAX +} GPIO_PIN; +#define MT_GPIO_BASE_START GPIO0 +#define MT_GPIO_EXT_START MT_GPIO_BASE_MAX + +typedef enum GPIO_PIN_EXT { + MT_GPIO_EXT_MAX = MT_GPIO_EXT_START +} GPIO_PIN_EXT; +#define MT_GPIO_MAX_PIN MT_GPIO_EXT_MAX + +#endif /* _GPIO_CONST_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/irqs.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/irqs.h new file mode 100644 index 0000000000000000000000000000000000000000..781f4df6166eea11a0820d7247c7ee9c37969b63 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/irqs.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __IRQS_H +#define __IRQS_H + +#define GIC_PRIVATE_SIGNALS (32) +#define NR_GIC_SGI (16) +#define NR_GIC_PPI (16) +#define GIC_PPI_OFFSET (27) +#define MT_NR_PPI (5) +#define MT_NR_SPI (256) +#define NR_MT_IRQ_LINE (GIC_PPI_OFFSET + MT_NR_PPI + MT_NR_SPI) + +#ifdef NR_IRQS +#undef NR_IRQS +#endif +#define NR_IRQS (NR_MT_IRQ_LINE+220) + +#define GIC_PPI_GLOBAL_TIMER (GIC_PPI_OFFSET + 0) +#define GIC_PPI_LEGACY_FIQ (GIC_PPI_OFFSET + 1) +#define GIC_PPI_PRIVATE_TIMER (GIC_PPI_OFFSET + 2) +#define GIC_PPI_WATCHDOG_TIMER (GIC_PPI_OFFSET + 3) +#define GIC_PPI_LEGACY_IRQ (GIC_PPI_OFFSET + 4) + +#define MT_BTIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 50) +#define MT_DMA_BTIF_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 71) +#define MT_DMA_BTIF_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 72) + +#define FIQ_START 0 +#define CPU_BRINGUP_SGI 1 +#define FIQ_SMP_CALL_SGI 13 +#define FIQ_DBG_SGI 14 + +#define MT_EDGE_SENSITIVE 0 +#define MT_LEVEL_SENSITIVE 1 +#define MT_POLARITY_LOW 0 +#define MT_POLARITY_HIGH 1 + +#ifndef __ASSEMBLY__ +typedef void (*fiq_isr_handler)(void *arg, void *regs, void *svc_sp); + +int request_fiq(int irq, fiq_isr_handler handler, + unsigned long irq_flags, void *arg); +#endif + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt6353_hw.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt6353_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..37ed3f48884867afa71bccef1b6305e8a2fec368 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt6353_hw.h @@ -0,0 +1,12933 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _MT_PMIC_UPMU_HW_MT6353_H_ +#define _MT_PMIC_UPMU_HW_MT6353_H_ + +/*MT6353*/ +#define MT6353_PMIC_REG_BASE (0x0000) + +#define MT6353_STRUP_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0000)) +#define MT6353_STRUP_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0002)) +#define MT6353_STRUP_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0004)) +#define MT6353_STRUP_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0006)) +#define MT6353_STRUP_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0008)) +#define MT6353_STRUP_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x000A)) +#define MT6353_STRUP_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x000C)) +#define MT6353_STRUP_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x000E)) +#define MT6353_STRUP_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0010)) +#define MT6353_STRUP_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0012)) +#define MT6353_STRUP_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0014)) +#define MT6353_STRUP_CON11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0016)) +#define MT6353_STRUP_CON12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0018)) +#define MT6353_STRUP_CON13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x001A)) +#define MT6353_STRUP_CON14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x001C)) +#define MT6353_STRUP_CON15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x001E)) +#define MT6353_STRUP_CON16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0020)) +#define MT6353_STRUP_CON17 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0022)) +#define MT6353_STRUP_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0024)) +#define MT6353_STRUP_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0026)) +#define MT6353_TYPE_C_PHY_RG_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0100)) +#define MT6353_TYPE_C_PHY_RG_CC_RESERVE_CSR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0102)) +#define MT6353_TYPE_C_VCMP_CTRL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0104)) +#define MT6353_TYPE_C_CTRL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0106)) +#define MT6353_TYPE_C_CC_SW_CTRL ((unsigned int)(MT6353_PMIC_REG_BASE+0x010a)) +#define MT6353_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL ((unsigned int)(MT6353_PMIC_REG_BASE+0x010c)) +#define MT6353_TYPE_C_CC_VOL_DEBOUCE_CNT_VAL ((unsigned int)(MT6353_PMIC_REG_BASE+0x010e)) +#define MT6353_TYPE_C_DRP_SRC_CNT_VAL_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0110)) +#define MT6353_TYPE_C_DRP_SNK_CNT_VAL_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0114)) +#define MT6353_TYPE_C_DRP_TRY_CNT_VAL_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0118)) +#define MT6353_TYPE_C_DRP_TRY_WAIT_CNT_VAL_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x011c)) +#define MT6353_TYPE_C_DRP_TRY_WAIT_CNT_VAL_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x011e)) +#define MT6353_TYPE_C_CC_SRC_DEFAULT_DAC_VAL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0120)) +#define MT6353_TYPE_C_CC_SRC_15_DAC_VAL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0122)) +#define MT6353_TYPE_C_CC_SRC_30_DAC_VAL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0124)) +#define MT6353_TYPE_C_CC_SNK_DAC_VAL_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0128)) +#define MT6353_TYPE_C_CC_SNK_DAC_VAL_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x012a)) +#define MT6353_TYPE_C_INTR_EN_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0130)) +#define MT6353_TYPE_C_INTR_EN_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0134)) +#define MT6353_TYPE_C_INTR_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0138)) +#define MT6353_TYPE_C_INTR_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x013C)) +#define MT6353_TYPE_C_CC_STATUS ((unsigned int)(MT6353_PMIC_REG_BASE+0x0140)) +#define MT6353_TYPE_C_PWR_STATUS ((unsigned int)(MT6353_PMIC_REG_BASE+0x0142)) +#define MT6353_TYPE_C_PHY_RG_CC1_RESISTENCE_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0144)) +#define MT6353_TYPE_C_PHY_RG_CC1_RESISTENCE_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0146)) +#define MT6353_TYPE_C_PHY_RG_CC2_RESISTENCE_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0148)) +#define MT6353_TYPE_C_PHY_RG_CC2_RESISTENCE_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x014a)) +#define MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE ((unsigned int)(MT6353_PMIC_REG_BASE+0x0160)) +#define MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0164)) +#define MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0166)) +#define MT6353_TYPE_C_CC_DAC_CALI_CTRL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0170)) +#define MT6353_TYPE_C_CC_DAC_CALI_RESULT ((unsigned int)(MT6353_PMIC_REG_BASE+0x0172)) +#define MT6353_TYPE_C_DEBUG_PORT_SELECT_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0180)) +#define MT6353_TYPE_C_DEBUG_PORT_SELECT_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0182)) +#define MT6353_TYPE_C_DEBUG_MODE_SELECT ((unsigned int)(MT6353_PMIC_REG_BASE+0x0184)) +#define MT6353_TYPE_C_DEBUG_OUT_READ_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0188)) +#define MT6353_TYPE_C_DEBUG_OUT_READ_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x018a)) +#define MT6353_HWCID ((unsigned int)(MT6353_PMIC_REG_BASE+0x0200)) +#define MT6353_SWCID ((unsigned int)(MT6353_PMIC_REG_BASE+0x0202)) +#define MT6353_TOP_CON ((unsigned int)(MT6353_PMIC_REG_BASE+0x0204)) +#define MT6353_TEST_OUT ((unsigned int)(MT6353_PMIC_REG_BASE+0x0206)) +#define MT6353_TEST_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0208)) +#define MT6353_TEST_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x020A)) +#define MT6353_TESTMODE_SW ((unsigned int)(MT6353_PMIC_REG_BASE+0x020C)) +#define MT6353_EN_STATUS1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x020E)) +#define MT6353_EN_STATUS2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0210)) +#define MT6353_OCSTATUS1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0212)) +#define MT6353_OCSTATUS2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0214)) +#define MT6353_PGDEBSTATUS0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0216)) +#define MT6353_PGSTATUS0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0218)) +#define MT6353_THERMALSTATUS ((unsigned int)(MT6353_PMIC_REG_BASE+0x021A)) +#define MT6353_TOPSTATUS ((unsigned int)(MT6353_PMIC_REG_BASE+0x021C)) +#define MT6353_TDSEL_CON ((unsigned int)(MT6353_PMIC_REG_BASE+0x021E)) +#define MT6353_RDSEL_CON ((unsigned int)(MT6353_PMIC_REG_BASE+0x0220)) +#define MT6353_SMT_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0222)) +#define MT6353_SMT_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0224)) +#define MT6353_SMT_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0226)) +#define MT6353_DRV_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0228)) +#define MT6353_DRV_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x022A)) +#define MT6353_DRV_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x022C)) +#define MT6353_DRV_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x022E)) +#define MT6353_TOP_STATUS ((unsigned int)(MT6353_PMIC_REG_BASE+0x0230)) +#define MT6353_TOP_STATUS_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0232)) +#define MT6353_TOP_STATUS_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0234)) +#define MT6353_CLK_RSV_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0236)) +#define MT6353_CLK_BUCK_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0238)) +#define MT6353_CLK_BUCK_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x023A)) +#define MT6353_CLK_BUCK_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x023C)) +#define MT6353_CLK_BUCK_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x023E)) +#define MT6353_CLK_BUCK_CON1_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0240)) +#define MT6353_CLK_BUCK_CON1_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0242)) +#define MT6353_TOP_CLKSQ ((unsigned int)(MT6353_PMIC_REG_BASE+0x0244)) +#define MT6353_TOP_CLKSQ_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0246)) +#define MT6353_TOP_CLKSQ_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0248)) +#define MT6353_TOP_CLKSQ_RTC ((unsigned int)(MT6353_PMIC_REG_BASE+0x024A)) +#define MT6353_TOP_CLKSQ_RTC_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x024C)) +#define MT6353_TOP_CLKSQ_RTC_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x024E)) +#define MT6353_TOP_CLK_TRIM ((unsigned int)(MT6353_PMIC_REG_BASE+0x0250)) +#define MT6353_CLK_CKROOTTST_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0252)) +#define MT6353_CLK_CKROOTTST_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0254)) +#define MT6353_CLK_PDN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0256)) +#define MT6353_CLK_PDN_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0258)) +#define MT6353_CLK_PDN_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x025A)) +#define MT6353_CLK_PDN_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x025C)) +#define MT6353_CLK_PDN_CON1_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x025E)) +#define MT6353_CLK_PDN_CON1_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0260)) +#define MT6353_CLK_SEL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0262)) +#define MT6353_CLK_SEL_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0264)) +#define MT6353_CLK_SEL_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0266)) +#define MT6353_CLK_SEL_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0268)) +#define MT6353_CLK_SEL_CON1_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x026A)) +#define MT6353_CLK_SEL_CON1_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x026C)) +#define MT6353_CLK_CKPDN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x026E)) +#define MT6353_CLK_CKPDN_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0270)) +#define MT6353_CLK_CKPDN_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0272)) +#define MT6353_CLK_CKPDN_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0274)) +#define MT6353_CLK_CKPDN_CON1_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0276)) +#define MT6353_CLK_CKPDN_CON1_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0278)) +#define MT6353_CLK_CKPDN_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x027A)) +#define MT6353_CLK_CKPDN_CON2_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x027C)) +#define MT6353_CLK_CKPDN_CON2_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x027E)) +#define MT6353_CLK_CKPDN_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0280)) +#define MT6353_CLK_CKPDN_CON3_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0282)) +#define MT6353_CLK_CKPDN_CON3_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0284)) +#define MT6353_CLK_CKPDN_HWEN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0286)) +#define MT6353_CLK_CKPDN_HWEN_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0288)) +#define MT6353_CLK_CKPDN_HWEN_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x028A)) +#define MT6353_CLK_CKSEL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x028C)) +#define MT6353_CLK_CKSEL_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x028E)) +#define MT6353_CLK_CKSEL_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0290)) +#define MT6353_CLK_CKDIVSEL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0292)) +#define MT6353_CLK_CKDIVSEL_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0294)) +#define MT6353_CLK_CKDIVSEL_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0296)) +#define MT6353_CLK_CKTSTSEL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0298)) +#define MT6353_TOP_RST_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x029A)) +#define MT6353_TOP_RST_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x029C)) +#define MT6353_TOP_RST_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x029E)) +#define MT6353_TOP_RST_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02A0)) +#define MT6353_TOP_RST_CON1_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x02A2)) +#define MT6353_TOP_RST_CON1_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x02A4)) +#define MT6353_TOP_RST_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02A6)) +#define MT6353_TOP_RST_MISC ((unsigned int)(MT6353_PMIC_REG_BASE+0x02A8)) +#define MT6353_TOP_RST_MISC_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x02AA)) +#define MT6353_TOP_RST_MISC_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x02AC)) +#define MT6353_TOP_RST_STATUS ((unsigned int)(MT6353_PMIC_REG_BASE+0x02AE)) +#define MT6353_TOP_RST_STATUS_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x02B0)) +#define MT6353_TOP_RST_STATUS_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x02B2)) +#define MT6353_TOP_RST_RSV_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02B4)) +#define MT6353_TOP_RST_RSV_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02B6)) +#define MT6353_INT_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02B8)) +#define MT6353_INT_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x02BA)) +#define MT6353_INT_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x02BC)) +#define MT6353_INT_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02BE)) +#define MT6353_INT_CON1_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x02C0)) +#define MT6353_INT_CON1_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x02C2)) +#define MT6353_INT_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02C4)) +#define MT6353_INT_CON2_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x02C6)) +#define MT6353_INT_CON2_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x02C8)) +#define MT6353_INT_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02CA)) +#define MT6353_INT_CON3_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x02CC)) +#define MT6353_INT_CON3_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x02CE)) +#define MT6353_INT_MISC_CON ((unsigned int)(MT6353_PMIC_REG_BASE+0x02D0)) +#define MT6353_INT_MISC_CON_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x02D2)) +#define MT6353_INT_MISC_CON_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x02D4)) +#define MT6353_INT_STATUS0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02D6)) +#define MT6353_INT_STATUS1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02D8)) +#define MT6353_INT_STATUS2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02DA)) +#define MT6353_INT_STATUS3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02DC)) +#define MT6353_OC_GEAR_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02DE)) +#define MT6353_SPK_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02E0)) +#define MT6353_SPK_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02E2)) +#define MT6353_SPK_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02E4)) +#define MT6353_SPK_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02E6)) +#define MT6353_SPK_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02E8)) +#define MT6353_SPK_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02EA)) +#define MT6353_SPK_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02EC)) +#define MT6353_SPK_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02EE)) +#define MT6353_SPK_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02F0)) +#define MT6353_SPK_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02F2)) +#define MT6353_SPK_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02F4)) +#define MT6353_SPK_CON11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02F6)) +#define MT6353_SPK_CON12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02F8)) +#define MT6353_SPK_CON13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02FA)) +#define MT6353_SPK_CON14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02FC)) +#define MT6353_SPK_CON15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x02FE)) +#define MT6353_SPK_CON16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0300)) +#define MT6353_SPK_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0302)) +#define MT6353_SPK_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0304)) +#define MT6353_SPK_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0306)) +#define MT6353_FQMTR_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0308)) +#define MT6353_FQMTR_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x030A)) +#define MT6353_FQMTR_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x030C)) +#define MT6353_ISINK_ANA_CON_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x030E)) +#define MT6353_ISINK0_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0310)) +#define MT6353_ISINK0_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0312)) +#define MT6353_ISINK0_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0314)) +#define MT6353_ISINK0_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0316)) +#define MT6353_ISINK1_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0318)) +#define MT6353_ISINK1_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x031A)) +#define MT6353_ISINK1_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x031C)) +#define MT6353_ISINK1_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x031E)) +#define MT6353_ISINK_ANA1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0320)) +#define MT6353_ISINK_PHASE_DLY ((unsigned int)(MT6353_PMIC_REG_BASE+0x0322)) +#define MT6353_ISINK_SFSTR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0324)) +#define MT6353_ISINK_EN_CTRL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0326)) +#define MT6353_ISINK_MODE_CTRL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0328)) +#define MT6353_ISINK_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x032A)) +#define MT6353_ISINK2_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x032C)) +#define MT6353_ISINK3_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x032E)) +#define MT6353_ISINK_PHASE_DLY_SMPL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0330)) +#define MT6353_ISINK_EN_CTRL_SMPL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0332)) +#define MT6353_CHRIND_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0334)) +#define MT6353_CHRIND_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0336)) +#define MT6353_CHRIND_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0338)) +#define MT6353_CHRIND_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x033A)) +#define MT6353_CHRIND_EN_CTRL ((unsigned int)(MT6353_PMIC_REG_BASE+0x033C)) +#define MT6353_RG_SPI_CON ((unsigned int)(MT6353_PMIC_REG_BASE+0x033E)) +#define MT6353_DEW_DIO_EN ((unsigned int)(MT6353_PMIC_REG_BASE+0x0340)) +#define MT6353_DEW_READ_TEST ((unsigned int)(MT6353_PMIC_REG_BASE+0x0342)) +#define MT6353_DEW_WRITE_TEST ((unsigned int)(MT6353_PMIC_REG_BASE+0x0344)) +#define MT6353_DEW_CRC_SWRST ((unsigned int)(MT6353_PMIC_REG_BASE+0x0346)) +#define MT6353_DEW_CRC_EN ((unsigned int)(MT6353_PMIC_REG_BASE+0x0348)) +#define MT6353_DEW_CRC_VAL ((unsigned int)(MT6353_PMIC_REG_BASE+0x034A)) +#define MT6353_DEW_DBG_MON_SEL ((unsigned int)(MT6353_PMIC_REG_BASE+0x034C)) +#define MT6353_DEW_CIPHER_KEY_SEL ((unsigned int)(MT6353_PMIC_REG_BASE+0x034E)) +#define MT6353_DEW_CIPHER_IV_SEL ((unsigned int)(MT6353_PMIC_REG_BASE+0x0350)) +#define MT6353_DEW_CIPHER_EN ((unsigned int)(MT6353_PMIC_REG_BASE+0x0352)) +#define MT6353_DEW_CIPHER_RDY ((unsigned int)(MT6353_PMIC_REG_BASE+0x0354)) +#define MT6353_DEW_CIPHER_MODE ((unsigned int)(MT6353_PMIC_REG_BASE+0x0356)) +#define MT6353_DEW_CIPHER_SWRST ((unsigned int)(MT6353_PMIC_REG_BASE+0x0358)) +#define MT6353_DEW_RDDMY_NO ((unsigned int)(MT6353_PMIC_REG_BASE+0x035A)) +#define MT6353_INT_TYPE_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x035C)) +#define MT6353_INT_TYPE_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x035E)) +#define MT6353_INT_TYPE_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0360)) +#define MT6353_INT_TYPE_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0362)) +#define MT6353_INT_TYPE_CON1_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0364)) +#define MT6353_INT_TYPE_CON1_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0366)) +#define MT6353_INT_TYPE_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0368)) +#define MT6353_INT_TYPE_CON2_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x036A)) +#define MT6353_INT_TYPE_CON2_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x036C)) +#define MT6353_INT_TYPE_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x036E)) +#define MT6353_INT_TYPE_CON3_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0370)) +#define MT6353_INT_TYPE_CON3_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0372)) +#define MT6353_INT_STA ((unsigned int)(MT6353_PMIC_REG_BASE+0x0374)) +#define MT6353_BUCK_ALL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0400)) +#define MT6353_BUCK_ALL_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0402)) +#define MT6353_BUCK_ALL_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0404)) +#define MT6353_BUCK_ALL_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0406)) +#define MT6353_BUCK_ALL_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0408)) +#define MT6353_BUCK_ALL_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x040A)) +#define MT6353_BUCK_DLC_VPA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x040C)) +#define MT6353_BUCK_DLC_VPA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x040E)) +#define MT6353_BUCK_DLC_VPA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0410)) +#define MT6353_BUCK_TRACKING_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0412)) +#define MT6353_BUCK_TRACKING_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0414)) +#define MT6353_BUCK_TRACKING_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0416)) +#define MT6353_BUCK_TRACKING_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0418)) +#define MT6353_BUCK_ANA_MON_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x041A)) +#define MT6353_BUCK_ANA_MON_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x041C)) +#define MT6353_BUCK_OC_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x041E)) +#define MT6353_BUCK_OC_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0420)) +#define MT6353_BUCK_OC_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0422)) +#define MT6353_BUCK_OC_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0424)) +#define MT6353_BUCK_OC_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0426)) +#define MT6353_BUCK_OC_VCORE_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0428)) +#define MT6353_BUCK_OC_VCORE2_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x042A)) +#define MT6353_BUCK_OC_VPROC_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x042C)) +#define MT6353_BUCK_OC_VS1_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x042E)) +#define MT6353_BUCK_OC_VPA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0430)) +#define MT6353_SMPS_TOP_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0432)) +#define MT6353_SMPS_TOP_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0434)) +#define MT6353_SMPS_TOP_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0436)) +#define MT6353_SMPS_TOP_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0438)) +#define MT6353_SMPS_TOP_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x043A)) +#define MT6353_SMPS_TOP_ANA_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x043C)) +#define MT6353_SMPS_TOP_ANA_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x043E)) +#define MT6353_VPA_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0440)) +#define MT6353_VPA_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0442)) +#define MT6353_VPA_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0444)) +#define MT6353_VPA_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0446)) +#define MT6353_VCORE_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0448)) +#define MT6353_VCORE_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x044A)) +#define MT6353_VCORE_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x044C)) +#define MT6353_VCORE_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x044E)) +#define MT6353_VCORE_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0450)) +#define MT6353_VPROC_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0452)) +#define MT6353_VPROC_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0454)) +#define MT6353_VPROC_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0456)) +#define MT6353_VPROC_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0458)) +#define MT6353_VPROC_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x045A)) +#define MT6353_VS1_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x045C)) +#define MT6353_VS1_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x045E)) +#define MT6353_VS1_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0460)) +#define MT6353_VS1_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0462)) +#define MT6353_VS1_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0464)) +#define MT6353_BUCK_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0466)) +#define MT6353_BUCK_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0468)) +#define MT6353_VCORE2_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x046A)) +#define MT6353_VCORE2_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x046C)) +#define MT6353_VCORE2_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x046E)) +#define MT6353_VCORE2_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0470)) +#define MT6353_VCORE2_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0472)) +#define MT6353_BUCK_VPROC_HWM_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0600)) +#define MT6353_BUCK_VPROC_HWM_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0602)) +#define MT6353_BUCK_VPROC_EN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0604)) +#define MT6353_BUCK_VPROC_SFCHG_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0606)) +#define MT6353_BUCK_VPROC_VOL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0608)) +#define MT6353_BUCK_VPROC_VOL_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x060A)) +#define MT6353_BUCK_VPROC_VOL_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x060C)) +#define MT6353_BUCK_VPROC_VOL_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x060E)) +#define MT6353_BUCK_VPROC_LPW_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0610)) +#define MT6353_BUCK_VS1_HWM_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0612)) +#define MT6353_BUCK_VS1_HWM_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0614)) +#define MT6353_BUCK_VS1_HWM_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0616)) +#define MT6353_BUCK_VS1_HWM_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0618)) +#define MT6353_BUCK_VS1_EN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x061A)) +#define MT6353_BUCK_VS1_SFCHG_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x061C)) +#define MT6353_BUCK_VS1_VOL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x061E)) +#define MT6353_BUCK_VS1_VOL_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0620)) +#define MT6353_BUCK_VS1_VOL_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0622)) +#define MT6353_BUCK_VS1_VOL_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0624)) +#define MT6353_BUCK_VS1_LPW_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0626)) +#define MT6353_BUCK_VCORE_HWM_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0628)) +#define MT6353_BUCK_VCORE_HWM_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x062A)) +#define MT6353_BUCK_VCORE_EN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x062C)) +#define MT6353_BUCK_VCORE_SFCHG_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x062E)) +#define MT6353_BUCK_VCORE_VOL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0630)) +#define MT6353_BUCK_VCORE_VOL_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0632)) +#define MT6353_BUCK_VCORE_VOL_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0634)) +#define MT6353_BUCK_VCORE_VOL_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0636)) +#define MT6353_BUCK_VCORE_LPW_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0638)) +#define MT6353_BUCK_VCORE2_HWM_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x063A)) +#define MT6353_BUCK_VCORE2_HWM_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x063C)) +#define MT6353_BUCK_VCORE2_EN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x063E)) +#define MT6353_BUCK_VCORE2_SFCHG_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0640)) +#define MT6353_BUCK_VCORE2_VOL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0642)) +#define MT6353_BUCK_VCORE2_VOL_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0644)) +#define MT6353_BUCK_VCORE2_VOL_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0646)) +#define MT6353_BUCK_VCORE2_VOL_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0648)) +#define MT6353_BUCK_VCORE2_LPW_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x064A)) +#define MT6353_BUCK_VPA_EN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x064C)) +#define MT6353_BUCK_VPA_SFCHG_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x064E)) +#define MT6353_BUCK_VPA_VOL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0650)) +#define MT6353_BUCK_VPA_VOL_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0652)) +#define MT6353_BUCK_VPA_LPW_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0654)) +#define MT6353_BUCK_K_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0656)) +#define MT6353_BUCK_K_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0658)) +#define MT6353_BUCK_K_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x065A)) +#define MT6353_BUCK_K_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x065C)) +#define MT6353_WDTDBG_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x065E)) +#define MT6353_WDTDBG_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0660)) +#define MT6353_WDTDBG_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0662)) +#define MT6353_WDTDBG_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0664)) +#define MT6353_ZCD_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0800)) +#define MT6353_ZCD_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0802)) +#define MT6353_ZCD_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0804)) +#define MT6353_ZCD_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0806)) +#define MT6353_ZCD_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0808)) +#define MT6353_ZCD_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x080A)) +#define MT6353_LDO_RSV_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A00)) +#define MT6353_LDO_RSV_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A02)) +#define MT6353_LDO_TOP_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A04)) +#define MT6353_LDO_VTCXO24_SW_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A06)) +#define MT6353_LDO_VXO22_SW_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A08)) +#define MT6353_LDO_OCFB0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A0A)) +#define MT6353_VRTC_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A0C)) +#define MT6353_LDO_SHARE_VCN33_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A0E)) +#define MT6353_LDO_SHARE_VCN33_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A10)) +#define MT6353_LDO3_VCN33_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A12)) +#define MT6353_LDO3_VCN33_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A14)) +#define MT6353_LDO_SHARE_VLDO28_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A16)) +#define MT6353_LDO_SHARE_VLDO28_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A18)) +#define MT6353_LDO1_VLDO28_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A1A)) +#define MT6353_LDO1_VLDO28_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A1C)) +#define MT6353_LDO_VLDO28_FAST_TRAN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A1E)) +#define MT6353_LDO_VSRAM_PROC_HWM_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A20)) +#define MT6353_LDO_VSRAM_PROC_SFCHG_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A22)) +#define MT6353_LDO_VSRAM_PROC_VOL_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A24)) +#define MT6353_LDO_VSRAM_PROC_VOL_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A26)) +#define MT6353_LDO_VSRAM_PROC_VOL_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A28)) +#define MT6353_LDO_VSRAM_PROC_VOL_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A2A)) +#define MT6353_LDO_VSRAM_PROC_LPW_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A2C)) +#define MT6353_LDO_BATON_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A2E)) +#define MT6353_LDO2_TREF_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A30)) +#define MT6353_LDO3_VTCXO28_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A32)) +#define MT6353_LDO3_VTCXO28_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A34)) +#define MT6353_LDO3_VTCXO24_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A36)) +#define MT6353_LDO3_VTCXO24_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A38)) +#define MT6353_LDO3_VXO22_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A3A)) +#define MT6353_LDO3_VXO22_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A3C)) +#define MT6353_LDO3_VRF18_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A3E)) +#define MT6353_LDO3_VRF18_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A40)) +#define MT6353_LDO3_VRF12_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A42)) +#define MT6353_LDO3_VRF12_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A44)) +#define MT6353_LDO_VRF12_FAST_TRAN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A46)) +#define MT6353_LDO3_VCN28_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A48)) +#define MT6353_LDO3_VCN28_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A4A)) +#define MT6353_LDO3_VCN18_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A4C)) +#define MT6353_LDO3_VCN18_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A4E)) +#define MT6353_LDO0_VCAMA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A50)) +#define MT6353_LDO0_VCAMA_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A52)) +#define MT6353_LDO0_VCAMIO_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A54)) +#define MT6353_LDO0_VCAMIO_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A56)) +#define MT6353_LDO0_VCAMD_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A58)) +#define MT6353_LDO0_VCAMD_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A5A)) +#define MT6353_LDO3_VAUX18_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A5C)) +#define MT6353_LDO3_VAUX18_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A5E)) +#define MT6353_LDO3_VAUD28_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A60)) +#define MT6353_LDO3_VAUD28_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A62)) +#define MT6353_LDO3_VSRAM_PROC_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A64)) +#define MT6353_LDO3_VSRAM_PROC_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A66)) +#define MT6353_LDO1_VDRAM_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A68)) +#define MT6353_LDO1_VDRAM_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A6A)) +#define MT6353_LDO_VDRAM_FAST_TRAN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A6C)) +#define MT6353_LDO1_VSIM1_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A6E)) +#define MT6353_LDO1_VSIM1_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A70)) +#define MT6353_LDO1_VSIM2_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A72)) +#define MT6353_LDO1_VSIM2_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A74)) +#define MT6353_LDO1_VIO28_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A76)) +#define MT6353_LDO1_VIO28_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A78)) +#define MT6353_LDO1_VMC_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A7A)) +#define MT6353_LDO1_VMC_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A7C)) +#define MT6353_LDO_VMC_FAST_TRAN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A7E)) +#define MT6353_LDO1_VMCH_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A80)) +#define MT6353_LDO1_VMCH_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A82)) +#define MT6353_LDO_VMCH_FAST_TRAN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A84)) +#define MT6353_LDO1_VUSB33_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A86)) +#define MT6353_LDO1_VUSB33_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A88)) +#define MT6353_LDO1_VEMC33_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A8A)) +#define MT6353_LDO1_VEMC33_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A8C)) +#define MT6353_LDO_VEMC33_FAST_TRAN_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A8E)) +#define MT6353_LDO1_VIO18_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A90)) +#define MT6353_LDO1_VIO18_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A92)) +#define MT6353_LDO0_VIBR_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A94)) +#define MT6353_LDO0_VIBR_OCFB_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A96)) +#define MT6353_ALDO_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A98)) +#define MT6353_ALDO_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A9A)) +#define MT6353_ALDO_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A9C)) +#define MT6353_ALDO_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0A9E)) +#define MT6353_ALDO_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AA0)) +#define MT6353_ALDO_ANA_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AA2)) +#define MT6353_ALDO_ANA_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AA4)) +#define MT6353_DLDO_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AA6)) +#define MT6353_DLDO_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AA8)) +#define MT6353_DLDO_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AAA)) +#define MT6353_DLDO_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AAC)) +#define MT6353_DLDO_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AAE)) +#define MT6353_DLDO_ANA_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AB0)) +#define MT6353_DLDO_ANA_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AB2)) +#define MT6353_DLDO_ANA_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AB4)) +#define MT6353_DLDO_ANA_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AB6)) +#define MT6353_DLDO_ANA_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AB8)) +#define MT6353_DLDO_ANA_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ABA)) +#define MT6353_DLDO_ANA_CON11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ABC)) +#define MT6353_DLDO_ANA_CON12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ABE)) +#define MT6353_DLDO_ANA_CON13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AC0)) +#define MT6353_DLDO_ANA_CON14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AC2)) +#define MT6353_DLDO_ANA_CON15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AC4)) +#define MT6353_DLDO_ANA_CON16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AC6)) +#define MT6353_DLDO_ANA_CON17 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AC8)) +#define MT6353_SLDO_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ACA)) +#define MT6353_SLDO_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ACC)) +#define MT6353_SLDO_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ACE)) +#define MT6353_SLDO_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AD0)) +#define MT6353_SLDO_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AD2)) +#define MT6353_SLDO_ANA_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AD4)) +#define MT6353_SLDO_ANA_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AD6)) +#define MT6353_SLDO_ANA_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0AD8)) +#define MT6353_SLDO_ANA_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ADA)) +#define MT6353_SLDO_ANA_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ADC)) +#define MT6353_SLDO_ANA_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ADE)) +#define MT6353_OTP_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C00)) +#define MT6353_OTP_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C02)) +#define MT6353_OTP_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C04)) +#define MT6353_OTP_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C06)) +#define MT6353_OTP_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C08)) +#define MT6353_OTP_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C0A)) +#define MT6353_OTP_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C0C)) +#define MT6353_OTP_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C0E)) +#define MT6353_OTP_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C10)) +#define MT6353_OTP_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C12)) +#define MT6353_OTP_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C14)) +#define MT6353_OTP_CON11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C16)) +#define MT6353_OTP_CON12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C18)) +#define MT6353_OTP_CON13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C1A)) +#define MT6353_OTP_CON14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C1C)) +#define MT6353_OTP_DOUT_0_15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C1E)) +#define MT6353_OTP_DOUT_16_31 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C20)) +#define MT6353_OTP_DOUT_32_47 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C22)) +#define MT6353_OTP_DOUT_48_63 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C24)) +#define MT6353_OTP_DOUT_64_79 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C26)) +#define MT6353_OTP_DOUT_80_95 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C28)) +#define MT6353_OTP_DOUT_96_111 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C2A)) +#define MT6353_OTP_DOUT_112_127 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C2C)) +#define MT6353_OTP_DOUT_128_143 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C2E)) +#define MT6353_OTP_DOUT_144_159 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C30)) +#define MT6353_OTP_DOUT_160_175 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C32)) +#define MT6353_OTP_DOUT_176_191 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C34)) +#define MT6353_OTP_DOUT_192_207 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C36)) +#define MT6353_OTP_DOUT_208_223 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C38)) +#define MT6353_OTP_DOUT_224_239 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C3A)) +#define MT6353_OTP_DOUT_240_255 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C3C)) +#define MT6353_OTP_DOUT_256_271 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C3E)) +#define MT6353_OTP_DOUT_272_287 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C40)) +#define MT6353_OTP_DOUT_288_303 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C42)) +#define MT6353_OTP_DOUT_304_319 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C44)) +#define MT6353_OTP_DOUT_320_335 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C46)) +#define MT6353_OTP_DOUT_336_351 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C48)) +#define MT6353_OTP_DOUT_352_367 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C4A)) +#define MT6353_OTP_DOUT_368_383 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C4C)) +#define MT6353_OTP_DOUT_384_399 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C4E)) +#define MT6353_OTP_DOUT_400_415 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C50)) +#define MT6353_OTP_DOUT_416_431 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C52)) +#define MT6353_OTP_DOUT_432_447 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C54)) +#define MT6353_OTP_DOUT_448_463 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C56)) +#define MT6353_OTP_DOUT_464_479 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C58)) +#define MT6353_OTP_DOUT_480_495 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C5A)) +#define MT6353_OTP_DOUT_496_511 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C5C)) +#define MT6353_OTP_VAL_0_15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C5E)) +#define MT6353_OTP_VAL_16_31 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C60)) +#define MT6353_OTP_VAL_32_47 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C62)) +#define MT6353_OTP_VAL_48_63 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C64)) +#define MT6353_OTP_VAL_64_79 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C66)) +#define MT6353_OTP_VAL_80_95 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C68)) +#define MT6353_OTP_VAL_96_111 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C6A)) +#define MT6353_OTP_VAL_112_127 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C6C)) +#define MT6353_OTP_VAL_128_143 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C6E)) +#define MT6353_OTP_VAL_144_159 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C70)) +#define MT6353_OTP_VAL_160_175 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C72)) +#define MT6353_OTP_VAL_176_191 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C74)) +#define MT6353_OTP_VAL_192_207 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C76)) +#define MT6353_OTP_VAL_208_223 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C78)) +#define MT6353_OTP_VAL_224_239 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C7A)) +#define MT6353_OTP_VAL_240_255 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C7C)) +#define MT6353_OTP_VAL_256_271 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C7E)) +#define MT6353_OTP_VAL_272_287 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C80)) +#define MT6353_OTP_VAL_288_303 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C82)) +#define MT6353_OTP_VAL_304_319 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C84)) +#define MT6353_OTP_VAL_320_335 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C86)) +#define MT6353_OTP_VAL_336_351 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C88)) +#define MT6353_OTP_VAL_352_367 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C8A)) +#define MT6353_OTP_VAL_368_383 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C8C)) +#define MT6353_OTP_VAL_384_399 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C8E)) +#define MT6353_OTP_VAL_400_415 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C90)) +#define MT6353_OTP_VAL_416_431 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C92)) +#define MT6353_OTP_VAL_432_447 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C94)) +#define MT6353_OTP_VAL_448_463 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C96)) +#define MT6353_OTP_VAL_464_479 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C98)) +#define MT6353_OTP_VAL_480_495 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C9A)) +#define MT6353_OTP_VAL_496_511 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C9C)) +#define MT6353_RTC_MIX_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0C9E)) +#define MT6353_RTC_MIX_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CA0)) +#define MT6353_RTC_MIX_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CA2)) +#define MT6353_FGADC_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CA4)) +#define MT6353_FGADC_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CA6)) +#define MT6353_FGADC_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CA8)) +#define MT6353_FGADC_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CAA)) +#define MT6353_FGADC_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CAC)) +#define MT6353_FGADC_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CAE)) +#define MT6353_FGADC_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CB0)) +#define MT6353_FGADC_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CB2)) +#define MT6353_FGADC_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CB4)) +#define MT6353_FGADC_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CB6)) +#define MT6353_FGADC_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CB8)) +#define MT6353_FGADC_CON11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CBA)) +#define MT6353_FGADC_CON12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CBC)) +#define MT6353_FGADC_CON13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CBE)) +#define MT6353_FGADC_CON14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CC0)) +#define MT6353_FGADC_CON15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CC2)) +#define MT6353_FGADC_CON16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CC4)) +#define MT6353_FGADC_CON17 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CC6)) +#define MT6353_FGADC_CON18 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CC8)) +#define MT6353_FGADC_CON19 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CCA)) +#define MT6353_FGADC_CON20 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CCC)) +#define MT6353_FGADC_CON21 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CCE)) +#define MT6353_FGADC_CON22 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CD0)) +#define MT6353_FGADC_CON23 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CD2)) +#define MT6353_FGADC_CON24 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CD4)) +#define MT6353_FGADC_CON25 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CD6)) +#define MT6353_FGADC_CON26 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CD8)) +#define MT6353_FGADC_CON27 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CDA)) +#define MT6353_FGADC_CON28 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CDC)) +#define MT6353_FGADC_CON29 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CDE)) +#define MT6353_FGADC_CON30 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CE0)) +#define MT6353_FGADC_CON31 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CE2)) +#define MT6353_FGADC_CON32 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CE4)) +#define MT6353_FGADC_CON33 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CE6)) +#define MT6353_SYSTEM_INFO_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CE8)) +#define MT6353_SYSTEM_INFO_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CEA)) +#define MT6353_SYSTEM_INFO_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CEC)) +#define MT6353_SYSTEM_INFO_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CEE)) +#define MT6353_SYSTEM_INFO_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CF0)) +#define MT6353_AUDDEC_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CF2)) +#define MT6353_AUDDEC_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CF4)) +#define MT6353_AUDDEC_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CF6)) +#define MT6353_AUDDEC_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CF8)) +#define MT6353_AUDDEC_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CFA)) +#define MT6353_AUDDEC_ANA_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CFC)) +#define MT6353_AUDDEC_ANA_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0CFE)) +#define MT6353_AUDDEC_ANA_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D00)) +#define MT6353_AUDDEC_ANA_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D02)) +#define MT6353_AUDENC_ANA_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D04)) +#define MT6353_AUDENC_ANA_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D06)) +#define MT6353_AUDENC_ANA_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D08)) +#define MT6353_AUDENC_ANA_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D0A)) +#define MT6353_AUDENC_ANA_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D0C)) +#define MT6353_AUDENC_ANA_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D0E)) +#define MT6353_AUDENC_ANA_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D10)) +#define MT6353_AUDENC_ANA_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D12)) +#define MT6353_AUDENC_ANA_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D14)) +#define MT6353_AUDENC_ANA_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D16)) +#define MT6353_AUDENC_ANA_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D18)) +#define MT6353_AUDNCP_CLKDIV_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D1A)) +#define MT6353_AUDNCP_CLKDIV_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D1C)) +#define MT6353_AUDNCP_CLKDIV_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D1E)) +#define MT6353_AUDNCP_CLKDIV_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D20)) +#define MT6353_AUDNCP_CLKDIV_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D22)) +#define MT6353_DCXO_CW00 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D24)) +#define MT6353_DCXO_CW00_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D26)) +#define MT6353_DCXO_CW00_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D28)) +#define MT6353_DCXO_CW01 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D2A)) +#define MT6353_DCXO_CW02 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D2C)) +#define MT6353_DCXO_CW03 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D2E)) +#define MT6353_DCXO_CW04 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D30)) +#define MT6353_DCXO_CW05 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D32)) +#define MT6353_DCXO_CW06 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D34)) +#define MT6353_DCXO_CW07 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D36)) +#define MT6353_DCXO_CW08 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D38)) +#define MT6353_DCXO_CW09 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D3A)) +#define MT6353_DCXO_CW10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D3C)) +#define MT6353_DCXO_CW11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D3E)) +#define MT6353_DCXO_CW12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D40)) +#define MT6353_DCXO_CW13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D42)) +#define MT6353_DCXO_CW14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D44)) +#define MT6353_DCXO_CW15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D46)) +#define MT6353_DCXO_CW16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0D48)) +#define MT6353_AUXADC_ADC0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E00)) +#define MT6353_AUXADC_ADC1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E02)) +#define MT6353_AUXADC_ADC2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E04)) +#define MT6353_AUXADC_ADC3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E06)) +#define MT6353_AUXADC_ADC4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E08)) +#define MT6353_AUXADC_ADC5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E0A)) +#define MT6353_AUXADC_ADC6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E0C)) +#define MT6353_AUXADC_ADC7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E0E)) +#define MT6353_AUXADC_ADC8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E10)) +#define MT6353_AUXADC_ADC9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E12)) +#define MT6353_AUXADC_ADC10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E14)) +#define MT6353_AUXADC_ADC11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E16)) +#define MT6353_AUXADC_ADC12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E18)) +#define MT6353_AUXADC_ADC13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E1A)) +#define MT6353_AUXADC_ADC14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E1C)) +#define MT6353_AUXADC_ADC15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E1E)) +#define MT6353_AUXADC_ADC16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E20)) +#define MT6353_AUXADC_ADC17 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E22)) +#define MT6353_AUXADC_ADC18 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E24)) +#define MT6353_AUXADC_ADC19 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E26)) +#define MT6353_AUXADC_ADC20 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E28)) +#define MT6353_AUXADC_ADC21 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E2A)) +#define MT6353_AUXADC_ADC22 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E2C)) +#define MT6353_AUXADC_ADC23 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E2E)) +#define MT6353_AUXADC_ADC24 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E30)) +#define MT6353_AUXADC_ADC25 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E32)) +#define MT6353_AUXADC_ADC26 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E34)) +#define MT6353_AUXADC_ADC27 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E36)) +#define MT6353_AUXADC_ADC28 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E38)) +#define MT6353_AUXADC_ADC29 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E3A)) +#define MT6353_AUXADC_ADC30 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E3C)) +#define MT6353_AUXADC_ADC31 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E3E)) +#define MT6353_AUXADC_ADC32 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E40)) +#define MT6353_AUXADC_ADC33 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E42)) +#define MT6353_AUXADC_ADC34 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E44)) +#define MT6353_AUXADC_ADC35 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E46)) +#define MT6353_AUXADC_ADC36 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E48)) +#define MT6353_AUXADC_ADC37 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E4A)) +#define MT6353_AUXADC_ADC38 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E4C)) +#define MT6353_AUXADC_ADC39 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E4E)) +#define MT6353_AUXADC_ADC40 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E50)) +#define MT6353_AUXADC_BUF0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E52)) +#define MT6353_AUXADC_BUF1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E54)) +#define MT6353_AUXADC_BUF2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E56)) +#define MT6353_AUXADC_BUF3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E58)) +#define MT6353_AUXADC_BUF4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E5A)) +#define MT6353_AUXADC_BUF5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E5C)) +#define MT6353_AUXADC_BUF6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E5E)) +#define MT6353_AUXADC_BUF7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E60)) +#define MT6353_AUXADC_BUF8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E62)) +#define MT6353_AUXADC_BUF9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E64)) +#define MT6353_AUXADC_BUF10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E66)) +#define MT6353_AUXADC_BUF11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E68)) +#define MT6353_AUXADC_BUF12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E6A)) +#define MT6353_AUXADC_BUF13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E6C)) +#define MT6353_AUXADC_BUF14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E6E)) +#define MT6353_AUXADC_BUF15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E70)) +#define MT6353_AUXADC_BUF16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E72)) +#define MT6353_AUXADC_BUF17 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E74)) +#define MT6353_AUXADC_BUF18 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E76)) +#define MT6353_AUXADC_BUF19 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E78)) +#define MT6353_AUXADC_BUF20 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E7A)) +#define MT6353_AUXADC_BUF21 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E7C)) +#define MT6353_AUXADC_BUF22 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E7E)) +#define MT6353_AUXADC_BUF23 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E80)) +#define MT6353_AUXADC_BUF24 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E82)) +#define MT6353_AUXADC_BUF25 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E84)) +#define MT6353_AUXADC_BUF26 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E86)) +#define MT6353_AUXADC_BUF27 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E88)) +#define MT6353_AUXADC_BUF28 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E8A)) +#define MT6353_AUXADC_BUF29 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E8C)) +#define MT6353_AUXADC_BUF30 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E8E)) +#define MT6353_AUXADC_BUF31 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E90)) +#define MT6353_AUXADC_STA0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E92)) +#define MT6353_AUXADC_STA1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E94)) +#define MT6353_AUXADC_STA2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E96)) +#define MT6353_AUXADC_RQST0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E98)) +#define MT6353_AUXADC_RQST0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E9A)) +#define MT6353_AUXADC_RQST0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E9C)) +#define MT6353_AUXADC_RQST1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0E9E)) +#define MT6353_AUXADC_RQST1_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EA0)) +#define MT6353_AUXADC_RQST1_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EA2)) +#define MT6353_AUXADC_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EA4)) +#define MT6353_AUXADC_CON0_SET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EA6)) +#define MT6353_AUXADC_CON0_CLR ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EA8)) +#define MT6353_AUXADC_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EAA)) +#define MT6353_AUXADC_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EAC)) +#define MT6353_AUXADC_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EAE)) +#define MT6353_AUXADC_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EB0)) +#define MT6353_AUXADC_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EB2)) +#define MT6353_AUXADC_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EB4)) +#define MT6353_AUXADC_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EB6)) +#define MT6353_AUXADC_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EB8)) +#define MT6353_AUXADC_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EBA)) +#define MT6353_AUXADC_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EBC)) +#define MT6353_AUXADC_CON11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EBE)) +#define MT6353_AUXADC_CON12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EC0)) +#define MT6353_AUXADC_CON13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EC2)) +#define MT6353_AUXADC_CON14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EC4)) +#define MT6353_AUXADC_CON15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EC6)) +#define MT6353_AUXADC_CON16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EC8)) +#define MT6353_AUXADC_AUTORPT0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ECA)) +#define MT6353_AUXADC_LBAT0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ECC)) +#define MT6353_AUXADC_LBAT1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ECE)) +#define MT6353_AUXADC_LBAT2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ED0)) +#define MT6353_AUXADC_LBAT3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ED2)) +#define MT6353_AUXADC_LBAT4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ED4)) +#define MT6353_AUXADC_LBAT5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ED6)) +#define MT6353_AUXADC_LBAT6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0ED8)) +#define MT6353_AUXADC_ACCDET ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EDA)) +#define MT6353_AUXADC_THR0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EDC)) +#define MT6353_AUXADC_THR1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EDE)) +#define MT6353_AUXADC_THR2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EE0)) +#define MT6353_AUXADC_THR3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EE2)) +#define MT6353_AUXADC_THR4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EE4)) +#define MT6353_AUXADC_THR5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EE6)) +#define MT6353_AUXADC_THR6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EE8)) +#define MT6353_AUXADC_EFUSE0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EEA)) +#define MT6353_AUXADC_EFUSE1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EEC)) +#define MT6353_AUXADC_EFUSE2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EEE)) +#define MT6353_AUXADC_EFUSE3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EF0)) +#define MT6353_AUXADC_EFUSE4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EF2)) +#define MT6353_AUXADC_EFUSE5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EF4)) +#define MT6353_AUXADC_DBG0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EF6)) +#define MT6353_AUXADC_IMP0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EF8)) +#define MT6353_AUXADC_IMP1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EFA)) +#define MT6353_AUXADC_VISMPS0_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EFC)) +#define MT6353_AUXADC_VISMPS0_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0EFE)) +#define MT6353_AUXADC_VISMPS0_3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F00)) +#define MT6353_AUXADC_VISMPS0_4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F02)) +#define MT6353_AUXADC_VISMPS0_5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F04)) +#define MT6353_AUXADC_VISMPS0_6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F06)) +#define MT6353_AUXADC_VISMPS0_7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F08)) +#define MT6353_AUXADC_LBAT2_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F0A)) +#define MT6353_AUXADC_LBAT2_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F0C)) +#define MT6353_AUXADC_LBAT2_3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F0E)) +#define MT6353_AUXADC_LBAT2_4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F10)) +#define MT6353_AUXADC_LBAT2_5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F12)) +#define MT6353_AUXADC_LBAT2_6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F14)) +#define MT6353_AUXADC_LBAT2_7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F16)) +#define MT6353_AUXADC_MDBG_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F18)) +#define MT6353_AUXADC_MDBG_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F1A)) +#define MT6353_AUXADC_MDBG_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F1C)) +#define MT6353_AUXADC_MDRT_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F1E)) +#define MT6353_AUXADC_MDRT_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F20)) +#define MT6353_AUXADC_MDRT_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F22)) +#define MT6353_AUXADC_DCXO_MDRT_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F24)) +#define MT6353_AUXADC_DCXO_MDRT_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F26)) +#define MT6353_AUXADC_DCXO_MDRT_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F28)) +#define MT6353_AUXADC_NAG_0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F2A)) +#define MT6353_AUXADC_NAG_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F2C)) +#define MT6353_AUXADC_NAG_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F2E)) +#define MT6353_AUXADC_NAG_3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F30)) +#define MT6353_AUXADC_NAG_4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F32)) +#define MT6353_AUXADC_NAG_5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F34)) +#define MT6353_AUXADC_NAG_6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F36)) +#define MT6353_AUXADC_NAG_7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F38)) +#define MT6353_AUXADC_NAG_8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F3A)) +#define MT6353_AUXADC_TYPEC_H_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F3C)) +#define MT6353_AUXADC_TYPEC_H_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F3E)) +#define MT6353_AUXADC_TYPEC_H_3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F40)) +#define MT6353_AUXADC_TYPEC_H_4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F42)) +#define MT6353_AUXADC_TYPEC_H_5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F44)) +#define MT6353_AUXADC_TYPEC_H_6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F46)) +#define MT6353_AUXADC_TYPEC_H_7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F48)) +#define MT6353_AUXADC_TYPEC_L_1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F4A)) +#define MT6353_AUXADC_TYPEC_L_2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F4C)) +#define MT6353_AUXADC_TYPEC_L_3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F4E)) +#define MT6353_AUXADC_TYPEC_L_4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F50)) +#define MT6353_AUXADC_TYPEC_L_5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F52)) +#define MT6353_AUXADC_TYPEC_L_6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F54)) +#define MT6353_AUXADC_TYPEC_L_7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F56)) +#define MT6353_ACCDET_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F58)) +#define MT6353_ACCDET_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F5A)) +#define MT6353_ACCDET_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F5C)) +#define MT6353_ACCDET_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F5E)) +#define MT6353_ACCDET_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F60)) +#define MT6353_ACCDET_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F62)) +#define MT6353_ACCDET_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F64)) +#define MT6353_ACCDET_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F66)) +#define MT6353_ACCDET_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F68)) +#define MT6353_ACCDET_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F6A)) +#define MT6353_ACCDET_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F6C)) +#define MT6353_ACCDET_CON11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F6E)) +#define MT6353_ACCDET_CON12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F70)) +#define MT6353_ACCDET_CON13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F72)) +#define MT6353_ACCDET_CON14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F74)) +#define MT6353_ACCDET_CON15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F76)) +#define MT6353_ACCDET_CON16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F78)) +#define MT6353_ACCDET_CON17 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F7A)) +#define MT6353_ACCDET_CON18 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F7C)) +#define MT6353_ACCDET_CON19 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F7E)) +#define MT6353_ACCDET_CON20 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F80)) +#define MT6353_ACCDET_CON21 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F82)) +#define MT6353_ACCDET_CON22 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F84)) +#define MT6353_ACCDET_CON23 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F86)) +#define MT6353_ACCDET_CON24 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F88)) +#define MT6353_ACCDET_CON25 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F8A)) +#define MT6353_CHR_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F8C)) +#define MT6353_CHR_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F8E)) +#define MT6353_CHR_CON2 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F90)) +#define MT6353_CHR_CON3 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F92)) +#define MT6353_CHR_CON4 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F94)) +#define MT6353_CHR_CON5 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F96)) +#define MT6353_CHR_CON6 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F98)) +#define MT6353_CHR_CON7 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F9A)) +#define MT6353_CHR_CON8 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F9C)) +#define MT6353_CHR_CON9 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0F9E)) +#define MT6353_CHR_CON10 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FA0)) +#define MT6353_CHR_CON11 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FA2)) +#define MT6353_CHR_CON12 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FA4)) +#define MT6353_CHR_CON13 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FA6)) +#define MT6353_CHR_CON14 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FA8)) +#define MT6353_CHR_CON15 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FAA)) +#define MT6353_CHR_CON16 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FAC)) +#define MT6353_CHR_CON17 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FAE)) +#define MT6353_CHR_CON18 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FB0)) +#define MT6353_CHR_CON19 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FB2)) +#define MT6353_CHR_CON20 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FB4)) +#define MT6353_CHR_CON21 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FB6)) +#define MT6353_CHR_CON22 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FB8)) +#define MT6353_CHR_CON23 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FBA)) +#define MT6353_CHR_CON24 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FBC)) +#define MT6353_CHR_CON25 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FBE)) +#define MT6353_CHR_CON26 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FC0)) +#define MT6353_CHR_CON27 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FC2)) +#define MT6353_CHR_CON28 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FC4)) +#define MT6353_CHR_CON29 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FC6)) +#define MT6353_CHR_CON30 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FC8)) +#define MT6353_CHR_CON31 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FCA)) +#define MT6353_CHR_CON32 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FCC)) +#define MT6353_CHR_CON33 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FCE)) +#define MT6353_CHR_CON34 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FD0)) +#define MT6353_CHR_CON35 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FD2)) +#define MT6353_CHR_CON36 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FD4)) +#define MT6353_CHR_CON37 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FD6)) +#define MT6353_CHR_CON38 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FD8)) +#define MT6353_CHR_CON39 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FDA)) +#define MT6353_CHR_CON40 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FDC)) +#define MT6353_CHR_CON41 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FDE)) +#define MT6353_CHR_CON42 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FE0)) +#define MT6353_BATON_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FE2)) +#define MT6353_CHR_CON43 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FE4)) +#define MT6353_CHR_CON44 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FE6)) +#define MT6353_CHR_CON48 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FE8)) +#define MT6353_EOSC_CALI_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FEA)) +#define MT6353_EOSC_CALI_CON1 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FEC)) +#define MT6353_VRTC_PWM_CON0 ((unsigned int)(MT6353_PMIC_REG_BASE+0x0FEE)) +/* mask is HEX; shift is Integer */ +#define PMIC_USBDL_ADDR MT6353_STRUP_CON0 +#define PMIC_USBDL_MASK 0x1 +#define PMIC_USBDL_SHIFT 0 +#define PMIC_VTCXO_CONFIG_ADDR MT6353_STRUP_CON0 +#define PMIC_VTCXO_CONFIG_MASK 0x1 +#define PMIC_VTCXO_CONFIG_SHIFT 1 +#define PMIC_RG_THR_DET_DIS_ADDR MT6353_STRUP_CON0 +#define PMIC_RG_THR_DET_DIS_MASK 0x1 +#define PMIC_RG_THR_DET_DIS_SHIFT 12 +#define PMIC_RG_THR_TEST_ADDR MT6353_STRUP_CON0 +#define PMIC_RG_THR_TEST_MASK 0x3 +#define PMIC_RG_THR_TEST_SHIFT 13 +#define PMIC_RG_STRUP_THER_DEB_RMAX_ADDR MT6353_STRUP_CON1 +#define PMIC_RG_STRUP_THER_DEB_RMAX_MASK 0xFFFF +#define PMIC_RG_STRUP_THER_DEB_RMAX_SHIFT 0 +#define PMIC_RG_STRUP_THER_DEB_FMAX_ADDR MT6353_STRUP_CON2 +#define PMIC_RG_STRUP_THER_DEB_FMAX_MASK 0xFFFF +#define PMIC_RG_STRUP_THER_DEB_FMAX_SHIFT 0 +#define PMIC_DDUVLO_DEB_EN_ADDR MT6353_STRUP_CON3 +#define PMIC_DDUVLO_DEB_EN_MASK 0x1 +#define PMIC_DDUVLO_DEB_EN_SHIFT 0 +#define PMIC_RG_PWRBB_DEB_EN_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_PWRBB_DEB_EN_MASK 0x1 +#define PMIC_RG_PWRBB_DEB_EN_SHIFT 1 +#define PMIC_RG_STRUP_OSC_EN_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_STRUP_OSC_EN_MASK 0x1 +#define PMIC_RG_STRUP_OSC_EN_SHIFT 2 +#define PMIC_RG_STRUP_OSC_EN_SEL_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_STRUP_OSC_EN_SEL_MASK 0x1 +#define PMIC_RG_STRUP_OSC_EN_SEL_SHIFT 3 +#define PMIC_RG_STRUP_FT_CTRL_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_STRUP_FT_CTRL_MASK 0x3 +#define PMIC_RG_STRUP_FT_CTRL_SHIFT 4 +#define PMIC_RG_STRUP_PWRON_FORCE_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_STRUP_PWRON_FORCE_MASK 0x1 +#define PMIC_RG_STRUP_PWRON_FORCE_SHIFT 6 +#define PMIC_RG_BIASGEN_FORCE_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_BIASGEN_FORCE_MASK 0x1 +#define PMIC_RG_BIASGEN_FORCE_SHIFT 7 +#define PMIC_RG_STRUP_PWRON_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_STRUP_PWRON_MASK 0x1 +#define PMIC_RG_STRUP_PWRON_SHIFT 8 +#define PMIC_RG_STRUP_PWRON_SEL_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_STRUP_PWRON_SEL_MASK 0x1 +#define PMIC_RG_STRUP_PWRON_SEL_SHIFT 9 +#define PMIC_RG_BIASGEN_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_BIASGEN_MASK 0x1 +#define PMIC_RG_BIASGEN_SHIFT 10 +#define PMIC_RG_BIASGEN_SEL_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_BIASGEN_SEL_MASK 0x1 +#define PMIC_RG_BIASGEN_SEL_SHIFT 11 +#define PMIC_RG_RTC_XOSC32_ENB_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_RTC_XOSC32_ENB_MASK 0x1 +#define PMIC_RG_RTC_XOSC32_ENB_SHIFT 12 +#define PMIC_RG_RTC_XOSC32_ENB_SEL_ADDR MT6353_STRUP_CON3 +#define PMIC_RG_RTC_XOSC32_ENB_SEL_MASK 0x1 +#define PMIC_RG_RTC_XOSC32_ENB_SEL_SHIFT 13 +#define PMIC_STRUP_DIG_IO_PG_FORCE_ADDR MT6353_STRUP_CON3 +#define PMIC_STRUP_DIG_IO_PG_FORCE_MASK 0x1 +#define PMIC_STRUP_DIG_IO_PG_FORCE_SHIFT 15 +#define PMIC_CLR_JUST_RST_ADDR MT6353_STRUP_CON4 +#define PMIC_CLR_JUST_RST_MASK 0x1 +#define PMIC_CLR_JUST_RST_SHIFT 4 +#define PMIC_UVLO_L2H_DEB_EN_ADDR MT6353_STRUP_CON4 +#define PMIC_UVLO_L2H_DEB_EN_MASK 0x1 +#define PMIC_UVLO_L2H_DEB_EN_SHIFT 5 +#define PMIC_JUST_PWRKEY_RST_ADDR MT6353_STRUP_CON4 +#define PMIC_JUST_PWRKEY_RST_MASK 0x1 +#define PMIC_JUST_PWRKEY_RST_SHIFT 14 +#define PMIC_DA_QI_OSC_EN_ADDR MT6353_STRUP_CON4 +#define PMIC_DA_QI_OSC_EN_MASK 0x1 +#define PMIC_DA_QI_OSC_EN_SHIFT 15 +#define PMIC_RG_STRUP_EXT_PMIC_EN_ADDR MT6353_STRUP_CON5 +#define PMIC_RG_STRUP_EXT_PMIC_EN_MASK 0x1 +#define PMIC_RG_STRUP_EXT_PMIC_EN_SHIFT 0 +#define PMIC_RG_STRUP_EXT_PMIC_SEL_ADDR MT6353_STRUP_CON5 +#define PMIC_RG_STRUP_EXT_PMIC_SEL_MASK 0x1 +#define PMIC_RG_STRUP_EXT_PMIC_SEL_SHIFT 1 +#define PMIC_STRUP_CON8_RSV0_ADDR MT6353_STRUP_CON5 +#define PMIC_STRUP_CON8_RSV0_MASK 0x7F +#define PMIC_STRUP_CON8_RSV0_SHIFT 8 +#define PMIC_DA_QI_EXT_PMIC_EN_ADDR MT6353_STRUP_CON5 +#define PMIC_DA_QI_EXT_PMIC_EN_MASK 0x1 +#define PMIC_DA_QI_EXT_PMIC_EN_SHIFT 15 +#define PMIC_RG_STRUP_AUXADC_START_SW_ADDR MT6353_STRUP_CON6 +#define PMIC_RG_STRUP_AUXADC_START_SW_MASK 0x1 +#define PMIC_RG_STRUP_AUXADC_START_SW_SHIFT 0 +#define PMIC_RG_STRUP_AUXADC_RSTB_SW_ADDR MT6353_STRUP_CON6 +#define PMIC_RG_STRUP_AUXADC_RSTB_SW_MASK 0x1 +#define PMIC_RG_STRUP_AUXADC_RSTB_SW_SHIFT 1 +#define PMIC_RG_STRUP_AUXADC_START_SEL_ADDR MT6353_STRUP_CON6 +#define PMIC_RG_STRUP_AUXADC_START_SEL_MASK 0x1 +#define PMIC_RG_STRUP_AUXADC_START_SEL_SHIFT 2 +#define PMIC_RG_STRUP_AUXADC_RSTB_SEL_ADDR MT6353_STRUP_CON6 +#define PMIC_RG_STRUP_AUXADC_RSTB_SEL_MASK 0x1 +#define PMIC_RG_STRUP_AUXADC_RSTB_SEL_SHIFT 3 +#define PMIC_RG_STRUP_AUXADC_RPCNT_MAX_ADDR MT6353_STRUP_CON6 +#define PMIC_RG_STRUP_AUXADC_RPCNT_MAX_MASK 0x7F +#define PMIC_RG_STRUP_AUXADC_RPCNT_MAX_SHIFT 4 +#define PMIC_STRUP_PWROFF_SEQ_EN_ADDR MT6353_STRUP_CON7 +#define PMIC_STRUP_PWROFF_SEQ_EN_MASK 0x1 +#define PMIC_STRUP_PWROFF_SEQ_EN_SHIFT 0 +#define PMIC_STRUP_PWROFF_PREOFF_EN_ADDR MT6353_STRUP_CON7 +#define PMIC_STRUP_PWROFF_PREOFF_EN_MASK 0x1 +#define PMIC_STRUP_PWROFF_PREOFF_EN_SHIFT 1 +#define PMIC_STRUP_DIG0_RSV0_ADDR MT6353_STRUP_CON8 +#define PMIC_STRUP_DIG0_RSV0_MASK 0xF +#define PMIC_STRUP_DIG0_RSV0_SHIFT 2 +#define PMIC_STRUP_DIG1_RSV0_ADDR MT6353_STRUP_CON8 +#define PMIC_STRUP_DIG1_RSV0_MASK 0x1F +#define PMIC_STRUP_DIG1_RSV0_SHIFT 6 +#define PMIC_RG_RSV_SWREG_ADDR MT6353_STRUP_CON9 +#define PMIC_RG_RSV_SWREG_MASK 0xFFFF +#define PMIC_RG_RSV_SWREG_SHIFT 0 +#define PMIC_RG_STRUP_UVLO_U1U2_SEL_ADDR MT6353_STRUP_CON10 +#define PMIC_RG_STRUP_UVLO_U1U2_SEL_MASK 0x1 +#define PMIC_RG_STRUP_UVLO_U1U2_SEL_SHIFT 0 +#define PMIC_RG_STRUP_UVLO_U1U2_SEL_SWCTRL_ADDR MT6353_STRUP_CON10 +#define PMIC_RG_STRUP_UVLO_U1U2_SEL_SWCTRL_MASK 0x1 +#define PMIC_RG_STRUP_UVLO_U1U2_SEL_SWCTRL_SHIFT 1 +#define PMIC_RG_STRUP_THR_CLR_ADDR MT6353_STRUP_CON11 +#define PMIC_RG_STRUP_THR_CLR_MASK 0x1 +#define PMIC_RG_STRUP_THR_CLR_SHIFT 0 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_ADDR MT6353_STRUP_CON12 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_MASK 0x3 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_SHIFT 0 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_TD_ADDR MT6353_STRUP_CON12 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_TD_MASK 0x3 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_TD_SHIFT 2 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_EN_ADDR MT6353_STRUP_CON12 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_EN_MASK 0x1 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_EN_SHIFT 4 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_ADDR MT6353_STRUP_CON12 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_MASK 0x1 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_SHIFT 5 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKEY_CTRL_ADDR MT6353_STRUP_CON12 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKEY_CTRL_MASK 0x1 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKEY_CTRL_SHIFT 6 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_ADDR MT6353_STRUP_CON12 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_MASK 0x1 +#define PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_SHIFT 7 +#define PMIC_RG_STRUP_ENVTEM_ADDR MT6353_STRUP_CON12 +#define PMIC_RG_STRUP_ENVTEM_MASK 0x1 +#define PMIC_RG_STRUP_ENVTEM_SHIFT 14 +#define PMIC_RG_STRUP_ENVTEM_CTRL_ADDR MT6353_STRUP_CON12 +#define PMIC_RG_STRUP_ENVTEM_CTRL_MASK 0x1 +#define PMIC_RG_STRUP_ENVTEM_CTRL_SHIFT 15 +#define PMIC_RG_STRUP_PWRKEY_COUNT_RESET_ADDR MT6353_STRUP_CON13 +#define PMIC_RG_STRUP_PWRKEY_COUNT_RESET_MASK 0x1 +#define PMIC_RG_STRUP_PWRKEY_COUNT_RESET_SHIFT 0 +#define PMIC_RG_STRUP_VCORE2_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VCORE2_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VCORE2_PG_H2L_EN_SHIFT 4 +#define PMIC_RG_STRUP_VMCH_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VMCH_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VMCH_PG_H2L_EN_SHIFT 5 +#define PMIC_RG_STRUP_VMC_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VMC_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VMC_PG_H2L_EN_SHIFT 6 +#define PMIC_RG_STRUP_VUSB33_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VUSB33_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VUSB33_PG_H2L_EN_SHIFT 7 +#define PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_SHIFT 8 +#define PMIC_RG_STRUP_VPROC_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VPROC_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VPROC_PG_H2L_EN_SHIFT 9 +#define PMIC_RG_STRUP_VDRAM_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VDRAM_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VDRAM_PG_H2L_EN_SHIFT 10 +#define PMIC_RG_STRUP_VAUD28_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VAUD28_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VAUD28_PG_H2L_EN_SHIFT 11 +#define PMIC_RG_STRUP_VEMC_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VEMC_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VEMC_PG_H2L_EN_SHIFT 12 +#define PMIC_RG_STRUP_VS1_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VS1_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VS1_PG_H2L_EN_SHIFT 13 +#define PMIC_RG_STRUP_VCORE_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VCORE_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VCORE_PG_H2L_EN_SHIFT 14 +#define PMIC_RG_STRUP_VAUX18_PG_H2L_EN_ADDR MT6353_STRUP_CON14 +#define PMIC_RG_STRUP_VAUX18_PG_H2L_EN_MASK 0x1 +#define PMIC_RG_STRUP_VAUX18_PG_H2L_EN_SHIFT 15 +#define PMIC_RG_STRUP_VCORE2_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VCORE2_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VCORE2_PG_ENB_SHIFT 0 +#define PMIC_RG_STRUP_VMCH_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VMCH_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VMCH_PG_ENB_SHIFT 1 +#define PMIC_RG_STRUP_VMC_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VMC_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VMC_PG_ENB_SHIFT 2 +#define PMIC_RG_STRUP_VXO22_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VXO22_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VXO22_PG_ENB_SHIFT 3 +#define PMIC_RG_STRUP_VTCXO_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VTCXO_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VTCXO_PG_ENB_SHIFT 4 +#define PMIC_RG_STRUP_VUSB33_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VUSB33_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VUSB33_PG_ENB_SHIFT 5 +#define PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_SHIFT 6 +#define PMIC_RG_STRUP_VPROC_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VPROC_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VPROC_PG_ENB_SHIFT 7 +#define PMIC_RG_STRUP_VDRAM_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VDRAM_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VDRAM_PG_ENB_SHIFT 8 +#define PMIC_RG_STRUP_VAUD28_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VAUD28_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VAUD28_PG_ENB_SHIFT 9 +#define PMIC_RG_STRUP_VIO28_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VIO28_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VIO28_PG_ENB_SHIFT 10 +#define PMIC_RG_STRUP_VEMC_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VEMC_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VEMC_PG_ENB_SHIFT 11 +#define PMIC_RG_STRUP_VIO18_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VIO18_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VIO18_PG_ENB_SHIFT 12 +#define PMIC_RG_STRUP_VS1_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VS1_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VS1_PG_ENB_SHIFT 13 +#define PMIC_RG_STRUP_VCORE_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VCORE_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VCORE_PG_ENB_SHIFT 14 +#define PMIC_RG_STRUP_VAUX18_PG_ENB_ADDR MT6353_STRUP_CON15 +#define PMIC_RG_STRUP_VAUX18_PG_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VAUX18_PG_ENB_SHIFT 15 +#define PMIC_RG_STRUP_VCORE2_OC_ENB_ADDR MT6353_STRUP_CON16 +#define PMIC_RG_STRUP_VCORE2_OC_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VCORE2_OC_ENB_SHIFT 12 +#define PMIC_RG_STRUP_VPROC_OC_ENB_ADDR MT6353_STRUP_CON16 +#define PMIC_RG_STRUP_VPROC_OC_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VPROC_OC_ENB_SHIFT 13 +#define PMIC_RG_STRUP_VS1_OC_ENB_ADDR MT6353_STRUP_CON16 +#define PMIC_RG_STRUP_VS1_OC_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VS1_OC_ENB_SHIFT 14 +#define PMIC_RG_STRUP_VCORE_OC_ENB_ADDR MT6353_STRUP_CON16 +#define PMIC_RG_STRUP_VCORE_OC_ENB_MASK 0x1 +#define PMIC_RG_STRUP_VCORE_OC_ENB_SHIFT 15 +#define PMIC_RG_STRUP_LONG_PRESS_RESET_EXTEND_ADDR MT6353_STRUP_CON17 +#define PMIC_RG_STRUP_LONG_PRESS_RESET_EXTEND_MASK 0x1 +#define PMIC_RG_STRUP_LONG_PRESS_RESET_EXTEND_SHIFT 0 +#define PMIC_RG_THRDET_SEL_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_THRDET_SEL_MASK 0x1 +#define PMIC_RG_THRDET_SEL_SHIFT 0 +#define PMIC_RG_STRUP_THR_SEL_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_STRUP_THR_SEL_MASK 0x3 +#define PMIC_RG_STRUP_THR_SEL_SHIFT 1 +#define PMIC_RG_THR_TMODE_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_THR_TMODE_MASK 0x1 +#define PMIC_RG_THR_TMODE_SHIFT 3 +#define PMIC_RG_VREF_BG_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_VREF_BG_MASK 0x7 +#define PMIC_RG_VREF_BG_SHIFT 4 +#define PMIC_RG_STRUP_IREF_TRIM_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_STRUP_IREF_TRIM_MASK 0x1F +#define PMIC_RG_STRUP_IREF_TRIM_SHIFT 7 +#define PMIC_RG_RST_DRVSEL_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_RST_DRVSEL_MASK 0x1 +#define PMIC_RG_RST_DRVSEL_SHIFT 12 +#define PMIC_RG_EN_DRVSEL_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_EN_DRVSEL_MASK 0x1 +#define PMIC_RG_EN_DRVSEL_SHIFT 13 +#define PMIC_RG_FCHR_KEYDET_EN_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_FCHR_KEYDET_EN_MASK 0x1 +#define PMIC_RG_FCHR_KEYDET_EN_SHIFT 14 +#define PMIC_RG_FCHR_PU_EN_ADDR MT6353_STRUP_ANA_CON0 +#define PMIC_RG_FCHR_PU_EN_MASK 0x1 +#define PMIC_RG_FCHR_PU_EN_SHIFT 15 +#define PMIC_RG_PMU_RSV_ADDR MT6353_STRUP_ANA_CON1 +#define PMIC_RG_PMU_RSV_MASK 0xF +#define PMIC_RG_PMU_RSV_SHIFT 0 +#define PMIC_TYPE_C_PHY_RG_CC_RP_SEL_ADDR MT6353_TYPE_C_PHY_RG_0 +#define PMIC_TYPE_C_PHY_RG_CC_RP_SEL_MASK 0x3 +#define PMIC_TYPE_C_PHY_RG_CC_RP_SEL_SHIFT 0 +#define PMIC_REG_TYPE_C_PHY_RG_PD_TX_SLEW_CALEN_ADDR MT6353_TYPE_C_PHY_RG_0 +#define PMIC_REG_TYPE_C_PHY_RG_PD_TX_SLEW_CALEN_MASK 0x1 +#define PMIC_REG_TYPE_C_PHY_RG_PD_TX_SLEW_CALEN_SHIFT 3 +#define PMIC_REG_TYPE_C_PHY_RG_PD_TXSLEW_I_ADDR MT6353_TYPE_C_PHY_RG_0 +#define PMIC_REG_TYPE_C_PHY_RG_PD_TXSLEW_I_MASK 0x7 +#define PMIC_REG_TYPE_C_PHY_RG_PD_TXSLEW_I_SHIFT 4 +#define PMIC_REG_TYPE_C_PHY_RG_CC_MPX_SEL_ADDR MT6353_TYPE_C_PHY_RG_0 +#define PMIC_REG_TYPE_C_PHY_RG_CC_MPX_SEL_MASK 0xFF +#define PMIC_REG_TYPE_C_PHY_RG_CC_MPX_SEL_SHIFT 8 +#define PMIC_REG_TYPE_C_PHY_RG_CC_RESERVE_ADDR MT6353_TYPE_C_PHY_RG_CC_RESERVE_CSR +#define PMIC_REG_TYPE_C_PHY_RG_CC_RESERVE_MASK 0xFF +#define PMIC_REG_TYPE_C_PHY_RG_CC_RESERVE_SHIFT 0 +#define PMIC_REG_TYPE_C_VCMP_CC2_SW_SEL_ST_CNT_VAL_ADDR MT6353_TYPE_C_VCMP_CTRL +#define PMIC_REG_TYPE_C_VCMP_CC2_SW_SEL_ST_CNT_VAL_MASK 0x1F +#define PMIC_REG_TYPE_C_VCMP_CC2_SW_SEL_ST_CNT_VAL_SHIFT 0 +#define PMIC_REG_TYPE_C_VCMP_BIAS_EN_ST_CNT_VAL_ADDR MT6353_TYPE_C_VCMP_CTRL +#define PMIC_REG_TYPE_C_VCMP_BIAS_EN_ST_CNT_VAL_MASK 0x3 +#define PMIC_REG_TYPE_C_VCMP_BIAS_EN_ST_CNT_VAL_SHIFT 5 +#define PMIC_REG_TYPE_C_VCMP_DAC_EN_ST_CNT_VAL_ADDR MT6353_TYPE_C_VCMP_CTRL +#define PMIC_REG_TYPE_C_VCMP_DAC_EN_ST_CNT_VAL_MASK 0x1 +#define PMIC_REG_TYPE_C_VCMP_DAC_EN_ST_CNT_VAL_SHIFT 7 +#define PMIC_REG_TYPE_C_PORT_SUPPORT_ROLE_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_PORT_SUPPORT_ROLE_MASK 0x3 +#define PMIC_REG_TYPE_C_PORT_SUPPORT_ROLE_SHIFT 0 +#define PMIC_REG_TYPE_C_ADC_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_ADC_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_ADC_EN_SHIFT 2 +#define PMIC_REG_TYPE_C_ACC_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_ACC_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_ACC_EN_SHIFT 3 +#define PMIC_REG_TYPE_C_AUDIO_ACC_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_AUDIO_ACC_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_AUDIO_ACC_EN_SHIFT 4 +#define PMIC_REG_TYPE_C_DEBUG_ACC_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_DEBUG_ACC_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_DEBUG_ACC_EN_SHIFT 5 +#define PMIC_REG_TYPE_C_TRY_SRC_ST_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_TRY_SRC_ST_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_TRY_SRC_ST_EN_SHIFT 6 +#define PMIC_REG_TYPE_C_ATTACH_SRC_2_TRY_WAIT_SNK_ST_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_ATTACH_SRC_2_TRY_WAIT_SNK_ST_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_ATTACH_SRC_2_TRY_WAIT_SNK_ST_EN_SHIFT 7 +#define PMIC_REG_TYPE_C_PD2CC_DET_DISABLE_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_PD2CC_DET_DISABLE_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_PD2CC_DET_DISABLE_EN_SHIFT 8 +#define PMIC_REG_TYPE_C_ATTACH_SRC_OPEN_PDDEBOUNCE_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_ATTACH_SRC_OPEN_PDDEBOUNCE_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_ATTACH_SRC_OPEN_PDDEBOUNCE_EN_SHIFT 9 +#define PMIC_REG_TYPE_C_DISABLE_ST_RD_EN_ADDR MT6353_TYPE_C_CTRL +#define PMIC_REG_TYPE_C_DISABLE_ST_RD_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_DISABLE_ST_RD_EN_SHIFT 10 +#define PMIC_W1_TYPE_C_SW_ENT_DISABLE_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_ENT_DISABLE_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_ENT_DISABLE_CMD_SHIFT 0 +#define PMIC_W1_TYPE_C_SW_ENT_UNATCH_SRC_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_ENT_UNATCH_SRC_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_ENT_UNATCH_SRC_CMD_SHIFT 1 +#define PMIC_W1_TYPE_C_SW_ENT_UNATCH_SNK_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_ENT_UNATCH_SNK_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_ENT_UNATCH_SNK_CMD_SHIFT 2 +#define PMIC_W1_TYPE_C_SW_PR_SWAP_INDICATE_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_PR_SWAP_INDICATE_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_PR_SWAP_INDICATE_CMD_SHIFT 3 +#define PMIC_W1_TYPE_C_SW_VCONN_SWAP_INDICATE_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_VCONN_SWAP_INDICATE_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_VCONN_SWAP_INDICATE_CMD_SHIFT 4 +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_DEFAULT_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_DEFAULT_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_DEFAULT_CMD_SHIFT 5 +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_15_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_15_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_15_CMD_SHIFT 6 +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_30_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_30_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_30_CMD_SHIFT 7 +#define PMIC_TYPE_C_SW_VBUS_PRESENT_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_TYPE_C_SW_VBUS_PRESENT_MASK 0x1 +#define PMIC_TYPE_C_SW_VBUS_PRESENT_SHIFT 8 +#define PMIC_TYPE_C_SW_DA_DRIVE_VCONN_EN_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_TYPE_C_SW_DA_DRIVE_VCONN_EN_MASK 0x1 +#define PMIC_TYPE_C_SW_DA_DRIVE_VCONN_EN_SHIFT 9 +#define PMIC_TYPE_C_SW_VBUS_DET_DIS_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_TYPE_C_SW_VBUS_DET_DIS_MASK 0x1 +#define PMIC_TYPE_C_SW_VBUS_DET_DIS_SHIFT 10 +#define PMIC_TYPE_C_SW_CC_DET_DIS_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_TYPE_C_SW_CC_DET_DIS_MASK 0x1 +#define PMIC_TYPE_C_SW_CC_DET_DIS_SHIFT 11 +#define PMIC_TYPE_C_SW_PD_EN_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_TYPE_C_SW_PD_EN_MASK 0x1 +#define PMIC_TYPE_C_SW_PD_EN_SHIFT 12 +#define PMIC_W1_TYPE_C_SW_ENT_SNK_PWR_REDETECT_CMD_ADDR MT6353_TYPE_C_CC_SW_CTRL +#define PMIC_W1_TYPE_C_SW_ENT_SNK_PWR_REDETECT_CMD_MASK 0x1 +#define PMIC_W1_TYPE_C_SW_ENT_SNK_PWR_REDETECT_CMD_SHIFT 15 +#define PMIC_REG_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL_ADDR MT6353_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL +#define PMIC_REG_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL_MASK 0x1FFF +#define PMIC_REG_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_VOL_CC_DEBOUNCE_CNT_VAL_ADDR MT6353_TYPE_C_CC_VOL_DEBOUCE_CNT_VAL +#define PMIC_REG_TYPE_C_CC_VOL_CC_DEBOUNCE_CNT_VAL_MASK 0xFF +#define PMIC_REG_TYPE_C_CC_VOL_CC_DEBOUNCE_CNT_VAL_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_VOL_PD_DEBOUNCE_CNT_VAL_ADDR MT6353_TYPE_C_CC_VOL_DEBOUCE_CNT_VAL +#define PMIC_REG_TYPE_C_CC_VOL_PD_DEBOUNCE_CNT_VAL_MASK 0x1F +#define PMIC_REG_TYPE_C_CC_VOL_PD_DEBOUNCE_CNT_VAL_SHIFT 8 +#define PMIC_REG_TYPE_C_DRP_SRC_CNT_VAL_0_ADDR MT6353_TYPE_C_DRP_SRC_CNT_VAL_0 +#define PMIC_REG_TYPE_C_DRP_SRC_CNT_VAL_0_MASK 0xFFFF +#define PMIC_REG_TYPE_C_DRP_SRC_CNT_VAL_0_SHIFT 0 +#define PMIC_REG_TYPE_C_DRP_SNK_CNT_VAL_0_ADDR MT6353_TYPE_C_DRP_SNK_CNT_VAL_0 +#define PMIC_REG_TYPE_C_DRP_SNK_CNT_VAL_0_MASK 0xFFFF +#define PMIC_REG_TYPE_C_DRP_SNK_CNT_VAL_0_SHIFT 0 +#define PMIC_REG_TYPE_C_DRP_TRY_CNT_VAL_0_ADDR MT6353_TYPE_C_DRP_TRY_CNT_VAL_0 +#define PMIC_REG_TYPE_C_DRP_TRY_CNT_VAL_0_MASK 0xFFFF +#define PMIC_REG_TYPE_C_DRP_TRY_CNT_VAL_0_SHIFT 0 +#define PMIC_REG_TYPE_C_DRP_TRY_WAIT_CNT_VAL_0_ADDR MT6353_TYPE_C_DRP_TRY_WAIT_CNT_VAL_0 +#define PMIC_REG_TYPE_C_DRP_TRY_WAIT_CNT_VAL_0_MASK 0xFFFF +#define PMIC_REG_TYPE_C_DRP_TRY_WAIT_CNT_VAL_0_SHIFT 0 +#define PMIC_REG_TYPE_C_DRP_TRY_WAIT_CNT_VAL_1_ADDR MT6353_TYPE_C_DRP_TRY_WAIT_CNT_VAL_1 +#define PMIC_REG_TYPE_C_DRP_TRY_WAIT_CNT_VAL_1_MASK 0xF +#define PMIC_REG_TYPE_C_DRP_TRY_WAIT_CNT_VAL_1_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_DEFAULT_DAC_VAL_ADDR MT6353_TYPE_C_CC_SRC_DEFAULT_DAC_VAL +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_DEFAULT_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_DEFAULT_DAC_VAL_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_SRC_VRD_DEFAULT_DAC_VAL_ADDR MT6353_TYPE_C_CC_SRC_DEFAULT_DAC_VAL +#define PMIC_REG_TYPE_C_CC_SRC_VRD_DEFAULT_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SRC_VRD_DEFAULT_DAC_VAL_SHIFT 8 +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_15_DAC_VAL_ADDR MT6353_TYPE_C_CC_SRC_15_DAC_VAL +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_15_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_15_DAC_VAL_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_SRC_VRD_15_DAC_VAL_ADDR MT6353_TYPE_C_CC_SRC_15_DAC_VAL +#define PMIC_REG_TYPE_C_CC_SRC_VRD_15_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SRC_VRD_15_DAC_VAL_SHIFT 8 +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_30_DAC_VAL_ADDR MT6353_TYPE_C_CC_SRC_30_DAC_VAL +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_30_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SRC_VOPEN_30_DAC_VAL_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_SRC_VRD_30_DAC_VAL_ADDR MT6353_TYPE_C_CC_SRC_30_DAC_VAL +#define PMIC_REG_TYPE_C_CC_SRC_VRD_30_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SRC_VRD_30_DAC_VAL_SHIFT 8 +#define PMIC_REG_TYPE_C_CC_SNK_VRP30_DAC_VAL_ADDR MT6353_TYPE_C_CC_SNK_DAC_VAL_0 +#define PMIC_REG_TYPE_C_CC_SNK_VRP30_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SNK_VRP30_DAC_VAL_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_SNK_VRP15_DAC_VAL_ADDR MT6353_TYPE_C_CC_SNK_DAC_VAL_0 +#define PMIC_REG_TYPE_C_CC_SNK_VRP15_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SNK_VRP15_DAC_VAL_SHIFT 8 +#define PMIC_REG_TYPE_C_CC_SNK_VRPUSB_DAC_VAL_ADDR MT6353_TYPE_C_CC_SNK_DAC_VAL_1 +#define PMIC_REG_TYPE_C_CC_SNK_VRPUSB_DAC_VAL_MASK 0x3F +#define PMIC_REG_TYPE_C_CC_SNK_VRPUSB_DAC_VAL_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_SRC_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_SRC_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_SRC_INTR_EN_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_SNK_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_SNK_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_SNK_INTR_EN_SHIFT 1 +#define PMIC_REG_TYPE_C_CC_ENT_AUDIO_ACC_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_AUDIO_ACC_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_AUDIO_ACC_INTR_EN_SHIFT 2 +#define PMIC_REG_TYPE_C_CC_ENT_DBG_ACC_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_DBG_ACC_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_DBG_ACC_INTR_EN_SHIFT 3 +#define PMIC_REG_TYPE_C_CC_ENT_DISABLE_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_DISABLE_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_DISABLE_INTR_EN_SHIFT 4 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_SRC_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_SRC_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_SRC_INTR_EN_SHIFT 5 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_SNK_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_SNK_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_SNK_INTR_EN_SHIFT 6 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_SRC_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_SRC_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_SRC_INTR_EN_SHIFT 7 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_SNK_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_SNK_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_SNK_INTR_EN_SHIFT 8 +#define PMIC_REG_TYPE_C_CC_ENT_TRY_SRC_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_TRY_SRC_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_TRY_SRC_INTR_EN_SHIFT 9 +#define PMIC_REG_TYPE_C_CC_ENT_TRY_WAIT_SNK_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_TRY_WAIT_SNK_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_TRY_WAIT_SNK_INTR_EN_SHIFT 10 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_ACC_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_ACC_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_UNATTACH_ACC_INTR_EN_SHIFT 11 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_ACC_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_0 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_ACC_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_ACC_INTR_EN_SHIFT 12 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_IDLE_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_2 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_IDLE_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_IDLE_INTR_EN_SHIFT 0 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_DEFAULT_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_2 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_DEFAULT_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_DEFAULT_INTR_EN_SHIFT 1 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_15_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_2 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_15_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_15_INTR_EN_SHIFT 2 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_30_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_2 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_30_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_30_INTR_EN_SHIFT 3 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_REDETECT_INTR_EN_ADDR MT6353_TYPE_C_INTR_EN_2 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_REDETECT_INTR_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_REDETECT_INTR_EN_SHIFT 4 +#define PMIC_TYPE_C_CC_ENT_ATTACH_SRC_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_ATTACH_SRC_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_ATTACH_SRC_INTR_SHIFT 0 +#define PMIC_TYPE_C_CC_ENT_ATTACH_SNK_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_ATTACH_SNK_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_ATTACH_SNK_INTR_SHIFT 1 +#define PMIC_TYPE_C_CC_ENT_AUDIO_ACC_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_AUDIO_ACC_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_AUDIO_ACC_INTR_SHIFT 2 +#define PMIC_TYPE_C_CC_ENT_DBG_ACC_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_DBG_ACC_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_DBG_ACC_INTR_SHIFT 3 +#define PMIC_TYPE_C_CC_ENT_DISABLE_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_DISABLE_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_DISABLE_INTR_SHIFT 4 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_SRC_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_SRC_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_SRC_INTR_SHIFT 5 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_SNK_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_SNK_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_SNK_INTR_SHIFT 6 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_SRC_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_SRC_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_SRC_INTR_SHIFT 7 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_SNK_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_SNK_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_SNK_INTR_SHIFT 8 +#define PMIC_TYPE_C_CC_ENT_TRY_SRC_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_TRY_SRC_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_TRY_SRC_INTR_SHIFT 9 +#define PMIC_TYPE_C_CC_ENT_TRY_WAIT_SNK_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_TRY_WAIT_SNK_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_TRY_WAIT_SNK_INTR_SHIFT 10 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_ACC_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_ACC_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_UNATTACH_ACC_INTR_SHIFT 11 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_ACC_INTR_ADDR MT6353_TYPE_C_INTR_0 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_ACC_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_ACC_INTR_SHIFT 12 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_IDLE_INTR_ADDR MT6353_TYPE_C_INTR_2 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_IDLE_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_IDLE_INTR_SHIFT 0 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_DEFAULT_INTR_ADDR MT6353_TYPE_C_INTR_2 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_DEFAULT_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_DEFAULT_INTR_SHIFT 1 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_15_INTR_ADDR MT6353_TYPE_C_INTR_2 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_15_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_15_INTR_SHIFT 2 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_30_INTR_ADDR MT6353_TYPE_C_INTR_2 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_30_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_30_INTR_SHIFT 3 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_REDETECT_INTR_ADDR MT6353_TYPE_C_INTR_2 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_REDETECT_INTR_MASK 0x1 +#define PMIC_TYPE_C_CC_ENT_SNK_PWR_REDETECT_INTR_SHIFT 4 +#define PMIC_RO_TYPE_C_CC_ST_ADDR MT6353_TYPE_C_CC_STATUS +#define PMIC_RO_TYPE_C_CC_ST_MASK 0xF +#define PMIC_RO_TYPE_C_CC_ST_SHIFT 0 +#define PMIC_RO_TYPE_C_ROUTED_CC_ADDR MT6353_TYPE_C_CC_STATUS +#define PMIC_RO_TYPE_C_ROUTED_CC_MASK 0x1 +#define PMIC_RO_TYPE_C_ROUTED_CC_SHIFT 15 +#define PMIC_RO_TYPE_C_CC_SNK_PWR_ST_ADDR MT6353_TYPE_C_PWR_STATUS +#define PMIC_RO_TYPE_C_CC_SNK_PWR_ST_MASK 0x7 +#define PMIC_RO_TYPE_C_CC_SNK_PWR_ST_SHIFT 0 +#define PMIC_RO_TYPE_C_CC_PWR_ROLE_ADDR MT6353_TYPE_C_PWR_STATUS +#define PMIC_RO_TYPE_C_CC_PWR_ROLE_MASK 0x1 +#define PMIC_RO_TYPE_C_CC_PWR_ROLE_SHIFT 4 +#define PMIC_RO_TYPE_C_DRIVE_VCONN_CAPABLE_ADDR MT6353_TYPE_C_PWR_STATUS +#define PMIC_RO_TYPE_C_DRIVE_VCONN_CAPABLE_MASK 0x1 +#define PMIC_RO_TYPE_C_DRIVE_VCONN_CAPABLE_SHIFT 5 +#define PMIC_RO_TYPE_C_AD_CC_CMP_OUT_ADDR MT6353_TYPE_C_PWR_STATUS +#define PMIC_RO_TYPE_C_AD_CC_CMP_OUT_MASK 0x1 +#define PMIC_RO_TYPE_C_AD_CC_CMP_OUT_SHIFT 6 +#define PMIC_RO_AD_CC_VUSB33_RDY_ADDR MT6353_TYPE_C_PWR_STATUS +#define PMIC_RO_AD_CC_VUSB33_RDY_MASK 0x1 +#define PMIC_RO_AD_CC_VUSB33_RDY_SHIFT 7 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RPDE_ADDR MT6353_TYPE_C_PHY_RG_CC1_RESISTENCE_0 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RPDE_MASK 0x7 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RPDE_SHIFT 0 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RP15_ADDR MT6353_TYPE_C_PHY_RG_CC1_RESISTENCE_0 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RP15_MASK 0x1F +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RP15_SHIFT 8 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RP3_ADDR MT6353_TYPE_C_PHY_RG_CC1_RESISTENCE_1 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RP3_MASK 0x1F +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RP3_SHIFT 0 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RD_ADDR MT6353_TYPE_C_PHY_RG_CC1_RESISTENCE_1 +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RD_MASK 0x1F +#define PMIC_REG_TYPE_C_PHY_RG_CC1_RD_SHIFT 8 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RPDE_ADDR MT6353_TYPE_C_PHY_RG_CC2_RESISTENCE_0 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RPDE_MASK 0x7 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RPDE_SHIFT 0 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RP15_ADDR MT6353_TYPE_C_PHY_RG_CC2_RESISTENCE_0 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RP15_MASK 0x1F +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RP15_SHIFT 8 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RP3_ADDR MT6353_TYPE_C_PHY_RG_CC2_RESISTENCE_1 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RP3_MASK 0x1F +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RP3_SHIFT 0 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RD_ADDR MT6353_TYPE_C_PHY_RG_CC2_RESISTENCE_1 +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RD_MASK 0x1F +#define PMIC_REG_TYPE_C_PHY_RG_CC2_RD_SHIFT 8 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_RCC1_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_RCC1_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_RCC1_SHIFT 0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_RCC2_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_RCC2_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_RCC2_SHIFT 1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_LEV_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_LEV_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_LEV_EN_SHIFT 2 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SW_SEL_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SW_SEL_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SW_SEL_SHIFT 3 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_BIAS_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_BIAS_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_BIAS_EN_SHIFT 4 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_LPF_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_LPF_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_LPF_EN_SHIFT 5 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_ADCSW_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_ADCSW_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_ADCSW_EN_SHIFT 6 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SASW_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SASW_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SASW_EN_SHIFT 7 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_EN_SHIFT 8 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SACLK_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SACLK_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SACLK_SHIFT 9 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_IN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_IN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_IN_SHIFT 10 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_CAL_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_CAL_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_CAL_SHIFT 11 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_GAIN_CAL_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_ENABLE +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_GAIN_CAL_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_GAIN_CAL_SHIFT 12 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RPCC1_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RPCC1_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RPCC1_EN_SHIFT 0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RDCC1_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RDCC1_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RDCC1_EN_SHIFT 1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RACC1_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RACC1_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RACC1_EN_SHIFT 2 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RPCC2_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RPCC2_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RPCC2_EN_SHIFT 3 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RDCC2_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RDCC2_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RDCC2_EN_SHIFT 4 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RACC2_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RACC2_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RACC2_EN_SHIFT 5 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_LEV_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_LEV_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_LEV_EN_SHIFT 6 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SW_SEL_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SW_SEL_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SW_SEL_SHIFT 7 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_BIAS_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_BIAS_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_BIAS_EN_SHIFT 8 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_LPF_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_LPF_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_LPF_EN_SHIFT 9 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_ADCSW_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_ADCSW_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_ADCSW_EN_SHIFT 10 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SASW_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SASW_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SASW_EN_SHIFT 11 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_EN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_EN_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_EN_SHIFT 12 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SACLK_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SACLK_MASK 0x1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SACLK_SHIFT 13 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_IN_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_IN_MASK 0x3F +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_IN_SHIFT 0 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_CAL_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_CAL_MASK 0xF +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_CAL_SHIFT 8 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_GAIN_CAL_ADDR MT6353_TYPE_C_CC_SW_FORCE_MODE_VAL_1 +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_GAIN_CAL_MASK 0xF +#define PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_GAIN_CAL_SHIFT 12 +#define PMIC_TYPE_C_DAC_CAL_START_ADDR MT6353_TYPE_C_CC_DAC_CALI_CTRL +#define PMIC_TYPE_C_DAC_CAL_START_MASK 0x1 +#define PMIC_TYPE_C_DAC_CAL_START_SHIFT 0 +#define PMIC_REG_TYPE_C_DAC_CAL_STAGE_ADDR MT6353_TYPE_C_CC_DAC_CALI_CTRL +#define PMIC_REG_TYPE_C_DAC_CAL_STAGE_MASK 0x1 +#define PMIC_REG_TYPE_C_DAC_CAL_STAGE_SHIFT 1 +#define PMIC_RO_TYPE_C_DAC_OK_ADDR MT6353_TYPE_C_CC_DAC_CALI_CTRL +#define PMIC_RO_TYPE_C_DAC_OK_MASK 0x1 +#define PMIC_RO_TYPE_C_DAC_OK_SHIFT 4 +#define PMIC_RO_TYPE_C_DAC_FAIL_ADDR MT6353_TYPE_C_CC_DAC_CALI_CTRL +#define PMIC_RO_TYPE_C_DAC_FAIL_MASK 0x1 +#define PMIC_RO_TYPE_C_DAC_FAIL_SHIFT 5 +#define PMIC_RO_DA_CC_DAC_CAL_ADDR MT6353_TYPE_C_CC_DAC_CALI_RESULT +#define PMIC_RO_DA_CC_DAC_CAL_MASK 0xF +#define PMIC_RO_DA_CC_DAC_CAL_SHIFT 0 +#define PMIC_RO_DA_CC_DAC_GAIN_CAL_ADDR MT6353_TYPE_C_CC_DAC_CALI_RESULT +#define PMIC_RO_DA_CC_DAC_GAIN_CAL_MASK 0xF +#define PMIC_RO_DA_CC_DAC_GAIN_CAL_SHIFT 4 +#define PMIC_REG_TYPE_C_DBG_PORT_SEL_0_ADDR MT6353_TYPE_C_DEBUG_PORT_SELECT_0 +#define PMIC_REG_TYPE_C_DBG_PORT_SEL_0_MASK 0xFFFF +#define PMIC_REG_TYPE_C_DBG_PORT_SEL_0_SHIFT 0 +#define PMIC_REG_TYPE_C_DBG_PORT_SEL_1_ADDR MT6353_TYPE_C_DEBUG_PORT_SELECT_1 +#define PMIC_REG_TYPE_C_DBG_PORT_SEL_1_MASK 0xFFFF +#define PMIC_REG_TYPE_C_DBG_PORT_SEL_1_SHIFT 0 +#define PMIC_REG_TYPE_C_DBG_MOD_SEL_ADDR MT6353_TYPE_C_DEBUG_MODE_SELECT +#define PMIC_REG_TYPE_C_DBG_MOD_SEL_MASK 0xFFFF +#define PMIC_REG_TYPE_C_DBG_MOD_SEL_SHIFT 0 +#define PMIC_RO_TYPE_C_DBG_OUT_READ_0_ADDR MT6353_TYPE_C_DEBUG_OUT_READ_0 +#define PMIC_RO_TYPE_C_DBG_OUT_READ_0_MASK 0xFFFF +#define PMIC_RO_TYPE_C_DBG_OUT_READ_0_SHIFT 0 +#define PMIC_RO_TYPE_C_DBG_OUT_READ_1_ADDR MT6353_TYPE_C_DEBUG_OUT_READ_1 +#define PMIC_RO_TYPE_C_DBG_OUT_READ_1_MASK 0xFFFF +#define PMIC_RO_TYPE_C_DBG_OUT_READ_1_SHIFT 0 +#define PMIC_HWCID_ADDR MT6353_HWCID +#define PMIC_HWCID_MASK 0xFFFF +#define PMIC_HWCID_SHIFT 0 +#define PMIC_SWCID_ADDR MT6353_SWCID +#define PMIC_SWCID_MASK 0xFFFF +#define PMIC_SWCID_SHIFT 0 +#define PMIC_RG_SRCLKEN_IN0_EN_ADDR MT6353_TOP_CON +#define PMIC_RG_SRCLKEN_IN0_EN_MASK 0x1 +#define PMIC_RG_SRCLKEN_IN0_EN_SHIFT 0 +#define PMIC_RG_SRCLKEN_IN1_EN_ADDR MT6353_TOP_CON +#define PMIC_RG_SRCLKEN_IN1_EN_MASK 0x1 +#define PMIC_RG_SRCLKEN_IN1_EN_SHIFT 1 +#define PMIC_RG_OSC_SEL_ADDR MT6353_TOP_CON +#define PMIC_RG_OSC_SEL_MASK 0x1 +#define PMIC_RG_OSC_SEL_SHIFT 2 +#define PMIC_RG_SRCLKEN_IN2_EN_ADDR MT6353_TOP_CON +#define PMIC_RG_SRCLKEN_IN2_EN_MASK 0x1 +#define PMIC_RG_SRCLKEN_IN2_EN_SHIFT 3 +#define PMIC_RG_SRCLKEN_IN0_HW_MODE_ADDR MT6353_TOP_CON +#define PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK 0x1 +#define PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT 4 +#define PMIC_RG_SRCLKEN_IN1_HW_MODE_ADDR MT6353_TOP_CON +#define PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK 0x1 +#define PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT 5 +#define PMIC_RG_OSC_SEL_HW_MODE_ADDR MT6353_TOP_CON +#define PMIC_RG_OSC_SEL_HW_MODE_MASK 0x1 +#define PMIC_RG_OSC_SEL_HW_MODE_SHIFT 6 +#define PMIC_RG_SRCLKEN_IN_SYNC_EN_ADDR MT6353_TOP_CON +#define PMIC_RG_SRCLKEN_IN_SYNC_EN_MASK 0x1 +#define PMIC_RG_SRCLKEN_IN_SYNC_EN_SHIFT 8 +#define PMIC_RG_OSC_EN_AUTO_OFF_ADDR MT6353_TOP_CON +#define PMIC_RG_OSC_EN_AUTO_OFF_MASK 0x1 +#define PMIC_RG_OSC_EN_AUTO_OFF_SHIFT 9 +#define PMIC_TEST_OUT_ADDR MT6353_TEST_OUT +#define PMIC_TEST_OUT_MASK 0xFF +#define PMIC_TEST_OUT_SHIFT 0 +#define PMIC_RG_MON_FLAG_SEL_ADDR MT6353_TEST_CON0 +#define PMIC_RG_MON_FLAG_SEL_MASK 0xFF +#define PMIC_RG_MON_FLAG_SEL_SHIFT 0 +#define PMIC_RG_MON_GRP_SEL_ADDR MT6353_TEST_CON0 +#define PMIC_RG_MON_GRP_SEL_MASK 0x1F +#define PMIC_RG_MON_GRP_SEL_SHIFT 8 +#define PMIC_RG_NANDTREE_MODE_ADDR MT6353_TEST_CON1 +#define PMIC_RG_NANDTREE_MODE_MASK 0x1 +#define PMIC_RG_NANDTREE_MODE_SHIFT 0 +#define PMIC_RG_TEST_AUXADC_ADDR MT6353_TEST_CON1 +#define PMIC_RG_TEST_AUXADC_MASK 0x1 +#define PMIC_RG_TEST_AUXADC_SHIFT 1 +#define PMIC_RG_EFUSE_MODE_ADDR MT6353_TEST_CON1 +#define PMIC_RG_EFUSE_MODE_MASK 0x1 +#define PMIC_RG_EFUSE_MODE_SHIFT 2 +#define PMIC_RG_TEST_STRUP_ADDR MT6353_TEST_CON1 +#define PMIC_RG_TEST_STRUP_MASK 0x1 +#define PMIC_RG_TEST_STRUP_SHIFT 3 +#define PMIC_TESTMODE_SW_ADDR MT6353_TESTMODE_SW +#define PMIC_TESTMODE_SW_MASK 0x1 +#define PMIC_TESTMODE_SW_SHIFT 0 +#define PMIC_EN_STATUS_VDRAM_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VDRAM_MASK 0x1 +#define PMIC_EN_STATUS_VDRAM_SHIFT 0 +#define PMIC_EN_STATUS_VSRAM_PROC_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VSRAM_PROC_MASK 0x1 +#define PMIC_EN_STATUS_VSRAM_PROC_SHIFT 1 +#define PMIC_EN_STATUS_VAUD28_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VAUD28_MASK 0x1 +#define PMIC_EN_STATUS_VAUD28_SHIFT 2 +#define PMIC_EN_STATUS_VAUX18_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VAUX18_MASK 0x1 +#define PMIC_EN_STATUS_VAUX18_SHIFT 3 +#define PMIC_EN_STATUS_VCAMD_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VCAMD_MASK 0x1 +#define PMIC_EN_STATUS_VCAMD_SHIFT 4 +#define PMIC_EN_STATUS_VLDO28_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VLDO28_MASK 0x1 +#define PMIC_EN_STATUS_VLDO28_SHIFT 5 +#define PMIC_EN_STATUS_VCAMIO_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VCAMIO_MASK 0x1 +#define PMIC_EN_STATUS_VCAMIO_SHIFT 6 +#define PMIC_EN_STATUS_VCAMA_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VCAMA_MASK 0x1 +#define PMIC_EN_STATUS_VCAMA_SHIFT 7 +#define PMIC_EN_STATUS_VCN18_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VCN18_MASK 0x1 +#define PMIC_EN_STATUS_VCN18_SHIFT 8 +#define PMIC_EN_STATUS_VCN28_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VCN28_MASK 0x1 +#define PMIC_EN_STATUS_VCN28_SHIFT 9 +#define PMIC_EN_STATUS_VCN33_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VCN33_MASK 0x1 +#define PMIC_EN_STATUS_VCN33_SHIFT 10 +#define PMIC_EN_STATUS_VRF12_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VRF12_MASK 0x1 +#define PMIC_EN_STATUS_VRF12_SHIFT 11 +#define PMIC_EN_STATUS_VRF18_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VRF18_MASK 0x1 +#define PMIC_EN_STATUS_VRF18_SHIFT 12 +#define PMIC_EN_STATUS_VXO22_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VXO22_MASK 0x1 +#define PMIC_EN_STATUS_VXO22_SHIFT 13 +#define PMIC_EN_STATUS_VTCXO24_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VTCXO24_MASK 0x1 +#define PMIC_EN_STATUS_VTCXO24_SHIFT 14 +#define PMIC_EN_STATUS_VTCXO28_ADDR MT6353_EN_STATUS1 +#define PMIC_EN_STATUS_VTCXO28_MASK 0x1 +#define PMIC_EN_STATUS_VTCXO28_SHIFT 15 +#define PMIC_EN_STATUS_VS1_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VS1_MASK 0x1 +#define PMIC_EN_STATUS_VS1_SHIFT 1 +#define PMIC_EN_STATUS_VCORE_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VCORE_MASK 0x1 +#define PMIC_EN_STATUS_VCORE_SHIFT 2 +#define PMIC_EN_STATUS_VPROC_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VPROC_MASK 0x1 +#define PMIC_EN_STATUS_VPROC_SHIFT 3 +#define PMIC_EN_STATUS_VPA_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VPA_MASK 0x1 +#define PMIC_EN_STATUS_VPA_SHIFT 4 +#define PMIC_EN_STATUS_VRTC_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VRTC_MASK 0x1 +#define PMIC_EN_STATUS_VRTC_SHIFT 5 +#define PMIC_EN_STATUS_TREF_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_TREF_MASK 0x1 +#define PMIC_EN_STATUS_TREF_SHIFT 6 +#define PMIC_EN_STATUS_VIBR_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VIBR_MASK 0x1 +#define PMIC_EN_STATUS_VIBR_SHIFT 7 +#define PMIC_EN_STATUS_VIO18_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VIO18_MASK 0x1 +#define PMIC_EN_STATUS_VIO18_SHIFT 8 +#define PMIC_EN_STATUS_VEMC33_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VEMC33_MASK 0x1 +#define PMIC_EN_STATUS_VEMC33_SHIFT 9 +#define PMIC_EN_STATUS_VUSB33_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VUSB33_MASK 0x1 +#define PMIC_EN_STATUS_VUSB33_SHIFT 10 +#define PMIC_EN_STATUS_VMCH_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VMCH_MASK 0x1 +#define PMIC_EN_STATUS_VMCH_SHIFT 11 +#define PMIC_EN_STATUS_VMC_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VMC_MASK 0x1 +#define PMIC_EN_STATUS_VMC_SHIFT 12 +#define PMIC_EN_STATUS_VIO28_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VIO28_MASK 0x1 +#define PMIC_EN_STATUS_VIO28_SHIFT 13 +#define PMIC_EN_STATUS_VSIM2_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VSIM2_MASK 0x1 +#define PMIC_EN_STATUS_VSIM2_SHIFT 14 +#define PMIC_EN_STATUS_VSIM1_ADDR MT6353_EN_STATUS2 +#define PMIC_EN_STATUS_VSIM1_MASK 0x1 +#define PMIC_EN_STATUS_VSIM1_SHIFT 15 +#define PMIC_OC_STATUS_VDRAM_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VDRAM_MASK 0x1 +#define PMIC_OC_STATUS_VDRAM_SHIFT 0 +#define PMIC_OC_STATUS_VSRAM_PROC_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VSRAM_PROC_MASK 0x1 +#define PMIC_OC_STATUS_VSRAM_PROC_SHIFT 1 +#define PMIC_OC_STATUS_VAUD28_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VAUD28_MASK 0x1 +#define PMIC_OC_STATUS_VAUD28_SHIFT 2 +#define PMIC_OC_STATUS_VAUX18_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VAUX18_MASK 0x1 +#define PMIC_OC_STATUS_VAUX18_SHIFT 3 +#define PMIC_OC_STATUS_VCAMD_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VCAMD_MASK 0x1 +#define PMIC_OC_STATUS_VCAMD_SHIFT 4 +#define PMIC_OC_STATUS_VLDO28_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VLDO28_MASK 0x1 +#define PMIC_OC_STATUS_VLDO28_SHIFT 5 +#define PMIC_OC_STATUS_VCAMIO_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VCAMIO_MASK 0x1 +#define PMIC_OC_STATUS_VCAMIO_SHIFT 6 +#define PMIC_OC_STATUS_VCAMA_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VCAMA_MASK 0x1 +#define PMIC_OC_STATUS_VCAMA_SHIFT 7 +#define PMIC_OC_STATUS_VCN18_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VCN18_MASK 0x1 +#define PMIC_OC_STATUS_VCN18_SHIFT 8 +#define PMIC_OC_STATUS_VCN28_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VCN28_MASK 0x1 +#define PMIC_OC_STATUS_VCN28_SHIFT 9 +#define PMIC_OC_STATUS_VCN33_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VCN33_MASK 0x1 +#define PMIC_OC_STATUS_VCN33_SHIFT 10 +#define PMIC_OC_STATUS_VRF12_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VRF12_MASK 0x1 +#define PMIC_OC_STATUS_VRF12_SHIFT 11 +#define PMIC_OC_STATUS_VRF18_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VRF18_MASK 0x1 +#define PMIC_OC_STATUS_VRF18_SHIFT 12 +#define PMIC_OC_STATUS_VXO22_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VXO22_MASK 0x1 +#define PMIC_OC_STATUS_VXO22_SHIFT 13 +#define PMIC_OC_STATUS_VTCXO24_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VTCXO24_MASK 0x1 +#define PMIC_OC_STATUS_VTCXO24_SHIFT 14 +#define PMIC_OC_STATUS_VTCXO28_ADDR MT6353_OCSTATUS1 +#define PMIC_OC_STATUS_VTCXO28_MASK 0x1 +#define PMIC_OC_STATUS_VTCXO28_SHIFT 15 +#define PMIC_OC_STATUS_VS1_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VS1_MASK 0x1 +#define PMIC_OC_STATUS_VS1_SHIFT 2 +#define PMIC_OC_STATUS_VCORE_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VCORE_MASK 0x1 +#define PMIC_OC_STATUS_VCORE_SHIFT 3 +#define PMIC_OC_STATUS_VPROC_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VPROC_MASK 0x1 +#define PMIC_OC_STATUS_VPROC_SHIFT 4 +#define PMIC_OC_STATUS_VPA_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VPA_MASK 0x1 +#define PMIC_OC_STATUS_VPA_SHIFT 5 +#define PMIC_OC_STATUS_TREF_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_TREF_MASK 0x1 +#define PMIC_OC_STATUS_TREF_SHIFT 6 +#define PMIC_OC_STATUS_VIBR_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VIBR_MASK 0x1 +#define PMIC_OC_STATUS_VIBR_SHIFT 7 +#define PMIC_OC_STATUS_VIO18_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VIO18_MASK 0x1 +#define PMIC_OC_STATUS_VIO18_SHIFT 8 +#define PMIC_OC_STATUS_VEMC33_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VEMC33_MASK 0x1 +#define PMIC_OC_STATUS_VEMC33_SHIFT 9 +#define PMIC_OC_STATUS_VUSB33_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VUSB33_MASK 0x1 +#define PMIC_OC_STATUS_VUSB33_SHIFT 10 +#define PMIC_OC_STATUS_VMCH_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VMCH_MASK 0x1 +#define PMIC_OC_STATUS_VMCH_SHIFT 11 +#define PMIC_OC_STATUS_VMC_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VMC_MASK 0x1 +#define PMIC_OC_STATUS_VMC_SHIFT 12 +#define PMIC_OC_STATUS_VIO28_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VIO28_MASK 0x1 +#define PMIC_OC_STATUS_VIO28_SHIFT 13 +#define PMIC_OC_STATUS_VSIM2_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VSIM2_MASK 0x1 +#define PMIC_OC_STATUS_VSIM2_SHIFT 14 +#define PMIC_OC_STATUS_VSIM1_ADDR MT6353_OCSTATUS2 +#define PMIC_OC_STATUS_VSIM1_MASK 0x1 +#define PMIC_OC_STATUS_VSIM1_SHIFT 15 +#define PMIC_VCORE2_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VCORE2_PG_DEB_MASK 0x1 +#define PMIC_VCORE2_PG_DEB_SHIFT 0 +#define PMIC_VS1_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VS1_PG_DEB_MASK 0x1 +#define PMIC_VS1_PG_DEB_SHIFT 1 +#define PMIC_VCORE_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VCORE_PG_DEB_MASK 0x1 +#define PMIC_VCORE_PG_DEB_SHIFT 2 +#define PMIC_VPROC_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VPROC_PG_DEB_MASK 0x1 +#define PMIC_VPROC_PG_DEB_SHIFT 3 +#define PMIC_VIO18_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VIO18_PG_DEB_MASK 0x1 +#define PMIC_VIO18_PG_DEB_SHIFT 4 +#define PMIC_VEMC33_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VEMC33_PG_DEB_MASK 0x1 +#define PMIC_VEMC33_PG_DEB_SHIFT 5 +#define PMIC_VUSB33_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VUSB33_PG_DEB_MASK 0x1 +#define PMIC_VUSB33_PG_DEB_SHIFT 6 +#define PMIC_VMCH_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VMCH_PG_DEB_MASK 0x1 +#define PMIC_VMCH_PG_DEB_SHIFT 7 +#define PMIC_VMC_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VMC_PG_DEB_MASK 0x1 +#define PMIC_VMC_PG_DEB_SHIFT 8 +#define PMIC_VIO28_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VIO28_PG_DEB_MASK 0x1 +#define PMIC_VIO28_PG_DEB_SHIFT 9 +#define PMIC_VDRAM_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VDRAM_PG_DEB_MASK 0x1 +#define PMIC_VDRAM_PG_DEB_SHIFT 10 +#define PMIC_VSRAM_PROC_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VSRAM_PROC_PG_DEB_MASK 0x1 +#define PMIC_VSRAM_PROC_PG_DEB_SHIFT 11 +#define PMIC_VAUD28_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VAUD28_PG_DEB_MASK 0x1 +#define PMIC_VAUD28_PG_DEB_SHIFT 12 +#define PMIC_VAUX18_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VAUX18_PG_DEB_MASK 0x1 +#define PMIC_VAUX18_PG_DEB_SHIFT 13 +#define PMIC_VXO22_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VXO22_PG_DEB_MASK 0x1 +#define PMIC_VXO22_PG_DEB_SHIFT 14 +#define PMIC_VTCXO24_PG_DEB_ADDR MT6353_PGDEBSTATUS0 +#define PMIC_VTCXO24_PG_DEB_MASK 0x1 +#define PMIC_VTCXO24_PG_DEB_SHIFT 15 +#define PMIC_STRUP_VMCH_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VMCH_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VMCH_PG_STATUS_GATED_SHIFT 0 +#define PMIC_STRUP_VMC_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VMC_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VMC_PG_STATUS_GATED_SHIFT 1 +#define PMIC_STRUP_VXO22_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VXO22_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VXO22_PG_STATUS_GATED_SHIFT 2 +#define PMIC_STRUP_VTCXO24_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VTCXO24_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VTCXO24_PG_STATUS_GATED_SHIFT 3 +#define PMIC_STRUP_VUSB33_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VUSB33_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VUSB33_PG_STATUS_GATED_SHIFT 4 +#define PMIC_STRUP_VSRAM_PROC_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VSRAM_PROC_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VSRAM_PROC_PG_STATUS_GATED_SHIFT 5 +#define PMIC_STRUP_VPROC_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VPROC_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VPROC_PG_STATUS_GATED_SHIFT 6 +#define PMIC_STRUP_VDRAM_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VDRAM_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VDRAM_PG_STATUS_GATED_SHIFT 7 +#define PMIC_STRUP_VAUD28_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VAUD28_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VAUD28_PG_STATUS_GATED_SHIFT 8 +#define PMIC_STRUP_VIO28_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VIO28_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VIO28_PG_STATUS_GATED_SHIFT 9 +#define PMIC_STRUP_VEMC33_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VEMC33_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VEMC33_PG_STATUS_GATED_SHIFT 10 +#define PMIC_STRUP_VIO18_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VIO18_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VIO18_PG_STATUS_GATED_SHIFT 11 +#define PMIC_STRUP_VS1_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VS1_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VS1_PG_STATUS_GATED_SHIFT 12 +#define PMIC_STRUP_VCORE_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VCORE_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VCORE_PG_STATUS_GATED_SHIFT 13 +#define PMIC_STRUP_VAUX18_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VAUX18_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VAUX18_PG_STATUS_GATED_SHIFT 14 +#define PMIC_STRUP_VCORE2_PG_STATUS_GATED_ADDR MT6353_PGSTATUS0 +#define PMIC_STRUP_VCORE2_PG_STATUS_GATED_MASK 0x1 +#define PMIC_STRUP_VCORE2_PG_STATUS_GATED_SHIFT 15 +#define PMIC_PMU_THERMAL_DEB_ADDR MT6353_THERMALSTATUS +#define PMIC_PMU_THERMAL_DEB_MASK 0x1 +#define PMIC_PMU_THERMAL_DEB_SHIFT 14 +#define PMIC_STRUP_THERMAL_STATUS_ADDR MT6353_THERMALSTATUS +#define PMIC_STRUP_THERMAL_STATUS_MASK 0x1 +#define PMIC_STRUP_THERMAL_STATUS_SHIFT 15 +#define PMIC_PMU_TEST_MODE_SCAN_ADDR MT6353_TOPSTATUS +#define PMIC_PMU_TEST_MODE_SCAN_MASK 0x1 +#define PMIC_PMU_TEST_MODE_SCAN_SHIFT 0 +#define PMIC_PWRKEY_DEB_ADDR MT6353_TOPSTATUS +#define PMIC_PWRKEY_DEB_MASK 0x1 +#define PMIC_PWRKEY_DEB_SHIFT 1 +#define PMIC_HOMEKEY_DEB_ADDR MT6353_TOPSTATUS +#define PMIC_HOMEKEY_DEB_MASK 0x1 +#define PMIC_HOMEKEY_DEB_SHIFT 2 +#define PMIC_RTC_XTAL_DET_DONE_ADDR MT6353_TOPSTATUS +#define PMIC_RTC_XTAL_DET_DONE_MASK 0x1 +#define PMIC_RTC_XTAL_DET_DONE_SHIFT 6 +#define PMIC_XOSC32_ENB_DET_ADDR MT6353_TOPSTATUS +#define PMIC_XOSC32_ENB_DET_MASK 0x1 +#define PMIC_XOSC32_ENB_DET_SHIFT 7 +#define PMIC_RTC_XTAL_DET_RSV_ADDR MT6353_TOPSTATUS +#define PMIC_RTC_XTAL_DET_RSV_MASK 0xF +#define PMIC_RTC_XTAL_DET_RSV_SHIFT 8 +#define PMIC_RG_PMU_TDSEL_ADDR MT6353_TDSEL_CON +#define PMIC_RG_PMU_TDSEL_MASK 0x1 +#define PMIC_RG_PMU_TDSEL_SHIFT 0 +#define PMIC_RG_SPI_TDSEL_ADDR MT6353_TDSEL_CON +#define PMIC_RG_SPI_TDSEL_MASK 0x1 +#define PMIC_RG_SPI_TDSEL_SHIFT 1 +#define PMIC_RG_AUD_TDSEL_ADDR MT6353_TDSEL_CON +#define PMIC_RG_AUD_TDSEL_MASK 0x1 +#define PMIC_RG_AUD_TDSEL_SHIFT 2 +#define PMIC_RG_E32CAL_TDSEL_ADDR MT6353_TDSEL_CON +#define PMIC_RG_E32CAL_TDSEL_MASK 0x1 +#define PMIC_RG_E32CAL_TDSEL_SHIFT 3 +#define PMIC_RG_PMU_RDSEL_ADDR MT6353_RDSEL_CON +#define PMIC_RG_PMU_RDSEL_MASK 0x1 +#define PMIC_RG_PMU_RDSEL_SHIFT 0 +#define PMIC_RG_SPI_RDSEL_ADDR MT6353_RDSEL_CON +#define PMIC_RG_SPI_RDSEL_MASK 0x1 +#define PMIC_RG_SPI_RDSEL_SHIFT 1 +#define PMIC_RG_AUD_RDSEL_ADDR MT6353_RDSEL_CON +#define PMIC_RG_AUD_RDSEL_MASK 0x1 +#define PMIC_RG_AUD_RDSEL_SHIFT 2 +#define PMIC_RG_E32CAL_RDSEL_ADDR MT6353_RDSEL_CON +#define PMIC_RG_E32CAL_RDSEL_MASK 0x1 +#define PMIC_RG_E32CAL_RDSEL_SHIFT 3 +#define PMIC_RG_SMT_WDTRSTB_IN_ADDR MT6353_SMT_CON0 +#define PMIC_RG_SMT_WDTRSTB_IN_MASK 0x1 +#define PMIC_RG_SMT_WDTRSTB_IN_SHIFT 0 +#define PMIC_RG_SMT_HOMEKEY_ADDR MT6353_SMT_CON0 +#define PMIC_RG_SMT_HOMEKEY_MASK 0x1 +#define PMIC_RG_SMT_HOMEKEY_SHIFT 1 +#define PMIC_RG_SMT_SRCLKEN_IN0_ADDR MT6353_SMT_CON0 +#define PMIC_RG_SMT_SRCLKEN_IN0_MASK 0x1 +#define PMIC_RG_SMT_SRCLKEN_IN0_SHIFT 2 +#define PMIC_RG_SMT_SRCLKEN_IN1_ADDR MT6353_SMT_CON0 +#define PMIC_RG_SMT_SRCLKEN_IN1_MASK 0x1 +#define PMIC_RG_SMT_SRCLKEN_IN1_SHIFT 3 +#define PMIC_RG_SMT_RTC_32K1V8_0_ADDR MT6353_SMT_CON0 +#define PMIC_RG_SMT_RTC_32K1V8_0_MASK 0x1 +#define PMIC_RG_SMT_RTC_32K1V8_0_SHIFT 4 +#define PMIC_RG_SMT_RTC_32K1V8_1_ADDR MT6353_SMT_CON0 +#define PMIC_RG_SMT_RTC_32K1V8_1_MASK 0x1 +#define PMIC_RG_SMT_RTC_32K1V8_1_SHIFT 5 +#define PMIC_RG_SMT_SPI_CLK_ADDR MT6353_SMT_CON1 +#define PMIC_RG_SMT_SPI_CLK_MASK 0x1 +#define PMIC_RG_SMT_SPI_CLK_SHIFT 0 +#define PMIC_RG_SMT_SPI_CSN_ADDR MT6353_SMT_CON1 +#define PMIC_RG_SMT_SPI_CSN_MASK 0x1 +#define PMIC_RG_SMT_SPI_CSN_SHIFT 1 +#define PMIC_RG_SMT_SPI_MOSI_ADDR MT6353_SMT_CON1 +#define PMIC_RG_SMT_SPI_MOSI_MASK 0x1 +#define PMIC_RG_SMT_SPI_MOSI_SHIFT 2 +#define PMIC_RG_SMT_SPI_MISO_ADDR MT6353_SMT_CON1 +#define PMIC_RG_SMT_SPI_MISO_MASK 0x1 +#define PMIC_RG_SMT_SPI_MISO_SHIFT 3 +#define PMIC_RG_SMT_AUD_CLK_ADDR MT6353_SMT_CON2 +#define PMIC_RG_SMT_AUD_CLK_MASK 0x1 +#define PMIC_RG_SMT_AUD_CLK_SHIFT 0 +#define PMIC_RG_SMT_AUD_DAT_MOSI_ADDR MT6353_SMT_CON2 +#define PMIC_RG_SMT_AUD_DAT_MOSI_MASK 0x1 +#define PMIC_RG_SMT_AUD_DAT_MOSI_SHIFT 1 +#define PMIC_RG_SMT_AUD_DAT_MISO_ADDR MT6353_SMT_CON2 +#define PMIC_RG_SMT_AUD_DAT_MISO_MASK 0x1 +#define PMIC_RG_SMT_AUD_DAT_MISO_SHIFT 2 +#define PMIC_RG_SMT_ANC_DAT_MOSI_ADDR MT6353_SMT_CON2 +#define PMIC_RG_SMT_ANC_DAT_MOSI_MASK 0x1 +#define PMIC_RG_SMT_ANC_DAT_MOSI_SHIFT 3 +#define PMIC_RG_SMT_VOW_CLK_MISO_ADDR MT6353_SMT_CON2 +#define PMIC_RG_SMT_VOW_CLK_MISO_MASK 0x1 +#define PMIC_RG_SMT_VOW_CLK_MISO_SHIFT 4 +#define PMIC_RG_SMT_ENBB_ADDR MT6353_SMT_CON2 +#define PMIC_RG_SMT_ENBB_MASK 0x1 +#define PMIC_RG_SMT_ENBB_SHIFT 5 +#define PMIC_RG_SMT_XOSC_EN_ADDR MT6353_SMT_CON2 +#define PMIC_RG_SMT_XOSC_EN_MASK 0x1 +#define PMIC_RG_SMT_XOSC_EN_SHIFT 6 +#define PMIC_RG_OCTL_SRCLKEN_IN0_ADDR MT6353_DRV_CON0 +#define PMIC_RG_OCTL_SRCLKEN_IN0_MASK 0xF +#define PMIC_RG_OCTL_SRCLKEN_IN0_SHIFT 0 +#define PMIC_RG_OCTL_SRCLKEN_IN1_ADDR MT6353_DRV_CON0 +#define PMIC_RG_OCTL_SRCLKEN_IN1_MASK 0xF +#define PMIC_RG_OCTL_SRCLKEN_IN1_SHIFT 4 +#define PMIC_RG_OCTL_RTC_32K1V8_0_ADDR MT6353_DRV_CON0 +#define PMIC_RG_OCTL_RTC_32K1V8_0_MASK 0xF +#define PMIC_RG_OCTL_RTC_32K1V8_0_SHIFT 8 +#define PMIC_RG_OCTL_RTC_32K1V8_1_ADDR MT6353_DRV_CON0 +#define PMIC_RG_OCTL_RTC_32K1V8_1_MASK 0xF +#define PMIC_RG_OCTL_RTC_32K1V8_1_SHIFT 12 +#define PMIC_RG_OCTL_SPI_CLK_ADDR MT6353_DRV_CON1 +#define PMIC_RG_OCTL_SPI_CLK_MASK 0xF +#define PMIC_RG_OCTL_SPI_CLK_SHIFT 0 +#define PMIC_RG_OCTL_SPI_CSN_ADDR MT6353_DRV_CON1 +#define PMIC_RG_OCTL_SPI_CSN_MASK 0xF +#define PMIC_RG_OCTL_SPI_CSN_SHIFT 4 +#define PMIC_RG_OCTL_SPI_MOSI_ADDR MT6353_DRV_CON1 +#define PMIC_RG_OCTL_SPI_MOSI_MASK 0xF +#define PMIC_RG_OCTL_SPI_MOSI_SHIFT 8 +#define PMIC_RG_OCTL_SPI_MISO_ADDR MT6353_DRV_CON1 +#define PMIC_RG_OCTL_SPI_MISO_MASK 0xF +#define PMIC_RG_OCTL_SPI_MISO_SHIFT 12 +#define PMIC_RG_OCTL_AUD_DAT_MOSI_ADDR MT6353_DRV_CON2 +#define PMIC_RG_OCTL_AUD_DAT_MOSI_MASK 0xF +#define PMIC_RG_OCTL_AUD_DAT_MOSI_SHIFT 0 +#define PMIC_RG_OCTL_AUD_DAT_MISO_ADDR MT6353_DRV_CON2 +#define PMIC_RG_OCTL_AUD_DAT_MISO_MASK 0xF +#define PMIC_RG_OCTL_AUD_DAT_MISO_SHIFT 4 +#define PMIC_RG_OCTL_AUD_CLK_ADDR MT6353_DRV_CON2 +#define PMIC_RG_OCTL_AUD_CLK_MASK 0xF +#define PMIC_RG_OCTL_AUD_CLK_SHIFT 8 +#define PMIC_RG_OCTL_ANC_DAT_MOSI_ADDR MT6353_DRV_CON2 +#define PMIC_RG_OCTL_ANC_DAT_MOSI_MASK 0xF +#define PMIC_RG_OCTL_ANC_DAT_MOSI_SHIFT 12 +#define PMIC_RG_OCTL_HOMEKEY_ADDR MT6353_DRV_CON3 +#define PMIC_RG_OCTL_HOMEKEY_MASK 0xF +#define PMIC_RG_OCTL_HOMEKEY_SHIFT 0 +#define PMIC_RG_OCTL_ENBB_ADDR MT6353_DRV_CON3 +#define PMIC_RG_OCTL_ENBB_MASK 0xF +#define PMIC_RG_OCTL_ENBB_SHIFT 4 +#define PMIC_RG_OCTL_XOSC_EN_ADDR MT6353_DRV_CON3 +#define PMIC_RG_OCTL_XOSC_EN_MASK 0xF +#define PMIC_RG_OCTL_XOSC_EN_SHIFT 8 +#define PMIC_RG_OCTL_VOW_CLK_MISO_ADDR MT6353_DRV_CON3 +#define PMIC_RG_OCTL_VOW_CLK_MISO_MASK 0xF +#define PMIC_RG_OCTL_VOW_CLK_MISO_SHIFT 12 +#define PMIC_TOP_STATUS_ADDR MT6353_TOP_STATUS +#define PMIC_TOP_STATUS_MASK 0xF +#define PMIC_TOP_STATUS_SHIFT 0 +#define PMIC_TOP_STATUS_SET_ADDR MT6353_TOP_STATUS_SET +#define PMIC_TOP_STATUS_SET_MASK 0x3 +#define PMIC_TOP_STATUS_SET_SHIFT 0 +#define PMIC_TOP_STATUS_CLR_ADDR MT6353_TOP_STATUS_CLR +#define PMIC_TOP_STATUS_CLR_MASK 0x3 +#define PMIC_TOP_STATUS_CLR_SHIFT 0 +#define PMIC_CLK_RSV_CON0_RSV_ADDR MT6353_CLK_RSV_CON0 +#define PMIC_CLK_RSV_CON0_RSV_MASK 0x3FFF +#define PMIC_CLK_RSV_CON0_RSV_SHIFT 0 +#define PMIC_RG_DCXO_PWRKEY_RSTB_SEL_ADDR MT6353_CLK_RSV_CON0 +#define PMIC_RG_DCXO_PWRKEY_RSTB_SEL_MASK 0x1 +#define PMIC_RG_DCXO_PWRKEY_RSTB_SEL_SHIFT 14 +#define PMIC_CLK_SRCVOLTEN_SW_ADDR MT6353_CLK_BUCK_CON0 +#define PMIC_CLK_SRCVOLTEN_SW_MASK 0x1 +#define PMIC_CLK_SRCVOLTEN_SW_SHIFT 0 +#define PMIC_CLK_BUCK_OSC_SEL_SW_ADDR MT6353_CLK_BUCK_CON0 +#define PMIC_CLK_BUCK_OSC_SEL_SW_MASK 0x1 +#define PMIC_CLK_BUCK_OSC_SEL_SW_SHIFT 2 +#define PMIC_CLK_VOWEN_SW_ADDR MT6353_CLK_BUCK_CON0 +#define PMIC_CLK_VOWEN_SW_MASK 0x1 +#define PMIC_CLK_VOWEN_SW_SHIFT 3 +#define PMIC_CLK_SRCVOLTEN_MODE_ADDR MT6353_CLK_BUCK_CON0 +#define PMIC_CLK_SRCVOLTEN_MODE_MASK 0x1 +#define PMIC_CLK_SRCVOLTEN_MODE_SHIFT 4 +#define PMIC_CLK_BUCK_OSC_SEL_MODE_ADDR MT6353_CLK_BUCK_CON0 +#define PMIC_CLK_BUCK_OSC_SEL_MODE_MASK 0x1 +#define PMIC_CLK_BUCK_OSC_SEL_MODE_SHIFT 6 +#define PMIC_CLK_VOWEN_MODE_ADDR MT6353_CLK_BUCK_CON0 +#define PMIC_CLK_VOWEN_MODE_MASK 0x1 +#define PMIC_CLK_VOWEN_MODE_SHIFT 7 +#define PMIC_RG_TOP_CKSEL_CON2_RSV_ADDR MT6353_CLK_BUCK_CON0 +#define PMIC_RG_TOP_CKSEL_CON2_RSV_MASK 0x3F +#define PMIC_RG_TOP_CKSEL_CON2_RSV_SHIFT 8 +#define PMIC_CLK_BUCK_CON0_RSV_ADDR MT6353_CLK_BUCK_CON0 +#define PMIC_CLK_BUCK_CON0_RSV_MASK 0x3 +#define PMIC_CLK_BUCK_CON0_RSV_SHIFT 14 +#define PMIC_CLK_BUCK_CON0_SET_ADDR MT6353_CLK_BUCK_CON0_SET +#define PMIC_CLK_BUCK_CON0_SET_MASK 0xFFFF +#define PMIC_CLK_BUCK_CON0_SET_SHIFT 0 +#define PMIC_CLK_BUCK_CON0_CLR_ADDR MT6353_CLK_BUCK_CON0_CLR +#define PMIC_CLK_BUCK_CON0_CLR_MASK 0xFFFF +#define PMIC_CLK_BUCK_CON0_CLR_SHIFT 0 +#define PMIC_CLK_BUCK_VCORE_OSC_SEL_SW_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VCORE_OSC_SEL_SW_MASK 0x1 +#define PMIC_CLK_BUCK_VCORE_OSC_SEL_SW_SHIFT 0 +#define PMIC_CLK_BUCK_VCORE2_OSC_SEL_SW_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VCORE2_OSC_SEL_SW_MASK 0x1 +#define PMIC_CLK_BUCK_VCORE2_OSC_SEL_SW_SHIFT 1 +#define PMIC_CLK_BUCK_VPROC_OSC_SEL_SW_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VPROC_OSC_SEL_SW_MASK 0x1 +#define PMIC_CLK_BUCK_VPROC_OSC_SEL_SW_SHIFT 2 +#define PMIC_CLK_BUCK_VPA_OSC_SEL_SW_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VPA_OSC_SEL_SW_MASK 0x1 +#define PMIC_CLK_BUCK_VPA_OSC_SEL_SW_SHIFT 3 +#define PMIC_CLK_BUCK_VS1_OSC_SEL_SW_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VS1_OSC_SEL_SW_MASK 0x1 +#define PMIC_CLK_BUCK_VS1_OSC_SEL_SW_SHIFT 4 +#define PMIC_CLK_LDO_VSRAM_PROC_OSC_SEL_SW_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_LDO_VSRAM_PROC_OSC_SEL_SW_MASK 0x1 +#define PMIC_CLK_LDO_VSRAM_PROC_OSC_SEL_SW_SHIFT 5 +#define PMIC_CLK_BUCK_VCORE_OSC_SEL_MODE_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VCORE_OSC_SEL_MODE_MASK 0x1 +#define PMIC_CLK_BUCK_VCORE_OSC_SEL_MODE_SHIFT 8 +#define PMIC_CLK_BUCK_VCORE2_OSC_SEL_MODE_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VCORE2_OSC_SEL_MODE_MASK 0x1 +#define PMIC_CLK_BUCK_VCORE2_OSC_SEL_MODE_SHIFT 9 +#define PMIC_CLK_BUCK_VPROC_OSC_SEL_MODE_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VPROC_OSC_SEL_MODE_MASK 0x1 +#define PMIC_CLK_BUCK_VPROC_OSC_SEL_MODE_SHIFT 10 +#define PMIC_CLK_BUCK_VPA_OSC_SEL_MODE_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VPA_OSC_SEL_MODE_MASK 0x1 +#define PMIC_CLK_BUCK_VPA_OSC_SEL_MODE_SHIFT 11 +#define PMIC_CLK_BUCK_VS1_OSC_SEL_MODE_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_VS1_OSC_SEL_MODE_MASK 0x1 +#define PMIC_CLK_BUCK_VS1_OSC_SEL_MODE_SHIFT 12 +#define PMIC_CLK_LDO_VSRAM_PROC_OSC_SEL_MODE_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_LDO_VSRAM_PROC_OSC_SEL_MODE_MASK 0x1 +#define PMIC_CLK_LDO_VSRAM_PROC_OSC_SEL_MODE_SHIFT 13 +#define PMIC_CLK_BUCK_CON1_RSV_ADDR MT6353_CLK_BUCK_CON1 +#define PMIC_CLK_BUCK_CON1_RSV_MASK 0x3 +#define PMIC_CLK_BUCK_CON1_RSV_SHIFT 14 +#define PMIC_CLK_BUCK_CON1_SET_ADDR MT6353_CLK_BUCK_CON1_SET +#define PMIC_CLK_BUCK_CON1_SET_MASK 0xFFFF +#define PMIC_CLK_BUCK_CON1_SET_SHIFT 0 +#define PMIC_CLK_BUCK_CON1_CLR_ADDR MT6353_CLK_BUCK_CON1_CLR +#define PMIC_CLK_BUCK_CON1_CLR_MASK 0xFFFF +#define PMIC_CLK_BUCK_CON1_CLR_SHIFT 0 +#define PMIC_RG_CLKSQ_EN_AUD_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_EN_AUD_MASK 0x1 +#define PMIC_RG_CLKSQ_EN_AUD_SHIFT 0 +#define PMIC_RG_CLKSQ_EN_FQR_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_EN_FQR_MASK 0x1 +#define PMIC_RG_CLKSQ_EN_FQR_SHIFT 1 +#define PMIC_RG_CLKSQ_EN_AUX_AP_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_EN_AUX_AP_MASK 0x1 +#define PMIC_RG_CLKSQ_EN_AUX_AP_SHIFT 2 +#define PMIC_RG_CLKSQ_EN_AUX_MD_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_EN_AUX_MD_MASK 0x1 +#define PMIC_RG_CLKSQ_EN_AUX_MD_SHIFT 3 +#define PMIC_RG_CLKSQ_EN_AUX_GPS_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_EN_AUX_GPS_MASK 0x1 +#define PMIC_RG_CLKSQ_EN_AUX_GPS_SHIFT 4 +#define PMIC_RG_CLKSQ_EN_AUX_RSV_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_EN_AUX_RSV_MASK 0x1 +#define PMIC_RG_CLKSQ_EN_AUX_RSV_SHIFT 5 +#define PMIC_RG_CLKSQ_EN_AUX_AP_MODE_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_EN_AUX_AP_MODE_MASK 0x1 +#define PMIC_RG_CLKSQ_EN_AUX_AP_MODE_SHIFT 8 +#define PMIC_RG_CLKSQ_EN_AUX_MD_MODE_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_EN_AUX_MD_MODE_MASK 0x1 +#define PMIC_RG_CLKSQ_EN_AUX_MD_MODE_SHIFT 9 +#define PMIC_RG_CLKSQ_IN_SEL_VA18_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_IN_SEL_VA18_MASK 0x1 +#define PMIC_RG_CLKSQ_IN_SEL_VA18_SHIFT 10 +#define PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_ADDR MT6353_TOP_CLKSQ +#define PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_MASK 0x1 +#define PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_SHIFT 11 +#define PMIC_TOP_CLKSQ_RSV_ADDR MT6353_TOP_CLKSQ +#define PMIC_TOP_CLKSQ_RSV_MASK 0x7 +#define PMIC_TOP_CLKSQ_RSV_SHIFT 12 +#define PMIC_DA_CLKSQ_EN_VA28_ADDR MT6353_TOP_CLKSQ +#define PMIC_DA_CLKSQ_EN_VA28_MASK 0x1 +#define PMIC_DA_CLKSQ_EN_VA28_SHIFT 15 +#define PMIC_TOP_CLKSQ_SET_ADDR MT6353_TOP_CLKSQ_SET +#define PMIC_TOP_CLKSQ_SET_MASK 0xFFFF +#define PMIC_TOP_CLKSQ_SET_SHIFT 0 +#define PMIC_TOP_CLKSQ_CLR_ADDR MT6353_TOP_CLKSQ_CLR +#define PMIC_TOP_CLKSQ_CLR_MASK 0xFFFF +#define PMIC_TOP_CLKSQ_CLR_SHIFT 0 +#define PMIC_RG_CLKSQ_RTC_EN_ADDR MT6353_TOP_CLKSQ_RTC +#define PMIC_RG_CLKSQ_RTC_EN_MASK 0x1 +#define PMIC_RG_CLKSQ_RTC_EN_SHIFT 0 +#define PMIC_RG_CLKSQ_RTC_EN_HW_MODE_ADDR MT6353_TOP_CLKSQ_RTC +#define PMIC_RG_CLKSQ_RTC_EN_HW_MODE_MASK 0x1 +#define PMIC_RG_CLKSQ_RTC_EN_HW_MODE_SHIFT 1 +#define PMIC_TOP_CLKSQ_RTC_RSV0_ADDR MT6353_TOP_CLKSQ_RTC +#define PMIC_TOP_CLKSQ_RTC_RSV0_MASK 0xF +#define PMIC_TOP_CLKSQ_RTC_RSV0_SHIFT 2 +#define PMIC_RG_ENBB_SEL_ADDR MT6353_TOP_CLKSQ_RTC +#define PMIC_RG_ENBB_SEL_MASK 0x1 +#define PMIC_RG_ENBB_SEL_SHIFT 8 +#define PMIC_RG_XOSC_EN_SEL_ADDR MT6353_TOP_CLKSQ_RTC +#define PMIC_RG_XOSC_EN_SEL_MASK 0x1 +#define PMIC_RG_XOSC_EN_SEL_SHIFT 9 +#define PMIC_TOP_CLKSQ_RTC_RSV1_ADDR MT6353_TOP_CLKSQ_RTC +#define PMIC_TOP_CLKSQ_RTC_RSV1_MASK 0x3 +#define PMIC_TOP_CLKSQ_RTC_RSV1_SHIFT 10 +#define PMIC_DA_CLKSQ_EN_VDIG18_ADDR MT6353_TOP_CLKSQ_RTC +#define PMIC_DA_CLKSQ_EN_VDIG18_MASK 0x1 +#define PMIC_DA_CLKSQ_EN_VDIG18_SHIFT 15 +#define PMIC_TOP_CLKSQ_RTC_SET_ADDR MT6353_TOP_CLKSQ_RTC_SET +#define PMIC_TOP_CLKSQ_RTC_SET_MASK 0xFFFF +#define PMIC_TOP_CLKSQ_RTC_SET_SHIFT 0 +#define PMIC_TOP_CLKSQ_RTC_CLR_ADDR MT6353_TOP_CLKSQ_RTC_CLR +#define PMIC_TOP_CLKSQ_RTC_CLR_MASK 0xFFFF +#define PMIC_TOP_CLKSQ_RTC_CLR_SHIFT 0 +#define PMIC_OSC_75K_TRIM_ADDR MT6353_TOP_CLK_TRIM +#define PMIC_OSC_75K_TRIM_MASK 0x1F +#define PMIC_OSC_75K_TRIM_SHIFT 0 +#define PMIC_RG_OSC_75K_TRIM_EN_ADDR MT6353_TOP_CLK_TRIM +#define PMIC_RG_OSC_75K_TRIM_EN_MASK 0x1 +#define PMIC_RG_OSC_75K_TRIM_EN_SHIFT 5 +#define PMIC_RG_OSC_75K_TRIM_RATE_ADDR MT6353_TOP_CLK_TRIM +#define PMIC_RG_OSC_75K_TRIM_RATE_MASK 0x3 +#define PMIC_RG_OSC_75K_TRIM_RATE_SHIFT 6 +#define PMIC_DA_OSC_75K_TRIM_ADDR MT6353_TOP_CLK_TRIM +#define PMIC_DA_OSC_75K_TRIM_MASK 0x1F +#define PMIC_DA_OSC_75K_TRIM_SHIFT 8 +#define PMIC_CLK_PMU75K_CK_TST_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_PMU75K_CK_TST_DIS_MASK 0x1 +#define PMIC_CLK_PMU75K_CK_TST_DIS_SHIFT 0 +#define PMIC_CLK_SMPS_CK_TST_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_SMPS_CK_TST_DIS_MASK 0x1 +#define PMIC_CLK_SMPS_CK_TST_DIS_SHIFT 1 +#define PMIC_CLK_AUD26M_CK_TST_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_AUD26M_CK_TST_DIS_MASK 0x1 +#define PMIC_CLK_AUD26M_CK_TST_DIS_SHIFT 2 +#define PMIC_CLK_VOW12M_CK_TST_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_VOW12M_CK_TST_DIS_MASK 0x1 +#define PMIC_CLK_VOW12M_CK_TST_DIS_SHIFT 3 +#define PMIC_CLK_RTC32K_CK_TST_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_RTC32K_CK_TST_DIS_MASK 0x1 +#define PMIC_CLK_RTC32K_CK_TST_DIS_SHIFT 4 +#define PMIC_CLK_RTC26M_CK_TST_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_RTC26M_CK_TST_DIS_MASK 0x1 +#define PMIC_CLK_RTC26M_CK_TST_DIS_SHIFT 5 +#define PMIC_CLK_FG_CK_TST_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_FG_CK_TST_DIS_MASK 0x1 +#define PMIC_CLK_FG_CK_TST_DIS_SHIFT 6 +#define PMIC_CLK_SPK_CK_TST_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_SPK_CK_TST_DIS_MASK 0x1 +#define PMIC_CLK_SPK_CK_TST_DIS_SHIFT 7 +#define PMIC_CLK_CKROOTTST_CON0_RSV_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_CKROOTTST_CON0_RSV_MASK 0x7F +#define PMIC_CLK_CKROOTTST_CON0_RSV_SHIFT 8 +#define PMIC_CLK_BUCK_ANA_AUTO_OFF_DIS_ADDR MT6353_CLK_CKROOTTST_CON0 +#define PMIC_CLK_BUCK_ANA_AUTO_OFF_DIS_MASK 0x1 +#define PMIC_CLK_BUCK_ANA_AUTO_OFF_DIS_SHIFT 15 +#define PMIC_CLK_PMU75K_CK_TSTSEL_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_PMU75K_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_PMU75K_CK_TSTSEL_SHIFT 0 +#define PMIC_CLK_SMPS_CK_TSTSEL_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_SMPS_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_SMPS_CK_TSTSEL_SHIFT 1 +#define PMIC_CLK_AUD26M_CK_TSTSEL_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_AUD26M_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_AUD26M_CK_TSTSEL_SHIFT 2 +#define PMIC_CLK_VOW12M_CK_TSTSEL_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_VOW12M_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_VOW12M_CK_TSTSEL_SHIFT 3 +#define PMIC_CLK_RTC32K_CK_TSTSEL_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_RTC32K_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_RTC32K_CK_TSTSEL_SHIFT 4 +#define PMIC_CLK_RTC26M_CK_TSTSEL_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_RTC26M_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_RTC26M_CK_TSTSEL_SHIFT 5 +#define PMIC_CLK_FG_CK_TSTSEL_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_FG_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_FG_CK_TSTSEL_SHIFT 6 +#define PMIC_CLK_SPK_CK_TSTSEL_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_SPK_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_SPK_CK_TSTSEL_SHIFT 7 +#define PMIC_CLK_CKROOTTST_CON1_RSV_ADDR MT6353_CLK_CKROOTTST_CON1 +#define PMIC_CLK_CKROOTTST_CON1_RSV_MASK 0xFF +#define PMIC_CLK_CKROOTTST_CON1_RSV_SHIFT 8 +#define PMIC_CLK_RTC32K_1V8_0_O_PDN_ADDR MT6353_CLK_PDN_CON0 +#define PMIC_CLK_RTC32K_1V8_0_O_PDN_MASK 0x1 +#define PMIC_CLK_RTC32K_1V8_0_O_PDN_SHIFT 0 +#define PMIC_CLK_RTC32K_1V8_1_O_PDN_ADDR MT6353_CLK_PDN_CON0 +#define PMIC_CLK_RTC32K_1V8_1_O_PDN_MASK 0x1 +#define PMIC_CLK_RTC32K_1V8_1_O_PDN_SHIFT 1 +#define PMIC_CLK_RTC_2SEC_OFF_DET_PDN_ADDR MT6353_CLK_PDN_CON0 +#define PMIC_CLK_RTC_2SEC_OFF_DET_PDN_MASK 0x1 +#define PMIC_CLK_RTC_2SEC_OFF_DET_PDN_SHIFT 2 +#define PMIC_CLK_PDN_CON0_RSV_ADDR MT6353_CLK_PDN_CON0 +#define PMIC_CLK_PDN_CON0_RSV_MASK 0x1FFF +#define PMIC_CLK_PDN_CON0_RSV_SHIFT 3 +#define PMIC_CLK_PDN_CON0_SET_ADDR MT6353_CLK_PDN_CON0_SET +#define PMIC_CLK_PDN_CON0_SET_MASK 0xFFFF +#define PMIC_CLK_PDN_CON0_SET_SHIFT 0 +#define PMIC_CLK_PDN_CON0_CLR_ADDR MT6353_CLK_PDN_CON0_CLR +#define PMIC_CLK_PDN_CON0_CLR_MASK 0xFFFF +#define PMIC_CLK_PDN_CON0_CLR_SHIFT 0 +#define PMIC_CLK_ZCD13M_CK_PDN_ADDR MT6353_CLK_PDN_CON1 +#define PMIC_CLK_ZCD13M_CK_PDN_MASK 0x1 +#define PMIC_CLK_ZCD13M_CK_PDN_SHIFT 0 +#define PMIC_CLK_SMPS_CK_DIV_PDN_ADDR MT6353_CLK_PDN_CON1 +#define PMIC_CLK_SMPS_CK_DIV_PDN_MASK 0x1 +#define PMIC_CLK_SMPS_CK_DIV_PDN_SHIFT 1 +#define PMIC_CLK_BUCK_ANA_CK_PDN_ADDR MT6353_CLK_PDN_CON1 +#define PMIC_CLK_BUCK_ANA_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_ANA_CK_PDN_SHIFT 3 +#define PMIC_CLK_PDN_CON1_RSV_ADDR MT6353_CLK_PDN_CON1 +#define PMIC_CLK_PDN_CON1_RSV_MASK 0xFFF +#define PMIC_CLK_PDN_CON1_RSV_SHIFT 4 +#define PMIC_CLK_PDN_CON1_SET_ADDR MT6353_CLK_PDN_CON1_SET +#define PMIC_CLK_PDN_CON1_SET_MASK 0xFFFF +#define PMIC_CLK_PDN_CON1_SET_SHIFT 0 +#define PMIC_CLK_PDN_CON1_CLR_ADDR MT6353_CLK_PDN_CON1_CLR +#define PMIC_CLK_PDN_CON1_CLR_MASK 0xFFFF +#define PMIC_CLK_PDN_CON1_CLR_SHIFT 0 +#define PMIC_CLK_OSC_SEL_HW_SRC_SEL_ADDR MT6353_CLK_SEL_CON0 +#define PMIC_CLK_OSC_SEL_HW_SRC_SEL_MASK 0x3 +#define PMIC_CLK_OSC_SEL_HW_SRC_SEL_SHIFT 0 +#define PMIC_CLK_SRCLKEN_SRC_SEL_ADDR MT6353_CLK_SEL_CON0 +#define PMIC_CLK_SRCLKEN_SRC_SEL_MASK 0x3 +#define PMIC_CLK_SRCLKEN_SRC_SEL_SHIFT 2 +#define PMIC_CLK_SEL_CON0_RSV_ADDR MT6353_CLK_SEL_CON0 +#define PMIC_CLK_SEL_CON0_RSV_MASK 0xFFF +#define PMIC_CLK_SEL_CON0_RSV_SHIFT 4 +#define PMIC_CLK_SEL_CON0_SET_ADDR MT6353_CLK_SEL_CON0_SET +#define PMIC_CLK_SEL_CON0_SET_MASK 0xFFFF +#define PMIC_CLK_SEL_CON0_SET_SHIFT 0 +#define PMIC_CLK_SEL_CON0_CLR_ADDR MT6353_CLK_SEL_CON0_CLR +#define PMIC_CLK_SEL_CON0_CLR_MASK 0xFFFF +#define PMIC_CLK_SEL_CON0_CLR_SHIFT 0 +#define PMIC_CLK_AUXADC_CK_CKSEL_HWEN_ADDR MT6353_CLK_SEL_CON1 +#define PMIC_CLK_AUXADC_CK_CKSEL_HWEN_MASK 0x1 +#define PMIC_CLK_AUXADC_CK_CKSEL_HWEN_SHIFT 0 +#define PMIC_CLK_AUXADC_CK_CKSEL_ADDR MT6353_CLK_SEL_CON1 +#define PMIC_CLK_AUXADC_CK_CKSEL_MASK 0x1 +#define PMIC_CLK_AUXADC_CK_CKSEL_SHIFT 1 +#define PMIC_CLK_75K_32K_SEL_ADDR MT6353_CLK_SEL_CON1 +#define PMIC_CLK_75K_32K_SEL_MASK 0x1 +#define PMIC_CLK_75K_32K_SEL_SHIFT 2 +#define PMIC_CLK_SEL_CON1_RSV_ADDR MT6353_CLK_SEL_CON1 +#define PMIC_CLK_SEL_CON1_RSV_MASK 0xFFF +#define PMIC_CLK_SEL_CON1_RSV_SHIFT 4 +#define PMIC_CLK_SEL_CON1_SET_ADDR MT6353_CLK_SEL_CON1_SET +#define PMIC_CLK_SEL_CON1_SET_MASK 0xFFFF +#define PMIC_CLK_SEL_CON1_SET_SHIFT 0 +#define PMIC_CLK_SEL_CON1_CLR_ADDR MT6353_CLK_SEL_CON1_CLR +#define PMIC_CLK_SEL_CON1_CLR_MASK 0xFFFF +#define PMIC_CLK_SEL_CON1_CLR_SHIFT 0 +#define PMIC_CLK_G_SMPS_PD_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_G_SMPS_PD_CK_PDN_MASK 0x1 +#define PMIC_CLK_G_SMPS_PD_CK_PDN_SHIFT 0 +#define PMIC_CLK_G_SMPS_AUD_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_G_SMPS_AUD_CK_PDN_MASK 0x1 +#define PMIC_CLK_G_SMPS_AUD_CK_PDN_SHIFT 1 +#define PMIC_CLK_G_SMPS_TEST_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_G_SMPS_TEST_CK_PDN_MASK 0x1 +#define PMIC_CLK_G_SMPS_TEST_CK_PDN_SHIFT 2 +#define PMIC_CLK_ACCDET_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_ACCDET_CK_PDN_MASK 0x1 +#define PMIC_CLK_ACCDET_CK_PDN_SHIFT 3 +#define PMIC_CLK_AUDIF_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_AUDIF_CK_PDN_MASK 0x1 +#define PMIC_CLK_AUDIF_CK_PDN_SHIFT 4 +#define PMIC_CLK_AUD_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_AUD_CK_PDN_MASK 0x1 +#define PMIC_CLK_AUD_CK_PDN_SHIFT 5 +#define PMIC_CLK_AUDNCP_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_AUDNCP_CK_PDN_MASK 0x1 +#define PMIC_CLK_AUDNCP_CK_PDN_SHIFT 6 +#define PMIC_CLK_AUXADC_1M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_AUXADC_1M_CK_PDN_MASK 0x1 +#define PMIC_CLK_AUXADC_1M_CK_PDN_SHIFT 7 +#define PMIC_CLK_AUXADC_SMPS_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_AUXADC_SMPS_CK_PDN_MASK 0x1 +#define PMIC_CLK_AUXADC_SMPS_CK_PDN_SHIFT 8 +#define PMIC_CLK_AUXADC_RNG_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_AUXADC_RNG_CK_PDN_MASK 0x1 +#define PMIC_CLK_AUXADC_RNG_CK_PDN_SHIFT 9 +#define PMIC_CLK_AUXADC_26M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_AUXADC_26M_CK_PDN_MASK 0x1 +#define PMIC_CLK_AUXADC_26M_CK_PDN_SHIFT 10 +#define PMIC_CLK_AUXADC_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_AUXADC_CK_PDN_MASK 0x1 +#define PMIC_CLK_AUXADC_CK_PDN_SHIFT 11 +#define PMIC_CLK_DRV_ISINK0_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_DRV_ISINK0_CK_PDN_MASK 0x1 +#define PMIC_CLK_DRV_ISINK0_CK_PDN_SHIFT 12 +#define PMIC_CLK_DRV_ISINK1_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_DRV_ISINK1_CK_PDN_MASK 0x1 +#define PMIC_CLK_DRV_ISINK1_CK_PDN_SHIFT 13 +#define PMIC_CLK_DRV_ISINK2_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_DRV_ISINK2_CK_PDN_MASK 0x1 +#define PMIC_CLK_DRV_ISINK2_CK_PDN_SHIFT 14 +#define PMIC_CLK_DRV_ISINK3_CK_PDN_ADDR MT6353_CLK_CKPDN_CON0 +#define PMIC_CLK_DRV_ISINK3_CK_PDN_MASK 0x1 +#define PMIC_CLK_DRV_ISINK3_CK_PDN_SHIFT 15 +#define PMIC_CLK_CKPDN_CON0_SET_ADDR MT6353_CLK_CKPDN_CON0_SET +#define PMIC_CLK_CKPDN_CON0_SET_MASK 0xFFFF +#define PMIC_CLK_CKPDN_CON0_SET_SHIFT 0 +#define PMIC_CLK_CKPDN_CON0_CLR_ADDR MT6353_CLK_CKPDN_CON0_CLR +#define PMIC_CLK_CKPDN_CON0_CLR_MASK 0xFFFF +#define PMIC_CLK_CKPDN_CON0_CLR_SHIFT 0 +#define PMIC_CLK_DRV_CHRIND_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_DRV_CHRIND_CK_PDN_MASK 0x1 +#define PMIC_CLK_DRV_CHRIND_CK_PDN_SHIFT 0 +#define PMIC_CLK_DRV_32K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_DRV_32K_CK_PDN_MASK 0x1 +#define PMIC_CLK_DRV_32K_CK_PDN_SHIFT 1 +#define PMIC_CLK_BUCK_1M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_BUCK_1M_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_1M_CK_PDN_SHIFT 2 +#define PMIC_CLK_BUCK_32K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_BUCK_32K_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_32K_CK_PDN_SHIFT 3 +#define PMIC_CLK_BUCK_9M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_BUCK_9M_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_9M_CK_PDN_SHIFT 4 +#define PMIC_CLK_PWMOC_6M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_PWMOC_6M_CK_PDN_MASK 0x1 +#define PMIC_CLK_PWMOC_6M_CK_PDN_SHIFT 5 +#define PMIC_CLK_BUCK_VPROC_9M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_BUCK_VPROC_9M_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_VPROC_9M_CK_PDN_SHIFT 6 +#define PMIC_CLK_BUCK_VCORE_9M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_BUCK_VCORE_9M_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_VCORE_9M_CK_PDN_SHIFT 7 +#define PMIC_CLK_BUCK_VCORE2_9M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_BUCK_VCORE2_9M_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_VCORE2_9M_CK_PDN_SHIFT 8 +#define PMIC_CLK_BUCK_VPA_9M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_BUCK_VPA_9M_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_VPA_9M_CK_PDN_SHIFT 9 +#define PMIC_CLK_BUCK_VS1_9M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_BUCK_VS1_9M_CK_PDN_MASK 0x1 +#define PMIC_CLK_BUCK_VS1_9M_CK_PDN_SHIFT 10 +#define PMIC_CLK_FQMTR_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_FQMTR_CK_PDN_MASK 0x1 +#define PMIC_CLK_FQMTR_CK_PDN_SHIFT 11 +#define PMIC_CLK_FQMTR_32K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_FQMTR_32K_CK_PDN_MASK 0x1 +#define PMIC_CLK_FQMTR_32K_CK_PDN_SHIFT 12 +#define PMIC_CLK_INTRP_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_INTRP_CK_PDN_MASK 0x1 +#define PMIC_CLK_INTRP_CK_PDN_SHIFT 13 +#define PMIC_CLK_INTRP_PRE_OC_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_INTRP_PRE_OC_CK_PDN_MASK 0x1 +#define PMIC_CLK_INTRP_PRE_OC_CK_PDN_SHIFT 14 +#define PMIC_CLK_STB_1M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON1 +#define PMIC_CLK_STB_1M_CK_PDN_MASK 0x1 +#define PMIC_CLK_STB_1M_CK_PDN_SHIFT 15 +#define PMIC_CLK_CKPDN_CON1_SET_ADDR MT6353_CLK_CKPDN_CON1_SET +#define PMIC_CLK_CKPDN_CON1_SET_MASK 0xFFFF +#define PMIC_CLK_CKPDN_CON1_SET_SHIFT 0 +#define PMIC_CLK_CKPDN_CON1_CLR_ADDR MT6353_CLK_CKPDN_CON1_CLR +#define PMIC_CLK_CKPDN_CON1_CLR_MASK 0xFFFF +#define PMIC_CLK_CKPDN_CON1_CLR_SHIFT 0 +#define PMIC_CLK_LDO_CALI_75K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_LDO_CALI_75K_CK_PDN_MASK 0x1 +#define PMIC_CLK_LDO_CALI_75K_CK_PDN_SHIFT 0 +#define PMIC_CLK_LDO_VSRAM_PROC_9M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_LDO_VSRAM_PROC_9M_CK_PDN_MASK 0x1 +#define PMIC_CLK_LDO_VSRAM_PROC_9M_CK_PDN_SHIFT 1 +#define PMIC_CLK_RTC_26M_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_RTC_26M_CK_PDN_MASK 0x1 +#define PMIC_CLK_RTC_26M_CK_PDN_SHIFT 2 +#define PMIC_CLK_RTC_32K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_RTC_32K_CK_PDN_MASK 0x1 +#define PMIC_CLK_RTC_32K_CK_PDN_SHIFT 3 +#define PMIC_CLK_RTC_MCLK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_RTC_MCLK_PDN_MASK 0x1 +#define PMIC_CLK_RTC_MCLK_PDN_SHIFT 4 +#define PMIC_CLK_RTC_75K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_RTC_75K_CK_PDN_MASK 0x1 +#define PMIC_CLK_RTC_75K_CK_PDN_SHIFT 5 +#define PMIC_CLK_RTCDET_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_RTCDET_CK_PDN_MASK 0x1 +#define PMIC_CLK_RTCDET_CK_PDN_SHIFT 6 +#define PMIC_CLK_RTC_EOSC32_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_RTC_EOSC32_CK_PDN_MASK 0x1 +#define PMIC_CLK_RTC_EOSC32_CK_PDN_SHIFT 7 +#define PMIC_CLK_EOSC_CALI_TEST_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_EOSC_CALI_TEST_CK_PDN_MASK 0x1 +#define PMIC_CLK_EOSC_CALI_TEST_CK_PDN_SHIFT 8 +#define PMIC_CLK_FGADC_ANA_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_FGADC_ANA_CK_PDN_MASK 0x1 +#define PMIC_CLK_FGADC_ANA_CK_PDN_SHIFT 9 +#define PMIC_CLK_FGADC_DIG_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_FGADC_DIG_CK_PDN_MASK 0x1 +#define PMIC_CLK_FGADC_DIG_CK_PDN_SHIFT 10 +#define PMIC_CLK_FGADC_FT_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_FGADC_FT_CK_PDN_MASK 0x1 +#define PMIC_CLK_FGADC_FT_CK_PDN_SHIFT 11 +#define PMIC_CLK_TRIM_75K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_TRIM_75K_CK_PDN_MASK 0x1 +#define PMIC_CLK_TRIM_75K_CK_PDN_SHIFT 12 +#define PMIC_CLK_EFUSE_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_EFUSE_CK_PDN_MASK 0x1 +#define PMIC_CLK_EFUSE_CK_PDN_SHIFT 13 +#define PMIC_CLK_STRUP_75K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_STRUP_75K_CK_PDN_MASK 0x1 +#define PMIC_CLK_STRUP_75K_CK_PDN_SHIFT 14 +#define PMIC_CLK_STRUP_32K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON2 +#define PMIC_CLK_STRUP_32K_CK_PDN_MASK 0x1 +#define PMIC_CLK_STRUP_32K_CK_PDN_SHIFT 15 +#define PMIC_CLK_CKPDN_CON2_SET_ADDR MT6353_CLK_CKPDN_CON2_SET +#define PMIC_CLK_CKPDN_CON2_SET_MASK 0xFFFF +#define PMIC_CLK_CKPDN_CON2_SET_SHIFT 0 +#define PMIC_CLK_CKPDN_CON2_CLR_ADDR MT6353_CLK_CKPDN_CON2_CLR +#define PMIC_CLK_CKPDN_CON2_CLR_MASK 0xFFFF +#define PMIC_CLK_CKPDN_CON2_CLR_SHIFT 0 +#define PMIC_CLK_PCHR_32K_CK_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_PCHR_32K_CK_PDN_MASK 0x1 +#define PMIC_CLK_PCHR_32K_CK_PDN_SHIFT 0 +#define PMIC_CLK_PCHR_TEST_CK_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_PCHR_TEST_CK_PDN_MASK 0x1 +#define PMIC_CLK_PCHR_TEST_CK_PDN_SHIFT 1 +#define PMIC_CLK_SPI_CK_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_SPI_CK_PDN_MASK 0x1 +#define PMIC_CLK_SPI_CK_PDN_SHIFT 2 +#define PMIC_CLK_BGR_TEST_CK_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_BGR_TEST_CK_PDN_MASK 0x1 +#define PMIC_CLK_BGR_TEST_CK_PDN_SHIFT 3 +#define PMIC_CLK_TYPE_C_CC_CK_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_TYPE_C_CC_CK_PDN_MASK 0x1 +#define PMIC_CLK_TYPE_C_CC_CK_PDN_SHIFT 4 +#define PMIC_CLK_TYPE_C_CSR_CK_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_TYPE_C_CSR_CK_PDN_MASK 0x1 +#define PMIC_CLK_TYPE_C_CSR_CK_PDN_SHIFT 5 +#define PMIC_CLK_SPK_CK_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_SPK_CK_PDN_MASK 0x1 +#define PMIC_CLK_SPK_CK_PDN_SHIFT 6 +#define PMIC_CLK_SPK_PWM_CK_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_SPK_PWM_CK_PDN_MASK 0x1 +#define PMIC_CLK_SPK_PWM_CK_PDN_SHIFT 7 +#define PMIC_CLK_RSV_PDN_ADDR MT6353_CLK_CKPDN_CON3 +#define PMIC_CLK_RSV_PDN_MASK 0xFF +#define PMIC_CLK_RSV_PDN_SHIFT 8 +#define PMIC_CLK_CKPDN_CON3_SET_ADDR MT6353_CLK_CKPDN_CON3_SET +#define PMIC_CLK_CKPDN_CON3_SET_MASK 0xFFFF +#define PMIC_CLK_CKPDN_CON3_SET_SHIFT 0 +#define PMIC_CLK_CKPDN_CON3_CLR_ADDR MT6353_CLK_CKPDN_CON3_CLR +#define PMIC_CLK_CKPDN_CON3_CLR_MASK 0xFFFF +#define PMIC_CLK_CKPDN_CON3_CLR_SHIFT 0 +#define PMIC_CLK_G_SMPS_PD_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_G_SMPS_PD_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_G_SMPS_PD_CK_PDN_HWEN_SHIFT 0 +#define PMIC_CLK_G_SMPS_AUD_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_G_SMPS_AUD_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_G_SMPS_AUD_CK_PDN_HWEN_SHIFT 1 +#define PMIC_CLK_AUXADC_SMPS_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_AUXADC_SMPS_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_AUXADC_SMPS_CK_PDN_HWEN_SHIFT 2 +#define PMIC_CLK_AUXADC_26M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_AUXADC_26M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_AUXADC_26M_CK_PDN_HWEN_SHIFT 3 +#define PMIC_CLK_AUXADC_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_AUXADC_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_AUXADC_CK_PDN_HWEN_SHIFT 4 +#define PMIC_CLK_BUCK_1M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_BUCK_1M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_BUCK_1M_CK_PDN_HWEN_SHIFT 5 +#define PMIC_CLK_BUCK_VPROC_9M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_BUCK_VPROC_9M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_BUCK_VPROC_9M_CK_PDN_HWEN_SHIFT 6 +#define PMIC_CLK_BUCK_VCORE_9M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_BUCK_VCORE_9M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_BUCK_VCORE_9M_CK_PDN_HWEN_SHIFT 7 +#define PMIC_CLK_BUCK_VCORE2_9M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_BUCK_VCORE2_9M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_BUCK_VCORE2_9M_CK_PDN_HWEN_SHIFT 8 +#define PMIC_CLK_BUCK_VPA_9M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_BUCK_VPA_9M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_BUCK_VPA_9M_CK_PDN_HWEN_SHIFT 9 +#define PMIC_CLK_BUCK_VS1_9M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_BUCK_VS1_9M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_BUCK_VS1_9M_CK_PDN_HWEN_SHIFT 10 +#define PMIC_CLK_STB_1M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_STB_1M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_STB_1M_CK_PDN_HWEN_SHIFT 11 +#define PMIC_CLK_LDO_VSRAM_PROC_9M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_LDO_VSRAM_PROC_9M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_LDO_VSRAM_PROC_9M_CK_PDN_HWEN_SHIFT 12 +#define PMIC_CLK_RTC_26M_CK_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_RTC_26M_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_RTC_26M_CK_PDN_HWEN_SHIFT 13 +#define PMIC_CLK_RSV_PDN_HWEN_ADDR MT6353_CLK_CKPDN_HWEN_CON0 +#define PMIC_CLK_RSV_PDN_HWEN_MASK 0x3 +#define PMIC_CLK_RSV_PDN_HWEN_SHIFT 14 +#define PMIC_CLK_CKPDN_HWEN_CON0_SET_ADDR MT6353_CLK_CKPDN_HWEN_CON0_SET +#define PMIC_CLK_CKPDN_HWEN_CON0_SET_MASK 0xFFFF +#define PMIC_CLK_CKPDN_HWEN_CON0_SET_SHIFT 0 +#define PMIC_CLK_CKPDN_HWEN_CON0_CLR_ADDR MT6353_CLK_CKPDN_HWEN_CON0_CLR +#define PMIC_CLK_CKPDN_HWEN_CON0_CLR_MASK 0xFFFF +#define PMIC_CLK_CKPDN_HWEN_CON0_CLR_SHIFT 0 +#define PMIC_CLK_AUDIF_CK_CKSEL_ADDR MT6353_CLK_CKSEL_CON0 +#define PMIC_CLK_AUDIF_CK_CKSEL_MASK 0x1 +#define PMIC_CLK_AUDIF_CK_CKSEL_SHIFT 0 +#define PMIC_CLK_AUD_CK_CKSEL_ADDR MT6353_CLK_CKSEL_CON0 +#define PMIC_CLK_AUD_CK_CKSEL_MASK 0x1 +#define PMIC_CLK_AUD_CK_CKSEL_SHIFT 1 +#define PMIC_CLK_FQMTR_CK_CKSEL_ADDR MT6353_CLK_CKSEL_CON0 +#define PMIC_CLK_FQMTR_CK_CKSEL_MASK 0x7 +#define PMIC_CLK_FQMTR_CK_CKSEL_SHIFT 2 +#define PMIC_CLK_FGADC_ANA_CK_CKSEL_ADDR MT6353_CLK_CKSEL_CON0 +#define PMIC_CLK_FGADC_ANA_CK_CKSEL_MASK 0x1 +#define PMIC_CLK_FGADC_ANA_CK_CKSEL_SHIFT 5 +#define PMIC_CLK_PCHR_TEST_CK_CKSEL_ADDR MT6353_CLK_CKSEL_CON0 +#define PMIC_CLK_PCHR_TEST_CK_CKSEL_MASK 0x1 +#define PMIC_CLK_PCHR_TEST_CK_CKSEL_SHIFT 6 +#define PMIC_CLK_BGR_TEST_CK_CKSEL_ADDR MT6353_CLK_CKSEL_CON0 +#define PMIC_CLK_BGR_TEST_CK_CKSEL_MASK 0x1 +#define PMIC_CLK_BGR_TEST_CK_CKSEL_SHIFT 7 +#define PMIC_CLK_EFUSE_CK_PDN_HWEN_ADDR MT6353_CLK_CKSEL_CON0 +#define PMIC_CLK_EFUSE_CK_PDN_HWEN_MASK 0x1 +#define PMIC_CLK_EFUSE_CK_PDN_HWEN_SHIFT 8 +#define PMIC_CLK_RSV_CKSEL_ADDR MT6353_CLK_CKSEL_CON0 +#define PMIC_CLK_RSV_CKSEL_MASK 0x7F +#define PMIC_CLK_RSV_CKSEL_SHIFT 9 +#define PMIC_CLK_CKSEL_CON0_SET_ADDR MT6353_CLK_CKSEL_CON0_SET +#define PMIC_CLK_CKSEL_CON0_SET_MASK 0xFFFF +#define PMIC_CLK_CKSEL_CON0_SET_SHIFT 0 +#define PMIC_CLK_CKSEL_CON0_CLR_ADDR MT6353_CLK_CKSEL_CON0_CLR +#define PMIC_CLK_CKSEL_CON0_CLR_MASK 0xFFFF +#define PMIC_CLK_CKSEL_CON0_CLR_SHIFT 0 +#define PMIC_CLK_AUXADC_SMPS_CK_DIVSEL_ADDR MT6353_CLK_CKDIVSEL_CON0 +#define PMIC_CLK_AUXADC_SMPS_CK_DIVSEL_MASK 0x3 +#define PMIC_CLK_AUXADC_SMPS_CK_DIVSEL_SHIFT 0 +#define PMIC_CLK_AUXADC_26M_CK_DIVSEL_ADDR MT6353_CLK_CKDIVSEL_CON0 +#define PMIC_CLK_AUXADC_26M_CK_DIVSEL_MASK 0x3 +#define PMIC_CLK_AUXADC_26M_CK_DIVSEL_SHIFT 2 +#define PMIC_CLK_BUCK_9M_CK_DIVSEL_ADDR MT6353_CLK_CKDIVSEL_CON0 +#define PMIC_CLK_BUCK_9M_CK_DIVSEL_MASK 0x1 +#define PMIC_CLK_BUCK_9M_CK_DIVSEL_SHIFT 4 +#define PMIC_CLK_REG_CK_DIVSEL_ADDR MT6353_CLK_CKDIVSEL_CON0 +#define PMIC_CLK_REG_CK_DIVSEL_MASK 0x3 +#define PMIC_CLK_REG_CK_DIVSEL_SHIFT 7 +#define PMIC_CLK_SPK_CK_DIVSEL_ADDR MT6353_CLK_CKDIVSEL_CON0 +#define PMIC_CLK_SPK_CK_DIVSEL_MASK 0x3 +#define PMIC_CLK_SPK_CK_DIVSEL_SHIFT 9 +#define PMIC_CLK_SPK_PWM_CK_DIVSEL_ADDR MT6353_CLK_CKDIVSEL_CON0 +#define PMIC_CLK_SPK_PWM_CK_DIVSEL_MASK 0x3 +#define PMIC_CLK_SPK_PWM_CK_DIVSEL_SHIFT 11 +#define PMIC_CLK_RSV_DIVSEL_ADDR MT6353_CLK_CKDIVSEL_CON0 +#define PMIC_CLK_RSV_DIVSEL_MASK 0x7 +#define PMIC_CLK_RSV_DIVSEL_SHIFT 13 +#define PMIC_CLK_CKDIVSEL_CON0_SET_ADDR MT6353_CLK_CKDIVSEL_CON0_SET +#define PMIC_CLK_CKDIVSEL_CON0_SET_MASK 0xFFFF +#define PMIC_CLK_CKDIVSEL_CON0_SET_SHIFT 0 +#define PMIC_CLK_CKDIVSEL_CON0_CLR_ADDR MT6353_CLK_CKDIVSEL_CON0_CLR +#define PMIC_CLK_CKDIVSEL_CON0_CLR_MASK 0xFFFF +#define PMIC_CLK_CKDIVSEL_CON0_CLR_SHIFT 0 +#define PMIC_CLK_AUDIF_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_AUDIF_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_AUDIF_CK_TSTSEL_SHIFT 0 +#define PMIC_CLK_AUD_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_AUD_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_AUD_CK_TSTSEL_SHIFT 1 +#define PMIC_CLK_AUXADC_SMPS_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_AUXADC_SMPS_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_AUXADC_SMPS_CK_TSTSEL_SHIFT 2 +#define PMIC_CLK_AUXADC_26M_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_AUXADC_26M_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_AUXADC_26M_CK_TSTSEL_SHIFT 3 +#define PMIC_CLK_AUXADC_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_AUXADC_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_AUXADC_CK_TSTSEL_SHIFT 4 +#define PMIC_CLK_DRV_CHRIND_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_DRV_CHRIND_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_DRV_CHRIND_CK_TSTSEL_SHIFT 5 +#define PMIC_CLK_FQMTR_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_FQMTR_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_FQMTR_CK_TSTSEL_SHIFT 6 +#define PMIC_CLK_RTCDET_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_RTCDET_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_RTCDET_CK_TSTSEL_SHIFT 7 +#define PMIC_CLK_RTC_EOSC32_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_RTC_EOSC32_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_RTC_EOSC32_CK_TSTSEL_SHIFT 8 +#define PMIC_CLK_EOSC_CALI_TEST_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_EOSC_CALI_TEST_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_EOSC_CALI_TEST_CK_TSTSEL_SHIFT 9 +#define PMIC_CLK_FGADC_ANA_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_FGADC_ANA_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_FGADC_ANA_CK_TSTSEL_SHIFT 10 +#define PMIC_CLK_PCHR_TEST_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_PCHR_TEST_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_PCHR_TEST_CK_TSTSEL_SHIFT 11 +#define PMIC_CLK_BGR_TEST_CK_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_BGR_TEST_CK_TSTSEL_MASK 0x1 +#define PMIC_CLK_BGR_TEST_CK_TSTSEL_SHIFT 12 +#define PMIC_CLK_RSV_TSTSEL_ADDR MT6353_CLK_CKTSTSEL_CON0 +#define PMIC_CLK_RSV_TSTSEL_MASK 0x7 +#define PMIC_CLK_RSV_TSTSEL_SHIFT 13 +#define PMIC_RG_EFUSE_MAN_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_EFUSE_MAN_RST_MASK 0x1 +#define PMIC_RG_EFUSE_MAN_RST_SHIFT 0 +#define PMIC_RG_AUXADC_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_AUXADC_RST_MASK 0x1 +#define PMIC_RG_AUXADC_RST_SHIFT 1 +#define PMIC_RG_AUXADC_REG_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_AUXADC_REG_RST_MASK 0x1 +#define PMIC_RG_AUXADC_REG_RST_SHIFT 2 +#define PMIC_RG_AUDIO_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_AUDIO_RST_MASK 0x1 +#define PMIC_RG_AUDIO_RST_SHIFT 3 +#define PMIC_RG_ACCDET_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_ACCDET_RST_MASK 0x1 +#define PMIC_RG_ACCDET_RST_SHIFT 4 +#define PMIC_RG_BIF_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_BIF_RST_MASK 0x1 +#define PMIC_RG_BIF_RST_SHIFT 5 +#define PMIC_RG_DRIVER_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_DRIVER_RST_MASK 0x1 +#define PMIC_RG_DRIVER_RST_SHIFT 6 +#define PMIC_RG_FGADC_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_FGADC_RST_MASK 0x1 +#define PMIC_RG_FGADC_RST_SHIFT 7 +#define PMIC_RG_FQMTR_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_FQMTR_RST_MASK 0x1 +#define PMIC_RG_FQMTR_RST_SHIFT 8 +#define PMIC_RG_RTC_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_RTC_RST_MASK 0x1 +#define PMIC_RG_RTC_RST_SHIFT 9 +#define PMIC_RG_TYPE_C_CC_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_TYPE_C_CC_RST_MASK 0x1 +#define PMIC_RG_TYPE_C_CC_RST_SHIFT 10 +#define PMIC_RG_CHRWDT_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_CHRWDT_RST_MASK 0x1 +#define PMIC_RG_CHRWDT_RST_SHIFT 11 +#define PMIC_RG_ZCD_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_ZCD_RST_MASK 0x1 +#define PMIC_RG_ZCD_RST_SHIFT 12 +#define PMIC_RG_AUDNCP_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_AUDNCP_RST_MASK 0x1 +#define PMIC_RG_AUDNCP_RST_SHIFT 13 +#define PMIC_RG_CLK_TRIM_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_CLK_TRIM_RST_MASK 0x1 +#define PMIC_RG_CLK_TRIM_RST_SHIFT 14 +#define PMIC_RG_BUCK_SRCLKEN_RST_ADDR MT6353_TOP_RST_CON0 +#define PMIC_RG_BUCK_SRCLKEN_RST_MASK 0x1 +#define PMIC_RG_BUCK_SRCLKEN_RST_SHIFT 15 +#define PMIC_TOP_RST_CON0_SET_ADDR MT6353_TOP_RST_CON0_SET +#define PMIC_TOP_RST_CON0_SET_MASK 0xFFFF +#define PMIC_TOP_RST_CON0_SET_SHIFT 0 +#define PMIC_TOP_RST_CON0_CLR_ADDR MT6353_TOP_RST_CON0_CLR +#define PMIC_TOP_RST_CON0_CLR_MASK 0xFFFF +#define PMIC_TOP_RST_CON0_CLR_SHIFT 0 +#define PMIC_RG_STRUP_LONG_PRESS_RST_ADDR MT6353_TOP_RST_CON1 +#define PMIC_RG_STRUP_LONG_PRESS_RST_MASK 0x1 +#define PMIC_RG_STRUP_LONG_PRESS_RST_SHIFT 0 +#define PMIC_RG_BUCK_PROT_PMPP_RST_ADDR MT6353_TOP_RST_CON1 +#define PMIC_RG_BUCK_PROT_PMPP_RST_MASK 0x1 +#define PMIC_RG_BUCK_PROT_PMPP_RST_SHIFT 1 +#define PMIC_RG_SPK_RST_ADDR MT6353_TOP_RST_CON1 +#define PMIC_RG_SPK_RST_MASK 0x1 +#define PMIC_RG_SPK_RST_SHIFT 2 +#define PMIC_TOP_RST_CON1_RSV_ADDR MT6353_TOP_RST_CON1 +#define PMIC_TOP_RST_CON1_RSV_MASK 0x1F +#define PMIC_TOP_RST_CON1_RSV_SHIFT 3 +#define PMIC_TOP_RST_CON1_SET_ADDR MT6353_TOP_RST_CON1_SET +#define PMIC_TOP_RST_CON1_SET_MASK 0xFFFF +#define PMIC_TOP_RST_CON1_SET_SHIFT 0 +#define PMIC_TOP_RST_CON1_CLR_ADDR MT6353_TOP_RST_CON1_CLR +#define PMIC_TOP_RST_CON1_CLR_MASK 0xFFFF +#define PMIC_TOP_RST_CON1_CLR_SHIFT 0 +#define PMIC_RG_CHR_LDO_DET_MODE_ADDR MT6353_TOP_RST_CON2 +#define PMIC_RG_CHR_LDO_DET_MODE_MASK 0x1 +#define PMIC_RG_CHR_LDO_DET_MODE_SHIFT 0 +#define PMIC_RG_CHR_LDO_DET_SW_ADDR MT6353_TOP_RST_CON2 +#define PMIC_RG_CHR_LDO_DET_SW_MASK 0x1 +#define PMIC_RG_CHR_LDO_DET_SW_SHIFT 1 +#define PMIC_RG_CHRWDT_FLAG_MODE_ADDR MT6353_TOP_RST_CON2 +#define PMIC_RG_CHRWDT_FLAG_MODE_MASK 0x1 +#define PMIC_RG_CHRWDT_FLAG_MODE_SHIFT 2 +#define PMIC_RG_CHRWDT_FLAG_SW_ADDR MT6353_TOP_RST_CON2 +#define PMIC_RG_CHRWDT_FLAG_SW_MASK 0x1 +#define PMIC_RG_CHRWDT_FLAG_SW_SHIFT 3 +#define PMIC_TOP_RST_CON2_RSV_ADDR MT6353_TOP_RST_CON2 +#define PMIC_TOP_RST_CON2_RSV_MASK 0xF +#define PMIC_TOP_RST_CON2_RSV_SHIFT 4 +#define PMIC_RG_WDTRSTB_EN_ADDR MT6353_TOP_RST_MISC +#define PMIC_RG_WDTRSTB_EN_MASK 0x1 +#define PMIC_RG_WDTRSTB_EN_SHIFT 0 +#define PMIC_RG_WDTRSTB_MODE_ADDR MT6353_TOP_RST_MISC +#define PMIC_RG_WDTRSTB_MODE_MASK 0x1 +#define PMIC_RG_WDTRSTB_MODE_SHIFT 1 +#define PMIC_WDTRSTB_STATUS_ADDR MT6353_TOP_RST_MISC +#define PMIC_WDTRSTB_STATUS_MASK 0x1 +#define PMIC_WDTRSTB_STATUS_SHIFT 2 +#define PMIC_WDTRSTB_STATUS_CLR_ADDR MT6353_TOP_RST_MISC +#define PMIC_WDTRSTB_STATUS_CLR_MASK 0x1 +#define PMIC_WDTRSTB_STATUS_CLR_SHIFT 3 +#define PMIC_RG_WDTRSTB_FB_EN_ADDR MT6353_TOP_RST_MISC +#define PMIC_RG_WDTRSTB_FB_EN_MASK 0x1 +#define PMIC_RG_WDTRSTB_FB_EN_SHIFT 4 +#define PMIC_RG_WDTRSTB_DEB_ADDR MT6353_TOP_RST_MISC +#define PMIC_RG_WDTRSTB_DEB_MASK 0x1 +#define PMIC_RG_WDTRSTB_DEB_SHIFT 5 +#define PMIC_RG_HOMEKEY_RST_EN_ADDR MT6353_TOP_RST_MISC +#define PMIC_RG_HOMEKEY_RST_EN_MASK 0x1 +#define PMIC_RG_HOMEKEY_RST_EN_SHIFT 8 +#define PMIC_RG_PWRKEY_RST_EN_ADDR MT6353_TOP_RST_MISC +#define PMIC_RG_PWRKEY_RST_EN_MASK 0x1 +#define PMIC_RG_PWRKEY_RST_EN_SHIFT 9 +#define PMIC_RG_PWRRST_TMR_DIS_ADDR MT6353_TOP_RST_MISC +#define PMIC_RG_PWRRST_TMR_DIS_MASK 0x1 +#define PMIC_RG_PWRRST_TMR_DIS_SHIFT 10 +#define PMIC_RG_PWRKEY_RST_TD_ADDR MT6353_TOP_RST_MISC +#define PMIC_RG_PWRKEY_RST_TD_MASK 0x3 +#define PMIC_RG_PWRKEY_RST_TD_SHIFT 12 +#define PMIC_TOP_RST_MISC_RSV_ADDR MT6353_TOP_RST_MISC +#define PMIC_TOP_RST_MISC_RSV_MASK 0x3 +#define PMIC_TOP_RST_MISC_RSV_SHIFT 14 +#define PMIC_TOP_RST_MISC_SET_ADDR MT6353_TOP_RST_MISC_SET +#define PMIC_TOP_RST_MISC_SET_MASK 0xFFFF +#define PMIC_TOP_RST_MISC_SET_SHIFT 0 +#define PMIC_TOP_RST_MISC_CLR_ADDR MT6353_TOP_RST_MISC_CLR +#define PMIC_TOP_RST_MISC_CLR_MASK 0xFFFF +#define PMIC_TOP_RST_MISC_CLR_SHIFT 0 +#define PMIC_VPWRIN_RSTB_STATUS_ADDR MT6353_TOP_RST_STATUS +#define PMIC_VPWRIN_RSTB_STATUS_MASK 0x1 +#define PMIC_VPWRIN_RSTB_STATUS_SHIFT 0 +#define PMIC_DDLO_RSTB_STATUS_ADDR MT6353_TOP_RST_STATUS +#define PMIC_DDLO_RSTB_STATUS_MASK 0x1 +#define PMIC_DDLO_RSTB_STATUS_SHIFT 1 +#define PMIC_UVLO_RSTB_STATUS_ADDR MT6353_TOP_RST_STATUS +#define PMIC_UVLO_RSTB_STATUS_MASK 0x1 +#define PMIC_UVLO_RSTB_STATUS_SHIFT 2 +#define PMIC_RTC_DDLO_RSTB_STATUS_ADDR MT6353_TOP_RST_STATUS +#define PMIC_RTC_DDLO_RSTB_STATUS_MASK 0x1 +#define PMIC_RTC_DDLO_RSTB_STATUS_SHIFT 3 +#define PMIC_CHRWDT_REG_RSTB_STATUS_ADDR MT6353_TOP_RST_STATUS +#define PMIC_CHRWDT_REG_RSTB_STATUS_MASK 0x1 +#define PMIC_CHRWDT_REG_RSTB_STATUS_SHIFT 4 +#define PMIC_CHRDET_REG_RSTB_STATUS_ADDR MT6353_TOP_RST_STATUS +#define PMIC_CHRDET_REG_RSTB_STATUS_MASK 0x1 +#define PMIC_CHRDET_REG_RSTB_STATUS_SHIFT 5 +#define PMIC_TOP_RST_STATUS_RSV_ADDR MT6353_TOP_RST_STATUS +#define PMIC_TOP_RST_STATUS_RSV_MASK 0x3 +#define PMIC_TOP_RST_STATUS_RSV_SHIFT 6 +#define PMIC_TOP_RST_STATUS_SET_ADDR MT6353_TOP_RST_STATUS_SET +#define PMIC_TOP_RST_STATUS_SET_MASK 0xFFFF +#define PMIC_TOP_RST_STATUS_SET_SHIFT 0 +#define PMIC_TOP_RST_STATUS_CLR_ADDR MT6353_TOP_RST_STATUS_CLR +#define PMIC_TOP_RST_STATUS_CLR_MASK 0xFFFF +#define PMIC_TOP_RST_STATUS_CLR_SHIFT 0 +#define PMIC_TOP_RST_RSV_CON0_ADDR MT6353_TOP_RST_RSV_CON0 +#define PMIC_TOP_RST_RSV_CON0_MASK 0xFFFF +#define PMIC_TOP_RST_RSV_CON0_SHIFT 0 +#define PMIC_TOP_RST_RSV_CON1_ADDR MT6353_TOP_RST_RSV_CON1 +#define PMIC_TOP_RST_RSV_CON1_MASK 0xFFFF +#define PMIC_TOP_RST_RSV_CON1_SHIFT 0 +#define PMIC_RG_INT_EN_PWRKEY_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_PWRKEY_MASK 0x1 +#define PMIC_RG_INT_EN_PWRKEY_SHIFT 0 +#define PMIC_RG_INT_EN_HOMEKEY_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_HOMEKEY_MASK 0x1 +#define PMIC_RG_INT_EN_HOMEKEY_SHIFT 1 +#define PMIC_RG_INT_EN_PWRKEY_R_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_PWRKEY_R_MASK 0x1 +#define PMIC_RG_INT_EN_PWRKEY_R_SHIFT 2 +#define PMIC_RG_INT_EN_HOMEKEY_R_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_HOMEKEY_R_MASK 0x1 +#define PMIC_RG_INT_EN_HOMEKEY_R_SHIFT 3 +#define PMIC_RG_INT_EN_THR_H_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_THR_H_MASK 0x1 +#define PMIC_RG_INT_EN_THR_H_SHIFT 4 +#define PMIC_RG_INT_EN_THR_L_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_THR_L_MASK 0x1 +#define PMIC_RG_INT_EN_THR_L_SHIFT 5 +#define PMIC_RG_INT_EN_BAT_H_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_BAT_H_MASK 0x1 +#define PMIC_RG_INT_EN_BAT_H_SHIFT 6 +#define PMIC_RG_INT_EN_BAT_L_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_BAT_L_MASK 0x1 +#define PMIC_RG_INT_EN_BAT_L_SHIFT 7 +#define PMIC_RG_INT_EN_RTC_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_RTC_MASK 0x1 +#define PMIC_RG_INT_EN_RTC_SHIFT 9 +#define PMIC_RG_INT_EN_AUDIO_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_AUDIO_MASK 0x1 +#define PMIC_RG_INT_EN_AUDIO_SHIFT 10 +#define PMIC_RG_INT_EN_ACCDET_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_ACCDET_MASK 0x1 +#define PMIC_RG_INT_EN_ACCDET_SHIFT 12 +#define PMIC_RG_INT_EN_ACCDET_EINT_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_ACCDET_EINT_MASK 0x1 +#define PMIC_RG_INT_EN_ACCDET_EINT_SHIFT 13 +#define PMIC_RG_INT_EN_ACCDET_NEGV_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_ACCDET_NEGV_MASK 0x1 +#define PMIC_RG_INT_EN_ACCDET_NEGV_SHIFT 14 +#define PMIC_RG_INT_EN_NI_LBAT_INT_ADDR MT6353_INT_CON0 +#define PMIC_RG_INT_EN_NI_LBAT_INT_MASK 0x1 +#define PMIC_RG_INT_EN_NI_LBAT_INT_SHIFT 15 +#define PMIC_INT_CON0_SET_ADDR MT6353_INT_CON0_SET +#define PMIC_INT_CON0_SET_MASK 0xFFFF +#define PMIC_INT_CON0_SET_SHIFT 0 +#define PMIC_INT_CON0_CLR_ADDR MT6353_INT_CON0_CLR +#define PMIC_INT_CON0_CLR_MASK 0xFFFF +#define PMIC_INT_CON0_CLR_SHIFT 0 +#define PMIC_RG_INT_EN_VCORE_OC_ADDR MT6353_INT_CON1 +#define PMIC_RG_INT_EN_VCORE_OC_MASK 0x1 +#define PMIC_RG_INT_EN_VCORE_OC_SHIFT 0 +#define PMIC_RG_INT_EN_VPROC_OC_ADDR MT6353_INT_CON1 +#define PMIC_RG_INT_EN_VPROC_OC_MASK 0x1 +#define PMIC_RG_INT_EN_VPROC_OC_SHIFT 1 +#define PMIC_RG_INT_EN_VS1_OC_ADDR MT6353_INT_CON1 +#define PMIC_RG_INT_EN_VS1_OC_MASK 0x1 +#define PMIC_RG_INT_EN_VS1_OC_SHIFT 2 +#define PMIC_RG_INT_EN_VPA_OC_ADDR MT6353_INT_CON1 +#define PMIC_RG_INT_EN_VPA_OC_MASK 0x1 +#define PMIC_RG_INT_EN_VPA_OC_SHIFT 3 +#define PMIC_RG_INT_EN_SPKL_D_ADDR MT6353_INT_CON1 +#define PMIC_RG_INT_EN_SPKL_D_MASK 0x1 +#define PMIC_RG_INT_EN_SPKL_D_SHIFT 4 +#define PMIC_RG_INT_EN_SPKL_AB_ADDR MT6353_INT_CON1 +#define PMIC_RG_INT_EN_SPKL_AB_MASK 0x1 +#define PMIC_RG_INT_EN_SPKL_AB_SHIFT 5 +#define PMIC_RG_INT_EN_LDO_OC_ADDR MT6353_INT_CON1 +#define PMIC_RG_INT_EN_LDO_OC_MASK 0x1 +#define PMIC_RG_INT_EN_LDO_OC_SHIFT 15 +#define PMIC_INT_CON1_SET_ADDR MT6353_INT_CON1_SET +#define PMIC_INT_CON1_SET_MASK 0xFFFF +#define PMIC_INT_CON1_SET_SHIFT 0 +#define PMIC_INT_CON1_CLR_ADDR MT6353_INT_CON1_CLR +#define PMIC_INT_CON1_CLR_MASK 0xFFFF +#define PMIC_INT_CON1_CLR_SHIFT 0 +#define PMIC_RG_INT_EN_TYPE_C_L_MIN_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_TYPE_C_L_MIN_MASK 0x1 +#define PMIC_RG_INT_EN_TYPE_C_L_MIN_SHIFT 0 +#define PMIC_RG_INT_EN_TYPE_C_L_MAX_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_TYPE_C_L_MAX_MASK 0x1 +#define PMIC_RG_INT_EN_TYPE_C_L_MAX_SHIFT 1 +#define PMIC_RG_INT_EN_TYPE_C_H_MIN_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_TYPE_C_H_MIN_MASK 0x1 +#define PMIC_RG_INT_EN_TYPE_C_H_MIN_SHIFT 2 +#define PMIC_RG_INT_EN_TYPE_C_H_MAX_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_TYPE_C_H_MAX_MASK 0x1 +#define PMIC_RG_INT_EN_TYPE_C_H_MAX_SHIFT 3 +#define PMIC_RG_INT_EN_AUXADC_IMP_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_AUXADC_IMP_MASK 0x1 +#define PMIC_RG_INT_EN_AUXADC_IMP_SHIFT 4 +#define PMIC_RG_INT_EN_NAG_C_DLTV_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_NAG_C_DLTV_MASK 0x1 +#define PMIC_RG_INT_EN_NAG_C_DLTV_SHIFT 5 +#define PMIC_RG_INT_EN_TYPE_C_CC_IRQ_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_TYPE_C_CC_IRQ_MASK 0x1 +#define PMIC_RG_INT_EN_TYPE_C_CC_IRQ_SHIFT 6 +#define PMIC_RG_INT_EN_CHRDET_EDGE_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_CHRDET_EDGE_MASK 0x1 +#define PMIC_RG_INT_EN_CHRDET_EDGE_SHIFT 7 +#define PMIC_RG_INT_EN_OV_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_OV_MASK 0x1 +#define PMIC_RG_INT_EN_OV_SHIFT 8 +#define PMIC_RG_INT_EN_BVALID_DET_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_BVALID_DET_MASK 0x1 +#define PMIC_RG_INT_EN_BVALID_DET_SHIFT 9 +#define PMIC_RG_INT_EN_RGS_BATON_HV_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_RGS_BATON_HV_MASK 0x1 +#define PMIC_RG_INT_EN_RGS_BATON_HV_SHIFT 10 +#define PMIC_RG_INT_EN_VBATON_UNDET_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_VBATON_UNDET_MASK 0x1 +#define PMIC_RG_INT_EN_VBATON_UNDET_SHIFT 11 +#define PMIC_RG_INT_EN_WATCHDOG_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_WATCHDOG_MASK 0x1 +#define PMIC_RG_INT_EN_WATCHDOG_SHIFT 12 +#define PMIC_RG_INT_EN_PCHR_CM_VDEC_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_PCHR_CM_VDEC_MASK 0x1 +#define PMIC_RG_INT_EN_PCHR_CM_VDEC_SHIFT 13 +#define PMIC_RG_INT_EN_CHRDET_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_CHRDET_MASK 0x1 +#define PMIC_RG_INT_EN_CHRDET_SHIFT 14 +#define PMIC_RG_INT_EN_PCHR_CM_VINC_ADDR MT6353_INT_CON2 +#define PMIC_RG_INT_EN_PCHR_CM_VINC_MASK 0x1 +#define PMIC_RG_INT_EN_PCHR_CM_VINC_SHIFT 15 +#define PMIC_INT_CON2_SET_ADDR MT6353_INT_CON2_SET +#define PMIC_INT_CON2_SET_MASK 0xFFFF +#define PMIC_INT_CON2_SET_SHIFT 0 +#define PMIC_INT_CON2_CLR_ADDR MT6353_INT_CON2_CLR +#define PMIC_INT_CON2_CLR_MASK 0xFFFF +#define PMIC_INT_CON2_CLR_SHIFT 0 +#define PMIC_RG_INT_EN_FG_BAT_H_ADDR MT6353_INT_CON3 +#define PMIC_RG_INT_EN_FG_BAT_H_MASK 0x1 +#define PMIC_RG_INT_EN_FG_BAT_H_SHIFT 0 +#define PMIC_RG_INT_EN_FG_BAT_L_ADDR MT6353_INT_CON3 +#define PMIC_RG_INT_EN_FG_BAT_L_MASK 0x1 +#define PMIC_RG_INT_EN_FG_BAT_L_SHIFT 1 +#define PMIC_RG_INT_EN_FG_CUR_H_ADDR MT6353_INT_CON3 +#define PMIC_RG_INT_EN_FG_CUR_H_MASK 0x1 +#define PMIC_RG_INT_EN_FG_CUR_H_SHIFT 2 +#define PMIC_RG_INT_EN_FG_CUR_L_ADDR MT6353_INT_CON3 +#define PMIC_RG_INT_EN_FG_CUR_L_MASK 0x1 +#define PMIC_RG_INT_EN_FG_CUR_L_SHIFT 3 +#define PMIC_RG_INT_EN_FG_ZCV_ADDR MT6353_INT_CON3 +#define PMIC_RG_INT_EN_FG_ZCV_MASK 0x1 +#define PMIC_RG_INT_EN_FG_ZCV_SHIFT 4 +#define PMIC_INT_CON3_SET_ADDR MT6353_INT_CON3_SET +#define PMIC_INT_CON3_SET_MASK 0xFFFF +#define PMIC_INT_CON3_SET_SHIFT 0 +#define PMIC_INT_CON3_CLR_ADDR MT6353_INT_CON3_CLR +#define PMIC_INT_CON3_CLR_MASK 0xFFFF +#define PMIC_INT_CON3_CLR_SHIFT 0 +#define PMIC_POLARITY_ADDR MT6353_INT_MISC_CON +#define PMIC_POLARITY_MASK 0x1 +#define PMIC_POLARITY_SHIFT 0 +#define PMIC_RG_HOMEKEY_INT_SEL_ADDR MT6353_INT_MISC_CON +#define PMIC_RG_HOMEKEY_INT_SEL_MASK 0x1 +#define PMIC_RG_HOMEKEY_INT_SEL_SHIFT 1 +#define PMIC_RG_PWRKEY_INT_SEL_ADDR MT6353_INT_MISC_CON +#define PMIC_RG_PWRKEY_INT_SEL_MASK 0x1 +#define PMIC_RG_PWRKEY_INT_SEL_SHIFT 2 +#define PMIC_RG_CHRDET_INT_SEL_ADDR MT6353_INT_MISC_CON +#define PMIC_RG_CHRDET_INT_SEL_MASK 0x1 +#define PMIC_RG_CHRDET_INT_SEL_SHIFT 3 +#define PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_ADDR MT6353_INT_MISC_CON +#define PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_MASK 0x1 +#define PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_SHIFT 4 +#define PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_ADDR MT6353_INT_MISC_CON +#define PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_MASK 0x1 +#define PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_SHIFT 5 +#define PMIC_INT_MISC_CON_SET_ADDR MT6353_INT_MISC_CON_SET +#define PMIC_INT_MISC_CON_SET_MASK 0xFFFF +#define PMIC_INT_MISC_CON_SET_SHIFT 0 +#define PMIC_INT_MISC_CON_CLR_ADDR MT6353_INT_MISC_CON_CLR +#define PMIC_INT_MISC_CON_CLR_MASK 0xFFFF +#define PMIC_INT_MISC_CON_CLR_SHIFT 0 +#define PMIC_RG_INT_STATUS_PWRKEY_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_PWRKEY_MASK 0x1 +#define PMIC_RG_INT_STATUS_PWRKEY_SHIFT 0 +#define PMIC_RG_INT_STATUS_HOMEKEY_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_HOMEKEY_MASK 0x1 +#define PMIC_RG_INT_STATUS_HOMEKEY_SHIFT 1 +#define PMIC_RG_INT_STATUS_PWRKEY_R_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_PWRKEY_R_MASK 0x1 +#define PMIC_RG_INT_STATUS_PWRKEY_R_SHIFT 2 +#define PMIC_RG_INT_STATUS_HOMEKEY_R_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_HOMEKEY_R_MASK 0x1 +#define PMIC_RG_INT_STATUS_HOMEKEY_R_SHIFT 3 +#define PMIC_RG_INT_STATUS_THR_H_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_THR_H_MASK 0x1 +#define PMIC_RG_INT_STATUS_THR_H_SHIFT 4 +#define PMIC_RG_INT_STATUS_THR_L_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_THR_L_MASK 0x1 +#define PMIC_RG_INT_STATUS_THR_L_SHIFT 5 +#define PMIC_RG_INT_STATUS_BAT_H_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_BAT_H_MASK 0x1 +#define PMIC_RG_INT_STATUS_BAT_H_SHIFT 6 +#define PMIC_RG_INT_STATUS_BAT_L_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_BAT_L_MASK 0x1 +#define PMIC_RG_INT_STATUS_BAT_L_SHIFT 7 +#define PMIC_RG_INT_STATUS_RTC_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_RTC_MASK 0x1 +#define PMIC_RG_INT_STATUS_RTC_SHIFT 9 +#define PMIC_RG_INT_STATUS_AUDIO_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_AUDIO_MASK 0x1 +#define PMIC_RG_INT_STATUS_AUDIO_SHIFT 10 +#define PMIC_RG_INT_STATUS_ACCDET_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_ACCDET_MASK 0x1 +#define PMIC_RG_INT_STATUS_ACCDET_SHIFT 12 +#define PMIC_RG_INT_STATUS_ACCDET_EINT_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_ACCDET_EINT_MASK 0x1 +#define PMIC_RG_INT_STATUS_ACCDET_EINT_SHIFT 13 +#define PMIC_RG_INT_STATUS_ACCDET_NEGV_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_ACCDET_NEGV_MASK 0x1 +#define PMIC_RG_INT_STATUS_ACCDET_NEGV_SHIFT 14 +#define PMIC_RG_INT_STATUS_NI_LBAT_INT_ADDR MT6353_INT_STATUS0 +#define PMIC_RG_INT_STATUS_NI_LBAT_INT_MASK 0x1 +#define PMIC_RG_INT_STATUS_NI_LBAT_INT_SHIFT 15 +#define PMIC_RG_INT_STATUS_VCORE_OC_ADDR MT6353_INT_STATUS1 +#define PMIC_RG_INT_STATUS_VCORE_OC_MASK 0x1 +#define PMIC_RG_INT_STATUS_VCORE_OC_SHIFT 0 +#define PMIC_RG_INT_STATUS_VPROC_OC_ADDR MT6353_INT_STATUS1 +#define PMIC_RG_INT_STATUS_VPROC_OC_MASK 0x1 +#define PMIC_RG_INT_STATUS_VPROC_OC_SHIFT 1 +#define PMIC_RG_INT_STATUS_VS1_OC_ADDR MT6353_INT_STATUS1 +#define PMIC_RG_INT_STATUS_VS1_OC_MASK 0x1 +#define PMIC_RG_INT_STATUS_VS1_OC_SHIFT 2 +#define PMIC_RG_INT_STATUS_VPA_OC_ADDR MT6353_INT_STATUS1 +#define PMIC_RG_INT_STATUS_VPA_OC_MASK 0x1 +#define PMIC_RG_INT_STATUS_VPA_OC_SHIFT 3 +#define PMIC_RG_INT_STATUS_SPKL_D_ADDR MT6353_INT_STATUS1 +#define PMIC_RG_INT_STATUS_SPKL_D_MASK 0x1 +#define PMIC_RG_INT_STATUS_SPKL_D_SHIFT 4 +#define PMIC_RG_INT_STATUS_SPKL_AB_ADDR MT6353_INT_STATUS1 +#define PMIC_RG_INT_STATUS_SPKL_AB_MASK 0x1 +#define PMIC_RG_INT_STATUS_SPKL_AB_SHIFT 5 +#define PMIC_RG_INT_STATUS_LDO_OC_ADDR MT6353_INT_STATUS1 +#define PMIC_RG_INT_STATUS_LDO_OC_MASK 0x1 +#define PMIC_RG_INT_STATUS_LDO_OC_SHIFT 15 +#define PMIC_RG_INT_STATUS_TYPE_C_L_MIN_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_TYPE_C_L_MIN_MASK 0x1 +#define PMIC_RG_INT_STATUS_TYPE_C_L_MIN_SHIFT 0 +#define PMIC_RG_INT_STATUS_TYPE_C_L_MAX_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_TYPE_C_L_MAX_MASK 0x1 +#define PMIC_RG_INT_STATUS_TYPE_C_L_MAX_SHIFT 1 +#define PMIC_RG_INT_STATUS_TYPE_C_H_MIN_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_TYPE_C_H_MIN_MASK 0x1 +#define PMIC_RG_INT_STATUS_TYPE_C_H_MIN_SHIFT 2 +#define PMIC_RG_INT_STATUS_TYPE_C_H_MAX_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_TYPE_C_H_MAX_MASK 0x1 +#define PMIC_RG_INT_STATUS_TYPE_C_H_MAX_SHIFT 3 +#define PMIC_RG_INT_STATUS_AUXADC_IMP_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_AUXADC_IMP_MASK 0x1 +#define PMIC_RG_INT_STATUS_AUXADC_IMP_SHIFT 4 +#define PMIC_RG_INT_STATUS_NAG_C_DLTV_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_NAG_C_DLTV_MASK 0x1 +#define PMIC_RG_INT_STATUS_NAG_C_DLTV_SHIFT 5 +#define PMIC_RG_INT_STATUS_TYPE_C_CC_IRQ_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_TYPE_C_CC_IRQ_MASK 0x1 +#define PMIC_RG_INT_STATUS_TYPE_C_CC_IRQ_SHIFT 6 +#define PMIC_RG_INT_STATUS_CHRDET_EDGE_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_CHRDET_EDGE_MASK 0x1 +#define PMIC_RG_INT_STATUS_CHRDET_EDGE_SHIFT 7 +#define PMIC_RG_INT_STATUS_OV_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_OV_MASK 0x1 +#define PMIC_RG_INT_STATUS_OV_SHIFT 8 +#define PMIC_RG_INT_STATUS_BVALID_DET_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_BVALID_DET_MASK 0x1 +#define PMIC_RG_INT_STATUS_BVALID_DET_SHIFT 9 +#define PMIC_RG_INT_STATUS_RGS_BATON_HV_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_RGS_BATON_HV_MASK 0x1 +#define PMIC_RG_INT_STATUS_RGS_BATON_HV_SHIFT 10 +#define PMIC_RG_INT_STATUS_VBATON_UNDET_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_VBATON_UNDET_MASK 0x1 +#define PMIC_RG_INT_STATUS_VBATON_UNDET_SHIFT 11 +#define PMIC_RG_INT_STATUS_WATCHDOG_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_WATCHDOG_MASK 0x1 +#define PMIC_RG_INT_STATUS_WATCHDOG_SHIFT 12 +#define PMIC_RG_INT_STATUS_PCHR_CM_VDEC_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_PCHR_CM_VDEC_MASK 0x1 +#define PMIC_RG_INT_STATUS_PCHR_CM_VDEC_SHIFT 13 +#define PMIC_RG_INT_STATUS_CHRDET_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_CHRDET_MASK 0x1 +#define PMIC_RG_INT_STATUS_CHRDET_SHIFT 14 +#define PMIC_RG_INT_STATUS_PCHR_CM_VINC_ADDR MT6353_INT_STATUS2 +#define PMIC_RG_INT_STATUS_PCHR_CM_VINC_MASK 0x1 +#define PMIC_RG_INT_STATUS_PCHR_CM_VINC_SHIFT 15 +#define PMIC_RG_INT_STATUS_FG_BAT_H_ADDR MT6353_INT_STATUS3 +#define PMIC_RG_INT_STATUS_FG_BAT_H_MASK 0x1 +#define PMIC_RG_INT_STATUS_FG_BAT_H_SHIFT 0 +#define PMIC_RG_INT_STATUS_FG_BAT_L_ADDR MT6353_INT_STATUS3 +#define PMIC_RG_INT_STATUS_FG_BAT_L_MASK 0x1 +#define PMIC_RG_INT_STATUS_FG_BAT_L_SHIFT 1 +#define PMIC_RG_INT_STATUS_FG_CUR_H_ADDR MT6353_INT_STATUS3 +#define PMIC_RG_INT_STATUS_FG_CUR_H_MASK 0x1 +#define PMIC_RG_INT_STATUS_FG_CUR_H_SHIFT 2 +#define PMIC_RG_INT_STATUS_FG_CUR_L_ADDR MT6353_INT_STATUS3 +#define PMIC_RG_INT_STATUS_FG_CUR_L_MASK 0x1 +#define PMIC_RG_INT_STATUS_FG_CUR_L_SHIFT 3 +#define PMIC_RG_INT_STATUS_FG_ZCV_ADDR MT6353_INT_STATUS3 +#define PMIC_RG_INT_STATUS_FG_ZCV_MASK 0x1 +#define PMIC_RG_INT_STATUS_FG_ZCV_SHIFT 4 +#define PMIC_OC_GEAR_LDO_ADDR MT6353_OC_GEAR_0 +#define PMIC_OC_GEAR_LDO_MASK 0x3 +#define PMIC_OC_GEAR_LDO_SHIFT 0 +#define PMIC_SPK_EN_L_ADDR MT6353_SPK_CON0 +#define PMIC_SPK_EN_L_MASK 0x1 +#define PMIC_SPK_EN_L_SHIFT 0 +#define PMIC_SPKMODE_L_ADDR MT6353_SPK_CON0 +#define PMIC_SPKMODE_L_MASK 0x1 +#define PMIC_SPKMODE_L_SHIFT 2 +#define PMIC_SPK_TRIM_EN_L_ADDR MT6353_SPK_CON0 +#define PMIC_SPK_TRIM_EN_L_MASK 0x1 +#define PMIC_SPK_TRIM_EN_L_SHIFT 3 +#define PMIC_SPK_OC_SHDN_DL_ADDR MT6353_SPK_CON0 +#define PMIC_SPK_OC_SHDN_DL_MASK 0x1 +#define PMIC_SPK_OC_SHDN_DL_SHIFT 8 +#define PMIC_SPK_THER_SHDN_L_EN_ADDR MT6353_SPK_CON0 +#define PMIC_SPK_THER_SHDN_L_EN_MASK 0x1 +#define PMIC_SPK_THER_SHDN_L_EN_SHIFT 9 +#define PMIC_SPK_OUT_STAGE_SEL_ADDR MT6353_SPK_CON0 +#define PMIC_SPK_OUT_STAGE_SEL_MASK 0x1 +#define PMIC_SPK_OUT_STAGE_SEL_SHIFT 10 +#define PMIC_RG_SPK_GAINL_ADDR MT6353_SPK_CON0 +#define PMIC_RG_SPK_GAINL_MASK 0x3 +#define PMIC_RG_SPK_GAINL_SHIFT 12 +#define PMIC_DA_SPK_OFFSET_L_ADDR MT6353_SPK_CON1 +#define PMIC_DA_SPK_OFFSET_L_MASK 0x1F +#define PMIC_DA_SPK_OFFSET_L_SHIFT 0 +#define PMIC_DA_SPK_LEAD_DGLH_L_ADDR MT6353_SPK_CON1 +#define PMIC_DA_SPK_LEAD_DGLH_L_MASK 0x1 +#define PMIC_DA_SPK_LEAD_DGLH_L_SHIFT 5 +#define PMIC_AD_NI_SPK_LEAD_L_ADDR MT6353_SPK_CON1 +#define PMIC_AD_NI_SPK_LEAD_L_MASK 0x1 +#define PMIC_AD_NI_SPK_LEAD_L_SHIFT 6 +#define PMIC_SPK_OFFSET_L_OV_ADDR MT6353_SPK_CON1 +#define PMIC_SPK_OFFSET_L_OV_MASK 0x1 +#define PMIC_SPK_OFFSET_L_OV_SHIFT 7 +#define PMIC_SPK_OFFSET_L_SW_ADDR MT6353_SPK_CON1 +#define PMIC_SPK_OFFSET_L_SW_MASK 0x1F +#define PMIC_SPK_OFFSET_L_SW_SHIFT 8 +#define PMIC_SPK_LEAD_L_SW_ADDR MT6353_SPK_CON1 +#define PMIC_SPK_LEAD_L_SW_MASK 0x1 +#define PMIC_SPK_LEAD_L_SW_SHIFT 13 +#define PMIC_SPK_OFFSET_L_MODE_ADDR MT6353_SPK_CON1 +#define PMIC_SPK_OFFSET_L_MODE_MASK 0x1 +#define PMIC_SPK_OFFSET_L_MODE_SHIFT 14 +#define PMIC_SPK_TRIM_DONE_L_ADDR MT6353_SPK_CON1 +#define PMIC_SPK_TRIM_DONE_L_MASK 0x1 +#define PMIC_SPK_TRIM_DONE_L_SHIFT 15 +#define PMIC_RG_SPK_INTG_RST_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPK_INTG_RST_L_MASK 0x1 +#define PMIC_RG_SPK_INTG_RST_L_SHIFT 0 +#define PMIC_RG_SPK_FORCE_EN_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPK_FORCE_EN_L_MASK 0x1 +#define PMIC_RG_SPK_FORCE_EN_L_SHIFT 1 +#define PMIC_RG_SPK_SLEW_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPK_SLEW_L_MASK 0x3 +#define PMIC_RG_SPK_SLEW_L_SHIFT 2 +#define PMIC_RG_SPKAB_OBIAS_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPKAB_OBIAS_L_MASK 0x3 +#define PMIC_RG_SPKAB_OBIAS_L_SHIFT 4 +#define PMIC_RG_SPKRCV_EN_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPKRCV_EN_L_MASK 0x1 +#define PMIC_RG_SPKRCV_EN_L_SHIFT 6 +#define PMIC_RG_SPK_DRC_EN_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPK_DRC_EN_L_MASK 0x1 +#define PMIC_RG_SPK_DRC_EN_L_SHIFT 7 +#define PMIC_RG_SPK_TEST_EN_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPK_TEST_EN_L_MASK 0x1 +#define PMIC_RG_SPK_TEST_EN_L_SHIFT 8 +#define PMIC_RG_SPKAB_OC_EN_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPKAB_OC_EN_L_MASK 0x1 +#define PMIC_RG_SPKAB_OC_EN_L_SHIFT 9 +#define PMIC_RG_SPK_OC_EN_L_ADDR MT6353_SPK_CON2 +#define PMIC_RG_SPK_OC_EN_L_MASK 0x1 +#define PMIC_RG_SPK_OC_EN_L_SHIFT 10 +#define PMIC_SPK_EN_R_ADDR MT6353_SPK_CON3 +#define PMIC_SPK_EN_R_MASK 0x1 +#define PMIC_SPK_EN_R_SHIFT 0 +#define PMIC_SPKMODE_R_ADDR MT6353_SPK_CON3 +#define PMIC_SPKMODE_R_MASK 0x1 +#define PMIC_SPKMODE_R_SHIFT 2 +#define PMIC_SPK_TRIM_EN_R_ADDR MT6353_SPK_CON3 +#define PMIC_SPK_TRIM_EN_R_MASK 0x1 +#define PMIC_SPK_TRIM_EN_R_SHIFT 3 +#define PMIC_SPK_OC_SHDN_DR_ADDR MT6353_SPK_CON3 +#define PMIC_SPK_OC_SHDN_DR_MASK 0x1 +#define PMIC_SPK_OC_SHDN_DR_SHIFT 8 +#define PMIC_SPK_THER_SHDN_R_EN_ADDR MT6353_SPK_CON3 +#define PMIC_SPK_THER_SHDN_R_EN_MASK 0x1 +#define PMIC_SPK_THER_SHDN_R_EN_SHIFT 9 +#define PMIC_RG_SPK_GAINR_ADDR MT6353_SPK_CON3 +#define PMIC_RG_SPK_GAINR_MASK 0x3 +#define PMIC_RG_SPK_GAINR_SHIFT 12 +#define PMIC_DA_SPK_OFFSET_R_ADDR MT6353_SPK_CON4 +#define PMIC_DA_SPK_OFFSET_R_MASK 0x1F +#define PMIC_DA_SPK_OFFSET_R_SHIFT 0 +#define PMIC_DA_SPK_LEAD_DGLH_R_ADDR MT6353_SPK_CON4 +#define PMIC_DA_SPK_LEAD_DGLH_R_MASK 0x1 +#define PMIC_DA_SPK_LEAD_DGLH_R_SHIFT 5 +#define PMIC_NI_SPK_LEAD_R_ADDR MT6353_SPK_CON4 +#define PMIC_NI_SPK_LEAD_R_MASK 0x1 +#define PMIC_NI_SPK_LEAD_R_SHIFT 6 +#define PMIC_SPK_OFFSET_R_OV_ADDR MT6353_SPK_CON4 +#define PMIC_SPK_OFFSET_R_OV_MASK 0x1 +#define PMIC_SPK_OFFSET_R_OV_SHIFT 7 +#define PMIC_SPK_OFFSET_R_SW_ADDR MT6353_SPK_CON4 +#define PMIC_SPK_OFFSET_R_SW_MASK 0x1F +#define PMIC_SPK_OFFSET_R_SW_SHIFT 8 +#define PMIC_SPK_LEAD_R_SW_ADDR MT6353_SPK_CON4 +#define PMIC_SPK_LEAD_R_SW_MASK 0x1 +#define PMIC_SPK_LEAD_R_SW_SHIFT 13 +#define PMIC_SPK_OFFSET_R_MODE_ADDR MT6353_SPK_CON4 +#define PMIC_SPK_OFFSET_R_MODE_MASK 0x1 +#define PMIC_SPK_OFFSET_R_MODE_SHIFT 14 +#define PMIC_SPK_TRIM_DONE_R_ADDR MT6353_SPK_CON4 +#define PMIC_SPK_TRIM_DONE_R_MASK 0x1 +#define PMIC_SPK_TRIM_DONE_R_SHIFT 15 +#define PMIC_RG_SPK_INTG_RST_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPK_INTG_RST_R_MASK 0x1 +#define PMIC_RG_SPK_INTG_RST_R_SHIFT 0 +#define PMIC_RG_SPK_FORCE_EN_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPK_FORCE_EN_R_MASK 0x1 +#define PMIC_RG_SPK_FORCE_EN_R_SHIFT 1 +#define PMIC_RG_SPK_SLEW_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPK_SLEW_R_MASK 0x3 +#define PMIC_RG_SPK_SLEW_R_SHIFT 2 +#define PMIC_RG_SPKAB_OBIAS_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPKAB_OBIAS_R_MASK 0x3 +#define PMIC_RG_SPKAB_OBIAS_R_SHIFT 4 +#define PMIC_RG_SPKRCV_EN_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPKRCV_EN_R_MASK 0x1 +#define PMIC_RG_SPKRCV_EN_R_SHIFT 6 +#define PMIC_RG_SPK_DRC_EN_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPK_DRC_EN_R_MASK 0x1 +#define PMIC_RG_SPK_DRC_EN_R_SHIFT 7 +#define PMIC_RG_SPK_TEST_EN_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPK_TEST_EN_R_MASK 0x1 +#define PMIC_RG_SPK_TEST_EN_R_SHIFT 8 +#define PMIC_RG_SPKAB_OC_EN_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPKAB_OC_EN_R_MASK 0x1 +#define PMIC_RG_SPKAB_OC_EN_R_SHIFT 9 +#define PMIC_RG_SPK_OC_EN_R_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPK_OC_EN_R_MASK 0x1 +#define PMIC_RG_SPK_OC_EN_R_SHIFT 10 +#define PMIC_RG_SPKPGA_GAINR_ADDR MT6353_SPK_CON5 +#define PMIC_RG_SPKPGA_GAINR_MASK 0xF +#define PMIC_RG_SPKPGA_GAINR_SHIFT 11 +#define PMIC_SPK_TRIM_WND_ADDR MT6353_SPK_CON6 +#define PMIC_SPK_TRIM_WND_MASK 0x7 +#define PMIC_SPK_TRIM_WND_SHIFT 0 +#define PMIC_SPK_TRIM_THD_ADDR MT6353_SPK_CON6 +#define PMIC_SPK_TRIM_THD_MASK 0x3 +#define PMIC_SPK_TRIM_THD_SHIFT 4 +#define PMIC_SPK_OC_WND_ADDR MT6353_SPK_CON6 +#define PMIC_SPK_OC_WND_MASK 0x3 +#define PMIC_SPK_OC_WND_SHIFT 8 +#define PMIC_SPK_OC_THD_ADDR MT6353_SPK_CON6 +#define PMIC_SPK_OC_THD_MASK 0x3 +#define PMIC_SPK_OC_THD_SHIFT 10 +#define PMIC_SPK_D_OC_R_DEG_ADDR MT6353_SPK_CON6 +#define PMIC_SPK_D_OC_R_DEG_MASK 0x1 +#define PMIC_SPK_D_OC_R_DEG_SHIFT 12 +#define PMIC_SPK_AB_OC_R_DEG_ADDR MT6353_SPK_CON6 +#define PMIC_SPK_AB_OC_R_DEG_MASK 0x1 +#define PMIC_SPK_AB_OC_R_DEG_SHIFT 13 +#define PMIC_SPK_D_OC_L_DEG_ADDR MT6353_SPK_CON6 +#define PMIC_SPK_D_OC_L_DEG_MASK 0x1 +#define PMIC_SPK_D_OC_L_DEG_SHIFT 14 +#define PMIC_SPK_AB_OC_L_DEG_ADDR MT6353_SPK_CON6 +#define PMIC_SPK_AB_OC_L_DEG_MASK 0x1 +#define PMIC_SPK_AB_OC_L_DEG_SHIFT 15 +#define PMIC_SPK_TD1_ADDR MT6353_SPK_CON7 +#define PMIC_SPK_TD1_MASK 0xF +#define PMIC_SPK_TD1_SHIFT 0 +#define PMIC_SPK_TD2_ADDR MT6353_SPK_CON7 +#define PMIC_SPK_TD2_MASK 0xF +#define PMIC_SPK_TD2_SHIFT 4 +#define PMIC_SPK_TD3_ADDR MT6353_SPK_CON7 +#define PMIC_SPK_TD3_MASK 0xF +#define PMIC_SPK_TD3_SHIFT 8 +#define PMIC_SPK_TRIM_DIV_ADDR MT6353_SPK_CON7 +#define PMIC_SPK_TRIM_DIV_MASK 0x7 +#define PMIC_SPK_TRIM_DIV_SHIFT 12 +#define PMIC_RG_BTL_SET_ADDR MT6353_SPK_CON8 +#define PMIC_RG_BTL_SET_MASK 0x3 +#define PMIC_RG_BTL_SET_SHIFT 0 +#define PMIC_RG_SPK_IBIAS_SEL_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPK_IBIAS_SEL_MASK 0x3 +#define PMIC_RG_SPK_IBIAS_SEL_SHIFT 2 +#define PMIC_RG_SPK_CCODE_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPK_CCODE_MASK 0xF +#define PMIC_RG_SPK_CCODE_SHIFT 4 +#define PMIC_RG_SPK_EN_VIEW_VCM_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPK_EN_VIEW_VCM_MASK 0x1 +#define PMIC_RG_SPK_EN_VIEW_VCM_SHIFT 8 +#define PMIC_RG_SPK_EN_VIEW_CLK_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPK_EN_VIEW_CLK_MASK 0x1 +#define PMIC_RG_SPK_EN_VIEW_CLK_SHIFT 9 +#define PMIC_RG_SPK_VCM_SEL_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPK_VCM_SEL_MASK 0x1 +#define PMIC_RG_SPK_VCM_SEL_SHIFT 10 +#define PMIC_RG_SPK_VCM_IBSEL_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPK_VCM_IBSEL_MASK 0x1 +#define PMIC_RG_SPK_VCM_IBSEL_SHIFT 11 +#define PMIC_RG_SPK_FBRC_EN_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPK_FBRC_EN_MASK 0x1 +#define PMIC_RG_SPK_FBRC_EN_SHIFT 12 +#define PMIC_RG_SPKAB_OVDRV_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPKAB_OVDRV_MASK 0x1 +#define PMIC_RG_SPKAB_OVDRV_SHIFT 13 +#define PMIC_RG_SPK_OCTH_D_ADDR MT6353_SPK_CON8 +#define PMIC_RG_SPK_OCTH_D_MASK 0x1 +#define PMIC_RG_SPK_OCTH_D_SHIFT 14 +#define PMIC_RG_SPKPGA_GAINL_ADDR MT6353_SPK_CON9 +#define PMIC_RG_SPKPGA_GAINL_MASK 0xF +#define PMIC_RG_SPKPGA_GAINL_SHIFT 8 +#define PMIC_SPK_RSV0_ADDR MT6353_SPK_CON9 +#define PMIC_SPK_RSV0_MASK 0x1 +#define PMIC_SPK_RSV0_SHIFT 12 +#define PMIC_SPK_VCM_FAST_EN_ADDR MT6353_SPK_CON9 +#define PMIC_SPK_VCM_FAST_EN_MASK 0x1 +#define PMIC_SPK_VCM_FAST_EN_SHIFT 13 +#define PMIC_SPK_TEST_MODE0_ADDR MT6353_SPK_CON9 +#define PMIC_SPK_TEST_MODE0_MASK 0x1 +#define PMIC_SPK_TEST_MODE0_SHIFT 14 +#define PMIC_SPK_TEST_MODE1_ADDR MT6353_SPK_CON9 +#define PMIC_SPK_TEST_MODE1_MASK 0x1 +#define PMIC_SPK_TEST_MODE1_SHIFT 15 +#define PMIC_SPK_TD_WAIT_ADDR MT6353_SPK_CON10 +#define PMIC_SPK_TD_WAIT_MASK 0x7 +#define PMIC_SPK_TD_WAIT_SHIFT 0 +#define PMIC_SPK_TD_DONE_ADDR MT6353_SPK_CON10 +#define PMIC_SPK_TD_DONE_MASK 0x7 +#define PMIC_SPK_TD_DONE_SHIFT 4 +#define PMIC_SPK_EN_MODE_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_EN_MODE_MASK 0x1 +#define PMIC_SPK_EN_MODE_SHIFT 0 +#define PMIC_SPK_VCM_FAST_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_VCM_FAST_SW_MASK 0x1 +#define PMIC_SPK_VCM_FAST_SW_SHIFT 1 +#define PMIC_SPK_RST_R_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_RST_R_SW_MASK 0x1 +#define PMIC_SPK_RST_R_SW_SHIFT 2 +#define PMIC_SPK_RST_L_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_RST_L_SW_MASK 0x1 +#define PMIC_SPK_RST_L_SW_SHIFT 3 +#define PMIC_SPKMODE_R_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPKMODE_R_SW_MASK 0x1 +#define PMIC_SPKMODE_R_SW_SHIFT 4 +#define PMIC_SPKMODE_L_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPKMODE_L_SW_MASK 0x1 +#define PMIC_SPKMODE_L_SW_SHIFT 5 +#define PMIC_SPK_DEPOP_EN_R_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_DEPOP_EN_R_SW_MASK 0x1 +#define PMIC_SPK_DEPOP_EN_R_SW_SHIFT 6 +#define PMIC_SPK_DEPOP_EN_L_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_DEPOP_EN_L_SW_MASK 0x1 +#define PMIC_SPK_DEPOP_EN_L_SW_SHIFT 7 +#define PMIC_SPK_EN_R_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_EN_R_SW_MASK 0x1 +#define PMIC_SPK_EN_R_SW_SHIFT 8 +#define PMIC_SPK_EN_L_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_EN_L_SW_MASK 0x1 +#define PMIC_SPK_EN_L_SW_SHIFT 9 +#define PMIC_SPK_OUTSTG_EN_R_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_OUTSTG_EN_R_SW_MASK 0x1 +#define PMIC_SPK_OUTSTG_EN_R_SW_SHIFT 10 +#define PMIC_SPK_OUTSTG_EN_L_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_OUTSTG_EN_L_SW_MASK 0x1 +#define PMIC_SPK_OUTSTG_EN_L_SW_SHIFT 11 +#define PMIC_SPK_TRIM_EN_R_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_TRIM_EN_R_SW_MASK 0x1 +#define PMIC_SPK_TRIM_EN_R_SW_SHIFT 12 +#define PMIC_SPK_TRIM_EN_L_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_TRIM_EN_L_SW_MASK 0x1 +#define PMIC_SPK_TRIM_EN_L_SW_SHIFT 13 +#define PMIC_SPK_TRIM_STOP_R_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_TRIM_STOP_R_SW_MASK 0x1 +#define PMIC_SPK_TRIM_STOP_R_SW_SHIFT 14 +#define PMIC_SPK_TRIM_STOP_L_SW_ADDR MT6353_SPK_CON11 +#define PMIC_SPK_TRIM_STOP_L_SW_MASK 0x1 +#define PMIC_SPK_TRIM_STOP_L_SW_SHIFT 15 +#define PMIC_RG_SPK_ISENSE_TEST_EN_ADDR MT6353_SPK_CON12 +#define PMIC_RG_SPK_ISENSE_TEST_EN_MASK 0x1 +#define PMIC_RG_SPK_ISENSE_TEST_EN_SHIFT 7 +#define PMIC_RG_SPK_ISENSE_REFSEL_ADDR MT6353_SPK_CON12 +#define PMIC_RG_SPK_ISENSE_REFSEL_MASK 0x7 +#define PMIC_RG_SPK_ISENSE_REFSEL_SHIFT 8 +#define PMIC_RG_SPK_ISENSE_GAINSEL_ADDR MT6353_SPK_CON12 +#define PMIC_RG_SPK_ISENSE_GAINSEL_MASK 0x7 +#define PMIC_RG_SPK_ISENSE_GAINSEL_SHIFT 11 +#define PMIC_RG_SPK_ISENSE_PDRESET_ADDR MT6353_SPK_CON12 +#define PMIC_RG_SPK_ISENSE_PDRESET_MASK 0x1 +#define PMIC_RG_SPK_ISENSE_PDRESET_SHIFT 14 +#define PMIC_RG_SPK_ISENSE_EN_ADDR MT6353_SPK_CON12 +#define PMIC_RG_SPK_ISENSE_EN_MASK 0x1 +#define PMIC_RG_SPK_ISENSE_EN_SHIFT 15 +#define PMIC_RG_SPK_RSV1_ADDR MT6353_SPK_CON13 +#define PMIC_RG_SPK_RSV1_MASK 0xFF +#define PMIC_RG_SPK_RSV1_SHIFT 0 +#define PMIC_RG_SPK_RSV0_ADDR MT6353_SPK_CON13 +#define PMIC_RG_SPK_RSV0_MASK 0xFF +#define PMIC_RG_SPK_RSV0_SHIFT 8 +#define PMIC_RG_SPK_ABD_VOLSEN_GAIN_ADDR MT6353_SPK_CON14 +#define PMIC_RG_SPK_ABD_VOLSEN_GAIN_MASK 0x3 +#define PMIC_RG_SPK_ABD_VOLSEN_GAIN_SHIFT 4 +#define PMIC_RG_SPK_ABD_VOLSEN_EN_ADDR MT6353_SPK_CON14 +#define PMIC_RG_SPK_ABD_VOLSEN_EN_MASK 0x1 +#define PMIC_RG_SPK_ABD_VOLSEN_EN_SHIFT 6 +#define PMIC_RG_SPK_ABD_CURSEN_SEL_ADDR MT6353_SPK_CON14 +#define PMIC_RG_SPK_ABD_CURSEN_SEL_MASK 0x1 +#define PMIC_RG_SPK_ABD_CURSEN_SEL_SHIFT 7 +#define PMIC_RG_SPK_RSV2_ADDR MT6353_SPK_CON14 +#define PMIC_RG_SPK_RSV2_MASK 0xFF +#define PMIC_RG_SPK_RSV2_SHIFT 8 +#define PMIC_RG_SPK_TRIM2_ADDR MT6353_SPK_CON15 +#define PMIC_RG_SPK_TRIM2_MASK 0xFF +#define PMIC_RG_SPK_TRIM2_SHIFT 0 +#define PMIC_RG_SPK_TRIM1_ADDR MT6353_SPK_CON15 +#define PMIC_RG_SPK_TRIM1_MASK 0xFF +#define PMIC_RG_SPK_TRIM1_SHIFT 8 +#define PMIC_RG_SPK_D_CURSEN_RSETSEL_ADDR MT6353_SPK_CON16 +#define PMIC_RG_SPK_D_CURSEN_RSETSEL_MASK 0x1F +#define PMIC_RG_SPK_D_CURSEN_RSETSEL_SHIFT 0 +#define PMIC_RG_SPK_D_CURSEN_GAIN_ADDR MT6353_SPK_CON16 +#define PMIC_RG_SPK_D_CURSEN_GAIN_MASK 0x3 +#define PMIC_RG_SPK_D_CURSEN_GAIN_SHIFT 5 +#define PMIC_RG_SPK_D_CURSEN_EN_ADDR MT6353_SPK_CON16 +#define PMIC_RG_SPK_D_CURSEN_EN_MASK 0x1 +#define PMIC_RG_SPK_D_CURSEN_EN_SHIFT 7 +#define PMIC_RG_SPK_AB_CURSEN_RSETSEL_ADDR MT6353_SPK_CON16 +#define PMIC_RG_SPK_AB_CURSEN_RSETSEL_MASK 0x1F +#define PMIC_RG_SPK_AB_CURSEN_RSETSEL_SHIFT 8 +#define PMIC_RG_SPK_AB_CURSEN_GAIN_ADDR MT6353_SPK_CON16 +#define PMIC_RG_SPK_AB_CURSEN_GAIN_MASK 0x3 +#define PMIC_RG_SPK_AB_CURSEN_GAIN_SHIFT 13 +#define PMIC_RG_SPK_AB_CURSEN_EN_ADDR MT6353_SPK_CON16 +#define PMIC_RG_SPK_AB_CURSEN_EN_MASK 0x1 +#define PMIC_RG_SPK_AB_CURSEN_EN_SHIFT 15 +#define PMIC_RG_SPKPGA_GAIN_ADDR MT6353_SPK_ANA_CON0 +#define PMIC_RG_SPKPGA_GAIN_MASK 0xF +#define PMIC_RG_SPKPGA_GAIN_SHIFT 11 +#define PMIC_RG_SPK_RSV_ADDR MT6353_SPK_ANA_CON1 +#define PMIC_RG_SPK_RSV_MASK 0xFF +#define PMIC_RG_SPK_RSV_SHIFT 0 +#define PMIC_RG_ISENSE_PD_RESET_ADDR MT6353_SPK_ANA_CON1 +#define PMIC_RG_ISENSE_PD_RESET_MASK 0x1 +#define PMIC_RG_ISENSE_PD_RESET_SHIFT 11 +#define PMIC_RG_AUDIVLPWRUP_VAUDP12_ADDR MT6353_SPK_ANA_CON3 +#define PMIC_RG_AUDIVLPWRUP_VAUDP12_MASK 0x1 +#define PMIC_RG_AUDIVLPWRUP_VAUDP12_SHIFT 4 +#define PMIC_RG_AUDIVLSTARTUP_VAUDP12_ADDR MT6353_SPK_ANA_CON3 +#define PMIC_RG_AUDIVLSTARTUP_VAUDP12_MASK 0x1 +#define PMIC_RG_AUDIVLSTARTUP_VAUDP12_SHIFT 5 +#define PMIC_RG_AUDIVLMUXSEL_VAUDP12_ADDR MT6353_SPK_ANA_CON3 +#define PMIC_RG_AUDIVLMUXSEL_VAUDP12_MASK 0x7 +#define PMIC_RG_AUDIVLMUXSEL_VAUDP12_SHIFT 6 +#define PMIC_RG_AUDIVLMUTE_VAUDP12_ADDR MT6353_SPK_ANA_CON3 +#define PMIC_RG_AUDIVLMUTE_VAUDP12_MASK 0x1 +#define PMIC_RG_AUDIVLMUTE_VAUDP12_SHIFT 9 +#define PMIC_FQMTR_TCKSEL_ADDR MT6353_FQMTR_CON0 +#define PMIC_FQMTR_TCKSEL_MASK 0x7 +#define PMIC_FQMTR_TCKSEL_SHIFT 0 +#define PMIC_FQMTR_BUSY_ADDR MT6353_FQMTR_CON0 +#define PMIC_FQMTR_BUSY_MASK 0x1 +#define PMIC_FQMTR_BUSY_SHIFT 3 +#define PMIC_FQMTR_DCXO26M_EN_ADDR MT6353_FQMTR_CON0 +#define PMIC_FQMTR_DCXO26M_EN_MASK 0x1 +#define PMIC_FQMTR_DCXO26M_EN_SHIFT 4 +#define PMIC_FQMTR_EN_ADDR MT6353_FQMTR_CON0 +#define PMIC_FQMTR_EN_MASK 0x1 +#define PMIC_FQMTR_EN_SHIFT 15 +#define PMIC_FQMTR_WINSET_ADDR MT6353_FQMTR_CON1 +#define PMIC_FQMTR_WINSET_MASK 0xFFFF +#define PMIC_FQMTR_WINSET_SHIFT 0 +#define PMIC_FQMTR_DATA_ADDR MT6353_FQMTR_CON2 +#define PMIC_FQMTR_DATA_MASK 0xFFFF +#define PMIC_FQMTR_DATA_SHIFT 0 +#define PMIC_RG_TRIM_EN_ADDR MT6353_ISINK_ANA_CON_0 +#define PMIC_RG_TRIM_EN_MASK 0x1 +#define PMIC_RG_TRIM_EN_SHIFT 0 +#define PMIC_RG_TRIM_SEL_ADDR MT6353_ISINK_ANA_CON_0 +#define PMIC_RG_TRIM_SEL_MASK 0x7 +#define PMIC_RG_TRIM_SEL_SHIFT 1 +#define PMIC_RG_ISINKS_RSV_ADDR MT6353_ISINK_ANA_CON_0 +#define PMIC_RG_ISINKS_RSV_MASK 0xFF +#define PMIC_RG_ISINKS_RSV_SHIFT 4 +#define PMIC_RG_ISINK0_DOUBLE_EN_ADDR MT6353_ISINK_ANA_CON_0 +#define PMIC_RG_ISINK0_DOUBLE_EN_MASK 0x1 +#define PMIC_RG_ISINK0_DOUBLE_EN_SHIFT 12 +#define PMIC_RG_ISINK1_DOUBLE_EN_ADDR MT6353_ISINK_ANA_CON_0 +#define PMIC_RG_ISINK1_DOUBLE_EN_MASK 0x1 +#define PMIC_RG_ISINK1_DOUBLE_EN_SHIFT 13 +#define PMIC_RG_ISINK2_DOUBLE_EN_ADDR MT6353_ISINK_ANA_CON_0 +#define PMIC_RG_ISINK2_DOUBLE_EN_MASK 0x1 +#define PMIC_RG_ISINK2_DOUBLE_EN_SHIFT 14 +#define PMIC_RG_ISINK3_DOUBLE_EN_ADDR MT6353_ISINK_ANA_CON_0 +#define PMIC_RG_ISINK3_DOUBLE_EN_MASK 0x1 +#define PMIC_RG_ISINK3_DOUBLE_EN_SHIFT 15 +#define PMIC_ISINK_DIM0_FSEL_ADDR MT6353_ISINK0_CON0 +#define PMIC_ISINK_DIM0_FSEL_MASK 0xFFFF +#define PMIC_ISINK_DIM0_FSEL_SHIFT 0 +#define PMIC_ISINK0_RSV1_ADDR MT6353_ISINK0_CON1 +#define PMIC_ISINK0_RSV1_MASK 0xF +#define PMIC_ISINK0_RSV1_SHIFT 0 +#define PMIC_ISINK0_RSV0_ADDR MT6353_ISINK0_CON1 +#define PMIC_ISINK0_RSV0_MASK 0x7 +#define PMIC_ISINK0_RSV0_SHIFT 4 +#define PMIC_ISINK_DIM0_DUTY_ADDR MT6353_ISINK0_CON1 +#define PMIC_ISINK_DIM0_DUTY_MASK 0x1F +#define PMIC_ISINK_DIM0_DUTY_SHIFT 7 +#define PMIC_ISINK_CH0_STEP_ADDR MT6353_ISINK0_CON1 +#define PMIC_ISINK_CH0_STEP_MASK 0x7 +#define PMIC_ISINK_CH0_STEP_SHIFT 12 +#define PMIC_ISINK_BREATH0_TF2_SEL_ADDR MT6353_ISINK0_CON2 +#define PMIC_ISINK_BREATH0_TF2_SEL_MASK 0xF +#define PMIC_ISINK_BREATH0_TF2_SEL_SHIFT 0 +#define PMIC_ISINK_BREATH0_TF1_SEL_ADDR MT6353_ISINK0_CON2 +#define PMIC_ISINK_BREATH0_TF1_SEL_MASK 0xF +#define PMIC_ISINK_BREATH0_TF1_SEL_SHIFT 4 +#define PMIC_ISINK_BREATH0_TR2_SEL_ADDR MT6353_ISINK0_CON2 +#define PMIC_ISINK_BREATH0_TR2_SEL_MASK 0xF +#define PMIC_ISINK_BREATH0_TR2_SEL_SHIFT 8 +#define PMIC_ISINK_BREATH0_TR1_SEL_ADDR MT6353_ISINK0_CON2 +#define PMIC_ISINK_BREATH0_TR1_SEL_MASK 0xF +#define PMIC_ISINK_BREATH0_TR1_SEL_SHIFT 12 +#define PMIC_ISINK_BREATH0_TOFF_SEL_ADDR MT6353_ISINK0_CON3 +#define PMIC_ISINK_BREATH0_TOFF_SEL_MASK 0xF +#define PMIC_ISINK_BREATH0_TOFF_SEL_SHIFT 0 +#define PMIC_ISINK_BREATH0_TON_SEL_ADDR MT6353_ISINK0_CON3 +#define PMIC_ISINK_BREATH0_TON_SEL_MASK 0xF +#define PMIC_ISINK_BREATH0_TON_SEL_SHIFT 8 +#define PMIC_ISINK_DIM1_FSEL_ADDR MT6353_ISINK1_CON0 +#define PMIC_ISINK_DIM1_FSEL_MASK 0xFFFF +#define PMIC_ISINK_DIM1_FSEL_SHIFT 0 +#define PMIC_ISINK1_RSV1_ADDR MT6353_ISINK1_CON1 +#define PMIC_ISINK1_RSV1_MASK 0xF +#define PMIC_ISINK1_RSV1_SHIFT 0 +#define PMIC_ISINK1_RSV0_ADDR MT6353_ISINK1_CON1 +#define PMIC_ISINK1_RSV0_MASK 0x7 +#define PMIC_ISINK1_RSV0_SHIFT 4 +#define PMIC_ISINK_DIM1_DUTY_ADDR MT6353_ISINK1_CON1 +#define PMIC_ISINK_DIM1_DUTY_MASK 0x1F +#define PMIC_ISINK_DIM1_DUTY_SHIFT 7 +#define PMIC_ISINK_CH1_STEP_ADDR MT6353_ISINK1_CON1 +#define PMIC_ISINK_CH1_STEP_MASK 0x7 +#define PMIC_ISINK_CH1_STEP_SHIFT 12 +#define PMIC_ISINK_BREATH1_TF2_SEL_ADDR MT6353_ISINK1_CON2 +#define PMIC_ISINK_BREATH1_TF2_SEL_MASK 0xF +#define PMIC_ISINK_BREATH1_TF2_SEL_SHIFT 0 +#define PMIC_ISINK_BREATH1_TF1_SEL_ADDR MT6353_ISINK1_CON2 +#define PMIC_ISINK_BREATH1_TF1_SEL_MASK 0xF +#define PMIC_ISINK_BREATH1_TF1_SEL_SHIFT 4 +#define PMIC_ISINK_BREATH1_TR2_SEL_ADDR MT6353_ISINK1_CON2 +#define PMIC_ISINK_BREATH1_TR2_SEL_MASK 0xF +#define PMIC_ISINK_BREATH1_TR2_SEL_SHIFT 8 +#define PMIC_ISINK_BREATH1_TR1_SEL_ADDR MT6353_ISINK1_CON2 +#define PMIC_ISINK_BREATH1_TR1_SEL_MASK 0xF +#define PMIC_ISINK_BREATH1_TR1_SEL_SHIFT 12 +#define PMIC_ISINK_BREATH1_TOFF_SEL_ADDR MT6353_ISINK1_CON3 +#define PMIC_ISINK_BREATH1_TOFF_SEL_MASK 0xF +#define PMIC_ISINK_BREATH1_TOFF_SEL_SHIFT 0 +#define PMIC_ISINK_BREATH1_TON_SEL_ADDR MT6353_ISINK1_CON3 +#define PMIC_ISINK_BREATH1_TON_SEL_MASK 0xF +#define PMIC_ISINK_BREATH1_TON_SEL_SHIFT 8 +#define PMIC_AD_NI_ISINK3_STATUS_ADDR MT6353_ISINK_ANA1 +#define PMIC_AD_NI_ISINK3_STATUS_MASK 0x1 +#define PMIC_AD_NI_ISINK3_STATUS_SHIFT 0 +#define PMIC_AD_NI_ISINK2_STATUS_ADDR MT6353_ISINK_ANA1 +#define PMIC_AD_NI_ISINK2_STATUS_MASK 0x1 +#define PMIC_AD_NI_ISINK2_STATUS_SHIFT 1 +#define PMIC_AD_NI_ISINK1_STATUS_ADDR MT6353_ISINK_ANA1 +#define PMIC_AD_NI_ISINK1_STATUS_MASK 0x1 +#define PMIC_AD_NI_ISINK1_STATUS_SHIFT 2 +#define PMIC_AD_NI_ISINK0_STATUS_ADDR MT6353_ISINK_ANA1 +#define PMIC_AD_NI_ISINK0_STATUS_MASK 0x1 +#define PMIC_AD_NI_ISINK0_STATUS_SHIFT 3 +#define PMIC_ISINK_PHASE0_DLY_EN_ADDR MT6353_ISINK_PHASE_DLY +#define PMIC_ISINK_PHASE0_DLY_EN_MASK 0x1 +#define PMIC_ISINK_PHASE0_DLY_EN_SHIFT 0 +#define PMIC_ISINK_PHASE1_DLY_EN_ADDR MT6353_ISINK_PHASE_DLY +#define PMIC_ISINK_PHASE1_DLY_EN_MASK 0x1 +#define PMIC_ISINK_PHASE1_DLY_EN_SHIFT 1 +#define PMIC_ISINK_PHASE_DLY_TC_ADDR MT6353_ISINK_PHASE_DLY +#define PMIC_ISINK_PHASE_DLY_TC_MASK 0x3 +#define PMIC_ISINK_PHASE_DLY_TC_SHIFT 4 +#define PMIC_ISINK_CHOP0_SW_ADDR MT6353_ISINK_PHASE_DLY +#define PMIC_ISINK_CHOP0_SW_MASK 0x1 +#define PMIC_ISINK_CHOP0_SW_SHIFT 12 +#define PMIC_ISINK_CHOP1_SW_ADDR MT6353_ISINK_PHASE_DLY +#define PMIC_ISINK_CHOP1_SW_MASK 0x1 +#define PMIC_ISINK_CHOP1_SW_SHIFT 13 +#define PMIC_ISINK_SFSTR1_EN_ADDR MT6353_ISINK_SFSTR +#define PMIC_ISINK_SFSTR1_EN_MASK 0x1 +#define PMIC_ISINK_SFSTR1_EN_SHIFT 8 +#define PMIC_ISINK_SFSTR1_TC_ADDR MT6353_ISINK_SFSTR +#define PMIC_ISINK_SFSTR1_TC_MASK 0x3 +#define PMIC_ISINK_SFSTR1_TC_SHIFT 9 +#define PMIC_ISINK_SFSTR0_EN_ADDR MT6353_ISINK_SFSTR +#define PMIC_ISINK_SFSTR0_EN_MASK 0x1 +#define PMIC_ISINK_SFSTR0_EN_SHIFT 12 +#define PMIC_ISINK_SFSTR0_TC_ADDR MT6353_ISINK_SFSTR +#define PMIC_ISINK_SFSTR0_TC_MASK 0x3 +#define PMIC_ISINK_SFSTR0_TC_SHIFT 13 +#define PMIC_ISINK_CH0_EN_ADDR MT6353_ISINK_EN_CTRL +#define PMIC_ISINK_CH0_EN_MASK 0x1 +#define PMIC_ISINK_CH0_EN_SHIFT 0 +#define PMIC_ISINK_CH1_EN_ADDR MT6353_ISINK_EN_CTRL +#define PMIC_ISINK_CH1_EN_MASK 0x1 +#define PMIC_ISINK_CH1_EN_SHIFT 1 +#define PMIC_ISINK_CHOP0_EN_ADDR MT6353_ISINK_EN_CTRL +#define PMIC_ISINK_CHOP0_EN_MASK 0x1 +#define PMIC_ISINK_CHOP0_EN_SHIFT 4 +#define PMIC_ISINK_CHOP1_EN_ADDR MT6353_ISINK_EN_CTRL +#define PMIC_ISINK_CHOP1_EN_MASK 0x1 +#define PMIC_ISINK_CHOP1_EN_SHIFT 5 +#define PMIC_ISINK_CH0_BIAS_EN_ADDR MT6353_ISINK_EN_CTRL +#define PMIC_ISINK_CH0_BIAS_EN_MASK 0x1 +#define PMIC_ISINK_CH0_BIAS_EN_SHIFT 8 +#define PMIC_ISINK_CH1_BIAS_EN_ADDR MT6353_ISINK_EN_CTRL +#define PMIC_ISINK_CH1_BIAS_EN_MASK 0x1 +#define PMIC_ISINK_CH1_BIAS_EN_SHIFT 9 +#define PMIC_ISINK_RSV_ADDR MT6353_ISINK_MODE_CTRL +#define PMIC_ISINK_RSV_MASK 0x1F +#define PMIC_ISINK_RSV_SHIFT 0 +#define PMIC_ISINK_CH1_MODE_ADDR MT6353_ISINK_MODE_CTRL +#define PMIC_ISINK_CH1_MODE_MASK 0x3 +#define PMIC_ISINK_CH1_MODE_SHIFT 12 +#define PMIC_ISINK_CH0_MODE_ADDR MT6353_ISINK_MODE_CTRL +#define PMIC_ISINK_CH0_MODE_MASK 0x3 +#define PMIC_ISINK_CH0_MODE_SHIFT 14 +#define PMIC_DA_QI_ISINKS_CH3_STEP_ADDR MT6353_ISINK_ANA_CON0 +#define PMIC_DA_QI_ISINKS_CH3_STEP_MASK 0x7 +#define PMIC_DA_QI_ISINKS_CH3_STEP_SHIFT 0 +#define PMIC_DA_QI_ISINKS_CH2_STEP_ADDR MT6353_ISINK_ANA_CON0 +#define PMIC_DA_QI_ISINKS_CH2_STEP_MASK 0x7 +#define PMIC_DA_QI_ISINKS_CH2_STEP_SHIFT 3 +#define PMIC_DA_QI_ISINKS_CH1_STEP_ADDR MT6353_ISINK_ANA_CON0 +#define PMIC_DA_QI_ISINKS_CH1_STEP_MASK 0x7 +#define PMIC_DA_QI_ISINKS_CH1_STEP_SHIFT 6 +#define PMIC_DA_QI_ISINKS_CH0_STEP_ADDR MT6353_ISINK_ANA_CON0 +#define PMIC_DA_QI_ISINKS_CH0_STEP_MASK 0x7 +#define PMIC_DA_QI_ISINKS_CH0_STEP_SHIFT 9 +#define PMIC_ISINK2_RSV1_ADDR MT6353_ISINK2_CON1 +#define PMIC_ISINK2_RSV1_MASK 0xF +#define PMIC_ISINK2_RSV1_SHIFT 0 +#define PMIC_ISINK2_RSV0_ADDR MT6353_ISINK2_CON1 +#define PMIC_ISINK2_RSV0_MASK 0x7 +#define PMIC_ISINK2_RSV0_SHIFT 4 +#define PMIC_ISINK_CH2_STEP_ADDR MT6353_ISINK2_CON1 +#define PMIC_ISINK_CH2_STEP_MASK 0x7 +#define PMIC_ISINK_CH2_STEP_SHIFT 12 +#define PMIC_ISINK3_RSV1_ADDR MT6353_ISINK3_CON1 +#define PMIC_ISINK3_RSV1_MASK 0xF +#define PMIC_ISINK3_RSV1_SHIFT 0 +#define PMIC_ISINK3_RSV0_ADDR MT6353_ISINK3_CON1 +#define PMIC_ISINK3_RSV0_MASK 0x7 +#define PMIC_ISINK3_RSV0_SHIFT 4 +#define PMIC_ISINK_CH3_STEP_ADDR MT6353_ISINK3_CON1 +#define PMIC_ISINK_CH3_STEP_MASK 0x7 +#define PMIC_ISINK_CH3_STEP_SHIFT 12 +#define PMIC_ISINK_CHOP3_SW_ADDR MT6353_ISINK_PHASE_DLY_SMPL +#define PMIC_ISINK_CHOP3_SW_MASK 0x1 +#define PMIC_ISINK_CHOP3_SW_SHIFT 14 +#define PMIC_ISINK_CHOP2_SW_ADDR MT6353_ISINK_PHASE_DLY_SMPL +#define PMIC_ISINK_CHOP2_SW_MASK 0x1 +#define PMIC_ISINK_CHOP2_SW_SHIFT 15 +#define PMIC_ISINK_CH3_EN_ADDR MT6353_ISINK_EN_CTRL_SMPL +#define PMIC_ISINK_CH3_EN_MASK 0x1 +#define PMIC_ISINK_CH3_EN_SHIFT 2 +#define PMIC_ISINK_CH2_EN_ADDR MT6353_ISINK_EN_CTRL_SMPL +#define PMIC_ISINK_CH2_EN_MASK 0x1 +#define PMIC_ISINK_CH2_EN_SHIFT 3 +#define PMIC_ISINK_CHOP3_EN_ADDR MT6353_ISINK_EN_CTRL_SMPL +#define PMIC_ISINK_CHOP3_EN_MASK 0x1 +#define PMIC_ISINK_CHOP3_EN_SHIFT 6 +#define PMIC_ISINK_CHOP2_EN_ADDR MT6353_ISINK_EN_CTRL_SMPL +#define PMIC_ISINK_CHOP2_EN_MASK 0x1 +#define PMIC_ISINK_CHOP2_EN_SHIFT 7 +#define PMIC_ISINK_CH3_BIAS_EN_ADDR MT6353_ISINK_EN_CTRL_SMPL +#define PMIC_ISINK_CH3_BIAS_EN_MASK 0x1 +#define PMIC_ISINK_CH3_BIAS_EN_SHIFT 10 +#define PMIC_ISINK_CH2_BIAS_EN_ADDR MT6353_ISINK_EN_CTRL_SMPL +#define PMIC_ISINK_CH2_BIAS_EN_MASK 0x1 +#define PMIC_ISINK_CH2_BIAS_EN_SHIFT 11 +#define PMIC_CHRIND_DIM_FSEL_ADDR MT6353_CHRIND_CON0 +#define PMIC_CHRIND_DIM_FSEL_MASK 0xFFFF +#define PMIC_CHRIND_DIM_FSEL_SHIFT 0 +#define PMIC_CHRIND_RSV1_ADDR MT6353_CHRIND_CON1 +#define PMIC_CHRIND_RSV1_MASK 0xF +#define PMIC_CHRIND_RSV1_SHIFT 0 +#define PMIC_CHRIND_RSV0_ADDR MT6353_CHRIND_CON1 +#define PMIC_CHRIND_RSV0_MASK 0x7 +#define PMIC_CHRIND_RSV0_SHIFT 4 +#define PMIC_CHRIND_DIM_DUTY_ADDR MT6353_CHRIND_CON1 +#define PMIC_CHRIND_DIM_DUTY_MASK 0x1F +#define PMIC_CHRIND_DIM_DUTY_SHIFT 7 +#define PMIC_CHRIND_STEP_ADDR MT6353_CHRIND_CON1 +#define PMIC_CHRIND_STEP_MASK 0x7 +#define PMIC_CHRIND_STEP_SHIFT 12 +#define PMIC_CHRIND_BREATH_TF2_SEL_ADDR MT6353_CHRIND_CON2 +#define PMIC_CHRIND_BREATH_TF2_SEL_MASK 0xF +#define PMIC_CHRIND_BREATH_TF2_SEL_SHIFT 0 +#define PMIC_CHRIND_BREATH_TF1_SEL_ADDR MT6353_CHRIND_CON2 +#define PMIC_CHRIND_BREATH_TF1_SEL_MASK 0xF +#define PMIC_CHRIND_BREATH_TF1_SEL_SHIFT 4 +#define PMIC_CHRIND_BREATH_TR2_SEL_ADDR MT6353_CHRIND_CON2 +#define PMIC_CHRIND_BREATH_TR2_SEL_MASK 0xF +#define PMIC_CHRIND_BREATH_TR2_SEL_SHIFT 8 +#define PMIC_CHRIND_BREATH_TR1_SEL_ADDR MT6353_CHRIND_CON2 +#define PMIC_CHRIND_BREATH_TR1_SEL_MASK 0xF +#define PMIC_CHRIND_BREATH_TR1_SEL_SHIFT 12 +#define PMIC_CHRIND_BREATH_TOFF_SEL_ADDR MT6353_CHRIND_CON3 +#define PMIC_CHRIND_BREATH_TOFF_SEL_MASK 0xF +#define PMIC_CHRIND_BREATH_TOFF_SEL_SHIFT 0 +#define PMIC_CHRIND_BREATH_TON_SEL_ADDR MT6353_CHRIND_CON3 +#define PMIC_CHRIND_BREATH_TON_SEL_MASK 0xF +#define PMIC_CHRIND_BREATH_TON_SEL_SHIFT 8 +#define PMIC_CHRIND_SFSTR_EN_ADDR MT6353_CHRIND_EN_CTRL +#define PMIC_CHRIND_SFSTR_EN_MASK 0x1 +#define PMIC_CHRIND_SFSTR_EN_SHIFT 0 +#define PMIC_CHRIND_SFSTR_TC_ADDR MT6353_CHRIND_EN_CTRL +#define PMIC_CHRIND_SFSTR_TC_MASK 0x3 +#define PMIC_CHRIND_SFSTR_TC_SHIFT 1 +#define PMIC_CHRIND_EN_SEL_ADDR MT6353_CHRIND_EN_CTRL +#define PMIC_CHRIND_EN_SEL_MASK 0x1 +#define PMIC_CHRIND_EN_SEL_SHIFT 3 +#define PMIC_CHRIND_EN_ADDR MT6353_CHRIND_EN_CTRL +#define PMIC_CHRIND_EN_MASK 0x1 +#define PMIC_CHRIND_EN_SHIFT 4 +#define PMIC_CHRIND_CHOP_EN_ADDR MT6353_CHRIND_EN_CTRL +#define PMIC_CHRIND_CHOP_EN_MASK 0x1 +#define PMIC_CHRIND_CHOP_EN_SHIFT 5 +#define PMIC_CHRIND_MODE_ADDR MT6353_CHRIND_EN_CTRL +#define PMIC_CHRIND_MODE_MASK 0x3 +#define PMIC_CHRIND_MODE_SHIFT 6 +#define PMIC_CHRIND_CHOP_SW_ADDR MT6353_CHRIND_EN_CTRL +#define PMIC_CHRIND_CHOP_SW_MASK 0x1 +#define PMIC_CHRIND_CHOP_SW_SHIFT 8 +#define PMIC_CHRIND_BIAS_EN_ADDR MT6353_CHRIND_EN_CTRL +#define PMIC_CHRIND_BIAS_EN_MASK 0x1 +#define PMIC_CHRIND_BIAS_EN_SHIFT 9 +#define PMIC_RG_SLP_RW_EN_ADDR MT6353_RG_SPI_CON +#define PMIC_RG_SLP_RW_EN_MASK 0x1 +#define PMIC_RG_SLP_RW_EN_SHIFT 0 +#define PMIC_RG_SPI_RSV_ADDR MT6353_RG_SPI_CON +#define PMIC_RG_SPI_RSV_MASK 0x7FFF +#define PMIC_RG_SPI_RSV_SHIFT 1 +#define PMIC_DEW_DIO_EN_ADDR MT6353_DEW_DIO_EN +#define PMIC_DEW_DIO_EN_MASK 0x1 +#define PMIC_DEW_DIO_EN_SHIFT 0 +#define PMIC_DEW_READ_TEST_ADDR MT6353_DEW_READ_TEST +#define PMIC_DEW_READ_TEST_MASK 0xFFFF +#define PMIC_DEW_READ_TEST_SHIFT 0 +#define PMIC_DEW_WRITE_TEST_ADDR MT6353_DEW_WRITE_TEST +#define PMIC_DEW_WRITE_TEST_MASK 0xFFFF +#define PMIC_DEW_WRITE_TEST_SHIFT 0 +#define PMIC_DEW_CRC_SWRST_ADDR MT6353_DEW_CRC_SWRST +#define PMIC_DEW_CRC_SWRST_MASK 0x1 +#define PMIC_DEW_CRC_SWRST_SHIFT 0 +#define PMIC_DEW_CRC_EN_ADDR MT6353_DEW_CRC_EN +#define PMIC_DEW_CRC_EN_MASK 0x1 +#define PMIC_DEW_CRC_EN_SHIFT 0 +#define PMIC_DEW_CRC_VAL_ADDR MT6353_DEW_CRC_VAL +#define PMIC_DEW_CRC_VAL_MASK 0xFF +#define PMIC_DEW_CRC_VAL_SHIFT 0 +#define PMIC_DEW_DBG_MON_SEL_ADDR MT6353_DEW_DBG_MON_SEL +#define PMIC_DEW_DBG_MON_SEL_MASK 0xF +#define PMIC_DEW_DBG_MON_SEL_SHIFT 0 +#define PMIC_DEW_CIPHER_KEY_SEL_ADDR MT6353_DEW_CIPHER_KEY_SEL +#define PMIC_DEW_CIPHER_KEY_SEL_MASK 0x3 +#define PMIC_DEW_CIPHER_KEY_SEL_SHIFT 0 +#define PMIC_DEW_CIPHER_IV_SEL_ADDR MT6353_DEW_CIPHER_IV_SEL +#define PMIC_DEW_CIPHER_IV_SEL_MASK 0x3 +#define PMIC_DEW_CIPHER_IV_SEL_SHIFT 0 +#define PMIC_DEW_CIPHER_EN_ADDR MT6353_DEW_CIPHER_EN +#define PMIC_DEW_CIPHER_EN_MASK 0x1 +#define PMIC_DEW_CIPHER_EN_SHIFT 0 +#define PMIC_DEW_CIPHER_RDY_ADDR MT6353_DEW_CIPHER_RDY +#define PMIC_DEW_CIPHER_RDY_MASK 0x1 +#define PMIC_DEW_CIPHER_RDY_SHIFT 0 +#define PMIC_DEW_CIPHER_MODE_ADDR MT6353_DEW_CIPHER_MODE +#define PMIC_DEW_CIPHER_MODE_MASK 0x1 +#define PMIC_DEW_CIPHER_MODE_SHIFT 0 +#define PMIC_DEW_CIPHER_SWRST_ADDR MT6353_DEW_CIPHER_SWRST +#define PMIC_DEW_CIPHER_SWRST_MASK 0x1 +#define PMIC_DEW_CIPHER_SWRST_SHIFT 0 +#define PMIC_DEW_RDDMY_NO_ADDR MT6353_DEW_RDDMY_NO +#define PMIC_DEW_RDDMY_NO_MASK 0xF +#define PMIC_DEW_RDDMY_NO_SHIFT 0 +#define PMIC_INT_TYPE_CON0_ADDR MT6353_INT_TYPE_CON0 +#define PMIC_INT_TYPE_CON0_MASK 0xFFFF +#define PMIC_INT_TYPE_CON0_SHIFT 0 +#define PMIC_INT_TYPE_CON0_SET_ADDR MT6353_INT_TYPE_CON0_SET +#define PMIC_INT_TYPE_CON0_SET_MASK 0xFFFF +#define PMIC_INT_TYPE_CON0_SET_SHIFT 0 +#define PMIC_INT_TYPE_CON0_CLR_ADDR MT6353_INT_TYPE_CON0_CLR +#define PMIC_INT_TYPE_CON0_CLR_MASK 0xFFFF +#define PMIC_INT_TYPE_CON0_CLR_SHIFT 0 +#define PMIC_INT_TYPE_CON1_ADDR MT6353_INT_TYPE_CON1 +#define PMIC_INT_TYPE_CON1_MASK 0xFFFF +#define PMIC_INT_TYPE_CON1_SHIFT 0 +#define PMIC_INT_TYPE_CON1_SET_ADDR MT6353_INT_TYPE_CON1_SET +#define PMIC_INT_TYPE_CON1_SET_MASK 0xFFFF +#define PMIC_INT_TYPE_CON1_SET_SHIFT 0 +#define PMIC_INT_TYPE_CON1_CLR_ADDR MT6353_INT_TYPE_CON1_CLR +#define PMIC_INT_TYPE_CON1_CLR_MASK 0xFFFF +#define PMIC_INT_TYPE_CON1_CLR_SHIFT 0 +#define PMIC_INT_TYPE_CON2_ADDR MT6353_INT_TYPE_CON2 +#define PMIC_INT_TYPE_CON2_MASK 0xFFFF +#define PMIC_INT_TYPE_CON2_SHIFT 0 +#define PMIC_INT_TYPE_CON2_SET_ADDR MT6353_INT_TYPE_CON2_SET +#define PMIC_INT_TYPE_CON2_SET_MASK 0xFFFF +#define PMIC_INT_TYPE_CON2_SET_SHIFT 0 +#define PMIC_INT_TYPE_CON2_CLR_ADDR MT6353_INT_TYPE_CON2_CLR +#define PMIC_INT_TYPE_CON2_CLR_MASK 0xFFFF +#define PMIC_INT_TYPE_CON2_CLR_SHIFT 0 +#define PMIC_INT_TYPE_CON3_ADDR MT6353_INT_TYPE_CON3 +#define PMIC_INT_TYPE_CON3_MASK 0x1F +#define PMIC_INT_TYPE_CON3_SHIFT 0 +#define PMIC_INT_TYPE_CON3_SET_ADDR MT6353_INT_TYPE_CON3_SET +#define PMIC_INT_TYPE_CON3_SET_MASK 0x1F +#define PMIC_INT_TYPE_CON3_SET_SHIFT 0 +#define PMIC_INT_TYPE_CON3_CLR_ADDR MT6353_INT_TYPE_CON3_CLR +#define PMIC_INT_TYPE_CON3_CLR_MASK 0x1F +#define PMIC_INT_TYPE_CON3_CLR_SHIFT 0 +#define PMIC_CPU_INT_STA_ADDR MT6353_INT_STA +#define PMIC_CPU_INT_STA_MASK 0x1 +#define PMIC_CPU_INT_STA_SHIFT 0 +#define PMIC_MD32_INT_STA_ADDR MT6353_INT_STA +#define PMIC_MD32_INT_STA_MASK 0x1 +#define PMIC_MD32_INT_STA_SHIFT 1 +#define PMIC_BUCK_LDO_FT_TESTMODE_EN_ADDR MT6353_BUCK_ALL_CON0 +#define PMIC_BUCK_LDO_FT_TESTMODE_EN_MASK 0x1 +#define PMIC_BUCK_LDO_FT_TESTMODE_EN_SHIFT 0 +#define PMIC_EFUSE_VOSEL_LIMIT_ADDR MT6353_BUCK_ALL_CON0 +#define PMIC_EFUSE_VOSEL_LIMIT_MASK 0x1 +#define PMIC_EFUSE_VOSEL_LIMIT_SHIFT 1 +#define PMIC_EFUSE_OC_EN_SEL_ADDR MT6353_BUCK_ALL_CON0 +#define PMIC_EFUSE_OC_EN_SEL_MASK 0x1 +#define PMIC_EFUSE_OC_EN_SEL_SHIFT 2 +#define PMIC_EFUSE_OC_SDN_EN_ADDR MT6353_BUCK_ALL_CON0 +#define PMIC_EFUSE_OC_SDN_EN_MASK 0x1 +#define PMIC_EFUSE_OC_SDN_EN_SHIFT 3 +#define PMIC_BUCK_FOR_LDO_OSC_SEL_ADDR MT6353_BUCK_ALL_CON0 +#define PMIC_BUCK_FOR_LDO_OSC_SEL_MASK 0x7 +#define PMIC_BUCK_FOR_LDO_OSC_SEL_SHIFT 4 +#define PMIC_BUCK_ALL_CON0_RSV0_ADDR MT6353_BUCK_ALL_CON0 +#define PMIC_BUCK_ALL_CON0_RSV0_MASK 0xFF +#define PMIC_BUCK_ALL_CON0_RSV0_SHIFT 8 +#define PMIC_BUCK_BUCK_RSV_ADDR MT6353_BUCK_ALL_CON1 +#define PMIC_BUCK_BUCK_RSV_MASK 0xFFFF +#define PMIC_BUCK_BUCK_RSV_SHIFT 0 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_PROT_ADDR MT6353_BUCK_ALL_CON2 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_PROT_MASK 0x1 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_PROT_SHIFT 0 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_PROT_EN_ADDR MT6353_BUCK_ALL_CON2 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_PROT_EN_MASK 0x1 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_PROT_EN_SHIFT 1 +#define PMIC_BUCK_ALL_CON2_RSV0_ADDR MT6353_BUCK_ALL_CON2 +#define PMIC_BUCK_ALL_CON2_RSV0_MASK 0x1F +#define PMIC_BUCK_ALL_CON2_RSV0_SHIFT 11 +#define PMIC_BUCK_VSLEEP_SRC0_ADDR MT6353_BUCK_ALL_CON3 +#define PMIC_BUCK_VSLEEP_SRC0_MASK 0x1FF +#define PMIC_BUCK_VSLEEP_SRC0_SHIFT 0 +#define PMIC_BUCK_VSLEEP_SRC1_ADDR MT6353_BUCK_ALL_CON3 +#define PMIC_BUCK_VSLEEP_SRC1_MASK 0xF +#define PMIC_BUCK_VSLEEP_SRC1_SHIFT 12 +#define PMIC_BUCK_R2R_SRC0_ADDR MT6353_BUCK_ALL_CON4 +#define PMIC_BUCK_R2R_SRC0_MASK 0x1FF +#define PMIC_BUCK_R2R_SRC0_SHIFT 0 +#define PMIC_BUCK_R2R_SRC1_ADDR MT6353_BUCK_ALL_CON4 +#define PMIC_BUCK_R2R_SRC1_MASK 0xF +#define PMIC_BUCK_R2R_SRC1_SHIFT 12 +#define PMIC_BUCK_BUCK_OSC_SEL_SRC0_ADDR MT6353_BUCK_ALL_CON5 +#define PMIC_BUCK_BUCK_OSC_SEL_SRC0_MASK 0x1FF +#define PMIC_BUCK_BUCK_OSC_SEL_SRC0_SHIFT 0 +#define PMIC_BUCK_SRCLKEN_DLY_SRC1_ADDR MT6353_BUCK_ALL_CON5 +#define PMIC_BUCK_SRCLKEN_DLY_SRC1_MASK 0xF +#define PMIC_BUCK_SRCLKEN_DLY_SRC1_SHIFT 12 +#define PMIC_BUCK_VPA_VOSEL_DLC011_ADDR MT6353_BUCK_DLC_VPA_CON0 +#define PMIC_BUCK_VPA_VOSEL_DLC011_MASK 0x3F +#define PMIC_BUCK_VPA_VOSEL_DLC011_SHIFT 0 +#define PMIC_BUCK_VPA_VOSEL_DLC111_ADDR MT6353_BUCK_DLC_VPA_CON0 +#define PMIC_BUCK_VPA_VOSEL_DLC111_MASK 0x3F +#define PMIC_BUCK_VPA_VOSEL_DLC111_SHIFT 8 +#define PMIC_BUCK_VPA_DLC_MAP_EN_ADDR MT6353_BUCK_DLC_VPA_CON1 +#define PMIC_BUCK_VPA_DLC_MAP_EN_MASK 0x1 +#define PMIC_BUCK_VPA_DLC_MAP_EN_SHIFT 0 +#define PMIC_BUCK_VPA_VOSEL_DLC001_ADDR MT6353_BUCK_DLC_VPA_CON1 +#define PMIC_BUCK_VPA_VOSEL_DLC001_MASK 0x3F +#define PMIC_BUCK_VPA_VOSEL_DLC001_SHIFT 8 +#define PMIC_BUCK_VPA_DLC_ADDR MT6353_BUCK_DLC_VPA_CON2 +#define PMIC_BUCK_VPA_DLC_MASK 0x7 +#define PMIC_BUCK_VPA_DLC_SHIFT 0 +#define PMIC_DA_NI_VPA_DLC_ADDR MT6353_BUCK_DLC_VPA_CON2 +#define PMIC_DA_NI_VPA_DLC_MASK 0x7 +#define PMIC_DA_NI_VPA_DLC_SHIFT 12 +#define PMIC_BUCK_VSRAM_PROC_TRACK_SLEEP_CTRL_ADDR MT6353_BUCK_TRACKING_CON0 +#define PMIC_BUCK_VSRAM_PROC_TRACK_SLEEP_CTRL_MASK 0x1 +#define PMIC_BUCK_VSRAM_PROC_TRACK_SLEEP_CTRL_SHIFT 0 +#define PMIC_BUCK_VSRAM_PROC_TRACK_ON_CTRL_ADDR MT6353_BUCK_TRACKING_CON0 +#define PMIC_BUCK_VSRAM_PROC_TRACK_ON_CTRL_MASK 0x1 +#define PMIC_BUCK_VSRAM_PROC_TRACK_ON_CTRL_SHIFT 1 +#define PMIC_BUCK_VPROC_TRACK_ON_CTRL_ADDR MT6353_BUCK_TRACKING_CON0 +#define PMIC_BUCK_VPROC_TRACK_ON_CTRL_MASK 0x1 +#define PMIC_BUCK_VPROC_TRACK_ON_CTRL_SHIFT 2 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_DELTA_ADDR MT6353_BUCK_TRACKING_CON1 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_DELTA_MASK 0x7F +#define PMIC_BUCK_VSRAM_PROC_VOSEL_DELTA_SHIFT 0 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_OFFSET_ADDR MT6353_BUCK_TRACKING_CON1 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_OFFSET_MASK 0x7F +#define PMIC_BUCK_VSRAM_PROC_VOSEL_OFFSET_SHIFT 8 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_ON_LB_ADDR MT6353_BUCK_TRACKING_CON2 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_ON_LB_MASK 0x7F +#define PMIC_BUCK_VSRAM_PROC_VOSEL_ON_LB_SHIFT 0 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_ON_HB_ADDR MT6353_BUCK_TRACKING_CON2 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_ON_HB_MASK 0x7F +#define PMIC_BUCK_VSRAM_PROC_VOSEL_ON_HB_SHIFT 8 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_LB_ADDR MT6353_BUCK_TRACKING_CON3 +#define PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_LB_MASK 0x7F +#define PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_LB_SHIFT 0 +#define PMIC_AD_QI_VCORE_OC_STATUS_ADDR MT6353_BUCK_ANA_MON_CON0 +#define PMIC_AD_QI_VCORE_OC_STATUS_MASK 0x1 +#define PMIC_AD_QI_VCORE_OC_STATUS_SHIFT 0 +#define PMIC_AD_QI_VPROC_OC_STATUS_ADDR MT6353_BUCK_ANA_MON_CON0 +#define PMIC_AD_QI_VPROC_OC_STATUS_MASK 0x1 +#define PMIC_AD_QI_VPROC_OC_STATUS_SHIFT 1 +#define PMIC_AD_QI_VS1_OC_STATUS_ADDR MT6353_BUCK_ANA_MON_CON0 +#define PMIC_AD_QI_VS1_OC_STATUS_MASK 0x1 +#define PMIC_AD_QI_VS1_OC_STATUS_SHIFT 2 +#define PMIC_AD_QI_VPA_OC_STATUS_ADDR MT6353_BUCK_ANA_MON_CON0 +#define PMIC_AD_QI_VPA_OC_STATUS_MASK 0x1 +#define PMIC_AD_QI_VPA_OC_STATUS_SHIFT 3 +#define PMIC_BUCK_ANA_STATUS_ADDR MT6353_BUCK_ANA_MON_CON0 +#define PMIC_BUCK_ANA_STATUS_MASK 0xF +#define PMIC_BUCK_ANA_STATUS_SHIFT 12 +#define PMIC_AD_QI_VCORE_DIG_MON_ADDR MT6353_BUCK_ANA_MON_CON1 +#define PMIC_AD_QI_VCORE_DIG_MON_MASK 0xF +#define PMIC_AD_QI_VCORE_DIG_MON_SHIFT 0 +#define PMIC_AD_QI_VPROC_DIG_MON_ADDR MT6353_BUCK_ANA_MON_CON1 +#define PMIC_AD_QI_VPROC_DIG_MON_MASK 0xF +#define PMIC_AD_QI_VPROC_DIG_MON_SHIFT 4 +#define PMIC_AD_QI_VS1_DIG_MON_ADDR MT6353_BUCK_ANA_MON_CON1 +#define PMIC_AD_QI_VS1_DIG_MON_MASK 0xF +#define PMIC_AD_QI_VS1_DIG_MON_SHIFT 8 +#define PMIC_BUCK_VCORE_OC_STATUS_ADDR MT6353_BUCK_OC_CON0 +#define PMIC_BUCK_VCORE_OC_STATUS_MASK 0x1 +#define PMIC_BUCK_VCORE_OC_STATUS_SHIFT 0 +#define PMIC_BUCK_VCORE2_OC_STATUS_ADDR MT6353_BUCK_OC_CON0 +#define PMIC_BUCK_VCORE2_OC_STATUS_MASK 0x1 +#define PMIC_BUCK_VCORE2_OC_STATUS_SHIFT 1 +#define PMIC_BUCK_VPROC_OC_STATUS_ADDR MT6353_BUCK_OC_CON0 +#define PMIC_BUCK_VPROC_OC_STATUS_MASK 0x1 +#define PMIC_BUCK_VPROC_OC_STATUS_SHIFT 2 +#define PMIC_BUCK_VS1_OC_STATUS_ADDR MT6353_BUCK_OC_CON0 +#define PMIC_BUCK_VS1_OC_STATUS_MASK 0x1 +#define PMIC_BUCK_VS1_OC_STATUS_SHIFT 3 +#define PMIC_BUCK_VPA_OC_STATUS_ADDR MT6353_BUCK_OC_CON0 +#define PMIC_BUCK_VPA_OC_STATUS_MASK 0x1 +#define PMIC_BUCK_VPA_OC_STATUS_SHIFT 4 +#define PMIC_BUCK_VCORE_OC_INT_EN_ADDR MT6353_BUCK_OC_CON1 +#define PMIC_BUCK_VCORE_OC_INT_EN_MASK 0x1 +#define PMIC_BUCK_VCORE_OC_INT_EN_SHIFT 0 +#define PMIC_BUCK_VCORE2_OC_INT_EN_ADDR MT6353_BUCK_OC_CON1 +#define PMIC_BUCK_VCORE2_OC_INT_EN_MASK 0x1 +#define PMIC_BUCK_VCORE2_OC_INT_EN_SHIFT 1 +#define PMIC_BUCK_VPROC_OC_INT_EN_ADDR MT6353_BUCK_OC_CON1 +#define PMIC_BUCK_VPROC_OC_INT_EN_MASK 0x1 +#define PMIC_BUCK_VPROC_OC_INT_EN_SHIFT 2 +#define PMIC_BUCK_VS1_OC_INT_EN_ADDR MT6353_BUCK_OC_CON1 +#define PMIC_BUCK_VS1_OC_INT_EN_MASK 0x1 +#define PMIC_BUCK_VS1_OC_INT_EN_SHIFT 3 +#define PMIC_BUCK_VPA_OC_INT_EN_ADDR MT6353_BUCK_OC_CON1 +#define PMIC_BUCK_VPA_OC_INT_EN_MASK 0x1 +#define PMIC_BUCK_VPA_OC_INT_EN_SHIFT 4 +#define PMIC_BUCK_VCORE_EN_OC_SDN_SEL_ADDR MT6353_BUCK_OC_CON2 +#define PMIC_BUCK_VCORE_EN_OC_SDN_SEL_MASK 0x1 +#define PMIC_BUCK_VCORE_EN_OC_SDN_SEL_SHIFT 0 +#define PMIC_BUCK_VCORE2_EN_OC_SDN_SEL_ADDR MT6353_BUCK_OC_CON2 +#define PMIC_BUCK_VCORE2_EN_OC_SDN_SEL_MASK 0x1 +#define PMIC_BUCK_VCORE2_EN_OC_SDN_SEL_SHIFT 1 +#define PMIC_BUCK_VPROC_EN_OC_SDN_SEL_ADDR MT6353_BUCK_OC_CON2 +#define PMIC_BUCK_VPROC_EN_OC_SDN_SEL_MASK 0x1 +#define PMIC_BUCK_VPROC_EN_OC_SDN_SEL_SHIFT 2 +#define PMIC_BUCK_VS1_EN_OC_SDN_SEL_ADDR MT6353_BUCK_OC_CON2 +#define PMIC_BUCK_VS1_EN_OC_SDN_SEL_MASK 0x1 +#define PMIC_BUCK_VS1_EN_OC_SDN_SEL_SHIFT 3 +#define PMIC_BUCK_VPA_EN_OC_SDN_SEL_ADDR MT6353_BUCK_OC_CON2 +#define PMIC_BUCK_VPA_EN_OC_SDN_SEL_MASK 0x1 +#define PMIC_BUCK_VPA_EN_OC_SDN_SEL_SHIFT 4 +#define PMIC_BUCK_VCORE_OC_FLAG_CLR_ADDR MT6353_BUCK_OC_CON3 +#define PMIC_BUCK_VCORE_OC_FLAG_CLR_MASK 0x1 +#define PMIC_BUCK_VCORE_OC_FLAG_CLR_SHIFT 0 +#define PMIC_BUCK_VCORE2_OC_FLAG_CLR_ADDR MT6353_BUCK_OC_CON3 +#define PMIC_BUCK_VCORE2_OC_FLAG_CLR_MASK 0x1 +#define PMIC_BUCK_VCORE2_OC_FLAG_CLR_SHIFT 1 +#define PMIC_BUCK_VPROC_OC_FLAG_CLR_ADDR MT6353_BUCK_OC_CON3 +#define PMIC_BUCK_VPROC_OC_FLAG_CLR_MASK 0x1 +#define PMIC_BUCK_VPROC_OC_FLAG_CLR_SHIFT 2 +#define PMIC_BUCK_VS1_OC_FLAG_CLR_ADDR MT6353_BUCK_OC_CON3 +#define PMIC_BUCK_VS1_OC_FLAG_CLR_MASK 0x1 +#define PMIC_BUCK_VS1_OC_FLAG_CLR_SHIFT 3 +#define PMIC_BUCK_VPA_OC_FLAG_CLR_ADDR MT6353_BUCK_OC_CON3 +#define PMIC_BUCK_VPA_OC_FLAG_CLR_MASK 0x1 +#define PMIC_BUCK_VPA_OC_FLAG_CLR_SHIFT 4 +#define PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_ADDR MT6353_BUCK_OC_CON4 +#define PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_MASK 0x1 +#define PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_SHIFT 0 +#define PMIC_BUCK_VCORE2_OC_FLAG_CLR_SEL_ADDR MT6353_BUCK_OC_CON4 +#define PMIC_BUCK_VCORE2_OC_FLAG_CLR_SEL_MASK 0x1 +#define PMIC_BUCK_VCORE2_OC_FLAG_CLR_SEL_SHIFT 1 +#define PMIC_BUCK_VPROC_OC_FLAG_CLR_SEL_ADDR MT6353_BUCK_OC_CON4 +#define PMIC_BUCK_VPROC_OC_FLAG_CLR_SEL_MASK 0x1 +#define PMIC_BUCK_VPROC_OC_FLAG_CLR_SEL_SHIFT 2 +#define PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_ADDR MT6353_BUCK_OC_CON4 +#define PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_MASK 0x1 +#define PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_SHIFT 3 +#define PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_ADDR MT6353_BUCK_OC_CON4 +#define PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_MASK 0x1 +#define PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_SHIFT 4 +#define PMIC_BUCK_VCORE_OC_DEG_EN_ADDR MT6353_BUCK_OC_VCORE_CON0 +#define PMIC_BUCK_VCORE_OC_DEG_EN_MASK 0x1 +#define PMIC_BUCK_VCORE_OC_DEG_EN_SHIFT 1 +#define PMIC_BUCK_VCORE_OC_WND_ADDR MT6353_BUCK_OC_VCORE_CON0 +#define PMIC_BUCK_VCORE_OC_WND_MASK 0x3 +#define PMIC_BUCK_VCORE_OC_WND_SHIFT 2 +#define PMIC_BUCK_VCORE_OC_THD_ADDR MT6353_BUCK_OC_VCORE_CON0 +#define PMIC_BUCK_VCORE_OC_THD_MASK 0x3 +#define PMIC_BUCK_VCORE_OC_THD_SHIFT 6 +#define PMIC_BUCK_VCORE2_OC_DEG_EN_ADDR MT6353_BUCK_OC_VCORE2_CON0 +#define PMIC_BUCK_VCORE2_OC_DEG_EN_MASK 0x1 +#define PMIC_BUCK_VCORE2_OC_DEG_EN_SHIFT 1 +#define PMIC_BUCK_VCORE2_OC_WND_ADDR MT6353_BUCK_OC_VCORE2_CON0 +#define PMIC_BUCK_VCORE2_OC_WND_MASK 0x3 +#define PMIC_BUCK_VCORE2_OC_WND_SHIFT 2 +#define PMIC_BUCK_VCORE2_OC_THD_ADDR MT6353_BUCK_OC_VCORE2_CON0 +#define PMIC_BUCK_VCORE2_OC_THD_MASK 0x3 +#define PMIC_BUCK_VCORE2_OC_THD_SHIFT 6 +#define PMIC_BUCK_VPROC_OC_DEG_EN_ADDR MT6353_BUCK_OC_VPROC_CON0 +#define PMIC_BUCK_VPROC_OC_DEG_EN_MASK 0x1 +#define PMIC_BUCK_VPROC_OC_DEG_EN_SHIFT 1 +#define PMIC_BUCK_VPROC_OC_WND_ADDR MT6353_BUCK_OC_VPROC_CON0 +#define PMIC_BUCK_VPROC_OC_WND_MASK 0x3 +#define PMIC_BUCK_VPROC_OC_WND_SHIFT 2 +#define PMIC_BUCK_VPROC_OC_THD_ADDR MT6353_BUCK_OC_VPROC_CON0 +#define PMIC_BUCK_VPROC_OC_THD_MASK 0x3 +#define PMIC_BUCK_VPROC_OC_THD_SHIFT 6 +#define PMIC_BUCK_VS1_OC_DEG_EN_ADDR MT6353_BUCK_OC_VS1_CON0 +#define PMIC_BUCK_VS1_OC_DEG_EN_MASK 0x1 +#define PMIC_BUCK_VS1_OC_DEG_EN_SHIFT 1 +#define PMIC_BUCK_VS1_OC_WND_ADDR MT6353_BUCK_OC_VS1_CON0 +#define PMIC_BUCK_VS1_OC_WND_MASK 0x3 +#define PMIC_BUCK_VS1_OC_WND_SHIFT 2 +#define PMIC_BUCK_VS1_OC_THD_ADDR MT6353_BUCK_OC_VS1_CON0 +#define PMIC_BUCK_VS1_OC_THD_MASK 0x3 +#define PMIC_BUCK_VS1_OC_THD_SHIFT 6 +#define PMIC_BUCK_VPA_OC_DEG_EN_ADDR MT6353_BUCK_OC_VPA_CON0 +#define PMIC_BUCK_VPA_OC_DEG_EN_MASK 0x1 +#define PMIC_BUCK_VPA_OC_DEG_EN_SHIFT 1 +#define PMIC_BUCK_VPA_OC_WND_ADDR MT6353_BUCK_OC_VPA_CON0 +#define PMIC_BUCK_VPA_OC_WND_MASK 0x3 +#define PMIC_BUCK_VPA_OC_WND_SHIFT 2 +#define PMIC_BUCK_VPA_OC_THD_ADDR MT6353_BUCK_OC_VPA_CON0 +#define PMIC_BUCK_VPA_OC_THD_MASK 0x3 +#define PMIC_BUCK_VPA_OC_THD_SHIFT 6 +#define PMIC_RG_SMPS_TESTMODE_B_ADDR MT6353_SMPS_TOP_ANA_CON0 +#define PMIC_RG_SMPS_TESTMODE_B_MASK 0x1FF +#define PMIC_RG_SMPS_TESTMODE_B_SHIFT 0 +#define PMIC_RG_VSRAM_PROC_TRIMH_ADDR MT6353_SMPS_TOP_ANA_CON0 +#define PMIC_RG_VSRAM_PROC_TRIMH_MASK 0x1F +#define PMIC_RG_VSRAM_PROC_TRIMH_SHIFT 9 +#define PMIC_RG_VSRAM_PROC_TRIML_ADDR MT6353_SMPS_TOP_ANA_CON1 +#define PMIC_RG_VSRAM_PROC_TRIML_MASK 0x1F +#define PMIC_RG_VSRAM_PROC_TRIML_SHIFT 0 +#define PMIC_RG_VPROC_TRIMH_ADDR MT6353_SMPS_TOP_ANA_CON1 +#define PMIC_RG_VPROC_TRIMH_MASK 0x1F +#define PMIC_RG_VPROC_TRIMH_SHIFT 5 +#define PMIC_RG_VPROC_TRIML_ADDR MT6353_SMPS_TOP_ANA_CON1 +#define PMIC_RG_VPROC_TRIML_MASK 0x1F +#define PMIC_RG_VPROC_TRIML_SHIFT 10 +#define PMIC_RG_VCORE_TRIMH_ADDR MT6353_SMPS_TOP_ANA_CON2 +#define PMIC_RG_VCORE_TRIMH_MASK 0x1F +#define PMIC_RG_VCORE_TRIMH_SHIFT 0 +#define PMIC_RG_VCORE_TRIML_ADDR MT6353_SMPS_TOP_ANA_CON2 +#define PMIC_RG_VCORE_TRIML_MASK 0x1F +#define PMIC_RG_VCORE_TRIML_SHIFT 5 +#define PMIC_RG_VCORE2_TRIMH_ADDR MT6353_SMPS_TOP_ANA_CON2 +#define PMIC_RG_VCORE2_TRIMH_MASK 0x1F +#define PMIC_RG_VCORE2_TRIMH_SHIFT 10 +#define PMIC_RG_VCORE2_TRIML_ADDR MT6353_SMPS_TOP_ANA_CON3 +#define PMIC_RG_VCORE2_TRIML_MASK 0x1F +#define PMIC_RG_VCORE2_TRIML_SHIFT 0 +#define PMIC_RG_VS1_TRIMH_ADDR MT6353_SMPS_TOP_ANA_CON3 +#define PMIC_RG_VS1_TRIMH_MASK 0xF +#define PMIC_RG_VS1_TRIMH_SHIFT 5 +#define PMIC_RG_VS1_TRIML_ADDR MT6353_SMPS_TOP_ANA_CON3 +#define PMIC_RG_VS1_TRIML_MASK 0xF +#define PMIC_RG_VS1_TRIML_SHIFT 9 +#define PMIC_RG_VPA_TRIMH_ADDR MT6353_SMPS_TOP_ANA_CON4 +#define PMIC_RG_VPA_TRIMH_MASK 0x1F +#define PMIC_RG_VPA_TRIMH_SHIFT 0 +#define PMIC_RG_VPA_TRIML_ADDR MT6353_SMPS_TOP_ANA_CON4 +#define PMIC_RG_VPA_TRIML_MASK 0x1F +#define PMIC_RG_VPA_TRIML_SHIFT 5 +#define PMIC_RG_VPA_TRIM_REF_ADDR MT6353_SMPS_TOP_ANA_CON4 +#define PMIC_RG_VPA_TRIM_REF_MASK 0x1F +#define PMIC_RG_VPA_TRIM_REF_SHIFT 10 +#define PMIC_RG_VSRAM_PROC_VSLEEP_ADDR MT6353_SMPS_TOP_ANA_CON5 +#define PMIC_RG_VSRAM_PROC_VSLEEP_MASK 0x7 +#define PMIC_RG_VSRAM_PROC_VSLEEP_SHIFT 0 +#define PMIC_RG_VPROC_VSLEEP_ADDR MT6353_SMPS_TOP_ANA_CON5 +#define PMIC_RG_VPROC_VSLEEP_MASK 0x7 +#define PMIC_RG_VPROC_VSLEEP_SHIFT 3 +#define PMIC_RG_VCORE_VSLEEP_ADDR MT6353_SMPS_TOP_ANA_CON5 +#define PMIC_RG_VCORE_VSLEEP_MASK 0x7 +#define PMIC_RG_VCORE_VSLEEP_SHIFT 6 +#define PMIC_RG_VCORE2_VSLEEP_ADDR MT6353_SMPS_TOP_ANA_CON5 +#define PMIC_RG_VCORE2_VSLEEP_MASK 0x7 +#define PMIC_RG_VCORE2_VSLEEP_SHIFT 9 +#define PMIC_RG_VPA_BURSTH_ADDR MT6353_SMPS_TOP_ANA_CON5 +#define PMIC_RG_VPA_BURSTH_MASK 0x3 +#define PMIC_RG_VPA_BURSTH_SHIFT 12 +#define PMIC_RG_VPA_BURSTL_ADDR MT6353_SMPS_TOP_ANA_CON5 +#define PMIC_RG_VPA_BURSTL_MASK 0x3 +#define PMIC_RG_VPA_BURSTL_SHIFT 14 +#define PMIC_RG_DMY100MA_EN_ADDR MT6353_SMPS_TOP_ANA_CON6 +#define PMIC_RG_DMY100MA_EN_MASK 0x1 +#define PMIC_RG_DMY100MA_EN_SHIFT 0 +#define PMIC_RG_DMY100MA_SEL_ADDR MT6353_SMPS_TOP_ANA_CON6 +#define PMIC_RG_DMY100MA_SEL_MASK 0x3 +#define PMIC_RG_DMY100MA_SEL_SHIFT 1 +#define PMIC_RG_VSRAM_PROC_VSLEEP_VOLTAGE_ADDR MT6353_SMPS_TOP_ANA_CON6 +#define PMIC_RG_VSRAM_PROC_VSLEEP_VOLTAGE_MASK 0x3 +#define PMIC_RG_VSRAM_PROC_VSLEEP_VOLTAGE_SHIFT 3 +#define PMIC_RG_VPROC_VSLEEP_VOLTAGE_ADDR MT6353_SMPS_TOP_ANA_CON6 +#define PMIC_RG_VPROC_VSLEEP_VOLTAGE_MASK 0x3 +#define PMIC_RG_VPROC_VSLEEP_VOLTAGE_SHIFT 5 +#define PMIC_RG_VCORE_VSLEEP_VOLTAGE_ADDR MT6353_SMPS_TOP_ANA_CON6 +#define PMIC_RG_VCORE_VSLEEP_VOLTAGE_MASK 0x3 +#define PMIC_RG_VCORE_VSLEEP_VOLTAGE_SHIFT 7 +#define PMIC_RG_VCORE2_VSLEEP_VOLTAGE_ADDR MT6353_SMPS_TOP_ANA_CON6 +#define PMIC_RG_VCORE2_VSLEEP_VOLTAGE_MASK 0x3 +#define PMIC_RG_VCORE2_VSLEEP_VOLTAGE_SHIFT 9 +#define PMIC_RG_VPA_RZSEL_ADDR MT6353_VPA_ANA_CON0 +#define PMIC_RG_VPA_RZSEL_MASK 0x3 +#define PMIC_RG_VPA_RZSEL_SHIFT 0 +#define PMIC_RG_VPA_CC_ADDR MT6353_VPA_ANA_CON0 +#define PMIC_RG_VPA_CC_MASK 0x3 +#define PMIC_RG_VPA_CC_SHIFT 2 +#define PMIC_RG_VPA_CSR_ADDR MT6353_VPA_ANA_CON0 +#define PMIC_RG_VPA_CSR_MASK 0x3 +#define PMIC_RG_VPA_CSR_SHIFT 4 +#define PMIC_RG_VPA_CSMIR_ADDR MT6353_VPA_ANA_CON0 +#define PMIC_RG_VPA_CSMIR_MASK 0x3 +#define PMIC_RG_VPA_CSMIR_SHIFT 6 +#define PMIC_RG_VPA_CSL_ADDR MT6353_VPA_ANA_CON0 +#define PMIC_RG_VPA_CSL_MASK 0x3 +#define PMIC_RG_VPA_CSL_SHIFT 8 +#define PMIC_RG_VPA_SLP_ADDR MT6353_VPA_ANA_CON0 +#define PMIC_RG_VPA_SLP_MASK 0x3 +#define PMIC_RG_VPA_SLP_SHIFT 10 +#define PMIC_RG_VPA_ZX_OS_TRIM_ADDR MT6353_VPA_ANA_CON1 +#define PMIC_RG_VPA_ZX_OS_TRIM_MASK 0x3F +#define PMIC_RG_VPA_ZX_OS_TRIM_SHIFT 0 +#define PMIC_RG_VPA_ZX_OS_ADDR MT6353_VPA_ANA_CON1 +#define PMIC_RG_VPA_ZX_OS_MASK 0x3 +#define PMIC_RG_VPA_ZX_OS_SHIFT 6 +#define PMIC_RG_VPA_HZP_ADDR MT6353_VPA_ANA_CON1 +#define PMIC_RG_VPA_HZP_MASK 0x1 +#define PMIC_RG_VPA_HZP_SHIFT 8 +#define PMIC_RG_VPA_BWEX_GAT_ADDR MT6353_VPA_ANA_CON1 +#define PMIC_RG_VPA_BWEX_GAT_MASK 0x1 +#define PMIC_RG_VPA_BWEX_GAT_SHIFT 9 +#define PMIC_RG_VPA_MODESET_ADDR MT6353_VPA_ANA_CON1 +#define PMIC_RG_VPA_MODESET_MASK 0x1 +#define PMIC_RG_VPA_MODESET_SHIFT 10 +#define PMIC_RG_VPA_SLEW_ADDR MT6353_VPA_ANA_CON1 +#define PMIC_RG_VPA_SLEW_MASK 0x3 +#define PMIC_RG_VPA_SLEW_SHIFT 11 +#define PMIC_RG_VPA_SLEW_NMOS_ADDR MT6353_VPA_ANA_CON1 +#define PMIC_RG_VPA_SLEW_NMOS_MASK 0x3 +#define PMIC_RG_VPA_SLEW_NMOS_SHIFT 13 +#define PMIC_RG_VPA_NDIS_EN_ADDR MT6353_VPA_ANA_CON1 +#define PMIC_RG_VPA_NDIS_EN_MASK 0x1 +#define PMIC_RG_VPA_NDIS_EN_SHIFT 15 +#define PMIC_RG_VPA_MIN_ON_ADDR MT6353_VPA_ANA_CON2 +#define PMIC_RG_VPA_MIN_ON_MASK 0x3 +#define PMIC_RG_VPA_MIN_ON_SHIFT 0 +#define PMIC_RG_VPA_VBAT_DEL_ADDR MT6353_VPA_ANA_CON2 +#define PMIC_RG_VPA_VBAT_DEL_MASK 0x3 +#define PMIC_RG_VPA_VBAT_DEL_SHIFT 2 +#define PMIC_RG_VPA_RSV1_ADDR MT6353_VPA_ANA_CON2 +#define PMIC_RG_VPA_RSV1_MASK 0xFF +#define PMIC_RG_VPA_RSV1_SHIFT 5 +#define PMIC_RG_VPA_RSV2_ADDR MT6353_VPA_ANA_CON3 +#define PMIC_RG_VPA_RSV2_MASK 0xFF +#define PMIC_RG_VPA_RSV2_SHIFT 0 +#define PMIC_RGS_VPA_ZX_STATUS_ADDR MT6353_VPA_ANA_CON3 +#define PMIC_RGS_VPA_ZX_STATUS_MASK 0x1 +#define PMIC_RGS_VPA_ZX_STATUS_SHIFT 8 +#define PMIC_RG_VCORE_MIN_OFF_ADDR MT6353_VCORE_ANA_CON0 +#define PMIC_RG_VCORE_MIN_OFF_MASK 0x3 +#define PMIC_RG_VCORE_MIN_OFF_SHIFT 0 +#define PMIC_RG_VCORE_VRF18_SSTART_EN_ADDR MT6353_VCORE_ANA_CON0 +#define PMIC_RG_VCORE_VRF18_SSTART_EN_MASK 0x1 +#define PMIC_RG_VCORE_VRF18_SSTART_EN_SHIFT 2 +#define PMIC_RG_VCORE_1P35UP_SEL_EN_ADDR MT6353_VCORE_ANA_CON0 +#define PMIC_RG_VCORE_1P35UP_SEL_EN_MASK 0x1 +#define PMIC_RG_VCORE_1P35UP_SEL_EN_SHIFT 3 +#define PMIC_RG_VCORE_RZSEL_ADDR MT6353_VCORE_ANA_CON0 +#define PMIC_RG_VCORE_RZSEL_MASK 0x7 +#define PMIC_RG_VCORE_RZSEL_SHIFT 4 +#define PMIC_RG_VCORE_CSR_ADDR MT6353_VCORE_ANA_CON0 +#define PMIC_RG_VCORE_CSR_MASK 0x7 +#define PMIC_RG_VCORE_CSR_SHIFT 7 +#define PMIC_RG_VCORE_CSL_ADDR MT6353_VCORE_ANA_CON0 +#define PMIC_RG_VCORE_CSL_MASK 0xF +#define PMIC_RG_VCORE_CSL_SHIFT 10 +#define PMIC_RG_VCORE_SLP_ADDR MT6353_VCORE_ANA_CON1 +#define PMIC_RG_VCORE_SLP_MASK 0x7 +#define PMIC_RG_VCORE_SLP_SHIFT 0 +#define PMIC_RG_VCORE_ZX_OS_ADDR MT6353_VCORE_ANA_CON1 +#define PMIC_RG_VCORE_ZX_OS_MASK 0x3 +#define PMIC_RG_VCORE_ZX_OS_SHIFT 3 +#define PMIC_RG_VCORE_ZXOS_TRIM_ADDR MT6353_VCORE_ANA_CON1 +#define PMIC_RG_VCORE_ZXOS_TRIM_MASK 0x3F +#define PMIC_RG_VCORE_ZXOS_TRIM_SHIFT 5 +#define PMIC_RG_VCORE_MODESET_ADDR MT6353_VCORE_ANA_CON1 +#define PMIC_RG_VCORE_MODESET_MASK 0x1 +#define PMIC_RG_VCORE_MODESET_SHIFT 11 +#define PMIC_RG_VCORE_NDIS_EN_ADDR MT6353_VCORE_ANA_CON1 +#define PMIC_RG_VCORE_NDIS_EN_MASK 0x1 +#define PMIC_RG_VCORE_NDIS_EN_SHIFT 12 +#define PMIC_RG_VCORE_CSM_N_ADDR MT6353_VCORE_ANA_CON2 +#define PMIC_RG_VCORE_CSM_N_MASK 0x3F +#define PMIC_RG_VCORE_CSM_N_SHIFT 0 +#define PMIC_RG_VCORE_CSM_P_ADDR MT6353_VCORE_ANA_CON2 +#define PMIC_RG_VCORE_CSM_P_MASK 0x3F +#define PMIC_RG_VCORE_CSM_P_SHIFT 6 +#define PMIC_RG_VCORE_RSV_ADDR MT6353_VCORE_ANA_CON3 +#define PMIC_RG_VCORE_RSV_MASK 0xFF +#define PMIC_RG_VCORE_RSV_SHIFT 0 +#define PMIC_RG_VCORE_PFM_RIP_ADDR MT6353_VCORE_ANA_CON3 +#define PMIC_RG_VCORE_PFM_RIP_MASK 0x7 +#define PMIC_RG_VCORE_PFM_RIP_SHIFT 8 +#define PMIC_RG_VCORE_DTS_ENB_ADDR MT6353_VCORE_ANA_CON3 +#define PMIC_RG_VCORE_DTS_ENB_MASK 0x1 +#define PMIC_RG_VCORE_DTS_ENB_SHIFT 11 +#define PMIC_RG_VCORE_AUTO_MODE_ADDR MT6353_VCORE_ANA_CON3 +#define PMIC_RG_VCORE_AUTO_MODE_MASK 0x1 +#define PMIC_RG_VCORE_AUTO_MODE_SHIFT 12 +#define PMIC_RG_VCORE_PWM_TRIG_ADDR MT6353_VCORE_ANA_CON3 +#define PMIC_RG_VCORE_PWM_TRIG_MASK 0x1 +#define PMIC_RG_VCORE_PWM_TRIG_SHIFT 13 +#define PMIC_RG_VCORE_TRAN_BST_ADDR MT6353_VCORE_ANA_CON4 +#define PMIC_RG_VCORE_TRAN_BST_MASK 0x3F +#define PMIC_RG_VCORE_TRAN_BST_SHIFT 0 +#define PMIC_RGS_VCORE_ENPWM_STATUS_ADDR MT6353_VCORE_ANA_CON4 +#define PMIC_RGS_VCORE_ENPWM_STATUS_MASK 0x1 +#define PMIC_RGS_VCORE_ENPWM_STATUS_SHIFT 6 +#define PMIC_RG_VPROC_MIN_OFF_ADDR MT6353_VPROC_ANA_CON0 +#define PMIC_RG_VPROC_MIN_OFF_MASK 0x3 +#define PMIC_RG_VPROC_MIN_OFF_SHIFT 0 +#define PMIC_RG_VPROC_VRF18_SSTART_EN_ADDR MT6353_VPROC_ANA_CON0 +#define PMIC_RG_VPROC_VRF18_SSTART_EN_MASK 0x1 +#define PMIC_RG_VPROC_VRF18_SSTART_EN_SHIFT 2 +#define PMIC_RG_VPROC_1P35UP_SEL_EN_ADDR MT6353_VPROC_ANA_CON0 +#define PMIC_RG_VPROC_1P35UP_SEL_EN_MASK 0x1 +#define PMIC_RG_VPROC_1P35UP_SEL_EN_SHIFT 3 +#define PMIC_RG_VPROC_RZSEL_ADDR MT6353_VPROC_ANA_CON0 +#define PMIC_RG_VPROC_RZSEL_MASK 0x7 +#define PMIC_RG_VPROC_RZSEL_SHIFT 4 +#define PMIC_RG_VPROC_CSR_ADDR MT6353_VPROC_ANA_CON0 +#define PMIC_RG_VPROC_CSR_MASK 0x7 +#define PMIC_RG_VPROC_CSR_SHIFT 7 +#define PMIC_RG_VPROC_CSL_ADDR MT6353_VPROC_ANA_CON0 +#define PMIC_RG_VPROC_CSL_MASK 0xF +#define PMIC_RG_VPROC_CSL_SHIFT 10 +#define PMIC_RG_VPROC_SLP_ADDR MT6353_VPROC_ANA_CON1 +#define PMIC_RG_VPROC_SLP_MASK 0x7 +#define PMIC_RG_VPROC_SLP_SHIFT 0 +#define PMIC_RG_VPROC_ZX_OS_ADDR MT6353_VPROC_ANA_CON1 +#define PMIC_RG_VPROC_ZX_OS_MASK 0x3 +#define PMIC_RG_VPROC_ZX_OS_SHIFT 3 +#define PMIC_RG_VPROC_ZXOS_TRIM_ADDR MT6353_VPROC_ANA_CON1 +#define PMIC_RG_VPROC_ZXOS_TRIM_MASK 0x3F +#define PMIC_RG_VPROC_ZXOS_TRIM_SHIFT 5 +#define PMIC_RG_VPROC_MODESET_ADDR MT6353_VPROC_ANA_CON1 +#define PMIC_RG_VPROC_MODESET_MASK 0x1 +#define PMIC_RG_VPROC_MODESET_SHIFT 11 +#define PMIC_RG_VPROC_NDIS_EN_ADDR MT6353_VPROC_ANA_CON1 +#define PMIC_RG_VPROC_NDIS_EN_MASK 0x1 +#define PMIC_RG_VPROC_NDIS_EN_SHIFT 12 +#define PMIC_RG_VPROC_CSM_N_ADDR MT6353_VPROC_ANA_CON2 +#define PMIC_RG_VPROC_CSM_N_MASK 0x3F +#define PMIC_RG_VPROC_CSM_N_SHIFT 0 +#define PMIC_RG_VPROC_CSM_P_ADDR MT6353_VPROC_ANA_CON2 +#define PMIC_RG_VPROC_CSM_P_MASK 0x3F +#define PMIC_RG_VPROC_CSM_P_SHIFT 6 +#define PMIC_RG_VPROC_RSV_ADDR MT6353_VPROC_ANA_CON3 +#define PMIC_RG_VPROC_RSV_MASK 0xFF +#define PMIC_RG_VPROC_RSV_SHIFT 0 +#define PMIC_RG_VPROC_PFM_RIP_ADDR MT6353_VPROC_ANA_CON3 +#define PMIC_RG_VPROC_PFM_RIP_MASK 0x7 +#define PMIC_RG_VPROC_PFM_RIP_SHIFT 8 +#define PMIC_RG_VPROC_DTS_ENB_ADDR MT6353_VPROC_ANA_CON3 +#define PMIC_RG_VPROC_DTS_ENB_MASK 0x1 +#define PMIC_RG_VPROC_DTS_ENB_SHIFT 11 +#define PMIC_RG_VPROC_BW_EXTEND_ADDR MT6353_VPROC_ANA_CON3 +#define PMIC_RG_VPROC_BW_EXTEND_MASK 0x1 +#define PMIC_RG_VPROC_BW_EXTEND_SHIFT 12 +#define PMIC_RG_VPROC_PWM_TRIG_ADDR MT6353_VPROC_ANA_CON3 +#define PMIC_RG_VPROC_PWM_TRIG_MASK 0x1 +#define PMIC_RG_VPROC_PWM_TRIG_SHIFT 13 +#define PMIC_RG_VPROC_TRAN_BST_ADDR MT6353_VPROC_ANA_CON4 +#define PMIC_RG_VPROC_TRAN_BST_MASK 0x3F +#define PMIC_RG_VPROC_TRAN_BST_SHIFT 0 +#define PMIC_RGS_VPROC_ENPWM_STATUS_ADDR MT6353_VPROC_ANA_CON4 +#define PMIC_RGS_VPROC_ENPWM_STATUS_MASK 0x1 +#define PMIC_RGS_VPROC_ENPWM_STATUS_SHIFT 6 +#define PMIC_RG_VS1_MIN_OFF_ADDR MT6353_VS1_ANA_CON0 +#define PMIC_RG_VS1_MIN_OFF_MASK 0x3 +#define PMIC_RG_VS1_MIN_OFF_SHIFT 0 +#define PMIC_RG_VS1_NVT_BUFF_OFF_EN_ADDR MT6353_VS1_ANA_CON0 +#define PMIC_RG_VS1_NVT_BUFF_OFF_EN_MASK 0x1 +#define PMIC_RG_VS1_NVT_BUFF_OFF_EN_SHIFT 2 +#define PMIC_RG_VS1_VRF18_SSTART_EN_ADDR MT6353_VS1_ANA_CON0 +#define PMIC_RG_VS1_VRF18_SSTART_EN_MASK 0x1 +#define PMIC_RG_VS1_VRF18_SSTART_EN_SHIFT 3 +#define PMIC_RG_VS1_1P35UP_SEL_EN_ADDR MT6353_VS1_ANA_CON0 +#define PMIC_RG_VS1_1P35UP_SEL_EN_MASK 0x1 +#define PMIC_RG_VS1_1P35UP_SEL_EN_SHIFT 4 +#define PMIC_RG_VS1_RZSEL_ADDR MT6353_VS1_ANA_CON0 +#define PMIC_RG_VS1_RZSEL_MASK 0x7 +#define PMIC_RG_VS1_RZSEL_SHIFT 5 +#define PMIC_RG_VS1_CSR_ADDR MT6353_VS1_ANA_CON0 +#define PMIC_RG_VS1_CSR_MASK 0x7 +#define PMIC_RG_VS1_CSR_SHIFT 8 +#define PMIC_RG_VS1_CSL_ADDR MT6353_VS1_ANA_CON0 +#define PMIC_RG_VS1_CSL_MASK 0xF +#define PMIC_RG_VS1_CSL_SHIFT 11 +#define PMIC_RG_VS1_SLP_ADDR MT6353_VS1_ANA_CON1 +#define PMIC_RG_VS1_SLP_MASK 0x7 +#define PMIC_RG_VS1_SLP_SHIFT 0 +#define PMIC_RG_VS1_ZX_OS_ADDR MT6353_VS1_ANA_CON1 +#define PMIC_RG_VS1_ZX_OS_MASK 0x3 +#define PMIC_RG_VS1_ZX_OS_SHIFT 3 +#define PMIC_RG_VS1_NDIS_EN_ADDR MT6353_VS1_ANA_CON1 +#define PMIC_RG_VS1_NDIS_EN_MASK 0x1 +#define PMIC_RG_VS1_NDIS_EN_SHIFT 5 +#define PMIC_RG_VS1_CSM_N_ADDR MT6353_VS1_ANA_CON1 +#define PMIC_RG_VS1_CSM_N_MASK 0x3F +#define PMIC_RG_VS1_CSM_N_SHIFT 6 +#define PMIC_RG_VS1_CSM_P_ADDR MT6353_VS1_ANA_CON2 +#define PMIC_RG_VS1_CSM_P_MASK 0x3F +#define PMIC_RG_VS1_CSM_P_SHIFT 0 +#define PMIC_RG_VS1_RSV_ADDR MT6353_VS1_ANA_CON2 +#define PMIC_RG_VS1_RSV_MASK 0xFF +#define PMIC_RG_VS1_RSV_SHIFT 6 +#define PMIC_RG_VS1_ZXOS_TRIM_ADDR MT6353_VS1_ANA_CON3 +#define PMIC_RG_VS1_ZXOS_TRIM_MASK 0x3F +#define PMIC_RG_VS1_ZXOS_TRIM_SHIFT 0 +#define PMIC_RG_VS1_MODESET_ADDR MT6353_VS1_ANA_CON3 +#define PMIC_RG_VS1_MODESET_MASK 0x1 +#define PMIC_RG_VS1_MODESET_SHIFT 6 +#define PMIC_RG_VS1_PFM_RIP_ADDR MT6353_VS1_ANA_CON3 +#define PMIC_RG_VS1_PFM_RIP_MASK 0x7 +#define PMIC_RG_VS1_PFM_RIP_SHIFT 7 +#define PMIC_RG_VS1_TRAN_BST_ADDR MT6353_VS1_ANA_CON3 +#define PMIC_RG_VS1_TRAN_BST_MASK 0x3F +#define PMIC_RG_VS1_TRAN_BST_SHIFT 10 +#define PMIC_RG_VS1_DTS_ENB_ADDR MT6353_VS1_ANA_CON4 +#define PMIC_RG_VS1_DTS_ENB_MASK 0x1 +#define PMIC_RG_VS1_DTS_ENB_SHIFT 0 +#define PMIC_RG_VS1_AUTO_MODE_ADDR MT6353_VS1_ANA_CON4 +#define PMIC_RG_VS1_AUTO_MODE_MASK 0x1 +#define PMIC_RG_VS1_AUTO_MODE_SHIFT 1 +#define PMIC_RG_VS1_PWM_TRIG_ADDR MT6353_VS1_ANA_CON4 +#define PMIC_RG_VS1_PWM_TRIG_MASK 0x1 +#define PMIC_RG_VS1_PWM_TRIG_SHIFT 2 +#define PMIC_RGS_VS1_ENPWM_STATUS_ADDR MT6353_VS1_ANA_CON4 +#define PMIC_RGS_VS1_ENPWM_STATUS_MASK 0x1 +#define PMIC_RGS_VS1_ENPWM_STATUS_SHIFT 3 +#define PMIC_DA_QI_VCORE_BURST_ADDR MT6353_BUCK_ANA_CON0 +#define PMIC_DA_QI_VCORE_BURST_MASK 0x7 +#define PMIC_DA_QI_VCORE_BURST_SHIFT 0 +#define PMIC_DA_QI_VCORE2_BURST_ADDR MT6353_BUCK_ANA_CON0 +#define PMIC_DA_QI_VCORE2_BURST_MASK 0x7 +#define PMIC_DA_QI_VCORE2_BURST_SHIFT 4 +#define PMIC_DA_QI_VS1_BURST_ADDR MT6353_BUCK_ANA_CON0 +#define PMIC_DA_QI_VS1_BURST_MASK 0x7 +#define PMIC_DA_QI_VS1_BURST_SHIFT 8 +#define PMIC_DA_QI_VPROC_BURST_ADDR MT6353_BUCK_ANA_CON0 +#define PMIC_DA_QI_VPROC_BURST_MASK 0x7 +#define PMIC_DA_QI_VPROC_BURST_SHIFT 11 +#define PMIC_DA_QI_VCORE_DLC_ADDR MT6353_BUCK_ANA_CON1 +#define PMIC_DA_QI_VCORE_DLC_MASK 0x3 +#define PMIC_DA_QI_VCORE_DLC_SHIFT 0 +#define PMIC_DA_QI_VCORE_DLC_N_ADDR MT6353_BUCK_ANA_CON1 +#define PMIC_DA_QI_VCORE_DLC_N_MASK 0x3 +#define PMIC_DA_QI_VCORE_DLC_N_SHIFT 2 +#define PMIC_DA_QI_VCORE2_DLC_ADDR MT6353_BUCK_ANA_CON1 +#define PMIC_DA_QI_VCORE2_DLC_MASK 0x3 +#define PMIC_DA_QI_VCORE2_DLC_SHIFT 4 +#define PMIC_DA_QI_VCORE2_DLC_N_ADDR MT6353_BUCK_ANA_CON1 +#define PMIC_DA_QI_VCORE2_DLC_N_MASK 0x3 +#define PMIC_DA_QI_VCORE2_DLC_N_SHIFT 6 +#define PMIC_DA_QI_VS1_DLC_ADDR MT6353_BUCK_ANA_CON1 +#define PMIC_DA_QI_VS1_DLC_MASK 0x3 +#define PMIC_DA_QI_VS1_DLC_SHIFT 8 +#define PMIC_DA_QI_VS1_DLC_N_ADDR MT6353_BUCK_ANA_CON1 +#define PMIC_DA_QI_VS1_DLC_N_MASK 0x3 +#define PMIC_DA_QI_VS1_DLC_N_SHIFT 10 +#define PMIC_DA_QI_VPROC_DLC_ADDR MT6353_BUCK_ANA_CON1 +#define PMIC_DA_QI_VPROC_DLC_MASK 0x3 +#define PMIC_DA_QI_VPROC_DLC_SHIFT 12 +#define PMIC_DA_QI_VPROC_DLC_N_ADDR MT6353_BUCK_ANA_CON1 +#define PMIC_DA_QI_VPROC_DLC_N_MASK 0x3 +#define PMIC_DA_QI_VPROC_DLC_N_SHIFT 14 +#define PMIC_RG_VCORE2_MIN_OFF_ADDR MT6353_VCORE2_ANA_CON0 +#define PMIC_RG_VCORE2_MIN_OFF_MASK 0x3 +#define PMIC_RG_VCORE2_MIN_OFF_SHIFT 0 +#define PMIC_RG_VCORE2_VRF18_SSTART_EN_ADDR MT6353_VCORE2_ANA_CON0 +#define PMIC_RG_VCORE2_VRF18_SSTART_EN_MASK 0x1 +#define PMIC_RG_VCORE2_VRF18_SSTART_EN_SHIFT 2 +#define PMIC_RG_VCORE2_1P35UP_SEL_EN_ADDR MT6353_VCORE2_ANA_CON0 +#define PMIC_RG_VCORE2_1P35UP_SEL_EN_MASK 0x1 +#define PMIC_RG_VCORE2_1P35UP_SEL_EN_SHIFT 3 +#define PMIC_RG_VCORE2_RZSEL_ADDR MT6353_VCORE2_ANA_CON0 +#define PMIC_RG_VCORE2_RZSEL_MASK 0x7 +#define PMIC_RG_VCORE2_RZSEL_SHIFT 4 +#define PMIC_RG_VCORE2_CSR_ADDR MT6353_VCORE2_ANA_CON0 +#define PMIC_RG_VCORE2_CSR_MASK 0x7 +#define PMIC_RG_VCORE2_CSR_SHIFT 7 +#define PMIC_RG_VCORE2_CSL_ADDR MT6353_VCORE2_ANA_CON0 +#define PMIC_RG_VCORE2_CSL_MASK 0xF +#define PMIC_RG_VCORE2_CSL_SHIFT 10 +#define PMIC_RG_VCORE2_SLP_ADDR MT6353_VCORE2_ANA_CON1 +#define PMIC_RG_VCORE2_SLP_MASK 0x7 +#define PMIC_RG_VCORE2_SLP_SHIFT 0 +#define PMIC_RG_VCORE2_ZX_OS_ADDR MT6353_VCORE2_ANA_CON1 +#define PMIC_RG_VCORE2_ZX_OS_MASK 0x3 +#define PMIC_RG_VCORE2_ZX_OS_SHIFT 3 +#define PMIC_RG_VCORE2_ZXOS_TRIM_ADDR MT6353_VCORE2_ANA_CON1 +#define PMIC_RG_VCORE2_ZXOS_TRIM_MASK 0x3F +#define PMIC_RG_VCORE2_ZXOS_TRIM_SHIFT 5 +#define PMIC_RG_VCORE2_MODESET_ADDR MT6353_VCORE2_ANA_CON1 +#define PMIC_RG_VCORE2_MODESET_MASK 0x1 +#define PMIC_RG_VCORE2_MODESET_SHIFT 11 +#define PMIC_RG_VCORE2_NDIS_EN_ADDR MT6353_VCORE2_ANA_CON1 +#define PMIC_RG_VCORE2_NDIS_EN_MASK 0x1 +#define PMIC_RG_VCORE2_NDIS_EN_SHIFT 12 +#define PMIC_RG_VCORE2_CSM_N_ADDR MT6353_VCORE2_ANA_CON2 +#define PMIC_RG_VCORE2_CSM_N_MASK 0x3F +#define PMIC_RG_VCORE2_CSM_N_SHIFT 0 +#define PMIC_RG_VCORE2_CSM_P_ADDR MT6353_VCORE2_ANA_CON2 +#define PMIC_RG_VCORE2_CSM_P_MASK 0x3F +#define PMIC_RG_VCORE2_CSM_P_SHIFT 6 +#define PMIC_RG_VCORE2_RSV_ADDR MT6353_VCORE2_ANA_CON3 +#define PMIC_RG_VCORE2_RSV_MASK 0xFF +#define PMIC_RG_VCORE2_RSV_SHIFT 0 +#define PMIC_RG_VCORE2_PFM_RIP_ADDR MT6353_VCORE2_ANA_CON3 +#define PMIC_RG_VCORE2_PFM_RIP_MASK 0x7 +#define PMIC_RG_VCORE2_PFM_RIP_SHIFT 8 +#define PMIC_RG_VCORE2_DTS_ENB_ADDR MT6353_VCORE2_ANA_CON3 +#define PMIC_RG_VCORE2_DTS_ENB_MASK 0x1 +#define PMIC_RG_VCORE2_DTS_ENB_SHIFT 11 +#define PMIC_RG_VCORE2_AUTO_MODE_ADDR MT6353_VCORE2_ANA_CON3 +#define PMIC_RG_VCORE2_AUTO_MODE_MASK 0x1 +#define PMIC_RG_VCORE2_AUTO_MODE_SHIFT 12 +#define PMIC_RG_VCORE2_PWM_TRIG_ADDR MT6353_VCORE2_ANA_CON3 +#define PMIC_RG_VCORE2_PWM_TRIG_MASK 0x1 +#define PMIC_RG_VCORE2_PWM_TRIG_SHIFT 13 +#define PMIC_RG_VCORE2_TRAN_BST_ADDR MT6353_VCORE2_ANA_CON4 +#define PMIC_RG_VCORE2_TRAN_BST_MASK 0x3F +#define PMIC_RG_VCORE2_TRAN_BST_SHIFT 0 +#define PMIC_RGS_VCORE2_ENPWM_STATUS_ADDR MT6353_VCORE2_ANA_CON4 +#define PMIC_RGS_VCORE2_ENPWM_STATUS_MASK 0x1 +#define PMIC_RGS_VCORE2_ENPWM_STATUS_SHIFT 6 +#define PMIC_BUCK_VPROC_EN_CTRL_ADDR MT6353_BUCK_VPROC_HWM_CON0 +#define PMIC_BUCK_VPROC_EN_CTRL_MASK 0x1 +#define PMIC_BUCK_VPROC_EN_CTRL_SHIFT 0 +#define PMIC_BUCK_VPROC_VOSEL_CTRL_ADDR MT6353_BUCK_VPROC_HWM_CON0 +#define PMIC_BUCK_VPROC_VOSEL_CTRL_MASK 0x1 +#define PMIC_BUCK_VPROC_VOSEL_CTRL_SHIFT 1 +#define PMIC_BUCK_VPROC_EN_SEL_ADDR MT6353_BUCK_VPROC_HWM_CON1 +#define PMIC_BUCK_VPROC_EN_SEL_MASK 0x7 +#define PMIC_BUCK_VPROC_EN_SEL_SHIFT 0 +#define PMIC_BUCK_VPROC_VOSEL_SEL_ADDR MT6353_BUCK_VPROC_HWM_CON1 +#define PMIC_BUCK_VPROC_VOSEL_SEL_MASK 0x7 +#define PMIC_BUCK_VPROC_VOSEL_SEL_SHIFT 3 +#define PMIC_BUCK_VPROC_EN_ADDR MT6353_BUCK_VPROC_EN_CON0 +#define PMIC_BUCK_VPROC_EN_MASK 0x1 +#define PMIC_BUCK_VPROC_EN_SHIFT 0 +#define PMIC_BUCK_VPROC_STBTD_ADDR MT6353_BUCK_VPROC_EN_CON0 +#define PMIC_BUCK_VPROC_STBTD_MASK 0x3 +#define PMIC_BUCK_VPROC_STBTD_SHIFT 4 +#define PMIC_DA_VPROC_STB_ADDR MT6353_BUCK_VPROC_EN_CON0 +#define PMIC_DA_VPROC_STB_MASK 0x1 +#define PMIC_DA_VPROC_STB_SHIFT 12 +#define PMIC_DA_QI_VPROC_EN_ADDR MT6353_BUCK_VPROC_EN_CON0 +#define PMIC_DA_QI_VPROC_EN_MASK 0x1 +#define PMIC_DA_QI_VPROC_EN_SHIFT 13 +#define PMIC_BUCK_VPROC_SFCHG_FRATE_ADDR MT6353_BUCK_VPROC_SFCHG_CON0 +#define PMIC_BUCK_VPROC_SFCHG_FRATE_MASK 0x7F +#define PMIC_BUCK_VPROC_SFCHG_FRATE_SHIFT 0 +#define PMIC_BUCK_VPROC_SFCHG_FEN_ADDR MT6353_BUCK_VPROC_SFCHG_CON0 +#define PMIC_BUCK_VPROC_SFCHG_FEN_MASK 0x1 +#define PMIC_BUCK_VPROC_SFCHG_FEN_SHIFT 7 +#define PMIC_BUCK_VPROC_SFCHG_RRATE_ADDR MT6353_BUCK_VPROC_SFCHG_CON0 +#define PMIC_BUCK_VPROC_SFCHG_RRATE_MASK 0x7F +#define PMIC_BUCK_VPROC_SFCHG_RRATE_SHIFT 8 +#define PMIC_BUCK_VPROC_SFCHG_REN_ADDR MT6353_BUCK_VPROC_SFCHG_CON0 +#define PMIC_BUCK_VPROC_SFCHG_REN_MASK 0x1 +#define PMIC_BUCK_VPROC_SFCHG_REN_SHIFT 15 +#define PMIC_DA_NI_VPROC_VOSEL_ADDR MT6353_BUCK_VPROC_VOL_CON0 +#define PMIC_DA_NI_VPROC_VOSEL_MASK 0x7F +#define PMIC_DA_NI_VPROC_VOSEL_SHIFT 0 +#define PMIC_BUCK_VPROC_VOSEL_ADDR MT6353_BUCK_VPROC_VOL_CON1 +#define PMIC_BUCK_VPROC_VOSEL_MASK 0x7F +#define PMIC_BUCK_VPROC_VOSEL_SHIFT 0 +#define PMIC_BUCK_VPROC_VOSEL_ON_ADDR MT6353_BUCK_VPROC_VOL_CON2 +#define PMIC_BUCK_VPROC_VOSEL_ON_MASK 0x7F +#define PMIC_BUCK_VPROC_VOSEL_ON_SHIFT 0 +#define PMIC_BUCK_VPROC_VOSEL_SLEEP_ADDR MT6353_BUCK_VPROC_VOL_CON3 +#define PMIC_BUCK_VPROC_VOSEL_SLEEP_MASK 0x7F +#define PMIC_BUCK_VPROC_VOSEL_SLEEP_SHIFT 0 +#define PMIC_BUCK_VPROC_TRANS_TD_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_BUCK_VPROC_TRANS_TD_MASK 0x3 +#define PMIC_BUCK_VPROC_TRANS_TD_SHIFT 0 +#define PMIC_BUCK_VPROC_TRANS_CTRL_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_BUCK_VPROC_TRANS_CTRL_MASK 0x3 +#define PMIC_BUCK_VPROC_TRANS_CTRL_SHIFT 4 +#define PMIC_BUCK_VPROC_TRANS_ONCE_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_BUCK_VPROC_TRANS_ONCE_MASK 0x1 +#define PMIC_BUCK_VPROC_TRANS_ONCE_SHIFT 6 +#define PMIC_DA_QI_VPROC_DVS_EN_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_DA_QI_VPROC_DVS_EN_MASK 0x1 +#define PMIC_DA_QI_VPROC_DVS_EN_SHIFT 7 +#define PMIC_BUCK_VPROC_VSLEEP_EN_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_BUCK_VPROC_VSLEEP_EN_MASK 0x1 +#define PMIC_BUCK_VPROC_VSLEEP_EN_SHIFT 8 +#define PMIC_BUCK_VPROC_R2R_PDN_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_BUCK_VPROC_R2R_PDN_MASK 0x1 +#define PMIC_BUCK_VPROC_R2R_PDN_SHIFT 10 +#define PMIC_BUCK_VPROC_VSLEEP_SEL_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_BUCK_VPROC_VSLEEP_SEL_MASK 0x1 +#define PMIC_BUCK_VPROC_VSLEEP_SEL_SHIFT 11 +#define PMIC_DA_NI_VPROC_R2R_PDN_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_DA_NI_VPROC_R2R_PDN_MASK 0x1 +#define PMIC_DA_NI_VPROC_R2R_PDN_SHIFT 14 +#define PMIC_DA_NI_VPROC_VSLEEP_SEL_ADDR MT6353_BUCK_VPROC_LPW_CON0 +#define PMIC_DA_NI_VPROC_VSLEEP_SEL_MASK 0x1 +#define PMIC_DA_NI_VPROC_VSLEEP_SEL_SHIFT 15 +#define PMIC_BUCK_VS1_EN_CTRL_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_EN_CTRL_MASK 0x1 +#define PMIC_BUCK_VS1_EN_CTRL_SHIFT 0 +#define PMIC_BUCK_VS1_VOSEL_CTRL_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_VOSEL_CTRL_MASK 0x1 +#define PMIC_BUCK_VS1_VOSEL_CTRL_SHIFT 1 +#define PMIC_BUCK_VS1_VOSEL_CTRL_0_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_VOSEL_CTRL_0_MASK 0x1 +#define PMIC_BUCK_VS1_VOSEL_CTRL_0_SHIFT 2 +#define PMIC_BUCK_VS1_VOSEL_CTRL_1_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_VOSEL_CTRL_1_MASK 0x1 +#define PMIC_BUCK_VS1_VOSEL_CTRL_1_SHIFT 3 +#define PMIC_BUCK_VS1_VOSEL_CTRL_2_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_VOSEL_CTRL_2_MASK 0x1 +#define PMIC_BUCK_VS1_VOSEL_CTRL_2_SHIFT 4 +#define PMIC_BUCK_VS1_MODESET_0_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_MODESET_0_MASK 0x1 +#define PMIC_BUCK_VS1_MODESET_0_SHIFT 5 +#define PMIC_BUCK_VS1_MODESET_1_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_MODESET_1_MASK 0x1 +#define PMIC_BUCK_VS1_MODESET_1_SHIFT 6 +#define PMIC_BUCK_VS1_MODESET_2_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_MODESET_2_MASK 0x1 +#define PMIC_BUCK_VS1_MODESET_2_SHIFT 7 +#define PMIC_DA_VS1_MODESET_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_DA_VS1_MODESET_MASK 0x1 +#define PMIC_DA_VS1_MODESET_SHIFT 8 +#define PMIC_BUCK_VS1_VOSEL_CTRL_INV_ADDR MT6353_BUCK_VS1_HWM_CON0 +#define PMIC_BUCK_VS1_VOSEL_CTRL_INV_MASK 0x1 +#define PMIC_BUCK_VS1_VOSEL_CTRL_INV_SHIFT 9 +#define PMIC_BUCK_VS1_HWM_CON0_SET_ADDR MT6353_BUCK_VS1_HWM_CON0_SET +#define PMIC_BUCK_VS1_HWM_CON0_SET_MASK 0xFFFF +#define PMIC_BUCK_VS1_HWM_CON0_SET_SHIFT 0 +#define PMIC_BUCK_VS1_HWM_CON0_CLR_ADDR MT6353_BUCK_VS1_HWM_CON0_CLR +#define PMIC_BUCK_VS1_HWM_CON0_CLR_MASK 0xFFFF +#define PMIC_BUCK_VS1_HWM_CON0_CLR_SHIFT 0 +#define PMIC_BUCK_VS1_EN_SEL_ADDR MT6353_BUCK_VS1_HWM_CON1 +#define PMIC_BUCK_VS1_EN_SEL_MASK 0x7 +#define PMIC_BUCK_VS1_EN_SEL_SHIFT 0 +#define PMIC_BUCK_VS1_VOSEL_SEL_ADDR MT6353_BUCK_VS1_HWM_CON1 +#define PMIC_BUCK_VS1_VOSEL_SEL_MASK 0x7 +#define PMIC_BUCK_VS1_VOSEL_SEL_SHIFT 3 +#define PMIC_BUCK_VS1_EN_ADDR MT6353_BUCK_VS1_EN_CON0 +#define PMIC_BUCK_VS1_EN_MASK 0x1 +#define PMIC_BUCK_VS1_EN_SHIFT 0 +#define PMIC_BUCK_VS1_STBTD_ADDR MT6353_BUCK_VS1_EN_CON0 +#define PMIC_BUCK_VS1_STBTD_MASK 0x3 +#define PMIC_BUCK_VS1_STBTD_SHIFT 4 +#define PMIC_DA_VS1_STB_ADDR MT6353_BUCK_VS1_EN_CON0 +#define PMIC_DA_VS1_STB_MASK 0x1 +#define PMIC_DA_VS1_STB_SHIFT 12 +#define PMIC_DA_QI_VS1_EN_ADDR MT6353_BUCK_VS1_EN_CON0 +#define PMIC_DA_QI_VS1_EN_MASK 0x1 +#define PMIC_DA_QI_VS1_EN_SHIFT 13 +#define PMIC_BUCK_VS1_SFCHG_FRATE_ADDR MT6353_BUCK_VS1_SFCHG_CON0 +#define PMIC_BUCK_VS1_SFCHG_FRATE_MASK 0x7F +#define PMIC_BUCK_VS1_SFCHG_FRATE_SHIFT 0 +#define PMIC_BUCK_VS1_SFCHG_FEN_ADDR MT6353_BUCK_VS1_SFCHG_CON0 +#define PMIC_BUCK_VS1_SFCHG_FEN_MASK 0x1 +#define PMIC_BUCK_VS1_SFCHG_FEN_SHIFT 7 +#define PMIC_BUCK_VS1_SFCHG_RRATE_ADDR MT6353_BUCK_VS1_SFCHG_CON0 +#define PMIC_BUCK_VS1_SFCHG_RRATE_MASK 0x7F +#define PMIC_BUCK_VS1_SFCHG_RRATE_SHIFT 8 +#define PMIC_BUCK_VS1_SFCHG_REN_ADDR MT6353_BUCK_VS1_SFCHG_CON0 +#define PMIC_BUCK_VS1_SFCHG_REN_MASK 0x1 +#define PMIC_BUCK_VS1_SFCHG_REN_SHIFT 15 +#define PMIC_DA_NI_VS1_VOSEL_ADDR MT6353_BUCK_VS1_VOL_CON0 +#define PMIC_DA_NI_VS1_VOSEL_MASK 0x7F +#define PMIC_DA_NI_VS1_VOSEL_SHIFT 0 +#define PMIC_BUCK_VS1_VOSEL_ADDR MT6353_BUCK_VS1_VOL_CON1 +#define PMIC_BUCK_VS1_VOSEL_MASK 0x7F +#define PMIC_BUCK_VS1_VOSEL_SHIFT 0 +#define PMIC_BUCK_VS1_VOSEL_ON_ADDR MT6353_BUCK_VS1_VOL_CON2 +#define PMIC_BUCK_VS1_VOSEL_ON_MASK 0x7F +#define PMIC_BUCK_VS1_VOSEL_ON_SHIFT 0 +#define PMIC_BUCK_VS1_VOSEL_SLEEP_ADDR MT6353_BUCK_VS1_VOL_CON3 +#define PMIC_BUCK_VS1_VOSEL_SLEEP_MASK 0x7F +#define PMIC_BUCK_VS1_VOSEL_SLEEP_SHIFT 0 +#define PMIC_BUCK_VS1_TRANS_TD_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_BUCK_VS1_TRANS_TD_MASK 0x3 +#define PMIC_BUCK_VS1_TRANS_TD_SHIFT 0 +#define PMIC_BUCK_VS1_TRANS_CTRL_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_BUCK_VS1_TRANS_CTRL_MASK 0x3 +#define PMIC_BUCK_VS1_TRANS_CTRL_SHIFT 4 +#define PMIC_BUCK_VS1_TRANS_ONCE_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_BUCK_VS1_TRANS_ONCE_MASK 0x1 +#define PMIC_BUCK_VS1_TRANS_ONCE_SHIFT 6 +#define PMIC_DA_QI_VS1_DVS_EN_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_DA_QI_VS1_DVS_EN_MASK 0x1 +#define PMIC_DA_QI_VS1_DVS_EN_SHIFT 7 +#define PMIC_BUCK_VS1_VSLEEP_EN_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_BUCK_VS1_VSLEEP_EN_MASK 0x1 +#define PMIC_BUCK_VS1_VSLEEP_EN_SHIFT 8 +#define PMIC_BUCK_VS1_R2R_PDN_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_BUCK_VS1_R2R_PDN_MASK 0x1 +#define PMIC_BUCK_VS1_R2R_PDN_SHIFT 10 +#define PMIC_BUCK_VS1_VSLEEP_SEL_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_BUCK_VS1_VSLEEP_SEL_MASK 0x1 +#define PMIC_BUCK_VS1_VSLEEP_SEL_SHIFT 11 +#define PMIC_DA_NI_VS1_R2R_PDN_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_DA_NI_VS1_R2R_PDN_MASK 0x1 +#define PMIC_DA_NI_VS1_R2R_PDN_SHIFT 14 +#define PMIC_DA_NI_VS1_VSLEEP_SEL_ADDR MT6353_BUCK_VS1_LPW_CON0 +#define PMIC_DA_NI_VS1_VSLEEP_SEL_MASK 0x1 +#define PMIC_DA_NI_VS1_VSLEEP_SEL_SHIFT 15 +#define PMIC_BUCK_VCORE_EN_CTRL_ADDR MT6353_BUCK_VCORE_HWM_CON0 +#define PMIC_BUCK_VCORE_EN_CTRL_MASK 0x1 +#define PMIC_BUCK_VCORE_EN_CTRL_SHIFT 0 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_ADDR MT6353_BUCK_VCORE_HWM_CON0 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_MASK 0x1 +#define PMIC_BUCK_VCORE_VOSEL_CTRL_SHIFT 1 +#define PMIC_BUCK_VCORE_EN_SEL_ADDR MT6353_BUCK_VCORE_HWM_CON1 +#define PMIC_BUCK_VCORE_EN_SEL_MASK 0x7 +#define PMIC_BUCK_VCORE_EN_SEL_SHIFT 0 +#define PMIC_BUCK_VCORE_VOSEL_SEL_ADDR MT6353_BUCK_VCORE_HWM_CON1 +#define PMIC_BUCK_VCORE_VOSEL_SEL_MASK 0x7 +#define PMIC_BUCK_VCORE_VOSEL_SEL_SHIFT 3 +#define PMIC_BUCK_VCORE_EN_ADDR MT6353_BUCK_VCORE_EN_CON0 +#define PMIC_BUCK_VCORE_EN_MASK 0x1 +#define PMIC_BUCK_VCORE_EN_SHIFT 0 +#define PMIC_BUCK_VCORE_STBTD_ADDR MT6353_BUCK_VCORE_EN_CON0 +#define PMIC_BUCK_VCORE_STBTD_MASK 0x3 +#define PMIC_BUCK_VCORE_STBTD_SHIFT 4 +#define PMIC_DA_VCORE_STB_ADDR MT6353_BUCK_VCORE_EN_CON0 +#define PMIC_DA_VCORE_STB_MASK 0x1 +#define PMIC_DA_VCORE_STB_SHIFT 12 +#define PMIC_DA_QI_VCORE_EN_ADDR MT6353_BUCK_VCORE_EN_CON0 +#define PMIC_DA_QI_VCORE_EN_MASK 0x1 +#define PMIC_DA_QI_VCORE_EN_SHIFT 13 +#define PMIC_BUCK_VCORE_SFCHG_FRATE_ADDR MT6353_BUCK_VCORE_SFCHG_CON0 +#define PMIC_BUCK_VCORE_SFCHG_FRATE_MASK 0x7F +#define PMIC_BUCK_VCORE_SFCHG_FRATE_SHIFT 0 +#define PMIC_BUCK_VCORE_SFCHG_FEN_ADDR MT6353_BUCK_VCORE_SFCHG_CON0 +#define PMIC_BUCK_VCORE_SFCHG_FEN_MASK 0x1 +#define PMIC_BUCK_VCORE_SFCHG_FEN_SHIFT 7 +#define PMIC_BUCK_VCORE_SFCHG_RRATE_ADDR MT6353_BUCK_VCORE_SFCHG_CON0 +#define PMIC_BUCK_VCORE_SFCHG_RRATE_MASK 0x7F +#define PMIC_BUCK_VCORE_SFCHG_RRATE_SHIFT 8 +#define PMIC_BUCK_VCORE_SFCHG_REN_ADDR MT6353_BUCK_VCORE_SFCHG_CON0 +#define PMIC_BUCK_VCORE_SFCHG_REN_MASK 0x1 +#define PMIC_BUCK_VCORE_SFCHG_REN_SHIFT 15 +#define PMIC_DA_NI_VCORE_VOSEL_ADDR MT6353_BUCK_VCORE_VOL_CON0 +#define PMIC_DA_NI_VCORE_VOSEL_MASK 0x7F +#define PMIC_DA_NI_VCORE_VOSEL_SHIFT 0 +#define PMIC_BUCK_VCORE_VOSEL_ADDR MT6353_BUCK_VCORE_VOL_CON1 +#define PMIC_BUCK_VCORE_VOSEL_MASK 0x7F +#define PMIC_BUCK_VCORE_VOSEL_SHIFT 0 +#define PMIC_BUCK_VCORE_VOSEL_ON_ADDR MT6353_BUCK_VCORE_VOL_CON2 +#define PMIC_BUCK_VCORE_VOSEL_ON_MASK 0x7F +#define PMIC_BUCK_VCORE_VOSEL_ON_SHIFT 0 +#define PMIC_BUCK_VCORE_VOSEL_SLEEP_ADDR MT6353_BUCK_VCORE_VOL_CON3 +#define PMIC_BUCK_VCORE_VOSEL_SLEEP_MASK 0x7F +#define PMIC_BUCK_VCORE_VOSEL_SLEEP_SHIFT 0 +#define PMIC_BUCK_VCORE_TRANS_TD_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_BUCK_VCORE_TRANS_TD_MASK 0x3 +#define PMIC_BUCK_VCORE_TRANS_TD_SHIFT 0 +#define PMIC_BUCK_VCORE_TRANS_CTRL_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_BUCK_VCORE_TRANS_CTRL_MASK 0x3 +#define PMIC_BUCK_VCORE_TRANS_CTRL_SHIFT 4 +#define PMIC_BUCK_VCORE_TRANS_ONCE_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_BUCK_VCORE_TRANS_ONCE_MASK 0x1 +#define PMIC_BUCK_VCORE_TRANS_ONCE_SHIFT 6 +#define PMIC_DA_QI_VCORE_DVS_EN_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_DA_QI_VCORE_DVS_EN_MASK 0x1 +#define PMIC_DA_QI_VCORE_DVS_EN_SHIFT 7 +#define PMIC_BUCK_VCORE_VSLEEP_EN_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_BUCK_VCORE_VSLEEP_EN_MASK 0x1 +#define PMIC_BUCK_VCORE_VSLEEP_EN_SHIFT 8 +#define PMIC_BUCK_VCORE_R2R_PDN_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_BUCK_VCORE_R2R_PDN_MASK 0x1 +#define PMIC_BUCK_VCORE_R2R_PDN_SHIFT 10 +#define PMIC_BUCK_VCORE_VSLEEP_SEL_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_BUCK_VCORE_VSLEEP_SEL_MASK 0x1 +#define PMIC_BUCK_VCORE_VSLEEP_SEL_SHIFT 11 +#define PMIC_DA_NI_VCORE_R2R_PDN_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_DA_NI_VCORE_R2R_PDN_MASK 0x1 +#define PMIC_DA_NI_VCORE_R2R_PDN_SHIFT 14 +#define PMIC_DA_NI_VCORE_VSLEEP_SEL_ADDR MT6353_BUCK_VCORE_LPW_CON0 +#define PMIC_DA_NI_VCORE_VSLEEP_SEL_MASK 0x1 +#define PMIC_DA_NI_VCORE_VSLEEP_SEL_SHIFT 15 +#define PMIC_BUCK_VCORE2_EN_CTRL_ADDR MT6353_BUCK_VCORE2_HWM_CON0 +#define PMIC_BUCK_VCORE2_EN_CTRL_MASK 0x1 +#define PMIC_BUCK_VCORE2_EN_CTRL_SHIFT 0 +#define PMIC_BUCK_VCORE2_VOSEL_CTRL_ADDR MT6353_BUCK_VCORE2_HWM_CON0 +#define PMIC_BUCK_VCORE2_VOSEL_CTRL_MASK 0x1 +#define PMIC_BUCK_VCORE2_VOSEL_CTRL_SHIFT 1 +#define PMIC_BUCK_VCORE2_EN_SEL_ADDR MT6353_BUCK_VCORE2_HWM_CON1 +#define PMIC_BUCK_VCORE2_EN_SEL_MASK 0x7 +#define PMIC_BUCK_VCORE2_EN_SEL_SHIFT 0 +#define PMIC_BUCK_VCORE2_VOSEL_SEL_ADDR MT6353_BUCK_VCORE2_HWM_CON1 +#define PMIC_BUCK_VCORE2_VOSEL_SEL_MASK 0x7 +#define PMIC_BUCK_VCORE2_VOSEL_SEL_SHIFT 3 +#define PMIC_BUCK_VCORE2_EN_ADDR MT6353_BUCK_VCORE2_EN_CON0 +#define PMIC_BUCK_VCORE2_EN_MASK 0x1 +#define PMIC_BUCK_VCORE2_EN_SHIFT 0 +#define PMIC_BUCK_VCORE2_STBTD_ADDR MT6353_BUCK_VCORE2_EN_CON0 +#define PMIC_BUCK_VCORE2_STBTD_MASK 0x3 +#define PMIC_BUCK_VCORE2_STBTD_SHIFT 4 +#define PMIC_DA_VCORE2_STB_ADDR MT6353_BUCK_VCORE2_EN_CON0 +#define PMIC_DA_VCORE2_STB_MASK 0x1 +#define PMIC_DA_VCORE2_STB_SHIFT 12 +#define PMIC_DA_QI_VCORE2_EN_ADDR MT6353_BUCK_VCORE2_EN_CON0 +#define PMIC_DA_QI_VCORE2_EN_MASK 0x1 +#define PMIC_DA_QI_VCORE2_EN_SHIFT 13 +#define PMIC_BUCK_VCORE2_SFCHG_FRATE_ADDR MT6353_BUCK_VCORE2_SFCHG_CON0 +#define PMIC_BUCK_VCORE2_SFCHG_FRATE_MASK 0x7F +#define PMIC_BUCK_VCORE2_SFCHG_FRATE_SHIFT 0 +#define PMIC_BUCK_VCORE2_SFCHG_FEN_ADDR MT6353_BUCK_VCORE2_SFCHG_CON0 +#define PMIC_BUCK_VCORE2_SFCHG_FEN_MASK 0x1 +#define PMIC_BUCK_VCORE2_SFCHG_FEN_SHIFT 7 +#define PMIC_BUCK_VCORE2_SFCHG_RRATE_ADDR MT6353_BUCK_VCORE2_SFCHG_CON0 +#define PMIC_BUCK_VCORE2_SFCHG_RRATE_MASK 0x7F +#define PMIC_BUCK_VCORE2_SFCHG_RRATE_SHIFT 8 +#define PMIC_BUCK_VCORE2_SFCHG_REN_ADDR MT6353_BUCK_VCORE2_SFCHG_CON0 +#define PMIC_BUCK_VCORE2_SFCHG_REN_MASK 0x1 +#define PMIC_BUCK_VCORE2_SFCHG_REN_SHIFT 15 +#define PMIC_DA_NI_VCORE2_VOSEL_ADDR MT6353_BUCK_VCORE2_VOL_CON0 +#define PMIC_DA_NI_VCORE2_VOSEL_MASK 0x7F +#define PMIC_DA_NI_VCORE2_VOSEL_SHIFT 0 +#define PMIC_BUCK_VCORE2_VOSEL_ADDR MT6353_BUCK_VCORE2_VOL_CON1 +#define PMIC_BUCK_VCORE2_VOSEL_MASK 0x7F +#define PMIC_BUCK_VCORE2_VOSEL_SHIFT 0 +#define PMIC_BUCK_VCORE2_VOSEL_ON_ADDR MT6353_BUCK_VCORE2_VOL_CON2 +#define PMIC_BUCK_VCORE2_VOSEL_ON_MASK 0x7F +#define PMIC_BUCK_VCORE2_VOSEL_ON_SHIFT 0 +#define PMIC_BUCK_VCORE2_VOSEL_SLEEP_ADDR MT6353_BUCK_VCORE2_VOL_CON3 +#define PMIC_BUCK_VCORE2_VOSEL_SLEEP_MASK 0x7F +#define PMIC_BUCK_VCORE2_VOSEL_SLEEP_SHIFT 0 +#define PMIC_BUCK_VCORE2_TRANS_TD_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_BUCK_VCORE2_TRANS_TD_MASK 0x3 +#define PMIC_BUCK_VCORE2_TRANS_TD_SHIFT 0 +#define PMIC_BUCK_VCORE2_TRANS_CTRL_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_BUCK_VCORE2_TRANS_CTRL_MASK 0x3 +#define PMIC_BUCK_VCORE2_TRANS_CTRL_SHIFT 4 +#define PMIC_BUCK_VCORE2_TRANS_ONCE_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_BUCK_VCORE2_TRANS_ONCE_MASK 0x1 +#define PMIC_BUCK_VCORE2_TRANS_ONCE_SHIFT 6 +#define PMIC_DA_QI_VCORE2_DVS_EN_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_DA_QI_VCORE2_DVS_EN_MASK 0x1 +#define PMIC_DA_QI_VCORE2_DVS_EN_SHIFT 7 +#define PMIC_BUCK_VCORE2_VSLEEP_EN_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_BUCK_VCORE2_VSLEEP_EN_MASK 0x1 +#define PMIC_BUCK_VCORE2_VSLEEP_EN_SHIFT 8 +#define PMIC_BUCK_VCORE2_R2R_PDN_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_BUCK_VCORE2_R2R_PDN_MASK 0x1 +#define PMIC_BUCK_VCORE2_R2R_PDN_SHIFT 10 +#define PMIC_BUCK_VCORE2_VSLEEP_SEL_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_BUCK_VCORE2_VSLEEP_SEL_MASK 0x1 +#define PMIC_BUCK_VCORE2_VSLEEP_SEL_SHIFT 11 +#define PMIC_DA_NI_VCORE2_R2R_PDN_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_DA_NI_VCORE2_R2R_PDN_MASK 0x1 +#define PMIC_DA_NI_VCORE2_R2R_PDN_SHIFT 14 +#define PMIC_DA_NI_VCORE2_VSLEEP_SEL_ADDR MT6353_BUCK_VCORE2_LPW_CON0 +#define PMIC_DA_NI_VCORE2_VSLEEP_SEL_MASK 0x1 +#define PMIC_DA_NI_VCORE2_VSLEEP_SEL_SHIFT 15 +#define PMIC_BUCK_VPA_EN_ADDR MT6353_BUCK_VPA_EN_CON0 +#define PMIC_BUCK_VPA_EN_MASK 0x1 +#define PMIC_BUCK_VPA_EN_SHIFT 0 +#define PMIC_BUCK_VPA_STBTD_ADDR MT6353_BUCK_VPA_EN_CON0 +#define PMIC_BUCK_VPA_STBTD_MASK 0x3 +#define PMIC_BUCK_VPA_STBTD_SHIFT 4 +#define PMIC_DA_VPA_STB_ADDR MT6353_BUCK_VPA_EN_CON0 +#define PMIC_DA_VPA_STB_MASK 0x1 +#define PMIC_DA_VPA_STB_SHIFT 12 +#define PMIC_DA_QI_VPA_EN_ADDR MT6353_BUCK_VPA_EN_CON0 +#define PMIC_DA_QI_VPA_EN_MASK 0x1 +#define PMIC_DA_QI_VPA_EN_SHIFT 13 +#define PMIC_BUCK_VPA_SFCHG_FRATE_ADDR MT6353_BUCK_VPA_SFCHG_CON0 +#define PMIC_BUCK_VPA_SFCHG_FRATE_MASK 0x7F +#define PMIC_BUCK_VPA_SFCHG_FRATE_SHIFT 0 +#define PMIC_BUCK_VPA_SFCHG_FEN_ADDR MT6353_BUCK_VPA_SFCHG_CON0 +#define PMIC_BUCK_VPA_SFCHG_FEN_MASK 0x1 +#define PMIC_BUCK_VPA_SFCHG_FEN_SHIFT 7 +#define PMIC_BUCK_VPA_SFCHG_RRATE_ADDR MT6353_BUCK_VPA_SFCHG_CON0 +#define PMIC_BUCK_VPA_SFCHG_RRATE_MASK 0x7F +#define PMIC_BUCK_VPA_SFCHG_RRATE_SHIFT 8 +#define PMIC_BUCK_VPA_SFCHG_REN_ADDR MT6353_BUCK_VPA_SFCHG_CON0 +#define PMIC_BUCK_VPA_SFCHG_REN_MASK 0x1 +#define PMIC_BUCK_VPA_SFCHG_REN_SHIFT 15 +#define PMIC_DA_NI_VPA_VOSEL_ADDR MT6353_BUCK_VPA_VOL_CON0 +#define PMIC_DA_NI_VPA_VOSEL_MASK 0x3F +#define PMIC_DA_NI_VPA_VOSEL_SHIFT 0 +#define PMIC_BUCK_VPA_VOSEL_ADDR MT6353_BUCK_VPA_VOL_CON1 +#define PMIC_BUCK_VPA_VOSEL_MASK 0x3F +#define PMIC_BUCK_VPA_VOSEL_SHIFT 0 +#define PMIC_BUCK_VPA_TRANS_TD_ADDR MT6353_BUCK_VPA_LPW_CON0 +#define PMIC_BUCK_VPA_TRANS_TD_MASK 0x3 +#define PMIC_BUCK_VPA_TRANS_TD_SHIFT 0 +#define PMIC_BUCK_VPA_TRANS_CTRL_ADDR MT6353_BUCK_VPA_LPW_CON0 +#define PMIC_BUCK_VPA_TRANS_CTRL_MASK 0x3 +#define PMIC_BUCK_VPA_TRANS_CTRL_SHIFT 4 +#define PMIC_BUCK_VPA_TRANS_ONCE_ADDR MT6353_BUCK_VPA_LPW_CON0 +#define PMIC_BUCK_VPA_TRANS_ONCE_MASK 0x1 +#define PMIC_BUCK_VPA_TRANS_ONCE_SHIFT 6 +#define PMIC_DA_NI_VPA_DVS_TRANST_ADDR MT6353_BUCK_VPA_LPW_CON0 +#define PMIC_DA_NI_VPA_DVS_TRANST_MASK 0x1 +#define PMIC_DA_NI_VPA_DVS_TRANST_SHIFT 7 +#define PMIC_BUCK_VPA_DVS_BW_TD_ADDR MT6353_BUCK_VPA_LPW_CON0 +#define PMIC_BUCK_VPA_DVS_BW_TD_MASK 0x3 +#define PMIC_BUCK_VPA_DVS_BW_TD_SHIFT 8 +#define PMIC_BUCK_VPA_DVS_BW_CTRL_ADDR MT6353_BUCK_VPA_LPW_CON0 +#define PMIC_BUCK_VPA_DVS_BW_CTRL_MASK 0x3 +#define PMIC_BUCK_VPA_DVS_BW_CTRL_SHIFT 12 +#define PMIC_BUCK_VPA_DVS_BW_ONCE_ADDR MT6353_BUCK_VPA_LPW_CON0 +#define PMIC_BUCK_VPA_DVS_BW_ONCE_MASK 0x1 +#define PMIC_BUCK_VPA_DVS_BW_ONCE_SHIFT 14 +#define PMIC_DA_NI_VPA_DVS_BW_ADDR MT6353_BUCK_VPA_LPW_CON0 +#define PMIC_DA_NI_VPA_DVS_BW_MASK 0x1 +#define PMIC_DA_NI_VPA_DVS_BW_SHIFT 15 +#define PMIC_BUCK_K_RST_DONE_ADDR MT6353_BUCK_K_CON0 +#define PMIC_BUCK_K_RST_DONE_MASK 0x1 +#define PMIC_BUCK_K_RST_DONE_SHIFT 0 +#define PMIC_BUCK_K_MAP_SEL_ADDR MT6353_BUCK_K_CON0 +#define PMIC_BUCK_K_MAP_SEL_MASK 0x1 +#define PMIC_BUCK_K_MAP_SEL_SHIFT 1 +#define PMIC_BUCK_K_ONCE_EN_ADDR MT6353_BUCK_K_CON0 +#define PMIC_BUCK_K_ONCE_EN_MASK 0x1 +#define PMIC_BUCK_K_ONCE_EN_SHIFT 2 +#define PMIC_BUCK_K_ONCE_ADDR MT6353_BUCK_K_CON0 +#define PMIC_BUCK_K_ONCE_MASK 0x1 +#define PMIC_BUCK_K_ONCE_SHIFT 3 +#define PMIC_BUCK_K_START_MANUAL_ADDR MT6353_BUCK_K_CON0 +#define PMIC_BUCK_K_START_MANUAL_MASK 0x1 +#define PMIC_BUCK_K_START_MANUAL_SHIFT 4 +#define PMIC_BUCK_K_SRC_SEL_ADDR MT6353_BUCK_K_CON0 +#define PMIC_BUCK_K_SRC_SEL_MASK 0x1 +#define PMIC_BUCK_K_SRC_SEL_SHIFT 5 +#define PMIC_BUCK_K_AUTO_EN_ADDR MT6353_BUCK_K_CON0 +#define PMIC_BUCK_K_AUTO_EN_MASK 0x1 +#define PMIC_BUCK_K_AUTO_EN_SHIFT 6 +#define PMIC_BUCK_K_INV_ADDR MT6353_BUCK_K_CON0 +#define PMIC_BUCK_K_INV_MASK 0x1 +#define PMIC_BUCK_K_INV_SHIFT 7 +#define PMIC_BUCK_K_CONTROL_SMPS_ADDR MT6353_BUCK_K_CON1 +#define PMIC_BUCK_K_CONTROL_SMPS_MASK 0x3F +#define PMIC_BUCK_K_CONTROL_SMPS_SHIFT 8 +#define PMIC_K_RESULT_ADDR MT6353_BUCK_K_CON2 +#define PMIC_K_RESULT_MASK 0x1 +#define PMIC_K_RESULT_SHIFT 0 +#define PMIC_K_DONE_ADDR MT6353_BUCK_K_CON2 +#define PMIC_K_DONE_MASK 0x1 +#define PMIC_K_DONE_SHIFT 1 +#define PMIC_K_CONTROL_ADDR MT6353_BUCK_K_CON2 +#define PMIC_K_CONTROL_MASK 0x3F +#define PMIC_K_CONTROL_SHIFT 2 +#define PMIC_DA_QI_SMPS_OSC_CAL_ADDR MT6353_BUCK_K_CON2 +#define PMIC_DA_QI_SMPS_OSC_CAL_MASK 0x3F +#define PMIC_DA_QI_SMPS_OSC_CAL_SHIFT 8 +#define PMIC_BUCK_K_BUCK_CK_CNT_ADDR MT6353_BUCK_K_CON3 +#define PMIC_BUCK_K_BUCK_CK_CNT_MASK 0x3FF +#define PMIC_BUCK_K_BUCK_CK_CNT_SHIFT 0 +#define PMIC_WDTDBG_CLR_ADDR MT6353_WDTDBG_CON0 +#define PMIC_WDTDBG_CLR_MASK 0x1 +#define PMIC_WDTDBG_CLR_SHIFT 0 +#define PMIC_WDTDBG_CON0_RSV0_ADDR MT6353_WDTDBG_CON0 +#define PMIC_WDTDBG_CON0_RSV0_MASK 0x1 +#define PMIC_WDTDBG_CON0_RSV0_SHIFT 1 +#define PMIC_VPROC_VOSEL_WDTDBG_ADDR MT6353_WDTDBG_CON1 +#define PMIC_VPROC_VOSEL_WDTDBG_MASK 0x7F +#define PMIC_VPROC_VOSEL_WDTDBG_SHIFT 0 +#define PMIC_VCORE_VOSEL_WDTDBG_ADDR MT6353_WDTDBG_CON1 +#define PMIC_VCORE_VOSEL_WDTDBG_MASK 0x7F +#define PMIC_VCORE_VOSEL_WDTDBG_SHIFT 8 +#define PMIC_VPA_VOSEL_WDTDBG_ADDR MT6353_WDTDBG_CON2 +#define PMIC_VPA_VOSEL_WDTDBG_MASK 0x3F +#define PMIC_VPA_VOSEL_WDTDBG_SHIFT 0 +#define PMIC_VS1_VOSEL_WDTDBG_ADDR MT6353_WDTDBG_CON2 +#define PMIC_VS1_VOSEL_WDTDBG_MASK 0x7F +#define PMIC_VS1_VOSEL_WDTDBG_SHIFT 8 +#define PMIC_VSRAM_PROC_VOSEL_WDTDBG_ADDR MT6353_WDTDBG_CON3 +#define PMIC_VSRAM_PROC_VOSEL_WDTDBG_MASK 0x7F +#define PMIC_VSRAM_PROC_VOSEL_WDTDBG_SHIFT 0 +#define PMIC_RG_AUDZCDENABLE_ADDR MT6353_ZCD_CON0 +#define PMIC_RG_AUDZCDENABLE_MASK 0x1 +#define PMIC_RG_AUDZCDENABLE_SHIFT 0 +#define PMIC_RG_AUDZCDGAINSTEPTIME_ADDR MT6353_ZCD_CON0 +#define PMIC_RG_AUDZCDGAINSTEPTIME_MASK 0x7 +#define PMIC_RG_AUDZCDGAINSTEPTIME_SHIFT 1 +#define PMIC_RG_AUDZCDGAINSTEPSIZE_ADDR MT6353_ZCD_CON0 +#define PMIC_RG_AUDZCDGAINSTEPSIZE_MASK 0x3 +#define PMIC_RG_AUDZCDGAINSTEPSIZE_SHIFT 4 +#define PMIC_RG_AUDZCDTIMEOUTMODESEL_ADDR MT6353_ZCD_CON0 +#define PMIC_RG_AUDZCDTIMEOUTMODESEL_MASK 0x1 +#define PMIC_RG_AUDZCDTIMEOUTMODESEL_SHIFT 6 +#define PMIC_RG_AUDZCDCLKSEL_VAUDP15_ADDR MT6353_ZCD_CON0 +#define PMIC_RG_AUDZCDCLKSEL_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDZCDCLKSEL_VAUDP15_SHIFT 7 +#define PMIC_RG_AUDZCDMUXSEL_VAUDP15_ADDR MT6353_ZCD_CON0 +#define PMIC_RG_AUDZCDMUXSEL_VAUDP15_MASK 0x7 +#define PMIC_RG_AUDZCDMUXSEL_VAUDP15_SHIFT 8 +#define PMIC_RG_AUDLOLGAIN_ADDR MT6353_ZCD_CON1 +#define PMIC_RG_AUDLOLGAIN_MASK 0x1F +#define PMIC_RG_AUDLOLGAIN_SHIFT 0 +#define PMIC_RG_AUDLORGAIN_ADDR MT6353_ZCD_CON1 +#define PMIC_RG_AUDLORGAIN_MASK 0x1F +#define PMIC_RG_AUDLORGAIN_SHIFT 7 +#define PMIC_RG_AUDHPLGAIN_ADDR MT6353_ZCD_CON2 +#define PMIC_RG_AUDHPLGAIN_MASK 0x1F +#define PMIC_RG_AUDHPLGAIN_SHIFT 0 +#define PMIC_RG_AUDHPRGAIN_ADDR MT6353_ZCD_CON2 +#define PMIC_RG_AUDHPRGAIN_MASK 0x1F +#define PMIC_RG_AUDHPRGAIN_SHIFT 7 +#define PMIC_RG_AUDHSGAIN_ADDR MT6353_ZCD_CON3 +#define PMIC_RG_AUDHSGAIN_MASK 0x1F +#define PMIC_RG_AUDHSGAIN_SHIFT 0 +#define PMIC_RG_AUDIVLGAIN_ADDR MT6353_ZCD_CON4 +#define PMIC_RG_AUDIVLGAIN_MASK 0x7 +#define PMIC_RG_AUDIVLGAIN_SHIFT 0 +#define PMIC_RG_AUDIVRGAIN_ADDR MT6353_ZCD_CON4 +#define PMIC_RG_AUDIVRGAIN_MASK 0x7 +#define PMIC_RG_AUDIVRGAIN_SHIFT 8 +#define PMIC_RG_AUDINTGAIN1_ADDR MT6353_ZCD_CON5 +#define PMIC_RG_AUDINTGAIN1_MASK 0x3F +#define PMIC_RG_AUDINTGAIN1_SHIFT 0 +#define PMIC_RG_AUDINTGAIN2_ADDR MT6353_ZCD_CON5 +#define PMIC_RG_AUDINTGAIN2_MASK 0x3F +#define PMIC_RG_AUDINTGAIN2_SHIFT 8 +#define PMIC_LDO_LDO_RSV1_ADDR MT6353_LDO_RSV_CON0 +#define PMIC_LDO_LDO_RSV1_MASK 0x3FF +#define PMIC_LDO_LDO_RSV1_SHIFT 0 +#define PMIC_LDO_LDO_RSV0_ADDR MT6353_LDO_RSV_CON0 +#define PMIC_LDO_LDO_RSV0_MASK 0x3F +#define PMIC_LDO_LDO_RSV0_SHIFT 10 +#define PMIC_LDO_LDO_RSV1_RO_ADDR MT6353_LDO_RSV_CON1 +#define PMIC_LDO_LDO_RSV1_RO_MASK 0xFF +#define PMIC_LDO_LDO_RSV1_RO_SHIFT 0 +#define PMIC_LDO_LDO_RSV2_ADDR MT6353_LDO_RSV_CON1 +#define PMIC_LDO_LDO_RSV2_MASK 0xFF +#define PMIC_LDO_LDO_RSV2_SHIFT 8 +#define PMIC_LDO_VAUX18_AUXADC_PWDB_EN_ADDR MT6353_LDO_TOP_CON0 +#define PMIC_LDO_VAUX18_AUXADC_PWDB_EN_MASK 0x1 +#define PMIC_LDO_VAUX18_AUXADC_PWDB_EN_SHIFT 0 +#define PMIC_LDO_VIBR_THER_SDN_EN_ADDR MT6353_LDO_TOP_CON0 +#define PMIC_LDO_VIBR_THER_SDN_EN_MASK 0x1 +#define PMIC_LDO_VIBR_THER_SDN_EN_SHIFT 1 +#define PMIC_LDO_TOP_CON0_RSV_ADDR MT6353_LDO_TOP_CON0 +#define PMIC_LDO_TOP_CON0_RSV_MASK 0x3FFF +#define PMIC_LDO_TOP_CON0_RSV_SHIFT 2 +#define PMIC_LDO_VTCXO24_SWITCH_ADDR MT6353_LDO_VTCXO24_SW_CON0 +#define PMIC_LDO_VTCXO24_SWITCH_MASK 0x1 +#define PMIC_LDO_VTCXO24_SWITCH_SHIFT 4 +#define PMIC_LDO_VXO22_SWITCH_ADDR MT6353_LDO_VXO22_SW_CON0 +#define PMIC_LDO_VXO22_SWITCH_MASK 0x1 +#define PMIC_LDO_VXO22_SWITCH_SHIFT 4 +#define PMIC_LDO_DEGTD_SEL_ADDR MT6353_LDO_OCFB0 +#define PMIC_LDO_DEGTD_SEL_MASK 0x1 +#define PMIC_LDO_DEGTD_SEL_SHIFT 0 +#define PMIC_LDO_VRTC_EN_ADDR MT6353_VRTC_CON0 +#define PMIC_LDO_VRTC_EN_MASK 0x1 +#define PMIC_LDO_VRTC_EN_SHIFT 1 +#define PMIC_DA_QI_VRTC_EN_ADDR MT6353_VRTC_CON0 +#define PMIC_DA_QI_VRTC_EN_MASK 0x1 +#define PMIC_DA_QI_VRTC_EN_SHIFT 15 +#define PMIC_LDO_VCN33_EN_BT_ADDR MT6353_LDO_SHARE_VCN33_CON0 +#define PMIC_LDO_VCN33_EN_BT_MASK 0x1 +#define PMIC_LDO_VCN33_EN_BT_SHIFT 1 +#define PMIC_LDO_VCN33_EN_CTRL_BT_ADDR MT6353_LDO_SHARE_VCN33_CON0 +#define PMIC_LDO_VCN33_EN_CTRL_BT_MASK 0x1 +#define PMIC_LDO_VCN33_EN_CTRL_BT_SHIFT 3 +#define PMIC_LDO_VCN33_EN_SEL_BT_ADDR MT6353_LDO_SHARE_VCN33_CON0 +#define PMIC_LDO_VCN33_EN_SEL_BT_MASK 0x7 +#define PMIC_LDO_VCN33_EN_SEL_BT_SHIFT 11 +#define PMIC_LDO_VCN33_EN_WIFI_ADDR MT6353_LDO_SHARE_VCN33_CON1 +#define PMIC_LDO_VCN33_EN_WIFI_MASK 0x1 +#define PMIC_LDO_VCN33_EN_WIFI_SHIFT 1 +#define PMIC_LDO_VCN33_EN_CTRL_WIFI_ADDR MT6353_LDO_SHARE_VCN33_CON1 +#define PMIC_LDO_VCN33_EN_CTRL_WIFI_MASK 0x1 +#define PMIC_LDO_VCN33_EN_CTRL_WIFI_SHIFT 3 +#define PMIC_LDO_VCN33_EN_SEL_WIFI_ADDR MT6353_LDO_SHARE_VCN33_CON1 +#define PMIC_LDO_VCN33_EN_SEL_WIFI_MASK 0x7 +#define PMIC_LDO_VCN33_EN_SEL_WIFI_SHIFT 11 +#define PMIC_LDO_VCN33_LP_MODE_ADDR MT6353_LDO3_VCN33_CON0 +#define PMIC_LDO_VCN33_LP_MODE_MASK 0x1 +#define PMIC_LDO_VCN33_LP_MODE_SHIFT 0 +#define PMIC_LDO_VCN33_LP_CTRL_ADDR MT6353_LDO3_VCN33_CON0 +#define PMIC_LDO_VCN33_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VCN33_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VCN33_LP_SEL_ADDR MT6353_LDO3_VCN33_CON0 +#define PMIC_LDO_VCN33_LP_SEL_MASK 0x7 +#define PMIC_LDO_VCN33_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VCN33_MODE_ADDR MT6353_LDO3_VCN33_CON0 +#define PMIC_DA_QI_VCN33_MODE_MASK 0x1 +#define PMIC_DA_QI_VCN33_MODE_SHIFT 8 +#define PMIC_LDO_VCN33_STBTD_ADDR MT6353_LDO3_VCN33_CON0 +#define PMIC_LDO_VCN33_STBTD_MASK 0x1 +#define PMIC_LDO_VCN33_STBTD_SHIFT 9 +#define PMIC_DA_QI_VCN33_STB_ADDR MT6353_LDO3_VCN33_CON0 +#define PMIC_DA_QI_VCN33_STB_MASK 0x1 +#define PMIC_DA_QI_VCN33_STB_SHIFT 14 +#define PMIC_DA_QI_VCN33_EN_ADDR MT6353_LDO3_VCN33_CON0 +#define PMIC_DA_QI_VCN33_EN_MASK 0x1 +#define PMIC_DA_QI_VCN33_EN_SHIFT 15 +#define PMIC_LDO_VCN33_OCFB_EN_ADDR MT6353_LDO3_VCN33_OCFB_CON0 +#define PMIC_LDO_VCN33_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VCN33_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VCN33_OCFB_EN_ADDR MT6353_LDO3_VCN33_OCFB_CON0 +#define PMIC_DA_QI_VCN33_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VCN33_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VLDO28_EN_0_ADDR MT6353_LDO_SHARE_VLDO28_CON0 +#define PMIC_LDO_VLDO28_EN_0_MASK 0x1 +#define PMIC_LDO_VLDO28_EN_0_SHIFT 1 +#define PMIC_LDO_VLDO28_EN_1_ADDR MT6353_LDO_SHARE_VLDO28_CON1 +#define PMIC_LDO_VLDO28_EN_1_MASK 0x1 +#define PMIC_LDO_VLDO28_EN_1_SHIFT 1 +#define PMIC_LDO_VLDO28_LP_MODE_ADDR MT6353_LDO1_VLDO28_CON0 +#define PMIC_LDO_VLDO28_LP_MODE_MASK 0x1 +#define PMIC_LDO_VLDO28_LP_MODE_SHIFT 0 +#define PMIC_LDO_VLDO28_LP_CTRL_ADDR MT6353_LDO1_VLDO28_CON0 +#define PMIC_LDO_VLDO28_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VLDO28_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VLDO28_LP_SEL_ADDR MT6353_LDO1_VLDO28_CON0 +#define PMIC_LDO_VLDO28_LP_SEL_MASK 0x7 +#define PMIC_LDO_VLDO28_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VLDO28_MODE_ADDR MT6353_LDO1_VLDO28_CON0 +#define PMIC_DA_QI_VLDO28_MODE_MASK 0x1 +#define PMIC_DA_QI_VLDO28_MODE_SHIFT 8 +#define PMIC_LDO_VLDO28_STBTD_ADDR MT6353_LDO1_VLDO28_CON0 +#define PMIC_LDO_VLDO28_STBTD_MASK 0x1 +#define PMIC_LDO_VLDO28_STBTD_SHIFT 9 +#define PMIC_DA_QI_VLDO28_STB_ADDR MT6353_LDO1_VLDO28_CON0 +#define PMIC_DA_QI_VLDO28_STB_MASK 0x1 +#define PMIC_DA_QI_VLDO28_STB_SHIFT 14 +#define PMIC_DA_QI_VLDO28_EN_ADDR MT6353_LDO1_VLDO28_CON0 +#define PMIC_DA_QI_VLDO28_EN_MASK 0x1 +#define PMIC_DA_QI_VLDO28_EN_SHIFT 15 +#define PMIC_LDO_VLDO28_OCFB_EN_ADDR MT6353_LDO1_VLDO28_OCFB_CON0 +#define PMIC_LDO_VLDO28_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VLDO28_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VLDO28_OCFB_EN_ADDR MT6353_LDO1_VLDO28_OCFB_CON0 +#define PMIC_DA_QI_VLDO28_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VLDO28_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VLDO28_FAST_TRAN_CON0 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_EN_SHIFT 0 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_CTRL_ADDR MT6353_LDO_VLDO28_FAST_TRAN_CON0 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_CTRL_MASK 0x1 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_CTRL_SHIFT 1 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_SRCLKEN_SEL_ADDR MT6353_LDO_VLDO28_FAST_TRAN_CON0 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VLDO28_FAST_TRAN_DL_SRCLKEN_SEL_SHIFT 2 +#define PMIC_DA_QI_VLDO28_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VLDO28_FAST_TRAN_CON0 +#define PMIC_DA_QI_VLDO28_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_DA_QI_VLDO28_FAST_TRAN_DL_EN_SHIFT 5 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VLDO28_FAST_TRAN_CON0 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_EN_SHIFT 8 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_CTRL_ADDR MT6353_LDO_VLDO28_FAST_TRAN_CON0 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_CTRL_MASK 0x1 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_CTRL_SHIFT 9 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_SRCLKEN_SEL_ADDR MT6353_LDO_VLDO28_FAST_TRAN_CON0 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VLDO28_FAST_TRAN_CL_SRCLKEN_SEL_SHIFT 10 +#define PMIC_DA_QI_VLDO28_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VLDO28_FAST_TRAN_CON0 +#define PMIC_DA_QI_VLDO28_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_DA_QI_VLDO28_FAST_TRAN_CL_EN_SHIFT 13 +#define PMIC_LDO_VSRAM_PROC_VOSEL_CTRL_ADDR MT6353_LDO_VSRAM_PROC_HWM_CON0 +#define PMIC_LDO_VSRAM_PROC_VOSEL_CTRL_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_VOSEL_CTRL_SHIFT 1 +#define PMIC_LDO_VSRAM_PROC_VOSEL_SEL_ADDR MT6353_LDO_VSRAM_PROC_HWM_CON0 +#define PMIC_LDO_VSRAM_PROC_VOSEL_SEL_MASK 0x7 +#define PMIC_LDO_VSRAM_PROC_VOSEL_SEL_SHIFT 3 +#define PMIC_LDO_VSRAM_PROC_SFCHG_FRATE_ADDR MT6353_LDO_VSRAM_PROC_SFCHG_CON0 +#define PMIC_LDO_VSRAM_PROC_SFCHG_FRATE_MASK 0x7F +#define PMIC_LDO_VSRAM_PROC_SFCHG_FRATE_SHIFT 0 +#define PMIC_LDO_VSRAM_PROC_SFCHG_FEN_ADDR MT6353_LDO_VSRAM_PROC_SFCHG_CON0 +#define PMIC_LDO_VSRAM_PROC_SFCHG_FEN_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_SFCHG_FEN_SHIFT 7 +#define PMIC_LDO_VSRAM_PROC_SFCHG_RRATE_ADDR MT6353_LDO_VSRAM_PROC_SFCHG_CON0 +#define PMIC_LDO_VSRAM_PROC_SFCHG_RRATE_MASK 0x7F +#define PMIC_LDO_VSRAM_PROC_SFCHG_RRATE_SHIFT 8 +#define PMIC_LDO_VSRAM_PROC_SFCHG_REN_ADDR MT6353_LDO_VSRAM_PROC_SFCHG_CON0 +#define PMIC_LDO_VSRAM_PROC_SFCHG_REN_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_SFCHG_REN_SHIFT 15 +#define PMIC_DA_NI_VSRAM_PROC_VOSEL_ADDR MT6353_LDO_VSRAM_PROC_VOL_CON0 +#define PMIC_DA_NI_VSRAM_PROC_VOSEL_MASK 0x7F +#define PMIC_DA_NI_VSRAM_PROC_VOSEL_SHIFT 0 +#define PMIC_LDO_VSRAM_PROC_VOSEL_ADDR MT6353_LDO_VSRAM_PROC_VOL_CON1 +#define PMIC_LDO_VSRAM_PROC_VOSEL_MASK 0x7F +#define PMIC_LDO_VSRAM_PROC_VOSEL_SHIFT 0 +#define PMIC_LDO_VSRAM_PROC_VOSEL_ON_ADDR MT6353_LDO_VSRAM_PROC_VOL_CON2 +#define PMIC_LDO_VSRAM_PROC_VOSEL_ON_MASK 0x7F +#define PMIC_LDO_VSRAM_PROC_VOSEL_ON_SHIFT 0 +#define PMIC_LDO_VSRAM_PROC_VOSEL_SLEEP_ADDR MT6353_LDO_VSRAM_PROC_VOL_CON3 +#define PMIC_LDO_VSRAM_PROC_VOSEL_SLEEP_MASK 0x7F +#define PMIC_LDO_VSRAM_PROC_VOSEL_SLEEP_SHIFT 0 +#define PMIC_LDO_VSRAM_PROC_TRANS_TD_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_LDO_VSRAM_PROC_TRANS_TD_MASK 0x3 +#define PMIC_LDO_VSRAM_PROC_TRANS_TD_SHIFT 0 +#define PMIC_LDO_VSRAM_PROC_TRANS_CTRL_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_LDO_VSRAM_PROC_TRANS_CTRL_MASK 0x3 +#define PMIC_LDO_VSRAM_PROC_TRANS_CTRL_SHIFT 4 +#define PMIC_LDO_VSRAM_PROC_TRANS_ONCE_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_LDO_VSRAM_PROC_TRANS_ONCE_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_TRANS_ONCE_SHIFT 6 +#define PMIC_DA_QI_VSRAM_PROC_DVS_EN_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_DA_QI_VSRAM_PROC_DVS_EN_MASK 0x1 +#define PMIC_DA_QI_VSRAM_PROC_DVS_EN_SHIFT 7 +#define PMIC_LDO_VSRAM_PROC_VSLEEP_EN_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_LDO_VSRAM_PROC_VSLEEP_EN_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_VSLEEP_EN_SHIFT 8 +#define PMIC_LDO_VSRAM_PROC_R2R_PDN_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_LDO_VSRAM_PROC_R2R_PDN_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_R2R_PDN_SHIFT 10 +#define PMIC_LDO_VSRAM_PROC_VSLEEP_SEL_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_LDO_VSRAM_PROC_VSLEEP_SEL_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_VSLEEP_SEL_SHIFT 11 +#define PMIC_DA_NI_VSRAM_PROC_R2R_PDN_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_DA_NI_VSRAM_PROC_R2R_PDN_MASK 0x1 +#define PMIC_DA_NI_VSRAM_PROC_R2R_PDN_SHIFT 14 +#define PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_ADDR MT6353_LDO_VSRAM_PROC_LPW_CON0 +#define PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_MASK 0x1 +#define PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_SHIFT 15 +#define PMIC_LDO_BATON_HT_EN_ADDR MT6353_LDO_BATON_CON0 +#define PMIC_LDO_BATON_HT_EN_MASK 0x1 +#define PMIC_LDO_BATON_HT_EN_SHIFT 0 +#define PMIC_LDO_BATON_HT_EN_DLY_TIME_ADDR MT6353_LDO_BATON_CON0 +#define PMIC_LDO_BATON_HT_EN_DLY_TIME_MASK 0x1 +#define PMIC_LDO_BATON_HT_EN_DLY_TIME_SHIFT 4 +#define PMIC_DA_QI_BATON_HT_EN_ADDR MT6353_LDO_BATON_CON0 +#define PMIC_DA_QI_BATON_HT_EN_MASK 0x1 +#define PMIC_DA_QI_BATON_HT_EN_SHIFT 5 +#define PMIC_LDO_TREF_EN_ADDR MT6353_LDO2_TREF_CON0 +#define PMIC_LDO_TREF_EN_MASK 0x1 +#define PMIC_LDO_TREF_EN_SHIFT 1 +#define PMIC_LDO_TREF_EN_CTRL_ADDR MT6353_LDO2_TREF_CON0 +#define PMIC_LDO_TREF_EN_CTRL_MASK 0x1 +#define PMIC_LDO_TREF_EN_CTRL_SHIFT 3 +#define PMIC_LDO_TREF_EN_SEL_ADDR MT6353_LDO2_TREF_CON0 +#define PMIC_LDO_TREF_EN_SEL_MASK 0x7 +#define PMIC_LDO_TREF_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_TREF_EN_ADDR MT6353_LDO2_TREF_CON0 +#define PMIC_DA_QI_TREF_EN_MASK 0x1 +#define PMIC_DA_QI_TREF_EN_SHIFT 15 +#define PMIC_LDO_VTCXO28_LP_MODE_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_LDO_VTCXO28_LP_MODE_MASK 0x1 +#define PMIC_LDO_VTCXO28_LP_MODE_SHIFT 0 +#define PMIC_LDO_VTCXO28_EN_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_LDO_VTCXO28_EN_MASK 0x1 +#define PMIC_LDO_VTCXO28_EN_SHIFT 1 +#define PMIC_LDO_VTCXO28_LP_CTRL_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_LDO_VTCXO28_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VTCXO28_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VTCXO28_EN_CTRL_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_LDO_VTCXO28_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VTCXO28_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VTCXO28_LP_SEL_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_LDO_VTCXO28_LP_SEL_MASK 0x7 +#define PMIC_LDO_VTCXO28_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VTCXO28_MODE_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_DA_QI_VTCXO28_MODE_MASK 0x1 +#define PMIC_DA_QI_VTCXO28_MODE_SHIFT 8 +#define PMIC_LDO_VTCXO28_STBTD_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_LDO_VTCXO28_STBTD_MASK 0x1 +#define PMIC_LDO_VTCXO28_STBTD_SHIFT 9 +#define PMIC_LDO_VTCXO28_EN_SEL_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_LDO_VTCXO28_EN_SEL_MASK 0x7 +#define PMIC_LDO_VTCXO28_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VTCXO28_STB_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_DA_QI_VTCXO28_STB_MASK 0x1 +#define PMIC_DA_QI_VTCXO28_STB_SHIFT 14 +#define PMIC_DA_QI_VTCXO28_EN_ADDR MT6353_LDO3_VTCXO28_CON0 +#define PMIC_DA_QI_VTCXO28_EN_MASK 0x1 +#define PMIC_DA_QI_VTCXO28_EN_SHIFT 15 +#define PMIC_LDO_VTCXO28_OCFB_EN_ADDR MT6353_LDO3_VTCXO28_OCFB_CON0 +#define PMIC_LDO_VTCXO28_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VTCXO28_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VTCXO28_OCFB_EN_ADDR MT6353_LDO3_VTCXO28_OCFB_CON0 +#define PMIC_DA_QI_VTCXO28_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VTCXO28_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VTCXO24_LP_MODE_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_LDO_VTCXO24_LP_MODE_MASK 0x1 +#define PMIC_LDO_VTCXO24_LP_MODE_SHIFT 0 +#define PMIC_LDO_VTCXO24_EN_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_LDO_VTCXO24_EN_MASK 0x1 +#define PMIC_LDO_VTCXO24_EN_SHIFT 1 +#define PMIC_LDO_VTCXO24_LP_CTRL_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_LDO_VTCXO24_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VTCXO24_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VTCXO24_EN_CTRL_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_LDO_VTCXO24_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VTCXO24_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VTCXO24_LP_SEL_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_LDO_VTCXO24_LP_SEL_MASK 0x7 +#define PMIC_LDO_VTCXO24_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VTCXO24_MODE_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_DA_QI_VTCXO24_MODE_MASK 0x1 +#define PMIC_DA_QI_VTCXO24_MODE_SHIFT 8 +#define PMIC_LDO_VTCXO24_STBTD_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_LDO_VTCXO24_STBTD_MASK 0x1 +#define PMIC_LDO_VTCXO24_STBTD_SHIFT 9 +#define PMIC_LDO_VTCXO24_EN_SEL_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_LDO_VTCXO24_EN_SEL_MASK 0x7 +#define PMIC_LDO_VTCXO24_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VTCXO24_STB_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_DA_QI_VTCXO24_STB_MASK 0x1 +#define PMIC_DA_QI_VTCXO24_STB_SHIFT 14 +#define PMIC_DA_QI_VTCXO24_EN_ADDR MT6353_LDO3_VTCXO24_CON0 +#define PMIC_DA_QI_VTCXO24_EN_MASK 0x1 +#define PMIC_DA_QI_VTCXO24_EN_SHIFT 15 +#define PMIC_LDO_VTCXO24_OCFB_EN_ADDR MT6353_LDO3_VTCXO24_OCFB_CON0 +#define PMIC_LDO_VTCXO24_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VTCXO24_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VTCXO24_OCFB_EN_ADDR MT6353_LDO3_VTCXO24_OCFB_CON0 +#define PMIC_DA_QI_VTCXO24_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VTCXO24_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VXO22_LP_MODE_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_LDO_VXO22_LP_MODE_MASK 0x1 +#define PMIC_LDO_VXO22_LP_MODE_SHIFT 0 +#define PMIC_LDO_VXO22_EN_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_LDO_VXO22_EN_MASK 0x1 +#define PMIC_LDO_VXO22_EN_SHIFT 1 +#define PMIC_LDO_VXO22_LP_CTRL_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_LDO_VXO22_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VXO22_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VXO22_EN_CTRL_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_LDO_VXO22_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VXO22_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VXO22_LP_SEL_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_LDO_VXO22_LP_SEL_MASK 0x7 +#define PMIC_LDO_VXO22_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VXO22_MODE_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_DA_QI_VXO22_MODE_MASK 0x1 +#define PMIC_DA_QI_VXO22_MODE_SHIFT 8 +#define PMIC_LDO_VXO22_STBTD_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_LDO_VXO22_STBTD_MASK 0x1 +#define PMIC_LDO_VXO22_STBTD_SHIFT 9 +#define PMIC_LDO_VXO22_EN_SEL_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_LDO_VXO22_EN_SEL_MASK 0x7 +#define PMIC_LDO_VXO22_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VXO22_STB_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_DA_QI_VXO22_STB_MASK 0x1 +#define PMIC_DA_QI_VXO22_STB_SHIFT 14 +#define PMIC_DA_QI_VXO22_EN_ADDR MT6353_LDO3_VXO22_CON0 +#define PMIC_DA_QI_VXO22_EN_MASK 0x1 +#define PMIC_DA_QI_VXO22_EN_SHIFT 15 +#define PMIC_LDO_VXO22_OCFB_EN_ADDR MT6353_LDO3_VXO22_OCFB_CON0 +#define PMIC_LDO_VXO22_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VXO22_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VXO22_OCFB_EN_ADDR MT6353_LDO3_VXO22_OCFB_CON0 +#define PMIC_DA_QI_VXO22_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VXO22_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VRF18_LP_MODE_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_LDO_VRF18_LP_MODE_MASK 0x1 +#define PMIC_LDO_VRF18_LP_MODE_SHIFT 0 +#define PMIC_LDO_VRF18_EN_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_LDO_VRF18_EN_MASK 0x1 +#define PMIC_LDO_VRF18_EN_SHIFT 1 +#define PMIC_LDO_VRF18_LP_CTRL_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_LDO_VRF18_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VRF18_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VRF18_EN_CTRL_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_LDO_VRF18_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VRF18_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VRF18_LP_SEL_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_LDO_VRF18_LP_SEL_MASK 0x7 +#define PMIC_LDO_VRF18_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VRF18_MODE_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_DA_QI_VRF18_MODE_MASK 0x1 +#define PMIC_DA_QI_VRF18_MODE_SHIFT 8 +#define PMIC_LDO_VRF18_STBTD_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_LDO_VRF18_STBTD_MASK 0x1 +#define PMIC_LDO_VRF18_STBTD_SHIFT 9 +#define PMIC_LDO_VRF18_EN_SEL_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_LDO_VRF18_EN_SEL_MASK 0x7 +#define PMIC_LDO_VRF18_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VRF18_STB_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_DA_QI_VRF18_STB_MASK 0x1 +#define PMIC_DA_QI_VRF18_STB_SHIFT 14 +#define PMIC_DA_QI_VRF18_EN_ADDR MT6353_LDO3_VRF18_CON0 +#define PMIC_DA_QI_VRF18_EN_MASK 0x1 +#define PMIC_DA_QI_VRF18_EN_SHIFT 15 +#define PMIC_LDO_VRF18_OCFB_EN_ADDR MT6353_LDO3_VRF18_OCFB_CON0 +#define PMIC_LDO_VRF18_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VRF18_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VRF18_OCFB_EN_ADDR MT6353_LDO3_VRF18_OCFB_CON0 +#define PMIC_DA_QI_VRF18_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VRF18_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VRF12_LP_MODE_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_LDO_VRF12_LP_MODE_MASK 0x1 +#define PMIC_LDO_VRF12_LP_MODE_SHIFT 0 +#define PMIC_LDO_VRF12_EN_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_LDO_VRF12_EN_MASK 0x1 +#define PMIC_LDO_VRF12_EN_SHIFT 1 +#define PMIC_LDO_VRF12_LP_CTRL_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_LDO_VRF12_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VRF12_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VRF12_EN_CTRL_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_LDO_VRF12_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VRF12_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VRF12_LP_SEL_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_LDO_VRF12_LP_SEL_MASK 0x7 +#define PMIC_LDO_VRF12_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VRF12_MODE_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_DA_QI_VRF12_MODE_MASK 0x1 +#define PMIC_DA_QI_VRF12_MODE_SHIFT 8 +#define PMIC_LDO_VRF12_STBTD_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_LDO_VRF12_STBTD_MASK 0x1 +#define PMIC_LDO_VRF12_STBTD_SHIFT 9 +#define PMIC_LDO_VRF12_EN_SEL_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_LDO_VRF12_EN_SEL_MASK 0x7 +#define PMIC_LDO_VRF12_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VRF12_STB_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_DA_QI_VRF12_STB_MASK 0x1 +#define PMIC_DA_QI_VRF12_STB_SHIFT 14 +#define PMIC_DA_QI_VRF12_EN_ADDR MT6353_LDO3_VRF12_CON0 +#define PMIC_DA_QI_VRF12_EN_MASK 0x1 +#define PMIC_DA_QI_VRF12_EN_SHIFT 15 +#define PMIC_LDO_VRF12_OCFB_EN_ADDR MT6353_LDO3_VRF12_OCFB_CON0 +#define PMIC_LDO_VRF12_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VRF12_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VRF12_OCFB_EN_ADDR MT6353_LDO3_VRF12_OCFB_CON0 +#define PMIC_DA_QI_VRF12_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VRF12_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VRF12_FAST_TRAN_CON0 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_EN_SHIFT 0 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_CTRL_ADDR MT6353_LDO_VRF12_FAST_TRAN_CON0 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_CTRL_MASK 0x1 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_CTRL_SHIFT 1 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_SRCLKEN_SEL_ADDR MT6353_LDO_VRF12_FAST_TRAN_CON0 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VRF12_FAST_TRAN_DL_SRCLKEN_SEL_SHIFT 2 +#define PMIC_DA_QI_VRF12_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VRF12_FAST_TRAN_CON0 +#define PMIC_DA_QI_VRF12_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_DA_QI_VRF12_FAST_TRAN_DL_EN_SHIFT 5 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VRF12_FAST_TRAN_CON0 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_EN_SHIFT 8 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_CTRL_ADDR MT6353_LDO_VRF12_FAST_TRAN_CON0 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_CTRL_MASK 0x1 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_CTRL_SHIFT 9 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_SRCLKEN_SEL_ADDR MT6353_LDO_VRF12_FAST_TRAN_CON0 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VRF12_FAST_TRAN_CL_SRCLKEN_SEL_SHIFT 10 +#define PMIC_DA_QI_VRF12_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VRF12_FAST_TRAN_CON0 +#define PMIC_DA_QI_VRF12_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_DA_QI_VRF12_FAST_TRAN_CL_EN_SHIFT 13 +#define PMIC_LDO_VCN28_LP_MODE_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_LDO_VCN28_LP_MODE_MASK 0x1 +#define PMIC_LDO_VCN28_LP_MODE_SHIFT 0 +#define PMIC_LDO_VCN28_EN_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_LDO_VCN28_EN_MASK 0x1 +#define PMIC_LDO_VCN28_EN_SHIFT 1 +#define PMIC_LDO_VCN28_LP_CTRL_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_LDO_VCN28_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VCN28_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VCN28_EN_CTRL_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_LDO_VCN28_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VCN28_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VCN28_LP_SEL_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_LDO_VCN28_LP_SEL_MASK 0x7 +#define PMIC_LDO_VCN28_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VCN28_MODE_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_DA_QI_VCN28_MODE_MASK 0x1 +#define PMIC_DA_QI_VCN28_MODE_SHIFT 8 +#define PMIC_LDO_VCN28_STBTD_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_LDO_VCN28_STBTD_MASK 0x1 +#define PMIC_LDO_VCN28_STBTD_SHIFT 9 +#define PMIC_LDO_VCN28_EN_SEL_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_LDO_VCN28_EN_SEL_MASK 0x7 +#define PMIC_LDO_VCN28_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VCN28_STB_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_DA_QI_VCN28_STB_MASK 0x1 +#define PMIC_DA_QI_VCN28_STB_SHIFT 14 +#define PMIC_DA_QI_VCN28_EN_ADDR MT6353_LDO3_VCN28_CON0 +#define PMIC_DA_QI_VCN28_EN_MASK 0x1 +#define PMIC_DA_QI_VCN28_EN_SHIFT 15 +#define PMIC_LDO_VCN28_OCFB_EN_ADDR MT6353_LDO3_VCN28_OCFB_CON0 +#define PMIC_LDO_VCN28_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VCN28_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VCN28_OCFB_EN_ADDR MT6353_LDO3_VCN28_OCFB_CON0 +#define PMIC_DA_QI_VCN28_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VCN28_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VCN18_LP_MODE_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_LDO_VCN18_LP_MODE_MASK 0x1 +#define PMIC_LDO_VCN18_LP_MODE_SHIFT 0 +#define PMIC_LDO_VCN18_EN_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_LDO_VCN18_EN_MASK 0x1 +#define PMIC_LDO_VCN18_EN_SHIFT 1 +#define PMIC_LDO_VCN18_LP_CTRL_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_LDO_VCN18_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VCN18_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VCN18_EN_CTRL_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_LDO_VCN18_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VCN18_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VCN18_LP_SEL_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_LDO_VCN18_LP_SEL_MASK 0x7 +#define PMIC_LDO_VCN18_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VCN18_MODE_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_DA_QI_VCN18_MODE_MASK 0x1 +#define PMIC_DA_QI_VCN18_MODE_SHIFT 8 +#define PMIC_LDO_VCN18_STBTD_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_LDO_VCN18_STBTD_MASK 0x1 +#define PMIC_LDO_VCN18_STBTD_SHIFT 9 +#define PMIC_LDO_VCN18_EN_SEL_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_LDO_VCN18_EN_SEL_MASK 0x7 +#define PMIC_LDO_VCN18_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VCN18_STB_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_DA_QI_VCN18_STB_MASK 0x1 +#define PMIC_DA_QI_VCN18_STB_SHIFT 14 +#define PMIC_DA_QI_VCN18_EN_ADDR MT6353_LDO3_VCN18_CON0 +#define PMIC_DA_QI_VCN18_EN_MASK 0x1 +#define PMIC_DA_QI_VCN18_EN_SHIFT 15 +#define PMIC_LDO_VCN18_OCFB_EN_ADDR MT6353_LDO3_VCN18_OCFB_CON0 +#define PMIC_LDO_VCN18_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VCN18_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VCN18_OCFB_EN_ADDR MT6353_LDO3_VCN18_OCFB_CON0 +#define PMIC_DA_QI_VCN18_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VCN18_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VCAMA_LP_MODE_ADDR MT6353_LDO0_VCAMA_CON0 +#define PMIC_LDO_VCAMA_LP_MODE_MASK 0x1 +#define PMIC_LDO_VCAMA_LP_MODE_SHIFT 0 +#define PMIC_LDO_VCAMA_EN_ADDR MT6353_LDO0_VCAMA_CON0 +#define PMIC_LDO_VCAMA_EN_MASK 0x1 +#define PMIC_LDO_VCAMA_EN_SHIFT 1 +#define PMIC_DA_QI_VCAMA_MODE_ADDR MT6353_LDO0_VCAMA_CON0 +#define PMIC_DA_QI_VCAMA_MODE_MASK 0x1 +#define PMIC_DA_QI_VCAMA_MODE_SHIFT 8 +#define PMIC_LDO_VCAMA_STBTD_ADDR MT6353_LDO0_VCAMA_CON0 +#define PMIC_LDO_VCAMA_STBTD_MASK 0x1 +#define PMIC_LDO_VCAMA_STBTD_SHIFT 9 +#define PMIC_DA_QI_VCAMA_STB_ADDR MT6353_LDO0_VCAMA_CON0 +#define PMIC_DA_QI_VCAMA_STB_MASK 0x1 +#define PMIC_DA_QI_VCAMA_STB_SHIFT 14 +#define PMIC_DA_QI_VCAMA_EN_ADDR MT6353_LDO0_VCAMA_CON0 +#define PMIC_DA_QI_VCAMA_EN_MASK 0x1 +#define PMIC_DA_QI_VCAMA_EN_SHIFT 15 +#define PMIC_LDO_VCAMA_OCFB_EN_ADDR MT6353_LDO0_VCAMA_OCFB_CON0 +#define PMIC_LDO_VCAMA_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VCAMA_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VCAMA_OCFB_EN_ADDR MT6353_LDO0_VCAMA_OCFB_CON0 +#define PMIC_DA_QI_VCAMA_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VCAMA_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VCAMIO_LP_MODE_ADDR MT6353_LDO0_VCAMIO_CON0 +#define PMIC_LDO_VCAMIO_LP_MODE_MASK 0x1 +#define PMIC_LDO_VCAMIO_LP_MODE_SHIFT 0 +#define PMIC_LDO_VCAMIO_EN_ADDR MT6353_LDO0_VCAMIO_CON0 +#define PMIC_LDO_VCAMIO_EN_MASK 0x1 +#define PMIC_LDO_VCAMIO_EN_SHIFT 1 +#define PMIC_DA_QI_VCAMIO_MODE_ADDR MT6353_LDO0_VCAMIO_CON0 +#define PMIC_DA_QI_VCAMIO_MODE_MASK 0x1 +#define PMIC_DA_QI_VCAMIO_MODE_SHIFT 8 +#define PMIC_LDO_VCAMIO_STBTD_ADDR MT6353_LDO0_VCAMIO_CON0 +#define PMIC_LDO_VCAMIO_STBTD_MASK 0x1 +#define PMIC_LDO_VCAMIO_STBTD_SHIFT 9 +#define PMIC_DA_QI_VCAMIO_STB_ADDR MT6353_LDO0_VCAMIO_CON0 +#define PMIC_DA_QI_VCAMIO_STB_MASK 0x1 +#define PMIC_DA_QI_VCAMIO_STB_SHIFT 14 +#define PMIC_DA_QI_VCAMIO_EN_ADDR MT6353_LDO0_VCAMIO_CON0 +#define PMIC_DA_QI_VCAMIO_EN_MASK 0x1 +#define PMIC_DA_QI_VCAMIO_EN_SHIFT 15 +#define PMIC_LDO_VCAMIO_OCFB_EN_ADDR MT6353_LDO0_VCAMIO_OCFB_CON0 +#define PMIC_LDO_VCAMIO_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VCAMIO_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VCAMIO_OCFB_EN_ADDR MT6353_LDO0_VCAMIO_OCFB_CON0 +#define PMIC_DA_QI_VCAMIO_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VCAMIO_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VCAMD_LP_MODE_ADDR MT6353_LDO0_VCAMD_CON0 +#define PMIC_LDO_VCAMD_LP_MODE_MASK 0x1 +#define PMIC_LDO_VCAMD_LP_MODE_SHIFT 0 +#define PMIC_LDO_VCAMD_EN_ADDR MT6353_LDO0_VCAMD_CON0 +#define PMIC_LDO_VCAMD_EN_MASK 0x1 +#define PMIC_LDO_VCAMD_EN_SHIFT 1 +#define PMIC_DA_QI_VCAMD_MODE_ADDR MT6353_LDO0_VCAMD_CON0 +#define PMIC_DA_QI_VCAMD_MODE_MASK 0x1 +#define PMIC_DA_QI_VCAMD_MODE_SHIFT 8 +#define PMIC_LDO_VCAMD_STBTD_ADDR MT6353_LDO0_VCAMD_CON0 +#define PMIC_LDO_VCAMD_STBTD_MASK 0x1 +#define PMIC_LDO_VCAMD_STBTD_SHIFT 9 +#define PMIC_DA_QI_VCAMD_STB_ADDR MT6353_LDO0_VCAMD_CON0 +#define PMIC_DA_QI_VCAMD_STB_MASK 0x1 +#define PMIC_DA_QI_VCAMD_STB_SHIFT 14 +#define PMIC_DA_QI_VCAMD_EN_ADDR MT6353_LDO0_VCAMD_CON0 +#define PMIC_DA_QI_VCAMD_EN_MASK 0x1 +#define PMIC_DA_QI_VCAMD_EN_SHIFT 15 +#define PMIC_LDO_VCAMD_OCFB_EN_ADDR MT6353_LDO0_VCAMD_OCFB_CON0 +#define PMIC_LDO_VCAMD_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VCAMD_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VCAMD_OCFB_EN_ADDR MT6353_LDO0_VCAMD_OCFB_CON0 +#define PMIC_DA_QI_VCAMD_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VCAMD_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VAUX18_LP_MODE_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_LDO_VAUX18_LP_MODE_MASK 0x1 +#define PMIC_LDO_VAUX18_LP_MODE_SHIFT 0 +#define PMIC_LDO_VAUX18_EN_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_LDO_VAUX18_EN_MASK 0x1 +#define PMIC_LDO_VAUX18_EN_SHIFT 1 +#define PMIC_LDO_VAUX18_LP_CTRL_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_LDO_VAUX18_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VAUX18_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VAUX18_EN_CTRL_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_LDO_VAUX18_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VAUX18_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VAUX18_LP_SEL_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_LDO_VAUX18_LP_SEL_MASK 0x7 +#define PMIC_LDO_VAUX18_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VAUX18_MODE_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_DA_QI_VAUX18_MODE_MASK 0x1 +#define PMIC_DA_QI_VAUX18_MODE_SHIFT 8 +#define PMIC_LDO_VAUX18_STBTD_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_LDO_VAUX18_STBTD_MASK 0x1 +#define PMIC_LDO_VAUX18_STBTD_SHIFT 9 +#define PMIC_LDO_VAUX18_EN_SEL_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_LDO_VAUX18_EN_SEL_MASK 0x7 +#define PMIC_LDO_VAUX18_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VAUX18_STB_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_DA_QI_VAUX18_STB_MASK 0x1 +#define PMIC_DA_QI_VAUX18_STB_SHIFT 14 +#define PMIC_DA_QI_VAUX18_EN_ADDR MT6353_LDO3_VAUX18_CON0 +#define PMIC_DA_QI_VAUX18_EN_MASK 0x1 +#define PMIC_DA_QI_VAUX18_EN_SHIFT 15 +#define PMIC_LDO_VAUX18_OCFB_EN_ADDR MT6353_LDO3_VAUX18_OCFB_CON0 +#define PMIC_LDO_VAUX18_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VAUX18_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VAUX18_OCFB_EN_ADDR MT6353_LDO3_VAUX18_OCFB_CON0 +#define PMIC_DA_QI_VAUX18_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VAUX18_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VAUD28_LP_MODE_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_LDO_VAUD28_LP_MODE_MASK 0x1 +#define PMIC_LDO_VAUD28_LP_MODE_SHIFT 0 +#define PMIC_LDO_VAUD28_EN_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_LDO_VAUD28_EN_MASK 0x1 +#define PMIC_LDO_VAUD28_EN_SHIFT 1 +#define PMIC_LDO_VAUD28_LP_CTRL_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_LDO_VAUD28_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VAUD28_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VAUD28_EN_CTRL_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_LDO_VAUD28_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VAUD28_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VAUD28_LP_SEL_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_LDO_VAUD28_LP_SEL_MASK 0x7 +#define PMIC_LDO_VAUD28_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VAUD28_MODE_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_DA_QI_VAUD28_MODE_MASK 0x1 +#define PMIC_DA_QI_VAUD28_MODE_SHIFT 8 +#define PMIC_LDO_VAUD28_STBTD_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_LDO_VAUD28_STBTD_MASK 0x1 +#define PMIC_LDO_VAUD28_STBTD_SHIFT 9 +#define PMIC_LDO_VAUD28_EN_SEL_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_LDO_VAUD28_EN_SEL_MASK 0x7 +#define PMIC_LDO_VAUD28_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VAUD28_STB_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_DA_QI_VAUD28_STB_MASK 0x1 +#define PMIC_DA_QI_VAUD28_STB_SHIFT 14 +#define PMIC_DA_QI_VAUD28_EN_ADDR MT6353_LDO3_VAUD28_CON0 +#define PMIC_DA_QI_VAUD28_EN_MASK 0x1 +#define PMIC_DA_QI_VAUD28_EN_SHIFT 15 +#define PMIC_LDO_VAUD28_OCFB_EN_ADDR MT6353_LDO3_VAUD28_OCFB_CON0 +#define PMIC_LDO_VAUD28_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VAUD28_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VAUD28_OCFB_EN_ADDR MT6353_LDO3_VAUD28_OCFB_CON0 +#define PMIC_DA_QI_VAUD28_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VAUD28_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VSRAM_PROC_LP_MODE_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_LDO_VSRAM_PROC_LP_MODE_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_LP_MODE_SHIFT 0 +#define PMIC_LDO_VSRAM_PROC_EN_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_LDO_VSRAM_PROC_EN_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_EN_SHIFT 1 +#define PMIC_LDO_VSRAM_PROC_LP_CTRL_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_LDO_VSRAM_PROC_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VSRAM_PROC_EN_CTRL_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_LDO_VSRAM_PROC_EN_CTRL_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_EN_CTRL_SHIFT 3 +#define PMIC_LDO_VSRAM_PROC_LP_SEL_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_LDO_VSRAM_PROC_LP_SEL_MASK 0x7 +#define PMIC_LDO_VSRAM_PROC_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VSRAM_PROC_MODE_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_DA_QI_VSRAM_PROC_MODE_MASK 0x1 +#define PMIC_DA_QI_VSRAM_PROC_MODE_SHIFT 8 +#define PMIC_LDO_VSRAM_PROC_STBTD_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_LDO_VSRAM_PROC_STBTD_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_STBTD_SHIFT 9 +#define PMIC_LDO_VSRAM_PROC_EN_SEL_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_LDO_VSRAM_PROC_EN_SEL_MASK 0x7 +#define PMIC_LDO_VSRAM_PROC_EN_SEL_SHIFT 11 +#define PMIC_DA_QI_VSRAM_PROC_STB_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_DA_QI_VSRAM_PROC_STB_MASK 0x1 +#define PMIC_DA_QI_VSRAM_PROC_STB_SHIFT 14 +#define PMIC_DA_QI_VSRAM_PROC_EN_ADDR MT6353_LDO3_VSRAM_PROC_CON0 +#define PMIC_DA_QI_VSRAM_PROC_EN_MASK 0x1 +#define PMIC_DA_QI_VSRAM_PROC_EN_SHIFT 15 +#define PMIC_LDO_VSRAM_PROC_OCFB_EN_ADDR MT6353_LDO3_VSRAM_PROC_OCFB_CON0 +#define PMIC_LDO_VSRAM_PROC_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VSRAM_PROC_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VSRAM_PROC_OCFB_EN_ADDR MT6353_LDO3_VSRAM_PROC_OCFB_CON0 +#define PMIC_DA_QI_VSRAM_PROC_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VSRAM_PROC_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VDRAM_LP_MODE_ADDR MT6353_LDO1_VDRAM_CON0 +#define PMIC_LDO_VDRAM_LP_MODE_MASK 0x1 +#define PMIC_LDO_VDRAM_LP_MODE_SHIFT 0 +#define PMIC_LDO_VDRAM_EN_ADDR MT6353_LDO1_VDRAM_CON0 +#define PMIC_LDO_VDRAM_EN_MASK 0x1 +#define PMIC_LDO_VDRAM_EN_SHIFT 1 +#define PMIC_LDO_VDRAM_LP_CTRL_ADDR MT6353_LDO1_VDRAM_CON0 +#define PMIC_LDO_VDRAM_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VDRAM_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VDRAM_LP_SEL_ADDR MT6353_LDO1_VDRAM_CON0 +#define PMIC_LDO_VDRAM_LP_SEL_MASK 0x7 +#define PMIC_LDO_VDRAM_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VDRAM_MODE_ADDR MT6353_LDO1_VDRAM_CON0 +#define PMIC_DA_QI_VDRAM_MODE_MASK 0x1 +#define PMIC_DA_QI_VDRAM_MODE_SHIFT 8 +#define PMIC_LDO_VDRAM_STBTD_ADDR MT6353_LDO1_VDRAM_CON0 +#define PMIC_LDO_VDRAM_STBTD_MASK 0x1 +#define PMIC_LDO_VDRAM_STBTD_SHIFT 9 +#define PMIC_DA_QI_VDRAM_STB_ADDR MT6353_LDO1_VDRAM_CON0 +#define PMIC_DA_QI_VDRAM_STB_MASK 0x1 +#define PMIC_DA_QI_VDRAM_STB_SHIFT 14 +#define PMIC_DA_QI_VDRAM_EN_ADDR MT6353_LDO1_VDRAM_CON0 +#define PMIC_DA_QI_VDRAM_EN_MASK 0x1 +#define PMIC_DA_QI_VDRAM_EN_SHIFT 15 +#define PMIC_LDO_VDRAM_OCFB_EN_ADDR MT6353_LDO1_VDRAM_OCFB_CON0 +#define PMIC_LDO_VDRAM_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VDRAM_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VDRAM_OCFB_EN_ADDR MT6353_LDO1_VDRAM_OCFB_CON0 +#define PMIC_DA_QI_VDRAM_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VDRAM_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VDRAM_FAST_TRAN_CON0 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_EN_SHIFT 0 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_CTRL_ADDR MT6353_LDO_VDRAM_FAST_TRAN_CON0 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_CTRL_MASK 0x1 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_CTRL_SHIFT 1 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_SRCLKEN_SEL_ADDR MT6353_LDO_VDRAM_FAST_TRAN_CON0 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VDRAM_FAST_TRAN_DL_SRCLKEN_SEL_SHIFT 2 +#define PMIC_DA_QI_VDRAM_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VDRAM_FAST_TRAN_CON0 +#define PMIC_DA_QI_VDRAM_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_DA_QI_VDRAM_FAST_TRAN_DL_EN_SHIFT 5 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VDRAM_FAST_TRAN_CON0 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_EN_SHIFT 8 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_CTRL_ADDR MT6353_LDO_VDRAM_FAST_TRAN_CON0 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_CTRL_MASK 0x1 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_CTRL_SHIFT 9 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_SRCLKEN_SEL_ADDR MT6353_LDO_VDRAM_FAST_TRAN_CON0 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VDRAM_FAST_TRAN_CL_SRCLKEN_SEL_SHIFT 10 +#define PMIC_DA_QI_VDRAM_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VDRAM_FAST_TRAN_CON0 +#define PMIC_DA_QI_VDRAM_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_DA_QI_VDRAM_FAST_TRAN_CL_EN_SHIFT 13 +#define PMIC_LDO_VSIM1_LP_MODE_ADDR MT6353_LDO1_VSIM1_CON0 +#define PMIC_LDO_VSIM1_LP_MODE_MASK 0x1 +#define PMIC_LDO_VSIM1_LP_MODE_SHIFT 0 +#define PMIC_LDO_VSIM1_EN_ADDR MT6353_LDO1_VSIM1_CON0 +#define PMIC_LDO_VSIM1_EN_MASK 0x1 +#define PMIC_LDO_VSIM1_EN_SHIFT 1 +#define PMIC_LDO_VSIM1_LP_CTRL_ADDR MT6353_LDO1_VSIM1_CON0 +#define PMIC_LDO_VSIM1_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VSIM1_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VSIM1_LP_SEL_ADDR MT6353_LDO1_VSIM1_CON0 +#define PMIC_LDO_VSIM1_LP_SEL_MASK 0x7 +#define PMIC_LDO_VSIM1_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VSIM1_MODE_ADDR MT6353_LDO1_VSIM1_CON0 +#define PMIC_DA_QI_VSIM1_MODE_MASK 0x1 +#define PMIC_DA_QI_VSIM1_MODE_SHIFT 8 +#define PMIC_LDO_VSIM1_STBTD_ADDR MT6353_LDO1_VSIM1_CON0 +#define PMIC_LDO_VSIM1_STBTD_MASK 0x1 +#define PMIC_LDO_VSIM1_STBTD_SHIFT 9 +#define PMIC_DA_QI_VSIM1_STB_ADDR MT6353_LDO1_VSIM1_CON0 +#define PMIC_DA_QI_VSIM1_STB_MASK 0x1 +#define PMIC_DA_QI_VSIM1_STB_SHIFT 14 +#define PMIC_DA_QI_VSIM1_EN_ADDR MT6353_LDO1_VSIM1_CON0 +#define PMIC_DA_QI_VSIM1_EN_MASK 0x1 +#define PMIC_DA_QI_VSIM1_EN_SHIFT 15 +#define PMIC_LDO_VSIM1_OCFB_EN_ADDR MT6353_LDO1_VSIM1_OCFB_CON0 +#define PMIC_LDO_VSIM1_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VSIM1_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VSIM1_OCFB_EN_ADDR MT6353_LDO1_VSIM1_OCFB_CON0 +#define PMIC_DA_QI_VSIM1_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VSIM1_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VSIM2_LP_MODE_ADDR MT6353_LDO1_VSIM2_CON0 +#define PMIC_LDO_VSIM2_LP_MODE_MASK 0x1 +#define PMIC_LDO_VSIM2_LP_MODE_SHIFT 0 +#define PMIC_LDO_VSIM2_EN_ADDR MT6353_LDO1_VSIM2_CON0 +#define PMIC_LDO_VSIM2_EN_MASK 0x1 +#define PMIC_LDO_VSIM2_EN_SHIFT 1 +#define PMIC_LDO_VSIM2_LP_CTRL_ADDR MT6353_LDO1_VSIM2_CON0 +#define PMIC_LDO_VSIM2_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VSIM2_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VSIM2_LP_SEL_ADDR MT6353_LDO1_VSIM2_CON0 +#define PMIC_LDO_VSIM2_LP_SEL_MASK 0x7 +#define PMIC_LDO_VSIM2_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VSIM2_MODE_ADDR MT6353_LDO1_VSIM2_CON0 +#define PMIC_DA_QI_VSIM2_MODE_MASK 0x1 +#define PMIC_DA_QI_VSIM2_MODE_SHIFT 8 +#define PMIC_LDO_VSIM2_STBTD_ADDR MT6353_LDO1_VSIM2_CON0 +#define PMIC_LDO_VSIM2_STBTD_MASK 0x1 +#define PMIC_LDO_VSIM2_STBTD_SHIFT 9 +#define PMIC_DA_QI_VSIM2_STB_ADDR MT6353_LDO1_VSIM2_CON0 +#define PMIC_DA_QI_VSIM2_STB_MASK 0x1 +#define PMIC_DA_QI_VSIM2_STB_SHIFT 14 +#define PMIC_DA_QI_VSIM2_EN_ADDR MT6353_LDO1_VSIM2_CON0 +#define PMIC_DA_QI_VSIM2_EN_MASK 0x1 +#define PMIC_DA_QI_VSIM2_EN_SHIFT 15 +#define PMIC_LDO_VSIM2_OCFB_EN_ADDR MT6353_LDO1_VSIM2_OCFB_CON0 +#define PMIC_LDO_VSIM2_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VSIM2_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VSIM2_OCFB_EN_ADDR MT6353_LDO1_VSIM2_OCFB_CON0 +#define PMIC_DA_QI_VSIM2_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VSIM2_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VIO28_LP_MODE_ADDR MT6353_LDO1_VIO28_CON0 +#define PMIC_LDO_VIO28_LP_MODE_MASK 0x1 +#define PMIC_LDO_VIO28_LP_MODE_SHIFT 0 +#define PMIC_LDO_VIO28_EN_ADDR MT6353_LDO1_VIO28_CON0 +#define PMIC_LDO_VIO28_EN_MASK 0x1 +#define PMIC_LDO_VIO28_EN_SHIFT 1 +#define PMIC_LDO_VIO28_LP_CTRL_ADDR MT6353_LDO1_VIO28_CON0 +#define PMIC_LDO_VIO28_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VIO28_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VIO28_LP_SEL_ADDR MT6353_LDO1_VIO28_CON0 +#define PMIC_LDO_VIO28_LP_SEL_MASK 0x7 +#define PMIC_LDO_VIO28_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VIO28_MODE_ADDR MT6353_LDO1_VIO28_CON0 +#define PMIC_DA_QI_VIO28_MODE_MASK 0x1 +#define PMIC_DA_QI_VIO28_MODE_SHIFT 8 +#define PMIC_LDO_VIO28_STBTD_ADDR MT6353_LDO1_VIO28_CON0 +#define PMIC_LDO_VIO28_STBTD_MASK 0x1 +#define PMIC_LDO_VIO28_STBTD_SHIFT 9 +#define PMIC_DA_QI_VIO28_STB_ADDR MT6353_LDO1_VIO28_CON0 +#define PMIC_DA_QI_VIO28_STB_MASK 0x1 +#define PMIC_DA_QI_VIO28_STB_SHIFT 14 +#define PMIC_DA_QI_VIO28_EN_ADDR MT6353_LDO1_VIO28_CON0 +#define PMIC_DA_QI_VIO28_EN_MASK 0x1 +#define PMIC_DA_QI_VIO28_EN_SHIFT 15 +#define PMIC_LDO_VIO28_OCFB_EN_ADDR MT6353_LDO1_VIO28_OCFB_CON0 +#define PMIC_LDO_VIO28_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VIO28_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VIO28_OCFB_EN_ADDR MT6353_LDO1_VIO28_OCFB_CON0 +#define PMIC_DA_QI_VIO28_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VIO28_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VMC_LP_MODE_ADDR MT6353_LDO1_VMC_CON0 +#define PMIC_LDO_VMC_LP_MODE_MASK 0x1 +#define PMIC_LDO_VMC_LP_MODE_SHIFT 0 +#define PMIC_LDO_VMC_EN_ADDR MT6353_LDO1_VMC_CON0 +#define PMIC_LDO_VMC_EN_MASK 0x1 +#define PMIC_LDO_VMC_EN_SHIFT 1 +#define PMIC_LDO_VMC_LP_CTRL_ADDR MT6353_LDO1_VMC_CON0 +#define PMIC_LDO_VMC_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VMC_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VMC_LP_SEL_ADDR MT6353_LDO1_VMC_CON0 +#define PMIC_LDO_VMC_LP_SEL_MASK 0x7 +#define PMIC_LDO_VMC_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VMC_MODE_ADDR MT6353_LDO1_VMC_CON0 +#define PMIC_DA_QI_VMC_MODE_MASK 0x1 +#define PMIC_DA_QI_VMC_MODE_SHIFT 8 +#define PMIC_LDO_VMC_STBTD_ADDR MT6353_LDO1_VMC_CON0 +#define PMIC_LDO_VMC_STBTD_MASK 0x1 +#define PMIC_LDO_VMC_STBTD_SHIFT 9 +#define PMIC_DA_QI_VMC_STB_ADDR MT6353_LDO1_VMC_CON0 +#define PMIC_DA_QI_VMC_STB_MASK 0x1 +#define PMIC_DA_QI_VMC_STB_SHIFT 14 +#define PMIC_DA_QI_VMC_EN_ADDR MT6353_LDO1_VMC_CON0 +#define PMIC_DA_QI_VMC_EN_MASK 0x1 +#define PMIC_DA_QI_VMC_EN_SHIFT 15 +#define PMIC_LDO_VMC_OCFB_EN_ADDR MT6353_LDO1_VMC_OCFB_CON0 +#define PMIC_LDO_VMC_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VMC_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VMC_OCFB_EN_ADDR MT6353_LDO1_VMC_OCFB_CON0 +#define PMIC_DA_QI_VMC_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VMC_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VMC_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VMC_FAST_TRAN_CON0 +#define PMIC_LDO_VMC_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_LDO_VMC_FAST_TRAN_DL_EN_SHIFT 0 +#define PMIC_LDO_VMC_FAST_TRAN_DL_CTRL_ADDR MT6353_LDO_VMC_FAST_TRAN_CON0 +#define PMIC_LDO_VMC_FAST_TRAN_DL_CTRL_MASK 0x1 +#define PMIC_LDO_VMC_FAST_TRAN_DL_CTRL_SHIFT 1 +#define PMIC_LDO_VMC_FAST_TRAN_DL_SRCLKEN_SEL_ADDR MT6353_LDO_VMC_FAST_TRAN_CON0 +#define PMIC_LDO_VMC_FAST_TRAN_DL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VMC_FAST_TRAN_DL_SRCLKEN_SEL_SHIFT 2 +#define PMIC_DA_QI_VMC_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VMC_FAST_TRAN_CON0 +#define PMIC_DA_QI_VMC_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_DA_QI_VMC_FAST_TRAN_DL_EN_SHIFT 5 +#define PMIC_LDO_VMC_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VMC_FAST_TRAN_CON0 +#define PMIC_LDO_VMC_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_LDO_VMC_FAST_TRAN_CL_EN_SHIFT 8 +#define PMIC_LDO_VMC_FAST_TRAN_CL_CTRL_ADDR MT6353_LDO_VMC_FAST_TRAN_CON0 +#define PMIC_LDO_VMC_FAST_TRAN_CL_CTRL_MASK 0x1 +#define PMIC_LDO_VMC_FAST_TRAN_CL_CTRL_SHIFT 9 +#define PMIC_LDO_VMC_FAST_TRAN_CL_SRCLKEN_SEL_ADDR MT6353_LDO_VMC_FAST_TRAN_CON0 +#define PMIC_LDO_VMC_FAST_TRAN_CL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VMC_FAST_TRAN_CL_SRCLKEN_SEL_SHIFT 10 +#define PMIC_DA_QI_VMC_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VMC_FAST_TRAN_CON0 +#define PMIC_DA_QI_VMC_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_DA_QI_VMC_FAST_TRAN_CL_EN_SHIFT 13 +#define PMIC_LDO_VMCH_LP_MODE_ADDR MT6353_LDO1_VMCH_CON0 +#define PMIC_LDO_VMCH_LP_MODE_MASK 0x1 +#define PMIC_LDO_VMCH_LP_MODE_SHIFT 0 +#define PMIC_LDO_VMCH_EN_ADDR MT6353_LDO1_VMCH_CON0 +#define PMIC_LDO_VMCH_EN_MASK 0x1 +#define PMIC_LDO_VMCH_EN_SHIFT 1 +#define PMIC_LDO_VMCH_LP_CTRL_ADDR MT6353_LDO1_VMCH_CON0 +#define PMIC_LDO_VMCH_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VMCH_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VMCH_LP_SEL_ADDR MT6353_LDO1_VMCH_CON0 +#define PMIC_LDO_VMCH_LP_SEL_MASK 0x7 +#define PMIC_LDO_VMCH_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VMCH_MODE_ADDR MT6353_LDO1_VMCH_CON0 +#define PMIC_DA_QI_VMCH_MODE_MASK 0x1 +#define PMIC_DA_QI_VMCH_MODE_SHIFT 8 +#define PMIC_LDO_VMCH_STBTD_ADDR MT6353_LDO1_VMCH_CON0 +#define PMIC_LDO_VMCH_STBTD_MASK 0x1 +#define PMIC_LDO_VMCH_STBTD_SHIFT 9 +#define PMIC_DA_QI_VMCH_STB_ADDR MT6353_LDO1_VMCH_CON0 +#define PMIC_DA_QI_VMCH_STB_MASK 0x1 +#define PMIC_DA_QI_VMCH_STB_SHIFT 14 +#define PMIC_DA_QI_VMCH_EN_ADDR MT6353_LDO1_VMCH_CON0 +#define PMIC_DA_QI_VMCH_EN_MASK 0x1 +#define PMIC_DA_QI_VMCH_EN_SHIFT 15 +#define PMIC_LDO_VMCH_OCFB_EN_ADDR MT6353_LDO1_VMCH_OCFB_CON0 +#define PMIC_LDO_VMCH_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VMCH_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VMCH_OCFB_EN_ADDR MT6353_LDO1_VMCH_OCFB_CON0 +#define PMIC_DA_QI_VMCH_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VMCH_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VMCH_FAST_TRAN_CON0 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_EN_SHIFT 0 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_CTRL_ADDR MT6353_LDO_VMCH_FAST_TRAN_CON0 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_CTRL_MASK 0x1 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_CTRL_SHIFT 1 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_SRCLKEN_SEL_ADDR MT6353_LDO_VMCH_FAST_TRAN_CON0 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VMCH_FAST_TRAN_DL_SRCLKEN_SEL_SHIFT 2 +#define PMIC_DA_QI_VMCH_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VMCH_FAST_TRAN_CON0 +#define PMIC_DA_QI_VMCH_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_DA_QI_VMCH_FAST_TRAN_DL_EN_SHIFT 5 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VMCH_FAST_TRAN_CON0 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_EN_SHIFT 8 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_CTRL_ADDR MT6353_LDO_VMCH_FAST_TRAN_CON0 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_CTRL_MASK 0x1 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_CTRL_SHIFT 9 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_SRCLKEN_SEL_ADDR MT6353_LDO_VMCH_FAST_TRAN_CON0 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VMCH_FAST_TRAN_CL_SRCLKEN_SEL_SHIFT 10 +#define PMIC_DA_QI_VMCH_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VMCH_FAST_TRAN_CON0 +#define PMIC_DA_QI_VMCH_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_DA_QI_VMCH_FAST_TRAN_CL_EN_SHIFT 13 +#define PMIC_LDO_VUSB33_LP_MODE_ADDR MT6353_LDO1_VUSB33_CON0 +#define PMIC_LDO_VUSB33_LP_MODE_MASK 0x1 +#define PMIC_LDO_VUSB33_LP_MODE_SHIFT 0 +#define PMIC_LDO_VUSB33_EN_ADDR MT6353_LDO1_VUSB33_CON0 +#define PMIC_LDO_VUSB33_EN_MASK 0x1 +#define PMIC_LDO_VUSB33_EN_SHIFT 1 +#define PMIC_LDO_VUSB33_LP_CTRL_ADDR MT6353_LDO1_VUSB33_CON0 +#define PMIC_LDO_VUSB33_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VUSB33_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VUSB33_LP_SEL_ADDR MT6353_LDO1_VUSB33_CON0 +#define PMIC_LDO_VUSB33_LP_SEL_MASK 0x7 +#define PMIC_LDO_VUSB33_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VUSB33_MODE_ADDR MT6353_LDO1_VUSB33_CON0 +#define PMIC_DA_QI_VUSB33_MODE_MASK 0x1 +#define PMIC_DA_QI_VUSB33_MODE_SHIFT 8 +#define PMIC_LDO_VUSB33_STBTD_ADDR MT6353_LDO1_VUSB33_CON0 +#define PMIC_LDO_VUSB33_STBTD_MASK 0x1 +#define PMIC_LDO_VUSB33_STBTD_SHIFT 9 +#define PMIC_DA_QI_VUSB33_STB_ADDR MT6353_LDO1_VUSB33_CON0 +#define PMIC_DA_QI_VUSB33_STB_MASK 0x1 +#define PMIC_DA_QI_VUSB33_STB_SHIFT 14 +#define PMIC_DA_QI_VUSB33_EN_ADDR MT6353_LDO1_VUSB33_CON0 +#define PMIC_DA_QI_VUSB33_EN_MASK 0x1 +#define PMIC_DA_QI_VUSB33_EN_SHIFT 15 +#define PMIC_LDO_VUSB33_OCFB_EN_ADDR MT6353_LDO1_VUSB33_OCFB_CON0 +#define PMIC_LDO_VUSB33_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VUSB33_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VUSB33_OCFB_EN_ADDR MT6353_LDO1_VUSB33_OCFB_CON0 +#define PMIC_DA_QI_VUSB33_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VUSB33_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VEMC33_LP_MODE_ADDR MT6353_LDO1_VEMC33_CON0 +#define PMIC_LDO_VEMC33_LP_MODE_MASK 0x1 +#define PMIC_LDO_VEMC33_LP_MODE_SHIFT 0 +#define PMIC_LDO_VEMC33_EN_ADDR MT6353_LDO1_VEMC33_CON0 +#define PMIC_LDO_VEMC33_EN_MASK 0x1 +#define PMIC_LDO_VEMC33_EN_SHIFT 1 +#define PMIC_LDO_VEMC33_LP_CTRL_ADDR MT6353_LDO1_VEMC33_CON0 +#define PMIC_LDO_VEMC33_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VEMC33_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VEMC33_LP_SEL_ADDR MT6353_LDO1_VEMC33_CON0 +#define PMIC_LDO_VEMC33_LP_SEL_MASK 0x7 +#define PMIC_LDO_VEMC33_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VEMC33_MODE_ADDR MT6353_LDO1_VEMC33_CON0 +#define PMIC_DA_QI_VEMC33_MODE_MASK 0x1 +#define PMIC_DA_QI_VEMC33_MODE_SHIFT 8 +#define PMIC_LDO_VEMC33_STBTD_ADDR MT6353_LDO1_VEMC33_CON0 +#define PMIC_LDO_VEMC33_STBTD_MASK 0x1 +#define PMIC_LDO_VEMC33_STBTD_SHIFT 9 +#define PMIC_DA_QI_VEMC33_STB_ADDR MT6353_LDO1_VEMC33_CON0 +#define PMIC_DA_QI_VEMC33_STB_MASK 0x1 +#define PMIC_DA_QI_VEMC33_STB_SHIFT 14 +#define PMIC_DA_QI_VEMC33_EN_ADDR MT6353_LDO1_VEMC33_CON0 +#define PMIC_DA_QI_VEMC33_EN_MASK 0x1 +#define PMIC_DA_QI_VEMC33_EN_SHIFT 15 +#define PMIC_LDO_VEMC33_OCFB_EN_ADDR MT6353_LDO1_VEMC33_OCFB_CON0 +#define PMIC_LDO_VEMC33_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VEMC33_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VEMC33_OCFB_EN_ADDR MT6353_LDO1_VEMC33_OCFB_CON0 +#define PMIC_DA_QI_VEMC33_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VEMC33_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VEMC33_FAST_TRAN_CON0 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_EN_SHIFT 0 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_CTRL_ADDR MT6353_LDO_VEMC33_FAST_TRAN_CON0 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_CTRL_MASK 0x1 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_CTRL_SHIFT 1 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_SRCLKEN_SEL_ADDR MT6353_LDO_VEMC33_FAST_TRAN_CON0 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VEMC33_FAST_TRAN_DL_SRCLKEN_SEL_SHIFT 2 +#define PMIC_DA_QI_VEMC33_FAST_TRAN_DL_EN_ADDR MT6353_LDO_VEMC33_FAST_TRAN_CON0 +#define PMIC_DA_QI_VEMC33_FAST_TRAN_DL_EN_MASK 0x1 +#define PMIC_DA_QI_VEMC33_FAST_TRAN_DL_EN_SHIFT 5 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VEMC33_FAST_TRAN_CON0 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_EN_SHIFT 8 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_CTRL_ADDR MT6353_LDO_VEMC33_FAST_TRAN_CON0 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_CTRL_MASK 0x1 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_CTRL_SHIFT 9 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_SRCLKEN_SEL_ADDR MT6353_LDO_VEMC33_FAST_TRAN_CON0 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_SRCLKEN_SEL_MASK 0x7 +#define PMIC_LDO_VEMC33_FAST_TRAN_CL_SRCLKEN_SEL_SHIFT 10 +#define PMIC_DA_QI_VEMC33_FAST_TRAN_CL_EN_ADDR MT6353_LDO_VEMC33_FAST_TRAN_CON0 +#define PMIC_DA_QI_VEMC33_FAST_TRAN_CL_EN_MASK 0x1 +#define PMIC_DA_QI_VEMC33_FAST_TRAN_CL_EN_SHIFT 13 +#define PMIC_LDO_VIO18_LP_MODE_ADDR MT6353_LDO1_VIO18_CON0 +#define PMIC_LDO_VIO18_LP_MODE_MASK 0x1 +#define PMIC_LDO_VIO18_LP_MODE_SHIFT 0 +#define PMIC_LDO_VIO18_EN_ADDR MT6353_LDO1_VIO18_CON0 +#define PMIC_LDO_VIO18_EN_MASK 0x1 +#define PMIC_LDO_VIO18_EN_SHIFT 1 +#define PMIC_LDO_VIO18_LP_CTRL_ADDR MT6353_LDO1_VIO18_CON0 +#define PMIC_LDO_VIO18_LP_CTRL_MASK 0x1 +#define PMIC_LDO_VIO18_LP_CTRL_SHIFT 2 +#define PMIC_LDO_VIO18_LP_SEL_ADDR MT6353_LDO1_VIO18_CON0 +#define PMIC_LDO_VIO18_LP_SEL_MASK 0x7 +#define PMIC_LDO_VIO18_LP_SEL_SHIFT 5 +#define PMIC_DA_QI_VIO18_MODE_ADDR MT6353_LDO1_VIO18_CON0 +#define PMIC_DA_QI_VIO18_MODE_MASK 0x1 +#define PMIC_DA_QI_VIO18_MODE_SHIFT 8 +#define PMIC_LDO_VIO18_STBTD_ADDR MT6353_LDO1_VIO18_CON0 +#define PMIC_LDO_VIO18_STBTD_MASK 0x1 +#define PMIC_LDO_VIO18_STBTD_SHIFT 9 +#define PMIC_DA_QI_VIO18_STB_ADDR MT6353_LDO1_VIO18_CON0 +#define PMIC_DA_QI_VIO18_STB_MASK 0x1 +#define PMIC_DA_QI_VIO18_STB_SHIFT 14 +#define PMIC_DA_QI_VIO18_EN_ADDR MT6353_LDO1_VIO18_CON0 +#define PMIC_DA_QI_VIO18_EN_MASK 0x1 +#define PMIC_DA_QI_VIO18_EN_SHIFT 15 +#define PMIC_LDO_VIO18_OCFB_EN_ADDR MT6353_LDO1_VIO18_OCFB_CON0 +#define PMIC_LDO_VIO18_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VIO18_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VIO18_OCFB_EN_ADDR MT6353_LDO1_VIO18_OCFB_CON0 +#define PMIC_DA_QI_VIO18_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VIO18_OCFB_EN_SHIFT 10 +#define PMIC_LDO_VIBR_LP_MODE_ADDR MT6353_LDO0_VIBR_CON0 +#define PMIC_LDO_VIBR_LP_MODE_MASK 0x1 +#define PMIC_LDO_VIBR_LP_MODE_SHIFT 0 +#define PMIC_LDO_VIBR_EN_ADDR MT6353_LDO0_VIBR_CON0 +#define PMIC_LDO_VIBR_EN_MASK 0x1 +#define PMIC_LDO_VIBR_EN_SHIFT 1 +#define PMIC_DA_QI_VIBR_MODE_ADDR MT6353_LDO0_VIBR_CON0 +#define PMIC_DA_QI_VIBR_MODE_MASK 0x1 +#define PMIC_DA_QI_VIBR_MODE_SHIFT 8 +#define PMIC_LDO_VIBR_STBTD_ADDR MT6353_LDO0_VIBR_CON0 +#define PMIC_LDO_VIBR_STBTD_MASK 0x1 +#define PMIC_LDO_VIBR_STBTD_SHIFT 9 +#define PMIC_DA_QI_VIBR_STB_ADDR MT6353_LDO0_VIBR_CON0 +#define PMIC_DA_QI_VIBR_STB_MASK 0x1 +#define PMIC_DA_QI_VIBR_STB_SHIFT 14 +#define PMIC_DA_QI_VIBR_EN_ADDR MT6353_LDO0_VIBR_CON0 +#define PMIC_DA_QI_VIBR_EN_MASK 0x1 +#define PMIC_DA_QI_VIBR_EN_SHIFT 15 +#define PMIC_LDO_VIBR_OCFB_EN_ADDR MT6353_LDO0_VIBR_OCFB_CON0 +#define PMIC_LDO_VIBR_OCFB_EN_MASK 0x1 +#define PMIC_LDO_VIBR_OCFB_EN_SHIFT 9 +#define PMIC_DA_QI_VIBR_OCFB_EN_ADDR MT6353_LDO0_VIBR_OCFB_CON0 +#define PMIC_DA_QI_VIBR_OCFB_EN_MASK 0x1 +#define PMIC_DA_QI_VIBR_OCFB_EN_SHIFT 10 +#define PMIC_RG_VTCXO28_CAL_ADDR MT6353_ALDO_ANA_CON0 +#define PMIC_RG_VTCXO28_CAL_MASK 0xF +#define PMIC_RG_VTCXO28_CAL_SHIFT 0 +#define PMIC_RG_VTCXO28_VOSEL_ADDR MT6353_ALDO_ANA_CON0 +#define PMIC_RG_VTCXO28_VOSEL_MASK 0x3 +#define PMIC_RG_VTCXO28_VOSEL_SHIFT 8 +#define PMIC_RG_VTCXO28_NDIS_EN_ADDR MT6353_ALDO_ANA_CON0 +#define PMIC_RG_VTCXO28_NDIS_EN_MASK 0x1 +#define PMIC_RG_VTCXO28_NDIS_EN_SHIFT 12 +#define PMIC_RG_VAUD28_CAL_ADDR MT6353_ALDO_ANA_CON1 +#define PMIC_RG_VAUD28_CAL_MASK 0xF +#define PMIC_RG_VAUD28_CAL_SHIFT 0 +#define PMIC_RG_VAUD28_VOSEL_ADDR MT6353_ALDO_ANA_CON1 +#define PMIC_RG_VAUD28_VOSEL_MASK 0x3 +#define PMIC_RG_VAUD28_VOSEL_SHIFT 8 +#define PMIC_RG_VAUD28_NDIS_EN_ADDR MT6353_ALDO_ANA_CON1 +#define PMIC_RG_VAUD28_NDIS_EN_MASK 0x1 +#define PMIC_RG_VAUD28_NDIS_EN_SHIFT 12 +#define PMIC_RG_VCN28_CAL_ADDR MT6353_ALDO_ANA_CON2 +#define PMIC_RG_VCN28_CAL_MASK 0xF +#define PMIC_RG_VCN28_CAL_SHIFT 0 +#define PMIC_RG_VCN28_VOSEL_ADDR MT6353_ALDO_ANA_CON2 +#define PMIC_RG_VCN28_VOSEL_MASK 0x3 +#define PMIC_RG_VCN28_VOSEL_SHIFT 8 +#define PMIC_RG_VCN28_NDIS_EN_ADDR MT6353_ALDO_ANA_CON2 +#define PMIC_RG_VCN28_NDIS_EN_MASK 0x1 +#define PMIC_RG_VCN28_NDIS_EN_SHIFT 12 +#define PMIC_RG_VAUX18_CAL_ADDR MT6353_ALDO_ANA_CON3 +#define PMIC_RG_VAUX18_CAL_MASK 0xF +#define PMIC_RG_VAUX18_CAL_SHIFT 0 +#define PMIC_RG_VAUX18_VOSEL_ADDR MT6353_ALDO_ANA_CON3 +#define PMIC_RG_VAUX18_VOSEL_MASK 0x3 +#define PMIC_RG_VAUX18_VOSEL_SHIFT 8 +#define PMIC_RG_VAUX18_NDIS_EN_ADDR MT6353_ALDO_ANA_CON3 +#define PMIC_RG_VAUX18_NDIS_EN_MASK 0x1 +#define PMIC_RG_VAUX18_NDIS_EN_SHIFT 12 +#define PMIC_RG_VCAMA_CAL_ADDR MT6353_ALDO_ANA_CON4 +#define PMIC_RG_VCAMA_CAL_MASK 0xF +#define PMIC_RG_VCAMA_CAL_SHIFT 0 +#define PMIC_RG_VCAMA_VOSEL_ADDR MT6353_ALDO_ANA_CON4 +#define PMIC_RG_VCAMA_VOSEL_MASK 0x3 +#define PMIC_RG_VCAMA_VOSEL_SHIFT 8 +#define PMIC_RG_VCAMA_NDIS_EN_ADDR MT6353_ALDO_ANA_CON4 +#define PMIC_RG_VCAMA_NDIS_EN_MASK 0x1 +#define PMIC_RG_VCAMA_NDIS_EN_SHIFT 12 +#define PMIC_RG_ALDO_RSV_H_ADDR MT6353_ALDO_ANA_CON5 +#define PMIC_RG_ALDO_RSV_H_MASK 0x3FF +#define PMIC_RG_ALDO_RSV_H_SHIFT 0 +#define PMIC_RG_ALDO_RSV_L_ADDR MT6353_ALDO_ANA_CON6 +#define PMIC_RG_ALDO_RSV_L_MASK 0x3FF +#define PMIC_RG_ALDO_RSV_L_SHIFT 0 +#define PMIC_RG_VXO22_CAL_ADDR MT6353_DLDO_ANA_CON0 +#define PMIC_RG_VXO22_CAL_MASK 0xF +#define PMIC_RG_VXO22_CAL_SHIFT 0 +#define PMIC_RG_VXO22_VOSEL_ADDR MT6353_DLDO_ANA_CON0 +#define PMIC_RG_VXO22_VOSEL_MASK 0x3 +#define PMIC_RG_VXO22_VOSEL_SHIFT 8 +#define PMIC_RG_VXO22_NDIS_EN_ADDR MT6353_DLDO_ANA_CON0 +#define PMIC_RG_VXO22_NDIS_EN_MASK 0x1 +#define PMIC_RG_VXO22_NDIS_EN_SHIFT 12 +#define PMIC_RG_VTCXO24_CAL_ADDR MT6353_DLDO_ANA_CON1 +#define PMIC_RG_VTCXO24_CAL_MASK 0xF +#define PMIC_RG_VTCXO24_CAL_SHIFT 0 +#define PMIC_RG_VTCXO24_VOSEL_ADDR MT6353_DLDO_ANA_CON1 +#define PMIC_RG_VTCXO24_VOSEL_MASK 0x3 +#define PMIC_RG_VTCXO24_VOSEL_SHIFT 8 +#define PMIC_RG_VTCXO24_NDIS_EN_ADDR MT6353_DLDO_ANA_CON1 +#define PMIC_RG_VTCXO24_NDIS_EN_MASK 0x1 +#define PMIC_RG_VTCXO24_NDIS_EN_SHIFT 12 +#define PMIC_RG_VSIM1_CAL_ADDR MT6353_DLDO_ANA_CON2 +#define PMIC_RG_VSIM1_CAL_MASK 0xF +#define PMIC_RG_VSIM1_CAL_SHIFT 0 +#define PMIC_RG_VSIM1_VOSEL_ADDR MT6353_DLDO_ANA_CON2 +#define PMIC_RG_VSIM1_VOSEL_MASK 0x7 +#define PMIC_RG_VSIM1_VOSEL_SHIFT 8 +#define PMIC_RG_VSIM1_NDIS_EN_ADDR MT6353_DLDO_ANA_CON2 +#define PMIC_RG_VSIM1_NDIS_EN_MASK 0x1 +#define PMIC_RG_VSIM1_NDIS_EN_SHIFT 12 +#define PMIC_RG_VSIM2_CAL_ADDR MT6353_DLDO_ANA_CON3 +#define PMIC_RG_VSIM2_CAL_MASK 0xF +#define PMIC_RG_VSIM2_CAL_SHIFT 0 +#define PMIC_RG_VSIM2_VOSEL_ADDR MT6353_DLDO_ANA_CON3 +#define PMIC_RG_VSIM2_VOSEL_MASK 0x7 +#define PMIC_RG_VSIM2_VOSEL_SHIFT 8 +#define PMIC_RG_VSIM2_NDIS_EN_ADDR MT6353_DLDO_ANA_CON3 +#define PMIC_RG_VSIM2_NDIS_EN_MASK 0x1 +#define PMIC_RG_VSIM2_NDIS_EN_SHIFT 12 +#define PMIC_RG_VCN33_CAL_ADDR MT6353_DLDO_ANA_CON4 +#define PMIC_RG_VCN33_CAL_MASK 0xF +#define PMIC_RG_VCN33_CAL_SHIFT 0 +#define PMIC_RG_VCN33_VOSEL_ADDR MT6353_DLDO_ANA_CON4 +#define PMIC_RG_VCN33_VOSEL_MASK 0x7 +#define PMIC_RG_VCN33_VOSEL_SHIFT 8 +#define PMIC_RG_VCN33_NDIS_EN_ADDR MT6353_DLDO_ANA_CON4 +#define PMIC_RG_VCN33_NDIS_EN_MASK 0x1 +#define PMIC_RG_VCN33_NDIS_EN_SHIFT 12 +#define PMIC_RG_VUSB33_CAL_ADDR MT6353_DLDO_ANA_CON5 +#define PMIC_RG_VUSB33_CAL_MASK 0xF +#define PMIC_RG_VUSB33_CAL_SHIFT 0 +#define PMIC_RG_VUSB33_NDIS_EN_ADDR MT6353_DLDO_ANA_CON5 +#define PMIC_RG_VUSB33_NDIS_EN_MASK 0x1 +#define PMIC_RG_VUSB33_NDIS_EN_SHIFT 12 +#define PMIC_RG_VMCH_CAL_ADDR MT6353_DLDO_ANA_CON6 +#define PMIC_RG_VMCH_CAL_MASK 0xF +#define PMIC_RG_VMCH_CAL_SHIFT 0 +#define PMIC_RG_VMCH_VOSEL_ADDR MT6353_DLDO_ANA_CON6 +#define PMIC_RG_VMCH_VOSEL_MASK 0x3 +#define PMIC_RG_VMCH_VOSEL_SHIFT 8 +#define PMIC_RG_VMCH_NDIS_EN_ADDR MT6353_DLDO_ANA_CON6 +#define PMIC_RG_VMCH_NDIS_EN_MASK 0x1 +#define PMIC_RG_VMCH_NDIS_EN_SHIFT 12 +#define PMIC_RG_VMCH_OC_TRIM_ADDR MT6353_DLDO_ANA_CON7 +#define PMIC_RG_VMCH_OC_TRIM_MASK 0xF +#define PMIC_RG_VMCH_OC_TRIM_SHIFT 0 +#define PMIC_RG_VMCH_DUMMY_LOAD_ADDR MT6353_DLDO_ANA_CON7 +#define PMIC_RG_VMCH_DUMMY_LOAD_MASK 0xF +#define PMIC_RG_VMCH_DUMMY_LOAD_SHIFT 4 +#define PMIC_RG_VMCH_DL_EN_ADDR MT6353_DLDO_ANA_CON7 +#define PMIC_RG_VMCH_DL_EN_MASK 0x1 +#define PMIC_RG_VMCH_DL_EN_SHIFT 8 +#define PMIC_RG_VMCH_CL_EN_ADDR MT6353_DLDO_ANA_CON7 +#define PMIC_RG_VMCH_CL_EN_MASK 0x1 +#define PMIC_RG_VMCH_CL_EN_SHIFT 9 +#define PMIC_RG_VMCH_STB_SEL_ADDR MT6353_DLDO_ANA_CON7 +#define PMIC_RG_VMCH_STB_SEL_MASK 0x1 +#define PMIC_RG_VMCH_STB_SEL_SHIFT 10 +#define PMIC_RG_VEMC33_CAL_ADDR MT6353_DLDO_ANA_CON8 +#define PMIC_RG_VEMC33_CAL_MASK 0xF +#define PMIC_RG_VEMC33_CAL_SHIFT 0 +#define PMIC_RG_VEMC33_VOSEL_ADDR MT6353_DLDO_ANA_CON8 +#define PMIC_RG_VEMC33_VOSEL_MASK 0x3 +#define PMIC_RG_VEMC33_VOSEL_SHIFT 8 +#define PMIC_RG_VEMC33_NDIS_EN_ADDR MT6353_DLDO_ANA_CON8 +#define PMIC_RG_VEMC33_NDIS_EN_MASK 0x1 +#define PMIC_RG_VEMC33_NDIS_EN_SHIFT 12 +#define PMIC_RG_VEMC33_OC_TRIM_ADDR MT6353_DLDO_ANA_CON9 +#define PMIC_RG_VEMC33_OC_TRIM_MASK 0xF +#define PMIC_RG_VEMC33_OC_TRIM_SHIFT 0 +#define PMIC_RG_VEMC33_DUMMY_LOAD_ADDR MT6353_DLDO_ANA_CON9 +#define PMIC_RG_VEMC33_DUMMY_LOAD_MASK 0xF +#define PMIC_RG_VEMC33_DUMMY_LOAD_SHIFT 4 +#define PMIC_RG_VEMC33_DL_EN_ADDR MT6353_DLDO_ANA_CON9 +#define PMIC_RG_VEMC33_DL_EN_MASK 0x1 +#define PMIC_RG_VEMC33_DL_EN_SHIFT 8 +#define PMIC_RG_VEMC33_CL_EN_ADDR MT6353_DLDO_ANA_CON9 +#define PMIC_RG_VEMC33_CL_EN_MASK 0x1 +#define PMIC_RG_VEMC33_CL_EN_SHIFT 9 +#define PMIC_RG_VEMC33_STB_SEL_ADDR MT6353_DLDO_ANA_CON9 +#define PMIC_RG_VEMC33_STB_SEL_MASK 0x1 +#define PMIC_RG_VEMC33_STB_SEL_SHIFT 10 +#define PMIC_RG_VIO28_CAL_ADDR MT6353_DLDO_ANA_CON10 +#define PMIC_RG_VIO28_CAL_MASK 0xF +#define PMIC_RG_VIO28_CAL_SHIFT 0 +#define PMIC_RG_VIO28_NDIS_EN_ADDR MT6353_DLDO_ANA_CON10 +#define PMIC_RG_VIO28_NDIS_EN_MASK 0x1 +#define PMIC_RG_VIO28_NDIS_EN_SHIFT 12 +#define PMIC_RG_VIBR_CAL_ADDR MT6353_DLDO_ANA_CON11 +#define PMIC_RG_VIBR_CAL_MASK 0xF +#define PMIC_RG_VIBR_CAL_SHIFT 0 +#define PMIC_RG_VIBR_VOSEL_ADDR MT6353_DLDO_ANA_CON11 +#define PMIC_RG_VIBR_VOSEL_MASK 0x7 +#define PMIC_RG_VIBR_VOSEL_SHIFT 8 +#define PMIC_RG_VIBR_NDIS_EN_ADDR MT6353_DLDO_ANA_CON11 +#define PMIC_RG_VIBR_NDIS_EN_MASK 0x1 +#define PMIC_RG_VIBR_NDIS_EN_SHIFT 12 +#define PMIC_RG_VLDO28_CAL_ADDR MT6353_DLDO_ANA_CON12 +#define PMIC_RG_VLDO28_CAL_MASK 0xF +#define PMIC_RG_VLDO28_CAL_SHIFT 0 +#define PMIC_RG_VLDO28_VOSEL_ADDR MT6353_DLDO_ANA_CON12 +#define PMIC_RG_VLDO28_VOSEL_MASK 0x7 +#define PMIC_RG_VLDO28_VOSEL_SHIFT 8 +#define PMIC_RG_VLDO28_NDIS_EN_ADDR MT6353_DLDO_ANA_CON12 +#define PMIC_RG_VLDO28_NDIS_EN_MASK 0x1 +#define PMIC_RG_VLDO28_NDIS_EN_SHIFT 12 +#define PMIC_RG_VLDO28_DUMMY_LOAD_ADDR MT6353_DLDO_ANA_CON13 +#define PMIC_RG_VLDO28_DUMMY_LOAD_MASK 0xF +#define PMIC_RG_VLDO28_DUMMY_LOAD_SHIFT 0 +#define PMIC_RG_VLDO28_DL_EN_ADDR MT6353_DLDO_ANA_CON13 +#define PMIC_RG_VLDO28_DL_EN_MASK 0x1 +#define PMIC_RG_VLDO28_DL_EN_SHIFT 4 +#define PMIC_RG_VLDO28_CL_EN_ADDR MT6353_DLDO_ANA_CON13 +#define PMIC_RG_VLDO28_CL_EN_MASK 0x1 +#define PMIC_RG_VLDO28_CL_EN_SHIFT 5 +#define PMIC_RG_VMC_CAL_ADDR MT6353_DLDO_ANA_CON14 +#define PMIC_RG_VMC_CAL_MASK 0xF +#define PMIC_RG_VMC_CAL_SHIFT 0 +#define PMIC_RG_VMC_VOSEL_ADDR MT6353_DLDO_ANA_CON14 +#define PMIC_RG_VMC_VOSEL_MASK 0x7 +#define PMIC_RG_VMC_VOSEL_SHIFT 8 +#define PMIC_RG_VMC_NDIS_EN_ADDR MT6353_DLDO_ANA_CON14 +#define PMIC_RG_VMC_NDIS_EN_MASK 0x1 +#define PMIC_RG_VMC_NDIS_EN_SHIFT 13 +#define PMIC_RG_VMC_DUMMY_LOAD_ADDR MT6353_DLDO_ANA_CON15 +#define PMIC_RG_VMC_DUMMY_LOAD_MASK 0xF +#define PMIC_RG_VMC_DUMMY_LOAD_SHIFT 0 +#define PMIC_RG_VMC_DL_EN_ADDR MT6353_DLDO_ANA_CON15 +#define PMIC_RG_VMC_DL_EN_MASK 0x1 +#define PMIC_RG_VMC_DL_EN_SHIFT 4 +#define PMIC_RG_VMC_CL_EN_ADDR MT6353_DLDO_ANA_CON15 +#define PMIC_RG_VMC_CL_EN_MASK 0x1 +#define PMIC_RG_VMC_CL_EN_SHIFT 5 +#define PMIC_RG_DLDO_RSV_H_ADDR MT6353_DLDO_ANA_CON16 +#define PMIC_RG_DLDO_RSV_H_MASK 0x3FF +#define PMIC_RG_DLDO_RSV_H_SHIFT 0 +#define PMIC_RG_DLDO_RSV_L_ADDR MT6353_DLDO_ANA_CON17 +#define PMIC_RG_DLDO_RSV_L_MASK 0x3FF +#define PMIC_RG_DLDO_RSV_L_SHIFT 0 +#define PMIC_RG_VCAMD_CAL_ADDR MT6353_SLDO_ANA_CON0 +#define PMIC_RG_VCAMD_CAL_MASK 0xF +#define PMIC_RG_VCAMD_CAL_SHIFT 0 +#define PMIC_RG_VCAMD_VOSEL_ADDR MT6353_SLDO_ANA_CON0 +#define PMIC_RG_VCAMD_VOSEL_MASK 0x7 +#define PMIC_RG_VCAMD_VOSEL_SHIFT 8 +#define PMIC_RG_VCAMD_NDIS_EN_ADDR MT6353_SLDO_ANA_CON0 +#define PMIC_RG_VCAMD_NDIS_EN_MASK 0x1 +#define PMIC_RG_VCAMD_NDIS_EN_SHIFT 12 +#define PMIC_RG_VRF18_CAL_ADDR MT6353_SLDO_ANA_CON1 +#define PMIC_RG_VRF18_CAL_MASK 0xF +#define PMIC_RG_VRF18_CAL_SHIFT 0 +#define PMIC_RG_VRF18_NDIS_EN_ADDR MT6353_SLDO_ANA_CON1 +#define PMIC_RG_VRF18_NDIS_EN_MASK 0x1 +#define PMIC_RG_VRF18_NDIS_EN_SHIFT 12 +#define PMIC_RG_VRF12_CAL_ADDR MT6353_SLDO_ANA_CON2 +#define PMIC_RG_VRF12_CAL_MASK 0xF +#define PMIC_RG_VRF12_CAL_SHIFT 0 +#define PMIC_RG_VRF12_VOSEL_ADDR MT6353_SLDO_ANA_CON2 +#define PMIC_RG_VRF12_VOSEL_MASK 0x7 +#define PMIC_RG_VRF12_VOSEL_SHIFT 8 +#define PMIC_RG_VRF12_NDIS_EN_ADDR MT6353_SLDO_ANA_CON2 +#define PMIC_RG_VRF12_NDIS_EN_MASK 0x1 +#define PMIC_RG_VRF12_NDIS_EN_SHIFT 12 +#define PMIC_RG_VRF12_STB_SEL_ADDR MT6353_SLDO_ANA_CON2 +#define PMIC_RG_VRF12_STB_SEL_MASK 0x1 +#define PMIC_RG_VRF12_STB_SEL_SHIFT 13 +#define PMIC_RG_VRF12_DUMMY_LOAD_ADDR MT6353_SLDO_ANA_CON3 +#define PMIC_RG_VRF12_DUMMY_LOAD_MASK 0x1F +#define PMIC_RG_VRF12_DUMMY_LOAD_SHIFT 0 +#define PMIC_RG_VRF12_DL_EN_ADDR MT6353_SLDO_ANA_CON3 +#define PMIC_RG_VRF12_DL_EN_MASK 0x1 +#define PMIC_RG_VRF12_DL_EN_SHIFT 5 +#define PMIC_RG_VRF12_CL_EN_ADDR MT6353_SLDO_ANA_CON3 +#define PMIC_RG_VRF12_CL_EN_MASK 0x1 +#define PMIC_RG_VRF12_CL_EN_SHIFT 6 +#define PMIC_RG_VIO18_CAL_ADDR MT6353_SLDO_ANA_CON4 +#define PMIC_RG_VIO18_CAL_MASK 0xF +#define PMIC_RG_VIO18_CAL_SHIFT 0 +#define PMIC_RG_VIO18_NDIS_EN_ADDR MT6353_SLDO_ANA_CON4 +#define PMIC_RG_VIO18_NDIS_EN_MASK 0x1 +#define PMIC_RG_VIO18_NDIS_EN_SHIFT 12 +#define PMIC_RG_VDRAM_CAL_ADDR MT6353_SLDO_ANA_CON5 +#define PMIC_RG_VDRAM_CAL_MASK 0xF +#define PMIC_RG_VDRAM_CAL_SHIFT 0 +#define PMIC_RG_VDRAM_VOSEL_ADDR MT6353_SLDO_ANA_CON5 +#define PMIC_RG_VDRAM_VOSEL_MASK 0x3 +#define PMIC_RG_VDRAM_VOSEL_SHIFT 8 +#define PMIC_RG_VDRAM_NDIS_EN_ADDR MT6353_SLDO_ANA_CON5 +#define PMIC_RG_VDRAM_NDIS_EN_MASK 0x1 +#define PMIC_RG_VDRAM_NDIS_EN_SHIFT 11 +#define PMIC_RG_VDRAM_PCUR_CAL_ADDR MT6353_SLDO_ANA_CON5 +#define PMIC_RG_VDRAM_PCUR_CAL_MASK 0x3 +#define PMIC_RG_VDRAM_PCUR_CAL_SHIFT 12 +#define PMIC_RG_VDRAM_DL_EN_ADDR MT6353_SLDO_ANA_CON5 +#define PMIC_RG_VDRAM_DL_EN_MASK 0x1 +#define PMIC_RG_VDRAM_DL_EN_SHIFT 14 +#define PMIC_RG_VDRAM_CL_EN_ADDR MT6353_SLDO_ANA_CON5 +#define PMIC_RG_VDRAM_CL_EN_MASK 0x1 +#define PMIC_RG_VDRAM_CL_EN_SHIFT 15 +#define PMIC_RG_VCAMIO_CAL_ADDR MT6353_SLDO_ANA_CON6 +#define PMIC_RG_VCAMIO_CAL_MASK 0xF +#define PMIC_RG_VCAMIO_CAL_SHIFT 0 +#define PMIC_RG_VCAMIO_VOSEL_ADDR MT6353_SLDO_ANA_CON6 +#define PMIC_RG_VCAMIO_VOSEL_MASK 0x3 +#define PMIC_RG_VCAMIO_VOSEL_SHIFT 8 +#define PMIC_RG_VCAMIO_NDIS_EN_ADDR MT6353_SLDO_ANA_CON6 +#define PMIC_RG_VCAMIO_NDIS_EN_MASK 0x1 +#define PMIC_RG_VCAMIO_NDIS_EN_SHIFT 12 +#define PMIC_RG_VCN18_CAL_ADDR MT6353_SLDO_ANA_CON7 +#define PMIC_RG_VCN18_CAL_MASK 0xF +#define PMIC_RG_VCN18_CAL_SHIFT 0 +#define PMIC_RG_VCN18_NDIS_EN_ADDR MT6353_SLDO_ANA_CON7 +#define PMIC_RG_VCN18_NDIS_EN_MASK 0x1 +#define PMIC_RG_VCN18_NDIS_EN_SHIFT 12 +#define PMIC_RG_VSRAM_PROC_VOSEL_ADDR MT6353_SLDO_ANA_CON8 +#define PMIC_RG_VSRAM_PROC_VOSEL_MASK 0x7F +#define PMIC_RG_VSRAM_PROC_VOSEL_SHIFT 0 +#define PMIC_RG_VSRAM_PROC_NDIS_PLCUR_ADDR MT6353_SLDO_ANA_CON8 +#define PMIC_RG_VSRAM_PROC_NDIS_PLCUR_MASK 0x3 +#define PMIC_RG_VSRAM_PROC_NDIS_PLCUR_SHIFT 7 +#define PMIC_RG_VSRAM_PROC_NDIS_EN_ADDR MT6353_SLDO_ANA_CON8 +#define PMIC_RG_VSRAM_PROC_NDIS_EN_MASK 0x1 +#define PMIC_RG_VSRAM_PROC_NDIS_EN_SHIFT 9 +#define PMIC_RG_VSRAM_PROC_PLCUR_EN_ADDR MT6353_SLDO_ANA_CON8 +#define PMIC_RG_VSRAM_PROC_PLCUR_EN_MASK 0x1 +#define PMIC_RG_VSRAM_PROC_PLCUR_EN_SHIFT 10 +#define PMIC_RG_SLDO_RSV_H_ADDR MT6353_SLDO_ANA_CON9 +#define PMIC_RG_SLDO_RSV_H_MASK 0x3FF +#define PMIC_RG_SLDO_RSV_H_SHIFT 0 +#define PMIC_RG_SLDO_RSV_L_ADDR MT6353_SLDO_ANA_CON10 +#define PMIC_RG_SLDO_RSV_L_MASK 0x3FF +#define PMIC_RG_SLDO_RSV_L_SHIFT 0 +#define PMIC_RG_OTP_PA_ADDR MT6353_OTP_CON0 +#define PMIC_RG_OTP_PA_MASK 0x3F +#define PMIC_RG_OTP_PA_SHIFT 0 +#define PMIC_RG_OTP_PDIN_ADDR MT6353_OTP_CON1 +#define PMIC_RG_OTP_PDIN_MASK 0xFF +#define PMIC_RG_OTP_PDIN_SHIFT 0 +#define PMIC_RG_OTP_PTM_ADDR MT6353_OTP_CON2 +#define PMIC_RG_OTP_PTM_MASK 0x3 +#define PMIC_RG_OTP_PTM_SHIFT 0 +#define PMIC_RG_OTP_PWE_ADDR MT6353_OTP_CON3 +#define PMIC_RG_OTP_PWE_MASK 0x3 +#define PMIC_RG_OTP_PWE_SHIFT 0 +#define PMIC_RG_OTP_PPROG_ADDR MT6353_OTP_CON4 +#define PMIC_RG_OTP_PPROG_MASK 0x1 +#define PMIC_RG_OTP_PPROG_SHIFT 0 +#define PMIC_RG_OTP_PWE_SRC_ADDR MT6353_OTP_CON5 +#define PMIC_RG_OTP_PWE_SRC_MASK 0x1 +#define PMIC_RG_OTP_PWE_SRC_SHIFT 0 +#define PMIC_RG_OTP_PROG_PKEY_ADDR MT6353_OTP_CON6 +#define PMIC_RG_OTP_PROG_PKEY_MASK 0xFFFF +#define PMIC_RG_OTP_PROG_PKEY_SHIFT 0 +#define PMIC_RG_OTP_RD_PKEY_ADDR MT6353_OTP_CON7 +#define PMIC_RG_OTP_RD_PKEY_MASK 0xFFFF +#define PMIC_RG_OTP_RD_PKEY_SHIFT 0 +#define PMIC_RG_OTP_RD_TRIG_ADDR MT6353_OTP_CON8 +#define PMIC_RG_OTP_RD_TRIG_MASK 0x1 +#define PMIC_RG_OTP_RD_TRIG_SHIFT 0 +#define PMIC_RG_RD_RDY_BYPASS_ADDR MT6353_OTP_CON9 +#define PMIC_RG_RD_RDY_BYPASS_MASK 0x1 +#define PMIC_RG_RD_RDY_BYPASS_SHIFT 0 +#define PMIC_RG_SKIP_OTP_OUT_ADDR MT6353_OTP_CON10 +#define PMIC_RG_SKIP_OTP_OUT_MASK 0x1 +#define PMIC_RG_SKIP_OTP_OUT_SHIFT 0 +#define PMIC_RG_OTP_RD_SW_ADDR MT6353_OTP_CON11 +#define PMIC_RG_OTP_RD_SW_MASK 0x1 +#define PMIC_RG_OTP_RD_SW_SHIFT 0 +#define PMIC_RG_OTP_DOUT_SW_ADDR MT6353_OTP_CON12 +#define PMIC_RG_OTP_DOUT_SW_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_SW_SHIFT 0 +#define PMIC_RG_OTP_RD_BUSY_ADDR MT6353_OTP_CON13 +#define PMIC_RG_OTP_RD_BUSY_MASK 0x1 +#define PMIC_RG_OTP_RD_BUSY_SHIFT 0 +#define PMIC_RG_OTP_RD_ACK_ADDR MT6353_OTP_CON13 +#define PMIC_RG_OTP_RD_ACK_MASK 0x1 +#define PMIC_RG_OTP_RD_ACK_SHIFT 2 +#define PMIC_RG_OTP_PA_SW_ADDR MT6353_OTP_CON14 +#define PMIC_RG_OTP_PA_SW_MASK 0x1F +#define PMIC_RG_OTP_PA_SW_SHIFT 0 +#define PMIC_RG_OTP_DOUT_0_15_ADDR MT6353_OTP_DOUT_0_15 +#define PMIC_RG_OTP_DOUT_0_15_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_0_15_SHIFT 0 +#define PMIC_RG_OTP_DOUT_16_31_ADDR MT6353_OTP_DOUT_16_31 +#define PMIC_RG_OTP_DOUT_16_31_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_16_31_SHIFT 0 +#define PMIC_RG_OTP_DOUT_32_47_ADDR MT6353_OTP_DOUT_32_47 +#define PMIC_RG_OTP_DOUT_32_47_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_32_47_SHIFT 0 +#define PMIC_RG_OTP_DOUT_48_63_ADDR MT6353_OTP_DOUT_48_63 +#define PMIC_RG_OTP_DOUT_48_63_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_48_63_SHIFT 0 +#define PMIC_RG_OTP_DOUT_64_79_ADDR MT6353_OTP_DOUT_64_79 +#define PMIC_RG_OTP_DOUT_64_79_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_64_79_SHIFT 0 +#define PMIC_RG_OTP_DOUT_80_95_ADDR MT6353_OTP_DOUT_80_95 +#define PMIC_RG_OTP_DOUT_80_95_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_80_95_SHIFT 0 +#define PMIC_RG_OTP_DOUT_96_111_ADDR MT6353_OTP_DOUT_96_111 +#define PMIC_RG_OTP_DOUT_96_111_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_96_111_SHIFT 0 +#define PMIC_RG_OTP_DOUT_112_127_ADDR MT6353_OTP_DOUT_112_127 +#define PMIC_RG_OTP_DOUT_112_127_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_112_127_SHIFT 0 +#define PMIC_RG_OTP_DOUT_128_143_ADDR MT6353_OTP_DOUT_128_143 +#define PMIC_RG_OTP_DOUT_128_143_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_128_143_SHIFT 0 +#define PMIC_RG_OTP_DOUT_144_159_ADDR MT6353_OTP_DOUT_144_159 +#define PMIC_RG_OTP_DOUT_144_159_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_144_159_SHIFT 0 +#define PMIC_RG_OTP_DOUT_160_175_ADDR MT6353_OTP_DOUT_160_175 +#define PMIC_RG_OTP_DOUT_160_175_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_160_175_SHIFT 0 +#define PMIC_RG_OTP_DOUT_176_191_ADDR MT6353_OTP_DOUT_176_191 +#define PMIC_RG_OTP_DOUT_176_191_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_176_191_SHIFT 0 +#define PMIC_RG_OTP_DOUT_192_207_ADDR MT6353_OTP_DOUT_192_207 +#define PMIC_RG_OTP_DOUT_192_207_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_192_207_SHIFT 0 +#define PMIC_RG_OTP_DOUT_208_223_ADDR MT6353_OTP_DOUT_208_223 +#define PMIC_RG_OTP_DOUT_208_223_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_208_223_SHIFT 0 +#define PMIC_RG_OTP_DOUT_224_239_ADDR MT6353_OTP_DOUT_224_239 +#define PMIC_RG_OTP_DOUT_224_239_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_224_239_SHIFT 0 +#define PMIC_RG_OTP_DOUT_240_255_ADDR MT6353_OTP_DOUT_240_255 +#define PMIC_RG_OTP_DOUT_240_255_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_240_255_SHIFT 0 +#define PMIC_RG_OTP_DOUT_256_271_ADDR MT6353_OTP_DOUT_256_271 +#define PMIC_RG_OTP_DOUT_256_271_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_256_271_SHIFT 0 +#define PMIC_RG_OTP_DOUT_272_287_ADDR MT6353_OTP_DOUT_272_287 +#define PMIC_RG_OTP_DOUT_272_287_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_272_287_SHIFT 0 +#define PMIC_RG_OTP_DOUT_288_303_ADDR MT6353_OTP_DOUT_288_303 +#define PMIC_RG_OTP_DOUT_288_303_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_288_303_SHIFT 0 +#define PMIC_RG_OTP_DOUT_304_319_ADDR MT6353_OTP_DOUT_304_319 +#define PMIC_RG_OTP_DOUT_304_319_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_304_319_SHIFT 0 +#define PMIC_RG_OTP_DOUT_320_335_ADDR MT6353_OTP_DOUT_320_335 +#define PMIC_RG_OTP_DOUT_320_335_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_320_335_SHIFT 0 +#define PMIC_RG_OTP_DOUT_336_351_ADDR MT6353_OTP_DOUT_336_351 +#define PMIC_RG_OTP_DOUT_336_351_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_336_351_SHIFT 0 +#define PMIC_RG_OTP_DOUT_352_367_ADDR MT6353_OTP_DOUT_352_367 +#define PMIC_RG_OTP_DOUT_352_367_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_352_367_SHIFT 0 +#define PMIC_RG_OTP_DOUT_368_383_ADDR MT6353_OTP_DOUT_368_383 +#define PMIC_RG_OTP_DOUT_368_383_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_368_383_SHIFT 0 +#define PMIC_RG_OTP_DOUT_384_399_ADDR MT6353_OTP_DOUT_384_399 +#define PMIC_RG_OTP_DOUT_384_399_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_384_399_SHIFT 0 +#define PMIC_RG_OTP_DOUT_400_415_ADDR MT6353_OTP_DOUT_400_415 +#define PMIC_RG_OTP_DOUT_400_415_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_400_415_SHIFT 0 +#define PMIC_RG_OTP_DOUT_416_431_ADDR MT6353_OTP_DOUT_416_431 +#define PMIC_RG_OTP_DOUT_416_431_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_416_431_SHIFT 0 +#define PMIC_RG_OTP_DOUT_432_447_ADDR MT6353_OTP_DOUT_432_447 +#define PMIC_RG_OTP_DOUT_432_447_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_432_447_SHIFT 0 +#define PMIC_RG_OTP_DOUT_448_463_ADDR MT6353_OTP_DOUT_448_463 +#define PMIC_RG_OTP_DOUT_448_463_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_448_463_SHIFT 0 +#define PMIC_RG_OTP_DOUT_464_479_ADDR MT6353_OTP_DOUT_464_479 +#define PMIC_RG_OTP_DOUT_464_479_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_464_479_SHIFT 0 +#define PMIC_RG_OTP_DOUT_480_495_ADDR MT6353_OTP_DOUT_480_495 +#define PMIC_RG_OTP_DOUT_480_495_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_480_495_SHIFT 0 +#define PMIC_RG_OTP_DOUT_496_511_ADDR MT6353_OTP_DOUT_496_511 +#define PMIC_RG_OTP_DOUT_496_511_MASK 0xFFFF +#define PMIC_RG_OTP_DOUT_496_511_SHIFT 0 +#define PMIC_RG_OTP_VAL_0_15_ADDR MT6353_OTP_VAL_0_15 +#define PMIC_RG_OTP_VAL_0_15_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_0_15_SHIFT 0 +#define PMIC_RG_OTP_VAL_16_31_ADDR MT6353_OTP_VAL_16_31 +#define PMIC_RG_OTP_VAL_16_31_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_16_31_SHIFT 0 +#define PMIC_RG_OTP_VAL_32_47_ADDR MT6353_OTP_VAL_32_47 +#define PMIC_RG_OTP_VAL_32_47_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_32_47_SHIFT 0 +#define PMIC_RG_OTP_VAL_48_63_ADDR MT6353_OTP_VAL_48_63 +#define PMIC_RG_OTP_VAL_48_63_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_48_63_SHIFT 0 +#define PMIC_RG_OTP_VAL_64_79_ADDR MT6353_OTP_VAL_64_79 +#define PMIC_RG_OTP_VAL_64_79_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_64_79_SHIFT 0 +#define PMIC_RG_OTP_VAL_80_95_ADDR MT6353_OTP_VAL_80_95 +#define PMIC_RG_OTP_VAL_80_95_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_80_95_SHIFT 0 +#define PMIC_RG_OTP_VAL_96_111_ADDR MT6353_OTP_VAL_96_111 +#define PMIC_RG_OTP_VAL_96_111_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_96_111_SHIFT 0 +#define PMIC_RG_OTP_VAL_112_127_ADDR MT6353_OTP_VAL_112_127 +#define PMIC_RG_OTP_VAL_112_127_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_112_127_SHIFT 0 +#define PMIC_RG_OTP_VAL_128_143_ADDR MT6353_OTP_VAL_128_143 +#define PMIC_RG_OTP_VAL_128_143_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_128_143_SHIFT 0 +#define PMIC_RG_OTP_VAL_144_159_ADDR MT6353_OTP_VAL_144_159 +#define PMIC_RG_OTP_VAL_144_159_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_144_159_SHIFT 0 +#define PMIC_RG_OTP_VAL_160_175_ADDR MT6353_OTP_VAL_160_175 +#define PMIC_RG_OTP_VAL_160_175_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_160_175_SHIFT 0 +#define PMIC_RG_OTP_VAL_176_191_ADDR MT6353_OTP_VAL_176_191 +#define PMIC_RG_OTP_VAL_176_191_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_176_191_SHIFT 0 +#define PMIC_RG_OTP_VAL_192_207_ADDR MT6353_OTP_VAL_192_207 +#define PMIC_RG_OTP_VAL_192_207_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_192_207_SHIFT 0 +#define PMIC_RG_OTP_VAL_208_223_ADDR MT6353_OTP_VAL_208_223 +#define PMIC_RG_OTP_VAL_208_223_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_208_223_SHIFT 0 +#define PMIC_RG_OTP_VAL_224_239_ADDR MT6353_OTP_VAL_224_239 +#define PMIC_RG_OTP_VAL_224_239_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_224_239_SHIFT 0 +#define PMIC_RG_OTP_VAL_240_255_ADDR MT6353_OTP_VAL_240_255 +#define PMIC_RG_OTP_VAL_240_255_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_240_255_SHIFT 0 +#define PMIC_RG_OTP_VAL_256_271_ADDR MT6353_OTP_VAL_256_271 +#define PMIC_RG_OTP_VAL_256_271_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_256_271_SHIFT 0 +#define PMIC_RG_OTP_VAL_272_287_ADDR MT6353_OTP_VAL_272_287 +#define PMIC_RG_OTP_VAL_272_287_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_272_287_SHIFT 0 +#define PMIC_RG_OTP_VAL_288_303_ADDR MT6353_OTP_VAL_288_303 +#define PMIC_RG_OTP_VAL_288_303_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_288_303_SHIFT 0 +#define PMIC_RG_OTP_VAL_304_319_ADDR MT6353_OTP_VAL_304_319 +#define PMIC_RG_OTP_VAL_304_319_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_304_319_SHIFT 0 +#define PMIC_RG_OTP_VAL_320_335_ADDR MT6353_OTP_VAL_320_335 +#define PMIC_RG_OTP_VAL_320_335_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_320_335_SHIFT 0 +#define PMIC_RG_OTP_VAL_336_351_ADDR MT6353_OTP_VAL_336_351 +#define PMIC_RG_OTP_VAL_336_351_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_336_351_SHIFT 0 +#define PMIC_RG_OTP_VAL_352_367_ADDR MT6353_OTP_VAL_352_367 +#define PMIC_RG_OTP_VAL_352_367_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_352_367_SHIFT 0 +#define PMIC_RG_OTP_VAL_368_383_ADDR MT6353_OTP_VAL_368_383 +#define PMIC_RG_OTP_VAL_368_383_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_368_383_SHIFT 0 +#define PMIC_RG_OTP_VAL_384_399_ADDR MT6353_OTP_VAL_384_399 +#define PMIC_RG_OTP_VAL_384_399_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_384_399_SHIFT 0 +#define PMIC_RG_OTP_VAL_400_415_ADDR MT6353_OTP_VAL_400_415 +#define PMIC_RG_OTP_VAL_400_415_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_400_415_SHIFT 0 +#define PMIC_RG_OTP_VAL_416_431_ADDR MT6353_OTP_VAL_416_431 +#define PMIC_RG_OTP_VAL_416_431_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_416_431_SHIFT 0 +#define PMIC_RG_OTP_VAL_432_447_ADDR MT6353_OTP_VAL_432_447 +#define PMIC_RG_OTP_VAL_432_447_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_432_447_SHIFT 0 +#define PMIC_RG_OTP_VAL_448_463_ADDR MT6353_OTP_VAL_448_463 +#define PMIC_RG_OTP_VAL_448_463_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_448_463_SHIFT 0 +#define PMIC_RG_OTP_VAL_464_479_ADDR MT6353_OTP_VAL_464_479 +#define PMIC_RG_OTP_VAL_464_479_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_464_479_SHIFT 0 +#define PMIC_RG_OTP_VAL_480_495_ADDR MT6353_OTP_VAL_480_495 +#define PMIC_RG_OTP_VAL_480_495_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_480_495_SHIFT 0 +#define PMIC_RG_OTP_VAL_496_511_ADDR MT6353_OTP_VAL_496_511 +#define PMIC_RG_OTP_VAL_496_511_MASK 0xFFFF +#define PMIC_RG_OTP_VAL_496_511_SHIFT 0 +#define PMIC_MIX_EOSC32_STP_LPDTB_ADDR MT6353_RTC_MIX_CON0 +#define PMIC_MIX_EOSC32_STP_LPDTB_MASK 0x1 +#define PMIC_MIX_EOSC32_STP_LPDTB_SHIFT 1 +#define PMIC_MIX_EOSC32_STP_LPDEN_ADDR MT6353_RTC_MIX_CON0 +#define PMIC_MIX_EOSC32_STP_LPDEN_MASK 0x1 +#define PMIC_MIX_EOSC32_STP_LPDEN_SHIFT 2 +#define PMIC_MIX_XOSC32_STP_PWDB_ADDR MT6353_RTC_MIX_CON0 +#define PMIC_MIX_XOSC32_STP_PWDB_MASK 0x1 +#define PMIC_MIX_XOSC32_STP_PWDB_SHIFT 3 +#define PMIC_MIX_XOSC32_STP_LPDTB_ADDR MT6353_RTC_MIX_CON0 +#define PMIC_MIX_XOSC32_STP_LPDTB_MASK 0x1 +#define PMIC_MIX_XOSC32_STP_LPDTB_SHIFT 4 +#define PMIC_MIX_XOSC32_STP_LPDEN_ADDR MT6353_RTC_MIX_CON0 +#define PMIC_MIX_XOSC32_STP_LPDEN_MASK 0x1 +#define PMIC_MIX_XOSC32_STP_LPDEN_SHIFT 5 +#define PMIC_MIX_XOSC32_STP_LPDRST_ADDR MT6353_RTC_MIX_CON0 +#define PMIC_MIX_XOSC32_STP_LPDRST_MASK 0x1 +#define PMIC_MIX_XOSC32_STP_LPDRST_SHIFT 6 +#define PMIC_MIX_XOSC32_STP_CALI_ADDR MT6353_RTC_MIX_CON0 +#define PMIC_MIX_XOSC32_STP_CALI_MASK 0x1F +#define PMIC_MIX_XOSC32_STP_CALI_SHIFT 7 +#define PMIC_STMP_MODE_ADDR MT6353_RTC_MIX_CON0 +#define PMIC_STMP_MODE_MASK 0x1 +#define PMIC_STMP_MODE_SHIFT 12 +#define PMIC_MIX_EOSC32_STP_CHOP_EN_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_EOSC32_STP_CHOP_EN_MASK 0x1 +#define PMIC_MIX_EOSC32_STP_CHOP_EN_SHIFT 0 +#define PMIC_MIX_DCXO_STP_LVSH_EN_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_DCXO_STP_LVSH_EN_MASK 0x1 +#define PMIC_MIX_DCXO_STP_LVSH_EN_SHIFT 1 +#define PMIC_MIX_PMU_STP_DDLO_VRTC_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_PMU_STP_DDLO_VRTC_MASK 0x1 +#define PMIC_MIX_PMU_STP_DDLO_VRTC_SHIFT 2 +#define PMIC_MIX_PMU_STP_DDLO_VRTC_EN_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_PMU_STP_DDLO_VRTC_EN_MASK 0x1 +#define PMIC_MIX_PMU_STP_DDLO_VRTC_EN_SHIFT 3 +#define PMIC_MIX_RTC_STP_XOSC32_ENB_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_RTC_STP_XOSC32_ENB_MASK 0x1 +#define PMIC_MIX_RTC_STP_XOSC32_ENB_SHIFT 4 +#define PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_MASK 0x1 +#define PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_SHIFT 5 +#define PMIC_MIX_EOSC32_STP_RSV_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_EOSC32_STP_RSV_MASK 0x3 +#define PMIC_MIX_EOSC32_STP_RSV_SHIFT 6 +#define PMIC_MIX_EOSC32_VCT_EN_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_EOSC32_VCT_EN_MASK 0x1 +#define PMIC_MIX_EOSC32_VCT_EN_SHIFT 8 +#define PMIC_MIX_EOSC32_OPT_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_EOSC32_OPT_MASK 0x3 +#define PMIC_MIX_EOSC32_OPT_SHIFT 9 +#define PMIC_MIX_DCXO_STP_LVSH_EN_INT_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_DCXO_STP_LVSH_EN_INT_MASK 0x1 +#define PMIC_MIX_DCXO_STP_LVSH_EN_INT_SHIFT 11 +#define PMIC_MIX_RTC_GPIO_COREDETB_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_RTC_GPIO_COREDETB_MASK 0x1 +#define PMIC_MIX_RTC_GPIO_COREDETB_SHIFT 12 +#define PMIC_MIX_RTC_GPIO_F32KOB_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_RTC_GPIO_F32KOB_MASK 0x1 +#define PMIC_MIX_RTC_GPIO_F32KOB_SHIFT 13 +#define PMIC_MIX_RTC_GPIO_GPO_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_RTC_GPIO_GPO_MASK 0x1 +#define PMIC_MIX_RTC_GPIO_GPO_SHIFT 14 +#define PMIC_MIX_RTC_GPIO_OE_ADDR MT6353_RTC_MIX_CON1 +#define PMIC_MIX_RTC_GPIO_OE_MASK 0x1 +#define PMIC_MIX_RTC_GPIO_OE_SHIFT 15 +#define PMIC_MIX_RTC_STP_DEBUG_OUT_ADDR MT6353_RTC_MIX_CON2 +#define PMIC_MIX_RTC_STP_DEBUG_OUT_MASK 0x3 +#define PMIC_MIX_RTC_STP_DEBUG_OUT_SHIFT 0 +#define PMIC_MIX_RTC_STP_DEBUG_SEL_ADDR MT6353_RTC_MIX_CON2 +#define PMIC_MIX_RTC_STP_DEBUG_SEL_MASK 0x3 +#define PMIC_MIX_RTC_STP_DEBUG_SEL_SHIFT 4 +#define PMIC_MIX_RTC_STP_K_EOSC32_EN_ADDR MT6353_RTC_MIX_CON2 +#define PMIC_MIX_RTC_STP_K_EOSC32_EN_MASK 0x1 +#define PMIC_MIX_RTC_STP_K_EOSC32_EN_SHIFT 7 +#define PMIC_MIX_RTC_STP_EMBCK_SEL_ADDR MT6353_RTC_MIX_CON2 +#define PMIC_MIX_RTC_STP_EMBCK_SEL_MASK 0x1 +#define PMIC_MIX_RTC_STP_EMBCK_SEL_SHIFT 8 +#define PMIC_MIX_STP_BBWAKEUP_ADDR MT6353_RTC_MIX_CON2 +#define PMIC_MIX_STP_BBWAKEUP_MASK 0x1 +#define PMIC_MIX_STP_BBWAKEUP_SHIFT 9 +#define PMIC_MIX_STP_RTC_DDLO_ADDR MT6353_RTC_MIX_CON2 +#define PMIC_MIX_STP_RTC_DDLO_MASK 0x1 +#define PMIC_MIX_STP_RTC_DDLO_SHIFT 10 +#define PMIC_MIX_RTC_XOSC32_ENB_ADDR MT6353_RTC_MIX_CON2 +#define PMIC_MIX_RTC_XOSC32_ENB_MASK 0x1 +#define PMIC_MIX_RTC_XOSC32_ENB_SHIFT 11 +#define PMIC_MIX_EFUSE_XOSC32_ENB_OPT_ADDR MT6353_RTC_MIX_CON2 +#define PMIC_MIX_EFUSE_XOSC32_ENB_OPT_MASK 0x1 +#define PMIC_MIX_EFUSE_XOSC32_ENB_OPT_SHIFT 12 +#define PMIC_FG_ON_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_ON_MASK 0x1 +#define PMIC_FG_ON_SHIFT 0 +#define PMIC_FG_CAL_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_CAL_MASK 0x3 +#define PMIC_FG_CAL_SHIFT 2 +#define PMIC_FG_AUTOCALRATE_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_AUTOCALRATE_MASK 0x7 +#define PMIC_FG_AUTOCALRATE_SHIFT 4 +#define PMIC_FG_SW_CR_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_SW_CR_MASK 0x1 +#define PMIC_FG_SW_CR_SHIFT 8 +#define PMIC_FG_SW_READ_PRE_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_SW_READ_PRE_MASK 0x1 +#define PMIC_FG_SW_READ_PRE_SHIFT 9 +#define PMIC_FG_LATCHDATA_ST_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_LATCHDATA_ST_MASK 0x1 +#define PMIC_FG_LATCHDATA_ST_SHIFT 10 +#define PMIC_FG_SW_CLEAR_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_SW_CLEAR_MASK 0x1 +#define PMIC_FG_SW_CLEAR_SHIFT 11 +#define PMIC_FG_OFFSET_RST_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_OFFSET_RST_MASK 0x1 +#define PMIC_FG_OFFSET_RST_SHIFT 12 +#define PMIC_FG_TIME_RST_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_TIME_RST_MASK 0x1 +#define PMIC_FG_TIME_RST_SHIFT 13 +#define PMIC_FG_CHARGE_RST_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_CHARGE_RST_MASK 0x1 +#define PMIC_FG_CHARGE_RST_SHIFT 14 +#define PMIC_FG_SW_RSTCLR_ADDR MT6353_FGADC_CON0 +#define PMIC_FG_SW_RSTCLR_MASK 0x1 +#define PMIC_FG_SW_RSTCLR_SHIFT 15 +#define PMIC_FG_CAR_34_19_ADDR MT6353_FGADC_CON1 +#define PMIC_FG_CAR_34_19_MASK 0xFFFF +#define PMIC_FG_CAR_34_19_SHIFT 0 +#define PMIC_FG_CAR_18_03_ADDR MT6353_FGADC_CON2 +#define PMIC_FG_CAR_18_03_MASK 0xFFFF +#define PMIC_FG_CAR_18_03_SHIFT 0 +#define PMIC_FG_CAR_02_00_ADDR MT6353_FGADC_CON3 +#define PMIC_FG_CAR_02_00_MASK 0x7 +#define PMIC_FG_CAR_02_00_SHIFT 0 +#define PMIC_FG_NTER_32_17_ADDR MT6353_FGADC_CON4 +#define PMIC_FG_NTER_32_17_MASK 0xFFFF +#define PMIC_FG_NTER_32_17_SHIFT 0 +#define PMIC_FG_NTER_16_01_ADDR MT6353_FGADC_CON5 +#define PMIC_FG_NTER_16_01_MASK 0xFFFF +#define PMIC_FG_NTER_16_01_SHIFT 0 +#define PMIC_FG_NTER_00_ADDR MT6353_FGADC_CON6 +#define PMIC_FG_NTER_00_MASK 0x1 +#define PMIC_FG_NTER_00_SHIFT 0 +#define PMIC_FG_BLTR_31_16_ADDR MT6353_FGADC_CON7 +#define PMIC_FG_BLTR_31_16_MASK 0xFFFF +#define PMIC_FG_BLTR_31_16_SHIFT 0 +#define PMIC_FG_BLTR_15_00_ADDR MT6353_FGADC_CON8 +#define PMIC_FG_BLTR_15_00_MASK 0xFFFF +#define PMIC_FG_BLTR_15_00_SHIFT 0 +#define PMIC_FG_BFTR_31_16_ADDR MT6353_FGADC_CON9 +#define PMIC_FG_BFTR_31_16_MASK 0xFFFF +#define PMIC_FG_BFTR_31_16_SHIFT 0 +#define PMIC_FG_BFTR_15_00_ADDR MT6353_FGADC_CON10 +#define PMIC_FG_BFTR_15_00_MASK 0xFFFF +#define PMIC_FG_BFTR_15_00_SHIFT 0 +#define PMIC_FG_CURRENT_OUT_ADDR MT6353_FGADC_CON11 +#define PMIC_FG_CURRENT_OUT_MASK 0xFFFF +#define PMIC_FG_CURRENT_OUT_SHIFT 0 +#define PMIC_FG_ADJUST_OFFSET_VALUE_ADDR MT6353_FGADC_CON12 +#define PMIC_FG_ADJUST_OFFSET_VALUE_MASK 0xFFFF +#define PMIC_FG_ADJUST_OFFSET_VALUE_SHIFT 0 +#define PMIC_FG_OFFSET_ADDR MT6353_FGADC_CON13 +#define PMIC_FG_OFFSET_MASK 0xFFFF +#define PMIC_FG_OFFSET_SHIFT 0 +#define PMIC_RG_FGANALOGTEST_ADDR MT6353_FGADC_CON14 +#define PMIC_RG_FGANALOGTEST_MASK 0xF +#define PMIC_RG_FGANALOGTEST_SHIFT 0 +#define PMIC_RG_FGINTMODE_ADDR MT6353_FGADC_CON14 +#define PMIC_RG_FGINTMODE_MASK 0x1 +#define PMIC_RG_FGINTMODE_SHIFT 4 +#define PMIC_RG_SPARE_ADDR MT6353_FGADC_CON14 +#define PMIC_RG_SPARE_MASK 0xFF +#define PMIC_RG_SPARE_SHIFT 5 +#define PMIC_FG_OSR_ADDR MT6353_FGADC_CON15 +#define PMIC_FG_OSR_MASK 0xF +#define PMIC_FG_OSR_SHIFT 0 +#define PMIC_FG_ADJ_OFFSET_EN_ADDR MT6353_FGADC_CON15 +#define PMIC_FG_ADJ_OFFSET_EN_MASK 0x1 +#define PMIC_FG_ADJ_OFFSET_EN_SHIFT 8 +#define PMIC_FG_ADC_AUTORST_ADDR MT6353_FGADC_CON15 +#define PMIC_FG_ADC_AUTORST_MASK 0x1 +#define PMIC_FG_ADC_AUTORST_SHIFT 9 +#define PMIC_FG_FIR1BYPASS_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_FIR1BYPASS_MASK 0x1 +#define PMIC_FG_FIR1BYPASS_SHIFT 0 +#define PMIC_FG_FIR2BYPASS_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_FIR2BYPASS_MASK 0x1 +#define PMIC_FG_FIR2BYPASS_SHIFT 1 +#define PMIC_FG_L_CUR_INT_STS_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_L_CUR_INT_STS_MASK 0x1 +#define PMIC_FG_L_CUR_INT_STS_SHIFT 2 +#define PMIC_FG_H_CUR_INT_STS_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_H_CUR_INT_STS_MASK 0x1 +#define PMIC_FG_H_CUR_INT_STS_SHIFT 3 +#define PMIC_FG_L_INT_STS_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_L_INT_STS_MASK 0x1 +#define PMIC_FG_L_INT_STS_SHIFT 4 +#define PMIC_FG_H_INT_STS_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_H_INT_STS_MASK 0x1 +#define PMIC_FG_H_INT_STS_SHIFT 5 +#define PMIC_FG_ADC_RSTDETECT_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_ADC_RSTDETECT_MASK 0x1 +#define PMIC_FG_ADC_RSTDETECT_SHIFT 7 +#define PMIC_FG_SLP_EN_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_SLP_EN_MASK 0x1 +#define PMIC_FG_SLP_EN_SHIFT 8 +#define PMIC_FG_ZCV_DET_EN_ADDR MT6353_FGADC_CON16 +#define PMIC_FG_ZCV_DET_EN_MASK 0x1 +#define PMIC_FG_ZCV_DET_EN_SHIFT 9 +#define PMIC_RG_FG_AUXADC_R_ADDR MT6353_FGADC_CON16 +#define PMIC_RG_FG_AUXADC_R_MASK 0x1 +#define PMIC_RG_FG_AUXADC_R_SHIFT 10 +#define PMIC_DA_FGADC_EN_ADDR MT6353_FGADC_CON16 +#define PMIC_DA_FGADC_EN_MASK 0x1 +#define PMIC_DA_FGADC_EN_SHIFT 12 +#define PMIC_DA_FGCAL_EN_ADDR MT6353_FGADC_CON16 +#define PMIC_DA_FGCAL_EN_MASK 0x1 +#define PMIC_DA_FGCAL_EN_SHIFT 13 +#define PMIC_DA_FG_RST_ADDR MT6353_FGADC_CON16 +#define PMIC_DA_FG_RST_MASK 0x1 +#define PMIC_DA_FG_RST_SHIFT 14 +#define PMIC_FG_CIC2_ADDR MT6353_FGADC_CON17 +#define PMIC_FG_CIC2_MASK 0xFFFF +#define PMIC_FG_CIC2_SHIFT 0 +#define PMIC_FG_SLP_CUR_TH_ADDR MT6353_FGADC_CON18 +#define PMIC_FG_SLP_CUR_TH_MASK 0xFFFF +#define PMIC_FG_SLP_CUR_TH_SHIFT 0 +#define PMIC_FG_SLP_TIME_ADDR MT6353_FGADC_CON19 +#define PMIC_FG_SLP_TIME_MASK 0xFF +#define PMIC_FG_SLP_TIME_SHIFT 0 +#define PMIC_FG_SRCVOLTEN_FTIME_ADDR MT6353_FGADC_CON20 +#define PMIC_FG_SRCVOLTEN_FTIME_MASK 0xFF +#define PMIC_FG_SRCVOLTEN_FTIME_SHIFT 0 +#define PMIC_FG_DET_TIME_ADDR MT6353_FGADC_CON20 +#define PMIC_FG_DET_TIME_MASK 0xFF +#define PMIC_FG_DET_TIME_SHIFT 8 +#define PMIC_FG_ZCV_CAR_34_19_ADDR MT6353_FGADC_CON21 +#define PMIC_FG_ZCV_CAR_34_19_MASK 0xFFFF +#define PMIC_FG_ZCV_CAR_34_19_SHIFT 0 +#define PMIC_FG_ZCV_CAR_18_03_ADDR MT6353_FGADC_CON22 +#define PMIC_FG_ZCV_CAR_18_03_MASK 0xFFFF +#define PMIC_FG_ZCV_CAR_18_03_SHIFT 0 +#define PMIC_FG_ZCV_CAR_02_00_ADDR MT6353_FGADC_CON23 +#define PMIC_FG_ZCV_CAR_02_00_MASK 0x7 +#define PMIC_FG_ZCV_CAR_02_00_SHIFT 0 +#define PMIC_FG_ZCV_CURR_ADDR MT6353_FGADC_CON24 +#define PMIC_FG_ZCV_CURR_MASK 0xFFFF +#define PMIC_FG_ZCV_CURR_SHIFT 0 +#define PMIC_FG_R_CURR_ADDR MT6353_FGADC_CON25 +#define PMIC_FG_R_CURR_MASK 0xFFFF +#define PMIC_FG_R_CURR_SHIFT 0 +#define PMIC_FG_MODE_ADDR MT6353_FGADC_CON26 +#define PMIC_FG_MODE_MASK 0x1 +#define PMIC_FG_MODE_SHIFT 0 +#define PMIC_FG_RST_SW_ADDR MT6353_FGADC_CON26 +#define PMIC_FG_RST_SW_MASK 0x1 +#define PMIC_FG_RST_SW_SHIFT 1 +#define PMIC_FG_FGCAL_EN_SW_ADDR MT6353_FGADC_CON26 +#define PMIC_FG_FGCAL_EN_SW_MASK 0x1 +#define PMIC_FG_FGCAL_EN_SW_SHIFT 2 +#define PMIC_FG_FGADC_EN_SW_ADDR MT6353_FGADC_CON26 +#define PMIC_FG_FGADC_EN_SW_MASK 0x1 +#define PMIC_FG_FGADC_EN_SW_SHIFT 3 +#define PMIC_FG_RSV1_ADDR MT6353_FGADC_CON26 +#define PMIC_FG_RSV1_MASK 0xF +#define PMIC_FG_RSV1_SHIFT 4 +#define PMIC_FG_TEST_MODE0_ADDR MT6353_FGADC_CON26 +#define PMIC_FG_TEST_MODE0_MASK 0x1 +#define PMIC_FG_TEST_MODE0_SHIFT 14 +#define PMIC_FG_TEST_MODE1_ADDR MT6353_FGADC_CON26 +#define PMIC_FG_TEST_MODE1_MASK 0x1 +#define PMIC_FG_TEST_MODE1_SHIFT 15 +#define PMIC_FG_GAIN_ADDR MT6353_FGADC_CON27 +#define PMIC_FG_GAIN_MASK 0x1FFF +#define PMIC_FG_GAIN_SHIFT 0 +#define PMIC_FG_CUR_HTH_ADDR MT6353_FGADC_CON28 +#define PMIC_FG_CUR_HTH_MASK 0xFFFF +#define PMIC_FG_CUR_HTH_SHIFT 0 +#define PMIC_FG_CUR_LTH_ADDR MT6353_FGADC_CON29 +#define PMIC_FG_CUR_LTH_MASK 0xFFFF +#define PMIC_FG_CUR_LTH_SHIFT 0 +#define PMIC_FG_ZCV_DET_TIME_ADDR MT6353_FGADC_CON30 +#define PMIC_FG_ZCV_DET_TIME_MASK 0x3F +#define PMIC_FG_ZCV_DET_TIME_SHIFT 0 +#define PMIC_FG_ZCV_CAR_TH_33_19_ADDR MT6353_FGADC_CON31 +#define PMIC_FG_ZCV_CAR_TH_33_19_MASK 0x7FFF +#define PMIC_FG_ZCV_CAR_TH_33_19_SHIFT 0 +#define PMIC_FG_ZCV_CAR_TH_18_03_ADDR MT6353_FGADC_CON32 +#define PMIC_FG_ZCV_CAR_TH_18_03_MASK 0xFFFF +#define PMIC_FG_ZCV_CAR_TH_18_03_SHIFT 0 +#define PMIC_FG_ZCV_CAR_TH_02_00_ADDR MT6353_FGADC_CON33 +#define PMIC_FG_ZCV_CAR_TH_02_00_MASK 0x7 +#define PMIC_FG_ZCV_CAR_TH_02_00_SHIFT 0 +#define PMIC_SYSTEM_INFO_CON0_ADDR MT6353_SYSTEM_INFO_CON0 +#define PMIC_SYSTEM_INFO_CON0_MASK 0xFFFF +#define PMIC_SYSTEM_INFO_CON0_SHIFT 0 +#define PMIC_SYSTEM_INFO_CON1_ADDR MT6353_SYSTEM_INFO_CON1 +#define PMIC_SYSTEM_INFO_CON1_MASK 0xFFFF +#define PMIC_SYSTEM_INFO_CON1_SHIFT 0 +#define PMIC_SYSTEM_INFO_CON2_ADDR MT6353_SYSTEM_INFO_CON2 +#define PMIC_SYSTEM_INFO_CON2_MASK 0xFFFF +#define PMIC_SYSTEM_INFO_CON2_SHIFT 0 +#define PMIC_SYSTEM_INFO_CON3_ADDR MT6353_SYSTEM_INFO_CON3 +#define PMIC_SYSTEM_INFO_CON3_MASK 0xFFFF +#define PMIC_SYSTEM_INFO_CON3_SHIFT 0 +#define PMIC_SYSTEM_INFO_CON4_ADDR MT6353_SYSTEM_INFO_CON4 +#define PMIC_SYSTEM_INFO_CON4_MASK 0xFFFF +#define PMIC_SYSTEM_INFO_CON4_SHIFT 0 +#define PMIC_RG_AUDDACLPWRUP_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDDACLPWRUP_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDDACLPWRUP_VAUDP15_SHIFT 0 +#define PMIC_RG_AUDDACRPWRUP_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDDACRPWRUP_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDDACRPWRUP_VAUDP15_SHIFT 1 +#define PMIC_RG_AUD_DAC_PWR_UP_VA28_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUD_DAC_PWR_UP_VA28_MASK 0x1 +#define PMIC_RG_AUD_DAC_PWR_UP_VA28_SHIFT 2 +#define PMIC_RG_AUD_DAC_PWL_UP_VA28_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUD_DAC_PWL_UP_VA28_MASK 0x1 +#define PMIC_RG_AUD_DAC_PWL_UP_VA28_SHIFT 3 +#define PMIC_RG_AUDHSPWRUP_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHSPWRUP_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHSPWRUP_VAUDP15_SHIFT 4 +#define PMIC_RG_AUDHPLPWRUP_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHPLPWRUP_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPLPWRUP_VAUDP15_SHIFT 5 +#define PMIC_RG_AUDHPRPWRUP_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHPRPWRUP_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPRPWRUP_VAUDP15_SHIFT 6 +#define PMIC_RG_AUDHSMUXINPUTSEL_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHSMUXINPUTSEL_VAUDP15_MASK 0x3 +#define PMIC_RG_AUDHSMUXINPUTSEL_VAUDP15_SHIFT 7 +#define PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP15_MASK 0x3 +#define PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP15_SHIFT 9 +#define PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP15_MASK 0x3 +#define PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP15_SHIFT 11 +#define PMIC_RG_AUDHSSCDISABLE_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHSSCDISABLE_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHSSCDISABLE_VAUDP15_SHIFT 13 +#define PMIC_RG_AUDHPLSCDISABLE_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHPLSCDISABLE_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPLSCDISABLE_VAUDP15_SHIFT 14 +#define PMIC_RG_AUDHPRSCDISABLE_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON0 +#define PMIC_RG_AUDHPRSCDISABLE_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPRSCDISABLE_VAUDP15_SHIFT 15 +#define PMIC_RG_AUDHPLBSCCURRENT_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_AUDHPLBSCCURRENT_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPLBSCCURRENT_VAUDP15_SHIFT 0 +#define PMIC_RG_AUDHPRBSCCURRENT_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_AUDHPRBSCCURRENT_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPRBSCCURRENT_VAUDP15_SHIFT 1 +#define PMIC_RG_AUDHSBSCCURRENT_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_AUDHSBSCCURRENT_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHSBSCCURRENT_VAUDP15_SHIFT 2 +#define PMIC_RG_AUDHPSTARTUP_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_AUDHPSTARTUP_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPSTARTUP_VAUDP15_SHIFT 3 +#define PMIC_RG_AUDHSSTARTUP_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_AUDHSSTARTUP_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHSSTARTUP_VAUDP15_SHIFT 4 +#define PMIC_RG_PRECHARGEBUF_EN_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_PRECHARGEBUF_EN_VAUDP15_MASK 0x1 +#define PMIC_RG_PRECHARGEBUF_EN_VAUDP15_SHIFT 5 +#define PMIC_RG_HPINPUTSTBENH_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HPINPUTSTBENH_VAUDP15_MASK 0x1 +#define PMIC_RG_HPINPUTSTBENH_VAUDP15_SHIFT 6 +#define PMIC_RG_HPOUTPUTSTBENH_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HPOUTPUTSTBENH_VAUDP15_MASK 0x1 +#define PMIC_RG_HPOUTPUTSTBENH_VAUDP15_SHIFT 7 +#define PMIC_RG_HPINPUTRESET0_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HPINPUTRESET0_VAUDP15_MASK 0x1 +#define PMIC_RG_HPINPUTRESET0_VAUDP15_SHIFT 8 +#define PMIC_RG_HPOUTPUTRESET0_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HPOUTPUTRESET0_VAUDP15_MASK 0x1 +#define PMIC_RG_HPOUTPUTRESET0_VAUDP15_SHIFT 9 +#define PMIC_RG_HPOUT_SHORTVCM_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HPOUT_SHORTVCM_VAUDP15_MASK 0x1 +#define PMIC_RG_HPOUT_SHORTVCM_VAUDP15_SHIFT 10 +#define PMIC_RG_HSINPUTSTBENH_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HSINPUTSTBENH_VAUDP15_MASK 0x1 +#define PMIC_RG_HSINPUTSTBENH_VAUDP15_SHIFT 11 +#define PMIC_RG_HSOUTPUTSTBENH_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HSOUTPUTSTBENH_VAUDP15_MASK 0x1 +#define PMIC_RG_HSOUTPUTSTBENH_VAUDP15_SHIFT 12 +#define PMIC_RG_HSINPUTRESET0_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HSINPUTRESET0_VAUDP15_MASK 0x1 +#define PMIC_RG_HSINPUTRESET0_VAUDP15_SHIFT 13 +#define PMIC_RG_HSOUTPUTRESET0_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON1 +#define PMIC_RG_HSOUTPUTRESET0_VAUDP15_MASK 0x1 +#define PMIC_RG_HSOUTPUTRESET0_VAUDP15_SHIFT 14 +#define PMIC_RG_HPOUTSTB_RSEL_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON2 +#define PMIC_RG_HPOUTSTB_RSEL_VAUDP15_MASK 0x3 +#define PMIC_RG_HPOUTSTB_RSEL_VAUDP15_SHIFT 0 +#define PMIC_RG_HSOUT_SHORTVCM_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON2 +#define PMIC_RG_HSOUT_SHORTVCM_VAUDP15_MASK 0x1 +#define PMIC_RG_HSOUT_SHORTVCM_VAUDP15_SHIFT 2 +#define PMIC_RG_AUDHPLTRIM_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON2 +#define PMIC_RG_AUDHPLTRIM_VAUDP15_MASK 0xF +#define PMIC_RG_AUDHPLTRIM_VAUDP15_SHIFT 3 +#define PMIC_RG_AUDHPRTRIM_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON2 +#define PMIC_RG_AUDHPRTRIM_VAUDP15_MASK 0xF +#define PMIC_RG_AUDHPRTRIM_VAUDP15_SHIFT 7 +#define PMIC_RG_AUDHPTRIM_EN_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON2 +#define PMIC_RG_AUDHPTRIM_EN_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPTRIM_EN_VAUDP15_SHIFT 11 +#define PMIC_RG_AUDHPLFINETRIM_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON2 +#define PMIC_RG_AUDHPLFINETRIM_VAUDP15_MASK 0x3 +#define PMIC_RG_AUDHPLFINETRIM_VAUDP15_SHIFT 12 +#define PMIC_RG_AUDHPRFINETRIM_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON2 +#define PMIC_RG_AUDHPRFINETRIM_VAUDP15_MASK 0x3 +#define PMIC_RG_AUDHPRFINETRIM_VAUDP15_SHIFT 14 +#define PMIC_RG_AUDTRIMBUF_EN_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON3 +#define PMIC_RG_AUDTRIMBUF_EN_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDTRIMBUF_EN_VAUDP15_SHIFT 0 +#define PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON3 +#define PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP15_MASK 0xF +#define PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP15_SHIFT 1 +#define PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON3 +#define PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP15_MASK 0x3 +#define PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP15_SHIFT 5 +#define PMIC_RG_AUDHPSPKDET_EN_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON3 +#define PMIC_RG_AUDHPSPKDET_EN_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDHPSPKDET_EN_VAUDP15_SHIFT 7 +#define PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON3 +#define PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP15_MASK 0x3 +#define PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP15_SHIFT 8 +#define PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON3 +#define PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP15_MASK 0x3 +#define PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP15_SHIFT 10 +#define PMIC_RG_ABIDEC_RESERVED_VA28_ADDR MT6353_AUDDEC_ANA_CON4 +#define PMIC_RG_ABIDEC_RESERVED_VA28_MASK 0xFF +#define PMIC_RG_ABIDEC_RESERVED_VA28_SHIFT 0 +#define PMIC_RG_ABIDEC_RESERVED_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON4 +#define PMIC_RG_ABIDEC_RESERVED_VAUDP15_MASK 0xFF +#define PMIC_RG_ABIDEC_RESERVED_VAUDP15_SHIFT 8 +#define PMIC_RG_AUDBIASADJ_0_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON5 +#define PMIC_RG_AUDBIASADJ_0_VAUDP15_MASK 0x3F +#define PMIC_RG_AUDBIASADJ_0_VAUDP15_SHIFT 4 +#define PMIC_RG_AUDBIASADJ_1_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON5 +#define PMIC_RG_AUDBIASADJ_1_VAUDP15_MASK 0x3F +#define PMIC_RG_AUDBIASADJ_1_VAUDP15_SHIFT 10 +#define PMIC_RG_AUDIBIASPWRDN_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_AUDIBIASPWRDN_VAUDP15_MASK 0x1 +#define PMIC_RG_AUDIBIASPWRDN_VAUDP15_SHIFT 0 +#define PMIC_RG_RSTB_DECODER_VA28_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_RSTB_DECODER_VA28_MASK 0x1 +#define PMIC_RG_RSTB_DECODER_VA28_SHIFT 1 +#define PMIC_RG_RSTB_ENCODER_VA28_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_RSTB_ENCODER_VA28_MASK 0x1 +#define PMIC_RG_RSTB_ENCODER_VA28_SHIFT 2 +#define PMIC_RG_SEL_DECODER_96K_VA28_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_SEL_DECODER_96K_VA28_MASK 0x1 +#define PMIC_RG_SEL_DECODER_96K_VA28_SHIFT 3 +#define PMIC_RG_SEL_ENCODER_96K_VA28_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_SEL_ENCODER_96K_VA28_MASK 0x1 +#define PMIC_RG_SEL_ENCODER_96K_VA28_SHIFT 4 +#define PMIC_RG_SEL_DELAY_VCORE_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_SEL_DELAY_VCORE_MASK 0x1 +#define PMIC_RG_SEL_DELAY_VCORE_SHIFT 5 +#define PMIC_RG_HCLDO_EN_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_HCLDO_EN_VA18_MASK 0x1 +#define PMIC_RG_HCLDO_EN_VA18_SHIFT 6 +#define PMIC_RG_LCLDO_EN_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_LCLDO_EN_VA18_MASK 0x1 +#define PMIC_RG_LCLDO_EN_VA18_SHIFT 7 +#define PMIC_RG_LCLDO_ENC_EN_VA28_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_LCLDO_ENC_EN_VA28_MASK 0x1 +#define PMIC_RG_LCLDO_ENC_EN_VA28_SHIFT 8 +#define PMIC_RG_VA33REFGEN_EN_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_VA33REFGEN_EN_VA18_MASK 0x1 +#define PMIC_RG_VA33REFGEN_EN_VA18_SHIFT 9 +#define PMIC_RG_HCLDO_PDDIS_EN_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_HCLDO_PDDIS_EN_VA18_MASK 0x1 +#define PMIC_RG_HCLDO_PDDIS_EN_VA18_SHIFT 10 +#define PMIC_RG_HCLDO_REMOTE_SENSE_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_HCLDO_REMOTE_SENSE_VA18_MASK 0x1 +#define PMIC_RG_HCLDO_REMOTE_SENSE_VA18_SHIFT 11 +#define PMIC_RG_LCLDO_PDDIS_EN_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_LCLDO_PDDIS_EN_VA18_MASK 0x1 +#define PMIC_RG_LCLDO_PDDIS_EN_VA18_SHIFT 12 +#define PMIC_RG_LCLDO_REMOTE_SENSE_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_LCLDO_REMOTE_SENSE_VA18_MASK 0x1 +#define PMIC_RG_LCLDO_REMOTE_SENSE_VA18_SHIFT 13 +#define PMIC_RG_LCLDO_VOSEL_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_LCLDO_VOSEL_VA18_MASK 0x1 +#define PMIC_RG_LCLDO_VOSEL_VA18_SHIFT 14 +#define PMIC_RG_HCLDO_VOSEL_VA18_ADDR MT6353_AUDDEC_ANA_CON6 +#define PMIC_RG_HCLDO_VOSEL_VA18_MASK 0x1 +#define PMIC_RG_HCLDO_VOSEL_VA18_SHIFT 15 +#define PMIC_RG_LCLDO_ENC_PDDIS_EN_VA28_ADDR MT6353_AUDDEC_ANA_CON7 +#define PMIC_RG_LCLDO_ENC_PDDIS_EN_VA28_MASK 0x1 +#define PMIC_RG_LCLDO_ENC_PDDIS_EN_VA28_SHIFT 0 +#define PMIC_RG_LCLDO_ENC_REMOTE_SENSE_VA28_ADDR MT6353_AUDDEC_ANA_CON7 +#define PMIC_RG_LCLDO_ENC_REMOTE_SENSE_VA28_MASK 0x1 +#define PMIC_RG_LCLDO_ENC_REMOTE_SENSE_VA28_SHIFT 1 +#define PMIC_RG_VA28REFGEN_EN_VA28_ADDR MT6353_AUDDEC_ANA_CON7 +#define PMIC_RG_VA28REFGEN_EN_VA28_MASK 0x1 +#define PMIC_RG_VA28REFGEN_EN_VA28_SHIFT 2 +#define PMIC_RG_AUDPMU_RESERVED_VA28_ADDR MT6353_AUDDEC_ANA_CON7 +#define PMIC_RG_AUDPMU_RESERVED_VA28_MASK 0xF +#define PMIC_RG_AUDPMU_RESERVED_VA28_SHIFT 3 +#define PMIC_RG_AUDPMU_RESERVED_VA18_ADDR MT6353_AUDDEC_ANA_CON7 +#define PMIC_RG_AUDPMU_RESERVED_VA18_MASK 0xF +#define PMIC_RG_AUDPMU_RESERVED_VA18_SHIFT 7 +#define PMIC_RG_AUDPMU_RESERVED_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON7 +#define PMIC_RG_AUDPMU_RESERVED_VAUDP15_MASK 0xF +#define PMIC_RG_AUDPMU_RESERVED_VAUDP15_SHIFT 11 +#define PMIC_RG_NVREG_EN_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON7 +#define PMIC_RG_NVREG_EN_VAUDP15_MASK 0x1 +#define PMIC_RG_NVREG_EN_VAUDP15_SHIFT 15 +#define PMIC_RG_NVREG_PULL0V_VAUDP15_ADDR MT6353_AUDDEC_ANA_CON8 +#define PMIC_RG_NVREG_PULL0V_VAUDP15_MASK 0x1 +#define PMIC_RG_NVREG_PULL0V_VAUDP15_SHIFT 0 +#define PMIC_RG_AUDGLB_PWRDN_VA28_ADDR MT6353_AUDDEC_ANA_CON8 +#define PMIC_RG_AUDGLB_PWRDN_VA28_MASK 0x1 +#define PMIC_RG_AUDGLB_PWRDN_VA28_SHIFT 1 +#define PMIC_RG_AUDPREAMPLON_ADDR MT6353_AUDENC_ANA_CON0 +#define PMIC_RG_AUDPREAMPLON_MASK 0x1 +#define PMIC_RG_AUDPREAMPLON_SHIFT 0 +#define PMIC_RG_AUDPREAMPLDCCEN_ADDR MT6353_AUDENC_ANA_CON0 +#define PMIC_RG_AUDPREAMPLDCCEN_MASK 0x1 +#define PMIC_RG_AUDPREAMPLDCCEN_SHIFT 1 +#define PMIC_RG_AUDPREAMPLDCRPECHARGE_ADDR MT6353_AUDENC_ANA_CON0 +#define PMIC_RG_AUDPREAMPLDCRPECHARGE_MASK 0x1 +#define PMIC_RG_AUDPREAMPLDCRPECHARGE_SHIFT 2 +#define PMIC_RG_AUDPREAMPLPGATEST_ADDR MT6353_AUDENC_ANA_CON0 +#define PMIC_RG_AUDPREAMPLPGATEST_MASK 0x1 +#define PMIC_RG_AUDPREAMPLPGATEST_SHIFT 3 +#define PMIC_RG_AUDPREAMPLVSCALE_ADDR MT6353_AUDENC_ANA_CON0 +#define PMIC_RG_AUDPREAMPLVSCALE_MASK 0x3 +#define PMIC_RG_AUDPREAMPLVSCALE_SHIFT 4 +#define PMIC_RG_AUDPREAMPLINPUTSEL_ADDR MT6353_AUDENC_ANA_CON0 +#define PMIC_RG_AUDPREAMPLINPUTSEL_MASK 0x3 +#define PMIC_RG_AUDPREAMPLINPUTSEL_SHIFT 6 +#define PMIC_RG_AUDADCLPWRUP_ADDR MT6353_AUDENC_ANA_CON0 +#define PMIC_RG_AUDADCLPWRUP_MASK 0x1 +#define PMIC_RG_AUDADCLPWRUP_SHIFT 8 +#define PMIC_RG_AUDADCLINPUTSEL_ADDR MT6353_AUDENC_ANA_CON0 +#define PMIC_RG_AUDADCLINPUTSEL_MASK 0x3 +#define PMIC_RG_AUDADCLINPUTSEL_SHIFT 9 +#define PMIC_RG_AUDPREAMPRON_ADDR MT6353_AUDENC_ANA_CON1 +#define PMIC_RG_AUDPREAMPRON_MASK 0x1 +#define PMIC_RG_AUDPREAMPRON_SHIFT 0 +#define PMIC_RG_AUDPREAMPRDCCEN_ADDR MT6353_AUDENC_ANA_CON1 +#define PMIC_RG_AUDPREAMPRDCCEN_MASK 0x1 +#define PMIC_RG_AUDPREAMPRDCCEN_SHIFT 1 +#define PMIC_RG_AUDPREAMPRDCRPECHARGE_ADDR MT6353_AUDENC_ANA_CON1 +#define PMIC_RG_AUDPREAMPRDCRPECHARGE_MASK 0x1 +#define PMIC_RG_AUDPREAMPRDCRPECHARGE_SHIFT 2 +#define PMIC_RG_AUDPREAMPRPGATEST_ADDR MT6353_AUDENC_ANA_CON1 +#define PMIC_RG_AUDPREAMPRPGATEST_MASK 0x1 +#define PMIC_RG_AUDPREAMPRPGATEST_SHIFT 3 +#define PMIC_RG_AUDPREAMPRVSCALE_ADDR MT6353_AUDENC_ANA_CON1 +#define PMIC_RG_AUDPREAMPRVSCALE_MASK 0x3 +#define PMIC_RG_AUDPREAMPRVSCALE_SHIFT 4 +#define PMIC_RG_AUDPREAMPRINPUTSEL_ADDR MT6353_AUDENC_ANA_CON1 +#define PMIC_RG_AUDPREAMPRINPUTSEL_MASK 0x3 +#define PMIC_RG_AUDPREAMPRINPUTSEL_SHIFT 6 +#define PMIC_RG_AUDADCRPWRUP_ADDR MT6353_AUDENC_ANA_CON1 +#define PMIC_RG_AUDADCRPWRUP_MASK 0x1 +#define PMIC_RG_AUDADCRPWRUP_SHIFT 8 +#define PMIC_RG_AUDADCRINPUTSEL_ADDR MT6353_AUDENC_ANA_CON1 +#define PMIC_RG_AUDADCRINPUTSEL_MASK 0x3 +#define PMIC_RG_AUDADCRINPUTSEL_SHIFT 9 +#define PMIC_RG_AUDULHALFBIAS_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDULHALFBIAS_MASK 0x1 +#define PMIC_RG_AUDULHALFBIAS_SHIFT 0 +#define PMIC_RG_AUDGLBMADLPWEN_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDGLBMADLPWEN_MASK 0x1 +#define PMIC_RG_AUDGLBMADLPWEN_SHIFT 1 +#define PMIC_RG_AUDPREAMPLPEN_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDPREAMPLPEN_MASK 0x1 +#define PMIC_RG_AUDPREAMPLPEN_SHIFT 2 +#define PMIC_RG_AUDADC1STSTAGELPEN_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDADC1STSTAGELPEN_MASK 0x1 +#define PMIC_RG_AUDADC1STSTAGELPEN_SHIFT 3 +#define PMIC_RG_AUDADC2NDSTAGELPEN_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDADC2NDSTAGELPEN_MASK 0x1 +#define PMIC_RG_AUDADC2NDSTAGELPEN_SHIFT 4 +#define PMIC_RG_AUDADCFLASHLPEN_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDADCFLASHLPEN_MASK 0x1 +#define PMIC_RG_AUDADCFLASHLPEN_SHIFT 5 +#define PMIC_RG_AUDPREAMPIDDTEST_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDPREAMPIDDTEST_MASK 0x3 +#define PMIC_RG_AUDPREAMPIDDTEST_SHIFT 6 +#define PMIC_RG_AUDADC1STSTAGEIDDTEST_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDADC1STSTAGEIDDTEST_MASK 0x3 +#define PMIC_RG_AUDADC1STSTAGEIDDTEST_SHIFT 8 +#define PMIC_RG_AUDADC2NDSTAGEIDDTEST_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDADC2NDSTAGEIDDTEST_MASK 0x3 +#define PMIC_RG_AUDADC2NDSTAGEIDDTEST_SHIFT 10 +#define PMIC_RG_AUDADCREFBUFIDDTEST_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDADCREFBUFIDDTEST_MASK 0x3 +#define PMIC_RG_AUDADCREFBUFIDDTEST_SHIFT 12 +#define PMIC_RG_AUDADCFLASHIDDTEST_ADDR MT6353_AUDENC_ANA_CON2 +#define PMIC_RG_AUDADCFLASHIDDTEST_MASK 0x3 +#define PMIC_RG_AUDADCFLASHIDDTEST_SHIFT 14 +#define PMIC_RG_AUDADCDAC0P25FS_ADDR MT6353_AUDENC_ANA_CON3 +#define PMIC_RG_AUDADCDAC0P25FS_MASK 0x1 +#define PMIC_RG_AUDADCDAC0P25FS_SHIFT 0 +#define PMIC_RG_AUDADCCLKSEL_ADDR MT6353_AUDENC_ANA_CON3 +#define PMIC_RG_AUDADCCLKSEL_MASK 0x1 +#define PMIC_RG_AUDADCCLKSEL_SHIFT 1 +#define PMIC_RG_AUDADCCLKSOURCE_ADDR MT6353_AUDENC_ANA_CON3 +#define PMIC_RG_AUDADCCLKSOURCE_MASK 0x3 +#define PMIC_RG_AUDADCCLKSOURCE_SHIFT 2 +#define PMIC_RG_AUDADCCLKGENMODE_ADDR MT6353_AUDENC_ANA_CON3 +#define PMIC_RG_AUDADCCLKGENMODE_MASK 0x3 +#define PMIC_RG_AUDADCCLKGENMODE_SHIFT 4 +#define PMIC_RG_AUDPREAMPAAFEN_ADDR MT6353_AUDENC_ANA_CON3 +#define PMIC_RG_AUDPREAMPAAFEN_MASK 0x1 +#define PMIC_RG_AUDPREAMPAAFEN_SHIFT 8 +#define PMIC_RG_DCCVCMBUFLPMODSEL_ADDR MT6353_AUDENC_ANA_CON3 +#define PMIC_RG_DCCVCMBUFLPMODSEL_MASK 0x1 +#define PMIC_RG_DCCVCMBUFLPMODSEL_SHIFT 9 +#define PMIC_RG_DCCVCMBUFLPSWEN_ADDR MT6353_AUDENC_ANA_CON3 +#define PMIC_RG_DCCVCMBUFLPSWEN_MASK 0x1 +#define PMIC_RG_DCCVCMBUFLPSWEN_SHIFT 10 +#define PMIC_RG_AUDSPAREPGA_ADDR MT6353_AUDENC_ANA_CON3 +#define PMIC_RG_AUDSPAREPGA_MASK 0x1 +#define PMIC_RG_AUDSPAREPGA_SHIFT 11 +#define PMIC_RG_AUDADC1STSTAGESDENB_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADC1STSTAGESDENB_MASK 0x1 +#define PMIC_RG_AUDADC1STSTAGESDENB_SHIFT 0 +#define PMIC_RG_AUDADC2NDSTAGERESET_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADC2NDSTAGERESET_MASK 0x1 +#define PMIC_RG_AUDADC2NDSTAGERESET_SHIFT 1 +#define PMIC_RG_AUDADC3RDSTAGERESET_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADC3RDSTAGERESET_MASK 0x1 +#define PMIC_RG_AUDADC3RDSTAGERESET_SHIFT 2 +#define PMIC_RG_AUDADCFSRESET_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCFSRESET_MASK 0x1 +#define PMIC_RG_AUDADCFSRESET_SHIFT 3 +#define PMIC_RG_AUDADCWIDECM_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCWIDECM_MASK 0x1 +#define PMIC_RG_AUDADCWIDECM_SHIFT 4 +#define PMIC_RG_AUDADCNOPATEST_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCNOPATEST_MASK 0x1 +#define PMIC_RG_AUDADCNOPATEST_SHIFT 5 +#define PMIC_RG_AUDADCBYPASS_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCBYPASS_MASK 0x1 +#define PMIC_RG_AUDADCBYPASS_SHIFT 6 +#define PMIC_RG_AUDADCFFBYPASS_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCFFBYPASS_MASK 0x1 +#define PMIC_RG_AUDADCFFBYPASS_SHIFT 7 +#define PMIC_RG_AUDADCDACFBCURRENT_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCDACFBCURRENT_MASK 0x1 +#define PMIC_RG_AUDADCDACFBCURRENT_SHIFT 8 +#define PMIC_RG_AUDADCDACIDDTEST_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCDACIDDTEST_MASK 0x3 +#define PMIC_RG_AUDADCDACIDDTEST_SHIFT 9 +#define PMIC_RG_AUDADCDACNRZ_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCDACNRZ_MASK 0x1 +#define PMIC_RG_AUDADCDACNRZ_SHIFT 11 +#define PMIC_RG_AUDADCNODEM_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCNODEM_MASK 0x1 +#define PMIC_RG_AUDADCNODEM_SHIFT 12 +#define PMIC_RG_AUDADCDACTEST_ADDR MT6353_AUDENC_ANA_CON4 +#define PMIC_RG_AUDADCDACTEST_MASK 0x1 +#define PMIC_RG_AUDADCDACTEST_SHIFT 13 +#define PMIC_RG_AUDADCTESTDATA_ADDR MT6353_AUDENC_ANA_CON5 +#define PMIC_RG_AUDADCTESTDATA_MASK 0xFFFF +#define PMIC_RG_AUDADCTESTDATA_SHIFT 0 +#define PMIC_RG_AUDRCTUNEL_ADDR MT6353_AUDENC_ANA_CON6 +#define PMIC_RG_AUDRCTUNEL_MASK 0x1F +#define PMIC_RG_AUDRCTUNEL_SHIFT 0 +#define PMIC_RG_AUDRCTUNELSEL_ADDR MT6353_AUDENC_ANA_CON6 +#define PMIC_RG_AUDRCTUNELSEL_MASK 0x1 +#define PMIC_RG_AUDRCTUNELSEL_SHIFT 5 +#define PMIC_RG_AUDRCTUNER_ADDR MT6353_AUDENC_ANA_CON6 +#define PMIC_RG_AUDRCTUNER_MASK 0x1F +#define PMIC_RG_AUDRCTUNER_SHIFT 6 +#define PMIC_RG_AUDRCTUNERSEL_ADDR MT6353_AUDENC_ANA_CON6 +#define PMIC_RG_AUDRCTUNERSEL_MASK 0x1 +#define PMIC_RG_AUDRCTUNERSEL_SHIFT 13 +#define PMIC_RG_AUDSPAREVA28_ADDR MT6353_AUDENC_ANA_CON7 +#define PMIC_RG_AUDSPAREVA28_MASK 0xF +#define PMIC_RG_AUDSPAREVA28_SHIFT 0 +#define PMIC_RG_AUDSPAREVA18_ADDR MT6353_AUDENC_ANA_CON7 +#define PMIC_RG_AUDSPAREVA18_MASK 0xF +#define PMIC_RG_AUDSPAREVA18_SHIFT 4 +#define PMIC_RG_AUDENCSPAREVA28_ADDR MT6353_AUDENC_ANA_CON7 +#define PMIC_RG_AUDENCSPAREVA28_MASK 0xF +#define PMIC_RG_AUDENCSPAREVA28_SHIFT 8 +#define PMIC_RG_AUDENCSPAREVA18_ADDR MT6353_AUDENC_ANA_CON7 +#define PMIC_RG_AUDENCSPAREVA18_MASK 0xF +#define PMIC_RG_AUDENCSPAREVA18_SHIFT 12 +#define PMIC_RG_AUDDIGMICEN_ADDR MT6353_AUDENC_ANA_CON8 +#define PMIC_RG_AUDDIGMICEN_MASK 0x1 +#define PMIC_RG_AUDDIGMICEN_SHIFT 0 +#define PMIC_RG_AUDDIGMICBIAS_ADDR MT6353_AUDENC_ANA_CON8 +#define PMIC_RG_AUDDIGMICBIAS_MASK 0x3 +#define PMIC_RG_AUDDIGMICBIAS_SHIFT 1 +#define PMIC_RG_DMICHPCLKEN_ADDR MT6353_AUDENC_ANA_CON8 +#define PMIC_RG_DMICHPCLKEN_MASK 0x1 +#define PMIC_RG_DMICHPCLKEN_SHIFT 3 +#define PMIC_RG_AUDDIGMICPDUTY_ADDR MT6353_AUDENC_ANA_CON8 +#define PMIC_RG_AUDDIGMICPDUTY_MASK 0x3 +#define PMIC_RG_AUDDIGMICPDUTY_SHIFT 4 +#define PMIC_RG_AUDDIGMICNDUTY_ADDR MT6353_AUDENC_ANA_CON8 +#define PMIC_RG_AUDDIGMICNDUTY_MASK 0x3 +#define PMIC_RG_AUDDIGMICNDUTY_SHIFT 6 +#define PMIC_RG_DMICMONEN_ADDR MT6353_AUDENC_ANA_CON8 +#define PMIC_RG_DMICMONEN_MASK 0x1 +#define PMIC_RG_DMICMONEN_SHIFT 8 +#define PMIC_RG_DMICMONSEL_ADDR MT6353_AUDENC_ANA_CON8 +#define PMIC_RG_DMICMONSEL_MASK 0x7 +#define PMIC_RG_DMICMONSEL_SHIFT 9 +#define PMIC_RG_AUDSPAREVMIC_ADDR MT6353_AUDENC_ANA_CON8 +#define PMIC_RG_AUDSPAREVMIC_MASK 0xF +#define PMIC_RG_AUDSPAREVMIC_SHIFT 12 +#define PMIC_RG_AUDPWDBMICBIAS0_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDPWDBMICBIAS0_MASK 0x1 +#define PMIC_RG_AUDPWDBMICBIAS0_SHIFT 0 +#define PMIC_RG_AUDMICBIAS0DCSWPEN_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDMICBIAS0DCSWPEN_MASK 0x1 +#define PMIC_RG_AUDMICBIAS0DCSWPEN_SHIFT 1 +#define PMIC_RG_AUDMICBIAS0DCSWNEN_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDMICBIAS0DCSWNEN_MASK 0x1 +#define PMIC_RG_AUDMICBIAS0DCSWNEN_SHIFT 2 +#define PMIC_RG_AUDMICBIAS0BYPASSEN_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDMICBIAS0BYPASSEN_MASK 0x1 +#define PMIC_RG_AUDMICBIAS0BYPASSEN_SHIFT 3 +#define PMIC_RG_AUDPWDBMICBIAS1_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDPWDBMICBIAS1_MASK 0x1 +#define PMIC_RG_AUDPWDBMICBIAS1_SHIFT 4 +#define PMIC_RG_AUDMICBIAS1DCSWPEN_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDMICBIAS1DCSWPEN_MASK 0x1 +#define PMIC_RG_AUDMICBIAS1DCSWPEN_SHIFT 5 +#define PMIC_RG_AUDMICBIAS1DCSWNEN_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDMICBIAS1DCSWNEN_MASK 0x1 +#define PMIC_RG_AUDMICBIAS1DCSWNEN_SHIFT 6 +#define PMIC_RG_AUDMICBIAS1BYPASSEN_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDMICBIAS1BYPASSEN_MASK 0x1 +#define PMIC_RG_AUDMICBIAS1BYPASSEN_SHIFT 7 +#define PMIC_RG_AUDMICBIASVREF_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDMICBIASVREF_MASK 0x7 +#define PMIC_RG_AUDMICBIASVREF_SHIFT 8 +#define PMIC_RG_AUDMICBIASLOWPEN_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_AUDMICBIASLOWPEN_MASK 0x1 +#define PMIC_RG_AUDMICBIASLOWPEN_SHIFT 11 +#define PMIC_RG_BANDGAPGEN_ADDR MT6353_AUDENC_ANA_CON9 +#define PMIC_RG_BANDGAPGEN_MASK 0x1 +#define PMIC_RG_BANDGAPGEN_SHIFT 12 +#define PMIC_RG_AUDPREAMPLGAIN_ADDR MT6353_AUDENC_ANA_CON10 +#define PMIC_RG_AUDPREAMPLGAIN_MASK 0x7 +#define PMIC_RG_AUDPREAMPLGAIN_SHIFT 0 +#define PMIC_RG_AUDPREAMPRGAIN_ADDR MT6353_AUDENC_ANA_CON10 +#define PMIC_RG_AUDPREAMPRGAIN_MASK 0x7 +#define PMIC_RG_AUDPREAMPRGAIN_SHIFT 4 +#define PMIC_RG_DIVCKS_CHG_ADDR MT6353_AUDNCP_CLKDIV_CON0 +#define PMIC_RG_DIVCKS_CHG_MASK 0x1 +#define PMIC_RG_DIVCKS_CHG_SHIFT 0 +#define PMIC_RG_DIVCKS_ON_ADDR MT6353_AUDNCP_CLKDIV_CON1 +#define PMIC_RG_DIVCKS_ON_MASK 0x1 +#define PMIC_RG_DIVCKS_ON_SHIFT 0 +#define PMIC_RG_DIVCKS_PRG_ADDR MT6353_AUDNCP_CLKDIV_CON2 +#define PMIC_RG_DIVCKS_PRG_MASK 0x1FF +#define PMIC_RG_DIVCKS_PRG_SHIFT 0 +#define PMIC_RG_DIVCKS_PWD_NCP_ADDR MT6353_AUDNCP_CLKDIV_CON3 +#define PMIC_RG_DIVCKS_PWD_NCP_MASK 0x1 +#define PMIC_RG_DIVCKS_PWD_NCP_SHIFT 0 +#define PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_ADDR MT6353_AUDNCP_CLKDIV_CON4 +#define PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_MASK 0x3 +#define PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_SHIFT 0 +#define PMIC_XO_EXTBUF1_MODE_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_EXTBUF1_MODE_MASK 0x3 +#define PMIC_XO_EXTBUF1_MODE_SHIFT 0 +#define PMIC_XO_EXTBUF1_EN_M_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_EXTBUF1_EN_M_MASK 0x1 +#define PMIC_XO_EXTBUF1_EN_M_SHIFT 2 +#define PMIC_XO_EXTBUF2_MODE_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_EXTBUF2_MODE_MASK 0x3 +#define PMIC_XO_EXTBUF2_MODE_SHIFT 3 +#define PMIC_XO_EXTBUF2_EN_M_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_EXTBUF2_EN_M_MASK 0x1 +#define PMIC_XO_EXTBUF2_EN_M_SHIFT 5 +#define PMIC_XO_EXTBUF3_MODE_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_EXTBUF3_MODE_MASK 0x3 +#define PMIC_XO_EXTBUF3_MODE_SHIFT 6 +#define PMIC_XO_EXTBUF3_EN_M_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_EXTBUF3_EN_M_MASK 0x1 +#define PMIC_XO_EXTBUF3_EN_M_SHIFT 8 +#define PMIC_XO_EXTBUF4_MODE_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_EXTBUF4_MODE_MASK 0x3 +#define PMIC_XO_EXTBUF4_MODE_SHIFT 9 +#define PMIC_XO_EXTBUF4_EN_M_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_EXTBUF4_EN_M_MASK 0x1 +#define PMIC_XO_EXTBUF4_EN_M_SHIFT 11 +#define PMIC_XO_BB_LPM_EN_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_BB_LPM_EN_MASK 0x1 +#define PMIC_XO_BB_LPM_EN_SHIFT 12 +#define PMIC_XO_ENBB_MAN_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_ENBB_MAN_MASK 0x1 +#define PMIC_XO_ENBB_MAN_SHIFT 13 +#define PMIC_XO_ENBB_EN_M_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_ENBB_EN_M_MASK 0x1 +#define PMIC_XO_ENBB_EN_M_SHIFT 14 +#define PMIC_XO_CLKSEL_MAN_ADDR MT6353_DCXO_CW00 +#define PMIC_XO_CLKSEL_MAN_MASK 0x1 +#define PMIC_XO_CLKSEL_MAN_SHIFT 15 +#define PMIC_DCXO_CW00_SET_ADDR MT6353_DCXO_CW00_SET +#define PMIC_DCXO_CW00_SET_MASK 0xFFFF +#define PMIC_DCXO_CW00_SET_SHIFT 0 +#define PMIC_DCXO_CW00_CLR_ADDR MT6353_DCXO_CW00_CLR +#define PMIC_DCXO_CW00_CLR_MASK 0xFFFF +#define PMIC_DCXO_CW00_CLR_SHIFT 0 +#define PMIC_XO_CLKSEL_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_CLKSEL_EN_M_MASK 0x1 +#define PMIC_XO_CLKSEL_EN_M_SHIFT 0 +#define PMIC_XO_EXTBUF1_CKG_MAN_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_EXTBUF1_CKG_MAN_MASK 0x1 +#define PMIC_XO_EXTBUF1_CKG_MAN_SHIFT 1 +#define PMIC_XO_EXTBUF1_CKG_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_EXTBUF1_CKG_EN_M_MASK 0x1 +#define PMIC_XO_EXTBUF1_CKG_EN_M_SHIFT 2 +#define PMIC_XO_EXTBUF2_CKG_MAN_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_EXTBUF2_CKG_MAN_MASK 0x1 +#define PMIC_XO_EXTBUF2_CKG_MAN_SHIFT 3 +#define PMIC_XO_EXTBUF2_CKG_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_EXTBUF2_CKG_EN_M_MASK 0x1 +#define PMIC_XO_EXTBUF2_CKG_EN_M_SHIFT 4 +#define PMIC_XO_EXTBUF3_CKG_MAN_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_EXTBUF3_CKG_MAN_MASK 0x1 +#define PMIC_XO_EXTBUF3_CKG_MAN_SHIFT 5 +#define PMIC_XO_EXTBUF3_CKG_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_EXTBUF3_CKG_EN_M_MASK 0x1 +#define PMIC_XO_EXTBUF3_CKG_EN_M_SHIFT 6 +#define PMIC_XO_EXTBUF4_CKG_MAN_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_EXTBUF4_CKG_MAN_MASK 0x1 +#define PMIC_XO_EXTBUF4_CKG_MAN_SHIFT 7 +#define PMIC_XO_EXTBUF4_CKG_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_EXTBUF4_CKG_EN_M_MASK 0x1 +#define PMIC_XO_EXTBUF4_CKG_EN_M_SHIFT 8 +#define PMIC_XO_INTBUF_MAN_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_INTBUF_MAN_MASK 0x1 +#define PMIC_XO_INTBUF_MAN_SHIFT 9 +#define PMIC_XO_PBUF_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_PBUF_EN_M_MASK 0x1 +#define PMIC_XO_PBUF_EN_M_SHIFT 10 +#define PMIC_XO_IBUF_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_IBUF_EN_M_MASK 0x1 +#define PMIC_XO_IBUF_EN_M_SHIFT 11 +#define PMIC_XO_LPMBUF_MAN_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_LPMBUF_MAN_MASK 0x1 +#define PMIC_XO_LPMBUF_MAN_SHIFT 12 +#define PMIC_XO_LPM_PREBUF_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_LPM_PREBUF_EN_M_MASK 0x1 +#define PMIC_XO_LPM_PREBUF_EN_M_SHIFT 13 +#define PMIC_XO_LPBUF_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_LPBUF_EN_M_MASK 0x1 +#define PMIC_XO_LPBUF_EN_M_SHIFT 14 +#define PMIC_XO_AUDIO_EN_M_ADDR MT6353_DCXO_CW01 +#define PMIC_XO_AUDIO_EN_M_MASK 0x1 +#define PMIC_XO_AUDIO_EN_M_SHIFT 15 +#define PMIC_XO_EN32K_MAN_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_EN32K_MAN_MASK 0x1 +#define PMIC_XO_EN32K_MAN_SHIFT 0 +#define PMIC_XO_EN32K_M_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_EN32K_M_MASK 0x1 +#define PMIC_XO_EN32K_M_SHIFT 1 +#define PMIC_XO_XMODE_MAN_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_XMODE_MAN_MASK 0x1 +#define PMIC_XO_XMODE_MAN_SHIFT 2 +#define PMIC_XO_XMODE_M_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_XMODE_M_MASK 0x1 +#define PMIC_XO_XMODE_M_SHIFT 3 +#define PMIC_XO_STRUP_MODE_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_STRUP_MODE_MASK 0x1 +#define PMIC_XO_STRUP_MODE_SHIFT 4 +#define PMIC_XO_AAC_FPM_TIME_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_AAC_FPM_TIME_MASK 0x3 +#define PMIC_XO_AAC_FPM_TIME_SHIFT 5 +#define PMIC_XO_AAC_MODE_LPM_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_AAC_MODE_LPM_MASK 0x3 +#define PMIC_XO_AAC_MODE_LPM_SHIFT 7 +#define PMIC_XO_AAC_MODE_FPM_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_AAC_MODE_FPM_MASK 0x3 +#define PMIC_XO_AAC_MODE_FPM_SHIFT 9 +#define PMIC_XO_EN26M_OFFSQ_EN_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_EN26M_OFFSQ_EN_MASK 0x1 +#define PMIC_XO_EN26M_OFFSQ_EN_SHIFT 11 +#define PMIC_XO_LDOCAL_EN_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_LDOCAL_EN_MASK 0x1 +#define PMIC_XO_LDOCAL_EN_SHIFT 12 +#define PMIC_XO_CBANK_SYNC_DYN_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_CBANK_SYNC_DYN_MASK 0x1 +#define PMIC_XO_CBANK_SYNC_DYN_SHIFT 13 +#define PMIC_XO_26MLP_MAN_EN_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_26MLP_MAN_EN_MASK 0x1 +#define PMIC_XO_26MLP_MAN_EN_SHIFT 14 +#define PMIC_XO_OPMODE_MAN_ADDR MT6353_DCXO_CW02 +#define PMIC_XO_OPMODE_MAN_MASK 0x1 +#define PMIC_XO_OPMODE_MAN_SHIFT 15 +#define PMIC_XO_BUFLDO13_VSET_M_ADDR MT6353_DCXO_CW03 +#define PMIC_XO_BUFLDO13_VSET_M_MASK 0xF +#define PMIC_XO_BUFLDO13_VSET_M_SHIFT 0 +#define PMIC_XO_RESERVED0_ADDR MT6353_DCXO_CW03 +#define PMIC_XO_RESERVED0_MASK 0x3 +#define PMIC_XO_RESERVED0_SHIFT 4 +#define PMIC_XO_LPM_ISEL_MAN_ADDR MT6353_DCXO_CW03 +#define PMIC_XO_LPM_ISEL_MAN_MASK 0x1F +#define PMIC_XO_LPM_ISEL_MAN_SHIFT 6 +#define PMIC_XO_FPM_ISEL_MAN_ADDR MT6353_DCXO_CW03 +#define PMIC_XO_FPM_ISEL_MAN_MASK 0x1F +#define PMIC_XO_FPM_ISEL_MAN_SHIFT 11 +#define PMIC_XO_CDAC_FPM_ADDR MT6353_DCXO_CW04 +#define PMIC_XO_CDAC_FPM_MASK 0xFF +#define PMIC_XO_CDAC_FPM_SHIFT 0 +#define PMIC_XO_CDAC_LPM_ADDR MT6353_DCXO_CW04 +#define PMIC_XO_CDAC_LPM_MASK 0xFF +#define PMIC_XO_CDAC_LPM_SHIFT 8 +#define PMIC_XO_32KDIV_NFRAC_FPM_ADDR MT6353_DCXO_CW05 +#define PMIC_XO_32KDIV_NFRAC_FPM_MASK 0x3FFF +#define PMIC_XO_32KDIV_NFRAC_FPM_SHIFT 0 +#define PMIC_XO_COFST_FPM_ADDR MT6353_DCXO_CW05 +#define PMIC_XO_COFST_FPM_MASK 0x3 +#define PMIC_XO_COFST_FPM_SHIFT 14 +#define PMIC_XO_32KDIV_NFRAC_LPM_ADDR MT6353_DCXO_CW06 +#define PMIC_XO_32KDIV_NFRAC_LPM_MASK 0x3FFF +#define PMIC_XO_32KDIV_NFRAC_LPM_SHIFT 0 +#define PMIC_XO_COFST_LPM_ADDR MT6353_DCXO_CW06 +#define PMIC_XO_COFST_LPM_MASK 0x3 +#define PMIC_XO_COFST_LPM_SHIFT 14 +#define PMIC_XO_CORE_MAN_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_MAN_MASK 0x1 +#define PMIC_XO_CORE_MAN_SHIFT 0 +#define PMIC_XO_CORE_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_EN_M_MASK 0x1 +#define PMIC_XO_CORE_EN_M_SHIFT 1 +#define PMIC_XO_CORE_TURBO_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_TURBO_EN_M_MASK 0x1 +#define PMIC_XO_CORE_TURBO_EN_M_SHIFT 2 +#define PMIC_XO_CORE_AAC_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_AAC_EN_M_MASK 0x1 +#define PMIC_XO_CORE_AAC_EN_M_SHIFT 3 +#define PMIC_XO_STARTUP_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_STARTUP_EN_M_MASK 0x1 +#define PMIC_XO_STARTUP_EN_M_SHIFT 4 +#define PMIC_XO_CORE_VBFPM_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_VBFPM_EN_M_MASK 0x1 +#define PMIC_XO_CORE_VBFPM_EN_M_SHIFT 5 +#define PMIC_XO_CORE_VBLPM_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_VBLPM_EN_M_MASK 0x1 +#define PMIC_XO_CORE_VBLPM_EN_M_SHIFT 6 +#define PMIC_XO_LPMBIAS_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_LPMBIAS_EN_M_MASK 0x1 +#define PMIC_XO_LPMBIAS_EN_M_SHIFT 7 +#define PMIC_XO_VTCGEN_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_VTCGEN_EN_M_MASK 0x1 +#define PMIC_XO_VTCGEN_EN_M_SHIFT 8 +#define PMIC_XO_IAAC_COMP_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_IAAC_COMP_EN_M_MASK 0x1 +#define PMIC_XO_IAAC_COMP_EN_M_SHIFT 9 +#define PMIC_XO_IFPM_COMP_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_IFPM_COMP_EN_M_MASK 0x1 +#define PMIC_XO_IFPM_COMP_EN_M_SHIFT 10 +#define PMIC_XO_ILPM_COMP_EN_M_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_ILPM_COMP_EN_M_MASK 0x1 +#define PMIC_XO_ILPM_COMP_EN_M_SHIFT 11 +#define PMIC_XO_CORE_BYPCAS_FPM_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_BYPCAS_FPM_MASK 0x1 +#define PMIC_XO_CORE_BYPCAS_FPM_SHIFT 12 +#define PMIC_XO_CORE_GMX2_FPM_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_GMX2_FPM_MASK 0x1 +#define PMIC_XO_CORE_GMX2_FPM_SHIFT 13 +#define PMIC_XO_CORE_IDAC_FPM_ADDR MT6353_DCXO_CW07 +#define PMIC_XO_CORE_IDAC_FPM_MASK 0x3 +#define PMIC_XO_CORE_IDAC_FPM_SHIFT 14 +#define PMIC_XO_AAC_COMP_MAN_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_COMP_MAN_MASK 0x1 +#define PMIC_XO_AAC_COMP_MAN_SHIFT 0 +#define PMIC_XO_AAC_EN_M_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_EN_M_MASK 0x1 +#define PMIC_XO_AAC_EN_M_SHIFT 1 +#define PMIC_XO_AAC_MONEN_M_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_MONEN_M_MASK 0x1 +#define PMIC_XO_AAC_MONEN_M_SHIFT 2 +#define PMIC_XO_COMP_EN_M_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_COMP_EN_M_MASK 0x1 +#define PMIC_XO_COMP_EN_M_SHIFT 3 +#define PMIC_XO_COMP_TSTEN_M_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_COMP_TSTEN_M_MASK 0x1 +#define PMIC_XO_COMP_TSTEN_M_SHIFT 4 +#define PMIC_XO_AAC_HV_FPM_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_HV_FPM_MASK 0x1 +#define PMIC_XO_AAC_HV_FPM_SHIFT 5 +#define PMIC_XO_AAC_IBIAS_FPM_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_IBIAS_FPM_MASK 0x3 +#define PMIC_XO_AAC_IBIAS_FPM_SHIFT 6 +#define PMIC_XO_AAC_VOFST_FPM_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_VOFST_FPM_MASK 0x3 +#define PMIC_XO_AAC_VOFST_FPM_SHIFT 8 +#define PMIC_XO_AAC_COMP_HV_FPM_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_COMP_HV_FPM_MASK 0x1 +#define PMIC_XO_AAC_COMP_HV_FPM_SHIFT 10 +#define PMIC_XO_AAC_VSEL_FPM_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_VSEL_FPM_MASK 0xF +#define PMIC_XO_AAC_VSEL_FPM_SHIFT 11 +#define PMIC_XO_AAC_COMP_POL_ADDR MT6353_DCXO_CW08 +#define PMIC_XO_AAC_COMP_POL_MASK 0x1 +#define PMIC_XO_AAC_COMP_POL_SHIFT 15 +#define PMIC_XO_CORE_BYPCAS_LPM_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_CORE_BYPCAS_LPM_MASK 0x1 +#define PMIC_XO_CORE_BYPCAS_LPM_SHIFT 0 +#define PMIC_XO_CORE_GMX2_LPM_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_CORE_GMX2_LPM_MASK 0x1 +#define PMIC_XO_CORE_GMX2_LPM_SHIFT 1 +#define PMIC_XO_CORE_IDAC_LPM_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_CORE_IDAC_LPM_MASK 0x3 +#define PMIC_XO_CORE_IDAC_LPM_SHIFT 2 +#define PMIC_XO_AAC_COMP_HV_LPM_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_AAC_COMP_HV_LPM_MASK 0x1 +#define PMIC_XO_AAC_COMP_HV_LPM_SHIFT 4 +#define PMIC_XO_AAC_VSEL_LPM_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_AAC_VSEL_LPM_MASK 0xF +#define PMIC_XO_AAC_VSEL_LPM_SHIFT 5 +#define PMIC_XO_AAC_HV_LPM_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_AAC_HV_LPM_MASK 0x1 +#define PMIC_XO_AAC_HV_LPM_SHIFT 9 +#define PMIC_XO_AAC_IBIAS_LPM_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_AAC_IBIAS_LPM_MASK 0x3 +#define PMIC_XO_AAC_IBIAS_LPM_SHIFT 10 +#define PMIC_XO_AAC_VOFST_LPM_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_AAC_VOFST_LPM_MASK 0x3 +#define PMIC_XO_AAC_VOFST_LPM_SHIFT 12 +#define PMIC_XO_AAC_FPM_SWEN_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_AAC_FPM_SWEN_MASK 0x1 +#define PMIC_XO_AAC_FPM_SWEN_SHIFT 14 +#define PMIC_XO_SWRST_ADDR MT6353_DCXO_CW09 +#define PMIC_XO_SWRST_MASK 0x1 +#define PMIC_XO_SWRST_SHIFT 15 +#define PMIC_XO_32KDIV_SWRST_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_32KDIV_SWRST_MASK 0x1 +#define PMIC_XO_32KDIV_SWRST_SHIFT 0 +#define PMIC_XO_32KDIV_RATIO_MAN_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_32KDIV_RATIO_MAN_MASK 0x1 +#define PMIC_XO_32KDIV_RATIO_MAN_SHIFT 1 +#define PMIC_XO_32KDIV_TEST_EN_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_32KDIV_TEST_EN_MASK 0x1 +#define PMIC_XO_32KDIV_TEST_EN_SHIFT 2 +#define PMIC_XO_CBANK_SYNC_MAN_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_CBANK_SYNC_MAN_MASK 0x1 +#define PMIC_XO_CBANK_SYNC_MAN_SHIFT 3 +#define PMIC_XO_CBANK_SYNC_EN_M_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_CBANK_SYNC_EN_M_MASK 0x1 +#define PMIC_XO_CBANK_SYNC_EN_M_SHIFT 4 +#define PMIC_XO_CTL_SYNC_MAN_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_CTL_SYNC_MAN_MASK 0x1 +#define PMIC_XO_CTL_SYNC_MAN_SHIFT 5 +#define PMIC_XO_CTL_SYNC_EN_M_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_CTL_SYNC_EN_M_MASK 0x1 +#define PMIC_XO_CTL_SYNC_EN_M_SHIFT 6 +#define PMIC_XO_LDO_MAN_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_LDO_MAN_MASK 0x1 +#define PMIC_XO_LDO_MAN_SHIFT 7 +#define PMIC_XO_LDOPBUF_EN_M_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_LDOPBUF_EN_M_MASK 0x1 +#define PMIC_XO_LDOPBUF_EN_M_SHIFT 8 +#define PMIC_XO_LDOPBUF_VSET_M_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_LDOPBUF_VSET_M_MASK 0xF +#define PMIC_XO_LDOPBUF_VSET_M_SHIFT 9 +#define PMIC_XO_LDOVTST_EN_M_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_LDOVTST_EN_M_MASK 0x1 +#define PMIC_XO_LDOVTST_EN_M_SHIFT 13 +#define PMIC_XO_TEST_VCAL_EN_M_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_TEST_VCAL_EN_M_MASK 0x1 +#define PMIC_XO_TEST_VCAL_EN_M_SHIFT 14 +#define PMIC_XO_VBIST_EN_M_ADDR MT6353_DCXO_CW10 +#define PMIC_XO_VBIST_EN_M_MASK 0x1 +#define PMIC_XO_VBIST_EN_M_SHIFT 15 +#define PMIC_XO_VTEST_SEL_MUX_ADDR MT6353_DCXO_CW11 +#define PMIC_XO_VTEST_SEL_MUX_MASK 0x1F +#define PMIC_XO_VTEST_SEL_MUX_SHIFT 0 +#define PMIC_RG_XO_CORE_OSCTD_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_CORE_OSCTD_MASK 0x3 +#define PMIC_RG_XO_CORE_OSCTD_SHIFT 5 +#define PMIC_RG_XO_THADC_EN_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_THADC_EN_MASK 0x1 +#define PMIC_RG_XO_THADC_EN_SHIFT 7 +#define PMIC_RG_XO_SYNC_CKPOL_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_SYNC_CKPOL_MASK 0x1 +#define PMIC_RG_XO_SYNC_CKPOL_SHIFT 8 +#define PMIC_RG_XO_CBANK_POL_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_CBANK_POL_MASK 0x1 +#define PMIC_RG_XO_CBANK_POL_SHIFT 9 +#define PMIC_RG_XO_CBANK_SYNC_BYP_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_CBANK_SYNC_BYP_MASK 0x1 +#define PMIC_RG_XO_CBANK_SYNC_BYP_SHIFT 10 +#define PMIC_RG_XO_CTL_POL_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_CTL_POL_MASK 0x1 +#define PMIC_RG_XO_CTL_POL_SHIFT 11 +#define PMIC_RG_XO_CTL_SYNC_BYP_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_CTL_SYNC_BYP_MASK 0x1 +#define PMIC_RG_XO_CTL_SYNC_BYP_SHIFT 12 +#define PMIC_RG_XO_LPBUF_INV_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_LPBUF_INV_MASK 0x1 +#define PMIC_RG_XO_LPBUF_INV_SHIFT 13 +#define PMIC_RG_XO_LDOPBUF_BYP_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_LDOPBUF_BYP_MASK 0x1 +#define PMIC_RG_XO_LDOPBUF_BYP_SHIFT 14 +#define PMIC_RG_XO_LDOPBUF_ENCL_ADDR MT6353_DCXO_CW11 +#define PMIC_RG_XO_LDOPBUF_ENCL_MASK 0x1 +#define PMIC_RG_XO_LDOPBUF_ENCL_SHIFT 15 +#define PMIC_RG_XO_VGBIAS_VSET_ADDR MT6353_DCXO_CW12 +#define PMIC_RG_XO_VGBIAS_VSET_MASK 0x3 +#define PMIC_RG_XO_VGBIAS_VSET_SHIFT 0 +#define PMIC_RG_XO_PBUF_ISET_ADDR MT6353_DCXO_CW12 +#define PMIC_RG_XO_PBUF_ISET_MASK 0x3 +#define PMIC_RG_XO_PBUF_ISET_SHIFT 2 +#define PMIC_RG_XO_IBUF_ISET_ADDR MT6353_DCXO_CW12 +#define PMIC_RG_XO_IBUF_ISET_MASK 0x3 +#define PMIC_RG_XO_IBUF_ISET_SHIFT 4 +#define PMIC_RG_XO_BUFLDO13_ENCL_ADDR MT6353_DCXO_CW12 +#define PMIC_RG_XO_BUFLDO13_ENCL_MASK 0x1 +#define PMIC_RG_XO_BUFLDO13_ENCL_SHIFT 6 +#define PMIC_RG_XO_BUFLDO13_IBX2_ADDR MT6353_DCXO_CW12 +#define PMIC_RG_XO_BUFLDO13_IBX2_MASK 0x1 +#define PMIC_RG_XO_BUFLDO13_IBX2_SHIFT 7 +#define PMIC_RG_XO_BUFLDO13_IX2_ADDR MT6353_DCXO_CW12 +#define PMIC_RG_XO_BUFLDO13_IX2_MASK 0x1 +#define PMIC_RG_XO_BUFLDO13_IX2_SHIFT 8 +#define PMIC_XO_RESERVED1_ADDR MT6353_DCXO_CW12 +#define PMIC_XO_RESERVED1_MASK 0x1 +#define PMIC_XO_RESERVED1_SHIFT 9 +#define PMIC_RG_XO_BUFLDO24_ENCL_ADDR MT6353_DCXO_CW12 +#define PMIC_RG_XO_BUFLDO24_ENCL_MASK 0x1 +#define PMIC_RG_XO_BUFLDO24_ENCL_SHIFT 10 +#define PMIC_RG_XO_BUFLDO24_IBX2_ADDR MT6353_DCXO_CW12 +#define PMIC_RG_XO_BUFLDO24_IBX2_MASK 0x1 +#define PMIC_RG_XO_BUFLDO24_IBX2_SHIFT 11 +#define PMIC_XO_BUFLDO24_VSET_M_ADDR MT6353_DCXO_CW12 +#define PMIC_XO_BUFLDO24_VSET_M_MASK 0xF +#define PMIC_XO_BUFLDO24_VSET_M_SHIFT 12 +#define PMIC_RG_XO_EXTBUF1_HD_ADDR MT6353_DCXO_CW13 +#define PMIC_RG_XO_EXTBUF1_HD_MASK 0x3 +#define PMIC_RG_XO_EXTBUF1_HD_SHIFT 0 +#define PMIC_RG_XO_EXTBUF1_ISET_ADDR MT6353_DCXO_CW13 +#define PMIC_RG_XO_EXTBUF1_ISET_MASK 0x3 +#define PMIC_RG_XO_EXTBUF1_ISET_SHIFT 2 +#define PMIC_RG_XO_EXTBUF2_HD_ADDR MT6353_DCXO_CW13 +#define PMIC_RG_XO_EXTBUF2_HD_MASK 0x3 +#define PMIC_RG_XO_EXTBUF2_HD_SHIFT 4 +#define PMIC_RG_XO_EXTBUF2_ISET_ADDR MT6353_DCXO_CW13 +#define PMIC_RG_XO_EXTBUF2_ISET_MASK 0x3 +#define PMIC_RG_XO_EXTBUF2_ISET_SHIFT 6 +#define PMIC_RG_XO_EXTBUF3_HD_ADDR MT6353_DCXO_CW13 +#define PMIC_RG_XO_EXTBUF3_HD_MASK 0x3 +#define PMIC_RG_XO_EXTBUF3_HD_SHIFT 8 +#define PMIC_RG_XO_EXTBUF3_ISET_ADDR MT6353_DCXO_CW13 +#define PMIC_RG_XO_EXTBUF3_ISET_MASK 0x3 +#define PMIC_RG_XO_EXTBUF3_ISET_SHIFT 10 +#define PMIC_RG_XO_EXTBUF4_HD_ADDR MT6353_DCXO_CW13 +#define PMIC_RG_XO_EXTBUF4_HD_MASK 0x3 +#define PMIC_RG_XO_EXTBUF4_HD_SHIFT 12 +#define PMIC_RG_XO_EXTBUF4_ISET_ADDR MT6353_DCXO_CW13 +#define PMIC_RG_XO_EXTBUF4_ISET_MASK 0x3 +#define PMIC_RG_XO_EXTBUF4_ISET_SHIFT 14 +#define PMIC_RG_XO_LPM_PREBUF_ISET_ADDR MT6353_DCXO_CW14 +#define PMIC_RG_XO_LPM_PREBUF_ISET_MASK 0x3 +#define PMIC_RG_XO_LPM_PREBUF_ISET_SHIFT 0 +#define PMIC_RG_XO_AUDIO_ATTEN_ADDR MT6353_DCXO_CW14 +#define PMIC_RG_XO_AUDIO_ATTEN_MASK 0x3 +#define PMIC_RG_XO_AUDIO_ATTEN_SHIFT 2 +#define PMIC_RG_XO_AUDIO_ISET_ADDR MT6353_DCXO_CW14 +#define PMIC_RG_XO_AUDIO_ISET_MASK 0x3 +#define PMIC_RG_XO_AUDIO_ISET_SHIFT 4 +#define PMIC_XO_EXTBUF4_CLKSEL_MAN_ADDR MT6353_DCXO_CW14 +#define PMIC_XO_EXTBUF4_CLKSEL_MAN_MASK 0x1 +#define PMIC_XO_EXTBUF4_CLKSEL_MAN_SHIFT 6 +#define PMIC_RG_XO_RESERVED0_ADDR MT6353_DCXO_CW14 +#define PMIC_RG_XO_RESERVED0_MASK 0x7 +#define PMIC_RG_XO_RESERVED0_SHIFT 7 +#define PMIC_XO_VIO18PG_BUFEN_ADDR MT6353_DCXO_CW14 +#define PMIC_XO_VIO18PG_BUFEN_MASK 0x1 +#define PMIC_XO_VIO18PG_BUFEN_SHIFT 10 +#define PMIC_RG_XO_RESERVED1_ADDR MT6353_DCXO_CW14 +#define PMIC_RG_XO_RESERVED1_MASK 0x7 +#define PMIC_RG_XO_RESERVED1_SHIFT 11 +#define PMIC_XO_CAL_EN_MAN_ADDR MT6353_DCXO_CW14 +#define PMIC_XO_CAL_EN_MAN_MASK 0x1 +#define PMIC_XO_CAL_EN_MAN_SHIFT 14 +#define PMIC_XO_CAL_EN_M_ADDR MT6353_DCXO_CW14 +#define PMIC_XO_CAL_EN_M_MASK 0x1 +#define PMIC_XO_CAL_EN_M_SHIFT 15 +#define PMIC_XO_STATIC_AUXOUT_SEL_ADDR MT6353_DCXO_CW15 +#define PMIC_XO_STATIC_AUXOUT_SEL_MASK 0x3F +#define PMIC_XO_STATIC_AUXOUT_SEL_SHIFT 0 +#define PMIC_XO_AUXOUT_SEL_ADDR MT6353_DCXO_CW15 +#define PMIC_XO_AUXOUT_SEL_MASK 0x3FF +#define PMIC_XO_AUXOUT_SEL_SHIFT 6 +#define PMIC_XO_STATIC_AUXOUT_ADDR MT6353_DCXO_CW16 +#define PMIC_XO_STATIC_AUXOUT_MASK 0xFFFF +#define PMIC_XO_STATIC_AUXOUT_SHIFT 0 +#define PMIC_AUXADC_ADC_OUT_CH0_ADDR MT6353_AUXADC_ADC0 +#define PMIC_AUXADC_ADC_OUT_CH0_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH0_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH0_ADDR MT6353_AUXADC_ADC0 +#define PMIC_AUXADC_ADC_RDY_CH0_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH0_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH1_ADDR MT6353_AUXADC_ADC1 +#define PMIC_AUXADC_ADC_OUT_CH1_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH1_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH1_ADDR MT6353_AUXADC_ADC1 +#define PMIC_AUXADC_ADC_RDY_CH1_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH1_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH2_ADDR MT6353_AUXADC_ADC2 +#define PMIC_AUXADC_ADC_OUT_CH2_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH2_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH2_ADDR MT6353_AUXADC_ADC2 +#define PMIC_AUXADC_ADC_RDY_CH2_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH2_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH3_ADDR MT6353_AUXADC_ADC3 +#define PMIC_AUXADC_ADC_OUT_CH3_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH3_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH3_ADDR MT6353_AUXADC_ADC3 +#define PMIC_AUXADC_ADC_RDY_CH3_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH3_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH4_ADDR MT6353_AUXADC_ADC4 +#define PMIC_AUXADC_ADC_OUT_CH4_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH4_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH4_ADDR MT6353_AUXADC_ADC4 +#define PMIC_AUXADC_ADC_RDY_CH4_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH4_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH5_ADDR MT6353_AUXADC_ADC5 +#define PMIC_AUXADC_ADC_OUT_CH5_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH5_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH5_ADDR MT6353_AUXADC_ADC5 +#define PMIC_AUXADC_ADC_RDY_CH5_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH5_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH6_ADDR MT6353_AUXADC_ADC6 +#define PMIC_AUXADC_ADC_OUT_CH6_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH6_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH6_ADDR MT6353_AUXADC_ADC6 +#define PMIC_AUXADC_ADC_RDY_CH6_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH6_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH7_ADDR MT6353_AUXADC_ADC7 +#define PMIC_AUXADC_ADC_OUT_CH7_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH7_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH7_ADDR MT6353_AUXADC_ADC7 +#define PMIC_AUXADC_ADC_RDY_CH7_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH7_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH8_ADDR MT6353_AUXADC_ADC8 +#define PMIC_AUXADC_ADC_OUT_CH8_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH8_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH8_ADDR MT6353_AUXADC_ADC8 +#define PMIC_AUXADC_ADC_RDY_CH8_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH8_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH9_ADDR MT6353_AUXADC_ADC9 +#define PMIC_AUXADC_ADC_OUT_CH9_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH9_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH9_ADDR MT6353_AUXADC_ADC9 +#define PMIC_AUXADC_ADC_RDY_CH9_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH9_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH10_ADDR MT6353_AUXADC_ADC10 +#define PMIC_AUXADC_ADC_OUT_CH10_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH10_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH10_ADDR MT6353_AUXADC_ADC10 +#define PMIC_AUXADC_ADC_RDY_CH10_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH10_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH11_ADDR MT6353_AUXADC_ADC11 +#define PMIC_AUXADC_ADC_OUT_CH11_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH11_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH11_ADDR MT6353_AUXADC_ADC11 +#define PMIC_AUXADC_ADC_RDY_CH11_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH11_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH12_15_ADDR MT6353_AUXADC_ADC12 +#define PMIC_AUXADC_ADC_OUT_CH12_15_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH12_15_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH12_15_ADDR MT6353_AUXADC_ADC12 +#define PMIC_AUXADC_ADC_RDY_CH12_15_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH12_15_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_THR_HW_ADDR MT6353_AUXADC_ADC13 +#define PMIC_AUXADC_ADC_OUT_THR_HW_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_THR_HW_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_THR_HW_ADDR MT6353_AUXADC_ADC13 +#define PMIC_AUXADC_ADC_RDY_THR_HW_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_THR_HW_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_LBAT_ADDR MT6353_AUXADC_ADC14 +#define PMIC_AUXADC_ADC_OUT_LBAT_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_LBAT_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_LBAT_ADDR MT6353_AUXADC_ADC14 +#define PMIC_AUXADC_ADC_RDY_LBAT_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_LBAT_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_LBAT2_ADDR MT6353_AUXADC_ADC15 +#define PMIC_AUXADC_ADC_OUT_LBAT2_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_LBAT2_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_LBAT2_ADDR MT6353_AUXADC_ADC15 +#define PMIC_AUXADC_ADC_RDY_LBAT2_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_LBAT2_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_ADDR MT6353_AUXADC_ADC16 +#define PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_ADDR MT6353_AUXADC_ADC16 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH7_BY_MD_ADDR MT6353_AUXADC_ADC17 +#define PMIC_AUXADC_ADC_OUT_CH7_BY_MD_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH7_BY_MD_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_MD_ADDR MT6353_AUXADC_ADC17 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_MD_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_MD_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH7_BY_AP_ADDR MT6353_AUXADC_ADC18 +#define PMIC_AUXADC_ADC_OUT_CH7_BY_AP_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH7_BY_AP_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_AP_ADDR MT6353_AUXADC_ADC18 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_AP_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH7_BY_AP_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH4_BY_MD_ADDR MT6353_AUXADC_ADC19 +#define PMIC_AUXADC_ADC_OUT_CH4_BY_MD_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_CH4_BY_MD_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH4_BY_MD_ADDR MT6353_AUXADC_ADC19 +#define PMIC_AUXADC_ADC_RDY_CH4_BY_MD_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH4_BY_MD_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_ADDR MT6353_AUXADC_ADC20 +#define PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_ADDR MT6353_AUXADC_ADC20 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_ADDR MT6353_AUXADC_ADC21 +#define PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_ADDR MT6353_AUXADC_ADC21 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH0_BY_MD_ADDR MT6353_AUXADC_ADC22 +#define PMIC_AUXADC_ADC_OUT_CH0_BY_MD_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH0_BY_MD_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH0_BY_MD_ADDR MT6353_AUXADC_ADC22 +#define PMIC_AUXADC_ADC_RDY_CH0_BY_MD_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH0_BY_MD_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH0_BY_AP_ADDR MT6353_AUXADC_ADC23 +#define PMIC_AUXADC_ADC_OUT_CH0_BY_AP_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH0_BY_AP_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH0_BY_AP_ADDR MT6353_AUXADC_ADC23 +#define PMIC_AUXADC_ADC_RDY_CH0_BY_AP_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH0_BY_AP_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH1_BY_MD_ADDR MT6353_AUXADC_ADC24 +#define PMIC_AUXADC_ADC_OUT_CH1_BY_MD_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH1_BY_MD_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH1_BY_MD_ADDR MT6353_AUXADC_ADC24 +#define PMIC_AUXADC_ADC_RDY_CH1_BY_MD_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH1_BY_MD_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_CH1_BY_AP_ADDR MT6353_AUXADC_ADC25 +#define PMIC_AUXADC_ADC_OUT_CH1_BY_AP_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_CH1_BY_AP_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_CH1_BY_AP_ADDR MT6353_AUXADC_ADC25 +#define PMIC_AUXADC_ADC_RDY_CH1_BY_AP_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_CH1_BY_AP_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_VISMPS0_ADDR MT6353_AUXADC_ADC26 +#define PMIC_AUXADC_ADC_OUT_VISMPS0_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_VISMPS0_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_VISMPS0_ADDR MT6353_AUXADC_ADC26 +#define PMIC_AUXADC_ADC_RDY_VISMPS0_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_VISMPS0_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_FGADC1_ADDR MT6353_AUXADC_ADC27 +#define PMIC_AUXADC_ADC_OUT_FGADC1_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_FGADC1_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_FGADC1_ADDR MT6353_AUXADC_ADC27 +#define PMIC_AUXADC_ADC_RDY_FGADC1_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_FGADC1_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_FGADC2_ADDR MT6353_AUXADC_ADC28 +#define PMIC_AUXADC_ADC_OUT_FGADC2_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_FGADC2_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_FGADC2_ADDR MT6353_AUXADC_ADC28 +#define PMIC_AUXADC_ADC_RDY_FGADC2_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_FGADC2_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_IMP_ADDR MT6353_AUXADC_ADC29 +#define PMIC_AUXADC_ADC_OUT_IMP_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_IMP_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_IMP_ADDR MT6353_AUXADC_ADC29 +#define PMIC_AUXADC_ADC_RDY_IMP_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_IMP_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_IMP_AVG_ADDR MT6353_AUXADC_ADC30 +#define PMIC_AUXADC_ADC_OUT_IMP_AVG_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_IMP_AVG_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_IMP_AVG_ADDR MT6353_AUXADC_ADC30 +#define PMIC_AUXADC_ADC_RDY_IMP_AVG_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_IMP_AVG_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_RAW_ADDR MT6353_AUXADC_ADC31 +#define PMIC_AUXADC_ADC_OUT_RAW_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_RAW_SHIFT 0 +#define PMIC_AUXADC_ADC_OUT_MDRT_ADDR MT6353_AUXADC_ADC32 +#define PMIC_AUXADC_ADC_OUT_MDRT_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_MDRT_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_MDRT_ADDR MT6353_AUXADC_ADC32 +#define PMIC_AUXADC_ADC_RDY_MDRT_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_MDRT_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_MDBG_ADDR MT6353_AUXADC_ADC33 +#define PMIC_AUXADC_ADC_OUT_MDBG_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_MDBG_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_MDBG_ADDR MT6353_AUXADC_ADC33 +#define PMIC_AUXADC_ADC_RDY_MDBG_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_MDBG_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_ADDR MT6353_AUXADC_ADC34 +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_ADDR MT6353_AUXADC_ADC34 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_ADDR MT6353_AUXADC_ADC35 +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_ADDR MT6353_AUXADC_ADC35 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_ADDR MT6353_AUXADC_ADC36 +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_ADDR MT6353_AUXADC_ADC36 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_DCXO_MDRT_ADDR MT6353_AUXADC_ADC37 +#define PMIC_AUXADC_ADC_OUT_DCXO_MDRT_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_DCXO_MDRT_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_DCXO_MDRT_ADDR MT6353_AUXADC_ADC37 +#define PMIC_AUXADC_ADC_RDY_DCXO_MDRT_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_DCXO_MDRT_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_NAG_ADDR MT6353_AUXADC_ADC38 +#define PMIC_AUXADC_ADC_OUT_NAG_MASK 0x7FFF +#define PMIC_AUXADC_ADC_OUT_NAG_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_NAG_ADDR MT6353_AUXADC_ADC38 +#define PMIC_AUXADC_ADC_RDY_NAG_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_NAG_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_TYPEC_H_ADDR MT6353_AUXADC_ADC39 +#define PMIC_AUXADC_ADC_OUT_TYPEC_H_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_TYPEC_H_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_TYPEC_H_ADDR MT6353_AUXADC_ADC39 +#define PMIC_AUXADC_ADC_RDY_TYPEC_H_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_TYPEC_H_SHIFT 15 +#define PMIC_AUXADC_ADC_OUT_TYPEC_L_ADDR MT6353_AUXADC_ADC40 +#define PMIC_AUXADC_ADC_OUT_TYPEC_L_MASK 0xFFF +#define PMIC_AUXADC_ADC_OUT_TYPEC_L_SHIFT 0 +#define PMIC_AUXADC_ADC_RDY_TYPEC_L_ADDR MT6353_AUXADC_ADC40 +#define PMIC_AUXADC_ADC_RDY_TYPEC_L_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_TYPEC_L_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_00_ADDR MT6353_AUXADC_BUF0 +#define PMIC_AUXADC_BUF_OUT_00_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_00_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_00_ADDR MT6353_AUXADC_BUF0 +#define PMIC_AUXADC_BUF_RDY_00_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_00_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_01_ADDR MT6353_AUXADC_BUF1 +#define PMIC_AUXADC_BUF_OUT_01_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_01_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_01_ADDR MT6353_AUXADC_BUF1 +#define PMIC_AUXADC_BUF_RDY_01_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_01_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_02_ADDR MT6353_AUXADC_BUF2 +#define PMIC_AUXADC_BUF_OUT_02_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_02_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_02_ADDR MT6353_AUXADC_BUF2 +#define PMIC_AUXADC_BUF_RDY_02_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_02_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_03_ADDR MT6353_AUXADC_BUF3 +#define PMIC_AUXADC_BUF_OUT_03_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_03_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_03_ADDR MT6353_AUXADC_BUF3 +#define PMIC_AUXADC_BUF_RDY_03_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_03_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_04_ADDR MT6353_AUXADC_BUF4 +#define PMIC_AUXADC_BUF_OUT_04_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_04_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_04_ADDR MT6353_AUXADC_BUF4 +#define PMIC_AUXADC_BUF_RDY_04_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_04_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_05_ADDR MT6353_AUXADC_BUF5 +#define PMIC_AUXADC_BUF_OUT_05_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_05_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_05_ADDR MT6353_AUXADC_BUF5 +#define PMIC_AUXADC_BUF_RDY_05_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_05_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_06_ADDR MT6353_AUXADC_BUF6 +#define PMIC_AUXADC_BUF_OUT_06_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_06_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_06_ADDR MT6353_AUXADC_BUF6 +#define PMIC_AUXADC_BUF_RDY_06_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_06_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_07_ADDR MT6353_AUXADC_BUF7 +#define PMIC_AUXADC_BUF_OUT_07_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_07_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_07_ADDR MT6353_AUXADC_BUF7 +#define PMIC_AUXADC_BUF_RDY_07_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_07_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_08_ADDR MT6353_AUXADC_BUF8 +#define PMIC_AUXADC_BUF_OUT_08_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_08_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_08_ADDR MT6353_AUXADC_BUF8 +#define PMIC_AUXADC_BUF_RDY_08_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_08_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_09_ADDR MT6353_AUXADC_BUF9 +#define PMIC_AUXADC_BUF_OUT_09_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_09_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_09_ADDR MT6353_AUXADC_BUF9 +#define PMIC_AUXADC_BUF_RDY_09_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_09_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_10_ADDR MT6353_AUXADC_BUF10 +#define PMIC_AUXADC_BUF_OUT_10_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_10_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_10_ADDR MT6353_AUXADC_BUF10 +#define PMIC_AUXADC_BUF_RDY_10_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_10_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_11_ADDR MT6353_AUXADC_BUF11 +#define PMIC_AUXADC_BUF_OUT_11_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_11_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_11_ADDR MT6353_AUXADC_BUF11 +#define PMIC_AUXADC_BUF_RDY_11_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_11_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_12_ADDR MT6353_AUXADC_BUF12 +#define PMIC_AUXADC_BUF_OUT_12_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_12_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_12_ADDR MT6353_AUXADC_BUF12 +#define PMIC_AUXADC_BUF_RDY_12_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_12_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_13_ADDR MT6353_AUXADC_BUF13 +#define PMIC_AUXADC_BUF_OUT_13_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_13_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_13_ADDR MT6353_AUXADC_BUF13 +#define PMIC_AUXADC_BUF_RDY_13_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_13_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_14_ADDR MT6353_AUXADC_BUF14 +#define PMIC_AUXADC_BUF_OUT_14_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_14_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_14_ADDR MT6353_AUXADC_BUF14 +#define PMIC_AUXADC_BUF_RDY_14_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_14_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_15_ADDR MT6353_AUXADC_BUF15 +#define PMIC_AUXADC_BUF_OUT_15_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_15_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_15_ADDR MT6353_AUXADC_BUF15 +#define PMIC_AUXADC_BUF_RDY_15_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_15_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_16_ADDR MT6353_AUXADC_BUF16 +#define PMIC_AUXADC_BUF_OUT_16_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_16_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_16_ADDR MT6353_AUXADC_BUF16 +#define PMIC_AUXADC_BUF_RDY_16_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_16_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_17_ADDR MT6353_AUXADC_BUF17 +#define PMIC_AUXADC_BUF_OUT_17_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_17_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_17_ADDR MT6353_AUXADC_BUF17 +#define PMIC_AUXADC_BUF_RDY_17_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_17_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_18_ADDR MT6353_AUXADC_BUF18 +#define PMIC_AUXADC_BUF_OUT_18_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_18_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_18_ADDR MT6353_AUXADC_BUF18 +#define PMIC_AUXADC_BUF_RDY_18_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_18_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_19_ADDR MT6353_AUXADC_BUF19 +#define PMIC_AUXADC_BUF_OUT_19_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_19_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_19_ADDR MT6353_AUXADC_BUF19 +#define PMIC_AUXADC_BUF_RDY_19_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_19_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_20_ADDR MT6353_AUXADC_BUF20 +#define PMIC_AUXADC_BUF_OUT_20_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_20_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_20_ADDR MT6353_AUXADC_BUF20 +#define PMIC_AUXADC_BUF_RDY_20_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_20_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_21_ADDR MT6353_AUXADC_BUF21 +#define PMIC_AUXADC_BUF_OUT_21_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_21_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_21_ADDR MT6353_AUXADC_BUF21 +#define PMIC_AUXADC_BUF_RDY_21_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_21_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_22_ADDR MT6353_AUXADC_BUF22 +#define PMIC_AUXADC_BUF_OUT_22_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_22_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_22_ADDR MT6353_AUXADC_BUF22 +#define PMIC_AUXADC_BUF_RDY_22_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_22_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_23_ADDR MT6353_AUXADC_BUF23 +#define PMIC_AUXADC_BUF_OUT_23_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_23_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_23_ADDR MT6353_AUXADC_BUF23 +#define PMIC_AUXADC_BUF_RDY_23_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_23_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_24_ADDR MT6353_AUXADC_BUF24 +#define PMIC_AUXADC_BUF_OUT_24_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_24_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_24_ADDR MT6353_AUXADC_BUF24 +#define PMIC_AUXADC_BUF_RDY_24_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_24_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_25_ADDR MT6353_AUXADC_BUF25 +#define PMIC_AUXADC_BUF_OUT_25_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_25_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_25_ADDR MT6353_AUXADC_BUF25 +#define PMIC_AUXADC_BUF_RDY_25_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_25_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_26_ADDR MT6353_AUXADC_BUF26 +#define PMIC_AUXADC_BUF_OUT_26_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_26_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_26_ADDR MT6353_AUXADC_BUF26 +#define PMIC_AUXADC_BUF_RDY_26_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_26_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_27_ADDR MT6353_AUXADC_BUF27 +#define PMIC_AUXADC_BUF_OUT_27_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_27_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_27_ADDR MT6353_AUXADC_BUF27 +#define PMIC_AUXADC_BUF_RDY_27_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_27_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_28_ADDR MT6353_AUXADC_BUF28 +#define PMIC_AUXADC_BUF_OUT_28_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_28_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_28_ADDR MT6353_AUXADC_BUF28 +#define PMIC_AUXADC_BUF_RDY_28_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_28_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_29_ADDR MT6353_AUXADC_BUF29 +#define PMIC_AUXADC_BUF_OUT_29_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_29_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_29_ADDR MT6353_AUXADC_BUF29 +#define PMIC_AUXADC_BUF_RDY_29_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_29_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_30_ADDR MT6353_AUXADC_BUF30 +#define PMIC_AUXADC_BUF_OUT_30_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_30_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_30_ADDR MT6353_AUXADC_BUF30 +#define PMIC_AUXADC_BUF_RDY_30_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_30_SHIFT 15 +#define PMIC_AUXADC_BUF_OUT_31_ADDR MT6353_AUXADC_BUF31 +#define PMIC_AUXADC_BUF_OUT_31_MASK 0x7FFF +#define PMIC_AUXADC_BUF_OUT_31_SHIFT 0 +#define PMIC_AUXADC_BUF_RDY_31_ADDR MT6353_AUXADC_BUF31 +#define PMIC_AUXADC_BUF_RDY_31_MASK 0x1 +#define PMIC_AUXADC_BUF_RDY_31_SHIFT 15 +#define PMIC_AUXADC_ADC_BUSY_IN_ADDR MT6353_AUXADC_STA0 +#define PMIC_AUXADC_ADC_BUSY_IN_MASK 0xFFF +#define PMIC_AUXADC_ADC_BUSY_IN_SHIFT 0 +#define PMIC_AUXADC_ADC_BUSY_IN_LBAT_ADDR MT6353_AUXADC_STA0 +#define PMIC_AUXADC_ADC_BUSY_IN_LBAT_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_LBAT_SHIFT 12 +#define PMIC_AUXADC_ADC_BUSY_IN_LBAT2_ADDR MT6353_AUXADC_STA0 +#define PMIC_AUXADC_ADC_BUSY_IN_LBAT2_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_LBAT2_SHIFT 13 +#define PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_ADDR MT6353_AUXADC_STA0 +#define PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_SHIFT 14 +#define PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_ADDR MT6353_AUXADC_STA0 +#define PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_SHIFT 15 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_SHIFT 0 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_SHIFT 1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_SHIFT 2 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_SHIFT 3 +#define PMIC_AUXADC_ADC_BUSY_IN_MDRT_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_MDRT_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_MDRT_SHIFT 5 +#define PMIC_AUXADC_ADC_BUSY_IN_MDBG_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_MDBG_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_MDBG_SHIFT 6 +#define PMIC_AUXADC_ADC_BUSY_IN_SHARE_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_SHARE_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_SHARE_SHIFT 7 +#define PMIC_AUXADC_ADC_BUSY_IN_IMP_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_IMP_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_IMP_SHIFT 8 +#define PMIC_AUXADC_ADC_BUSY_IN_FGADC1_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_FGADC1_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_FGADC1_SHIFT 9 +#define PMIC_AUXADC_ADC_BUSY_IN_FGADC2_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_FGADC2_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_FGADC2_SHIFT 10 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_SHIFT 11 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_SHIFT 12 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_GPS_SHIFT 13 +#define PMIC_AUXADC_ADC_BUSY_IN_THR_HW_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_THR_HW_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_THR_HW_SHIFT 14 +#define PMIC_AUXADC_ADC_BUSY_IN_THR_MD_ADDR MT6353_AUXADC_STA1 +#define PMIC_AUXADC_ADC_BUSY_IN_THR_MD_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_THR_MD_SHIFT 15 +#define PMIC_AUXADC_ADC_BUSY_IN_TYPEC_H_ADDR MT6353_AUXADC_STA2 +#define PMIC_AUXADC_ADC_BUSY_IN_TYPEC_H_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_TYPEC_H_SHIFT 13 +#define PMIC_AUXADC_ADC_BUSY_IN_TYPEC_L_ADDR MT6353_AUXADC_STA2 +#define PMIC_AUXADC_ADC_BUSY_IN_TYPEC_L_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_TYPEC_L_SHIFT 14 +#define PMIC_AUXADC_ADC_BUSY_IN_NAG_ADDR MT6353_AUXADC_STA2 +#define PMIC_AUXADC_ADC_BUSY_IN_NAG_MASK 0x1 +#define PMIC_AUXADC_ADC_BUSY_IN_NAG_SHIFT 15 +#define PMIC_AUXADC_RQST_CH0_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH0_MASK 0x1 +#define PMIC_AUXADC_RQST_CH0_SHIFT 0 +#define PMIC_AUXADC_RQST_CH1_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH1_MASK 0x1 +#define PMIC_AUXADC_RQST_CH1_SHIFT 1 +#define PMIC_AUXADC_RQST_CH2_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH2_MASK 0x1 +#define PMIC_AUXADC_RQST_CH2_SHIFT 2 +#define PMIC_AUXADC_RQST_CH3_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH3_MASK 0x1 +#define PMIC_AUXADC_RQST_CH3_SHIFT 3 +#define PMIC_AUXADC_RQST_CH4_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH4_MASK 0x1 +#define PMIC_AUXADC_RQST_CH4_SHIFT 4 +#define PMIC_AUXADC_RQST_CH5_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH5_MASK 0x1 +#define PMIC_AUXADC_RQST_CH5_SHIFT 5 +#define PMIC_AUXADC_RQST_CH6_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH6_MASK 0x1 +#define PMIC_AUXADC_RQST_CH6_SHIFT 6 +#define PMIC_AUXADC_RQST_CH7_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH7_MASK 0x1 +#define PMIC_AUXADC_RQST_CH7_SHIFT 7 +#define PMIC_AUXADC_RQST_CH8_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH8_MASK 0x1 +#define PMIC_AUXADC_RQST_CH8_SHIFT 8 +#define PMIC_AUXADC_RQST_CH9_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH9_MASK 0x1 +#define PMIC_AUXADC_RQST_CH9_SHIFT 9 +#define PMIC_AUXADC_RQST_CH10_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH10_MASK 0x1 +#define PMIC_AUXADC_RQST_CH10_SHIFT 10 +#define PMIC_AUXADC_RQST_CH11_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH11_MASK 0x1 +#define PMIC_AUXADC_RQST_CH11_SHIFT 11 +#define PMIC_AUXADC_RQST_CH12_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH12_MASK 0x1 +#define PMIC_AUXADC_RQST_CH12_SHIFT 12 +#define PMIC_AUXADC_RQST_CH13_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH13_MASK 0x1 +#define PMIC_AUXADC_RQST_CH13_SHIFT 13 +#define PMIC_AUXADC_RQST_CH14_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH14_MASK 0x1 +#define PMIC_AUXADC_RQST_CH14_SHIFT 14 +#define PMIC_AUXADC_RQST_CH15_ADDR MT6353_AUXADC_RQST0 +#define PMIC_AUXADC_RQST_CH15_MASK 0x1 +#define PMIC_AUXADC_RQST_CH15_SHIFT 15 +#define PMIC_AUXADC_RQST0_SET_ADDR MT6353_AUXADC_RQST0_SET +#define PMIC_AUXADC_RQST0_SET_MASK 0xFFFF +#define PMIC_AUXADC_RQST0_SET_SHIFT 0 +#define PMIC_AUXADC_RQST0_CLR_ADDR MT6353_AUXADC_RQST0_CLR +#define PMIC_AUXADC_RQST0_CLR_MASK 0xFFFF +#define PMIC_AUXADC_RQST0_CLR_SHIFT 0 +#define PMIC_AUXADC_RQST_CH0_BY_MD_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_CH0_BY_MD_MASK 0x1 +#define PMIC_AUXADC_RQST_CH0_BY_MD_SHIFT 0 +#define PMIC_AUXADC_RQST_CH1_BY_MD_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_CH1_BY_MD_MASK 0x1 +#define PMIC_AUXADC_RQST_CH1_BY_MD_SHIFT 1 +#define PMIC_AUXADC_RQST_RSV0_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_RSV0_MASK 0x3 +#define PMIC_AUXADC_RQST_RSV0_SHIFT 2 +#define PMIC_AUXADC_RQST_CH4_BY_MD_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_CH4_BY_MD_MASK 0x1 +#define PMIC_AUXADC_RQST_CH4_BY_MD_SHIFT 4 +#define PMIC_AUXADC_RQST_CH7_BY_MD_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_CH7_BY_MD_MASK 0x1 +#define PMIC_AUXADC_RQST_CH7_BY_MD_SHIFT 7 +#define PMIC_AUXADC_RQST_CH7_BY_GPS_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_CH7_BY_GPS_MASK 0x1 +#define PMIC_AUXADC_RQST_CH7_BY_GPS_SHIFT 8 +#define PMIC_AUXADC_RQST_DCXO_BY_MD_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_DCXO_BY_MD_MASK 0x1 +#define PMIC_AUXADC_RQST_DCXO_BY_MD_SHIFT 9 +#define PMIC_AUXADC_RQST_DCXO_BY_GPS_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_DCXO_BY_GPS_MASK 0x1 +#define PMIC_AUXADC_RQST_DCXO_BY_GPS_SHIFT 10 +#define PMIC_AUXADC_RQST_RSV1_ADDR MT6353_AUXADC_RQST1 +#define PMIC_AUXADC_RQST_RSV1_MASK 0x1F +#define PMIC_AUXADC_RQST_RSV1_SHIFT 11 +#define PMIC_AUXADC_RQST1_SET_ADDR MT6353_AUXADC_RQST1_SET +#define PMIC_AUXADC_RQST1_SET_MASK 0xFFFF +#define PMIC_AUXADC_RQST1_SET_SHIFT 0 +#define PMIC_AUXADC_RQST1_CLR_ADDR MT6353_AUXADC_RQST1_CLR +#define PMIC_AUXADC_RQST1_CLR_MASK 0xFFFF +#define PMIC_AUXADC_RQST1_CLR_SHIFT 0 +#define PMIC_AUXADC_CK_ON_EXTD_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_CK_ON_EXTD_MASK 0x3F +#define PMIC_AUXADC_CK_ON_EXTD_SHIFT 0 +#define PMIC_AUXADC_SRCLKEN_SRC_SEL_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_SRCLKEN_SRC_SEL_MASK 0x3 +#define PMIC_AUXADC_SRCLKEN_SRC_SEL_SHIFT 6 +#define PMIC_AUXADC_ADC_PWDB_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_ADC_PWDB_MASK 0x1 +#define PMIC_AUXADC_ADC_PWDB_SHIFT 8 +#define PMIC_AUXADC_ADC_PWDB_SWCTRL_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_ADC_PWDB_SWCTRL_MASK 0x1 +#define PMIC_AUXADC_ADC_PWDB_SWCTRL_SHIFT 9 +#define PMIC_AUXADC_STRUP_CK_ON_ENB_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_STRUP_CK_ON_ENB_MASK 0x1 +#define PMIC_AUXADC_STRUP_CK_ON_ENB_SHIFT 10 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_MASK 0x1 +#define PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_SHIFT 11 +#define PMIC_AUXADC_SRCLKEN_CK_EN_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_SRCLKEN_CK_EN_MASK 0x1 +#define PMIC_AUXADC_SRCLKEN_CK_EN_SHIFT 12 +#define PMIC_AUXADC_CK_AON_GPS_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_CK_AON_GPS_MASK 0x1 +#define PMIC_AUXADC_CK_AON_GPS_SHIFT 13 +#define PMIC_AUXADC_CK_AON_MD_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_CK_AON_MD_MASK 0x1 +#define PMIC_AUXADC_CK_AON_MD_SHIFT 14 +#define PMIC_AUXADC_CK_AON_ADDR MT6353_AUXADC_CON0 +#define PMIC_AUXADC_CK_AON_MASK 0x1 +#define PMIC_AUXADC_CK_AON_SHIFT 15 +#define PMIC_AUXADC_CON0_SET_ADDR MT6353_AUXADC_CON0_SET +#define PMIC_AUXADC_CON0_SET_MASK 0xFFFF +#define PMIC_AUXADC_CON0_SET_SHIFT 0 +#define PMIC_AUXADC_CON0_CLR_ADDR MT6353_AUXADC_CON0_CLR +#define PMIC_AUXADC_CON0_CLR_MASK 0xFFFF +#define PMIC_AUXADC_CON0_CLR_SHIFT 0 +#define PMIC_AUXADC_AVG_NUM_SMALL_ADDR MT6353_AUXADC_CON1 +#define PMIC_AUXADC_AVG_NUM_SMALL_MASK 0x7 +#define PMIC_AUXADC_AVG_NUM_SMALL_SHIFT 0 +#define PMIC_AUXADC_AVG_NUM_LARGE_ADDR MT6353_AUXADC_CON1 +#define PMIC_AUXADC_AVG_NUM_LARGE_MASK 0x7 +#define PMIC_AUXADC_AVG_NUM_LARGE_SHIFT 3 +#define PMIC_AUXADC_SPL_NUM_ADDR MT6353_AUXADC_CON1 +#define PMIC_AUXADC_SPL_NUM_MASK 0x3FF +#define PMIC_AUXADC_SPL_NUM_SHIFT 6 +#define PMIC_AUXADC_AVG_NUM_SEL_ADDR MT6353_AUXADC_CON2 +#define PMIC_AUXADC_AVG_NUM_SEL_MASK 0xFFF +#define PMIC_AUXADC_AVG_NUM_SEL_SHIFT 0 +#define PMIC_AUXADC_AVG_NUM_SEL_SHARE_ADDR MT6353_AUXADC_CON2 +#define PMIC_AUXADC_AVG_NUM_SEL_SHARE_MASK 0x1 +#define PMIC_AUXADC_AVG_NUM_SEL_SHARE_SHIFT 12 +#define PMIC_AUXADC_AVG_NUM_SEL_LBAT_ADDR MT6353_AUXADC_CON2 +#define PMIC_AUXADC_AVG_NUM_SEL_LBAT_MASK 0x1 +#define PMIC_AUXADC_AVG_NUM_SEL_LBAT_SHIFT 13 +#define PMIC_AUXADC_AVG_NUM_SEL_VISMPS_ADDR MT6353_AUXADC_CON2 +#define PMIC_AUXADC_AVG_NUM_SEL_VISMPS_MASK 0x1 +#define PMIC_AUXADC_AVG_NUM_SEL_VISMPS_SHIFT 14 +#define PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_ADDR MT6353_AUXADC_CON2 +#define PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_MASK 0x1 +#define PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_SHIFT 15 +#define PMIC_AUXADC_SPL_NUM_LARGE_ADDR MT6353_AUXADC_CON3 +#define PMIC_AUXADC_SPL_NUM_LARGE_MASK 0x3FF +#define PMIC_AUXADC_SPL_NUM_LARGE_SHIFT 0 +#define PMIC_AUXADC_SPL_NUM_SLEEP_ADDR MT6353_AUXADC_CON4 +#define PMIC_AUXADC_SPL_NUM_SLEEP_MASK 0x3FF +#define PMIC_AUXADC_SPL_NUM_SLEEP_SHIFT 0 +#define PMIC_AUXADC_SPL_NUM_SLEEP_SEL_ADDR MT6353_AUXADC_CON4 +#define PMIC_AUXADC_SPL_NUM_SLEEP_SEL_MASK 0x1 +#define PMIC_AUXADC_SPL_NUM_SLEEP_SEL_SHIFT 15 +#define PMIC_AUXADC_SPL_NUM_SEL_ADDR MT6353_AUXADC_CON5 +#define PMIC_AUXADC_SPL_NUM_SEL_MASK 0xFFF +#define PMIC_AUXADC_SPL_NUM_SEL_SHIFT 0 +#define PMIC_AUXADC_SPL_NUM_SEL_SHARE_ADDR MT6353_AUXADC_CON5 +#define PMIC_AUXADC_SPL_NUM_SEL_SHARE_MASK 0x1 +#define PMIC_AUXADC_SPL_NUM_SEL_SHARE_SHIFT 12 +#define PMIC_AUXADC_SPL_NUM_SEL_LBAT_ADDR MT6353_AUXADC_CON5 +#define PMIC_AUXADC_SPL_NUM_SEL_LBAT_MASK 0x1 +#define PMIC_AUXADC_SPL_NUM_SEL_LBAT_SHIFT 13 +#define PMIC_AUXADC_SPL_NUM_SEL_VISMPS_ADDR MT6353_AUXADC_CON5 +#define PMIC_AUXADC_SPL_NUM_SEL_VISMPS_MASK 0x1 +#define PMIC_AUXADC_SPL_NUM_SEL_VISMPS_SHIFT 14 +#define PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_ADDR MT6353_AUXADC_CON5 +#define PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_MASK 0x1 +#define PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_SHIFT 15 +#define PMIC_AUXADC_TRIM_CH0_SEL_ADDR MT6353_AUXADC_CON6 +#define PMIC_AUXADC_TRIM_CH0_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH0_SEL_SHIFT 0 +#define PMIC_AUXADC_TRIM_CH1_SEL_ADDR MT6353_AUXADC_CON6 +#define PMIC_AUXADC_TRIM_CH1_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH1_SEL_SHIFT 2 +#define PMIC_AUXADC_TRIM_CH2_SEL_ADDR MT6353_AUXADC_CON6 +#define PMIC_AUXADC_TRIM_CH2_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH2_SEL_SHIFT 4 +#define PMIC_AUXADC_TRIM_CH3_SEL_ADDR MT6353_AUXADC_CON6 +#define PMIC_AUXADC_TRIM_CH3_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH3_SEL_SHIFT 6 +#define PMIC_AUXADC_TRIM_CH4_SEL_ADDR MT6353_AUXADC_CON6 +#define PMIC_AUXADC_TRIM_CH4_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH4_SEL_SHIFT 8 +#define PMIC_AUXADC_TRIM_CH5_SEL_ADDR MT6353_AUXADC_CON6 +#define PMIC_AUXADC_TRIM_CH5_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH5_SEL_SHIFT 10 +#define PMIC_AUXADC_TRIM_CH6_SEL_ADDR MT6353_AUXADC_CON6 +#define PMIC_AUXADC_TRIM_CH6_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH6_SEL_SHIFT 12 +#define PMIC_AUXADC_TRIM_CH7_SEL_ADDR MT6353_AUXADC_CON6 +#define PMIC_AUXADC_TRIM_CH7_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH7_SEL_SHIFT 14 +#define PMIC_AUXADC_TRIM_CH8_SEL_ADDR MT6353_AUXADC_CON7 +#define PMIC_AUXADC_TRIM_CH8_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH8_SEL_SHIFT 0 +#define PMIC_AUXADC_TRIM_CH9_SEL_ADDR MT6353_AUXADC_CON7 +#define PMIC_AUXADC_TRIM_CH9_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH9_SEL_SHIFT 2 +#define PMIC_AUXADC_TRIM_CH10_SEL_ADDR MT6353_AUXADC_CON7 +#define PMIC_AUXADC_TRIM_CH10_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH10_SEL_SHIFT 4 +#define PMIC_AUXADC_TRIM_CH11_SEL_ADDR MT6353_AUXADC_CON7 +#define PMIC_AUXADC_TRIM_CH11_SEL_MASK 0x3 +#define PMIC_AUXADC_TRIM_CH11_SEL_SHIFT 6 +#define PMIC_AUXADC_ADC_2S_COMP_ENB_ADDR MT6353_AUXADC_CON7 +#define PMIC_AUXADC_ADC_2S_COMP_ENB_MASK 0x1 +#define PMIC_AUXADC_ADC_2S_COMP_ENB_SHIFT 14 +#define PMIC_AUXADC_ADC_TRIM_COMP_ADDR MT6353_AUXADC_CON7 +#define PMIC_AUXADC_ADC_TRIM_COMP_MASK 0x1 +#define PMIC_AUXADC_ADC_TRIM_COMP_SHIFT 15 +#define PMIC_AUXADC_SW_GAIN_TRIM_ADDR MT6353_AUXADC_CON8 +#define PMIC_AUXADC_SW_GAIN_TRIM_MASK 0x7FFF +#define PMIC_AUXADC_SW_GAIN_TRIM_SHIFT 0 +#define PMIC_AUXADC_SW_OFFSET_TRIM_ADDR MT6353_AUXADC_CON9 +#define PMIC_AUXADC_SW_OFFSET_TRIM_MASK 0x7FFF +#define PMIC_AUXADC_SW_OFFSET_TRIM_SHIFT 0 +#define PMIC_AUXADC_RNG_EN_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_RNG_EN_MASK 0x1 +#define PMIC_AUXADC_RNG_EN_SHIFT 0 +#define PMIC_AUXADC_DATA_REUSE_SEL_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_DATA_REUSE_SEL_MASK 0x3 +#define PMIC_AUXADC_DATA_REUSE_SEL_SHIFT 1 +#define PMIC_AUXADC_TEST_MODE_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_TEST_MODE_MASK 0x1 +#define PMIC_AUXADC_TEST_MODE_SHIFT 3 +#define PMIC_AUXADC_BIT_SEL_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_BIT_SEL_MASK 0x1 +#define PMIC_AUXADC_BIT_SEL_SHIFT 4 +#define PMIC_AUXADC_START_SW_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_START_SW_MASK 0x1 +#define PMIC_AUXADC_START_SW_SHIFT 5 +#define PMIC_AUXADC_START_SWCTRL_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_START_SWCTRL_MASK 0x1 +#define PMIC_AUXADC_START_SWCTRL_SHIFT 6 +#define PMIC_AUXADC_TS_VBE_SEL_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_TS_VBE_SEL_MASK 0x1 +#define PMIC_AUXADC_TS_VBE_SEL_SHIFT 7 +#define PMIC_AUXADC_TS_VBE_SEL_SWCTRL_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_TS_VBE_SEL_SWCTRL_MASK 0x1 +#define PMIC_AUXADC_TS_VBE_SEL_SWCTRL_SHIFT 8 +#define PMIC_AUXADC_VBUF_EN_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_VBUF_EN_MASK 0x1 +#define PMIC_AUXADC_VBUF_EN_SHIFT 9 +#define PMIC_AUXADC_VBUF_EN_SWCTRL_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_VBUF_EN_SWCTRL_MASK 0x1 +#define PMIC_AUXADC_VBUF_EN_SWCTRL_SHIFT 10 +#define PMIC_AUXADC_OUT_SEL_ADDR MT6353_AUXADC_CON10 +#define PMIC_AUXADC_OUT_SEL_MASK 0x1 +#define PMIC_AUXADC_OUT_SEL_SHIFT 11 +#define PMIC_AUXADC_DA_DAC_ADDR MT6353_AUXADC_CON11 +#define PMIC_AUXADC_DA_DAC_MASK 0xFFF +#define PMIC_AUXADC_DA_DAC_SHIFT 0 +#define PMIC_AUXADC_DA_DAC_SWCTRL_ADDR MT6353_AUXADC_CON11 +#define PMIC_AUXADC_DA_DAC_SWCTRL_MASK 0x1 +#define PMIC_AUXADC_DA_DAC_SWCTRL_SHIFT 12 +#define PMIC_AD_AUXADC_COMP_ADDR MT6353_AUXADC_CON11 +#define PMIC_AD_AUXADC_COMP_MASK 0x1 +#define PMIC_AD_AUXADC_COMP_SHIFT 15 +#define PMIC_RG_VBUF_EXTEN_ADDR MT6353_AUXADC_CON12 +#define PMIC_RG_VBUF_EXTEN_MASK 0x1 +#define PMIC_RG_VBUF_EXTEN_SHIFT 0 +#define PMIC_RG_VBUF_CALEN_ADDR MT6353_AUXADC_CON12 +#define PMIC_RG_VBUF_CALEN_MASK 0x1 +#define PMIC_RG_VBUF_CALEN_SHIFT 1 +#define PMIC_RG_VBUF_BYP_ADDR MT6353_AUXADC_CON12 +#define PMIC_RG_VBUF_BYP_MASK 0x1 +#define PMIC_RG_VBUF_BYP_SHIFT 2 +#define PMIC_RG_AUX_RSV_ADDR MT6353_AUXADC_CON12 +#define PMIC_RG_AUX_RSV_MASK 0xF +#define PMIC_RG_AUX_RSV_SHIFT 3 +#define PMIC_RG_AUXADC_CALI_ADDR MT6353_AUXADC_CON12 +#define PMIC_RG_AUXADC_CALI_MASK 0xF +#define PMIC_RG_AUXADC_CALI_SHIFT 7 +#define PMIC_RG_VBUF_EN_ADDR MT6353_AUXADC_CON12 +#define PMIC_RG_VBUF_EN_MASK 0x1 +#define PMIC_RG_VBUF_EN_SHIFT 11 +#define PMIC_RG_VBE_SEL_ADDR MT6353_AUXADC_CON12 +#define PMIC_RG_VBE_SEL_MASK 0x1 +#define PMIC_RG_VBE_SEL_SHIFT 12 +#define PMIC_AUXADC_ADCIN_VSEN_EN_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_ADCIN_VSEN_EN_MASK 0x1 +#define PMIC_AUXADC_ADCIN_VSEN_EN_SHIFT 0 +#define PMIC_AUXADC_ADCIN_VBAT_EN_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_ADCIN_VBAT_EN_MASK 0x1 +#define PMIC_AUXADC_ADCIN_VBAT_EN_SHIFT 1 +#define PMIC_AUXADC_ADCIN_VSEN_MUX_EN_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_ADCIN_VSEN_MUX_EN_MASK 0x1 +#define PMIC_AUXADC_ADCIN_VSEN_MUX_EN_SHIFT 2 +#define PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_MASK 0x1 +#define PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_SHIFT 3 +#define PMIC_AUXADC_ADCIN_CHR_EN_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_ADCIN_CHR_EN_MASK 0x1 +#define PMIC_AUXADC_ADCIN_CHR_EN_SHIFT 4 +#define PMIC_AUXADC_ADCIN_BATON_TDET_EN_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_ADCIN_BATON_TDET_EN_MASK 0x1 +#define PMIC_AUXADC_ADCIN_BATON_TDET_EN_SHIFT 5 +#define PMIC_AUXADC_ACCDET_ANASWCTRL_EN_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_ACCDET_ANASWCTRL_EN_MASK 0x1 +#define PMIC_AUXADC_ACCDET_ANASWCTRL_EN_SHIFT 6 +#define PMIC_AUXADC_DIG0_RSV0_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_DIG0_RSV0_MASK 0xF +#define PMIC_AUXADC_DIG0_RSV0_SHIFT 7 +#define PMIC_AUXADC_CHSEL_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_CHSEL_MASK 0xF +#define PMIC_AUXADC_CHSEL_SHIFT 11 +#define PMIC_AUXADC_SWCTRL_EN_ADDR MT6353_AUXADC_CON13 +#define PMIC_AUXADC_SWCTRL_EN_MASK 0x1 +#define PMIC_AUXADC_SWCTRL_EN_SHIFT 15 +#define PMIC_AUXADC_SOURCE_LBAT_SEL_ADDR MT6353_AUXADC_CON14 +#define PMIC_AUXADC_SOURCE_LBAT_SEL_MASK 0x1 +#define PMIC_AUXADC_SOURCE_LBAT_SEL_SHIFT 0 +#define PMIC_AUXADC_SOURCE_LBAT2_SEL_ADDR MT6353_AUXADC_CON14 +#define PMIC_AUXADC_SOURCE_LBAT2_SEL_MASK 0x1 +#define PMIC_AUXADC_SOURCE_LBAT2_SEL_SHIFT 1 +#define PMIC_AUXADC_DIG0_RSV2_ADDR MT6353_AUXADC_CON14 +#define PMIC_AUXADC_DIG0_RSV2_MASK 0x7 +#define PMIC_AUXADC_DIG0_RSV2_SHIFT 2 +#define PMIC_AUXADC_DIG1_RSV2_ADDR MT6353_AUXADC_CON14 +#define PMIC_AUXADC_DIG1_RSV2_MASK 0xF +#define PMIC_AUXADC_DIG1_RSV2_SHIFT 5 +#define PMIC_AUXADC_DAC_EXTD_ADDR MT6353_AUXADC_CON14 +#define PMIC_AUXADC_DAC_EXTD_MASK 0xF +#define PMIC_AUXADC_DAC_EXTD_SHIFT 11 +#define PMIC_AUXADC_DAC_EXTD_EN_ADDR MT6353_AUXADC_CON14 +#define PMIC_AUXADC_DAC_EXTD_EN_MASK 0x1 +#define PMIC_AUXADC_DAC_EXTD_EN_SHIFT 15 +#define PMIC_AUXADC_PMU_THR_PDN_SW_ADDR MT6353_AUXADC_CON15 +#define PMIC_AUXADC_PMU_THR_PDN_SW_MASK 0x1 +#define PMIC_AUXADC_PMU_THR_PDN_SW_SHIFT 10 +#define PMIC_AUXADC_PMU_THR_PDN_SEL_ADDR MT6353_AUXADC_CON15 +#define PMIC_AUXADC_PMU_THR_PDN_SEL_MASK 0x1 +#define PMIC_AUXADC_PMU_THR_PDN_SEL_SHIFT 11 +#define PMIC_AUXADC_PMU_THR_PDN_STATUS_ADDR MT6353_AUXADC_CON15 +#define PMIC_AUXADC_PMU_THR_PDN_STATUS_MASK 0x1 +#define PMIC_AUXADC_PMU_THR_PDN_STATUS_SHIFT 12 +#define PMIC_AUXADC_DIG0_RSV1_ADDR MT6353_AUXADC_CON15 +#define PMIC_AUXADC_DIG0_RSV1_MASK 0x7 +#define PMIC_AUXADC_DIG0_RSV1_SHIFT 13 +#define PMIC_AUXADC_START_SHADE_NUM_ADDR MT6353_AUXADC_CON16 +#define PMIC_AUXADC_START_SHADE_NUM_MASK 0x3FF +#define PMIC_AUXADC_START_SHADE_NUM_SHIFT 0 +#define PMIC_AUXADC_START_SHADE_EN_ADDR MT6353_AUXADC_CON16 +#define PMIC_AUXADC_START_SHADE_EN_MASK 0x1 +#define PMIC_AUXADC_START_SHADE_EN_SHIFT 14 +#define PMIC_AUXADC_START_SHADE_SEL_ADDR MT6353_AUXADC_CON16 +#define PMIC_AUXADC_START_SHADE_SEL_MASK 0x1 +#define PMIC_AUXADC_START_SHADE_SEL_SHIFT 15 +#define PMIC_AUXADC_AUTORPT_PRD_ADDR MT6353_AUXADC_AUTORPT0 +#define PMIC_AUXADC_AUTORPT_PRD_MASK 0x3FF +#define PMIC_AUXADC_AUTORPT_PRD_SHIFT 0 +#define PMIC_AUXADC_AUTORPT_EN_ADDR MT6353_AUXADC_AUTORPT0 +#define PMIC_AUXADC_AUTORPT_EN_MASK 0x1 +#define PMIC_AUXADC_AUTORPT_EN_SHIFT 15 +#define PMIC_AUXADC_LBAT_DEBT_MAX_ADDR MT6353_AUXADC_LBAT0 +#define PMIC_AUXADC_LBAT_DEBT_MAX_MASK 0xFF +#define PMIC_AUXADC_LBAT_DEBT_MAX_SHIFT 0 +#define PMIC_AUXADC_LBAT_DEBT_MIN_ADDR MT6353_AUXADC_LBAT0 +#define PMIC_AUXADC_LBAT_DEBT_MIN_MASK 0xFF +#define PMIC_AUXADC_LBAT_DEBT_MIN_SHIFT 8 +#define PMIC_AUXADC_LBAT_DET_PRD_15_0_ADDR MT6353_AUXADC_LBAT1 +#define PMIC_AUXADC_LBAT_DET_PRD_15_0_MASK 0xFFFF +#define PMIC_AUXADC_LBAT_DET_PRD_15_0_SHIFT 0 +#define PMIC_AUXADC_LBAT_DET_PRD_19_16_ADDR MT6353_AUXADC_LBAT2 +#define PMIC_AUXADC_LBAT_DET_PRD_19_16_MASK 0xF +#define PMIC_AUXADC_LBAT_DET_PRD_19_16_SHIFT 0 +#define PMIC_AUXADC_LBAT_VOLT_MAX_ADDR MT6353_AUXADC_LBAT3 +#define PMIC_AUXADC_LBAT_VOLT_MAX_MASK 0xFFF +#define PMIC_AUXADC_LBAT_VOLT_MAX_SHIFT 0 +#define PMIC_AUXADC_LBAT_IRQ_EN_MAX_ADDR MT6353_AUXADC_LBAT3 +#define PMIC_AUXADC_LBAT_IRQ_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_LBAT_IRQ_EN_MAX_SHIFT 12 +#define PMIC_AUXADC_LBAT_EN_MAX_ADDR MT6353_AUXADC_LBAT3 +#define PMIC_AUXADC_LBAT_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_LBAT_EN_MAX_SHIFT 13 +#define PMIC_AUXADC_LBAT_MAX_IRQ_B_ADDR MT6353_AUXADC_LBAT3 +#define PMIC_AUXADC_LBAT_MAX_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_LBAT_MAX_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_LBAT_VOLT_MIN_ADDR MT6353_AUXADC_LBAT4 +#define PMIC_AUXADC_LBAT_VOLT_MIN_MASK 0xFFF +#define PMIC_AUXADC_LBAT_VOLT_MIN_SHIFT 0 +#define PMIC_AUXADC_LBAT_IRQ_EN_MIN_ADDR MT6353_AUXADC_LBAT4 +#define PMIC_AUXADC_LBAT_IRQ_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_LBAT_IRQ_EN_MIN_SHIFT 12 +#define PMIC_AUXADC_LBAT_EN_MIN_ADDR MT6353_AUXADC_LBAT4 +#define PMIC_AUXADC_LBAT_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_LBAT_EN_MIN_SHIFT 13 +#define PMIC_AUXADC_LBAT_MIN_IRQ_B_ADDR MT6353_AUXADC_LBAT4 +#define PMIC_AUXADC_LBAT_MIN_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_LBAT_MIN_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_ADDR MT6353_AUXADC_LBAT5 +#define PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_ADDR MT6353_AUXADC_LBAT6 +#define PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define PMIC_AUXADC_ACCDET_AUTO_SPL_ADDR MT6353_AUXADC_ACCDET +#define PMIC_AUXADC_ACCDET_AUTO_SPL_MASK 0x1 +#define PMIC_AUXADC_ACCDET_AUTO_SPL_SHIFT 0 +#define PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_ADDR MT6353_AUXADC_ACCDET +#define PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_MASK 0x1 +#define PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_SHIFT 1 +#define PMIC_AUXADC_ACCDET_DIG1_RSV0_ADDR MT6353_AUXADC_ACCDET +#define PMIC_AUXADC_ACCDET_DIG1_RSV0_MASK 0x3F +#define PMIC_AUXADC_ACCDET_DIG1_RSV0_SHIFT 2 +#define PMIC_AUXADC_ACCDET_DIG0_RSV0_ADDR MT6353_AUXADC_ACCDET +#define PMIC_AUXADC_ACCDET_DIG0_RSV0_MASK 0xFF +#define PMIC_AUXADC_ACCDET_DIG0_RSV0_SHIFT 8 +#define PMIC_AUXADC_THR_DEBT_MAX_ADDR MT6353_AUXADC_THR0 +#define PMIC_AUXADC_THR_DEBT_MAX_MASK 0xFF +#define PMIC_AUXADC_THR_DEBT_MAX_SHIFT 0 +#define PMIC_AUXADC_THR_DEBT_MIN_ADDR MT6353_AUXADC_THR0 +#define PMIC_AUXADC_THR_DEBT_MIN_MASK 0xFF +#define PMIC_AUXADC_THR_DEBT_MIN_SHIFT 8 +#define PMIC_AUXADC_THR_DET_PRD_15_0_ADDR MT6353_AUXADC_THR1 +#define PMIC_AUXADC_THR_DET_PRD_15_0_MASK 0xFFFF +#define PMIC_AUXADC_THR_DET_PRD_15_0_SHIFT 0 +#define PMIC_AUXADC_THR_DET_PRD_19_16_ADDR MT6353_AUXADC_THR2 +#define PMIC_AUXADC_THR_DET_PRD_19_16_MASK 0xF +#define PMIC_AUXADC_THR_DET_PRD_19_16_SHIFT 0 +#define PMIC_AUXADC_THR_VOLT_MAX_ADDR MT6353_AUXADC_THR3 +#define PMIC_AUXADC_THR_VOLT_MAX_MASK 0xFFF +#define PMIC_AUXADC_THR_VOLT_MAX_SHIFT 0 +#define PMIC_AUXADC_THR_IRQ_EN_MAX_ADDR MT6353_AUXADC_THR3 +#define PMIC_AUXADC_THR_IRQ_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_THR_IRQ_EN_MAX_SHIFT 12 +#define PMIC_AUXADC_THR_EN_MAX_ADDR MT6353_AUXADC_THR3 +#define PMIC_AUXADC_THR_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_THR_EN_MAX_SHIFT 13 +#define PMIC_AUXADC_THR_MAX_IRQ_B_ADDR MT6353_AUXADC_THR3 +#define PMIC_AUXADC_THR_MAX_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_THR_MAX_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_THR_VOLT_MIN_ADDR MT6353_AUXADC_THR4 +#define PMIC_AUXADC_THR_VOLT_MIN_MASK 0xFFF +#define PMIC_AUXADC_THR_VOLT_MIN_SHIFT 0 +#define PMIC_AUXADC_THR_IRQ_EN_MIN_ADDR MT6353_AUXADC_THR4 +#define PMIC_AUXADC_THR_IRQ_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_THR_IRQ_EN_MIN_SHIFT 12 +#define PMIC_AUXADC_THR_EN_MIN_ADDR MT6353_AUXADC_THR4 +#define PMIC_AUXADC_THR_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_THR_EN_MIN_SHIFT 13 +#define PMIC_AUXADC_THR_MIN_IRQ_B_ADDR MT6353_AUXADC_THR4 +#define PMIC_AUXADC_THR_MIN_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_THR_MIN_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_ADDR MT6353_AUXADC_THR5 +#define PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_ADDR MT6353_AUXADC_THR6 +#define PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define PMIC_EFUSE_GAIN_CH4_TRIM_ADDR MT6353_AUXADC_EFUSE0 +#define PMIC_EFUSE_GAIN_CH4_TRIM_MASK 0xFFF +#define PMIC_EFUSE_GAIN_CH4_TRIM_SHIFT 0 +#define PMIC_EFUSE_OFFSET_CH4_TRIM_ADDR MT6353_AUXADC_EFUSE1 +#define PMIC_EFUSE_OFFSET_CH4_TRIM_MASK 0x7FF +#define PMIC_EFUSE_OFFSET_CH4_TRIM_SHIFT 0 +#define PMIC_EFUSE_GAIN_CH0_TRIM_ADDR MT6353_AUXADC_EFUSE2 +#define PMIC_EFUSE_GAIN_CH0_TRIM_MASK 0xFFF +#define PMIC_EFUSE_GAIN_CH0_TRIM_SHIFT 0 +#define PMIC_EFUSE_OFFSET_CH0_TRIM_ADDR MT6353_AUXADC_EFUSE3 +#define PMIC_EFUSE_OFFSET_CH0_TRIM_MASK 0x7FF +#define PMIC_EFUSE_OFFSET_CH0_TRIM_SHIFT 0 +#define PMIC_EFUSE_GAIN_CH7_TRIM_ADDR MT6353_AUXADC_EFUSE4 +#define PMIC_EFUSE_GAIN_CH7_TRIM_MASK 0xFFF +#define PMIC_EFUSE_GAIN_CH7_TRIM_SHIFT 0 +#define PMIC_EFUSE_OFFSET_CH7_TRIM_ADDR MT6353_AUXADC_EFUSE5 +#define PMIC_EFUSE_OFFSET_CH7_TRIM_MASK 0x7FF +#define PMIC_EFUSE_OFFSET_CH7_TRIM_SHIFT 0 +#define PMIC_AUXADC_FGADC_START_SW_ADDR MT6353_AUXADC_DBG0 +#define PMIC_AUXADC_FGADC_START_SW_MASK 0x1 +#define PMIC_AUXADC_FGADC_START_SW_SHIFT 0 +#define PMIC_AUXADC_FGADC_START_SEL_ADDR MT6353_AUXADC_DBG0 +#define PMIC_AUXADC_FGADC_START_SEL_MASK 0x1 +#define PMIC_AUXADC_FGADC_START_SEL_SHIFT 1 +#define PMIC_AUXADC_FGADC_R_SW_ADDR MT6353_AUXADC_DBG0 +#define PMIC_AUXADC_FGADC_R_SW_MASK 0x1 +#define PMIC_AUXADC_FGADC_R_SW_SHIFT 2 +#define PMIC_AUXADC_FGADC_R_SEL_ADDR MT6353_AUXADC_DBG0 +#define PMIC_AUXADC_FGADC_R_SEL_MASK 0x1 +#define PMIC_AUXADC_FGADC_R_SEL_SHIFT 3 +#define PMIC_AUXADC_DBG_DIG0_RSV2_ADDR MT6353_AUXADC_DBG0 +#define PMIC_AUXADC_DBG_DIG0_RSV2_MASK 0x3F +#define PMIC_AUXADC_DBG_DIG0_RSV2_SHIFT 4 +#define PMIC_AUXADC_DBG_DIG1_RSV2_ADDR MT6353_AUXADC_DBG0 +#define PMIC_AUXADC_DBG_DIG1_RSV2_MASK 0x3F +#define PMIC_AUXADC_DBG_DIG1_RSV2_SHIFT 10 +#define PMIC_AUXADC_IMPEDANCE_CNT_ADDR MT6353_AUXADC_IMP0 +#define PMIC_AUXADC_IMPEDANCE_CNT_MASK 0x3F +#define PMIC_AUXADC_IMPEDANCE_CNT_SHIFT 0 +#define PMIC_AUXADC_IMPEDANCE_CHSEL_ADDR MT6353_AUXADC_IMP0 +#define PMIC_AUXADC_IMPEDANCE_CHSEL_MASK 0x1 +#define PMIC_AUXADC_IMPEDANCE_CHSEL_SHIFT 6 +#define PMIC_AUXADC_IMPEDANCE_IRQ_CLR_ADDR MT6353_AUXADC_IMP0 +#define PMIC_AUXADC_IMPEDANCE_IRQ_CLR_MASK 0x1 +#define PMIC_AUXADC_IMPEDANCE_IRQ_CLR_SHIFT 7 +#define PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_ADDR MT6353_AUXADC_IMP0 +#define PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_MASK 0x1 +#define PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_SHIFT 8 +#define PMIC_AUXADC_CLR_IMP_CNT_STOP_ADDR MT6353_AUXADC_IMP0 +#define PMIC_AUXADC_CLR_IMP_CNT_STOP_MASK 0x1 +#define PMIC_AUXADC_CLR_IMP_CNT_STOP_SHIFT 14 +#define PMIC_AUXADC_IMPEDANCE_MODE_ADDR MT6353_AUXADC_IMP0 +#define PMIC_AUXADC_IMPEDANCE_MODE_MASK 0x1 +#define PMIC_AUXADC_IMPEDANCE_MODE_SHIFT 15 +#define PMIC_AUXADC_IMP_AUTORPT_PRD_ADDR MT6353_AUXADC_IMP1 +#define PMIC_AUXADC_IMP_AUTORPT_PRD_MASK 0x3FF +#define PMIC_AUXADC_IMP_AUTORPT_PRD_SHIFT 0 +#define PMIC_AUXADC_IMP_AUTORPT_EN_ADDR MT6353_AUXADC_IMP1 +#define PMIC_AUXADC_IMP_AUTORPT_EN_MASK 0x1 +#define PMIC_AUXADC_IMP_AUTORPT_EN_SHIFT 15 +#define PMIC_AUXADC_VISMPS0_DEBT_MAX_ADDR MT6353_AUXADC_VISMPS0_1 +#define PMIC_AUXADC_VISMPS0_DEBT_MAX_MASK 0xFF +#define PMIC_AUXADC_VISMPS0_DEBT_MAX_SHIFT 0 +#define PMIC_AUXADC_VISMPS0_DEBT_MIN_ADDR MT6353_AUXADC_VISMPS0_1 +#define PMIC_AUXADC_VISMPS0_DEBT_MIN_MASK 0xFF +#define PMIC_AUXADC_VISMPS0_DEBT_MIN_SHIFT 8 +#define PMIC_AUXADC_VISMPS0_DET_PRD_15_0_ADDR MT6353_AUXADC_VISMPS0_2 +#define PMIC_AUXADC_VISMPS0_DET_PRD_15_0_MASK 0xFFFF +#define PMIC_AUXADC_VISMPS0_DET_PRD_15_0_SHIFT 0 +#define PMIC_AUXADC_VISMPS0_DET_PRD_19_16_ADDR MT6353_AUXADC_VISMPS0_3 +#define PMIC_AUXADC_VISMPS0_DET_PRD_19_16_MASK 0xF +#define PMIC_AUXADC_VISMPS0_DET_PRD_19_16_SHIFT 0 +#define PMIC_AUXADC_VISMPS0_VOLT_MAX_ADDR MT6353_AUXADC_VISMPS0_4 +#define PMIC_AUXADC_VISMPS0_VOLT_MAX_MASK 0xFFF +#define PMIC_AUXADC_VISMPS0_VOLT_MAX_SHIFT 0 +#define PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_ADDR MT6353_AUXADC_VISMPS0_4 +#define PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_SHIFT 12 +#define PMIC_AUXADC_VISMPS0_EN_MAX_ADDR MT6353_AUXADC_VISMPS0_4 +#define PMIC_AUXADC_VISMPS0_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_VISMPS0_EN_MAX_SHIFT 13 +#define PMIC_AUXADC_VISMPS0_MAX_IRQ_B_ADDR MT6353_AUXADC_VISMPS0_4 +#define PMIC_AUXADC_VISMPS0_MAX_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_VISMPS0_MAX_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_VISMPS0_VOLT_MIN_ADDR MT6353_AUXADC_VISMPS0_5 +#define PMIC_AUXADC_VISMPS0_VOLT_MIN_MASK 0xFFF +#define PMIC_AUXADC_VISMPS0_VOLT_MIN_SHIFT 0 +#define PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_ADDR MT6353_AUXADC_VISMPS0_5 +#define PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_SHIFT 12 +#define PMIC_AUXADC_VISMPS0_EN_MIN_ADDR MT6353_AUXADC_VISMPS0_5 +#define PMIC_AUXADC_VISMPS0_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_VISMPS0_EN_MIN_SHIFT 13 +#define PMIC_AUXADC_VISMPS0_MIN_IRQ_B_ADDR MT6353_AUXADC_VISMPS0_5 +#define PMIC_AUXADC_VISMPS0_MIN_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_VISMPS0_MIN_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_ADDR MT6353_AUXADC_VISMPS0_6 +#define PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_ADDR MT6353_AUXADC_VISMPS0_7 +#define PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define PMIC_AUXADC_LBAT2_DEBT_MAX_ADDR MT6353_AUXADC_LBAT2_1 +#define PMIC_AUXADC_LBAT2_DEBT_MAX_MASK 0xFF +#define PMIC_AUXADC_LBAT2_DEBT_MAX_SHIFT 0 +#define PMIC_AUXADC_LBAT2_DEBT_MIN_ADDR MT6353_AUXADC_LBAT2_1 +#define PMIC_AUXADC_LBAT2_DEBT_MIN_MASK 0xFF +#define PMIC_AUXADC_LBAT2_DEBT_MIN_SHIFT 8 +#define PMIC_AUXADC_LBAT2_DET_PRD_15_0_ADDR MT6353_AUXADC_LBAT2_2 +#define PMIC_AUXADC_LBAT2_DET_PRD_15_0_MASK 0xFFFF +#define PMIC_AUXADC_LBAT2_DET_PRD_15_0_SHIFT 0 +#define PMIC_AUXADC_LBAT2_DET_PRD_19_16_ADDR MT6353_AUXADC_LBAT2_3 +#define PMIC_AUXADC_LBAT2_DET_PRD_19_16_MASK 0xF +#define PMIC_AUXADC_LBAT2_DET_PRD_19_16_SHIFT 0 +#define PMIC_AUXADC_LBAT2_VOLT_MAX_ADDR MT6353_AUXADC_LBAT2_4 +#define PMIC_AUXADC_LBAT2_VOLT_MAX_MASK 0xFFF +#define PMIC_AUXADC_LBAT2_VOLT_MAX_SHIFT 0 +#define PMIC_AUXADC_LBAT2_IRQ_EN_MAX_ADDR MT6353_AUXADC_LBAT2_4 +#define PMIC_AUXADC_LBAT2_IRQ_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_LBAT2_IRQ_EN_MAX_SHIFT 12 +#define PMIC_AUXADC_LBAT2_EN_MAX_ADDR MT6353_AUXADC_LBAT2_4 +#define PMIC_AUXADC_LBAT2_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_LBAT2_EN_MAX_SHIFT 13 +#define PMIC_AUXADC_LBAT2_MAX_IRQ_B_ADDR MT6353_AUXADC_LBAT2_4 +#define PMIC_AUXADC_LBAT2_MAX_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_LBAT2_MAX_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_LBAT2_VOLT_MIN_ADDR MT6353_AUXADC_LBAT2_5 +#define PMIC_AUXADC_LBAT2_VOLT_MIN_MASK 0xFFF +#define PMIC_AUXADC_LBAT2_VOLT_MIN_SHIFT 0 +#define PMIC_AUXADC_LBAT2_IRQ_EN_MIN_ADDR MT6353_AUXADC_LBAT2_5 +#define PMIC_AUXADC_LBAT2_IRQ_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_LBAT2_IRQ_EN_MIN_SHIFT 12 +#define PMIC_AUXADC_LBAT2_EN_MIN_ADDR MT6353_AUXADC_LBAT2_5 +#define PMIC_AUXADC_LBAT2_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_LBAT2_EN_MIN_SHIFT 13 +#define PMIC_AUXADC_LBAT2_MIN_IRQ_B_ADDR MT6353_AUXADC_LBAT2_5 +#define PMIC_AUXADC_LBAT2_MIN_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_LBAT2_MIN_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_ADDR MT6353_AUXADC_LBAT2_6 +#define PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_ADDR MT6353_AUXADC_LBAT2_7 +#define PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define PMIC_AUXADC_MDBG_DET_PRD_ADDR MT6353_AUXADC_MDBG_0 +#define PMIC_AUXADC_MDBG_DET_PRD_MASK 0x3FF +#define PMIC_AUXADC_MDBG_DET_PRD_SHIFT 0 +#define PMIC_AUXADC_MDBG_DET_EN_ADDR MT6353_AUXADC_MDBG_0 +#define PMIC_AUXADC_MDBG_DET_EN_MASK 0x1 +#define PMIC_AUXADC_MDBG_DET_EN_SHIFT 15 +#define PMIC_AUXADC_MDBG_R_PTR_ADDR MT6353_AUXADC_MDBG_1 +#define PMIC_AUXADC_MDBG_R_PTR_MASK 0x3F +#define PMIC_AUXADC_MDBG_R_PTR_SHIFT 0 +#define PMIC_AUXADC_MDBG_W_PTR_ADDR MT6353_AUXADC_MDBG_1 +#define PMIC_AUXADC_MDBG_W_PTR_MASK 0x3F +#define PMIC_AUXADC_MDBG_W_PTR_SHIFT 8 +#define PMIC_AUXADC_MDBG_BUF_LENGTH_ADDR MT6353_AUXADC_MDBG_2 +#define PMIC_AUXADC_MDBG_BUF_LENGTH_MASK 0x3F +#define PMIC_AUXADC_MDBG_BUF_LENGTH_SHIFT 0 +#define PMIC_AUXADC_MDRT_DET_PRD_ADDR MT6353_AUXADC_MDRT_0 +#define PMIC_AUXADC_MDRT_DET_PRD_MASK 0x3FF +#define PMIC_AUXADC_MDRT_DET_PRD_SHIFT 0 +#define PMIC_AUXADC_MDRT_DET_EN_ADDR MT6353_AUXADC_MDRT_0 +#define PMIC_AUXADC_MDRT_DET_EN_MASK 0x1 +#define PMIC_AUXADC_MDRT_DET_EN_SHIFT 15 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_ADDR MT6353_AUXADC_MDRT_1 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_MASK 0xFFF +#define PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_SHIFT 0 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_ADDR MT6353_AUXADC_MDRT_1 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_MASK 0x1 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_SHIFT 15 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_ADDR MT6353_AUXADC_MDRT_2 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_MASK 0x1 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_SHIFT 0 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_ADDR MT6353_AUXADC_MDRT_2 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_MASK 0x1 +#define PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_SHIFT 1 +#define PMIC_AUXADC_MDRT_DET_WKUP_EN_ADDR MT6353_AUXADC_MDRT_2 +#define PMIC_AUXADC_MDRT_DET_WKUP_EN_MASK 0x1 +#define PMIC_AUXADC_MDRT_DET_WKUP_EN_SHIFT 2 +#define PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_ADDR MT6353_AUXADC_MDRT_2 +#define PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_MASK 0x1 +#define PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_SHIFT 3 +#define PMIC_AUXADC_DCXO_MDRT_DET_PRD_ADDR MT6353_AUXADC_DCXO_MDRT_0 +#define PMIC_AUXADC_DCXO_MDRT_DET_PRD_MASK 0x3FF +#define PMIC_AUXADC_DCXO_MDRT_DET_PRD_SHIFT 0 +#define PMIC_AUXADC_DCXO_MDRT_DET_EN_ADDR MT6353_AUXADC_DCXO_MDRT_0 +#define PMIC_AUXADC_DCXO_MDRT_DET_EN_MASK 0x1 +#define PMIC_AUXADC_DCXO_MDRT_DET_EN_SHIFT 15 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_ADDR MT6353_AUXADC_DCXO_MDRT_1 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_MASK 0xFFF +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_SHIFT 0 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_ADDR MT6353_AUXADC_DCXO_MDRT_1 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_MASK 0x1 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_SHIFT 15 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_ADDR MT6353_AUXADC_DCXO_MDRT_2 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_MASK 0x1 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_SHIFT 0 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_ADDR MT6353_AUXADC_DCXO_MDRT_2 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_MASK 0x1 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_SHIFT 1 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_ADDR MT6353_AUXADC_DCXO_MDRT_2 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_MASK 0x1 +#define PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SHIFT 2 +#define PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_ADDR MT6353_AUXADC_DCXO_MDRT_2 +#define PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_MASK 0x1 +#define PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_SHIFT 3 +#define PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_ADDR MT6353_AUXADC_DCXO_MDRT_2 +#define PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_MASK 0x1 +#define PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_SHIFT 4 +#define PMIC_AUXADC_NAG_EN_ADDR MT6353_AUXADC_NAG_0 +#define PMIC_AUXADC_NAG_EN_MASK 0x1 +#define PMIC_AUXADC_NAG_EN_SHIFT 0 +#define PMIC_AUXADC_NAG_CLR_ADDR MT6353_AUXADC_NAG_0 +#define PMIC_AUXADC_NAG_CLR_MASK 0x1 +#define PMIC_AUXADC_NAG_CLR_SHIFT 1 +#define PMIC_AUXADC_NAG_VBAT1_SEL_ADDR MT6353_AUXADC_NAG_0 +#define PMIC_AUXADC_NAG_VBAT1_SEL_MASK 0x1 +#define PMIC_AUXADC_NAG_VBAT1_SEL_SHIFT 2 +#define PMIC_AUXADC_NAG_PRD_ADDR MT6353_AUXADC_NAG_0 +#define PMIC_AUXADC_NAG_PRD_MASK 0x7F +#define PMIC_AUXADC_NAG_PRD_SHIFT 3 +#define PMIC_AUXADC_NAG_IRQ_EN_ADDR MT6353_AUXADC_NAG_0 +#define PMIC_AUXADC_NAG_IRQ_EN_MASK 0x1 +#define PMIC_AUXADC_NAG_IRQ_EN_SHIFT 10 +#define PMIC_AUXADC_NAG_C_DLTV_IRQ_ADDR MT6353_AUXADC_NAG_0 +#define PMIC_AUXADC_NAG_C_DLTV_IRQ_MASK 0x1 +#define PMIC_AUXADC_NAG_C_DLTV_IRQ_SHIFT 15 +#define PMIC_AUXADC_NAG_ZCV_ADDR MT6353_AUXADC_NAG_1 +#define PMIC_AUXADC_NAG_ZCV_MASK 0x7FFF +#define PMIC_AUXADC_NAG_ZCV_SHIFT 0 +#define PMIC_AUXADC_NAG_C_DLTV_TH_15_0_ADDR MT6353_AUXADC_NAG_2 +#define PMIC_AUXADC_NAG_C_DLTV_TH_15_0_MASK 0xFFFF +#define PMIC_AUXADC_NAG_C_DLTV_TH_15_0_SHIFT 0 +#define PMIC_AUXADC_NAG_C_DLTV_TH_26_16_ADDR MT6353_AUXADC_NAG_3 +#define PMIC_AUXADC_NAG_C_DLTV_TH_26_16_MASK 0x7FF +#define PMIC_AUXADC_NAG_C_DLTV_TH_26_16_SHIFT 0 +#define PMIC_AUXADC_NAG_CNT_15_0_ADDR MT6353_AUXADC_NAG_4 +#define PMIC_AUXADC_NAG_CNT_15_0_MASK 0xFFFF +#define PMIC_AUXADC_NAG_CNT_15_0_SHIFT 0 +#define PMIC_AUXADC_NAG_CNT_25_16_ADDR MT6353_AUXADC_NAG_5 +#define PMIC_AUXADC_NAG_CNT_25_16_MASK 0x3FF +#define PMIC_AUXADC_NAG_CNT_25_16_SHIFT 0 +#define PMIC_AUXADC_NAG_DLTV_ADDR MT6353_AUXADC_NAG_6 +#define PMIC_AUXADC_NAG_DLTV_MASK 0xFFFF +#define PMIC_AUXADC_NAG_DLTV_SHIFT 0 +#define PMIC_AUXADC_NAG_C_DLTV_15_0_ADDR MT6353_AUXADC_NAG_7 +#define PMIC_AUXADC_NAG_C_DLTV_15_0_MASK 0xFFFF +#define PMIC_AUXADC_NAG_C_DLTV_15_0_SHIFT 0 +#define PMIC_AUXADC_NAG_C_DLTV_26_16_ADDR MT6353_AUXADC_NAG_8 +#define PMIC_AUXADC_NAG_C_DLTV_26_16_MASK 0x7FF +#define PMIC_AUXADC_NAG_C_DLTV_26_16_SHIFT 0 +#define PMIC_AUXADC_TYPEC_H_DEBT_MAX_ADDR MT6353_AUXADC_TYPEC_H_1 +#define PMIC_AUXADC_TYPEC_H_DEBT_MAX_MASK 0xFF +#define PMIC_AUXADC_TYPEC_H_DEBT_MAX_SHIFT 0 +#define PMIC_AUXADC_TYPEC_H_DEBT_MIN_ADDR MT6353_AUXADC_TYPEC_H_1 +#define PMIC_AUXADC_TYPEC_H_DEBT_MIN_MASK 0xFF +#define PMIC_AUXADC_TYPEC_H_DEBT_MIN_SHIFT 8 +#define PMIC_AUXADC_TYPEC_H_DET_PRD_15_0_ADDR MT6353_AUXADC_TYPEC_H_2 +#define PMIC_AUXADC_TYPEC_H_DET_PRD_15_0_MASK 0xFFFF +#define PMIC_AUXADC_TYPEC_H_DET_PRD_15_0_SHIFT 0 +#define PMIC_AUXADC_TYPEC_H_DET_PRD_19_16_ADDR MT6353_AUXADC_TYPEC_H_3 +#define PMIC_AUXADC_TYPEC_H_DET_PRD_19_16_MASK 0xF +#define PMIC_AUXADC_TYPEC_H_DET_PRD_19_16_SHIFT 0 +#define PMIC_AUXADC_TYPEC_H_VOLT_MAX_ADDR MT6353_AUXADC_TYPEC_H_4 +#define PMIC_AUXADC_TYPEC_H_VOLT_MAX_MASK 0xFFF +#define PMIC_AUXADC_TYPEC_H_VOLT_MAX_SHIFT 0 +#define PMIC_AUXADC_TYPEC_H_IRQ_EN_MAX_ADDR MT6353_AUXADC_TYPEC_H_4 +#define PMIC_AUXADC_TYPEC_H_IRQ_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_TYPEC_H_IRQ_EN_MAX_SHIFT 12 +#define PMIC_AUXADC_TYPEC_H_EN_MAX_ADDR MT6353_AUXADC_TYPEC_H_4 +#define PMIC_AUXADC_TYPEC_H_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_TYPEC_H_EN_MAX_SHIFT 13 +#define PMIC_AUXADC_TYPEC_H_MAX_IRQ_B_ADDR MT6353_AUXADC_TYPEC_H_4 +#define PMIC_AUXADC_TYPEC_H_MAX_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_TYPEC_H_MAX_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_TYPEC_H_VOLT_MIN_ADDR MT6353_AUXADC_TYPEC_H_5 +#define PMIC_AUXADC_TYPEC_H_VOLT_MIN_MASK 0xFFF +#define PMIC_AUXADC_TYPEC_H_VOLT_MIN_SHIFT 0 +#define PMIC_AUXADC_TYPEC_H_IRQ_EN_MIN_ADDR MT6353_AUXADC_TYPEC_H_5 +#define PMIC_AUXADC_TYPEC_H_IRQ_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_TYPEC_H_IRQ_EN_MIN_SHIFT 12 +#define PMIC_AUXADC_TYPEC_H_EN_MIN_ADDR MT6353_AUXADC_TYPEC_H_5 +#define PMIC_AUXADC_TYPEC_H_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_TYPEC_H_EN_MIN_SHIFT 13 +#define PMIC_AUXADC_TYPEC_H_MIN_IRQ_B_ADDR MT6353_AUXADC_TYPEC_H_5 +#define PMIC_AUXADC_TYPEC_H_MIN_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_TYPEC_H_MIN_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_TYPEC_H_DEBOUNCE_COUNT_MAX_ADDR MT6353_AUXADC_TYPEC_H_6 +#define PMIC_AUXADC_TYPEC_H_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define PMIC_AUXADC_TYPEC_H_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define PMIC_AUXADC_TYPEC_H_DEBOUNCE_COUNT_MIN_ADDR MT6353_AUXADC_TYPEC_H_7 +#define PMIC_AUXADC_TYPEC_H_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define PMIC_AUXADC_TYPEC_H_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define PMIC_AUXADC_TYPEC_L_DEBT_MAX_ADDR MT6353_AUXADC_TYPEC_L_1 +#define PMIC_AUXADC_TYPEC_L_DEBT_MAX_MASK 0xFF +#define PMIC_AUXADC_TYPEC_L_DEBT_MAX_SHIFT 0 +#define PMIC_AUXADC_TYPEC_L_DEBT_MIN_ADDR MT6353_AUXADC_TYPEC_L_1 +#define PMIC_AUXADC_TYPEC_L_DEBT_MIN_MASK 0xFF +#define PMIC_AUXADC_TYPEC_L_DEBT_MIN_SHIFT 8 +#define PMIC_AUXADC_TYPEC_L_DET_PRD_15_0_ADDR MT6353_AUXADC_TYPEC_L_2 +#define PMIC_AUXADC_TYPEC_L_DET_PRD_15_0_MASK 0xFFFF +#define PMIC_AUXADC_TYPEC_L_DET_PRD_15_0_SHIFT 0 +#define PMIC_AUXADC_TYPEC_L_DET_PRD_19_16_ADDR MT6353_AUXADC_TYPEC_L_3 +#define PMIC_AUXADC_TYPEC_L_DET_PRD_19_16_MASK 0xF +#define PMIC_AUXADC_TYPEC_L_DET_PRD_19_16_SHIFT 0 +#define PMIC_AUXADC_TYPEC_L_VOLT_MAX_ADDR MT6353_AUXADC_TYPEC_L_4 +#define PMIC_AUXADC_TYPEC_L_VOLT_MAX_MASK 0xFFF +#define PMIC_AUXADC_TYPEC_L_VOLT_MAX_SHIFT 0 +#define PMIC_AUXADC_TYPEC_L_IRQ_EN_MAX_ADDR MT6353_AUXADC_TYPEC_L_4 +#define PMIC_AUXADC_TYPEC_L_IRQ_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_TYPEC_L_IRQ_EN_MAX_SHIFT 12 +#define PMIC_AUXADC_TYPEC_L_EN_MAX_ADDR MT6353_AUXADC_TYPEC_L_4 +#define PMIC_AUXADC_TYPEC_L_EN_MAX_MASK 0x1 +#define PMIC_AUXADC_TYPEC_L_EN_MAX_SHIFT 13 +#define PMIC_AUXADC_TYPEC_L_MAX_IRQ_B_ADDR MT6353_AUXADC_TYPEC_L_4 +#define PMIC_AUXADC_TYPEC_L_MAX_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_TYPEC_L_MAX_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_TYPEC_L_VOLT_MIN_ADDR MT6353_AUXADC_TYPEC_L_5 +#define PMIC_AUXADC_TYPEC_L_VOLT_MIN_MASK 0xFFF +#define PMIC_AUXADC_TYPEC_L_VOLT_MIN_SHIFT 0 +#define PMIC_AUXADC_TYPEC_L_IRQ_EN_MIN_ADDR MT6353_AUXADC_TYPEC_L_5 +#define PMIC_AUXADC_TYPEC_L_IRQ_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_TYPEC_L_IRQ_EN_MIN_SHIFT 12 +#define PMIC_AUXADC_TYPEC_L_EN_MIN_ADDR MT6353_AUXADC_TYPEC_L_5 +#define PMIC_AUXADC_TYPEC_L_EN_MIN_MASK 0x1 +#define PMIC_AUXADC_TYPEC_L_EN_MIN_SHIFT 13 +#define PMIC_AUXADC_TYPEC_L_MIN_IRQ_B_ADDR MT6353_AUXADC_TYPEC_L_5 +#define PMIC_AUXADC_TYPEC_L_MIN_IRQ_B_MASK 0x1 +#define PMIC_AUXADC_TYPEC_L_MIN_IRQ_B_SHIFT 15 +#define PMIC_AUXADC_TYPEC_L_DEBOUNCE_COUNT_MAX_ADDR MT6353_AUXADC_TYPEC_L_6 +#define PMIC_AUXADC_TYPEC_L_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define PMIC_AUXADC_TYPEC_L_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define PMIC_AUXADC_TYPEC_L_DEBOUNCE_COUNT_MIN_ADDR MT6353_AUXADC_TYPEC_L_7 +#define PMIC_AUXADC_TYPEC_L_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define PMIC_AUXADC_TYPEC_L_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define PMIC_RG_AUDACCDETVTHBCAL_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETVTHBCAL_MASK 0x1 +#define PMIC_RG_AUDACCDETVTHBCAL_SHIFT 0 +#define PMIC_RG_AUDACCDETVTHACAL_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETVTHACAL_MASK 0x1 +#define PMIC_RG_AUDACCDETVTHACAL_SHIFT 1 +#define PMIC_RG_AUDACCDETANASWCTRLENB_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETANASWCTRLENB_MASK 0x1 +#define PMIC_RG_AUDACCDETANASWCTRLENB_SHIFT 2 +#define PMIC_RG_ACCDETSEL_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_ACCDETSEL_MASK 0x1 +#define PMIC_RG_ACCDETSEL_SHIFT 3 +#define PMIC_RG_AUDACCDETSWCTRL_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETSWCTRL_MASK 0x7 +#define PMIC_RG_AUDACCDETSWCTRL_SHIFT 4 +#define PMIC_RG_AUDACCDETMICBIAS1PULLLOW_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETMICBIAS1PULLLOW_MASK 0x1 +#define PMIC_RG_AUDACCDETMICBIAS1PULLLOW_SHIFT 7 +#define PMIC_RG_AUDACCDETTVDET_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETTVDET_MASK 0x1 +#define PMIC_RG_AUDACCDETTVDET_SHIFT 8 +#define PMIC_RG_AUDACCDETVIN1PULLLOW_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETVIN1PULLLOW_MASK 0x1 +#define PMIC_RG_AUDACCDETVIN1PULLLOW_SHIFT 9 +#define PMIC_AUDACCDETAUXADCSWCTRL_ADDR MT6353_ACCDET_CON0 +#define PMIC_AUDACCDETAUXADCSWCTRL_MASK 0x1 +#define PMIC_AUDACCDETAUXADCSWCTRL_SHIFT 10 +#define PMIC_AUDACCDETAUXADCSWCTRL_SEL_ADDR MT6353_ACCDET_CON0 +#define PMIC_AUDACCDETAUXADCSWCTRL_SEL_MASK 0x1 +#define PMIC_AUDACCDETAUXADCSWCTRL_SEL_SHIFT 11 +#define PMIC_RG_AUDACCDETMICBIAS0PULLLOW_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETMICBIAS0PULLLOW_MASK 0x1 +#define PMIC_RG_AUDACCDETMICBIAS0PULLLOW_SHIFT 12 +#define PMIC_RG_AUDACCDETRSV_ADDR MT6353_ACCDET_CON0 +#define PMIC_RG_AUDACCDETRSV_MASK 0x3 +#define PMIC_RG_AUDACCDETRSV_SHIFT 13 +#define PMIC_ACCDET_EN_ADDR MT6353_ACCDET_CON1 +#define PMIC_ACCDET_EN_MASK 0x1 +#define PMIC_ACCDET_EN_SHIFT 0 +#define PMIC_ACCDET_SEQ_INIT_ADDR MT6353_ACCDET_CON1 +#define PMIC_ACCDET_SEQ_INIT_MASK 0x1 +#define PMIC_ACCDET_SEQ_INIT_SHIFT 1 +#define PMIC_ACCDET_EINTDET_EN_ADDR MT6353_ACCDET_CON1 +#define PMIC_ACCDET_EINTDET_EN_MASK 0x1 +#define PMIC_ACCDET_EINTDET_EN_SHIFT 2 +#define PMIC_ACCDET_EINT_SEQ_INIT_ADDR MT6353_ACCDET_CON1 +#define PMIC_ACCDET_EINT_SEQ_INIT_MASK 0x1 +#define PMIC_ACCDET_EINT_SEQ_INIT_SHIFT 3 +#define PMIC_ACCDET_NEGVDET_EN_ADDR MT6353_ACCDET_CON1 +#define PMIC_ACCDET_NEGVDET_EN_MASK 0x1 +#define PMIC_ACCDET_NEGVDET_EN_SHIFT 4 +#define PMIC_ACCDET_NEGVDET_EN_CTRL_ADDR MT6353_ACCDET_CON1 +#define PMIC_ACCDET_NEGVDET_EN_CTRL_MASK 0x1 +#define PMIC_ACCDET_NEGVDET_EN_CTRL_SHIFT 5 +#define PMIC_ACCDET_ANASWCTRL_SEL_ADDR MT6353_ACCDET_CON1 +#define PMIC_ACCDET_ANASWCTRL_SEL_MASK 0x1 +#define PMIC_ACCDET_ANASWCTRL_SEL_SHIFT 6 +#define PMIC_ACCDET_CMP_PWM_EN_ADDR MT6353_ACCDET_CON2 +#define PMIC_ACCDET_CMP_PWM_EN_MASK 0x1 +#define PMIC_ACCDET_CMP_PWM_EN_SHIFT 0 +#define PMIC_ACCDET_VTH_PWM_EN_ADDR MT6353_ACCDET_CON2 +#define PMIC_ACCDET_VTH_PWM_EN_MASK 0x1 +#define PMIC_ACCDET_VTH_PWM_EN_SHIFT 1 +#define PMIC_ACCDET_MBIAS_PWM_EN_ADDR MT6353_ACCDET_CON2 +#define PMIC_ACCDET_MBIAS_PWM_EN_MASK 0x1 +#define PMIC_ACCDET_MBIAS_PWM_EN_SHIFT 2 +#define PMIC_ACCDET_EINT_PWM_EN_ADDR MT6353_ACCDET_CON2 +#define PMIC_ACCDET_EINT_PWM_EN_MASK 0x1 +#define PMIC_ACCDET_EINT_PWM_EN_SHIFT 3 +#define PMIC_ACCDET_CMP_PWM_IDLE_ADDR MT6353_ACCDET_CON2 +#define PMIC_ACCDET_CMP_PWM_IDLE_MASK 0x1 +#define PMIC_ACCDET_CMP_PWM_IDLE_SHIFT 4 +#define PMIC_ACCDET_VTH_PWM_IDLE_ADDR MT6353_ACCDET_CON2 +#define PMIC_ACCDET_VTH_PWM_IDLE_MASK 0x1 +#define PMIC_ACCDET_VTH_PWM_IDLE_SHIFT 5 +#define PMIC_ACCDET_MBIAS_PWM_IDLE_ADDR MT6353_ACCDET_CON2 +#define PMIC_ACCDET_MBIAS_PWM_IDLE_MASK 0x1 +#define PMIC_ACCDET_MBIAS_PWM_IDLE_SHIFT 6 +#define PMIC_ACCDET_EINT_PWM_IDLE_ADDR MT6353_ACCDET_CON2 +#define PMIC_ACCDET_EINT_PWM_IDLE_MASK 0x1 +#define PMIC_ACCDET_EINT_PWM_IDLE_SHIFT 7 +#define PMIC_ACCDET_PWM_WIDTH_ADDR MT6353_ACCDET_CON3 +#define PMIC_ACCDET_PWM_WIDTH_MASK 0xFFFF +#define PMIC_ACCDET_PWM_WIDTH_SHIFT 0 +#define PMIC_ACCDET_PWM_THRESH_ADDR MT6353_ACCDET_CON4 +#define PMIC_ACCDET_PWM_THRESH_MASK 0xFFFF +#define PMIC_ACCDET_PWM_THRESH_SHIFT 0 +#define PMIC_ACCDET_RISE_DELAY_ADDR MT6353_ACCDET_CON5 +#define PMIC_ACCDET_RISE_DELAY_MASK 0x7FFF +#define PMIC_ACCDET_RISE_DELAY_SHIFT 0 +#define PMIC_ACCDET_FALL_DELAY_ADDR MT6353_ACCDET_CON5 +#define PMIC_ACCDET_FALL_DELAY_MASK 0x1 +#define PMIC_ACCDET_FALL_DELAY_SHIFT 15 +#define PMIC_ACCDET_DEBOUNCE0_ADDR MT6353_ACCDET_CON6 +#define PMIC_ACCDET_DEBOUNCE0_MASK 0xFFFF +#define PMIC_ACCDET_DEBOUNCE0_SHIFT 0 +#define PMIC_ACCDET_DEBOUNCE1_ADDR MT6353_ACCDET_CON7 +#define PMIC_ACCDET_DEBOUNCE1_MASK 0xFFFF +#define PMIC_ACCDET_DEBOUNCE1_SHIFT 0 +#define PMIC_ACCDET_DEBOUNCE2_ADDR MT6353_ACCDET_CON8 +#define PMIC_ACCDET_DEBOUNCE2_MASK 0xFFFF +#define PMIC_ACCDET_DEBOUNCE2_SHIFT 0 +#define PMIC_ACCDET_DEBOUNCE3_ADDR MT6353_ACCDET_CON9 +#define PMIC_ACCDET_DEBOUNCE3_MASK 0xFFFF +#define PMIC_ACCDET_DEBOUNCE3_SHIFT 0 +#define PMIC_ACCDET_DEBOUNCE4_ADDR MT6353_ACCDET_CON10 +#define PMIC_ACCDET_DEBOUNCE4_MASK 0xFFFF +#define PMIC_ACCDET_DEBOUNCE4_SHIFT 0 +#define PMIC_ACCDET_IVAL_CUR_IN_ADDR MT6353_ACCDET_CON11 +#define PMIC_ACCDET_IVAL_CUR_IN_MASK 0x3 +#define PMIC_ACCDET_IVAL_CUR_IN_SHIFT 0 +#define PMIC_ACCDET_EINT_IVAL_CUR_IN_ADDR MT6353_ACCDET_CON11 +#define PMIC_ACCDET_EINT_IVAL_CUR_IN_MASK 0x1 +#define PMIC_ACCDET_EINT_IVAL_CUR_IN_SHIFT 2 +#define PMIC_ACCDET_IVAL_SAM_IN_ADDR MT6353_ACCDET_CON11 +#define PMIC_ACCDET_IVAL_SAM_IN_MASK 0x3 +#define PMIC_ACCDET_IVAL_SAM_IN_SHIFT 4 +#define PMIC_ACCDET_EINT_IVAL_SAM_IN_ADDR MT6353_ACCDET_CON11 +#define PMIC_ACCDET_EINT_IVAL_SAM_IN_MASK 0x1 +#define PMIC_ACCDET_EINT_IVAL_SAM_IN_SHIFT 6 +#define PMIC_ACCDET_IVAL_MEM_IN_ADDR MT6353_ACCDET_CON11 +#define PMIC_ACCDET_IVAL_MEM_IN_MASK 0x3 +#define PMIC_ACCDET_IVAL_MEM_IN_SHIFT 8 +#define PMIC_ACCDET_EINT_IVAL_MEM_IN_ADDR MT6353_ACCDET_CON11 +#define PMIC_ACCDET_EINT_IVAL_MEM_IN_MASK 0x1 +#define PMIC_ACCDET_EINT_IVAL_MEM_IN_SHIFT 10 +#define PMIC_ACCDET_EINT_IVAL_SEL_ADDR MT6353_ACCDET_CON11 +#define PMIC_ACCDET_EINT_IVAL_SEL_MASK 0x1 +#define PMIC_ACCDET_EINT_IVAL_SEL_SHIFT 14 +#define PMIC_ACCDET_IVAL_SEL_ADDR MT6353_ACCDET_CON11 +#define PMIC_ACCDET_IVAL_SEL_MASK 0x1 +#define PMIC_ACCDET_IVAL_SEL_SHIFT 15 +#define PMIC_ACCDET_IRQ_ADDR MT6353_ACCDET_CON12 +#define PMIC_ACCDET_IRQ_MASK 0x1 +#define PMIC_ACCDET_IRQ_SHIFT 0 +#define PMIC_ACCDET_NEGV_IRQ_ADDR MT6353_ACCDET_CON12 +#define PMIC_ACCDET_NEGV_IRQ_MASK 0x1 +#define PMIC_ACCDET_NEGV_IRQ_SHIFT 1 +#define PMIC_ACCDET_EINT_IRQ_ADDR MT6353_ACCDET_CON12 +#define PMIC_ACCDET_EINT_IRQ_MASK 0x1 +#define PMIC_ACCDET_EINT_IRQ_SHIFT 2 +#define PMIC_ACCDET_IRQ_CLR_ADDR MT6353_ACCDET_CON12 +#define PMIC_ACCDET_IRQ_CLR_MASK 0x1 +#define PMIC_ACCDET_IRQ_CLR_SHIFT 8 +#define PMIC_ACCDET_NEGV_IRQ_CLR_ADDR MT6353_ACCDET_CON12 +#define PMIC_ACCDET_NEGV_IRQ_CLR_MASK 0x1 +#define PMIC_ACCDET_NEGV_IRQ_CLR_SHIFT 9 +#define PMIC_ACCDET_EINT_IRQ_CLR_ADDR MT6353_ACCDET_CON12 +#define PMIC_ACCDET_EINT_IRQ_CLR_MASK 0x1 +#define PMIC_ACCDET_EINT_IRQ_CLR_SHIFT 10 +#define PMIC_ACCDET_EINT_IRQ_POLARITY_ADDR MT6353_ACCDET_CON12 +#define PMIC_ACCDET_EINT_IRQ_POLARITY_MASK 0x1 +#define PMIC_ACCDET_EINT_IRQ_POLARITY_SHIFT 15 +#define PMIC_ACCDET_TEST_MODE0_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_TEST_MODE0_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE0_SHIFT 0 +#define PMIC_ACCDET_TEST_MODE1_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_TEST_MODE1_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE1_SHIFT 1 +#define PMIC_ACCDET_TEST_MODE2_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_TEST_MODE2_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE2_SHIFT 2 +#define PMIC_ACCDET_TEST_MODE3_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_TEST_MODE3_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE3_SHIFT 3 +#define PMIC_ACCDET_TEST_MODE4_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_TEST_MODE4_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE4_SHIFT 4 +#define PMIC_ACCDET_TEST_MODE5_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_TEST_MODE5_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE5_SHIFT 5 +#define PMIC_ACCDET_PWM_SEL_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_PWM_SEL_MASK 0x3 +#define PMIC_ACCDET_PWM_SEL_SHIFT 6 +#define PMIC_ACCDET_IN_SW_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_IN_SW_MASK 0x3 +#define PMIC_ACCDET_IN_SW_SHIFT 8 +#define PMIC_ACCDET_CMP_EN_SW_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_CMP_EN_SW_MASK 0x1 +#define PMIC_ACCDET_CMP_EN_SW_SHIFT 12 +#define PMIC_ACCDET_VTH_EN_SW_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_VTH_EN_SW_MASK 0x1 +#define PMIC_ACCDET_VTH_EN_SW_SHIFT 13 +#define PMIC_ACCDET_MBIAS_EN_SW_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_MBIAS_EN_SW_MASK 0x1 +#define PMIC_ACCDET_MBIAS_EN_SW_SHIFT 14 +#define PMIC_ACCDET_PWM_EN_SW_ADDR MT6353_ACCDET_CON13 +#define PMIC_ACCDET_PWM_EN_SW_MASK 0x1 +#define PMIC_ACCDET_PWM_EN_SW_SHIFT 15 +#define PMIC_ACCDET_IN_ADDR MT6353_ACCDET_CON14 +#define PMIC_ACCDET_IN_MASK 0x3 +#define PMIC_ACCDET_IN_SHIFT 0 +#define PMIC_ACCDET_CUR_IN_ADDR MT6353_ACCDET_CON14 +#define PMIC_ACCDET_CUR_IN_MASK 0x3 +#define PMIC_ACCDET_CUR_IN_SHIFT 2 +#define PMIC_ACCDET_SAM_IN_ADDR MT6353_ACCDET_CON14 +#define PMIC_ACCDET_SAM_IN_MASK 0x3 +#define PMIC_ACCDET_SAM_IN_SHIFT 4 +#define PMIC_ACCDET_MEM_IN_ADDR MT6353_ACCDET_CON14 +#define PMIC_ACCDET_MEM_IN_MASK 0x3 +#define PMIC_ACCDET_MEM_IN_SHIFT 6 +#define PMIC_ACCDET_STATE_ADDR MT6353_ACCDET_CON14 +#define PMIC_ACCDET_STATE_MASK 0x7 +#define PMIC_ACCDET_STATE_SHIFT 8 +#define PMIC_ACCDET_MBIAS_CLK_ADDR MT6353_ACCDET_CON14 +#define PMIC_ACCDET_MBIAS_CLK_MASK 0x1 +#define PMIC_ACCDET_MBIAS_CLK_SHIFT 12 +#define PMIC_ACCDET_VTH_CLK_ADDR MT6353_ACCDET_CON14 +#define PMIC_ACCDET_VTH_CLK_MASK 0x1 +#define PMIC_ACCDET_VTH_CLK_SHIFT 13 +#define PMIC_ACCDET_CMP_CLK_ADDR MT6353_ACCDET_CON14 +#define PMIC_ACCDET_CMP_CLK_MASK 0x1 +#define PMIC_ACCDET_CMP_CLK_SHIFT 14 +#define PMIC_DA_AUDACCDETAUXADCSWCTRL_ADDR MT6353_ACCDET_CON14 +#define PMIC_DA_AUDACCDETAUXADCSWCTRL_MASK 0x1 +#define PMIC_DA_AUDACCDETAUXADCSWCTRL_SHIFT 15 +#define PMIC_ACCDET_EINT_DEB_SEL_ADDR MT6353_ACCDET_CON15 +#define PMIC_ACCDET_EINT_DEB_SEL_MASK 0x1 +#define PMIC_ACCDET_EINT_DEB_SEL_SHIFT 0 +#define PMIC_ACCDET_EINT_DEBOUNCE_ADDR MT6353_ACCDET_CON15 +#define PMIC_ACCDET_EINT_DEBOUNCE_MASK 0x7 +#define PMIC_ACCDET_EINT_DEBOUNCE_SHIFT 4 +#define PMIC_ACCDET_EINT_PWM_THRESH_ADDR MT6353_ACCDET_CON15 +#define PMIC_ACCDET_EINT_PWM_THRESH_MASK 0x7 +#define PMIC_ACCDET_EINT_PWM_THRESH_SHIFT 8 +#define PMIC_ACCDET_EINT_PWM_WIDTH_ADDR MT6353_ACCDET_CON15 +#define PMIC_ACCDET_EINT_PWM_WIDTH_MASK 0x3 +#define PMIC_ACCDET_EINT_PWM_WIDTH_SHIFT 12 +#define PMIC_ACCDET_NEGV_THRESH_ADDR MT6353_ACCDET_CON16 +#define PMIC_ACCDET_NEGV_THRESH_MASK 0x1F +#define PMIC_ACCDET_NEGV_THRESH_SHIFT 0 +#define PMIC_ACCDET_EINT_PWM_FALL_DELAY_ADDR MT6353_ACCDET_CON16 +#define PMIC_ACCDET_EINT_PWM_FALL_DELAY_MASK 0x1 +#define PMIC_ACCDET_EINT_PWM_FALL_DELAY_SHIFT 5 +#define PMIC_ACCDET_EINT_PWM_RISE_DELAY_ADDR MT6353_ACCDET_CON16 +#define PMIC_ACCDET_EINT_PWM_RISE_DELAY_MASK 0x3FF +#define PMIC_ACCDET_EINT_PWM_RISE_DELAY_SHIFT 6 +#define PMIC_ACCDET_TEST_MODE13_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_TEST_MODE13_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE13_SHIFT 1 +#define PMIC_ACCDET_TEST_MODE12_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_TEST_MODE12_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE12_SHIFT 2 +#define PMIC_ACCDET_NVDETECTOUT_SW_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_NVDETECTOUT_SW_MASK 0x1 +#define PMIC_ACCDET_NVDETECTOUT_SW_SHIFT 3 +#define PMIC_ACCDET_TEST_MODE11_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_TEST_MODE11_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE11_SHIFT 5 +#define PMIC_ACCDET_TEST_MODE10_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_TEST_MODE10_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE10_SHIFT 6 +#define PMIC_ACCDET_EINTCMPOUT_SW_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_EINTCMPOUT_SW_MASK 0x1 +#define PMIC_ACCDET_EINTCMPOUT_SW_SHIFT 7 +#define PMIC_ACCDET_TEST_MODE9_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_TEST_MODE9_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE9_SHIFT 9 +#define PMIC_ACCDET_TEST_MODE8_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_TEST_MODE8_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE8_SHIFT 10 +#define PMIC_ACCDET_AUXADC_CTRL_SW_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_AUXADC_CTRL_SW_MASK 0x1 +#define PMIC_ACCDET_AUXADC_CTRL_SW_SHIFT 11 +#define PMIC_ACCDET_TEST_MODE7_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_TEST_MODE7_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE7_SHIFT 13 +#define PMIC_ACCDET_TEST_MODE6_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_TEST_MODE6_MASK 0x1 +#define PMIC_ACCDET_TEST_MODE6_SHIFT 14 +#define PMIC_ACCDET_EINTCMP_EN_SW_ADDR MT6353_ACCDET_CON17 +#define PMIC_ACCDET_EINTCMP_EN_SW_MASK 0x1 +#define PMIC_ACCDET_EINTCMP_EN_SW_SHIFT 15 +#define PMIC_RG_NVCMPSWEN_ADDR MT6353_ACCDET_CON18 +#define PMIC_RG_NVCMPSWEN_MASK 0x1 +#define PMIC_RG_NVCMPSWEN_SHIFT 8 +#define PMIC_RG_NVMODSEL_ADDR MT6353_ACCDET_CON18 +#define PMIC_RG_NVMODSEL_MASK 0x1 +#define PMIC_RG_NVMODSEL_SHIFT 9 +#define PMIC_RG_SWBUFSWEN_ADDR MT6353_ACCDET_CON18 +#define PMIC_RG_SWBUFSWEN_MASK 0x1 +#define PMIC_RG_SWBUFSWEN_SHIFT 10 +#define PMIC_RG_SWBUFMODSEL_ADDR MT6353_ACCDET_CON18 +#define PMIC_RG_SWBUFMODSEL_MASK 0x1 +#define PMIC_RG_SWBUFMODSEL_SHIFT 11 +#define PMIC_RG_NVDETVTH_ADDR MT6353_ACCDET_CON18 +#define PMIC_RG_NVDETVTH_MASK 0x1 +#define PMIC_RG_NVDETVTH_SHIFT 12 +#define PMIC_RG_NVDETCMPEN_ADDR MT6353_ACCDET_CON18 +#define PMIC_RG_NVDETCMPEN_MASK 0x1 +#define PMIC_RG_NVDETCMPEN_SHIFT 13 +#define PMIC_RG_EINTCONFIGACCDET_ADDR MT6353_ACCDET_CON18 +#define PMIC_RG_EINTCONFIGACCDET_MASK 0x1 +#define PMIC_RG_EINTCONFIGACCDET_SHIFT 14 +#define PMIC_RG_EINTCOMPVTH_ADDR MT6353_ACCDET_CON18 +#define PMIC_RG_EINTCOMPVTH_MASK 0x1 +#define PMIC_RG_EINTCOMPVTH_SHIFT 15 +#define PMIC_ACCDET_EINT_STATE_ADDR MT6353_ACCDET_CON19 +#define PMIC_ACCDET_EINT_STATE_MASK 0x7 +#define PMIC_ACCDET_EINT_STATE_SHIFT 0 +#define PMIC_ACCDET_AUXADC_DEBOUNCE_END_ADDR MT6353_ACCDET_CON19 +#define PMIC_ACCDET_AUXADC_DEBOUNCE_END_MASK 0x1 +#define PMIC_ACCDET_AUXADC_DEBOUNCE_END_SHIFT 3 +#define PMIC_ACCDET_AUXADC_CONNECT_PRE_ADDR MT6353_ACCDET_CON19 +#define PMIC_ACCDET_AUXADC_CONNECT_PRE_MASK 0x1 +#define PMIC_ACCDET_AUXADC_CONNECT_PRE_SHIFT 4 +#define PMIC_ACCDET_EINT_CUR_IN_ADDR MT6353_ACCDET_CON19 +#define PMIC_ACCDET_EINT_CUR_IN_MASK 0x1 +#define PMIC_ACCDET_EINT_CUR_IN_SHIFT 8 +#define PMIC_ACCDET_EINT_SAM_IN_ADDR MT6353_ACCDET_CON19 +#define PMIC_ACCDET_EINT_SAM_IN_MASK 0x1 +#define PMIC_ACCDET_EINT_SAM_IN_SHIFT 9 +#define PMIC_ACCDET_EINT_MEM_IN_ADDR MT6353_ACCDET_CON19 +#define PMIC_ACCDET_EINT_MEM_IN_MASK 0x1 +#define PMIC_ACCDET_EINT_MEM_IN_SHIFT 10 +#define PMIC_AD_NVDETECTOUT_ADDR MT6353_ACCDET_CON19 +#define PMIC_AD_NVDETECTOUT_MASK 0x1 +#define PMIC_AD_NVDETECTOUT_SHIFT 13 +#define PMIC_AD_EINTCMPOUT_ADDR MT6353_ACCDET_CON19 +#define PMIC_AD_EINTCMPOUT_MASK 0x1 +#define PMIC_AD_EINTCMPOUT_SHIFT 14 +#define PMIC_DA_NI_EINTCMPEN_ADDR MT6353_ACCDET_CON19 +#define PMIC_DA_NI_EINTCMPEN_MASK 0x1 +#define PMIC_DA_NI_EINTCMPEN_SHIFT 15 +#define PMIC_ACCDET_NEGV_COUNT_IN_ADDR MT6353_ACCDET_CON20 +#define PMIC_ACCDET_NEGV_COUNT_IN_MASK 0x3F +#define PMIC_ACCDET_NEGV_COUNT_IN_SHIFT 0 +#define PMIC_ACCDET_NEGV_EN_FINAL_ADDR MT6353_ACCDET_CON20 +#define PMIC_ACCDET_NEGV_EN_FINAL_MASK 0x1 +#define PMIC_ACCDET_NEGV_EN_FINAL_SHIFT 6 +#define PMIC_ACCDET_NEGV_COUNT_END_ADDR MT6353_ACCDET_CON20 +#define PMIC_ACCDET_NEGV_COUNT_END_MASK 0x1 +#define PMIC_ACCDET_NEGV_COUNT_END_SHIFT 12 +#define PMIC_ACCDET_NEGV_MINU_ADDR MT6353_ACCDET_CON20 +#define PMIC_ACCDET_NEGV_MINU_MASK 0x1 +#define PMIC_ACCDET_NEGV_MINU_SHIFT 13 +#define PMIC_ACCDET_NEGV_ADD_ADDR MT6353_ACCDET_CON20 +#define PMIC_ACCDET_NEGV_ADD_MASK 0x1 +#define PMIC_ACCDET_NEGV_ADD_SHIFT 14 +#define PMIC_ACCDET_NEGV_CMP_ADDR MT6353_ACCDET_CON20 +#define PMIC_ACCDET_NEGV_CMP_MASK 0x1 +#define PMIC_ACCDET_NEGV_CMP_SHIFT 15 +#define PMIC_ACCDET_CUR_DEB_ADDR MT6353_ACCDET_CON21 +#define PMIC_ACCDET_CUR_DEB_MASK 0xFFFF +#define PMIC_ACCDET_CUR_DEB_SHIFT 0 +#define PMIC_ACCDET_EINT_CUR_DEB_ADDR MT6353_ACCDET_CON22 +#define PMIC_ACCDET_EINT_CUR_DEB_MASK 0x7FFF +#define PMIC_ACCDET_EINT_CUR_DEB_SHIFT 0 +#define PMIC_ACCDET_RSV_CON0_ADDR MT6353_ACCDET_CON23 +#define PMIC_ACCDET_RSV_CON0_MASK 0xFFFF +#define PMIC_ACCDET_RSV_CON0_SHIFT 0 +#define PMIC_ACCDET_RSV_CON1_ADDR MT6353_ACCDET_CON24 +#define PMIC_ACCDET_RSV_CON1_MASK 0xFFFF +#define PMIC_ACCDET_RSV_CON1_SHIFT 0 +#define PMIC_ACCDET_AUXADC_CONNECT_TIME_ADDR MT6353_ACCDET_CON25 +#define PMIC_ACCDET_AUXADC_CONNECT_TIME_MASK 0xFFFF +#define PMIC_ACCDET_AUXADC_CONNECT_TIME_SHIFT 0 +#define PMIC_RG_VCDT_HV_EN_ADDR MT6353_CHR_CON0 +#define PMIC_RG_VCDT_HV_EN_MASK 0x1 +#define PMIC_RG_VCDT_HV_EN_SHIFT 0 +#define PMIC_RGS_CHR_LDO_DET_ADDR MT6353_CHR_CON0 +#define PMIC_RGS_CHR_LDO_DET_MASK 0x1 +#define PMIC_RGS_CHR_LDO_DET_SHIFT 1 +#define PMIC_RG_PCHR_AUTOMODE_ADDR MT6353_CHR_CON0 +#define PMIC_RG_PCHR_AUTOMODE_MASK 0x1 +#define PMIC_RG_PCHR_AUTOMODE_SHIFT 2 +#define PMIC_RG_CSDAC_EN_ADDR MT6353_CHR_CON0 +#define PMIC_RG_CSDAC_EN_MASK 0x1 +#define PMIC_RG_CSDAC_EN_SHIFT 3 +#define PMIC_RG_CHR_EN_ADDR MT6353_CHR_CON0 +#define PMIC_RG_CHR_EN_MASK 0x1 +#define PMIC_RG_CHR_EN_SHIFT 4 +#define PMIC_RGS_CHRDET_ADDR MT6353_CHR_CON0 +#define PMIC_RGS_CHRDET_MASK 0x1 +#define PMIC_RGS_CHRDET_SHIFT 5 +#define PMIC_RGS_VCDT_LV_DET_ADDR MT6353_CHR_CON0 +#define PMIC_RGS_VCDT_LV_DET_MASK 0x1 +#define PMIC_RGS_VCDT_LV_DET_SHIFT 6 +#define PMIC_RGS_VCDT_HV_DET_ADDR MT6353_CHR_CON0 +#define PMIC_RGS_VCDT_HV_DET_MASK 0x1 +#define PMIC_RGS_VCDT_HV_DET_SHIFT 7 +#define PMIC_RG_VCDT_LV_VTH_ADDR MT6353_CHR_CON1 +#define PMIC_RG_VCDT_LV_VTH_MASK 0xF +#define PMIC_RG_VCDT_LV_VTH_SHIFT 0 +#define PMIC_RG_VCDT_HV_VTH_ADDR MT6353_CHR_CON1 +#define PMIC_RG_VCDT_HV_VTH_MASK 0xF +#define PMIC_RG_VCDT_HV_VTH_SHIFT 4 +#define PMIC_RG_VBAT_CV_EN_ADDR MT6353_CHR_CON2 +#define PMIC_RG_VBAT_CV_EN_MASK 0x1 +#define PMIC_RG_VBAT_CV_EN_SHIFT 1 +#define PMIC_RG_VBAT_CC_EN_ADDR MT6353_CHR_CON2 +#define PMIC_RG_VBAT_CC_EN_MASK 0x1 +#define PMIC_RG_VBAT_CC_EN_SHIFT 2 +#define PMIC_RG_CS_EN_ADDR MT6353_CHR_CON2 +#define PMIC_RG_CS_EN_MASK 0x1 +#define PMIC_RG_CS_EN_SHIFT 3 +#define PMIC_RGS_CS_DET_ADDR MT6353_CHR_CON2 +#define PMIC_RGS_CS_DET_MASK 0x1 +#define PMIC_RGS_CS_DET_SHIFT 5 +#define PMIC_RGS_VBAT_CV_DET_ADDR MT6353_CHR_CON2 +#define PMIC_RGS_VBAT_CV_DET_MASK 0x1 +#define PMIC_RGS_VBAT_CV_DET_SHIFT 6 +#define PMIC_RGS_VBAT_CC_DET_ADDR MT6353_CHR_CON2 +#define PMIC_RGS_VBAT_CC_DET_MASK 0x1 +#define PMIC_RGS_VBAT_CC_DET_SHIFT 7 +#define PMIC_RG_VBAT_CV_VTH_ADDR MT6353_CHR_CON3 +#define PMIC_RG_VBAT_CV_VTH_MASK 0x1F +#define PMIC_RG_VBAT_CV_VTH_SHIFT 0 +#define PMIC_RG_VBAT_CC_VTH_ADDR MT6353_CHR_CON3 +#define PMIC_RG_VBAT_CC_VTH_MASK 0x3 +#define PMIC_RG_VBAT_CC_VTH_SHIFT 6 +#define PMIC_RG_CS_VTH_ADDR MT6353_CHR_CON4 +#define PMIC_RG_CS_VTH_MASK 0xF +#define PMIC_RG_CS_VTH_SHIFT 0 +#define PMIC_RG_PCHR_TOHTC_ADDR MT6353_CHR_CON5 +#define PMIC_RG_PCHR_TOHTC_MASK 0x7 +#define PMIC_RG_PCHR_TOHTC_SHIFT 0 +#define PMIC_RG_PCHR_TOLTC_ADDR MT6353_CHR_CON5 +#define PMIC_RG_PCHR_TOLTC_MASK 0x7 +#define PMIC_RG_PCHR_TOLTC_SHIFT 4 +#define PMIC_RG_VBAT_OV_EN_ADDR MT6353_CHR_CON6 +#define PMIC_RG_VBAT_OV_EN_MASK 0x1 +#define PMIC_RG_VBAT_OV_EN_SHIFT 0 +#define PMIC_RG_VBAT_OV_VTH_ADDR MT6353_CHR_CON6 +#define PMIC_RG_VBAT_OV_VTH_MASK 0x7 +#define PMIC_RG_VBAT_OV_VTH_SHIFT 2 +#define PMIC_RG_VBAT_OV_DEG_ADDR MT6353_CHR_CON6 +#define PMIC_RG_VBAT_OV_DEG_MASK 0x1 +#define PMIC_RG_VBAT_OV_DEG_SHIFT 5 +#define PMIC_RGS_VBAT_OV_DET_ADDR MT6353_CHR_CON6 +#define PMIC_RGS_VBAT_OV_DET_MASK 0x1 +#define PMIC_RGS_VBAT_OV_DET_SHIFT 6 +#define PMIC_RG_BATON_EN_ADDR MT6353_CHR_CON7 +#define PMIC_RG_BATON_EN_MASK 0x1 +#define PMIC_RG_BATON_EN_SHIFT 0 +#define PMIC_RG_BATON_HT_EN_RSV0_ADDR MT6353_CHR_CON7 +#define PMIC_RG_BATON_HT_EN_RSV0_MASK 0x1 +#define PMIC_RG_BATON_HT_EN_RSV0_SHIFT 1 +#define PMIC_BATON_TDET_EN_ADDR MT6353_CHR_CON7 +#define PMIC_BATON_TDET_EN_MASK 0x1 +#define PMIC_BATON_TDET_EN_SHIFT 2 +#define PMIC_RG_BATON_HT_TRIM_ADDR MT6353_CHR_CON7 +#define PMIC_RG_BATON_HT_TRIM_MASK 0x7 +#define PMIC_RG_BATON_HT_TRIM_SHIFT 4 +#define PMIC_RG_BATON_HT_TRIM_SET_ADDR MT6353_CHR_CON7 +#define PMIC_RG_BATON_HT_TRIM_SET_MASK 0x1 +#define PMIC_RG_BATON_HT_TRIM_SET_SHIFT 7 +#define PMIC_RG_BATON_TDET_EN_ADDR MT6353_CHR_CON7 +#define PMIC_RG_BATON_TDET_EN_MASK 0x1 +#define PMIC_RG_BATON_TDET_EN_SHIFT 8 +#define PMIC_RG_CSDAC_DATA_ADDR MT6353_CHR_CON8 +#define PMIC_RG_CSDAC_DATA_MASK 0x3FF +#define PMIC_RG_CSDAC_DATA_SHIFT 0 +#define PMIC_RG_FRC_CSVTH_USBDL_ADDR MT6353_CHR_CON9 +#define PMIC_RG_FRC_CSVTH_USBDL_MASK 0x1 +#define PMIC_RG_FRC_CSVTH_USBDL_SHIFT 0 +#define PMIC_RGS_PCHR_FLAG_OUT_ADDR MT6353_CHR_CON10 +#define PMIC_RGS_PCHR_FLAG_OUT_MASK 0xF +#define PMIC_RGS_PCHR_FLAG_OUT_SHIFT 0 +#define PMIC_RG_PCHR_FLAG_EN_ADDR MT6353_CHR_CON10 +#define PMIC_RG_PCHR_FLAG_EN_MASK 0x1 +#define PMIC_RG_PCHR_FLAG_EN_SHIFT 4 +#define PMIC_RG_OTG_BVALID_EN_ADDR MT6353_CHR_CON10 +#define PMIC_RG_OTG_BVALID_EN_MASK 0x1 +#define PMIC_RG_OTG_BVALID_EN_SHIFT 5 +#define PMIC_RGS_OTG_BVALID_DET_ADDR MT6353_CHR_CON10 +#define PMIC_RGS_OTG_BVALID_DET_MASK 0x1 +#define PMIC_RGS_OTG_BVALID_DET_SHIFT 6 +#define PMIC_RG_PCHR_FLAG_SEL_ADDR MT6353_CHR_CON11 +#define PMIC_RG_PCHR_FLAG_SEL_MASK 0x3F +#define PMIC_RG_PCHR_FLAG_SEL_SHIFT 0 +#define PMIC_RG_PCHR_TESTMODE_ADDR MT6353_CHR_CON12 +#define PMIC_RG_PCHR_TESTMODE_MASK 0x1 +#define PMIC_RG_PCHR_TESTMODE_SHIFT 0 +#define PMIC_RG_CSDAC_TESTMODE_ADDR MT6353_CHR_CON12 +#define PMIC_RG_CSDAC_TESTMODE_MASK 0x1 +#define PMIC_RG_CSDAC_TESTMODE_SHIFT 1 +#define PMIC_RG_PCHR_RST_ADDR MT6353_CHR_CON12 +#define PMIC_RG_PCHR_RST_MASK 0x1 +#define PMIC_RG_PCHR_RST_SHIFT 2 +#define PMIC_RG_PCHR_FT_CTRL_ADDR MT6353_CHR_CON12 +#define PMIC_RG_PCHR_FT_CTRL_MASK 0x7 +#define PMIC_RG_PCHR_FT_CTRL_SHIFT 4 +#define PMIC_RG_CHRWDT_TD_ADDR MT6353_CHR_CON13 +#define PMIC_RG_CHRWDT_TD_MASK 0xF +#define PMIC_RG_CHRWDT_TD_SHIFT 0 +#define PMIC_RG_CHRWDT_EN_ADDR MT6353_CHR_CON13 +#define PMIC_RG_CHRWDT_EN_MASK 0x1 +#define PMIC_RG_CHRWDT_EN_SHIFT 4 +#define PMIC_RG_CHRWDT_WR_ADDR MT6353_CHR_CON13 +#define PMIC_RG_CHRWDT_WR_MASK 0x1 +#define PMIC_RG_CHRWDT_WR_SHIFT 8 +#define PMIC_RG_PCHR_RV_ADDR MT6353_CHR_CON14 +#define PMIC_RG_PCHR_RV_MASK 0xFF +#define PMIC_RG_PCHR_RV_SHIFT 0 +#define PMIC_RG_CHRWDT_INT_EN_ADDR MT6353_CHR_CON15 +#define PMIC_RG_CHRWDT_INT_EN_MASK 0x1 +#define PMIC_RG_CHRWDT_INT_EN_SHIFT 0 +#define PMIC_RG_CHRWDT_FLAG_WR_ADDR MT6353_CHR_CON15 +#define PMIC_RG_CHRWDT_FLAG_WR_MASK 0x1 +#define PMIC_RG_CHRWDT_FLAG_WR_SHIFT 1 +#define PMIC_RGS_CHRWDT_OUT_ADDR MT6353_CHR_CON15 +#define PMIC_RGS_CHRWDT_OUT_MASK 0x1 +#define PMIC_RGS_CHRWDT_OUT_SHIFT 2 +#define PMIC_RG_USBDL_RST_ADDR MT6353_CHR_CON16 +#define PMIC_RG_USBDL_RST_MASK 0x1 +#define PMIC_RG_USBDL_RST_SHIFT 2 +#define PMIC_RG_USBDL_SET_ADDR MT6353_CHR_CON16 +#define PMIC_RG_USBDL_SET_MASK 0x1 +#define PMIC_RG_USBDL_SET_SHIFT 3 +#define PMIC_RG_ADCIN_VSEN_MUX_EN_ADDR MT6353_CHR_CON16 +#define PMIC_RG_ADCIN_VSEN_MUX_EN_MASK 0x1 +#define PMIC_RG_ADCIN_VSEN_MUX_EN_SHIFT 8 +#define PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_ADDR MT6353_CHR_CON16 +#define PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_MASK 0x1 +#define PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_SHIFT 9 +#define PMIC_RG_ADCIN_VBAT_EN_ADDR MT6353_CHR_CON16 +#define PMIC_RG_ADCIN_VBAT_EN_MASK 0x1 +#define PMIC_RG_ADCIN_VBAT_EN_SHIFT 10 +#define PMIC_RG_ADCIN_VSEN_EN_ADDR MT6353_CHR_CON16 +#define PMIC_RG_ADCIN_VSEN_EN_MASK 0x1 +#define PMIC_RG_ADCIN_VSEN_EN_SHIFT 11 +#define PMIC_RG_ADCIN_CHR_EN_ADDR MT6353_CHR_CON16 +#define PMIC_RG_ADCIN_CHR_EN_MASK 0x1 +#define PMIC_RG_ADCIN_CHR_EN_SHIFT 12 +#define PMIC_RG_UVLO_VTHL_ADDR MT6353_CHR_CON17 +#define PMIC_RG_UVLO_VTHL_MASK 0x1F +#define PMIC_RG_UVLO_VTHL_SHIFT 0 +#define PMIC_RG_UVLO_VH_LAT_ADDR MT6353_CHR_CON17 +#define PMIC_RG_UVLO_VH_LAT_MASK 0x1 +#define PMIC_RG_UVLO_VH_LAT_SHIFT 7 +#define PMIC_RG_LBAT_INT_VTH_ADDR MT6353_CHR_CON18 +#define PMIC_RG_LBAT_INT_VTH_MASK 0x1F +#define PMIC_RG_LBAT_INT_VTH_SHIFT 0 +#define PMIC_RG_BGR_RSEL_ADDR MT6353_CHR_CON19 +#define PMIC_RG_BGR_RSEL_MASK 0x7 +#define PMIC_RG_BGR_RSEL_SHIFT 0 +#define PMIC_RG_BGR_UNCHOP_PH_ADDR MT6353_CHR_CON19 +#define PMIC_RG_BGR_UNCHOP_PH_MASK 0x1 +#define PMIC_RG_BGR_UNCHOP_PH_SHIFT 4 +#define PMIC_RG_BGR_UNCHOP_ADDR MT6353_CHR_CON19 +#define PMIC_RG_BGR_UNCHOP_MASK 0x1 +#define PMIC_RG_BGR_UNCHOP_SHIFT 5 +#define PMIC_RG_BC11_BB_CTRL_ADDR MT6353_CHR_CON20 +#define PMIC_RG_BC11_BB_CTRL_MASK 0x1 +#define PMIC_RG_BC11_BB_CTRL_SHIFT 0 +#define PMIC_RG_BC11_RST_ADDR MT6353_CHR_CON20 +#define PMIC_RG_BC11_RST_MASK 0x1 +#define PMIC_RG_BC11_RST_SHIFT 1 +#define PMIC_RG_BC11_VSRC_EN_ADDR MT6353_CHR_CON20 +#define PMIC_RG_BC11_VSRC_EN_MASK 0x3 +#define PMIC_RG_BC11_VSRC_EN_SHIFT 2 +#define PMIC_RGS_BC11_CMP_OUT_ADDR MT6353_CHR_CON20 +#define PMIC_RGS_BC11_CMP_OUT_MASK 0x1 +#define PMIC_RGS_BC11_CMP_OUT_SHIFT 7 +#define PMIC_RG_BC11_VREF_VTH_ADDR MT6353_CHR_CON21 +#define PMIC_RG_BC11_VREF_VTH_MASK 0x3 +#define PMIC_RG_BC11_VREF_VTH_SHIFT 0 +#define PMIC_RG_BC11_CMP_EN_ADDR MT6353_CHR_CON21 +#define PMIC_RG_BC11_CMP_EN_MASK 0x3 +#define PMIC_RG_BC11_CMP_EN_SHIFT 2 +#define PMIC_RG_BC11_IPD_EN_ADDR MT6353_CHR_CON21 +#define PMIC_RG_BC11_IPD_EN_MASK 0x3 +#define PMIC_RG_BC11_IPD_EN_SHIFT 4 +#define PMIC_RG_BC11_IPU_EN_ADDR MT6353_CHR_CON21 +#define PMIC_RG_BC11_IPU_EN_MASK 0x3 +#define PMIC_RG_BC11_IPU_EN_SHIFT 6 +#define PMIC_RG_BC11_BIAS_EN_ADDR MT6353_CHR_CON21 +#define PMIC_RG_BC11_BIAS_EN_MASK 0x1 +#define PMIC_RG_BC11_BIAS_EN_SHIFT 8 +#define PMIC_RG_CSDAC_STP_INC_ADDR MT6353_CHR_CON22 +#define PMIC_RG_CSDAC_STP_INC_MASK 0x7 +#define PMIC_RG_CSDAC_STP_INC_SHIFT 0 +#define PMIC_RG_CSDAC_STP_DEC_ADDR MT6353_CHR_CON22 +#define PMIC_RG_CSDAC_STP_DEC_MASK 0x7 +#define PMIC_RG_CSDAC_STP_DEC_SHIFT 4 +#define PMIC_RG_CSDAC_DLY_ADDR MT6353_CHR_CON23 +#define PMIC_RG_CSDAC_DLY_MASK 0x7 +#define PMIC_RG_CSDAC_DLY_SHIFT 0 +#define PMIC_RG_CSDAC_STP_ADDR MT6353_CHR_CON23 +#define PMIC_RG_CSDAC_STP_MASK 0x7 +#define PMIC_RG_CSDAC_STP_SHIFT 4 +#define PMIC_RG_LOW_ICH_DB_ADDR MT6353_CHR_CON24 +#define PMIC_RG_LOW_ICH_DB_MASK 0x3F +#define PMIC_RG_LOW_ICH_DB_SHIFT 0 +#define PMIC_RG_CHRIND_ON_ADDR MT6353_CHR_CON24 +#define PMIC_RG_CHRIND_ON_MASK 0x1 +#define PMIC_RG_CHRIND_ON_SHIFT 6 +#define PMIC_RG_CHRIND_DIMMING_ADDR MT6353_CHR_CON24 +#define PMIC_RG_CHRIND_DIMMING_MASK 0x1 +#define PMIC_RG_CHRIND_DIMMING_SHIFT 7 +#define PMIC_RG_CV_MODE_ADDR MT6353_CHR_CON25 +#define PMIC_RG_CV_MODE_MASK 0x1 +#define PMIC_RG_CV_MODE_SHIFT 0 +#define PMIC_RG_VCDT_MODE_ADDR MT6353_CHR_CON25 +#define PMIC_RG_VCDT_MODE_MASK 0x1 +#define PMIC_RG_VCDT_MODE_SHIFT 1 +#define PMIC_RG_CSDAC_MODE_ADDR MT6353_CHR_CON25 +#define PMIC_RG_CSDAC_MODE_MASK 0x1 +#define PMIC_RG_CSDAC_MODE_SHIFT 2 +#define PMIC_RG_TRACKING_EN_ADDR MT6353_CHR_CON25 +#define PMIC_RG_TRACKING_EN_MASK 0x1 +#define PMIC_RG_TRACKING_EN_SHIFT 4 +#define PMIC_RG_HWCV_EN_ADDR MT6353_CHR_CON25 +#define PMIC_RG_HWCV_EN_MASK 0x1 +#define PMIC_RG_HWCV_EN_SHIFT 6 +#define PMIC_RG_ULC_DET_EN_ADDR MT6353_CHR_CON25 +#define PMIC_RG_ULC_DET_EN_MASK 0x1 +#define PMIC_RG_ULC_DET_EN_SHIFT 7 +#define PMIC_RG_BGR_TRIM_EN_ADDR MT6353_CHR_CON26 +#define PMIC_RG_BGR_TRIM_EN_MASK 0x1 +#define PMIC_RG_BGR_TRIM_EN_SHIFT 0 +#define PMIC_RG_ICHRG_TRIM_ADDR MT6353_CHR_CON26 +#define PMIC_RG_ICHRG_TRIM_MASK 0xF +#define PMIC_RG_ICHRG_TRIM_SHIFT 4 +#define PMIC_RG_BGR_TRIM_ADDR MT6353_CHR_CON27 +#define PMIC_RG_BGR_TRIM_MASK 0x1F +#define PMIC_RG_BGR_TRIM_SHIFT 0 +#define PMIC_RG_OVP_TRIM_ADDR MT6353_CHR_CON28 +#define PMIC_RG_OVP_TRIM_MASK 0xF +#define PMIC_RG_OVP_TRIM_SHIFT 0 +#define PMIC_RG_CHR_OSC_TRIM_ADDR MT6353_CHR_CON29 +#define PMIC_RG_CHR_OSC_TRIM_MASK 0x1F +#define PMIC_RG_CHR_OSC_TRIM_SHIFT 0 +#define PMIC_DA_QI_BGR_EXT_BUF_EN_ADDR MT6353_CHR_CON29 +#define PMIC_DA_QI_BGR_EXT_BUF_EN_MASK 0x1 +#define PMIC_DA_QI_BGR_EXT_BUF_EN_SHIFT 5 +#define PMIC_RG_BGR_TEST_EN_ADDR MT6353_CHR_CON29 +#define PMIC_RG_BGR_TEST_EN_MASK 0x1 +#define PMIC_RG_BGR_TEST_EN_SHIFT 6 +#define PMIC_RG_BGR_TEST_RSTB_ADDR MT6353_CHR_CON29 +#define PMIC_RG_BGR_TEST_RSTB_MASK 0x1 +#define PMIC_RG_BGR_TEST_RSTB_SHIFT 7 +#define PMIC_RG_DAC_USBDL_MAX_ADDR MT6353_CHR_CON30 +#define PMIC_RG_DAC_USBDL_MAX_MASK 0x3FF +#define PMIC_RG_DAC_USBDL_MAX_SHIFT 0 +#define PMIC_RG_CM_VDEC_TRIG_ADDR MT6353_CHR_CON31 +#define PMIC_RG_CM_VDEC_TRIG_MASK 0x1 +#define PMIC_RG_CM_VDEC_TRIG_SHIFT 0 +#define PMIC_PCHR_CM_VDEC_STATUS_ADDR MT6353_CHR_CON31 +#define PMIC_PCHR_CM_VDEC_STATUS_MASK 0x1 +#define PMIC_PCHR_CM_VDEC_STATUS_SHIFT 4 +#define PMIC_RG_CM_VINC_TRIG_ADDR MT6353_CHR_CON32 +#define PMIC_RG_CM_VINC_TRIG_MASK 0x1 +#define PMIC_RG_CM_VINC_TRIG_SHIFT 0 +#define PMIC_PCHR_CM_VINC_STATUS_ADDR MT6353_CHR_CON32 +#define PMIC_PCHR_CM_VINC_STATUS_MASK 0x1 +#define PMIC_PCHR_CM_VINC_STATUS_SHIFT 4 +#define PMIC_RG_CM_VDEC_HPRD1_ADDR MT6353_CHR_CON33 +#define PMIC_RG_CM_VDEC_HPRD1_MASK 0x3F +#define PMIC_RG_CM_VDEC_HPRD1_SHIFT 0 +#define PMIC_RG_CM_VDEC_HPRD2_ADDR MT6353_CHR_CON33 +#define PMIC_RG_CM_VDEC_HPRD2_MASK 0x3F +#define PMIC_RG_CM_VDEC_HPRD2_SHIFT 8 +#define PMIC_RG_CM_VDEC_HPRD3_ADDR MT6353_CHR_CON34 +#define PMIC_RG_CM_VDEC_HPRD3_MASK 0x3F +#define PMIC_RG_CM_VDEC_HPRD3_SHIFT 0 +#define PMIC_RG_CM_VDEC_HPRD4_ADDR MT6353_CHR_CON34 +#define PMIC_RG_CM_VDEC_HPRD4_MASK 0x3F +#define PMIC_RG_CM_VDEC_HPRD4_SHIFT 8 +#define PMIC_RG_CM_VDEC_HPRD5_ADDR MT6353_CHR_CON35 +#define PMIC_RG_CM_VDEC_HPRD5_MASK 0x3F +#define PMIC_RG_CM_VDEC_HPRD5_SHIFT 0 +#define PMIC_RG_CM_VDEC_HPRD6_ADDR MT6353_CHR_CON35 +#define PMIC_RG_CM_VDEC_HPRD6_MASK 0x3F +#define PMIC_RG_CM_VDEC_HPRD6_SHIFT 8 +#define PMIC_RG_CM_VINC_HPRD1_ADDR MT6353_CHR_CON36 +#define PMIC_RG_CM_VINC_HPRD1_MASK 0x3F +#define PMIC_RG_CM_VINC_HPRD1_SHIFT 0 +#define PMIC_RG_CM_VINC_HPRD2_ADDR MT6353_CHR_CON36 +#define PMIC_RG_CM_VINC_HPRD2_MASK 0x3F +#define PMIC_RG_CM_VINC_HPRD2_SHIFT 8 +#define PMIC_RG_CM_VINC_HPRD3_ADDR MT6353_CHR_CON37 +#define PMIC_RG_CM_VINC_HPRD3_MASK 0x3F +#define PMIC_RG_CM_VINC_HPRD3_SHIFT 0 +#define PMIC_RG_CM_VINC_HPRD4_ADDR MT6353_CHR_CON37 +#define PMIC_RG_CM_VINC_HPRD4_MASK 0x3F +#define PMIC_RG_CM_VINC_HPRD4_SHIFT 8 +#define PMIC_RG_CM_VINC_HPRD5_ADDR MT6353_CHR_CON38 +#define PMIC_RG_CM_VINC_HPRD5_MASK 0x3F +#define PMIC_RG_CM_VINC_HPRD5_SHIFT 0 +#define PMIC_RG_CM_VINC_HPRD6_ADDR MT6353_CHR_CON38 +#define PMIC_RG_CM_VINC_HPRD6_MASK 0x3F +#define PMIC_RG_CM_VINC_HPRD6_SHIFT 8 +#define PMIC_RG_CM_LPRD_ADDR MT6353_CHR_CON39 +#define PMIC_RG_CM_LPRD_MASK 0x3F +#define PMIC_RG_CM_LPRD_SHIFT 0 +#define PMIC_RG_CM_CS_VTHL_ADDR MT6353_CHR_CON40 +#define PMIC_RG_CM_CS_VTHL_MASK 0xF +#define PMIC_RG_CM_CS_VTHL_SHIFT 0 +#define PMIC_RG_CM_CS_VTHH_ADDR MT6353_CHR_CON40 +#define PMIC_RG_CM_CS_VTHH_MASK 0xF +#define PMIC_RG_CM_CS_VTHH_SHIFT 4 +#define PMIC_RG_PCHR_RSV_ADDR MT6353_CHR_CON41 +#define PMIC_RG_PCHR_RSV_MASK 0xFF +#define PMIC_RG_PCHR_RSV_SHIFT 0 +#define PMIC_RG_ENVTEM_D_ADDR MT6353_CHR_CON42 +#define PMIC_RG_ENVTEM_D_MASK 0x1 +#define PMIC_RG_ENVTEM_D_SHIFT 0 +#define PMIC_RG_ENVTEM_EN_ADDR MT6353_CHR_CON42 +#define PMIC_RG_ENVTEM_EN_MASK 0x1 +#define PMIC_RG_ENVTEM_EN_SHIFT 1 +#define PMIC_RGS_BATON_HV_ADDR MT6353_BATON_CON0 +#define PMIC_RGS_BATON_HV_MASK 0x1 +#define PMIC_RGS_BATON_HV_SHIFT 6 +#define PMIC_RG_HW_VTH_CTRL_ADDR MT6353_BATON_CON0 +#define PMIC_RG_HW_VTH_CTRL_MASK 0x1 +#define PMIC_RG_HW_VTH_CTRL_SHIFT 11 +#define PMIC_RG_HW_VTH2_ADDR MT6353_BATON_CON0 +#define PMIC_RG_HW_VTH2_MASK 0x3 +#define PMIC_RG_HW_VTH2_SHIFT 12 +#define PMIC_RG_HW_VTH1_ADDR MT6353_BATON_CON0 +#define PMIC_RG_HW_VTH1_MASK 0x3 +#define PMIC_RG_HW_VTH1_SHIFT 14 +#define PMIC_RG_CM_VDEC_INT_EN_ADDR MT6353_CHR_CON43 +#define PMIC_RG_CM_VDEC_INT_EN_MASK 0x1 +#define PMIC_RG_CM_VDEC_INT_EN_SHIFT 9 +#define PMIC_RG_CM_VINC_INT_EN_ADDR MT6353_CHR_CON43 +#define PMIC_RG_CM_VINC_INT_EN_MASK 0x1 +#define PMIC_RG_CM_VINC_INT_EN_SHIFT 11 +#define PMIC_RG_QI_BATON_LT_EN_ADDR MT6353_CHR_CON44 +#define PMIC_RG_QI_BATON_LT_EN_MASK 0x1 +#define PMIC_RG_QI_BATON_LT_EN_SHIFT 0 +#define PMIC_RGS_BATON_UNDET_ADDR MT6353_CHR_CON44 +#define PMIC_RGS_BATON_UNDET_MASK 0x1 +#define PMIC_RGS_BATON_UNDET_SHIFT 1 +#define PMIC_RG_VCDT_TRIM_ADDR MT6353_CHR_CON48 +#define PMIC_RG_VCDT_TRIM_MASK 0xF +#define PMIC_RG_VCDT_TRIM_SHIFT 0 +#define PMIC_RG_INDICATOR_TRIM_ADDR MT6353_CHR_CON48 +#define PMIC_RG_INDICATOR_TRIM_MASK 0x7 +#define PMIC_RG_INDICATOR_TRIM_SHIFT 10 +#define PMIC_EOSC_CALI_START_ADDR MT6353_EOSC_CALI_CON0 +#define PMIC_EOSC_CALI_START_MASK 0x1 +#define PMIC_EOSC_CALI_START_SHIFT 0 +#define PMIC_EOSC_CALI_TD_ADDR MT6353_EOSC_CALI_CON0 +#define PMIC_EOSC_CALI_TD_MASK 0x7 +#define PMIC_EOSC_CALI_TD_SHIFT 5 +#define PMIC_EOSC_CALI_TEST_ADDR MT6353_EOSC_CALI_CON0 +#define PMIC_EOSC_CALI_TEST_MASK 0xF +#define PMIC_EOSC_CALI_TEST_SHIFT 9 +#define PMIC_EOSC_CALI_DCXO_RDY_TD_ADDR MT6353_EOSC_CALI_CON1 +#define PMIC_EOSC_CALI_DCXO_RDY_TD_MASK 0x7 +#define PMIC_EOSC_CALI_DCXO_RDY_TD_SHIFT 0 +#define PMIC_FRC_VTCXO0_ON_ADDR MT6353_EOSC_CALI_CON1 +#define PMIC_FRC_VTCXO0_ON_MASK 0x1 +#define PMIC_FRC_VTCXO0_ON_SHIFT 8 +#define PMIC_EOSC_CALI_RSV_ADDR MT6353_EOSC_CALI_CON1 +#define PMIC_EOSC_CALI_RSV_MASK 0xF +#define PMIC_EOSC_CALI_RSV_SHIFT 11 +#define PMIC_VRTC_PWM_MODE_ADDR MT6353_VRTC_PWM_CON0 +#define PMIC_VRTC_PWM_MODE_MASK 0x1 +#define PMIC_VRTC_PWM_MODE_SHIFT 0 +#define PMIC_VRTC_PWM_RSV_ADDR MT6353_VRTC_PWM_CON0 +#define PMIC_VRTC_PWM_RSV_MASK 0x7 +#define PMIC_VRTC_PWM_RSV_SHIFT 1 +#define PMIC_VRTC_PWM_L_DUTY_ADDR MT6353_VRTC_PWM_CON0 +#define PMIC_VRTC_PWM_L_DUTY_MASK 0xF +#define PMIC_VRTC_PWM_L_DUTY_SHIFT 4 +#define PMIC_VRTC_PWM_H_DUTY_ADDR MT6353_VRTC_PWM_CON0 +#define PMIC_VRTC_PWM_H_DUTY_MASK 0xF +#define PMIC_VRTC_PWM_H_DUTY_SHIFT 8 +#define PMIC_VRTC_CAP_SEL_ADDR MT6353_VRTC_PWM_CON0 +#define PMIC_VRTC_CAP_SEL_MASK 0x1 +#define PMIC_VRTC_CAP_SEL_SHIFT 12 + +typedef enum { + PMIC_USBDL, + PMIC_VTCXO_CONFIG, + PMIC_RG_THR_DET_DIS, + PMIC_RG_THR_TEST, + PMIC_RG_STRUP_THER_DEB_RMAX, + PMIC_RG_STRUP_THER_DEB_FMAX, + PMIC_DDUVLO_DEB_EN, + PMIC_RG_PWRBB_DEB_EN, + PMIC_RG_STRUP_OSC_EN, + PMIC_RG_STRUP_OSC_EN_SEL, + PMIC_RG_STRUP_FT_CTRL, + PMIC_RG_STRUP_PWRON_FORCE, + PMIC_RG_BIASGEN_FORCE, + PMIC_RG_STRUP_PWRON, + PMIC_RG_STRUP_PWRON_SEL, + PMIC_RG_BIASGEN, + PMIC_RG_BIASGEN_SEL, + PMIC_RG_RTC_XOSC32_ENB, + PMIC_RG_RTC_XOSC32_ENB_SEL, + PMIC_STRUP_DIG_IO_PG_FORCE, + PMIC_CLR_JUST_RST, + PMIC_UVLO_L2H_DEB_EN, + PMIC_JUST_PWRKEY_RST, + PMIC_DA_QI_OSC_EN, + PMIC_RG_STRUP_EXT_PMIC_EN, + PMIC_RG_STRUP_EXT_PMIC_SEL, + PMIC_STRUP_CON8_RSV0, + PMIC_DA_QI_EXT_PMIC_EN, + PMIC_RG_STRUP_AUXADC_START_SW, + PMIC_RG_STRUP_AUXADC_RSTB_SW, + PMIC_RG_STRUP_AUXADC_START_SEL, + PMIC_RG_STRUP_AUXADC_RSTB_SEL, + PMIC_RG_STRUP_AUXADC_RPCNT_MAX, + PMIC_STRUP_PWROFF_SEQ_EN, + PMIC_STRUP_PWROFF_PREOFF_EN, + PMIC_STRUP_DIG0_RSV0, + PMIC_STRUP_DIG1_RSV0, + PMIC_RG_RSV_SWREG, + PMIC_RG_STRUP_UVLO_U1U2_SEL, + PMIC_RG_STRUP_UVLO_U1U2_SEL_SWCTRL, + PMIC_RG_STRUP_THR_CLR, + PMIC_RG_STRUP_LONG_PRESS_EXT_SEL, + PMIC_RG_STRUP_LONG_PRESS_EXT_TD, + PMIC_RG_STRUP_LONG_PRESS_EXT_EN, + PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL, + PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKEY_CTRL, + PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL, + PMIC_RG_STRUP_ENVTEM, + PMIC_RG_STRUP_ENVTEM_CTRL, + PMIC_RG_STRUP_PWRKEY_COUNT_RESET, + PMIC_RG_STRUP_VCORE2_PG_H2L_EN, + PMIC_RG_STRUP_VMCH_PG_H2L_EN, + PMIC_RG_STRUP_VMC_PG_H2L_EN, + PMIC_RG_STRUP_VUSB33_PG_H2L_EN, + PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN, + PMIC_RG_STRUP_VPROC_PG_H2L_EN, + PMIC_RG_STRUP_VDRAM_PG_H2L_EN, + PMIC_RG_STRUP_VAUD28_PG_H2L_EN, + PMIC_RG_STRUP_VEMC_PG_H2L_EN, + PMIC_RG_STRUP_VS1_PG_H2L_EN, + PMIC_RG_STRUP_VCORE_PG_H2L_EN, + PMIC_RG_STRUP_VAUX18_PG_H2L_EN, + PMIC_RG_STRUP_VCORE2_PG_ENB, + PMIC_RG_STRUP_VMCH_PG_ENB, + PMIC_RG_STRUP_VMC_PG_ENB, + PMIC_RG_STRUP_VXO22_PG_ENB, + PMIC_RG_STRUP_VTCXO_PG_ENB, + PMIC_RG_STRUP_VUSB33_PG_ENB, + PMIC_RG_STRUP_VSRAM_PROC_PG_ENB, + PMIC_RG_STRUP_VPROC_PG_ENB, + PMIC_RG_STRUP_VDRAM_PG_ENB, + PMIC_RG_STRUP_VAUD28_PG_ENB, + PMIC_RG_STRUP_VIO28_PG_ENB, + PMIC_RG_STRUP_VEMC_PG_ENB, + PMIC_RG_STRUP_VIO18_PG_ENB, + PMIC_RG_STRUP_VS1_PG_ENB, + PMIC_RG_STRUP_VCORE_PG_ENB, + PMIC_RG_STRUP_VAUX18_PG_ENB, + PMIC_RG_STRUP_VCORE2_OC_ENB, + PMIC_RG_STRUP_VPROC_OC_ENB, + PMIC_RG_STRUP_VS1_OC_ENB, + PMIC_RG_STRUP_VCORE_OC_ENB, + PMIC_RG_STRUP_LONG_PRESS_RESET_EXTEND, + PMIC_RG_THRDET_SEL, + PMIC_RG_STRUP_THR_SEL, + PMIC_RG_THR_TMODE, + PMIC_RG_VREF_BG, + PMIC_RG_STRUP_IREF_TRIM, + PMIC_RG_RST_DRVSEL, + PMIC_RG_EN_DRVSEL, + PMIC_RG_FCHR_KEYDET_EN, + PMIC_RG_FCHR_PU_EN, + PMIC_RG_PMU_RSV, + PMIC_TYPE_C_PHY_RG_CC_RP_SEL, + PMIC_REG_TYPE_C_PHY_RG_PD_TX_SLEW_CALEN, + PMIC_REG_TYPE_C_PHY_RG_PD_TXSLEW_I, + PMIC_REG_TYPE_C_PHY_RG_CC_MPX_SEL, + PMIC_REG_TYPE_C_PHY_RG_CC_RESERVE, + PMIC_REG_TYPE_C_VCMP_CC2_SW_SEL_ST_CNT_VAL, + PMIC_REG_TYPE_C_VCMP_BIAS_EN_ST_CNT_VAL, + PMIC_REG_TYPE_C_VCMP_DAC_EN_ST_CNT_VAL, + PMIC_REG_TYPE_C_PORT_SUPPORT_ROLE, + PMIC_REG_TYPE_C_ADC_EN, + PMIC_REG_TYPE_C_ACC_EN, + PMIC_REG_TYPE_C_AUDIO_ACC_EN, + PMIC_REG_TYPE_C_DEBUG_ACC_EN, + PMIC_REG_TYPE_C_TRY_SRC_ST_EN, + PMIC_REG_TYPE_C_ATTACH_SRC_2_TRY_WAIT_SNK_ST_EN, + PMIC_REG_TYPE_C_PD2CC_DET_DISABLE_EN, + PMIC_REG_TYPE_C_ATTACH_SRC_OPEN_PDDEBOUNCE_EN, + PMIC_REG_TYPE_C_DISABLE_ST_RD_EN, + PMIC_W1_TYPE_C_SW_ENT_DISABLE_CMD, + PMIC_W1_TYPE_C_SW_ENT_UNATCH_SRC_CMD, + PMIC_W1_TYPE_C_SW_ENT_UNATCH_SNK_CMD, + PMIC_W1_TYPE_C_SW_PR_SWAP_INDICATE_CMD, + PMIC_W1_TYPE_C_SW_VCONN_SWAP_INDICATE_CMD, + PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_DEFAULT_CMD, + PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_15_CMD, + PMIC_W1_TYPE_C_SW_ADC_RESULT_MET_VRD_30_CMD, + PMIC_TYPE_C_SW_VBUS_PRESENT, + PMIC_TYPE_C_SW_DA_DRIVE_VCONN_EN, + PMIC_TYPE_C_SW_VBUS_DET_DIS, + PMIC_TYPE_C_SW_CC_DET_DIS, + PMIC_TYPE_C_SW_PD_EN, + PMIC_W1_TYPE_C_SW_ENT_SNK_PWR_REDETECT_CMD, + PMIC_REG_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL, + PMIC_REG_TYPE_C_CC_VOL_CC_DEBOUNCE_CNT_VAL, + PMIC_REG_TYPE_C_CC_VOL_PD_DEBOUNCE_CNT_VAL, + PMIC_REG_TYPE_C_DRP_SRC_CNT_VAL_0, + PMIC_REG_TYPE_C_DRP_SNK_CNT_VAL_0, + PMIC_REG_TYPE_C_DRP_TRY_CNT_VAL_0, + PMIC_REG_TYPE_C_DRP_TRY_WAIT_CNT_VAL_0, + PMIC_REG_TYPE_C_DRP_TRY_WAIT_CNT_VAL_1, + PMIC_REG_TYPE_C_CC_SRC_VOPEN_DEFAULT_DAC_VAL, + PMIC_REG_TYPE_C_CC_SRC_VRD_DEFAULT_DAC_VAL, + PMIC_REG_TYPE_C_CC_SRC_VOPEN_15_DAC_VAL, + PMIC_REG_TYPE_C_CC_SRC_VRD_15_DAC_VAL, + PMIC_REG_TYPE_C_CC_SRC_VOPEN_30_DAC_VAL, + PMIC_REG_TYPE_C_CC_SRC_VRD_30_DAC_VAL, + PMIC_REG_TYPE_C_CC_SNK_VRP30_DAC_VAL, + PMIC_REG_TYPE_C_CC_SNK_VRP15_DAC_VAL, + PMIC_REG_TYPE_C_CC_SNK_VRPUSB_DAC_VAL, + PMIC_REG_TYPE_C_CC_ENT_ATTACH_SRC_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_ATTACH_SNK_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_AUDIO_ACC_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_DBG_ACC_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_DISABLE_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_UNATTACH_SRC_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_UNATTACH_SNK_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_SRC_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_SNK_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_TRY_SRC_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_TRY_WAIT_SNK_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_UNATTACH_ACC_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_ATTACH_WAIT_ACC_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_IDLE_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_DEFAULT_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_15_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_30_INTR_EN, + PMIC_REG_TYPE_C_CC_ENT_SNK_PWR_REDETECT_INTR_EN, + PMIC_TYPE_C_CC_ENT_ATTACH_SRC_INTR, + PMIC_TYPE_C_CC_ENT_ATTACH_SNK_INTR, + PMIC_TYPE_C_CC_ENT_AUDIO_ACC_INTR, + PMIC_TYPE_C_CC_ENT_DBG_ACC_INTR, + PMIC_TYPE_C_CC_ENT_DISABLE_INTR, + PMIC_TYPE_C_CC_ENT_UNATTACH_SRC_INTR, + PMIC_TYPE_C_CC_ENT_UNATTACH_SNK_INTR, + PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_SRC_INTR, + PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_SNK_INTR, + PMIC_TYPE_C_CC_ENT_TRY_SRC_INTR, + PMIC_TYPE_C_CC_ENT_TRY_WAIT_SNK_INTR, + PMIC_TYPE_C_CC_ENT_UNATTACH_ACC_INTR, + PMIC_TYPE_C_CC_ENT_ATTACH_WAIT_ACC_INTR, + PMIC_TYPE_C_CC_ENT_SNK_PWR_IDLE_INTR, + PMIC_TYPE_C_CC_ENT_SNK_PWR_DEFAULT_INTR, + PMIC_TYPE_C_CC_ENT_SNK_PWR_15_INTR, + PMIC_TYPE_C_CC_ENT_SNK_PWR_30_INTR, + PMIC_TYPE_C_CC_ENT_SNK_PWR_REDETECT_INTR, + PMIC_RO_TYPE_C_CC_ST, + PMIC_RO_TYPE_C_ROUTED_CC, + PMIC_RO_TYPE_C_CC_SNK_PWR_ST, + PMIC_RO_TYPE_C_CC_PWR_ROLE, + PMIC_RO_TYPE_C_DRIVE_VCONN_CAPABLE, + PMIC_RO_TYPE_C_AD_CC_CMP_OUT, + PMIC_RO_AD_CC_VUSB33_RDY, + PMIC_REG_TYPE_C_PHY_RG_CC1_RPDE, + PMIC_REG_TYPE_C_PHY_RG_CC1_RP15, + PMIC_REG_TYPE_C_PHY_RG_CC1_RP3, + PMIC_REG_TYPE_C_PHY_RG_CC1_RD, + PMIC_REG_TYPE_C_PHY_RG_CC2_RPDE, + PMIC_REG_TYPE_C_PHY_RG_CC2_RP15, + PMIC_REG_TYPE_C_PHY_RG_CC2_RP3, + PMIC_REG_TYPE_C_PHY_RG_CC2_RD, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_RCC1, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_RCC2, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_LEV_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SW_SEL, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_BIAS_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_LPF_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_ADCSW_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SASW_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_SACLK, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_IN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_CAL, + PMIC_REG_TYPE_C_SW_FORCE_MODE_EN_DA_CC_DAC_GAIN_CAL, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RPCC1_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RDCC1_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RACC1_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RPCC2_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RDCC2_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_RACC2_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_LEV_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SW_SEL, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_BIAS_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_LPF_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_ADCSW_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SASW_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_EN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_SACLK, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_IN, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_CAL, + PMIC_REG_TYPE_C_SW_FORCE_MODE_DA_CC_DAC_GAIN_CAL, + PMIC_TYPE_C_DAC_CAL_START, + PMIC_REG_TYPE_C_DAC_CAL_STAGE, + PMIC_RO_TYPE_C_DAC_OK, + PMIC_RO_TYPE_C_DAC_FAIL, + PMIC_RO_DA_CC_DAC_CAL, + PMIC_RO_DA_CC_DAC_GAIN_CAL, + PMIC_REG_TYPE_C_DBG_PORT_SEL_0, + PMIC_REG_TYPE_C_DBG_PORT_SEL_1, + PMIC_REG_TYPE_C_DBG_MOD_SEL, + PMIC_RO_TYPE_C_DBG_OUT_READ_0, + PMIC_RO_TYPE_C_DBG_OUT_READ_1, + PMIC_HWCID, + PMIC_SWCID, + PMIC_RG_SRCLKEN_IN0_EN, + PMIC_RG_SRCLKEN_IN1_EN, + PMIC_RG_OSC_SEL, + PMIC_RG_SRCLKEN_IN2_EN, + PMIC_RG_SRCLKEN_IN0_HW_MODE, + PMIC_RG_SRCLKEN_IN1_HW_MODE, + PMIC_RG_OSC_SEL_HW_MODE, + PMIC_RG_SRCLKEN_IN_SYNC_EN, + PMIC_RG_OSC_EN_AUTO_OFF, + PMIC_TEST_OUT, + PMIC_RG_MON_FLAG_SEL, + PMIC_RG_MON_GRP_SEL, + PMIC_RG_NANDTREE_MODE, + PMIC_RG_TEST_AUXADC, + PMIC_RG_EFUSE_MODE, + PMIC_RG_TEST_STRUP, + PMIC_TESTMODE_SW, + PMIC_EN_STATUS_VDRAM, + PMIC_EN_STATUS_VSRAM_PROC, + PMIC_EN_STATUS_VAUD28, + PMIC_EN_STATUS_VAUX18, + PMIC_EN_STATUS_VCAMD, + PMIC_EN_STATUS_VLDO28, + PMIC_EN_STATUS_VCAMIO, + PMIC_EN_STATUS_VCAMA, + PMIC_EN_STATUS_VCN18, + PMIC_EN_STATUS_VCN28, + PMIC_EN_STATUS_VCN33, + PMIC_EN_STATUS_VRF12, + PMIC_EN_STATUS_VRF18, + PMIC_EN_STATUS_VXO22, + PMIC_EN_STATUS_VTCXO24, + PMIC_EN_STATUS_VTCXO28, + PMIC_EN_STATUS_VS1, + PMIC_EN_STATUS_VCORE, + PMIC_EN_STATUS_VPROC, + PMIC_EN_STATUS_VPA, + PMIC_EN_STATUS_VRTC, + PMIC_EN_STATUS_TREF, + PMIC_EN_STATUS_VIBR, + PMIC_EN_STATUS_VIO18, + PMIC_EN_STATUS_VEMC33, + PMIC_EN_STATUS_VUSB33, + PMIC_EN_STATUS_VMCH, + PMIC_EN_STATUS_VMC, + PMIC_EN_STATUS_VIO28, + PMIC_EN_STATUS_VSIM2, + PMIC_EN_STATUS_VSIM1, + PMIC_OC_STATUS_VDRAM, + PMIC_OC_STATUS_VSRAM_PROC, + PMIC_OC_STATUS_VAUD28, + PMIC_OC_STATUS_VAUX18, + PMIC_OC_STATUS_VCAMD, + PMIC_OC_STATUS_VLDO28, + PMIC_OC_STATUS_VCAMIO, + PMIC_OC_STATUS_VCAMA, + PMIC_OC_STATUS_VCN18, + PMIC_OC_STATUS_VCN28, + PMIC_OC_STATUS_VCN33, + PMIC_OC_STATUS_VRF12, + PMIC_OC_STATUS_VRF18, + PMIC_OC_STATUS_VXO22, + PMIC_OC_STATUS_VTCXO24, + PMIC_OC_STATUS_VTCXO28, + PMIC_OC_STATUS_VS1, + PMIC_OC_STATUS_VCORE, + PMIC_OC_STATUS_VPROC, + PMIC_OC_STATUS_VPA, + PMIC_OC_STATUS_TREF, + PMIC_OC_STATUS_VIBR, + PMIC_OC_STATUS_VIO18, + PMIC_OC_STATUS_VEMC33, + PMIC_OC_STATUS_VUSB33, + PMIC_OC_STATUS_VMCH, + PMIC_OC_STATUS_VMC, + PMIC_OC_STATUS_VIO28, + PMIC_OC_STATUS_VSIM2, + PMIC_OC_STATUS_VSIM1, + PMIC_VCORE2_PG_DEB, + PMIC_VS1_PG_DEB, + PMIC_VCORE_PG_DEB, + PMIC_VPROC_PG_DEB, + PMIC_VIO18_PG_DEB, + PMIC_VEMC33_PG_DEB, + PMIC_VUSB33_PG_DEB, + PMIC_VMCH_PG_DEB, + PMIC_VMC_PG_DEB, + PMIC_VIO28_PG_DEB, + PMIC_VDRAM_PG_DEB, + PMIC_VSRAM_PROC_PG_DEB, + PMIC_VAUD28_PG_DEB, + PMIC_VAUX18_PG_DEB, + PMIC_VXO22_PG_DEB, + PMIC_VTCXO24_PG_DEB, + PMIC_STRUP_VMCH_PG_STATUS_GATED, + PMIC_STRUP_VMC_PG_STATUS_GATED, + PMIC_STRUP_VXO22_PG_STATUS_GATED, + PMIC_STRUP_VTCXO24_PG_STATUS_GATED, + PMIC_STRUP_VUSB33_PG_STATUS_GATED, + PMIC_STRUP_VSRAM_PROC_PG_STATUS_GATED, + PMIC_STRUP_VPROC_PG_STATUS_GATED, + PMIC_STRUP_VDRAM_PG_STATUS_GATED, + PMIC_STRUP_VAUD28_PG_STATUS_GATED, + PMIC_STRUP_VIO28_PG_STATUS_GATED, + PMIC_STRUP_VEMC33_PG_STATUS_GATED, + PMIC_STRUP_VIO18_PG_STATUS_GATED, + PMIC_STRUP_VS1_PG_STATUS_GATED, + PMIC_STRUP_VCORE_PG_STATUS_GATED, + PMIC_STRUP_VAUX18_PG_STATUS_GATED, + PMIC_STRUP_VCORE2_PG_STATUS_GATED, + PMIC_PMU_THERMAL_DEB, + PMIC_STRUP_THERMAL_STATUS, + PMIC_PMU_TEST_MODE_SCAN, + PMIC_PWRKEY_DEB, + PMIC_HOMEKEY_DEB, + PMIC_RTC_XTAL_DET_DONE, + PMIC_XOSC32_ENB_DET, + PMIC_RTC_XTAL_DET_RSV, + PMIC_RG_PMU_TDSEL, + PMIC_RG_SPI_TDSEL, + PMIC_RG_AUD_TDSEL, + PMIC_RG_E32CAL_TDSEL, + PMIC_RG_PMU_RDSEL, + PMIC_RG_SPI_RDSEL, + PMIC_RG_AUD_RDSEL, + PMIC_RG_E32CAL_RDSEL, + PMIC_RG_SMT_WDTRSTB_IN, + PMIC_RG_SMT_HOMEKEY, + PMIC_RG_SMT_SRCLKEN_IN0, + PMIC_RG_SMT_SRCLKEN_IN1, + PMIC_RG_SMT_RTC_32K1V8_0, + PMIC_RG_SMT_RTC_32K1V8_1, + PMIC_RG_SMT_SPI_CLK, + PMIC_RG_SMT_SPI_CSN, + PMIC_RG_SMT_SPI_MOSI, + PMIC_RG_SMT_SPI_MISO, + PMIC_RG_SMT_AUD_CLK, + PMIC_RG_SMT_AUD_DAT_MOSI, + PMIC_RG_SMT_AUD_DAT_MISO, + PMIC_RG_SMT_ANC_DAT_MOSI, + PMIC_RG_SMT_VOW_CLK_MISO, + PMIC_RG_SMT_ENBB, + PMIC_RG_SMT_XOSC_EN, + PMIC_RG_OCTL_SRCLKEN_IN0, + PMIC_RG_OCTL_SRCLKEN_IN1, + PMIC_RG_OCTL_RTC_32K1V8_0, + PMIC_RG_OCTL_RTC_32K1V8_1, + PMIC_RG_OCTL_SPI_CLK, + PMIC_RG_OCTL_SPI_CSN, + PMIC_RG_OCTL_SPI_MOSI, + PMIC_RG_OCTL_SPI_MISO, + PMIC_RG_OCTL_AUD_DAT_MOSI, + PMIC_RG_OCTL_AUD_DAT_MISO, + PMIC_RG_OCTL_AUD_CLK, + PMIC_RG_OCTL_ANC_DAT_MOSI, + PMIC_RG_OCTL_HOMEKEY, + PMIC_RG_OCTL_ENBB, + PMIC_RG_OCTL_XOSC_EN, + PMIC_RG_OCTL_VOW_CLK_MISO, + PMIC_TOP_STATUS, + PMIC_TOP_STATUS_SET, + PMIC_TOP_STATUS_CLR, + PMIC_CLK_RSV_CON0_RSV, + PMIC_RG_DCXO_PWRKEY_RSTB_SEL, + PMIC_CLK_SRCVOLTEN_SW, + PMIC_CLK_BUCK_OSC_SEL_SW, + PMIC_CLK_VOWEN_SW, + PMIC_CLK_SRCVOLTEN_MODE, + PMIC_CLK_BUCK_OSC_SEL_MODE, + PMIC_CLK_VOWEN_MODE, + PMIC_RG_TOP_CKSEL_CON2_RSV, + PMIC_CLK_BUCK_CON0_RSV, + PMIC_CLK_BUCK_CON0_SET, + PMIC_CLK_BUCK_CON0_CLR, + PMIC_CLK_BUCK_VCORE_OSC_SEL_SW, + PMIC_CLK_BUCK_VCORE2_OSC_SEL_SW, + PMIC_CLK_BUCK_VPROC_OSC_SEL_SW, + PMIC_CLK_BUCK_VPA_OSC_SEL_SW, + PMIC_CLK_BUCK_VS1_OSC_SEL_SW, + PMIC_CLK_LDO_VSRAM_PROC_OSC_SEL_SW, + PMIC_CLK_BUCK_VCORE_OSC_SEL_MODE, + PMIC_CLK_BUCK_VCORE2_OSC_SEL_MODE, + PMIC_CLK_BUCK_VPROC_OSC_SEL_MODE, + PMIC_CLK_BUCK_VPA_OSC_SEL_MODE, + PMIC_CLK_BUCK_VS1_OSC_SEL_MODE, + PMIC_CLK_LDO_VSRAM_PROC_OSC_SEL_MODE, + PMIC_CLK_BUCK_CON1_RSV, + PMIC_CLK_BUCK_CON1_SET, + PMIC_CLK_BUCK_CON1_CLR, + PMIC_RG_CLKSQ_EN_AUD, + PMIC_RG_CLKSQ_EN_FQR, + PMIC_RG_CLKSQ_EN_AUX_AP, + PMIC_RG_CLKSQ_EN_AUX_MD, + PMIC_RG_CLKSQ_EN_AUX_GPS, + PMIC_RG_CLKSQ_EN_AUX_RSV, + PMIC_RG_CLKSQ_EN_AUX_AP_MODE, + PMIC_RG_CLKSQ_EN_AUX_MD_MODE, + PMIC_RG_CLKSQ_IN_SEL_VA18, + PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL, + PMIC_TOP_CLKSQ_RSV, + PMIC_DA_CLKSQ_EN_VA28, + PMIC_TOP_CLKSQ_SET, + PMIC_TOP_CLKSQ_CLR, + PMIC_RG_CLKSQ_RTC_EN, + PMIC_RG_CLKSQ_RTC_EN_HW_MODE, + PMIC_TOP_CLKSQ_RTC_RSV0, + PMIC_RG_ENBB_SEL, + PMIC_RG_XOSC_EN_SEL, + PMIC_TOP_CLKSQ_RTC_RSV1, + PMIC_DA_CLKSQ_EN_VDIG18, + PMIC_TOP_CLKSQ_RTC_SET, + PMIC_TOP_CLKSQ_RTC_CLR, + PMIC_OSC_75K_TRIM, + PMIC_RG_OSC_75K_TRIM_EN, + PMIC_RG_OSC_75K_TRIM_RATE, + PMIC_DA_OSC_75K_TRIM, + PMIC_CLK_PMU75K_CK_TST_DIS, + PMIC_CLK_SMPS_CK_TST_DIS, + PMIC_CLK_AUD26M_CK_TST_DIS, + PMIC_CLK_VOW12M_CK_TST_DIS, + PMIC_CLK_RTC32K_CK_TST_DIS, + PMIC_CLK_RTC26M_CK_TST_DIS, + PMIC_CLK_FG_CK_TST_DIS, + PMIC_CLK_SPK_CK_TST_DIS, + PMIC_CLK_CKROOTTST_CON0_RSV, + PMIC_CLK_BUCK_ANA_AUTO_OFF_DIS, + PMIC_CLK_PMU75K_CK_TSTSEL, + PMIC_CLK_SMPS_CK_TSTSEL, + PMIC_CLK_AUD26M_CK_TSTSEL, + PMIC_CLK_VOW12M_CK_TSTSEL, + PMIC_CLK_RTC32K_CK_TSTSEL, + PMIC_CLK_RTC26M_CK_TSTSEL, + PMIC_CLK_FG_CK_TSTSEL, + PMIC_CLK_SPK_CK_TSTSEL, + PMIC_CLK_CKROOTTST_CON1_RSV, + PMIC_CLK_RTC32K_1V8_0_O_PDN, + PMIC_CLK_RTC32K_1V8_1_O_PDN, + PMIC_CLK_RTC_2SEC_OFF_DET_PDN, + PMIC_CLK_PDN_CON0_RSV, + PMIC_CLK_PDN_CON0_SET, + PMIC_CLK_PDN_CON0_CLR, + PMIC_CLK_ZCD13M_CK_PDN, + PMIC_CLK_SMPS_CK_DIV_PDN, + PMIC_CLK_BUCK_ANA_CK_PDN, + PMIC_CLK_PDN_CON1_RSV, + PMIC_CLK_PDN_CON1_SET, + PMIC_CLK_PDN_CON1_CLR, + PMIC_CLK_OSC_SEL_HW_SRC_SEL, + PMIC_CLK_SRCLKEN_SRC_SEL, + PMIC_CLK_SEL_CON0_RSV, + PMIC_CLK_SEL_CON0_SET, + PMIC_CLK_SEL_CON0_CLR, + PMIC_CLK_AUXADC_CK_CKSEL_HWEN, + PMIC_CLK_AUXADC_CK_CKSEL, + PMIC_CLK_75K_32K_SEL, + PMIC_CLK_SEL_CON1_RSV, + PMIC_CLK_SEL_CON1_SET, + PMIC_CLK_SEL_CON1_CLR, + PMIC_CLK_G_SMPS_PD_CK_PDN, + PMIC_CLK_G_SMPS_AUD_CK_PDN, + PMIC_CLK_G_SMPS_TEST_CK_PDN, + PMIC_CLK_ACCDET_CK_PDN, + PMIC_CLK_AUDIF_CK_PDN, + PMIC_CLK_AUD_CK_PDN, + PMIC_CLK_AUDNCP_CK_PDN, + PMIC_CLK_AUXADC_1M_CK_PDN, + PMIC_CLK_AUXADC_SMPS_CK_PDN, + PMIC_CLK_AUXADC_RNG_CK_PDN, + PMIC_CLK_AUXADC_26M_CK_PDN, + PMIC_CLK_AUXADC_CK_PDN, + PMIC_CLK_DRV_ISINK0_CK_PDN, + PMIC_CLK_DRV_ISINK1_CK_PDN, + PMIC_CLK_DRV_ISINK2_CK_PDN, + PMIC_CLK_DRV_ISINK3_CK_PDN, + PMIC_CLK_CKPDN_CON0_SET, + PMIC_CLK_CKPDN_CON0_CLR, + PMIC_CLK_DRV_CHRIND_CK_PDN, + PMIC_CLK_DRV_32K_CK_PDN, + PMIC_CLK_BUCK_1M_CK_PDN, + PMIC_CLK_BUCK_32K_CK_PDN, + PMIC_CLK_BUCK_9M_CK_PDN, + PMIC_CLK_PWMOC_6M_CK_PDN, + PMIC_CLK_BUCK_VPROC_9M_CK_PDN, + PMIC_CLK_BUCK_VCORE_9M_CK_PDN, + PMIC_CLK_BUCK_VCORE2_9M_CK_PDN, + PMIC_CLK_BUCK_VPA_9M_CK_PDN, + PMIC_CLK_BUCK_VS1_9M_CK_PDN, + PMIC_CLK_FQMTR_CK_PDN, + PMIC_CLK_FQMTR_32K_CK_PDN, + PMIC_CLK_INTRP_CK_PDN, + PMIC_CLK_INTRP_PRE_OC_CK_PDN, + PMIC_CLK_STB_1M_CK_PDN, + PMIC_CLK_CKPDN_CON1_SET, + PMIC_CLK_CKPDN_CON1_CLR, + PMIC_CLK_LDO_CALI_75K_CK_PDN, + PMIC_CLK_LDO_VSRAM_PROC_9M_CK_PDN, + PMIC_CLK_RTC_26M_CK_PDN, + PMIC_CLK_RTC_32K_CK_PDN, + PMIC_CLK_RTC_MCLK_PDN, + PMIC_CLK_RTC_75K_CK_PDN, + PMIC_CLK_RTCDET_CK_PDN, + PMIC_CLK_RTC_EOSC32_CK_PDN, + PMIC_CLK_EOSC_CALI_TEST_CK_PDN, + PMIC_CLK_FGADC_ANA_CK_PDN, + PMIC_CLK_FGADC_DIG_CK_PDN, + PMIC_CLK_FGADC_FT_CK_PDN, + PMIC_CLK_TRIM_75K_CK_PDN, + PMIC_CLK_EFUSE_CK_PDN, + PMIC_CLK_STRUP_75K_CK_PDN, + PMIC_CLK_STRUP_32K_CK_PDN, + PMIC_CLK_CKPDN_CON2_SET, + PMIC_CLK_CKPDN_CON2_CLR, + PMIC_CLK_PCHR_32K_CK_PDN, + PMIC_CLK_PCHR_TEST_CK_PDN, + PMIC_CLK_SPI_CK_PDN, + PMIC_CLK_BGR_TEST_CK_PDN, + PMIC_CLK_TYPE_C_CC_CK_PDN, + PMIC_CLK_TYPE_C_CSR_CK_PDN, + PMIC_CLK_SPK_CK_PDN, + PMIC_CLK_SPK_PWM_CK_PDN, + PMIC_CLK_RSV_PDN, + PMIC_CLK_CKPDN_CON3_SET, + PMIC_CLK_CKPDN_CON3_CLR, + PMIC_CLK_G_SMPS_PD_CK_PDN_HWEN, + PMIC_CLK_G_SMPS_AUD_CK_PDN_HWEN, + PMIC_CLK_AUXADC_SMPS_CK_PDN_HWEN, + PMIC_CLK_AUXADC_26M_CK_PDN_HWEN, + PMIC_CLK_AUXADC_CK_PDN_HWEN, + PMIC_CLK_BUCK_1M_CK_PDN_HWEN, + PMIC_CLK_BUCK_VPROC_9M_CK_PDN_HWEN, + PMIC_CLK_BUCK_VCORE_9M_CK_PDN_HWEN, + PMIC_CLK_BUCK_VCORE2_9M_CK_PDN_HWEN, + PMIC_CLK_BUCK_VPA_9M_CK_PDN_HWEN, + PMIC_CLK_BUCK_VS1_9M_CK_PDN_HWEN, + PMIC_CLK_STB_1M_CK_PDN_HWEN, + PMIC_CLK_LDO_VSRAM_PROC_9M_CK_PDN_HWEN, + PMIC_CLK_RTC_26M_CK_PDN_HWEN, + PMIC_CLK_RSV_PDN_HWEN, + PMIC_CLK_CKPDN_HWEN_CON0_SET, + PMIC_CLK_CKPDN_HWEN_CON0_CLR, + PMIC_CLK_AUDIF_CK_CKSEL, + PMIC_CLK_AUD_CK_CKSEL, + PMIC_CLK_FQMTR_CK_CKSEL, + PMIC_CLK_FGADC_ANA_CK_CKSEL, + PMIC_CLK_PCHR_TEST_CK_CKSEL, + PMIC_CLK_BGR_TEST_CK_CKSEL, + PMIC_CLK_EFUSE_CK_PDN_HWEN, + PMIC_CLK_RSV_CKSEL, + PMIC_CLK_CKSEL_CON0_SET, + PMIC_CLK_CKSEL_CON0_CLR, + PMIC_CLK_AUXADC_SMPS_CK_DIVSEL, + PMIC_CLK_AUXADC_26M_CK_DIVSEL, + PMIC_CLK_BUCK_9M_CK_DIVSEL, + PMIC_CLK_REG_CK_DIVSEL, + PMIC_CLK_SPK_CK_DIVSEL, + PMIC_CLK_SPK_PWM_CK_DIVSEL, + PMIC_CLK_RSV_DIVSEL, + PMIC_CLK_CKDIVSEL_CON0_SET, + PMIC_CLK_CKDIVSEL_CON0_CLR, + PMIC_CLK_AUDIF_CK_TSTSEL, + PMIC_CLK_AUD_CK_TSTSEL, + PMIC_CLK_AUXADC_SMPS_CK_TSTSEL, + PMIC_CLK_AUXADC_26M_CK_TSTSEL, + PMIC_CLK_AUXADC_CK_TSTSEL, + PMIC_CLK_DRV_CHRIND_CK_TSTSEL, + PMIC_CLK_FQMTR_CK_TSTSEL, + PMIC_CLK_RTCDET_CK_TSTSEL, + PMIC_CLK_RTC_EOSC32_CK_TSTSEL, + PMIC_CLK_EOSC_CALI_TEST_CK_TSTSEL, + PMIC_CLK_FGADC_ANA_CK_TSTSEL, + PMIC_CLK_PCHR_TEST_CK_TSTSEL, + PMIC_CLK_BGR_TEST_CK_TSTSEL, + PMIC_CLK_RSV_TSTSEL, + PMIC_RG_EFUSE_MAN_RST, + PMIC_RG_AUXADC_RST, + PMIC_RG_AUXADC_REG_RST, + PMIC_RG_AUDIO_RST, + PMIC_RG_ACCDET_RST, + PMIC_RG_BIF_RST, + PMIC_RG_DRIVER_RST, + PMIC_RG_FGADC_RST, + PMIC_RG_FQMTR_RST, + PMIC_RG_RTC_RST, + PMIC_RG_TYPE_C_CC_RST, + PMIC_RG_CHRWDT_RST, + PMIC_RG_ZCD_RST, + PMIC_RG_AUDNCP_RST, + PMIC_RG_CLK_TRIM_RST, + PMIC_RG_BUCK_SRCLKEN_RST, + PMIC_TOP_RST_CON0_SET, + PMIC_TOP_RST_CON0_CLR, + PMIC_RG_STRUP_LONG_PRESS_RST, + PMIC_RG_BUCK_PROT_PMPP_RST, + PMIC_RG_SPK_RST, + PMIC_TOP_RST_CON1_RSV, + PMIC_TOP_RST_CON1_SET, + PMIC_TOP_RST_CON1_CLR, + PMIC_RG_CHR_LDO_DET_MODE, + PMIC_RG_CHR_LDO_DET_SW, + PMIC_RG_CHRWDT_FLAG_MODE, + PMIC_RG_CHRWDT_FLAG_SW, + PMIC_TOP_RST_CON2_RSV, + PMIC_RG_WDTRSTB_EN, + PMIC_RG_WDTRSTB_MODE, + PMIC_WDTRSTB_STATUS, + PMIC_WDTRSTB_STATUS_CLR, + PMIC_RG_WDTRSTB_FB_EN, + PMIC_RG_WDTRSTB_DEB, + PMIC_RG_HOMEKEY_RST_EN, + PMIC_RG_PWRKEY_RST_EN, + PMIC_RG_PWRRST_TMR_DIS, + PMIC_RG_PWRKEY_RST_TD, + PMIC_TOP_RST_MISC_RSV, + PMIC_TOP_RST_MISC_SET, + PMIC_TOP_RST_MISC_CLR, + PMIC_VPWRIN_RSTB_STATUS, + PMIC_DDLO_RSTB_STATUS, + PMIC_UVLO_RSTB_STATUS, + PMIC_RTC_DDLO_RSTB_STATUS, + PMIC_CHRWDT_REG_RSTB_STATUS, + PMIC_CHRDET_REG_RSTB_STATUS, + PMIC_TOP_RST_STATUS_RSV, + PMIC_TOP_RST_STATUS_SET, + PMIC_TOP_RST_STATUS_CLR, + PMIC_TOP_RST_RSV_CON0, + PMIC_TOP_RST_RSV_CON1, + PMIC_RG_INT_EN_PWRKEY, + PMIC_RG_INT_EN_HOMEKEY, + PMIC_RG_INT_EN_PWRKEY_R, + PMIC_RG_INT_EN_HOMEKEY_R, + PMIC_RG_INT_EN_THR_H, + PMIC_RG_INT_EN_THR_L, + PMIC_RG_INT_EN_BAT_H, + PMIC_RG_INT_EN_BAT_L, + PMIC_RG_INT_EN_RTC, + PMIC_RG_INT_EN_AUDIO, + PMIC_RG_INT_EN_ACCDET, + PMIC_RG_INT_EN_ACCDET_EINT, + PMIC_RG_INT_EN_ACCDET_NEGV, + PMIC_RG_INT_EN_NI_LBAT_INT, + PMIC_INT_CON0_SET, + PMIC_INT_CON0_CLR, + PMIC_RG_INT_EN_VCORE_OC, + PMIC_RG_INT_EN_VPROC_OC, + PMIC_RG_INT_EN_VS1_OC, + PMIC_RG_INT_EN_VPA_OC, + PMIC_RG_INT_EN_SPKL_D, + PMIC_RG_INT_EN_SPKL_AB, + PMIC_RG_INT_EN_LDO_OC, + PMIC_INT_CON1_SET, + PMIC_INT_CON1_CLR, + PMIC_RG_INT_EN_TYPE_C_L_MIN, + PMIC_RG_INT_EN_TYPE_C_L_MAX, + PMIC_RG_INT_EN_TYPE_C_H_MIN, + PMIC_RG_INT_EN_TYPE_C_H_MAX, + PMIC_RG_INT_EN_AUXADC_IMP, + PMIC_RG_INT_EN_NAG_C_DLTV, + PMIC_RG_INT_EN_TYPE_C_CC_IRQ, + PMIC_RG_INT_EN_CHRDET_EDGE, + PMIC_RG_INT_EN_OV, + PMIC_RG_INT_EN_BVALID_DET, + PMIC_RG_INT_EN_RGS_BATON_HV, + PMIC_RG_INT_EN_VBATON_UNDET, + PMIC_RG_INT_EN_WATCHDOG, + PMIC_RG_INT_EN_PCHR_CM_VDEC, + PMIC_RG_INT_EN_CHRDET, + PMIC_RG_INT_EN_PCHR_CM_VINC, + PMIC_INT_CON2_SET, + PMIC_INT_CON2_CLR, + PMIC_RG_INT_EN_FG_BAT_H, + PMIC_RG_INT_EN_FG_BAT_L, + PMIC_RG_INT_EN_FG_CUR_H, + PMIC_RG_INT_EN_FG_CUR_L, + PMIC_RG_INT_EN_FG_ZCV, + PMIC_INT_CON3_SET, + PMIC_INT_CON3_CLR, + PMIC_POLARITY, + PMIC_RG_HOMEKEY_INT_SEL, + PMIC_RG_PWRKEY_INT_SEL, + PMIC_RG_CHRDET_INT_SEL, + PMIC_RG_PCHR_CM_VINC_POLARITY_RSV, + PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV, + PMIC_INT_MISC_CON_SET, + PMIC_INT_MISC_CON_CLR, + PMIC_RG_INT_STATUS_PWRKEY, + PMIC_RG_INT_STATUS_HOMEKEY, + PMIC_RG_INT_STATUS_PWRKEY_R, + PMIC_RG_INT_STATUS_HOMEKEY_R, + PMIC_RG_INT_STATUS_THR_H, + PMIC_RG_INT_STATUS_THR_L, + PMIC_RG_INT_STATUS_BAT_H, + PMIC_RG_INT_STATUS_BAT_L, + PMIC_RG_INT_STATUS_RTC, + PMIC_RG_INT_STATUS_AUDIO, + PMIC_RG_INT_STATUS_ACCDET, + PMIC_RG_INT_STATUS_ACCDET_EINT, + PMIC_RG_INT_STATUS_ACCDET_NEGV, + PMIC_RG_INT_STATUS_NI_LBAT_INT, + PMIC_RG_INT_STATUS_VCORE_OC, + PMIC_RG_INT_STATUS_VPROC_OC, + PMIC_RG_INT_STATUS_VS1_OC, + PMIC_RG_INT_STATUS_VPA_OC, + PMIC_RG_INT_STATUS_SPKL_D, + PMIC_RG_INT_STATUS_SPKL_AB, + PMIC_RG_INT_STATUS_LDO_OC, + PMIC_RG_INT_STATUS_TYPE_C_L_MIN, + PMIC_RG_INT_STATUS_TYPE_C_L_MAX, + PMIC_RG_INT_STATUS_TYPE_C_H_MIN, + PMIC_RG_INT_STATUS_TYPE_C_H_MAX, + PMIC_RG_INT_STATUS_AUXADC_IMP, + PMIC_RG_INT_STATUS_NAG_C_DLTV, + PMIC_RG_INT_STATUS_TYPE_C_CC_IRQ, + PMIC_RG_INT_STATUS_CHRDET_EDGE, + PMIC_RG_INT_STATUS_OV, + PMIC_RG_INT_STATUS_BVALID_DET, + PMIC_RG_INT_STATUS_RGS_BATON_HV, + PMIC_RG_INT_STATUS_VBATON_UNDET, + PMIC_RG_INT_STATUS_WATCHDOG, + PMIC_RG_INT_STATUS_PCHR_CM_VDEC, + PMIC_RG_INT_STATUS_CHRDET, + PMIC_RG_INT_STATUS_PCHR_CM_VINC, + PMIC_RG_INT_STATUS_FG_BAT_H, + PMIC_RG_INT_STATUS_FG_BAT_L, + PMIC_RG_INT_STATUS_FG_CUR_H, + PMIC_RG_INT_STATUS_FG_CUR_L, + PMIC_RG_INT_STATUS_FG_ZCV, + PMIC_OC_GEAR_LDO, + PMIC_SPK_EN_L, + PMIC_SPKMODE_L, + PMIC_SPK_TRIM_EN_L, + PMIC_SPK_OC_SHDN_DL, + PMIC_SPK_THER_SHDN_L_EN, + PMIC_SPK_OUT_STAGE_SEL, + PMIC_RG_SPK_GAINL, + PMIC_DA_SPK_OFFSET_L, + PMIC_DA_SPK_LEAD_DGLH_L, + PMIC_AD_NI_SPK_LEAD_L, + PMIC_SPK_OFFSET_L_OV, + PMIC_SPK_OFFSET_L_SW, + PMIC_SPK_LEAD_L_SW, + PMIC_SPK_OFFSET_L_MODE, + PMIC_SPK_TRIM_DONE_L, + PMIC_RG_SPK_INTG_RST_L, + PMIC_RG_SPK_FORCE_EN_L, + PMIC_RG_SPK_SLEW_L, + PMIC_RG_SPKAB_OBIAS_L, + PMIC_RG_SPKRCV_EN_L, + PMIC_RG_SPK_DRC_EN_L, + PMIC_RG_SPK_TEST_EN_L, + PMIC_RG_SPKAB_OC_EN_L, + PMIC_RG_SPK_OC_EN_L, + PMIC_SPK_EN_R, + PMIC_SPKMODE_R, + PMIC_SPK_TRIM_EN_R, + PMIC_SPK_OC_SHDN_DR, + PMIC_SPK_THER_SHDN_R_EN, + PMIC_RG_SPK_GAINR, + PMIC_DA_SPK_OFFSET_R, + PMIC_DA_SPK_LEAD_DGLH_R, + PMIC_NI_SPK_LEAD_R, + PMIC_SPK_OFFSET_R_OV, + PMIC_SPK_OFFSET_R_SW, + PMIC_SPK_LEAD_R_SW, + PMIC_SPK_OFFSET_R_MODE, + PMIC_SPK_TRIM_DONE_R, + PMIC_RG_SPK_INTG_RST_R, + PMIC_RG_SPK_FORCE_EN_R, + PMIC_RG_SPK_SLEW_R, + PMIC_RG_SPKAB_OBIAS_R, + PMIC_RG_SPKRCV_EN_R, + PMIC_RG_SPK_DRC_EN_R, + PMIC_RG_SPK_TEST_EN_R, + PMIC_RG_SPKAB_OC_EN_R, + PMIC_RG_SPK_OC_EN_R, + PMIC_RG_SPKPGA_GAINR, + PMIC_SPK_TRIM_WND, + PMIC_SPK_TRIM_THD, + PMIC_SPK_OC_WND, + PMIC_SPK_OC_THD, + PMIC_SPK_D_OC_R_DEG, + PMIC_SPK_AB_OC_R_DEG, + PMIC_SPK_D_OC_L_DEG, + PMIC_SPK_AB_OC_L_DEG, + PMIC_SPK_TD1, + PMIC_SPK_TD2, + PMIC_SPK_TD3, + PMIC_SPK_TRIM_DIV, + PMIC_RG_BTL_SET, + PMIC_RG_SPK_IBIAS_SEL, + PMIC_RG_SPK_CCODE, + PMIC_RG_SPK_EN_VIEW_VCM, + PMIC_RG_SPK_EN_VIEW_CLK, + PMIC_RG_SPK_VCM_SEL, + PMIC_RG_SPK_VCM_IBSEL, + PMIC_RG_SPK_FBRC_EN, + PMIC_RG_SPKAB_OVDRV, + PMIC_RG_SPK_OCTH_D, + PMIC_RG_SPKPGA_GAINL, + PMIC_SPK_RSV0, + PMIC_SPK_VCM_FAST_EN, + PMIC_SPK_TEST_MODE0, + PMIC_SPK_TEST_MODE1, + PMIC_SPK_TD_WAIT, + PMIC_SPK_TD_DONE, + PMIC_SPK_EN_MODE, + PMIC_SPK_VCM_FAST_SW, + PMIC_SPK_RST_R_SW, + PMIC_SPK_RST_L_SW, + PMIC_SPKMODE_R_SW, + PMIC_SPKMODE_L_SW, + PMIC_SPK_DEPOP_EN_R_SW, + PMIC_SPK_DEPOP_EN_L_SW, + PMIC_SPK_EN_R_SW, + PMIC_SPK_EN_L_SW, + PMIC_SPK_OUTSTG_EN_R_SW, + PMIC_SPK_OUTSTG_EN_L_SW, + PMIC_SPK_TRIM_EN_R_SW, + PMIC_SPK_TRIM_EN_L_SW, + PMIC_SPK_TRIM_STOP_R_SW, + PMIC_SPK_TRIM_STOP_L_SW, + PMIC_RG_SPK_ISENSE_TEST_EN, + PMIC_RG_SPK_ISENSE_REFSEL, + PMIC_RG_SPK_ISENSE_GAINSEL, + PMIC_RG_SPK_ISENSE_PDRESET, + PMIC_RG_SPK_ISENSE_EN, + PMIC_RG_SPK_RSV1, + PMIC_RG_SPK_RSV0, + PMIC_RG_SPK_ABD_VOLSEN_GAIN, + PMIC_RG_SPK_ABD_VOLSEN_EN, + PMIC_RG_SPK_ABD_CURSEN_SEL, + PMIC_RG_SPK_RSV2, + PMIC_RG_SPK_TRIM2, + PMIC_RG_SPK_TRIM1, + PMIC_RG_SPK_D_CURSEN_RSETSEL, + PMIC_RG_SPK_D_CURSEN_GAIN, + PMIC_RG_SPK_D_CURSEN_EN, + PMIC_RG_SPK_AB_CURSEN_RSETSEL, + PMIC_RG_SPK_AB_CURSEN_GAIN, + PMIC_RG_SPK_AB_CURSEN_EN, + PMIC_RG_SPKPGA_GAIN, + PMIC_RG_SPK_RSV, + PMIC_RG_ISENSE_PD_RESET, + PMIC_RG_AUDIVLPWRUP_VAUDP12, + PMIC_RG_AUDIVLSTARTUP_VAUDP12, + PMIC_RG_AUDIVLMUXSEL_VAUDP12, + PMIC_RG_AUDIVLMUTE_VAUDP12, + PMIC_FQMTR_TCKSEL, + PMIC_FQMTR_BUSY, + PMIC_FQMTR_DCXO26M_EN, + PMIC_FQMTR_EN, + PMIC_FQMTR_WINSET, + PMIC_FQMTR_DATA, + PMIC_RG_TRIM_EN, + PMIC_RG_TRIM_SEL, + PMIC_RG_ISINKS_RSV, + PMIC_RG_ISINK0_DOUBLE_EN, + PMIC_RG_ISINK1_DOUBLE_EN, + PMIC_RG_ISINK2_DOUBLE_EN, + PMIC_RG_ISINK3_DOUBLE_EN, + PMIC_ISINK_DIM0_FSEL, + PMIC_ISINK0_RSV1, + PMIC_ISINK0_RSV0, + PMIC_ISINK_DIM0_DUTY, + PMIC_ISINK_CH0_STEP, + PMIC_ISINK_BREATH0_TF2_SEL, + PMIC_ISINK_BREATH0_TF1_SEL, + PMIC_ISINK_BREATH0_TR2_SEL, + PMIC_ISINK_BREATH0_TR1_SEL, + PMIC_ISINK_BREATH0_TOFF_SEL, + PMIC_ISINK_BREATH0_TON_SEL, + PMIC_ISINK_DIM1_FSEL, + PMIC_ISINK1_RSV1, + PMIC_ISINK1_RSV0, + PMIC_ISINK_DIM1_DUTY, + PMIC_ISINK_CH1_STEP, + PMIC_ISINK_BREATH1_TF2_SEL, + PMIC_ISINK_BREATH1_TF1_SEL, + PMIC_ISINK_BREATH1_TR2_SEL, + PMIC_ISINK_BREATH1_TR1_SEL, + PMIC_ISINK_BREATH1_TOFF_SEL, + PMIC_ISINK_BREATH1_TON_SEL, + PMIC_AD_NI_ISINK3_STATUS, + PMIC_AD_NI_ISINK2_STATUS, + PMIC_AD_NI_ISINK1_STATUS, + PMIC_AD_NI_ISINK0_STATUS, + PMIC_ISINK_PHASE0_DLY_EN, + PMIC_ISINK_PHASE1_DLY_EN, + PMIC_ISINK_PHASE_DLY_TC, + PMIC_ISINK_CHOP0_SW, + PMIC_ISINK_CHOP1_SW, + PMIC_ISINK_SFSTR1_EN, + PMIC_ISINK_SFSTR1_TC, + PMIC_ISINK_SFSTR0_EN, + PMIC_ISINK_SFSTR0_TC, + PMIC_ISINK_CH0_EN, + PMIC_ISINK_CH1_EN, + PMIC_ISINK_CHOP0_EN, + PMIC_ISINK_CHOP1_EN, + PMIC_ISINK_CH0_BIAS_EN, + PMIC_ISINK_CH1_BIAS_EN, + PMIC_ISINK_RSV, + PMIC_ISINK_CH1_MODE, + PMIC_ISINK_CH0_MODE, + PMIC_DA_QI_ISINKS_CH3_STEP, + PMIC_DA_QI_ISINKS_CH2_STEP, + PMIC_DA_QI_ISINKS_CH1_STEP, + PMIC_DA_QI_ISINKS_CH0_STEP, + PMIC_ISINK2_RSV1, + PMIC_ISINK2_RSV0, + PMIC_ISINK_CH2_STEP, + PMIC_ISINK3_RSV1, + PMIC_ISINK3_RSV0, + PMIC_ISINK_CH3_STEP, + PMIC_ISINK_CHOP3_SW, + PMIC_ISINK_CHOP2_SW, + PMIC_ISINK_CH3_EN, + PMIC_ISINK_CH2_EN, + PMIC_ISINK_CHOP3_EN, + PMIC_ISINK_CHOP2_EN, + PMIC_ISINK_CH3_BIAS_EN, + PMIC_ISINK_CH2_BIAS_EN, + PMIC_CHRIND_DIM_FSEL, + PMIC_CHRIND_RSV1, + PMIC_CHRIND_RSV0, + PMIC_CHRIND_DIM_DUTY, + PMIC_CHRIND_STEP, + PMIC_CHRIND_BREATH_TF2_SEL, + PMIC_CHRIND_BREATH_TF1_SEL, + PMIC_CHRIND_BREATH_TR2_SEL, + PMIC_CHRIND_BREATH_TR1_SEL, + PMIC_CHRIND_BREATH_TOFF_SEL, + PMIC_CHRIND_BREATH_TON_SEL, + PMIC_CHRIND_SFSTR_EN, + PMIC_CHRIND_SFSTR_TC, + PMIC_CHRIND_EN_SEL, + PMIC_CHRIND_EN, + PMIC_CHRIND_CHOP_EN, + PMIC_CHRIND_MODE, + PMIC_CHRIND_CHOP_SW, + PMIC_CHRIND_BIAS_EN, + PMIC_RG_SLP_RW_EN, + PMIC_RG_SPI_RSV, + PMIC_DEW_DIO_EN, + PMIC_DEW_READ_TEST, + PMIC_DEW_WRITE_TEST, + PMIC_DEW_CRC_SWRST, + PMIC_DEW_CRC_EN, + PMIC_DEW_CRC_VAL, + PMIC_DEW_DBG_MON_SEL, + PMIC_DEW_CIPHER_KEY_SEL, + PMIC_DEW_CIPHER_IV_SEL, + PMIC_DEW_CIPHER_EN, + PMIC_DEW_CIPHER_RDY, + PMIC_DEW_CIPHER_MODE, + PMIC_DEW_CIPHER_SWRST, + PMIC_DEW_RDDMY_NO, + PMIC_INT_TYPE_CON0, + PMIC_INT_TYPE_CON0_SET, + PMIC_INT_TYPE_CON0_CLR, + PMIC_INT_TYPE_CON1, + PMIC_INT_TYPE_CON1_SET, + PMIC_INT_TYPE_CON1_CLR, + PMIC_INT_TYPE_CON2, + PMIC_INT_TYPE_CON2_SET, + PMIC_INT_TYPE_CON2_CLR, + PMIC_INT_TYPE_CON3, + PMIC_INT_TYPE_CON3_SET, + PMIC_INT_TYPE_CON3_CLR, + PMIC_CPU_INT_STA, + PMIC_MD32_INT_STA, + PMIC_BUCK_LDO_FT_TESTMODE_EN, + PMIC_EFUSE_VOSEL_LIMIT, + PMIC_EFUSE_OC_EN_SEL, + PMIC_EFUSE_OC_SDN_EN, + PMIC_BUCK_FOR_LDO_OSC_SEL, + PMIC_BUCK_ALL_CON0_RSV0, + PMIC_BUCK_BUCK_RSV, + PMIC_BUCK_VCORE_VOSEL_CTRL_PROT, + PMIC_BUCK_VCORE_VOSEL_CTRL_PROT_EN, + PMIC_BUCK_ALL_CON2_RSV0, + PMIC_BUCK_VSLEEP_SRC0, + PMIC_BUCK_VSLEEP_SRC1, + PMIC_BUCK_R2R_SRC0, + PMIC_BUCK_R2R_SRC1, + PMIC_BUCK_BUCK_OSC_SEL_SRC0, + PMIC_BUCK_SRCLKEN_DLY_SRC1, + PMIC_BUCK_VPA_VOSEL_DLC011, + PMIC_BUCK_VPA_VOSEL_DLC111, + PMIC_BUCK_VPA_DLC_MAP_EN, + PMIC_BUCK_VPA_VOSEL_DLC001, + PMIC_BUCK_VPA_DLC, + PMIC_DA_NI_VPA_DLC, + PMIC_BUCK_VSRAM_PROC_TRACK_SLEEP_CTRL, + PMIC_BUCK_VSRAM_PROC_TRACK_ON_CTRL, + PMIC_BUCK_VPROC_TRACK_ON_CTRL, + PMIC_BUCK_VSRAM_PROC_VOSEL_DELTA, + PMIC_BUCK_VSRAM_PROC_VOSEL_OFFSET, + PMIC_BUCK_VSRAM_PROC_VOSEL_ON_LB, + PMIC_BUCK_VSRAM_PROC_VOSEL_ON_HB, + PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_LB, + PMIC_AD_QI_VCORE_OC_STATUS, + PMIC_AD_QI_VPROC_OC_STATUS, + PMIC_AD_QI_VS1_OC_STATUS, + PMIC_AD_QI_VPA_OC_STATUS, + PMIC_BUCK_ANA_STATUS, + PMIC_AD_QI_VCORE_DIG_MON, + PMIC_AD_QI_VPROC_DIG_MON, + PMIC_AD_QI_VS1_DIG_MON, + PMIC_BUCK_VCORE_OC_STATUS, + PMIC_BUCK_VCORE2_OC_STATUS, + PMIC_BUCK_VPROC_OC_STATUS, + PMIC_BUCK_VS1_OC_STATUS, + PMIC_BUCK_VPA_OC_STATUS, + PMIC_BUCK_VCORE_OC_INT_EN, + PMIC_BUCK_VCORE2_OC_INT_EN, + PMIC_BUCK_VPROC_OC_INT_EN, + PMIC_BUCK_VS1_OC_INT_EN, + PMIC_BUCK_VPA_OC_INT_EN, + PMIC_BUCK_VCORE_EN_OC_SDN_SEL, + PMIC_BUCK_VCORE2_EN_OC_SDN_SEL, + PMIC_BUCK_VPROC_EN_OC_SDN_SEL, + PMIC_BUCK_VS1_EN_OC_SDN_SEL, + PMIC_BUCK_VPA_EN_OC_SDN_SEL, + PMIC_BUCK_VCORE_OC_FLAG_CLR, + PMIC_BUCK_VCORE2_OC_FLAG_CLR, + PMIC_BUCK_VPROC_OC_FLAG_CLR, + PMIC_BUCK_VS1_OC_FLAG_CLR, + PMIC_BUCK_VPA_OC_FLAG_CLR, + PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL, + PMIC_BUCK_VCORE2_OC_FLAG_CLR_SEL, + PMIC_BUCK_VPROC_OC_FLAG_CLR_SEL, + PMIC_BUCK_VS1_OC_FLAG_CLR_SEL, + PMIC_BUCK_VPA_OC_FLAG_CLR_SEL, + PMIC_BUCK_VCORE_OC_DEG_EN, + PMIC_BUCK_VCORE_OC_WND, + PMIC_BUCK_VCORE_OC_THD, + PMIC_BUCK_VCORE2_OC_DEG_EN, + PMIC_BUCK_VCORE2_OC_WND, + PMIC_BUCK_VCORE2_OC_THD, + PMIC_BUCK_VPROC_OC_DEG_EN, + PMIC_BUCK_VPROC_OC_WND, + PMIC_BUCK_VPROC_OC_THD, + PMIC_BUCK_VS1_OC_DEG_EN, + PMIC_BUCK_VS1_OC_WND, + PMIC_BUCK_VS1_OC_THD, + PMIC_BUCK_VPA_OC_DEG_EN, + PMIC_BUCK_VPA_OC_WND, + PMIC_BUCK_VPA_OC_THD, + PMIC_RG_SMPS_TESTMODE_B, + PMIC_RG_VSRAM_PROC_TRIMH, + PMIC_RG_VSRAM_PROC_TRIML, + PMIC_RG_VPROC_TRIMH, + PMIC_RG_VPROC_TRIML, + PMIC_RG_VCORE_TRIMH, + PMIC_RG_VCORE_TRIML, + PMIC_RG_VCORE2_TRIMH, + PMIC_RG_VCORE2_TRIML, + PMIC_RG_VS1_TRIMH, + PMIC_RG_VS1_TRIML, + PMIC_RG_VPA_TRIMH, + PMIC_RG_VPA_TRIML, + PMIC_RG_VPA_TRIM_REF, + PMIC_RG_VSRAM_PROC_VSLEEP, + PMIC_RG_VPROC_VSLEEP, + PMIC_RG_VCORE_VSLEEP, + PMIC_RG_VCORE2_VSLEEP, + PMIC_RG_VPA_BURSTH, + PMIC_RG_VPA_BURSTL, + PMIC_RG_DMY100MA_EN, + PMIC_RG_DMY100MA_SEL, + PMIC_RG_VSRAM_PROC_VSLEEP_VOLTAGE, + PMIC_RG_VPROC_VSLEEP_VOLTAGE, + PMIC_RG_VCORE_VSLEEP_VOLTAGE, + PMIC_RG_VCORE2_VSLEEP_VOLTAGE, + PMIC_RG_VPA_RZSEL, + PMIC_RG_VPA_CC, + PMIC_RG_VPA_CSR, + PMIC_RG_VPA_CSMIR, + PMIC_RG_VPA_CSL, + PMIC_RG_VPA_SLP, + PMIC_RG_VPA_ZX_OS_TRIM, + PMIC_RG_VPA_ZX_OS, + PMIC_RG_VPA_HZP, + PMIC_RG_VPA_BWEX_GAT, + PMIC_RG_VPA_MODESET, + PMIC_RG_VPA_SLEW, + PMIC_RG_VPA_SLEW_NMOS, + PMIC_RG_VPA_NDIS_EN, + PMIC_RG_VPA_MIN_ON, + PMIC_RG_VPA_VBAT_DEL, + PMIC_RG_VPA_RSV1, + PMIC_RG_VPA_RSV2, + PMIC_RGS_VPA_ZX_STATUS, + PMIC_RG_VCORE_MIN_OFF, + PMIC_RG_VCORE_VRF18_SSTART_EN, + PMIC_RG_VCORE_1P35UP_SEL_EN, + PMIC_RG_VCORE_RZSEL, + PMIC_RG_VCORE_CSR, + PMIC_RG_VCORE_CSL, + PMIC_RG_VCORE_SLP, + PMIC_RG_VCORE_ZX_OS, + PMIC_RG_VCORE_ZXOS_TRIM, + PMIC_RG_VCORE_MODESET, + PMIC_RG_VCORE_NDIS_EN, + PMIC_RG_VCORE_CSM_N, + PMIC_RG_VCORE_CSM_P, + PMIC_RG_VCORE_RSV, + PMIC_RG_VCORE_PFM_RIP, + PMIC_RG_VCORE_DTS_ENB, + PMIC_RG_VCORE_AUTO_MODE, + PMIC_RG_VCORE_PWM_TRIG, + PMIC_RG_VCORE_TRAN_BST, + PMIC_RGS_VCORE_ENPWM_STATUS, + PMIC_RG_VPROC_MIN_OFF, + PMIC_RG_VPROC_VRF18_SSTART_EN, + PMIC_RG_VPROC_1P35UP_SEL_EN, + PMIC_RG_VPROC_RZSEL, + PMIC_RG_VPROC_CSR, + PMIC_RG_VPROC_CSL, + PMIC_RG_VPROC_SLP, + PMIC_RG_VPROC_ZX_OS, + PMIC_RG_VPROC_ZXOS_TRIM, + PMIC_RG_VPROC_MODESET, + PMIC_RG_VPROC_NDIS_EN, + PMIC_RG_VPROC_CSM_N, + PMIC_RG_VPROC_CSM_P, + PMIC_RG_VPROC_RSV, + PMIC_RG_VPROC_PFM_RIP, + PMIC_RG_VPROC_DTS_ENB, + PMIC_RG_VPROC_BW_EXTEND, + PMIC_RG_VPROC_PWM_TRIG, + PMIC_RG_VPROC_TRAN_BST, + PMIC_RGS_VPROC_ENPWM_STATUS, + PMIC_RG_VS1_MIN_OFF, + PMIC_RG_VS1_NVT_BUFF_OFF_EN, + PMIC_RG_VS1_VRF18_SSTART_EN, + PMIC_RG_VS1_1P35UP_SEL_EN, + PMIC_RG_VS1_RZSEL, + PMIC_RG_VS1_CSR, + PMIC_RG_VS1_CSL, + PMIC_RG_VS1_SLP, + PMIC_RG_VS1_ZX_OS, + PMIC_RG_VS1_NDIS_EN, + PMIC_RG_VS1_CSM_N, + PMIC_RG_VS1_CSM_P, + PMIC_RG_VS1_RSV, + PMIC_RG_VS1_ZXOS_TRIM, + PMIC_RG_VS1_MODESET, + PMIC_RG_VS1_PFM_RIP, + PMIC_RG_VS1_TRAN_BST, + PMIC_RG_VS1_DTS_ENB, + PMIC_RG_VS1_AUTO_MODE, + PMIC_RG_VS1_PWM_TRIG, + PMIC_RGS_VS1_ENPWM_STATUS, + PMIC_DA_QI_VCORE_BURST, + PMIC_DA_QI_VCORE2_BURST, + PMIC_DA_QI_VS1_BURST, + PMIC_DA_QI_VPROC_BURST, + PMIC_DA_QI_VCORE_DLC, + PMIC_DA_QI_VCORE_DLC_N, + PMIC_DA_QI_VCORE2_DLC, + PMIC_DA_QI_VCORE2_DLC_N, + PMIC_DA_QI_VS1_DLC, + PMIC_DA_QI_VS1_DLC_N, + PMIC_DA_QI_VPROC_DLC, + PMIC_DA_QI_VPROC_DLC_N, + PMIC_RG_VCORE2_MIN_OFF, + PMIC_RG_VCORE2_VRF18_SSTART_EN, + PMIC_RG_VCORE2_1P35UP_SEL_EN, + PMIC_RG_VCORE2_RZSEL, + PMIC_RG_VCORE2_CSR, + PMIC_RG_VCORE2_CSL, + PMIC_RG_VCORE2_SLP, + PMIC_RG_VCORE2_ZX_OS, + PMIC_RG_VCORE2_ZXOS_TRIM, + PMIC_RG_VCORE2_MODESET, + PMIC_RG_VCORE2_NDIS_EN, + PMIC_RG_VCORE2_CSM_N, + PMIC_RG_VCORE2_CSM_P, + PMIC_RG_VCORE2_RSV, + PMIC_RG_VCORE2_PFM_RIP, + PMIC_RG_VCORE2_DTS_ENB, + PMIC_RG_VCORE2_AUTO_MODE, + PMIC_RG_VCORE2_PWM_TRIG, + PMIC_RG_VCORE2_TRAN_BST, + PMIC_RGS_VCORE2_ENPWM_STATUS, + PMIC_BUCK_VPROC_EN_CTRL, + PMIC_BUCK_VPROC_VOSEL_CTRL, + PMIC_BUCK_VPROC_EN_SEL, + PMIC_BUCK_VPROC_VOSEL_SEL, + PMIC_BUCK_VPROC_EN, + PMIC_BUCK_VPROC_STBTD, + PMIC_DA_VPROC_STB, + PMIC_DA_QI_VPROC_EN, + PMIC_BUCK_VPROC_SFCHG_FRATE, + PMIC_BUCK_VPROC_SFCHG_FEN, + PMIC_BUCK_VPROC_SFCHG_RRATE, + PMIC_BUCK_VPROC_SFCHG_REN, + PMIC_DA_NI_VPROC_VOSEL, + PMIC_BUCK_VPROC_VOSEL, + PMIC_BUCK_VPROC_VOSEL_ON, + PMIC_BUCK_VPROC_VOSEL_SLEEP, + PMIC_BUCK_VPROC_TRANS_TD, + PMIC_BUCK_VPROC_TRANS_CTRL, + PMIC_BUCK_VPROC_TRANS_ONCE, + PMIC_DA_QI_VPROC_DVS_EN, + PMIC_BUCK_VPROC_VSLEEP_EN, + PMIC_BUCK_VPROC_R2R_PDN, + PMIC_BUCK_VPROC_VSLEEP_SEL, + PMIC_DA_NI_VPROC_R2R_PDN, + PMIC_DA_NI_VPROC_VSLEEP_SEL, + PMIC_BUCK_VS1_EN_CTRL, + PMIC_BUCK_VS1_VOSEL_CTRL, + PMIC_BUCK_VS1_VOSEL_CTRL_0, + PMIC_BUCK_VS1_VOSEL_CTRL_1, + PMIC_BUCK_VS1_VOSEL_CTRL_2, + PMIC_BUCK_VS1_MODESET_0, + PMIC_BUCK_VS1_MODESET_1, + PMIC_BUCK_VS1_MODESET_2, + PMIC_DA_VS1_MODESET, + PMIC_BUCK_VS1_VOSEL_CTRL_INV, + PMIC_BUCK_VS1_HWM_CON0_SET, + PMIC_BUCK_VS1_HWM_CON0_CLR, + PMIC_BUCK_VS1_EN_SEL, + PMIC_BUCK_VS1_VOSEL_SEL, + PMIC_BUCK_VS1_EN, + PMIC_BUCK_VS1_STBTD, + PMIC_DA_VS1_STB, + PMIC_DA_QI_VS1_EN, + PMIC_BUCK_VS1_SFCHG_FRATE, + PMIC_BUCK_VS1_SFCHG_FEN, + PMIC_BUCK_VS1_SFCHG_RRATE, + PMIC_BUCK_VS1_SFCHG_REN, + PMIC_DA_NI_VS1_VOSEL, + PMIC_BUCK_VS1_VOSEL, + PMIC_BUCK_VS1_VOSEL_ON, + PMIC_BUCK_VS1_VOSEL_SLEEP, + PMIC_BUCK_VS1_TRANS_TD, + PMIC_BUCK_VS1_TRANS_CTRL, + PMIC_BUCK_VS1_TRANS_ONCE, + PMIC_DA_QI_VS1_DVS_EN, + PMIC_BUCK_VS1_VSLEEP_EN, + PMIC_BUCK_VS1_R2R_PDN, + PMIC_BUCK_VS1_VSLEEP_SEL, + PMIC_DA_NI_VS1_R2R_PDN, + PMIC_DA_NI_VS1_VSLEEP_SEL, + PMIC_BUCK_VCORE_EN_CTRL, + PMIC_BUCK_VCORE_VOSEL_CTRL, + PMIC_BUCK_VCORE_EN_SEL, + PMIC_BUCK_VCORE_VOSEL_SEL, + PMIC_BUCK_VCORE_EN, + PMIC_BUCK_VCORE_STBTD, + PMIC_DA_VCORE_STB, + PMIC_DA_QI_VCORE_EN, + PMIC_BUCK_VCORE_SFCHG_FRATE, + PMIC_BUCK_VCORE_SFCHG_FEN, + PMIC_BUCK_VCORE_SFCHG_RRATE, + PMIC_BUCK_VCORE_SFCHG_REN, + PMIC_DA_NI_VCORE_VOSEL, + PMIC_BUCK_VCORE_VOSEL, + PMIC_BUCK_VCORE_VOSEL_ON, + PMIC_BUCK_VCORE_VOSEL_SLEEP, + PMIC_BUCK_VCORE_TRANS_TD, + PMIC_BUCK_VCORE_TRANS_CTRL, + PMIC_BUCK_VCORE_TRANS_ONCE, + PMIC_DA_QI_VCORE_DVS_EN, + PMIC_BUCK_VCORE_VSLEEP_EN, + PMIC_BUCK_VCORE_R2R_PDN, + PMIC_BUCK_VCORE_VSLEEP_SEL, + PMIC_DA_NI_VCORE_R2R_PDN, + PMIC_DA_NI_VCORE_VSLEEP_SEL, + PMIC_BUCK_VCORE2_EN_CTRL, + PMIC_BUCK_VCORE2_VOSEL_CTRL, + PMIC_BUCK_VCORE2_EN_SEL, + PMIC_BUCK_VCORE2_VOSEL_SEL, + PMIC_BUCK_VCORE2_EN, + PMIC_BUCK_VCORE2_STBTD, + PMIC_DA_VCORE2_STB, + PMIC_DA_QI_VCORE2_EN, + PMIC_BUCK_VCORE2_SFCHG_FRATE, + PMIC_BUCK_VCORE2_SFCHG_FEN, + PMIC_BUCK_VCORE2_SFCHG_RRATE, + PMIC_BUCK_VCORE2_SFCHG_REN, + PMIC_DA_NI_VCORE2_VOSEL, + PMIC_BUCK_VCORE2_VOSEL, + PMIC_BUCK_VCORE2_VOSEL_ON, + PMIC_BUCK_VCORE2_VOSEL_SLEEP, + PMIC_BUCK_VCORE2_TRANS_TD, + PMIC_BUCK_VCORE2_TRANS_CTRL, + PMIC_BUCK_VCORE2_TRANS_ONCE, + PMIC_DA_QI_VCORE2_DVS_EN, + PMIC_BUCK_VCORE2_VSLEEP_EN, + PMIC_BUCK_VCORE2_R2R_PDN, + PMIC_BUCK_VCORE2_VSLEEP_SEL, + PMIC_DA_NI_VCORE2_R2R_PDN, + PMIC_DA_NI_VCORE2_VSLEEP_SEL, + PMIC_BUCK_VPA_EN, + PMIC_BUCK_VPA_STBTD, + PMIC_DA_VPA_STB, + PMIC_DA_QI_VPA_EN, + PMIC_BUCK_VPA_SFCHG_FRATE, + PMIC_BUCK_VPA_SFCHG_FEN, + PMIC_BUCK_VPA_SFCHG_RRATE, + PMIC_BUCK_VPA_SFCHG_REN, + PMIC_DA_NI_VPA_VOSEL, + PMIC_BUCK_VPA_VOSEL, + PMIC_BUCK_VPA_TRANS_TD, + PMIC_BUCK_VPA_TRANS_CTRL, + PMIC_BUCK_VPA_TRANS_ONCE, + PMIC_DA_NI_VPA_DVS_TRANST, + PMIC_BUCK_VPA_DVS_BW_TD, + PMIC_BUCK_VPA_DVS_BW_CTRL, + PMIC_BUCK_VPA_DVS_BW_ONCE, + PMIC_DA_NI_VPA_DVS_BW, + PMIC_BUCK_K_RST_DONE, + PMIC_BUCK_K_MAP_SEL, + PMIC_BUCK_K_ONCE_EN, + PMIC_BUCK_K_ONCE, + PMIC_BUCK_K_START_MANUAL, + PMIC_BUCK_K_SRC_SEL, + PMIC_BUCK_K_AUTO_EN, + PMIC_BUCK_K_INV, + PMIC_BUCK_K_CONTROL_SMPS, + PMIC_K_RESULT, + PMIC_K_DONE, + PMIC_K_CONTROL, + PMIC_DA_QI_SMPS_OSC_CAL, + PMIC_BUCK_K_BUCK_CK_CNT, + PMIC_WDTDBG_CLR, + PMIC_WDTDBG_CON0_RSV0, + PMIC_VPROC_VOSEL_WDTDBG, + PMIC_VCORE_VOSEL_WDTDBG, + PMIC_VPA_VOSEL_WDTDBG, + PMIC_VS1_VOSEL_WDTDBG, + PMIC_VSRAM_PROC_VOSEL_WDTDBG, + PMIC_RG_AUDZCDENABLE, + PMIC_RG_AUDZCDGAINSTEPTIME, + PMIC_RG_AUDZCDGAINSTEPSIZE, + PMIC_RG_AUDZCDTIMEOUTMODESEL, + PMIC_RG_AUDZCDCLKSEL_VAUDP15, + PMIC_RG_AUDZCDMUXSEL_VAUDP15, + PMIC_RG_AUDLOLGAIN, + PMIC_RG_AUDLORGAIN, + PMIC_RG_AUDHPLGAIN, + PMIC_RG_AUDHPRGAIN, + PMIC_RG_AUDHSGAIN, + PMIC_RG_AUDIVLGAIN, + PMIC_RG_AUDIVRGAIN, + PMIC_RG_AUDINTGAIN1, + PMIC_RG_AUDINTGAIN2, + PMIC_LDO_LDO_RSV1, + PMIC_LDO_LDO_RSV0, + PMIC_LDO_LDO_RSV1_RO, + PMIC_LDO_LDO_RSV2, + PMIC_LDO_VAUX18_AUXADC_PWDB_EN, + PMIC_LDO_VIBR_THER_SDN_EN, + PMIC_LDO_TOP_CON0_RSV, + PMIC_LDO_VTCXO24_SWITCH, + PMIC_LDO_VXO22_SWITCH, + PMIC_LDO_DEGTD_SEL, + PMIC_LDO_VRTC_EN, + PMIC_DA_QI_VRTC_EN, + PMIC_LDO_VCN33_EN_BT, + PMIC_LDO_VCN33_EN_CTRL_BT, + PMIC_LDO_VCN33_EN_SEL_BT, + PMIC_LDO_VCN33_EN_WIFI, + PMIC_LDO_VCN33_EN_CTRL_WIFI, + PMIC_LDO_VCN33_EN_SEL_WIFI, + PMIC_LDO_VCN33_LP_MODE, + PMIC_LDO_VCN33_LP_CTRL, + PMIC_LDO_VCN33_LP_SEL, + PMIC_DA_QI_VCN33_MODE, + PMIC_LDO_VCN33_STBTD, + PMIC_DA_QI_VCN33_STB, + PMIC_DA_QI_VCN33_EN, + PMIC_LDO_VCN33_OCFB_EN, + PMIC_DA_QI_VCN33_OCFB_EN, + PMIC_LDO_VLDO28_EN_0, + PMIC_LDO_VLDO28_EN_1, + PMIC_LDO_VLDO28_LP_MODE, + PMIC_LDO_VLDO28_LP_CTRL, + PMIC_LDO_VLDO28_LP_SEL, + PMIC_DA_QI_VLDO28_MODE, + PMIC_LDO_VLDO28_STBTD, + PMIC_DA_QI_VLDO28_STB, + PMIC_DA_QI_VLDO28_EN, + PMIC_LDO_VLDO28_OCFB_EN, + PMIC_DA_QI_VLDO28_OCFB_EN, + PMIC_LDO_VLDO28_FAST_TRAN_DL_EN, + PMIC_LDO_VLDO28_FAST_TRAN_DL_CTRL, + PMIC_LDO_VLDO28_FAST_TRAN_DL_SRCLKEN_SEL, + PMIC_DA_QI_VLDO28_FAST_TRAN_DL_EN, + PMIC_LDO_VLDO28_FAST_TRAN_CL_EN, + PMIC_LDO_VLDO28_FAST_TRAN_CL_CTRL, + PMIC_LDO_VLDO28_FAST_TRAN_CL_SRCLKEN_SEL, + PMIC_DA_QI_VLDO28_FAST_TRAN_CL_EN, + PMIC_LDO_VSRAM_PROC_VOSEL_CTRL, + PMIC_LDO_VSRAM_PROC_VOSEL_SEL, + PMIC_LDO_VSRAM_PROC_SFCHG_FRATE, + PMIC_LDO_VSRAM_PROC_SFCHG_FEN, + PMIC_LDO_VSRAM_PROC_SFCHG_RRATE, + PMIC_LDO_VSRAM_PROC_SFCHG_REN, + PMIC_DA_NI_VSRAM_PROC_VOSEL, + PMIC_LDO_VSRAM_PROC_VOSEL, + PMIC_LDO_VSRAM_PROC_VOSEL_ON, + PMIC_LDO_VSRAM_PROC_VOSEL_SLEEP, + PMIC_LDO_VSRAM_PROC_TRANS_TD, + PMIC_LDO_VSRAM_PROC_TRANS_CTRL, + PMIC_LDO_VSRAM_PROC_TRANS_ONCE, + PMIC_DA_QI_VSRAM_PROC_DVS_EN, + PMIC_LDO_VSRAM_PROC_VSLEEP_EN, + PMIC_LDO_VSRAM_PROC_R2R_PDN, + PMIC_LDO_VSRAM_PROC_VSLEEP_SEL, + PMIC_DA_NI_VSRAM_PROC_R2R_PDN, + PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL, + PMIC_LDO_BATON_HT_EN, + PMIC_LDO_BATON_HT_EN_DLY_TIME, + PMIC_DA_QI_BATON_HT_EN, + PMIC_LDO_TREF_EN, + PMIC_LDO_TREF_EN_CTRL, + PMIC_LDO_TREF_EN_SEL, + PMIC_DA_QI_TREF_EN, + PMIC_LDO_VTCXO28_LP_MODE, + PMIC_LDO_VTCXO28_EN, + PMIC_LDO_VTCXO28_LP_CTRL, + PMIC_LDO_VTCXO28_EN_CTRL, + PMIC_LDO_VTCXO28_LP_SEL, + PMIC_DA_QI_VTCXO28_MODE, + PMIC_LDO_VTCXO28_STBTD, + PMIC_LDO_VTCXO28_EN_SEL, + PMIC_DA_QI_VTCXO28_STB, + PMIC_DA_QI_VTCXO28_EN, + PMIC_LDO_VTCXO28_OCFB_EN, + PMIC_DA_QI_VTCXO28_OCFB_EN, + PMIC_LDO_VTCXO24_LP_MODE, + PMIC_LDO_VTCXO24_EN, + PMIC_LDO_VTCXO24_LP_CTRL, + PMIC_LDO_VTCXO24_EN_CTRL, + PMIC_LDO_VTCXO24_LP_SEL, + PMIC_DA_QI_VTCXO24_MODE, + PMIC_LDO_VTCXO24_STBTD, + PMIC_LDO_VTCXO24_EN_SEL, + PMIC_DA_QI_VTCXO24_STB, + PMIC_DA_QI_VTCXO24_EN, + PMIC_LDO_VTCXO24_OCFB_EN, + PMIC_DA_QI_VTCXO24_OCFB_EN, + PMIC_LDO_VXO22_LP_MODE, + PMIC_LDO_VXO22_EN, + PMIC_LDO_VXO22_LP_CTRL, + PMIC_LDO_VXO22_EN_CTRL, + PMIC_LDO_VXO22_LP_SEL, + PMIC_DA_QI_VXO22_MODE, + PMIC_LDO_VXO22_STBTD, + PMIC_LDO_VXO22_EN_SEL, + PMIC_DA_QI_VXO22_STB, + PMIC_DA_QI_VXO22_EN, + PMIC_LDO_VXO22_OCFB_EN, + PMIC_DA_QI_VXO22_OCFB_EN, + PMIC_LDO_VRF18_LP_MODE, + PMIC_LDO_VRF18_EN, + PMIC_LDO_VRF18_LP_CTRL, + PMIC_LDO_VRF18_EN_CTRL, + PMIC_LDO_VRF18_LP_SEL, + PMIC_DA_QI_VRF18_MODE, + PMIC_LDO_VRF18_STBTD, + PMIC_LDO_VRF18_EN_SEL, + PMIC_DA_QI_VRF18_STB, + PMIC_DA_QI_VRF18_EN, + PMIC_LDO_VRF18_OCFB_EN, + PMIC_DA_QI_VRF18_OCFB_EN, + PMIC_LDO_VRF12_LP_MODE, + PMIC_LDO_VRF12_EN, + PMIC_LDO_VRF12_LP_CTRL, + PMIC_LDO_VRF12_EN_CTRL, + PMIC_LDO_VRF12_LP_SEL, + PMIC_DA_QI_VRF12_MODE, + PMIC_LDO_VRF12_STBTD, + PMIC_LDO_VRF12_EN_SEL, + PMIC_DA_QI_VRF12_STB, + PMIC_DA_QI_VRF12_EN, + PMIC_LDO_VRF12_OCFB_EN, + PMIC_DA_QI_VRF12_OCFB_EN, + PMIC_LDO_VRF12_FAST_TRAN_DL_EN, + PMIC_LDO_VRF12_FAST_TRAN_DL_CTRL, + PMIC_LDO_VRF12_FAST_TRAN_DL_SRCLKEN_SEL, + PMIC_DA_QI_VRF12_FAST_TRAN_DL_EN, + PMIC_LDO_VRF12_FAST_TRAN_CL_EN, + PMIC_LDO_VRF12_FAST_TRAN_CL_CTRL, + PMIC_LDO_VRF12_FAST_TRAN_CL_SRCLKEN_SEL, + PMIC_DA_QI_VRF12_FAST_TRAN_CL_EN, + PMIC_LDO_VCN28_LP_MODE, + PMIC_LDO_VCN28_EN, + PMIC_LDO_VCN28_LP_CTRL, + PMIC_LDO_VCN28_EN_CTRL, + PMIC_LDO_VCN28_LP_SEL, + PMIC_DA_QI_VCN28_MODE, + PMIC_LDO_VCN28_STBTD, + PMIC_LDO_VCN28_EN_SEL, + PMIC_DA_QI_VCN28_STB, + PMIC_DA_QI_VCN28_EN, + PMIC_LDO_VCN28_OCFB_EN, + PMIC_DA_QI_VCN28_OCFB_EN, + PMIC_LDO_VCN18_LP_MODE, + PMIC_LDO_VCN18_EN, + PMIC_LDO_VCN18_LP_CTRL, + PMIC_LDO_VCN18_EN_CTRL, + PMIC_LDO_VCN18_LP_SEL, + PMIC_DA_QI_VCN18_MODE, + PMIC_LDO_VCN18_STBTD, + PMIC_LDO_VCN18_EN_SEL, + PMIC_DA_QI_VCN18_STB, + PMIC_DA_QI_VCN18_EN, + PMIC_LDO_VCN18_OCFB_EN, + PMIC_DA_QI_VCN18_OCFB_EN, + PMIC_LDO_VCAMA_LP_MODE, + PMIC_LDO_VCAMA_EN, + PMIC_DA_QI_VCAMA_MODE, + PMIC_LDO_VCAMA_STBTD, + PMIC_DA_QI_VCAMA_STB, + PMIC_DA_QI_VCAMA_EN, + PMIC_LDO_VCAMA_OCFB_EN, + PMIC_DA_QI_VCAMA_OCFB_EN, + PMIC_LDO_VCAMIO_LP_MODE, + PMIC_LDO_VCAMIO_EN, + PMIC_DA_QI_VCAMIO_MODE, + PMIC_LDO_VCAMIO_STBTD, + PMIC_DA_QI_VCAMIO_STB, + PMIC_DA_QI_VCAMIO_EN, + PMIC_LDO_VCAMIO_OCFB_EN, + PMIC_DA_QI_VCAMIO_OCFB_EN, + PMIC_LDO_VCAMD_LP_MODE, + PMIC_LDO_VCAMD_EN, + PMIC_DA_QI_VCAMD_MODE, + PMIC_LDO_VCAMD_STBTD, + PMIC_DA_QI_VCAMD_STB, + PMIC_DA_QI_VCAMD_EN, + PMIC_LDO_VCAMD_OCFB_EN, + PMIC_DA_QI_VCAMD_OCFB_EN, + PMIC_LDO_VAUX18_LP_MODE, + PMIC_LDO_VAUX18_EN, + PMIC_LDO_VAUX18_LP_CTRL, + PMIC_LDO_VAUX18_EN_CTRL, + PMIC_LDO_VAUX18_LP_SEL, + PMIC_DA_QI_VAUX18_MODE, + PMIC_LDO_VAUX18_STBTD, + PMIC_LDO_VAUX18_EN_SEL, + PMIC_DA_QI_VAUX18_STB, + PMIC_DA_QI_VAUX18_EN, + PMIC_LDO_VAUX18_OCFB_EN, + PMIC_DA_QI_VAUX18_OCFB_EN, + PMIC_LDO_VAUD28_LP_MODE, + PMIC_LDO_VAUD28_EN, + PMIC_LDO_VAUD28_LP_CTRL, + PMIC_LDO_VAUD28_EN_CTRL, + PMIC_LDO_VAUD28_LP_SEL, + PMIC_DA_QI_VAUD28_MODE, + PMIC_LDO_VAUD28_STBTD, + PMIC_LDO_VAUD28_EN_SEL, + PMIC_DA_QI_VAUD28_STB, + PMIC_DA_QI_VAUD28_EN, + PMIC_LDO_VAUD28_OCFB_EN, + PMIC_DA_QI_VAUD28_OCFB_EN, + PMIC_LDO_VSRAM_PROC_LP_MODE, + PMIC_LDO_VSRAM_PROC_EN, + PMIC_LDO_VSRAM_PROC_LP_CTRL, + PMIC_LDO_VSRAM_PROC_EN_CTRL, + PMIC_LDO_VSRAM_PROC_LP_SEL, + PMIC_DA_QI_VSRAM_PROC_MODE, + PMIC_LDO_VSRAM_PROC_STBTD, + PMIC_LDO_VSRAM_PROC_EN_SEL, + PMIC_DA_QI_VSRAM_PROC_STB, + PMIC_DA_QI_VSRAM_PROC_EN, + PMIC_LDO_VSRAM_PROC_OCFB_EN, + PMIC_DA_QI_VSRAM_PROC_OCFB_EN, + PMIC_LDO_VDRAM_LP_MODE, + PMIC_LDO_VDRAM_EN, + PMIC_LDO_VDRAM_LP_CTRL, + PMIC_LDO_VDRAM_LP_SEL, + PMIC_DA_QI_VDRAM_MODE, + PMIC_LDO_VDRAM_STBTD, + PMIC_DA_QI_VDRAM_STB, + PMIC_DA_QI_VDRAM_EN, + PMIC_LDO_VDRAM_OCFB_EN, + PMIC_DA_QI_VDRAM_OCFB_EN, + PMIC_LDO_VDRAM_FAST_TRAN_DL_EN, + PMIC_LDO_VDRAM_FAST_TRAN_DL_CTRL, + PMIC_LDO_VDRAM_FAST_TRAN_DL_SRCLKEN_SEL, + PMIC_DA_QI_VDRAM_FAST_TRAN_DL_EN, + PMIC_LDO_VDRAM_FAST_TRAN_CL_EN, + PMIC_LDO_VDRAM_FAST_TRAN_CL_CTRL, + PMIC_LDO_VDRAM_FAST_TRAN_CL_SRCLKEN_SEL, + PMIC_DA_QI_VDRAM_FAST_TRAN_CL_EN, + PMIC_LDO_VSIM1_LP_MODE, + PMIC_LDO_VSIM1_EN, + PMIC_LDO_VSIM1_LP_CTRL, + PMIC_LDO_VSIM1_LP_SEL, + PMIC_DA_QI_VSIM1_MODE, + PMIC_LDO_VSIM1_STBTD, + PMIC_DA_QI_VSIM1_STB, + PMIC_DA_QI_VSIM1_EN, + PMIC_LDO_VSIM1_OCFB_EN, + PMIC_DA_QI_VSIM1_OCFB_EN, + PMIC_LDO_VSIM2_LP_MODE, + PMIC_LDO_VSIM2_EN, + PMIC_LDO_VSIM2_LP_CTRL, + PMIC_LDO_VSIM2_LP_SEL, + PMIC_DA_QI_VSIM2_MODE, + PMIC_LDO_VSIM2_STBTD, + PMIC_DA_QI_VSIM2_STB, + PMIC_DA_QI_VSIM2_EN, + PMIC_LDO_VSIM2_OCFB_EN, + PMIC_DA_QI_VSIM2_OCFB_EN, + PMIC_LDO_VIO28_LP_MODE, + PMIC_LDO_VIO28_EN, + PMIC_LDO_VIO28_LP_CTRL, + PMIC_LDO_VIO28_LP_SEL, + PMIC_DA_QI_VIO28_MODE, + PMIC_LDO_VIO28_STBTD, + PMIC_DA_QI_VIO28_STB, + PMIC_DA_QI_VIO28_EN, + PMIC_LDO_VIO28_OCFB_EN, + PMIC_DA_QI_VIO28_OCFB_EN, + PMIC_LDO_VMC_LP_MODE, + PMIC_LDO_VMC_EN, + PMIC_LDO_VMC_LP_CTRL, + PMIC_LDO_VMC_LP_SEL, + PMIC_DA_QI_VMC_MODE, + PMIC_LDO_VMC_STBTD, + PMIC_DA_QI_VMC_STB, + PMIC_DA_QI_VMC_EN, + PMIC_LDO_VMC_OCFB_EN, + PMIC_DA_QI_VMC_OCFB_EN, + PMIC_LDO_VMC_FAST_TRAN_DL_EN, + PMIC_LDO_VMC_FAST_TRAN_DL_CTRL, + PMIC_LDO_VMC_FAST_TRAN_DL_SRCLKEN_SEL, + PMIC_DA_QI_VMC_FAST_TRAN_DL_EN, + PMIC_LDO_VMC_FAST_TRAN_CL_EN, + PMIC_LDO_VMC_FAST_TRAN_CL_CTRL, + PMIC_LDO_VMC_FAST_TRAN_CL_SRCLKEN_SEL, + PMIC_DA_QI_VMC_FAST_TRAN_CL_EN, + PMIC_LDO_VMCH_LP_MODE, + PMIC_LDO_VMCH_EN, + PMIC_LDO_VMCH_LP_CTRL, + PMIC_LDO_VMCH_LP_SEL, + PMIC_DA_QI_VMCH_MODE, + PMIC_LDO_VMCH_STBTD, + PMIC_DA_QI_VMCH_STB, + PMIC_DA_QI_VMCH_EN, + PMIC_LDO_VMCH_OCFB_EN, + PMIC_DA_QI_VMCH_OCFB_EN, + PMIC_LDO_VMCH_FAST_TRAN_DL_EN, + PMIC_LDO_VMCH_FAST_TRAN_DL_CTRL, + PMIC_LDO_VMCH_FAST_TRAN_DL_SRCLKEN_SEL, + PMIC_DA_QI_VMCH_FAST_TRAN_DL_EN, + PMIC_LDO_VMCH_FAST_TRAN_CL_EN, + PMIC_LDO_VMCH_FAST_TRAN_CL_CTRL, + PMIC_LDO_VMCH_FAST_TRAN_CL_SRCLKEN_SEL, + PMIC_DA_QI_VMCH_FAST_TRAN_CL_EN, + PMIC_LDO_VUSB33_LP_MODE, + PMIC_LDO_VUSB33_EN, + PMIC_LDO_VUSB33_LP_CTRL, + PMIC_LDO_VUSB33_LP_SEL, + PMIC_DA_QI_VUSB33_MODE, + PMIC_LDO_VUSB33_STBTD, + PMIC_DA_QI_VUSB33_STB, + PMIC_DA_QI_VUSB33_EN, + PMIC_LDO_VUSB33_OCFB_EN, + PMIC_DA_QI_VUSB33_OCFB_EN, + PMIC_LDO_VEMC33_LP_MODE, + PMIC_LDO_VEMC33_EN, + PMIC_LDO_VEMC33_LP_CTRL, + PMIC_LDO_VEMC33_LP_SEL, + PMIC_DA_QI_VEMC33_MODE, + PMIC_LDO_VEMC33_STBTD, + PMIC_DA_QI_VEMC33_STB, + PMIC_DA_QI_VEMC33_EN, + PMIC_LDO_VEMC33_OCFB_EN, + PMIC_DA_QI_VEMC33_OCFB_EN, + PMIC_LDO_VEMC33_FAST_TRAN_DL_EN, + PMIC_LDO_VEMC33_FAST_TRAN_DL_CTRL, + PMIC_LDO_VEMC33_FAST_TRAN_DL_SRCLKEN_SEL, + PMIC_DA_QI_VEMC33_FAST_TRAN_DL_EN, + PMIC_LDO_VEMC33_FAST_TRAN_CL_EN, + PMIC_LDO_VEMC33_FAST_TRAN_CL_CTRL, + PMIC_LDO_VEMC33_FAST_TRAN_CL_SRCLKEN_SEL, + PMIC_DA_QI_VEMC33_FAST_TRAN_CL_EN, + PMIC_LDO_VIO18_LP_MODE, + PMIC_LDO_VIO18_EN, + PMIC_LDO_VIO18_LP_CTRL, + PMIC_LDO_VIO18_LP_SEL, + PMIC_DA_QI_VIO18_MODE, + PMIC_LDO_VIO18_STBTD, + PMIC_DA_QI_VIO18_STB, + PMIC_DA_QI_VIO18_EN, + PMIC_LDO_VIO18_OCFB_EN, + PMIC_DA_QI_VIO18_OCFB_EN, + PMIC_LDO_VIBR_LP_MODE, + PMIC_LDO_VIBR_EN, + PMIC_DA_QI_VIBR_MODE, + PMIC_LDO_VIBR_STBTD, + PMIC_DA_QI_VIBR_STB, + PMIC_DA_QI_VIBR_EN, + PMIC_LDO_VIBR_OCFB_EN, + PMIC_DA_QI_VIBR_OCFB_EN, + PMIC_RG_VTCXO28_CAL, + PMIC_RG_VTCXO28_VOSEL, + PMIC_RG_VTCXO28_NDIS_EN, + PMIC_RG_VAUD28_CAL, + PMIC_RG_VAUD28_VOSEL, + PMIC_RG_VAUD28_NDIS_EN, + PMIC_RG_VCN28_CAL, + PMIC_RG_VCN28_VOSEL, + PMIC_RG_VCN28_NDIS_EN, + PMIC_RG_VAUX18_CAL, + PMIC_RG_VAUX18_VOSEL, + PMIC_RG_VAUX18_NDIS_EN, + PMIC_RG_VCAMA_CAL, + PMIC_RG_VCAMA_VOSEL, + PMIC_RG_VCAMA_NDIS_EN, + PMIC_RG_ALDO_RSV_H, + PMIC_RG_ALDO_RSV_L, + PMIC_RG_VXO22_CAL, + PMIC_RG_VXO22_VOSEL, + PMIC_RG_VXO22_NDIS_EN, + PMIC_RG_VTCXO24_CAL, + PMIC_RG_VTCXO24_VOSEL, + PMIC_RG_VTCXO24_NDIS_EN, + PMIC_RG_VSIM1_CAL, + PMIC_RG_VSIM1_VOSEL, + PMIC_RG_VSIM1_NDIS_EN, + PMIC_RG_VSIM2_CAL, + PMIC_RG_VSIM2_VOSEL, + PMIC_RG_VSIM2_NDIS_EN, + PMIC_RG_VCN33_CAL, + PMIC_RG_VCN33_VOSEL, + PMIC_RG_VCN33_NDIS_EN, + PMIC_RG_VUSB33_CAL, + PMIC_RG_VUSB33_NDIS_EN, + PMIC_RG_VMCH_CAL, + PMIC_RG_VMCH_VOSEL, + PMIC_RG_VMCH_NDIS_EN, + PMIC_RG_VMCH_OC_TRIM, + PMIC_RG_VMCH_DUMMY_LOAD, + PMIC_RG_VMCH_DL_EN, + PMIC_RG_VMCH_CL_EN, + PMIC_RG_VMCH_STB_SEL, + PMIC_RG_VEMC33_CAL, + PMIC_RG_VEMC33_VOSEL, + PMIC_RG_VEMC33_NDIS_EN, + PMIC_RG_VEMC33_OC_TRIM, + PMIC_RG_VEMC33_DUMMY_LOAD, + PMIC_RG_VEMC33_DL_EN, + PMIC_RG_VEMC33_CL_EN, + PMIC_RG_VEMC33_STB_SEL, + PMIC_RG_VIO28_CAL, + PMIC_RG_VIO28_NDIS_EN, + PMIC_RG_VIBR_CAL, + PMIC_RG_VIBR_VOSEL, + PMIC_RG_VIBR_NDIS_EN, + PMIC_RG_VLDO28_CAL, + PMIC_RG_VLDO28_VOSEL, + PMIC_RG_VLDO28_NDIS_EN, + PMIC_RG_VLDO28_DUMMY_LOAD, + PMIC_RG_VLDO28_DL_EN, + PMIC_RG_VLDO28_CL_EN, + PMIC_RG_VMC_CAL, + PMIC_RG_VMC_VOSEL, + PMIC_RG_VMC_NDIS_EN, + PMIC_RG_VMC_DUMMY_LOAD, + PMIC_RG_VMC_DL_EN, + PMIC_RG_VMC_CL_EN, + PMIC_RG_DLDO_RSV_H, + PMIC_RG_DLDO_RSV_L, + PMIC_RG_VCAMD_CAL, + PMIC_RG_VCAMD_VOSEL, + PMIC_RG_VCAMD_NDIS_EN, + PMIC_RG_VRF18_CAL, + PMIC_RG_VRF18_NDIS_EN, + PMIC_RG_VRF12_CAL, + PMIC_RG_VRF12_VOSEL, + PMIC_RG_VRF12_NDIS_EN, + PMIC_RG_VRF12_STB_SEL, + PMIC_RG_VRF12_DUMMY_LOAD, + PMIC_RG_VRF12_DL_EN, + PMIC_RG_VRF12_CL_EN, + PMIC_RG_VIO18_CAL, + PMIC_RG_VIO18_NDIS_EN, + PMIC_RG_VDRAM_CAL, + PMIC_RG_VDRAM_VOSEL, + PMIC_RG_VDRAM_NDIS_EN, + PMIC_RG_VDRAM_PCUR_CAL, + PMIC_RG_VDRAM_DL_EN, + PMIC_RG_VDRAM_CL_EN, + PMIC_RG_VCAMIO_CAL, + PMIC_RG_VCAMIO_VOSEL, + PMIC_RG_VCAMIO_NDIS_EN, + PMIC_RG_VCN18_CAL, + PMIC_RG_VCN18_NDIS_EN, + PMIC_RG_VSRAM_PROC_VOSEL, + PMIC_RG_VSRAM_PROC_NDIS_PLCUR, + PMIC_RG_VSRAM_PROC_NDIS_EN, + PMIC_RG_VSRAM_PROC_PLCUR_EN, + PMIC_RG_SLDO_RSV_H, + PMIC_RG_SLDO_RSV_L, + PMIC_RG_OTP_PA, + PMIC_RG_OTP_PDIN, + PMIC_RG_OTP_PTM, + PMIC_RG_OTP_PWE, + PMIC_RG_OTP_PPROG, + PMIC_RG_OTP_PWE_SRC, + PMIC_RG_OTP_PROG_PKEY, + PMIC_RG_OTP_RD_PKEY, + PMIC_RG_OTP_RD_TRIG, + PMIC_RG_RD_RDY_BYPASS, + PMIC_RG_SKIP_OTP_OUT, + PMIC_RG_OTP_RD_SW, + PMIC_RG_OTP_DOUT_SW, + PMIC_RG_OTP_RD_BUSY, + PMIC_RG_OTP_RD_ACK, + PMIC_RG_OTP_PA_SW, + PMIC_RG_OTP_DOUT_0_15, + PMIC_RG_OTP_DOUT_16_31, + PMIC_RG_OTP_DOUT_32_47, + PMIC_RG_OTP_DOUT_48_63, + PMIC_RG_OTP_DOUT_64_79, + PMIC_RG_OTP_DOUT_80_95, + PMIC_RG_OTP_DOUT_96_111, + PMIC_RG_OTP_DOUT_112_127, + PMIC_RG_OTP_DOUT_128_143, + PMIC_RG_OTP_DOUT_144_159, + PMIC_RG_OTP_DOUT_160_175, + PMIC_RG_OTP_DOUT_176_191, + PMIC_RG_OTP_DOUT_192_207, + PMIC_RG_OTP_DOUT_208_223, + PMIC_RG_OTP_DOUT_224_239, + PMIC_RG_OTP_DOUT_240_255, + PMIC_RG_OTP_DOUT_256_271, + PMIC_RG_OTP_DOUT_272_287, + PMIC_RG_OTP_DOUT_288_303, + PMIC_RG_OTP_DOUT_304_319, + PMIC_RG_OTP_DOUT_320_335, + PMIC_RG_OTP_DOUT_336_351, + PMIC_RG_OTP_DOUT_352_367, + PMIC_RG_OTP_DOUT_368_383, + PMIC_RG_OTP_DOUT_384_399, + PMIC_RG_OTP_DOUT_400_415, + PMIC_RG_OTP_DOUT_416_431, + PMIC_RG_OTP_DOUT_432_447, + PMIC_RG_OTP_DOUT_448_463, + PMIC_RG_OTP_DOUT_464_479, + PMIC_RG_OTP_DOUT_480_495, + PMIC_RG_OTP_DOUT_496_511, + PMIC_RG_OTP_VAL_0_15, + PMIC_RG_OTP_VAL_16_31, + PMIC_RG_OTP_VAL_32_47, + PMIC_RG_OTP_VAL_48_63, + PMIC_RG_OTP_VAL_64_79, + PMIC_RG_OTP_VAL_80_95, + PMIC_RG_OTP_VAL_96_111, + PMIC_RG_OTP_VAL_112_127, + PMIC_RG_OTP_VAL_128_143, + PMIC_RG_OTP_VAL_144_159, + PMIC_RG_OTP_VAL_160_175, + PMIC_RG_OTP_VAL_176_191, + PMIC_RG_OTP_VAL_192_207, + PMIC_RG_OTP_VAL_208_223, + PMIC_RG_OTP_VAL_224_239, + PMIC_RG_OTP_VAL_240_255, + PMIC_RG_OTP_VAL_256_271, + PMIC_RG_OTP_VAL_272_287, + PMIC_RG_OTP_VAL_288_303, + PMIC_RG_OTP_VAL_304_319, + PMIC_RG_OTP_VAL_320_335, + PMIC_RG_OTP_VAL_336_351, + PMIC_RG_OTP_VAL_352_367, + PMIC_RG_OTP_VAL_368_383, + PMIC_RG_OTP_VAL_384_399, + PMIC_RG_OTP_VAL_400_415, + PMIC_RG_OTP_VAL_416_431, + PMIC_RG_OTP_VAL_432_447, + PMIC_RG_OTP_VAL_448_463, + PMIC_RG_OTP_VAL_464_479, + PMIC_RG_OTP_VAL_480_495, + PMIC_RG_OTP_VAL_496_511, + PMIC_MIX_EOSC32_STP_LPDTB, + PMIC_MIX_EOSC32_STP_LPDEN, + PMIC_MIX_XOSC32_STP_PWDB, + PMIC_MIX_XOSC32_STP_LPDTB, + PMIC_MIX_XOSC32_STP_LPDEN, + PMIC_MIX_XOSC32_STP_LPDRST, + PMIC_MIX_XOSC32_STP_CALI, + PMIC_STMP_MODE, + PMIC_MIX_EOSC32_STP_CHOP_EN, + PMIC_MIX_DCXO_STP_LVSH_EN, + PMIC_MIX_PMU_STP_DDLO_VRTC, + PMIC_MIX_PMU_STP_DDLO_VRTC_EN, + PMIC_MIX_RTC_STP_XOSC32_ENB, + PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE, + PMIC_MIX_EOSC32_STP_RSV, + PMIC_MIX_EOSC32_VCT_EN, + PMIC_MIX_EOSC32_OPT, + PMIC_MIX_DCXO_STP_LVSH_EN_INT, + PMIC_MIX_RTC_GPIO_COREDETB, + PMIC_MIX_RTC_GPIO_F32KOB, + PMIC_MIX_RTC_GPIO_GPO, + PMIC_MIX_RTC_GPIO_OE, + PMIC_MIX_RTC_STP_DEBUG_OUT, + PMIC_MIX_RTC_STP_DEBUG_SEL, + PMIC_MIX_RTC_STP_K_EOSC32_EN, + PMIC_MIX_RTC_STP_EMBCK_SEL, + PMIC_MIX_STP_BBWAKEUP, + PMIC_MIX_STP_RTC_DDLO, + PMIC_MIX_RTC_XOSC32_ENB, + PMIC_MIX_EFUSE_XOSC32_ENB_OPT, + PMIC_FG_ON, + PMIC_FG_CAL, + PMIC_FG_AUTOCALRATE, + PMIC_FG_SW_CR, + PMIC_FG_SW_READ_PRE, + PMIC_FG_LATCHDATA_ST, + PMIC_FG_SW_CLEAR, + PMIC_FG_OFFSET_RST, + PMIC_FG_TIME_RST, + PMIC_FG_CHARGE_RST, + PMIC_FG_SW_RSTCLR, + PMIC_FG_CAR_34_19, + PMIC_FG_CAR_18_03, + PMIC_FG_CAR_02_00, + PMIC_FG_NTER_32_17, + PMIC_FG_NTER_16_01, + PMIC_FG_NTER_00, + PMIC_FG_BLTR_31_16, + PMIC_FG_BLTR_15_00, + PMIC_FG_BFTR_31_16, + PMIC_FG_BFTR_15_00, + PMIC_FG_CURRENT_OUT, + PMIC_FG_ADJUST_OFFSET_VALUE, + PMIC_FG_OFFSET, + PMIC_RG_FGANALOGTEST, + PMIC_RG_FGINTMODE, + PMIC_RG_SPARE, + PMIC_FG_OSR, + PMIC_FG_ADJ_OFFSET_EN, + PMIC_FG_ADC_AUTORST, + PMIC_FG_FIR1BYPASS, + PMIC_FG_FIR2BYPASS, + PMIC_FG_L_CUR_INT_STS, + PMIC_FG_H_CUR_INT_STS, + PMIC_FG_L_INT_STS, + PMIC_FG_H_INT_STS, + PMIC_FG_ADC_RSTDETECT, + PMIC_FG_SLP_EN, + PMIC_FG_ZCV_DET_EN, + PMIC_RG_FG_AUXADC_R, + PMIC_DA_FGADC_EN, + PMIC_DA_FGCAL_EN, + PMIC_DA_FG_RST, + PMIC_FG_CIC2, + PMIC_FG_SLP_CUR_TH, + PMIC_FG_SLP_TIME, + PMIC_FG_SRCVOLTEN_FTIME, + PMIC_FG_DET_TIME, + PMIC_FG_ZCV_CAR_34_19, + PMIC_FG_ZCV_CAR_18_03, + PMIC_FG_ZCV_CAR_02_00, + PMIC_FG_ZCV_CURR, + PMIC_FG_R_CURR, + PMIC_FG_MODE, + PMIC_FG_RST_SW, + PMIC_FG_FGCAL_EN_SW, + PMIC_FG_FGADC_EN_SW, + PMIC_FG_RSV1, + PMIC_FG_TEST_MODE0, + PMIC_FG_TEST_MODE1, + PMIC_FG_GAIN, + PMIC_FG_CUR_HTH, + PMIC_FG_CUR_LTH, + PMIC_FG_ZCV_DET_TIME, + PMIC_FG_ZCV_CAR_TH_33_19, + PMIC_FG_ZCV_CAR_TH_18_03, + PMIC_FG_ZCV_CAR_TH_02_00, + PMIC_SYSTEM_INFO_CON0, + PMIC_SYSTEM_INFO_CON1, + PMIC_SYSTEM_INFO_CON2, + PMIC_SYSTEM_INFO_CON3, + PMIC_SYSTEM_INFO_CON4, + PMIC_RG_AUDDACLPWRUP_VAUDP15, + PMIC_RG_AUDDACRPWRUP_VAUDP15, + PMIC_RG_AUD_DAC_PWR_UP_VA28, + PMIC_RG_AUD_DAC_PWL_UP_VA28, + PMIC_RG_AUDHSPWRUP_VAUDP15, + PMIC_RG_AUDHPLPWRUP_VAUDP15, + PMIC_RG_AUDHPRPWRUP_VAUDP15, + PMIC_RG_AUDHSMUXINPUTSEL_VAUDP15, + PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP15, + PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP15, + PMIC_RG_AUDHSSCDISABLE_VAUDP15, + PMIC_RG_AUDHPLSCDISABLE_VAUDP15, + PMIC_RG_AUDHPRSCDISABLE_VAUDP15, + PMIC_RG_AUDHPLBSCCURRENT_VAUDP15, + PMIC_RG_AUDHPRBSCCURRENT_VAUDP15, + PMIC_RG_AUDHSBSCCURRENT_VAUDP15, + PMIC_RG_AUDHPSTARTUP_VAUDP15, + PMIC_RG_AUDHSSTARTUP_VAUDP15, + PMIC_RG_PRECHARGEBUF_EN_VAUDP15, + PMIC_RG_HPINPUTSTBENH_VAUDP15, + PMIC_RG_HPOUTPUTSTBENH_VAUDP15, + PMIC_RG_HPINPUTRESET0_VAUDP15, + PMIC_RG_HPOUTPUTRESET0_VAUDP15, + PMIC_RG_HPOUT_SHORTVCM_VAUDP15, + PMIC_RG_HSINPUTSTBENH_VAUDP15, + PMIC_RG_HSOUTPUTSTBENH_VAUDP15, + PMIC_RG_HSINPUTRESET0_VAUDP15, + PMIC_RG_HSOUTPUTRESET0_VAUDP15, + PMIC_RG_HPOUTSTB_RSEL_VAUDP15, + PMIC_RG_HSOUT_SHORTVCM_VAUDP15, + PMIC_RG_AUDHPLTRIM_VAUDP15, + PMIC_RG_AUDHPRTRIM_VAUDP15, + PMIC_RG_AUDHPTRIM_EN_VAUDP15, + PMIC_RG_AUDHPLFINETRIM_VAUDP15, + PMIC_RG_AUDHPRFINETRIM_VAUDP15, + PMIC_RG_AUDTRIMBUF_EN_VAUDP15, + PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP15, + PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP15, + PMIC_RG_AUDHPSPKDET_EN_VAUDP15, + PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP15, + PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP15, + PMIC_RG_ABIDEC_RESERVED_VA28, + PMIC_RG_ABIDEC_RESERVED_VAUDP15, + PMIC_RG_AUDBIASADJ_0_VAUDP15, + PMIC_RG_AUDBIASADJ_1_VAUDP15, + PMIC_RG_AUDIBIASPWRDN_VAUDP15, + PMIC_RG_RSTB_DECODER_VA28, + PMIC_RG_RSTB_ENCODER_VA28, + PMIC_RG_SEL_DECODER_96K_VA28, + PMIC_RG_SEL_ENCODER_96K_VA28, + PMIC_RG_SEL_DELAY_VCORE, + PMIC_RG_HCLDO_EN_VA18, + PMIC_RG_LCLDO_EN_VA18, + PMIC_RG_LCLDO_ENC_EN_VA28, + PMIC_RG_VA33REFGEN_EN_VA18, + PMIC_RG_HCLDO_PDDIS_EN_VA18, + PMIC_RG_HCLDO_REMOTE_SENSE_VA18, + PMIC_RG_LCLDO_PDDIS_EN_VA18, + PMIC_RG_LCLDO_REMOTE_SENSE_VA18, + PMIC_RG_LCLDO_VOSEL_VA18, + PMIC_RG_HCLDO_VOSEL_VA18, + PMIC_RG_LCLDO_ENC_PDDIS_EN_VA28, + PMIC_RG_LCLDO_ENC_REMOTE_SENSE_VA28, + PMIC_RG_VA28REFGEN_EN_VA28, + PMIC_RG_AUDPMU_RESERVED_VA28, + PMIC_RG_AUDPMU_RESERVED_VA18, + PMIC_RG_AUDPMU_RESERVED_VAUDP15, + PMIC_RG_NVREG_EN_VAUDP15, + PMIC_RG_NVREG_PULL0V_VAUDP15, + PMIC_RG_AUDGLB_PWRDN_VA28, + PMIC_RG_AUDPREAMPLON, + PMIC_RG_AUDPREAMPLDCCEN, + PMIC_RG_AUDPREAMPLDCRPECHARGE, + PMIC_RG_AUDPREAMPLPGATEST, + PMIC_RG_AUDPREAMPLVSCALE, + PMIC_RG_AUDPREAMPLINPUTSEL, + PMIC_RG_AUDADCLPWRUP, + PMIC_RG_AUDADCLINPUTSEL, + PMIC_RG_AUDPREAMPRON, + PMIC_RG_AUDPREAMPRDCCEN, + PMIC_RG_AUDPREAMPRDCRPECHARGE, + PMIC_RG_AUDPREAMPRPGATEST, + PMIC_RG_AUDPREAMPRVSCALE, + PMIC_RG_AUDPREAMPRINPUTSEL, + PMIC_RG_AUDADCRPWRUP, + PMIC_RG_AUDADCRINPUTSEL, + PMIC_RG_AUDULHALFBIAS, + PMIC_RG_AUDGLBMADLPWEN, + PMIC_RG_AUDPREAMPLPEN, + PMIC_RG_AUDADC1STSTAGELPEN, + PMIC_RG_AUDADC2NDSTAGELPEN, + PMIC_RG_AUDADCFLASHLPEN, + PMIC_RG_AUDPREAMPIDDTEST, + PMIC_RG_AUDADC1STSTAGEIDDTEST, + PMIC_RG_AUDADC2NDSTAGEIDDTEST, + PMIC_RG_AUDADCREFBUFIDDTEST, + PMIC_RG_AUDADCFLASHIDDTEST, + PMIC_RG_AUDADCDAC0P25FS, + PMIC_RG_AUDADCCLKSEL, + PMIC_RG_AUDADCCLKSOURCE, + PMIC_RG_AUDADCCLKGENMODE, + PMIC_RG_AUDPREAMPAAFEN, + PMIC_RG_DCCVCMBUFLPMODSEL, + PMIC_RG_DCCVCMBUFLPSWEN, + PMIC_RG_AUDSPAREPGA, + PMIC_RG_AUDADC1STSTAGESDENB, + PMIC_RG_AUDADC2NDSTAGERESET, + PMIC_RG_AUDADC3RDSTAGERESET, + PMIC_RG_AUDADCFSRESET, + PMIC_RG_AUDADCWIDECM, + PMIC_RG_AUDADCNOPATEST, + PMIC_RG_AUDADCBYPASS, + PMIC_RG_AUDADCFFBYPASS, + PMIC_RG_AUDADCDACFBCURRENT, + PMIC_RG_AUDADCDACIDDTEST, + PMIC_RG_AUDADCDACNRZ, + PMIC_RG_AUDADCNODEM, + PMIC_RG_AUDADCDACTEST, + PMIC_RG_AUDADCTESTDATA, + PMIC_RG_AUDRCTUNEL, + PMIC_RG_AUDRCTUNELSEL, + PMIC_RG_AUDRCTUNER, + PMIC_RG_AUDRCTUNERSEL, + PMIC_RG_AUDSPAREVA28, + PMIC_RG_AUDSPAREVA18, + PMIC_RG_AUDENCSPAREVA28, + PMIC_RG_AUDENCSPAREVA18, + PMIC_RG_AUDDIGMICEN, + PMIC_RG_AUDDIGMICBIAS, + PMIC_RG_DMICHPCLKEN, + PMIC_RG_AUDDIGMICPDUTY, + PMIC_RG_AUDDIGMICNDUTY, + PMIC_RG_DMICMONEN, + PMIC_RG_DMICMONSEL, + PMIC_RG_AUDSPAREVMIC, + PMIC_RG_AUDPWDBMICBIAS0, + PMIC_RG_AUDMICBIAS0DCSWPEN, + PMIC_RG_AUDMICBIAS0DCSWNEN, + PMIC_RG_AUDMICBIAS0BYPASSEN, + PMIC_RG_AUDPWDBMICBIAS1, + PMIC_RG_AUDMICBIAS1DCSWPEN, + PMIC_RG_AUDMICBIAS1DCSWNEN, + PMIC_RG_AUDMICBIAS1BYPASSEN, + PMIC_RG_AUDMICBIASVREF, + PMIC_RG_AUDMICBIASLOWPEN, + PMIC_RG_BANDGAPGEN, + PMIC_RG_AUDPREAMPLGAIN, + PMIC_RG_AUDPREAMPRGAIN, + PMIC_RG_DIVCKS_CHG, + PMIC_RG_DIVCKS_ON, + PMIC_RG_DIVCKS_PRG, + PMIC_RG_DIVCKS_PWD_NCP, + PMIC_RG_DIVCKS_PWD_NCP_ST_SEL, + PMIC_XO_EXTBUF1_MODE, + PMIC_XO_EXTBUF1_EN_M, + PMIC_XO_EXTBUF2_MODE, + PMIC_XO_EXTBUF2_EN_M, + PMIC_XO_EXTBUF3_MODE, + PMIC_XO_EXTBUF3_EN_M, + PMIC_XO_EXTBUF4_MODE, + PMIC_XO_EXTBUF4_EN_M, + PMIC_XO_BB_LPM_EN, + PMIC_XO_ENBB_MAN, + PMIC_XO_ENBB_EN_M, + PMIC_XO_CLKSEL_MAN, + PMIC_DCXO_CW00_SET, + PMIC_DCXO_CW00_CLR, + PMIC_XO_CLKSEL_EN_M, + PMIC_XO_EXTBUF1_CKG_MAN, + PMIC_XO_EXTBUF1_CKG_EN_M, + PMIC_XO_EXTBUF2_CKG_MAN, + PMIC_XO_EXTBUF2_CKG_EN_M, + PMIC_XO_EXTBUF3_CKG_MAN, + PMIC_XO_EXTBUF3_CKG_EN_M, + PMIC_XO_EXTBUF4_CKG_MAN, + PMIC_XO_EXTBUF4_CKG_EN_M, + PMIC_XO_INTBUF_MAN, + PMIC_XO_PBUF_EN_M, + PMIC_XO_IBUF_EN_M, + PMIC_XO_LPMBUF_MAN, + PMIC_XO_LPM_PREBUF_EN_M, + PMIC_XO_LPBUF_EN_M, + PMIC_XO_AUDIO_EN_M, + PMIC_XO_EN32K_MAN, + PMIC_XO_EN32K_M, + PMIC_XO_XMODE_MAN, + PMIC_XO_XMODE_M, + PMIC_XO_STRUP_MODE, + PMIC_XO_AAC_FPM_TIME, + PMIC_XO_AAC_MODE_LPM, + PMIC_XO_AAC_MODE_FPM, + PMIC_XO_EN26M_OFFSQ_EN, + PMIC_XO_LDOCAL_EN, + PMIC_XO_CBANK_SYNC_DYN, + PMIC_XO_26MLP_MAN_EN, + PMIC_XO_OPMODE_MAN, + PMIC_XO_BUFLDO13_VSET_M, + PMIC_XO_RESERVED0, + PMIC_XO_LPM_ISEL_MAN, + PMIC_XO_FPM_ISEL_MAN, + PMIC_XO_CDAC_FPM, + PMIC_XO_CDAC_LPM, + PMIC_XO_32KDIV_NFRAC_FPM, + PMIC_XO_COFST_FPM, + PMIC_XO_32KDIV_NFRAC_LPM, + PMIC_XO_COFST_LPM, + PMIC_XO_CORE_MAN, + PMIC_XO_CORE_EN_M, + PMIC_XO_CORE_TURBO_EN_M, + PMIC_XO_CORE_AAC_EN_M, + PMIC_XO_STARTUP_EN_M, + PMIC_XO_CORE_VBFPM_EN_M, + PMIC_XO_CORE_VBLPM_EN_M, + PMIC_XO_LPMBIAS_EN_M, + PMIC_XO_VTCGEN_EN_M, + PMIC_XO_IAAC_COMP_EN_M, + PMIC_XO_IFPM_COMP_EN_M, + PMIC_XO_ILPM_COMP_EN_M, + PMIC_XO_CORE_BYPCAS_FPM, + PMIC_XO_CORE_GMX2_FPM, + PMIC_XO_CORE_IDAC_FPM, + PMIC_XO_AAC_COMP_MAN, + PMIC_XO_AAC_EN_M, + PMIC_XO_AAC_MONEN_M, + PMIC_XO_COMP_EN_M, + PMIC_XO_COMP_TSTEN_M, + PMIC_XO_AAC_HV_FPM, + PMIC_XO_AAC_IBIAS_FPM, + PMIC_XO_AAC_VOFST_FPM, + PMIC_XO_AAC_COMP_HV_FPM, + PMIC_XO_AAC_VSEL_FPM, + PMIC_XO_AAC_COMP_POL, + PMIC_XO_CORE_BYPCAS_LPM, + PMIC_XO_CORE_GMX2_LPM, + PMIC_XO_CORE_IDAC_LPM, + PMIC_XO_AAC_COMP_HV_LPM, + PMIC_XO_AAC_VSEL_LPM, + PMIC_XO_AAC_HV_LPM, + PMIC_XO_AAC_IBIAS_LPM, + PMIC_XO_AAC_VOFST_LPM, + PMIC_XO_AAC_FPM_SWEN, + PMIC_XO_SWRST, + PMIC_XO_32KDIV_SWRST, + PMIC_XO_32KDIV_RATIO_MAN, + PMIC_XO_32KDIV_TEST_EN, + PMIC_XO_CBANK_SYNC_MAN, + PMIC_XO_CBANK_SYNC_EN_M, + PMIC_XO_CTL_SYNC_MAN, + PMIC_XO_CTL_SYNC_EN_M, + PMIC_XO_LDO_MAN, + PMIC_XO_LDOPBUF_EN_M, + PMIC_XO_LDOPBUF_VSET_M, + PMIC_XO_LDOVTST_EN_M, + PMIC_XO_TEST_VCAL_EN_M, + PMIC_XO_VBIST_EN_M, + PMIC_XO_VTEST_SEL_MUX, + PMIC_RG_XO_CORE_OSCTD, + PMIC_RG_XO_THADC_EN, + PMIC_RG_XO_SYNC_CKPOL, + PMIC_RG_XO_CBANK_POL, + PMIC_RG_XO_CBANK_SYNC_BYP, + PMIC_RG_XO_CTL_POL, + PMIC_RG_XO_CTL_SYNC_BYP, + PMIC_RG_XO_LPBUF_INV, + PMIC_RG_XO_LDOPBUF_BYP, + PMIC_RG_XO_LDOPBUF_ENCL, + PMIC_RG_XO_VGBIAS_VSET, + PMIC_RG_XO_PBUF_ISET, + PMIC_RG_XO_IBUF_ISET, + PMIC_RG_XO_BUFLDO13_ENCL, + PMIC_RG_XO_BUFLDO13_IBX2, + PMIC_RG_XO_BUFLDO13_IX2, + PMIC_XO_RESERVED1, + PMIC_RG_XO_BUFLDO24_ENCL, + PMIC_RG_XO_BUFLDO24_IBX2, + PMIC_XO_BUFLDO24_VSET_M, + PMIC_RG_XO_EXTBUF1_HD, + PMIC_RG_XO_EXTBUF1_ISET, + PMIC_RG_XO_EXTBUF2_HD, + PMIC_RG_XO_EXTBUF2_ISET, + PMIC_RG_XO_EXTBUF3_HD, + PMIC_RG_XO_EXTBUF3_ISET, + PMIC_RG_XO_EXTBUF4_HD, + PMIC_RG_XO_EXTBUF4_ISET, + PMIC_RG_XO_LPM_PREBUF_ISET, + PMIC_RG_XO_AUDIO_ATTEN, + PMIC_RG_XO_AUDIO_ISET, + PMIC_XO_EXTBUF4_CLKSEL_MAN, + PMIC_RG_XO_RESERVED0, + PMIC_XO_VIO18PG_BUFEN, + PMIC_RG_XO_RESERVED1, + PMIC_XO_CAL_EN_MAN, + PMIC_XO_CAL_EN_M, + PMIC_XO_STATIC_AUXOUT_SEL, + PMIC_XO_AUXOUT_SEL, + PMIC_XO_STATIC_AUXOUT, + PMIC_AUXADC_ADC_OUT_CH0, + PMIC_AUXADC_ADC_RDY_CH0, + PMIC_AUXADC_ADC_OUT_CH1, + PMIC_AUXADC_ADC_RDY_CH1, + PMIC_AUXADC_ADC_OUT_CH2, + PMIC_AUXADC_ADC_RDY_CH2, + PMIC_AUXADC_ADC_OUT_CH3, + PMIC_AUXADC_ADC_RDY_CH3, + PMIC_AUXADC_ADC_OUT_CH4, + PMIC_AUXADC_ADC_RDY_CH4, + PMIC_AUXADC_ADC_OUT_CH5, + PMIC_AUXADC_ADC_RDY_CH5, + PMIC_AUXADC_ADC_OUT_CH6, + PMIC_AUXADC_ADC_RDY_CH6, + PMIC_AUXADC_ADC_OUT_CH7, + PMIC_AUXADC_ADC_RDY_CH7, + PMIC_AUXADC_ADC_OUT_CH8, + PMIC_AUXADC_ADC_RDY_CH8, + PMIC_AUXADC_ADC_OUT_CH9, + PMIC_AUXADC_ADC_RDY_CH9, + PMIC_AUXADC_ADC_OUT_CH10, + PMIC_AUXADC_ADC_RDY_CH10, + PMIC_AUXADC_ADC_OUT_CH11, + PMIC_AUXADC_ADC_RDY_CH11, + PMIC_AUXADC_ADC_OUT_CH12_15, + PMIC_AUXADC_ADC_RDY_CH12_15, + PMIC_AUXADC_ADC_OUT_THR_HW, + PMIC_AUXADC_ADC_RDY_THR_HW, + PMIC_AUXADC_ADC_OUT_LBAT, + PMIC_AUXADC_ADC_RDY_LBAT, + PMIC_AUXADC_ADC_OUT_LBAT2, + PMIC_AUXADC_ADC_RDY_LBAT2, + PMIC_AUXADC_ADC_OUT_CH7_BY_GPS, + PMIC_AUXADC_ADC_RDY_CH7_BY_GPS, + PMIC_AUXADC_ADC_OUT_CH7_BY_MD, + PMIC_AUXADC_ADC_RDY_CH7_BY_MD, + PMIC_AUXADC_ADC_OUT_CH7_BY_AP, + PMIC_AUXADC_ADC_RDY_CH7_BY_AP, + PMIC_AUXADC_ADC_OUT_CH4_BY_MD, + PMIC_AUXADC_ADC_RDY_CH4_BY_MD, + PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR, + PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR, + PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR, + PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR, + PMIC_AUXADC_ADC_OUT_CH0_BY_MD, + PMIC_AUXADC_ADC_RDY_CH0_BY_MD, + PMIC_AUXADC_ADC_OUT_CH0_BY_AP, + PMIC_AUXADC_ADC_RDY_CH0_BY_AP, + PMIC_AUXADC_ADC_OUT_CH1_BY_MD, + PMIC_AUXADC_ADC_RDY_CH1_BY_MD, + PMIC_AUXADC_ADC_OUT_CH1_BY_AP, + PMIC_AUXADC_ADC_RDY_CH1_BY_AP, + PMIC_AUXADC_ADC_OUT_VISMPS0, + PMIC_AUXADC_ADC_RDY_VISMPS0, + PMIC_AUXADC_ADC_OUT_FGADC1, + PMIC_AUXADC_ADC_RDY_FGADC1, + PMIC_AUXADC_ADC_OUT_FGADC2, + PMIC_AUXADC_ADC_RDY_FGADC2, + PMIC_AUXADC_ADC_OUT_IMP, + PMIC_AUXADC_ADC_RDY_IMP, + PMIC_AUXADC_ADC_OUT_IMP_AVG, + PMIC_AUXADC_ADC_RDY_IMP_AVG, + PMIC_AUXADC_ADC_OUT_RAW, + PMIC_AUXADC_ADC_OUT_MDRT, + PMIC_AUXADC_ADC_RDY_MDRT, + PMIC_AUXADC_ADC_OUT_MDBG, + PMIC_AUXADC_ADC_RDY_MDBG, + PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS, + PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS, + PMIC_AUXADC_ADC_OUT_DCXO_BY_MD, + PMIC_AUXADC_ADC_RDY_DCXO_BY_MD, + PMIC_AUXADC_ADC_OUT_DCXO_BY_AP, + PMIC_AUXADC_ADC_RDY_DCXO_BY_AP, + PMIC_AUXADC_ADC_OUT_DCXO_MDRT, + PMIC_AUXADC_ADC_RDY_DCXO_MDRT, + PMIC_AUXADC_ADC_OUT_NAG, + PMIC_AUXADC_ADC_RDY_NAG, + PMIC_AUXADC_ADC_OUT_TYPEC_H, + PMIC_AUXADC_ADC_RDY_TYPEC_H, + PMIC_AUXADC_ADC_OUT_TYPEC_L, + PMIC_AUXADC_ADC_RDY_TYPEC_L, + PMIC_AUXADC_BUF_OUT_00, + PMIC_AUXADC_BUF_RDY_00, + PMIC_AUXADC_BUF_OUT_01, + PMIC_AUXADC_BUF_RDY_01, + PMIC_AUXADC_BUF_OUT_02, + PMIC_AUXADC_BUF_RDY_02, + PMIC_AUXADC_BUF_OUT_03, + PMIC_AUXADC_BUF_RDY_03, + PMIC_AUXADC_BUF_OUT_04, + PMIC_AUXADC_BUF_RDY_04, + PMIC_AUXADC_BUF_OUT_05, + PMIC_AUXADC_BUF_RDY_05, + PMIC_AUXADC_BUF_OUT_06, + PMIC_AUXADC_BUF_RDY_06, + PMIC_AUXADC_BUF_OUT_07, + PMIC_AUXADC_BUF_RDY_07, + PMIC_AUXADC_BUF_OUT_08, + PMIC_AUXADC_BUF_RDY_08, + PMIC_AUXADC_BUF_OUT_09, + PMIC_AUXADC_BUF_RDY_09, + PMIC_AUXADC_BUF_OUT_10, + PMIC_AUXADC_BUF_RDY_10, + PMIC_AUXADC_BUF_OUT_11, + PMIC_AUXADC_BUF_RDY_11, + PMIC_AUXADC_BUF_OUT_12, + PMIC_AUXADC_BUF_RDY_12, + PMIC_AUXADC_BUF_OUT_13, + PMIC_AUXADC_BUF_RDY_13, + PMIC_AUXADC_BUF_OUT_14, + PMIC_AUXADC_BUF_RDY_14, + PMIC_AUXADC_BUF_OUT_15, + PMIC_AUXADC_BUF_RDY_15, + PMIC_AUXADC_BUF_OUT_16, + PMIC_AUXADC_BUF_RDY_16, + PMIC_AUXADC_BUF_OUT_17, + PMIC_AUXADC_BUF_RDY_17, + PMIC_AUXADC_BUF_OUT_18, + PMIC_AUXADC_BUF_RDY_18, + PMIC_AUXADC_BUF_OUT_19, + PMIC_AUXADC_BUF_RDY_19, + PMIC_AUXADC_BUF_OUT_20, + PMIC_AUXADC_BUF_RDY_20, + PMIC_AUXADC_BUF_OUT_21, + PMIC_AUXADC_BUF_RDY_21, + PMIC_AUXADC_BUF_OUT_22, + PMIC_AUXADC_BUF_RDY_22, + PMIC_AUXADC_BUF_OUT_23, + PMIC_AUXADC_BUF_RDY_23, + PMIC_AUXADC_BUF_OUT_24, + PMIC_AUXADC_BUF_RDY_24, + PMIC_AUXADC_BUF_OUT_25, + PMIC_AUXADC_BUF_RDY_25, + PMIC_AUXADC_BUF_OUT_26, + PMIC_AUXADC_BUF_RDY_26, + PMIC_AUXADC_BUF_OUT_27, + PMIC_AUXADC_BUF_RDY_27, + PMIC_AUXADC_BUF_OUT_28, + PMIC_AUXADC_BUF_RDY_28, + PMIC_AUXADC_BUF_OUT_29, + PMIC_AUXADC_BUF_RDY_29, + PMIC_AUXADC_BUF_OUT_30, + PMIC_AUXADC_BUF_RDY_30, + PMIC_AUXADC_BUF_OUT_31, + PMIC_AUXADC_BUF_RDY_31, + PMIC_AUXADC_ADC_BUSY_IN, + PMIC_AUXADC_ADC_BUSY_IN_LBAT, + PMIC_AUXADC_ADC_BUSY_IN_LBAT2, + PMIC_AUXADC_ADC_BUSY_IN_VISMPS0, + PMIC_AUXADC_ADC_BUSY_IN_WAKEUP, + PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT, + PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP, + PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD, + PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS, + PMIC_AUXADC_ADC_BUSY_IN_MDRT, + PMIC_AUXADC_ADC_BUSY_IN_MDBG, + PMIC_AUXADC_ADC_BUSY_IN_SHARE, + PMIC_AUXADC_ADC_BUSY_IN_IMP, + PMIC_AUXADC_ADC_BUSY_IN_FGADC1, + PMIC_AUXADC_ADC_BUSY_IN_FGADC2, + PMIC_AUXADC_ADC_BUSY_IN_GPS_AP, + PMIC_AUXADC_ADC_BUSY_IN_GPS_MD, + PMIC_AUXADC_ADC_BUSY_IN_GPS, + PMIC_AUXADC_ADC_BUSY_IN_THR_HW, + PMIC_AUXADC_ADC_BUSY_IN_THR_MD, + PMIC_AUXADC_ADC_BUSY_IN_TYPEC_H, + PMIC_AUXADC_ADC_BUSY_IN_TYPEC_L, + PMIC_AUXADC_ADC_BUSY_IN_NAG, + PMIC_AUXADC_RQST_CH0, + PMIC_AUXADC_RQST_CH1, + PMIC_AUXADC_RQST_CH2, + PMIC_AUXADC_RQST_CH3, + PMIC_AUXADC_RQST_CH4, + PMIC_AUXADC_RQST_CH5, + PMIC_AUXADC_RQST_CH6, + PMIC_AUXADC_RQST_CH7, + PMIC_AUXADC_RQST_CH8, + PMIC_AUXADC_RQST_CH9, + PMIC_AUXADC_RQST_CH10, + PMIC_AUXADC_RQST_CH11, + PMIC_AUXADC_RQST_CH12, + PMIC_AUXADC_RQST_CH13, + PMIC_AUXADC_RQST_CH14, + PMIC_AUXADC_RQST_CH15, + PMIC_AUXADC_RQST0_SET, + PMIC_AUXADC_RQST0_CLR, + PMIC_AUXADC_RQST_CH0_BY_MD, + PMIC_AUXADC_RQST_CH1_BY_MD, + PMIC_AUXADC_RQST_RSV0, + PMIC_AUXADC_RQST_CH4_BY_MD, + PMIC_AUXADC_RQST_CH7_BY_MD, + PMIC_AUXADC_RQST_CH7_BY_GPS, + PMIC_AUXADC_RQST_DCXO_BY_MD, + PMIC_AUXADC_RQST_DCXO_BY_GPS, + PMIC_AUXADC_RQST_RSV1, + PMIC_AUXADC_RQST1_SET, + PMIC_AUXADC_RQST1_CLR, + PMIC_AUXADC_CK_ON_EXTD, + PMIC_AUXADC_SRCLKEN_SRC_SEL, + PMIC_AUXADC_ADC_PWDB, + PMIC_AUXADC_ADC_PWDB_SWCTRL, + PMIC_AUXADC_STRUP_CK_ON_ENB, + PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, + PMIC_AUXADC_SRCLKEN_CK_EN, + PMIC_AUXADC_CK_AON_GPS, + PMIC_AUXADC_CK_AON_MD, + PMIC_AUXADC_CK_AON, + PMIC_AUXADC_CON0_SET, + PMIC_AUXADC_CON0_CLR, + PMIC_AUXADC_AVG_NUM_SMALL, + PMIC_AUXADC_AVG_NUM_LARGE, + PMIC_AUXADC_SPL_NUM, + PMIC_AUXADC_AVG_NUM_SEL, + PMIC_AUXADC_AVG_NUM_SEL_SHARE, + PMIC_AUXADC_AVG_NUM_SEL_LBAT, + PMIC_AUXADC_AVG_NUM_SEL_VISMPS, + PMIC_AUXADC_AVG_NUM_SEL_WAKEUP, + PMIC_AUXADC_SPL_NUM_LARGE, + PMIC_AUXADC_SPL_NUM_SLEEP, + PMIC_AUXADC_SPL_NUM_SLEEP_SEL, + PMIC_AUXADC_SPL_NUM_SEL, + PMIC_AUXADC_SPL_NUM_SEL_SHARE, + PMIC_AUXADC_SPL_NUM_SEL_LBAT, + PMIC_AUXADC_SPL_NUM_SEL_VISMPS, + PMIC_AUXADC_SPL_NUM_SEL_WAKEUP, + PMIC_AUXADC_TRIM_CH0_SEL, + PMIC_AUXADC_TRIM_CH1_SEL, + PMIC_AUXADC_TRIM_CH2_SEL, + PMIC_AUXADC_TRIM_CH3_SEL, + PMIC_AUXADC_TRIM_CH4_SEL, + PMIC_AUXADC_TRIM_CH5_SEL, + PMIC_AUXADC_TRIM_CH6_SEL, + PMIC_AUXADC_TRIM_CH7_SEL, + PMIC_AUXADC_TRIM_CH8_SEL, + PMIC_AUXADC_TRIM_CH9_SEL, + PMIC_AUXADC_TRIM_CH10_SEL, + PMIC_AUXADC_TRIM_CH11_SEL, + PMIC_AUXADC_ADC_2S_COMP_ENB, + PMIC_AUXADC_ADC_TRIM_COMP, + PMIC_AUXADC_SW_GAIN_TRIM, + PMIC_AUXADC_SW_OFFSET_TRIM, + PMIC_AUXADC_RNG_EN, + PMIC_AUXADC_DATA_REUSE_SEL, + PMIC_AUXADC_TEST_MODE, + PMIC_AUXADC_BIT_SEL, + PMIC_AUXADC_START_SW, + PMIC_AUXADC_START_SWCTRL, + PMIC_AUXADC_TS_VBE_SEL, + PMIC_AUXADC_TS_VBE_SEL_SWCTRL, + PMIC_AUXADC_VBUF_EN, + PMIC_AUXADC_VBUF_EN_SWCTRL, + PMIC_AUXADC_OUT_SEL, + PMIC_AUXADC_DA_DAC, + PMIC_AUXADC_DA_DAC_SWCTRL, + PMIC_AD_AUXADC_COMP, + PMIC_RG_VBUF_EXTEN, + PMIC_RG_VBUF_CALEN, + PMIC_RG_VBUF_BYP, + PMIC_RG_AUX_RSV, + PMIC_RG_AUXADC_CALI, + PMIC_RG_VBUF_EN, + PMIC_RG_VBE_SEL, + PMIC_AUXADC_ADCIN_VSEN_EN, + PMIC_AUXADC_ADCIN_VBAT_EN, + PMIC_AUXADC_ADCIN_VSEN_MUX_EN, + PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN, + PMIC_AUXADC_ADCIN_CHR_EN, + PMIC_AUXADC_ADCIN_BATON_TDET_EN, + PMIC_AUXADC_ACCDET_ANASWCTRL_EN, + PMIC_AUXADC_DIG0_RSV0, + PMIC_AUXADC_CHSEL, + PMIC_AUXADC_SWCTRL_EN, + PMIC_AUXADC_SOURCE_LBAT_SEL, + PMIC_AUXADC_SOURCE_LBAT2_SEL, + PMIC_AUXADC_DIG0_RSV2, + PMIC_AUXADC_DIG1_RSV2, + PMIC_AUXADC_DAC_EXTD, + PMIC_AUXADC_DAC_EXTD_EN, + PMIC_AUXADC_PMU_THR_PDN_SW, + PMIC_AUXADC_PMU_THR_PDN_SEL, + PMIC_AUXADC_PMU_THR_PDN_STATUS, + PMIC_AUXADC_DIG0_RSV1, + PMIC_AUXADC_START_SHADE_NUM, + PMIC_AUXADC_START_SHADE_EN, + PMIC_AUXADC_START_SHADE_SEL, + PMIC_AUXADC_AUTORPT_PRD, + PMIC_AUXADC_AUTORPT_EN, + PMIC_AUXADC_LBAT_DEBT_MAX, + PMIC_AUXADC_LBAT_DEBT_MIN, + PMIC_AUXADC_LBAT_DET_PRD_15_0, + PMIC_AUXADC_LBAT_DET_PRD_19_16, + PMIC_AUXADC_LBAT_VOLT_MAX, + PMIC_AUXADC_LBAT_IRQ_EN_MAX, + PMIC_AUXADC_LBAT_EN_MAX, + PMIC_AUXADC_LBAT_MAX_IRQ_B, + PMIC_AUXADC_LBAT_VOLT_MIN, + PMIC_AUXADC_LBAT_IRQ_EN_MIN, + PMIC_AUXADC_LBAT_EN_MIN, + PMIC_AUXADC_LBAT_MIN_IRQ_B, + PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN, + PMIC_AUXADC_ACCDET_AUTO_SPL, + PMIC_AUXADC_ACCDET_AUTO_RQST_CLR, + PMIC_AUXADC_ACCDET_DIG1_RSV0, + PMIC_AUXADC_ACCDET_DIG0_RSV0, + PMIC_AUXADC_THR_DEBT_MAX, + PMIC_AUXADC_THR_DEBT_MIN, + PMIC_AUXADC_THR_DET_PRD_15_0, + PMIC_AUXADC_THR_DET_PRD_19_16, + PMIC_AUXADC_THR_VOLT_MAX, + PMIC_AUXADC_THR_IRQ_EN_MAX, + PMIC_AUXADC_THR_EN_MAX, + PMIC_AUXADC_THR_MAX_IRQ_B, + PMIC_AUXADC_THR_VOLT_MIN, + PMIC_AUXADC_THR_IRQ_EN_MIN, + PMIC_AUXADC_THR_EN_MIN, + PMIC_AUXADC_THR_MIN_IRQ_B, + PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN, + PMIC_EFUSE_GAIN_CH4_TRIM, + PMIC_EFUSE_OFFSET_CH4_TRIM, + PMIC_EFUSE_GAIN_CH0_TRIM, + PMIC_EFUSE_OFFSET_CH0_TRIM, + PMIC_EFUSE_GAIN_CH7_TRIM, + PMIC_EFUSE_OFFSET_CH7_TRIM, + PMIC_AUXADC_FGADC_START_SW, + PMIC_AUXADC_FGADC_START_SEL, + PMIC_AUXADC_FGADC_R_SW, + PMIC_AUXADC_FGADC_R_SEL, + PMIC_AUXADC_DBG_DIG0_RSV2, + PMIC_AUXADC_DBG_DIG1_RSV2, + PMIC_AUXADC_IMPEDANCE_CNT, + PMIC_AUXADC_IMPEDANCE_CHSEL, + PMIC_AUXADC_IMPEDANCE_IRQ_CLR, + PMIC_AUXADC_IMPEDANCE_IRQ_STATUS, + PMIC_AUXADC_CLR_IMP_CNT_STOP, + PMIC_AUXADC_IMPEDANCE_MODE, + PMIC_AUXADC_IMP_AUTORPT_PRD, + PMIC_AUXADC_IMP_AUTORPT_EN, + PMIC_AUXADC_VISMPS0_DEBT_MAX, + PMIC_AUXADC_VISMPS0_DEBT_MIN, + PMIC_AUXADC_VISMPS0_DET_PRD_15_0, + PMIC_AUXADC_VISMPS0_DET_PRD_19_16, + PMIC_AUXADC_VISMPS0_VOLT_MAX, + PMIC_AUXADC_VISMPS0_IRQ_EN_MAX, + PMIC_AUXADC_VISMPS0_EN_MAX, + PMIC_AUXADC_VISMPS0_MAX_IRQ_B, + PMIC_AUXADC_VISMPS0_VOLT_MIN, + PMIC_AUXADC_VISMPS0_IRQ_EN_MIN, + PMIC_AUXADC_VISMPS0_EN_MIN, + PMIC_AUXADC_VISMPS0_MIN_IRQ_B, + PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN, + PMIC_AUXADC_LBAT2_DEBT_MAX, + PMIC_AUXADC_LBAT2_DEBT_MIN, + PMIC_AUXADC_LBAT2_DET_PRD_15_0, + PMIC_AUXADC_LBAT2_DET_PRD_19_16, + PMIC_AUXADC_LBAT2_VOLT_MAX, + PMIC_AUXADC_LBAT2_IRQ_EN_MAX, + PMIC_AUXADC_LBAT2_EN_MAX, + PMIC_AUXADC_LBAT2_MAX_IRQ_B, + PMIC_AUXADC_LBAT2_VOLT_MIN, + PMIC_AUXADC_LBAT2_IRQ_EN_MIN, + PMIC_AUXADC_LBAT2_EN_MIN, + PMIC_AUXADC_LBAT2_MIN_IRQ_B, + PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN, + PMIC_AUXADC_MDBG_DET_PRD, + PMIC_AUXADC_MDBG_DET_EN, + PMIC_AUXADC_MDBG_R_PTR, + PMIC_AUXADC_MDBG_W_PTR, + PMIC_AUXADC_MDBG_BUF_LENGTH, + PMIC_AUXADC_MDRT_DET_PRD, + PMIC_AUXADC_MDRT_DET_EN, + PMIC_AUXADC_MDRT_DET_WKUP_START_CNT, + PMIC_AUXADC_MDRT_DET_WKUP_START_CLR, + PMIC_AUXADC_MDRT_DET_WKUP_START, + PMIC_AUXADC_MDRT_DET_WKUP_START_SEL, + PMIC_AUXADC_MDRT_DET_WKUP_EN, + PMIC_AUXADC_MDRT_DET_SRCLKEN_IND, + PMIC_AUXADC_DCXO_MDRT_DET_PRD, + PMIC_AUXADC_DCXO_MDRT_DET_EN, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START, + PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND, + PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL, + PMIC_AUXADC_NAG_EN, + PMIC_AUXADC_NAG_CLR, + PMIC_AUXADC_NAG_VBAT1_SEL, + PMIC_AUXADC_NAG_PRD, + PMIC_AUXADC_NAG_IRQ_EN, + PMIC_AUXADC_NAG_C_DLTV_IRQ, + PMIC_AUXADC_NAG_ZCV, + PMIC_AUXADC_NAG_C_DLTV_TH_15_0, + PMIC_AUXADC_NAG_C_DLTV_TH_26_16, + PMIC_AUXADC_NAG_CNT_15_0, + PMIC_AUXADC_NAG_CNT_25_16, + PMIC_AUXADC_NAG_DLTV, + PMIC_AUXADC_NAG_C_DLTV_15_0, + PMIC_AUXADC_NAG_C_DLTV_26_16, + PMIC_AUXADC_TYPEC_H_DEBT_MAX, + PMIC_AUXADC_TYPEC_H_DEBT_MIN, + PMIC_AUXADC_TYPEC_H_DET_PRD_15_0, + PMIC_AUXADC_TYPEC_H_DET_PRD_19_16, + PMIC_AUXADC_TYPEC_H_VOLT_MAX, + PMIC_AUXADC_TYPEC_H_IRQ_EN_MAX, + PMIC_AUXADC_TYPEC_H_EN_MAX, + PMIC_AUXADC_TYPEC_H_MAX_IRQ_B, + PMIC_AUXADC_TYPEC_H_VOLT_MIN, + PMIC_AUXADC_TYPEC_H_IRQ_EN_MIN, + PMIC_AUXADC_TYPEC_H_EN_MIN, + PMIC_AUXADC_TYPEC_H_MIN_IRQ_B, + PMIC_AUXADC_TYPEC_H_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_TYPEC_H_DEBOUNCE_COUNT_MIN, + PMIC_AUXADC_TYPEC_L_DEBT_MAX, + PMIC_AUXADC_TYPEC_L_DEBT_MIN, + PMIC_AUXADC_TYPEC_L_DET_PRD_15_0, + PMIC_AUXADC_TYPEC_L_DET_PRD_19_16, + PMIC_AUXADC_TYPEC_L_VOLT_MAX, + PMIC_AUXADC_TYPEC_L_IRQ_EN_MAX, + PMIC_AUXADC_TYPEC_L_EN_MAX, + PMIC_AUXADC_TYPEC_L_MAX_IRQ_B, + PMIC_AUXADC_TYPEC_L_VOLT_MIN, + PMIC_AUXADC_TYPEC_L_IRQ_EN_MIN, + PMIC_AUXADC_TYPEC_L_EN_MIN, + PMIC_AUXADC_TYPEC_L_MIN_IRQ_B, + PMIC_AUXADC_TYPEC_L_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_TYPEC_L_DEBOUNCE_COUNT_MIN, + PMIC_RG_AUDACCDETVTHBCAL, + PMIC_RG_AUDACCDETVTHACAL, + PMIC_RG_AUDACCDETANASWCTRLENB, + PMIC_RG_ACCDETSEL, + PMIC_RG_AUDACCDETSWCTRL, + PMIC_RG_AUDACCDETMICBIAS1PULLLOW, + PMIC_RG_AUDACCDETTVDET, + PMIC_RG_AUDACCDETVIN1PULLLOW, + PMIC_AUDACCDETAUXADCSWCTRL, + PMIC_AUDACCDETAUXADCSWCTRL_SEL, + PMIC_RG_AUDACCDETMICBIAS0PULLLOW, + PMIC_RG_AUDACCDETRSV, + PMIC_ACCDET_EN, + PMIC_ACCDET_SEQ_INIT, + PMIC_ACCDET_EINTDET_EN, + PMIC_ACCDET_EINT_SEQ_INIT, + PMIC_ACCDET_NEGVDET_EN, + PMIC_ACCDET_NEGVDET_EN_CTRL, + PMIC_ACCDET_ANASWCTRL_SEL, + PMIC_ACCDET_CMP_PWM_EN, + PMIC_ACCDET_VTH_PWM_EN, + PMIC_ACCDET_MBIAS_PWM_EN, + PMIC_ACCDET_EINT_PWM_EN, + PMIC_ACCDET_CMP_PWM_IDLE, + PMIC_ACCDET_VTH_PWM_IDLE, + PMIC_ACCDET_MBIAS_PWM_IDLE, + PMIC_ACCDET_EINT_PWM_IDLE, + PMIC_ACCDET_PWM_WIDTH, + PMIC_ACCDET_PWM_THRESH, + PMIC_ACCDET_RISE_DELAY, + PMIC_ACCDET_FALL_DELAY, + PMIC_ACCDET_DEBOUNCE0, + PMIC_ACCDET_DEBOUNCE1, + PMIC_ACCDET_DEBOUNCE2, + PMIC_ACCDET_DEBOUNCE3, + PMIC_ACCDET_DEBOUNCE4, + PMIC_ACCDET_IVAL_CUR_IN, + PMIC_ACCDET_EINT_IVAL_CUR_IN, + PMIC_ACCDET_IVAL_SAM_IN, + PMIC_ACCDET_EINT_IVAL_SAM_IN, + PMIC_ACCDET_IVAL_MEM_IN, + PMIC_ACCDET_EINT_IVAL_MEM_IN, + PMIC_ACCDET_EINT_IVAL_SEL, + PMIC_ACCDET_IVAL_SEL, + PMIC_ACCDET_IRQ, + PMIC_ACCDET_NEGV_IRQ, + PMIC_ACCDET_EINT_IRQ, + PMIC_ACCDET_IRQ_CLR, + PMIC_ACCDET_NEGV_IRQ_CLR, + PMIC_ACCDET_EINT_IRQ_CLR, + PMIC_ACCDET_EINT_IRQ_POLARITY, + PMIC_ACCDET_TEST_MODE0, + PMIC_ACCDET_TEST_MODE1, + PMIC_ACCDET_TEST_MODE2, + PMIC_ACCDET_TEST_MODE3, + PMIC_ACCDET_TEST_MODE4, + PMIC_ACCDET_TEST_MODE5, + PMIC_ACCDET_PWM_SEL, + PMIC_ACCDET_IN_SW, + PMIC_ACCDET_CMP_EN_SW, + PMIC_ACCDET_VTH_EN_SW, + PMIC_ACCDET_MBIAS_EN_SW, + PMIC_ACCDET_PWM_EN_SW, + PMIC_ACCDET_IN, + PMIC_ACCDET_CUR_IN, + PMIC_ACCDET_SAM_IN, + PMIC_ACCDET_MEM_IN, + PMIC_ACCDET_STATE, + PMIC_ACCDET_MBIAS_CLK, + PMIC_ACCDET_VTH_CLK, + PMIC_ACCDET_CMP_CLK, + PMIC_DA_AUDACCDETAUXADCSWCTRL, + PMIC_ACCDET_EINT_DEB_SEL, + PMIC_ACCDET_EINT_DEBOUNCE, + PMIC_ACCDET_EINT_PWM_THRESH, + PMIC_ACCDET_EINT_PWM_WIDTH, + PMIC_ACCDET_NEGV_THRESH, + PMIC_ACCDET_EINT_PWM_FALL_DELAY, + PMIC_ACCDET_EINT_PWM_RISE_DELAY, + PMIC_ACCDET_TEST_MODE13, + PMIC_ACCDET_TEST_MODE12, + PMIC_ACCDET_NVDETECTOUT_SW, + PMIC_ACCDET_TEST_MODE11, + PMIC_ACCDET_TEST_MODE10, + PMIC_ACCDET_EINTCMPOUT_SW, + PMIC_ACCDET_TEST_MODE9, + PMIC_ACCDET_TEST_MODE8, + PMIC_ACCDET_AUXADC_CTRL_SW, + PMIC_ACCDET_TEST_MODE7, + PMIC_ACCDET_TEST_MODE6, + PMIC_ACCDET_EINTCMP_EN_SW, + PMIC_RG_NVCMPSWEN, + PMIC_RG_NVMODSEL, + PMIC_RG_SWBUFSWEN, + PMIC_RG_SWBUFMODSEL, + PMIC_RG_NVDETVTH, + PMIC_RG_NVDETCMPEN, + PMIC_RG_EINTCONFIGACCDET, + PMIC_RG_EINTCOMPVTH, + PMIC_ACCDET_EINT_STATE, + PMIC_ACCDET_AUXADC_DEBOUNCE_END, + PMIC_ACCDET_AUXADC_CONNECT_PRE, + PMIC_ACCDET_EINT_CUR_IN, + PMIC_ACCDET_EINT_SAM_IN, + PMIC_ACCDET_EINT_MEM_IN, + PMIC_AD_NVDETECTOUT, + PMIC_AD_EINTCMPOUT, + PMIC_DA_NI_EINTCMPEN, + PMIC_ACCDET_NEGV_COUNT_IN, + PMIC_ACCDET_NEGV_EN_FINAL, + PMIC_ACCDET_NEGV_COUNT_END, + PMIC_ACCDET_NEGV_MINU, + PMIC_ACCDET_NEGV_ADD, + PMIC_ACCDET_NEGV_CMP, + PMIC_ACCDET_CUR_DEB, + PMIC_ACCDET_EINT_CUR_DEB, + PMIC_ACCDET_RSV_CON0, + PMIC_ACCDET_RSV_CON1, + PMIC_ACCDET_AUXADC_CONNECT_TIME, + PMIC_RG_VCDT_HV_EN, + PMIC_RGS_CHR_LDO_DET, + PMIC_RG_PCHR_AUTOMODE, + PMIC_RG_CSDAC_EN, + PMIC_RG_CHR_EN, + PMIC_RGS_CHRDET, + PMIC_RGS_VCDT_LV_DET, + PMIC_RGS_VCDT_HV_DET, + PMIC_RG_VCDT_LV_VTH, + PMIC_RG_VCDT_HV_VTH, + PMIC_RG_VBAT_CV_EN, + PMIC_RG_VBAT_CC_EN, + PMIC_RG_CS_EN, + PMIC_RGS_CS_DET, + PMIC_RGS_VBAT_CV_DET, + PMIC_RGS_VBAT_CC_DET, + PMIC_RG_VBAT_CV_VTH, + PMIC_RG_VBAT_CC_VTH, + PMIC_RG_CS_VTH, + PMIC_RG_PCHR_TOHTC, + PMIC_RG_PCHR_TOLTC, + PMIC_RG_VBAT_OV_EN, + PMIC_RG_VBAT_OV_VTH, + PMIC_RG_VBAT_OV_DEG, + PMIC_RGS_VBAT_OV_DET, + PMIC_RG_BATON_EN, + PMIC_RG_BATON_HT_EN_RSV0, + PMIC_BATON_TDET_EN, + PMIC_RG_BATON_HT_TRIM, + PMIC_RG_BATON_HT_TRIM_SET, + PMIC_RG_BATON_TDET_EN, + PMIC_RG_CSDAC_DATA, + PMIC_RG_FRC_CSVTH_USBDL, + PMIC_RGS_PCHR_FLAG_OUT, + PMIC_RG_PCHR_FLAG_EN, + PMIC_RG_OTG_BVALID_EN, + PMIC_RGS_OTG_BVALID_DET, + PMIC_RG_PCHR_FLAG_SEL, + PMIC_RG_PCHR_TESTMODE, + PMIC_RG_CSDAC_TESTMODE, + PMIC_RG_PCHR_RST, + PMIC_RG_PCHR_FT_CTRL, + PMIC_RG_CHRWDT_TD, + PMIC_RG_CHRWDT_EN, + PMIC_RG_CHRWDT_WR, + PMIC_RG_PCHR_RV, + PMIC_RG_CHRWDT_INT_EN, + PMIC_RG_CHRWDT_FLAG_WR, + PMIC_RGS_CHRWDT_OUT, + PMIC_RG_USBDL_RST, + PMIC_RG_USBDL_SET, + PMIC_RG_ADCIN_VSEN_MUX_EN, + PMIC_RG_ADCIN_VSEN_EXT_BATON_EN, + PMIC_RG_ADCIN_VBAT_EN, + PMIC_RG_ADCIN_VSEN_EN, + PMIC_RG_ADCIN_CHR_EN, + PMIC_RG_UVLO_VTHL, + PMIC_RG_UVLO_VH_LAT, + PMIC_RG_LBAT_INT_VTH, + PMIC_RG_BGR_RSEL, + PMIC_RG_BGR_UNCHOP_PH, + PMIC_RG_BGR_UNCHOP, + PMIC_RG_BC11_BB_CTRL, + PMIC_RG_BC11_RST, + PMIC_RG_BC11_VSRC_EN, + PMIC_RGS_BC11_CMP_OUT, + PMIC_RG_BC11_VREF_VTH, + PMIC_RG_BC11_CMP_EN, + PMIC_RG_BC11_IPD_EN, + PMIC_RG_BC11_IPU_EN, + PMIC_RG_BC11_BIAS_EN, + PMIC_RG_CSDAC_STP_INC, + PMIC_RG_CSDAC_STP_DEC, + PMIC_RG_CSDAC_DLY, + PMIC_RG_CSDAC_STP, + PMIC_RG_LOW_ICH_DB, + PMIC_RG_CHRIND_ON, + PMIC_RG_CHRIND_DIMMING, + PMIC_RG_CV_MODE, + PMIC_RG_VCDT_MODE, + PMIC_RG_CSDAC_MODE, + PMIC_RG_TRACKING_EN, + PMIC_RG_HWCV_EN, + PMIC_RG_ULC_DET_EN, + PMIC_RG_BGR_TRIM_EN, + PMIC_RG_ICHRG_TRIM, + PMIC_RG_BGR_TRIM, + PMIC_RG_OVP_TRIM, + PMIC_RG_CHR_OSC_TRIM, + PMIC_DA_QI_BGR_EXT_BUF_EN, + PMIC_RG_BGR_TEST_EN, + PMIC_RG_BGR_TEST_RSTB, + PMIC_RG_DAC_USBDL_MAX, + PMIC_RG_CM_VDEC_TRIG, + PMIC_PCHR_CM_VDEC_STATUS, + PMIC_RG_CM_VINC_TRIG, + PMIC_PCHR_CM_VINC_STATUS, + PMIC_RG_CM_VDEC_HPRD1, + PMIC_RG_CM_VDEC_HPRD2, + PMIC_RG_CM_VDEC_HPRD3, + PMIC_RG_CM_VDEC_HPRD4, + PMIC_RG_CM_VDEC_HPRD5, + PMIC_RG_CM_VDEC_HPRD6, + PMIC_RG_CM_VINC_HPRD1, + PMIC_RG_CM_VINC_HPRD2, + PMIC_RG_CM_VINC_HPRD3, + PMIC_RG_CM_VINC_HPRD4, + PMIC_RG_CM_VINC_HPRD5, + PMIC_RG_CM_VINC_HPRD6, + PMIC_RG_CM_LPRD, + PMIC_RG_CM_CS_VTHL, + PMIC_RG_CM_CS_VTHH, + PMIC_RG_PCHR_RSV, + PMIC_RG_ENVTEM_D, + PMIC_RG_ENVTEM_EN, + PMIC_RGS_BATON_HV, + PMIC_RG_HW_VTH_CTRL, + PMIC_RG_HW_VTH2, + PMIC_RG_HW_VTH1, + PMIC_RG_CM_VDEC_INT_EN, + PMIC_RG_CM_VINC_INT_EN, + PMIC_RG_QI_BATON_LT_EN, + PMIC_RGS_BATON_UNDET, + PMIC_RG_VCDT_TRIM, + PMIC_RG_INDICATOR_TRIM, + PMIC_EOSC_CALI_START, + PMIC_EOSC_CALI_TD, + PMIC_EOSC_CALI_TEST, + PMIC_EOSC_CALI_DCXO_RDY_TD, + PMIC_FRC_VTCXO0_ON, + PMIC_EOSC_CALI_RSV, + PMIC_VRTC_PWM_MODE, + PMIC_VRTC_PWM_RSV, + PMIC_VRTC_PWM_L_DUTY, + PMIC_VRTC_PWM_H_DUTY, + PMIC_VRTC_CAP_SEL, + PMU_COMMAND_MAX +} PMU_FLAGS_LIST_ENUM; + +typedef struct { + PMU_FLAGS_LIST_ENUM flagname; + unsigned short offset; + unsigned short mask; + unsigned char shift; +} PMU_FLAG_TABLE_ENTRY; + +#endif /* _MT_PMIC_UPMU_HW_MT6353_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt6353_sw.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt6353_sw.h new file mode 100644 index 0000000000000000000000000000000000000000..ffbd40e9a379007e677ec04aad70dd607b49526d --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt6353_sw.h @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _MT_PMIC_UPMU_SW_MT6353_H_ +#define _MT_PMIC_UPMU_SW_MT6353_H_ +#include + +#define AUXADC_SUPPORT_IMM_CURRENT_MODE +/*#define BATTERY_DTS_SUPPORT*/ +#define BATTERY_SW_INIT +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* #define RBAT_PULL_UP_VOLT_BY_BIF */ +#else + #define RBAT_PULL_UP_VOLT_BY_BIF +#endif + +#define FG_BAT_INT_H_NO 48 +#define FG_BAT_INT_L_NO 49 + + +/*============================================================================== + * Low battery level define + * ============================================================================== */ +typedef enum LOW_BATTERY_LEVEL_TAG { + LOW_BATTERY_LEVEL_0 = 0, + LOW_BATTERY_LEVEL_1 = 1, + LOW_BATTERY_LEVEL_2 = 2 +} LOW_BATTERY_LEVEL; + +typedef enum LOW_BATTERY_PRIO_TAG { + LOW_BATTERY_PRIO_CPU_B = 0, + LOW_BATTERY_PRIO_CPU_L = 1, + LOW_BATTERY_PRIO_GPU = 2, + LOW_BATTERY_PRIO_MD = 3, + LOW_BATTERY_PRIO_MD5 = 4, + LOW_BATTERY_PRIO_FLASHLIGHT = 5, + LOW_BATTERY_PRIO_VIDEO = 6, + LOW_BATTERY_PRIO_WIFI = 7, + LOW_BATTERY_PRIO_BACKLIGHT = 8 +} LOW_BATTERY_PRIO; + +extern void (*low_battery_callback)(LOW_BATTERY_LEVEL); +extern void register_low_battery_notify(void (*low_battery_callback) (LOW_BATTERY_LEVEL), + LOW_BATTERY_PRIO prio_val); + + +/* ============================================================================== + * Battery OC level define + * ============================================================================== */ +typedef enum BATTERY_OC_LEVEL_TAG { + BATTERY_OC_LEVEL_0 = 0, + BATTERY_OC_LEVEL_1 = 1 +} BATTERY_OC_LEVEL; + +typedef enum BATTERY_OC_PRIO_TAG { + BATTERY_OC_PRIO_CPU_B = 0, + BATTERY_OC_PRIO_CPU_L = 1, + BATTERY_OC_PRIO_GPU = 2 +} BATTERY_OC_PRIO; + +extern void (*battery_oc_callback)(BATTERY_OC_LEVEL); +extern void register_battery_oc_notify(void (*battery_oc_callback) (BATTERY_OC_LEVEL), + BATTERY_OC_PRIO prio_val); + +/*============================================================================== + * Battery percent define + *==============================================================================*/ +typedef enum BATTERY_PERCENT_LEVEL_TAG { + BATTERY_PERCENT_LEVEL_0 = 0, + BATTERY_PERCENT_LEVEL_1 = 1 +} BATTERY_PERCENT_LEVEL; + +typedef enum BATTERY_PERCENT_PRIO_TAG { + BATTERY_PERCENT_PRIO_CPU_B = 0, + BATTERY_PERCENT_PRIO_CPU_L = 1, + BATTERY_PERCENT_PRIO_GPU = 2, + BATTERY_PERCENT_PRIO_MD = 3, + BATTERY_PERCENT_PRIO_MD5 = 4, + BATTERY_PERCENT_PRIO_FLASHLIGHT = 5, + BATTERY_PERCENT_PRIO_VIDEO = 6, + BATTERY_PERCENT_PRIO_WIFI = 7, + BATTERY_PERCENT_PRIO_BACKLIGHT = 8 +} BATTERY_PERCENT_PRIO; + +extern void (*battery_percent_callback)(BATTERY_PERCENT_LEVEL); +extern void +register_battery_percent_notify(void (*battery_percent_callback) (BATTERY_PERCENT_LEVEL), + BATTERY_PERCENT_PRIO prio_val); + +/* ADC Channel Number */ +typedef enum { + PMIC_AUX_BATSNS_AP = 0x000, + PMIC_AUX_ISENSE_AP, + PMIC_AUX_VCDT_AP, + PMIC_AUX_BATON_AP, /* BATON/BIF */ + PMIC_AUX_CH4, + PMIC_AUX_VACCDET_AP, + PMIC_AUX_CH6, + PMIC_AUX_TSX, + PMIC_AUX_CH8, + PMIC_AUX_CH9, + PMIC_AUX_CH10, + PMIC_AUX_CH11, + PMIC_AUX_CH12, + PMIC_AUX_CH13, + PMIC_AUX_CH14, + PMIC_AUX_CH15, + PMIC_AUX_CH16, + PMIC_AUX_CH4_DCXO = 0x10000004, +} pmic_adc_ch_list_enum; + +typedef enum MT_POWER_TAG { + MT6353_POWER_LDO_VTCXO24, + MT6353_POWER_LDO_VXO22, + MT6353_POWER_LDO_VCN33_BT, + MT6353_POWER_LDO_VCN33_WIFI, + MT6353_POWER_LDO_VSRAM_PROC, + MT6353_POWER_LDO_VLDO28, + MT6353_POWER_LDO_VLDO28_1, + MT6353_POWER_LDO_VTCXO28, + MT6353_POWER_LDO_VRF18, + MT6353_POWER_LDO_VRF12, + MT6353_POWER_LDO_VCN28, + MT6353_POWER_LDO_VCN18, + MT6353_POWER_LDO_VCAMA, + MT6353_POWER_LDO_VCAMIO, + MT6353_POWER_LDO_VCAMD, + MT6353_POWER_LDO_VAUX18, + MT6353_POWER_LDO_VAUD28, + MT6353_POWER_LDO_VDRAM, + MT6353_POWER_LDO_VSIM1, + MT6353_POWER_LDO_VSIM2, + MT6353_POWER_LDO_VIO28, + MT6353_POWER_LDO_VMC, + MT6353_POWER_LDO_VMCH, + MT6353_POWER_LDO_VUSB33, + MT6353_POWER_LDO_VEMC, + MT6353_POWER_LDO_VIO18, + MT6353_POWER_LDO_VIBR, + MT65XX_POWER_COUNT_END, + MT65XX_POWER_LDO_DEFAULT, + MT65XX_POWER_NONE = -1 +} MT65XX_POWER; + +/*============================================================================== + * DLPT define + *==============================================================================*/ +typedef enum DLPT_PRIO_TAG { + DLPT_PRIO_PBM = 0, + DLPT_PRIO_CPU_B = 1, + DLPT_PRIO_CPU_L = 2, + DLPT_PRIO_GPU = 3, + DLPT_PRIO_MD = 4, + DLPT_PRIO_MD5 = 5, + DLPT_PRIO_FLASHLIGHT = 6, + DLPT_PRIO_VIDEO = 7, + DLPT_PRIO_WIFI = 8, + DLPT_PRIO_BACKLIGHT = 9 +} DLPT_PRIO; + +extern void (*dlpt_callback)(unsigned int); +extern void register_dlpt_notify(void (*dlpt_callback) (unsigned int), DLPT_PRIO prio_val); +extern const PMU_FLAG_TABLE_ENTRY pmu_flags_table[]; + +extern unsigned short is_battery_remove; +extern unsigned short is_wdt_reboot_pmic; +extern unsigned short is_wdt_reboot_pmic_chk; +extern unsigned int g_pmic_pad_vbif28_vol; + +/*============================================================================== +// PMIC LDO define +//==============================================================================*/ + +/*============================================================================== +// PMIC auxadc define +//==============================================================================*/ +extern signed int g_I_SENSE_offset; +extern void pmic_auxadc_init(void); +extern void pmic_auxadc_lock(void); +extern void pmic_auxadc_unlock(void); +extern void mt_power_off(void); +/*============================================================================== +// PMIC fg define +//==============================================================================*/ +extern unsigned int bat_get_ui_percentage(void); +extern signed int fgauge_read_v_by_d(int d_val); +extern signed int fgauge_read_r_bat_by_v(signed int voltage); +extern signed int fgauge_read_IM_current(void *data); +extern void kpd_pwrkey_pmic_handler(unsigned long pressed); +extern void kpd_pmic_rstkey_handler(unsigned long pressed); +extern int is_mt6311_sw_ready(void); +extern int is_mt6311_exist(void); +extern int get_mt6311_i2c_ch_num(void); +/*extern bool crystal_exist_status(void);*/ +#if defined CONFIG_MTK_LEGACY +extern void pmu_drv_tool_customization_init(void); +#endif +extern int batt_init_cust_data(void); +extern void PMIC_INIT_SETTING_V1(void); + + +#endif /* _MT_PMIC_UPMU_SW_MT6353_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter.h new file mode 100644 index 0000000000000000000000000000000000000000..c81eccc42dd96e193fb17b7df5e206ff54db9c45 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _CUST_BATTERY_METER_H +#define _CUST_BATTERY_METER_H + +/* ============================================================*/ +/* define*/ +/* ============================================================*/ +/*#define SOC_BY_AUXADC*/ +#define SOC_BY_HW_FG +/*#define HW_FG_FORCE_USE_SW_OCV*/ +/*#define SOC_BY_SW_FG*/ + +/*#define CONFIG_DIS_CHECK_BATTERY*/ +/*#define FIXED_TBAT_25*/ + +/* ADC resistor */ +#define R_BAT_SENSE 4 +#define R_I_SENSE 4 +#define R_CHARGER_1 330 +#define R_CHARGER_2 39 + +#define TEMPERATURE_T0 110 +#define TEMPERATURE_T1 0 +#define TEMPERATURE_T2 25 +#define TEMPERATURE_T3 50 +#define TEMPERATURE_T 255 /* This should be fixed, never change the value*/ + +#define FG_METER_RESISTANCE 0 + +/* Qmax for battery */ +#define Q_MAX_POS_50 2743 +#define Q_MAX_POS_25 2709 +#define Q_MAX_POS_0 1168 +#define Q_MAX_NEG_10 762 + +#define Q_MAX_POS_50_H_CURRENT 2688 +#define Q_MAX_POS_25_H_CURRENT 2655 +#define Q_MAX_POS_0_H_CURRENT 1145 +#define Q_MAX_NEG_10_H_CURRENT 747 + + +/* Discharge Percentage */ +#define OAM_D5 1 /* 1 : D5, 0: D2*/ + + +/* battery meter parameter */ +#define CHANGE_TRACKING_POINT +#ifdef CONFIG_MTK_HAFG_20 +#define CUST_TRACKING_POINT 0 +#else +#define CUST_TRACKING_POINT 1 +#endif +#define CUST_R_SENSE 56 +#define CUST_HW_CC 0 +#define AGING_TUNING_VALUE 103 +#define CUST_R_FG_OFFSET 0 + +#define OCV_BOARD_COMPESATE 0 /*mV */ +#define R_FG_BOARD_BASE 1000 +#define R_FG_BOARD_SLOPE 1000 /*slope*/ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + #define CAR_TUNE_VALUE 101 /*1.00 */ +#else + #define CAR_TUNE_VALUE 118 /*1.00 */ +#endif + + +/* HW Fuel gague */ +#define CURRENT_DETECT_R_FG 10 /*1mA*/ +#define MinErrorOffset 1000 +#define FG_VBAT_AVERAGE_SIZE 18 +#define R_FG_VALUE 10 /* mOhm, base is 20*/ + +/* fg 2.0 */ +#define DIFFERENCE_HWOCV_RTC 30 +#define DIFFERENCE_HWOCV_SWOCV 10 +#define DIFFERENCE_SWOCV_RTC 10 +#define DIFFERENCE_HWOCV_VBAT 30 +#define DIFFERENCE_VBAT_RTC 30 +#define DIFFERENCE_SWOCV_RTC_POS 15 +#define MAX_SWOCV 3 + +#define DIFFERENCE_VOLTAGE_UPDATE 20 +#define AGING1_LOAD_SOC 70 +#define AGING1_UPDATE_SOC 30 +#define BATTERYPSEUDO100 95 +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#define BATTERYPSEUDO1 2 +#else +#define BATTERYPSEUDO1 6 +#endif + +/* #define Q_MAX_BY_SYS */ /*8. Qmax variant by system drop voltage.*/ +#define Q_MAX_SYS_VOLTAGE 3350 +#define SHUTDOWN_GAUGE0 +#define SHUTDOWN_GAUGE1_XMINS +#define SHUTDOWN_GAUGE1_MINS 60 + +#define SHUTDOWN_SYSTEM_VOLTAGE 3400 +#define CHARGE_TRACKING_TIME 60 +#define DISCHARGE_TRACKING_TIME 10 + +#define RECHARGE_TOLERANCE 10 +/* SW Fuel Gauge */ +#define MAX_HWOCV 5 +#define MAX_VBAT 90 + +/* fg 1.0 */ +#define CUST_POWERON_DELTA_CAPACITY_TOLRANCE 40 +#define CUST_POWERON_LOW_CAPACITY_TOLRANCE 5 +#define CUST_POWERON_MAX_VBAT_TOLRANCE 90 +#define CUST_POWERON_DELTA_VBAT_TOLRANCE 30 +#define CUST_POWERON_DELTA_HW_SW_OCV_CAPACITY_TOLRANCE 10 + + +/* Disable Battery check for HQA */ +#ifdef CONFIG_MTK_DISABLE_POWER_ON_OFF_VOLTAGE_LIMITATION +#define FIXED_TBAT_25 +#endif + +/* Dynamic change wake up period of battery thread when suspend*/ +#define VBAT_NORMAL_WAKEUP 3600 /*3.6V*/ +#define VBAT_LOW_POWER_WAKEUP 3500 /*3.5v*/ +#define NORMAL_WAKEUP_PERIOD 5400 /*90 * 60 = 90 min*/ +#define LOW_POWER_WAKEUP_PERIOD 300 /*5 * 60 = 5 min*/ +#define CLOSE_POWEROFF_WAKEUP_PERIOD 30 /*30 s*/ + +/* Vanzo:zhangqingzhan on: Wed, 08 Feb 2017 12:08:36 +0800 +use hw soc +#define INIT_SOC_BY_SW_SOC + */ +// End of Vanzo: zhangqingzhan + +/*3. UI SOC sync to FG SOC immediately*/ +/*#define SYNC_UI_SOC_IMM*/ + +/*6. Q_MAX aging algorithm*/ +#define MTK_ENABLE_AGING_ALGORITHM + +/*5. Gauge Adjust by OCV 9. MD sleep current check*/ +#define MD_SLEEP_CURRENT_CHECK + +/*7. Qmax variant by current loading.*/ +/* #define Q_MAX_BY_CURRENT */ + +#define FG_BAT_INT +#define IS_BATTERY_REMOVE_BY_PMIC +/* #define USE_EMBEDDED_BATTERY */ + +/* Calculate do in Kernel */ +/* #define FORCE_D0_IN_KERNEL */ + +/* Use UI_SOC3 to smooth UI_SOC2 */ +/* #define USING_SMOOTH_UI_SOC2 */ + +/* SOC track to SWOCV */ +#define CUST_TRACKING_GAP 15 /* start tracking gap */ +#define CUST_TRACKINGOFFSET 0 /* Force offset to shift SOC to 0 */ +#define CUST_TRACKINGEN 0 /* 0:disable, 1:enable */ + +/* Multi battery */ +/* #define MTK_MULTI_BAT_PROFILE_SUPPORT */ +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter_table.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..13f734b5b26fc0ca8bd436e58cbc89bad8b20a40 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter_table.h @@ -0,0 +1,996 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _CUST_BATTERY_METER_TABLE_H +#define _CUST_BATTERY_METER_TABLE_H + + +/* ============================================================ +// define +// ============================================================*/ +#define BAT_NTC_10 1 +#define BAT_NTC_47 0 + +#if (BAT_NTC_10 == 1) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + #define RBAT_PULL_UP_R 16900 +#else + #define RBAT_PULL_UP_R 24000 +#endif +#endif + +#if (BAT_NTC_47 == 1) +#define RBAT_PULL_UP_R 61900 +#endif + +#define RBAT_PULL_UP_VOLT 1800 + + + +/* ============================================================ +// ENUM +// ============================================================*/ + +/* ============================================================ +// structure +// ============================================================*/ + +/* ============================================================ +// typedef +// ============================================================*/ +typedef struct _BATTERY_PROFILE_STRUCT { + signed int percentage; + signed int voltage; + } BATTERY_PROFILE_STRUCT, *BATTERY_PROFILE_STRUCT_P; + +typedef struct _R_PROFILE_STRUCT { + signed int resistance; /* Ohm*/ + signed int voltage; +} R_PROFILE_STRUCT, *R_PROFILE_STRUCT_P; + +typedef enum { + T1_0C, + T2_25C, + T3_50C +} PROFILE_TEMPERATURE; + +/* ============================================================ +// External Variables +// ============================================================*/ + +/* ============================================================ +// External function +// ============================================================*/ + +/* ============================================================ +// Table +// ============================================================*/ +#if (BAT_NTC_10 == 1) +BATT_TEMPERATURE Batt_Temperature_Table[] = { + {-20, 68237}, + {-15, 53650}, + {-10, 42506}, + { -5, 33892}, + { 0, 27219}, + { 5, 22021}, + { 10, 17926}, + { 15, 14674}, + { 20, 12081}, + { 25, 10000}, + { 30, 8315}, + { 35, 6948}, + { 40, 5834}, + { 45, 4917}, + { 50, 4161}, + { 55, 3535}, + { 60, 3014} +}; +#endif + +#if (BAT_NTC_47 == 1) +BATT_TEMPERATURE Batt_Temperature_Table[] = { + {-20, 483954}, + {-15, 360850}, + {-10, 271697}, + { -5, 206463}, + { 0, 158214}, + { 5, 122259}, + { 10, 95227}, + { 15, 74730}, + { 20, 59065}, + { 25, 47000}, + { 30, 37643}, + { 35, 30334}, + { 40, 24591}, + { 45, 20048}, + { 50, 16433}, + { 55, 13539}, + { 60, 11210} +}; +#endif + +/* T0 -10C */ +BATTERY_PROFILE_STRUCT battery_profile_t0[] = { + { 0, 4303}, + {6, 4281}, + {13, 4261}, + {19, 4240}, + {27, 4217}, + {33, 4194}, + {40, 4169}, + {46, 4145}, + {54, 4117}, + {60, 4088}, + {66, 4068}, + {73, 4047}, + {79, 4019}, + {87, 3997}, + {93, 3981}, + {100, 3967}, + {106, 3956}, + {113, 3942}, + {119, 3929}, + {125, 3913}, + {133, 3895}, + {136, 3880}, + {143, 3869}, + {149, 3857}, + {155, 3848}, + {163, 3839}, + {169, 3830}, + {176, 3823}, + {182, 3818}, + {190, 3811}, + {195, 3806}, + {203, 3800}, + {209, 3796}, + {215, 3791}, + {222, 3787}, + {228, 3781}, + {236, 3775}, + {242, 3770}, + {249, 3760}, + {255, 3752}, + {263, 3742}, + {269, 3731}, + {275, 3721}, + {282, 3713}, + {288, 3704}, + {295, 3698}, + {301, 3688}, + {309, 3665}, + {315, 3613}, + {322, 3526}, + {325, 3466}, + {328, 3444}, + {331, 3424}, + {331, 3404}, + {331, 3381}, + {334, 3357}, + {334, 3332}, + {334, 3310}, + {334, 3291}, + {334, 3274}, + {334, 3259}, + {334, 3245}, + {339, 3234}, + {339, 3221}, + {339, 3212}, + {339, 3204}, + {339, 3193}, + {339, 3186}, + {339, 3179}, + {339, 3168}, + {339, 3162}, + {339, 3157}, + {339, 3151}, + {339, 3143}, + {339, 3133}, + {339, 3125}, + {339, 3125}, + {339, 3125}, + {339, 3125}, + {339, 3125}, + {339, 3125}, + {339, 3125}, +}; + +/* T1 0C */ +BATTERY_PROFILE_STRUCT battery_profile_t1[] = { + {0, 4316}, + {5, 4283}, + {9, 4244}, + {14, 4210}, + {16, 4185}, + {21, 4164}, + {25, 4144}, + {30, 4128}, + {35, 4109}, + {39, 4093}, + {44, 4080}, + {46, 4069}, + {51, 4047}, + {56, 4023}, + {60, 4003}, + {65, 3989}, + {68, 3977}, + {72, 3967}, + {75, 3955}, + {81, 3940}, + {86, 3923}, + {89, 3907}, + {95, 3891}, + {100, 3877}, + {102, 3864}, + {107, 3855}, + {111, 3846}, + {116, 3837}, + {119, 3831}, + {125, 3823}, + {130, 3815}, + {132, 3811}, + {137, 3804}, + {140, 3799}, + {146, 3794}, + {151, 3790}, + {154, 3785}, + {160, 3782}, + {161, 3778}, + {167, 3773}, + {170, 3768}, + {175, 3761}, + {181, 3753}, + {184, 3742}, + {188, 3727}, + {191, 3712}, + {196, 3704}, + {200, 3701}, + {205, 3698}, + {211, 3692}, + {214, 3680}, + {218, 3625}, + {221, 3528}, + {226, 3472}, + {232, 3403}, + {233, 3323}, + {233, 3267}, + {233, 3230}, + {235, 3203}, + {235, 3180}, + {235, 3157}, + {235, 3141}, + {235, 3124}, + {235, 3109}, + {235, 3096}, + {235, 3084}, + {235, 3079}, + {235, 3067}, + {235, 3058}, + {235, 3047}, + {235, 3041}, + {235, 3032}, + {235, 3029}, + {235, 3018}, + {235, 3008}, + {235, 3002}, + {235, 3003}, + {235, 2995}, + {235, 2985}, + {235, 2983}, + {235, 2979}, + {235, 2967}, + +}; + +/* T2 25C*/ +BATTERY_PROFILE_STRUCT battery_profile_t2[] = { + {0, 4317}, + {2, 4292}, + {3, 4270}, + {5, 4250}, + {8, 4231}, + {10, 4213}, + {11, 4195}, + {13, 4176}, + {15, 4159}, + {16, 4143}, + {18, 4125}, + {20, 4110}, + {23, 4093}, + {24, 4077}, + {26, 4061}, + {28, 4047}, + {29, 4030}, + {31, 4014}, + {33, 4001}, + {35, 3988}, + {37, 3976}, + {39, 3962}, + {41, 3951}, + {42, 3935}, + {44, 3916}, + {46, 3897}, + {48, 3881}, + {49, 3869}, + {52, 3859}, + {54, 3849}, + {55, 3840}, + {57, 3835}, + {59, 3827}, + {61, 3820}, + {62, 3813}, + {65, 3807}, + {67, 3803}, + {68, 3797}, + {70, 3790}, + {72, 3786}, + {74, 3782}, + {75, 3777}, + {77, 3770}, + {80, 3763}, + {81, 3755}, + {83, 3745}, + {85, 3734}, + {87, 3717}, + {88, 3699}, + {90, 3692}, + {92, 3690}, + {94, 3689}, + {96, 3688}, + {98, 3676}, + {100, 3623}, + {101, 3548}, + {103, 3500}, + {105, 3482}, + {106, 3442}, + {109, 3323}, + {110, 3204}, + {110, 3162}, + {110, 3128}, + {111, 3098}, + {111, 3073}, + {111, 3053}, + {111, 3036}, + {111, 3023}, + {111, 3012}, + {111, 2998}, + {111, 2987}, + {111, 2978}, + {111, 2971}, + {111, 2963}, + {111, 2958}, + {111, 2956}, + {111, 2953}, + {111, 2948}, + {111, 2940}, + {111, 2934}, + {111, 2929}, + {111, 2926}, +}; + +/* T3 50C*/ +BATTERY_PROFILE_STRUCT battery_profile_t3[] = { + {0, 4331}, + {2, 4305}, + {3, 4284}, + {5, 4265}, + {7, 4244}, + {10, 4225}, + {11, 4206}, + {13, 4188}, + {15, 4170}, + {16, 4153}, + {18, 4135}, + {20, 4119}, + {22, 4102}, + {23, 4085}, + {26, 4069}, + {28, 4054}, + {29, 4038}, + {31, 4023}, + {33, 4010}, + {35, 3996}, + {36, 3984}, + {38, 3970}, + {40, 3958}, + {41, 3947}, + {44, 3934}, + {46, 3921}, + {47, 3904}, + {49, 3884}, + {51, 3868}, + {53, 3857}, + {54, 3848}, + {56, 3838}, + {59, 3832}, + {60, 3824}, + {62, 3817}, + {64, 3811}, + {66, 3806}, + {67, 3800}, + {69, 3794}, + {71, 3790}, + {72, 3784}, + {74, 3777}, + {77, 3763}, + {79, 3758}, + {80, 3750}, + {82, 3742}, + {84, 3733}, + {85, 3723}, + {87, 3709}, + {89, 3694}, + {91, 3678}, + {93, 3676}, + {95, 3675}, + {97, 3674}, + {98, 3669}, + {100, 3625}, + {102, 3547}, + {104, 3495}, + {105, 3458}, + {107, 3331}, + {109, 3140}, + {109, 3078}, + {109, 3033}, + {109, 3001}, + {109, 2980}, + {110, 2960}, + {110, 2944}, + {110, 2932}, + {110, 2921}, + {110, 2913}, + {110, 2903}, + {110, 2899}, + {110, 2889}, + {110, 2889}, + {110, 2889}, + {110, 2889}, + {110, 2889}, + {110, 2889}, + {110, 2889}, + {110, 2889}, + {110, 2889}, + {110, 2889}, +}; + +/* battery profile for actual temperature. The size should be the same as T1, T2 and T3*/ +BATTERY_PROFILE_STRUCT battery_profile_temperature[] = { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0 } +}; + +/* ============================================================ +// Table +// ============================================================*/ +/* T0 -10C*/ +R_PROFILE_STRUCT r_profile_t0[] = { + {408, 4303}, + {408, 4281}, + {415, 4261}, + {425, 4240}, + {430, 4217}, + {440, 4194}, + {463, 4169}, + {490, 4145}, + {525, 4117}, + {573, 4088}, + {615, 4068}, + {650, 4047}, + {675, 4019}, + {685, 3997}, + {705, 3981}, + {713, 3967}, + {720, 3956}, + {733, 3942}, + {728, 3929}, + {738, 3913}, + {725, 3895}, + {735, 3880}, + {745, 3869}, + {748, 3857}, + {760, 3848}, + {773, 3839}, + {783, 3830}, + {803, 3823}, + {820, 3818}, + {835, 3811}, + {863, 3806}, + {888, 3800}, + {903, 3796}, + {925, 3791}, + {955, 3787}, + {975, 3781}, + {1000, 3775}, + {1035, 3770}, + {1058, 3760}, + {1090, 3752}, + {1105, 3742}, + {1135, 3731}, + {1168, 3721}, + {1210, 3713}, + {1255, 3704}, + {1345, 3698}, + {1430, 3688}, + {1518, 3665}, + {1570, 3613}, + {1618, 3526}, + {1668, 3466}, + {1613, 3444}, + {1563, 3424}, + {1510, 3404}, + {1460, 3381}, + {1400, 3357}, + {1333, 3332}, + {1283, 3310}, + {1233, 3291}, + {1198, 3274}, + {1155, 3259}, + {1128, 3245}, + {1093, 3234}, + {1075, 3221}, + {1053, 3212}, + {1023, 3204}, + {1018, 3193}, + {1005, 3186}, + {978, 3179}, + {960, 3168}, + {940, 3162}, + {895, 3157}, + {890, 3151}, + {863, 3143}, + {925, 3133}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125} +}; + +/* T1 0C*/ +R_PROFILE_STRUCT r_profile_t1[] = { + {258, 4316}, + {258, 4283}, + {278, 4244}, + {303, 4210}, + {333, 4185}, + {343, 4164}, + {350, 4144}, + {365, 4128}, + {370, 4109}, + {370, 4093}, + {380, 4080}, + {403, 4069}, + {395, 4047}, + {403, 4023}, + {403, 4003}, + {413, 3989}, + {418, 3977}, + {420, 3967}, + {423, 3955}, + {415, 3940}, + {410, 3923}, + {400, 3907}, + {393, 3891}, + {393, 3877}, + {388, 3864}, + {395, 3855}, + {403, 3846}, + {405, 3837}, + {415, 3831}, + {425, 3823}, + {430, 3815}, + {443, 3811}, + {450, 3804}, + {465, 3799}, + {475, 3794}, + {483, 3790}, + {490, 3785}, + {503, 3782}, + {520, 3778}, + {533, 3773}, + {545, 3768}, + {563, 3761}, + {588, 3753}, + {600, 3742}, + {608, 3727}, + {615, 3712}, + {635, 3704}, + {670, 3701}, + {710, 3698}, + {765, 3692}, + {840, 3680}, + {880, 3625}, + {915, 3528}, + {1080, 3472}, + {1323, 3403}, + {1315, 3323}, + {1180, 3267}, + {1080, 3230}, + {1010, 3203}, + {958, 3180}, + {925, 3157}, + {888, 3141}, + {860, 3124}, + {810, 3109}, + {788, 3096}, + {765, 3084}, + {700, 3079}, + {745, 3067}, + {680, 3058}, + {685, 3047}, + {650, 3041}, + {683, 3032}, + {615, 3029}, + {643, 3018}, + {660, 3008}, + {635, 3002}, + {530, 3003}, + {640, 2995}, + {595, 2985}, + {535, 2983}, + {463, 2979}, + {600, 2967} +}; + +/* T2 25C*/ +R_PROFILE_STRUCT r_profile_t2[] = { + {173, 4317}, + {173, 4292}, + {175, 4270}, + {170, 4250}, + {173, 4231}, + {173, 4213}, + {178, 4195}, + {173, 4176}, + {183, 4159}, + {193, 4143}, + {193, 4125}, + {203, 4110}, + {205, 4093}, + {208, 4077}, + {205, 4061}, + {213, 4047}, + {215, 4030}, + {223, 4014}, + {230, 4001}, + {233, 3988}, + {240, 3976}, + {243, 3962}, + {248, 3951}, + {243, 3935}, + {223, 3916}, + {203, 3897}, + {195, 3881}, + {188, 3869}, + {188, 3859}, + {185, 3849}, + {183, 3840}, + {195, 3835}, + {198, 3827}, + {195, 3820}, + {198, 3813}, + {200, 3807}, + {208, 3803}, + {205, 3797}, + {205, 3790}, + {205, 3786}, + {210, 3782}, + {213, 3777}, + {208, 3770}, + {203, 3763}, + {198, 3755}, + {195, 3745}, + {198, 3734}, + {193, 3717}, + {193, 3699}, + {193, 3692}, + {195, 3690}, + {205, 3689}, + {220, 3688}, + {238, 3676}, + {238, 3623}, + {255, 3548}, + {293, 3500}, + {330, 3482}, + {390, 3442}, + {485, 3323}, + {1018, 3204}, + {925, 3162}, + {838, 3128}, + {748, 3098}, + {720, 3073}, + {668, 3053}, + {608, 3036}, + {560, 3023}, + {550, 3012}, + {558, 2998}, + {538, 2987}, + {515, 2978}, + {485, 2971}, + {458, 2963}, + {455, 2958}, + {403, 2956}, + {398, 2953}, + {373, 2948}, + {373, 2940}, + {408, 2934}, + {420, 2929}, + {335, 2926} +}; + +/* T3 50C*/ +R_PROFILE_STRUCT r_profile_t3[] = { + {123, 4331}, + {123, 4305}, + {128, 4284}, + {130, 4265}, + {130, 4244}, + {130, 4225}, + {128, 4206}, + {125, 4188}, + {130, 4170}, + {133, 4153}, + {133, 4135}, + {138, 4119}, + {138, 4102}, + {140, 4085}, + {140, 4069}, + {143, 4054}, + {140, 4038}, + {143, 4023}, + {148, 4010}, + {153, 3996}, + {155, 3984}, + {155, 3970}, + {165, 3958}, + {175, 3947}, + {175, 3934}, + {178, 3921}, + {170, 3904}, + {148, 3884}, + {135, 3868}, + {135, 3857}, + {133, 3848}, + {133, 3838}, + {135, 3832}, + {135, 3824}, + {135, 3817}, + {143, 3811}, + {145, 3806}, + {148, 3800}, + {145, 3794}, + {153, 3790}, + {150, 3784}, + {150, 3777}, + {133, 3763}, + {143, 3758}, + {140, 3750}, + {138, 3742}, + {135, 3733}, + {135, 3723}, + {133, 3709}, + {133, 3694}, + {130, 3678}, + {130, 3676}, + {138, 3675}, + {148, 3674}, + {160, 3669}, + {158, 3625}, + {170, 3547}, + {208, 3495}, + {220, 3458}, + {265, 3331}, + {855, 3140}, + {725, 3078}, + {600, 3033}, + {528, 3001}, + {460, 2980}, + {400, 2960}, + {380, 2944}, + {355, 2932}, + {315, 2921}, + {303, 2913}, + {308, 2903}, + {255, 2899}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889} +}; + +/* r-table profile for actual temperature. The size should be the same as T1, T2 and T3*/ +R_PROFILE_STRUCT r_profile_temperature[] = { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} +}; + +/* ============================================================ +// function prototype +// ============================================================*/ +int fgauge_get_saddles(void); +BATTERY_PROFILE_STRUCT_P fgauge_get_profile(unsigned int temperature); + +int fgauge_get_saddles_r_table(void); +R_PROFILE_STRUCT_P fgauge_get_profile_r_table(unsigned int temperature); + +#endif + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter_table_multi_profile.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter_table_multi_profile.h new file mode 100644 index 0000000000000000000000000000000000000000..48648dbcc143f538c5e2033031dcbde72f691c85 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_battery_meter_table_multi_profile.h @@ -0,0 +1,3673 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _CUST_BATTERY_METER_TABLE_H +#define _CUST_BATTERY_METER_TABLE_H + + +/* ============================================================ +// define +// ============================================================*/ +#define BAT_NTC_10 1 +#define BAT_NTC_47 0 + +#if (BAT_NTC_10 == 1) +#define RBAT_PULL_UP_R 24000 +#endif + +#if (BAT_NTC_47 == 1) +#define RBAT_PULL_UP_R 61900 +#endif + +#define RBAT_PULL_UP_VOLT 2800 + +#define BIF_NTC_R 16000 + +/* multiple battery profile compile options */ +#define MTK_GET_BATTERY_ID_BY_AUXADC +#define BATTERY_ID_CHANNEL_NUM 3 +#define TOTAL_BATTERY_NUMBER 4 +/*#define MTK_GET_BATTERY_ID_BY_GPIO*/ + +/* ============================================================ +// ENUM +// ============================================================*/ + +/* ============================================================ +// structure +// ============================================================*/ + +/* ============================================================ +// typedef +// ============================================================*/ +typedef struct _BATTERY_PROFILE_STRUCT { + signed int percentage; + signed int voltage; + } BATTERY_PROFILE_STRUCT, *BATTERY_PROFILE_STRUCT_P; + +typedef struct _R_PROFILE_STRUCT { + signed int resistance; /* Ohm*/ + signed int voltage; +} R_PROFILE_STRUCT, *R_PROFILE_STRUCT_P; + +typedef enum { + T1_0C, + T2_25C, + T3_50C +} PROFILE_TEMPERATURE; + +/* ============================================================ +// External Variables +// ============================================================*/ + +/* ============================================================ +// External function +// ============================================================*/ + +/* ============================================================ +// Table +// ============================================================*/ + +/* Qmax for battery */ +signed int g_Q_MAX_POS_50[TOTAL_BATTERY_NUMBER] = {2500, 2500, 2500, 2500}; +signed int g_Q_MAX_POS_25[TOTAL_BATTERY_NUMBER] = {2432, 2432, 2432, 2432}; +signed int g_Q_MAX_POS_0[TOTAL_BATTERY_NUMBER] = {2244, 2244, 2244, 2244}; +signed int g_Q_MAX_NEG_10[TOTAL_BATTERY_NUMBER] = {1654, 1654, 1654, 1654}; + +signed int g_Q_MAX_POS_50_H_CURRENT[TOTAL_BATTERY_NUMBER] = {2500, 2500, 2500, 2500}; +signed int g_Q_MAX_POS_25_H_CURRENT[TOTAL_BATTERY_NUMBER] = {2390, 2390, 2390, 2390}; +signed int g_Q_MAX_POS_0_H_CURRENT[TOTAL_BATTERY_NUMBER] = {1814, 1814, 1814, 1814}; +signed int g_Q_MAX_NEG_10_H_CURRENT[TOTAL_BATTERY_NUMBER] = {696, 696, 696, 696}; + +signed int g_Q_MAX_SYS_VOLTAGE[TOTAL_BATTERY_NUMBER] = {3350, 3350, 3350, 3350}; +signed int g_BATTERYPSEUDO1[TOTAL_BATTERY_NUMBER] = {4, 4, 4, 4}; + +/* 0~0.5V for battery 0, 0.5~1V for battery 1, 1~1.5V for battery 2, -1 for the last one (battery 3) */ +signed int g_battery_id_voltage[TOTAL_BATTERY_NUMBER] = {500000, 1000000, 1500000, -1}; + +#if (BAT_NTC_10 == 1) +BATT_TEMPERATURE Batt_Temperature_Table[TOTAL_BATTERY_NUMBER][17] = { + { + {-20, 68237}, + {-15, 53650}, + {-10, 42506}, + { -5, 33892}, + { 0, 27219}, + { 5, 22021}, + { 10, 17926}, + { 15, 14674}, + { 20, 12081}, + { 25, 10000}, + { 30, 8315}, + { 35, 6948}, + { 40, 5834}, + { 45, 4917}, + { 50, 4161}, + { 55, 3535}, + { 60, 3014} + }, + { + {-20, 68237}, + {-15, 53650}, + {-10, 42506}, + { -5, 33892}, + { 0, 27219}, + { 5, 22021}, + { 10, 17926}, + { 15, 14674}, + { 20, 12081}, + { 25, 10000}, + { 30, 8315}, + { 35, 6948}, + { 40, 5834}, + { 45, 4917}, + { 50, 4161}, + { 55, 3535}, + { 60, 3014} + }, + { + {-20, 68237}, + {-15, 53650}, + {-10, 42506}, + { -5, 33892}, + { 0, 27219}, + { 5, 22021}, + { 10, 17926}, + { 15, 14674}, + { 20, 12081}, + { 25, 10000}, + { 30, 8315}, + { 35, 6948}, + { 40, 5834}, + { 45, 4917}, + { 50, 4161}, + { 55, 3535}, + { 60, 3014} + }, + { + {-20, 68237}, + {-15, 53650}, + {-10, 42506}, + { -5, 33892}, + { 0, 27219}, + { 5, 22021}, + { 10, 17926}, + { 15, 14674}, + { 20, 12081}, + { 25, 10000}, + { 30, 8315}, + { 35, 6948}, + { 40, 5834}, + { 45, 4917}, + { 50, 4161}, + { 55, 3535}, + { 60, 3014} + } +}; +#endif + +#if (BAT_NTC_47 == 1) +BATT_TEMPERATURE Batt_Temperature_Table[TOTAL_BATTERY_NUMBER][17] = { + { + {-20, 483954}, + {-15, 360850}, + {-10, 271697}, + { -5, 206463}, + { 0, 158214}, + { 5, 122259}, + { 10, 95227}, + { 15, 74730}, + { 20, 59065}, + { 25, 47000}, + { 30, 37643}, + { 35, 30334}, + { 40, 24591}, + { 45, 20048}, + { 50, 16433}, + { 55, 13539}, + { 60, 11210} + }, + { + {-20, 483954}, + {-15, 360850}, + {-10, 271697}, + { -5, 206463}, + { 0, 158214}, + { 5, 122259}, + { 10, 95227}, + { 15, 74730}, + { 20, 59065}, + { 25, 47000}, + { 30, 37643}, + { 35, 30334}, + { 40, 24591}, + { 45, 20048}, + { 50, 16433}, + { 55, 13539}, + { 60, 11210} + }, + { + {-20, 483954}, + {-15, 360850}, + {-10, 271697}, + { -5, 206463}, + { 0, 158214}, + { 5, 122259}, + { 10, 95227}, + { 15, 74730}, + { 20, 59065}, + { 25, 47000}, + { 30, 37643}, + { 35, 30334}, + { 40, 24591}, + { 45, 20048}, + { 50, 16433}, + { 55, 13539}, + { 60, 11210} + }, + { + {-20, 483954}, + {-15, 360850}, + {-10, 271697}, + { -5, 206463}, + { 0, 158214}, + { 5, 122259}, + { 10, 95227}, + { 15, 74730}, + { 20, 59065}, + { 25, 47000}, + { 30, 37643}, + { 35, 30334}, + { 40, 24591}, + { 45, 20048}, + { 50, 16433}, + { 55, 13539}, + { 60, 11210} + } +}; +#endif + +/* T0 -10C */ +BATTERY_PROFILE_STRUCT battery_profile_t0[TOTAL_BATTERY_NUMBER][82] = { + { + {0, 4303}, + {6, 4281}, + {13, 4261}, + {19, 4240}, + {26, 4217}, + {32, 4194}, + {39, 4169}, + {45, 4145}, + {52, 4117}, + {55, 4088}, + {61, 4068}, + {68, 4047}, + {74, 4019}, + {81, 3997}, + {87, 3981}, + {94, 3967}, + {100, 3956}, + {107, 3942}, + {113, 3929}, + {119, 3913}, + {126, 3895}, + {132, 3880}, + {139, 3869}, + {145, 3857}, + {152, 3848}, + {158, 3839}, + {165, 3830}, + {168, 3823}, + {174, 3818}, + {181, 3811}, + {187, 3806}, + {194, 3800}, + {200, 3796}, + {207, 3791}, + {213, 3787}, + {219, 3781}, + {226, 3775}, + {232, 3770}, + {239, 3760}, + {245, 3752}, + {252, 3742}, + {258, 3731}, + {265, 3721}, + {271, 3713}, + {278, 3704}, + {281, 3698}, + {287, 3688}, + {294, 3665}, + {300, 3613}, + {307, 3526}, + {313, 3466}, + {313, 3444}, + {316, 3424}, + {316, 3404}, + {320, 3381}, + {320, 3357}, + {320, 3332}, + {320, 3310}, + {320, 3291}, + {323, 3274}, + {323, 3259}, + {323, 3245}, + {323, 3234}, + {323, 3221}, + {323, 3212}, + {323, 3204}, + {323, 3193}, + {323, 3186}, + {323, 3179}, + {323, 3168}, + {323, 3162}, + {323, 3157}, + {323, 3151}, + {323, 3143}, + {323, 3133}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + }, + { + {0, 4303}, + {6, 4281}, + {13, 4261}, + {19, 4240}, + {26, 4217}, + {32, 4194}, + {39, 4169}, + {45, 4145}, + {52, 4117}, + {55, 4088}, + {61, 4068}, + {68, 4047}, + {74, 4019}, + {81, 3997}, + {87, 3981}, + {94, 3967}, + {100, 3956}, + {107, 3942}, + {113, 3929}, + {119, 3913}, + {126, 3895}, + {132, 3880}, + {139, 3869}, + {145, 3857}, + {152, 3848}, + {158, 3839}, + {165, 3830}, + {168, 3823}, + {174, 3818}, + {181, 3811}, + {187, 3806}, + {194, 3800}, + {200, 3796}, + {207, 3791}, + {213, 3787}, + {219, 3781}, + {226, 3775}, + {232, 3770}, + {239, 3760}, + {245, 3752}, + {252, 3742}, + {258, 3731}, + {265, 3721}, + {271, 3713}, + {278, 3704}, + {281, 3698}, + {287, 3688}, + {294, 3665}, + {300, 3613}, + {307, 3526}, + {313, 3466}, + {313, 3444}, + {316, 3424}, + {316, 3404}, + {320, 3381}, + {320, 3357}, + {320, 3332}, + {320, 3310}, + {320, 3291}, + {323, 3274}, + {323, 3259}, + {323, 3245}, + {323, 3234}, + {323, 3221}, + {323, 3212}, + {323, 3204}, + {323, 3193}, + {323, 3186}, + {323, 3179}, + {323, 3168}, + {323, 3162}, + {323, 3157}, + {323, 3151}, + {323, 3143}, + {323, 3133}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + }, + { + {0, 4303}, + {6, 4281}, + {13, 4261}, + {19, 4240}, + {26, 4217}, + {32, 4194}, + {39, 4169}, + {45, 4145}, + {52, 4117}, + {55, 4088}, + {61, 4068}, + {68, 4047}, + {74, 4019}, + {81, 3997}, + {87, 3981}, + {94, 3967}, + {100, 3956}, + {107, 3942}, + {113, 3929}, + {119, 3913}, + {126, 3895}, + {132, 3880}, + {139, 3869}, + {145, 3857}, + {152, 3848}, + {158, 3839}, + {165, 3830}, + {168, 3823}, + {174, 3818}, + {181, 3811}, + {187, 3806}, + {194, 3800}, + {200, 3796}, + {207, 3791}, + {213, 3787}, + {219, 3781}, + {226, 3775}, + {232, 3770}, + {239, 3760}, + {245, 3752}, + {252, 3742}, + {258, 3731}, + {265, 3721}, + {271, 3713}, + {278, 3704}, + {281, 3698}, + {287, 3688}, + {294, 3665}, + {300, 3613}, + {307, 3526}, + {313, 3466}, + {313, 3444}, + {316, 3424}, + {316, 3404}, + {320, 3381}, + {320, 3357}, + {320, 3332}, + {320, 3310}, + {320, 3291}, + {323, 3274}, + {323, 3259}, + {323, 3245}, + {323, 3234}, + {323, 3221}, + {323, 3212}, + {323, 3204}, + {323, 3193}, + {323, 3186}, + {323, 3179}, + {323, 3168}, + {323, 3162}, + {323, 3157}, + {323, 3151}, + {323, 3143}, + {323, 3133}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + }, + { + {0, 4303}, + {6, 4281}, + {13, 4261}, + {19, 4240}, + {26, 4217}, + {32, 4194}, + {39, 4169}, + {45, 4145}, + {52, 4117}, + {55, 4088}, + {61, 4068}, + {68, 4047}, + {74, 4019}, + {81, 3997}, + {87, 3981}, + {94, 3967}, + {100, 3956}, + {107, 3942}, + {113, 3929}, + {119, 3913}, + {126, 3895}, + {132, 3880}, + {139, 3869}, + {145, 3857}, + {152, 3848}, + {158, 3839}, + {165, 3830}, + {168, 3823}, + {174, 3818}, + {181, 3811}, + {187, 3806}, + {194, 3800}, + {200, 3796}, + {207, 3791}, + {213, 3787}, + {219, 3781}, + {226, 3775}, + {232, 3770}, + {239, 3760}, + {245, 3752}, + {252, 3742}, + {258, 3731}, + {265, 3721}, + {271, 3713}, + {278, 3704}, + {281, 3698}, + {287, 3688}, + {294, 3665}, + {300, 3613}, + {307, 3526}, + {313, 3466}, + {313, 3444}, + {316, 3424}, + {316, 3404}, + {320, 3381}, + {320, 3357}, + {320, 3332}, + {320, 3310}, + {320, 3291}, + {323, 3274}, + {323, 3259}, + {323, 3245}, + {323, 3234}, + {323, 3221}, + {323, 3212}, + {323, 3204}, + {323, 3193}, + {323, 3186}, + {323, 3179}, + {323, 3168}, + {323, 3162}, + {323, 3157}, + {323, 3151}, + {323, 3143}, + {323, 3133}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + {323, 3125}, + } +}; + +/* T1 0C */ +BATTERY_PROFILE_STRUCT battery_profile_t1[TOTAL_BATTERY_NUMBER][82] = { + { + {0, 4316}, + {3, 4283}, + {5, 4244}, + {7, 4210}, + {10, 4185}, + {12, 4164}, + {15, 4144}, + {18, 4128}, + {21, 4109}, + {22, 4093}, + {25, 4080}, + {27, 4069}, + {30, 4047}, + {33, 4023}, + {36, 4003}, + {37, 3989}, + {40, 3977}, + {42, 3967}, + {45, 3955}, + {48, 3940}, + {49, 3923}, + {52, 3907}, + {55, 3891}, + {58, 3877}, + {60, 3864}, + {63, 3855}, + {64, 3846}, + {67, 3837}, + {70, 3831}, + {73, 3823}, + {75, 3815}, + {78, 3811}, + {79, 3804}, + {82, 3799}, + {85, 3794}, + {88, 3790}, + {90, 3785}, + {92, 3782}, + {95, 3778}, + {97, 3773}, + {100, 3768}, + {103, 3761}, + {106, 3753}, + {107, 3742}, + {110, 3727}, + {112, 3712}, + {115, 3704}, + {118, 3701}, + {119, 3698}, + {122, 3692}, + {125, 3680}, + {127, 3625}, + {130, 3528}, + {133, 3472}, + {134, 3403}, + {136, 3323}, + {137, 3267}, + {137, 3230}, + {137, 3203}, + {137, 3180}, + {137, 3157}, + {137, 3141}, + {137, 3124}, + {137, 3109}, + {137, 3096}, + {137, 3084}, + {137, 3079}, + {137, 3067}, + {137, 3058}, + {137, 3047}, + {137, 3041}, + {137, 3032}, + {137, 3029}, + {137, 3018}, + {137, 3008}, + {137, 3002}, + {137, 3003}, + {137, 2995}, + {137, 2985}, + {137, 2983}, + {137, 2979}, + {137, 2967}, + }, + { + {0, 4316}, + {3, 4283}, + {5, 4244}, + {7, 4210}, + {10, 4185}, + {12, 4164}, + {15, 4144}, + {18, 4128}, + {21, 4109}, + {22, 4093}, + {25, 4080}, + {27, 4069}, + {30, 4047}, + {33, 4023}, + {36, 4003}, + {37, 3989}, + {40, 3977}, + {42, 3967}, + {45, 3955}, + {48, 3940}, + {49, 3923}, + {52, 3907}, + {55, 3891}, + {58, 3877}, + {60, 3864}, + {63, 3855}, + {64, 3846}, + {67, 3837}, + {70, 3831}, + {73, 3823}, + {75, 3815}, + {78, 3811}, + {79, 3804}, + {82, 3799}, + {85, 3794}, + {88, 3790}, + {90, 3785}, + {92, 3782}, + {95, 3778}, + {97, 3773}, + {100, 3768}, + {103, 3761}, + {106, 3753}, + {107, 3742}, + {110, 3727}, + {112, 3712}, + {115, 3704}, + {118, 3701}, + {119, 3698}, + {122, 3692}, + {125, 3680}, + {127, 3625}, + {130, 3528}, + {133, 3472}, + {134, 3403}, + {136, 3323}, + {137, 3267}, + {137, 3230}, + {137, 3203}, + {137, 3180}, + {137, 3157}, + {137, 3141}, + {137, 3124}, + {137, 3109}, + {137, 3096}, + {137, 3084}, + {137, 3079}, + {137, 3067}, + {137, 3058}, + {137, 3047}, + {137, 3041}, + {137, 3032}, + {137, 3029}, + {137, 3018}, + {137, 3008}, + {137, 3002}, + {137, 3003}, + {137, 2995}, + {137, 2985}, + {137, 2983}, + {137, 2979}, + {137, 2967}, + }, + { + {0, 4316}, + {3, 4283}, + {5, 4244}, + {7, 4210}, + {10, 4185}, + {12, 4164}, + {15, 4144}, + {18, 4128}, + {21, 4109}, + {22, 4093}, + {25, 4080}, + {27, 4069}, + {30, 4047}, + {33, 4023}, + {36, 4003}, + {37, 3989}, + {40, 3977}, + {42, 3967}, + {45, 3955}, + {48, 3940}, + {49, 3923}, + {52, 3907}, + {55, 3891}, + {58, 3877}, + {60, 3864}, + {63, 3855}, + {64, 3846}, + {67, 3837}, + {70, 3831}, + {73, 3823}, + {75, 3815}, + {78, 3811}, + {79, 3804}, + {82, 3799}, + {85, 3794}, + {88, 3790}, + {90, 3785}, + {92, 3782}, + {95, 3778}, + {97, 3773}, + {100, 3768}, + {103, 3761}, + {106, 3753}, + {107, 3742}, + {110, 3727}, + {112, 3712}, + {115, 3704}, + {118, 3701}, + {119, 3698}, + {122, 3692}, + {125, 3680}, + {127, 3625}, + {130, 3528}, + {133, 3472}, + {134, 3403}, + {136, 3323}, + {137, 3267}, + {137, 3230}, + {137, 3203}, + {137, 3180}, + {137, 3157}, + {137, 3141}, + {137, 3124}, + {137, 3109}, + {137, 3096}, + {137, 3084}, + {137, 3079}, + {137, 3067}, + {137, 3058}, + {137, 3047}, + {137, 3041}, + {137, 3032}, + {137, 3029}, + {137, 3018}, + {137, 3008}, + {137, 3002}, + {137, 3003}, + {137, 2995}, + {137, 2985}, + {137, 2983}, + {137, 2979}, + {137, 2967}, + }, + { + {0, 4316}, + {3, 4283}, + {5, 4244}, + {7, 4210}, + {10, 4185}, + {12, 4164}, + {15, 4144}, + {18, 4128}, + {21, 4109}, + {22, 4093}, + {25, 4080}, + {27, 4069}, + {30, 4047}, + {33, 4023}, + {36, 4003}, + {37, 3989}, + {40, 3977}, + {42, 3967}, + {45, 3955}, + {48, 3940}, + {49, 3923}, + {52, 3907}, + {55, 3891}, + {58, 3877}, + {60, 3864}, + {63, 3855}, + {64, 3846}, + {67, 3837}, + {70, 3831}, + {73, 3823}, + {75, 3815}, + {78, 3811}, + {79, 3804}, + {82, 3799}, + {85, 3794}, + {88, 3790}, + {90, 3785}, + {92, 3782}, + {95, 3778}, + {97, 3773}, + {100, 3768}, + {103, 3761}, + {106, 3753}, + {107, 3742}, + {110, 3727}, + {112, 3712}, + {115, 3704}, + {118, 3701}, + {119, 3698}, + {122, 3692}, + {125, 3680}, + {127, 3625}, + {130, 3528}, + {133, 3472}, + {134, 3403}, + {136, 3323}, + {137, 3267}, + {137, 3230}, + {137, 3203}, + {137, 3180}, + {137, 3157}, + {137, 3141}, + {137, 3124}, + {137, 3109}, + {137, 3096}, + {137, 3084}, + {137, 3079}, + {137, 3067}, + {137, 3058}, + {137, 3047}, + {137, 3041}, + {137, 3032}, + {137, 3029}, + {137, 3018}, + {137, 3008}, + {137, 3002}, + {137, 3003}, + {137, 2995}, + {137, 2985}, + {137, 2983}, + {137, 2979}, + {137, 2967}, + } +}; + +/* T2 25C*/ +BATTERY_PROFILE_STRUCT battery_profile_t2[TOTAL_BATTERY_NUMBER][82] = { + { + {0, 4317}, + {2, 4292}, + {3, 4270}, + {5, 4250}, + {8, 4231}, + {9, 4213}, + {11, 4195}, + {13, 4176}, + {14, 4159}, + {16, 4143}, + {18, 4125}, + {20, 4110}, + {22, 4093}, + {24, 4077}, + {25, 4061}, + {27, 4047}, + {29, 4030}, + {32, 4014}, + {33, 4001}, + {35, 3988}, + {37, 3976}, + {38, 3962}, + {40, 3951}, + {42, 3935}, + {43, 3916}, + {46, 3897}, + {48, 3881}, + {49, 3869}, + {51, 3859}, + {53, 3849}, + {54, 3840}, + {57, 3835}, + {59, 3827}, + {60, 3820}, + {62, 3813}, + {64, 3807}, + {65, 3803}, + {67, 3797}, + {70, 3790}, + {71, 3786}, + {73, 3782}, + {75, 3777}, + {76, 3770}, + {78, 3763}, + {80, 3755}, + {83, 3745}, + {84, 3734}, + {86, 3717}, + {88, 3699}, + {89, 3692}, + {91, 3690}, + {93, 3689}, + {95, 3688}, + {97, 3676}, + {99, 3623}, + {100, 3548}, + {102, 3500}, + {104, 3482}, + {105, 3442}, + {108, 3323}, + {109, 3204}, + {109, 3162}, + {109, 3128}, + {109, 3098}, + {109, 3073}, + {110, 3053}, + {110, 3036}, + {110, 3023}, + {110, 3012}, + {110, 2998}, + {110, 2987}, + {110, 2978}, + {110, 2971}, + {110, 2963}, + {110, 2958}, + {110, 2956}, + {110, 2953}, + {110, 2948}, + {110, 2940}, + {110, 2934}, + {110, 2929}, + {110, 2926}, + }, + { + {0, 4317}, + {2, 4292}, + {3, 4270}, + {5, 4250}, + {8, 4231}, + {9, 4213}, + {11, 4195}, + {13, 4176}, + {14, 4159}, + {16, 4143}, + {18, 4125}, + {20, 4110}, + {22, 4093}, + {24, 4077}, + {25, 4061}, + {27, 4047}, + {29, 4030}, + {32, 4014}, + {33, 4001}, + {35, 3988}, + {37, 3976}, + {38, 3962}, + {40, 3951}, + {42, 3935}, + {43, 3916}, + {46, 3897}, + {48, 3881}, + {49, 3869}, + {51, 3859}, + {53, 3849}, + {54, 3840}, + {57, 3835}, + {59, 3827}, + {60, 3820}, + {62, 3813}, + {64, 3807}, + {65, 3803}, + {67, 3797}, + {70, 3790}, + {71, 3786}, + {73, 3782}, + {75, 3777}, + {76, 3770}, + {78, 3763}, + {80, 3755}, + {83, 3745}, + {84, 3734}, + {86, 3717}, + {88, 3699}, + {89, 3692}, + {91, 3690}, + {93, 3689}, + {95, 3688}, + {97, 3676}, + {99, 3623}, + {100, 3548}, + {102, 3500}, + {104, 3482}, + {105, 3442}, + {108, 3323}, + {109, 3204}, + {109, 3162}, + {109, 3128}, + {109, 3098}, + {109, 3073}, + {110, 3053}, + {110, 3036}, + {110, 3023}, + {110, 3012}, + {110, 2998}, + {110, 2987}, + {110, 2978}, + {110, 2971}, + {110, 2963}, + {110, 2958}, + {110, 2956}, + {110, 2953}, + {110, 2948}, + {110, 2940}, + {110, 2934}, + {110, 2929}, + {110, 2926}, + }, + { + {0, 4317}, + {2, 4292}, + {3, 4270}, + {5, 4250}, + {8, 4231}, + {9, 4213}, + {11, 4195}, + {13, 4176}, + {14, 4159}, + {16, 4143}, + {18, 4125}, + {20, 4110}, + {22, 4093}, + {24, 4077}, + {25, 4061}, + {27, 4047}, + {29, 4030}, + {32, 4014}, + {33, 4001}, + {35, 3988}, + {37, 3976}, + {38, 3962}, + {40, 3951}, + {42, 3935}, + {43, 3916}, + {46, 3897}, + {48, 3881}, + {49, 3869}, + {51, 3859}, + {53, 3849}, + {54, 3840}, + {57, 3835}, + {59, 3827}, + {60, 3820}, + {62, 3813}, + {64, 3807}, + {65, 3803}, + {67, 3797}, + {70, 3790}, + {71, 3786}, + {73, 3782}, + {75, 3777}, + {76, 3770}, + {78, 3763}, + {80, 3755}, + {83, 3745}, + {84, 3734}, + {86, 3717}, + {88, 3699}, + {89, 3692}, + {91, 3690}, + {93, 3689}, + {95, 3688}, + {97, 3676}, + {99, 3623}, + {100, 3548}, + {102, 3500}, + {104, 3482}, + {105, 3442}, + {108, 3323}, + {109, 3204}, + {109, 3162}, + {109, 3128}, + {109, 3098}, + {109, 3073}, + {110, 3053}, + {110, 3036}, + {110, 3023}, + {110, 3012}, + {110, 2998}, + {110, 2987}, + {110, 2978}, + {110, 2971}, + {110, 2963}, + {110, 2958}, + {110, 2956}, + {110, 2953}, + {110, 2948}, + {110, 2940}, + {110, 2934}, + {110, 2929}, + {110, 2926}, + }, + { + {0, 4317}, + {2, 4292}, + {3, 4270}, + {5, 4250}, + {8, 4231}, + {9, 4213}, + {11, 4195}, + {13, 4176}, + {14, 4159}, + {16, 4143}, + {18, 4125}, + {20, 4110}, + {22, 4093}, + {24, 4077}, + {25, 4061}, + {27, 4047}, + {29, 4030}, + {32, 4014}, + {33, 4001}, + {35, 3988}, + {37, 3976}, + {38, 3962}, + {40, 3951}, + {42, 3935}, + {43, 3916}, + {46, 3897}, + {48, 3881}, + {49, 3869}, + {51, 3859}, + {53, 3849}, + {54, 3840}, + {57, 3835}, + {59, 3827}, + {60, 3820}, + {62, 3813}, + {64, 3807}, + {65, 3803}, + {67, 3797}, + {70, 3790}, + {71, 3786}, + {73, 3782}, + {75, 3777}, + {76, 3770}, + {78, 3763}, + {80, 3755}, + {83, 3745}, + {84, 3734}, + {86, 3717}, + {88, 3699}, + {89, 3692}, + {91, 3690}, + {93, 3689}, + {95, 3688}, + {97, 3676}, + {99, 3623}, + {100, 3548}, + {102, 3500}, + {104, 3482}, + {105, 3442}, + {108, 3323}, + {109, 3204}, + {109, 3162}, + {109, 3128}, + {109, 3098}, + {109, 3073}, + {110, 3053}, + {110, 3036}, + {110, 3023}, + {110, 3012}, + {110, 2998}, + {110, 2987}, + {110, 2978}, + {110, 2971}, + {110, 2963}, + {110, 2958}, + {110, 2956}, + {110, 2953}, + {110, 2948}, + {110, 2940}, + {110, 2934}, + {110, 2929}, + {110, 2926}, + } +}; + +/* T3 50C*/ +BATTERY_PROFILE_STRUCT battery_profile_t3[TOTAL_BATTERY_NUMBER][82] = { + { + {0, 4331}, + {2, 4305}, + {3, 4284}, + {5, 4265}, + {7, 4244}, + {8, 4225}, + {10, 4206}, + {12, 4188}, + {13, 4170}, + {15, 4153}, + {17, 4135}, + {18, 4119}, + {20, 4102}, + {22, 4085}, + {24, 4069}, + {26, 4054}, + {28, 4038}, + {30, 4023}, + {31, 4010}, + {33, 3996}, + {35, 3984}, + {36, 3970}, + {38, 3958}, + {40, 3947}, + {41, 3934}, + {43, 3921}, + {45, 3904}, + {46, 3884}, + {48, 3868}, + {50, 3857}, + {51, 3848}, + {53, 3838}, + {55, 3832}, + {57, 3824}, + {58, 3817}, + {60, 3811}, + {62, 3806}, + {63, 3800}, + {65, 3794}, + {67, 3790}, + {68, 3784}, + {70, 3777}, + {72, 3763}, + {73, 3758}, + {76, 3750}, + {78, 3742}, + {79, 3733}, + {81, 3723}, + {83, 3709}, + {84, 3694}, + {86, 3678}, + {88, 3676}, + {89, 3675}, + {91, 3674}, + {93, 3669}, + {94, 3625}, + {96, 3547}, + {98, 3495}, + {100, 3458}, + {101, 3331}, + {102, 3140}, + {103, 3078}, + {103, 3033}, + {103, 3001}, + {103, 2980}, + {103, 2960}, + {103, 2944}, + {103, 2932}, + {103, 2921}, + {103, 2913}, + {103, 2903}, + {103, 2899}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + }, + { + {0, 4331}, + {2, 4305}, + {3, 4284}, + {5, 4265}, + {7, 4244}, + {8, 4225}, + {10, 4206}, + {12, 4188}, + {13, 4170}, + {15, 4153}, + {17, 4135}, + {18, 4119}, + {20, 4102}, + {22, 4085}, + {24, 4069}, + {26, 4054}, + {28, 4038}, + {30, 4023}, + {31, 4010}, + {33, 3996}, + {35, 3984}, + {36, 3970}, + {38, 3958}, + {40, 3947}, + {41, 3934}, + {43, 3921}, + {45, 3904}, + {46, 3884}, + {48, 3868}, + {50, 3857}, + {51, 3848}, + {53, 3838}, + {55, 3832}, + {57, 3824}, + {58, 3817}, + {60, 3811}, + {62, 3806}, + {63, 3800}, + {65, 3794}, + {67, 3790}, + {68, 3784}, + {70, 3777}, + {72, 3763}, + {73, 3758}, + {76, 3750}, + {78, 3742}, + {79, 3733}, + {81, 3723}, + {83, 3709}, + {84, 3694}, + {86, 3678}, + {88, 3676}, + {89, 3675}, + {91, 3674}, + {93, 3669}, + {94, 3625}, + {96, 3547}, + {98, 3495}, + {100, 3458}, + {101, 3331}, + {102, 3140}, + {103, 3078}, + {103, 3033}, + {103, 3001}, + {103, 2980}, + {103, 2960}, + {103, 2944}, + {103, 2932}, + {103, 2921}, + {103, 2913}, + {103, 2903}, + {103, 2899}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + }, + { + {0, 4331}, + {2, 4305}, + {3, 4284}, + {5, 4265}, + {7, 4244}, + {8, 4225}, + {10, 4206}, + {12, 4188}, + {13, 4170}, + {15, 4153}, + {17, 4135}, + {18, 4119}, + {20, 4102}, + {22, 4085}, + {24, 4069}, + {26, 4054}, + {28, 4038}, + {30, 4023}, + {31, 4010}, + {33, 3996}, + {35, 3984}, + {36, 3970}, + {38, 3958}, + {40, 3947}, + {41, 3934}, + {43, 3921}, + {45, 3904}, + {46, 3884}, + {48, 3868}, + {50, 3857}, + {51, 3848}, + {53, 3838}, + {55, 3832}, + {57, 3824}, + {58, 3817}, + {60, 3811}, + {62, 3806}, + {63, 3800}, + {65, 3794}, + {67, 3790}, + {68, 3784}, + {70, 3777}, + {72, 3763}, + {73, 3758}, + {76, 3750}, + {78, 3742}, + {79, 3733}, + {81, 3723}, + {83, 3709}, + {84, 3694}, + {86, 3678}, + {88, 3676}, + {89, 3675}, + {91, 3674}, + {93, 3669}, + {94, 3625}, + {96, 3547}, + {98, 3495}, + {100, 3458}, + {101, 3331}, + {102, 3140}, + {103, 3078}, + {103, 3033}, + {103, 3001}, + {103, 2980}, + {103, 2960}, + {103, 2944}, + {103, 2932}, + {103, 2921}, + {103, 2913}, + {103, 2903}, + {103, 2899}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + }, + { + {0, 4331}, + {2, 4305}, + {3, 4284}, + {5, 4265}, + {7, 4244}, + {8, 4225}, + {10, 4206}, + {12, 4188}, + {13, 4170}, + {15, 4153}, + {17, 4135}, + {18, 4119}, + {20, 4102}, + {22, 4085}, + {24, 4069}, + {26, 4054}, + {28, 4038}, + {30, 4023}, + {31, 4010}, + {33, 3996}, + {35, 3984}, + {36, 3970}, + {38, 3958}, + {40, 3947}, + {41, 3934}, + {43, 3921}, + {45, 3904}, + {46, 3884}, + {48, 3868}, + {50, 3857}, + {51, 3848}, + {53, 3838}, + {55, 3832}, + {57, 3824}, + {58, 3817}, + {60, 3811}, + {62, 3806}, + {63, 3800}, + {65, 3794}, + {67, 3790}, + {68, 3784}, + {70, 3777}, + {72, 3763}, + {73, 3758}, + {76, 3750}, + {78, 3742}, + {79, 3733}, + {81, 3723}, + {83, 3709}, + {84, 3694}, + {86, 3678}, + {88, 3676}, + {89, 3675}, + {91, 3674}, + {93, 3669}, + {94, 3625}, + {96, 3547}, + {98, 3495}, + {100, 3458}, + {101, 3331}, + {102, 3140}, + {103, 3078}, + {103, 3033}, + {103, 3001}, + {103, 2980}, + {103, 2960}, + {103, 2944}, + {103, 2932}, + {103, 2921}, + {103, 2913}, + {103, 2903}, + {103, 2899}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + {103, 2889}, + } +}; + +/* battery profile for actual temperature. The size should be the same as T1, T2 and T3*/ +BATTERY_PROFILE_STRUCT battery_profile_temperature[TOTAL_BATTERY_NUMBER][82] = { + { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + }, + { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + }, + { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + }, + { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + } +}; + +/* ============================================================ +// Table +// ============================================================*/ +/* T0 -10C*/ +R_PROFILE_STRUCT r_profile_t0[TOTAL_BATTERY_NUMBER][82] = { + { + {408, 4303}, + {408, 4281}, + {415, 4261}, + {425, 4240}, + {430, 4217}, + {440, 4194}, + {463, 4169}, + {490, 4145}, + {525, 4117}, + {573, 4088}, + {615, 4068}, + {650, 4047}, + {675, 4019}, + {685, 3997}, + {705, 3981}, + {713, 3967}, + {720, 3956}, + {733, 3942}, + {728, 3929}, + {738, 3913}, + {725, 3895}, + {735, 3880}, + {745, 3869}, + {748, 3857}, + {760, 3848}, + {773, 3839}, + {783, 3830}, + {803, 3823}, + {820, 3818}, + {835, 3811}, + {863, 3806}, + {888, 3800}, + {903, 3796}, + {925, 3791}, + {955, 3787}, + {975, 3781}, + {1000, 3775}, + {1035, 3770}, + {1058, 3760}, + {1090, 3752}, + {1105, 3742}, + {1135, 3731}, + {1168, 3721}, + {1210, 3713}, + {1255, 3704}, + {1345, 3698}, + {1430, 3688}, + {1518, 3665}, + {1570, 3613}, + {1618, 3526}, + {1668, 3466}, + {1613, 3444}, + {1563, 3424}, + {1510, 3404}, + {1460, 3381}, + {1400, 3357}, + {1333, 3332}, + {1283, 3310}, + {1233, 3291}, + {1198, 3274}, + {1155, 3259}, + {1128, 3245}, + {1093, 3234}, + {1075, 3221}, + {1053, 3212}, + {1023, 3204}, + {1018, 3193}, + {1005, 3186}, + {978, 3179}, + {960, 3168}, + {940, 3162}, + {895, 3157}, + {890, 3151}, + {863, 3143}, + {925, 3133}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125} + }, + { + {408, 4303}, + {408, 4281}, + {415, 4261}, + {425, 4240}, + {430, 4217}, + {440, 4194}, + {463, 4169}, + {490, 4145}, + {525, 4117}, + {573, 4088}, + {615, 4068}, + {650, 4047}, + {675, 4019}, + {685, 3997}, + {705, 3981}, + {713, 3967}, + {720, 3956}, + {733, 3942}, + {728, 3929}, + {738, 3913}, + {725, 3895}, + {735, 3880}, + {745, 3869}, + {748, 3857}, + {760, 3848}, + {773, 3839}, + {783, 3830}, + {803, 3823}, + {820, 3818}, + {835, 3811}, + {863, 3806}, + {888, 3800}, + {903, 3796}, + {925, 3791}, + {955, 3787}, + {975, 3781}, + {1000, 3775}, + {1035, 3770}, + {1058, 3760}, + {1090, 3752}, + {1105, 3742}, + {1135, 3731}, + {1168, 3721}, + {1210, 3713}, + {1255, 3704}, + {1345, 3698}, + {1430, 3688}, + {1518, 3665}, + {1570, 3613}, + {1618, 3526}, + {1668, 3466}, + {1613, 3444}, + {1563, 3424}, + {1510, 3404}, + {1460, 3381}, + {1400, 3357}, + {1333, 3332}, + {1283, 3310}, + {1233, 3291}, + {1198, 3274}, + {1155, 3259}, + {1128, 3245}, + {1093, 3234}, + {1075, 3221}, + {1053, 3212}, + {1023, 3204}, + {1018, 3193}, + {1005, 3186}, + {978, 3179}, + {960, 3168}, + {940, 3162}, + {895, 3157}, + {890, 3151}, + {863, 3143}, + {925, 3133}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125} + }, + { + {408, 4303}, + {408, 4281}, + {415, 4261}, + {425, 4240}, + {430, 4217}, + {440, 4194}, + {463, 4169}, + {490, 4145}, + {525, 4117}, + {573, 4088}, + {615, 4068}, + {650, 4047}, + {675, 4019}, + {685, 3997}, + {705, 3981}, + {713, 3967}, + {720, 3956}, + {733, 3942}, + {728, 3929}, + {738, 3913}, + {725, 3895}, + {735, 3880}, + {745, 3869}, + {748, 3857}, + {760, 3848}, + {773, 3839}, + {783, 3830}, + {803, 3823}, + {820, 3818}, + {835, 3811}, + {863, 3806}, + {888, 3800}, + {903, 3796}, + {925, 3791}, + {955, 3787}, + {975, 3781}, + {1000, 3775}, + {1035, 3770}, + {1058, 3760}, + {1090, 3752}, + {1105, 3742}, + {1135, 3731}, + {1168, 3721}, + {1210, 3713}, + {1255, 3704}, + {1345, 3698}, + {1430, 3688}, + {1518, 3665}, + {1570, 3613}, + {1618, 3526}, + {1668, 3466}, + {1613, 3444}, + {1563, 3424}, + {1510, 3404}, + {1460, 3381}, + {1400, 3357}, + {1333, 3332}, + {1283, 3310}, + {1233, 3291}, + {1198, 3274}, + {1155, 3259}, + {1128, 3245}, + {1093, 3234}, + {1075, 3221}, + {1053, 3212}, + {1023, 3204}, + {1018, 3193}, + {1005, 3186}, + {978, 3179}, + {960, 3168}, + {940, 3162}, + {895, 3157}, + {890, 3151}, + {863, 3143}, + {925, 3133}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125} + }, + { + {408, 4303}, + {408, 4281}, + {415, 4261}, + {425, 4240}, + {430, 4217}, + {440, 4194}, + {463, 4169}, + {490, 4145}, + {525, 4117}, + {573, 4088}, + {615, 4068}, + {650, 4047}, + {675, 4019}, + {685, 3997}, + {705, 3981}, + {713, 3967}, + {720, 3956}, + {733, 3942}, + {728, 3929}, + {738, 3913}, + {725, 3895}, + {735, 3880}, + {745, 3869}, + {748, 3857}, + {760, 3848}, + {773, 3839}, + {783, 3830}, + {803, 3823}, + {820, 3818}, + {835, 3811}, + {863, 3806}, + {888, 3800}, + {903, 3796}, + {925, 3791}, + {955, 3787}, + {975, 3781}, + {1000, 3775}, + {1035, 3770}, + {1058, 3760}, + {1090, 3752}, + {1105, 3742}, + {1135, 3731}, + {1168, 3721}, + {1210, 3713}, + {1255, 3704}, + {1345, 3698}, + {1430, 3688}, + {1518, 3665}, + {1570, 3613}, + {1618, 3526}, + {1668, 3466}, + {1613, 3444}, + {1563, 3424}, + {1510, 3404}, + {1460, 3381}, + {1400, 3357}, + {1333, 3332}, + {1283, 3310}, + {1233, 3291}, + {1198, 3274}, + {1155, 3259}, + {1128, 3245}, + {1093, 3234}, + {1075, 3221}, + {1053, 3212}, + {1023, 3204}, + {1018, 3193}, + {1005, 3186}, + {978, 3179}, + {960, 3168}, + {940, 3162}, + {895, 3157}, + {890, 3151}, + {863, 3143}, + {925, 3133}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125}, + {893, 3125} + } +}; + +/* T1 0C*/ +R_PROFILE_STRUCT r_profile_t1[TOTAL_BATTERY_NUMBER][82] = { + { + {258, 4316}, + {258, 4283}, + {278, 4244}, + {303, 4210}, + {333, 4185}, + {343, 4164}, + {350, 4144}, + {365, 4128}, + {370, 4109}, + {370, 4093}, + {380, 4080}, + {403, 4069}, + {395, 4047}, + {403, 4023}, + {403, 4003}, + {413, 3989}, + {418, 3977}, + {420, 3967}, + {423, 3955}, + {415, 3940}, + {410, 3923}, + {400, 3907}, + {393, 3891}, + {393, 3877}, + {388, 3864}, + {395, 3855}, + {403, 3846}, + {405, 3837}, + {415, 3831}, + {425, 3823}, + {430, 3815}, + {443, 3811}, + {450, 3804}, + {465, 3799}, + {475, 3794}, + {483, 3790}, + {490, 3785}, + {503, 3782}, + {520, 3778}, + {533, 3773}, + {545, 3768}, + {563, 3761}, + {588, 3753}, + {600, 3742}, + {608, 3727}, + {615, 3712}, + {635, 3704}, + {670, 3701}, + {710, 3698}, + {765, 3692}, + {840, 3680}, + {880, 3625}, + {915, 3528}, + {1080, 3472}, + {1323, 3403}, + {1315, 3323}, + {1180, 3267}, + {1080, 3230}, + {1010, 3203}, + {958, 3180}, + {925, 3157}, + {888, 3141}, + {860, 3124}, + {810, 3109}, + {788, 3096}, + {765, 3084}, + {700, 3079}, + {745, 3067}, + {680, 3058}, + {685, 3047}, + {650, 3041}, + {683, 3032}, + {615, 3029}, + {643, 3018}, + {660, 3008}, + {635, 3002}, + {530, 3003}, + {640, 2995}, + {595, 2985}, + {535, 2983}, + {463, 2979}, + {600, 2967} + }, + { + {258, 4316}, + {258, 4283}, + {278, 4244}, + {303, 4210}, + {333, 4185}, + {343, 4164}, + {350, 4144}, + {365, 4128}, + {370, 4109}, + {370, 4093}, + {380, 4080}, + {403, 4069}, + {395, 4047}, + {403, 4023}, + {403, 4003}, + {413, 3989}, + {418, 3977}, + {420, 3967}, + {423, 3955}, + {415, 3940}, + {410, 3923}, + {400, 3907}, + {393, 3891}, + {393, 3877}, + {388, 3864}, + {395, 3855}, + {403, 3846}, + {405, 3837}, + {415, 3831}, + {425, 3823}, + {430, 3815}, + {443, 3811}, + {450, 3804}, + {465, 3799}, + {475, 3794}, + {483, 3790}, + {490, 3785}, + {503, 3782}, + {520, 3778}, + {533, 3773}, + {545, 3768}, + {563, 3761}, + {588, 3753}, + {600, 3742}, + {608, 3727}, + {615, 3712}, + {635, 3704}, + {670, 3701}, + {710, 3698}, + {765, 3692}, + {840, 3680}, + {880, 3625}, + {915, 3528}, + {1080, 3472}, + {1323, 3403}, + {1315, 3323}, + {1180, 3267}, + {1080, 3230}, + {1010, 3203}, + {958, 3180}, + {925, 3157}, + {888, 3141}, + {860, 3124}, + {810, 3109}, + {788, 3096}, + {765, 3084}, + {700, 3079}, + {745, 3067}, + {680, 3058}, + {685, 3047}, + {650, 3041}, + {683, 3032}, + {615, 3029}, + {643, 3018}, + {660, 3008}, + {635, 3002}, + {530, 3003}, + {640, 2995}, + {595, 2985}, + {535, 2983}, + {463, 2979}, + {600, 2967} + }, + { + {258, 4316}, + {258, 4283}, + {278, 4244}, + {303, 4210}, + {333, 4185}, + {343, 4164}, + {350, 4144}, + {365, 4128}, + {370, 4109}, + {370, 4093}, + {380, 4080}, + {403, 4069}, + {395, 4047}, + {403, 4023}, + {403, 4003}, + {413, 3989}, + {418, 3977}, + {420, 3967}, + {423, 3955}, + {415, 3940}, + {410, 3923}, + {400, 3907}, + {393, 3891}, + {393, 3877}, + {388, 3864}, + {395, 3855}, + {403, 3846}, + {405, 3837}, + {415, 3831}, + {425, 3823}, + {430, 3815}, + {443, 3811}, + {450, 3804}, + {465, 3799}, + {475, 3794}, + {483, 3790}, + {490, 3785}, + {503, 3782}, + {520, 3778}, + {533, 3773}, + {545, 3768}, + {563, 3761}, + {588, 3753}, + {600, 3742}, + {608, 3727}, + {615, 3712}, + {635, 3704}, + {670, 3701}, + {710, 3698}, + {765, 3692}, + {840, 3680}, + {880, 3625}, + {915, 3528}, + {1080, 3472}, + {1323, 3403}, + {1315, 3323}, + {1180, 3267}, + {1080, 3230}, + {1010, 3203}, + {958, 3180}, + {925, 3157}, + {888, 3141}, + {860, 3124}, + {810, 3109}, + {788, 3096}, + {765, 3084}, + {700, 3079}, + {745, 3067}, + {680, 3058}, + {685, 3047}, + {650, 3041}, + {683, 3032}, + {615, 3029}, + {643, 3018}, + {660, 3008}, + {635, 3002}, + {530, 3003}, + {640, 2995}, + {595, 2985}, + {535, 2983}, + {463, 2979}, + {600, 2967} + }, + { + {258, 4316}, + {258, 4283}, + {278, 4244}, + {303, 4210}, + {333, 4185}, + {343, 4164}, + {350, 4144}, + {365, 4128}, + {370, 4109}, + {370, 4093}, + {380, 4080}, + {403, 4069}, + {395, 4047}, + {403, 4023}, + {403, 4003}, + {413, 3989}, + {418, 3977}, + {420, 3967}, + {423, 3955}, + {415, 3940}, + {410, 3923}, + {400, 3907}, + {393, 3891}, + {393, 3877}, + {388, 3864}, + {395, 3855}, + {403, 3846}, + {405, 3837}, + {415, 3831}, + {425, 3823}, + {430, 3815}, + {443, 3811}, + {450, 3804}, + {465, 3799}, + {475, 3794}, + {483, 3790}, + {490, 3785}, + {503, 3782}, + {520, 3778}, + {533, 3773}, + {545, 3768}, + {563, 3761}, + {588, 3753}, + {600, 3742}, + {608, 3727}, + {615, 3712}, + {635, 3704}, + {670, 3701}, + {710, 3698}, + {765, 3692}, + {840, 3680}, + {880, 3625}, + {915, 3528}, + {1080, 3472}, + {1323, 3403}, + {1315, 3323}, + {1180, 3267}, + {1080, 3230}, + {1010, 3203}, + {958, 3180}, + {925, 3157}, + {888, 3141}, + {860, 3124}, + {810, 3109}, + {788, 3096}, + {765, 3084}, + {700, 3079}, + {745, 3067}, + {680, 3058}, + {685, 3047}, + {650, 3041}, + {683, 3032}, + {615, 3029}, + {643, 3018}, + {660, 3008}, + {635, 3002}, + {530, 3003}, + {640, 2995}, + {595, 2985}, + {535, 2983}, + {463, 2979}, + {600, 2967} + } +}; + +/* T2 25C*/ +R_PROFILE_STRUCT r_profile_t2[TOTAL_BATTERY_NUMBER][82] = { + { + {173, 4317}, + {173, 4292}, + {175, 4270}, + {170, 4250}, + {173, 4231}, + {173, 4213}, + {178, 4195}, + {173, 4176}, + {183, 4159}, + {193, 4143}, + {193, 4125}, + {203, 4110}, + {205, 4093}, + {208, 4077}, + {205, 4061}, + {213, 4047}, + {215, 4030}, + {223, 4014}, + {230, 4001}, + {233, 3988}, + {240, 3976}, + {243, 3962}, + {248, 3951}, + {243, 3935}, + {223, 3916}, + {203, 3897}, + {195, 3881}, + {188, 3869}, + {188, 3859}, + {185, 3849}, + {183, 3840}, + {195, 3835}, + {198, 3827}, + {195, 3820}, + {198, 3813}, + {200, 3807}, + {208, 3803}, + {205, 3797}, + {205, 3790}, + {205, 3786}, + {210, 3782}, + {213, 3777}, + {208, 3770}, + {203, 3763}, + {198, 3755}, + {195, 3745}, + {198, 3734}, + {193, 3717}, + {193, 3699}, + {193, 3692}, + {195, 3690}, + {205, 3689}, + {220, 3688}, + {238, 3676}, + {238, 3623}, + {255, 3548}, + {293, 3500}, + {330, 3482}, + {390, 3442}, + {485, 3323}, + {1018, 3204}, + {925, 3162}, + {838, 3128}, + {748, 3098}, + {720, 3073}, + {668, 3053}, + {608, 3036}, + {560, 3023}, + {550, 3012}, + {558, 2998}, + {538, 2987}, + {515, 2978}, + {485, 2971}, + {458, 2963}, + {455, 2958}, + {403, 2956}, + {398, 2953}, + {373, 2948}, + {373, 2940}, + {408, 2934}, + {420, 2929}, + {335, 2926} + }, + { + {173, 4317}, + {173, 4292}, + {175, 4270}, + {170, 4250}, + {173, 4231}, + {173, 4213}, + {178, 4195}, + {173, 4176}, + {183, 4159}, + {193, 4143}, + {193, 4125}, + {203, 4110}, + {205, 4093}, + {208, 4077}, + {205, 4061}, + {213, 4047}, + {215, 4030}, + {223, 4014}, + {230, 4001}, + {233, 3988}, + {240, 3976}, + {243, 3962}, + {248, 3951}, + {243, 3935}, + {223, 3916}, + {203, 3897}, + {195, 3881}, + {188, 3869}, + {188, 3859}, + {185, 3849}, + {183, 3840}, + {195, 3835}, + {198, 3827}, + {195, 3820}, + {198, 3813}, + {200, 3807}, + {208, 3803}, + {205, 3797}, + {205, 3790}, + {205, 3786}, + {210, 3782}, + {213, 3777}, + {208, 3770}, + {203, 3763}, + {198, 3755}, + {195, 3745}, + {198, 3734}, + {193, 3717}, + {193, 3699}, + {193, 3692}, + {195, 3690}, + {205, 3689}, + {220, 3688}, + {238, 3676}, + {238, 3623}, + {255, 3548}, + {293, 3500}, + {330, 3482}, + {390, 3442}, + {485, 3323}, + {1018, 3204}, + {925, 3162}, + {838, 3128}, + {748, 3098}, + {720, 3073}, + {668, 3053}, + {608, 3036}, + {560, 3023}, + {550, 3012}, + {558, 2998}, + {538, 2987}, + {515, 2978}, + {485, 2971}, + {458, 2963}, + {455, 2958}, + {403, 2956}, + {398, 2953}, + {373, 2948}, + {373, 2940}, + {408, 2934}, + {420, 2929}, + {335, 2926} + }, + { + {173, 4317}, + {173, 4292}, + {175, 4270}, + {170, 4250}, + {173, 4231}, + {173, 4213}, + {178, 4195}, + {173, 4176}, + {183, 4159}, + {193, 4143}, + {193, 4125}, + {203, 4110}, + {205, 4093}, + {208, 4077}, + {205, 4061}, + {213, 4047}, + {215, 4030}, + {223, 4014}, + {230, 4001}, + {233, 3988}, + {240, 3976}, + {243, 3962}, + {248, 3951}, + {243, 3935}, + {223, 3916}, + {203, 3897}, + {195, 3881}, + {188, 3869}, + {188, 3859}, + {185, 3849}, + {183, 3840}, + {195, 3835}, + {198, 3827}, + {195, 3820}, + {198, 3813}, + {200, 3807}, + {208, 3803}, + {205, 3797}, + {205, 3790}, + {205, 3786}, + {210, 3782}, + {213, 3777}, + {208, 3770}, + {203, 3763}, + {198, 3755}, + {195, 3745}, + {198, 3734}, + {193, 3717}, + {193, 3699}, + {193, 3692}, + {195, 3690}, + {205, 3689}, + {220, 3688}, + {238, 3676}, + {238, 3623}, + {255, 3548}, + {293, 3500}, + {330, 3482}, + {390, 3442}, + {485, 3323}, + {1018, 3204}, + {925, 3162}, + {838, 3128}, + {748, 3098}, + {720, 3073}, + {668, 3053}, + {608, 3036}, + {560, 3023}, + {550, 3012}, + {558, 2998}, + {538, 2987}, + {515, 2978}, + {485, 2971}, + {458, 2963}, + {455, 2958}, + {403, 2956}, + {398, 2953}, + {373, 2948}, + {373, 2940}, + {408, 2934}, + {420, 2929}, + {335, 2926} + }, + { + {173, 4317}, + {173, 4292}, + {175, 4270}, + {170, 4250}, + {173, 4231}, + {173, 4213}, + {178, 4195}, + {173, 4176}, + {183, 4159}, + {193, 4143}, + {193, 4125}, + {203, 4110}, + {205, 4093}, + {208, 4077}, + {205, 4061}, + {213, 4047}, + {215, 4030}, + {223, 4014}, + {230, 4001}, + {233, 3988}, + {240, 3976}, + {243, 3962}, + {248, 3951}, + {243, 3935}, + {223, 3916}, + {203, 3897}, + {195, 3881}, + {188, 3869}, + {188, 3859}, + {185, 3849}, + {183, 3840}, + {195, 3835}, + {198, 3827}, + {195, 3820}, + {198, 3813}, + {200, 3807}, + {208, 3803}, + {205, 3797}, + {205, 3790}, + {205, 3786}, + {210, 3782}, + {213, 3777}, + {208, 3770}, + {203, 3763}, + {198, 3755}, + {195, 3745}, + {198, 3734}, + {193, 3717}, + {193, 3699}, + {193, 3692}, + {195, 3690}, + {205, 3689}, + {220, 3688}, + {238, 3676}, + {238, 3623}, + {255, 3548}, + {293, 3500}, + {330, 3482}, + {390, 3442}, + {485, 3323}, + {1018, 3204}, + {925, 3162}, + {838, 3128}, + {748, 3098}, + {720, 3073}, + {668, 3053}, + {608, 3036}, + {560, 3023}, + {550, 3012}, + {558, 2998}, + {538, 2987}, + {515, 2978}, + {485, 2971}, + {458, 2963}, + {455, 2958}, + {403, 2956}, + {398, 2953}, + {373, 2948}, + {373, 2940}, + {408, 2934}, + {420, 2929}, + {335, 2926} + } +}; + +/* T3 50C*/ +R_PROFILE_STRUCT r_profile_t3[TOTAL_BATTERY_NUMBER][82] = { + { + {123, 4331}, + {123, 4305}, + {128, 4284}, + {130, 4265}, + {130, 4244}, + {130, 4225}, + {128, 4206}, + {125, 4188}, + {130, 4170}, + {133, 4153}, + {133, 4135}, + {138, 4119}, + {138, 4102}, + {140, 4085}, + {140, 4069}, + {143, 4054}, + {140, 4038}, + {143, 4023}, + {148, 4010}, + {153, 3996}, + {155, 3984}, + {155, 3970}, + {165, 3958}, + {175, 3947}, + {175, 3934}, + {178, 3921}, + {170, 3904}, + {148, 3884}, + {135, 3868}, + {135, 3857}, + {133, 3848}, + {133, 3838}, + {135, 3832}, + {135, 3824}, + {135, 3817}, + {143, 3811}, + {145, 3806}, + {148, 3800}, + {145, 3794}, + {153, 3790}, + {150, 3784}, + {150, 3777}, + {133, 3763}, + {143, 3758}, + {140, 3750}, + {138, 3742}, + {135, 3733}, + {135, 3723}, + {133, 3709}, + {133, 3694}, + {130, 3678}, + {130, 3676}, + {138, 3675}, + {148, 3674}, + {160, 3669}, + {158, 3625}, + {170, 3547}, + {208, 3495}, + {220, 3458}, + {265, 3331}, + {855, 3140}, + {725, 3078}, + {600, 3033}, + {528, 3001}, + {460, 2980}, + {400, 2960}, + {380, 2944}, + {355, 2932}, + {315, 2921}, + {303, 2913}, + {308, 2903}, + {255, 2899}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889} + }, + { + {123, 4331}, + {123, 4305}, + {128, 4284}, + {130, 4265}, + {130, 4244}, + {130, 4225}, + {128, 4206}, + {125, 4188}, + {130, 4170}, + {133, 4153}, + {133, 4135}, + {138, 4119}, + {138, 4102}, + {140, 4085}, + {140, 4069}, + {143, 4054}, + {140, 4038}, + {143, 4023}, + {148, 4010}, + {153, 3996}, + {155, 3984}, + {155, 3970}, + {165, 3958}, + {175, 3947}, + {175, 3934}, + {178, 3921}, + {170, 3904}, + {148, 3884}, + {135, 3868}, + {135, 3857}, + {133, 3848}, + {133, 3838}, + {135, 3832}, + {135, 3824}, + {135, 3817}, + {143, 3811}, + {145, 3806}, + {148, 3800}, + {145, 3794}, + {153, 3790}, + {150, 3784}, + {150, 3777}, + {133, 3763}, + {143, 3758}, + {140, 3750}, + {138, 3742}, + {135, 3733}, + {135, 3723}, + {133, 3709}, + {133, 3694}, + {130, 3678}, + {130, 3676}, + {138, 3675}, + {148, 3674}, + {160, 3669}, + {158, 3625}, + {170, 3547}, + {208, 3495}, + {220, 3458}, + {265, 3331}, + {855, 3140}, + {725, 3078}, + {600, 3033}, + {528, 3001}, + {460, 2980}, + {400, 2960}, + {380, 2944}, + {355, 2932}, + {315, 2921}, + {303, 2913}, + {308, 2903}, + {255, 2899}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889} + }, + { + {123, 4331}, + {123, 4305}, + {128, 4284}, + {130, 4265}, + {130, 4244}, + {130, 4225}, + {128, 4206}, + {125, 4188}, + {130, 4170}, + {133, 4153}, + {133, 4135}, + {138, 4119}, + {138, 4102}, + {140, 4085}, + {140, 4069}, + {143, 4054}, + {140, 4038}, + {143, 4023}, + {148, 4010}, + {153, 3996}, + {155, 3984}, + {155, 3970}, + {165, 3958}, + {175, 3947}, + {175, 3934}, + {178, 3921}, + {170, 3904}, + {148, 3884}, + {135, 3868}, + {135, 3857}, + {133, 3848}, + {133, 3838}, + {135, 3832}, + {135, 3824}, + {135, 3817}, + {143, 3811}, + {145, 3806}, + {148, 3800}, + {145, 3794}, + {153, 3790}, + {150, 3784}, + {150, 3777}, + {133, 3763}, + {143, 3758}, + {140, 3750}, + {138, 3742}, + {135, 3733}, + {135, 3723}, + {133, 3709}, + {133, 3694}, + {130, 3678}, + {130, 3676}, + {138, 3675}, + {148, 3674}, + {160, 3669}, + {158, 3625}, + {170, 3547}, + {208, 3495}, + {220, 3458}, + {265, 3331}, + {855, 3140}, + {725, 3078}, + {600, 3033}, + {528, 3001}, + {460, 2980}, + {400, 2960}, + {380, 2944}, + {355, 2932}, + {315, 2921}, + {303, 2913}, + {308, 2903}, + {255, 2899}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889} + }, + { + {123, 4331}, + {123, 4305}, + {128, 4284}, + {130, 4265}, + {130, 4244}, + {130, 4225}, + {128, 4206}, + {125, 4188}, + {130, 4170}, + {133, 4153}, + {133, 4135}, + {138, 4119}, + {138, 4102}, + {140, 4085}, + {140, 4069}, + {143, 4054}, + {140, 4038}, + {143, 4023}, + {148, 4010}, + {153, 3996}, + {155, 3984}, + {155, 3970}, + {165, 3958}, + {175, 3947}, + {175, 3934}, + {178, 3921}, + {170, 3904}, + {148, 3884}, + {135, 3868}, + {135, 3857}, + {133, 3848}, + {133, 3838}, + {135, 3832}, + {135, 3824}, + {135, 3817}, + {143, 3811}, + {145, 3806}, + {148, 3800}, + {145, 3794}, + {153, 3790}, + {150, 3784}, + {150, 3777}, + {133, 3763}, + {143, 3758}, + {140, 3750}, + {138, 3742}, + {135, 3733}, + {135, 3723}, + {133, 3709}, + {133, 3694}, + {130, 3678}, + {130, 3676}, + {138, 3675}, + {148, 3674}, + {160, 3669}, + {158, 3625}, + {170, 3547}, + {208, 3495}, + {220, 3458}, + {265, 3331}, + {855, 3140}, + {725, 3078}, + {600, 3033}, + {528, 3001}, + {460, 2980}, + {400, 2960}, + {380, 2944}, + {355, 2932}, + {315, 2921}, + {303, 2913}, + {308, 2903}, + {255, 2899}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889}, + {273, 2889} + } +}; + +/* r-table profile for actual temperature. The size should be the same as T1, T2 and T3*/ +R_PROFILE_STRUCT r_profile_temperature[TOTAL_BATTERY_NUMBER][82] = { + { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + }, + { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + }, + { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + }, + { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0} + } +}; + +/* ============================================================ +// function prototype +// ============================================================*/ +int fgauge_get_saddles(void); +BATTERY_PROFILE_STRUCT_P fgauge_get_profile(unsigned int temperature); + +int fgauge_get_saddles_r_table(void); +R_PROFILE_STRUCT_P fgauge_get_profile_r_table(unsigned int temperature); + +#endif + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_charging.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_charging.h new file mode 100644 index 0000000000000000000000000000000000000000..e27745d5067a8e326d9951827b60f2c883e98766 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_charging.h @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _CUST_BAT_H_ +#define _CUST_BAT_H_ + +/* stop charging while in talking mode */ +#define STOP_CHARGING_IN_TAKLING +#define TALKING_RECHARGE_VOLTAGE 3800 +#define TALKING_SYNC_TIME 60 + +/* Battery Temperature Protection */ +#define MTK_TEMPERATURE_RECHARGE_SUPPORT +#define MAX_CHARGE_TEMPERATURE 50 +#define MAX_CHARGE_TEMPERATURE_MINUS_X_DEGREE 47 +#define MIN_CHARGE_TEMPERATURE 0 +#define MIN_CHARGE_TEMPERATURE_PLUS_X_DEGREE 6 +#define ERR_CHARGE_TEMPERATURE 0xFF + +/* Linear Charging Threshold */ +#define V_PRE2CC_THRES 3400 /* mV */ +#define V_CC2TOPOFF_THRES 4352 +#define RECHARGING_VOLTAGE 4110 +#define CHARGING_FULL_CURRENT 150 /* mA */ + +/* Charging Current Setting */ +/* #define CONFIG_USB_IF */ +#define USB_CHARGER_CURRENT_SUSPEND 0/* def CONFIG_USB_IF */ +#define USB_CHARGER_CURRENT_UNCONFIGURED CHARGE_CURRENT_70_00_MA/* 70mA */ +#define USB_CHARGER_CURRENT_CONFIGURED CHARGE_CURRENT_500_00_MA/* 500mA */ + +#define USB_CHARGER_CURRENT CHARGE_CURRENT_500_00_MA /* 500mA */ +/* #define AC_CHARGER_CURRENT CHARGE_CURRENT_650_00_MA */ +#define AC_CHARGER_CURRENT CHARGE_CURRENT_1400_00_MA +#define AC_CHARGER_INPUT_CURRENT CHARGE_CURRENT_1400_00_MA +#define NON_STD_AC_CHARGER_CURRENT CHARGE_CURRENT_900_00_MA +#define CHARGING_HOST_CHARGER_CURRENT CHARGE_CURRENT_650_00_MA +#define APPLE_0_5A_CHARGER_CURRENT CHARGE_CURRENT_500_00_MA +#define APPLE_1_0A_CHARGER_CURRENT CHARGE_CURRENT_900_00_MA +#define APPLE_2_1A_CHARGER_CURRENT CHARGE_CURRENT_1400_00_MA + + +/* Precise Tunning */ +#define BATTERY_AVERAGE_DATA_NUMBER 3 +#define BATTERY_AVERAGE_SIZE 30 + +/* charger error check */ +/* #define BAT_LOW_TEMP_PROTECT_ENABLE // stop charging if temp < MIN_CHARGE_TEMPERATURE */ +#define V_CHARGER_ENABLE 0 /* 1:ON , 0:OFF */ +#define V_CHARGER_MAX 6500 /* 6.5 V */ +#define V_CHARGER_MIN 4400 /* 4.4 V */ + +/* Tracking TIME */ +#define ONEHUNDRED_PERCENT_TRACKING_TIME 10 /* 10 second */ +#define NPERCENT_TRACKING_TIME 20 /* 20 second */ +#define SYNC_TO_REAL_TRACKING_TIME 60 /* 60 second */ +#define V_0PERCENT_TRACKING 3450 /*3450mV */ + +/*#define CUST_SYSTEM_OFF_VOLTAGE 3300 +#define SYSTEM_OFF_VOLTAGE CUST_SYSTEM_OFF_VOLTAGE*/ + +/* Battery Notify */ +#define BATTERY_NOTIFY_CASE_0001_VCHARGER +#define BATTERY_NOTIFY_CASE_0002_VBATTEMP +/* #define BATTERY_NOTIFY_CASE_0003_ICHARGING */ +/* #define BATTERY_NOTIFY_CASE_0004_VBAT */ +/* #define BATTERY_NOTIFY_CASE_0005_TOTAL_CHARGINGTIME */ + +/* High battery support */ +#define HIGH_BATTERY_VOLTAGE_SUPPORT + +/* JEITA parameter */ +/*#define MTK_JEITA_STANDARD_SUPPORT*/ +#define CUST_SOC_JEITA_SYNC_TIME 30 +#define JEITA_RECHARGE_VOLTAGE 4110 /* for linear charging */ +#ifdef HIGH_BATTERY_VOLTAGE_SUPPORT +#define JEITA_TEMP_ABOVE_POS_60_CV_VOLTAGE BATTERY_VOLT_04_240000_V +#define JEITA_TEMP_POS_45_TO_POS_60_CV_VOLTAGE BATTERY_VOLT_04_240000_V +#define JEITA_TEMP_POS_10_TO_POS_45_CV_VOLTAGE BATTERY_VOLT_04_340000_V +#define JEITA_TEMP_POS_0_TO_POS_10_CV_VOLTAGE BATTERY_VOLT_04_240000_V +#define JEITA_TEMP_NEG_10_TO_POS_0_CV_VOLTAGE BATTERY_VOLT_04_040000_V +#define JEITA_TEMP_BELOW_NEG_10_CV_VOLTAGE BATTERY_VOLT_04_040000_V +#else +#define JEITA_TEMP_ABOVE_POS_60_CV_VOLTAGE BATTERY_VOLT_04_100000_V +#define JEITA_TEMP_POS_45_TO_POS_60_CV_VOLTAGE BATTERY_VOLT_04_100000_V +#define JEITA_TEMP_POS_10_TO_POS_45_CV_VOLTAGE BATTERY_VOLT_04_200000_V +#define JEITA_TEMP_POS_0_TO_POS_10_CV_VOLTAGE BATTERY_VOLT_04_100000_V +#define JEITA_TEMP_NEG_10_TO_POS_0_CV_VOLTAGE BATTERY_VOLT_03_900000_V +#define JEITA_TEMP_BELOW_NEG_10_CV_VOLTAGE BATTERY_VOLT_03_900000_V +#endif +/* For JEITA Linear Charging only */ +#define JEITA_NEG_10_TO_POS_0_FULL_CURRENT 120/* mA */ +#define JEITA_TEMP_POS_45_TO_POS_60_RECHARGE_VOLTAGE 4000 +#define JEITA_TEMP_POS_10_TO_POS_45_RECHARGE_VOLTAGE 4100 +#define JEITA_TEMP_POS_0_TO_POS_10_RECHARGE_VOLTAGE 4000 +#define JEITA_TEMP_NEG_10_TO_POS_0_RECHARGE_VOLTAGE 3800 +#define JEITA_TEMP_POS_45_TO_POS_60_CC2TOPOFF_THRESHOLD 4050 +#define JEITA_TEMP_POS_10_TO_POS_45_CC2TOPOFF_THRESHOLD 4050 +#define JEITA_TEMP_POS_0_TO_POS_10_CC2TOPOFF_THRESHOLD 4050 +#define JEITA_TEMP_NEG_10_TO_POS_0_CC2TOPOFF_THRESHOLD 3850 + + +/* For CV_E1_INTERNAL */ +#define CV_E1_INTERNAL + +/* Disable Battery check for HQA */ +#ifdef CONFIG_MTK_DISABLE_POWER_ON_OFF_VOLTAGE_LIMITATION +#define CONFIG_DIS_CHECK_BATTERY +#endif + +#ifdef CONFIG_MTK_FAN5405_SUPPORT +#define FAN5405_BUSNUM 1 +#endif + +/*VINDPM moved from cust_pe.h to de-relating from PE+*/ +#define SWITCH_CHR_VINDPM_5V 0x13 /* 4.5V */ +#define SWITCH_CHR_VINDPM_7V 0x25 /* 6.3V */ +#define SWITCH_CHR_VINDPM_9V 0x37 /* 8.1V */ +#define SWITCH_CHR_VINDPM_12V 0x54 /* 11.0 set this tp prevent adapters from failure and reset*/ + +/*Added switch chr OPTIONS for BQ25896*/ +/*switch charger input/output current separation; moved to Kconfig.driver*/ +/*#define CONFIG_MTK_SWITCH_INPUT_OUTPUT_CURRENT_SUPPORT*/ +/*Dynamic CV using BIF +* Note: CONFIG_MTK_BAT_BIF_SUPPORT=yes, otherwise default constant CV +*/ +/*#define CONFIG_MTK_DYNAMIC_BAT_CV_SUPPORT*/ +/*Define this macro for thermal team experiment:no current limitation*/ +#define CONFIG_MTK_THERMAL_TEST_SUPPORT +/*enable to save charger in detection power by turning off Chr clock*/ +#define CONFIG_MTK_CHRIND_CLK_PDN_SUPPORT + +/*Added battery_common options*/ +/*enable this to change thread wakeup period to 10 secs to avoid suspend failure*/ +#define CONFIG_MTK_I2C_CHR_SUPPORT + +#define BATTERY_MODULE_INIT + +#if defined(CONFIG_MTK_BQ24196_SUPPORT)\ + || defined(CONFIG_MTK_BQ24296_SUPPORT)\ + || defined(CONFIG_MTK_BQ24160_SUPPORT)\ + || defined(CONFIG_MTK_BQ25896_SUPPORT)\ + || defined(CONFIG_MTK_BQ24261_SUPPORT) +#define SWCHR_POWER_PATH +#endif + +#if defined(CONFIG_MTK_FAN5402_SUPPORT) \ + || defined(CONFIG_MTK_FAN5405_SUPPORT) \ + || defined(CONFIG_MTK_BQ24158_SUPPORT) \ + || defined(CONFIG_MTK_BQ24196_SUPPORT) \ + || defined(CONFIG_MTK_BQ24296_SUPPORT) \ + || defined(CONFIG_MTK_NCP1851_SUPPORT) \ + || defined(CONFIG_MTK_NCP1854_SUPPORT) \ + || defined(CONFIG_MTK_BQ24160_SUPPORT) \ + || defined(CONFIG_MTK_BQ24157_SUPPORT) \ + || defined(CONFIG_MTK_BQ24250_SUPPORT) \ + || defined(CONFIG_MTK_BQ24261_SUPPORT) +#define EXTERNAL_SWCHR_SUPPORT +#endif + +#endif /* _CUST_BAT_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..39c0eb827d8f40c75072c8b13b9a8f5153c79bf5 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_CLKMGR_H +#define _MT_CLKMGR_H + +#ifdef CONFIG_MTK_CLKMGR +#ifdef CONFIG_ARCH_MT6735M +#include "mach/mt_clkmgr2.h" +#elif defined(CONFIG_ARCH_MT6753) +#include "mach/mt_clkmgr3.h" +#else /* CONFIG_ARCH_MT6735 */ +#include "mach/mt_clkmgr1_legacy.h" +#endif +#else /* !CONFIG_MTK_CLKMGR */ +#ifdef CONFIG_ARCH_MT6735M +#error "Does not support common clock framework" +#elif defined(CONFIG_ARCH_MT6753) +#error "Does not support common clock framework" +#else /* CONFIG_ARCH_MT6735 */ +#include "mach/mt_clkmgr1.h" +#endif +#endif + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr1.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr1.h new file mode 100644 index 0000000000000000000000000000000000000000..50c9ae6ba56334e6122a90ab54425069cd1366f9 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr1.h @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_CLKMGR1_H +#define _MT_CLKMGR1_H + +#include +/* #include "mach/mt_reg_base.h" */ +/* #include "mach/mt_typedefs.h" */ + +#define CONFIG_CLKMGR_STAT +#define PLL_CLK_LINK +#define CLKMGR_INCFILE_VER "CLKMGR_INCFILE_D1_CCF" + +/* +#define APMIXED_BASE (0x10209000) +#define CKSYS_BASE (0x10210000) +#define INFRACFG_AO_BASE (0x10000000) +#define PERICFG_BASE (0x10002000) +#define AUDIO_BASE (0x11220000) +#define MFGCFG_BASE (0x13000000) +#define MMSYS_CONFIG_BASE (0x14000000) +#define IMGSYS_BASE (0x15000000) +#define VDEC_GCON_BASE (0x16000000) +#define MJC_CONFIG_BASE (0xF2000000) +#define VENC_GCON_BASE (0x17000000) +*/ +#ifdef CONFIG_OF +extern void __iomem *clk_apmixed_base; +extern void __iomem *clk_cksys_base; +extern void __iomem *clk_infracfg_ao_base; +extern void __iomem *clk_pericfg_base; +extern void __iomem *clk_audio_base; +extern void __iomem *clk_mfgcfg_base; +extern void __iomem *clk_mmsys_config_base; +extern void __iomem *clk_imgsys_base; +extern void __iomem *clk_vdec_gcon_base; +/* extern void __iomem *clk_mjc_config_base; */ +extern void __iomem *clk_venc_gcon_base; +#endif + + +/* APMIXEDSYS Register */ +#define AP_PLL_CON0 (clk_apmixed_base + 0x00) +#define AP_PLL_CON1 (clk_apmixed_base + 0x04) +#define AP_PLL_CON2 (clk_apmixed_base + 0x08) +#define AP_PLL_CON3 (clk_apmixed_base + 0x0C) +#define AP_PLL_CON4 (clk_apmixed_base + 0x10) +#define AP_PLL_CON5 (clk_apmixed_base + 0x14) +#define AP_PLL_CON6 (clk_apmixed_base + 0x18) +#define AP_PLL_CON7 (clk_apmixed_base + 0x1C) +#define CLKSQ_STB_CON0 (clk_apmixed_base + 0x20) +#define PLL_PWR_CON0 (clk_apmixed_base + 0x24) +#define PLL_PWR_CON1 (clk_apmixed_base + 0x28) +#define PLL_ISO_CON0 (clk_apmixed_base + 0x2C) +#define PLL_ISO_CON1 (clk_apmixed_base + 0x30) +#define PLL_STB_CON0 (clk_apmixed_base + 0x34) +#define DIV_STB_CON0 (clk_apmixed_base + 0x38) +#define PLL_CHG_CON0 (clk_apmixed_base + 0x3C) +#define PLL_TEST_CON0 (clk_apmixed_base + 0x40) + +#define ARMPLL_CON0 (clk_apmixed_base + 0x200) +#define ARMPLL_CON1 (clk_apmixed_base + 0x204) +#define ARMPLL_CON2 (clk_apmixed_base + 0x208) +#define ARMPLL_PWR_CON0 (clk_apmixed_base + 0x20C) + +#define MAINPLL_CON0 (clk_apmixed_base + 0x210) +#define MAINPLL_CON1 (clk_apmixed_base + 0x214) +#define MAINPLL_PWR_CON0 (clk_apmixed_base + 0x21C) + +#define UNIVPLL_CON0 (clk_apmixed_base + 0x220) +#define UNIVPLL_CON1 (clk_apmixed_base + 0x224) +#define UNIVPLL_PWR_CON0 (clk_apmixed_base + 0x22C) + +#define MMPLL_CON0 (clk_apmixed_base + 0x230) +#define MMPLL_CON1 (clk_apmixed_base + 0x234) +#define MMPLL_CON2 (clk_apmixed_base + 0x238) +#define MMPLL_PWR_CON0 (clk_apmixed_base + 0x23C) + +#define MSDCPLL_CON0 (clk_apmixed_base + 0x240) +#define MSDCPLL_CON1 (clk_apmixed_base + 0x244) +#define MSDCPLL_PWR_CON0 (clk_apmixed_base + 0x24C) + +#define VENCPLL_CON0 (clk_apmixed_base + 0x250) +#define VENCPLL_CON1 (clk_apmixed_base + 0x254) +#define VENCPLL_PWR_CON0 (clk_apmixed_base + 0x25C) + +#define TVDPLL_CON0 (clk_apmixed_base + 0x260) +#define TVDPLL_CON1 (clk_apmixed_base + 0x264) +#define TVDPLL_PWR_CON0 (clk_apmixed_base + 0x26C) + +/* #define MPLL_CON0 (clk_apmixed_base + 0x280) */ +/* #define MPLL_CON1 (clk_apmixed_base + 0x284) */ +/* #define MPLL_PWR_CON0 (clk_apmixed_base + 0x28C) */ + +#define APLL1_CON0 (clk_apmixed_base + 0x270) +#define APLL1_CON1 (clk_apmixed_base + 0x274) +#define APLL1_CON2 (clk_apmixed_base + 0x278) +#define APLL1_CON3 (clk_apmixed_base + 0x27C) +#define APLL1_PWR_CON0 (clk_apmixed_base + 0x280) + +#define APLL2_CON0 (clk_apmixed_base + 0x284) +#define APLL2_CON1 (clk_apmixed_base + 0x288) +#define APLL2_CON2 (clk_apmixed_base + 0x28C) +#define APLL2_CON3 (clk_apmixed_base + 0x290) +#define APLL2_PWR_CON0 (clk_apmixed_base + 0x294) + +/* TOPCKGEN Register */ +#define CLK_MODE (clk_cksys_base + 0x000) +/* #define CLK_CFG_UPDATE (clk_cksys_base + 0x004) */ +#define TST_SEL_0 (clk_cksys_base + 0x020) +#define TST_SEL_1 (clk_cksys_base + 0x024) +/* #define TST_SEL_2 (clk_cksys_base + 0x028) */ +#define CLK_CFG_0 (clk_cksys_base + 0x040) +#define CLK_CFG_1 (clk_cksys_base + 0x050) +#define CLK_CFG_2 (clk_cksys_base + 0x060) +#define CLK_CFG_3 (clk_cksys_base + 0x070) +#define CLK_CFG_4 (clk_cksys_base + 0x080) +#define CLK_CFG_5 (clk_cksys_base + 0x090) +#define CLK_CFG_6 (clk_cksys_base + 0x0A0) +#define CLK_CFG_7 (clk_cksys_base + 0x0B0) +#define CLK_CFG_8 (clk_cksys_base + 0x100) +#define CLK_CFG_9 (clk_cksys_base + 0x104) +#define CLK_CFG_10 (clk_cksys_base + 0x108) +#define CLK_CFG_11 (clk_cksys_base + 0x10C) +#define CLK_SCP_CFG_0 (clk_cksys_base + 0x200) +#define CLK_SCP_CFG_1 (clk_cksys_base + 0x204) +#define CLK_MISC_CFG_0 (clk_cksys_base + 0x210) +#define CLK_MISC_CFG_1 (clk_cksys_base + 0x214) +#define CLK_MISC_CFG_2 (clk_cksys_base + 0x218) +#define CLK26CALI_0 (clk_cksys_base + 0x220) +#define CLK26CALI_1 (clk_cksys_base + 0x224) +#define CLK26CALI_2 (clk_cksys_base + 0x228) +#define CKSTA_REG (clk_cksys_base + 0x22C) +#define MBIST_CFG_0 (clk_cksys_base + 0x308) +#define MBIST_CFG_1 (clk_cksys_base + 0x30C) + +/* INFRASYS Register */ +#define TOP_CKMUXSEL (clk_infracfg_ao_base + 0x00) +#define TOP_CKDIV1 (clk_infracfg_ao_base + 0x08) + +#define INFRA_PDN_SET0 (clk_infracfg_ao_base + 0x0040) +#define INFRA_PDN_CLR0 (clk_infracfg_ao_base + 0x0044) +#define INFRA_PDN_STA0 (clk_infracfg_ao_base + 0x0048) + +#define TOPAXI_PROT_EN (clk_infracfg_ao_base + 0x0220) +#define TOPAXI_PROT_STA1 (clk_infracfg_ao_base + 0x0228) +#define C2K_SPM_CTRL (clk_infracfg_ao_base + 0x0338) + +#define PERI_PDN_SET0 (clk_pericfg_base + 0x0008) +#define PERI_PDN_CLR0 (clk_pericfg_base + 0x0010) +#define PERI_PDN_STA0 (clk_pericfg_base + 0x0018) +#define PERI_GLOBALCON_CKSEL (clk_pericfg_base + 0x005c) + +/* Audio Register*/ +#define AUDIO_TOP_CON0 (clk_audio_base + 0x0000) +#define AUDIO_TOP_CON1 (clk_audio_base + 0x0004) + +/* MFGCFG Register*/ +#define MFG_CG_CON (clk_mfgcfg_base + 0) +#define MFG_CG_SET (clk_mfgcfg_base + 4) +#define MFG_CG_CLR (clk_mfgcfg_base + 8) + +/* MMSYS Register*/ +#define DISP_CG_CON0 (clk_mmsys_config_base + 0x100) +#define DISP_CG_SET0 (clk_mmsys_config_base + 0x104) +#define DISP_CG_CLR0 (clk_mmsys_config_base + 0x108) +#define DISP_CG_CON1 (clk_mmsys_config_base + 0x110) +#define DISP_CG_SET1 (clk_mmsys_config_base + 0x114) +#define DISP_CG_CLR1 (clk_mmsys_config_base + 0x118) + +#define MMSYS_DUMMY (clk_mmsys_config_base + 0x894) +/* #define SMI_LARB_BWL_EN_REG (clk_mmsys_config_base + 0x21050) */ + +/* IMGSYS Register */ +#define IMG_CG_CON (clk_imgsys_base + 0x0000) +#define IMG_CG_SET (clk_imgsys_base + 0x0004) +#define IMG_CG_CLR (clk_imgsys_base + 0x0008) + +/* VDEC Register */ +#define VDEC_CKEN_SET (clk_vdec_gcon_base + 0x0000) +#define VDEC_CKEN_CLR (clk_vdec_gcon_base + 0x0004) +#define LARB_CKEN_SET (clk_vdec_gcon_base + 0x0008) +#define LARB_CKEN_CLR (clk_vdec_gcon_base + 0x000C) + +/* MJC Register*/ +/* #define MJC_CG_CON (clk_mjc_config_base + 0x0000) */ +/* #define MJC_CG_SET (clk_mjc_config_base + 0x0004) */ +/* #define MJC_CG_CLR (clk_mjc_config_base + 0x0008) */ + +/* VENC Register*/ +#define VENC_CG_CON (clk_venc_gcon_base + 0x0) +#define VENC_CG_SET (clk_venc_gcon_base + 0x4) +#define VENC_CG_CLR (clk_venc_gcon_base + 0x8) + +/* MCUSYS Register */ +/* #define IR_ROSC_CTL (MCUCFG_BASE + 0x030) */ + +enum { + MT_LARB_DISP = 0, + MT_LARB_VDEC = 1, + MT_LARB_IMG = 2, + MT_LARB_VENC = 3, + /* MT_LARB_MJC = 4, */ +}; + +/* larb monitor mechanism definition*/ +enum { + LARB_MONITOR_LEVEL_HIGH = 10, + LARB_MONITOR_LEVEL_MEDIUM = 20, + LARB_MONITOR_LEVEL_LOW = 30, +}; + +struct larb_monitor { + struct list_head link; + int level; + void (*backup)(struct larb_monitor *h, int larb_idx); /* called before disable larb clock */ + void (*restore)(struct larb_monitor *h, int larb_idx); /* called after enable larb clock */ +}; + +enum monitor_clk_sel_0 { + no_clk_0 = 0, + AD_UNIV_624M_CK = 5, + AD_UNIV_416M_CK = 6, + AD_UNIV_249P6M_CK = 7, + AD_UNIV_178P3M_CK_0 = 8, + AD_UNIV_48M_CK = 9, + AD_USB_48M_CK = 10, + rtc32k_ck_i_0 = 20, + AD_SYS_26M_CK_0 = 21, +}; +enum monitor_clk_sel { + no_clk = 0, + AD_SYS_26M_CK = 1, + rtc32k_ck_i = 2, + clkph_MCLK_o = 7, + AD_DPICLK = 8, + AD_MSDCPLL_CK = 9, + AD_MMPLL_CK = 10, + AD_UNIV_178P3M_CK = 11, + AD_MAIN_H156M_CK = 12, + AD_VENCPLL_CK = 13, +}; + +enum ckmon_sel { + clk_ckmon0 = 0, + clk_ckmon1 = 1, + clk_ckmon2 = 2, + clk_ckmon3 = 3, +}; + +/* enum idle_mode { + dpidle = 0, + soidle = 1, + slidle = 2, +}; */ + +extern void register_larb_monitor(struct larb_monitor *handler); +extern void unregister_larb_monitor(struct larb_monitor *handler); +extern void print_grp_regs(void); + +/* clock API */ +/* extern int enable_clock(enum cg_clk_id id, char *mod_name); */ +/* extern int disable_clock(enum cg_clk_id id, char *mod_name); */ +/* extern int mt_enable_clock(enum cg_clk_id id, char *mod_name); */ +/* extern int mt_disable_clock(enum cg_clk_id id, char *mod_name); */ + +/* extern int enable_clock_ext_locked(int id, char *mod_name); */ +/* extern int disable_clock_ext_locked(int id, char *mod_name); */ + +/* extern int clock_is_on(int id); */ + +/* extern int clkmux_sel(int id, unsigned int clksrc, char *name); */ +/* extern void enable_mux(int id, char *name); */ +/* extern void disable_mux(int id, char *name); */ + +/* extern void clk_set_force_on(int id); */ +/* extern void clk_clr_force_on(int id); */ +/* extern int clk_is_force_on(int id); */ + +/* pll API */ +/* extern int enable_pll(int id, char *mod_name); */ +/* extern int disable_pll(int id, char *mod_name); */ + +/* extern int pll_hp_switch_on(int id, int hp_on); */ +/* extern int pll_hp_switch_off(int id, int hp_off); */ + +/* extern int pll_fsel(int id, unsigned int value); */ +/* extern int pll_is_on(int id); */ + +/* subsys API */ +/* extern int enable_subsys(int id, char *mod_name); */ +/* extern int disable_subsys(int id, char *mod_name); */ + +/* extern int subsys_is_on(int id); */ +/* extern int md_power_on(int id); */ +/* extern int md_power_off(int id, unsigned int timeout); */ +/* extern int conn_power_on(void); */ +/* extern int conn_power_off(void); */ + +/* other API */ + +extern void set_mipi26m(int en); +/* extern void set_ada_ssusb_xtal_ck(int en); */ + +/* const char* grp_get_name(int id); */ +/* extern int clkmgr_is_locked(void); */ + +/* init */ +extern int mt_clkmgr_init(void); + +/* extern int clk_monitor_0(enum ckmon_sel ckmon, enum monitor_clk_sel_0 sel, int div); */ +/* extern int clk_monitor(enum ckmon_sel ckmon, enum monitor_clk_sel sel, int div); */ + +/* extern void clk_stat_check(int id); */ +extern void slp_check_pm_mtcmos_pll(void); + +/* sram debug */ +extern void aee_rr_rec_clk(int id, u32 val); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr1_legacy.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr1_legacy.h new file mode 100644 index 0000000000000000000000000000000000000000..3d24e66b2d2c3e032e57810ab6df090ba5494b11 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr1_legacy.h @@ -0,0 +1,584 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_CLKMGR1_LEGACY_H +#define _MT_CLKMGR1_LEGACY_H + +#include +/* #include "mach/mt_reg_base.h" */ +/* #include "mach/mt_typedefs.h" */ + +#define CONFIG_CLKMGR_STAT +#define PLL_CLK_LINK +#define CLKMGR_INCFILE_VER "CLKMGR_INCFILE_D1_LEGACY" + +/* +#define APMIXED_BASE (0x10209000) +#define CKSYS_BASE (0x10210000) +#define INFRACFG_AO_BASE (0x10000000) +#define PERICFG_BASE (0x10002000) +#define AUDIO_BASE (0x11220000) +#define MFGCFG_BASE (0x13000000) +#define MMSYS_CONFIG_BASE (0x14000000) +#define IMGSYS_BASE (0x15000000) +#define VDEC_GCON_BASE (0x16000000) +#define MJC_CONFIG_BASE (0xF2000000) +#define VENC_GCON_BASE (0x17000000) +*/ +#ifdef CONFIG_OF +extern void __iomem *clk_apmixed_base; +extern void __iomem *clk_cksys_base; +extern void __iomem *clk_infracfg_ao_base; +extern void __iomem *clk_pericfg_base; +extern void __iomem *clk_audio_base; +extern void __iomem *clk_mfgcfg_base; +extern void __iomem *clk_mmsys_config_base; +extern void __iomem *clk_imgsys_base; +extern void __iomem *clk_vdec_gcon_base; +/* extern void __iomem *clk_mjc_config_base; */ +extern void __iomem *clk_venc_gcon_base; +#endif + + +/* APMIXEDSYS Register */ +#define AP_PLL_CON0 (clk_apmixed_base + 0x00) +#define AP_PLL_CON1 (clk_apmixed_base + 0x04) +#define AP_PLL_CON2 (clk_apmixed_base + 0x08) +#define AP_PLL_CON3 (clk_apmixed_base + 0x0C) +#define AP_PLL_CON4 (clk_apmixed_base + 0x10) +#define AP_PLL_CON5 (clk_apmixed_base + 0x14) +#define AP_PLL_CON6 (clk_apmixed_base + 0x18) +#define AP_PLL_CON7 (clk_apmixed_base + 0x1C) +#define CLKSQ_STB_CON0 (clk_apmixed_base + 0x20) +#define PLL_PWR_CON0 (clk_apmixed_base + 0x24) +#define PLL_PWR_CON1 (clk_apmixed_base + 0x28) +#define PLL_ISO_CON0 (clk_apmixed_base + 0x2C) +#define PLL_ISO_CON1 (clk_apmixed_base + 0x30) +#define PLL_STB_CON0 (clk_apmixed_base + 0x34) +#define DIV_STB_CON0 (clk_apmixed_base + 0x38) +#define PLL_CHG_CON0 (clk_apmixed_base + 0x3C) +#define PLL_TEST_CON0 (clk_apmixed_base + 0x40) + +#define ARMPLL_CON0 (clk_apmixed_base + 0x200) +#define ARMPLL_CON1 (clk_apmixed_base + 0x204) +#define ARMPLL_CON2 (clk_apmixed_base + 0x208) +#define ARMPLL_PWR_CON0 (clk_apmixed_base + 0x20C) + +#define MAINPLL_CON0 (clk_apmixed_base + 0x210) +#define MAINPLL_CON1 (clk_apmixed_base + 0x214) +#define MAINPLL_PWR_CON0 (clk_apmixed_base + 0x21C) + +#define UNIVPLL_CON0 (clk_apmixed_base + 0x220) +#define UNIVPLL_CON1 (clk_apmixed_base + 0x224) +#define UNIVPLL_PWR_CON0 (clk_apmixed_base + 0x22C) + +#define MMPLL_CON0 (clk_apmixed_base + 0x230) +#define MMPLL_CON1 (clk_apmixed_base + 0x234) +#define MMPLL_CON2 (clk_apmixed_base + 0x238) +#define MMPLL_PWR_CON0 (clk_apmixed_base + 0x23C) + +#define MSDCPLL_CON0 (clk_apmixed_base + 0x240) +#define MSDCPLL_CON1 (clk_apmixed_base + 0x244) +#define MSDCPLL_PWR_CON0 (clk_apmixed_base + 0x24C) + +#define VENCPLL_CON0 (clk_apmixed_base + 0x250) +#define VENCPLL_CON1 (clk_apmixed_base + 0x254) +#define VENCPLL_PWR_CON0 (clk_apmixed_base + 0x25C) + +#define TVDPLL_CON0 (clk_apmixed_base + 0x260) +#define TVDPLL_CON1 (clk_apmixed_base + 0x264) +#define TVDPLL_PWR_CON0 (clk_apmixed_base + 0x26C) + +/* #define MPLL_CON0 (clk_apmixed_base + 0x280) */ +/* #define MPLL_CON1 (clk_apmixed_base + 0x284) */ +/* #define MPLL_PWR_CON0 (clk_apmixed_base + 0x28C) */ + +#define APLL1_CON0 (clk_apmixed_base + 0x270) +#define APLL1_CON1 (clk_apmixed_base + 0x274) +#define APLL1_CON2 (clk_apmixed_base + 0x278) +#define APLL1_CON3 (clk_apmixed_base + 0x27C) +#define APLL1_PWR_CON0 (clk_apmixed_base + 0x280) + +#define APLL2_CON0 (clk_apmixed_base + 0x284) +#define APLL2_CON1 (clk_apmixed_base + 0x288) +#define APLL2_CON2 (clk_apmixed_base + 0x28C) +#define APLL2_CON3 (clk_apmixed_base + 0x290) +#define APLL2_PWR_CON0 (clk_apmixed_base + 0x294) + +/* TOPCKGEN Register */ +#define CLK_MODE (clk_cksys_base + 0x000) +/* #define CLK_CFG_UPDATE (clk_cksys_base + 0x004) */ +#define TST_SEL_0 (clk_cksys_base + 0x020) +#define TST_SEL_1 (clk_cksys_base + 0x024) +/* #define TST_SEL_2 (clk_cksys_base + 0x028) */ +#define CLK_CFG_0 (clk_cksys_base + 0x040) +#define CLK_CFG_1 (clk_cksys_base + 0x050) +#define CLK_CFG_2 (clk_cksys_base + 0x060) +#define CLK_CFG_3 (clk_cksys_base + 0x070) +#define CLK_CFG_4 (clk_cksys_base + 0x080) +#define CLK_CFG_5 (clk_cksys_base + 0x090) +#define CLK_CFG_6 (clk_cksys_base + 0x0A0) +#define CLK_CFG_7 (clk_cksys_base + 0x0B0) +#define CLK_CFG_8 (clk_cksys_base + 0x100) +#define CLK_CFG_9 (clk_cksys_base + 0x104) +#define CLK_CFG_10 (clk_cksys_base + 0x108) +#define CLK_CFG_11 (clk_cksys_base + 0x10C) +#define CLK_SCP_CFG_0 (clk_cksys_base + 0x200) +#define CLK_SCP_CFG_1 (clk_cksys_base + 0x204) +#define CLK_MISC_CFG_0 (clk_cksys_base + 0x210) +#define CLK_MISC_CFG_1 (clk_cksys_base + 0x214) +#define CLK_MISC_CFG_2 (clk_cksys_base + 0x218) +#define CLK26CALI_0 (clk_cksys_base + 0x220) +#define CLK26CALI_1 (clk_cksys_base + 0x224) +#define CLK26CALI_2 (clk_cksys_base + 0x228) +#define CKSTA_REG (clk_cksys_base + 0x22C) +#define MBIST_CFG_0 (clk_cksys_base + 0x308) +#define MBIST_CFG_1 (clk_cksys_base + 0x30C) + +/* INFRASYS Register */ +#define TOP_CKMUXSEL (clk_infracfg_ao_base + 0x00) +#define TOP_CKDIV1 (clk_infracfg_ao_base + 0x08) + +#define INFRA_PDN_SET0 (clk_infracfg_ao_base + 0x0040) +#define INFRA_PDN_CLR0 (clk_infracfg_ao_base + 0x0044) +#define INFRA_PDN_STA0 (clk_infracfg_ao_base + 0x0048) + +#define TOPAXI_PROT_EN (clk_infracfg_ao_base + 0x0220) +#define TOPAXI_PROT_STA1 (clk_infracfg_ao_base + 0x0228) +#define C2K_SPM_CTRL (clk_infracfg_ao_base + 0x0338) + +#define PERI_PDN_SET0 (clk_pericfg_base + 0x0008) +#define PERI_PDN_CLR0 (clk_pericfg_base + 0x0010) +#define PERI_PDN_STA0 (clk_pericfg_base + 0x0018) +#define PERI_GLOBALCON_CKSEL (clk_pericfg_base + 0x005c) + +/* Audio Register*/ +#define AUDIO_TOP_CON0 (clk_audio_base + 0x0000) +#define AUDIO_TOP_CON1 (clk_audio_base + 0x0004) + +/* MFGCFG Register*/ +#define MFG_CG_CON (clk_mfgcfg_base + 0) +#define MFG_CG_SET (clk_mfgcfg_base + 4) +#define MFG_CG_CLR (clk_mfgcfg_base + 8) + +/* MMSYS Register*/ +#define DISP_CG_CON0 (clk_mmsys_config_base + 0x100) +#define DISP_CG_SET0 (clk_mmsys_config_base + 0x104) +#define DISP_CG_CLR0 (clk_mmsys_config_base + 0x108) +#define DISP_CG_CON1 (clk_mmsys_config_base + 0x110) +#define DISP_CG_SET1 (clk_mmsys_config_base + 0x114) +#define DISP_CG_CLR1 (clk_mmsys_config_base + 0x118) + +#define MMSYS_DUMMY (clk_mmsys_config_base + 0x894) +/* #define SMI_LARB_BWL_EN_REG (clk_mmsys_config_base + 0x21050) */ + +/* IMGSYS Register */ +#define IMG_CG_CON (clk_imgsys_base + 0x0000) +#define IMG_CG_SET (clk_imgsys_base + 0x0004) +#define IMG_CG_CLR (clk_imgsys_base + 0x0008) + +/* VDEC Register */ +#define VDEC_CKEN_SET (clk_vdec_gcon_base + 0x0000) +#define VDEC_CKEN_CLR (clk_vdec_gcon_base + 0x0004) +#define LARB_CKEN_SET (clk_vdec_gcon_base + 0x0008) +#define LARB_CKEN_CLR (clk_vdec_gcon_base + 0x000C) + +/* MJC Register*/ +/* #define MJC_CG_CON (clk_mjc_config_base + 0x0000) */ +/* #define MJC_CG_SET (clk_mjc_config_base + 0x0004) */ +/* #define MJC_CG_CLR (clk_mjc_config_base + 0x0008) */ + +/* VENC Register*/ +#define VENC_CG_CON (clk_venc_gcon_base + 0x0) +#define VENC_CG_SET (clk_venc_gcon_base + 0x4) +#define VENC_CG_CLR (clk_venc_gcon_base + 0x8) + +/* MCUSYS Register */ +/* #define IR_ROSC_CTL (MCUCFG_BASE + 0x030) */ + + + +enum { + CG_INFRA = 0, + CG_PERI = 1, + CG_DISP0 = 2, + CG_DISP1 = 3, + CG_IMAGE = 4, + CG_MFG = 5, + CG_AUDIO = 6, + CG_VDEC0 = 7, + CG_VDEC1 = 8, + CG_VENC = 9, + NR_GRPS = 10, +}; + +#ifndef _MT_IDLE_H +enum cg_clk_id { /* The following is CODA name */ + MT_CG_INFRA_DBGCLK = 0, /* */ + MT_CG_INFRA_GCE = 1, /* */ + MT_CG_INFRA_TRBG = 2, /* */ + MT_CG_INFRA_CPUM = 3, /* */ + MT_CG_INFRA_DEVAPC = 4, /* */ + MT_CG_INFRA_AUDIO = 5, /* */ + MT_CG_INFRA_GCPU = 6, /* */ + MT_CG_INFRA_L2C_SRAM = 7, /* */ + MT_CG_INFRA_M4U = 8, /* */ + MT_CG_INFRA_CLDMA = 12, /* */ + MT_CG_INFRA_CONNMCU_BUS = 15, /* */ + MT_CG_INFRA_KP = 16, /* */ + MT_CG_INFRA_APXGPT = 18, /* */ + MT_CG_INFRA_SEJ = 19, /* */ + MT_CG_INFRA_CCIF0_AP = 20, /* */ + MT_CG_INFRA_CCIF1_AP = 21, /* */ + MT_CG_INFRA_PMIC_SPI = 22, /* */ + MT_CG_INFRA_PMIC_WRAP = 23, /* */ +/* MT_CG_INFRA_CG_0 = 32, */ + + MT_CG_PERI_DISP_PWM = 0 + 32, /* */ + MT_CG_PERI_THERM = 1 + 32, /* */ + MT_CG_PERI_PWM1 = 2 + 32, /* */ + MT_CG_PERI_PWM2 = 3 + 32, /* */ + MT_CG_PERI_PWM3 = 4 + 32, /* */ + MT_CG_PERI_PWM4 = 5 + 32, /* */ + MT_CG_PERI_PWM5 = 6 + 32, /* */ + MT_CG_PERI_PWM6 = 7 + 32, /* */ + MT_CG_PERI_PWM7 = 8 + 32, /* */ + MT_CG_PERI_PWM = 9 + 32, /* */ + MT_CG_PERI_USB0 = 10 + 32, /* */ + MT_CG_PERI_IRDA = 11 + 32, /* */ + MT_CG_PERI_APDMA = 12 + 32, /* */ + MT_CG_PERI_MSDC30_0 = 13 + 32, /* */ + MT_CG_PERI_MSDC30_1 = 14 + 32, /* */ + MT_CG_PERI_MSDC30_2 = 15 + 32, /* */ + MT_CG_PERI_MSDC30_3 = 16 + 32, /* */ + MT_CG_PERI_UART0 = 17 + 32, /* */ + MT_CG_PERI_UART1 = 18 + 32, /* */ + MT_CG_PERI_UART2 = 19 + 32, /* */ + MT_CG_PERI_UART3 = 20 + 32, /* */ + MT_CG_PERI_UART4 = 21 + 32, /* */ + MT_CG_PERI_BTIF = 22 + 32, /* */ + MT_CG_PERI_I2C0 = 23 + 32, /* */ + MT_CG_PERI_I2C1 = 24 + 32, /* */ + MT_CG_PERI_I2C2 = 25 + 32, /* */ + MT_CG_PERI_I2C3 = 26 + 32, /* */ + MT_CG_PERI_AUXADC = 27 + 32, /* */ + MT_CG_PERI_SPI0 = 28 + 32, /* */ + MT_CG_PERI_IRTX = 29 + 32, /* */ +/* MT_CG_INFRA_CG_1 = 64, // , */ + + MT_CG_DISP0_SMI_COMMON = 0 + 64, /* SMI_COMMON */ + MT_CG_DISP0_SMI_LARB0 = 1 + 64, /* SMI_LARB0 */ + MT_CG_DISP0_CAM_MDP = 2 + 64, /* CAM_MDP */ + MT_CG_DISP0_MDP_RDMA = 3 + 64, /* MDP_RDMA */ + MT_CG_DISP0_MDP_RSZ0 = 4 + 64, /* MDP_RSZ0 */ + MT_CG_DISP0_MDP_RSZ1 = 5 + 64, /* */ + MT_CG_DISP0_MDP_TDSHP = 6 + 64, /* */ + MT_CG_DISP0_MDP_WDMA = 7 + 64, /* */ + MT_CG_DISP0_MDP_WROT = 8 + 64, /* */ + MT_CG_DISP0_FAKE_ENG = 9 + 64, /* */ + MT_CG_DISP0_DISP_OVL0 = 10 + 64, /* */ + MT_CG_DISP0_DISP_RDMA0 = 11 + 64, /* */ + MT_CG_DISP0_DISP_RDMA1 = 12 + 64, /* */ + MT_CG_DISP0_DISP_WDMA0 = 13 + 64, /* */ + MT_CG_DISP0_DISP_COLOR = 14 + 64, /* */ + MT_CG_DISP0_DISP_CCORR = 15 + 64, /* */ + MT_CG_DISP0_DISP_AAL = 16 + 64, /* */ + MT_CG_DISP0_DISP_GAMMA = 17 + 64, /* */ + MT_CG_DISP0_DISP_DITHER = 18 + 64, /* */ +/* MT_CG_DISP0_AXI_ASIF = 20 +64, // */ +/* MT_CG_DISP0_CG_0 = 96, */ + + MT_CG_DISP1_DSI_ENGINE = 2 + 96, /* */ + MT_CG_DISP1_DSI_DIGITAL = 3 + 96, /* */ + MT_CG_DISP1_DPI_ENGINE = 4 + 96, /* */ + MT_CG_DISP1_DPI_PIXEL = 5 + 96, /* */ +/* MT_CG_DISP1_CG_1 = 128, */ + + MT_CG_IMAGE_LARB2_SMI = 0 + 128, /* LARB2_SMI_CKPDN */ + MT_CG_IMAGE_CAM_SMI = 5 + 128, /* CAM_SMI_CKPDN */ + MT_CG_IMAGE_CAM_CAM = 6 + 128, /* CAM_CAM_CKPDN */ + MT_CG_IMAGE_SEN_TG = 7 + 128, /* SEN_TG_CKPDN */ + MT_CG_IMAGE_SEN_CAM = 8 + 128, /* SEN_CAM_CKPDN */ + MT_CG_IMAGE_CAM_SV = 9 + 128, /* CAM_SV_CKPDN */ + MT_CG_IMAGE_SUFOD = 10 + 128, /* SUFOD_CKPDN */ + MT_CG_IMAGE_FD = 11 + 128, /* FD_CKPDN */ +/* MT_CG_IMAGE_CG = 160, */ + + MT_CG_MFG_BG3D = 0 + 160, /* BG3D_PDN */ +/* MT_CG_MFG_CG = 192, */ + + MT_CG_AUDIO_AFE = 2 + 192, /* PDN_AFE */ + MT_CG_AUDIO_I2S = 6 + 192, /* PDN_I2S */ + MT_CG_AUDIO_22M = 8 + 192, /* PDN_22M */ + MT_CG_AUDIO_24M = 9 + 192, /* PDN_24M */ + MT_CG_AUDIO_APLL2_TUNER = 18 + 192, /* PDN_APLL2_TUNER */ + MT_CG_AUDIO_APLL_TUNER = 19 + 192, /* PDN_APLL_TUNER */ + MT_CG_AUDIO_ADC = 24 + 192, + MT_CG_AUDIO_DAC = 25 + 192, + MT_CG_AUDIO_DAC_PREDIS = 26 + 192, + MT_CG_AUDIO_TML = 27 + 192, +/* MT_CG_AUDIO_CG = 224, */ + + MT_CG_VDEC0_VDEC = 0 + 224, /* VDEC_CKEN */ +/* MT_CG_VDEC0_CG = 256, */ + + MT_CG_VDEC1_LARB = 0 + 256, /* LARB_CKEN */ +/* MT_CG_VDEC1_CG = 288, */ + + MT_CG_VENC_LARB = 0 + 288, /* LARB_CKE */ + MT_CG_VENC_VENC = 4 + 288, /* VENC_CKE */ + MT_CG_VENC_JPGENC = 8 + 288, /* JPGENC_CKE */ + MT_CG_VENC_JPGDEC = 12 + 288, /* JPGDEC_CKE */ + + CG_INFRA_FROM = MT_CG_INFRA_DBGCLK, + CG_INFRA_TO = MT_CG_INFRA_PMIC_WRAP, + NR_INFRA_CLKS = 23, + + CG_PERI_FROM = MT_CG_PERI_DISP_PWM, + CG_PERI_TO = MT_CG_PERI_IRTX, + NR_PERI_CLKS = 29, + + CG_DISP0_FROM = MT_CG_DISP0_SMI_COMMON, + CG_DISP0_TO = MT_CG_DISP0_DISP_DITHER, + NR_DISP0_CLKS = 19, + + CG_DISP1_FROM = MT_CG_DISP1_DSI_ENGINE, + CG_DISP1_TO = MT_CG_DISP1_DPI_PIXEL, + NR_DISP1_CLKS = 5, + + CG_IMAGE_FROM = MT_CG_IMAGE_LARB2_SMI, + CG_IMAGE_TO = MT_CG_IMAGE_FD, + NR_IMAGE_CLKS = 11, + + CG_MFG_FROM = MT_CG_MFG_BG3D, + CG_MFG_TO = MT_CG_MFG_BG3D, + NR_MFG_CLKS = 1, + + CG_AUDIO_FROM = MT_CG_AUDIO_AFE, + CG_AUDIO_TO = MT_CG_AUDIO_TML, + NR_AUDIO_CLKS = 27, + + CG_VDEC0_FROM = MT_CG_VDEC0_VDEC, + CG_VDEC0_TO = MT_CG_VDEC0_VDEC, + NR_VDEC0_CLKS = 1, + + CG_VDEC1_FROM = MT_CG_VDEC1_LARB, + CG_VDEC1_TO = MT_CG_VDEC1_LARB, + NR_VDEC1_CLKS = 1, + + CG_VENC_FROM = MT_CG_VENC_LARB, + CG_VENC_TO = MT_CG_VENC_JPGDEC, + NR_VENC_CLKS = 12, + + NR_CLKS = 301, + +}; +#endif /* _MT_IDLE_H */ + +enum { + /* CLK_CFG_0 */ + MT_MUX_MM = 0, + MT_MUX_DDRPHY = 1, + MT_MUX_MEM = 2, + MT_MUX_AXI = 3, + + /* CLK_CFG_1 */ + MT_MUX_CAMTG = 4, + MT_MUX_MFG = 5, + MT_MUX_VDEC = 6, + MT_MUX_PWM = 7, + + /* CLK_CFG_2 */ + MT_MUX_MSDC50_0 = 8, + MT_MUX_USB20 = 9, + MT_MUX_SPI = 10, + MT_MUX_UART = 11, + + /* CLK_CFG_3 */ + MT_MUX_MSDC30_3 = 12, + MT_MUX_MSDC30_2 = 13, + MT_MUX_MSDC30_1 = 14, + MT_MUX_MSDC30_0 = 15, + + /* CLK_CFG_4 */ + MT_MUX_SCP = 16, + MT_MUX_PMICSPI = 17, + MT_MUX_AUDINTBUS = 18, + MT_MUX_AUDIO = 19, + + /* CLK_CFG_5 */ + MT_MUX_MFG13M = 20, + MT_MUX_SCAM = 21, + MT_MUX_DPI0 = 22, + MT_MUX_ATB = 23, + + /* CLK_CFG_6 */ + MT_MUX_IRTX = 24, + MT_MUX_IRDA = 25, + MT_MUX_AUD2 = 26, + MT_MUX_AUD1 = 27, + + /* CLK_CFG_7 */ + MT_MUX_DISPPWM = 28, + + NR_MUXS = 29, +}; + +enum { + ARMPLL = 0, + MAINPLL = 1, + MSDCPLL = 2, + UNIVPLL = 3, + MMPLL = 4, + VENCPLL = 5, + TVDPLL = 6, + APLL1 = 7, + APLL2 = 8, + NR_PLLS = 9, +}; + +enum { + SYS_MD1 = 0, + SYS_MD2 = 1, + SYS_CONN = 2, + SYS_DIS = 3, + SYS_MFG = 4, + SYS_ISP = 5, + SYS_VDE = 6, + SYS_VEN = 7, +/* SYS_AUD = 8, */ + NR_SYSS = 8, +}; + +enum { + MT_LARB_DISP = 0, + MT_LARB_VDEC = 1, + MT_LARB_IMG = 2, + MT_LARB_VENC = 3, + /* MT_LARB_MJC = 4, */ +}; + +/* larb monitor mechanism definition*/ +enum { + LARB_MONITOR_LEVEL_HIGH = 10, + LARB_MONITOR_LEVEL_MEDIUM = 20, + LARB_MONITOR_LEVEL_LOW = 30, +}; + +struct larb_monitor { + struct list_head link; + int level; + void (*backup)(struct larb_monitor *h, int larb_idx); /* called before disable larb clock */ + void (*restore)(struct larb_monitor *h, int larb_idx); /* called after enable larb clock */ +}; + +enum monitor_clk_sel_0 { + no_clk_0 = 0, + AD_UNIV_624M_CK = 5, + AD_UNIV_416M_CK = 6, + AD_UNIV_249P6M_CK = 7, + AD_UNIV_178P3M_CK_0 = 8, + AD_UNIV_48M_CK = 9, + AD_USB_48M_CK = 10, + rtc32k_ck_i_0 = 20, + AD_SYS_26M_CK_0 = 21, +}; +enum monitor_clk_sel { + no_clk = 0, + AD_SYS_26M_CK = 1, + rtc32k_ck_i = 2, + clkph_MCLK_o = 7, + AD_DPICLK = 8, + AD_MSDCPLL_CK = 9, + AD_MMPLL_CK = 10, + AD_UNIV_178P3M_CK = 11, + AD_MAIN_H156M_CK = 12, + AD_VENCPLL_CK = 13, +}; + +enum ckmon_sel { + clk_ckmon0 = 0, + clk_ckmon1 = 1, + clk_ckmon2 = 2, + clk_ckmon3 = 3, +}; + +enum idle_mode { + dpidle = 0, + soidle = 1, + slidle = 2, +}; + +extern void register_larb_monitor(struct larb_monitor *handler); +extern void unregister_larb_monitor(struct larb_monitor *handler); + +/* clock API */ +extern int enable_clock(int id, char *mod_name); +extern int disable_clock(int id, char *mod_name); +extern int mt_enable_clock(int id, char *mod_name); +extern int mt_disable_clock(int id, char *mod_name); + +extern int enable_clock_ext_locked(int id, char *mod_name); +extern int disable_clock_ext_locked(int id, char *mod_name); + +extern int clock_is_on(int id); + +extern int clkmux_sel(int id, unsigned int clksrc, char *name); +extern void enable_mux(int id, char *name); +extern void disable_mux(int id, char *name); + +extern void clk_set_force_on(int id); +extern void clk_clr_force_on(int id); +extern int clk_is_force_on(int id); + +/* pll API */ +extern int enable_pll(int id, char *mod_name); +extern int disable_pll(int id, char *mod_name); + +extern int pll_hp_switch_on(int id, int hp_on); +extern int pll_hp_switch_off(int id, int hp_off); + +extern int pll_fsel(int id, unsigned int value); +extern int pll_is_on(int id); + +/* subsys API */ +extern int enable_subsys(int id, char *mod_name); +extern int disable_subsys(int id, char *mod_name); + +extern int subsys_is_on(int id); +extern int md_power_on(int id); +extern int md_power_off(int id, unsigned int timeout); +extern int conn_power_on(void); +extern int conn_power_off(void); + +/* other API */ + +extern void set_mipi26m(int en); +extern void set_ada_ssusb_xtal_ck(int en); + +const char *grp_get_name(int id); +extern int clkmgr_is_locked(void); + +/* init */ +extern int mt_clkmgr_init(void); + +extern int clk_monitor_0(enum ckmon_sel ckmon, enum monitor_clk_sel_0 sel, int div); +extern int clk_monitor(enum ckmon_sel ckmon, enum monitor_clk_sel sel, int div); + +extern void clk_stat_check(int id); +extern void slp_check_pm_mtcmos_pll(void); + +/* sram debug */ +extern void aee_rr_rec_clk(int id, u32 val); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr2.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr2.h new file mode 100644 index 0000000000000000000000000000000000000000..31c3e5556e1431cc2bed0f411ef847ea03c1f865 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr2.h @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_CLKMGR2_H +#define _MT_CLKMGR2_H + +#include +/* #include "mach/mt_reg_base.h" */ +/* #include "mach/mt_typedefs.h" */ + +#define CONFIG_CLKMGR_STAT +#define PLL_CLK_LINK +#define CLKMGR_INCFILE_VER "CLKMGR_INCFILE_D2_LEGACY" + +/* +#define APMIXED_BASE (0x10209000) +#define CKSYS_BASE (0x10210000) +#define INFRACFG_AO_BASE (0x10000000) +#define PERICFG_BASE (0x10002000) +#define AUDIO_BASE (0x11220000) +#define MFGCFG_BASE (0x13000000) +#define MMSYS_CONFIG_BASE (0x14000000) +#define IMGSYS_BASE (0x15000000) +#define VDEC_GCON_BASE (0x16000000) +#define MJC_CONFIG_BASE (0xF2000000) +#define VENC_GCON_BASE (0x17000000) +*/ +#ifdef CONFIG_OF +extern void __iomem *clk_apmixed_base; +extern void __iomem *clk_cksys_base; +extern void __iomem *clk_infracfg_ao_base; +extern void __iomem *clk_pericfg_base; +extern void __iomem *clk_audio_base; +extern void __iomem *clk_mfgcfg_base; +extern void __iomem *clk_mmsys_config_base; +extern void __iomem *clk_imgsys_base; +extern void __iomem *clk_vdec_gcon_base; +/* extern void __iomem *clk_mjc_config_base; */ +/* extern void __iomem *clk_venc_gcon_base; */ +#endif + + +/* APMIXEDSYS Register */ +#define AP_PLL_CON0 (clk_apmixed_base + 0x00) +#define AP_PLL_CON1 (clk_apmixed_base + 0x04) +#define AP_PLL_CON2 (clk_apmixed_base + 0x08) +#define AP_PLL_CON3 (clk_apmixed_base + 0x0C) +#define AP_PLL_CON4 (clk_apmixed_base + 0x10) +#define AP_PLL_CON5 (clk_apmixed_base + 0x14) +#define AP_PLL_CON6 (clk_apmixed_base + 0x18) +#define AP_PLL_CON7 (clk_apmixed_base + 0x1C) +#define CLKSQ_STB_CON0 (clk_apmixed_base + 0x20) +#define PLL_PWR_CON0 (clk_apmixed_base + 0x24) +#define PLL_PWR_CON1 (clk_apmixed_base + 0x28) +#define PLL_ISO_CON0 (clk_apmixed_base + 0x2C) +#define PLL_ISO_CON1 (clk_apmixed_base + 0x30) +#define PLL_STB_CON0 (clk_apmixed_base + 0x34) +#define DIV_STB_CON0 (clk_apmixed_base + 0x38) +#define PLL_CHG_CON0 (clk_apmixed_base + 0x3C) +#define PLL_TEST_CON0 (clk_apmixed_base + 0x40) + +#define ARMPLL_CON0 (clk_apmixed_base + 0x200) +#define ARMPLL_CON1 (clk_apmixed_base + 0x204) +#define ARMPLL_CON2 (clk_apmixed_base + 0x208) +#define ARMPLL_PWR_CON0 (clk_apmixed_base + 0x20C) + +#define MAINPLL_CON0 (clk_apmixed_base + 0x210) +#define MAINPLL_CON1 (clk_apmixed_base + 0x214) +#define MAINPLL_PWR_CON0 (clk_apmixed_base + 0x21C) + +#define UNIVPLL_CON0 (clk_apmixed_base + 0x220) +#define UNIVPLL_CON1 (clk_apmixed_base + 0x224) +#define UNIVPLL_PWR_CON0 (clk_apmixed_base + 0x22C) + +#define MMPLL_CON0 (clk_apmixed_base + 0x230) +#define MMPLL_CON1 (clk_apmixed_base + 0x234) +#define MMPLL_CON2 (clk_apmixed_base + 0x238) +#define MMPLL_PWR_CON0 (clk_apmixed_base + 0x23C) + +#define MSDCPLL_CON0 (clk_apmixed_base + 0x240) +#define MSDCPLL_CON1 (clk_apmixed_base + 0x244) +#define MSDCPLL_PWR_CON0 (clk_apmixed_base + 0x24C) + +#define VENCPLL_CON0 (clk_apmixed_base + 0x250) +#define VENCPLL_CON1 (clk_apmixed_base + 0x254) +#define VENCPLL_PWR_CON0 (clk_apmixed_base + 0x25C) + +#define TVDPLL_CON0 (clk_apmixed_base + 0x260) +#define TVDPLL_CON1 (clk_apmixed_base + 0x264) +#define TVDPLL_PWR_CON0 (clk_apmixed_base + 0x26C) + +/* #define MPLL_CON0 (clk_apmixed_base + 0x280) */ +/* #define MPLL_CON1 (clk_apmixed_base + 0x284) */ +/* #define MPLL_PWR_CON0 (clk_apmixed_base + 0x28C) */ + +#define APLL1_CON0 (clk_apmixed_base + 0x270) +#define APLL1_CON1 (clk_apmixed_base + 0x274) +#define APLL1_CON2 (clk_apmixed_base + 0x278) +#define APLL1_CON3 (clk_apmixed_base + 0x27C) +#define APLL1_PWR_CON0 (clk_apmixed_base + 0x280) + +#define APLL2_CON0 (clk_apmixed_base + 0x284) +#define APLL2_CON1 (clk_apmixed_base + 0x288) +#define APLL2_CON2 (clk_apmixed_base + 0x28C) +#define APLL2_CON3 (clk_apmixed_base + 0x290) +#define APLL2_PWR_CON0 (clk_apmixed_base + 0x294) + +/* TOPCKGEN Register */ +#define CLK_MODE (clk_cksys_base + 0x000) +/* #define CLK_CFG_UPDATE (clk_cksys_base + 0x004) */ +#define TST_SEL_0 (clk_cksys_base + 0x020) +#define TST_SEL_1 (clk_cksys_base + 0x024) +/* #define TST_SEL_2 (clk_cksys_base + 0x028) */ +#define CLK_CFG_0 (clk_cksys_base + 0x040) +#define CLK_CFG_1 (clk_cksys_base + 0x050) +#define CLK_CFG_2 (clk_cksys_base + 0x060) +#define CLK_CFG_3 (clk_cksys_base + 0x070) +#define CLK_CFG_4 (clk_cksys_base + 0x080) +#define CLK_CFG_5 (clk_cksys_base + 0x090) +#define CLK_CFG_6 (clk_cksys_base + 0x0A0) +#define CLK_CFG_7 (clk_cksys_base + 0x0B0) +#define CLK_CFG_8 (clk_cksys_base + 0x100) +#define CLK_CFG_9 (clk_cksys_base + 0x104) +#define CLK_CFG_10 (clk_cksys_base + 0x108) +#define CLK_CFG_11 (clk_cksys_base + 0x10C) +#define CLK_SCP_CFG_0 (clk_cksys_base + 0x200) +#define CLK_SCP_CFG_1 (clk_cksys_base + 0x204) +#define CLK_MISC_CFG_0 (clk_cksys_base + 0x210) +#define CLK_MISC_CFG_1 (clk_cksys_base + 0x214) +#define CLK_MISC_CFG_2 (clk_cksys_base + 0x218) +#define CLK26CALI_0 (clk_cksys_base + 0x220) +#define CLK26CALI_1 (clk_cksys_base + 0x224) +#define CLK26CALI_2 (clk_cksys_base + 0x228) +#define CKSTA_REG (clk_cksys_base + 0x22C) +#define MBIST_CFG_0 (clk_cksys_base + 0x308) +#define MBIST_CFG_1 (clk_cksys_base + 0x30C) + +/* INFRASYS Register */ +#define TOP_CKMUXSEL (clk_infracfg_ao_base + 0x00) +#define TOP_CKDIV1 (clk_infracfg_ao_base + 0x08) + +#define INFRA_PDN_SET0 (clk_infracfg_ao_base + 0x0040) +#define INFRA_PDN_CLR0 (clk_infracfg_ao_base + 0x0044) +#define INFRA_PDN_STA0 (clk_infracfg_ao_base + 0x0048) + +#define TOPAXI_PROT_EN (clk_infracfg_ao_base + 0x0220) +#define TOPAXI_PROT_STA1 (clk_infracfg_ao_base + 0x0228) +#define C2K_SPM_CTRL (clk_infracfg_ao_base + 0x0338) + +/* PERI Register */ +#define PERI_PDN_SET0 (clk_pericfg_base + 0x0008) +#define PERI_PDN_CLR0 (clk_pericfg_base + 0x0010) +#define PERI_PDN_STA0 (clk_pericfg_base + 0x0018) +#define PERI_GLOBALCON_CKSEL (clk_pericfg_base + 0x005c) /* used in clkmux_sel_op for vcore DVFS */ + +/* Audio Register*/ +#define AUDIO_TOP_CON0 (clk_audio_base + 0x0000) +#define AUDIO_TOP_CON1 (clk_audio_base + 0x0004) + +/* MFGCFG Register*/ +#define MFG_CG_CON (clk_mfgcfg_base + 0) +#define MFG_CG_SET (clk_mfgcfg_base + 4) +#define MFG_CG_CLR (clk_mfgcfg_base + 8) + +/* MMSYS Register*/ +#define DISP_CG_CON0 (clk_mmsys_config_base + 0x100) +#define DISP_CG_SET0 (clk_mmsys_config_base + 0x104) +#define DISP_CG_CLR0 (clk_mmsys_config_base + 0x108) +#define DISP_CG_CON1 (clk_mmsys_config_base + 0x110) +#define DISP_CG_SET1 (clk_mmsys_config_base + 0x114) +#define DISP_CG_CLR1 (clk_mmsys_config_base + 0x118) + +#define MMSYS_DUMMY (clk_mmsys_config_base + 0x894) /* use MMSYS_DUMMY1 for D1/D2/D3 SW compatible */ +#define MMSYS_DUMMY_1 (clk_mmsys_config_base + 0x898) /* use MMSYS_DUMMY2 for D1/D2/D3 SW compatible */ + +/* IMGSYS Register */ +#define IMG_CG_CON (clk_imgsys_base + 0x0000) +#define IMG_CG_SET (clk_imgsys_base + 0x0004) +#define IMG_CG_CLR (clk_imgsys_base + 0x0008) + +/* VDEC Register */ +#define VDEC_CKEN_SET (clk_vdec_gcon_base + 0x0000) +#define VDEC_CKEN_CLR (clk_vdec_gcon_base + 0x0004) +#define LARB_CKEN_SET (clk_vdec_gcon_base + 0x0008) +#define LARB_CKEN_CLR (clk_vdec_gcon_base + 0x000C) + +/* MJC Register*/ +/* #define MJC_CG_CON (clk_mjc_config_base + 0x0000) */ +/* #define MJC_CG_SET (clk_mjc_config_base + 0x0004) */ +/* #define MJC_CG_CLR (clk_mjc_config_base + 0x0008) */ + +/* VENC Register*/ +/* #define VENC_CG_CON (clk_venc_gcon_base + 0x0) */ +/* #define VENC_CG_SET (clk_venc_gcon_base + 0x4) */ +/* #define VENC_CG_CLR (clk_venc_gcon_base + 0x8) */ + +/* MCUSYS Register */ +/* #define IR_ROSC_CTL (MCUCFG_BASE + 0x030) */ + + + +enum { + CG_INFRA = 0, + CG_PERI = 1, + CG_DISP0 = 2, + CG_DISP1 = 3, + CG_IMAGE = 4, + CG_MFG = 5, + CG_AUDIO = 6, + CG_VDEC0 = 7, + CG_VDEC1 = 8, + /* CG_VENC = X, */ + /* NR_GRPS = X, */ + NR_GRPS = 9, +}; + +#ifndef _MT_IDLE_H +enum cg_clk_id { + MT_CG_INFRA_DBGCLK = 0, + MT_CG_INFRA_GCE = 1, + MT_CG_INFRA_TRNG = 2, + MT_CG_INFRA_CPUM = 3, + MT_CG_INFRA_DEVAPC = 4, + MT_CG_INFRA_AUDIO = 5, + MT_CG_INFRA_GCPU = 6, + MT_CG_INFRA_L2C_SRAM = 7, + MT_CG_INFRA_M4U = 8, + MT_CG_INFRA_CLDMA = 12, + MT_CG_INFRA_CONNMCU_BUS = 15, + MT_CG_INFRA_KP = 16, + MT_CG_INFRA_APXGPT = 18, + MT_CG_INFRA_SEJ = 19, + MT_CG_INFRA_CCIF0_AP = 20, + MT_CG_INFRA_CCIF1_AP = 21, + MT_CG_INFRA_PMIC_SPI = 22, + MT_CG_INFRA_PMIC_WRAP = 23, + /* MT_CG_INFRA_CG_0 = 32, */ + + MT_CG_PERI_DISP_PWM = 0 + 32, + MT_CG_PERI_THERM = 1 + 32, + MT_CG_PERI_PWM1 = 2 + 32, + MT_CG_PERI_PWM2 = 3 + 32, + MT_CG_PERI_PWM3 = 4 + 32, + MT_CG_PERI_PWM4 = 5 + 32, + MT_CG_PERI_PWM5 = 6 + 32, + MT_CG_PERI_PWM6 = 7 + 32, + MT_CG_PERI_PWM7 = 8 + 32, + MT_CG_PERI_PWM = 9 + 32, + MT_CG_PERI_USB0 = 10 + 32, + MT_CG_PERI_IRDA = 11 + 32, + MT_CG_PERI_APDMA = 12 + 32, + MT_CG_PERI_MSDC30_0 = 13 + 32, + MT_CG_PERI_MSDC30_1 = 14 + 32, + /* MT_CG_PERI_MSDC30_2 = 15 + 32, */ + /* MT_CG_PERI_MSDC30_3 = 16 + 32, */ + MT_CG_PERI_UART0 = 17 + 32, + MT_CG_PERI_UART1 = 18 + 32, + MT_CG_PERI_UART2 = 19 + 32, + MT_CG_PERI_UART3 = 20 + 32, + /* MT_CG_PERI_UART4 = 21 + 32, */ + MT_CG_PERI_BTIF = 22 + 32, + MT_CG_PERI_I2C0 = 23 + 32, + MT_CG_PERI_I2C1 = 24 + 32, + MT_CG_PERI_I2C2 = 25 + 32, + MT_CG_PERI_I2C3 = 26 + 32, + MT_CG_PERI_AUXADC = 27 + 32, + MT_CG_PERI_SPI0 = 28 + 32, + MT_CG_PERI_IRTX = 29 + 32, + /* MT_CG_PERI_CG_1 = 64, */ + + MT_CG_DISP0_SMI_COMMON = 0 + 64, + MT_CG_DISP0_SMI_LARB0 = 1 + 64, + MT_CG_DISP0_CAM_MDP = 2 + 64, + MT_CG_DISP0_MDP_RDMA = 3 + 64, + MT_CG_DISP0_MDP_RSZ0 = 4 + 64, + MT_CG_DISP0_MDP_RSZ1 = 5 + 64, + MT_CG_DISP0_MDP_TDSHP = 6 + 64, + MT_CG_DISP0_MDP_WDMA = 7 + 64, + MT_CG_DISP0_MDP_WROT = 8 + 64, + MT_CG_DISP0_FAKE_ENG = 9 + 64, + MT_CG_DISP0_DISP_OVL0 = 10 + 64, + MT_CG_DISP0_DISP_RDMA0 = 11 + 64, + MT_CG_DISP0_DISP_RDMA1 = 12 + 64, + MT_CG_DISP0_DISP_WDMA0 = 13 + 64, + MT_CG_DISP0_DISP_COLOR = 14 + 64, + MT_CG_DISP0_DISP_CCORR = 15 + 64, + MT_CG_DISP0_DISP_AAL = 16 + 64, + MT_CG_DISP0_DISP_GAMMA = 17 + 64, + MT_CG_DISP0_DISP_DITHER = 18 + 64, + /* MT_CG_DISP0_DISP_UFOE = 19 + 64, */ + /* MT_CG_DISP0_AXI_ASIF = 20 + 64, */ + /* MT_CG_DISP0_CG_0 = 96, */ + + /* MT_CG_DISP1_DSI_PWM_MM = 0 + 96, */ + /* MT_CG_DISP1_DSI_PWM_26M = 1 + 96, */ + MT_CG_DISP1_DSI_ENGINE = 2 + 96, + MT_CG_DISP1_DSI_DIGITAL = 3 + 96, + MT_CG_DISP1_DPI_ENGINE = 4 + 96, + MT_CG_DISP1_DPI_PIXEL = 5 + 96, + /* MT_CG_DISP1_CG_1 = 128, */ + + MT_CG_IMAGE_LARB2_SMI = 0 + 128, + MT_CG_IMAGE_JPGENC = 4 + 128, + MT_CG_IMAGE_CAM_SMI = 5 + 128, + MT_CG_IMAGE_CAM_CAM = 6 + 128, + MT_CG_IMAGE_SEN_TG = 7 + 128, + MT_CG_IMAGE_SEN_CAM = 8 + 128, + MT_CG_IMAGE_VCODEC = 9 + 128, + /* MT_CG_IMAGE_CG = 160, */ + + MT_CG_MFG_BG3D = 0 + 160, + /* MT_CG_MFG_CG = 192, */ + + MT_CG_AUDIO_AFE = 2 + 192, + MT_CG_AUDIO_I2S = 6 + 192, + /* MT_CG_AUDIO_ADDA4_ADC = 7 + 192,*/ /* GeorgeCY:no use */ + MT_CG_AUDIO_22M = 8 + 192, + MT_CG_AUDIO_24M = 9 + 192, + MT_CG_AUDIO_APLL2_TUNER = 18 + 192, + MT_CG_AUDIO_APLL_TUNER = 19 + 192, + MT_CG_AUDIO_ADC = 24 + 192, + MT_CG_AUDIO_DAC = 25 + 192, + MT_CG_AUDIO_DAC_PREDIS = 26 + 192, + MT_CG_AUDIO_TML = 27 + 192, + /* MT_CG_AUDIO_CG = 224, */ + + MT_CG_VDEC0_VDEC = 0 + 224, + /* MT_CG_VDEC0_CG = 256, */ + + MT_CG_VDEC1_LARB = 0 + 256, + /* MT_CG_VDEC1_CG = 288, */ + + /* MT_CG_VENC_LARB = 0 + 288, */ + /* MT_CG_VENC_VENC = 4 + 288, */ + /* MT_CG_VENC_JPGENC = 8 + 288, */ + /* MT_CG_VENC_JPGDEC = 12 + 288, */ + + CG_INFRA_FROM = MT_CG_INFRA_DBGCLK, + CG_INFRA_TO = MT_CG_INFRA_PMIC_WRAP, + NR_INFRA_CLKS = 24, + + CG_PERI_FROM = MT_CG_PERI_DISP_PWM, + CG_PERI_TO = MT_CG_PERI_IRTX, + NR_PERI_CLKS = 30, + + CG_DISP0_FROM = MT_CG_DISP0_SMI_COMMON, + CG_DISP0_TO = MT_CG_DISP0_DISP_DITHER, + NR_DISP0_CLKS = 19, + + CG_DISP1_FROM = MT_CG_DISP1_DSI_ENGINE, + CG_DISP1_TO = MT_CG_DISP1_DPI_PIXEL, + NR_DISP1_CLKS = 6, + + CG_IMAGE_FROM = MT_CG_IMAGE_LARB2_SMI, + CG_IMAGE_TO = MT_CG_IMAGE_VCODEC, + NR_IMAGE_CLKS = 10, + + CG_MFG_FROM = MT_CG_MFG_BG3D, + CG_MFG_TO = MT_CG_MFG_BG3D, + NR_MFG_CLKS = 1, + + CG_AUDIO_FROM = MT_CG_AUDIO_AFE, + CG_AUDIO_TO = MT_CG_AUDIO_TML, + NR_AUDIO_CLKS = 28, + + CG_VDEC0_FROM = MT_CG_VDEC0_VDEC, + CG_VDEC0_TO = MT_CG_VDEC0_VDEC, + NR_VDEC0_CLKS = 1, + + CG_VDEC1_FROM = MT_CG_VDEC1_LARB, + CG_VDEC1_TO = MT_CG_VDEC1_LARB, + NR_VDEC1_CLKS = 1, + + /* CG_VENC_FROM = MT_CG_VENC_LARB, */ + /* CG_VENC_TO = MT_CG_VENC_JPGDEC, */ + /* NR_VENC_CLKS = 12, */ + + NR_CLKS = 257, + +}; +#endif /* _MT_IDLE_H */ + +enum { + /* CLK_CFG_0 */ + MT_MUX_MM = 0, + MT_MUX_DDRPHY = 1, + MT_MUX_MEM = 2, + MT_MUX_AXI = 3, + + /* CLK_CFG_1 */ + MT_MUX_CAMTG = 4, + MT_MUX_MFG = 5, + MT_MUX_VDEC = 6, + MT_MUX_PWM = 7, + + /* CLK_CFG_2 */ + MT_MUX_MSDC50_0 = 8, + MT_MUX_USB20 = 9, + MT_MUX_SPI = 10, + MT_MUX_UART = 11, + + /* CLK_CFG_3 */ + /* MT_MUX_MSDC30_3 = X, */ + /* MT_MUX_MSDC30_2 = X, */ + MT_MUX_MSDC30_1 = 12, + MT_MUX_MSDC30_0 = 13, + + /* CLK_CFG_4 */ + MT_MUX_SCP = 14, + MT_MUX_PMICSPI = 15, + MT_MUX_AUDINTBUS = 16, + MT_MUX_AUDIO = 17, + + /* CLK_CFG_5 */ + MT_MUX_MFG13M = 18, + MT_MUX_SCAM = 19, + MT_MUX_DPI0 = 20, + MT_MUX_ATB = 21, + + /* CLK_CFG_6 */ + MT_MUX_IRTX = 22, + MT_MUX_IRDA = 23, + MT_MUX_AUD2 = 24, + MT_MUX_AUD1 = 25, + + /* CLK_CFG_7 */ + MT_MUX_DISPPWM = 26, + + NR_MUXS = 27, +}; + +enum { + ARMPLL = 0, + MAINPLL = 1, + MSDCPLL = 2, + UNIVPLL = 3, + MMPLL = 4, + VENCPLL = 5, /* for display */ + TVDPLL = 6, + APLL1 = 7, + APLL2 = 8, + NR_PLLS = 9, +}; + +enum { + SYS_MD1 = 0, + /* SYS_MD2 = X, */ + SYS_CONN = 1, + SYS_DIS = 2, + SYS_MFG = 3, + SYS_ISP = 4, + SYS_VDE = 5, + /* SYS_VEN = X, */ + /* SYS_AUD = X, */ + NR_SYSS = 6, +}; + +enum { + MT_LARB_DISP = 0, + MT_LARB_VDEC = 1, + MT_LARB_IMG = 2, + /* MT_LARB_VENC = 3, */ + /* MT_LARB_MJC = 4, */ +}; + +/* larb monitor mechanism definition*/ +enum { + LARB_MONITOR_LEVEL_HIGH = 10, + LARB_MONITOR_LEVEL_MEDIUM = 20, + LARB_MONITOR_LEVEL_LOW = 30, +}; + +struct larb_monitor { + struct list_head link; + int level; + void (*backup)(struct larb_monitor *h, int larb_idx); /* called before disable larb clock */ + void (*restore)(struct larb_monitor *h, int larb_idx); /* called after enable larb clock */ +}; + +enum monitor_clk_sel_0 { + no_clk_0 = 0, + AD_UNIV_624M_CK = 5, + AD_UNIV_416M_CK = 6, + AD_UNIV_249P6M_CK = 7, + AD_UNIV_178P3M_CK_0 = 8, + AD_UNIV_48M_CK = 9, + AD_USB_48M_CK = 10, + rtc32k_ck_i_0 = 20, + AD_SYS_26M_CK_0 = 21, +}; +enum monitor_clk_sel { + no_clk = 0, + AD_SYS_26M_CK = 1, + rtc32k_ck_i = 2, + clkph_MCLK_o = 7, + AD_DPICLK = 8, + AD_MSDCPLL_CK = 9, + AD_MMPLL_CK = 10, + AD_UNIV_178P3M_CK = 11, + AD_MAIN_H156M_CK = 12, + AD_VENCPLL_CK = 13, +}; + +enum ckmon_sel { + clk_ckmon0 = 0, + clk_ckmon1 = 1, + clk_ckmon2 = 2, + clk_ckmon3 = 3, +}; + +enum idle_mode { + dpidle = 0, + soidle = 1, + slidle = 2, +}; + +extern void register_larb_monitor(struct larb_monitor *handler); +extern void unregister_larb_monitor(struct larb_monitor *handler); + +/* clock API */ +extern int enable_clock(int id, char *mod_name); +extern int disable_clock(int id, char *mod_name); +extern int mt_enable_clock(int id, char *mod_name); +extern int mt_disable_clock(int id, char *mod_name); + +extern int enable_clock_ext_locked(int id, char *mod_name); +extern int disable_clock_ext_locked(int id, char *mod_name); + +extern int clock_is_on(int id); + +extern int clkmux_sel(int id, unsigned int clksrc, char *name); +extern void enable_mux(int id, char *name); +extern void disable_mux(int id, char *name); + +extern void clk_set_force_on(int id); +extern void clk_clr_force_on(int id); +extern int clk_is_force_on(int id); + +/* pll API */ +extern int enable_pll(int id, char *mod_name); +extern int disable_pll(int id, char *mod_name); + +extern int pll_hp_switch_on(int id, int hp_on); +extern int pll_hp_switch_off(int id, int hp_off); + +extern int pll_fsel(int id, unsigned int value); +extern int pll_is_on(int id); + +/* subsys API */ +extern int enable_subsys(int id, char *mod_name); +extern int disable_subsys(int id, char *mod_name); + +extern int subsys_is_on(int id); +extern int md_power_on(int id); +extern int md_power_off(int id, unsigned int timeout); +extern int conn_power_on(void); +extern int conn_power_off(void); + +/* other API */ + +extern void set_mipi26m(int en); +extern void set_ada_ssusb_xtal_ck(int en); + +const char *grp_get_name(int id); +extern int clkmgr_is_locked(void); + +/* init */ +extern int mt_clkmgr_init(void); + +extern int clk_monitor_0(enum ckmon_sel ckmon, enum monitor_clk_sel_0 sel, int div); +extern int clk_monitor(enum ckmon_sel ckmon, enum monitor_clk_sel sel, int div); + +extern void clk_stat_check(int id); +extern void slp_check_pm_mtcmos_pll(void); + +/* sram debug */ +extern void aee_rr_rec_clk(int id, u32 val); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr3.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr3.h new file mode 100644 index 0000000000000000000000000000000000000000..10a3853c0e1ccd3e3d3eb1e4ff8025590ea9a49b --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_clkmgr3.h @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_CLKMGR3_H +#define _MT_CLKMGR3_H + +#include +/* #include "mach/mt_reg_base.h" */ +/* #include "mach/mt_typedefs.h" */ + +#define CONFIG_CLKMGR_STAT +#define PLL_CLK_LINK + +/* +#define APMIXED_BASE (0x10209000) +#define CKSYS_BASE (0x10210000) +#define INFRACFG_AO_BASE (0x10000000) +#define PERICFG_BASE (0x10002000) +#define AUDIO_BASE (0x11220000) +#define MFGCFG_BASE (0x13000000) +#define MMSYS_CONFIG_BASE (0x14000000) +#define IMGSYS_BASE (0x15000000) +#define VDEC_GCON_BASE (0x16000000) +#define MJC_CONFIG_BASE (0xF2000000) +#define VENC_GCON_BASE (0x17000000) +*/ +#ifdef CONFIG_OF +extern void __iomem *clk_apmixed_base; +extern void __iomem *clk_cksys_base; +extern void __iomem *clk_infracfg_ao_base; +extern void __iomem *clk_pericfg_base; +extern void __iomem *clk_audio_base; +extern void __iomem *clk_mfgcfg_base; +extern void __iomem *clk_mmsys_config_base; +extern void __iomem *clk_imgsys_base; +extern void __iomem *clk_vdec_gcon_base; +/* extern void __iomem *clk_mjc_config_base; */ +extern void __iomem *clk_venc_gcon_base; +#endif + + +/* APMIXEDSYS Register */ +#define AP_PLL_CON0 (clk_apmixed_base + 0x00) +#define AP_PLL_CON1 (clk_apmixed_base + 0x04) +#define AP_PLL_CON2 (clk_apmixed_base + 0x08) +#define AP_PLL_CON3 (clk_apmixed_base + 0x0C) +#define AP_PLL_CON4 (clk_apmixed_base + 0x10) +#define AP_PLL_CON5 (clk_apmixed_base + 0x14) +#define AP_PLL_CON6 (clk_apmixed_base + 0x18) +#define AP_PLL_CON7 (clk_apmixed_base + 0x1C) +#define CLKSQ_STB_CON0 (clk_apmixed_base + 0x20) +#define PLL_PWR_CON0 (clk_apmixed_base + 0x24) +#define PLL_PWR_CON1 (clk_apmixed_base + 0x28) +#define PLL_ISO_CON0 (clk_apmixed_base + 0x2C) +#define PLL_ISO_CON1 (clk_apmixed_base + 0x30) +#define PLL_STB_CON0 (clk_apmixed_base + 0x34) +#define DIV_STB_CON0 (clk_apmixed_base + 0x38) +#define PLL_CHG_CON0 (clk_apmixed_base + 0x3C) +#define PLL_TEST_CON0 (clk_apmixed_base + 0x40) + +#define ARMPLL_CON0 (clk_apmixed_base + 0x200) +#define ARMPLL_CON1 (clk_apmixed_base + 0x204) +#define ARMPLL_CON2 (clk_apmixed_base + 0x208) +#define ARMPLL_PWR_CON0 (clk_apmixed_base + 0x20C) + +#define MAINPLL_CON0 (clk_apmixed_base + 0x210) +#define MAINPLL_CON1 (clk_apmixed_base + 0x214) +#define MAINPLL_PWR_CON0 (clk_apmixed_base + 0x21C) + +#define UNIVPLL_CON0 (clk_apmixed_base + 0x220) +#define UNIVPLL_CON1 (clk_apmixed_base + 0x224) +#define UNIVPLL_PWR_CON0 (clk_apmixed_base + 0x22C) + +#define MMPLL_CON0 (clk_apmixed_base + 0x230) +#define MMPLL_CON1 (clk_apmixed_base + 0x234) +#define MMPLL_CON2 (clk_apmixed_base + 0x238) +#define MMPLL_PWR_CON0 (clk_apmixed_base + 0x23C) + +#define MSDCPLL_CON0 (clk_apmixed_base + 0x240) +#define MSDCPLL_CON1 (clk_apmixed_base + 0x244) +#define MSDCPLL_PWR_CON0 (clk_apmixed_base + 0x24C) + +#define VENCPLL_CON0 (clk_apmixed_base + 0x250) +#define VENCPLL_CON1 (clk_apmixed_base + 0x254) +#define VENCPLL_PWR_CON0 (clk_apmixed_base + 0x25C) + +#define TVDPLL_CON0 (clk_apmixed_base + 0x260) +#define TVDPLL_CON1 (clk_apmixed_base + 0x264) +#define TVDPLL_PWR_CON0 (clk_apmixed_base + 0x26C) + +/* #define MPLL_CON0 (clk_apmixed_base + 0x280) */ +/* #define MPLL_CON1 (clk_apmixed_base + 0x284) */ +/* #define MPLL_PWR_CON0 (clk_apmixed_base + 0x28C) */ + +#define APLL1_CON0 (clk_apmixed_base + 0x270) +#define APLL1_CON1 (clk_apmixed_base + 0x274) +#define APLL1_CON2 (clk_apmixed_base + 0x278) +#define APLL1_CON3 (clk_apmixed_base + 0x27C) +#define APLL1_PWR_CON0 (clk_apmixed_base + 0x280) + +#define APLL2_CON0 (clk_apmixed_base + 0x284) +#define APLL2_CON1 (clk_apmixed_base + 0x288) +#define APLL2_CON2 (clk_apmixed_base + 0x28C) +#define APLL2_CON3 (clk_apmixed_base + 0x290) +#define APLL2_PWR_CON0 (clk_apmixed_base + 0x294) + +/* TOPCKGEN Register */ +#define CLK_MODE (clk_cksys_base + 0x000) +/* #define CLK_CFG_UPDATE (clk_cksys_base + 0x004) */ +#define TST_SEL_0 (clk_cksys_base + 0x020) +#define TST_SEL_1 (clk_cksys_base + 0x024) +/* #define TST_SEL_2 (clk_cksys_base + 0x028) */ +#define CLK_CFG_0 (clk_cksys_base + 0x040) +#define CLK_CFG_1 (clk_cksys_base + 0x050) +#define CLK_CFG_2 (clk_cksys_base + 0x060) +#define CLK_CFG_3 (clk_cksys_base + 0x070) +#define CLK_CFG_4 (clk_cksys_base + 0x080) +#define CLK_CFG_5 (clk_cksys_base + 0x090) +#define CLK_CFG_6 (clk_cksys_base + 0x0A0) +#define CLK_CFG_7 (clk_cksys_base + 0x0B0) +#define CLK_CFG_8 (clk_cksys_base + 0x100) +#define CLK_CFG_9 (clk_cksys_base + 0x104) +#define CLK_CFG_10 (clk_cksys_base + 0x108) +#define CLK_CFG_11 (clk_cksys_base + 0x10C) +#define CLK_SCP_CFG_0 (clk_cksys_base + 0x200) +#define CLK_SCP_CFG_1 (clk_cksys_base + 0x204) +#define CLK_MISC_CFG_0 (clk_cksys_base + 0x210) +#define CLK_MISC_CFG_1 (clk_cksys_base + 0x214) +#define CLK_MISC_CFG_2 (clk_cksys_base + 0x218) +#define CLK26CALI_0 (clk_cksys_base + 0x220) +#define CLK26CALI_1 (clk_cksys_base + 0x224) +#define CLK26CALI_2 (clk_cksys_base + 0x228) +#define CKSTA_REG (clk_cksys_base + 0x22C) +#define MBIST_CFG_0 (clk_cksys_base + 0x308) +#define MBIST_CFG_1 (clk_cksys_base + 0x30C) + +/* INFRASYS Register */ +#define TOP_CKMUXSEL (clk_infracfg_ao_base + 0x00) +#define TOP_CKDIV1 (clk_infracfg_ao_base + 0x08) + +#define INFRA_PDN_SET0 (clk_infracfg_ao_base + 0x0040) +#define INFRA_PDN_CLR0 (clk_infracfg_ao_base + 0x0044) +#define INFRA_PDN_STA0 (clk_infracfg_ao_base + 0x0048) + +#define TOPAXI_PROT_EN (clk_infracfg_ao_base + 0x0220) +#define TOPAXI_PROT_STA1 (clk_infracfg_ao_base + 0x0228) +#define C2K_SPM_CTRL (clk_infracfg_ao_base + 0x0338) + +#define PERI_PDN_SET0 (clk_pericfg_base + 0x0008) +#define PERI_PDN_CLR0 (clk_pericfg_base + 0x0010) +#define PERI_PDN_STA0 (clk_pericfg_base + 0x0018) +#define PERI_GLOBALCON_CKSEL (clk_pericfg_base + 0x005c) + +/* Audio Register*/ +#define AUDIO_TOP_CON0 (clk_audio_base + 0x0000) +#define AUDIO_TOP_CON1 (clk_audio_base + 0x0004) + +/* MFGCFG Register*/ +#define MFG_CG_CON (clk_mfgcfg_base + 0) +#define MFG_CG_SET (clk_mfgcfg_base + 4) +#define MFG_CG_CLR (clk_mfgcfg_base + 8) + +/* MMSYS Register*/ +#define DISP_CG_CON0 (clk_mmsys_config_base + 0x100) +#define DISP_CG_SET0 (clk_mmsys_config_base + 0x104) +#define DISP_CG_CLR0 (clk_mmsys_config_base + 0x108) +#define DISP_CG_CON1 (clk_mmsys_config_base + 0x110) +#define DISP_CG_SET1 (clk_mmsys_config_base + 0x114) +#define DISP_CG_CLR1 (clk_mmsys_config_base + 0x118) + +#define MMSYS_DUMMY (clk_mmsys_config_base + 0x894) +/* #define SMI_LARB_BWL_EN_REG (clk_mmsys_config_base + 0x21050) */ + +/* IMGSYS Register */ +#define IMG_CG_CON (clk_imgsys_base + 0x0000) +#define IMG_CG_SET (clk_imgsys_base + 0x0004) +#define IMG_CG_CLR (clk_imgsys_base + 0x0008) + +/* VDEC Register */ +#define VDEC_CKEN_SET (clk_vdec_gcon_base + 0x0000) +#define VDEC_CKEN_CLR (clk_vdec_gcon_base + 0x0004) +#define LARB_CKEN_SET (clk_vdec_gcon_base + 0x0008) +#define LARB_CKEN_CLR (clk_vdec_gcon_base + 0x000C) + +/* MJC Register*/ +/* #define MJC_CG_CON (clk_mjc_config_base + 0x0000) */ +/* #define MJC_CG_SET (clk_mjc_config_base + 0x0004) */ +/* #define MJC_CG_CLR (clk_mjc_config_base + 0x0008) */ + +/* VENC Register*/ +#define VENC_CG_CON (clk_venc_gcon_base + 0x0) +#define VENC_CG_SET (clk_venc_gcon_base + 0x4) +#define VENC_CG_CLR (clk_venc_gcon_base + 0x8) + +/* MCUSYS Register */ +/* #define IR_ROSC_CTL (MCUCFG_BASE + 0x030) */ + + + +enum { + CG_INFRA = 0, + CG_PERI = 1, + CG_DISP0 = 2, + CG_DISP1 = 3, + CG_IMAGE = 4, + CG_MFG = 5, + CG_AUDIO = 6, + CG_VDEC0 = 7, + CG_VDEC1 = 8, + CG_VENC = 9, + NR_GRPS = 10, +}; + +enum cg_clk_id { /* The following is CODA name */ + MT_CG_INFRA_DBGCLK = 0, /* */ + MT_CG_INFRA_GCE = 1, /* */ + MT_CG_INFRA_TRBG = 2, /* */ + MT_CG_INFRA_CPUM = 3, /* */ + MT_CG_INFRA_DEVAPC = 4, /* */ + MT_CG_INFRA_AUDIO = 5, /* */ + MT_CG_INFRA_GCPU = 6, /* */ + MT_CG_INFRA_L2C_SRAM = 7, /* */ + MT_CG_INFRA_M4U = 8, /* */ + MT_CG_INFRA_CLDMA = 12, /* */ + MT_CG_INFRA_CONNMCU_BUS = 15, /* */ + MT_CG_INFRA_KP = 16, /* */ + MT_CG_INFRA_APXGPT = 18, /* */ + MT_CG_INFRA_SEJ = 19, /* */ + MT_CG_INFRA_CCIF0_AP = 20, /* */ + MT_CG_INFRA_CCIF1_AP = 21, /* */ + MT_CG_INFRA_PMIC_SPI = 22, /* */ + MT_CG_INFRA_PMIC_WRAP = 23, /* */ +/* MT_CG_INFRA_CG_0 = 32, */ + + MT_CG_PERI_DISP_PWM = 0 + 32, + MT_CG_PERI_THERM = 1 + 32, + MT_CG_PERI_PWM1 = 2 + 32, + MT_CG_PERI_PWM2 = 3 + 32, + MT_CG_PERI_PWM3 = 4 + 32, + MT_CG_PERI_PWM4 = 5 + 32, + MT_CG_PERI_PWM5 = 6 + 32, + MT_CG_PERI_PWM6 = 7 + 32, + MT_CG_PERI_PWM7 = 8 + 32, + MT_CG_PERI_PWM = 9 + 32, + MT_CG_PERI_USB0 = 10 + 32, + MT_CG_PERI_IRDA = 11 + 32, + MT_CG_PERI_APDMA = 12 + 32, + MT_CG_PERI_MSDC30_0 = 13 + 32, + MT_CG_PERI_MSDC30_1 = 14 + 32, + MT_CG_PERI_MSDC30_2 = 15 + 32, + MT_CG_PERI_MSDC30_3 = 16 + 32, + MT_CG_PERI_UART0 = 17 + 32, + MT_CG_PERI_UART1 = 18 + 32, + MT_CG_PERI_UART2 = 19 + 32, + MT_CG_PERI_UART3 = 20 + 32, + MT_CG_PERI_UART4 = 21 + 32, + MT_CG_PERI_BTIF = 22 + 32, + MT_CG_PERI_I2C0 = 23 + 32, + MT_CG_PERI_I2C1 = 24 + 32, + MT_CG_PERI_I2C2 = 25 + 32, + MT_CG_PERI_I2C3 = 26 + 32, + MT_CG_PERI_AUXADC = 27 + 32, + MT_CG_PERI_SPI0 = 28 + 32, + MT_CG_PERI_IRTX = 29 + 32, + MT_CG_PERI_I2C4 = 30 + 32, +/* MT_CG_INFRA_CG_1 = 64, // , */ + + MT_CG_DISP0_SMI_COMMON = 0 + 64, + MT_CG_DISP0_SMI_LARB0 = 1 + 64, + MT_CG_DISP0_CAM_MDP = 2 + 64, + MT_CG_DISP0_MDP_RDMA = 3 + 64, + MT_CG_DISP0_MDP_RSZ0 = 4 + 64, + MT_CG_DISP0_MDP_RSZ1 = 5 + 64, + MT_CG_DISP0_MDP_TDSHP = 6 + 64, + MT_CG_DISP0_MDP_WDMA = 7 + 64, + MT_CG_DISP0_MDP_WROT = 8 + 64, + MT_CG_DISP0_FAKE_ENG = 9 + 64, + MT_CG_DISP0_DISP_OVL0 = 10 + 64, + MT_CG_DISP0_DISP_OVL1 = 11 + 64, + MT_CG_DISP0_DISP_RDMA0 = 12 + 64, + MT_CG_DISP0_DISP_RDMA1 = 13 + 64, + MT_CG_DISP0_DISP_WDMA0 = 14 + 64, + MT_CG_DISP0_DISP_COLOR = 15 + 64, + MT_CG_DISP0_DISP_CCORR = 16 + 64, + MT_CG_DISP0_DISP_AAL = 17 + 64, + MT_CG_DISP0_DISP_GAMMA = 18 + 64, + MT_CG_DISP0_DISP_DITHER = 19 + 64, + MT_CG_DISP0_DISP_OD = 21 + 64, +/* MT_CG_DISP0_CG_0 = 96, */ + + MT_CG_DISP1_DSI_ENGINE = 2 + 96, + MT_CG_DISP1_DSI_DIGITAL = 3 + 96, + MT_CG_DISP1_DPI_ENGINE = 4 + 96, + MT_CG_DISP1_DPI_PIXEL = 5 + 96, +/* MT_CG_DISP1_CG_1 = 128, */ + + MT_CG_IMAGE_LARB2_SMI = 0 + 128, + MT_CG_IMAGE_CAM_SMI = 5 + 128, + MT_CG_IMAGE_CAM_CAM = 6 + 128, + MT_CG_IMAGE_SEN_TG = 7 + 128, + MT_CG_IMAGE_SEN_CAM = 8 + 128, + MT_CG_IMAGE_CAM_SV = 9 + 128, + MT_CG_IMAGE_SUFOD = 10 + 128, + MT_CG_IMAGE_FD = 11 + 128, +/* MT_CG_IMAGE_CG = 160, */ + + MT_CG_MFG_BG3D = 0 + 160, +/* MT_CG_MFG_CG = 192, */ + + MT_CG_AUDIO_AFE = 2 + 192, + MT_CG_AUDIO_I2S = 6 + 192, + MT_CG_AUDIO_22M = 8 + 192, + MT_CG_AUDIO_24M = 9 + 192, + MT_CG_AUDIO_APLL2_TUNER = 18 + 192, + MT_CG_AUDIO_APLL_TUNER = 19 + 192, + MT_CG_AUDIO_ADC = 24 + 192, + MT_CG_AUDIO_DAC = 25 + 192, + MT_CG_AUDIO_DAC_PREDIS = 26 + 192, + MT_CG_AUDIO_TML = 27 + 192, +/* MT_CG_AUDIO_CG = 224, */ + + MT_CG_VDEC0_VDEC = 0 + 224, +/* MT_CG_VDEC0_CG = 256, */ + + MT_CG_VDEC1_LARB = 0 + 256, +/* MT_CG_VDEC1_CG = 288, */ + + MT_CG_VENC_LARB = 0 + 288, + MT_CG_VENC_VENC = 4 + 288, + MT_CG_VENC_JPGENC = 8 + 288, + MT_CG_VENC_JPGDEC = 12 + 288, + + CG_INFRA_FROM = MT_CG_INFRA_DBGCLK, + CG_INFRA_TO = MT_CG_INFRA_PMIC_WRAP, + NR_INFRA_CLKS = 23, + + CG_PERI_FROM = MT_CG_PERI_DISP_PWM, + CG_PERI_TO = MT_CG_PERI_I2C4, + NR_PERI_CLKS = 29, + + CG_DISP0_FROM = MT_CG_DISP0_SMI_COMMON, + CG_DISP0_TO = MT_CG_DISP0_DISP_OD, + NR_DISP0_CLKS = 21, + + CG_DISP1_FROM = MT_CG_DISP1_DSI_ENGINE, + CG_DISP1_TO = MT_CG_DISP1_DPI_PIXEL, + NR_DISP1_CLKS = 5, + + CG_IMAGE_FROM = MT_CG_IMAGE_LARB2_SMI, + CG_IMAGE_TO = MT_CG_IMAGE_FD, + NR_IMAGE_CLKS = 11, + + CG_MFG_FROM = MT_CG_MFG_BG3D, + CG_MFG_TO = MT_CG_MFG_BG3D, + NR_MFG_CLKS = 1, + + CG_AUDIO_FROM = MT_CG_AUDIO_AFE, + CG_AUDIO_TO = MT_CG_AUDIO_TML, + NR_AUDIO_CLKS = 27, + + CG_VDEC0_FROM = MT_CG_VDEC0_VDEC, + CG_VDEC0_TO = MT_CG_VDEC0_VDEC, + NR_VDEC0_CLKS = 1, + + CG_VDEC1_FROM = MT_CG_VDEC1_LARB, + CG_VDEC1_TO = MT_CG_VDEC1_LARB, + NR_VDEC1_CLKS = 1, + + CG_VENC_FROM = MT_CG_VENC_LARB, + CG_VENC_TO = MT_CG_VENC_JPGDEC, + NR_VENC_CLKS = 12, + + NR_CLKS = 301, + +}; + +enum { + /* CLK_CFG_0 */ + MT_MUX_MM = 0, + MT_MUX_DDRPHY = 1, + MT_MUX_MEM = 2, + MT_MUX_AXI = 3, + + /* CLK_CFG_1 */ + MT_MUX_CAMTG = 4, + MT_MUX_MFG = 5, + MT_MUX_VDEC = 6, + MT_MUX_PWM = 7, + + /* CLK_CFG_2 */ + MT_MUX_MSDC50_0 = 8, + MT_MUX_USB20 = 9, + MT_MUX_SPI = 10, + MT_MUX_UART = 11, + + /* CLK_CFG_3 */ + MT_MUX_MSDC30_3 = 12, + MT_MUX_MSDC30_2 = 13, + MT_MUX_MSDC30_1 = 14, + MT_MUX_MSDC30_0 = 15, + + /* CLK_CFG_4 */ + MT_MUX_SCP = 16, + MT_MUX_PMICSPI = 17, + MT_MUX_AUDINTBUS = 18, + MT_MUX_AUDIO = 19, + + /* CLK_CFG_5 */ + MT_MUX_MFG13M = 20, + MT_MUX_SCAM = 21, + MT_MUX_DPI0 = 22, + MT_MUX_ATB = 23, + + /* CLK_CFG_6 */ + MT_MUX_IRTX = 24, + MT_MUX_IRDA = 25, + MT_MUX_AUD2 = 26, + MT_MUX_AUD1 = 27, + + /* CLK_CFG_7 */ + MT_MUX_DISPPWM = 28, + + NR_MUXS = 29, +}; + +enum { + ARMPLL = 0, + MAINPLL = 1, + MSDCPLL = 2, + UNIVPLL = 3, + MMPLL = 4, + VENCPLL = 5, + TVDPLL = 6, + APLL1 = 7, + APLL2 = 8, + NR_PLLS = 9, +}; + +enum { + SYS_MD1 = 0, + SYS_MD2 = 1, + SYS_CONN = 2, + SYS_DIS = 3, + SYS_MFG = 4, + SYS_ISP = 5, + SYS_VDE = 6, + SYS_VEN = 7, +/* SYS_AUD = 8, */ + NR_SYSS = 8, +}; + +enum { + MT_LARB_DISP = 0, + MT_LARB_VDEC = 1, + MT_LARB_IMG = 2, + MT_LARB_VENC = 3, + /* MT_LARB_MJC = 4, */ +}; + +/* larb monitor mechanism definition*/ +enum { + LARB_MONITOR_LEVEL_HIGH = 10, + LARB_MONITOR_LEVEL_MEDIUM = 20, + LARB_MONITOR_LEVEL_LOW = 30, +}; + +struct larb_monitor { + struct list_head link; + int level; + void (*backup)(struct larb_monitor *h, int larb_idx); /* called before disable larb clock */ + void (*restore)(struct larb_monitor *h, int larb_idx); /* called after enable larb clock */ +}; + +enum monitor_clk_sel_0 { + no_clk_0 = 0, + AD_UNIV_624M_CK = 5, + AD_UNIV_416M_CK = 6, + AD_UNIV_249P6M_CK = 7, + AD_UNIV_178P3M_CK_0 = 8, + AD_UNIV_48M_CK = 9, + AD_USB_48M_CK = 10, + rtc32k_ck_i_0 = 20, + AD_SYS_26M_CK_0 = 21, +}; +enum monitor_clk_sel { + no_clk = 0, + AD_SYS_26M_CK = 1, + rtc32k_ck_i = 2, + clkph_MCLK_o = 7, + AD_DPICLK = 8, + AD_MSDCPLL_CK = 9, + AD_MMPLL_CK = 10, + AD_UNIV_178P3M_CK = 11, + AD_MAIN_H156M_CK = 12, + AD_VENCPLL_CK = 13, +}; + +enum ckmon_sel { + clk_ckmon0 = 0, + clk_ckmon1 = 1, + clk_ckmon2 = 2, + clk_ckmon3 = 3, +}; + +enum idle_mode { + dpidle = 0, + soidle = 1, + slidle = 2, +}; + +extern void register_larb_monitor(struct larb_monitor *handler); +extern void unregister_larb_monitor(struct larb_monitor *handler); + +/* clock API */ +extern int enable_clock(int id, char *mod_name); +extern int disable_clock(int id, char *mod_name); +extern int mt_enable_clock(int id, char *mod_name); +extern int mt_disable_clock(int id, char *mod_name); + +extern int enable_clock_ext_locked(int id, char *mod_name); +extern int disable_clock_ext_locked(int id, char *mod_name); + +extern int clock_is_on(int id); + +extern int clkmux_sel(int id, unsigned int clksrc, char *name); +extern void enable_mux(int id, char *name); +extern void disable_mux(int id, char *name); + +extern void clk_set_force_on(int id); +extern void clk_clr_force_on(int id); +extern int clk_is_force_on(int id); + +/* pll API */ +extern int enable_pll(int id, char *mod_name); +extern int disable_pll(int id, char *mod_name); + +extern int pll_hp_switch_on(int id, int hp_on); +extern int pll_hp_switch_off(int id, int hp_off); + +extern int pll_fsel(int id, unsigned int value); +extern int pll_is_on(int id); + +/* subsys API */ +extern int enable_subsys(int id, char *mod_name); +extern int disable_subsys(int id, char *mod_name); + +extern int subsys_is_on(int id); +extern int md_power_on(int id); +extern int md_power_off(int id, unsigned int timeout); +extern int conn_power_on(void); +extern int conn_power_off(void); + +/* other API */ + +extern void set_mipi26m(int en); +extern void set_ada_ssusb_xtal_ck(int en); + +const char *grp_get_name(int id); +extern int clkmgr_is_locked(void); + +/* init */ +extern int mt_clkmgr_init(void); + +extern int clk_monitor_0(enum ckmon_sel ckmon, enum monitor_clk_sel_0 sel, int div); +extern int clk_monitor(enum ckmon_sel ckmon, enum monitor_clk_sel sel, int div); + +extern void clk_stat_check(int id); +extern void slp_check_pm_mtcmos_pll(void); + +/* sram debug */ +extern void aee_rr_rec_clk(int id, u32 val); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_cpuxgpt.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_cpuxgpt.h new file mode 100644 index 0000000000000000000000000000000000000000..77319f017c7087bc012a6c96cc1b92a931b2c7cd --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_cpuxgpt.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_CPUXGPT_H_ +#define _MT_CPUXGPT_H_ + +#include + +typedef enum cpuxgpt_num { + CPUXGPT0 = 0, + CPUXGPT1, + CPUXGPT2, + CPUXGPT3, + CPUXGPT4, + CPUXGPT5, + CPUXGPT6, + CPUXGPT7, + CPUXGPTNUMBERS, +} CPUXGPT_NUM; + +/* REG */ +#define INDEX_CTL_REG 0x000 +#define INDEX_STA_REG 0x004 +#define INDEX_CNT_L_INIT 0x008 +#define INDEX_CNT_H_INIT 0x00C +#define INDEX_IRQ_MASK 0x030 /* 0~7 bit mask cnt0~cnt7 interrupt */ + +#define INDEX_CMP_BASE 0x034 + +/* CTL_REG SET */ +#define EN_CPUXGPT 0x01 +#define EN_AHLT_DEBUG 0x02 +/* #define CLK_DIV1 (0b001 << 8) */ +/* #define CLK_DIV2 (0b010 << 8) */ +/* #define CLK_DIV4 (0b100 << 8) */ +#define CLK_DIV1 (0x1 << 8) +#define CLK_DIV2 (0x2 << 8) +#define CLK_DIV4 (0x4 << 8) +#define CLK_DIV_MASK (~(0x7<<8)) + +#define CPUX_GPT0_ACK (1<<0x0) +#define CPUX_GPT1_ACK (1<<0x1) +#define CPUX_GPT2_ACK (1<<0x2) +#define CPUX_GPT3_ACK (1<<0x3) +#define CPUX_GPT4_ACK (1<<0x4) +#define CPUX_GPT5_ACK (1<<0x5) +#define CPUX_GPT6_ACK (1<<0x6) +#define CPUX_GPT7_ACK (1<<0x7) + +void enable_cpuxgpt(void); +void set_cpuxgpt_clk(unsigned int div); +void disable_cpuxgpt(void); +int cpu_xgpt_set_timer(int id, u64 ns); +int cpu_xgpt_set_cmp(CPUXGPT_NUM cpuxgpt_num, u64 count); +int cpu_xgpt_register_timer(unsigned int id, irqreturn_t (*func)(int irq, void *dev_id)); +void cpu_xgpt_set_init_count(unsigned int countH, unsigned int countL); +void cpu_xgpt_halt_on_debug_en(int en); +u64 localtimer_get_phy_count(void); +unsigned int cpu_xgpt_irq_dis(int cpuxgpt_num); +void restore_cpuxgpt(void); +void save_cpuxgpt(void); +void generic_timer_backup(void); +void mt_cpuxgpt_map_base(void); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_emi_bm.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_emi_bm.h new file mode 100644 index 0000000000000000000000000000000000000000..3e7cd37736740a39a98c097949133f2534994dcb --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_emi_bm.h @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_EMI_BM_H__ +#define __MT_EMI_BW_H__ + +#define EMI_CONM (EMI_BASE_ADDR + 0x060) +#define EMI_ARBA (EMI_BASE_ADDR + 0x100) +#define EMI_ARBB (EMI_BASE_ADDR + 0x108) +#define EMI_ARBC (EMI_BASE_ADDR + 0x110) +#define EMI_ARBD (EMI_BASE_ADDR + 0x118) +#define EMI_ARBE (EMI_BASE_ADDR + 0x120) +#define EMI_ARBF (EMI_BASE_ADDR + 0x128) +#define EMI_ARBG_2ND (EMI_BASE_ADDR + 0x134) +#define EMI_ARBG (EMI_BASE_ADDR + 0x130) +#define EMI_ARBH (EMI_BASE_ADDR + 0x138) +#define EMI_BMEN (EMI_BASE_ADDR + 0x400) +#define EMI_BCNT (EMI_BASE_ADDR + 0x408) +#define EMI_TACT (EMI_BASE_ADDR + 0x410) +#define EMI_TSCT (EMI_BASE_ADDR + 0x418) +#define EMI_WACT (EMI_BASE_ADDR + 0x420) +#define EMI_WSCT (EMI_BASE_ADDR + 0x428) +#define EMI_BACT (EMI_BASE_ADDR + 0x430) +#define EMI_BSCT (EMI_BASE_ADDR + 0x438) +#define EMI_MSEL (EMI_BASE_ADDR + 0x440) +#define EMI_TSCT2 (EMI_BASE_ADDR + 0x448) +#define EMI_TSCT3 (EMI_BASE_ADDR + 0x450) +#define EMI_WSCT2 (EMI_BASE_ADDR + 0x458) +#define EMI_WSCT3 (EMI_BASE_ADDR + 0x460) +#define EMI_WSCT4 (EMI_BASE_ADDR + 0x464) +#define EMI_MSEL2 (EMI_BASE_ADDR + 0x468) +#define EMI_MSEL3 (EMI_BASE_ADDR + 0x470) +#define EMI_MSEL4 (EMI_BASE_ADDR + 0x478) +#define EMI_MSEL5 (EMI_BASE_ADDR + 0x480) +#define EMI_MSEL6 (EMI_BASE_ADDR + 0x488) +#define EMI_MSEL7 (EMI_BASE_ADDR + 0x490) +#define EMI_MSEL8 (EMI_BASE_ADDR + 0x498) +#define EMI_MSEL9 (EMI_BASE_ADDR + 0x4A0) +#define EMI_MSEL10 (EMI_BASE_ADDR + 0x4A8) +#define EMI_BMID0 (EMI_BASE_ADDR + 0x4B0) +#define EMI_BMEN1 (EMI_BASE_ADDR + 0x4E0) +#define EMI_BMEN2 (EMI_BASE_ADDR + 0x4E8) +#define EMI_TTYPE1 (EMI_BASE_ADDR + 0x500) +#define EMI_TTYPE2 (EMI_BASE_ADDR + 0x508) +#define EMI_TTYPE3 (EMI_BASE_ADDR + 0x510) +#define EMI_TTYPE4 (EMI_BASE_ADDR + 0x518) +#define EMI_TTYPE5 (EMI_BASE_ADDR + 0x520) +#define EMI_TTYPE6 (EMI_BASE_ADDR + 0x528) +#define EMI_TTYPE7 (EMI_BASE_ADDR + 0x530) +#define EMI_TTYPE9 (EMI_BASE_ADDR + 0x540) +#define EMI_TTYPE10 (EMI_BASE_ADDR + 0x548) +#define EMI_TTYPE11 (EMI_BASE_ADDR + 0x550) +#define EMI_TTYPE12 (EMI_BASE_ADDR + 0x558) +#define EMI_TTYPE13 (EMI_BASE_ADDR + 0x560) +#define EMI_TTYPE14 (EMI_BASE_ADDR + 0x568) +#define EMI_TTYPE15 (EMI_BASE_ADDR + 0x570) +#define EMI_TTYPE16 (EMI_BASE_ADDR + 0x578) +#define EMI_TTYPE17 (EMI_BASE_ADDR + 0x580) +#define EMI_TTYPE18 (EMI_BASE_ADDR + 0x588) +#define EMI_TTYPE19 (EMI_BASE_ADDR + 0x590) +#define EMI_TTYPE20 (EMI_BASE_ADDR + 0x598) +#define EMI_TTYPE21 (EMI_BASE_ADDR + 0x5A0) + +#define EMI_CONH (EMI_BASE_ADDR + 0x038) +#define EMI_CONO (EMI_BASE_ADDR + 0x04C) +#define EMI_BWST (EMI_BASE_ADDR + 0x03C) +#define EMI_BWST1 (EMI_BASE_ADDR + 0x05C) +#define DRAMC_R2R_PAGE_HIT (0x280) +#define DRAMC_R2R_PAGE_MISS (0x284) +#define DRAMC_R2R_INTERBANK (0x288) +#define DRAMC_R2W_PAGE_HIT (0x28C) +#define DRAMC_R2W_PAGE_MISS (0x290) +#define DRAMC_R2W_INTERBANK (0x294) +#define DRAMC_W2R_PAGE_HIT (0x298) +#define DRAMC_W2R_PAGE_MISS (0x29C) +#define DRAMC_W2R_INTERBANK (0x2A0) +#define DRAMC_W2W_PAGE_HIT (0x2A4) +#define DRAMC_W2W_PAGE_MISS (0x2A8) +#define DRAMC_W2W_INTERBANK (0x2AC) +#define DRAMC_IDLE_COUNT (0x2B0) + +enum { + DRAMC_R2R, + DRAMC_R2W, + DRAMC_W2R, + DRAMC_W2W, + DRAMC_ALL +}; + +enum { + BM_BOTH_READ_WRITE, + BM_READ_ONLY, + BM_WRITE_ONLY +}; + +enum { + BM_TRANS_TYPE_1BEAT = 0x0, + BM_TRANS_TYPE_2BEAT, + BM_TRANS_TYPE_3BEAT, + BM_TRANS_TYPE_4BEAT, + BM_TRANS_TYPE_5BEAT, + BM_TRANS_TYPE_6BEAT, + BM_TRANS_TYPE_7BEAT, + BM_TRANS_TYPE_8BEAT, + BM_TRANS_TYPE_9BEAT, + BM_TRANS_TYPE_10BEAT, + BM_TRANS_TYPE_11BEAT, + BM_TRANS_TYPE_12BEAT, + BM_TRANS_TYPE_13BEAT, + BM_TRANS_TYPE_14BEAT, + BM_TRANS_TYPE_15BEAT, + BM_TRANS_TYPE_16BEAT, + BM_TRANS_TYPE_1Byte = 0 << 4, + BM_TRANS_TYPE_2Byte = 1 << 4, + BM_TRANS_TYPE_4Byte = 2 << 4, + BM_TRANS_TYPE_8Byte = 3 << 4, + BM_TRANS_TYPE_16Byte = 4 << 4, + BM_TRANS_TYPE_BURST_WRAP = 0 << 7, + BM_TRANS_TYPE_BURST_INCR = 1 << 7 +}; + +#define BM_MASTER_AP_MCU1 (0x01) +#define BM_MASTER_AP_MCU2 (0x02) +#define BM_MASTER_MM1 (0x04) +#define BM_MASTER_MD_MCU (0x08) +#define BM_MASTER_2G_3G_MDDMA (0x10) +#define BM_MASTER_MM2 (0x20) +#define BM_MASTER_GPU1 (0x40) +#define BM_MASTER_GPU2 (0x80) +#define BM_MASTER_ALL (0xFF) + +#define BUS_MON_EN (0x00000001) +#define BUS_MON_PAUSE (0x00000002) +#define BC_OVERRUN (0x00000100) + +#define BM_COUNTER_MAX (21) + +#define BM_REQ_OK (0) +#define BM_ERR_WRONG_REQ (-1) +#define BM_ERR_OVERRUN (-2) + +extern void BM_Init(void); +extern void BM_DeInit(void); +extern void BM_Enable(const unsigned int enable); +/* extern void BM_Disable(void); */ +extern void BM_Pause(void); +extern void BM_Continue(void); +extern unsigned int BM_IsOverrun(void); +extern void BM_SetReadWriteType(const unsigned int ReadWriteType); +extern int BM_GetBusCycCount(void); +extern unsigned int BM_GetTransAllCount(void); +extern int BM_GetTransCount(const unsigned int counter_num); +extern long long BM_GetWordAllCount(void); +extern int BM_GetWordCount(const unsigned int counter_num); +extern unsigned int BM_GetBandwidthWordCount(void); +extern unsigned int BM_GetOverheadWordCount(void); +extern int BM_GetTransTypeCount(const unsigned int counter_num); +extern int BM_SetMonitorCounter(const unsigned int counter_num, +const unsigned int master, const unsigned int trans_type); +extern int BM_SetMaster(const unsigned int counter_num, + const unsigned int master); +extern int BM_SetIDSelect(const unsigned int counter_num, const unsigned int id, + const unsigned int enable); +extern int BM_SetUltraHighFilter(const unsigned int counter_num, + const unsigned int enable); +extern int BM_SetLatencyCounter(void); +extern int BM_GetLatencyCycle(const unsigned int counter_num); +extern int BM_GetEmiDcm(void); +extern int BM_SetEmiDcm(const unsigned int setting); + +extern unsigned int DRAMC_GetPageHitCount(const unsigned int CountType); +extern unsigned int DRAMC_GetPageMissCount(const unsigned int CountType); +extern unsigned int DRAMC_GetInterbankCount(const unsigned int CountType); +extern unsigned int DRAMC_GetIdleCount(void); +extern unsigned int ucDram_Register_Read(unsigned long u4reg_addr); +extern int BM_SetBW(const unsigned int BW_config); +extern int BM_SetBW1(const unsigned int BW_config); +extern unsigned int BM_GetBWST(void); +extern unsigned int BM_GetBWST1(void); +extern unsigned int BM_GetBW(void); +extern unsigned int BM_GetBW1(void); +extern void *mt_emi_base_get(void); + +#endif /* !__MT_EMI_BW_H__ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_fhreg.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_fhreg.h new file mode 100644 index 0000000000000000000000000000000000000000..779d6ec3dce7280eca5e5d11249349211f20a456 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_fhreg.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_FHREG_H__ +#define __MT_FHREG_H__ + +#include + +/*--------------------------------------------------------------------------*/ +/* Common Macro */ +/*--------------------------------------------------------------------------*/ +#ifdef CONFIG_OF + +#ifdef CONFIG_ARM64 +#define REG_ADDR(x) ((unsigned long)g_fhctl_base + (x)) +#define REG_APMIX_ADDR(x) ((unsigned long)g_apmixed_base + (x)) +#define REG_DDRPHY_ADDR(x) ((unsigned long)g_ddrphy_base + (x)) +#else +#define REG_ADDR(x) ((unsigned int)g_fhctl_base + (x)) +#define REG_APMIX_ADDR(x) ((unsigned int)g_apmixed_base + (x)) +#define REG_DDRPHY_ADDR(x) ((unsigned int)g_ddrphy_base + (x)) +#endif + +#else +#define REG_ADDR(x) ((0xF0209F00) + (x)) +#define REG_APMIX_ADDR(x) ((0xF0209000) + (x)) +#define REG_DDRPHY_ADDR(x) ((0xF000F000) + (x)) +#endif + +#define REG_FHCTL_HP_EN REG_ADDR(0x0000) +#define REG_FHCTL_CLK_CON REG_ADDR(0x0004) +#define REG_FHCTL_RST_CON REG_ADDR(0x0008) +#define REG_FHCTL_SLOPE0 REG_ADDR(0x000C) +#define REG_FHCTL_SLOPE1 REG_ADDR(0x0010) +#define REG_FHCTL_DSSC_CFG REG_ADDR(0x0014) + +#define REG_FHCTL_DSSC0_CON REG_ADDR(0x0018) +#define REG_FHCTL_DSSC1_CON REG_ADDR(0x001C) +#define REG_FHCTL_DSSC2_CON REG_ADDR(0x0020) +#define REG_FHCTL_DSSC3_CON REG_ADDR(0x0024) +#define REG_FHCTL_DSSC4_CON REG_ADDR(0x0028) +#define REG_FHCTL_DSSC5_CON REG_ADDR(0x002C) +#define REG_FHCTL_DSSC6_CON REG_ADDR(0x0030) +#define REG_FHCTL_DSSC7_CON REG_ADDR(0x0034) + +#define REG_FHCTL0_CFG REG_ADDR(0x0038) +#define REG_FHCTL0_UPDNLMT REG_ADDR(0x003C) +#define REG_FHCTL0_DDS REG_ADDR(0x0040) +#define REG_FHCTL0_DVFS REG_ADDR(0x0044) +#define REG_FHCTL0_MON REG_ADDR(0x0048) + +#define REG_FHCTL1_CFG REG_ADDR(0x004C) +#define REG_FHCTL1_UPDNLMT REG_ADDR(0x0050) +#define REG_FHCTL1_DDS REG_ADDR(0x0054) +#define REG_FHCTL1_DVFS REG_ADDR(0x0058) +#define REG_FHCTL1_MON REG_ADDR(0x005C) + +#define REG_FHCTL2_CFG REG_ADDR(0x0060) +#define REG_FHCTL2_UPDNLMT REG_ADDR(0x0064) +#define REG_FHCTL2_DDS REG_ADDR(0x0068) +#define REG_FHCTL2_DVFS REG_ADDR(0x006C) +#define REG_FHCTL2_MON REG_ADDR(0x0070) + +#define REG_FHCTL3_CFG REG_ADDR(0x0074) +#define REG_FHCTL3_UPDNLMT REG_ADDR(0x0078) +#define REG_FHCTL3_DDS REG_ADDR(0x007C) +#define REG_FHCTL3_DVFS REG_ADDR(0x0080) +#define REG_FHCTL3_MON REG_ADDR(0x0084) + +#define REG_FHCTL4_CFG REG_ADDR(0x0088) +#define REG_FHCTL4_UPDNLMT REG_ADDR(0x008C) +#define REG_FHCTL4_DDS REG_ADDR(0x0090) +#define REG_FHCTL4_DVFS REG_ADDR(0x0094) +#define REG_FHCTL4_MON REG_ADDR(0x0098) + +#define REG_FHCTL5_CFG REG_ADDR(0x009C) +#define REG_FHCTL5_UPDNLMT REG_ADDR(0x00A0) +#define REG_FHCTL5_DDS REG_ADDR(0x00A4) +#define REG_FHCTL5_DVFS REG_ADDR(0x00A8) +#define REG_FHCTL5_MON REG_ADDR(0x00AC) + +#define REG_FHCTL6_CFG REG_ADDR(0x00B0) +#define REG_FHCTL6_UPDNLMT REG_ADDR(0x00B4) +#define REG_FHCTL6_DDS REG_ADDR(0x00B8) +#define REG_FHCTL6_DVFS REG_ADDR(0x00BC) +#define REG_FHCTL6_MON REG_ADDR(0x00C0) + +#define REG_FHCTL7_CFG REG_ADDR(0x00C4) +#define REG_FHCTL7_UPDNLMT REG_ADDR(0x00C8) +#define REG_FHCTL7_DDS REG_ADDR(0x00CC) +#define REG_FHCTL7_DVFS REG_ADDR(0x00D0) +#define REG_FHCTL7_MON REG_ADDR(0x00D4) + +#define REG_FHCTL8_CFG REG_ADDR(0x00D8) +#define REG_FHCTL8_UPDNLMT REG_ADDR(0x00DC) +#define REG_FHCTL8_DDS REG_ADDR(0x00E0) +#define REG_FHCTL8_DVFS REG_ADDR(0x00E4) +#define REG_FHCTL8_MON REG_ADDR(0x00E8) + +/**************************************************** + APMIXED CON0/CON1 Register + ***************************************************/ +/*CON0, PLL enable status */ +#define REG_ARMCA15PLL_CON0 REG_APMIX_ADDR(0x0200) +#define REG_ARMCA7PLL_CON0 REG_APMIX_ADDR(0x0210) +#define REG_MAINPLL_CON0 REG_APMIX_ADDR(0x0220) +#define REG_MEMPLL_CON0 REG_DDRPHY_ADDR(0x0604) /*< Bit[28] RG_MEMPLL_EN */ +#define REG_MMPLL_CON0 REG_APMIX_ADDR(0x0240) +#define REG_MPLL_CON0 REG_APMIX_ADDR(0x0280) +#define REG_VENCPLL_CON0 REG_APMIX_ADDR(0x0260) +#define REG_MSDCPLL_CON0 REG_APMIX_ADDR(0x0250) +#define REG_TVDPLL_CON0 REG_APMIX_ADDR(0x0270) + +/*CON1, DDS value */ +#define REG_ARMCA15PLL_CON1 REG_APMIX_ADDR(0x0204) +#define REG_ARMCA7PLL_CON1 REG_APMIX_ADDR(0x0214) +#define REG_MAINPLL_CON1 REG_APMIX_ADDR(0x0224) +#define REG_MEMPLL_CON1 REG_DDRPHY_ADDR(0x0600) /*< Bit[30:10] DDS, Bit[31] Update DDS */ +#define REG_MMPLL_CON1 REG_APMIX_ADDR(0x0244) +#define REG_MPLL_CON1 REG_APMIX_ADDR(0x0284) +#define REG_VENCPLL_CON1 REG_APMIX_ADDR(0x0264) +#define REG_MSDCPLL_CON1 REG_APMIX_ADDR(0x0254) +#define REG_TVDPLL_CON1 REG_APMIX_ADDR(0x0274) +/****************************************************/ + +static inline unsigned int uffs(unsigned int x) +{ + unsigned int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + +#define fh_read8(reg) readb(reg) +#define fh_read16(reg) readw(reg) +#define fh_read32(reg) readl((void __iomem *)reg) +#define fh_write8(reg, val) mt_reg_sync_writeb((val), (reg)) +#define fh_write16(reg, val) mt_reg_sync_writew((val), (reg)) +#define fh_write32(reg, val) mt_reg_sync_writel((val), (reg)) + +/*#define fh_set_bits(reg,bs) ((*(volatile u32*)(reg)) |= (u32)(bs))*/ +/*#define fh_clr_bits(reg,bs) ((*(volatile u32*)(reg)) &= ~((u32)(bs)))*/ + +#define fh_set_field(reg, field, val) \ + do { \ + volatile unsigned int tv = fh_read32(reg); \ + tv &= ~(field); \ + tv |= ((val) << (uffs((unsigned int)field) - 1)); \ + fh_write32(reg, tv); \ + } while (0) + +#define fh_get_field(reg, field, val) \ + do { \ + volatile unsigned int tv = fh_read32(reg); \ + val = ((tv & (field)) >> (uffs((unsigned int)field) - 1)); \ + } while (0) + +#endif /* #ifndef __MT_FHREG_H__ */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_freqhopping.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_freqhopping.h new file mode 100644 index 0000000000000000000000000000000000000000..00c11aa15d83bb6460bf0a95d9bbfc8676ac55b5 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_freqhopping.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_FREQHOPPING_H__ +#define __MT_FREQHOPPING_H__ + +/* +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt +#include +*/ + +#define PLATFORM_DEP_DEBUG_PROC_READ +#undef DISABLE_FREQ_HOPPING /* Disable all FHCTL function for K2 Bringup */ + +#define FHTAG "[FH]" +#define VERBOSE_DEBUG 0 +#define DEBUG_MSG_ENABLE 0 + +#if VERBOSE_DEBUG + #define FH_MSG(fmt, args...) \ + printk(FHTAG""fmt" <- %s(): L<%d> PID<%s><%d>\n", \ + ##args, __func__, __LINE__, current->comm, current->pid) + + #define FH_MSG_DEBUG FH_MSG +#else + #if 1 /* log level is 6 pr_debug */ + #define FH_MSG(fmt, args...) \ + pr_debug(fmt, ##args) + #else /* log level is 4 (printk) */ + #define FH_MSG(fmt, args...) \ + printk(FHTAG""fmt"\n", \ + ##args) + #endif + + #define FH_MSG_DEBUG(fmt, args...)\ + do { \ + if (DEBUG_MSG_ENABLE) \ + pr_debug(FHTAG""fmt"\n", ##args); \ + } while (0) +#endif + +enum FH_FH_STATUS { + FH_FH_DISABLE = 0, + FH_FH_ENABLE_SSC, + FH_FH_ENABLE_DFH, + FH_FH_ENABLE_DVFS, +}; + +enum FH_PLL_STATUS { + FH_PLL_DISABLE = 0, + FH_PLL_ENABLE = 1 +}; + +/* +TODO: FREQ_MODIFIED should not be here +FH_PLL_STATUS_FREQ_MODIFIED = 3 +*/ +enum FH_CMD { + FH_CMD_ENABLE = 1, + FH_CMD_DISABLE, + FH_CMD_ENABLE_USR_DEFINED, + FH_CMD_DISABLE_USR_DEFINED, + FH_CMD_INTERNAL_MAX_CMD +}; + +/* Jade */ +enum FH_PLL_ID { + FH_MIN_PLLID = 0, + FH_ARMCA15_PLLID = FH_MIN_PLLID, + FH_ARMCA7_PLLID = 1, + FH_MAIN_PLLID = 2, + FH_MEM_PLLID = 3, + FH_MM_PLLID = 4, + FH_M_PLLID = 5, + FH_VENC_PLLID = 6, + FH_MSDC_PLLID = 7, + FH_TVD_PLLID = 8, + FH_MAX_PLLID = FH_TVD_PLLID, + FH_PLL_NUM +}; + +/* +keep track the status of each PLL +TODO: do we need another "uint mode" for Dynamic FH +*/ +typedef struct { + unsigned int fh_status; + unsigned int pll_status; + unsigned int setting_id; + unsigned int curr_freq; + unsigned int user_defined; +} fh_pll_t; + + +/* Record the owner of enable freq hopping <==TBD */ +struct freqhopping_pll { + union { + int mt_pll[FH_PLL_NUM]; + struct { /* TODO: access this struct with mt_pll instead of .mt_arm_fhpll etc. */ + int mt_arm_fhpll; + int mt_main_fhpll; + int mt_mem_fhpll; + int mt_msdc_fhpll; + int mt_mm_fhpll; + int mt_venc_fhpll; + }; + }; +}; + +struct freqhopping_ssc { + unsigned int freq; + unsigned int dt; + unsigned int df; + unsigned int upbnd; + unsigned int lowbnd; + unsigned int dds; +}; + +struct freqhopping_ioctl { + unsigned int pll_id; + struct freqhopping_ssc ssc_setting; /* used only when user-define */ + int result; +}; + +int freqhopping_config(unsigned int pll_id, unsigned long vco_freq, unsigned int enable); +void mt_freqhopping_init(void); +void mt_freqhopping_pll_init(void); +int mt_h2l_mempll(void); +int mt_l2h_mempll(void); +int mt_h2l_dvfs_mempll(void); +int mt_l2h_dvfs_mempll(void); +int mt_is_support_DFS_mode(void); +void mt_fh_popod_save(void); +void mt_fh_popod_restore(void); +int mt_fh_dram_overclock(int clk); +int mt_fh_get_dramc(void); +int mt_freqhopping_devctl(unsigned int cmd, void *args); + + +/* for PLL 695.5 MHz */ +#define MMPLL_TARGET1_VCO 2782000 +#define MMPLL_TARGET1_DDS 0x001AC000 +/* for PLL 598 MHz */ +#define MMPLL_TARGET2_VCO 2392000 +#define MMPLL_TARGET2_DDS 0x00170000 +/* for PLL 494 MHz */ +#define MMPLL_TARGET3_VCO 1976000 +#define MMPLL_TARGET3_DDS 0x00130000 +/* for PLL 396.5 MHz */ +#define MMPLL_TARGET4_VCO 1586000 +#define MMPLL_TARGET4_DDS 0x000F4000 +/* for PLL 299 MHz */ +#define MMPLL_TARGET5_VCO 1196000 +#define MMPLL_TARGET5_DDS 0x000B8000 +/* for 253.5 PLL Hz */ +#define MMPLL_TARGET6_VCO 1014000 +#define MMPLL_TARGET6_DDS 0x0009C000 +int mt_dfs_mmpll(unsigned int target_freq); +/* + pll = {FH_ARMCA7_PLLID, FH_ARMCA15_PLLID} +*/ +int mt_dfs_armpll(unsigned int pll, unsigned int dds); +int mt_pause_armpll(unsigned int pll, unsigned int pause); +int mt_dfs_vencpll(unsigned int target_dds); + +#endif/* !__MT_FREQHOPPING_H__ */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_gpt.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_gpt.h new file mode 100644 index 0000000000000000000000000000000000000000..8e79ecb971d15f1cc40aa34f27a42f9ffb11e373 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_gpt.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_GPT_H_ +#define _MT_GPT_H_ + +#include + +#define GPT1 0x0 +#define GPT2 0x1 +#define GPT3 0x2 +#define GPT4 0x3 +#define GPT5 0x4 +#define GPT6 0x5 +#define NR_GPTS 0x6 + + +#define GPT_ONE_SHOT 0x0 +#define GPT_REPEAT 0x1 +#define GPT_KEEP_GO 0x2 +#define GPT_FREE_RUN 0x3 + + +#define GPT_CLK_DIV_1 0x0000 +#define GPT_CLK_DIV_2 0x0001 +#define GPT_CLK_DIV_3 0x0002 +#define GPT_CLK_DIV_4 0x0003 +#define GPT_CLK_DIV_5 0x0004 +#define GPT_CLK_DIV_6 0x0005 +#define GPT_CLK_DIV_7 0x0006 +#define GPT_CLK_DIV_8 0x0007 +#define GPT_CLK_DIV_9 0x0008 +#define GPT_CLK_DIV_10 0x0009 +#define GPT_CLK_DIV_11 0x000a +#define GPT_CLK_DIV_12 0x000b +#define GPT_CLK_DIV_13 0x000c +#define GPT_CLK_DIV_16 0x000d +#define GPT_CLK_DIV_32 0x000e +#define GPT_CLK_DIV_64 0x000f + + +#define GPT_CLK_SRC_SYS 0x0 +#define GPT_CLK_SRC_RTC 0x1 + + +#define GPT_NOAUTOEN 0x0001 +#define GPT_NOIRQEN 0x0002 + + +extern int request_gpt(unsigned int id, unsigned int mode, unsigned int clksrc, + unsigned int clkdiv, unsigned int cmp, + void (*func)(unsigned long), unsigned int flags); +extern int free_gpt(unsigned int id); + +extern int start_gpt(unsigned int id); +extern int stop_gpt(unsigned int id); +extern int restart_gpt(unsigned int id); + +extern int gpt_is_counting(unsigned int id); + +extern int gpt_set_cmp(unsigned int id, unsigned int val); +extern int gpt_get_cmp(unsigned int id, unsigned int *ptr); +extern int gpt_get_cnt(unsigned int id, unsigned int *ptr); + +extern int gpt_check_irq(unsigned int id); +extern int gpt_check_and_ack_irq(unsigned int id); +extern int gpt_set_clk(unsigned int id, unsigned int clksrc, unsigned int clkdiv); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_mem_bw.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_mem_bw.h new file mode 100644 index 0000000000000000000000000000000000000000..939f44e252c9cc11c29fd0f8ef13e5a58fbfa3c2 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_mem_bw.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_MEM_BW_H__ +#define __MT_MEM_BW_H__ + +#define DISABLE_FLIPPER_FUNC 0 + +typedef unsigned long long (*getmembw_func)(void); +extern void mt_getmembw_registerCB(getmembw_func pCB); + +unsigned long long get_mem_bw(void); + +#endif /* !__MT_MEM_BW_H__ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pbm.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pbm.h new file mode 100644 index 0000000000000000000000000000000000000000..894508adeeb714a64322f2433df7bedcbe09cd08 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pbm.h @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_PBM_ +#define _MT_PBM_ + +/* #include */ +#include + +#ifdef DISABLE_DLPT_FEATURE +#define DISABLE_PBM_FEATURE +#endif + +#define MD1_MAX_PW 3000 /* mW */ +#define MD3_MAX_PW 2500 /* mW */ +#define POWER_FLASH 3500 /* mW */ +#define GUARDING_PATTERN 0 + +struct pbm { + u8 feature_en; + u8 pbm_drv_done; + u32 hpf_en; +}; + +struct hpf { + bool switch_md1; + bool switch_md3; + bool switch_gpu; + bool switch_flash; + + bool md1_ccci_ready; + bool md3_ccci_ready; + + int cpu_volt; + int gpu_volt; + int cpu_num; + + unsigned long loading_leakage; + unsigned long loading_dlpt; + unsigned long loading_md1; + unsigned long loading_md3; + unsigned long loading_cpu; + unsigned long loading_gpu; + unsigned long loading_flash; +}; + +struct mrp { + bool switch_md; + bool switch_gpu; + bool switch_flash; + + int cpu_volt; + int gpu_volt; + int cpu_num; + + unsigned long loading_dlpt; + unsigned long loading_cpu; + unsigned long loading_gpu; +}; + +enum pbm_kicker { + KR_DLPT, /* 0 */ + KR_MD1, /* 1 */ + KR_MD3, /* 2 */ + KR_CPU, /* 3 */ + KR_GPU, /* 4 */ + KR_FLASH /* 5 */ +}; + +#define MD_POWER_METER_ENABLE 1 +/* #define TEST_MD_POWER */ + +#define SECTION_LEN 0xFFFFFFFF /* total 4 byte, 6 section = 11 11111 11111 11111 11111 11111 11111 */ +#define SECTION_VALUE 0x1F /* each section is 0x1F = bit(11111) */ + +enum section_level_tbl { + BIT_SECTION_1 = 0, + BIT_SECTION_2 = 5, + BIT_SECTION_3 = 10, + BIT_SECTION_4 = 15, + BIT_SECTION_5 = 20, + BIT_SECTION_6 = 25, + SECTION_NUM = 6 +}; + +enum md1_scenario { + CAT6_CA_DATALINK, /* 0 */ + NON_CA_DATALINK, /* 1 */ + PAGING, /* 2 */ + POSITION, /* 3 */ + CELL_SEARCH, /* 4 */ + CELL_MANAGEMENT, /* 5 */ + TALKING_2G, /* 6 */ + DATALINK_2G, /* 7 */ + TALKING_3G, /* 8 */ + DATALINK_3G, /* 9 */ + SCENARIO_NUM /* 10 */ +}; + +enum share_mem_mapping { /* each of 4 byte */ + DBM_2G_TABLE = 0, + DBM_3G_TABLE = 1, + DBM_4G_TABLE = 2, + DBM_TDD_TABLE = 3, + DBM_C2K_TABLE = 4, + SECTION_LEVLE_2G = 5, + SECTION_LEVLE_3G = 6, + SECTION_LEVLE_4G = 7, + SECTION_LEVLE_TDD = 8, + SECTION_LEVLE_C2K = 9, + SHARE_MEM_BLOCK_NUM +}; + +/* + * MD1/MD3 Section level (can't more than SECTION_VALUE) + */ +enum md1_section_level_tbl_2g { + VAL_MD1_2G_SECTION_1 = 31, + VAL_MD1_2G_SECTION_2 = 29, + VAL_MD1_2G_SECTION_3 = 27, + VAL_MD1_2G_SECTION_4 = 23, + VAL_MD1_2G_SECTION_5 = 17, + VAL_MD1_2G_SECTION_6 = 0 +}; + +enum md1_section_level_tbl_3g { + VAL_MD1_3G_SECTION_1 = 21, + VAL_MD1_3G_SECTION_2 = 19, + VAL_MD1_3G_SECTION_3 = 18, + VAL_MD1_3G_SECTION_4 = 16, + VAL_MD1_3G_SECTION_5 = 13, + VAL_MD1_3G_SECTION_6 = 0 +}; + +enum md1_section_level_tbl_4g { + VAL_MD1_4G_SECTION_1 = 21, + VAL_MD1_4G_SECTION_2 = 19, + VAL_MD1_4G_SECTION_3 = 18, + VAL_MD1_4G_SECTION_4 = 16, + VAL_MD1_4G_SECTION_5 = 13, + VAL_MD1_4G_SECTION_6 = 0 +}; + +enum md1_section_level_tbl_tdd { + VAL_MD1_TDD_SECTION_1 = 21, + VAL_MD1_TDD_SECTION_2 = 19, + VAL_MD1_TDD_SECTION_3 = 18, + VAL_MD1_TDD_SECTION_4 = 16, + VAL_MD1_TDD_SECTION_5 = 13, + VAL_MD1_TDD_SECTION_6 = 0 +}; + +enum md3_section_level_tbl { + VAL_MD3_SECTION_1 = 24, + VAL_MD3_SECTION_2 = 23, + VAL_MD3_SECTION_3 = 21, + VAL_MD3_SECTION_4 = 19, + VAL_MD3_SECTION_5 = 14, + VAL_MD3_SECTION_6 = 0 +}; + +/* + * MD1/MD3 Scenario power + */ +enum md1_scenario_pwr_tbl { + PW_CAT6_CA_DATALINK = 1000, + PW_NON_CA_DATALINK = 700, + PW_PAGING = 30, + PW_POSITION = 1000, /* same as PW_CAT6_CA_DATALINK */ + PW_CELL_SEARCH = 0, /* no use */ + PW_CELL_MANAGEMENT = 0, /* no use */ + PW_TALKING_2G = 200, + PW_DATALINK_2G = 200, + PW_TALKING_3G = 350, + PW_DATALINK_3G = 470 +}; + +enum md3_scenario_pwr_tbl { + PW_MD3 = 500 +}; + +/* + * MD1/MD3 PA power + */ +enum md1_pa_pwr_tbl_2g { + PW_MD1_PA_2G_SECTION_1 = 688, + PW_MD1_PA_2G_SECTION_2 = 440, + PW_MD1_PA_2G_SECTION_3 = 353, + PW_MD1_PA_2G_SECTION_4 = 284, + PW_MD1_PA_2G_SECTION_5 = 184, + PW_MD1_PA_2G_SECTION_6 = 99 +}; + +enum md1_pa_pwr_tbl_3g { + PW_MD1_PA_3G_SECTION_1 = 1965, + PW_MD1_PA_3G_SECTION_2 = 1557, + PW_MD1_PA_3G_SECTION_3 = 1022, + PW_MD1_PA_3G_SECTION_4 = 914, + PW_MD1_PA_3G_SECTION_5 = 553, + PW_MD1_PA_3G_SECTION_6 = 294 +}; + +enum md1_pa_pwr_tbl_4g { + PW_MD1_PA_4G_SECTION_1 = 1965, + PW_MD1_PA_4G_SECTION_2 = 1557, + PW_MD1_PA_4G_SECTION_3 = 1022, + PW_MD1_PA_4G_SECTION_4 = 914, + PW_MD1_PA_4G_SECTION_5 = 553, + PW_MD1_PA_4G_SECTION_6 = 294 +}; + +enum md3_pa_pwr_tbl { + PW_MD3_PA_SECTION_1 = 1956, + PW_MD3_PA_SECTION_2 = 1759, + PW_MD3_PA_SECTION_3 = 1257, + PW_MD3_PA_SECTION_4 = 907, + PW_MD3_PA_SECTION_5 = 554, + PW_MD3_PA_SECTION_6 = 226 +}; + +/* + * MD1/MD3 RF power + */ +enum md1_rf_power { + PW_MD1_RF_SECTION_1 = 512, + PW_MD1_RF_SECTION_2 = 256 +}; + +enum md3_rf_power { + PW_MD3_RF_SECTION_1 = 280, + PW_MD3_RF_SECTION_2 = 140 +}; + +extern void kicker_pbm_by_dlpt(unsigned int i_max); +extern void kicker_pbm_by_md(enum pbm_kicker kicker, bool status); +extern void kicker_pbm_by_cpu(unsigned int loading, int core, int voltage); +extern void kicker_pbm_by_gpu(bool status, unsigned int loading, int voltage); +extern void kicker_pbm_by_flash(bool status); + +extern void init_md_section_level(enum pbm_kicker); + +#ifndef DISABLE_PBM_FEATURE +extern int g_dlpt_stop; +#endif + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pe.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pe.h new file mode 100644 index 0000000000000000000000000000000000000000..69110737fb6af17264059a4a1a8163c6f3b65e39 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pe.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _CUST_PE_H_ +#define _CUST_PE_H_ + +/* Pump Express support (fast charging) */ +#define TA_START_BATTERY_SOC 1 +#define TA_STOP_BATTERY_SOC 85 +#define TA_AC_12V_INPUT_CURRENT CHARGE_CURRENT_3200_00_MA +#define TA_AC_9V_INPUT_CURRENT CHARGE_CURRENT_3200_00_MA +#define TA_AC_7V_INPUT_CURRENT CHARGE_CURRENT_3200_00_MA +#define TA_AC_CHARGING_CURRENT CHARGE_CURRENT_3200_00_MA +#define TA_9V_SUPPORT +#define TA_12V_SUPPORT + +/* Ichg threshold for leaving PE+/PE+20 */ +#define PEP20_ICHG_LEAVE_THRESHOLD 1000 /* mA */ +#define PEP_ICHG_LEAVE_THRESHOLD 1000 /* mA */ + +/* For PE+20, VBUS V.S. VBAT table, according to BQ25896 */ +#define VBAT3400_VBUS CHR_VOLT_08_000000_V +#define VBAT3500_VBUS CHR_VOLT_08_500000_V +#define VBAT3600_VBUS CHR_VOLT_08_500000_V +#define VBAT3700_VBUS CHR_VOLT_09_000000_V +#define VBAT3800_VBUS CHR_VOLT_09_000000_V +#define VBAT3900_VBUS CHR_VOLT_09_000000_V +#define VBAT4000_VBUS CHR_VOLT_09_500000_V +#define VBAT4100_VBUS CHR_VOLT_09_500000_V +#define VBAT4200_VBUS CHR_VOLT_10_000000_V +#define VBAT4300_VBUS CHR_VOLT_10_000000_V + +#endif /* _CUST_PE_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pmic.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pmic.h new file mode 100644 index 0000000000000000000000000000000000000000..7bbd85dba73d5bddedc154c3ae2583d737429cb4 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pmic.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _CUST_PMIC_H_ +#define _CUST_PMIC_H_ + +/*#define PMIC_VDVFS_CUST_ENABLE*/ + +#define LOW_POWER_LIMIT_LEVEL_1 15 + +/* +//Define for disable low battery protect feature, default no define for enable low battery protect. +//#define DISABLE_LOW_BATTERY_PROTECT + +//Define for disable battery OC protect +//#define DISABLE_BATTERY_OC_PROTECT + +//Define for disable battery 15% protect +//#define DISABLE_BATTERY_PERCENT_PROTECT +*/ +/*Define for DLPT*/ +/*#define DISABLE_DLPT_FEATURE*/ +#define POWER_UVLO_VOLT_LEVEL 2600 +#define IMAX_MAX_VALUE 5500 + +#define POWER_INT0_VOLT 3400 +#define POWER_INT1_VOLT 3250 +#define POWER_INT2_VOLT 3100 + +#define POWER_BAT_OC_CURRENT_H 4670 +#define POWER_BAT_OC_CURRENT_L 5500 +#define POWER_BAT_OC_CURRENT_H_RE 4670 +#define POWER_BAT_OC_CURRENT_L_RE 5500 + +#define DLPT_POWER_OFF_EN +#define POWEROFF_BAT_CURRENT 3000 +#define DLPT_POWER_OFF_THD 100 + +#define BATTERY_MODULE_INIT + +/* ADC Channel Number */ +typedef enum { + AUX_BATSNS_AP = 0x000, + AUX_ISENSE_AP, + AUX_VCDT_AP, + AUX_BATON_AP, + AUX_TSENSE_AP, + AUX_TSENSE_MD = 0x005, + AUX_VACCDET_AP = 0x007, + AUX_VISMPS_AP = 0x00B, + AUX_ICLASSAB_AP = 0x016, + AUX_HP_AP = 0x017, + AUX_CH10_AP = 0x018, + AUX_VBIF_AP = 0x019, + AUX_CH0_6311 = 0x020, + AUX_CH1_6311 = 0x021, + AUX_ADCVIN0_MD = 0x10F, + AUX_ADCVIN0_GPS = 0x20C, + AUX_CH12 = 0x1011, + AUX_CH13 = 0x2011, + AUX_CH14 = 0x3011, + AUX_CH15 = 0x4011, +} upmu_adc_chl_list_enum; + +#endif /* _CUST_PMIC_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pmic_wrap.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pmic_wrap.h new file mode 100644 index 0000000000000000000000000000000000000000..dd6fe4902809cd0dfc48e77a46f84dc50eb49f9d --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pmic_wrap.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef __MT_PMIC_WRAP_H__ +#define __MT_PMIC_WRAP_H__ +/* #include */ +/* #include */ +#include +#include +struct mt_pmic_wrap_driver { + + struct device_driver driver; + s32 (*wacs2_hal)(u32 write, u32 adr, u32 wdata, u32 *rdata); + s32 (*show_hal)(char *buf); + s32 (*store_hal)(const char *buf, size_t count); + s32 (*suspend)(void); + void (*resume)(void); +}; +typedef enum { + PWRAP_READ = 0, + PWRAP_WRITE = 1, +} PWRAP_OPS; + +/* ------external API for pmic_wrap user-------------------------------------------------- */ +s32 pwrap_read(u32 adr, u32 *rdata); +s32 pwrap_write(u32 adr, u32 wdata); +s32 pwrap_wacs2(u32 write, u32 adr, u32 wdata, u32 *rdata); +/*_____________ROME only_____________________________________________*/ +/********************************************************************/ +/* return value : EINT_STA: [0]: CPU IRQ status in MT6331 */ +/* [1]: MD32 IRQ status in MT6331 */ +/* [2]: CPU IRQ status in MT6332 */ +/* [3]: RESERVED */ +/********************************************************************/ +u32 pmic_wrap_eint_status(void); +/********************************************************************/ +/* set value(W1C) : EINT_CLR: [0]: CPU IRQ status in MT6331 */ +/* [1]: MD32 IRQ status in MT6331 */ +/* [2]: CPU IRQ status in MT6332 */ +/* [3]: RESERVED */ +/* para: offset is shift of clear bit which needs to clear */ +/********************************************************************/ +void pmic_wrap_eint_clr(int offset); +/*--------------------------------------------------------------------*/ +u32 mt_pmic_wrap_eint_status(void); +void mt_pmic_wrap_eint_clr(int offset); +s32 pwrap_init(void); +struct mt_pmic_wrap_driver *get_mt_pmic_wrap_drv(void); +void pwrap_dump_all_register(void); + +#endif /* __MT_PMIC_WRAP_H__ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_ppm_api.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_ppm_api.h new file mode 100644 index 0000000000000000000000000000000000000000..da4499c83cbac9cd9f97a78823177b3cba39b9cc --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_ppm_api.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#ifndef __MT_PPM_API_H__ +#define __MT_PPM_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +/*==============================================================*/ +/* Enum */ +/*==============================================================*/ +enum ppm_client { + PPM_CLIENT_DVFS = 0, + PPM_CLIENT_HOTPLUG, + + NR_PPM_CLIENTS, +}; + +enum dvfs_table_type { + DVFS_TABLE_TYPE_FY = 0, + DVFS_TABLE_TYPE_SB, + + NR_DVFS_TABLE_TYPE, +}; + +enum ppm_sysboost_user { + BOOST_BY_WIFI = 0, + BOOST_BY_PERFSERV, + BOOST_BY_USB, + BOOST_BY_UT, + + NR_PPM_SYSBOOST_USER, +}; + +/*==============================================================*/ +/* Definition */ +/*==============================================================*/ +typedef void (*met_set_ppm_state_funcMET)(unsigned int state); + +/*==============================================================*/ +/* Data Structures */ +/*==============================================================*/ +struct ppm_client_req { + unsigned int cluster_num; + unsigned int root_cluster; + bool is_ptp_policy_activate; + struct ppm_client_limit { + unsigned int cluster_id; + unsigned int cpu_id; + + int min_cpufreq_idx; + int max_cpufreq_idx; + unsigned int min_cpu_core; + unsigned int max_cpu_core; + + bool has_advise_freq; + bool has_advise_core; + int advise_cpufreq_idx; + int advise_cpu_core; + } *cpu_limit; +}; + +struct ppm_client_data { + const char *name; + enum ppm_client client; + + /* callback */ + void (*limit_cb)(struct ppm_client_req req); +}; + +struct ppm_cluster_status { + int core_num; + int freq_idx; /* -1 if core_num = 0 */ + int volt; +}; + +/*==============================================================*/ +/* APIs */ +/*==============================================================*/ +extern void mt_ppm_set_dvfs_table(unsigned int cpu, struct cpufreq_frequency_table *tbl, + unsigned int num, enum dvfs_table_type type); +extern void mt_ppm_register_client(enum ppm_client client, void (*limit)(struct ppm_client_req req)); +extern void mt_ppm_set_5A_limit_throttle(bool enable); +extern void mt_ppm_limit_freq_when_ke(void); + +/* SYS boost policy */ +extern void mt_ppm_sysboost_core(enum ppm_sysboost_user user, unsigned int core_num); +extern void mt_ppm_sysboost_freq(enum ppm_sysboost_user user, unsigned int freq); +extern void mt_ppm_sysboost_set_core_limit(enum ppm_sysboost_user user, unsigned int cluster, + int min_core, int max_core); +extern void mt_ppm_sysboost_set_freq_limit(enum ppm_sysboost_user user, unsigned int cluster, + int min_freq, int max_freq); + +/* DLPT policy */ +extern void mt_ppm_dlpt_set_limit_by_pbm(unsigned int limited_power); +extern void mt_ppm_dlpt_kick_PBM(struct ppm_cluster_status *cluster_status, unsigned int cluster_num); + +/* Thermal policy */ +extern void mt_ppm_cpu_thermal_protect(unsigned int limited_power); +extern unsigned int mt_ppm_thermal_get_min_power(void); +extern unsigned int mt_ppm_thermal_get_max_power(void); +extern unsigned int mt_ppm_thermal_get_cur_power(void); + +/* PTPOD policy */ +extern void mt_ppm_ptpod_policy_activate(void); +extern void mt_ppm_ptpod_policy_deactivate(void); + +/* HICA policy */ +extern void mt_ppm_hica_update_algo_data(unsigned int cur_loads, + unsigned int cur_nr_heavy_task, unsigned int cur_tlp); +extern int mt_ppm_main(void); + +/* MET */ +void mt_set_ppm_state_registerCB(met_set_ppm_state_funcMET pCB); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pwm_hal.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pwm_hal.h new file mode 100644 index 0000000000000000000000000000000000000000..3cc05f51c26bd3c1f0ee305071c21711510ec3a5 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pwm_hal.h @@ -0,0 +1,176 @@ +/******************************************************************************* +* mt6595_pwm.h PWM Drvier +* +* Copyright (c) 2010, Media Teck.inc +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public Licence, +* version 2, as publish by the Free Software Foundation. +* +* This program is distributed and in hope it will be useful, but WITHOUT +* ANY WARRNTY; without even the implied warranty of MERCHANTABITLITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +*/ + +#ifndef __MT_PWM_HAL_H__ +#define __MT_PWM_HAL_H__ + +#include + +#include +#if defined(CONFIG_MTK_CLKMGR) +#include +#endif + +/******************* Register Manipulations*****************/ +#define INREG32(reg) __raw_readl((void *)reg) +#define OUTREG32(reg, val) mt_reg_sync_writel(val, reg) +#define OUTREG32_DMA(reg, val) ((*(volatile long*)(reg)) |= (long)(val)) +#define SETREG32(reg, val) OUTREG32(reg, INREG32(reg)|(val)) +#define CLRREG32(reg, val) OUTREG32(reg, INREG32(reg)&~(val)) +#define MASKREG32(x, y, z) OUTREG32(x, (INREG32(x)&~(y))|(z)) + + +#define PWM_NEW_MODE_DUTY_TOTAL_BITS 64 + +#ifdef CONFIG_OF +extern void __iomem *pwm_base; +#endif + +/********************************** +* Global enum data +**********************************/ +enum PWN_NO { + PWM_MIN, + PWM1 = PWM_MIN, + PWM2, + PWM3, + PWM4, + PWM_NUM, + PWM_MAX = PWM_NUM +}; + + +enum TEST_SEL_BIT { + TEST_SEL_FALSE, + TEST_SEL_TRUE +}; + +enum PWM_CON_MODE_BIT { + PERIOD, + RAND +}; + +enum PWM_CON_SRCSEL_BIT { + PWM_FIFO, + MEMORY +}; + +enum PWM_CON_IDLE_BIT { + IDLE_FALSE, + IDLE_TRUE, + IDLE_MAX +}; + +enum PWM_CON_GUARD_BIT { + GUARD_FALSE, + GUARD_TRUE, + GUARD_MAX +}; + +enum OLD_MODE_BIT { + OLDMODE_DISABLE, + OLDMODE_ENABLE +}; + +enum PWM_BUF_VALID_BIT { + BUF0_VALID, + BUF0_EN_VALID, + BUF1_VALID, + BUF1_EN_VALID, + BUF_EN_MAX +}; + +enum CLOCK_SRC { + CLK_BLOCK, + CLK_BLOCK_BY_1625_OR_32K +}; + +enum PWM_CLK_DIV { + CLK_DIV_MIN, + CLK_DIV1 = CLK_DIV_MIN, + CLK_DIV2, + CLK_DIV4, + CLK_DIV8, + CLK_DIV16, + CLK_DIV32, + CLK_DIV64, + CLK_DIV128, + CLK_DIV_MAX +}; + +enum PWM_INT_ENABLE_BITS { + PWM1_INT_FINISH_EN, + PWM1_INT_UNDERFLOW_EN, + PWM2_INT_FINISH_EN, + PWM2_INT_UNDERFLOW_EN, + PWM3_INT_FINISH_EN, + PWM3_INT_UNDERFLOW_EN, + PWM4_INT_FINISH_EN, + PWM4_INT_UNDERFLOW_EN, + PWM_INT_ENABLE_BITS_MAX, +}; + +enum PWM_INT_STATUS_BITS { + PWM1_INT_FINISH_ST, + PWM1_INT_UNDERFLOW_ST, + PWM2_INT_FINISH_ST, + PWM2_INT_UNDERFLOW_ST, + PWM3_INT_FINISH_ST, + PWM3_INT_UNDERFLOW_ST, + PWM4_INT_FINISH_ST, + PWM4_INT_UNDERFLOW_ST, + PWM_INT_STATUS_BITS_MAX, +}; + +enum PWM_INT_ACK_BITS { + PWM1_INT_FINISH_ACK, + PWM1_INT_UNDERFLOW_ACK, + PWM2_INT_FINISH_ACK, + PWM2_INT_UNDERFLOW_ACK, + PWM3_INT_FINISH_ACK, + PWM3_INT_UNDERFLOW_ACK, + PWM4_INT_FINISH_ACK, + PWM4_INT_UNDERFLOW_ACK, + PWM_INT_ACK_BITS_MAX, +}; + +enum PWM_CLOCK_SRC_ENUM { + PWM_CLK_SRC_MIN, + PWM_CLK_OLD_MODE_BLOCK = PWM_CLK_SRC_MIN, + PWM_CLK_OLD_MODE_32K, + PWM_CLK_NEW_MODE_BLOCK, + PWM_CLK_NEW_MODE_BLOCK_DIV_BY_1625, + PWM_CLK_SRC_NUM, + PWM_CLK_SRC_INVALID, +}; + +enum PWM_MODE_ENUM { + PWM_MODE_MIN, + PWM_MODE_OLD = PWM_MODE_MIN, + PWM_MODE_FIFO, + PWM_MODE_MEMORY, + PWM_MODE_RANDOM, + PWM_MODE_DELAY, + PWM_MODE_INVALID, +}; + +void mt_set_pwm_3dlcm_enable_hal(u8 enable); +void mt_set_pwm_3dlcm_inv_hal(u32 pwm_no, u8 inv); +void mt_set_pwm_3dlcm_base_hal(u32 pwm_no); + +void mt_pwm_26M_clk_enable_hal(u32 enable); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pwm_prv.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pwm_prv.h new file mode 100644 index 0000000000000000000000000000000000000000..f1c4265b90a0515e46171e636881c69f8f223308 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_pwm_prv.h @@ -0,0 +1,74 @@ +/******************************************************************************* +* mt6595_pwm.h PWM Drvier +* +* Copyright (c) 2010, Media Teck.inc +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public Licence, +* version 2, as publish by the Free Software Foundation. +* +* This program is distributed and in hope it will be useful, but WITHOUT +* ANY WARRNTY; without even the implied warranty of MERCHANTABITLITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +*/ + +#ifndef __MT_PWM_PRV_H__ +#define __MT_PWM_PRV_H__ + + +#ifdef CONFIG_OF +extern void __iomem *pwm_base; +/* unsigned int pwm_irqnr; */ + +#undef PWM_BASE +#define PWM_BASE pwm_base + +#endif + +/*********************************** +* PWM register address * +************************************/ +#define PWM_ENABLE (PWM_BASE+0x0000) + +#define PWM_3DLCM (PWM_BASE+0x1D0) +#define PWM_3DLCM_ENABLE_OFFSET 0 + +#define PWM_INT_ENABLE (PWM_BASE+0x0200) +#define PWM_INT_STATUS (PWM_BASE+0x0204) +#define PWM_INT_ACK (PWM_BASE+0x0208) +#define PWM_EN_STATUS (PWM_BASE+0x020c) + +#define PWM_CK_26M_SEL (PWM_BASE+0x0210) +#define PWM_CK_26M_SEL_OFFSET 0 + +/*PWM1~PWM3 control registers*/ +#define PWM_CON_CLKDIV_MASK 0x00000007 +#define PWM_CON_CLKDIV_OFFSET 0 +#define PWM_CON_CLKSEL_MASK 0x00000008 +#define PWM_CON_CLKSEL_OFFSET 3 +#define PWM_CON_CLKSEL_OLD_MASK 0x00000010 +#define PWM_CON_CLKSEL_OLD_OFFSET 4 + +#define PWM_CON_SRCSEL_MASK 0x00000020 +#define PWM_CON_SRCSEL_OFFSET 5 + +#define PWM_CON_MODE_MASK 0x00000040 +#define PWM_CON_MODE_OFFSET 6 + +#define PWM_CON_IDLE_VALUE_MASK 0x00000080 +#define PWM_CON_IDLE_VALUE_OFFSET 7 + +#define PWM_CON_GUARD_VALUE_MASK 0x00000100 +#define PWM_CON_GUARD_VALUE_OFFSET 8 + +#define PWM_CON_STOP_BITS_MASK 0x00007E00 +#define PWM_CON_STOP_BITS_OFFSET 9 +#define PWM_CON_OLD_MODE_MASK 0x00008000 +#define PWM_CON_OLD_MODE_OFFSET 15 + +#define BLOCK_CLK (66UL*1000*1000) +#define PWM_26M_CLK (26UL*1000*1000) + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_rtc_hw.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_rtc_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..38f2ff2f6d935d0ae19d429fbebf8eca01b627e1 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_rtc_hw.h @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_RTC_HW_H__ +#define __MT_RTC_HW_H__ + +/* RTC registers */ +#define MT_PMIC_REG_BASE (0x0000) +#define RTC_BBPU (RTC_BASE + 0x0000) +#define RTC_BBPU_PWREN (1U << 0) /* BBPU = 1 when alarm occurs */ +#define RTC_BBPU_BBPU (1U << 2) /* 1: power on, 0: power down */ +#define RTC_BBPU_AUTO (1U << 3) /* BBPU = 0 when xreset_rstb goes low */ +#define RTC_BBPU_CLRPKY (1U << 4) +#define RTC_BBPU_RELOAD (1U << 5) +#define RTC_BBPU_CBUSY (1U << 6) +#define RTC_BBPU_KEY (0x43 << 8) + +#define RTC_IRQ_STA (RTC_BASE + 0x0002) +#define RTC_IRQ_STA_AL (1U << 0) +#define RTC_IRQ_STA_TC (1U << 1) +#define RTC_IRQ_STA_LP (1U << 3) + +#define RTC_IRQ_EN (RTC_BASE + 0x0004) +#define RTC_IRQ_EN_AL (1U << 0) +#define RTC_IRQ_EN_TC (1U << 1) +#define RTC_IRQ_EN_ONESHOT (1U << 2) +#define RTC_IRQ_EN_LP (1U << 3) +#define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL) + +#define RTC_CII_EN (RTC_BASE + 0x0006) +#define RTC_CII_SEC (1U << 0) +#define RTC_CII_MIN (1U << 1) +#define RTC_CII_HOU (1U << 2) +#define RTC_CII_DOM (1U << 3) +#define RTC_CII_DOW (1U << 4) +#define RTC_CII_MTH (1U << 5) +#define RTC_CII_YEA (1U << 6) +#define RTC_CII_1_2_SEC (1U << 7) +#define RTC_CII_1_4_SEC (1U << 8) +#define RTC_CII_1_8_SEC (1U << 9) + +#define RTC_AL_MASK (RTC_BASE + 0x0008) +#define RTC_AL_MASK_SEC (1U << 0) +#define RTC_AL_MASK_MIN (1U << 1) +#define RTC_AL_MASK_HOU (1U << 2) +#define RTC_AL_MASK_DOM (1U << 3) +#define RTC_AL_MASK_DOW (1U << 4) +#define RTC_AL_MASK_MTH (1U << 5) +#define RTC_AL_MASK_YEA (1U << 6) + +#define RTC_TC_SEC (RTC_BASE + 0x000a) +#define RTC_TC_SEC_MASK 0x003f + +#define RTC_TC_MIN (RTC_BASE + 0x000c) +#define RTC_TC_MIN_MASK 0x003f + +#define RTC_TC_HOU (RTC_BASE + 0x000e) +#define RTC_TC_HOU_MASK 0x001f + +#define RTC_TC_DOM (RTC_BASE + 0x0010) +#define RTC_TC_DOM_MASK 0x001f + +#define RTC_TC_DOW (RTC_BASE + 0x0012) +#define RTC_TC_DOW_MASK 0x0007 + +#define RTC_TC_MTH (RTC_BASE + 0x0014) +#define RTC_TC_MTH_MASK 0x000f + +#define RTC_TC_YEA (RTC_BASE + 0x0016) +#define RTC_TC_YEA_MASK 0x007f + +#define RTC_AL_SEC (RTC_BASE + 0x0018) +#define RTC_K_EOSC32_VTCXO_ON_SEL (1U << 15) +#define RTC_LPD_OPT_SHIFT 13 +#define RTC_LPD_OPT (1U << RTC_LPD_OPT_SHIFT) +#define RTC_BBPU_2SEC_STAT_CLEAR (1U << 11) +#define RTC_BBPU_2SEC_MODE (3U << 9) +#define RTC_BBPU_2SEC_EN (1U << 8) +#define RTC_BBPU_2SEC_CK_SEL (1U << 7) +#define RTC_BBPU_AUTO_PDN_SEL (1U << 6) +#define RTC_AL_SEC_MASK 0x003f + +#define RTC_AL_MIN (RTC_BASE + 0x001a) +#define RTC_AL_MIN_MASK 0x003f + +/* + * RTC_NEW_SPARE0: RTC_AL_HOU bit0~4 + * bit 8 ~ 14 : Fuel Gauge + * bit 15 : reserved bits + */ +#define RTC_AL_HOU (RTC_BASE + 0x001c) +#define RTC_AL_HOU_MASK 0x001f + +#define RTC_FG_SOC RTC_AL_HOU +#define RTC_FG_SOC_MASK 0x7f +#define RTC_FG_SOC_SHIFT 8 + + +/* + * RTC_NEW_SPARE1: RTC_AL_DOM bit0~4 + * bit 8 ~ 15 : reserved bits + */ +#define RTC_AL_DOM (RTC_BASE + 0x001e) +#define RTC_NEW_SPARE1 0xff00 +#define RTC_AL_DOM_MASK 0x001f + +/* + * RTC_NEW_SPARE2: RTC_AL_DOW bit0~2 + * bit 8 ~ 15 : reserved bits + */ +#define RTC_AL_DOW (RTC_BASE + 0x0020) +#define RTC_NEW_SPARE2 0xff00 +#define RTC_AL_DOW_MASK 0x0007 + +/* + * RTC_NEW_SPARE3: RTC_AL_MTH bit0~3 + * bit 8 ~ 15 : reserved bits + */ +#define RTC_AL_MTH (RTC_BASE + 0x0022) +#define RTC_NEW_SPARE3 0xff00 +#define RTC_AL_MTH_MASK 0x000f + +#define RTC_AL_YEA (RTC_BASE + 0x0024) +#define RTC_K_EOSC_RSV_7 (1U << 15) +#define RTC_K_EOSC_RSV_6 (1U << 14) +#define RTC_K_EOSC_RSV_5 (1U << 13) +#define RTC_K_EOSC_RSV_4 (1U << 12) +#define RTC_K_EOSC_RSV_3 (1U << 11) +#define RTC_K_EOSC_RSV_2 (1U << 10) +#define RTC_K_EOSC_RSV_1 (1U << 9) +#define RTC_K_EOSC_RSV_0 (1U << 8) +#define RTC_AL_YEA_MASK 0x007f + +#define RTC_OSC32CON (RTC_BASE + 0x0026) +#define RTC_OSC32CON_UNLOCK1 0x1a57 +#define RTC_OSC32CON_UNLOCK2 0x2b68 +#define RTC_REG_XOSC32_ENB (1U << 15) +#define RTC_GP_OSC32_CON (3U << 13) +#define RTC_EOSC32_CHOP_EN (1U << 12) +#define RTC_EOSC32_VCT_EN_SHIFT 11 +#define RTC_EOSC32_VCT_EN (1U << RTC_EOSC32_VCT_EN_SHIFT) +#define RTC_EOSC32_OPT (1U << 10) +/* +0: embedded clock switch back to dcxo decided by (eosc32_ck_alive & powerkey_match) +1: embedded clock switch back to dcxo decided by (powerkey_match) +*/ +#define RTC_EMBCK_SEL_OPTION (1U << 9) +#define RTC_EMBCK_SRC_SEL (1U << 8) +#define RTC_EMBCK_SEL_MODE (3U << 6) +/* 0: emb_hw 1: emb_k_eosc_32 2:dcxo_ck 3: eosc32_ck*/ +#define RTC_EMBCK_SEL_HW (0 << 6) +#define RTC_EMBCK_SEL_K_EOSC (1U << 6) +#define RTC_EMBCK_SEL_DCXO (2U << 6) +#define RTC_EMBCK_SEL_EOSC (3U << 6) +/* 0 (32k crystal exist) 1 (32k crystal doesn't exist)*/ +#define RTC_XOSC32_ENB (1U << 5) +/*Default 4'b0111, 2nd step suggest to set to 4'b0000 EOSC_CALI = charging cap calibration*/ +#define RTC_XOSCCALI_MASK 0x001f + +#define OSC32CON_ANALOG_SETTING (RTC_GP_OSC32_CON | RTC_EOSC32_VCT_EN | RTC_EOSC32_CHOP_EN \ + & (~RTC_REG_XOSC32_ENB) & (~RTC_EMBCK_SEL_MODE) | RTC_EMBCK_SEL_OPTION | RTC_EMBCK_SRC_SEL) + +#define RTC_XOSCCALI_START 0x0000 +#define RTC_XOSCCALI_END 0x001f + +#define RTC_POWERKEY1 (RTC_BASE + 0x0028) +#define RTC_POWERKEY2 (RTC_BASE + 0x002a) +#define RTC_POWERKEY1_KEY 0xa357 +#define RTC_POWERKEY2_KEY 0x67d2 +/* + * RTC_PDN1: + * bit 0 - 3 : Android bits + * bit 4 - 5 : Recovery bits (0x10: factory data reset) + * bit 6 : Bypass PWRKEY bit + * bit 7 : Power-On Time bit + * bit 8 : RTC_GPIO_USER_WIFI bit + * bit 9 : RTC_GPIO_USER_GPS bit + * bit 10 : RTC_GPIO_USER_BT bit + * bit 11 : RTC_GPIO_USER_FM bit + * bit 12 : RTC_GPIO_USER_PMIC bit + * bit 13 : Fast Boot + * bit 14 : Kernel Power Off Charging + * bit 15 : Debug bit + */ +#define RTC_PDN1 (RTC_BASE + 0x002c) +#define RTC_PDN1_ANDROID_MASK 0x000f +#define RTC_PDN1_RECOVERY_MASK 0x0030 +#define RTC_PDN1_FAC_RESET (1U << 4) +#define RTC_PDN1_BYPASS_PWR (1U << 6) +#define RTC_PDN1_PWRON_TIME (1U << 7) +#define RTC_PDN1_GPIO_WIFI (1U << 8) +#define RTC_PDN1_GPIO_GPS (1U << 9) +#define RTC_PDN1_GPIO_BT (1U << 10) +#define RTC_PDN1_GPIO_FM (1U << 11) +#define RTC_PDN1_GPIO_PMIC (1U << 12) +#define RTC_PDN1_FAST_BOOT (1U << 13) +#define RTC_PDN1_KPOC (1U << 14) +#define RTC_PDN1_DEBUG (1U << 15) + +/* + * RTC_PDN2: + * bit 0 - 3 : MTH in power-on time + * bit 4 : Power-On Alarm bit + * bit 5 - 6 : UART bits + * bit 7 : autoboot bit + * bit 8 - 14: YEA in power-on time + * bit 15 : Power-On Logo bit + */ +#define RTC_PDN2 (RTC_BASE + 0x002e) +#define RTC_PDN2_PWRON_ALARM (1U << 4) +#define RTC_PDN2_UART_MASK 0x0060 +#define RTC_PDN2_UART_SHIFT 5 +#define RTC_AUTOBOOT_MASK 0x1 +#define RTC_AUTOBOOT_SHIFT 7 +#define RTC_PDN2_PWRON_LOGO (1U << 15) + +/* + * RTC_SPAR0: + * bit 0 - 5 : SEC in power-on time + * bit 6 : 32K less bit. True:with 32K, False:Without 32K + * bit 7 - 15: reserved bits + */ +#define RTC_SPAR0 (RTC_BASE + 0x0030) +#define RTC_SPAR0_32K_LESS (1U << 6) +#define RTC_SPAR0_LP_DET (1U << 7) + +/* + * RTC_SPAR1: + * bit 0 - 5 : MIN in power-on time + * bit 6 - 10 : HOU in power-on time + * bit 11 - 15: DOM in power-on time + */ +#define RTC_SPAR1 (RTC_BASE + 0x0032) + +#define RTC_PROT (RTC_BASE + 0x0036) +#define RTC_PROT_UNLOCK1 0x586a +#define RTC_PROT_UNLOCK2 0x9136 + +#define RTC_DIFF (RTC_BASE + 0x0038) +#define RTC_CALI_RD_SEL_SHIFT 15 +#define RTC_CALI_RD_SEL (1U << RTC_CALI_RD_SEL_SHIFT) +#define RTC_K_EOSC32_RSV (1U << 14) +#define RTC_DIFF_MASK 0xFFF +#define RTC_DIFF_SHIFT 0 + +#define RTC_CALI (RTC_BASE + 0x003a) +#define RTC_K_EOSC32_OVERFLOW (1U << 15) +#define RTC_CALI_WR_SEL_SHIFT 14 +#define RTC_CALI_WR_SEL_MASK 1 +#define RTC_CALI_XOSC 0 +#define RTC_CALI_K_EOSC_32 1 +#define RTC_CALI_MASK 0x3FFF +#define RTC_CALI_SHIFT 0 + +#define RTC_WRTGR (RTC_BASE + 0x003c) + +#define RTC_CON (RTC_BASE + 0x003e) +#define RTC_VBAT_LPSTA_RAW (1U << 0) +#define RTC_EOSC32_LPEN (1U << 1) +#define RTC_XOSC32_LPEN (1U << 2) +#define RTC_CON_LPRST (1U << 3) +#define RTC_CON_CDBO (1U << 4) +#define RTC_CON_F32KOB (1U << 5) /* 0: RTC_GPIO exports 32K */ +#define RTC_CON_GPO (1U << 6) +#define RTC_CON_GOE (1U << 7) /* 1: GPO mode, 0: GPI mode */ +#define RTC_CON_GSR (1U << 8) +#define RTC_CON_GSMT (1U << 9) +#define RTC_CON_GPEN (1U << 10) +#define RTC_CON_GPU (1U << 11) +#define RTC_CON_GE4 (1U << 12) +#define RTC_CON_GE8 (1U << 13) +#define RTC_CON_GPI (1U << 14) +#define RTC_CON_LPSTA_RAW (1U << 15) /* 32K was stopped */ + +/* power on alarm time setting */ + +#define RTC_PWRON_YEA RTC_PDN2 +#define RTC_PWRON_YEA_MASK 0x7f00 +#define RTC_PWRON_YEA_SHIFT 8 + +#define RTC_PWRON_MTH RTC_PDN2 +#define RTC_PWRON_MTH_MASK 0x000f +#define RTC_PWRON_MTH_SHIFT 0 + +#define RTC_PWRON_SEC RTC_SPAR0 +#define RTC_PWRON_SEC_MASK 0x003f +#define RTC_PWRON_SEC_SHIFT 0 + +#define RTC_PWRON_MIN RTC_SPAR1 +#define RTC_PWRON_MIN_MASK 0x003f +#define RTC_PWRON_MIN_SHIFT 0 + +#define RTC_PWRON_HOU RTC_SPAR1 +#define RTC_PWRON_HOU_MASK 0x07c0 +#define RTC_PWRON_HOU_SHIFT 6 + +#define RTC_PWRON_DOM RTC_SPAR1 +#define RTC_PWRON_DOM_MASK 0xf800 +#define RTC_PWRON_DOM_SHIFT 11 + +extern u16 rtc_spare_reg[][3]; + +#define MT_VRTC_PWM_CON0 ((MT_PMIC_REG_BASE+0x0FAE)) +#define MT_PMIC_VRTC_PWM_MODE_ADDR MT_VRTC_PWM_CON0 +#define MT_PMIC_VRTC_PWM_MODE_MASK 0x1 +#define MT_PMIC_VRTC_PWM_MODE_SHIFT 0 +#define MT_PMIC_VRTC_PWM_RSV_ADDR MT_VRTC_PWM_CON0 +#define MT_PMIC_VRTC_PWM_RSV_MASK 0x7 +#define MT_PMIC_VRTC_PWM_RSV_SHIFT 1 +#define MT_PMIC_VRTC_PWM_L_DUTY_ADDR MT_VRTC_PWM_CON0 +#define MT_PMIC_VRTC_PWM_L_DUTY_MASK 0xF +#define MT_PMIC_VRTC_PWM_L_DUTY_SHIFT 4 +#define MT_PMIC_VRTC_PWM_H_DUTY_ADDR MT_VRTC_PWM_CON0 +#define MT_PMIC_VRTC_PWM_H_DUTY_MASK 0xF +#define MT_PMIC_VRTC_PWM_H_DUTY_SHIFT 8 +#define MT_PMIC_VRTC_CAP_SEL_ADDR MT_VRTC_PWM_CON0 +#define MT_PMIC_VRTC_CAP_SEL_MASK 0x1 +#define MT_PMIC_VRTC_CAP_SEL_SHIFT 12 +#define VTRC_CAP_SEL (1 << MT_PMIC_VRTC_CAP_SEL_SHIFT) +#define VRTC_PWM_H_DUTY_12_8_MS (0 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_25_6_MS (1 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_51_2_MS (3 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_102_4_MS (7 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_204_8_MS (15 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_0_64_MS (0 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_1_28_MS (1 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_2_56_MS (3 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_5_12_MS (7 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_H_DUTY_10_24_MS (15 << MT_PMIC_VRTC_PWM_H_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_128_0_MS (0 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_256_0_MS (1 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_512_0_MS (3 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_1024_0_MS (7 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_2148_0_MS (15 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_6_4_MS (0 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_12_8_MS (1 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_25_6_MS (3 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_51_2_MS (7 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_L_DUTY_102_4_MS (15 << MT_PMIC_VRTC_PWM_L_DUTY_SHIFT) +#define VRTC_PWM_MODE (1 << MT_PMIC_VRTC_PWM_MODE_SHIFT) + + +#endif /* __MT_RTC_HW_H__ */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_secure_api.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_secure_api.h new file mode 100644 index 0000000000000000000000000000000000000000..7f2d1f63e3f7624fc57cc97d47d0c5d81d3bbe6f --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_secure_api.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#ifndef _MT_SECURE_API_H_ +#define _MT_SECURE_API_H_ + +#include + +#if defined(CONFIG_ARM_PSCI) || defined(CONFIG_MTK_PSCI) +/* Error Code */ +#define SIP_SVC_E_SUCCESS 0 +#define SIP_SVC_E_NOT_SUPPORTED -1 +#define SIP_SVC_E_INVALID_PARAMS -2 +#define SIP_SVC_E_INVALID_Range -3 +#define SIP_SVC_E_PERMISSION_DENY -4 + +#define MTK_SIP_KERNEL_MCUSYS_WRITE 0x82000201 +#define MTK_SIP_KERNEL_MCUSYS_ACCESS_COUNT 0x82000202 +#define MTK_SIP_KERNEL_L2_SHARING 0x82000203 +#define MTK_SIP_KERNEL_WDT 0x82000204 + +#define TBASE_SMC_AEE_DUMP (0xB200AEED) +#define MTK_SIP_KERNEL_GIC_DUMP 0x82000205 +#define MTK_SIP_KERNEL_DAPC_INIT 0x82000206 +#define MTK_SIP_KERNEL_EMIMPU_WRITE 0x82000207 +#define MTK_SIP_KERNEL_EMIMPU_READ 0x82000208 +#define MTK_SIP_KERNEL_EMIMPU_SET 0x82000209 +#define MTK_SIP_KERNEL_ICACHE_DUMP 0x82000210 + +#define MTK_SIP_KERNEL_MSG 0x820002ff + +#ifdef CONFIG_ARM64 +/* SIP SMC Call 64 */ +static noinline int mt_secure_call(u64 function_id, + u64 arg0, u64 arg1, u64 arg2) +{ + register u64 reg0 __asm__("x0") = function_id; + register u64 reg1 __asm__("x1") = arg0; + register u64 reg2 __asm__("x2") = arg1; + register u64 reg3 __asm__("x3") = arg2; + int ret = 0; + + asm volatile ("smc #0\n" : "+r" (reg0) : + "r"(reg1), "r"(reg2), "r"(reg3)); + + ret = (int)reg0; + return ret; +} + +#else +#include +#include +/* SIP SMC Call 32 */ +static noinline int mt_secure_call(u32 function_id, + u32 arg0, u32 arg1, u32 arg2) +{ + register u32 reg0 __asm__("r0") = function_id; + register u32 reg1 __asm__("r1") = arg0; + register u32 reg2 __asm__("r2") = arg1; + register u32 reg3 __asm__("r3") = arg2; + int ret = 0; + + asm volatile (__SMC(0) : "+r"(reg0), + "+r"(reg1), "+r"(reg2), "+r"(reg3)); + + ret = reg0; + return ret; +} +#endif +#define tbase_trigger_aee_dump() \ + mt_secure_call(TBASE_SMC_AEE_DUMP, 0, 0, 0) +#endif +#define emi_mpu_smc_write(offset, val) \ +mt_secure_call(MTK_SIP_KERNEL_EMIMPU_WRITE, offset, val, 0) + +#define emi_mpu_smc_read(offset) \ +mt_secure_call(MTK_SIP_KERNEL_EMIMPU_READ, offset, 0, 0) + +#define emi_mpu_smc_set(start, end, region_permission) \ +mt_secure_call(MTK_SIP_KERNEL_EMIMPU_SET, start, end, region_permission) + +#define CONFIG_MCUSYS_WRITE_PROTECT + +#if defined(CONFIG_MCUSYS_WRITE_PROTECT) && \ + (defined(CONFIG_ARM_PSCI) || defined(CONFIG_MTK_PSCI)) + +#ifdef CONFIG_ARM64 /* Kernel 64 */ +#define mcusys_smc_write(virt_addr, val) \ + mt_reg_sync_writel(val, virt_addr) + +#define mcusys_smc_write_phy(addr, val) \ +mt_secure_call(MTK_SIP_KERNEL_MCUSYS_WRITE, addr, val, 0) + +#define mcusys_access_count() \ +mt_secure_call(MTK_SIP_KERNEL_MCUSYS_ACCESS_COUNT, 0, 0, 0) + +#else /* Kernel 32 */ +#define SMC_IO_VIRT_TO_PHY(addr) (addr-0xF0000000+0x10000000) +#define mcusys_smc_write(virt_addr, val) \ + mt_secure_call(MTK_SIP_KERNEL_MCUSYS_WRITE, \ + SMC_IO_VIRT_TO_PHY(virt_addr), val, 0) + +#define mcusys_smc_write_phy(addr, val) \ +mt_secure_call(MTK_SIP_KERNEL_MCUSYS_WRITE, addr, val, 0) + +#define mcusys_access_count() \ +mt_secure_call(MTK_SIP_KERNEL_MCUSYS_ACCESS_COUNT, 0, 0, 0) +#endif + +#else +#define mcusys_smc_write(virt_addr, val) \ + mt_reg_sync_writel(val, virt_addr) +#define mcusys_access_count() (0) +#endif + +#define kernel_smc_msg(x1, x2, x3) \ + mt_secure_call(MTK_SIP_KERNEL_MSG, x1, x2, x3) + +#endif /* _MT_SECURE_API_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_sleep.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_sleep.h new file mode 100644 index 0000000000000000000000000000000000000000..5c4f2fca1575ab815207a53ad3ef7f22d3d70c90 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_sleep.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_SLEEP_ +#define _MT_SLEEP_ + +#include +#include "mt_spm.h" +#include "mt_spm_sleep.h" + +#define WAKE_SRC_CFG_KEY (1U << 31) + +extern int slp_set_wakesrc(u32 wakesrc, bool enable, bool ck26m_on); + +extern wake_reason_t slp_get_wake_reason(void); +extern bool slp_will_infra_pdn(void); +extern void slp_pasr_en(bool en, u32 value); +extern void slp_dpd_en(bool en); + +extern void slp_set_auto_suspend_wakelock(bool lock); +extern void slp_start_auto_suspend_resume_timer(u32 sec); +extern void slp_create_auto_suspend_resume_thread(void); + +extern void slp_module_init(void); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm.h new file mode 100644 index 0000000000000000000000000000000000000000..db18abd68c067daedf2b36e34d714caf0437b14a --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm.h @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_SPM_ +#define _MT_SPM_ + +#include +#include + +#ifdef CONFIG_OF +extern void __iomem *spm_base; +extern void __iomem *scp_i2c0_base; +extern void __iomem *scp_i2c1_base; +extern void __iomem *scp_i2c2_base; +extern u32 spm_irq_0; +extern u32 spm_irq_1; +extern u32 spm_irq_2; +extern u32 spm_irq_3; +extern u32 spm_irq_4; +extern u32 spm_irq_5; +extern u32 spm_irq_6; +extern u32 spm_irq_7; + +#undef SPM_BASE +#define SPM_BASE spm_base +#else +/* #include */ +#endif + +/* #include */ +#include +#include + +/************************************** + * Config and Parameter + **************************************/ + +/* ****: for bring up */ +#ifdef CONFIG_OF /* device tree */ +#undef SPM_I2C0_BASE +#undef SPM_I2C1_BASE +#undef SPM_I2C2_BASE +#define SPM_I2C0_BASE scp_i2c0_base +#define SPM_I2C1_BASE scp_i2c1_base +#define SPM_I2C2_BASE scp_i2c2_base + +#define SPM_IRQ0_ID spm_irq_0 +#define SPM_IRQ1_ID spm_irq_1 +#define SPM_IRQ2_ID spm_irq_2 +#define SPM_IRQ3_ID spm_irq_3 +#define SPM_IRQ4_ID spm_irq_4 +#define SPM_IRQ5_ID spm_irq_5 +#define SPM_IRQ6_ID spm_irq_6 +#define SPM_IRQ7_ID spm_irq_7 +#else /* no device tree: 6795: 163+32=195, 6735: 165+32=197 */ +#define SPM_BASE SLEEP_BASE +/* 6735 no SCP, so no peripheral i2c interface */ +#define SPM_I2C0_BASE 0xF0059C00 /* SCP_I2C0_BASE */ +#define SPM_I2C1_BASE 0xF0059C00 /* SCP_I2C1_BASE */ +#define SPM_I2C2_BASE 0xF0059C00 /* SCP_I2C2_BASE */ + +#define SPM_IRQ0_ID 195 /* SLEEP_IRQ_BIT0_ID */ +#define SPM_IRQ1_ID 196 /* SLEEP_IRQ_BIT1_ID */ +#define SPM_IRQ2_ID 197 /* SLEEP_IRQ_BIT2_ID */ +#define SPM_IRQ3_ID 198 /* SLEEP_IRQ_BIT3_ID */ +#define SPM_IRQ4_ID 199 /* SLEEP_IRQ_BIT4_ID */ +#define SPM_IRQ5_ID 200 /* SLEEP_IRQ_BIT5_ID */ +#define SPM_IRQ6_ID 201 /* SLEEP_IRQ_BIT6_ID */ +#define SPM_IRQ7_ID 202 /* SLEEP_IRQ_BIT7_ID */ +#endif + +/************************************** + * Define and Declare + **************************************/ +#define SPM_POWERON_CONFIG_SET (SPM_BASE + 0x000) +#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x010) +#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x014) +#define SPM_CLK_SETTLE (SPM_BASE + 0x100) +#define SPM_CA7_CPU0_PWR_CON (SPM_BASE + 0x200) +#define SPM_CA7_DBG_PWR_CON (SPM_BASE + 0x204) +#define SPM_CA7_CPUTOP_PWR_CON (SPM_BASE + 0x208) +#define SPM_VDE_PWR_CON (SPM_BASE + 0x210) +#define SPM_MFG_PWR_CON (SPM_BASE + 0x214) +#define SPM_CA7_CPU1_PWR_CON (SPM_BASE + 0x218) +#define SPM_CA7_CPU2_PWR_CON (SPM_BASE + 0x21c) +#define SPM_CA7_CPU3_PWR_CON (SPM_BASE + 0x220) +#define SPM_VEN_PWR_CON (SPM_BASE + 0x230) +#define SPM_IFR_PWR_CON (SPM_BASE + 0x234) +#define SPM_ISP_PWR_CON (SPM_BASE + 0x238) +#define SPM_DIS_PWR_CON (SPM_BASE + 0x23c) +#define SPM_DPY_PWR_CON (SPM_BASE + 0x240) +#define SPM_CA7_CPUTOP_L2_PDN (SPM_BASE + 0x244) +#define SPM_CA7_CPUTOP_L2_SLEEP (SPM_BASE + 0x248) +#define SPM_CA7_CPU0_L1_PDN (SPM_BASE + 0x25c) +#define SPM_CA7_CPU1_L1_PDN (SPM_BASE + 0x264) +#define SPM_CA7_CPU2_L1_PDN (SPM_BASE + 0x26c) +#define SPM_CA7_CPU3_L1_PDN (SPM_BASE + 0x274) +#define SPM_GCPU_SRAM_CON (SPM_BASE + 0x27c) +#define SPM_CONN_PWR_CON (SPM_BASE + 0x280) +#define SPM_MD_PWR_CON (SPM_BASE + 0x284) +#define SPM_MCU_PWR_CON (SPM_BASE + 0x290) +#define SPM_IFR_SRAMROM_CON (SPM_BASE + 0x294) +#define SPM_MJC_PWR_CON (SPM_BASE + 0x298) +#define SPM_AUDIO_PWR_CON (SPM_BASE + 0x29c) +#define SPM_CA15_CPU0_PWR_CON (SPM_BASE + 0x2a0) +#define SPM_CA15_CPU1_PWR_CON (SPM_BASE + 0x2a4) +#define SPM_CA15_CPU2_PWR_CON (SPM_BASE + 0x2a8) +#define SPM_CA15_CPU3_PWR_CON (SPM_BASE + 0x2ac) +#define SPM_CA15_CPUTOP_PWR_CON (SPM_BASE + 0x2b0) +#define SPM_CA15_L1_PWR_CON (SPM_BASE + 0x2b4) +#define SPM_CA15_L2_PWR_CON (SPM_BASE + 0x2b8) +#define SPM_MFG_2D_PWR_CON (SPM_BASE + 0x2c0) /* Need to remove in K2 */ +#define SPM_MFG_ASYNC_PWR_CON (SPM_BASE + 0x2c4) /* mt6797 */ +#define SPM_MD32_SRAM_CON (SPM_BASE + 0x2c8) +#define SPM_ARMPLL_DIV_PWR_CON (SPM_BASE + 0x2cc) +#define SPM_MD2_PWR_CON (SPM_BASE + 0x2d0) +#define SPM_C2K_PWR_CON (SPM_BASE + 0x2d4) /* mt6797 */ +#define SPM_INFRA_MD_PWR_CON (SPM_BASE + 0x2d8) /* mt6797 */ +#define SPM_CPU_EXT_ISO (SPM_BASE + 0x2dc) /* mt6797 */ +#define SPM_PCM_CON0 (SPM_BASE + 0x310) +#define SPM_PCM_CON1 (SPM_BASE + 0x314) +#define SPM_PCM_IM_PTR (SPM_BASE + 0x318) +#define SPM_PCM_IM_LEN (SPM_BASE + 0x31c) +#define SPM_PCM_REG_DATA_INI (SPM_BASE + 0x320) +#define SPM_PCM_EVENT_VECTOR0 (SPM_BASE + 0x340) +#define SPM_PCM_EVENT_VECTOR1 (SPM_BASE + 0x344) +#define SPM_PCM_EVENT_VECTOR2 (SPM_BASE + 0x348) +#define SPM_PCM_EVENT_VECTOR3 (SPM_BASE + 0x34c) +#define SPM_PCM_MAS_PAUSE_MASK (SPM_BASE + 0x354) +#define SPM_PCM_PWR_IO_EN (SPM_BASE + 0x358) +#define SPM_PCM_TIMER_VAL (SPM_BASE + 0x35c) +#define SPM_PCM_TIMER_OUT (SPM_BASE + 0x360) +#define SPM_PCM_REG0_DATA (SPM_BASE + 0x380) +#define SPM_PCM_REG1_DATA (SPM_BASE + 0x384) +#define SPM_PCM_REG2_DATA (SPM_BASE + 0x388) +#define SPM_PCM_REG3_DATA (SPM_BASE + 0x38c) +#define SPM_PCM_REG4_DATA (SPM_BASE + 0x390) +#define SPM_PCM_REG5_DATA (SPM_BASE + 0x394) +#define SPM_PCM_REG6_DATA (SPM_BASE + 0x398) +#define SPM_PCM_REG7_DATA (SPM_BASE + 0x39c) +#define SPM_PCM_REG8_DATA (SPM_BASE + 0x3a0) +#define SPM_PCM_REG9_DATA (SPM_BASE + 0x3a4) +#define SPM_PCM_REG10_DATA (SPM_BASE + 0x3a8) +#define SPM_PCM_REG11_DATA (SPM_BASE + 0x3ac) +#define SPM_PCM_REG12_DATA (SPM_BASE + 0x3b0) +#define SPM_PCM_REG13_DATA (SPM_BASE + 0x3b4) +#define SPM_PCM_REG14_DATA (SPM_BASE + 0x3b8) +#define SPM_PCM_REG15_DATA (SPM_BASE + 0x3bc) +#define SPM_PCM_EVENT_REG_STA (SPM_BASE + 0x3c0) +#define SPM_PCM_FSM_STA (SPM_BASE + 0x3c4) +#define SPM_PCM_IM_HOST_RW_PTR (SPM_BASE + 0x3c8) +#define SPM_PCM_IM_HOST_RW_DAT (SPM_BASE + 0x3cc) +#define SPM_PCM_EVENT_VECTOR4 (SPM_BASE + 0x3d0) +#define SPM_PCM_EVENT_VECTOR5 (SPM_BASE + 0x3d4) +#define SPM_PCM_EVENT_VECTOR6 (SPM_BASE + 0x3d8) +#define SPM_PCM_EVENT_VECTOR7 (SPM_BASE + 0x3dc) +#define SPM_PCM_SW_INT_SET (SPM_BASE + 0x3e0) +#define SPM_PCM_SW_INT_CLEAR (SPM_BASE + 0x3e4) +#define SPM_PCM_REG12_MASK (SPM_BASE + 0x3e8) +#define SPM_CLK_CON (SPM_BASE + 0x400) +#define SPM_SLEEP_DUAL_VCORE_PWR_CON (SPM_BASE + 0x404) +#define SPM_SLEEP_PTPOD2_CON (SPM_BASE + 0x408) +#define SPM_APMCU_PWRCTL (SPM_BASE + 0x600) +#define SPM_AP_DVFS_CON_SET (SPM_BASE + 0x604) +#define SPM_AP_STANBY_CON (SPM_BASE + 0x608) /* mt6797 */ +#define SPM_PWR_STATUS (SPM_BASE + 0x60c) +#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x610) +/* #define SPM_AP_BSI_REQ (SPM_BASE + 0x614) */ +#define SPM_SLEEP_MDBSI_CON (SPM_BASE + 0x614) /* mt6797 */ +#define SPM_BSI_GEN (SPM_BASE + 0x620) /* mt6797 */ +#define SPM_BSI_EN_SR (SPM_BASE + 0x624) /* mt6797 */ +#define SPM_BSI_CLK_SR (SPM_BASE + 0x628) /* mt6797 */ +#define SPM_BSI_DO_SR (SPM_BASE + 0x62c) /* mt6797 */ +#define SPM_BSI_D1_SR (SPM_BASE + 0x630) /* mt6797 */ +#define SPM_BSI_D2_SR (SPM_BASE + 0x634) /* mt6797 */ +#define SPM_AP_SEMA (SPM_BASE + 0x638) /* mt6797 */ +#define SPM_SPM_SEMA (SPM_BASE + 0x63c) /* mt6797 */ +#define SPM_SLEEP_TIMER_STA (SPM_BASE + 0x720) +#define SPM_SLEEP_TWAM_CON (SPM_BASE + 0x760) +#define SPM_SLEEP_TWAM_STATUS0 (SPM_BASE + 0x764) +#define SPM_SLEEP_TWAM_STATUS1 (SPM_BASE + 0x768) +#define SPM_SLEEP_TWAM_STATUS2 (SPM_BASE + 0x76c) +#define SPM_SLEEP_TWAM_STATUS3 (SPM_BASE + 0x770) +#define SPM_SLEEP_TWAM_CURR_STATUS0 (SPM_BASE + 0x774) +#define SPM_SLEEP_TWAM_CURR_STATUS1 (SPM_BASE + 0x778) +#define SPM_SLEEP_TWAM_CURR_STATUS2 (SPM_BASE + 0x77C) +#define SPM_SLEEP_TWAM_CURR_STATUS3 (SPM_BASE + 0x780) +#define SPM_SLEEP_TWAM_TIMER_OUT (SPM_BASE + 0x784) +#define SPM_SLEEP_TWAM_WINDOW_LEN (SPM_BASE + 0x788) +#define SPM_SLEEP_IDLE_SEL (SPM_BASE + 0x78C) +#define SPM_SLEEP_WAKEUP_EVENT_MASK (SPM_BASE + 0x810) +#define SPM_SLEEP_CPU_WAKEUP_EVENT (SPM_BASE + 0x814) +#define SPM_SLEEP_MD32_WAKEUP_EVENT_MASK (SPM_BASE + 0x818) +#define SPM_PCM_WDT_TIMER_VAL (SPM_BASE + 0x824) +#define SPM_PCM_WDT_TIMER_OUT (SPM_BASE + 0x828) +#define SPM_PCM_MD32_MAILBOX (SPM_BASE + 0x830) +#define SPM_PCM_MD32_IRQ (SPM_BASE + 0x834) +#define SPM_SLEEP_ISR_MASK (SPM_BASE + 0x900) +#define SPM_SLEEP_ISR_STATUS (SPM_BASE + 0x904) +#define SPM_SLEEP_ISR_RAW_STA (SPM_BASE + 0x910) +#define SPM_SLEEP_MD32_ISR_RAW_STA (SPM_BASE + 0x914) +#define SPM_SLEEP_WAKEUP_MISC (SPM_BASE + 0x918) +#define SPM_SLEEP_BUS_PROTECT_RDY (SPM_BASE + 0x91c) +#define SPM_SLEEP_SUBSYS_IDLE_STA (SPM_BASE + 0x920) +#define SPM_PCM_RESERVE (SPM_BASE + 0xb00) +#define SPM_PCM_RESERVE2 (SPM_BASE + 0xb04) +#define SPM_PCM_FLAGS (SPM_BASE + 0xb08) +#define SPM_PCM_SRC_REQ (SPM_BASE + 0xb0c) +#define SPM_PCM_RESERVE3 (SPM_BASE + 0xb14) +#define SPM_PCM_RESERVE4 (SPM_BASE + 0xb18) +#define SPM_PCM_DEBUG_CON (SPM_BASE + 0xb20) +#define SPM_CA7_CPU0_IRQ_MASK (SPM_BASE + 0xb30) +#define SPM_CA7_CPU1_IRQ_MASK (SPM_BASE + 0xb34) +#define SPM_CA7_CPU2_IRQ_MASK (SPM_BASE + 0xb38) +#define SPM_CA7_CPU3_IRQ_MASK (SPM_BASE + 0xb3c) +#define SPM_CA15_CPU0_IRQ_MASK (SPM_BASE + 0xb40) +#define SPM_CA15_CPU1_IRQ_MASK (SPM_BASE + 0xb44) +#define SPM_CA15_CPU2_IRQ_MASK (SPM_BASE + 0xb48) +#define SPM_CA15_CPU3_IRQ_MASK (SPM_BASE + 0xb4c) +#define SPM_PCM_PASR_DPD_0 (SPM_BASE + 0xb60) +#define SPM_PCM_PASR_DPD_1 (SPM_BASE + 0xb64) +#define SPM_PCM_PASR_DPD_2 (SPM_BASE + 0xb68) +#define SPM_PCM_PASR_DPD_3 (SPM_BASE + 0xb6c) +#define SPM_SLEEP_CA7_WFI0_EN (SPM_BASE + 0xf00) +#define SPM_SLEEP_CA7_WFI1_EN (SPM_BASE + 0xf04) +#define SPM_SLEEP_CA7_WFI2_EN (SPM_BASE + 0xf08) +#define SPM_SLEEP_CA7_WFI3_EN (SPM_BASE + 0xf0c) +#define SPM_SLEEP_CA15_WFI0_EN (SPM_BASE + 0xf10) +#define SPM_SLEEP_CA15_WFI1_EN (SPM_BASE + 0xf14) +#define SPM_SLEEP_CA15_WFI2_EN (SPM_BASE + 0xf18) +#define SPM_SLEEP_CA15_WFI3_EN (SPM_BASE + 0xf1c) + +#define SPM_PROJECT_CODE 0xb16 + +#define SPM_REGWR_EN (1U << 0) +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) + +/* PCM Flags store in PCM_RESERVE4(0xB18)*/ +#define SPM_CPU_PDN_DIS (1U << 0) +#define SPM_INFRA_PDN_DIS (1U << 1) +#define SPM_DDRPHY_PDN_DIS (1U << 2) +#define SPM_PASR_DIS (1U << 4) +#define SPM_MD_VRF18_DIS (1U << 5) /* mt6797 */ +#define SPM_MEMPLL_CG_EN (1U << 6) /* mt6797 */ +/* #define SPM_MEMPLL_RESET (1U << 7)//mt6797 no use */ +#define SPM_VCORE_DVFS_EN (1U << 8) /* mt6797 */ +#define SPM_CPU_DVS_DIS (1U << 9) +#define SPM_IFRA_MD_PDN_DIS (1U << 10) /* mt6797 */ +#define SPM_VCORE_DVS_EVENT_DIS (1U << 11) /* mt6797 */ +#define SPM_DDR_HIGH_SPEED (1U << 12) /* mt6797 no use */ +#define SPM_DISABLE_ATF_ABORT (1U << 13) /* mt6797 */ +#define SPM_DRAM_RANK1_ADDR_SEL0 (1U << 19) /* 0x60000000, 0x70000000 */ +#define SPM_DRAM_RANK1_ADDR_SEL1 (1U << 20) /* 0x80000000 */ +#define SPM_DRAM_RANK1_ADDR_SEL2 (1U << 21) /* 0xc0000000 */ +#define SPM_DRAM_RANK1_ADDR_SEL3 (1U << 24) /* 0xa0000000 */ +#define SPM_BUCK_SEL (1U << 26) /* mt6753 use */ + +/******/ +/* Wakeup Source */ +enum SPM_WAKE_SRC_LIST { + WAKE_SRC_SPM_MERGE = (1U << 0), /* PCM timer, TWAM or CPU */ + WAKE_SRC_LTE_PTP = (1U << 1), + WAKE_SRC_KP = (1U << 2), + WAKE_SRC_WDT = (1U << 3), + WAKE_SRC_GPT = (1U << 4), + WAKE_SRC_EINT = (1U << 5), + WAKE_SRC_CONN_WDT = (1U << 6), + WAKE_SRC_CCIF0_MD = (1U << 7), + WAKE_SRC_CCIF1_MD = (1U << 8), + WAKE_SRC_LOW_BAT = (1U << 9), + WAKE_SRC_CONN2AP = (1U << 10), + WAKE_SRC_F26M_WAKE = (1U << 11), + WAKE_SRC_F26M_SLEEP = (1U << 12), + WAKE_SRC_PCM_WDT = (1U << 13), + WAKE_SRC_USB_CD = (1U << 14), + WAKE_SRC_USB_PDN = (1U << 15), + WAKE_SRC_LTE_WAKE = (1U << 16), + WAKE_SRC_LTE_SLEEP = (1U << 17), + WAKE_SRC_SEJ = (1U << 18), + WAKE_SRC_UART0 = (1U << 19), + WAKE_SRC_AFE = (1U << 20), + WAKE_SRC_THERM = (1U << 21), + WAKE_SRC_CIRQ = (1U << 22), + WAKE_SRC_MD1_VRF18_WAKE = (1U << 23), + WAKE_SRC_SYSPWREQ = (1U << 24), + WAKE_SRC_MD_WDT = (1U << 25), + WAKE_SRC_C2K_WDT = (1U << 26), + WAKE_SRC_CLDMA_MD = (1U << 27), + WAKE_SRC_MD1_VRF18_SLEEP = (1U << 28), + WAKE_SRC_CPU_IRQ = (1U << 29), + WAKE_SRC_APSRC_WAKE = (1U << 30), + WAKE_SRC_APSRC_SLEEP = (1U << 31) +}; + +typedef enum { + WR_NONE = 0, + WR_UART_BUSY = 1, + WR_PCM_ASSERT = 2, + WR_PCM_TIMER = 3, + WR_WAKE_SRC = 4, + WR_UNKNOWN = 5, +} wake_reason_t; + +struct twam_sig { + u32 sig0; /* signal 0: config or status */ + u32 sig1; /* signal 1: config or status */ + u32 sig2; /* signal 2: config or status */ + u32 sig3; /* signal 3: config or status */ +}; + +enum spm_clk_buf_pad_id { + BSI_EN_SR = 0, + BSI_CLK_SR = 1, + BSI_D0_SR = 2, + BSI_D1_SR = 3, + BSI_D2_SR = 4, +}; + +typedef void (*twam_handler_t) (struct twam_sig *twamsig); + +/* for power management init */ +extern int spm_module_init(void); + +/* for ANC in talking */ +extern void spm_mainpll_on_request(const char *drv_name); +extern void spm_mainpll_on_unrequest(const char *drv_name); + +/* for TWAM in MET */ +extern void spm_twam_register_handler(twam_handler_t handler); +extern void spm_twam_enable_monitor(const struct twam_sig *twamsig, + bool speed_mode, unsigned int window_len); +extern void spm_twam_disable_monitor(void); + +/* for Vcore DVFS */ +extern void spm_go_to_vcore_dvfs(u32 spm_flags, u32 spm_data); +extern int spm_set_vcore_dvs_voltage(unsigned int opp); +extern char *spm_dump_vcore_dvs_regs(char *p); + +/* for AP BSI Generator */ +void spm_ap_bsi_gen(unsigned int *clk_buf_cfg); + +unsigned int spm_get_cpu_pwr_status(void); + +/************************************** + * Macro and Inline + **************************************/ +#define spm_read(addr) __raw_readl(IOMEM(addr)) +#define spm_write(addr, val) mt_reg_sync_writel(val, addr) + +#define is_cpu_pdn(flags) (!((flags) & SPM_CPU_PDN_DIS)) +#define is_infra_pdn(flags) (!((flags) & SPM_INFRA_PDN_DIS)) +#define is_ddrphy_pdn(flags) (!((flags) & SPM_DDRPHY_PDN_DIS)) +#define is_dualvcore_pdn(flags) (!((flags) & SPM_DUALVCORE_PDN_DIS)) + +#define get_high_cnt(sigsta) ((sigsta) & 0x3ff) +#define get_high_percent(sigsta) ((get_high_cnt(sigsta) * 100 + 511) / 1023) +#define get_percent(sigsta, tick) ((sigsta * 100) / tick) + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_mtcmos.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_mtcmos.h new file mode 100644 index 0000000000000000000000000000000000000000..295c014fe8da037e084e9154f16cd8d493c06dea --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_mtcmos.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_SPM_MTCMOS_ +#define _MT_SPM_MTCMOS_ + +#include + +#define STA_POWER_DOWN 0 +#define STA_POWER_ON 1 + +/* + * 1. for CPU MTCMOS: CPU0, CPU1, CPU2, CPU3, DBG0, CPU4, CPU5, CPU6, CPU7, DBG1, CPUSYS1 + * 2. call spm_mtcmos_cpu_lock/unlock() before/after any operations + */ +extern int spm_mtcmos_cpu_init(void); + +extern void spm_mtcmos_cpu_lock(unsigned long *flags); +extern void spm_mtcmos_cpu_unlock(unsigned long *flags); + +extern int spm_mtcmos_ctrl_cpu(unsigned int cpu, int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu0(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu1(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu2(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu3(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu4(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu5(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu6(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu7(int state, int chkWfiBeforePdn); + +extern int spm_mtcmos_ctrl_dbg0(int state); + +extern int spm_mtcmos_ctrl_cpusys0(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpusys1(int state, int chkWfiBeforePdn); + +extern bool spm_cpusys0_can_power_down(void); +extern bool spm_cpusys1_can_power_down(void); + +extern void spm_mtcmos_ctrl_cpusys1_init_1st_bring_up(int state); + + +/* + * 1. for non-CPU MTCMOS: VDEC, VENC, ISP, DISP, MFG, INFRA, DDRPHY, MDSYS1, MDSYS2 + * 2. call spm_mtcmos_noncpu_lock/unlock() before/after any operations + */ +/* extern void spm_mtcmos_noncpu_lock(unsigned long *flags); */ +/* extern void spm_mtcmos_noncpu_unlock(unsigned long *flags); */ + +extern int spm_mtcmos_ctrl_vdec(int state); +extern int spm_mtcmos_ctrl_venc(int state); +extern int spm_mtcmos_ctrl_isp(int state); +extern int spm_mtcmos_ctrl_disp(int state); +extern int spm_mtcmos_ctrl_mfg(int state); +/* extern int spm_mtcmos_ctrl_mfg_ASYNC(int state); */ +/* extern int spm_mtcmos_ctrl_mjc(int state); */ +/* extern int spm_mtcmos_ctrl_aud(int state); */ + +/* extern int spm_mtcmos_ctrl_infra(int state); */ +/* extern int spm_mtcmos_ctrl_ddrphy(int state); */ + +extern int spm_mtcmos_ctrl_mdsys1(int state); +extern int spm_mtcmos_ctrl_mdsys2(int state); +extern int spm_mtcmos_ctrl_connsys(int state); + +extern int spm_topaxi_prot(int bit, int en); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_mtcmos_internal.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_mtcmos_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..63985b9f5a3fa9efbe38f0bbba00fbcd411b5b26 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_mtcmos_internal.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_SPM_MTCMOS_INTERNAL_ +#define _MT_SPM_MTCMOS_INTERNAL_ + + +/************************************** + * for CPU MTCMOS + **************************************/ +/* + * regiser bit definition + */ +/* SPM_CA7_CPU0_PWR_CON */ +/* SPM_CA7_CPU1_PWR_CON */ +/* SPM_CA7_CPU2_PWR_CON */ +/* SPM_CA7_CPU3_PWR_CON */ +/* SPM_CA7_DBG_PWR_CON */ +/* SPM_CA7_CPUTOP_PWR_CON */ +/* SPM_CA15_CPU0_PWR_CON */ +/* SPM_CA15_CPU1_PWR_CON */ +/* SPM_CA15_CPU2_PWR_CON */ +/* SPM_CA15_CPU3_PWR_CON */ +/* SPM_CA15_CPUTOP_PWR_CON */ +#define SRAM_ISOINT_B (1U << 6) +#define SRAM_CKISO (1U << 5) +#define PWR_CLK_DIS (1U << 4) +#define PWR_ON_2ND (1U << 3) +#define PWR_ON (1U << 2) +#define PWR_ISO (1U << 1) +#define PWR_RST_B (1U << 0) + +/* SPM_CA7_CPU0_L1_PDN */ +/* SPM_CA7_CPU1_L1_PDN */ +/* SPM_CA7_CPU2_L1_PDN */ +/* SPM_CA7_CPU3_L1_PDN */ +#define L1_PDN_ACK (1U << 8) +#define L1_PDN (1U << 0) +/* SPM_CA7_CPUTOP_L2_PDN */ +#define L2_SRAM_PDN_ACK (1U << 8) +#define L2_SRAM_PDN (1U << 0) +/* SPM_CA7_CPUTOP_L2_SLEEP */ +#define L2_SRAM_SLEEP_B_ACK (1U << 8) +#define L2_SRAM_SLEEP_B (1U << 0) + +/* SPM_CA15_L1_PWR_CON */ +#define CPU3_CA15_L1_PDN_ACK (1U << 19) +#define CPU2_CA15_L1_PDN_ACK (1U << 18) +#define CPU1_CA15_L1_PDN_ACK (1U << 17) +#define CPU0_CA15_L1_PDN_ACK (1U << 16) +#define CPU3_CA15_L1_PDN_ISO (1U << 7) +#define CPU2_CA15_L1_PDN_ISO (1U << 6) +#define CPU1_CA15_L1_PDN_ISO (1U << 5) +#define CPU0_CA15_L1_PDN_ISO (1U << 4) +#define CPU3_CA15_L1_PDN (1U << 3) +#define CPU2_CA15_L1_PDN (1U << 2) +#define CPU1_CA15_L1_PDN (1U << 1) +#define CPU0_CA15_L1_PDN (1U << 0) +/* SPM_CA15_L2_PWR_CON */ +#define CA15_L2_SLEEPB_ACK (1U << 4) +#define CA15_L2_PDN_ACK (1U << 0) +#define CA15_L2_SLEEPB_ISO (1U << 6) +#define CA15_L2_SLEEPB (1U << 4) +#define CA15_L2_PDN_ISO (1U << 2) +#define CA15_L2_PDN (1U << 0) + +/* SPM_PWR_STATUS */ +/* SPM_PWR_STATUS_2ND */ +#define CA15_CPU3 (1U << 17) +#define CA15_CPU2 (1U << 18) +#define CA15_CPU1 (1U << 19) +#define CA15_CPU0 (1U << 20) +#define CA15_CPUTOP (1U << 16) +/* #define CA7_DBG (1U << 13) */ +#define CA7_CPU3 (1U << 10) +#define CA7_CPU2 (1U << 11) +#define CA7_CPU1 (1U << 12) +#define CA7_CPU0 (1U << 13) +#define CA7_CPUTOP (1U << 9) + +/* SPM_SLEEP_TIMER_STA */ +#define CA15_CPUTOP_STANDBYWFI (1U << 25) +#define CA7_CPUTOP_STANDBYWFI (1U << 24) +#define CA15_CPU3_STANDBYWFI (1U << 23) +#define CA15_CPU2_STANDBYWFI (1U << 22) +#define CA15_CPU1_STANDBYWFI (1U << 21) +#define CA15_CPU0_STANDBYWFI (1U << 20) +#define CA7_CPU3_STANDBYWFI (1U << 19) +#define CA7_CPU2_STANDBYWFI (1U << 18) +#define CA7_CPU1_STANDBYWFI (1U << 17) +#define CA7_CPU0_STANDBYWFI (1U << 16) + +/* SPM_SLEEP_DUAL_VCORE_PWR_CON */ +#define VCA15_PWR_ISO (1U << 13) +#define VCA7_PWR_ISO (1U << 12) + +/* INFRA_TOPAXI_PROTECTEN */ +#define CA15_PDN_REQ (30) +#define CA7_PDN_REQ (29) + + +#endif /* #ifndef _MT_SPM_MTCMOS_INTERNAL_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_sleep.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_sleep.h new file mode 100644 index 0000000000000000000000000000000000000000..31a5ad977acdfd661ef2feabaefe217f2741c494 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_spm_sleep.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_SPM_SLEEP_ +#define _MT_SPM_SLEEP_ + +#include +#include "mt_spm.h" +/* + * for suspend + */ +extern int spm_set_sleep_wakesrc(u32 wakesrc, bool enable, bool replace); +extern u32 spm_get_sleep_wakesrc(void); +extern wake_reason_t spm_go_to_sleep(u32 spm_flags, u32 spm_data); + +extern bool spm_is_md_sleep(void); +extern bool spm_is_md1_sleep(void); +extern bool spm_is_md2_sleep(void); +extern bool spm_is_conn_sleep(void); +extern void spm_set_wakeup_src_check(void); +extern bool spm_check_wakeup_src(void); +extern void spm_poweron_config_set(void); +extern void spm_md32_sram_con(u32 value); +extern void spm_ap_mdsrc_req(u8 set); +extern bool spm_set_suspned_pcm_init_flag(u32 *suspend_flags); + +extern void spm_output_sleep_option(void); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_thermal.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_thermal.h new file mode 100644 index 0000000000000000000000000000000000000000..c51fe47f5754e8756a57ba0800f6f0923f1e7911 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mt_thermal.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT6755_THERMAL_H +#define _MT6755_THERMAL_H + +#include +#include +#include +#include + +#include +#include + +#include "mt-plat/sync_write.h" +#include "mtk_thermal_typedefs.h" +#include "mt_gpufreq.h" + +/* +Bank0 : CPU_mp0 (TS_MCU4) +Bank1 : SOC+GPU (TS_MCU1, TS_MCU2, TS_MCU3) +Bank2 : CPU_mp1 (TS_MCU4) +*/ +typedef enum { + THERMAL_SENSOR1 = 0, /*TS_MCU1 */ + THERMAL_SENSOR2 = 1, /*TS_MCU2 */ + THERMAL_SENSOR3 = 2, /*TS_MCU3 */ + THERMAL_SENSOR4 = 3, /*TS_MCU4 */ + THERMAL_SENSOR_ABB = 4, /*TS_ABB */ + THERMAL_SENSOR_NUM +} thermal_sensor_name; + +typedef enum { + THERMAL_BANK0 = 0, /* CPU (TSMCU2) */ + THERMAL_BANK1 = 1, /* SOC + GPU (TSMCU1) */ + THERMAL_BANK2 = 2, /* LTE (TSMCU3) */ + THERMAL_BANK_NUM +} thermal_bank_name; + + +struct TS_PTPOD { + unsigned int ts_MTS; + unsigned int ts_BTS; +}; + +extern int mtktscpu_limited_dmips; + +extern void get_thermal_slope_intercept(struct TS_PTPOD *ts_info, thermal_bank_name ts_bank); +extern void set_taklking_flag(bool flag); +extern int tscpu_get_cpu_temp(void); +extern int tscpu_get_temp_by_bank(thermal_bank_name ts_bank); + +#define THERMAL_WRAP_WR32(val, addr) mt_reg_sync_writel((val), ((void *)addr)) + + +extern int get_immediate_cpu0_wrap(void); +extern int get_immediate_gpu_wrap(void); +extern int get_immediate_cpu1_wrap(void); + +/*add for DLPT*/ +extern int tscpu_get_min_cpu_pwr(void); +extern int tscpu_get_min_gpu_pwr(void); + +/*4 thermal sensors*/ +typedef enum { + MTK_THERMAL_SENSOR_TS1 = 0, + MTK_THERMAL_SENSOR_TS2, + MTK_THERMAL_SENSOR_TS3, + MTK_THERMAL_SENSOR_TS4, + MTK_THERMAL_SENSOR_TSABB, + + ATM_CPU_LIMIT, + ATM_GPU_LIMIT, + + MTK_THERMAL_SENSOR_CPU_COUNT +} MTK_THERMAL_SENSOR_CPU_ID_MET; + + +extern int tscpu_get_cpu_temp_met(MTK_THERMAL_SENSOR_CPU_ID_MET id); + + +typedef void (*met_thermalsampler_funcMET) (void); +extern void mt_thermalsampler_registerCB(met_thermalsampler_funcMET pCB); + +extern void tscpu_start_thermal(void); +extern void tscpu_stop_thermal(void); +extern void tscpu_cancel_thermal_timer(void); +extern void tscpu_start_thermal_timer(void); +extern void mtkts_btsmdpa_cancel_thermal_timer(void); +extern void mtkts_btsmdpa_start_thermal_timer(void); +extern void mtkts_bts_cancel_thermal_timer(void); +extern void mtkts_bts_start_thermal_timer(void); +extern void mtkts_pmic_cancel_thermal_timer(void); +extern void mtkts_pmic_start_thermal_timer(void); +extern void mtkts_battery_cancel_thermal_timer(void); +extern void mtkts_battery_start_thermal_timer(void); +extern void mtkts_pa_cancel_thermal_timer(void); +extern void mtkts_pa_start_thermal_timer(void); +extern void mtkts_wmt_cancel_thermal_timer(void); +extern void mtkts_wmt_start_thermal_timer(void); + +extern void mtkts_allts_cancel_ts1_timer(void); +extern void mtkts_allts_start_ts1_timer(void); +extern void mtkts_allts_cancel_ts2_timer(void); +extern void mtkts_allts_start_ts2_timer(void); +extern void mtkts_allts_cancel_ts3_timer(void); +extern void mtkts_allts_start_ts3_timer(void); +extern void mtkts_allts_cancel_ts4_timer(void); +extern void mtkts_allts_start_ts4_timer(void); +extern void mtkts_allts_cancel_ts5_timer(void); +extern void mtkts_allts_start_ts5_timer(void); + +extern int mtkts_bts_get_hw_temp(void); + +extern int get_immediate_ts1_wrap(void); +extern int get_immediate_ts2_wrap(void); +extern int get_immediate_ts3_wrap(void); +extern int get_immediate_ts4_wrap(void); +extern int get_immediate_tsabb_wrap(void); + +/* Get TS_ temperatures from its thermal_zone instead of raw data, + * temperature here would be processed according to the policy setting */ +extern int mtkts_get_ts1_temp(void); +extern int mtkts_get_ts2_temp(void); +extern int mtkts_get_ts3_temp(void); +extern int mtkts_get_ts4_temp(void); +extern int mtkts_get_tsabb_temp(void); + +extern int is_cpu_power_unlimit(void); /* in mtk_ts_cpu.c */ +extern int is_cpu_power_min(void); /* in mtk_ts_cpu.c */ +extern int get_cpu_target_tj(void); +extern int get_cpu_target_offset(void); +extern int mtk_gpufreq_register(struct mt_gpufreq_power_table_info *freqs, int num); + +extern int get_target_tj(void); +extern int mtk_thermal_get_tpcb_target(void); + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mtk_rtc_hal.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mtk_rtc_hal.h new file mode 100644 index 0000000000000000000000000000000000000000..d77c91ec9580c54732ffd4abedabcb60454ce0ee --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/mtk_rtc_hal.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 MediaTek, Inc. + * + * Author: Terry Chang + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef _MTK_RTC_HAL_H_ +#define _MTK_RTC_HAL_H_ + +#include +#include + +#define RTC_CON_LPEN 0 + +#define PMIC_REGISTER_INTERRUPT_ENABLE /*register rtc interrupt*/ +#ifdef PMIC_REGISTER_INTERRUPT_ENABLE +#define RTC_INTERRUPT_NUM 9 +#endif + +#ifdef VRTC_PWM_ENABLE +#define RTC_PWM_ENABLE_POLLING_TIMER (30*60) /*30 min */ +#endif + +#define RTC_GPIO_USER_MASK (((1U << 13) - 1) & 0xff00) + +/* RTC registers */ +#define RTC_BASE (0x4000) + +extern u16 hal_rtc_get_gpio_32k_status(void); +extern void hal_rtc_set_gpio_32k_status(u16 user, bool enable); +extern void hal_rtc_set_abb_32k(u16 enable); +extern void hal_rtc_bbpu_pwdn(void); +extern void hal_rtc_get_pwron_alarm(struct rtc_time *tm, struct rtc_wkalrm *alm); +extern bool hal_rtc_is_lp_irq(void); +extern bool hal_rtc_is_pwron_alarm(struct rtc_time *nowtm, struct rtc_time *tm); +extern void hal_rtc_get_alarm(struct rtc_time *tm, struct rtc_wkalrm *alm); +extern void hal_rtc_set_alarm(struct rtc_time *tm); +extern void hal_rtc_clear_alarm(struct rtc_time *tm); +extern void hal_rtc_set_lp_irq(void); +extern void hal_rtc_save_pwron_time(bool enable, struct rtc_time *tm, bool logo); +#ifdef VRTC_PWM_ENABLE +extern void hal_rtc_pwm_enable(void); +#endif +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/upmu_hw.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/upmu_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..caf98c5a80124adf9640196cfd3ed298331984fb --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/upmu_hw.h @@ -0,0 +1,18629 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _MT_PMIC_UPMU_HW_H_ +#define _MT_PMIC_UPMU_HW_H_ + +#ifdef CONFIG_MTK_PMIC_NEW_ARCH + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#include +#endif + +#else +/*MT6351*/ +#define MT6351_PMIC_REG_BASE (0x0000) + +#define MT6351_STRUP_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0000)) +#define MT6351_STRUP_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0002)) +#define MT6351_STRUP_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0004)) +#define MT6351_STRUP_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0006)) +#define MT6351_STRUP_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0008)) +#define MT6351_STRUP_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x000A)) +#define MT6351_STRUP_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x000C)) +#define MT6351_STRUP_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x000E)) +#define MT6351_STRUP_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0010)) +#define MT6351_STRUP_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0012)) +#define MT6351_STRUP_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0014)) +#define MT6351_STRUP_CON11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0016)) +#define MT6351_STRUP_CON12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0018)) +#define MT6351_STRUP_CON13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x001A)) +#define MT6351_STRUP_CON14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x001C)) +#define MT6351_STRUP_CON15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x001E)) +#define MT6351_STRUP_CON16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0020)) +#define MT6351_STRUP_CON17 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0022)) +#define MT6351_STRUP_CON18 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0024)) +#define MT6351_STRUP_CON19 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0026)) +#define MT6351_STRUP_CON20 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0028)) +#define MT6351_STRUP_CON21 ((unsigned int)(MT6351_PMIC_REG_BASE+0x002A)) +#define MT6351_STRUP_CON22 ((unsigned int)(MT6351_PMIC_REG_BASE+0x002C)) +#define MT6351_STRUP_CON23 ((unsigned int)(MT6351_PMIC_REG_BASE+0x002E)) +#define MT6351_STRUP_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0030)) +#define MT6351_STRUP_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0032)) +#define MT6351_HWCID ((unsigned int)(MT6351_PMIC_REG_BASE+0x0200)) +#define MT6351_SWCID ((unsigned int)(MT6351_PMIC_REG_BASE+0x0202)) +#define MT6351_TOP_CON ((unsigned int)(MT6351_PMIC_REG_BASE+0x0204)) +#define MT6351_TEST_OUT ((unsigned int)(MT6351_PMIC_REG_BASE+0x0206)) +#define MT6351_TEST_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0208)) +#define MT6351_TEST_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x020A)) +#define MT6351_TESTMODE_SW ((unsigned int)(MT6351_PMIC_REG_BASE+0x020C)) +#define MT6351_EN_STATUS1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x020E)) +#define MT6351_EN_STATUS2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0210)) +#define MT6351_OCSTATUS1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0212)) +#define MT6351_OCSTATUS2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0214)) +#define MT6351_PGDEBSTATUS0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0216)) +#define MT6351_PGDEBSTATU1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0218)) +#define MT6351_PGSTATUS0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x021A)) +#define MT6351_PGSTATUS1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x021C)) +#define MT6351_THERMALSTATUS ((unsigned int)(MT6351_PMIC_REG_BASE+0x021E)) +#define MT6351_TOPSTATUS ((unsigned int)(MT6351_PMIC_REG_BASE+0x0220)) +#define MT6351_TDSEL_CON ((unsigned int)(MT6351_PMIC_REG_BASE+0x0222)) +#define MT6351_RDSEL_CON ((unsigned int)(MT6351_PMIC_REG_BASE+0x0224)) +#define MT6351_SMT_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0226)) +#define MT6351_SMT_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0228)) +#define MT6351_SMT_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x022A)) +#define MT6351_DRV_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x022C)) +#define MT6351_DRV_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x022E)) +#define MT6351_DRV_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0230)) +#define MT6351_DRV_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0232)) +#define MT6351_TOP_STATUS ((unsigned int)(MT6351_PMIC_REG_BASE+0x0234)) +#define MT6351_TOP_STATUS_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0236)) +#define MT6351_TOP_STATUS_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0238)) +#define MT6351_TOP_CKPDN_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x023A)) +#define MT6351_TOP_CKPDN_CON0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x023C)) +#define MT6351_TOP_CKPDN_CON0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x023E)) +#define MT6351_TOP_CKPDN_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0240)) +#define MT6351_TOP_CKPDN_CON1_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0242)) +#define MT6351_TOP_CKPDN_CON1_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0244)) +#define MT6351_TOP_CKPDN_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0246)) +#define MT6351_TOP_CKPDN_CON2_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0248)) +#define MT6351_TOP_CKPDN_CON2_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x024A)) +#define MT6351_TOP_CKPDN_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x024C)) +#define MT6351_TOP_CKPDN_CON3_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x024E)) +#define MT6351_TOP_CKPDN_CON3_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0250)) +#define MT6351_TOP_CKPDN_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0252)) +#define MT6351_TOP_CKPDN_CON4_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0254)) +#define MT6351_TOP_CKPDN_CON4_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0256)) +#define MT6351_TOP_CKPDN_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0258)) +#define MT6351_TOP_CKPDN_CON5_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x025A)) +#define MT6351_TOP_CKPDN_CON5_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x025C)) +#define MT6351_TOP_CKSEL_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x025E)) +#define MT6351_TOP_CKSEL_CON0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0260)) +#define MT6351_TOP_CKSEL_CON0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0262)) +#define MT6351_TOP_CKSEL_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0264)) +#define MT6351_TOP_CKSEL_CON1_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0266)) +#define MT6351_TOP_CKSEL_CON1_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0268)) +#define MT6351_TOP_CKSEL_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x026A)) +#define MT6351_TOP_CKSEL_CON2_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x026C)) +#define MT6351_TOP_CKSEL_CON2_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x026E)) +#define MT6351_TOP_CKSEL_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0270)) +#define MT6351_TOP_CKSEL_CON3_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0272)) +#define MT6351_TOP_CKSEL_CON3_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0274)) +#define MT6351_TOP_CKDIVSEL_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0276)) +#define MT6351_TOP_CKDIVSEL_CON0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0278)) +#define MT6351_TOP_CKDIVSEL_CON0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x027A)) +#define MT6351_TOP_CKDIVSEL_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x027C)) +#define MT6351_TOP_CKDIVSEL_CON1_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x027E)) +#define MT6351_TOP_CKDIVSEL_CON1_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0280)) +#define MT6351_TOP_CKHWEN_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0282)) +#define MT6351_TOP_CKHWEN_CON0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0284)) +#define MT6351_TOP_CKHWEN_CON0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0286)) +#define MT6351_TOP_CKHWEN_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0288)) +#define MT6351_TOP_CKHWEN_CON1_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x028A)) +#define MT6351_TOP_CKHWEN_CON1_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x028C)) +#define MT6351_TOP_CKHWEN_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x028E)) +#define MT6351_TOP_CKHWEN_CON2_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0290)) +#define MT6351_TOP_CKHWEN_CON2_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0292)) +#define MT6351_TOP_CKTST_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0294)) +#define MT6351_TOP_CKTST_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0296)) +#define MT6351_TOP_CKTST_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0298)) +#define MT6351_TOP_CLKSQ ((unsigned int)(MT6351_PMIC_REG_BASE+0x029A)) +#define MT6351_TOP_CLKSQ_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x029C)) +#define MT6351_TOP_CLKSQ_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x029E)) +#define MT6351_TOP_CLKSQ_RTC ((unsigned int)(MT6351_PMIC_REG_BASE+0x02A0)) +#define MT6351_TOP_CLKSQ_RTC_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02A2)) +#define MT6351_TOP_CLKSQ_RTC_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02A4)) +#define MT6351_TOP_CLK_TRIM ((unsigned int)(MT6351_PMIC_REG_BASE+0x02A6)) +#define MT6351_TOP_RST_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02A8)) +#define MT6351_TOP_RST_CON0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02AA)) +#define MT6351_TOP_RST_CON0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02AC)) +#define MT6351_TOP_RST_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02AE)) +#define MT6351_TOP_RST_CON1_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02B0)) +#define MT6351_TOP_RST_CON1_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02B2)) +#define MT6351_TOP_RST_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02B4)) +#define MT6351_TOP_RST_MISC ((unsigned int)(MT6351_PMIC_REG_BASE+0x02B6)) +#define MT6351_TOP_RST_MISC_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02B8)) +#define MT6351_TOP_RST_MISC_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02BA)) +#define MT6351_TOP_RST_STATUS ((unsigned int)(MT6351_PMIC_REG_BASE+0x02BC)) +#define MT6351_TOP_RST_STATUS_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02BE)) +#define MT6351_TOP_RST_STATUS_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02C0)) +#define MT6351_INT_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02C2)) +#define MT6351_INT_CON0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02C4)) +#define MT6351_INT_CON0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02C6)) +#define MT6351_INT_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02C8)) +#define MT6351_INT_CON1_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02CA)) +#define MT6351_INT_CON1_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02CC)) +#define MT6351_INT_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02CE)) +#define MT6351_INT_CON2_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02D0)) +#define MT6351_INT_CON2_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02D2)) +#define MT6351_INT_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02D4)) +#define MT6351_INT_CON3_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02D6)) +#define MT6351_INT_CON3_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02D8)) +#define MT6351_INT_MISC_CON ((unsigned int)(MT6351_PMIC_REG_BASE+0x02DA)) +#define MT6351_INT_MISC_CON_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x02DC)) +#define MT6351_INT_MISC_CON_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x02DE)) +#define MT6351_INT_STATUS0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02E0)) +#define MT6351_INT_STATUS1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02E2)) +#define MT6351_INT_STATUS2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02E4)) +#define MT6351_INT_STATUS3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02E6)) +#define MT6351_OC_GEAR_0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02E8)) +#define MT6351_FQMTR_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02EA)) +#define MT6351_FQMTR_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02EC)) +#define MT6351_FQMTR_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x02EE)) +#define MT6351_RG_SPI_CON ((unsigned int)(MT6351_PMIC_REG_BASE+0x02F0)) +#define MT6351_DEW_DIO_EN ((unsigned int)(MT6351_PMIC_REG_BASE+0x02F2)) +#define MT6351_DEW_READ_TEST ((unsigned int)(MT6351_PMIC_REG_BASE+0x02F4)) +#define MT6351_DEW_WRITE_TEST ((unsigned int)(MT6351_PMIC_REG_BASE+0x02F6)) +#define MT6351_DEW_CRC_SWRST ((unsigned int)(MT6351_PMIC_REG_BASE+0x02F8)) +#define MT6351_DEW_CRC_EN ((unsigned int)(MT6351_PMIC_REG_BASE+0x02FA)) +#define MT6351_DEW_CRC_VAL ((unsigned int)(MT6351_PMIC_REG_BASE+0x02FC)) +#define MT6351_DEW_DBG_MON_SEL ((unsigned int)(MT6351_PMIC_REG_BASE+0x02FE)) +#define MT6351_DEW_CIPHER_KEY_SEL ((unsigned int)(MT6351_PMIC_REG_BASE+0x0300)) +#define MT6351_DEW_CIPHER_IV_SEL ((unsigned int)(MT6351_PMIC_REG_BASE+0x0302)) +#define MT6351_DEW_CIPHER_EN ((unsigned int)(MT6351_PMIC_REG_BASE+0x0304)) +#define MT6351_DEW_CIPHER_RDY ((unsigned int)(MT6351_PMIC_REG_BASE+0x0306)) +#define MT6351_DEW_CIPHER_MODE ((unsigned int)(MT6351_PMIC_REG_BASE+0x0308)) +#define MT6351_DEW_CIPHER_SWRST ((unsigned int)(MT6351_PMIC_REG_BASE+0x030A)) +#define MT6351_DEW_RDDMY_NO ((unsigned int)(MT6351_PMIC_REG_BASE+0x030C)) +#define MT6351_INT_TYPE_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x030E)) +#define MT6351_INT_TYPE_CON0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0310)) +#define MT6351_INT_TYPE_CON0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0312)) +#define MT6351_INT_TYPE_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0314)) +#define MT6351_INT_TYPE_CON1_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0316)) +#define MT6351_INT_TYPE_CON1_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0318)) +#define MT6351_INT_TYPE_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x031A)) +#define MT6351_INT_TYPE_CON2_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x031C)) +#define MT6351_INT_TYPE_CON2_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x031E)) +#define MT6351_INT_TYPE_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0320)) +#define MT6351_INT_TYPE_CON3_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0322)) +#define MT6351_INT_TYPE_CON3_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0324)) +#define MT6351_INT_STA ((unsigned int)(MT6351_PMIC_REG_BASE+0x0326)) +#define MT6351_BUCK_ALL_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0400)) +#define MT6351_BUCK_ALL_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0402)) +#define MT6351_BUCK_ALL_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0404)) +#define MT6351_BUCK_ALL_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0406)) +#define MT6351_BUCK_ALL_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0408)) +#define MT6351_BUCK_ALL_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x040A)) +#define MT6351_BUCK_ALL_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x040C)) +#define MT6351_BUCK_DLC_VPA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x040E)) +#define MT6351_BUCK_DLC_VPA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0410)) +#define MT6351_BUCK_DLC_VPA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0412)) +#define MT6351_BUCK_DVS_VPA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0414)) +#define MT6351_BUCK_VOW_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0416)) +#define MT6351_BUCK_VOW_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0418)) +#define MT6351_BUCK_VOW_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x041A)) +#define MT6351_BUCK_VOW_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x041C)) +#define MT6351_BUCK_OC_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x041E)) +#define MT6351_BUCK_OC_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0420)) +#define MT6351_BUCK_OC_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0422)) +#define MT6351_BUCK_OC_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0424)) +#define MT6351_BUCK_OC_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0426)) +#define MT6351_BUCK_OC_VCORE_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0428)) +#define MT6351_BUCK_OC_VGPU_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x042A)) +#define MT6351_BUCK_OC_VMODEM_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x042C)) +#define MT6351_BUCK_OC_VMD1_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x042E)) +#define MT6351_BUCK_OC_VSRAM_MD_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0430)) +#define MT6351_BUCK_OC_VS1_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0432)) +#define MT6351_BUCK_OC_VS2_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0434)) +#define MT6351_BUCK_OC_VPA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0436)) +#define MT6351_SMPS_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0438)) +#define MT6351_SMPS_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x043A)) +#define MT6351_SMPS_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x043C)) +#define MT6351_SMPS_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x043E)) +#define MT6351_SMPS_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0440)) +#define MT6351_SMPS_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0442)) +#define MT6351_SMPS_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0444)) +#define MT6351_SMPS_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0446)) +#define MT6351_SMPS_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0448)) +#define MT6351_SMPS_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x044A)) +#define MT6351_SMPS_ANA_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x044C)) +#define MT6351_VCORE_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x044E)) +#define MT6351_VCORE_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0450)) +#define MT6351_VCORE_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0452)) +#define MT6351_VCORE_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0454)) +#define MT6351_VCORE_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0456)) +#define MT6351_VCORE_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0458)) +#define MT6351_VCORE_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x045A)) +#define MT6351_VCORE_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x045C)) +#define MT6351_VCORE_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x045E)) +#define MT6351_VCORE_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0460)) +#define MT6351_VGPU_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0462)) +#define MT6351_VGPU_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0464)) +#define MT6351_VGPU_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0466)) +#define MT6351_VGPU_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0468)) +#define MT6351_VGPU_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x046A)) +#define MT6351_VGPU_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x046C)) +#define MT6351_VGPU_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x046E)) +#define MT6351_VGPU_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0470)) +#define MT6351_VGPU_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0472)) +#define MT6351_VGPU_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0474)) +#define MT6351_VSRAM_MD_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0476)) +#define MT6351_VSRAM_MD_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0478)) +#define MT6351_VSRAM_MD_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x047A)) +#define MT6351_VSRAM_MD_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x047C)) +#define MT6351_VSRAM_MD_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x047E)) +#define MT6351_VSRAM_MD_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0480)) +#define MT6351_VSRAM_MD_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0482)) +#define MT6351_VSRAM_MD_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0484)) +#define MT6351_VSRAM_MD_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0486)) +#define MT6351_VSRAM_MD_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0488)) +#define MT6351_VMODEM_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x048A)) +#define MT6351_VMODEM_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x048C)) +#define MT6351_VMODEM_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x048E)) +#define MT6351_VMODEM_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0490)) +#define MT6351_VMODEM_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0492)) +#define MT6351_VMODEM_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0494)) +#define MT6351_VMODEM_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0496)) +#define MT6351_VMODEM_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0498)) +#define MT6351_VMODEM_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x049A)) +#define MT6351_VMODEM_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x049C)) +#define MT6351_VMD1_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x049E)) +#define MT6351_VMD1_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04A0)) +#define MT6351_VMD1_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04A2)) +#define MT6351_VMD1_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04A4)) +#define MT6351_VMD1_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04A6)) +#define MT6351_VMD1_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04A8)) +#define MT6351_VMD1_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04AA)) +#define MT6351_VMD1_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04AC)) +#define MT6351_VMD1_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04AE)) +#define MT6351_VMD1_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04B0)) +#define MT6351_VS1_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04B2)) +#define MT6351_VS1_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04B4)) +#define MT6351_VS1_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04B6)) +#define MT6351_VS1_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04B8)) +#define MT6351_VS1_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04BA)) +#define MT6351_VS1_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04BC)) +#define MT6351_VS1_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04BE)) +#define MT6351_VS1_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04C0)) +#define MT6351_VS1_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04C2)) +#define MT6351_VS1_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04C4)) +#define MT6351_VS2_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04C6)) +#define MT6351_VS2_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04C8)) +#define MT6351_VS2_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04CA)) +#define MT6351_VS2_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04CC)) +#define MT6351_VS2_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04CE)) +#define MT6351_VS2_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04D0)) +#define MT6351_VS2_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04D2)) +#define MT6351_VS2_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04D4)) +#define MT6351_VS2_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04D6)) +#define MT6351_VS2_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04D8)) +#define MT6351_VPA_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04DA)) +#define MT6351_VPA_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04DC)) +#define MT6351_VPA_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04DE)) +#define MT6351_VPA_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04E0)) +#define MT6351_VPA_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04E2)) +#define MT6351_VPA_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x04E4)) +#define MT6351_BUCK_VCORE_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0600)) +#define MT6351_BUCK_VCORE_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0602)) +#define MT6351_BUCK_VCORE_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0604)) +#define MT6351_BUCK_VCORE_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0606)) +#define MT6351_BUCK_VCORE_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0608)) +#define MT6351_BUCK_VCORE_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x060A)) +#define MT6351_BUCK_VCORE_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x060C)) +#define MT6351_BUCK_VCORE_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x060E)) +#define MT6351_BUCK_VCORE_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0610)) +#define MT6351_BUCK_VCORE_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0612)) +#define MT6351_BUCK_VGPU_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0614)) +#define MT6351_BUCK_VGPU_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0616)) +#define MT6351_BUCK_VGPU_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0618)) +#define MT6351_BUCK_VGPU_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x061A)) +#define MT6351_BUCK_VGPU_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x061C)) +#define MT6351_BUCK_VGPU_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x061E)) +#define MT6351_BUCK_VGPU_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0620)) +#define MT6351_BUCK_VGPU_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0622)) +#define MT6351_BUCK_VGPU_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0624)) +#define MT6351_BUCK_VGPU_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0626)) +#define MT6351_BUCK_VMODEM_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0628)) +#define MT6351_BUCK_VMODEM_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x062A)) +#define MT6351_BUCK_VMODEM_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x062C)) +#define MT6351_BUCK_VMODEM_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x062E)) +#define MT6351_BUCK_VMODEM_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0630)) +#define MT6351_BUCK_VMODEM_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0632)) +#define MT6351_BUCK_VMODEM_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0634)) +#define MT6351_BUCK_VMODEM_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0636)) +#define MT6351_BUCK_VMODEM_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0638)) +#define MT6351_BUCK_VMODEM_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x063A)) +#define MT6351_BUCK_VMD1_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x063C)) +#define MT6351_BUCK_VMD1_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x063E)) +#define MT6351_BUCK_VMD1_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0640)) +#define MT6351_BUCK_VMD1_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0642)) +#define MT6351_BUCK_VMD1_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0644)) +#define MT6351_BUCK_VMD1_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0646)) +#define MT6351_BUCK_VMD1_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0648)) +#define MT6351_BUCK_VMD1_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x064A)) +#define MT6351_BUCK_VMD1_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x064C)) +#define MT6351_BUCK_VMD1_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x064E)) +#define MT6351_BUCK_VSRAM_MD_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0650)) +#define MT6351_BUCK_VSRAM_MD_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0652)) +#define MT6351_BUCK_VSRAM_MD_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0654)) +#define MT6351_BUCK_VSRAM_MD_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0656)) +#define MT6351_BUCK_VSRAM_MD_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0658)) +#define MT6351_BUCK_VSRAM_MD_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x065A)) +#define MT6351_BUCK_VSRAM_MD_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x065C)) +#define MT6351_BUCK_VSRAM_MD_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x065E)) +#define MT6351_BUCK_VSRAM_MD_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0660)) +#define MT6351_BUCK_VSRAM_MD_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0662)) +#define MT6351_BUCK_VS1_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0664)) +#define MT6351_BUCK_VS1_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0666)) +#define MT6351_BUCK_VS1_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0668)) +#define MT6351_BUCK_VS1_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x066A)) +#define MT6351_BUCK_VS1_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x066C)) +#define MT6351_BUCK_VS1_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x066E)) +#define MT6351_BUCK_VS1_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0670)) +#define MT6351_BUCK_VS1_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0672)) +#define MT6351_BUCK_VS1_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0674)) +#define MT6351_BUCK_VS1_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0676)) +#define MT6351_BUCK_VS2_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0678)) +#define MT6351_BUCK_VS2_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x067A)) +#define MT6351_BUCK_VS2_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x067C)) +#define MT6351_BUCK_VS2_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x067E)) +#define MT6351_BUCK_VS2_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0680)) +#define MT6351_BUCK_VS2_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0682)) +#define MT6351_BUCK_VS2_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0684)) +#define MT6351_BUCK_VS2_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0686)) +#define MT6351_BUCK_VS2_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0688)) +#define MT6351_BUCK_VS2_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x068A)) +#define MT6351_BUCK_VPA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x068C)) +#define MT6351_BUCK_VPA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x068E)) +#define MT6351_BUCK_VPA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0690)) +#define MT6351_BUCK_VPA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0692)) +#define MT6351_BUCK_VPA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0694)) +#define MT6351_BUCK_VPA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0696)) +#define MT6351_BUCK_VPA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0698)) +#define MT6351_BUCK_VPA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x069A)) +#define MT6351_BUCK_VPA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x069C)) +#define MT6351_BUCK_VPA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x069E)) +#define MT6351_BUCK_VSRAM_PROC_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06A0)) +#define MT6351_BUCK_VSRAM_PROC_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06A2)) +#define MT6351_BUCK_VSRAM_PROC_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06A4)) +#define MT6351_BUCK_VSRAM_PROC_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06A6)) +#define MT6351_BUCK_VSRAM_PROC_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06A8)) +#define MT6351_BUCK_VSRAM_PROC_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06AA)) +#define MT6351_BUCK_VSRAM_PROC_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06AC)) +#define MT6351_BUCK_VSRAM_PROC_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06AE)) +#define MT6351_BUCK_VSRAM_PROC_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06B0)) +#define MT6351_BUCK_VSRAM_PROC_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06B2)) +#define MT6351_BUCK_K_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06B4)) +#define MT6351_BUCK_K_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06B6)) +#define MT6351_BUCK_K_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06B8)) +#define MT6351_BUCK_K_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06BA)) +#define MT6351_WDTDBG_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06BC)) +#define MT6351_WDTDBG_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06BE)) +#define MT6351_WDTDBG_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06C0)) +#define MT6351_WDTDBG_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x06C2)) +#define MT6351_ZCD_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0800)) +#define MT6351_ZCD_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0802)) +#define MT6351_ZCD_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0804)) +#define MT6351_ZCD_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0806)) +#define MT6351_ZCD_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0808)) +#define MT6351_ZCD_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x080A)) +#define MT6351_ISINKA_ANA_CON_0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x080C)) +#define MT6351_ISINKB_ANA_CON_0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x080E)) +#define MT6351_ISINK0_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0810)) +#define MT6351_ISINK0_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0812)) +#define MT6351_ISINK0_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0814)) +#define MT6351_ISINK0_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0816)) +#define MT6351_ISINK1_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0818)) +#define MT6351_ISINK1_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x081A)) +#define MT6351_ISINK1_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x081C)) +#define MT6351_ISINK1_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x081E)) +#define MT6351_ISINK4_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0820)) +#define MT6351_ISINK4_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0822)) +#define MT6351_ISINK4_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0824)) +#define MT6351_ISINK4_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0826)) +#define MT6351_ISINK5_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0828)) +#define MT6351_ISINK5_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x082A)) +#define MT6351_ISINK5_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x082C)) +#define MT6351_ISINK5_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x082E)) +#define MT6351_ISINK_ANA1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0830)) +#define MT6351_ISINK_PHASE_DLY ((unsigned int)(MT6351_PMIC_REG_BASE+0x0832)) +#define MT6351_ISINK_SFSTR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0834)) +#define MT6351_ISINK_EN_CTRL ((unsigned int)(MT6351_PMIC_REG_BASE+0x0836)) +#define MT6351_ISINK_MODE_CTRL ((unsigned int)(MT6351_PMIC_REG_BASE+0x0838)) +#define MT6351_ISINK_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x083A)) +#define MT6351_ISINK2_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x083C)) +#define MT6351_ISINK3_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x083E)) +#define MT6351_ISINK6_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0840)) +#define MT6351_ISINK7_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0842)) +#define MT6351_ISINK_ANA1_SMPL ((unsigned int)(MT6351_PMIC_REG_BASE+0x0844)) +#define MT6351_ISINK_PHASE_DLY_SMPL ((unsigned int)(MT6351_PMIC_REG_BASE+0x0846)) +#define MT6351_ISINK_EN_CTRL_SMPL ((unsigned int)(MT6351_PMIC_REG_BASE+0x0848)) +#define MT6351_CHRIND_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x084A)) +#define MT6351_CHRIND_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x084C)) +#define MT6351_CHRIND_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x084E)) +#define MT6351_CHRIND_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0850)) +#define MT6351_CHRIND_EN_CTRL ((unsigned int)(MT6351_PMIC_REG_BASE+0x0852)) +#define MT6351_LDO_VA18_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A00)) +#define MT6351_LDO_VA18_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A02)) +#define MT6351_LDO_VTCXO24_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A04)) +#define MT6351_LDO_VTCXO24_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A06)) +#define MT6351_LDO_VTCXO28_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A08)) +#define MT6351_LDO_VTCXO28_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A0A)) +#define MT6351_LDO_VCN28_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A0C)) +#define MT6351_LDO_VCN28_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A0E)) +#define MT6351_LDO_VCN28_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A10)) +#define MT6351_LDO_VCAMA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A12)) +#define MT6351_LDO_VCAMA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A14)) +#define MT6351_LDO_VUSB33_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A16)) +#define MT6351_LDO_VUSB33_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A18)) +#define MT6351_LDO_VUSB33_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A1A)) +#define MT6351_LDO_VSIM1_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A1C)) +#define MT6351_LDO_VSIM1_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A1E)) +#define MT6351_LDO_VSIM1_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A20)) +#define MT6351_LDO_VSIM2_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A22)) +#define MT6351_LDO_VSIM2_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A24)) +#define MT6351_LDO_VSIM2_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A26)) +#define MT6351_LDO_VEMC_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A28)) +#define MT6351_LDO_VEMC_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A2A)) +#define MT6351_LDO_VEMC_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A2C)) +#define MT6351_LDO_VMCH_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A2E)) +#define MT6351_LDO_VMCH_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A30)) +#define MT6351_LDO_VMCH_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A32)) +#define MT6351_LDO_VIO28_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A34)) +#define MT6351_LDO_VIO28_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A36)) +#define MT6351_LDO_VIO28_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A38)) +#define MT6351_LDO_VIBR_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A3A)) +#define MT6351_LDO_VIBR_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A3C)) +#define MT6351_LDO_VIBR_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A3E)) +#define MT6351_LDO_VCAMD_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A40)) +#define MT6351_LDO_VCAMD_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A42)) +#define MT6351_LDO_VCAMD_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A44)) +#define MT6351_LDO_VRF18_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A46)) +#define MT6351_LDO_VRF18_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A48)) +#define MT6351_LDO_VRF18_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A4A)) +#define MT6351_LDO_VIO18_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A4C)) +#define MT6351_LDO_VIO18_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A4E)) +#define MT6351_LDO_VIO18_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A50)) +#define MT6351_LDO_VCN18_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A52)) +#define MT6351_LDO_VCN18_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A54)) +#define MT6351_LDO_VCN18_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A56)) +#define MT6351_LDO_VCAMIO_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A58)) +#define MT6351_LDO_VCAMIO_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A5A)) +#define MT6351_LDO_VCAMIO_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A5C)) +#define MT6351_LDO_VSRAM_PROC_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A5E)) +#define MT6351_LDO_VSRAM_PROC_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A60)) +#define MT6351_LDO_VSRAM_PROC_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A62)) +#define MT6351_LDO_VXO22_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A64)) +#define MT6351_LDO_VXO22_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A66)) +#define MT6351_LDO_VRF12_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A68)) +#define MT6351_LDO_VRF12_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A6A)) +#define MT6351_LDO_VRF12_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A6C)) +#define MT6351_LDO_VA10_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A6E)) +#define MT6351_LDO_VA10_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A70)) +#define MT6351_LDO_VA10_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A72)) +#define MT6351_LDO_VDRAM_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A74)) +#define MT6351_LDO_VDRAM_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A76)) +#define MT6351_LDO_VDRAM_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A78)) +#define MT6351_LDO_VMIPI_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A7A)) +#define MT6351_LDO_VMIPI_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A7C)) +#define MT6351_LDO_VMIPI_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A7E)) +#define MT6351_LDO_VGP3_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A80)) +#define MT6351_LDO_VGP3_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A82)) +#define MT6351_LDO_VGP3_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A84)) +#define MT6351_LDO_VBIF28_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A86)) +#define MT6351_LDO_VBIF28_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A88)) +#define MT6351_LDO_VBIF28_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A8A)) +#define MT6351_LDO_VEFUSE_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A8C)) +#define MT6351_LDO_VEFUSE_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A8E)) +#define MT6351_LDO_VEFUSE_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A90)) +#define MT6351_LDO_VCN33_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A92)) +#define MT6351_LDO_VCN33_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A94)) +#define MT6351_LDO_VCN33_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A96)) +#define MT6351_LDO_VCN33_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A98)) +#define MT6351_LDO_VCN33_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A9A)) +#define MT6351_LDO_VLDO28_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A9C)) +#define MT6351_LDO_VLDO28_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0A9E)) +#define MT6351_LDO_VLDO28_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AA0)) +#define MT6351_LDO_VLDO28_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AA2)) +#define MT6351_LDO_VLDO28_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AA4)) +#define MT6351_LDO_RSV_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AA6)) +#define MT6351_LDO_RSV_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AA8)) +#define MT6351_LDO_VMC_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AAA)) +#define MT6351_LDO_VMC_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AAC)) +#define MT6351_LDO_VMC_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AAE)) +#define MT6351_LDO_VMC_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AB0)) +#define MT6351_LDO_K_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AB2)) +#define MT6351_LDO_K_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AB4)) +#define MT6351_LDO_K_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AB6)) +#define MT6351_LDO_OCFB0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AB8)) +#define MT6351_VRTC_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ABA)) +#define MT6351_ALDO_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ABC)) +#define MT6351_DLDO_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ABE)) +#define MT6351_SLDO20_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AC0)) +#define MT6351_SLDO14_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AC2)) +#define MT6351_VXO22_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AC4)) +#define MT6351_VTCXO28_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AC6)) +#define MT6351_VTCXO24_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AC8)) +#define MT6351_VBIF28_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ACA)) +#define MT6351_VCN28_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ACC)) +#define MT6351_VMCH_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ACE)) +#define MT6351_VMCH_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AD0)) +#define MT6351_VEMC_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AD2)) +#define MT6351_VEMC_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AD4)) +#define MT6351_VCAMA_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AD6)) +#define MT6351_VCAMA_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AD8)) +#define MT6351_VCN33_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ADA)) +#define MT6351_VCN33_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ADC)) +#define MT6351_VIO28_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ADE)) +#define MT6351_VIO28_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AE0)) +#define MT6351_VMC_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AE2)) +#define MT6351_VMC_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AE4)) +#define MT6351_VIBR_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AE6)) +#define MT6351_VIBR_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AE8)) +#define MT6351_VUSB33_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AEA)) +#define MT6351_VUSB33_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AEC)) +#define MT6351_VSIM1_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AEE)) +#define MT6351_VSIM1_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AF0)) +#define MT6351_VSIM2_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AF2)) +#define MT6351_VSIM2_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AF4)) +#define MT6351_VEFUSE_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AF6)) +#define MT6351_VEFUSE_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AF8)) +#define MT6351_VA18_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AFA)) +#define MT6351_VGP3_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AFC)) +#define MT6351_VGP3_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0AFE)) +#define MT6351_VCAMD_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B00)) +#define MT6351_VCAMD_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B02)) +#define MT6351_VIO18_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B04)) +#define MT6351_VIO18_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B06)) +#define MT6351_VRF18_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B08)) +#define MT6351_VRF18_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B0A)) +#define MT6351_VRF12_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B0C)) +#define MT6351_VRF12_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B0E)) +#define MT6351_VA10_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B10)) +#define MT6351_VA10_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B12)) +#define MT6351_VCAMIO_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B14)) +#define MT6351_VCAMIO_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B16)) +#define MT6351_VCN18_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B18)) +#define MT6351_VCN18_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B1A)) +#define MT6351_VMIPI_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B1C)) +#define MT6351_VMIPI_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B1E)) +#define MT6351_VSRAM_PROC_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B20)) +#define MT6351_VDRAM_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B22)) +#define MT6351_VDRAM_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B24)) +#define MT6351_VLDO28_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B26)) +#define MT6351_VLDO28_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B28)) +#define MT6351_BIF_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B2A)) +#define MT6351_BIF_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B2C)) +#define MT6351_BIF_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B2E)) +#define MT6351_BIF_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B30)) +#define MT6351_BIF_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B32)) +#define MT6351_BIF_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B34)) +#define MT6351_BIF_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B36)) +#define MT6351_BIF_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B38)) +#define MT6351_BIF_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B3A)) +#define MT6351_BIF_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B3C)) +#define MT6351_BIF_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B3E)) +#define MT6351_BIF_CON11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B40)) +#define MT6351_BIF_CON12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B42)) +#define MT6351_BIF_CON13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B44)) +#define MT6351_BIF_CON14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B46)) +#define MT6351_BIF_CON15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B48)) +#define MT6351_BIF_CON16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B4A)) +#define MT6351_BIF_CON17 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B4C)) +#define MT6351_BIF_CON18 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B4E)) +#define MT6351_BIF_CON19 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B50)) +#define MT6351_BIF_CON20 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B52)) +#define MT6351_BIF_CON21 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B54)) +#define MT6351_BIF_CON22 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B56)) +#define MT6351_BIF_CON23 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B58)) +#define MT6351_BIF_CON24 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B5A)) +#define MT6351_BIF_CON25 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B5C)) +#define MT6351_BIF_CON26 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B5E)) +#define MT6351_BIF_CON27 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B60)) +#define MT6351_BIF_CON28 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B62)) +#define MT6351_BIF_CON29 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B64)) +#define MT6351_BIF_CON30 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B66)) +#define MT6351_BIF_CON31 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B68)) +#define MT6351_BIF_CON32 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B6A)) +#define MT6351_BIF_CON33 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B6C)) +#define MT6351_BIF_CON34 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B6E)) +#define MT6351_BIF_CON35 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B70)) +#define MT6351_BIF_CON36 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B72)) +#define MT6351_BIF_BAT_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B74)) +#define MT6351_BIF_CON37 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B76)) +#define MT6351_BIF_CON38 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B78)) +#define MT6351_BIF_CON39 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0B7A)) +#define MT6351_OTP_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C00)) +#define MT6351_OTP_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C02)) +#define MT6351_OTP_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C04)) +#define MT6351_OTP_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C06)) +#define MT6351_OTP_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C08)) +#define MT6351_OTP_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C0A)) +#define MT6351_OTP_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C0C)) +#define MT6351_OTP_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C0E)) +#define MT6351_OTP_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C10)) +#define MT6351_OTP_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C12)) +#define MT6351_OTP_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C14)) +#define MT6351_OTP_CON11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C16)) +#define MT6351_OTP_CON12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C18)) +#define MT6351_OTP_CON13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C1A)) +#define MT6351_OTP_CON14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C1C)) +#define MT6351_OTP_DOUT_0_15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C1E)) +#define MT6351_OTP_DOUT_16_31 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C20)) +#define MT6351_OTP_DOUT_32_47 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C22)) +#define MT6351_OTP_DOUT_48_63 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C24)) +#define MT6351_OTP_DOUT_64_79 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C26)) +#define MT6351_OTP_DOUT_80_95 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C28)) +#define MT6351_OTP_DOUT_96_111 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C2A)) +#define MT6351_OTP_DOUT_112_127 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C2C)) +#define MT6351_OTP_DOUT_128_143 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C2E)) +#define MT6351_OTP_DOUT_144_159 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C30)) +#define MT6351_OTP_DOUT_160_175 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C32)) +#define MT6351_OTP_DOUT_176_191 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C34)) +#define MT6351_OTP_DOUT_192_207 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C36)) +#define MT6351_OTP_DOUT_208_223 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C38)) +#define MT6351_OTP_DOUT_224_239 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C3A)) +#define MT6351_OTP_DOUT_240_255 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C3C)) +#define MT6351_OTP_DOUT_256_271 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C3E)) +#define MT6351_OTP_DOUT_272_287 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C40)) +#define MT6351_OTP_DOUT_288_303 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C42)) +#define MT6351_OTP_DOUT_304_319 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C44)) +#define MT6351_OTP_DOUT_320_335 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C46)) +#define MT6351_OTP_DOUT_336_351 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C48)) +#define MT6351_OTP_DOUT_352_367 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C4A)) +#define MT6351_OTP_DOUT_368_383 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C4C)) +#define MT6351_OTP_DOUT_384_399 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C4E)) +#define MT6351_OTP_DOUT_400_415 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C50)) +#define MT6351_OTP_DOUT_416_431 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C52)) +#define MT6351_OTP_DOUT_432_447 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C54)) +#define MT6351_OTP_DOUT_448_463 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C56)) +#define MT6351_OTP_DOUT_464_479 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C58)) +#define MT6351_OTP_DOUT_480_495 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C5A)) +#define MT6351_OTP_DOUT_496_511 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C5C)) +#define MT6351_OTP_VAL_0_15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C5E)) +#define MT6351_OTP_VAL_16_31 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C60)) +#define MT6351_OTP_VAL_32_47 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C62)) +#define MT6351_OTP_VAL_48_63 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C64)) +#define MT6351_OTP_VAL_64_79 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C66)) +#define MT6351_OTP_VAL_80_95 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C68)) +#define MT6351_OTP_VAL_96_111 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C6A)) +#define MT6351_OTP_VAL_112_127 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C6C)) +#define MT6351_OTP_VAL_128_143 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C6E)) +#define MT6351_OTP_VAL_144_159 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C70)) +#define MT6351_OTP_VAL_160_175 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C72)) +#define MT6351_OTP_VAL_176_191 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C74)) +#define MT6351_OTP_VAL_192_207 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C76)) +#define MT6351_OTP_VAL_208_223 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C78)) +#define MT6351_OTP_VAL_224_239 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C7A)) +#define MT6351_OTP_VAL_240_255 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C7C)) +#define MT6351_OTP_VAL_256_271 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C7E)) +#define MT6351_OTP_VAL_272_287 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C80)) +#define MT6351_OTP_VAL_288_303 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C82)) +#define MT6351_OTP_VAL_304_319 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C84)) +#define MT6351_OTP_VAL_320_335 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C86)) +#define MT6351_OTP_VAL_336_351 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C88)) +#define MT6351_OTP_VAL_352_367 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C8A)) +#define MT6351_OTP_VAL_368_383 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C8C)) +#define MT6351_OTP_VAL_384_399 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C8E)) +#define MT6351_OTP_VAL_400_415 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C90)) +#define MT6351_OTP_VAL_416_431 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C92)) +#define MT6351_OTP_VAL_432_447 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C94)) +#define MT6351_OTP_VAL_448_463 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C96)) +#define MT6351_OTP_VAL_464_479 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C98)) +#define MT6351_OTP_VAL_480_495 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C9A)) +#define MT6351_OTP_VAL_496_511 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C9C)) +#define MT6351_RTC_MIX_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0C9E)) +#define MT6351_RTC_MIX_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CA0)) +#define MT6351_RTC_MIX_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CA2)) +#define MT6351_FGADC_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CA4)) +#define MT6351_FGADC_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CA6)) +#define MT6351_FGADC_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CA8)) +#define MT6351_FGADC_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CAA)) +#define MT6351_FGADC_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CAC)) +#define MT6351_FGADC_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CAE)) +#define MT6351_FGADC_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CB0)) +#define MT6351_FGADC_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CB2)) +#define MT6351_FGADC_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CB4)) +#define MT6351_FGADC_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CB6)) +#define MT6351_FGADC_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CB8)) +#define MT6351_FGADC_CON11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CBA)) +#define MT6351_FGADC_CON12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CBC)) +#define MT6351_FGADC_CON13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CBE)) +#define MT6351_FGADC_CON14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CC0)) +#define MT6351_FGADC_CON15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CC2)) +#define MT6351_FGADC_CON16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CC4)) +#define MT6351_FGADC_CON17 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CC6)) +#define MT6351_FGADC_CON18 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CC8)) +#define MT6351_FGADC_CON19 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CCA)) +#define MT6351_FGADC_CON20 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CCC)) +#define MT6351_FGADC_CON21 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CCE)) +#define MT6351_FGADC_CON22 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CD0)) +#define MT6351_FGADC_CON23 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CD2)) +#define MT6351_FGADC_CON24 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CD4)) +#define MT6351_FGADC_CON25 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CD6)) +#define MT6351_FGADC_CON26 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CD8)) +#define MT6351_FGADC_CON27 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CDA)) +#define MT6351_FGADC_CON28 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CDC)) +#define MT6351_FGADC_CON29 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CDE)) +#define MT6351_FGADC_CON30 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CE0)) +#define MT6351_FGADC_CON31 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CE2)) +#define MT6351_FGADC_CON32 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CE4)) +#define MT6351_FGADC_CON33 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CE6)) +#define MT6351_SYSTEM_INFO_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CE8)) +#define MT6351_SYSTEM_INFO_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CEA)) +#define MT6351_SYSTEM_INFO_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CEC)) +#define MT6351_SYSTEM_INFO_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CEE)) +#define MT6351_SYSTEM_INFO_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CF0)) +#define MT6351_AUDDEC_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CF2)) +#define MT6351_AUDDEC_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CF4)) +#define MT6351_AUDDEC_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CF6)) +#define MT6351_AUDDEC_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CF8)) +#define MT6351_AUDDEC_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CFA)) +#define MT6351_AUDDEC_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CFC)) +#define MT6351_AUDDEC_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0CFE)) +#define MT6351_AUDDEC_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D00)) +#define MT6351_AUDDEC_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D02)) +#define MT6351_AUDDEC_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D04)) +#define MT6351_AUDDEC_ANA_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D06)) +#define MT6351_AUDENC_ANA_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D08)) +#define MT6351_AUDENC_ANA_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D0A)) +#define MT6351_AUDENC_ANA_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D0C)) +#define MT6351_AUDENC_ANA_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D0E)) +#define MT6351_AUDENC_ANA_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D10)) +#define MT6351_AUDENC_ANA_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D12)) +#define MT6351_AUDENC_ANA_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D14)) +#define MT6351_AUDENC_ANA_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D16)) +#define MT6351_AUDENC_ANA_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D18)) +#define MT6351_AUDENC_ANA_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D1A)) +#define MT6351_AUDENC_ANA_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D1C)) +#define MT6351_AUDENC_ANA_CON11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D1E)) +#define MT6351_AUDENC_ANA_CON12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D20)) +#define MT6351_AUDENC_ANA_CON13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D22)) +#define MT6351_AUDENC_ANA_CON14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D24)) +#define MT6351_AUDENC_ANA_CON15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D26)) +#define MT6351_AUDENC_ANA_CON16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D28)) +#define MT6351_AUDNCP_CLKDIV_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D2A)) +#define MT6351_AUDNCP_CLKDIV_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D2C)) +#define MT6351_AUDNCP_CLKDIV_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D2E)) +#define MT6351_AUDNCP_CLKDIV_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D30)) +#define MT6351_AUDNCP_CLKDIV_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0D32)) +#define MT6351_AUXADC_ADC0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E00)) +#define MT6351_AUXADC_ADC1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E02)) +#define MT6351_AUXADC_ADC2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E04)) +#define MT6351_AUXADC_ADC3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E06)) +#define MT6351_AUXADC_ADC4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E08)) +#define MT6351_AUXADC_ADC5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E0A)) +#define MT6351_AUXADC_ADC6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E0C)) +#define MT6351_AUXADC_ADC7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E0E)) +#define MT6351_AUXADC_ADC8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E10)) +#define MT6351_AUXADC_ADC9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E12)) +#define MT6351_AUXADC_ADC10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E14)) +#define MT6351_AUXADC_ADC11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E16)) +#define MT6351_AUXADC_ADC12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E18)) +#define MT6351_AUXADC_ADC13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E1A)) +#define MT6351_AUXADC_ADC14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E1C)) +#define MT6351_AUXADC_ADC15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E1E)) +#define MT6351_AUXADC_ADC16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E20)) +#define MT6351_AUXADC_ADC17 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E22)) +#define MT6351_AUXADC_ADC18 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E24)) +#define MT6351_AUXADC_ADC19 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E26)) +#define MT6351_AUXADC_ADC20 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E28)) +#define MT6351_AUXADC_ADC21 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E2A)) +#define MT6351_AUXADC_ADC22 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E2C)) +#define MT6351_AUXADC_ADC23 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E2E)) +#define MT6351_AUXADC_ADC24 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E30)) +#define MT6351_AUXADC_ADC25 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E32)) +#define MT6351_AUXADC_ADC26 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E34)) +#define MT6351_AUXADC_ADC27 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E36)) +#define MT6351_AUXADC_ADC28 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E38)) +#define MT6351_AUXADC_ADC29 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E3A)) +#define MT6351_AUXADC_ADC30 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E3C)) +#define MT6351_AUXADC_ADC31 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E3E)) +#define MT6351_AUXADC_ADC32 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E40)) +#define MT6351_AUXADC_ADC33 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E42)) +#define MT6351_AUXADC_ADC34 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E44)) +#define MT6351_AUXADC_ADC35 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E46)) +#define MT6351_AUXADC_ADC36 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E48)) +#define MT6351_AUXADC_ADC37 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E4A)) +#define MT6351_AUXADC_ADC38 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E4C)) +#define MT6351_AUXADC_ADC39 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E4E)) +#define MT6351_AUXADC_BUF0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E50)) +#define MT6351_AUXADC_BUF1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E52)) +#define MT6351_AUXADC_BUF2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E54)) +#define MT6351_AUXADC_BUF3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E56)) +#define MT6351_AUXADC_BUF4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E58)) +#define MT6351_AUXADC_BUF5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E5A)) +#define MT6351_AUXADC_BUF6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E5C)) +#define MT6351_AUXADC_BUF7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E5E)) +#define MT6351_AUXADC_BUF8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E60)) +#define MT6351_AUXADC_BUF9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E62)) +#define MT6351_AUXADC_BUF10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E64)) +#define MT6351_AUXADC_BUF11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E66)) +#define MT6351_AUXADC_BUF12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E68)) +#define MT6351_AUXADC_BUF13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E6A)) +#define MT6351_AUXADC_BUF14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E6C)) +#define MT6351_AUXADC_BUF15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E6E)) +#define MT6351_AUXADC_BUF16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E70)) +#define MT6351_AUXADC_BUF17 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E72)) +#define MT6351_AUXADC_BUF18 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E74)) +#define MT6351_AUXADC_BUF19 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E76)) +#define MT6351_AUXADC_BUF20 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E78)) +#define MT6351_AUXADC_BUF21 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E7A)) +#define MT6351_AUXADC_BUF22 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E7C)) +#define MT6351_AUXADC_BUF23 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E7E)) +#define MT6351_AUXADC_BUF24 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E80)) +#define MT6351_AUXADC_BUF25 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E82)) +#define MT6351_AUXADC_BUF26 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E84)) +#define MT6351_AUXADC_BUF27 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E86)) +#define MT6351_AUXADC_BUF28 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E88)) +#define MT6351_AUXADC_BUF29 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E8A)) +#define MT6351_AUXADC_BUF30 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E8C)) +#define MT6351_AUXADC_BUF31 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E8E)) +#define MT6351_AUXADC_STA0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E90)) +#define MT6351_AUXADC_STA1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E92)) +#define MT6351_AUXADC_STA2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E94)) +#define MT6351_AUXADC_RQST0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E96)) +#define MT6351_AUXADC_RQST0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E98)) +#define MT6351_AUXADC_RQST0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E9A)) +#define MT6351_AUXADC_RQST1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E9C)) +#define MT6351_AUXADC_RQST1_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0E9E)) +#define MT6351_AUXADC_RQST1_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EA0)) +#define MT6351_AUXADC_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EA2)) +#define MT6351_AUXADC_CON0_SET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EA4)) +#define MT6351_AUXADC_CON0_CLR ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EA6)) +#define MT6351_AUXADC_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EA8)) +#define MT6351_AUXADC_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EAA)) +#define MT6351_AUXADC_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EAC)) +#define MT6351_AUXADC_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EAE)) +#define MT6351_AUXADC_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EB0)) +#define MT6351_AUXADC_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EB2)) +#define MT6351_AUXADC_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EB4)) +#define MT6351_AUXADC_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EB6)) +#define MT6351_AUXADC_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EB8)) +#define MT6351_AUXADC_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EBA)) +#define MT6351_AUXADC_CON11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EBC)) +#define MT6351_AUXADC_CON12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EBE)) +#define MT6351_AUXADC_CON13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EC0)) +#define MT6351_AUXADC_CON14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EC2)) +#define MT6351_AUXADC_CON15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EC4)) +#define MT6351_AUXADC_CON16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EC6)) +#define MT6351_AUXADC_AUTORPT0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EC8)) +#define MT6351_AUXADC_LBAT0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ECA)) +#define MT6351_AUXADC_LBAT1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ECC)) +#define MT6351_AUXADC_LBAT2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ECE)) +#define MT6351_AUXADC_LBAT3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ED0)) +#define MT6351_AUXADC_LBAT4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ED2)) +#define MT6351_AUXADC_LBAT5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ED4)) +#define MT6351_AUXADC_LBAT6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ED6)) +#define MT6351_AUXADC_ACCDET ((unsigned int)(MT6351_PMIC_REG_BASE+0x0ED8)) +#define MT6351_AUXADC_THR0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EDA)) +#define MT6351_AUXADC_THR1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EDC)) +#define MT6351_AUXADC_THR2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EDE)) +#define MT6351_AUXADC_THR3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EE0)) +#define MT6351_AUXADC_THR4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EE2)) +#define MT6351_AUXADC_THR5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EE4)) +#define MT6351_AUXADC_THR6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EE6)) +#define MT6351_AUXADC_EFUSE0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EE8)) +#define MT6351_AUXADC_EFUSE1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EEA)) +#define MT6351_AUXADC_EFUSE2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EEC)) +#define MT6351_AUXADC_EFUSE3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EEE)) +#define MT6351_AUXADC_EFUSE4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EF0)) +#define MT6351_AUXADC_EFUSE5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EF2)) +#define MT6351_AUXADC_DBG0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EF4)) +#define MT6351_AUXADC_IMP0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EF6)) +#define MT6351_AUXADC_IMP1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EF8)) +#define MT6351_AUXADC_VISMPS0_1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EFA)) +#define MT6351_AUXADC_VISMPS0_2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EFC)) +#define MT6351_AUXADC_VISMPS0_3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0EFE)) +#define MT6351_AUXADC_VISMPS0_4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F00)) +#define MT6351_AUXADC_VISMPS0_5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F02)) +#define MT6351_AUXADC_VISMPS0_6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F04)) +#define MT6351_AUXADC_VISMPS0_7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F06)) +#define MT6351_AUXADC_LBAT2_1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F08)) +#define MT6351_AUXADC_LBAT2_2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F0A)) +#define MT6351_AUXADC_LBAT2_3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F0C)) +#define MT6351_AUXADC_LBAT2_4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F0E)) +#define MT6351_AUXADC_LBAT2_5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F10)) +#define MT6351_AUXADC_LBAT2_6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F12)) +#define MT6351_AUXADC_LBAT2_7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F14)) +#define MT6351_AUXADC_MDBG_0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F16)) +#define MT6351_AUXADC_MDBG_1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F18)) +#define MT6351_AUXADC_MDBG_2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F1A)) +#define MT6351_AUXADC_MDRT_0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F1C)) +#define MT6351_AUXADC_MDRT_1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F1E)) +#define MT6351_AUXADC_MDRT_2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F20)) +#define MT6351_AUXADC_JEITA_0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F22)) +#define MT6351_AUXADC_JEITA_1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F24)) +#define MT6351_AUXADC_JEITA_2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F26)) +#define MT6351_AUXADC_JEITA_3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F28)) +#define MT6351_AUXADC_JEITA_4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F2A)) +#define MT6351_AUXADC_JEITA_5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F2C)) +#define MT6351_AUXADC_DCXO_MDRT_0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F2E)) +#define MT6351_AUXADC_DCXO_MDRT_1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F30)) +#define MT6351_AUXADC_DCXO_MDRT_2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F32)) +#define MT6351_AUXADC_NAG_0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F34)) +#define MT6351_AUXADC_NAG_1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F36)) +#define MT6351_AUXADC_NAG_2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F38)) +#define MT6351_AUXADC_NAG_3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F3A)) +#define MT6351_AUXADC_NAG_4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F3C)) +#define MT6351_AUXADC_NAG_5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F3E)) +#define MT6351_AUXADC_NAG_6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F40)) +#define MT6351_AUXADC_NAG_7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F42)) +#define MT6351_AUXADC_NAG_8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F44)) +#define MT6351_ACCDET_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F46)) +#define MT6351_ACCDET_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F48)) +#define MT6351_ACCDET_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F4A)) +#define MT6351_ACCDET_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F4C)) +#define MT6351_ACCDET_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F4E)) +#define MT6351_ACCDET_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F50)) +#define MT6351_ACCDET_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F52)) +#define MT6351_ACCDET_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F54)) +#define MT6351_ACCDET_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F56)) +#define MT6351_ACCDET_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F58)) +#define MT6351_ACCDET_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F5A)) +#define MT6351_ACCDET_CON11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F5C)) +#define MT6351_ACCDET_CON12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F5E)) +#define MT6351_ACCDET_CON13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F60)) +#define MT6351_ACCDET_CON14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F62)) +#define MT6351_ACCDET_CON15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F64)) +#define MT6351_ACCDET_CON16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F66)) +#define MT6351_ACCDET_CON17 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F68)) +#define MT6351_ACCDET_CON19 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F6A)) +#define MT6351_ACCDET_CON20 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F6C)) +#define MT6351_ACCDET_CON21 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F6E)) +#define MT6351_ACCDET_CON22 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F70)) +#define MT6351_ACCDET_CON23 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F72)) +#define MT6351_ACCDET_CON24 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F74)) +#define MT6351_ACCDET_CON25 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F76)) +#define MT6351_CHR_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F78)) +#define MT6351_CHR_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F7A)) +#define MT6351_CHR_CON2 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F7C)) +#define MT6351_CHR_CON3 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F7E)) +#define MT6351_CHR_CON4 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F80)) +#define MT6351_CHR_CON5 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F82)) +#define MT6351_CHR_CON6 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F84)) +#define MT6351_CHR_CON7 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F86)) +#define MT6351_CHR_CON8 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F88)) +#define MT6351_CHR_CON9 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F8A)) +#define MT6351_CHR_CON10 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F8C)) +#define MT6351_CHR_CON11 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F8E)) +#define MT6351_CHR_CON12 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F90)) +#define MT6351_CHR_CON13 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F92)) +#define MT6351_CHR_CON14 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F94)) +#define MT6351_CHR_CON15 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F96)) +#define MT6351_CHR_CON16 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F98)) +#define MT6351_CHR_CON17 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F9A)) +#define MT6351_CHR_CON18 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F9C)) +#define MT6351_CHR_CON19 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0F9E)) +#define MT6351_CHR_CON20 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FA0)) +#define MT6351_CHR_CON21 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FA2)) +#define MT6351_CHR_CON22 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FA4)) +#define MT6351_CHR_CON23 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FA6)) +#define MT6351_CHR_CON24 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FA8)) +#define MT6351_CHR_CON25 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FAA)) +#define MT6351_CHR_CON26 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FAC)) +#define MT6351_CHR_CON27 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FAE)) +#define MT6351_CHR_CON28 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FB0)) +#define MT6351_CHR_CON29 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FB2)) +#define MT6351_CHR_CON30 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FB4)) +#define MT6351_CHR_CON31 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FB6)) +#define MT6351_CHR_CON32 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FB8)) +#define MT6351_CHR_CON33 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FBA)) +#define MT6351_CHR_CON34 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FBC)) +#define MT6351_CHR_CON35 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FBE)) +#define MT6351_CHR_CON36 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FC0)) +#define MT6351_CHR_CON37 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FC2)) +#define MT6351_CHR_CON38 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FC4)) +#define MT6351_CHR_CON39 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FC6)) +#define MT6351_CHR_CON40 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FC8)) +#define MT6351_CHR_CON41 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FCA)) +#define MT6351_CHR_CON42 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FCC)) +#define MT6351_BATON_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FCE)) +#define MT6351_CHR_CON43 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FD0)) +#define MT6351_CHR_CON44 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FD2)) +#define MT6351_CHR_CON45 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FD4)) +#define MT6351_CHR_CON46 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FD6)) +#define MT6351_CHR_CON47 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FD8)) +#define MT6351_CHR_CON48 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FDA)) +#define MT6351_EOSC_CALI_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FDC)) +#define MT6351_EOSC_CALI_CON1 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FDE)) +#define MT6351_VRTC_PWM_CON0 ((unsigned int)(MT6351_PMIC_REG_BASE+0x0FE0)) +/*mask is HEX; shift is Integer*/ +#define MT6351_PMIC_THR_DET_DIS_ADDR MT6351_STRUP_CON0 +#define MT6351_PMIC_THR_DET_DIS_MASK 0x1 +#define MT6351_PMIC_THR_DET_DIS_SHIFT 0 +#define MT6351_PMIC_THR_TEST_ADDR MT6351_STRUP_CON0 +#define MT6351_PMIC_THR_TEST_MASK 0x3 +#define MT6351_PMIC_THR_TEST_SHIFT 1 +#define MT6351_PMIC_THR_HWPDN_EN_ADDR MT6351_STRUP_CON0 +#define MT6351_PMIC_THR_HWPDN_EN_MASK 0x1 +#define MT6351_PMIC_THR_HWPDN_EN_SHIFT 5 +#define MT6351_PMIC_STRUP_THERMAL_DEB_SEL_ADDR MT6351_STRUP_CON0 +#define MT6351_PMIC_STRUP_THERMAL_DEB_SEL_MASK 0x1 +#define MT6351_PMIC_STRUP_THERMAL_DEB_SEL_SHIFT 15 +#define MT6351_PMIC_USBDL_ADDR MT6351_STRUP_CON1 +#define MT6351_PMIC_USBDL_MASK 0x1 +#define MT6351_PMIC_USBDL_SHIFT 0 +#define MT6351_PMIC_PMU_THERMAL_DEB_ADDR MT6351_STRUP_CON1 +#define MT6351_PMIC_PMU_THERMAL_DEB_MASK 0x1 +#define MT6351_PMIC_PMU_THERMAL_DEB_SHIFT 1 +#define MT6351_PMIC_PMU_THR_DEB_ADDR MT6351_STRUP_CON1 +#define MT6351_PMIC_PMU_THR_DEB_MASK 0x7 +#define MT6351_PMIC_PMU_THR_DEB_SHIFT 4 +#define MT6351_PMIC_PMU_THR_STATUS_ADDR MT6351_STRUP_CON1 +#define MT6351_PMIC_PMU_THR_STATUS_MASK 0x7 +#define MT6351_PMIC_PMU_THR_STATUS_SHIFT 8 +#define MT6351_PMIC_STRUP_THER_DEB_RMAX_ADDR MT6351_STRUP_CON2 +#define MT6351_PMIC_STRUP_THER_DEB_RMAX_MASK 0xFFFF +#define MT6351_PMIC_STRUP_THER_DEB_RMAX_SHIFT 0 +#define MT6351_PMIC_STRUP_THER_DEB_FMAX_ADDR MT6351_STRUP_CON3 +#define MT6351_PMIC_STRUP_THER_DEB_FMAX_MASK 0xFFFF +#define MT6351_PMIC_STRUP_THER_DEB_FMAX_SHIFT 0 +#define MT6351_PMIC_DDUVLO_DEB_EN_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_DDUVLO_DEB_EN_MASK 0x1 +#define MT6351_PMIC_DDUVLO_DEB_EN_SHIFT 0 +#define MT6351_PMIC_PWRBB_DEB_EN_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_PWRBB_DEB_EN_MASK 0x1 +#define MT6351_PMIC_PWRBB_DEB_EN_SHIFT 1 +#define MT6351_PMIC_STRUP_OSC_EN_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_STRUP_OSC_EN_MASK 0x1 +#define MT6351_PMIC_STRUP_OSC_EN_SHIFT 2 +#define MT6351_PMIC_STRUP_OSC_EN_SEL_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_STRUP_OSC_EN_SEL_MASK 0x1 +#define MT6351_PMIC_STRUP_OSC_EN_SEL_SHIFT 3 +#define MT6351_PMIC_STRUP_FT_CTRL_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_STRUP_FT_CTRL_MASK 0x3 +#define MT6351_PMIC_STRUP_FT_CTRL_SHIFT 4 +#define MT6351_PMIC_STRUP_PWRON_FORCE_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_STRUP_PWRON_FORCE_MASK 0x1 +#define MT6351_PMIC_STRUP_PWRON_FORCE_SHIFT 6 +#define MT6351_PMIC_BIAS_GEN_EN_FORCE_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_BIAS_GEN_EN_FORCE_MASK 0x1 +#define MT6351_PMIC_BIAS_GEN_EN_FORCE_SHIFT 7 +#define MT6351_PMIC_STRUP_PWRON_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_STRUP_PWRON_MASK 0x1 +#define MT6351_PMIC_STRUP_PWRON_SHIFT 8 +#define MT6351_PMIC_STRUP_PWRON_SEL_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_STRUP_PWRON_SEL_MASK 0x1 +#define MT6351_PMIC_STRUP_PWRON_SEL_SHIFT 9 +#define MT6351_PMIC_BIAS_GEN_EN_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_BIAS_GEN_EN_MASK 0x1 +#define MT6351_PMIC_BIAS_GEN_EN_SHIFT 10 +#define MT6351_PMIC_BIAS_GEN_EN_SEL_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_BIAS_GEN_EN_SEL_MASK 0x1 +#define MT6351_PMIC_BIAS_GEN_EN_SEL_SHIFT 11 +#define MT6351_PMIC_RTC_XOSC32_ENB_SW_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_RTC_XOSC32_ENB_SW_MASK 0x1 +#define MT6351_PMIC_RTC_XOSC32_ENB_SW_SHIFT 12 +#define MT6351_PMIC_RTC_XOSC32_ENB_SEL_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_RTC_XOSC32_ENB_SEL_MASK 0x1 +#define MT6351_PMIC_RTC_XOSC32_ENB_SEL_SHIFT 13 +#define MT6351_PMIC_STRUP_DIG_IO_PG_FORCE_ADDR MT6351_STRUP_CON4 +#define MT6351_PMIC_STRUP_DIG_IO_PG_FORCE_MASK 0x1 +#define MT6351_PMIC_STRUP_DIG_IO_PG_FORCE_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_H2L_EN_SHIFT 1 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_H2L_EN_SHIFT 2 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_H2L_EN_SHIFT 3 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_SHIFT 4 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN_SHIFT 5 +#define MT6351_PMIC_RG_STRUP_VA10_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VA10_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VA10_PG_H2L_EN_SHIFT 7 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_H2L_EN_SHIFT 8 +#define MT6351_PMIC_RG_STRUP_VS2_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VS2_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS2_PG_H2L_EN_SHIFT 10 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_H2L_EN_SHIFT 11 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_H2L_EN_SHIFT 12 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_H2L_EN_SHIFT 13 +#define MT6351_PMIC_RG_STRUP_VA18_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VA18_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VA18_PG_H2L_EN_SHIFT 14 +#define MT6351_PMIC_RG_STRUP_VS1_PG_H2L_EN_ADDR MT6351_STRUP_CON5 +#define MT6351_PMIC_RG_STRUP_VS1_PG_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS1_PG_H2L_EN_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_VTCXO24_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VTCXO24_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VTCXO24_PG_ENB_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_ENB_SHIFT 1 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_ENB_SHIFT 2 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_ENB_SHIFT 3 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_SHIFT 4 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_ENB_SHIFT 5 +#define MT6351_PMIC_RG_STRUP_VIO28_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VIO28_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VIO28_PG_ENB_SHIFT 6 +#define MT6351_PMIC_RG_STRUP_VA10_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VA10_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VA10_PG_ENB_SHIFT 7 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_ENB_SHIFT 8 +#define MT6351_PMIC_RG_STRUP_VIO18_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VIO18_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VIO18_PG_ENB_SHIFT 9 +#define MT6351_PMIC_RG_STRUP_VS2_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VS2_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS2_PG_ENB_SHIFT 10 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_ENB_SHIFT 11 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_ENB_SHIFT 12 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_ENB_SHIFT 13 +#define MT6351_PMIC_RG_STRUP_VA18_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VA18_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VA18_PG_ENB_SHIFT 14 +#define MT6351_PMIC_RG_STRUP_VS1_PG_ENB_ADDR MT6351_STRUP_CON6 +#define MT6351_PMIC_RG_STRUP_VS1_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS1_PG_ENB_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_VXO22_PG_ENB_ADDR MT6351_STRUP_CON7 +#define MT6351_PMIC_RG_STRUP_VXO22_PG_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VXO22_PG_ENB_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_H2L_EN_ADDR MT6351_STRUP_CON8 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_H2L_EN_SHIFT 9 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN_ADDR MT6351_STRUP_CON8 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN_SHIFT 10 +#define MT6351_PMIC_RG_STRUP_VS2_OC_H2L_EN_ADDR MT6351_STRUP_CON8 +#define MT6351_PMIC_RG_STRUP_VS2_OC_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS2_OC_H2L_EN_SHIFT 11 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_H2L_EN_ADDR MT6351_STRUP_CON8 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_H2L_EN_SHIFT 12 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_H2L_EN_ADDR MT6351_STRUP_CON8 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_H2L_EN_SHIFT 13 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_H2L_EN_ADDR MT6351_STRUP_CON8 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_H2L_EN_SHIFT 14 +#define MT6351_PMIC_RG_STRUP_VS1_OC_H2L_EN_ADDR MT6351_STRUP_CON8 +#define MT6351_PMIC_RG_STRUP_VS1_OC_H2L_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS1_OC_H2L_EN_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_ENB_ADDR MT6351_STRUP_CON9 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_ENB_SHIFT 9 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_ENB_ADDR MT6351_STRUP_CON9 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_ENB_SHIFT 10 +#define MT6351_PMIC_RG_STRUP_VS2_OC_ENB_ADDR MT6351_STRUP_CON9 +#define MT6351_PMIC_RG_STRUP_VS2_OC_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS2_OC_ENB_SHIFT 11 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_ENB_ADDR MT6351_STRUP_CON9 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_ENB_SHIFT 12 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_ENB_ADDR MT6351_STRUP_CON9 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_ENB_SHIFT 13 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_ENB_ADDR MT6351_STRUP_CON9 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_ENB_SHIFT 14 +#define MT6351_PMIC_RG_STRUP_VS1_OC_ENB_ADDR MT6351_STRUP_CON9 +#define MT6351_PMIC_RG_STRUP_VS1_OC_ENB_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS1_OC_ENB_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS_SHIFT 7 +#define MT6351_PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS_SHIFT 8 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS_SHIFT 9 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS_SHIFT 10 +#define MT6351_PMIC_RG_STRUP_VS2_OC_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VS2_OC_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS2_OC_DEB_BYPASS_SHIFT 11 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS_SHIFT 12 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS_SHIFT 13 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS_SHIFT 14 +#define MT6351_PMIC_RG_STRUP_VS1_OC_DEB_BYPASS_ADDR MT6351_STRUP_CON10 +#define MT6351_PMIC_RG_STRUP_VS1_OC_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS1_OC_DEB_BYPASS_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS_SHIFT 1 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS_SHIFT 2 +#define MT6351_PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS_SHIFT 3 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS_SHIFT 4 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS_SHIFT 5 +#define MT6351_PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS_SHIFT 6 +#define MT6351_PMIC_RG_STRUP_VA10_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VA10_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VA10_PG_DEB_BYPASS_SHIFT 7 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS_SHIFT 8 +#define MT6351_PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS_SHIFT 9 +#define MT6351_PMIC_RG_STRUP_VS2_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VS2_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS2_PG_DEB_BYPASS_SHIFT 10 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS_SHIFT 11 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS_SHIFT 12 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS_SHIFT 13 +#define MT6351_PMIC_RG_STRUP_VA18_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VA18_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VA18_PG_DEB_BYPASS_SHIFT 14 +#define MT6351_PMIC_RG_STRUP_VS1_PG_DEB_BYPASS_ADDR MT6351_STRUP_CON11 +#define MT6351_PMIC_RG_STRUP_VS1_PG_DEB_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_VS1_PG_DEB_BYPASS_SHIFT 15 +#define MT6351_PMIC_CLR_JUST_RST_ADDR MT6351_STRUP_CON12 +#define MT6351_PMIC_CLR_JUST_RST_MASK 0x1 +#define MT6351_PMIC_CLR_JUST_RST_SHIFT 4 +#define MT6351_PMIC_UVLO_L2H_DEB_EN_ADDR MT6351_STRUP_CON12 +#define MT6351_PMIC_UVLO_L2H_DEB_EN_MASK 0x1 +#define MT6351_PMIC_UVLO_L2H_DEB_EN_SHIFT 5 +#define MT6351_PMIC_JUST_PWRKEY_RST_ADDR MT6351_STRUP_CON12 +#define MT6351_PMIC_JUST_PWRKEY_RST_MASK 0x1 +#define MT6351_PMIC_JUST_PWRKEY_RST_SHIFT 14 +#define MT6351_PMIC_DA_QI_OSC_EN_ADDR MT6351_STRUP_CON12 +#define MT6351_PMIC_DA_QI_OSC_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_OSC_EN_SHIFT 15 +#define MT6351_PMIC_STRUP_EXT_PMIC_EN_ADDR MT6351_STRUP_CON13 +#define MT6351_PMIC_STRUP_EXT_PMIC_EN_MASK 0x1 +#define MT6351_PMIC_STRUP_EXT_PMIC_EN_SHIFT 0 +#define MT6351_PMIC_STRUP_EXT_PMIC_SEL_ADDR MT6351_STRUP_CON13 +#define MT6351_PMIC_STRUP_EXT_PMIC_SEL_MASK 0x1 +#define MT6351_PMIC_STRUP_EXT_PMIC_SEL_SHIFT 1 +#define MT6351_PMIC_STRUP_CON8_RSV0_ADDR MT6351_STRUP_CON13 +#define MT6351_PMIC_STRUP_CON8_RSV0_MASK 0x7F +#define MT6351_PMIC_STRUP_CON8_RSV0_SHIFT 8 +#define MT6351_PMIC_DA_QI_EXT_PMIC_EN_ADDR MT6351_STRUP_CON13 +#define MT6351_PMIC_DA_QI_EXT_PMIC_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_EXT_PMIC_EN_SHIFT 15 +#define MT6351_PMIC_STRUP_AUXADC_START_SW_ADDR MT6351_STRUP_CON14 +#define MT6351_PMIC_STRUP_AUXADC_START_SW_MASK 0x1 +#define MT6351_PMIC_STRUP_AUXADC_START_SW_SHIFT 4 +#define MT6351_PMIC_STRUP_AUXADC_RSTB_SW_ADDR MT6351_STRUP_CON14 +#define MT6351_PMIC_STRUP_AUXADC_RSTB_SW_MASK 0x1 +#define MT6351_PMIC_STRUP_AUXADC_RSTB_SW_SHIFT 5 +#define MT6351_PMIC_STRUP_AUXADC_START_SEL_ADDR MT6351_STRUP_CON14 +#define MT6351_PMIC_STRUP_AUXADC_START_SEL_MASK 0x1 +#define MT6351_PMIC_STRUP_AUXADC_START_SEL_SHIFT 6 +#define MT6351_PMIC_STRUP_AUXADC_RSTB_SEL_ADDR MT6351_STRUP_CON14 +#define MT6351_PMIC_STRUP_AUXADC_RSTB_SEL_MASK 0x1 +#define MT6351_PMIC_STRUP_AUXADC_RSTB_SEL_SHIFT 7 +#define MT6351_PMIC_STRUP_PWROFF_SEQ_EN_ADDR MT6351_STRUP_CON15 +#define MT6351_PMIC_STRUP_PWROFF_SEQ_EN_MASK 0x1 +#define MT6351_PMIC_STRUP_PWROFF_SEQ_EN_SHIFT 0 +#define MT6351_PMIC_STRUP_PWROFF_PREOFF_EN_ADDR MT6351_STRUP_CON15 +#define MT6351_PMIC_STRUP_PWROFF_PREOFF_EN_MASK 0x1 +#define MT6351_PMIC_STRUP_PWROFF_PREOFF_EN_SHIFT 1 +#define MT6351_PMIC_STRUP_PP_EN_ADDR MT6351_STRUP_CON16 +#define MT6351_PMIC_STRUP_PP_EN_MASK 0x1 +#define MT6351_PMIC_STRUP_PP_EN_SHIFT 0 +#define MT6351_PMIC_STRUP_PP_EN_SEL_ADDR MT6351_STRUP_CON16 +#define MT6351_PMIC_STRUP_PP_EN_SEL_MASK 0x1 +#define MT6351_PMIC_STRUP_PP_EN_SEL_SHIFT 1 +#define MT6351_PMIC_STRUP_DIG0_RSV0_ADDR MT6351_STRUP_CON16 +#define MT6351_PMIC_STRUP_DIG0_RSV0_MASK 0xF +#define MT6351_PMIC_STRUP_DIG0_RSV0_SHIFT 2 +#define MT6351_PMIC_STRUP_DIG1_RSV0_ADDR MT6351_STRUP_CON16 +#define MT6351_PMIC_STRUP_DIG1_RSV0_MASK 0x1F +#define MT6351_PMIC_STRUP_DIG1_RSV0_SHIFT 6 +#define MT6351_PMIC_RG_RSV_SWREG_ADDR MT6351_STRUP_CON17 +#define MT6351_PMIC_RG_RSV_SWREG_MASK 0xFFFF +#define MT6351_PMIC_RG_RSV_SWREG_SHIFT 0 +#define MT6351_PMIC_STRUP_PP_EN_PWROFF_CNT_ADDR MT6351_STRUP_CON18 +#define MT6351_PMIC_STRUP_PP_EN_PWROFF_CNT_MASK 0x3FF +#define MT6351_PMIC_STRUP_PP_EN_PWROFF_CNT_SHIFT 0 +#define MT6351_PMIC_STRUP_UVLO_U1U2_SEL_ADDR MT6351_STRUP_CON19 +#define MT6351_PMIC_STRUP_UVLO_U1U2_SEL_MASK 0x1 +#define MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SHIFT 0 +#define MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL_ADDR MT6351_STRUP_CON19 +#define MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL_MASK 0x1 +#define MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL_SHIFT 1 +#define MT6351_PMIC_STRUP_AUXADC_RPCNT_MAX_ADDR MT6351_STRUP_CON20 +#define MT6351_PMIC_STRUP_AUXADC_RPCNT_MAX_MASK 0x7F +#define MT6351_PMIC_STRUP_AUXADC_RPCNT_MAX_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_CLR_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_CLR_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_CLR_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_THR_110_CLR_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_110_CLR_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_110_CLR_SHIFT 1 +#define MT6351_PMIC_RG_STRUP_THR_125_CLR_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_125_CLR_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_125_CLR_SHIFT 2 +#define MT6351_PMIC_RG_STRUP_THR_CLR_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_CLR_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_CLR_SHIFT 3 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_EN_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_EN_SHIFT 8 +#define MT6351_PMIC_RG_STRUP_THR_110_IRQ_EN_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_110_IRQ_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_110_IRQ_EN_SHIFT 9 +#define MT6351_PMIC_RG_STRUP_THR_125_IRQ_EN_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_125_IRQ_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_125_IRQ_EN_SHIFT 10 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS_SHIFT 12 +#define MT6351_PMIC_RG_STRUP_THR_110_IRQ_STATUS_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_110_IRQ_STATUS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_110_IRQ_STATUS_SHIFT 13 +#define MT6351_PMIC_RG_STRUP_THR_125_IRQ_STATUS_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_RG_STRUP_THR_125_IRQ_STATUS_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_THR_125_IRQ_STATUS_SHIFT 14 +#define MT6351_PMIC_STRUP_PG_STATUS_CLR_ADDR MT6351_STRUP_CON21 +#define MT6351_PMIC_STRUP_PG_STATUS_CLR_MASK 0x1 +#define MT6351_PMIC_STRUP_PG_STATUS_CLR_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_ADDR MT6351_STRUP_CON22 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_MASK 0x3 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_TD_ADDR MT6351_STRUP_CON22 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_TD_MASK 0x3 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_TD_SHIFT 2 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_EN_ADDR MT6351_STRUP_CON22 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_EN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_EN_SHIFT 4 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_ADDR MT6351_STRUP_CON22 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_SHIFT 5 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL_ADDR MT6351_STRUP_CON22 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL_SHIFT 6 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_ADDR MT6351_STRUP_CON22 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_SHIFT 7 +#define MT6351_PMIC_RG_STRUP_ENVTEM_ADDR MT6351_STRUP_CON22 +#define MT6351_PMIC_RG_STRUP_ENVTEM_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_ENVTEM_SHIFT 14 +#define MT6351_PMIC_RG_STRUP_ENVTEM_CTRL_ADDR MT6351_STRUP_CON22 +#define MT6351_PMIC_RG_STRUP_ENVTEM_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_ENVTEM_CTRL_SHIFT 15 +#define MT6351_PMIC_RG_STRUP_PWRKEY_COUNT_RESET_ADDR MT6351_STRUP_CON23 +#define MT6351_PMIC_RG_STRUP_PWRKEY_COUNT_RESET_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_PWRKEY_COUNT_RESET_SHIFT 0 +#define MT6351_PMIC_RGS_ANA_CHIP_ID_ADDR MT6351_STRUP_ANA_CON0 +#define MT6351_PMIC_RGS_ANA_CHIP_ID_MASK 0x7 +#define MT6351_PMIC_RGS_ANA_CHIP_ID_SHIFT 7 +#define MT6351_PMIC_RG_PP_EN_DRVSEL_ADDR MT6351_STRUP_ANA_CON0 +#define MT6351_PMIC_RG_PP_EN_DRVSEL_MASK 0x1 +#define MT6351_PMIC_RG_PP_EN_DRVSEL_SHIFT 10 +#define MT6351_PMIC_RG_FCHR_PU_EN_ADDR MT6351_STRUP_ANA_CON0 +#define MT6351_PMIC_RG_FCHR_PU_EN_MASK 0x1 +#define MT6351_PMIC_RG_FCHR_PU_EN_SHIFT 11 +#define MT6351_PMIC_RG_PMU_RSV_ADDR MT6351_STRUP_ANA_CON0 +#define MT6351_PMIC_RG_PMU_RSV_MASK 0xF +#define MT6351_PMIC_RG_PMU_RSV_SHIFT 12 +#define MT6351_PMIC_RG_FCHR_KEYDET_EN_ADDR MT6351_STRUP_ANA_CON1 +#define MT6351_PMIC_RG_FCHR_KEYDET_EN_MASK 0x1 +#define MT6351_PMIC_RG_FCHR_KEYDET_EN_SHIFT 1 +#define MT6351_PMIC_RG_EN_DRVSEL_ADDR MT6351_STRUP_ANA_CON1 +#define MT6351_PMIC_RG_EN_DRVSEL_MASK 0x1 +#define MT6351_PMIC_RG_EN_DRVSEL_SHIFT 2 +#define MT6351_PMIC_RG_RST_DRVSEL_ADDR MT6351_STRUP_ANA_CON1 +#define MT6351_PMIC_RG_RST_DRVSEL_MASK 0x1 +#define MT6351_PMIC_RG_RST_DRVSEL_SHIFT 3 +#define MT6351_PMIC_RG_STRUP_IREF_TRIM_ADDR MT6351_STRUP_ANA_CON1 +#define MT6351_PMIC_RG_STRUP_IREF_TRIM_MASK 0x1F +#define MT6351_PMIC_RG_STRUP_IREF_TRIM_SHIFT 4 +#define MT6351_PMIC_RG_VREF_BG_ADDR MT6351_STRUP_ANA_CON1 +#define MT6351_PMIC_RG_VREF_BG_MASK 0x7 +#define MT6351_PMIC_RG_VREF_BG_SHIFT 9 +#define MT6351_PMIC_RG_THR_TMODE_ADDR MT6351_STRUP_ANA_CON1 +#define MT6351_PMIC_RG_THR_TMODE_MASK 0x1 +#define MT6351_PMIC_RG_THR_TMODE_SHIFT 12 +#define MT6351_PMIC_RG_STRUP_THR_SEL_ADDR MT6351_STRUP_ANA_CON1 +#define MT6351_PMIC_RG_STRUP_THR_SEL_MASK 0x3 +#define MT6351_PMIC_RG_STRUP_THR_SEL_SHIFT 13 +#define MT6351_PMIC_RG_THRDET_SEL_ADDR MT6351_STRUP_ANA_CON1 +#define MT6351_PMIC_RG_THRDET_SEL_MASK 0x1 +#define MT6351_PMIC_RG_THRDET_SEL_SHIFT 15 +#define MT6351_PMIC_HWCID_ADDR MT6351_HWCID +#define MT6351_PMIC_HWCID_MASK 0xFFFF +#define MT6351_PMIC_HWCID_SHIFT 0 +#define MT6351_PMIC_SWCID_ADDR MT6351_SWCID +#define MT6351_PMIC_SWCID_MASK 0xFFFF +#define MT6351_PMIC_SWCID_SHIFT 0 +#define MT6351_PMIC_RG_SRCLKEN_IN0_EN_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_SRCLKEN_IN0_EN_MASK 0x1 +#define MT6351_PMIC_RG_SRCLKEN_IN0_EN_SHIFT 0 +#define MT6351_PMIC_RG_SRCLKEN_IN1_EN_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_SRCLKEN_IN1_EN_MASK 0x1 +#define MT6351_PMIC_RG_SRCLKEN_IN1_EN_SHIFT 1 +#define MT6351_PMIC_RG_OSC_SEL_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_OSC_SEL_MASK 0x1 +#define MT6351_PMIC_RG_OSC_SEL_SHIFT 2 +#define MT6351_PMIC_RG_SRCLKEN_IN2_EN_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_SRCLKEN_IN2_EN_MASK 0x1 +#define MT6351_PMIC_RG_SRCLKEN_IN2_EN_SHIFT 3 +#define MT6351_PMIC_RG_SRCLKEN_IN0_HW_MODE_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK 0x1 +#define MT6351_PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT 4 +#define MT6351_PMIC_RG_SRCLKEN_IN1_HW_MODE_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK 0x1 +#define MT6351_PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT 5 +#define MT6351_PMIC_RG_OSC_SEL_HW_MODE_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_OSC_SEL_HW_MODE_MASK 0x1 +#define MT6351_PMIC_RG_OSC_SEL_HW_MODE_SHIFT 6 +#define MT6351_PMIC_RG_SRCLKEN_IN_SYNC_EN_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_SRCLKEN_IN_SYNC_EN_MASK 0x1 +#define MT6351_PMIC_RG_SRCLKEN_IN_SYNC_EN_SHIFT 8 +#define MT6351_PMIC_RG_OSC_EN_AUTO_OFF_ADDR MT6351_TOP_CON +#define MT6351_PMIC_RG_OSC_EN_AUTO_OFF_MASK 0x1 +#define MT6351_PMIC_RG_OSC_EN_AUTO_OFF_SHIFT 9 +#define MT6351_PMIC_TEST_OUT_ADDR MT6351_TEST_OUT +#define MT6351_PMIC_TEST_OUT_MASK 0xFF +#define MT6351_PMIC_TEST_OUT_SHIFT 0 +#define MT6351_PMIC_RG_MON_FLAG_SEL_ADDR MT6351_TEST_CON0 +#define MT6351_PMIC_RG_MON_FLAG_SEL_MASK 0xFF +#define MT6351_PMIC_RG_MON_FLAG_SEL_SHIFT 0 +#define MT6351_PMIC_RG_MON_GRP_SEL_ADDR MT6351_TEST_CON0 +#define MT6351_PMIC_RG_MON_GRP_SEL_MASK 0x1F +#define MT6351_PMIC_RG_MON_GRP_SEL_SHIFT 8 +#define MT6351_PMIC_RG_NANDTREE_MODE_ADDR MT6351_TEST_CON1 +#define MT6351_PMIC_RG_NANDTREE_MODE_MASK 0x1 +#define MT6351_PMIC_RG_NANDTREE_MODE_SHIFT 0 +#define MT6351_PMIC_RG_TEST_AUXADC_ADDR MT6351_TEST_CON1 +#define MT6351_PMIC_RG_TEST_AUXADC_MASK 0x1 +#define MT6351_PMIC_RG_TEST_AUXADC_SHIFT 1 +#define MT6351_PMIC_RG_EFUSE_MODE_ADDR MT6351_TEST_CON1 +#define MT6351_PMIC_RG_EFUSE_MODE_MASK 0x1 +#define MT6351_PMIC_RG_EFUSE_MODE_SHIFT 2 +#define MT6351_PMIC_RG_TEST_STRUP_ADDR MT6351_TEST_CON1 +#define MT6351_PMIC_RG_TEST_STRUP_MASK 0x1 +#define MT6351_PMIC_RG_TEST_STRUP_SHIFT 3 +#define MT6351_PMIC_TESTMODE_SW_ADDR MT6351_TESTMODE_SW +#define MT6351_PMIC_TESTMODE_SW_MASK 0x1 +#define MT6351_PMIC_TESTMODE_SW_SHIFT 0 +#define MT6351_PMIC_EN_STATUS_VLDO28_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VLDO28_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VLDO28_SHIFT 0 +#define MT6351_PMIC_EN_STATUS_VIO28_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VIO28_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VIO28_SHIFT 1 +#define MT6351_PMIC_EN_STATUS_VMCH_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VMCH_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VMCH_SHIFT 2 +#define MT6351_PMIC_EN_STATUS_VMC_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VMC_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VMC_SHIFT 3 +#define MT6351_PMIC_EN_STATUS_VEMC_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VEMC_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VEMC_SHIFT 4 +#define MT6351_PMIC_EN_STATUS_VSIM2_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VSIM2_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VSIM2_SHIFT 5 +#define MT6351_PMIC_EN_STATUS_VSIM1_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VSIM1_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VSIM1_SHIFT 6 +#define MT6351_PMIC_EN_STATUS_VEFUSE_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VEFUSE_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VEFUSE_SHIFT 7 +#define MT6351_PMIC_EN_STATUS_VUSB33_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VUSB33_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VUSB33_SHIFT 8 +#define MT6351_PMIC_EN_STATUS_VCN33_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VCN33_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VCN33_SHIFT 9 +#define MT6351_PMIC_EN_STATUS_VCAMA_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VCAMA_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VCAMA_SHIFT 10 +#define MT6351_PMIC_EN_STATUS_VCN28_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VCN28_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VCN28_SHIFT 11 +#define MT6351_PMIC_EN_STATUS_VTCXO24_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VTCXO24_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VTCXO24_SHIFT 12 +#define MT6351_PMIC_EN_STATUS_VTCXO28_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VTCXO28_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VTCXO28_SHIFT 13 +#define MT6351_PMIC_EN_STATUS_VA18_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VA18_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VA18_SHIFT 14 +#define MT6351_PMIC_EN_STATUS_VRTC_ADDR MT6351_EN_STATUS1 +#define MT6351_PMIC_EN_STATUS_VRTC_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VRTC_SHIFT 15 +#define MT6351_PMIC_EN_STATUS_VBIF28_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VBIF28_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VBIF28_SHIFT 2 +#define MT6351_PMIC_EN_STATUS_VGP3_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VGP3_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VGP3_SHIFT 3 +#define MT6351_PMIC_EN_STATUS_VMIPI_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VMIPI_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VMIPI_SHIFT 4 +#define MT6351_PMIC_EN_STATUS_VDRAM_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VDRAM_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VDRAM_SHIFT 5 +#define MT6351_PMIC_EN_STATUS_VA10_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VA10_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VA10_SHIFT 6 +#define MT6351_PMIC_EN_STATUS_VRF12_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VRF12_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VRF12_SHIFT 7 +#define MT6351_PMIC_EN_STATUS_VXO22_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VXO22_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VXO22_SHIFT 8 +#define MT6351_PMIC_EN_STATUS_VSRAM_PROC_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VSRAM_PROC_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VSRAM_PROC_SHIFT 9 +#define MT6351_PMIC_EN_STATUS_VCAMIO_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VCAMIO_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VCAMIO_SHIFT 10 +#define MT6351_PMIC_EN_STATUS_VCN18_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VCN18_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VCN18_SHIFT 11 +#define MT6351_PMIC_EN_STATUS_VIO18_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VIO18_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VIO18_SHIFT 12 +#define MT6351_PMIC_EN_STATUS_VRF18_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VRF18_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VRF18_SHIFT 13 +#define MT6351_PMIC_EN_STATUS_VCAMD_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VCAMD_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VCAMD_SHIFT 14 +#define MT6351_PMIC_EN_STATUS_VIBR_ADDR MT6351_EN_STATUS2 +#define MT6351_PMIC_EN_STATUS_VIBR_MASK 0x1 +#define MT6351_PMIC_EN_STATUS_VIBR_SHIFT 15 +#define MT6351_PMIC_OC_STATUS_VIBR_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VIBR_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VIBR_SHIFT 0 +#define MT6351_PMIC_OC_STATUS_VLDO28_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VLDO28_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VLDO28_SHIFT 1 +#define MT6351_PMIC_OC_STATUS_VIO28_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VIO28_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VIO28_SHIFT 2 +#define MT6351_PMIC_OC_STATUS_VMC_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VMC_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VMC_SHIFT 3 +#define MT6351_PMIC_OC_STATUS_VMCH_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VMCH_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VMCH_SHIFT 4 +#define MT6351_PMIC_OC_STATUS_VEMC_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VEMC_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VEMC_SHIFT 5 +#define MT6351_PMIC_OC_STATUS_VSIM2_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VSIM2_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VSIM2_SHIFT 6 +#define MT6351_PMIC_OC_STATUS_VSIM1_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VSIM1_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VSIM1_SHIFT 7 +#define MT6351_PMIC_OC_STATUS_VEFUSE_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VEFUSE_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VEFUSE_SHIFT 8 +#define MT6351_PMIC_OC_STATUS_VUSB33_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VUSB33_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VUSB33_SHIFT 9 +#define MT6351_PMIC_OC_STATUS_VCN33_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VCN33_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VCN33_SHIFT 10 +#define MT6351_PMIC_OC_STATUS_VCAMA_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VCAMA_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VCAMA_SHIFT 11 +#define MT6351_PMIC_OC_STATUS_VCN28_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VCN28_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VCN28_SHIFT 12 +#define MT6351_PMIC_OC_STATUS_VTCXO24_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VTCXO24_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VTCXO24_SHIFT 13 +#define MT6351_PMIC_OC_STATUS_VTCXO28_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VTCXO28_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VTCXO28_SHIFT 14 +#define MT6351_PMIC_OC_STATUS_VA18_ADDR MT6351_OCSTATUS1 +#define MT6351_PMIC_OC_STATUS_VA18_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VA18_SHIFT 15 +#define MT6351_PMIC_OC_STATUS_VBIF28_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VBIF28_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VBIF28_SHIFT 3 +#define MT6351_PMIC_OC_STATUS_VGP3_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VGP3_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VGP3_SHIFT 4 +#define MT6351_PMIC_OC_STATUS_VMIPI_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VMIPI_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VMIPI_SHIFT 5 +#define MT6351_PMIC_OC_STATUS_VDRAM_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VDRAM_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VDRAM_SHIFT 6 +#define MT6351_PMIC_OC_STATUS_VA10_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VA10_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VA10_SHIFT 7 +#define MT6351_PMIC_OC_STATUS_VRF12_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VRF12_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VRF12_SHIFT 8 +#define MT6351_PMIC_OC_STATUS_VXO22_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VXO22_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VXO22_SHIFT 9 +#define MT6351_PMIC_OC_STATUS_VSRAM_PROC_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VSRAM_PROC_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VSRAM_PROC_SHIFT 10 +#define MT6351_PMIC_OC_STATUS_VCAMIO_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VCAMIO_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VCAMIO_SHIFT 11 +#define MT6351_PMIC_OC_STATUS_VCN18_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VCN18_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VCN18_SHIFT 12 +#define MT6351_PMIC_OC_STATUS_VIO18_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VIO18_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VIO18_SHIFT 13 +#define MT6351_PMIC_OC_STATUS_VRF18_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VRF18_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VRF18_SHIFT 14 +#define MT6351_PMIC_OC_STATUS_VCAMD_ADDR MT6351_OCSTATUS2 +#define MT6351_PMIC_OC_STATUS_VCAMD_MASK 0x1 +#define MT6351_PMIC_OC_STATUS_VCAMD_SHIFT 15 +#define MT6351_PMIC_VA18_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VA18_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VA18_PG_DEB_SHIFT 0 +#define MT6351_PMIC_VCORE_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VCORE_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VCORE_PG_DEB_SHIFT 1 +#define MT6351_PMIC_VMD1_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VMD1_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VMD1_PG_DEB_SHIFT 2 +#define MT6351_PMIC_VMODEM_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VMODEM_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VMODEM_PG_DEB_SHIFT 3 +#define MT6351_PMIC_VS2_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VS2_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VS2_PG_DEB_SHIFT 4 +#define MT6351_PMIC_VIO18_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VIO18_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VIO18_PG_DEB_SHIFT 5 +#define MT6351_PMIC_VEMC_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VEMC_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VEMC_PG_DEB_SHIFT 6 +#define MT6351_PMIC_VA10_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VA10_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VA10_PG_DEB_SHIFT 7 +#define MT6351_PMIC_VIO28_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VIO28_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VIO28_PG_DEB_SHIFT 8 +#define MT6351_PMIC_VSRAM_MD_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VSRAM_MD_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VSRAM_MD_PG_DEB_SHIFT 9 +#define MT6351_PMIC_VSRAM_PROC_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VSRAM_PROC_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VSRAM_PROC_PG_DEB_SHIFT 10 +#define MT6351_PMIC_VDRAM_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VDRAM_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VDRAM_PG_DEB_SHIFT 11 +#define MT6351_PMIC_VGPU_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VGPU_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VGPU_PG_DEB_SHIFT 12 +#define MT6351_PMIC_VUSB33_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VUSB33_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VUSB33_PG_DEB_SHIFT 13 +#define MT6351_PMIC_VXO22_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VXO22_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VXO22_PG_DEB_SHIFT 14 +#define MT6351_PMIC_VTCXO24_PG_DEB_ADDR MT6351_PGDEBSTATUS0 +#define MT6351_PMIC_VTCXO24_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VTCXO24_PG_DEB_SHIFT 15 +#define MT6351_PMIC_VS1_PG_DEB_ADDR MT6351_PGDEBSTATU1 +#define MT6351_PMIC_VS1_PG_DEB_MASK 0x1 +#define MT6351_PMIC_VS1_PG_DEB_SHIFT 15 +#define MT6351_PMIC_STRUP_VA18_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VA18_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VA18_PG_STATUS_SHIFT 0 +#define MT6351_PMIC_STRUP_VCORE_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VCORE_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VCORE_PG_STATUS_SHIFT 1 +#define MT6351_PMIC_STRUP_VMD1_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VMD1_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VMD1_PG_STATUS_SHIFT 2 +#define MT6351_PMIC_STRUP_VMODEM_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VMODEM_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VMODEM_PG_STATUS_SHIFT 3 +#define MT6351_PMIC_STRUP_VS2_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VS2_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VS2_PG_STATUS_SHIFT 4 +#define MT6351_PMIC_STRUP_VIO18_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VIO18_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VIO18_PG_STATUS_SHIFT 5 +#define MT6351_PMIC_STRUP_VEMC_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VEMC_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VEMC_PG_STATUS_SHIFT 6 +#define MT6351_PMIC_STRUP_VA10_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VA10_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VA10_PG_STATUS_SHIFT 7 +#define MT6351_PMIC_STRUP_VIO28_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VIO28_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VIO28_PG_STATUS_SHIFT 8 +#define MT6351_PMIC_STRUP_VSRAM_MD_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VSRAM_MD_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VSRAM_MD_PG_STATUS_SHIFT 9 +#define MT6351_PMIC_STRUP_VSRAM_PROC_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VSRAM_PROC_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VSRAM_PROC_PG_STATUS_SHIFT 10 +#define MT6351_PMIC_STRUP_VDRAM_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VDRAM_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VDRAM_PG_STATUS_SHIFT 11 +#define MT6351_PMIC_STRUP_VGPU_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VGPU_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VGPU_PG_STATUS_SHIFT 12 +#define MT6351_PMIC_STRUP_VUSB33_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VUSB33_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VUSB33_PG_STATUS_SHIFT 13 +#define MT6351_PMIC_STRUP_VXO22_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VXO22_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VXO22_PG_STATUS_SHIFT 14 +#define MT6351_PMIC_STRUP_VTCXO24_PG_STATUS_ADDR MT6351_PGSTATUS0 +#define MT6351_PMIC_STRUP_VTCXO24_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VTCXO24_PG_STATUS_SHIFT 15 +#define MT6351_PMIC_STRUP_VS1_PG_STATUS_ADDR MT6351_PGSTATUS1 +#define MT6351_PMIC_STRUP_VS1_PG_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_VS1_PG_STATUS_SHIFT 15 +#define MT6351_PMIC_THERMAL_BACK110_ADDR MT6351_THERMALSTATUS +#define MT6351_PMIC_THERMAL_BACK110_MASK 0x1 +#define MT6351_PMIC_THERMAL_BACK110_SHIFT 12 +#define MT6351_PMIC_THERMAL_OVER110_ADDR MT6351_THERMALSTATUS +#define MT6351_PMIC_THERMAL_OVER110_MASK 0x1 +#define MT6351_PMIC_THERMAL_OVER110_SHIFT 13 +#define MT6351_PMIC_THERMAL_OVER125_ADDR MT6351_THERMALSTATUS +#define MT6351_PMIC_THERMAL_OVER125_MASK 0x1 +#define MT6351_PMIC_THERMAL_OVER125_SHIFT 14 +#define MT6351_PMIC_STRUP_THERMAL_STATUS_ADDR MT6351_THERMALSTATUS +#define MT6351_PMIC_STRUP_THERMAL_STATUS_MASK 0x1 +#define MT6351_PMIC_STRUP_THERMAL_STATUS_SHIFT 15 +#define MT6351_PMIC_PMU_TEST_MODE_SCAN_ADDR MT6351_TOPSTATUS +#define MT6351_PMIC_PMU_TEST_MODE_SCAN_MASK 0x1 +#define MT6351_PMIC_PMU_TEST_MODE_SCAN_SHIFT 0 +#define MT6351_PMIC_PWRKEY_DEB_ADDR MT6351_TOPSTATUS +#define MT6351_PMIC_PWRKEY_DEB_MASK 0x1 +#define MT6351_PMIC_PWRKEY_DEB_SHIFT 1 +#define MT6351_PMIC_HOMEKEY_DEB_ADDR MT6351_TOPSTATUS +#define MT6351_PMIC_HOMEKEY_DEB_MASK 0x1 +#define MT6351_PMIC_HOMEKEY_DEB_SHIFT 2 +#define MT6351_PMIC_RTC_XTAL_DET_DONE_ADDR MT6351_TOPSTATUS +#define MT6351_PMIC_RTC_XTAL_DET_DONE_MASK 0x1 +#define MT6351_PMIC_RTC_XTAL_DET_DONE_SHIFT 6 +#define MT6351_PMIC_XOSC32_ENB_DET_ADDR MT6351_TOPSTATUS +#define MT6351_PMIC_XOSC32_ENB_DET_MASK 0x1 +#define MT6351_PMIC_XOSC32_ENB_DET_SHIFT 7 +#define MT6351_PMIC_RTC_XTAL_DET_RSV_ADDR MT6351_TOPSTATUS +#define MT6351_PMIC_RTC_XTAL_DET_RSV_MASK 0xF +#define MT6351_PMIC_RTC_XTAL_DET_RSV_SHIFT 8 +#define MT6351_PMIC_RG_PMU_TDSEL_ADDR MT6351_TDSEL_CON +#define MT6351_PMIC_RG_PMU_TDSEL_MASK 0x1 +#define MT6351_PMIC_RG_PMU_TDSEL_SHIFT 0 +#define MT6351_PMIC_RG_SPI_TDSEL_ADDR MT6351_TDSEL_CON +#define MT6351_PMIC_RG_SPI_TDSEL_MASK 0x1 +#define MT6351_PMIC_RG_SPI_TDSEL_SHIFT 1 +#define MT6351_PMIC_RG_AUD_TDSEL_ADDR MT6351_TDSEL_CON +#define MT6351_PMIC_RG_AUD_TDSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUD_TDSEL_SHIFT 2 +#define MT6351_PMIC_RG_E32CAL_TDSEL_ADDR MT6351_TDSEL_CON +#define MT6351_PMIC_RG_E32CAL_TDSEL_MASK 0x1 +#define MT6351_PMIC_RG_E32CAL_TDSEL_SHIFT 3 +#define MT6351_PMIC_RG_PMU_RDSEL_ADDR MT6351_RDSEL_CON +#define MT6351_PMIC_RG_PMU_RDSEL_MASK 0x1 +#define MT6351_PMIC_RG_PMU_RDSEL_SHIFT 0 +#define MT6351_PMIC_RG_SPI_RDSEL_ADDR MT6351_RDSEL_CON +#define MT6351_PMIC_RG_SPI_RDSEL_MASK 0x1 +#define MT6351_PMIC_RG_SPI_RDSEL_SHIFT 1 +#define MT6351_PMIC_RG_AUD_RDSEL_ADDR MT6351_RDSEL_CON +#define MT6351_PMIC_RG_AUD_RDSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUD_RDSEL_SHIFT 2 +#define MT6351_PMIC_RG_E32CAL_RDSEL_ADDR MT6351_RDSEL_CON +#define MT6351_PMIC_RG_E32CAL_RDSEL_MASK 0x1 +#define MT6351_PMIC_RG_E32CAL_RDSEL_SHIFT 3 +#define MT6351_PMIC_RG_SMT_WDTRSTB_IN_ADDR MT6351_SMT_CON0 +#define MT6351_PMIC_RG_SMT_WDTRSTB_IN_MASK 0x1 +#define MT6351_PMIC_RG_SMT_WDTRSTB_IN_SHIFT 0 +#define MT6351_PMIC_RG_SMT_HOMEKEY_ADDR MT6351_SMT_CON0 +#define MT6351_PMIC_RG_SMT_HOMEKEY_MASK 0x1 +#define MT6351_PMIC_RG_SMT_HOMEKEY_SHIFT 1 +#define MT6351_PMIC_RG_SMT_SRCLKEN_IN0_ADDR MT6351_SMT_CON0 +#define MT6351_PMIC_RG_SMT_SRCLKEN_IN0_MASK 0x1 +#define MT6351_PMIC_RG_SMT_SRCLKEN_IN0_SHIFT 2 +#define MT6351_PMIC_RG_SMT_SRCLKEN_IN1_ADDR MT6351_SMT_CON0 +#define MT6351_PMIC_RG_SMT_SRCLKEN_IN1_MASK 0x1 +#define MT6351_PMIC_RG_SMT_SRCLKEN_IN1_SHIFT 3 +#define MT6351_PMIC_RG_SMT_RTC_32K1V8_0_ADDR MT6351_SMT_CON0 +#define MT6351_PMIC_RG_SMT_RTC_32K1V8_0_MASK 0x1 +#define MT6351_PMIC_RG_SMT_RTC_32K1V8_0_SHIFT 4 +#define MT6351_PMIC_RG_SMT_RTC_32K1V8_1_ADDR MT6351_SMT_CON0 +#define MT6351_PMIC_RG_SMT_RTC_32K1V8_1_MASK 0x1 +#define MT6351_PMIC_RG_SMT_RTC_32K1V8_1_SHIFT 5 +#define MT6351_PMIC_RG_SMT_SPI_CLK_ADDR MT6351_SMT_CON1 +#define MT6351_PMIC_RG_SMT_SPI_CLK_MASK 0x1 +#define MT6351_PMIC_RG_SMT_SPI_CLK_SHIFT 0 +#define MT6351_PMIC_RG_SMT_SPI_CSN_ADDR MT6351_SMT_CON1 +#define MT6351_PMIC_RG_SMT_SPI_CSN_MASK 0x1 +#define MT6351_PMIC_RG_SMT_SPI_CSN_SHIFT 1 +#define MT6351_PMIC_RG_SMT_SPI_MOSI_ADDR MT6351_SMT_CON1 +#define MT6351_PMIC_RG_SMT_SPI_MOSI_MASK 0x1 +#define MT6351_PMIC_RG_SMT_SPI_MOSI_SHIFT 2 +#define MT6351_PMIC_RG_SMT_SPI_MISO_ADDR MT6351_SMT_CON1 +#define MT6351_PMIC_RG_SMT_SPI_MISO_MASK 0x1 +#define MT6351_PMIC_RG_SMT_SPI_MISO_SHIFT 3 +#define MT6351_PMIC_RG_SMT_AUD_CLK_ADDR MT6351_SMT_CON2 +#define MT6351_PMIC_RG_SMT_AUD_CLK_MASK 0x1 +#define MT6351_PMIC_RG_SMT_AUD_CLK_SHIFT 0 +#define MT6351_PMIC_RG_SMT_AUD_DAT_MOSI_ADDR MT6351_SMT_CON2 +#define MT6351_PMIC_RG_SMT_AUD_DAT_MOSI_MASK 0x1 +#define MT6351_PMIC_RG_SMT_AUD_DAT_MOSI_SHIFT 1 +#define MT6351_PMIC_RG_SMT_AUD_DAT_MISO_ADDR MT6351_SMT_CON2 +#define MT6351_PMIC_RG_SMT_AUD_DAT_MISO_MASK 0x1 +#define MT6351_PMIC_RG_SMT_AUD_DAT_MISO_SHIFT 2 +#define MT6351_PMIC_RG_SMT_ANC_DAT_MOSI_ADDR MT6351_SMT_CON2 +#define MT6351_PMIC_RG_SMT_ANC_DAT_MOSI_MASK 0x1 +#define MT6351_PMIC_RG_SMT_ANC_DAT_MOSI_SHIFT 3 +#define MT6351_PMIC_RG_SMT_VOW_CLK_MISO_ADDR MT6351_SMT_CON2 +#define MT6351_PMIC_RG_SMT_VOW_CLK_MISO_MASK 0x1 +#define MT6351_PMIC_RG_SMT_VOW_CLK_MISO_SHIFT 4 +#define MT6351_PMIC_RG_SMT_ENBB_ADDR MT6351_SMT_CON2 +#define MT6351_PMIC_RG_SMT_ENBB_MASK 0x1 +#define MT6351_PMIC_RG_SMT_ENBB_SHIFT 5 +#define MT6351_PMIC_RG_SMT_XOSC_EN_ADDR MT6351_SMT_CON2 +#define MT6351_PMIC_RG_SMT_XOSC_EN_MASK 0x1 +#define MT6351_PMIC_RG_SMT_XOSC_EN_SHIFT 6 +#define MT6351_PMIC_RG_OCTL_SRCLKEN_IN0_ADDR MT6351_DRV_CON0 +#define MT6351_PMIC_RG_OCTL_SRCLKEN_IN0_MASK 0xF +#define MT6351_PMIC_RG_OCTL_SRCLKEN_IN0_SHIFT 0 +#define MT6351_PMIC_RG_OCTL_SRCLKEN_IN1_ADDR MT6351_DRV_CON0 +#define MT6351_PMIC_RG_OCTL_SRCLKEN_IN1_MASK 0xF +#define MT6351_PMIC_RG_OCTL_SRCLKEN_IN1_SHIFT 4 +#define MT6351_PMIC_RG_OCTL_RTC_32K1V8_0_ADDR MT6351_DRV_CON0 +#define MT6351_PMIC_RG_OCTL_RTC_32K1V8_0_MASK 0xF +#define MT6351_PMIC_RG_OCTL_RTC_32K1V8_0_SHIFT 8 +#define MT6351_PMIC_RG_OCTL_RTC_32K1V8_1_ADDR MT6351_DRV_CON0 +#define MT6351_PMIC_RG_OCTL_RTC_32K1V8_1_MASK 0xF +#define MT6351_PMIC_RG_OCTL_RTC_32K1V8_1_SHIFT 12 +#define MT6351_PMIC_RG_OCTL_SPI_CLK_ADDR MT6351_DRV_CON1 +#define MT6351_PMIC_RG_OCTL_SPI_CLK_MASK 0xF +#define MT6351_PMIC_RG_OCTL_SPI_CLK_SHIFT 0 +#define MT6351_PMIC_RG_OCTL_SPI_CSN_ADDR MT6351_DRV_CON1 +#define MT6351_PMIC_RG_OCTL_SPI_CSN_MASK 0xF +#define MT6351_PMIC_RG_OCTL_SPI_CSN_SHIFT 4 +#define MT6351_PMIC_RG_OCTL_SPI_MOSI_ADDR MT6351_DRV_CON1 +#define MT6351_PMIC_RG_OCTL_SPI_MOSI_MASK 0xF +#define MT6351_PMIC_RG_OCTL_SPI_MOSI_SHIFT 8 +#define MT6351_PMIC_RG_OCTL_SPI_MISO_ADDR MT6351_DRV_CON1 +#define MT6351_PMIC_RG_OCTL_SPI_MISO_MASK 0xF +#define MT6351_PMIC_RG_OCTL_SPI_MISO_SHIFT 12 +#define MT6351_PMIC_RG_OCTL_AUD_DAT_MOSI_ADDR MT6351_DRV_CON2 +#define MT6351_PMIC_RG_OCTL_AUD_DAT_MOSI_MASK 0xF +#define MT6351_PMIC_RG_OCTL_AUD_DAT_MOSI_SHIFT 0 +#define MT6351_PMIC_RG_OCTL_AUD_DAT_MISO_ADDR MT6351_DRV_CON2 +#define MT6351_PMIC_RG_OCTL_AUD_DAT_MISO_MASK 0xF +#define MT6351_PMIC_RG_OCTL_AUD_DAT_MISO_SHIFT 4 +#define MT6351_PMIC_RG_OCTL_AUD_CLK_ADDR MT6351_DRV_CON2 +#define MT6351_PMIC_RG_OCTL_AUD_CLK_MASK 0xF +#define MT6351_PMIC_RG_OCTL_AUD_CLK_SHIFT 8 +#define MT6351_PMIC_RG_OCTL_ANC_DAT_MOSI_ADDR MT6351_DRV_CON2 +#define MT6351_PMIC_RG_OCTL_ANC_DAT_MOSI_MASK 0xF +#define MT6351_PMIC_RG_OCTL_ANC_DAT_MOSI_SHIFT 12 +#define MT6351_PMIC_RG_OCTL_HOMEKEY_ADDR MT6351_DRV_CON3 +#define MT6351_PMIC_RG_OCTL_HOMEKEY_MASK 0xF +#define MT6351_PMIC_RG_OCTL_HOMEKEY_SHIFT 0 +#define MT6351_PMIC_RG_OCTL_ENBB_ADDR MT6351_DRV_CON3 +#define MT6351_PMIC_RG_OCTL_ENBB_MASK 0xF +#define MT6351_PMIC_RG_OCTL_ENBB_SHIFT 4 +#define MT6351_PMIC_RG_OCTL_XOSC_EN_ADDR MT6351_DRV_CON3 +#define MT6351_PMIC_RG_OCTL_XOSC_EN_MASK 0xF +#define MT6351_PMIC_RG_OCTL_XOSC_EN_SHIFT 8 +#define MT6351_PMIC_RG_OCTL_VOW_CLK_MISO_ADDR MT6351_DRV_CON3 +#define MT6351_PMIC_RG_OCTL_VOW_CLK_MISO_MASK 0xF +#define MT6351_PMIC_RG_OCTL_VOW_CLK_MISO_SHIFT 12 +#define MT6351_PMIC_TOP_STATUS_ADDR MT6351_TOP_STATUS +#define MT6351_PMIC_TOP_STATUS_MASK 0xF +#define MT6351_PMIC_TOP_STATUS_SHIFT 0 +#define MT6351_PMIC_TOP_STATUS_SET_ADDR MT6351_TOP_STATUS_SET +#define MT6351_PMIC_TOP_STATUS_SET_MASK 0x3 +#define MT6351_PMIC_TOP_STATUS_SET_SHIFT 0 +#define MT6351_PMIC_TOP_STATUS_CLR_ADDR MT6351_TOP_STATUS_CLR +#define MT6351_PMIC_TOP_STATUS_CLR_MASK 0x3 +#define MT6351_PMIC_TOP_STATUS_CLR_SHIFT 0 +#define MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_SHIFT 0 +#define MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_SHIFT 1 +#define MT6351_PMIC_RG_G_DRV_2M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_G_DRV_2M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_G_DRV_2M_CK_PDN_SHIFT 2 +#define MT6351_PMIC_RG_DRV_32K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_DRV_32K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_32K_CK_PDN_SHIFT 3 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_PDN_SHIFT 4 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_PDN_SHIFT 5 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_PDN_SHIFT 6 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_PDN_SHIFT 7 +#define MT6351_PMIC_RG_AUXADC_1M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_AUXADC_1M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_1M_CK_PDN_SHIFT 8 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_SHIFT 9 +#define MT6351_PMIC_RG_AUXADC_RNG_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_AUXADC_RNG_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_RNG_CK_PDN_SHIFT 10 +#define MT6351_PMIC_RG_AUXADC_26M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_AUXADC_26M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_26M_CK_PDN_SHIFT 11 +#define MT6351_PMIC_RG_AUDNCP_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_AUDNCP_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUDNCP_CK_PDN_SHIFT 12 +#define MT6351_PMIC_RG_AUDIF_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_AUDIF_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUDIF_CK_PDN_SHIFT 13 +#define MT6351_PMIC_RG_AUD_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_AUD_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUD_CK_PDN_SHIFT 14 +#define MT6351_PMIC_RG_ZCD13M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON0 +#define MT6351_PMIC_RG_ZCD13M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_ZCD13M_CK_PDN_SHIFT 15 +#define MT6351_PMIC_TOP_CKPDN_CON0_SET_ADDR MT6351_TOP_CKPDN_CON0_SET +#define MT6351_PMIC_TOP_CKPDN_CON0_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON0_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKPDN_CON0_CLR_ADDR MT6351_TOP_CKPDN_CON0_CLR +#define MT6351_PMIC_TOP_CKPDN_CON0_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON0_CLR_SHIFT 0 +#define MT6351_PMIC_RG_RTC_32K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_RTC_32K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTC_32K_CK_PDN_SHIFT 0 +#define MT6351_PMIC_RG_RTC_MCLK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_RTC_MCLK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTC_MCLK_PDN_SHIFT 1 +#define MT6351_PMIC_RG_RTC_75K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_RTC_75K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTC_75K_CK_PDN_SHIFT 2 +#define MT6351_PMIC_RG_RTCDET_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_RTCDET_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTCDET_CK_PDN_SHIFT 3 +#define MT6351_PMIC_RG_RTC32K_1V8_0_O_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_RTC32K_1V8_0_O_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTC32K_1V8_0_O_PDN_SHIFT 4 +#define MT6351_PMIC_RG_RTC32K_1V8_1_O_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_RTC32K_1V8_1_O_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTC32K_1V8_1_O_PDN_SHIFT 5 +#define MT6351_PMIC_RG_RTC_2SEC_OFF_DET_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_RTC_2SEC_OFF_DET_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTC_2SEC_OFF_DET_PDN_SHIFT 6 +#define MT6351_PMIC_RG_FQMTR_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_FQMTR_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_FQMTR_CK_PDN_SHIFT 7 +#define MT6351_PMIC_RG_STB_1M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_STB_1M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_STB_1M_CK_PDN_SHIFT 8 +#define MT6351_PMIC_RG_BUCK_1M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_BUCK_1M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_1M_CK_PDN_SHIFT 9 +#define MT6351_PMIC_RG_AUXADC_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_AUXADC_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_CK_PDN_SHIFT 10 +#define MT6351_PMIC_RG_PWMOC_6M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_PWMOC_6M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_PWMOC_6M_CK_PDN_SHIFT 11 +#define MT6351_PMIC_RG_PWMOC_AUD_6M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON1 +#define MT6351_PMIC_RG_PWMOC_AUD_6M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_PWMOC_AUD_6M_CK_PDN_SHIFT 12 +#define MT6351_PMIC_TOP_CKPDN_CON1_SET_ADDR MT6351_TOP_CKPDN_CON1_SET +#define MT6351_PMIC_TOP_CKPDN_CON1_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON1_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKPDN_CON1_CLR_ADDR MT6351_TOP_CKPDN_CON1_CLR +#define MT6351_PMIC_TOP_CKPDN_CON1_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON1_CLR_SHIFT 0 +#define MT6351_PMIC_RG_FGADC_ANA_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_FGADC_ANA_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_FGADC_ANA_CK_PDN_SHIFT 2 +#define MT6351_PMIC_RG_FGADC_DIG_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_FGADC_DIG_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_FGADC_DIG_CK_PDN_SHIFT 3 +#define MT6351_PMIC_RG_BIF_X72_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_BIF_X72_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BIF_X72_CK_PDN_SHIFT 4 +#define MT6351_PMIC_RG_BIF_X4_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_BIF_X4_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BIF_X4_CK_PDN_SHIFT 5 +#define MT6351_PMIC_RG_BIF_X1_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_BIF_X1_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BIF_X1_CK_PDN_SHIFT 6 +#define MT6351_PMIC_RG_PCHR_32K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_PCHR_32K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_32K_CK_PDN_SHIFT 7 +#define MT6351_PMIC_RG_ACCDET_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_ACCDET_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_ACCDET_CK_PDN_SHIFT 9 +#define MT6351_PMIC_RG_FQMTR_32K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_FQMTR_32K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_FQMTR_32K_CK_PDN_SHIFT 10 +#define MT6351_PMIC_RG_INTRP_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_INTRP_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_INTRP_CK_PDN_SHIFT 11 +#define MT6351_PMIC_RG_RTC_26M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_RTC_26M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTC_26M_CK_PDN_SHIFT 12 +#define MT6351_PMIC_RG_RTC_EOSC32_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_RTC_EOSC32_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT 13 +#define MT6351_PMIC_RG_TRIM_75K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_TRIM_75K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_TRIM_75K_CK_PDN_SHIFT 14 +#define MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_PDN_ADDR MT6351_TOP_CKPDN_CON2 +#define MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_PDN_SHIFT 15 +#define MT6351_PMIC_TOP_CKPDN_CON2_SET_ADDR MT6351_TOP_CKPDN_CON2_SET +#define MT6351_PMIC_TOP_CKPDN_CON2_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON2_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKPDN_CON2_CLR_ADDR MT6351_TOP_CKPDN_CON2_CLR +#define MT6351_PMIC_TOP_CKPDN_CON2_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON2_CLR_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_75K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_STRUP_75K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_75K_CK_PDN_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_32K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_STRUP_32K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_32K_CK_PDN_SHIFT 1 +#define MT6351_PMIC_RG_EFUSE_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_EFUSE_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_EFUSE_CK_PDN_SHIFT 2 +#define MT6351_PMIC_RG_SMPS_CK_DIV_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_SMPS_CK_DIV_PDN_MASK 0x1 +#define MT6351_PMIC_RG_SMPS_CK_DIV_PDN_SHIFT 3 +#define MT6351_PMIC_RG_SPI_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_SPI_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_SPI_CK_PDN_SHIFT 4 +#define MT6351_PMIC_RG_BGR_TEST_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_BGR_TEST_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BGR_TEST_CK_PDN_SHIFT 5 +#define MT6351_PMIC_RG_FGADC_FT_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_FGADC_FT_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_FGADC_FT_CK_PDN_SHIFT 6 +#define MT6351_PMIC_RG_PCHR_TEST_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_PCHR_TEST_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_TEST_CK_PDN_SHIFT 7 +#define MT6351_PMIC_RG_BUCK_32K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_BUCK_32K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_32K_CK_PDN_SHIFT 8 +#define MT6351_PMIC_RG_BUCK_ANA_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_BUCK_ANA_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_ANA_CK_PDN_SHIFT 9 +#define MT6351_PMIC_RG_EOSC_CALI_TEST_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_EOSC_CALI_TEST_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_EOSC_CALI_TEST_CK_PDN_SHIFT 10 +#define MT6351_PMIC_RG_G_SMPS_TEST_CK_PDN_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_RG_G_SMPS_TEST_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_G_SMPS_TEST_CK_PDN_SHIFT 11 +#define MT6351_PMIC_TOP_CKPDN_CON3_RSV_ADDR MT6351_TOP_CKPDN_CON3 +#define MT6351_PMIC_TOP_CKPDN_CON3_RSV_MASK 0xF +#define MT6351_PMIC_TOP_CKPDN_CON3_RSV_SHIFT 12 +#define MT6351_PMIC_TOP_CKPDN_CON3_SET_ADDR MT6351_TOP_CKPDN_CON3_SET +#define MT6351_PMIC_TOP_CKPDN_CON3_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON3_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKPDN_CON3_CLR_ADDR MT6351_TOP_CKPDN_CON3_CLR +#define MT6351_PMIC_TOP_CKPDN_CON3_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON3_CLR_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON4 +#define MT6351_PMIC_RG_BUCK_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_9M_CK_PDN_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON4 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_SHIFT 1 +#define MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON4 +#define MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_SHIFT 2 +#define MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON4 +#define MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_SHIFT 3 +#define MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON4 +#define MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_SHIFT 5 +#define MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON4 +#define MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_SHIFT 6 +#define MT6351_PMIC_TOP_CKPDN_CON4_RSV_ADDR MT6351_TOP_CKPDN_CON4 +#define MT6351_PMIC_TOP_CKPDN_CON4_RSV_MASK 0x1FF +#define MT6351_PMIC_TOP_CKPDN_CON4_RSV_SHIFT 7 +#define MT6351_PMIC_TOP_CKPDN_CON4_SET_ADDR MT6351_TOP_CKPDN_CON4_SET +#define MT6351_PMIC_TOP_CKPDN_CON4_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON4_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKPDN_CON4_CLR_ADDR MT6351_TOP_CKPDN_CON4_CLR +#define MT6351_PMIC_TOP_CKPDN_CON4_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON4_CLR_SHIFT 0 +#define MT6351_PMIC_RG_LDO_CALI_75K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_LDO_CALI_75K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_LDO_CALI_75K_CK_PDN_SHIFT 0 +#define MT6351_PMIC_RG_INTRP_PRE_OC_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_INTRP_PRE_OC_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_INTRP_PRE_OC_CK_PDN_SHIFT 1 +#define MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_SHIFT 2 +#define MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_SHIFT 3 +#define MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_SHIFT 4 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_SHIFT 5 +#define MT6351_PMIC_RG_VOW32K_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_VOW32K_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_VOW32K_CK_PDN_SHIFT 6 +#define MT6351_PMIC_RG_VOW12M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_VOW12M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_VOW12M_CK_PDN_SHIFT 7 +#define MT6351_PMIC_RG_AUD18M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_AUD18M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_AUD18M_CK_PDN_SHIFT 8 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_PDN_SHIFT 9 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_PDN_SHIFT 10 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_PDN_SHIFT 11 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_PDN_SHIFT 12 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_PDN_SHIFT 13 +#define MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_SHIFT 14 +#define MT6351_PMIC_RG_STB_AUD_1M_CK_PDN_ADDR MT6351_TOP_CKPDN_CON5 +#define MT6351_PMIC_RG_STB_AUD_1M_CK_PDN_MASK 0x1 +#define MT6351_PMIC_RG_STB_AUD_1M_CK_PDN_SHIFT 15 +#define MT6351_PMIC_TOP_CKPDN_CON5_SET_ADDR MT6351_TOP_CKPDN_CON5_SET +#define MT6351_PMIC_TOP_CKPDN_CON5_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON5_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKPDN_CON5_CLR_ADDR MT6351_TOP_CKPDN_CON5_CLR +#define MT6351_PMIC_TOP_CKPDN_CON5_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKPDN_CON5_CLR_SHIFT 0 +#define MT6351_PMIC_RG_AUDIF_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_AUDIF_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUDIF_CK_CKSEL_SHIFT 0 +#define MT6351_PMIC_RG_AUD_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_AUD_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUD_CK_CKSEL_SHIFT 1 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL_SHIFT 2 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL_SHIFT 3 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_CKSEL_SHIFT 4 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_CKSEL_SHIFT 5 +#define MT6351_PMIC_RG_FQMTR_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_FQMTR_CK_CKSEL_MASK 0x7 +#define MT6351_PMIC_RG_FQMTR_CK_CKSEL_SHIFT 6 +#define MT6351_PMIC_RG_75K_32K_SEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_75K_32K_SEL_MASK 0x1 +#define MT6351_PMIC_RG_75K_32K_SEL_SHIFT 9 +#define MT6351_PMIC_RG_AUXADC_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_AUXADC_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_CK_CKSEL_SHIFT 10 +#define MT6351_PMIC_RG_OSC_SEL_HW_SRC_SEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_OSC_SEL_HW_SRC_SEL_MASK 0x3 +#define MT6351_PMIC_RG_OSC_SEL_HW_SRC_SEL_SHIFT 12 +#define MT6351_PMIC_RG_SRCLKEN_SRC_SEL_ADDR MT6351_TOP_CKSEL_CON0 +#define MT6351_PMIC_RG_SRCLKEN_SRC_SEL_MASK 0x3 +#define MT6351_PMIC_RG_SRCLKEN_SRC_SEL_SHIFT 14 +#define MT6351_PMIC_TOP_CKSEL_CON_SET_ADDR MT6351_TOP_CKSEL_CON0_SET +#define MT6351_PMIC_TOP_CKSEL_CON_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKSEL_CON_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKSEL_CON_CLR_ADDR MT6351_TOP_CKSEL_CON0_CLR +#define MT6351_PMIC_TOP_CKSEL_CON_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKSEL_CON_CLR_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_75K_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_STRUP_75K_CK_CKSEL_MASK 0x3 +#define MT6351_PMIC_RG_STRUP_75K_CK_CKSEL_SHIFT 0 +#define MT6351_PMIC_RG_BGR_TEST_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_BGR_TEST_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_BGR_TEST_CK_CKSEL_SHIFT 2 +#define MT6351_PMIC_RG_PCHR_TEST_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_PCHR_TEST_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_TEST_CK_CKSEL_SHIFT 3 +#define MT6351_PMIC_RG_FGADC_ANA_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_FGADC_ANA_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_FGADC_ANA_CK_CKSEL_SHIFT 4 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL_SHIFT 5 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL_SHIFT 6 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_CKSEL_SHIFT 7 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_CKSEL_SHIFT 8 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_CKSEL_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_CKSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_CKSEL_SHIFT 9 +#define MT6351_PMIC_RG_TOP_CKSEL_CON1_RSV_ADDR MT6351_TOP_CKSEL_CON1 +#define MT6351_PMIC_RG_TOP_CKSEL_CON1_RSV_MASK 0x3F +#define MT6351_PMIC_RG_TOP_CKSEL_CON1_RSV_SHIFT 10 +#define MT6351_PMIC_TOP_CKSEL_CON1_SET_ADDR MT6351_TOP_CKSEL_CON1_SET +#define MT6351_PMIC_TOP_CKSEL_CON1_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKSEL_CON1_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKSEL_CON1_CLR_ADDR MT6351_TOP_CKSEL_CON1_CLR +#define MT6351_PMIC_TOP_CKSEL_CON1_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKSEL_CON1_CLR_SHIFT 0 +#define MT6351_PMIC_RG_SRCVOLTEN_SW_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_SRCVOLTEN_SW_MASK 0x1 +#define MT6351_PMIC_RG_SRCVOLTEN_SW_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_BUCK_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_OSC_SEL_SW_SHIFT 2 +#define MT6351_PMIC_RG_VOWEN_SW_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_VOWEN_SW_MASK 0x1 +#define MT6351_PMIC_RG_VOWEN_SW_SHIFT 3 +#define MT6351_PMIC_RG_SRCVOLTEN_MODE_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_SRCVOLTEN_MODE_MASK 0x1 +#define MT6351_PMIC_RG_SRCVOLTEN_MODE_SHIFT 4 +#define MT6351_PMIC_RG_BUCK_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_BUCK_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_OSC_SEL_MODE_SHIFT 6 +#define MT6351_PMIC_RG_VOWEN_MODE_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_VOWEN_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VOWEN_MODE_SHIFT 7 +#define MT6351_PMIC_RG_TOP_CKSEL_CON2_RSV_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_TOP_CKSEL_CON2_RSV_MASK 0x3F +#define MT6351_PMIC_RG_TOP_CKSEL_CON2_RSV_SHIFT 8 +#define MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_SW_SHIFT 14 +#define MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON2 +#define MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_MODE_SHIFT 15 +#define MT6351_PMIC_TOP_CKSEL_CON2_SET_ADDR MT6351_TOP_CKSEL_CON2_SET +#define MT6351_PMIC_TOP_CKSEL_CON2_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKSEL_CON2_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKSEL_CON2_CLR_ADDR MT6351_TOP_CKSEL_CON2_CLR +#define MT6351_PMIC_TOP_CKSEL_CON2_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKSEL_CON2_CLR_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_SW_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW_SHIFT 1 +#define MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_SW_SHIFT 2 +#define MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_SW_SHIFT 3 +#define MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_SW_SHIFT 4 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW_SHIFT 5 +#define MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_SW_SHIFT 6 +#define MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_SW_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_SW_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_SW_SHIFT 7 +#define MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_MODE_SHIFT 8 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE_SHIFT 9 +#define MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_MODE_SHIFT 10 +#define MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE_SHIFT 11 +#define MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_MODE_SHIFT 12 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE_SHIFT 13 +#define MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_MODE_SHIFT 14 +#define MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_MODE_ADDR MT6351_TOP_CKSEL_CON3 +#define MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_MODE_SHIFT 15 +#define MT6351_PMIC_TOP_CKSEL_CON3_SET_ADDR MT6351_TOP_CKSEL_CON3_SET +#define MT6351_PMIC_TOP_CKSEL_CON3_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKSEL_CON3_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKSEL_CON3_CLR_ADDR MT6351_TOP_CKSEL_CON3_CLR +#define MT6351_PMIC_TOP_CKSEL_CON3_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKSEL_CON3_CLR_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL_ADDR MT6351_TOP_CKDIVSEL_CON0 +#define MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL_MASK 0x3 +#define MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL_SHIFT 0 +#define MT6351_PMIC_TOP_CKDIVSEL_CON_RSV_ADDR MT6351_TOP_CKDIVSEL_CON0 +#define MT6351_PMIC_TOP_CKDIVSEL_CON_RSV_MASK 0x3 +#define MT6351_PMIC_TOP_CKDIVSEL_CON_RSV_SHIFT 2 +#define MT6351_PMIC_RG_BIF_X4_CK_DIVSEL_ADDR MT6351_TOP_CKDIVSEL_CON0 +#define MT6351_PMIC_RG_BIF_X4_CK_DIVSEL_MASK 0x7 +#define MT6351_PMIC_RG_BIF_X4_CK_DIVSEL_SHIFT 4 +#define MT6351_PMIC_RG_REG_CK_DIVSEL_ADDR MT6351_TOP_CKDIVSEL_CON0 +#define MT6351_PMIC_RG_REG_CK_DIVSEL_MASK 0x3 +#define MT6351_PMIC_RG_REG_CK_DIVSEL_SHIFT 8 +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_RSV_ADDR MT6351_TOP_CKDIVSEL_CON0 +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_RSV_MASK 0x3F +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_RSV_SHIFT 10 +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_SET_ADDR MT6351_TOP_CKDIVSEL_CON0_SET +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_CLR_ADDR MT6351_TOP_CKDIVSEL_CON0_CLR +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKDIVSEL_CON0_CLR_SHIFT 0 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_DIVSEL_ADDR MT6351_TOP_CKDIVSEL_CON1 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_DIVSEL_MASK 0x3 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_DIVSEL_SHIFT 0 +#define MT6351_PMIC_RG_AUXADC_26M_CK_DIVSEL_ADDR MT6351_TOP_CKDIVSEL_CON1 +#define MT6351_PMIC_RG_AUXADC_26M_CK_DIVSEL_MASK 0x3 +#define MT6351_PMIC_RG_AUXADC_26M_CK_DIVSEL_SHIFT 2 +#define MT6351_PMIC_RG_BUCK_9M_CK_DIVSEL_ADDR MT6351_TOP_CKDIVSEL_CON1 +#define MT6351_PMIC_RG_BUCK_9M_CK_DIVSEL_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_9M_CK_DIVSEL_SHIFT 4 +#define MT6351_PMIC_TOP_CKDIVSEL_CON1_SET_ADDR MT6351_TOP_CKDIVSEL_CON1_SET +#define MT6351_PMIC_TOP_CKDIVSEL_CON1_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKDIVSEL_CON1_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKDIVSEL_CON1_CLR_ADDR MT6351_TOP_CKDIVSEL_CON1_CLR +#define MT6351_PMIC_TOP_CKDIVSEL_CON1_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKDIVSEL_CON1_CLR_SHIFT 0 +#define MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_HWEN_SHIFT 0 +#define MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN_SHIFT 1 +#define MT6351_PMIC_RG_G_DRV_2M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_G_DRV_2M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_G_DRV_2M_CK_PDN_HWEN_SHIFT 2 +#define MT6351_PMIC_RG_AUXADC_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_AUXADC_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_CK_PDN_HWEN_SHIFT 3 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN_SHIFT 4 +#define MT6351_PMIC_RG_BUCK_1M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_BUCK_1M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_1M_CK_PDN_HWEN_SHIFT 5 +#define MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_SHIFT 6 +#define MT6351_PMIC_RG_RTC_26M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_RTC_26M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_RTC_26M_CK_PDN_HWEN_SHIFT 7 +#define MT6351_PMIC_RG_AUXADC_26M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_AUXADC_26M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_26M_CK_PDN_HWEN_SHIFT 10 +#define MT6351_PMIC_RG_AUXADC_CK_CKSEL_HWEN_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_RG_AUXADC_CK_CKSEL_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_CK_CKSEL_HWEN_SHIFT 11 +#define MT6351_PMIC_TOP_CKHWEN_CON0_RSV_ADDR MT6351_TOP_CKHWEN_CON0 +#define MT6351_PMIC_TOP_CKHWEN_CON0_RSV_MASK 0xF +#define MT6351_PMIC_TOP_CKHWEN_CON0_RSV_SHIFT 12 +#define MT6351_PMIC_TOP_CKHWEN_CON0_SET_ADDR MT6351_TOP_CKHWEN_CON0_SET +#define MT6351_PMIC_TOP_CKHWEN_CON0_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKHWEN_CON0_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKHWEN_CON0_CLR_ADDR MT6351_TOP_CKHWEN_CON0_CLR +#define MT6351_PMIC_TOP_CKHWEN_CON0_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKHWEN_CON0_CLR_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON1 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON1 +#define MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN_SHIFT 1 +#define MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON1 +#define MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN_SHIFT 2 +#define MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON1 +#define MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN_SHIFT 4 +#define MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON1 +#define MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN_SHIFT 5 +#define MT6351_PMIC_TOP_CKHWEN_CON1_RSV_ADDR MT6351_TOP_CKHWEN_CON1 +#define MT6351_PMIC_TOP_CKHWEN_CON1_RSV_MASK 0xF +#define MT6351_PMIC_TOP_CKHWEN_CON1_RSV_SHIFT 12 +#define MT6351_PMIC_TOP_CKHWEN_CON1_SET_ADDR MT6351_TOP_CKHWEN_CON1_SET +#define MT6351_PMIC_TOP_CKHWEN_CON1_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKHWEN_CON1_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKHWEN_CON1_CLR_ADDR MT6351_TOP_CKHWEN_CON1_CLR +#define MT6351_PMIC_TOP_CKHWEN_CON1_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKHWEN_CON1_CLR_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON2 +#define MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN_SHIFT 0 +#define MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON2 +#define MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN_SHIFT 1 +#define MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON2 +#define MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN_SHIFT 2 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON2 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN_SHIFT 3 +#define MT6351_PMIC_RG_AUD18M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON2 +#define MT6351_PMIC_RG_AUD18M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_AUD18M_CK_PDN_HWEN_SHIFT 4 +#define MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN_ADDR MT6351_TOP_CKHWEN_CON2 +#define MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN_SHIFT 5 +#define MT6351_PMIC_TOP_CKHWEN_CON2_RSV_ADDR MT6351_TOP_CKHWEN_CON2 +#define MT6351_PMIC_TOP_CKHWEN_CON2_RSV_MASK 0x3FF +#define MT6351_PMIC_TOP_CKHWEN_CON2_RSV_SHIFT 6 +#define MT6351_PMIC_TOP_CKHWEN_CON2_SET_ADDR MT6351_TOP_CKHWEN_CON2_SET +#define MT6351_PMIC_TOP_CKHWEN_CON2_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKHWEN_CON2_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CKHWEN_CON2_CLR_ADDR MT6351_TOP_CKHWEN_CON2_CLR +#define MT6351_PMIC_TOP_CKHWEN_CON2_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CKHWEN_CON2_CLR_SHIFT 0 +#define MT6351_PMIC_RG_PMU75K_CK_TST_DIS_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_RG_PMU75K_CK_TST_DIS_MASK 0x1 +#define MT6351_PMIC_RG_PMU75K_CK_TST_DIS_SHIFT 0 +#define MT6351_PMIC_RG_SMPS_CK_TST_DIS_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_RG_SMPS_CK_TST_DIS_MASK 0x1 +#define MT6351_PMIC_RG_SMPS_CK_TST_DIS_SHIFT 1 +#define MT6351_PMIC_RG_AUD26M_CK_TST_DIS_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_RG_AUD26M_CK_TST_DIS_MASK 0x1 +#define MT6351_PMIC_RG_AUD26M_CK_TST_DIS_SHIFT 2 +#define MT6351_PMIC_RG_RTC32K_CK_TST_DIS_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_RG_RTC32K_CK_TST_DIS_MASK 0x1 +#define MT6351_PMIC_RG_RTC32K_CK_TST_DIS_SHIFT 4 +#define MT6351_PMIC_RG_FG_CK_TST_DIS_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_RG_FG_CK_TST_DIS_MASK 0x1 +#define MT6351_PMIC_RG_FG_CK_TST_DIS_SHIFT 6 +#define MT6351_PMIC_RG_RTC26M_CK_TST_DIS_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_RG_RTC26M_CK_TST_DIS_MASK 0x1 +#define MT6351_PMIC_RG_RTC26M_CK_TST_DIS_SHIFT 7 +#define MT6351_PMIC_RG_VOW12M_CK_TST_DIS_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_RG_VOW12M_CK_TST_DIS_MASK 0x1 +#define MT6351_PMIC_RG_VOW12M_CK_TST_DIS_SHIFT 8 +#define MT6351_PMIC_TOP_CKTST_CON0_RSV_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_TOP_CKTST_CON0_RSV_MASK 0x3F +#define MT6351_PMIC_TOP_CKTST_CON0_RSV_SHIFT 9 +#define MT6351_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_ADDR MT6351_TOP_CKTST_CON0 +#define MT6351_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_MASK 0x1 +#define MT6351_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_SHIFT 15 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK0_CK_TSTSEL_SHIFT 0 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK1_CK_TSTSEL_SHIFT 1 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK2_CK_TSTSEL_SHIFT 2 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK3_CK_TSTSEL_SHIFT 3 +#define MT6351_PMIC_RG_FQMTR_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_FQMTR_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_FQMTR_CK_TSTSEL_SHIFT 4 +#define MT6351_PMIC_RG_RTCDET_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_RTCDET_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_RTCDET_CK_TSTSEL_SHIFT 5 +#define MT6351_PMIC_RG_PMU75K_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_PMU75K_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_PMU75K_CK_TSTSEL_SHIFT 6 +#define MT6351_PMIC_RG_SMPS_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_SMPS_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_SMPS_CK_TSTSEL_SHIFT 7 +#define MT6351_PMIC_RG_AUD26M_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_AUD26M_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUD26M_CK_TSTSEL_SHIFT 8 +#define MT6351_PMIC_RG_AUDIF_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_AUDIF_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUDIF_CK_TSTSEL_SHIFT 10 +#define MT6351_PMIC_RG_AUD_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_AUD_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUD_CK_TSTSEL_SHIFT 11 +#define MT6351_PMIC_RG_STRUP_75K_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_STRUP_75K_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_75K_CK_TSTSEL_SHIFT 12 +#define MT6351_PMIC_RG_RTC32K_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_RTC32K_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_RTC32K_CK_TSTSEL_SHIFT 13 +#define MT6351_PMIC_RG_PCHR_TEST_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_PCHR_TEST_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_TEST_CK_TSTSEL_SHIFT 14 +#define MT6351_PMIC_RG_BGR_TEST_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON1 +#define MT6351_PMIC_RG_BGR_TEST_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_BGR_TEST_CK_TSTSEL_SHIFT 15 +#define MT6351_PMIC_RG_FG_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_FG_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_FG_CK_TSTSEL_SHIFT 0 +#define MT6351_PMIC_RG_FGADC_ANA_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_FGADC_ANA_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_FGADC_ANA_CK_TSTSEL_SHIFT 1 +#define MT6351_PMIC_RG_RTC26M_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_RTC26M_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_RTC26M_CK_TSTSEL_SHIFT 3 +#define MT6351_PMIC_RG_RTC_EOSC32_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_RTC_EOSC32_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_RTC_EOSC32_CK_TSTSEL_SHIFT 4 +#define MT6351_PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL_SHIFT 5 +#define MT6351_PMIC_RG_AUXADC_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_AUXADC_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_CK_TSTSEL_SHIFT 6 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_SMPS_CK_TSTSEL_SHIFT 7 +#define MT6351_PMIC_RG_AUXADC_26M_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_AUXADC_26M_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_26M_CK_TSTSEL_SHIFT 8 +#define MT6351_PMIC_RG_VOW12M_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_VOW12M_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_VOW12M_CK_TSTSEL_SHIFT 9 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK4_CK_TSTSEL_SHIFT 10 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK5_CK_TSTSEL_SHIFT 11 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK6_CK_TSTSEL_SHIFT 12 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_ISINK7_CK_TSTSEL_SHIFT 13 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_TSTSEL_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_TSTSEL_MASK 0x1 +#define MT6351_PMIC_RG_DRV_CHRIND_CK_TSTSEL_SHIFT 14 +#define MT6351_PMIC_TOP_CKTST_CON2_RSV_ADDR MT6351_TOP_CKTST_CON2 +#define MT6351_PMIC_TOP_CKTST_CON2_RSV_MASK 0x1 +#define MT6351_PMIC_TOP_CKTST_CON2_RSV_SHIFT 15 +#define MT6351_PMIC_RG_CLKSQ_EN_AUD_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_EN_AUD_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_EN_AUD_SHIFT 0 +#define MT6351_PMIC_RG_CLKSQ_EN_FQR_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_EN_FQR_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_EN_FQR_SHIFT 1 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_SHIFT 2 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_SHIFT 3 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_GPS_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_GPS_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_GPS_SHIFT 4 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_RSV_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_RSV_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_RSV_SHIFT 5 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MODE_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MODE_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MODE_SHIFT 8 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MODE_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MODE_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MODE_SHIFT 9 +#define MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SHIFT 10 +#define MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_SHIFT 11 +#define MT6351_PMIC_TOP_CLKSQ_RSV_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_TOP_CLKSQ_RSV_MASK 0x7 +#define MT6351_PMIC_TOP_CLKSQ_RSV_SHIFT 12 +#define MT6351_PMIC_DA_CLKSQ_EN_VA18_ADDR MT6351_TOP_CLKSQ +#define MT6351_PMIC_DA_CLKSQ_EN_VA18_MASK 0x1 +#define MT6351_PMIC_DA_CLKSQ_EN_VA18_SHIFT 15 +#define MT6351_PMIC_TOP_CLKSQ_SET_ADDR MT6351_TOP_CLKSQ_SET +#define MT6351_PMIC_TOP_CLKSQ_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CLKSQ_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CLKSQ_CLR_ADDR MT6351_TOP_CLKSQ_CLR +#define MT6351_PMIC_TOP_CLKSQ_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CLKSQ_CLR_SHIFT 0 +#define MT6351_PMIC_RG_CLKSQ_RTC_EN_ADDR MT6351_TOP_CLKSQ_RTC +#define MT6351_PMIC_RG_CLKSQ_RTC_EN_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_RTC_EN_SHIFT 0 +#define MT6351_PMIC_RG_CLKSQ_RTC_EN_HW_MODE_ADDR MT6351_TOP_CLKSQ_RTC +#define MT6351_PMIC_RG_CLKSQ_RTC_EN_HW_MODE_MASK 0x1 +#define MT6351_PMIC_RG_CLKSQ_RTC_EN_HW_MODE_SHIFT 1 +#define MT6351_PMIC_TOP_CLKSQ_RTC_RSV0_ADDR MT6351_TOP_CLKSQ_RTC +#define MT6351_PMIC_TOP_CLKSQ_RTC_RSV0_MASK 0xF +#define MT6351_PMIC_TOP_CLKSQ_RTC_RSV0_SHIFT 2 +#define MT6351_PMIC_RG_ENBB_SEL_ADDR MT6351_TOP_CLKSQ_RTC +#define MT6351_PMIC_RG_ENBB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_ENBB_SEL_SHIFT 8 +#define MT6351_PMIC_RG_XOSC_EN_SEL_ADDR MT6351_TOP_CLKSQ_RTC +#define MT6351_PMIC_RG_XOSC_EN_SEL_MASK 0x1 +#define MT6351_PMIC_RG_XOSC_EN_SEL_SHIFT 9 +#define MT6351_PMIC_TOP_CLKSQ_RTC_RSV1_ADDR MT6351_TOP_CLKSQ_RTC +#define MT6351_PMIC_TOP_CLKSQ_RTC_RSV1_MASK 0x3 +#define MT6351_PMIC_TOP_CLKSQ_RTC_RSV1_SHIFT 10 +#define MT6351_PMIC_DA_CLKSQ_EN_VDIG18_ADDR MT6351_TOP_CLKSQ_RTC +#define MT6351_PMIC_DA_CLKSQ_EN_VDIG18_MASK 0x1 +#define MT6351_PMIC_DA_CLKSQ_EN_VDIG18_SHIFT 15 +#define MT6351_PMIC_TOP_CLKSQ_RTC_SET_ADDR MT6351_TOP_CLKSQ_RTC_SET +#define MT6351_PMIC_TOP_CLKSQ_RTC_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_CLKSQ_RTC_SET_SHIFT 0 +#define MT6351_PMIC_TOP_CLKSQ_RTC_CLR_ADDR MT6351_TOP_CLKSQ_RTC_CLR +#define MT6351_PMIC_TOP_CLKSQ_RTC_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_CLKSQ_RTC_CLR_SHIFT 0 +#define MT6351_PMIC_OSC_75K_TRIM_ADDR MT6351_TOP_CLK_TRIM +#define MT6351_PMIC_OSC_75K_TRIM_MASK 0x1F +#define MT6351_PMIC_OSC_75K_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_OSC_75K_TRIM_EN_ADDR MT6351_TOP_CLK_TRIM +#define MT6351_PMIC_RG_OSC_75K_TRIM_EN_MASK 0x1 +#define MT6351_PMIC_RG_OSC_75K_TRIM_EN_SHIFT 5 +#define MT6351_PMIC_RG_OSC_75K_TRIM_RATE_ADDR MT6351_TOP_CLK_TRIM +#define MT6351_PMIC_RG_OSC_75K_TRIM_RATE_MASK 0x3 +#define MT6351_PMIC_RG_OSC_75K_TRIM_RATE_SHIFT 6 +#define MT6351_PMIC_DA_OSC_75K_TRIM_ADDR MT6351_TOP_CLK_TRIM +#define MT6351_PMIC_DA_OSC_75K_TRIM_MASK 0x1F +#define MT6351_PMIC_DA_OSC_75K_TRIM_SHIFT 8 +#define MT6351_PMIC_RG_EFUSE_MAN_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_EFUSE_MAN_RST_MASK 0x1 +#define MT6351_PMIC_RG_EFUSE_MAN_RST_SHIFT 0 +#define MT6351_PMIC_RG_AUXADC_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_AUXADC_RST_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_RST_SHIFT 1 +#define MT6351_PMIC_RG_AUXADC_REG_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_AUXADC_REG_RST_MASK 0x1 +#define MT6351_PMIC_RG_AUXADC_REG_RST_SHIFT 2 +#define MT6351_PMIC_RG_AUDIO_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_AUDIO_RST_MASK 0x1 +#define MT6351_PMIC_RG_AUDIO_RST_SHIFT 3 +#define MT6351_PMIC_RG_ACCDET_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_ACCDET_RST_MASK 0x1 +#define MT6351_PMIC_RG_ACCDET_RST_SHIFT 4 +#define MT6351_PMIC_RG_BIF_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_BIF_RST_MASK 0x1 +#define MT6351_PMIC_RG_BIF_RST_SHIFT 5 +#define MT6351_PMIC_RG_DRIVER_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_DRIVER_RST_MASK 0x1 +#define MT6351_PMIC_RG_DRIVER_RST_SHIFT 6 +#define MT6351_PMIC_RG_FGADC_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_FGADC_RST_MASK 0x1 +#define MT6351_PMIC_RG_FGADC_RST_SHIFT 7 +#define MT6351_PMIC_RG_FQMTR_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_FQMTR_RST_MASK 0x1 +#define MT6351_PMIC_RG_FQMTR_RST_SHIFT 8 +#define MT6351_PMIC_RG_RTC_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_RTC_RST_MASK 0x1 +#define MT6351_PMIC_RG_RTC_RST_SHIFT 9 +#define MT6351_PMIC_RG_CHRWDT_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_CHRWDT_RST_MASK 0x1 +#define MT6351_PMIC_RG_CHRWDT_RST_SHIFT 11 +#define MT6351_PMIC_RG_ZCD_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_ZCD_RST_MASK 0x1 +#define MT6351_PMIC_RG_ZCD_RST_SHIFT 12 +#define MT6351_PMIC_RG_AUDNCP_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_AUDNCP_RST_MASK 0x1 +#define MT6351_PMIC_RG_AUDNCP_RST_SHIFT 13 +#define MT6351_PMIC_RG_CLK_TRIM_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_CLK_TRIM_RST_MASK 0x1 +#define MT6351_PMIC_RG_CLK_TRIM_RST_SHIFT 14 +#define MT6351_PMIC_RG_LDO_CALI_RST_ADDR MT6351_TOP_RST_CON0 +#define MT6351_PMIC_RG_LDO_CALI_RST_MASK 0x1 +#define MT6351_PMIC_RG_LDO_CALI_RST_SHIFT 15 +#define MT6351_PMIC_TOP_RST_CON0_SET_ADDR MT6351_TOP_RST_CON0_SET +#define MT6351_PMIC_TOP_RST_CON0_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_RST_CON0_SET_SHIFT 0 +#define MT6351_PMIC_TOP_RST_CON0_CLR_ADDR MT6351_TOP_RST_CON0_CLR +#define MT6351_PMIC_TOP_RST_CON0_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_RST_CON0_CLR_SHIFT 0 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_RST_ADDR MT6351_TOP_RST_CON1 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_RST_MASK 0x1 +#define MT6351_PMIC_RG_STRUP_LONG_PRESS_RST_SHIFT 0 +#define MT6351_PMIC_TOP_RST_CON1_RSV_ADDR MT6351_TOP_RST_CON1 +#define MT6351_PMIC_TOP_RST_CON1_RSV_MASK 0x1F +#define MT6351_PMIC_TOP_RST_CON1_RSV_SHIFT 1 +#define MT6351_PMIC_TOP_RST_CON1_SET_ADDR MT6351_TOP_RST_CON1_SET +#define MT6351_PMIC_TOP_RST_CON1_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_RST_CON1_SET_SHIFT 0 +#define MT6351_PMIC_TOP_RST_CON1_CLR_ADDR MT6351_TOP_RST_CON1_CLR +#define MT6351_PMIC_TOP_RST_CON1_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_RST_CON1_CLR_SHIFT 0 +#define MT6351_PMIC_RG_CHR_LDO_DET_MODE_ADDR MT6351_TOP_RST_CON2 +#define MT6351_PMIC_RG_CHR_LDO_DET_MODE_MASK 0x1 +#define MT6351_PMIC_RG_CHR_LDO_DET_MODE_SHIFT 0 +#define MT6351_PMIC_RG_CHR_LDO_DET_SW_ADDR MT6351_TOP_RST_CON2 +#define MT6351_PMIC_RG_CHR_LDO_DET_SW_MASK 0x1 +#define MT6351_PMIC_RG_CHR_LDO_DET_SW_SHIFT 1 +#define MT6351_PMIC_RG_CHRWDT_FLAG_MODE_ADDR MT6351_TOP_RST_CON2 +#define MT6351_PMIC_RG_CHRWDT_FLAG_MODE_MASK 0x1 +#define MT6351_PMIC_RG_CHRWDT_FLAG_MODE_SHIFT 2 +#define MT6351_PMIC_RG_CHRWDT_FLAG_SW_ADDR MT6351_TOP_RST_CON2 +#define MT6351_PMIC_RG_CHRWDT_FLAG_SW_MASK 0x1 +#define MT6351_PMIC_RG_CHRWDT_FLAG_SW_SHIFT 3 +#define MT6351_PMIC_TOP_RST_CON2_RSV_ADDR MT6351_TOP_RST_CON2 +#define MT6351_PMIC_TOP_RST_CON2_RSV_MASK 0xF +#define MT6351_PMIC_TOP_RST_CON2_RSV_SHIFT 4 +#define MT6351_PMIC_RG_WDTRSTB_EN_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_RG_WDTRSTB_EN_MASK 0x1 +#define MT6351_PMIC_RG_WDTRSTB_EN_SHIFT 0 +#define MT6351_PMIC_RG_WDTRSTB_MODE_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_RG_WDTRSTB_MODE_MASK 0x1 +#define MT6351_PMIC_RG_WDTRSTB_MODE_SHIFT 1 +#define MT6351_PMIC_WDTRSTB_STATUS_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_WDTRSTB_STATUS_MASK 0x1 +#define MT6351_PMIC_WDTRSTB_STATUS_SHIFT 2 +#define MT6351_PMIC_WDTRSTB_STATUS_CLR_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_WDTRSTB_STATUS_CLR_MASK 0x1 +#define MT6351_PMIC_WDTRSTB_STATUS_CLR_SHIFT 3 +#define MT6351_PMIC_RG_WDTRSTB_FB_EN_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_RG_WDTRSTB_FB_EN_MASK 0x1 +#define MT6351_PMIC_RG_WDTRSTB_FB_EN_SHIFT 4 +#define MT6351_PMIC_RG_WDTRSTB_DEB_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_RG_WDTRSTB_DEB_MASK 0x1 +#define MT6351_PMIC_RG_WDTRSTB_DEB_SHIFT 5 +#define MT6351_PMIC_RG_HOMEKEY_RST_EN_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_RG_HOMEKEY_RST_EN_MASK 0x1 +#define MT6351_PMIC_RG_HOMEKEY_RST_EN_SHIFT 8 +#define MT6351_PMIC_RG_PWRKEY_RST_EN_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_RG_PWRKEY_RST_EN_MASK 0x1 +#define MT6351_PMIC_RG_PWRKEY_RST_EN_SHIFT 9 +#define MT6351_PMIC_RG_PWRRST_TMR_DIS_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_RG_PWRRST_TMR_DIS_MASK 0x1 +#define MT6351_PMIC_RG_PWRRST_TMR_DIS_SHIFT 10 +#define MT6351_PMIC_RG_PWRKEY_RST_TD_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_RG_PWRKEY_RST_TD_MASK 0x3 +#define MT6351_PMIC_RG_PWRKEY_RST_TD_SHIFT 12 +#define MT6351_PMIC_TOP_RST_MISC_RSV_ADDR MT6351_TOP_RST_MISC +#define MT6351_PMIC_TOP_RST_MISC_RSV_MASK 0x3 +#define MT6351_PMIC_TOP_RST_MISC_RSV_SHIFT 14 +#define MT6351_PMIC_TOP_RST_MISC_SET_ADDR MT6351_TOP_RST_MISC_SET +#define MT6351_PMIC_TOP_RST_MISC_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_RST_MISC_SET_SHIFT 0 +#define MT6351_PMIC_TOP_RST_MISC_CLR_ADDR MT6351_TOP_RST_MISC_CLR +#define MT6351_PMIC_TOP_RST_MISC_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_RST_MISC_CLR_SHIFT 0 +#define MT6351_PMIC_VPWRIN_RSTB_STATUS_ADDR MT6351_TOP_RST_STATUS +#define MT6351_PMIC_VPWRIN_RSTB_STATUS_MASK 0x1 +#define MT6351_PMIC_VPWRIN_RSTB_STATUS_SHIFT 0 +#define MT6351_PMIC_DDLO_RSTB_STATUS_ADDR MT6351_TOP_RST_STATUS +#define MT6351_PMIC_DDLO_RSTB_STATUS_MASK 0x1 +#define MT6351_PMIC_DDLO_RSTB_STATUS_SHIFT 1 +#define MT6351_PMIC_UVLO_RSTB_STATUS_ADDR MT6351_TOP_RST_STATUS +#define MT6351_PMIC_UVLO_RSTB_STATUS_MASK 0x1 +#define MT6351_PMIC_UVLO_RSTB_STATUS_SHIFT 2 +#define MT6351_PMIC_RTC_DDLO_RSTB_STATUS_ADDR MT6351_TOP_RST_STATUS +#define MT6351_PMIC_RTC_DDLO_RSTB_STATUS_MASK 0x1 +#define MT6351_PMIC_RTC_DDLO_RSTB_STATUS_SHIFT 3 +#define MT6351_PMIC_CHRWDT_REG_RSTB_STATUS_ADDR MT6351_TOP_RST_STATUS +#define MT6351_PMIC_CHRWDT_REG_RSTB_STATUS_MASK 0x1 +#define MT6351_PMIC_CHRWDT_REG_RSTB_STATUS_SHIFT 4 +#define MT6351_PMIC_CHRDET_REG_RSTB_STATUS_ADDR MT6351_TOP_RST_STATUS +#define MT6351_PMIC_CHRDET_REG_RSTB_STATUS_MASK 0x1 +#define MT6351_PMIC_CHRDET_REG_RSTB_STATUS_SHIFT 5 +#define MT6351_PMIC_TOP_RST_STATUS_RSV_ADDR MT6351_TOP_RST_STATUS +#define MT6351_PMIC_TOP_RST_STATUS_RSV_MASK 0x3 +#define MT6351_PMIC_TOP_RST_STATUS_RSV_SHIFT 6 +#define MT6351_PMIC_TOP_RST_STATUS_SET_ADDR MT6351_TOP_RST_STATUS_SET +#define MT6351_PMIC_TOP_RST_STATUS_SET_MASK 0xFFFF +#define MT6351_PMIC_TOP_RST_STATUS_SET_SHIFT 0 +#define MT6351_PMIC_TOP_RST_STATUS_CLR_ADDR MT6351_TOP_RST_STATUS_CLR +#define MT6351_PMIC_TOP_RST_STATUS_CLR_MASK 0xFFFF +#define MT6351_PMIC_TOP_RST_STATUS_CLR_SHIFT 0 +#define MT6351_PMIC_RG_INT_EN_PWRKEY_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_PWRKEY_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_PWRKEY_SHIFT 0 +#define MT6351_PMIC_RG_INT_EN_HOMEKEY_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_HOMEKEY_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_HOMEKEY_SHIFT 1 +#define MT6351_PMIC_RG_INT_EN_PWRKEY_R_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_PWRKEY_R_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_PWRKEY_R_SHIFT 2 +#define MT6351_PMIC_RG_INT_EN_HOMEKEY_R_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_HOMEKEY_R_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_HOMEKEY_R_SHIFT 3 +#define MT6351_PMIC_RG_INT_EN_THR_H_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_THR_H_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_THR_H_SHIFT 4 +#define MT6351_PMIC_RG_INT_EN_THR_L_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_THR_L_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_THR_L_SHIFT 5 +#define MT6351_PMIC_RG_INT_EN_BAT_H_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_BAT_H_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_BAT_H_SHIFT 6 +#define MT6351_PMIC_RG_INT_EN_BAT_L_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_BAT_L_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_BAT_L_SHIFT 7 +#define MT6351_PMIC_RG_INT_EN_RTC_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_RTC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_RTC_SHIFT 9 +#define MT6351_PMIC_RG_INT_EN_AUDIO_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_AUDIO_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_AUDIO_SHIFT 10 +#define MT6351_PMIC_RG_INT_EN_MAD_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_MAD_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_MAD_SHIFT 11 +#define MT6351_PMIC_RG_INT_EN_ACCDET_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_ACCDET_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_ACCDET_SHIFT 12 +#define MT6351_PMIC_RG_INT_EN_ACCDET_EINT_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_ACCDET_EINT_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_ACCDET_EINT_SHIFT 13 +#define MT6351_PMIC_RG_INT_EN_ACCDET_NEGV_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_ACCDET_NEGV_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_ACCDET_NEGV_SHIFT 14 +#define MT6351_PMIC_RG_INT_EN_NI_LBAT_INT_ADDR MT6351_INT_CON0 +#define MT6351_PMIC_RG_INT_EN_NI_LBAT_INT_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_NI_LBAT_INT_SHIFT 15 +#define MT6351_PMIC_INT_CON0_SET_ADDR MT6351_INT_CON0_SET +#define MT6351_PMIC_INT_CON0_SET_MASK 0xFFFF +#define MT6351_PMIC_INT_CON0_SET_SHIFT 0 +#define MT6351_PMIC_INT_CON0_CLR_ADDR MT6351_INT_CON0_CLR +#define MT6351_PMIC_INT_CON0_CLR_MASK 0xFFFF +#define MT6351_PMIC_INT_CON0_CLR_SHIFT 0 +#define MT6351_PMIC_RG_INT_EN_VCORE_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VCORE_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VCORE_OC_SHIFT 0 +#define MT6351_PMIC_RG_INT_EN_VGPU_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VGPU_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VGPU_OC_SHIFT 1 +#define MT6351_PMIC_RG_INT_EN_VSRAM_MD_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VSRAM_MD_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VSRAM_MD_OC_SHIFT 2 +#define MT6351_PMIC_RG_INT_EN_VMODEM_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VMODEM_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VMODEM_OC_SHIFT 3 +#define MT6351_PMIC_RG_INT_EN_VM1_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VM1_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VM1_OC_SHIFT 4 +#define MT6351_PMIC_RG_INT_EN_VS1_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VS1_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VS1_OC_SHIFT 5 +#define MT6351_PMIC_RG_INT_EN_VS2_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VS2_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VS2_OC_SHIFT 6 +#define MT6351_PMIC_RG_INT_EN_VPA_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VPA_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VPA_OC_SHIFT 7 +#define MT6351_PMIC_RG_INT_EN_VCORE_PREOC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VCORE_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VCORE_PREOC_SHIFT 8 +#define MT6351_PMIC_RG_INT_EN_VGPU_PREOC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VGPU_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VGPU_PREOC_SHIFT 9 +#define MT6351_PMIC_RG_INT_EN_VSRAM_MD_PREOC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VSRAM_MD_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VSRAM_MD_PREOC_SHIFT 10 +#define MT6351_PMIC_RG_INT_EN_VMODEM_PREOC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VMODEM_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VMODEM_PREOC_SHIFT 11 +#define MT6351_PMIC_RG_INT_EN_VM1_PREOC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VM1_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VM1_PREOC_SHIFT 12 +#define MT6351_PMIC_RG_INT_EN_VS1_PREOC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VS1_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VS1_PREOC_SHIFT 13 +#define MT6351_PMIC_RG_INT_EN_VS2_PREOC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_VS2_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VS2_PREOC_SHIFT 14 +#define MT6351_PMIC_RG_INT_EN_LDO_OC_ADDR MT6351_INT_CON1 +#define MT6351_PMIC_RG_INT_EN_LDO_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_LDO_OC_SHIFT 15 +#define MT6351_PMIC_INT_CON1_SET_ADDR MT6351_INT_CON1_SET +#define MT6351_PMIC_INT_CON1_SET_MASK 0xFFFF +#define MT6351_PMIC_INT_CON1_SET_SHIFT 0 +#define MT6351_PMIC_INT_CON1_CLR_ADDR MT6351_INT_CON1_CLR +#define MT6351_PMIC_INT_CON1_CLR_MASK 0xFFFF +#define MT6351_PMIC_INT_CON1_CLR_SHIFT 0 +#define MT6351_PMIC_RG_INT_EN_JEITA_HOT_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_JEITA_HOT_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_JEITA_HOT_SHIFT 0 +#define MT6351_PMIC_RG_INT_EN_JEITA_WARM_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_JEITA_WARM_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_JEITA_WARM_SHIFT 1 +#define MT6351_PMIC_RG_INT_EN_JEITA_COOL_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_JEITA_COOL_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_JEITA_COOL_SHIFT 2 +#define MT6351_PMIC_RG_INT_EN_JEITA_COLD_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_JEITA_COLD_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_JEITA_COLD_SHIFT 3 +#define MT6351_PMIC_RG_INT_EN_AUXADC_IMP_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_AUXADC_IMP_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_AUXADC_IMP_SHIFT 4 +#define MT6351_PMIC_RG_INT_EN_NAG_C_DLTV_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_NAG_C_DLTV_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_NAG_C_DLTV_SHIFT 5 +#define MT6351_PMIC_RG_INT_EN_OV_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_OV_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_OV_SHIFT 8 +#define MT6351_PMIC_RG_INT_EN_BVALID_DET_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_BVALID_DET_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_BVALID_DET_SHIFT 9 +#define MT6351_PMIC_RG_INT_EN_RGS_BATON_HV_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_RGS_BATON_HV_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_RGS_BATON_HV_SHIFT 10 +#define MT6351_PMIC_RG_INT_EN_VBATON_UNDET_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_VBATON_UNDET_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_VBATON_UNDET_SHIFT 11 +#define MT6351_PMIC_RG_INT_EN_WATCHDOG_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_WATCHDOG_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_WATCHDOG_SHIFT 12 +#define MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC_SHIFT 13 +#define MT6351_PMIC_RG_INT_EN_CHRDET_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_CHRDET_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_CHRDET_SHIFT 14 +#define MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC_ADDR MT6351_INT_CON2 +#define MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC_SHIFT 15 +#define MT6351_PMIC_INT_CON2_SET_ADDR MT6351_INT_CON2_SET +#define MT6351_PMIC_INT_CON2_SET_MASK 0xFFFF +#define MT6351_PMIC_INT_CON2_SET_SHIFT 0 +#define MT6351_PMIC_INT_CON2_CLR_ADDR MT6351_INT_CON2_CLR +#define MT6351_PMIC_INT_CON2_CLR_MASK 0xFFFF +#define MT6351_PMIC_INT_CON2_CLR_SHIFT 0 +#define MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR MT6351_INT_CON3 +#define MT6351_PMIC_RG_INT_EN_FG_BAT_H_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_FG_BAT_H_SHIFT 0 +#define MT6351_PMIC_RG_INT_EN_FG_BAT_L_ADDR MT6351_INT_CON3 +#define MT6351_PMIC_RG_INT_EN_FG_BAT_L_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_FG_BAT_L_SHIFT 1 +#define MT6351_PMIC_RG_INT_EN_FG_CUR_H_ADDR MT6351_INT_CON3 +#define MT6351_PMIC_RG_INT_EN_FG_CUR_H_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_FG_CUR_H_SHIFT 2 +#define MT6351_PMIC_RG_INT_EN_FG_CUR_L_ADDR MT6351_INT_CON3 +#define MT6351_PMIC_RG_INT_EN_FG_CUR_L_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_FG_CUR_L_SHIFT 3 +#define MT6351_PMIC_RG_INT_EN_FG_ZCV_ADDR MT6351_INT_CON3 +#define MT6351_PMIC_RG_INT_EN_FG_ZCV_MASK 0x1 +#define MT6351_PMIC_RG_INT_EN_FG_ZCV_SHIFT 4 +#define MT6351_PMIC_INT_CON3_SET_ADDR MT6351_INT_CON3_SET +#define MT6351_PMIC_INT_CON3_SET_MASK 0xFFFF +#define MT6351_PMIC_INT_CON3_SET_SHIFT 0 +#define MT6351_PMIC_INT_CON3_CLR_ADDR MT6351_INT_CON3_CLR +#define MT6351_PMIC_INT_CON3_CLR_MASK 0xFFFF +#define MT6351_PMIC_INT_CON3_CLR_SHIFT 0 +#define MT6351_PMIC_POLARITY_ADDR MT6351_INT_MISC_CON +#define MT6351_PMIC_POLARITY_MASK 0x1 +#define MT6351_PMIC_POLARITY_SHIFT 0 +#define MT6351_PMIC_RG_HOMEKEY_INT_SEL_ADDR MT6351_INT_MISC_CON +#define MT6351_PMIC_RG_HOMEKEY_INT_SEL_MASK 0x1 +#define MT6351_PMIC_RG_HOMEKEY_INT_SEL_SHIFT 1 +#define MT6351_PMIC_RG_PWRKEY_INT_SEL_ADDR MT6351_INT_MISC_CON +#define MT6351_PMIC_RG_PWRKEY_INT_SEL_MASK 0x1 +#define MT6351_PMIC_RG_PWRKEY_INT_SEL_SHIFT 2 +#define MT6351_PMIC_RG_CHRDET_INT_SEL_ADDR MT6351_INT_MISC_CON +#define MT6351_PMIC_RG_CHRDET_INT_SEL_MASK 0x1 +#define MT6351_PMIC_RG_CHRDET_INT_SEL_SHIFT 3 +#define MT6351_PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_ADDR MT6351_INT_MISC_CON +#define MT6351_PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_SHIFT 4 +#define MT6351_PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_ADDR MT6351_INT_MISC_CON +#define MT6351_PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_SHIFT 5 +#define MT6351_PMIC_INT_MISC_CON_SET_ADDR MT6351_INT_MISC_CON_SET +#define MT6351_PMIC_INT_MISC_CON_SET_MASK 0xFFFF +#define MT6351_PMIC_INT_MISC_CON_SET_SHIFT 0 +#define MT6351_PMIC_INT_MISC_CON_CLR_ADDR MT6351_INT_MISC_CON_CLR +#define MT6351_PMIC_INT_MISC_CON_CLR_MASK 0xFFFF +#define MT6351_PMIC_INT_MISC_CON_CLR_SHIFT 0 +#define MT6351_PMIC_RG_INT_STATUS_PWRKEY_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_PWRKEY_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_PWRKEY_SHIFT 0 +#define MT6351_PMIC_RG_INT_STATUS_HOMEKEY_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_HOMEKEY_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_HOMEKEY_SHIFT 1 +#define MT6351_PMIC_RG_INT_STATUS_PWRKEY_R_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_PWRKEY_R_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_PWRKEY_R_SHIFT 2 +#define MT6351_PMIC_RG_INT_STATUS_HOMEKEY_R_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_HOMEKEY_R_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_HOMEKEY_R_SHIFT 3 +#define MT6351_PMIC_RG_INT_STATUS_THR_H_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_THR_H_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_THR_H_SHIFT 4 +#define MT6351_PMIC_RG_INT_STATUS_THR_L_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_THR_L_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_THR_L_SHIFT 5 +#define MT6351_PMIC_RG_INT_STATUS_BAT_H_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_BAT_H_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_BAT_H_SHIFT 6 +#define MT6351_PMIC_RG_INT_STATUS_BAT_L_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_BAT_L_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_BAT_L_SHIFT 7 +#define MT6351_PMIC_RG_INT_STATUS_RTC_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_RTC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_RTC_SHIFT 9 +#define MT6351_PMIC_RG_INT_STATUS_AUDIO_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_AUDIO_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_AUDIO_SHIFT 10 +#define MT6351_PMIC_RG_INT_STATUS_MAD_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_MAD_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_MAD_SHIFT 11 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_SHIFT 12 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_EINT_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_EINT_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_EINT_SHIFT 13 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_NEGV_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_NEGV_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_ACCDET_NEGV_SHIFT 14 +#define MT6351_PMIC_RG_INT_STATUS_NI_LBAT_INT_ADDR MT6351_INT_STATUS0 +#define MT6351_PMIC_RG_INT_STATUS_NI_LBAT_INT_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_NI_LBAT_INT_SHIFT 15 +#define MT6351_PMIC_RG_INT_STATUS_VCORE_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VCORE_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VCORE_OC_SHIFT 0 +#define MT6351_PMIC_RG_INT_STATUS_VGPU_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VGPU_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VGPU_OC_SHIFT 1 +#define MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_OC_SHIFT 2 +#define MT6351_PMIC_RG_INT_STATUS_VMODEM_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VMODEM_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VMODEM_OC_SHIFT 3 +#define MT6351_PMIC_RG_INT_STATUS_VM1_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VM1_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VM1_OC_SHIFT 4 +#define MT6351_PMIC_RG_INT_STATUS_VS1_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VS1_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VS1_OC_SHIFT 5 +#define MT6351_PMIC_RG_INT_STATUS_VS2_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VS2_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VS2_OC_SHIFT 6 +#define MT6351_PMIC_RG_INT_STATUS_VPA_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VPA_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VPA_OC_SHIFT 7 +#define MT6351_PMIC_RG_INT_STATUS_VCORE_PREOC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VCORE_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VCORE_PREOC_SHIFT 8 +#define MT6351_PMIC_RG_INT_STATUS_VGPU_PREOC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VGPU_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VGPU_PREOC_SHIFT 9 +#define MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_PREOC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_PREOC_SHIFT 10 +#define MT6351_PMIC_RG_INT_STATUS_VMODEM_PREOC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VMODEM_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VMODEM_PREOC_SHIFT 11 +#define MT6351_PMIC_RG_INT_STATUS_VM1_PREOC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VM1_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VM1_PREOC_SHIFT 12 +#define MT6351_PMIC_RG_INT_STATUS_VS1_PREOC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VS1_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VS1_PREOC_SHIFT 13 +#define MT6351_PMIC_RG_INT_STATUS_VS2_PREOC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_VS2_PREOC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VS2_PREOC_SHIFT 14 +#define MT6351_PMIC_RG_INT_STATUS_LDO_OC_ADDR MT6351_INT_STATUS1 +#define MT6351_PMIC_RG_INT_STATUS_LDO_OC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_LDO_OC_SHIFT 15 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_HOT_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_HOT_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_HOT_SHIFT 0 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_WARM_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_WARM_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_WARM_SHIFT 1 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_COOL_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_COOL_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_COOL_SHIFT 2 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_COLD_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_COLD_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_JEITA_COLD_SHIFT 3 +#define MT6351_PMIC_RG_INT_STATUS_AUXADC_IMP_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_AUXADC_IMP_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_AUXADC_IMP_SHIFT 4 +#define MT6351_PMIC_RG_INT_STATUS_NAG_C_DLTV_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_NAG_C_DLTV_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_NAG_C_DLTV_SHIFT 5 +#define MT6351_PMIC_RG_INT_STATUS_OV_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_OV_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_OV_SHIFT 8 +#define MT6351_PMIC_RG_INT_STATUS_BVALID_DET_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_BVALID_DET_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_BVALID_DET_SHIFT 9 +#define MT6351_PMIC_RG_INT_STATUS_RGS_BATON_HV_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_RGS_BATON_HV_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_RGS_BATON_HV_SHIFT 10 +#define MT6351_PMIC_RG_INT_STATUS_VBATON_UNDET_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_VBATON_UNDET_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_VBATON_UNDET_SHIFT 11 +#define MT6351_PMIC_RG_INT_STATUS_WATCHDOG_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_WATCHDOG_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_WATCHDOG_SHIFT 12 +#define MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VDEC_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VDEC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VDEC_SHIFT 13 +#define MT6351_PMIC_RG_INT_STATUS_CHRDET_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_CHRDET_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_CHRDET_SHIFT 14 +#define MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VINC_ADDR MT6351_INT_STATUS2 +#define MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VINC_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VINC_SHIFT 15 +#define MT6351_PMIC_RG_INT_STATUS_FG_BAT_H_ADDR MT6351_INT_STATUS3 +#define MT6351_PMIC_RG_INT_STATUS_FG_BAT_H_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_FG_BAT_H_SHIFT 0 +#define MT6351_PMIC_RG_INT_STATUS_FG_BAT_L_ADDR MT6351_INT_STATUS3 +#define MT6351_PMIC_RG_INT_STATUS_FG_BAT_L_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_FG_BAT_L_SHIFT 1 +#define MT6351_PMIC_RG_INT_STATUS_FG_CUR_H_ADDR MT6351_INT_STATUS3 +#define MT6351_PMIC_RG_INT_STATUS_FG_CUR_H_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_FG_CUR_H_SHIFT 2 +#define MT6351_PMIC_RG_INT_STATUS_FG_CUR_L_ADDR MT6351_INT_STATUS3 +#define MT6351_PMIC_RG_INT_STATUS_FG_CUR_L_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_FG_CUR_L_SHIFT 3 +#define MT6351_PMIC_RG_INT_STATUS_FG_ZCV_ADDR MT6351_INT_STATUS3 +#define MT6351_PMIC_RG_INT_STATUS_FG_ZCV_MASK 0x1 +#define MT6351_PMIC_RG_INT_STATUS_FG_ZCV_SHIFT 4 +#define MT6351_PMIC_OC_GEAR_LDO_ADDR MT6351_OC_GEAR_0 +#define MT6351_PMIC_OC_GEAR_LDO_MASK 0x3 +#define MT6351_PMIC_OC_GEAR_LDO_SHIFT 0 +#define MT6351_PMIC_FQMTR_TCKSEL_ADDR MT6351_FQMTR_CON0 +#define MT6351_PMIC_FQMTR_TCKSEL_MASK 0x7 +#define MT6351_PMIC_FQMTR_TCKSEL_SHIFT 0 +#define MT6351_PMIC_FQMTR_BUSY_ADDR MT6351_FQMTR_CON0 +#define MT6351_PMIC_FQMTR_BUSY_MASK 0x1 +#define MT6351_PMIC_FQMTR_BUSY_SHIFT 3 +#define MT6351_PMIC_FQMTR_EN_ADDR MT6351_FQMTR_CON0 +#define MT6351_PMIC_FQMTR_EN_MASK 0x1 +#define MT6351_PMIC_FQMTR_EN_SHIFT 15 +#define MT6351_PMIC_FQMTR_WINSET_ADDR MT6351_FQMTR_CON1 +#define MT6351_PMIC_FQMTR_WINSET_MASK 0xFFFF +#define MT6351_PMIC_FQMTR_WINSET_SHIFT 0 +#define MT6351_PMIC_FQMTR_DATA_ADDR MT6351_FQMTR_CON2 +#define MT6351_PMIC_FQMTR_DATA_MASK 0xFFFF +#define MT6351_PMIC_FQMTR_DATA_SHIFT 0 +#define MT6351_PMIC_RG_SLP_RW_EN_ADDR MT6351_RG_SPI_CON +#define MT6351_PMIC_RG_SLP_RW_EN_MASK 0x1 +#define MT6351_PMIC_RG_SLP_RW_EN_SHIFT 0 +#define MT6351_PMIC_RG_SPI_RSV_ADDR MT6351_RG_SPI_CON +#define MT6351_PMIC_RG_SPI_RSV_MASK 0x7FFF +#define MT6351_PMIC_RG_SPI_RSV_SHIFT 1 +#define MT6351_PMIC_DEW_DIO_EN_ADDR MT6351_DEW_DIO_EN +#define MT6351_PMIC_DEW_DIO_EN_MASK 0x1 +#define MT6351_PMIC_DEW_DIO_EN_SHIFT 0 +#define MT6351_PMIC_DEW_READ_TEST_ADDR MT6351_DEW_READ_TEST +#define MT6351_PMIC_DEW_READ_TEST_MASK 0xFFFF +#define MT6351_PMIC_DEW_READ_TEST_SHIFT 0 +#define MT6351_PMIC_DEW_WRITE_TEST_ADDR MT6351_DEW_WRITE_TEST +#define MT6351_PMIC_DEW_WRITE_TEST_MASK 0xFFFF +#define MT6351_PMIC_DEW_WRITE_TEST_SHIFT 0 +#define MT6351_PMIC_DEW_CRC_SWRST_ADDR MT6351_DEW_CRC_SWRST +#define MT6351_PMIC_DEW_CRC_SWRST_MASK 0x1 +#define MT6351_PMIC_DEW_CRC_SWRST_SHIFT 0 +#define MT6351_PMIC_DEW_CRC_EN_ADDR MT6351_DEW_CRC_EN +#define MT6351_PMIC_DEW_CRC_EN_MASK 0x1 +#define MT6351_PMIC_DEW_CRC_EN_SHIFT 0 +#define MT6351_PMIC_DEW_CRC_VAL_ADDR MT6351_DEW_CRC_VAL +#define MT6351_PMIC_DEW_CRC_VAL_MASK 0xFF +#define MT6351_PMIC_DEW_CRC_VAL_SHIFT 0 +#define MT6351_PMIC_DEW_DBG_MON_SEL_ADDR MT6351_DEW_DBG_MON_SEL +#define MT6351_PMIC_DEW_DBG_MON_SEL_MASK 0xF +#define MT6351_PMIC_DEW_DBG_MON_SEL_SHIFT 0 +#define MT6351_PMIC_DEW_CIPHER_KEY_SEL_ADDR MT6351_DEW_CIPHER_KEY_SEL +#define MT6351_PMIC_DEW_CIPHER_KEY_SEL_MASK 0x3 +#define MT6351_PMIC_DEW_CIPHER_KEY_SEL_SHIFT 0 +#define MT6351_PMIC_DEW_CIPHER_IV_SEL_ADDR MT6351_DEW_CIPHER_IV_SEL +#define MT6351_PMIC_DEW_CIPHER_IV_SEL_MASK 0x3 +#define MT6351_PMIC_DEW_CIPHER_IV_SEL_SHIFT 0 +#define MT6351_PMIC_DEW_CIPHER_EN_ADDR MT6351_DEW_CIPHER_EN +#define MT6351_PMIC_DEW_CIPHER_EN_MASK 0x1 +#define MT6351_PMIC_DEW_CIPHER_EN_SHIFT 0 +#define MT6351_PMIC_DEW_CIPHER_RDY_ADDR MT6351_DEW_CIPHER_RDY +#define MT6351_PMIC_DEW_CIPHER_RDY_MASK 0x1 +#define MT6351_PMIC_DEW_CIPHER_RDY_SHIFT 0 +#define MT6351_PMIC_DEW_CIPHER_MODE_ADDR MT6351_DEW_CIPHER_MODE +#define MT6351_PMIC_DEW_CIPHER_MODE_MASK 0x1 +#define MT6351_PMIC_DEW_CIPHER_MODE_SHIFT 0 +#define MT6351_PMIC_DEW_CIPHER_SWRST_ADDR MT6351_DEW_CIPHER_SWRST +#define MT6351_PMIC_DEW_CIPHER_SWRST_MASK 0x1 +#define MT6351_PMIC_DEW_CIPHER_SWRST_SHIFT 0 +#define MT6351_PMIC_DEW_RDDMY_NO_ADDR MT6351_DEW_RDDMY_NO +#define MT6351_PMIC_DEW_RDDMY_NO_MASK 0xF +#define MT6351_PMIC_DEW_RDDMY_NO_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON0_ADDR MT6351_INT_TYPE_CON0 +#define MT6351_PMIC_INT_TYPE_CON0_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON0_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON0_SET_ADDR MT6351_INT_TYPE_CON0_SET +#define MT6351_PMIC_INT_TYPE_CON0_SET_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON0_SET_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON0_CLR_ADDR MT6351_INT_TYPE_CON0_CLR +#define MT6351_PMIC_INT_TYPE_CON0_CLR_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON0_CLR_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON1_ADDR MT6351_INT_TYPE_CON1 +#define MT6351_PMIC_INT_TYPE_CON1_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON1_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON1_SET_ADDR MT6351_INT_TYPE_CON1_SET +#define MT6351_PMIC_INT_TYPE_CON1_SET_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON1_SET_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON1_CLR_ADDR MT6351_INT_TYPE_CON1_CLR +#define MT6351_PMIC_INT_TYPE_CON1_CLR_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON1_CLR_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON2_ADDR MT6351_INT_TYPE_CON2 +#define MT6351_PMIC_INT_TYPE_CON2_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON2_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON2_SET_ADDR MT6351_INT_TYPE_CON2_SET +#define MT6351_PMIC_INT_TYPE_CON2_SET_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON2_SET_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON2_CLR_ADDR MT6351_INT_TYPE_CON2_CLR +#define MT6351_PMIC_INT_TYPE_CON2_CLR_MASK 0xFFFF +#define MT6351_PMIC_INT_TYPE_CON2_CLR_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON3_ADDR MT6351_INT_TYPE_CON3 +#define MT6351_PMIC_INT_TYPE_CON3_MASK 0x1F +#define MT6351_PMIC_INT_TYPE_CON3_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON3_SET_ADDR MT6351_INT_TYPE_CON3_SET +#define MT6351_PMIC_INT_TYPE_CON3_SET_MASK 0x1F +#define MT6351_PMIC_INT_TYPE_CON3_SET_SHIFT 0 +#define MT6351_PMIC_INT_TYPE_CON3_CLR_ADDR MT6351_INT_TYPE_CON3_CLR +#define MT6351_PMIC_INT_TYPE_CON3_CLR_MASK 0x1F +#define MT6351_PMIC_INT_TYPE_CON3_CLR_SHIFT 0 +#define MT6351_PMIC_CPU_INT_STA_ADDR MT6351_INT_STA +#define MT6351_PMIC_CPU_INT_STA_MASK 0x1 +#define MT6351_PMIC_CPU_INT_STA_SHIFT 0 +#define MT6351_PMIC_MD32_INT_STA_ADDR MT6351_INT_STA +#define MT6351_PMIC_MD32_INT_STA_MASK 0x1 +#define MT6351_PMIC_MD32_INT_STA_SHIFT 1 +#define MT6351_PMIC_BUCK_LDO_FT_TESTMODE_EN_ADDR MT6351_BUCK_ALL_CON0 +#define MT6351_PMIC_BUCK_LDO_FT_TESTMODE_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_LDO_FT_TESTMODE_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_ALL_CON0_RSV1_ADDR MT6351_BUCK_ALL_CON0 +#define MT6351_PMIC_BUCK_ALL_CON0_RSV1_MASK 0x7F +#define MT6351_PMIC_BUCK_ALL_CON0_RSV1_SHIFT 1 +#define MT6351_PMIC_BUCK_ALL_CON0_RSV0_ADDR MT6351_BUCK_ALL_CON0 +#define MT6351_PMIC_BUCK_ALL_CON0_RSV0_MASK 0xFF +#define MT6351_PMIC_BUCK_ALL_CON0_RSV0_SHIFT 8 +#define MT6351_PMIC_BUCK_BUCK_RSV_ADDR MT6351_BUCK_ALL_CON1 +#define MT6351_PMIC_BUCK_BUCK_RSV_MASK 0xFFFF +#define MT6351_PMIC_BUCK_BUCK_RSV_SHIFT 0 +#define MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL_ADDR MT6351_BUCK_ALL_CON2 +#define MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL_MASK 0x3 +#define MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL_ADDR MT6351_BUCK_ALL_CON2 +#define MT6351_PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL_MASK 0x3 +#define MT6351_PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL_SHIFT 4 +#define MT6351_PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL_ADDR MT6351_BUCK_ALL_CON2 +#define MT6351_PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL_MASK 0x3 +#define MT6351_PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_BUCK_ALL_CON2_RSV0_ADDR MT6351_BUCK_ALL_CON2 +#define MT6351_PMIC_BUCK_ALL_CON2_RSV0_MASK 0x1F +#define MT6351_PMIC_BUCK_ALL_CON2_RSV0_SHIFT 11 +#define MT6351_PMIC_BUCK_VSLEEP_SRC0_ADDR MT6351_BUCK_ALL_CON3 +#define MT6351_PMIC_BUCK_VSLEEP_SRC0_MASK 0x1FF +#define MT6351_PMIC_BUCK_VSLEEP_SRC0_SHIFT 0 +#define MT6351_PMIC_BUCK_VSLEEP_SRC1_ADDR MT6351_BUCK_ALL_CON3 +#define MT6351_PMIC_BUCK_VSLEEP_SRC1_MASK 0xF +#define MT6351_PMIC_BUCK_VSLEEP_SRC1_SHIFT 12 +#define MT6351_PMIC_BUCK_R2R_SRC0_ADDR MT6351_BUCK_ALL_CON4 +#define MT6351_PMIC_BUCK_R2R_SRC0_MASK 0x1FF +#define MT6351_PMIC_BUCK_R2R_SRC0_SHIFT 0 +#define MT6351_PMIC_BUCK_R2R_SRC1_ADDR MT6351_BUCK_ALL_CON4 +#define MT6351_PMIC_BUCK_R2R_SRC1_MASK 0xF +#define MT6351_PMIC_BUCK_R2R_SRC1_SHIFT 12 +#define MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRC0_ADDR MT6351_BUCK_ALL_CON5 +#define MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRC0_MASK 0x1FF +#define MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRC0_SHIFT 0 +#define MT6351_PMIC_BUCK_SRCLKEN_DLY_SRC1_ADDR MT6351_BUCK_ALL_CON5 +#define MT6351_PMIC_BUCK_SRCLKEN_DLY_SRC1_MASK 0xF +#define MT6351_PMIC_BUCK_SRCLKEN_DLY_SRC1_SHIFT 12 +#define MT6351_PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB_SHIFT 1 +#define MT6351_PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB_SHIFT 2 +#define MT6351_PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB_SHIFT 3 +#define MT6351_PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB_SHIFT 4 +#define MT6351_PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB_SHIFT 5 +#define MT6351_PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB_SHIFT 6 +#define MT6351_PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB_SHIFT 7 +#define MT6351_PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB_ADDR MT6351_BUCK_ALL_CON6 +#define MT6351_PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB_SHIFT 8 +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC011_ADDR MT6351_BUCK_DLC_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC011_MASK 0x3F +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC011_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC111_ADDR MT6351_BUCK_DLC_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC111_MASK 0x3F +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC111_SHIFT 8 +#define MT6351_PMIC_BUCK_VPA_DLC_MAP_EN_ADDR MT6351_BUCK_DLC_VPA_CON1 +#define MT6351_PMIC_BUCK_VPA_DLC_MAP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_DLC_MAP_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC001_ADDR MT6351_BUCK_DLC_VPA_CON1 +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC001_MASK 0x3F +#define MT6351_PMIC_BUCK_VPA_VOSEL_DLC001_SHIFT 8 +#define MT6351_PMIC_BUCK_VPA_DLC_ADDR MT6351_BUCK_DLC_VPA_CON2 +#define MT6351_PMIC_BUCK_VPA_DLC_MASK 0x7 +#define MT6351_PMIC_BUCK_VPA_DLC_SHIFT 0 +#define MT6351_PMIC_DA_NI_VPA_DLC_ADDR MT6351_BUCK_DLC_VPA_CON2 +#define MT6351_PMIC_DA_NI_VPA_DLC_MASK 0x7 +#define MT6351_PMIC_DA_NI_VPA_DLC_SHIFT 12 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_TD_ADDR MT6351_BUCK_DVS_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_CTRL_ADDR MT6351_BUCK_DVS_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_ONCE_ADDR MT6351_BUCK_DVS_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_DVS_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_NI_VPA_DVS_TRANST_ADDR MT6351_BUCK_DVS_VPA_CON0 +#define MT6351_PMIC_DA_NI_VPA_DVS_TRANST_MASK 0x1 +#define MT6351_PMIC_DA_NI_VPA_DVS_TRANST_SHIFT 7 +#define MT6351_PMIC_BUCK_VPA_DIG0_RSV5_ADDR MT6351_BUCK_DVS_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_DIG0_RSV5_MASK 0xF +#define MT6351_PMIC_BUCK_VPA_DIG0_RSV5_SHIFT 8 +#define MT6351_PMIC_BUCK_VPA_DIG1_RSV5_ADDR MT6351_BUCK_DVS_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_DIG1_RSV5_MASK 0xF +#define MT6351_PMIC_BUCK_VPA_DIG1_RSV5_SHIFT 12 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_AUD_ADDR MT6351_BUCK_VOW_CON0 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_AUD_MASK 0x7F +#define MT6351_PMIC_BUCK_VCORE_VOSEL_AUD_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_ADDR MT6351_BUCK_VOW_CON1 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SW_ADDR MT6351_BUCK_VOW_CON1 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SW_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SW_SHIFT 1 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_STA_ADDR MT6351_BUCK_VOW_CON1 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_STA_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_DVFS_DONE_STA_SHIFT 4 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_AUD_ADDR MT6351_BUCK_VOW_CON2 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_AUD_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_AUD_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_ADDR MT6351_BUCK_VOW_CON3 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW_ADDR MT6351_BUCK_VOW_CON3 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW_SHIFT 1 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA_ADDR MT6351_BUCK_VOW_CON3 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA_SHIFT 4 +#define MT6351_PMIC_BUCK_VCORE_OC_STATUS_ADDR MT6351_BUCK_OC_CON0 +#define MT6351_PMIC_BUCK_VCORE_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_OC_STATUS_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_OC_STATUS_ADDR MT6351_BUCK_OC_CON0 +#define MT6351_PMIC_BUCK_VGPU_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_OC_STATUS_SHIFT 1 +#define MT6351_PMIC_BUCK_VMODEM_OC_STATUS_ADDR MT6351_BUCK_OC_CON0 +#define MT6351_PMIC_BUCK_VMODEM_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_OC_STATUS_SHIFT 2 +#define MT6351_PMIC_BUCK_VMD1_OC_STATUS_ADDR MT6351_BUCK_OC_CON0 +#define MT6351_PMIC_BUCK_VMD1_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_OC_STATUS_SHIFT 3 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_STATUS_ADDR MT6351_BUCK_OC_CON0 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_STATUS_SHIFT 4 +#define MT6351_PMIC_BUCK_VS1_OC_STATUS_ADDR MT6351_BUCK_OC_CON0 +#define MT6351_PMIC_BUCK_VS1_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_OC_STATUS_SHIFT 5 +#define MT6351_PMIC_BUCK_VS2_OC_STATUS_ADDR MT6351_BUCK_OC_CON0 +#define MT6351_PMIC_BUCK_VS2_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_OC_STATUS_SHIFT 6 +#define MT6351_PMIC_BUCK_VPA_OC_STATUS_ADDR MT6351_BUCK_OC_CON0 +#define MT6351_PMIC_BUCK_VPA_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_OC_STATUS_SHIFT 7 +#define MT6351_PMIC_BUCK_VCORE_OC_INT_EN_ADDR MT6351_BUCK_OC_CON1 +#define MT6351_PMIC_BUCK_VCORE_OC_INT_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_OC_INT_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_OC_INT_EN_ADDR MT6351_BUCK_OC_CON1 +#define MT6351_PMIC_BUCK_VGPU_OC_INT_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_OC_INT_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VMODEM_OC_INT_EN_ADDR MT6351_BUCK_OC_CON1 +#define MT6351_PMIC_BUCK_VMODEM_OC_INT_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_OC_INT_EN_SHIFT 2 +#define MT6351_PMIC_BUCK_VMD1_OC_INT_EN_ADDR MT6351_BUCK_OC_CON1 +#define MT6351_PMIC_BUCK_VMD1_OC_INT_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_OC_INT_EN_SHIFT 3 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_INT_EN_ADDR MT6351_BUCK_OC_CON1 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_INT_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_INT_EN_SHIFT 4 +#define MT6351_PMIC_BUCK_VS1_OC_INT_EN_ADDR MT6351_BUCK_OC_CON1 +#define MT6351_PMIC_BUCK_VS1_OC_INT_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_OC_INT_EN_SHIFT 5 +#define MT6351_PMIC_BUCK_VS2_OC_INT_EN_ADDR MT6351_BUCK_OC_CON1 +#define MT6351_PMIC_BUCK_VS2_OC_INT_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_OC_INT_EN_SHIFT 6 +#define MT6351_PMIC_BUCK_VPA_OC_INT_EN_ADDR MT6351_BUCK_OC_CON1 +#define MT6351_PMIC_BUCK_VPA_OC_INT_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_OC_INT_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VCORE_EN_OC_SDN_SEL_ADDR MT6351_BUCK_OC_CON2 +#define MT6351_PMIC_BUCK_VCORE_EN_OC_SDN_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_EN_OC_SDN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_EN_OC_SDN_SEL_ADDR MT6351_BUCK_OC_CON2 +#define MT6351_PMIC_BUCK_VGPU_EN_OC_SDN_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_EN_OC_SDN_SEL_SHIFT 1 +#define MT6351_PMIC_BUCK_VMODEM_EN_OC_SDN_SEL_ADDR MT6351_BUCK_OC_CON2 +#define MT6351_PMIC_BUCK_VMODEM_EN_OC_SDN_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_EN_OC_SDN_SEL_SHIFT 2 +#define MT6351_PMIC_BUCK_VMD1_EN_OC_SDN_SEL_ADDR MT6351_BUCK_OC_CON2 +#define MT6351_PMIC_BUCK_VMD1_EN_OC_SDN_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_EN_OC_SDN_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL_ADDR MT6351_BUCK_OC_CON2 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL_SHIFT 4 +#define MT6351_PMIC_BUCK_VS1_EN_OC_SDN_SEL_ADDR MT6351_BUCK_OC_CON2 +#define MT6351_PMIC_BUCK_VS1_EN_OC_SDN_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_EN_OC_SDN_SEL_SHIFT 5 +#define MT6351_PMIC_BUCK_VS2_EN_OC_SDN_SEL_ADDR MT6351_BUCK_OC_CON2 +#define MT6351_PMIC_BUCK_VS2_EN_OC_SDN_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_EN_OC_SDN_SEL_SHIFT 6 +#define MT6351_PMIC_BUCK_VPA_EN_OC_SDN_SEL_ADDR MT6351_BUCK_OC_CON2 +#define MT6351_PMIC_BUCK_VPA_EN_OC_SDN_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_EN_OC_SDN_SEL_SHIFT 7 +#define MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_ADDR MT6351_BUCK_OC_CON3 +#define MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_ADDR MT6351_BUCK_OC_CON3 +#define MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SHIFT 1 +#define MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_ADDR MT6351_BUCK_OC_CON3 +#define MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SHIFT 2 +#define MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_ADDR MT6351_BUCK_OC_CON3 +#define MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SHIFT 3 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_ADDR MT6351_BUCK_OC_CON3 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SHIFT 4 +#define MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_ADDR MT6351_BUCK_OC_CON3 +#define MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SHIFT 5 +#define MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_ADDR MT6351_BUCK_OC_CON3 +#define MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SHIFT 6 +#define MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_ADDR MT6351_BUCK_OC_CON3 +#define MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SHIFT 7 +#define MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_ADDR MT6351_BUCK_OC_CON4 +#define MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL_ADDR MT6351_BUCK_OC_CON4 +#define MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL_SHIFT 1 +#define MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL_ADDR MT6351_BUCK_OC_CON4 +#define MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL_SHIFT 2 +#define MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL_ADDR MT6351_BUCK_OC_CON4 +#define MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL_ADDR MT6351_BUCK_OC_CON4 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL_SHIFT 4 +#define MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_ADDR MT6351_BUCK_OC_CON4 +#define MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_SHIFT 5 +#define MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SEL_ADDR MT6351_BUCK_OC_CON4 +#define MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SEL_SHIFT 6 +#define MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_ADDR MT6351_BUCK_OC_CON4 +#define MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_SHIFT 7 +#define MT6351_PMIC_BUCK_VCORE_OC_DEG_EN_ADDR MT6351_BUCK_OC_VCORE_CON0 +#define MT6351_PMIC_BUCK_VCORE_OC_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_OC_DEG_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VCORE_OC_WND_ADDR MT6351_BUCK_OC_VCORE_CON0 +#define MT6351_PMIC_BUCK_VCORE_OC_WND_MASK 0x3 +#define MT6351_PMIC_BUCK_VCORE_OC_WND_SHIFT 2 +#define MT6351_PMIC_BUCK_VCORE_OC_THD_ADDR MT6351_BUCK_OC_VCORE_CON0 +#define MT6351_PMIC_BUCK_VCORE_OC_THD_MASK 0x3 +#define MT6351_PMIC_BUCK_VCORE_OC_THD_SHIFT 6 +#define MT6351_PMIC_BUCK_VGPU_OC_DEG_EN_ADDR MT6351_BUCK_OC_VGPU_CON0 +#define MT6351_PMIC_BUCK_VGPU_OC_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_OC_DEG_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VGPU_OC_WND_ADDR MT6351_BUCK_OC_VGPU_CON0 +#define MT6351_PMIC_BUCK_VGPU_OC_WND_MASK 0x3 +#define MT6351_PMIC_BUCK_VGPU_OC_WND_SHIFT 2 +#define MT6351_PMIC_BUCK_VGPU_OC_THD_ADDR MT6351_BUCK_OC_VGPU_CON0 +#define MT6351_PMIC_BUCK_VGPU_OC_THD_MASK 0x3 +#define MT6351_PMIC_BUCK_VGPU_OC_THD_SHIFT 6 +#define MT6351_PMIC_BUCK_VMODEM_OC_DEG_EN_ADDR MT6351_BUCK_OC_VMODEM_CON0 +#define MT6351_PMIC_BUCK_VMODEM_OC_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_OC_DEG_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VMODEM_OC_WND_ADDR MT6351_BUCK_OC_VMODEM_CON0 +#define MT6351_PMIC_BUCK_VMODEM_OC_WND_MASK 0x3 +#define MT6351_PMIC_BUCK_VMODEM_OC_WND_SHIFT 2 +#define MT6351_PMIC_BUCK_VMODEM_OC_THD_ADDR MT6351_BUCK_OC_VMODEM_CON0 +#define MT6351_PMIC_BUCK_VMODEM_OC_THD_MASK 0x3 +#define MT6351_PMIC_BUCK_VMODEM_OC_THD_SHIFT 6 +#define MT6351_PMIC_BUCK_VMD1_OC_DEG_EN_ADDR MT6351_BUCK_OC_VMD1_CON0 +#define MT6351_PMIC_BUCK_VMD1_OC_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_OC_DEG_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VMD1_OC_WND_ADDR MT6351_BUCK_OC_VMD1_CON0 +#define MT6351_PMIC_BUCK_VMD1_OC_WND_MASK 0x3 +#define MT6351_PMIC_BUCK_VMD1_OC_WND_SHIFT 2 +#define MT6351_PMIC_BUCK_VMD1_OC_THD_ADDR MT6351_BUCK_OC_VMD1_CON0 +#define MT6351_PMIC_BUCK_VMD1_OC_THD_MASK 0x3 +#define MT6351_PMIC_BUCK_VMD1_OC_THD_SHIFT 6 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_DEG_EN_ADDR MT6351_BUCK_OC_VSRAM_MD_CON0 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_DEG_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_WND_ADDR MT6351_BUCK_OC_VSRAM_MD_CON0 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_WND_MASK 0x3 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_WND_SHIFT 2 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_THD_ADDR MT6351_BUCK_OC_VSRAM_MD_CON0 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_THD_MASK 0x3 +#define MT6351_PMIC_BUCK_VSRAM_MD_OC_THD_SHIFT 6 +#define MT6351_PMIC_BUCK_VS1_OC_DEG_EN_ADDR MT6351_BUCK_OC_VS1_CON0 +#define MT6351_PMIC_BUCK_VS1_OC_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_OC_DEG_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VS1_OC_WND_ADDR MT6351_BUCK_OC_VS1_CON0 +#define MT6351_PMIC_BUCK_VS1_OC_WND_MASK 0x3 +#define MT6351_PMIC_BUCK_VS1_OC_WND_SHIFT 2 +#define MT6351_PMIC_BUCK_VS1_OC_THD_ADDR MT6351_BUCK_OC_VS1_CON0 +#define MT6351_PMIC_BUCK_VS1_OC_THD_MASK 0x3 +#define MT6351_PMIC_BUCK_VS1_OC_THD_SHIFT 6 +#define MT6351_PMIC_BUCK_VS2_OC_DEG_EN_ADDR MT6351_BUCK_OC_VS2_CON0 +#define MT6351_PMIC_BUCK_VS2_OC_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_OC_DEG_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VS2_OC_WND_ADDR MT6351_BUCK_OC_VS2_CON0 +#define MT6351_PMIC_BUCK_VS2_OC_WND_MASK 0x3 +#define MT6351_PMIC_BUCK_VS2_OC_WND_SHIFT 2 +#define MT6351_PMIC_BUCK_VS2_OC_THD_ADDR MT6351_BUCK_OC_VS2_CON0 +#define MT6351_PMIC_BUCK_VS2_OC_THD_MASK 0x3 +#define MT6351_PMIC_BUCK_VS2_OC_THD_SHIFT 6 +#define MT6351_PMIC_BUCK_VPA_OC_DEG_EN_ADDR MT6351_BUCK_OC_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_OC_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_OC_DEG_EN_SHIFT 1 +#define MT6351_PMIC_BUCK_VPA_OC_WND_ADDR MT6351_BUCK_OC_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_OC_WND_MASK 0x3 +#define MT6351_PMIC_BUCK_VPA_OC_WND_SHIFT 2 +#define MT6351_PMIC_BUCK_VPA_OC_THD_ADDR MT6351_BUCK_OC_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_OC_THD_MASK 0x3 +#define MT6351_PMIC_BUCK_VPA_OC_THD_SHIFT 6 +#define MT6351_PMIC_RG_SMPS_TESTMODE_B_ADDR MT6351_SMPS_ANA_CON0 +#define MT6351_PMIC_RG_SMPS_TESTMODE_B_MASK 0xFFF +#define MT6351_PMIC_RG_SMPS_TESTMODE_B_SHIFT 0 +#define MT6351_PMIC_RG_VPA_BURSTH_ADDR MT6351_SMPS_ANA_CON0 +#define MT6351_PMIC_RG_VPA_BURSTH_MASK 0x3 +#define MT6351_PMIC_RG_VPA_BURSTH_SHIFT 12 +#define MT6351_PMIC_RG_VPA_BURSTL_ADDR MT6351_SMPS_ANA_CON0 +#define MT6351_PMIC_RG_VPA_BURSTL_MASK 0x3 +#define MT6351_PMIC_RG_VPA_BURSTL_SHIFT 14 +#define MT6351_PMIC_RG_VPA_TRIMH_ADDR MT6351_SMPS_ANA_CON1 +#define MT6351_PMIC_RG_VPA_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VPA_TRIMH_SHIFT 0 +#define MT6351_PMIC_RG_VPA_TRIML_ADDR MT6351_SMPS_ANA_CON1 +#define MT6351_PMIC_RG_VPA_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VPA_TRIML_SHIFT 5 +#define MT6351_PMIC_RG_VPA_TRIM_REF_ADDR MT6351_SMPS_ANA_CON1 +#define MT6351_PMIC_RG_VPA_TRIM_REF_MASK 0x1F +#define MT6351_PMIC_RG_VPA_TRIM_REF_SHIFT 10 +#define MT6351_PMIC_RG_VCORE_TRIMH_ADDR MT6351_SMPS_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VCORE_TRIMH_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_TRIML_ADDR MT6351_SMPS_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VCORE_TRIML_SHIFT 5 +#define MT6351_PMIC_RG_VCORE_VSLEEP_ADDR MT6351_SMPS_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_VSLEEP_MASK 0x7 +#define MT6351_PMIC_RG_VCORE_VSLEEP_SHIFT 10 +#define MT6351_PMIC_RG_VGPU_TRIMH_ADDR MT6351_SMPS_ANA_CON3 +#define MT6351_PMIC_RG_VGPU_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VGPU_TRIMH_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_TRIML_ADDR MT6351_SMPS_ANA_CON3 +#define MT6351_PMIC_RG_VGPU_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VGPU_TRIML_SHIFT 5 +#define MT6351_PMIC_RG_VGPU_VSLEEP_ADDR MT6351_SMPS_ANA_CON3 +#define MT6351_PMIC_RG_VGPU_VSLEEP_MASK 0x7 +#define MT6351_PMIC_RG_VGPU_VSLEEP_SHIFT 10 +#define MT6351_PMIC_RG_VSRAM_MD_TRIMH_ADDR MT6351_SMPS_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VSRAM_MD_TRIMH_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_TRIML_ADDR MT6351_SMPS_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VSRAM_MD_TRIML_SHIFT 5 +#define MT6351_PMIC_RG_VSRAM_MD_VSLEEP_ADDR MT6351_SMPS_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_VSLEEP_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SHIFT 10 +#define MT6351_PMIC_RG_VMODEM_TRIMH_ADDR MT6351_SMPS_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VMODEM_TRIMH_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_TRIML_ADDR MT6351_SMPS_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VMODEM_TRIML_SHIFT 5 +#define MT6351_PMIC_RG_VMODEM_VSLEEP_ADDR MT6351_SMPS_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_VSLEEP_MASK 0x7 +#define MT6351_PMIC_RG_VMODEM_VSLEEP_SHIFT 10 +#define MT6351_PMIC_RG_VMD1_TRIMH_ADDR MT6351_SMPS_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VMD1_TRIMH_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_TRIML_ADDR MT6351_SMPS_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VMD1_TRIML_SHIFT 5 +#define MT6351_PMIC_RG_VMD1_VSLEEP_ADDR MT6351_SMPS_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_VSLEEP_MASK 0x7 +#define MT6351_PMIC_RG_VMD1_VSLEEP_SHIFT 10 +#define MT6351_PMIC_RG_VS1_TRIMH_ADDR MT6351_SMPS_ANA_CON7 +#define MT6351_PMIC_RG_VS1_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VS1_TRIMH_SHIFT 0 +#define MT6351_PMIC_RG_VS1_TRIML_ADDR MT6351_SMPS_ANA_CON7 +#define MT6351_PMIC_RG_VS1_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VS1_TRIML_SHIFT 5 +#define MT6351_PMIC_RG_VS1_VSLEEP_ADDR MT6351_SMPS_ANA_CON7 +#define MT6351_PMIC_RG_VS1_VSLEEP_MASK 0x7 +#define MT6351_PMIC_RG_VS1_VSLEEP_SHIFT 10 +#define MT6351_PMIC_RG_VS2_TRIML_ADDR MT6351_SMPS_ANA_CON8 +#define MT6351_PMIC_RG_VS2_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VS2_TRIML_SHIFT 0 +#define MT6351_PMIC_RG_VS2_VSLEEP_ADDR MT6351_SMPS_ANA_CON8 +#define MT6351_PMIC_RG_VS2_VSLEEP_MASK 0x7 +#define MT6351_PMIC_RG_VS2_VSLEEP_SHIFT 5 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIMH_ADDR MT6351_SMPS_ANA_CON8 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIMH_SHIFT 8 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIML_ADDR MT6351_SMPS_ANA_CON9 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIML_MASK 0x1F +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIML_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_ADDR MT6351_SMPS_ANA_CON9 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SHIFT 5 +#define MT6351_PMIC_RG_VCORE_VSLEEP_SEL_ADDR MT6351_SMPS_ANA_CON9 +#define MT6351_PMIC_RG_VCORE_VSLEEP_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_VSLEEP_SEL_SHIFT 8 +#define MT6351_PMIC_RG_VGPU_VSLEEP_SEL_ADDR MT6351_SMPS_ANA_CON9 +#define MT6351_PMIC_RG_VGPU_VSLEEP_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_VSLEEP_SEL_SHIFT 10 +#define MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SEL_ADDR MT6351_SMPS_ANA_CON9 +#define MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SEL_SHIFT 12 +#define MT6351_PMIC_RG_VMODEM_VSLEEP_SEL_ADDR MT6351_SMPS_ANA_CON9 +#define MT6351_PMIC_RG_VMODEM_VSLEEP_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_VSLEEP_SEL_SHIFT 14 +#define MT6351_PMIC_RG_VMD1_VSLEEP_SEL_ADDR MT6351_SMPS_ANA_CON10 +#define MT6351_PMIC_RG_VMD1_VSLEEP_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_VSLEEP_SEL_SHIFT 0 +#define MT6351_PMIC_RG_VS1_VSLEEP_SEL_ADDR MT6351_SMPS_ANA_CON10 +#define MT6351_PMIC_RG_VS1_VSLEEP_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VS1_VSLEEP_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VS2_VSLEEP_SEL_ADDR MT6351_SMPS_ANA_CON10 +#define MT6351_PMIC_RG_VS2_VSLEEP_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VS2_VSLEEP_SEL_SHIFT 4 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL_ADDR MT6351_SMPS_ANA_CON10 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL_SHIFT 6 +#define MT6351_PMIC_RG_VOUTDET_EN_ADDR MT6351_SMPS_ANA_CON10 +#define MT6351_PMIC_RG_VOUTDET_EN_MASK 0x1 +#define MT6351_PMIC_RG_VOUTDET_EN_SHIFT 8 +#define MT6351_PMIC_RG_VS2_TRIMH_ADDR MT6351_SMPS_ANA_CON10 +#define MT6351_PMIC_RG_VS2_TRIMH_MASK 0x1F +#define MT6351_PMIC_RG_VS2_TRIMH_SHIFT 9 +#define MT6351_PMIC_RG_VCORE_MODESET_ADDR MT6351_VCORE_ANA_CON0 +#define MT6351_PMIC_RG_VCORE_MODESET_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_MODESET_SHIFT 1 +#define MT6351_PMIC_RG_VCORE_NDIS_EN_ADDR MT6351_VCORE_ANA_CON0 +#define MT6351_PMIC_RG_VCORE_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_NDIS_EN_SHIFT 2 +#define MT6351_PMIC_RG_VCORE_VRF18_SSTART_EN_ADDR MT6351_VCORE_ANA_CON0 +#define MT6351_PMIC_RG_VCORE_VRF18_SSTART_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_VRF18_SSTART_EN_SHIFT 3 +#define MT6351_PMIC_RG_VCORE_AUTO_MODE_ADDR MT6351_VCORE_ANA_CON0 +#define MT6351_PMIC_RG_VCORE_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_AUTO_MODE_SHIFT 4 +#define MT6351_PMIC_RG_VCORE_RZSEL0_ADDR MT6351_VCORE_ANA_CON1 +#define MT6351_PMIC_RG_VCORE_RZSEL0_MASK 0x7 +#define MT6351_PMIC_RG_VCORE_RZSEL0_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_RZSEL1_ADDR MT6351_VCORE_ANA_CON1 +#define MT6351_PMIC_RG_VCORE_RZSEL1_MASK 0xF +#define MT6351_PMIC_RG_VCORE_RZSEL1_SHIFT 3 +#define MT6351_PMIC_RG_VCORE_CCSEL0_ADDR MT6351_VCORE_ANA_CON1 +#define MT6351_PMIC_RG_VCORE_CCSEL0_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_CCSEL0_SHIFT 7 +#define MT6351_PMIC_RG_VCORE_CCSEL1_ADDR MT6351_VCORE_ANA_CON1 +#define MT6351_PMIC_RG_VCORE_CCSEL1_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_CCSEL1_SHIFT 9 +#define MT6351_PMIC_RG_VCORE_CSL_ADDR MT6351_VCORE_ANA_CON1 +#define MT6351_PMIC_RG_VCORE_CSL_MASK 0xF +#define MT6351_PMIC_RG_VCORE_CSL_SHIFT 11 +#define MT6351_PMIC_RG_VCORE_SLP_ADDR MT6351_VCORE_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_SLP_MASK 0x7 +#define MT6351_PMIC_RG_VCORE_SLP_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_ADRC_FEN_ADDR MT6351_VCORE_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_ADRC_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_ADRC_FEN_SHIFT 3 +#define MT6351_PMIC_RG_VCORE_VCCAP_CLAMP_FEN_ADDR MT6351_VCORE_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_VCCAP_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_VCCAP_CLAMP_FEN_SHIFT 4 +#define MT6351_PMIC_RG_VCORE_VC_CLAMP_FEN_ADDR MT6351_VCORE_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_VC_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_VC_CLAMP_FEN_SHIFT 5 +#define MT6351_PMIC_RG_VCORE_PREOC_SEL_ADDR MT6351_VCORE_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_PREOC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCORE_PREOC_SEL_SHIFT 6 +#define MT6351_PMIC_RG_VCORE_PFMOC_ADDR MT6351_VCORE_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_PFMOC_MASK 0x7 +#define MT6351_PMIC_RG_VCORE_PFMOC_SHIFT 9 +#define MT6351_PMIC_RG_VCORE_CSR_ADDR MT6351_VCORE_ANA_CON2 +#define MT6351_PMIC_RG_VCORE_CSR_MASK 0x7 +#define MT6351_PMIC_RG_VCORE_CSR_SHIFT 12 +#define MT6351_PMIC_RG_VCORE_ZXOS_TRIM_ADDR MT6351_VCORE_ANA_CON3 +#define MT6351_PMIC_RG_VCORE_ZXOS_TRIM_MASK 0xFF +#define MT6351_PMIC_RG_VCORE_ZXOS_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_CSM_N_ADDR MT6351_VCORE_ANA_CON3 +#define MT6351_PMIC_RG_VCORE_CSM_N_MASK 0x3F +#define MT6351_PMIC_RG_VCORE_CSM_N_SHIFT 8 +#define MT6351_PMIC_RG_VCORE_CSM_P_ADDR MT6351_VCORE_ANA_CON4 +#define MT6351_PMIC_RG_VCORE_CSM_P_MASK 0x3F +#define MT6351_PMIC_RG_VCORE_CSM_P_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_PFMSR_EH_ADDR MT6351_VCORE_ANA_CON4 +#define MT6351_PMIC_RG_VCORE_PFMSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_PFMSR_EH_SHIFT 6 +#define MT6351_PMIC_RG_VCORE_NLIM_GATING_ADDR MT6351_VCORE_ANA_CON4 +#define MT6351_PMIC_RG_VCORE_NLIM_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_NLIM_GATING_SHIFT 7 +#define MT6351_PMIC_RG_VCORE_PWRSR_EH_ADDR MT6351_VCORE_ANA_CON4 +#define MT6351_PMIC_RG_VCORE_PWRSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_PWRSR_EH_SHIFT 8 +#define MT6351_PMIC_RG_VCORE_HS_VTHDET_ADDR MT6351_VCORE_ANA_CON4 +#define MT6351_PMIC_RG_VCORE_HS_VTHDET_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_HS_VTHDET_SHIFT 9 +#define MT6351_PMIC_RG_VCORE_PG_GATING_ADDR MT6351_VCORE_ANA_CON4 +#define MT6351_PMIC_RG_VCORE_PG_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_PG_GATING_SHIFT 10 +#define MT6351_PMIC_RG_VCORE_HS_ONSPEED_EH_ADDR MT6351_VCORE_ANA_CON4 +#define MT6351_PMIC_RG_VCORE_HS_ONSPEED_EH_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_HS_ONSPEED_EH_SHIFT 11 +#define MT6351_PMIC_RG_VCORE_NLIM_TRIMMING_ADDR MT6351_VCORE_ANA_CON4 +#define MT6351_PMIC_RG_VCORE_NLIM_TRIMMING_MASK 0xF +#define MT6351_PMIC_RG_VCORE_NLIM_TRIMMING_SHIFT 12 +#define MT6351_PMIC_RG_VCORE_DLC_ADDR MT6351_VCORE_ANA_CON5 +#define MT6351_PMIC_RG_VCORE_DLC_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_DLC_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_DLC_N_ADDR MT6351_VCORE_ANA_CON5 +#define MT6351_PMIC_RG_VCORE_DLC_N_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_DLC_N_SHIFT 2 +#define MT6351_PMIC_RG_VCORE_PFM_RIP_ADDR MT6351_VCORE_ANA_CON5 +#define MT6351_PMIC_RG_VCORE_PFM_RIP_MASK 0x7 +#define MT6351_PMIC_RG_VCORE_PFM_RIP_SHIFT 4 +#define MT6351_PMIC_RG_VCORE_TRAN_BST_ADDR MT6351_VCORE_ANA_CON5 +#define MT6351_PMIC_RG_VCORE_TRAN_BST_MASK 0x3F +#define MT6351_PMIC_RG_VCORE_TRAN_BST_SHIFT 7 +#define MT6351_PMIC_RG_VCORE_DTS_ENB_ADDR MT6351_VCORE_ANA_CON5 +#define MT6351_PMIC_RG_VCORE_DTS_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_DTS_ENB_SHIFT 13 +#define MT6351_PMIC_RG_VCORE_MIN_OFF_ADDR MT6351_VCORE_ANA_CON5 +#define MT6351_PMIC_RG_VCORE_MIN_OFF_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_MIN_OFF_SHIFT 14 +#define MT6351_PMIC_RG_VCORE_1P35UP_SEL_EN_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_1P35UP_SEL_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_1P35UP_SEL_EN_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_DLC_AUTO_MODE_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_DLC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_DLC_AUTO_MODE_SHIFT 1 +#define MT6351_PMIC_RG_VCORE_DLC_SEL_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_DLC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCORE_DLC_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VCORE_SRC_AUTO_MODE_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_SRC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_SRC_AUTO_MODE_SHIFT 5 +#define MT6351_PMIC_RG_VCORE_UGP_SR_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_UGP_SR_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_UGP_SR_SHIFT 6 +#define MT6351_PMIC_RG_VCORE_LGN_SR_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_LGN_SR_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_LGN_SR_SHIFT 8 +#define MT6351_PMIC_RG_VCORE_UGP_SR_PFM_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_UGP_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_UGP_SR_PFM_SHIFT 10 +#define MT6351_PMIC_RG_VCORE_LGN_SR_PFM_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_LGN_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_LGN_SR_PFM_SHIFT 12 +#define MT6351_PMIC_RG_VCORE_UGD_VTHSEL_ADDR MT6351_VCORE_ANA_CON6 +#define MT6351_PMIC_RG_VCORE_UGD_VTHSEL_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_UGD_VTHSEL_SHIFT 14 +#define MT6351_PMIC_RG_VCORE_FNLX_SNS_ADDR MT6351_VCORE_ANA_CON7 +#define MT6351_PMIC_RG_VCORE_FNLX_SNS_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_FNLX_SNS_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_VDIFF_ENLOWIQ_ADDR MT6351_VCORE_ANA_CON7 +#define MT6351_PMIC_RG_VCORE_VDIFF_ENLOWIQ_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_VDIFF_ENLOWIQ_SHIFT 1 +#define MT6351_PMIC_RG_VCORE_PFMOC_FWUPOFF_ADDR MT6351_VCORE_ANA_CON7 +#define MT6351_PMIC_RG_VCORE_PFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_PFMOC_FWUPOFF_SHIFT 2 +#define MT6351_PMIC_RG_VCORE_PWFMOC_FWUPOFF_ADDR MT6351_VCORE_ANA_CON7 +#define MT6351_PMIC_RG_VCORE_PWFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_PWFMOC_FWUPOFF_SHIFT 3 +#define MT6351_PMIC_RG_VCORE_CP_FWUPOFF_ADDR MT6351_VCORE_ANA_CON7 +#define MT6351_PMIC_RG_VCORE_CP_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_CP_FWUPOFF_SHIFT 4 +#define MT6351_PMIC_RG_VCORE_ZX_GATING_ADDR MT6351_VCORE_ANA_CON7 +#define MT6351_PMIC_RG_VCORE_ZX_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_ZX_GATING_SHIFT 5 +#define MT6351_PMIC_RG_VCORE_RSV_ADDR MT6351_VCORE_ANA_CON8 +#define MT6351_PMIC_RG_VCORE_RSV_MASK 0xFFFF +#define MT6351_PMIC_RG_VCORE_RSV_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_PREOC_TRIMMING_ADDR MT6351_VCORE_ANA_CON9 +#define MT6351_PMIC_RG_VCORE_PREOC_TRIMMING_MASK 0x1F +#define MT6351_PMIC_RG_VCORE_PREOC_TRIMMING_SHIFT 0 +#define MT6351_PMIC_RG_VCORE_AZC_EN_ADDR MT6351_VCORE_ANA_CON9 +#define MT6351_PMIC_RG_VCORE_AZC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_AZC_EN_SHIFT 5 +#define MT6351_PMIC_RG_VCORE_AZC_DELAY_ADDR MT6351_VCORE_ANA_CON9 +#define MT6351_PMIC_RG_VCORE_AZC_DELAY_MASK 0x3 +#define MT6351_PMIC_RG_VCORE_AZC_DELAY_SHIFT 6 +#define MT6351_PMIC_RG_VCORE_AZC_HOLD_ENB_ADDR MT6351_VCORE_ANA_CON9 +#define MT6351_PMIC_RG_VCORE_AZC_HOLD_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VCORE_AZC_HOLD_ENB_SHIFT 8 +#define MT6351_PMIC_RGS_QI_VCORE_OC_STATUS_ADDR MT6351_VCORE_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VCORE_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VCORE_OC_STATUS_SHIFT 9 +#define MT6351_PMIC_RGS_QI_VCORE_DIG_MON_ADDR MT6351_VCORE_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VCORE_DIG_MON_MASK 0xF +#define MT6351_PMIC_RGS_QI_VCORE_DIG_MON_SHIFT 10 +#define MT6351_PMIC_RGS_VCORE_ENPWM_STATUS_ADDR MT6351_VCORE_ANA_CON9 +#define MT6351_PMIC_RGS_VCORE_ENPWM_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_VCORE_ENPWM_STATUS_SHIFT 14 +#define MT6351_PMIC_RGS_QI_VCORE_PREOC_ADDR MT6351_VCORE_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VCORE_PREOC_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VCORE_PREOC_SHIFT 15 +#define MT6351_PMIC_RG_VGPU_MODESET_ADDR MT6351_VGPU_ANA_CON0 +#define MT6351_PMIC_RG_VGPU_MODESET_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_MODESET_SHIFT 1 +#define MT6351_PMIC_RG_VGPU_NDIS_EN_ADDR MT6351_VGPU_ANA_CON0 +#define MT6351_PMIC_RG_VGPU_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_NDIS_EN_SHIFT 2 +#define MT6351_PMIC_RG_VGPU_VRF18_SSTART_EN_ADDR MT6351_VGPU_ANA_CON0 +#define MT6351_PMIC_RG_VGPU_VRF18_SSTART_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_VRF18_SSTART_EN_SHIFT 3 +#define MT6351_PMIC_RG_VGPU_AUTO_MODE_ADDR MT6351_VGPU_ANA_CON0 +#define MT6351_PMIC_RG_VGPU_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_AUTO_MODE_SHIFT 4 +#define MT6351_PMIC_RG_VGPU_RZSEL0_ADDR MT6351_VGPU_ANA_CON1 +#define MT6351_PMIC_RG_VGPU_RZSEL0_MASK 0x7 +#define MT6351_PMIC_RG_VGPU_RZSEL0_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_RZSEL1_ADDR MT6351_VGPU_ANA_CON1 +#define MT6351_PMIC_RG_VGPU_RZSEL1_MASK 0xF +#define MT6351_PMIC_RG_VGPU_RZSEL1_SHIFT 3 +#define MT6351_PMIC_RG_VGPU_CCSEL0_ADDR MT6351_VGPU_ANA_CON1 +#define MT6351_PMIC_RG_VGPU_CCSEL0_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_CCSEL0_SHIFT 7 +#define MT6351_PMIC_RG_VGPU_CCSEL1_ADDR MT6351_VGPU_ANA_CON1 +#define MT6351_PMIC_RG_VGPU_CCSEL1_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_CCSEL1_SHIFT 9 +#define MT6351_PMIC_RG_VGPU_CSL_ADDR MT6351_VGPU_ANA_CON1 +#define MT6351_PMIC_RG_VGPU_CSL_MASK 0xF +#define MT6351_PMIC_RG_VGPU_CSL_SHIFT 11 +#define MT6351_PMIC_RG_VGPU_SLP_ADDR MT6351_VGPU_ANA_CON2 +#define MT6351_PMIC_RG_VGPU_SLP_MASK 0x7 +#define MT6351_PMIC_RG_VGPU_SLP_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_ADRC_FEN_ADDR MT6351_VGPU_ANA_CON2 +#define MT6351_PMIC_RG_VGPU_ADRC_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_ADRC_FEN_SHIFT 3 +#define MT6351_PMIC_RG_VGPU_VCCAP_CLAMP_FEN_ADDR MT6351_VGPU_ANA_CON2 +#define MT6351_PMIC_RG_VGPU_VCCAP_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_VCCAP_CLAMP_FEN_SHIFT 4 +#define MT6351_PMIC_RG_VGPU_VC_CLAMP_FEN_ADDR MT6351_VGPU_ANA_CON2 +#define MT6351_PMIC_RG_VGPU_VC_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_VC_CLAMP_FEN_SHIFT 5 +#define MT6351_PMIC_RG_VGPU_PREOC_SEL_ADDR MT6351_VGPU_ANA_CON2 +#define MT6351_PMIC_RG_VGPU_PREOC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VGPU_PREOC_SEL_SHIFT 6 +#define MT6351_PMIC_RG_VGPU_PFMOC_ADDR MT6351_VGPU_ANA_CON2 +#define MT6351_PMIC_RG_VGPU_PFMOC_MASK 0x7 +#define MT6351_PMIC_RG_VGPU_PFMOC_SHIFT 9 +#define MT6351_PMIC_RG_VGPU_CSR_ADDR MT6351_VGPU_ANA_CON2 +#define MT6351_PMIC_RG_VGPU_CSR_MASK 0x7 +#define MT6351_PMIC_RG_VGPU_CSR_SHIFT 12 +#define MT6351_PMIC_RG_VGPU_ZXOS_TRIM_ADDR MT6351_VGPU_ANA_CON3 +#define MT6351_PMIC_RG_VGPU_ZXOS_TRIM_MASK 0xFF +#define MT6351_PMIC_RG_VGPU_ZXOS_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_CSM_N_ADDR MT6351_VGPU_ANA_CON3 +#define MT6351_PMIC_RG_VGPU_CSM_N_MASK 0x3F +#define MT6351_PMIC_RG_VGPU_CSM_N_SHIFT 8 +#define MT6351_PMIC_RG_VGPU_CSM_P_ADDR MT6351_VGPU_ANA_CON4 +#define MT6351_PMIC_RG_VGPU_CSM_P_MASK 0x3F +#define MT6351_PMIC_RG_VGPU_CSM_P_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_PFMSR_EH_ADDR MT6351_VGPU_ANA_CON4 +#define MT6351_PMIC_RG_VGPU_PFMSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_PFMSR_EH_SHIFT 6 +#define MT6351_PMIC_RG_VGPU_NLIM_GATING_ADDR MT6351_VGPU_ANA_CON4 +#define MT6351_PMIC_RG_VGPU_NLIM_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_NLIM_GATING_SHIFT 7 +#define MT6351_PMIC_RG_VGPU_PWRSR_EH_ADDR MT6351_VGPU_ANA_CON4 +#define MT6351_PMIC_RG_VGPU_PWRSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_PWRSR_EH_SHIFT 8 +#define MT6351_PMIC_RG_VGPU_HS_VTHDET_ADDR MT6351_VGPU_ANA_CON4 +#define MT6351_PMIC_RG_VGPU_HS_VTHDET_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_HS_VTHDET_SHIFT 9 +#define MT6351_PMIC_RG_VGPU_PG_GATING_ADDR MT6351_VGPU_ANA_CON4 +#define MT6351_PMIC_RG_VGPU_PG_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_PG_GATING_SHIFT 10 +#define MT6351_PMIC_RG_VGPU_HS_ONSPEED_EH_ADDR MT6351_VGPU_ANA_CON4 +#define MT6351_PMIC_RG_VGPU_HS_ONSPEED_EH_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_HS_ONSPEED_EH_SHIFT 11 +#define MT6351_PMIC_RG_VGPU_NLIM_TRIMMING_ADDR MT6351_VGPU_ANA_CON4 +#define MT6351_PMIC_RG_VGPU_NLIM_TRIMMING_MASK 0xF +#define MT6351_PMIC_RG_VGPU_NLIM_TRIMMING_SHIFT 12 +#define MT6351_PMIC_RG_VGPU_DLC_ADDR MT6351_VGPU_ANA_CON5 +#define MT6351_PMIC_RG_VGPU_DLC_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_DLC_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_DLC_N_ADDR MT6351_VGPU_ANA_CON5 +#define MT6351_PMIC_RG_VGPU_DLC_N_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_DLC_N_SHIFT 2 +#define MT6351_PMIC_RG_VGPU_PFM_RIP_ADDR MT6351_VGPU_ANA_CON5 +#define MT6351_PMIC_RG_VGPU_PFM_RIP_MASK 0x7 +#define MT6351_PMIC_RG_VGPU_PFM_RIP_SHIFT 4 +#define MT6351_PMIC_RG_VGPU_TRAN_BST_ADDR MT6351_VGPU_ANA_CON5 +#define MT6351_PMIC_RG_VGPU_TRAN_BST_MASK 0x3F +#define MT6351_PMIC_RG_VGPU_TRAN_BST_SHIFT 7 +#define MT6351_PMIC_RG_VGPU_DTS_ENB_ADDR MT6351_VGPU_ANA_CON5 +#define MT6351_PMIC_RG_VGPU_DTS_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_DTS_ENB_SHIFT 13 +#define MT6351_PMIC_RG_VGPU_MIN_OFF_ADDR MT6351_VGPU_ANA_CON5 +#define MT6351_PMIC_RG_VGPU_MIN_OFF_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_MIN_OFF_SHIFT 14 +#define MT6351_PMIC_RG_VGPU_1P35UP_SEL_EN_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_1P35UP_SEL_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_1P35UP_SEL_EN_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_DLC_AUTO_MODE_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_DLC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_DLC_AUTO_MODE_SHIFT 1 +#define MT6351_PMIC_RG_VGPU_DLC_SEL_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_DLC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VGPU_DLC_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VGPU_SRC_AUTO_MODE_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_SRC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_SRC_AUTO_MODE_SHIFT 5 +#define MT6351_PMIC_RG_VGPU_UGP_SR_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_UGP_SR_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_UGP_SR_SHIFT 6 +#define MT6351_PMIC_RG_VGPU_LGN_SR_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_LGN_SR_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_LGN_SR_SHIFT 8 +#define MT6351_PMIC_RG_VGPU_UGP_SR_PFM_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_UGP_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_UGP_SR_PFM_SHIFT 10 +#define MT6351_PMIC_RG_VGPU_LGN_SR_PFM_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_LGN_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_LGN_SR_PFM_SHIFT 12 +#define MT6351_PMIC_RG_VGPU_UGD_VTHSEL_ADDR MT6351_VGPU_ANA_CON6 +#define MT6351_PMIC_RG_VGPU_UGD_VTHSEL_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_UGD_VTHSEL_SHIFT 14 +#define MT6351_PMIC_RG_VGPU_FNLX_SNS_ADDR MT6351_VGPU_ANA_CON7 +#define MT6351_PMIC_RG_VGPU_FNLX_SNS_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_FNLX_SNS_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_VDIFF_ENLOWIQ_ADDR MT6351_VGPU_ANA_CON7 +#define MT6351_PMIC_RG_VGPU_VDIFF_ENLOWIQ_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_VDIFF_ENLOWIQ_SHIFT 1 +#define MT6351_PMIC_RG_VGPU_PFMOC_FWUPOFF_ADDR MT6351_VGPU_ANA_CON7 +#define MT6351_PMIC_RG_VGPU_PFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_PFMOC_FWUPOFF_SHIFT 2 +#define MT6351_PMIC_RG_VGPU_PWFMOC_FWUPOFF_ADDR MT6351_VGPU_ANA_CON7 +#define MT6351_PMIC_RG_VGPU_PWFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_PWFMOC_FWUPOFF_SHIFT 3 +#define MT6351_PMIC_RG_VGPU_CP_FWUPOFF_ADDR MT6351_VGPU_ANA_CON7 +#define MT6351_PMIC_RG_VGPU_CP_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_CP_FWUPOFF_SHIFT 4 +#define MT6351_PMIC_RG_VGPU_ZX_GATING_ADDR MT6351_VGPU_ANA_CON7 +#define MT6351_PMIC_RG_VGPU_ZX_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_ZX_GATING_SHIFT 5 +#define MT6351_PMIC_RG_VGPU_RSV_ADDR MT6351_VGPU_ANA_CON8 +#define MT6351_PMIC_RG_VGPU_RSV_MASK 0xFFFF +#define MT6351_PMIC_RG_VGPU_RSV_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_PREOC_TRIMMING_ADDR MT6351_VGPU_ANA_CON9 +#define MT6351_PMIC_RG_VGPU_PREOC_TRIMMING_MASK 0x1F +#define MT6351_PMIC_RG_VGPU_PREOC_TRIMMING_SHIFT 0 +#define MT6351_PMIC_RG_VGPU_AZC_EN_ADDR MT6351_VGPU_ANA_CON9 +#define MT6351_PMIC_RG_VGPU_AZC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_AZC_EN_SHIFT 5 +#define MT6351_PMIC_RG_VGPU_AZC_DELAY_ADDR MT6351_VGPU_ANA_CON9 +#define MT6351_PMIC_RG_VGPU_AZC_DELAY_MASK 0x3 +#define MT6351_PMIC_RG_VGPU_AZC_DELAY_SHIFT 6 +#define MT6351_PMIC_RG_VGPU_AZC_HOLD_ENB_ADDR MT6351_VGPU_ANA_CON9 +#define MT6351_PMIC_RG_VGPU_AZC_HOLD_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VGPU_AZC_HOLD_ENB_SHIFT 8 +#define MT6351_PMIC_RGS_QI_VGPU_OC_STATUS_ADDR MT6351_VGPU_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VGPU_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VGPU_OC_STATUS_SHIFT 9 +#define MT6351_PMIC_RGS_QI_VGPU_DIG_MON_ADDR MT6351_VGPU_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VGPU_DIG_MON_MASK 0xF +#define MT6351_PMIC_RGS_QI_VGPU_DIG_MON_SHIFT 10 +#define MT6351_PMIC_RGS_VGPU_ENPWM_STATUS_ADDR MT6351_VGPU_ANA_CON9 +#define MT6351_PMIC_RGS_VGPU_ENPWM_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_VGPU_ENPWM_STATUS_SHIFT 14 +#define MT6351_PMIC_RGS_QI_VGPU_PREOC_ADDR MT6351_VGPU_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VGPU_PREOC_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VGPU_PREOC_SHIFT 15 +#define MT6351_PMIC_RG_VSRAM_MD_MODESET_ADDR MT6351_VSRAM_MD_ANA_CON0 +#define MT6351_PMIC_RG_VSRAM_MD_MODESET_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_MODESET_SHIFT 1 +#define MT6351_PMIC_RG_VSRAM_MD_NDIS_EN_ADDR MT6351_VSRAM_MD_ANA_CON0 +#define MT6351_PMIC_RG_VSRAM_MD_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_NDIS_EN_SHIFT 2 +#define MT6351_PMIC_RG_VSRAM_MD_VRF18_SSTART_EN_ADDR MT6351_VSRAM_MD_ANA_CON0 +#define MT6351_PMIC_RG_VSRAM_MD_VRF18_SSTART_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_VRF18_SSTART_EN_SHIFT 3 +#define MT6351_PMIC_RG_VSRAM_MD_AUTO_MODE_ADDR MT6351_VSRAM_MD_ANA_CON0 +#define MT6351_PMIC_RG_VSRAM_MD_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_AUTO_MODE_SHIFT 4 +#define MT6351_PMIC_RG_VSRAM_MD_RZSEL0_ADDR MT6351_VSRAM_MD_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_MD_RZSEL0_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_MD_RZSEL0_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_RZSEL1_ADDR MT6351_VSRAM_MD_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_MD_RZSEL1_MASK 0xF +#define MT6351_PMIC_RG_VSRAM_MD_RZSEL1_SHIFT 3 +#define MT6351_PMIC_RG_VSRAM_MD_CCSEL0_ADDR MT6351_VSRAM_MD_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_MD_CCSEL0_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_CCSEL0_SHIFT 7 +#define MT6351_PMIC_RG_VSRAM_MD_CCSEL1_ADDR MT6351_VSRAM_MD_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_MD_CCSEL1_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_CCSEL1_SHIFT 9 +#define MT6351_PMIC_RG_VSRAM_MD_CSL_ADDR MT6351_VSRAM_MD_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_MD_CSL_MASK 0xF +#define MT6351_PMIC_RG_VSRAM_MD_CSL_SHIFT 11 +#define MT6351_PMIC_RG_VSRAM_MD_SLP_ADDR MT6351_VSRAM_MD_ANA_CON2 +#define MT6351_PMIC_RG_VSRAM_MD_SLP_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_MD_SLP_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_ADRC_FEN_ADDR MT6351_VSRAM_MD_ANA_CON2 +#define MT6351_PMIC_RG_VSRAM_MD_ADRC_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_ADRC_FEN_SHIFT 3 +#define MT6351_PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN_ADDR MT6351_VSRAM_MD_ANA_CON2 +#define MT6351_PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN_SHIFT 4 +#define MT6351_PMIC_RG_VSRAM_MD_VC_CLAMP_FEN_ADDR MT6351_VSRAM_MD_ANA_CON2 +#define MT6351_PMIC_RG_VSRAM_MD_VC_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_VC_CLAMP_FEN_SHIFT 5 +#define MT6351_PMIC_RG_VSRAM_MD_PFMOC_ADDR MT6351_VSRAM_MD_ANA_CON2 +#define MT6351_PMIC_RG_VSRAM_MD_PFMOC_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_MD_PFMOC_SHIFT 6 +#define MT6351_PMIC_RG_VSRAM_MD_CSR_ADDR MT6351_VSRAM_MD_ANA_CON2 +#define MT6351_PMIC_RG_VSRAM_MD_CSR_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_MD_CSR_SHIFT 9 +#define MT6351_PMIC_RG_VSRAM_MD_ZXOS_TRIM_ADDR MT6351_VSRAM_MD_ANA_CON3 +#define MT6351_PMIC_RG_VSRAM_MD_ZXOS_TRIM_MASK 0xFF +#define MT6351_PMIC_RG_VSRAM_MD_ZXOS_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_PFMSR_EH_ADDR MT6351_VSRAM_MD_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_PFMSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_PFMSR_EH_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_NLIM_GATING_ADDR MT6351_VSRAM_MD_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_NLIM_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_NLIM_GATING_SHIFT 1 +#define MT6351_PMIC_RG_VSRAM_MD_PWRSR_EH_ADDR MT6351_VSRAM_MD_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_PWRSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_PWRSR_EH_SHIFT 2 +#define MT6351_PMIC_RG_VSRAM_MD_HS_VTHDET_ADDR MT6351_VSRAM_MD_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_HS_VTHDET_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_HS_VTHDET_SHIFT 3 +#define MT6351_PMIC_RG_VSRAM_MD_PG_GATING_ADDR MT6351_VSRAM_MD_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_PG_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_PG_GATING_SHIFT 4 +#define MT6351_PMIC_RG_VSRAM_MD_HS_ONSPEED_EH_ADDR MT6351_VSRAM_MD_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_HS_ONSPEED_EH_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_HS_ONSPEED_EH_SHIFT 5 +#define MT6351_PMIC_RG_VSRAM_MD_NLIM_TRIMMING_ADDR MT6351_VSRAM_MD_ANA_CON4 +#define MT6351_PMIC_RG_VSRAM_MD_NLIM_TRIMMING_MASK 0xF +#define MT6351_PMIC_RG_VSRAM_MD_NLIM_TRIMMING_SHIFT 6 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_ADDR MT6351_VSRAM_MD_ANA_CON5 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_N_ADDR MT6351_VSRAM_MD_ANA_CON5 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_N_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_N_SHIFT 2 +#define MT6351_PMIC_RG_VSRAM_MD_PFM_RIP_ADDR MT6351_VSRAM_MD_ANA_CON5 +#define MT6351_PMIC_RG_VSRAM_MD_PFM_RIP_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_MD_PFM_RIP_SHIFT 4 +#define MT6351_PMIC_RG_VSRAM_MD_TRAN_BST_ADDR MT6351_VSRAM_MD_ANA_CON5 +#define MT6351_PMIC_RG_VSRAM_MD_TRAN_BST_MASK 0x3F +#define MT6351_PMIC_RG_VSRAM_MD_TRAN_BST_SHIFT 7 +#define MT6351_PMIC_RG_VSRAM_MD_DTS_ENB_ADDR MT6351_VSRAM_MD_ANA_CON5 +#define MT6351_PMIC_RG_VSRAM_MD_DTS_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_DTS_ENB_SHIFT 13 +#define MT6351_PMIC_RG_VSRAM_MD_MIN_OFF_ADDR MT6351_VSRAM_MD_ANA_CON5 +#define MT6351_PMIC_RG_VSRAM_MD_MIN_OFF_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_MIN_OFF_SHIFT 14 +#define MT6351_PMIC_RG_VSRAM_MD_1P35UP_SEL_EN_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_1P35UP_SEL_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_1P35UP_SEL_EN_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_AUTO_MODE_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_AUTO_MODE_SHIFT 1 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_SEL_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_MD_DLC_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VSRAM_MD_SRC_AUTO_MODE_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_SRC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_SRC_AUTO_MODE_SHIFT 5 +#define MT6351_PMIC_RG_VSRAM_MD_UGP_SR_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_UGP_SR_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_UGP_SR_SHIFT 6 +#define MT6351_PMIC_RG_VSRAM_MD_LGN_SR_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_LGN_SR_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_LGN_SR_SHIFT 8 +#define MT6351_PMIC_RG_VSRAM_MD_UGP_SR_PFM_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_UGP_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_UGP_SR_PFM_SHIFT 10 +#define MT6351_PMIC_RG_VSRAM_MD_LGN_SR_PFM_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_LGN_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_LGN_SR_PFM_SHIFT 12 +#define MT6351_PMIC_RG_VSRAM_MD_UGD_VTHSEL_ADDR MT6351_VSRAM_MD_ANA_CON6 +#define MT6351_PMIC_RG_VSRAM_MD_UGD_VTHSEL_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_UGD_VTHSEL_SHIFT 14 +#define MT6351_PMIC_RG_VSRAM_MD_FNLX_SNS_ADDR MT6351_VSRAM_MD_ANA_CON7 +#define MT6351_PMIC_RG_VSRAM_MD_FNLX_SNS_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_FNLX_SNS_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ_ADDR MT6351_VSRAM_MD_ANA_CON7 +#define MT6351_PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ_SHIFT 1 +#define MT6351_PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF_ADDR MT6351_VSRAM_MD_ANA_CON7 +#define MT6351_PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF_SHIFT 2 +#define MT6351_PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF_ADDR MT6351_VSRAM_MD_ANA_CON7 +#define MT6351_PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF_SHIFT 3 +#define MT6351_PMIC_RG_VSRAM_MD_CP_FWUPOFF_ADDR MT6351_VSRAM_MD_ANA_CON7 +#define MT6351_PMIC_RG_VSRAM_MD_CP_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_CP_FWUPOFF_SHIFT 4 +#define MT6351_PMIC_RG_VSRAM_MD_ZX_GATING_ADDR MT6351_VSRAM_MD_ANA_CON7 +#define MT6351_PMIC_RG_VSRAM_MD_ZX_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_ZX_GATING_SHIFT 5 +#define MT6351_PMIC_RG_VSRAM_MD_RSV_ADDR MT6351_VSRAM_MD_ANA_CON8 +#define MT6351_PMIC_RG_VSRAM_MD_RSV_MASK 0xFFFF +#define MT6351_PMIC_RG_VSRAM_MD_RSV_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_EN_ADDR MT6351_VSRAM_MD_ANA_CON9 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_EN_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_DELAY_ADDR MT6351_VSRAM_MD_ANA_CON9 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_DELAY_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_DELAY_SHIFT 1 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_HOLD_ENB_ADDR MT6351_VSRAM_MD_ANA_CON9 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_HOLD_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_MD_AZC_HOLD_ENB_SHIFT 3 +#define MT6351_PMIC_RGS_QI_VSRAM_MD_OC_STATUS_ADDR MT6351_VSRAM_MD_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VSRAM_MD_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VSRAM_MD_OC_STATUS_SHIFT 4 +#define MT6351_PMIC_RGS_QI_VSRAM_MD_DIG_MON_ADDR MT6351_VSRAM_MD_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VSRAM_MD_DIG_MON_MASK 0xF +#define MT6351_PMIC_RGS_QI_VSRAM_MD_DIG_MON_SHIFT 5 +#define MT6351_PMIC_RGS_VSRAM_MD_ENPWM_STATUS_ADDR MT6351_VSRAM_MD_ANA_CON9 +#define MT6351_PMIC_RGS_VSRAM_MD_ENPWM_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_VSRAM_MD_ENPWM_STATUS_SHIFT 9 +#define MT6351_PMIC_RG_VMODEM_MODESET_ADDR MT6351_VMODEM_ANA_CON0 +#define MT6351_PMIC_RG_VMODEM_MODESET_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_MODESET_SHIFT 1 +#define MT6351_PMIC_RG_VMODEM_NDIS_EN_ADDR MT6351_VMODEM_ANA_CON0 +#define MT6351_PMIC_RG_VMODEM_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_NDIS_EN_SHIFT 2 +#define MT6351_PMIC_RG_VMODEM_VRF18_SSTART_EN_ADDR MT6351_VMODEM_ANA_CON0 +#define MT6351_PMIC_RG_VMODEM_VRF18_SSTART_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_VRF18_SSTART_EN_SHIFT 3 +#define MT6351_PMIC_RG_VMODEM_AUTO_MODE_ADDR MT6351_VMODEM_ANA_CON0 +#define MT6351_PMIC_RG_VMODEM_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_AUTO_MODE_SHIFT 4 +#define MT6351_PMIC_RG_VMODEM_RZSEL0_ADDR MT6351_VMODEM_ANA_CON1 +#define MT6351_PMIC_RG_VMODEM_RZSEL0_MASK 0x7 +#define MT6351_PMIC_RG_VMODEM_RZSEL0_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_RZSEL1_ADDR MT6351_VMODEM_ANA_CON1 +#define MT6351_PMIC_RG_VMODEM_RZSEL1_MASK 0xF +#define MT6351_PMIC_RG_VMODEM_RZSEL1_SHIFT 3 +#define MT6351_PMIC_RG_VMODEM_CCSEL0_ADDR MT6351_VMODEM_ANA_CON1 +#define MT6351_PMIC_RG_VMODEM_CCSEL0_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_CCSEL0_SHIFT 7 +#define MT6351_PMIC_RG_VMODEM_CCSEL1_ADDR MT6351_VMODEM_ANA_CON1 +#define MT6351_PMIC_RG_VMODEM_CCSEL1_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_CCSEL1_SHIFT 9 +#define MT6351_PMIC_RG_VMODEM_CSL_ADDR MT6351_VMODEM_ANA_CON1 +#define MT6351_PMIC_RG_VMODEM_CSL_MASK 0xF +#define MT6351_PMIC_RG_VMODEM_CSL_SHIFT 11 +#define MT6351_PMIC_RG_VMODEM_SLP_ADDR MT6351_VMODEM_ANA_CON2 +#define MT6351_PMIC_RG_VMODEM_SLP_MASK 0x7 +#define MT6351_PMIC_RG_VMODEM_SLP_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_ADRC_FEN_ADDR MT6351_VMODEM_ANA_CON2 +#define MT6351_PMIC_RG_VMODEM_ADRC_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_ADRC_FEN_SHIFT 3 +#define MT6351_PMIC_RG_VMODEM_VCCAP_CLAMP_FEN_ADDR MT6351_VMODEM_ANA_CON2 +#define MT6351_PMIC_RG_VMODEM_VCCAP_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_VCCAP_CLAMP_FEN_SHIFT 4 +#define MT6351_PMIC_RG_VMODEM_VC_CLAMP_FEN_ADDR MT6351_VMODEM_ANA_CON2 +#define MT6351_PMIC_RG_VMODEM_VC_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_VC_CLAMP_FEN_SHIFT 5 +#define MT6351_PMIC_RG_VMODEM_PFMOC_ADDR MT6351_VMODEM_ANA_CON2 +#define MT6351_PMIC_RG_VMODEM_PFMOC_MASK 0x7 +#define MT6351_PMIC_RG_VMODEM_PFMOC_SHIFT 6 +#define MT6351_PMIC_RG_VMODEM_CSR_ADDR MT6351_VMODEM_ANA_CON2 +#define MT6351_PMIC_RG_VMODEM_CSR_MASK 0x7 +#define MT6351_PMIC_RG_VMODEM_CSR_SHIFT 9 +#define MT6351_PMIC_RG_VMODEM_ZXOS_TRIM_ADDR MT6351_VMODEM_ANA_CON3 +#define MT6351_PMIC_RG_VMODEM_ZXOS_TRIM_MASK 0xFF +#define MT6351_PMIC_RG_VMODEM_ZXOS_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_PFMSR_EH_ADDR MT6351_VMODEM_ANA_CON4 +#define MT6351_PMIC_RG_VMODEM_PFMSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_PFMSR_EH_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_NLIM_GATING_ADDR MT6351_VMODEM_ANA_CON4 +#define MT6351_PMIC_RG_VMODEM_NLIM_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_NLIM_GATING_SHIFT 1 +#define MT6351_PMIC_RG_VMODEM_PWRSR_EH_ADDR MT6351_VMODEM_ANA_CON4 +#define MT6351_PMIC_RG_VMODEM_PWRSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_PWRSR_EH_SHIFT 2 +#define MT6351_PMIC_RG_VMODEM_HS_VTHDET_ADDR MT6351_VMODEM_ANA_CON4 +#define MT6351_PMIC_RG_VMODEM_HS_VTHDET_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_HS_VTHDET_SHIFT 3 +#define MT6351_PMIC_RG_VMODEM_PG_GATING_ADDR MT6351_VMODEM_ANA_CON4 +#define MT6351_PMIC_RG_VMODEM_PG_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_PG_GATING_SHIFT 4 +#define MT6351_PMIC_RG_VMODEM_HS_ONSPEED_EH_ADDR MT6351_VMODEM_ANA_CON4 +#define MT6351_PMIC_RG_VMODEM_HS_ONSPEED_EH_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_HS_ONSPEED_EH_SHIFT 5 +#define MT6351_PMIC_RG_VMODEM_NLIM_TRIMMING_ADDR MT6351_VMODEM_ANA_CON4 +#define MT6351_PMIC_RG_VMODEM_NLIM_TRIMMING_MASK 0xF +#define MT6351_PMIC_RG_VMODEM_NLIM_TRIMMING_SHIFT 6 +#define MT6351_PMIC_RG_VMODEM_DLC_ADDR MT6351_VMODEM_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_DLC_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_DLC_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_DLC_N_ADDR MT6351_VMODEM_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_DLC_N_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_DLC_N_SHIFT 2 +#define MT6351_PMIC_RG_VMODEM_PFM_RIP_ADDR MT6351_VMODEM_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_PFM_RIP_MASK 0x7 +#define MT6351_PMIC_RG_VMODEM_PFM_RIP_SHIFT 4 +#define MT6351_PMIC_RG_VMODEM_TRAN_BST_ADDR MT6351_VMODEM_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_TRAN_BST_MASK 0x3F +#define MT6351_PMIC_RG_VMODEM_TRAN_BST_SHIFT 7 +#define MT6351_PMIC_RG_VMODEM_DTS_ENB_ADDR MT6351_VMODEM_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_DTS_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_DTS_ENB_SHIFT 13 +#define MT6351_PMIC_RG_VMODEM_MIN_OFF_ADDR MT6351_VMODEM_ANA_CON5 +#define MT6351_PMIC_RG_VMODEM_MIN_OFF_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_MIN_OFF_SHIFT 14 +#define MT6351_PMIC_RG_VMODEM_1P35UP_SEL_EN_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_1P35UP_SEL_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_1P35UP_SEL_EN_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_DLC_AUTO_MODE_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_DLC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_DLC_AUTO_MODE_SHIFT 1 +#define MT6351_PMIC_RG_VMODEM_DLC_SEL_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_DLC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMODEM_DLC_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VMODEM_SRC_AUTO_MODE_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_SRC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_SRC_AUTO_MODE_SHIFT 5 +#define MT6351_PMIC_RG_VMODEM_UGP_SR_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_UGP_SR_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_UGP_SR_SHIFT 6 +#define MT6351_PMIC_RG_VMODEM_LGN_SR_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_LGN_SR_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_LGN_SR_SHIFT 8 +#define MT6351_PMIC_RG_VMODEM_UGP_SR_PFM_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_UGP_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_UGP_SR_PFM_SHIFT 10 +#define MT6351_PMIC_RG_VMODEM_LGN_SR_PFM_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_LGN_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_LGN_SR_PFM_SHIFT 12 +#define MT6351_PMIC_RG_VMODEM_UGD_VTHSEL_ADDR MT6351_VMODEM_ANA_CON6 +#define MT6351_PMIC_RG_VMODEM_UGD_VTHSEL_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_UGD_VTHSEL_SHIFT 14 +#define MT6351_PMIC_RG_VMODEM_FNLX_SNS_ADDR MT6351_VMODEM_ANA_CON7 +#define MT6351_PMIC_RG_VMODEM_FNLX_SNS_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_FNLX_SNS_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_VDIFF_ENLOWIQ_ADDR MT6351_VMODEM_ANA_CON7 +#define MT6351_PMIC_RG_VMODEM_VDIFF_ENLOWIQ_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_VDIFF_ENLOWIQ_SHIFT 1 +#define MT6351_PMIC_RG_VMODEM_PFMOC_FWUPOFF_ADDR MT6351_VMODEM_ANA_CON7 +#define MT6351_PMIC_RG_VMODEM_PFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_PFMOC_FWUPOFF_SHIFT 2 +#define MT6351_PMIC_RG_VMODEM_PWFMOC_FWUPOFF_ADDR MT6351_VMODEM_ANA_CON7 +#define MT6351_PMIC_RG_VMODEM_PWFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_PWFMOC_FWUPOFF_SHIFT 3 +#define MT6351_PMIC_RG_VMODEM_CP_FWUPOFF_ADDR MT6351_VMODEM_ANA_CON7 +#define MT6351_PMIC_RG_VMODEM_CP_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_CP_FWUPOFF_SHIFT 4 +#define MT6351_PMIC_RG_VMODEM_ZX_GATING_ADDR MT6351_VMODEM_ANA_CON7 +#define MT6351_PMIC_RG_VMODEM_ZX_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_ZX_GATING_SHIFT 5 +#define MT6351_PMIC_RG_VMODEM_RSV_ADDR MT6351_VMODEM_ANA_CON8 +#define MT6351_PMIC_RG_VMODEM_RSV_MASK 0xFFFF +#define MT6351_PMIC_RG_VMODEM_RSV_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_AZC_EN_ADDR MT6351_VMODEM_ANA_CON9 +#define MT6351_PMIC_RG_VMODEM_AZC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_AZC_EN_SHIFT 0 +#define MT6351_PMIC_RG_VMODEM_AZC_DELAY_ADDR MT6351_VMODEM_ANA_CON9 +#define MT6351_PMIC_RG_VMODEM_AZC_DELAY_MASK 0x3 +#define MT6351_PMIC_RG_VMODEM_AZC_DELAY_SHIFT 1 +#define MT6351_PMIC_RG_VMODEM_AZC_HOLD_ENB_ADDR MT6351_VMODEM_ANA_CON9 +#define MT6351_PMIC_RG_VMODEM_AZC_HOLD_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VMODEM_AZC_HOLD_ENB_SHIFT 3 +#define MT6351_PMIC_RGS_QI_VMODEM_OC_STATUS_ADDR MT6351_VMODEM_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VMODEM_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VMODEM_OC_STATUS_SHIFT 4 +#define MT6351_PMIC_RGS_QI_VMODEM_DIG_MON_ADDR MT6351_VMODEM_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VMODEM_DIG_MON_MASK 0xF +#define MT6351_PMIC_RGS_QI_VMODEM_DIG_MON_SHIFT 5 +#define MT6351_PMIC_RGS_VMODEM_ENPWM_STATUS_ADDR MT6351_VMODEM_ANA_CON9 +#define MT6351_PMIC_RGS_VMODEM_ENPWM_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_VMODEM_ENPWM_STATUS_SHIFT 9 +#define MT6351_PMIC_RG_VMD1_MODESET_ADDR MT6351_VMD1_ANA_CON0 +#define MT6351_PMIC_RG_VMD1_MODESET_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_MODESET_SHIFT 1 +#define MT6351_PMIC_RG_VMD1_NDIS_EN_ADDR MT6351_VMD1_ANA_CON0 +#define MT6351_PMIC_RG_VMD1_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_NDIS_EN_SHIFT 2 +#define MT6351_PMIC_RG_VMD1_VRF18_SSTART_EN_ADDR MT6351_VMD1_ANA_CON0 +#define MT6351_PMIC_RG_VMD1_VRF18_SSTART_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_VRF18_SSTART_EN_SHIFT 3 +#define MT6351_PMIC_RG_VMD1_AUTO_MODE_ADDR MT6351_VMD1_ANA_CON0 +#define MT6351_PMIC_RG_VMD1_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_AUTO_MODE_SHIFT 4 +#define MT6351_PMIC_RG_VMD1_RZSEL0_ADDR MT6351_VMD1_ANA_CON1 +#define MT6351_PMIC_RG_VMD1_RZSEL0_MASK 0x7 +#define MT6351_PMIC_RG_VMD1_RZSEL0_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_RZSEL1_ADDR MT6351_VMD1_ANA_CON1 +#define MT6351_PMIC_RG_VMD1_RZSEL1_MASK 0xF +#define MT6351_PMIC_RG_VMD1_RZSEL1_SHIFT 3 +#define MT6351_PMIC_RG_VMD1_CCSEL0_ADDR MT6351_VMD1_ANA_CON1 +#define MT6351_PMIC_RG_VMD1_CCSEL0_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_CCSEL0_SHIFT 7 +#define MT6351_PMIC_RG_VMD1_CCSEL1_ADDR MT6351_VMD1_ANA_CON1 +#define MT6351_PMIC_RG_VMD1_CCSEL1_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_CCSEL1_SHIFT 9 +#define MT6351_PMIC_RG_VMD1_CSL_ADDR MT6351_VMD1_ANA_CON1 +#define MT6351_PMIC_RG_VMD1_CSL_MASK 0xF +#define MT6351_PMIC_RG_VMD1_CSL_SHIFT 11 +#define MT6351_PMIC_RG_VMD1_SLP_ADDR MT6351_VMD1_ANA_CON2 +#define MT6351_PMIC_RG_VMD1_SLP_MASK 0x7 +#define MT6351_PMIC_RG_VMD1_SLP_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_ADRC_FEN_ADDR MT6351_VMD1_ANA_CON2 +#define MT6351_PMIC_RG_VMD1_ADRC_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_ADRC_FEN_SHIFT 3 +#define MT6351_PMIC_RG_VMD1_VCCAP_CLAMP_FEN_ADDR MT6351_VMD1_ANA_CON2 +#define MT6351_PMIC_RG_VMD1_VCCAP_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_VCCAP_CLAMP_FEN_SHIFT 4 +#define MT6351_PMIC_RG_VMD1_VC_CLAMP_FEN_ADDR MT6351_VMD1_ANA_CON2 +#define MT6351_PMIC_RG_VMD1_VC_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_VC_CLAMP_FEN_SHIFT 5 +#define MT6351_PMIC_RG_VMD1_PFMOC_ADDR MT6351_VMD1_ANA_CON2 +#define MT6351_PMIC_RG_VMD1_PFMOC_MASK 0x7 +#define MT6351_PMIC_RG_VMD1_PFMOC_SHIFT 6 +#define MT6351_PMIC_RG_VMD1_CSR_ADDR MT6351_VMD1_ANA_CON2 +#define MT6351_PMIC_RG_VMD1_CSR_MASK 0x7 +#define MT6351_PMIC_RG_VMD1_CSR_SHIFT 9 +#define MT6351_PMIC_RG_VMD1_ZXOS_TRIM_ADDR MT6351_VMD1_ANA_CON3 +#define MT6351_PMIC_RG_VMD1_ZXOS_TRIM_MASK 0xFF +#define MT6351_PMIC_RG_VMD1_ZXOS_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_PFMSR_EH_ADDR MT6351_VMD1_ANA_CON4 +#define MT6351_PMIC_RG_VMD1_PFMSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_PFMSR_EH_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_NLIM_GATING_ADDR MT6351_VMD1_ANA_CON4 +#define MT6351_PMIC_RG_VMD1_NLIM_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_NLIM_GATING_SHIFT 1 +#define MT6351_PMIC_RG_VMD1_PWRSR_EH_ADDR MT6351_VMD1_ANA_CON4 +#define MT6351_PMIC_RG_VMD1_PWRSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_PWRSR_EH_SHIFT 2 +#define MT6351_PMIC_RG_VMD1_HS_VTHDET_ADDR MT6351_VMD1_ANA_CON4 +#define MT6351_PMIC_RG_VMD1_HS_VTHDET_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_HS_VTHDET_SHIFT 3 +#define MT6351_PMIC_RG_VMD1_PG_GATING_ADDR MT6351_VMD1_ANA_CON4 +#define MT6351_PMIC_RG_VMD1_PG_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_PG_GATING_SHIFT 4 +#define MT6351_PMIC_RG_VMD1_HS_ONSPEED_EH_ADDR MT6351_VMD1_ANA_CON4 +#define MT6351_PMIC_RG_VMD1_HS_ONSPEED_EH_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_HS_ONSPEED_EH_SHIFT 5 +#define MT6351_PMIC_RG_VMD1_NLIM_TRIMMING_ADDR MT6351_VMD1_ANA_CON4 +#define MT6351_PMIC_RG_VMD1_NLIM_TRIMMING_MASK 0xF +#define MT6351_PMIC_RG_VMD1_NLIM_TRIMMING_SHIFT 6 +#define MT6351_PMIC_RG_VMD1_DLC_ADDR MT6351_VMD1_ANA_CON5 +#define MT6351_PMIC_RG_VMD1_DLC_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_DLC_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_DLC_N_ADDR MT6351_VMD1_ANA_CON5 +#define MT6351_PMIC_RG_VMD1_DLC_N_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_DLC_N_SHIFT 2 +#define MT6351_PMIC_RG_VMD1_PFM_RIP_ADDR MT6351_VMD1_ANA_CON5 +#define MT6351_PMIC_RG_VMD1_PFM_RIP_MASK 0x7 +#define MT6351_PMIC_RG_VMD1_PFM_RIP_SHIFT 4 +#define MT6351_PMIC_RG_VMD1_TRAN_BST_ADDR MT6351_VMD1_ANA_CON5 +#define MT6351_PMIC_RG_VMD1_TRAN_BST_MASK 0x3F +#define MT6351_PMIC_RG_VMD1_TRAN_BST_SHIFT 7 +#define MT6351_PMIC_RG_VMD1_DTS_ENB_ADDR MT6351_VMD1_ANA_CON5 +#define MT6351_PMIC_RG_VMD1_DTS_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_DTS_ENB_SHIFT 13 +#define MT6351_PMIC_RG_VMD1_MIN_OFF_ADDR MT6351_VMD1_ANA_CON5 +#define MT6351_PMIC_RG_VMD1_MIN_OFF_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_MIN_OFF_SHIFT 14 +#define MT6351_PMIC_RG_VMD1_1P35UP_SEL_EN_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_1P35UP_SEL_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_1P35UP_SEL_EN_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_DLC_AUTO_MODE_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_DLC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_DLC_AUTO_MODE_SHIFT 1 +#define MT6351_PMIC_RG_VMD1_DLC_SEL_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_DLC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMD1_DLC_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VMD1_SRC_AUTO_MODE_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_SRC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_SRC_AUTO_MODE_SHIFT 5 +#define MT6351_PMIC_RG_VMD1_UGP_SR_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_UGP_SR_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_UGP_SR_SHIFT 6 +#define MT6351_PMIC_RG_VMD1_LGN_SR_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_LGN_SR_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_LGN_SR_SHIFT 8 +#define MT6351_PMIC_RG_VMD1_UGP_SR_PFM_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_UGP_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_UGP_SR_PFM_SHIFT 10 +#define MT6351_PMIC_RG_VMD1_LGN_SR_PFM_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_LGN_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_LGN_SR_PFM_SHIFT 12 +#define MT6351_PMIC_RG_VMD1_UGD_VTHSEL_ADDR MT6351_VMD1_ANA_CON6 +#define MT6351_PMIC_RG_VMD1_UGD_VTHSEL_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_UGD_VTHSEL_SHIFT 14 +#define MT6351_PMIC_RG_VMD1_FNLX_SNS_ADDR MT6351_VMD1_ANA_CON7 +#define MT6351_PMIC_RG_VMD1_FNLX_SNS_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_FNLX_SNS_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_VDIFF_ENLOWIQ_ADDR MT6351_VMD1_ANA_CON7 +#define MT6351_PMIC_RG_VMD1_VDIFF_ENLOWIQ_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_VDIFF_ENLOWIQ_SHIFT 1 +#define MT6351_PMIC_RG_VMD1_PFMOC_FWUPOFF_ADDR MT6351_VMD1_ANA_CON7 +#define MT6351_PMIC_RG_VMD1_PFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_PFMOC_FWUPOFF_SHIFT 2 +#define MT6351_PMIC_RG_VMD1_PWFMOC_FWUPOFF_ADDR MT6351_VMD1_ANA_CON7 +#define MT6351_PMIC_RG_VMD1_PWFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_PWFMOC_FWUPOFF_SHIFT 3 +#define MT6351_PMIC_RG_VMD1_CP_FWUPOFF_ADDR MT6351_VMD1_ANA_CON7 +#define MT6351_PMIC_RG_VMD1_CP_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_CP_FWUPOFF_SHIFT 4 +#define MT6351_PMIC_RG_VMD1_ZX_GATING_ADDR MT6351_VMD1_ANA_CON7 +#define MT6351_PMIC_RG_VMD1_ZX_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_ZX_GATING_SHIFT 5 +#define MT6351_PMIC_RG_VMD1_RSV_ADDR MT6351_VMD1_ANA_CON8 +#define MT6351_PMIC_RG_VMD1_RSV_MASK 0xFFFF +#define MT6351_PMIC_RG_VMD1_RSV_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_AZC_EN_ADDR MT6351_VMD1_ANA_CON9 +#define MT6351_PMIC_RG_VMD1_AZC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_AZC_EN_SHIFT 0 +#define MT6351_PMIC_RG_VMD1_AZC_DELAY_ADDR MT6351_VMD1_ANA_CON9 +#define MT6351_PMIC_RG_VMD1_AZC_DELAY_MASK 0x3 +#define MT6351_PMIC_RG_VMD1_AZC_DELAY_SHIFT 1 +#define MT6351_PMIC_RG_VMD1_AZC_HOLD_ENB_ADDR MT6351_VMD1_ANA_CON9 +#define MT6351_PMIC_RG_VMD1_AZC_HOLD_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VMD1_AZC_HOLD_ENB_SHIFT 3 +#define MT6351_PMIC_RGS_QI_VMD1_OC_STATUS_ADDR MT6351_VMD1_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VMD1_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VMD1_OC_STATUS_SHIFT 4 +#define MT6351_PMIC_RGS_QI_VMD1_DIG_MON_ADDR MT6351_VMD1_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VMD1_DIG_MON_MASK 0xF +#define MT6351_PMIC_RGS_QI_VMD1_DIG_MON_SHIFT 5 +#define MT6351_PMIC_RGS_VMD1_ENPWM_STATUS_ADDR MT6351_VMD1_ANA_CON9 +#define MT6351_PMIC_RGS_VMD1_ENPWM_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_VMD1_ENPWM_STATUS_SHIFT 9 +#define MT6351_PMIC_RG_VS1_MODESET_ADDR MT6351_VS1_ANA_CON0 +#define MT6351_PMIC_RG_VS1_MODESET_MASK 0x1 +#define MT6351_PMIC_RG_VS1_MODESET_SHIFT 1 +#define MT6351_PMIC_RG_VS1_NDIS_EN_ADDR MT6351_VS1_ANA_CON0 +#define MT6351_PMIC_RG_VS1_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VS1_NDIS_EN_SHIFT 2 +#define MT6351_PMIC_RG_VS1_VRF18_SSTART_EN_ADDR MT6351_VS1_ANA_CON0 +#define MT6351_PMIC_RG_VS1_VRF18_SSTART_EN_MASK 0x1 +#define MT6351_PMIC_RG_VS1_VRF18_SSTART_EN_SHIFT 3 +#define MT6351_PMIC_RG_VS1_AUTO_MODE_ADDR MT6351_VS1_ANA_CON0 +#define MT6351_PMIC_RG_VS1_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VS1_AUTO_MODE_SHIFT 4 +#define MT6351_PMIC_RG_VS1_RZSEL0_ADDR MT6351_VS1_ANA_CON1 +#define MT6351_PMIC_RG_VS1_RZSEL0_MASK 0x7 +#define MT6351_PMIC_RG_VS1_RZSEL0_SHIFT 0 +#define MT6351_PMIC_RG_VS1_RZSEL1_ADDR MT6351_VS1_ANA_CON1 +#define MT6351_PMIC_RG_VS1_RZSEL1_MASK 0xF +#define MT6351_PMIC_RG_VS1_RZSEL1_SHIFT 3 +#define MT6351_PMIC_RG_VS1_CCSEL0_ADDR MT6351_VS1_ANA_CON1 +#define MT6351_PMIC_RG_VS1_CCSEL0_MASK 0x3 +#define MT6351_PMIC_RG_VS1_CCSEL0_SHIFT 7 +#define MT6351_PMIC_RG_VS1_CCSEL1_ADDR MT6351_VS1_ANA_CON1 +#define MT6351_PMIC_RG_VS1_CCSEL1_MASK 0x3 +#define MT6351_PMIC_RG_VS1_CCSEL1_SHIFT 9 +#define MT6351_PMIC_RG_VS1_CSL_ADDR MT6351_VS1_ANA_CON1 +#define MT6351_PMIC_RG_VS1_CSL_MASK 0xF +#define MT6351_PMIC_RG_VS1_CSL_SHIFT 11 +#define MT6351_PMIC_RG_VS1_SLP_ADDR MT6351_VS1_ANA_CON2 +#define MT6351_PMIC_RG_VS1_SLP_MASK 0x7 +#define MT6351_PMIC_RG_VS1_SLP_SHIFT 0 +#define MT6351_PMIC_RG_VS1_ADRC_FEN_ADDR MT6351_VS1_ANA_CON2 +#define MT6351_PMIC_RG_VS1_ADRC_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VS1_ADRC_FEN_SHIFT 3 +#define MT6351_PMIC_RG_VS1_VCCAP_CLAMP_FEN_ADDR MT6351_VS1_ANA_CON2 +#define MT6351_PMIC_RG_VS1_VCCAP_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VS1_VCCAP_CLAMP_FEN_SHIFT 4 +#define MT6351_PMIC_RG_VS1_VC_CLAMP_FEN_ADDR MT6351_VS1_ANA_CON2 +#define MT6351_PMIC_RG_VS1_VC_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VS1_VC_CLAMP_FEN_SHIFT 5 +#define MT6351_PMIC_RG_VS1_PFMOC_ADDR MT6351_VS1_ANA_CON2 +#define MT6351_PMIC_RG_VS1_PFMOC_MASK 0x7 +#define MT6351_PMIC_RG_VS1_PFMOC_SHIFT 6 +#define MT6351_PMIC_RG_VS1_CSR_ADDR MT6351_VS1_ANA_CON2 +#define MT6351_PMIC_RG_VS1_CSR_MASK 0x7 +#define MT6351_PMIC_RG_VS1_CSR_SHIFT 9 +#define MT6351_PMIC_RG_VS1_ZXOS_TRIM_ADDR MT6351_VS1_ANA_CON3 +#define MT6351_PMIC_RG_VS1_ZXOS_TRIM_MASK 0xFF +#define MT6351_PMIC_RG_VS1_ZXOS_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_VS1_PFMSR_EH_ADDR MT6351_VS1_ANA_CON4 +#define MT6351_PMIC_RG_VS1_PFMSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VS1_PFMSR_EH_SHIFT 0 +#define MT6351_PMIC_RG_VS1_NLIM_GATING_ADDR MT6351_VS1_ANA_CON4 +#define MT6351_PMIC_RG_VS1_NLIM_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VS1_NLIM_GATING_SHIFT 1 +#define MT6351_PMIC_RG_VS1_PWRSR_EH_ADDR MT6351_VS1_ANA_CON4 +#define MT6351_PMIC_RG_VS1_PWRSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VS1_PWRSR_EH_SHIFT 2 +#define MT6351_PMIC_RG_VS1_HS_VTHDET_ADDR MT6351_VS1_ANA_CON4 +#define MT6351_PMIC_RG_VS1_HS_VTHDET_MASK 0x1 +#define MT6351_PMIC_RG_VS1_HS_VTHDET_SHIFT 3 +#define MT6351_PMIC_RG_VS1_PG_GATING_ADDR MT6351_VS1_ANA_CON4 +#define MT6351_PMIC_RG_VS1_PG_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VS1_PG_GATING_SHIFT 4 +#define MT6351_PMIC_RG_VS1_HS_ONSPEED_EH_ADDR MT6351_VS1_ANA_CON4 +#define MT6351_PMIC_RG_VS1_HS_ONSPEED_EH_MASK 0x1 +#define MT6351_PMIC_RG_VS1_HS_ONSPEED_EH_SHIFT 5 +#define MT6351_PMIC_RG_VS1_NLIM_TRIMMING_ADDR MT6351_VS1_ANA_CON4 +#define MT6351_PMIC_RG_VS1_NLIM_TRIMMING_MASK 0xF +#define MT6351_PMIC_RG_VS1_NLIM_TRIMMING_SHIFT 6 +#define MT6351_PMIC_RG_VS1_DLC_ADDR MT6351_VS1_ANA_CON5 +#define MT6351_PMIC_RG_VS1_DLC_MASK 0x3 +#define MT6351_PMIC_RG_VS1_DLC_SHIFT 0 +#define MT6351_PMIC_RG_VS1_DLC_N_ADDR MT6351_VS1_ANA_CON5 +#define MT6351_PMIC_RG_VS1_DLC_N_MASK 0x3 +#define MT6351_PMIC_RG_VS1_DLC_N_SHIFT 2 +#define MT6351_PMIC_RG_VS1_PFM_RIP_ADDR MT6351_VS1_ANA_CON5 +#define MT6351_PMIC_RG_VS1_PFM_RIP_MASK 0x7 +#define MT6351_PMIC_RG_VS1_PFM_RIP_SHIFT 4 +#define MT6351_PMIC_RG_VS1_TRAN_BST_ADDR MT6351_VS1_ANA_CON5 +#define MT6351_PMIC_RG_VS1_TRAN_BST_MASK 0x3F +#define MT6351_PMIC_RG_VS1_TRAN_BST_SHIFT 7 +#define MT6351_PMIC_RG_VS1_DTS_ENB_ADDR MT6351_VS1_ANA_CON5 +#define MT6351_PMIC_RG_VS1_DTS_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VS1_DTS_ENB_SHIFT 13 +#define MT6351_PMIC_RG_VS1_MIN_OFF_ADDR MT6351_VS1_ANA_CON5 +#define MT6351_PMIC_RG_VS1_MIN_OFF_MASK 0x3 +#define MT6351_PMIC_RG_VS1_MIN_OFF_SHIFT 14 +#define MT6351_PMIC_RG_VS1_1P35UP_SEL_EN_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_1P35UP_SEL_EN_MASK 0x1 +#define MT6351_PMIC_RG_VS1_1P35UP_SEL_EN_SHIFT 0 +#define MT6351_PMIC_RG_VS1_DLC_AUTO_MODE_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_DLC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VS1_DLC_AUTO_MODE_SHIFT 1 +#define MT6351_PMIC_RG_VS1_DLC_SEL_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_DLC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VS1_DLC_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VS1_SRC_AUTO_MODE_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_SRC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VS1_SRC_AUTO_MODE_SHIFT 5 +#define MT6351_PMIC_RG_VS1_UGP_SR_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_UGP_SR_MASK 0x3 +#define MT6351_PMIC_RG_VS1_UGP_SR_SHIFT 6 +#define MT6351_PMIC_RG_VS1_LGN_SR_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_LGN_SR_MASK 0x3 +#define MT6351_PMIC_RG_VS1_LGN_SR_SHIFT 8 +#define MT6351_PMIC_RG_VS1_UGP_SR_PFM_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_UGP_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VS1_UGP_SR_PFM_SHIFT 10 +#define MT6351_PMIC_RG_VS1_LGN_SR_PFM_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_LGN_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VS1_LGN_SR_PFM_SHIFT 12 +#define MT6351_PMIC_RG_VS1_UGD_VTHSEL_ADDR MT6351_VS1_ANA_CON6 +#define MT6351_PMIC_RG_VS1_UGD_VTHSEL_MASK 0x3 +#define MT6351_PMIC_RG_VS1_UGD_VTHSEL_SHIFT 14 +#define MT6351_PMIC_RG_VS1_FNLX_SNS_ADDR MT6351_VS1_ANA_CON7 +#define MT6351_PMIC_RG_VS1_FNLX_SNS_MASK 0x1 +#define MT6351_PMIC_RG_VS1_FNLX_SNS_SHIFT 0 +#define MT6351_PMIC_RG_VS1_VDIFF_ENLOWIQ_ADDR MT6351_VS1_ANA_CON7 +#define MT6351_PMIC_RG_VS1_VDIFF_ENLOWIQ_MASK 0x1 +#define MT6351_PMIC_RG_VS1_VDIFF_ENLOWIQ_SHIFT 1 +#define MT6351_PMIC_RG_VS1_PFMOC_FWUPOFF_ADDR MT6351_VS1_ANA_CON7 +#define MT6351_PMIC_RG_VS1_PFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VS1_PFMOC_FWUPOFF_SHIFT 2 +#define MT6351_PMIC_RG_VS1_PWFMOC_FWUPOFF_ADDR MT6351_VS1_ANA_CON7 +#define MT6351_PMIC_RG_VS1_PWFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VS1_PWFMOC_FWUPOFF_SHIFT 3 +#define MT6351_PMIC_RG_VS1_CP_FWUPOFF_ADDR MT6351_VS1_ANA_CON7 +#define MT6351_PMIC_RG_VS1_CP_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VS1_CP_FWUPOFF_SHIFT 4 +#define MT6351_PMIC_RG_VS1_ZX_GATING_ADDR MT6351_VS1_ANA_CON7 +#define MT6351_PMIC_RG_VS1_ZX_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VS1_ZX_GATING_SHIFT 5 +#define MT6351_PMIC_RG_VS1_RSV_ADDR MT6351_VS1_ANA_CON8 +#define MT6351_PMIC_RG_VS1_RSV_MASK 0xFFFF +#define MT6351_PMIC_RG_VS1_RSV_SHIFT 0 +#define MT6351_PMIC_RG_VS1_AZC_EN_ADDR MT6351_VS1_ANA_CON9 +#define MT6351_PMIC_RG_VS1_AZC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VS1_AZC_EN_SHIFT 0 +#define MT6351_PMIC_RG_VS1_AZC_DELAY_ADDR MT6351_VS1_ANA_CON9 +#define MT6351_PMIC_RG_VS1_AZC_DELAY_MASK 0x3 +#define MT6351_PMIC_RG_VS1_AZC_DELAY_SHIFT 1 +#define MT6351_PMIC_RG_VS1_AZC_HOLD_ENB_ADDR MT6351_VS1_ANA_CON9 +#define MT6351_PMIC_RG_VS1_AZC_HOLD_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VS1_AZC_HOLD_ENB_SHIFT 3 +#define MT6351_PMIC_RGS_QI_VS1_OC_STATUS_ADDR MT6351_VS1_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VS1_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VS1_OC_STATUS_SHIFT 4 +#define MT6351_PMIC_RGS_QI_VS1_DIG_MON_ADDR MT6351_VS1_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VS1_DIG_MON_MASK 0xF +#define MT6351_PMIC_RGS_QI_VS1_DIG_MON_SHIFT 5 +#define MT6351_PMIC_RGS_VS1_ENPWM_STATUS_ADDR MT6351_VS1_ANA_CON9 +#define MT6351_PMIC_RGS_VS1_ENPWM_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_VS1_ENPWM_STATUS_SHIFT 9 +#define MT6351_PMIC_RG_VS2_MODESET_ADDR MT6351_VS2_ANA_CON0 +#define MT6351_PMIC_RG_VS2_MODESET_MASK 0x1 +#define MT6351_PMIC_RG_VS2_MODESET_SHIFT 1 +#define MT6351_PMIC_RG_VS2_NDIS_EN_ADDR MT6351_VS2_ANA_CON0 +#define MT6351_PMIC_RG_VS2_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VS2_NDIS_EN_SHIFT 2 +#define MT6351_PMIC_RG_VS2_VRF18_SSTART_EN_ADDR MT6351_VS2_ANA_CON0 +#define MT6351_PMIC_RG_VS2_VRF18_SSTART_EN_MASK 0x1 +#define MT6351_PMIC_RG_VS2_VRF18_SSTART_EN_SHIFT 3 +#define MT6351_PMIC_RG_VS2_AUTO_MODE_ADDR MT6351_VS2_ANA_CON0 +#define MT6351_PMIC_RG_VS2_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VS2_AUTO_MODE_SHIFT 4 +#define MT6351_PMIC_RG_VS2_RZSEL0_ADDR MT6351_VS2_ANA_CON1 +#define MT6351_PMIC_RG_VS2_RZSEL0_MASK 0x7 +#define MT6351_PMIC_RG_VS2_RZSEL0_SHIFT 0 +#define MT6351_PMIC_RG_VS2_RZSEL1_ADDR MT6351_VS2_ANA_CON1 +#define MT6351_PMIC_RG_VS2_RZSEL1_MASK 0xF +#define MT6351_PMIC_RG_VS2_RZSEL1_SHIFT 3 +#define MT6351_PMIC_RG_VS2_CCSEL0_ADDR MT6351_VS2_ANA_CON1 +#define MT6351_PMIC_RG_VS2_CCSEL0_MASK 0x3 +#define MT6351_PMIC_RG_VS2_CCSEL0_SHIFT 7 +#define MT6351_PMIC_RG_VS2_CCSEL1_ADDR MT6351_VS2_ANA_CON1 +#define MT6351_PMIC_RG_VS2_CCSEL1_MASK 0x3 +#define MT6351_PMIC_RG_VS2_CCSEL1_SHIFT 9 +#define MT6351_PMIC_RG_VS2_CSL_ADDR MT6351_VS2_ANA_CON1 +#define MT6351_PMIC_RG_VS2_CSL_MASK 0xF +#define MT6351_PMIC_RG_VS2_CSL_SHIFT 11 +#define MT6351_PMIC_RG_VS2_SLP_ADDR MT6351_VS2_ANA_CON2 +#define MT6351_PMIC_RG_VS2_SLP_MASK 0x7 +#define MT6351_PMIC_RG_VS2_SLP_SHIFT 0 +#define MT6351_PMIC_RG_VS2_ADRC_FEN_ADDR MT6351_VS2_ANA_CON2 +#define MT6351_PMIC_RG_VS2_ADRC_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VS2_ADRC_FEN_SHIFT 3 +#define MT6351_PMIC_RG_VS2_VCCAP_CLAMP_FEN_ADDR MT6351_VS2_ANA_CON2 +#define MT6351_PMIC_RG_VS2_VCCAP_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VS2_VCCAP_CLAMP_FEN_SHIFT 4 +#define MT6351_PMIC_RG_VS2_VC_CLAMP_FEN_ADDR MT6351_VS2_ANA_CON2 +#define MT6351_PMIC_RG_VS2_VC_CLAMP_FEN_MASK 0x1 +#define MT6351_PMIC_RG_VS2_VC_CLAMP_FEN_SHIFT 5 +#define MT6351_PMIC_RG_VS2_PFMOC_ADDR MT6351_VS2_ANA_CON2 +#define MT6351_PMIC_RG_VS2_PFMOC_MASK 0x7 +#define MT6351_PMIC_RG_VS2_PFMOC_SHIFT 6 +#define MT6351_PMIC_RG_VS2_CSR_ADDR MT6351_VS2_ANA_CON2 +#define MT6351_PMIC_RG_VS2_CSR_MASK 0x7 +#define MT6351_PMIC_RG_VS2_CSR_SHIFT 9 +#define MT6351_PMIC_RG_VS2_ZXOS_TRIM_ADDR MT6351_VS2_ANA_CON3 +#define MT6351_PMIC_RG_VS2_ZXOS_TRIM_MASK 0xFF +#define MT6351_PMIC_RG_VS2_ZXOS_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_VS2_PFMSR_EH_ADDR MT6351_VS2_ANA_CON4 +#define MT6351_PMIC_RG_VS2_PFMSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VS2_PFMSR_EH_SHIFT 0 +#define MT6351_PMIC_RG_VS2_NLIM_GATING_ADDR MT6351_VS2_ANA_CON4 +#define MT6351_PMIC_RG_VS2_NLIM_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VS2_NLIM_GATING_SHIFT 1 +#define MT6351_PMIC_RG_VS2_PWRSR_EH_ADDR MT6351_VS2_ANA_CON4 +#define MT6351_PMIC_RG_VS2_PWRSR_EH_MASK 0x1 +#define MT6351_PMIC_RG_VS2_PWRSR_EH_SHIFT 2 +#define MT6351_PMIC_RG_VS2_HS_VTHDET_ADDR MT6351_VS2_ANA_CON4 +#define MT6351_PMIC_RG_VS2_HS_VTHDET_MASK 0x1 +#define MT6351_PMIC_RG_VS2_HS_VTHDET_SHIFT 3 +#define MT6351_PMIC_RG_VS2_PG_GATING_ADDR MT6351_VS2_ANA_CON4 +#define MT6351_PMIC_RG_VS2_PG_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VS2_PG_GATING_SHIFT 4 +#define MT6351_PMIC_RG_VS2_HS_ONSPEED_EH_ADDR MT6351_VS2_ANA_CON4 +#define MT6351_PMIC_RG_VS2_HS_ONSPEED_EH_MASK 0x1 +#define MT6351_PMIC_RG_VS2_HS_ONSPEED_EH_SHIFT 5 +#define MT6351_PMIC_RG_VS2_NLIM_TRIMMING_ADDR MT6351_VS2_ANA_CON4 +#define MT6351_PMIC_RG_VS2_NLIM_TRIMMING_MASK 0xF +#define MT6351_PMIC_RG_VS2_NLIM_TRIMMING_SHIFT 6 +#define MT6351_PMIC_RG_VS2_DLC_ADDR MT6351_VS2_ANA_CON5 +#define MT6351_PMIC_RG_VS2_DLC_MASK 0x3 +#define MT6351_PMIC_RG_VS2_DLC_SHIFT 0 +#define MT6351_PMIC_RG_VS2_DLC_N_ADDR MT6351_VS2_ANA_CON5 +#define MT6351_PMIC_RG_VS2_DLC_N_MASK 0x3 +#define MT6351_PMIC_RG_VS2_DLC_N_SHIFT 2 +#define MT6351_PMIC_RG_VS2_PFM_RIP_ADDR MT6351_VS2_ANA_CON5 +#define MT6351_PMIC_RG_VS2_PFM_RIP_MASK 0x7 +#define MT6351_PMIC_RG_VS2_PFM_RIP_SHIFT 4 +#define MT6351_PMIC_RG_VS2_TRAN_BST_ADDR MT6351_VS2_ANA_CON5 +#define MT6351_PMIC_RG_VS2_TRAN_BST_MASK 0x3F +#define MT6351_PMIC_RG_VS2_TRAN_BST_SHIFT 7 +#define MT6351_PMIC_RG_VS2_DTS_ENB_ADDR MT6351_VS2_ANA_CON5 +#define MT6351_PMIC_RG_VS2_DTS_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VS2_DTS_ENB_SHIFT 13 +#define MT6351_PMIC_RG_VS2_MIN_OFF_ADDR MT6351_VS2_ANA_CON5 +#define MT6351_PMIC_RG_VS2_MIN_OFF_MASK 0x3 +#define MT6351_PMIC_RG_VS2_MIN_OFF_SHIFT 14 +#define MT6351_PMIC_RG_VS2_1P35UP_SEL_EN_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_1P35UP_SEL_EN_MASK 0x1 +#define MT6351_PMIC_RG_VS2_1P35UP_SEL_EN_SHIFT 0 +#define MT6351_PMIC_RG_VS2_DLC_AUTO_MODE_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_DLC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VS2_DLC_AUTO_MODE_SHIFT 1 +#define MT6351_PMIC_RG_VS2_DLC_SEL_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_DLC_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VS2_DLC_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VS2_SRC_AUTO_MODE_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_SRC_AUTO_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VS2_SRC_AUTO_MODE_SHIFT 5 +#define MT6351_PMIC_RG_VS2_UGP_SR_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_UGP_SR_MASK 0x3 +#define MT6351_PMIC_RG_VS2_UGP_SR_SHIFT 6 +#define MT6351_PMIC_RG_VS2_LGN_SR_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_LGN_SR_MASK 0x3 +#define MT6351_PMIC_RG_VS2_LGN_SR_SHIFT 8 +#define MT6351_PMIC_RG_VS2_UGP_SR_PFM_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_UGP_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VS2_UGP_SR_PFM_SHIFT 10 +#define MT6351_PMIC_RG_VS2_LGN_SR_PFM_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_LGN_SR_PFM_MASK 0x3 +#define MT6351_PMIC_RG_VS2_LGN_SR_PFM_SHIFT 12 +#define MT6351_PMIC_RG_VS2_UGD_VTHSEL_ADDR MT6351_VS2_ANA_CON6 +#define MT6351_PMIC_RG_VS2_UGD_VTHSEL_MASK 0x3 +#define MT6351_PMIC_RG_VS2_UGD_VTHSEL_SHIFT 14 +#define MT6351_PMIC_RG_VS2_FNLX_SNS_ADDR MT6351_VS2_ANA_CON7 +#define MT6351_PMIC_RG_VS2_FNLX_SNS_MASK 0x1 +#define MT6351_PMIC_RG_VS2_FNLX_SNS_SHIFT 0 +#define MT6351_PMIC_RG_VS2_VDIFF_ENLOWIQ_ADDR MT6351_VS2_ANA_CON7 +#define MT6351_PMIC_RG_VS2_VDIFF_ENLOWIQ_MASK 0x1 +#define MT6351_PMIC_RG_VS2_VDIFF_ENLOWIQ_SHIFT 1 +#define MT6351_PMIC_RG_VS2_PFMOC_FWUPOFF_ADDR MT6351_VS2_ANA_CON7 +#define MT6351_PMIC_RG_VS2_PFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VS2_PFMOC_FWUPOFF_SHIFT 2 +#define MT6351_PMIC_RG_VS2_PWFMOC_FWUPOFF_ADDR MT6351_VS2_ANA_CON7 +#define MT6351_PMIC_RG_VS2_PWFMOC_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VS2_PWFMOC_FWUPOFF_SHIFT 3 +#define MT6351_PMIC_RG_VS2_CP_FWUPOFF_ADDR MT6351_VS2_ANA_CON7 +#define MT6351_PMIC_RG_VS2_CP_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VS2_CP_FWUPOFF_SHIFT 4 +#define MT6351_PMIC_RG_VS2_ZX_GATING_ADDR MT6351_VS2_ANA_CON7 +#define MT6351_PMIC_RG_VS2_ZX_GATING_MASK 0x1 +#define MT6351_PMIC_RG_VS2_ZX_GATING_SHIFT 5 +#define MT6351_PMIC_RG_VS2_RSV_ADDR MT6351_VS2_ANA_CON8 +#define MT6351_PMIC_RG_VS2_RSV_MASK 0xFFFF +#define MT6351_PMIC_RG_VS2_RSV_SHIFT 0 +#define MT6351_PMIC_RG_VS2_AZC_EN_ADDR MT6351_VS2_ANA_CON9 +#define MT6351_PMIC_RG_VS2_AZC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VS2_AZC_EN_SHIFT 0 +#define MT6351_PMIC_RG_VS2_AZC_DELAY_ADDR MT6351_VS2_ANA_CON9 +#define MT6351_PMIC_RG_VS2_AZC_DELAY_MASK 0x3 +#define MT6351_PMIC_RG_VS2_AZC_DELAY_SHIFT 1 +#define MT6351_PMIC_RG_VS2_AZC_HOLD_ENB_ADDR MT6351_VS2_ANA_CON9 +#define MT6351_PMIC_RG_VS2_AZC_HOLD_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VS2_AZC_HOLD_ENB_SHIFT 3 +#define MT6351_PMIC_RGS_QI_VS2_OC_STATUS_ADDR MT6351_VS2_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VS2_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VS2_OC_STATUS_SHIFT 4 +#define MT6351_PMIC_RGS_QI_VS2_DIG_MON_ADDR MT6351_VS2_ANA_CON9 +#define MT6351_PMIC_RGS_QI_VS2_DIG_MON_MASK 0xF +#define MT6351_PMIC_RGS_QI_VS2_DIG_MON_SHIFT 5 +#define MT6351_PMIC_RGS_VS2_ENPWM_STATUS_ADDR MT6351_VS2_ANA_CON9 +#define MT6351_PMIC_RGS_VS2_ENPWM_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_VS2_ENPWM_STATUS_SHIFT 9 +#define MT6351_PMIC_RG_VPA_NDIS_EN_ADDR MT6351_VPA_ANA_CON0 +#define MT6351_PMIC_RG_VPA_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VPA_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VPA_MODESET_ADDR MT6351_VPA_ANA_CON0 +#define MT6351_PMIC_RG_VPA_MODESET_MASK 0x1 +#define MT6351_PMIC_RG_VPA_MODESET_SHIFT 3 +#define MT6351_PMIC_RG_VPA_CC_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_CC_MASK 0x3 +#define MT6351_PMIC_RG_VPA_CC_SHIFT 0 +#define MT6351_PMIC_RG_VPA_CSR_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_CSR_MASK 0x3 +#define MT6351_PMIC_RG_VPA_CSR_SHIFT 2 +#define MT6351_PMIC_RG_VPA_CSMIR_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_CSMIR_MASK 0x3 +#define MT6351_PMIC_RG_VPA_CSMIR_SHIFT 4 +#define MT6351_PMIC_RG_VPA_CSL_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_CSL_MASK 0x3 +#define MT6351_PMIC_RG_VPA_CSL_SHIFT 6 +#define MT6351_PMIC_RG_VPA_SLP_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_SLP_MASK 0x3 +#define MT6351_PMIC_RG_VPA_SLP_SHIFT 8 +#define MT6351_PMIC_RG_VPA_AZC_EN_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_AZC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VPA_AZC_EN_SHIFT 10 +#define MT6351_PMIC_RG_VPA_CP_FWUPOFF_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_CP_FWUPOFF_MASK 0x1 +#define MT6351_PMIC_RG_VPA_CP_FWUPOFF_SHIFT 11 +#define MT6351_PMIC_RG_VPA_AZC_DELAY_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_AZC_DELAY_MASK 0x3 +#define MT6351_PMIC_RG_VPA_AZC_DELAY_SHIFT 12 +#define MT6351_PMIC_RG_VPA_RZSEL_ADDR MT6351_VPA_ANA_CON1 +#define MT6351_PMIC_RG_VPA_RZSEL_MASK 0x3 +#define MT6351_PMIC_RG_VPA_RZSEL_SHIFT 14 +#define MT6351_PMIC_RG_VPA_ZXREF_ADDR MT6351_VPA_ANA_CON2 +#define MT6351_PMIC_RG_VPA_ZXREF_MASK 0xFF +#define MT6351_PMIC_RG_VPA_ZXREF_SHIFT 0 +#define MT6351_PMIC_RG_VPA_NLIM_SEL_ADDR MT6351_VPA_ANA_CON2 +#define MT6351_PMIC_RG_VPA_NLIM_SEL_MASK 0xF +#define MT6351_PMIC_RG_VPA_NLIM_SEL_SHIFT 8 +#define MT6351_PMIC_RG_VPA_HZP_ADDR MT6351_VPA_ANA_CON2 +#define MT6351_PMIC_RG_VPA_HZP_MASK 0x1 +#define MT6351_PMIC_RG_VPA_HZP_SHIFT 12 +#define MT6351_PMIC_RG_VPA_BWEX_GAT_ADDR MT6351_VPA_ANA_CON2 +#define MT6351_PMIC_RG_VPA_BWEX_GAT_MASK 0x1 +#define MT6351_PMIC_RG_VPA_BWEX_GAT_SHIFT 13 +#define MT6351_PMIC_RG_VPA_SLEW_ADDR MT6351_VPA_ANA_CON2 +#define MT6351_PMIC_RG_VPA_SLEW_MASK 0x3 +#define MT6351_PMIC_RG_VPA_SLEW_SHIFT 14 +#define MT6351_PMIC_RG_VPA_SLEW_NMOS_ADDR MT6351_VPA_ANA_CON3 +#define MT6351_PMIC_RG_VPA_SLEW_NMOS_MASK 0x3 +#define MT6351_PMIC_RG_VPA_SLEW_NMOS_SHIFT 0 +#define MT6351_PMIC_RG_VPA_MIN_ON_ADDR MT6351_VPA_ANA_CON3 +#define MT6351_PMIC_RG_VPA_MIN_ON_MASK 0x3 +#define MT6351_PMIC_RG_VPA_MIN_ON_SHIFT 2 +#define MT6351_PMIC_RG_VPA_VBAT_DEL_ADDR MT6351_VPA_ANA_CON3 +#define MT6351_PMIC_RG_VPA_VBAT_DEL_MASK 0x3 +#define MT6351_PMIC_RG_VPA_VBAT_DEL_SHIFT 4 +#define MT6351_PMIC_RGS_VPA_AZC_VOS_SEL_ADDR MT6351_VPA_ANA_CON3 +#define MT6351_PMIC_RGS_VPA_AZC_VOS_SEL_MASK 0xFF +#define MT6351_PMIC_RGS_VPA_AZC_VOS_SEL_SHIFT 6 +#define MT6351_PMIC_RG_VPA_MIN_PK_ADDR MT6351_VPA_ANA_CON3 +#define MT6351_PMIC_RG_VPA_MIN_PK_MASK 0x3 +#define MT6351_PMIC_RG_VPA_MIN_PK_SHIFT 14 +#define MT6351_PMIC_RG_VPA_RSV1_ADDR MT6351_VPA_ANA_CON4 +#define MT6351_PMIC_RG_VPA_RSV1_MASK 0xFF +#define MT6351_PMIC_RG_VPA_RSV1_SHIFT 0 +#define MT6351_PMIC_RG_VPA_RSV2_ADDR MT6351_VPA_ANA_CON4 +#define MT6351_PMIC_RG_VPA_RSV2_MASK 0xFF +#define MT6351_PMIC_RG_VPA_RSV2_SHIFT 8 +#define MT6351_PMIC_RGS_QI_VPA_OC_STATUS_ADDR MT6351_VPA_ANA_CON5 +#define MT6351_PMIC_RGS_QI_VPA_OC_STATUS_MASK 0x1 +#define MT6351_PMIC_RGS_QI_VPA_OC_STATUS_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_EN_CTRL_ADDR MT6351_BUCK_VCORE_CON0 +#define MT6351_PMIC_BUCK_VCORE_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_CTRL_ADDR MT6351_BUCK_VCORE_CON0 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VCORE_EN_SEL_ADDR MT6351_BUCK_VCORE_CON1 +#define MT6351_PMIC_BUCK_VCORE_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VCORE_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_SEL_ADDR MT6351_BUCK_VCORE_CON1 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VCORE_EN_ADDR MT6351_BUCK_VCORE_CON2 +#define MT6351_PMIC_BUCK_VCORE_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_STBTD_ADDR MT6351_BUCK_VCORE_CON2 +#define MT6351_PMIC_BUCK_VCORE_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VCORE_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VCORE_STB_ADDR MT6351_BUCK_VCORE_CON2 +#define MT6351_PMIC_DA_VCORE_STB_MASK 0x1 +#define MT6351_PMIC_DA_VCORE_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VCORE_EN_ADDR MT6351_BUCK_VCORE_CON2 +#define MT6351_PMIC_DA_QI_VCORE_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCORE_EN_SHIFT 13 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_FRATE_ADDR MT6351_BUCK_VCORE_CON3 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VCORE_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_FEN_ADDR MT6351_BUCK_VCORE_CON3 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_RRATE_ADDR MT6351_BUCK_VCORE_CON3 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VCORE_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_REN_ADDR MT6351_BUCK_VCORE_CON3 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_ADDR MT6351_BUCK_VCORE_CON4 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_MASK 0x7F +#define MT6351_PMIC_BUCK_VCORE_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_ON_ADDR MT6351_BUCK_VCORE_CON5 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_ON_MASK 0x7F +#define MT6351_PMIC_BUCK_VCORE_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_SLEEP_ADDR MT6351_BUCK_VCORE_CON6 +#define MT6351_PMIC_BUCK_VCORE_VOSEL_SLEEP_MASK 0x7F +#define MT6351_PMIC_BUCK_VCORE_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VCORE_VOSEL_ADDR MT6351_BUCK_VCORE_CON7 +#define MT6351_PMIC_DA_NI_VCORE_VOSEL_MASK 0x7F +#define MT6351_PMIC_DA_NI_VCORE_VOSEL_SHIFT 0 +#define MT6351_PMIC_DA_NI_VCORE_VOSEL_SYNC_ADDR MT6351_BUCK_VCORE_CON8 +#define MT6351_PMIC_DA_NI_VCORE_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VCORE_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_TRANS_TD_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_BUCK_VCORE_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VCORE_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VCORE_TRANS_CTRL_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_BUCK_VCORE_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VCORE_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VCORE_TRANS_ONCE_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_BUCK_VCORE_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VCORE_DVS_EN_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_DA_QI_VCORE_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCORE_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VCORE_R2R_PDN_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_BUCK_VCORE_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VCORE_VSLEEP_SEL_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_BUCK_VCORE_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VCORE_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VCORE_R2R_PDN_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_DA_NI_VCORE_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VCORE_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VCORE_VSLEEP_SEL_ADDR MT6351_BUCK_VCORE_CON9 +#define MT6351_PMIC_DA_NI_VCORE_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VCORE_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_VGPU_EN_CTRL_ADDR MT6351_BUCK_VGPU_CON0 +#define MT6351_PMIC_BUCK_VGPU_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_ADDR MT6351_BUCK_VGPU_CON0 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VGPU_EN_SEL_ADDR MT6351_BUCK_VGPU_CON1 +#define MT6351_PMIC_BUCK_VGPU_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VGPU_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_SEL_ADDR MT6351_BUCK_VGPU_CON1 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VGPU_EN_ADDR MT6351_BUCK_VGPU_CON2 +#define MT6351_PMIC_BUCK_VGPU_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_STBTD_ADDR MT6351_BUCK_VGPU_CON2 +#define MT6351_PMIC_BUCK_VGPU_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VGPU_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VGPU_STB_ADDR MT6351_BUCK_VGPU_CON2 +#define MT6351_PMIC_DA_VGPU_STB_MASK 0x1 +#define MT6351_PMIC_DA_VGPU_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VGPU_EN_ADDR MT6351_BUCK_VGPU_CON2 +#define MT6351_PMIC_DA_QI_VGPU_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VGPU_EN_SHIFT 13 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_FRATE_ADDR MT6351_BUCK_VGPU_CON3 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VGPU_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_FEN_ADDR MT6351_BUCK_VGPU_CON3 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_RRATE_ADDR MT6351_BUCK_VGPU_CON3 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VGPU_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_REN_ADDR MT6351_BUCK_VGPU_CON3 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_ADDR MT6351_BUCK_VGPU_CON4 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_MASK 0x7F +#define MT6351_PMIC_BUCK_VGPU_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_ON_ADDR MT6351_BUCK_VGPU_CON5 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_ON_MASK 0x7F +#define MT6351_PMIC_BUCK_VGPU_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_SLEEP_ADDR MT6351_BUCK_VGPU_CON6 +#define MT6351_PMIC_BUCK_VGPU_VOSEL_SLEEP_MASK 0x7F +#define MT6351_PMIC_BUCK_VGPU_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VGPU_VOSEL_ADDR MT6351_BUCK_VGPU_CON7 +#define MT6351_PMIC_DA_NI_VGPU_VOSEL_MASK 0x7F +#define MT6351_PMIC_DA_NI_VGPU_VOSEL_SHIFT 0 +#define MT6351_PMIC_DA_NI_VGPU_VOSEL_SYNC_ADDR MT6351_BUCK_VGPU_CON8 +#define MT6351_PMIC_DA_NI_VGPU_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VGPU_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_TRANS_TD_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_BUCK_VGPU_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VGPU_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VGPU_TRANS_CTRL_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_BUCK_VGPU_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VGPU_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VGPU_TRANS_ONCE_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_BUCK_VGPU_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VGPU_DVS_EN_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_DA_QI_VGPU_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VGPU_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VGPU_R2R_PDN_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_BUCK_VGPU_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VGPU_VSLEEP_SEL_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_BUCK_VGPU_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VGPU_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VGPU_R2R_PDN_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_DA_NI_VGPU_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VGPU_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VGPU_VSLEEP_SEL_ADDR MT6351_BUCK_VGPU_CON9 +#define MT6351_PMIC_DA_NI_VGPU_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VGPU_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_VMODEM_EN_CTRL_ADDR MT6351_BUCK_VMODEM_CON0 +#define MT6351_PMIC_BUCK_VMODEM_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL_ADDR MT6351_BUCK_VMODEM_CON0 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VMODEM_EN_SEL_ADDR MT6351_BUCK_VMODEM_CON1 +#define MT6351_PMIC_BUCK_VMODEM_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VMODEM_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_SEL_ADDR MT6351_BUCK_VMODEM_CON1 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VMODEM_EN_ADDR MT6351_BUCK_VMODEM_CON2 +#define MT6351_PMIC_BUCK_VMODEM_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VMODEM_STBTD_ADDR MT6351_BUCK_VMODEM_CON2 +#define MT6351_PMIC_BUCK_VMODEM_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VMODEM_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VMODEM_STB_ADDR MT6351_BUCK_VMODEM_CON2 +#define MT6351_PMIC_DA_VMODEM_STB_MASK 0x1 +#define MT6351_PMIC_DA_VMODEM_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VMODEM_EN_ADDR MT6351_BUCK_VMODEM_CON2 +#define MT6351_PMIC_DA_QI_VMODEM_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMODEM_EN_SHIFT 13 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_FRATE_ADDR MT6351_BUCK_VMODEM_CON3 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_FEN_ADDR MT6351_BUCK_VMODEM_CON3 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_RRATE_ADDR MT6351_BUCK_VMODEM_CON3 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_REN_ADDR MT6351_BUCK_VMODEM_CON3 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_ADDR MT6351_BUCK_VMODEM_CON4 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_MASK 0x7F +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_ON_ADDR MT6351_BUCK_VMODEM_CON5 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_ON_MASK 0x7F +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_SLEEP_ADDR MT6351_BUCK_VMODEM_CON6 +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_SLEEP_MASK 0x7F +#define MT6351_PMIC_BUCK_VMODEM_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VMODEM_VOSEL_ADDR MT6351_BUCK_VMODEM_CON7 +#define MT6351_PMIC_DA_NI_VMODEM_VOSEL_MASK 0x7F +#define MT6351_PMIC_DA_NI_VMODEM_VOSEL_SHIFT 0 +#define MT6351_PMIC_DA_NI_VMODEM_VOSEL_SYNC_ADDR MT6351_BUCK_VMODEM_CON8 +#define MT6351_PMIC_DA_NI_VMODEM_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VMODEM_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_TD_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_CTRL_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_ONCE_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VMODEM_DVS_EN_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_DA_QI_VMODEM_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMODEM_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VMODEM_R2R_PDN_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_BUCK_VMODEM_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VMODEM_VSLEEP_SEL_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_BUCK_VMODEM_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMODEM_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VMODEM_R2R_PDN_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_DA_NI_VMODEM_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VMODEM_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VMODEM_VSLEEP_SEL_ADDR MT6351_BUCK_VMODEM_CON9 +#define MT6351_PMIC_DA_NI_VMODEM_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VMODEM_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_VMD1_EN_CTRL_ADDR MT6351_BUCK_VMD1_CON0 +#define MT6351_PMIC_BUCK_VMD1_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL_ADDR MT6351_BUCK_VMD1_CON0 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VMD1_EN_SEL_ADDR MT6351_BUCK_VMD1_CON1 +#define MT6351_PMIC_BUCK_VMD1_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VMD1_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_SEL_ADDR MT6351_BUCK_VMD1_CON1 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VMD1_EN_ADDR MT6351_BUCK_VMD1_CON2 +#define MT6351_PMIC_BUCK_VMD1_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VMD1_STBTD_ADDR MT6351_BUCK_VMD1_CON2 +#define MT6351_PMIC_BUCK_VMD1_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VMD1_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VMD1_STB_ADDR MT6351_BUCK_VMD1_CON2 +#define MT6351_PMIC_DA_VMD1_STB_MASK 0x1 +#define MT6351_PMIC_DA_VMD1_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VMD1_EN_ADDR MT6351_BUCK_VMD1_CON2 +#define MT6351_PMIC_DA_QI_VMD1_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMD1_EN_SHIFT 13 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_FRATE_ADDR MT6351_BUCK_VMD1_CON3 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VMD1_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_FEN_ADDR MT6351_BUCK_VMD1_CON3 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_RRATE_ADDR MT6351_BUCK_VMD1_CON3 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VMD1_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_REN_ADDR MT6351_BUCK_VMD1_CON3 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_ADDR MT6351_BUCK_VMD1_CON4 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_MASK 0x7F +#define MT6351_PMIC_BUCK_VMD1_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_ON_ADDR MT6351_BUCK_VMD1_CON5 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_ON_MASK 0x7F +#define MT6351_PMIC_BUCK_VMD1_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_SLEEP_ADDR MT6351_BUCK_VMD1_CON6 +#define MT6351_PMIC_BUCK_VMD1_VOSEL_SLEEP_MASK 0x7F +#define MT6351_PMIC_BUCK_VMD1_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VMD1_VOSEL_ADDR MT6351_BUCK_VMD1_CON7 +#define MT6351_PMIC_DA_NI_VMD1_VOSEL_MASK 0x7F +#define MT6351_PMIC_DA_NI_VMD1_VOSEL_SHIFT 0 +#define MT6351_PMIC_DA_NI_VMD1_VOSEL_SYNC_ADDR MT6351_BUCK_VMD1_CON8 +#define MT6351_PMIC_DA_NI_VMD1_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VMD1_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VMD1_TRANS_TD_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_BUCK_VMD1_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VMD1_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VMD1_TRANS_CTRL_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_BUCK_VMD1_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VMD1_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VMD1_TRANS_ONCE_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_BUCK_VMD1_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VMD1_DVS_EN_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_DA_QI_VMD1_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMD1_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VMD1_R2R_PDN_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_BUCK_VMD1_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VMD1_VSLEEP_SEL_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_BUCK_VMD1_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VMD1_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VMD1_R2R_PDN_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_DA_NI_VMD1_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VMD1_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VMD1_VSLEEP_SEL_ADDR MT6351_BUCK_VMD1_CON9 +#define MT6351_PMIC_DA_NI_VMD1_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VMD1_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_CTRL_ADDR MT6351_BUCK_VSRAM_MD_CON0 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL_ADDR MT6351_BUCK_VSRAM_MD_CON0 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_SEL_ADDR MT6351_BUCK_VSRAM_MD_CON1 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SEL_ADDR MT6351_BUCK_VSRAM_MD_CON1 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_ADDR MT6351_BUCK_VSRAM_MD_CON2 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_STBTD_ADDR MT6351_BUCK_VSRAM_MD_CON2 +#define MT6351_PMIC_BUCK_VSRAM_MD_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VSRAM_MD_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VSRAM_MD_STB_ADDR MT6351_BUCK_VSRAM_MD_CON2 +#define MT6351_PMIC_DA_VSRAM_MD_STB_MASK 0x1 +#define MT6351_PMIC_DA_VSRAM_MD_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VSRAM_MD_EN_ADDR MT6351_BUCK_VSRAM_MD_CON2 +#define MT6351_PMIC_DA_QI_VSRAM_MD_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSRAM_MD_EN_SHIFT 13 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FRATE_ADDR MT6351_BUCK_VSRAM_MD_CON3 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FEN_ADDR MT6351_BUCK_VSRAM_MD_CON3 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_RRATE_ADDR MT6351_BUCK_VSRAM_MD_CON3 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_REN_ADDR MT6351_BUCK_VSRAM_MD_CON3 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ADDR MT6351_BUCK_VSRAM_MD_CON4 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON_ADDR MT6351_BUCK_VSRAM_MD_CON5 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP_ADDR MT6351_BUCK_VSRAM_MD_CON6 +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_ADDR MT6351_BUCK_VSRAM_MD_CON7 +#define MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_MASK 0x7F +#define MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SHIFT 0 +#define MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC_ADDR MT6351_BUCK_VSRAM_MD_CON8 +#define MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_TD_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_CTRL_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_ONCE_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VSRAM_MD_DVS_EN_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_DA_QI_VSRAM_MD_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSRAM_MD_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VSRAM_MD_R2R_PDN_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_BUCK_VSRAM_MD_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_SEL_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VSRAM_MD_R2R_PDN_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_DA_NI_VSRAM_MD_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VSRAM_MD_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL_ADDR MT6351_BUCK_VSRAM_MD_CON9 +#define MT6351_PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_VS1_EN_CTRL_ADDR MT6351_BUCK_VS1_CON0 +#define MT6351_PMIC_BUCK_VS1_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VS1_VOSEL_CTRL_ADDR MT6351_BUCK_VS1_CON0 +#define MT6351_PMIC_BUCK_VS1_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VS1_EN_SEL_ADDR MT6351_BUCK_VS1_CON1 +#define MT6351_PMIC_BUCK_VS1_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VS1_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VS1_VOSEL_SEL_ADDR MT6351_BUCK_VS1_CON1 +#define MT6351_PMIC_BUCK_VS1_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VS1_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VS1_EN_ADDR MT6351_BUCK_VS1_CON2 +#define MT6351_PMIC_BUCK_VS1_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VS1_STBTD_ADDR MT6351_BUCK_VS1_CON2 +#define MT6351_PMIC_BUCK_VS1_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VS1_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VS1_STB_ADDR MT6351_BUCK_VS1_CON2 +#define MT6351_PMIC_DA_VS1_STB_MASK 0x1 +#define MT6351_PMIC_DA_VS1_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VS1_EN_ADDR MT6351_BUCK_VS1_CON2 +#define MT6351_PMIC_DA_QI_VS1_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VS1_EN_SHIFT 13 +#define MT6351_PMIC_BUCK_VS1_SFCHG_FRATE_ADDR MT6351_BUCK_VS1_CON3 +#define MT6351_PMIC_BUCK_VS1_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VS1_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VS1_SFCHG_FEN_ADDR MT6351_BUCK_VS1_CON3 +#define MT6351_PMIC_BUCK_VS1_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VS1_SFCHG_RRATE_ADDR MT6351_BUCK_VS1_CON3 +#define MT6351_PMIC_BUCK_VS1_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VS1_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VS1_SFCHG_REN_ADDR MT6351_BUCK_VS1_CON3 +#define MT6351_PMIC_BUCK_VS1_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VS1_VOSEL_ADDR MT6351_BUCK_VS1_CON4 +#define MT6351_PMIC_BUCK_VS1_VOSEL_MASK 0x7F +#define MT6351_PMIC_BUCK_VS1_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VS1_VOSEL_ON_ADDR MT6351_BUCK_VS1_CON5 +#define MT6351_PMIC_BUCK_VS1_VOSEL_ON_MASK 0x7F +#define MT6351_PMIC_BUCK_VS1_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VS1_VOSEL_SLEEP_ADDR MT6351_BUCK_VS1_CON6 +#define MT6351_PMIC_BUCK_VS1_VOSEL_SLEEP_MASK 0x7F +#define MT6351_PMIC_BUCK_VS1_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VS1_VOSEL_ADDR MT6351_BUCK_VS1_CON7 +#define MT6351_PMIC_DA_NI_VS1_VOSEL_MASK 0x7F +#define MT6351_PMIC_DA_NI_VS1_VOSEL_SHIFT 0 +#define MT6351_PMIC_DA_NI_VS1_VOSEL_SYNC_ADDR MT6351_BUCK_VS1_CON8 +#define MT6351_PMIC_DA_NI_VS1_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VS1_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VS1_TRANS_TD_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_BUCK_VS1_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VS1_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VS1_TRANS_CTRL_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_BUCK_VS1_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VS1_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VS1_TRANS_ONCE_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_BUCK_VS1_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VS1_DVS_EN_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_DA_QI_VS1_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VS1_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VS1_VSLEEP_EN_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_BUCK_VS1_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VS1_R2R_PDN_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_BUCK_VS1_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VS1_VSLEEP_SEL_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_BUCK_VS1_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS1_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VS1_R2R_PDN_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_DA_NI_VS1_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VS1_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VS1_VSLEEP_SEL_ADDR MT6351_BUCK_VS1_CON9 +#define MT6351_PMIC_DA_NI_VS1_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VS1_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_VS2_EN_CTRL_ADDR MT6351_BUCK_VS2_CON0 +#define MT6351_PMIC_BUCK_VS2_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_VOSEL_CTRL_ADDR MT6351_BUCK_VS2_CON0 +#define MT6351_PMIC_BUCK_VS2_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VS2_EN_SEL_ADDR MT6351_BUCK_VS2_CON1 +#define MT6351_PMIC_BUCK_VS2_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VS2_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_VOSEL_SEL_ADDR MT6351_BUCK_VS2_CON1 +#define MT6351_PMIC_BUCK_VS2_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VS2_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VS2_EN_ADDR MT6351_BUCK_VS2_CON2 +#define MT6351_PMIC_BUCK_VS2_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_STBTD_ADDR MT6351_BUCK_VS2_CON2 +#define MT6351_PMIC_BUCK_VS2_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VS2_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VS2_STB_ADDR MT6351_BUCK_VS2_CON2 +#define MT6351_PMIC_DA_VS2_STB_MASK 0x1 +#define MT6351_PMIC_DA_VS2_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VS2_EN_ADDR MT6351_BUCK_VS2_CON2 +#define MT6351_PMIC_DA_QI_VS2_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VS2_EN_SHIFT 13 +#define MT6351_PMIC_BUCK_VS2_SFCHG_FRATE_ADDR MT6351_BUCK_VS2_CON3 +#define MT6351_PMIC_BUCK_VS2_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VS2_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_SFCHG_FEN_ADDR MT6351_BUCK_VS2_CON3 +#define MT6351_PMIC_BUCK_VS2_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VS2_SFCHG_RRATE_ADDR MT6351_BUCK_VS2_CON3 +#define MT6351_PMIC_BUCK_VS2_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VS2_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VS2_SFCHG_REN_ADDR MT6351_BUCK_VS2_CON3 +#define MT6351_PMIC_BUCK_VS2_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VS2_VOSEL_ADDR MT6351_BUCK_VS2_CON4 +#define MT6351_PMIC_BUCK_VS2_VOSEL_MASK 0x7F +#define MT6351_PMIC_BUCK_VS2_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_VOSEL_ON_ADDR MT6351_BUCK_VS2_CON5 +#define MT6351_PMIC_BUCK_VS2_VOSEL_ON_MASK 0x7F +#define MT6351_PMIC_BUCK_VS2_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_VOSEL_SLEEP_ADDR MT6351_BUCK_VS2_CON6 +#define MT6351_PMIC_BUCK_VS2_VOSEL_SLEEP_MASK 0x7F +#define MT6351_PMIC_BUCK_VS2_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VS2_VOSEL_ADDR MT6351_BUCK_VS2_CON7 +#define MT6351_PMIC_DA_NI_VS2_VOSEL_MASK 0x7F +#define MT6351_PMIC_DA_NI_VS2_VOSEL_SHIFT 0 +#define MT6351_PMIC_DA_NI_VS2_VOSEL_SYNC_ADDR MT6351_BUCK_VS2_CON8 +#define MT6351_PMIC_DA_NI_VS2_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VS2_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_TRANS_TD_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_BUCK_VS2_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VS2_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VS2_TRANS_CTRL_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_BUCK_VS2_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VS2_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VS2_TRANS_ONCE_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_BUCK_VS2_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VS2_DVS_EN_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_DA_QI_VS2_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VS2_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VS2_VSLEEP_EN_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_BUCK_VS2_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VS2_R2R_PDN_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_BUCK_VS2_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VS2_VSLEEP_SEL_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_BUCK_VS2_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VS2_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VS2_R2R_PDN_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_DA_NI_VS2_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VS2_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VS2_VSLEEP_SEL_ADDR MT6351_BUCK_VS2_CON9 +#define MT6351_PMIC_DA_NI_VS2_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VS2_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_VPA_EN_CTRL_ADDR MT6351_BUCK_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_CTRL_ADDR MT6351_BUCK_VPA_CON0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VPA_EN_SEL_ADDR MT6351_BUCK_VPA_CON1 +#define MT6351_PMIC_BUCK_VPA_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VPA_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_SEL_ADDR MT6351_BUCK_VPA_CON1 +#define MT6351_PMIC_BUCK_VPA_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VPA_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VPA_EN_ADDR MT6351_BUCK_VPA_CON2 +#define MT6351_PMIC_BUCK_VPA_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_STBTD_ADDR MT6351_BUCK_VPA_CON2 +#define MT6351_PMIC_BUCK_VPA_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VPA_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VPA_STB_ADDR MT6351_BUCK_VPA_CON2 +#define MT6351_PMIC_DA_VPA_STB_MASK 0x1 +#define MT6351_PMIC_DA_VPA_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VPA_EN_ADDR MT6351_BUCK_VPA_CON2 +#define MT6351_PMIC_DA_QI_VPA_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VPA_EN_SHIFT 13 +#define MT6351_PMIC_BUCK_VPA_SFCHG_FRATE_ADDR MT6351_BUCK_VPA_CON3 +#define MT6351_PMIC_BUCK_VPA_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VPA_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_SFCHG_FEN_ADDR MT6351_BUCK_VPA_CON3 +#define MT6351_PMIC_BUCK_VPA_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VPA_SFCHG_RRATE_ADDR MT6351_BUCK_VPA_CON3 +#define MT6351_PMIC_BUCK_VPA_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VPA_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VPA_SFCHG_REN_ADDR MT6351_BUCK_VPA_CON3 +#define MT6351_PMIC_BUCK_VPA_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VPA_VOSEL_ADDR MT6351_BUCK_VPA_CON4 +#define MT6351_PMIC_BUCK_VPA_VOSEL_MASK 0x3F +#define MT6351_PMIC_BUCK_VPA_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_ON_ADDR MT6351_BUCK_VPA_CON5 +#define MT6351_PMIC_BUCK_VPA_VOSEL_ON_MASK 0x3F +#define MT6351_PMIC_BUCK_VPA_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_VOSEL_SLEEP_ADDR MT6351_BUCK_VPA_CON6 +#define MT6351_PMIC_BUCK_VPA_VOSEL_SLEEP_MASK 0x3F +#define MT6351_PMIC_BUCK_VPA_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VPA_VOSEL_GRAY_ADDR MT6351_BUCK_VPA_CON7 +#define MT6351_PMIC_DA_NI_VPA_VOSEL_GRAY_MASK 0x7F +#define MT6351_PMIC_DA_NI_VPA_VOSEL_GRAY_SHIFT 0 +#define MT6351_PMIC_DA_NI_VPA_VOSEL_SYNC_ADDR MT6351_BUCK_VPA_CON8 +#define MT6351_PMIC_DA_NI_VPA_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VPA_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_TRANS_TD_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_BUCK_VPA_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VPA_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VPA_TRANS_CTRL_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_BUCK_VPA_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VPA_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VPA_TRANS_ONCE_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_BUCK_VPA_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VPA_DVS_EN_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_DA_QI_VPA_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VPA_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VPA_VSLEEP_EN_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_BUCK_VPA_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VPA_R2R_PDN_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_BUCK_VPA_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VPA_VSLEEP_SEL_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_BUCK_VPA_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VPA_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VPA_R2R_PDN_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_DA_NI_VPA_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VPA_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VPA_VSLEEP_SEL_ADDR MT6351_BUCK_VPA_CON9 +#define MT6351_PMIC_DA_NI_VPA_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VPA_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_CTRL_ADDR MT6351_BUCK_VSRAM_PROC_CON0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_CTRL_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL_ADDR MT6351_BUCK_VSRAM_PROC_CON0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL_SHIFT 1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_SEL_ADDR MT6351_BUCK_VSRAM_PROC_CON1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_SEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SEL_ADDR MT6351_BUCK_VSRAM_PROC_CON1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SEL_MASK 0x7 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SEL_SHIFT 3 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_ADDR MT6351_BUCK_VSRAM_PROC_CON2 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_EN_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_STBTD_ADDR MT6351_BUCK_VSRAM_PROC_CON2 +#define MT6351_PMIC_BUCK_VSRAM_PROC_STBTD_MASK 0x3 +#define MT6351_PMIC_BUCK_VSRAM_PROC_STBTD_SHIFT 4 +#define MT6351_PMIC_DA_VSRAM_PROC_STB_ADDR MT6351_BUCK_VSRAM_PROC_CON2 +#define MT6351_PMIC_DA_VSRAM_PROC_STB_MASK 0x1 +#define MT6351_PMIC_DA_VSRAM_PROC_STB_SHIFT 12 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_EN_RSV_ADDR MT6351_BUCK_VSRAM_PROC_CON2 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_EN_RSV_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_EN_RSV_SHIFT 13 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE_ADDR MT6351_BUCK_VSRAM_PROC_CON3 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FEN_ADDR MT6351_BUCK_VSRAM_PROC_CON3 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FEN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FEN_SHIFT 7 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE_ADDR MT6351_BUCK_VSRAM_PROC_CON3 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE_SHIFT 8 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_REN_ADDR MT6351_BUCK_VSRAM_PROC_CON3 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_REN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_REN_SHIFT 15 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ADDR MT6351_BUCK_VSRAM_PROC_CON4 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_ADDR MT6351_BUCK_VSRAM_PROC_CON5 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_ADDR MT6351_BUCK_VSRAM_PROC_CON6 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_MASK 0x7F +#define MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_SHIFT 0 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_ADDR MT6351_BUCK_VSRAM_PROC_CON7 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_MASK 0x7F +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SHIFT 0 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC_ADDR MT6351_BUCK_VSRAM_PROC_CON8 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC_MASK 0x7F +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_TD_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_TD_MASK 0x3 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_TD_SHIFT 0 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_CTRL_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_CTRL_SHIFT 4 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_ONCE_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_ONCE_SHIFT 6 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_DVS_EN_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_DVS_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_DVS_EN_SHIFT 7 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_SHIFT 8 +#define MT6351_PMIC_BUCK_VSRAM_PROC_R2R_PDN_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_BUCK_VSRAM_PROC_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_R2R_PDN_SHIFT 10 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL_SHIFT 11 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_R2R_PDN_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_R2R_PDN_MASK 0x1 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_R2R_PDN_SHIFT 14 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_ADDR MT6351_BUCK_VSRAM_PROC_CON9 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_BUCK_K_RST_DONE_ADDR MT6351_BUCK_K_CON0 +#define MT6351_PMIC_BUCK_K_RST_DONE_MASK 0x1 +#define MT6351_PMIC_BUCK_K_RST_DONE_SHIFT 0 +#define MT6351_PMIC_BUCK_K_MAP_SEL_ADDR MT6351_BUCK_K_CON0 +#define MT6351_PMIC_BUCK_K_MAP_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_K_MAP_SEL_SHIFT 1 +#define MT6351_PMIC_BUCK_K_ONCE_EN_ADDR MT6351_BUCK_K_CON0 +#define MT6351_PMIC_BUCK_K_ONCE_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_K_ONCE_EN_SHIFT 2 +#define MT6351_PMIC_BUCK_K_ONCE_ADDR MT6351_BUCK_K_CON0 +#define MT6351_PMIC_BUCK_K_ONCE_MASK 0x1 +#define MT6351_PMIC_BUCK_K_ONCE_SHIFT 3 +#define MT6351_PMIC_BUCK_K_START_MANUAL_ADDR MT6351_BUCK_K_CON0 +#define MT6351_PMIC_BUCK_K_START_MANUAL_MASK 0x1 +#define MT6351_PMIC_BUCK_K_START_MANUAL_SHIFT 4 +#define MT6351_PMIC_BUCK_K_SRC_SEL_ADDR MT6351_BUCK_K_CON0 +#define MT6351_PMIC_BUCK_K_SRC_SEL_MASK 0x1 +#define MT6351_PMIC_BUCK_K_SRC_SEL_SHIFT 5 +#define MT6351_PMIC_BUCK_K_AUTO_EN_ADDR MT6351_BUCK_K_CON0 +#define MT6351_PMIC_BUCK_K_AUTO_EN_MASK 0x1 +#define MT6351_PMIC_BUCK_K_AUTO_EN_SHIFT 6 +#define MT6351_PMIC_BUCK_K_INV_ADDR MT6351_BUCK_K_CON0 +#define MT6351_PMIC_BUCK_K_INV_MASK 0x1 +#define MT6351_PMIC_BUCK_K_INV_SHIFT 7 +#define MT6351_PMIC_BUCK_K_CONTROL_SMPS_ADDR MT6351_BUCK_K_CON1 +#define MT6351_PMIC_BUCK_K_CONTROL_SMPS_MASK 0x3F +#define MT6351_PMIC_BUCK_K_CONTROL_SMPS_SHIFT 8 +#define MT6351_PMIC_K_RESULT_ADDR MT6351_BUCK_K_CON2 +#define MT6351_PMIC_K_RESULT_MASK 0x1 +#define MT6351_PMIC_K_RESULT_SHIFT 0 +#define MT6351_PMIC_K_DONE_ADDR MT6351_BUCK_K_CON2 +#define MT6351_PMIC_K_DONE_MASK 0x1 +#define MT6351_PMIC_K_DONE_SHIFT 1 +#define MT6351_PMIC_K_CONTROL_ADDR MT6351_BUCK_K_CON2 +#define MT6351_PMIC_K_CONTROL_MASK 0x3F +#define MT6351_PMIC_K_CONTROL_SHIFT 2 +#define MT6351_PMIC_DA_QI_SMPS_OSC_CAL_ADDR MT6351_BUCK_K_CON2 +#define MT6351_PMIC_DA_QI_SMPS_OSC_CAL_MASK 0x3F +#define MT6351_PMIC_DA_QI_SMPS_OSC_CAL_SHIFT 8 +#define MT6351_PMIC_BUCK_K_BUCK_CK_CNT_ADDR MT6351_BUCK_K_CON3 +#define MT6351_PMIC_BUCK_K_BUCK_CK_CNT_MASK 0x3FF +#define MT6351_PMIC_BUCK_K_BUCK_CK_CNT_SHIFT 0 +#define MT6351_PMIC_WDTDBG_CLR_ADDR MT6351_WDTDBG_CON0 +#define MT6351_PMIC_WDTDBG_CLR_MASK 0x1 +#define MT6351_PMIC_WDTDBG_CLR_SHIFT 0 +#define MT6351_PMIC_WDTDBG_CON0_RSV0_ADDR MT6351_WDTDBG_CON0 +#define MT6351_PMIC_WDTDBG_CON0_RSV0_MASK 0x1 +#define MT6351_PMIC_WDTDBG_CON0_RSV0_SHIFT 1 +#define MT6351_PMIC_VGPU_VOSEL_WDTDBG_ADDR MT6351_WDTDBG_CON1 +#define MT6351_PMIC_VGPU_VOSEL_WDTDBG_MASK 0x7F +#define MT6351_PMIC_VGPU_VOSEL_WDTDBG_SHIFT 0 +#define MT6351_PMIC_VCORE_VOSEL_WDTDBG_ADDR MT6351_WDTDBG_CON1 +#define MT6351_PMIC_VCORE_VOSEL_WDTDBG_MASK 0x7F +#define MT6351_PMIC_VCORE_VOSEL_WDTDBG_SHIFT 8 +#define MT6351_PMIC_VMD1_VOSEL_WDTDBG_ADDR MT6351_WDTDBG_CON2 +#define MT6351_PMIC_VMD1_VOSEL_WDTDBG_MASK 0x7F +#define MT6351_PMIC_VMD1_VOSEL_WDTDBG_SHIFT 0 +#define MT6351_PMIC_VMODEM_VOSEL_WDTDBG_ADDR MT6351_WDTDBG_CON2 +#define MT6351_PMIC_VMODEM_VOSEL_WDTDBG_MASK 0x7F +#define MT6351_PMIC_VMODEM_VOSEL_WDTDBG_SHIFT 8 +#define MT6351_PMIC_VSRAM_PROC_VOSEL_WDTDBG_ADDR MT6351_WDTDBG_CON3 +#define MT6351_PMIC_VSRAM_PROC_VOSEL_WDTDBG_MASK 0x7F +#define MT6351_PMIC_VSRAM_PROC_VOSEL_WDTDBG_SHIFT 0 +#define MT6351_PMIC_VSRAM_MD_VOSEL_WDTDBG_ADDR MT6351_WDTDBG_CON3 +#define MT6351_PMIC_VSRAM_MD_VOSEL_WDTDBG_MASK 0x7F +#define MT6351_PMIC_VSRAM_MD_VOSEL_WDTDBG_SHIFT 8 +#define MT6351_PMIC_RG_AUDZCDENABLE_ADDR MT6351_ZCD_CON0 +#define MT6351_PMIC_RG_AUDZCDENABLE_MASK 0x1 +#define MT6351_PMIC_RG_AUDZCDENABLE_SHIFT 0 +#define MT6351_PMIC_RG_AUDZCDGAINSTEPTIME_ADDR MT6351_ZCD_CON0 +#define MT6351_PMIC_RG_AUDZCDGAINSTEPTIME_MASK 0x7 +#define MT6351_PMIC_RG_AUDZCDGAINSTEPTIME_SHIFT 1 +#define MT6351_PMIC_RG_AUDZCDGAINSTEPSIZE_ADDR MT6351_ZCD_CON0 +#define MT6351_PMIC_RG_AUDZCDGAINSTEPSIZE_MASK 0x3 +#define MT6351_PMIC_RG_AUDZCDGAINSTEPSIZE_SHIFT 4 +#define MT6351_PMIC_RG_AUDZCDTIMEOUTMODESEL_ADDR MT6351_ZCD_CON0 +#define MT6351_PMIC_RG_AUDZCDTIMEOUTMODESEL_MASK 0x1 +#define MT6351_PMIC_RG_AUDZCDTIMEOUTMODESEL_SHIFT 6 +#define MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP15_ADDR MT6351_ZCD_CON0 +#define MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP15_MASK 0x1 +#define MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP15_SHIFT 7 +#define MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP15_ADDR MT6351_ZCD_CON0 +#define MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP15_MASK 0x7 +#define MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP15_SHIFT 8 +#define MT6351_PMIC_RG_AUDLOLGAIN_ADDR MT6351_ZCD_CON1 +#define MT6351_PMIC_RG_AUDLOLGAIN_MASK 0x1F +#define MT6351_PMIC_RG_AUDLOLGAIN_SHIFT 0 +#define MT6351_PMIC_RG_AUDLORGAIN_ADDR MT6351_ZCD_CON1 +#define MT6351_PMIC_RG_AUDLORGAIN_MASK 0x1F +#define MT6351_PMIC_RG_AUDLORGAIN_SHIFT 7 +#define MT6351_PMIC_RG_AUDHPLGAIN_ADDR MT6351_ZCD_CON2 +#define MT6351_PMIC_RG_AUDHPLGAIN_MASK 0x1F +#define MT6351_PMIC_RG_AUDHPLGAIN_SHIFT 0 +#define MT6351_PMIC_RG_AUDHPRGAIN_ADDR MT6351_ZCD_CON2 +#define MT6351_PMIC_RG_AUDHPRGAIN_MASK 0x1F +#define MT6351_PMIC_RG_AUDHPRGAIN_SHIFT 7 +#define MT6351_PMIC_RG_AUDHSGAIN_ADDR MT6351_ZCD_CON3 +#define MT6351_PMIC_RG_AUDHSGAIN_MASK 0x1F +#define MT6351_PMIC_RG_AUDHSGAIN_SHIFT 0 +#define MT6351_PMIC_RG_AUDIVLGAIN_ADDR MT6351_ZCD_CON4 +#define MT6351_PMIC_RG_AUDIVLGAIN_MASK 0x7 +#define MT6351_PMIC_RG_AUDIVLGAIN_SHIFT 0 +#define MT6351_PMIC_RG_AUDIVRGAIN_ADDR MT6351_ZCD_CON4 +#define MT6351_PMIC_RG_AUDIVRGAIN_MASK 0x7 +#define MT6351_PMIC_RG_AUDIVRGAIN_SHIFT 8 +#define MT6351_PMIC_RG_AUDINTGAIN1_ADDR MT6351_ZCD_CON5 +#define MT6351_PMIC_RG_AUDINTGAIN1_MASK 0x3F +#define MT6351_PMIC_RG_AUDINTGAIN1_SHIFT 0 +#define MT6351_PMIC_RG_AUDINTGAIN2_ADDR MT6351_ZCD_CON5 +#define MT6351_PMIC_RG_AUDINTGAIN2_MASK 0x3F +#define MT6351_PMIC_RG_AUDINTGAIN2_SHIFT 8 +#define MT6351_PMIC_RG_A_TRIM_EN_ADDR MT6351_ISINKA_ANA_CON_0 +#define MT6351_PMIC_RG_A_TRIM_EN_MASK 0x1 +#define MT6351_PMIC_RG_A_TRIM_EN_SHIFT 0 +#define MT6351_PMIC_RG_A_TRIM_SEL_ADDR MT6351_ISINKA_ANA_CON_0 +#define MT6351_PMIC_RG_A_TRIM_SEL_MASK 0x7 +#define MT6351_PMIC_RG_A_TRIM_SEL_SHIFT 1 +#define MT6351_PMIC_RG_A_ISINKS_RSV_ADDR MT6351_ISINKA_ANA_CON_0 +#define MT6351_PMIC_RG_A_ISINKS_RSV_MASK 0xFF +#define MT6351_PMIC_RG_A_ISINKS_RSV_SHIFT 4 +#define MT6351_PMIC_RG_B_TRIM_EN_ADDR MT6351_ISINKB_ANA_CON_0 +#define MT6351_PMIC_RG_B_TRIM_EN_MASK 0x1 +#define MT6351_PMIC_RG_B_TRIM_EN_SHIFT 0 +#define MT6351_PMIC_RG_B_TRIM_SEL_ADDR MT6351_ISINKB_ANA_CON_0 +#define MT6351_PMIC_RG_B_TRIM_SEL_MASK 0x7 +#define MT6351_PMIC_RG_B_TRIM_SEL_SHIFT 1 +#define MT6351_PMIC_RG_B_ISINKS_RSV_ADDR MT6351_ISINKB_ANA_CON_0 +#define MT6351_PMIC_RG_B_ISINKS_RSV_MASK 0xFF +#define MT6351_PMIC_RG_B_ISINKS_RSV_SHIFT 4 +#define MT6351_PMIC_ISINK_DIM0_FSEL_ADDR MT6351_ISINK0_CON0 +#define MT6351_PMIC_ISINK_DIM0_FSEL_MASK 0xFFFF +#define MT6351_PMIC_ISINK_DIM0_FSEL_SHIFT 0 +#define MT6351_PMIC_ISINK0_RSV1_ADDR MT6351_ISINK0_CON1 +#define MT6351_PMIC_ISINK0_RSV1_MASK 0xF +#define MT6351_PMIC_ISINK0_RSV1_SHIFT 0 +#define MT6351_PMIC_ISINK0_RSV0_ADDR MT6351_ISINK0_CON1 +#define MT6351_PMIC_ISINK0_RSV0_MASK 0x7 +#define MT6351_PMIC_ISINK0_RSV0_SHIFT 4 +#define MT6351_PMIC_ISINK_DIM0_DUTY_ADDR MT6351_ISINK0_CON1 +#define MT6351_PMIC_ISINK_DIM0_DUTY_MASK 0x1F +#define MT6351_PMIC_ISINK_DIM0_DUTY_SHIFT 7 +#define MT6351_PMIC_ISINK_CH0_STEP_ADDR MT6351_ISINK0_CON1 +#define MT6351_PMIC_ISINK_CH0_STEP_MASK 0x7 +#define MT6351_PMIC_ISINK_CH0_STEP_SHIFT 12 +#define MT6351_PMIC_ISINK_BREATH0_TF2_SEL_ADDR MT6351_ISINK0_CON2 +#define MT6351_PMIC_ISINK_BREATH0_TF2_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH0_TF2_SEL_SHIFT 0 +#define MT6351_PMIC_ISINK_BREATH0_TF1_SEL_ADDR MT6351_ISINK0_CON2 +#define MT6351_PMIC_ISINK_BREATH0_TF1_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH0_TF1_SEL_SHIFT 4 +#define MT6351_PMIC_ISINK_BREATH0_TR2_SEL_ADDR MT6351_ISINK0_CON2 +#define MT6351_PMIC_ISINK_BREATH0_TR2_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH0_TR2_SEL_SHIFT 8 +#define MT6351_PMIC_ISINK_BREATH0_TR1_SEL_ADDR MT6351_ISINK0_CON2 +#define MT6351_PMIC_ISINK_BREATH0_TR1_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH0_TR1_SEL_SHIFT 12 +#define MT6351_PMIC_ISINK_BREATH0_TOFF_SEL_ADDR MT6351_ISINK0_CON3 +#define MT6351_PMIC_ISINK_BREATH0_TOFF_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH0_TOFF_SEL_SHIFT 0 +#define MT6351_PMIC_ISINK_BREATH0_TON_SEL_ADDR MT6351_ISINK0_CON3 +#define MT6351_PMIC_ISINK_BREATH0_TON_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH0_TON_SEL_SHIFT 8 +#define MT6351_PMIC_ISINK_DIM1_FSEL_ADDR MT6351_ISINK1_CON0 +#define MT6351_PMIC_ISINK_DIM1_FSEL_MASK 0xFFFF +#define MT6351_PMIC_ISINK_DIM1_FSEL_SHIFT 0 +#define MT6351_PMIC_ISINK1_RSV1_ADDR MT6351_ISINK1_CON1 +#define MT6351_PMIC_ISINK1_RSV1_MASK 0xF +#define MT6351_PMIC_ISINK1_RSV1_SHIFT 0 +#define MT6351_PMIC_ISINK1_RSV0_ADDR MT6351_ISINK1_CON1 +#define MT6351_PMIC_ISINK1_RSV0_MASK 0x7 +#define MT6351_PMIC_ISINK1_RSV0_SHIFT 4 +#define MT6351_PMIC_ISINK_DIM1_DUTY_ADDR MT6351_ISINK1_CON1 +#define MT6351_PMIC_ISINK_DIM1_DUTY_MASK 0x1F +#define MT6351_PMIC_ISINK_DIM1_DUTY_SHIFT 7 +#define MT6351_PMIC_ISINK_CH1_STEP_ADDR MT6351_ISINK1_CON1 +#define MT6351_PMIC_ISINK_CH1_STEP_MASK 0x7 +#define MT6351_PMIC_ISINK_CH1_STEP_SHIFT 12 +#define MT6351_PMIC_ISINK_BREATH1_TF2_SEL_ADDR MT6351_ISINK1_CON2 +#define MT6351_PMIC_ISINK_BREATH1_TF2_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH1_TF2_SEL_SHIFT 0 +#define MT6351_PMIC_ISINK_BREATH1_TF1_SEL_ADDR MT6351_ISINK1_CON2 +#define MT6351_PMIC_ISINK_BREATH1_TF1_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH1_TF1_SEL_SHIFT 4 +#define MT6351_PMIC_ISINK_BREATH1_TR2_SEL_ADDR MT6351_ISINK1_CON2 +#define MT6351_PMIC_ISINK_BREATH1_TR2_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH1_TR2_SEL_SHIFT 8 +#define MT6351_PMIC_ISINK_BREATH1_TR1_SEL_ADDR MT6351_ISINK1_CON2 +#define MT6351_PMIC_ISINK_BREATH1_TR1_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH1_TR1_SEL_SHIFT 12 +#define MT6351_PMIC_ISINK_BREATH1_TOFF_SEL_ADDR MT6351_ISINK1_CON3 +#define MT6351_PMIC_ISINK_BREATH1_TOFF_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH1_TOFF_SEL_SHIFT 0 +#define MT6351_PMIC_ISINK_BREATH1_TON_SEL_ADDR MT6351_ISINK1_CON3 +#define MT6351_PMIC_ISINK_BREATH1_TON_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH1_TON_SEL_SHIFT 8 +#define MT6351_PMIC_ISINK_DIM4_FSEL_ADDR MT6351_ISINK4_CON0 +#define MT6351_PMIC_ISINK_DIM4_FSEL_MASK 0xFFFF +#define MT6351_PMIC_ISINK_DIM4_FSEL_SHIFT 0 +#define MT6351_PMIC_ISINK4_RSV1_ADDR MT6351_ISINK4_CON1 +#define MT6351_PMIC_ISINK4_RSV1_MASK 0xF +#define MT6351_PMIC_ISINK4_RSV1_SHIFT 0 +#define MT6351_PMIC_ISINK4_RSV0_ADDR MT6351_ISINK4_CON1 +#define MT6351_PMIC_ISINK4_RSV0_MASK 0x7 +#define MT6351_PMIC_ISINK4_RSV0_SHIFT 4 +#define MT6351_PMIC_ISINK_DIM4_DUTY_ADDR MT6351_ISINK4_CON1 +#define MT6351_PMIC_ISINK_DIM4_DUTY_MASK 0x1F +#define MT6351_PMIC_ISINK_DIM4_DUTY_SHIFT 7 +#define MT6351_PMIC_ISINK_CH4_STEP_ADDR MT6351_ISINK4_CON1 +#define MT6351_PMIC_ISINK_CH4_STEP_MASK 0x7 +#define MT6351_PMIC_ISINK_CH4_STEP_SHIFT 12 +#define MT6351_PMIC_ISINK_BREATH4_TF2_SEL_ADDR MT6351_ISINK4_CON2 +#define MT6351_PMIC_ISINK_BREATH4_TF2_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH4_TF2_SEL_SHIFT 0 +#define MT6351_PMIC_ISINK_BREATH4_TF1_SEL_ADDR MT6351_ISINK4_CON2 +#define MT6351_PMIC_ISINK_BREATH4_TF1_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH4_TF1_SEL_SHIFT 4 +#define MT6351_PMIC_ISINK_BREATH4_TR2_SEL_ADDR MT6351_ISINK4_CON2 +#define MT6351_PMIC_ISINK_BREATH4_TR2_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH4_TR2_SEL_SHIFT 8 +#define MT6351_PMIC_ISINK_BREATH4_TR1_SEL_ADDR MT6351_ISINK4_CON2 +#define MT6351_PMIC_ISINK_BREATH4_TR1_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH4_TR1_SEL_SHIFT 12 +#define MT6351_PMIC_ISINK_BREATH4_TOFF_SEL_ADDR MT6351_ISINK4_CON3 +#define MT6351_PMIC_ISINK_BREATH4_TOFF_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH4_TOFF_SEL_SHIFT 0 +#define MT6351_PMIC_ISINK_BREATH4_TON_SEL_ADDR MT6351_ISINK4_CON3 +#define MT6351_PMIC_ISINK_BREATH4_TON_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH4_TON_SEL_SHIFT 8 +#define MT6351_PMIC_ISINK_DIM5_FSEL_ADDR MT6351_ISINK5_CON0 +#define MT6351_PMIC_ISINK_DIM5_FSEL_MASK 0xFFFF +#define MT6351_PMIC_ISINK_DIM5_FSEL_SHIFT 0 +#define MT6351_PMIC_ISINK5_RSV1_ADDR MT6351_ISINK5_CON1 +#define MT6351_PMIC_ISINK5_RSV1_MASK 0xF +#define MT6351_PMIC_ISINK5_RSV1_SHIFT 0 +#define MT6351_PMIC_ISINK5_RSV0_ADDR MT6351_ISINK5_CON1 +#define MT6351_PMIC_ISINK5_RSV0_MASK 0x7 +#define MT6351_PMIC_ISINK5_RSV0_SHIFT 4 +#define MT6351_PMIC_ISINK_DIM5_DUTY_ADDR MT6351_ISINK5_CON1 +#define MT6351_PMIC_ISINK_DIM5_DUTY_MASK 0x1F +#define MT6351_PMIC_ISINK_DIM5_DUTY_SHIFT 7 +#define MT6351_PMIC_ISINK_CH5_STEP_ADDR MT6351_ISINK5_CON1 +#define MT6351_PMIC_ISINK_CH5_STEP_MASK 0x7 +#define MT6351_PMIC_ISINK_CH5_STEP_SHIFT 12 +#define MT6351_PMIC_ISINK_BREATH5_TF2_SEL_ADDR MT6351_ISINK5_CON2 +#define MT6351_PMIC_ISINK_BREATH5_TF2_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH5_TF2_SEL_SHIFT 0 +#define MT6351_PMIC_ISINK_BREATH5_TF1_SEL_ADDR MT6351_ISINK5_CON2 +#define MT6351_PMIC_ISINK_BREATH5_TF1_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH5_TF1_SEL_SHIFT 4 +#define MT6351_PMIC_ISINK_BREATH5_TR2_SEL_ADDR MT6351_ISINK5_CON2 +#define MT6351_PMIC_ISINK_BREATH5_TR2_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH5_TR2_SEL_SHIFT 8 +#define MT6351_PMIC_ISINK_BREATH5_TR1_SEL_ADDR MT6351_ISINK5_CON2 +#define MT6351_PMIC_ISINK_BREATH5_TR1_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH5_TR1_SEL_SHIFT 12 +#define MT6351_PMIC_ISINK_BREATH5_TOFF_SEL_ADDR MT6351_ISINK5_CON3 +#define MT6351_PMIC_ISINK_BREATH5_TOFF_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH5_TOFF_SEL_SHIFT 0 +#define MT6351_PMIC_ISINK_BREATH5_TON_SEL_ADDR MT6351_ISINK5_CON3 +#define MT6351_PMIC_ISINK_BREATH5_TON_SEL_MASK 0xF +#define MT6351_PMIC_ISINK_BREATH5_TON_SEL_SHIFT 8 +#define MT6351_PMIC_AD_NI_B_ISINK1_STATUS_ADDR MT6351_ISINK_ANA1 +#define MT6351_PMIC_AD_NI_B_ISINK1_STATUS_MASK 0x1 +#define MT6351_PMIC_AD_NI_B_ISINK1_STATUS_SHIFT 0 +#define MT6351_PMIC_AD_NI_B_ISINK0_STATUS_ADDR MT6351_ISINK_ANA1 +#define MT6351_PMIC_AD_NI_B_ISINK0_STATUS_MASK 0x1 +#define MT6351_PMIC_AD_NI_B_ISINK0_STATUS_SHIFT 1 +#define MT6351_PMIC_AD_NI_A_ISINK1_STATUS_ADDR MT6351_ISINK_ANA1 +#define MT6351_PMIC_AD_NI_A_ISINK1_STATUS_MASK 0x1 +#define MT6351_PMIC_AD_NI_A_ISINK1_STATUS_SHIFT 2 +#define MT6351_PMIC_AD_NI_A_ISINK0_STATUS_ADDR MT6351_ISINK_ANA1 +#define MT6351_PMIC_AD_NI_A_ISINK0_STATUS_MASK 0x1 +#define MT6351_PMIC_AD_NI_A_ISINK0_STATUS_SHIFT 3 +#define MT6351_PMIC_ISINK_PHASE0_DLY_EN_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_PHASE0_DLY_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_PHASE0_DLY_EN_SHIFT 0 +#define MT6351_PMIC_ISINK_PHASE1_DLY_EN_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_PHASE1_DLY_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_PHASE1_DLY_EN_SHIFT 1 +#define MT6351_PMIC_ISINK_PHASE4_DLY_EN_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_PHASE4_DLY_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_PHASE4_DLY_EN_SHIFT 2 +#define MT6351_PMIC_ISINK_PHASE5_DLY_EN_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_PHASE5_DLY_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_PHASE5_DLY_EN_SHIFT 3 +#define MT6351_PMIC_ISINK_PHASE_DLY_TC_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_PHASE_DLY_TC_MASK 0x3 +#define MT6351_PMIC_ISINK_PHASE_DLY_TC_SHIFT 4 +#define MT6351_PMIC_ISINK_CHOP0_SW_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_CHOP0_SW_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP0_SW_SHIFT 12 +#define MT6351_PMIC_ISINK_CHOP1_SW_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_CHOP1_SW_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP1_SW_SHIFT 13 +#define MT6351_PMIC_ISINK_CHOP4_SW_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_CHOP4_SW_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP4_SW_SHIFT 14 +#define MT6351_PMIC_ISINK_CHOP5_SW_ADDR MT6351_ISINK_PHASE_DLY +#define MT6351_PMIC_ISINK_CHOP5_SW_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP5_SW_SHIFT 15 +#define MT6351_PMIC_ISINK_SFSTR5_EN_ADDR MT6351_ISINK_SFSTR +#define MT6351_PMIC_ISINK_SFSTR5_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_SFSTR5_EN_SHIFT 0 +#define MT6351_PMIC_ISINK_SFSTR5_TC_ADDR MT6351_ISINK_SFSTR +#define MT6351_PMIC_ISINK_SFSTR5_TC_MASK 0x3 +#define MT6351_PMIC_ISINK_SFSTR5_TC_SHIFT 1 +#define MT6351_PMIC_ISINK_SFSTR4_EN_ADDR MT6351_ISINK_SFSTR +#define MT6351_PMIC_ISINK_SFSTR4_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_SFSTR4_EN_SHIFT 4 +#define MT6351_PMIC_ISINK_SFSTR4_TC_ADDR MT6351_ISINK_SFSTR +#define MT6351_PMIC_ISINK_SFSTR4_TC_MASK 0x3 +#define MT6351_PMIC_ISINK_SFSTR4_TC_SHIFT 5 +#define MT6351_PMIC_ISINK_SFSTR1_EN_ADDR MT6351_ISINK_SFSTR +#define MT6351_PMIC_ISINK_SFSTR1_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_SFSTR1_EN_SHIFT 8 +#define MT6351_PMIC_ISINK_SFSTR1_TC_ADDR MT6351_ISINK_SFSTR +#define MT6351_PMIC_ISINK_SFSTR1_TC_MASK 0x3 +#define MT6351_PMIC_ISINK_SFSTR1_TC_SHIFT 9 +#define MT6351_PMIC_ISINK_SFSTR0_EN_ADDR MT6351_ISINK_SFSTR +#define MT6351_PMIC_ISINK_SFSTR0_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_SFSTR0_EN_SHIFT 12 +#define MT6351_PMIC_ISINK_SFSTR0_TC_ADDR MT6351_ISINK_SFSTR +#define MT6351_PMIC_ISINK_SFSTR0_TC_MASK 0x3 +#define MT6351_PMIC_ISINK_SFSTR0_TC_SHIFT 13 +#define MT6351_PMIC_ISINK_CH0_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CH0_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH0_EN_SHIFT 0 +#define MT6351_PMIC_ISINK_CH1_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CH1_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH1_EN_SHIFT 1 +#define MT6351_PMIC_ISINK_CH4_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CH4_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH4_EN_SHIFT 2 +#define MT6351_PMIC_ISINK_CH5_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CH5_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH5_EN_SHIFT 3 +#define MT6351_PMIC_ISINK_CHOP0_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CHOP0_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP0_EN_SHIFT 4 +#define MT6351_PMIC_ISINK_CHOP1_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CHOP1_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP1_EN_SHIFT 5 +#define MT6351_PMIC_ISINK_CHOP4_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CHOP4_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP4_EN_SHIFT 6 +#define MT6351_PMIC_ISINK_CHOP5_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CHOP5_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP5_EN_SHIFT 7 +#define MT6351_PMIC_ISINK_CH0_BIAS_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CH0_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH0_BIAS_EN_SHIFT 8 +#define MT6351_PMIC_ISINK_CH1_BIAS_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CH1_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH1_BIAS_EN_SHIFT 9 +#define MT6351_PMIC_ISINK_CH4_BIAS_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CH4_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH4_BIAS_EN_SHIFT 10 +#define MT6351_PMIC_ISINK_CH5_BIAS_EN_ADDR MT6351_ISINK_EN_CTRL +#define MT6351_PMIC_ISINK_CH5_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH5_BIAS_EN_SHIFT 11 +#define MT6351_PMIC_ISINK_RSV_ADDR MT6351_ISINK_MODE_CTRL +#define MT6351_PMIC_ISINK_RSV_MASK 0x1F +#define MT6351_PMIC_ISINK_RSV_SHIFT 0 +#define MT6351_PMIC_ISINK_CH5_MODE_ADDR MT6351_ISINK_MODE_CTRL +#define MT6351_PMIC_ISINK_CH5_MODE_MASK 0x3 +#define MT6351_PMIC_ISINK_CH5_MODE_SHIFT 8 +#define MT6351_PMIC_ISINK_CH4_MODE_ADDR MT6351_ISINK_MODE_CTRL +#define MT6351_PMIC_ISINK_CH4_MODE_MASK 0x3 +#define MT6351_PMIC_ISINK_CH4_MODE_SHIFT 10 +#define MT6351_PMIC_ISINK_CH1_MODE_ADDR MT6351_ISINK_MODE_CTRL +#define MT6351_PMIC_ISINK_CH1_MODE_MASK 0x3 +#define MT6351_PMIC_ISINK_CH1_MODE_SHIFT 12 +#define MT6351_PMIC_ISINK_CH0_MODE_ADDR MT6351_ISINK_MODE_CTRL +#define MT6351_PMIC_ISINK_CH0_MODE_MASK 0x3 +#define MT6351_PMIC_ISINK_CH0_MODE_SHIFT 14 +#define MT6351_PMIC_DA_QI_A_ISINKS_CH0_STEP_ADDR MT6351_ISINK_ANA_CON0 +#define MT6351_PMIC_DA_QI_A_ISINKS_CH0_STEP_MASK 0x7 +#define MT6351_PMIC_DA_QI_A_ISINKS_CH0_STEP_SHIFT 0 +#define MT6351_PMIC_DA_QI_A_ISINKS_CH1_STEP_ADDR MT6351_ISINK_ANA_CON0 +#define MT6351_PMIC_DA_QI_A_ISINKS_CH1_STEP_MASK 0x7 +#define MT6351_PMIC_DA_QI_A_ISINKS_CH1_STEP_SHIFT 3 +#define MT6351_PMIC_DA_QI_B_ISINKS_CH0_STEP_ADDR MT6351_ISINK_ANA_CON0 +#define MT6351_PMIC_DA_QI_B_ISINKS_CH0_STEP_MASK 0x7 +#define MT6351_PMIC_DA_QI_B_ISINKS_CH0_STEP_SHIFT 6 +#define MT6351_PMIC_DA_QI_B_ISINKS_CH1_STEP_ADDR MT6351_ISINK_ANA_CON0 +#define MT6351_PMIC_DA_QI_B_ISINKS_CH1_STEP_MASK 0x7 +#define MT6351_PMIC_DA_QI_B_ISINKS_CH1_STEP_SHIFT 9 +#define MT6351_PMIC_ISINK2_RSV1_ADDR MT6351_ISINK2_CON1 +#define MT6351_PMIC_ISINK2_RSV1_MASK 0xF +#define MT6351_PMIC_ISINK2_RSV1_SHIFT 0 +#define MT6351_PMIC_ISINK2_RSV0_ADDR MT6351_ISINK2_CON1 +#define MT6351_PMIC_ISINK2_RSV0_MASK 0x7 +#define MT6351_PMIC_ISINK2_RSV0_SHIFT 4 +#define MT6351_PMIC_ISINK_CH2_STEP_ADDR MT6351_ISINK2_CON1 +#define MT6351_PMIC_ISINK_CH2_STEP_MASK 0x7 +#define MT6351_PMIC_ISINK_CH2_STEP_SHIFT 12 +#define MT6351_PMIC_ISINK3_RSV1_ADDR MT6351_ISINK3_CON1 +#define MT6351_PMIC_ISINK3_RSV1_MASK 0xF +#define MT6351_PMIC_ISINK3_RSV1_SHIFT 0 +#define MT6351_PMIC_ISINK3_RSV0_ADDR MT6351_ISINK3_CON1 +#define MT6351_PMIC_ISINK3_RSV0_MASK 0x7 +#define MT6351_PMIC_ISINK3_RSV0_SHIFT 4 +#define MT6351_PMIC_ISINK_CH3_STEP_ADDR MT6351_ISINK3_CON1 +#define MT6351_PMIC_ISINK_CH3_STEP_MASK 0x7 +#define MT6351_PMIC_ISINK_CH3_STEP_SHIFT 12 +#define MT6351_PMIC_ISINK6_RSV1_ADDR MT6351_ISINK6_CON1 +#define MT6351_PMIC_ISINK6_RSV1_MASK 0xF +#define MT6351_PMIC_ISINK6_RSV1_SHIFT 0 +#define MT6351_PMIC_ISINK6_RSV0_ADDR MT6351_ISINK6_CON1 +#define MT6351_PMIC_ISINK6_RSV0_MASK 0x7 +#define MT6351_PMIC_ISINK6_RSV0_SHIFT 4 +#define MT6351_PMIC_ISINK_CH6_STEP_ADDR MT6351_ISINK6_CON1 +#define MT6351_PMIC_ISINK_CH6_STEP_MASK 0x7 +#define MT6351_PMIC_ISINK_CH6_STEP_SHIFT 12 +#define MT6351_PMIC_ISINK7_RSV1_ADDR MT6351_ISINK7_CON1 +#define MT6351_PMIC_ISINK7_RSV1_MASK 0xF +#define MT6351_PMIC_ISINK7_RSV1_SHIFT 0 +#define MT6351_PMIC_ISINK7_RSV0_ADDR MT6351_ISINK7_CON1 +#define MT6351_PMIC_ISINK7_RSV0_MASK 0x7 +#define MT6351_PMIC_ISINK7_RSV0_SHIFT 4 +#define MT6351_PMIC_ISINK_CH7_STEP_ADDR MT6351_ISINK7_CON1 +#define MT6351_PMIC_ISINK_CH7_STEP_MASK 0x7 +#define MT6351_PMIC_ISINK_CH7_STEP_SHIFT 12 +#define MT6351_PMIC_AD_NI_B_ISINK3_STATUS_ADDR MT6351_ISINK_ANA1_SMPL +#define MT6351_PMIC_AD_NI_B_ISINK3_STATUS_MASK 0x1 +#define MT6351_PMIC_AD_NI_B_ISINK3_STATUS_SHIFT 0 +#define MT6351_PMIC_AD_NI_B_ISINK2_STATUS_ADDR MT6351_ISINK_ANA1_SMPL +#define MT6351_PMIC_AD_NI_B_ISINK2_STATUS_MASK 0x1 +#define MT6351_PMIC_AD_NI_B_ISINK2_STATUS_SHIFT 1 +#define MT6351_PMIC_AD_NI_A_ISINK3_STATUS_ADDR MT6351_ISINK_ANA1_SMPL +#define MT6351_PMIC_AD_NI_A_ISINK3_STATUS_MASK 0x1 +#define MT6351_PMIC_AD_NI_A_ISINK3_STATUS_SHIFT 2 +#define MT6351_PMIC_AD_NI_A_ISINK2_STATUS_ADDR MT6351_ISINK_ANA1_SMPL +#define MT6351_PMIC_AD_NI_A_ISINK2_STATUS_MASK 0x1 +#define MT6351_PMIC_AD_NI_A_ISINK2_STATUS_SHIFT 3 +#define MT6351_PMIC_ISINK_CHOP7_SW_ADDR MT6351_ISINK_PHASE_DLY_SMPL +#define MT6351_PMIC_ISINK_CHOP7_SW_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP7_SW_SHIFT 12 +#define MT6351_PMIC_ISINK_CHOP6_SW_ADDR MT6351_ISINK_PHASE_DLY_SMPL +#define MT6351_PMIC_ISINK_CHOP6_SW_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP6_SW_SHIFT 13 +#define MT6351_PMIC_ISINK_CHOP3_SW_ADDR MT6351_ISINK_PHASE_DLY_SMPL +#define MT6351_PMIC_ISINK_CHOP3_SW_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP3_SW_SHIFT 14 +#define MT6351_PMIC_ISINK_CHOP2_SW_ADDR MT6351_ISINK_PHASE_DLY_SMPL +#define MT6351_PMIC_ISINK_CHOP2_SW_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP2_SW_SHIFT 15 +#define MT6351_PMIC_ISINK_CH7_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CH7_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH7_EN_SHIFT 0 +#define MT6351_PMIC_ISINK_CH6_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CH6_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH6_EN_SHIFT 1 +#define MT6351_PMIC_ISINK_CH3_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CH3_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH3_EN_SHIFT 2 +#define MT6351_PMIC_ISINK_CH2_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CH2_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH2_EN_SHIFT 3 +#define MT6351_PMIC_ISINK_CHOP7_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CHOP7_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP7_EN_SHIFT 4 +#define MT6351_PMIC_ISINK_CHOP6_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CHOP6_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP6_EN_SHIFT 5 +#define MT6351_PMIC_ISINK_CHOP3_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CHOP3_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP3_EN_SHIFT 6 +#define MT6351_PMIC_ISINK_CHOP2_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CHOP2_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CHOP2_EN_SHIFT 7 +#define MT6351_PMIC_ISINK_CH7_BIAS_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CH7_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH7_BIAS_EN_SHIFT 8 +#define MT6351_PMIC_ISINK_CH6_BIAS_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CH6_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH6_BIAS_EN_SHIFT 9 +#define MT6351_PMIC_ISINK_CH3_BIAS_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CH3_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH3_BIAS_EN_SHIFT 10 +#define MT6351_PMIC_ISINK_CH2_BIAS_EN_ADDR MT6351_ISINK_EN_CTRL_SMPL +#define MT6351_PMIC_ISINK_CH2_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_ISINK_CH2_BIAS_EN_SHIFT 11 +#define MT6351_PMIC_CHRIND_DIM_FSEL_ADDR MT6351_CHRIND_CON0 +#define MT6351_PMIC_CHRIND_DIM_FSEL_MASK 0xFFFF +#define MT6351_PMIC_CHRIND_DIM_FSEL_SHIFT 0 +#define MT6351_PMIC_CHRIND_RSV1_ADDR MT6351_CHRIND_CON1 +#define MT6351_PMIC_CHRIND_RSV1_MASK 0xF +#define MT6351_PMIC_CHRIND_RSV1_SHIFT 0 +#define MT6351_PMIC_CHRIND_RSV0_ADDR MT6351_CHRIND_CON1 +#define MT6351_PMIC_CHRIND_RSV0_MASK 0x7 +#define MT6351_PMIC_CHRIND_RSV0_SHIFT 4 +#define MT6351_PMIC_CHRIND_DIM_DUTY_ADDR MT6351_CHRIND_CON1 +#define MT6351_PMIC_CHRIND_DIM_DUTY_MASK 0x1F +#define MT6351_PMIC_CHRIND_DIM_DUTY_SHIFT 7 +#define MT6351_PMIC_CHRIND_STEP_ADDR MT6351_CHRIND_CON1 +#define MT6351_PMIC_CHRIND_STEP_MASK 0x7 +#define MT6351_PMIC_CHRIND_STEP_SHIFT 12 +#define MT6351_PMIC_CHRIND_BREATH_TF2_SEL_ADDR MT6351_CHRIND_CON2 +#define MT6351_PMIC_CHRIND_BREATH_TF2_SEL_MASK 0xF +#define MT6351_PMIC_CHRIND_BREATH_TF2_SEL_SHIFT 0 +#define MT6351_PMIC_CHRIND_BREATH_TF1_SEL_ADDR MT6351_CHRIND_CON2 +#define MT6351_PMIC_CHRIND_BREATH_TF1_SEL_MASK 0xF +#define MT6351_PMIC_CHRIND_BREATH_TF1_SEL_SHIFT 4 +#define MT6351_PMIC_CHRIND_BREATH_TR2_SEL_ADDR MT6351_CHRIND_CON2 +#define MT6351_PMIC_CHRIND_BREATH_TR2_SEL_MASK 0xF +#define MT6351_PMIC_CHRIND_BREATH_TR2_SEL_SHIFT 8 +#define MT6351_PMIC_CHRIND_BREATH_TR1_SEL_ADDR MT6351_CHRIND_CON2 +#define MT6351_PMIC_CHRIND_BREATH_TR1_SEL_MASK 0xF +#define MT6351_PMIC_CHRIND_BREATH_TR1_SEL_SHIFT 12 +#define MT6351_PMIC_CHRIND_BREATH_TOFF_SEL_ADDR MT6351_CHRIND_CON3 +#define MT6351_PMIC_CHRIND_BREATH_TOFF_SEL_MASK 0xF +#define MT6351_PMIC_CHRIND_BREATH_TOFF_SEL_SHIFT 0 +#define MT6351_PMIC_CHRIND_BREATH_TON_SEL_ADDR MT6351_CHRIND_CON3 +#define MT6351_PMIC_CHRIND_BREATH_TON_SEL_MASK 0xF +#define MT6351_PMIC_CHRIND_BREATH_TON_SEL_SHIFT 8 +#define MT6351_PMIC_CHRIND_SFSTR_EN_ADDR MT6351_CHRIND_EN_CTRL +#define MT6351_PMIC_CHRIND_SFSTR_EN_MASK 0x1 +#define MT6351_PMIC_CHRIND_SFSTR_EN_SHIFT 0 +#define MT6351_PMIC_CHRIND_SFSTR_TC_ADDR MT6351_CHRIND_EN_CTRL +#define MT6351_PMIC_CHRIND_SFSTR_TC_MASK 0x3 +#define MT6351_PMIC_CHRIND_SFSTR_TC_SHIFT 1 +#define MT6351_PMIC_CHRIND_EN_SEL_ADDR MT6351_CHRIND_EN_CTRL +#define MT6351_PMIC_CHRIND_EN_SEL_MASK 0x1 +#define MT6351_PMIC_CHRIND_EN_SEL_SHIFT 3 +#define MT6351_PMIC_CHRIND_EN_ADDR MT6351_CHRIND_EN_CTRL +#define MT6351_PMIC_CHRIND_EN_MASK 0x1 +#define MT6351_PMIC_CHRIND_EN_SHIFT 4 +#define MT6351_PMIC_CHRIND_CHOP_EN_ADDR MT6351_CHRIND_EN_CTRL +#define MT6351_PMIC_CHRIND_CHOP_EN_MASK 0x1 +#define MT6351_PMIC_CHRIND_CHOP_EN_SHIFT 5 +#define MT6351_PMIC_CHRIND_MODE_ADDR MT6351_CHRIND_EN_CTRL +#define MT6351_PMIC_CHRIND_MODE_MASK 0x3 +#define MT6351_PMIC_CHRIND_MODE_SHIFT 6 +#define MT6351_PMIC_CHRIND_CHOP_SW_ADDR MT6351_CHRIND_EN_CTRL +#define MT6351_PMIC_CHRIND_CHOP_SW_MASK 0x1 +#define MT6351_PMIC_CHRIND_CHOP_SW_SHIFT 8 +#define MT6351_PMIC_CHRIND_BIAS_EN_ADDR MT6351_CHRIND_EN_CTRL +#define MT6351_PMIC_CHRIND_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_CHRIND_BIAS_EN_SHIFT 9 +#define MT6351_PMIC_RG_VA18_MODE_SET_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_RG_VA18_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VA18_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VA18_EN_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_RG_VA18_EN_MASK 0x1 +#define MT6351_PMIC_RG_VA18_EN_SHIFT 1 +#define MT6351_PMIC_RG_VA18_MODE_CTRL_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_RG_VA18_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VA18_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VA18_ON_CTRL_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_RG_VA18_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VA18_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VA18_SRCLK_MODE_SEL_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_RG_VA18_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VA18_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VA18_MODE_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_DA_QI_VA18_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VA18_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VA18_STBTD_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_RG_VA18_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VA18_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VA18_SRCLK_EN_SEL_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_RG_VA18_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VA18_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VA18_STB_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_DA_QI_VA18_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VA18_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VA18_EN_ADDR MT6351_LDO_VA18_CON0 +#define MT6351_PMIC_DA_QI_VA18_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VA18_EN_SHIFT 15 +#define MT6351_PMIC_RG_VA18_AUXADC_PWDB_EN_ADDR MT6351_LDO_VA18_CON1 +#define MT6351_PMIC_RG_VA18_AUXADC_PWDB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VA18_AUXADC_PWDB_EN_SHIFT 2 +#define MT6351_PMIC_RG_VA18_OCFB_EN_ADDR MT6351_LDO_VA18_CON1 +#define MT6351_PMIC_RG_VA18_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VA18_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VA18_OCFB_EN_ADDR MT6351_LDO_VA18_CON1 +#define MT6351_PMIC_DA_QI_VA18_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VA18_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VTCXO24_MODE_SET_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_RG_VTCXO24_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO24_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VTCXO24_EN_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_RG_VTCXO24_EN_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO24_EN_SHIFT 1 +#define MT6351_PMIC_RG_VTCXO24_MODE_CTRL_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_RG_VTCXO24_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO24_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VTCXO24_ON_CTRL_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_RG_VTCXO24_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO24_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VTCXO24_SWITCH_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_RG_VTCXO24_SWITCH_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO24_SWITCH_SHIFT 4 +#define MT6351_PMIC_RG_VTCXO24_SRCLK_MODE_SEL_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_RG_VTCXO24_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VTCXO24_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VTCXO24_MODE_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_DA_QI_VTCXO24_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VTCXO24_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VTCXO24_STBTD_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_RG_VTCXO24_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VTCXO24_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VTCXO24_SRCLK_EN_SEL_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_RG_VTCXO24_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VTCXO24_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VTCXO24_STB_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_DA_QI_VTCXO24_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VTCXO24_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VTCXO24_EN_ADDR MT6351_LDO_VTCXO24_CON0 +#define MT6351_PMIC_DA_QI_VTCXO24_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VTCXO24_EN_SHIFT 15 +#define MT6351_PMIC_RG_VTCXO24_OCFB_EN_ADDR MT6351_LDO_VTCXO24_CON1 +#define MT6351_PMIC_RG_VTCXO24_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO24_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VTCXO24_OCFB_EN_ADDR MT6351_LDO_VTCXO24_CON1 +#define MT6351_PMIC_DA_QI_VTCXO24_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VTCXO24_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VTCXO28_MODE_SET_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_RG_VTCXO28_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO28_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VTCXO28_EN_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_RG_VTCXO28_EN_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO28_EN_SHIFT 1 +#define MT6351_PMIC_RG_VTCXO28_MODE_CTRL_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_RG_VTCXO28_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO28_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VTCXO28_ON_CTRL_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_RG_VTCXO28_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO28_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VTCXO28_SRCLK_MODE_SEL_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_RG_VTCXO28_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VTCXO28_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VTCXO28_MODE_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_DA_QI_VTCXO28_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VTCXO28_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VTCXO28_STBTD_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_RG_VTCXO28_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VTCXO28_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VTCXO28_SRCLK_EN_SEL_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_RG_VTCXO28_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VTCXO28_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VTCXO28_STB_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_DA_QI_VTCXO28_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VTCXO28_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VTCXO28_EN_ADDR MT6351_LDO_VTCXO28_CON0 +#define MT6351_PMIC_DA_QI_VTCXO28_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VTCXO28_EN_SHIFT 15 +#define MT6351_PMIC_RG_VTCXO28_OCFB_EN_ADDR MT6351_LDO_VTCXO28_CON1 +#define MT6351_PMIC_RG_VTCXO28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO28_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VTCXO28_OCFB_EN_ADDR MT6351_LDO_VTCXO28_CON1 +#define MT6351_PMIC_DA_QI_VTCXO28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VTCXO28_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VCN28_MODE_SET_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_RG_VCN28_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VCN28_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VCN28_EN_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_RG_VCN28_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN28_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCN28_MODE_CTRL_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_RG_VCN28_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCN28_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VCN28_ON_CTRL_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_RG_VCN28_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCN28_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VCN28_SRCLK_MODE_SEL_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_RG_VCN28_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN28_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VCN28_MODE_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_DA_QI_VCN28_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN28_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VCN28_STBTD_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_RG_VCN28_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VCN28_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VCN28_SRCLK_EN_SEL_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_RG_VCN28_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN28_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VCN28_STB_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_DA_QI_VCN28_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN28_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VCN28_EN_ADDR MT6351_LDO_VCN28_CON0 +#define MT6351_PMIC_DA_QI_VCN28_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN28_EN_SHIFT 15 +#define MT6351_PMIC_RG_VCN28_OCFB_EN_ADDR MT6351_LDO_VCN28_CON1 +#define MT6351_PMIC_RG_VCN28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN28_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCN28_OCFB_EN_ADDR MT6351_LDO_VCN28_CON1 +#define MT6351_PMIC_DA_QI_VCN28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN28_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_EN_ADDR MT6351_LDO_VCN28_CON2 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VCN28_CON2 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_ADDR MT6351_LDO_VCN28_CON2 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VCN28_CON2 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VCN28_DUMMY_LOAD_ADDR MT6351_LDO_VCN28_CON2 +#define MT6351_PMIC_DA_QI_VCN28_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VCN28_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VCAMA_EN_ADDR MT6351_LDO_VCAMA_CON0 +#define MT6351_PMIC_RG_VCAMA_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMA_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCAMA_ON_CTRL_ADDR MT6351_LDO_VCAMA_CON0 +#define MT6351_PMIC_RG_VCAMA_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCAMA_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VCAMA_SRCLK_MODE_SEL_ADDR MT6351_LDO_VCAMA_CON0 +#define MT6351_PMIC_RG_VCAMA_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMA_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VCAMA_MODE_ADDR MT6351_LDO_VCAMA_CON0 +#define MT6351_PMIC_DA_QI_VCAMA_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMA_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VCAMA_STBTD_ADDR MT6351_LDO_VCAMA_CON0 +#define MT6351_PMIC_RG_VCAMA_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VCAMA_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VCAMA_SRCLK_EN_SEL_ADDR MT6351_LDO_VCAMA_CON0 +#define MT6351_PMIC_RG_VCAMA_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMA_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VCAMA_STB_ADDR MT6351_LDO_VCAMA_CON0 +#define MT6351_PMIC_DA_QI_VCAMA_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMA_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VCAMA_EN_ADDR MT6351_LDO_VCAMA_CON0 +#define MT6351_PMIC_DA_QI_VCAMA_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMA_EN_SHIFT 15 +#define MT6351_PMIC_RG_VCAMA_OCFB_EN_ADDR MT6351_LDO_VCAMA_CON1 +#define MT6351_PMIC_RG_VCAMA_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMA_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCAMA_OCFB_EN_ADDR MT6351_LDO_VCAMA_CON1 +#define MT6351_PMIC_DA_QI_VCAMA_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMA_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VUSB33_MODE_SET_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_RG_VUSB33_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VUSB33_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VUSB33_EN_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_RG_VUSB33_EN_MASK 0x1 +#define MT6351_PMIC_RG_VUSB33_EN_SHIFT 1 +#define MT6351_PMIC_RG_VUSB33_MODE_CTRL_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_RG_VUSB33_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VUSB33_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VUSB33_ON_CTRL_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_RG_VUSB33_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VUSB33_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VUSB33_SRCLK_MODE_SEL_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_RG_VUSB33_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VUSB33_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VUSB33_MODE_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_DA_QI_VUSB33_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VUSB33_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VUSB33_STBTD_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_RG_VUSB33_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VUSB33_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VUSB33_SRCLK_EN_SEL_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_RG_VUSB33_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VUSB33_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VUSB33_STB_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_DA_QI_VUSB33_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VUSB33_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VUSB33_EN_ADDR MT6351_LDO_VUSB33_CON0 +#define MT6351_PMIC_DA_QI_VUSB33_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VUSB33_EN_SHIFT 15 +#define MT6351_PMIC_RG_VUSB33_OCFB_EN_ADDR MT6351_LDO_VUSB33_CON1 +#define MT6351_PMIC_RG_VUSB33_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VUSB33_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VUSB33_OCFB_EN_ADDR MT6351_LDO_VUSB33_CON1 +#define MT6351_PMIC_DA_QI_VUSB33_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VUSB33_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_EN_ADDR MT6351_LDO_VUSB33_CON2 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VUSB33_CON2 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_ADDR MT6351_LDO_VUSB33_CON2 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VUSB33_CON2 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VUSB33_DUMMY_LOAD_ADDR MT6351_LDO_VUSB33_CON2 +#define MT6351_PMIC_DA_QI_VUSB33_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VUSB33_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VSIM1_MODE_SET_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_RG_VSIM1_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VSIM1_EN_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_RG_VSIM1_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_EN_SHIFT 1 +#define MT6351_PMIC_RG_VSIM1_MODE_CTRL_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_RG_VSIM1_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VSIM1_ON_CTRL_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_RG_VSIM1_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VSIM1_SRCLK_MODE_SEL_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_RG_VSIM1_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSIM1_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VSIM1_MODE_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_DA_QI_VSIM1_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSIM1_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VSIM1_STBTD_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_RG_VSIM1_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VSIM1_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VSIM1_SRCLK_EN_SEL_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_RG_VSIM1_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSIM1_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VSIM1_STB_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_DA_QI_VSIM1_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSIM1_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VSIM1_EN_ADDR MT6351_LDO_VSIM1_CON0 +#define MT6351_PMIC_DA_QI_VSIM1_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSIM1_EN_SHIFT 15 +#define MT6351_PMIC_RG_VSIM1_OCFB_EN_ADDR MT6351_LDO_VSIM1_CON1 +#define MT6351_PMIC_RG_VSIM1_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VSIM1_OCFB_EN_ADDR MT6351_LDO_VSIM1_CON1 +#define MT6351_PMIC_DA_QI_VSIM1_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSIM1_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_EN_ADDR MT6351_LDO_VSIM1_CON2 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VSIM1_CON2 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_ADDR MT6351_LDO_VSIM1_CON2 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VSIM1_CON2 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VSIM1_DUMMY_LOAD_ADDR MT6351_LDO_VSIM1_CON2 +#define MT6351_PMIC_DA_QI_VSIM1_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VSIM1_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VSIM2_MODE_SET_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_RG_VSIM2_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VSIM2_EN_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_RG_VSIM2_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_EN_SHIFT 1 +#define MT6351_PMIC_RG_VSIM2_MODE_CTRL_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_RG_VSIM2_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VSIM2_ON_CTRL_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_RG_VSIM2_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VSIM2_SRCLK_MODE_SEL_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_RG_VSIM2_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSIM2_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VSIM2_MODE_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_DA_QI_VSIM2_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSIM2_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VSIM2_STBTD_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_RG_VSIM2_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VSIM2_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VSIM2_SRCLK_EN_SEL_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_RG_VSIM2_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSIM2_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VSIM2_STB_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_DA_QI_VSIM2_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSIM2_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VSIM2_EN_ADDR MT6351_LDO_VSIM2_CON0 +#define MT6351_PMIC_DA_QI_VSIM2_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSIM2_EN_SHIFT 15 +#define MT6351_PMIC_RG_VSIM2_OCFB_EN_ADDR MT6351_LDO_VSIM2_CON1 +#define MT6351_PMIC_RG_VSIM2_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VSIM2_OCFB_EN_ADDR MT6351_LDO_VSIM2_CON1 +#define MT6351_PMIC_DA_QI_VSIM2_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSIM2_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_EN_ADDR MT6351_LDO_VSIM2_CON2 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VSIM2_CON2 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_ADDR MT6351_LDO_VSIM2_CON2 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VSIM2_CON2 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VSIM2_DUMMY_LOAD_ADDR MT6351_LDO_VSIM2_CON2 +#define MT6351_PMIC_DA_QI_VSIM2_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VSIM2_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VEMC_MODE_SET_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_RG_VEMC_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VEMC_EN_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_RG_VEMC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_EN_SHIFT 1 +#define MT6351_PMIC_RG_VEMC_MODE_CTRL_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_RG_VEMC_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VEMC_ON_CTRL_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_RG_VEMC_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VEMC_SRCLK_MODE_SEL_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_RG_VEMC_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VEMC_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VEMC_MODE_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_DA_QI_VEMC_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VEMC_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VEMC_STBTD_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_RG_VEMC_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VEMC_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VEMC_SRCLK_EN_SEL_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_RG_VEMC_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VEMC_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VEMC_STB_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_DA_QI_VEMC_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VEMC_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VEMC_EN_ADDR MT6351_LDO_VEMC_CON0 +#define MT6351_PMIC_DA_QI_VEMC_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VEMC_EN_SHIFT 15 +#define MT6351_PMIC_RG_VEMC_OCFB_EN_ADDR MT6351_LDO_VEMC_CON1 +#define MT6351_PMIC_RG_VEMC_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VEMC_OCFB_EN_ADDR MT6351_LDO_VEMC_CON1 +#define MT6351_PMIC_DA_QI_VEMC_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VEMC_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_EN_ADDR MT6351_LDO_VEMC_CON2 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VEMC_CON2 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_ADDR MT6351_LDO_VEMC_CON2 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VEMC_CON2 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VEMC_DUMMY_LOAD_ADDR MT6351_LDO_VEMC_CON2 +#define MT6351_PMIC_DA_QI_VEMC_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VEMC_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VMCH_MODE_SET_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_RG_VMCH_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VMCH_EN_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_RG_VMCH_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_EN_SHIFT 1 +#define MT6351_PMIC_RG_VMCH_MODE_CTRL_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_RG_VMCH_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VMCH_ON_CTRL_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_RG_VMCH_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VMCH_SRCLK_MODE_SEL_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_RG_VMCH_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMCH_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VMCH_MODE_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_DA_QI_VMCH_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMCH_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VMCH_STBTD_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_RG_VMCH_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VMCH_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VMCH_SRCLK_EN_SEL_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_RG_VMCH_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMCH_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VMCH_STB_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_DA_QI_VMCH_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMCH_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VMCH_EN_ADDR MT6351_LDO_VMCH_CON0 +#define MT6351_PMIC_DA_QI_VMCH_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMCH_EN_SHIFT 15 +#define MT6351_PMIC_RG_VMCH_OCFB_EN_ADDR MT6351_LDO_VMCH_CON1 +#define MT6351_PMIC_RG_VMCH_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VMCH_OCFB_EN_ADDR MT6351_LDO_VMCH_CON1 +#define MT6351_PMIC_DA_QI_VMCH_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMCH_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_EN_ADDR MT6351_LDO_VMCH_CON2 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VMCH_CON2 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_ADDR MT6351_LDO_VMCH_CON2 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VMCH_CON2 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VMCH_DUMMY_LOAD_ADDR MT6351_LDO_VMCH_CON2 +#define MT6351_PMIC_DA_QI_VMCH_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VMCH_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VIO28_MODE_SET_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_RG_VIO28_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VIO28_EN_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_RG_VIO28_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_EN_SHIFT 1 +#define MT6351_PMIC_RG_VIO28_MODE_CTRL_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_RG_VIO28_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VIO28_ON_CTRL_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_RG_VIO28_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VIO28_SRCLK_MODE_SEL_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_RG_VIO28_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIO28_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VIO28_MODE_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_DA_QI_VIO28_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO28_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VIO28_STBTD_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_RG_VIO28_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VIO28_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VIO28_SRCLK_EN_SEL_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_RG_VIO28_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIO28_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VIO28_STB_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_DA_QI_VIO28_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO28_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VIO28_EN_ADDR MT6351_LDO_VIO28_CON0 +#define MT6351_PMIC_DA_QI_VIO28_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO28_EN_SHIFT 15 +#define MT6351_PMIC_RG_VIO28_OCFB_EN_ADDR MT6351_LDO_VIO28_CON1 +#define MT6351_PMIC_RG_VIO28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VIO28_OCFB_EN_ADDR MT6351_LDO_VIO28_CON1 +#define MT6351_PMIC_DA_QI_VIO28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO28_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_EN_ADDR MT6351_LDO_VIO28_CON2 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VIO28_CON2 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_ADDR MT6351_LDO_VIO28_CON2 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VIO28_CON2 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VIO28_DUMMY_LOAD_ADDR MT6351_LDO_VIO28_CON2 +#define MT6351_PMIC_DA_QI_VIO28_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VIO28_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VIBR_MODE_SET_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_RG_VIBR_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VIBR_EN_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_RG_VIBR_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_EN_SHIFT 1 +#define MT6351_PMIC_RG_VIBR_MODE_CTRL_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_RG_VIBR_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VIBR_ON_CTRL_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_RG_VIBR_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VIBR_THER_SDN_EN_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_RG_VIBR_THER_SDN_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_THER_SDN_EN_SHIFT 4 +#define MT6351_PMIC_RG_VIBR_SRCLK_MODE_SEL_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_RG_VIBR_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIBR_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VIBR_MODE_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_DA_QI_VIBR_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIBR_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VIBR_STBTD_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_RG_VIBR_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VIBR_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VIBR_SRCLK_EN_SEL_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_RG_VIBR_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIBR_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VIBR_STB_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_DA_QI_VIBR_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIBR_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VIBR_EN_ADDR MT6351_LDO_VIBR_CON0 +#define MT6351_PMIC_DA_QI_VIBR_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIBR_EN_SHIFT 15 +#define MT6351_PMIC_RG_VIBR_OCFB_EN_ADDR MT6351_LDO_VIBR_CON1 +#define MT6351_PMIC_RG_VIBR_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VIBR_OCFB_EN_ADDR MT6351_LDO_VIBR_CON1 +#define MT6351_PMIC_DA_QI_VIBR_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIBR_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_EN_ADDR MT6351_LDO_VIBR_CON2 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VIBR_CON2 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_ADDR MT6351_LDO_VIBR_CON2 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VIBR_CON2 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VIBR_DUMMY_LOAD_ADDR MT6351_LDO_VIBR_CON2 +#define MT6351_PMIC_DA_QI_VIBR_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VIBR_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VCAMD_MODE_SET_ADDR MT6351_LDO_VCAMD_CON0 +#define MT6351_PMIC_RG_VCAMD_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VCAMD_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VCAMD_EN_ADDR MT6351_LDO_VCAMD_CON0 +#define MT6351_PMIC_RG_VCAMD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMD_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCAMD_MODE_CTRL_ADDR MT6351_LDO_VCAMD_CON0 +#define MT6351_PMIC_RG_VCAMD_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCAMD_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VCAMD_SRCLK_MODE_SEL_ADDR MT6351_LDO_VCAMD_CON0 +#define MT6351_PMIC_RG_VCAMD_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMD_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VCAMD_MODE_ADDR MT6351_LDO_VCAMD_CON0 +#define MT6351_PMIC_DA_QI_VCAMD_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMD_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VCAMD_STBTD_ADDR MT6351_LDO_VCAMD_CON0 +#define MT6351_PMIC_RG_VCAMD_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VCAMD_STBTD_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCAMD_STB_ADDR MT6351_LDO_VCAMD_CON0 +#define MT6351_PMIC_DA_QI_VCAMD_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMD_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VCAMD_EN_ADDR MT6351_LDO_VCAMD_CON0 +#define MT6351_PMIC_DA_QI_VCAMD_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMD_EN_SHIFT 15 +#define MT6351_PMIC_RG_VCAMD_OCFB_EN_ADDR MT6351_LDO_VCAMD_CON1 +#define MT6351_PMIC_RG_VCAMD_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMD_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCAMD_OCFB_EN_ADDR MT6351_LDO_VCAMD_CON1 +#define MT6351_PMIC_DA_QI_VCAMD_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMD_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_EN_ADDR MT6351_LDO_VCAMD_CON2 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VCAMD_CON2 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_ADDR MT6351_LDO_VCAMD_CON2 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VCAMD_CON2 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VCAMD_DUMMY_LOAD_ADDR MT6351_LDO_VCAMD_CON2 +#define MT6351_PMIC_DA_QI_VCAMD_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VCAMD_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VRF18_MODE_SET_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_RG_VRF18_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VRF18_EN_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_RG_VRF18_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_EN_SHIFT 1 +#define MT6351_PMIC_RG_VRF18_MODE_CTRL_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_RG_VRF18_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VRF18_ON_CTRL_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_RG_VRF18_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VRF18_SRCLK_MODE_SEL_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_RG_VRF18_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VRF18_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VRF18_MODE_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_DA_QI_VRF18_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRF18_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VRF18_STBTD_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_RG_VRF18_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VRF18_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VRF18_SRCLK_EN_SEL_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_RG_VRF18_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VRF18_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VRF18_STB_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_DA_QI_VRF18_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRF18_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VRF18_EN_ADDR MT6351_LDO_VRF18_CON0 +#define MT6351_PMIC_DA_QI_VRF18_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRF18_EN_SHIFT 15 +#define MT6351_PMIC_RG_VRF18_OCFB_EN_ADDR MT6351_LDO_VRF18_CON1 +#define MT6351_PMIC_RG_VRF18_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VRF18_OCFB_EN_ADDR MT6351_LDO_VRF18_CON1 +#define MT6351_PMIC_DA_QI_VRF18_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRF18_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_EN_ADDR MT6351_LDO_VRF18_CON2 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VRF18_CON2 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_ADDR MT6351_LDO_VRF18_CON2 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VRF18_CON2 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VRF18_DUMMY_LOAD_ADDR MT6351_LDO_VRF18_CON2 +#define MT6351_PMIC_DA_QI_VRF18_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VRF18_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VIO18_MODE_SET_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_RG_VIO18_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VIO18_EN_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_RG_VIO18_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_EN_SHIFT 1 +#define MT6351_PMIC_RG_VIO18_MODE_CTRL_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_RG_VIO18_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VIO18_ON_CTRL_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_RG_VIO18_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VIO18_SRCLK_MODE_SEL_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_RG_VIO18_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIO18_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VIO18_MODE_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_DA_QI_VIO18_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO18_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VIO18_STBTD_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_RG_VIO18_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VIO18_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VIO18_SRCLK_EN_SEL_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_RG_VIO18_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIO18_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VIO18_STB_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_DA_QI_VIO18_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO18_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VIO18_EN_ADDR MT6351_LDO_VIO18_CON0 +#define MT6351_PMIC_DA_QI_VIO18_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO18_EN_SHIFT 15 +#define MT6351_PMIC_RG_VIO18_OCFB_EN_ADDR MT6351_LDO_VIO18_CON1 +#define MT6351_PMIC_RG_VIO18_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VIO18_OCFB_EN_ADDR MT6351_LDO_VIO18_CON1 +#define MT6351_PMIC_DA_QI_VIO18_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO18_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_EN_ADDR MT6351_LDO_VIO18_CON2 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VIO18_CON2 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_ADDR MT6351_LDO_VIO18_CON2 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VIO18_CON2 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VIO18_DUMMY_LOAD_ADDR MT6351_LDO_VIO18_CON2 +#define MT6351_PMIC_DA_QI_VIO18_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VIO18_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VCN18_MODE_SET_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_RG_VCN18_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VCN18_EN_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_RG_VCN18_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCN18_MODE_CTRL_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_RG_VCN18_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VCN18_ON_CTRL_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_RG_VCN18_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VCN18_SRCLK_MODE_SEL_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_RG_VCN18_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN18_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VCN18_MODE_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_DA_QI_VCN18_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN18_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VCN18_STBTD_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_RG_VCN18_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VCN18_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VCN18_SRCLK_EN_SEL_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_RG_VCN18_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN18_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VCN18_STB_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_DA_QI_VCN18_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN18_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VCN18_EN_ADDR MT6351_LDO_VCN18_CON0 +#define MT6351_PMIC_DA_QI_VCN18_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN18_EN_SHIFT 15 +#define MT6351_PMIC_RG_VCN18_OCFB_EN_ADDR MT6351_LDO_VCN18_CON1 +#define MT6351_PMIC_RG_VCN18_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCN18_OCFB_EN_ADDR MT6351_LDO_VCN18_CON1 +#define MT6351_PMIC_DA_QI_VCN18_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN18_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_EN_ADDR MT6351_LDO_VCN18_CON2 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VCN18_CON2 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_ADDR MT6351_LDO_VCN18_CON2 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VCN18_CON2 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VCN18_DUMMY_LOAD_ADDR MT6351_LDO_VCN18_CON2 +#define MT6351_PMIC_DA_QI_VCN18_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VCN18_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VCAMIO_MODE_SET_ADDR MT6351_LDO_VCAMIO_CON0 +#define MT6351_PMIC_RG_VCAMIO_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VCAMIO_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VCAMIO_EN_ADDR MT6351_LDO_VCAMIO_CON0 +#define MT6351_PMIC_RG_VCAMIO_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMIO_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCAMIO_MODE_CTRL_ADDR MT6351_LDO_VCAMIO_CON0 +#define MT6351_PMIC_RG_VCAMIO_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCAMIO_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VCAMIO_SRCLK_MODE_SEL_ADDR MT6351_LDO_VCAMIO_CON0 +#define MT6351_PMIC_RG_VCAMIO_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMIO_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VCAMIO_MODE_ADDR MT6351_LDO_VCAMIO_CON0 +#define MT6351_PMIC_DA_QI_VCAMIO_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMIO_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VCAMIO_STBTD_ADDR MT6351_LDO_VCAMIO_CON0 +#define MT6351_PMIC_RG_VCAMIO_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VCAMIO_STBTD_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCAMIO_STB_ADDR MT6351_LDO_VCAMIO_CON0 +#define MT6351_PMIC_DA_QI_VCAMIO_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMIO_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VCAMIO_EN_ADDR MT6351_LDO_VCAMIO_CON0 +#define MT6351_PMIC_DA_QI_VCAMIO_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMIO_EN_SHIFT 15 +#define MT6351_PMIC_RG_VCAMIO_OCFB_EN_ADDR MT6351_LDO_VCAMIO_CON1 +#define MT6351_PMIC_RG_VCAMIO_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMIO_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCAMIO_OCFB_EN_ADDR MT6351_LDO_VCAMIO_CON1 +#define MT6351_PMIC_DA_QI_VCAMIO_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCAMIO_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_EN_ADDR MT6351_LDO_VCAMIO_CON2 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VCAMIO_CON2 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_ADDR MT6351_LDO_VCAMIO_CON2 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VCAMIO_CON2 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VCAMIO_DUMMY_LOAD_ADDR MT6351_LDO_VCAMIO_CON2 +#define MT6351_PMIC_DA_QI_VCAMIO_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VCAMIO_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VSRAM_PROC_MODE_SET_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_RG_VSRAM_PROC_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_PROC_EN_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_RG_VSRAM_PROC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_EN_SHIFT 1 +#define MT6351_PMIC_RG_VSRAM_PROC_MODE_CTRL_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_RG_VSRAM_PROC_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VSRAM_PROC_ON_CTRL_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_RG_VSRAM_PROC_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_MODE_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VSRAM_PROC_STBTD_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_RG_VSRAM_PROC_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_PROC_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_STB_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_EN_ADDR MT6351_LDO_VSRAM_PROC_CON0 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_EN_SHIFT 15 +#define MT6351_PMIC_RG_VSRAM_PROC_OCFB_EN_ADDR MT6351_LDO_VSRAM_PROC_CON1 +#define MT6351_PMIC_RG_VSRAM_PROC_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_OCFB_EN_ADDR MT6351_LDO_VSRAM_PROC_CON1 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN_ADDR MT6351_LDO_VSRAM_PROC_CON2 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VSRAM_PROC_CON2 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_ADDR MT6351_LDO_VSRAM_PROC_CON2 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VSRAM_PROC_CON2 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD_ADDR MT6351_LDO_VSRAM_PROC_CON2 +#define MT6351_PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VXO22_MODE_SET_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_RG_VXO22_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VXO22_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VXO22_EN_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_RG_VXO22_EN_MASK 0x1 +#define MT6351_PMIC_RG_VXO22_EN_SHIFT 1 +#define MT6351_PMIC_RG_VXO22_MODE_CTRL_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_RG_VXO22_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VXO22_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VXO22_ON_CTRL_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_RG_VXO22_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VXO22_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VXO22_SWITCH_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_RG_VXO22_SWITCH_MASK 0x1 +#define MT6351_PMIC_RG_VXO22_SWITCH_SHIFT 4 +#define MT6351_PMIC_RG_VXO22_SRCLK_MODE_SEL_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_RG_VXO22_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VXO22_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VXO22_MODE_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_DA_QI_VXO22_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VXO22_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VXO22_STBTD_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_RG_VXO22_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VXO22_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VXO22_SRCLK_EN_SEL_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_RG_VXO22_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VXO22_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VXO22_STB_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_DA_QI_VXO22_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VXO22_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VXO22_EN_ADDR MT6351_LDO_VXO22_CON0 +#define MT6351_PMIC_DA_QI_VXO22_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VXO22_EN_SHIFT 15 +#define MT6351_PMIC_RG_VXO22_OCFB_EN_ADDR MT6351_LDO_VXO22_CON1 +#define MT6351_PMIC_RG_VXO22_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VXO22_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VXO22_OCFB_EN_ADDR MT6351_LDO_VXO22_CON1 +#define MT6351_PMIC_DA_QI_VXO22_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VXO22_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VRF12_MODE_SET_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_RG_VRF12_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VRF12_EN_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_RG_VRF12_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_EN_SHIFT 1 +#define MT6351_PMIC_RG_VRF12_MODE_CTRL_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_RG_VRF12_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VRF12_ON_CTRL_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_RG_VRF12_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VRF12_SRCLK_MODE_SEL_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_RG_VRF12_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VRF12_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VRF12_MODE_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_DA_QI_VRF12_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRF12_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VRF12_STBTD_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_RG_VRF12_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VRF12_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VRF12_SRCLK_EN_SEL_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_RG_VRF12_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VRF12_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VRF12_STB_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_DA_QI_VRF12_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRF12_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VRF12_EN_ADDR MT6351_LDO_VRF12_CON0 +#define MT6351_PMIC_DA_QI_VRF12_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRF12_EN_SHIFT 15 +#define MT6351_PMIC_RG_VRF12_OCFB_EN_ADDR MT6351_LDO_VRF12_CON1 +#define MT6351_PMIC_RG_VRF12_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VRF12_OCFB_EN_ADDR MT6351_LDO_VRF12_CON1 +#define MT6351_PMIC_DA_QI_VRF12_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRF12_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_EN_ADDR MT6351_LDO_VRF12_CON2 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VRF12_CON2 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_ADDR MT6351_LDO_VRF12_CON2 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VRF12_CON2 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VRF12_DUMMY_LOAD_ADDR MT6351_LDO_VRF12_CON2 +#define MT6351_PMIC_DA_QI_VRF12_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VRF12_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VA10_MODE_SET_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_RG_VA10_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VA10_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VA10_EN_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_RG_VA10_EN_MASK 0x1 +#define MT6351_PMIC_RG_VA10_EN_SHIFT 1 +#define MT6351_PMIC_RG_VA10_MODE_CTRL_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_RG_VA10_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VA10_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VA10_ON_CTRL_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_RG_VA10_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VA10_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VA10_SRCLK_MODE_SEL_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_RG_VA10_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VA10_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VA10_MODE_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_DA_QI_VA10_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VA10_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VA10_STBTD_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_RG_VA10_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VA10_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VA10_SRCLK_EN_SEL_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_RG_VA10_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VA10_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VA10_STB_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_DA_QI_VA10_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VA10_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VA10_EN_ADDR MT6351_LDO_VA10_CON0 +#define MT6351_PMIC_DA_QI_VA10_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VA10_EN_SHIFT 15 +#define MT6351_PMIC_RG_VA10_OCFB_EN_ADDR MT6351_LDO_VA10_CON1 +#define MT6351_PMIC_RG_VA10_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VA10_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VA10_OCFB_EN_ADDR MT6351_LDO_VA10_CON1 +#define MT6351_PMIC_DA_QI_VA10_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VA10_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_EN_ADDR MT6351_LDO_VA10_CON2 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VA10_CON2 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_ADDR MT6351_LDO_VA10_CON2 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VA10_CON2 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VA10_DUMMY_LOAD_ADDR MT6351_LDO_VA10_CON2 +#define MT6351_PMIC_DA_QI_VA10_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VA10_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VDRAM_MODE_SET_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_RG_VDRAM_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VDRAM_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VDRAM_EN_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_RG_VDRAM_EN_MASK 0x1 +#define MT6351_PMIC_RG_VDRAM_EN_SHIFT 1 +#define MT6351_PMIC_RG_VDRAM_MODE_CTRL_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_RG_VDRAM_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VDRAM_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VDRAM_ON_CTRL_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_RG_VDRAM_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VDRAM_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VDRAM_SRCLK_MODE_SEL_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_RG_VDRAM_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VDRAM_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VDRAM_MODE_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_DA_QI_VDRAM_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VDRAM_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VDRAM_STBTD_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_RG_VDRAM_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VDRAM_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VDRAM_SRCLK_EN_SEL_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_RG_VDRAM_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VDRAM_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VDRAM_STB_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_DA_QI_VDRAM_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VDRAM_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VDRAM_EN_ADDR MT6351_LDO_VDRAM_CON0 +#define MT6351_PMIC_DA_QI_VDRAM_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VDRAM_EN_SHIFT 15 +#define MT6351_PMIC_RG_VDRAM_OCFB_EN_ADDR MT6351_LDO_VDRAM_CON1 +#define MT6351_PMIC_RG_VDRAM_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VDRAM_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VDRAM_OCFB_EN_ADDR MT6351_LDO_VDRAM_CON1 +#define MT6351_PMIC_DA_QI_VDRAM_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VDRAM_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_EN_ADDR MT6351_LDO_VDRAM_CON2 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VDRAM_CON2 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_ADDR MT6351_LDO_VDRAM_CON2 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VDRAM_CON2 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VDRAM_DUMMY_LOAD_ADDR MT6351_LDO_VDRAM_CON2 +#define MT6351_PMIC_DA_QI_VDRAM_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VDRAM_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VMIPI_MODE_SET_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_RG_VMIPI_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VMIPI_EN_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_RG_VMIPI_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_EN_SHIFT 1 +#define MT6351_PMIC_RG_VMIPI_MODE_CTRL_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_RG_VMIPI_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VMIPI_ON_CTRL_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_RG_VMIPI_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VMIPI_SRCLK_MODE_SEL_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_RG_VMIPI_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMIPI_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VMIPI_MODE_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_DA_QI_VMIPI_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMIPI_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VMIPI_STBTD_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_RG_VMIPI_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VMIPI_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VMIPI_SRCLK_EN_SEL_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_RG_VMIPI_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMIPI_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VMIPI_STB_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_DA_QI_VMIPI_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMIPI_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VMIPI_EN_ADDR MT6351_LDO_VMIPI_CON0 +#define MT6351_PMIC_DA_QI_VMIPI_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMIPI_EN_SHIFT 15 +#define MT6351_PMIC_RG_VMIPI_OCFB_EN_ADDR MT6351_LDO_VMIPI_CON1 +#define MT6351_PMIC_RG_VMIPI_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VMIPI_OCFB_EN_ADDR MT6351_LDO_VMIPI_CON1 +#define MT6351_PMIC_DA_QI_VMIPI_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMIPI_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_EN_ADDR MT6351_LDO_VMIPI_CON2 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VMIPI_CON2 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_ADDR MT6351_LDO_VMIPI_CON2 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VMIPI_CON2 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VMIPI_DUMMY_LOAD_ADDR MT6351_LDO_VMIPI_CON2 +#define MT6351_PMIC_DA_QI_VMIPI_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VMIPI_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VGP3_MODE_SET_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_RG_VGP3_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VGP3_EN_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_RG_VGP3_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_EN_SHIFT 1 +#define MT6351_PMIC_RG_VGP3_MODE_CTRL_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_RG_VGP3_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VGP3_ON_CTRL_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_RG_VGP3_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VGP3_SRCLK_MODE_SEL_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_RG_VGP3_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VGP3_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VGP3_MODE_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_DA_QI_VGP3_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VGP3_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VGP3_STBTD_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_RG_VGP3_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VGP3_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VGP3_SRCLK_EN_SEL_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_RG_VGP3_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VGP3_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VGP3_STB_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_DA_QI_VGP3_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VGP3_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VGP3_EN_ADDR MT6351_LDO_VGP3_CON0 +#define MT6351_PMIC_DA_QI_VGP3_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VGP3_EN_SHIFT 15 +#define MT6351_PMIC_RG_VGP3_OCFB_EN_ADDR MT6351_LDO_VGP3_CON1 +#define MT6351_PMIC_RG_VGP3_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VGP3_OCFB_EN_ADDR MT6351_LDO_VGP3_CON1 +#define MT6351_PMIC_DA_QI_VGP3_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VGP3_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_EN_ADDR MT6351_LDO_VGP3_CON2 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VGP3_CON2 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_ADDR MT6351_LDO_VGP3_CON2 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VGP3_CON2 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VGP3_DUMMY_LOAD_ADDR MT6351_LDO_VGP3_CON2 +#define MT6351_PMIC_DA_QI_VGP3_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VGP3_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VBIF28_MODE_SET_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_RG_VBIF28_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VBIF28_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VBIF28_EN_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_RG_VBIF28_EN_MASK 0x1 +#define MT6351_PMIC_RG_VBIF28_EN_SHIFT 1 +#define MT6351_PMIC_RG_VBIF28_MODE_CTRL_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_RG_VBIF28_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VBIF28_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VBIF28_ON_CTRL_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_RG_VBIF28_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VBIF28_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VBIF28_SRCLK_MODE_SEL_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_RG_VBIF28_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VBIF28_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VBIF28_MODE_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_DA_QI_VBIF28_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VBIF28_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VBIF28_STBTD_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_RG_VBIF28_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VBIF28_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VBIF28_SRCLK_EN_SEL_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_RG_VBIF28_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VBIF28_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VBIF28_STB_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_DA_QI_VBIF28_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VBIF28_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VBIF28_EN_ADDR MT6351_LDO_VBIF28_CON0 +#define MT6351_PMIC_DA_QI_VBIF28_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VBIF28_EN_SHIFT 15 +#define MT6351_PMIC_RG_VBIF28_OCFB_EN_ADDR MT6351_LDO_VBIF28_CON1 +#define MT6351_PMIC_RG_VBIF28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VBIF28_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VBIF28_OCFB_EN_ADDR MT6351_LDO_VBIF28_CON1 +#define MT6351_PMIC_DA_QI_VBIF28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VBIF28_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_EN_ADDR MT6351_LDO_VBIF28_CON2 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VBIF28_CON2 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_ADDR MT6351_LDO_VBIF28_CON2 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VBIF28_CON2 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VBIF28_DUMMY_LOAD_ADDR MT6351_LDO_VBIF28_CON2 +#define MT6351_PMIC_DA_QI_VBIF28_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VBIF28_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VEFUSE_MODE_SET_ADDR MT6351_LDO_VEFUSE_CON0 +#define MT6351_PMIC_RG_VEFUSE_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VEFUSE_EN_ADDR MT6351_LDO_VEFUSE_CON0 +#define MT6351_PMIC_RG_VEFUSE_EN_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_EN_SHIFT 1 +#define MT6351_PMIC_RG_VEFUSE_MODE_CTRL_ADDR MT6351_LDO_VEFUSE_CON0 +#define MT6351_PMIC_RG_VEFUSE_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VEFUSE_SRCLK_MODE_SEL_ADDR MT6351_LDO_VEFUSE_CON0 +#define MT6351_PMIC_RG_VEFUSE_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VEFUSE_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VEFUSE_MODE_ADDR MT6351_LDO_VEFUSE_CON0 +#define MT6351_PMIC_DA_QI_VEFUSE_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VEFUSE_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VEFUSE_STBTD_ADDR MT6351_LDO_VEFUSE_CON0 +#define MT6351_PMIC_RG_VEFUSE_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VEFUSE_STBTD_SHIFT 9 +#define MT6351_PMIC_DA_QI_VEFUSE_STB_ADDR MT6351_LDO_VEFUSE_CON0 +#define MT6351_PMIC_DA_QI_VEFUSE_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VEFUSE_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VEFUSE_EN_ADDR MT6351_LDO_VEFUSE_CON0 +#define MT6351_PMIC_DA_QI_VEFUSE_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VEFUSE_EN_SHIFT 15 +#define MT6351_PMIC_RG_VEFUSE_OCFB_EN_ADDR MT6351_LDO_VEFUSE_CON1 +#define MT6351_PMIC_RG_VEFUSE_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VEFUSE_OCFB_EN_ADDR MT6351_LDO_VEFUSE_CON1 +#define MT6351_PMIC_DA_QI_VEFUSE_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VEFUSE_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_EN_ADDR MT6351_LDO_VEFUSE_CON2 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VEFUSE_CON2 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_ADDR MT6351_LDO_VEFUSE_CON2 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VEFUSE_CON2 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VEFUSE_DUMMY_LOAD_ADDR MT6351_LDO_VEFUSE_CON2 +#define MT6351_PMIC_DA_QI_VEFUSE_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VEFUSE_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VCN33_MODE_SET_ADDR MT6351_LDO_VCN33_CON0 +#define MT6351_PMIC_RG_VCN33_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VCN33_MODE_CTRL_ADDR MT6351_LDO_VCN33_CON0 +#define MT6351_PMIC_RG_VCN33_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VCN33_SRCLK_MODE_SEL_ADDR MT6351_LDO_VCN33_CON0 +#define MT6351_PMIC_RG_VCN33_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN33_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VCN33_MODE_ADDR MT6351_LDO_VCN33_CON0 +#define MT6351_PMIC_DA_QI_VCN33_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN33_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VCN33_STBTD_ADDR MT6351_LDO_VCN33_CON0 +#define MT6351_PMIC_RG_VCN33_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VCN33_STBTD_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCN33_STB_ADDR MT6351_LDO_VCN33_CON0 +#define MT6351_PMIC_DA_QI_VCN33_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN33_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VCN33_EN_ADDR MT6351_LDO_VCN33_CON0 +#define MT6351_PMIC_DA_QI_VCN33_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN33_EN_SHIFT 15 +#define MT6351_PMIC_RG_VCN33_OCFB_EN_ADDR MT6351_LDO_VCN33_CON1 +#define MT6351_PMIC_RG_VCN33_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VCN33_OCFB_EN_ADDR MT6351_LDO_VCN33_CON1 +#define MT6351_PMIC_DA_QI_VCN33_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VCN33_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_EN_ADDR MT6351_LDO_VCN33_CON2 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VCN33_CON2 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_ADDR MT6351_LDO_VCN33_CON2 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VCN33_CON2 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VCN33_DUMMY_LOAD_ADDR MT6351_LDO_VCN33_CON2 +#define MT6351_PMIC_DA_QI_VCN33_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VCN33_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VCN33_EN_BT_ADDR MT6351_LDO_VCN33_CON3 +#define MT6351_PMIC_RG_VCN33_EN_BT_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_EN_BT_SHIFT 1 +#define MT6351_PMIC_RG_VCN33_ON_CTRL_BT_ADDR MT6351_LDO_VCN33_CON3 +#define MT6351_PMIC_RG_VCN33_ON_CTRL_BT_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_ON_CTRL_BT_SHIFT 3 +#define MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_BT_ADDR MT6351_LDO_VCN33_CON3 +#define MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_BT_MASK 0x7 +#define MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_BT_SHIFT 11 +#define MT6351_PMIC_RG_VCN33_EN_WIFI_ADDR MT6351_LDO_VCN33_CON4 +#define MT6351_PMIC_RG_VCN33_EN_WIFI_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_EN_WIFI_SHIFT 1 +#define MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI_ADDR MT6351_LDO_VCN33_CON4 +#define MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI_SHIFT 3 +#define MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI_ADDR MT6351_LDO_VCN33_CON4 +#define MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI_MASK 0x7 +#define MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI_SHIFT 11 +#define MT6351_PMIC_RG_VLDO28_MODE_SET_ADDR MT6351_LDO_VLDO28_CON0 +#define MT6351_PMIC_RG_VLDO28_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VLDO28_MODE_CTRL_ADDR MT6351_LDO_VLDO28_CON0 +#define MT6351_PMIC_RG_VLDO28_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_ADDR MT6351_LDO_VLDO28_CON0 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VLDO28_SRCLK_MODE_SEL_ADDR MT6351_LDO_VLDO28_CON0 +#define MT6351_PMIC_RG_VLDO28_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VLDO28_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VLDO28_MODE_ADDR MT6351_LDO_VLDO28_CON0 +#define MT6351_PMIC_DA_QI_VLDO28_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VLDO28_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VLDO28_STBTD_ADDR MT6351_LDO_VLDO28_CON0 +#define MT6351_PMIC_RG_VLDO28_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VLDO28_STBTD_SHIFT 9 +#define MT6351_PMIC_DA_QI_VLDO28_STB_ADDR MT6351_LDO_VLDO28_CON0 +#define MT6351_PMIC_DA_QI_VLDO28_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VLDO28_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VLDO28_EN_ADDR MT6351_LDO_VLDO28_CON0 +#define MT6351_PMIC_DA_QI_VLDO28_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VLDO28_EN_SHIFT 15 +#define MT6351_PMIC_RG_VLDO28_OCFB_EN_ADDR MT6351_LDO_VLDO28_CON1 +#define MT6351_PMIC_RG_VLDO28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VLDO28_OCFB_EN_ADDR MT6351_LDO_VLDO28_CON1 +#define MT6351_PMIC_DA_QI_VLDO28_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VLDO28_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_EN_ADDR MT6351_LDO_VLDO28_CON2 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VLDO28_CON2 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_ADDR MT6351_LDO_VLDO28_CON2 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VLDO28_CON2 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VLDO28_DUMMY_LOAD_ADDR MT6351_LDO_VLDO28_CON2 +#define MT6351_PMIC_DA_QI_VLDO28_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VLDO28_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VLDO28_EN_0_ADDR MT6351_LDO_VLDO28_CON3 +#define MT6351_PMIC_RG_VLDO28_EN_0_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_EN_0_SHIFT 1 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_0_ADDR MT6351_LDO_VLDO28_CON3 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_0_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_0_SHIFT 3 +#define MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_0_ADDR MT6351_LDO_VLDO28_CON3 +#define MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_0_MASK 0x7 +#define MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_0_SHIFT 11 +#define MT6351_PMIC_RG_VLDO28_EN_1_ADDR MT6351_LDO_VLDO28_CON4 +#define MT6351_PMIC_RG_VLDO28_EN_1_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_EN_1_SHIFT 1 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_1_ADDR MT6351_LDO_VLDO28_CON4 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_1_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_ON_CTRL_1_SHIFT 3 +#define MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_1_ADDR MT6351_LDO_VLDO28_CON4 +#define MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_1_MASK 0x7 +#define MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_1_SHIFT 11 +#define MT6351_PMIC_RG_LDO_RSV1_ADDR MT6351_LDO_RSV_CON0 +#define MT6351_PMIC_RG_LDO_RSV1_MASK 0x3FF +#define MT6351_PMIC_RG_LDO_RSV1_SHIFT 0 +#define MT6351_PMIC_RG_LDO_RSV0_ADDR MT6351_LDO_RSV_CON0 +#define MT6351_PMIC_RG_LDO_RSV0_MASK 0x3F +#define MT6351_PMIC_RG_LDO_RSV0_SHIFT 10 +#define MT6351_PMIC_RG_LDO_RSV2_ADDR MT6351_LDO_RSV_CON1 +#define MT6351_PMIC_RG_LDO_RSV2_MASK 0xFFFF +#define MT6351_PMIC_RG_LDO_RSV2_SHIFT 0 +#define MT6351_PMIC_RG_VMC_MODE_SET_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_RG_VMC_MODE_SET_MASK 0x1 +#define MT6351_PMIC_RG_VMC_MODE_SET_SHIFT 0 +#define MT6351_PMIC_RG_VMC_EN_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_RG_VMC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMC_EN_SHIFT 1 +#define MT6351_PMIC_RG_VMC_MODE_CTRL_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_RG_VMC_MODE_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMC_MODE_CTRL_SHIFT 2 +#define MT6351_PMIC_RG_VMC_ON_CTRL_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_RG_VMC_ON_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMC_ON_CTRL_SHIFT 3 +#define MT6351_PMIC_RG_VMC_SRCLK_MODE_SEL_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_RG_VMC_SRCLK_MODE_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMC_SRCLK_MODE_SEL_SHIFT 5 +#define MT6351_PMIC_DA_QI_VMC_MODE_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_DA_QI_VMC_MODE_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMC_MODE_SHIFT 8 +#define MT6351_PMIC_RG_VMC_STBTD_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_RG_VMC_STBTD_MASK 0x3 +#define MT6351_PMIC_RG_VMC_STBTD_SHIFT 9 +#define MT6351_PMIC_RG_VMC_SRCLK_EN_SEL_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_RG_VMC_SRCLK_EN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMC_SRCLK_EN_SEL_SHIFT 11 +#define MT6351_PMIC_DA_QI_VMC_STB_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_DA_QI_VMC_STB_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMC_STB_SHIFT 14 +#define MT6351_PMIC_DA_QI_VMC_EN_ADDR MT6351_LDO_VMC_CON0 +#define MT6351_PMIC_DA_QI_VMC_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMC_EN_SHIFT 15 +#define MT6351_PMIC_RG_VMC_OCFB_EN_ADDR MT6351_LDO_VMC_CON1 +#define MT6351_PMIC_RG_VMC_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMC_OCFB_EN_SHIFT 9 +#define MT6351_PMIC_DA_QI_VMC_OCFB_EN_ADDR MT6351_LDO_VMC_CON1 +#define MT6351_PMIC_DA_QI_VMC_OCFB_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMC_OCFB_EN_SHIFT 10 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_EN_ADDR MT6351_LDO_VMC_CON2 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_EN_SHIFT 0 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_CTRL_ADDR MT6351_LDO_VMC_CON2 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_ADDR MT6351_LDO_VMC_CON2 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_MASK 0x7 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_SHIFT 4 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL_ADDR MT6351_LDO_VMC_CON2 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL_MASK 0x7 +#define MT6351_PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL_SHIFT 8 +#define MT6351_PMIC_DA_QI_VMC_DUMMY_LOAD_ADDR MT6351_LDO_VMC_CON2 +#define MT6351_PMIC_DA_QI_VMC_DUMMY_LOAD_MASK 0x1F +#define MT6351_PMIC_DA_QI_VMC_DUMMY_LOAD_SHIFT 11 +#define MT6351_PMIC_RG_VMC_TRANS_EN_ADDR MT6351_LDO_VMC_CON3 +#define MT6351_PMIC_RG_VMC_TRANS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMC_TRANS_EN_SHIFT 0 +#define MT6351_PMIC_RG_VMC_TRANS_CTRL_ADDR MT6351_LDO_VMC_CON3 +#define MT6351_PMIC_RG_VMC_TRANS_CTRL_MASK 0x3 +#define MT6351_PMIC_RG_VMC_TRANS_CTRL_SHIFT 1 +#define MT6351_PMIC_RG_VMC_TRANS_ONCE_ADDR MT6351_LDO_VMC_CON3 +#define MT6351_PMIC_RG_VMC_TRANS_ONCE_MASK 0x1 +#define MT6351_PMIC_RG_VMC_TRANS_ONCE_SHIFT 3 +#define MT6351_PMIC_RG_VMC_INT_DIS_SEL_ADDR MT6351_LDO_VMC_CON3 +#define MT6351_PMIC_RG_VMC_INT_DIS_SEL_MASK 0x3 +#define MT6351_PMIC_RG_VMC_INT_DIS_SEL_SHIFT 4 +#define MT6351_PMIC_DA_QI_VMC_INT_DIS_ADDR MT6351_LDO_VMC_CON3 +#define MT6351_PMIC_DA_QI_VMC_INT_DIS_MASK 0x1 +#define MT6351_PMIC_DA_QI_VMC_INT_DIS_SHIFT 15 +#define MT6351_PMIC_RG_LDO_MANUAL_OFS_SEL_ADDR MT6351_LDO_K_CON0 +#define MT6351_PMIC_RG_LDO_MANUAL_OFS_SEL_MASK 0x1F +#define MT6351_PMIC_RG_LDO_MANUAL_OFS_SEL_SHIFT 0 +#define MT6351_PMIC_RG_LDO_MANUAL_OFS_EN_ADDR MT6351_LDO_K_CON0 +#define MT6351_PMIC_RG_LDO_MANUAL_OFS_EN_MASK 0x1 +#define MT6351_PMIC_RG_LDO_MANUAL_OFS_EN_SHIFT 7 +#define MT6351_PMIC_RG_LDO_CALI_RSV_ADDR MT6351_LDO_K_CON0 +#define MT6351_PMIC_RG_LDO_CALI_RSV_MASK 0x1F +#define MT6351_PMIC_RG_LDO_CALI_RSV_SHIFT 8 +#define MT6351_PMIC_RG_LDO_CALI_MODE_SEL_ADDR MT6351_LDO_K_CON0 +#define MT6351_PMIC_RG_LDO_CALI_MODE_SEL_MASK 0x1 +#define MT6351_PMIC_RG_LDO_CALI_MODE_SEL_SHIFT 13 +#define MT6351_PMIC_RG_LDO_MANUAL_MODE_ADDR MT6351_LDO_K_CON0 +#define MT6351_PMIC_RG_LDO_MANUAL_MODE_MASK 0x1 +#define MT6351_PMIC_RG_LDO_MANUAL_MODE_SHIFT 14 +#define MT6351_PMIC_RG_LDO_AUTO_START_ADDR MT6351_LDO_K_CON0 +#define MT6351_PMIC_RG_LDO_AUTO_START_MASK 0x1 +#define MT6351_PMIC_RG_LDO_AUTO_START_SHIFT 15 +#define MT6351_PMIC_RG_LDO_CALI_CLR_ADDR MT6351_LDO_K_CON1 +#define MT6351_PMIC_RG_LDO_CALI_CLR_MASK 0x1 +#define MT6351_PMIC_RG_LDO_CALI_CLR_SHIFT 0 +#define MT6351_PMIC_LDO_CALI_INC_COUNT_ADDR MT6351_LDO_K_CON1 +#define MT6351_PMIC_LDO_CALI_INC_COUNT_MASK 0x3 +#define MT6351_PMIC_LDO_CALI_INC_COUNT_SHIFT 1 +#define MT6351_PMIC_LDO_K_START_ADDR MT6351_LDO_K_CON1 +#define MT6351_PMIC_LDO_K_START_MASK 0x1 +#define MT6351_PMIC_LDO_K_START_SHIFT 3 +#define MT6351_PMIC_LDO_CALI_DONE_ADDR MT6351_LDO_K_CON1 +#define MT6351_PMIC_LDO_CALI_DONE_MASK 0x1 +#define MT6351_PMIC_LDO_CALI_DONE_SHIFT 4 +#define MT6351_PMIC_LDO_CALI_CNT_ADDR MT6351_LDO_K_CON1 +#define MT6351_PMIC_LDO_CALI_CNT_MASK 0x7 +#define MT6351_PMIC_LDO_CALI_CNT_SHIFT 5 +#define MT6351_PMIC_LDO_CALI_EFUSE_EN_ADDR MT6351_LDO_K_CON1 +#define MT6351_PMIC_LDO_CALI_EFUSE_EN_MASK 0x1 +#define MT6351_PMIC_LDO_CALI_EFUSE_EN_SHIFT 8 +#define MT6351_PMIC_DA_QI_VIO18_OFS_CAL_EN_ADDR MT6351_LDO_K_CON2 +#define MT6351_PMIC_DA_QI_VIO18_OFS_CAL_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VIO18_OFS_CAL_EN_SHIFT 0 +#define MT6351_PMIC_AD_QI_VIO18_CAL_INDI_ADDR MT6351_LDO_K_CON2 +#define MT6351_PMIC_AD_QI_VIO18_CAL_INDI_MASK 0x1 +#define MT6351_PMIC_AD_QI_VIO18_CAL_INDI_SHIFT 1 +#define MT6351_PMIC_DA_QI_VIO18_OFS_SEL_ADDR MT6351_LDO_K_CON2 +#define MT6351_PMIC_DA_QI_VIO18_OFS_SEL_MASK 0x1F +#define MT6351_PMIC_DA_QI_VIO18_OFS_SEL_SHIFT 11 +#define MT6351_PMIC_LDO_DEGTD_SEL_ADDR MT6351_LDO_OCFB0 +#define MT6351_PMIC_LDO_DEGTD_SEL_MASK 0x3 +#define MT6351_PMIC_LDO_DEGTD_SEL_SHIFT 14 +#define MT6351_PMIC_RG_VRTC_EN_ADDR MT6351_VRTC_CON0 +#define MT6351_PMIC_RG_VRTC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRTC_EN_SHIFT 1 +#define MT6351_PMIC_DA_QI_VRTC_EN_ADDR MT6351_VRTC_CON0 +#define MT6351_PMIC_DA_QI_VRTC_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_VRTC_EN_SHIFT 15 +#define MT6351_PMIC_RG_ALDO_RESEV_ADDR MT6351_ALDO_ANA_CON0 +#define MT6351_PMIC_RG_ALDO_RESEV_MASK 0x7F +#define MT6351_PMIC_RG_ALDO_RESEV_SHIFT 0 +#define MT6351_PMIC_RG_DLDO_RESEV_ADDR MT6351_DLDO_ANA_CON0 +#define MT6351_PMIC_RG_DLDO_RESEV_MASK 0xFF +#define MT6351_PMIC_RG_DLDO_RESEV_SHIFT 0 +#define MT6351_PMIC_RG_SLDO_RESEV195_ADDR MT6351_SLDO20_ANA_CON0 +#define MT6351_PMIC_RG_SLDO_RESEV195_MASK 0x7F +#define MT6351_PMIC_RG_SLDO_RESEV195_SHIFT 0 +#define MT6351_PMIC_RG_SLDO_2_RESEV195_ADDR MT6351_SLDO20_ANA_CON0 +#define MT6351_PMIC_RG_SLDO_2_RESEV195_MASK 0x7F +#define MT6351_PMIC_RG_SLDO_2_RESEV195_SHIFT 7 +#define MT6351_PMIC_RG_SLDO_RESEV135_ADDR MT6351_SLDO14_ANA_CON0 +#define MT6351_PMIC_RG_SLDO_RESEV135_MASK 0x7F +#define MT6351_PMIC_RG_SLDO_RESEV135_SHIFT 0 +#define MT6351_PMIC_RG_SLDO_2_RESEV135_ADDR MT6351_SLDO14_ANA_CON0 +#define MT6351_PMIC_RG_SLDO_2_RESEV135_MASK 0x7F +#define MT6351_PMIC_RG_SLDO_2_RESEV135_SHIFT 7 +#define MT6351_PMIC_RG_VXO22_CAL_ADDR MT6351_VXO22_ANA_CON0 +#define MT6351_PMIC_RG_VXO22_CAL_MASK 0xF +#define MT6351_PMIC_RG_VXO22_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VXO22_VOSEL_ADDR MT6351_VXO22_ANA_CON0 +#define MT6351_PMIC_RG_VXO22_VOSEL_MASK 0x3 +#define MT6351_PMIC_RG_VXO22_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VXO22_NDIS_EN_ADDR MT6351_VXO22_ANA_CON0 +#define MT6351_PMIC_RG_VXO22_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VXO22_NDIS_EN_SHIFT 11 +#define MT6351_PMIC_RG_VTCXO28_CAL_ADDR MT6351_VTCXO28_ANA_CON0 +#define MT6351_PMIC_RG_VTCXO28_CAL_MASK 0xF +#define MT6351_PMIC_RG_VTCXO28_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VTCXO28_VOSEL_ADDR MT6351_VTCXO28_ANA_CON0 +#define MT6351_PMIC_RG_VTCXO28_VOSEL_MASK 0x3 +#define MT6351_PMIC_RG_VTCXO28_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VTCXO28_NDIS_EN_ADDR MT6351_VTCXO28_ANA_CON0 +#define MT6351_PMIC_RG_VTCXO28_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO28_NDIS_EN_SHIFT 11 +#define MT6351_PMIC_RG_VTCXO24_CAL_ADDR MT6351_VTCXO24_ANA_CON0 +#define MT6351_PMIC_RG_VTCXO24_CAL_MASK 0xF +#define MT6351_PMIC_RG_VTCXO24_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VTCXO24_VOSEL_ADDR MT6351_VTCXO24_ANA_CON0 +#define MT6351_PMIC_RG_VTCXO24_VOSEL_MASK 0x3 +#define MT6351_PMIC_RG_VTCXO24_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VTCXO24_NDIS_EN_ADDR MT6351_VTCXO24_ANA_CON0 +#define MT6351_PMIC_RG_VTCXO24_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VTCXO24_NDIS_EN_SHIFT 11 +#define MT6351_PMIC_RG_VBIF28_CAL_ADDR MT6351_VBIF28_ANA_CON0 +#define MT6351_PMIC_RG_VBIF28_CAL_MASK 0xF +#define MT6351_PMIC_RG_VBIF28_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VBIF28_VOSEL_ADDR MT6351_VBIF28_ANA_CON0 +#define MT6351_PMIC_RG_VBIF28_VOSEL_MASK 0x3 +#define MT6351_PMIC_RG_VBIF28_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VBIF28_NDIS_EN_ADDR MT6351_VBIF28_ANA_CON0 +#define MT6351_PMIC_RG_VBIF28_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VBIF28_NDIS_EN_SHIFT 11 +#define MT6351_PMIC_RG_VCN28_CAL_ADDR MT6351_VCN28_ANA_CON0 +#define MT6351_PMIC_RG_VCN28_CAL_MASK 0xF +#define MT6351_PMIC_RG_VCN28_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VCN28_VOSEL_ADDR MT6351_VCN28_ANA_CON0 +#define MT6351_PMIC_RG_VCN28_VOSEL_MASK 0x3 +#define MT6351_PMIC_RG_VCN28_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VCN28_NDIS_EN_ADDR MT6351_VCN28_ANA_CON0 +#define MT6351_PMIC_RG_VCN28_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN28_NDIS_EN_SHIFT 11 +#define MT6351_PMIC_RG_VMCH_CAL_ADDR MT6351_VMCH_ANA_CON0 +#define MT6351_PMIC_RG_VMCH_CAL_MASK 0x1F +#define MT6351_PMIC_RG_VMCH_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VMCH_VOSEL_ADDR MT6351_VMCH_ANA_CON0 +#define MT6351_PMIC_RG_VMCH_VOSEL_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VMCH_NDIS_EN_ADDR MT6351_VMCH_ANA_CON1 +#define MT6351_PMIC_RG_VMCH_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VMCH_OC_TRIM_ADDR MT6351_VMCH_ANA_CON1 +#define MT6351_PMIC_RG_VMCH_OC_TRIM_MASK 0x3F +#define MT6351_PMIC_RG_VMCH_OC_TRIM_SHIFT 2 +#define MT6351_PMIC_RG_VMCH_N2LP_EHC_V18_ADDR MT6351_VMCH_ANA_CON1 +#define MT6351_PMIC_RG_VMCH_N2LP_EHC_V18_MASK 0x1 +#define MT6351_PMIC_RG_VMCH_N2LP_EHC_V18_SHIFT 8 +#define MT6351_PMIC_RG_VEMC_CAL_ADDR MT6351_VEMC_ANA_CON0 +#define MT6351_PMIC_RG_VEMC_CAL_MASK 0x1F +#define MT6351_PMIC_RG_VEMC_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VEMC_VOSEL_ADDR MT6351_VEMC_ANA_CON0 +#define MT6351_PMIC_RG_VEMC_VOSEL_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VEMC_NDIS_EN_ADDR MT6351_VEMC_ANA_CON1 +#define MT6351_PMIC_RG_VEMC_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VEMC_OC_TRIM_ADDR MT6351_VEMC_ANA_CON1 +#define MT6351_PMIC_RG_VEMC_OC_TRIM_MASK 0x3F +#define MT6351_PMIC_RG_VEMC_OC_TRIM_SHIFT 2 +#define MT6351_PMIC_RG_VEMC_N2LP_EHC_V18_ADDR MT6351_VEMC_ANA_CON1 +#define MT6351_PMIC_RG_VEMC_N2LP_EHC_V18_MASK 0x1 +#define MT6351_PMIC_RG_VEMC_N2LP_EHC_V18_SHIFT 8 +#define MT6351_PMIC_RG_VCAMA_CAL_ADDR MT6351_VCAMA_ANA_CON0 +#define MT6351_PMIC_RG_VCAMA_CAL_MASK 0xF +#define MT6351_PMIC_RG_VCAMA_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VCAMA_VOSEL_ADDR MT6351_VCAMA_ANA_CON0 +#define MT6351_PMIC_RG_VCAMA_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMA_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VCAMA_NDIS_EN_ADDR MT6351_VCAMA_ANA_CON1 +#define MT6351_PMIC_RG_VCAMA_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMA_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCAMA_FBSEL_ADDR MT6351_VCAMA_ANA_CON1 +#define MT6351_PMIC_RG_VCAMA_FBSEL_MASK 0x3 +#define MT6351_PMIC_RG_VCAMA_FBSEL_SHIFT 2 +#define MT6351_PMIC_RG_VCN33_CAL_ADDR MT6351_VCN33_ANA_CON0 +#define MT6351_PMIC_RG_VCN33_CAL_MASK 0x1F +#define MT6351_PMIC_RG_VCN33_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VCN33_VOSEL_ADDR MT6351_VCN33_ANA_CON0 +#define MT6351_PMIC_RG_VCN33_VOSEL_MASK 0x3 +#define MT6351_PMIC_RG_VCN33_VOSEL_SHIFT 9 +#define MT6351_PMIC_RG_VCN33_NDIS_EN_ADDR MT6351_VCN33_ANA_CON1 +#define MT6351_PMIC_RG_VCN33_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCN33_N2LP_EHC_V18_ADDR MT6351_VCN33_ANA_CON1 +#define MT6351_PMIC_RG_VCN33_N2LP_EHC_V18_MASK 0x1 +#define MT6351_PMIC_RG_VCN33_N2LP_EHC_V18_SHIFT 2 +#define MT6351_PMIC_RG_VIO28_CAL_ADDR MT6351_VIO28_ANA_CON0 +#define MT6351_PMIC_RG_VIO28_CAL_MASK 0xF +#define MT6351_PMIC_RG_VIO28_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VIO28_VOSEL_ADDR MT6351_VIO28_ANA_CON0 +#define MT6351_PMIC_RG_VIO28_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VIO28_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VIO28_NDIS_EN_ADDR MT6351_VIO28_ANA_CON1 +#define MT6351_PMIC_RG_VIO28_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VIO28_LP_HIGH_SPEED_ENB_ADDR MT6351_VIO28_ANA_CON1 +#define MT6351_PMIC_RG_VIO28_LP_HIGH_SPEED_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VIO28_LP_HIGH_SPEED_ENB_SHIFT 2 +#define MT6351_PMIC_RG_VMC_CAL_ADDR MT6351_VMC_ANA_CON0 +#define MT6351_PMIC_RG_VMC_CAL_MASK 0x1F +#define MT6351_PMIC_RG_VMC_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VMC_VOSEL_ADDR MT6351_VMC_ANA_CON0 +#define MT6351_PMIC_RG_VMC_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VMC_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VMC_NDIS_EN_ADDR MT6351_VMC_ANA_CON1 +#define MT6351_PMIC_RG_VMC_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMC_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VMC_LP_HIGH_SPEED_ENB_ADDR MT6351_VMC_ANA_CON1 +#define MT6351_PMIC_RG_VMC_LP_HIGH_SPEED_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VMC_LP_HIGH_SPEED_ENB_SHIFT 2 +#define MT6351_PMIC_RG_VIBR_CAL_ADDR MT6351_VIBR_ANA_CON0 +#define MT6351_PMIC_RG_VIBR_CAL_MASK 0xF +#define MT6351_PMIC_RG_VIBR_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VIBR_VOSEL_ADDR MT6351_VIBR_ANA_CON0 +#define MT6351_PMIC_RG_VIBR_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VIBR_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VIBR_NDIS_EN_ADDR MT6351_VIBR_ANA_CON1 +#define MT6351_PMIC_RG_VIBR_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VIBR_LP_HIGH_SPEED_ENB_ADDR MT6351_VIBR_ANA_CON1 +#define MT6351_PMIC_RG_VIBR_LP_HIGH_SPEED_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VIBR_LP_HIGH_SPEED_ENB_SHIFT 2 +#define MT6351_PMIC_RG_VUSB33_CAL_ADDR MT6351_VUSB33_ANA_CON0 +#define MT6351_PMIC_RG_VUSB33_CAL_MASK 0xF +#define MT6351_PMIC_RG_VUSB33_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VUSB33_NDIS_EN_ADDR MT6351_VUSB33_ANA_CON1 +#define MT6351_PMIC_RG_VUSB33_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VUSB33_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VUSB33_OC_TRIM_ADDR MT6351_VUSB33_ANA_CON1 +#define MT6351_PMIC_RG_VUSB33_OC_TRIM_MASK 0x3F +#define MT6351_PMIC_RG_VUSB33_OC_TRIM_SHIFT 2 +#define MT6351_PMIC_RG_VSIM1_CAL_ADDR MT6351_VSIM1_ANA_CON0 +#define MT6351_PMIC_RG_VSIM1_CAL_MASK 0xF +#define MT6351_PMIC_RG_VSIM1_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VSIM1_VOSEL_ADDR MT6351_VSIM1_ANA_CON0 +#define MT6351_PMIC_RG_VSIM1_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VSIM1_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VSIM1_NDIS_EN_ADDR MT6351_VSIM1_ANA_CON1 +#define MT6351_PMIC_RG_VSIM1_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VSIM1_STB_CAL_ADDR MT6351_VSIM1_ANA_CON1 +#define MT6351_PMIC_RG_VSIM1_STB_CAL_MASK 0x3 +#define MT6351_PMIC_RG_VSIM1_STB_CAL_SHIFT 6 +#define MT6351_PMIC_RG_VSIM1_STB_SEL_ADDR MT6351_VSIM1_ANA_CON1 +#define MT6351_PMIC_RG_VSIM1_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_STB_SEL_SHIFT 8 +#define MT6351_PMIC_RG_VSIM1_OC_TRIM_ADDR MT6351_VSIM1_ANA_CON1 +#define MT6351_PMIC_RG_VSIM1_OC_TRIM_MASK 0xF +#define MT6351_PMIC_RG_VSIM1_OC_TRIM_SHIFT 9 +#define MT6351_PMIC_RG_VSIM1_NDIS_EN_INT_ADDR MT6351_VSIM1_ANA_CON1 +#define MT6351_PMIC_RG_VSIM1_NDIS_EN_INT_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_NDIS_EN_INT_SHIFT 13 +#define MT6351_PMIC_RG_EFUSE_SIM1_MODE_ADDR MT6351_VSIM1_ANA_CON1 +#define MT6351_PMIC_RG_EFUSE_SIM1_MODE_MASK 0x1 +#define MT6351_PMIC_RG_EFUSE_SIM1_MODE_SHIFT 14 +#define MT6351_PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB_ADDR MT6351_VSIM1_ANA_CON1 +#define MT6351_PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB_SHIFT 15 +#define MT6351_PMIC_RG_VSIM2_CAL_ADDR MT6351_VSIM2_ANA_CON0 +#define MT6351_PMIC_RG_VSIM2_CAL_MASK 0xF +#define MT6351_PMIC_RG_VSIM2_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VSIM2_VOSEL_ADDR MT6351_VSIM2_ANA_CON0 +#define MT6351_PMIC_RG_VSIM2_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VSIM2_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VSIM2_NDIS_EN_ADDR MT6351_VSIM2_ANA_CON1 +#define MT6351_PMIC_RG_VSIM2_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VSIM2_STB_CAL_ADDR MT6351_VSIM2_ANA_CON1 +#define MT6351_PMIC_RG_VSIM2_STB_CAL_MASK 0x3 +#define MT6351_PMIC_RG_VSIM2_STB_CAL_SHIFT 6 +#define MT6351_PMIC_RG_VSIM2_STB_SEL_ADDR MT6351_VSIM2_ANA_CON1 +#define MT6351_PMIC_RG_VSIM2_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_STB_SEL_SHIFT 8 +#define MT6351_PMIC_RG_VSIM2_OC_TRIM_ADDR MT6351_VSIM2_ANA_CON1 +#define MT6351_PMIC_RG_VSIM2_OC_TRIM_MASK 0xF +#define MT6351_PMIC_RG_VSIM2_OC_TRIM_SHIFT 9 +#define MT6351_PMIC_RG_VSIM2_NDIS_EN_INT_ADDR MT6351_VSIM2_ANA_CON1 +#define MT6351_PMIC_RG_VSIM2_NDIS_EN_INT_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_NDIS_EN_INT_SHIFT 13 +#define MT6351_PMIC_RG_EFUSE_VSIM2_MODE_ADDR MT6351_VSIM2_ANA_CON1 +#define MT6351_PMIC_RG_EFUSE_VSIM2_MODE_MASK 0x1 +#define MT6351_PMIC_RG_EFUSE_VSIM2_MODE_SHIFT 14 +#define MT6351_PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB_ADDR MT6351_VSIM2_ANA_CON1 +#define MT6351_PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB_SHIFT 15 +#define MT6351_PMIC_RG_VEFUSE_CAL_ADDR MT6351_VEFUSE_ANA_CON0 +#define MT6351_PMIC_RG_VEFUSE_CAL_MASK 0xF +#define MT6351_PMIC_RG_VEFUSE_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VEFUSE_VOSEL_ADDR MT6351_VEFUSE_ANA_CON0 +#define MT6351_PMIC_RG_VEFUSE_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VEFUSE_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VEFUSE_NDIS_EN_ADDR MT6351_VEFUSE_ANA_CON1 +#define MT6351_PMIC_RG_VEFUSE_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VEFUSE_STB_CAL_ADDR MT6351_VEFUSE_ANA_CON1 +#define MT6351_PMIC_RG_VEFUSE_STB_CAL_MASK 0x3 +#define MT6351_PMIC_RG_VEFUSE_STB_CAL_SHIFT 6 +#define MT6351_PMIC_RG_VEFUSE_STB_SEL_ADDR MT6351_VEFUSE_ANA_CON1 +#define MT6351_PMIC_RG_VEFUSE_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_STB_SEL_SHIFT 8 +#define MT6351_PMIC_RG_VEFUSE_OC_TRIM_ADDR MT6351_VEFUSE_ANA_CON1 +#define MT6351_PMIC_RG_VEFUSE_OC_TRIM_MASK 0xF +#define MT6351_PMIC_RG_VEFUSE_OC_TRIM_SHIFT 9 +#define MT6351_PMIC_RG_VEFUSE_NDIS_EN_INT_ADDR MT6351_VEFUSE_ANA_CON1 +#define MT6351_PMIC_RG_VEFUSE_NDIS_EN_INT_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_NDIS_EN_INT_SHIFT 13 +#define MT6351_PMIC_RG_EFUSE_MODE_1_ADDR MT6351_VEFUSE_ANA_CON1 +#define MT6351_PMIC_RG_EFUSE_MODE_1_MASK 0x1 +#define MT6351_PMIC_RG_EFUSE_MODE_1_SHIFT 14 +#define MT6351_PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB_ADDR MT6351_VEFUSE_ANA_CON1 +#define MT6351_PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB_MASK 0x1 +#define MT6351_PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB_SHIFT 15 +#define MT6351_PMIC_RG_VA18_CAL_ADDR MT6351_VA18_ANA_CON0 +#define MT6351_PMIC_RG_VA18_CAL_MASK 0xF +#define MT6351_PMIC_RG_VA18_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VA18_VOSEL_ADDR MT6351_VA18_ANA_CON0 +#define MT6351_PMIC_RG_VA18_VOSEL_MASK 0x3 +#define MT6351_PMIC_RG_VA18_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VA18_NDIS_EN_ADDR MT6351_VA18_ANA_CON0 +#define MT6351_PMIC_RG_VA18_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VA18_NDIS_EN_SHIFT 11 +#define MT6351_PMIC_RG_VGP3_CAL_ADDR MT6351_VGP3_ANA_CON0 +#define MT6351_PMIC_RG_VGP3_CAL_MASK 0xF +#define MT6351_PMIC_RG_VGP3_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VGP3_VOSEL_ADDR MT6351_VGP3_ANA_CON0 +#define MT6351_PMIC_RG_VGP3_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VGP3_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VGP3_NDIS_EN_ADDR MT6351_VGP3_ANA_CON1 +#define MT6351_PMIC_RG_VGP3_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VGP3_FT_DNMC_EN_ADDR MT6351_VGP3_ANA_CON1 +#define MT6351_PMIC_RG_VGP3_FT_DNMC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VGP3_FT_DNMC_EN_SHIFT 4 +#define MT6351_PMIC_RG_VCAMD_CAL_ADDR MT6351_VCAMD_ANA_CON0 +#define MT6351_PMIC_RG_VCAMD_CAL_MASK 0x1F +#define MT6351_PMIC_RG_VCAMD_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VCAMD_VOSEL_ADDR MT6351_VCAMD_ANA_CON0 +#define MT6351_PMIC_RG_VCAMD_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMD_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VCAMD_NDIS_EN_ADDR MT6351_VCAMD_ANA_CON1 +#define MT6351_PMIC_RG_VCAMD_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMD_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCAMD_RSV_ADDR MT6351_VCAMD_ANA_CON1 +#define MT6351_PMIC_RG_VCAMD_RSV_MASK 0xFF +#define MT6351_PMIC_RG_VCAMD_RSV_SHIFT 2 +#define MT6351_PMIC_RG_VCAMD_OC_TRIM_ADDR MT6351_VCAMD_ANA_CON1 +#define MT6351_PMIC_RG_VCAMD_OC_TRIM_MASK 0xF +#define MT6351_PMIC_RG_VCAMD_OC_TRIM_SHIFT 10 +#define MT6351_PMIC_RG_VIO18_CAL_ADDR MT6351_VIO18_ANA_CON0 +#define MT6351_PMIC_RG_VIO18_CAL_MASK 0xF +#define MT6351_PMIC_RG_VIO18_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VIO18_NDIS_EN_ADDR MT6351_VIO18_ANA_CON1 +#define MT6351_PMIC_RG_VIO18_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VIO18_FT_DNMC_EN_ADDR MT6351_VIO18_ANA_CON1 +#define MT6351_PMIC_RG_VIO18_FT_DNMC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VIO18_FT_DNMC_EN_SHIFT 4 +#define MT6351_PMIC_RG_VRF18_CAL_ADDR MT6351_VRF18_ANA_CON0 +#define MT6351_PMIC_RG_VRF18_CAL_MASK 0xF +#define MT6351_PMIC_RG_VRF18_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VRF18_VOSEL_ADDR MT6351_VRF18_ANA_CON0 +#define MT6351_PMIC_RG_VRF18_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VRF18_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VRF18_NDIS_EN_ADDR MT6351_VRF18_ANA_CON1 +#define MT6351_PMIC_RG_VRF18_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VRF18_FT_DNMC_EN_ADDR MT6351_VRF18_ANA_CON1 +#define MT6351_PMIC_RG_VRF18_FT_DNMC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF18_FT_DNMC_EN_SHIFT 4 +#define MT6351_PMIC_RG_VRF12_CAL_ADDR MT6351_VRF12_ANA_CON0 +#define MT6351_PMIC_RG_VRF12_CAL_MASK 0xF +#define MT6351_PMIC_RG_VRF12_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VRF12_VOSEL_ADDR MT6351_VRF12_ANA_CON0 +#define MT6351_PMIC_RG_VRF12_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VRF12_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VRF12_NDIS_EN_ADDR MT6351_VRF12_ANA_CON1 +#define MT6351_PMIC_RG_VRF12_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VRF12_STB_SEL_ADDR MT6351_VRF12_ANA_CON1 +#define MT6351_PMIC_RG_VRF12_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VRF12_STB_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VA10_CAL_ADDR MT6351_VA10_ANA_CON0 +#define MT6351_PMIC_RG_VA10_CAL_MASK 0xF +#define MT6351_PMIC_RG_VA10_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VA10_VOSEL_ADDR MT6351_VA10_ANA_CON0 +#define MT6351_PMIC_RG_VA10_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VA10_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VA10_NDIS_EN_ADDR MT6351_VA10_ANA_CON1 +#define MT6351_PMIC_RG_VA10_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VA10_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VA10_STB_SEL_ADDR MT6351_VA10_ANA_CON1 +#define MT6351_PMIC_RG_VA10_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VA10_STB_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VCAMIO_CAL_ADDR MT6351_VCAMIO_ANA_CON0 +#define MT6351_PMIC_RG_VCAMIO_CAL_MASK 0xF +#define MT6351_PMIC_RG_VCAMIO_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VCAMIO_VOSEL_ADDR MT6351_VCAMIO_ANA_CON0 +#define MT6351_PMIC_RG_VCAMIO_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VCAMIO_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VCAMIO_NDIS_EN_ADDR MT6351_VCAMIO_ANA_CON1 +#define MT6351_PMIC_RG_VCAMIO_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCAMIO_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCAMIO_STB_SEL_ADDR MT6351_VCAMIO_ANA_CON1 +#define MT6351_PMIC_RG_VCAMIO_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VCAMIO_STB_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VCN18_CAL_ADDR MT6351_VCN18_ANA_CON0 +#define MT6351_PMIC_RG_VCN18_CAL_MASK 0xF +#define MT6351_PMIC_RG_VCN18_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VCN18_VOSEL_ADDR MT6351_VCN18_ANA_CON0 +#define MT6351_PMIC_RG_VCN18_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VCN18_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VCN18_NDIS_EN_ADDR MT6351_VCN18_ANA_CON1 +#define MT6351_PMIC_RG_VCN18_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCN18_STB_SEL_ADDR MT6351_VCN18_ANA_CON1 +#define MT6351_PMIC_RG_VCN18_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VCN18_STB_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VMIPI_CAL_ADDR MT6351_VMIPI_ANA_CON0 +#define MT6351_PMIC_RG_VMIPI_CAL_MASK 0xF +#define MT6351_PMIC_RG_VMIPI_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VMIPI_VOSEL_ADDR MT6351_VMIPI_ANA_CON0 +#define MT6351_PMIC_RG_VMIPI_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VMIPI_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VMIPI_NDIS_EN_ADDR MT6351_VMIPI_ANA_CON1 +#define MT6351_PMIC_RG_VMIPI_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VMIPI_STB_SEL_ADDR MT6351_VMIPI_ANA_CON1 +#define MT6351_PMIC_RG_VMIPI_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VMIPI_STB_SEL_SHIFT 2 +#define MT6351_PMIC_RG_VSRAM_PROC_NDIS_EN_ADDR MT6351_VSRAM_PROC_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_PROC_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VSRAM_PROC_NDIS_PLCUR_ADDR MT6351_VSRAM_PROC_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_PROC_NDIS_PLCUR_MASK 0x3 +#define MT6351_PMIC_RG_VSRAM_PROC_NDIS_PLCUR_SHIFT 2 +#define MT6351_PMIC_RG_VSRAM_PROC_STB_SEL_ADDR MT6351_VSRAM_PROC_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_PROC_STB_SEL_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_STB_SEL_SHIFT 4 +#define MT6351_PMIC_RG_VSRAM_PROC_PLCUR_EN_ADDR MT6351_VSRAM_PROC_ANA_CON1 +#define MT6351_PMIC_RG_VSRAM_PROC_PLCUR_EN_MASK 0x1 +#define MT6351_PMIC_RG_VSRAM_PROC_PLCUR_EN_SHIFT 5 +#define MT6351_PMIC_RG_VDRAM_CAL_ADDR MT6351_VDRAM_ANA_CON0 +#define MT6351_PMIC_RG_VDRAM_CAL_MASK 0x1F +#define MT6351_PMIC_RG_VDRAM_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VDRAM_VOSEL_ADDR MT6351_VDRAM_ANA_CON0 +#define MT6351_PMIC_RG_VDRAM_VOSEL_MASK 0x7 +#define MT6351_PMIC_RG_VDRAM_VOSEL_SHIFT 8 +#define MT6351_PMIC_RG_VDRAM_NDIS_EN_ADDR MT6351_VDRAM_ANA_CON1 +#define MT6351_PMIC_RG_VDRAM_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VDRAM_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VDRAM_RSV_ADDR MT6351_VDRAM_ANA_CON1 +#define MT6351_PMIC_RG_VDRAM_RSV_MASK 0xFF +#define MT6351_PMIC_RG_VDRAM_RSV_SHIFT 2 +#define MT6351_PMIC_RG_VDRAM_OC_TRIM_ADDR MT6351_VDRAM_ANA_CON1 +#define MT6351_PMIC_RG_VDRAM_OC_TRIM_MASK 0xF +#define MT6351_PMIC_RG_VDRAM_OC_TRIM_SHIFT 10 +#define MT6351_PMIC_RG_VLDO28_CAL_ADDR MT6351_VLDO28_ANA_CON0 +#define MT6351_PMIC_RG_VLDO28_CAL_MASK 0x1F +#define MT6351_PMIC_RG_VLDO28_CAL_SHIFT 0 +#define MT6351_PMIC_RG_VLDO28_NDIS_EN_ADDR MT6351_VLDO28_ANA_CON1 +#define MT6351_PMIC_RG_VLDO28_NDIS_EN_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_NDIS_EN_SHIFT 1 +#define MT6351_PMIC_RG_VLDO28_OC_TRIM_ADDR MT6351_VLDO28_ANA_CON1 +#define MT6351_PMIC_RG_VLDO28_OC_TRIM_MASK 0x3F +#define MT6351_PMIC_RG_VLDO28_OC_TRIM_SHIFT 2 +#define MT6351_PMIC_RG_VLDO28_N2LP_EHC_V18_ADDR MT6351_VLDO28_ANA_CON1 +#define MT6351_PMIC_RG_VLDO28_N2LP_EHC_V18_MASK 0x1 +#define MT6351_PMIC_RG_VLDO28_N2LP_EHC_V18_SHIFT 8 +#define MT6351_PMIC_BIF_COMMAND_0_ADDR MT6351_BIF_CON0 +#define MT6351_PMIC_BIF_COMMAND_0_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_0_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_1_ADDR MT6351_BIF_CON1 +#define MT6351_PMIC_BIF_COMMAND_1_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_1_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_2_ADDR MT6351_BIF_CON2 +#define MT6351_PMIC_BIF_COMMAND_2_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_2_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_3_ADDR MT6351_BIF_CON3 +#define MT6351_PMIC_BIF_COMMAND_3_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_3_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_4_ADDR MT6351_BIF_CON4 +#define MT6351_PMIC_BIF_COMMAND_4_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_4_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_5_ADDR MT6351_BIF_CON5 +#define MT6351_PMIC_BIF_COMMAND_5_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_5_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_6_ADDR MT6351_BIF_CON6 +#define MT6351_PMIC_BIF_COMMAND_6_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_6_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_7_ADDR MT6351_BIF_CON7 +#define MT6351_PMIC_BIF_COMMAND_7_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_7_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_8_ADDR MT6351_BIF_CON8 +#define MT6351_PMIC_BIF_COMMAND_8_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_8_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_9_ADDR MT6351_BIF_CON9 +#define MT6351_PMIC_BIF_COMMAND_9_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_9_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_10_ADDR MT6351_BIF_CON10 +#define MT6351_PMIC_BIF_COMMAND_10_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_10_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_11_ADDR MT6351_BIF_CON11 +#define MT6351_PMIC_BIF_COMMAND_11_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_11_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_12_ADDR MT6351_BIF_CON12 +#define MT6351_PMIC_BIF_COMMAND_12_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_12_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_13_ADDR MT6351_BIF_CON13 +#define MT6351_PMIC_BIF_COMMAND_13_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_13_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_14_ADDR MT6351_BIF_CON14 +#define MT6351_PMIC_BIF_COMMAND_14_MASK 0x7FF +#define MT6351_PMIC_BIF_COMMAND_14_SHIFT 0 +#define MT6351_PMIC_BIF_RSV_ADDR MT6351_BIF_CON15 +#define MT6351_PMIC_BIF_RSV_MASK 0x7F +#define MT6351_PMIC_BIF_RSV_SHIFT 0 +#define MT6351_PMIC_BIF_COMMAND_TYPE_ADDR MT6351_BIF_CON15 +#define MT6351_PMIC_BIF_COMMAND_TYPE_MASK 0x3 +#define MT6351_PMIC_BIF_COMMAND_TYPE_SHIFT 8 +#define MT6351_PMIC_BIF_TRASFER_NUM_ADDR MT6351_BIF_CON15 +#define MT6351_PMIC_BIF_TRASFER_NUM_MASK 0xF +#define MT6351_PMIC_BIF_TRASFER_NUM_SHIFT 12 +#define MT6351_PMIC_BIF_LOGIC_0_SET_ADDR MT6351_BIF_CON16 +#define MT6351_PMIC_BIF_LOGIC_0_SET_MASK 0xF +#define MT6351_PMIC_BIF_LOGIC_0_SET_SHIFT 0 +#define MT6351_PMIC_BIF_LOGIC_1_SET_ADDR MT6351_BIF_CON16 +#define MT6351_PMIC_BIF_LOGIC_1_SET_MASK 0x1F +#define MT6351_PMIC_BIF_LOGIC_1_SET_SHIFT 4 +#define MT6351_PMIC_BIF_STOP_SET_ADDR MT6351_BIF_CON16 +#define MT6351_PMIC_BIF_STOP_SET_MASK 0x3F +#define MT6351_PMIC_BIF_STOP_SET_SHIFT 10 +#define MT6351_PMIC_BIF_DEBOUNCE_WND_ADDR MT6351_BIF_CON17 +#define MT6351_PMIC_BIF_DEBOUNCE_WND_MASK 0x3 +#define MT6351_PMIC_BIF_DEBOUNCE_WND_SHIFT 0 +#define MT6351_PMIC_BIF_DEBOUNCE_THD_ADDR MT6351_BIF_CON17 +#define MT6351_PMIC_BIF_DEBOUNCE_THD_MASK 0x3 +#define MT6351_PMIC_BIF_DEBOUNCE_THD_SHIFT 2 +#define MT6351_PMIC_BIF_DEBOUNCE_EN_ADDR MT6351_BIF_CON17 +#define MT6351_PMIC_BIF_DEBOUNCE_EN_MASK 0x1 +#define MT6351_PMIC_BIF_DEBOUNCE_EN_SHIFT 4 +#define MT6351_PMIC_BIF_READ_EXPECT_NUM_ADDR MT6351_BIF_CON17 +#define MT6351_PMIC_BIF_READ_EXPECT_NUM_MASK 0xF +#define MT6351_PMIC_BIF_READ_EXPECT_NUM_SHIFT 12 +#define MT6351_PMIC_BIF_TRASACT_TRIGGER_ADDR MT6351_BIF_CON18 +#define MT6351_PMIC_BIF_TRASACT_TRIGGER_MASK 0x1 +#define MT6351_PMIC_BIF_TRASACT_TRIGGER_SHIFT 0 +#define MT6351_PMIC_BIF_DATA_NUM_ADDR MT6351_BIF_CON19 +#define MT6351_PMIC_BIF_DATA_NUM_MASK 0xF +#define MT6351_PMIC_BIF_DATA_NUM_SHIFT 0 +#define MT6351_PMIC_BIF_RESPONSE_ADDR MT6351_BIF_CON19 +#define MT6351_PMIC_BIF_RESPONSE_MASK 0x1 +#define MT6351_PMIC_BIF_RESPONSE_SHIFT 12 +#define MT6351_PMIC_BIF_DATA_0_ADDR MT6351_BIF_CON20 +#define MT6351_PMIC_BIF_DATA_0_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_0_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_0_ADDR MT6351_BIF_CON20 +#define MT6351_PMIC_BIF_ACK_0_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_0_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_0_ADDR MT6351_BIF_CON20 +#define MT6351_PMIC_BIF_ERROR_0_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_0_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_1_ADDR MT6351_BIF_CON21 +#define MT6351_PMIC_BIF_DATA_1_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_1_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_1_ADDR MT6351_BIF_CON21 +#define MT6351_PMIC_BIF_ACK_1_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_1_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_1_ADDR MT6351_BIF_CON21 +#define MT6351_PMIC_BIF_ERROR_1_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_1_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_2_ADDR MT6351_BIF_CON22 +#define MT6351_PMIC_BIF_DATA_2_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_2_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_2_ADDR MT6351_BIF_CON22 +#define MT6351_PMIC_BIF_ACK_2_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_2_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_2_ADDR MT6351_BIF_CON22 +#define MT6351_PMIC_BIF_ERROR_2_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_2_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_3_ADDR MT6351_BIF_CON23 +#define MT6351_PMIC_BIF_DATA_3_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_3_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_3_ADDR MT6351_BIF_CON23 +#define MT6351_PMIC_BIF_ACK_3_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_3_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_3_ADDR MT6351_BIF_CON23 +#define MT6351_PMIC_BIF_ERROR_3_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_3_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_4_ADDR MT6351_BIF_CON24 +#define MT6351_PMIC_BIF_DATA_4_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_4_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_4_ADDR MT6351_BIF_CON24 +#define MT6351_PMIC_BIF_ACK_4_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_4_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_4_ADDR MT6351_BIF_CON24 +#define MT6351_PMIC_BIF_ERROR_4_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_4_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_5_ADDR MT6351_BIF_CON25 +#define MT6351_PMIC_BIF_DATA_5_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_5_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_5_ADDR MT6351_BIF_CON25 +#define MT6351_PMIC_BIF_ACK_5_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_5_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_5_ADDR MT6351_BIF_CON25 +#define MT6351_PMIC_BIF_ERROR_5_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_5_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_6_ADDR MT6351_BIF_CON26 +#define MT6351_PMIC_BIF_DATA_6_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_6_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_6_ADDR MT6351_BIF_CON26 +#define MT6351_PMIC_BIF_ACK_6_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_6_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_6_ADDR MT6351_BIF_CON26 +#define MT6351_PMIC_BIF_ERROR_6_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_6_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_7_ADDR MT6351_BIF_CON27 +#define MT6351_PMIC_BIF_DATA_7_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_7_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_7_ADDR MT6351_BIF_CON27 +#define MT6351_PMIC_BIF_ACK_7_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_7_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_7_ADDR MT6351_BIF_CON27 +#define MT6351_PMIC_BIF_ERROR_7_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_7_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_8_ADDR MT6351_BIF_CON28 +#define MT6351_PMIC_BIF_DATA_8_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_8_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_8_ADDR MT6351_BIF_CON28 +#define MT6351_PMIC_BIF_ACK_8_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_8_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_8_ADDR MT6351_BIF_CON28 +#define MT6351_PMIC_BIF_ERROR_8_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_8_SHIFT 15 +#define MT6351_PMIC_BIF_DATA_9_ADDR MT6351_BIF_CON29 +#define MT6351_PMIC_BIF_DATA_9_MASK 0xFF +#define MT6351_PMIC_BIF_DATA_9_SHIFT 0 +#define MT6351_PMIC_BIF_ACK_9_ADDR MT6351_BIF_CON29 +#define MT6351_PMIC_BIF_ACK_9_MASK 0x1 +#define MT6351_PMIC_BIF_ACK_9_SHIFT 8 +#define MT6351_PMIC_BIF_ERROR_9_ADDR MT6351_BIF_CON29 +#define MT6351_PMIC_BIF_ERROR_9_MASK 0x1 +#define MT6351_PMIC_BIF_ERROR_9_SHIFT 15 +#define MT6351_PMIC_BIF_TEST_MODE0_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE0_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE0_SHIFT 0 +#define MT6351_PMIC_BIF_TEST_MODE1_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE1_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE1_SHIFT 1 +#define MT6351_PMIC_BIF_TEST_MODE2_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE2_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE2_SHIFT 2 +#define MT6351_PMIC_BIF_TEST_MODE3_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE3_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE3_SHIFT 3 +#define MT6351_PMIC_BIF_TEST_MODE4_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE4_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE4_SHIFT 4 +#define MT6351_PMIC_BIF_TEST_MODE5_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE5_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE5_SHIFT 5 +#define MT6351_PMIC_BIF_TEST_MODE6_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE6_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE6_SHIFT 6 +#define MT6351_PMIC_BIF_TEST_MODE7_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE7_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE7_SHIFT 7 +#define MT6351_PMIC_BIF_TEST_MODE8_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TEST_MODE8_MASK 0x1 +#define MT6351_PMIC_BIF_TEST_MODE8_SHIFT 8 +#define MT6351_PMIC_BIF_BAT_LOST_SW_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_BAT_LOST_SW_MASK 0x1 +#define MT6351_PMIC_BIF_BAT_LOST_SW_SHIFT 11 +#define MT6351_PMIC_BIF_RX_DATA_SW_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_RX_DATA_SW_MASK 0x1 +#define MT6351_PMIC_BIF_RX_DATA_SW_SHIFT 12 +#define MT6351_PMIC_BIF_TX_DATA_SW_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TX_DATA_SW_MASK 0x1 +#define MT6351_PMIC_BIF_TX_DATA_SW_SHIFT 13 +#define MT6351_PMIC_BIF_RX_EN_SW_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_RX_EN_SW_MASK 0x1 +#define MT6351_PMIC_BIF_RX_EN_SW_SHIFT 14 +#define MT6351_PMIC_BIF_TX_EN_SW_ADDR MT6351_BIF_CON30 +#define MT6351_PMIC_BIF_TX_EN_SW_MASK 0x1 +#define MT6351_PMIC_BIF_TX_EN_SW_SHIFT 15 +#define MT6351_PMIC_BIF_BACK_NORMAL_ADDR MT6351_BIF_CON31 +#define MT6351_PMIC_BIF_BACK_NORMAL_MASK 0x1 +#define MT6351_PMIC_BIF_BACK_NORMAL_SHIFT 0 +#define MT6351_PMIC_BIF_IRQ_CLR_ADDR MT6351_BIF_CON31 +#define MT6351_PMIC_BIF_IRQ_CLR_MASK 0x1 +#define MT6351_PMIC_BIF_IRQ_CLR_SHIFT 1 +#define MT6351_PMIC_BIF_BAT_LOST_GATED_ADDR MT6351_BIF_CON31 +#define MT6351_PMIC_BIF_BAT_LOST_GATED_MASK 0x1 +#define MT6351_PMIC_BIF_BAT_LOST_GATED_SHIFT 10 +#define MT6351_PMIC_BIF_IRQ_ADDR MT6351_BIF_CON31 +#define MT6351_PMIC_BIF_IRQ_MASK 0x1 +#define MT6351_PMIC_BIF_IRQ_SHIFT 11 +#define MT6351_PMIC_BIF_TIMEOUT_ADDR MT6351_BIF_CON31 +#define MT6351_PMIC_BIF_TIMEOUT_MASK 0x1 +#define MT6351_PMIC_BIF_TIMEOUT_SHIFT 12 +#define MT6351_PMIC_BIF_BAT_LOST_ADDR MT6351_BIF_CON31 +#define MT6351_PMIC_BIF_BAT_LOST_MASK 0x1 +#define MT6351_PMIC_BIF_BAT_LOST_SHIFT 13 +#define MT6351_PMIC_BIF_TOTAL_VALID_ADDR MT6351_BIF_CON31 +#define MT6351_PMIC_BIF_TOTAL_VALID_MASK 0x1 +#define MT6351_PMIC_BIF_TOTAL_VALID_SHIFT 14 +#define MT6351_PMIC_BIF_BUS_STATUS_ADDR MT6351_BIF_CON31 +#define MT6351_PMIC_BIF_BUS_STATUS_MASK 0x1 +#define MT6351_PMIC_BIF_BUS_STATUS_SHIFT 15 +#define MT6351_PMIC_BIF_POWER_UP_COUNT_ADDR MT6351_BIF_CON32 +#define MT6351_PMIC_BIF_POWER_UP_COUNT_MASK 0x1F +#define MT6351_PMIC_BIF_POWER_UP_COUNT_SHIFT 0 +#define MT6351_PMIC_BIF_POWER_UP_ADDR MT6351_BIF_CON32 +#define MT6351_PMIC_BIF_POWER_UP_MASK 0x1 +#define MT6351_PMIC_BIF_POWER_UP_SHIFT 15 +#define MT6351_PMIC_BIF_RX_ERROR_UNKNOWN_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_BIF_RX_ERROR_UNKNOWN_MASK 0x1 +#define MT6351_PMIC_BIF_RX_ERROR_UNKNOWN_SHIFT 2 +#define MT6351_PMIC_BIF_RX_ERROR_INSUFF_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_BIF_RX_ERROR_INSUFF_MASK 0x1 +#define MT6351_PMIC_BIF_RX_ERROR_INSUFF_SHIFT 3 +#define MT6351_PMIC_BIF_RX_ERROR_LOWPHASE_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_BIF_RX_ERROR_LOWPHASE_MASK 0x1 +#define MT6351_PMIC_BIF_RX_ERROR_LOWPHASE_SHIFT 4 +#define MT6351_PMIC_BIF_RX_STATE_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_BIF_RX_STATE_MASK 0x7 +#define MT6351_PMIC_BIF_RX_STATE_SHIFT 5 +#define MT6351_PMIC_BIF_FLOW_CTL_STATE_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_BIF_FLOW_CTL_STATE_MASK 0x3 +#define MT6351_PMIC_BIF_FLOW_CTL_STATE_SHIFT 8 +#define MT6351_PMIC_BIF_TX_STATE_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_BIF_TX_STATE_MASK 0x3 +#define MT6351_PMIC_BIF_TX_STATE_SHIFT 10 +#define MT6351_PMIC_AD_QI_BIF_RX_DATA_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_AD_QI_BIF_RX_DATA_MASK 0x1 +#define MT6351_PMIC_AD_QI_BIF_RX_DATA_SHIFT 12 +#define MT6351_PMIC_DA_QI_BIF_RX_EN_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_DA_QI_BIF_RX_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_BIF_RX_EN_SHIFT 13 +#define MT6351_PMIC_DA_QI_BIF_TX_DATA_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_DA_QI_BIF_TX_DATA_MASK 0x1 +#define MT6351_PMIC_DA_QI_BIF_TX_DATA_SHIFT 14 +#define MT6351_PMIC_DA_QI_BIF_TX_EN_ADDR MT6351_BIF_CON33 +#define MT6351_PMIC_DA_QI_BIF_TX_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_BIF_TX_EN_SHIFT 15 +#define MT6351_PMIC_BIF_TX_DATA_FIANL_ADDR MT6351_BIF_CON34 +#define MT6351_PMIC_BIF_TX_DATA_FIANL_MASK 0xFFFF +#define MT6351_PMIC_BIF_TX_DATA_FIANL_SHIFT 0 +#define MT6351_PMIC_BIF_RX_DATA_SAMPLING_ADDR MT6351_BIF_CON35 +#define MT6351_PMIC_BIF_RX_DATA_SAMPLING_MASK 0xFFFF +#define MT6351_PMIC_BIF_RX_DATA_SAMPLING_SHIFT 0 +#define MT6351_PMIC_BIF_RX_DATA_RECOVERY_ADDR MT6351_BIF_CON36 +#define MT6351_PMIC_BIF_RX_DATA_RECOVERY_MASK 0x3FFF +#define MT6351_PMIC_BIF_RX_DATA_RECOVERY_SHIFT 0 +#define MT6351_PMIC_RG_BATON_HT_EN_ADDR MT6351_BIF_BAT_CON0 +#define MT6351_PMIC_RG_BATON_HT_EN_MASK 0x1 +#define MT6351_PMIC_RG_BATON_HT_EN_SHIFT 0 +#define MT6351_PMIC_RG_BATON_HT_EN_DLY_TIME_ADDR MT6351_BIF_BAT_CON0 +#define MT6351_PMIC_RG_BATON_HT_EN_DLY_TIME_MASK 0x1 +#define MT6351_PMIC_RG_BATON_HT_EN_DLY_TIME_SHIFT 4 +#define MT6351_PMIC_DA_QI_BATON_HT_EN_ADDR MT6351_BIF_BAT_CON0 +#define MT6351_PMIC_DA_QI_BATON_HT_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_BATON_HT_EN_SHIFT 5 +#define MT6351_PMIC_BIF_TIMEOUT_SET_ADDR MT6351_BIF_CON37 +#define MT6351_PMIC_BIF_TIMEOUT_SET_MASK 0xFFFF +#define MT6351_PMIC_BIF_TIMEOUT_SET_SHIFT 0 +#define MT6351_PMIC_BIF_RX_DEG_WND_ADDR MT6351_BIF_CON38 +#define MT6351_PMIC_BIF_RX_DEG_WND_MASK 0x3FF +#define MT6351_PMIC_BIF_RX_DEG_WND_SHIFT 0 +#define MT6351_PMIC_BIF_RX_DEG_EN_ADDR MT6351_BIF_CON38 +#define MT6351_PMIC_BIF_RX_DEG_EN_MASK 0x1 +#define MT6351_PMIC_BIF_RX_DEG_EN_SHIFT 15 +#define MT6351_PMIC_BIF_RSV1_ADDR MT6351_BIF_CON39 +#define MT6351_PMIC_BIF_RSV1_MASK 0xFF +#define MT6351_PMIC_BIF_RSV1_SHIFT 0 +#define MT6351_PMIC_BIF_RSV0_ADDR MT6351_BIF_CON39 +#define MT6351_PMIC_BIF_RSV0_MASK 0xFF +#define MT6351_PMIC_BIF_RSV0_SHIFT 8 +#define MT6351_PMIC_RG_OTP_PA_ADDR MT6351_OTP_CON0 +#define MT6351_PMIC_RG_OTP_PA_MASK 0x3F +#define MT6351_PMIC_RG_OTP_PA_SHIFT 0 +#define MT6351_PMIC_RG_OTP_PDIN_ADDR MT6351_OTP_CON1 +#define MT6351_PMIC_RG_OTP_PDIN_MASK 0xFF +#define MT6351_PMIC_RG_OTP_PDIN_SHIFT 0 +#define MT6351_PMIC_RG_OTP_PTM_ADDR MT6351_OTP_CON2 +#define MT6351_PMIC_RG_OTP_PTM_MASK 0x3 +#define MT6351_PMIC_RG_OTP_PTM_SHIFT 0 +#define MT6351_PMIC_RG_OTP_PWE_ADDR MT6351_OTP_CON3 +#define MT6351_PMIC_RG_OTP_PWE_MASK 0x3 +#define MT6351_PMIC_RG_OTP_PWE_SHIFT 0 +#define MT6351_PMIC_RG_OTP_PPROG_ADDR MT6351_OTP_CON4 +#define MT6351_PMIC_RG_OTP_PPROG_MASK 0x1 +#define MT6351_PMIC_RG_OTP_PPROG_SHIFT 0 +#define MT6351_PMIC_RG_OTP_PWE_SRC_ADDR MT6351_OTP_CON5 +#define MT6351_PMIC_RG_OTP_PWE_SRC_MASK 0x1 +#define MT6351_PMIC_RG_OTP_PWE_SRC_SHIFT 0 +#define MT6351_PMIC_RG_OTP_PROG_PKEY_ADDR MT6351_OTP_CON6 +#define MT6351_PMIC_RG_OTP_PROG_PKEY_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_PROG_PKEY_SHIFT 0 +#define MT6351_PMIC_RG_OTP_RD_PKEY_ADDR MT6351_OTP_CON7 +#define MT6351_PMIC_RG_OTP_RD_PKEY_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_RD_PKEY_SHIFT 0 +#define MT6351_PMIC_RG_OTP_RD_TRIG_ADDR MT6351_OTP_CON8 +#define MT6351_PMIC_RG_OTP_RD_TRIG_MASK 0x1 +#define MT6351_PMIC_RG_OTP_RD_TRIG_SHIFT 0 +#define MT6351_PMIC_RG_RD_RDY_BYPASS_ADDR MT6351_OTP_CON9 +#define MT6351_PMIC_RG_RD_RDY_BYPASS_MASK 0x1 +#define MT6351_PMIC_RG_RD_RDY_BYPASS_SHIFT 0 +#define MT6351_PMIC_RG_SKIP_OTP_OUT_ADDR MT6351_OTP_CON10 +#define MT6351_PMIC_RG_SKIP_OTP_OUT_MASK 0x1 +#define MT6351_PMIC_RG_SKIP_OTP_OUT_SHIFT 0 +#define MT6351_PMIC_RG_OTP_RD_SW_ADDR MT6351_OTP_CON11 +#define MT6351_PMIC_RG_OTP_RD_SW_MASK 0x1 +#define MT6351_PMIC_RG_OTP_RD_SW_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_SW_ADDR MT6351_OTP_CON12 +#define MT6351_PMIC_RG_OTP_DOUT_SW_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_SW_SHIFT 0 +#define MT6351_PMIC_RG_OTP_RD_BUSY_ADDR MT6351_OTP_CON13 +#define MT6351_PMIC_RG_OTP_RD_BUSY_MASK 0x1 +#define MT6351_PMIC_RG_OTP_RD_BUSY_SHIFT 0 +#define MT6351_PMIC_RG_OTP_RD_ACK_ADDR MT6351_OTP_CON13 +#define MT6351_PMIC_RG_OTP_RD_ACK_MASK 0x1 +#define MT6351_PMIC_RG_OTP_RD_ACK_SHIFT 2 +#define MT6351_PMIC_RG_OTP_PA_SW_ADDR MT6351_OTP_CON14 +#define MT6351_PMIC_RG_OTP_PA_SW_MASK 0x1F +#define MT6351_PMIC_RG_OTP_PA_SW_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_0_15_ADDR MT6351_OTP_DOUT_0_15 +#define MT6351_PMIC_RG_OTP_DOUT_0_15_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_0_15_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_16_31_ADDR MT6351_OTP_DOUT_16_31 +#define MT6351_PMIC_RG_OTP_DOUT_16_31_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_16_31_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_32_47_ADDR MT6351_OTP_DOUT_32_47 +#define MT6351_PMIC_RG_OTP_DOUT_32_47_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_32_47_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_48_63_ADDR MT6351_OTP_DOUT_48_63 +#define MT6351_PMIC_RG_OTP_DOUT_48_63_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_48_63_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_64_79_ADDR MT6351_OTP_DOUT_64_79 +#define MT6351_PMIC_RG_OTP_DOUT_64_79_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_64_79_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_80_95_ADDR MT6351_OTP_DOUT_80_95 +#define MT6351_PMIC_RG_OTP_DOUT_80_95_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_80_95_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_96_111_ADDR MT6351_OTP_DOUT_96_111 +#define MT6351_PMIC_RG_OTP_DOUT_96_111_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_96_111_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_112_127_ADDR MT6351_OTP_DOUT_112_127 +#define MT6351_PMIC_RG_OTP_DOUT_112_127_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_112_127_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_128_143_ADDR MT6351_OTP_DOUT_128_143 +#define MT6351_PMIC_RG_OTP_DOUT_128_143_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_128_143_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_144_159_ADDR MT6351_OTP_DOUT_144_159 +#define MT6351_PMIC_RG_OTP_DOUT_144_159_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_144_159_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_160_175_ADDR MT6351_OTP_DOUT_160_175 +#define MT6351_PMIC_RG_OTP_DOUT_160_175_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_160_175_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_176_191_ADDR MT6351_OTP_DOUT_176_191 +#define MT6351_PMIC_RG_OTP_DOUT_176_191_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_176_191_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_192_207_ADDR MT6351_OTP_DOUT_192_207 +#define MT6351_PMIC_RG_OTP_DOUT_192_207_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_192_207_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_208_223_ADDR MT6351_OTP_DOUT_208_223 +#define MT6351_PMIC_RG_OTP_DOUT_208_223_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_208_223_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_224_239_ADDR MT6351_OTP_DOUT_224_239 +#define MT6351_PMIC_RG_OTP_DOUT_224_239_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_224_239_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_240_255_ADDR MT6351_OTP_DOUT_240_255 +#define MT6351_PMIC_RG_OTP_DOUT_240_255_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_240_255_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_256_271_ADDR MT6351_OTP_DOUT_256_271 +#define MT6351_PMIC_RG_OTP_DOUT_256_271_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_256_271_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_272_287_ADDR MT6351_OTP_DOUT_272_287 +#define MT6351_PMIC_RG_OTP_DOUT_272_287_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_272_287_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_288_303_ADDR MT6351_OTP_DOUT_288_303 +#define MT6351_PMIC_RG_OTP_DOUT_288_303_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_288_303_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_304_319_ADDR MT6351_OTP_DOUT_304_319 +#define MT6351_PMIC_RG_OTP_DOUT_304_319_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_304_319_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_320_335_ADDR MT6351_OTP_DOUT_320_335 +#define MT6351_PMIC_RG_OTP_DOUT_320_335_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_320_335_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_336_351_ADDR MT6351_OTP_DOUT_336_351 +#define MT6351_PMIC_RG_OTP_DOUT_336_351_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_336_351_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_352_367_ADDR MT6351_OTP_DOUT_352_367 +#define MT6351_PMIC_RG_OTP_DOUT_352_367_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_352_367_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_368_383_ADDR MT6351_OTP_DOUT_368_383 +#define MT6351_PMIC_RG_OTP_DOUT_368_383_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_368_383_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_384_399_ADDR MT6351_OTP_DOUT_384_399 +#define MT6351_PMIC_RG_OTP_DOUT_384_399_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_384_399_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_400_415_ADDR MT6351_OTP_DOUT_400_415 +#define MT6351_PMIC_RG_OTP_DOUT_400_415_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_400_415_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_416_431_ADDR MT6351_OTP_DOUT_416_431 +#define MT6351_PMIC_RG_OTP_DOUT_416_431_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_416_431_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_432_447_ADDR MT6351_OTP_DOUT_432_447 +#define MT6351_PMIC_RG_OTP_DOUT_432_447_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_432_447_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_448_463_ADDR MT6351_OTP_DOUT_448_463 +#define MT6351_PMIC_RG_OTP_DOUT_448_463_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_448_463_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_464_479_ADDR MT6351_OTP_DOUT_464_479 +#define MT6351_PMIC_RG_OTP_DOUT_464_479_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_464_479_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_480_495_ADDR MT6351_OTP_DOUT_480_495 +#define MT6351_PMIC_RG_OTP_DOUT_480_495_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_480_495_SHIFT 0 +#define MT6351_PMIC_RG_OTP_DOUT_496_511_ADDR MT6351_OTP_DOUT_496_511 +#define MT6351_PMIC_RG_OTP_DOUT_496_511_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_DOUT_496_511_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_0_15_ADDR MT6351_OTP_VAL_0_15 +#define MT6351_PMIC_RG_OTP_VAL_0_15_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_0_15_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_16_31_ADDR MT6351_OTP_VAL_16_31 +#define MT6351_PMIC_RG_OTP_VAL_16_31_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_16_31_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_32_47_ADDR MT6351_OTP_VAL_32_47 +#define MT6351_PMIC_RG_OTP_VAL_32_47_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_32_47_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_48_63_ADDR MT6351_OTP_VAL_48_63 +#define MT6351_PMIC_RG_OTP_VAL_48_63_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_48_63_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_64_79_ADDR MT6351_OTP_VAL_64_79 +#define MT6351_PMIC_RG_OTP_VAL_64_79_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_64_79_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_80_95_ADDR MT6351_OTP_VAL_80_95 +#define MT6351_PMIC_RG_OTP_VAL_80_95_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_80_95_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_96_111_ADDR MT6351_OTP_VAL_96_111 +#define MT6351_PMIC_RG_OTP_VAL_96_111_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_96_111_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_112_127_ADDR MT6351_OTP_VAL_112_127 +#define MT6351_PMIC_RG_OTP_VAL_112_127_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_112_127_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_128_143_ADDR MT6351_OTP_VAL_128_143 +#define MT6351_PMIC_RG_OTP_VAL_128_143_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_128_143_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_144_159_ADDR MT6351_OTP_VAL_144_159 +#define MT6351_PMIC_RG_OTP_VAL_144_159_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_144_159_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_160_175_ADDR MT6351_OTP_VAL_160_175 +#define MT6351_PMIC_RG_OTP_VAL_160_175_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_160_175_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_176_191_ADDR MT6351_OTP_VAL_176_191 +#define MT6351_PMIC_RG_OTP_VAL_176_191_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_176_191_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_192_207_ADDR MT6351_OTP_VAL_192_207 +#define MT6351_PMIC_RG_OTP_VAL_192_207_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_192_207_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_208_223_ADDR MT6351_OTP_VAL_208_223 +#define MT6351_PMIC_RG_OTP_VAL_208_223_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_208_223_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_224_239_ADDR MT6351_OTP_VAL_224_239 +#define MT6351_PMIC_RG_OTP_VAL_224_239_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_224_239_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_240_255_ADDR MT6351_OTP_VAL_240_255 +#define MT6351_PMIC_RG_OTP_VAL_240_255_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_240_255_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_256_271_ADDR MT6351_OTP_VAL_256_271 +#define MT6351_PMIC_RG_OTP_VAL_256_271_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_256_271_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_272_287_ADDR MT6351_OTP_VAL_272_287 +#define MT6351_PMIC_RG_OTP_VAL_272_287_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_272_287_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_288_303_ADDR MT6351_OTP_VAL_288_303 +#define MT6351_PMIC_RG_OTP_VAL_288_303_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_288_303_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_304_319_ADDR MT6351_OTP_VAL_304_319 +#define MT6351_PMIC_RG_OTP_VAL_304_319_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_304_319_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_320_335_ADDR MT6351_OTP_VAL_320_335 +#define MT6351_PMIC_RG_OTP_VAL_320_335_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_320_335_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_336_351_ADDR MT6351_OTP_VAL_336_351 +#define MT6351_PMIC_RG_OTP_VAL_336_351_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_336_351_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_352_367_ADDR MT6351_OTP_VAL_352_367 +#define MT6351_PMIC_RG_OTP_VAL_352_367_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_352_367_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_368_383_ADDR MT6351_OTP_VAL_368_383 +#define MT6351_PMIC_RG_OTP_VAL_368_383_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_368_383_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_384_399_ADDR MT6351_OTP_VAL_384_399 +#define MT6351_PMIC_RG_OTP_VAL_384_399_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_384_399_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_400_415_ADDR MT6351_OTP_VAL_400_415 +#define MT6351_PMIC_RG_OTP_VAL_400_415_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_400_415_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_416_431_ADDR MT6351_OTP_VAL_416_431 +#define MT6351_PMIC_RG_OTP_VAL_416_431_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_416_431_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_432_447_ADDR MT6351_OTP_VAL_432_447 +#define MT6351_PMIC_RG_OTP_VAL_432_447_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_432_447_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_448_463_ADDR MT6351_OTP_VAL_448_463 +#define MT6351_PMIC_RG_OTP_VAL_448_463_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_448_463_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_464_479_ADDR MT6351_OTP_VAL_464_479 +#define MT6351_PMIC_RG_OTP_VAL_464_479_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_464_479_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_480_495_ADDR MT6351_OTP_VAL_480_495 +#define MT6351_PMIC_RG_OTP_VAL_480_495_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_480_495_SHIFT 0 +#define MT6351_PMIC_RG_OTP_VAL_496_511_ADDR MT6351_OTP_VAL_496_511 +#define MT6351_PMIC_RG_OTP_VAL_496_511_MASK 0xFFFF +#define MT6351_PMIC_RG_OTP_VAL_496_511_SHIFT 0 +#define MT6351_PMIC_MIX_EOSC32_STP_LPDTB_ADDR MT6351_RTC_MIX_CON0 +#define MT6351_PMIC_MIX_EOSC32_STP_LPDTB_MASK 0x1 +#define MT6351_PMIC_MIX_EOSC32_STP_LPDTB_SHIFT 1 +#define MT6351_PMIC_MIX_EOSC32_STP_LPDEN_ADDR MT6351_RTC_MIX_CON0 +#define MT6351_PMIC_MIX_EOSC32_STP_LPDEN_MASK 0x1 +#define MT6351_PMIC_MIX_EOSC32_STP_LPDEN_SHIFT 2 +#define MT6351_PMIC_MIX_XOSC32_STP_PWDB_ADDR MT6351_RTC_MIX_CON0 +#define MT6351_PMIC_MIX_XOSC32_STP_PWDB_MASK 0x1 +#define MT6351_PMIC_MIX_XOSC32_STP_PWDB_SHIFT 3 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDTB_ADDR MT6351_RTC_MIX_CON0 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDTB_MASK 0x1 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDTB_SHIFT 4 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDEN_ADDR MT6351_RTC_MIX_CON0 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDEN_MASK 0x1 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDEN_SHIFT 5 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDRST_ADDR MT6351_RTC_MIX_CON0 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDRST_MASK 0x1 +#define MT6351_PMIC_MIX_XOSC32_STP_LPDRST_SHIFT 6 +#define MT6351_PMIC_MIX_XOSC32_STP_CALI_ADDR MT6351_RTC_MIX_CON0 +#define MT6351_PMIC_MIX_XOSC32_STP_CALI_MASK 0x1F +#define MT6351_PMIC_MIX_XOSC32_STP_CALI_SHIFT 7 +#define MT6351_PMIC_STMP_MODE_ADDR MT6351_RTC_MIX_CON0 +#define MT6351_PMIC_STMP_MODE_MASK 0x1 +#define MT6351_PMIC_STMP_MODE_SHIFT 12 +#define MT6351_PMIC_MIX_EOSC32_STP_CHOP_EN_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_EOSC32_STP_CHOP_EN_MASK 0x1 +#define MT6351_PMIC_MIX_EOSC32_STP_CHOP_EN_SHIFT 0 +#define MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_MASK 0x1 +#define MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_SHIFT 1 +#define MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_MASK 0x1 +#define MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_SHIFT 2 +#define MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_EN_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_EN_MASK 0x1 +#define MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_EN_SHIFT 3 +#define MT6351_PMIC_MIX_RTC_STP_XOSC32_ENB_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_RTC_STP_XOSC32_ENB_MASK 0x1 +#define MT6351_PMIC_MIX_RTC_STP_XOSC32_ENB_SHIFT 4 +#define MT6351_PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_MASK 0x1 +#define MT6351_PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_SHIFT 5 +#define MT6351_PMIC_MIX_EOSC32_STP_RSV_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_EOSC32_STP_RSV_MASK 0x3 +#define MT6351_PMIC_MIX_EOSC32_STP_RSV_SHIFT 6 +#define MT6351_PMIC_MIX_EOSC32_VCT_EN_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_EOSC32_VCT_EN_MASK 0x1 +#define MT6351_PMIC_MIX_EOSC32_VCT_EN_SHIFT 8 +#define MT6351_PMIC_MIX_EOSC32_OPT_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_EOSC32_OPT_MASK 0x3 +#define MT6351_PMIC_MIX_EOSC32_OPT_SHIFT 9 +#define MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_INT_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_INT_MASK 0x1 +#define MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_INT_SHIFT 11 +#define MT6351_PMIC_MIX_RTC_GPIO_COREDETB_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_RTC_GPIO_COREDETB_MASK 0x1 +#define MT6351_PMIC_MIX_RTC_GPIO_COREDETB_SHIFT 12 +#define MT6351_PMIC_MIX_RTC_GPIO_F32KOB_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_RTC_GPIO_F32KOB_MASK 0x1 +#define MT6351_PMIC_MIX_RTC_GPIO_F32KOB_SHIFT 13 +#define MT6351_PMIC_MIX_RTC_GPIO_GPO_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_RTC_GPIO_GPO_MASK 0x1 +#define MT6351_PMIC_MIX_RTC_GPIO_GPO_SHIFT 14 +#define MT6351_PMIC_MIX_RTC_GPIO_OE_ADDR MT6351_RTC_MIX_CON1 +#define MT6351_PMIC_MIX_RTC_GPIO_OE_MASK 0x1 +#define MT6351_PMIC_MIX_RTC_GPIO_OE_SHIFT 15 +#define MT6351_PMIC_MIX_RTC_STP_DEBUG_OUT_ADDR MT6351_RTC_MIX_CON2 +#define MT6351_PMIC_MIX_RTC_STP_DEBUG_OUT_MASK 0x3 +#define MT6351_PMIC_MIX_RTC_STP_DEBUG_OUT_SHIFT 0 +#define MT6351_PMIC_MIX_RTC_STP_DEBUG_SEL_ADDR MT6351_RTC_MIX_CON2 +#define MT6351_PMIC_MIX_RTC_STP_DEBUG_SEL_MASK 0x3 +#define MT6351_PMIC_MIX_RTC_STP_DEBUG_SEL_SHIFT 4 +#define MT6351_PMIC_MIX_RTC_STP_K_EOSC32_EN_ADDR MT6351_RTC_MIX_CON2 +#define MT6351_PMIC_MIX_RTC_STP_K_EOSC32_EN_MASK 0x1 +#define MT6351_PMIC_MIX_RTC_STP_K_EOSC32_EN_SHIFT 7 +#define MT6351_PMIC_MIX_RTC_STP_EMBCK_SEL_ADDR MT6351_RTC_MIX_CON2 +#define MT6351_PMIC_MIX_RTC_STP_EMBCK_SEL_MASK 0x1 +#define MT6351_PMIC_MIX_RTC_STP_EMBCK_SEL_SHIFT 8 +#define MT6351_PMIC_MIX_STP_BBWAKEUP_ADDR MT6351_RTC_MIX_CON2 +#define MT6351_PMIC_MIX_STP_BBWAKEUP_MASK 0x1 +#define MT6351_PMIC_MIX_STP_BBWAKEUP_SHIFT 9 +#define MT6351_PMIC_MIX_STP_RTC_DDLO_ADDR MT6351_RTC_MIX_CON2 +#define MT6351_PMIC_MIX_STP_RTC_DDLO_MASK 0x1 +#define MT6351_PMIC_MIX_STP_RTC_DDLO_SHIFT 10 +#define MT6351_PMIC_MIX_RTC_XOSC32_ENB_ADDR MT6351_RTC_MIX_CON2 +#define MT6351_PMIC_MIX_RTC_XOSC32_ENB_MASK 0x1 +#define MT6351_PMIC_MIX_RTC_XOSC32_ENB_SHIFT 11 +#define MT6351_PMIC_MIX_EFUSE_XOSC32_ENB_OPT_ADDR MT6351_RTC_MIX_CON2 +#define MT6351_PMIC_MIX_EFUSE_XOSC32_ENB_OPT_MASK 0x1 +#define MT6351_PMIC_MIX_EFUSE_XOSC32_ENB_OPT_SHIFT 12 +#define MT6351_PMIC_FG_ON_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_ON_MASK 0x1 +#define MT6351_PMIC_FG_ON_SHIFT 0 +#define MT6351_PMIC_FG_CAL_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_CAL_MASK 0x3 +#define MT6351_PMIC_FG_CAL_SHIFT 2 +#define MT6351_PMIC_FG_AUTOCALRATE_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_AUTOCALRATE_MASK 0x7 +#define MT6351_PMIC_FG_AUTOCALRATE_SHIFT 4 +#define MT6351_PMIC_FG_SW_CR_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_SW_CR_MASK 0x1 +#define MT6351_PMIC_FG_SW_CR_SHIFT 8 +#define MT6351_PMIC_FG_SW_READ_PRE_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_SW_READ_PRE_MASK 0x1 +#define MT6351_PMIC_FG_SW_READ_PRE_SHIFT 9 +#define MT6351_PMIC_FG_LATCHDATA_ST_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_LATCHDATA_ST_MASK 0x1 +#define MT6351_PMIC_FG_LATCHDATA_ST_SHIFT 10 +#define MT6351_PMIC_FG_SW_CLEAR_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_SW_CLEAR_MASK 0x1 +#define MT6351_PMIC_FG_SW_CLEAR_SHIFT 11 +#define MT6351_PMIC_FG_OFFSET_RST_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_OFFSET_RST_MASK 0x1 +#define MT6351_PMIC_FG_OFFSET_RST_SHIFT 12 +#define MT6351_PMIC_FG_TIME_RST_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_TIME_RST_MASK 0x1 +#define MT6351_PMIC_FG_TIME_RST_SHIFT 13 +#define MT6351_PMIC_FG_CHARGE_RST_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_CHARGE_RST_MASK 0x1 +#define MT6351_PMIC_FG_CHARGE_RST_SHIFT 14 +#define MT6351_PMIC_FG_SW_RSTCLR_ADDR MT6351_FGADC_CON0 +#define MT6351_PMIC_FG_SW_RSTCLR_MASK 0x1 +#define MT6351_PMIC_FG_SW_RSTCLR_SHIFT 15 +#define MT6351_PMIC_FG_CAR_34_19_ADDR MT6351_FGADC_CON1 +#define MT6351_PMIC_FG_CAR_34_19_MASK 0xFFFF +#define MT6351_PMIC_FG_CAR_34_19_SHIFT 0 +#define MT6351_PMIC_FG_CAR_18_03_ADDR MT6351_FGADC_CON2 +#define MT6351_PMIC_FG_CAR_18_03_MASK 0xFFFF +#define MT6351_PMIC_FG_CAR_18_03_SHIFT 0 +#define MT6351_PMIC_FG_CAR_02_00_ADDR MT6351_FGADC_CON3 +#define MT6351_PMIC_FG_CAR_02_00_MASK 0x7 +#define MT6351_PMIC_FG_CAR_02_00_SHIFT 0 +#define MT6351_PMIC_FG_NTER_32_17_ADDR MT6351_FGADC_CON4 +#define MT6351_PMIC_FG_NTER_32_17_MASK 0xFFFF +#define MT6351_PMIC_FG_NTER_32_17_SHIFT 0 +#define MT6351_PMIC_FG_NTER_16_01_ADDR MT6351_FGADC_CON5 +#define MT6351_PMIC_FG_NTER_16_01_MASK 0xFFFF +#define MT6351_PMIC_FG_NTER_16_01_SHIFT 0 +#define MT6351_PMIC_FG_NTER_00_ADDR MT6351_FGADC_CON6 +#define MT6351_PMIC_FG_NTER_00_MASK 0x1 +#define MT6351_PMIC_FG_NTER_00_SHIFT 0 +#define MT6351_PMIC_FG_BLTR_31_16_ADDR MT6351_FGADC_CON7 +#define MT6351_PMIC_FG_BLTR_31_16_MASK 0xFFFF +#define MT6351_PMIC_FG_BLTR_31_16_SHIFT 0 +#define MT6351_PMIC_FG_BLTR_15_00_ADDR MT6351_FGADC_CON8 +#define MT6351_PMIC_FG_BLTR_15_00_MASK 0xFFFF +#define MT6351_PMIC_FG_BLTR_15_00_SHIFT 0 +#define MT6351_PMIC_FG_BFTR_31_16_ADDR MT6351_FGADC_CON9 +#define MT6351_PMIC_FG_BFTR_31_16_MASK 0xFFFF +#define MT6351_PMIC_FG_BFTR_31_16_SHIFT 0 +#define MT6351_PMIC_FG_BFTR_15_00_ADDR MT6351_FGADC_CON10 +#define MT6351_PMIC_FG_BFTR_15_00_MASK 0xFFFF +#define MT6351_PMIC_FG_BFTR_15_00_SHIFT 0 +#define MT6351_PMIC_FG_CURRENT_OUT_ADDR MT6351_FGADC_CON11 +#define MT6351_PMIC_FG_CURRENT_OUT_MASK 0xFFFF +#define MT6351_PMIC_FG_CURRENT_OUT_SHIFT 0 +#define MT6351_PMIC_FG_ADJUST_OFFSET_VALUE_ADDR MT6351_FGADC_CON12 +#define MT6351_PMIC_FG_ADJUST_OFFSET_VALUE_MASK 0xFFFF +#define MT6351_PMIC_FG_ADJUST_OFFSET_VALUE_SHIFT 0 +#define MT6351_PMIC_FG_OFFSET_ADDR MT6351_FGADC_CON13 +#define MT6351_PMIC_FG_OFFSET_MASK 0xFFFF +#define MT6351_PMIC_FG_OFFSET_SHIFT 0 +#define MT6351_PMIC_RG_FGANALOGTEST_ADDR MT6351_FGADC_CON14 +#define MT6351_PMIC_RG_FGANALOGTEST_MASK 0xF +#define MT6351_PMIC_RG_FGANALOGTEST_SHIFT 0 +#define MT6351_PMIC_RG_FGRINTMODE_ADDR MT6351_FGADC_CON14 +#define MT6351_PMIC_RG_FGRINTMODE_MASK 0x1 +#define MT6351_PMIC_RG_FGRINTMODE_SHIFT 4 +#define MT6351_PMIC_RG_SPARE_ADDR MT6351_FGADC_CON14 +#define MT6351_PMIC_RG_SPARE_MASK 0xFF +#define MT6351_PMIC_RG_SPARE_SHIFT 5 +#define MT6351_PMIC_FG_OSR_ADDR MT6351_FGADC_CON15 +#define MT6351_PMIC_FG_OSR_MASK 0xF +#define MT6351_PMIC_FG_OSR_SHIFT 0 +#define MT6351_PMIC_FG_ADJ_OFFSET_EN_ADDR MT6351_FGADC_CON15 +#define MT6351_PMIC_FG_ADJ_OFFSET_EN_MASK 0x1 +#define MT6351_PMIC_FG_ADJ_OFFSET_EN_SHIFT 8 +#define MT6351_PMIC_FG_ADC_AUTORST_ADDR MT6351_FGADC_CON15 +#define MT6351_PMIC_FG_ADC_AUTORST_MASK 0x1 +#define MT6351_PMIC_FG_ADC_AUTORST_SHIFT 9 +#define MT6351_PMIC_FG_FIR1BYPASS_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_FIR1BYPASS_MASK 0x1 +#define MT6351_PMIC_FG_FIR1BYPASS_SHIFT 0 +#define MT6351_PMIC_FG_FIR2BYPASS_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_FIR2BYPASS_MASK 0x1 +#define MT6351_PMIC_FG_FIR2BYPASS_SHIFT 1 +#define MT6351_PMIC_FG_L_CUR_INT_STS_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_L_CUR_INT_STS_MASK 0x1 +#define MT6351_PMIC_FG_L_CUR_INT_STS_SHIFT 2 +#define MT6351_PMIC_FG_H_CUR_INT_STS_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_H_CUR_INT_STS_MASK 0x1 +#define MT6351_PMIC_FG_H_CUR_INT_STS_SHIFT 3 +#define MT6351_PMIC_FG_L_INT_STS_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_L_INT_STS_MASK 0x1 +#define MT6351_PMIC_FG_L_INT_STS_SHIFT 4 +#define MT6351_PMIC_FG_H_INT_STS_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_H_INT_STS_MASK 0x1 +#define MT6351_PMIC_FG_H_INT_STS_SHIFT 5 +#define MT6351_PMIC_FG_ADC_RSTDETECT_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_ADC_RSTDETECT_MASK 0x1 +#define MT6351_PMIC_FG_ADC_RSTDETECT_SHIFT 7 +#define MT6351_PMIC_FG_SLP_EN_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_SLP_EN_MASK 0x1 +#define MT6351_PMIC_FG_SLP_EN_SHIFT 8 +#define MT6351_PMIC_FG_ZCV_DET_EN_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_FG_ZCV_DET_EN_MASK 0x1 +#define MT6351_PMIC_FG_ZCV_DET_EN_SHIFT 9 +#define MT6351_PMIC_RG_FG_AUXADC_R_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_RG_FG_AUXADC_R_MASK 0x1 +#define MT6351_PMIC_RG_FG_AUXADC_R_SHIFT 10 +#define MT6351_PMIC_DA_FGADC_EN_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_DA_FGADC_EN_MASK 0x1 +#define MT6351_PMIC_DA_FGADC_EN_SHIFT 12 +#define MT6351_PMIC_DA_FGCAL_EN_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_DA_FGCAL_EN_MASK 0x1 +#define MT6351_PMIC_DA_FGCAL_EN_SHIFT 13 +#define MT6351_PMIC_DA_FG_RST_ADDR MT6351_FGADC_CON16 +#define MT6351_PMIC_DA_FG_RST_MASK 0x1 +#define MT6351_PMIC_DA_FG_RST_SHIFT 14 +#define MT6351_PMIC_FG_CIC2_ADDR MT6351_FGADC_CON17 +#define MT6351_PMIC_FG_CIC2_MASK 0xFFFF +#define MT6351_PMIC_FG_CIC2_SHIFT 0 +#define MT6351_PMIC_FG_SLP_CUR_TH_ADDR MT6351_FGADC_CON18 +#define MT6351_PMIC_FG_SLP_CUR_TH_MASK 0xFFFF +#define MT6351_PMIC_FG_SLP_CUR_TH_SHIFT 0 +#define MT6351_PMIC_FG_SLP_TIME_ADDR MT6351_FGADC_CON19 +#define MT6351_PMIC_FG_SLP_TIME_MASK 0xFF +#define MT6351_PMIC_FG_SLP_TIME_SHIFT 0 +#define MT6351_PMIC_FG_SRCVOLTEN_FTIME_ADDR MT6351_FGADC_CON20 +#define MT6351_PMIC_FG_SRCVOLTEN_FTIME_MASK 0xFF +#define MT6351_PMIC_FG_SRCVOLTEN_FTIME_SHIFT 0 +#define MT6351_PMIC_FG_DET_TIME_ADDR MT6351_FGADC_CON20 +#define MT6351_PMIC_FG_DET_TIME_MASK 0xFF +#define MT6351_PMIC_FG_DET_TIME_SHIFT 8 +#define MT6351_PMIC_FG_ZCV_CAR_34_19_ADDR MT6351_FGADC_CON21 +#define MT6351_PMIC_FG_ZCV_CAR_34_19_MASK 0xFFFF +#define MT6351_PMIC_FG_ZCV_CAR_34_19_SHIFT 0 +#define MT6351_PMIC_FG_ZCV_CAR_18_03_ADDR MT6351_FGADC_CON22 +#define MT6351_PMIC_FG_ZCV_CAR_18_03_MASK 0xFFFF +#define MT6351_PMIC_FG_ZCV_CAR_18_03_SHIFT 0 +#define MT6351_PMIC_FG_ZCV_CAR_02_00_ADDR MT6351_FGADC_CON23 +#define MT6351_PMIC_FG_ZCV_CAR_02_00_MASK 0x7 +#define MT6351_PMIC_FG_ZCV_CAR_02_00_SHIFT 0 +#define MT6351_PMIC_FG_ZCV_CURR_ADDR MT6351_FGADC_CON24 +#define MT6351_PMIC_FG_ZCV_CURR_MASK 0xFFFF +#define MT6351_PMIC_FG_ZCV_CURR_SHIFT 0 +#define MT6351_PMIC_FG_R_CURR_ADDR MT6351_FGADC_CON25 +#define MT6351_PMIC_FG_R_CURR_MASK 0xFFFF +#define MT6351_PMIC_FG_R_CURR_SHIFT 0 +#define MT6351_PMIC_FG_MODE_ADDR MT6351_FGADC_CON26 +#define MT6351_PMIC_FG_MODE_MASK 0x1 +#define MT6351_PMIC_FG_MODE_SHIFT 0 +#define MT6351_PMIC_FG_RST_SW_ADDR MT6351_FGADC_CON26 +#define MT6351_PMIC_FG_RST_SW_MASK 0x1 +#define MT6351_PMIC_FG_RST_SW_SHIFT 1 +#define MT6351_PMIC_FG_FGCAL_EN_SW_ADDR MT6351_FGADC_CON26 +#define MT6351_PMIC_FG_FGCAL_EN_SW_MASK 0x1 +#define MT6351_PMIC_FG_FGCAL_EN_SW_SHIFT 2 +#define MT6351_PMIC_FG_FGADC_EN_SW_ADDR MT6351_FGADC_CON26 +#define MT6351_PMIC_FG_FGADC_EN_SW_MASK 0x1 +#define MT6351_PMIC_FG_FGADC_EN_SW_SHIFT 3 +#define MT6351_PMIC_FG_RSV1_ADDR MT6351_FGADC_CON26 +#define MT6351_PMIC_FG_RSV1_MASK 0xF +#define MT6351_PMIC_FG_RSV1_SHIFT 4 +#define MT6351_PMIC_FG_TEST_MODE0_ADDR MT6351_FGADC_CON26 +#define MT6351_PMIC_FG_TEST_MODE0_MASK 0x1 +#define MT6351_PMIC_FG_TEST_MODE0_SHIFT 14 +#define MT6351_PMIC_FG_TEST_MODE1_ADDR MT6351_FGADC_CON26 +#define MT6351_PMIC_FG_TEST_MODE1_MASK 0x1 +#define MT6351_PMIC_FG_TEST_MODE1_SHIFT 15 +#define MT6351_PMIC_FG_GAIN_ADDR MT6351_FGADC_CON27 +#define MT6351_PMIC_FG_GAIN_MASK 0x1FFF +#define MT6351_PMIC_FG_GAIN_SHIFT 0 +#define MT6351_PMIC_FG_CUR_HTH_ADDR MT6351_FGADC_CON28 +#define MT6351_PMIC_FG_CUR_HTH_MASK 0xFFFF +#define MT6351_PMIC_FG_CUR_HTH_SHIFT 0 +#define MT6351_PMIC_FG_CUR_LTH_ADDR MT6351_FGADC_CON29 +#define MT6351_PMIC_FG_CUR_LTH_MASK 0xFFFF +#define MT6351_PMIC_FG_CUR_LTH_SHIFT 0 +#define MT6351_PMIC_FG_ZCV_DET_TIME_ADDR MT6351_FGADC_CON30 +#define MT6351_PMIC_FG_ZCV_DET_TIME_MASK 0x3F +#define MT6351_PMIC_FG_ZCV_DET_TIME_SHIFT 0 +#define MT6351_PMIC_FG_ZCV_CAR_TH_33_19_ADDR MT6351_FGADC_CON31 +#define MT6351_PMIC_FG_ZCV_CAR_TH_33_19_MASK 0x7FFF +#define MT6351_PMIC_FG_ZCV_CAR_TH_33_19_SHIFT 0 +#define MT6351_PMIC_FG_ZCV_CAR_TH_18_03_ADDR MT6351_FGADC_CON32 +#define MT6351_PMIC_FG_ZCV_CAR_TH_18_03_MASK 0xFFFF +#define MT6351_PMIC_FG_ZCV_CAR_TH_18_03_SHIFT 0 +#define MT6351_PMIC_FG_ZCV_CAR_TH_02_00_ADDR MT6351_FGADC_CON33 +#define MT6351_PMIC_FG_ZCV_CAR_TH_02_00_MASK 0x7 +#define MT6351_PMIC_FG_ZCV_CAR_TH_02_00_SHIFT 0 +#define MT6351_PMIC_SYSTEM_INFO_CON0_ADDR MT6351_SYSTEM_INFO_CON0 +#define MT6351_PMIC_SYSTEM_INFO_CON0_MASK 0xFFFF +#define MT6351_PMIC_SYSTEM_INFO_CON0_SHIFT 0 +#define MT6351_PMIC_SYSTEM_INFO_CON1_ADDR MT6351_SYSTEM_INFO_CON1 +#define MT6351_PMIC_SYSTEM_INFO_CON1_MASK 0xFFFF +#define MT6351_PMIC_SYSTEM_INFO_CON1_SHIFT 0 +#define MT6351_PMIC_SYSTEM_INFO_CON2_ADDR MT6351_SYSTEM_INFO_CON2 +#define MT6351_PMIC_SYSTEM_INFO_CON2_MASK 0xFFFF +#define MT6351_PMIC_SYSTEM_INFO_CON2_SHIFT 0 +#define MT6351_PMIC_SYSTEM_INFO_CON3_ADDR MT6351_SYSTEM_INFO_CON3 +#define MT6351_PMIC_SYSTEM_INFO_CON3_MASK 0xFFFF +#define MT6351_PMIC_SYSTEM_INFO_CON3_SHIFT 0 +#define MT6351_PMIC_SYSTEM_INFO_CON4_ADDR MT6351_SYSTEM_INFO_CON4 +#define MT6351_PMIC_SYSTEM_INFO_CON4_MASK 0xFFFF +#define MT6351_PMIC_SYSTEM_INFO_CON4_SHIFT 0 +#define MT6351_PMIC_RG_AUDDACLPWRUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDDACLPWRUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDDACLPWRUP_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_AUDDACRPWRUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDDACRPWRUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDDACRPWRUP_VAUDP32_SHIFT 1 +#define MT6351_PMIC_RG_AUD_DAC_PWR_UP_VA32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUD_DAC_PWR_UP_VA32_MASK 0x1 +#define MT6351_PMIC_RG_AUD_DAC_PWR_UP_VA32_SHIFT 2 +#define MT6351_PMIC_RG_AUD_DAC_PWL_UP_VA32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUD_DAC_PWL_UP_VA32_MASK 0x1 +#define MT6351_PMIC_RG_AUD_DAC_PWL_UP_VA32_SHIFT 3 +#define MT6351_PMIC_RG_AUDHSPWRUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHSPWRUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHSPWRUP_VAUDP32_SHIFT 4 +#define MT6351_PMIC_RG_AUDHPLPWRUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHPLPWRUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPLPWRUP_VAUDP32_SHIFT 5 +#define MT6351_PMIC_RG_AUDHPRPWRUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHPRPWRUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPRPWRUP_VAUDP32_SHIFT 6 +#define MT6351_PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32_SHIFT 7 +#define MT6351_PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32_SHIFT 9 +#define MT6351_PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32_SHIFT 11 +#define MT6351_PMIC_RG_AUDHSSCDISABLE_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHSSCDISABLE_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHSSCDISABLE_VAUDP32_SHIFT 13 +#define MT6351_PMIC_RG_AUDHPLSCDISABLE_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHPLSCDISABLE_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPLSCDISABLE_VAUDP32_SHIFT 14 +#define MT6351_PMIC_RG_AUDHPRSCDISABLE_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON0 +#define MT6351_PMIC_RG_AUDHPRSCDISABLE_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPRSCDISABLE_VAUDP32_SHIFT 15 +#define MT6351_PMIC_RG_AUDHSBSCCURRENT_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_AUDHSBSCCURRENT_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHSBSCCURRENT_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_AUDHPLBSCCURRENT_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_AUDHPLBSCCURRENT_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPLBSCCURRENT_VAUDP32_SHIFT 1 +#define MT6351_PMIC_RG_AUDHPRBSCCURRENT_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_AUDHPRBSCCURRENT_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPRBSCCURRENT_VAUDP32_SHIFT 2 +#define MT6351_PMIC_RG_AUDHSSTARTUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_AUDHSSTARTUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHSSTARTUP_VAUDP32_SHIFT 3 +#define MT6351_PMIC_RG_AUDHPSTARTUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_AUDHPSTARTUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPSTARTUP_VAUDP32_SHIFT 4 +#define MT6351_PMIC_RG_AUDBGBON_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_AUDBGBON_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDBGBON_VAUDP32_SHIFT 5 +#define MT6351_PMIC_RG_PRECHARGEBUF_EN_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_PRECHARGEBUF_EN_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_PRECHARGEBUF_EN_VAUDP32_SHIFT 6 +#define MT6351_PMIC_RG_HSINPUTSTBENH_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HSINPUTSTBENH_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HSINPUTSTBENH_VAUDP32_SHIFT 7 +#define MT6351_PMIC_RG_HSOUTPUTSTBENH_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HSOUTPUTSTBENH_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HSOUTPUTSTBENH_VAUDP32_SHIFT 8 +#define MT6351_PMIC_RG_HSINPUTRESET0_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HSINPUTRESET0_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HSINPUTRESET0_VAUDP32_SHIFT 9 +#define MT6351_PMIC_RG_HSOUTPUTRESET0_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HSOUTPUTRESET0_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HSOUTPUTRESET0_VAUDP32_SHIFT 10 +#define MT6351_PMIC_RG_HSOUT_SHORTVCM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HSOUT_SHORTVCM_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HSOUT_SHORTVCM_VAUDP32_SHIFT 11 +#define MT6351_PMIC_RG_HPINPUTSTBENH_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HPINPUTSTBENH_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HPINPUTSTBENH_VAUDP32_SHIFT 12 +#define MT6351_PMIC_RG_HPOUTPUTSTBENH_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HPOUTPUTSTBENH_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HPOUTPUTSTBENH_VAUDP32_SHIFT 13 +#define MT6351_PMIC_RG_HPINPUTRESET0_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HPINPUTRESET0_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HPINPUTRESET0_VAUDP32_SHIFT 14 +#define MT6351_PMIC_RG_HPOUTPUTRESET0_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON1 +#define MT6351_PMIC_RG_HPOUTPUTRESET0_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HPOUTPUTRESET0_VAUDP32_SHIFT 15 +#define MT6351_PMIC_RG_HPOUT_SHORTVCM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON2 +#define MT6351_PMIC_RG_HPOUT_SHORTVCM_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_HPOUT_SHORTVCM_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_HPOUTSTB_RSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON2 +#define MT6351_PMIC_RG_HPOUTSTB_RSEL_VAUDP32_MASK 0x7 +#define MT6351_PMIC_RG_HPOUTSTB_RSEL_VAUDP32_SHIFT 1 +#define MT6351_PMIC_RG_LINENOISEENH_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON2 +#define MT6351_PMIC_RG_LINENOISEENH_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_LINENOISEENH_VAUDP32_SHIFT 4 +#define MT6351_PMIC_RG_AUDHPLTRIM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON2 +#define MT6351_PMIC_RG_AUDHPLTRIM_VAUDP32_MASK 0xF +#define MT6351_PMIC_RG_AUDHPLTRIM_VAUDP32_SHIFT 5 +#define MT6351_PMIC_RG_AUDHPRTRIM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON2 +#define MT6351_PMIC_RG_AUDHPRTRIM_VAUDP32_MASK 0xF +#define MT6351_PMIC_RG_AUDHPRTRIM_VAUDP32_SHIFT 9 +#define MT6351_PMIC_RG_AUDHPTRIM_EN_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON2 +#define MT6351_PMIC_RG_AUDHPTRIM_EN_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPTRIM_EN_VAUDP32_SHIFT 13 +#define MT6351_PMIC_RG_AUDHPLFINETRIM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON2 +#define MT6351_PMIC_RG_AUDHPLFINETRIM_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDHPLFINETRIM_VAUDP32_SHIFT 14 +#define MT6351_PMIC_RG_AUDHPRFINETRIM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_AUDHPRFINETRIM_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDHPRFINETRIM_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_AUDLOLPWRUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_AUDLOLPWRUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDLOLPWRUP_VAUDP32_SHIFT 2 +#define MT6351_PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32_SHIFT 3 +#define MT6351_PMIC_RG_AUDLOLSCDISABLE_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_AUDLOLSCDISABLE_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDLOLSCDISABLE_VAUDP32_SHIFT 5 +#define MT6351_PMIC_RG_AUDLOLBSCCURRENT_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_AUDLOLBSCCURRENT_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDLOLBSCCURRENT_VAUDP32_SHIFT 6 +#define MT6351_PMIC_RG_AUDLOSTARTUP_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_AUDLOSTARTUP_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDLOSTARTUP_VAUDP32_SHIFT 7 +#define MT6351_PMIC_RG_LOINPUTSTBENH_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_LOINPUTSTBENH_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_LOINPUTSTBENH_VAUDP32_SHIFT 8 +#define MT6351_PMIC_RG_LOOUTPUTSTBENH_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_LOOUTPUTSTBENH_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_LOOUTPUTSTBENH_VAUDP32_SHIFT 9 +#define MT6351_PMIC_RG_LOINPUTRESET0_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_LOINPUTRESET0_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_LOINPUTRESET0_VAUDP32_SHIFT 10 +#define MT6351_PMIC_RG_LOOUTPUTRESET0_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_LOOUTPUTRESET0_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_LOOUTPUTRESET0_VAUDP32_SHIFT 11 +#define MT6351_PMIC_RG_LOOUT_SHORTVCM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_LOOUT_SHORTVCM_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_LOOUT_SHORTVCM_VAUDP32_SHIFT 12 +#define MT6351_PMIC_RG_LOOUTSTB_RSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON3 +#define MT6351_PMIC_RG_LOOUTSTB_RSEL_VAUDP32_MASK 0x7 +#define MT6351_PMIC_RG_LOOUTSTB_RSEL_VAUDP32_SHIFT 13 +#define MT6351_PMIC_RG_AUDLOLTRIM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON4 +#define MT6351_PMIC_RG_AUDLOLTRIM_VAUDP32_MASK 0xF +#define MT6351_PMIC_RG_AUDLOLTRIM_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_AUDLOTRIM_EN_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON4 +#define MT6351_PMIC_RG_AUDLOTRIM_EN_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDLOTRIM_EN_VAUDP32_SHIFT 4 +#define MT6351_PMIC_RG_AUDLOLFINETRIM_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON4 +#define MT6351_PMIC_RG_AUDLOLFINETRIM_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDLOLFINETRIM_VAUDP32_SHIFT 5 +#define MT6351_PMIC_RG_AUDTRIMBUF_EN_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON4 +#define MT6351_PMIC_RG_AUDTRIMBUF_EN_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDTRIMBUF_EN_VAUDP32_SHIFT 7 +#define MT6351_PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON4 +#define MT6351_PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_MASK 0xF +#define MT6351_PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_SHIFT 8 +#define MT6351_PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON4 +#define MT6351_PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32_SHIFT 12 +#define MT6351_PMIC_RG_AUDHPSPKDET_EN_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON4 +#define MT6351_PMIC_RG_AUDHPSPKDET_EN_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDHPSPKDET_EN_VAUDP32_SHIFT 14 +#define MT6351_PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON5 +#define MT6351_PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON5 +#define MT6351_PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_MASK 0x3 +#define MT6351_PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_SHIFT 2 +#define MT6351_PMIC_RG_ABIDEC_RSVD0_VA32_ADDR MT6351_AUDDEC_ANA_CON5 +#define MT6351_PMIC_RG_ABIDEC_RSVD0_VA32_MASK 0xFF +#define MT6351_PMIC_RG_ABIDEC_RSVD0_VA32_SHIFT 4 +#define MT6351_PMIC_RG_ABIDEC_RSVD1_VA32_ADDR MT6351_AUDDEC_ANA_CON6 +#define MT6351_PMIC_RG_ABIDEC_RSVD1_VA32_MASK 0xFF +#define MT6351_PMIC_RG_ABIDEC_RSVD1_VA32_SHIFT 0 +#define MT6351_PMIC_RG_ABIDEC_RSVD0_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON6 +#define MT6351_PMIC_RG_ABIDEC_RSVD0_VAUDP32_MASK 0xFF +#define MT6351_PMIC_RG_ABIDEC_RSVD0_VAUDP32_SHIFT 8 +#define MT6351_PMIC_RG_ABIDEC_RSVD1_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON7 +#define MT6351_PMIC_RG_ABIDEC_RSVD1_VAUDP32_MASK 0xFF +#define MT6351_PMIC_RG_ABIDEC_RSVD1_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON7 +#define MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP32_MASK 0x7 +#define MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP32_SHIFT 8 +#define MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON7 +#define MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP32_SHIFT 11 +#define MT6351_PMIC_RG_AUDBIASADJ_0_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON8 +#define MT6351_PMIC_RG_AUDBIASADJ_0_VAUDP32_MASK 0x1FF +#define MT6351_PMIC_RG_AUDBIASADJ_0_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_AUDBIASADJ_1_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_AUDBIASADJ_1_VAUDP32_MASK 0xFF +#define MT6351_PMIC_RG_AUDBIASADJ_1_VAUDP32_SHIFT 0 +#define MT6351_PMIC_RG_AUDIBIASPWRDN_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_AUDIBIASPWRDN_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_AUDIBIASPWRDN_VAUDP32_SHIFT 8 +#define MT6351_PMIC_RG_RSTB_DECODER_VA32_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_RSTB_DECODER_VA32_MASK 0x1 +#define MT6351_PMIC_RG_RSTB_DECODER_VA32_SHIFT 9 +#define MT6351_PMIC_RG_SEL_DECODER_96K_VA32_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_SEL_DECODER_96K_VA32_MASK 0x1 +#define MT6351_PMIC_RG_SEL_DECODER_96K_VA32_SHIFT 10 +#define MT6351_PMIC_RG_SEL_DELAY_VCORE_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_SEL_DELAY_VCORE_MASK 0x1 +#define MT6351_PMIC_RG_SEL_DELAY_VCORE_SHIFT 11 +#define MT6351_PMIC_RG_AUDGLB_PWRDN_VA32_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_AUDGLB_PWRDN_VA32_MASK 0x1 +#define MT6351_PMIC_RG_AUDGLB_PWRDN_VA32_SHIFT 12 +#define MT6351_PMIC_RG_LCLDO_DEC_EN_VA32_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_LCLDO_DEC_EN_VA32_MASK 0x1 +#define MT6351_PMIC_RG_LCLDO_DEC_EN_VA32_SHIFT 13 +#define MT6351_PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18_MASK 0x1 +#define MT6351_PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18_SHIFT 14 +#define MT6351_PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18_ADDR MT6351_AUDDEC_ANA_CON9 +#define MT6351_PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18_MASK 0x1 +#define MT6351_PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18_SHIFT 15 +#define MT6351_PMIC_RG_AUDPMU_RSVD_VA18_ADDR MT6351_AUDDEC_ANA_CON10 +#define MT6351_PMIC_RG_AUDPMU_RSVD_VA18_MASK 0xFF +#define MT6351_PMIC_RG_AUDPMU_RSVD_VA18_SHIFT 0 +#define MT6351_PMIC_RG_NVREG_EN_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON10 +#define MT6351_PMIC_RG_NVREG_EN_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_NVREG_EN_VAUDP32_SHIFT 8 +#define MT6351_PMIC_RG_NVREG_PULL0V_VAUDP32_ADDR MT6351_AUDDEC_ANA_CON10 +#define MT6351_PMIC_RG_NVREG_PULL0V_VAUDP32_MASK 0x1 +#define MT6351_PMIC_RG_NVREG_PULL0V_VAUDP32_SHIFT 9 +#define MT6351_PMIC_RG_AUDGLB_LP2_VOW_EN_VA32_ADDR MT6351_AUDDEC_ANA_CON10 +#define MT6351_PMIC_RG_AUDGLB_LP2_VOW_EN_VA32_MASK 0x1 +#define MT6351_PMIC_RG_AUDGLB_LP2_VOW_EN_VA32_SHIFT 10 +#define MT6351_PMIC_RG_AUDPREAMPLON_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDPREAMPLON_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPLON_SHIFT 0 +#define MT6351_PMIC_RG_AUDPREAMPLDCCEN_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDPREAMPLDCCEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPLDCCEN_SHIFT 1 +#define MT6351_PMIC_RG_AUDPREAMPLDCPRECHARGE_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDPREAMPLDCPRECHARGE_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPLDCPRECHARGE_SHIFT 2 +#define MT6351_PMIC_RG_AUDPREAMPLPGATEST_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDPREAMPLPGATEST_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPLPGATEST_SHIFT 3 +#define MT6351_PMIC_RG_AUDPREAMPLINPUTSEL_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDPREAMPLINPUTSEL_MASK 0x3 +#define MT6351_PMIC_RG_AUDPREAMPLINPUTSEL_SHIFT 4 +#define MT6351_PMIC_RG_AUDPREAMPLVSCALE_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDPREAMPLVSCALE_MASK 0x3 +#define MT6351_PMIC_RG_AUDPREAMPLVSCALE_SHIFT 6 +#define MT6351_PMIC_RG_AUDPREAMPLGAIN_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDPREAMPLGAIN_MASK 0x7 +#define MT6351_PMIC_RG_AUDPREAMPLGAIN_SHIFT 8 +#define MT6351_PMIC_RG_AUDADCLPWRUP_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDADCLPWRUP_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCLPWRUP_SHIFT 12 +#define MT6351_PMIC_RG_AUDADCLINPUTSEL_ADDR MT6351_AUDENC_ANA_CON0 +#define MT6351_PMIC_RG_AUDADCLINPUTSEL_MASK 0x3 +#define MT6351_PMIC_RG_AUDADCLINPUTSEL_SHIFT 13 +#define MT6351_PMIC_RG_AUDPREAMPRON_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDPREAMPRON_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPRON_SHIFT 0 +#define MT6351_PMIC_RG_AUDPREAMPRDCCEN_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDPREAMPRDCCEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPRDCCEN_SHIFT 1 +#define MT6351_PMIC_RG_AUDPREAMPRDCPRECHARGE_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDPREAMPRDCPRECHARGE_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPRDCPRECHARGE_SHIFT 2 +#define MT6351_PMIC_RG_AUDPREAMPRPGATEST_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDPREAMPRPGATEST_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPRPGATEST_SHIFT 3 +#define MT6351_PMIC_RG_AUDPREAMPRINPUTSEL_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDPREAMPRINPUTSEL_MASK 0x3 +#define MT6351_PMIC_RG_AUDPREAMPRINPUTSEL_SHIFT 4 +#define MT6351_PMIC_RG_AUDPREAMPRVSCALE_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDPREAMPRVSCALE_MASK 0x3 +#define MT6351_PMIC_RG_AUDPREAMPRVSCALE_SHIFT 6 +#define MT6351_PMIC_RG_AUDPREAMPRGAIN_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDPREAMPRGAIN_MASK 0x7 +#define MT6351_PMIC_RG_AUDPREAMPRGAIN_SHIFT 8 +#define MT6351_PMIC_RG_AUDADCRPWRUP_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDADCRPWRUP_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCRPWRUP_SHIFT 12 +#define MT6351_PMIC_RG_AUDADCRINPUTSEL_ADDR MT6351_AUDENC_ANA_CON1 +#define MT6351_PMIC_RG_AUDADCRINPUTSEL_MASK 0x3 +#define MT6351_PMIC_RG_AUDADCRINPUTSEL_SHIFT 13 +#define MT6351_PMIC_RG_AUDULHALFBIAS_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDULHALFBIAS_MASK 0x1 +#define MT6351_PMIC_RG_AUDULHALFBIAS_SHIFT 0 +#define MT6351_PMIC_RG_AUDGLBVOWLPWEN_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDGLBVOWLPWEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDGLBVOWLPWEN_SHIFT 1 +#define MT6351_PMIC_RG_AUDPREAMPLPEN_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDPREAMPLPEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPLPEN_SHIFT 2 +#define MT6351_PMIC_RG_AUDADC1STSTAGELPEN_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDADC1STSTAGELPEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDADC1STSTAGELPEN_SHIFT 3 +#define MT6351_PMIC_RG_AUDADC2NDSTAGELPEN_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDADC2NDSTAGELPEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDADC2NDSTAGELPEN_SHIFT 4 +#define MT6351_PMIC_RG_AUDADCFLASHLPEN_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDADCFLASHLPEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCFLASHLPEN_SHIFT 5 +#define MT6351_PMIC_RG_AUDPREAMPIDDTEST_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDPREAMPIDDTEST_MASK 0x3 +#define MT6351_PMIC_RG_AUDPREAMPIDDTEST_SHIFT 6 +#define MT6351_PMIC_RG_AUDADC1STSTAGEIDDTEST_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDADC1STSTAGEIDDTEST_MASK 0x3 +#define MT6351_PMIC_RG_AUDADC1STSTAGEIDDTEST_SHIFT 8 +#define MT6351_PMIC_RG_AUDADC2NDSTAGEIDDTEST_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDADC2NDSTAGEIDDTEST_MASK 0x3 +#define MT6351_PMIC_RG_AUDADC2NDSTAGEIDDTEST_SHIFT 10 +#define MT6351_PMIC_RG_AUDADCREFBUFIDDTEST_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDADCREFBUFIDDTEST_MASK 0x3 +#define MT6351_PMIC_RG_AUDADCREFBUFIDDTEST_SHIFT 12 +#define MT6351_PMIC_RG_AUDADCFLASHIDDTEST_ADDR MT6351_AUDENC_ANA_CON2 +#define MT6351_PMIC_RG_AUDADCFLASHIDDTEST_MASK 0x3 +#define MT6351_PMIC_RG_AUDADCFLASHIDDTEST_SHIFT 14 +#define MT6351_PMIC_RG_AUDADCDAC0P25FS_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_AUDADCDAC0P25FS_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCDAC0P25FS_SHIFT 0 +#define MT6351_PMIC_RG_AUDADCCLKSEL_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_AUDADCCLKSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCCLKSEL_SHIFT 1 +#define MT6351_PMIC_RG_AUDADCCLKSOURCE_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_AUDADCCLKSOURCE_MASK 0x3 +#define MT6351_PMIC_RG_AUDADCCLKSOURCE_SHIFT 2 +#define MT6351_PMIC_RG_AUDADCCLKGENMODE_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_AUDADCCLKGENMODE_MASK 0x3 +#define MT6351_PMIC_RG_AUDADCCLKGENMODE_SHIFT 4 +#define MT6351_PMIC_RG_AUDADCCLKRSTB_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_AUDADCCLKRSTB_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCCLKRSTB_SHIFT 6 +#define MT6351_PMIC_RG_AUDPREAMPAAFEN_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_AUDPREAMPAAFEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDPREAMPAAFEN_SHIFT 8 +#define MT6351_PMIC_RG_DCCVCMBUFLPMODSEL_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_DCCVCMBUFLPMODSEL_MASK 0x1 +#define MT6351_PMIC_RG_DCCVCMBUFLPMODSEL_SHIFT 9 +#define MT6351_PMIC_RG_DCCVCMBUFLPSWEN_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_DCCVCMBUFLPSWEN_MASK 0x1 +#define MT6351_PMIC_RG_DCCVCMBUFLPSWEN_SHIFT 10 +#define MT6351_PMIC_RG_AUDSPAREPGA_ADDR MT6351_AUDENC_ANA_CON3 +#define MT6351_PMIC_RG_AUDSPAREPGA_MASK 0x1F +#define MT6351_PMIC_RG_AUDSPAREPGA_SHIFT 11 +#define MT6351_PMIC_RG_AUDADC1STSTAGESDENB_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADC1STSTAGESDENB_MASK 0x1 +#define MT6351_PMIC_RG_AUDADC1STSTAGESDENB_SHIFT 0 +#define MT6351_PMIC_RG_AUDADC2NDSTAGERESET_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADC2NDSTAGERESET_MASK 0x1 +#define MT6351_PMIC_RG_AUDADC2NDSTAGERESET_SHIFT 1 +#define MT6351_PMIC_RG_AUDADC3RDSTAGERESET_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADC3RDSTAGERESET_MASK 0x1 +#define MT6351_PMIC_RG_AUDADC3RDSTAGERESET_SHIFT 2 +#define MT6351_PMIC_RG_AUDADCFSRESET_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCFSRESET_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCFSRESET_SHIFT 3 +#define MT6351_PMIC_RG_AUDADCWIDECM_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCWIDECM_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCWIDECM_SHIFT 4 +#define MT6351_PMIC_RG_AUDADCNOPATEST_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCNOPATEST_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCNOPATEST_SHIFT 5 +#define MT6351_PMIC_RG_AUDADCBYPASS_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCBYPASS_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCBYPASS_SHIFT 6 +#define MT6351_PMIC_RG_AUDADCFFBYPASS_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCFFBYPASS_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCFFBYPASS_SHIFT 7 +#define MT6351_PMIC_RG_AUDADCDACFBCURRENT_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCDACFBCURRENT_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCDACFBCURRENT_SHIFT 8 +#define MT6351_PMIC_RG_AUDADCDACIDDTEST_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCDACIDDTEST_MASK 0x3 +#define MT6351_PMIC_RG_AUDADCDACIDDTEST_SHIFT 9 +#define MT6351_PMIC_RG_AUDADCDACNRZ_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCDACNRZ_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCDACNRZ_SHIFT 11 +#define MT6351_PMIC_RG_AUDADCNODEM_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCNODEM_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCNODEM_SHIFT 12 +#define MT6351_PMIC_RG_AUDADCDACTEST_ADDR MT6351_AUDENC_ANA_CON4 +#define MT6351_PMIC_RG_AUDADCDACTEST_MASK 0x1 +#define MT6351_PMIC_RG_AUDADCDACTEST_SHIFT 13 +#define MT6351_PMIC_RG_AUDADCTESTDATA_ADDR MT6351_AUDENC_ANA_CON5 +#define MT6351_PMIC_RG_AUDADCTESTDATA_MASK 0xFFFF +#define MT6351_PMIC_RG_AUDADCTESTDATA_SHIFT 0 +#define MT6351_PMIC_RG_AUDRCTUNEL_ADDR MT6351_AUDENC_ANA_CON6 +#define MT6351_PMIC_RG_AUDRCTUNEL_MASK 0x1F +#define MT6351_PMIC_RG_AUDRCTUNEL_SHIFT 0 +#define MT6351_PMIC_RG_AUDRCTUNELSEL_ADDR MT6351_AUDENC_ANA_CON6 +#define MT6351_PMIC_RG_AUDRCTUNELSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUDRCTUNELSEL_SHIFT 5 +#define MT6351_PMIC_RG_AUDRCTUNER_ADDR MT6351_AUDENC_ANA_CON6 +#define MT6351_PMIC_RG_AUDRCTUNER_MASK 0x1F +#define MT6351_PMIC_RG_AUDRCTUNER_SHIFT 8 +#define MT6351_PMIC_RG_AUDRCTUNERSEL_ADDR MT6351_AUDENC_ANA_CON6 +#define MT6351_PMIC_RG_AUDRCTUNERSEL_MASK 0x1 +#define MT6351_PMIC_RG_AUDRCTUNERSEL_SHIFT 13 +#define MT6351_PMIC_RG_AUDSPAREVA30_ADDR MT6351_AUDENC_ANA_CON7 +#define MT6351_PMIC_RG_AUDSPAREVA30_MASK 0xFF +#define MT6351_PMIC_RG_AUDSPAREVA30_SHIFT 0 +#define MT6351_PMIC_RG_AUDSPAREVA18_ADDR MT6351_AUDENC_ANA_CON7 +#define MT6351_PMIC_RG_AUDSPAREVA18_MASK 0xFF +#define MT6351_PMIC_RG_AUDSPAREVA18_SHIFT 8 +#define MT6351_PMIC_RG_AUDDIGMICEN_ADDR MT6351_AUDENC_ANA_CON8 +#define MT6351_PMIC_RG_AUDDIGMICEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDDIGMICEN_SHIFT 0 +#define MT6351_PMIC_RG_AUDDIGMICBIAS_ADDR MT6351_AUDENC_ANA_CON8 +#define MT6351_PMIC_RG_AUDDIGMICBIAS_MASK 0x3 +#define MT6351_PMIC_RG_AUDDIGMICBIAS_SHIFT 1 +#define MT6351_PMIC_RG_DMICHPCLKEN_ADDR MT6351_AUDENC_ANA_CON8 +#define MT6351_PMIC_RG_DMICHPCLKEN_MASK 0x1 +#define MT6351_PMIC_RG_DMICHPCLKEN_SHIFT 3 +#define MT6351_PMIC_RG_AUDDIGMICPDUTY_ADDR MT6351_AUDENC_ANA_CON8 +#define MT6351_PMIC_RG_AUDDIGMICPDUTY_MASK 0x3 +#define MT6351_PMIC_RG_AUDDIGMICPDUTY_SHIFT 4 +#define MT6351_PMIC_RG_AUDDIGMICNDUTY_ADDR MT6351_AUDENC_ANA_CON8 +#define MT6351_PMIC_RG_AUDDIGMICNDUTY_MASK 0x3 +#define MT6351_PMIC_RG_AUDDIGMICNDUTY_SHIFT 6 +#define MT6351_PMIC_RG_DMICMONEN_ADDR MT6351_AUDENC_ANA_CON8 +#define MT6351_PMIC_RG_DMICMONEN_MASK 0x1 +#define MT6351_PMIC_RG_DMICMONEN_SHIFT 8 +#define MT6351_PMIC_RG_DMICMONSEL_ADDR MT6351_AUDENC_ANA_CON8 +#define MT6351_PMIC_RG_DMICMONSEL_MASK 0x7 +#define MT6351_PMIC_RG_DMICMONSEL_SHIFT 9 +#define MT6351_PMIC_RG_AUDSPAREVMIC_ADDR MT6351_AUDENC_ANA_CON8 +#define MT6351_PMIC_RG_AUDSPAREVMIC_MASK 0xF +#define MT6351_PMIC_RG_AUDSPAREVMIC_SHIFT 12 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS0_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS0_MASK 0x1 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS0_SHIFT 0 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0P1EN_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0P1EN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0P1EN_SHIFT 1 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0P2EN_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0P2EN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0P2EN_SHIFT 2 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0NEN_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0NEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS0DCSW0NEN_SHIFT 3 +#define MT6351_PMIC_RG_AUDMICBIAS0VREF_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS0VREF_MASK 0x7 +#define MT6351_PMIC_RG_AUDMICBIAS0VREF_SHIFT 4 +#define MT6351_PMIC_RG_AUDMICBIAS0LOWPEN_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS0LOWPEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS0LOWPEN_SHIFT 7 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS2_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS2_MASK 0x1 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS2_SHIFT 8 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2P1EN_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2P1EN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2P1EN_SHIFT 9 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2P2EN_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2P2EN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2P2EN_SHIFT 10 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2NEN_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2NEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW2NEN_SHIFT 11 +#define MT6351_PMIC_RG_AUDMICBIAS2VREF_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS2VREF_MASK 0x7 +#define MT6351_PMIC_RG_AUDMICBIAS2VREF_SHIFT 12 +#define MT6351_PMIC_RG_AUDMICBIAS2LOWPEN_ADDR MT6351_AUDENC_ANA_CON9 +#define MT6351_PMIC_RG_AUDMICBIAS2LOWPEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS2LOWPEN_SHIFT 15 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS1_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS1_MASK 0x1 +#define MT6351_PMIC_RG_AUDPWDBMICBIAS1_SHIFT 0 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW1PEN_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW1PEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW1PEN_SHIFT 1 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW1NEN_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW1NEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW1NEN_SHIFT 2 +#define MT6351_PMIC_RG_AUDMICBIAS1VREF_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDMICBIAS1VREF_MASK 0x7 +#define MT6351_PMIC_RG_AUDMICBIAS1VREF_SHIFT 4 +#define MT6351_PMIC_RG_AUDMICBIAS1LOWPEN_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDMICBIAS1LOWPEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS1LOWPEN_SHIFT 7 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW3PEN_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW3PEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW3PEN_SHIFT 8 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW3NEN_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW3NEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS1DCSW3NEN_SHIFT 9 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW3PEN_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW3PEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW3PEN_SHIFT 10 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW3NEN_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW3NEN_MASK 0x1 +#define MT6351_PMIC_RG_AUDMICBIAS2DCSW3NEN_SHIFT 11 +#define MT6351_PMIC_RG_BANDGAPGEN_ADDR MT6351_AUDENC_ANA_CON10 +#define MT6351_PMIC_RG_BANDGAPGEN_MASK 0x1 +#define MT6351_PMIC_RG_BANDGAPGEN_SHIFT 12 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS0PULLLOW_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS0PULLLOW_MASK 0x1 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS0PULLLOW_SHIFT 0 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS1PULLLOW_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS1PULLLOW_MASK 0x1 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS1PULLLOW_SHIFT 1 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS2PULLLOW_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS2PULLLOW_MASK 0x1 +#define MT6351_PMIC_RG_AUDACCDETMICBIAS2PULLLOW_SHIFT 2 +#define MT6351_PMIC_RG_AUDACCDETVIN1PULLLOW_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_AUDACCDETVIN1PULLLOW_MASK 0x1 +#define MT6351_PMIC_RG_AUDACCDETVIN1PULLLOW_SHIFT 3 +#define MT6351_PMIC_RG_AUDACCDETVTHACAL_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_AUDACCDETVTHACAL_MASK 0x1 +#define MT6351_PMIC_RG_AUDACCDETVTHACAL_SHIFT 4 +#define MT6351_PMIC_RG_AUDACCDETVTHBCAL_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_AUDACCDETVTHBCAL_MASK 0x1 +#define MT6351_PMIC_RG_AUDACCDETVTHBCAL_SHIFT 5 +#define MT6351_PMIC_RG_ACCDET1SEL_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_ACCDET1SEL_MASK 0x1 +#define MT6351_PMIC_RG_ACCDET1SEL_SHIFT 6 +#define MT6351_PMIC_RG_ACCDET2SEL_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_ACCDET2SEL_MASK 0x1 +#define MT6351_PMIC_RG_ACCDET2SEL_SHIFT 7 +#define MT6351_PMIC_RG_SWBUFMODSEL_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_SWBUFMODSEL_MASK 0x1 +#define MT6351_PMIC_RG_SWBUFMODSEL_SHIFT 8 +#define MT6351_PMIC_RG_SWBUFSWEN_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_SWBUFSWEN_MASK 0x1 +#define MT6351_PMIC_RG_SWBUFSWEN_SHIFT 9 +#define MT6351_PMIC_RG_EINTCOMPVTH_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_EINTCOMPVTH_MASK 0x1 +#define MT6351_PMIC_RG_EINTCOMPVTH_SHIFT 10 +#define MT6351_PMIC_RG_EINTCONFIGACCDET_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_EINTCONFIGACCDET_MASK 0x1 +#define MT6351_PMIC_RG_EINTCONFIGACCDET_SHIFT 11 +#define MT6351_PMIC_RG_NVDETCMPEN_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_NVDETCMPEN_MASK 0x1 +#define MT6351_PMIC_RG_NVDETCMPEN_SHIFT 12 +#define MT6351_PMIC_RG_NVDETVTH_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_NVDETVTH_MASK 0x1 +#define MT6351_PMIC_RG_NVDETVTH_SHIFT 13 +#define MT6351_PMIC_RG_NVMODSEL_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_NVMODSEL_MASK 0x1 +#define MT6351_PMIC_RG_NVMODSEL_SHIFT 14 +#define MT6351_PMIC_RG_NVCMPSWEN_ADDR MT6351_AUDENC_ANA_CON11 +#define MT6351_PMIC_RG_NVCMPSWEN_MASK 0x1 +#define MT6351_PMIC_RG_NVCMPSWEN_SHIFT 15 +#define MT6351_PMIC_RG_AUDENCSPAREVA30_ADDR MT6351_AUDENC_ANA_CON12 +#define MT6351_PMIC_RG_AUDENCSPAREVA30_MASK 0xFF +#define MT6351_PMIC_RG_AUDENCSPAREVA30_SHIFT 0 +#define MT6351_PMIC_RG_AUDENCSPAREVA18_ADDR MT6351_AUDENC_ANA_CON12 +#define MT6351_PMIC_RG_AUDENCSPAREVA18_MASK 0xFF +#define MT6351_PMIC_RG_AUDENCSPAREVA18_SHIFT 8 +#define MT6351_PMIC_RG_PLL_EN_ADDR MT6351_AUDENC_ANA_CON13 +#define MT6351_PMIC_RG_PLL_EN_MASK 0x1 +#define MT6351_PMIC_RG_PLL_EN_SHIFT 0 +#define MT6351_PMIC_RG_PLLBS_RST_ADDR MT6351_AUDENC_ANA_CON13 +#define MT6351_PMIC_RG_PLLBS_RST_MASK 0x1 +#define MT6351_PMIC_RG_PLLBS_RST_SHIFT 1 +#define MT6351_PMIC_RG_PLL_DCKO_SEL_ADDR MT6351_AUDENC_ANA_CON13 +#define MT6351_PMIC_RG_PLL_DCKO_SEL_MASK 0x3 +#define MT6351_PMIC_RG_PLL_DCKO_SEL_SHIFT 2 +#define MT6351_PMIC_RG_PLL_DIV1_ADDR MT6351_AUDENC_ANA_CON13 +#define MT6351_PMIC_RG_PLL_DIV1_MASK 0x3F +#define MT6351_PMIC_RG_PLL_DIV1_SHIFT 4 +#define MT6351_PMIC_RG_PLL_RLATCH_EN_ADDR MT6351_AUDENC_ANA_CON13 +#define MT6351_PMIC_RG_PLL_RLATCH_EN_MASK 0x1 +#define MT6351_PMIC_RG_PLL_RLATCH_EN_SHIFT 10 +#define MT6351_PMIC_RG_PLL_PDIV1_EN_ADDR MT6351_AUDENC_ANA_CON13 +#define MT6351_PMIC_RG_PLL_PDIV1_EN_MASK 0x1 +#define MT6351_PMIC_RG_PLL_PDIV1_EN_SHIFT 11 +#define MT6351_PMIC_RG_PLL_PDIV1_ADDR MT6351_AUDENC_ANA_CON13 +#define MT6351_PMIC_RG_PLL_PDIV1_MASK 0xF +#define MT6351_PMIC_RG_PLL_PDIV1_SHIFT 12 +#define MT6351_PMIC_RG_PLL_BC_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_BC_MASK 0x3 +#define MT6351_PMIC_RG_PLL_BC_SHIFT 0 +#define MT6351_PMIC_RG_PLL_BP_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_BP_MASK 0x3 +#define MT6351_PMIC_RG_PLL_BP_SHIFT 2 +#define MT6351_PMIC_RG_PLL_BR_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_BR_MASK 0x3 +#define MT6351_PMIC_RG_PLL_BR_SHIFT 4 +#define MT6351_PMIC_RG_CKO_SEL_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_CKO_SEL_MASK 0x3 +#define MT6351_PMIC_RG_CKO_SEL_SHIFT 6 +#define MT6351_PMIC_RG_PLL_IBSEL_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_IBSEL_MASK 0x3 +#define MT6351_PMIC_RG_PLL_IBSEL_SHIFT 8 +#define MT6351_PMIC_RG_PLL_CKT_SEL_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_CKT_SEL_MASK 0x3 +#define MT6351_PMIC_RG_PLL_CKT_SEL_SHIFT 10 +#define MT6351_PMIC_RG_PLL_VCT_EN_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_VCT_EN_MASK 0x1 +#define MT6351_PMIC_RG_PLL_VCT_EN_SHIFT 12 +#define MT6351_PMIC_RG_PLL_CKT_EN_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_CKT_EN_MASK 0x1 +#define MT6351_PMIC_RG_PLL_CKT_EN_SHIFT 13 +#define MT6351_PMIC_RG_PLL_HPM_EN_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_HPM_EN_MASK 0x1 +#define MT6351_PMIC_RG_PLL_HPM_EN_SHIFT 14 +#define MT6351_PMIC_RG_PLL_DCHP_EN_ADDR MT6351_AUDENC_ANA_CON14 +#define MT6351_PMIC_RG_PLL_DCHP_EN_MASK 0x1 +#define MT6351_PMIC_RG_PLL_DCHP_EN_SHIFT 15 +#define MT6351_PMIC_RG_PLL_CDIV_ADDR MT6351_AUDENC_ANA_CON15 +#define MT6351_PMIC_RG_PLL_CDIV_MASK 0x7 +#define MT6351_PMIC_RG_PLL_CDIV_SHIFT 0 +#define MT6351_PMIC_RG_VCOBAND_ADDR MT6351_AUDENC_ANA_CON15 +#define MT6351_PMIC_RG_VCOBAND_MASK 0x7 +#define MT6351_PMIC_RG_VCOBAND_SHIFT 3 +#define MT6351_PMIC_RG_CKDRV_EN_ADDR MT6351_AUDENC_ANA_CON15 +#define MT6351_PMIC_RG_CKDRV_EN_MASK 0x1 +#define MT6351_PMIC_RG_CKDRV_EN_SHIFT 6 +#define MT6351_PMIC_RG_PLL_DCHP_AEN_ADDR MT6351_AUDENC_ANA_CON15 +#define MT6351_PMIC_RG_PLL_DCHP_AEN_MASK 0x1 +#define MT6351_PMIC_RG_PLL_DCHP_AEN_SHIFT 7 +#define MT6351_PMIC_RG_PLL_RSVA_ADDR MT6351_AUDENC_ANA_CON15 +#define MT6351_PMIC_RG_PLL_RSVA_MASK 0xFF +#define MT6351_PMIC_RG_PLL_RSVA_SHIFT 8 +#define MT6351_PMIC_RGS_AUDRCTUNELREAD_ADDR MT6351_AUDENC_ANA_CON16 +#define MT6351_PMIC_RGS_AUDRCTUNELREAD_MASK 0x1F +#define MT6351_PMIC_RGS_AUDRCTUNELREAD_SHIFT 0 +#define MT6351_PMIC_RGS_AUDRCTUNERREAD_ADDR MT6351_AUDENC_ANA_CON16 +#define MT6351_PMIC_RGS_AUDRCTUNERREAD_MASK 0x1F +#define MT6351_PMIC_RGS_AUDRCTUNERREAD_SHIFT 8 +#define MT6351_PMIC_RG_DIVCKS_CHG_ADDR MT6351_AUDNCP_CLKDIV_CON0 +#define MT6351_PMIC_RG_DIVCKS_CHG_MASK 0x1 +#define MT6351_PMIC_RG_DIVCKS_CHG_SHIFT 0 +#define MT6351_PMIC_RG_DIVCKS_ON_ADDR MT6351_AUDNCP_CLKDIV_CON1 +#define MT6351_PMIC_RG_DIVCKS_ON_MASK 0x1 +#define MT6351_PMIC_RG_DIVCKS_ON_SHIFT 0 +#define MT6351_PMIC_RG_DIVCKS_PRG_ADDR MT6351_AUDNCP_CLKDIV_CON2 +#define MT6351_PMIC_RG_DIVCKS_PRG_MASK 0x1FF +#define MT6351_PMIC_RG_DIVCKS_PRG_SHIFT 0 +#define MT6351_PMIC_RG_DIVCKS_PWD_NCP_ADDR MT6351_AUDNCP_CLKDIV_CON3 +#define MT6351_PMIC_RG_DIVCKS_PWD_NCP_MASK 0x1 +#define MT6351_PMIC_RG_DIVCKS_PWD_NCP_SHIFT 0 +#define MT6351_PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_ADDR MT6351_AUDNCP_CLKDIV_CON4 +#define MT6351_PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_MASK 0x3 +#define MT6351_PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_ADDR MT6351_AUXADC_ADC0 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_ADDR MT6351_AUXADC_ADC0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_ADDR MT6351_AUXADC_ADC1 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_ADDR MT6351_AUXADC_ADC1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH2_ADDR MT6351_AUXADC_ADC2 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH2_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH2_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH2_ADDR MT6351_AUXADC_ADC2 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH2_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH2_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH3_ADDR MT6351_AUXADC_ADC3 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH3_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH3_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH3_ADDR MT6351_AUXADC_ADC3 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH3_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH3_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH4_ADDR MT6351_AUXADC_ADC4 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH4_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH4_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH4_ADDR MT6351_AUXADC_ADC4 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH4_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH4_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH5_ADDR MT6351_AUXADC_ADC5 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH5_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH5_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH5_ADDR MT6351_AUXADC_ADC5 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH5_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH5_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH6_ADDR MT6351_AUXADC_ADC6 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH6_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH6_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH6_ADDR MT6351_AUXADC_ADC6 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH6_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH6_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_ADDR MT6351_AUXADC_ADC7 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_ADDR MT6351_AUXADC_ADC7 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH8_ADDR MT6351_AUXADC_ADC8 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH8_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH8_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH8_ADDR MT6351_AUXADC_ADC8 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH8_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH8_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH9_ADDR MT6351_AUXADC_ADC9 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH9_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH9_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH9_ADDR MT6351_AUXADC_ADC9 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH9_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH9_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH10_ADDR MT6351_AUXADC_ADC10 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH10_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH10_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH10_ADDR MT6351_AUXADC_ADC10 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH10_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH10_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH11_ADDR MT6351_AUXADC_ADC11 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH11_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH11_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH11_ADDR MT6351_AUXADC_ADC11 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH11_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH11_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH12_15_ADDR MT6351_AUXADC_ADC12 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH12_15_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH12_15_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH12_15_ADDR MT6351_AUXADC_ADC12 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH12_15_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH12_15_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_THR_HW_ADDR MT6351_AUXADC_ADC13 +#define MT6351_PMIC_AUXADC_ADC_OUT_THR_HW_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_THR_HW_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_THR_HW_ADDR MT6351_AUXADC_ADC13 +#define MT6351_PMIC_AUXADC_ADC_RDY_THR_HW_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_THR_HW_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_LBAT_ADDR MT6351_AUXADC_ADC14 +#define MT6351_PMIC_AUXADC_ADC_OUT_LBAT_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_LBAT_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_LBAT_ADDR MT6351_AUXADC_ADC14 +#define MT6351_PMIC_AUXADC_ADC_RDY_LBAT_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_LBAT_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_LBAT2_ADDR MT6351_AUXADC_ADC15 +#define MT6351_PMIC_AUXADC_ADC_OUT_LBAT2_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_LBAT2_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_LBAT2_ADDR MT6351_AUXADC_ADC15 +#define MT6351_PMIC_AUXADC_ADC_RDY_LBAT2_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_LBAT2_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_ADDR MT6351_AUXADC_ADC16 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_ADDR MT6351_AUXADC_ADC16 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_MD_ADDR MT6351_AUXADC_ADC17 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_MD_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_MD_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_MD_ADDR MT6351_AUXADC_ADC17 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_MD_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_AP_ADDR MT6351_AUXADC_ADC18 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_AP_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_AP_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_AP_ADDR MT6351_AUXADC_ADC18 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_AP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_AP_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH4_BY_MD_ADDR MT6351_AUXADC_ADC19 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH4_BY_MD_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH4_BY_MD_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH4_BY_MD_ADDR MT6351_AUXADC_ADC19 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH4_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH4_BY_MD_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_ADDR MT6351_AUXADC_ADC20 +#define MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_ADDR MT6351_AUXADC_ADC20 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_ADDR MT6351_AUXADC_ADC21 +#define MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_ADDR MT6351_AUXADC_ADC21 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_MD_ADDR MT6351_AUXADC_ADC22 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_MD_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_MD_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_MD_ADDR MT6351_AUXADC_ADC22 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_MD_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_AP_ADDR MT6351_AUXADC_ADC23 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_AP_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_AP_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_AP_ADDR MT6351_AUXADC_ADC23 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_AP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_AP_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_MD_ADDR MT6351_AUXADC_ADC24 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_MD_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_MD_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_MD_ADDR MT6351_AUXADC_ADC24 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_MD_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_AP_ADDR MT6351_AUXADC_ADC25 +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_AP_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_AP_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_AP_ADDR MT6351_AUXADC_ADC25 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_AP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_AP_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_VISMPS0_ADDR MT6351_AUXADC_ADC26 +#define MT6351_PMIC_AUXADC_ADC_OUT_VISMPS0_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_VISMPS0_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_VISMPS0_ADDR MT6351_AUXADC_ADC26 +#define MT6351_PMIC_AUXADC_ADC_RDY_VISMPS0_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_VISMPS0_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_FGADC1_ADDR MT6351_AUXADC_ADC27 +#define MT6351_PMIC_AUXADC_ADC_OUT_FGADC1_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_FGADC1_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_FGADC1_ADDR MT6351_AUXADC_ADC27 +#define MT6351_PMIC_AUXADC_ADC_RDY_FGADC1_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_FGADC1_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_FGADC2_ADDR MT6351_AUXADC_ADC28 +#define MT6351_PMIC_AUXADC_ADC_OUT_FGADC2_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_FGADC2_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_FGADC2_ADDR MT6351_AUXADC_ADC28 +#define MT6351_PMIC_AUXADC_ADC_RDY_FGADC2_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_FGADC2_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_IMP_ADDR MT6351_AUXADC_ADC29 +#define MT6351_PMIC_AUXADC_ADC_OUT_IMP_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_IMP_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_IMP_ADDR MT6351_AUXADC_ADC29 +#define MT6351_PMIC_AUXADC_ADC_RDY_IMP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_IMP_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_IMP_AVG_ADDR MT6351_AUXADC_ADC30 +#define MT6351_PMIC_AUXADC_ADC_OUT_IMP_AVG_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_IMP_AVG_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_IMP_AVG_ADDR MT6351_AUXADC_ADC30 +#define MT6351_PMIC_AUXADC_ADC_RDY_IMP_AVG_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_IMP_AVG_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_RAW_ADDR MT6351_AUXADC_ADC31 +#define MT6351_PMIC_AUXADC_ADC_OUT_RAW_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_RAW_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_OUT_MDRT_ADDR MT6351_AUXADC_ADC32 +#define MT6351_PMIC_AUXADC_ADC_OUT_MDRT_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_MDRT_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_MDRT_ADDR MT6351_AUXADC_ADC32 +#define MT6351_PMIC_AUXADC_ADC_RDY_MDRT_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_MDRT_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_MDBG_ADDR MT6351_AUXADC_ADC33 +#define MT6351_PMIC_AUXADC_ADC_OUT_MDBG_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_MDBG_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_MDBG_ADDR MT6351_AUXADC_ADC33 +#define MT6351_PMIC_AUXADC_ADC_RDY_MDBG_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_MDBG_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_JEITA_ADDR MT6351_AUXADC_ADC34 +#define MT6351_PMIC_AUXADC_ADC_OUT_JEITA_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_JEITA_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_JEITA_ADDR MT6351_AUXADC_ADC34 +#define MT6351_PMIC_AUXADC_ADC_RDY_JEITA_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_JEITA_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_ADDR MT6351_AUXADC_ADC35 +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_ADDR MT6351_AUXADC_ADC35 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_ADDR MT6351_AUXADC_ADC36 +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_ADDR MT6351_AUXADC_ADC36 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_ADDR MT6351_AUXADC_ADC37 +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_ADDR MT6351_AUXADC_ADC37 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_MDRT_ADDR MT6351_AUXADC_ADC38 +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_MDRT_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_OUT_DCXO_MDRT_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_MDRT_ADDR MT6351_AUXADC_ADC38 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_MDRT_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_DCXO_MDRT_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_OUT_NAG_ADDR MT6351_AUXADC_ADC39 +#define MT6351_PMIC_AUXADC_ADC_OUT_NAG_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_ADC_OUT_NAG_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_RDY_NAG_ADDR MT6351_AUXADC_ADC39 +#define MT6351_PMIC_AUXADC_ADC_RDY_NAG_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_NAG_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_00_ADDR MT6351_AUXADC_BUF0 +#define MT6351_PMIC_AUXADC_BUF_OUT_00_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_00_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_00_ADDR MT6351_AUXADC_BUF0 +#define MT6351_PMIC_AUXADC_BUF_RDY_00_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_00_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_01_ADDR MT6351_AUXADC_BUF1 +#define MT6351_PMIC_AUXADC_BUF_OUT_01_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_01_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_01_ADDR MT6351_AUXADC_BUF1 +#define MT6351_PMIC_AUXADC_BUF_RDY_01_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_01_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_02_ADDR MT6351_AUXADC_BUF2 +#define MT6351_PMIC_AUXADC_BUF_OUT_02_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_02_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_02_ADDR MT6351_AUXADC_BUF2 +#define MT6351_PMIC_AUXADC_BUF_RDY_02_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_02_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_03_ADDR MT6351_AUXADC_BUF3 +#define MT6351_PMIC_AUXADC_BUF_OUT_03_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_03_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_03_ADDR MT6351_AUXADC_BUF3 +#define MT6351_PMIC_AUXADC_BUF_RDY_03_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_03_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_04_ADDR MT6351_AUXADC_BUF4 +#define MT6351_PMIC_AUXADC_BUF_OUT_04_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_04_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_04_ADDR MT6351_AUXADC_BUF4 +#define MT6351_PMIC_AUXADC_BUF_RDY_04_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_04_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_05_ADDR MT6351_AUXADC_BUF5 +#define MT6351_PMIC_AUXADC_BUF_OUT_05_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_05_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_05_ADDR MT6351_AUXADC_BUF5 +#define MT6351_PMIC_AUXADC_BUF_RDY_05_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_05_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_06_ADDR MT6351_AUXADC_BUF6 +#define MT6351_PMIC_AUXADC_BUF_OUT_06_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_06_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_06_ADDR MT6351_AUXADC_BUF6 +#define MT6351_PMIC_AUXADC_BUF_RDY_06_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_06_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_07_ADDR MT6351_AUXADC_BUF7 +#define MT6351_PMIC_AUXADC_BUF_OUT_07_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_07_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_07_ADDR MT6351_AUXADC_BUF7 +#define MT6351_PMIC_AUXADC_BUF_RDY_07_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_07_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_08_ADDR MT6351_AUXADC_BUF8 +#define MT6351_PMIC_AUXADC_BUF_OUT_08_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_08_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_08_ADDR MT6351_AUXADC_BUF8 +#define MT6351_PMIC_AUXADC_BUF_RDY_08_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_08_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_09_ADDR MT6351_AUXADC_BUF9 +#define MT6351_PMIC_AUXADC_BUF_OUT_09_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_09_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_09_ADDR MT6351_AUXADC_BUF9 +#define MT6351_PMIC_AUXADC_BUF_RDY_09_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_09_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_10_ADDR MT6351_AUXADC_BUF10 +#define MT6351_PMIC_AUXADC_BUF_OUT_10_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_10_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_10_ADDR MT6351_AUXADC_BUF10 +#define MT6351_PMIC_AUXADC_BUF_RDY_10_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_10_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_11_ADDR MT6351_AUXADC_BUF11 +#define MT6351_PMIC_AUXADC_BUF_OUT_11_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_11_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_11_ADDR MT6351_AUXADC_BUF11 +#define MT6351_PMIC_AUXADC_BUF_RDY_11_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_11_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_12_ADDR MT6351_AUXADC_BUF12 +#define MT6351_PMIC_AUXADC_BUF_OUT_12_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_12_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_12_ADDR MT6351_AUXADC_BUF12 +#define MT6351_PMIC_AUXADC_BUF_RDY_12_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_12_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_13_ADDR MT6351_AUXADC_BUF13 +#define MT6351_PMIC_AUXADC_BUF_OUT_13_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_13_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_13_ADDR MT6351_AUXADC_BUF13 +#define MT6351_PMIC_AUXADC_BUF_RDY_13_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_13_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_14_ADDR MT6351_AUXADC_BUF14 +#define MT6351_PMIC_AUXADC_BUF_OUT_14_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_14_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_14_ADDR MT6351_AUXADC_BUF14 +#define MT6351_PMIC_AUXADC_BUF_RDY_14_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_14_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_15_ADDR MT6351_AUXADC_BUF15 +#define MT6351_PMIC_AUXADC_BUF_OUT_15_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_15_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_15_ADDR MT6351_AUXADC_BUF15 +#define MT6351_PMIC_AUXADC_BUF_RDY_15_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_15_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_16_ADDR MT6351_AUXADC_BUF16 +#define MT6351_PMIC_AUXADC_BUF_OUT_16_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_16_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_16_ADDR MT6351_AUXADC_BUF16 +#define MT6351_PMIC_AUXADC_BUF_RDY_16_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_16_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_17_ADDR MT6351_AUXADC_BUF17 +#define MT6351_PMIC_AUXADC_BUF_OUT_17_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_17_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_17_ADDR MT6351_AUXADC_BUF17 +#define MT6351_PMIC_AUXADC_BUF_RDY_17_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_17_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_18_ADDR MT6351_AUXADC_BUF18 +#define MT6351_PMIC_AUXADC_BUF_OUT_18_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_18_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_18_ADDR MT6351_AUXADC_BUF18 +#define MT6351_PMIC_AUXADC_BUF_RDY_18_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_18_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_19_ADDR MT6351_AUXADC_BUF19 +#define MT6351_PMIC_AUXADC_BUF_OUT_19_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_19_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_19_ADDR MT6351_AUXADC_BUF19 +#define MT6351_PMIC_AUXADC_BUF_RDY_19_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_19_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_20_ADDR MT6351_AUXADC_BUF20 +#define MT6351_PMIC_AUXADC_BUF_OUT_20_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_20_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_20_ADDR MT6351_AUXADC_BUF20 +#define MT6351_PMIC_AUXADC_BUF_RDY_20_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_20_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_21_ADDR MT6351_AUXADC_BUF21 +#define MT6351_PMIC_AUXADC_BUF_OUT_21_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_21_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_21_ADDR MT6351_AUXADC_BUF21 +#define MT6351_PMIC_AUXADC_BUF_RDY_21_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_21_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_22_ADDR MT6351_AUXADC_BUF22 +#define MT6351_PMIC_AUXADC_BUF_OUT_22_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_22_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_22_ADDR MT6351_AUXADC_BUF22 +#define MT6351_PMIC_AUXADC_BUF_RDY_22_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_22_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_23_ADDR MT6351_AUXADC_BUF23 +#define MT6351_PMIC_AUXADC_BUF_OUT_23_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_23_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_23_ADDR MT6351_AUXADC_BUF23 +#define MT6351_PMIC_AUXADC_BUF_RDY_23_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_23_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_24_ADDR MT6351_AUXADC_BUF24 +#define MT6351_PMIC_AUXADC_BUF_OUT_24_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_24_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_24_ADDR MT6351_AUXADC_BUF24 +#define MT6351_PMIC_AUXADC_BUF_RDY_24_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_24_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_25_ADDR MT6351_AUXADC_BUF25 +#define MT6351_PMIC_AUXADC_BUF_OUT_25_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_25_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_25_ADDR MT6351_AUXADC_BUF25 +#define MT6351_PMIC_AUXADC_BUF_RDY_25_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_25_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_26_ADDR MT6351_AUXADC_BUF26 +#define MT6351_PMIC_AUXADC_BUF_OUT_26_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_26_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_26_ADDR MT6351_AUXADC_BUF26 +#define MT6351_PMIC_AUXADC_BUF_RDY_26_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_26_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_27_ADDR MT6351_AUXADC_BUF27 +#define MT6351_PMIC_AUXADC_BUF_OUT_27_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_27_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_27_ADDR MT6351_AUXADC_BUF27 +#define MT6351_PMIC_AUXADC_BUF_RDY_27_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_27_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_28_ADDR MT6351_AUXADC_BUF28 +#define MT6351_PMIC_AUXADC_BUF_OUT_28_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_28_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_28_ADDR MT6351_AUXADC_BUF28 +#define MT6351_PMIC_AUXADC_BUF_RDY_28_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_28_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_29_ADDR MT6351_AUXADC_BUF29 +#define MT6351_PMIC_AUXADC_BUF_OUT_29_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_29_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_29_ADDR MT6351_AUXADC_BUF29 +#define MT6351_PMIC_AUXADC_BUF_RDY_29_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_29_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_30_ADDR MT6351_AUXADC_BUF30 +#define MT6351_PMIC_AUXADC_BUF_OUT_30_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_30_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_30_ADDR MT6351_AUXADC_BUF30 +#define MT6351_PMIC_AUXADC_BUF_RDY_30_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_30_SHIFT 15 +#define MT6351_PMIC_AUXADC_BUF_OUT_31_ADDR MT6351_AUXADC_BUF31 +#define MT6351_PMIC_AUXADC_BUF_OUT_31_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_BUF_OUT_31_SHIFT 0 +#define MT6351_PMIC_AUXADC_BUF_RDY_31_ADDR MT6351_AUXADC_BUF31 +#define MT6351_PMIC_AUXADC_BUF_RDY_31_MASK 0x1 +#define MT6351_PMIC_AUXADC_BUF_RDY_31_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_ADDR MT6351_AUXADC_STA0 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_MASK 0xFFF +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT_ADDR MT6351_AUXADC_STA0 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT_SHIFT 12 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT2_ADDR MT6351_AUXADC_STA0 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT2_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT2_SHIFT 13 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_ADDR MT6351_AUXADC_STA0 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_SHIFT 14 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_ADDR MT6351_AUXADC_STA0 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_SHIFT 1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_SHIFT 2 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_SHIFT 3 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_JEITA_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_JEITA_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_JEITA_SHIFT 4 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDRT_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDRT_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDRT_SHIFT 5 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDBG_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDBG_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDBG_SHIFT 6 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHARE_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHARE_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHARE_SHIFT 7 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_IMP_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_IMP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_IMP_SHIFT 8 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC1_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC1_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC1_SHIFT 9 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC2_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC2_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC2_SHIFT 10 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_SHIFT 11 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_SHIFT 12 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_SHIFT 13 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_HW_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_HW_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_HW_SHIFT 14 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_MD_ADDR MT6351_AUXADC_STA1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_MD_SHIFT 15 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_NAG_ADDR MT6351_AUXADC_STA2 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_NAG_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_BUSY_IN_NAG_SHIFT 15 +#define MT6351_PMIC_AUXADC_RQST_CH0_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH0_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH0_SHIFT 0 +#define MT6351_PMIC_AUXADC_RQST_CH1_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH1_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH1_SHIFT 1 +#define MT6351_PMIC_AUXADC_RQST_CH2_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH2_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH2_SHIFT 2 +#define MT6351_PMIC_AUXADC_RQST_CH3_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH3_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH3_SHIFT 3 +#define MT6351_PMIC_AUXADC_RQST_CH4_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH4_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH4_SHIFT 4 +#define MT6351_PMIC_AUXADC_RQST_CH5_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH5_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH5_SHIFT 5 +#define MT6351_PMIC_AUXADC_RQST_CH6_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH6_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH6_SHIFT 6 +#define MT6351_PMIC_AUXADC_RQST_CH7_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH7_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH7_SHIFT 7 +#define MT6351_PMIC_AUXADC_RQST_CH8_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH8_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH8_SHIFT 8 +#define MT6351_PMIC_AUXADC_RQST_CH9_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH9_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH9_SHIFT 9 +#define MT6351_PMIC_AUXADC_RQST_CH10_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH10_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH10_SHIFT 10 +#define MT6351_PMIC_AUXADC_RQST_CH11_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH11_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH11_SHIFT 11 +#define MT6351_PMIC_AUXADC_RQST_CH12_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH12_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH12_SHIFT 12 +#define MT6351_PMIC_AUXADC_RQST_CH13_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH13_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH13_SHIFT 13 +#define MT6351_PMIC_AUXADC_RQST_CH14_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH14_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH14_SHIFT 14 +#define MT6351_PMIC_AUXADC_RQST_CH15_ADDR MT6351_AUXADC_RQST0 +#define MT6351_PMIC_AUXADC_RQST_CH15_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH15_SHIFT 15 +#define MT6351_PMIC_AUXADC_RQST0_SET_ADDR MT6351_AUXADC_RQST0_SET +#define MT6351_PMIC_AUXADC_RQST0_SET_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_RQST0_SET_SHIFT 0 +#define MT6351_PMIC_AUXADC_RQST0_CLR_ADDR MT6351_AUXADC_RQST0_CLR +#define MT6351_PMIC_AUXADC_RQST0_CLR_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_RQST0_CLR_SHIFT 0 +#define MT6351_PMIC_AUXADC_RQST_CH0_BY_MD_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_CH0_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH0_BY_MD_SHIFT 0 +#define MT6351_PMIC_AUXADC_RQST_CH1_BY_MD_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_CH1_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH1_BY_MD_SHIFT 1 +#define MT6351_PMIC_AUXADC_RQST_RSV0_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_RSV0_MASK 0x3 +#define MT6351_PMIC_AUXADC_RQST_RSV0_SHIFT 2 +#define MT6351_PMIC_AUXADC_RQST_CH4_BY_MD_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_CH4_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH4_BY_MD_SHIFT 4 +#define MT6351_PMIC_AUXADC_RQST_CH7_BY_MD_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_CH7_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH7_BY_MD_SHIFT 7 +#define MT6351_PMIC_AUXADC_RQST_CH7_BY_GPS_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_CH7_BY_GPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_CH7_BY_GPS_SHIFT 8 +#define MT6351_PMIC_AUXADC_RQST_DCXO_BY_MD_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_DCXO_BY_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_DCXO_BY_MD_SHIFT 9 +#define MT6351_PMIC_AUXADC_RQST_DCXO_BY_GPS_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_DCXO_BY_GPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_RQST_DCXO_BY_GPS_SHIFT 10 +#define MT6351_PMIC_AUXADC_RQST_RSV1_ADDR MT6351_AUXADC_RQST1 +#define MT6351_PMIC_AUXADC_RQST_RSV1_MASK 0x1F +#define MT6351_PMIC_AUXADC_RQST_RSV1_SHIFT 11 +#define MT6351_PMIC_AUXADC_RQST1_SET_ADDR MT6351_AUXADC_RQST1_SET +#define MT6351_PMIC_AUXADC_RQST1_SET_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_RQST1_SET_SHIFT 0 +#define MT6351_PMIC_AUXADC_RQST1_CLR_ADDR MT6351_AUXADC_RQST1_CLR +#define MT6351_PMIC_AUXADC_RQST1_CLR_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_RQST1_CLR_SHIFT 0 +#define MT6351_PMIC_AUXADC_CK_ON_EXTD_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_CK_ON_EXTD_MASK 0x3F +#define MT6351_PMIC_AUXADC_CK_ON_EXTD_SHIFT 0 +#define MT6351_PMIC_AUXADC_SRCLKEN_SRC_SEL_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_SRCLKEN_SRC_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_SRCLKEN_SRC_SEL_SHIFT 6 +#define MT6351_PMIC_AUXADC_ADC_PWDB_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_ADC_PWDB_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_PWDB_SHIFT 8 +#define MT6351_PMIC_AUXADC_ADC_PWDB_SWCTRL_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_ADC_PWDB_SWCTRL_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_PWDB_SWCTRL_SHIFT 9 +#define MT6351_PMIC_AUXADC_STRUP_CK_ON_ENB_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_STRUP_CK_ON_ENB_MASK 0x1 +#define MT6351_PMIC_AUXADC_STRUP_CK_ON_ENB_SHIFT 10 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_SHIFT 11 +#define MT6351_PMIC_AUXADC_SRCLKEN_CK_EN_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_SRCLKEN_CK_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_SRCLKEN_CK_EN_SHIFT 12 +#define MT6351_PMIC_AUXADC_CK_AON_GPS_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_CK_AON_GPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_CK_AON_GPS_SHIFT 13 +#define MT6351_PMIC_AUXADC_CK_AON_MD_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_CK_AON_MD_MASK 0x1 +#define MT6351_PMIC_AUXADC_CK_AON_MD_SHIFT 14 +#define MT6351_PMIC_AUXADC_CK_AON_ADDR MT6351_AUXADC_CON0 +#define MT6351_PMIC_AUXADC_CK_AON_MASK 0x1 +#define MT6351_PMIC_AUXADC_CK_AON_SHIFT 15 +#define MT6351_PMIC_AUXADC_CON0_SET_ADDR MT6351_AUXADC_CON0_SET +#define MT6351_PMIC_AUXADC_CON0_SET_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_CON0_SET_SHIFT 0 +#define MT6351_PMIC_AUXADC_CON0_CLR_ADDR MT6351_AUXADC_CON0_CLR +#define MT6351_PMIC_AUXADC_CON0_CLR_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_CON0_CLR_SHIFT 0 +#define MT6351_PMIC_AUXADC_AVG_NUM_SMALL_ADDR MT6351_AUXADC_CON1 +#define MT6351_PMIC_AUXADC_AVG_NUM_SMALL_MASK 0x7 +#define MT6351_PMIC_AUXADC_AVG_NUM_SMALL_SHIFT 0 +#define MT6351_PMIC_AUXADC_AVG_NUM_LARGE_ADDR MT6351_AUXADC_CON1 +#define MT6351_PMIC_AUXADC_AVG_NUM_LARGE_MASK 0x7 +#define MT6351_PMIC_AUXADC_AVG_NUM_LARGE_SHIFT 3 +#define MT6351_PMIC_AUXADC_SPL_NUM_ADDR MT6351_AUXADC_CON1 +#define MT6351_PMIC_AUXADC_SPL_NUM_MASK 0x3FF +#define MT6351_PMIC_AUXADC_SPL_NUM_SHIFT 6 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_ADDR MT6351_AUXADC_CON2 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_MASK 0xFFF +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHIFT 0 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHARE_ADDR MT6351_AUXADC_CON2 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHARE_MASK 0x1 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHARE_SHIFT 12 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_LBAT_ADDR MT6351_AUXADC_CON2 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_LBAT_MASK 0x1 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_LBAT_SHIFT 13 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_VISMPS_ADDR MT6351_AUXADC_CON2 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_VISMPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_VISMPS_SHIFT 14 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_ADDR MT6351_AUXADC_CON2 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_MASK 0x1 +#define MT6351_PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_SHIFT 15 +#define MT6351_PMIC_AUXADC_SPL_NUM_LARGE_ADDR MT6351_AUXADC_CON3 +#define MT6351_PMIC_AUXADC_SPL_NUM_LARGE_MASK 0x3FF +#define MT6351_PMIC_AUXADC_SPL_NUM_LARGE_SHIFT 0 +#define MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_ADDR MT6351_AUXADC_CON4 +#define MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_MASK 0x3FF +#define MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SHIFT 0 +#define MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SEL_ADDR MT6351_AUXADC_CON4 +#define MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SEL_SHIFT 15 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_ADDR MT6351_AUXADC_CON5 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_MASK 0xFFF +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHIFT 0 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHARE_ADDR MT6351_AUXADC_CON5 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHARE_MASK 0x1 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHARE_SHIFT 12 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_LBAT_ADDR MT6351_AUXADC_CON5 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_LBAT_MASK 0x1 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_LBAT_SHIFT 13 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_VISMPS_ADDR MT6351_AUXADC_CON5 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_VISMPS_MASK 0x1 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_VISMPS_SHIFT 14 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_ADDR MT6351_AUXADC_CON5 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_MASK 0x1 +#define MT6351_PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_SHIFT 15 +#define MT6351_PMIC_AUXADC_TRIM_CH0_SEL_ADDR MT6351_AUXADC_CON6 +#define MT6351_PMIC_AUXADC_TRIM_CH0_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH0_SEL_SHIFT 0 +#define MT6351_PMIC_AUXADC_TRIM_CH1_SEL_ADDR MT6351_AUXADC_CON6 +#define MT6351_PMIC_AUXADC_TRIM_CH1_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH1_SEL_SHIFT 2 +#define MT6351_PMIC_AUXADC_TRIM_CH2_SEL_ADDR MT6351_AUXADC_CON6 +#define MT6351_PMIC_AUXADC_TRIM_CH2_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH2_SEL_SHIFT 4 +#define MT6351_PMIC_AUXADC_TRIM_CH3_SEL_ADDR MT6351_AUXADC_CON6 +#define MT6351_PMIC_AUXADC_TRIM_CH3_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH3_SEL_SHIFT 6 +#define MT6351_PMIC_AUXADC_TRIM_CH4_SEL_ADDR MT6351_AUXADC_CON6 +#define MT6351_PMIC_AUXADC_TRIM_CH4_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH4_SEL_SHIFT 8 +#define MT6351_PMIC_AUXADC_TRIM_CH5_SEL_ADDR MT6351_AUXADC_CON6 +#define MT6351_PMIC_AUXADC_TRIM_CH5_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH5_SEL_SHIFT 10 +#define MT6351_PMIC_AUXADC_TRIM_CH6_SEL_ADDR MT6351_AUXADC_CON6 +#define MT6351_PMIC_AUXADC_TRIM_CH6_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH6_SEL_SHIFT 12 +#define MT6351_PMIC_AUXADC_TRIM_CH7_SEL_ADDR MT6351_AUXADC_CON6 +#define MT6351_PMIC_AUXADC_TRIM_CH7_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH7_SEL_SHIFT 14 +#define MT6351_PMIC_AUXADC_TRIM_CH8_SEL_ADDR MT6351_AUXADC_CON7 +#define MT6351_PMIC_AUXADC_TRIM_CH8_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH8_SEL_SHIFT 0 +#define MT6351_PMIC_AUXADC_TRIM_CH9_SEL_ADDR MT6351_AUXADC_CON7 +#define MT6351_PMIC_AUXADC_TRIM_CH9_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH9_SEL_SHIFT 2 +#define MT6351_PMIC_AUXADC_TRIM_CH10_SEL_ADDR MT6351_AUXADC_CON7 +#define MT6351_PMIC_AUXADC_TRIM_CH10_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH10_SEL_SHIFT 4 +#define MT6351_PMIC_AUXADC_TRIM_CH11_SEL_ADDR MT6351_AUXADC_CON7 +#define MT6351_PMIC_AUXADC_TRIM_CH11_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_TRIM_CH11_SEL_SHIFT 6 +#define MT6351_PMIC_AUXADC_ADC_2S_COMP_ENB_ADDR MT6351_AUXADC_CON7 +#define MT6351_PMIC_AUXADC_ADC_2S_COMP_ENB_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_2S_COMP_ENB_SHIFT 14 +#define MT6351_PMIC_AUXADC_ADC_TRIM_COMP_ADDR MT6351_AUXADC_CON7 +#define MT6351_PMIC_AUXADC_ADC_TRIM_COMP_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADC_TRIM_COMP_SHIFT 15 +#define MT6351_PMIC_AUXADC_SW_GAIN_TRIM_ADDR MT6351_AUXADC_CON8 +#define MT6351_PMIC_AUXADC_SW_GAIN_TRIM_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_SW_GAIN_TRIM_SHIFT 0 +#define MT6351_PMIC_AUXADC_SW_OFFSET_TRIM_ADDR MT6351_AUXADC_CON9 +#define MT6351_PMIC_AUXADC_SW_OFFSET_TRIM_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_SW_OFFSET_TRIM_SHIFT 0 +#define MT6351_PMIC_AUXADC_RNG_EN_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_RNG_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_RNG_EN_SHIFT 0 +#define MT6351_PMIC_AUXADC_DATA_REUSE_SEL_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_DATA_REUSE_SEL_MASK 0x3 +#define MT6351_PMIC_AUXADC_DATA_REUSE_SEL_SHIFT 1 +#define MT6351_PMIC_AUXADC_TEST_MODE_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_TEST_MODE_MASK 0x1 +#define MT6351_PMIC_AUXADC_TEST_MODE_SHIFT 3 +#define MT6351_PMIC_AUXADC_BIT_SEL_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_BIT_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_BIT_SEL_SHIFT 4 +#define MT6351_PMIC_AUXADC_START_SW_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_START_SW_MASK 0x1 +#define MT6351_PMIC_AUXADC_START_SW_SHIFT 5 +#define MT6351_PMIC_AUXADC_START_SWCTRL_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_START_SWCTRL_MASK 0x1 +#define MT6351_PMIC_AUXADC_START_SWCTRL_SHIFT 6 +#define MT6351_PMIC_AUXADC_TS_VBE_SEL_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_TS_VBE_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_TS_VBE_SEL_SHIFT 7 +#define MT6351_PMIC_AUXADC_TS_VBE_SEL_SWCTRL_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_TS_VBE_SEL_SWCTRL_MASK 0x1 +#define MT6351_PMIC_AUXADC_TS_VBE_SEL_SWCTRL_SHIFT 8 +#define MT6351_PMIC_AUXADC_VBUF_EN_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_VBUF_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_VBUF_EN_SHIFT 9 +#define MT6351_PMIC_AUXADC_VBUF_EN_SWCTRL_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_VBUF_EN_SWCTRL_MASK 0x1 +#define MT6351_PMIC_AUXADC_VBUF_EN_SWCTRL_SHIFT 10 +#define MT6351_PMIC_AUXADC_OUT_SEL_ADDR MT6351_AUXADC_CON10 +#define MT6351_PMIC_AUXADC_OUT_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_OUT_SEL_SHIFT 11 +#define MT6351_PMIC_AUXADC_DA_DAC_ADDR MT6351_AUXADC_CON11 +#define MT6351_PMIC_AUXADC_DA_DAC_MASK 0xFFF +#define MT6351_PMIC_AUXADC_DA_DAC_SHIFT 0 +#define MT6351_PMIC_AUXADC_DA_DAC_SWCTRL_ADDR MT6351_AUXADC_CON11 +#define MT6351_PMIC_AUXADC_DA_DAC_SWCTRL_MASK 0x1 +#define MT6351_PMIC_AUXADC_DA_DAC_SWCTRL_SHIFT 12 +#define MT6351_PMIC_AD_AUXADC_COMP_ADDR MT6351_AUXADC_CON11 +#define MT6351_PMIC_AD_AUXADC_COMP_MASK 0x1 +#define MT6351_PMIC_AD_AUXADC_COMP_SHIFT 15 +#define MT6351_PMIC_RG_VBUF_EXTEN_ADDR MT6351_AUXADC_CON12 +#define MT6351_PMIC_RG_VBUF_EXTEN_MASK 0x1 +#define MT6351_PMIC_RG_VBUF_EXTEN_SHIFT 0 +#define MT6351_PMIC_RG_VBUF_CALEN_ADDR MT6351_AUXADC_CON12 +#define MT6351_PMIC_RG_VBUF_CALEN_MASK 0x1 +#define MT6351_PMIC_RG_VBUF_CALEN_SHIFT 1 +#define MT6351_PMIC_RG_VBUF_BYP_ADDR MT6351_AUXADC_CON12 +#define MT6351_PMIC_RG_VBUF_BYP_MASK 0x1 +#define MT6351_PMIC_RG_VBUF_BYP_SHIFT 2 +#define MT6351_PMIC_RG_AUX_RSV_ADDR MT6351_AUXADC_CON12 +#define MT6351_PMIC_RG_AUX_RSV_MASK 0xF +#define MT6351_PMIC_RG_AUX_RSV_SHIFT 3 +#define MT6351_PMIC_RG_AUXADC_CALI_ADDR MT6351_AUXADC_CON12 +#define MT6351_PMIC_RG_AUXADC_CALI_MASK 0xF +#define MT6351_PMIC_RG_AUXADC_CALI_SHIFT 7 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_EN_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_EN_SHIFT 0 +#define MT6351_PMIC_AUXADC_ADCIN_VBAT_EN_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_ADCIN_VBAT_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADCIN_VBAT_EN_SHIFT 1 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_MUX_EN_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_MUX_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_MUX_EN_SHIFT 2 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_SHIFT 3 +#define MT6351_PMIC_AUXADC_ADCIN_CHR_EN_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_ADCIN_CHR_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADCIN_CHR_EN_SHIFT 4 +#define MT6351_PMIC_AUXADC_ADCIN_BATON_TDET_EN_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_ADCIN_BATON_TDET_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_ADCIN_BATON_TDET_EN_SHIFT 5 +#define MT6351_PMIC_AUXADC_ACCDET_ANASWCTRL_EN_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_ACCDET_ANASWCTRL_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_ACCDET_ANASWCTRL_EN_SHIFT 6 +#define MT6351_PMIC_AUXADC_DIG0_RSV0_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_DIG0_RSV0_MASK 0xF +#define MT6351_PMIC_AUXADC_DIG0_RSV0_SHIFT 7 +#define MT6351_PMIC_AUXADC_CHSEL_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_CHSEL_MASK 0xF +#define MT6351_PMIC_AUXADC_CHSEL_SHIFT 11 +#define MT6351_PMIC_AUXADC_SWCTRL_EN_ADDR MT6351_AUXADC_CON13 +#define MT6351_PMIC_AUXADC_SWCTRL_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_SWCTRL_EN_SHIFT 15 +#define MT6351_PMIC_AUXADC_SOURCE_LBAT_SEL_ADDR MT6351_AUXADC_CON14 +#define MT6351_PMIC_AUXADC_SOURCE_LBAT_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_SOURCE_LBAT_SEL_SHIFT 0 +#define MT6351_PMIC_AUXADC_SOURCE_LBAT2_SEL_ADDR MT6351_AUXADC_CON14 +#define MT6351_PMIC_AUXADC_SOURCE_LBAT2_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_SOURCE_LBAT2_SEL_SHIFT 1 +#define MT6351_PMIC_AUXADC_DIG0_RSV2_ADDR MT6351_AUXADC_CON14 +#define MT6351_PMIC_AUXADC_DIG0_RSV2_MASK 0x7 +#define MT6351_PMIC_AUXADC_DIG0_RSV2_SHIFT 2 +#define MT6351_PMIC_AUXADC_DIG1_RSV2_ADDR MT6351_AUXADC_CON14 +#define MT6351_PMIC_AUXADC_DIG1_RSV2_MASK 0xF +#define MT6351_PMIC_AUXADC_DIG1_RSV2_SHIFT 5 +#define MT6351_PMIC_AUXADC_DAC_EXTD_ADDR MT6351_AUXADC_CON14 +#define MT6351_PMIC_AUXADC_DAC_EXTD_MASK 0xF +#define MT6351_PMIC_AUXADC_DAC_EXTD_SHIFT 11 +#define MT6351_PMIC_AUXADC_DAC_EXTD_EN_ADDR MT6351_AUXADC_CON14 +#define MT6351_PMIC_AUXADC_DAC_EXTD_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_DAC_EXTD_EN_SHIFT 15 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_SW_ADDR MT6351_AUXADC_CON15 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_SW_MASK 0x1 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_SW_SHIFT 10 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_SEL_ADDR MT6351_AUXADC_CON15 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_SEL_SHIFT 11 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_STATUS_ADDR MT6351_AUXADC_CON15 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_STATUS_MASK 0x1 +#define MT6351_PMIC_AUXADC_PMU_THR_PDN_STATUS_SHIFT 12 +#define MT6351_PMIC_AUXADC_DIG0_RSV1_ADDR MT6351_AUXADC_CON15 +#define MT6351_PMIC_AUXADC_DIG0_RSV1_MASK 0x7 +#define MT6351_PMIC_AUXADC_DIG0_RSV1_SHIFT 13 +#define MT6351_PMIC_AUXADC_START_SHADE_NUM_ADDR MT6351_AUXADC_CON16 +#define MT6351_PMIC_AUXADC_START_SHADE_NUM_MASK 0x3FF +#define MT6351_PMIC_AUXADC_START_SHADE_NUM_SHIFT 0 +#define MT6351_PMIC_AUXADC_START_SHADE_EN_ADDR MT6351_AUXADC_CON16 +#define MT6351_PMIC_AUXADC_START_SHADE_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_START_SHADE_EN_SHIFT 14 +#define MT6351_PMIC_AUXADC_START_SHADE_SEL_ADDR MT6351_AUXADC_CON16 +#define MT6351_PMIC_AUXADC_START_SHADE_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_START_SHADE_SEL_SHIFT 15 +#define MT6351_PMIC_AUXADC_AUTORPT_PRD_ADDR MT6351_AUXADC_AUTORPT0 +#define MT6351_PMIC_AUXADC_AUTORPT_PRD_MASK 0x3FF +#define MT6351_PMIC_AUXADC_AUTORPT_PRD_SHIFT 0 +#define MT6351_PMIC_AUXADC_AUTORPT_EN_ADDR MT6351_AUXADC_AUTORPT0 +#define MT6351_PMIC_AUXADC_AUTORPT_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_AUTORPT_EN_SHIFT 15 +#define MT6351_PMIC_AUXADC_LBAT_DEBT_MAX_ADDR MT6351_AUXADC_LBAT0 +#define MT6351_PMIC_AUXADC_LBAT_DEBT_MAX_MASK 0xFF +#define MT6351_PMIC_AUXADC_LBAT_DEBT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT_DEBT_MIN_ADDR MT6351_AUXADC_LBAT0 +#define MT6351_PMIC_AUXADC_LBAT_DEBT_MIN_MASK 0xFF +#define MT6351_PMIC_AUXADC_LBAT_DEBT_MIN_SHIFT 8 +#define MT6351_PMIC_AUXADC_LBAT_DET_PRD_15_0_ADDR MT6351_AUXADC_LBAT1 +#define MT6351_PMIC_AUXADC_LBAT_DET_PRD_15_0_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_LBAT_DET_PRD_15_0_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT_DET_PRD_19_16_ADDR MT6351_AUXADC_LBAT2 +#define MT6351_PMIC_AUXADC_LBAT_DET_PRD_19_16_MASK 0xF +#define MT6351_PMIC_AUXADC_LBAT_DET_PRD_19_16_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT_VOLT_MAX_ADDR MT6351_AUXADC_LBAT3 +#define MT6351_PMIC_AUXADC_LBAT_VOLT_MAX_MASK 0xFFF +#define MT6351_PMIC_AUXADC_LBAT_VOLT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MAX_ADDR MT6351_AUXADC_LBAT3 +#define MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MAX_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MAX_SHIFT 12 +#define MT6351_PMIC_AUXADC_LBAT_EN_MAX_ADDR MT6351_AUXADC_LBAT3 +#define MT6351_PMIC_AUXADC_LBAT_EN_MAX_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT_EN_MAX_SHIFT 13 +#define MT6351_PMIC_AUXADC_LBAT_MAX_IRQ_B_ADDR MT6351_AUXADC_LBAT3 +#define MT6351_PMIC_AUXADC_LBAT_MAX_IRQ_B_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT_MAX_IRQ_B_SHIFT 15 +#define MT6351_PMIC_AUXADC_LBAT_VOLT_MIN_ADDR MT6351_AUXADC_LBAT4 +#define MT6351_PMIC_AUXADC_LBAT_VOLT_MIN_MASK 0xFFF +#define MT6351_PMIC_AUXADC_LBAT_VOLT_MIN_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MIN_ADDR MT6351_AUXADC_LBAT4 +#define MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MIN_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MIN_SHIFT 12 +#define MT6351_PMIC_AUXADC_LBAT_EN_MIN_ADDR MT6351_AUXADC_LBAT4 +#define MT6351_PMIC_AUXADC_LBAT_EN_MIN_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT_EN_MIN_SHIFT 13 +#define MT6351_PMIC_AUXADC_LBAT_MIN_IRQ_B_ADDR MT6351_AUXADC_LBAT4 +#define MT6351_PMIC_AUXADC_LBAT_MIN_IRQ_B_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT_MIN_IRQ_B_SHIFT 15 +#define MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_ADDR MT6351_AUXADC_LBAT5 +#define MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_ADDR MT6351_AUXADC_LBAT6 +#define MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define MT6351_PMIC_AUXADC_ACCDET_AUTO_SPL_ADDR MT6351_AUXADC_ACCDET +#define MT6351_PMIC_AUXADC_ACCDET_AUTO_SPL_MASK 0x1 +#define MT6351_PMIC_AUXADC_ACCDET_AUTO_SPL_SHIFT 0 +#define MT6351_PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_ADDR MT6351_AUXADC_ACCDET +#define MT6351_PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_MASK 0x1 +#define MT6351_PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_SHIFT 1 +#define MT6351_PMIC_AUXADC_ACCDET_DIG1_RSV0_ADDR MT6351_AUXADC_ACCDET +#define MT6351_PMIC_AUXADC_ACCDET_DIG1_RSV0_MASK 0x3F +#define MT6351_PMIC_AUXADC_ACCDET_DIG1_RSV0_SHIFT 2 +#define MT6351_PMIC_AUXADC_ACCDET_DIG0_RSV0_ADDR MT6351_AUXADC_ACCDET +#define MT6351_PMIC_AUXADC_ACCDET_DIG0_RSV0_MASK 0xFF +#define MT6351_PMIC_AUXADC_ACCDET_DIG0_RSV0_SHIFT 8 +#define MT6351_PMIC_AUXADC_THR_DEBT_MAX_ADDR MT6351_AUXADC_THR0 +#define MT6351_PMIC_AUXADC_THR_DEBT_MAX_MASK 0xFF +#define MT6351_PMIC_AUXADC_THR_DEBT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_THR_DEBT_MIN_ADDR MT6351_AUXADC_THR0 +#define MT6351_PMIC_AUXADC_THR_DEBT_MIN_MASK 0xFF +#define MT6351_PMIC_AUXADC_THR_DEBT_MIN_SHIFT 8 +#define MT6351_PMIC_AUXADC_THR_DET_PRD_15_0_ADDR MT6351_AUXADC_THR1 +#define MT6351_PMIC_AUXADC_THR_DET_PRD_15_0_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_THR_DET_PRD_15_0_SHIFT 0 +#define MT6351_PMIC_AUXADC_THR_DET_PRD_19_16_ADDR MT6351_AUXADC_THR2 +#define MT6351_PMIC_AUXADC_THR_DET_PRD_19_16_MASK 0xF +#define MT6351_PMIC_AUXADC_THR_DET_PRD_19_16_SHIFT 0 +#define MT6351_PMIC_AUXADC_THR_VOLT_MAX_ADDR MT6351_AUXADC_THR3 +#define MT6351_PMIC_AUXADC_THR_VOLT_MAX_MASK 0xFFF +#define MT6351_PMIC_AUXADC_THR_VOLT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_THR_IRQ_EN_MAX_ADDR MT6351_AUXADC_THR3 +#define MT6351_PMIC_AUXADC_THR_IRQ_EN_MAX_MASK 0x1 +#define MT6351_PMIC_AUXADC_THR_IRQ_EN_MAX_SHIFT 12 +#define MT6351_PMIC_AUXADC_THR_EN_MAX_ADDR MT6351_AUXADC_THR3 +#define MT6351_PMIC_AUXADC_THR_EN_MAX_MASK 0x1 +#define MT6351_PMIC_AUXADC_THR_EN_MAX_SHIFT 13 +#define MT6351_PMIC_AUXADC_THR_MAX_IRQ_B_ADDR MT6351_AUXADC_THR3 +#define MT6351_PMIC_AUXADC_THR_MAX_IRQ_B_MASK 0x1 +#define MT6351_PMIC_AUXADC_THR_MAX_IRQ_B_SHIFT 15 +#define MT6351_PMIC_AUXADC_THR_VOLT_MIN_ADDR MT6351_AUXADC_THR4 +#define MT6351_PMIC_AUXADC_THR_VOLT_MIN_MASK 0xFFF +#define MT6351_PMIC_AUXADC_THR_VOLT_MIN_SHIFT 0 +#define MT6351_PMIC_AUXADC_THR_IRQ_EN_MIN_ADDR MT6351_AUXADC_THR4 +#define MT6351_PMIC_AUXADC_THR_IRQ_EN_MIN_MASK 0x1 +#define MT6351_PMIC_AUXADC_THR_IRQ_EN_MIN_SHIFT 12 +#define MT6351_PMIC_AUXADC_THR_EN_MIN_ADDR MT6351_AUXADC_THR4 +#define MT6351_PMIC_AUXADC_THR_EN_MIN_MASK 0x1 +#define MT6351_PMIC_AUXADC_THR_EN_MIN_SHIFT 13 +#define MT6351_PMIC_AUXADC_THR_MIN_IRQ_B_ADDR MT6351_AUXADC_THR4 +#define MT6351_PMIC_AUXADC_THR_MIN_IRQ_B_MASK 0x1 +#define MT6351_PMIC_AUXADC_THR_MIN_IRQ_B_SHIFT 15 +#define MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_ADDR MT6351_AUXADC_THR5 +#define MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_ADDR MT6351_AUXADC_THR6 +#define MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define MT6351_PMIC_EFUSE_GAIN_CH4_TRIM_ADDR MT6351_AUXADC_EFUSE0 +#define MT6351_PMIC_EFUSE_GAIN_CH4_TRIM_MASK 0xFFF +#define MT6351_PMIC_EFUSE_GAIN_CH4_TRIM_SHIFT 0 +#define MT6351_PMIC_EFUSE_OFFSET_CH4_TRIM_ADDR MT6351_AUXADC_EFUSE1 +#define MT6351_PMIC_EFUSE_OFFSET_CH4_TRIM_MASK 0x7FF +#define MT6351_PMIC_EFUSE_OFFSET_CH4_TRIM_SHIFT 0 +#define MT6351_PMIC_EFUSE_GAIN_CH0_TRIM_ADDR MT6351_AUXADC_EFUSE2 +#define MT6351_PMIC_EFUSE_GAIN_CH0_TRIM_MASK 0xFFF +#define MT6351_PMIC_EFUSE_GAIN_CH0_TRIM_SHIFT 0 +#define MT6351_PMIC_EFUSE_OFFSET_CH0_TRIM_ADDR MT6351_AUXADC_EFUSE3 +#define MT6351_PMIC_EFUSE_OFFSET_CH0_TRIM_MASK 0x7FF +#define MT6351_PMIC_EFUSE_OFFSET_CH0_TRIM_SHIFT 0 +#define MT6351_PMIC_EFUSE_GAIN_CH7_TRIM_ADDR MT6351_AUXADC_EFUSE4 +#define MT6351_PMIC_EFUSE_GAIN_CH7_TRIM_MASK 0xFFF +#define MT6351_PMIC_EFUSE_GAIN_CH7_TRIM_SHIFT 0 +#define MT6351_PMIC_EFUSE_OFFSET_CH7_TRIM_ADDR MT6351_AUXADC_EFUSE5 +#define MT6351_PMIC_EFUSE_OFFSET_CH7_TRIM_MASK 0x7FF +#define MT6351_PMIC_EFUSE_OFFSET_CH7_TRIM_SHIFT 0 +#define MT6351_PMIC_AUXADC_FGADC_START_SW_ADDR MT6351_AUXADC_DBG0 +#define MT6351_PMIC_AUXADC_FGADC_START_SW_MASK 0x1 +#define MT6351_PMIC_AUXADC_FGADC_START_SW_SHIFT 0 +#define MT6351_PMIC_AUXADC_FGADC_START_SEL_ADDR MT6351_AUXADC_DBG0 +#define MT6351_PMIC_AUXADC_FGADC_START_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_FGADC_START_SEL_SHIFT 1 +#define MT6351_PMIC_AUXADC_FGADC_R_SW_ADDR MT6351_AUXADC_DBG0 +#define MT6351_PMIC_AUXADC_FGADC_R_SW_MASK 0x1 +#define MT6351_PMIC_AUXADC_FGADC_R_SW_SHIFT 2 +#define MT6351_PMIC_AUXADC_FGADC_R_SEL_ADDR MT6351_AUXADC_DBG0 +#define MT6351_PMIC_AUXADC_FGADC_R_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_FGADC_R_SEL_SHIFT 3 +#define MT6351_PMIC_AUXADC_DBG_DIG0_RSV2_ADDR MT6351_AUXADC_DBG0 +#define MT6351_PMIC_AUXADC_DBG_DIG0_RSV2_MASK 0x3F +#define MT6351_PMIC_AUXADC_DBG_DIG0_RSV2_SHIFT 4 +#define MT6351_PMIC_AUXADC_DBG_DIG1_RSV2_ADDR MT6351_AUXADC_DBG0 +#define MT6351_PMIC_AUXADC_DBG_DIG1_RSV2_MASK 0x3F +#define MT6351_PMIC_AUXADC_DBG_DIG1_RSV2_SHIFT 10 +#define MT6351_PMIC_AUXADC_IMPEDANCE_CNT_ADDR MT6351_AUXADC_IMP0 +#define MT6351_PMIC_AUXADC_IMPEDANCE_CNT_MASK 0x3F +#define MT6351_PMIC_AUXADC_IMPEDANCE_CNT_SHIFT 0 +#define MT6351_PMIC_AUXADC_IMPEDANCE_CHSEL_ADDR MT6351_AUXADC_IMP0 +#define MT6351_PMIC_AUXADC_IMPEDANCE_CHSEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_IMPEDANCE_CHSEL_SHIFT 6 +#define MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_CLR_ADDR MT6351_AUXADC_IMP0 +#define MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_CLR_MASK 0x1 +#define MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_CLR_SHIFT 7 +#define MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_ADDR MT6351_AUXADC_IMP0 +#define MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_MASK 0x1 +#define MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_SHIFT 8 +#define MT6351_PMIC_AUXADC_CLR_IMP_CNT_STOP_ADDR MT6351_AUXADC_IMP0 +#define MT6351_PMIC_AUXADC_CLR_IMP_CNT_STOP_MASK 0x1 +#define MT6351_PMIC_AUXADC_CLR_IMP_CNT_STOP_SHIFT 14 +#define MT6351_PMIC_AUXADC_IMPEDANCE_MODE_ADDR MT6351_AUXADC_IMP0 +#define MT6351_PMIC_AUXADC_IMPEDANCE_MODE_MASK 0x1 +#define MT6351_PMIC_AUXADC_IMPEDANCE_MODE_SHIFT 15 +#define MT6351_PMIC_AUXADC_IMP_AUTORPT_PRD_ADDR MT6351_AUXADC_IMP1 +#define MT6351_PMIC_AUXADC_IMP_AUTORPT_PRD_MASK 0x3FF +#define MT6351_PMIC_AUXADC_IMP_AUTORPT_PRD_SHIFT 0 +#define MT6351_PMIC_AUXADC_IMP_AUTORPT_EN_ADDR MT6351_AUXADC_IMP1 +#define MT6351_PMIC_AUXADC_IMP_AUTORPT_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_IMP_AUTORPT_EN_SHIFT 15 +#define MT6351_PMIC_AUXADC_VISMPS0_DEBT_MAX_ADDR MT6351_AUXADC_VISMPS0_1 +#define MT6351_PMIC_AUXADC_VISMPS0_DEBT_MAX_MASK 0xFF +#define MT6351_PMIC_AUXADC_VISMPS0_DEBT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_VISMPS0_DEBT_MIN_ADDR MT6351_AUXADC_VISMPS0_1 +#define MT6351_PMIC_AUXADC_VISMPS0_DEBT_MIN_MASK 0xFF +#define MT6351_PMIC_AUXADC_VISMPS0_DEBT_MIN_SHIFT 8 +#define MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_15_0_ADDR MT6351_AUXADC_VISMPS0_2 +#define MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_15_0_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_15_0_SHIFT 0 +#define MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_19_16_ADDR MT6351_AUXADC_VISMPS0_3 +#define MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_19_16_MASK 0xF +#define MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_19_16_SHIFT 0 +#define MT6351_PMIC_AUXADC_VISMPS0_VOLT_MAX_ADDR MT6351_AUXADC_VISMPS0_4 +#define MT6351_PMIC_AUXADC_VISMPS0_VOLT_MAX_MASK 0xFFF +#define MT6351_PMIC_AUXADC_VISMPS0_VOLT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_ADDR MT6351_AUXADC_VISMPS0_4 +#define MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_MASK 0x1 +#define MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_SHIFT 12 +#define MT6351_PMIC_AUXADC_VISMPS0_EN_MAX_ADDR MT6351_AUXADC_VISMPS0_4 +#define MT6351_PMIC_AUXADC_VISMPS0_EN_MAX_MASK 0x1 +#define MT6351_PMIC_AUXADC_VISMPS0_EN_MAX_SHIFT 13 +#define MT6351_PMIC_AUXADC_VISMPS0_MAX_IRQ_B_ADDR MT6351_AUXADC_VISMPS0_4 +#define MT6351_PMIC_AUXADC_VISMPS0_MAX_IRQ_B_MASK 0x1 +#define MT6351_PMIC_AUXADC_VISMPS0_MAX_IRQ_B_SHIFT 15 +#define MT6351_PMIC_AUXADC_VISMPS0_VOLT_MIN_ADDR MT6351_AUXADC_VISMPS0_5 +#define MT6351_PMIC_AUXADC_VISMPS0_VOLT_MIN_MASK 0xFFF +#define MT6351_PMIC_AUXADC_VISMPS0_VOLT_MIN_SHIFT 0 +#define MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_ADDR MT6351_AUXADC_VISMPS0_5 +#define MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_MASK 0x1 +#define MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_SHIFT 12 +#define MT6351_PMIC_AUXADC_VISMPS0_EN_MIN_ADDR MT6351_AUXADC_VISMPS0_5 +#define MT6351_PMIC_AUXADC_VISMPS0_EN_MIN_MASK 0x1 +#define MT6351_PMIC_AUXADC_VISMPS0_EN_MIN_SHIFT 13 +#define MT6351_PMIC_AUXADC_VISMPS0_MIN_IRQ_B_ADDR MT6351_AUXADC_VISMPS0_5 +#define MT6351_PMIC_AUXADC_VISMPS0_MIN_IRQ_B_MASK 0x1 +#define MT6351_PMIC_AUXADC_VISMPS0_MIN_IRQ_B_SHIFT 15 +#define MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_ADDR MT6351_AUXADC_VISMPS0_6 +#define MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_ADDR MT6351_AUXADC_VISMPS0_7 +#define MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT2_DEBT_MAX_ADDR MT6351_AUXADC_LBAT2_1 +#define MT6351_PMIC_AUXADC_LBAT2_DEBT_MAX_MASK 0xFF +#define MT6351_PMIC_AUXADC_LBAT2_DEBT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT2_DEBT_MIN_ADDR MT6351_AUXADC_LBAT2_1 +#define MT6351_PMIC_AUXADC_LBAT2_DEBT_MIN_MASK 0xFF +#define MT6351_PMIC_AUXADC_LBAT2_DEBT_MIN_SHIFT 8 +#define MT6351_PMIC_AUXADC_LBAT2_DET_PRD_15_0_ADDR MT6351_AUXADC_LBAT2_2 +#define MT6351_PMIC_AUXADC_LBAT2_DET_PRD_15_0_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_LBAT2_DET_PRD_15_0_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT2_DET_PRD_19_16_ADDR MT6351_AUXADC_LBAT2_3 +#define MT6351_PMIC_AUXADC_LBAT2_DET_PRD_19_16_MASK 0xF +#define MT6351_PMIC_AUXADC_LBAT2_DET_PRD_19_16_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT2_VOLT_MAX_ADDR MT6351_AUXADC_LBAT2_4 +#define MT6351_PMIC_AUXADC_LBAT2_VOLT_MAX_MASK 0xFFF +#define MT6351_PMIC_AUXADC_LBAT2_VOLT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MAX_ADDR MT6351_AUXADC_LBAT2_4 +#define MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MAX_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MAX_SHIFT 12 +#define MT6351_PMIC_AUXADC_LBAT2_EN_MAX_ADDR MT6351_AUXADC_LBAT2_4 +#define MT6351_PMIC_AUXADC_LBAT2_EN_MAX_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT2_EN_MAX_SHIFT 13 +#define MT6351_PMIC_AUXADC_LBAT2_MAX_IRQ_B_ADDR MT6351_AUXADC_LBAT2_4 +#define MT6351_PMIC_AUXADC_LBAT2_MAX_IRQ_B_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT2_MAX_IRQ_B_SHIFT 15 +#define MT6351_PMIC_AUXADC_LBAT2_VOLT_MIN_ADDR MT6351_AUXADC_LBAT2_5 +#define MT6351_PMIC_AUXADC_LBAT2_VOLT_MIN_MASK 0xFFF +#define MT6351_PMIC_AUXADC_LBAT2_VOLT_MIN_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MIN_ADDR MT6351_AUXADC_LBAT2_5 +#define MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MIN_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MIN_SHIFT 12 +#define MT6351_PMIC_AUXADC_LBAT2_EN_MIN_ADDR MT6351_AUXADC_LBAT2_5 +#define MT6351_PMIC_AUXADC_LBAT2_EN_MIN_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT2_EN_MIN_SHIFT 13 +#define MT6351_PMIC_AUXADC_LBAT2_MIN_IRQ_B_ADDR MT6351_AUXADC_LBAT2_5 +#define MT6351_PMIC_AUXADC_LBAT2_MIN_IRQ_B_MASK 0x1 +#define MT6351_PMIC_AUXADC_LBAT2_MIN_IRQ_B_SHIFT 15 +#define MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_ADDR MT6351_AUXADC_LBAT2_6 +#define MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_MASK 0x1FF +#define MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_ADDR MT6351_AUXADC_LBAT2_7 +#define MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_MASK 0x1FF +#define MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define MT6351_PMIC_AUXADC_MDBG_DET_PRD_ADDR MT6351_AUXADC_MDBG_0 +#define MT6351_PMIC_AUXADC_MDBG_DET_PRD_MASK 0x3FF +#define MT6351_PMIC_AUXADC_MDBG_DET_PRD_SHIFT 0 +#define MT6351_PMIC_AUXADC_MDBG_DET_EN_ADDR MT6351_AUXADC_MDBG_0 +#define MT6351_PMIC_AUXADC_MDBG_DET_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_MDBG_DET_EN_SHIFT 15 +#define MT6351_PMIC_AUXADC_MDBG_R_PTR_ADDR MT6351_AUXADC_MDBG_1 +#define MT6351_PMIC_AUXADC_MDBG_R_PTR_MASK 0x3F +#define MT6351_PMIC_AUXADC_MDBG_R_PTR_SHIFT 0 +#define MT6351_PMIC_AUXADC_MDBG_W_PTR_ADDR MT6351_AUXADC_MDBG_1 +#define MT6351_PMIC_AUXADC_MDBG_W_PTR_MASK 0x3F +#define MT6351_PMIC_AUXADC_MDBG_W_PTR_SHIFT 8 +#define MT6351_PMIC_AUXADC_MDBG_BUF_LENGTH_ADDR MT6351_AUXADC_MDBG_2 +#define MT6351_PMIC_AUXADC_MDBG_BUF_LENGTH_MASK 0x3F +#define MT6351_PMIC_AUXADC_MDBG_BUF_LENGTH_SHIFT 0 +#define MT6351_PMIC_AUXADC_MDRT_DET_PRD_ADDR MT6351_AUXADC_MDRT_0 +#define MT6351_PMIC_AUXADC_MDRT_DET_PRD_MASK 0x3FF +#define MT6351_PMIC_AUXADC_MDRT_DET_PRD_SHIFT 0 +#define MT6351_PMIC_AUXADC_MDRT_DET_EN_ADDR MT6351_AUXADC_MDRT_0 +#define MT6351_PMIC_AUXADC_MDRT_DET_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_MDRT_DET_EN_SHIFT 15 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_ADDR MT6351_AUXADC_MDRT_1 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_MASK 0xFFF +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_SHIFT 0 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_ADDR MT6351_AUXADC_MDRT_1 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_MASK 0x1 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_SHIFT 15 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_ADDR MT6351_AUXADC_MDRT_2 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_MASK 0x1 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SHIFT 0 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_ADDR MT6351_AUXADC_MDRT_2 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_SHIFT 1 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_EN_ADDR MT6351_AUXADC_MDRT_2 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_MDRT_DET_WKUP_EN_SHIFT 2 +#define MT6351_PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_ADDR MT6351_AUXADC_MDRT_2 +#define MT6351_PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_MASK 0x1 +#define MT6351_PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_SHIFT 3 +#define MT6351_PMIC_AUXADC_JEITA_IRQ_EN_ADDR MT6351_AUXADC_JEITA_0 +#define MT6351_PMIC_AUXADC_JEITA_IRQ_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_JEITA_IRQ_EN_SHIFT 0 +#define MT6351_PMIC_AUXADC_JEITA_EN_ADDR MT6351_AUXADC_JEITA_0 +#define MT6351_PMIC_AUXADC_JEITA_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_JEITA_EN_SHIFT 1 +#define MT6351_PMIC_AUXADC_JEITA_DET_PRD_ADDR MT6351_AUXADC_JEITA_0 +#define MT6351_PMIC_AUXADC_JEITA_DET_PRD_MASK 0xF +#define MT6351_PMIC_AUXADC_JEITA_DET_PRD_SHIFT 2 +#define MT6351_PMIC_AUXADC_JEITA_DEBT_ADDR MT6351_AUXADC_JEITA_0 +#define MT6351_PMIC_AUXADC_JEITA_DEBT_MASK 0xF +#define MT6351_PMIC_AUXADC_JEITA_DEBT_SHIFT 6 +#define MT6351_PMIC_AUXADC_JEITA_MIPI_DIS_ADDR MT6351_AUXADC_JEITA_0 +#define MT6351_PMIC_AUXADC_JEITA_MIPI_DIS_MASK 0x1 +#define MT6351_PMIC_AUXADC_JEITA_MIPI_DIS_SHIFT 10 +#define MT6351_PMIC_AUXADC_JEITA_VOLT_HOT_ADDR MT6351_AUXADC_JEITA_1 +#define MT6351_PMIC_AUXADC_JEITA_VOLT_HOT_MASK 0xFFF +#define MT6351_PMIC_AUXADC_JEITA_VOLT_HOT_SHIFT 0 +#define MT6351_PMIC_AUXADC_JEITA_HOT_IRQ_ADDR MT6351_AUXADC_JEITA_1 +#define MT6351_PMIC_AUXADC_JEITA_HOT_IRQ_MASK 0x1 +#define MT6351_PMIC_AUXADC_JEITA_HOT_IRQ_SHIFT 15 +#define MT6351_PMIC_AUXADC_JEITA_VOLT_WARM_ADDR MT6351_AUXADC_JEITA_2 +#define MT6351_PMIC_AUXADC_JEITA_VOLT_WARM_MASK 0xFFF +#define MT6351_PMIC_AUXADC_JEITA_VOLT_WARM_SHIFT 0 +#define MT6351_PMIC_AUXADC_JEITA_WARM_IRQ_ADDR MT6351_AUXADC_JEITA_2 +#define MT6351_PMIC_AUXADC_JEITA_WARM_IRQ_MASK 0x1 +#define MT6351_PMIC_AUXADC_JEITA_WARM_IRQ_SHIFT 15 +#define MT6351_PMIC_AUXADC_JEITA_VOLT_COOL_ADDR MT6351_AUXADC_JEITA_3 +#define MT6351_PMIC_AUXADC_JEITA_VOLT_COOL_MASK 0xFFF +#define MT6351_PMIC_AUXADC_JEITA_VOLT_COOL_SHIFT 0 +#define MT6351_PMIC_AUXADC_JEITA_COOL_IRQ_ADDR MT6351_AUXADC_JEITA_3 +#define MT6351_PMIC_AUXADC_JEITA_COOL_IRQ_MASK 0x1 +#define MT6351_PMIC_AUXADC_JEITA_COOL_IRQ_SHIFT 15 +#define MT6351_PMIC_AUXADC_JEITA_VOLT_COLD_ADDR MT6351_AUXADC_JEITA_4 +#define MT6351_PMIC_AUXADC_JEITA_VOLT_COLD_MASK 0xFFF +#define MT6351_PMIC_AUXADC_JEITA_VOLT_COLD_SHIFT 0 +#define MT6351_PMIC_AUXADC_JEITA_COLD_IRQ_ADDR MT6351_AUXADC_JEITA_4 +#define MT6351_PMIC_AUXADC_JEITA_COLD_IRQ_MASK 0x1 +#define MT6351_PMIC_AUXADC_JEITA_COLD_IRQ_SHIFT 15 +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD_ADDR MT6351_AUXADC_JEITA_5 +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD_MASK 0xF +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD_SHIFT 0 +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL_ADDR MT6351_AUXADC_JEITA_5 +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL_MASK 0xF +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL_SHIFT 4 +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM_ADDR MT6351_AUXADC_JEITA_5 +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM_MASK 0xF +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM_SHIFT 8 +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT_ADDR MT6351_AUXADC_JEITA_5 +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT_MASK 0xF +#define MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT_SHIFT 12 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_PRD_ADDR MT6351_AUXADC_DCXO_MDRT_0 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_PRD_MASK 0x3FF +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_PRD_SHIFT 0 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_EN_ADDR MT6351_AUXADC_DCXO_MDRT_0 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_EN_SHIFT 15 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_ADDR MT6351_AUXADC_DCXO_MDRT_1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_MASK 0xFFF +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_SHIFT 0 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_ADDR MT6351_AUXADC_DCXO_MDRT_1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_MASK 0x1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_SHIFT 15 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_ADDR MT6351_AUXADC_DCXO_MDRT_2 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_SHIFT 0 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_ADDR MT6351_AUXADC_DCXO_MDRT_2 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_SHIFT 1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_ADDR MT6351_AUXADC_DCXO_MDRT_2 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_MASK 0x1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SHIFT 2 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_ADDR MT6351_AUXADC_DCXO_MDRT_2 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_MASK 0x1 +#define MT6351_PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_SHIFT 3 +#define MT6351_PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_ADDR MT6351_AUXADC_DCXO_MDRT_2 +#define MT6351_PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_SHIFT 4 +#define MT6351_PMIC_AUXADC_NAG_EN_ADDR MT6351_AUXADC_NAG_0 +#define MT6351_PMIC_AUXADC_NAG_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_NAG_EN_SHIFT 0 +#define MT6351_PMIC_AUXADC_NAG_CLR_ADDR MT6351_AUXADC_NAG_0 +#define MT6351_PMIC_AUXADC_NAG_CLR_MASK 0x1 +#define MT6351_PMIC_AUXADC_NAG_CLR_SHIFT 1 +#define MT6351_PMIC_AUXADC_NAG_VBAT1_SEL_ADDR MT6351_AUXADC_NAG_0 +#define MT6351_PMIC_AUXADC_NAG_VBAT1_SEL_MASK 0x1 +#define MT6351_PMIC_AUXADC_NAG_VBAT1_SEL_SHIFT 2 +#define MT6351_PMIC_AUXADC_NAG_PRD_ADDR MT6351_AUXADC_NAG_0 +#define MT6351_PMIC_AUXADC_NAG_PRD_MASK 0x7F +#define MT6351_PMIC_AUXADC_NAG_PRD_SHIFT 3 +#define MT6351_PMIC_AUXADC_NAG_IRQ_EN_ADDR MT6351_AUXADC_NAG_0 +#define MT6351_PMIC_AUXADC_NAG_IRQ_EN_MASK 0x1 +#define MT6351_PMIC_AUXADC_NAG_IRQ_EN_SHIFT 10 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_IRQ_ADDR MT6351_AUXADC_NAG_0 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_IRQ_MASK 0x1 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_IRQ_SHIFT 15 +#define MT6351_PMIC_AUXADC_NAG_ZCV_ADDR MT6351_AUXADC_NAG_1 +#define MT6351_PMIC_AUXADC_NAG_ZCV_MASK 0x7FFF +#define MT6351_PMIC_AUXADC_NAG_ZCV_SHIFT 0 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_15_0_ADDR MT6351_AUXADC_NAG_2 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_15_0_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_15_0_SHIFT 0 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_26_16_ADDR MT6351_AUXADC_NAG_3 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_26_16_MASK 0x7FF +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_26_16_SHIFT 0 +#define MT6351_PMIC_AUXADC_NAG_CNT_15_0_ADDR MT6351_AUXADC_NAG_4 +#define MT6351_PMIC_AUXADC_NAG_CNT_15_0_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_NAG_CNT_15_0_SHIFT 0 +#define MT6351_PMIC_AUXADC_NAG_CNT_25_16_ADDR MT6351_AUXADC_NAG_5 +#define MT6351_PMIC_AUXADC_NAG_CNT_25_16_MASK 0x3FF +#define MT6351_PMIC_AUXADC_NAG_CNT_25_16_SHIFT 0 +#define MT6351_PMIC_AUXADC_NAG_DLTV_ADDR MT6351_AUXADC_NAG_6 +#define MT6351_PMIC_AUXADC_NAG_DLTV_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_NAG_DLTV_SHIFT 0 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_15_0_ADDR MT6351_AUXADC_NAG_7 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_15_0_MASK 0xFFFF +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_15_0_SHIFT 0 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_26_16_ADDR MT6351_AUXADC_NAG_8 +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_26_16_MASK 0x7FF +#define MT6351_PMIC_AUXADC_NAG_C_DLTV_26_16_SHIFT 0 +#define MT6351_PMIC_AD_AUDACCDETCMPOC_ADDR MT6351_ACCDET_CON0 +#define MT6351_PMIC_AD_AUDACCDETCMPOC_MASK 0x1 +#define MT6351_PMIC_AD_AUDACCDETCMPOC_SHIFT 0 +#define MT6351_PMIC_RG_AUDACCDETANASWCTRLENB_ADDR MT6351_ACCDET_CON0 +#define MT6351_PMIC_RG_AUDACCDETANASWCTRLENB_MASK 0x1 +#define MT6351_PMIC_RG_AUDACCDETANASWCTRLENB_SHIFT 2 +#define MT6351_PMIC_RG_ACCDETSEL_ADDR MT6351_ACCDET_CON0 +#define MT6351_PMIC_RG_ACCDETSEL_MASK 0x1 +#define MT6351_PMIC_RG_ACCDETSEL_SHIFT 3 +#define MT6351_PMIC_RG_AUDACCDETSWCTRL_ADDR MT6351_ACCDET_CON0 +#define MT6351_PMIC_RG_AUDACCDETSWCTRL_MASK 0x7 +#define MT6351_PMIC_RG_AUDACCDETSWCTRL_SHIFT 4 +#define MT6351_PMIC_RG_AUDACCDETTVDET_ADDR MT6351_ACCDET_CON0 +#define MT6351_PMIC_RG_AUDACCDETTVDET_MASK 0x1 +#define MT6351_PMIC_RG_AUDACCDETTVDET_SHIFT 8 +#define MT6351_PMIC_AUDACCDETAUXADCSWCTRL_ADDR MT6351_ACCDET_CON0 +#define MT6351_PMIC_AUDACCDETAUXADCSWCTRL_MASK 0x1 +#define MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SHIFT 10 +#define MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SEL_ADDR MT6351_ACCDET_CON0 +#define MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SEL_MASK 0x1 +#define MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SEL_SHIFT 11 +#define MT6351_PMIC_RG_AUDACCDETRSV_ADDR MT6351_ACCDET_CON0 +#define MT6351_PMIC_RG_AUDACCDETRSV_MASK 0x3 +#define MT6351_PMIC_RG_AUDACCDETRSV_SHIFT 13 +#define MT6351_PMIC_ACCDET_EN_ADDR MT6351_ACCDET_CON1 +#define MT6351_PMIC_ACCDET_EN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EN_SHIFT 0 +#define MT6351_PMIC_ACCDET_SEQ_INIT_ADDR MT6351_ACCDET_CON1 +#define MT6351_PMIC_ACCDET_SEQ_INIT_MASK 0x1 +#define MT6351_PMIC_ACCDET_SEQ_INIT_SHIFT 1 +#define MT6351_PMIC_ACCDET_EINTDET_EN_ADDR MT6351_ACCDET_CON1 +#define MT6351_PMIC_ACCDET_EINTDET_EN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINTDET_EN_SHIFT 2 +#define MT6351_PMIC_ACCDET_EINT_SEQ_INIT_ADDR MT6351_ACCDET_CON1 +#define MT6351_PMIC_ACCDET_EINT_SEQ_INIT_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_SEQ_INIT_SHIFT 3 +#define MT6351_PMIC_ACCDET_NEGVDET_EN_ADDR MT6351_ACCDET_CON1 +#define MT6351_PMIC_ACCDET_NEGVDET_EN_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGVDET_EN_SHIFT 4 +#define MT6351_PMIC_ACCDET_NEGVDET_EN_CTRL_ADDR MT6351_ACCDET_CON1 +#define MT6351_PMIC_ACCDET_NEGVDET_EN_CTRL_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGVDET_EN_CTRL_SHIFT 5 +#define MT6351_PMIC_ACCDET_ANASWCTRL_SEL_ADDR MT6351_ACCDET_CON1 +#define MT6351_PMIC_ACCDET_ANASWCTRL_SEL_MASK 0x1 +#define MT6351_PMIC_ACCDET_ANASWCTRL_SEL_SHIFT 6 +#define MT6351_PMIC_ACCDET_CMP_PWM_EN_ADDR MT6351_ACCDET_CON2 +#define MT6351_PMIC_ACCDET_CMP_PWM_EN_MASK 0x1 +#define MT6351_PMIC_ACCDET_CMP_PWM_EN_SHIFT 0 +#define MT6351_PMIC_ACCDET_VTH_PWM_EN_ADDR MT6351_ACCDET_CON2 +#define MT6351_PMIC_ACCDET_VTH_PWM_EN_MASK 0x1 +#define MT6351_PMIC_ACCDET_VTH_PWM_EN_SHIFT 1 +#define MT6351_PMIC_ACCDET_MBIAS_PWM_EN_ADDR MT6351_ACCDET_CON2 +#define MT6351_PMIC_ACCDET_MBIAS_PWM_EN_MASK 0x1 +#define MT6351_PMIC_ACCDET_MBIAS_PWM_EN_SHIFT 2 +#define MT6351_PMIC_ACCDET_EINT_PWM_EN_ADDR MT6351_ACCDET_CON2 +#define MT6351_PMIC_ACCDET_EINT_PWM_EN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_PWM_EN_SHIFT 3 +#define MT6351_PMIC_ACCDET_CMP_PWM_IDLE_ADDR MT6351_ACCDET_CON2 +#define MT6351_PMIC_ACCDET_CMP_PWM_IDLE_MASK 0x1 +#define MT6351_PMIC_ACCDET_CMP_PWM_IDLE_SHIFT 4 +#define MT6351_PMIC_ACCDET_VTH_PWM_IDLE_ADDR MT6351_ACCDET_CON2 +#define MT6351_PMIC_ACCDET_VTH_PWM_IDLE_MASK 0x1 +#define MT6351_PMIC_ACCDET_VTH_PWM_IDLE_SHIFT 5 +#define MT6351_PMIC_ACCDET_MBIAS_PWM_IDLE_ADDR MT6351_ACCDET_CON2 +#define MT6351_PMIC_ACCDET_MBIAS_PWM_IDLE_MASK 0x1 +#define MT6351_PMIC_ACCDET_MBIAS_PWM_IDLE_SHIFT 6 +#define MT6351_PMIC_ACCDET_EINT_PWM_IDLE_ADDR MT6351_ACCDET_CON2 +#define MT6351_PMIC_ACCDET_EINT_PWM_IDLE_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_PWM_IDLE_SHIFT 7 +#define MT6351_PMIC_ACCDET_PWM_WIDTH_ADDR MT6351_ACCDET_CON3 +#define MT6351_PMIC_ACCDET_PWM_WIDTH_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_PWM_WIDTH_SHIFT 0 +#define MT6351_PMIC_ACCDET_PWM_THRESH_ADDR MT6351_ACCDET_CON4 +#define MT6351_PMIC_ACCDET_PWM_THRESH_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_PWM_THRESH_SHIFT 0 +#define MT6351_PMIC_ACCDET_RISE_DELAY_ADDR MT6351_ACCDET_CON5 +#define MT6351_PMIC_ACCDET_RISE_DELAY_MASK 0x7FFF +#define MT6351_PMIC_ACCDET_RISE_DELAY_SHIFT 0 +#define MT6351_PMIC_ACCDET_FALL_DELAY_ADDR MT6351_ACCDET_CON5 +#define MT6351_PMIC_ACCDET_FALL_DELAY_MASK 0x1 +#define MT6351_PMIC_ACCDET_FALL_DELAY_SHIFT 15 +#define MT6351_PMIC_ACCDET_DEBOUNCE0_ADDR MT6351_ACCDET_CON6 +#define MT6351_PMIC_ACCDET_DEBOUNCE0_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_DEBOUNCE0_SHIFT 0 +#define MT6351_PMIC_ACCDET_DEBOUNCE1_ADDR MT6351_ACCDET_CON7 +#define MT6351_PMIC_ACCDET_DEBOUNCE1_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_DEBOUNCE1_SHIFT 0 +#define MT6351_PMIC_ACCDET_DEBOUNCE2_ADDR MT6351_ACCDET_CON8 +#define MT6351_PMIC_ACCDET_DEBOUNCE2_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_DEBOUNCE2_SHIFT 0 +#define MT6351_PMIC_ACCDET_DEBOUNCE3_ADDR MT6351_ACCDET_CON9 +#define MT6351_PMIC_ACCDET_DEBOUNCE3_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_DEBOUNCE3_SHIFT 0 +#define MT6351_PMIC_ACCDET_DEBOUNCE4_ADDR MT6351_ACCDET_CON10 +#define MT6351_PMIC_ACCDET_DEBOUNCE4_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_DEBOUNCE4_SHIFT 0 +#define MT6351_PMIC_ACCDET_IVAL_CUR_IN_ADDR MT6351_ACCDET_CON11 +#define MT6351_PMIC_ACCDET_IVAL_CUR_IN_MASK 0x3 +#define MT6351_PMIC_ACCDET_IVAL_CUR_IN_SHIFT 0 +#define MT6351_PMIC_ACCDET_EINT_IVAL_CUR_IN_ADDR MT6351_ACCDET_CON11 +#define MT6351_PMIC_ACCDET_EINT_IVAL_CUR_IN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_IVAL_CUR_IN_SHIFT 2 +#define MT6351_PMIC_ACCDET_IVAL_SAM_IN_ADDR MT6351_ACCDET_CON11 +#define MT6351_PMIC_ACCDET_IVAL_SAM_IN_MASK 0x3 +#define MT6351_PMIC_ACCDET_IVAL_SAM_IN_SHIFT 4 +#define MT6351_PMIC_ACCDET_EINT_IVAL_SAM_IN_ADDR MT6351_ACCDET_CON11 +#define MT6351_PMIC_ACCDET_EINT_IVAL_SAM_IN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_IVAL_SAM_IN_SHIFT 6 +#define MT6351_PMIC_ACCDET_IVAL_MEM_IN_ADDR MT6351_ACCDET_CON11 +#define MT6351_PMIC_ACCDET_IVAL_MEM_IN_MASK 0x3 +#define MT6351_PMIC_ACCDET_IVAL_MEM_IN_SHIFT 8 +#define MT6351_PMIC_ACCDET_EINT_IVAL_MEM_IN_ADDR MT6351_ACCDET_CON11 +#define MT6351_PMIC_ACCDET_EINT_IVAL_MEM_IN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_IVAL_MEM_IN_SHIFT 10 +#define MT6351_PMIC_ACCDET_EINT_IVAL_SEL_ADDR MT6351_ACCDET_CON11 +#define MT6351_PMIC_ACCDET_EINT_IVAL_SEL_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_IVAL_SEL_SHIFT 14 +#define MT6351_PMIC_ACCDET_IVAL_SEL_ADDR MT6351_ACCDET_CON11 +#define MT6351_PMIC_ACCDET_IVAL_SEL_MASK 0x1 +#define MT6351_PMIC_ACCDET_IVAL_SEL_SHIFT 15 +#define MT6351_PMIC_ACCDET_IRQ_ADDR MT6351_ACCDET_CON12 +#define MT6351_PMIC_ACCDET_IRQ_MASK 0x1 +#define MT6351_PMIC_ACCDET_IRQ_SHIFT 0 +#define MT6351_PMIC_ACCDET_NEGV_IRQ_ADDR MT6351_ACCDET_CON12 +#define MT6351_PMIC_ACCDET_NEGV_IRQ_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGV_IRQ_SHIFT 1 +#define MT6351_PMIC_ACCDET_EINT_IRQ_ADDR MT6351_ACCDET_CON12 +#define MT6351_PMIC_ACCDET_EINT_IRQ_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_IRQ_SHIFT 2 +#define MT6351_PMIC_ACCDET_IRQ_CLR_ADDR MT6351_ACCDET_CON12 +#define MT6351_PMIC_ACCDET_IRQ_CLR_MASK 0x1 +#define MT6351_PMIC_ACCDET_IRQ_CLR_SHIFT 8 +#define MT6351_PMIC_ACCDET_NEGV_IRQ_CLR_ADDR MT6351_ACCDET_CON12 +#define MT6351_PMIC_ACCDET_NEGV_IRQ_CLR_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGV_IRQ_CLR_SHIFT 9 +#define MT6351_PMIC_ACCDET_EINT_IRQ_CLR_ADDR MT6351_ACCDET_CON12 +#define MT6351_PMIC_ACCDET_EINT_IRQ_CLR_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_IRQ_CLR_SHIFT 10 +#define MT6351_PMIC_ACCDET_EINT_IRQ_POLARITY_ADDR MT6351_ACCDET_CON12 +#define MT6351_PMIC_ACCDET_EINT_IRQ_POLARITY_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_IRQ_POLARITY_SHIFT 15 +#define MT6351_PMIC_ACCDET_TEST_MODE0_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_TEST_MODE0_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE0_SHIFT 0 +#define MT6351_PMIC_ACCDET_TEST_MODE1_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_TEST_MODE1_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE1_SHIFT 1 +#define MT6351_PMIC_ACCDET_TEST_MODE2_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_TEST_MODE2_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE2_SHIFT 2 +#define MT6351_PMIC_ACCDET_TEST_MODE3_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_TEST_MODE3_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE3_SHIFT 3 +#define MT6351_PMIC_ACCDET_TEST_MODE4_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_TEST_MODE4_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE4_SHIFT 4 +#define MT6351_PMIC_ACCDET_TEST_MODE5_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_TEST_MODE5_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE5_SHIFT 5 +#define MT6351_PMIC_ACCDET_PWM_SEL_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_PWM_SEL_MASK 0x3 +#define MT6351_PMIC_ACCDET_PWM_SEL_SHIFT 6 +#define MT6351_PMIC_ACCDET_IN_SW_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_IN_SW_MASK 0x3 +#define MT6351_PMIC_ACCDET_IN_SW_SHIFT 8 +#define MT6351_PMIC_ACCDET_CMP_EN_SW_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_CMP_EN_SW_MASK 0x1 +#define MT6351_PMIC_ACCDET_CMP_EN_SW_SHIFT 12 +#define MT6351_PMIC_ACCDET_VTH_EN_SW_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_VTH_EN_SW_MASK 0x1 +#define MT6351_PMIC_ACCDET_VTH_EN_SW_SHIFT 13 +#define MT6351_PMIC_ACCDET_MBIAS_EN_SW_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_MBIAS_EN_SW_MASK 0x1 +#define MT6351_PMIC_ACCDET_MBIAS_EN_SW_SHIFT 14 +#define MT6351_PMIC_ACCDET_PWM_EN_SW_ADDR MT6351_ACCDET_CON13 +#define MT6351_PMIC_ACCDET_PWM_EN_SW_MASK 0x1 +#define MT6351_PMIC_ACCDET_PWM_EN_SW_SHIFT 15 +#define MT6351_PMIC_ACCDET_IN_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_ACCDET_IN_MASK 0x3 +#define MT6351_PMIC_ACCDET_IN_SHIFT 0 +#define MT6351_PMIC_ACCDET_CUR_IN_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_ACCDET_CUR_IN_MASK 0x3 +#define MT6351_PMIC_ACCDET_CUR_IN_SHIFT 2 +#define MT6351_PMIC_ACCDET_SAM_IN_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_ACCDET_SAM_IN_MASK 0x3 +#define MT6351_PMIC_ACCDET_SAM_IN_SHIFT 4 +#define MT6351_PMIC_ACCDET_MEM_IN_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_ACCDET_MEM_IN_MASK 0x3 +#define MT6351_PMIC_ACCDET_MEM_IN_SHIFT 6 +#define MT6351_PMIC_ACCDET_STATE_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_ACCDET_STATE_MASK 0x7 +#define MT6351_PMIC_ACCDET_STATE_SHIFT 8 +#define MT6351_PMIC_ACCDET_MBIAS_CLK_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_ACCDET_MBIAS_CLK_MASK 0x1 +#define MT6351_PMIC_ACCDET_MBIAS_CLK_SHIFT 12 +#define MT6351_PMIC_ACCDET_VTH_CLK_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_ACCDET_VTH_CLK_MASK 0x1 +#define MT6351_PMIC_ACCDET_VTH_CLK_SHIFT 13 +#define MT6351_PMIC_ACCDET_CMP_CLK_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_ACCDET_CMP_CLK_MASK 0x1 +#define MT6351_PMIC_ACCDET_CMP_CLK_SHIFT 14 +#define MT6351_PMIC_DA_NI_AUDACCDETAUXADCSWCTRL_ADDR MT6351_ACCDET_CON14 +#define MT6351_PMIC_DA_NI_AUDACCDETAUXADCSWCTRL_MASK 0x1 +#define MT6351_PMIC_DA_NI_AUDACCDETAUXADCSWCTRL_SHIFT 15 +#define MT6351_PMIC_ACCDET_EINT_DEB_SEL_ADDR MT6351_ACCDET_CON15 +#define MT6351_PMIC_ACCDET_EINT_DEB_SEL_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_DEB_SEL_SHIFT 0 +#define MT6351_PMIC_ACCDET_EINT_DEBOUNCE_ADDR MT6351_ACCDET_CON15 +#define MT6351_PMIC_ACCDET_EINT_DEBOUNCE_MASK 0x7 +#define MT6351_PMIC_ACCDET_EINT_DEBOUNCE_SHIFT 4 +#define MT6351_PMIC_ACCDET_EINT_PWM_THRESH_ADDR MT6351_ACCDET_CON15 +#define MT6351_PMIC_ACCDET_EINT_PWM_THRESH_MASK 0x7 +#define MT6351_PMIC_ACCDET_EINT_PWM_THRESH_SHIFT 8 +#define MT6351_PMIC_ACCDET_EINT_PWM_WIDTH_ADDR MT6351_ACCDET_CON15 +#define MT6351_PMIC_ACCDET_EINT_PWM_WIDTH_MASK 0x3 +#define MT6351_PMIC_ACCDET_EINT_PWM_WIDTH_SHIFT 12 +#define MT6351_PMIC_ACCDET_NEGV_THRESH_ADDR MT6351_ACCDET_CON16 +#define MT6351_PMIC_ACCDET_NEGV_THRESH_MASK 0x1F +#define MT6351_PMIC_ACCDET_NEGV_THRESH_SHIFT 0 +#define MT6351_PMIC_ACCDET_EINT_PWM_FALL_DELAY_ADDR MT6351_ACCDET_CON16 +#define MT6351_PMIC_ACCDET_EINT_PWM_FALL_DELAY_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_PWM_FALL_DELAY_SHIFT 5 +#define MT6351_PMIC_ACCDET_EINT_PWM_RISE_DELAY_ADDR MT6351_ACCDET_CON16 +#define MT6351_PMIC_ACCDET_EINT_PWM_RISE_DELAY_MASK 0x3FF +#define MT6351_PMIC_ACCDET_EINT_PWM_RISE_DELAY_SHIFT 6 +#define MT6351_PMIC_ACCDET_TEST_MODE13_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_TEST_MODE13_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE13_SHIFT 1 +#define MT6351_PMIC_ACCDET_TEST_MODE12_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_TEST_MODE12_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE12_SHIFT 2 +#define MT6351_PMIC_ACCDET_NVDETECTOUT_SW_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_NVDETECTOUT_SW_MASK 0x1 +#define MT6351_PMIC_ACCDET_NVDETECTOUT_SW_SHIFT 3 +#define MT6351_PMIC_ACCDET_TEST_MODE11_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_TEST_MODE11_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE11_SHIFT 5 +#define MT6351_PMIC_ACCDET_TEST_MODE10_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_TEST_MODE10_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE10_SHIFT 6 +#define MT6351_PMIC_ACCDET_EINTCMPOUT_SW_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_EINTCMPOUT_SW_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINTCMPOUT_SW_SHIFT 7 +#define MT6351_PMIC_ACCDET_TEST_MODE9_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_TEST_MODE9_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE9_SHIFT 9 +#define MT6351_PMIC_ACCDET_TEST_MODE8_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_TEST_MODE8_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE8_SHIFT 10 +#define MT6351_PMIC_ACCDET_AUXADC_CTRL_SW_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_AUXADC_CTRL_SW_MASK 0x1 +#define MT6351_PMIC_ACCDET_AUXADC_CTRL_SW_SHIFT 11 +#define MT6351_PMIC_ACCDET_TEST_MODE7_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_TEST_MODE7_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE7_SHIFT 13 +#define MT6351_PMIC_ACCDET_TEST_MODE6_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_TEST_MODE6_MASK 0x1 +#define MT6351_PMIC_ACCDET_TEST_MODE6_SHIFT 14 +#define MT6351_PMIC_ACCDET_EINTCMP_EN_SW_ADDR MT6351_ACCDET_CON17 +#define MT6351_PMIC_ACCDET_EINTCMP_EN_SW_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINTCMP_EN_SW_SHIFT 15 +#define MT6351_PMIC_ACCDET_EINT_STATE_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_ACCDET_EINT_STATE_MASK 0x7 +#define MT6351_PMIC_ACCDET_EINT_STATE_SHIFT 0 +#define MT6351_PMIC_ACCDET_AUXADC_DEBOUNCE_END_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_ACCDET_AUXADC_DEBOUNCE_END_MASK 0x1 +#define MT6351_PMIC_ACCDET_AUXADC_DEBOUNCE_END_SHIFT 3 +#define MT6351_PMIC_ACCDET_AUXADC_CONNECT_PRE_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_ACCDET_AUXADC_CONNECT_PRE_MASK 0x1 +#define MT6351_PMIC_ACCDET_AUXADC_CONNECT_PRE_SHIFT 4 +#define MT6351_PMIC_ACCDET_EINT_CUR_IN_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_ACCDET_EINT_CUR_IN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_CUR_IN_SHIFT 8 +#define MT6351_PMIC_ACCDET_EINT_SAM_IN_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_ACCDET_EINT_SAM_IN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_SAM_IN_SHIFT 9 +#define MT6351_PMIC_ACCDET_EINT_MEM_IN_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_ACCDET_EINT_MEM_IN_MASK 0x1 +#define MT6351_PMIC_ACCDET_EINT_MEM_IN_SHIFT 10 +#define MT6351_PMIC_AD_NVDETECTOUT_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_AD_NVDETECTOUT_MASK 0x1 +#define MT6351_PMIC_AD_NVDETECTOUT_SHIFT 13 +#define MT6351_PMIC_AD_EINTCMPOUT_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_AD_EINTCMPOUT_MASK 0x1 +#define MT6351_PMIC_AD_EINTCMPOUT_SHIFT 14 +#define MT6351_PMIC_DA_NI_EINTCMPEN_ADDR MT6351_ACCDET_CON19 +#define MT6351_PMIC_DA_NI_EINTCMPEN_MASK 0x1 +#define MT6351_PMIC_DA_NI_EINTCMPEN_SHIFT 15 +#define MT6351_PMIC_ACCDET_NEGV_COUNT_IN_ADDR MT6351_ACCDET_CON20 +#define MT6351_PMIC_ACCDET_NEGV_COUNT_IN_MASK 0x3F +#define MT6351_PMIC_ACCDET_NEGV_COUNT_IN_SHIFT 0 +#define MT6351_PMIC_ACCDET_NEGV_EN_FINAL_ADDR MT6351_ACCDET_CON20 +#define MT6351_PMIC_ACCDET_NEGV_EN_FINAL_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGV_EN_FINAL_SHIFT 6 +#define MT6351_PMIC_ACCDET_NEGV_COUNT_END_ADDR MT6351_ACCDET_CON20 +#define MT6351_PMIC_ACCDET_NEGV_COUNT_END_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGV_COUNT_END_SHIFT 12 +#define MT6351_PMIC_ACCDET_NEGV_MINU_ADDR MT6351_ACCDET_CON20 +#define MT6351_PMIC_ACCDET_NEGV_MINU_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGV_MINU_SHIFT 13 +#define MT6351_PMIC_ACCDET_NEGV_ADD_ADDR MT6351_ACCDET_CON20 +#define MT6351_PMIC_ACCDET_NEGV_ADD_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGV_ADD_SHIFT 14 +#define MT6351_PMIC_ACCDET_NEGV_CMP_ADDR MT6351_ACCDET_CON20 +#define MT6351_PMIC_ACCDET_NEGV_CMP_MASK 0x1 +#define MT6351_PMIC_ACCDET_NEGV_CMP_SHIFT 15 +#define MT6351_PMIC_ACCDET_CUR_DEB_ADDR MT6351_ACCDET_CON21 +#define MT6351_PMIC_ACCDET_CUR_DEB_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_CUR_DEB_SHIFT 0 +#define MT6351_PMIC_ACCDET_EINT_CUR_DEB_ADDR MT6351_ACCDET_CON22 +#define MT6351_PMIC_ACCDET_EINT_CUR_DEB_MASK 0x7FFF +#define MT6351_PMIC_ACCDET_EINT_CUR_DEB_SHIFT 0 +#define MT6351_PMIC_ACCDET_RSV_CON0_ADDR MT6351_ACCDET_CON23 +#define MT6351_PMIC_ACCDET_RSV_CON0_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_RSV_CON0_SHIFT 0 +#define MT6351_PMIC_ACCDET_RSV_CON1_ADDR MT6351_ACCDET_CON24 +#define MT6351_PMIC_ACCDET_RSV_CON1_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_RSV_CON1_SHIFT 0 +#define MT6351_PMIC_ACCDET_AUXADC_CONNECT_TIME_ADDR MT6351_ACCDET_CON25 +#define MT6351_PMIC_ACCDET_AUXADC_CONNECT_TIME_MASK 0xFFFF +#define MT6351_PMIC_ACCDET_AUXADC_CONNECT_TIME_SHIFT 0 +#define MT6351_PMIC_RG_VCDT_HV_EN_ADDR MT6351_CHR_CON0 +#define MT6351_PMIC_RG_VCDT_HV_EN_MASK 0x1 +#define MT6351_PMIC_RG_VCDT_HV_EN_SHIFT 0 +#define MT6351_PMIC_RGS_CHR_LDO_DET_ADDR MT6351_CHR_CON0 +#define MT6351_PMIC_RGS_CHR_LDO_DET_MASK 0x1 +#define MT6351_PMIC_RGS_CHR_LDO_DET_SHIFT 1 +#define MT6351_PMIC_RG_PCHR_AUTOMODE_ADDR MT6351_CHR_CON0 +#define MT6351_PMIC_RG_PCHR_AUTOMODE_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_AUTOMODE_SHIFT 2 +#define MT6351_PMIC_RG_CSDAC_EN_ADDR MT6351_CHR_CON0 +#define MT6351_PMIC_RG_CSDAC_EN_MASK 0x1 +#define MT6351_PMIC_RG_CSDAC_EN_SHIFT 3 +#define MT6351_PMIC_RG_NORM_CHR_EN_ADDR MT6351_CHR_CON0 +#define MT6351_PMIC_RG_NORM_CHR_EN_MASK 0x1 +#define MT6351_PMIC_RG_NORM_CHR_EN_SHIFT 4 +#define MT6351_PMIC_RGS_CHRDET_ADDR MT6351_CHR_CON0 +#define MT6351_PMIC_RGS_CHRDET_MASK 0x1 +#define MT6351_PMIC_RGS_CHRDET_SHIFT 5 +#define MT6351_PMIC_RGS_VCDT_LV_DET_ADDR MT6351_CHR_CON0 +#define MT6351_PMIC_RGS_VCDT_LV_DET_MASK 0x1 +#define MT6351_PMIC_RGS_VCDT_LV_DET_SHIFT 6 +#define MT6351_PMIC_RGS_VCDT_HV_DET_ADDR MT6351_CHR_CON0 +#define MT6351_PMIC_RGS_VCDT_HV_DET_MASK 0x1 +#define MT6351_PMIC_RGS_VCDT_HV_DET_SHIFT 7 +#define MT6351_PMIC_RG_VCDT_LV_VTH_ADDR MT6351_CHR_CON1 +#define MT6351_PMIC_RG_VCDT_LV_VTH_MASK 0xF +#define MT6351_PMIC_RG_VCDT_LV_VTH_SHIFT 0 +#define MT6351_PMIC_RG_VCDT_HV_VTH_ADDR MT6351_CHR_CON1 +#define MT6351_PMIC_RG_VCDT_HV_VTH_MASK 0xF +#define MT6351_PMIC_RG_VCDT_HV_VTH_SHIFT 4 +#define MT6351_PMIC_RG_VBAT_CV_EN_ADDR MT6351_CHR_CON2 +#define MT6351_PMIC_RG_VBAT_CV_EN_MASK 0x1 +#define MT6351_PMIC_RG_VBAT_CV_EN_SHIFT 1 +#define MT6351_PMIC_RG_VBAT_CC_EN_ADDR MT6351_CHR_CON2 +#define MT6351_PMIC_RG_VBAT_CC_EN_MASK 0x1 +#define MT6351_PMIC_RG_VBAT_CC_EN_SHIFT 2 +#define MT6351_PMIC_RG_CS_EN_ADDR MT6351_CHR_CON2 +#define MT6351_PMIC_RG_CS_EN_MASK 0x1 +#define MT6351_PMIC_RG_CS_EN_SHIFT 3 +#define MT6351_PMIC_RGS_CS_DET_ADDR MT6351_CHR_CON2 +#define MT6351_PMIC_RGS_CS_DET_MASK 0x1 +#define MT6351_PMIC_RGS_CS_DET_SHIFT 5 +#define MT6351_PMIC_RGS_VBAT_CV_DET_ADDR MT6351_CHR_CON2 +#define MT6351_PMIC_RGS_VBAT_CV_DET_MASK 0x1 +#define MT6351_PMIC_RGS_VBAT_CV_DET_SHIFT 6 +#define MT6351_PMIC_RGS_VBAT_CC_DET_ADDR MT6351_CHR_CON2 +#define MT6351_PMIC_RGS_VBAT_CC_DET_MASK 0x1 +#define MT6351_PMIC_RGS_VBAT_CC_DET_SHIFT 7 +#define MT6351_PMIC_RG_VBAT_NORM_CV_VTH_ADDR MT6351_CHR_CON3 +#define MT6351_PMIC_RG_VBAT_NORM_CV_VTH_MASK 0x3F +#define MT6351_PMIC_RG_VBAT_NORM_CV_VTH_SHIFT 0 +#define MT6351_PMIC_RG_VBAT_CC_VTH_ADDR MT6351_CHR_CON3 +#define MT6351_PMIC_RG_VBAT_CC_VTH_MASK 0x3 +#define MT6351_PMIC_RG_VBAT_CC_VTH_SHIFT 6 +#define MT6351_PMIC_RG_NORM_CS_VTH_ADDR MT6351_CHR_CON4 +#define MT6351_PMIC_RG_NORM_CS_VTH_MASK 0xF +#define MT6351_PMIC_RG_NORM_CS_VTH_SHIFT 0 +#define MT6351_PMIC_RG_PCHR_TOHTC_ADDR MT6351_CHR_CON5 +#define MT6351_PMIC_RG_PCHR_TOHTC_MASK 0x7 +#define MT6351_PMIC_RG_PCHR_TOHTC_SHIFT 0 +#define MT6351_PMIC_RG_PCHR_TOLTC_ADDR MT6351_CHR_CON5 +#define MT6351_PMIC_RG_PCHR_TOLTC_MASK 0x7 +#define MT6351_PMIC_RG_PCHR_TOLTC_SHIFT 4 +#define MT6351_PMIC_RG_VBAT_OV_EN_ADDR MT6351_CHR_CON6 +#define MT6351_PMIC_RG_VBAT_OV_EN_MASK 0x1 +#define MT6351_PMIC_RG_VBAT_OV_EN_SHIFT 0 +#define MT6351_PMIC_RG_VBAT_OV_VTH_ADDR MT6351_CHR_CON6 +#define MT6351_PMIC_RG_VBAT_OV_VTH_MASK 0xF +#define MT6351_PMIC_RG_VBAT_OV_VTH_SHIFT 1 +#define MT6351_PMIC_RG_VBAT_OV_DEG_ADDR MT6351_CHR_CON6 +#define MT6351_PMIC_RG_VBAT_OV_DEG_MASK 0x1 +#define MT6351_PMIC_RG_VBAT_OV_DEG_SHIFT 5 +#define MT6351_PMIC_RGS_VBAT_OV_DET_ADDR MT6351_CHR_CON6 +#define MT6351_PMIC_RGS_VBAT_OV_DET_MASK 0x1 +#define MT6351_PMIC_RGS_VBAT_OV_DET_SHIFT 6 +#define MT6351_PMIC_RG_BATON_EN_ADDR MT6351_CHR_CON7 +#define MT6351_PMIC_RG_BATON_EN_MASK 0x1 +#define MT6351_PMIC_RG_BATON_EN_SHIFT 0 +#define MT6351_PMIC_RG_BATON_HT_EN_RSV0_ADDR MT6351_CHR_CON7 +#define MT6351_PMIC_RG_BATON_HT_EN_RSV0_MASK 0x1 +#define MT6351_PMIC_RG_BATON_HT_EN_RSV0_SHIFT 1 +#define MT6351_PMIC_BATON_TDET_EN_ADDR MT6351_CHR_CON7 +#define MT6351_PMIC_BATON_TDET_EN_MASK 0x1 +#define MT6351_PMIC_BATON_TDET_EN_SHIFT 2 +#define MT6351_PMIC_RG_BATON_HT_TRIM_ADDR MT6351_CHR_CON7 +#define MT6351_PMIC_RG_BATON_HT_TRIM_MASK 0x7 +#define MT6351_PMIC_RG_BATON_HT_TRIM_SHIFT 4 +#define MT6351_PMIC_RG_BATON_HT_TRIM_SET_ADDR MT6351_CHR_CON7 +#define MT6351_PMIC_RG_BATON_HT_TRIM_SET_MASK 0x1 +#define MT6351_PMIC_RG_BATON_HT_TRIM_SET_SHIFT 7 +#define MT6351_PMIC_RG_BATON_TDET_EN_ADDR MT6351_CHR_CON7 +#define MT6351_PMIC_RG_BATON_TDET_EN_MASK 0x1 +#define MT6351_PMIC_RG_BATON_TDET_EN_SHIFT 8 +#define MT6351_PMIC_RG_CSDAC_DATA_ADDR MT6351_CHR_CON8 +#define MT6351_PMIC_RG_CSDAC_DATA_MASK 0x3FF +#define MT6351_PMIC_RG_CSDAC_DATA_SHIFT 0 +#define MT6351_PMIC_RG_FRC_CSVTH_USBDL_ADDR MT6351_CHR_CON9 +#define MT6351_PMIC_RG_FRC_CSVTH_USBDL_MASK 0x1 +#define MT6351_PMIC_RG_FRC_CSVTH_USBDL_SHIFT 0 +#define MT6351_PMIC_RGS_PCHR_FLAG_OUT_ADDR MT6351_CHR_CON10 +#define MT6351_PMIC_RGS_PCHR_FLAG_OUT_MASK 0xF +#define MT6351_PMIC_RGS_PCHR_FLAG_OUT_SHIFT 0 +#define MT6351_PMIC_RG_PCHR_FLAG_EN_ADDR MT6351_CHR_CON10 +#define MT6351_PMIC_RG_PCHR_FLAG_EN_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_FLAG_EN_SHIFT 4 +#define MT6351_PMIC_RG_OTG_BVALID_EN_ADDR MT6351_CHR_CON10 +#define MT6351_PMIC_RG_OTG_BVALID_EN_MASK 0x1 +#define MT6351_PMIC_RG_OTG_BVALID_EN_SHIFT 5 +#define MT6351_PMIC_RGS_OTG_BVALID_DET_ADDR MT6351_CHR_CON10 +#define MT6351_PMIC_RGS_OTG_BVALID_DET_MASK 0x1 +#define MT6351_PMIC_RGS_OTG_BVALID_DET_SHIFT 6 +#define MT6351_PMIC_RG_PCHR_FLAG_SEL_ADDR MT6351_CHR_CON11 +#define MT6351_PMIC_RG_PCHR_FLAG_SEL_MASK 0x3F +#define MT6351_PMIC_RG_PCHR_FLAG_SEL_SHIFT 0 +#define MT6351_PMIC_RG_PCHR_TESTMODE_ADDR MT6351_CHR_CON12 +#define MT6351_PMIC_RG_PCHR_TESTMODE_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_TESTMODE_SHIFT 0 +#define MT6351_PMIC_RG_CSDAC_TESTMODE_ADDR MT6351_CHR_CON12 +#define MT6351_PMIC_RG_CSDAC_TESTMODE_MASK 0x1 +#define MT6351_PMIC_RG_CSDAC_TESTMODE_SHIFT 1 +#define MT6351_PMIC_RG_PCHR_RST_ADDR MT6351_CHR_CON12 +#define MT6351_PMIC_RG_PCHR_RST_MASK 0x1 +#define MT6351_PMIC_RG_PCHR_RST_SHIFT 2 +#define MT6351_PMIC_RG_PCHR_FT_CTRL_ADDR MT6351_CHR_CON12 +#define MT6351_PMIC_RG_PCHR_FT_CTRL_MASK 0x7 +#define MT6351_PMIC_RG_PCHR_FT_CTRL_SHIFT 4 +#define MT6351_PMIC_RG_CHRWDT_TD_ADDR MT6351_CHR_CON13 +#define MT6351_PMIC_RG_CHRWDT_TD_MASK 0xF +#define MT6351_PMIC_RG_CHRWDT_TD_SHIFT 0 +#define MT6351_PMIC_RG_CHRWDT_EN_ADDR MT6351_CHR_CON13 +#define MT6351_PMIC_RG_CHRWDT_EN_MASK 0x1 +#define MT6351_PMIC_RG_CHRWDT_EN_SHIFT 4 +#define MT6351_PMIC_RG_CHRWDT_WR_ADDR MT6351_CHR_CON13 +#define MT6351_PMIC_RG_CHRWDT_WR_MASK 0x1 +#define MT6351_PMIC_RG_CHRWDT_WR_SHIFT 8 +#define MT6351_PMIC_RG_PCHR_RV_ADDR MT6351_CHR_CON14 +#define MT6351_PMIC_RG_PCHR_RV_MASK 0xFF +#define MT6351_PMIC_RG_PCHR_RV_SHIFT 0 +#define MT6351_PMIC_RG_CHRWDT_INT_EN_ADDR MT6351_CHR_CON15 +#define MT6351_PMIC_RG_CHRWDT_INT_EN_MASK 0x1 +#define MT6351_PMIC_RG_CHRWDT_INT_EN_SHIFT 0 +#define MT6351_PMIC_RG_CHRWDT_FLAG_WR_ADDR MT6351_CHR_CON15 +#define MT6351_PMIC_RG_CHRWDT_FLAG_WR_MASK 0x1 +#define MT6351_PMIC_RG_CHRWDT_FLAG_WR_SHIFT 1 +#define MT6351_PMIC_RGS_CHRWDT_OUT_ADDR MT6351_CHR_CON15 +#define MT6351_PMIC_RGS_CHRWDT_OUT_MASK 0x1 +#define MT6351_PMIC_RGS_CHRWDT_OUT_SHIFT 2 +#define MT6351_PMIC_RG_USBDL_RST_ADDR MT6351_CHR_CON16 +#define MT6351_PMIC_RG_USBDL_RST_MASK 0x1 +#define MT6351_PMIC_RG_USBDL_RST_SHIFT 2 +#define MT6351_PMIC_RG_USBDL_SET_ADDR MT6351_CHR_CON16 +#define MT6351_PMIC_RG_USBDL_SET_MASK 0x1 +#define MT6351_PMIC_RG_USBDL_SET_SHIFT 3 +#define MT6351_PMIC_RG_ADCIN_VSEN_MUX_EN_ADDR MT6351_CHR_CON16 +#define MT6351_PMIC_RG_ADCIN_VSEN_MUX_EN_MASK 0x1 +#define MT6351_PMIC_RG_ADCIN_VSEN_MUX_EN_SHIFT 8 +#define MT6351_PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_ADDR MT6351_CHR_CON16 +#define MT6351_PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_MASK 0x1 +#define MT6351_PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_SHIFT 9 +#define MT6351_PMIC_RG_ADCIN_VBAT_EN_ADDR MT6351_CHR_CON16 +#define MT6351_PMIC_RG_ADCIN_VBAT_EN_MASK 0x1 +#define MT6351_PMIC_RG_ADCIN_VBAT_EN_SHIFT 10 +#define MT6351_PMIC_RG_ADCIN_VSEN_EN_ADDR MT6351_CHR_CON16 +#define MT6351_PMIC_RG_ADCIN_VSEN_EN_MASK 0x1 +#define MT6351_PMIC_RG_ADCIN_VSEN_EN_SHIFT 11 +#define MT6351_PMIC_RG_ADCIN_CHR_EN_ADDR MT6351_CHR_CON16 +#define MT6351_PMIC_RG_ADCIN_CHR_EN_MASK 0x1 +#define MT6351_PMIC_RG_ADCIN_CHR_EN_SHIFT 12 +#define MT6351_PMIC_RG_UVLO_VTHL_ADDR MT6351_CHR_CON17 +#define MT6351_PMIC_RG_UVLO_VTHL_MASK 0x1F +#define MT6351_PMIC_RG_UVLO_VTHL_SHIFT 0 +#define MT6351_PMIC_RG_UVLO_VH_LAT_ADDR MT6351_CHR_CON17 +#define MT6351_PMIC_RG_UVLO_VH_LAT_MASK 0x1 +#define MT6351_PMIC_RG_UVLO_VH_LAT_SHIFT 7 +#define MT6351_PMIC_RG_LBAT_INT_VTH_ADDR MT6351_CHR_CON18 +#define MT6351_PMIC_RG_LBAT_INT_VTH_MASK 0x1F +#define MT6351_PMIC_RG_LBAT_INT_VTH_SHIFT 0 +#define MT6351_PMIC_RG_BGR_RSEL_ADDR MT6351_CHR_CON19 +#define MT6351_PMIC_RG_BGR_RSEL_MASK 0x7 +#define MT6351_PMIC_RG_BGR_RSEL_SHIFT 0 +#define MT6351_PMIC_RG_BGR_UNCHOP_PH_ADDR MT6351_CHR_CON19 +#define MT6351_PMIC_RG_BGR_UNCHOP_PH_MASK 0x1 +#define MT6351_PMIC_RG_BGR_UNCHOP_PH_SHIFT 4 +#define MT6351_PMIC_RG_BGR_UNCHOP_ADDR MT6351_CHR_CON19 +#define MT6351_PMIC_RG_BGR_UNCHOP_MASK 0x1 +#define MT6351_PMIC_RG_BGR_UNCHOP_SHIFT 5 +#define MT6351_PMIC_RG_BC11_BB_CTRL_ADDR MT6351_CHR_CON20 +#define MT6351_PMIC_RG_BC11_BB_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_BC11_BB_CTRL_SHIFT 0 +#define MT6351_PMIC_RG_BC11_RST_ADDR MT6351_CHR_CON20 +#define MT6351_PMIC_RG_BC11_RST_MASK 0x1 +#define MT6351_PMIC_RG_BC11_RST_SHIFT 1 +#define MT6351_PMIC_RG_BC11_VSRC_EN_ADDR MT6351_CHR_CON20 +#define MT6351_PMIC_RG_BC11_VSRC_EN_MASK 0x3 +#define MT6351_PMIC_RG_BC11_VSRC_EN_SHIFT 2 +#define MT6351_PMIC_RGS_BC11_CMP_OUT_ADDR MT6351_CHR_CON20 +#define MT6351_PMIC_RGS_BC11_CMP_OUT_MASK 0x1 +#define MT6351_PMIC_RGS_BC11_CMP_OUT_SHIFT 7 +#define MT6351_PMIC_RG_BC11_VREF_VTH_ADDR MT6351_CHR_CON21 +#define MT6351_PMIC_RG_BC11_VREF_VTH_MASK 0x3 +#define MT6351_PMIC_RG_BC11_VREF_VTH_SHIFT 0 +#define MT6351_PMIC_RG_BC11_CMP_EN_ADDR MT6351_CHR_CON21 +#define MT6351_PMIC_RG_BC11_CMP_EN_MASK 0x3 +#define MT6351_PMIC_RG_BC11_CMP_EN_SHIFT 2 +#define MT6351_PMIC_RG_BC11_IPD_EN_ADDR MT6351_CHR_CON21 +#define MT6351_PMIC_RG_BC11_IPD_EN_MASK 0x3 +#define MT6351_PMIC_RG_BC11_IPD_EN_SHIFT 4 +#define MT6351_PMIC_RG_BC11_IPU_EN_ADDR MT6351_CHR_CON21 +#define MT6351_PMIC_RG_BC11_IPU_EN_MASK 0x3 +#define MT6351_PMIC_RG_BC11_IPU_EN_SHIFT 6 +#define MT6351_PMIC_RG_BC11_BIAS_EN_ADDR MT6351_CHR_CON21 +#define MT6351_PMIC_RG_BC11_BIAS_EN_MASK 0x1 +#define MT6351_PMIC_RG_BC11_BIAS_EN_SHIFT 8 +#define MT6351_PMIC_RG_CSDAC_STP_INC_ADDR MT6351_CHR_CON22 +#define MT6351_PMIC_RG_CSDAC_STP_INC_MASK 0x7 +#define MT6351_PMIC_RG_CSDAC_STP_INC_SHIFT 0 +#define MT6351_PMIC_RG_CSDAC_STP_DEC_ADDR MT6351_CHR_CON22 +#define MT6351_PMIC_RG_CSDAC_STP_DEC_MASK 0x7 +#define MT6351_PMIC_RG_CSDAC_STP_DEC_SHIFT 4 +#define MT6351_PMIC_RG_CSDAC_DLY_ADDR MT6351_CHR_CON23 +#define MT6351_PMIC_RG_CSDAC_DLY_MASK 0x7 +#define MT6351_PMIC_RG_CSDAC_DLY_SHIFT 0 +#define MT6351_PMIC_RG_CSDAC_STP_ADDR MT6351_CHR_CON23 +#define MT6351_PMIC_RG_CSDAC_STP_MASK 0x7 +#define MT6351_PMIC_RG_CSDAC_STP_SHIFT 4 +#define MT6351_PMIC_RG_LOW_ICH_DB_ADDR MT6351_CHR_CON24 +#define MT6351_PMIC_RG_LOW_ICH_DB_MASK 0x3F +#define MT6351_PMIC_RG_LOW_ICH_DB_SHIFT 0 +#define MT6351_PMIC_RG_CHRIND_ON_ADDR MT6351_CHR_CON24 +#define MT6351_PMIC_RG_CHRIND_ON_MASK 0x1 +#define MT6351_PMIC_RG_CHRIND_ON_SHIFT 6 +#define MT6351_PMIC_RG_CHRIND_DIMMING_ADDR MT6351_CHR_CON24 +#define MT6351_PMIC_RG_CHRIND_DIMMING_MASK 0x1 +#define MT6351_PMIC_RG_CHRIND_DIMMING_SHIFT 7 +#define MT6351_PMIC_RG_CV_MODE_ADDR MT6351_CHR_CON25 +#define MT6351_PMIC_RG_CV_MODE_MASK 0x1 +#define MT6351_PMIC_RG_CV_MODE_SHIFT 0 +#define MT6351_PMIC_RG_VCDT_MODE_ADDR MT6351_CHR_CON25 +#define MT6351_PMIC_RG_VCDT_MODE_MASK 0x1 +#define MT6351_PMIC_RG_VCDT_MODE_SHIFT 1 +#define MT6351_PMIC_RG_CSDAC_MODE_ADDR MT6351_CHR_CON25 +#define MT6351_PMIC_RG_CSDAC_MODE_MASK 0x1 +#define MT6351_PMIC_RG_CSDAC_MODE_SHIFT 2 +#define MT6351_PMIC_RG_TRACKING_EN_ADDR MT6351_CHR_CON25 +#define MT6351_PMIC_RG_TRACKING_EN_MASK 0x1 +#define MT6351_PMIC_RG_TRACKING_EN_SHIFT 4 +#define MT6351_PMIC_RG_HWCV_EN_ADDR MT6351_CHR_CON25 +#define MT6351_PMIC_RG_HWCV_EN_MASK 0x1 +#define MT6351_PMIC_RG_HWCV_EN_SHIFT 6 +#define MT6351_PMIC_RG_ULC_DET_EN_ADDR MT6351_CHR_CON25 +#define MT6351_PMIC_RG_ULC_DET_EN_MASK 0x1 +#define MT6351_PMIC_RG_ULC_DET_EN_SHIFT 7 +#define MT6351_PMIC_RG_BGR_TRIM_EN_ADDR MT6351_CHR_CON26 +#define MT6351_PMIC_RG_BGR_TRIM_EN_MASK 0x1 +#define MT6351_PMIC_RG_BGR_TRIM_EN_SHIFT 0 +#define MT6351_PMIC_RG_ICHRG_TRIM_ADDR MT6351_CHR_CON26 +#define MT6351_PMIC_RG_ICHRG_TRIM_MASK 0xF +#define MT6351_PMIC_RG_ICHRG_TRIM_SHIFT 4 +#define MT6351_PMIC_RG_BGR_TRIM_ADDR MT6351_CHR_CON27 +#define MT6351_PMIC_RG_BGR_TRIM_MASK 0x1F +#define MT6351_PMIC_RG_BGR_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_OVP_TRIM_ADDR MT6351_CHR_CON28 +#define MT6351_PMIC_RG_OVP_TRIM_MASK 0xF +#define MT6351_PMIC_RG_OVP_TRIM_SHIFT 0 +#define MT6351_PMIC_RG_CHR_OSC_TRIM_ADDR MT6351_CHR_CON29 +#define MT6351_PMIC_RG_CHR_OSC_TRIM_MASK 0x1F +#define MT6351_PMIC_RG_CHR_OSC_TRIM_SHIFT 0 +#define MT6351_PMIC_DA_QI_BGR_EXT_BUF_EN_ADDR MT6351_CHR_CON29 +#define MT6351_PMIC_DA_QI_BGR_EXT_BUF_EN_MASK 0x1 +#define MT6351_PMIC_DA_QI_BGR_EXT_BUF_EN_SHIFT 5 +#define MT6351_PMIC_RG_BGR_TEST_EN_ADDR MT6351_CHR_CON29 +#define MT6351_PMIC_RG_BGR_TEST_EN_MASK 0x1 +#define MT6351_PMIC_RG_BGR_TEST_EN_SHIFT 6 +#define MT6351_PMIC_RG_BGR_TEST_RSTB_ADDR MT6351_CHR_CON29 +#define MT6351_PMIC_RG_BGR_TEST_RSTB_MASK 0x1 +#define MT6351_PMIC_RG_BGR_TEST_RSTB_SHIFT 7 +#define MT6351_PMIC_RG_DAC_USBDL_MAX_ADDR MT6351_CHR_CON30 +#define MT6351_PMIC_RG_DAC_USBDL_MAX_MASK 0x3FF +#define MT6351_PMIC_RG_DAC_USBDL_MAX_SHIFT 0 +#define MT6351_PMIC_RG_CM_VDEC_TRIG_ADDR MT6351_CHR_CON31 +#define MT6351_PMIC_RG_CM_VDEC_TRIG_MASK 0x1 +#define MT6351_PMIC_RG_CM_VDEC_TRIG_SHIFT 0 +#define MT6351_PMIC_PCHR_CM_VDEC_STATUS_ADDR MT6351_CHR_CON31 +#define MT6351_PMIC_PCHR_CM_VDEC_STATUS_MASK 0x1 +#define MT6351_PMIC_PCHR_CM_VDEC_STATUS_SHIFT 4 +#define MT6351_PMIC_RG_CM_VINC_TRIG_ADDR MT6351_CHR_CON32 +#define MT6351_PMIC_RG_CM_VINC_TRIG_MASK 0x1 +#define MT6351_PMIC_RG_CM_VINC_TRIG_SHIFT 0 +#define MT6351_PMIC_PCHR_CM_VINC_STATUS_ADDR MT6351_CHR_CON32 +#define MT6351_PMIC_PCHR_CM_VINC_STATUS_MASK 0x1 +#define MT6351_PMIC_PCHR_CM_VINC_STATUS_SHIFT 4 +#define MT6351_PMIC_RG_CM_VDEC_HPRD1_ADDR MT6351_CHR_CON33 +#define MT6351_PMIC_RG_CM_VDEC_HPRD1_MASK 0x3F +#define MT6351_PMIC_RG_CM_VDEC_HPRD1_SHIFT 0 +#define MT6351_PMIC_RG_CM_VDEC_HPRD2_ADDR MT6351_CHR_CON33 +#define MT6351_PMIC_RG_CM_VDEC_HPRD2_MASK 0x3F +#define MT6351_PMIC_RG_CM_VDEC_HPRD2_SHIFT 8 +#define MT6351_PMIC_RG_CM_VDEC_HPRD3_ADDR MT6351_CHR_CON34 +#define MT6351_PMIC_RG_CM_VDEC_HPRD3_MASK 0x3F +#define MT6351_PMIC_RG_CM_VDEC_HPRD3_SHIFT 0 +#define MT6351_PMIC_RG_CM_VDEC_HPRD4_ADDR MT6351_CHR_CON34 +#define MT6351_PMIC_RG_CM_VDEC_HPRD4_MASK 0x3F +#define MT6351_PMIC_RG_CM_VDEC_HPRD4_SHIFT 8 +#define MT6351_PMIC_RG_CM_VDEC_HPRD5_ADDR MT6351_CHR_CON35 +#define MT6351_PMIC_RG_CM_VDEC_HPRD5_MASK 0x3F +#define MT6351_PMIC_RG_CM_VDEC_HPRD5_SHIFT 0 +#define MT6351_PMIC_RG_CM_VDEC_HPRD6_ADDR MT6351_CHR_CON35 +#define MT6351_PMIC_RG_CM_VDEC_HPRD6_MASK 0x3F +#define MT6351_PMIC_RG_CM_VDEC_HPRD6_SHIFT 8 +#define MT6351_PMIC_RG_CM_VINC_HPRD1_ADDR MT6351_CHR_CON36 +#define MT6351_PMIC_RG_CM_VINC_HPRD1_MASK 0x3F +#define MT6351_PMIC_RG_CM_VINC_HPRD1_SHIFT 0 +#define MT6351_PMIC_RG_CM_VINC_HPRD2_ADDR MT6351_CHR_CON36 +#define MT6351_PMIC_RG_CM_VINC_HPRD2_MASK 0x3F +#define MT6351_PMIC_RG_CM_VINC_HPRD2_SHIFT 8 +#define MT6351_PMIC_RG_CM_VINC_HPRD3_ADDR MT6351_CHR_CON37 +#define MT6351_PMIC_RG_CM_VINC_HPRD3_MASK 0x3F +#define MT6351_PMIC_RG_CM_VINC_HPRD3_SHIFT 0 +#define MT6351_PMIC_RG_CM_VINC_HPRD4_ADDR MT6351_CHR_CON37 +#define MT6351_PMIC_RG_CM_VINC_HPRD4_MASK 0x3F +#define MT6351_PMIC_RG_CM_VINC_HPRD4_SHIFT 8 +#define MT6351_PMIC_RG_CM_VINC_HPRD5_ADDR MT6351_CHR_CON38 +#define MT6351_PMIC_RG_CM_VINC_HPRD5_MASK 0x3F +#define MT6351_PMIC_RG_CM_VINC_HPRD5_SHIFT 0 +#define MT6351_PMIC_RG_CM_VINC_HPRD6_ADDR MT6351_CHR_CON38 +#define MT6351_PMIC_RG_CM_VINC_HPRD6_MASK 0x3F +#define MT6351_PMIC_RG_CM_VINC_HPRD6_SHIFT 8 +#define MT6351_PMIC_RG_CM_LPRD_ADDR MT6351_CHR_CON39 +#define MT6351_PMIC_RG_CM_LPRD_MASK 0x3F +#define MT6351_PMIC_RG_CM_LPRD_SHIFT 0 +#define MT6351_PMIC_RG_CM_CS_VTHL_ADDR MT6351_CHR_CON40 +#define MT6351_PMIC_RG_CM_CS_VTHL_MASK 0xF +#define MT6351_PMIC_RG_CM_CS_VTHL_SHIFT 0 +#define MT6351_PMIC_RG_CM_CS_VTHH_ADDR MT6351_CHR_CON40 +#define MT6351_PMIC_RG_CM_CS_VTHH_MASK 0xF +#define MT6351_PMIC_RG_CM_CS_VTHH_SHIFT 4 +#define MT6351_PMIC_RG_PCHR_RSV_ADDR MT6351_CHR_CON41 +#define MT6351_PMIC_RG_PCHR_RSV_MASK 0xFF +#define MT6351_PMIC_RG_PCHR_RSV_SHIFT 0 +#define MT6351_PMIC_RG_ENVTEM_D_ADDR MT6351_CHR_CON42 +#define MT6351_PMIC_RG_ENVTEM_D_MASK 0x1 +#define MT6351_PMIC_RG_ENVTEM_D_SHIFT 0 +#define MT6351_PMIC_RG_ENVTEM_EN_ADDR MT6351_CHR_CON42 +#define MT6351_PMIC_RG_ENVTEM_EN_MASK 0x1 +#define MT6351_PMIC_RG_ENVTEM_EN_SHIFT 1 +#define MT6351_PMIC_RGS_BATON_HV_ADDR MT6351_BATON_CON0 +#define MT6351_PMIC_RGS_BATON_HV_MASK 0x1 +#define MT6351_PMIC_RGS_BATON_HV_SHIFT 6 +#define MT6351_PMIC_RG_HW_VTH_CTRL_ADDR MT6351_BATON_CON0 +#define MT6351_PMIC_RG_HW_VTH_CTRL_MASK 0x1 +#define MT6351_PMIC_RG_HW_VTH_CTRL_SHIFT 11 +#define MT6351_PMIC_RG_HW_VTH2_ADDR MT6351_BATON_CON0 +#define MT6351_PMIC_RG_HW_VTH2_MASK 0x3 +#define MT6351_PMIC_RG_HW_VTH2_SHIFT 12 +#define MT6351_PMIC_RG_HW_VTH1_ADDR MT6351_BATON_CON0 +#define MT6351_PMIC_RG_HW_VTH1_MASK 0x3 +#define MT6351_PMIC_RG_HW_VTH1_SHIFT 14 +#define MT6351_PMIC_RG_CM_VDEC_INT_EN_ADDR MT6351_CHR_CON43 +#define MT6351_PMIC_RG_CM_VDEC_INT_EN_MASK 0x1 +#define MT6351_PMIC_RG_CM_VDEC_INT_EN_SHIFT 9 +#define MT6351_PMIC_RG_CM_VINC_INT_EN_ADDR MT6351_CHR_CON43 +#define MT6351_PMIC_RG_CM_VINC_INT_EN_MASK 0x1 +#define MT6351_PMIC_RG_CM_VINC_INT_EN_SHIFT 11 +#define MT6351_PMIC_RG_QI_BATON_LT_EN_ADDR MT6351_CHR_CON44 +#define MT6351_PMIC_RG_QI_BATON_LT_EN_MASK 0x1 +#define MT6351_PMIC_RG_QI_BATON_LT_EN_SHIFT 0 +#define MT6351_PMIC_RGS_BATON_UNDET_ADDR MT6351_CHR_CON44 +#define MT6351_PMIC_RGS_BATON_UNDET_MASK 0x1 +#define MT6351_PMIC_RGS_BATON_UNDET_SHIFT 1 +#define MT6351_PMIC_RG_JW_CS_VTH_ADDR MT6351_CHR_CON45 +#define MT6351_PMIC_RG_JW_CS_VTH_MASK 0xF +#define MT6351_PMIC_RG_JW_CS_VTH_SHIFT 0 +#define MT6351_PMIC_RG_JW_CV_VTH_ADDR MT6351_CHR_CON45 +#define MT6351_PMIC_RG_JW_CV_VTH_MASK 0x3F +#define MT6351_PMIC_RG_JW_CV_VTH_SHIFT 8 +#define MT6351_PMIC_RG_JC_CS_VTH_ADDR MT6351_CHR_CON46 +#define MT6351_PMIC_RG_JC_CS_VTH_MASK 0xF +#define MT6351_PMIC_RG_JC_CS_VTH_SHIFT 0 +#define MT6351_PMIC_RG_JC_CV_VTH_ADDR MT6351_CHR_CON46 +#define MT6351_PMIC_RG_JC_CV_VTH_MASK 0x3F +#define MT6351_PMIC_RG_JC_CV_VTH_SHIFT 8 +#define MT6351_PMIC_RG_BC11_ACA_EN_ADDR MT6351_CHR_CON47 +#define MT6351_PMIC_RG_BC11_ACA_EN_MASK 0x1 +#define MT6351_PMIC_RG_BC11_ACA_EN_SHIFT 0 +#define MT6351_PMIC_RG_JEITA_EN_ADDR MT6351_CHR_CON47 +#define MT6351_PMIC_RG_JEITA_EN_MASK 0x1 +#define MT6351_PMIC_RG_JEITA_EN_SHIFT 1 +#define MT6351_PMIC_RG_VCDT_TRIM_ADDR MT6351_CHR_CON48 +#define MT6351_PMIC_RG_VCDT_TRIM_MASK 0xF +#define MT6351_PMIC_RG_VCDT_TRIM_SHIFT 0 +#define MT6351_PMIC_RGS_BC11_ID_FLOAT_ADDR MT6351_CHR_CON48 +#define MT6351_PMIC_RGS_BC11_ID_FLOAT_MASK 0x1 +#define MT6351_PMIC_RGS_BC11_ID_FLOAT_SHIFT 4 +#define MT6351_PMIC_RGS_BC11_ID_A_ADDR MT6351_CHR_CON48 +#define MT6351_PMIC_RGS_BC11_ID_A_MASK 0x1 +#define MT6351_PMIC_RGS_BC11_ID_A_SHIFT 5 +#define MT6351_PMIC_RGS_BC11_ID_B_ADDR MT6351_CHR_CON48 +#define MT6351_PMIC_RGS_BC11_ID_B_MASK 0x1 +#define MT6351_PMIC_RGS_BC11_ID_B_SHIFT 6 +#define MT6351_PMIC_RGS_BC11_ID_C_ADDR MT6351_CHR_CON48 +#define MT6351_PMIC_RGS_BC11_ID_C_MASK 0x1 +#define MT6351_PMIC_RGS_BC11_ID_C_SHIFT 7 +#define MT6351_PMIC_RGS_BC11_ID_GND_ADDR MT6351_CHR_CON48 +#define MT6351_PMIC_RGS_BC11_ID_GND_MASK 0x1 +#define MT6351_PMIC_RGS_BC11_ID_GND_SHIFT 8 +#define MT6351_PMIC_RGS_BC11_ACA_OTG_DET_ADDR MT6351_CHR_CON48 +#define MT6351_PMIC_RGS_BC11_ACA_OTG_DET_MASK 0x1 +#define MT6351_PMIC_RGS_BC11_ACA_OTG_DET_SHIFT 9 +#define MT6351_PMIC_RG_INDICATOR_TRIM_ADDR MT6351_CHR_CON48 +#define MT6351_PMIC_RG_INDICATOR_TRIM_MASK 0x7 +#define MT6351_PMIC_RG_INDICATOR_TRIM_SHIFT 10 +#define MT6351_PMIC_EOSC_CALI_START_ADDR MT6351_EOSC_CALI_CON0 +#define MT6351_PMIC_EOSC_CALI_START_MASK 0x1 +#define MT6351_PMIC_EOSC_CALI_START_SHIFT 0 +#define MT6351_PMIC_EOSC_CALI_TD_ADDR MT6351_EOSC_CALI_CON0 +#define MT6351_PMIC_EOSC_CALI_TD_MASK 0x7 +#define MT6351_PMIC_EOSC_CALI_TD_SHIFT 5 +#define MT6351_PMIC_EOSC_CALI_TEST_ADDR MT6351_EOSC_CALI_CON0 +#define MT6351_PMIC_EOSC_CALI_TEST_MASK 0xF +#define MT6351_PMIC_EOSC_CALI_TEST_SHIFT 9 +#define MT6351_PMIC_EOSC_CALI_DCXO_RDY_TD_ADDR MT6351_EOSC_CALI_CON1 +#define MT6351_PMIC_EOSC_CALI_DCXO_RDY_TD_MASK 0x7 +#define MT6351_PMIC_EOSC_CALI_DCXO_RDY_TD_SHIFT 0 +#define MT6351_PMIC_FRC_VTCXO0_ON_ADDR MT6351_EOSC_CALI_CON1 +#define MT6351_PMIC_FRC_VTCXO0_ON_MASK 0x1 +#define MT6351_PMIC_FRC_VTCXO0_ON_SHIFT 8 +#define MT6351_PMIC_EOSC_CALI_RSV_ADDR MT6351_EOSC_CALI_CON1 +#define MT6351_PMIC_EOSC_CALI_RSV_MASK 0xF +#define MT6351_PMIC_EOSC_CALI_RSV_SHIFT 11 +#define MT6351_PMIC_VRTC_PWM_MODE_ADDR MT6351_VRTC_PWM_CON0 +#define MT6351_PMIC_VRTC_PWM_MODE_MASK 0x1 +#define MT6351_PMIC_VRTC_PWM_MODE_SHIFT 0 +#define MT6351_PMIC_VRTC_PWM_RSV_ADDR MT6351_VRTC_PWM_CON0 +#define MT6351_PMIC_VRTC_PWM_RSV_MASK 0x7 +#define MT6351_PMIC_VRTC_PWM_RSV_SHIFT 1 +#define MT6351_PMIC_VRTC_PWM_L_DUTY_ADDR MT6351_VRTC_PWM_CON0 +#define MT6351_PMIC_VRTC_PWM_L_DUTY_MASK 0xF +#define MT6351_PMIC_VRTC_PWM_L_DUTY_SHIFT 4 +#define MT6351_PMIC_VRTC_PWM_H_DUTY_ADDR MT6351_VRTC_PWM_CON0 +#define MT6351_PMIC_VRTC_PWM_H_DUTY_MASK 0xF +#define MT6351_PMIC_VRTC_PWM_H_DUTY_SHIFT 8 +#define MT6351_PMIC_VRTC_CAP_SEL_ADDR MT6351_VRTC_PWM_CON0 +#define MT6351_PMIC_VRTC_CAP_SEL_MASK 0x1 +#define MT6351_PMIC_VRTC_CAP_SEL_SHIFT 12 + +typedef enum { + MT6351_PMIC_THR_DET_DIS, + MT6351_PMIC_THR_TEST, + MT6351_PMIC_THR_HWPDN_EN, + MT6351_PMIC_STRUP_THERMAL_DEB_SEL, + MT6351_PMIC_USBDL, + MT6351_PMIC_PMU_THERMAL_DEB, + MT6351_PMIC_PMU_THR_DEB, + MT6351_PMIC_PMU_THR_STATUS, + MT6351_PMIC_STRUP_THER_DEB_RMAX, + MT6351_PMIC_STRUP_THER_DEB_FMAX, + MT6351_PMIC_DDUVLO_DEB_EN, + MT6351_PMIC_PWRBB_DEB_EN, + MT6351_PMIC_STRUP_OSC_EN, + MT6351_PMIC_STRUP_OSC_EN_SEL, + MT6351_PMIC_STRUP_FT_CTRL, + MT6351_PMIC_STRUP_PWRON_FORCE, + MT6351_PMIC_BIAS_GEN_EN_FORCE, + MT6351_PMIC_STRUP_PWRON, + MT6351_PMIC_STRUP_PWRON_SEL, + MT6351_PMIC_BIAS_GEN_EN, + MT6351_PMIC_BIAS_GEN_EN_SEL, + MT6351_PMIC_RTC_XOSC32_ENB_SW, + MT6351_PMIC_RTC_XOSC32_ENB_SEL, + MT6351_PMIC_STRUP_DIG_IO_PG_FORCE, + MT6351_PMIC_RG_STRUP_VUSB33_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VGPU_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VDRAM_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VA10_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VEMC_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VS2_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VMODEM_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VMD1_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VCORE_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VA18_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VS1_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VTCXO24_PG_ENB, + MT6351_PMIC_RG_STRUP_VUSB33_PG_ENB, + MT6351_PMIC_RG_STRUP_VGPU_PG_ENB, + MT6351_PMIC_RG_STRUP_VDRAM_PG_ENB, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_ENB, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_ENB, + MT6351_PMIC_RG_STRUP_VIO28_PG_ENB, + MT6351_PMIC_RG_STRUP_VA10_PG_ENB, + MT6351_PMIC_RG_STRUP_VEMC_PG_ENB, + MT6351_PMIC_RG_STRUP_VIO18_PG_ENB, + MT6351_PMIC_RG_STRUP_VS2_PG_ENB, + MT6351_PMIC_RG_STRUP_VMODEM_PG_ENB, + MT6351_PMIC_RG_STRUP_VMD1_PG_ENB, + MT6351_PMIC_RG_STRUP_VCORE_PG_ENB, + MT6351_PMIC_RG_STRUP_VA18_PG_ENB, + MT6351_PMIC_RG_STRUP_VS1_PG_ENB, + MT6351_PMIC_RG_STRUP_VXO22_PG_ENB, + MT6351_PMIC_RG_STRUP_VGPU_OC_H2L_EN, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN, + MT6351_PMIC_RG_STRUP_VS2_OC_H2L_EN, + MT6351_PMIC_RG_STRUP_VMODEM_OC_H2L_EN, + MT6351_PMIC_RG_STRUP_VMD1_OC_H2L_EN, + MT6351_PMIC_RG_STRUP_VCORE_OC_H2L_EN, + MT6351_PMIC_RG_STRUP_VS1_OC_H2L_EN, + MT6351_PMIC_RG_STRUP_VGPU_OC_ENB, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_ENB, + MT6351_PMIC_RG_STRUP_VS2_OC_ENB, + MT6351_PMIC_RG_STRUP_VMODEM_OC_ENB, + MT6351_PMIC_RG_STRUP_VMD1_OC_ENB, + MT6351_PMIC_RG_STRUP_VCORE_OC_ENB, + MT6351_PMIC_RG_STRUP_VS1_OC_ENB, + MT6351_PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VS2_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VS1_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VA10_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VS2_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VA18_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VS1_PG_DEB_BYPASS, + MT6351_PMIC_CLR_JUST_RST, + MT6351_PMIC_UVLO_L2H_DEB_EN, + MT6351_PMIC_JUST_PWRKEY_RST, + MT6351_PMIC_DA_QI_OSC_EN, + MT6351_PMIC_STRUP_EXT_PMIC_EN, + MT6351_PMIC_STRUP_EXT_PMIC_SEL, + MT6351_PMIC_STRUP_CON8_RSV0, + MT6351_PMIC_DA_QI_EXT_PMIC_EN, + MT6351_PMIC_STRUP_AUXADC_START_SW, + MT6351_PMIC_STRUP_AUXADC_RSTB_SW, + MT6351_PMIC_STRUP_AUXADC_START_SEL, + MT6351_PMIC_STRUP_AUXADC_RSTB_SEL, + MT6351_PMIC_STRUP_PWROFF_SEQ_EN, + MT6351_PMIC_STRUP_PWROFF_PREOFF_EN, + MT6351_PMIC_STRUP_PP_EN, + MT6351_PMIC_STRUP_PP_EN_SEL, + MT6351_PMIC_STRUP_DIG0_RSV0, + MT6351_PMIC_STRUP_DIG1_RSV0, + MT6351_PMIC_RG_RSV_SWREG, + MT6351_PMIC_STRUP_PP_EN_PWROFF_CNT, + MT6351_PMIC_STRUP_UVLO_U1U2_SEL, + MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL, + MT6351_PMIC_STRUP_AUXADC_RPCNT_MAX, + MT6351_PMIC_RG_STRUP_THR_OVER_110_CLR, + MT6351_PMIC_RG_STRUP_THR_110_CLR, + MT6351_PMIC_RG_STRUP_THR_125_CLR, + MT6351_PMIC_RG_STRUP_THR_CLR, + MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_EN, + MT6351_PMIC_RG_STRUP_THR_110_IRQ_EN, + MT6351_PMIC_RG_STRUP_THR_125_IRQ_EN, + MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS, + MT6351_PMIC_RG_STRUP_THR_110_IRQ_STATUS, + MT6351_PMIC_RG_STRUP_THR_125_IRQ_STATUS, + MT6351_PMIC_STRUP_PG_STATUS_CLR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_SEL, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_TD, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_EN, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL, + MT6351_PMIC_RG_STRUP_ENVTEM, + MT6351_PMIC_RG_STRUP_ENVTEM_CTRL, + MT6351_PMIC_RG_STRUP_PWRKEY_COUNT_RESET, + MT6351_PMIC_RGS_ANA_CHIP_ID, + MT6351_PMIC_RG_PP_EN_DRVSEL, + MT6351_PMIC_RG_FCHR_PU_EN, + MT6351_PMIC_RG_PMU_RSV, + MT6351_PMIC_RG_FCHR_KEYDET_EN, + MT6351_PMIC_RG_EN_DRVSEL, + MT6351_PMIC_RG_RST_DRVSEL, + MT6351_PMIC_RG_STRUP_IREF_TRIM, + MT6351_PMIC_RG_VREF_BG, + MT6351_PMIC_RG_THR_TMODE, + MT6351_PMIC_RG_STRUP_THR_SEL, + MT6351_PMIC_RG_THRDET_SEL, + MT6351_PMIC_HWCID, + MT6351_PMIC_SWCID, + MT6351_PMIC_RG_SRCLKEN_IN0_EN, + MT6351_PMIC_RG_SRCLKEN_IN1_EN, + MT6351_PMIC_RG_OSC_SEL, + MT6351_PMIC_RG_SRCLKEN_IN2_EN, + MT6351_PMIC_RG_SRCLKEN_IN0_HW_MODE, + MT6351_PMIC_RG_SRCLKEN_IN1_HW_MODE, + MT6351_PMIC_RG_OSC_SEL_HW_MODE, + MT6351_PMIC_RG_SRCLKEN_IN_SYNC_EN, + MT6351_PMIC_RG_OSC_EN_AUTO_OFF, + MT6351_PMIC_TEST_OUT, + MT6351_PMIC_RG_MON_FLAG_SEL, + MT6351_PMIC_RG_MON_GRP_SEL, + MT6351_PMIC_RG_NANDTREE_MODE, + MT6351_PMIC_RG_TEST_AUXADC, + MT6351_PMIC_RG_EFUSE_MODE, + MT6351_PMIC_RG_TEST_STRUP, + MT6351_PMIC_TESTMODE_SW, + MT6351_PMIC_EN_STATUS_VLDO28, + MT6351_PMIC_EN_STATUS_VIO28, + MT6351_PMIC_EN_STATUS_VMCH, + MT6351_PMIC_EN_STATUS_VMC, + MT6351_PMIC_EN_STATUS_VEMC, + MT6351_PMIC_EN_STATUS_VSIM2, + MT6351_PMIC_EN_STATUS_VSIM1, + MT6351_PMIC_EN_STATUS_VEFUSE, + MT6351_PMIC_EN_STATUS_VUSB33, + MT6351_PMIC_EN_STATUS_VCN33, + MT6351_PMIC_EN_STATUS_VCAMA, + MT6351_PMIC_EN_STATUS_VCN28, + MT6351_PMIC_EN_STATUS_VTCXO24, + MT6351_PMIC_EN_STATUS_VTCXO28, + MT6351_PMIC_EN_STATUS_VA18, + MT6351_PMIC_EN_STATUS_VRTC, + MT6351_PMIC_EN_STATUS_VBIF28, + MT6351_PMIC_EN_STATUS_VGP3, + MT6351_PMIC_EN_STATUS_VMIPI, + MT6351_PMIC_EN_STATUS_VDRAM, + MT6351_PMIC_EN_STATUS_VA10, + MT6351_PMIC_EN_STATUS_VRF12, + MT6351_PMIC_EN_STATUS_VXO22, + MT6351_PMIC_EN_STATUS_VSRAM_PROC, + MT6351_PMIC_EN_STATUS_VCAMIO, + MT6351_PMIC_EN_STATUS_VCN18, + MT6351_PMIC_EN_STATUS_VIO18, + MT6351_PMIC_EN_STATUS_VRF18, + MT6351_PMIC_EN_STATUS_VCAMD, + MT6351_PMIC_EN_STATUS_VIBR, + MT6351_PMIC_OC_STATUS_VIBR, + MT6351_PMIC_OC_STATUS_VLDO28, + MT6351_PMIC_OC_STATUS_VIO28, + MT6351_PMIC_OC_STATUS_VMC, + MT6351_PMIC_OC_STATUS_VMCH, + MT6351_PMIC_OC_STATUS_VEMC, + MT6351_PMIC_OC_STATUS_VSIM2, + MT6351_PMIC_OC_STATUS_VSIM1, + MT6351_PMIC_OC_STATUS_VEFUSE, + MT6351_PMIC_OC_STATUS_VUSB33, + MT6351_PMIC_OC_STATUS_VCN33, + MT6351_PMIC_OC_STATUS_VCAMA, + MT6351_PMIC_OC_STATUS_VCN28, + MT6351_PMIC_OC_STATUS_VTCXO24, + MT6351_PMIC_OC_STATUS_VTCXO28, + MT6351_PMIC_OC_STATUS_VA18, + MT6351_PMIC_OC_STATUS_VBIF28, + MT6351_PMIC_OC_STATUS_VGP3, + MT6351_PMIC_OC_STATUS_VMIPI, + MT6351_PMIC_OC_STATUS_VDRAM, + MT6351_PMIC_OC_STATUS_VA10, + MT6351_PMIC_OC_STATUS_VRF12, + MT6351_PMIC_OC_STATUS_VXO22, + MT6351_PMIC_OC_STATUS_VSRAM_PROC, + MT6351_PMIC_OC_STATUS_VCAMIO, + MT6351_PMIC_OC_STATUS_VCN18, + MT6351_PMIC_OC_STATUS_VIO18, + MT6351_PMIC_OC_STATUS_VRF18, + MT6351_PMIC_OC_STATUS_VCAMD, + MT6351_PMIC_VA18_PG_DEB, + MT6351_PMIC_VCORE_PG_DEB, + MT6351_PMIC_VMD1_PG_DEB, + MT6351_PMIC_VMODEM_PG_DEB, + MT6351_PMIC_VS2_PG_DEB, + MT6351_PMIC_VIO18_PG_DEB, + MT6351_PMIC_VEMC_PG_DEB, + MT6351_PMIC_VA10_PG_DEB, + MT6351_PMIC_VIO28_PG_DEB, + MT6351_PMIC_VSRAM_MD_PG_DEB, + MT6351_PMIC_VSRAM_PROC_PG_DEB, + MT6351_PMIC_VDRAM_PG_DEB, + MT6351_PMIC_VGPU_PG_DEB, + MT6351_PMIC_VUSB33_PG_DEB, + MT6351_PMIC_VXO22_PG_DEB, + MT6351_PMIC_VTCXO24_PG_DEB, + MT6351_PMIC_VS1_PG_DEB, + MT6351_PMIC_STRUP_VA18_PG_STATUS, + MT6351_PMIC_STRUP_VCORE_PG_STATUS, + MT6351_PMIC_STRUP_VMD1_PG_STATUS, + MT6351_PMIC_STRUP_VMODEM_PG_STATUS, + MT6351_PMIC_STRUP_VS2_PG_STATUS, + MT6351_PMIC_STRUP_VIO18_PG_STATUS, + MT6351_PMIC_STRUP_VEMC_PG_STATUS, + MT6351_PMIC_STRUP_VA10_PG_STATUS, + MT6351_PMIC_STRUP_VIO28_PG_STATUS, + MT6351_PMIC_STRUP_VSRAM_MD_PG_STATUS, + MT6351_PMIC_STRUP_VSRAM_PROC_PG_STATUS, + MT6351_PMIC_STRUP_VDRAM_PG_STATUS, + MT6351_PMIC_STRUP_VGPU_PG_STATUS, + MT6351_PMIC_STRUP_VUSB33_PG_STATUS, + MT6351_PMIC_STRUP_VXO22_PG_STATUS, + MT6351_PMIC_STRUP_VTCXO24_PG_STATUS, + MT6351_PMIC_STRUP_VS1_PG_STATUS, + MT6351_PMIC_THERMAL_BACK110, + MT6351_PMIC_THERMAL_OVER110, + MT6351_PMIC_THERMAL_OVER125, + MT6351_PMIC_STRUP_THERMAL_STATUS, + MT6351_PMIC_PMU_TEST_MODE_SCAN, + MT6351_PMIC_PWRKEY_DEB, + MT6351_PMIC_HOMEKEY_DEB, + MT6351_PMIC_RTC_XTAL_DET_DONE, + MT6351_PMIC_XOSC32_ENB_DET, + MT6351_PMIC_RTC_XTAL_DET_RSV, + MT6351_PMIC_RG_PMU_TDSEL, + MT6351_PMIC_RG_SPI_TDSEL, + MT6351_PMIC_RG_AUD_TDSEL, + MT6351_PMIC_RG_E32CAL_TDSEL, + MT6351_PMIC_RG_PMU_RDSEL, + MT6351_PMIC_RG_SPI_RDSEL, + MT6351_PMIC_RG_AUD_RDSEL, + MT6351_PMIC_RG_E32CAL_RDSEL, + MT6351_PMIC_RG_SMT_WDTRSTB_IN, + MT6351_PMIC_RG_SMT_HOMEKEY, + MT6351_PMIC_RG_SMT_SRCLKEN_IN0, + MT6351_PMIC_RG_SMT_SRCLKEN_IN1, + MT6351_PMIC_RG_SMT_RTC_32K1V8_0, + MT6351_PMIC_RG_SMT_RTC_32K1V8_1, + MT6351_PMIC_RG_SMT_SPI_CLK, + MT6351_PMIC_RG_SMT_SPI_CSN, + MT6351_PMIC_RG_SMT_SPI_MOSI, + MT6351_PMIC_RG_SMT_SPI_MISO, + MT6351_PMIC_RG_SMT_AUD_CLK, + MT6351_PMIC_RG_SMT_AUD_DAT_MOSI, + MT6351_PMIC_RG_SMT_AUD_DAT_MISO, + MT6351_PMIC_RG_SMT_ANC_DAT_MOSI, + MT6351_PMIC_RG_SMT_VOW_CLK_MISO, + MT6351_PMIC_RG_SMT_ENBB, + MT6351_PMIC_RG_SMT_XOSC_EN, + MT6351_PMIC_RG_OCTL_SRCLKEN_IN0, + MT6351_PMIC_RG_OCTL_SRCLKEN_IN1, + MT6351_PMIC_RG_OCTL_RTC_32K1V8_0, + MT6351_PMIC_RG_OCTL_RTC_32K1V8_1, + MT6351_PMIC_RG_OCTL_SPI_CLK, + MT6351_PMIC_RG_OCTL_SPI_CSN, + MT6351_PMIC_RG_OCTL_SPI_MOSI, + MT6351_PMIC_RG_OCTL_SPI_MISO, + MT6351_PMIC_RG_OCTL_AUD_DAT_MOSI, + MT6351_PMIC_RG_OCTL_AUD_DAT_MISO, + MT6351_PMIC_RG_OCTL_AUD_CLK, + MT6351_PMIC_RG_OCTL_ANC_DAT_MOSI, + MT6351_PMIC_RG_OCTL_HOMEKEY, + MT6351_PMIC_RG_OCTL_ENBB, + MT6351_PMIC_RG_OCTL_XOSC_EN, + MT6351_PMIC_RG_OCTL_VOW_CLK_MISO, + MT6351_PMIC_TOP_STATUS, + MT6351_PMIC_TOP_STATUS_SET, + MT6351_PMIC_TOP_STATUS_CLR, + MT6351_PMIC_RG_G_SMPS_PD_CK_PDN, + MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN, + MT6351_PMIC_RG_G_DRV_2M_CK_PDN, + MT6351_PMIC_RG_DRV_32K_CK_PDN, + MT6351_PMIC_RG_DRV_ISINK0_CK_PDN, + MT6351_PMIC_RG_DRV_ISINK1_CK_PDN, + MT6351_PMIC_RG_DRV_ISINK2_CK_PDN, + MT6351_PMIC_RG_DRV_ISINK3_CK_PDN, + MT6351_PMIC_RG_AUXADC_1M_CK_PDN, + MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN, + MT6351_PMIC_RG_AUXADC_RNG_CK_PDN, + MT6351_PMIC_RG_AUXADC_26M_CK_PDN, + MT6351_PMIC_RG_AUDNCP_CK_PDN, + MT6351_PMIC_RG_AUDIF_CK_PDN, + MT6351_PMIC_RG_AUD_CK_PDN, + MT6351_PMIC_RG_ZCD13M_CK_PDN, + MT6351_PMIC_TOP_CKPDN_CON0_SET, + MT6351_PMIC_TOP_CKPDN_CON0_CLR, + MT6351_PMIC_RG_RTC_32K_CK_PDN, + MT6351_PMIC_RG_RTC_MCLK_PDN, + MT6351_PMIC_RG_RTC_75K_CK_PDN, + MT6351_PMIC_RG_RTCDET_CK_PDN, + MT6351_PMIC_RG_RTC32K_1V8_0_O_PDN, + MT6351_PMIC_RG_RTC32K_1V8_1_O_PDN, + MT6351_PMIC_RG_RTC_2SEC_OFF_DET_PDN, + MT6351_PMIC_RG_FQMTR_CK_PDN, + MT6351_PMIC_RG_STB_1M_CK_PDN, + MT6351_PMIC_RG_BUCK_1M_CK_PDN, + MT6351_PMIC_RG_AUXADC_CK_PDN, + MT6351_PMIC_RG_PWMOC_6M_CK_PDN, + MT6351_PMIC_RG_PWMOC_AUD_6M_CK_PDN, + MT6351_PMIC_TOP_CKPDN_CON1_SET, + MT6351_PMIC_TOP_CKPDN_CON1_CLR, + MT6351_PMIC_RG_FGADC_ANA_CK_PDN, + MT6351_PMIC_RG_FGADC_DIG_CK_PDN, + MT6351_PMIC_RG_BIF_X72_CK_PDN, + MT6351_PMIC_RG_BIF_X4_CK_PDN, + MT6351_PMIC_RG_BIF_X1_CK_PDN, + MT6351_PMIC_RG_PCHR_32K_CK_PDN, + MT6351_PMIC_RG_ACCDET_CK_PDN, + MT6351_PMIC_RG_FQMTR_32K_CK_PDN, + MT6351_PMIC_RG_INTRP_CK_PDN, + MT6351_PMIC_RG_RTC_26M_CK_PDN, + MT6351_PMIC_RG_RTC_EOSC32_CK_PDN, + MT6351_PMIC_RG_TRIM_75K_CK_PDN, + MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_PDN, + MT6351_PMIC_TOP_CKPDN_CON2_SET, + MT6351_PMIC_TOP_CKPDN_CON2_CLR, + MT6351_PMIC_RG_STRUP_75K_CK_PDN, + MT6351_PMIC_RG_STRUP_32K_CK_PDN, + MT6351_PMIC_RG_EFUSE_CK_PDN, + MT6351_PMIC_RG_SMPS_CK_DIV_PDN, + MT6351_PMIC_RG_SPI_CK_PDN, + MT6351_PMIC_RG_BGR_TEST_CK_PDN, + MT6351_PMIC_RG_FGADC_FT_CK_PDN, + MT6351_PMIC_RG_PCHR_TEST_CK_PDN, + MT6351_PMIC_RG_BUCK_32K_CK_PDN, + MT6351_PMIC_RG_BUCK_ANA_CK_PDN, + MT6351_PMIC_RG_EOSC_CALI_TEST_CK_PDN, + MT6351_PMIC_RG_G_SMPS_TEST_CK_PDN, + MT6351_PMIC_TOP_CKPDN_CON3_RSV, + MT6351_PMIC_TOP_CKPDN_CON3_SET, + MT6351_PMIC_TOP_CKPDN_CON3_CLR, + MT6351_PMIC_RG_BUCK_9M_CK_PDN, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN, + MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN, + MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN, + MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN, + MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN, + MT6351_PMIC_TOP_CKPDN_CON4_RSV, + MT6351_PMIC_TOP_CKPDN_CON4_SET, + MT6351_PMIC_TOP_CKPDN_CON4_CLR, + MT6351_PMIC_RG_LDO_CALI_75K_CK_PDN, + MT6351_PMIC_RG_INTRP_PRE_OC_CK_PDN, + MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN, + MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN, + MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN, + MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN, + MT6351_PMIC_RG_VOW32K_CK_PDN, + MT6351_PMIC_RG_VOW12M_CK_PDN, + MT6351_PMIC_RG_AUD18M_CK_PDN, + MT6351_PMIC_RG_DRV_ISINK4_CK_PDN, + MT6351_PMIC_RG_DRV_ISINK5_CK_PDN, + MT6351_PMIC_RG_DRV_ISINK6_CK_PDN, + MT6351_PMIC_RG_DRV_ISINK7_CK_PDN, + MT6351_PMIC_RG_DRV_CHRIND_CK_PDN, + MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN, + MT6351_PMIC_RG_STB_AUD_1M_CK_PDN, + MT6351_PMIC_TOP_CKPDN_CON5_SET, + MT6351_PMIC_TOP_CKPDN_CON5_CLR, + MT6351_PMIC_RG_AUDIF_CK_CKSEL, + MT6351_PMIC_RG_AUD_CK_CKSEL, + MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL, + MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL, + MT6351_PMIC_RG_DRV_ISINK2_CK_CKSEL, + MT6351_PMIC_RG_DRV_ISINK3_CK_CKSEL, + MT6351_PMIC_RG_FQMTR_CK_CKSEL, + MT6351_PMIC_RG_75K_32K_SEL, + MT6351_PMIC_RG_AUXADC_CK_CKSEL, + MT6351_PMIC_RG_OSC_SEL_HW_SRC_SEL, + MT6351_PMIC_RG_SRCLKEN_SRC_SEL, + MT6351_PMIC_TOP_CKSEL_CON_SET, + MT6351_PMIC_TOP_CKSEL_CON_CLR, + MT6351_PMIC_RG_STRUP_75K_CK_CKSEL, + MT6351_PMIC_RG_BGR_TEST_CK_CKSEL, + MT6351_PMIC_RG_PCHR_TEST_CK_CKSEL, + MT6351_PMIC_RG_FGADC_ANA_CK_CKSEL, + MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL, + MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL, + MT6351_PMIC_RG_DRV_ISINK6_CK_CKSEL, + MT6351_PMIC_RG_DRV_ISINK7_CK_CKSEL, + MT6351_PMIC_RG_DRV_CHRIND_CK_CKSEL, + MT6351_PMIC_RG_TOP_CKSEL_CON1_RSV, + MT6351_PMIC_TOP_CKSEL_CON1_SET, + MT6351_PMIC_TOP_CKSEL_CON1_CLR, + MT6351_PMIC_RG_SRCVOLTEN_SW, + MT6351_PMIC_RG_BUCK_OSC_SEL_SW, + MT6351_PMIC_RG_VOWEN_SW, + MT6351_PMIC_RG_SRCVOLTEN_MODE, + MT6351_PMIC_RG_BUCK_OSC_SEL_MODE, + MT6351_PMIC_RG_VOWEN_MODE, + MT6351_PMIC_RG_TOP_CKSEL_CON2_RSV, + MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_MODE, + MT6351_PMIC_TOP_CKSEL_CON2_SET, + MT6351_PMIC_TOP_CKSEL_CON2_CLR, + MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_MODE, + MT6351_PMIC_TOP_CKSEL_CON3_SET, + MT6351_PMIC_TOP_CKSEL_CON3_CLR, + MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL, + MT6351_PMIC_TOP_CKDIVSEL_CON_RSV, + MT6351_PMIC_RG_BIF_X4_CK_DIVSEL, + MT6351_PMIC_RG_REG_CK_DIVSEL, + MT6351_PMIC_TOP_CKDIVSEL_CON0_RSV, + MT6351_PMIC_TOP_CKDIVSEL_CON0_SET, + MT6351_PMIC_TOP_CKDIVSEL_CON0_CLR, + MT6351_PMIC_RG_AUXADC_SMPS_CK_DIVSEL, + MT6351_PMIC_RG_AUXADC_26M_CK_DIVSEL, + MT6351_PMIC_RG_BUCK_9M_CK_DIVSEL, + MT6351_PMIC_TOP_CKDIVSEL_CON1_SET, + MT6351_PMIC_TOP_CKDIVSEL_CON1_CLR, + MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_HWEN, + MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN, + MT6351_PMIC_RG_G_DRV_2M_CK_PDN_HWEN, + MT6351_PMIC_RG_AUXADC_CK_PDN_HWEN, + MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_1M_CK_PDN_HWEN, + MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN, + MT6351_PMIC_RG_RTC_26M_CK_PDN_HWEN, + MT6351_PMIC_RG_AUXADC_26M_CK_PDN_HWEN, + MT6351_PMIC_RG_AUXADC_CK_CKSEL_HWEN, + MT6351_PMIC_TOP_CKHWEN_CON0_RSV, + MT6351_PMIC_TOP_CKHWEN_CON0_SET, + MT6351_PMIC_TOP_CKHWEN_CON0_CLR, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN, + MT6351_PMIC_TOP_CKHWEN_CON1_RSV, + MT6351_PMIC_TOP_CKHWEN_CON1_SET, + MT6351_PMIC_TOP_CKHWEN_CON1_CLR, + MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_AUD18M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN, + MT6351_PMIC_TOP_CKHWEN_CON2_RSV, + MT6351_PMIC_TOP_CKHWEN_CON2_SET, + MT6351_PMIC_TOP_CKHWEN_CON2_CLR, + MT6351_PMIC_RG_PMU75K_CK_TST_DIS, + MT6351_PMIC_RG_SMPS_CK_TST_DIS, + MT6351_PMIC_RG_AUD26M_CK_TST_DIS, + MT6351_PMIC_RG_RTC32K_CK_TST_DIS, + MT6351_PMIC_RG_FG_CK_TST_DIS, + MT6351_PMIC_RG_RTC26M_CK_TST_DIS, + MT6351_PMIC_RG_VOW12M_CK_TST_DIS, + MT6351_PMIC_TOP_CKTST_CON0_RSV, + MT6351_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS, + MT6351_PMIC_RG_DRV_ISINK0_CK_TSTSEL, + MT6351_PMIC_RG_DRV_ISINK1_CK_TSTSEL, + MT6351_PMIC_RG_DRV_ISINK2_CK_TSTSEL, + MT6351_PMIC_RG_DRV_ISINK3_CK_TSTSEL, + MT6351_PMIC_RG_FQMTR_CK_TSTSEL, + MT6351_PMIC_RG_RTCDET_CK_TSTSEL, + MT6351_PMIC_RG_PMU75K_CK_TSTSEL, + MT6351_PMIC_RG_SMPS_CK_TSTSEL, + MT6351_PMIC_RG_AUD26M_CK_TSTSEL, + MT6351_PMIC_RG_AUDIF_CK_TSTSEL, + MT6351_PMIC_RG_AUD_CK_TSTSEL, + MT6351_PMIC_RG_STRUP_75K_CK_TSTSEL, + MT6351_PMIC_RG_RTC32K_CK_TSTSEL, + MT6351_PMIC_RG_PCHR_TEST_CK_TSTSEL, + MT6351_PMIC_RG_BGR_TEST_CK_TSTSEL, + MT6351_PMIC_RG_FG_CK_TSTSEL, + MT6351_PMIC_RG_FGADC_ANA_CK_TSTSEL, + MT6351_PMIC_RG_RTC26M_CK_TSTSEL, + MT6351_PMIC_RG_RTC_EOSC32_CK_TSTSEL, + MT6351_PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL, + MT6351_PMIC_RG_AUXADC_CK_TSTSEL, + MT6351_PMIC_RG_AUXADC_SMPS_CK_TSTSEL, + MT6351_PMIC_RG_AUXADC_26M_CK_TSTSEL, + MT6351_PMIC_RG_VOW12M_CK_TSTSEL, + MT6351_PMIC_RG_DRV_ISINK4_CK_TSTSEL, + MT6351_PMIC_RG_DRV_ISINK5_CK_TSTSEL, + MT6351_PMIC_RG_DRV_ISINK6_CK_TSTSEL, + MT6351_PMIC_RG_DRV_ISINK7_CK_TSTSEL, + MT6351_PMIC_RG_DRV_CHRIND_CK_TSTSEL, + MT6351_PMIC_TOP_CKTST_CON2_RSV, + MT6351_PMIC_RG_CLKSQ_EN_AUD, + MT6351_PMIC_RG_CLKSQ_EN_FQR, + MT6351_PMIC_RG_CLKSQ_EN_AUX_AP, + MT6351_PMIC_RG_CLKSQ_EN_AUX_MD, + MT6351_PMIC_RG_CLKSQ_EN_AUX_GPS, + MT6351_PMIC_RG_CLKSQ_EN_AUX_RSV, + MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MODE, + MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MODE, + MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18, + MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL, + MT6351_PMIC_TOP_CLKSQ_RSV, + MT6351_PMIC_DA_CLKSQ_EN_VA18, + MT6351_PMIC_TOP_CLKSQ_SET, + MT6351_PMIC_TOP_CLKSQ_CLR, + MT6351_PMIC_RG_CLKSQ_RTC_EN, + MT6351_PMIC_RG_CLKSQ_RTC_EN_HW_MODE, + MT6351_PMIC_TOP_CLKSQ_RTC_RSV0, + MT6351_PMIC_RG_ENBB_SEL, + MT6351_PMIC_RG_XOSC_EN_SEL, + MT6351_PMIC_TOP_CLKSQ_RTC_RSV1, + MT6351_PMIC_DA_CLKSQ_EN_VDIG18, + MT6351_PMIC_TOP_CLKSQ_RTC_SET, + MT6351_PMIC_TOP_CLKSQ_RTC_CLR, + MT6351_PMIC_OSC_75K_TRIM, + MT6351_PMIC_RG_OSC_75K_TRIM_EN, + MT6351_PMIC_RG_OSC_75K_TRIM_RATE, + MT6351_PMIC_DA_OSC_75K_TRIM, + MT6351_PMIC_RG_EFUSE_MAN_RST, + MT6351_PMIC_RG_AUXADC_RST, + MT6351_PMIC_RG_AUXADC_REG_RST, + MT6351_PMIC_RG_AUDIO_RST, + MT6351_PMIC_RG_ACCDET_RST, + MT6351_PMIC_RG_BIF_RST, + MT6351_PMIC_RG_DRIVER_RST, + MT6351_PMIC_RG_FGADC_RST, + MT6351_PMIC_RG_FQMTR_RST, + MT6351_PMIC_RG_RTC_RST, + MT6351_PMIC_RG_CHRWDT_RST, + MT6351_PMIC_RG_ZCD_RST, + MT6351_PMIC_RG_AUDNCP_RST, + MT6351_PMIC_RG_CLK_TRIM_RST, + MT6351_PMIC_RG_LDO_CALI_RST, + MT6351_PMIC_TOP_RST_CON0_SET, + MT6351_PMIC_TOP_RST_CON0_CLR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_RST, + MT6351_PMIC_TOP_RST_CON1_RSV, + MT6351_PMIC_TOP_RST_CON1_SET, + MT6351_PMIC_TOP_RST_CON1_CLR, + MT6351_PMIC_RG_CHR_LDO_DET_MODE, + MT6351_PMIC_RG_CHR_LDO_DET_SW, + MT6351_PMIC_RG_CHRWDT_FLAG_MODE, + MT6351_PMIC_RG_CHRWDT_FLAG_SW, + MT6351_PMIC_TOP_RST_CON2_RSV, + MT6351_PMIC_RG_WDTRSTB_EN, + MT6351_PMIC_RG_WDTRSTB_MODE, + MT6351_PMIC_WDTRSTB_STATUS, + MT6351_PMIC_WDTRSTB_STATUS_CLR, + MT6351_PMIC_RG_WDTRSTB_FB_EN, + MT6351_PMIC_RG_WDTRSTB_DEB, + MT6351_PMIC_RG_HOMEKEY_RST_EN, + MT6351_PMIC_RG_PWRKEY_RST_EN, + MT6351_PMIC_RG_PWRRST_TMR_DIS, + MT6351_PMIC_RG_PWRKEY_RST_TD, + MT6351_PMIC_TOP_RST_MISC_RSV, + MT6351_PMIC_TOP_RST_MISC_SET, + MT6351_PMIC_TOP_RST_MISC_CLR, + MT6351_PMIC_VPWRIN_RSTB_STATUS, + MT6351_PMIC_DDLO_RSTB_STATUS, + MT6351_PMIC_UVLO_RSTB_STATUS, + MT6351_PMIC_RTC_DDLO_RSTB_STATUS, + MT6351_PMIC_CHRWDT_REG_RSTB_STATUS, + MT6351_PMIC_CHRDET_REG_RSTB_STATUS, + MT6351_PMIC_TOP_RST_STATUS_RSV, + MT6351_PMIC_TOP_RST_STATUS_SET, + MT6351_PMIC_TOP_RST_STATUS_CLR, + MT6351_PMIC_RG_INT_EN_PWRKEY, + MT6351_PMIC_RG_INT_EN_HOMEKEY, + MT6351_PMIC_RG_INT_EN_PWRKEY_R, + MT6351_PMIC_RG_INT_EN_HOMEKEY_R, + MT6351_PMIC_RG_INT_EN_THR_H, + MT6351_PMIC_RG_INT_EN_THR_L, + MT6351_PMIC_RG_INT_EN_BAT_H, + MT6351_PMIC_RG_INT_EN_BAT_L, + MT6351_PMIC_RG_INT_EN_RTC, + MT6351_PMIC_RG_INT_EN_AUDIO, + MT6351_PMIC_RG_INT_EN_MAD, + MT6351_PMIC_RG_INT_EN_ACCDET, + MT6351_PMIC_RG_INT_EN_ACCDET_EINT, + MT6351_PMIC_RG_INT_EN_ACCDET_NEGV, + MT6351_PMIC_RG_INT_EN_NI_LBAT_INT, + MT6351_PMIC_INT_CON0_SET, + MT6351_PMIC_INT_CON0_CLR, + MT6351_PMIC_RG_INT_EN_VCORE_OC, + MT6351_PMIC_RG_INT_EN_VGPU_OC, + MT6351_PMIC_RG_INT_EN_VSRAM_MD_OC, + MT6351_PMIC_RG_INT_EN_VMODEM_OC, + MT6351_PMIC_RG_INT_EN_VM1_OC, + MT6351_PMIC_RG_INT_EN_VS1_OC, + MT6351_PMIC_RG_INT_EN_VS2_OC, + MT6351_PMIC_RG_INT_EN_VPA_OC, + MT6351_PMIC_RG_INT_EN_VCORE_PREOC, + MT6351_PMIC_RG_INT_EN_VGPU_PREOC, + MT6351_PMIC_RG_INT_EN_VSRAM_MD_PREOC, + MT6351_PMIC_RG_INT_EN_VMODEM_PREOC, + MT6351_PMIC_RG_INT_EN_VM1_PREOC, + MT6351_PMIC_RG_INT_EN_VS1_PREOC, + MT6351_PMIC_RG_INT_EN_VS2_PREOC, + MT6351_PMIC_RG_INT_EN_LDO_OC, + MT6351_PMIC_INT_CON1_SET, + MT6351_PMIC_INT_CON1_CLR, + MT6351_PMIC_RG_INT_EN_JEITA_HOT, + MT6351_PMIC_RG_INT_EN_JEITA_WARM, + MT6351_PMIC_RG_INT_EN_JEITA_COOL, + MT6351_PMIC_RG_INT_EN_JEITA_COLD, + MT6351_PMIC_RG_INT_EN_AUXADC_IMP, + MT6351_PMIC_RG_INT_EN_NAG_C_DLTV, + MT6351_PMIC_RG_INT_EN_OV, + MT6351_PMIC_RG_INT_EN_BVALID_DET, + MT6351_PMIC_RG_INT_EN_RGS_BATON_HV, + MT6351_PMIC_RG_INT_EN_VBATON_UNDET, + MT6351_PMIC_RG_INT_EN_WATCHDOG, + MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC, + MT6351_PMIC_RG_INT_EN_CHRDET, + MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC, + MT6351_PMIC_INT_CON2_SET, + MT6351_PMIC_INT_CON2_CLR, + MT6351_PMIC_RG_INT_EN_FG_BAT_H, + MT6351_PMIC_RG_INT_EN_FG_BAT_L, + MT6351_PMIC_RG_INT_EN_FG_CUR_H, + MT6351_PMIC_RG_INT_EN_FG_CUR_L, + MT6351_PMIC_RG_INT_EN_FG_ZCV, + MT6351_PMIC_INT_CON3_SET, + MT6351_PMIC_INT_CON3_CLR, + MT6351_PMIC_POLARITY, + MT6351_PMIC_RG_HOMEKEY_INT_SEL, + MT6351_PMIC_RG_PWRKEY_INT_SEL, + MT6351_PMIC_RG_CHRDET_INT_SEL, + MT6351_PMIC_RG_PCHR_CM_VINC_POLARITY_RSV, + MT6351_PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV, + MT6351_PMIC_INT_MISC_CON_SET, + MT6351_PMIC_INT_MISC_CON_CLR, + MT6351_PMIC_RG_INT_STATUS_PWRKEY, + MT6351_PMIC_RG_INT_STATUS_HOMEKEY, + MT6351_PMIC_RG_INT_STATUS_PWRKEY_R, + MT6351_PMIC_RG_INT_STATUS_HOMEKEY_R, + MT6351_PMIC_RG_INT_STATUS_THR_H, + MT6351_PMIC_RG_INT_STATUS_THR_L, + MT6351_PMIC_RG_INT_STATUS_BAT_H, + MT6351_PMIC_RG_INT_STATUS_BAT_L, + MT6351_PMIC_RG_INT_STATUS_RTC, + MT6351_PMIC_RG_INT_STATUS_AUDIO, + MT6351_PMIC_RG_INT_STATUS_MAD, + MT6351_PMIC_RG_INT_STATUS_ACCDET, + MT6351_PMIC_RG_INT_STATUS_ACCDET_EINT, + MT6351_PMIC_RG_INT_STATUS_ACCDET_NEGV, + MT6351_PMIC_RG_INT_STATUS_NI_LBAT_INT, + MT6351_PMIC_RG_INT_STATUS_VCORE_OC, + MT6351_PMIC_RG_INT_STATUS_VGPU_OC, + MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_OC, + MT6351_PMIC_RG_INT_STATUS_VMODEM_OC, + MT6351_PMIC_RG_INT_STATUS_VM1_OC, + MT6351_PMIC_RG_INT_STATUS_VS1_OC, + MT6351_PMIC_RG_INT_STATUS_VS2_OC, + MT6351_PMIC_RG_INT_STATUS_VPA_OC, + MT6351_PMIC_RG_INT_STATUS_VCORE_PREOC, + MT6351_PMIC_RG_INT_STATUS_VGPU_PREOC, + MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_PREOC, + MT6351_PMIC_RG_INT_STATUS_VMODEM_PREOC, + MT6351_PMIC_RG_INT_STATUS_VM1_PREOC, + MT6351_PMIC_RG_INT_STATUS_VS1_PREOC, + MT6351_PMIC_RG_INT_STATUS_VS2_PREOC, + MT6351_PMIC_RG_INT_STATUS_LDO_OC, + MT6351_PMIC_RG_INT_STATUS_JEITA_HOT, + MT6351_PMIC_RG_INT_STATUS_JEITA_WARM, + MT6351_PMIC_RG_INT_STATUS_JEITA_COOL, + MT6351_PMIC_RG_INT_STATUS_JEITA_COLD, + MT6351_PMIC_RG_INT_STATUS_AUXADC_IMP, + MT6351_PMIC_RG_INT_STATUS_NAG_C_DLTV, + MT6351_PMIC_RG_INT_STATUS_OV, + MT6351_PMIC_RG_INT_STATUS_BVALID_DET, + MT6351_PMIC_RG_INT_STATUS_RGS_BATON_HV, + MT6351_PMIC_RG_INT_STATUS_VBATON_UNDET, + MT6351_PMIC_RG_INT_STATUS_WATCHDOG, + MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VDEC, + MT6351_PMIC_RG_INT_STATUS_CHRDET, + MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VINC, + MT6351_PMIC_RG_INT_STATUS_FG_BAT_H, + MT6351_PMIC_RG_INT_STATUS_FG_BAT_L, + MT6351_PMIC_RG_INT_STATUS_FG_CUR_H, + MT6351_PMIC_RG_INT_STATUS_FG_CUR_L, + MT6351_PMIC_RG_INT_STATUS_FG_ZCV, + MT6351_PMIC_OC_GEAR_LDO, + MT6351_PMIC_FQMTR_TCKSEL, + MT6351_PMIC_FQMTR_BUSY, + MT6351_PMIC_FQMTR_EN, + MT6351_PMIC_FQMTR_WINSET, + MT6351_PMIC_FQMTR_DATA, + MT6351_PMIC_RG_SLP_RW_EN, + MT6351_PMIC_RG_SPI_RSV, + MT6351_PMIC_DEW_DIO_EN, + MT6351_PMIC_DEW_READ_TEST, + MT6351_PMIC_DEW_WRITE_TEST, + MT6351_PMIC_DEW_CRC_SWRST, + MT6351_PMIC_DEW_CRC_EN, + MT6351_PMIC_DEW_CRC_VAL, + MT6351_PMIC_DEW_DBG_MON_SEL, + MT6351_PMIC_DEW_CIPHER_KEY_SEL, + MT6351_PMIC_DEW_CIPHER_IV_SEL, + MT6351_PMIC_DEW_CIPHER_EN, + MT6351_PMIC_DEW_CIPHER_RDY, + MT6351_PMIC_DEW_CIPHER_MODE, + MT6351_PMIC_DEW_CIPHER_SWRST, + MT6351_PMIC_DEW_RDDMY_NO, + MT6351_PMIC_INT_TYPE_CON0, + MT6351_PMIC_INT_TYPE_CON0_SET, + MT6351_PMIC_INT_TYPE_CON0_CLR, + MT6351_PMIC_INT_TYPE_CON1, + MT6351_PMIC_INT_TYPE_CON1_SET, + MT6351_PMIC_INT_TYPE_CON1_CLR, + MT6351_PMIC_INT_TYPE_CON2, + MT6351_PMIC_INT_TYPE_CON2_SET, + MT6351_PMIC_INT_TYPE_CON2_CLR, + MT6351_PMIC_INT_TYPE_CON3, + MT6351_PMIC_INT_TYPE_CON3_SET, + MT6351_PMIC_INT_TYPE_CON3_CLR, + MT6351_PMIC_CPU_INT_STA, + MT6351_PMIC_MD32_INT_STA, + MT6351_PMIC_BUCK_LDO_FT_TESTMODE_EN, + MT6351_PMIC_BUCK_ALL_CON0_RSV1, + MT6351_PMIC_BUCK_ALL_CON0_RSV0, + MT6351_PMIC_BUCK_BUCK_RSV, + MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL, + MT6351_PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL, + MT6351_PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL, + MT6351_PMIC_BUCK_ALL_CON2_RSV0, + MT6351_PMIC_BUCK_VSLEEP_SRC0, + MT6351_PMIC_BUCK_VSLEEP_SRC1, + MT6351_PMIC_BUCK_R2R_SRC0, + MT6351_PMIC_BUCK_R2R_SRC1, + MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRC0, + MT6351_PMIC_BUCK_SRCLKEN_DLY_SRC1, + MT6351_PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VPA_VOSEL_DLC011, + MT6351_PMIC_BUCK_VPA_VOSEL_DLC111, + MT6351_PMIC_BUCK_VPA_DLC_MAP_EN, + MT6351_PMIC_BUCK_VPA_VOSEL_DLC001, + MT6351_PMIC_BUCK_VPA_DLC, + MT6351_PMIC_DA_NI_VPA_DLC, + MT6351_PMIC_BUCK_VPA_DVS_TRANS_TD, + MT6351_PMIC_BUCK_VPA_DVS_TRANS_CTRL, + MT6351_PMIC_BUCK_VPA_DVS_TRANS_ONCE, + MT6351_PMIC_DA_NI_VPA_DVS_TRANST, + MT6351_PMIC_BUCK_VPA_DIG0_RSV5, + MT6351_PMIC_BUCK_VPA_DIG1_RSV5, + MT6351_PMIC_BUCK_VCORE_VOSEL_AUD, + MT6351_PMIC_BUCK_VCORE_DVFS_DONE, + MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SW, + MT6351_PMIC_BUCK_VCORE_DVFS_DONE_STA, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_AUD, + MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE, + MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW, + MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA, + MT6351_PMIC_BUCK_VCORE_OC_STATUS, + MT6351_PMIC_BUCK_VGPU_OC_STATUS, + MT6351_PMIC_BUCK_VMODEM_OC_STATUS, + MT6351_PMIC_BUCK_VMD1_OC_STATUS, + MT6351_PMIC_BUCK_VSRAM_MD_OC_STATUS, + MT6351_PMIC_BUCK_VS1_OC_STATUS, + MT6351_PMIC_BUCK_VS2_OC_STATUS, + MT6351_PMIC_BUCK_VPA_OC_STATUS, + MT6351_PMIC_BUCK_VCORE_OC_INT_EN, + MT6351_PMIC_BUCK_VGPU_OC_INT_EN, + MT6351_PMIC_BUCK_VMODEM_OC_INT_EN, + MT6351_PMIC_BUCK_VMD1_OC_INT_EN, + MT6351_PMIC_BUCK_VSRAM_MD_OC_INT_EN, + MT6351_PMIC_BUCK_VS1_OC_INT_EN, + MT6351_PMIC_BUCK_VS2_OC_INT_EN, + MT6351_PMIC_BUCK_VPA_OC_INT_EN, + MT6351_PMIC_BUCK_VCORE_EN_OC_SDN_SEL, + MT6351_PMIC_BUCK_VGPU_EN_OC_SDN_SEL, + MT6351_PMIC_BUCK_VMODEM_EN_OC_SDN_SEL, + MT6351_PMIC_BUCK_VMD1_EN_OC_SDN_SEL, + MT6351_PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL, + MT6351_PMIC_BUCK_VS1_EN_OC_SDN_SEL, + MT6351_PMIC_BUCK_VS2_EN_OC_SDN_SEL, + MT6351_PMIC_BUCK_VPA_EN_OC_SDN_SEL, + MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR, + MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR, + MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR, + MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR, + MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR, + MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR, + MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR, + MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR, + MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VCORE_OC_DEG_EN, + MT6351_PMIC_BUCK_VCORE_OC_WND, + MT6351_PMIC_BUCK_VCORE_OC_THD, + MT6351_PMIC_BUCK_VGPU_OC_DEG_EN, + MT6351_PMIC_BUCK_VGPU_OC_WND, + MT6351_PMIC_BUCK_VGPU_OC_THD, + MT6351_PMIC_BUCK_VMODEM_OC_DEG_EN, + MT6351_PMIC_BUCK_VMODEM_OC_WND, + MT6351_PMIC_BUCK_VMODEM_OC_THD, + MT6351_PMIC_BUCK_VMD1_OC_DEG_EN, + MT6351_PMIC_BUCK_VMD1_OC_WND, + MT6351_PMIC_BUCK_VMD1_OC_THD, + MT6351_PMIC_BUCK_VSRAM_MD_OC_DEG_EN, + MT6351_PMIC_BUCK_VSRAM_MD_OC_WND, + MT6351_PMIC_BUCK_VSRAM_MD_OC_THD, + MT6351_PMIC_BUCK_VS1_OC_DEG_EN, + MT6351_PMIC_BUCK_VS1_OC_WND, + MT6351_PMIC_BUCK_VS1_OC_THD, + MT6351_PMIC_BUCK_VS2_OC_DEG_EN, + MT6351_PMIC_BUCK_VS2_OC_WND, + MT6351_PMIC_BUCK_VS2_OC_THD, + MT6351_PMIC_BUCK_VPA_OC_DEG_EN, + MT6351_PMIC_BUCK_VPA_OC_WND, + MT6351_PMIC_BUCK_VPA_OC_THD, + MT6351_PMIC_RG_SMPS_TESTMODE_B, + MT6351_PMIC_RG_VPA_BURSTH, + MT6351_PMIC_RG_VPA_BURSTL, + MT6351_PMIC_RG_VPA_TRIMH, + MT6351_PMIC_RG_VPA_TRIML, + MT6351_PMIC_RG_VPA_TRIM_REF, + MT6351_PMIC_RG_VCORE_TRIMH, + MT6351_PMIC_RG_VCORE_TRIML, + MT6351_PMIC_RG_VCORE_VSLEEP, + MT6351_PMIC_RG_VGPU_TRIMH, + MT6351_PMIC_RG_VGPU_TRIML, + MT6351_PMIC_RG_VGPU_VSLEEP, + MT6351_PMIC_RG_VSRAM_MD_TRIMH, + MT6351_PMIC_RG_VSRAM_MD_TRIML, + MT6351_PMIC_RG_VSRAM_MD_VSLEEP, + MT6351_PMIC_RG_VMODEM_TRIMH, + MT6351_PMIC_RG_VMODEM_TRIML, + MT6351_PMIC_RG_VMODEM_VSLEEP, + MT6351_PMIC_RG_VMD1_TRIMH, + MT6351_PMIC_RG_VMD1_TRIML, + MT6351_PMIC_RG_VMD1_VSLEEP, + MT6351_PMIC_RG_VS1_TRIMH, + MT6351_PMIC_RG_VS1_TRIML, + MT6351_PMIC_RG_VS1_VSLEEP, + MT6351_PMIC_RG_VS2_TRIML, + MT6351_PMIC_RG_VS2_VSLEEP, + MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIMH, + MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIML, + MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP, + MT6351_PMIC_RG_VCORE_VSLEEP_SEL, + MT6351_PMIC_RG_VGPU_VSLEEP_SEL, + MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SEL, + MT6351_PMIC_RG_VMODEM_VSLEEP_SEL, + MT6351_PMIC_RG_VMD1_VSLEEP_SEL, + MT6351_PMIC_RG_VS1_VSLEEP_SEL, + MT6351_PMIC_RG_VS2_VSLEEP_SEL, + MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL, + MT6351_PMIC_RG_VOUTDET_EN, + MT6351_PMIC_RG_VS2_TRIMH, + MT6351_PMIC_RG_VCORE_MODESET, + MT6351_PMIC_RG_VCORE_NDIS_EN, + MT6351_PMIC_RG_VCORE_VRF18_SSTART_EN, + MT6351_PMIC_RG_VCORE_AUTO_MODE, + MT6351_PMIC_RG_VCORE_RZSEL0, + MT6351_PMIC_RG_VCORE_RZSEL1, + MT6351_PMIC_RG_VCORE_CCSEL0, + MT6351_PMIC_RG_VCORE_CCSEL1, + MT6351_PMIC_RG_VCORE_CSL, + MT6351_PMIC_RG_VCORE_SLP, + MT6351_PMIC_RG_VCORE_ADRC_FEN, + MT6351_PMIC_RG_VCORE_VCCAP_CLAMP_FEN, + MT6351_PMIC_RG_VCORE_VC_CLAMP_FEN, + MT6351_PMIC_RG_VCORE_PREOC_SEL, + MT6351_PMIC_RG_VCORE_PFMOC, + MT6351_PMIC_RG_VCORE_CSR, + MT6351_PMIC_RG_VCORE_ZXOS_TRIM, + MT6351_PMIC_RG_VCORE_CSM_N, + MT6351_PMIC_RG_VCORE_CSM_P, + MT6351_PMIC_RG_VCORE_PFMSR_EH, + MT6351_PMIC_RG_VCORE_NLIM_GATING, + MT6351_PMIC_RG_VCORE_PWRSR_EH, + MT6351_PMIC_RG_VCORE_HS_VTHDET, + MT6351_PMIC_RG_VCORE_PG_GATING, + MT6351_PMIC_RG_VCORE_HS_ONSPEED_EH, + MT6351_PMIC_RG_VCORE_NLIM_TRIMMING, + MT6351_PMIC_RG_VCORE_DLC, + MT6351_PMIC_RG_VCORE_DLC_N, + MT6351_PMIC_RG_VCORE_PFM_RIP, + MT6351_PMIC_RG_VCORE_TRAN_BST, + MT6351_PMIC_RG_VCORE_DTS_ENB, + MT6351_PMIC_RG_VCORE_MIN_OFF, + MT6351_PMIC_RG_VCORE_1P35UP_SEL_EN, + MT6351_PMIC_RG_VCORE_DLC_AUTO_MODE, + MT6351_PMIC_RG_VCORE_DLC_SEL, + MT6351_PMIC_RG_VCORE_SRC_AUTO_MODE, + MT6351_PMIC_RG_VCORE_UGP_SR, + MT6351_PMIC_RG_VCORE_LGN_SR, + MT6351_PMIC_RG_VCORE_UGP_SR_PFM, + MT6351_PMIC_RG_VCORE_LGN_SR_PFM, + MT6351_PMIC_RG_VCORE_UGD_VTHSEL, + MT6351_PMIC_RG_VCORE_FNLX_SNS, + MT6351_PMIC_RG_VCORE_VDIFF_ENLOWIQ, + MT6351_PMIC_RG_VCORE_PFMOC_FWUPOFF, + MT6351_PMIC_RG_VCORE_PWFMOC_FWUPOFF, + MT6351_PMIC_RG_VCORE_CP_FWUPOFF, + MT6351_PMIC_RG_VCORE_ZX_GATING, + MT6351_PMIC_RG_VCORE_RSV, + MT6351_PMIC_RG_VCORE_PREOC_TRIMMING, + MT6351_PMIC_RG_VCORE_AZC_EN, + MT6351_PMIC_RG_VCORE_AZC_DELAY, + MT6351_PMIC_RG_VCORE_AZC_HOLD_ENB, + MT6351_PMIC_RGS_QI_VCORE_OC_STATUS, + MT6351_PMIC_RGS_QI_VCORE_DIG_MON, + MT6351_PMIC_RGS_VCORE_ENPWM_STATUS, + MT6351_PMIC_RGS_QI_VCORE_PREOC, + MT6351_PMIC_RG_VGPU_MODESET, + MT6351_PMIC_RG_VGPU_NDIS_EN, + MT6351_PMIC_RG_VGPU_VRF18_SSTART_EN, + MT6351_PMIC_RG_VGPU_AUTO_MODE, + MT6351_PMIC_RG_VGPU_RZSEL0, + MT6351_PMIC_RG_VGPU_RZSEL1, + MT6351_PMIC_RG_VGPU_CCSEL0, + MT6351_PMIC_RG_VGPU_CCSEL1, + MT6351_PMIC_RG_VGPU_CSL, + MT6351_PMIC_RG_VGPU_SLP, + MT6351_PMIC_RG_VGPU_ADRC_FEN, + MT6351_PMIC_RG_VGPU_VCCAP_CLAMP_FEN, + MT6351_PMIC_RG_VGPU_VC_CLAMP_FEN, + MT6351_PMIC_RG_VGPU_PREOC_SEL, + MT6351_PMIC_RG_VGPU_PFMOC, + MT6351_PMIC_RG_VGPU_CSR, + MT6351_PMIC_RG_VGPU_ZXOS_TRIM, + MT6351_PMIC_RG_VGPU_CSM_N, + MT6351_PMIC_RG_VGPU_CSM_P, + MT6351_PMIC_RG_VGPU_PFMSR_EH, + MT6351_PMIC_RG_VGPU_NLIM_GATING, + MT6351_PMIC_RG_VGPU_PWRSR_EH, + MT6351_PMIC_RG_VGPU_HS_VTHDET, + MT6351_PMIC_RG_VGPU_PG_GATING, + MT6351_PMIC_RG_VGPU_HS_ONSPEED_EH, + MT6351_PMIC_RG_VGPU_NLIM_TRIMMING, + MT6351_PMIC_RG_VGPU_DLC, + MT6351_PMIC_RG_VGPU_DLC_N, + MT6351_PMIC_RG_VGPU_PFM_RIP, + MT6351_PMIC_RG_VGPU_TRAN_BST, + MT6351_PMIC_RG_VGPU_DTS_ENB, + MT6351_PMIC_RG_VGPU_MIN_OFF, + MT6351_PMIC_RG_VGPU_1P35UP_SEL_EN, + MT6351_PMIC_RG_VGPU_DLC_AUTO_MODE, + MT6351_PMIC_RG_VGPU_DLC_SEL, + MT6351_PMIC_RG_VGPU_SRC_AUTO_MODE, + MT6351_PMIC_RG_VGPU_UGP_SR, + MT6351_PMIC_RG_VGPU_LGN_SR, + MT6351_PMIC_RG_VGPU_UGP_SR_PFM, + MT6351_PMIC_RG_VGPU_LGN_SR_PFM, + MT6351_PMIC_RG_VGPU_UGD_VTHSEL, + MT6351_PMIC_RG_VGPU_FNLX_SNS, + MT6351_PMIC_RG_VGPU_VDIFF_ENLOWIQ, + MT6351_PMIC_RG_VGPU_PFMOC_FWUPOFF, + MT6351_PMIC_RG_VGPU_PWFMOC_FWUPOFF, + MT6351_PMIC_RG_VGPU_CP_FWUPOFF, + MT6351_PMIC_RG_VGPU_ZX_GATING, + MT6351_PMIC_RG_VGPU_RSV, + MT6351_PMIC_RG_VGPU_PREOC_TRIMMING, + MT6351_PMIC_RG_VGPU_AZC_EN, + MT6351_PMIC_RG_VGPU_AZC_DELAY, + MT6351_PMIC_RG_VGPU_AZC_HOLD_ENB, + MT6351_PMIC_RGS_QI_VGPU_OC_STATUS, + MT6351_PMIC_RGS_QI_VGPU_DIG_MON, + MT6351_PMIC_RGS_VGPU_ENPWM_STATUS, + MT6351_PMIC_RGS_QI_VGPU_PREOC, + MT6351_PMIC_RG_VSRAM_MD_MODESET, + MT6351_PMIC_RG_VSRAM_MD_NDIS_EN, + MT6351_PMIC_RG_VSRAM_MD_VRF18_SSTART_EN, + MT6351_PMIC_RG_VSRAM_MD_AUTO_MODE, + MT6351_PMIC_RG_VSRAM_MD_RZSEL0, + MT6351_PMIC_RG_VSRAM_MD_RZSEL1, + MT6351_PMIC_RG_VSRAM_MD_CCSEL0, + MT6351_PMIC_RG_VSRAM_MD_CCSEL1, + MT6351_PMIC_RG_VSRAM_MD_CSL, + MT6351_PMIC_RG_VSRAM_MD_SLP, + MT6351_PMIC_RG_VSRAM_MD_ADRC_FEN, + MT6351_PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN, + MT6351_PMIC_RG_VSRAM_MD_VC_CLAMP_FEN, + MT6351_PMIC_RG_VSRAM_MD_PFMOC, + MT6351_PMIC_RG_VSRAM_MD_CSR, + MT6351_PMIC_RG_VSRAM_MD_ZXOS_TRIM, + MT6351_PMIC_RG_VSRAM_MD_PFMSR_EH, + MT6351_PMIC_RG_VSRAM_MD_NLIM_GATING, + MT6351_PMIC_RG_VSRAM_MD_PWRSR_EH, + MT6351_PMIC_RG_VSRAM_MD_HS_VTHDET, + MT6351_PMIC_RG_VSRAM_MD_PG_GATING, + MT6351_PMIC_RG_VSRAM_MD_HS_ONSPEED_EH, + MT6351_PMIC_RG_VSRAM_MD_NLIM_TRIMMING, + MT6351_PMIC_RG_VSRAM_MD_DLC, + MT6351_PMIC_RG_VSRAM_MD_DLC_N, + MT6351_PMIC_RG_VSRAM_MD_PFM_RIP, + MT6351_PMIC_RG_VSRAM_MD_TRAN_BST, + MT6351_PMIC_RG_VSRAM_MD_DTS_ENB, + MT6351_PMIC_RG_VSRAM_MD_MIN_OFF, + MT6351_PMIC_RG_VSRAM_MD_1P35UP_SEL_EN, + MT6351_PMIC_RG_VSRAM_MD_DLC_AUTO_MODE, + MT6351_PMIC_RG_VSRAM_MD_DLC_SEL, + MT6351_PMIC_RG_VSRAM_MD_SRC_AUTO_MODE, + MT6351_PMIC_RG_VSRAM_MD_UGP_SR, + MT6351_PMIC_RG_VSRAM_MD_LGN_SR, + MT6351_PMIC_RG_VSRAM_MD_UGP_SR_PFM, + MT6351_PMIC_RG_VSRAM_MD_LGN_SR_PFM, + MT6351_PMIC_RG_VSRAM_MD_UGD_VTHSEL, + MT6351_PMIC_RG_VSRAM_MD_FNLX_SNS, + MT6351_PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ, + MT6351_PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF, + MT6351_PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF, + MT6351_PMIC_RG_VSRAM_MD_CP_FWUPOFF, + MT6351_PMIC_RG_VSRAM_MD_ZX_GATING, + MT6351_PMIC_RG_VSRAM_MD_RSV, + MT6351_PMIC_RG_VSRAM_MD_AZC_EN, + MT6351_PMIC_RG_VSRAM_MD_AZC_DELAY, + MT6351_PMIC_RG_VSRAM_MD_AZC_HOLD_ENB, + MT6351_PMIC_RGS_QI_VSRAM_MD_OC_STATUS, + MT6351_PMIC_RGS_QI_VSRAM_MD_DIG_MON, + MT6351_PMIC_RGS_VSRAM_MD_ENPWM_STATUS, + MT6351_PMIC_RG_VMODEM_MODESET, + MT6351_PMIC_RG_VMODEM_NDIS_EN, + MT6351_PMIC_RG_VMODEM_VRF18_SSTART_EN, + MT6351_PMIC_RG_VMODEM_AUTO_MODE, + MT6351_PMIC_RG_VMODEM_RZSEL0, + MT6351_PMIC_RG_VMODEM_RZSEL1, + MT6351_PMIC_RG_VMODEM_CCSEL0, + MT6351_PMIC_RG_VMODEM_CCSEL1, + MT6351_PMIC_RG_VMODEM_CSL, + MT6351_PMIC_RG_VMODEM_SLP, + MT6351_PMIC_RG_VMODEM_ADRC_FEN, + MT6351_PMIC_RG_VMODEM_VCCAP_CLAMP_FEN, + MT6351_PMIC_RG_VMODEM_VC_CLAMP_FEN, + MT6351_PMIC_RG_VMODEM_PFMOC, + MT6351_PMIC_RG_VMODEM_CSR, + MT6351_PMIC_RG_VMODEM_ZXOS_TRIM, + MT6351_PMIC_RG_VMODEM_PFMSR_EH, + MT6351_PMIC_RG_VMODEM_NLIM_GATING, + MT6351_PMIC_RG_VMODEM_PWRSR_EH, + MT6351_PMIC_RG_VMODEM_HS_VTHDET, + MT6351_PMIC_RG_VMODEM_PG_GATING, + MT6351_PMIC_RG_VMODEM_HS_ONSPEED_EH, + MT6351_PMIC_RG_VMODEM_NLIM_TRIMMING, + MT6351_PMIC_RG_VMODEM_DLC, + MT6351_PMIC_RG_VMODEM_DLC_N, + MT6351_PMIC_RG_VMODEM_PFM_RIP, + MT6351_PMIC_RG_VMODEM_TRAN_BST, + MT6351_PMIC_RG_VMODEM_DTS_ENB, + MT6351_PMIC_RG_VMODEM_MIN_OFF, + MT6351_PMIC_RG_VMODEM_1P35UP_SEL_EN, + MT6351_PMIC_RG_VMODEM_DLC_AUTO_MODE, + MT6351_PMIC_RG_VMODEM_DLC_SEL, + MT6351_PMIC_RG_VMODEM_SRC_AUTO_MODE, + MT6351_PMIC_RG_VMODEM_UGP_SR, + MT6351_PMIC_RG_VMODEM_LGN_SR, + MT6351_PMIC_RG_VMODEM_UGP_SR_PFM, + MT6351_PMIC_RG_VMODEM_LGN_SR_PFM, + MT6351_PMIC_RG_VMODEM_UGD_VTHSEL, + MT6351_PMIC_RG_VMODEM_FNLX_SNS, + MT6351_PMIC_RG_VMODEM_VDIFF_ENLOWIQ, + MT6351_PMIC_RG_VMODEM_PFMOC_FWUPOFF, + MT6351_PMIC_RG_VMODEM_PWFMOC_FWUPOFF, + MT6351_PMIC_RG_VMODEM_CP_FWUPOFF, + MT6351_PMIC_RG_VMODEM_ZX_GATING, + MT6351_PMIC_RG_VMODEM_RSV, + MT6351_PMIC_RG_VMODEM_AZC_EN, + MT6351_PMIC_RG_VMODEM_AZC_DELAY, + MT6351_PMIC_RG_VMODEM_AZC_HOLD_ENB, + MT6351_PMIC_RGS_QI_VMODEM_OC_STATUS, + MT6351_PMIC_RGS_QI_VMODEM_DIG_MON, + MT6351_PMIC_RGS_VMODEM_ENPWM_STATUS, + MT6351_PMIC_RG_VMD1_MODESET, + MT6351_PMIC_RG_VMD1_NDIS_EN, + MT6351_PMIC_RG_VMD1_VRF18_SSTART_EN, + MT6351_PMIC_RG_VMD1_AUTO_MODE, + MT6351_PMIC_RG_VMD1_RZSEL0, + MT6351_PMIC_RG_VMD1_RZSEL1, + MT6351_PMIC_RG_VMD1_CCSEL0, + MT6351_PMIC_RG_VMD1_CCSEL1, + MT6351_PMIC_RG_VMD1_CSL, + MT6351_PMIC_RG_VMD1_SLP, + MT6351_PMIC_RG_VMD1_ADRC_FEN, + MT6351_PMIC_RG_VMD1_VCCAP_CLAMP_FEN, + MT6351_PMIC_RG_VMD1_VC_CLAMP_FEN, + MT6351_PMIC_RG_VMD1_PFMOC, + MT6351_PMIC_RG_VMD1_CSR, + MT6351_PMIC_RG_VMD1_ZXOS_TRIM, + MT6351_PMIC_RG_VMD1_PFMSR_EH, + MT6351_PMIC_RG_VMD1_NLIM_GATING, + MT6351_PMIC_RG_VMD1_PWRSR_EH, + MT6351_PMIC_RG_VMD1_HS_VTHDET, + MT6351_PMIC_RG_VMD1_PG_GATING, + MT6351_PMIC_RG_VMD1_HS_ONSPEED_EH, + MT6351_PMIC_RG_VMD1_NLIM_TRIMMING, + MT6351_PMIC_RG_VMD1_DLC, + MT6351_PMIC_RG_VMD1_DLC_N, + MT6351_PMIC_RG_VMD1_PFM_RIP, + MT6351_PMIC_RG_VMD1_TRAN_BST, + MT6351_PMIC_RG_VMD1_DTS_ENB, + MT6351_PMIC_RG_VMD1_MIN_OFF, + MT6351_PMIC_RG_VMD1_1P35UP_SEL_EN, + MT6351_PMIC_RG_VMD1_DLC_AUTO_MODE, + MT6351_PMIC_RG_VMD1_DLC_SEL, + MT6351_PMIC_RG_VMD1_SRC_AUTO_MODE, + MT6351_PMIC_RG_VMD1_UGP_SR, + MT6351_PMIC_RG_VMD1_LGN_SR, + MT6351_PMIC_RG_VMD1_UGP_SR_PFM, + MT6351_PMIC_RG_VMD1_LGN_SR_PFM, + MT6351_PMIC_RG_VMD1_UGD_VTHSEL, + MT6351_PMIC_RG_VMD1_FNLX_SNS, + MT6351_PMIC_RG_VMD1_VDIFF_ENLOWIQ, + MT6351_PMIC_RG_VMD1_PFMOC_FWUPOFF, + MT6351_PMIC_RG_VMD1_PWFMOC_FWUPOFF, + MT6351_PMIC_RG_VMD1_CP_FWUPOFF, + MT6351_PMIC_RG_VMD1_ZX_GATING, + MT6351_PMIC_RG_VMD1_RSV, + MT6351_PMIC_RG_VMD1_AZC_EN, + MT6351_PMIC_RG_VMD1_AZC_DELAY, + MT6351_PMIC_RG_VMD1_AZC_HOLD_ENB, + MT6351_PMIC_RGS_QI_VMD1_OC_STATUS, + MT6351_PMIC_RGS_QI_VMD1_DIG_MON, + MT6351_PMIC_RGS_VMD1_ENPWM_STATUS, + MT6351_PMIC_RG_VS1_MODESET, + MT6351_PMIC_RG_VS1_NDIS_EN, + MT6351_PMIC_RG_VS1_VRF18_SSTART_EN, + MT6351_PMIC_RG_VS1_AUTO_MODE, + MT6351_PMIC_RG_VS1_RZSEL0, + MT6351_PMIC_RG_VS1_RZSEL1, + MT6351_PMIC_RG_VS1_CCSEL0, + MT6351_PMIC_RG_VS1_CCSEL1, + MT6351_PMIC_RG_VS1_CSL, + MT6351_PMIC_RG_VS1_SLP, + MT6351_PMIC_RG_VS1_ADRC_FEN, + MT6351_PMIC_RG_VS1_VCCAP_CLAMP_FEN, + MT6351_PMIC_RG_VS1_VC_CLAMP_FEN, + MT6351_PMIC_RG_VS1_PFMOC, + MT6351_PMIC_RG_VS1_CSR, + MT6351_PMIC_RG_VS1_ZXOS_TRIM, + MT6351_PMIC_RG_VS1_PFMSR_EH, + MT6351_PMIC_RG_VS1_NLIM_GATING, + MT6351_PMIC_RG_VS1_PWRSR_EH, + MT6351_PMIC_RG_VS1_HS_VTHDET, + MT6351_PMIC_RG_VS1_PG_GATING, + MT6351_PMIC_RG_VS1_HS_ONSPEED_EH, + MT6351_PMIC_RG_VS1_NLIM_TRIMMING, + MT6351_PMIC_RG_VS1_DLC, + MT6351_PMIC_RG_VS1_DLC_N, + MT6351_PMIC_RG_VS1_PFM_RIP, + MT6351_PMIC_RG_VS1_TRAN_BST, + MT6351_PMIC_RG_VS1_DTS_ENB, + MT6351_PMIC_RG_VS1_MIN_OFF, + MT6351_PMIC_RG_VS1_1P35UP_SEL_EN, + MT6351_PMIC_RG_VS1_DLC_AUTO_MODE, + MT6351_PMIC_RG_VS1_DLC_SEL, + MT6351_PMIC_RG_VS1_SRC_AUTO_MODE, + MT6351_PMIC_RG_VS1_UGP_SR, + MT6351_PMIC_RG_VS1_LGN_SR, + MT6351_PMIC_RG_VS1_UGP_SR_PFM, + MT6351_PMIC_RG_VS1_LGN_SR_PFM, + MT6351_PMIC_RG_VS1_UGD_VTHSEL, + MT6351_PMIC_RG_VS1_FNLX_SNS, + MT6351_PMIC_RG_VS1_VDIFF_ENLOWIQ, + MT6351_PMIC_RG_VS1_PFMOC_FWUPOFF, + MT6351_PMIC_RG_VS1_PWFMOC_FWUPOFF, + MT6351_PMIC_RG_VS1_CP_FWUPOFF, + MT6351_PMIC_RG_VS1_ZX_GATING, + MT6351_PMIC_RG_VS1_RSV, + MT6351_PMIC_RG_VS1_AZC_EN, + MT6351_PMIC_RG_VS1_AZC_DELAY, + MT6351_PMIC_RG_VS1_AZC_HOLD_ENB, + MT6351_PMIC_RGS_QI_VS1_OC_STATUS, + MT6351_PMIC_RGS_QI_VS1_DIG_MON, + MT6351_PMIC_RGS_VS1_ENPWM_STATUS, + MT6351_PMIC_RG_VS2_MODESET, + MT6351_PMIC_RG_VS2_NDIS_EN, + MT6351_PMIC_RG_VS2_VRF18_SSTART_EN, + MT6351_PMIC_RG_VS2_AUTO_MODE, + MT6351_PMIC_RG_VS2_RZSEL0, + MT6351_PMIC_RG_VS2_RZSEL1, + MT6351_PMIC_RG_VS2_CCSEL0, + MT6351_PMIC_RG_VS2_CCSEL1, + MT6351_PMIC_RG_VS2_CSL, + MT6351_PMIC_RG_VS2_SLP, + MT6351_PMIC_RG_VS2_ADRC_FEN, + MT6351_PMIC_RG_VS2_VCCAP_CLAMP_FEN, + MT6351_PMIC_RG_VS2_VC_CLAMP_FEN, + MT6351_PMIC_RG_VS2_PFMOC, + MT6351_PMIC_RG_VS2_CSR, + MT6351_PMIC_RG_VS2_ZXOS_TRIM, + MT6351_PMIC_RG_VS2_PFMSR_EH, + MT6351_PMIC_RG_VS2_NLIM_GATING, + MT6351_PMIC_RG_VS2_PWRSR_EH, + MT6351_PMIC_RG_VS2_HS_VTHDET, + MT6351_PMIC_RG_VS2_PG_GATING, + MT6351_PMIC_RG_VS2_HS_ONSPEED_EH, + MT6351_PMIC_RG_VS2_NLIM_TRIMMING, + MT6351_PMIC_RG_VS2_DLC, + MT6351_PMIC_RG_VS2_DLC_N, + MT6351_PMIC_RG_VS2_PFM_RIP, + MT6351_PMIC_RG_VS2_TRAN_BST, + MT6351_PMIC_RG_VS2_DTS_ENB, + MT6351_PMIC_RG_VS2_MIN_OFF, + MT6351_PMIC_RG_VS2_1P35UP_SEL_EN, + MT6351_PMIC_RG_VS2_DLC_AUTO_MODE, + MT6351_PMIC_RG_VS2_DLC_SEL, + MT6351_PMIC_RG_VS2_SRC_AUTO_MODE, + MT6351_PMIC_RG_VS2_UGP_SR, + MT6351_PMIC_RG_VS2_LGN_SR, + MT6351_PMIC_RG_VS2_UGP_SR_PFM, + MT6351_PMIC_RG_VS2_LGN_SR_PFM, + MT6351_PMIC_RG_VS2_UGD_VTHSEL, + MT6351_PMIC_RG_VS2_FNLX_SNS, + MT6351_PMIC_RG_VS2_VDIFF_ENLOWIQ, + MT6351_PMIC_RG_VS2_PFMOC_FWUPOFF, + MT6351_PMIC_RG_VS2_PWFMOC_FWUPOFF, + MT6351_PMIC_RG_VS2_CP_FWUPOFF, + MT6351_PMIC_RG_VS2_ZX_GATING, + MT6351_PMIC_RG_VS2_RSV, + MT6351_PMIC_RG_VS2_AZC_EN, + MT6351_PMIC_RG_VS2_AZC_DELAY, + MT6351_PMIC_RG_VS2_AZC_HOLD_ENB, + MT6351_PMIC_RGS_QI_VS2_OC_STATUS, + MT6351_PMIC_RGS_QI_VS2_DIG_MON, + MT6351_PMIC_RGS_VS2_ENPWM_STATUS, + MT6351_PMIC_RG_VPA_NDIS_EN, + MT6351_PMIC_RG_VPA_MODESET, + MT6351_PMIC_RG_VPA_CC, + MT6351_PMIC_RG_VPA_CSR, + MT6351_PMIC_RG_VPA_CSMIR, + MT6351_PMIC_RG_VPA_CSL, + MT6351_PMIC_RG_VPA_SLP, + MT6351_PMIC_RG_VPA_AZC_EN, + MT6351_PMIC_RG_VPA_CP_FWUPOFF, + MT6351_PMIC_RG_VPA_AZC_DELAY, + MT6351_PMIC_RG_VPA_RZSEL, + MT6351_PMIC_RG_VPA_ZXREF, + MT6351_PMIC_RG_VPA_NLIM_SEL, + MT6351_PMIC_RG_VPA_HZP, + MT6351_PMIC_RG_VPA_BWEX_GAT, + MT6351_PMIC_RG_VPA_SLEW, + MT6351_PMIC_RG_VPA_SLEW_NMOS, + MT6351_PMIC_RG_VPA_MIN_ON, + MT6351_PMIC_RG_VPA_VBAT_DEL, + MT6351_PMIC_RGS_VPA_AZC_VOS_SEL, + MT6351_PMIC_RG_VPA_MIN_PK, + MT6351_PMIC_RG_VPA_RSV1, + MT6351_PMIC_RG_VPA_RSV2, + MT6351_PMIC_RGS_QI_VPA_OC_STATUS, + MT6351_PMIC_BUCK_VCORE_EN_CTRL, + MT6351_PMIC_BUCK_VCORE_VOSEL_CTRL, + MT6351_PMIC_BUCK_VCORE_EN_SEL, + MT6351_PMIC_BUCK_VCORE_VOSEL_SEL, + MT6351_PMIC_BUCK_VCORE_EN, + MT6351_PMIC_BUCK_VCORE_STBTD, + MT6351_PMIC_DA_VCORE_STB, + MT6351_PMIC_DA_QI_VCORE_EN, + MT6351_PMIC_BUCK_VCORE_SFCHG_FRATE, + MT6351_PMIC_BUCK_VCORE_SFCHG_FEN, + MT6351_PMIC_BUCK_VCORE_SFCHG_RRATE, + MT6351_PMIC_BUCK_VCORE_SFCHG_REN, + MT6351_PMIC_BUCK_VCORE_VOSEL, + MT6351_PMIC_BUCK_VCORE_VOSEL_ON, + MT6351_PMIC_BUCK_VCORE_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VCORE_VOSEL, + MT6351_PMIC_DA_NI_VCORE_VOSEL_SYNC, + MT6351_PMIC_BUCK_VCORE_TRANS_TD, + MT6351_PMIC_BUCK_VCORE_TRANS_CTRL, + MT6351_PMIC_BUCK_VCORE_TRANS_ONCE, + MT6351_PMIC_DA_QI_VCORE_DVS_EN, + MT6351_PMIC_BUCK_VCORE_VSLEEP_EN, + MT6351_PMIC_BUCK_VCORE_R2R_PDN, + MT6351_PMIC_BUCK_VCORE_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VCORE_R2R_PDN, + MT6351_PMIC_DA_NI_VCORE_VSLEEP_SEL, + MT6351_PMIC_BUCK_VGPU_EN_CTRL, + MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL, + MT6351_PMIC_BUCK_VGPU_EN_SEL, + MT6351_PMIC_BUCK_VGPU_VOSEL_SEL, + MT6351_PMIC_BUCK_VGPU_EN, + MT6351_PMIC_BUCK_VGPU_STBTD, + MT6351_PMIC_DA_VGPU_STB, + MT6351_PMIC_DA_QI_VGPU_EN, + MT6351_PMIC_BUCK_VGPU_SFCHG_FRATE, + MT6351_PMIC_BUCK_VGPU_SFCHG_FEN, + MT6351_PMIC_BUCK_VGPU_SFCHG_RRATE, + MT6351_PMIC_BUCK_VGPU_SFCHG_REN, + MT6351_PMIC_BUCK_VGPU_VOSEL, + MT6351_PMIC_BUCK_VGPU_VOSEL_ON, + MT6351_PMIC_BUCK_VGPU_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VGPU_VOSEL, + MT6351_PMIC_DA_NI_VGPU_VOSEL_SYNC, + MT6351_PMIC_BUCK_VGPU_TRANS_TD, + MT6351_PMIC_BUCK_VGPU_TRANS_CTRL, + MT6351_PMIC_BUCK_VGPU_TRANS_ONCE, + MT6351_PMIC_DA_QI_VGPU_DVS_EN, + MT6351_PMIC_BUCK_VGPU_VSLEEP_EN, + MT6351_PMIC_BUCK_VGPU_R2R_PDN, + MT6351_PMIC_BUCK_VGPU_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VGPU_R2R_PDN, + MT6351_PMIC_DA_NI_VGPU_VSLEEP_SEL, + MT6351_PMIC_BUCK_VMODEM_EN_CTRL, + MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL, + MT6351_PMIC_BUCK_VMODEM_EN_SEL, + MT6351_PMIC_BUCK_VMODEM_VOSEL_SEL, + MT6351_PMIC_BUCK_VMODEM_EN, + MT6351_PMIC_BUCK_VMODEM_STBTD, + MT6351_PMIC_DA_VMODEM_STB, + MT6351_PMIC_DA_QI_VMODEM_EN, + MT6351_PMIC_BUCK_VMODEM_SFCHG_FRATE, + MT6351_PMIC_BUCK_VMODEM_SFCHG_FEN, + MT6351_PMIC_BUCK_VMODEM_SFCHG_RRATE, + MT6351_PMIC_BUCK_VMODEM_SFCHG_REN, + MT6351_PMIC_BUCK_VMODEM_VOSEL, + MT6351_PMIC_BUCK_VMODEM_VOSEL_ON, + MT6351_PMIC_BUCK_VMODEM_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VMODEM_VOSEL, + MT6351_PMIC_DA_NI_VMODEM_VOSEL_SYNC, + MT6351_PMIC_BUCK_VMODEM_TRANS_TD, + MT6351_PMIC_BUCK_VMODEM_TRANS_CTRL, + MT6351_PMIC_BUCK_VMODEM_TRANS_ONCE, + MT6351_PMIC_DA_QI_VMODEM_DVS_EN, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN, + MT6351_PMIC_BUCK_VMODEM_R2R_PDN, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VMODEM_R2R_PDN, + MT6351_PMIC_DA_NI_VMODEM_VSLEEP_SEL, + MT6351_PMIC_BUCK_VMD1_EN_CTRL, + MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL, + MT6351_PMIC_BUCK_VMD1_EN_SEL, + MT6351_PMIC_BUCK_VMD1_VOSEL_SEL, + MT6351_PMIC_BUCK_VMD1_EN, + MT6351_PMIC_BUCK_VMD1_STBTD, + MT6351_PMIC_DA_VMD1_STB, + MT6351_PMIC_DA_QI_VMD1_EN, + MT6351_PMIC_BUCK_VMD1_SFCHG_FRATE, + MT6351_PMIC_BUCK_VMD1_SFCHG_FEN, + MT6351_PMIC_BUCK_VMD1_SFCHG_RRATE, + MT6351_PMIC_BUCK_VMD1_SFCHG_REN, + MT6351_PMIC_BUCK_VMD1_VOSEL, + MT6351_PMIC_BUCK_VMD1_VOSEL_ON, + MT6351_PMIC_BUCK_VMD1_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VMD1_VOSEL, + MT6351_PMIC_DA_NI_VMD1_VOSEL_SYNC, + MT6351_PMIC_BUCK_VMD1_TRANS_TD, + MT6351_PMIC_BUCK_VMD1_TRANS_CTRL, + MT6351_PMIC_BUCK_VMD1_TRANS_ONCE, + MT6351_PMIC_DA_QI_VMD1_DVS_EN, + MT6351_PMIC_BUCK_VMD1_VSLEEP_EN, + MT6351_PMIC_BUCK_VMD1_R2R_PDN, + MT6351_PMIC_BUCK_VMD1_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VMD1_R2R_PDN, + MT6351_PMIC_DA_NI_VMD1_VSLEEP_SEL, + MT6351_PMIC_BUCK_VSRAM_MD_EN_CTRL, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL, + MT6351_PMIC_BUCK_VSRAM_MD_EN_SEL, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SEL, + MT6351_PMIC_BUCK_VSRAM_MD_EN, + MT6351_PMIC_BUCK_VSRAM_MD_STBTD, + MT6351_PMIC_DA_VSRAM_MD_STB, + MT6351_PMIC_DA_QI_VSRAM_MD_EN, + MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FRATE, + MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FEN, + MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_RRATE, + MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_REN, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL, + MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC, + MT6351_PMIC_BUCK_VSRAM_MD_TRANS_TD, + MT6351_PMIC_BUCK_VSRAM_MD_TRANS_CTRL, + MT6351_PMIC_BUCK_VSRAM_MD_TRANS_ONCE, + MT6351_PMIC_DA_QI_VSRAM_MD_DVS_EN, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN, + MT6351_PMIC_BUCK_VSRAM_MD_R2R_PDN, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VSRAM_MD_R2R_PDN, + MT6351_PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL, + MT6351_PMIC_BUCK_VS1_EN_CTRL, + MT6351_PMIC_BUCK_VS1_VOSEL_CTRL, + MT6351_PMIC_BUCK_VS1_EN_SEL, + MT6351_PMIC_BUCK_VS1_VOSEL_SEL, + MT6351_PMIC_BUCK_VS1_EN, + MT6351_PMIC_BUCK_VS1_STBTD, + MT6351_PMIC_DA_VS1_STB, + MT6351_PMIC_DA_QI_VS1_EN, + MT6351_PMIC_BUCK_VS1_SFCHG_FRATE, + MT6351_PMIC_BUCK_VS1_SFCHG_FEN, + MT6351_PMIC_BUCK_VS1_SFCHG_RRATE, + MT6351_PMIC_BUCK_VS1_SFCHG_REN, + MT6351_PMIC_BUCK_VS1_VOSEL, + MT6351_PMIC_BUCK_VS1_VOSEL_ON, + MT6351_PMIC_BUCK_VS1_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VS1_VOSEL, + MT6351_PMIC_DA_NI_VS1_VOSEL_SYNC, + MT6351_PMIC_BUCK_VS1_TRANS_TD, + MT6351_PMIC_BUCK_VS1_TRANS_CTRL, + MT6351_PMIC_BUCK_VS1_TRANS_ONCE, + MT6351_PMIC_DA_QI_VS1_DVS_EN, + MT6351_PMIC_BUCK_VS1_VSLEEP_EN, + MT6351_PMIC_BUCK_VS1_R2R_PDN, + MT6351_PMIC_BUCK_VS1_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VS1_R2R_PDN, + MT6351_PMIC_DA_NI_VS1_VSLEEP_SEL, + MT6351_PMIC_BUCK_VS2_EN_CTRL, + MT6351_PMIC_BUCK_VS2_VOSEL_CTRL, + MT6351_PMIC_BUCK_VS2_EN_SEL, + MT6351_PMIC_BUCK_VS2_VOSEL_SEL, + MT6351_PMIC_BUCK_VS2_EN, + MT6351_PMIC_BUCK_VS2_STBTD, + MT6351_PMIC_DA_VS2_STB, + MT6351_PMIC_DA_QI_VS2_EN, + MT6351_PMIC_BUCK_VS2_SFCHG_FRATE, + MT6351_PMIC_BUCK_VS2_SFCHG_FEN, + MT6351_PMIC_BUCK_VS2_SFCHG_RRATE, + MT6351_PMIC_BUCK_VS2_SFCHG_REN, + MT6351_PMIC_BUCK_VS2_VOSEL, + MT6351_PMIC_BUCK_VS2_VOSEL_ON, + MT6351_PMIC_BUCK_VS2_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VS2_VOSEL, + MT6351_PMIC_DA_NI_VS2_VOSEL_SYNC, + MT6351_PMIC_BUCK_VS2_TRANS_TD, + MT6351_PMIC_BUCK_VS2_TRANS_CTRL, + MT6351_PMIC_BUCK_VS2_TRANS_ONCE, + MT6351_PMIC_DA_QI_VS2_DVS_EN, + MT6351_PMIC_BUCK_VS2_VSLEEP_EN, + MT6351_PMIC_BUCK_VS2_R2R_PDN, + MT6351_PMIC_BUCK_VS2_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VS2_R2R_PDN, + MT6351_PMIC_DA_NI_VS2_VSLEEP_SEL, + MT6351_PMIC_BUCK_VPA_EN_CTRL, + MT6351_PMIC_BUCK_VPA_VOSEL_CTRL, + MT6351_PMIC_BUCK_VPA_EN_SEL, + MT6351_PMIC_BUCK_VPA_VOSEL_SEL, + MT6351_PMIC_BUCK_VPA_EN, + MT6351_PMIC_BUCK_VPA_STBTD, + MT6351_PMIC_DA_VPA_STB, + MT6351_PMIC_DA_QI_VPA_EN, + MT6351_PMIC_BUCK_VPA_SFCHG_FRATE, + MT6351_PMIC_BUCK_VPA_SFCHG_FEN, + MT6351_PMIC_BUCK_VPA_SFCHG_RRATE, + MT6351_PMIC_BUCK_VPA_SFCHG_REN, + MT6351_PMIC_BUCK_VPA_VOSEL, + MT6351_PMIC_BUCK_VPA_VOSEL_ON, + MT6351_PMIC_BUCK_VPA_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VPA_VOSEL_GRAY, + MT6351_PMIC_DA_NI_VPA_VOSEL_SYNC, + MT6351_PMIC_BUCK_VPA_TRANS_TD, + MT6351_PMIC_BUCK_VPA_TRANS_CTRL, + MT6351_PMIC_BUCK_VPA_TRANS_ONCE, + MT6351_PMIC_DA_QI_VPA_DVS_EN, + MT6351_PMIC_BUCK_VPA_VSLEEP_EN, + MT6351_PMIC_BUCK_VPA_R2R_PDN, + MT6351_PMIC_BUCK_VPA_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VPA_R2R_PDN, + MT6351_PMIC_DA_NI_VPA_VSLEEP_SEL, + MT6351_PMIC_BUCK_VSRAM_PROC_EN_CTRL, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL, + MT6351_PMIC_BUCK_VSRAM_PROC_EN_SEL, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SEL, + MT6351_PMIC_BUCK_VSRAM_PROC_EN, + MT6351_PMIC_BUCK_VSRAM_PROC_STBTD, + MT6351_PMIC_DA_VSRAM_PROC_STB, + MT6351_PMIC_DA_QI_VSRAM_PROC_EN_RSV, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FEN, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_REN, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP, + MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL, + MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC, + MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_TD, + MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_CTRL, + MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_ONCE, + MT6351_PMIC_DA_QI_VSRAM_PROC_DVS_EN, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN, + MT6351_PMIC_BUCK_VSRAM_PROC_R2R_PDN, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL, + MT6351_PMIC_DA_NI_VSRAM_PROC_R2R_PDN, + MT6351_PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL, + MT6351_PMIC_BUCK_K_RST_DONE, + MT6351_PMIC_BUCK_K_MAP_SEL, + MT6351_PMIC_BUCK_K_ONCE_EN, + MT6351_PMIC_BUCK_K_ONCE, + MT6351_PMIC_BUCK_K_START_MANUAL, + MT6351_PMIC_BUCK_K_SRC_SEL, + MT6351_PMIC_BUCK_K_AUTO_EN, + MT6351_PMIC_BUCK_K_INV, + MT6351_PMIC_BUCK_K_CONTROL_SMPS, + MT6351_PMIC_K_RESULT, + MT6351_PMIC_K_DONE, + MT6351_PMIC_K_CONTROL, + MT6351_PMIC_DA_QI_SMPS_OSC_CAL, + MT6351_PMIC_BUCK_K_BUCK_CK_CNT, + MT6351_PMIC_WDTDBG_CLR, + MT6351_PMIC_WDTDBG_CON0_RSV0, + MT6351_PMIC_VGPU_VOSEL_WDTDBG, + MT6351_PMIC_VCORE_VOSEL_WDTDBG, + MT6351_PMIC_VMD1_VOSEL_WDTDBG, + MT6351_PMIC_VMODEM_VOSEL_WDTDBG, + MT6351_PMIC_VSRAM_PROC_VOSEL_WDTDBG, + MT6351_PMIC_VSRAM_MD_VOSEL_WDTDBG, + MT6351_PMIC_RG_AUDZCDENABLE, + MT6351_PMIC_RG_AUDZCDGAINSTEPTIME, + MT6351_PMIC_RG_AUDZCDGAINSTEPSIZE, + MT6351_PMIC_RG_AUDZCDTIMEOUTMODESEL, + MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP15, + MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP15, + MT6351_PMIC_RG_AUDLOLGAIN, + MT6351_PMIC_RG_AUDLORGAIN, + MT6351_PMIC_RG_AUDHPLGAIN, + MT6351_PMIC_RG_AUDHPRGAIN, + MT6351_PMIC_RG_AUDHSGAIN, + MT6351_PMIC_RG_AUDIVLGAIN, + MT6351_PMIC_RG_AUDIVRGAIN, + MT6351_PMIC_RG_AUDINTGAIN1, + MT6351_PMIC_RG_AUDINTGAIN2, + MT6351_PMIC_RG_A_TRIM_EN, + MT6351_PMIC_RG_A_TRIM_SEL, + MT6351_PMIC_RG_A_ISINKS_RSV, + MT6351_PMIC_RG_B_TRIM_EN, + MT6351_PMIC_RG_B_TRIM_SEL, + MT6351_PMIC_RG_B_ISINKS_RSV, + MT6351_PMIC_ISINK_DIM0_FSEL, + MT6351_PMIC_ISINK0_RSV1, + MT6351_PMIC_ISINK0_RSV0, + MT6351_PMIC_ISINK_DIM0_DUTY, + MT6351_PMIC_ISINK_CH0_STEP, + MT6351_PMIC_ISINK_BREATH0_TF2_SEL, + MT6351_PMIC_ISINK_BREATH0_TF1_SEL, + MT6351_PMIC_ISINK_BREATH0_TR2_SEL, + MT6351_PMIC_ISINK_BREATH0_TR1_SEL, + MT6351_PMIC_ISINK_BREATH0_TOFF_SEL, + MT6351_PMIC_ISINK_BREATH0_TON_SEL, + MT6351_PMIC_ISINK_DIM1_FSEL, + MT6351_PMIC_ISINK1_RSV1, + MT6351_PMIC_ISINK1_RSV0, + MT6351_PMIC_ISINK_DIM1_DUTY, + MT6351_PMIC_ISINK_CH1_STEP, + MT6351_PMIC_ISINK_BREATH1_TF2_SEL, + MT6351_PMIC_ISINK_BREATH1_TF1_SEL, + MT6351_PMIC_ISINK_BREATH1_TR2_SEL, + MT6351_PMIC_ISINK_BREATH1_TR1_SEL, + MT6351_PMIC_ISINK_BREATH1_TOFF_SEL, + MT6351_PMIC_ISINK_BREATH1_TON_SEL, + MT6351_PMIC_ISINK_DIM4_FSEL, + MT6351_PMIC_ISINK4_RSV1, + MT6351_PMIC_ISINK4_RSV0, + MT6351_PMIC_ISINK_DIM4_DUTY, + MT6351_PMIC_ISINK_CH4_STEP, + MT6351_PMIC_ISINK_BREATH4_TF2_SEL, + MT6351_PMIC_ISINK_BREATH4_TF1_SEL, + MT6351_PMIC_ISINK_BREATH4_TR2_SEL, + MT6351_PMIC_ISINK_BREATH4_TR1_SEL, + MT6351_PMIC_ISINK_BREATH4_TOFF_SEL, + MT6351_PMIC_ISINK_BREATH4_TON_SEL, + MT6351_PMIC_ISINK_DIM5_FSEL, + MT6351_PMIC_ISINK5_RSV1, + MT6351_PMIC_ISINK5_RSV0, + MT6351_PMIC_ISINK_DIM5_DUTY, + MT6351_PMIC_ISINK_CH5_STEP, + MT6351_PMIC_ISINK_BREATH5_TF2_SEL, + MT6351_PMIC_ISINK_BREATH5_TF1_SEL, + MT6351_PMIC_ISINK_BREATH5_TR2_SEL, + MT6351_PMIC_ISINK_BREATH5_TR1_SEL, + MT6351_PMIC_ISINK_BREATH5_TOFF_SEL, + MT6351_PMIC_ISINK_BREATH5_TON_SEL, + MT6351_PMIC_AD_NI_B_ISINK1_STATUS, + MT6351_PMIC_AD_NI_B_ISINK0_STATUS, + MT6351_PMIC_AD_NI_A_ISINK1_STATUS, + MT6351_PMIC_AD_NI_A_ISINK0_STATUS, + MT6351_PMIC_ISINK_PHASE0_DLY_EN, + MT6351_PMIC_ISINK_PHASE1_DLY_EN, + MT6351_PMIC_ISINK_PHASE4_DLY_EN, + MT6351_PMIC_ISINK_PHASE5_DLY_EN, + MT6351_PMIC_ISINK_PHASE_DLY_TC, + MT6351_PMIC_ISINK_CHOP0_SW, + MT6351_PMIC_ISINK_CHOP1_SW, + MT6351_PMIC_ISINK_CHOP4_SW, + MT6351_PMIC_ISINK_CHOP5_SW, + MT6351_PMIC_ISINK_SFSTR5_EN, + MT6351_PMIC_ISINK_SFSTR5_TC, + MT6351_PMIC_ISINK_SFSTR4_EN, + MT6351_PMIC_ISINK_SFSTR4_TC, + MT6351_PMIC_ISINK_SFSTR1_EN, + MT6351_PMIC_ISINK_SFSTR1_TC, + MT6351_PMIC_ISINK_SFSTR0_EN, + MT6351_PMIC_ISINK_SFSTR0_TC, + MT6351_PMIC_ISINK_CH0_EN, + MT6351_PMIC_ISINK_CH1_EN, + MT6351_PMIC_ISINK_CH4_EN, + MT6351_PMIC_ISINK_CH5_EN, + MT6351_PMIC_ISINK_CHOP0_EN, + MT6351_PMIC_ISINK_CHOP1_EN, + MT6351_PMIC_ISINK_CHOP4_EN, + MT6351_PMIC_ISINK_CHOP5_EN, + MT6351_PMIC_ISINK_CH0_BIAS_EN, + MT6351_PMIC_ISINK_CH1_BIAS_EN, + MT6351_PMIC_ISINK_CH4_BIAS_EN, + MT6351_PMIC_ISINK_CH5_BIAS_EN, + MT6351_PMIC_ISINK_RSV, + MT6351_PMIC_ISINK_CH5_MODE, + MT6351_PMIC_ISINK_CH4_MODE, + MT6351_PMIC_ISINK_CH1_MODE, + MT6351_PMIC_ISINK_CH0_MODE, + MT6351_PMIC_DA_QI_A_ISINKS_CH0_STEP, + MT6351_PMIC_DA_QI_A_ISINKS_CH1_STEP, + MT6351_PMIC_DA_QI_B_ISINKS_CH0_STEP, + MT6351_PMIC_DA_QI_B_ISINKS_CH1_STEP, + MT6351_PMIC_ISINK2_RSV1, + MT6351_PMIC_ISINK2_RSV0, + MT6351_PMIC_ISINK_CH2_STEP, + MT6351_PMIC_ISINK3_RSV1, + MT6351_PMIC_ISINK3_RSV0, + MT6351_PMIC_ISINK_CH3_STEP, + MT6351_PMIC_ISINK6_RSV1, + MT6351_PMIC_ISINK6_RSV0, + MT6351_PMIC_ISINK_CH6_STEP, + MT6351_PMIC_ISINK7_RSV1, + MT6351_PMIC_ISINK7_RSV0, + MT6351_PMIC_ISINK_CH7_STEP, + MT6351_PMIC_AD_NI_B_ISINK3_STATUS, + MT6351_PMIC_AD_NI_B_ISINK2_STATUS, + MT6351_PMIC_AD_NI_A_ISINK3_STATUS, + MT6351_PMIC_AD_NI_A_ISINK2_STATUS, + MT6351_PMIC_ISINK_CHOP7_SW, + MT6351_PMIC_ISINK_CHOP6_SW, + MT6351_PMIC_ISINK_CHOP3_SW, + MT6351_PMIC_ISINK_CHOP2_SW, + MT6351_PMIC_ISINK_CH7_EN, + MT6351_PMIC_ISINK_CH6_EN, + MT6351_PMIC_ISINK_CH3_EN, + MT6351_PMIC_ISINK_CH2_EN, + MT6351_PMIC_ISINK_CHOP7_EN, + MT6351_PMIC_ISINK_CHOP6_EN, + MT6351_PMIC_ISINK_CHOP3_EN, + MT6351_PMIC_ISINK_CHOP2_EN, + MT6351_PMIC_ISINK_CH7_BIAS_EN, + MT6351_PMIC_ISINK_CH6_BIAS_EN, + MT6351_PMIC_ISINK_CH3_BIAS_EN, + MT6351_PMIC_ISINK_CH2_BIAS_EN, + MT6351_PMIC_CHRIND_DIM_FSEL, + MT6351_PMIC_CHRIND_RSV1, + MT6351_PMIC_CHRIND_RSV0, + MT6351_PMIC_CHRIND_DIM_DUTY, + MT6351_PMIC_CHRIND_STEP, + MT6351_PMIC_CHRIND_BREATH_TF2_SEL, + MT6351_PMIC_CHRIND_BREATH_TF1_SEL, + MT6351_PMIC_CHRIND_BREATH_TR2_SEL, + MT6351_PMIC_CHRIND_BREATH_TR1_SEL, + MT6351_PMIC_CHRIND_BREATH_TOFF_SEL, + MT6351_PMIC_CHRIND_BREATH_TON_SEL, + MT6351_PMIC_CHRIND_SFSTR_EN, + MT6351_PMIC_CHRIND_SFSTR_TC, + MT6351_PMIC_CHRIND_EN_SEL, + MT6351_PMIC_CHRIND_EN, + MT6351_PMIC_CHRIND_CHOP_EN, + MT6351_PMIC_CHRIND_MODE, + MT6351_PMIC_CHRIND_CHOP_SW, + MT6351_PMIC_CHRIND_BIAS_EN, + MT6351_PMIC_RG_VA18_MODE_SET, + MT6351_PMIC_RG_VA18_EN, + MT6351_PMIC_RG_VA18_MODE_CTRL, + MT6351_PMIC_RG_VA18_ON_CTRL, + MT6351_PMIC_RG_VA18_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VA18_MODE, + MT6351_PMIC_RG_VA18_STBTD, + MT6351_PMIC_RG_VA18_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VA18_STB, + MT6351_PMIC_DA_QI_VA18_EN, + MT6351_PMIC_RG_VA18_AUXADC_PWDB_EN, + MT6351_PMIC_RG_VA18_OCFB_EN, + MT6351_PMIC_DA_QI_VA18_OCFB_EN, + MT6351_PMIC_RG_VTCXO24_MODE_SET, + MT6351_PMIC_RG_VTCXO24_EN, + MT6351_PMIC_RG_VTCXO24_MODE_CTRL, + MT6351_PMIC_RG_VTCXO24_ON_CTRL, + MT6351_PMIC_RG_VTCXO24_SWITCH, + MT6351_PMIC_RG_VTCXO24_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VTCXO24_MODE, + MT6351_PMIC_RG_VTCXO24_STBTD, + MT6351_PMIC_RG_VTCXO24_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VTCXO24_STB, + MT6351_PMIC_DA_QI_VTCXO24_EN, + MT6351_PMIC_RG_VTCXO24_OCFB_EN, + MT6351_PMIC_DA_QI_VTCXO24_OCFB_EN, + MT6351_PMIC_RG_VTCXO28_MODE_SET, + MT6351_PMIC_RG_VTCXO28_EN, + MT6351_PMIC_RG_VTCXO28_MODE_CTRL, + MT6351_PMIC_RG_VTCXO28_ON_CTRL, + MT6351_PMIC_RG_VTCXO28_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VTCXO28_MODE, + MT6351_PMIC_RG_VTCXO28_STBTD, + MT6351_PMIC_RG_VTCXO28_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VTCXO28_STB, + MT6351_PMIC_DA_QI_VTCXO28_EN, + MT6351_PMIC_RG_VTCXO28_OCFB_EN, + MT6351_PMIC_DA_QI_VTCXO28_OCFB_EN, + MT6351_PMIC_RG_VCN28_MODE_SET, + MT6351_PMIC_RG_VCN28_EN, + MT6351_PMIC_RG_VCN28_MODE_CTRL, + MT6351_PMIC_RG_VCN28_ON_CTRL, + MT6351_PMIC_RG_VCN28_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VCN28_MODE, + MT6351_PMIC_RG_VCN28_STBTD, + MT6351_PMIC_RG_VCN28_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VCN28_STB, + MT6351_PMIC_DA_QI_VCN28_EN, + MT6351_PMIC_RG_VCN28_OCFB_EN, + MT6351_PMIC_DA_QI_VCN28_OCFB_EN, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VCN28_DUMMY_LOAD, + MT6351_PMIC_RG_VCAMA_EN, + MT6351_PMIC_RG_VCAMA_ON_CTRL, + MT6351_PMIC_RG_VCAMA_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VCAMA_MODE, + MT6351_PMIC_RG_VCAMA_STBTD, + MT6351_PMIC_RG_VCAMA_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VCAMA_STB, + MT6351_PMIC_DA_QI_VCAMA_EN, + MT6351_PMIC_RG_VCAMA_OCFB_EN, + MT6351_PMIC_DA_QI_VCAMA_OCFB_EN, + MT6351_PMIC_RG_VUSB33_MODE_SET, + MT6351_PMIC_RG_VUSB33_EN, + MT6351_PMIC_RG_VUSB33_MODE_CTRL, + MT6351_PMIC_RG_VUSB33_ON_CTRL, + MT6351_PMIC_RG_VUSB33_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VUSB33_MODE, + MT6351_PMIC_RG_VUSB33_STBTD, + MT6351_PMIC_RG_VUSB33_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VUSB33_STB, + MT6351_PMIC_DA_QI_VUSB33_EN, + MT6351_PMIC_RG_VUSB33_OCFB_EN, + MT6351_PMIC_DA_QI_VUSB33_OCFB_EN, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VUSB33_DUMMY_LOAD, + MT6351_PMIC_RG_VSIM1_MODE_SET, + MT6351_PMIC_RG_VSIM1_EN, + MT6351_PMIC_RG_VSIM1_MODE_CTRL, + MT6351_PMIC_RG_VSIM1_ON_CTRL, + MT6351_PMIC_RG_VSIM1_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VSIM1_MODE, + MT6351_PMIC_RG_VSIM1_STBTD, + MT6351_PMIC_RG_VSIM1_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VSIM1_STB, + MT6351_PMIC_DA_QI_VSIM1_EN, + MT6351_PMIC_RG_VSIM1_OCFB_EN, + MT6351_PMIC_DA_QI_VSIM1_OCFB_EN, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VSIM1_DUMMY_LOAD, + MT6351_PMIC_RG_VSIM2_MODE_SET, + MT6351_PMIC_RG_VSIM2_EN, + MT6351_PMIC_RG_VSIM2_MODE_CTRL, + MT6351_PMIC_RG_VSIM2_ON_CTRL, + MT6351_PMIC_RG_VSIM2_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VSIM2_MODE, + MT6351_PMIC_RG_VSIM2_STBTD, + MT6351_PMIC_RG_VSIM2_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VSIM2_STB, + MT6351_PMIC_DA_QI_VSIM2_EN, + MT6351_PMIC_RG_VSIM2_OCFB_EN, + MT6351_PMIC_DA_QI_VSIM2_OCFB_EN, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VSIM2_DUMMY_LOAD, + MT6351_PMIC_RG_VEMC_MODE_SET, + MT6351_PMIC_RG_VEMC_EN, + MT6351_PMIC_RG_VEMC_MODE_CTRL, + MT6351_PMIC_RG_VEMC_ON_CTRL, + MT6351_PMIC_RG_VEMC_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VEMC_MODE, + MT6351_PMIC_RG_VEMC_STBTD, + MT6351_PMIC_RG_VEMC_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VEMC_STB, + MT6351_PMIC_DA_QI_VEMC_EN, + MT6351_PMIC_RG_VEMC_OCFB_EN, + MT6351_PMIC_DA_QI_VEMC_OCFB_EN, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VEMC_DUMMY_LOAD, + MT6351_PMIC_RG_VMCH_MODE_SET, + MT6351_PMIC_RG_VMCH_EN, + MT6351_PMIC_RG_VMCH_MODE_CTRL, + MT6351_PMIC_RG_VMCH_ON_CTRL, + MT6351_PMIC_RG_VMCH_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VMCH_MODE, + MT6351_PMIC_RG_VMCH_STBTD, + MT6351_PMIC_RG_VMCH_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VMCH_STB, + MT6351_PMIC_DA_QI_VMCH_EN, + MT6351_PMIC_RG_VMCH_OCFB_EN, + MT6351_PMIC_DA_QI_VMCH_OCFB_EN, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VMCH_DUMMY_LOAD, + MT6351_PMIC_RG_VIO28_MODE_SET, + MT6351_PMIC_RG_VIO28_EN, + MT6351_PMIC_RG_VIO28_MODE_CTRL, + MT6351_PMIC_RG_VIO28_ON_CTRL, + MT6351_PMIC_RG_VIO28_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VIO28_MODE, + MT6351_PMIC_RG_VIO28_STBTD, + MT6351_PMIC_RG_VIO28_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VIO28_STB, + MT6351_PMIC_DA_QI_VIO28_EN, + MT6351_PMIC_RG_VIO28_OCFB_EN, + MT6351_PMIC_DA_QI_VIO28_OCFB_EN, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VIO28_DUMMY_LOAD, + MT6351_PMIC_RG_VIBR_MODE_SET, + MT6351_PMIC_RG_VIBR_EN, + MT6351_PMIC_RG_VIBR_MODE_CTRL, + MT6351_PMIC_RG_VIBR_ON_CTRL, + MT6351_PMIC_RG_VIBR_THER_SDN_EN, + MT6351_PMIC_RG_VIBR_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VIBR_MODE, + MT6351_PMIC_RG_VIBR_STBTD, + MT6351_PMIC_RG_VIBR_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VIBR_STB, + MT6351_PMIC_DA_QI_VIBR_EN, + MT6351_PMIC_RG_VIBR_OCFB_EN, + MT6351_PMIC_DA_QI_VIBR_OCFB_EN, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VIBR_DUMMY_LOAD, + MT6351_PMIC_RG_VCAMD_MODE_SET, + MT6351_PMIC_RG_VCAMD_EN, + MT6351_PMIC_RG_VCAMD_MODE_CTRL, + MT6351_PMIC_RG_VCAMD_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VCAMD_MODE, + MT6351_PMIC_RG_VCAMD_STBTD, + MT6351_PMIC_DA_QI_VCAMD_STB, + MT6351_PMIC_DA_QI_VCAMD_EN, + MT6351_PMIC_RG_VCAMD_OCFB_EN, + MT6351_PMIC_DA_QI_VCAMD_OCFB_EN, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VCAMD_DUMMY_LOAD, + MT6351_PMIC_RG_VRF18_MODE_SET, + MT6351_PMIC_RG_VRF18_EN, + MT6351_PMIC_RG_VRF18_MODE_CTRL, + MT6351_PMIC_RG_VRF18_ON_CTRL, + MT6351_PMIC_RG_VRF18_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VRF18_MODE, + MT6351_PMIC_RG_VRF18_STBTD, + MT6351_PMIC_RG_VRF18_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VRF18_STB, + MT6351_PMIC_DA_QI_VRF18_EN, + MT6351_PMIC_RG_VRF18_OCFB_EN, + MT6351_PMIC_DA_QI_VRF18_OCFB_EN, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VRF18_DUMMY_LOAD, + MT6351_PMIC_RG_VIO18_MODE_SET, + MT6351_PMIC_RG_VIO18_EN, + MT6351_PMIC_RG_VIO18_MODE_CTRL, + MT6351_PMIC_RG_VIO18_ON_CTRL, + MT6351_PMIC_RG_VIO18_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VIO18_MODE, + MT6351_PMIC_RG_VIO18_STBTD, + MT6351_PMIC_RG_VIO18_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VIO18_STB, + MT6351_PMIC_DA_QI_VIO18_EN, + MT6351_PMIC_RG_VIO18_OCFB_EN, + MT6351_PMIC_DA_QI_VIO18_OCFB_EN, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VIO18_DUMMY_LOAD, + MT6351_PMIC_RG_VCN18_MODE_SET, + MT6351_PMIC_RG_VCN18_EN, + MT6351_PMIC_RG_VCN18_MODE_CTRL, + MT6351_PMIC_RG_VCN18_ON_CTRL, + MT6351_PMIC_RG_VCN18_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VCN18_MODE, + MT6351_PMIC_RG_VCN18_STBTD, + MT6351_PMIC_RG_VCN18_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VCN18_STB, + MT6351_PMIC_DA_QI_VCN18_EN, + MT6351_PMIC_RG_VCN18_OCFB_EN, + MT6351_PMIC_DA_QI_VCN18_OCFB_EN, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VCN18_DUMMY_LOAD, + MT6351_PMIC_RG_VCAMIO_MODE_SET, + MT6351_PMIC_RG_VCAMIO_EN, + MT6351_PMIC_RG_VCAMIO_MODE_CTRL, + MT6351_PMIC_RG_VCAMIO_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VCAMIO_MODE, + MT6351_PMIC_RG_VCAMIO_STBTD, + MT6351_PMIC_DA_QI_VCAMIO_STB, + MT6351_PMIC_DA_QI_VCAMIO_EN, + MT6351_PMIC_RG_VCAMIO_OCFB_EN, + MT6351_PMIC_DA_QI_VCAMIO_OCFB_EN, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VCAMIO_DUMMY_LOAD, + MT6351_PMIC_RG_VSRAM_PROC_MODE_SET, + MT6351_PMIC_RG_VSRAM_PROC_EN, + MT6351_PMIC_RG_VSRAM_PROC_MODE_CTRL, + MT6351_PMIC_RG_VSRAM_PROC_ON_CTRL, + MT6351_PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VSRAM_PROC_MODE, + MT6351_PMIC_RG_VSRAM_PROC_STBTD, + MT6351_PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VSRAM_PROC_STB, + MT6351_PMIC_DA_QI_VSRAM_PROC_EN, + MT6351_PMIC_RG_VSRAM_PROC_OCFB_EN, + MT6351_PMIC_DA_QI_VSRAM_PROC_OCFB_EN, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD, + MT6351_PMIC_RG_VXO22_MODE_SET, + MT6351_PMIC_RG_VXO22_EN, + MT6351_PMIC_RG_VXO22_MODE_CTRL, + MT6351_PMIC_RG_VXO22_ON_CTRL, + MT6351_PMIC_RG_VXO22_SWITCH, + MT6351_PMIC_RG_VXO22_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VXO22_MODE, + MT6351_PMIC_RG_VXO22_STBTD, + MT6351_PMIC_RG_VXO22_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VXO22_STB, + MT6351_PMIC_DA_QI_VXO22_EN, + MT6351_PMIC_RG_VXO22_OCFB_EN, + MT6351_PMIC_DA_QI_VXO22_OCFB_EN, + MT6351_PMIC_RG_VRF12_MODE_SET, + MT6351_PMIC_RG_VRF12_EN, + MT6351_PMIC_RG_VRF12_MODE_CTRL, + MT6351_PMIC_RG_VRF12_ON_CTRL, + MT6351_PMIC_RG_VRF12_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VRF12_MODE, + MT6351_PMIC_RG_VRF12_STBTD, + MT6351_PMIC_RG_VRF12_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VRF12_STB, + MT6351_PMIC_DA_QI_VRF12_EN, + MT6351_PMIC_RG_VRF12_OCFB_EN, + MT6351_PMIC_DA_QI_VRF12_OCFB_EN, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VRF12_DUMMY_LOAD, + MT6351_PMIC_RG_VA10_MODE_SET, + MT6351_PMIC_RG_VA10_EN, + MT6351_PMIC_RG_VA10_MODE_CTRL, + MT6351_PMIC_RG_VA10_ON_CTRL, + MT6351_PMIC_RG_VA10_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VA10_MODE, + MT6351_PMIC_RG_VA10_STBTD, + MT6351_PMIC_RG_VA10_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VA10_STB, + MT6351_PMIC_DA_QI_VA10_EN, + MT6351_PMIC_RG_VA10_OCFB_EN, + MT6351_PMIC_DA_QI_VA10_OCFB_EN, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VA10_DUMMY_LOAD, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VA10_DUMMY_LOAD, + MT6351_PMIC_RG_VDRAM_MODE_SET, + MT6351_PMIC_RG_VDRAM_EN, + MT6351_PMIC_RG_VDRAM_MODE_CTRL, + MT6351_PMIC_RG_VDRAM_ON_CTRL, + MT6351_PMIC_RG_VDRAM_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VDRAM_MODE, + MT6351_PMIC_RG_VDRAM_STBTD, + MT6351_PMIC_RG_VDRAM_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VDRAM_STB, + MT6351_PMIC_DA_QI_VDRAM_EN, + MT6351_PMIC_RG_VDRAM_OCFB_EN, + MT6351_PMIC_DA_QI_VDRAM_OCFB_EN, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VDRAM_DUMMY_LOAD, + MT6351_PMIC_RG_VMIPI_MODE_SET, + MT6351_PMIC_RG_VMIPI_EN, + MT6351_PMIC_RG_VMIPI_MODE_CTRL, + MT6351_PMIC_RG_VMIPI_ON_CTRL, + MT6351_PMIC_RG_VMIPI_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VMIPI_MODE, + MT6351_PMIC_RG_VMIPI_STBTD, + MT6351_PMIC_RG_VMIPI_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VMIPI_STB, + MT6351_PMIC_DA_QI_VMIPI_EN, + MT6351_PMIC_RG_VMIPI_OCFB_EN, + MT6351_PMIC_DA_QI_VMIPI_OCFB_EN, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VMIPI_DUMMY_LOAD, + MT6351_PMIC_RG_VGP3_MODE_SET, + MT6351_PMIC_RG_VGP3_EN, + MT6351_PMIC_RG_VGP3_MODE_CTRL, + MT6351_PMIC_RG_VGP3_ON_CTRL, + MT6351_PMIC_RG_VGP3_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VGP3_MODE, + MT6351_PMIC_RG_VGP3_STBTD, + MT6351_PMIC_RG_VGP3_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VGP3_STB, + MT6351_PMIC_DA_QI_VGP3_EN, + MT6351_PMIC_RG_VGP3_OCFB_EN, + MT6351_PMIC_DA_QI_VGP3_OCFB_EN, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VGP3_DUMMY_LOAD, + MT6351_PMIC_RG_VBIF28_MODE_SET, + MT6351_PMIC_RG_VBIF28_EN, + MT6351_PMIC_RG_VBIF28_MODE_CTRL, + MT6351_PMIC_RG_VBIF28_ON_CTRL, + MT6351_PMIC_RG_VBIF28_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VBIF28_MODE, + MT6351_PMIC_RG_VBIF28_STBTD, + MT6351_PMIC_RG_VBIF28_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VBIF28_STB, + MT6351_PMIC_DA_QI_VBIF28_EN, + MT6351_PMIC_RG_VBIF28_OCFB_EN, + MT6351_PMIC_DA_QI_VBIF28_OCFB_EN, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VBIF28_DUMMY_LOAD, + MT6351_PMIC_RG_VEFUSE_MODE_SET, + MT6351_PMIC_RG_VEFUSE_EN, + MT6351_PMIC_RG_VEFUSE_MODE_CTRL, + MT6351_PMIC_RG_VEFUSE_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VEFUSE_MODE, + MT6351_PMIC_RG_VEFUSE_STBTD, + MT6351_PMIC_DA_QI_VEFUSE_STB, + MT6351_PMIC_DA_QI_VEFUSE_EN, + MT6351_PMIC_RG_VEFUSE_OCFB_EN, + MT6351_PMIC_DA_QI_VEFUSE_OCFB_EN, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VEFUSE_DUMMY_LOAD, + MT6351_PMIC_RG_VCN33_MODE_SET, + MT6351_PMIC_RG_VCN33_MODE_CTRL, + MT6351_PMIC_RG_VCN33_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VCN33_MODE, + MT6351_PMIC_RG_VCN33_STBTD, + MT6351_PMIC_DA_QI_VCN33_STB, + MT6351_PMIC_DA_QI_VCN33_EN, + MT6351_PMIC_RG_VCN33_OCFB_EN, + MT6351_PMIC_DA_QI_VCN33_OCFB_EN, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VCN33_DUMMY_LOAD, + MT6351_PMIC_RG_VCN33_EN_BT, + MT6351_PMIC_RG_VCN33_ON_CTRL_BT, + MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_BT, + MT6351_PMIC_RG_VCN33_EN_WIFI, + MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI, + MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI, + MT6351_PMIC_RG_VLDO28_MODE_SET, + MT6351_PMIC_RG_VLDO28_MODE_CTRL, + MT6351_PMIC_RG_VLDO28_ON_CTRL, + MT6351_PMIC_RG_VLDO28_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VLDO28_MODE, + MT6351_PMIC_RG_VLDO28_STBTD, + MT6351_PMIC_DA_QI_VLDO28_STB, + MT6351_PMIC_DA_QI_VLDO28_EN, + MT6351_PMIC_RG_VLDO28_OCFB_EN, + MT6351_PMIC_DA_QI_VLDO28_OCFB_EN, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VLDO28_DUMMY_LOAD, + MT6351_PMIC_RG_VLDO28_EN_0, + MT6351_PMIC_RG_VLDO28_ON_CTRL_0, + MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_0, + MT6351_PMIC_RG_VLDO28_EN_1, + MT6351_PMIC_RG_VLDO28_ON_CTRL_1, + MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_1, + MT6351_PMIC_RG_LDO_RSV1, + MT6351_PMIC_RG_LDO_RSV0, + MT6351_PMIC_RG_LDO_RSV2, + MT6351_PMIC_RG_VMC_MODE_SET, + MT6351_PMIC_RG_VMC_EN, + MT6351_PMIC_RG_VMC_MODE_CTRL, + MT6351_PMIC_RG_VMC_ON_CTRL, + MT6351_PMIC_RG_VMC_SRCLK_MODE_SEL, + MT6351_PMIC_DA_QI_VMC_MODE, + MT6351_PMIC_RG_VMC_STBTD, + MT6351_PMIC_RG_VMC_SRCLK_EN_SEL, + MT6351_PMIC_DA_QI_VMC_STB, + MT6351_PMIC_DA_QI_VMC_EN, + MT6351_PMIC_RG_VMC_OCFB_EN, + MT6351_PMIC_DA_QI_VMC_OCFB_EN, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_EN, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VMC_DUMMY_LOAD, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_DA_QI_VMC_DUMMY_LOAD, + MT6351_PMIC_RG_VMC_TRANS_EN, + MT6351_PMIC_RG_VMC_TRANS_CTRL, + MT6351_PMIC_RG_VMC_TRANS_ONCE, + MT6351_PMIC_RG_VMC_INT_DIS_SEL, + MT6351_PMIC_DA_QI_VMC_INT_DIS, + MT6351_PMIC_RG_LDO_MANUAL_OFS_SEL, + MT6351_PMIC_RG_LDO_MANUAL_OFS_EN, + MT6351_PMIC_RG_LDO_CALI_RSV, + MT6351_PMIC_RG_LDO_CALI_MODE_SEL, + MT6351_PMIC_RG_LDO_MANUAL_MODE, + MT6351_PMIC_RG_LDO_AUTO_START, + MT6351_PMIC_RG_LDO_CALI_CLR, + MT6351_PMIC_LDO_CALI_INC_COUNT, + MT6351_PMIC_LDO_K_START, + MT6351_PMIC_LDO_CALI_DONE, + MT6351_PMIC_LDO_CALI_CNT, + MT6351_PMIC_LDO_CALI_EFUSE_EN, + MT6351_PMIC_DA_QI_VIO18_OFS_CAL_EN, + MT6351_PMIC_AD_QI_VIO18_CAL_INDI, + MT6351_PMIC_DA_QI_VIO18_OFS_SEL, + MT6351_PMIC_LDO_DEGTD_SEL, + MT6351_PMIC_RG_VRTC_EN, + MT6351_PMIC_DA_QI_VRTC_EN, + MT6351_PMIC_RG_ALDO_RESEV, + MT6351_PMIC_RG_DLDO_RESEV, + MT6351_PMIC_RG_SLDO_RESEV195, + MT6351_PMIC_RG_SLDO_2_RESEV195, + MT6351_PMIC_RG_SLDO_RESEV135, + MT6351_PMIC_RG_SLDO_2_RESEV135, + MT6351_PMIC_RG_VXO22_CAL, + MT6351_PMIC_RG_VXO22_VOSEL, + MT6351_PMIC_RG_VXO22_NDIS_EN, + MT6351_PMIC_RG_VTCXO28_CAL, + MT6351_PMIC_RG_VTCXO28_VOSEL, + MT6351_PMIC_RG_VTCXO28_NDIS_EN, + MT6351_PMIC_RG_VTCXO24_CAL, + MT6351_PMIC_RG_VTCXO24_VOSEL, + MT6351_PMIC_RG_VTCXO24_NDIS_EN, + MT6351_PMIC_RG_VBIF28_CAL, + MT6351_PMIC_RG_VBIF28_VOSEL, + MT6351_PMIC_RG_VBIF28_NDIS_EN, + MT6351_PMIC_RG_VCN28_CAL, + MT6351_PMIC_RG_VCN28_VOSEL, + MT6351_PMIC_RG_VCN28_NDIS_EN, + MT6351_PMIC_RG_VMCH_CAL, + MT6351_PMIC_RG_VMCH_VOSEL, + MT6351_PMIC_RG_VMCH_NDIS_EN, + MT6351_PMIC_RG_VMCH_OC_TRIM, + MT6351_PMIC_RG_VMCH_N2LP_EHC_V18, + MT6351_PMIC_RG_VEMC_CAL, + MT6351_PMIC_RG_VEMC_VOSEL, + MT6351_PMIC_RG_VEMC_NDIS_EN, + MT6351_PMIC_RG_VEMC_OC_TRIM, + MT6351_PMIC_RG_VEMC_N2LP_EHC_V18, + MT6351_PMIC_RG_VCAMA_CAL, + MT6351_PMIC_RG_VCAMA_VOSEL, + MT6351_PMIC_RG_VCAMA_NDIS_EN, + MT6351_PMIC_RG_VCAMA_FBSEL, + MT6351_PMIC_RG_VCN33_CAL, + MT6351_PMIC_RG_VCN33_VOSEL, + MT6351_PMIC_RG_VCN33_NDIS_EN, + MT6351_PMIC_RG_VCN33_N2LP_EHC_V18, + MT6351_PMIC_RG_VIO28_CAL, + MT6351_PMIC_RG_VIO28_VOSEL, + MT6351_PMIC_RG_VIO28_NDIS_EN, + MT6351_PMIC_RG_VIO28_LP_HIGH_SPEED_ENB, + MT6351_PMIC_RG_VMC_CAL, + MT6351_PMIC_RG_VMC_VOSEL, + MT6351_PMIC_RG_VMC_NDIS_EN, + MT6351_PMIC_RG_VMC_LP_HIGH_SPEED_ENB, + MT6351_PMIC_RG_VIBR_CAL, + MT6351_PMIC_RG_VIBR_VOSEL, + MT6351_PMIC_RG_VIBR_NDIS_EN, + MT6351_PMIC_RG_VIBR_LP_HIGH_SPEED_ENB, + MT6351_PMIC_RG_VUSB33_CAL, + MT6351_PMIC_RG_VUSB33_NDIS_EN, + MT6351_PMIC_RG_VUSB33_OC_TRIM, + MT6351_PMIC_RG_VSIM1_CAL, + MT6351_PMIC_RG_VSIM1_VOSEL, + MT6351_PMIC_RG_VSIM1_NDIS_EN, + MT6351_PMIC_RG_VSIM1_STB_CAL, + MT6351_PMIC_RG_VSIM1_STB_SEL, + MT6351_PMIC_RG_VSIM1_OC_TRIM, + MT6351_PMIC_RG_VSIM1_NDIS_EN_INT, + MT6351_PMIC_RG_EFUSE_SIM1_MODE, + MT6351_PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB, + MT6351_PMIC_RG_VSIM2_CAL, + MT6351_PMIC_RG_VSIM2_VOSEL, + MT6351_PMIC_RG_VSIM2_NDIS_EN, + MT6351_PMIC_RG_VSIM2_STB_CAL, + MT6351_PMIC_RG_VSIM2_STB_SEL, + MT6351_PMIC_RG_VSIM2_OC_TRIM, + MT6351_PMIC_RG_VSIM2_NDIS_EN_INT, + MT6351_PMIC_RG_EFUSE_VSIM2_MODE, + MT6351_PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB, + MT6351_PMIC_RG_VEFUSE_CAL, + MT6351_PMIC_RG_VEFUSE_VOSEL, + MT6351_PMIC_RG_VEFUSE_NDIS_EN, + MT6351_PMIC_RG_VEFUSE_STB_CAL, + MT6351_PMIC_RG_VEFUSE_STB_SEL, + MT6351_PMIC_RG_VEFUSE_OC_TRIM, + MT6351_PMIC_RG_VEFUSE_NDIS_EN_INT, + MT6351_PMIC_RG_EFUSE_MODE_1, + MT6351_PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB, + MT6351_PMIC_RG_VA18_CAL, + MT6351_PMIC_RG_VA18_VOSEL, + MT6351_PMIC_RG_VA18_NDIS_EN, + MT6351_PMIC_RG_VGP3_CAL, + MT6351_PMIC_RG_VGP3_VOSEL, + MT6351_PMIC_RG_VGP3_NDIS_EN, + MT6351_PMIC_RG_VGP3_FT_DNMC_EN, + MT6351_PMIC_RG_VCAMD_CAL, + MT6351_PMIC_RG_VCAMD_VOSEL, + MT6351_PMIC_RG_VCAMD_NDIS_EN, + MT6351_PMIC_RG_VCAMD_RSV, + MT6351_PMIC_RG_VCAMD_OC_TRIM, + MT6351_PMIC_RG_VIO18_CAL, + MT6351_PMIC_RG_VIO18_NDIS_EN, + MT6351_PMIC_RG_VIO18_FT_DNMC_EN, + MT6351_PMIC_RG_VRF18_CAL, + MT6351_PMIC_RG_VRF18_VOSEL, + MT6351_PMIC_RG_VRF18_NDIS_EN, + MT6351_PMIC_RG_VRF18_FT_DNMC_EN, + MT6351_PMIC_RG_VRF12_CAL, + MT6351_PMIC_RG_VRF12_VOSEL, + MT6351_PMIC_RG_VRF12_NDIS_EN, + MT6351_PMIC_RG_VRF12_STB_SEL, + MT6351_PMIC_RG_VA10_CAL, + MT6351_PMIC_RG_VA10_VOSEL, + MT6351_PMIC_RG_VA10_NDIS_EN, + MT6351_PMIC_RG_VA10_STB_SEL, + MT6351_PMIC_RG_VCAMIO_CAL, + MT6351_PMIC_RG_VCAMIO_VOSEL, + MT6351_PMIC_RG_VCAMIO_NDIS_EN, + MT6351_PMIC_RG_VCAMIO_STB_SEL, + MT6351_PMIC_RG_VCN18_CAL, + MT6351_PMIC_RG_VCN18_VOSEL, + MT6351_PMIC_RG_VCN18_NDIS_EN, + MT6351_PMIC_RG_VCN18_STB_SEL, + MT6351_PMIC_RG_VMIPI_CAL, + MT6351_PMIC_RG_VMIPI_VOSEL, + MT6351_PMIC_RG_VMIPI_NDIS_EN, + MT6351_PMIC_RG_VMIPI_STB_SEL, + MT6351_PMIC_RG_VSRAM_PROC_NDIS_EN, + MT6351_PMIC_RG_VSRAM_PROC_NDIS_PLCUR, + MT6351_PMIC_RG_VSRAM_PROC_STB_SEL, + MT6351_PMIC_RG_VSRAM_PROC_PLCUR_EN, + MT6351_PMIC_RG_VDRAM_CAL, + MT6351_PMIC_RG_VDRAM_VOSEL, + MT6351_PMIC_RG_VDRAM_NDIS_EN, + MT6351_PMIC_RG_VDRAM_RSV, + MT6351_PMIC_RG_VDRAM_OC_TRIM, + MT6351_PMIC_RG_VLDO28_CAL, + MT6351_PMIC_RG_VLDO28_NDIS_EN, + MT6351_PMIC_RG_VLDO28_OC_TRIM, + MT6351_PMIC_RG_VLDO28_N2LP_EHC_V18, + MT6351_PMIC_BIF_COMMAND_0, + MT6351_PMIC_BIF_COMMAND_1, + MT6351_PMIC_BIF_COMMAND_2, + MT6351_PMIC_BIF_COMMAND_3, + MT6351_PMIC_BIF_COMMAND_4, + MT6351_PMIC_BIF_COMMAND_5, + MT6351_PMIC_BIF_COMMAND_6, + MT6351_PMIC_BIF_COMMAND_7, + MT6351_PMIC_BIF_COMMAND_8, + MT6351_PMIC_BIF_COMMAND_9, + MT6351_PMIC_BIF_COMMAND_10, + MT6351_PMIC_BIF_COMMAND_11, + MT6351_PMIC_BIF_COMMAND_12, + MT6351_PMIC_BIF_COMMAND_13, + MT6351_PMIC_BIF_COMMAND_14, + MT6351_PMIC_BIF_RSV, + MT6351_PMIC_BIF_COMMAND_TYPE, + MT6351_PMIC_BIF_TRASFER_NUM, + MT6351_PMIC_BIF_LOGIC_0_SET, + MT6351_PMIC_BIF_LOGIC_1_SET, + MT6351_PMIC_BIF_STOP_SET, + MT6351_PMIC_BIF_DEBOUNCE_WND, + MT6351_PMIC_BIF_DEBOUNCE_THD, + MT6351_PMIC_BIF_DEBOUNCE_EN, + MT6351_PMIC_BIF_READ_EXPECT_NUM, + MT6351_PMIC_BIF_TRASACT_TRIGGER, + MT6351_PMIC_BIF_DATA_NUM, + MT6351_PMIC_BIF_RESPONSE, + MT6351_PMIC_BIF_DATA_0, + MT6351_PMIC_BIF_ACK_0, + MT6351_PMIC_BIF_ERROR_0, + MT6351_PMIC_BIF_DATA_1, + MT6351_PMIC_BIF_ACK_1, + MT6351_PMIC_BIF_ERROR_1, + MT6351_PMIC_BIF_DATA_2, + MT6351_PMIC_BIF_ACK_2, + MT6351_PMIC_BIF_ERROR_2, + MT6351_PMIC_BIF_DATA_3, + MT6351_PMIC_BIF_ACK_3, + MT6351_PMIC_BIF_ERROR_3, + MT6351_PMIC_BIF_DATA_4, + MT6351_PMIC_BIF_ACK_4, + MT6351_PMIC_BIF_ERROR_4, + MT6351_PMIC_BIF_DATA_5, + MT6351_PMIC_BIF_ACK_5, + MT6351_PMIC_BIF_ERROR_5, + MT6351_PMIC_BIF_DATA_6, + MT6351_PMIC_BIF_ACK_6, + MT6351_PMIC_BIF_ERROR_6, + MT6351_PMIC_BIF_DATA_7, + MT6351_PMIC_BIF_ACK_7, + MT6351_PMIC_BIF_ERROR_7, + MT6351_PMIC_BIF_DATA_8, + MT6351_PMIC_BIF_ACK_8, + MT6351_PMIC_BIF_ERROR_8, + MT6351_PMIC_BIF_DATA_9, + MT6351_PMIC_BIF_ACK_9, + MT6351_PMIC_BIF_ERROR_9, + MT6351_PMIC_BIF_TEST_MODE0, + MT6351_PMIC_BIF_TEST_MODE1, + MT6351_PMIC_BIF_TEST_MODE2, + MT6351_PMIC_BIF_TEST_MODE3, + MT6351_PMIC_BIF_TEST_MODE4, + MT6351_PMIC_BIF_TEST_MODE5, + MT6351_PMIC_BIF_TEST_MODE6, + MT6351_PMIC_BIF_TEST_MODE7, + MT6351_PMIC_BIF_TEST_MODE8, + MT6351_PMIC_BIF_BAT_LOST_SW, + MT6351_PMIC_BIF_RX_DATA_SW, + MT6351_PMIC_BIF_TX_DATA_SW, + MT6351_PMIC_BIF_RX_EN_SW, + MT6351_PMIC_BIF_TX_EN_SW, + MT6351_PMIC_BIF_BACK_NORMAL, + MT6351_PMIC_BIF_IRQ_CLR, + MT6351_PMIC_BIF_BAT_LOST_GATED, + MT6351_PMIC_BIF_IRQ, + MT6351_PMIC_BIF_TIMEOUT, + MT6351_PMIC_BIF_BAT_LOST, + MT6351_PMIC_BIF_TOTAL_VALID, + MT6351_PMIC_BIF_BUS_STATUS, + MT6351_PMIC_BIF_POWER_UP_COUNT, + MT6351_PMIC_BIF_POWER_UP, + MT6351_PMIC_BIF_RX_ERROR_UNKNOWN, + MT6351_PMIC_BIF_RX_ERROR_INSUFF, + MT6351_PMIC_BIF_RX_ERROR_LOWPHASE, + MT6351_PMIC_BIF_RX_STATE, + MT6351_PMIC_BIF_FLOW_CTL_STATE, + MT6351_PMIC_BIF_TX_STATE, + MT6351_PMIC_AD_QI_BIF_RX_DATA, + MT6351_PMIC_DA_QI_BIF_RX_EN, + MT6351_PMIC_DA_QI_BIF_TX_DATA, + MT6351_PMIC_DA_QI_BIF_TX_EN, + MT6351_PMIC_BIF_TX_DATA_FIANL, + MT6351_PMIC_BIF_RX_DATA_SAMPLING, + MT6351_PMIC_BIF_RX_DATA_RECOVERY, + MT6351_PMIC_RG_BATON_HT_EN, + MT6351_PMIC_RG_BATON_HT_EN_DLY_TIME, + MT6351_PMIC_DA_QI_BATON_HT_EN, + MT6351_PMIC_BIF_TIMEOUT_SET, + MT6351_PMIC_BIF_RX_DEG_WND, + MT6351_PMIC_BIF_RX_DEG_EN, + MT6351_PMIC_BIF_RSV1, + MT6351_PMIC_BIF_RSV0, + MT6351_PMIC_RG_OTP_PA, + MT6351_PMIC_RG_OTP_PDIN, + MT6351_PMIC_RG_OTP_PTM, + MT6351_PMIC_RG_OTP_PWE, + MT6351_PMIC_RG_OTP_PPROG, + MT6351_PMIC_RG_OTP_PWE_SRC, + MT6351_PMIC_RG_OTP_PROG_PKEY, + MT6351_PMIC_RG_OTP_RD_PKEY, + MT6351_PMIC_RG_OTP_RD_TRIG, + MT6351_PMIC_RG_RD_RDY_BYPASS, + MT6351_PMIC_RG_SKIP_OTP_OUT, + MT6351_PMIC_RG_OTP_RD_SW, + MT6351_PMIC_RG_OTP_DOUT_SW, + MT6351_PMIC_RG_OTP_RD_BUSY, + MT6351_PMIC_RG_OTP_RD_ACK, + MT6351_PMIC_RG_OTP_PA_SW, + MT6351_PMIC_RG_OTP_DOUT_0_15, + MT6351_PMIC_RG_OTP_DOUT_16_31, + MT6351_PMIC_RG_OTP_DOUT_32_47, + MT6351_PMIC_RG_OTP_DOUT_48_63, + MT6351_PMIC_RG_OTP_DOUT_64_79, + MT6351_PMIC_RG_OTP_DOUT_80_95, + MT6351_PMIC_RG_OTP_DOUT_96_111, + MT6351_PMIC_RG_OTP_DOUT_112_127, + MT6351_PMIC_RG_OTP_DOUT_128_143, + MT6351_PMIC_RG_OTP_DOUT_144_159, + MT6351_PMIC_RG_OTP_DOUT_160_175, + MT6351_PMIC_RG_OTP_DOUT_176_191, + MT6351_PMIC_RG_OTP_DOUT_192_207, + MT6351_PMIC_RG_OTP_DOUT_208_223, + MT6351_PMIC_RG_OTP_DOUT_224_239, + MT6351_PMIC_RG_OTP_DOUT_240_255, + MT6351_PMIC_RG_OTP_DOUT_256_271, + MT6351_PMIC_RG_OTP_DOUT_272_287, + MT6351_PMIC_RG_OTP_DOUT_288_303, + MT6351_PMIC_RG_OTP_DOUT_304_319, + MT6351_PMIC_RG_OTP_DOUT_320_335, + MT6351_PMIC_RG_OTP_DOUT_336_351, + MT6351_PMIC_RG_OTP_DOUT_352_367, + MT6351_PMIC_RG_OTP_DOUT_368_383, + MT6351_PMIC_RG_OTP_DOUT_384_399, + MT6351_PMIC_RG_OTP_DOUT_400_415, + MT6351_PMIC_RG_OTP_DOUT_416_431, + MT6351_PMIC_RG_OTP_DOUT_432_447, + MT6351_PMIC_RG_OTP_DOUT_448_463, + MT6351_PMIC_RG_OTP_DOUT_464_479, + MT6351_PMIC_RG_OTP_DOUT_480_495, + MT6351_PMIC_RG_OTP_DOUT_496_511, + MT6351_PMIC_RG_OTP_VAL_0_15, + MT6351_PMIC_RG_OTP_VAL_16_31, + MT6351_PMIC_RG_OTP_VAL_32_47, + MT6351_PMIC_RG_OTP_VAL_48_63, + MT6351_PMIC_RG_OTP_VAL_64_79, + MT6351_PMIC_RG_OTP_VAL_80_95, + MT6351_PMIC_RG_OTP_VAL_96_111, + MT6351_PMIC_RG_OTP_VAL_112_127, + MT6351_PMIC_RG_OTP_VAL_128_143, + MT6351_PMIC_RG_OTP_VAL_144_159, + MT6351_PMIC_RG_OTP_VAL_160_175, + MT6351_PMIC_RG_OTP_VAL_176_191, + MT6351_PMIC_RG_OTP_VAL_192_207, + MT6351_PMIC_RG_OTP_VAL_208_223, + MT6351_PMIC_RG_OTP_VAL_224_239, + MT6351_PMIC_RG_OTP_VAL_240_255, + MT6351_PMIC_RG_OTP_VAL_256_271, + MT6351_PMIC_RG_OTP_VAL_272_287, + MT6351_PMIC_RG_OTP_VAL_288_303, + MT6351_PMIC_RG_OTP_VAL_304_319, + MT6351_PMIC_RG_OTP_VAL_320_335, + MT6351_PMIC_RG_OTP_VAL_336_351, + MT6351_PMIC_RG_OTP_VAL_352_367, + MT6351_PMIC_RG_OTP_VAL_368_383, + MT6351_PMIC_RG_OTP_VAL_384_399, + MT6351_PMIC_RG_OTP_VAL_400_415, + MT6351_PMIC_RG_OTP_VAL_416_431, + MT6351_PMIC_RG_OTP_VAL_432_447, + MT6351_PMIC_RG_OTP_VAL_448_463, + MT6351_PMIC_RG_OTP_VAL_464_479, + MT6351_PMIC_RG_OTP_VAL_480_495, + MT6351_PMIC_RG_OTP_VAL_496_511, + MT6351_PMIC_MIX_EOSC32_STP_LPDTB, + MT6351_PMIC_MIX_EOSC32_STP_LPDEN, + MT6351_PMIC_MIX_XOSC32_STP_PWDB, + MT6351_PMIC_MIX_XOSC32_STP_LPDTB, + MT6351_PMIC_MIX_XOSC32_STP_LPDEN, + MT6351_PMIC_MIX_XOSC32_STP_LPDRST, + MT6351_PMIC_MIX_XOSC32_STP_CALI, + MT6351_PMIC_STMP_MODE, + MT6351_PMIC_MIX_EOSC32_STP_CHOP_EN, + MT6351_PMIC_MIX_DCXO_STP_LVSH_EN, + MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC, + MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_EN, + MT6351_PMIC_MIX_RTC_STP_XOSC32_ENB, + MT6351_PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE, + MT6351_PMIC_MIX_EOSC32_STP_RSV, + MT6351_PMIC_MIX_EOSC32_VCT_EN, + MT6351_PMIC_MIX_EOSC32_OPT, + MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_INT, + MT6351_PMIC_MIX_RTC_GPIO_COREDETB, + MT6351_PMIC_MIX_RTC_GPIO_F32KOB, + MT6351_PMIC_MIX_RTC_GPIO_GPO, + MT6351_PMIC_MIX_RTC_GPIO_OE, + MT6351_PMIC_MIX_RTC_STP_DEBUG_OUT, + MT6351_PMIC_MIX_RTC_STP_DEBUG_SEL, + MT6351_PMIC_MIX_RTC_STP_K_EOSC32_EN, + MT6351_PMIC_MIX_RTC_STP_EMBCK_SEL, + MT6351_PMIC_MIX_STP_BBWAKEUP, + MT6351_PMIC_MIX_STP_RTC_DDLO, + MT6351_PMIC_MIX_RTC_XOSC32_ENB, + MT6351_PMIC_MIX_EFUSE_XOSC32_ENB_OPT, + MT6351_PMIC_FG_ON, + MT6351_PMIC_FG_CAL, + MT6351_PMIC_FG_AUTOCALRATE, + MT6351_PMIC_FG_SW_CR, + MT6351_PMIC_FG_SW_READ_PRE, + MT6351_PMIC_FG_LATCHDATA_ST, + MT6351_PMIC_FG_SW_CLEAR, + MT6351_PMIC_FG_OFFSET_RST, + MT6351_PMIC_FG_TIME_RST, + MT6351_PMIC_FG_CHARGE_RST, + MT6351_PMIC_FG_SW_RSTCLR, + MT6351_PMIC_FG_CAR_34_19, + MT6351_PMIC_FG_CAR_18_03, + MT6351_PMIC_FG_CAR_02_00, + MT6351_PMIC_FG_NTER_32_17, + MT6351_PMIC_FG_NTER_16_01, + MT6351_PMIC_FG_NTER_00, + MT6351_PMIC_FG_BLTR_31_16, + MT6351_PMIC_FG_BLTR_15_00, + MT6351_PMIC_FG_BFTR_31_16, + MT6351_PMIC_FG_BFTR_15_00, + MT6351_PMIC_FG_CURRENT_OUT, + MT6351_PMIC_FG_ADJUST_OFFSET_VALUE, + MT6351_PMIC_FG_OFFSET, + MT6351_PMIC_RG_FGANALOGTEST, + MT6351_PMIC_RG_FGRINTMODE, + MT6351_PMIC_RG_SPARE, + MT6351_PMIC_FG_OSR, + MT6351_PMIC_FG_ADJ_OFFSET_EN, + MT6351_PMIC_FG_ADC_AUTORST, + MT6351_PMIC_FG_FIR1BYPASS, + MT6351_PMIC_FG_FIR2BYPASS, + MT6351_PMIC_FG_L_CUR_INT_STS, + MT6351_PMIC_FG_H_CUR_INT_STS, + MT6351_PMIC_FG_L_INT_STS, + MT6351_PMIC_FG_H_INT_STS, + MT6351_PMIC_FG_ADC_RSTDETECT, + MT6351_PMIC_FG_SLP_EN, + MT6351_PMIC_FG_ZCV_DET_EN, + MT6351_PMIC_RG_FG_AUXADC_R, + MT6351_PMIC_DA_FGADC_EN, + MT6351_PMIC_DA_FGCAL_EN, + MT6351_PMIC_DA_FG_RST, + MT6351_PMIC_FG_CIC2, + MT6351_PMIC_FG_SLP_CUR_TH, + MT6351_PMIC_FG_SLP_TIME, + MT6351_PMIC_FG_SRCVOLTEN_FTIME, + MT6351_PMIC_FG_DET_TIME, + MT6351_PMIC_FG_ZCV_CAR_34_19, + MT6351_PMIC_FG_ZCV_CAR_18_03, + MT6351_PMIC_FG_ZCV_CAR_02_00, + MT6351_PMIC_FG_ZCV_CURR, + MT6351_PMIC_FG_R_CURR, + MT6351_PMIC_FG_MODE, + MT6351_PMIC_FG_RST_SW, + MT6351_PMIC_FG_FGCAL_EN_SW, + MT6351_PMIC_FG_FGADC_EN_SW, + MT6351_PMIC_FG_RSV1, + MT6351_PMIC_FG_TEST_MODE0, + MT6351_PMIC_FG_TEST_MODE1, + MT6351_PMIC_FG_GAIN, + MT6351_PMIC_FG_CUR_HTH, + MT6351_PMIC_FG_CUR_LTH, + MT6351_PMIC_FG_ZCV_DET_TIME, + MT6351_PMIC_FG_ZCV_CAR_TH_33_19, + MT6351_PMIC_FG_ZCV_CAR_TH_18_03, + MT6351_PMIC_FG_ZCV_CAR_TH_02_00, + MT6351_PMIC_SYSTEM_INFO_CON0, + MT6351_PMIC_SYSTEM_INFO_CON1, + MT6351_PMIC_SYSTEM_INFO_CON2, + MT6351_PMIC_SYSTEM_INFO_CON3, + MT6351_PMIC_SYSTEM_INFO_CON4, + MT6351_PMIC_RG_AUDDACLPWRUP_VAUDP32, + MT6351_PMIC_RG_AUDDACRPWRUP_VAUDP32, + MT6351_PMIC_RG_AUD_DAC_PWR_UP_VA32, + MT6351_PMIC_RG_AUD_DAC_PWL_UP_VA32, + MT6351_PMIC_RG_AUDHSPWRUP_VAUDP32, + MT6351_PMIC_RG_AUDHPLPWRUP_VAUDP32, + MT6351_PMIC_RG_AUDHPRPWRUP_VAUDP32, + MT6351_PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32, + MT6351_PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32, + MT6351_PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32, + MT6351_PMIC_RG_AUDHSSCDISABLE_VAUDP32, + MT6351_PMIC_RG_AUDHPLSCDISABLE_VAUDP32, + MT6351_PMIC_RG_AUDHPRSCDISABLE_VAUDP32, + MT6351_PMIC_RG_AUDHSBSCCURRENT_VAUDP32, + MT6351_PMIC_RG_AUDHPLBSCCURRENT_VAUDP32, + MT6351_PMIC_RG_AUDHPRBSCCURRENT_VAUDP32, + MT6351_PMIC_RG_AUDHSSTARTUP_VAUDP32, + MT6351_PMIC_RG_AUDHPSTARTUP_VAUDP32, + MT6351_PMIC_RG_AUDBGBON_VAUDP32, + MT6351_PMIC_RG_PRECHARGEBUF_EN_VAUDP32, + MT6351_PMIC_RG_HSINPUTSTBENH_VAUDP32, + MT6351_PMIC_RG_HSOUTPUTSTBENH_VAUDP32, + MT6351_PMIC_RG_HSINPUTRESET0_VAUDP32, + MT6351_PMIC_RG_HSOUTPUTRESET0_VAUDP32, + MT6351_PMIC_RG_HSOUT_SHORTVCM_VAUDP32, + MT6351_PMIC_RG_HPINPUTSTBENH_VAUDP32, + MT6351_PMIC_RG_HPOUTPUTSTBENH_VAUDP32, + MT6351_PMIC_RG_HPINPUTRESET0_VAUDP32, + MT6351_PMIC_RG_HPOUTPUTRESET0_VAUDP32, + MT6351_PMIC_RG_HPOUT_SHORTVCM_VAUDP32, + MT6351_PMIC_RG_HPOUTSTB_RSEL_VAUDP32, + MT6351_PMIC_RG_LINENOISEENH_VAUDP32, + MT6351_PMIC_RG_AUDHPLTRIM_VAUDP32, + MT6351_PMIC_RG_AUDHPRTRIM_VAUDP32, + MT6351_PMIC_RG_AUDHPTRIM_EN_VAUDP32, + MT6351_PMIC_RG_AUDHPLFINETRIM_VAUDP32, + MT6351_PMIC_RG_AUDHPRFINETRIM_VAUDP32, + MT6351_PMIC_RG_AUDLOLPWRUP_VAUDP32, + MT6351_PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32, + MT6351_PMIC_RG_AUDLOLSCDISABLE_VAUDP32, + MT6351_PMIC_RG_AUDLOLBSCCURRENT_VAUDP32, + MT6351_PMIC_RG_AUDLOSTARTUP_VAUDP32, + MT6351_PMIC_RG_LOINPUTSTBENH_VAUDP32, + MT6351_PMIC_RG_LOOUTPUTSTBENH_VAUDP32, + MT6351_PMIC_RG_LOINPUTRESET0_VAUDP32, + MT6351_PMIC_RG_LOOUTPUTRESET0_VAUDP32, + MT6351_PMIC_RG_LOOUT_SHORTVCM_VAUDP32, + MT6351_PMIC_RG_LOOUTSTB_RSEL_VAUDP32, + MT6351_PMIC_RG_AUDLOLTRIM_VAUDP32, + MT6351_PMIC_RG_AUDLOTRIM_EN_VAUDP32, + MT6351_PMIC_RG_AUDLOLFINETRIM_VAUDP32, + MT6351_PMIC_RG_AUDTRIMBUF_EN_VAUDP32, + MT6351_PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32, + MT6351_PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32, + MT6351_PMIC_RG_AUDHPSPKDET_EN_VAUDP32, + MT6351_PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32, + MT6351_PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32, + MT6351_PMIC_RG_ABIDEC_RSVD0_VA32, + MT6351_PMIC_RG_ABIDEC_RSVD1_VA32, + MT6351_PMIC_RG_ABIDEC_RSVD0_VAUDP32, + MT6351_PMIC_RG_ABIDEC_RSVD1_VAUDP32, + MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP32, + MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP32, + MT6351_PMIC_RG_AUDBIASADJ_0_VAUDP32, + MT6351_PMIC_RG_AUDBIASADJ_1_VAUDP32, + MT6351_PMIC_RG_AUDIBIASPWRDN_VAUDP32, + MT6351_PMIC_RG_RSTB_DECODER_VA32, + MT6351_PMIC_RG_SEL_DECODER_96K_VA32, + MT6351_PMIC_RG_SEL_DELAY_VCORE, + MT6351_PMIC_RG_AUDGLB_PWRDN_VA32, + MT6351_PMIC_RG_LCLDO_DEC_EN_VA32, + MT6351_PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18, + MT6351_PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18, + MT6351_PMIC_RG_AUDPMU_RSVD_VA18, + MT6351_PMIC_RG_NVREG_EN_VAUDP32, + MT6351_PMIC_RG_NVREG_PULL0V_VAUDP32, + MT6351_PMIC_RG_AUDGLB_LP2_VOW_EN_VA32, + MT6351_PMIC_RG_AUDPREAMPLON, + MT6351_PMIC_RG_AUDPREAMPLDCCEN, + MT6351_PMIC_RG_AUDPREAMPLDCPRECHARGE, + MT6351_PMIC_RG_AUDPREAMPLPGATEST, + MT6351_PMIC_RG_AUDPREAMPLINPUTSEL, + MT6351_PMIC_RG_AUDPREAMPLVSCALE, + MT6351_PMIC_RG_AUDPREAMPLGAIN, + MT6351_PMIC_RG_AUDADCLPWRUP, + MT6351_PMIC_RG_AUDADCLINPUTSEL, + MT6351_PMIC_RG_AUDPREAMPRON, + MT6351_PMIC_RG_AUDPREAMPRDCCEN, + MT6351_PMIC_RG_AUDPREAMPRDCPRECHARGE, + MT6351_PMIC_RG_AUDPREAMPRPGATEST, + MT6351_PMIC_RG_AUDPREAMPRINPUTSEL, + MT6351_PMIC_RG_AUDPREAMPRVSCALE, + MT6351_PMIC_RG_AUDPREAMPRGAIN, + MT6351_PMIC_RG_AUDADCRPWRUP, + MT6351_PMIC_RG_AUDADCRINPUTSEL, + MT6351_PMIC_RG_AUDULHALFBIAS, + MT6351_PMIC_RG_AUDGLBVOWLPWEN, + MT6351_PMIC_RG_AUDPREAMPLPEN, + MT6351_PMIC_RG_AUDADC1STSTAGELPEN, + MT6351_PMIC_RG_AUDADC2NDSTAGELPEN, + MT6351_PMIC_RG_AUDADCFLASHLPEN, + MT6351_PMIC_RG_AUDPREAMPIDDTEST, + MT6351_PMIC_RG_AUDADC1STSTAGEIDDTEST, + MT6351_PMIC_RG_AUDADC2NDSTAGEIDDTEST, + MT6351_PMIC_RG_AUDADCREFBUFIDDTEST, + MT6351_PMIC_RG_AUDADCFLASHIDDTEST, + MT6351_PMIC_RG_AUDADCDAC0P25FS, + MT6351_PMIC_RG_AUDADCCLKSEL, + MT6351_PMIC_RG_AUDADCCLKSOURCE, + MT6351_PMIC_RG_AUDADCCLKGENMODE, + MT6351_PMIC_RG_AUDADCCLKRSTB, + MT6351_PMIC_RG_AUDPREAMPAAFEN, + MT6351_PMIC_RG_DCCVCMBUFLPMODSEL, + MT6351_PMIC_RG_DCCVCMBUFLPSWEN, + MT6351_PMIC_RG_AUDSPAREPGA, + MT6351_PMIC_RG_AUDADC1STSTAGESDENB, + MT6351_PMIC_RG_AUDADC2NDSTAGERESET, + MT6351_PMIC_RG_AUDADC3RDSTAGERESET, + MT6351_PMIC_RG_AUDADCFSRESET, + MT6351_PMIC_RG_AUDADCWIDECM, + MT6351_PMIC_RG_AUDADCNOPATEST, + MT6351_PMIC_RG_AUDADCBYPASS, + MT6351_PMIC_RG_AUDADCFFBYPASS, + MT6351_PMIC_RG_AUDADCDACFBCURRENT, + MT6351_PMIC_RG_AUDADCDACIDDTEST, + MT6351_PMIC_RG_AUDADCDACNRZ, + MT6351_PMIC_RG_AUDADCNODEM, + MT6351_PMIC_RG_AUDADCDACTEST, + MT6351_PMIC_RG_AUDADCTESTDATA, + MT6351_PMIC_RG_AUDRCTUNEL, + MT6351_PMIC_RG_AUDRCTUNELSEL, + MT6351_PMIC_RG_AUDRCTUNER, + MT6351_PMIC_RG_AUDRCTUNERSEL, + MT6351_PMIC_RG_AUDSPAREVA30, + MT6351_PMIC_RG_AUDSPAREVA18, + MT6351_PMIC_RG_AUDDIGMICEN, + MT6351_PMIC_RG_AUDDIGMICBIAS, + MT6351_PMIC_RG_DMICHPCLKEN, + MT6351_PMIC_RG_AUDDIGMICPDUTY, + MT6351_PMIC_RG_AUDDIGMICNDUTY, + MT6351_PMIC_RG_DMICMONEN, + MT6351_PMIC_RG_DMICMONSEL, + MT6351_PMIC_RG_AUDSPAREVMIC, + MT6351_PMIC_RG_AUDPWDBMICBIAS0, + MT6351_PMIC_RG_AUDMICBIAS0DCSW0P1EN, + MT6351_PMIC_RG_AUDMICBIAS0DCSW0P2EN, + MT6351_PMIC_RG_AUDMICBIAS0DCSW0NEN, + MT6351_PMIC_RG_AUDMICBIAS0VREF, + MT6351_PMIC_RG_AUDMICBIAS0LOWPEN, + MT6351_PMIC_RG_AUDPWDBMICBIAS2, + MT6351_PMIC_RG_AUDMICBIAS2DCSW2P1EN, + MT6351_PMIC_RG_AUDMICBIAS2DCSW2P2EN, + MT6351_PMIC_RG_AUDMICBIAS2DCSW2NEN, + MT6351_PMIC_RG_AUDMICBIAS2VREF, + MT6351_PMIC_RG_AUDMICBIAS2LOWPEN, + MT6351_PMIC_RG_AUDPWDBMICBIAS1, + MT6351_PMIC_RG_AUDMICBIAS1DCSW1PEN, + MT6351_PMIC_RG_AUDMICBIAS1DCSW1NEN, + MT6351_PMIC_RG_AUDMICBIAS1VREF, + MT6351_PMIC_RG_AUDMICBIAS1LOWPEN, + MT6351_PMIC_RG_AUDMICBIAS1DCSW3PEN, + MT6351_PMIC_RG_AUDMICBIAS1DCSW3NEN, + MT6351_PMIC_RG_AUDMICBIAS2DCSW3PEN, + MT6351_PMIC_RG_AUDMICBIAS2DCSW3NEN, + MT6351_PMIC_RG_BANDGAPGEN, + MT6351_PMIC_RG_AUDACCDETMICBIAS0PULLLOW, + MT6351_PMIC_RG_AUDACCDETMICBIAS1PULLLOW, + MT6351_PMIC_RG_AUDACCDETMICBIAS2PULLLOW, + MT6351_PMIC_RG_AUDACCDETVIN1PULLLOW, + MT6351_PMIC_RG_AUDACCDETVTHACAL, + MT6351_PMIC_RG_AUDACCDETVTHBCAL, + MT6351_PMIC_RG_ACCDET1SEL, + MT6351_PMIC_RG_ACCDET2SEL, + MT6351_PMIC_RG_SWBUFMODSEL, + MT6351_PMIC_RG_SWBUFSWEN, + MT6351_PMIC_RG_EINTCOMPVTH, + MT6351_PMIC_RG_EINTCONFIGACCDET, + MT6351_PMIC_RG_NVDETCMPEN, + MT6351_PMIC_RG_NVDETVTH, + MT6351_PMIC_RG_NVMODSEL, + MT6351_PMIC_RG_NVCMPSWEN, + MT6351_PMIC_RG_AUDENCSPAREVA30, + MT6351_PMIC_RG_AUDENCSPAREVA18, + MT6351_PMIC_RG_PLL_EN, + MT6351_PMIC_RG_PLLBS_RST, + MT6351_PMIC_RG_PLL_DCKO_SEL, + MT6351_PMIC_RG_PLL_DIV1, + MT6351_PMIC_RG_PLL_RLATCH_EN, + MT6351_PMIC_RG_PLL_PDIV1_EN, + MT6351_PMIC_RG_PLL_PDIV1, + MT6351_PMIC_RG_PLL_BC, + MT6351_PMIC_RG_PLL_BP, + MT6351_PMIC_RG_PLL_BR, + MT6351_PMIC_RG_CKO_SEL, + MT6351_PMIC_RG_PLL_IBSEL, + MT6351_PMIC_RG_PLL_CKT_SEL, + MT6351_PMIC_RG_PLL_VCT_EN, + MT6351_PMIC_RG_PLL_CKT_EN, + MT6351_PMIC_RG_PLL_HPM_EN, + MT6351_PMIC_RG_PLL_DCHP_EN, + MT6351_PMIC_RG_PLL_CDIV, + MT6351_PMIC_RG_VCOBAND, + MT6351_PMIC_RG_CKDRV_EN, + MT6351_PMIC_RG_PLL_DCHP_AEN, + MT6351_PMIC_RG_PLL_RSVA, + MT6351_PMIC_RGS_AUDRCTUNELREAD, + MT6351_PMIC_RGS_AUDRCTUNERREAD, + MT6351_PMIC_RG_DIVCKS_CHG, + MT6351_PMIC_RG_DIVCKS_ON, + MT6351_PMIC_RG_DIVCKS_PRG, + MT6351_PMIC_RG_DIVCKS_PWD_NCP, + MT6351_PMIC_RG_DIVCKS_PWD_NCP_ST_SEL, + MT6351_PMIC_AUXADC_ADC_OUT_CH0, + MT6351_PMIC_AUXADC_ADC_RDY_CH0, + MT6351_PMIC_AUXADC_ADC_OUT_CH1, + MT6351_PMIC_AUXADC_ADC_RDY_CH1, + MT6351_PMIC_AUXADC_ADC_OUT_CH2, + MT6351_PMIC_AUXADC_ADC_RDY_CH2, + MT6351_PMIC_AUXADC_ADC_OUT_CH3, + MT6351_PMIC_AUXADC_ADC_RDY_CH3, + MT6351_PMIC_AUXADC_ADC_OUT_CH4, + MT6351_PMIC_AUXADC_ADC_RDY_CH4, + MT6351_PMIC_AUXADC_ADC_OUT_CH5, + MT6351_PMIC_AUXADC_ADC_RDY_CH5, + MT6351_PMIC_AUXADC_ADC_OUT_CH6, + MT6351_PMIC_AUXADC_ADC_RDY_CH6, + MT6351_PMIC_AUXADC_ADC_OUT_CH7, + MT6351_PMIC_AUXADC_ADC_RDY_CH7, + MT6351_PMIC_AUXADC_ADC_OUT_CH8, + MT6351_PMIC_AUXADC_ADC_RDY_CH8, + MT6351_PMIC_AUXADC_ADC_OUT_CH9, + MT6351_PMIC_AUXADC_ADC_RDY_CH9, + MT6351_PMIC_AUXADC_ADC_OUT_CH10, + MT6351_PMIC_AUXADC_ADC_RDY_CH10, + MT6351_PMIC_AUXADC_ADC_OUT_CH11, + MT6351_PMIC_AUXADC_ADC_RDY_CH11, + MT6351_PMIC_AUXADC_ADC_OUT_CH12_15, + MT6351_PMIC_AUXADC_ADC_RDY_CH12_15, + MT6351_PMIC_AUXADC_ADC_OUT_THR_HW, + MT6351_PMIC_AUXADC_ADC_RDY_THR_HW, + MT6351_PMIC_AUXADC_ADC_OUT_LBAT, + MT6351_PMIC_AUXADC_ADC_RDY_LBAT, + MT6351_PMIC_AUXADC_ADC_OUT_LBAT2, + MT6351_PMIC_AUXADC_ADC_RDY_LBAT2, + MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_GPS, + MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_GPS, + MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_MD, + MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_MD, + MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_AP, + MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_AP, + MT6351_PMIC_AUXADC_ADC_OUT_CH4_BY_MD, + MT6351_PMIC_AUXADC_ADC_RDY_CH4_BY_MD, + MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR, + MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR, + MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR, + MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR, + MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_MD, + MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_MD, + MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_AP, + MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_AP, + MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_MD, + MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_MD, + MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_AP, + MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_AP, + MT6351_PMIC_AUXADC_ADC_OUT_VISMPS0, + MT6351_PMIC_AUXADC_ADC_RDY_VISMPS0, + MT6351_PMIC_AUXADC_ADC_OUT_FGADC1, + MT6351_PMIC_AUXADC_ADC_RDY_FGADC1, + MT6351_PMIC_AUXADC_ADC_OUT_FGADC2, + MT6351_PMIC_AUXADC_ADC_RDY_FGADC2, + MT6351_PMIC_AUXADC_ADC_OUT_IMP, + MT6351_PMIC_AUXADC_ADC_RDY_IMP, + MT6351_PMIC_AUXADC_ADC_OUT_IMP_AVG, + MT6351_PMIC_AUXADC_ADC_RDY_IMP_AVG, + MT6351_PMIC_AUXADC_ADC_OUT_RAW, + MT6351_PMIC_AUXADC_ADC_OUT_MDRT, + MT6351_PMIC_AUXADC_ADC_RDY_MDRT, + MT6351_PMIC_AUXADC_ADC_OUT_MDBG, + MT6351_PMIC_AUXADC_ADC_RDY_MDBG, + MT6351_PMIC_AUXADC_ADC_OUT_JEITA, + MT6351_PMIC_AUXADC_ADC_RDY_JEITA, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_MD, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_MD, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_AP, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_AP, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_MDRT, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_MDRT, + MT6351_PMIC_AUXADC_ADC_OUT_NAG, + MT6351_PMIC_AUXADC_ADC_RDY_NAG, + MT6351_PMIC_AUXADC_BUF_OUT_00, + MT6351_PMIC_AUXADC_BUF_RDY_00, + MT6351_PMIC_AUXADC_BUF_OUT_01, + MT6351_PMIC_AUXADC_BUF_RDY_01, + MT6351_PMIC_AUXADC_BUF_OUT_02, + MT6351_PMIC_AUXADC_BUF_RDY_02, + MT6351_PMIC_AUXADC_BUF_OUT_03, + MT6351_PMIC_AUXADC_BUF_RDY_03, + MT6351_PMIC_AUXADC_BUF_OUT_04, + MT6351_PMIC_AUXADC_BUF_RDY_04, + MT6351_PMIC_AUXADC_BUF_OUT_05, + MT6351_PMIC_AUXADC_BUF_RDY_05, + MT6351_PMIC_AUXADC_BUF_OUT_06, + MT6351_PMIC_AUXADC_BUF_RDY_06, + MT6351_PMIC_AUXADC_BUF_OUT_07, + MT6351_PMIC_AUXADC_BUF_RDY_07, + MT6351_PMIC_AUXADC_BUF_OUT_08, + MT6351_PMIC_AUXADC_BUF_RDY_08, + MT6351_PMIC_AUXADC_BUF_OUT_09, + MT6351_PMIC_AUXADC_BUF_RDY_09, + MT6351_PMIC_AUXADC_BUF_OUT_10, + MT6351_PMIC_AUXADC_BUF_RDY_10, + MT6351_PMIC_AUXADC_BUF_OUT_11, + MT6351_PMIC_AUXADC_BUF_RDY_11, + MT6351_PMIC_AUXADC_BUF_OUT_12, + MT6351_PMIC_AUXADC_BUF_RDY_12, + MT6351_PMIC_AUXADC_BUF_OUT_13, + MT6351_PMIC_AUXADC_BUF_RDY_13, + MT6351_PMIC_AUXADC_BUF_OUT_14, + MT6351_PMIC_AUXADC_BUF_RDY_14, + MT6351_PMIC_AUXADC_BUF_OUT_15, + MT6351_PMIC_AUXADC_BUF_RDY_15, + MT6351_PMIC_AUXADC_BUF_OUT_16, + MT6351_PMIC_AUXADC_BUF_RDY_16, + MT6351_PMIC_AUXADC_BUF_OUT_17, + MT6351_PMIC_AUXADC_BUF_RDY_17, + MT6351_PMIC_AUXADC_BUF_OUT_18, + MT6351_PMIC_AUXADC_BUF_RDY_18, + MT6351_PMIC_AUXADC_BUF_OUT_19, + MT6351_PMIC_AUXADC_BUF_RDY_19, + MT6351_PMIC_AUXADC_BUF_OUT_20, + MT6351_PMIC_AUXADC_BUF_RDY_20, + MT6351_PMIC_AUXADC_BUF_OUT_21, + MT6351_PMIC_AUXADC_BUF_RDY_21, + MT6351_PMIC_AUXADC_BUF_OUT_22, + MT6351_PMIC_AUXADC_BUF_RDY_22, + MT6351_PMIC_AUXADC_BUF_OUT_23, + MT6351_PMIC_AUXADC_BUF_RDY_23, + MT6351_PMIC_AUXADC_BUF_OUT_24, + MT6351_PMIC_AUXADC_BUF_RDY_24, + MT6351_PMIC_AUXADC_BUF_OUT_25, + MT6351_PMIC_AUXADC_BUF_RDY_25, + MT6351_PMIC_AUXADC_BUF_OUT_26, + MT6351_PMIC_AUXADC_BUF_RDY_26, + MT6351_PMIC_AUXADC_BUF_OUT_27, + MT6351_PMIC_AUXADC_BUF_RDY_27, + MT6351_PMIC_AUXADC_BUF_OUT_28, + MT6351_PMIC_AUXADC_BUF_RDY_28, + MT6351_PMIC_AUXADC_BUF_OUT_29, + MT6351_PMIC_AUXADC_BUF_RDY_29, + MT6351_PMIC_AUXADC_BUF_OUT_30, + MT6351_PMIC_AUXADC_BUF_RDY_30, + MT6351_PMIC_AUXADC_BUF_OUT_31, + MT6351_PMIC_AUXADC_BUF_RDY_31, + MT6351_PMIC_AUXADC_ADC_BUSY_IN, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT2, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_VISMPS0, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_WAKEUP, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_JEITA, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDRT, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDBG, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHARE, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_IMP, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC1, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC2, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_AP, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MD, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_HW, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_MD, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_NAG, + MT6351_PMIC_AUXADC_RQST_CH0, + MT6351_PMIC_AUXADC_RQST_CH1, + MT6351_PMIC_AUXADC_RQST_CH2, + MT6351_PMIC_AUXADC_RQST_CH3, + MT6351_PMIC_AUXADC_RQST_CH4, + MT6351_PMIC_AUXADC_RQST_CH5, + MT6351_PMIC_AUXADC_RQST_CH6, + MT6351_PMIC_AUXADC_RQST_CH7, + MT6351_PMIC_AUXADC_RQST_CH8, + MT6351_PMIC_AUXADC_RQST_CH9, + MT6351_PMIC_AUXADC_RQST_CH10, + MT6351_PMIC_AUXADC_RQST_CH11, + MT6351_PMIC_AUXADC_RQST_CH12, + MT6351_PMIC_AUXADC_RQST_CH13, + MT6351_PMIC_AUXADC_RQST_CH14, + MT6351_PMIC_AUXADC_RQST_CH15, + MT6351_PMIC_AUXADC_RQST0_SET, + MT6351_PMIC_AUXADC_RQST0_CLR, + MT6351_PMIC_AUXADC_RQST_CH0_BY_MD, + MT6351_PMIC_AUXADC_RQST_CH1_BY_MD, + MT6351_PMIC_AUXADC_RQST_RSV0, + MT6351_PMIC_AUXADC_RQST_CH4_BY_MD, + MT6351_PMIC_AUXADC_RQST_CH7_BY_MD, + MT6351_PMIC_AUXADC_RQST_CH7_BY_GPS, + MT6351_PMIC_AUXADC_RQST_DCXO_BY_MD, + MT6351_PMIC_AUXADC_RQST_DCXO_BY_GPS, + MT6351_PMIC_AUXADC_RQST_RSV1, + MT6351_PMIC_AUXADC_RQST1_SET, + MT6351_PMIC_AUXADC_RQST1_CLR, + MT6351_PMIC_AUXADC_CK_ON_EXTD, + MT6351_PMIC_AUXADC_SRCLKEN_SRC_SEL, + MT6351_PMIC_AUXADC_ADC_PWDB, + MT6351_PMIC_AUXADC_ADC_PWDB_SWCTRL, + MT6351_PMIC_AUXADC_STRUP_CK_ON_ENB, + MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, + MT6351_PMIC_AUXADC_SRCLKEN_CK_EN, + MT6351_PMIC_AUXADC_CK_AON_GPS, + MT6351_PMIC_AUXADC_CK_AON_MD, + MT6351_PMIC_AUXADC_CK_AON, + MT6351_PMIC_AUXADC_CON0_SET, + MT6351_PMIC_AUXADC_CON0_CLR, + MT6351_PMIC_AUXADC_AVG_NUM_SMALL, + MT6351_PMIC_AUXADC_AVG_NUM_LARGE, + MT6351_PMIC_AUXADC_SPL_NUM, + MT6351_PMIC_AUXADC_AVG_NUM_SEL, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHARE, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_LBAT, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_VISMPS, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_WAKEUP, + MT6351_PMIC_AUXADC_SPL_NUM_LARGE, + MT6351_PMIC_AUXADC_SPL_NUM_SLEEP, + MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SEL, + MT6351_PMIC_AUXADC_SPL_NUM_SEL, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHARE, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_LBAT, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_VISMPS, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_WAKEUP, + MT6351_PMIC_AUXADC_TRIM_CH0_SEL, + MT6351_PMIC_AUXADC_TRIM_CH1_SEL, + MT6351_PMIC_AUXADC_TRIM_CH2_SEL, + MT6351_PMIC_AUXADC_TRIM_CH3_SEL, + MT6351_PMIC_AUXADC_TRIM_CH4_SEL, + MT6351_PMIC_AUXADC_TRIM_CH5_SEL, + MT6351_PMIC_AUXADC_TRIM_CH6_SEL, + MT6351_PMIC_AUXADC_TRIM_CH7_SEL, + MT6351_PMIC_AUXADC_TRIM_CH8_SEL, + MT6351_PMIC_AUXADC_TRIM_CH9_SEL, + MT6351_PMIC_AUXADC_TRIM_CH10_SEL, + MT6351_PMIC_AUXADC_TRIM_CH11_SEL, + MT6351_PMIC_AUXADC_ADC_2S_COMP_ENB, + MT6351_PMIC_AUXADC_ADC_TRIM_COMP, + MT6351_PMIC_AUXADC_SW_GAIN_TRIM, + MT6351_PMIC_AUXADC_SW_OFFSET_TRIM, + MT6351_PMIC_AUXADC_RNG_EN, + MT6351_PMIC_AUXADC_DATA_REUSE_SEL, + MT6351_PMIC_AUXADC_TEST_MODE, + MT6351_PMIC_AUXADC_BIT_SEL, + MT6351_PMIC_AUXADC_START_SW, + MT6351_PMIC_AUXADC_START_SWCTRL, + MT6351_PMIC_AUXADC_TS_VBE_SEL, + MT6351_PMIC_AUXADC_TS_VBE_SEL_SWCTRL, + MT6351_PMIC_AUXADC_VBUF_EN, + MT6351_PMIC_AUXADC_VBUF_EN_SWCTRL, + MT6351_PMIC_AUXADC_OUT_SEL, + MT6351_PMIC_AUXADC_DA_DAC, + MT6351_PMIC_AUXADC_DA_DAC_SWCTRL, + MT6351_PMIC_AD_AUXADC_COMP, + MT6351_PMIC_RG_VBUF_EXTEN, + MT6351_PMIC_RG_VBUF_CALEN, + MT6351_PMIC_RG_VBUF_BYP, + MT6351_PMIC_RG_AUX_RSV, + MT6351_PMIC_RG_AUXADC_CALI, + MT6351_PMIC_AUXADC_ADCIN_VSEN_EN, + MT6351_PMIC_AUXADC_ADCIN_VBAT_EN, + MT6351_PMIC_AUXADC_ADCIN_VSEN_MUX_EN, + MT6351_PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN, + MT6351_PMIC_AUXADC_ADCIN_CHR_EN, + MT6351_PMIC_AUXADC_ADCIN_BATON_TDET_EN, + MT6351_PMIC_AUXADC_ACCDET_ANASWCTRL_EN, + MT6351_PMIC_AUXADC_DIG0_RSV0, + MT6351_PMIC_AUXADC_CHSEL, + MT6351_PMIC_AUXADC_SWCTRL_EN, + MT6351_PMIC_AUXADC_SOURCE_LBAT_SEL, + MT6351_PMIC_AUXADC_SOURCE_LBAT2_SEL, + MT6351_PMIC_AUXADC_DIG0_RSV2, + MT6351_PMIC_AUXADC_DIG1_RSV2, + MT6351_PMIC_AUXADC_DAC_EXTD, + MT6351_PMIC_AUXADC_DAC_EXTD_EN, + MT6351_PMIC_AUXADC_PMU_THR_PDN_SW, + MT6351_PMIC_AUXADC_PMU_THR_PDN_SEL, + MT6351_PMIC_AUXADC_PMU_THR_PDN_STATUS, + MT6351_PMIC_AUXADC_DIG0_RSV1, + MT6351_PMIC_AUXADC_START_SHADE_NUM, + MT6351_PMIC_AUXADC_START_SHADE_EN, + MT6351_PMIC_AUXADC_START_SHADE_SEL, + MT6351_PMIC_AUXADC_AUTORPT_PRD, + MT6351_PMIC_AUXADC_AUTORPT_EN, + MT6351_PMIC_AUXADC_LBAT_DEBT_MAX, + MT6351_PMIC_AUXADC_LBAT_DEBT_MIN, + MT6351_PMIC_AUXADC_LBAT_DET_PRD_15_0, + MT6351_PMIC_AUXADC_LBAT_DET_PRD_19_16, + MT6351_PMIC_AUXADC_LBAT_VOLT_MAX, + MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MAX, + MT6351_PMIC_AUXADC_LBAT_EN_MAX, + MT6351_PMIC_AUXADC_LBAT_MAX_IRQ_B, + MT6351_PMIC_AUXADC_LBAT_VOLT_MIN, + MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MIN, + MT6351_PMIC_AUXADC_LBAT_EN_MIN, + MT6351_PMIC_AUXADC_LBAT_MIN_IRQ_B, + MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX, + MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN, + MT6351_PMIC_AUXADC_ACCDET_AUTO_SPL, + MT6351_PMIC_AUXADC_ACCDET_AUTO_RQST_CLR, + MT6351_PMIC_AUXADC_ACCDET_DIG1_RSV0, + MT6351_PMIC_AUXADC_ACCDET_DIG0_RSV0, + MT6351_PMIC_AUXADC_THR_DEBT_MAX, + MT6351_PMIC_AUXADC_THR_DEBT_MIN, + MT6351_PMIC_AUXADC_THR_DET_PRD_15_0, + MT6351_PMIC_AUXADC_THR_DET_PRD_19_16, + MT6351_PMIC_AUXADC_THR_VOLT_MAX, + MT6351_PMIC_AUXADC_THR_IRQ_EN_MAX, + MT6351_PMIC_AUXADC_THR_EN_MAX, + MT6351_PMIC_AUXADC_THR_MAX_IRQ_B, + MT6351_PMIC_AUXADC_THR_VOLT_MIN, + MT6351_PMIC_AUXADC_THR_IRQ_EN_MIN, + MT6351_PMIC_AUXADC_THR_EN_MIN, + MT6351_PMIC_AUXADC_THR_MIN_IRQ_B, + MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX, + MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN, + MT6351_PMIC_EFUSE_GAIN_CH4_TRIM, + MT6351_PMIC_EFUSE_OFFSET_CH4_TRIM, + MT6351_PMIC_EFUSE_GAIN_CH0_TRIM, + MT6351_PMIC_EFUSE_OFFSET_CH0_TRIM, + MT6351_PMIC_EFUSE_GAIN_CH7_TRIM, + MT6351_PMIC_EFUSE_OFFSET_CH7_TRIM, + MT6351_PMIC_AUXADC_FGADC_START_SW, + MT6351_PMIC_AUXADC_FGADC_START_SEL, + MT6351_PMIC_AUXADC_FGADC_R_SW, + MT6351_PMIC_AUXADC_FGADC_R_SEL, + MT6351_PMIC_AUXADC_DBG_DIG0_RSV2, + MT6351_PMIC_AUXADC_DBG_DIG1_RSV2, + MT6351_PMIC_AUXADC_IMPEDANCE_CNT, + MT6351_PMIC_AUXADC_IMPEDANCE_CHSEL, + MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_CLR, + MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS, + MT6351_PMIC_AUXADC_CLR_IMP_CNT_STOP, + MT6351_PMIC_AUXADC_IMPEDANCE_MODE, + MT6351_PMIC_AUXADC_IMP_AUTORPT_PRD, + MT6351_PMIC_AUXADC_IMP_AUTORPT_EN, + MT6351_PMIC_AUXADC_VISMPS0_DEBT_MAX, + MT6351_PMIC_AUXADC_VISMPS0_DEBT_MIN, + MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_15_0, + MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_19_16, + MT6351_PMIC_AUXADC_VISMPS0_VOLT_MAX, + MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MAX, + MT6351_PMIC_AUXADC_VISMPS0_EN_MAX, + MT6351_PMIC_AUXADC_VISMPS0_MAX_IRQ_B, + MT6351_PMIC_AUXADC_VISMPS0_VOLT_MIN, + MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MIN, + MT6351_PMIC_AUXADC_VISMPS0_EN_MIN, + MT6351_PMIC_AUXADC_VISMPS0_MIN_IRQ_B, + MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX, + MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN, + MT6351_PMIC_AUXADC_LBAT2_DEBT_MAX, + MT6351_PMIC_AUXADC_LBAT2_DEBT_MIN, + MT6351_PMIC_AUXADC_LBAT2_DET_PRD_15_0, + MT6351_PMIC_AUXADC_LBAT2_DET_PRD_19_16, + MT6351_PMIC_AUXADC_LBAT2_VOLT_MAX, + MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MAX, + MT6351_PMIC_AUXADC_LBAT2_EN_MAX, + MT6351_PMIC_AUXADC_LBAT2_MAX_IRQ_B, + MT6351_PMIC_AUXADC_LBAT2_VOLT_MIN, + MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MIN, + MT6351_PMIC_AUXADC_LBAT2_EN_MIN, + MT6351_PMIC_AUXADC_LBAT2_MIN_IRQ_B, + MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX, + MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN, + MT6351_PMIC_AUXADC_MDBG_DET_PRD, + MT6351_PMIC_AUXADC_MDBG_DET_EN, + MT6351_PMIC_AUXADC_MDBG_R_PTR, + MT6351_PMIC_AUXADC_MDBG_W_PTR, + MT6351_PMIC_AUXADC_MDBG_BUF_LENGTH, + MT6351_PMIC_AUXADC_MDRT_DET_PRD, + MT6351_PMIC_AUXADC_MDRT_DET_EN, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CNT, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CLR, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SEL, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_EN, + MT6351_PMIC_AUXADC_MDRT_DET_SRCLKEN_IND, + MT6351_PMIC_AUXADC_JEITA_IRQ_EN, + MT6351_PMIC_AUXADC_JEITA_EN, + MT6351_PMIC_AUXADC_JEITA_DET_PRD, + MT6351_PMIC_AUXADC_JEITA_DEBT, + MT6351_PMIC_AUXADC_JEITA_MIPI_DIS, + MT6351_PMIC_AUXADC_JEITA_VOLT_HOT, + MT6351_PMIC_AUXADC_JEITA_HOT_IRQ, + MT6351_PMIC_AUXADC_JEITA_VOLT_WARM, + MT6351_PMIC_AUXADC_JEITA_WARM_IRQ, + MT6351_PMIC_AUXADC_JEITA_VOLT_COOL, + MT6351_PMIC_AUXADC_JEITA_COOL_IRQ, + MT6351_PMIC_AUXADC_JEITA_VOLT_COLD, + MT6351_PMIC_AUXADC_JEITA_COLD_IRQ, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_PRD, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_EN, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND, + MT6351_PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL, + MT6351_PMIC_AUXADC_NAG_EN, + MT6351_PMIC_AUXADC_NAG_CLR, + MT6351_PMIC_AUXADC_NAG_VBAT1_SEL, + MT6351_PMIC_AUXADC_NAG_PRD, + MT6351_PMIC_AUXADC_NAG_IRQ_EN, + MT6351_PMIC_AUXADC_NAG_C_DLTV_IRQ, + MT6351_PMIC_AUXADC_NAG_ZCV, + MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_15_0, + MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_26_16, + MT6351_PMIC_AUXADC_NAG_CNT_15_0, + MT6351_PMIC_AUXADC_NAG_CNT_25_16, + MT6351_PMIC_AUXADC_NAG_DLTV, + MT6351_PMIC_AUXADC_NAG_C_DLTV_15_0, + MT6351_PMIC_AUXADC_NAG_C_DLTV_26_16, + MT6351_PMIC_AD_AUDACCDETCMPOC, + MT6351_PMIC_RG_AUDACCDETANASWCTRLENB, + MT6351_PMIC_RG_ACCDETSEL, + MT6351_PMIC_RG_AUDACCDETSWCTRL, + MT6351_PMIC_RG_AUDACCDETTVDET, + MT6351_PMIC_AUDACCDETAUXADCSWCTRL, + MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SEL, + MT6351_PMIC_RG_AUDACCDETRSV, + MT6351_PMIC_ACCDET_EN, + MT6351_PMIC_ACCDET_SEQ_INIT, + MT6351_PMIC_ACCDET_EINTDET_EN, + MT6351_PMIC_ACCDET_EINT_SEQ_INIT, + MT6351_PMIC_ACCDET_NEGVDET_EN, + MT6351_PMIC_ACCDET_NEGVDET_EN_CTRL, + MT6351_PMIC_ACCDET_ANASWCTRL_SEL, + MT6351_PMIC_ACCDET_CMP_PWM_EN, + MT6351_PMIC_ACCDET_VTH_PWM_EN, + MT6351_PMIC_ACCDET_MBIAS_PWM_EN, + MT6351_PMIC_ACCDET_EINT_PWM_EN, + MT6351_PMIC_ACCDET_CMP_PWM_IDLE, + MT6351_PMIC_ACCDET_VTH_PWM_IDLE, + MT6351_PMIC_ACCDET_MBIAS_PWM_IDLE, + MT6351_PMIC_ACCDET_EINT_PWM_IDLE, + MT6351_PMIC_ACCDET_PWM_WIDTH, + MT6351_PMIC_ACCDET_PWM_THRESH, + MT6351_PMIC_ACCDET_RISE_DELAY, + MT6351_PMIC_ACCDET_FALL_DELAY, + MT6351_PMIC_ACCDET_DEBOUNCE0, + MT6351_PMIC_ACCDET_DEBOUNCE1, + MT6351_PMIC_ACCDET_DEBOUNCE2, + MT6351_PMIC_ACCDET_DEBOUNCE3, + MT6351_PMIC_ACCDET_DEBOUNCE4, + MT6351_PMIC_ACCDET_IVAL_CUR_IN, + MT6351_PMIC_ACCDET_EINT_IVAL_CUR_IN, + MT6351_PMIC_ACCDET_IVAL_SAM_IN, + MT6351_PMIC_ACCDET_EINT_IVAL_SAM_IN, + MT6351_PMIC_ACCDET_IVAL_MEM_IN, + MT6351_PMIC_ACCDET_EINT_IVAL_MEM_IN, + MT6351_PMIC_ACCDET_EINT_IVAL_SEL, + MT6351_PMIC_ACCDET_IVAL_SEL, + MT6351_PMIC_ACCDET_IRQ, + MT6351_PMIC_ACCDET_NEGV_IRQ, + MT6351_PMIC_ACCDET_EINT_IRQ, + MT6351_PMIC_ACCDET_IRQ_CLR, + MT6351_PMIC_ACCDET_NEGV_IRQ_CLR, + MT6351_PMIC_ACCDET_EINT_IRQ_CLR, + MT6351_PMIC_ACCDET_EINT_IRQ_POLARITY, + MT6351_PMIC_ACCDET_TEST_MODE0, + MT6351_PMIC_ACCDET_TEST_MODE1, + MT6351_PMIC_ACCDET_TEST_MODE2, + MT6351_PMIC_ACCDET_TEST_MODE3, + MT6351_PMIC_ACCDET_TEST_MODE4, + MT6351_PMIC_ACCDET_TEST_MODE5, + MT6351_PMIC_ACCDET_PWM_SEL, + MT6351_PMIC_ACCDET_IN_SW, + MT6351_PMIC_ACCDET_CMP_EN_SW, + MT6351_PMIC_ACCDET_VTH_EN_SW, + MT6351_PMIC_ACCDET_MBIAS_EN_SW, + MT6351_PMIC_ACCDET_PWM_EN_SW, + MT6351_PMIC_ACCDET_IN, + MT6351_PMIC_ACCDET_CUR_IN, + MT6351_PMIC_ACCDET_SAM_IN, + MT6351_PMIC_ACCDET_MEM_IN, + MT6351_PMIC_ACCDET_STATE, + MT6351_PMIC_ACCDET_MBIAS_CLK, + MT6351_PMIC_ACCDET_VTH_CLK, + MT6351_PMIC_ACCDET_CMP_CLK, + MT6351_PMIC_DA_NI_AUDACCDETAUXADCSWCTRL, + MT6351_PMIC_ACCDET_EINT_DEB_SEL, + MT6351_PMIC_ACCDET_EINT_DEBOUNCE, + MT6351_PMIC_ACCDET_EINT_PWM_THRESH, + MT6351_PMIC_ACCDET_EINT_PWM_WIDTH, + MT6351_PMIC_ACCDET_NEGV_THRESH, + MT6351_PMIC_ACCDET_EINT_PWM_FALL_DELAY, + MT6351_PMIC_ACCDET_EINT_PWM_RISE_DELAY, + MT6351_PMIC_ACCDET_TEST_MODE13, + MT6351_PMIC_ACCDET_TEST_MODE12, + MT6351_PMIC_ACCDET_NVDETECTOUT_SW, + MT6351_PMIC_ACCDET_TEST_MODE11, + MT6351_PMIC_ACCDET_TEST_MODE10, + MT6351_PMIC_ACCDET_EINTCMPOUT_SW, + MT6351_PMIC_ACCDET_TEST_MODE9, + MT6351_PMIC_ACCDET_TEST_MODE8, + MT6351_PMIC_ACCDET_AUXADC_CTRL_SW, + MT6351_PMIC_ACCDET_TEST_MODE7, + MT6351_PMIC_ACCDET_TEST_MODE6, + MT6351_PMIC_ACCDET_EINTCMP_EN_SW, + MT6351_PMIC_ACCDET_EINT_STATE, + MT6351_PMIC_ACCDET_AUXADC_DEBOUNCE_END, + MT6351_PMIC_ACCDET_AUXADC_CONNECT_PRE, + MT6351_PMIC_ACCDET_EINT_CUR_IN, + MT6351_PMIC_ACCDET_EINT_SAM_IN, + MT6351_PMIC_ACCDET_EINT_MEM_IN, + MT6351_PMIC_AD_NVDETECTOUT, + MT6351_PMIC_AD_EINTCMPOUT, + MT6351_PMIC_DA_NI_EINTCMPEN, + MT6351_PMIC_ACCDET_NEGV_COUNT_IN, + MT6351_PMIC_ACCDET_NEGV_EN_FINAL, + MT6351_PMIC_ACCDET_NEGV_COUNT_END, + MT6351_PMIC_ACCDET_NEGV_MINU, + MT6351_PMIC_ACCDET_NEGV_ADD, + MT6351_PMIC_ACCDET_NEGV_CMP, + MT6351_PMIC_ACCDET_CUR_DEB, + MT6351_PMIC_ACCDET_EINT_CUR_DEB, + MT6351_PMIC_ACCDET_RSV_CON0, + MT6351_PMIC_ACCDET_RSV_CON1, + MT6351_PMIC_ACCDET_AUXADC_CONNECT_TIME, + MT6351_PMIC_RG_VCDT_HV_EN, + MT6351_PMIC_RGS_CHR_LDO_DET, + MT6351_PMIC_RG_PCHR_AUTOMODE, + MT6351_PMIC_RG_CSDAC_EN, + MT6351_PMIC_RG_NORM_CHR_EN, + MT6351_PMIC_RGS_CHRDET, + MT6351_PMIC_RGS_VCDT_LV_DET, + MT6351_PMIC_RGS_VCDT_HV_DET, + MT6351_PMIC_RG_VCDT_LV_VTH, + MT6351_PMIC_RG_VCDT_HV_VTH, + MT6351_PMIC_RG_VBAT_CV_EN, + MT6351_PMIC_RG_VBAT_CC_EN, + MT6351_PMIC_RG_CS_EN, + MT6351_PMIC_RGS_CS_DET, + MT6351_PMIC_RGS_VBAT_CV_DET, + MT6351_PMIC_RGS_VBAT_CC_DET, + MT6351_PMIC_RG_VBAT_NORM_CV_VTH, + MT6351_PMIC_RG_VBAT_CC_VTH, + MT6351_PMIC_RG_NORM_CS_VTH, + MT6351_PMIC_RG_PCHR_TOHTC, + MT6351_PMIC_RG_PCHR_TOLTC, + MT6351_PMIC_RG_VBAT_OV_EN, + MT6351_PMIC_RG_VBAT_OV_VTH, + MT6351_PMIC_RG_VBAT_OV_DEG, + MT6351_PMIC_RGS_VBAT_OV_DET, + MT6351_PMIC_RG_BATON_EN, + MT6351_PMIC_RG_BATON_HT_EN_RSV0, + MT6351_PMIC_BATON_TDET_EN, + MT6351_PMIC_RG_BATON_HT_TRIM, + MT6351_PMIC_RG_BATON_HT_TRIM_SET, + MT6351_PMIC_RG_BATON_TDET_EN, + MT6351_PMIC_RG_CSDAC_DATA, + MT6351_PMIC_RG_FRC_CSVTH_USBDL, + MT6351_PMIC_RGS_PCHR_FLAG_OUT, + MT6351_PMIC_RG_PCHR_FLAG_EN, + MT6351_PMIC_RG_OTG_BVALID_EN, + MT6351_PMIC_RGS_OTG_BVALID_DET, + MT6351_PMIC_RG_PCHR_FLAG_SEL, + MT6351_PMIC_RG_PCHR_TESTMODE, + MT6351_PMIC_RG_CSDAC_TESTMODE, + MT6351_PMIC_RG_PCHR_RST, + MT6351_PMIC_RG_PCHR_FT_CTRL, + MT6351_PMIC_RG_CHRWDT_TD, + MT6351_PMIC_RG_CHRWDT_EN, + MT6351_PMIC_RG_CHRWDT_WR, + MT6351_PMIC_RG_PCHR_RV, + MT6351_PMIC_RG_CHRWDT_INT_EN, + MT6351_PMIC_RG_CHRWDT_FLAG_WR, + MT6351_PMIC_RGS_CHRWDT_OUT, + MT6351_PMIC_RG_USBDL_RST, + MT6351_PMIC_RG_USBDL_SET, + MT6351_PMIC_RG_ADCIN_VSEN_MUX_EN, + MT6351_PMIC_RG_ADCIN_VSEN_EXT_BATON_EN, + MT6351_PMIC_RG_ADCIN_VBAT_EN, + MT6351_PMIC_RG_ADCIN_VSEN_EN, + MT6351_PMIC_RG_ADCIN_CHR_EN, + MT6351_PMIC_RG_UVLO_VTHL, + MT6351_PMIC_RG_UVLO_VH_LAT, + MT6351_PMIC_RG_LBAT_INT_VTH, + MT6351_PMIC_RG_BGR_RSEL, + MT6351_PMIC_RG_BGR_UNCHOP_PH, + MT6351_PMIC_RG_BGR_UNCHOP, + MT6351_PMIC_RG_BC11_BB_CTRL, + MT6351_PMIC_RG_BC11_RST, + MT6351_PMIC_RG_BC11_VSRC_EN, + MT6351_PMIC_RGS_BC11_CMP_OUT, + MT6351_PMIC_RG_BC11_VREF_VTH, + MT6351_PMIC_RG_BC11_CMP_EN, + MT6351_PMIC_RG_BC11_IPD_EN, + MT6351_PMIC_RG_BC11_IPU_EN, + MT6351_PMIC_RG_BC11_BIAS_EN, + MT6351_PMIC_RG_CSDAC_STP_INC, + MT6351_PMIC_RG_CSDAC_STP_DEC, + MT6351_PMIC_RG_CSDAC_DLY, + MT6351_PMIC_RG_CSDAC_STP, + MT6351_PMIC_RG_LOW_ICH_DB, + MT6351_PMIC_RG_CHRIND_ON, + MT6351_PMIC_RG_CHRIND_DIMMING, + MT6351_PMIC_RG_CV_MODE, + MT6351_PMIC_RG_VCDT_MODE, + MT6351_PMIC_RG_CSDAC_MODE, + MT6351_PMIC_RG_TRACKING_EN, + MT6351_PMIC_RG_HWCV_EN, + MT6351_PMIC_RG_ULC_DET_EN, + MT6351_PMIC_RG_BGR_TRIM_EN, + MT6351_PMIC_RG_ICHRG_TRIM, + MT6351_PMIC_RG_BGR_TRIM, + MT6351_PMIC_RG_OVP_TRIM, + MT6351_PMIC_RG_CHR_OSC_TRIM, + MT6351_PMIC_DA_QI_BGR_EXT_BUF_EN, + MT6351_PMIC_RG_BGR_TEST_EN, + MT6351_PMIC_RG_BGR_TEST_RSTB, + MT6351_PMIC_RG_DAC_USBDL_MAX, + MT6351_PMIC_RG_CM_VDEC_TRIG, + MT6351_PMIC_PCHR_CM_VDEC_STATUS, + MT6351_PMIC_RG_CM_VINC_TRIG, + MT6351_PMIC_PCHR_CM_VINC_STATUS, + MT6351_PMIC_RG_CM_VDEC_HPRD1, + MT6351_PMIC_RG_CM_VDEC_HPRD2, + MT6351_PMIC_RG_CM_VDEC_HPRD3, + MT6351_PMIC_RG_CM_VDEC_HPRD4, + MT6351_PMIC_RG_CM_VDEC_HPRD5, + MT6351_PMIC_RG_CM_VDEC_HPRD6, + MT6351_PMIC_RG_CM_VINC_HPRD1, + MT6351_PMIC_RG_CM_VINC_HPRD2, + MT6351_PMIC_RG_CM_VINC_HPRD3, + MT6351_PMIC_RG_CM_VINC_HPRD4, + MT6351_PMIC_RG_CM_VINC_HPRD5, + MT6351_PMIC_RG_CM_VINC_HPRD6, + MT6351_PMIC_RG_CM_LPRD, + MT6351_PMIC_RG_CM_CS_VTHL, + MT6351_PMIC_RG_CM_CS_VTHH, + MT6351_PMIC_RG_PCHR_RSV, + MT6351_PMIC_RG_ENVTEM_D, + MT6351_PMIC_RG_ENVTEM_EN, + MT6351_PMIC_RGS_BATON_HV, + MT6351_PMIC_RG_HW_VTH_CTRL, + MT6351_PMIC_RG_HW_VTH2, + MT6351_PMIC_RG_HW_VTH1, + MT6351_PMIC_RG_CM_VDEC_INT_EN, + MT6351_PMIC_RG_CM_VINC_INT_EN, + MT6351_PMIC_RG_QI_BATON_LT_EN, + MT6351_PMIC_RGS_BATON_UNDET, + MT6351_PMIC_RG_JW_CS_VTH, + MT6351_PMIC_RG_JW_CV_VTH, + MT6351_PMIC_RG_JC_CS_VTH, + MT6351_PMIC_RG_JC_CV_VTH, + MT6351_PMIC_RG_BC11_ACA_EN, + MT6351_PMIC_RG_JEITA_EN, + MT6351_PMIC_RG_VCDT_TRIM, + MT6351_PMIC_RGS_BC11_ID_FLOAT, + MT6351_PMIC_RGS_BC11_ID_A, + MT6351_PMIC_RGS_BC11_ID_B, + MT6351_PMIC_RGS_BC11_ID_C, + MT6351_PMIC_RGS_BC11_ID_GND, + MT6351_PMIC_RGS_BC11_ACA_OTG_DET, + MT6351_PMIC_RG_INDICATOR_TRIM, + MT6351_PMIC_EOSC_CALI_START, + MT6351_PMIC_EOSC_CALI_TD, + MT6351_PMIC_EOSC_CALI_TEST, + MT6351_PMIC_EOSC_CALI_DCXO_RDY_TD, + MT6351_PMIC_FRC_VTCXO0_ON, + MT6351_PMIC_EOSC_CALI_RSV, + MT6351_PMIC_VRTC_PWM_MODE, + MT6351_PMIC_VRTC_PWM_RSV, + MT6351_PMIC_VRTC_PWM_L_DUTY, + MT6351_PMIC_VRTC_PWM_H_DUTY, + MT6351_PMIC_VRTC_CAP_SEL, +} MT6351_FLAGS_LIST_ENUM; + +typedef enum { + PMIC_THR_DET_DIS = MT6351_PMIC_THR_DET_DIS, + PMIC_THR_TEST = MT6351_PMIC_THR_TEST, + PMIC_THR_HWPDN_EN = MT6351_PMIC_THR_HWPDN_EN, + PMIC_STRUP_THERMAL_DEB_SEL = MT6351_PMIC_STRUP_THERMAL_DEB_SEL, + PMIC_USBDL = MT6351_PMIC_USBDL, + PMIC_PMU_THERMAL_DEB = MT6351_PMIC_PMU_THERMAL_DEB, + PMIC_PMU_THR_DEB = MT6351_PMIC_PMU_THR_DEB, + PMIC_PMU_THR_STATUS = MT6351_PMIC_PMU_THR_STATUS, + PMIC_STRUP_THER_DEB_RMAX = MT6351_PMIC_STRUP_THER_DEB_RMAX, + PMIC_STRUP_THER_DEB_FMAX = MT6351_PMIC_STRUP_THER_DEB_FMAX, + PMIC_DDUVLO_DEB_EN = MT6351_PMIC_DDUVLO_DEB_EN, + PMIC_PWRBB_DEB_EN = MT6351_PMIC_PWRBB_DEB_EN, + PMIC_STRUP_OSC_EN = MT6351_PMIC_STRUP_OSC_EN, + PMIC_STRUP_OSC_EN_SEL = MT6351_PMIC_STRUP_OSC_EN_SEL, + PMIC_STRUP_FT_CTRL = MT6351_PMIC_STRUP_FT_CTRL, + PMIC_STRUP_PWRON_FORCE = MT6351_PMIC_STRUP_PWRON_FORCE, + PMIC_BIAS_GEN_EN_FORCE = MT6351_PMIC_BIAS_GEN_EN_FORCE, + PMIC_STRUP_PWRON = MT6351_PMIC_STRUP_PWRON, + PMIC_STRUP_PWRON_SEL = MT6351_PMIC_STRUP_PWRON_SEL, + PMIC_BIAS_GEN_EN = MT6351_PMIC_BIAS_GEN_EN, + PMIC_BIAS_GEN_EN_SEL = MT6351_PMIC_BIAS_GEN_EN_SEL, + PMIC_RTC_XOSC32_ENB_SW = MT6351_PMIC_RTC_XOSC32_ENB_SW, + PMIC_RTC_XOSC32_ENB_SEL = MT6351_PMIC_RTC_XOSC32_ENB_SEL, + PMIC_STRUP_DIG_IO_PG_FORCE = MT6351_PMIC_STRUP_DIG_IO_PG_FORCE, + PMIC_RG_STRUP_VUSB33_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VUSB33_PG_H2L_EN, + PMIC_RG_STRUP_VGPU_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VGPU_PG_H2L_EN, + PMIC_RG_STRUP_VDRAM_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VDRAM_PG_H2L_EN, + PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN, + PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN, + PMIC_RG_STRUP_VA10_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VA10_PG_H2L_EN, + PMIC_RG_STRUP_VEMC_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VEMC_PG_H2L_EN, + PMIC_RG_STRUP_VS2_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VS2_PG_H2L_EN, + PMIC_RG_STRUP_VMODEM_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VMODEM_PG_H2L_EN, + PMIC_RG_STRUP_VMD1_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VMD1_PG_H2L_EN, + PMIC_RG_STRUP_VCORE_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VCORE_PG_H2L_EN, + PMIC_RG_STRUP_VA18_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VA18_PG_H2L_EN, + PMIC_RG_STRUP_VS1_PG_H2L_EN = MT6351_PMIC_RG_STRUP_VS1_PG_H2L_EN, + PMIC_RG_STRUP_VTCXO24_PG_ENB = MT6351_PMIC_RG_STRUP_VTCXO24_PG_ENB, + PMIC_RG_STRUP_VUSB33_PG_ENB = MT6351_PMIC_RG_STRUP_VUSB33_PG_ENB, + PMIC_RG_STRUP_VGPU_PG_ENB = MT6351_PMIC_RG_STRUP_VGPU_PG_ENB, + PMIC_RG_STRUP_VDRAM_PG_ENB = MT6351_PMIC_RG_STRUP_VDRAM_PG_ENB, + PMIC_RG_STRUP_VSRAM_PROC_PG_ENB = MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_ENB, + PMIC_RG_STRUP_VSRAM_MD_PG_ENB = MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_ENB, + PMIC_RG_STRUP_VIO28_PG_ENB = MT6351_PMIC_RG_STRUP_VIO28_PG_ENB, + PMIC_RG_STRUP_VA10_PG_ENB = MT6351_PMIC_RG_STRUP_VA10_PG_ENB, + PMIC_RG_STRUP_VEMC_PG_ENB = MT6351_PMIC_RG_STRUP_VEMC_PG_ENB, + PMIC_RG_STRUP_VIO18_PG_ENB = MT6351_PMIC_RG_STRUP_VIO18_PG_ENB, + PMIC_RG_STRUP_VS2_PG_ENB = MT6351_PMIC_RG_STRUP_VS2_PG_ENB, + PMIC_RG_STRUP_VMODEM_PG_ENB = MT6351_PMIC_RG_STRUP_VMODEM_PG_ENB, + PMIC_RG_STRUP_VMD1_PG_ENB = MT6351_PMIC_RG_STRUP_VMD1_PG_ENB, + PMIC_RG_STRUP_VCORE_PG_ENB = MT6351_PMIC_RG_STRUP_VCORE_PG_ENB, + PMIC_RG_STRUP_VA18_PG_ENB = MT6351_PMIC_RG_STRUP_VA18_PG_ENB, + PMIC_RG_STRUP_VS1_PG_ENB = MT6351_PMIC_RG_STRUP_VS1_PG_ENB, + PMIC_RG_STRUP_VXO22_PG_ENB = MT6351_PMIC_RG_STRUP_VXO22_PG_ENB, + PMIC_RG_STRUP_VGPU_OC_H2L_EN = MT6351_PMIC_RG_STRUP_VGPU_OC_H2L_EN, + PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN = MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN, + PMIC_RG_STRUP_VS2_OC_H2L_EN = MT6351_PMIC_RG_STRUP_VS2_OC_H2L_EN, + PMIC_RG_STRUP_VMODEM_OC_H2L_EN = MT6351_PMIC_RG_STRUP_VMODEM_OC_H2L_EN, + PMIC_RG_STRUP_VMD1_OC_H2L_EN = MT6351_PMIC_RG_STRUP_VMD1_OC_H2L_EN, + PMIC_RG_STRUP_VCORE_OC_H2L_EN = MT6351_PMIC_RG_STRUP_VCORE_OC_H2L_EN, + PMIC_RG_STRUP_VS1_OC_H2L_EN = MT6351_PMIC_RG_STRUP_VS1_OC_H2L_EN, + PMIC_RG_STRUP_VGPU_OC_ENB = MT6351_PMIC_RG_STRUP_VGPU_OC_ENB, + PMIC_RG_STRUP_VSRAM_MD_OC_ENB = MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_ENB, + PMIC_RG_STRUP_VS2_OC_ENB = MT6351_PMIC_RG_STRUP_VS2_OC_ENB, + PMIC_RG_STRUP_VMODEM_OC_ENB = MT6351_PMIC_RG_STRUP_VMODEM_OC_ENB, + PMIC_RG_STRUP_VMD1_OC_ENB = MT6351_PMIC_RG_STRUP_VMD1_OC_ENB, + PMIC_RG_STRUP_VCORE_OC_ENB = MT6351_PMIC_RG_STRUP_VCORE_OC_ENB, + PMIC_RG_STRUP_VS1_OC_ENB = MT6351_PMIC_RG_STRUP_VS1_OC_ENB, + PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS, + PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS, + PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS, + PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS, + PMIC_RG_STRUP_VS2_OC_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VS2_OC_DEB_BYPASS, + PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS, + PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS, + PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS, + PMIC_RG_STRUP_VS1_OC_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VS1_OC_DEB_BYPASS, + PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS, + PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS, + PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS, + PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS, + PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS, + PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS, + PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS, + PMIC_RG_STRUP_VA10_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VA10_PG_DEB_BYPASS, + PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS, + PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS, + PMIC_RG_STRUP_VS2_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VS2_PG_DEB_BYPASS, + PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS, + PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS, + PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS, + PMIC_RG_STRUP_VA18_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VA18_PG_DEB_BYPASS, + PMIC_RG_STRUP_VS1_PG_DEB_BYPASS = MT6351_PMIC_RG_STRUP_VS1_PG_DEB_BYPASS, + PMIC_CLR_JUST_RST = MT6351_PMIC_CLR_JUST_RST, + PMIC_UVLO_L2H_DEB_EN = MT6351_PMIC_UVLO_L2H_DEB_EN, + PMIC_JUST_PWRKEY_RST = MT6351_PMIC_JUST_PWRKEY_RST, + PMIC_DA_QI_OSC_EN = MT6351_PMIC_DA_QI_OSC_EN, + PMIC_STRUP_EXT_PMIC_EN = MT6351_PMIC_STRUP_EXT_PMIC_EN, + PMIC_STRUP_EXT_PMIC_SEL = MT6351_PMIC_STRUP_EXT_PMIC_SEL, + PMIC_STRUP_CON8_RSV0 = MT6351_PMIC_STRUP_CON8_RSV0, + PMIC_DA_QI_EXT_PMIC_EN = MT6351_PMIC_DA_QI_EXT_PMIC_EN, + PMIC_STRUP_AUXADC_START_SW = MT6351_PMIC_STRUP_AUXADC_START_SW, + PMIC_STRUP_AUXADC_RSTB_SW = MT6351_PMIC_STRUP_AUXADC_RSTB_SW, + PMIC_STRUP_AUXADC_START_SEL = MT6351_PMIC_STRUP_AUXADC_START_SEL, + PMIC_STRUP_AUXADC_RSTB_SEL = MT6351_PMIC_STRUP_AUXADC_RSTB_SEL, + PMIC_STRUP_PWROFF_SEQ_EN = MT6351_PMIC_STRUP_PWROFF_SEQ_EN, + PMIC_STRUP_PWROFF_PREOFF_EN = MT6351_PMIC_STRUP_PWROFF_PREOFF_EN, + PMIC_STRUP_PP_EN = MT6351_PMIC_STRUP_PP_EN, + PMIC_STRUP_PP_EN_SEL = MT6351_PMIC_STRUP_PP_EN_SEL, + PMIC_STRUP_DIG0_RSV0 = MT6351_PMIC_STRUP_DIG0_RSV0, + PMIC_STRUP_DIG1_RSV0 = MT6351_PMIC_STRUP_DIG1_RSV0, + PMIC_RG_RSV_SWREG = MT6351_PMIC_RG_RSV_SWREG, + PMIC_STRUP_PP_EN_PWROFF_CNT = MT6351_PMIC_STRUP_PP_EN_PWROFF_CNT, + PMIC_STRUP_UVLO_U1U2_SEL = MT6351_PMIC_STRUP_UVLO_U1U2_SEL, + PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL = MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL, + PMIC_STRUP_AUXADC_RPCNT_MAX = MT6351_PMIC_STRUP_AUXADC_RPCNT_MAX, + PMIC_RG_STRUP_THR_OVER_110_CLR = MT6351_PMIC_RG_STRUP_THR_OVER_110_CLR, + PMIC_RG_STRUP_THR_110_CLR = MT6351_PMIC_RG_STRUP_THR_110_CLR, + PMIC_RG_STRUP_THR_125_CLR = MT6351_PMIC_RG_STRUP_THR_125_CLR, + PMIC_RG_STRUP_THR_CLR = MT6351_PMIC_RG_STRUP_THR_CLR, + PMIC_RG_STRUP_THR_OVER_110_IRQ_EN = MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_EN, + PMIC_RG_STRUP_THR_110_IRQ_EN = MT6351_PMIC_RG_STRUP_THR_110_IRQ_EN, + PMIC_RG_STRUP_THR_125_IRQ_EN = MT6351_PMIC_RG_STRUP_THR_125_IRQ_EN, + PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS = MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS, + PMIC_RG_STRUP_THR_110_IRQ_STATUS = MT6351_PMIC_RG_STRUP_THR_110_IRQ_STATUS, + PMIC_RG_STRUP_THR_125_IRQ_STATUS = MT6351_PMIC_RG_STRUP_THR_125_IRQ_STATUS, + PMIC_STRUP_PG_STATUS_CLR = MT6351_PMIC_STRUP_PG_STATUS_CLR, + PMIC_RG_STRUP_LONG_PRESS_EXT_SEL = MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_SEL, + PMIC_RG_STRUP_LONG_PRESS_EXT_TD = MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_TD, + PMIC_RG_STRUP_LONG_PRESS_EXT_EN = MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_EN, + PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL = MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL, + PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL = MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL, + PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL = MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL, + PMIC_RG_STRUP_ENVTEM = MT6351_PMIC_RG_STRUP_ENVTEM, + PMIC_RG_STRUP_ENVTEM_CTRL = MT6351_PMIC_RG_STRUP_ENVTEM_CTRL, + PMIC_RG_STRUP_PWRKEY_COUNT_RESET = MT6351_PMIC_RG_STRUP_PWRKEY_COUNT_RESET, + PMIC_RGS_ANA_CHIP_ID = MT6351_PMIC_RGS_ANA_CHIP_ID, + PMIC_RG_PP_EN_DRVSEL = MT6351_PMIC_RG_PP_EN_DRVSEL, + PMIC_RG_FCHR_PU_EN = MT6351_PMIC_RG_FCHR_PU_EN, + PMIC_RG_PMU_RSV = MT6351_PMIC_RG_PMU_RSV, + PMIC_RG_FCHR_KEYDET_EN = MT6351_PMIC_RG_FCHR_KEYDET_EN, + PMIC_RG_EN_DRVSEL = MT6351_PMIC_RG_EN_DRVSEL, + PMIC_RG_RST_DRVSEL = MT6351_PMIC_RG_RST_DRVSEL, + PMIC_RG_STRUP_IREF_TRIM = MT6351_PMIC_RG_STRUP_IREF_TRIM, + PMIC_RG_VREF_BG = MT6351_PMIC_RG_VREF_BG, + PMIC_RG_THR_TMODE = MT6351_PMIC_RG_THR_TMODE, + PMIC_RG_STRUP_THR_SEL = MT6351_PMIC_RG_STRUP_THR_SEL, + PMIC_RG_THRDET_SEL = MT6351_PMIC_RG_THRDET_SEL, + PMIC_HWCID = MT6351_PMIC_HWCID, + PMIC_SWCID = MT6351_PMIC_SWCID, + PMIC_RG_SRCLKEN_IN0_EN = MT6351_PMIC_RG_SRCLKEN_IN0_EN, + PMIC_RG_SRCLKEN_IN1_EN = MT6351_PMIC_RG_SRCLKEN_IN1_EN, + PMIC_RG_OSC_SEL = MT6351_PMIC_RG_OSC_SEL, + PMIC_RG_SRCLKEN_IN2_EN = MT6351_PMIC_RG_SRCLKEN_IN2_EN, + PMIC_RG_SRCLKEN_IN0_HW_MODE = MT6351_PMIC_RG_SRCLKEN_IN0_HW_MODE, + PMIC_RG_SRCLKEN_IN1_HW_MODE = MT6351_PMIC_RG_SRCLKEN_IN1_HW_MODE, + PMIC_RG_OSC_SEL_HW_MODE = MT6351_PMIC_RG_OSC_SEL_HW_MODE, + PMIC_RG_SRCLKEN_IN_SYNC_EN = MT6351_PMIC_RG_SRCLKEN_IN_SYNC_EN, + PMIC_RG_OSC_EN_AUTO_OFF = MT6351_PMIC_RG_OSC_EN_AUTO_OFF, + PMIC_TEST_OUT = MT6351_PMIC_TEST_OUT, + PMIC_RG_MON_FLAG_SEL = MT6351_PMIC_RG_MON_FLAG_SEL, + PMIC_RG_MON_GRP_SEL = MT6351_PMIC_RG_MON_GRP_SEL, + PMIC_RG_NANDTREE_MODE = MT6351_PMIC_RG_NANDTREE_MODE, + PMIC_RG_TEST_AUXADC = MT6351_PMIC_RG_TEST_AUXADC, + PMIC_RG_EFUSE_MODE = MT6351_PMIC_RG_EFUSE_MODE, + PMIC_RG_TEST_STRUP = MT6351_PMIC_RG_TEST_STRUP, + PMIC_TESTMODE_SW = MT6351_PMIC_TESTMODE_SW, + PMIC_EN_STATUS_VLDO28 = MT6351_PMIC_EN_STATUS_VLDO28, + PMIC_EN_STATUS_VIO28 = MT6351_PMIC_EN_STATUS_VIO28, + PMIC_EN_STATUS_VMCH = MT6351_PMIC_EN_STATUS_VMCH, + PMIC_EN_STATUS_VMC = MT6351_PMIC_EN_STATUS_VMC, + PMIC_EN_STATUS_VEMC = MT6351_PMIC_EN_STATUS_VEMC, + PMIC_EN_STATUS_VSIM2 = MT6351_PMIC_EN_STATUS_VSIM2, + PMIC_EN_STATUS_VSIM1 = MT6351_PMIC_EN_STATUS_VSIM1, + PMIC_EN_STATUS_VEFUSE = MT6351_PMIC_EN_STATUS_VEFUSE, + PMIC_EN_STATUS_VUSB33 = MT6351_PMIC_EN_STATUS_VUSB33, + PMIC_EN_STATUS_VCN33 = MT6351_PMIC_EN_STATUS_VCN33, + PMIC_EN_STATUS_VCAMA = MT6351_PMIC_EN_STATUS_VCAMA, + PMIC_EN_STATUS_VCN28 = MT6351_PMIC_EN_STATUS_VCN28, + PMIC_EN_STATUS_VTCXO24 = MT6351_PMIC_EN_STATUS_VTCXO24, + PMIC_EN_STATUS_VTCXO28 = MT6351_PMIC_EN_STATUS_VTCXO28, + PMIC_EN_STATUS_VA18 = MT6351_PMIC_EN_STATUS_VA18, + PMIC_EN_STATUS_VRTC = MT6351_PMIC_EN_STATUS_VRTC, + PMIC_EN_STATUS_VBIF28 = MT6351_PMIC_EN_STATUS_VBIF28, + PMIC_EN_STATUS_VGP3 = MT6351_PMIC_EN_STATUS_VGP3, + PMIC_EN_STATUS_VMIPI = MT6351_PMIC_EN_STATUS_VMIPI, + PMIC_EN_STATUS_VDRAM = MT6351_PMIC_EN_STATUS_VDRAM, + PMIC_EN_STATUS_VA10 = MT6351_PMIC_EN_STATUS_VA10, + PMIC_EN_STATUS_VRF12 = MT6351_PMIC_EN_STATUS_VRF12, + PMIC_EN_STATUS_VXO22 = MT6351_PMIC_EN_STATUS_VXO22, + PMIC_EN_STATUS_VSRAM_PROC = MT6351_PMIC_EN_STATUS_VSRAM_PROC, + PMIC_EN_STATUS_VCAMIO = MT6351_PMIC_EN_STATUS_VCAMIO, + PMIC_EN_STATUS_VCN18 = MT6351_PMIC_EN_STATUS_VCN18, + PMIC_EN_STATUS_VIO18 = MT6351_PMIC_EN_STATUS_VIO18, + PMIC_EN_STATUS_VRF18 = MT6351_PMIC_EN_STATUS_VRF18, + PMIC_EN_STATUS_VCAMD = MT6351_PMIC_EN_STATUS_VCAMD, + PMIC_EN_STATUS_VIBR = MT6351_PMIC_EN_STATUS_VIBR, + PMIC_OC_STATUS_VIBR = MT6351_PMIC_OC_STATUS_VIBR, + PMIC_OC_STATUS_VLDO28 = MT6351_PMIC_OC_STATUS_VLDO28, + PMIC_OC_STATUS_VIO28 = MT6351_PMIC_OC_STATUS_VIO28, + PMIC_OC_STATUS_VMC = MT6351_PMIC_OC_STATUS_VMC, + PMIC_OC_STATUS_VMCH = MT6351_PMIC_OC_STATUS_VMCH, + PMIC_OC_STATUS_VEMC = MT6351_PMIC_OC_STATUS_VEMC, + PMIC_OC_STATUS_VSIM2 = MT6351_PMIC_OC_STATUS_VSIM2, + PMIC_OC_STATUS_VSIM1 = MT6351_PMIC_OC_STATUS_VSIM1, + PMIC_OC_STATUS_VEFUSE = MT6351_PMIC_OC_STATUS_VEFUSE, + PMIC_OC_STATUS_VUSB33 = MT6351_PMIC_OC_STATUS_VUSB33, + PMIC_OC_STATUS_VCN33 = MT6351_PMIC_OC_STATUS_VCN33, + PMIC_OC_STATUS_VCAMA = MT6351_PMIC_OC_STATUS_VCAMA, + PMIC_OC_STATUS_VCN28 = MT6351_PMIC_OC_STATUS_VCN28, + PMIC_OC_STATUS_VTCXO24 = MT6351_PMIC_OC_STATUS_VTCXO24, + PMIC_OC_STATUS_VTCXO28 = MT6351_PMIC_OC_STATUS_VTCXO28, + PMIC_OC_STATUS_VA18 = MT6351_PMIC_OC_STATUS_VA18, + PMIC_OC_STATUS_VBIF28 = MT6351_PMIC_OC_STATUS_VBIF28, + PMIC_OC_STATUS_VGP3 = MT6351_PMIC_OC_STATUS_VGP3, + PMIC_OC_STATUS_VMIPI = MT6351_PMIC_OC_STATUS_VMIPI, + PMIC_OC_STATUS_VDRAM = MT6351_PMIC_OC_STATUS_VDRAM, + PMIC_OC_STATUS_VA10 = MT6351_PMIC_OC_STATUS_VA10, + PMIC_OC_STATUS_VRF12 = MT6351_PMIC_OC_STATUS_VRF12, + PMIC_OC_STATUS_VXO22 = MT6351_PMIC_OC_STATUS_VXO22, + PMIC_OC_STATUS_VSRAM_PROC = MT6351_PMIC_OC_STATUS_VSRAM_PROC, + PMIC_OC_STATUS_VCAMIO = MT6351_PMIC_OC_STATUS_VCAMIO, + PMIC_OC_STATUS_VCN18 = MT6351_PMIC_OC_STATUS_VCN18, + PMIC_OC_STATUS_VIO18 = MT6351_PMIC_OC_STATUS_VIO18, + PMIC_OC_STATUS_VRF18 = MT6351_PMIC_OC_STATUS_VRF18, + PMIC_OC_STATUS_VCAMD = MT6351_PMIC_OC_STATUS_VCAMD, + PMIC_VA18_PG_DEB = MT6351_PMIC_VA18_PG_DEB, + PMIC_VCORE_PG_DEB = MT6351_PMIC_VCORE_PG_DEB, + PMIC_VMD1_PG_DEB = MT6351_PMIC_VMD1_PG_DEB, + PMIC_VMODEM_PG_DEB = MT6351_PMIC_VMODEM_PG_DEB, + PMIC_VS2_PG_DEB = MT6351_PMIC_VS2_PG_DEB, + PMIC_VIO18_PG_DEB = MT6351_PMIC_VIO18_PG_DEB, + PMIC_VEMC_PG_DEB = MT6351_PMIC_VEMC_PG_DEB, + PMIC_VA10_PG_DEB = MT6351_PMIC_VA10_PG_DEB, + PMIC_VIO28_PG_DEB = MT6351_PMIC_VIO28_PG_DEB, + PMIC_VSRAM_MD_PG_DEB = MT6351_PMIC_VSRAM_MD_PG_DEB, + PMIC_VSRAM_PROC_PG_DEB = MT6351_PMIC_VSRAM_PROC_PG_DEB, + PMIC_VDRAM_PG_DEB = MT6351_PMIC_VDRAM_PG_DEB, + PMIC_VGPU_PG_DEB = MT6351_PMIC_VGPU_PG_DEB, + PMIC_VUSB33_PG_DEB = MT6351_PMIC_VUSB33_PG_DEB, + PMIC_VXO22_PG_DEB = MT6351_PMIC_VXO22_PG_DEB, + PMIC_VTCXO24_PG_DEB = MT6351_PMIC_VTCXO24_PG_DEB, + PMIC_VS1_PG_DEB = MT6351_PMIC_VS1_PG_DEB, + PMIC_STRUP_VA18_PG_STATUS = MT6351_PMIC_STRUP_VA18_PG_STATUS, + PMIC_STRUP_VCORE_PG_STATUS = MT6351_PMIC_STRUP_VCORE_PG_STATUS, + PMIC_STRUP_VMD1_PG_STATUS = MT6351_PMIC_STRUP_VMD1_PG_STATUS, + PMIC_STRUP_VMODEM_PG_STATUS = MT6351_PMIC_STRUP_VMODEM_PG_STATUS, + PMIC_STRUP_VS2_PG_STATUS = MT6351_PMIC_STRUP_VS2_PG_STATUS, + PMIC_STRUP_VIO18_PG_STATUS = MT6351_PMIC_STRUP_VIO18_PG_STATUS, + PMIC_STRUP_VEMC_PG_STATUS = MT6351_PMIC_STRUP_VEMC_PG_STATUS, + PMIC_STRUP_VA10_PG_STATUS = MT6351_PMIC_STRUP_VA10_PG_STATUS, + PMIC_STRUP_VIO28_PG_STATUS = MT6351_PMIC_STRUP_VIO28_PG_STATUS, + PMIC_STRUP_VSRAM_MD_PG_STATUS = MT6351_PMIC_STRUP_VSRAM_MD_PG_STATUS, + PMIC_STRUP_VSRAM_PROC_PG_STATUS = MT6351_PMIC_STRUP_VSRAM_PROC_PG_STATUS, + PMIC_STRUP_VDRAM_PG_STATUS = MT6351_PMIC_STRUP_VDRAM_PG_STATUS, + PMIC_STRUP_VGPU_PG_STATUS = MT6351_PMIC_STRUP_VGPU_PG_STATUS, + PMIC_STRUP_VUSB33_PG_STATUS = MT6351_PMIC_STRUP_VUSB33_PG_STATUS, + PMIC_STRUP_VXO22_PG_STATUS = MT6351_PMIC_STRUP_VXO22_PG_STATUS, + PMIC_STRUP_VTCXO24_PG_STATUS = MT6351_PMIC_STRUP_VTCXO24_PG_STATUS, + PMIC_STRUP_VS1_PG_STATUS = MT6351_PMIC_STRUP_VS1_PG_STATUS, + PMIC_THERMAL_BACK110 = MT6351_PMIC_THERMAL_BACK110, + PMIC_THERMAL_OVER110 = MT6351_PMIC_THERMAL_OVER110, + PMIC_THERMAL_OVER125 = MT6351_PMIC_THERMAL_OVER125, + PMIC_STRUP_THERMAL_STATUS = MT6351_PMIC_STRUP_THERMAL_STATUS, + PMIC_PMU_TEST_MODE_SCAN = MT6351_PMIC_PMU_TEST_MODE_SCAN, + PMIC_PWRKEY_DEB = MT6351_PMIC_PWRKEY_DEB, + PMIC_HOMEKEY_DEB = MT6351_PMIC_HOMEKEY_DEB, + PMIC_RTC_XTAL_DET_DONE = MT6351_PMIC_RTC_XTAL_DET_DONE, + PMIC_XOSC32_ENB_DET = MT6351_PMIC_XOSC32_ENB_DET, + PMIC_RTC_XTAL_DET_RSV = MT6351_PMIC_RTC_XTAL_DET_RSV, + PMIC_RG_PMU_TDSEL = MT6351_PMIC_RG_PMU_TDSEL, + PMIC_RG_SPI_TDSEL = MT6351_PMIC_RG_SPI_TDSEL, + PMIC_RG_AUD_TDSEL = MT6351_PMIC_RG_AUD_TDSEL, + PMIC_RG_E32CAL_TDSEL = MT6351_PMIC_RG_E32CAL_TDSEL, + PMIC_RG_PMU_RDSEL = MT6351_PMIC_RG_PMU_RDSEL, + PMIC_RG_SPI_RDSEL = MT6351_PMIC_RG_SPI_RDSEL, + PMIC_RG_AUD_RDSEL = MT6351_PMIC_RG_AUD_RDSEL, + PMIC_RG_E32CAL_RDSEL = MT6351_PMIC_RG_E32CAL_RDSEL, + PMIC_RG_SMT_WDTRSTB_IN = MT6351_PMIC_RG_SMT_WDTRSTB_IN, + PMIC_RG_SMT_HOMEKEY = MT6351_PMIC_RG_SMT_HOMEKEY, + PMIC_RG_SMT_SRCLKEN_IN0 = MT6351_PMIC_RG_SMT_SRCLKEN_IN0, + PMIC_RG_SMT_SRCLKEN_IN1 = MT6351_PMIC_RG_SMT_SRCLKEN_IN1, + PMIC_RG_SMT_RTC_32K1V8_0 = MT6351_PMIC_RG_SMT_RTC_32K1V8_0, + PMIC_RG_SMT_RTC_32K1V8_1 = MT6351_PMIC_RG_SMT_RTC_32K1V8_1, + PMIC_RG_SMT_SPI_CLK = MT6351_PMIC_RG_SMT_SPI_CLK, + PMIC_RG_SMT_SPI_CSN = MT6351_PMIC_RG_SMT_SPI_CSN, + PMIC_RG_SMT_SPI_MOSI = MT6351_PMIC_RG_SMT_SPI_MOSI, + PMIC_RG_SMT_SPI_MISO = MT6351_PMIC_RG_SMT_SPI_MISO, + PMIC_RG_SMT_AUD_CLK = MT6351_PMIC_RG_SMT_AUD_CLK, + PMIC_RG_SMT_AUD_DAT_MOSI = MT6351_PMIC_RG_SMT_AUD_DAT_MOSI, + PMIC_RG_SMT_AUD_DAT_MISO = MT6351_PMIC_RG_SMT_AUD_DAT_MISO, + PMIC_RG_SMT_ANC_DAT_MOSI = MT6351_PMIC_RG_SMT_ANC_DAT_MOSI, + PMIC_RG_SMT_VOW_CLK_MISO = MT6351_PMIC_RG_SMT_VOW_CLK_MISO, + PMIC_RG_SMT_ENBB = MT6351_PMIC_RG_SMT_ENBB, + PMIC_RG_SMT_XOSC_EN = MT6351_PMIC_RG_SMT_XOSC_EN, + PMIC_RG_OCTL_SRCLKEN_IN0 = MT6351_PMIC_RG_OCTL_SRCLKEN_IN0, + PMIC_RG_OCTL_SRCLKEN_IN1 = MT6351_PMIC_RG_OCTL_SRCLKEN_IN1, + PMIC_RG_OCTL_RTC_32K1V8_0 = MT6351_PMIC_RG_OCTL_RTC_32K1V8_0, + PMIC_RG_OCTL_RTC_32K1V8_1 = MT6351_PMIC_RG_OCTL_RTC_32K1V8_1, + PMIC_RG_OCTL_SPI_CLK = MT6351_PMIC_RG_OCTL_SPI_CLK, + PMIC_RG_OCTL_SPI_CSN = MT6351_PMIC_RG_OCTL_SPI_CSN, + PMIC_RG_OCTL_SPI_MOSI = MT6351_PMIC_RG_OCTL_SPI_MOSI, + PMIC_RG_OCTL_SPI_MISO = MT6351_PMIC_RG_OCTL_SPI_MISO, + PMIC_RG_OCTL_AUD_DAT_MOSI = MT6351_PMIC_RG_OCTL_AUD_DAT_MOSI, + PMIC_RG_OCTL_AUD_DAT_MISO = MT6351_PMIC_RG_OCTL_AUD_DAT_MISO, + PMIC_RG_OCTL_AUD_CLK = MT6351_PMIC_RG_OCTL_AUD_CLK, + PMIC_RG_OCTL_ANC_DAT_MOSI = MT6351_PMIC_RG_OCTL_ANC_DAT_MOSI, + PMIC_RG_OCTL_HOMEKEY = MT6351_PMIC_RG_OCTL_HOMEKEY, + PMIC_RG_OCTL_ENBB = MT6351_PMIC_RG_OCTL_ENBB, + PMIC_RG_OCTL_XOSC_EN = MT6351_PMIC_RG_OCTL_XOSC_EN, + PMIC_RG_OCTL_VOW_CLK_MISO = MT6351_PMIC_RG_OCTL_VOW_CLK_MISO, + PMIC_TOP_STATUS = MT6351_PMIC_TOP_STATUS, + PMIC_TOP_STATUS_SET = MT6351_PMIC_TOP_STATUS_SET, + PMIC_TOP_STATUS_CLR = MT6351_PMIC_TOP_STATUS_CLR, + PMIC_RG_G_SMPS_PD_CK_PDN = MT6351_PMIC_RG_G_SMPS_PD_CK_PDN, + PMIC_RG_G_SMPS_AUD_CK_PDN = MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN, + PMIC_RG_G_DRV_2M_CK_PDN = MT6351_PMIC_RG_G_DRV_2M_CK_PDN, + PMIC_RG_DRV_32K_CK_PDN = MT6351_PMIC_RG_DRV_32K_CK_PDN, + PMIC_RG_DRV_ISINK0_CK_PDN = MT6351_PMIC_RG_DRV_ISINK0_CK_PDN, + PMIC_RG_DRV_ISINK1_CK_PDN = MT6351_PMIC_RG_DRV_ISINK1_CK_PDN, + PMIC_RG_DRV_ISINK2_CK_PDN = MT6351_PMIC_RG_DRV_ISINK2_CK_PDN, + PMIC_RG_DRV_ISINK3_CK_PDN = MT6351_PMIC_RG_DRV_ISINK3_CK_PDN, + PMIC_RG_AUXADC_1M_CK_PDN = MT6351_PMIC_RG_AUXADC_1M_CK_PDN, + PMIC_RG_AUXADC_SMPS_CK_PDN = MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN, + PMIC_RG_AUXADC_RNG_CK_PDN = MT6351_PMIC_RG_AUXADC_RNG_CK_PDN, + PMIC_RG_AUXADC_26M_CK_PDN = MT6351_PMIC_RG_AUXADC_26M_CK_PDN, + PMIC_RG_AUDNCP_CK_PDN = MT6351_PMIC_RG_AUDNCP_CK_PDN, + PMIC_RG_AUDIF_CK_PDN = MT6351_PMIC_RG_AUDIF_CK_PDN, + PMIC_RG_AUD_CK_PDN = MT6351_PMIC_RG_AUD_CK_PDN, + PMIC_RG_ZCD13M_CK_PDN = MT6351_PMIC_RG_ZCD13M_CK_PDN, + PMIC_TOP_CKPDN_CON0_SET = MT6351_PMIC_TOP_CKPDN_CON0_SET, + PMIC_TOP_CKPDN_CON0_CLR = MT6351_PMIC_TOP_CKPDN_CON0_CLR, + PMIC_RG_RTC_32K_CK_PDN = MT6351_PMIC_RG_RTC_32K_CK_PDN, + PMIC_RG_RTC_MCLK_PDN = MT6351_PMIC_RG_RTC_MCLK_PDN, + PMIC_RG_RTC_75K_CK_PDN = MT6351_PMIC_RG_RTC_75K_CK_PDN, + PMIC_RG_RTCDET_CK_PDN = MT6351_PMIC_RG_RTCDET_CK_PDN, + PMIC_RG_RTC32K_1V8_0_O_PDN = MT6351_PMIC_RG_RTC32K_1V8_0_O_PDN, + PMIC_RG_RTC32K_1V8_1_O_PDN = MT6351_PMIC_RG_RTC32K_1V8_1_O_PDN, + PMIC_RG_RTC_2SEC_OFF_DET_PDN = MT6351_PMIC_RG_RTC_2SEC_OFF_DET_PDN, + PMIC_RG_FQMTR_CK_PDN = MT6351_PMIC_RG_FQMTR_CK_PDN, + PMIC_RG_STB_1M_CK_PDN = MT6351_PMIC_RG_STB_1M_CK_PDN, + PMIC_RG_BUCK_1M_CK_PDN = MT6351_PMIC_RG_BUCK_1M_CK_PDN, + PMIC_RG_AUXADC_CK_PDN = MT6351_PMIC_RG_AUXADC_CK_PDN, + PMIC_RG_PWMOC_6M_CK_PDN = MT6351_PMIC_RG_PWMOC_6M_CK_PDN, + PMIC_RG_PWMOC_AUD_6M_CK_PDN = MT6351_PMIC_RG_PWMOC_AUD_6M_CK_PDN, + PMIC_TOP_CKPDN_CON1_SET = MT6351_PMIC_TOP_CKPDN_CON1_SET, + PMIC_TOP_CKPDN_CON1_CLR = MT6351_PMIC_TOP_CKPDN_CON1_CLR, + PMIC_RG_FGADC_ANA_CK_PDN = MT6351_PMIC_RG_FGADC_ANA_CK_PDN, + PMIC_RG_FGADC_DIG_CK_PDN = MT6351_PMIC_RG_FGADC_DIG_CK_PDN, + PMIC_RG_BIF_X72_CK_PDN = MT6351_PMIC_RG_BIF_X72_CK_PDN, + PMIC_RG_BIF_X4_CK_PDN = MT6351_PMIC_RG_BIF_X4_CK_PDN, + PMIC_RG_BIF_X1_CK_PDN = MT6351_PMIC_RG_BIF_X1_CK_PDN, + PMIC_RG_PCHR_32K_CK_PDN = MT6351_PMIC_RG_PCHR_32K_CK_PDN, + PMIC_RG_ACCDET_CK_PDN = MT6351_PMIC_RG_ACCDET_CK_PDN, + PMIC_RG_FQMTR_32K_CK_PDN = MT6351_PMIC_RG_FQMTR_32K_CK_PDN, + PMIC_RG_INTRP_CK_PDN = MT6351_PMIC_RG_INTRP_CK_PDN, + PMIC_RG_RTC_26M_CK_PDN = MT6351_PMIC_RG_RTC_26M_CK_PDN, + PMIC_RG_RTC_EOSC32_CK_PDN = MT6351_PMIC_RG_RTC_EOSC32_CK_PDN, + PMIC_RG_TRIM_75K_CK_PDN = MT6351_PMIC_RG_TRIM_75K_CK_PDN, + PMIC_RG_STRUP_LBAT_SEL_CK_PDN = MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_PDN, + PMIC_TOP_CKPDN_CON2_SET = MT6351_PMIC_TOP_CKPDN_CON2_SET, + PMIC_TOP_CKPDN_CON2_CLR = MT6351_PMIC_TOP_CKPDN_CON2_CLR, + PMIC_RG_STRUP_75K_CK_PDN = MT6351_PMIC_RG_STRUP_75K_CK_PDN, + PMIC_RG_STRUP_32K_CK_PDN = MT6351_PMIC_RG_STRUP_32K_CK_PDN, + PMIC_RG_EFUSE_CK_PDN = MT6351_PMIC_RG_EFUSE_CK_PDN, + PMIC_RG_SMPS_CK_DIV_PDN = MT6351_PMIC_RG_SMPS_CK_DIV_PDN, + PMIC_RG_SPI_CK_PDN = MT6351_PMIC_RG_SPI_CK_PDN, + PMIC_RG_BGR_TEST_CK_PDN = MT6351_PMIC_RG_BGR_TEST_CK_PDN, + PMIC_RG_FGADC_FT_CK_PDN = MT6351_PMIC_RG_FGADC_FT_CK_PDN, + PMIC_RG_PCHR_TEST_CK_PDN = MT6351_PMIC_RG_PCHR_TEST_CK_PDN, + PMIC_RG_BUCK_32K_CK_PDN = MT6351_PMIC_RG_BUCK_32K_CK_PDN, + PMIC_RG_BUCK_ANA_CK_PDN = MT6351_PMIC_RG_BUCK_ANA_CK_PDN, + PMIC_RG_EOSC_CALI_TEST_CK_PDN = MT6351_PMIC_RG_EOSC_CALI_TEST_CK_PDN, + PMIC_RG_G_SMPS_TEST_CK_PDN = MT6351_PMIC_RG_G_SMPS_TEST_CK_PDN, + PMIC_TOP_CKPDN_CON3_RSV = MT6351_PMIC_TOP_CKPDN_CON3_RSV, + PMIC_TOP_CKPDN_CON3_SET = MT6351_PMIC_TOP_CKPDN_CON3_SET, + PMIC_TOP_CKPDN_CON3_CLR = MT6351_PMIC_TOP_CKPDN_CON3_CLR, + PMIC_RG_BUCK_9M_CK_PDN = MT6351_PMIC_RG_BUCK_9M_CK_PDN, + PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN, + PMIC_RG_BUCK_VPA_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN, + PMIC_RG_BUCK_VMODEM_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN, + PMIC_RG_BUCK_VCORE_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN, + PMIC_RG_BUCK_VGPU_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN, + PMIC_TOP_CKPDN_CON4_RSV = MT6351_PMIC_TOP_CKPDN_CON4_RSV, + PMIC_TOP_CKPDN_CON4_SET = MT6351_PMIC_TOP_CKPDN_CON4_SET, + PMIC_TOP_CKPDN_CON4_CLR = MT6351_PMIC_TOP_CKPDN_CON4_CLR, + PMIC_RG_LDO_CALI_75K_CK_PDN = MT6351_PMIC_RG_LDO_CALI_75K_CK_PDN, + PMIC_RG_INTRP_PRE_OC_CK_PDN = MT6351_PMIC_RG_INTRP_PRE_OC_CK_PDN, + PMIC_RG_BUCK_VS2_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN, + PMIC_RG_BUCK_VS1_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN, + PMIC_RG_BUCK_VMD1_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN, + PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN = MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN, + PMIC_RG_VOW32K_CK_PDN = MT6351_PMIC_RG_VOW32K_CK_PDN, + PMIC_RG_VOW12M_CK_PDN = MT6351_PMIC_RG_VOW12M_CK_PDN, + PMIC_RG_AUD18M_CK_PDN = MT6351_PMIC_RG_AUD18M_CK_PDN, + PMIC_RG_DRV_ISINK4_CK_PDN = MT6351_PMIC_RG_DRV_ISINK4_CK_PDN, + PMIC_RG_DRV_ISINK5_CK_PDN = MT6351_PMIC_RG_DRV_ISINK5_CK_PDN, + PMIC_RG_DRV_ISINK6_CK_PDN = MT6351_PMIC_RG_DRV_ISINK6_CK_PDN, + PMIC_RG_DRV_ISINK7_CK_PDN = MT6351_PMIC_RG_DRV_ISINK7_CK_PDN, + PMIC_RG_DRV_CHRIND_CK_PDN = MT6351_PMIC_RG_DRV_CHRIND_CK_PDN, + PMIC_RG_BUCK_AUD_1M_CK_PDN = MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN, + PMIC_RG_STB_AUD_1M_CK_PDN = MT6351_PMIC_RG_STB_AUD_1M_CK_PDN, + PMIC_TOP_CKPDN_CON5_SET = MT6351_PMIC_TOP_CKPDN_CON5_SET, + PMIC_TOP_CKPDN_CON5_CLR = MT6351_PMIC_TOP_CKPDN_CON5_CLR, + PMIC_RG_AUDIF_CK_CKSEL = MT6351_PMIC_RG_AUDIF_CK_CKSEL, + PMIC_RG_AUD_CK_CKSEL = MT6351_PMIC_RG_AUD_CK_CKSEL, + PMIC_RG_DRV_ISINK0_CK_CKSEL = MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL, + PMIC_RG_DRV_ISINK1_CK_CKSEL = MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL, + PMIC_RG_DRV_ISINK2_CK_CKSEL = MT6351_PMIC_RG_DRV_ISINK2_CK_CKSEL, + PMIC_RG_DRV_ISINK3_CK_CKSEL = MT6351_PMIC_RG_DRV_ISINK3_CK_CKSEL, + PMIC_RG_FQMTR_CK_CKSEL = MT6351_PMIC_RG_FQMTR_CK_CKSEL, + PMIC_RG_75K_32K_SEL = MT6351_PMIC_RG_75K_32K_SEL, + PMIC_RG_AUXADC_CK_CKSEL = MT6351_PMIC_RG_AUXADC_CK_CKSEL, + PMIC_RG_OSC_SEL_HW_SRC_SEL = MT6351_PMIC_RG_OSC_SEL_HW_SRC_SEL, + PMIC_RG_SRCLKEN_SRC_SEL = MT6351_PMIC_RG_SRCLKEN_SRC_SEL, + PMIC_TOP_CKSEL_CON_SET = MT6351_PMIC_TOP_CKSEL_CON_SET, + PMIC_TOP_CKSEL_CON_CLR = MT6351_PMIC_TOP_CKSEL_CON_CLR, + PMIC_RG_STRUP_75K_CK_CKSEL = MT6351_PMIC_RG_STRUP_75K_CK_CKSEL, + PMIC_RG_BGR_TEST_CK_CKSEL = MT6351_PMIC_RG_BGR_TEST_CK_CKSEL, + PMIC_RG_PCHR_TEST_CK_CKSEL = MT6351_PMIC_RG_PCHR_TEST_CK_CKSEL, + PMIC_RG_FGADC_ANA_CK_CKSEL = MT6351_PMIC_RG_FGADC_ANA_CK_CKSEL, + PMIC_RG_DRV_ISINK4_CK_CKSEL = MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL, + PMIC_RG_DRV_ISINK5_CK_CKSEL = MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL, + PMIC_RG_DRV_ISINK6_CK_CKSEL = MT6351_PMIC_RG_DRV_ISINK6_CK_CKSEL, + PMIC_RG_DRV_ISINK7_CK_CKSEL = MT6351_PMIC_RG_DRV_ISINK7_CK_CKSEL, + PMIC_RG_DRV_CHRIND_CK_CKSEL = MT6351_PMIC_RG_DRV_CHRIND_CK_CKSEL, + PMIC_RG_TOP_CKSEL_CON1_RSV = MT6351_PMIC_RG_TOP_CKSEL_CON1_RSV, + PMIC_TOP_CKSEL_CON1_SET = MT6351_PMIC_TOP_CKSEL_CON1_SET, + PMIC_TOP_CKSEL_CON1_CLR = MT6351_PMIC_TOP_CKSEL_CON1_CLR, + PMIC_RG_SRCVOLTEN_SW = MT6351_PMIC_RG_SRCVOLTEN_SW, + PMIC_RG_BUCK_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_OSC_SEL_SW, + PMIC_RG_VOWEN_SW = MT6351_PMIC_RG_VOWEN_SW, + PMIC_RG_SRCVOLTEN_MODE = MT6351_PMIC_RG_SRCVOLTEN_MODE, + PMIC_RG_BUCK_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_OSC_SEL_MODE, + PMIC_RG_VOWEN_MODE = MT6351_PMIC_RG_VOWEN_MODE, + PMIC_RG_TOP_CKSEL_CON2_RSV = MT6351_PMIC_RG_TOP_CKSEL_CON2_RSV, + PMIC_RG_BUCK_VMD1_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_SW, + PMIC_RG_BUCK_VMD1_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_MODE, + PMIC_TOP_CKSEL_CON2_SET = MT6351_PMIC_TOP_CKSEL_CON2_SET, + PMIC_TOP_CKSEL_CON2_CLR = MT6351_PMIC_TOP_CKSEL_CON2_CLR, + PMIC_RG_BUCK_VCORE_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_SW, + PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW, + PMIC_RG_BUCK_VPA_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_SW, + PMIC_RG_BUCK_VMODEM_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_SW, + PMIC_RG_BUCK_VGPU_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_SW, + PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW, + PMIC_RG_BUCK_VS2_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_SW, + PMIC_RG_BUCK_VS1_OSC_SEL_SW = MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_SW, + PMIC_RG_BUCK_VCORE_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_MODE, + PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE, + PMIC_RG_BUCK_VPA_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_MODE, + PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE, + PMIC_RG_BUCK_VGPU_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_MODE, + PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE, + PMIC_RG_BUCK_VS2_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_MODE, + PMIC_RG_BUCK_VS1_OSC_SEL_MODE = MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_MODE, + PMIC_TOP_CKSEL_CON3_SET = MT6351_PMIC_TOP_CKSEL_CON3_SET, + PMIC_TOP_CKSEL_CON3_CLR = MT6351_PMIC_TOP_CKSEL_CON3_CLR, + PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL = MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL, + PMIC_TOP_CKDIVSEL_CON_RSV = MT6351_PMIC_TOP_CKDIVSEL_CON_RSV, + PMIC_RG_BIF_X4_CK_DIVSEL = MT6351_PMIC_RG_BIF_X4_CK_DIVSEL, + PMIC_RG_REG_CK_DIVSEL = MT6351_PMIC_RG_REG_CK_DIVSEL, + PMIC_TOP_CKDIVSEL_CON0_RSV = MT6351_PMIC_TOP_CKDIVSEL_CON0_RSV, + PMIC_TOP_CKDIVSEL_CON0_SET = MT6351_PMIC_TOP_CKDIVSEL_CON0_SET, + PMIC_TOP_CKDIVSEL_CON0_CLR = MT6351_PMIC_TOP_CKDIVSEL_CON0_CLR, + PMIC_RG_AUXADC_SMPS_CK_DIVSEL = MT6351_PMIC_RG_AUXADC_SMPS_CK_DIVSEL, + PMIC_RG_AUXADC_26M_CK_DIVSEL = MT6351_PMIC_RG_AUXADC_26M_CK_DIVSEL, + PMIC_RG_BUCK_9M_CK_DIVSEL = MT6351_PMIC_RG_BUCK_9M_CK_DIVSEL, + PMIC_TOP_CKDIVSEL_CON1_SET = MT6351_PMIC_TOP_CKDIVSEL_CON1_SET, + PMIC_TOP_CKDIVSEL_CON1_CLR = MT6351_PMIC_TOP_CKDIVSEL_CON1_CLR, + PMIC_RG_G_SMPS_PD_CK_PDN_HWEN = MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_HWEN, + PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN = MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN, + PMIC_RG_G_DRV_2M_CK_PDN_HWEN = MT6351_PMIC_RG_G_DRV_2M_CK_PDN_HWEN, + PMIC_RG_AUXADC_CK_PDN_HWEN = MT6351_PMIC_RG_AUXADC_CK_PDN_HWEN, + PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN = MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN, + PMIC_RG_BUCK_1M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_1M_CK_PDN_HWEN, + PMIC_RG_EFUSE_CK_PDN_HWEN = MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN, + PMIC_RG_RTC_26M_CK_PDN_HWEN = MT6351_PMIC_RG_RTC_26M_CK_PDN_HWEN, + PMIC_RG_AUXADC_26M_CK_PDN_HWEN = MT6351_PMIC_RG_AUXADC_26M_CK_PDN_HWEN, + PMIC_RG_AUXADC_CK_CKSEL_HWEN = MT6351_PMIC_RG_AUXADC_CK_CKSEL_HWEN, + PMIC_TOP_CKHWEN_CON0_RSV = MT6351_PMIC_TOP_CKHWEN_CON0_RSV, + PMIC_TOP_CKHWEN_CON0_SET = MT6351_PMIC_TOP_CKHWEN_CON0_SET, + PMIC_TOP_CKHWEN_CON0_CLR = MT6351_PMIC_TOP_CKHWEN_CON0_CLR, + PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN, + PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN, + PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN, + PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN, + PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN, + PMIC_TOP_CKHWEN_CON1_RSV = MT6351_PMIC_TOP_CKHWEN_CON1_RSV, + PMIC_TOP_CKHWEN_CON1_SET = MT6351_PMIC_TOP_CKHWEN_CON1_SET, + PMIC_TOP_CKHWEN_CON1_CLR = MT6351_PMIC_TOP_CKHWEN_CON1_CLR, + PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN, + PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN, + PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN, + PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN, + PMIC_RG_AUD18M_CK_PDN_HWEN = MT6351_PMIC_RG_AUD18M_CK_PDN_HWEN, + PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN = MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN, + PMIC_TOP_CKHWEN_CON2_RSV = MT6351_PMIC_TOP_CKHWEN_CON2_RSV, + PMIC_TOP_CKHWEN_CON2_SET = MT6351_PMIC_TOP_CKHWEN_CON2_SET, + PMIC_TOP_CKHWEN_CON2_CLR = MT6351_PMIC_TOP_CKHWEN_CON2_CLR, + PMIC_RG_PMU75K_CK_TST_DIS = MT6351_PMIC_RG_PMU75K_CK_TST_DIS, + PMIC_RG_SMPS_CK_TST_DIS = MT6351_PMIC_RG_SMPS_CK_TST_DIS, + PMIC_RG_AUD26M_CK_TST_DIS = MT6351_PMIC_RG_AUD26M_CK_TST_DIS, + PMIC_RG_RTC32K_CK_TST_DIS = MT6351_PMIC_RG_RTC32K_CK_TST_DIS, + PMIC_RG_FG_CK_TST_DIS = MT6351_PMIC_RG_FG_CK_TST_DIS, + PMIC_RG_RTC26M_CK_TST_DIS = MT6351_PMIC_RG_RTC26M_CK_TST_DIS, + PMIC_RG_VOW12M_CK_TST_DIS = MT6351_PMIC_RG_VOW12M_CK_TST_DIS, + PMIC_TOP_CKTST_CON0_RSV = MT6351_PMIC_TOP_CKTST_CON0_RSV, + PMIC_RG_BUCK_ANA_AUTO_OFF_DIS = MT6351_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS, + PMIC_RG_DRV_ISINK0_CK_TSTSEL = MT6351_PMIC_RG_DRV_ISINK0_CK_TSTSEL, + PMIC_RG_DRV_ISINK1_CK_TSTSEL = MT6351_PMIC_RG_DRV_ISINK1_CK_TSTSEL, + PMIC_RG_DRV_ISINK2_CK_TSTSEL = MT6351_PMIC_RG_DRV_ISINK2_CK_TSTSEL, + PMIC_RG_DRV_ISINK3_CK_TSTSEL = MT6351_PMIC_RG_DRV_ISINK3_CK_TSTSEL, + PMIC_RG_FQMTR_CK_TSTSEL = MT6351_PMIC_RG_FQMTR_CK_TSTSEL, + PMIC_RG_RTCDET_CK_TSTSEL = MT6351_PMIC_RG_RTCDET_CK_TSTSEL, + PMIC_RG_PMU75K_CK_TSTSEL = MT6351_PMIC_RG_PMU75K_CK_TSTSEL, + PMIC_RG_SMPS_CK_TSTSEL = MT6351_PMIC_RG_SMPS_CK_TSTSEL, + PMIC_RG_AUD26M_CK_TSTSEL = MT6351_PMIC_RG_AUD26M_CK_TSTSEL, + PMIC_RG_AUDIF_CK_TSTSEL = MT6351_PMIC_RG_AUDIF_CK_TSTSEL, + PMIC_RG_AUD_CK_TSTSEL = MT6351_PMIC_RG_AUD_CK_TSTSEL, + PMIC_RG_STRUP_75K_CK_TSTSEL = MT6351_PMIC_RG_STRUP_75K_CK_TSTSEL, + PMIC_RG_RTC32K_CK_TSTSEL = MT6351_PMIC_RG_RTC32K_CK_TSTSEL, + PMIC_RG_PCHR_TEST_CK_TSTSEL = MT6351_PMIC_RG_PCHR_TEST_CK_TSTSEL, + PMIC_RG_BGR_TEST_CK_TSTSEL = MT6351_PMIC_RG_BGR_TEST_CK_TSTSEL, + PMIC_RG_FG_CK_TSTSEL = MT6351_PMIC_RG_FG_CK_TSTSEL, + PMIC_RG_FGADC_ANA_CK_TSTSEL = MT6351_PMIC_RG_FGADC_ANA_CK_TSTSEL, + PMIC_RG_RTC26M_CK_TSTSEL = MT6351_PMIC_RG_RTC26M_CK_TSTSEL, + PMIC_RG_RTC_EOSC32_CK_TSTSEL = MT6351_PMIC_RG_RTC_EOSC32_CK_TSTSEL, + PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL = MT6351_PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL, + PMIC_RG_AUXADC_CK_TSTSEL = MT6351_PMIC_RG_AUXADC_CK_TSTSEL, + PMIC_RG_AUXADC_SMPS_CK_TSTSEL = MT6351_PMIC_RG_AUXADC_SMPS_CK_TSTSEL, + PMIC_RG_AUXADC_26M_CK_TSTSEL = MT6351_PMIC_RG_AUXADC_26M_CK_TSTSEL, + PMIC_RG_VOW12M_CK_TSTSEL = MT6351_PMIC_RG_VOW12M_CK_TSTSEL, + PMIC_RG_DRV_ISINK4_CK_TSTSEL = MT6351_PMIC_RG_DRV_ISINK4_CK_TSTSEL, + PMIC_RG_DRV_ISINK5_CK_TSTSEL = MT6351_PMIC_RG_DRV_ISINK5_CK_TSTSEL, + PMIC_RG_DRV_ISINK6_CK_TSTSEL = MT6351_PMIC_RG_DRV_ISINK6_CK_TSTSEL, + PMIC_RG_DRV_ISINK7_CK_TSTSEL = MT6351_PMIC_RG_DRV_ISINK7_CK_TSTSEL, + PMIC_RG_DRV_CHRIND_CK_TSTSEL = MT6351_PMIC_RG_DRV_CHRIND_CK_TSTSEL, + PMIC_TOP_CKTST_CON2_RSV = MT6351_PMIC_TOP_CKTST_CON2_RSV, + PMIC_RG_CLKSQ_EN_AUD = MT6351_PMIC_RG_CLKSQ_EN_AUD, + PMIC_RG_CLKSQ_EN_FQR = MT6351_PMIC_RG_CLKSQ_EN_FQR, + PMIC_RG_CLKSQ_EN_AUX_AP = MT6351_PMIC_RG_CLKSQ_EN_AUX_AP, + PMIC_RG_CLKSQ_EN_AUX_MD = MT6351_PMIC_RG_CLKSQ_EN_AUX_MD, + PMIC_RG_CLKSQ_EN_AUX_GPS = MT6351_PMIC_RG_CLKSQ_EN_AUX_GPS, + PMIC_RG_CLKSQ_EN_AUX_RSV = MT6351_PMIC_RG_CLKSQ_EN_AUX_RSV, + PMIC_RG_CLKSQ_EN_AUX_AP_MODE = MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MODE, + PMIC_RG_CLKSQ_EN_AUX_MD_MODE = MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MODE, + PMIC_RG_CLKSQ_IN_SEL_VA18 = MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18, + PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL = MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL, + PMIC_TOP_CLKSQ_RSV = MT6351_PMIC_TOP_CLKSQ_RSV, + PMIC_DA_CLKSQ_EN_VA18 = MT6351_PMIC_DA_CLKSQ_EN_VA18, + PMIC_TOP_CLKSQ_SET = MT6351_PMIC_TOP_CLKSQ_SET, + PMIC_TOP_CLKSQ_CLR = MT6351_PMIC_TOP_CLKSQ_CLR, + PMIC_RG_CLKSQ_RTC_EN = MT6351_PMIC_RG_CLKSQ_RTC_EN, + PMIC_RG_CLKSQ_RTC_EN_HW_MODE = MT6351_PMIC_RG_CLKSQ_RTC_EN_HW_MODE, + PMIC_TOP_CLKSQ_RTC_RSV0 = MT6351_PMIC_TOP_CLKSQ_RTC_RSV0, + PMIC_RG_ENBB_SEL = MT6351_PMIC_RG_ENBB_SEL, + PMIC_RG_XOSC_EN_SEL = MT6351_PMIC_RG_XOSC_EN_SEL, + PMIC_TOP_CLKSQ_RTC_RSV1 = MT6351_PMIC_TOP_CLKSQ_RTC_RSV1, + PMIC_DA_CLKSQ_EN_VDIG18 = MT6351_PMIC_DA_CLKSQ_EN_VDIG18, + PMIC_TOP_CLKSQ_RTC_SET = MT6351_PMIC_TOP_CLKSQ_RTC_SET, + PMIC_TOP_CLKSQ_RTC_CLR = MT6351_PMIC_TOP_CLKSQ_RTC_CLR, + PMIC_OSC_75K_TRIM = MT6351_PMIC_OSC_75K_TRIM, + PMIC_RG_OSC_75K_TRIM_EN = MT6351_PMIC_RG_OSC_75K_TRIM_EN, + PMIC_RG_OSC_75K_TRIM_RATE = MT6351_PMIC_RG_OSC_75K_TRIM_RATE, + PMIC_DA_OSC_75K_TRIM = MT6351_PMIC_DA_OSC_75K_TRIM, + PMIC_RG_EFUSE_MAN_RST = MT6351_PMIC_RG_EFUSE_MAN_RST, + PMIC_RG_AUXADC_RST = MT6351_PMIC_RG_AUXADC_RST, + PMIC_RG_AUXADC_REG_RST = MT6351_PMIC_RG_AUXADC_REG_RST, + PMIC_RG_AUDIO_RST = MT6351_PMIC_RG_AUDIO_RST, + PMIC_RG_ACCDET_RST = MT6351_PMIC_RG_ACCDET_RST, + PMIC_RG_BIF_RST = MT6351_PMIC_RG_BIF_RST, + PMIC_RG_DRIVER_RST = MT6351_PMIC_RG_DRIVER_RST, + PMIC_RG_FGADC_RST = MT6351_PMIC_RG_FGADC_RST, + PMIC_RG_FQMTR_RST = MT6351_PMIC_RG_FQMTR_RST, + PMIC_RG_RTC_RST = MT6351_PMIC_RG_RTC_RST, + PMIC_RG_CHRWDT_RST = MT6351_PMIC_RG_CHRWDT_RST, + PMIC_RG_ZCD_RST = MT6351_PMIC_RG_ZCD_RST, + PMIC_RG_AUDNCP_RST = MT6351_PMIC_RG_AUDNCP_RST, + PMIC_RG_CLK_TRIM_RST = MT6351_PMIC_RG_CLK_TRIM_RST, + PMIC_RG_LDO_CALI_RST = MT6351_PMIC_RG_LDO_CALI_RST, + PMIC_TOP_RST_CON0_SET = MT6351_PMIC_TOP_RST_CON0_SET, + PMIC_TOP_RST_CON0_CLR = MT6351_PMIC_TOP_RST_CON0_CLR, + PMIC_RG_STRUP_LONG_PRESS_RST = MT6351_PMIC_RG_STRUP_LONG_PRESS_RST, + PMIC_TOP_RST_CON1_RSV = MT6351_PMIC_TOP_RST_CON1_RSV, + PMIC_TOP_RST_CON1_SET = MT6351_PMIC_TOP_RST_CON1_SET, + PMIC_TOP_RST_CON1_CLR = MT6351_PMIC_TOP_RST_CON1_CLR, + PMIC_RG_CHR_LDO_DET_MODE = MT6351_PMIC_RG_CHR_LDO_DET_MODE, + PMIC_RG_CHR_LDO_DET_SW = MT6351_PMIC_RG_CHR_LDO_DET_SW, + PMIC_RG_CHRWDT_FLAG_MODE = MT6351_PMIC_RG_CHRWDT_FLAG_MODE, + PMIC_RG_CHRWDT_FLAG_SW = MT6351_PMIC_RG_CHRWDT_FLAG_SW, + PMIC_TOP_RST_CON2_RSV = MT6351_PMIC_TOP_RST_CON2_RSV, + PMIC_RG_WDTRSTB_EN = MT6351_PMIC_RG_WDTRSTB_EN, + PMIC_RG_WDTRSTB_MODE = MT6351_PMIC_RG_WDTRSTB_MODE, + PMIC_WDTRSTB_STATUS = MT6351_PMIC_WDTRSTB_STATUS, + PMIC_WDTRSTB_STATUS_CLR = MT6351_PMIC_WDTRSTB_STATUS_CLR, + PMIC_RG_WDTRSTB_FB_EN = MT6351_PMIC_RG_WDTRSTB_FB_EN, + PMIC_RG_WDTRSTB_DEB = MT6351_PMIC_RG_WDTRSTB_DEB, + PMIC_RG_HOMEKEY_RST_EN = MT6351_PMIC_RG_HOMEKEY_RST_EN, + PMIC_RG_PWRKEY_RST_EN = MT6351_PMIC_RG_PWRKEY_RST_EN, + PMIC_RG_PWRRST_TMR_DIS = MT6351_PMIC_RG_PWRRST_TMR_DIS, + PMIC_RG_PWRKEY_RST_TD = MT6351_PMIC_RG_PWRKEY_RST_TD, + PMIC_TOP_RST_MISC_RSV = MT6351_PMIC_TOP_RST_MISC_RSV, + PMIC_TOP_RST_MISC_SET = MT6351_PMIC_TOP_RST_MISC_SET, + PMIC_TOP_RST_MISC_CLR = MT6351_PMIC_TOP_RST_MISC_CLR, + PMIC_VPWRIN_RSTB_STATUS = MT6351_PMIC_VPWRIN_RSTB_STATUS, + PMIC_DDLO_RSTB_STATUS = MT6351_PMIC_DDLO_RSTB_STATUS, + PMIC_UVLO_RSTB_STATUS = MT6351_PMIC_UVLO_RSTB_STATUS, + PMIC_RTC_DDLO_RSTB_STATUS = MT6351_PMIC_RTC_DDLO_RSTB_STATUS, + PMIC_CHRWDT_REG_RSTB_STATUS = MT6351_PMIC_CHRWDT_REG_RSTB_STATUS, + PMIC_CHRDET_REG_RSTB_STATUS = MT6351_PMIC_CHRDET_REG_RSTB_STATUS, + PMIC_TOP_RST_STATUS_RSV = MT6351_PMIC_TOP_RST_STATUS_RSV, + PMIC_TOP_RST_STATUS_SET = MT6351_PMIC_TOP_RST_STATUS_SET, + PMIC_TOP_RST_STATUS_CLR = MT6351_PMIC_TOP_RST_STATUS_CLR, + PMIC_RG_INT_EN_PWRKEY = MT6351_PMIC_RG_INT_EN_PWRKEY, + PMIC_RG_INT_EN_HOMEKEY = MT6351_PMIC_RG_INT_EN_HOMEKEY, + PMIC_RG_INT_EN_PWRKEY_R = MT6351_PMIC_RG_INT_EN_PWRKEY_R, + PMIC_RG_INT_EN_HOMEKEY_R = MT6351_PMIC_RG_INT_EN_HOMEKEY_R, + PMIC_RG_INT_EN_THR_H = MT6351_PMIC_RG_INT_EN_THR_H, + PMIC_RG_INT_EN_THR_L = MT6351_PMIC_RG_INT_EN_THR_L, + PMIC_RG_INT_EN_BAT_H = MT6351_PMIC_RG_INT_EN_BAT_H, + PMIC_RG_INT_EN_BAT_L = MT6351_PMIC_RG_INT_EN_BAT_L, + PMIC_RG_INT_EN_RTC = MT6351_PMIC_RG_INT_EN_RTC, + PMIC_RG_INT_EN_AUDIO = MT6351_PMIC_RG_INT_EN_AUDIO, + PMIC_RG_INT_EN_MAD = MT6351_PMIC_RG_INT_EN_MAD, + PMIC_RG_INT_EN_ACCDET = MT6351_PMIC_RG_INT_EN_ACCDET, + PMIC_RG_INT_EN_ACCDET_EINT = MT6351_PMIC_RG_INT_EN_ACCDET_EINT, + PMIC_RG_INT_EN_ACCDET_NEGV = MT6351_PMIC_RG_INT_EN_ACCDET_NEGV, + PMIC_RG_INT_EN_NI_LBAT_INT = MT6351_PMIC_RG_INT_EN_NI_LBAT_INT, + PMIC_INT_CON0_SET = MT6351_PMIC_INT_CON0_SET, + PMIC_INT_CON0_CLR = MT6351_PMIC_INT_CON0_CLR, + PMIC_RG_INT_EN_VCORE_OC = MT6351_PMIC_RG_INT_EN_VCORE_OC, + PMIC_RG_INT_EN_VGPU_OC = MT6351_PMIC_RG_INT_EN_VGPU_OC, + PMIC_RG_INT_EN_VSRAM_MD_OC = MT6351_PMIC_RG_INT_EN_VSRAM_MD_OC, + PMIC_RG_INT_EN_VMODEM_OC = MT6351_PMIC_RG_INT_EN_VMODEM_OC, + PMIC_RG_INT_EN_VM1_OC = MT6351_PMIC_RG_INT_EN_VM1_OC, + PMIC_RG_INT_EN_VS1_OC = MT6351_PMIC_RG_INT_EN_VS1_OC, + PMIC_RG_INT_EN_VS2_OC = MT6351_PMIC_RG_INT_EN_VS2_OC, + PMIC_RG_INT_EN_VPA_OC = MT6351_PMIC_RG_INT_EN_VPA_OC, + PMIC_RG_INT_EN_VCORE_PREOC = MT6351_PMIC_RG_INT_EN_VCORE_PREOC, + PMIC_RG_INT_EN_VGPU_PREOC = MT6351_PMIC_RG_INT_EN_VGPU_PREOC, + PMIC_RG_INT_EN_VSRAM_MD_PREOC = MT6351_PMIC_RG_INT_EN_VSRAM_MD_PREOC, + PMIC_RG_INT_EN_VMODEM_PREOC = MT6351_PMIC_RG_INT_EN_VMODEM_PREOC, + PMIC_RG_INT_EN_VM1_PREOC = MT6351_PMIC_RG_INT_EN_VM1_PREOC, + PMIC_RG_INT_EN_VS1_PREOC = MT6351_PMIC_RG_INT_EN_VS1_PREOC, + PMIC_RG_INT_EN_VS2_PREOC = MT6351_PMIC_RG_INT_EN_VS2_PREOC, + PMIC_RG_INT_EN_LDO_OC = MT6351_PMIC_RG_INT_EN_LDO_OC, + PMIC_INT_CON1_SET = MT6351_PMIC_INT_CON1_SET, + PMIC_INT_CON1_CLR = MT6351_PMIC_INT_CON1_CLR, + PMIC_RG_INT_EN_JEITA_HOT = MT6351_PMIC_RG_INT_EN_JEITA_HOT, + PMIC_RG_INT_EN_JEITA_WARM = MT6351_PMIC_RG_INT_EN_JEITA_WARM, + PMIC_RG_INT_EN_JEITA_COOL = MT6351_PMIC_RG_INT_EN_JEITA_COOL, + PMIC_RG_INT_EN_JEITA_COLD = MT6351_PMIC_RG_INT_EN_JEITA_COLD, + PMIC_RG_INT_EN_AUXADC_IMP = MT6351_PMIC_RG_INT_EN_AUXADC_IMP, + PMIC_RG_INT_EN_NAG_C_DLTV = MT6351_PMIC_RG_INT_EN_NAG_C_DLTV, + PMIC_RG_INT_EN_OV = MT6351_PMIC_RG_INT_EN_OV, + PMIC_RG_INT_EN_BVALID_DET = MT6351_PMIC_RG_INT_EN_BVALID_DET, + PMIC_RG_INT_EN_RGS_BATON_HV = MT6351_PMIC_RG_INT_EN_RGS_BATON_HV, + PMIC_RG_INT_EN_VBATON_UNDET = MT6351_PMIC_RG_INT_EN_VBATON_UNDET, + PMIC_RG_INT_EN_WATCHDOG = MT6351_PMIC_RG_INT_EN_WATCHDOG, + PMIC_RG_INT_EN_PCHR_CM_VDEC = MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC, + PMIC_RG_INT_EN_CHRDET = MT6351_PMIC_RG_INT_EN_CHRDET, + PMIC_RG_INT_EN_PCHR_CM_VINC = MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC, + PMIC_INT_CON2_SET = MT6351_PMIC_INT_CON2_SET, + PMIC_INT_CON2_CLR = MT6351_PMIC_INT_CON2_CLR, + PMIC_RG_INT_EN_FG_BAT_H = MT6351_PMIC_RG_INT_EN_FG_BAT_H, + PMIC_RG_INT_EN_FG_BAT_L = MT6351_PMIC_RG_INT_EN_FG_BAT_L, + PMIC_RG_INT_EN_FG_CUR_H = MT6351_PMIC_RG_INT_EN_FG_CUR_H, + PMIC_RG_INT_EN_FG_CUR_L = MT6351_PMIC_RG_INT_EN_FG_CUR_L, + PMIC_RG_INT_EN_FG_ZCV = MT6351_PMIC_RG_INT_EN_FG_ZCV, + PMIC_INT_CON3_SET = MT6351_PMIC_INT_CON3_SET, + PMIC_INT_CON3_CLR = MT6351_PMIC_INT_CON3_CLR, + PMIC_POLARITY = MT6351_PMIC_POLARITY, + PMIC_RG_HOMEKEY_INT_SEL = MT6351_PMIC_RG_HOMEKEY_INT_SEL, + PMIC_RG_PWRKEY_INT_SEL = MT6351_PMIC_RG_PWRKEY_INT_SEL, + PMIC_RG_CHRDET_INT_SEL = MT6351_PMIC_RG_CHRDET_INT_SEL, + PMIC_RG_PCHR_CM_VINC_POLARITY_RSV = MT6351_PMIC_RG_PCHR_CM_VINC_POLARITY_RSV, + PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV = MT6351_PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV, + PMIC_INT_MISC_CON_SET = MT6351_PMIC_INT_MISC_CON_SET, + PMIC_INT_MISC_CON_CLR = MT6351_PMIC_INT_MISC_CON_CLR, + PMIC_RG_INT_STATUS_PWRKEY = MT6351_PMIC_RG_INT_STATUS_PWRKEY, + PMIC_RG_INT_STATUS_HOMEKEY = MT6351_PMIC_RG_INT_STATUS_HOMEKEY, + PMIC_RG_INT_STATUS_PWRKEY_R = MT6351_PMIC_RG_INT_STATUS_PWRKEY_R, + PMIC_RG_INT_STATUS_HOMEKEY_R = MT6351_PMIC_RG_INT_STATUS_HOMEKEY_R, + PMIC_RG_INT_STATUS_THR_H = MT6351_PMIC_RG_INT_STATUS_THR_H, + PMIC_RG_INT_STATUS_THR_L = MT6351_PMIC_RG_INT_STATUS_THR_L, + PMIC_RG_INT_STATUS_BAT_H = MT6351_PMIC_RG_INT_STATUS_BAT_H, + PMIC_RG_INT_STATUS_BAT_L = MT6351_PMIC_RG_INT_STATUS_BAT_L, + PMIC_RG_INT_STATUS_RTC = MT6351_PMIC_RG_INT_STATUS_RTC, + PMIC_RG_INT_STATUS_AUDIO = MT6351_PMIC_RG_INT_STATUS_AUDIO, + PMIC_RG_INT_STATUS_MAD = MT6351_PMIC_RG_INT_STATUS_MAD, + PMIC_RG_INT_STATUS_ACCDET = MT6351_PMIC_RG_INT_STATUS_ACCDET, + PMIC_RG_INT_STATUS_ACCDET_EINT = MT6351_PMIC_RG_INT_STATUS_ACCDET_EINT, + PMIC_RG_INT_STATUS_ACCDET_NEGV = MT6351_PMIC_RG_INT_STATUS_ACCDET_NEGV, + PMIC_RG_INT_STATUS_NI_LBAT_INT = MT6351_PMIC_RG_INT_STATUS_NI_LBAT_INT, + PMIC_RG_INT_STATUS_VCORE_OC = MT6351_PMIC_RG_INT_STATUS_VCORE_OC, + PMIC_RG_INT_STATUS_VGPU_OC = MT6351_PMIC_RG_INT_STATUS_VGPU_OC, + PMIC_RG_INT_STATUS_VSRAM_MD_OC = MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_OC, + PMIC_RG_INT_STATUS_VMODEM_OC = MT6351_PMIC_RG_INT_STATUS_VMODEM_OC, + PMIC_RG_INT_STATUS_VM1_OC = MT6351_PMIC_RG_INT_STATUS_VM1_OC, + PMIC_RG_INT_STATUS_VS1_OC = MT6351_PMIC_RG_INT_STATUS_VS1_OC, + PMIC_RG_INT_STATUS_VS2_OC = MT6351_PMIC_RG_INT_STATUS_VS2_OC, + PMIC_RG_INT_STATUS_VPA_OC = MT6351_PMIC_RG_INT_STATUS_VPA_OC, + PMIC_RG_INT_STATUS_VCORE_PREOC = MT6351_PMIC_RG_INT_STATUS_VCORE_PREOC, + PMIC_RG_INT_STATUS_VGPU_PREOC = MT6351_PMIC_RG_INT_STATUS_VGPU_PREOC, + PMIC_RG_INT_STATUS_VSRAM_MD_PREOC = MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_PREOC, + PMIC_RG_INT_STATUS_VMODEM_PREOC = MT6351_PMIC_RG_INT_STATUS_VMODEM_PREOC, + PMIC_RG_INT_STATUS_VM1_PREOC = MT6351_PMIC_RG_INT_STATUS_VM1_PREOC, + PMIC_RG_INT_STATUS_VS1_PREOC = MT6351_PMIC_RG_INT_STATUS_VS1_PREOC, + PMIC_RG_INT_STATUS_VS2_PREOC = MT6351_PMIC_RG_INT_STATUS_VS2_PREOC, + PMIC_RG_INT_STATUS_LDO_OC = MT6351_PMIC_RG_INT_STATUS_LDO_OC, + PMIC_RG_INT_STATUS_JEITA_HOT = MT6351_PMIC_RG_INT_STATUS_JEITA_HOT, + PMIC_RG_INT_STATUS_JEITA_WARM = MT6351_PMIC_RG_INT_STATUS_JEITA_WARM, + PMIC_RG_INT_STATUS_JEITA_COOL = MT6351_PMIC_RG_INT_STATUS_JEITA_COOL, + PMIC_RG_INT_STATUS_JEITA_COLD = MT6351_PMIC_RG_INT_STATUS_JEITA_COLD, + PMIC_RG_INT_STATUS_AUXADC_IMP = MT6351_PMIC_RG_INT_STATUS_AUXADC_IMP, + PMIC_RG_INT_STATUS_NAG_C_DLTV = MT6351_PMIC_RG_INT_STATUS_NAG_C_DLTV, + PMIC_RG_INT_STATUS_OV = MT6351_PMIC_RG_INT_STATUS_OV, + PMIC_RG_INT_STATUS_BVALID_DET = MT6351_PMIC_RG_INT_STATUS_BVALID_DET, + PMIC_RG_INT_STATUS_RGS_BATON_HV = MT6351_PMIC_RG_INT_STATUS_RGS_BATON_HV, + PMIC_RG_INT_STATUS_VBATON_UNDET = MT6351_PMIC_RG_INT_STATUS_VBATON_UNDET, + PMIC_RG_INT_STATUS_WATCHDOG = MT6351_PMIC_RG_INT_STATUS_WATCHDOG, + PMIC_RG_INT_STATUS_PCHR_CM_VDEC = MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VDEC, + PMIC_RG_INT_STATUS_CHRDET = MT6351_PMIC_RG_INT_STATUS_CHRDET, + PMIC_RG_INT_STATUS_PCHR_CM_VINC = MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VINC, + PMIC_RG_INT_STATUS_FG_BAT_H = MT6351_PMIC_RG_INT_STATUS_FG_BAT_H, + PMIC_RG_INT_STATUS_FG_BAT_L = MT6351_PMIC_RG_INT_STATUS_FG_BAT_L, + PMIC_RG_INT_STATUS_FG_CUR_H = MT6351_PMIC_RG_INT_STATUS_FG_CUR_H, + PMIC_RG_INT_STATUS_FG_CUR_L = MT6351_PMIC_RG_INT_STATUS_FG_CUR_L, + PMIC_RG_INT_STATUS_FG_ZCV = MT6351_PMIC_RG_INT_STATUS_FG_ZCV, + PMIC_OC_GEAR_LDO = MT6351_PMIC_OC_GEAR_LDO, + PMIC_FQMTR_TCKSEL = MT6351_PMIC_FQMTR_TCKSEL, + PMIC_FQMTR_BUSY = MT6351_PMIC_FQMTR_BUSY, + PMIC_FQMTR_EN = MT6351_PMIC_FQMTR_EN, + PMIC_FQMTR_WINSET = MT6351_PMIC_FQMTR_WINSET, + PMIC_FQMTR_DATA = MT6351_PMIC_FQMTR_DATA, + PMIC_RG_SLP_RW_EN = MT6351_PMIC_RG_SLP_RW_EN, + PMIC_RG_SPI_RSV = MT6351_PMIC_RG_SPI_RSV, + PMIC_DEW_DIO_EN = MT6351_PMIC_DEW_DIO_EN, + PMIC_DEW_READ_TEST = MT6351_PMIC_DEW_READ_TEST, + PMIC_DEW_WRITE_TEST = MT6351_PMIC_DEW_WRITE_TEST, + PMIC_DEW_CRC_SWRST = MT6351_PMIC_DEW_CRC_SWRST, + PMIC_DEW_CRC_EN = MT6351_PMIC_DEW_CRC_EN, + PMIC_DEW_CRC_VAL = MT6351_PMIC_DEW_CRC_VAL, + PMIC_DEW_DBG_MON_SEL = MT6351_PMIC_DEW_DBG_MON_SEL, + PMIC_DEW_CIPHER_KEY_SEL = MT6351_PMIC_DEW_CIPHER_KEY_SEL, + PMIC_DEW_CIPHER_IV_SEL = MT6351_PMIC_DEW_CIPHER_IV_SEL, + PMIC_DEW_CIPHER_EN = MT6351_PMIC_DEW_CIPHER_EN, + PMIC_DEW_CIPHER_RDY = MT6351_PMIC_DEW_CIPHER_RDY, + PMIC_DEW_CIPHER_MODE = MT6351_PMIC_DEW_CIPHER_MODE, + PMIC_DEW_CIPHER_SWRST = MT6351_PMIC_DEW_CIPHER_SWRST, + PMIC_DEW_RDDMY_NO = MT6351_PMIC_DEW_RDDMY_NO, + PMIC_INT_TYPE_CON0 = MT6351_PMIC_INT_TYPE_CON0, + PMIC_INT_TYPE_CON0_SET = MT6351_PMIC_INT_TYPE_CON0_SET, + PMIC_INT_TYPE_CON0_CLR = MT6351_PMIC_INT_TYPE_CON0_CLR, + PMIC_INT_TYPE_CON1 = MT6351_PMIC_INT_TYPE_CON1, + PMIC_INT_TYPE_CON1_SET = MT6351_PMIC_INT_TYPE_CON1_SET, + PMIC_INT_TYPE_CON1_CLR = MT6351_PMIC_INT_TYPE_CON1_CLR, + PMIC_INT_TYPE_CON2 = MT6351_PMIC_INT_TYPE_CON2, + PMIC_INT_TYPE_CON2_SET = MT6351_PMIC_INT_TYPE_CON2_SET, + PMIC_INT_TYPE_CON2_CLR = MT6351_PMIC_INT_TYPE_CON2_CLR, + PMIC_INT_TYPE_CON3 = MT6351_PMIC_INT_TYPE_CON3, + PMIC_INT_TYPE_CON3_SET = MT6351_PMIC_INT_TYPE_CON3_SET, + PMIC_INT_TYPE_CON3_CLR = MT6351_PMIC_INT_TYPE_CON3_CLR, + PMIC_CPU_INT_STA = MT6351_PMIC_CPU_INT_STA, + PMIC_MD32_INT_STA = MT6351_PMIC_MD32_INT_STA, + PMIC_BUCK_LDO_FT_TESTMODE_EN = MT6351_PMIC_BUCK_LDO_FT_TESTMODE_EN, + PMIC_BUCK_ALL_CON0_RSV1 = MT6351_PMIC_BUCK_ALL_CON0_RSV1, + PMIC_BUCK_ALL_CON0_RSV0 = MT6351_PMIC_BUCK_ALL_CON0_RSV0, + PMIC_BUCK_BUCK_RSV = MT6351_PMIC_BUCK_BUCK_RSV, + PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL = MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL, + PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL = MT6351_PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL, + PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL = MT6351_PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL, + PMIC_BUCK_ALL_CON2_RSV0 = MT6351_PMIC_BUCK_ALL_CON2_RSV0, + PMIC_BUCK_VSLEEP_SRC0 = MT6351_PMIC_BUCK_VSLEEP_SRC0, + PMIC_BUCK_VSLEEP_SRC1 = MT6351_PMIC_BUCK_VSLEEP_SRC1, + PMIC_BUCK_R2R_SRC0 = MT6351_PMIC_BUCK_R2R_SRC0, + PMIC_BUCK_R2R_SRC1 = MT6351_PMIC_BUCK_R2R_SRC1, + PMIC_BUCK_BUCK_OSC_SEL_SRC0 = MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRC0, + PMIC_BUCK_SRCLKEN_DLY_SRC1 = MT6351_PMIC_BUCK_SRCLKEN_DLY_SRC1, + PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB = MT6351_PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB, + PMIC_BUCK_VPA_VOSEL_DLC011 = MT6351_PMIC_BUCK_VPA_VOSEL_DLC011, + PMIC_BUCK_VPA_VOSEL_DLC111 = MT6351_PMIC_BUCK_VPA_VOSEL_DLC111, + PMIC_BUCK_VPA_DLC_MAP_EN = MT6351_PMIC_BUCK_VPA_DLC_MAP_EN, + PMIC_BUCK_VPA_VOSEL_DLC001 = MT6351_PMIC_BUCK_VPA_VOSEL_DLC001, + PMIC_BUCK_VPA_DLC = MT6351_PMIC_BUCK_VPA_DLC, + PMIC_DA_NI_VPA_DLC = MT6351_PMIC_DA_NI_VPA_DLC, + PMIC_BUCK_VPA_DVS_TRANS_TD = MT6351_PMIC_BUCK_VPA_DVS_TRANS_TD, + PMIC_BUCK_VPA_DVS_TRANS_CTRL = MT6351_PMIC_BUCK_VPA_DVS_TRANS_CTRL, + PMIC_BUCK_VPA_DVS_TRANS_ONCE = MT6351_PMIC_BUCK_VPA_DVS_TRANS_ONCE, + PMIC_DA_NI_VPA_DVS_TRANST = MT6351_PMIC_DA_NI_VPA_DVS_TRANST, + PMIC_BUCK_VPA_DIG0_RSV5 = MT6351_PMIC_BUCK_VPA_DIG0_RSV5, + PMIC_BUCK_VPA_DIG1_RSV5 = MT6351_PMIC_BUCK_VPA_DIG1_RSV5, + PMIC_BUCK_VCORE_VOSEL_AUD = MT6351_PMIC_BUCK_VCORE_VOSEL_AUD, + PMIC_BUCK_VCORE_DVFS_DONE = MT6351_PMIC_BUCK_VCORE_DVFS_DONE, + PMIC_BUCK_VCORE_DVFS_DONE_SW = MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SW, + PMIC_BUCK_VCORE_DVFS_DONE_STA = MT6351_PMIC_BUCK_VCORE_DVFS_DONE_STA, + PMIC_BUCK_VSRAM_MD_VOSEL_AUD = MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_AUD, + PMIC_BUCK_VSRAM_MD_DVFS_DONE = MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE, + PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW = MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW, + PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA = MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA, + PMIC_BUCK_VCORE_OC_STATUS = MT6351_PMIC_BUCK_VCORE_OC_STATUS, + PMIC_BUCK_VGPU_OC_STATUS = MT6351_PMIC_BUCK_VGPU_OC_STATUS, + PMIC_BUCK_VMODEM_OC_STATUS = MT6351_PMIC_BUCK_VMODEM_OC_STATUS, + PMIC_BUCK_VMD1_OC_STATUS = MT6351_PMIC_BUCK_VMD1_OC_STATUS, + PMIC_BUCK_VSRAM_MD_OC_STATUS = MT6351_PMIC_BUCK_VSRAM_MD_OC_STATUS, + PMIC_BUCK_VS1_OC_STATUS = MT6351_PMIC_BUCK_VS1_OC_STATUS, + PMIC_BUCK_VS2_OC_STATUS = MT6351_PMIC_BUCK_VS2_OC_STATUS, + PMIC_BUCK_VPA_OC_STATUS = MT6351_PMIC_BUCK_VPA_OC_STATUS, + PMIC_BUCK_VCORE_OC_INT_EN = MT6351_PMIC_BUCK_VCORE_OC_INT_EN, + PMIC_BUCK_VGPU_OC_INT_EN = MT6351_PMIC_BUCK_VGPU_OC_INT_EN, + PMIC_BUCK_VMODEM_OC_INT_EN = MT6351_PMIC_BUCK_VMODEM_OC_INT_EN, + PMIC_BUCK_VMD1_OC_INT_EN = MT6351_PMIC_BUCK_VMD1_OC_INT_EN, + PMIC_BUCK_VSRAM_MD_OC_INT_EN = MT6351_PMIC_BUCK_VSRAM_MD_OC_INT_EN, + PMIC_BUCK_VS1_OC_INT_EN = MT6351_PMIC_BUCK_VS1_OC_INT_EN, + PMIC_BUCK_VS2_OC_INT_EN = MT6351_PMIC_BUCK_VS2_OC_INT_EN, + PMIC_BUCK_VPA_OC_INT_EN = MT6351_PMIC_BUCK_VPA_OC_INT_EN, + PMIC_BUCK_VCORE_EN_OC_SDN_SEL = MT6351_PMIC_BUCK_VCORE_EN_OC_SDN_SEL, + PMIC_BUCK_VGPU_EN_OC_SDN_SEL = MT6351_PMIC_BUCK_VGPU_EN_OC_SDN_SEL, + PMIC_BUCK_VMODEM_EN_OC_SDN_SEL = MT6351_PMIC_BUCK_VMODEM_EN_OC_SDN_SEL, + PMIC_BUCK_VMD1_EN_OC_SDN_SEL = MT6351_PMIC_BUCK_VMD1_EN_OC_SDN_SEL, + PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL = MT6351_PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL, + PMIC_BUCK_VS1_EN_OC_SDN_SEL = MT6351_PMIC_BUCK_VS1_EN_OC_SDN_SEL, + PMIC_BUCK_VS2_EN_OC_SDN_SEL = MT6351_PMIC_BUCK_VS2_EN_OC_SDN_SEL, + PMIC_BUCK_VPA_EN_OC_SDN_SEL = MT6351_PMIC_BUCK_VPA_EN_OC_SDN_SEL, + PMIC_BUCK_VCORE_OC_FLAG_CLR = MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR, + PMIC_BUCK_VGPU_OC_FLAG_CLR = MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR, + PMIC_BUCK_VMODEM_OC_FLAG_CLR = MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR, + PMIC_BUCK_VMD1_OC_FLAG_CLR = MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR, + PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR = MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR, + PMIC_BUCK_VS1_OC_FLAG_CLR = MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR, + PMIC_BUCK_VS2_OC_FLAG_CLR = MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR, + PMIC_BUCK_VPA_OC_FLAG_CLR = MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR, + PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL = MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL, + PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL = MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL, + PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL = MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL, + PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL = MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL, + PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL = MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL, + PMIC_BUCK_VS1_OC_FLAG_CLR_SEL = MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SEL, + PMIC_BUCK_VS2_OC_FLAG_CLR_SEL = MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SEL, + PMIC_BUCK_VPA_OC_FLAG_CLR_SEL = MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SEL, + PMIC_BUCK_VCORE_OC_DEG_EN = MT6351_PMIC_BUCK_VCORE_OC_DEG_EN, + PMIC_BUCK_VCORE_OC_WND = MT6351_PMIC_BUCK_VCORE_OC_WND, + PMIC_BUCK_VCORE_OC_THD = MT6351_PMIC_BUCK_VCORE_OC_THD, + PMIC_BUCK_VGPU_OC_DEG_EN = MT6351_PMIC_BUCK_VGPU_OC_DEG_EN, + PMIC_BUCK_VGPU_OC_WND = MT6351_PMIC_BUCK_VGPU_OC_WND, + PMIC_BUCK_VGPU_OC_THD = MT6351_PMIC_BUCK_VGPU_OC_THD, + PMIC_BUCK_VMODEM_OC_DEG_EN = MT6351_PMIC_BUCK_VMODEM_OC_DEG_EN, + PMIC_BUCK_VMODEM_OC_WND = MT6351_PMIC_BUCK_VMODEM_OC_WND, + PMIC_BUCK_VMODEM_OC_THD = MT6351_PMIC_BUCK_VMODEM_OC_THD, + PMIC_BUCK_VMD1_OC_DEG_EN = MT6351_PMIC_BUCK_VMD1_OC_DEG_EN, + PMIC_BUCK_VMD1_OC_WND = MT6351_PMIC_BUCK_VMD1_OC_WND, + PMIC_BUCK_VMD1_OC_THD = MT6351_PMIC_BUCK_VMD1_OC_THD, + PMIC_BUCK_VSRAM_MD_OC_DEG_EN = MT6351_PMIC_BUCK_VSRAM_MD_OC_DEG_EN, + PMIC_BUCK_VSRAM_MD_OC_WND = MT6351_PMIC_BUCK_VSRAM_MD_OC_WND, + PMIC_BUCK_VSRAM_MD_OC_THD = MT6351_PMIC_BUCK_VSRAM_MD_OC_THD, + PMIC_BUCK_VS1_OC_DEG_EN = MT6351_PMIC_BUCK_VS1_OC_DEG_EN, + PMIC_BUCK_VS1_OC_WND = MT6351_PMIC_BUCK_VS1_OC_WND, + PMIC_BUCK_VS1_OC_THD = MT6351_PMIC_BUCK_VS1_OC_THD, + PMIC_BUCK_VS2_OC_DEG_EN = MT6351_PMIC_BUCK_VS2_OC_DEG_EN, + PMIC_BUCK_VS2_OC_WND = MT6351_PMIC_BUCK_VS2_OC_WND, + PMIC_BUCK_VS2_OC_THD = MT6351_PMIC_BUCK_VS2_OC_THD, + PMIC_BUCK_VPA_OC_DEG_EN = MT6351_PMIC_BUCK_VPA_OC_DEG_EN, + PMIC_BUCK_VPA_OC_WND = MT6351_PMIC_BUCK_VPA_OC_WND, + PMIC_BUCK_VPA_OC_THD = MT6351_PMIC_BUCK_VPA_OC_THD, + PMIC_RG_SMPS_TESTMODE_B = MT6351_PMIC_RG_SMPS_TESTMODE_B, + PMIC_RG_VPA_BURSTH = MT6351_PMIC_RG_VPA_BURSTH, + PMIC_RG_VPA_BURSTL = MT6351_PMIC_RG_VPA_BURSTL, + PMIC_RG_VPA_TRIMH = MT6351_PMIC_RG_VPA_TRIMH, + PMIC_RG_VPA_TRIML = MT6351_PMIC_RG_VPA_TRIML, + PMIC_RG_VPA_TRIM_REF = MT6351_PMIC_RG_VPA_TRIM_REF, + PMIC_RG_VCORE_TRIMH = MT6351_PMIC_RG_VCORE_TRIMH, + PMIC_RG_VCORE_TRIML = MT6351_PMIC_RG_VCORE_TRIML, + PMIC_RG_VCORE_VSLEEP = MT6351_PMIC_RG_VCORE_VSLEEP, + PMIC_RG_VGPU_TRIMH = MT6351_PMIC_RG_VGPU_TRIMH, + PMIC_RG_VGPU_TRIML = MT6351_PMIC_RG_VGPU_TRIML, + PMIC_RG_VGPU_VSLEEP = MT6351_PMIC_RG_VGPU_VSLEEP, + PMIC_RG_VSRAM_MD_TRIMH = MT6351_PMIC_RG_VSRAM_MD_TRIMH, + PMIC_RG_VSRAM_MD_TRIML = MT6351_PMIC_RG_VSRAM_MD_TRIML, + PMIC_RG_VSRAM_MD_VSLEEP = MT6351_PMIC_RG_VSRAM_MD_VSLEEP, + PMIC_RG_VMODEM_TRIMH = MT6351_PMIC_RG_VMODEM_TRIMH, + PMIC_RG_VMODEM_TRIML = MT6351_PMIC_RG_VMODEM_TRIML, + PMIC_RG_VMODEM_VSLEEP = MT6351_PMIC_RG_VMODEM_VSLEEP, + PMIC_RG_VMD1_TRIMH = MT6351_PMIC_RG_VMD1_TRIMH, + PMIC_RG_VMD1_TRIML = MT6351_PMIC_RG_VMD1_TRIML, + PMIC_RG_VMD1_VSLEEP = MT6351_PMIC_RG_VMD1_VSLEEP, + PMIC_RG_VS1_TRIMH = MT6351_PMIC_RG_VS1_TRIMH, + PMIC_RG_VS1_TRIML = MT6351_PMIC_RG_VS1_TRIML, + PMIC_RG_VS1_VSLEEP = MT6351_PMIC_RG_VS1_VSLEEP, + PMIC_RG_VS2_TRIML = MT6351_PMIC_RG_VS2_TRIML, + PMIC_RG_VS2_VSLEEP = MT6351_PMIC_RG_VS2_VSLEEP, + PMIC_RG_VSRAM_PROCESSOR_TRIMH = MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIMH, + PMIC_RG_VSRAM_PROCESSOR_TRIML = MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIML, + PMIC_RG_VSRAM_PROCESSOR_VSLEEP = MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP, + PMIC_RG_VCORE_VSLEEP_SEL = MT6351_PMIC_RG_VCORE_VSLEEP_SEL, + PMIC_RG_VGPU_VSLEEP_SEL = MT6351_PMIC_RG_VGPU_VSLEEP_SEL, + PMIC_RG_VSRAM_MD_VSLEEP_SEL = MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SEL, + PMIC_RG_VMODEM_VSLEEP_SEL = MT6351_PMIC_RG_VMODEM_VSLEEP_SEL, + PMIC_RG_VMD1_VSLEEP_SEL = MT6351_PMIC_RG_VMD1_VSLEEP_SEL, + PMIC_RG_VS1_VSLEEP_SEL = MT6351_PMIC_RG_VS1_VSLEEP_SEL, + PMIC_RG_VS2_VSLEEP_SEL = MT6351_PMIC_RG_VS2_VSLEEP_SEL, + PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL = MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL, + PMIC_RG_VOUTDET_EN = MT6351_PMIC_RG_VOUTDET_EN, + PMIC_RG_VS2_TRIMH = MT6351_PMIC_RG_VS2_TRIMH, + PMIC_RG_VCORE_MODESET = MT6351_PMIC_RG_VCORE_MODESET, + PMIC_RG_VCORE_NDIS_EN = MT6351_PMIC_RG_VCORE_NDIS_EN, + PMIC_RG_VCORE_VRF18_SSTART_EN = MT6351_PMIC_RG_VCORE_VRF18_SSTART_EN, + PMIC_RG_VCORE_AUTO_MODE = MT6351_PMIC_RG_VCORE_AUTO_MODE, + PMIC_RG_VCORE_RZSEL0 = MT6351_PMIC_RG_VCORE_RZSEL0, + PMIC_RG_VCORE_RZSEL1 = MT6351_PMIC_RG_VCORE_RZSEL1, + PMIC_RG_VCORE_CCSEL0 = MT6351_PMIC_RG_VCORE_CCSEL0, + PMIC_RG_VCORE_CCSEL1 = MT6351_PMIC_RG_VCORE_CCSEL1, + PMIC_RG_VCORE_CSL = MT6351_PMIC_RG_VCORE_CSL, + PMIC_RG_VCORE_SLP = MT6351_PMIC_RG_VCORE_SLP, + PMIC_RG_VCORE_ADRC_FEN = MT6351_PMIC_RG_VCORE_ADRC_FEN, + PMIC_RG_VCORE_VCCAP_CLAMP_FEN = MT6351_PMIC_RG_VCORE_VCCAP_CLAMP_FEN, + PMIC_RG_VCORE_VC_CLAMP_FEN = MT6351_PMIC_RG_VCORE_VC_CLAMP_FEN, + PMIC_RG_VCORE_PREOC_SEL = MT6351_PMIC_RG_VCORE_PREOC_SEL, + PMIC_RG_VCORE_PFMOC = MT6351_PMIC_RG_VCORE_PFMOC, + PMIC_RG_VCORE_CSR = MT6351_PMIC_RG_VCORE_CSR, + PMIC_RG_VCORE_ZXOS_TRIM = MT6351_PMIC_RG_VCORE_ZXOS_TRIM, + PMIC_RG_VCORE_CSM_N = MT6351_PMIC_RG_VCORE_CSM_N, + PMIC_RG_VCORE_CSM_P = MT6351_PMIC_RG_VCORE_CSM_P, + PMIC_RG_VCORE_PFMSR_EH = MT6351_PMIC_RG_VCORE_PFMSR_EH, + PMIC_RG_VCORE_NLIM_GATING = MT6351_PMIC_RG_VCORE_NLIM_GATING, + PMIC_RG_VCORE_PWRSR_EH = MT6351_PMIC_RG_VCORE_PWRSR_EH, + PMIC_RG_VCORE_HS_VTHDET = MT6351_PMIC_RG_VCORE_HS_VTHDET, + PMIC_RG_VCORE_PG_GATING = MT6351_PMIC_RG_VCORE_PG_GATING, + PMIC_RG_VCORE_HS_ONSPEED_EH = MT6351_PMIC_RG_VCORE_HS_ONSPEED_EH, + PMIC_RG_VCORE_NLIM_TRIMMING = MT6351_PMIC_RG_VCORE_NLIM_TRIMMING, + PMIC_RG_VCORE_DLC = MT6351_PMIC_RG_VCORE_DLC, + PMIC_RG_VCORE_DLC_N = MT6351_PMIC_RG_VCORE_DLC_N, + PMIC_RG_VCORE_PFM_RIP = MT6351_PMIC_RG_VCORE_PFM_RIP, + PMIC_RG_VCORE_TRAN_BST = MT6351_PMIC_RG_VCORE_TRAN_BST, + PMIC_RG_VCORE_DTS_ENB = MT6351_PMIC_RG_VCORE_DTS_ENB, + PMIC_RG_VCORE_MIN_OFF = MT6351_PMIC_RG_VCORE_MIN_OFF, + PMIC_RG_VCORE_1P35UP_SEL_EN = MT6351_PMIC_RG_VCORE_1P35UP_SEL_EN, + PMIC_RG_VCORE_DLC_AUTO_MODE = MT6351_PMIC_RG_VCORE_DLC_AUTO_MODE, + PMIC_RG_VCORE_DLC_SEL = MT6351_PMIC_RG_VCORE_DLC_SEL, + PMIC_RG_VCORE_SRC_AUTO_MODE = MT6351_PMIC_RG_VCORE_SRC_AUTO_MODE, + PMIC_RG_VCORE_UGP_SR = MT6351_PMIC_RG_VCORE_UGP_SR, + PMIC_RG_VCORE_LGN_SR = MT6351_PMIC_RG_VCORE_LGN_SR, + PMIC_RG_VCORE_UGP_SR_PFM = MT6351_PMIC_RG_VCORE_UGP_SR_PFM, + PMIC_RG_VCORE_LGN_SR_PFM = MT6351_PMIC_RG_VCORE_LGN_SR_PFM, + PMIC_RG_VCORE_UGD_VTHSEL = MT6351_PMIC_RG_VCORE_UGD_VTHSEL, + PMIC_RG_VCORE_FNLX_SNS = MT6351_PMIC_RG_VCORE_FNLX_SNS, + PMIC_RG_VCORE_VDIFF_ENLOWIQ = MT6351_PMIC_RG_VCORE_VDIFF_ENLOWIQ, + PMIC_RG_VCORE_PFMOC_FWUPOFF = MT6351_PMIC_RG_VCORE_PFMOC_FWUPOFF, + PMIC_RG_VCORE_PWFMOC_FWUPOFF = MT6351_PMIC_RG_VCORE_PWFMOC_FWUPOFF, + PMIC_RG_VCORE_CP_FWUPOFF = MT6351_PMIC_RG_VCORE_CP_FWUPOFF, + PMIC_RG_VCORE_ZX_GATING = MT6351_PMIC_RG_VCORE_ZX_GATING, + PMIC_RG_VCORE_RSV = MT6351_PMIC_RG_VCORE_RSV, + PMIC_RG_VCORE_PREOC_TRIMMING = MT6351_PMIC_RG_VCORE_PREOC_TRIMMING, + PMIC_RG_VCORE_AZC_EN = MT6351_PMIC_RG_VCORE_AZC_EN, + PMIC_RG_VCORE_AZC_DELAY = MT6351_PMIC_RG_VCORE_AZC_DELAY, + PMIC_RG_VCORE_AZC_HOLD_ENB = MT6351_PMIC_RG_VCORE_AZC_HOLD_ENB, + PMIC_RGS_QI_VCORE_OC_STATUS = MT6351_PMIC_RGS_QI_VCORE_OC_STATUS, + PMIC_RGS_QI_VCORE_DIG_MON = MT6351_PMIC_RGS_QI_VCORE_DIG_MON, + PMIC_RGS_VCORE_ENPWM_STATUS = MT6351_PMIC_RGS_VCORE_ENPWM_STATUS, + PMIC_RGS_QI_VCORE_PREOC = MT6351_PMIC_RGS_QI_VCORE_PREOC, + PMIC_RG_VGPU_MODESET = MT6351_PMIC_RG_VGPU_MODESET, + PMIC_RG_VGPU_NDIS_EN = MT6351_PMIC_RG_VGPU_NDIS_EN, + PMIC_RG_VGPU_VRF18_SSTART_EN = MT6351_PMIC_RG_VGPU_VRF18_SSTART_EN, + PMIC_RG_VGPU_AUTO_MODE = MT6351_PMIC_RG_VGPU_AUTO_MODE, + PMIC_RG_VGPU_RZSEL0 = MT6351_PMIC_RG_VGPU_RZSEL0, + PMIC_RG_VGPU_RZSEL1 = MT6351_PMIC_RG_VGPU_RZSEL1, + PMIC_RG_VGPU_CCSEL0 = MT6351_PMIC_RG_VGPU_CCSEL0, + PMIC_RG_VGPU_CCSEL1 = MT6351_PMIC_RG_VGPU_CCSEL1, + PMIC_RG_VGPU_CSL = MT6351_PMIC_RG_VGPU_CSL, + PMIC_RG_VGPU_SLP = MT6351_PMIC_RG_VGPU_SLP, + PMIC_RG_VGPU_ADRC_FEN = MT6351_PMIC_RG_VGPU_ADRC_FEN, + PMIC_RG_VGPU_VCCAP_CLAMP_FEN = MT6351_PMIC_RG_VGPU_VCCAP_CLAMP_FEN, + PMIC_RG_VGPU_VC_CLAMP_FEN = MT6351_PMIC_RG_VGPU_VC_CLAMP_FEN, + PMIC_RG_VGPU_PREOC_SEL = MT6351_PMIC_RG_VGPU_PREOC_SEL, + PMIC_RG_VGPU_PFMOC = MT6351_PMIC_RG_VGPU_PFMOC, + PMIC_RG_VGPU_CSR = MT6351_PMIC_RG_VGPU_CSR, + PMIC_RG_VGPU_ZXOS_TRIM = MT6351_PMIC_RG_VGPU_ZXOS_TRIM, + PMIC_RG_VGPU_CSM_N = MT6351_PMIC_RG_VGPU_CSM_N, + PMIC_RG_VGPU_CSM_P = MT6351_PMIC_RG_VGPU_CSM_P, + PMIC_RG_VGPU_PFMSR_EH = MT6351_PMIC_RG_VGPU_PFMSR_EH, + PMIC_RG_VGPU_NLIM_GATING = MT6351_PMIC_RG_VGPU_NLIM_GATING, + PMIC_RG_VGPU_PWRSR_EH = MT6351_PMIC_RG_VGPU_PWRSR_EH, + PMIC_RG_VGPU_HS_VTHDET = MT6351_PMIC_RG_VGPU_HS_VTHDET, + PMIC_RG_VGPU_PG_GATING = MT6351_PMIC_RG_VGPU_PG_GATING, + PMIC_RG_VGPU_HS_ONSPEED_EH = MT6351_PMIC_RG_VGPU_HS_ONSPEED_EH, + PMIC_RG_VGPU_NLIM_TRIMMING = MT6351_PMIC_RG_VGPU_NLIM_TRIMMING, + PMIC_RG_VGPU_DLC = MT6351_PMIC_RG_VGPU_DLC, + PMIC_RG_VGPU_DLC_N = MT6351_PMIC_RG_VGPU_DLC_N, + PMIC_RG_VGPU_PFM_RIP = MT6351_PMIC_RG_VGPU_PFM_RIP, + PMIC_RG_VGPU_TRAN_BST = MT6351_PMIC_RG_VGPU_TRAN_BST, + PMIC_RG_VGPU_DTS_ENB = MT6351_PMIC_RG_VGPU_DTS_ENB, + PMIC_RG_VGPU_MIN_OFF = MT6351_PMIC_RG_VGPU_MIN_OFF, + PMIC_RG_VGPU_1P35UP_SEL_EN = MT6351_PMIC_RG_VGPU_1P35UP_SEL_EN, + PMIC_RG_VGPU_DLC_AUTO_MODE = MT6351_PMIC_RG_VGPU_DLC_AUTO_MODE, + PMIC_RG_VGPU_DLC_SEL = MT6351_PMIC_RG_VGPU_DLC_SEL, + PMIC_RG_VGPU_SRC_AUTO_MODE = MT6351_PMIC_RG_VGPU_SRC_AUTO_MODE, + PMIC_RG_VGPU_UGP_SR = MT6351_PMIC_RG_VGPU_UGP_SR, + PMIC_RG_VGPU_LGN_SR = MT6351_PMIC_RG_VGPU_LGN_SR, + PMIC_RG_VGPU_UGP_SR_PFM = MT6351_PMIC_RG_VGPU_UGP_SR_PFM, + PMIC_RG_VGPU_LGN_SR_PFM = MT6351_PMIC_RG_VGPU_LGN_SR_PFM, + PMIC_RG_VGPU_UGD_VTHSEL = MT6351_PMIC_RG_VGPU_UGD_VTHSEL, + PMIC_RG_VGPU_FNLX_SNS = MT6351_PMIC_RG_VGPU_FNLX_SNS, + PMIC_RG_VGPU_VDIFF_ENLOWIQ = MT6351_PMIC_RG_VGPU_VDIFF_ENLOWIQ, + PMIC_RG_VGPU_PFMOC_FWUPOFF = MT6351_PMIC_RG_VGPU_PFMOC_FWUPOFF, + PMIC_RG_VGPU_PWFMOC_FWUPOFF = MT6351_PMIC_RG_VGPU_PWFMOC_FWUPOFF, + PMIC_RG_VGPU_CP_FWUPOFF = MT6351_PMIC_RG_VGPU_CP_FWUPOFF, + PMIC_RG_VGPU_ZX_GATING = MT6351_PMIC_RG_VGPU_ZX_GATING, + PMIC_RG_VGPU_RSV = MT6351_PMIC_RG_VGPU_RSV, + PMIC_RG_VGPU_PREOC_TRIMMING = MT6351_PMIC_RG_VGPU_PREOC_TRIMMING, + PMIC_RG_VGPU_AZC_EN = MT6351_PMIC_RG_VGPU_AZC_EN, + PMIC_RG_VGPU_AZC_DELAY = MT6351_PMIC_RG_VGPU_AZC_DELAY, + PMIC_RG_VGPU_AZC_HOLD_ENB = MT6351_PMIC_RG_VGPU_AZC_HOLD_ENB, + PMIC_RGS_QI_VGPU_OC_STATUS = MT6351_PMIC_RGS_QI_VGPU_OC_STATUS, + PMIC_RGS_QI_VGPU_DIG_MON = MT6351_PMIC_RGS_QI_VGPU_DIG_MON, + PMIC_RGS_VGPU_ENPWM_STATUS = MT6351_PMIC_RGS_VGPU_ENPWM_STATUS, + PMIC_RGS_QI_VGPU_PREOC = MT6351_PMIC_RGS_QI_VGPU_PREOC, + PMIC_RG_VSRAM_MD_MODESET = MT6351_PMIC_RG_VSRAM_MD_MODESET, + PMIC_RG_VSRAM_MD_NDIS_EN = MT6351_PMIC_RG_VSRAM_MD_NDIS_EN, + PMIC_RG_VSRAM_MD_VRF18_SSTART_EN = MT6351_PMIC_RG_VSRAM_MD_VRF18_SSTART_EN, + PMIC_RG_VSRAM_MD_AUTO_MODE = MT6351_PMIC_RG_VSRAM_MD_AUTO_MODE, + PMIC_RG_VSRAM_MD_RZSEL0 = MT6351_PMIC_RG_VSRAM_MD_RZSEL0, + PMIC_RG_VSRAM_MD_RZSEL1 = MT6351_PMIC_RG_VSRAM_MD_RZSEL1, + PMIC_RG_VSRAM_MD_CCSEL0 = MT6351_PMIC_RG_VSRAM_MD_CCSEL0, + PMIC_RG_VSRAM_MD_CCSEL1 = MT6351_PMIC_RG_VSRAM_MD_CCSEL1, + PMIC_RG_VSRAM_MD_CSL = MT6351_PMIC_RG_VSRAM_MD_CSL, + PMIC_RG_VSRAM_MD_SLP = MT6351_PMIC_RG_VSRAM_MD_SLP, + PMIC_RG_VSRAM_MD_ADRC_FEN = MT6351_PMIC_RG_VSRAM_MD_ADRC_FEN, + PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN = MT6351_PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN, + PMIC_RG_VSRAM_MD_VC_CLAMP_FEN = MT6351_PMIC_RG_VSRAM_MD_VC_CLAMP_FEN, + PMIC_RG_VSRAM_MD_PFMOC = MT6351_PMIC_RG_VSRAM_MD_PFMOC, + PMIC_RG_VSRAM_MD_CSR = MT6351_PMIC_RG_VSRAM_MD_CSR, + PMIC_RG_VSRAM_MD_ZXOS_TRIM = MT6351_PMIC_RG_VSRAM_MD_ZXOS_TRIM, + PMIC_RG_VSRAM_MD_PFMSR_EH = MT6351_PMIC_RG_VSRAM_MD_PFMSR_EH, + PMIC_RG_VSRAM_MD_NLIM_GATING = MT6351_PMIC_RG_VSRAM_MD_NLIM_GATING, + PMIC_RG_VSRAM_MD_PWRSR_EH = MT6351_PMIC_RG_VSRAM_MD_PWRSR_EH, + PMIC_RG_VSRAM_MD_HS_VTHDET = MT6351_PMIC_RG_VSRAM_MD_HS_VTHDET, + PMIC_RG_VSRAM_MD_PG_GATING = MT6351_PMIC_RG_VSRAM_MD_PG_GATING, + PMIC_RG_VSRAM_MD_HS_ONSPEED_EH = MT6351_PMIC_RG_VSRAM_MD_HS_ONSPEED_EH, + PMIC_RG_VSRAM_MD_NLIM_TRIMMING = MT6351_PMIC_RG_VSRAM_MD_NLIM_TRIMMING, + PMIC_RG_VSRAM_MD_DLC = MT6351_PMIC_RG_VSRAM_MD_DLC, + PMIC_RG_VSRAM_MD_DLC_N = MT6351_PMIC_RG_VSRAM_MD_DLC_N, + PMIC_RG_VSRAM_MD_PFM_RIP = MT6351_PMIC_RG_VSRAM_MD_PFM_RIP, + PMIC_RG_VSRAM_MD_TRAN_BST = MT6351_PMIC_RG_VSRAM_MD_TRAN_BST, + PMIC_RG_VSRAM_MD_DTS_ENB = MT6351_PMIC_RG_VSRAM_MD_DTS_ENB, + PMIC_RG_VSRAM_MD_MIN_OFF = MT6351_PMIC_RG_VSRAM_MD_MIN_OFF, + PMIC_RG_VSRAM_MD_1P35UP_SEL_EN = MT6351_PMIC_RG_VSRAM_MD_1P35UP_SEL_EN, + PMIC_RG_VSRAM_MD_DLC_AUTO_MODE = MT6351_PMIC_RG_VSRAM_MD_DLC_AUTO_MODE, + PMIC_RG_VSRAM_MD_DLC_SEL = MT6351_PMIC_RG_VSRAM_MD_DLC_SEL, + PMIC_RG_VSRAM_MD_SRC_AUTO_MODE = MT6351_PMIC_RG_VSRAM_MD_SRC_AUTO_MODE, + PMIC_RG_VSRAM_MD_UGP_SR = MT6351_PMIC_RG_VSRAM_MD_UGP_SR, + PMIC_RG_VSRAM_MD_LGN_SR = MT6351_PMIC_RG_VSRAM_MD_LGN_SR, + PMIC_RG_VSRAM_MD_UGP_SR_PFM = MT6351_PMIC_RG_VSRAM_MD_UGP_SR_PFM, + PMIC_RG_VSRAM_MD_LGN_SR_PFM = MT6351_PMIC_RG_VSRAM_MD_LGN_SR_PFM, + PMIC_RG_VSRAM_MD_UGD_VTHSEL = MT6351_PMIC_RG_VSRAM_MD_UGD_VTHSEL, + PMIC_RG_VSRAM_MD_FNLX_SNS = MT6351_PMIC_RG_VSRAM_MD_FNLX_SNS, + PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ = MT6351_PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ, + PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF = MT6351_PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF, + PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF = MT6351_PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF, + PMIC_RG_VSRAM_MD_CP_FWUPOFF = MT6351_PMIC_RG_VSRAM_MD_CP_FWUPOFF, + PMIC_RG_VSRAM_MD_ZX_GATING = MT6351_PMIC_RG_VSRAM_MD_ZX_GATING, + PMIC_RG_VSRAM_MD_RSV = MT6351_PMIC_RG_VSRAM_MD_RSV, + PMIC_RG_VSRAM_MD_AZC_EN = MT6351_PMIC_RG_VSRAM_MD_AZC_EN, + PMIC_RG_VSRAM_MD_AZC_DELAY = MT6351_PMIC_RG_VSRAM_MD_AZC_DELAY, + PMIC_RG_VSRAM_MD_AZC_HOLD_ENB = MT6351_PMIC_RG_VSRAM_MD_AZC_HOLD_ENB, + PMIC_RGS_QI_VSRAM_MD_OC_STATUS = MT6351_PMIC_RGS_QI_VSRAM_MD_OC_STATUS, + PMIC_RGS_QI_VSRAM_MD_DIG_MON = MT6351_PMIC_RGS_QI_VSRAM_MD_DIG_MON, + PMIC_RGS_VSRAM_MD_ENPWM_STATUS = MT6351_PMIC_RGS_VSRAM_MD_ENPWM_STATUS, + PMIC_RG_VMODEM_MODESET = MT6351_PMIC_RG_VMODEM_MODESET, + PMIC_RG_VMODEM_NDIS_EN = MT6351_PMIC_RG_VMODEM_NDIS_EN, + PMIC_RG_VMODEM_VRF18_SSTART_EN = MT6351_PMIC_RG_VMODEM_VRF18_SSTART_EN, + PMIC_RG_VMODEM_AUTO_MODE = MT6351_PMIC_RG_VMODEM_AUTO_MODE, + PMIC_RG_VMODEM_RZSEL0 = MT6351_PMIC_RG_VMODEM_RZSEL0, + PMIC_RG_VMODEM_RZSEL1 = MT6351_PMIC_RG_VMODEM_RZSEL1, + PMIC_RG_VMODEM_CCSEL0 = MT6351_PMIC_RG_VMODEM_CCSEL0, + PMIC_RG_VMODEM_CCSEL1 = MT6351_PMIC_RG_VMODEM_CCSEL1, + PMIC_RG_VMODEM_CSL = MT6351_PMIC_RG_VMODEM_CSL, + PMIC_RG_VMODEM_SLP = MT6351_PMIC_RG_VMODEM_SLP, + PMIC_RG_VMODEM_ADRC_FEN = MT6351_PMIC_RG_VMODEM_ADRC_FEN, + PMIC_RG_VMODEM_VCCAP_CLAMP_FEN = MT6351_PMIC_RG_VMODEM_VCCAP_CLAMP_FEN, + PMIC_RG_VMODEM_VC_CLAMP_FEN = MT6351_PMIC_RG_VMODEM_VC_CLAMP_FEN, + PMIC_RG_VMODEM_PFMOC = MT6351_PMIC_RG_VMODEM_PFMOC, + PMIC_RG_VMODEM_CSR = MT6351_PMIC_RG_VMODEM_CSR, + PMIC_RG_VMODEM_ZXOS_TRIM = MT6351_PMIC_RG_VMODEM_ZXOS_TRIM, + PMIC_RG_VMODEM_PFMSR_EH = MT6351_PMIC_RG_VMODEM_PFMSR_EH, + PMIC_RG_VMODEM_NLIM_GATING = MT6351_PMIC_RG_VMODEM_NLIM_GATING, + PMIC_RG_VMODEM_PWRSR_EH = MT6351_PMIC_RG_VMODEM_PWRSR_EH, + PMIC_RG_VMODEM_HS_VTHDET = MT6351_PMIC_RG_VMODEM_HS_VTHDET, + PMIC_RG_VMODEM_PG_GATING = MT6351_PMIC_RG_VMODEM_PG_GATING, + PMIC_RG_VMODEM_HS_ONSPEED_EH = MT6351_PMIC_RG_VMODEM_HS_ONSPEED_EH, + PMIC_RG_VMODEM_NLIM_TRIMMING = MT6351_PMIC_RG_VMODEM_NLIM_TRIMMING, + PMIC_RG_VMODEM_DLC = MT6351_PMIC_RG_VMODEM_DLC, + PMIC_RG_VMODEM_DLC_N = MT6351_PMIC_RG_VMODEM_DLC_N, + PMIC_RG_VMODEM_PFM_RIP = MT6351_PMIC_RG_VMODEM_PFM_RIP, + PMIC_RG_VMODEM_TRAN_BST = MT6351_PMIC_RG_VMODEM_TRAN_BST, + PMIC_RG_VMODEM_DTS_ENB = MT6351_PMIC_RG_VMODEM_DTS_ENB, + PMIC_RG_VMODEM_MIN_OFF = MT6351_PMIC_RG_VMODEM_MIN_OFF, + PMIC_RG_VMODEM_1P35UP_SEL_EN = MT6351_PMIC_RG_VMODEM_1P35UP_SEL_EN, + PMIC_RG_VMODEM_DLC_AUTO_MODE = MT6351_PMIC_RG_VMODEM_DLC_AUTO_MODE, + PMIC_RG_VMODEM_DLC_SEL = MT6351_PMIC_RG_VMODEM_DLC_SEL, + PMIC_RG_VMODEM_SRC_AUTO_MODE = MT6351_PMIC_RG_VMODEM_SRC_AUTO_MODE, + PMIC_RG_VMODEM_UGP_SR = MT6351_PMIC_RG_VMODEM_UGP_SR, + PMIC_RG_VMODEM_LGN_SR = MT6351_PMIC_RG_VMODEM_LGN_SR, + PMIC_RG_VMODEM_UGP_SR_PFM = MT6351_PMIC_RG_VMODEM_UGP_SR_PFM, + PMIC_RG_VMODEM_LGN_SR_PFM = MT6351_PMIC_RG_VMODEM_LGN_SR_PFM, + PMIC_RG_VMODEM_UGD_VTHSEL = MT6351_PMIC_RG_VMODEM_UGD_VTHSEL, + PMIC_RG_VMODEM_FNLX_SNS = MT6351_PMIC_RG_VMODEM_FNLX_SNS, + PMIC_RG_VMODEM_VDIFF_ENLOWIQ = MT6351_PMIC_RG_VMODEM_VDIFF_ENLOWIQ, + PMIC_RG_VMODEM_PFMOC_FWUPOFF = MT6351_PMIC_RG_VMODEM_PFMOC_FWUPOFF, + PMIC_RG_VMODEM_PWFMOC_FWUPOFF = MT6351_PMIC_RG_VMODEM_PWFMOC_FWUPOFF, + PMIC_RG_VMODEM_CP_FWUPOFF = MT6351_PMIC_RG_VMODEM_CP_FWUPOFF, + PMIC_RG_VMODEM_ZX_GATING = MT6351_PMIC_RG_VMODEM_ZX_GATING, + PMIC_RG_VMODEM_RSV = MT6351_PMIC_RG_VMODEM_RSV, + PMIC_RG_VMODEM_AZC_EN = MT6351_PMIC_RG_VMODEM_AZC_EN, + PMIC_RG_VMODEM_AZC_DELAY = MT6351_PMIC_RG_VMODEM_AZC_DELAY, + PMIC_RG_VMODEM_AZC_HOLD_ENB = MT6351_PMIC_RG_VMODEM_AZC_HOLD_ENB, + PMIC_RGS_QI_VMODEM_OC_STATUS = MT6351_PMIC_RGS_QI_VMODEM_OC_STATUS, + PMIC_RGS_QI_VMODEM_DIG_MON = MT6351_PMIC_RGS_QI_VMODEM_DIG_MON, + PMIC_RGS_VMODEM_ENPWM_STATUS = MT6351_PMIC_RGS_VMODEM_ENPWM_STATUS, + PMIC_RG_VMD1_MODESET = MT6351_PMIC_RG_VMD1_MODESET, + PMIC_RG_VMD1_NDIS_EN = MT6351_PMIC_RG_VMD1_NDIS_EN, + PMIC_RG_VMD1_VRF18_SSTART_EN = MT6351_PMIC_RG_VMD1_VRF18_SSTART_EN, + PMIC_RG_VMD1_AUTO_MODE = MT6351_PMIC_RG_VMD1_AUTO_MODE, + PMIC_RG_VMD1_RZSEL0 = MT6351_PMIC_RG_VMD1_RZSEL0, + PMIC_RG_VMD1_RZSEL1 = MT6351_PMIC_RG_VMD1_RZSEL1, + PMIC_RG_VMD1_CCSEL0 = MT6351_PMIC_RG_VMD1_CCSEL0, + PMIC_RG_VMD1_CCSEL1 = MT6351_PMIC_RG_VMD1_CCSEL1, + PMIC_RG_VMD1_CSL = MT6351_PMIC_RG_VMD1_CSL, + PMIC_RG_VMD1_SLP = MT6351_PMIC_RG_VMD1_SLP, + PMIC_RG_VMD1_ADRC_FEN = MT6351_PMIC_RG_VMD1_ADRC_FEN, + PMIC_RG_VMD1_VCCAP_CLAMP_FEN = MT6351_PMIC_RG_VMD1_VCCAP_CLAMP_FEN, + PMIC_RG_VMD1_VC_CLAMP_FEN = MT6351_PMIC_RG_VMD1_VC_CLAMP_FEN, + PMIC_RG_VMD1_PFMOC = MT6351_PMIC_RG_VMD1_PFMOC, + PMIC_RG_VMD1_CSR = MT6351_PMIC_RG_VMD1_CSR, + PMIC_RG_VMD1_ZXOS_TRIM = MT6351_PMIC_RG_VMD1_ZXOS_TRIM, + PMIC_RG_VMD1_PFMSR_EH = MT6351_PMIC_RG_VMD1_PFMSR_EH, + PMIC_RG_VMD1_NLIM_GATING = MT6351_PMIC_RG_VMD1_NLIM_GATING, + PMIC_RG_VMD1_PWRSR_EH = MT6351_PMIC_RG_VMD1_PWRSR_EH, + PMIC_RG_VMD1_HS_VTHDET = MT6351_PMIC_RG_VMD1_HS_VTHDET, + PMIC_RG_VMD1_PG_GATING = MT6351_PMIC_RG_VMD1_PG_GATING, + PMIC_RG_VMD1_HS_ONSPEED_EH = MT6351_PMIC_RG_VMD1_HS_ONSPEED_EH, + PMIC_RG_VMD1_NLIM_TRIMMING = MT6351_PMIC_RG_VMD1_NLIM_TRIMMING, + PMIC_RG_VMD1_DLC = MT6351_PMIC_RG_VMD1_DLC, + PMIC_RG_VMD1_DLC_N = MT6351_PMIC_RG_VMD1_DLC_N, + PMIC_RG_VMD1_PFM_RIP = MT6351_PMIC_RG_VMD1_PFM_RIP, + PMIC_RG_VMD1_TRAN_BST = MT6351_PMIC_RG_VMD1_TRAN_BST, + PMIC_RG_VMD1_DTS_ENB = MT6351_PMIC_RG_VMD1_DTS_ENB, + PMIC_RG_VMD1_MIN_OFF = MT6351_PMIC_RG_VMD1_MIN_OFF, + PMIC_RG_VMD1_1P35UP_SEL_EN = MT6351_PMIC_RG_VMD1_1P35UP_SEL_EN, + PMIC_RG_VMD1_DLC_AUTO_MODE = MT6351_PMIC_RG_VMD1_DLC_AUTO_MODE, + PMIC_RG_VMD1_DLC_SEL = MT6351_PMIC_RG_VMD1_DLC_SEL, + PMIC_RG_VMD1_SRC_AUTO_MODE = MT6351_PMIC_RG_VMD1_SRC_AUTO_MODE, + PMIC_RG_VMD1_UGP_SR = MT6351_PMIC_RG_VMD1_UGP_SR, + PMIC_RG_VMD1_LGN_SR = MT6351_PMIC_RG_VMD1_LGN_SR, + PMIC_RG_VMD1_UGP_SR_PFM = MT6351_PMIC_RG_VMD1_UGP_SR_PFM, + PMIC_RG_VMD1_LGN_SR_PFM = MT6351_PMIC_RG_VMD1_LGN_SR_PFM, + PMIC_RG_VMD1_UGD_VTHSEL = MT6351_PMIC_RG_VMD1_UGD_VTHSEL, + PMIC_RG_VMD1_FNLX_SNS = MT6351_PMIC_RG_VMD1_FNLX_SNS, + PMIC_RG_VMD1_VDIFF_ENLOWIQ = MT6351_PMIC_RG_VMD1_VDIFF_ENLOWIQ, + PMIC_RG_VMD1_PFMOC_FWUPOFF = MT6351_PMIC_RG_VMD1_PFMOC_FWUPOFF, + PMIC_RG_VMD1_PWFMOC_FWUPOFF = MT6351_PMIC_RG_VMD1_PWFMOC_FWUPOFF, + PMIC_RG_VMD1_CP_FWUPOFF = MT6351_PMIC_RG_VMD1_CP_FWUPOFF, + PMIC_RG_VMD1_ZX_GATING = MT6351_PMIC_RG_VMD1_ZX_GATING, + PMIC_RG_VMD1_RSV = MT6351_PMIC_RG_VMD1_RSV, + PMIC_RG_VMD1_AZC_EN = MT6351_PMIC_RG_VMD1_AZC_EN, + PMIC_RG_VMD1_AZC_DELAY = MT6351_PMIC_RG_VMD1_AZC_DELAY, + PMIC_RG_VMD1_AZC_HOLD_ENB = MT6351_PMIC_RG_VMD1_AZC_HOLD_ENB, + PMIC_RGS_QI_VMD1_OC_STATUS = MT6351_PMIC_RGS_QI_VMD1_OC_STATUS, + PMIC_RGS_QI_VMD1_DIG_MON = MT6351_PMIC_RGS_QI_VMD1_DIG_MON, + PMIC_RGS_VMD1_ENPWM_STATUS = MT6351_PMIC_RGS_VMD1_ENPWM_STATUS, + PMIC_RG_VS1_MODESET = MT6351_PMIC_RG_VS1_MODESET, + PMIC_RG_VS1_NDIS_EN = MT6351_PMIC_RG_VS1_NDIS_EN, + PMIC_RG_VS1_VRF18_SSTART_EN = MT6351_PMIC_RG_VS1_VRF18_SSTART_EN, + PMIC_RG_VS1_AUTO_MODE = MT6351_PMIC_RG_VS1_AUTO_MODE, + PMIC_RG_VS1_RZSEL0 = MT6351_PMIC_RG_VS1_RZSEL0, + PMIC_RG_VS1_RZSEL1 = MT6351_PMIC_RG_VS1_RZSEL1, + PMIC_RG_VS1_CCSEL0 = MT6351_PMIC_RG_VS1_CCSEL0, + PMIC_RG_VS1_CCSEL1 = MT6351_PMIC_RG_VS1_CCSEL1, + PMIC_RG_VS1_CSL = MT6351_PMIC_RG_VS1_CSL, + PMIC_RG_VS1_SLP = MT6351_PMIC_RG_VS1_SLP, + PMIC_RG_VS1_ADRC_FEN = MT6351_PMIC_RG_VS1_ADRC_FEN, + PMIC_RG_VS1_VCCAP_CLAMP_FEN = MT6351_PMIC_RG_VS1_VCCAP_CLAMP_FEN, + PMIC_RG_VS1_VC_CLAMP_FEN = MT6351_PMIC_RG_VS1_VC_CLAMP_FEN, + PMIC_RG_VS1_PFMOC = MT6351_PMIC_RG_VS1_PFMOC, + PMIC_RG_VS1_CSR = MT6351_PMIC_RG_VS1_CSR, + PMIC_RG_VS1_ZXOS_TRIM = MT6351_PMIC_RG_VS1_ZXOS_TRIM, + PMIC_RG_VS1_PFMSR_EH = MT6351_PMIC_RG_VS1_PFMSR_EH, + PMIC_RG_VS1_NLIM_GATING = MT6351_PMIC_RG_VS1_NLIM_GATING, + PMIC_RG_VS1_PWRSR_EH = MT6351_PMIC_RG_VS1_PWRSR_EH, + PMIC_RG_VS1_HS_VTHDET = MT6351_PMIC_RG_VS1_HS_VTHDET, + PMIC_RG_VS1_PG_GATING = MT6351_PMIC_RG_VS1_PG_GATING, + PMIC_RG_VS1_HS_ONSPEED_EH = MT6351_PMIC_RG_VS1_HS_ONSPEED_EH, + PMIC_RG_VS1_NLIM_TRIMMING = MT6351_PMIC_RG_VS1_NLIM_TRIMMING, + PMIC_RG_VS1_DLC = MT6351_PMIC_RG_VS1_DLC, + PMIC_RG_VS1_DLC_N = MT6351_PMIC_RG_VS1_DLC_N, + PMIC_RG_VS1_PFM_RIP = MT6351_PMIC_RG_VS1_PFM_RIP, + PMIC_RG_VS1_TRAN_BST = MT6351_PMIC_RG_VS1_TRAN_BST, + PMIC_RG_VS1_DTS_ENB = MT6351_PMIC_RG_VS1_DTS_ENB, + PMIC_RG_VS1_MIN_OFF = MT6351_PMIC_RG_VS1_MIN_OFF, + PMIC_RG_VS1_1P35UP_SEL_EN = MT6351_PMIC_RG_VS1_1P35UP_SEL_EN, + PMIC_RG_VS1_DLC_AUTO_MODE = MT6351_PMIC_RG_VS1_DLC_AUTO_MODE, + PMIC_RG_VS1_DLC_SEL = MT6351_PMIC_RG_VS1_DLC_SEL, + PMIC_RG_VS1_SRC_AUTO_MODE = MT6351_PMIC_RG_VS1_SRC_AUTO_MODE, + PMIC_RG_VS1_UGP_SR = MT6351_PMIC_RG_VS1_UGP_SR, + PMIC_RG_VS1_LGN_SR = MT6351_PMIC_RG_VS1_LGN_SR, + PMIC_RG_VS1_UGP_SR_PFM = MT6351_PMIC_RG_VS1_UGP_SR_PFM, + PMIC_RG_VS1_LGN_SR_PFM = MT6351_PMIC_RG_VS1_LGN_SR_PFM, + PMIC_RG_VS1_UGD_VTHSEL = MT6351_PMIC_RG_VS1_UGD_VTHSEL, + PMIC_RG_VS1_FNLX_SNS = MT6351_PMIC_RG_VS1_FNLX_SNS, + PMIC_RG_VS1_VDIFF_ENLOWIQ = MT6351_PMIC_RG_VS1_VDIFF_ENLOWIQ, + PMIC_RG_VS1_PFMOC_FWUPOFF = MT6351_PMIC_RG_VS1_PFMOC_FWUPOFF, + PMIC_RG_VS1_PWFMOC_FWUPOFF = MT6351_PMIC_RG_VS1_PWFMOC_FWUPOFF, + PMIC_RG_VS1_CP_FWUPOFF = MT6351_PMIC_RG_VS1_CP_FWUPOFF, + PMIC_RG_VS1_ZX_GATING = MT6351_PMIC_RG_VS1_ZX_GATING, + PMIC_RG_VS1_RSV = MT6351_PMIC_RG_VS1_RSV, + PMIC_RG_VS1_AZC_EN = MT6351_PMIC_RG_VS1_AZC_EN, + PMIC_RG_VS1_AZC_DELAY = MT6351_PMIC_RG_VS1_AZC_DELAY, + PMIC_RG_VS1_AZC_HOLD_ENB = MT6351_PMIC_RG_VS1_AZC_HOLD_ENB, + PMIC_RGS_QI_VS1_OC_STATUS = MT6351_PMIC_RGS_QI_VS1_OC_STATUS, + PMIC_RGS_QI_VS1_DIG_MON = MT6351_PMIC_RGS_QI_VS1_DIG_MON, + PMIC_RGS_VS1_ENPWM_STATUS = MT6351_PMIC_RGS_VS1_ENPWM_STATUS, + PMIC_RG_VS2_MODESET = MT6351_PMIC_RG_VS2_MODESET, + PMIC_RG_VS2_NDIS_EN = MT6351_PMIC_RG_VS2_NDIS_EN, + PMIC_RG_VS2_VRF18_SSTART_EN = MT6351_PMIC_RG_VS2_VRF18_SSTART_EN, + PMIC_RG_VS2_AUTO_MODE = MT6351_PMIC_RG_VS2_AUTO_MODE, + PMIC_RG_VS2_RZSEL0 = MT6351_PMIC_RG_VS2_RZSEL0, + PMIC_RG_VS2_RZSEL1 = MT6351_PMIC_RG_VS2_RZSEL1, + PMIC_RG_VS2_CCSEL0 = MT6351_PMIC_RG_VS2_CCSEL0, + PMIC_RG_VS2_CCSEL1 = MT6351_PMIC_RG_VS2_CCSEL1, + PMIC_RG_VS2_CSL = MT6351_PMIC_RG_VS2_CSL, + PMIC_RG_VS2_SLP = MT6351_PMIC_RG_VS2_SLP, + PMIC_RG_VS2_ADRC_FEN = MT6351_PMIC_RG_VS2_ADRC_FEN, + PMIC_RG_VS2_VCCAP_CLAMP_FEN = MT6351_PMIC_RG_VS2_VCCAP_CLAMP_FEN, + PMIC_RG_VS2_VC_CLAMP_FEN = MT6351_PMIC_RG_VS2_VC_CLAMP_FEN, + PMIC_RG_VS2_PFMOC = MT6351_PMIC_RG_VS2_PFMOC, + PMIC_RG_VS2_CSR = MT6351_PMIC_RG_VS2_CSR, + PMIC_RG_VS2_ZXOS_TRIM = MT6351_PMIC_RG_VS2_ZXOS_TRIM, + PMIC_RG_VS2_PFMSR_EH = MT6351_PMIC_RG_VS2_PFMSR_EH, + PMIC_RG_VS2_NLIM_GATING = MT6351_PMIC_RG_VS2_NLIM_GATING, + PMIC_RG_VS2_PWRSR_EH = MT6351_PMIC_RG_VS2_PWRSR_EH, + PMIC_RG_VS2_HS_VTHDET = MT6351_PMIC_RG_VS2_HS_VTHDET, + PMIC_RG_VS2_PG_GATING = MT6351_PMIC_RG_VS2_PG_GATING, + PMIC_RG_VS2_HS_ONSPEED_EH = MT6351_PMIC_RG_VS2_HS_ONSPEED_EH, + PMIC_RG_VS2_NLIM_TRIMMING = MT6351_PMIC_RG_VS2_NLIM_TRIMMING, + PMIC_RG_VS2_DLC = MT6351_PMIC_RG_VS2_DLC, + PMIC_RG_VS2_DLC_N = MT6351_PMIC_RG_VS2_DLC_N, + PMIC_RG_VS2_PFM_RIP = MT6351_PMIC_RG_VS2_PFM_RIP, + PMIC_RG_VS2_TRAN_BST = MT6351_PMIC_RG_VS2_TRAN_BST, + PMIC_RG_VS2_DTS_ENB = MT6351_PMIC_RG_VS2_DTS_ENB, + PMIC_RG_VS2_MIN_OFF = MT6351_PMIC_RG_VS2_MIN_OFF, + PMIC_RG_VS2_1P35UP_SEL_EN = MT6351_PMIC_RG_VS2_1P35UP_SEL_EN, + PMIC_RG_VS2_DLC_AUTO_MODE = MT6351_PMIC_RG_VS2_DLC_AUTO_MODE, + PMIC_RG_VS2_DLC_SEL = MT6351_PMIC_RG_VS2_DLC_SEL, + PMIC_RG_VS2_SRC_AUTO_MODE = MT6351_PMIC_RG_VS2_SRC_AUTO_MODE, + PMIC_RG_VS2_UGP_SR = MT6351_PMIC_RG_VS2_UGP_SR, + PMIC_RG_VS2_LGN_SR = MT6351_PMIC_RG_VS2_LGN_SR, + PMIC_RG_VS2_UGP_SR_PFM = MT6351_PMIC_RG_VS2_UGP_SR_PFM, + PMIC_RG_VS2_LGN_SR_PFM = MT6351_PMIC_RG_VS2_LGN_SR_PFM, + PMIC_RG_VS2_UGD_VTHSEL = MT6351_PMIC_RG_VS2_UGD_VTHSEL, + PMIC_RG_VS2_FNLX_SNS = MT6351_PMIC_RG_VS2_FNLX_SNS, + PMIC_RG_VS2_VDIFF_ENLOWIQ = MT6351_PMIC_RG_VS2_VDIFF_ENLOWIQ, + PMIC_RG_VS2_PFMOC_FWUPOFF = MT6351_PMIC_RG_VS2_PFMOC_FWUPOFF, + PMIC_RG_VS2_PWFMOC_FWUPOFF = MT6351_PMIC_RG_VS2_PWFMOC_FWUPOFF, + PMIC_RG_VS2_CP_FWUPOFF = MT6351_PMIC_RG_VS2_CP_FWUPOFF, + PMIC_RG_VS2_ZX_GATING = MT6351_PMIC_RG_VS2_ZX_GATING, + PMIC_RG_VS2_RSV = MT6351_PMIC_RG_VS2_RSV, + PMIC_RG_VS2_AZC_EN = MT6351_PMIC_RG_VS2_AZC_EN, + PMIC_RG_VS2_AZC_DELAY = MT6351_PMIC_RG_VS2_AZC_DELAY, + PMIC_RG_VS2_AZC_HOLD_ENB = MT6351_PMIC_RG_VS2_AZC_HOLD_ENB, + PMIC_RGS_QI_VS2_OC_STATUS = MT6351_PMIC_RGS_QI_VS2_OC_STATUS, + PMIC_RGS_QI_VS2_DIG_MON = MT6351_PMIC_RGS_QI_VS2_DIG_MON, + PMIC_RGS_VS2_ENPWM_STATUS = MT6351_PMIC_RGS_VS2_ENPWM_STATUS, + PMIC_RG_VPA_NDIS_EN = MT6351_PMIC_RG_VPA_NDIS_EN, + PMIC_RG_VPA_MODESET = MT6351_PMIC_RG_VPA_MODESET, + PMIC_RG_VPA_CC = MT6351_PMIC_RG_VPA_CC, + PMIC_RG_VPA_CSR = MT6351_PMIC_RG_VPA_CSR, + PMIC_RG_VPA_CSMIR = MT6351_PMIC_RG_VPA_CSMIR, + PMIC_RG_VPA_CSL = MT6351_PMIC_RG_VPA_CSL, + PMIC_RG_VPA_SLP = MT6351_PMIC_RG_VPA_SLP, + PMIC_RG_VPA_AZC_EN = MT6351_PMIC_RG_VPA_AZC_EN, + PMIC_RG_VPA_CP_FWUPOFF = MT6351_PMIC_RG_VPA_CP_FWUPOFF, + PMIC_RG_VPA_AZC_DELAY = MT6351_PMIC_RG_VPA_AZC_DELAY, + PMIC_RG_VPA_RZSEL = MT6351_PMIC_RG_VPA_RZSEL, + PMIC_RG_VPA_ZXREF = MT6351_PMIC_RG_VPA_ZXREF, + PMIC_RG_VPA_NLIM_SEL = MT6351_PMIC_RG_VPA_NLIM_SEL, + PMIC_RG_VPA_HZP = MT6351_PMIC_RG_VPA_HZP, + PMIC_RG_VPA_BWEX_GAT = MT6351_PMIC_RG_VPA_BWEX_GAT, + PMIC_RG_VPA_SLEW = MT6351_PMIC_RG_VPA_SLEW, + PMIC_RG_VPA_SLEW_NMOS = MT6351_PMIC_RG_VPA_SLEW_NMOS, + PMIC_RG_VPA_MIN_ON = MT6351_PMIC_RG_VPA_MIN_ON, + PMIC_RG_VPA_VBAT_DEL = MT6351_PMIC_RG_VPA_VBAT_DEL, + PMIC_RGS_VPA_AZC_VOS_SEL = MT6351_PMIC_RGS_VPA_AZC_VOS_SEL, + PMIC_RG_VPA_MIN_PK = MT6351_PMIC_RG_VPA_MIN_PK, + PMIC_RG_VPA_RSV1 = MT6351_PMIC_RG_VPA_RSV1, + PMIC_RG_VPA_RSV2 = MT6351_PMIC_RG_VPA_RSV2, + PMIC_RGS_QI_VPA_OC_STATUS = MT6351_PMIC_RGS_QI_VPA_OC_STATUS, + PMIC_BUCK_VCORE_EN_CTRL = MT6351_PMIC_BUCK_VCORE_EN_CTRL, + PMIC_BUCK_VCORE_VOSEL_CTRL = MT6351_PMIC_BUCK_VCORE_VOSEL_CTRL, + PMIC_BUCK_VCORE_EN_SEL = MT6351_PMIC_BUCK_VCORE_EN_SEL, + PMIC_BUCK_VCORE_VOSEL_SEL = MT6351_PMIC_BUCK_VCORE_VOSEL_SEL, + PMIC_BUCK_VCORE_EN = MT6351_PMIC_BUCK_VCORE_EN, + PMIC_BUCK_VCORE_STBTD = MT6351_PMIC_BUCK_VCORE_STBTD, + PMIC_DA_VCORE_STB = MT6351_PMIC_DA_VCORE_STB, + PMIC_DA_QI_VCORE_EN = MT6351_PMIC_DA_QI_VCORE_EN, + PMIC_BUCK_VCORE_SFCHG_FRATE = MT6351_PMIC_BUCK_VCORE_SFCHG_FRATE, + PMIC_BUCK_VCORE_SFCHG_FEN = MT6351_PMIC_BUCK_VCORE_SFCHG_FEN, + PMIC_BUCK_VCORE_SFCHG_RRATE = MT6351_PMIC_BUCK_VCORE_SFCHG_RRATE, + PMIC_BUCK_VCORE_SFCHG_REN = MT6351_PMIC_BUCK_VCORE_SFCHG_REN, + PMIC_BUCK_VCORE_VOSEL = MT6351_PMIC_BUCK_VCORE_VOSEL, + PMIC_BUCK_VCORE_VOSEL_ON = MT6351_PMIC_BUCK_VCORE_VOSEL_ON, + PMIC_BUCK_VCORE_VOSEL_SLEEP = MT6351_PMIC_BUCK_VCORE_VOSEL_SLEEP, + PMIC_DA_NI_VCORE_VOSEL = MT6351_PMIC_DA_NI_VCORE_VOSEL, + PMIC_DA_NI_VCORE_VOSEL_SYNC = MT6351_PMIC_DA_NI_VCORE_VOSEL_SYNC, + PMIC_BUCK_VCORE_TRANS_TD = MT6351_PMIC_BUCK_VCORE_TRANS_TD, + PMIC_BUCK_VCORE_TRANS_CTRL = MT6351_PMIC_BUCK_VCORE_TRANS_CTRL, + PMIC_BUCK_VCORE_TRANS_ONCE = MT6351_PMIC_BUCK_VCORE_TRANS_ONCE, + PMIC_DA_QI_VCORE_DVS_EN = MT6351_PMIC_DA_QI_VCORE_DVS_EN, + PMIC_BUCK_VCORE_VSLEEP_EN = MT6351_PMIC_BUCK_VCORE_VSLEEP_EN, + PMIC_BUCK_VCORE_R2R_PDN = MT6351_PMIC_BUCK_VCORE_R2R_PDN, + PMIC_BUCK_VCORE_VSLEEP_SEL = MT6351_PMIC_BUCK_VCORE_VSLEEP_SEL, + PMIC_DA_NI_VCORE_R2R_PDN = MT6351_PMIC_DA_NI_VCORE_R2R_PDN, + PMIC_DA_NI_VCORE_VSLEEP_SEL = MT6351_PMIC_DA_NI_VCORE_VSLEEP_SEL, + PMIC_BUCK_VGPU_EN_CTRL = MT6351_PMIC_BUCK_VGPU_EN_CTRL, + PMIC_BUCK_VGPU_VOSEL_CTRL = MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL, + PMIC_BUCK_VGPU_EN_SEL = MT6351_PMIC_BUCK_VGPU_EN_SEL, + PMIC_BUCK_VGPU_VOSEL_SEL = MT6351_PMIC_BUCK_VGPU_VOSEL_SEL, + PMIC_BUCK_VGPU_EN = MT6351_PMIC_BUCK_VGPU_EN, + PMIC_BUCK_VGPU_STBTD = MT6351_PMIC_BUCK_VGPU_STBTD, + PMIC_DA_VGPU_STB = MT6351_PMIC_DA_VGPU_STB, + PMIC_DA_QI_VGPU_EN = MT6351_PMIC_DA_QI_VGPU_EN, + PMIC_BUCK_VGPU_SFCHG_FRATE = MT6351_PMIC_BUCK_VGPU_SFCHG_FRATE, + PMIC_BUCK_VGPU_SFCHG_FEN = MT6351_PMIC_BUCK_VGPU_SFCHG_FEN, + PMIC_BUCK_VGPU_SFCHG_RRATE = MT6351_PMIC_BUCK_VGPU_SFCHG_RRATE, + PMIC_BUCK_VGPU_SFCHG_REN = MT6351_PMIC_BUCK_VGPU_SFCHG_REN, + PMIC_BUCK_VGPU_VOSEL = MT6351_PMIC_BUCK_VGPU_VOSEL, + PMIC_BUCK_VGPU_VOSEL_ON = MT6351_PMIC_BUCK_VGPU_VOSEL_ON, + PMIC_BUCK_VGPU_VOSEL_SLEEP = MT6351_PMIC_BUCK_VGPU_VOSEL_SLEEP, + PMIC_DA_NI_VGPU_VOSEL = MT6351_PMIC_DA_NI_VGPU_VOSEL, + PMIC_DA_NI_VGPU_VOSEL_SYNC = MT6351_PMIC_DA_NI_VGPU_VOSEL_SYNC, + PMIC_BUCK_VGPU_TRANS_TD = MT6351_PMIC_BUCK_VGPU_TRANS_TD, + PMIC_BUCK_VGPU_TRANS_CTRL = MT6351_PMIC_BUCK_VGPU_TRANS_CTRL, + PMIC_BUCK_VGPU_TRANS_ONCE = MT6351_PMIC_BUCK_VGPU_TRANS_ONCE, + PMIC_DA_QI_VGPU_DVS_EN = MT6351_PMIC_DA_QI_VGPU_DVS_EN, + PMIC_BUCK_VGPU_VSLEEP_EN = MT6351_PMIC_BUCK_VGPU_VSLEEP_EN, + PMIC_BUCK_VGPU_R2R_PDN = MT6351_PMIC_BUCK_VGPU_R2R_PDN, + PMIC_BUCK_VGPU_VSLEEP_SEL = MT6351_PMIC_BUCK_VGPU_VSLEEP_SEL, + PMIC_DA_NI_VGPU_R2R_PDN = MT6351_PMIC_DA_NI_VGPU_R2R_PDN, + PMIC_DA_NI_VGPU_VSLEEP_SEL = MT6351_PMIC_DA_NI_VGPU_VSLEEP_SEL, + PMIC_BUCK_VMODEM_EN_CTRL = MT6351_PMIC_BUCK_VMODEM_EN_CTRL, + PMIC_BUCK_VMODEM_VOSEL_CTRL = MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL, + PMIC_BUCK_VMODEM_EN_SEL = MT6351_PMIC_BUCK_VMODEM_EN_SEL, + PMIC_BUCK_VMODEM_VOSEL_SEL = MT6351_PMIC_BUCK_VMODEM_VOSEL_SEL, + PMIC_BUCK_VMODEM_EN = MT6351_PMIC_BUCK_VMODEM_EN, + PMIC_BUCK_VMODEM_STBTD = MT6351_PMIC_BUCK_VMODEM_STBTD, + PMIC_DA_VMODEM_STB = MT6351_PMIC_DA_VMODEM_STB, + PMIC_DA_QI_VMODEM_EN = MT6351_PMIC_DA_QI_VMODEM_EN, + PMIC_BUCK_VMODEM_SFCHG_FRATE = MT6351_PMIC_BUCK_VMODEM_SFCHG_FRATE, + PMIC_BUCK_VMODEM_SFCHG_FEN = MT6351_PMIC_BUCK_VMODEM_SFCHG_FEN, + PMIC_BUCK_VMODEM_SFCHG_RRATE = MT6351_PMIC_BUCK_VMODEM_SFCHG_RRATE, + PMIC_BUCK_VMODEM_SFCHG_REN = MT6351_PMIC_BUCK_VMODEM_SFCHG_REN, + PMIC_BUCK_VMODEM_VOSEL = MT6351_PMIC_BUCK_VMODEM_VOSEL, + PMIC_BUCK_VMODEM_VOSEL_ON = MT6351_PMIC_BUCK_VMODEM_VOSEL_ON, + PMIC_BUCK_VMODEM_VOSEL_SLEEP = MT6351_PMIC_BUCK_VMODEM_VOSEL_SLEEP, + PMIC_DA_NI_VMODEM_VOSEL = MT6351_PMIC_DA_NI_VMODEM_VOSEL, + PMIC_DA_NI_VMODEM_VOSEL_SYNC = MT6351_PMIC_DA_NI_VMODEM_VOSEL_SYNC, + PMIC_BUCK_VMODEM_TRANS_TD = MT6351_PMIC_BUCK_VMODEM_TRANS_TD, + PMIC_BUCK_VMODEM_TRANS_CTRL = MT6351_PMIC_BUCK_VMODEM_TRANS_CTRL, + PMIC_BUCK_VMODEM_TRANS_ONCE = MT6351_PMIC_BUCK_VMODEM_TRANS_ONCE, + PMIC_DA_QI_VMODEM_DVS_EN = MT6351_PMIC_DA_QI_VMODEM_DVS_EN, + PMIC_BUCK_VMODEM_VSLEEP_EN = MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN, + PMIC_BUCK_VMODEM_R2R_PDN = MT6351_PMIC_BUCK_VMODEM_R2R_PDN, + PMIC_BUCK_VMODEM_VSLEEP_SEL = MT6351_PMIC_BUCK_VMODEM_VSLEEP_SEL, + PMIC_DA_NI_VMODEM_R2R_PDN = MT6351_PMIC_DA_NI_VMODEM_R2R_PDN, + PMIC_DA_NI_VMODEM_VSLEEP_SEL = MT6351_PMIC_DA_NI_VMODEM_VSLEEP_SEL, + PMIC_BUCK_VMD1_EN_CTRL = MT6351_PMIC_BUCK_VMD1_EN_CTRL, + PMIC_BUCK_VMD1_VOSEL_CTRL = MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL, + PMIC_BUCK_VMD1_EN_SEL = MT6351_PMIC_BUCK_VMD1_EN_SEL, + PMIC_BUCK_VMD1_VOSEL_SEL = MT6351_PMIC_BUCK_VMD1_VOSEL_SEL, + PMIC_BUCK_VMD1_EN = MT6351_PMIC_BUCK_VMD1_EN, + PMIC_BUCK_VMD1_STBTD = MT6351_PMIC_BUCK_VMD1_STBTD, + PMIC_DA_VMD1_STB = MT6351_PMIC_DA_VMD1_STB, + PMIC_DA_QI_VMD1_EN = MT6351_PMIC_DA_QI_VMD1_EN, + PMIC_BUCK_VMD1_SFCHG_FRATE = MT6351_PMIC_BUCK_VMD1_SFCHG_FRATE, + PMIC_BUCK_VMD1_SFCHG_FEN = MT6351_PMIC_BUCK_VMD1_SFCHG_FEN, + PMIC_BUCK_VMD1_SFCHG_RRATE = MT6351_PMIC_BUCK_VMD1_SFCHG_RRATE, + PMIC_BUCK_VMD1_SFCHG_REN = MT6351_PMIC_BUCK_VMD1_SFCHG_REN, + PMIC_BUCK_VMD1_VOSEL = MT6351_PMIC_BUCK_VMD1_VOSEL, + PMIC_BUCK_VMD1_VOSEL_ON = MT6351_PMIC_BUCK_VMD1_VOSEL_ON, + PMIC_BUCK_VMD1_VOSEL_SLEEP = MT6351_PMIC_BUCK_VMD1_VOSEL_SLEEP, + PMIC_DA_NI_VMD1_VOSEL = MT6351_PMIC_DA_NI_VMD1_VOSEL, + PMIC_DA_NI_VMD1_VOSEL_SYNC = MT6351_PMIC_DA_NI_VMD1_VOSEL_SYNC, + PMIC_BUCK_VMD1_TRANS_TD = MT6351_PMIC_BUCK_VMD1_TRANS_TD, + PMIC_BUCK_VMD1_TRANS_CTRL = MT6351_PMIC_BUCK_VMD1_TRANS_CTRL, + PMIC_BUCK_VMD1_TRANS_ONCE = MT6351_PMIC_BUCK_VMD1_TRANS_ONCE, + PMIC_DA_QI_VMD1_DVS_EN = MT6351_PMIC_DA_QI_VMD1_DVS_EN, + PMIC_BUCK_VMD1_VSLEEP_EN = MT6351_PMIC_BUCK_VMD1_VSLEEP_EN, + PMIC_BUCK_VMD1_R2R_PDN = MT6351_PMIC_BUCK_VMD1_R2R_PDN, + PMIC_BUCK_VMD1_VSLEEP_SEL = MT6351_PMIC_BUCK_VMD1_VSLEEP_SEL, + PMIC_DA_NI_VMD1_R2R_PDN = MT6351_PMIC_DA_NI_VMD1_R2R_PDN, + PMIC_DA_NI_VMD1_VSLEEP_SEL = MT6351_PMIC_DA_NI_VMD1_VSLEEP_SEL, + PMIC_BUCK_VSRAM_MD_EN_CTRL = MT6351_PMIC_BUCK_VSRAM_MD_EN_CTRL, + PMIC_BUCK_VSRAM_MD_VOSEL_CTRL = MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL, + PMIC_BUCK_VSRAM_MD_EN_SEL = MT6351_PMIC_BUCK_VSRAM_MD_EN_SEL, + PMIC_BUCK_VSRAM_MD_VOSEL_SEL = MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SEL, + PMIC_BUCK_VSRAM_MD_EN = MT6351_PMIC_BUCK_VSRAM_MD_EN, + PMIC_BUCK_VSRAM_MD_STBTD = MT6351_PMIC_BUCK_VSRAM_MD_STBTD, + PMIC_DA_VSRAM_MD_STB = MT6351_PMIC_DA_VSRAM_MD_STB, + PMIC_DA_QI_VSRAM_MD_EN = MT6351_PMIC_DA_QI_VSRAM_MD_EN, + PMIC_BUCK_VSRAM_MD_SFCHG_FRATE = MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FRATE, + PMIC_BUCK_VSRAM_MD_SFCHG_FEN = MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FEN, + PMIC_BUCK_VSRAM_MD_SFCHG_RRATE = MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_RRATE, + PMIC_BUCK_VSRAM_MD_SFCHG_REN = MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_REN, + PMIC_BUCK_VSRAM_MD_VOSEL = MT6351_PMIC_BUCK_VSRAM_MD_VOSEL, + PMIC_BUCK_VSRAM_MD_VOSEL_ON = MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON, + PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP = MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP, + PMIC_DA_NI_VSRAM_MD_VOSEL = MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL, + PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC = MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC, + PMIC_BUCK_VSRAM_MD_TRANS_TD = MT6351_PMIC_BUCK_VSRAM_MD_TRANS_TD, + PMIC_BUCK_VSRAM_MD_TRANS_CTRL = MT6351_PMIC_BUCK_VSRAM_MD_TRANS_CTRL, + PMIC_BUCK_VSRAM_MD_TRANS_ONCE = MT6351_PMIC_BUCK_VSRAM_MD_TRANS_ONCE, + PMIC_DA_QI_VSRAM_MD_DVS_EN = MT6351_PMIC_DA_QI_VSRAM_MD_DVS_EN, + PMIC_BUCK_VSRAM_MD_VSLEEP_EN = MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN, + PMIC_BUCK_VSRAM_MD_R2R_PDN = MT6351_PMIC_BUCK_VSRAM_MD_R2R_PDN, + PMIC_BUCK_VSRAM_MD_VSLEEP_SEL = MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_SEL, + PMIC_DA_NI_VSRAM_MD_R2R_PDN = MT6351_PMIC_DA_NI_VSRAM_MD_R2R_PDN, + PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL = MT6351_PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL, + PMIC_BUCK_VS1_EN_CTRL = MT6351_PMIC_BUCK_VS1_EN_CTRL, + PMIC_BUCK_VS1_VOSEL_CTRL = MT6351_PMIC_BUCK_VS1_VOSEL_CTRL, + PMIC_BUCK_VS1_EN_SEL = MT6351_PMIC_BUCK_VS1_EN_SEL, + PMIC_BUCK_VS1_VOSEL_SEL = MT6351_PMIC_BUCK_VS1_VOSEL_SEL, + PMIC_BUCK_VS1_EN = MT6351_PMIC_BUCK_VS1_EN, + PMIC_BUCK_VS1_STBTD = MT6351_PMIC_BUCK_VS1_STBTD, + PMIC_DA_VS1_STB = MT6351_PMIC_DA_VS1_STB, + PMIC_DA_QI_VS1_EN = MT6351_PMIC_DA_QI_VS1_EN, + PMIC_BUCK_VS1_SFCHG_FRATE = MT6351_PMIC_BUCK_VS1_SFCHG_FRATE, + PMIC_BUCK_VS1_SFCHG_FEN = MT6351_PMIC_BUCK_VS1_SFCHG_FEN, + PMIC_BUCK_VS1_SFCHG_RRATE = MT6351_PMIC_BUCK_VS1_SFCHG_RRATE, + PMIC_BUCK_VS1_SFCHG_REN = MT6351_PMIC_BUCK_VS1_SFCHG_REN, + PMIC_BUCK_VS1_VOSEL = MT6351_PMIC_BUCK_VS1_VOSEL, + PMIC_BUCK_VS1_VOSEL_ON = MT6351_PMIC_BUCK_VS1_VOSEL_ON, + PMIC_BUCK_VS1_VOSEL_SLEEP = MT6351_PMIC_BUCK_VS1_VOSEL_SLEEP, + PMIC_DA_NI_VS1_VOSEL = MT6351_PMIC_DA_NI_VS1_VOSEL, + PMIC_DA_NI_VS1_VOSEL_SYNC = MT6351_PMIC_DA_NI_VS1_VOSEL_SYNC, + PMIC_BUCK_VS1_TRANS_TD = MT6351_PMIC_BUCK_VS1_TRANS_TD, + PMIC_BUCK_VS1_TRANS_CTRL = MT6351_PMIC_BUCK_VS1_TRANS_CTRL, + PMIC_BUCK_VS1_TRANS_ONCE = MT6351_PMIC_BUCK_VS1_TRANS_ONCE, + PMIC_DA_QI_VS1_DVS_EN = MT6351_PMIC_DA_QI_VS1_DVS_EN, + PMIC_BUCK_VS1_VSLEEP_EN = MT6351_PMIC_BUCK_VS1_VSLEEP_EN, + PMIC_BUCK_VS1_R2R_PDN = MT6351_PMIC_BUCK_VS1_R2R_PDN, + PMIC_BUCK_VS1_VSLEEP_SEL = MT6351_PMIC_BUCK_VS1_VSLEEP_SEL, + PMIC_DA_NI_VS1_R2R_PDN = MT6351_PMIC_DA_NI_VS1_R2R_PDN, + PMIC_DA_NI_VS1_VSLEEP_SEL = MT6351_PMIC_DA_NI_VS1_VSLEEP_SEL, + PMIC_BUCK_VS2_EN_CTRL = MT6351_PMIC_BUCK_VS2_EN_CTRL, + PMIC_BUCK_VS2_VOSEL_CTRL = MT6351_PMIC_BUCK_VS2_VOSEL_CTRL, + PMIC_BUCK_VS2_EN_SEL = MT6351_PMIC_BUCK_VS2_EN_SEL, + PMIC_BUCK_VS2_VOSEL_SEL = MT6351_PMIC_BUCK_VS2_VOSEL_SEL, + PMIC_BUCK_VS2_EN = MT6351_PMIC_BUCK_VS2_EN, + PMIC_BUCK_VS2_STBTD = MT6351_PMIC_BUCK_VS2_STBTD, + PMIC_DA_VS2_STB = MT6351_PMIC_DA_VS2_STB, + PMIC_DA_QI_VS2_EN = MT6351_PMIC_DA_QI_VS2_EN, + PMIC_BUCK_VS2_SFCHG_FRATE = MT6351_PMIC_BUCK_VS2_SFCHG_FRATE, + PMIC_BUCK_VS2_SFCHG_FEN = MT6351_PMIC_BUCK_VS2_SFCHG_FEN, + PMIC_BUCK_VS2_SFCHG_RRATE = MT6351_PMIC_BUCK_VS2_SFCHG_RRATE, + PMIC_BUCK_VS2_SFCHG_REN = MT6351_PMIC_BUCK_VS2_SFCHG_REN, + PMIC_BUCK_VS2_VOSEL = MT6351_PMIC_BUCK_VS2_VOSEL, + PMIC_BUCK_VS2_VOSEL_ON = MT6351_PMIC_BUCK_VS2_VOSEL_ON, + PMIC_BUCK_VS2_VOSEL_SLEEP = MT6351_PMIC_BUCK_VS2_VOSEL_SLEEP, + PMIC_DA_NI_VS2_VOSEL = MT6351_PMIC_DA_NI_VS2_VOSEL, + PMIC_DA_NI_VS2_VOSEL_SYNC = MT6351_PMIC_DA_NI_VS2_VOSEL_SYNC, + PMIC_BUCK_VS2_TRANS_TD = MT6351_PMIC_BUCK_VS2_TRANS_TD, + PMIC_BUCK_VS2_TRANS_CTRL = MT6351_PMIC_BUCK_VS2_TRANS_CTRL, + PMIC_BUCK_VS2_TRANS_ONCE = MT6351_PMIC_BUCK_VS2_TRANS_ONCE, + PMIC_DA_QI_VS2_DVS_EN = MT6351_PMIC_DA_QI_VS2_DVS_EN, + PMIC_BUCK_VS2_VSLEEP_EN = MT6351_PMIC_BUCK_VS2_VSLEEP_EN, + PMIC_BUCK_VS2_R2R_PDN = MT6351_PMIC_BUCK_VS2_R2R_PDN, + PMIC_BUCK_VS2_VSLEEP_SEL = MT6351_PMIC_BUCK_VS2_VSLEEP_SEL, + PMIC_DA_NI_VS2_R2R_PDN = MT6351_PMIC_DA_NI_VS2_R2R_PDN, + PMIC_DA_NI_VS2_VSLEEP_SEL = MT6351_PMIC_DA_NI_VS2_VSLEEP_SEL, + PMIC_BUCK_VPA_EN_CTRL = MT6351_PMIC_BUCK_VPA_EN_CTRL, + PMIC_BUCK_VPA_VOSEL_CTRL = MT6351_PMIC_BUCK_VPA_VOSEL_CTRL, + PMIC_BUCK_VPA_EN_SEL = MT6351_PMIC_BUCK_VPA_EN_SEL, + PMIC_BUCK_VPA_VOSEL_SEL = MT6351_PMIC_BUCK_VPA_VOSEL_SEL, + PMIC_BUCK_VPA_EN = MT6351_PMIC_BUCK_VPA_EN, + PMIC_BUCK_VPA_STBTD = MT6351_PMIC_BUCK_VPA_STBTD, + PMIC_DA_VPA_STB = MT6351_PMIC_DA_VPA_STB, + PMIC_DA_QI_VPA_EN = MT6351_PMIC_DA_QI_VPA_EN, + PMIC_BUCK_VPA_SFCHG_FRATE = MT6351_PMIC_BUCK_VPA_SFCHG_FRATE, + PMIC_BUCK_VPA_SFCHG_FEN = MT6351_PMIC_BUCK_VPA_SFCHG_FEN, + PMIC_BUCK_VPA_SFCHG_RRATE = MT6351_PMIC_BUCK_VPA_SFCHG_RRATE, + PMIC_BUCK_VPA_SFCHG_REN = MT6351_PMIC_BUCK_VPA_SFCHG_REN, + PMIC_BUCK_VPA_VOSEL = MT6351_PMIC_BUCK_VPA_VOSEL, + PMIC_BUCK_VPA_VOSEL_ON = MT6351_PMIC_BUCK_VPA_VOSEL_ON, + PMIC_BUCK_VPA_VOSEL_SLEEP = MT6351_PMIC_BUCK_VPA_VOSEL_SLEEP, + PMIC_DA_NI_VPA_VOSEL_GRAY = MT6351_PMIC_DA_NI_VPA_VOSEL_GRAY, + PMIC_DA_NI_VPA_VOSEL_SYNC = MT6351_PMIC_DA_NI_VPA_VOSEL_SYNC, + PMIC_BUCK_VPA_TRANS_TD = MT6351_PMIC_BUCK_VPA_TRANS_TD, + PMIC_BUCK_VPA_TRANS_CTRL = MT6351_PMIC_BUCK_VPA_TRANS_CTRL, + PMIC_BUCK_VPA_TRANS_ONCE = MT6351_PMIC_BUCK_VPA_TRANS_ONCE, + PMIC_DA_QI_VPA_DVS_EN = MT6351_PMIC_DA_QI_VPA_DVS_EN, + PMIC_BUCK_VPA_VSLEEP_EN = MT6351_PMIC_BUCK_VPA_VSLEEP_EN, + PMIC_BUCK_VPA_R2R_PDN = MT6351_PMIC_BUCK_VPA_R2R_PDN, + PMIC_BUCK_VPA_VSLEEP_SEL = MT6351_PMIC_BUCK_VPA_VSLEEP_SEL, + PMIC_DA_NI_VPA_R2R_PDN = MT6351_PMIC_DA_NI_VPA_R2R_PDN, + PMIC_DA_NI_VPA_VSLEEP_SEL = MT6351_PMIC_DA_NI_VPA_VSLEEP_SEL, + PMIC_BUCK_VSRAM_PROC_EN_CTRL = MT6351_PMIC_BUCK_VSRAM_PROC_EN_CTRL, + PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL = MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL, + PMIC_BUCK_VSRAM_PROC_EN_SEL = MT6351_PMIC_BUCK_VSRAM_PROC_EN_SEL, + PMIC_BUCK_VSRAM_PROC_VOSEL_SEL = MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SEL, + PMIC_BUCK_VSRAM_PROC_EN = MT6351_PMIC_BUCK_VSRAM_PROC_EN, + PMIC_BUCK_VSRAM_PROC_STBTD = MT6351_PMIC_BUCK_VSRAM_PROC_STBTD, + PMIC_DA_VSRAM_PROC_STB = MT6351_PMIC_DA_VSRAM_PROC_STB, + PMIC_DA_QI_VSRAM_PROC_EN_RSV = MT6351_PMIC_DA_QI_VSRAM_PROC_EN_RSV, + PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE = MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE, + PMIC_BUCK_VSRAM_PROC_SFCHG_FEN = MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FEN, + PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE = MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE, + PMIC_BUCK_VSRAM_PROC_SFCHG_REN = MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_REN, + PMIC_BUCK_VSRAM_PROC_VOSEL = MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL, + PMIC_BUCK_VSRAM_PROC_VOSEL_ON = MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON, + PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP = MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP, + PMIC_DA_NI_VSRAM_PROC_VOSEL = MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL, + PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC = MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC, + PMIC_BUCK_VSRAM_PROC_TRANS_TD = MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_TD, + PMIC_BUCK_VSRAM_PROC_TRANS_CTRL = MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_CTRL, + PMIC_BUCK_VSRAM_PROC_TRANS_ONCE = MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_ONCE, + PMIC_DA_QI_VSRAM_PROC_DVS_EN = MT6351_PMIC_DA_QI_VSRAM_PROC_DVS_EN, + PMIC_BUCK_VSRAM_PROC_VSLEEP_EN = MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN, + PMIC_BUCK_VSRAM_PROC_R2R_PDN = MT6351_PMIC_BUCK_VSRAM_PROC_R2R_PDN, + PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL = MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL, + PMIC_DA_NI_VSRAM_PROC_R2R_PDN = MT6351_PMIC_DA_NI_VSRAM_PROC_R2R_PDN, + PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL = MT6351_PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL, + PMIC_BUCK_K_RST_DONE = MT6351_PMIC_BUCK_K_RST_DONE, + PMIC_BUCK_K_MAP_SEL = MT6351_PMIC_BUCK_K_MAP_SEL, + PMIC_BUCK_K_ONCE_EN = MT6351_PMIC_BUCK_K_ONCE_EN, + PMIC_BUCK_K_ONCE = MT6351_PMIC_BUCK_K_ONCE, + PMIC_BUCK_K_START_MANUAL = MT6351_PMIC_BUCK_K_START_MANUAL, + PMIC_BUCK_K_SRC_SEL = MT6351_PMIC_BUCK_K_SRC_SEL, + PMIC_BUCK_K_AUTO_EN = MT6351_PMIC_BUCK_K_AUTO_EN, + PMIC_BUCK_K_INV = MT6351_PMIC_BUCK_K_INV, + PMIC_BUCK_K_CONTROL_SMPS = MT6351_PMIC_BUCK_K_CONTROL_SMPS, + PMIC_K_RESULT = MT6351_PMIC_K_RESULT, + PMIC_K_DONE = MT6351_PMIC_K_DONE, + PMIC_K_CONTROL = MT6351_PMIC_K_CONTROL, + PMIC_DA_QI_SMPS_OSC_CAL = MT6351_PMIC_DA_QI_SMPS_OSC_CAL, + PMIC_BUCK_K_BUCK_CK_CNT = MT6351_PMIC_BUCK_K_BUCK_CK_CNT, + PMIC_WDTDBG_CLR = MT6351_PMIC_WDTDBG_CLR, + PMIC_WDTDBG_CON0_RSV0 = MT6351_PMIC_WDTDBG_CON0_RSV0, + PMIC_VGPU_VOSEL_WDTDBG = MT6351_PMIC_VGPU_VOSEL_WDTDBG, + PMIC_VCORE_VOSEL_WDTDBG = MT6351_PMIC_VCORE_VOSEL_WDTDBG, + PMIC_VMD1_VOSEL_WDTDBG = MT6351_PMIC_VMD1_VOSEL_WDTDBG, + PMIC_VMODEM_VOSEL_WDTDBG = MT6351_PMIC_VMODEM_VOSEL_WDTDBG, + PMIC_VSRAM_PROC_VOSEL_WDTDBG = MT6351_PMIC_VSRAM_PROC_VOSEL_WDTDBG, + PMIC_VSRAM_MD_VOSEL_WDTDBG = MT6351_PMIC_VSRAM_MD_VOSEL_WDTDBG, + PMIC_RG_AUDZCDENABLE = MT6351_PMIC_RG_AUDZCDENABLE, + PMIC_RG_AUDZCDGAINSTEPTIME = MT6351_PMIC_RG_AUDZCDGAINSTEPTIME, + PMIC_RG_AUDZCDGAINSTEPSIZE = MT6351_PMIC_RG_AUDZCDGAINSTEPSIZE, + PMIC_RG_AUDZCDTIMEOUTMODESEL = MT6351_PMIC_RG_AUDZCDTIMEOUTMODESEL, + PMIC_RG_AUDZCDCLKSEL_VAUDP15 = MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP15, + PMIC_RG_AUDZCDMUXSEL_VAUDP15 = MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP15, + PMIC_RG_AUDLOLGAIN = MT6351_PMIC_RG_AUDLOLGAIN, + PMIC_RG_AUDLORGAIN = MT6351_PMIC_RG_AUDLORGAIN, + PMIC_RG_AUDHPLGAIN = MT6351_PMIC_RG_AUDHPLGAIN, + PMIC_RG_AUDHPRGAIN = MT6351_PMIC_RG_AUDHPRGAIN, + PMIC_RG_AUDHSGAIN = MT6351_PMIC_RG_AUDHSGAIN, + PMIC_RG_AUDIVLGAIN = MT6351_PMIC_RG_AUDIVLGAIN, + PMIC_RG_AUDIVRGAIN = MT6351_PMIC_RG_AUDIVRGAIN, + PMIC_RG_AUDINTGAIN1 = MT6351_PMIC_RG_AUDINTGAIN1, + PMIC_RG_AUDINTGAIN2 = MT6351_PMIC_RG_AUDINTGAIN2, + PMIC_RG_A_TRIM_EN = MT6351_PMIC_RG_A_TRIM_EN, + PMIC_RG_A_TRIM_SEL = MT6351_PMIC_RG_A_TRIM_SEL, + PMIC_RG_A_ISINKS_RSV = MT6351_PMIC_RG_A_ISINKS_RSV, + PMIC_RG_B_TRIM_EN = MT6351_PMIC_RG_B_TRIM_EN, + PMIC_RG_B_TRIM_SEL = MT6351_PMIC_RG_B_TRIM_SEL, + PMIC_RG_B_ISINKS_RSV = MT6351_PMIC_RG_B_ISINKS_RSV, + PMIC_ISINK_DIM0_FSEL = MT6351_PMIC_ISINK_DIM0_FSEL, + PMIC_ISINK0_RSV1 = MT6351_PMIC_ISINK0_RSV1, + PMIC_ISINK0_RSV0 = MT6351_PMIC_ISINK0_RSV0, + PMIC_ISINK_DIM0_DUTY = MT6351_PMIC_ISINK_DIM0_DUTY, + PMIC_ISINK_CH0_STEP = MT6351_PMIC_ISINK_CH0_STEP, + PMIC_ISINK_BREATH0_TF2_SEL = MT6351_PMIC_ISINK_BREATH0_TF2_SEL, + PMIC_ISINK_BREATH0_TF1_SEL = MT6351_PMIC_ISINK_BREATH0_TF1_SEL, + PMIC_ISINK_BREATH0_TR2_SEL = MT6351_PMIC_ISINK_BREATH0_TR2_SEL, + PMIC_ISINK_BREATH0_TR1_SEL = MT6351_PMIC_ISINK_BREATH0_TR1_SEL, + PMIC_ISINK_BREATH0_TOFF_SEL = MT6351_PMIC_ISINK_BREATH0_TOFF_SEL, + PMIC_ISINK_BREATH0_TON_SEL = MT6351_PMIC_ISINK_BREATH0_TON_SEL, + PMIC_ISINK_DIM1_FSEL = MT6351_PMIC_ISINK_DIM1_FSEL, + PMIC_ISINK1_RSV1 = MT6351_PMIC_ISINK1_RSV1, + PMIC_ISINK1_RSV0 = MT6351_PMIC_ISINK1_RSV0, + PMIC_ISINK_DIM1_DUTY = MT6351_PMIC_ISINK_DIM1_DUTY, + PMIC_ISINK_CH1_STEP = MT6351_PMIC_ISINK_CH1_STEP, + PMIC_ISINK_BREATH1_TF2_SEL = MT6351_PMIC_ISINK_BREATH1_TF2_SEL, + PMIC_ISINK_BREATH1_TF1_SEL = MT6351_PMIC_ISINK_BREATH1_TF1_SEL, + PMIC_ISINK_BREATH1_TR2_SEL = MT6351_PMIC_ISINK_BREATH1_TR2_SEL, + PMIC_ISINK_BREATH1_TR1_SEL = MT6351_PMIC_ISINK_BREATH1_TR1_SEL, + PMIC_ISINK_BREATH1_TOFF_SEL = MT6351_PMIC_ISINK_BREATH1_TOFF_SEL, + PMIC_ISINK_BREATH1_TON_SEL = MT6351_PMIC_ISINK_BREATH1_TON_SEL, + PMIC_ISINK_DIM4_FSEL = MT6351_PMIC_ISINK_DIM4_FSEL, + PMIC_ISINK4_RSV1 = MT6351_PMIC_ISINK4_RSV1, + PMIC_ISINK4_RSV0 = MT6351_PMIC_ISINK4_RSV0, + PMIC_ISINK_DIM4_DUTY = MT6351_PMIC_ISINK_DIM4_DUTY, + PMIC_ISINK_CH4_STEP = MT6351_PMIC_ISINK_CH4_STEP, + PMIC_ISINK_BREATH4_TF2_SEL = MT6351_PMIC_ISINK_BREATH4_TF2_SEL, + PMIC_ISINK_BREATH4_TF1_SEL = MT6351_PMIC_ISINK_BREATH4_TF1_SEL, + PMIC_ISINK_BREATH4_TR2_SEL = MT6351_PMIC_ISINK_BREATH4_TR2_SEL, + PMIC_ISINK_BREATH4_TR1_SEL = MT6351_PMIC_ISINK_BREATH4_TR1_SEL, + PMIC_ISINK_BREATH4_TOFF_SEL = MT6351_PMIC_ISINK_BREATH4_TOFF_SEL, + PMIC_ISINK_BREATH4_TON_SEL = MT6351_PMIC_ISINK_BREATH4_TON_SEL, + PMIC_ISINK_DIM5_FSEL = MT6351_PMIC_ISINK_DIM5_FSEL, + PMIC_ISINK5_RSV1 = MT6351_PMIC_ISINK5_RSV1, + PMIC_ISINK5_RSV0 = MT6351_PMIC_ISINK5_RSV0, + PMIC_ISINK_DIM5_DUTY = MT6351_PMIC_ISINK_DIM5_DUTY, + PMIC_ISINK_CH5_STEP = MT6351_PMIC_ISINK_CH5_STEP, + PMIC_ISINK_BREATH5_TF2_SEL = MT6351_PMIC_ISINK_BREATH5_TF2_SEL, + PMIC_ISINK_BREATH5_TF1_SEL = MT6351_PMIC_ISINK_BREATH5_TF1_SEL, + PMIC_ISINK_BREATH5_TR2_SEL = MT6351_PMIC_ISINK_BREATH5_TR2_SEL, + PMIC_ISINK_BREATH5_TR1_SEL = MT6351_PMIC_ISINK_BREATH5_TR1_SEL, + PMIC_ISINK_BREATH5_TOFF_SEL = MT6351_PMIC_ISINK_BREATH5_TOFF_SEL, + PMIC_ISINK_BREATH5_TON_SEL = MT6351_PMIC_ISINK_BREATH5_TON_SEL, + PMIC_AD_NI_B_ISINK1_STATUS = MT6351_PMIC_AD_NI_B_ISINK1_STATUS, + PMIC_AD_NI_B_ISINK0_STATUS = MT6351_PMIC_AD_NI_B_ISINK0_STATUS, + PMIC_AD_NI_A_ISINK1_STATUS = MT6351_PMIC_AD_NI_A_ISINK1_STATUS, + PMIC_AD_NI_A_ISINK0_STATUS = MT6351_PMIC_AD_NI_A_ISINK0_STATUS, + PMIC_ISINK_PHASE0_DLY_EN = MT6351_PMIC_ISINK_PHASE0_DLY_EN, + PMIC_ISINK_PHASE1_DLY_EN = MT6351_PMIC_ISINK_PHASE1_DLY_EN, + PMIC_ISINK_PHASE4_DLY_EN = MT6351_PMIC_ISINK_PHASE4_DLY_EN, + PMIC_ISINK_PHASE5_DLY_EN = MT6351_PMIC_ISINK_PHASE5_DLY_EN, + PMIC_ISINK_PHASE_DLY_TC = MT6351_PMIC_ISINK_PHASE_DLY_TC, + PMIC_ISINK_CHOP0_SW = MT6351_PMIC_ISINK_CHOP0_SW, + PMIC_ISINK_CHOP1_SW = MT6351_PMIC_ISINK_CHOP1_SW, + PMIC_ISINK_CHOP4_SW = MT6351_PMIC_ISINK_CHOP4_SW, + PMIC_ISINK_CHOP5_SW = MT6351_PMIC_ISINK_CHOP5_SW, + PMIC_ISINK_SFSTR5_EN = MT6351_PMIC_ISINK_SFSTR5_EN, + PMIC_ISINK_SFSTR5_TC = MT6351_PMIC_ISINK_SFSTR5_TC, + PMIC_ISINK_SFSTR4_EN = MT6351_PMIC_ISINK_SFSTR4_EN, + PMIC_ISINK_SFSTR4_TC = MT6351_PMIC_ISINK_SFSTR4_TC, + PMIC_ISINK_SFSTR1_EN = MT6351_PMIC_ISINK_SFSTR1_EN, + PMIC_ISINK_SFSTR1_TC = MT6351_PMIC_ISINK_SFSTR1_TC, + PMIC_ISINK_SFSTR0_EN = MT6351_PMIC_ISINK_SFSTR0_EN, + PMIC_ISINK_SFSTR0_TC = MT6351_PMIC_ISINK_SFSTR0_TC, + PMIC_ISINK_CH0_EN = MT6351_PMIC_ISINK_CH0_EN, + PMIC_ISINK_CH1_EN = MT6351_PMIC_ISINK_CH1_EN, + PMIC_ISINK_CH4_EN = MT6351_PMIC_ISINK_CH4_EN, + PMIC_ISINK_CH5_EN = MT6351_PMIC_ISINK_CH5_EN, + PMIC_ISINK_CHOP0_EN = MT6351_PMIC_ISINK_CHOP0_EN, + PMIC_ISINK_CHOP1_EN = MT6351_PMIC_ISINK_CHOP1_EN, + PMIC_ISINK_CHOP4_EN = MT6351_PMIC_ISINK_CHOP4_EN, + PMIC_ISINK_CHOP5_EN = MT6351_PMIC_ISINK_CHOP5_EN, + PMIC_ISINK_CH0_BIAS_EN = MT6351_PMIC_ISINK_CH0_BIAS_EN, + PMIC_ISINK_CH1_BIAS_EN = MT6351_PMIC_ISINK_CH1_BIAS_EN, + PMIC_ISINK_CH4_BIAS_EN = MT6351_PMIC_ISINK_CH4_BIAS_EN, + PMIC_ISINK_CH5_BIAS_EN = MT6351_PMIC_ISINK_CH5_BIAS_EN, + PMIC_ISINK_RSV = MT6351_PMIC_ISINK_RSV, + PMIC_ISINK_CH5_MODE = MT6351_PMIC_ISINK_CH5_MODE, + PMIC_ISINK_CH4_MODE = MT6351_PMIC_ISINK_CH4_MODE, + PMIC_ISINK_CH1_MODE = MT6351_PMIC_ISINK_CH1_MODE, + PMIC_ISINK_CH0_MODE = MT6351_PMIC_ISINK_CH0_MODE, + PMIC_DA_QI_A_ISINKS_CH0_STEP = MT6351_PMIC_DA_QI_A_ISINKS_CH0_STEP, + PMIC_DA_QI_A_ISINKS_CH1_STEP = MT6351_PMIC_DA_QI_A_ISINKS_CH1_STEP, + PMIC_DA_QI_B_ISINKS_CH0_STEP = MT6351_PMIC_DA_QI_B_ISINKS_CH0_STEP, + PMIC_DA_QI_B_ISINKS_CH1_STEP = MT6351_PMIC_DA_QI_B_ISINKS_CH1_STEP, + PMIC_ISINK2_RSV1 = MT6351_PMIC_ISINK2_RSV1, + PMIC_ISINK2_RSV0 = MT6351_PMIC_ISINK2_RSV0, + PMIC_ISINK_CH2_STEP = MT6351_PMIC_ISINK_CH2_STEP, + PMIC_ISINK3_RSV1 = MT6351_PMIC_ISINK3_RSV1, + PMIC_ISINK3_RSV0 = MT6351_PMIC_ISINK3_RSV0, + PMIC_ISINK_CH3_STEP = MT6351_PMIC_ISINK_CH3_STEP, + PMIC_ISINK6_RSV1 = MT6351_PMIC_ISINK6_RSV1, + PMIC_ISINK6_RSV0 = MT6351_PMIC_ISINK6_RSV0, + PMIC_ISINK_CH6_STEP = MT6351_PMIC_ISINK_CH6_STEP, + PMIC_ISINK7_RSV1 = MT6351_PMIC_ISINK7_RSV1, + PMIC_ISINK7_RSV0 = MT6351_PMIC_ISINK7_RSV0, + PMIC_ISINK_CH7_STEP = MT6351_PMIC_ISINK_CH7_STEP, + PMIC_AD_NI_B_ISINK3_STATUS = MT6351_PMIC_AD_NI_B_ISINK3_STATUS, + PMIC_AD_NI_B_ISINK2_STATUS = MT6351_PMIC_AD_NI_B_ISINK2_STATUS, + PMIC_AD_NI_A_ISINK3_STATUS = MT6351_PMIC_AD_NI_A_ISINK3_STATUS, + PMIC_AD_NI_A_ISINK2_STATUS = MT6351_PMIC_AD_NI_A_ISINK2_STATUS, + PMIC_ISINK_CHOP7_SW = MT6351_PMIC_ISINK_CHOP7_SW, + PMIC_ISINK_CHOP6_SW = MT6351_PMIC_ISINK_CHOP6_SW, + PMIC_ISINK_CHOP3_SW = MT6351_PMIC_ISINK_CHOP3_SW, + PMIC_ISINK_CHOP2_SW = MT6351_PMIC_ISINK_CHOP2_SW, + PMIC_ISINK_CH7_EN = MT6351_PMIC_ISINK_CH7_EN, + PMIC_ISINK_CH6_EN = MT6351_PMIC_ISINK_CH6_EN, + PMIC_ISINK_CH3_EN = MT6351_PMIC_ISINK_CH3_EN, + PMIC_ISINK_CH2_EN = MT6351_PMIC_ISINK_CH2_EN, + PMIC_ISINK_CHOP7_EN = MT6351_PMIC_ISINK_CHOP7_EN, + PMIC_ISINK_CHOP6_EN = MT6351_PMIC_ISINK_CHOP6_EN, + PMIC_ISINK_CHOP3_EN = MT6351_PMIC_ISINK_CHOP3_EN, + PMIC_ISINK_CHOP2_EN = MT6351_PMIC_ISINK_CHOP2_EN, + PMIC_ISINK_CH7_BIAS_EN = MT6351_PMIC_ISINK_CH7_BIAS_EN, + PMIC_ISINK_CH6_BIAS_EN = MT6351_PMIC_ISINK_CH6_BIAS_EN, + PMIC_ISINK_CH3_BIAS_EN = MT6351_PMIC_ISINK_CH3_BIAS_EN, + PMIC_ISINK_CH2_BIAS_EN = MT6351_PMIC_ISINK_CH2_BIAS_EN, + PMIC_CHRIND_DIM_FSEL = MT6351_PMIC_CHRIND_DIM_FSEL, + PMIC_CHRIND_RSV1 = MT6351_PMIC_CHRIND_RSV1, + PMIC_CHRIND_RSV0 = MT6351_PMIC_CHRIND_RSV0, + PMIC_CHRIND_DIM_DUTY = MT6351_PMIC_CHRIND_DIM_DUTY, + PMIC_CHRIND_STEP = MT6351_PMIC_CHRIND_STEP, + PMIC_CHRIND_BREATH_TF2_SEL = MT6351_PMIC_CHRIND_BREATH_TF2_SEL, + PMIC_CHRIND_BREATH_TF1_SEL = MT6351_PMIC_CHRIND_BREATH_TF1_SEL, + PMIC_CHRIND_BREATH_TR2_SEL = MT6351_PMIC_CHRIND_BREATH_TR2_SEL, + PMIC_CHRIND_BREATH_TR1_SEL = MT6351_PMIC_CHRIND_BREATH_TR1_SEL, + PMIC_CHRIND_BREATH_TOFF_SEL = MT6351_PMIC_CHRIND_BREATH_TOFF_SEL, + PMIC_CHRIND_BREATH_TON_SEL = MT6351_PMIC_CHRIND_BREATH_TON_SEL, + PMIC_CHRIND_SFSTR_EN = MT6351_PMIC_CHRIND_SFSTR_EN, + PMIC_CHRIND_SFSTR_TC = MT6351_PMIC_CHRIND_SFSTR_TC, + PMIC_CHRIND_EN_SEL = MT6351_PMIC_CHRIND_EN_SEL, + PMIC_CHRIND_EN = MT6351_PMIC_CHRIND_EN, + PMIC_CHRIND_CHOP_EN = MT6351_PMIC_CHRIND_CHOP_EN, + PMIC_CHRIND_MODE = MT6351_PMIC_CHRIND_MODE, + PMIC_CHRIND_CHOP_SW = MT6351_PMIC_CHRIND_CHOP_SW, + PMIC_CHRIND_BIAS_EN = MT6351_PMIC_CHRIND_BIAS_EN, + PMIC_RG_VA18_MODE_SET = MT6351_PMIC_RG_VA18_MODE_SET, + PMIC_RG_VA18_EN = MT6351_PMIC_RG_VA18_EN, + PMIC_RG_VA18_MODE_CTRL = MT6351_PMIC_RG_VA18_MODE_CTRL, + PMIC_RG_VA18_ON_CTRL = MT6351_PMIC_RG_VA18_ON_CTRL, + PMIC_RG_VA18_SRCLK_MODE_SEL = MT6351_PMIC_RG_VA18_SRCLK_MODE_SEL, + PMIC_DA_QI_VA18_MODE = MT6351_PMIC_DA_QI_VA18_MODE, + PMIC_RG_VA18_STBTD = MT6351_PMIC_RG_VA18_STBTD, + PMIC_RG_VA18_SRCLK_EN_SEL = MT6351_PMIC_RG_VA18_SRCLK_EN_SEL, + PMIC_DA_QI_VA18_STB = MT6351_PMIC_DA_QI_VA18_STB, + PMIC_DA_QI_VA18_EN = MT6351_PMIC_DA_QI_VA18_EN, + PMIC_RG_VA18_AUXADC_PWDB_EN = MT6351_PMIC_RG_VA18_AUXADC_PWDB_EN, + PMIC_RG_VA18_OCFB_EN = MT6351_PMIC_RG_VA18_OCFB_EN, + PMIC_DA_QI_VA18_OCFB_EN = MT6351_PMIC_DA_QI_VA18_OCFB_EN, + PMIC_RG_VTCXO24_MODE_SET = MT6351_PMIC_RG_VTCXO24_MODE_SET, + PMIC_RG_VTCXO24_EN = MT6351_PMIC_RG_VTCXO24_EN, + PMIC_RG_VTCXO24_MODE_CTRL = MT6351_PMIC_RG_VTCXO24_MODE_CTRL, + PMIC_RG_VTCXO24_ON_CTRL = MT6351_PMIC_RG_VTCXO24_ON_CTRL, + PMIC_RG_VTCXO24_SWITCH = MT6351_PMIC_RG_VTCXO24_SWITCH, + PMIC_RG_VTCXO24_SRCLK_MODE_SEL = MT6351_PMIC_RG_VTCXO24_SRCLK_MODE_SEL, + PMIC_DA_QI_VTCXO24_MODE = MT6351_PMIC_DA_QI_VTCXO24_MODE, + PMIC_RG_VTCXO24_STBTD = MT6351_PMIC_RG_VTCXO24_STBTD, + PMIC_RG_VTCXO24_SRCLK_EN_SEL = MT6351_PMIC_RG_VTCXO24_SRCLK_EN_SEL, + PMIC_DA_QI_VTCXO24_STB = MT6351_PMIC_DA_QI_VTCXO24_STB, + PMIC_DA_QI_VTCXO24_EN = MT6351_PMIC_DA_QI_VTCXO24_EN, + PMIC_RG_VTCXO24_OCFB_EN = MT6351_PMIC_RG_VTCXO24_OCFB_EN, + PMIC_DA_QI_VTCXO24_OCFB_EN = MT6351_PMIC_DA_QI_VTCXO24_OCFB_EN, + PMIC_RG_VTCXO28_MODE_SET = MT6351_PMIC_RG_VTCXO28_MODE_SET, + PMIC_RG_VTCXO28_EN = MT6351_PMIC_RG_VTCXO28_EN, + PMIC_RG_VTCXO28_MODE_CTRL = MT6351_PMIC_RG_VTCXO28_MODE_CTRL, + PMIC_RG_VTCXO28_ON_CTRL = MT6351_PMIC_RG_VTCXO28_ON_CTRL, + PMIC_RG_VTCXO28_SRCLK_MODE_SEL = MT6351_PMIC_RG_VTCXO28_SRCLK_MODE_SEL, + PMIC_DA_QI_VTCXO28_MODE = MT6351_PMIC_DA_QI_VTCXO28_MODE, + PMIC_RG_VTCXO28_STBTD = MT6351_PMIC_RG_VTCXO28_STBTD, + PMIC_RG_VTCXO28_SRCLK_EN_SEL = MT6351_PMIC_RG_VTCXO28_SRCLK_EN_SEL, + PMIC_DA_QI_VTCXO28_STB = MT6351_PMIC_DA_QI_VTCXO28_STB, + PMIC_DA_QI_VTCXO28_EN = MT6351_PMIC_DA_QI_VTCXO28_EN, + PMIC_RG_VTCXO28_OCFB_EN = MT6351_PMIC_RG_VTCXO28_OCFB_EN, + PMIC_DA_QI_VTCXO28_OCFB_EN = MT6351_PMIC_DA_QI_VTCXO28_OCFB_EN, + PMIC_RG_VCN28_MODE_SET = MT6351_PMIC_RG_VCN28_MODE_SET, + PMIC_RG_VCN28_EN = MT6351_PMIC_RG_VCN28_EN, + PMIC_RG_VCN28_MODE_CTRL = MT6351_PMIC_RG_VCN28_MODE_CTRL, + PMIC_RG_VCN28_ON_CTRL = MT6351_PMIC_RG_VCN28_ON_CTRL, + PMIC_RG_VCN28_SRCLK_MODE_SEL = MT6351_PMIC_RG_VCN28_SRCLK_MODE_SEL, + PMIC_DA_QI_VCN28_MODE = MT6351_PMIC_DA_QI_VCN28_MODE, + PMIC_RG_VCN28_STBTD = MT6351_PMIC_RG_VCN28_STBTD, + PMIC_RG_VCN28_SRCLK_EN_SEL = MT6351_PMIC_RG_VCN28_SRCLK_EN_SEL, + PMIC_DA_QI_VCN28_STB = MT6351_PMIC_DA_QI_VCN28_STB, + PMIC_DA_QI_VCN28_EN = MT6351_PMIC_DA_QI_VCN28_EN, + PMIC_RG_VCN28_OCFB_EN = MT6351_PMIC_RG_VCN28_OCFB_EN, + PMIC_DA_QI_VCN28_OCFB_EN = MT6351_PMIC_DA_QI_VCN28_OCFB_EN, + PMIC_RG_VCN28_DUMMY_LOAD_EN = MT6351_PMIC_RG_VCN28_DUMMY_LOAD_EN, + PMIC_RG_VCN28_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VCN28_DUMMY_LOAD_CTRL, + PMIC_RG_VCN28_DUMMY_LOAD = MT6351_PMIC_RG_VCN28_DUMMY_LOAD, + PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VCN28_DUMMY_LOAD = MT6351_PMIC_DA_QI_VCN28_DUMMY_LOAD, + PMIC_RG_VCAMA_EN = MT6351_PMIC_RG_VCAMA_EN, + PMIC_RG_VCAMA_ON_CTRL = MT6351_PMIC_RG_VCAMA_ON_CTRL, + PMIC_RG_VCAMA_SRCLK_MODE_SEL = MT6351_PMIC_RG_VCAMA_SRCLK_MODE_SEL, + PMIC_DA_QI_VCAMA_MODE = MT6351_PMIC_DA_QI_VCAMA_MODE, + PMIC_RG_VCAMA_STBTD = MT6351_PMIC_RG_VCAMA_STBTD, + PMIC_RG_VCAMA_SRCLK_EN_SEL = MT6351_PMIC_RG_VCAMA_SRCLK_EN_SEL, + PMIC_DA_QI_VCAMA_STB = MT6351_PMIC_DA_QI_VCAMA_STB, + PMIC_DA_QI_VCAMA_EN = MT6351_PMIC_DA_QI_VCAMA_EN, + PMIC_RG_VCAMA_OCFB_EN = MT6351_PMIC_RG_VCAMA_OCFB_EN, + PMIC_DA_QI_VCAMA_OCFB_EN = MT6351_PMIC_DA_QI_VCAMA_OCFB_EN, + PMIC_RG_VUSB33_MODE_SET = MT6351_PMIC_RG_VUSB33_MODE_SET, + PMIC_RG_VUSB33_EN = MT6351_PMIC_RG_VUSB33_EN, + PMIC_RG_VUSB33_MODE_CTRL = MT6351_PMIC_RG_VUSB33_MODE_CTRL, + PMIC_RG_VUSB33_ON_CTRL = MT6351_PMIC_RG_VUSB33_ON_CTRL, + PMIC_RG_VUSB33_SRCLK_MODE_SEL = MT6351_PMIC_RG_VUSB33_SRCLK_MODE_SEL, + PMIC_DA_QI_VUSB33_MODE = MT6351_PMIC_DA_QI_VUSB33_MODE, + PMIC_RG_VUSB33_STBTD = MT6351_PMIC_RG_VUSB33_STBTD, + PMIC_RG_VUSB33_SRCLK_EN_SEL = MT6351_PMIC_RG_VUSB33_SRCLK_EN_SEL, + PMIC_DA_QI_VUSB33_STB = MT6351_PMIC_DA_QI_VUSB33_STB, + PMIC_DA_QI_VUSB33_EN = MT6351_PMIC_DA_QI_VUSB33_EN, + PMIC_RG_VUSB33_OCFB_EN = MT6351_PMIC_RG_VUSB33_OCFB_EN, + PMIC_DA_QI_VUSB33_OCFB_EN = MT6351_PMIC_DA_QI_VUSB33_OCFB_EN, + PMIC_RG_VUSB33_DUMMY_LOAD_EN = MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_EN, + PMIC_RG_VUSB33_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_CTRL, + PMIC_RG_VUSB33_DUMMY_LOAD = MT6351_PMIC_RG_VUSB33_DUMMY_LOAD, + PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VUSB33_DUMMY_LOAD = MT6351_PMIC_DA_QI_VUSB33_DUMMY_LOAD, + PMIC_RG_VSIM1_MODE_SET = MT6351_PMIC_RG_VSIM1_MODE_SET, + PMIC_RG_VSIM1_EN = MT6351_PMIC_RG_VSIM1_EN, + PMIC_RG_VSIM1_MODE_CTRL = MT6351_PMIC_RG_VSIM1_MODE_CTRL, + PMIC_RG_VSIM1_ON_CTRL = MT6351_PMIC_RG_VSIM1_ON_CTRL, + PMIC_RG_VSIM1_SRCLK_MODE_SEL = MT6351_PMIC_RG_VSIM1_SRCLK_MODE_SEL, + PMIC_DA_QI_VSIM1_MODE = MT6351_PMIC_DA_QI_VSIM1_MODE, + PMIC_RG_VSIM1_STBTD = MT6351_PMIC_RG_VSIM1_STBTD, + PMIC_RG_VSIM1_SRCLK_EN_SEL = MT6351_PMIC_RG_VSIM1_SRCLK_EN_SEL, + PMIC_DA_QI_VSIM1_STB = MT6351_PMIC_DA_QI_VSIM1_STB, + PMIC_DA_QI_VSIM1_EN = MT6351_PMIC_DA_QI_VSIM1_EN, + PMIC_RG_VSIM1_OCFB_EN = MT6351_PMIC_RG_VSIM1_OCFB_EN, + PMIC_DA_QI_VSIM1_OCFB_EN = MT6351_PMIC_DA_QI_VSIM1_OCFB_EN, + PMIC_RG_VSIM1_DUMMY_LOAD_EN = MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_EN, + PMIC_RG_VSIM1_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_CTRL, + PMIC_RG_VSIM1_DUMMY_LOAD = MT6351_PMIC_RG_VSIM1_DUMMY_LOAD, + PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VSIM1_DUMMY_LOAD = MT6351_PMIC_DA_QI_VSIM1_DUMMY_LOAD, + PMIC_RG_VSIM2_MODE_SET = MT6351_PMIC_RG_VSIM2_MODE_SET, + PMIC_RG_VSIM2_EN = MT6351_PMIC_RG_VSIM2_EN, + PMIC_RG_VSIM2_MODE_CTRL = MT6351_PMIC_RG_VSIM2_MODE_CTRL, + PMIC_RG_VSIM2_ON_CTRL = MT6351_PMIC_RG_VSIM2_ON_CTRL, + PMIC_RG_VSIM2_SRCLK_MODE_SEL = MT6351_PMIC_RG_VSIM2_SRCLK_MODE_SEL, + PMIC_DA_QI_VSIM2_MODE = MT6351_PMIC_DA_QI_VSIM2_MODE, + PMIC_RG_VSIM2_STBTD = MT6351_PMIC_RG_VSIM2_STBTD, + PMIC_RG_VSIM2_SRCLK_EN_SEL = MT6351_PMIC_RG_VSIM2_SRCLK_EN_SEL, + PMIC_DA_QI_VSIM2_STB = MT6351_PMIC_DA_QI_VSIM2_STB, + PMIC_DA_QI_VSIM2_EN = MT6351_PMIC_DA_QI_VSIM2_EN, + PMIC_RG_VSIM2_OCFB_EN = MT6351_PMIC_RG_VSIM2_OCFB_EN, + PMIC_DA_QI_VSIM2_OCFB_EN = MT6351_PMIC_DA_QI_VSIM2_OCFB_EN, + PMIC_RG_VSIM2_DUMMY_LOAD_EN = MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_EN, + PMIC_RG_VSIM2_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_CTRL, + PMIC_RG_VSIM2_DUMMY_LOAD = MT6351_PMIC_RG_VSIM2_DUMMY_LOAD, + PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VSIM2_DUMMY_LOAD = MT6351_PMIC_DA_QI_VSIM2_DUMMY_LOAD, + PMIC_RG_VEMC_MODE_SET = MT6351_PMIC_RG_VEMC_MODE_SET, + PMIC_RG_VEMC_EN = MT6351_PMIC_RG_VEMC_EN, + PMIC_RG_VEMC_MODE_CTRL = MT6351_PMIC_RG_VEMC_MODE_CTRL, + PMIC_RG_VEMC_ON_CTRL = MT6351_PMIC_RG_VEMC_ON_CTRL, + PMIC_RG_VEMC_SRCLK_MODE_SEL = MT6351_PMIC_RG_VEMC_SRCLK_MODE_SEL, + PMIC_DA_QI_VEMC_MODE = MT6351_PMIC_DA_QI_VEMC_MODE, + PMIC_RG_VEMC_STBTD = MT6351_PMIC_RG_VEMC_STBTD, + PMIC_RG_VEMC_SRCLK_EN_SEL = MT6351_PMIC_RG_VEMC_SRCLK_EN_SEL, + PMIC_DA_QI_VEMC_STB = MT6351_PMIC_DA_QI_VEMC_STB, + PMIC_DA_QI_VEMC_EN = MT6351_PMIC_DA_QI_VEMC_EN, + PMIC_RG_VEMC_OCFB_EN = MT6351_PMIC_RG_VEMC_OCFB_EN, + PMIC_DA_QI_VEMC_OCFB_EN = MT6351_PMIC_DA_QI_VEMC_OCFB_EN, + PMIC_RG_VEMC_DUMMY_LOAD_EN = MT6351_PMIC_RG_VEMC_DUMMY_LOAD_EN, + PMIC_RG_VEMC_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VEMC_DUMMY_LOAD_CTRL, + PMIC_RG_VEMC_DUMMY_LOAD = MT6351_PMIC_RG_VEMC_DUMMY_LOAD, + PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VEMC_DUMMY_LOAD = MT6351_PMIC_DA_QI_VEMC_DUMMY_LOAD, + PMIC_RG_VMCH_MODE_SET = MT6351_PMIC_RG_VMCH_MODE_SET, + PMIC_RG_VMCH_EN = MT6351_PMIC_RG_VMCH_EN, + PMIC_RG_VMCH_MODE_CTRL = MT6351_PMIC_RG_VMCH_MODE_CTRL, + PMIC_RG_VMCH_ON_CTRL = MT6351_PMIC_RG_VMCH_ON_CTRL, + PMIC_RG_VMCH_SRCLK_MODE_SEL = MT6351_PMIC_RG_VMCH_SRCLK_MODE_SEL, + PMIC_DA_QI_VMCH_MODE = MT6351_PMIC_DA_QI_VMCH_MODE, + PMIC_RG_VMCH_STBTD = MT6351_PMIC_RG_VMCH_STBTD, + PMIC_RG_VMCH_SRCLK_EN_SEL = MT6351_PMIC_RG_VMCH_SRCLK_EN_SEL, + PMIC_DA_QI_VMCH_STB = MT6351_PMIC_DA_QI_VMCH_STB, + PMIC_DA_QI_VMCH_EN = MT6351_PMIC_DA_QI_VMCH_EN, + PMIC_RG_VMCH_OCFB_EN = MT6351_PMIC_RG_VMCH_OCFB_EN, + PMIC_DA_QI_VMCH_OCFB_EN = MT6351_PMIC_DA_QI_VMCH_OCFB_EN, + PMIC_RG_VMCH_DUMMY_LOAD_EN = MT6351_PMIC_RG_VMCH_DUMMY_LOAD_EN, + PMIC_RG_VMCH_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VMCH_DUMMY_LOAD_CTRL, + PMIC_RG_VMCH_DUMMY_LOAD = MT6351_PMIC_RG_VMCH_DUMMY_LOAD, + PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VMCH_DUMMY_LOAD = MT6351_PMIC_DA_QI_VMCH_DUMMY_LOAD, + PMIC_RG_VIO28_MODE_SET = MT6351_PMIC_RG_VIO28_MODE_SET, + PMIC_RG_VIO28_EN = MT6351_PMIC_RG_VIO28_EN, + PMIC_RG_VIO28_MODE_CTRL = MT6351_PMIC_RG_VIO28_MODE_CTRL, + PMIC_RG_VIO28_ON_CTRL = MT6351_PMIC_RG_VIO28_ON_CTRL, + PMIC_RG_VIO28_SRCLK_MODE_SEL = MT6351_PMIC_RG_VIO28_SRCLK_MODE_SEL, + PMIC_DA_QI_VIO28_MODE = MT6351_PMIC_DA_QI_VIO28_MODE, + PMIC_RG_VIO28_STBTD = MT6351_PMIC_RG_VIO28_STBTD, + PMIC_RG_VIO28_SRCLK_EN_SEL = MT6351_PMIC_RG_VIO28_SRCLK_EN_SEL, + PMIC_DA_QI_VIO28_STB = MT6351_PMIC_DA_QI_VIO28_STB, + PMIC_DA_QI_VIO28_EN = MT6351_PMIC_DA_QI_VIO28_EN, + PMIC_RG_VIO28_OCFB_EN = MT6351_PMIC_RG_VIO28_OCFB_EN, + PMIC_DA_QI_VIO28_OCFB_EN = MT6351_PMIC_DA_QI_VIO28_OCFB_EN, + PMIC_RG_VIO28_DUMMY_LOAD_EN = MT6351_PMIC_RG_VIO28_DUMMY_LOAD_EN, + PMIC_RG_VIO28_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VIO28_DUMMY_LOAD_CTRL, + PMIC_RG_VIO28_DUMMY_LOAD = MT6351_PMIC_RG_VIO28_DUMMY_LOAD, + PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VIO28_DUMMY_LOAD = MT6351_PMIC_DA_QI_VIO28_DUMMY_LOAD, + PMIC_RG_VIBR_MODE_SET = MT6351_PMIC_RG_VIBR_MODE_SET, + PMIC_RG_VIBR_EN = MT6351_PMIC_RG_VIBR_EN, + PMIC_RG_VIBR_MODE_CTRL = MT6351_PMIC_RG_VIBR_MODE_CTRL, + PMIC_RG_VIBR_ON_CTRL = MT6351_PMIC_RG_VIBR_ON_CTRL, + PMIC_RG_VIBR_THER_SDN_EN = MT6351_PMIC_RG_VIBR_THER_SDN_EN, + PMIC_RG_VIBR_SRCLK_MODE_SEL = MT6351_PMIC_RG_VIBR_SRCLK_MODE_SEL, + PMIC_DA_QI_VIBR_MODE = MT6351_PMIC_DA_QI_VIBR_MODE, + PMIC_RG_VIBR_STBTD = MT6351_PMIC_RG_VIBR_STBTD, + PMIC_RG_VIBR_SRCLK_EN_SEL = MT6351_PMIC_RG_VIBR_SRCLK_EN_SEL, + PMIC_DA_QI_VIBR_STB = MT6351_PMIC_DA_QI_VIBR_STB, + PMIC_DA_QI_VIBR_EN = MT6351_PMIC_DA_QI_VIBR_EN, + PMIC_RG_VIBR_OCFB_EN = MT6351_PMIC_RG_VIBR_OCFB_EN, + PMIC_DA_QI_VIBR_OCFB_EN = MT6351_PMIC_DA_QI_VIBR_OCFB_EN, + PMIC_RG_VIBR_DUMMY_LOAD_EN = MT6351_PMIC_RG_VIBR_DUMMY_LOAD_EN, + PMIC_RG_VIBR_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VIBR_DUMMY_LOAD_CTRL, + PMIC_RG_VIBR_DUMMY_LOAD = MT6351_PMIC_RG_VIBR_DUMMY_LOAD, + PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VIBR_DUMMY_LOAD = MT6351_PMIC_DA_QI_VIBR_DUMMY_LOAD, + PMIC_RG_VCAMD_MODE_SET = MT6351_PMIC_RG_VCAMD_MODE_SET, + PMIC_RG_VCAMD_EN = MT6351_PMIC_RG_VCAMD_EN, + PMIC_RG_VCAMD_MODE_CTRL = MT6351_PMIC_RG_VCAMD_MODE_CTRL, + PMIC_RG_VCAMD_SRCLK_MODE_SEL = MT6351_PMIC_RG_VCAMD_SRCLK_MODE_SEL, + PMIC_DA_QI_VCAMD_MODE = MT6351_PMIC_DA_QI_VCAMD_MODE, + PMIC_RG_VCAMD_STBTD = MT6351_PMIC_RG_VCAMD_STBTD, + PMIC_DA_QI_VCAMD_STB = MT6351_PMIC_DA_QI_VCAMD_STB, + PMIC_DA_QI_VCAMD_EN = MT6351_PMIC_DA_QI_VCAMD_EN, + PMIC_RG_VCAMD_OCFB_EN = MT6351_PMIC_RG_VCAMD_OCFB_EN, + PMIC_DA_QI_VCAMD_OCFB_EN = MT6351_PMIC_DA_QI_VCAMD_OCFB_EN, + PMIC_RG_VCAMD_DUMMY_LOAD_EN = MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_EN, + PMIC_RG_VCAMD_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_CTRL, + PMIC_RG_VCAMD_DUMMY_LOAD = MT6351_PMIC_RG_VCAMD_DUMMY_LOAD, + PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VCAMD_DUMMY_LOAD = MT6351_PMIC_DA_QI_VCAMD_DUMMY_LOAD, + PMIC_RG_VRF18_MODE_SET = MT6351_PMIC_RG_VRF18_MODE_SET, + PMIC_RG_VRF18_EN = MT6351_PMIC_RG_VRF18_EN, + PMIC_RG_VRF18_MODE_CTRL = MT6351_PMIC_RG_VRF18_MODE_CTRL, + PMIC_RG_VRF18_ON_CTRL = MT6351_PMIC_RG_VRF18_ON_CTRL, + PMIC_RG_VRF18_SRCLK_MODE_SEL = MT6351_PMIC_RG_VRF18_SRCLK_MODE_SEL, + PMIC_DA_QI_VRF18_MODE = MT6351_PMIC_DA_QI_VRF18_MODE, + PMIC_RG_VRF18_STBTD = MT6351_PMIC_RG_VRF18_STBTD, + PMIC_RG_VRF18_SRCLK_EN_SEL = MT6351_PMIC_RG_VRF18_SRCLK_EN_SEL, + PMIC_DA_QI_VRF18_STB = MT6351_PMIC_DA_QI_VRF18_STB, + PMIC_DA_QI_VRF18_EN = MT6351_PMIC_DA_QI_VRF18_EN, + PMIC_RG_VRF18_OCFB_EN = MT6351_PMIC_RG_VRF18_OCFB_EN, + PMIC_DA_QI_VRF18_OCFB_EN = MT6351_PMIC_DA_QI_VRF18_OCFB_EN, + PMIC_RG_VRF18_DUMMY_LOAD_EN = MT6351_PMIC_RG_VRF18_DUMMY_LOAD_EN, + PMIC_RG_VRF18_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VRF18_DUMMY_LOAD_CTRL, + PMIC_RG_VRF18_DUMMY_LOAD = MT6351_PMIC_RG_VRF18_DUMMY_LOAD, + PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VRF18_DUMMY_LOAD = MT6351_PMIC_DA_QI_VRF18_DUMMY_LOAD, + PMIC_RG_VIO18_MODE_SET = MT6351_PMIC_RG_VIO18_MODE_SET, + PMIC_RG_VIO18_EN = MT6351_PMIC_RG_VIO18_EN, + PMIC_RG_VIO18_MODE_CTRL = MT6351_PMIC_RG_VIO18_MODE_CTRL, + PMIC_RG_VIO18_ON_CTRL = MT6351_PMIC_RG_VIO18_ON_CTRL, + PMIC_RG_VIO18_SRCLK_MODE_SEL = MT6351_PMIC_RG_VIO18_SRCLK_MODE_SEL, + PMIC_DA_QI_VIO18_MODE = MT6351_PMIC_DA_QI_VIO18_MODE, + PMIC_RG_VIO18_STBTD = MT6351_PMIC_RG_VIO18_STBTD, + PMIC_RG_VIO18_SRCLK_EN_SEL = MT6351_PMIC_RG_VIO18_SRCLK_EN_SEL, + PMIC_DA_QI_VIO18_STB = MT6351_PMIC_DA_QI_VIO18_STB, + PMIC_DA_QI_VIO18_EN = MT6351_PMIC_DA_QI_VIO18_EN, + PMIC_RG_VIO18_OCFB_EN = MT6351_PMIC_RG_VIO18_OCFB_EN, + PMIC_DA_QI_VIO18_OCFB_EN = MT6351_PMIC_DA_QI_VIO18_OCFB_EN, + PMIC_RG_VIO18_DUMMY_LOAD_EN = MT6351_PMIC_RG_VIO18_DUMMY_LOAD_EN, + PMIC_RG_VIO18_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VIO18_DUMMY_LOAD_CTRL, + PMIC_RG_VIO18_DUMMY_LOAD = MT6351_PMIC_RG_VIO18_DUMMY_LOAD, + PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VIO18_DUMMY_LOAD = MT6351_PMIC_DA_QI_VIO18_DUMMY_LOAD, + PMIC_RG_VCN18_MODE_SET = MT6351_PMIC_RG_VCN18_MODE_SET, + PMIC_RG_VCN18_EN = MT6351_PMIC_RG_VCN18_EN, + PMIC_RG_VCN18_MODE_CTRL = MT6351_PMIC_RG_VCN18_MODE_CTRL, + PMIC_RG_VCN18_ON_CTRL = MT6351_PMIC_RG_VCN18_ON_CTRL, + PMIC_RG_VCN18_SRCLK_MODE_SEL = MT6351_PMIC_RG_VCN18_SRCLK_MODE_SEL, + PMIC_DA_QI_VCN18_MODE = MT6351_PMIC_DA_QI_VCN18_MODE, + PMIC_RG_VCN18_STBTD = MT6351_PMIC_RG_VCN18_STBTD, + PMIC_RG_VCN18_SRCLK_EN_SEL = MT6351_PMIC_RG_VCN18_SRCLK_EN_SEL, + PMIC_DA_QI_VCN18_STB = MT6351_PMIC_DA_QI_VCN18_STB, + PMIC_DA_QI_VCN18_EN = MT6351_PMIC_DA_QI_VCN18_EN, + PMIC_RG_VCN18_OCFB_EN = MT6351_PMIC_RG_VCN18_OCFB_EN, + PMIC_DA_QI_VCN18_OCFB_EN = MT6351_PMIC_DA_QI_VCN18_OCFB_EN, + PMIC_RG_VCN18_DUMMY_LOAD_EN = MT6351_PMIC_RG_VCN18_DUMMY_LOAD_EN, + PMIC_RG_VCN18_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VCN18_DUMMY_LOAD_CTRL, + PMIC_RG_VCN18_DUMMY_LOAD = MT6351_PMIC_RG_VCN18_DUMMY_LOAD, + PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VCN18_DUMMY_LOAD = MT6351_PMIC_DA_QI_VCN18_DUMMY_LOAD, + PMIC_RG_VCAMIO_MODE_SET = MT6351_PMIC_RG_VCAMIO_MODE_SET, + PMIC_RG_VCAMIO_EN = MT6351_PMIC_RG_VCAMIO_EN, + PMIC_RG_VCAMIO_MODE_CTRL = MT6351_PMIC_RG_VCAMIO_MODE_CTRL, + PMIC_RG_VCAMIO_SRCLK_MODE_SEL = MT6351_PMIC_RG_VCAMIO_SRCLK_MODE_SEL, + PMIC_DA_QI_VCAMIO_MODE = MT6351_PMIC_DA_QI_VCAMIO_MODE, + PMIC_RG_VCAMIO_STBTD = MT6351_PMIC_RG_VCAMIO_STBTD, + PMIC_DA_QI_VCAMIO_STB = MT6351_PMIC_DA_QI_VCAMIO_STB, + PMIC_DA_QI_VCAMIO_EN = MT6351_PMIC_DA_QI_VCAMIO_EN, + PMIC_RG_VCAMIO_OCFB_EN = MT6351_PMIC_RG_VCAMIO_OCFB_EN, + PMIC_DA_QI_VCAMIO_OCFB_EN = MT6351_PMIC_DA_QI_VCAMIO_OCFB_EN, + PMIC_RG_VCAMIO_DUMMY_LOAD_EN = MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_EN, + PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL, + PMIC_RG_VCAMIO_DUMMY_LOAD = MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD, + PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VCAMIO_DUMMY_LOAD = MT6351_PMIC_DA_QI_VCAMIO_DUMMY_LOAD, + PMIC_RG_VSRAM_PROC_MODE_SET = MT6351_PMIC_RG_VSRAM_PROC_MODE_SET, + PMIC_RG_VSRAM_PROC_EN = MT6351_PMIC_RG_VSRAM_PROC_EN, + PMIC_RG_VSRAM_PROC_MODE_CTRL = MT6351_PMIC_RG_VSRAM_PROC_MODE_CTRL, + PMIC_RG_VSRAM_PROC_ON_CTRL = MT6351_PMIC_RG_VSRAM_PROC_ON_CTRL, + PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL = MT6351_PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL, + PMIC_DA_QI_VSRAM_PROC_MODE = MT6351_PMIC_DA_QI_VSRAM_PROC_MODE, + PMIC_RG_VSRAM_PROC_STBTD = MT6351_PMIC_RG_VSRAM_PROC_STBTD, + PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL = MT6351_PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL, + PMIC_DA_QI_VSRAM_PROC_STB = MT6351_PMIC_DA_QI_VSRAM_PROC_STB, + PMIC_DA_QI_VSRAM_PROC_EN = MT6351_PMIC_DA_QI_VSRAM_PROC_EN, + PMIC_RG_VSRAM_PROC_OCFB_EN = MT6351_PMIC_RG_VSRAM_PROC_OCFB_EN, + PMIC_DA_QI_VSRAM_PROC_OCFB_EN = MT6351_PMIC_DA_QI_VSRAM_PROC_OCFB_EN, + PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN = MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN, + PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL, + PMIC_RG_VSRAM_PROC_DUMMY_LOAD = MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD, + PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD = MT6351_PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD, + PMIC_RG_VXO22_MODE_SET = MT6351_PMIC_RG_VXO22_MODE_SET, + PMIC_RG_VXO22_EN = MT6351_PMIC_RG_VXO22_EN, + PMIC_RG_VXO22_MODE_CTRL = MT6351_PMIC_RG_VXO22_MODE_CTRL, + PMIC_RG_VXO22_ON_CTRL = MT6351_PMIC_RG_VXO22_ON_CTRL, + PMIC_RG_VXO22_SWITCH = MT6351_PMIC_RG_VXO22_SWITCH, + PMIC_RG_VXO22_SRCLK_MODE_SEL = MT6351_PMIC_RG_VXO22_SRCLK_MODE_SEL, + PMIC_DA_QI_VXO22_MODE = MT6351_PMIC_DA_QI_VXO22_MODE, + PMIC_RG_VXO22_STBTD = MT6351_PMIC_RG_VXO22_STBTD, + PMIC_RG_VXO22_SRCLK_EN_SEL = MT6351_PMIC_RG_VXO22_SRCLK_EN_SEL, + PMIC_DA_QI_VXO22_STB = MT6351_PMIC_DA_QI_VXO22_STB, + PMIC_DA_QI_VXO22_EN = MT6351_PMIC_DA_QI_VXO22_EN, + PMIC_RG_VXO22_OCFB_EN = MT6351_PMIC_RG_VXO22_OCFB_EN, + PMIC_DA_QI_VXO22_OCFB_EN = MT6351_PMIC_DA_QI_VXO22_OCFB_EN, + PMIC_RG_VRF12_MODE_SET = MT6351_PMIC_RG_VRF12_MODE_SET, + PMIC_RG_VRF12_EN = MT6351_PMIC_RG_VRF12_EN, + PMIC_RG_VRF12_MODE_CTRL = MT6351_PMIC_RG_VRF12_MODE_CTRL, + PMIC_RG_VRF12_ON_CTRL = MT6351_PMIC_RG_VRF12_ON_CTRL, + PMIC_RG_VRF12_SRCLK_MODE_SEL = MT6351_PMIC_RG_VRF12_SRCLK_MODE_SEL, + PMIC_DA_QI_VRF12_MODE = MT6351_PMIC_DA_QI_VRF12_MODE, + PMIC_RG_VRF12_STBTD = MT6351_PMIC_RG_VRF12_STBTD, + PMIC_RG_VRF12_SRCLK_EN_SEL = MT6351_PMIC_RG_VRF12_SRCLK_EN_SEL, + PMIC_DA_QI_VRF12_STB = MT6351_PMIC_DA_QI_VRF12_STB, + PMIC_DA_QI_VRF12_EN = MT6351_PMIC_DA_QI_VRF12_EN, + PMIC_RG_VRF12_OCFB_EN = MT6351_PMIC_RG_VRF12_OCFB_EN, + PMIC_DA_QI_VRF12_OCFB_EN = MT6351_PMIC_DA_QI_VRF12_OCFB_EN, + PMIC_RG_VRF12_DUMMY_LOAD_EN = MT6351_PMIC_RG_VRF12_DUMMY_LOAD_EN, + PMIC_RG_VRF12_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VRF12_DUMMY_LOAD_CTRL, + PMIC_RG_VRF12_DUMMY_LOAD = MT6351_PMIC_RG_VRF12_DUMMY_LOAD, + PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VRF12_DUMMY_LOAD = MT6351_PMIC_DA_QI_VRF12_DUMMY_LOAD, + PMIC_RG_VA10_MODE_SET = MT6351_PMIC_RG_VA10_MODE_SET, + PMIC_RG_VA10_EN = MT6351_PMIC_RG_VA10_EN, + PMIC_RG_VA10_MODE_CTRL = MT6351_PMIC_RG_VA10_MODE_CTRL, + PMIC_RG_VA10_ON_CTRL = MT6351_PMIC_RG_VA10_ON_CTRL, + PMIC_RG_VA10_SRCLK_MODE_SEL = MT6351_PMIC_RG_VA10_SRCLK_MODE_SEL, + PMIC_DA_QI_VA10_MODE = MT6351_PMIC_DA_QI_VA10_MODE, + PMIC_RG_VA10_STBTD = MT6351_PMIC_RG_VA10_STBTD, + PMIC_RG_VA10_SRCLK_EN_SEL = MT6351_PMIC_RG_VA10_SRCLK_EN_SEL, + PMIC_DA_QI_VA10_STB = MT6351_PMIC_DA_QI_VA10_STB, + PMIC_DA_QI_VA10_EN = MT6351_PMIC_DA_QI_VA10_EN, + PMIC_RG_VA10_OCFB_EN = MT6351_PMIC_RG_VA10_OCFB_EN, + PMIC_DA_QI_VA10_OCFB_EN = MT6351_PMIC_DA_QI_VA10_OCFB_EN, + PMIC_RG_VA10_DUMMY_LOAD_EN = MT6351_PMIC_RG_VA10_DUMMY_LOAD_EN, + PMIC_RG_VA10_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VA10_DUMMY_LOAD_CTRL, + PMIC_RG_VA10_DUMMY_LOAD = MT6351_PMIC_RG_VA10_DUMMY_LOAD, + PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VA10_DUMMY_LOAD = MT6351_PMIC_DA_QI_VA10_DUMMY_LOAD, + PMIC_RG_VDRAM_MODE_SET = MT6351_PMIC_RG_VDRAM_MODE_SET, + PMIC_RG_VDRAM_EN = MT6351_PMIC_RG_VDRAM_EN, + PMIC_RG_VDRAM_MODE_CTRL = MT6351_PMIC_RG_VDRAM_MODE_CTRL, + PMIC_RG_VDRAM_ON_CTRL = MT6351_PMIC_RG_VDRAM_ON_CTRL, + PMIC_RG_VDRAM_SRCLK_MODE_SEL = MT6351_PMIC_RG_VDRAM_SRCLK_MODE_SEL, + PMIC_DA_QI_VDRAM_MODE = MT6351_PMIC_DA_QI_VDRAM_MODE, + PMIC_RG_VDRAM_STBTD = MT6351_PMIC_RG_VDRAM_STBTD, + PMIC_RG_VDRAM_SRCLK_EN_SEL = MT6351_PMIC_RG_VDRAM_SRCLK_EN_SEL, + PMIC_DA_QI_VDRAM_STB = MT6351_PMIC_DA_QI_VDRAM_STB, + PMIC_DA_QI_VDRAM_EN = MT6351_PMIC_DA_QI_VDRAM_EN, + PMIC_RG_VDRAM_OCFB_EN = MT6351_PMIC_RG_VDRAM_OCFB_EN, + PMIC_DA_QI_VDRAM_OCFB_EN = MT6351_PMIC_DA_QI_VDRAM_OCFB_EN, + PMIC_RG_VDRAM_DUMMY_LOAD_EN = MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_EN, + PMIC_RG_VDRAM_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_CTRL, + PMIC_RG_VDRAM_DUMMY_LOAD = MT6351_PMIC_RG_VDRAM_DUMMY_LOAD, + PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VDRAM_DUMMY_LOAD = MT6351_PMIC_DA_QI_VDRAM_DUMMY_LOAD, + PMIC_RG_VMIPI_MODE_SET = MT6351_PMIC_RG_VMIPI_MODE_SET, + PMIC_RG_VMIPI_EN = MT6351_PMIC_RG_VMIPI_EN, + PMIC_RG_VMIPI_MODE_CTRL = MT6351_PMIC_RG_VMIPI_MODE_CTRL, + PMIC_RG_VMIPI_ON_CTRL = MT6351_PMIC_RG_VMIPI_ON_CTRL, + PMIC_RG_VMIPI_SRCLK_MODE_SEL = MT6351_PMIC_RG_VMIPI_SRCLK_MODE_SEL, + PMIC_DA_QI_VMIPI_MODE = MT6351_PMIC_DA_QI_VMIPI_MODE, + PMIC_RG_VMIPI_STBTD = MT6351_PMIC_RG_VMIPI_STBTD, + PMIC_RG_VMIPI_SRCLK_EN_SEL = MT6351_PMIC_RG_VMIPI_SRCLK_EN_SEL, + PMIC_DA_QI_VMIPI_STB = MT6351_PMIC_DA_QI_VMIPI_STB, + PMIC_DA_QI_VMIPI_EN = MT6351_PMIC_DA_QI_VMIPI_EN, + PMIC_RG_VMIPI_OCFB_EN = MT6351_PMIC_RG_VMIPI_OCFB_EN, + PMIC_DA_QI_VMIPI_OCFB_EN = MT6351_PMIC_DA_QI_VMIPI_OCFB_EN, + PMIC_RG_VMIPI_DUMMY_LOAD_EN = MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_EN, + PMIC_RG_VMIPI_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_CTRL, + PMIC_RG_VMIPI_DUMMY_LOAD = MT6351_PMIC_RG_VMIPI_DUMMY_LOAD, + PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VMIPI_DUMMY_LOAD = MT6351_PMIC_DA_QI_VMIPI_DUMMY_LOAD, + PMIC_RG_VGP3_MODE_SET = MT6351_PMIC_RG_VGP3_MODE_SET, + PMIC_RG_VGP3_EN = MT6351_PMIC_RG_VGP3_EN, + PMIC_RG_VGP3_MODE_CTRL = MT6351_PMIC_RG_VGP3_MODE_CTRL, + PMIC_RG_VGP3_ON_CTRL = MT6351_PMIC_RG_VGP3_ON_CTRL, + PMIC_RG_VGP3_SRCLK_MODE_SEL = MT6351_PMIC_RG_VGP3_SRCLK_MODE_SEL, + PMIC_DA_QI_VGP3_MODE = MT6351_PMIC_DA_QI_VGP3_MODE, + PMIC_RG_VGP3_STBTD = MT6351_PMIC_RG_VGP3_STBTD, + PMIC_RG_VGP3_SRCLK_EN_SEL = MT6351_PMIC_RG_VGP3_SRCLK_EN_SEL, + PMIC_DA_QI_VGP3_STB = MT6351_PMIC_DA_QI_VGP3_STB, + PMIC_DA_QI_VGP3_EN = MT6351_PMIC_DA_QI_VGP3_EN, + PMIC_RG_VGP3_OCFB_EN = MT6351_PMIC_RG_VGP3_OCFB_EN, + PMIC_DA_QI_VGP3_OCFB_EN = MT6351_PMIC_DA_QI_VGP3_OCFB_EN, + PMIC_RG_VGP3_DUMMY_LOAD_EN = MT6351_PMIC_RG_VGP3_DUMMY_LOAD_EN, + PMIC_RG_VGP3_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VGP3_DUMMY_LOAD_CTRL, + PMIC_RG_VGP3_DUMMY_LOAD = MT6351_PMIC_RG_VGP3_DUMMY_LOAD, + PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VGP3_DUMMY_LOAD = MT6351_PMIC_DA_QI_VGP3_DUMMY_LOAD, + PMIC_RG_VBIF28_MODE_SET = MT6351_PMIC_RG_VBIF28_MODE_SET, + PMIC_RG_VBIF28_EN = MT6351_PMIC_RG_VBIF28_EN, + PMIC_RG_VBIF28_MODE_CTRL = MT6351_PMIC_RG_VBIF28_MODE_CTRL, + PMIC_RG_VBIF28_ON_CTRL = MT6351_PMIC_RG_VBIF28_ON_CTRL, + PMIC_RG_VBIF28_SRCLK_MODE_SEL = MT6351_PMIC_RG_VBIF28_SRCLK_MODE_SEL, + PMIC_DA_QI_VBIF28_MODE = MT6351_PMIC_DA_QI_VBIF28_MODE, + PMIC_RG_VBIF28_STBTD = MT6351_PMIC_RG_VBIF28_STBTD, + PMIC_RG_VBIF28_SRCLK_EN_SEL = MT6351_PMIC_RG_VBIF28_SRCLK_EN_SEL, + PMIC_DA_QI_VBIF28_STB = MT6351_PMIC_DA_QI_VBIF28_STB, + PMIC_DA_QI_VBIF28_EN = MT6351_PMIC_DA_QI_VBIF28_EN, + PMIC_RG_VBIF28_OCFB_EN = MT6351_PMIC_RG_VBIF28_OCFB_EN, + PMIC_DA_QI_VBIF28_OCFB_EN = MT6351_PMIC_DA_QI_VBIF28_OCFB_EN, + PMIC_RG_VBIF28_DUMMY_LOAD_EN = MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_EN, + PMIC_RG_VBIF28_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_CTRL, + PMIC_RG_VBIF28_DUMMY_LOAD = MT6351_PMIC_RG_VBIF28_DUMMY_LOAD, + PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VBIF28_DUMMY_LOAD = MT6351_PMIC_DA_QI_VBIF28_DUMMY_LOAD, + PMIC_RG_VEFUSE_MODE_SET = MT6351_PMIC_RG_VEFUSE_MODE_SET, + PMIC_RG_VEFUSE_EN = MT6351_PMIC_RG_VEFUSE_EN, + PMIC_RG_VEFUSE_MODE_CTRL = MT6351_PMIC_RG_VEFUSE_MODE_CTRL, + PMIC_RG_VEFUSE_SRCLK_MODE_SEL = MT6351_PMIC_RG_VEFUSE_SRCLK_MODE_SEL, + PMIC_DA_QI_VEFUSE_MODE = MT6351_PMIC_DA_QI_VEFUSE_MODE, + PMIC_RG_VEFUSE_STBTD = MT6351_PMIC_RG_VEFUSE_STBTD, + PMIC_DA_QI_VEFUSE_STB = MT6351_PMIC_DA_QI_VEFUSE_STB, + PMIC_DA_QI_VEFUSE_EN = MT6351_PMIC_DA_QI_VEFUSE_EN, + PMIC_RG_VEFUSE_OCFB_EN = MT6351_PMIC_RG_VEFUSE_OCFB_EN, + PMIC_DA_QI_VEFUSE_OCFB_EN = MT6351_PMIC_DA_QI_VEFUSE_OCFB_EN, + PMIC_RG_VEFUSE_DUMMY_LOAD_EN = MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_EN, + PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL, + PMIC_RG_VEFUSE_DUMMY_LOAD = MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD, + PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VEFUSE_DUMMY_LOAD = MT6351_PMIC_DA_QI_VEFUSE_DUMMY_LOAD, + PMIC_RG_VCN33_MODE_SET = MT6351_PMIC_RG_VCN33_MODE_SET, + PMIC_RG_VCN33_MODE_CTRL = MT6351_PMIC_RG_VCN33_MODE_CTRL, + PMIC_RG_VCN33_SRCLK_MODE_SEL = MT6351_PMIC_RG_VCN33_SRCLK_MODE_SEL, + PMIC_DA_QI_VCN33_MODE = MT6351_PMIC_DA_QI_VCN33_MODE, + PMIC_RG_VCN33_STBTD = MT6351_PMIC_RG_VCN33_STBTD, + PMIC_DA_QI_VCN33_STB = MT6351_PMIC_DA_QI_VCN33_STB, + PMIC_DA_QI_VCN33_EN = MT6351_PMIC_DA_QI_VCN33_EN, + PMIC_RG_VCN33_OCFB_EN = MT6351_PMIC_RG_VCN33_OCFB_EN, + PMIC_DA_QI_VCN33_OCFB_EN = MT6351_PMIC_DA_QI_VCN33_OCFB_EN, + PMIC_RG_VCN33_DUMMY_LOAD_EN = MT6351_PMIC_RG_VCN33_DUMMY_LOAD_EN, + PMIC_RG_VCN33_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VCN33_DUMMY_LOAD_CTRL, + PMIC_RG_VCN33_DUMMY_LOAD = MT6351_PMIC_RG_VCN33_DUMMY_LOAD, + PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VCN33_DUMMY_LOAD = MT6351_PMIC_DA_QI_VCN33_DUMMY_LOAD, + PMIC_RG_VCN33_EN_BT = MT6351_PMIC_RG_VCN33_EN_BT, + PMIC_RG_VCN33_ON_CTRL_BT = MT6351_PMIC_RG_VCN33_ON_CTRL_BT, + PMIC_RG_VCN33_SRCLK_EN_SEL_BT = MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_BT, + PMIC_RG_VCN33_EN_WIFI = MT6351_PMIC_RG_VCN33_EN_WIFI, + PMIC_RG_VCN33_ON_CTRL_WIFI = MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI, + PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI = MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI, + PMIC_RG_VLDO28_MODE_SET = MT6351_PMIC_RG_VLDO28_MODE_SET, + PMIC_RG_VLDO28_MODE_CTRL = MT6351_PMIC_RG_VLDO28_MODE_CTRL, + PMIC_RG_VLDO28_ON_CTRL = MT6351_PMIC_RG_VLDO28_ON_CTRL, + PMIC_RG_VLDO28_SRCLK_MODE_SEL = MT6351_PMIC_RG_VLDO28_SRCLK_MODE_SEL, + PMIC_DA_QI_VLDO28_MODE = MT6351_PMIC_DA_QI_VLDO28_MODE, + PMIC_RG_VLDO28_STBTD = MT6351_PMIC_RG_VLDO28_STBTD, + PMIC_DA_QI_VLDO28_STB = MT6351_PMIC_DA_QI_VLDO28_STB, + PMIC_DA_QI_VLDO28_EN = MT6351_PMIC_DA_QI_VLDO28_EN, + PMIC_RG_VLDO28_OCFB_EN = MT6351_PMIC_RG_VLDO28_OCFB_EN, + PMIC_DA_QI_VLDO28_OCFB_EN = MT6351_PMIC_DA_QI_VLDO28_OCFB_EN, + PMIC_RG_VLDO28_DUMMY_LOAD_EN = MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_EN, + PMIC_RG_VLDO28_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_CTRL, + PMIC_RG_VLDO28_DUMMY_LOAD = MT6351_PMIC_RG_VLDO28_DUMMY_LOAD, + PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VLDO28_DUMMY_LOAD = MT6351_PMIC_DA_QI_VLDO28_DUMMY_LOAD, + PMIC_RG_VLDO28_EN_0 = MT6351_PMIC_RG_VLDO28_EN_0, + PMIC_RG_VLDO28_ON_CTRL_0 = MT6351_PMIC_RG_VLDO28_ON_CTRL_0, + PMIC_RG_VLDO28_SRCLK_EN_SEL_0 = MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_0, + PMIC_RG_VLDO28_EN_1 = MT6351_PMIC_RG_VLDO28_EN_1, + PMIC_RG_VLDO28_ON_CTRL_1 = MT6351_PMIC_RG_VLDO28_ON_CTRL_1, + PMIC_RG_VLDO28_SRCLK_EN_SEL_1 = MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_1, + PMIC_RG_LDO_RSV1 = MT6351_PMIC_RG_LDO_RSV1, + PMIC_RG_LDO_RSV0 = MT6351_PMIC_RG_LDO_RSV0, + PMIC_RG_LDO_RSV2 = MT6351_PMIC_RG_LDO_RSV2, + PMIC_RG_VMC_MODE_SET = MT6351_PMIC_RG_VMC_MODE_SET, + PMIC_RG_VMC_EN = MT6351_PMIC_RG_VMC_EN, + PMIC_RG_VMC_MODE_CTRL = MT6351_PMIC_RG_VMC_MODE_CTRL, + PMIC_RG_VMC_ON_CTRL = MT6351_PMIC_RG_VMC_ON_CTRL, + PMIC_RG_VMC_SRCLK_MODE_SEL = MT6351_PMIC_RG_VMC_SRCLK_MODE_SEL, + PMIC_DA_QI_VMC_MODE = MT6351_PMIC_DA_QI_VMC_MODE, + PMIC_RG_VMC_STBTD = MT6351_PMIC_RG_VMC_STBTD, + PMIC_RG_VMC_SRCLK_EN_SEL = MT6351_PMIC_RG_VMC_SRCLK_EN_SEL, + PMIC_DA_QI_VMC_STB = MT6351_PMIC_DA_QI_VMC_STB, + PMIC_DA_QI_VMC_EN = MT6351_PMIC_DA_QI_VMC_EN, + PMIC_RG_VMC_OCFB_EN = MT6351_PMIC_RG_VMC_OCFB_EN, + PMIC_DA_QI_VMC_OCFB_EN = MT6351_PMIC_DA_QI_VMC_OCFB_EN, + PMIC_RG_VMC_DUMMY_LOAD_EN = MT6351_PMIC_RG_VMC_DUMMY_LOAD_EN, + PMIC_RG_VMC_DUMMY_LOAD_CTRL = MT6351_PMIC_RG_VMC_DUMMY_LOAD_CTRL, + PMIC_RG_VMC_DUMMY_LOAD = MT6351_PMIC_RG_VMC_DUMMY_LOAD, + PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL = MT6351_PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL, + PMIC_DA_QI_VMC_DUMMY_LOAD = MT6351_PMIC_DA_QI_VMC_DUMMY_LOAD, + PMIC_RG_VMC_TRANS_EN = MT6351_PMIC_RG_VMC_TRANS_EN, + PMIC_RG_VMC_TRANS_CTRL = MT6351_PMIC_RG_VMC_TRANS_CTRL, + PMIC_RG_VMC_TRANS_ONCE = MT6351_PMIC_RG_VMC_TRANS_ONCE, + PMIC_RG_VMC_INT_DIS_SEL = MT6351_PMIC_RG_VMC_INT_DIS_SEL, + PMIC_DA_QI_VMC_INT_DIS = MT6351_PMIC_DA_QI_VMC_INT_DIS, + PMIC_RG_LDO_MANUAL_OFS_SEL = MT6351_PMIC_RG_LDO_MANUAL_OFS_SEL, + PMIC_RG_LDO_MANUAL_OFS_EN = MT6351_PMIC_RG_LDO_MANUAL_OFS_EN, + PMIC_RG_LDO_CALI_RSV = MT6351_PMIC_RG_LDO_CALI_RSV, + PMIC_RG_LDO_CALI_MODE_SEL = MT6351_PMIC_RG_LDO_CALI_MODE_SEL, + PMIC_RG_LDO_MANUAL_MODE = MT6351_PMIC_RG_LDO_MANUAL_MODE, + PMIC_RG_LDO_AUTO_START = MT6351_PMIC_RG_LDO_AUTO_START, + PMIC_RG_LDO_CALI_CLR = MT6351_PMIC_RG_LDO_CALI_CLR, + PMIC_LDO_CALI_INC_COUNT = MT6351_PMIC_LDO_CALI_INC_COUNT, + PMIC_LDO_K_START = MT6351_PMIC_LDO_K_START, + PMIC_LDO_CALI_DONE = MT6351_PMIC_LDO_CALI_DONE, + PMIC_LDO_CALI_CNT = MT6351_PMIC_LDO_CALI_CNT, + PMIC_LDO_CALI_EFUSE_EN = MT6351_PMIC_LDO_CALI_EFUSE_EN, + PMIC_DA_QI_VIO18_OFS_CAL_EN = MT6351_PMIC_DA_QI_VIO18_OFS_CAL_EN, + PMIC_AD_QI_VIO18_CAL_INDI = MT6351_PMIC_AD_QI_VIO18_CAL_INDI, + PMIC_DA_QI_VIO18_OFS_SEL = MT6351_PMIC_DA_QI_VIO18_OFS_SEL, + PMIC_LDO_DEGTD_SEL = MT6351_PMIC_LDO_DEGTD_SEL, + PMIC_RG_VRTC_EN = MT6351_PMIC_RG_VRTC_EN, + PMIC_DA_QI_VRTC_EN = MT6351_PMIC_DA_QI_VRTC_EN, + PMIC_RG_ALDO_RESEV = MT6351_PMIC_RG_ALDO_RESEV, + PMIC_RG_DLDO_RESEV = MT6351_PMIC_RG_DLDO_RESEV, + PMIC_RG_SLDO_RESEV195 = MT6351_PMIC_RG_SLDO_RESEV195, + PMIC_RG_SLDO_2_RESEV195 = MT6351_PMIC_RG_SLDO_2_RESEV195, + PMIC_RG_SLDO_RESEV135 = MT6351_PMIC_RG_SLDO_RESEV135, + PMIC_RG_SLDO_2_RESEV135 = MT6351_PMIC_RG_SLDO_2_RESEV135, + PMIC_RG_VXO22_CAL = MT6351_PMIC_RG_VXO22_CAL, + PMIC_RG_VXO22_VOSEL = MT6351_PMIC_RG_VXO22_VOSEL, + PMIC_RG_VXO22_NDIS_EN = MT6351_PMIC_RG_VXO22_NDIS_EN, + PMIC_RG_VTCXO28_CAL = MT6351_PMIC_RG_VTCXO28_CAL, + PMIC_RG_VTCXO28_VOSEL = MT6351_PMIC_RG_VTCXO28_VOSEL, + PMIC_RG_VTCXO28_NDIS_EN = MT6351_PMIC_RG_VTCXO28_NDIS_EN, + PMIC_RG_VTCXO24_CAL = MT6351_PMIC_RG_VTCXO24_CAL, + PMIC_RG_VTCXO24_VOSEL = MT6351_PMIC_RG_VTCXO24_VOSEL, + PMIC_RG_VTCXO24_NDIS_EN = MT6351_PMIC_RG_VTCXO24_NDIS_EN, + PMIC_RG_VBIF28_CAL = MT6351_PMIC_RG_VBIF28_CAL, + PMIC_RG_VBIF28_VOSEL = MT6351_PMIC_RG_VBIF28_VOSEL, + PMIC_RG_VBIF28_NDIS_EN = MT6351_PMIC_RG_VBIF28_NDIS_EN, + PMIC_RG_VCN28_CAL = MT6351_PMIC_RG_VCN28_CAL, + PMIC_RG_VCN28_VOSEL = MT6351_PMIC_RG_VCN28_VOSEL, + PMIC_RG_VCN28_NDIS_EN = MT6351_PMIC_RG_VCN28_NDIS_EN, + PMIC_RG_VMCH_CAL = MT6351_PMIC_RG_VMCH_CAL, + PMIC_RG_VMCH_VOSEL = MT6351_PMIC_RG_VMCH_VOSEL, + PMIC_RG_VMCH_NDIS_EN = MT6351_PMIC_RG_VMCH_NDIS_EN, + PMIC_RG_VMCH_OC_TRIM = MT6351_PMIC_RG_VMCH_OC_TRIM, + PMIC_RG_VMCH_N2LP_EHC_V18 = MT6351_PMIC_RG_VMCH_N2LP_EHC_V18, + PMIC_RG_VEMC_CAL = MT6351_PMIC_RG_VEMC_CAL, + PMIC_RG_VEMC_VOSEL = MT6351_PMIC_RG_VEMC_VOSEL, + PMIC_RG_VEMC_NDIS_EN = MT6351_PMIC_RG_VEMC_NDIS_EN, + PMIC_RG_VEMC_OC_TRIM = MT6351_PMIC_RG_VEMC_OC_TRIM, + PMIC_RG_VEMC_N2LP_EHC_V18 = MT6351_PMIC_RG_VEMC_N2LP_EHC_V18, + PMIC_RG_VCAMA_CAL = MT6351_PMIC_RG_VCAMA_CAL, + PMIC_RG_VCAMA_VOSEL = MT6351_PMIC_RG_VCAMA_VOSEL, + PMIC_RG_VCAMA_NDIS_EN = MT6351_PMIC_RG_VCAMA_NDIS_EN, + PMIC_RG_VCAMA_FBSEL = MT6351_PMIC_RG_VCAMA_FBSEL, + PMIC_RG_VCN33_CAL = MT6351_PMIC_RG_VCN33_CAL, + PMIC_RG_VCN33_VOSEL = MT6351_PMIC_RG_VCN33_VOSEL, + PMIC_RG_VCN33_NDIS_EN = MT6351_PMIC_RG_VCN33_NDIS_EN, + PMIC_RG_VCN33_N2LP_EHC_V18 = MT6351_PMIC_RG_VCN33_N2LP_EHC_V18, + PMIC_RG_VIO28_CAL = MT6351_PMIC_RG_VIO28_CAL, + PMIC_RG_VIO28_VOSEL = MT6351_PMIC_RG_VIO28_VOSEL, + PMIC_RG_VIO28_NDIS_EN = MT6351_PMIC_RG_VIO28_NDIS_EN, + PMIC_RG_VIO28_LP_HIGH_SPEED_ENB = MT6351_PMIC_RG_VIO28_LP_HIGH_SPEED_ENB, + PMIC_RG_VMC_CAL = MT6351_PMIC_RG_VMC_CAL, + PMIC_RG_VMC_VOSEL = MT6351_PMIC_RG_VMC_VOSEL, + PMIC_RG_VMC_NDIS_EN = MT6351_PMIC_RG_VMC_NDIS_EN, + PMIC_RG_VMC_LP_HIGH_SPEED_ENB = MT6351_PMIC_RG_VMC_LP_HIGH_SPEED_ENB, + PMIC_RG_VIBR_CAL = MT6351_PMIC_RG_VIBR_CAL, + PMIC_RG_VIBR_VOSEL = MT6351_PMIC_RG_VIBR_VOSEL, + PMIC_RG_VIBR_NDIS_EN = MT6351_PMIC_RG_VIBR_NDIS_EN, + PMIC_RG_VIBR_LP_HIGH_SPEED_ENB = MT6351_PMIC_RG_VIBR_LP_HIGH_SPEED_ENB, + PMIC_RG_VUSB33_CAL = MT6351_PMIC_RG_VUSB33_CAL, + PMIC_RG_VUSB33_NDIS_EN = MT6351_PMIC_RG_VUSB33_NDIS_EN, + PMIC_RG_VUSB33_OC_TRIM = MT6351_PMIC_RG_VUSB33_OC_TRIM, + PMIC_RG_VSIM1_CAL = MT6351_PMIC_RG_VSIM1_CAL, + PMIC_RG_VSIM1_VOSEL = MT6351_PMIC_RG_VSIM1_VOSEL, + PMIC_RG_VSIM1_NDIS_EN = MT6351_PMIC_RG_VSIM1_NDIS_EN, + PMIC_RG_VSIM1_STB_CAL = MT6351_PMIC_RG_VSIM1_STB_CAL, + PMIC_RG_VSIM1_STB_SEL = MT6351_PMIC_RG_VSIM1_STB_SEL, + PMIC_RG_VSIM1_OC_TRIM = MT6351_PMIC_RG_VSIM1_OC_TRIM, + PMIC_RG_VSIM1_NDIS_EN_INT = MT6351_PMIC_RG_VSIM1_NDIS_EN_INT, + PMIC_RG_EFUSE_SIM1_MODE = MT6351_PMIC_RG_EFUSE_SIM1_MODE, + PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB = MT6351_PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB, + PMIC_RG_VSIM2_CAL = MT6351_PMIC_RG_VSIM2_CAL, + PMIC_RG_VSIM2_VOSEL = MT6351_PMIC_RG_VSIM2_VOSEL, + PMIC_RG_VSIM2_NDIS_EN = MT6351_PMIC_RG_VSIM2_NDIS_EN, + PMIC_RG_VSIM2_STB_CAL = MT6351_PMIC_RG_VSIM2_STB_CAL, + PMIC_RG_VSIM2_STB_SEL = MT6351_PMIC_RG_VSIM2_STB_SEL, + PMIC_RG_VSIM2_OC_TRIM = MT6351_PMIC_RG_VSIM2_OC_TRIM, + PMIC_RG_VSIM2_NDIS_EN_INT = MT6351_PMIC_RG_VSIM2_NDIS_EN_INT, + PMIC_RG_EFUSE_VSIM2_MODE = MT6351_PMIC_RG_EFUSE_VSIM2_MODE, + PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB = MT6351_PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB, + PMIC_RG_VEFUSE_CAL = MT6351_PMIC_RG_VEFUSE_CAL, + PMIC_RG_VEFUSE_VOSEL = MT6351_PMIC_RG_VEFUSE_VOSEL, + PMIC_RG_VEFUSE_NDIS_EN = MT6351_PMIC_RG_VEFUSE_NDIS_EN, + PMIC_RG_VEFUSE_STB_CAL = MT6351_PMIC_RG_VEFUSE_STB_CAL, + PMIC_RG_VEFUSE_STB_SEL = MT6351_PMIC_RG_VEFUSE_STB_SEL, + PMIC_RG_VEFUSE_OC_TRIM = MT6351_PMIC_RG_VEFUSE_OC_TRIM, + PMIC_RG_VEFUSE_NDIS_EN_INT = MT6351_PMIC_RG_VEFUSE_NDIS_EN_INT, + PMIC_RG_EFUSE_MODE_1 = MT6351_PMIC_RG_EFUSE_MODE_1, + PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB = MT6351_PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB, + PMIC_RG_VA18_CAL = MT6351_PMIC_RG_VA18_CAL, + PMIC_RG_VA18_VOSEL = MT6351_PMIC_RG_VA18_VOSEL, + PMIC_RG_VA18_NDIS_EN = MT6351_PMIC_RG_VA18_NDIS_EN, + PMIC_RG_VGP3_CAL = MT6351_PMIC_RG_VGP3_CAL, + PMIC_RG_VGP3_VOSEL = MT6351_PMIC_RG_VGP3_VOSEL, + PMIC_RG_VGP3_NDIS_EN = MT6351_PMIC_RG_VGP3_NDIS_EN, + PMIC_RG_VGP3_FT_DNMC_EN = MT6351_PMIC_RG_VGP3_FT_DNMC_EN, + PMIC_RG_VCAMD_CAL = MT6351_PMIC_RG_VCAMD_CAL, + PMIC_RG_VCAMD_VOSEL = MT6351_PMIC_RG_VCAMD_VOSEL, + PMIC_RG_VCAMD_NDIS_EN = MT6351_PMIC_RG_VCAMD_NDIS_EN, + PMIC_RG_VCAMD_RSV = MT6351_PMIC_RG_VCAMD_RSV, + PMIC_RG_VCAMD_OC_TRIM = MT6351_PMIC_RG_VCAMD_OC_TRIM, + PMIC_RG_VIO18_CAL = MT6351_PMIC_RG_VIO18_CAL, + PMIC_RG_VIO18_NDIS_EN = MT6351_PMIC_RG_VIO18_NDIS_EN, + PMIC_RG_VIO18_FT_DNMC_EN = MT6351_PMIC_RG_VIO18_FT_DNMC_EN, + PMIC_RG_VRF18_CAL = MT6351_PMIC_RG_VRF18_CAL, + PMIC_RG_VRF18_VOSEL = MT6351_PMIC_RG_VRF18_VOSEL, + PMIC_RG_VRF18_NDIS_EN = MT6351_PMIC_RG_VRF18_NDIS_EN, + PMIC_RG_VRF18_FT_DNMC_EN = MT6351_PMIC_RG_VRF18_FT_DNMC_EN, + PMIC_RG_VRF12_CAL = MT6351_PMIC_RG_VRF12_CAL, + PMIC_RG_VRF12_VOSEL = MT6351_PMIC_RG_VRF12_VOSEL, + PMIC_RG_VRF12_NDIS_EN = MT6351_PMIC_RG_VRF12_NDIS_EN, + PMIC_RG_VRF12_STB_SEL = MT6351_PMIC_RG_VRF12_STB_SEL, + PMIC_RG_VA10_CAL = MT6351_PMIC_RG_VA10_CAL, + PMIC_RG_VA10_VOSEL = MT6351_PMIC_RG_VA10_VOSEL, + PMIC_RG_VA10_NDIS_EN = MT6351_PMIC_RG_VA10_NDIS_EN, + PMIC_RG_VA10_STB_SEL = MT6351_PMIC_RG_VA10_STB_SEL, + PMIC_RG_VCAMIO_CAL = MT6351_PMIC_RG_VCAMIO_CAL, + PMIC_RG_VCAMIO_VOSEL = MT6351_PMIC_RG_VCAMIO_VOSEL, + PMIC_RG_VCAMIO_NDIS_EN = MT6351_PMIC_RG_VCAMIO_NDIS_EN, + PMIC_RG_VCAMIO_STB_SEL = MT6351_PMIC_RG_VCAMIO_STB_SEL, + PMIC_RG_VCN18_CAL = MT6351_PMIC_RG_VCN18_CAL, + PMIC_RG_VCN18_VOSEL = MT6351_PMIC_RG_VCN18_VOSEL, + PMIC_RG_VCN18_NDIS_EN = MT6351_PMIC_RG_VCN18_NDIS_EN, + PMIC_RG_VCN18_STB_SEL = MT6351_PMIC_RG_VCN18_STB_SEL, + PMIC_RG_VMIPI_CAL = MT6351_PMIC_RG_VMIPI_CAL, + PMIC_RG_VMIPI_VOSEL = MT6351_PMIC_RG_VMIPI_VOSEL, + PMIC_RG_VMIPI_NDIS_EN = MT6351_PMIC_RG_VMIPI_NDIS_EN, + PMIC_RG_VMIPI_STB_SEL = MT6351_PMIC_RG_VMIPI_STB_SEL, + PMIC_RG_VSRAM_PROC_NDIS_EN = MT6351_PMIC_RG_VSRAM_PROC_NDIS_EN, + PMIC_RG_VSRAM_PROC_NDIS_PLCUR = MT6351_PMIC_RG_VSRAM_PROC_NDIS_PLCUR, + PMIC_RG_VSRAM_PROC_STB_SEL = MT6351_PMIC_RG_VSRAM_PROC_STB_SEL, + PMIC_RG_VSRAM_PROC_PLCUR_EN = MT6351_PMIC_RG_VSRAM_PROC_PLCUR_EN, + PMIC_RG_VDRAM_CAL = MT6351_PMIC_RG_VDRAM_CAL, + PMIC_RG_VDRAM_VOSEL = MT6351_PMIC_RG_VDRAM_VOSEL, + PMIC_RG_VDRAM_NDIS_EN = MT6351_PMIC_RG_VDRAM_NDIS_EN, + PMIC_RG_VDRAM_RSV = MT6351_PMIC_RG_VDRAM_RSV, + PMIC_RG_VDRAM_OC_TRIM = MT6351_PMIC_RG_VDRAM_OC_TRIM, + PMIC_RG_VLDO28_CAL = MT6351_PMIC_RG_VLDO28_CAL, + PMIC_RG_VLDO28_NDIS_EN = MT6351_PMIC_RG_VLDO28_NDIS_EN, + PMIC_RG_VLDO28_OC_TRIM = MT6351_PMIC_RG_VLDO28_OC_TRIM, + PMIC_RG_VLDO28_N2LP_EHC_V18 = MT6351_PMIC_RG_VLDO28_N2LP_EHC_V18, + PMIC_BIF_COMMAND_0 = MT6351_PMIC_BIF_COMMAND_0, + PMIC_BIF_COMMAND_1 = MT6351_PMIC_BIF_COMMAND_1, + PMIC_BIF_COMMAND_2 = MT6351_PMIC_BIF_COMMAND_2, + PMIC_BIF_COMMAND_3 = MT6351_PMIC_BIF_COMMAND_3, + PMIC_BIF_COMMAND_4 = MT6351_PMIC_BIF_COMMAND_4, + PMIC_BIF_COMMAND_5 = MT6351_PMIC_BIF_COMMAND_5, + PMIC_BIF_COMMAND_6 = MT6351_PMIC_BIF_COMMAND_6, + PMIC_BIF_COMMAND_7 = MT6351_PMIC_BIF_COMMAND_7, + PMIC_BIF_COMMAND_8 = MT6351_PMIC_BIF_COMMAND_8, + PMIC_BIF_COMMAND_9 = MT6351_PMIC_BIF_COMMAND_9, + PMIC_BIF_COMMAND_10 = MT6351_PMIC_BIF_COMMAND_10, + PMIC_BIF_COMMAND_11 = MT6351_PMIC_BIF_COMMAND_11, + PMIC_BIF_COMMAND_12 = MT6351_PMIC_BIF_COMMAND_12, + PMIC_BIF_COMMAND_13 = MT6351_PMIC_BIF_COMMAND_13, + PMIC_BIF_COMMAND_14 = MT6351_PMIC_BIF_COMMAND_14, + PMIC_BIF_RSV = MT6351_PMIC_BIF_RSV, + PMIC_BIF_COMMAND_TYPE = MT6351_PMIC_BIF_COMMAND_TYPE, + PMIC_BIF_TRASFER_NUM = MT6351_PMIC_BIF_TRASFER_NUM, + PMIC_BIF_LOGIC_0_SET = MT6351_PMIC_BIF_LOGIC_0_SET, + PMIC_BIF_LOGIC_1_SET = MT6351_PMIC_BIF_LOGIC_1_SET, + PMIC_BIF_STOP_SET = MT6351_PMIC_BIF_STOP_SET, + PMIC_BIF_DEBOUNCE_WND = MT6351_PMIC_BIF_DEBOUNCE_WND, + PMIC_BIF_DEBOUNCE_THD = MT6351_PMIC_BIF_DEBOUNCE_THD, + PMIC_BIF_DEBOUNCE_EN = MT6351_PMIC_BIF_DEBOUNCE_EN, + PMIC_BIF_READ_EXPECT_NUM = MT6351_PMIC_BIF_READ_EXPECT_NUM, + PMIC_BIF_TRASACT_TRIGGER = MT6351_PMIC_BIF_TRASACT_TRIGGER, + PMIC_BIF_DATA_NUM = MT6351_PMIC_BIF_DATA_NUM, + PMIC_BIF_RESPONSE = MT6351_PMIC_BIF_RESPONSE, + PMIC_BIF_DATA_0 = MT6351_PMIC_BIF_DATA_0, + PMIC_BIF_ACK_0 = MT6351_PMIC_BIF_ACK_0, + PMIC_BIF_ERROR_0 = MT6351_PMIC_BIF_ERROR_0, + PMIC_BIF_DATA_1 = MT6351_PMIC_BIF_DATA_1, + PMIC_BIF_ACK_1 = MT6351_PMIC_BIF_ACK_1, + PMIC_BIF_ERROR_1 = MT6351_PMIC_BIF_ERROR_1, + PMIC_BIF_DATA_2 = MT6351_PMIC_BIF_DATA_2, + PMIC_BIF_ACK_2 = MT6351_PMIC_BIF_ACK_2, + PMIC_BIF_ERROR_2 = MT6351_PMIC_BIF_ERROR_2, + PMIC_BIF_DATA_3 = MT6351_PMIC_BIF_DATA_3, + PMIC_BIF_ACK_3 = MT6351_PMIC_BIF_ACK_3, + PMIC_BIF_ERROR_3 = MT6351_PMIC_BIF_ERROR_3, + PMIC_BIF_DATA_4 = MT6351_PMIC_BIF_DATA_4, + PMIC_BIF_ACK_4 = MT6351_PMIC_BIF_ACK_4, + PMIC_BIF_ERROR_4 = MT6351_PMIC_BIF_ERROR_4, + PMIC_BIF_DATA_5 = MT6351_PMIC_BIF_DATA_5, + PMIC_BIF_ACK_5 = MT6351_PMIC_BIF_ACK_5, + PMIC_BIF_ERROR_5 = MT6351_PMIC_BIF_ERROR_5, + PMIC_BIF_DATA_6 = MT6351_PMIC_BIF_DATA_6, + PMIC_BIF_ACK_6 = MT6351_PMIC_BIF_ACK_6, + PMIC_BIF_ERROR_6 = MT6351_PMIC_BIF_ERROR_6, + PMIC_BIF_DATA_7 = MT6351_PMIC_BIF_DATA_7, + PMIC_BIF_ACK_7 = MT6351_PMIC_BIF_ACK_7, + PMIC_BIF_ERROR_7 = MT6351_PMIC_BIF_ERROR_7, + PMIC_BIF_DATA_8 = MT6351_PMIC_BIF_DATA_8, + PMIC_BIF_ACK_8 = MT6351_PMIC_BIF_ACK_8, + PMIC_BIF_ERROR_8 = MT6351_PMIC_BIF_ERROR_8, + PMIC_BIF_DATA_9 = MT6351_PMIC_BIF_DATA_9, + PMIC_BIF_ACK_9 = MT6351_PMIC_BIF_ACK_9, + PMIC_BIF_ERROR_9 = MT6351_PMIC_BIF_ERROR_9, + PMIC_BIF_TEST_MODE0 = MT6351_PMIC_BIF_TEST_MODE0, + PMIC_BIF_TEST_MODE1 = MT6351_PMIC_BIF_TEST_MODE1, + PMIC_BIF_TEST_MODE2 = MT6351_PMIC_BIF_TEST_MODE2, + PMIC_BIF_TEST_MODE3 = MT6351_PMIC_BIF_TEST_MODE3, + PMIC_BIF_TEST_MODE4 = MT6351_PMIC_BIF_TEST_MODE4, + PMIC_BIF_TEST_MODE5 = MT6351_PMIC_BIF_TEST_MODE5, + PMIC_BIF_TEST_MODE6 = MT6351_PMIC_BIF_TEST_MODE6, + PMIC_BIF_TEST_MODE7 = MT6351_PMIC_BIF_TEST_MODE7, + PMIC_BIF_TEST_MODE8 = MT6351_PMIC_BIF_TEST_MODE8, + PMIC_BIF_BAT_LOST_SW = MT6351_PMIC_BIF_BAT_LOST_SW, + PMIC_BIF_RX_DATA_SW = MT6351_PMIC_BIF_RX_DATA_SW, + PMIC_BIF_TX_DATA_SW = MT6351_PMIC_BIF_TX_DATA_SW, + PMIC_BIF_RX_EN_SW = MT6351_PMIC_BIF_RX_EN_SW, + PMIC_BIF_TX_EN_SW = MT6351_PMIC_BIF_TX_EN_SW, + PMIC_BIF_BACK_NORMAL = MT6351_PMIC_BIF_BACK_NORMAL, + PMIC_BIF_IRQ_CLR = MT6351_PMIC_BIF_IRQ_CLR, + PMIC_BIF_BAT_LOST_GATED = MT6351_PMIC_BIF_BAT_LOST_GATED, + PMIC_BIF_IRQ = MT6351_PMIC_BIF_IRQ, + PMIC_BIF_TIMEOUT = MT6351_PMIC_BIF_TIMEOUT, + PMIC_BIF_BAT_LOST = MT6351_PMIC_BIF_BAT_LOST, + PMIC_BIF_TOTAL_VALID = MT6351_PMIC_BIF_TOTAL_VALID, + PMIC_BIF_BUS_STATUS = MT6351_PMIC_BIF_BUS_STATUS, + PMIC_BIF_POWER_UP_COUNT = MT6351_PMIC_BIF_POWER_UP_COUNT, + PMIC_BIF_POWER_UP = MT6351_PMIC_BIF_POWER_UP, + PMIC_BIF_RX_ERROR_UNKNOWN = MT6351_PMIC_BIF_RX_ERROR_UNKNOWN, + PMIC_BIF_RX_ERROR_INSUFF = MT6351_PMIC_BIF_RX_ERROR_INSUFF, + PMIC_BIF_RX_ERROR_LOWPHASE = MT6351_PMIC_BIF_RX_ERROR_LOWPHASE, + PMIC_BIF_RX_STATE = MT6351_PMIC_BIF_RX_STATE, + PMIC_BIF_FLOW_CTL_STATE = MT6351_PMIC_BIF_FLOW_CTL_STATE, + PMIC_BIF_TX_STATE = MT6351_PMIC_BIF_TX_STATE, + PMIC_AD_QI_BIF_RX_DATA = MT6351_PMIC_AD_QI_BIF_RX_DATA, + PMIC_DA_QI_BIF_RX_EN = MT6351_PMIC_DA_QI_BIF_RX_EN, + PMIC_DA_QI_BIF_TX_DATA = MT6351_PMIC_DA_QI_BIF_TX_DATA, + PMIC_DA_QI_BIF_TX_EN = MT6351_PMIC_DA_QI_BIF_TX_EN, + PMIC_BIF_TX_DATA_FIANL = MT6351_PMIC_BIF_TX_DATA_FIANL, + PMIC_BIF_RX_DATA_SAMPLING = MT6351_PMIC_BIF_RX_DATA_SAMPLING, + PMIC_BIF_RX_DATA_RECOVERY = MT6351_PMIC_BIF_RX_DATA_RECOVERY, + PMIC_RG_BATON_HT_EN = MT6351_PMIC_RG_BATON_HT_EN, + PMIC_RG_BATON_HT_EN_DLY_TIME = MT6351_PMIC_RG_BATON_HT_EN_DLY_TIME, + PMIC_DA_QI_BATON_HT_EN = MT6351_PMIC_DA_QI_BATON_HT_EN, + PMIC_BIF_TIMEOUT_SET = MT6351_PMIC_BIF_TIMEOUT_SET, + PMIC_BIF_RX_DEG_WND = MT6351_PMIC_BIF_RX_DEG_WND, + PMIC_BIF_RX_DEG_EN = MT6351_PMIC_BIF_RX_DEG_EN, + PMIC_BIF_RSV1 = MT6351_PMIC_BIF_RSV1, + PMIC_BIF_RSV0 = MT6351_PMIC_BIF_RSV0, + PMIC_RG_OTP_PA = MT6351_PMIC_RG_OTP_PA, + PMIC_RG_OTP_PDIN = MT6351_PMIC_RG_OTP_PDIN, + PMIC_RG_OTP_PTM = MT6351_PMIC_RG_OTP_PTM, + PMIC_RG_OTP_PWE = MT6351_PMIC_RG_OTP_PWE, + PMIC_RG_OTP_PPROG = MT6351_PMIC_RG_OTP_PPROG, + PMIC_RG_OTP_PWE_SRC = MT6351_PMIC_RG_OTP_PWE_SRC, + PMIC_RG_OTP_PROG_PKEY = MT6351_PMIC_RG_OTP_PROG_PKEY, + PMIC_RG_OTP_RD_PKEY = MT6351_PMIC_RG_OTP_RD_PKEY, + PMIC_RG_OTP_RD_TRIG = MT6351_PMIC_RG_OTP_RD_TRIG, + PMIC_RG_RD_RDY_BYPASS = MT6351_PMIC_RG_RD_RDY_BYPASS, + PMIC_RG_SKIP_OTP_OUT = MT6351_PMIC_RG_SKIP_OTP_OUT, + PMIC_RG_OTP_RD_SW = MT6351_PMIC_RG_OTP_RD_SW, + PMIC_RG_OTP_DOUT_SW = MT6351_PMIC_RG_OTP_DOUT_SW, + PMIC_RG_OTP_RD_BUSY = MT6351_PMIC_RG_OTP_RD_BUSY, + PMIC_RG_OTP_RD_ACK = MT6351_PMIC_RG_OTP_RD_ACK, + PMIC_RG_OTP_PA_SW = MT6351_PMIC_RG_OTP_PA_SW, + PMIC_RG_OTP_DOUT_0_15 = MT6351_PMIC_RG_OTP_DOUT_0_15, + PMIC_RG_OTP_DOUT_16_31 = MT6351_PMIC_RG_OTP_DOUT_16_31, + PMIC_RG_OTP_DOUT_32_47 = MT6351_PMIC_RG_OTP_DOUT_32_47, + PMIC_RG_OTP_DOUT_48_63 = MT6351_PMIC_RG_OTP_DOUT_48_63, + PMIC_RG_OTP_DOUT_64_79 = MT6351_PMIC_RG_OTP_DOUT_64_79, + PMIC_RG_OTP_DOUT_80_95 = MT6351_PMIC_RG_OTP_DOUT_80_95, + PMIC_RG_OTP_DOUT_96_111 = MT6351_PMIC_RG_OTP_DOUT_96_111, + PMIC_RG_OTP_DOUT_112_127 = MT6351_PMIC_RG_OTP_DOUT_112_127, + PMIC_RG_OTP_DOUT_128_143 = MT6351_PMIC_RG_OTP_DOUT_128_143, + PMIC_RG_OTP_DOUT_144_159 = MT6351_PMIC_RG_OTP_DOUT_144_159, + PMIC_RG_OTP_DOUT_160_175 = MT6351_PMIC_RG_OTP_DOUT_160_175, + PMIC_RG_OTP_DOUT_176_191 = MT6351_PMIC_RG_OTP_DOUT_176_191, + PMIC_RG_OTP_DOUT_192_207 = MT6351_PMIC_RG_OTP_DOUT_192_207, + PMIC_RG_OTP_DOUT_208_223 = MT6351_PMIC_RG_OTP_DOUT_208_223, + PMIC_RG_OTP_DOUT_224_239 = MT6351_PMIC_RG_OTP_DOUT_224_239, + PMIC_RG_OTP_DOUT_240_255 = MT6351_PMIC_RG_OTP_DOUT_240_255, + PMIC_RG_OTP_DOUT_256_271 = MT6351_PMIC_RG_OTP_DOUT_256_271, + PMIC_RG_OTP_DOUT_272_287 = MT6351_PMIC_RG_OTP_DOUT_272_287, + PMIC_RG_OTP_DOUT_288_303 = MT6351_PMIC_RG_OTP_DOUT_288_303, + PMIC_RG_OTP_DOUT_304_319 = MT6351_PMIC_RG_OTP_DOUT_304_319, + PMIC_RG_OTP_DOUT_320_335 = MT6351_PMIC_RG_OTP_DOUT_320_335, + PMIC_RG_OTP_DOUT_336_351 = MT6351_PMIC_RG_OTP_DOUT_336_351, + PMIC_RG_OTP_DOUT_352_367 = MT6351_PMIC_RG_OTP_DOUT_352_367, + PMIC_RG_OTP_DOUT_368_383 = MT6351_PMIC_RG_OTP_DOUT_368_383, + PMIC_RG_OTP_DOUT_384_399 = MT6351_PMIC_RG_OTP_DOUT_384_399, + PMIC_RG_OTP_DOUT_400_415 = MT6351_PMIC_RG_OTP_DOUT_400_415, + PMIC_RG_OTP_DOUT_416_431 = MT6351_PMIC_RG_OTP_DOUT_416_431, + PMIC_RG_OTP_DOUT_432_447 = MT6351_PMIC_RG_OTP_DOUT_432_447, + PMIC_RG_OTP_DOUT_448_463 = MT6351_PMIC_RG_OTP_DOUT_448_463, + PMIC_RG_OTP_DOUT_464_479 = MT6351_PMIC_RG_OTP_DOUT_464_479, + PMIC_RG_OTP_DOUT_480_495 = MT6351_PMIC_RG_OTP_DOUT_480_495, + PMIC_RG_OTP_DOUT_496_511 = MT6351_PMIC_RG_OTP_DOUT_496_511, + PMIC_RG_OTP_VAL_0_15 = MT6351_PMIC_RG_OTP_VAL_0_15, + PMIC_RG_OTP_VAL_16_31 = MT6351_PMIC_RG_OTP_VAL_16_31, + PMIC_RG_OTP_VAL_32_47 = MT6351_PMIC_RG_OTP_VAL_32_47, + PMIC_RG_OTP_VAL_48_63 = MT6351_PMIC_RG_OTP_VAL_48_63, + PMIC_RG_OTP_VAL_64_79 = MT6351_PMIC_RG_OTP_VAL_64_79, + PMIC_RG_OTP_VAL_80_95 = MT6351_PMIC_RG_OTP_VAL_80_95, + PMIC_RG_OTP_VAL_96_111 = MT6351_PMIC_RG_OTP_VAL_96_111, + PMIC_RG_OTP_VAL_112_127 = MT6351_PMIC_RG_OTP_VAL_112_127, + PMIC_RG_OTP_VAL_128_143 = MT6351_PMIC_RG_OTP_VAL_128_143, + PMIC_RG_OTP_VAL_144_159 = MT6351_PMIC_RG_OTP_VAL_144_159, + PMIC_RG_OTP_VAL_160_175 = MT6351_PMIC_RG_OTP_VAL_160_175, + PMIC_RG_OTP_VAL_176_191 = MT6351_PMIC_RG_OTP_VAL_176_191, + PMIC_RG_OTP_VAL_192_207 = MT6351_PMIC_RG_OTP_VAL_192_207, + PMIC_RG_OTP_VAL_208_223 = MT6351_PMIC_RG_OTP_VAL_208_223, + PMIC_RG_OTP_VAL_224_239 = MT6351_PMIC_RG_OTP_VAL_224_239, + PMIC_RG_OTP_VAL_240_255 = MT6351_PMIC_RG_OTP_VAL_240_255, + PMIC_RG_OTP_VAL_256_271 = MT6351_PMIC_RG_OTP_VAL_256_271, + PMIC_RG_OTP_VAL_272_287 = MT6351_PMIC_RG_OTP_VAL_272_287, + PMIC_RG_OTP_VAL_288_303 = MT6351_PMIC_RG_OTP_VAL_288_303, + PMIC_RG_OTP_VAL_304_319 = MT6351_PMIC_RG_OTP_VAL_304_319, + PMIC_RG_OTP_VAL_320_335 = MT6351_PMIC_RG_OTP_VAL_320_335, + PMIC_RG_OTP_VAL_336_351 = MT6351_PMIC_RG_OTP_VAL_336_351, + PMIC_RG_OTP_VAL_352_367 = MT6351_PMIC_RG_OTP_VAL_352_367, + PMIC_RG_OTP_VAL_368_383 = MT6351_PMIC_RG_OTP_VAL_368_383, + PMIC_RG_OTP_VAL_384_399 = MT6351_PMIC_RG_OTP_VAL_384_399, + PMIC_RG_OTP_VAL_400_415 = MT6351_PMIC_RG_OTP_VAL_400_415, + PMIC_RG_OTP_VAL_416_431 = MT6351_PMIC_RG_OTP_VAL_416_431, + PMIC_RG_OTP_VAL_432_447 = MT6351_PMIC_RG_OTP_VAL_432_447, + PMIC_RG_OTP_VAL_448_463 = MT6351_PMIC_RG_OTP_VAL_448_463, + PMIC_RG_OTP_VAL_464_479 = MT6351_PMIC_RG_OTP_VAL_464_479, + PMIC_RG_OTP_VAL_480_495 = MT6351_PMIC_RG_OTP_VAL_480_495, + PMIC_RG_OTP_VAL_496_511 = MT6351_PMIC_RG_OTP_VAL_496_511, + PMIC_MIX_EOSC32_STP_LPDTB = MT6351_PMIC_MIX_EOSC32_STP_LPDTB, + PMIC_MIX_EOSC32_STP_LPDEN = MT6351_PMIC_MIX_EOSC32_STP_LPDEN, + PMIC_MIX_XOSC32_STP_PWDB = MT6351_PMIC_MIX_XOSC32_STP_PWDB, + PMIC_MIX_XOSC32_STP_LPDTB = MT6351_PMIC_MIX_XOSC32_STP_LPDTB, + PMIC_MIX_XOSC32_STP_LPDEN = MT6351_PMIC_MIX_XOSC32_STP_LPDEN, + PMIC_MIX_XOSC32_STP_LPDRST = MT6351_PMIC_MIX_XOSC32_STP_LPDRST, + PMIC_MIX_XOSC32_STP_CALI = MT6351_PMIC_MIX_XOSC32_STP_CALI, + PMIC_STMP_MODE = MT6351_PMIC_STMP_MODE, + PMIC_MIX_EOSC32_STP_CHOP_EN = MT6351_PMIC_MIX_EOSC32_STP_CHOP_EN, + PMIC_MIX_DCXO_STP_LVSH_EN = MT6351_PMIC_MIX_DCXO_STP_LVSH_EN, + PMIC_MIX_PMU_STP_DDLO_VRTC = MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC, + PMIC_MIX_PMU_STP_DDLO_VRTC_EN = MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_EN, + PMIC_MIX_RTC_STP_XOSC32_ENB = MT6351_PMIC_MIX_RTC_STP_XOSC32_ENB, + PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE = MT6351_PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE, + PMIC_MIX_EOSC32_STP_RSV = MT6351_PMIC_MIX_EOSC32_STP_RSV, + PMIC_MIX_EOSC32_VCT_EN = MT6351_PMIC_MIX_EOSC32_VCT_EN, + PMIC_MIX_EOSC32_OPT = MT6351_PMIC_MIX_EOSC32_OPT, + PMIC_MIX_DCXO_STP_LVSH_EN_INT = MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_INT, + PMIC_MIX_RTC_GPIO_COREDETB = MT6351_PMIC_MIX_RTC_GPIO_COREDETB, + PMIC_MIX_RTC_GPIO_F32KOB = MT6351_PMIC_MIX_RTC_GPIO_F32KOB, + PMIC_MIX_RTC_GPIO_GPO = MT6351_PMIC_MIX_RTC_GPIO_GPO, + PMIC_MIX_RTC_GPIO_OE = MT6351_PMIC_MIX_RTC_GPIO_OE, + PMIC_MIX_RTC_STP_DEBUG_OUT = MT6351_PMIC_MIX_RTC_STP_DEBUG_OUT, + PMIC_MIX_RTC_STP_DEBUG_SEL = MT6351_PMIC_MIX_RTC_STP_DEBUG_SEL, + PMIC_MIX_RTC_STP_K_EOSC32_EN = MT6351_PMIC_MIX_RTC_STP_K_EOSC32_EN, + PMIC_MIX_RTC_STP_EMBCK_SEL = MT6351_PMIC_MIX_RTC_STP_EMBCK_SEL, + PMIC_MIX_STP_BBWAKEUP = MT6351_PMIC_MIX_STP_BBWAKEUP, + PMIC_MIX_STP_RTC_DDLO = MT6351_PMIC_MIX_STP_RTC_DDLO, + PMIC_MIX_RTC_XOSC32_ENB = MT6351_PMIC_MIX_RTC_XOSC32_ENB, + PMIC_MIX_EFUSE_XOSC32_ENB_OPT = MT6351_PMIC_MIX_EFUSE_XOSC32_ENB_OPT, + PMIC_FG_ON = MT6351_PMIC_FG_ON, + PMIC_FG_CAL = MT6351_PMIC_FG_CAL, + PMIC_FG_AUTOCALRATE = MT6351_PMIC_FG_AUTOCALRATE, + PMIC_FG_SW_CR = MT6351_PMIC_FG_SW_CR, + PMIC_FG_SW_READ_PRE = MT6351_PMIC_FG_SW_READ_PRE, + PMIC_FG_LATCHDATA_ST = MT6351_PMIC_FG_LATCHDATA_ST, + PMIC_FG_SW_CLEAR = MT6351_PMIC_FG_SW_CLEAR, + PMIC_FG_OFFSET_RST = MT6351_PMIC_FG_OFFSET_RST, + PMIC_FG_TIME_RST = MT6351_PMIC_FG_TIME_RST, + PMIC_FG_CHARGE_RST = MT6351_PMIC_FG_CHARGE_RST, + PMIC_FG_SW_RSTCLR = MT6351_PMIC_FG_SW_RSTCLR, + PMIC_FG_CAR_34_19 = MT6351_PMIC_FG_CAR_34_19, + PMIC_FG_CAR_18_03 = MT6351_PMIC_FG_CAR_18_03, + PMIC_FG_CAR_02_00 = MT6351_PMIC_FG_CAR_02_00, + PMIC_FG_NTER_32_17 = MT6351_PMIC_FG_NTER_32_17, + PMIC_FG_NTER_16_01 = MT6351_PMIC_FG_NTER_16_01, + PMIC_FG_NTER_00 = MT6351_PMIC_FG_NTER_00, + PMIC_FG_BLTR_31_16 = MT6351_PMIC_FG_BLTR_31_16, + PMIC_FG_BLTR_15_00 = MT6351_PMIC_FG_BLTR_15_00, + PMIC_FG_BFTR_31_16 = MT6351_PMIC_FG_BFTR_31_16, + PMIC_FG_BFTR_15_00 = MT6351_PMIC_FG_BFTR_15_00, + PMIC_FG_CURRENT_OUT = MT6351_PMIC_FG_CURRENT_OUT, + PMIC_FG_ADJUST_OFFSET_VALUE = MT6351_PMIC_FG_ADJUST_OFFSET_VALUE, + PMIC_FG_OFFSET = MT6351_PMIC_FG_OFFSET, + PMIC_RG_FGANALOGTEST = MT6351_PMIC_RG_FGANALOGTEST, + PMIC_RG_FGRINTMODE = MT6351_PMIC_RG_FGRINTMODE, + PMIC_RG_SPARE = MT6351_PMIC_RG_SPARE, + PMIC_FG_OSR = MT6351_PMIC_FG_OSR, + PMIC_FG_ADJ_OFFSET_EN = MT6351_PMIC_FG_ADJ_OFFSET_EN, + PMIC_FG_ADC_AUTORST = MT6351_PMIC_FG_ADC_AUTORST, + PMIC_FG_FIR1BYPASS = MT6351_PMIC_FG_FIR1BYPASS, + PMIC_FG_FIR2BYPASS = MT6351_PMIC_FG_FIR2BYPASS, + PMIC_FG_L_CUR_INT_STS = MT6351_PMIC_FG_L_CUR_INT_STS, + PMIC_FG_H_CUR_INT_STS = MT6351_PMIC_FG_H_CUR_INT_STS, + PMIC_FG_L_INT_STS = MT6351_PMIC_FG_L_INT_STS, + PMIC_FG_H_INT_STS = MT6351_PMIC_FG_H_INT_STS, + PMIC_FG_ADC_RSTDETECT = MT6351_PMIC_FG_ADC_RSTDETECT, + PMIC_FG_SLP_EN = MT6351_PMIC_FG_SLP_EN, + PMIC_FG_ZCV_DET_EN = MT6351_PMIC_FG_ZCV_DET_EN, + PMIC_RG_FG_AUXADC_R = MT6351_PMIC_RG_FG_AUXADC_R, + PMIC_DA_FGADC_EN = MT6351_PMIC_DA_FGADC_EN, + PMIC_DA_FGCAL_EN = MT6351_PMIC_DA_FGCAL_EN, + PMIC_DA_FG_RST = MT6351_PMIC_DA_FG_RST, + PMIC_FG_CIC2 = MT6351_PMIC_FG_CIC2, + PMIC_FG_SLP_CUR_TH = MT6351_PMIC_FG_SLP_CUR_TH, + PMIC_FG_SLP_TIME = MT6351_PMIC_FG_SLP_TIME, + PMIC_FG_SRCVOLTEN_FTIME = MT6351_PMIC_FG_SRCVOLTEN_FTIME, + PMIC_FG_DET_TIME = MT6351_PMIC_FG_DET_TIME, + PMIC_FG_ZCV_CAR_34_19 = MT6351_PMIC_FG_ZCV_CAR_34_19, + PMIC_FG_ZCV_CAR_18_03 = MT6351_PMIC_FG_ZCV_CAR_18_03, + PMIC_FG_ZCV_CAR_02_00 = MT6351_PMIC_FG_ZCV_CAR_02_00, + PMIC_FG_ZCV_CURR = MT6351_PMIC_FG_ZCV_CURR, + PMIC_FG_R_CURR = MT6351_PMIC_FG_R_CURR, + PMIC_FG_MODE = MT6351_PMIC_FG_MODE, + PMIC_FG_RST_SW = MT6351_PMIC_FG_RST_SW, + PMIC_FG_FGCAL_EN_SW = MT6351_PMIC_FG_FGCAL_EN_SW, + PMIC_FG_FGADC_EN_SW = MT6351_PMIC_FG_FGADC_EN_SW, + PMIC_FG_RSV1 = MT6351_PMIC_FG_RSV1, + PMIC_FG_TEST_MODE0 = MT6351_PMIC_FG_TEST_MODE0, + PMIC_FG_TEST_MODE1 = MT6351_PMIC_FG_TEST_MODE1, + PMIC_FG_GAIN = MT6351_PMIC_FG_GAIN, + PMIC_FG_CUR_HTH = MT6351_PMIC_FG_CUR_HTH, + PMIC_FG_CUR_LTH = MT6351_PMIC_FG_CUR_LTH, + PMIC_FG_ZCV_DET_TIME = MT6351_PMIC_FG_ZCV_DET_TIME, + PMIC_FG_ZCV_CAR_TH_33_19 = MT6351_PMIC_FG_ZCV_CAR_TH_33_19, + PMIC_FG_ZCV_CAR_TH_18_03 = MT6351_PMIC_FG_ZCV_CAR_TH_18_03, + PMIC_FG_ZCV_CAR_TH_02_00 = MT6351_PMIC_FG_ZCV_CAR_TH_02_00, + PMIC_SYSTEM_INFO_CON0 = MT6351_PMIC_SYSTEM_INFO_CON0, + PMIC_SYSTEM_INFO_CON1 = MT6351_PMIC_SYSTEM_INFO_CON1, + PMIC_SYSTEM_INFO_CON2 = MT6351_PMIC_SYSTEM_INFO_CON2, + PMIC_SYSTEM_INFO_CON3 = MT6351_PMIC_SYSTEM_INFO_CON3, + PMIC_SYSTEM_INFO_CON4 = MT6351_PMIC_SYSTEM_INFO_CON4, + PMIC_RG_AUDDACLPWRUP_VAUDP32 = MT6351_PMIC_RG_AUDDACLPWRUP_VAUDP32, + PMIC_RG_AUDDACRPWRUP_VAUDP32 = MT6351_PMIC_RG_AUDDACRPWRUP_VAUDP32, + PMIC_RG_AUD_DAC_PWR_UP_VA32 = MT6351_PMIC_RG_AUD_DAC_PWR_UP_VA32, + PMIC_RG_AUD_DAC_PWL_UP_VA32 = MT6351_PMIC_RG_AUD_DAC_PWL_UP_VA32, + PMIC_RG_AUDHSPWRUP_VAUDP32 = MT6351_PMIC_RG_AUDHSPWRUP_VAUDP32, + PMIC_RG_AUDHPLPWRUP_VAUDP32 = MT6351_PMIC_RG_AUDHPLPWRUP_VAUDP32, + PMIC_RG_AUDHPRPWRUP_VAUDP32 = MT6351_PMIC_RG_AUDHPRPWRUP_VAUDP32, + PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32 = MT6351_PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32, + PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32 = MT6351_PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32, + PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32 = MT6351_PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32, + PMIC_RG_AUDHSSCDISABLE_VAUDP32 = MT6351_PMIC_RG_AUDHSSCDISABLE_VAUDP32, + PMIC_RG_AUDHPLSCDISABLE_VAUDP32 = MT6351_PMIC_RG_AUDHPLSCDISABLE_VAUDP32, + PMIC_RG_AUDHPRSCDISABLE_VAUDP32 = MT6351_PMIC_RG_AUDHPRSCDISABLE_VAUDP32, + PMIC_RG_AUDHSBSCCURRENT_VAUDP32 = MT6351_PMIC_RG_AUDHSBSCCURRENT_VAUDP32, + PMIC_RG_AUDHPLBSCCURRENT_VAUDP32 = MT6351_PMIC_RG_AUDHPLBSCCURRENT_VAUDP32, + PMIC_RG_AUDHPRBSCCURRENT_VAUDP32 = MT6351_PMIC_RG_AUDHPRBSCCURRENT_VAUDP32, + PMIC_RG_AUDHSSTARTUP_VAUDP32 = MT6351_PMIC_RG_AUDHSSTARTUP_VAUDP32, + PMIC_RG_AUDHPSTARTUP_VAUDP32 = MT6351_PMIC_RG_AUDHPSTARTUP_VAUDP32, + PMIC_RG_AUDBGBON_VAUDP32 = MT6351_PMIC_RG_AUDBGBON_VAUDP32, + PMIC_RG_PRECHARGEBUF_EN_VAUDP32 = MT6351_PMIC_RG_PRECHARGEBUF_EN_VAUDP32, + PMIC_RG_HSINPUTSTBENH_VAUDP32 = MT6351_PMIC_RG_HSINPUTSTBENH_VAUDP32, + PMIC_RG_HSOUTPUTSTBENH_VAUDP32 = MT6351_PMIC_RG_HSOUTPUTSTBENH_VAUDP32, + PMIC_RG_HSINPUTRESET0_VAUDP32 = MT6351_PMIC_RG_HSINPUTRESET0_VAUDP32, + PMIC_RG_HSOUTPUTRESET0_VAUDP32 = MT6351_PMIC_RG_HSOUTPUTRESET0_VAUDP32, + PMIC_RG_HSOUT_SHORTVCM_VAUDP32 = MT6351_PMIC_RG_HSOUT_SHORTVCM_VAUDP32, + PMIC_RG_HPINPUTSTBENH_VAUDP32 = MT6351_PMIC_RG_HPINPUTSTBENH_VAUDP32, + PMIC_RG_HPOUTPUTSTBENH_VAUDP32 = MT6351_PMIC_RG_HPOUTPUTSTBENH_VAUDP32, + PMIC_RG_HPINPUTRESET0_VAUDP32 = MT6351_PMIC_RG_HPINPUTRESET0_VAUDP32, + PMIC_RG_HPOUTPUTRESET0_VAUDP32 = MT6351_PMIC_RG_HPOUTPUTRESET0_VAUDP32, + PMIC_RG_HPOUT_SHORTVCM_VAUDP32 = MT6351_PMIC_RG_HPOUT_SHORTVCM_VAUDP32, + PMIC_RG_HPOUTSTB_RSEL_VAUDP32 = MT6351_PMIC_RG_HPOUTSTB_RSEL_VAUDP32, + PMIC_RG_LINENOISEENH_VAUDP32 = MT6351_PMIC_RG_LINENOISEENH_VAUDP32, + PMIC_RG_AUDHPLTRIM_VAUDP32 = MT6351_PMIC_RG_AUDHPLTRIM_VAUDP32, + PMIC_RG_AUDHPRTRIM_VAUDP32 = MT6351_PMIC_RG_AUDHPRTRIM_VAUDP32, + PMIC_RG_AUDHPTRIM_EN_VAUDP32 = MT6351_PMIC_RG_AUDHPTRIM_EN_VAUDP32, + PMIC_RG_AUDHPLFINETRIM_VAUDP32 = MT6351_PMIC_RG_AUDHPLFINETRIM_VAUDP32, + PMIC_RG_AUDHPRFINETRIM_VAUDP32 = MT6351_PMIC_RG_AUDHPRFINETRIM_VAUDP32, + PMIC_RG_AUDLOLPWRUP_VAUDP32 = MT6351_PMIC_RG_AUDLOLPWRUP_VAUDP32, + PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32 = MT6351_PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32, + PMIC_RG_AUDLOLSCDISABLE_VAUDP32 = MT6351_PMIC_RG_AUDLOLSCDISABLE_VAUDP32, + PMIC_RG_AUDLOLBSCCURRENT_VAUDP32 = MT6351_PMIC_RG_AUDLOLBSCCURRENT_VAUDP32, + PMIC_RG_AUDLOSTARTUP_VAUDP32 = MT6351_PMIC_RG_AUDLOSTARTUP_VAUDP32, + PMIC_RG_LOINPUTSTBENH_VAUDP32 = MT6351_PMIC_RG_LOINPUTSTBENH_VAUDP32, + PMIC_RG_LOOUTPUTSTBENH_VAUDP32 = MT6351_PMIC_RG_LOOUTPUTSTBENH_VAUDP32, + PMIC_RG_LOINPUTRESET0_VAUDP32 = MT6351_PMIC_RG_LOINPUTRESET0_VAUDP32, + PMIC_RG_LOOUTPUTRESET0_VAUDP32 = MT6351_PMIC_RG_LOOUTPUTRESET0_VAUDP32, + PMIC_RG_LOOUT_SHORTVCM_VAUDP32 = MT6351_PMIC_RG_LOOUT_SHORTVCM_VAUDP32, + PMIC_RG_LOOUTSTB_RSEL_VAUDP32 = MT6351_PMIC_RG_LOOUTSTB_RSEL_VAUDP32, + PMIC_RG_AUDLOLTRIM_VAUDP32 = MT6351_PMIC_RG_AUDLOLTRIM_VAUDP32, + PMIC_RG_AUDLOTRIM_EN_VAUDP32 = MT6351_PMIC_RG_AUDLOTRIM_EN_VAUDP32, + PMIC_RG_AUDLOLFINETRIM_VAUDP32 = MT6351_PMIC_RG_AUDLOLFINETRIM_VAUDP32, + PMIC_RG_AUDTRIMBUF_EN_VAUDP32 = MT6351_PMIC_RG_AUDTRIMBUF_EN_VAUDP32, + PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32 = MT6351_PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32, + PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32 = MT6351_PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32, + PMIC_RG_AUDHPSPKDET_EN_VAUDP32 = MT6351_PMIC_RG_AUDHPSPKDET_EN_VAUDP32, + PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32 = MT6351_PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32, + PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32 = MT6351_PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32, + PMIC_RG_ABIDEC_RSVD0_VA32 = MT6351_PMIC_RG_ABIDEC_RSVD0_VA32, + PMIC_RG_ABIDEC_RSVD1_VA32 = MT6351_PMIC_RG_ABIDEC_RSVD1_VA32, + PMIC_RG_ABIDEC_RSVD0_VAUDP32 = MT6351_PMIC_RG_ABIDEC_RSVD0_VAUDP32, + PMIC_RG_ABIDEC_RSVD1_VAUDP32 = MT6351_PMIC_RG_ABIDEC_RSVD1_VAUDP32, + PMIC_RG_AUDZCDMUXSEL_VAUDP32 = MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP32, + PMIC_RG_AUDZCDCLKSEL_VAUDP32 = MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP32, + PMIC_RG_AUDBIASADJ_0_VAUDP32 = MT6351_PMIC_RG_AUDBIASADJ_0_VAUDP32, + PMIC_RG_AUDBIASADJ_1_VAUDP32 = MT6351_PMIC_RG_AUDBIASADJ_1_VAUDP32, + PMIC_RG_AUDIBIASPWRDN_VAUDP32 = MT6351_PMIC_RG_AUDIBIASPWRDN_VAUDP32, + PMIC_RG_RSTB_DECODER_VA32 = MT6351_PMIC_RG_RSTB_DECODER_VA32, + PMIC_RG_SEL_DECODER_96K_VA32 = MT6351_PMIC_RG_SEL_DECODER_96K_VA32, + PMIC_RG_SEL_DELAY_VCORE = MT6351_PMIC_RG_SEL_DELAY_VCORE, + PMIC_RG_AUDGLB_PWRDN_VA32 = MT6351_PMIC_RG_AUDGLB_PWRDN_VA32, + PMIC_RG_LCLDO_DEC_EN_VA32 = MT6351_PMIC_RG_LCLDO_DEC_EN_VA32, + PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18 = MT6351_PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18, + PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18 = MT6351_PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18, + PMIC_RG_AUDPMU_RSVD_VA18 = MT6351_PMIC_RG_AUDPMU_RSVD_VA18, + PMIC_RG_NVREG_EN_VAUDP32 = MT6351_PMIC_RG_NVREG_EN_VAUDP32, + PMIC_RG_NVREG_PULL0V_VAUDP32 = MT6351_PMIC_RG_NVREG_PULL0V_VAUDP32, + PMIC_RG_AUDGLB_LP2_VOW_EN_VA32 = MT6351_PMIC_RG_AUDGLB_LP2_VOW_EN_VA32, + PMIC_RG_AUDPREAMPLON = MT6351_PMIC_RG_AUDPREAMPLON, + PMIC_RG_AUDPREAMPLDCCEN = MT6351_PMIC_RG_AUDPREAMPLDCCEN, + PMIC_RG_AUDPREAMPLDCPRECHARGE = MT6351_PMIC_RG_AUDPREAMPLDCPRECHARGE, + PMIC_RG_AUDPREAMPLPGATEST = MT6351_PMIC_RG_AUDPREAMPLPGATEST, + PMIC_RG_AUDPREAMPLINPUTSEL = MT6351_PMIC_RG_AUDPREAMPLINPUTSEL, + PMIC_RG_AUDPREAMPLVSCALE = MT6351_PMIC_RG_AUDPREAMPLVSCALE, + PMIC_RG_AUDPREAMPLGAIN = MT6351_PMIC_RG_AUDPREAMPLGAIN, + PMIC_RG_AUDADCLPWRUP = MT6351_PMIC_RG_AUDADCLPWRUP, + PMIC_RG_AUDADCLINPUTSEL = MT6351_PMIC_RG_AUDADCLINPUTSEL, + PMIC_RG_AUDPREAMPRON = MT6351_PMIC_RG_AUDPREAMPRON, + PMIC_RG_AUDPREAMPRDCCEN = MT6351_PMIC_RG_AUDPREAMPRDCCEN, + PMIC_RG_AUDPREAMPRDCPRECHARGE = MT6351_PMIC_RG_AUDPREAMPRDCPRECHARGE, + PMIC_RG_AUDPREAMPRPGATEST = MT6351_PMIC_RG_AUDPREAMPRPGATEST, + PMIC_RG_AUDPREAMPRINPUTSEL = MT6351_PMIC_RG_AUDPREAMPRINPUTSEL, + PMIC_RG_AUDPREAMPRVSCALE = MT6351_PMIC_RG_AUDPREAMPRVSCALE, + PMIC_RG_AUDPREAMPRGAIN = MT6351_PMIC_RG_AUDPREAMPRGAIN, + PMIC_RG_AUDADCRPWRUP = MT6351_PMIC_RG_AUDADCRPWRUP, + PMIC_RG_AUDADCRINPUTSEL = MT6351_PMIC_RG_AUDADCRINPUTSEL, + PMIC_RG_AUDULHALFBIAS = MT6351_PMIC_RG_AUDULHALFBIAS, + PMIC_RG_AUDGLBVOWLPWEN = MT6351_PMIC_RG_AUDGLBVOWLPWEN, + PMIC_RG_AUDPREAMPLPEN = MT6351_PMIC_RG_AUDPREAMPLPEN, + PMIC_RG_AUDADC1STSTAGELPEN = MT6351_PMIC_RG_AUDADC1STSTAGELPEN, + PMIC_RG_AUDADC2NDSTAGELPEN = MT6351_PMIC_RG_AUDADC2NDSTAGELPEN, + PMIC_RG_AUDADCFLASHLPEN = MT6351_PMIC_RG_AUDADCFLASHLPEN, + PMIC_RG_AUDPREAMPIDDTEST = MT6351_PMIC_RG_AUDPREAMPIDDTEST, + PMIC_RG_AUDADC1STSTAGEIDDTEST = MT6351_PMIC_RG_AUDADC1STSTAGEIDDTEST, + PMIC_RG_AUDADC2NDSTAGEIDDTEST = MT6351_PMIC_RG_AUDADC2NDSTAGEIDDTEST, + PMIC_RG_AUDADCREFBUFIDDTEST = MT6351_PMIC_RG_AUDADCREFBUFIDDTEST, + PMIC_RG_AUDADCFLASHIDDTEST = MT6351_PMIC_RG_AUDADCFLASHIDDTEST, + PMIC_RG_AUDADCDAC0P25FS = MT6351_PMIC_RG_AUDADCDAC0P25FS, + PMIC_RG_AUDADCCLKSEL = MT6351_PMIC_RG_AUDADCCLKSEL, + PMIC_RG_AUDADCCLKSOURCE = MT6351_PMIC_RG_AUDADCCLKSOURCE, + PMIC_RG_AUDADCCLKGENMODE = MT6351_PMIC_RG_AUDADCCLKGENMODE, + PMIC_RG_AUDADCCLKRSTB = MT6351_PMIC_RG_AUDADCCLKRSTB, + PMIC_RG_AUDPREAMPAAFEN = MT6351_PMIC_RG_AUDPREAMPAAFEN, + PMIC_RG_DCCVCMBUFLPMODSEL = MT6351_PMIC_RG_DCCVCMBUFLPMODSEL, + PMIC_RG_DCCVCMBUFLPSWEN = MT6351_PMIC_RG_DCCVCMBUFLPSWEN, + PMIC_RG_AUDSPAREPGA = MT6351_PMIC_RG_AUDSPAREPGA, + PMIC_RG_AUDADC1STSTAGESDENB = MT6351_PMIC_RG_AUDADC1STSTAGESDENB, + PMIC_RG_AUDADC2NDSTAGERESET = MT6351_PMIC_RG_AUDADC2NDSTAGERESET, + PMIC_RG_AUDADC3RDSTAGERESET = MT6351_PMIC_RG_AUDADC3RDSTAGERESET, + PMIC_RG_AUDADCFSRESET = MT6351_PMIC_RG_AUDADCFSRESET, + PMIC_RG_AUDADCWIDECM = MT6351_PMIC_RG_AUDADCWIDECM, + PMIC_RG_AUDADCNOPATEST = MT6351_PMIC_RG_AUDADCNOPATEST, + PMIC_RG_AUDADCBYPASS = MT6351_PMIC_RG_AUDADCBYPASS, + PMIC_RG_AUDADCFFBYPASS = MT6351_PMIC_RG_AUDADCFFBYPASS, + PMIC_RG_AUDADCDACFBCURRENT = MT6351_PMIC_RG_AUDADCDACFBCURRENT, + PMIC_RG_AUDADCDACIDDTEST = MT6351_PMIC_RG_AUDADCDACIDDTEST, + PMIC_RG_AUDADCDACNRZ = MT6351_PMIC_RG_AUDADCDACNRZ, + PMIC_RG_AUDADCNODEM = MT6351_PMIC_RG_AUDADCNODEM, + PMIC_RG_AUDADCDACTEST = MT6351_PMIC_RG_AUDADCDACTEST, + PMIC_RG_AUDADCTESTDATA = MT6351_PMIC_RG_AUDADCTESTDATA, + PMIC_RG_AUDRCTUNEL = MT6351_PMIC_RG_AUDRCTUNEL, + PMIC_RG_AUDRCTUNELSEL = MT6351_PMIC_RG_AUDRCTUNELSEL, + PMIC_RG_AUDRCTUNER = MT6351_PMIC_RG_AUDRCTUNER, + PMIC_RG_AUDRCTUNERSEL = MT6351_PMIC_RG_AUDRCTUNERSEL, + PMIC_RG_AUDSPAREVA30 = MT6351_PMIC_RG_AUDSPAREVA30, + PMIC_RG_AUDSPAREVA18 = MT6351_PMIC_RG_AUDSPAREVA18, + PMIC_RG_AUDDIGMICEN = MT6351_PMIC_RG_AUDDIGMICEN, + PMIC_RG_AUDDIGMICBIAS = MT6351_PMIC_RG_AUDDIGMICBIAS, + PMIC_RG_DMICHPCLKEN = MT6351_PMIC_RG_DMICHPCLKEN, + PMIC_RG_AUDDIGMICPDUTY = MT6351_PMIC_RG_AUDDIGMICPDUTY, + PMIC_RG_AUDDIGMICNDUTY = MT6351_PMIC_RG_AUDDIGMICNDUTY, + PMIC_RG_DMICMONEN = MT6351_PMIC_RG_DMICMONEN, + PMIC_RG_DMICMONSEL = MT6351_PMIC_RG_DMICMONSEL, + PMIC_RG_AUDSPAREVMIC = MT6351_PMIC_RG_AUDSPAREVMIC, + PMIC_RG_AUDPWDBMICBIAS0 = MT6351_PMIC_RG_AUDPWDBMICBIAS0, + PMIC_RG_AUDMICBIAS0DCSW0P1EN = MT6351_PMIC_RG_AUDMICBIAS0DCSW0P1EN, + PMIC_RG_AUDMICBIAS0DCSW0P2EN = MT6351_PMIC_RG_AUDMICBIAS0DCSW0P2EN, + PMIC_RG_AUDMICBIAS0DCSW0NEN = MT6351_PMIC_RG_AUDMICBIAS0DCSW0NEN, + PMIC_RG_AUDMICBIAS0VREF = MT6351_PMIC_RG_AUDMICBIAS0VREF, + PMIC_RG_AUDMICBIAS0LOWPEN = MT6351_PMIC_RG_AUDMICBIAS0LOWPEN, + PMIC_RG_AUDPWDBMICBIAS2 = MT6351_PMIC_RG_AUDPWDBMICBIAS2, + PMIC_RG_AUDMICBIAS2DCSW2P1EN = MT6351_PMIC_RG_AUDMICBIAS2DCSW2P1EN, + PMIC_RG_AUDMICBIAS2DCSW2P2EN = MT6351_PMIC_RG_AUDMICBIAS2DCSW2P2EN, + PMIC_RG_AUDMICBIAS2DCSW2NEN = MT6351_PMIC_RG_AUDMICBIAS2DCSW2NEN, + PMIC_RG_AUDMICBIAS2VREF = MT6351_PMIC_RG_AUDMICBIAS2VREF, + PMIC_RG_AUDMICBIAS2LOWPEN = MT6351_PMIC_RG_AUDMICBIAS2LOWPEN, + PMIC_RG_AUDPWDBMICBIAS1 = MT6351_PMIC_RG_AUDPWDBMICBIAS1, + PMIC_RG_AUDMICBIAS1DCSW1PEN = MT6351_PMIC_RG_AUDMICBIAS1DCSW1PEN, + PMIC_RG_AUDMICBIAS1DCSW1NEN = MT6351_PMIC_RG_AUDMICBIAS1DCSW1NEN, + PMIC_RG_AUDMICBIAS1VREF = MT6351_PMIC_RG_AUDMICBIAS1VREF, + PMIC_RG_AUDMICBIAS1LOWPEN = MT6351_PMIC_RG_AUDMICBIAS1LOWPEN, + PMIC_RG_AUDMICBIAS1DCSW3PEN = MT6351_PMIC_RG_AUDMICBIAS1DCSW3PEN, + PMIC_RG_AUDMICBIAS1DCSW3NEN = MT6351_PMIC_RG_AUDMICBIAS1DCSW3NEN, + PMIC_RG_AUDMICBIAS2DCSW3PEN = MT6351_PMIC_RG_AUDMICBIAS2DCSW3PEN, + PMIC_RG_AUDMICBIAS2DCSW3NEN = MT6351_PMIC_RG_AUDMICBIAS2DCSW3NEN, + PMIC_RG_BANDGAPGEN = MT6351_PMIC_RG_BANDGAPGEN, + PMIC_RG_AUDACCDETMICBIAS0PULLLOW = MT6351_PMIC_RG_AUDACCDETMICBIAS0PULLLOW, + PMIC_RG_AUDACCDETMICBIAS1PULLLOW = MT6351_PMIC_RG_AUDACCDETMICBIAS1PULLLOW, + PMIC_RG_AUDACCDETMICBIAS2PULLLOW = MT6351_PMIC_RG_AUDACCDETMICBIAS2PULLLOW, + PMIC_RG_AUDACCDETVIN1PULLLOW = MT6351_PMIC_RG_AUDACCDETVIN1PULLLOW, + PMIC_RG_AUDACCDETVTHACAL = MT6351_PMIC_RG_AUDACCDETVTHACAL, + PMIC_RG_AUDACCDETVTHBCAL = MT6351_PMIC_RG_AUDACCDETVTHBCAL, + PMIC_RG_ACCDET1SEL = MT6351_PMIC_RG_ACCDET1SEL, + PMIC_RG_ACCDET2SEL = MT6351_PMIC_RG_ACCDET2SEL, + PMIC_RG_SWBUFMODSEL = MT6351_PMIC_RG_SWBUFMODSEL, + PMIC_RG_SWBUFSWEN = MT6351_PMIC_RG_SWBUFSWEN, + PMIC_RG_EINTCOMPVTH = MT6351_PMIC_RG_EINTCOMPVTH, + PMIC_RG_EINTCONFIGACCDET = MT6351_PMIC_RG_EINTCONFIGACCDET, + PMIC_RG_NVDETCMPEN = MT6351_PMIC_RG_NVDETCMPEN, + PMIC_RG_NVDETVTH = MT6351_PMIC_RG_NVDETVTH, + PMIC_RG_NVMODSEL = MT6351_PMIC_RG_NVMODSEL, + PMIC_RG_NVCMPSWEN = MT6351_PMIC_RG_NVCMPSWEN, + PMIC_RG_AUDENCSPAREVA30 = MT6351_PMIC_RG_AUDENCSPAREVA30, + PMIC_RG_AUDENCSPAREVA18 = MT6351_PMIC_RG_AUDENCSPAREVA18, + PMIC_RG_PLL_EN = MT6351_PMIC_RG_PLL_EN, + PMIC_RG_PLLBS_RST = MT6351_PMIC_RG_PLLBS_RST, + PMIC_RG_PLL_DCKO_SEL = MT6351_PMIC_RG_PLL_DCKO_SEL, + PMIC_RG_PLL_DIV1 = MT6351_PMIC_RG_PLL_DIV1, + PMIC_RG_PLL_RLATCH_EN = MT6351_PMIC_RG_PLL_RLATCH_EN, + PMIC_RG_PLL_PDIV1_EN = MT6351_PMIC_RG_PLL_PDIV1_EN, + PMIC_RG_PLL_PDIV1 = MT6351_PMIC_RG_PLL_PDIV1, + PMIC_RG_PLL_BC = MT6351_PMIC_RG_PLL_BC, + PMIC_RG_PLL_BP = MT6351_PMIC_RG_PLL_BP, + PMIC_RG_PLL_BR = MT6351_PMIC_RG_PLL_BR, + PMIC_RG_CKO_SEL = MT6351_PMIC_RG_CKO_SEL, + PMIC_RG_PLL_IBSEL = MT6351_PMIC_RG_PLL_IBSEL, + PMIC_RG_PLL_CKT_SEL = MT6351_PMIC_RG_PLL_CKT_SEL, + PMIC_RG_PLL_VCT_EN = MT6351_PMIC_RG_PLL_VCT_EN, + PMIC_RG_PLL_CKT_EN = MT6351_PMIC_RG_PLL_CKT_EN, + PMIC_RG_PLL_HPM_EN = MT6351_PMIC_RG_PLL_HPM_EN, + PMIC_RG_PLL_DCHP_EN = MT6351_PMIC_RG_PLL_DCHP_EN, + PMIC_RG_PLL_CDIV = MT6351_PMIC_RG_PLL_CDIV, + PMIC_RG_VCOBAND = MT6351_PMIC_RG_VCOBAND, + PMIC_RG_CKDRV_EN = MT6351_PMIC_RG_CKDRV_EN, + PMIC_RG_PLL_DCHP_AEN = MT6351_PMIC_RG_PLL_DCHP_AEN, + PMIC_RG_PLL_RSVA = MT6351_PMIC_RG_PLL_RSVA, + PMIC_RGS_AUDRCTUNELREAD = MT6351_PMIC_RGS_AUDRCTUNELREAD, + PMIC_RGS_AUDRCTUNERREAD = MT6351_PMIC_RGS_AUDRCTUNERREAD, + PMIC_RG_DIVCKS_CHG = MT6351_PMIC_RG_DIVCKS_CHG, + PMIC_RG_DIVCKS_ON = MT6351_PMIC_RG_DIVCKS_ON, + PMIC_RG_DIVCKS_PRG = MT6351_PMIC_RG_DIVCKS_PRG, + PMIC_RG_DIVCKS_PWD_NCP = MT6351_PMIC_RG_DIVCKS_PWD_NCP, + PMIC_RG_DIVCKS_PWD_NCP_ST_SEL = MT6351_PMIC_RG_DIVCKS_PWD_NCP_ST_SEL, + PMIC_AUXADC_ADC_OUT_CH0 = MT6351_PMIC_AUXADC_ADC_OUT_CH0, + PMIC_AUXADC_ADC_RDY_CH0 = MT6351_PMIC_AUXADC_ADC_RDY_CH0, + PMIC_AUXADC_ADC_OUT_CH1 = MT6351_PMIC_AUXADC_ADC_OUT_CH1, + PMIC_AUXADC_ADC_RDY_CH1 = MT6351_PMIC_AUXADC_ADC_RDY_CH1, + PMIC_AUXADC_ADC_OUT_CH2 = MT6351_PMIC_AUXADC_ADC_OUT_CH2, + PMIC_AUXADC_ADC_RDY_CH2 = MT6351_PMIC_AUXADC_ADC_RDY_CH2, + PMIC_AUXADC_ADC_OUT_CH3 = MT6351_PMIC_AUXADC_ADC_OUT_CH3, + PMIC_AUXADC_ADC_RDY_CH3 = MT6351_PMIC_AUXADC_ADC_RDY_CH3, + PMIC_AUXADC_ADC_OUT_CH4 = MT6351_PMIC_AUXADC_ADC_OUT_CH4, + PMIC_AUXADC_ADC_RDY_CH4 = MT6351_PMIC_AUXADC_ADC_RDY_CH4, + PMIC_AUXADC_ADC_OUT_CH5 = MT6351_PMIC_AUXADC_ADC_OUT_CH5, + PMIC_AUXADC_ADC_RDY_CH5 = MT6351_PMIC_AUXADC_ADC_RDY_CH5, + PMIC_AUXADC_ADC_OUT_CH6 = MT6351_PMIC_AUXADC_ADC_OUT_CH6, + PMIC_AUXADC_ADC_RDY_CH6 = MT6351_PMIC_AUXADC_ADC_RDY_CH6, + PMIC_AUXADC_ADC_OUT_CH7 = MT6351_PMIC_AUXADC_ADC_OUT_CH7, + PMIC_AUXADC_ADC_RDY_CH7 = MT6351_PMIC_AUXADC_ADC_RDY_CH7, + PMIC_AUXADC_ADC_OUT_CH8 = MT6351_PMIC_AUXADC_ADC_OUT_CH8, + PMIC_AUXADC_ADC_RDY_CH8 = MT6351_PMIC_AUXADC_ADC_RDY_CH8, + PMIC_AUXADC_ADC_OUT_CH9 = MT6351_PMIC_AUXADC_ADC_OUT_CH9, + PMIC_AUXADC_ADC_RDY_CH9 = MT6351_PMIC_AUXADC_ADC_RDY_CH9, + PMIC_AUXADC_ADC_OUT_CH10 = MT6351_PMIC_AUXADC_ADC_OUT_CH10, + PMIC_AUXADC_ADC_RDY_CH10 = MT6351_PMIC_AUXADC_ADC_RDY_CH10, + PMIC_AUXADC_ADC_OUT_CH11 = MT6351_PMIC_AUXADC_ADC_OUT_CH11, + PMIC_AUXADC_ADC_RDY_CH11 = MT6351_PMIC_AUXADC_ADC_RDY_CH11, + PMIC_AUXADC_ADC_OUT_CH12_15 = MT6351_PMIC_AUXADC_ADC_OUT_CH12_15, + PMIC_AUXADC_ADC_RDY_CH12_15 = MT6351_PMIC_AUXADC_ADC_RDY_CH12_15, + PMIC_AUXADC_ADC_OUT_THR_HW = MT6351_PMIC_AUXADC_ADC_OUT_THR_HW, + PMIC_AUXADC_ADC_RDY_THR_HW = MT6351_PMIC_AUXADC_ADC_RDY_THR_HW, + PMIC_AUXADC_ADC_OUT_LBAT = MT6351_PMIC_AUXADC_ADC_OUT_LBAT, + PMIC_AUXADC_ADC_RDY_LBAT = MT6351_PMIC_AUXADC_ADC_RDY_LBAT, + PMIC_AUXADC_ADC_OUT_LBAT2 = MT6351_PMIC_AUXADC_ADC_OUT_LBAT2, + PMIC_AUXADC_ADC_RDY_LBAT2 = MT6351_PMIC_AUXADC_ADC_RDY_LBAT2, + PMIC_AUXADC_ADC_OUT_CH7_BY_GPS = MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_GPS, + PMIC_AUXADC_ADC_RDY_CH7_BY_GPS = MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_GPS, + PMIC_AUXADC_ADC_OUT_CH7_BY_MD = MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_MD, + PMIC_AUXADC_ADC_RDY_CH7_BY_MD = MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_MD, + PMIC_AUXADC_ADC_OUT_CH7_BY_AP = MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_AP, + PMIC_AUXADC_ADC_RDY_CH7_BY_AP = MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_AP, + PMIC_AUXADC_ADC_OUT_CH4_BY_MD = MT6351_PMIC_AUXADC_ADC_OUT_CH4_BY_MD, + PMIC_AUXADC_ADC_RDY_CH4_BY_MD = MT6351_PMIC_AUXADC_ADC_RDY_CH4_BY_MD, + PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR = MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR, + PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR = MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR, + PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR = MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR, + PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR = MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR, + PMIC_AUXADC_ADC_OUT_CH0_BY_MD = MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_MD, + PMIC_AUXADC_ADC_RDY_CH0_BY_MD = MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_MD, + PMIC_AUXADC_ADC_OUT_CH0_BY_AP = MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_AP, + PMIC_AUXADC_ADC_RDY_CH0_BY_AP = MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_AP, + PMIC_AUXADC_ADC_OUT_CH1_BY_MD = MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_MD, + PMIC_AUXADC_ADC_RDY_CH1_BY_MD = MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_MD, + PMIC_AUXADC_ADC_OUT_CH1_BY_AP = MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_AP, + PMIC_AUXADC_ADC_RDY_CH1_BY_AP = MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_AP, + PMIC_AUXADC_ADC_OUT_VISMPS0 = MT6351_PMIC_AUXADC_ADC_OUT_VISMPS0, + PMIC_AUXADC_ADC_RDY_VISMPS0 = MT6351_PMIC_AUXADC_ADC_RDY_VISMPS0, + PMIC_AUXADC_ADC_OUT_FGADC1 = MT6351_PMIC_AUXADC_ADC_OUT_FGADC1, + PMIC_AUXADC_ADC_RDY_FGADC1 = MT6351_PMIC_AUXADC_ADC_RDY_FGADC1, + PMIC_AUXADC_ADC_OUT_FGADC2 = MT6351_PMIC_AUXADC_ADC_OUT_FGADC2, + PMIC_AUXADC_ADC_RDY_FGADC2 = MT6351_PMIC_AUXADC_ADC_RDY_FGADC2, + PMIC_AUXADC_ADC_OUT_IMP = MT6351_PMIC_AUXADC_ADC_OUT_IMP, + PMIC_AUXADC_ADC_RDY_IMP = MT6351_PMIC_AUXADC_ADC_RDY_IMP, + PMIC_AUXADC_ADC_OUT_IMP_AVG = MT6351_PMIC_AUXADC_ADC_OUT_IMP_AVG, + PMIC_AUXADC_ADC_RDY_IMP_AVG = MT6351_PMIC_AUXADC_ADC_RDY_IMP_AVG, + PMIC_AUXADC_ADC_OUT_RAW = MT6351_PMIC_AUXADC_ADC_OUT_RAW, + PMIC_AUXADC_ADC_OUT_MDRT = MT6351_PMIC_AUXADC_ADC_OUT_MDRT, + PMIC_AUXADC_ADC_RDY_MDRT = MT6351_PMIC_AUXADC_ADC_RDY_MDRT, + PMIC_AUXADC_ADC_OUT_MDBG = MT6351_PMIC_AUXADC_ADC_OUT_MDBG, + PMIC_AUXADC_ADC_RDY_MDBG = MT6351_PMIC_AUXADC_ADC_RDY_MDBG, + PMIC_AUXADC_ADC_OUT_JEITA = MT6351_PMIC_AUXADC_ADC_OUT_JEITA, + PMIC_AUXADC_ADC_RDY_JEITA = MT6351_PMIC_AUXADC_ADC_RDY_JEITA, + PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS = MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS, + PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS = MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS, + PMIC_AUXADC_ADC_OUT_DCXO_BY_MD = MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_MD, + PMIC_AUXADC_ADC_RDY_DCXO_BY_MD = MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_MD, + PMIC_AUXADC_ADC_OUT_DCXO_BY_AP = MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_AP, + PMIC_AUXADC_ADC_RDY_DCXO_BY_AP = MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_AP, + PMIC_AUXADC_ADC_OUT_DCXO_MDRT = MT6351_PMIC_AUXADC_ADC_OUT_DCXO_MDRT, + PMIC_AUXADC_ADC_RDY_DCXO_MDRT = MT6351_PMIC_AUXADC_ADC_RDY_DCXO_MDRT, + PMIC_AUXADC_ADC_OUT_NAG = MT6351_PMIC_AUXADC_ADC_OUT_NAG, + PMIC_AUXADC_ADC_RDY_NAG = MT6351_PMIC_AUXADC_ADC_RDY_NAG, + PMIC_AUXADC_BUF_OUT_00 = MT6351_PMIC_AUXADC_BUF_OUT_00, + PMIC_AUXADC_BUF_RDY_00 = MT6351_PMIC_AUXADC_BUF_RDY_00, + PMIC_AUXADC_BUF_OUT_01 = MT6351_PMIC_AUXADC_BUF_OUT_01, + PMIC_AUXADC_BUF_RDY_01 = MT6351_PMIC_AUXADC_BUF_RDY_01, + PMIC_AUXADC_BUF_OUT_02 = MT6351_PMIC_AUXADC_BUF_OUT_02, + PMIC_AUXADC_BUF_RDY_02 = MT6351_PMIC_AUXADC_BUF_RDY_02, + PMIC_AUXADC_BUF_OUT_03 = MT6351_PMIC_AUXADC_BUF_OUT_03, + PMIC_AUXADC_BUF_RDY_03 = MT6351_PMIC_AUXADC_BUF_RDY_03, + PMIC_AUXADC_BUF_OUT_04 = MT6351_PMIC_AUXADC_BUF_OUT_04, + PMIC_AUXADC_BUF_RDY_04 = MT6351_PMIC_AUXADC_BUF_RDY_04, + PMIC_AUXADC_BUF_OUT_05 = MT6351_PMIC_AUXADC_BUF_OUT_05, + PMIC_AUXADC_BUF_RDY_05 = MT6351_PMIC_AUXADC_BUF_RDY_05, + PMIC_AUXADC_BUF_OUT_06 = MT6351_PMIC_AUXADC_BUF_OUT_06, + PMIC_AUXADC_BUF_RDY_06 = MT6351_PMIC_AUXADC_BUF_RDY_06, + PMIC_AUXADC_BUF_OUT_07 = MT6351_PMIC_AUXADC_BUF_OUT_07, + PMIC_AUXADC_BUF_RDY_07 = MT6351_PMIC_AUXADC_BUF_RDY_07, + PMIC_AUXADC_BUF_OUT_08 = MT6351_PMIC_AUXADC_BUF_OUT_08, + PMIC_AUXADC_BUF_RDY_08 = MT6351_PMIC_AUXADC_BUF_RDY_08, + PMIC_AUXADC_BUF_OUT_09 = MT6351_PMIC_AUXADC_BUF_OUT_09, + PMIC_AUXADC_BUF_RDY_09 = MT6351_PMIC_AUXADC_BUF_RDY_09, + PMIC_AUXADC_BUF_OUT_10 = MT6351_PMIC_AUXADC_BUF_OUT_10, + PMIC_AUXADC_BUF_RDY_10 = MT6351_PMIC_AUXADC_BUF_RDY_10, + PMIC_AUXADC_BUF_OUT_11 = MT6351_PMIC_AUXADC_BUF_OUT_11, + PMIC_AUXADC_BUF_RDY_11 = MT6351_PMIC_AUXADC_BUF_RDY_11, + PMIC_AUXADC_BUF_OUT_12 = MT6351_PMIC_AUXADC_BUF_OUT_12, + PMIC_AUXADC_BUF_RDY_12 = MT6351_PMIC_AUXADC_BUF_RDY_12, + PMIC_AUXADC_BUF_OUT_13 = MT6351_PMIC_AUXADC_BUF_OUT_13, + PMIC_AUXADC_BUF_RDY_13 = MT6351_PMIC_AUXADC_BUF_RDY_13, + PMIC_AUXADC_BUF_OUT_14 = MT6351_PMIC_AUXADC_BUF_OUT_14, + PMIC_AUXADC_BUF_RDY_14 = MT6351_PMIC_AUXADC_BUF_RDY_14, + PMIC_AUXADC_BUF_OUT_15 = MT6351_PMIC_AUXADC_BUF_OUT_15, + PMIC_AUXADC_BUF_RDY_15 = MT6351_PMIC_AUXADC_BUF_RDY_15, + PMIC_AUXADC_BUF_OUT_16 = MT6351_PMIC_AUXADC_BUF_OUT_16, + PMIC_AUXADC_BUF_RDY_16 = MT6351_PMIC_AUXADC_BUF_RDY_16, + PMIC_AUXADC_BUF_OUT_17 = MT6351_PMIC_AUXADC_BUF_OUT_17, + PMIC_AUXADC_BUF_RDY_17 = MT6351_PMIC_AUXADC_BUF_RDY_17, + PMIC_AUXADC_BUF_OUT_18 = MT6351_PMIC_AUXADC_BUF_OUT_18, + PMIC_AUXADC_BUF_RDY_18 = MT6351_PMIC_AUXADC_BUF_RDY_18, + PMIC_AUXADC_BUF_OUT_19 = MT6351_PMIC_AUXADC_BUF_OUT_19, + PMIC_AUXADC_BUF_RDY_19 = MT6351_PMIC_AUXADC_BUF_RDY_19, + PMIC_AUXADC_BUF_OUT_20 = MT6351_PMIC_AUXADC_BUF_OUT_20, + PMIC_AUXADC_BUF_RDY_20 = MT6351_PMIC_AUXADC_BUF_RDY_20, + PMIC_AUXADC_BUF_OUT_21 = MT6351_PMIC_AUXADC_BUF_OUT_21, + PMIC_AUXADC_BUF_RDY_21 = MT6351_PMIC_AUXADC_BUF_RDY_21, + PMIC_AUXADC_BUF_OUT_22 = MT6351_PMIC_AUXADC_BUF_OUT_22, + PMIC_AUXADC_BUF_RDY_22 = MT6351_PMIC_AUXADC_BUF_RDY_22, + PMIC_AUXADC_BUF_OUT_23 = MT6351_PMIC_AUXADC_BUF_OUT_23, + PMIC_AUXADC_BUF_RDY_23 = MT6351_PMIC_AUXADC_BUF_RDY_23, + PMIC_AUXADC_BUF_OUT_24 = MT6351_PMIC_AUXADC_BUF_OUT_24, + PMIC_AUXADC_BUF_RDY_24 = MT6351_PMIC_AUXADC_BUF_RDY_24, + PMIC_AUXADC_BUF_OUT_25 = MT6351_PMIC_AUXADC_BUF_OUT_25, + PMIC_AUXADC_BUF_RDY_25 = MT6351_PMIC_AUXADC_BUF_RDY_25, + PMIC_AUXADC_BUF_OUT_26 = MT6351_PMIC_AUXADC_BUF_OUT_26, + PMIC_AUXADC_BUF_RDY_26 = MT6351_PMIC_AUXADC_BUF_RDY_26, + PMIC_AUXADC_BUF_OUT_27 = MT6351_PMIC_AUXADC_BUF_OUT_27, + PMIC_AUXADC_BUF_RDY_27 = MT6351_PMIC_AUXADC_BUF_RDY_27, + PMIC_AUXADC_BUF_OUT_28 = MT6351_PMIC_AUXADC_BUF_OUT_28, + PMIC_AUXADC_BUF_RDY_28 = MT6351_PMIC_AUXADC_BUF_RDY_28, + PMIC_AUXADC_BUF_OUT_29 = MT6351_PMIC_AUXADC_BUF_OUT_29, + PMIC_AUXADC_BUF_RDY_29 = MT6351_PMIC_AUXADC_BUF_RDY_29, + PMIC_AUXADC_BUF_OUT_30 = MT6351_PMIC_AUXADC_BUF_OUT_30, + PMIC_AUXADC_BUF_RDY_30 = MT6351_PMIC_AUXADC_BUF_RDY_30, + PMIC_AUXADC_BUF_OUT_31 = MT6351_PMIC_AUXADC_BUF_OUT_31, + PMIC_AUXADC_BUF_RDY_31 = MT6351_PMIC_AUXADC_BUF_RDY_31, + PMIC_AUXADC_ADC_BUSY_IN = MT6351_PMIC_AUXADC_ADC_BUSY_IN, + PMIC_AUXADC_ADC_BUSY_IN_LBAT = MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT, + PMIC_AUXADC_ADC_BUSY_IN_LBAT2 = MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT2, + PMIC_AUXADC_ADC_BUSY_IN_VISMPS0 = MT6351_PMIC_AUXADC_ADC_BUSY_IN_VISMPS0, + PMIC_AUXADC_ADC_BUSY_IN_WAKEUP = MT6351_PMIC_AUXADC_ADC_BUSY_IN_WAKEUP, + PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT = MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT, + PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP = MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP, + PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD = MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD, + PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS = MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS, + PMIC_AUXADC_ADC_BUSY_IN_JEITA = MT6351_PMIC_AUXADC_ADC_BUSY_IN_JEITA, + PMIC_AUXADC_ADC_BUSY_IN_MDRT = MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDRT, + PMIC_AUXADC_ADC_BUSY_IN_MDBG = MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDBG, + PMIC_AUXADC_ADC_BUSY_IN_SHARE = MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHARE, + PMIC_AUXADC_ADC_BUSY_IN_IMP = MT6351_PMIC_AUXADC_ADC_BUSY_IN_IMP, + PMIC_AUXADC_ADC_BUSY_IN_FGADC1 = MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC1, + PMIC_AUXADC_ADC_BUSY_IN_FGADC2 = MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC2, + PMIC_AUXADC_ADC_BUSY_IN_GPS_AP = MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_AP, + PMIC_AUXADC_ADC_BUSY_IN_GPS_MD = MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MD, + PMIC_AUXADC_ADC_BUSY_IN_GPS = MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS, + PMIC_AUXADC_ADC_BUSY_IN_THR_HW = MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_HW, + PMIC_AUXADC_ADC_BUSY_IN_THR_MD = MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_MD, + PMIC_AUXADC_ADC_BUSY_IN_NAG = MT6351_PMIC_AUXADC_ADC_BUSY_IN_NAG, + PMIC_AUXADC_RQST_CH0 = MT6351_PMIC_AUXADC_RQST_CH0, + PMIC_AUXADC_RQST_CH1 = MT6351_PMIC_AUXADC_RQST_CH1, + PMIC_AUXADC_RQST_CH2 = MT6351_PMIC_AUXADC_RQST_CH2, + PMIC_AUXADC_RQST_CH3 = MT6351_PMIC_AUXADC_RQST_CH3, + PMIC_AUXADC_RQST_CH4 = MT6351_PMIC_AUXADC_RQST_CH4, + PMIC_AUXADC_RQST_CH5 = MT6351_PMIC_AUXADC_RQST_CH5, + PMIC_AUXADC_RQST_CH6 = MT6351_PMIC_AUXADC_RQST_CH6, + PMIC_AUXADC_RQST_CH7 = MT6351_PMIC_AUXADC_RQST_CH7, + PMIC_AUXADC_RQST_CH8 = MT6351_PMIC_AUXADC_RQST_CH8, + PMIC_AUXADC_RQST_CH9 = MT6351_PMIC_AUXADC_RQST_CH9, + PMIC_AUXADC_RQST_CH10 = MT6351_PMIC_AUXADC_RQST_CH10, + PMIC_AUXADC_RQST_CH11 = MT6351_PMIC_AUXADC_RQST_CH11, + PMIC_AUXADC_RQST_CH12 = MT6351_PMIC_AUXADC_RQST_CH12, + PMIC_AUXADC_RQST_CH13 = MT6351_PMIC_AUXADC_RQST_CH13, + PMIC_AUXADC_RQST_CH14 = MT6351_PMIC_AUXADC_RQST_CH14, + PMIC_AUXADC_RQST_CH15 = MT6351_PMIC_AUXADC_RQST_CH15, + PMIC_AUXADC_RQST0_SET = MT6351_PMIC_AUXADC_RQST0_SET, + PMIC_AUXADC_RQST0_CLR = MT6351_PMIC_AUXADC_RQST0_CLR, + PMIC_AUXADC_RQST_CH0_BY_MD = MT6351_PMIC_AUXADC_RQST_CH0_BY_MD, + PMIC_AUXADC_RQST_CH1_BY_MD = MT6351_PMIC_AUXADC_RQST_CH1_BY_MD, + PMIC_AUXADC_RQST_RSV0 = MT6351_PMIC_AUXADC_RQST_RSV0, + PMIC_AUXADC_RQST_CH4_BY_MD = MT6351_PMIC_AUXADC_RQST_CH4_BY_MD, + PMIC_AUXADC_RQST_CH7_BY_MD = MT6351_PMIC_AUXADC_RQST_CH7_BY_MD, + PMIC_AUXADC_RQST_CH7_BY_GPS = MT6351_PMIC_AUXADC_RQST_CH7_BY_GPS, + PMIC_AUXADC_RQST_DCXO_BY_MD = MT6351_PMIC_AUXADC_RQST_DCXO_BY_MD, + PMIC_AUXADC_RQST_DCXO_BY_GPS = MT6351_PMIC_AUXADC_RQST_DCXO_BY_GPS, + PMIC_AUXADC_RQST_RSV1 = MT6351_PMIC_AUXADC_RQST_RSV1, + PMIC_AUXADC_RQST1_SET = MT6351_PMIC_AUXADC_RQST1_SET, + PMIC_AUXADC_RQST1_CLR = MT6351_PMIC_AUXADC_RQST1_CLR, + PMIC_AUXADC_CK_ON_EXTD = MT6351_PMIC_AUXADC_CK_ON_EXTD, + PMIC_AUXADC_SRCLKEN_SRC_SEL = MT6351_PMIC_AUXADC_SRCLKEN_SRC_SEL, + PMIC_AUXADC_ADC_PWDB = MT6351_PMIC_AUXADC_ADC_PWDB, + PMIC_AUXADC_ADC_PWDB_SWCTRL = MT6351_PMIC_AUXADC_ADC_PWDB_SWCTRL, + PMIC_AUXADC_STRUP_CK_ON_ENB = MT6351_PMIC_AUXADC_STRUP_CK_ON_ENB, + PMIC_AUXADC_ADC_RDY_WAKEUP_CLR = MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, + PMIC_AUXADC_SRCLKEN_CK_EN = MT6351_PMIC_AUXADC_SRCLKEN_CK_EN, + PMIC_AUXADC_CK_AON_GPS = MT6351_PMIC_AUXADC_CK_AON_GPS, + PMIC_AUXADC_CK_AON_MD = MT6351_PMIC_AUXADC_CK_AON_MD, + PMIC_AUXADC_CK_AON = MT6351_PMIC_AUXADC_CK_AON, + PMIC_AUXADC_CON0_SET = MT6351_PMIC_AUXADC_CON0_SET, + PMIC_AUXADC_CON0_CLR = MT6351_PMIC_AUXADC_CON0_CLR, + PMIC_AUXADC_AVG_NUM_SMALL = MT6351_PMIC_AUXADC_AVG_NUM_SMALL, + PMIC_AUXADC_AVG_NUM_LARGE = MT6351_PMIC_AUXADC_AVG_NUM_LARGE, + PMIC_AUXADC_SPL_NUM = MT6351_PMIC_AUXADC_SPL_NUM, + PMIC_AUXADC_AVG_NUM_SEL = MT6351_PMIC_AUXADC_AVG_NUM_SEL, + PMIC_AUXADC_AVG_NUM_SEL_SHARE = MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHARE, + PMIC_AUXADC_AVG_NUM_SEL_LBAT = MT6351_PMIC_AUXADC_AVG_NUM_SEL_LBAT, + PMIC_AUXADC_AVG_NUM_SEL_VISMPS = MT6351_PMIC_AUXADC_AVG_NUM_SEL_VISMPS, + PMIC_AUXADC_AVG_NUM_SEL_WAKEUP = MT6351_PMIC_AUXADC_AVG_NUM_SEL_WAKEUP, + PMIC_AUXADC_SPL_NUM_LARGE = MT6351_PMIC_AUXADC_SPL_NUM_LARGE, + PMIC_AUXADC_SPL_NUM_SLEEP = MT6351_PMIC_AUXADC_SPL_NUM_SLEEP, + PMIC_AUXADC_SPL_NUM_SLEEP_SEL = MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SEL, + PMIC_AUXADC_SPL_NUM_SEL = MT6351_PMIC_AUXADC_SPL_NUM_SEL, + PMIC_AUXADC_SPL_NUM_SEL_SHARE = MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHARE, + PMIC_AUXADC_SPL_NUM_SEL_LBAT = MT6351_PMIC_AUXADC_SPL_NUM_SEL_LBAT, + PMIC_AUXADC_SPL_NUM_SEL_VISMPS = MT6351_PMIC_AUXADC_SPL_NUM_SEL_VISMPS, + PMIC_AUXADC_SPL_NUM_SEL_WAKEUP = MT6351_PMIC_AUXADC_SPL_NUM_SEL_WAKEUP, + PMIC_AUXADC_TRIM_CH0_SEL = MT6351_PMIC_AUXADC_TRIM_CH0_SEL, + PMIC_AUXADC_TRIM_CH1_SEL = MT6351_PMIC_AUXADC_TRIM_CH1_SEL, + PMIC_AUXADC_TRIM_CH2_SEL = MT6351_PMIC_AUXADC_TRIM_CH2_SEL, + PMIC_AUXADC_TRIM_CH3_SEL = MT6351_PMIC_AUXADC_TRIM_CH3_SEL, + PMIC_AUXADC_TRIM_CH4_SEL = MT6351_PMIC_AUXADC_TRIM_CH4_SEL, + PMIC_AUXADC_TRIM_CH5_SEL = MT6351_PMIC_AUXADC_TRIM_CH5_SEL, + PMIC_AUXADC_TRIM_CH6_SEL = MT6351_PMIC_AUXADC_TRIM_CH6_SEL, + PMIC_AUXADC_TRIM_CH7_SEL = MT6351_PMIC_AUXADC_TRIM_CH7_SEL, + PMIC_AUXADC_TRIM_CH8_SEL = MT6351_PMIC_AUXADC_TRIM_CH8_SEL, + PMIC_AUXADC_TRIM_CH9_SEL = MT6351_PMIC_AUXADC_TRIM_CH9_SEL, + PMIC_AUXADC_TRIM_CH10_SEL = MT6351_PMIC_AUXADC_TRIM_CH10_SEL, + PMIC_AUXADC_TRIM_CH11_SEL = MT6351_PMIC_AUXADC_TRIM_CH11_SEL, + PMIC_AUXADC_ADC_2S_COMP_ENB = MT6351_PMIC_AUXADC_ADC_2S_COMP_ENB, + PMIC_AUXADC_ADC_TRIM_COMP = MT6351_PMIC_AUXADC_ADC_TRIM_COMP, + PMIC_AUXADC_SW_GAIN_TRIM = MT6351_PMIC_AUXADC_SW_GAIN_TRIM, + PMIC_AUXADC_SW_OFFSET_TRIM = MT6351_PMIC_AUXADC_SW_OFFSET_TRIM, + PMIC_AUXADC_RNG_EN = MT6351_PMIC_AUXADC_RNG_EN, + PMIC_AUXADC_DATA_REUSE_SEL = MT6351_PMIC_AUXADC_DATA_REUSE_SEL, + PMIC_AUXADC_TEST_MODE = MT6351_PMIC_AUXADC_TEST_MODE, + PMIC_AUXADC_BIT_SEL = MT6351_PMIC_AUXADC_BIT_SEL, + PMIC_AUXADC_START_SW = MT6351_PMIC_AUXADC_START_SW, + PMIC_AUXADC_START_SWCTRL = MT6351_PMIC_AUXADC_START_SWCTRL, + PMIC_AUXADC_TS_VBE_SEL = MT6351_PMIC_AUXADC_TS_VBE_SEL, + PMIC_AUXADC_TS_VBE_SEL_SWCTRL = MT6351_PMIC_AUXADC_TS_VBE_SEL_SWCTRL, + PMIC_AUXADC_VBUF_EN = MT6351_PMIC_AUXADC_VBUF_EN, + PMIC_AUXADC_VBUF_EN_SWCTRL = MT6351_PMIC_AUXADC_VBUF_EN_SWCTRL, + PMIC_AUXADC_OUT_SEL = MT6351_PMIC_AUXADC_OUT_SEL, + PMIC_AUXADC_DA_DAC = MT6351_PMIC_AUXADC_DA_DAC, + PMIC_AUXADC_DA_DAC_SWCTRL = MT6351_PMIC_AUXADC_DA_DAC_SWCTRL, + PMIC_AD_AUXADC_COMP = MT6351_PMIC_AD_AUXADC_COMP, + PMIC_RG_VBUF_EXTEN = MT6351_PMIC_RG_VBUF_EXTEN, + PMIC_RG_VBUF_CALEN = MT6351_PMIC_RG_VBUF_CALEN, + PMIC_RG_VBUF_BYP = MT6351_PMIC_RG_VBUF_BYP, + PMIC_RG_AUX_RSV = MT6351_PMIC_RG_AUX_RSV, + PMIC_RG_AUXADC_CALI = MT6351_PMIC_RG_AUXADC_CALI, + PMIC_AUXADC_ADCIN_VSEN_EN = MT6351_PMIC_AUXADC_ADCIN_VSEN_EN, + PMIC_AUXADC_ADCIN_VBAT_EN = MT6351_PMIC_AUXADC_ADCIN_VBAT_EN, + PMIC_AUXADC_ADCIN_VSEN_MUX_EN = MT6351_PMIC_AUXADC_ADCIN_VSEN_MUX_EN, + PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN = MT6351_PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN, + PMIC_AUXADC_ADCIN_CHR_EN = MT6351_PMIC_AUXADC_ADCIN_CHR_EN, + PMIC_AUXADC_ADCIN_BATON_TDET_EN = MT6351_PMIC_AUXADC_ADCIN_BATON_TDET_EN, + PMIC_AUXADC_ACCDET_ANASWCTRL_EN = MT6351_PMIC_AUXADC_ACCDET_ANASWCTRL_EN, + PMIC_AUXADC_DIG0_RSV0 = MT6351_PMIC_AUXADC_DIG0_RSV0, + PMIC_AUXADC_CHSEL = MT6351_PMIC_AUXADC_CHSEL, + PMIC_AUXADC_SWCTRL_EN = MT6351_PMIC_AUXADC_SWCTRL_EN, + PMIC_AUXADC_SOURCE_LBAT_SEL = MT6351_PMIC_AUXADC_SOURCE_LBAT_SEL, + PMIC_AUXADC_SOURCE_LBAT2_SEL = MT6351_PMIC_AUXADC_SOURCE_LBAT2_SEL, + PMIC_AUXADC_DIG0_RSV2 = MT6351_PMIC_AUXADC_DIG0_RSV2, + PMIC_AUXADC_DIG1_RSV2 = MT6351_PMIC_AUXADC_DIG1_RSV2, + PMIC_AUXADC_DAC_EXTD = MT6351_PMIC_AUXADC_DAC_EXTD, + PMIC_AUXADC_DAC_EXTD_EN = MT6351_PMIC_AUXADC_DAC_EXTD_EN, + PMIC_AUXADC_PMU_THR_PDN_SW = MT6351_PMIC_AUXADC_PMU_THR_PDN_SW, + PMIC_AUXADC_PMU_THR_PDN_SEL = MT6351_PMIC_AUXADC_PMU_THR_PDN_SEL, + PMIC_AUXADC_PMU_THR_PDN_STATUS = MT6351_PMIC_AUXADC_PMU_THR_PDN_STATUS, + PMIC_AUXADC_DIG0_RSV1 = MT6351_PMIC_AUXADC_DIG0_RSV1, + PMIC_AUXADC_START_SHADE_NUM = MT6351_PMIC_AUXADC_START_SHADE_NUM, + PMIC_AUXADC_START_SHADE_EN = MT6351_PMIC_AUXADC_START_SHADE_EN, + PMIC_AUXADC_START_SHADE_SEL = MT6351_PMIC_AUXADC_START_SHADE_SEL, + PMIC_AUXADC_AUTORPT_PRD = MT6351_PMIC_AUXADC_AUTORPT_PRD, + PMIC_AUXADC_AUTORPT_EN = MT6351_PMIC_AUXADC_AUTORPT_EN, + PMIC_AUXADC_LBAT_DEBT_MAX = MT6351_PMIC_AUXADC_LBAT_DEBT_MAX, + PMIC_AUXADC_LBAT_DEBT_MIN = MT6351_PMIC_AUXADC_LBAT_DEBT_MIN, + PMIC_AUXADC_LBAT_DET_PRD_15_0 = MT6351_PMIC_AUXADC_LBAT_DET_PRD_15_0, + PMIC_AUXADC_LBAT_DET_PRD_19_16 = MT6351_PMIC_AUXADC_LBAT_DET_PRD_19_16, + PMIC_AUXADC_LBAT_VOLT_MAX = MT6351_PMIC_AUXADC_LBAT_VOLT_MAX, + PMIC_AUXADC_LBAT_IRQ_EN_MAX = MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MAX, + PMIC_AUXADC_LBAT_EN_MAX = MT6351_PMIC_AUXADC_LBAT_EN_MAX, + PMIC_AUXADC_LBAT_MAX_IRQ_B = MT6351_PMIC_AUXADC_LBAT_MAX_IRQ_B, + PMIC_AUXADC_LBAT_VOLT_MIN = MT6351_PMIC_AUXADC_LBAT_VOLT_MIN, + PMIC_AUXADC_LBAT_IRQ_EN_MIN = MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MIN, + PMIC_AUXADC_LBAT_EN_MIN = MT6351_PMIC_AUXADC_LBAT_EN_MIN, + PMIC_AUXADC_LBAT_MIN_IRQ_B = MT6351_PMIC_AUXADC_LBAT_MIN_IRQ_B, + PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX = MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN = MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN, + PMIC_AUXADC_ACCDET_AUTO_SPL = MT6351_PMIC_AUXADC_ACCDET_AUTO_SPL, + PMIC_AUXADC_ACCDET_AUTO_RQST_CLR = MT6351_PMIC_AUXADC_ACCDET_AUTO_RQST_CLR, + PMIC_AUXADC_ACCDET_DIG1_RSV0 = MT6351_PMIC_AUXADC_ACCDET_DIG1_RSV0, + PMIC_AUXADC_ACCDET_DIG0_RSV0 = MT6351_PMIC_AUXADC_ACCDET_DIG0_RSV0, + PMIC_AUXADC_THR_DEBT_MAX = MT6351_PMIC_AUXADC_THR_DEBT_MAX, + PMIC_AUXADC_THR_DEBT_MIN = MT6351_PMIC_AUXADC_THR_DEBT_MIN, + PMIC_AUXADC_THR_DET_PRD_15_0 = MT6351_PMIC_AUXADC_THR_DET_PRD_15_0, + PMIC_AUXADC_THR_DET_PRD_19_16 = MT6351_PMIC_AUXADC_THR_DET_PRD_19_16, + PMIC_AUXADC_THR_VOLT_MAX = MT6351_PMIC_AUXADC_THR_VOLT_MAX, + PMIC_AUXADC_THR_IRQ_EN_MAX = MT6351_PMIC_AUXADC_THR_IRQ_EN_MAX, + PMIC_AUXADC_THR_EN_MAX = MT6351_PMIC_AUXADC_THR_EN_MAX, + PMIC_AUXADC_THR_MAX_IRQ_B = MT6351_PMIC_AUXADC_THR_MAX_IRQ_B, + PMIC_AUXADC_THR_VOLT_MIN = MT6351_PMIC_AUXADC_THR_VOLT_MIN, + PMIC_AUXADC_THR_IRQ_EN_MIN = MT6351_PMIC_AUXADC_THR_IRQ_EN_MIN, + PMIC_AUXADC_THR_EN_MIN = MT6351_PMIC_AUXADC_THR_EN_MIN, + PMIC_AUXADC_THR_MIN_IRQ_B = MT6351_PMIC_AUXADC_THR_MIN_IRQ_B, + PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX = MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN = MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN, + PMIC_EFUSE_GAIN_CH4_TRIM = MT6351_PMIC_EFUSE_GAIN_CH4_TRIM, + PMIC_EFUSE_OFFSET_CH4_TRIM = MT6351_PMIC_EFUSE_OFFSET_CH4_TRIM, + PMIC_EFUSE_GAIN_CH0_TRIM = MT6351_PMIC_EFUSE_GAIN_CH0_TRIM, + PMIC_EFUSE_OFFSET_CH0_TRIM = MT6351_PMIC_EFUSE_OFFSET_CH0_TRIM, + PMIC_EFUSE_GAIN_CH7_TRIM = MT6351_PMIC_EFUSE_GAIN_CH7_TRIM, + PMIC_EFUSE_OFFSET_CH7_TRIM = MT6351_PMIC_EFUSE_OFFSET_CH7_TRIM, + PMIC_AUXADC_FGADC_START_SW = MT6351_PMIC_AUXADC_FGADC_START_SW, + PMIC_AUXADC_FGADC_START_SEL = MT6351_PMIC_AUXADC_FGADC_START_SEL, + PMIC_AUXADC_FGADC_R_SW = MT6351_PMIC_AUXADC_FGADC_R_SW, + PMIC_AUXADC_FGADC_R_SEL = MT6351_PMIC_AUXADC_FGADC_R_SEL, + PMIC_AUXADC_DBG_DIG0_RSV2 = MT6351_PMIC_AUXADC_DBG_DIG0_RSV2, + PMIC_AUXADC_DBG_DIG1_RSV2 = MT6351_PMIC_AUXADC_DBG_DIG1_RSV2, + PMIC_AUXADC_IMPEDANCE_CNT = MT6351_PMIC_AUXADC_IMPEDANCE_CNT, + PMIC_AUXADC_IMPEDANCE_CHSEL = MT6351_PMIC_AUXADC_IMPEDANCE_CHSEL, + PMIC_AUXADC_IMPEDANCE_IRQ_CLR = MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_CLR, + PMIC_AUXADC_IMPEDANCE_IRQ_STATUS = MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS, + PMIC_AUXADC_CLR_IMP_CNT_STOP = MT6351_PMIC_AUXADC_CLR_IMP_CNT_STOP, + PMIC_AUXADC_IMPEDANCE_MODE = MT6351_PMIC_AUXADC_IMPEDANCE_MODE, + PMIC_AUXADC_IMP_AUTORPT_PRD = MT6351_PMIC_AUXADC_IMP_AUTORPT_PRD, + PMIC_AUXADC_IMP_AUTORPT_EN = MT6351_PMIC_AUXADC_IMP_AUTORPT_EN, + PMIC_AUXADC_VISMPS0_DEBT_MAX = MT6351_PMIC_AUXADC_VISMPS0_DEBT_MAX, + PMIC_AUXADC_VISMPS0_DEBT_MIN = MT6351_PMIC_AUXADC_VISMPS0_DEBT_MIN, + PMIC_AUXADC_VISMPS0_DET_PRD_15_0 = MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_15_0, + PMIC_AUXADC_VISMPS0_DET_PRD_19_16 = MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_19_16, + PMIC_AUXADC_VISMPS0_VOLT_MAX = MT6351_PMIC_AUXADC_VISMPS0_VOLT_MAX, + PMIC_AUXADC_VISMPS0_IRQ_EN_MAX = MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MAX, + PMIC_AUXADC_VISMPS0_EN_MAX = MT6351_PMIC_AUXADC_VISMPS0_EN_MAX, + PMIC_AUXADC_VISMPS0_MAX_IRQ_B = MT6351_PMIC_AUXADC_VISMPS0_MAX_IRQ_B, + PMIC_AUXADC_VISMPS0_VOLT_MIN = MT6351_PMIC_AUXADC_VISMPS0_VOLT_MIN, + PMIC_AUXADC_VISMPS0_IRQ_EN_MIN = MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MIN, + PMIC_AUXADC_VISMPS0_EN_MIN = MT6351_PMIC_AUXADC_VISMPS0_EN_MIN, + PMIC_AUXADC_VISMPS0_MIN_IRQ_B = MT6351_PMIC_AUXADC_VISMPS0_MIN_IRQ_B, + PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX = MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN = MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN, + PMIC_AUXADC_LBAT2_DEBT_MAX = MT6351_PMIC_AUXADC_LBAT2_DEBT_MAX, + PMIC_AUXADC_LBAT2_DEBT_MIN = MT6351_PMIC_AUXADC_LBAT2_DEBT_MIN, + PMIC_AUXADC_LBAT2_DET_PRD_15_0 = MT6351_PMIC_AUXADC_LBAT2_DET_PRD_15_0, + PMIC_AUXADC_LBAT2_DET_PRD_19_16 = MT6351_PMIC_AUXADC_LBAT2_DET_PRD_19_16, + PMIC_AUXADC_LBAT2_VOLT_MAX = MT6351_PMIC_AUXADC_LBAT2_VOLT_MAX, + PMIC_AUXADC_LBAT2_IRQ_EN_MAX = MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MAX, + PMIC_AUXADC_LBAT2_EN_MAX = MT6351_PMIC_AUXADC_LBAT2_EN_MAX, + PMIC_AUXADC_LBAT2_MAX_IRQ_B = MT6351_PMIC_AUXADC_LBAT2_MAX_IRQ_B, + PMIC_AUXADC_LBAT2_VOLT_MIN = MT6351_PMIC_AUXADC_LBAT2_VOLT_MIN, + PMIC_AUXADC_LBAT2_IRQ_EN_MIN = MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MIN, + PMIC_AUXADC_LBAT2_EN_MIN = MT6351_PMIC_AUXADC_LBAT2_EN_MIN, + PMIC_AUXADC_LBAT2_MIN_IRQ_B = MT6351_PMIC_AUXADC_LBAT2_MIN_IRQ_B, + PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX = MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX, + PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN = MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN, + PMIC_AUXADC_MDBG_DET_PRD = MT6351_PMIC_AUXADC_MDBG_DET_PRD, + PMIC_AUXADC_MDBG_DET_EN = MT6351_PMIC_AUXADC_MDBG_DET_EN, + PMIC_AUXADC_MDBG_R_PTR = MT6351_PMIC_AUXADC_MDBG_R_PTR, + PMIC_AUXADC_MDBG_W_PTR = MT6351_PMIC_AUXADC_MDBG_W_PTR, + PMIC_AUXADC_MDBG_BUF_LENGTH = MT6351_PMIC_AUXADC_MDBG_BUF_LENGTH, + PMIC_AUXADC_MDRT_DET_PRD = MT6351_PMIC_AUXADC_MDRT_DET_PRD, + PMIC_AUXADC_MDRT_DET_EN = MT6351_PMIC_AUXADC_MDRT_DET_EN, + PMIC_AUXADC_MDRT_DET_WKUP_START_CNT = MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CNT, + PMIC_AUXADC_MDRT_DET_WKUP_START_CLR = MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CLR, + PMIC_AUXADC_MDRT_DET_WKUP_START = MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START, + PMIC_AUXADC_MDRT_DET_WKUP_START_SEL = MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SEL, + PMIC_AUXADC_MDRT_DET_WKUP_EN = MT6351_PMIC_AUXADC_MDRT_DET_WKUP_EN, + PMIC_AUXADC_MDRT_DET_SRCLKEN_IND = MT6351_PMIC_AUXADC_MDRT_DET_SRCLKEN_IND, + PMIC_AUXADC_JEITA_IRQ_EN = MT6351_PMIC_AUXADC_JEITA_IRQ_EN, + PMIC_AUXADC_JEITA_EN = MT6351_PMIC_AUXADC_JEITA_EN, + PMIC_AUXADC_JEITA_DET_PRD = MT6351_PMIC_AUXADC_JEITA_DET_PRD, + PMIC_AUXADC_JEITA_DEBT = MT6351_PMIC_AUXADC_JEITA_DEBT, + PMIC_AUXADC_JEITA_MIPI_DIS = MT6351_PMIC_AUXADC_JEITA_MIPI_DIS, + PMIC_AUXADC_JEITA_VOLT_HOT = MT6351_PMIC_AUXADC_JEITA_VOLT_HOT, + PMIC_AUXADC_JEITA_HOT_IRQ = MT6351_PMIC_AUXADC_JEITA_HOT_IRQ, + PMIC_AUXADC_JEITA_VOLT_WARM = MT6351_PMIC_AUXADC_JEITA_VOLT_WARM, + PMIC_AUXADC_JEITA_WARM_IRQ = MT6351_PMIC_AUXADC_JEITA_WARM_IRQ, + PMIC_AUXADC_JEITA_VOLT_COOL = MT6351_PMIC_AUXADC_JEITA_VOLT_COOL, + PMIC_AUXADC_JEITA_COOL_IRQ = MT6351_PMIC_AUXADC_JEITA_COOL_IRQ, + PMIC_AUXADC_JEITA_VOLT_COLD = MT6351_PMIC_AUXADC_JEITA_VOLT_COLD, + PMIC_AUXADC_JEITA_COLD_IRQ = MT6351_PMIC_AUXADC_JEITA_COLD_IRQ, + PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD = MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD, + PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL = MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL, + PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM = MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM, + PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT = MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT, + PMIC_AUXADC_DCXO_MDRT_DET_PRD = MT6351_PMIC_AUXADC_DCXO_MDRT_DET_PRD, + PMIC_AUXADC_DCXO_MDRT_DET_EN = MT6351_PMIC_AUXADC_DCXO_MDRT_DET_EN, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT = MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR = MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN = MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL = MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL, + PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START = MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START, + PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND = MT6351_PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND, + PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL = MT6351_PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL, + PMIC_AUXADC_NAG_EN = MT6351_PMIC_AUXADC_NAG_EN, + PMIC_AUXADC_NAG_CLR = MT6351_PMIC_AUXADC_NAG_CLR, + PMIC_AUXADC_NAG_VBAT1_SEL = MT6351_PMIC_AUXADC_NAG_VBAT1_SEL, + PMIC_AUXADC_NAG_PRD = MT6351_PMIC_AUXADC_NAG_PRD, + PMIC_AUXADC_NAG_IRQ_EN = MT6351_PMIC_AUXADC_NAG_IRQ_EN, + PMIC_AUXADC_NAG_C_DLTV_IRQ = MT6351_PMIC_AUXADC_NAG_C_DLTV_IRQ, + PMIC_AUXADC_NAG_ZCV = MT6351_PMIC_AUXADC_NAG_ZCV, + PMIC_AUXADC_NAG_C_DLTV_TH_15_0 = MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_15_0, + PMIC_AUXADC_NAG_C_DLTV_TH_26_16 = MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_26_16, + PMIC_AUXADC_NAG_CNT_15_0 = MT6351_PMIC_AUXADC_NAG_CNT_15_0, + PMIC_AUXADC_NAG_CNT_25_16 = MT6351_PMIC_AUXADC_NAG_CNT_25_16, + PMIC_AUXADC_NAG_DLTV = MT6351_PMIC_AUXADC_NAG_DLTV, + PMIC_AUXADC_NAG_C_DLTV_15_0 = MT6351_PMIC_AUXADC_NAG_C_DLTV_15_0, + PMIC_AUXADC_NAG_C_DLTV_26_16 = MT6351_PMIC_AUXADC_NAG_C_DLTV_26_16, + PMIC_AD_AUDACCDETCMPOC = MT6351_PMIC_AD_AUDACCDETCMPOC, + PMIC_RG_AUDACCDETANASWCTRLENB = MT6351_PMIC_RG_AUDACCDETANASWCTRLENB, + PMIC_RG_ACCDETSEL = MT6351_PMIC_RG_ACCDETSEL, + PMIC_RG_AUDACCDETSWCTRL = MT6351_PMIC_RG_AUDACCDETSWCTRL, + PMIC_RG_AUDACCDETTVDET = MT6351_PMIC_RG_AUDACCDETTVDET, + PMIC_AUDACCDETAUXADCSWCTRL = MT6351_PMIC_AUDACCDETAUXADCSWCTRL, + PMIC_AUDACCDETAUXADCSWCTRL_SEL = MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SEL, + PMIC_RG_AUDACCDETRSV = MT6351_PMIC_RG_AUDACCDETRSV, + PMIC_ACCDET_EN = MT6351_PMIC_ACCDET_EN, + PMIC_ACCDET_SEQ_INIT = MT6351_PMIC_ACCDET_SEQ_INIT, + PMIC_ACCDET_EINTDET_EN = MT6351_PMIC_ACCDET_EINTDET_EN, + PMIC_ACCDET_EINT_SEQ_INIT = MT6351_PMIC_ACCDET_EINT_SEQ_INIT, + PMIC_ACCDET_NEGVDET_EN = MT6351_PMIC_ACCDET_NEGVDET_EN, + PMIC_ACCDET_NEGVDET_EN_CTRL = MT6351_PMIC_ACCDET_NEGVDET_EN_CTRL, + PMIC_ACCDET_ANASWCTRL_SEL = MT6351_PMIC_ACCDET_ANASWCTRL_SEL, + PMIC_ACCDET_CMP_PWM_EN = MT6351_PMIC_ACCDET_CMP_PWM_EN, + PMIC_ACCDET_VTH_PWM_EN = MT6351_PMIC_ACCDET_VTH_PWM_EN, + PMIC_ACCDET_MBIAS_PWM_EN = MT6351_PMIC_ACCDET_MBIAS_PWM_EN, + PMIC_ACCDET_EINT_PWM_EN = MT6351_PMIC_ACCDET_EINT_PWM_EN, + PMIC_ACCDET_CMP_PWM_IDLE = MT6351_PMIC_ACCDET_CMP_PWM_IDLE, + PMIC_ACCDET_VTH_PWM_IDLE = MT6351_PMIC_ACCDET_VTH_PWM_IDLE, + PMIC_ACCDET_MBIAS_PWM_IDLE = MT6351_PMIC_ACCDET_MBIAS_PWM_IDLE, + PMIC_ACCDET_EINT_PWM_IDLE = MT6351_PMIC_ACCDET_EINT_PWM_IDLE, + PMIC_ACCDET_PWM_WIDTH = MT6351_PMIC_ACCDET_PWM_WIDTH, + PMIC_ACCDET_PWM_THRESH = MT6351_PMIC_ACCDET_PWM_THRESH, + PMIC_ACCDET_RISE_DELAY = MT6351_PMIC_ACCDET_RISE_DELAY, + PMIC_ACCDET_FALL_DELAY = MT6351_PMIC_ACCDET_FALL_DELAY, + PMIC_ACCDET_DEBOUNCE0 = MT6351_PMIC_ACCDET_DEBOUNCE0, + PMIC_ACCDET_DEBOUNCE1 = MT6351_PMIC_ACCDET_DEBOUNCE1, + PMIC_ACCDET_DEBOUNCE2 = MT6351_PMIC_ACCDET_DEBOUNCE2, + PMIC_ACCDET_DEBOUNCE3 = MT6351_PMIC_ACCDET_DEBOUNCE3, + PMIC_ACCDET_DEBOUNCE4 = MT6351_PMIC_ACCDET_DEBOUNCE4, + PMIC_ACCDET_IVAL_CUR_IN = MT6351_PMIC_ACCDET_IVAL_CUR_IN, + PMIC_ACCDET_EINT_IVAL_CUR_IN = MT6351_PMIC_ACCDET_EINT_IVAL_CUR_IN, + PMIC_ACCDET_IVAL_SAM_IN = MT6351_PMIC_ACCDET_IVAL_SAM_IN, + PMIC_ACCDET_EINT_IVAL_SAM_IN = MT6351_PMIC_ACCDET_EINT_IVAL_SAM_IN, + PMIC_ACCDET_IVAL_MEM_IN = MT6351_PMIC_ACCDET_IVAL_MEM_IN, + PMIC_ACCDET_EINT_IVAL_MEM_IN = MT6351_PMIC_ACCDET_EINT_IVAL_MEM_IN, + PMIC_ACCDET_EINT_IVAL_SEL = MT6351_PMIC_ACCDET_EINT_IVAL_SEL, + PMIC_ACCDET_IVAL_SEL = MT6351_PMIC_ACCDET_IVAL_SEL, + PMIC_ACCDET_IRQ = MT6351_PMIC_ACCDET_IRQ, + PMIC_ACCDET_NEGV_IRQ = MT6351_PMIC_ACCDET_NEGV_IRQ, + PMIC_ACCDET_EINT_IRQ = MT6351_PMIC_ACCDET_EINT_IRQ, + PMIC_ACCDET_IRQ_CLR = MT6351_PMIC_ACCDET_IRQ_CLR, + PMIC_ACCDET_NEGV_IRQ_CLR = MT6351_PMIC_ACCDET_NEGV_IRQ_CLR, + PMIC_ACCDET_EINT_IRQ_CLR = MT6351_PMIC_ACCDET_EINT_IRQ_CLR, + PMIC_ACCDET_EINT_IRQ_POLARITY = MT6351_PMIC_ACCDET_EINT_IRQ_POLARITY, + PMIC_ACCDET_TEST_MODE0 = MT6351_PMIC_ACCDET_TEST_MODE0, + PMIC_ACCDET_TEST_MODE1 = MT6351_PMIC_ACCDET_TEST_MODE1, + PMIC_ACCDET_TEST_MODE2 = MT6351_PMIC_ACCDET_TEST_MODE2, + PMIC_ACCDET_TEST_MODE3 = MT6351_PMIC_ACCDET_TEST_MODE3, + PMIC_ACCDET_TEST_MODE4 = MT6351_PMIC_ACCDET_TEST_MODE4, + PMIC_ACCDET_TEST_MODE5 = MT6351_PMIC_ACCDET_TEST_MODE5, + PMIC_ACCDET_PWM_SEL = MT6351_PMIC_ACCDET_PWM_SEL, + PMIC_ACCDET_IN_SW = MT6351_PMIC_ACCDET_IN_SW, + PMIC_ACCDET_CMP_EN_SW = MT6351_PMIC_ACCDET_CMP_EN_SW, + PMIC_ACCDET_VTH_EN_SW = MT6351_PMIC_ACCDET_VTH_EN_SW, + PMIC_ACCDET_MBIAS_EN_SW = MT6351_PMIC_ACCDET_MBIAS_EN_SW, + PMIC_ACCDET_PWM_EN_SW = MT6351_PMIC_ACCDET_PWM_EN_SW, + PMIC_ACCDET_IN = MT6351_PMIC_ACCDET_IN, + PMIC_ACCDET_CUR_IN = MT6351_PMIC_ACCDET_CUR_IN, + PMIC_ACCDET_SAM_IN = MT6351_PMIC_ACCDET_SAM_IN, + PMIC_ACCDET_MEM_IN = MT6351_PMIC_ACCDET_MEM_IN, + PMIC_ACCDET_STATE = MT6351_PMIC_ACCDET_STATE, + PMIC_ACCDET_MBIAS_CLK = MT6351_PMIC_ACCDET_MBIAS_CLK, + PMIC_ACCDET_VTH_CLK = MT6351_PMIC_ACCDET_VTH_CLK, + PMIC_ACCDET_CMP_CLK = MT6351_PMIC_ACCDET_CMP_CLK, + PMIC_DA_NI_AUDACCDETAUXADCSWCTRL = MT6351_PMIC_DA_NI_AUDACCDETAUXADCSWCTRL, + PMIC_ACCDET_EINT_DEB_SEL = MT6351_PMIC_ACCDET_EINT_DEB_SEL, + PMIC_ACCDET_EINT_DEBOUNCE = MT6351_PMIC_ACCDET_EINT_DEBOUNCE, + PMIC_ACCDET_EINT_PWM_THRESH = MT6351_PMIC_ACCDET_EINT_PWM_THRESH, + PMIC_ACCDET_EINT_PWM_WIDTH = MT6351_PMIC_ACCDET_EINT_PWM_WIDTH, + PMIC_ACCDET_NEGV_THRESH = MT6351_PMIC_ACCDET_NEGV_THRESH, + PMIC_ACCDET_EINT_PWM_FALL_DELAY = MT6351_PMIC_ACCDET_EINT_PWM_FALL_DELAY, + PMIC_ACCDET_EINT_PWM_RISE_DELAY = MT6351_PMIC_ACCDET_EINT_PWM_RISE_DELAY, + PMIC_ACCDET_TEST_MODE13 = MT6351_PMIC_ACCDET_TEST_MODE13, + PMIC_ACCDET_TEST_MODE12 = MT6351_PMIC_ACCDET_TEST_MODE12, + PMIC_ACCDET_NVDETECTOUT_SW = MT6351_PMIC_ACCDET_NVDETECTOUT_SW, + PMIC_ACCDET_TEST_MODE11 = MT6351_PMIC_ACCDET_TEST_MODE11, + PMIC_ACCDET_TEST_MODE10 = MT6351_PMIC_ACCDET_TEST_MODE10, + PMIC_ACCDET_EINTCMPOUT_SW = MT6351_PMIC_ACCDET_EINTCMPOUT_SW, + PMIC_ACCDET_TEST_MODE9 = MT6351_PMIC_ACCDET_TEST_MODE9, + PMIC_ACCDET_TEST_MODE8 = MT6351_PMIC_ACCDET_TEST_MODE8, + PMIC_ACCDET_AUXADC_CTRL_SW = MT6351_PMIC_ACCDET_AUXADC_CTRL_SW, + PMIC_ACCDET_TEST_MODE7 = MT6351_PMIC_ACCDET_TEST_MODE7, + PMIC_ACCDET_TEST_MODE6 = MT6351_PMIC_ACCDET_TEST_MODE6, + PMIC_ACCDET_EINTCMP_EN_SW = MT6351_PMIC_ACCDET_EINTCMP_EN_SW, + PMIC_ACCDET_EINT_STATE = MT6351_PMIC_ACCDET_EINT_STATE, + PMIC_ACCDET_AUXADC_DEBOUNCE_END = MT6351_PMIC_ACCDET_AUXADC_DEBOUNCE_END, + PMIC_ACCDET_AUXADC_CONNECT_PRE = MT6351_PMIC_ACCDET_AUXADC_CONNECT_PRE, + PMIC_ACCDET_EINT_CUR_IN = MT6351_PMIC_ACCDET_EINT_CUR_IN, + PMIC_ACCDET_EINT_SAM_IN = MT6351_PMIC_ACCDET_EINT_SAM_IN, + PMIC_ACCDET_EINT_MEM_IN = MT6351_PMIC_ACCDET_EINT_MEM_IN, + PMIC_AD_NVDETECTOUT = MT6351_PMIC_AD_NVDETECTOUT, + PMIC_AD_EINTCMPOUT = MT6351_PMIC_AD_EINTCMPOUT, + PMIC_DA_NI_EINTCMPEN = MT6351_PMIC_DA_NI_EINTCMPEN, + PMIC_ACCDET_NEGV_COUNT_IN = MT6351_PMIC_ACCDET_NEGV_COUNT_IN, + PMIC_ACCDET_NEGV_EN_FINAL = MT6351_PMIC_ACCDET_NEGV_EN_FINAL, + PMIC_ACCDET_NEGV_COUNT_END = MT6351_PMIC_ACCDET_NEGV_COUNT_END, + PMIC_ACCDET_NEGV_MINU = MT6351_PMIC_ACCDET_NEGV_MINU, + PMIC_ACCDET_NEGV_ADD = MT6351_PMIC_ACCDET_NEGV_ADD, + PMIC_ACCDET_NEGV_CMP = MT6351_PMIC_ACCDET_NEGV_CMP, + PMIC_ACCDET_CUR_DEB = MT6351_PMIC_ACCDET_CUR_DEB, + PMIC_ACCDET_EINT_CUR_DEB = MT6351_PMIC_ACCDET_EINT_CUR_DEB, + PMIC_ACCDET_RSV_CON0 = MT6351_PMIC_ACCDET_RSV_CON0, + PMIC_ACCDET_RSV_CON1 = MT6351_PMIC_ACCDET_RSV_CON1, + PMIC_ACCDET_AUXADC_CONNECT_TIME = MT6351_PMIC_ACCDET_AUXADC_CONNECT_TIME, + PMIC_RG_VCDT_HV_EN = MT6351_PMIC_RG_VCDT_HV_EN, + PMIC_RGS_CHR_LDO_DET = MT6351_PMIC_RGS_CHR_LDO_DET, + PMIC_RG_PCHR_AUTOMODE = MT6351_PMIC_RG_PCHR_AUTOMODE, + PMIC_RG_CSDAC_EN = MT6351_PMIC_RG_CSDAC_EN, + PMIC_RG_NORM_CHR_EN = MT6351_PMIC_RG_NORM_CHR_EN, + PMIC_RGS_CHRDET = MT6351_PMIC_RGS_CHRDET, + PMIC_RGS_VCDT_LV_DET = MT6351_PMIC_RGS_VCDT_LV_DET, + PMIC_RGS_VCDT_HV_DET = MT6351_PMIC_RGS_VCDT_HV_DET, + PMIC_RG_VCDT_LV_VTH = MT6351_PMIC_RG_VCDT_LV_VTH, + PMIC_RG_VCDT_HV_VTH = MT6351_PMIC_RG_VCDT_HV_VTH, + PMIC_RG_VBAT_CV_EN = MT6351_PMIC_RG_VBAT_CV_EN, + PMIC_RG_VBAT_CC_EN = MT6351_PMIC_RG_VBAT_CC_EN, + PMIC_RG_CS_EN = MT6351_PMIC_RG_CS_EN, + PMIC_RGS_CS_DET = MT6351_PMIC_RGS_CS_DET, + PMIC_RGS_VBAT_CV_DET = MT6351_PMIC_RGS_VBAT_CV_DET, + PMIC_RGS_VBAT_CC_DET = MT6351_PMIC_RGS_VBAT_CC_DET, + PMIC_RG_VBAT_NORM_CV_VTH = MT6351_PMIC_RG_VBAT_NORM_CV_VTH, + PMIC_RG_VBAT_CC_VTH = MT6351_PMIC_RG_VBAT_CC_VTH, + PMIC_RG_NORM_CS_VTH = MT6351_PMIC_RG_NORM_CS_VTH, + PMIC_RG_PCHR_TOHTC = MT6351_PMIC_RG_PCHR_TOHTC, + PMIC_RG_PCHR_TOLTC = MT6351_PMIC_RG_PCHR_TOLTC, + PMIC_RG_VBAT_OV_EN = MT6351_PMIC_RG_VBAT_OV_EN, + PMIC_RG_VBAT_OV_VTH = MT6351_PMIC_RG_VBAT_OV_VTH, + PMIC_RG_VBAT_OV_DEG = MT6351_PMIC_RG_VBAT_OV_DEG, + PMIC_RGS_VBAT_OV_DET = MT6351_PMIC_RGS_VBAT_OV_DET, + PMIC_RG_BATON_EN = MT6351_PMIC_RG_BATON_EN, + PMIC_RG_BATON_HT_EN_RSV0 = MT6351_PMIC_RG_BATON_HT_EN_RSV0, + PMIC_BATON_TDET_EN = MT6351_PMIC_BATON_TDET_EN, + PMIC_RG_BATON_HT_TRIM = MT6351_PMIC_RG_BATON_HT_TRIM, + PMIC_RG_BATON_HT_TRIM_SET = MT6351_PMIC_RG_BATON_HT_TRIM_SET, + PMIC_RG_BATON_TDET_EN = MT6351_PMIC_RG_BATON_TDET_EN, + PMIC_RG_CSDAC_DATA = MT6351_PMIC_RG_CSDAC_DATA, + PMIC_RG_FRC_CSVTH_USBDL = MT6351_PMIC_RG_FRC_CSVTH_USBDL, + PMIC_RGS_PCHR_FLAG_OUT = MT6351_PMIC_RGS_PCHR_FLAG_OUT, + PMIC_RG_PCHR_FLAG_EN = MT6351_PMIC_RG_PCHR_FLAG_EN, + PMIC_RG_OTG_BVALID_EN = MT6351_PMIC_RG_OTG_BVALID_EN, + PMIC_RGS_OTG_BVALID_DET = MT6351_PMIC_RGS_OTG_BVALID_DET, + PMIC_RG_PCHR_FLAG_SEL = MT6351_PMIC_RG_PCHR_FLAG_SEL, + PMIC_RG_PCHR_TESTMODE = MT6351_PMIC_RG_PCHR_TESTMODE, + PMIC_RG_CSDAC_TESTMODE = MT6351_PMIC_RG_CSDAC_TESTMODE, + PMIC_RG_PCHR_RST = MT6351_PMIC_RG_PCHR_RST, + PMIC_RG_PCHR_FT_CTRL = MT6351_PMIC_RG_PCHR_FT_CTRL, + PMIC_RG_CHRWDT_TD = MT6351_PMIC_RG_CHRWDT_TD, + PMIC_RG_CHRWDT_EN = MT6351_PMIC_RG_CHRWDT_EN, + PMIC_RG_CHRWDT_WR = MT6351_PMIC_RG_CHRWDT_WR, + PMIC_RG_PCHR_RV = MT6351_PMIC_RG_PCHR_RV, + PMIC_RG_CHRWDT_INT_EN = MT6351_PMIC_RG_CHRWDT_INT_EN, + PMIC_RG_CHRWDT_FLAG_WR = MT6351_PMIC_RG_CHRWDT_FLAG_WR, + PMIC_RGS_CHRWDT_OUT = MT6351_PMIC_RGS_CHRWDT_OUT, + PMIC_RG_USBDL_RST = MT6351_PMIC_RG_USBDL_RST, + PMIC_RG_USBDL_SET = MT6351_PMIC_RG_USBDL_SET, + PMIC_RG_ADCIN_VSEN_MUX_EN = MT6351_PMIC_RG_ADCIN_VSEN_MUX_EN, + PMIC_RG_ADCIN_VSEN_EXT_BATON_EN = MT6351_PMIC_RG_ADCIN_VSEN_EXT_BATON_EN, + PMIC_RG_ADCIN_VBAT_EN = MT6351_PMIC_RG_ADCIN_VBAT_EN, + PMIC_RG_ADCIN_VSEN_EN = MT6351_PMIC_RG_ADCIN_VSEN_EN, + PMIC_RG_ADCIN_CHR_EN = MT6351_PMIC_RG_ADCIN_CHR_EN, + PMIC_RG_UVLO_VTHL = MT6351_PMIC_RG_UVLO_VTHL, + PMIC_RG_UVLO_VH_LAT = MT6351_PMIC_RG_UVLO_VH_LAT, + PMIC_RG_LBAT_INT_VTH = MT6351_PMIC_RG_LBAT_INT_VTH, + PMIC_RG_BGR_RSEL = MT6351_PMIC_RG_BGR_RSEL, + PMIC_RG_BGR_UNCHOP_PH = MT6351_PMIC_RG_BGR_UNCHOP_PH, + PMIC_RG_BGR_UNCHOP = MT6351_PMIC_RG_BGR_UNCHOP, + PMIC_RG_BC11_BB_CTRL = MT6351_PMIC_RG_BC11_BB_CTRL, + PMIC_RG_BC11_RST = MT6351_PMIC_RG_BC11_RST, + PMIC_RG_BC11_VSRC_EN = MT6351_PMIC_RG_BC11_VSRC_EN, + PMIC_RGS_BC11_CMP_OUT = MT6351_PMIC_RGS_BC11_CMP_OUT, + PMIC_RG_BC11_VREF_VTH = MT6351_PMIC_RG_BC11_VREF_VTH, + PMIC_RG_BC11_CMP_EN = MT6351_PMIC_RG_BC11_CMP_EN, + PMIC_RG_BC11_IPD_EN = MT6351_PMIC_RG_BC11_IPD_EN, + PMIC_RG_BC11_IPU_EN = MT6351_PMIC_RG_BC11_IPU_EN, + PMIC_RG_BC11_BIAS_EN = MT6351_PMIC_RG_BC11_BIAS_EN, + PMIC_RG_CSDAC_STP_INC = MT6351_PMIC_RG_CSDAC_STP_INC, + PMIC_RG_CSDAC_STP_DEC = MT6351_PMIC_RG_CSDAC_STP_DEC, + PMIC_RG_CSDAC_DLY = MT6351_PMIC_RG_CSDAC_DLY, + PMIC_RG_CSDAC_STP = MT6351_PMIC_RG_CSDAC_STP, + PMIC_RG_LOW_ICH_DB = MT6351_PMIC_RG_LOW_ICH_DB, + PMIC_RG_CHRIND_ON = MT6351_PMIC_RG_CHRIND_ON, + PMIC_RG_CHRIND_DIMMING = MT6351_PMIC_RG_CHRIND_DIMMING, + PMIC_RG_CV_MODE = MT6351_PMIC_RG_CV_MODE, + PMIC_RG_VCDT_MODE = MT6351_PMIC_RG_VCDT_MODE, + PMIC_RG_CSDAC_MODE = MT6351_PMIC_RG_CSDAC_MODE, + PMIC_RG_TRACKING_EN = MT6351_PMIC_RG_TRACKING_EN, + PMIC_RG_HWCV_EN = MT6351_PMIC_RG_HWCV_EN, + PMIC_RG_ULC_DET_EN = MT6351_PMIC_RG_ULC_DET_EN, + PMIC_RG_BGR_TRIM_EN = MT6351_PMIC_RG_BGR_TRIM_EN, + PMIC_RG_ICHRG_TRIM = MT6351_PMIC_RG_ICHRG_TRIM, + PMIC_RG_BGR_TRIM = MT6351_PMIC_RG_BGR_TRIM, + PMIC_RG_OVP_TRIM = MT6351_PMIC_RG_OVP_TRIM, + PMIC_RG_CHR_OSC_TRIM = MT6351_PMIC_RG_CHR_OSC_TRIM, + PMIC_DA_QI_BGR_EXT_BUF_EN = MT6351_PMIC_DA_QI_BGR_EXT_BUF_EN, + PMIC_RG_BGR_TEST_EN = MT6351_PMIC_RG_BGR_TEST_EN, + PMIC_RG_BGR_TEST_RSTB = MT6351_PMIC_RG_BGR_TEST_RSTB, + PMIC_RG_DAC_USBDL_MAX = MT6351_PMIC_RG_DAC_USBDL_MAX, + PMIC_RG_CM_VDEC_TRIG = MT6351_PMIC_RG_CM_VDEC_TRIG, + PMIC_PCHR_CM_VDEC_STATUS = MT6351_PMIC_PCHR_CM_VDEC_STATUS, + PMIC_RG_CM_VINC_TRIG = MT6351_PMIC_RG_CM_VINC_TRIG, + PMIC_PCHR_CM_VINC_STATUS = MT6351_PMIC_PCHR_CM_VINC_STATUS, + PMIC_RG_CM_VDEC_HPRD1 = MT6351_PMIC_RG_CM_VDEC_HPRD1, + PMIC_RG_CM_VDEC_HPRD2 = MT6351_PMIC_RG_CM_VDEC_HPRD2, + PMIC_RG_CM_VDEC_HPRD3 = MT6351_PMIC_RG_CM_VDEC_HPRD3, + PMIC_RG_CM_VDEC_HPRD4 = MT6351_PMIC_RG_CM_VDEC_HPRD4, + PMIC_RG_CM_VDEC_HPRD5 = MT6351_PMIC_RG_CM_VDEC_HPRD5, + PMIC_RG_CM_VDEC_HPRD6 = MT6351_PMIC_RG_CM_VDEC_HPRD6, + PMIC_RG_CM_VINC_HPRD1 = MT6351_PMIC_RG_CM_VINC_HPRD1, + PMIC_RG_CM_VINC_HPRD2 = MT6351_PMIC_RG_CM_VINC_HPRD2, + PMIC_RG_CM_VINC_HPRD3 = MT6351_PMIC_RG_CM_VINC_HPRD3, + PMIC_RG_CM_VINC_HPRD4 = MT6351_PMIC_RG_CM_VINC_HPRD4, + PMIC_RG_CM_VINC_HPRD5 = MT6351_PMIC_RG_CM_VINC_HPRD5, + PMIC_RG_CM_VINC_HPRD6 = MT6351_PMIC_RG_CM_VINC_HPRD6, + PMIC_RG_CM_LPRD = MT6351_PMIC_RG_CM_LPRD, + PMIC_RG_CM_CS_VTHL = MT6351_PMIC_RG_CM_CS_VTHL, + PMIC_RG_CM_CS_VTHH = MT6351_PMIC_RG_CM_CS_VTHH, + PMIC_RG_PCHR_RSV = MT6351_PMIC_RG_PCHR_RSV, + PMIC_RG_ENVTEM_D = MT6351_PMIC_RG_ENVTEM_D, + PMIC_RG_ENVTEM_EN = MT6351_PMIC_RG_ENVTEM_EN, + PMIC_RGS_BATON_HV = MT6351_PMIC_RGS_BATON_HV, + PMIC_RG_HW_VTH_CTRL = MT6351_PMIC_RG_HW_VTH_CTRL, + PMIC_RG_HW_VTH2 = MT6351_PMIC_RG_HW_VTH2, + PMIC_RG_HW_VTH1 = MT6351_PMIC_RG_HW_VTH1, + PMIC_RG_CM_VDEC_INT_EN = MT6351_PMIC_RG_CM_VDEC_INT_EN, + PMIC_RG_CM_VINC_INT_EN = MT6351_PMIC_RG_CM_VINC_INT_EN, + PMIC_RG_QI_BATON_LT_EN = MT6351_PMIC_RG_QI_BATON_LT_EN, + PMIC_RGS_BATON_UNDET = MT6351_PMIC_RGS_BATON_UNDET, + PMIC_RG_JW_CS_VTH = MT6351_PMIC_RG_JW_CS_VTH, + PMIC_RG_JW_CV_VTH = MT6351_PMIC_RG_JW_CV_VTH, + PMIC_RG_JC_CS_VTH = MT6351_PMIC_RG_JC_CS_VTH, + PMIC_RG_JC_CV_VTH = MT6351_PMIC_RG_JC_CV_VTH, + PMIC_RG_BC11_ACA_EN = MT6351_PMIC_RG_BC11_ACA_EN, + PMIC_RG_JEITA_EN = MT6351_PMIC_RG_JEITA_EN, + PMIC_RG_VCDT_TRIM = MT6351_PMIC_RG_VCDT_TRIM, + PMIC_RGS_BC11_ID_FLOAT = MT6351_PMIC_RGS_BC11_ID_FLOAT, + PMIC_RGS_BC11_ID_A = MT6351_PMIC_RGS_BC11_ID_A, + PMIC_RGS_BC11_ID_B = MT6351_PMIC_RGS_BC11_ID_B, + PMIC_RGS_BC11_ID_C = MT6351_PMIC_RGS_BC11_ID_C, + PMIC_RGS_BC11_ID_GND = MT6351_PMIC_RGS_BC11_ID_GND, + PMIC_RGS_BC11_ACA_OTG_DET = MT6351_PMIC_RGS_BC11_ACA_OTG_DET, + PMIC_RG_INDICATOR_TRIM = MT6351_PMIC_RG_INDICATOR_TRIM, + PMIC_EOSC_CALI_START = MT6351_PMIC_EOSC_CALI_START, + PMIC_EOSC_CALI_TD = MT6351_PMIC_EOSC_CALI_TD, + PMIC_EOSC_CALI_TEST = MT6351_PMIC_EOSC_CALI_TEST, + PMIC_EOSC_CALI_DCXO_RDY_TD = MT6351_PMIC_EOSC_CALI_DCXO_RDY_TD, + PMIC_FRC_VTCXO0_ON = MT6351_PMIC_FRC_VTCXO0_ON, + PMIC_EOSC_CALI_RSV = MT6351_PMIC_EOSC_CALI_RSV, + PMIC_VRTC_PWM_MODE = MT6351_PMIC_VRTC_PWM_MODE, + PMIC_VRTC_PWM_RSV = MT6351_PMIC_VRTC_PWM_RSV, + PMIC_VRTC_PWM_L_DUTY = MT6351_PMIC_VRTC_PWM_L_DUTY, + PMIC_VRTC_PWM_H_DUTY = MT6351_PMIC_VRTC_PWM_H_DUTY, + PMIC_VRTC_CAP_SEL = MT6351_PMIC_VRTC_CAP_SEL, + PMU_COMMAND_MAX +} PMU_FLAGS_LIST_ENUM; + +typedef struct { + PMU_FLAGS_LIST_ENUM flagname; + unsigned short offset; + unsigned short mask; + unsigned char shift; +} PMU_FLAG_TABLE_ENTRY; +#endif + +#endif /* _MT_PMIC_UPMU_HW_H_ */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/upmu_sw.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/upmu_sw.h new file mode 100644 index 0000000000000000000000000000000000000000..6dbdb183170d90ec2408506fbc23569deabe3a45 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/upmu_sw.h @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _MT_PMIC_UPMU_SW_H_ +#define _MT_PMIC_UPMU_SW_H_ + +#ifdef CONFIG_MTK_PMIC_NEW_ARCH + +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +#include +#include +#endif + +#else +#include + +#define AUXADC_SUPPORT_IMM_CURRENT_MODE +/*#define BATTERY_DTS_SUPPORT*/ +#define RBAT_PULL_UP_VOLT_BY_BIF +#define BATTERY_SW_INIT +/* #define INIT_BAT_CUR_FROM_PTIM */ + +#define FG_BAT_INT_H_NO 48 +#define FG_BAT_INT_L_NO 49 + + +/*============================================================================== + * Low battery level define + * ============================================================================== */ +typedef enum LOW_BATTERY_LEVEL_TAG { + LOW_BATTERY_LEVEL_0 = 0, + LOW_BATTERY_LEVEL_1 = 1, + LOW_BATTERY_LEVEL_2 = 2 +} LOW_BATTERY_LEVEL; + +typedef enum LOW_BATTERY_PRIO_TAG { + LOW_BATTERY_PRIO_CPU_B = 0, + LOW_BATTERY_PRIO_CPU_L = 1, + LOW_BATTERY_PRIO_GPU = 2, + LOW_BATTERY_PRIO_MD = 3, + LOW_BATTERY_PRIO_MD5 = 4, + LOW_BATTERY_PRIO_FLASHLIGHT = 5, + LOW_BATTERY_PRIO_VIDEO = 6, + LOW_BATTERY_PRIO_WIFI = 7, + LOW_BATTERY_PRIO_BACKLIGHT = 8 +} LOW_BATTERY_PRIO; + +extern void (*low_battery_callback)(LOW_BATTERY_LEVEL); +extern void register_low_battery_notify(void (*low_battery_callback) (LOW_BATTERY_LEVEL), + LOW_BATTERY_PRIO prio_val); + + +/* ============================================================================== + * Battery OC level define + * ============================================================================== */ +typedef enum BATTERY_OC_LEVEL_TAG { + BATTERY_OC_LEVEL_0 = 0, + BATTERY_OC_LEVEL_1 = 1 +} BATTERY_OC_LEVEL; + +typedef enum BATTERY_OC_PRIO_TAG { + BATTERY_OC_PRIO_CPU_B = 0, + BATTERY_OC_PRIO_CPU_L = 1, + BATTERY_OC_PRIO_GPU = 2 +} BATTERY_OC_PRIO; + +extern void (*battery_oc_callback)(BATTERY_OC_LEVEL); +extern void register_battery_oc_notify(void (*battery_oc_callback) (BATTERY_OC_LEVEL), + BATTERY_OC_PRIO prio_val); + +/*============================================================================== + * Battery percent define + *==============================================================================*/ +typedef enum BATTERY_PERCENT_LEVEL_TAG { + BATTERY_PERCENT_LEVEL_0 = 0, + BATTERY_PERCENT_LEVEL_1 = 1 +} BATTERY_PERCENT_LEVEL; + +typedef enum BATTERY_PERCENT_PRIO_TAG { + BATTERY_PERCENT_PRIO_CPU_B = 0, + BATTERY_PERCENT_PRIO_CPU_L = 1, + BATTERY_PERCENT_PRIO_GPU = 2, + BATTERY_PERCENT_PRIO_MD = 3, + BATTERY_PERCENT_PRIO_MD5 = 4, + BATTERY_PERCENT_PRIO_FLASHLIGHT = 5, + BATTERY_PERCENT_PRIO_VIDEO = 6, + BATTERY_PERCENT_PRIO_WIFI = 7, + BATTERY_PERCENT_PRIO_BACKLIGHT = 8 +} BATTERY_PERCENT_PRIO; + +extern void (*battery_percent_callback)(BATTERY_PERCENT_LEVEL); +extern void +register_battery_percent_notify(void (*battery_percent_callback) (BATTERY_PERCENT_LEVEL), + BATTERY_PERCENT_PRIO prio_val); + +/* ADC Channel Number */ +typedef enum { + PMIC_AUX_BATSNS_AP = 0x000, + PMIC_AUX_ISENSE_AP, + PMIC_AUX_VCDT_AP, + PMIC_AUX_BATON_AP, /* BATON/BIF */ + PMIC_AUX_CH4, + PMIC_AUX_VACCDET_AP, + PMIC_AUX_CH6, + PMIC_AUX_TSX, + PMIC_AUX_CH8, + PMIC_AUX_CH9, + PMIC_AUX_CH10, + PMIC_AUX_CH11, + PMIC_AUX_CH12, + PMIC_AUX_CH13, + PMIC_AUX_CH14, + PMIC_AUX_CH15, + PMIC_AUX_CH16, + PMIC_AUX_CH4_DCXO = 0x10000004, +} pmic_adc_ch_list_enum; + +typedef enum MT_POWER_TAG { + MT6351_POWER_LDO_VA18, + MT6351_POWER_LDO_VTCXO24, + MT6351_POWER_LDO_VTCXO28, + MT6351_POWER_LDO_VCN28, + MT6351_POWER_LDO_VCAMA, + MT6351_POWER_LDO_VUSB33, + MT6351_POWER_LDO_VSIM1, + MT6351_POWER_LDO_VSIM2, + MT6351_POWER_LDO_VEMC, + MT6351_POWER_LDO_VMCH, + MT6351_POWER_LDO_VIO28, + MT6351_POWER_LDO_VIBR, + MT6351_POWER_LDO_VCAMD, + MT6351_POWER_LDO_VRF18, + MT6351_POWER_LDO_VIO18, + MT6351_POWER_LDO_VCN18, + MT6351_POWER_LDO_VCAMIO, + MT6351_POWER_LDO_VSRAM_PROC, + MT6351_POWER_LDO_VXO22, + MT6351_POWER_LDO_VRF12, + MT6351_POWER_LDO_VA10, + MT6351_POWER_LDO_VDRAM, + MT6351_POWER_LDO_VMIPI, + MT6351_POWER_LDO_VGP3, + MT6351_POWER_LDO_VBIF28, + MT6351_POWER_LDO_VEFUSE, + MT6351_POWER_LDO_VCN33_BT, + MT6351_POWER_LDO_VCN33_WIFI, + MT6351_POWER_LDO_VLDO28, + MT6351_POWER_LDO_VMC, + MT6351_POWER_LDO_VLDO28_0, + MT6351_POWER_LDO_VLDO28_1, + MT65XX_POWER_COUNT_END, + MT65XX_POWER_LDO_DEFAULT, + MT65XX_POWER_NONE = -1 +} MT65XX_POWER; + +/*============================================================================== + * DLPT define + *==============================================================================*/ +typedef enum DLPT_PRIO_TAG { + DLPT_PRIO_PBM = 0, + DLPT_PRIO_CPU_B = 1, + DLPT_PRIO_CPU_L = 2, + DLPT_PRIO_GPU = 3, + DLPT_PRIO_MD = 4, + DLPT_PRIO_MD5 = 5, + DLPT_PRIO_FLASHLIGHT = 6, + DLPT_PRIO_VIDEO = 7, + DLPT_PRIO_WIFI = 8, + DLPT_PRIO_BACKLIGHT = 9 +} DLPT_PRIO; + +extern void (*dlpt_callback)(unsigned int); +extern void register_dlpt_notify(void (*dlpt_callback)(unsigned int), DLPT_PRIO prio_val); +extern const PMU_FLAG_TABLE_ENTRY pmu_flags_table[]; + +extern unsigned short is_battery_remove; +extern unsigned short is_wdt_reboot_pmic; +extern unsigned short is_wdt_reboot_pmic_chk; +extern unsigned int g_pmic_pad_vbif28_vol; + +/*============================================================================== +// PMIC LDO define +//==============================================================================*/ + +/*============================================================================== +// PMIC auxadc define +//==============================================================================*/ +extern signed int g_I_SENSE_offset; +extern void pmic_auxadc_init(void); +extern void pmic_auxadc_lock(void); +extern void pmic_auxadc_unlock(void); +extern void mt_power_off(void); +/*============================================================================== +// PMIC fg define +//==============================================================================*/ +extern unsigned int bat_get_ui_percentage(void); +extern signed int fgauge_read_v_by_d(int d_val); +extern signed int fgauge_read_r_bat_by_v(signed int voltage); +extern signed int fgauge_read_IM_current(void *data); +extern void kpd_pwrkey_pmic_handler(unsigned long pressed); +extern void kpd_pmic_rstkey_handler(unsigned long pressed); +extern int is_mt6311_sw_ready(void); +extern int is_mt6311_exist(void); +extern int get_mt6311_i2c_ch_num(void); +/*extern bool crystal_exist_status(void);*/ +#if defined CONFIG_MTK_LEGACY +extern void pmu_drv_tool_customization_init(void); +#endif +extern int batt_init_cust_data(void); +extern void PMIC_INIT_SETTING_V1(void); + +extern int do_ptim_ex(bool isSuspend, unsigned int *bat, signed int *cur); +#endif + +#endif /* _MT_PMIC_UPMU_SW_H_ */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/wd_api.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/wd_api.h new file mode 100644 index 0000000000000000000000000000000000000000..d2669a0d49c569a873df817c0081c9d8b4078468 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/mach/wd_api.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MT_WD_API_H_ +#define _MT_WD_API_H_ +/* WD MODE MARK BIT */ +#define MTK_WDT_REQ_DEBUG_EN_MARK (0x80000) +#define MTK_WDT_REQ_SPM_THERMAL_MARK (0x0001) +#define MTK_WDT_REQ_SPM_SCPSYS_MARK (0x0002) +#define MTK_WDT_REQ_EINT_MARK (1<<2) +#define MTK_WDT_REQ_SYSRST_MARK (1<<3) +#define MTK_WDT_REQ_THERMAL_MARK (1<<18) + +#ifndef FALSE + #define FALSE (0) +#endif + +#ifndef TRUE + #define TRUE (1) +#endif + +typedef enum ext_wdt_mode { + WDT_IRQ_ONLY_MODE, + WDT_HW_REBOOT_ONLY_MODE, + WDT_DUAL_MODE, +} WD_MODE; + +typedef enum wk_wdt_en { + WK_WDT_DIS, + WK_WDT_EN, +} WD_CTL; + + +typedef enum wd_restart_type { + WD_TYPE_NORMAL, + WD_TYPE_NOLOCK, +} WD_RES_TYPE; + +typedef enum wk_req_en { + WD_REQ_DIS, + WD_REQ_EN, +} WD_REQ_CTL; + +typedef enum wk_req_mode { + WD_REQ_IRQ_MODE, + WD_REQ_RST_MODE, +} WD_REQ_MODE; + +struct wd_api { + long ready; + int (*wd_restart)(enum wd_restart_type type); + int (*wd_cpu_hot_plug_on_notify)(int); + int (*wd_cpu_hot_plug_off_notify)(int); + int (*wd_sw_reset)(int); + int (*wd_config)(enum ext_wdt_mode, int timeout_val); + int (*wd_disable_ext)(void); + int (*wd_disable_local)(void); + int (*wd_disable_all)(void); + int (*wd_set_mode)(enum ext_wdt_mode); + int (*wd_aee_confirm_hwreboot)(void); + void (*wd_suspend_notify)(void); + void (*wd_resume_notify)(void); + unsigned int (*wd_get_check_bit)(void); + unsigned int (*wd_get_kick_bit)(void); + int (*wd_spmwdt_mode_config)(WD_REQ_CTL en, WD_REQ_MODE mode); + int (*wd_thermal_mode_config)(WD_REQ_CTL en, WD_REQ_MODE mode); + int (*wd_dram_reserved_mode)(bool enabled); + int (*wd_thermal_direct_mode_config)(WD_REQ_CTL en, WD_REQ_MODE mode); + int (*wd_debug_key_eint_config)(WD_REQ_CTL en, WD_REQ_MODE mode); + int (*wd_debug_key_sysrst_config)(WD_REQ_CTL en, WD_REQ_MODE mode); +}; + +int wd_api_init(void); +int get_wd_api(struct wd_api **obj); +void wk_cpu_update_bit_flag(int cpu, int plug_status); +unsigned int get_check_bit(void); +unsigned int get_kick_bit(void); +extern void aee_wdt_printf(const char *fmt, ...); + +#endif /* _MT_WD_API_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/m4u/tz_m4u.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/m4u/tz_m4u.h new file mode 100644 index 0000000000000000000000000000000000000000..fe1529e3e1d4783b025b944426c34dedb3fc0172 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/m4u/tz_m4u.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2013 TRUSTONIC LIMITED + * All rights reserved + * + * The present software is the confidential and proprietary information of + * TRUSTONIC LIMITED. You shall not disclose the present software and shall + * use it only in accordance with the terms of the license agreement you + * entered into with TRUSTONIC LIMITED. This software may be subject to + * export or import laws in certain countries. + */ + +#ifndef __TZ_M4U_H__ +#define __TZ_M4U_H__ + +/* #include "drStd.h" */ +#include "m4u_port.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* #define __M4U_SECURE_SYSTRACE_ENABLE__ */ + +#define M4U_NONSEC_MVA_START (0x20000000) + +#define CMD_M4U_MAGIC (0x77880000) + +typedef enum { + CMD_M4U_ADD = CMD_M4U_MAGIC, + CMD_M4U_CFG_PORT, + CMD_M4U_MAP_NONSEC_BUFFER, + CMD_M4U_SEC_INIT, + CMD_M4U_ALLOC_MVA, + CMD_M4U_DEALLOC_MVA, + CMD_M4U_REG_BACKUP, + CMD_M4U_REG_RESTORE, + CMD_M4U_PRINT_PORT, + CMD_M4U_DUMP_SEC_PGTABLE, + + CMD_M4UTL_INIT, + + CMD_M4U_OPEN_SESSION, + CMD_M4U_CLOSE_SESSION, + + CMD_M4U_CFG_PORT_ARRAY, + + CMD_M4U_SYSTRACE_MAP, + CMD_M4U_SYSTRACE_UNMAP, + CMD_M4U_SYSTRACE_TRANSACT, + + CMD_M4U_LARB_BACKUP, + CMD_M4U_LARB_RESTORE, + CMD_M4U_UNMAP_NONSEC_BUFFER, + + CMD_M4U_GET_RESERVED_MEMORY, +} m4u_cmd_t; + + +#define M4U_RET_OK 0 +#define M4U_RET_UNKNOWN_CMD -1 +#define M4U_RET_NO_PERM -2 + + +#define EXIT_ERROR ((uint32_t)(-1)) + +typedef struct { + int a; + int b; + int result; +} m4u_add_param_t; + +#define M4U_SIN_NAME_LEN 12 + +typedef struct { + int sid; + char name[M4U_SIN_NAME_LEN]; +} m4u_session_param_t; + +typedef struct { + int port; + int virt; + int sec; + int distance; + int direction; +} m4u_cfg_port_param_t; + +typedef struct { + int port; + unsigned int mva; + unsigned int size; + unsigned int pa; +} m4u_buf_param_t; + +typedef struct { + unsigned int nonsec_pt_pa; + int l2_en; + unsigned int sec_pt_pa; + unsigned int sec_pa_start; + unsigned int sec_pa_size; +} m4u_init_param_t; + +typedef struct { + unsigned long pa; + unsigned long size; +} m4u_systrace_param_t; + +typedef struct { + unsigned char m4u_port_array[(M4U_PORT_NR+1)/2]; +} m4u_cfg_port_array_param_t; + +typedef struct { + unsigned int larb_idx; +} m4u_larb_restore_param_t; + +typedef struct { + unsigned int reserved_mem_start; + unsigned int reserved_mem_size; +} m4u_reserved_memory_param_t; + +typedef struct { + unsigned int cmd; + unsigned int retval_for_tbase; /* it must be 0 */ + unsigned int rsp; + + union { + m4u_add_param_t add_param; + m4u_session_param_t session_param; + m4u_cfg_port_param_t port_param; + m4u_buf_param_t buf_param; + m4u_init_param_t init_param; + m4u_cfg_port_array_param_t port_array_param; +#ifdef __M4U_SECURE_SYSTRACE_ENABLE__ + m4u_systrace_param_t systrace_param; +#endif + m4u_larb_restore_param_t larb_param; + m4u_reserved_memory_param_t reserved_memory_param; + }; +} m4u_msg_t; + + +#if defined(__cplusplus) +} +#endif + + +#endif /* TLFOO_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/tplay/Tltplay/public/tci.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/tplay/Tltplay/public/tci.h new file mode 100644 index 0000000000000000000000000000000000000000..fdfdc1daf72c144814e7847d6740e755176becb1 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/tplay/Tltplay/public/tci.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013-2016 TRUSTONIC LIMITED + * 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 + * version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef TCI_H_ +#define TCI_H_ + +typedef uint32_t tciCommandId_t; +typedef uint32_t tciResponseId_t; +typedef uint32_t tciReturnCode_t; + +/**< Responses have bit 31 set */ +#define RSP_ID_MASK (1U << 31) +#define RSP_ID(cmdId) (((uint32_t)(cmdId)) | RSP_ID_MASK) +#define IS_CMD(cmdId) ((((uint32_t)(cmdId)) & RSP_ID_MASK) == 0) +#define IS_RSP(cmdId) ((((uint32_t)(cmdId)) & RSP_ID_MASK) == RSP_ID_MASK) + +/** + * Return codes of Trustlet commands. + */ +#define RET_OK 0 /**< Set, if processing is error free */ +#define RET_ERR_UNKNOWN_CMD 1 /**< Unknown command */ +#define INVALID_VIRTUAL_ADDR 2 + +/** + * TCI command header. + */ +typedef struct{ + tciCommandId_t commandId; /**< Command ID */ +} tciCommandHeader_t; + +/** + * TCI response header. + */ +typedef struct{ + tciResponseId_t responseId; /**< Response ID (must be command ID | RSP_ID_MASK )*/ + tciReturnCode_t returnCode; /**< Return code of command */ +} tciResponseHeader_t; + +#endif /* TCI_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/tplay/Tltplay/public/tlcApitplay.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/tplay/Tltplay/public/tlcApitplay.h new file mode 100644 index 0000000000000000000000000000000000000000..0c957508a33da363537970ede59bf30435332a7f --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/tplay/Tltplay/public/tlcApitplay.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef TLTPLAY_H_ +#define TLTPLAY_H_ + +#include "tci.h" + +/* + * Command ID's for communication Trustlet Connector -> Trustlet. + */ +#define CMD_TPLAY_REQUEST 4 +#define CMD_TPLAY_DUMP_PHY 5 +#define CMD_TPLAY_TEST 6 + + + +/* + * Termination codes + */ +#define EXIT_ERROR ((uint32_t)(-1)) + +/* + * command message. + * + * @param len Length of the data to process. + * @param data Data to processed (cleartext or ciphertext). + */ +typedef struct { + tciCommandHeader_t header; /**< Command header */ + uint32_t len; /**< Length of data to process or buffer */ + uint32_t respLen; /**< Length of response buffer */ +} tplay_cmd_t; + +/* + * Response structure Trustlet -> Trustlet Connector. + */ +typedef struct { + tciResponseHeader_t header; /**< Response header */ + uint32_t len; +} tplay_rsp_t; + +/* + * TCI message data. + */ +typedef struct { + union { + tplay_cmd_t cmd; + tplay_rsp_t rsp; + }; + uint32_t index; + uint32_t result; + uint32_t data_addr; + uint32_t data_len; + uint32_t seed_addr; + uint32_t seed_len; + uint32_t hacc_user; + uint32_t direction; + uint32_t tplay_handle_low_addr; + uint32_t tplay_handle_high_addr; +} tplay_tciMessage_t; + +/* + * Trustlet UUID. + */ +/* 05200000000000000000000000000000 */ +#define TL_TPLAY_UUID {{0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } + +#endif /* TLFOO_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/utils/tlutils/tci.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/utils/tlutils/tci.h new file mode 100644 index 0000000000000000000000000000000000000000..145dcfbe30dc84c9eb2a5209db3dc5874134c951 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/utils/tlutils/tci.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013-2016 TRUSTONIC LIMITED + * 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 + * version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef TCI_H_ +#define TCI_H_ + +typedef uint32_t tciCommandId_t; +typedef uint32_t tciResponseId_t; +typedef uint32_t tciReturnCode_t; + +/**< Responses have bit 31 set */ +#define RSP_ID_MASK (1U << 31) +#define RSP_ID(cmdId) (((uint32_t)(cmdId)) | RSP_ID_MASK) +#define IS_CMD(cmdId) ((((uint32_t)(cmdId)) & RSP_ID_MASK) == 0) +#define IS_RSP(cmdId) ((((uint32_t)(cmdId)) & RSP_ID_MASK) == RSP_ID_MASK) + +/** + * Return codes of Trustlet commands. + */ +#define RET_OK 0 /**< Set, if processing is error free */ +#define RET_ERR_UNKNOWN_CMD 1 /**< Unknown command */ + +/** + * TCI command header. + */ +typedef struct{ + tciCommandId_t commandId; /**< Command ID */ +} tciCommandHeader_t; + +/** + * TCI response header. + */ +typedef struct{ + tciResponseId_t responseId; /**< Response ID (must be command ID | RSP_ID_MASK )*/ + tciReturnCode_t returnCode; /**< Return code of command */ +} tciResponseHeader_t; + +#endif /* TCI_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/utils/tlutils/tlsecmem_api.h b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/utils/tlutils/tlsecmem_api.h new file mode 100644 index 0000000000000000000000000000000000000000..094ac34805c2aae33db8be2391ad551463ba2ee3 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt6755/include/trustzone/utils/tlutils/tlsecmem_api.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef TLSECMEM_H_ +#define TLSECMEM_H_ + +#include "tci.h" + +/* + * Command ID's for communication Trustlet Connector -> Trustlet. + */ +#define CMD_SEC_MEM_ALLOC 1 +#define CMD_SEC_MEM_REF 2 +#define CMD_SEC_MEM_UNREF 3 +#define CMD_SEC_MEM_ALLOC_TBL 4 +#define CMD_SEC_MEM_UNREF_TBL 5 +#define CMD_SEC_MEM_USAGE_DUMP 6 +#define CMD_SEC_MEM_ENABLE 7 +#define CMD_SEC_MEM_DISABLE 8 +#define CMD_SEC_MEM_ALLOCATED 9 +#define CMD_SEC_MEM_ALLOC_PA 10 +#define CMD_SEC_MEM_REF_PA 11 +#define CMD_SEC_MEM_UNREF_PA 12 +#define CMD_SEC_MEM_ALLOC_ZERO 13 + +#define CMD_SEC_MEM_DUMP_INFO 255 + +#define MAX_NAME_SZ (32) + +/* + * Termination codes + */ +#define EXIT_ERROR ((uint32_t)(-1)) + +/* + * command message. + * + * @param len Length of the data to process. + * @param data Data to processed (cleartext or ciphertext). + */ +typedef struct { + tciCommandHeader_t header; /**< Command header */ + uint32_t len; /**< Length of data to process or buffer */ + uint32_t respLen; /**< Length of response buffer */ +} tl_cmd_t; + +/* + * Response structure Trustlet -> Trustlet Connector. + */ +typedef struct { + tciResponseHeader_t header; /**< Response header */ + uint32_t len; +} tl_rsp_t; + +typedef struct { + uint8_t name[MAX_NAME_SZ]; + uint32_t id; +} tl_sender_info_t; + +/* + * TCI message data. + */ +typedef struct { + union { + tl_cmd_t cmd_secmem; + tl_rsp_t rsp_secmem; + }; + uint32_t alignment; /* IN */ + uint32_t size; /* IN */ + uint32_t refcount; /* INOUT */ + uint32_t sec_handle; /* OUT */ + uint32_t ResultData; + + /* Debugging purpose */ + tl_sender_info_t sender; + +} tciMessage_t; + +/* + * Trustlet UUID. + */ +#define TL_SECMEM_UUID {0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + +#endif /* TLSECMEM_H_ */ diff --git a/drivers/misc/mediatek/irtx/mt6755/Makefile b/drivers/misc/mediatek/irtx/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3dbb194fcb8b5f14a3b96565b477d5302b09d761 --- /dev/null +++ b/drivers/misc/mediatek/irtx/mt6755/Makefile @@ -0,0 +1,25 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +$(info IRTX: PWM+IRTX:$(CONFIG_MTK_IRTX_SUPPORT)) +$(info IRTX: PWM ONLY:$(CONFIG_MTK_IRTX_PWM_SUPPORT)) + +ifeq ($(CONFIG_MTK_IRTX_SUPPORT), y) +obj-y := mt_irtx.o +else +ifeq ($(CONFIG_MTK_IRTX_PWM_SUPPORT), y) +obj-y := mt_irtx_pwm.o +else +obj- := dummy.o +endif +endif diff --git a/drivers/misc/mediatek/irtx/mt6755/mt_irtx.c b/drivers/misc/mediatek/irtx/mt6755/mt_irtx.c new file mode 100644 index 0000000000000000000000000000000000000000..0415bff7a6bac24e10d777fd42da95c050555103 --- /dev/null +++ b/drivers/misc/mediatek/irtx/mt6755/mt_irtx.c @@ -0,0 +1,580 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + +#ifdef CONFIG_OF +#include +#include +#include +#include +#endif + +#include +#include +#include + +#if defined(CONFIG_MTK_LEGACY) +#include +#include +#endif /* !defined(CONFIG_MTK_LEGACY) */ + +#include "mt_irtx.h" + +#if defined(CONFIG_MTK_LEGACY) +#define IRTX_GPIO_EN (GPIO104 | 0x80000000) +#define IRTX_GPIO (GPIO116 | 0x80000000) +#endif /* !defined(CONFIG_MTK_LEGACY) */ + +struct mt_irtx mt_irtx_dev; +void __iomem *irtx_reg_base; +unsigned int irtx_irq; + +struct pwm_spec_config irtx_pwm_config = { + .pwm_no = 3, + .mode = PWM_MODE_MEMORY, + .clk_div = CLK_DIV1, + .clk_src = PWM_CLK_NEW_MODE_BLOCK, + .pmic_pad = 0, + .PWM_MODE_MEMORY_REGS.IDLE_VALUE = IDLE_FALSE, + .PWM_MODE_MEMORY_REGS.GUARD_VALUE = GUARD_FALSE, + .PWM_MODE_MEMORY_REGS.STOP_BITPOS_VALUE = 31, + .PWM_MODE_MEMORY_REGS.HDURATION = 25, /* 1 microseconds, assume clock source is 26M */ + .PWM_MODE_MEMORY_REGS.LDURATION = 25, + .PWM_MODE_MEMORY_REGS.GDURATION = 0, + .PWM_MODE_MEMORY_REGS.WAVE_NUM = 1, +}; + +#if !defined(CONFIG_MTK_LEGACY) + +#define IRTX_GPIO_MODE_LED_DEFAULT 0 +#define IRTX_GPIO_MODE_LED_SET 1 +#define IRTX_GPIO_MODE_EN_DEFAULT 2 +#define IRTX_GPIO_MODE_EN_SET 3 +char *irtx_gpio_cfg[] = { "irtx_gpio_led_default", "irtx_gpio_led_set", + "irtx_gpio_en_default", "irtx_gpio_en_set" }; + +void switch_irtx_gpio(int mode) +{ + struct pinctrl *ppinctrl_irtx = mt_irtx_dev.ppinctrl_irtx; + struct pinctrl_state *pins_irtx = NULL; + + pr_debug("[IRTX][PinC]%s(%d)+\n", __func__, mode); + + if (mode >= (sizeof(irtx_gpio_cfg) / sizeof(irtx_gpio_cfg[0]))) { + pr_err("[IRTX][PinC]%s(%d) fail!! - parameter error!\n", __func__, mode); + return; + } + + if (IS_ERR(ppinctrl_irtx)) { + pr_err("[IRTX][PinC]%s ppinctrl_irtx:%p is error! err:%ld\n", + __func__, ppinctrl_irtx, PTR_ERR(ppinctrl_irtx)); + return; + } + + pins_irtx = pinctrl_lookup_state(ppinctrl_irtx, irtx_gpio_cfg[mode]); + if (IS_ERR(pins_irtx)) { + pr_err("[IRTX][PinC]%s pinctrl_lockup(%p, %s) fail!! ppinctrl:%p, err:%ld\n", + __func__, ppinctrl_irtx, irtx_gpio_cfg[mode], pins_irtx, PTR_ERR(pins_irtx)); + return; + } + + pinctrl_select_state(ppinctrl_irtx, pins_irtx); + pr_debug("[IRTX][PinC]%s(%d)-\n", __func__, mode); +} +#endif /* !defined(CONFIG_MTK_LEGACY) */ + +static void set_irtx_duty(int duty_cycle) +{ + unsigned int cdt, cwt; + + pr_debug("[IRTX] change IrTx duty cycle\n"); + + cwt = (CLOCK_SRC * 1000 * 1000) / (mt_irtx_dev.carrier_freq); /* carrier freq. */ + if (duty_cycle == 33) + cdt = cwt / 3; /* duty=33% */ + else if (duty_cycle == 30) + cdt = cwt * 3 / 10; /* duty=30% */ + else { + cdt = 0; + pr_err("[IRTX] non-default duty cycle\n"); + } + + irtx_write32(mt_irtx_dev.reg_base, IRTXMT, (cdt << 16) | (cwt & 0xFFFF)); + + pr_debug("[IRTX] configured IrTx: mt=%x/%x\n", cdt, cwt); +} + +static int dev_char_open(struct inode *inode, struct file *file) +{ +#if !defined(CONFIG_MTK_CLKMGR) + int clk_en_ret = 0; +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + + if (atomic_read(&mt_irtx_dev.usage_cnt)) + return -EBUSY; + +#if !defined(CONFIG_MTK_CLKMGR) + pr_debug("[IRTX][CCF]enable clk_irtx_main:%p\n", mt_irtx_dev.clk_irtx_main); + clk_en_ret = clk_prepare_enable(mt_irtx_dev.clk_irtx_main); + if (clk_en_ret) { + pr_err("[IRTX][CCF]enable clk_irtx_main failed. ret:%d, clk_irtx_main:%p\n", + clk_en_ret, mt_irtx_dev.clk_irtx_main); + } +#else /* !defined(CONFIG_MTK_CLKMGR) */ + enable_clock(MT_CG_PERI_IRTX, "IRTX"); +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + + pr_debug("[IRTX] open by %s\n", current->comm); + /* set IRTX_IRINV */ + irtx_write32(mt_irtx_dev.reg_base, IRTXCFG, + irtx_read32(mt_irtx_dev.reg_base, IRTXCFG) | 0x80); + nonseekable_open(inode, file); + atomic_inc(&mt_irtx_dev.usage_cnt); + return 0; +} + +static int dev_char_close(struct inode *inode, struct file *file) +{ + pr_debug("[IRTX] close by %s\n", current->comm); + atomic_dec(&mt_irtx_dev.usage_cnt); +#if !defined(CONFIG_MTK_CLKMGR) + pr_debug("[IRTX][CCF]disable clk_irtx_main:%p\n", mt_irtx_dev.clk_irtx_main); + clk_disable_unprepare(mt_irtx_dev.clk_irtx_main); +#else /* !defined(CONFIG_MTK_CLKMGR) */ + disable_clock(MT_CG_PERI_IRTX, "IRTX"); +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + + return 0; +} + +static ssize_t dev_char_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + return 0; +} + +static long dev_char_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + unsigned int para = 0, gpio_id = -1, en = 0; +#if defined(CONFIG_MTK_LEGACY) + unsigned long mode = 0, dir = 0, outp = 0; +#endif /* defined(CONFIG_MTK_LEGACY) */ + + switch (cmd) { + case IRTX_IOC_SET_CARRIER_FREQ: + /*-----------------Reduce duty cycle------------------*/ + set_irtx_duty(30); + /*----------------------------------------------------*/ + + if (copy_from_user(&mt_irtx_dev.carrier_freq, (void __user *)arg, sizeof(unsigned int))) { + pr_err("[IRTX] IRTX_IOC_SET_CARRIER_FREQ: copy_from_user fail!\n"); + ret = -EFAULT; + } else { + pr_debug("[IRTX] IRTX_IOC_SET_CARRIER_FREQ: %d\n", mt_irtx_dev.carrier_freq); + if (!mt_irtx_dev.carrier_freq) { + ret = -EINVAL; + mt_irtx_dev.carrier_freq = 38000; + } + } + break; + + case IRTX_IOC_SET_IRTX_LED_EN: + if (copy_from_user(¶, (void __user *)arg, sizeof(unsigned int))) { + pr_err("[IRTX] IRTX_IOC_SET_IRTX_LED_EN: copy_from_user fail!\n"); + ret = -EFAULT; + } else { + /* en: bit 12; */ + /* gpio: bit 0-11 */ + gpio_id = (unsigned long)((para & 0x0FFF0000) > 16); + en = (para & 0xF); + pr_debug("[IRTX] IRTX_IOC_SET_IRTX_LED_EN: 0x%x, gpio_id:%ul, en:%ul\n", + para, gpio_id, en); + +#if !defined(CONFIG_MTK_LEGACY) + if (en) { + switch_irtx_gpio(IRTX_GPIO_MODE_EN_SET); + switch_irtx_gpio(IRTX_GPIO_MODE_LED_SET); + } else { + switch_irtx_gpio(IRTX_GPIO_MODE_LED_DEFAULT); + switch_irtx_gpio(IRTX_GPIO_MODE_EN_DEFAULT); + } +#else /* !defined(CONFIG_MTK_LEGACY) */ + + /*-----------------Reduce duty cycle------------------*/ + set_irtx_duty(30); + /*----------------------------------------------------*/ + + if (en) { + /*-----------------IR power on------------------*/ + mt_set_gpio_mode(IRTX_GPIO_EN, GPIO_MODE_00); + mt_set_gpio_dir(IRTX_GPIO_EN, GPIO_DIR_OUT); + mt_set_gpio_out(IRTX_GPIO_EN, GPIO_OUT_ONE); + /*----------------------------------------------*/ + + mode = GPIO_MODE_06; + dir = GPIO_DIR_OUT; + outp = GPIO_OUT_ONE; /* High means enable LED */ + } else { + mode = GPIO_MODE_06; + dir = GPIO_DIR_OUT; + outp = GPIO_OUT_ZERO; /* Low means disable LED */ + + } + gpio_id = IRTX_GPIO; + + mt_set_gpio_mode(gpio_id, mode); + mt_set_gpio_dir(gpio_id, dir); + mt_set_gpio_out(gpio_id, outp); + + pr_debug + ("[IRTX] IOC_SET_IRTX_LED_EN: IR_GPIO gpio:0x%xl, mode:%d, dir:%d, out:%d\n", + gpio_id, mt_get_gpio_mode(gpio_id), mt_get_gpio_dir(gpio_id), + mt_get_gpio_out(gpio_id)); + if (!en) { + /*-----------------IR power off------------------*/ + mt_set_gpio_mode(IRTX_GPIO_EN, GPIO_MODE_00); + mt_set_gpio_dir(IRTX_GPIO_EN, GPIO_DIR_OUT); + mt_set_gpio_out(IRTX_GPIO_EN, GPIO_OUT_ZERO); + + /*-----------------Back to duty cycle------------------*/ + set_irtx_duty(33); + } +#endif /* !defined(CONFIG_MTK_LEGACY) */ + } + break; + + default: + pr_err("[IRTX] unknown ioctl cmd 0x%x\n", cmd); + ret = -ENOTTY; + break; + } + return ret; +} + +static void set_irtx_sw_mode(void) +{ + unsigned int ir_conf_wr; + unsigned int L0H, L0L, L1H, L1L; + unsigned int sync_h, sync_l; + unsigned int cdt, cwt; + struct irtx_config ir_conf; + + pr_debug("[IRTX] configure IrTx software mode\n"); + + ir_conf.mode = 3; + ir_conf.start = 0; + ir_conf.sw_o = 0; + ir_conf.b_ord = 1; /* LSB first */ + ir_conf.r_ord = 0; /* R0 first */ + ir_conf.ir_os = 1; /* modulated signal */ + ir_conf.ir_inv = 1; + ir_conf.bit_num = 0; + ir_conf.data_inv = 0; + L0H = 0; + L0L = mt_irtx_dev.pwm_ch; + L1H = 0; + L1L = 0; + sync_h = 0; + sync_l = 0; + cwt = (CLOCK_SRC * 1000 * 1000) / (mt_irtx_dev.carrier_freq); /* carrier freq. */ + cdt = cwt / 3; /* duty=1/3 */ + + memcpy(&ir_conf_wr, &ir_conf, sizeof(ir_conf)); + irtx_write32(mt_irtx_dev.reg_base, IRTXCFG, ir_conf_wr); + irtx_write32(mt_irtx_dev.reg_base, IRTX_L0H, L0H); + irtx_write32(mt_irtx_dev.reg_base, IRTX_L0L, L0L); + irtx_write32(mt_irtx_dev.reg_base, IRTX_L1H, L1H); + irtx_write32(mt_irtx_dev.reg_base, IRTX_L1L, L1L); + irtx_write32(mt_irtx_dev.reg_base, IRTXSYNCH, sync_h); + irtx_write32(mt_irtx_dev.reg_base, IRTXSYNCL, sync_l); + irtx_write32(mt_irtx_dev.reg_base, IRTXMT, (cdt << 16) | (cwt & 0xFFFF)); + + pr_debug("[IRTX] configured IrTx: cfg=%x L0=%x/%x L1=%x/%x sync=%x/%x mt=%x/%x\n", + ir_conf_wr, L0H, L0L, L1H, L1L, sync_h, sync_l, cdt, cwt); + pr_debug("[IRTX] configured cfg=0x%x", + (unsigned int)irtx_read32(mt_irtx_dev.reg_base, IRTXCFG)); +} + +static ssize_t dev_char_write(struct file *file, const char __user *buf, size_t count, + loff_t *ppos) +{ + dma_addr_t wave_phy; + void *wave_vir; + int ret; + int buf_size = (count + 3) / 4; /* when count is 5... */ + + pr_debug("[IRTX] irtx write len=0x%x, pwm=%d\n", (unsigned int)count, + (unsigned int)irtx_pwm_config.pwm_no); + wave_vir = dma_alloc_coherent(&mt_irtx_dev.plat_dev->dev, count, &wave_phy, GFP_KERNEL); + if (!wave_vir) { + pr_err("[IRTX] alloc memory fail\n"); + return -ENOMEM; + } + ret = copy_from_user(wave_vir, buf, count); + if (ret) { + pr_err("[IRTX] write, copy from user fail %d\n", ret); + goto exit; + } + + mt_set_intr_enable(0); + mt_set_intr_enable(1); + mt_pwm_26M_clk_enable_hal(1); + pr_debug("[IRTX] irtx before read IRTXCFG:0x%x\n", + (irtx_read32(mt_irtx_dev.reg_base, IRTXCFG))); + irtx_pwm_config.PWM_MODE_MEMORY_REGS.BUF0_BASE_ADDR = wave_phy; + irtx_pwm_config.PWM_MODE_MEMORY_REGS.BUF0_SIZE = (buf_size ? (buf_size - 1) : 0); + + set_irtx_sw_mode(); + +#if !defined(CONFIG_MTK_LEGACY) + switch_irtx_gpio(IRTX_GPIO_MODE_EN_SET); + switch_irtx_gpio(IRTX_GPIO_MODE_LED_SET); +#else /* !defined(CONFIG_MTK_LEGACY) */ + /*-----------------IR power on------------------*/ + mt_set_gpio_mode(IRTX_GPIO_EN, GPIO_MODE_00); + mt_set_gpio_dir(IRTX_GPIO_EN, GPIO_DIR_OUT); + mt_set_gpio_out(IRTX_GPIO_EN, GPIO_OUT_ONE); + /*----------------------------------------------*/ + + mt_set_gpio_mode(IRTX_GPIO, GPIO_MODE_06); + mt_set_gpio_dir(IRTX_GPIO, GPIO_DIR_OUT); + mt_set_gpio_out(IRTX_GPIO, GPIO_OUT_ONE); +#endif /* !defined(CONFIG_MTK_LEGACY) */ + irtx_write32(mt_irtx_dev.reg_base, IRTXCFG, irtx_read32(mt_irtx_dev.reg_base, IRTXCFG) | 0x1); /* STRT=1 */ + + mt_set_intr_ack(0); + mt_set_intr_ack(1); + ret = pwm_set_spec_config(&irtx_pwm_config); + pr_debug("[IRTX] pwm is triggered, %d\n", ret); + + msleep(count * 8 / 1000); + msleep(100); + ret = count; + +exit: + pr_debug("[IRTX] done, clean up\n"); + dma_free_coherent(&mt_irtx_dev.plat_dev->dev, count, wave_vir, wave_phy); + /* SWO=0 */ + irtx_write32(mt_irtx_dev.reg_base, IRTXCFG, irtx_read32(mt_irtx_dev.reg_base, IRTXCFG) & 0xFFFFFFF7); + /* STRT=0 */ + irtx_write32(mt_irtx_dev.reg_base, IRTXCFG, irtx_read32(mt_irtx_dev.reg_base, IRTXCFG) & 0xFFFFFFFE); + mt_pwm_disable(irtx_pwm_config.pwm_no, irtx_pwm_config.pmic_pad); + +#if !defined(CONFIG_MTK_LEGACY) + switch_irtx_gpio(IRTX_GPIO_MODE_LED_DEFAULT); + switch_irtx_gpio(IRTX_GPIO_MODE_EN_DEFAULT); +#else /* !defined(CONFIG_MTK_LEGACY) */ + mt_set_gpio_mode(IRTX_GPIO, GPIO_MODE_06); + mt_set_gpio_dir(IRTX_GPIO, GPIO_DIR_OUT); + mt_set_gpio_out(IRTX_GPIO, GPIO_OUT_ZERO); + + /*-----------------IR power off------------------*/ + mt_set_gpio_mode(IRTX_GPIO_EN, GPIO_MODE_00); + mt_set_gpio_dir(IRTX_GPIO_EN, GPIO_DIR_OUT); + mt_set_gpio_out(IRTX_GPIO_EN, GPIO_OUT_ZERO); + /*----------------------------------------------*/ +#endif /* !defined(CONFIG_MTK_LEGACY) */ + + return ret; +} + +static irqreturn_t irtx_isr(int irq, void *data) +{ + return IRQ_HANDLED; +} + +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) +static u64 irtx_dma_mask = DMA_BIT_MASK((sizeof(unsigned long) << 3)); /* TODO: 3? */ + +static struct file_operations const char_dev_fops = { + .owner = THIS_MODULE, + .open = &dev_char_open, + .read = &dev_char_read, + .write = &dev_char_write, + .release = &dev_char_close, + .unlocked_ioctl = &dev_char_ioctl, +}; + +#define irtx_driver_name "mt_irtx" +static int irtx_probe(struct platform_device *plat_dev) +{ + struct cdev *c_dev; + dev_t dev_t_irtx; + struct device *dev = NULL; + static void *dev_class; + u32 major = 0, minor = 0; + int ret = 0; +#if defined(CONFIG_MTK_LEGACY) + unsigned int gpio_id = -1; +#endif /* defined(CONFIG_MTK_LEGACY) */ + +#ifdef CONFIG_OF + if (plat_dev->dev.of_node == NULL) { + pr_err("[IRTX] irtx OF node is NULL\n"); + return -1; + } + + of_property_read_u32(plat_dev->dev.of_node, "major", &major); + mt_irtx_dev.reg_base = of_iomap(plat_dev->dev.of_node, 0); + mt_irtx_dev.irq = irq_of_parse_and_map(plat_dev->dev.of_node, 0); + of_property_read_u32(plat_dev->dev.of_node, "pwm_ch", &mt_irtx_dev.pwm_ch); + pr_debug("[IRTX] device tree info: major=%d base=0x%p irq=%d pwm=%d\n", major, + mt_irtx_dev.reg_base, mt_irtx_dev.irq, mt_irtx_dev.pwm_ch); +#endif + +#if !defined(CONFIG_MTK_CLKMGR) + mt_irtx_dev.clk_irtx_main = devm_clk_get(&plat_dev->dev, "clk-irtx-main"); + if (IS_ERR(mt_irtx_dev.clk_irtx_main)) { + pr_err("[IRTX][CCF]cannot get irtx clock. ptr_err:%ld\n", + PTR_ERR(mt_irtx_dev.clk_irtx_main)); + return PTR_ERR(mt_irtx_dev.clk_irtx_main); + } + pr_debug("[IRTX][CCF]clk_irtx_main:%p\n", mt_irtx_dev.clk_irtx_main); +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + +#if !defined(CONFIG_MTK_LEGACY) + mt_irtx_dev.ppinctrl_irtx = devm_pinctrl_get(&plat_dev->dev); + if (IS_ERR(mt_irtx_dev.ppinctrl_irtx)) { + pr_err("[IRTX][PinC]cannot find pinctrl. ptr_err:%ld\n", + PTR_ERR(mt_irtx_dev.ppinctrl_irtx)); + return PTR_ERR(mt_irtx_dev.ppinctrl_irtx); + } + pr_debug("[IRTX][PinC]devm_pinctrl_get ppinctrl:%p\n", mt_irtx_dev.ppinctrl_irtx); + + /* Set GPIO as default */ + switch_irtx_gpio(IRTX_GPIO_MODE_EN_DEFAULT); + switch_irtx_gpio(IRTX_GPIO_MODE_LED_DEFAULT); +#else /* !defined(CONFIG_MTK_LEGACY) */ + gpio_id = IRTX_GPIO; + + mt_set_gpio_mode(gpio_id, GPIO_MODE_06); + mt_set_gpio_dir(gpio_id, GPIO_DIR_OUT); +/* mt_set_gpio_out(gpio_id, GPIO_OUT_ZERO); */ +#endif /* !defined(CONFIG_MTK_LEGACY) */ + + if (!major) { + ret = alloc_chrdev_region(&dev_t_irtx, 0, 1, irtx_driver_name); + if (ret) { + pr_err("[IRTX] alloc_chrdev_region fail ret=%d\n", ret); + goto exit; + } else { + major = MAJOR(dev_t_irtx); + minor = MINOR(dev_t_irtx); + } + } else { + dev_t_irtx = MKDEV(major, minor); + ret = register_chrdev_region(dev_t_irtx, 1, irtx_driver_name); + if (ret) { + pr_err("[IRTX] register_chrdev_region fail ret=%d\n", ret); + goto exit; + } + } + + ret = request_irq(mt_irtx_dev.irq, irtx_isr, IRQF_TRIGGER_FALLING, "IRTX", NULL); /* TODO: trigger */ + if (ret) { + pr_err("[IRTX] request IRQ(%d) fail ret=%d\n", mt_irtx_dev.irq, ret); + goto exit; + } + irtx_pwm_config.pwm_no = mt_irtx_dev.pwm_ch; + + mt_irtx_dev.plat_dev = plat_dev; + mt_irtx_dev.plat_dev->dev.dma_mask = &irtx_dma_mask; + mt_irtx_dev.plat_dev->dev.coherent_dma_mask = irtx_dma_mask; + atomic_set(&mt_irtx_dev.usage_cnt, 0); + mt_irtx_dev.carrier_freq = 38000; /* NEC as default */ + + c_dev = kmalloc(sizeof(struct cdev), GFP_KERNEL); + if (!c_dev) + goto exit; + + cdev_init(c_dev, &char_dev_fops); + c_dev->owner = THIS_MODULE; + ret = cdev_add(c_dev, dev_t_irtx, 1); + if (ret) { + pr_err("[IRTX] cdev_add fail ret=%d\n", ret); + goto exit; + } + dev_class = class_create(THIS_MODULE, irtx_driver_name); + dev = device_create(dev_class, NULL, dev_t_irtx, NULL, "irtx"); + if (IS_ERR(dev)) { + ret = PTR_ERR(dev); + pr_err("[IRTX] device_create fail ret=%d\n", ret); + goto exit; + } + +exit: + pr_debug("[IRTX] irtx probe ret=%d\n", ret); + return ret; +} + +#ifdef CONFIG_OF +static const struct of_device_id irtx_of_ids[] = { + {.compatible = "mediatek,irtx",}, + {} +}; +#endif + +static struct platform_driver irtx_driver = { + .driver = { + .name = "mt_irtx", + }, + .probe = irtx_probe, +}; + +static int __init irtx_init(void) +{ + int ret = 0; + + pr_debug("[IRTX] irtx init\n"); +#ifdef CONFIG_OF + irtx_driver.driver.of_match_table = irtx_of_ids; +#else + pr_err("[IRTX] irtx needs device tree!\n"); + BUG_ON(1); +#endif + + ret = platform_driver_register(&irtx_driver); + if (ret) { + pr_err("[IRTX] irtx platform driver register fail %d\n", ret); + goto exit; + } + +exit: + return ret; +} + +module_init(irtx_init); + +MODULE_AUTHOR("Xiao Wang "); +MODULE_DESCRIPTION("Consumer IR transmitter driver v0.1"); diff --git a/drivers/misc/mediatek/irtx/mt6755/mt_irtx.h b/drivers/misc/mediatek/irtx/mt6755/mt_irtx.h new file mode 100644 index 0000000000000000000000000000000000000000..f838fdf67faa067dbf2e3954ef4b3024c09143f8 --- /dev/null +++ b/drivers/misc/mediatek/irtx/mt6755/mt_irtx.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +struct mt_irtx { + unsigned int pwm_ch; + unsigned int pwm_data_invert; + void __iomem *reg_base; + unsigned int irq; + struct platform_device *plat_dev; + unsigned int carrier_freq; + atomic_t usage_cnt; + + /* struct clk *clk_irtx_main; */ + struct clk *clk_irtx_main; + /* GPIO pin control */ + struct pinctrl *ppinctrl_irtx; +}; + +struct irtx_config { + unsigned int start : 1; + unsigned int mode : 2; + unsigned int sw_o : 1; + unsigned int b_ord : 1; + unsigned int r_ord : 1; + unsigned int ir_os : 1; + unsigned int ir_inv : 1; + unsigned int bit_num : 7; + unsigned int data_inv : 1; +}; + +#define IRTX_IOC_SET_CARRIER_FREQ _IOW('R', 0, unsigned int) +#define IRTX_IOC_GET_SOLUTTION_TYPE _IOR('R', 1, unsigned int) +#define IRTX_IOC_SET_IRTX_LED_EN _IOW('R', 10, unsigned int) + +#define irtx_write32(b, a, v) mt_reg_sync_writel(v, (b)+(a)) +#define irtx_read32(b, a) ioread32((void __iomem *)((b)+(a))) + +#define CLOCK_SRC 26 /* MHz */ + +#define IRTXCFG 0x0 +#define IRTXD0 0x4 +#define IRTXD1 0x8 +#define IRTXD2 0xC +#define IRTX_L0H 0x10 +#define IRTX_L0L 0x14 +#define IRTX_L1H 0x18 +#define IRTX_L1L 0x1C +#define IRTXSYNCH 0x20 +#define IRTXSYNCL 0x24 +#define IRTXMT 0x28 + diff --git a/drivers/misc/mediatek/irtx/mt6755/mt_irtx_pwm.c b/drivers/misc/mediatek/irtx/mt6755/mt_irtx_pwm.c new file mode 100644 index 0000000000000000000000000000000000000000..e8016038fd9df0bb872ad8e33d92f54143d99239 --- /dev/null +++ b/drivers/misc/mediatek/irtx/mt6755/mt_irtx_pwm.c @@ -0,0 +1,363 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#include +#endif + +#include +#include + +#include "mt_irtx.h" + +struct mt_irtx mt_irtx_dev; +void __iomem *irtx_reg_base; +unsigned int irtx_irq; + +static atomic_t ir_usage_cnt; + +int get_ir_device(void) +{ + if (atomic_cmpxchg(&ir_usage_cnt, 0, 1) != 0) + return -EBUSY; + return 0; +} + +int put_ir_device(void) +{ + if (atomic_cmpxchg(&ir_usage_cnt, 1, 0) != 1) + return -EFAULT; + return 0; +} + +struct pwm_spec_config irtx_pwm_config = { + .pwm_no = 3, + .mode = PWM_MODE_MEMORY, + .clk_div = CLK_DIV1, + .clk_src = PWM_CLK_NEW_MODE_BLOCK, + .pmic_pad = 0, + .PWM_MODE_MEMORY_REGS.IDLE_VALUE = IDLE_FALSE, + .PWM_MODE_MEMORY_REGS.GUARD_VALUE = GUARD_FALSE, + .PWM_MODE_MEMORY_REGS.STOP_BITPOS_VALUE = 31, + .PWM_MODE_MEMORY_REGS.HDURATION = 25, /* 1 microseconds, assume clock source is 26M */ + .PWM_MODE_MEMORY_REGS.LDURATION = 25, + .PWM_MODE_MEMORY_REGS.GDURATION = 0, + .PWM_MODE_MEMORY_REGS.WAVE_NUM = 1, +}; + +#if !defined(CONFIG_MTK_LEGACY) + +#define IRTX_GPIO_MODE_LED_DEFAULT 0 +#define IRTX_GPIO_MODE_LED_SET 1 +#define IRTX_GPIO_MODE_EN_DEFAULT 2 +#define IRTX_GPIO_MODE_EN_SET 3 +char *irtx_gpio_cfg[] = { "irtx_gpio_led_default", "irtx_gpio_led_set", + "irtx_gpio_en_default", "irtx_gpio_en_set" }; + +void switch_irtx_gpio(int mode) +{ + struct pinctrl *ppinctrl_irtx = mt_irtx_dev.ppinctrl_irtx; + struct pinctrl_state *pins_irtx = NULL; + + pr_debug("[IRTX][PinC]%s(%d)+\n", __func__, mode); + + if (mode >= (sizeof(irtx_gpio_cfg) / sizeof(irtx_gpio_cfg[0]))) { + pr_err("[IRTX][PinC]%s(%d) fail!! - parameter error!\n", __func__, mode); + return; + } + + if (IS_ERR(ppinctrl_irtx)) { + pr_err("[IRTX][PinC]%s ppinctrl_irtx:%p is error! err:%ld\n", + __func__, ppinctrl_irtx, PTR_ERR(ppinctrl_irtx)); + return; + } + + pins_irtx = pinctrl_lookup_state(ppinctrl_irtx, irtx_gpio_cfg[mode]); + if (IS_ERR(pins_irtx)) { + pr_err("[IRTX][PinC]%s pinctrl_lockup(%p, %s) fail!! ppinctrl:%p, err:%ld\n", + __func__, ppinctrl_irtx, irtx_gpio_cfg[mode], pins_irtx, PTR_ERR(pins_irtx)); + return; + } + + pinctrl_select_state(ppinctrl_irtx, pins_irtx); + pr_debug("[IRTX][PinC]%s(%d)-\n", __func__, mode); +} +#endif /* !defined(CONFIG_MTK_LEGACY) */ + +static int dev_char_open(struct inode *inode, struct file *file) +{ + int ret = 0; + + ret = get_ir_device(); + if (ret) { + pr_err("[IRTX] device busy\n"); + goto exit; + } + + pr_debug("[IRTX] open by %s\n", current->comm); + nonseekable_open(inode, file); +exit: + return ret; +} + +static int dev_char_close(struct inode *inode, struct file *file) +{ + int ret = 0; + + ret = put_ir_device(); + if (ret) { + pr_err("[IRTX] device close without open\n"); + goto exit; + } + + pr_debug("[IRTX] close by %s\n", current->comm); +exit: + return ret; +} + +static ssize_t dev_char_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + return 0; +} + +static long dev_char_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + unsigned int para = 0; + + switch (cmd) { + case IRTX_IOC_GET_SOLUTTION_TYPE: + ret = put_user(1, (unsigned int __user *)arg); + break; + case IRTX_IOC_SET_IRTX_LED_EN: + if (copy_from_user(¶, (void __user *)arg, sizeof(unsigned int))) { + pr_err("[IRTX] IRTX_IOC_SET_IRTX_LED_EN: copy_from_user fail!\n"); + ret = -EFAULT; + } else { + /* TODO */ + } + break; + default: + pr_err("[IRTX] unknown ioctl cmd 0x%x\n", cmd); + ret = -ENOTTY; + break; + } + return ret; +} + +static ssize_t dev_char_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + dma_addr_t wave_phy; + void *wave_vir; + int ret, i; + int buf_size = (count + 3) / 4; /* when count is 5... */ + unsigned char *data_ptr; + + pr_debug("[IRTX] irtx write len=0x%x, pwm=%d\n", (unsigned int)count, (unsigned int)irtx_pwm_config.pwm_no); + wave_vir = dma_alloc_coherent(&mt_irtx_dev.plat_dev->dev, count, &wave_phy, GFP_KERNEL); + if (!wave_vir) { + pr_err("[IRTX] alloc memory fail\n"); + return -ENOMEM; + } + ret = copy_from_user(wave_vir, buf, count); + if (ret) { + pr_err("[IRTX] write, copy from user fail %d\n", ret); + goto exit; + } + /* invert bit */ + if (mt_irtx_dev.pwm_data_invert) { + pr_debug("[IRTX] invert data\n"); + for (i = 0; i < count; i++) { + data_ptr = (unsigned char *)wave_vir + i; + *data_ptr = ~(*data_ptr); + } + } + + mt_set_intr_enable(0); + mt_set_intr_enable(1); + mt_pwm_26M_clk_enable_hal(1); + irtx_pwm_config.PWM_MODE_MEMORY_REGS.BUF0_BASE_ADDR = wave_phy; + irtx_pwm_config.PWM_MODE_MEMORY_REGS.BUF0_SIZE = (buf_size ? (buf_size - 1) : 0); + +#if !defined(CONFIG_MTK_LEGACY) + switch_irtx_gpio(IRTX_GPIO_MODE_EN_SET); + switch_irtx_gpio(IRTX_GPIO_MODE_LED_SET); +#endif /* !defined(CONFIG_MTK_LEGACY) */ + mt_set_intr_ack(0); + mt_set_intr_ack(1); + ret = pwm_set_spec_config(&irtx_pwm_config); + pr_debug("[IRTX] pwm is triggered, %d\n", ret); + + msleep(count * 8 / 1000); + msleep(100); + ret = count; +exit: + pr_debug("[IRTX] done, clean up\n"); + dma_free_coherent(&mt_irtx_dev.plat_dev->dev, count, wave_vir, wave_phy); + mt_pwm_disable(irtx_pwm_config.pwm_no, irtx_pwm_config.pmic_pad); + +#if !defined(CONFIG_MTK_LEGACY) + switch_irtx_gpio(IRTX_GPIO_MODE_LED_DEFAULT); + switch_irtx_gpio(IRTX_GPIO_MODE_EN_DEFAULT); +#endif /* !defined(CONFIG_MTK_LEGACY) */ + return ret; +} + +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) +static u64 irtx_dma_mask = DMA_BIT_MASK((sizeof(unsigned long) << 3)); /* TODO: 3? */ + +static struct file_operations const char_dev_fops = { + .owner = THIS_MODULE, + .open = &dev_char_open, + .read = &dev_char_read, + .write = &dev_char_write, + .release = &dev_char_close, + .unlocked_ioctl = &dev_char_ioctl, +}; + +#define irtx_driver_name "mt_irtx" +static int irtx_probe(struct platform_device *plat_dev) +{ + struct cdev *c_dev; + dev_t dev_t_irtx; + struct device *dev = NULL; + static void *dev_class; + u32 major = 0, minor = 0; + int ret = 0; + +#ifdef CONFIG_OF + if (plat_dev->dev.of_node == NULL) { + pr_err("[IRTX] irtx OF node is NULL\n"); + return -1; + } + + of_property_read_u32(plat_dev->dev.of_node, "major", &major); + mt_irtx_dev.reg_base = of_iomap(plat_dev->dev.of_node, 0); + mt_irtx_dev.irq = irq_of_parse_and_map(plat_dev->dev.of_node, 0); + of_property_read_u32(plat_dev->dev.of_node, "pwm_ch", &mt_irtx_dev.pwm_ch); + of_property_read_u32(plat_dev->dev.of_node, "pwm_data_invert", &mt_irtx_dev.pwm_data_invert); + pr_debug("[IRTX] device tree info: major=%d pwm=%d invert=%d\n", + major, mt_irtx_dev.pwm_ch, mt_irtx_dev.pwm_data_invert); +#endif + +#if !defined(CONFIG_MTK_LEGACY) + mt_irtx_dev.ppinctrl_irtx = devm_pinctrl_get(&plat_dev->dev); + if (IS_ERR(mt_irtx_dev.ppinctrl_irtx)) { + pr_err("[IRTX][PinC]cannot find pinctrl. ptr_err:%ld\n", + PTR_ERR(mt_irtx_dev.ppinctrl_irtx)); + return PTR_ERR(mt_irtx_dev.ppinctrl_irtx); + } + pr_debug("[IRTX][PinC]devm_pinctrl_get ppinctrl:%p\n", mt_irtx_dev.ppinctrl_irtx); + + /* Set GPIO as default */ + switch_irtx_gpio(IRTX_GPIO_MODE_EN_DEFAULT); + switch_irtx_gpio(IRTX_GPIO_MODE_LED_DEFAULT); +#endif /* !defined(CONFIG_MTK_LEGACY) */ + if (!major) { + ret = alloc_chrdev_region(&dev_t_irtx, 0, 1, irtx_driver_name); + if (ret) { + pr_err("[IRTX] alloc_chrdev_region fail ret=%d\n", ret); + goto exit; + } else { + major = MAJOR(dev_t_irtx); + minor = MINOR(dev_t_irtx); + } + } else { + dev_t_irtx = MKDEV(major, minor); + ret = register_chrdev_region(dev_t_irtx, 1, irtx_driver_name); + if (ret) { + pr_err("[IRTX] register_chrdev_region fail ret=%d\n", ret); + goto exit; + } + } + + irtx_pwm_config.pwm_no = mt_irtx_dev.pwm_ch; + + mt_irtx_dev.plat_dev = plat_dev; + mt_irtx_dev.plat_dev->dev.dma_mask = &irtx_dma_mask; + mt_irtx_dev.plat_dev->dev.coherent_dma_mask = irtx_dma_mask; + + c_dev = kmalloc(sizeof(struct cdev), GFP_KERNEL); + if (!c_dev) { + /* pr_err("[IRTX] kmalloc cdev fail\n"); */ + goto exit; + } + cdev_init(c_dev, &char_dev_fops); + c_dev->owner = THIS_MODULE; + ret = cdev_add(c_dev, dev_t_irtx, 1); + if (ret) { + pr_err("[IRTX] cdev_add fail ret=%d\n", ret); + goto exit; + } + dev_class = class_create(THIS_MODULE, irtx_driver_name); + dev = device_create(dev_class, NULL, dev_t_irtx, NULL, "irtx"); + if (IS_ERR(dev)) { + ret = PTR_ERR(dev); + pr_err("[IRTX] device_create fail ret=%d\n", ret); + goto exit; + } + + exit: + pr_debug("[IRTX] irtx probe ret=%d\n", ret); + return ret; +} + +#ifdef CONFIG_OF +static const struct of_device_id irtx_of_ids[] = { + {.compatible = "mediatek,irtx-pwm",}, + {} +}; +#endif + +static struct platform_driver irtx_driver = { + .driver = { + .name = "mt_irtx", + }, + .probe = irtx_probe, +}; + +static int __init irtx_init(void) +{ + int ret = 0; + + pr_debug("[IRTX] irtx init\n"); +#ifdef CONFIG_OF + irtx_driver.driver.of_match_table = irtx_of_ids; +#else + pr_err("[IRTX] irtx needs device tree!\n"); + BUG_ON(1); +#endif + + ret = platform_driver_register(&irtx_driver); + if (ret) { + pr_err("[IRTX] irtx platform driver register fail %d\n", ret); + goto exit; + } + + exit: + return ret; +} + +module_init(irtx_init); + +MODULE_AUTHOR("Xiao Wang "); +MODULE_DESCRIPTION("Consumer IR transmitter driver v0.1"); diff --git a/drivers/misc/mediatek/lcm/hct_hx8394d_dsi_vdo_hd_cmi/hct_hx8394d_dsi_vdo_hd_cmi.c b/drivers/misc/mediatek/lcm/hct_hx8394d_dsi_vdo_hd_cmi/hct_hx8394d_dsi_vdo_hd_cmi.c index 3d4c1907bc3da838bc935a939ee5cdf054e76e01..5974731d13ff41ca07a4dd3e023b7b1978e19de8 100644 --- a/drivers/misc/mediatek/lcm/hct_hx8394d_dsi_vdo_hd_cmi/hct_hx8394d_dsi_vdo_hd_cmi.c +++ b/drivers/misc/mediatek/lcm/hct_hx8394d_dsi_vdo_hd_cmi/hct_hx8394d_dsi_vdo_hd_cmi.c @@ -51,7 +51,7 @@ #define FRAME_WIDTH (720) #define FRAME_HEIGHT (1280) -#define LCM_ID (0x94) +#define LCM_ID (0x0d) #define REGFLAG_DELAY (0XFE) #define REGFLAG_END_OF_TABLE (0x100) // END OF REGISTERS MARKER @@ -75,17 +75,16 @@ static LCM_UTIL_FUNCS lcm_util = {0}; #define UDELAY(n) (lcm_util.udelay(n)) #define MDELAY(n) (lcm_util.mdelay(n)) -static unsigned int lcm_esd_test = FALSE; ///only for ESD test // --------------------------------------------------------------------------- // Local Functions // --------------------------------------------------------------------------- -#define dsi_set_cmdq_V3(para_tbl,size,force_update) lcm_util.dsi_set_cmdq_V3(para_tbl,size,force_update) + #define dsi_set_cmdq_V2(cmd, count, ppara, force_update) lcm_util.dsi_set_cmdq_V2(cmd, count, ppara, force_update) #define dsi_set_cmdq(pdata, queue_size, force_update) lcm_util.dsi_set_cmdq(pdata, queue_size, force_update) #define wrtie_cmd(cmd) lcm_util.dsi_write_cmd(cmd) #define write_regs(addr, pdata, byte_nums) lcm_util.dsi_write_regs(addr, pdata, byte_nums) -#define read_reg(cmd) lcm_util.dsi_dcs_read_lcm_reg(cmd) +#define read_reg lcm_util.dsi_read_reg() #define read_reg_v2(cmd, buffer, buffer_size) lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size) struct LCM_setting_table { @@ -94,114 +93,70 @@ static unsigned int lcm_esd_test = FALSE; ///only for ESD test unsigned char para_list[64]; }; +#if 0 static struct LCM_setting_table lcm_initialization_setting[] = { -// Set EXTC -{0xB9, 3, {0xFF,0x83,0x94}}, - -// Set MIPI -{0xBA, 6, {0x63,0x03,0x68,0x6B,0xB2,0xC0}}, - -// Set Power -{0xB1, 10, {0x50,0x12,0x72,0x09,0x33,0x54,0x71,0x31,0x70,0x2F}}, - -// Set Display -{0xB2, 6, {0x00,0x80,0x64,0x0E,0x0D,0x2F}}, - -// Set CYC -{0xB4, 21, {0x64,0x65,0x64,0x65,0x64,0x65,0x01,0x01,0x7E,0x75, -0x00,0x3F,0x64,0x65,0x64,0x65,0x64,0x65,0x01,0x01, -0x7E}}, - -// Set VCOM -{0xB6, 2, {0x75,0x75}}, - -// Set D3 -{0xD3, 33, {0x00,0x00,0x07,0x07,0x40,0x07,0x10,0x00,0x08,0x10, -0x08,0x00,0x08,0x54,0x15,0x0E,0x05,0x0E,0x02,0x15, -0x06,0x05,0x06,0x47,0x44,0x0A,0x0A,0x4B,0x10,0x07, -0x07,0x0E,0x40}}, - -// Set GIP -{0xD5, 44, {0x1A,0x1A,0x1B,0x1B,0x00,0x01,0x02,0x03,0x04,0x05, -0x06,0x07,0x08,0x09,0x0A,0x0B,0x24,0x25,0x18,0x18, -0x26,0x27,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, -0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x20,0x21, -0x18,0x18,0x18,0x18}}, - -// Set D6 -{0xD6, 44, {0x1A,0x1A,0x1B,0x1B,0x0B,0x0A,0x09,0x08,0x07,0x06, -0x05,0x04,0x03,0x02,0x01,0x00,0x21,0x20,0x18,0x18, -0x27,0x26,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, -0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x25,0x24, -0x18,0x18,0x18,0x18}}, - -// Set Gamma -{0xE0, 58, {0x00,0x0C,0x19,0x20,0x23,0x26,0x29,0x28,0x51,0x61, -0x70,0x6F,0x76,0x86,0x89,0x8D,0x99,0x9A,0x95,0xA1, -0xB0,0x57,0x55,0x58,0x5C,0x5E,0x64,0x6B,0x7F,0x00, -0x0C,0x18,0x20,0x23,0x26,0x29,0x28,0x51,0x61,0x70, -0x6F,0x76,0x86,0x89,0x8D,0x99,0x9A,0x95,0xA1,0xB0, -0x57,0x55,0x58,0x5C,0x5E,0x64,0x6B,0x7F}}, - -// Set C0 -{0xC0, 2, {0x1F,0x73}}, - -// Set Panel -{0xCC, 1, {0x0B}}, - -// Set D4 enhance -{0xD4, 1, {0x02}}, - -// Sleep Out -{0x11, 0, {0x00}}, -{REGFLAG_DELAY, 120, {0}}, - -// Set Power Option HX5186 Mode -{0xBF, 7, {0x40,0x81,0x50,0x02,0x1A,0xFC,0x02}}, - -// Display ON -{0x29, 0, {0x00}}, -{REGFLAG_DELAY, 20, {0}}, -}; + // Set EXTC + {0xB9, 3, {0xFF,0x83,0x94}}, + + // Set MIPI + {0xBA, 2, {0x73,0x83}}, + #if 1 //HX5186 Mode + // Set Power HX5186 Mode + {0xB1, 15, {0x6C,0x12,0x12,0x34,0x04,0x11,0xF1,0x80,0xFA,0x54,0x23,0x80,0xC0,0xD2,0x58}}, + #else //External Power mode + // Set Power External Power mode + {0xB1, 15, {0x6C,0x12,0x12,0x34,0x04,0x11,0xF1,0x80,0xFA,0x54,0x23,0x80,0xC0,0xD2,0x58}}, + #endif + + // Set Display + {0xB2, 11, {0x00,0x64,0x0E,0x0D,0x32,0x1C,0x08,0x08,0x1C,0x4D,0x00}}, + + // Set CYC + {0xB4, 12, {0x00,0xFF,0x51,0x5A,0x59,0x5A,0x03,0x5A,0x01,0x60,0x20,0x60}}, + + // Set VDC + {0xBC, 1, {0x07}}, + + // Set Power Option HX5186 Mode + {0xBF, 3, {0x41,0x0E,0x01}}, + + // Set Gamma + {0xE0, 42, {0x00,0x0E,0x13,0x32,0x37,0x3F,0x20,0x40,0x07,0x0B,0x0D,0x17,0x0E,0x10,0x14,0x12,0x13,0x06,0x10,0x10,0x17,0x00,0x0D,0x14,0x33,0x38,0x3F,0x21,0x3F,0x06,0x0A,0x0C,0x17,0x0D,0x11,0x13,0x12,0x14,0x07,0x11,0x12,0x16}}, + + // Set GIP + {0xD3, 30, {0x00,0x07,0x00,0x40,0x07,0x10,0x00,0x08,0x10,0x08,0x00,0x08,0x54,0x15,0x0E,0x05,0x0E,0x02,0x15,0x06,0x05,0x06,0x47,0x44,0x0A,0x0A,0x4B,0x10,0x07,0x07}}, + + // Set Forward GIP + {0xD5, 44, {0x1A,0x1A,0x1B,0x1B,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x24,0x25,0x18,0x18,0x26,0x27,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x20,0x21,0x18,0x18,0x18,0x18}}, + + // Set Backward GIP + {0xD6, 44, {0x1A,0x1A,0x1B,0x1B,0x0B,0x0A,0x09,0x08,0x07,0x06, + 0x05,0x04,0x03,0x02,0x01,0x00,0x21,0x20,0x58,0x58, + 0x27,0x26,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x25,0x24, + 0x18,0x18,0x18,0x18}}, + + // Set Panel + {0xCC, 1, {0x01}}, + + // Set C0 + {0xC0, 2, {0x30,0x14}}, + + // Set TCON Option + {0xC7, 4, {0x00,0xC0,0x40,0xC0}}, + + //----------------------------------------------------- + {0x11, 0, {0}}, + {REGFLAG_DELAY, 120, {0}}, -static struct LCM_setting_table lcm_sleep_out_setting[] = { - // Sleep Out - {0x11, 1, {0x00}}, - {REGFLAG_DELAY, 150, {}}, - // Display ON - //{0x2C, 1, {0x00}}, - //{0x13, 1, {0x00}}, - {0x29, 1, {0x00}}, - {REGFLAG_DELAY, 200, {}}, - {REGFLAG_END_OF_TABLE, 0x00, {}} + {0x29, 0, {0}}, + {REGFLAG_DELAY, 20, {0}}, }; -static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = { - // Display off sequence - {0x28, 1, {0x00}}, - {REGFLAG_DELAY, 150, {}}, - - // Sleep Mode On - {0x10, 1, {0x00}}, - {REGFLAG_DELAY, 150, {}}, - - {REGFLAG_END_OF_TABLE, 0x00, {}} -}; - -static struct LCM_setting_table lcm_compare_id_setting[] = { - // Display off sequence - {0xf0, 5, {0x55, 0xaa, 0x52, 0x08, 0x01}}, - {REGFLAG_DELAY, 10, {}}, - {REGFLAG_END_OF_TABLE, 0x00, {}} -}; -static struct LCM_setting_table lcm_backlight_level_setting[] = { - {0x51, 1, {0xFF}}, - {REGFLAG_END_OF_TABLE, 0x00, {}} -}; static void push_table(struct LCM_setting_table *table, unsigned int count, unsigned char force_update) @@ -229,7 +184,7 @@ static void push_table(struct LCM_setting_table *table, unsigned int count, unsi } - +#endif // --------------------------------------------------------------------------- // LCM Driver Implementations // --------------------------------------------------------------------------- @@ -248,9 +203,9 @@ static void lcm_get_params(LCM_PARAMS *params) // enable tearing-free params->dbi.te_mode = LCM_DBI_TE_MODE_DISABLED; - params->dbi.te_edge_polarity = LCM_POLARITY_RISING; + //params->dbi.te_edge_polarity = LCM_POLARITY_RISING; - params->dsi.mode = SYNC_PULSE_VDO_MODE; //SYNC_PULSE_VDO_MODE; + params->dsi.mode =SYNC_EVENT_VDO_MODE; // DSI /* Command mode setting */ @@ -266,79 +221,127 @@ static void lcm_get_params(LCM_PARAMS *params) // Video mode setting params->dsi.intermediat_buffer_num = 2; params->dsi.PS=LCM_PACKED_PS_24BIT_RGB888; - params->dsi.word_count=720 * 3; + //params->dsi.word_count=720 * 3; params->dsi.vertical_sync_active = 4;//5 params->dsi.vertical_backporch = 12; params->dsi.vertical_frontporch = 15; params->dsi.vertical_active_line = FRAME_HEIGHT; - params->dsi.horizontal_sync_active = 40; - params->dsi.horizontal_backporch = 40;//66 - params->dsi.horizontal_frontporch = 40;//70 + params->dsi.horizontal_sync_active = 40;//38//15 + params->dsi.horizontal_backporch = 40;//38//70 + params->dsi.horizontal_frontporch = 40;//38//65 //params->dsi.horizontal_blanking_pixel = 60; params->dsi.horizontal_active_pixel = FRAME_WIDTH; // Bit rate calculation - params->dsi.PLL_CLOCK=205;//227;//254;//254//247 240 +#if FRAME_WIDTH == 480 + params->dsi.PLL_CLOCK=210;//254//247 +#elif FRAME_WIDTH == 540 + params->dsi.PLL_CLOCK=230; +#elif FRAME_WIDTH == 720 + params->dsi.PLL_CLOCK=218;//256 276 +#elif FRAME_WIDTH == 1080 + params->dsi.PLL_CLOCK=410; +#else + params->dsi.PLL_CLOCK=230; +#endif + + params->dsi.esd_check_enable = 1; + params->dsi.customization_esd_check_enable = 1; + params->dsi.cont_clock=0; //1; + params->dsi.lcm_esd_check_table[0].cmd = 0xd9; + params->dsi.lcm_esd_check_table[0].count = 1; + params->dsi.lcm_esd_check_table[0].para_list[0] = 0x80; + /* + params->dsi.lcm_esd_check_table[0].cmd = 0x9;//09 ,45,d9 + params->dsi.lcm_esd_check_table[0].count = 3; + params->dsi.lcm_esd_check_table[0].para_list[0] = 0x80; + params->dsi.lcm_esd_check_table[0].para_list[1] = 0x73; + params->dsi.lcm_esd_check_table[0].para_list[2] = 0x6;//04/06 + + params->dsi.lcm_esd_check_table[1].cmd = 0xd9; + params->dsi.lcm_esd_check_table[1].count = 1; + params->dsi.lcm_esd_check_table[1].para_list[0] = 0x80; + //params->dsi.lcm_esd_check_table[1].para_list[1] = 0x00; + //params->dsi.lcm_esd_check_table[1].para_list[2] = 0x45; + + params->dsi.lcm_esd_check_table[2].cmd = 0x45; + params->dsi.lcm_esd_check_table[2].count = 2; + params->dsi.lcm_esd_check_table[2].para_list[0] = 0x5; + params->dsi.lcm_esd_check_table[2].para_list[1] = 0x1d; + */ } -static unsigned int lcm_init_resgister(void) +static void lcm_init_register(void) { - unsigned int data_array[16]; - + unsigned int data_array[16]; + MDELAY(180); data_array[0] = 0x00043902; data_array[1] = 0x9483ffb9; dsi_set_cmdq(data_array, 2, 1); - MDELAY(5); - data_array[0] = 0x00073902; - data_array[1] = 0x680363ba; - data_array[2] = 0x00c0b26b; - dsi_set_cmdq(data_array, 3, 1); - MDELAY(5); - data_array[0] = 0x000B3902; - data_array[1] = 0x721250b1; - data_array[2] = 0x71543309; - data_array[3] = 0x002f7031; + + data_array[0] = 0x00033902; + data_array[1] = 0x008373ba; + dsi_set_cmdq(data_array, 2, 1); + + data_array[0] = 0x00103902; + data_array[1] = 0x12126cb1; + data_array[2] = 0xf1110434; + data_array[3] = 0x2354fa80; + data_array[4] = 0x58d2c080; + dsi_set_cmdq(data_array, 5, 1); + + data_array[0] = 0x000c3902; + data_array[1] = 0x0e6400b2; + data_array[2] = 0x081c320d; + data_array[3] = 0x004d1c08; dsi_set_cmdq(data_array, 4, 1); - MDELAY(5); - data_array[0] = 0x00073902; - data_array[1] = 0x648000b2; - data_array[2] = 0x002F0D0E; - dsi_set_cmdq(data_array, 3, 1); - MDELAY(5); - data_array[0] = 0x00163902; - data_array[1] = 0x646564b4; - data_array[2] = 0x01656465; - data_array[3] = 0x00757E01; - data_array[4] = 0x6465643F; - data_array[5] = 0x01656465; - data_array[6] = 0x00007E01; - dsi_set_cmdq(data_array, 7, 1); - MDELAY(5); - - data_array[0] = 0x00033902; - data_array[1] = 0x007575b6; + + data_array[0] = 0x000d3902; + data_array[1] = 0x51ff00b4; + data_array[2] = 0x035a595a; + data_array[3] = 0x2070015a; + data_array[4] = 0x00000070; + dsi_set_cmdq(data_array, 5, 1); + + data_array[0] = 0x00023902; + data_array[1] = 0x000007bc; dsi_set_cmdq(data_array, 2, 1); - MDELAY(5); - - data_array[0] = 0x00223902; - data_array[1] = 0x070000d3; - data_array[2] = 0x10074007; - data_array[3] = 0x08100800; - data_array[4] = 0x15540800; - data_array[5] = 0x020E050E; - data_array[6] = 0x06050615; - data_array[7] = 0x0A0A4447; - data_array[8] = 0x0707104B; - data_array[9] = 0x0000400E; - dsi_set_cmdq(data_array, 10, 1); - MDELAY(5); - + + data_array[0] = 0x00043902; + data_array[1] = 0x010e41bf; + dsi_set_cmdq(data_array, 2, 1); + + data_array[0] = 0x002b3902; + data_array[1] = 0x130e00e0; + data_array[2] = 0x203f3732; + data_array[3] = 0x0d0b0740; + data_array[4] = 0x14100e17; + data_array[5] = 0x10061312; + data_array[6] = 0x0d001710; + data_array[7] = 0x3f383314; + data_array[8] = 0x0a063f21; + data_array[9] = 0x110d170c; + data_array[10] = 0x07141213; + data_array[11] = 0x00161211; + dsi_set_cmdq(data_array, 12, 1); + + data_array[0] = 0x001f3902; + data_array[1] = 0x000700d3; + data_array[2] = 0x00100740; + data_array[3] = 0x00081008; + data_array[4] = 0x0e155408; + data_array[5] = 0x15020e05; + data_array[6] = 0x47060506; + data_array[7] = 0x4b0a0a44; + data_array[8] = 0x00070710; + dsi_set_cmdq(data_array, 9, 1); + data_array[0] = 0x002d3902; - data_array[1] = 0x1B1A1Ad5; - data_array[2] = 0x0201001B; + data_array[1] = 0x1b1a1ad5; + data_array[2] = 0x0201001b; data_array[3] = 0x06050403; - data_array[4] = 0x0A090807; - data_array[5] = 0x1825240B; + data_array[4] = 0x0a090807; + data_array[5] = 0x1825240b; data_array[6] = 0x18272618; data_array[7] = 0x18181818; data_array[8] = 0x18181818; @@ -347,14 +350,14 @@ static unsigned int lcm_init_resgister(void) data_array[11] = 0x18181821; data_array[12] = 0x00000018; dsi_set_cmdq(data_array, 13, 1); - MDELAY(5); - data_array[0] = 0x002d3902; - data_array[1] = 0x1B1A1Ad6; - data_array[2] = 0x090A0B1B; + + data_array[0] = 0x002d3902; + data_array[1] = 0x1b1a1ad6; + data_array[2] = 0x090a0b1b; data_array[3] = 0x05060708; data_array[4] = 0x01020304; - data_array[5] = 0x18202100; - data_array[6] = 0x18262718; + data_array[5] = 0x58202100; + data_array[6] = 0x18262758; data_array[7] = 0x18181818; data_array[8] = 0x18181818; data_array[9] = 0x18181818; @@ -362,163 +365,84 @@ static unsigned int lcm_init_resgister(void) data_array[11] = 0x18181824; data_array[12] = 0x00000018; dsi_set_cmdq(data_array, 13, 1); - MDELAY(5); - - data_array[0] = 0x003B3902; - data_array[1] = 0x190C00e0; - data_array[2] = 0x29262320; - data_array[3] = 0x70615128; - data_array[4] = 0x8986766F; - data_array[5] = 0x959A998D; - data_array[6] = 0x5557B0A1; - data_array[7] = 0x645E5C58; - data_array[8] = 0x0C007F6B; - data_array[9] = 0x26232018; - data_array[10] = 0x61512829; - data_array[11] = 0x86766F70; - data_array[12] = 0x9A998D89; - data_array[13] = 0x57B0A195; - data_array[14] = 0x5E5C5855; - data_array[15] = 0x007F6B64; - dsi_set_cmdq(data_array, 16, 1); - MDELAY(5); - - - - data_array[0] = 0x00033902; - data_array[1] = 0x00731Fc0; + + data_array[0] = 0x00023902; + data_array[1] = 0x0000bdc6; dsi_set_cmdq(data_array, 2, 1); - MDELAY(5); - + data_array[0] = 0x00023902; - data_array[1] = 0x00000Bcc; + data_array[1] = 0x000002bd; dsi_set_cmdq(data_array, 2, 1); - MDELAY(5); + + data_array[0] = 0x000d3902; + data_array[1] = 0xeeffffd8; + data_array[2] = 0xffa0fbeb; + data_array[3] = 0xfbebeeff; + data_array[4] = 0x000000a0; + dsi_set_cmdq(data_array, 5, 1); + data_array[0] = 0x00023902; - data_array[1] = 0x000002D4; + data_array[1] = 0x000009cc; + dsi_set_cmdq(data_array, 2, 1); + + data_array[0] = 0x00033902; + data_array[1] = 0x001430c0; + dsi_set_cmdq(data_array, 2, 1); + + data_array[0] = 0x00053902; + data_array[1] = 0x40c000c7; + data_array[2] = 0x000000c0; + dsi_set_cmdq(data_array, 3, 1); + + data_array[0] = 0x00033902; + data_array[1] = 0x006767b6; dsi_set_cmdq(data_array, 2, 1); - MDELAY(5); + MDELAY(15); data_array[0] = 0x00110500; dsi_set_cmdq(data_array, 1, 1); MDELAY(120); - - data_array[0] = 0x00083902; - data_array[1] = 0x508140BF; - data_array[2] = 0x02FC1A02; - dsi_set_cmdq(data_array, 3, 1); - MDELAY(5); - - data_array[0] = 0x00290500; dsi_set_cmdq(data_array, 1, 1); MDELAY(20); - /////////////////////////// -return 0; -}; - +} static void lcm_init(void) { SET_RESET_PIN(1); MDELAY(10); SET_RESET_PIN(0); - MDELAY(20); + MDELAY(10); SET_RESET_PIN(1); MDELAY(120); - lcm_init_resgister(); - // dsi_set_cmdq_V3(lcm_initialization_setting_V3, sizeof(lcm_initialization_setting_V3) / sizeof(LCM_setting_table_V3), 1); - // dsi_set_cmdq_V3(lcm_initialization_setting,sizeof(lcm_initialization_setting)/sizeof(lcm_initialization_setting[0]),1); + lcm_init_register(); //push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1); } static void lcm_suspend(void) { -#ifndef BUILD_LK - SET_RESET_PIN(1); //NOTE:should reset LCM firstly - MDELAY(10); - SET_RESET_PIN(0); - MDELAY(30); - SET_RESET_PIN(1); - MDELAY(120); -// push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1); //wqtao. enable -#endif + unsigned int data_array[16]; + data_array[0]=0x00280500; + dsi_set_cmdq(data_array, 1, 1); + MDELAY(10); + data_array[0]=0x00100500; + dsi_set_cmdq(data_array, 1, 1); + SET_RESET_PIN(1); + MDELAY(10); + SET_RESET_PIN(0); + MDELAY(50); } static unsigned int lcm_compare_id(void); static void lcm_resume(void) { -#ifndef BUILD_LK -// lcm_compare_id(); lcm_init(); -#endif } -static unsigned int lcm_esd_check(void) -{ -#ifndef BUILD_LK - int array[4]; - unsigned char buffer[2]; - - if(lcm_esd_test) - { - lcm_esd_test = FALSE; - return TRUE; - } - - /// please notice: the max return packet size is 1 - /// if you want to change it, you can refer to the following marked code - /// but read_reg currently only support read no more than 4 bytes.... - /// if you need to read more, please let BinHan knows. - /* - unsigned int data_array[16]; - unsigned int max_return_size = 1; - - data_array[0]= 0x00003700 | (max_return_size << 16); - - dsi_set_cmdq(&data_array, 1, 1); - */ - - array[0]=0x00043902; - array[1]=0x9483FFB9;// page enable - dsi_set_cmdq(array, 2, 1); -// MDELAY(20); - - array[0]=0x00083902; - array[1]=0x009341BA;// page enable - array[2]=0x1800A416; - dsi_set_cmdq(array, 3, 1); -// MDELAY(10); - - array[0] = 0x00023700;// return byte number - dsi_set_cmdq(array, 1, 1); -// MDELAY(10); - read_reg_v2(0x0a, buffer, 1); - - #ifndef BUILD_LK - printk("[%s] hct_hx8394f_dsi_vdo_hd_* lcm esd check. arthur %x\n", __FUNCTION__, buffer[0]); - #endif - - if(buffer[0] == 0x1c) - { - return FALSE; - } - else - { - return TRUE; - } -#endif -} - -static unsigned int lcm_esd_recover(void) -{ - lcm_init(); - return TRUE; -} static unsigned int lcm_compare_id(void) { @@ -539,7 +463,7 @@ static unsigned int lcm_compare_id(void) MDELAY(10); array[0]=0x00033902; - array[1]=0x008373BA;// page enable //9341 + array[1]=0x008372BA;// page enable //9341 //array[2]=0x1800A416; dsi_set_cmdq(array, 2, 1); MDELAY(10); @@ -548,7 +472,7 @@ static unsigned int lcm_compare_id(void) dsi_set_cmdq(array, 1, 1); MDELAY(10); - read_reg_v2(0xF4, buffer, 2); + read_reg_v2(0xdc, buffer, 2); id = buffer[0]; #ifdef BUILD_LK @@ -557,6 +481,7 @@ static unsigned int lcm_compare_id(void) printk("[HX8394D]%s, id = 0x%x\n", __func__, id); #endif + return (LCM_ID == id)?1:0; } diff --git a/drivers/misc/mediatek/lcm/ili9881_hds_hd720_5p0_h1_t592_otd/Makefile b/drivers/misc/mediatek/lcm/ili9881_hds_hd720_5p0_h1_t592_otd/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..51e0eb23901c44a19b61694993494d7362cab408 --- /dev/null +++ b/drivers/misc/mediatek/lcm/ili9881_hds_hd720_5p0_h1_t592_otd/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for misc devices that really don't fit anywhere else. +# +ifdef MTK_LEGCY +include $(srctree)/drivers/misc/mediatek/Makefile.custom +endif + +ccflags-y += -Wno-unused-variable -g +ccflags-y += -Wno-unused-function -g + +obj-y +=ili9881_hds_hd720_5p0_h1_t592_otd.o + + + + diff --git a/drivers/misc/mediatek/lcm/ili9881_hds_hd720_5p0_h1_t592_otd/ili9881_hds_hd720_5p0_h1_t592_otd.c b/drivers/misc/mediatek/lcm/ili9881_hds_hd720_5p0_h1_t592_otd/ili9881_hds_hd720_5p0_h1_t592_otd.c new file mode 100644 index 0000000000000000000000000000000000000000..a7a39bdfe0b7994ce133ebf368e76f9fb11b3ad3 --- /dev/null +++ b/drivers/misc/mediatek/lcm/ili9881_hds_hd720_5p0_h1_t592_otd/ili9881_hds_hd720_5p0_h1_t592_otd.c @@ -0,0 +1,688 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + */ +/* MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + +/***************************************************************************** +* Copyright Statement: +* -------------------- +* This software is protected by Copyright and the information contained +* herein is confidential. The software may not be copied and the information +* contained herein may not be used or disclosed except with the written +* permission of MediaTek Inc. (C) 2008 +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES +* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") +* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON +* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. +* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE +* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR +* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH +* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO +* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S +* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, +* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, +* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO +* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF +* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND +* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER +* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). +* +*****************************************************************************/ +#ifndef BUILD_LK +#include +#endif + +#include "lcm_drv.h" + +#if defined(BUILD_LK) +#else + +#include //proc file use +#endif + + +// --------------------------------------------------------------------------- +// Local Constants +// --------------------------------------------------------------------------- + +#define FRAME_WIDTH (720) +#define FRAME_HEIGHT (1280) +#define LCM_ID (0x1283) + +#define REGFLAG_DELAY (0XFE) +#define REGFLAG_END_OF_TABLE (0x100) // END OF REGISTERS MARKER + + +#define LCM_DSI_CMD_MODE 0 + +#ifndef TRUE + #define TRUE 1 +#endif + +#ifndef FALSE + #define FALSE 0 +#endif + +// --------------------------------------------------------------------------- +// Local Variables +// --------------------------------------------------------------------------- + +static LCM_UTIL_FUNCS lcm_util = {0}; + +#define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v))) + +#define UDELAY(n) (lcm_util.udelay(n)) +#define MDELAY(n) (lcm_util.mdelay(n)) + +static unsigned int lcm_esd_test = FALSE; ///only for ESD test + +// --------------------------------------------------------------------------- +// Local Functions +// --------------------------------------------------------------------------- + +#define dsi_set_cmdq_V2(cmd, count, ppara, force_update) lcm_util.dsi_set_cmdq_V2(cmd, count, ppara, force_update) +#define dsi_set_cmdq(pdata, queue_size, force_update) lcm_util.dsi_set_cmdq(pdata, queue_size, force_update) +#define wrtie_cmd(cmd) lcm_util.dsi_write_cmd(cmd) +#define write_regs(addr, pdata, byte_nums) lcm_util.dsi_write_regs(addr, pdata, byte_nums) +#define read_reg(cmd) lcm_util.dsi_dcs_read_lcm_reg(cmd) +#define read_reg_v2(cmd, buffer, buffer_size) lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size) + + struct LCM_setting_table { + unsigned cmd; + unsigned char count; + unsigned char para_list[64]; +}; + + +static struct LCM_setting_table lcm_initialization_setting[] = { + + /* + Note : + + Data ID will depends on the following rule. + + count of parameters > 1 => Data ID = 0x39 + count of parameters = 1 => Data ID = 0x15 + count of parameters = 0 => Data ID = 0x05 + + Structure Format : + + {DCS command, count of parameters, {parameter list}} + {REGFLAG_DELAY, milliseconds of time, {}}, + + ... + + Setting ending by predefined flag + + {REGFLAG_END_OF_TABLE, 0x00, {}} + */ +{0xFF,3,{0x98,0x81,0x07}}, //CMD_Page 7 +{0x03,1,{0x20 }}, //GIP_1 +{0x04,1,{0x06 }}, +{0x05,1,{0x00 }}, +{0x06,1,{0x1 }}, +{0x07,1,{0x00 }}, +{0x08,1,{0x00 }}, +{0x09,1,{0x00 }}, +{0x0A,1,{0x1 }}, +{0x0B,1,{0x2F }}, +{0x0C,1,{0x00 }}, +{0x0D,1,{0x00 }}, +{0x0E,1,{0x00 }}, +{0x0F,1,{0x00 }}, +{0x10,1,{0x44 }}, +{0x11,1,{0x02 }}, +{0x12,1,{0x03 }}, +{0x13,1,{0x00 }}, +{0x14,1,{0x00 }}, +{0x15,1,{0x00 }}, +{0x16,1,{0x2F }}, +{0x17,1,{0x2F }}, +{0x18,1,{0x00 }}, +{0x19,1,{0x00 }}, +{0x1A,1,{0x00 }}, +{0x1B,1,{0x50 }}, +{0x1C,1,{0xBB }}, +{0x1D,1,{0x0C }}, +{0x1E,1,{0x00 }}, +{0x1F,1,{0x00 }}, +{0x20,1,{0x00 }}, +{0x21,1,{0x00 }}, +{0x22,1,{0x00 }}, +{0x23,1,{0x00 }}, +{0x24,1,{0x30 }}, +{0x25,1,{0x00 }}, +{0x26,1,{0x00 }}, +{0x27,1,{0x03 }}, +{0x30,1,{0x1 }},//GIP_2 +{0x31,1,{0x23 }}, +{0x32,1,{0x45 }}, +{0x33,1,{0x67 }}, +{0x34,1,{0x89 }}, +{0x35,1,{0xAB }}, +{0x36,1,{0x1 }}, +{0x37,1,{0x23 }}, +{0x38,1,{0x45 }}, +{0x39,1,{0x67 }}, +{0x3A,1,{0x89 }}, +{0x3B,1,{0xAB }}, +{0x3C,1,{0xCD }}, +{0x3D,1,{0xEF }}, + +{0x50,1,{0x11 }}, //GIP_3 +{0x51,1,{0x06 }}, +{0x52,1,{0x0C }}, +{0x53,1,{0x0D }}, +{0x54,1,{0x0E }}, +{0x55,1,{0x0F }}, +{0x56,1,{0x02 }}, +{0x57,1,{0x02 }}, +{0x58,1,{0x02 }}, +{0x59,1,{0x02 }}, +{0x5A,1,{0x02 }}, +{0x5B,1,{0x02 }}, +{0x5C,1,{0x02 }}, +{0x5D,1,{0x02 }}, +{0x5E,1,{0x02 }}, +{0x5F,1,{0x02 }}, +{0x60,1,{0x05 }}, +{0x61,1,{0x05 }}, +{0x62,1,{0x05 }}, +{0x63,1,{0x02 }}, +{0x64,1,{0x1 }}, +{0x65,1,{0x00 }}, +{0x66,1,{0x08 }}, +{0x67,1,{0x08 }}, +{0x68,1,{0x0C }}, +{0x69,1,{0x0D }}, +{0x6A,1,{0x0E }}, +{0x6B,1,{0x0F }}, +{0x6C,1,{0x02 }}, +{0x6D,1,{0x02 }}, +{0x6E,1,{0x02 }}, +{0x6F,1,{0x02 }}, +{0x70,1,{0x02 }}, +{0x71,1,{0x02 }}, +{0x72,1,{0x02 }}, +{0x73,1,{0x02 }}, +{0x74,1,{0x02 }}, +{0x75,1,{0x02 }}, +{0x76,1,{0x05 }}, +{0x77,1,{0x05 }}, +{0x78,1,{0x05 }}, +{0x79,1,{0x02 }}, +{0x7A,1,{0x1 }}, +{0x7B,1,{0x00 }}, +{0x7C,1,{0x06 }}, + +{0xFF,3,{0x98,0x81,0x08}}, //CMD_Page 8 +{0x76,1,{0xB4 }}, //VGH pumping ratio 3x +{0x78,1,{0x02 }}, +{0x74,1,{0x2B }}, +{0x8E,1,{0x15 }}, +{0x40,1,{0x1 }}, +{0x84,1,{0x81 }}, +{0x72,1,{0x25 }}, +{0xE3,1,{0x45 }}, +{0x7D,1,{0xCB }}, +{0x7E,1,{0x49 }}, +{0x49,1,{0x10 }}, +{0x2F,1,{0x1 }}, + +{0xFF,3,{0x98,0x81,0x1}}, //CMD_Page 1 +{0x22,1,{0x0A }}, +{0x53,1,{0x6F }}, +{0x55,1,{0x75 }}, +{0x50,1,{0xB9 }}, +{0x51,1,{0xBA }}, +{0x31,1,{0x00 }}, + +{0xA0,1,{0x08 }}, //VP255 Gamma P +{0xA1,1,{0x14 }}, //VP251 +{0xA2,1,{0x1d }}, //VP247 +{0xA3,1,{0x0f }}, +{0xA4,1,{0x0d }}, +{0xA5,1,{0x1f }}, +{0xA6,1,{0x14 }}, +{0xA7,1,{0x18 }}, +{0xA8,1,{0x7d }}, +{0xA9,1,{0x1d }}, +{0xAA,1,{0x2a }}, +{0xAB,1,{0x83 }}, +{0xAC,1,{0x1d }}, +{0xAD,1,{0x1d }}, +{0xAE,1,{0x50 }}, +{0xAF,1,{0x22 }}, +{0xB0,1,{0x23 }}, +{0xB1,1,{0x28 }}, +{0xB2,1,{0x53 }}, +{0xB3,1,{0x63 }}, +{0xB7,1,{0x39 }}, + +{0xC0,1,{0x08 }}, //VN255 GAMMA N +{0xC1,1,{0x13 }}, //VN251 +{0xC2,1,{0x1d }}, //VN247 +{0xC3,1,{0x0e }}, +{0xC4,1,{0x0e }}, +{0xC5,1,{0x1f }}, +{0xC6,1,{0x13 }}, +{0xC7,1,{0x18 }}, +{0xC8,1,{0x7e }}, +{0xC9,1,{0x1e }}, +{0xCA,1,{0x2b }}, +{0xCB,1,{0x83 }}, +{0xCC,1,{0x1e }}, +{0xCD,1,{0x1c }}, +{0xCE,1,{0x50 }}, +{0xCF,1,{0x23 }}, +{0xD0,1,{0x29 }}, +{0xD1,1,{0x53 }}, +{0xD2,1,{0x63 }}, +{0xD3,1,{0x39 }}, + +{0xFF,3,{0x98,0x81,0x00 }}, + +{0x35,1,{0x00}}, //TE ON +//{0x35}1{, + {0x11,1,{0x00}}, + {REGFLAG_DELAY,120,{}}, + + {0x29,1,{0x00}},//Display ON + {REGFLAG_DELAY,20,{}}, + +// Setting ending by predefined flag + {REGFLAG_END_OF_TABLE, 0x00, {}} +}; + +static struct LCM_setting_table lcm_sleep_out_setting[] = { + // Sleep Out + {0x11, 1, {0x00}}, + {REGFLAG_DELAY, 120, {}}, + // Display ON + //{0x2C, 1, {0x00}}, + //{0x13, 1, {0x00}}, + {0x29, 1, {0x00}}, + {REGFLAG_DELAY, 20, {}}, + {REGFLAG_END_OF_TABLE, 0x00, {}} +}; + + +static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = { + // Display off sequence + {0x28, 1, {0x00}}, + {REGFLAG_DELAY, 20, {}}, + + // Sleep Mode On + {0x10, 1, {0x00}}, + {REGFLAG_DELAY, 120, {}}, + + {REGFLAG_END_OF_TABLE, 0x00, {}} +}; + +static struct LCM_setting_table lcm_compare_id_setting[] = { + // Display off sequence + {0xf0, 5, {0x55, 0xaa, 0x52, 0x08, 0x01}}, + {REGFLAG_DELAY, 10, {}}, + {REGFLAG_END_OF_TABLE, 0x00, {}} +}; + +static struct LCM_setting_table lcm_backlight_level_setting[] = { + {0x51, 1, {0xFF}}, + {REGFLAG_END_OF_TABLE, 0x00, {}} +}; + +//static int vcom=0x40; +static void push_table(struct LCM_setting_table *table, unsigned int count, unsigned char force_update) +{ + unsigned int i; + + for(i = 0; i < count; i++) { + + unsigned cmd; + cmd = table[i].cmd; + + switch (cmd) { + /*case 0xd9: + table[i].para_list[0]=vcom; + dsi_set_cmdq_V2(cmd, table[i].count, table[i].para_list, force_update); + vcom+=2; + break; + */ + case REGFLAG_DELAY : + MDELAY(table[i].count); + break; + + case REGFLAG_END_OF_TABLE : + break; + + default: + dsi_set_cmdq_V2(cmd, table[i].count, table[i].para_list, force_update); + } + } + +} + + +// --------------------------------------------------------------------------- +// LCM Driver Implementations +// --------------------------------------------------------------------------- + +static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util) +{ + memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS)); +} + + +static void lcm_get_params(LCM_PARAMS *params) +{ + memset(params, 0, sizeof(LCM_PARAMS)); + params->type = LCM_TYPE_DSI; + params->width = FRAME_WIDTH; + params->height = FRAME_HEIGHT; + + // enable tearing-free + params->dbi.te_mode = LCM_DBI_TE_MODE_DISABLED; + params->dbi.te_edge_polarity = LCM_POLARITY_RISING; + + + + params->dsi.mode = SYNC_EVENT_VDO_MODE; + + + // DSI + /* Command mode setting */ + params->dsi.LANE_NUM = LCM_FOUR_LANE; + //The following defined the fomat for data coming from LCD engine. + params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB; + params->dsi.data_format.trans_seq = LCM_DSI_TRANS_SEQ_MSB_FIRST; + params->dsi.data_format.padding = LCM_DSI_PADDING_ON_LSB; + params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888; + // Highly depends on LCD driver capability. + // Not support in MT6573 + params->dsi.packet_size=256; + // Video mode setting + params->dsi.intermediat_buffer_num = 2; + params->dsi.PS=LCM_PACKED_PS_24BIT_RGB888; + params->dsi.vertical_sync_active = 4; + params->dsi.vertical_backporch = 16; + params->dsi.vertical_frontporch = 15; + params->dsi.vertical_active_line = FRAME_HEIGHT; + params->dsi.horizontal_sync_active = 10; + params->dsi.horizontal_backporch = 64; + params->dsi.horizontal_frontporch = 64; + params->dsi.horizontal_blanking_pixel = 60; + params->dsi.horizontal_active_pixel = FRAME_WIDTH; + // Bit rate calculation +#if 0 + params->dsi.pll_div1=1; // div1=0,1,2,3;div1_real=1,2,4,4 + params->dsi.pll_div2=1; // div2=0,1,2,3;div2_real=1,2,4,4 + params->dsi.fbk_sel=1; // fbk_sel=0,1,2,3;fbk_sel_real=1,2,4,4 + params->dsi.fbk_div =30; // fref=26MHz, fvco=fref*(fbk_div+1)*2/(div1_real*div2_real) +#else + params->dsi.PLL_CLOCK=230;//227;//254;//254//247 +#endif +} + +static void lcm_init(void) +{ + SET_RESET_PIN(1); + MDELAY(10); + SET_RESET_PIN(0); + MDELAY(20); + SET_RESET_PIN(1); + MDELAY(120); + + push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1); +#ifdef BUILD_LK + printf("[erick-lk]%s\n", __func__); +#else + printk("[erick-k]%s\n", __func__); +#endif +} + + +static void lcm_suspend(void) +{ +#ifndef BUILD_LK + push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1); //wqtao. enable + #ifdef BUILD_LK + printf("[erick-lk]%s\n", __func__); + #else + printk("[erick-k]%s\n", __func__); + #endif +#endif +} + + +static void lcm_resume(void) +{ +#ifndef BUILD_LK + push_table(lcm_sleep_out_setting, sizeof(lcm_sleep_out_setting) / sizeof(struct LCM_setting_table), 1); + #ifdef BUILD_LK + printf("[erick-lk]%s\n", __func__); + #else + printk("[erick-k]%s\n", __func__); + #endif +#endif +} + +#if (LCM_DSI_CMD_MODE) +static void lcm_update(unsigned int x, unsigned int y, + unsigned int width, unsigned int height) +{ + unsigned int x0 = x; + unsigned int y0 = y; + unsigned int x1 = x0 + width - 1; + unsigned int y1 = y0 + height - 1; + + unsigned char x0_MSB = ((x0>>8)&0xFF); + unsigned char x0_LSB = (x0&0xFF); + unsigned char x1_MSB = ((x1>>8)&0xFF); + unsigned char x1_LSB = (x1&0xFF); + unsigned char y0_MSB = ((y0>>8)&0xFF); + unsigned char y0_LSB = (y0&0xFF); + unsigned char y1_MSB = ((y1>>8)&0xFF); + unsigned char y1_LSB = (y1&0xFF); + + unsigned int data_array[16]; + + + data_array[0]= 0x00053902; + data_array[1]= (x1_MSB<<24)|(x0_LSB<<16)|(x0_MSB<<8)|0x2a; + data_array[2]= (x1_LSB); + dsi_set_cmdq(data_array, 3, 1); + + data_array[0]= 0x00053902; + data_array[1]= (y1_MSB<<24)|(y0_LSB<<16)|(y0_MSB<<8)|0x2b; + data_array[2]= (y1_LSB); + dsi_set_cmdq(data_array, 3, 1); + + data_array[0]= 0x00290508; //HW bug, so need send one HS packet + dsi_set_cmdq(data_array, 1, 1); + + data_array[0]= 0x002c3909; + dsi_set_cmdq(data_array, 1, 0); +} +#endif + +#if 0 //wqtao. +static void lcm_setbacklight(unsigned int level) +{ + unsigned int default_level = 145; + unsigned int mapped_level = 0; + + //for LGE backlight IC mapping table + if(level > 255) + level = 255; + + if(level >0) + mapped_level = default_level+(level)*(255-default_level)/(255); + else + mapped_level=0; + + // Refresh value of backlight level. + lcm_backlight_level_setting[0].para_list[0] = mapped_level; + + push_table(lcm_backlight_level_setting, sizeof(lcm_backlight_level_setting) / sizeof(struct LCM_setting_table), 1); +} +#endif + +static unsigned int lcm_esd_check(void) +{ +#ifndef BUILD_LK + if(lcm_esd_test) + { + lcm_esd_test = FALSE; + return TRUE; + } + + /// please notice: the max return packet size is 1 + /// if you want to change it, you can refer to the following marked code + /// but read_reg currently only support read no more than 4 bytes.... + /// if you need to read more, please let BinHan knows. + /* + unsigned int data_array[16]; + unsigned int max_return_size = 1; + + data_array[0]= 0x00003700 | (max_return_size << 16); + + dsi_set_cmdq(&data_array, 1, 1); + */ + + if(read_reg(0x0a) == 0x9c) + { + return FALSE; + } + else + { + return TRUE; + } +#endif +} + +static unsigned int lcm_esd_recover(void) +{ + unsigned char para = 0; + + SET_RESET_PIN(1); + SET_RESET_PIN(0); + MDELAY(1); + SET_RESET_PIN(1); + MDELAY(120); + push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1); + MDELAY(10); + push_table(lcm_sleep_out_setting, sizeof(lcm_sleep_out_setting) / sizeof(struct LCM_setting_table), 1); + MDELAY(10); + dsi_set_cmdq_V2(0x35, 1, ¶, 1); ///enable TE + MDELAY(10); + + return TRUE; +} + + +static unsigned int lcm_compare_id(void) +{ + int array[4]; + char buffer[5]; + char id_high=0; + char id_midd=0; + char id_low=0; + int id=0; + //Do reset here + SET_RESET_PIN(1); + SET_RESET_PIN(0); + MDELAY(25); + SET_RESET_PIN(1); + MDELAY(50); + + array[0]=0x00043902; + array[1]=0x018198FF; + dsi_set_cmdq(array, 3, 1); + MDELAY(10); + array[0]=0x00023700; + dsi_set_cmdq(array, 1, 1); + //read_reg_v2(0x04, buffer, 3); + + read_reg_v2(0x00, buffer,1); + id_high = buffer[0]; ///////////////////////0x98 + read_reg_v2(0x01, buffer,1); + id_midd = buffer[1]; ///////////////////////0x81 + read_reg_v2(0x02, buffer,1); + id_low = buffer[2]; ////////////////////////0x00 + // id = (id_midd << 8) | id_low; + +#ifdef BUILD_LK + printf("[erick-lk]%s, 9881 id = 0x%08x,0x%08x\n", __func__, id_high,id_midd); +#else + printk("[erick-k]%s, 9881 id = 0x%08x,0x%08x\n", __func__, id_high,id_midd); +#endif + if((0x98 == id_high)&&(0x81 == id_midd)) + { + return 1; + } + else + { + return 0; + } + //return (0x98 == id_high)?1:0; +} + +// --------------------------------------------------------------------------- +// Get LCM Driver Hooks +// --------------------------------------------------------------------------- +LCM_DRIVER ili9881_hds_hd720_5p0_h1_t592_otd = +{ + .name = "ili9881_hds_hd720_5p0_h1_t592_otd", + .set_util_funcs = lcm_set_util_funcs, + .get_params = lcm_get_params, + .init = lcm_init, + .suspend = lcm_suspend, + .resume = lcm_resume, + .compare_id = lcm_compare_id, +#if (LCM_DSI_CMD_MODE) + //.set_backlight = lcm_setbacklight, + //.esd_check = lcm_esd_check, + //.esd_recover = lcm_esd_recover, + .update = lcm_update, +#endif //wqtao +}; + diff --git a/drivers/misc/mediatek/lcm/mt65xx_lcm_list.c b/drivers/misc/mediatek/lcm/mt65xx_lcm_list.c index 409207576c0084752459eb29323f09eb605b621f..53b8779f047f3ba8dd07d870d581069586e946a9 100644 --- a/drivers/misc/mediatek/lcm/mt65xx_lcm_list.c +++ b/drivers/misc/mediatek/lcm/mt65xx_lcm_list.c @@ -86,6 +86,9 @@ LCM_DRIVER *lcm_driver_list[] = { #if defined(ILI9806E_HLT_HD720_DSI) &ili9806e_hlt_hd720_dsi, #endif +#if defined(ILI9881_HDS_HD720_5P0_H1_T592_OTD) + &ili9881_hds_hd720_5p0_h1_t592_otd, +#endif diff --git a/drivers/misc/mediatek/lcm/mt65xx_lcm_list.h b/drivers/misc/mediatek/lcm/mt65xx_lcm_list.h index cc93040e595cabe79433aa5f53eefc21b117e4b6..295a951179e6ac2f75ca3ea392e78fe50a0bdf29 100644 --- a/drivers/misc/mediatek/lcm/mt65xx_lcm_list.h +++ b/drivers/misc/mediatek/lcm/mt65xx_lcm_list.h @@ -31,6 +31,7 @@ extern LCM_DRIVER hct_otm1284a_dsi_vdo_hd_boe; extern LCM_DRIVER hct_otm1285a_dsi_vdo_hd_boe_3lane; extern LCM_DRIVER nt35521_dsi_6735_H; extern LCM_DRIVER ili9806e_hlt_hd720_dsi; +extern LCM_DRIVER ili9881_hds_hd720_5p0_h1_t592_otd; extern LCM_DRIVER otm1282a_hd720_dsi_vdo_60hz_lcm_drv; diff --git a/drivers/misc/mediatek/lcm/nt35695_fhd_dsi_cmd_truly_nt50358/Makefile b/drivers/misc/mediatek/lcm/nt35695_fhd_dsi_cmd_truly_nt50358/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..84cc431fea1edb6b08467f427763c7f58f066493 --- /dev/null +++ b/drivers/misc/mediatek/lcm/nt35695_fhd_dsi_cmd_truly_nt50358/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +# +# Makefile for misc devices that really don't fit anywhere else. +# + +obj-y += nt35695_fhd_dsi_cmd_truly_nt50358.o + +ccflags-$(CONFIG_MTK_LCM) += -I$(srctree)/drivers/misc/mediatek/lcm/inc diff --git a/drivers/misc/mediatek/lcm/nt35695_fhd_dsi_cmd_truly_nt50358/nt35695_fhd_dsi_cmd_truly_nt50358.c b/drivers/misc/mediatek/lcm/nt35695_fhd_dsi_cmd_truly_nt50358/nt35695_fhd_dsi_cmd_truly_nt50358.c new file mode 100644 index 0000000000000000000000000000000000000000..6d33398f43431d65a13bc544dbc7321bf70db5f7 --- /dev/null +++ b/drivers/misc/mediatek/lcm/nt35695_fhd_dsi_cmd_truly_nt50358/nt35695_fhd_dsi_cmd_truly_nt50358.c @@ -0,0 +1,1898 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "LCM" + +#ifndef BUILD_LK +#include +#include +#endif + +#include "lcm_drv.h" + + +#ifdef BUILD_LK +#include +#include +#include +#include +#include +#elif defined(BUILD_UBOOT) +#include +#else +/*#include */ +#ifdef CONFIG_MTK_LEGACY +#include +#endif +#endif +#ifdef CONFIG_MTK_LEGACY +#include +#endif +#ifndef CONFIG_FPGA_EARLY_PORTING +#if defined(CONFIG_MTK_LEGACY) +#include +#endif +#endif + +#ifdef BUILD_LK +#define LCM_LOGI(string, args...) dprintf(0, "[LK/"LOG_TAG"]"string, ##args) +#define LCM_LOGD(string, args...) dprintf(1, "[LK/"LOG_TAG"]"string, ##args) +#else +#define LCM_LOGI(fmt, args...) pr_debug("[KERNEL/"LOG_TAG"]"fmt, ##args) +#define LCM_LOGD(fmt, args...) pr_debug("[KERNEL/"LOG_TAG"]"fmt, ##args) +#endif + +#define LCM_ID_NT35695 (0xf5) + +static const unsigned int BL_MIN_LEVEL = 20; +static LCM_UTIL_FUNCS lcm_util; + + +#define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v))) +#define MDELAY(n) (lcm_util.mdelay(n)) +#define UDELAY(n) (lcm_util.udelay(n)) + +#define dsi_set_cmdq_V22(cmdq, cmd, count, ppara, force_update) \ + lcm_util.dsi_set_cmdq_V22(cmdq, cmd, count, ppara, force_update) +#define dsi_set_cmdq_V2(cmd, count, ppara, force_update) \ + lcm_util.dsi_set_cmdq_V2(cmd, count, ppara, force_update) +#define dsi_set_cmdq(pdata, queue_size, force_update) \ + lcm_util.dsi_set_cmdq(pdata, queue_size, force_update) +#define wrtie_cmd(cmd) lcm_util.dsi_write_cmd(cmd) +#define write_regs(addr, pdata, byte_nums) \ + lcm_util.dsi_write_regs(addr, pdata, byte_nums) +#define read_reg(cmd) \ + lcm_util.dsi_dcs_read_lcm_reg(cmd) +#define read_reg_v2(cmd, buffer, buffer_size) \ + lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size) + +#define set_gpio_lcd_enp(cmd) \ + lcm_util.set_gpio_lcd_enp_bias(cmd) +#ifndef BUILD_LK +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +/* #include */ +#include +#include +#include +#include + + +#ifndef CONFIG_FPGA_EARLY_PORTING + +#define TPS_I2C_BUSNUM I2C_I2C_LCD_BIAS_CHANNEL /* for I2C channel 0 */ +#define I2C_ID_NAME "tps65132" +#define TPS_ADDR 0x3E + +#if defined(CONFIG_MTK_LEGACY) +static struct i2c_board_info tps65132_board_info __initdata = { I2C_BOARD_INFO(I2C_ID_NAME, TPS_ADDR) }; +#endif +#if !defined(CONFIG_MTK_LEGACY) +static const struct of_device_id lcm_of_match[] = { + {.compatible = "mediatek,I2C_LCD_BIAS"}, + {}, +}; +#endif + +/*static struct i2c_client *tps65132_i2c_client;*/ +struct i2c_client *tps65132_i2c_client; + +/***************************************************************************** + * Function Prototype + *****************************************************************************/ +static int tps65132_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int tps65132_remove(struct i2c_client *client); +/***************************************************************************** + * Data Structure + *****************************************************************************/ + +struct tps65132_dev { + struct i2c_client *client; + +}; + +static const struct i2c_device_id tps65132_id[] = { + {I2C_ID_NAME, 0}, + {} +}; + +/* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) */ +/* static struct i2c_client_address_data addr_data = { .forces = forces,}; */ +/* #endif */ +static struct i2c_driver tps65132_iic_driver = { + .id_table = tps65132_id, + .probe = tps65132_probe, + .remove = tps65132_remove, + /* .detect = mt6605_detect, */ + .driver = { + .owner = THIS_MODULE, + .name = "tps65132", +#if !defined(CONFIG_MTK_LEGACY) + .of_match_table = lcm_of_match, +#endif + }, +}; + +static int tps65132_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + LCM_LOGI("tps65132_iic_probe\n"); + LCM_LOGI("TPS: info==>name=%s addr=0x%x\n", client->name, client->addr); + tps65132_i2c_client = client; + return 0; +} + +static int tps65132_remove(struct i2c_client *client) +{ + LCM_LOGI("tps65132_remove\n"); + tps65132_i2c_client = NULL; + i2c_unregister_device(client); + return 0; +} + +/*static int tps65132_write_bytes(unsigned char addr, unsigned char value)*/ +#if !defined(CONFIG_ARCH_MT6797) +int tps65132_write_bytes(unsigned char addr, unsigned char value) +{ + int ret = 0; + struct i2c_client *client = tps65132_i2c_client; + char write_data[2] = { 0 }; + write_data[0] = addr; + write_data[1] = value; + ret = i2c_master_send(client, write_data, 2); + if (ret < 0) + LCM_LOGI("tps65132 write data fail !!\n"); + return ret; +} +#endif + +static int __init tps65132_iic_init(void) +{ + LCM_LOGI("tps65132_iic_init\n"); +#if defined(CONFIG_MTK_LEGACY) + i2c_register_board_info(TPS_I2C_BUSNUM, &tps65132_board_info, 1); +#endif + LCM_LOGI("tps65132_iic_init2\n"); + i2c_add_driver(&tps65132_iic_driver); + LCM_LOGI("tps65132_iic_init success\n"); + return 0; +} + +static void __exit tps65132_iic_exit(void) +{ + LCM_LOGI("tps65132_iic_exit\n"); + i2c_del_driver(&tps65132_iic_driver); +} + + +module_init(tps65132_iic_init); +module_exit(tps65132_iic_exit); + +MODULE_AUTHOR("Mike Liu"); +MODULE_DESCRIPTION("MTK TPS65132 I2C Driver"); +MODULE_LICENSE("GPL"); +#endif +#endif + +/* static unsigned char lcd_id_pins_value = 0xFF; */ +static const unsigned char LCD_MODULE_ID = 0x01; +#define LCM_DSI_CMD_MODE 1 +#define FRAME_WIDTH (1080) +#define FRAME_HEIGHT (1920) + +#define LCM_PHYSICAL_WIDTH (74520) +#define LCM_PHYSICAL_HEIGHT (132480) + +#ifndef CONFIG_FPGA_EARLY_PORTING +#define GPIO_65132_EN GPIO_LCD_BIAS_ENP_PIN +#endif + +#define REGFLAG_DELAY 0xFFFC +#define REGFLAG_UDELAY 0xFFFB +#define REGFLAG_END_OF_TABLE 0xFFFD +#define REGFLAG_RESET_LOW 0xFFFE +#define REGFLAG_RESET_HIGH 0xFFFF + +static LCM_DSI_MODE_SWITCH_CMD lcm_switch_mode_cmd; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +struct LCM_setting_table { + unsigned int cmd; + unsigned char count; + unsigned char para_list[64]; +}; + +static struct LCM_setting_table lcm_suspend_setting[] = { + {0x28, 0, {} }, + {0x10, 0, {} }, + {REGFLAG_DELAY, 120, {} }, + {0x4F, 1, {0x01} }, + {REGFLAG_DELAY, 120, {} } +}; + +static struct LCM_setting_table init_setting[] = { + {0xFF, 1, {0x24} }, + {0xFB, 1, {0x01} }, + {0x2D, 1, {0x08} }, + {0xFF, 1, {0x24} }, /* Return To CMD1 */ + {0x6E, 1, {0x10} }, /* Return To CMD1 */ + {0xFB, 1, {0x01} }, /* Return To CMD1 */ + {0xFF, 1, {0x10} }, /* Return To CMD1 */ + + {0xFF, 1, {0x10} }, /* Return To CMD1 */ + {REGFLAG_UDELAY, 1, {} }, + {0xBB, 1, {0x10} },/*CMD MODE*/ + {0x3B, 5, {0x03, 0x0A, 0x0A, 0x0A, 0x0A} }, + {0x53, 1, {0x24} }, + {0x55, 1, {0x00} }, + {0x5E, 1, {0x00} }, + {0xFF, 1, {0x24} }, /* CMD2 Page4 Entrance */ + {REGFLAG_UDELAY, 1, {} }, + {0xFB, 1, {0x01} }, + {0x9D, 1, {0xB0} }, + {0x72, 1, {0x00} }, + {0x93, 1, {0x04} }, + {0x94, 1, {0x04} }, + {0x9B, 1, {0x0F} }, + {0x8A, 1, {0x33} }, + {0x86, 1, {0x1B} }, + {0x87, 1, {0x39} }, + {0x88, 1, {0x1B} }, + {0x89, 1, {0x39} }, + {0x8B, 1, {0xF4} }, + {0x8C, 1, {0x01} }, + /* Change for 695 RTN Start */ + {0x90, 1, {0x95} }, + {0x91, 1, {0xC8} }, + /* modify to 0x77 to see whether fps is higher */ + /* {0x92,1,{0x79}}, */ + {0x92, 1, {0x95} }, + {0x93, 1, {0x02} }, + {0x94, 1, {0x08} }, + {0x95, 1, {0x2B} }, + {0x96, 1, {0x95} }, + /* Change for 695 RTN End */ + {0xDE, 1, {0xFF} }, + {0xDF, 1, {0x82} }, + {0x00, 1, {0x0F} }, + {0x01, 1, {0x00} }, + {0x02, 1, {0x00} }, + {0x03, 1, {0x00} }, + {0x04, 1, {0x0B} }, + {0x05, 1, {0x0C} }, + {0x06, 1, {0x00} }, + {0x07, 1, {0x00} }, + {0x08, 1, {0x00} }, + {0x09, 1, {0x00} }, + {0x0A, 1, {0X03} }, + {0x0B, 1, {0X04} }, + {0x0C, 1, {0x01} }, + {0x0D, 1, {0x13} }, + {0x0E, 1, {0x15} }, + {0x0F, 1, {0x17} }, + {0x10, 1, {0x0F} }, + {0x11, 1, {0x00} }, + {0x12, 1, {0x00} }, + {0x13, 1, {0x00} }, + {0x14, 1, {0x0B} }, + {0x15, 1, {0x0C} }, + {0x16, 1, {0x00} }, + {0x17, 1, {0x00} }, + {0x18, 1, {0x00} }, + {0x19, 1, {0x00} }, + {0x1A, 1, {0x03} }, + {0x1B, 1, {0X04} }, + {0x1C, 1, {0x01} }, + {0x1D, 1, {0x13} }, + {0x1E, 1, {0x15} }, + {0x1F, 1, {0x17} }, + + {0x20, 1, {0x09} }, + {0x21, 1, {0x01} }, + {0x22, 1, {0x00} }, + {0x23, 1, {0x00} }, + {0x24, 1, {0x00} }, + {0x25, 1, {0x6D} }, + {0x26, 1, {0x00} }, + {0x27, 1, {0x00} }, + + {0x2F, 1, {0x02} }, + {0x30, 1, {0x04} }, + {0x31, 1, {0x49} }, + {0x32, 1, {0x23} }, + {0x33, 1, {0x01} }, + {0x34, 1, {0x00} }, + /* Change for 695 */ + {0x35, 1, {0x83} }, + {0x36, 1, {0x00} }, + {0x37, 1, {0x2D} }, + {0x38, 1, {0x08} }, + {0x39, 1, {0x00} }, + /* Change for 695 */ + {0x3A, 1, {0x83} }, + + {0x29, 1, {0x58} }, + {0x2A, 1, {0x16} }, + + {0x5B, 1, {0x00} }, + {0x5F, 1, {0x75} }, + {0x63, 1, {0x00} }, + {0x67, 1, {0x04} }, + + /* Change for 695 */ + {0x74, 1, {0x14} }, + /* Change for 695 */ + {0x75, 1, {0x1F} }, + {0x7B, 1, {0x80} }, + {0x7C, 1, {0xD8} }, + {0x7D, 1, {0x60} }, + /* Change for 695 */ + {0x7E, 1, {0x14} }, + /* Change for 695 */ + {0x7F, 1, {0x1F} }, + {0x80, 1, {0x00} }, + {0x81, 1, {0x06} }, + {0x82, 1, {0x03} }, + {0x83, 1, {0x00} }, + {0x84, 1, {0x03} }, + {0x85, 1, {0x07} }, + {0x74, 1, {0x10} }, + {0x75, 1, {0x19} }, + {0x76, 1, {0x06} }, + {0x77, 1, {0x03} }, + + {0x78, 1, {0x00} }, + {0x79, 1, {0x00} }, + {0x99, 1, {0x33} }, + {0x98, 1, {0x00} }, + {0xB3, 1, {0x28} }, + {0xB4, 1, {0x05} }, + {0xB5, 1, {0x10} }, + + {0xFF, 1, {0x20} }, /* Page 0,1,{ power-related setting */ + {REGFLAG_UDELAY, 1, {} }, + {0x00, 1, {0x01} }, + {0x01, 1, {0x55} }, + {0x02, 1, {0x45} }, + {0x03, 1, {0x55} }, + {0x05, 1, {0x50} }, + {0x06, 1, {0x9E} }, + {0x07, 1, {0xA8} }, + {0x08, 1, {0x0C} }, + {0x0B, 1, {0x96} }, + {0x0C, 1, {0x96} }, + {0x0E, 1, {0x00} }, + {0x0F, 1, {0x00} }, + {0x11, 1, {0x29} }, + {0x12, 1, {0x29} }, + {0x13, 1, {0x03} }, + {0x14, 1, {0x0A} }, + {0x15, 1, {0x99} }, + {0x16, 1, {0x99} }, + /* Change for 695 */ + {0x6D, 1, {0x68} }, + {0x58, 1, {0x05} }, + {0x59, 1, {0x05} }, + {0x5A, 1, {0x05} }, + {0x5B, 1, {0x05} }, + {0x5C, 1, {0x00} }, + {0x5D, 1, {0x00} }, + {0x5E, 1, {0x00} }, + {0x5F, 1, {0x00} }, + + {0x1B, 1, {0x39} }, + {0x1C, 1, {0x39} }, + {0x1D, 1, {0x47} }, + + {0xFF, 1, {0x20} }, /* Page 0,1,{ power-related setting */ + {REGFLAG_UDELAY, 1, {} }, + /* R+ ,1,{}}, */ + {0x75, 1, {0x00} }, + {0x76, 1, {0x00} }, + {0x77, 1, {0x00} }, + {0x78, 1, {0x3e} }, + {0x79, 1, {0x00} }, + {0x7A, 1, {0x6f} }, + {0x7B, 1, {0x00} }, + {0x7C, 1, {0x8f} }, + {0x7D, 1, {0x00} }, + {0x7E, 1, {0xa7} }, + {0x7F, 1, {0x00} }, + {0x80, 1, {0xbc} }, + {0x81, 1, {0x00} }, + {0x82, 1, {0xce} }, + {0x83, 1, {0x00} }, + {0x84, 1, {0xdd} }, + {0x85, 1, {0x00} }, + {0x86, 1, {0xec} }, + {0x87, 1, {0x01} }, + {0x88, 1, {0x1a} }, + {0x89, 1, {0x01} }, + {0x8A, 1, {0x3e} }, + {0x8B, 1, {0x01} }, + {0x8C, 1, {0x76} }, + {0x8D, 1, {0x01} }, + {0x8E, 1, {0xa3} }, + {0x8F, 1, {0x01} }, + {0x90, 1, {0xe9} }, + {0x91, 1, {0x02} }, + {0x92, 1, {0x20} }, + {0x93, 1, {0x02} }, + {0x94, 1, {0x22} }, + {0x95, 1, {0x02} }, + {0x96, 1, {0x56} }, + {0x97, 1, {0x02} }, + {0x98, 1, {0x8f} }, + {0x99, 1, {0x02} }, + {0x9A, 1, {0xb2} }, + {0x9B, 1, {0x02} }, + {0x9C, 1, {0xe2} }, + {0x9D, 1, {0x03} }, + {0x9E, 1, {0x02} }, + {0x9F, 1, {0x03} }, + {0xA0, 1, {0x2d} }, + {0xA2, 1, {0x03} }, + {0xA3, 1, {0x3a} }, + {0xA4, 1, {0x03} }, + {0xA5, 1, {0x48} }, + {0xA6, 1, {0x03} }, + {0xA7, 1, {0x58} }, + {0xA9, 1, {0x03} }, + {0xAA, 1, {0x6a} }, + {0xAB, 1, {0x03} }, + {0xAC, 1, {0x80} }, + {0xAD, 1, {0x03} }, + {0xAE, 1, {0x9d} }, + {0xAF, 1, {0x03} }, + {0xB0, 1, {0xb7} }, + {0xB1, 1, {0x03} }, + {0xB2, 1, {0xFF} }, + /* R- ,1,{}}, */ + {0xB3, 1, {0x00} }, + {0xB4, 1, {0x00} }, + {0xB5, 1, {0x00} }, + {0xB6, 1, {0x3e} }, + {0xB7, 1, {0x00} }, + {0xB8, 1, {0x6f} }, + {0xB9, 1, {0x00} }, + {0xBA, 1, {0x8f} }, + {0xBB, 1, {0x00} }, + {0xBC, 1, {0xa7} }, + {0xBD, 1, {0x00} }, + {0xBE, 1, {0xbc} }, + {0xBF, 1, {0x00} }, + {0xC0, 1, {0xce} }, + {0xC1, 1, {0x00} }, + {0xC2, 1, {0xdd} }, + {0xC3, 1, {0x00} }, + {0xC4, 1, {0xec} }, + {0xC5, 1, {0x01} }, + {0xC6, 1, {0x1a} }, + {0xC7, 1, {0x01} }, + {0xC8, 1, {0x3e} }, + {0xC9, 1, {0x01} }, + {0xCA, 1, {0x76} }, + {0xCB, 1, {0x01} }, + {0xCC, 1, {0xa3} }, + {0xCD, 1, {0x01} }, + {0xCE, 1, {0xe9} }, + {0xCF, 1, {0x02} }, + {0xD0, 1, {0x20} }, + {0xD1, 1, {0x02} }, + {0xD2, 1, {0x22} }, + {0xD3, 1, {0x02} }, + {0xD4, 1, {0x56} }, + {0xD5, 1, {0x02} }, + {0xD6, 1, {0x8f} }, + {0xD7, 1, {0x02} }, + {0xD8, 1, {0xb2} }, + {0xD9, 1, {0x02} }, + {0xDA, 1, {0xe2} }, + {0xDB, 1, {0x03} }, + {0xDC, 1, {0x02} }, + {0xDD, 1, {0x03} }, + {0xDE, 1, {0x2d} }, + {0xDF, 1, {0x03} }, + {0xE0, 1, {0x3a} }, + {0xE1, 1, {0x03} }, + {0xE2, 1, {0x48} }, + {0xE3, 1, {0x03} }, + {0xE4, 1, {0x58} }, + {0xE5, 1, {0x03} }, + {0xE6, 1, {0x6a} }, + {0xE7, 1, {0x03} }, + {0xE8, 1, {0x80} }, + {0xE9, 1, {0x03} }, + {0xEA, 1, {0x9d} }, + {0xEB, 1, {0x03} }, + {0xEC, 1, {0xb7} }, + {0xED, 1, {0x03} }, + {0xEE, 1, {0xFF} }, + /* G+ ,1,{}}, */ + {0xEF, 1, {0x00} }, + {0xF0, 1, {0x00} }, + {0xF1, 1, {0x00} }, + {0xF2, 1, {0x3e} }, + {0xF3, 1, {0x00} }, + {0xF4, 1, {0x6f} }, + {0xF5, 1, {0x00} }, + {0xF6, 1, {0x8f} }, + {0xF7, 1, {0x00} }, + {0xF8, 1, {0xa7} }, + {0xF9, 1, {0x00} }, + {0xFA, 1, {0xbc} }, + + {0xFF, 1, {0x21} }, /* Page 0,1,{ power-related setting */ + {REGFLAG_UDELAY, 1, {} }, + {0x00, 1, {0x00} }, + {0x01, 1, {0xce} }, + {0x02, 1, {0x00} }, + {0x03, 1, {0xdd} }, + {0x04, 1, {0x00} }, + {0x05, 1, {0xec} }, + {0x06, 1, {0x01} }, + {0x07, 1, {0x1a} }, + {0x08, 1, {0x01} }, + {0x09, 1, {0x3e} }, + {0x0A, 1, {0x01} }, + {0x0B, 1, {0x76} }, + {0x0C, 1, {0x01} }, + {0x0D, 1, {0xa3} }, + {0x0E, 1, {0x01} }, + {0x0F, 1, {0xe9} }, + {0x10, 1, {0x02} }, + {0x11, 1, {0x20} }, + {0x12, 1, {0x02} }, + {0x13, 1, {0x22} }, + {0x14, 1, {0x02} }, + {0x15, 1, {0x56} }, + {0x16, 1, {0x02} }, + {0x17, 1, {0x8f} }, + {0x18, 1, {0x02} }, + {0x19, 1, {0xb2} }, + {0x1A, 1, {0x02} }, + {0x1B, 1, {0xe2} }, + {0x1C, 1, {0x03} }, + {0x1D, 1, {0x02} }, + {0x1E, 1, {0x03} }, + {0x1F, 1, {0x2d} }, + {0x20, 1, {0x03} }, + {0x21, 1, {0x3a} }, + {0x22, 1, {0x03} }, + {0x23, 1, {0x48} }, + {0x24, 1, {0x03} }, + {0x25, 1, {0x58} }, + {0x26, 1, {0x03} }, + {0x27, 1, {0x6a} }, + {0x28, 1, {0x03} }, + {0x29, 1, {0x80} }, + {0x2A, 1, {0x03} }, + {0x2B, 1, {0x9d} }, + {0x2D, 1, {0x03} }, + {0x2F, 1, {0xb7} }, + {0x30, 1, {0x03} }, + {0x31, 1, {0xFF} }, + /* G- ,1,{}}, */ + {0x32, 1, {0x00} }, + {0x33, 1, {0x00} }, + {0x34, 1, {0x00} }, + {0x35, 1, {0x3e} }, + {0x36, 1, {0x00} }, + {0x37, 1, {0x6f} }, + {0x38, 1, {0x00} }, + {0x39, 1, {0x8f} }, + {0x3A, 1, {0x00} }, + {0x3B, 1, {0xa7} }, + {0x3D, 1, {0x00} }, + {0x3F, 1, {0xbc} }, + {0x40, 1, {0x00} }, + {0x41, 1, {0xce} }, + {0x42, 1, {0x00} }, + {0x43, 1, {0xdd} }, + {0x44, 1, {0x00} }, + {0x45, 1, {0xec} }, + {0x46, 1, {0x01} }, + {0x47, 1, {0x1a} }, + {0x48, 1, {0x01} }, + {0x49, 1, {0x3e} }, + {0x4A, 1, {0x01} }, + {0x4B, 1, {0x76} }, + {0x4C, 1, {0x01} }, + {0x4D, 1, {0xa3} }, + {0x4E, 1, {0x01} }, + {0x4F, 1, {0xe9} }, + {0x50, 1, {0x02} }, + {0x51, 1, {0x20} }, + {0x52, 1, {0x02} }, + {0x53, 1, {0x22} }, + {0x54, 1, {0x02} }, + {0x55, 1, {0x56} }, + {0x56, 1, {0x02} }, + {0x58, 1, {0x8f} }, + {0x59, 1, {0x02} }, + {0x5A, 1, {0xb2} }, + {0x5B, 1, {0x02} }, + {0x5C, 1, {0xe2} }, + {0x5D, 1, {0x03} }, + {0x5E, 1, {0x02} }, + {0x5F, 1, {0x03} }, + {0x60, 1, {0x2d} }, + {0x61, 1, {0x03} }, + {0x62, 1, {0x3a} }, + {0x63, 1, {0x03} }, + {0x64, 1, {0x48} }, + {0x65, 1, {0x03} }, + {0x66, 1, {0x58} }, + {0x67, 1, {0x03} }, + {0x68, 1, {0x6a} }, + {0x69, 1, {0x03} }, + {0x6A, 1, {0x80} }, + {0x6B, 1, {0x03} }, + {0x6C, 1, {0x9d} }, + {0x6D, 1, {0x03} }, + {0x6E, 1, {0xb7} }, + {0x6F, 1, {0x03} }, + {0x70, 1, {0xFF} }, + /* B+ ,1,{}}, */ + {0x71, 1, {0x00} }, + {0x72, 1, {0x00} }, + {0x73, 1, {0x00} }, + {0x74, 1, {0x3e} }, + {0x75, 1, {0x00} }, + {0x76, 1, {0x6f} }, + {0x77, 1, {0x00} }, + {0x78, 1, {0x8f} }, + {0x79, 1, {0x00} }, + {0x7A, 1, {0xa7} }, + {0x7B, 1, {0x00} }, + {0x7C, 1, {0xbc} }, + {0x7D, 1, {0x00} }, + {0x7E, 1, {0xce} }, + {0x7F, 1, {0x00} }, + {0x80, 1, {0xdd} }, + {0x81, 1, {0x00} }, + {0x82, 1, {0xec} }, + {0x83, 1, {0x01} }, + {0x84, 1, {0x1a} }, + {0x85, 1, {0x01} }, + {0x86, 1, {0x3e} }, + {0x87, 1, {0x01} }, + {0x88, 1, {0x76} }, + {0x89, 1, {0x01} }, + {0x8A, 1, {0xa3} }, + {0x8B, 1, {0x01} }, + {0x8C, 1, {0xe9} }, + {0x8D, 1, {0x02} }, + {0x8E, 1, {0x20} }, + {0x8F, 1, {0x02} }, + {0x90, 1, {0x22} }, + {0x91, 1, {0x02} }, + {0x92, 1, {0x56} }, + {0x93, 1, {0x02} }, + {0x94, 1, {0x8f} }, + {0x95, 1, {0x02} }, + {0x96, 1, {0xb2} }, + {0x97, 1, {0x02} }, + {0x98, 1, {0xe2} }, + {0x99, 1, {0x03} }, + {0x9A, 1, {0x02} }, + {0x9B, 1, {0x03} }, + {0x9C, 1, {0x2d} }, + {0x9D, 1, {0x03} }, + {0x9E, 1, {0x3a} }, + {0x9F, 1, {0x03} }, + {0xA0, 1, {0x48} }, + {0xA2, 1, {0x03} }, + {0xA3, 1, {0x58} }, + {0xA4, 1, {0x03} }, + {0xA5, 1, {0x6a} }, + {0xA6, 1, {0x03} }, + {0xA7, 1, {0x80} }, + {0xA9, 1, {0x03} }, + {0xAA, 1, {0x9d} }, + {0xAB, 1, {0x03} }, + {0xAC, 1, {0xb7} }, + {0xAD, 1, {0x03} }, + {0xAE, 1, {0xFF} }, + /* B- ,1,{}}, */ + {0xAF, 1, {0x00} }, + {0xB0, 1, {0x00} }, + {0xB1, 1, {0x00} }, + {0xB2, 1, {0x3e} }, + {0xB3, 1, {0x00} }, + {0xB4, 1, {0x6f} }, + {0xB5, 1, {0x00} }, + {0xB6, 1, {0x8f} }, + {0xB7, 1, {0x00} }, + {0xB8, 1, {0xa7} }, + {0xB9, 1, {0x00} }, + {0xBA, 1, {0xbc} }, + {0xBB, 1, {0x00} }, + {0xBC, 1, {0xce} }, + {0xBD, 1, {0x00} }, + {0xBE, 1, {0xdd} }, + {0xBF, 1, {0x00} }, + {0xC0, 1, {0xec} }, + {0xC1, 1, {0x01} }, + {0xC2, 1, {0x1a} }, + {0xC3, 1, {0x01} }, + {0xC4, 1, {0x3e} }, + {0xC5, 1, {0x01} }, + {0xC6, 1, {0x76} }, + {0xC7, 1, {0x01} }, + {0xC8, 1, {0xa3} }, + {0xC9, 1, {0x01} }, + {0xCA, 1, {0xe9} }, + {0xCB, 1, {0x02} }, + {0xCC, 1, {0x20} }, + {0xCD, 1, {0x02} }, + {0xCE, 1, {0x22} }, + {0xCF, 1, {0x02} }, + {0xD0, 1, {0x56} }, + {0xD1, 1, {0x02} }, + {0xD2, 1, {0x8f} }, + {0xD3, 1, {0x02} }, + {0xD4, 1, {0xb2} }, + {0xD5, 1, {0x02} }, + {0xD6, 1, {0xe2} }, + {0xD7, 1, {0x03} }, + {0xD8, 1, {0x02} }, + {0xD9, 1, {0x03} }, + {0xDA, 1, {0x2d} }, + {0xDB, 1, {0x03} }, + {0xDC, 1, {0x3a} }, + {0xDD, 1, {0x03} }, + {0xDE, 1, {0x48} }, + {0xDF, 1, {0x03} }, + {0xE0, 1, {0x58} }, + {0xE1, 1, {0x03} }, + {0xE2, 1, {0x6a} }, + {0xE3, 1, {0x03} }, + {0xE4, 1, {0x80} }, + {0xE5, 1, {0x03} }, + {0xE6, 1, {0x9d} }, + {0xE7, 1, {0x03} }, + {0xE8, 1, {0xb7} }, + {0xE9, 1, {0x03} }, + {0xEA, 1, {0xFF} }, + + {0xFF, 1, {0x21} }, /* Page ,1,{ Gamma Default Update */ + {REGFLAG_UDELAY, 1, {} }, + {0xEB, 1, {0x30} }, + {0xEC, 1, {0x17} }, + {0xED, 1, {0x20} }, + {0xEE, 1, {0x0F} }, + {0xEF, 1, {0x1F} }, + {0xF0, 1, {0x0F} }, + {0xF1, 1, {0x0F} }, + {0xF2, 1, {0x07} }, + + {0xFF, 1, {0x23} }, /* CMD2 Page 3 Entrance */ + {REGFLAG_UDELAY, 1, {} }, + {0x08, 1, {0x04} }, + + /* image.first */ + {0xFF, 1, {0x10} }, /* Return To CMD1 */ + {REGFLAG_UDELAY, 1, {} }, + {0x35, 1, {0x00} }, + {0x44, 2, {0x05, 0x00} }, + {0x11, 0, {} }, + {REGFLAG_DELAY, 120, {} }, + {0x29, 0, {} }, + /* {0x51,1,{0xFF}},//writedisplay brightness */ +}; + +static struct LCM_setting_table init_setting2[] = { + {0xFF, 1, {0x24} }, + {0xFB, 1, {0x01} }, + {0x2D, 1, {0x08} }, + {0xFF, 1, {0x24} }, /* Return To CMD1 */ + {0x6E, 1, {0x10} }, /* Return To CMD1 */ + {0xFB, 1, {0x01} }, /* Return To CMD1 */ + {0xFF, 1, {0x10} }, /* Return To CMD1 */ + + {0xFF, 1, {0x10} }, /* Return To CMD1 */ + {REGFLAG_UDELAY, 1, {} }, + {0xBB, 1, {0x03} },/*VDO MODE*/ + {0x3B, 5, {0x03, 0x0A, 0x0A, 0x0A, 0x0A} }, + {0x53, 1, {0x24} }, + {0x55, 1, {0x00} }, + {0x5E, 1, {0x00} }, + {0xFF, 1, {0x24} }, /* CMD2 Page4 Entrance */ + {REGFLAG_UDELAY, 1, {} }, + {0xFB, 1, {0x01} }, + {0x9D, 1, {0xB0} }, + {0x72, 1, {0x00} }, + {0x93, 1, {0x04} }, + {0x94, 1, {0x04} }, + {0x9B, 1, {0x0F} }, + {0x8A, 1, {0x33} }, + {0x86, 1, {0x1B} }, + {0x87, 1, {0x39} }, + {0x88, 1, {0x1B} }, + {0x89, 1, {0x39} }, + {0x8B, 1, {0xF4} }, + {0x8C, 1, {0x01} }, + /* Change for 695 RTN Start */ + {0x90, 1, {0x95} }, + {0x91, 1, {0xC8} }, + /* modify to 0x77 to see whether fps is higher */ + /* {0x92,1,{0x79}}, */ + {0x92, 1, {0x95} }, + {0x93, 1, {0x02} }, + {0x94, 1, {0x08} }, + {0x95, 1, {0x2B} }, + {0x96, 1, {0x95} }, + /* Change for 695 RTN End */ + {0xDE, 1, {0xFF} }, + {0xDF, 1, {0x82} }, + {0x00, 1, {0x0F} }, + {0x01, 1, {0x00} }, + {0x02, 1, {0x00} }, + {0x03, 1, {0x00} }, + {0x04, 1, {0x0B} }, + {0x05, 1, {0x0C} }, + {0x06, 1, {0x00} }, + {0x07, 1, {0x00} }, + {0x08, 1, {0x00} }, + {0x09, 1, {0x00} }, + {0x0A, 1, {0X03} }, + {0x0B, 1, {0X04} }, + {0x0C, 1, {0x01} }, + {0x0D, 1, {0x13} }, + {0x0E, 1, {0x15} }, + {0x0F, 1, {0x17} }, + {0x10, 1, {0x0F} }, + {0x11, 1, {0x00} }, + {0x12, 1, {0x00} }, + {0x13, 1, {0x00} }, + {0x14, 1, {0x0B} }, + {0x15, 1, {0x0C} }, + {0x16, 1, {0x00} }, + {0x17, 1, {0x00} }, + {0x18, 1, {0x00} }, + {0x19, 1, {0x00} }, + {0x1A, 1, {0x03} }, + {0x1B, 1, {0X04} }, + {0x1C, 1, {0x01} }, + {0x1D, 1, {0x13} }, + {0x1E, 1, {0x15} }, + {0x1F, 1, {0x17} }, + + {0x20, 1, {0x09} }, + {0x21, 1, {0x01} }, + {0x22, 1, {0x00} }, + {0x23, 1, {0x00} }, + {0x24, 1, {0x00} }, + {0x25, 1, {0x6D} }, + {0x26, 1, {0x00} }, + {0x27, 1, {0x00} }, + + {0x2F, 1, {0x02} }, + {0x30, 1, {0x04} }, + {0x31, 1, {0x49} }, + {0x32, 1, {0x23} }, + {0x33, 1, {0x01} }, + {0x34, 1, {0x00} }, + /* Change for 695 */ + {0x35, 1, {0x83} }, + {0x36, 1, {0x00} }, + {0x37, 1, {0x2D} }, + {0x38, 1, {0x08} }, + {0x39, 1, {0x00} }, + /* Change for 695 */ + {0x3A, 1, {0x83} }, + + {0x29, 1, {0x58} }, + {0x2A, 1, {0x16} }, + + {0x5B, 1, {0x00} }, + {0x5F, 1, {0x75} }, + {0x63, 1, {0x00} }, + {0x67, 1, {0x04} }, + + /* Change for 695 */ + {0x74, 1, {0x14} }, + /* Change for 695 */ + {0x75, 1, {0x1F} }, + {0x7B, 1, {0x80} }, + {0x7C, 1, {0xD8} }, + {0x7D, 1, {0x60} }, + /* Change for 695 */ + {0x7E, 1, {0x14} }, + /* Change for 695 */ + {0x7F, 1, {0x1F} }, + {0x80, 1, {0x00} }, + {0x81, 1, {0x06} }, + {0x82, 1, {0x03} }, + {0x83, 1, {0x00} }, + {0x84, 1, {0x03} }, + {0x85, 1, {0x07} }, + {0x74, 1, {0x10} }, + {0x75, 1, {0x19} }, + {0x76, 1, {0x06} }, + {0x77, 1, {0x03} }, + + {0x78, 1, {0x00} }, + {0x79, 1, {0x00} }, + {0x99, 1, {0x33} }, + {0x98, 1, {0x00} }, + {0xB3, 1, {0x28} }, + {0xB4, 1, {0x05} }, + {0xB5, 1, {0x10} }, + + {0xFF, 1, {0x20} }, /* Page 0,1,{ power-related setting */ + {REGFLAG_UDELAY, 1, {} }, + {0x00, 1, {0x01} }, + {0x01, 1, {0x55} }, + {0x02, 1, {0x45} }, + {0x03, 1, {0x55} }, + {0x05, 1, {0x50} }, + {0x06, 1, {0x9E} }, + {0x07, 1, {0xA8} }, + {0x08, 1, {0x0C} }, + {0x0B, 1, {0x96} }, + {0x0C, 1, {0x96} }, + {0x0E, 1, {0x00} }, + {0x0F, 1, {0x00} }, + {0x11, 1, {0x29} }, + {0x12, 1, {0x29} }, + {0x13, 1, {0x03} }, + {0x14, 1, {0x0A} }, + {0x15, 1, {0x99} }, + {0x16, 1, {0x99} }, + /* Change for 695 */ + {0x6D, 1, {0x68} }, + {0x58, 1, {0x05} }, + {0x59, 1, {0x05} }, + {0x5A, 1, {0x05} }, + {0x5B, 1, {0x05} }, + {0x5C, 1, {0x00} }, + {0x5D, 1, {0x00} }, + {0x5E, 1, {0x00} }, + {0x5F, 1, {0x00} }, + + {0x1B, 1, {0x39} }, + {0x1C, 1, {0x39} }, + {0x1D, 1, {0x47} }, + + {0xFF, 1, {0x20} }, /* Page 0,1,{ power-related setting */ + {REGFLAG_UDELAY, 1, {} }, + /* R+ ,1,{}}, */ + {0x75, 1, {0x00} }, + {0x76, 1, {0x00} }, + {0x77, 1, {0x00} }, + {0x78, 1, {0x3e} }, + {0x79, 1, {0x00} }, + {0x7A, 1, {0x6f} }, + {0x7B, 1, {0x00} }, + {0x7C, 1, {0x8f} }, + {0x7D, 1, {0x00} }, + {0x7E, 1, {0xa7} }, + {0x7F, 1, {0x00} }, + {0x80, 1, {0xbc} }, + {0x81, 1, {0x00} }, + {0x82, 1, {0xce} }, + {0x83, 1, {0x00} }, + {0x84, 1, {0xdd} }, + {0x85, 1, {0x00} }, + {0x86, 1, {0xec} }, + {0x87, 1, {0x01} }, + {0x88, 1, {0x1a} }, + {0x89, 1, {0x01} }, + {0x8A, 1, {0x3e} }, + {0x8B, 1, {0x01} }, + {0x8C, 1, {0x76} }, + {0x8D, 1, {0x01} }, + {0x8E, 1, {0xa3} }, + {0x8F, 1, {0x01} }, + {0x90, 1, {0xe9} }, + {0x91, 1, {0x02} }, + {0x92, 1, {0x20} }, + {0x93, 1, {0x02} }, + {0x94, 1, {0x22} }, + {0x95, 1, {0x02} }, + {0x96, 1, {0x56} }, + {0x97, 1, {0x02} }, + {0x98, 1, {0x8f} }, + {0x99, 1, {0x02} }, + {0x9A, 1, {0xb2} }, + {0x9B, 1, {0x02} }, + {0x9C, 1, {0xe2} }, + {0x9D, 1, {0x03} }, + {0x9E, 1, {0x02} }, + {0x9F, 1, {0x03} }, + {0xA0, 1, {0x2d} }, + {0xA2, 1, {0x03} }, + {0xA3, 1, {0x3a} }, + {0xA4, 1, {0x03} }, + {0xA5, 1, {0x48} }, + {0xA6, 1, {0x03} }, + {0xA7, 1, {0x58} }, + {0xA9, 1, {0x03} }, + {0xAA, 1, {0x6a} }, + {0xAB, 1, {0x03} }, + {0xAC, 1, {0x80} }, + {0xAD, 1, {0x03} }, + {0xAE, 1, {0x9d} }, + {0xAF, 1, {0x03} }, + {0xB0, 1, {0xb7} }, + {0xB1, 1, {0x03} }, + {0xB2, 1, {0xFF} }, + /* R- ,1,{}}, */ + {0xB3, 1, {0x00} }, + {0xB4, 1, {0x00} }, + {0xB5, 1, {0x00} }, + {0xB6, 1, {0x3e} }, + {0xB7, 1, {0x00} }, + {0xB8, 1, {0x6f} }, + {0xB9, 1, {0x00} }, + {0xBA, 1, {0x8f} }, + {0xBB, 1, {0x00} }, + {0xBC, 1, {0xa7} }, + {0xBD, 1, {0x00} }, + {0xBE, 1, {0xbc} }, + {0xBF, 1, {0x00} }, + {0xC0, 1, {0xce} }, + {0xC1, 1, {0x00} }, + {0xC2, 1, {0xdd} }, + {0xC3, 1, {0x00} }, + {0xC4, 1, {0xec} }, + {0xC5, 1, {0x01} }, + {0xC6, 1, {0x1a} }, + {0xC7, 1, {0x01} }, + {0xC8, 1, {0x3e} }, + {0xC9, 1, {0x01} }, + {0xCA, 1, {0x76} }, + {0xCB, 1, {0x01} }, + {0xCC, 1, {0xa3} }, + {0xCD, 1, {0x01} }, + {0xCE, 1, {0xe9} }, + {0xCF, 1, {0x02} }, + {0xD0, 1, {0x20} }, + {0xD1, 1, {0x02} }, + {0xD2, 1, {0x22} }, + {0xD3, 1, {0x02} }, + {0xD4, 1, {0x56} }, + {0xD5, 1, {0x02} }, + {0xD6, 1, {0x8f} }, + {0xD7, 1, {0x02} }, + {0xD8, 1, {0xb2} }, + {0xD9, 1, {0x02} }, + {0xDA, 1, {0xe2} }, + {0xDB, 1, {0x03} }, + {0xDC, 1, {0x02} }, + {0xDD, 1, {0x03} }, + {0xDE, 1, {0x2d} }, + {0xDF, 1, {0x03} }, + {0xE0, 1, {0x3a} }, + {0xE1, 1, {0x03} }, + {0xE2, 1, {0x48} }, + {0xE3, 1, {0x03} }, + {0xE4, 1, {0x58} }, + {0xE5, 1, {0x03} }, + {0xE6, 1, {0x6a} }, + {0xE7, 1, {0x03} }, + {0xE8, 1, {0x80} }, + {0xE9, 1, {0x03} }, + {0xEA, 1, {0x9d} }, + {0xEB, 1, {0x03} }, + {0xEC, 1, {0xb7} }, + {0xED, 1, {0x03} }, + {0xEE, 1, {0xFF} }, + /* G+ ,1,{}}, */ + {0xEF, 1, {0x00} }, + {0xF0, 1, {0x00} }, + {0xF1, 1, {0x00} }, + {0xF2, 1, {0x3e} }, + {0xF3, 1, {0x00} }, + {0xF4, 1, {0x6f} }, + {0xF5, 1, {0x00} }, + {0xF6, 1, {0x8f} }, + {0xF7, 1, {0x00} }, + {0xF8, 1, {0xa7} }, + {0xF9, 1, {0x00} }, + {0xFA, 1, {0xbc} }, + + {0xFF, 1, {0x21} }, /* Page 0,1,{ power-related setting */ + {REGFLAG_UDELAY, 1, {} }, + {0x00, 1, {0x00} }, + {0x01, 1, {0xce} }, + {0x02, 1, {0x00} }, + {0x03, 1, {0xdd} }, + {0x04, 1, {0x00} }, + {0x05, 1, {0xec} }, + {0x06, 1, {0x01} }, + {0x07, 1, {0x1a} }, + {0x08, 1, {0x01} }, + {0x09, 1, {0x3e} }, + {0x0A, 1, {0x01} }, + {0x0B, 1, {0x76} }, + {0x0C, 1, {0x01} }, + {0x0D, 1, {0xa3} }, + {0x0E, 1, {0x01} }, + {0x0F, 1, {0xe9} }, + {0x10, 1, {0x02} }, + {0x11, 1, {0x20} }, + {0x12, 1, {0x02} }, + {0x13, 1, {0x22} }, + {0x14, 1, {0x02} }, + {0x15, 1, {0x56} }, + {0x16, 1, {0x02} }, + {0x17, 1, {0x8f} }, + {0x18, 1, {0x02} }, + {0x19, 1, {0xb2} }, + {0x1A, 1, {0x02} }, + {0x1B, 1, {0xe2} }, + {0x1C, 1, {0x03} }, + {0x1D, 1, {0x02} }, + {0x1E, 1, {0x03} }, + {0x1F, 1, {0x2d} }, + {0x20, 1, {0x03} }, + {0x21, 1, {0x3a} }, + {0x22, 1, {0x03} }, + {0x23, 1, {0x48} }, + {0x24, 1, {0x03} }, + {0x25, 1, {0x58} }, + {0x26, 1, {0x03} }, + {0x27, 1, {0x6a} }, + {0x28, 1, {0x03} }, + {0x29, 1, {0x80} }, + {0x2A, 1, {0x03} }, + {0x2B, 1, {0x9d} }, + {0x2D, 1, {0x03} }, + {0x2F, 1, {0xb7} }, + {0x30, 1, {0x03} }, + {0x31, 1, {0xFF} }, + /* G- ,1,{}}, */ + {0x32, 1, {0x00} }, + {0x33, 1, {0x00} }, + {0x34, 1, {0x00} }, + {0x35, 1, {0x3e} }, + {0x36, 1, {0x00} }, + {0x37, 1, {0x6f} }, + {0x38, 1, {0x00} }, + {0x39, 1, {0x8f} }, + {0x3A, 1, {0x00} }, + {0x3B, 1, {0xa7} }, + {0x3D, 1, {0x00} }, + {0x3F, 1, {0xbc} }, + {0x40, 1, {0x00} }, + {0x41, 1, {0xce} }, + {0x42, 1, {0x00} }, + {0x43, 1, {0xdd} }, + {0x44, 1, {0x00} }, + {0x45, 1, {0xec} }, + {0x46, 1, {0x01} }, + {0x47, 1, {0x1a} }, + {0x48, 1, {0x01} }, + {0x49, 1, {0x3e} }, + {0x4A, 1, {0x01} }, + {0x4B, 1, {0x76} }, + {0x4C, 1, {0x01} }, + {0x4D, 1, {0xa3} }, + {0x4E, 1, {0x01} }, + {0x4F, 1, {0xe9} }, + {0x50, 1, {0x02} }, + {0x51, 1, {0x20} }, + {0x52, 1, {0x02} }, + {0x53, 1, {0x22} }, + {0x54, 1, {0x02} }, + {0x55, 1, {0x56} }, + {0x56, 1, {0x02} }, + {0x58, 1, {0x8f} }, + {0x59, 1, {0x02} }, + {0x5A, 1, {0xb2} }, + {0x5B, 1, {0x02} }, + {0x5C, 1, {0xe2} }, + {0x5D, 1, {0x03} }, + {0x5E, 1, {0x02} }, + {0x5F, 1, {0x03} }, + {0x60, 1, {0x2d} }, + {0x61, 1, {0x03} }, + {0x62, 1, {0x3a} }, + {0x63, 1, {0x03} }, + {0x64, 1, {0x48} }, + {0x65, 1, {0x03} }, + {0x66, 1, {0x58} }, + {0x67, 1, {0x03} }, + {0x68, 1, {0x6a} }, + {0x69, 1, {0x03} }, + {0x6A, 1, {0x80} }, + {0x6B, 1, {0x03} }, + {0x6C, 1, {0x9d} }, + {0x6D, 1, {0x03} }, + {0x6E, 1, {0xb7} }, + {0x6F, 1, {0x03} }, + {0x70, 1, {0xFF} }, + /* B+ ,1,{}}, */ + {0x71, 1, {0x00} }, + {0x72, 1, {0x00} }, + {0x73, 1, {0x00} }, + {0x74, 1, {0x3e} }, + {0x75, 1, {0x00} }, + {0x76, 1, {0x6f} }, + {0x77, 1, {0x00} }, + {0x78, 1, {0x8f} }, + {0x79, 1, {0x00} }, + {0x7A, 1, {0xa7} }, + {0x7B, 1, {0x00} }, + {0x7C, 1, {0xbc} }, + {0x7D, 1, {0x00} }, + {0x7E, 1, {0xce} }, + {0x7F, 1, {0x00} }, + {0x80, 1, {0xdd} }, + {0x81, 1, {0x00} }, + {0x82, 1, {0xec} }, + {0x83, 1, {0x01} }, + {0x84, 1, {0x1a} }, + {0x85, 1, {0x01} }, + {0x86, 1, {0x3e} }, + {0x87, 1, {0x01} }, + {0x88, 1, {0x76} }, + {0x89, 1, {0x01} }, + {0x8A, 1, {0xa3} }, + {0x8B, 1, {0x01} }, + {0x8C, 1, {0xe9} }, + {0x8D, 1, {0x02} }, + {0x8E, 1, {0x20} }, + {0x8F, 1, {0x02} }, + {0x90, 1, {0x22} }, + {0x91, 1, {0x02} }, + {0x92, 1, {0x56} }, + {0x93, 1, {0x02} }, + {0x94, 1, {0x8f} }, + {0x95, 1, {0x02} }, + {0x96, 1, {0xb2} }, + {0x97, 1, {0x02} }, + {0x98, 1, {0xe2} }, + {0x99, 1, {0x03} }, + {0x9A, 1, {0x02} }, + {0x9B, 1, {0x03} }, + {0x9C, 1, {0x2d} }, + {0x9D, 1, {0x03} }, + {0x9E, 1, {0x3a} }, + {0x9F, 1, {0x03} }, + {0xA0, 1, {0x48} }, + {0xA2, 1, {0x03} }, + {0xA3, 1, {0x58} }, + {0xA4, 1, {0x03} }, + {0xA5, 1, {0x6a} }, + {0xA6, 1, {0x03} }, + {0xA7, 1, {0x80} }, + {0xA9, 1, {0x03} }, + {0xAA, 1, {0x9d} }, + {0xAB, 1, {0x03} }, + {0xAC, 1, {0xb7} }, + {0xAD, 1, {0x03} }, + {0xAE, 1, {0xFF} }, + /* B- ,1,{}}, */ + {0xAF, 1, {0x00} }, + {0xB0, 1, {0x00} }, + {0xB1, 1, {0x00} }, + {0xB2, 1, {0x3e} }, + {0xB3, 1, {0x00} }, + {0xB4, 1, {0x6f} }, + {0xB5, 1, {0x00} }, + {0xB6, 1, {0x8f} }, + {0xB7, 1, {0x00} }, + {0xB8, 1, {0xa7} }, + {0xB9, 1, {0x00} }, + {0xBA, 1, {0xbc} }, + {0xBB, 1, {0x00} }, + {0xBC, 1, {0xce} }, + {0xBD, 1, {0x00} }, + {0xBE, 1, {0xdd} }, + {0xBF, 1, {0x00} }, + {0xC0, 1, {0xec} }, + {0xC1, 1, {0x01} }, + {0xC2, 1, {0x1a} }, + {0xC3, 1, {0x01} }, + {0xC4, 1, {0x3e} }, + {0xC5, 1, {0x01} }, + {0xC6, 1, {0x76} }, + {0xC7, 1, {0x01} }, + {0xC8, 1, {0xa3} }, + {0xC9, 1, {0x01} }, + {0xCA, 1, {0xe9} }, + {0xCB, 1, {0x02} }, + {0xCC, 1, {0x20} }, + {0xCD, 1, {0x02} }, + {0xCE, 1, {0x22} }, + {0xCF, 1, {0x02} }, + {0xD0, 1, {0x56} }, + {0xD1, 1, {0x02} }, + {0xD2, 1, {0x8f} }, + {0xD3, 1, {0x02} }, + {0xD4, 1, {0xb2} }, + {0xD5, 1, {0x02} }, + {0xD6, 1, {0xe2} }, + {0xD7, 1, {0x03} }, + {0xD8, 1, {0x02} }, + {0xD9, 1, {0x03} }, + {0xDA, 1, {0x2d} }, + {0xDB, 1, {0x03} }, + {0xDC, 1, {0x3a} }, + {0xDD, 1, {0x03} }, + {0xDE, 1, {0x48} }, + {0xDF, 1, {0x03} }, + {0xE0, 1, {0x58} }, + {0xE1, 1, {0x03} }, + {0xE2, 1, {0x6a} }, + {0xE3, 1, {0x03} }, + {0xE4, 1, {0x80} }, + {0xE5, 1, {0x03} }, + {0xE6, 1, {0x9d} }, + {0xE7, 1, {0x03} }, + {0xE8, 1, {0xb7} }, + {0xE9, 1, {0x03} }, + {0xEA, 1, {0xFF} }, + + {0xFF, 1, {0x21} }, /* Page ,1,{ Gamma Default Update */ + {REGFLAG_UDELAY, 1, {} }, + {0xEB, 1, {0x30} }, + {0xEC, 1, {0x17} }, + {0xED, 1, {0x20} }, + {0xEE, 1, {0x0F} }, + {0xEF, 1, {0x1F} }, + {0xF0, 1, {0x0F} }, + {0xF1, 1, {0x0F} }, + {0xF2, 1, {0x07} }, + + {0xFF, 1, {0x23} }, /* CMD2 Page 3 Entrance */ + {REGFLAG_UDELAY, 1, {} }, + {0x08, 1, {0x04} }, + + /* image.first */ + {0xFF, 1, {0x10} }, /* Return To CMD1 */ + {REGFLAG_UDELAY, 1, {} }, + {0x35, 1, {0x00} }, + {0x44, 2, {0x05, 0x00} }, + {0x11, 0, {} }, + {REGFLAG_DELAY, 120, {} }, + {0x29, 0, {} }, + /* {0x51,1,{0xFF}},//writedisplay brightness */ +}; + +#if 0 +static struct LCM_setting_table lcm_set_window[] = { + {0x2A, 4, {0x00, 0x00, (FRAME_WIDTH >> 8), (FRAME_WIDTH & 0xFF)} }, + {0x2B, 4, {0x00, 0x00, (FRAME_HEIGHT >> 8), (FRAME_HEIGHT & 0xFF)} }, + {REGFLAG_END_OF_TABLE, 0x00, {} } +}; +#endif +#if 0 +static struct LCM_setting_table lcm_sleep_out_setting[] = { + /* Sleep Out */ + {0x11, 1, {0x00} }, + {REGFLAG_DELAY, 120, {} }, + + /* Display ON */ + {0x29, 1, {0x00} }, + {REGFLAG_DELAY, 20, {} }, + {REGFLAG_END_OF_TABLE, 0x00, {} } +}; + +static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = { + /* Display off sequence */ + {0x28, 1, {0x00} }, + {REGFLAG_DELAY, 20, {} }, + + /* Sleep Mode On */ + {0x10, 1, {0x00} }, + {REGFLAG_DELAY, 120, {} }, + {REGFLAG_END_OF_TABLE, 0x00, {} } +}; +#endif +static struct LCM_setting_table bl_level[] = { + {0x51, 1, {0xFF} }, + {REGFLAG_END_OF_TABLE, 0x00, {} } +}; + +static void push_table(void *cmdq, struct LCM_setting_table *table, + unsigned int count, unsigned char force_update) +{ + unsigned int i; + unsigned cmd; + + for (i = 0; i < count; i++) { + cmd = table[i].cmd; + + switch (cmd) { + + case REGFLAG_DELAY: + if (table[i].count <= 10) + MDELAY(table[i].count); + else + MDELAY(table[i].count); + break; + + case REGFLAG_UDELAY: + UDELAY(table[i].count); + break; + + case REGFLAG_END_OF_TABLE: + break; + + default: + dsi_set_cmdq_V22(cmdq, cmd, table[i].count, table[i].para_list, force_update); + } + } +} + + +static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util) +{ + memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS)); +} + + +static void lcm_get_params(LCM_PARAMS *params) +{ + memset(params, 0, sizeof(LCM_PARAMS)); + + params->type = LCM_TYPE_DSI; + + params->width = FRAME_WIDTH; + params->height = FRAME_HEIGHT; + + params->physical_width = LCM_PHYSICAL_WIDTH/1000; + params->physical_height = LCM_PHYSICAL_HEIGHT/1000; + params->physical_width_um = LCM_PHYSICAL_WIDTH; + params->physical_height_um = LCM_PHYSICAL_HEIGHT; + +#if (LCM_DSI_CMD_MODE) + params->dsi.mode = CMD_MODE; + params->dsi.switch_mode = SYNC_PULSE_VDO_MODE; + lcm_dsi_mode = CMD_MODE; +#else + params->dsi.mode = SYNC_PULSE_VDO_MODE; + params->dsi.switch_mode = CMD_MODE; + lcm_dsi_mode = SYNC_PULSE_VDO_MODE; +#endif + LCM_LOGI("lcm_get_params lcm_dsi_mode %d\n", lcm_dsi_mode); + params->dsi.switch_mode_enable = 0; + + /* DSI */ + /* Command mode setting */ + params->dsi.LANE_NUM = LCM_FOUR_LANE; + /* The following defined the fomat for data coming from LCD engine. */ + params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB; + params->dsi.data_format.trans_seq = LCM_DSI_TRANS_SEQ_MSB_FIRST; + params->dsi.data_format.padding = LCM_DSI_PADDING_ON_LSB; + params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888; + + /* Highly depends on LCD driver capability. */ + params->dsi.packet_size = 256; + /* video mode timing */ + + params->dsi.PS = LCM_PACKED_PS_24BIT_RGB888; + + params->dsi.vertical_sync_active = 2; + params->dsi.vertical_backporch = 8; + params->dsi.vertical_frontporch = 10; + params->dsi.vertical_active_line = FRAME_HEIGHT; + + params->dsi.horizontal_sync_active = 10; + params->dsi.horizontal_backporch = 20; + params->dsi.horizontal_frontporch = 40; + params->dsi.horizontal_active_pixel = FRAME_WIDTH; + params->dsi.ssc_disable = 1; +#ifndef CONFIG_FPGA_EARLY_PORTING +#if (LCM_DSI_CMD_MODE) + params->dsi.PLL_CLOCK = 420; /* this value must be in MTK suggested table */ +#else + params->dsi.PLL_CLOCK = 440; /* this value must be in MTK suggested table */ +#endif + params->dsi.PLL_CK_CMD = 420; + params->dsi.PLL_CK_VDO = 440; +#else + params->dsi.pll_div1 = 0; + params->dsi.pll_div2 = 0; + params->dsi.fbk_div = 0x1; +#endif + params->dsi.CLK_HS_POST = 36; + params->dsi.clk_lp_per_line_enable = 0; + params->dsi.esd_check_enable = 1; + params->dsi.customization_esd_check_enable = 0; + params->dsi.lcm_esd_check_table[0].cmd = 0x53; + params->dsi.lcm_esd_check_table[0].count = 1; + params->dsi.lcm_esd_check_table[0].para_list[0] = 0x24; + +} + +#ifdef BUILD_LK +#ifndef CONFIG_FPGA_EARLY_PORTING +#define TPS65132_SLAVE_ADDR_WRITE 0x7C +static struct mt_i2c_t TPS65132_i2c; + +static int TPS65132_write_byte(kal_uint8 addr, kal_uint8 value) +{ + kal_uint32 ret_code = I2C_OK; + kal_uint8 write_data[2]; + kal_uint16 len; + + write_data[0] = addr; + write_data[1] = value; + + TPS65132_i2c.id = I2C_I2C_LCD_BIAS_CHANNEL; /* I2C2; */ + /* Since i2c will left shift 1 bit, we need to set FAN5405 I2C address to >>1 */ + TPS65132_i2c.addr = (TPS65132_SLAVE_ADDR_WRITE >> 1); + TPS65132_i2c.mode = ST_MODE; + TPS65132_i2c.speed = 100; + len = 2; + + ret_code = i2c_write(&TPS65132_i2c, write_data, len); + /* printf("%s: i2c_write: ret_code: %d\n", __func__, ret_code); */ + + return ret_code; +} + +#else + +/* extern int mt8193_i2c_write(u16 addr, u32 data); */ +/* extern int mt8193_i2c_read(u16 addr, u32 *data); */ + +/* #define TPS65132_write_byte(add, data) mt8193_i2c_write(add, data) */ +/* #define TPS65132_read_byte(add) mt8193_i2c_read(add) */ + +#endif +#endif + + +static void lcm_init_power(void) +{ +/*#ifndef CONFIG_FPGA_EARLY_PORTING +#ifdef BUILD_LK + mt6325_upmu_set_rg_vgp1_en(1); +#else + LCM_LOGI("%s, begin\n", __func__); + hwPowerOn(MT6325_POWER_LDO_VGP1, VOL_DEFAULT, "LCM_DRV"); + LCM_LOGI("%s, end\n", __func__); +#endif +#endif*/ +} + +static void lcm_suspend_power(void) +{ +/*#ifndef CONFIG_FPGA_EARLY_PORTING +#ifdef BUILD_LK + mt6325_upmu_set_rg_vgp1_en(0); +#else + LCM_LOGI("%s, begin\n", __func__); + hwPowerDown(MT6325_POWER_LDO_VGP1, "LCM_DRV"); + LCM_LOGI("%s, end\n", __func__); +#endif +#endif*/ +} + +static void lcm_resume_power(void) +{ +/*#ifndef CONFIG_FPGA_EARLY_PORTING +#ifdef BUILD_LK + mt6325_upmu_set_rg_vgp1_en(1); +#else + LCM_LOGI("%s, begin\n", __func__); + hwPowerOn(MT6325_POWER_LDO_VGP1, VOL_DEFAULT, "LCM_DRV"); + LCM_LOGI("%s, end\n", __func__); +#endif +#endif*/ +} + + +static void lcm_init(void) +{ + unsigned char cmd = 0x0; + unsigned char data = 0xFF; +#ifndef CONFIG_FPGA_EARLY_PORTING + int ret = 0; +#endif + + cmd = 0x00; + data = 0x0E; + + SET_RESET_PIN(0); + +#ifndef CONFIG_FPGA_EARLY_PORTING +#ifdef CONFIG_MTK_LEGACY + mt_set_gpio_mode(GPIO_65132_EN, GPIO_MODE_00); + mt_set_gpio_dir(GPIO_65132_EN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_65132_EN, GPIO_OUT_ONE); +#else + set_gpio_lcd_enp(1); +#endif + MDELAY(5); +#ifdef BUILD_LK + ret = TPS65132_write_byte(cmd, data); +#else +#if !defined(CONFIG_ARCH_MT6797) + ret = tps65132_write_bytes(cmd, data); +#endif +#endif + + if (ret < 0) + LCM_LOGI("nt35695----tps6132----cmd=%0x--i2c write error----\n", cmd); + else + LCM_LOGI("nt35695----tps6132----cmd=%0x--i2c write success----\n", cmd); + + cmd = 0x01; + data = 0x0E; + +#ifdef BUILD_LK + ret = TPS65132_write_byte(cmd, data); +#else +#if !defined(CONFIG_ARCH_MT6797) + ret = tps65132_write_bytes(cmd, data); +#endif +#endif + + if (ret < 0) + LCM_LOGI("nt35695----tps6132----cmd=%0x--i2c write error----\n", cmd); + else + LCM_LOGI("nt35695----tps6132----cmd=%0x--i2c write success----\n", cmd); + +#endif + SET_RESET_PIN(1); + MDELAY(1); + SET_RESET_PIN(0); + MDELAY(10); + + SET_RESET_PIN(1); + MDELAY(10); + if (lcm_dsi_mode == CMD_MODE) { + push_table(NULL, init_setting, sizeof(init_setting) / sizeof(struct LCM_setting_table), 1); + LCM_LOGI("nt35695----tps6132----lcm mode = cmd mode :%d----\n", lcm_dsi_mode); + } else { + push_table(NULL, init_setting2, sizeof(init_setting2) / sizeof(struct LCM_setting_table), 1); + LCM_LOGI("nt35695----tps6132----lcm mode = vdo mode :%d----\n", lcm_dsi_mode); + } +} + +static void lcm_suspend(void) +{ + push_table(NULL, lcm_suspend_setting, sizeof(lcm_suspend_setting) / sizeof(struct LCM_setting_table), 1); + MDELAY(10); +#ifndef CONFIG_FPGA_EARLY_PORTING +#ifdef CONFIG_MTK_LEGACY + mt_set_gpio_mode(GPIO_65132_EN, GPIO_MODE_00); + mt_set_gpio_dir(GPIO_65132_EN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_65132_EN, GPIO_OUT_ZERO); +#else + set_gpio_lcd_enp(0); +#endif +#endif + /* SET_RESET_PIN(0); */ +} + +static void lcm_resume(void) +{ + lcm_init(); +} + +static void lcm_update(unsigned int x, unsigned int y, unsigned int width, unsigned int height) +{ + unsigned int x0 = x; + unsigned int y0 = y; + unsigned int x1 = x0 + width - 1; + unsigned int y1 = y0 + height - 1; + + unsigned char x0_MSB = ((x0 >> 8) & 0xFF); + unsigned char x0_LSB = (x0 & 0xFF); + unsigned char x1_MSB = ((x1 >> 8) & 0xFF); + unsigned char x1_LSB = (x1 & 0xFF); + unsigned char y0_MSB = ((y0 >> 8) & 0xFF); + unsigned char y0_LSB = (y0 & 0xFF); + unsigned char y1_MSB = ((y1 >> 8) & 0xFF); + unsigned char y1_LSB = (y1 & 0xFF); + + unsigned int data_array[16]; + + data_array[0] = 0x00053902; + data_array[1] = (x1_MSB << 24) | (x0_LSB << 16) | (x0_MSB << 8) | 0x2a; + data_array[2] = (x1_LSB); + dsi_set_cmdq(data_array, 3, 1); + + data_array[0] = 0x00053902; + data_array[1] = (y1_MSB << 24) | (y0_LSB << 16) | (y0_MSB << 8) | 0x2b; + data_array[2] = (y1_LSB); + dsi_set_cmdq(data_array, 3, 1); + + data_array[0] = 0x002c3909; + dsi_set_cmdq(data_array, 1, 0); +} + +static unsigned int lcm_compare_id(void) +{ + unsigned int id = 0; + unsigned char buffer[2]; + unsigned int array[16]; + + SET_RESET_PIN(1); + SET_RESET_PIN(0); + MDELAY(1); + + SET_RESET_PIN(1); + MDELAY(20); + + array[0] = 0x00023700; /* read id return two byte,version and id */ + dsi_set_cmdq(array, 1, 1); + + read_reg_v2(0xF4, buffer, 2); + id = buffer[0]; /* we only need ID */ + + LCM_LOGI("%s,nt35695 debug: nt35695 id = 0x%08x\n", __func__, id); + + if (id == LCM_ID_NT35695) + return 1; + else + return 0; + +} + + +/* return TRUE: need recovery */ +/* return FALSE: No need recovery */ +static unsigned int lcm_esd_check(void) +{ +#ifndef BUILD_LK + char buffer[3]; + int array[4]; + + array[0] = 0x00013700; + dsi_set_cmdq(array, 1, 1); + + read_reg_v2(0x53, buffer, 1); + + if (buffer[0] != 0x24) { + LCM_LOGI("[LCM ERROR] [0x53]=0x%02x\n", buffer[0]); + return TRUE; + } + LCM_LOGI("[LCM NORMAL] [0x53]=0x%02x\n", buffer[0]); + return FALSE; +#else + return FALSE; +#endif + +} + +static unsigned int lcm_ata_check(unsigned char *buffer) +{ +#ifndef BUILD_LK + unsigned int ret = 0; + unsigned int x0 = FRAME_WIDTH / 4; + unsigned int x1 = FRAME_WIDTH * 3 / 4; + + unsigned char x0_MSB = ((x0 >> 8) & 0xFF); + unsigned char x0_LSB = (x0 & 0xFF); + unsigned char x1_MSB = ((x1 >> 8) & 0xFF); + unsigned char x1_LSB = (x1 & 0xFF); + + unsigned int data_array[3]; + unsigned char read_buf[4]; + + LCM_LOGI("ATA check size = 0x%x,0x%x,0x%x,0x%x\n", x0_MSB, x0_LSB, x1_MSB, x1_LSB); + data_array[0] = 0x0005390A; /* HS packet */ + data_array[1] = (x1_MSB << 24) | (x0_LSB << 16) | (x0_MSB << 8) | 0x2a; + data_array[2] = (x1_LSB); + dsi_set_cmdq(data_array, 3, 1); + + data_array[0] = 0x00043700; /* read id return two byte,version and id */ + dsi_set_cmdq(data_array, 1, 1); + + read_reg_v2(0x2A, read_buf, 4); + + if ((read_buf[0] == x0_MSB) && (read_buf[1] == x0_LSB) + && (read_buf[2] == x1_MSB) && (read_buf[3] == x1_LSB)) + ret = 1; + else + ret = 0; + + x0 = 0; + x1 = FRAME_WIDTH - 1; + + x0_MSB = ((x0 >> 8) & 0xFF); + x0_LSB = (x0 & 0xFF); + x1_MSB = ((x1 >> 8) & 0xFF); + x1_LSB = (x1 & 0xFF); + + data_array[0] = 0x0005390A; /* HS packet */ + data_array[1] = (x1_MSB << 24) | (x0_LSB << 16) | (x0_MSB << 8) | 0x2a; + data_array[2] = (x1_LSB); + dsi_set_cmdq(data_array, 3, 1); + return ret; +#else + return 0; +#endif +} + +static void lcm_setbacklight_cmdq(void *handle, unsigned int level) +{ + + LCM_LOGI("%s,nt35695 backlight: level = %d\n", __func__, level); + + bl_level[0].para_list[0] = level; + + push_table(handle, bl_level, sizeof(bl_level) / sizeof(struct LCM_setting_table), 1); +} + +static void *lcm_switch_mode(int mode) +{ +#ifndef BUILD_LK +/* customization: 1. V2C config 2 values, C2V config 1 value; 2. config mode control register */ + if (mode == 0) { /* V2C */ + lcm_switch_mode_cmd.mode = CMD_MODE; + lcm_switch_mode_cmd.addr = 0xBB; /* mode control addr */ + lcm_switch_mode_cmd.val[0] = 0x13; /* enabel GRAM firstly, ensure writing one frame to GRAM */ + lcm_switch_mode_cmd.val[1] = 0x10; /* disable video mode secondly */ + } else { /* C2V */ + lcm_switch_mode_cmd.mode = SYNC_PULSE_VDO_MODE; + lcm_switch_mode_cmd.addr = 0xBB; + lcm_switch_mode_cmd.val[0] = 0x03; /* disable GRAM and enable video mode */ + } + return (void *)(&lcm_switch_mode_cmd); +#else + return NULL; +#endif +} + + +LCM_DRIVER nt35695_fhd_dsi_cmd_truly_nt50358_lcm_drv = { + .name = "nt35695_fhd_dsi_cmd_truly_nt50358_drv", + .set_util_funcs = lcm_set_util_funcs, + .get_params = lcm_get_params, + .init = lcm_init, + .suspend = lcm_suspend, + .resume = lcm_resume, + .compare_id = lcm_compare_id, + .init_power = lcm_init_power, + .resume_power = lcm_resume_power, + .suspend_power = lcm_suspend_power, + .esd_check = lcm_esd_check, + .set_backlight_cmdq = lcm_setbacklight_cmdq, + .ata_check = lcm_ata_check, + .update = lcm_update, + .switch_mode = lcm_switch_mode, +}; diff --git a/drivers/misc/mediatek/leds/mt6755/Makefile b/drivers/misc/mediatek/leds/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2340f16a7aeb6874b9b6f70b2369ac34d0927fed --- /dev/null +++ b/drivers/misc/mediatek/leds/mt6755/Makefile @@ -0,0 +1,3 @@ + +obj-$(CONFIG_MTK_LEDS) := leds.o +ccflags-y += -I$(srctree)/drivers/misc/mediatek/video/include diff --git a/drivers/misc/mediatek/leds/mt6755/leds.c b/drivers/misc/mediatek/leds/mt6755/leds.c new file mode 100644 index 0000000000000000000000000000000000000000..294ad5bd8053bd36d794e6487905258c01505beb --- /dev/null +++ b/drivers/misc/mediatek/leds/mt6755/leds.c @@ -0,0 +1,1515 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +#include +#include +/* #include +#include +#include */ + +/* Vanzo:zhangqingzhan on: Tue, 27 Sep 2016 18:17:53 +0800 + *for button light + */ +#include +#include + +// End of Vanzo: zhangqingzhan + + +#ifdef CONFIG_MTK_AAL_SUPPORT +#include +/* #include */ +#endif + +#include +#include +#include + +#include "leds_sw.h" +#include "leds_hal.h" +#include "ddp_pwm.h" +#include "mtkfb.h" + + +/* for LED&Backlight bringup, define the dummy API */ +#ifndef CONFIG_MTK_PMIC +u16 pmic_set_register_value(u32 flagname, u32 val) +{ + return 0; +} +#endif + +int __weak mtkfb_set_backlight_level(unsigned int level) +{ + return 0; +} + +#ifndef CONFIG_MTK_PWM +s32 pwm_set_spec_config(struct pwm_spec_config *conf) +{ + return 0; +} + +void mt_pwm_disable(u32 pwm_no, u8 pmic_pad) +{ +} +#endif + +/* Vanzo:zhangqingzhan on: Tue, 27 Sep 2016 18:18:20 +0800 + *for button light + */ +static long gpio_set_buttonlight(int level_1024); +static long gpio_button_init(void); + +struct pinctrl *buttonctrl = NULL; +struct pinctrl_state *button_gpio_h = NULL; +struct pinctrl_state *button_gpio_l = NULL; + +// End of Vanzo: zhangqingzhan + + +static DEFINE_MUTEX(leds_mutex); +static DEFINE_MUTEX(leds_pmic_mutex); + +/**************************************************************************** + * variables + ***************************************************************************/ +/* struct cust_mt65xx_led* bl_setting_hal = NULL; */ +static unsigned int bl_brightness_hal = 102; +static unsigned int bl_duty_hal = 21; +static unsigned int bl_div_hal = CLK_DIV1; +static unsigned int bl_frequency_hal = 32000; +/* for button led don't do ISINK disable first time */ +static int button_flag_isink0; +static int button_flag_isink1; +static int button_flag_isink2; +static int button_flag_isink3; + +struct wake_lock leds_suspend_lock; + +char *leds_name[MT65XX_LED_TYPE_TOTAL] = { + "red", + "green", + "blue", + "jogball-backlight", + "keyboard-backlight", + "button-backlight", + "lcd-backlight", +}; + +struct cust_mt65xx_led *pled_dtsi = NULL; +/**************************************************************************** + * DEBUG MACROS + ***************************************************************************/ +static int debug_enable_led_hal = 1; +#define LEDS_DEBUG(format, args...) do { \ + if (debug_enable_led_hal) { \ + pr_debug("[LED]"format, ##args);\ + } \ +} while (0) + +/*****************PWM *************************************************/ +#define PWM_DIV_NUM 8 +static int time_array_hal[PWM_DIV_NUM] = { + 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 }; +static unsigned int div_array_hal[PWM_DIV_NUM] = { + 1, 2, 4, 8, 16, 32, 64, 128 }; + +static unsigned int backlight_PWM_div_hal = CLK_DIV1; /* this para come from cust_leds. */ + +/**************************************************************************** + * func:return global variables + ***************************************************************************/ +static unsigned long long current_time, last_time; +static int count; +static char buffer[4096] = "[BL] Set Backlight directly "; + + +/* Vanzo:zhangqingzhan on: Tue, 27 Sep 2016 18:18:53 +0800 + *for button light + */ +static long gpio_button_init(void) +{ + long ret = 0; + struct device_node *node = NULL; + struct platform_device *pdev = NULL; + + node = of_find_compatible_node(NULL, NULL,"mediatek,button-backlight"); + if(node){ + pdev = of_find_device_by_node(node); + if (pdev) { + buttonctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(buttonctrl)) { + ret = PTR_ERR(buttonctrl); + LEDS_DEBUG("%s can't find button pinctrl\n", __func__); + return ret; + } + } else { + LEDS_DEBUG("%s platform device is null\n", __func__); + } + + button_gpio_h = pinctrl_lookup_state(buttonctrl, "gpio_button_on"); + if (IS_ERR(button_gpio_h)) { + LEDS_DEBUG("gpio_button_init gpio_name=button_gpio_h failed\n"); + ret = PTR_ERR(button_gpio_h); + return ret; + } + button_gpio_l = pinctrl_lookup_state(buttonctrl, "gpio_button_off"); + if (IS_ERR(button_gpio_l)) { + LEDS_DEBUG("gpio_button_init gpio_name=button_gpio_l failed\n"); + ret = PTR_ERR(button_gpio_l); + return ret; + } + }else{ + LEDS_DEBUG("device node is null\n"); + } + return ret; +} +static long gpio_set_buttonlight(int level_1024) +{ + if (IS_ERR(button_gpio_l)){ + LEDS_DEBUG("gpio_button_init gpio_name=button_gpio_l failed\n"); + return 0; + } + if (IS_ERR(button_gpio_h)) { + LEDS_DEBUG("gpio_button_init gpio_name=button_gpio_h failed\n"); + return 0; + } + if(level_1024) + pinctrl_select_state(buttonctrl,button_gpio_h); + else + pinctrl_select_state(buttonctrl,button_gpio_l); + return 0; +} + +// End of Vanzo: zhangqingzhan +static void backlight_debug_log(int level, int mappingLevel) +{ + unsigned long long temp_time, rem; + + current_time = sched_clock(); + temp_time = current_time; + rem = do_div(temp_time, 1000000000); + do_div(rem, 1000000); + + sprintf(buffer + strlen(buffer), "T:%lld.%lld,L:%d map:%d ", + temp_time, rem, level, mappingLevel); + + count++; + + if (level == 0 || count == 5 || (current_time - last_time) > 1000000000) { + LEDS_DEBUG("%s", buffer); + count = 0; + buffer[strlen("[BL] Set Backlight directly ")] = '\0'; + } + + last_time = sched_clock(); +} + +void mt_leds_wake_lock_init(void) +{ + wake_lock_init(&leds_suspend_lock, WAKE_LOCK_SUSPEND, "leds wakelock"); +} + +unsigned int mt_get_bl_brightness(void) +{ + return bl_brightness_hal; +} + +unsigned int mt_get_bl_duty(void) +{ + return bl_duty_hal; +} + +unsigned int mt_get_bl_div(void) +{ + return bl_div_hal; +} + +unsigned int mt_get_bl_frequency(void) +{ + return bl_frequency_hal; +} + +unsigned int *mt_get_div_array(void) +{ + return &div_array_hal[0]; +} + +void mt_set_bl_duty(unsigned int level) +{ + bl_duty_hal = level; +} + +void mt_set_bl_div(unsigned int div) +{ + bl_div_hal = div; +} + +void mt_set_bl_frequency(unsigned int freq) +{ + bl_frequency_hal = freq; +} + +struct cust_mt65xx_led *get_cust_led_dtsi(void) +{ + struct device_node *led_node = NULL; + bool isSupportDTS = false; + int i, ret; + int mode, data; + int pwm_config[5] = { 0 }; + + /* LEDS_DEBUG("get_cust_led_dtsi: get the leds info from device tree\n"); */ + if (pled_dtsi == NULL) { + /* this can allocat an new struct array */ + pled_dtsi = kmalloc(MT65XX_LED_TYPE_TOTAL * + sizeof(struct + cust_mt65xx_led), + GFP_KERNEL); + if (pled_dtsi == NULL) { + LEDS_DEBUG("get_cust_led_dtsi kmalloc fail\n"); + goto out; + } + + for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++) { + + char node_name[32] = "mediatek,"; + if (strlen(node_name) + strlen(leds_name[i]) + 1 > sizeof(node_name)) { + LEDS_DEBUG("buffer for %s%s not enough\n", node_name, leds_name[i]); + pled_dtsi[i].mode = 0; + pled_dtsi[i].data = -1; + continue; + } + + pled_dtsi[i].name = leds_name[i]; + + led_node = + of_find_compatible_node(NULL, NULL, + strncat(node_name, + leds_name[i], sizeof(node_name) - strlen(node_name) - 1)); + if (!led_node) { + LEDS_DEBUG("Cannot find LED node from dts\n"); + pled_dtsi[i].mode = 0; + pled_dtsi[i].data = -1; + } else { + isSupportDTS = true; + ret = + of_property_read_u32(led_node, "led_mode", + &mode); + if (!ret) { + pled_dtsi[i].mode = mode; + LEDS_DEBUG + ("The %s's led mode is : %d\n", + pled_dtsi[i].name, + pled_dtsi[i].mode); + } else { + LEDS_DEBUG + ("led dts can not get led mode"); + pled_dtsi[i].mode = 0; + } + + ret = + of_property_read_u32(led_node, "data", + &data); + if (!ret) { + pled_dtsi[i].data = data; + LEDS_DEBUG + ("The %s's led data is : %ld\n", + pled_dtsi[i].name, + pled_dtsi[i].data); + } else { + LEDS_DEBUG + ("led dts can not get led data"); + pled_dtsi[i].data = -1; + } + + ret = + of_property_read_u32_array(led_node, + "pwm_config", + pwm_config, + ARRAY_SIZE + (pwm_config)); + if (!ret) { + LEDS_DEBUG + ("The %s's pwm config data is %d %d %d %d %d\n", + pled_dtsi[i].name, pwm_config[0], + pwm_config[1], pwm_config[2], + pwm_config[3], pwm_config[4]); + pled_dtsi[i].config_data.clock_source = + pwm_config[0]; + pled_dtsi[i].config_data.div = + pwm_config[1]; + pled_dtsi[i].config_data.low_duration = + pwm_config[2]; + pled_dtsi[i].config_data.High_duration = + pwm_config[3]; + pled_dtsi[i].config_data.pmic_pad = + pwm_config[4]; + + } else + LEDS_DEBUG + ("led dts can not get pwm config data.\n"); + + switch (pled_dtsi[i].mode) { + case MT65XX_LED_MODE_CUST_LCM: + pled_dtsi[i].data = + (long)mtkfb_set_backlight_level; + LEDS_DEBUG + ("kernel:the backlight hw mode is LCM.\n"); + break; + case MT65XX_LED_MODE_CUST_BLS_PWM: + pled_dtsi[i].data = + (long)disp_bls_set_backlight; + LEDS_DEBUG + ("kernel:the backlight hw mode is BLS.\n"); + break; +/* Vanzo:zhangqingzhan on: Tue, 27 Sep 2016 18:19:42 +0800 + *for button light + */ + case MT65XX_LED_MODE_GPIO: + gpio_button_init(); + pled_dtsi[i].data = + (long)gpio_set_buttonlight; + LEDS_DEBUG + ("kernel:the button light mode.\n"); + break; + +// End of Vanzo: zhangqingzhan + default: + break; + } + } + } + + if (!isSupportDTS) { + kfree(pled_dtsi); + pled_dtsi = NULL; + } + } + out: + return pled_dtsi; +} + +struct cust_mt65xx_led *mt_get_cust_led_list(void) +{ + struct cust_mt65xx_led *cust_led_list = get_cust_led_dtsi(); + return cust_led_list; +} + +/**************************************************************************** + * internal functions + ***************************************************************************/ +static int brightness_mapto64(int level) +{ + if (level < 30) + return (level >> 1) + 7; + else if (level <= 120) + return (level >> 2) + 14; + else if (level <= 160) + return level / 5 + 20; + else + return (level >> 3) + 33; +} + +static int find_time_index(int time) +{ + int index = 0; + + while (index < 8) { + if (time < time_array_hal[index]) + return index; + index++; + } + return PWM_DIV_NUM - 1; +} + +int mt_led_set_pwm(int pwm_num, struct nled_setting *led) +{ + struct pwm_spec_config pwm_setting = { .pwm_no = pwm_num}; + int time_index = 0; + + pwm_setting.pwm_no = pwm_num; + pwm_setting.mode = PWM_MODE_OLD; + + LEDS_DEBUG("led_set_pwm: mode=%d,pwm_no=%d\n", led->nled_mode, + pwm_num); + /* We won't choose 32K to be the clock src of old mode because of system performance. */ + /* The setting here will be clock src = 26MHz, CLKSEL = 26M/1625 (i.e. 16K) */ + pwm_setting.clk_src = PWM_CLK_OLD_MODE_32K; + + switch (led->nled_mode) { + /* Actually, the setting still can not to turn off NLED. We should disable PWM to turn off NLED. */ + case NLED_OFF: + pwm_setting.PWM_MODE_OLD_REGS.THRESH = 0; + pwm_setting.clk_div = CLK_DIV1; + pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 100 / 2; + break; + + case NLED_ON: + pwm_setting.PWM_MODE_OLD_REGS.THRESH = 30 / 2; + pwm_setting.clk_div = CLK_DIV1; + pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 100 / 2; + break; + + case NLED_BLINK: + LEDS_DEBUG("LED blink on time = %d offtime = %d\n", + led->blink_on_time, led->blink_off_time); + time_index = + find_time_index(led->blink_on_time + led->blink_off_time); + LEDS_DEBUG("LED div is %d\n", time_index); + pwm_setting.clk_div = time_index; + pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = + (led->blink_on_time + + led->blink_off_time) * MIN_FRE_OLD_PWM / + div_array_hal[time_index]; + pwm_setting.PWM_MODE_OLD_REGS.THRESH = + (led->blink_on_time * 100) / (led->blink_on_time + + led->blink_off_time); + } + + pwm_setting.PWM_MODE_FIFO_REGS.IDLE_VALUE = 0; + pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0; + pwm_setting.PWM_MODE_FIFO_REGS.GDURATION = 0; + pwm_setting.PWM_MODE_FIFO_REGS.WAVE_NUM = 0; + pwm_set_spec_config(&pwm_setting); + + return 0; +} + +/************************ led breath function*****************************/ +/************************************************************************* +//func is to swtich to breath mode from PWM mode of ISINK +//para: enable: 1 : breath mode; 0: PWM mode; +*************************************************************************/ +#if 0 +static int led_switch_breath_pmic(enum mt65xx_led_pmic pmic_type, + struct nled_setting *led, int enable) +{ + /* int time_index = 0; */ + /* int duty = 0; */ + LEDS_DEBUG("led_blink_pmic: pmic_type=%d\n", pmic_type); + + if ((pmic_type != MT65XX_LED_PMIC_NLED_ISINK0 + && pmic_type != MT65XX_LED_PMIC_NLED_ISINK1 + && pmic_type != MT65XX_LED_PMIC_NLED_ISINK2 + && pmic_type != MT65XX_LED_PMIC_NLED_ISINK3) + || led->nled_mode != NLED_BLINK) { + return -1; + } + if (1 == enable) { + switch (pmic_type) { + case MT65XX_LED_PMIC_NLED_ISINK0: + pmic_set_register_value(PMIC_ISINK_CH0_MODE, ISINK_BREATH_MODE); + pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3); + pmic_set_register_value(PMIC_ISINK_BREATH0_TRF_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH0_TR1_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH0_TR2_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH0_TF1_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH0_TF2_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH0_TON_SEL, 0x02); + pmic_set_register_value(PMIC_ISINK_BREATH0_TOFF_SEL, 0x03); + pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, 15); + pmic_set_register_value(PMIC_ISINK_DIM0_FSEL, 11); + /* pmic_set_register_value(PMIC_ISINK_CH0_EN,NLED_ON); */ + break; + case MT65XX_LED_PMIC_NLED_ISINK1: + pmic_set_register_value(PMIC_ISINK_CH1_MODE, ISINK_BREATH_MODE); + pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3); + pmic_set_register_value(PMIC_ISINK_BREATH1_TRF_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH1_TR1_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH1_TR2_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH1_TF1_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH1_TF2_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH1_TON_SEL, 0x02); + pmic_set_register_value(PMIC_ISINK_BREATH1_TOFF_SEL, 0x03); + pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, 15); + pmic_set_register_value(PMIC_ISINK_DIM1_FSEL, 11); + /* pmic_set_register_value(PMIC_ISINK_CH1_EN,NLED_ON); */ + break; + case MT65XX_LED_PMIC_NLED_ISINK2: + pmic_set_register_value(PMIC_ISINK_CH4_MODE, ISINK_BREATH_MODE); + pmic_set_register_value(PMIC_ISINK_CH4_STEP, ISINK_3); + pmic_set_register_value(PMIC_ISINK_BREATH4_TRF_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH4_TR1_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH4_TR2_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH4_TF1_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH4_TF2_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH4_TON_SEL, 0x02); + pmic_set_register_value(PMIC_ISINK_BREATH4_TOFF_SEL, 0x03); + pmic_set_register_value(PMIC_ISINK_DIM4_DUTY, 15); + pmic_set_register_value(PMIC_ISINK_DIM4_FSEL, 11); + /* pmic_set_register_value(PMIC_ISINK_CH4_EN,NLED_ON); */ + break; + case MT65XX_LED_PMIC_NLED_ISINK3: + pmic_set_register_value(PMIC_ISINK_CH5_MODE, ISINK_BREATH_MODE); + pmic_set_register_value(PMIC_ISINK_CH5_STEP, ISINK_3); + pmic_set_register_value(PMIC_ISINK_BREATH5_TRF_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH5_TR1_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH5_TR2_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH5_TF1_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH5_TF2_SEL, 0x04); + pmic_set_register_value(PMIC_ISINK_BREATH5_TON_SEL, 0x02); + pmic_set_register_value(PMIC_ISINK_BREATH5_TOFF_SEL, 0x03); + pmic_set_register_value(PMIC_ISINK_DIM5_DUTY, 15); + pmic_set_register_value(PMIC_ISINK_DIM5_FSEL, 11); + /* pmic_set_register_value(PMIC_ISINK_CH5_EN,NLED_ON); */ + break; + default: + break; + } + } else { + switch (pmic_type) { + case MT65XX_LED_PMIC_NLED_ISINK0: + pmic_set_register_value(PMIC_ISINK_CH0_MODE, + ISINK_PWM_MODE); + break; + case MT65XX_LED_PMIC_NLED_ISINK1: + pmic_set_register_value(PMIC_ISINK_CH1_MODE, + ISINK_PWM_MODE); + break; + case MT65XX_LED_PMIC_NLED_ISINK2: + pmic_set_register_value(PMIC_ISINK_CH4_MODE, + ISINK_PWM_MODE); + break; + case MT65XX_LED_PMIC_NLED_ISINK3: + pmic_set_register_value(PMIC_ISINK_CH5_MODE, + ISINK_PWM_MODE); + break; + default: + break; + } + } + return 0; + +} +#endif + +#define PMIC_PERIOD_NUM 8 +/* 100 * period, ex: 0.01 Hz -> 0.01 * 100 = 1 */ +int pmic_period_array[] = { 250, 500, 1000, 1250, 1666, 2000, 2500, 10000 }; + +/* int pmic_freqsel_array[] = {99999, 9999, 4999, 1999, 999, 499, 199, 4, 0}; */ +int pmic_freqsel_array[] = { 0, 4, 199, 499, 999, 1999, 1999, 1999 }; + +static int find_time_index_pmic(int time_ms) +{ + int i; + + for (i = 0; i < PMIC_PERIOD_NUM; i++) { + if (time_ms <= pmic_period_array[i]) + return i; + } + return PMIC_PERIOD_NUM - 1; +} + +int mt_led_blink_pmic(enum mt65xx_led_pmic pmic_type, struct nled_setting *led) +{ +#ifdef CONFIG_MTK_PMIC + int time_index = 0; + int duty = 0; + + LEDS_DEBUG("led_blink_pmic: pmic_type=%d\n", pmic_type); + + if (led->nled_mode != NLED_BLINK) + return -1; + + LEDS_DEBUG("LED blink on time = %d offtime = %d\n", + led->blink_on_time, led->blink_off_time); + time_index = + find_time_index_pmic(led->blink_on_time + led->blink_off_time); + LEDS_DEBUG("LED index is %d freqsel=%d\n", time_index, + pmic_freqsel_array[time_index]); + duty = + 32 * led->blink_on_time / (led->blink_on_time + + led->blink_off_time); + if (pmic_type > MT65XX_LED_PMIC_NLED_ISINK_MIN && pmic_type < MT65XX_LED_PMIC_NLED_ISINK_MAX) { + /* pmic_set_register_value(PMIC_RG_G_DRV_2M_CK_PDN(0X0); // DISABLE POWER DOWN ,Indicator no need) */ + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + #endif + } + + switch (pmic_type) { + case MT65XX_LED_PMIC_NLED_ISINK0: + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_ISINK0_CK_PDN, 0); + pmic_set_register_value(PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE); + pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, duty); + pmic_set_register_value(PMIC_ISINK_DIM0_FSEL, + pmic_freqsel_array[time_index]); + pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_ON); + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK0_CK_PDN, 0); + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL, 0); + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE); + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(MT6351_PMIC_ISINK_DIM0_DUTY, duty); + pmic_set_register_value(MT6351_PMIC_ISINK_DIM0_FSEL, + pmic_freqsel_array[time_index]); + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_EN, NLED_ON); + #endif + break; + case MT65XX_LED_PMIC_NLED_ISINK1: + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_ISINK1_CK_PDN, 0); + pmic_set_register_value(PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE); + pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, duty); + pmic_set_register_value(PMIC_ISINK_DIM1_FSEL, + pmic_freqsel_array[time_index]); + pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_ON); + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK1_CK_PDN, 0); + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL, 0); + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE); + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(MT6351_PMIC_ISINK_DIM1_DUTY, duty); + pmic_set_register_value(MT6351_PMIC_ISINK_DIM1_FSEL, + pmic_freqsel_array[time_index]); + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_EN, NLED_ON); + #endif + break; + case MT65XX_LED_PMIC_NLED_ISINK2: + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_ISINK2_CK_PDN, 0); + pmic_set_register_value(PMIC_ISINK_CH2_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(PMIC_ISINK_CH2_EN, NLED_ON); + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK4_CK_PDN, 0); + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL, 0); + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_MODE, ISINK_PWM_MODE); + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(MT6351_PMIC_ISINK_DIM4_DUTY, duty); + pmic_set_register_value(MT6351_PMIC_ISINK_DIM4_FSEL, + pmic_freqsel_array[time_index]); + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_EN, NLED_ON); + #endif + break; + case MT65XX_LED_PMIC_NLED_ISINK3: + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_ISINK3_CK_PDN, 0); + pmic_set_register_value(PMIC_ISINK_CH3_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(PMIC_ISINK_CH3_EN, NLED_ON); + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK5_CK_PDN, 0); + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL, 0); + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_MODE, ISINK_PWM_MODE); + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(MT6351_PMIC_ISINK_DIM5_DUTY, duty); + pmic_set_register_value(MT6351_PMIC_ISINK_DIM5_FSEL, + pmic_freqsel_array[time_index]); + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_EN, NLED_ON); + #endif + break; + default: + LEDS_DEBUG("[LEDS] pmic_type %d is not handled\n", pmic_type); + break; + } +#endif /* End of #ifdef CONFIG_MTK_PMIC */ + return 0; +} + +int mt_backlight_set_pwm(int pwm_num, u32 level, u32 div, + struct PWM_config *config_data) +{ + struct pwm_spec_config pwm_setting = { .pwm_no = pwm_num}; + unsigned int BacklightLevelSupport = + Cust_GetBacklightLevelSupport_byPWM(); + pwm_setting.pwm_no = pwm_num; + + if (BacklightLevelSupport == BACKLIGHT_LEVEL_PWM_256_SUPPORT) + pwm_setting.mode = PWM_MODE_OLD; + else + pwm_setting.mode = PWM_MODE_FIFO; /* New mode fifo and periodical mode */ + + pwm_setting.pmic_pad = config_data->pmic_pad; + + if (config_data->div) { + pwm_setting.clk_div = config_data->div; + backlight_PWM_div_hal = config_data->div; + } else + pwm_setting.clk_div = div; + + if (BacklightLevelSupport == BACKLIGHT_LEVEL_PWM_256_SUPPORT) { + if (config_data->clock_source) + pwm_setting.clk_src = PWM_CLK_OLD_MODE_BLOCK; + else + pwm_setting.clk_src = PWM_CLK_OLD_MODE_32K; /* actually. + it's block/1625 = 26M/1625 = 16KHz @ MT6571 */ + + pwm_setting.PWM_MODE_OLD_REGS.IDLE_VALUE = 0; + pwm_setting.PWM_MODE_OLD_REGS.GUARD_VALUE = 0; + pwm_setting.PWM_MODE_OLD_REGS.GDURATION = 0; + pwm_setting.PWM_MODE_OLD_REGS.WAVE_NUM = 0; + pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 255; /* 256 level */ + pwm_setting.PWM_MODE_OLD_REGS.THRESH = level; + + LEDS_DEBUG("[LEDS][%d]backlight_set_pwm:duty is %d/%d\n", + BacklightLevelSupport, level, + pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH); + LEDS_DEBUG("[LEDS][%d]backlight_set_pwm:clk_src/div is %d%d\n", + BacklightLevelSupport, pwm_setting.clk_src, + pwm_setting.clk_div); + if (level > 0 && level < 256) { + pwm_set_spec_config(&pwm_setting); + LEDS_DEBUG + ("[LEDS][%d]backlight_set_pwm: old mode: thres/data_width is %d/%d\n", + BacklightLevelSupport, + pwm_setting.PWM_MODE_OLD_REGS.THRESH, + pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH); + } else { + LEDS_DEBUG("[LEDS][%d]Error level in backlight\n", + BacklightLevelSupport); + mt_pwm_disable(pwm_setting.pwm_no, + config_data->pmic_pad); + } + return 0; + + } else { + if (config_data->clock_source) { + pwm_setting.clk_src = PWM_CLK_NEW_MODE_BLOCK; + } else { + pwm_setting.clk_src = + PWM_CLK_NEW_MODE_BLOCK_DIV_BY_1625; + } + + if (config_data->High_duration && config_data->low_duration) { + pwm_setting.PWM_MODE_FIFO_REGS.HDURATION = + config_data->High_duration; + pwm_setting.PWM_MODE_FIFO_REGS.LDURATION = + pwm_setting.PWM_MODE_FIFO_REGS.HDURATION; + } else { + pwm_setting.PWM_MODE_FIFO_REGS.HDURATION = 4; + pwm_setting.PWM_MODE_FIFO_REGS.LDURATION = 4; + } + + pwm_setting.PWM_MODE_FIFO_REGS.IDLE_VALUE = 0; + pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0; + pwm_setting.PWM_MODE_FIFO_REGS.STOP_BITPOS_VALUE = 31; + pwm_setting.PWM_MODE_FIFO_REGS.GDURATION = + (pwm_setting.PWM_MODE_FIFO_REGS.HDURATION + 1) * 32 - 1; + pwm_setting.PWM_MODE_FIFO_REGS.WAVE_NUM = 0; + + LEDS_DEBUG("[LEDS]backlight_set_pwm:duty is %d\n", level); + LEDS_DEBUG + ("[LEDS]backlight_set_pwm:clk_src/div/high/low is %d%d%d%d\n", + pwm_setting.clk_src, pwm_setting.clk_div, + pwm_setting.PWM_MODE_FIFO_REGS.HDURATION, + pwm_setting.PWM_MODE_FIFO_REGS.LDURATION); + + if (level > 0 && level <= 32) { + pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0; + pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0 = + (1 << level) - 1; + pwm_set_spec_config(&pwm_setting); + } else if (level > 32 && level <= 64) { + pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 1; + level -= 32; + pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0 = + (1 << level) - 1; + pwm_set_spec_config(&pwm_setting); + } else { + LEDS_DEBUG("[LEDS]Error level in backlight\n"); + mt_pwm_disable(pwm_setting.pwm_no, + config_data->pmic_pad); + } + + return 0; + + } +} + +void mt_led_pwm_disable(int pwm_num) +{ + struct cust_mt65xx_led *cust_led_list = get_cust_led_dtsi(); + + mt_pwm_disable(pwm_num, cust_led_list->config_data.pmic_pad); +} + +void mt_backlight_set_pwm_duty(int pwm_num, u32 level, u32 div, + struct PWM_config *config_data) +{ + mt_backlight_set_pwm(pwm_num, level, div, config_data); +} + +void mt_backlight_set_pwm_div(int pwm_num, u32 level, u32 div, + struct PWM_config *config_data) +{ + mt_backlight_set_pwm(pwm_num, level, div, config_data); +} + +void mt_backlight_get_pwm_fsel(unsigned int bl_div, unsigned int *bl_frequency) +{ + +} + +void mt_store_pwm_register(unsigned int addr, unsigned int value) +{ + +} + +unsigned int mt_show_pwm_register(unsigned int addr) +{ + return 0; +} + +#define PMIC_BACKLIGHT_LEVEL 80 +int mt_brightness_set_pmic(enum mt65xx_led_pmic pmic_type, u32 level, u32 div) +{ + static bool first_time = true; +#if 0 + int tmp_level = level; + static bool backlight_init_flag; + static unsigned char duty_mapping[PMIC_BACKLIGHT_LEVEL] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 24, + 25, 26, 27, 28, 29, 30, 31, 25, 26, 27, 28, 29, + 30, 31, 26, 27, 28, 29, 30, 31, + }; + static unsigned char current_mapping[PMIC_BACKLIGHT_LEVEL] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 5, + }; +#endif + LEDS_DEBUG("PMIC#%d:%d\n", pmic_type, level); + mutex_lock(&leds_pmic_mutex); + if (pmic_type == MT65XX_LED_PMIC_LCD_ISINK) { +#if 0 + if (backlight_init_flag == false) { + pmic_set_register_value(PMIC_RG_G_DRV_2M_CK_PDN, 0x0); /* Disable power down */ + + /* For backlight: Current: 24mA, PWM frequency: 20K */ + /* Duty: 20~100, Soft start: off, Phase shift: on */ + /* ISINK0 */ + pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_CKSEL, 0x1); /* Freq = 1Mhz for Backlight */ + pmic_set_register_value(PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE); + pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_5); /* 24mA */ + pmic_set_register_value(PMIC_ISINK_SFSTR0_EN, 0x0); /* Disable soft start */ + pmic_set_register_value(PMIC_ISINK_PHASE_DLY_TC, 0x0); /* TC = 0.5us */ + pmic_set_register_value(PMIC_ISINK_PHASE0_DLY_EN, 0x1); /* Enable phase delay */ + pmic_set_register_value(PMIC_ISINK_CHOP0_EN, 0x1); /* Enable CHOP clk */ + /* ISINK1 */ + pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_CKSEL, 0x1); /* Freq = 1Mhz for Backlight */ + pmic_set_register_value(PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE); + pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3); /* 24mA */ + pmic_set_register_value(PMIC_ISINK_SFSTR1_EN, 0x0); /* Disable soft start */ + pmic_set_register_value(PMIC_ISINK_PHASE1_DLY_EN, 0x1); /* Enable phase delay */ + pmic_set_register_value(PMIC_ISINK_CHOP1_EN, 0x1); /* Enable CHOP clk */ + /* ISINK2 */ + pmic_set_register_value(PMIC_RG_DRV_ISINK2_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_RG_DRV_ISINK2_CK_CKSEL, 0x1); /* Freq = 1Mhz for Backlight */ + pmic_set_register_value(PMIC_ISINK_CH2_STEP, ISINK_3); /* 24mA */ + pmic_set_register_value(PMIC_ISINK_CHOP2_EN, 0x1); /* Enable CHOP clk */ + /* ISINK3 */ + pmic_set_register_value(PMIC_RG_DRV_ISINK3_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_RG_DRV_ISINK3_CK_CKSEL, 0x1); /* Freq = 1Mhz for Backlight */ + pmic_set_register_value(PMIC_ISINK_CH3_STEP, ISINK_3); /* 24mA */ + pmic_set_register_value(PMIC_ISINK_CHOP3_EN, 0x1); /* Enable CHOP clk */ + /* ISINK4 */ + pmic_set_register_value(PMIC_RG_DRV_ISINK4_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_RG_DRV_ISINK4_CK_CKSEL, 0x1); /* Freq = 1Mhz for Backlight */ + pmic_set_register_value(PMIC_ISINK_CH4_MODE, ISINK_PWM_MODE); + pmic_set_register_value(PMIC_ISINK_CH4_STEP, ISINK_5); /* 24mA */ + pmic_set_register_value(PMIC_ISINK_SFSTR4_EN, 0x0); /* Disable soft start */ + pmic_set_register_value(PMIC_ISINK_PHASE4_DLY_EN, 0x1); /* Enable phase delay */ + pmic_set_register_value(PMIC_ISINK_CHOP4_EN, 0x1); /* Enable CHOP clk */ + /* ISINK5 */ + pmic_set_register_value(PMIC_RG_DRV_ISINK5_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_RG_DRV_ISINK5_CK_CKSEL, 0x1); /* Freq = 1Mhz for Backlight */ + pmic_set_register_value(PMIC_ISINK_CH5_MODE, ISINK_PWM_MODE); + pmic_set_register_value(PMIC_ISINK_CH5_STEP, ISINK_3); /* 24mA */ + pmic_set_register_value(PMIC_ISINK_SFSTR5_EN, 0x0); /* Disable soft start */ + pmic_set_register_value(PMIC_ISINK_PHASE5_DLY_EN, 0x1); /* Enable phase delay */ + pmic_set_register_value(PMIC_ISINK_CHOP5_EN, 0x1); /* Enable CHOP clk */ + /* ISINK6 */ + pmic_set_register_value(PMIC_RG_DRV_ISINK6_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_RG_DRV_ISINK6_CK_CKSEL, 0x1); /* Freq = 1Mhz for Backlight */ + pmic_set_register_value(PMIC_ISINK_CH6_STEP, ISINK_3); /* 24mA */ + pmic_set_register_value(PMIC_ISINK_CHOP6_EN, 0x1); /* Enable CHOP clk */ + /* ISINK7 */ + pmic_set_register_value(PMIC_RG_DRV_ISINK7_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_RG_DRV_ISINK7_CK_CKSEL, 0x1); /* Freq = 1Mhz for Backlight */ + pmic_set_register_value(PMIC_ISINK_CH7_STEP, ISINK_3); /* 24mA */ + pmic_set_register_value(PMIC_ISINK_CHOP7_EN, 0x1); /* Enable CHOP clk */ + backlight_init_flag = true; + } + + if (level) { + level = brightness_mapping(tmp_level); + if (level == ERROR_BL_LEVEL) + level = 255; + if (level == 255) + level = PMIC_BACKLIGHT_LEVEL; + else + level = ((level * PMIC_BACKLIGHT_LEVEL) / 255) + 1; + + LEDS_DEBUG("[LED]Level Mapping = %d\n", level); + LEDS_DEBUG("[LED]ISINK DIM Duty = %d\n", duty_mapping[level - 1]); + LEDS_DEBUG("[LED]ISINK Current = %d\n", current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, + duty_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, + duty_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_DIM4_DUTY, + duty_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_DIM5_DUTY, + duty_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_CH0_STEP, + current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_CH1_STEP, + current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_CH2_STEP, + current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_CH3_STEP, + current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_CH4_STEP, + current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_CH5_STEP, + current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_CH6_STEP, + current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_CH7_STEP, + current_mapping[level - 1]); + pmic_set_register_value(PMIC_ISINK_DIM0_FSEL, ISINK_2M_20KHZ); /* 20Khz */ + pmic_set_register_value(PMIC_ISINK_DIM1_FSEL, ISINK_2M_20KHZ); /* 20Khz */ + pmic_set_register_value(PMIC_ISINK_DIM4_FSEL, ISINK_2M_20KHZ); /* 20Khz */ + pmic_set_register_value(PMIC_ISINK_DIM5_FSEL, ISINK_2M_20KHZ); /* 20Khz */ + pmic_set_register_value(PMIC_ISINK_CH0_EN, 0x1); /* Turn on ISINK Channel 0 */ + pmic_set_register_value(PMIC_ISINK_CH1_EN, 0x1); /* Turn on ISINK Channel 1 */ + pmic_set_register_value(PMIC_ISINK_CH2_EN, 0x1); /* Turn on ISINK Channel 2 */ + pmic_set_register_value(PMIC_ISINK_CH3_EN, 0x1); /* Turn on ISINK Channel 3 */ + pmic_set_register_value(PMIC_ISINK_CH4_EN, 0x1); /* Turn on ISINK Channel 4 */ + pmic_set_register_value(PMIC_ISINK_CH5_EN, 0x1); /* Turn on ISINK Channel 5 */ + pmic_set_register_value(PMIC_ISINK_CH6_EN, 0x1); /* Turn on ISINK Channel 6 */ + pmic_set_register_value(PMIC_ISINK_CH7_EN, 0x1); /* Turn on ISINK Channel 7 */ + } else { + pmic_set_register_value(PMIC_ISINK_CH0_EN, 0x0); /* Turn off ISINK Channel 0 */ + pmic_set_register_value(PMIC_ISINK_CH1_EN, 0x0); /* Turn off ISINK Channel 1 */ + pmic_set_register_value(PMIC_ISINK_CH2_EN, 0x0); /* Turn off ISINK Channel 2 */ + pmic_set_register_value(PMIC_ISINK_CH3_EN, 0x0); /* Turn off ISINK Channel 3 */ + pmic_set_register_value(PMIC_ISINK_CH4_EN, 0x0); /* Turn on ISINK Channel 4 */ + pmic_set_register_value(PMIC_ISINK_CH5_EN, 0x0); /* Turn on ISINK Channel 5 */ + pmic_set_register_value(PMIC_ISINK_CH6_EN, 0x0); /* Turn on ISINK Channel 6 */ + pmic_set_register_value(PMIC_ISINK_CH7_EN, 0x0); /* Turn on ISINK Channel 7 */ + } +#endif /* No Support */ + mutex_unlock(&leds_pmic_mutex); + return 0; + } else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK0) { + if ((button_flag_isink0 == 0) && (first_time == true)) { + /* button flag ==0, means this ISINK is not for button backlight */ + if (button_flag_isink1 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH1_EN, + NLED_OFF); /* sw workround for sync leds status */ + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_EN, + NLED_OFF); /* sw workround for sync leds status */ + #endif + if (button_flag_isink2 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH2_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH2_EN, + NLED_OFF); + #endif + if (button_flag_isink3 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH3_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH3_EN, + NLED_OFF); + #endif + first_time = false; + } + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_CLK_DRV_ISINK0_CK_PDN, 0); + pmic_set_register_value(PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE); + pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, 15); + pmic_set_register_value(PMIC_ISINK_DIM0_FSEL, ISINK_1KHZ); + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK0_CK_PDN, 0); + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL, 0); + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE); + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(MT6351_PMIC_ISINK_DIM0_DUTY, 15); + pmic_set_register_value(MT6351_PMIC_ISINK_DIM0_FSEL, ISINK_1KHZ); /* 1KHz */ + #endif + if (level) { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_ON); + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_EN, NLED_ON); + #endif + } else { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_EN, NLED_OFF); + #endif + } + mutex_unlock(&leds_pmic_mutex); + return 0; + } else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK1) { + if ((button_flag_isink1 == 0) && (first_time == true)) { + /* button flag ==0, means this ISINK is not for button backlight */ + if (button_flag_isink0 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH0_EN, + NLED_OFF); /* sw workround for sync leds status */ + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_EN, + NLED_OFF); /* sw workround for sync leds status */ + #endif + if (button_flag_isink2 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH2_EN, + NLED_OFF); /* sw workround for sync leds status */ + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_EN, + NLED_OFF); + #endif + if (button_flag_isink3 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH3_EN, + NLED_OFF); /* sw workround for sync leds status */ + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_EN, + NLED_OFF); + #endif + first_time = false; + } + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_CLK_DRV_ISINK1_CK_PDN, 0); + pmic_set_register_value(PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE); + pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, 15); + pmic_set_register_value(PMIC_ISINK_DIM1_FSEL, ISINK_1KHZ); + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK1_CK_PDN, 0); + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL, 0); + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE); + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(MT6351_PMIC_ISINK_DIM1_DUTY, 15); + pmic_set_register_value(MT6351_PMIC_ISINK_DIM1_FSEL, ISINK_1KHZ); /* 1KHz */ + #endif + if (level) { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_ON); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_EN, NLED_ON); + #endif + } else { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_EN, NLED_OFF); + #endif + } + mutex_unlock(&leds_pmic_mutex); + return 0; + } else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK2) { + if ((button_flag_isink2 == 0) && (first_time == true)) { + /* button flag ==0, means this ISINK is not for button backlight */ + if (button_flag_isink0 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_EN, NLED_OFF); + #endif + if (button_flag_isink1 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_EN, NLED_OFF); + #endif + if (button_flag_isink3 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH3_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_EN, NLED_OFF); + #endif + first_time = false; + } + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_CLK_DRV_ISINK2_CK_PDN, 0); + pmic_set_register_value(PMIC_ISINK_CH2_STEP, ISINK_3); /* 16mA */ + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK4_CK_PDN, 0); + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL, 0); + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_MODE, ISINK_PWM_MODE); + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(MT6351_PMIC_ISINK_DIM4_DUTY, 15); + pmic_set_register_value(MT6351_PMIC_ISINK_DIM4_FSEL, ISINK_1KHZ); /* 1KHz */ + #endif + if (level) { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH2_EN, NLED_ON); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_EN, NLED_ON); + #endif + } else { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH2_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_EN, NLED_OFF); + #endif + } + } else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK3) { + if ((button_flag_isink3 == 0) && (first_time == true)) { + /* button flag ==0, means this ISINK is not for button backlight */ + if (button_flag_isink0 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH0_EN, + NLED_OFF); /* sw workround for sync leds status */ + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH0_EN, + NLED_OFF); /* sw workround for sync leds status */ + #endif + if (button_flag_isink1 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH1_EN, + NLED_OFF); /* sw workround for sync leds status */ + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH1_EN, + NLED_OFF); + #endif + if (button_flag_isink2 == 0) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH2_EN, + NLED_OFF); /* sw workround for sync leds status */ + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH4_EN, + NLED_OFF); + #endif + first_time = false; + } + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(PMIC_CLK_DRV_ISINK3_CK_PDN, 0); + pmic_set_register_value(PMIC_ISINK_CH3_STEP, ISINK_3); /* 16mA */ + #else + pmic_set_register_value(MT6351_PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */ + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK5_CK_PDN, 0); + pmic_set_register_value(MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL, 0); + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_MODE, ISINK_PWM_MODE); + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_STEP, ISINK_3); /* 16mA */ + pmic_set_register_value(MT6351_PMIC_ISINK_DIM5_DUTY, 15); + pmic_set_register_value(MT6351_PMIC_ISINK_DIM5_FSEL, ISINK_1KHZ); /* 1KHz */ + #endif + if (level) { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH3_EN, NLED_ON); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_EN, NLED_ON); + #endif + } else { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_ISINK_CH3_EN, NLED_OFF); + #else + pmic_set_register_value(MT6351_PMIC_ISINK_CH5_EN, NLED_OFF); + #endif + } + mutex_unlock(&leds_pmic_mutex); + return 0; + } + mutex_unlock(&leds_pmic_mutex); + return -1; +} + +int mt_brightness_set_pmic_duty_store(u32 level, u32 div) +{ + return -1; +} + +int mt_mt65xx_led_set_cust(struct cust_mt65xx_led *cust, int level) +{ + struct nled_setting led_tmp_setting = { 0, 0, 0 }; + int tmp_level = level; + static bool button_flag; + unsigned int BacklightLevelSupport = + Cust_GetBacklightLevelSupport_byPWM(); + + switch (cust->mode) { + + case MT65XX_LED_MODE_PWM: + if (strcmp(cust->name, "lcd-backlight") == 0) { + bl_brightness_hal = level; + if (level == 0) { + mt_pwm_disable(cust->data, + cust->config_data.pmic_pad); + + } else { + + if (BacklightLevelSupport == + BACKLIGHT_LEVEL_PWM_256_SUPPORT) + level = brightness_mapping(tmp_level); + else + level = brightness_mapto64(tmp_level); + mt_backlight_set_pwm(cust->data, level, + bl_div_hal, + &cust->config_data); + } + bl_duty_hal = level; + + } else { + if (level == 0) { + led_tmp_setting.nled_mode = NLED_OFF; + mt_led_set_pwm(cust->data, &led_tmp_setting); + mt_pwm_disable(cust->data, + cust->config_data.pmic_pad); + } else { + led_tmp_setting.nled_mode = NLED_ON; + mt_led_set_pwm(cust->data, &led_tmp_setting); + } + } + return 1; + + case MT65XX_LED_MODE_GPIO: + LEDS_DEBUG("brightness_set_cust:go GPIO mode!!!!!\n"); + return ((cust_set_brightness) (cust->data)) (level); + + case MT65XX_LED_MODE_PMIC: + /* for button baclight used SINK channel, when set button ISINK, + don't do disable other ISINK channel */ + if ((strcmp(cust->name, "button-backlight") == 0)) { + if (button_flag == false) { + switch (cust->data) { + case MT65XX_LED_PMIC_NLED_ISINK0: + button_flag_isink0 = 1; + break; + case MT65XX_LED_PMIC_NLED_ISINK1: + button_flag_isink1 = 1; + break; + case MT65XX_LED_PMIC_NLED_ISINK2: + button_flag_isink2 = 1; + break; + case MT65XX_LED_PMIC_NLED_ISINK3: + button_flag_isink3 = 1; + break; + default: + break; + } + button_flag = true; + } + } + return mt_brightness_set_pmic(cust->data, level, bl_div_hal); + + case MT65XX_LED_MODE_CUST_LCM: + if (strcmp(cust->name, "lcd-backlight") == 0) + bl_brightness_hal = level; + LEDS_DEBUG("brightness_set_cust:backlight control by LCM\n"); + /* warning for this API revork */ + return ((cust_brightness_set) (cust->data)) (level, bl_div_hal); + + case MT65XX_LED_MODE_CUST_BLS_PWM: + if (strcmp(cust->name, "lcd-backlight") == 0) + bl_brightness_hal = level; + return ((cust_set_brightness) (cust->data)) (level); + + case MT65XX_LED_MODE_NONE: + default: + break; + } + return -1; +} + +void mt_mt65xx_led_work(struct work_struct *work) +{ + struct mt65xx_led_data *led_data = + container_of(work, struct mt65xx_led_data, work); + + LEDS_DEBUG("%s:%d\n", led_data->cust.name, led_data->level); + mutex_lock(&leds_mutex); + mt_mt65xx_led_set_cust(&led_data->cust, led_data->level); + mutex_unlock(&leds_mutex); +} + +void mt_mt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness level) +{ + struct mt65xx_led_data *led_data = + container_of(led_cdev, struct mt65xx_led_data, cdev); + /* unsigned long flags; */ + /* spin_lock_irqsave(&leds_lock, flags); */ + +#ifdef CONFIG_MTK_AAL_SUPPORT + if (led_data->level != level) { + led_data->level = level; + if (strcmp(led_data->cust.name, "lcd-backlight") != 0) { + LEDS_DEBUG("Set NLED directly %d at time %lu\n", + led_data->level, jiffies); + schedule_work(&led_data->work); + } else { + if (level != 0 + && level * CONFIG_LIGHTNESS_MAPPING_VALUE < 255) { + level = 1; + } else { + level = + (level * CONFIG_LIGHTNESS_MAPPING_VALUE) / + 255; + } + /* LEDS_DEBUG + ("Set Backlight directly %d at time %lu, mapping level is %d\n", + led_data->level, jiffies, level); */ + backlight_debug_log(led_data->level, level); + /* mt_mt65xx_led_set_cust(&led_data->cust, led_data->level); */ + disp_aal_notify_backlight_changed((((1 << + MT_LED_INTERNAL_LEVEL_BIT_CNT) + - 1) * level + + 127) / 255); + } + } +#else + /* do something only when level is changed */ + if (led_data->level != level) { + led_data->level = level; + if (strcmp(led_data->cust.name, "lcd-backlight") != 0) { + LEDS_DEBUG("Set NLED directly %d at time %lu\n", + led_data->level, jiffies); + schedule_work(&led_data->work); + } else { + if (level != 0 + && level * CONFIG_LIGHTNESS_MAPPING_VALUE < 255) { + level = 1; + } else { + level = + (level * CONFIG_LIGHTNESS_MAPPING_VALUE) / + 255; + } + /* LEDS_DEBUG + ("Set Backlight directly %d at time %lu, mapping level is %d\n", + led_data->level, jiffies, level); */ + backlight_debug_log(led_data->level, level); + if (MT65XX_LED_MODE_CUST_BLS_PWM == led_data->cust.mode) { + mt_mt65xx_led_set_cust(&led_data->cust, + ((((1 << + MT_LED_INTERNAL_LEVEL_BIT_CNT) + - 1) * level + + 127) / 255)); + } else { + mt_mt65xx_led_set_cust(&led_data->cust, level); + } + } + } + /* spin_unlock_irqrestore(&leds_lock, flags); */ +#endif +/* if(0!=aee_kernel_Powerkey_is_press()) */ +/* aee_kernel_wdt_kick_Powkey_api("mt_mt65xx_led_set",WDT_SETBY_Backlight); */ +} + +int mt_mt65xx_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, unsigned long *delay_off) +{ + struct mt65xx_led_data *led_data = + container_of(led_cdev, struct mt65xx_led_data, cdev); + static int got_wake_lock; + struct nled_setting nled_tmp_setting = { 0, 0, 0 }; + + /* only allow software blink when delay_on or delay_off changed */ + if (*delay_on != led_data->delay_on + || *delay_off != led_data->delay_off) { + led_data->delay_on = *delay_on; + led_data->delay_off = *delay_off; + if (led_data->delay_on && led_data->delay_off) { /* enable blink */ + led_data->level = 255; /* when enable blink then to set the level (255) */ + /* AP PWM all support OLD mode */ + if (led_data->cust.mode == MT65XX_LED_MODE_PWM) { + nled_tmp_setting.nled_mode = NLED_BLINK; + nled_tmp_setting.blink_off_time = + led_data->delay_off; + nled_tmp_setting.blink_on_time = + led_data->delay_on; + mt_led_set_pwm(led_data->cust.data, + &nled_tmp_setting); + return 0; + } else if ((led_data->cust.mode == MT65XX_LED_MODE_PMIC) + && (led_data->cust.data == + MT65XX_LED_PMIC_NLED_ISINK0 + || led_data->cust.data == + MT65XX_LED_PMIC_NLED_ISINK1 + || led_data->cust.data == + MT65XX_LED_PMIC_NLED_ISINK2 + || led_data->cust.data == + MT65XX_LED_PMIC_NLED_ISINK3)) { + nled_tmp_setting.nled_mode = NLED_BLINK; + nled_tmp_setting.blink_off_time = + led_data->delay_off; + nled_tmp_setting.blink_on_time = + led_data->delay_on; + mt_led_blink_pmic(led_data->cust.data, + &nled_tmp_setting); + return 0; + } else if (!got_wake_lock) { + wake_lock(&leds_suspend_lock); + got_wake_lock = 1; + } + } else if (!led_data->delay_on && !led_data->delay_off) { /* disable blink */ + /* AP PWM all support OLD mode */ + if (led_data->cust.mode == MT65XX_LED_MODE_PWM) { + nled_tmp_setting.nled_mode = NLED_OFF; + mt_led_set_pwm(led_data->cust.data, + &nled_tmp_setting); + return 0; + } else if ((led_data->cust.mode == MT65XX_LED_MODE_PMIC) + && (led_data->cust.data == + MT65XX_LED_PMIC_NLED_ISINK0 + || led_data->cust.data == + MT65XX_LED_PMIC_NLED_ISINK1 + || led_data->cust.data == + MT65XX_LED_PMIC_NLED_ISINK2 + || led_data->cust.data == + MT65XX_LED_PMIC_NLED_ISINK3)) { + mt_brightness_set_pmic(led_data->cust.data, 0, + 0); + return 0; + } else if (got_wake_lock) { + wake_unlock(&leds_suspend_lock); + got_wake_lock = 0; + } + } + return -1; + } + /* delay_on and delay_off are not changed */ + return 0; +} diff --git a/drivers/misc/mediatek/leds/mt6755/leds_hal.h b/drivers/misc/mediatek/leds/mt6755/leds_hal.h new file mode 100644 index 0000000000000000000000000000000000000000..7614b8d2b9b30b27627b7e1ab8871837be749324 --- /dev/null +++ b/drivers/misc/mediatek/leds/mt6755/leds_hal.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _LEDS_HAL_H +#define _LEDS_HAL_H + +#include "leds_sw.h" + +/**************************************************************************** + * LED HAL functions + ***************************************************************************/ +extern void mt_leds_wake_lock_init(void); +extern unsigned int mt_get_bl_brightness(void); +extern unsigned int mt_get_bl_duty(void); +extern unsigned int mt_get_bl_div(void); +extern unsigned int mt_get_bl_frequency(void); +extern unsigned int *mt_get_div_array(void); +extern void mt_set_bl_duty(unsigned int level); +extern void mt_set_bl_div(unsigned int div); +extern void mt_set_bl_frequency(unsigned int freq); +extern void mt_led_pwm_disable(int pwm_num); +extern int mt_brightness_set_pmic_duty_store(u32 level, u32 div); +extern void mt_backlight_set_pwm_duty(int pwm_num, u32 level, u32 div, + struct PWM_config *config_data); +extern void mt_backlight_set_pwm_div(int pwm_num, u32 level, u32 div, + struct PWM_config *config_data); +extern void mt_backlight_get_pwm_fsel(unsigned int bl_div, + unsigned int *bl_frequency); +extern void mt_store_pwm_register(unsigned int addr, unsigned int value); +extern unsigned int mt_show_pwm_register(unsigned int addr); +extern int mt_led_set_pwm(int pwm_num, struct nled_setting *led); +extern int mt_led_blink_pmic(enum mt65xx_led_pmic pmic_type, + struct nled_setting *led); +extern int mt_backlight_set_pwm(int pwm_num, u32 level, u32 div, + struct PWM_config *config_data); +extern int mt_brightness_set_pmic(enum mt65xx_led_pmic pmic_type, u32 level, + u32 div); +extern int mt_mt65xx_led_set_cust(struct cust_mt65xx_led *cust, int level); +extern void mt_mt65xx_led_work(struct work_struct *work); +extern void mt_mt65xx_led_set(struct led_classdev *led_cdev, + enum led_brightness level); +extern int mt_mt65xx_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off); + +extern struct cust_mt65xx_led *mt_get_cust_led_list(void); + +extern int mtkfb_set_backlight_level(unsigned int level); +#endif diff --git a/drivers/misc/mediatek/leds/mt6755/leds_sw.h b/drivers/misc/mediatek/leds/mt6755/leds_sw.h new file mode 100644 index 0000000000000000000000000000000000000000..b1b28164eb43afe7a77d96a62dcadfdb04ed0117 --- /dev/null +++ b/drivers/misc/mediatek/leds/mt6755/leds_sw.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _LEDS_SW_H +#define _LEDS_SW_H + +/****************************************************************************** + * LED & Backlight type defination + *****************************************************************************/ + +enum mt65xx_led_type { + MT65XX_LED_TYPE_RED = 0, + MT65XX_LED_TYPE_GREEN, + MT65XX_LED_TYPE_BLUE, + MT65XX_LED_TYPE_JOGBALL, + MT65XX_LED_TYPE_KEYBOARD, + MT65XX_LED_TYPE_BUTTON, + MT65XX_LED_TYPE_LCD, + MT65XX_LED_TYPE_TOTAL, +}; + +enum mt65xx_led_mode { + MT65XX_LED_MODE_NONE, + MT65XX_LED_MODE_PWM, + MT65XX_LED_MODE_GPIO, + MT65XX_LED_MODE_PMIC, + MT65XX_LED_MODE_CUST_LCM, + MT65XX_LED_MODE_CUST_BLS_PWM +}; + +/****************************************************************************** + * for backlight + *****************************************************************************/ + +/* backlight call back function */ +typedef int (*cust_brightness_set) (int level, int div); +typedef int (*cust_set_brightness) (int level); + +/* 10bit backlight level */ +#define LED_INCREASE_LED_LEVEL_MTKPATCH +#ifdef LED_INCREASE_LED_LEVEL_MTKPATCH +#define MT_LED_INTERNAL_LEVEL_BIT_CNT 10 +#endif + +/****************************************************************************** + * for PMIC + *****************************************************************************/ + +enum mt65xx_led_pmic { + MT65XX_LED_PMIC_LCD_ISINK = 0, + MT65XX_LED_PMIC_NLED_ISINK_MIN = MT65XX_LED_PMIC_LCD_ISINK, + MT65XX_LED_PMIC_NLED_ISINK0, + MT65XX_LED_PMIC_NLED_ISINK1, + MT65XX_LED_PMIC_NLED_ISINK2, + MT65XX_LED_PMIC_NLED_ISINK3, + MT65XX_LED_PMIC_NLED_ISINK_MAX, +}; + +enum MT65XX_PMIC_ISINK_MODE { + ISINK_PWM_MODE = 0, + ISINK_BREATH_MODE = 1, + ISINK_REGISTER_MODE = 2 +}; + +enum MT65XX_PMIC_ISINK_STEP { + ISINK_0 = 0, /* 4mA */ + ISINK_1 = 1, /* 8mA */ + ISINK_2 = 2, /* 12mA */ + ISINK_3 = 3, /* 16mA */ + ISINK_4 = 4, /* 20mA */ + ISINK_5 = 5 /* 24mA */ +}; + +enum MT65XX_PMIC_ISINK_FSEL { + /* 32K clock */ + ISINK_1KHZ = 0, + ISINK_200HZ = 4, + ISINK_5HZ = 199, + ISINK_2HZ = 499, + ISINK_1HZ = 999, + ISINK_05HZ = 1999, + ISINK_02HZ = 4999, + ISINK_01HZ = 9999, + /* 2M clock */ + ISINK_2M_20KHZ = 2, + ISINK_2M_1KHZ = 61, + ISINK_2M_200HZ = 311, + ISINK_2M_5HZ = 12499, + ISINK_2M_2HZ = 31249, + ISINK_2M_1HZ = 62499 +}; + +/****************************************************************************** + * for PWM + *****************************************************************************/ + +#define MIN_FRE_OLD_PWM 32 /* the min frequence when use old mode pwm by kHz */ +#define BACKLIGHT_LEVEL_PWM_64_FIFO_MODE_SUPPORT 64 +#define BACKLIGHT_LEVEL_PWM_256_SUPPORT 256 +#define BACKLIGHT_LEVEL_PWM_MODE_CONFIG BACKLIGHT_LEVEL_PWM_256_SUPPORT +static inline unsigned int Cust_GetBacklightLevelSupport_byPWM(void) +{ + return BACKLIGHT_LEVEL_PWM_MODE_CONFIG; +} + +static inline unsigned int brightness_mapping(unsigned int level) +{ + unsigned int mapped_level; + + mapped_level = level; + return mapped_level; +} + +struct PWM_config { + int clock_source; + int div; + int low_duration; + int High_duration; + bool pmic_pad; +}; + +/**************************************************************************** + * sw data structures + ***************************************************************************/ + +/** + * led customization data structure + * name : must the same as lights HAL + * mode : control mode + * data : + * PWM: pwm number + * GPIO: gpio id + * PMIC: enum mt65xx_led_pmic + * CUST: custom set brightness function pointer + * config_data: pwm config data + */ +struct cust_mt65xx_led { + char *name; + enum mt65xx_led_mode mode; + long data; + struct PWM_config config_data; +}; + +/** + * led device node structure with mtk extentions + * cdev: common led device structure + * cust: customization data from device tree + * work: workqueue for specialfied led device + * level: brightness level + * delay_on: on time if led is blinking + * delay_off: off time if led is blinking + */ +struct mt65xx_led_data { + struct led_classdev cdev; + struct cust_mt65xx_led cust; + struct work_struct work; + int level; + int delay_on; + int delay_off; +}; + +/** + * LED Variable Settings + * nled_mode: 0, off; 1, on; 2, blink + * blink_on_time: on time if led is blinking + * blink_off_time: off time if led is blinking + */ +#define NLED_OFF 0 +#define NLED_ON 1 +#define NLED_BLINK 2 + +struct nled_setting { + u8 nled_mode; + u32 blink_on_time; + u32 blink_off_time; +}; + +#endif /* _LEDS_SW_H */ diff --git a/drivers/misc/mediatek/m4u/mt6755/Makefile b/drivers/misc/mediatek/m4u/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..22a57ca264b1dac41d602e6ec55ece12ac89428f --- /dev/null +++ b/drivers/misc/mediatek/m4u/mt6755/Makefile @@ -0,0 +1,25 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += -I$(srctree)/drivers/staging/android/ion +ccflags-y += -I$(srctree)/drivers/misc/mediatek/gud/$(MTK_PLATFORM)/gud/MobiCoreKernelApi/public +ccflags-y += -I$(srctree)/drivers/misc/mediatek/gud/$(MTK_PLATFORM)/gud/MobiCoreKernelApi/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/trustzone/m4u +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/mach +ccflags-y += -I$(srctree)/drivers/misc/mediatek/irq/$(MTK_PLATFORM)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mmp/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/m4u/2.0 + +obj-$(CONFIG_MTK_M4U) += m4u_hw.o diff --git a/drivers/misc/mediatek/m4u/mt6755/m4u.h b/drivers/misc/mediatek/m4u/mt6755/m4u.h new file mode 100644 index 0000000000000000000000000000000000000000..49a9b1d0ed366c56d39aad64e9cca1cc4d4d8ff3 --- /dev/null +++ b/drivers/misc/mediatek/m4u/mt6755/m4u.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __M4U_H__ +#define __M4U_H__ + +#include "../2.0/m4u_v2.h" + +#endif + diff --git a/drivers/misc/mediatek/m4u/mt6755/m4u_hw.c b/drivers/misc/mediatek/m4u/mt6755/m4u_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..e2cc69b22139f3a4fa2c8ddf60f1f672751ab575 --- /dev/null +++ b/drivers/misc/mediatek/m4u/mt6755/m4u_hw.c @@ -0,0 +1,2428 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + +#include "m4u_priv.h" +#include "m4u_platform.h" +#include "m4u_hw.h" + +#include +#include + +#include + +static m4u_domain_t gM4uDomain; + +static unsigned long gM4UBaseAddr[TOTAL_M4U_NUM]; +static unsigned long gLarbBaseAddr[SMI_LARB_NR]; +static unsigned long gPericfgBaseAddr; +static unsigned int gM4UTagCount[] = {64}; + +static M4U_RANGE_DES_T gM4u0_seq[M4U0_SEQ_NR] = {{0} }; +/* static M4U_RANGE_DES_T gM4u1_seq[M4U1_SEQ_NR] = {{0} }; */ +static M4U_RANGE_DES_T *gM4USeq[] = {gM4u0_seq, NULL}; +static M4U_MAU_STATUS_T gM4u0_mau[M4U0_MAU_NR] = {{0} }; +static unsigned int gMAU_candidate_id = M4U0_MAU_NR - 1; + +static DEFINE_MUTEX(gM4u_seq_mutex); + +static M4U_PROG_DIST_T gM4U0_prog_pfh[M4U0_PROG_PFH_NR] = {{0} }; +/* static M4U_PROG_DIST_T gM4u1_prog_pfh[M4U0_PROG_PFH_NR] = {{0} }; */ +static M4U_PROG_DIST_T *gM4UProgPfh[] = {gM4U0_prog_pfh, NULL}; + +static DEFINE_MUTEX(gM4u_prog_pfh_mutex); + +#define TF_PROTECT_BUFFER_SIZE 128L + +int gM4U_L2_enable = 1; +int gM4U_4G_DRAM_Mode = 0; + +static spinlock_t gM4u_reg_lock; +int gM4u_port_num = M4U_PORT_UNKNOWN; + +static int _is_display_port(int m4u_port) +{ + if (M4U_PORT_DISP_OVL0 == m4u_port || + M4U_PORT_DISP_OVL1 == m4u_port || + M4U_PORT_DISP_2L_OVL0 == m4u_port || + M4U_PORT_DISP_2L_OVL1 == m4u_port || + M4U_PORT_DISP_RDMA0 == m4u_port || M4U_PORT_DISP_WDMA0 == m4u_port) + return 1; + + return 0; +} + +int m4u_invalid_tlb(int m4u_id, int L2_en, int isInvAll, unsigned int mva_start, unsigned int mva_end) +{ + unsigned int reg = 0; + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + + if (mva_start >= mva_end) + isInvAll = 1; + + if (!isInvAll) { + mva_start = round_down(mva_start, SZ_4K); + mva_end = round_up(mva_end, SZ_4K); + } + + if (L2_en) + reg = F_MMU_INV_EN_L2; + + reg |= F_MMU_INV_EN_L1; + + spin_lock(&gM4u_reg_lock); + + M4U_WriteReg32(m4u_base, REG_INVLID_SEL, reg); + + if (isInvAll) + M4U_WriteReg32(m4u_base, REG_MMU_INVLD, F_MMU_INV_ALL); + else { + /* + unsigned int type_start = m4u_get_pt_type(gPgd_nonsec, mva_start); + unsigned int type_end = m4u_get_pt_type(gPgd_nonsec, mva_end); + unsigned int type = max(type_start, type_end); + unsigned int alignment; + if(type > MMU_PT_TYPE_SUPERSECTION) + type = MMU_PT_TYPE_SUPERSECTION; + alignment = m4u_get_pt_type_size(type) - 1; + + M4U_WriteReg32(m4u_base, REG_MMU_INVLD_SA ,mva_start & (~alignment)); + M4U_WriteReg32(m4u_base, REG_MMU_INVLD_EA, mva_end | alignment); + M4U_WriteReg32(m4u_base, REG_MMU_INVLD, F_MMU_INV_RANGE); + */ + + M4U_WriteReg32(m4u_base, REG_MMU_INVLD_SA , mva_start); + M4U_WriteReg32(m4u_base, REG_MMU_INVLD_EA, mva_end); + M4U_WriteReg32(m4u_base, REG_MMU_INVLD, F_MMU_INV_RANGE); + } + + if (!isInvAll) { + while (!M4U_ReadReg32(m4u_base, REG_MMU_CPE_DONE)) + ; + M4U_WriteReg32(m4u_base, REG_MMU_CPE_DONE, 0); + } + + spin_unlock(&gM4u_reg_lock); + + return 0; +} + +static void m4u_invalid_tlb_all(int m4u_id) +{ + m4u_invalid_tlb(m4u_id, gM4U_L2_enable, 1, 0, 0); +} + +void m4u_invalid_tlb_by_range(m4u_domain_t *m4u_domain, unsigned int mva_start, unsigned int mva_end) +{ + int i; + /* to-do: should get m4u connected to domain here */ + for (i = 0; i < TOTAL_M4U_NUM; i++) + m4u_invalid_tlb(i, gM4U_L2_enable, 0, mva_start, mva_end); + /* m4u_invalid_tlb_all(0); */ + /* m4u_invalid_tlb_all(1); */ +} + +static int __m4u_dump_rs_info(unsigned int va[], unsigned int pa[], unsigned int st[], unsigned int pte[]) +{ + int i; + + M4ULOG_MID("m4u dump RS information =====>\n"); + M4ULOG_MID("id mva valid port-id pa pte larb w/r other-status\n"); + for (i = 0; i < MMU_TOTAL_RS_NR; i++) { + M4ULOG_MID("%d: 0x%8x %5d 0x%3x 0x%8x 0x%8x %d %d 0x%3x\n", i, + F_MMU_RSx_VA_GET(va[i]), F_MMU_RSx_VA_VALID(va[i]), + F_MMU_RSx_VA_PID(va[i]), pa[i], pte[i], F_MMU_RSx_ST_LID(st[i]), + F_MMU_RSx_ST_WRT(st[i]), F_MMU_RSx_ST_OTHER(st[i])); + } + M4ULOG_MID("m4u dump RS information done =====>\n"); + return 0; +} + +static int m4u_dump_rs_info(int m4u_index, int m4u_slave_id) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_index]; + int i; + unsigned int va[MMU_TOTAL_RS_NR], pa[MMU_TOTAL_RS_NR], st[MMU_TOTAL_RS_NR], pte[MMU_TOTAL_RS_NR]; + + for (i = 0; i < MMU_TOTAL_RS_NR; i++) { + va[i] = COM_ReadReg32((m4u_base+REG_MMU_RSx_VA(m4u_slave_id, i))); + pa[i] = COM_ReadReg32((m4u_base+REG_MMU_RSx_PA(m4u_slave_id, i))); + st[i] = COM_ReadReg32((m4u_base+REG_MMU_RSx_ST(m4u_slave_id, i))); + pte[i] = COM_ReadReg32((m4u_base+REG_MMU_RSx_2ND_BASE(m4u_slave_id, i))); + } + + M4ULOG_MID("m4u dump RS information index: %d=====>\n", m4u_slave_id); + __m4u_dump_rs_info(va, pa, st, pte); + M4ULOG_MID("m4u dump RS information done =====>\n"); + return 0; +} + +static inline void m4u_clear_intr(unsigned int m4u_id) +{ + m4uHw_set_field_by_mask(gM4UBaseAddr[m4u_id], REG_MMU_INT_L2_CONTROL, F_INT_L2_CLR_BIT, F_INT_L2_CLR_BIT); +} + +static inline void m4u_enable_intr(unsigned int m4u_id) +{ + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_INT_L2_CONTROL, 0x6f); + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_INT_MAIN_CONTROL, 0xffffffff); +} + +static inline void m4u_disable_intr(unsigned int m4u_id) +{ + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_INT_L2_CONTROL, 0); + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_INT_MAIN_CONTROL, 0); +} + +static inline void m4u_intr_modify_all(unsigned long enable) +{ + int i; + + for (i = 0; i < TOTAL_M4U_NUM; i++) + if (enable) + m4u_enable_intr(i); + else + m4u_disable_intr(i); +} + +struct mau_config_info { + int m4u_id; + int m4u_slave_id; + int mau_set; + unsigned int start; + unsigned int end; + unsigned int port_mask; + unsigned int larb_mask; + unsigned int write_monitor;/* :1; */ + unsigned int virt;/* :1; */ + unsigned int io;/* :1; */ + unsigned int start_bit32;/* :1; */ + unsigned int end_bit32;/* :1; */ +}; + +/***********************************************************/ +/** +* @param m4u_id -- IOMMU main id +* @param m4u_slave_id -- IOMMU slave id +* @param mau_set -- mau set/entry (3 mau set per iommu) +* @param wr -- write monitor enable: 0 for read, 1 for write + NOTES: cannot monitor read and write using one mau set!! +* @param vir -- virtual monitor enable ? (if enable we will monitor mva, or else monitor PA) +* @param io -- I/O use mau at input or output of RS. 0 for input, 1 for output + input: mau @ RS input, can monitor mva or pa (bypass m4u); + output:mau @ RS output, can monitor pa to emi(bypass m4u, or after mva translation) +* @param bit32 -- enable bit32 monitor? +* @param start -- start address of monitor (can be any address without alignment) +* @param end -- end address of monitor (can be any address without alignment) +* @param port -- port mask or AXI_ID[4:0] mask +* @param larb -- larb[0..7] mask or AXI_ID[7:5] mask +* +* @return +* @remark + monitor range is [start, end) +* @see +* @author K Zhang @date 2013/11/13 +************************************************************/ +int mau_start_monitor(int m4u_id, int m4u_slave_id, int mau_set, + int wr, int vir, int io, int bit32, + unsigned int start, unsigned int end, unsigned int port_mask, unsigned int larb_mask) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + + if (0 == m4u_base) + return -1; + + M4U_WriteReg32(m4u_base, REG_MMU_MAU_START(m4u_slave_id, mau_set), start); + M4U_WriteReg32(m4u_base, REG_MMU_MAU_START_BIT32(m4u_slave_id, mau_set), !!(bit32)); + M4U_WriteReg32(m4u_base, REG_MMU_MAU_END(m4u_slave_id, mau_set), end); + M4U_WriteReg32(m4u_base, REG_MMU_MAU_END_BIT32(m4u_slave_id, mau_set), !!(bit32)); + + M4U_WriteReg32(m4u_base, REG_MMU_MAU_PORT_EN(m4u_slave_id, mau_set), port_mask); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_MAU_LARB_EN(m4u_slave_id), + F_MAU_LARB_MSK(mau_set), F_MAU_LARB_VAL(mau_set, larb_mask)); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_MAU_IO(m4u_slave_id), + F_MAU_BIT_VAL(1, mau_set), F_MAU_BIT_VAL(io, mau_set)); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_MAU_RW(m4u_slave_id), + F_MAU_BIT_VAL(1, mau_set), F_MAU_BIT_VAL(wr, mau_set)); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_MAU_VA(m4u_slave_id), + F_MAU_BIT_VAL(1, mau_set), F_MAU_BIT_VAL(vir, mau_set)); + + return 0; +} + +int config_mau(M4U_MAU_STRUCT mau) +{ + int i; + int free_id = -1; + int m4u_id = m4u_port_2_m4u_id(mau.port); + int larb = m4u_port_2_larb_id(mau.port); + unsigned int MVAStart = mau.mva; + unsigned int MVAEnd = mau.mva + mau.size; + + if (0 != m4u_id) + return -1; + + for (i = 0; i < M4U0_MAU_NR; i++) { + if (0 != gM4u0_mau[i].Enabled) { + if (MVAStart >= gM4u0_mau[i].MVAStart && MVAEnd <= gM4u0_mau[i].MVAEnd) { /* no overlap */ + if (mau.enable == 0) { + gM4u0_mau[i].Enabled = 0; + mau_start_monitor(0, 0, i, 0, 0, 0, 0, 0, 0, 0, 0); + continue; + } + } + } else { + free_id = i; + } + } + + if (mau.enable == 0) + return 0; + + if (free_id == -1) { + if (mau.force == 0) + return -1; + } + else { + free_id = gMAU_candidate_id; + if (0 == gMAU_candidate_id) + gMAU_candidate_id = M4U0_MAU_NR - 1; + else + gMAU_candidate_id--; + } + + gM4u0_mau[free_id].Enabled = 1; + gM4u0_mau[free_id].MVAStart = MVAStart; + gM4u0_mau[free_id].MVAEnd = MVAEnd; + gM4u0_mau[free_id].port = mau.port; + + mau_start_monitor(m4u_id, larb_2_m4u_slave_id(larb), free_id, (int)mau.write, + 1, 0, 0, MVAStart, MVAEnd, 1 << m4u_port_2_larb_port(mau.port), 1 << larb); + return free_id; +} + +/* notes: you must fill cfg->m4u_id/m4u_slave_id/mau_set before call this func. */ +int mau_get_config_info(struct mau_config_info *cfg) +{ + int m4u_id = cfg->m4u_id; + int m4u_slave_id = cfg->m4u_slave_id; + int mau_set = cfg->mau_set; + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + + cfg->start = M4U_ReadReg32(m4u_base, REG_MMU_MAU_START(m4u_slave_id, mau_set)); + cfg->end = M4U_ReadReg32(m4u_base, REG_MMU_MAU_END(m4u_slave_id, mau_set)); + cfg->start_bit32 = M4U_ReadReg32(m4u_base, REG_MMU_MAU_START_BIT32(m4u_slave_id, mau_set)); + cfg->end_bit32 = M4U_ReadReg32(m4u_base, REG_MMU_MAU_START_BIT32(m4u_slave_id, mau_set)); + cfg->port_mask = M4U_ReadReg32(m4u_base, REG_MMU_MAU_PORT_EN(m4u_slave_id, mau_set)); + cfg->larb_mask = m4uHw_get_field_by_mask(m4u_base, REG_MMU_MAU_LARB_EN(m4u_slave_id), F_MAU_LARB_MSK(mau_set)); + + cfg->io = !!(m4uHw_get_field_by_mask(m4u_base, REG_MMU_MAU_IO(m4u_slave_id), F_MAU_BIT_VAL(1, mau_set))); + + cfg->write_monitor = + !!m4uHw_get_field_by_mask(m4u_base, REG_MMU_MAU_RW(m4u_slave_id), F_MAU_BIT_VAL(1, mau_set)); + + cfg->virt = !!m4uHw_get_field_by_mask(m4u_base, REG_MMU_MAU_VA(m4u_slave_id), F_MAU_BIT_VAL(1, mau_set)); + + return 0; +} + +int __mau_dump_status(int m4u_id, int m4u_slave_id, int mau) +{ + unsigned long m4u_base; + unsigned int status; + unsigned int assert_id, assert_addr, assert_b32; + int larb, port; + struct mau_config_info mau_cfg; + + m4u_base = gM4UBaseAddr[m4u_id]; + status = M4U_ReadReg32(m4u_base, REG_MMU_MAU_ASSERT_ST(m4u_slave_id)); + + if (status & (1 << mau)) { + M4ULOG_HIGH("mau_assert in set %d\n", mau); + assert_id = M4U_ReadReg32(m4u_base, REG_MMU_MAU_ASSERT_ID(m4u_slave_id, mau)); + assert_addr = M4U_ReadReg32(m4u_base, REG_MMU_MAU_ADDR(m4u_slave_id, mau)); + assert_b32 = M4U_ReadReg32(m4u_base, REG_MMU_MAU_ADDR_BIT32(m4u_slave_id, mau)); + larb = F_MMU_MAU_ASSERT_ID_LARB(assert_id); + port = F_MMU_MAU_ASSERT_ID_PORT(assert_id); + M4ULOG_HIGH("id=0x%x(%s),addr=0x%x,b32=0x%x\n", assert_id, + m4u_get_port_name(larb_port_2_m4u_port(larb, port)), assert_addr, assert_b32); + + M4U_WriteReg32(m4u_base, REG_MMU_MAU_CLR(m4u_slave_id), (1 << mau)); + M4U_WriteReg32(m4u_base, REG_MMU_MAU_CLR(m4u_slave_id), 0); + + mau_cfg.m4u_id = m4u_id; + mau_cfg.m4u_slave_id = m4u_slave_id; + mau_cfg.mau_set = mau; + mau_get_config_info(&mau_cfg); + M4ULOG_HIGH("mau_cfg: start=0x%x,end=0x%x,virt(%d),io(%d),wr(%d),s_b32(%d),e_b32(%d)\n", + mau_cfg.start, mau_cfg.end, mau_cfg.virt, mau_cfg.io, + mau_cfg.write_monitor, mau_cfg.start_bit32, mau_cfg.end_bit32); + } else + M4ULOG_MID("mau no assert in set %d\n", mau); + + return 0; +} + +int mau_dump_status(int m4u_id, int m4u_slave_id) +{ + int i; + + for (i = 0; i < MAU_NR_PER_M4U_SLAVE; i++) + __mau_dump_status(m4u_id, m4u_slave_id, i); + + return 0; +} + +int m4u_dump_reg(int m4u_index, unsigned int start) +{ + int i; + + M4UINFO("Register Start =======\n"); + for (i = 0; i < 368 / 8; i += 4) { + M4UINFO("+0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", start + 8 * i, + M4U_ReadReg32(gM4UBaseAddr[m4u_index], start + 8 * i + 4 * 0), + M4U_ReadReg32(gM4UBaseAddr[m4u_index], start + 8 * i + 4 * 1), + M4U_ReadReg32(gM4UBaseAddr[m4u_index], start + 8 * i + 4 * 2), + M4U_ReadReg32(gM4UBaseAddr[m4u_index], start + 8 * i + 4 * 3), + M4U_ReadReg32(gM4UBaseAddr[m4u_index], start + 8 * i + 4 * 4), + M4U_ReadReg32(gM4UBaseAddr[m4u_index], start + 8 * i + 4 * 5), + M4U_ReadReg32(gM4UBaseAddr[m4u_index], start + 8 * i + 4 * 6), + M4U_ReadReg32(gM4UBaseAddr[m4u_index], start + 8 * i + 4 * 7)); + } + M4UINFO("Register End ==========\n"); + + return 0; +} + +unsigned int m4u_get_main_descriptor(int m4u_id, int m4u_slave_id, int idx) +{ + unsigned int regValue = 0; + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + + regValue = F_READ_ENTRY_EN + | F_READ_ENTRY_MMx_MAIN(m4u_slave_id) + | F_READ_ENTRY_MAIN_IDX(idx); + + M4U_WriteReg32(m4u_base, REG_MMU_READ_ENTRY, regValue); + while (M4U_ReadReg32(m4u_base, REG_MMU_READ_ENTRY)&F_READ_ENTRY_EN) + ; + return M4U_ReadReg32(m4u_base, REG_MMU_DES_RDATA); +} + +unsigned int m4u_get_main_tag(int m4u_id, int m4u_slave_id, int idx) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + + return M4U_ReadReg32(m4u_base, REG_MMU_MAIN_TAG(m4u_slave_id, idx)); +} + +void m4u_get_main_tlb(int m4u_id, int m4u_slave_id, int idx, mmu_tlb_t *pTlb) +{ + pTlb->tag = m4u_get_main_tag(m4u_id, m4u_slave_id, idx); + pTlb->desc = m4u_get_main_descriptor(m4u_id, m4u_slave_id, idx); +} + +unsigned int m4u_get_pfh_tlb(int m4u_id, int set, int page, int way, mmu_tlb_t *pTlb) +{ + unsigned int regValue = 0; + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + + regValue = F_READ_ENTRY_EN + | F_READ_ENTRY_PFH + | F_READ_ENTRY_PFH_IDX(set) + | F_READ_ENTRY_PFH_PAGE_IDX(page) + | F_READ_ENTRY_PFH_WAY(way); + + M4U_WriteReg32(m4u_base, REG_MMU_READ_ENTRY, regValue); + while (M4U_ReadReg32(m4u_base, REG_MMU_READ_ENTRY)&F_READ_ENTRY_EN) + ; + pTlb->desc = M4U_ReadReg32(m4u_base, REG_MMU_DES_RDATA); + pTlb->tag = M4U_ReadReg32(m4u_base, REG_MMU_PFH_TAG_RDATA); + + return 0; +} + +unsigned int m4u_get_pfh_tag(int m4u_id, int set, int page, int way) +{ + mmu_tlb_t tlb; + + m4u_get_pfh_tlb(m4u_id, set, page, way, &tlb); + return tlb.tag; +} + +unsigned int m4u_get_pfh_descriptor(int m4u_id, int set, int page, int way) +{ + mmu_tlb_t tlb; + + m4u_get_pfh_tlb(m4u_id, set, page, way, &tlb); + return tlb.desc; +} + +int m4u_dump_main_tlb(int m4u_id, int m4u_slave_id) +{ + /* M4U related */ + unsigned int i = 0; + mmu_tlb_t tlb; + + M4ULOG_HIGH("dump main tlb: m4u %d ====>\n", m4u_id); + for (i = 0; i < gM4UTagCount[m4u_id]; i++) { + m4u_get_main_tlb(m4u_id, m4u_slave_id, i, &tlb); + M4ULOG_HIGH("%d:0x%x:0x%x ", i, tlb.tag, tlb.desc); + if ((i+1)%8 == 0) + M4ULOG_HIGH("===\n"); + } + + return 0; +} + +int m4u_dump_invalid_main_tlb(int m4u_id, int m4u_slave_id) +{ + unsigned int i = 0; + mmu_tlb_t tlb; + + M4UMSG("dump inv main tlb=>\n"); + for (i = 0; i < gM4UTagCount[m4u_id]; i++) { + m4u_get_main_tlb(m4u_id, m4u_slave_id, i, &tlb); + if ((tlb.tag&(F_MAIN_TLB_VALID_BIT|F_MAIN_TLB_INV_DES_BIT)) + == (F_MAIN_TLB_VALID_BIT|F_MAIN_TLB_INV_DES_BIT)) + M4ULOG_HIGH("%d:0x%x:0x%x ", i, tlb.tag, tlb.desc); + } + M4ULOG_HIGH("\n"); + + return 0; +} + +static unsigned int imu_pfh_tag_to_va(int mmu, int set, int way, unsigned int tag) +{ + unsigned int tmp; + + if (tag&F_PFH_TAG_LAYER_BIT) + return (F_PFH_TAG_VA_GET(mmu, tag)|((set)<<15)); + + tmp = F_PFH_TAG_VA_GET(mmu, tag); + tmp &= F_MMU_PFH_TAG_VA_LAYER0_MSK(mmu); + tmp |= (set)<<23; + return tmp; +} + +int m4u_dump_pfh_tlb(int m4u_id) +{ + unsigned int regval; + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + int result = 0; + int set_nr, way_nr, set, way; + int valid; + + set_nr = MMU_SET_NR(m4u_id); + way_nr = MMU_WAY_NR; + + M4ULOG_HIGH("dump pfh_tlb: m4u %d ====>\n", m4u_id); + + for (way = 0; way < way_nr; way++) { + for (set = 0; set < set_nr; set++) { + int page; + mmu_tlb_t tlb; + + regval = M4U_ReadReg32(m4u_base, REG_MMU_PFH_VLD(m4u_id, set, way)); + valid = !!(regval & F_MMU_PFH_VLD_BIT(set, way)); + m4u_get_pfh_tlb(m4u_id, set, 0, way, &tlb); + M4ULOG_HIGH("va(0x%x) lay(%d) 16x(%d) sec(%d) pfh(%d) v(%d),set(%d),way(%d), 0x%x:", + imu_pfh_tag_to_va(m4u_id, set, way, tlb.tag), + !!(tlb.tag & F_PFH_TAG_LAYER_BIT), + !!(tlb.tag & F_PFH_TAG_16X_BIT), + !!(tlb.tag & F_PFH_TAG_SEC_BIT), + !!(tlb.tag & F_PFH_TAG_AUTO_PFH), + valid, + set, way, + tlb.desc); + + for (page = 1; page < 8; page++) { + m4u_get_pfh_tlb(m4u_id, set, page, way, &tlb); + M4ULOG_HIGH("0x%x:", tlb.desc); + } + M4ULOG_HIGH("\n"); + } + } + + return result; +} + +int m4u_get_pfh_tlb_all(int m4u_id, mmu_pfh_tlb_t *pfh_buf) +{ + unsigned int regval; + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + int set_nr, way_nr, set, way; + int valid; + int pfh_id = 0; + + set_nr = MMU_SET_NR(m4u_id); + way_nr = MMU_WAY_NR; + + for (way = 0; way < way_nr; way++) { + for (set = 0; set < set_nr; set++) { + int page; + mmu_tlb_t tlb; + + regval = M4U_ReadReg32(m4u_base, REG_MMU_PFH_VLD(m4u_id, set, way)); + valid = !!(regval & F_MMU_PFH_VLD_BIT(set, way)); + m4u_get_pfh_tlb(m4u_id, set, 0, way, &tlb); + + pfh_buf[pfh_id].tag = tlb.tag; + pfh_buf[pfh_id].va = imu_pfh_tag_to_va(m4u_id, set, way, tlb.tag); + pfh_buf[pfh_id].layer = !!(tlb.tag & F_PFH_TAG_LAYER_BIT); + pfh_buf[pfh_id].x16 = !!(tlb.tag & F_PFH_TAG_16X_BIT); + pfh_buf[pfh_id].sec = !!(tlb.tag & F_PFH_TAG_SEC_BIT); + pfh_buf[pfh_id].pfh = !!(tlb.tag & F_PFH_TAG_AUTO_PFH); + pfh_buf[pfh_id].set = set; + pfh_buf[pfh_id].way = way; + pfh_buf[pfh_id].valid = valid; + pfh_buf[pfh_id].desc[0] = tlb.desc; + pfh_buf[pfh_id].page_size = pfh_buf[pfh_id].layer ? MMU_SMALL_PAGE_SIZE : MMU_SECTION_SIZE; + + for (page = 1; page < MMU_PAGE_PER_LINE; page++) { + m4u_get_pfh_tlb(m4u_id, set, page, way, &tlb); + pfh_buf[pfh_id].desc[page] = tlb.desc; + } + pfh_id++; + } + } + + return 0; +} + +int m4u_confirm_main_range_invalidated(int m4u_index, int m4u_slave_id, unsigned int MVAStart, unsigned int MVAEnd) +{ + unsigned int i; + unsigned int regval; + + /* /> check Main TLB part */ + for (i = 0; i < gM4UTagCount[m4u_index]; i++) { + regval = m4u_get_main_tag(m4u_index, m4u_slave_id, i); + + if (regval & (F_MAIN_TLB_VALID_BIT)) { + unsigned int tag_s, tag_e, sa, ea; + int layer = regval&F_MAIN_TLB_LAYER_BIT; + int large = regval&F_MAIN_TLB_16X_BIT; + + tag_s = regval & F_MAIN_TLB_VA_MSK; + sa = MVAStart & (~(PAGE_SIZE-1)); + ea = MVAEnd | (PAGE_SIZE-1); + + if (layer) { /* pte */ + if (large) + tag_e = tag_s + MMU_LARGE_PAGE_SIZE - 1; + else + tag_e = tag_s + PAGE_SIZE - 1; + + if (!((tag_e < sa) || (tag_s > ea))) { + M4UERR("main: i=%d, idx=0x%x, MVAStart=0x%x, MVAEnd=0x%x, RegValue=0x%x\n", + i, m4u_index, MVAStart, MVAEnd, regval); + return -1; + } + } else { + if (large) + tag_e = tag_s + MMU_SUPERSECTION_SIZE - 1; + else + tag_e = tag_s + MMU_SECTION_SIZE - 1; + + if ((tag_s >= sa) && (tag_e <= ea)) { + M4UERR("main: i=%d, idx=0x%x, MVAStart=0x%x, MVAEnd=0x%x, RegValue=0x%x\n", + i, m4u_index, MVAStart, MVAEnd, regval); + return -1; + } + } + } + } + return 0; +} + +int m4u_confirm_range_invalidated(int m4u_index, unsigned int MVAStart, unsigned int MVAEnd) +{ + unsigned int i = 0; + unsigned int regval; + unsigned long m4u_base = gM4UBaseAddr[m4u_index]; + int result = 0; + int set_nr, way_nr, set, way; + + /* /> check Main TLB part */ + result = m4u_confirm_main_range_invalidated(m4u_index, 0, MVAStart, MVAEnd); + if (result < 0) + return -1; + + if (m4u_index == 0) { + result = m4u_confirm_main_range_invalidated(m4u_index, 1, MVAStart, MVAEnd); + if (result < 0) + return -1; + } + + set_nr = MMU_SET_NR(m4u_index); + way_nr = MMU_WAY_NR; + + for (way = 0; way < way_nr; way++) { + for (set = 0; set < set_nr; set++) { + regval = M4U_ReadReg32(m4u_base, REG_MMU_PFH_VLD(m4u_index, set, way)); + if (regval & F_MMU_PFH_VLD_BIT(set, way)) { + unsigned int tag = m4u_get_pfh_tag(m4u_index, set, 0, way); + unsigned int tag_s, tag_e, sa, ea; + int layer = tag&F_PFH_TAG_LAYER_BIT; + int large = tag&F_PFH_TAG_16X_BIT; + + tag_s = imu_pfh_tag_to_va(m4u_index, set, way, tag); + + sa = MVAStart & (~(PAGE_SIZE-1)); + ea = MVAEnd | (PAGE_SIZE-1); + + if (layer) { /* pte */ + if (large) + tag_e = tag_s + MMU_LARGE_PAGE_SIZE*8 - 1; + else + tag_e = tag_s + PAGE_SIZE*8 - 1; + + if (!((tag_e < sa) || (tag_s > ea))) { + M4UERR( + "main: i=%d, idx=0x%x, MVAStart=0x%x, MVAEnd=0x%x, RegValue=0x%x\n", + i, m4u_index, MVAStart, MVAEnd, regval); + return -1; + } + + } else { + if (large) + tag_e = tag_s + MMU_SUPERSECTION_SIZE*8 - 1; + else + tag_e = tag_s + MMU_SECTION_SIZE*8 - 1; + + /* if((tag_s>=sa)&&(tag_e<=ea)) */ + if (!((tag_e < sa) || (tag_s > ea))) { + M4UERR( + "main: i=%d, idx=0x%x, MVAStart=0x%x, MVAEnd=0x%x, RegValue=0x%x\n", + i, m4u_index, MVAStart, MVAEnd, regval); + return -1; + } + } + } + } + } + + return result; +} + +int m4u_confirm_main_all_invalid(int m4u_index, int m4u_slave_id) +{ + unsigned int i; + unsigned int regval; + + for (i = 0; i < gM4UTagCount[m4u_index]; i++) { + regval = m4u_get_main_tag(m4u_index, m4u_slave_id, i); + + if (regval & (F_MAIN_TLB_VALID_BIT)) { + M4UERR("main: i=%d, idx=0x%x, RegValue=0x%x\n", i, m4u_index, regval); + return -1; + } + } + return 0; +} + +int m4u_confirm_pfh_all_invalid(int m4u_index) +{ + unsigned int regval; + unsigned long m4u_base = gM4UBaseAddr[m4u_index]; + int set_nr, way_nr, set, way; + + set_nr = MMU_SET_NR(m4u_index); + way_nr = MMU_WAY_NR; + + for (way = 0; way < way_nr; way++) + for (set = 0; set < set_nr; set++) + regval = M4U_ReadReg32(m4u_base, REG_MMU_PFH_VLD(m4u_index, set, way)); + if (regval & F_MMU_PFH_VLD_BIT(set, way)) + return -1; + + return 0; +} + +int m4u_confirm_all_invalidated(int m4u_index) +{ + if (m4u_confirm_main_all_invalid(m4u_index, 0)) + return -1; + + if (m4u_index == 0) + if (m4u_confirm_main_all_invalid(m4u_index, 1)) + return -1; + + if (m4u_confirm_pfh_all_invalid(m4u_index)) + return -1; + + return 0; +} + +int m4u_power_on(int m4u_index) +{ + return 0; +} + +int m4u_power_off(int m4u_index) +{ + return 0; +} + +static int m4u_clock_on(void) +{ +#if defined(CONFIG_MTK_CLKMGR) +/* no m4u, smi CG */ + enable_clock(MT_CG_INFRA_M4U, "infra_m4u"); +/* enable_clock(MT_CG_INFRA_SMI, "infra_smi"); */ +#else + int ret; + + ret = clk_prepare_enable(gM4uDev->infra_m4u); + if (ret) + M4UMSG("error: prepare clk infra m4u fail!.\n"); +#endif + + return 0; +} + +/* +static int m4u_clock_off(void) +{ +#if defined(CONFIG_MTK_CLKMGR) + disable_clock(MT_CG_INFRA_M4U, "infra_m4u"); + disable_clock(MT_CG_INFRA_SMI, "infra_smi"); +#else + clk_disable_unprepare(gM4uDev->infra_m4u); +#endif + + return 0; +} +*/ + +#if !defined(CONFIG_MTK_CLKMGR) +const char *smi_clk_name[] = { + "smi_common", "m4u_disp0_smi_larb0", "m4u_vdec0_vdec", "m4u_vdec1_larb", + "m4u_img_image_larb2_smi", "m4u_venc_venc", "m4u_venc_larb", "m4u_mtcmos_ven", + "m4u_mtcmos_vde", "m4u_mtcmos_isp", "m4u_mtcmos_dis" +}; +#endif + +#if !defined(CONFIG_MTK_CLKMGR) +static int smi_larb_clock_prepare(void) +{ + int ret; + + ret = clk_prepare(gM4uDev->smi_clk[SMI_COMMON_CLK]); + if (ret) + M4UMSG("error: prepare clk %s fail!.\n", smi_clk_name[SMI_COMMON_CLK]); + + ret = clk_prepare(gM4uDev->smi_clk[DISP0_SMI_LARB0_CLK]); + if (ret) + M4UMSG("error: prepare clk %s fail!.\n", smi_clk_name[DISP0_SMI_LARB0_CLK]); + ret = clk_prepare(gM4uDev->smi_clk[VDEC0_VDEC_CLK]); + if (ret) + M4UMSG("error: prepare clk %s fail!.\n", smi_clk_name[VDEC0_VDEC_CLK]); + ret = clk_prepare(gM4uDev->smi_clk[VDEC1_LARB_CLK]); + if (ret) + M4UMSG("error: prepare clk %s fail!.\n", smi_clk_name[VDEC1_LARB_CLK]); + ret = clk_prepare(gM4uDev->smi_clk[LARB2_SMI_CLK]); + if (ret) + M4UMSG("error: prepare clk %s fail!.\n", smi_clk_name[LARB2_SMI_CLK]); + ret = clk_prepare(gM4uDev->smi_clk[VENC_VENC_CLK]); + if (ret) + M4UMSG("error: prepare clk %s fail!.\n", smi_clk_name[VENC_VENC_CLK]); + ret = clk_prepare(gM4uDev->smi_clk[VENC_LARB_CLK]); + if (ret) + M4UMSG("error: prepare clk %s fail!.\n", smi_clk_name[VENC_LARB_CLK]); + + return 0; +} + +static int smi_larb_clock_unprepare(void) +{ + clk_unprepare(gM4uDev->smi_clk[SMI_COMMON_CLK]); + + clk_unprepare(gM4uDev->smi_clk[DISP0_SMI_LARB0_CLK]); + clk_unprepare(gM4uDev->smi_clk[VDEC0_VDEC_CLK]); + clk_unprepare(gM4uDev->smi_clk[VDEC1_LARB_CLK]); + clk_unprepare(gM4uDev->smi_clk[LARB2_SMI_CLK]); + clk_unprepare(gM4uDev->smi_clk[VENC_VENC_CLK]); + clk_unprepare(gM4uDev->smi_clk[VENC_LARB_CLK]); + + return 0; +} +#endif + +static int larb_clock_on(int larb) +{ +#if defined(CONFIG_MTK_CLKMGR) + switch (larb) { + case 0: + enable_clock(MT_CG_DISP0_SMI_LARB0, "m4u_larb0"); + break; + case 1: + enable_clock(MT_CG_VDEC0_VDEC, "m4u_larb1"); + enable_clock(MT_CG_VDEC1_LARB, "m4u_larb1"); + break; + case 2: + enable_clock(MT_CG_IMAGE_LARB2_SMI, "m4u_larb2"); + break; + case 3: + enable_clock(MT_CG_VENC_VENC, "m4u_larb3"); + enable_clock(MT_CG_VENC_LARB, "m4u_larb3"); + break; + default: + M4UMSG("error: unknown larb id %d, %s\n", larb, __func__); + break; + } +#else + int ret; + + ret = clk_prepare_enable(gM4uDev->smi_clk[NTCMOS_DIS]); + switch (larb) { + case 0: + ret = clk_enable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + ret = clk_enable(gM4uDev->smi_clk[DISP0_SMI_LARB0_CLK]); + if (ret) + M4UMSG("error: enable clk %s fail!.\n", smi_clk_name[DISP0_SMI_LARB0_CLK]); + break; + + case 1: + ret = clk_prepare_enable(gM4uDev->smi_clk[NTCMOS_VDE]); + + ret = clk_enable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + ret = clk_enable(gM4uDev->smi_clk[VDEC0_VDEC_CLK]); + if (ret) + M4UMSG("error: enable clk %s fail!.\n", smi_clk_name[VDEC0_VDEC_CLK]); + ret = clk_enable(gM4uDev->smi_clk[VDEC1_LARB_CLK]); + if (ret) + M4UMSG("error: enable clk %s fail!.\n", smi_clk_name[VDEC1_LARB_CLK]); + break; + + case 2: + ret = clk_prepare_enable(gM4uDev->smi_clk[NTCMOS_ISP]); + + ret = clk_enable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + ret = clk_enable(gM4uDev->smi_clk[LARB2_SMI_CLK]); + if (ret) + M4UMSG("error: enable clk %s fail!.\n", smi_clk_name[LARB2_SMI_CLK]); + break; + + case 3: + ret = clk_prepare_enable(gM4uDev->smi_clk[NTCMOS_VEN]); + + ret = clk_enable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + ret = clk_enable(gM4uDev->smi_clk[VENC_VENC_CLK]); + if (ret) + M4UMSG("error: enable clk %s fail!.\n", smi_clk_name[VENC_VENC_CLK]); + ret = clk_enable(gM4uDev->smi_clk[VENC_LARB_CLK]); + if (ret) + M4UMSG("error: enable clk %s fail!.\n", smi_clk_name[VENC_LARB_CLK]); + break; + default: + M4UMSG("error: unknown larb id %d, %s\n", larb, __func__); + break; + } +#endif + + return 0; +} + +static int larb_clock_off(int larb) +{ +#if defined(CONFIG_MTK_CLKMGR) + switch (larb) { + case 0: + disable_clock(MT_CG_DISP0_SMI_LARB0, "m4u_larb0"); + break; + case 1: + disable_clock(MT_CG_VDEC0_VDEC, "m4u_larb1"); + disable_clock(MT_CG_VDEC1_LARB, "m4u_larb1"); + break; + case 2: + disable_clock(MT_CG_IMAGE_LARB2_SMI, "m4u_larb2"); + break; + case 3: + disable_clock(MT_CG_VENC_VENC, "m4u_larb3"); + disable_clock(MT_CG_VENC_LARB, "m4u_larb3"); + break; + default: + M4UMSG("error: unknown larb id %d, %s\n", larb, __func__); + break; + } +#else + switch (larb) { + case 0: + clk_disable(gM4uDev->smi_clk[DISP0_SMI_LARB0_CLK]); + clk_disable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + break; + case 1: + clk_disable(gM4uDev->smi_clk[VDEC1_LARB_CLK]); + clk_disable(gM4uDev->smi_clk[VDEC0_VDEC_CLK]); + clk_disable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + clk_disable_unprepare(gM4uDev->smi_clk[NTCMOS_VDE]); + break; + case 2: + clk_disable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + clk_disable(gM4uDev->smi_clk[LARB2_SMI_CLK]); + clk_disable_unprepare(gM4uDev->smi_clk[NTCMOS_ISP]); + break; + case 3: + clk_disable(gM4uDev->smi_clk[VENC_VENC_CLK]); + clk_disable(gM4uDev->smi_clk[VENC_LARB_CLK]); + clk_disable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + clk_disable_unprepare(gM4uDev->smi_clk[NTCMOS_VEN]); + break; + default: + M4UMSG("error: unknown larb id %d, %s\n", larb, __func__); + break; + } + + clk_disable_unprepare(gM4uDev->smi_clk[NTCMOS_DIS]); +#endif + return 0; +} + +static int larb_clock_all_on(void) +{ + int i; + + return 0; + for (i = 0 ; i < SMI_LARB_NR ; i++) + larb_clock_on(i); + + return 0; +} +static int larb_clock_all_off(void) +{ + int i; + + return 0; + for (i = 0 ; i < SMI_LARB_NR ; i++) + larb_clock_off(i); + + return 0; +} + +void smi_common_clock_on(void) +{ +#if defined(CONFIG_MTK_CLKMGR) + enable_clock(MT_CG_DISP0_SMI_COMMON, "smi_common"); + /* m4uHw_set_field_by_mask(0, 0xf4000108, 0x1, 0x1); */ +#else + int ret = 0; + + M4UMSG("error: smi_common_clock_on not support.\n"); + return; + clk_enable(gM4uDev->smi_clk[SMI_COMMON_CLK]); + + if (ret) + M4UMSG("error: prepare clk %s fail!.\n", smi_clk_name[SMI_COMMON_CLK]); +#endif +} +EXPORT_SYMBOL(smi_common_clock_on); + +void smi_common_clock_off(void) +{ +#if defined(CONFIG_MTK_CLKMGR) + disable_clock(MT_CG_DISP0_SMI_COMMON, "smi_common"); + /* m4uHw_set_field_by_mask(0, 0xf4000108, 0x1, 0x0); */ +#else + M4UMSG("error: smi_common_clock_off not support.\n"); + return; + clk_disable(gM4uDev->smi_clk[SMI_COMMON_CLK]); +#endif +} +EXPORT_SYMBOL(smi_common_clock_off); + +int m4u_enable_prog_dist_by_id(int port, int id) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_port_2_m4u_id(port)]; + + spin_lock(&gM4u_reg_lock); + m4uHw_set_field_by_mask(m4u_base, REG_MMU_PROG_DIST(id), F_PF_EN(1), 1); + spin_unlock(&gM4u_reg_lock); + + return 0; +} + +int m4u_disable_prog_dist_by_id(int port, int id) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_port_2_m4u_id(port)]; + + spin_lock(&gM4u_reg_lock); + m4uHw_set_field_by_mask(m4u_base, REG_MMU_PROG_DIST(id), F_PF_EN(1), 0); + spin_unlock(&gM4u_reg_lock); + + return 0; +} + +int m4u_config_prog_dist(M4U_PORT_ID port, int dir, int dist, int en, int mm_id, int sel) +{ + int i, free_id = -1; + int m4u_index = m4u_port_2_m4u_id(port); + unsigned int m4u_slave_id = m4u_port_2_m4u_slave_id(port); + unsigned long m4u_base = gM4UBaseAddr[m4u_index]; + unsigned long larb_base; + unsigned int larb, larb_port; + unsigned int axi_id; + M4U_PROG_DIST_T *pProgPfh = gM4UProgPfh[m4u_index] + M4U_PROG_PFH_NUM(m4u_index)*m4u_slave_id; + + larb = m4u_port_2_larb_id(port); + larb_port = m4u_port_2_larb_port(port); + larb_base = gLarbBaseAddr[larb]; + axi_id = ((larb) << 7 | ((port) << 2) | mm_id); + + mutex_lock(&gM4u_prog_pfh_mutex); + + for (i = 0; i < M4U_PROG_PFH_NUM(m4u_index); i++) { + if (1 == pProgPfh[i].Enabled) { + if (axi_id == pProgPfh[i].axi_id) { + free_id = i; + M4UMSG( + "original value: module = %s, axi_id = %d, dir = %d, dist = %d, sel = %d.\n", + m4u_get_port_name(port), axi_id, dir, dist, sel); + M4UMSG( + "new value: module = %s, mm_id = %d, dir = %d, dist = %d, sel = %d.\n", + m4u_get_port_name(pProgPfh[i].port), pProgPfh[i].axi_id, pProgPfh[i].dir, + pProgPfh[i].dist, pProgPfh[i].sel); + break; + } else if (((axi_id & F_PF_AXI_ID_MSK) == (pProgPfh[i].axi_id & F_PF_AXI_ID_MSK)) + && (sel == 0 || pProgPfh[i].sel == 0)) { + M4UERR( + "m4u error: cannot set two direction or difference distance in the same port.\n"); + M4UMSG("original value: module = %s, axi_id = %d, dir = %d, dist = %d, sel = %d.\n", + m4u_get_port_name(port), axi_id, dir, dist, sel); + M4UMSG("new value: module = %s, axi_id = %d, dir = %d, dist = %d, sel = %d.\n", + m4u_get_port_name(pProgPfh[i].port), pProgPfh[i].axi_id, + pProgPfh[i].dir, pProgPfh[i].dist, pProgPfh[i].sel); + mutex_unlock(&gM4u_seq_mutex); + return -1; + } + } else { + free_id = i; + break; + } + } + + if (free_id == -1) { + M4ULOG_MID("warning: can not find available prog pfh reg.\n"); + mutex_unlock(&gM4u_prog_pfh_mutex); + return -1; + } + + pProgPfh[free_id].Enabled = 1; + pProgPfh[free_id].port = port; + pProgPfh[free_id].axi_id = axi_id; + pProgPfh[free_id].dir = dir; + pProgPfh[free_id].dist = dist; + pProgPfh[free_id].en = en; + pProgPfh[free_id].sel = sel; + mutex_unlock(&gM4u_prog_pfh_mutex); + + spin_lock(&gM4u_reg_lock); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_PROG_DIST(free_id), F_PF_DIR(1), F_PF_DIR(!!(dir))); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_PROG_DIST(free_id), F_PF_DIST(1), F_PF_DIST(dist)); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_PROG_DIST(free_id), F_PF_ID_MASK(1), F_PF_ID(axi_id)); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_PROG_DIST(free_id), F_PF_EN(1), F_PF_EN(!!(en))); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_PROG_DIST(free_id), F_PF_ID_COMP_SEL(1), F_PF_ID_COMP_SEL(!!(sel))); + + spin_unlock(&gM4u_reg_lock); + + return free_id; +} + +int m4u_invalid_prog_dist_by_id(int port, int id) +{ + int m4u_index = m4u_port_2_m4u_id(port); + int m4u_slave_id = m4u_port_2_m4u_slave_id(port); + unsigned long m4u_base = gM4UBaseAddr[m4u_index]; + M4U_PROG_DIST_T *pProgPfh = gM4UProgPfh[m4u_index] + M4U_PROG_PFH_NUM(m4u_index)*m4u_slave_id; + + mutex_lock(&gM4u_prog_pfh_mutex); + + pProgPfh[id].Enabled = 0; + + mutex_unlock(&gM4u_prog_pfh_mutex); + + spin_lock(&gM4u_reg_lock); + M4U_WriteReg32(m4u_base, REG_MMU_PROG_DIST(id), 0); + spin_unlock(&gM4u_reg_lock); + + return 0; +} + +int m4u_insert_seq_range(M4U_PORT_ID port, unsigned int MVAStart, unsigned int MVAEnd) +{ + int i, free_id = -1; + unsigned int m4u_index = m4u_port_2_m4u_id(port); + unsigned int m4u_slave_id = m4u_port_2_m4u_slave_id(port); + M4U_RANGE_DES_T *pSeq = gM4USeq[m4u_index] + M4U_SEQ_NUM(m4u_index)*m4u_slave_id; + + M4ULOG_MID("m4u_insert_seq_range , module:%s, MVAStart:0x%x, MVAEnd:0x%x\n", + m4u_get_port_name(port), MVAStart, MVAEnd); + + if (MVAEnd - MVAStart < PAGE_SIZE) { + M4ULOG_MID("too small size, skip to insert! module:%s, MVAStart:0x%x, size:%d\n", + m4u_get_port_name(port), MVAStart, MVAEnd - MVAStart + 1); + return free_id; + } + + /* =============================================== */ + /* every seq range has to align to 1M Bytes */ + MVAStart &= ~M4U_SEQ_ALIGN_MSK; + MVAEnd |= M4U_SEQ_ALIGN_MSK; + + mutex_lock(&gM4u_seq_mutex); + + /* ================================================================== */ + /* check if the range is overlap with previous ones */ + + for (i = 0; i < M4U_SEQ_NUM(m4u_index); i++) { + if (1 == pSeq[i].Enabled) { + if (MVAEnd < pSeq[i].MVAStart || MVAStart > pSeq[i].MVAEnd) + continue; + else { + M4ULOG_HIGH("insert range overlap!: larb=%d,module=%s\n", + m4u_port_2_larb_id(port), m4u_get_port_name(port)); + M4ULOG_HIGH( + "warning: insert tlb range is overlapped with previous ranges, current process=%s,!\n", + current->comm); + M4ULOG_HIGH("module=%s, mva_start=0x%x, mva_end=0x%x\n", + m4u_get_port_name(port), MVAStart, MVAEnd); + M4ULOG_HIGH("overlapped range id=%d, module=%s, mva_start=0x%x, mva_end=0x%x\n", + i, m4u_get_port_name(pSeq[i].port), pSeq[i].MVAStart, pSeq[i].MVAEnd); + mutex_unlock(&gM4u_seq_mutex); + return -1; + } + } else + free_id = i; + } + + if (free_id == -1) { + M4ULOG_MID("warning: can not find available range\n"); + mutex_unlock(&gM4u_seq_mutex); + return -1; + } + + /* /> record range information in array */ + pSeq[free_id].Enabled = 1; + pSeq[free_id].port = port; + pSeq[free_id].MVAStart = MVAStart; + pSeq[free_id].MVAEnd = MVAEnd; + + mutex_unlock(&gM4u_seq_mutex); + + /* /> set the range register */ + + MVAStart &= F_SQ_VA_MASK; + MVAStart |= F_SQ_EN_BIT; + /* align mvaend to 1M */ + MVAEnd |= ~F_SQ_VA_MASK; + + spin_lock(&gM4u_reg_lock); + { + M4U_WriteReg32(gM4UBaseAddr[m4u_index], REG_MMU_SQ_START(m4u_slave_id, free_id), MVAStart); + M4U_WriteReg32(gM4UBaseAddr[m4u_index], REG_MMU_SQ_END(m4u_slave_id, free_id), MVAEnd); + } + spin_unlock(&gM4u_reg_lock); + + return free_id; +} + +int m4u_invalid_seq_range_by_id(int port, int seq_id) +{ + int m4u_index = m4u_port_2_m4u_id(port); + int m4u_slave_id = m4u_port_2_m4u_slave_id(port); + unsigned long m4u_base = gM4UBaseAddr[m4u_index]; + M4U_RANGE_DES_T *pSeq = gM4USeq[m4u_index] + M4U_SEQ_NUM(m4u_index)*m4u_slave_id; + int ret = 0; + + mutex_lock(&gM4u_seq_mutex); + { + pSeq[seq_id].Enabled = 0; + } + mutex_unlock(&gM4u_seq_mutex); + + spin_lock(&gM4u_reg_lock); + M4U_WriteReg32(m4u_base, REG_MMU_SQ_START(m4u_slave_id, seq_id), 0); + M4U_WriteReg32(m4u_base, REG_MMU_SQ_END(m4u_slave_id, seq_id), 0); + spin_unlock(&gM4u_reg_lock); + + return ret; +} + +/* +static int m4u_invalid_seq_range_by_mva(int m4u_index, int m4u_slave_id, unsigned int MVAStart, unsigned int MVAEnd) +{ + unsigned int i; + unsigned int m4u_base = gM4UBaseAddr[m4u_index]; + M4U_RANGE_DES_T *pSeq = gM4USeq[m4u_index] + SEQ_NR_PER_M4U_SLAVE*m4u_slave_id; + int ret=-1; + + MVAStart &= ~M4U_SEQ_ALIGN_MSK; + MVAEnd |= M4U_SEQ_ALIGN_MSK; + + mutex_lock(&gM4u_seq_mutex); + for(i=0; i=MVAStart && + pSeq[i].MVAEnd<=MVAEnd) { + pSeq[i].Enabled = 0; + spin_lock(&gM4u_reg_lock); + M4U_WriteReg32(m4u_base, REG_MMU_SQ_START(m4u_slave_id,i), 0); + M4U_WriteReg32(m4u_base, REG_MMU_SQ_END(m4u_slave_id,i), 0); + spin_unlock(&gM4u_reg_lock); + break; + } + } + mutex_unlock(&gM4u_seq_mutex); + + return ret; +} +*/ + +static int _m4u_config_port(int port, int virt, int sec, int dis, int dir) +{ + int m4u_index = m4u_port_2_m4u_id(port); + /* unsigned long m4u_base = gM4UBaseAddr[m4u_index]; */ + unsigned long larb_base; + unsigned int larb, larb_port; + int ret = 0; + + M4ULOG_MID("config_port:%s,v%d,s%d\n", + m4u_get_port_name(port), virt, sec); + + /* MMProfileLogEx(M4U_MMP_Events[M4U_MMP_CONFIG_PORT], MMProfileFlagStart, port, virt); */ + + spin_lock(&gM4u_reg_lock); + /* Direction, one bit for each port, 1:-, 0:+ */ + /* m4uHw_set_field_by_mask(m4u_base, REG_MMU_PFH_DIR(port), + F_MMU_PFH_DIR(port, 1), F_MMU_PFH_DIR(port, dir)); + + m4uHw_set_field_by_mask(m4u_base, REG_MMU_PFH_DIST(port), + F_MMU_PFH_DIST_MASK(port), F_MMU_PFH_DIST_VAL(port, dis)); */ + + if (m4u_index == 0) { + int mmu_en = 0; + + larb = m4u_port_2_larb_id(port); + larb_port = m4u_port_2_larb_port(port); + larb_base = gLarbBaseAddr[larb]; + + m4uHw_set_field_by_mask(larb_base, SMI_LARB_MMU_EN, + F_SMI_MMU_EN(larb_port, 1), F_SMI_MMU_EN(larb_port, !!(virt))); + + m4uHw_set_field_by_mask(larb_base, SMI_LARB_SEC_EN, + F_SMI_SEC_EN(larb_port, 1), F_SMI_SEC_EN(larb_port, !!(sec))); + + /* multimedia engines will should set domain as 3. */ + /* m4uHw_set_field_by_mask(larb_base, REG_SMI_LARB_DOMN_OF_PORT(larb_port), */ + /* F_SMI_DOMN(larb_port, 0x3), F_SMI_DOMN(larb_port, pM4uPort->domain)); */ + + /* debug use */ + mmu_en = m4uHw_get_field_by_mask(larb_base, SMI_LARB_MMU_EN, F_SMI_MMU_EN(larb_port, 1)); + if (!!(mmu_en) != virt) + M4ULOG_HIGH( + "m4u_config_port error, port=%s, Virtuality=%d, mmu_en=%x (%x, %x)\n", + m4u_get_port_name(port), virt, mmu_en, + M4U_ReadReg32(larb_base, SMI_LARB_MMU_EN), + F_SMI_MMU_EN(larb_port, 1)); + } else { + larb_port = m4u_port_2_larb_port(port); + + m4uHw_set_field_by_mask(gPericfgBaseAddr, REG_PERIAXI_BUS_CTL3, + F_PERI_MMU_EN(larb_port, 1), F_PERI_MMU_EN(larb_port, !!(virt))); + } + + spin_unlock(&gM4u_reg_lock); + + /* MMProfileLogEx(M4U_MMP_Events[M4U_MMP_CONFIG_PORT], MMProfileFlagEnd, dis, dir); */ + + return ret; +} + +static inline void _m4u_port_clock_toggle(int m4u_index, int larb, int on) +{ + unsigned long long start, end; + + /* MMProfileLogEx(M4U_MMP_Events[M4U_MMP_TOGGLE_CG], MMProfileFlagStart, larb, on); */ + if (m4u_index == 0) { + start = sched_clock(); + if (on) { + larb_clock_on(larb); + } else { + larb_clock_off(larb); + } + end = sched_clock(); + + if (end-start > 50000000ULL) /* unit is ns */ + M4ULOG_HIGH("warn: larb%d clock %d time: %lld ns\n", larb, on, end-start); + } + /* MMProfileLogEx(M4U_MMP_Events[M4U_MMP_TOGGLE_CG], MMProfileFlagEnd, 0, 0); */ +} + +int m4u_config_port(M4U_PORT_STRUCT *pM4uPort) /* native */ +{ + M4U_PORT_ID PortID = (pM4uPort->ePortID); + int m4u_index = m4u_port_2_m4u_id(PortID); + int larb = m4u_port_2_larb_id(PortID); + int ret; +#ifdef M4U_TEE_SERVICE_ENABLE + unsigned int larb_port, mmu_en = 0, sec_en = 0; +#endif + + _m4u_port_clock_toggle(m4u_index, larb, 1); + +#ifdef M4U_TEE_SERVICE_ENABLE + larb_port = m4u_port_2_larb_port(PortID); + /* mmu_en = + * !!(m4uHw_get_field_by_mask(gLarbBaseAddr[larb], SMI_LARB_MMU_EN, F_SMI_MMU_EN(larb_port, 1))); */ + /* sec_en = + * !!(m4uHw_get_field_by_mask(gLarbBaseAddr[larb], SMI_LARB_SEC_EN, F_SMI_SEC_EN(larb_port, 1))); */ + M4ULOG_HIGH("m4u_config_port: %s, m4u_tee_en:%d, mmu_en: %d -> %d, sec_en:%d -> %d\n", + m4u_get_port_name(PortID), m4u_tee_en, mmu_en, + pM4uPort->Virtuality, sec_en, pM4uPort->Security); +#if 0 + if (mmu_en == pM4uPort->Virtuality && sec_en == pM4uPort->Security) { + _m4u_port_clock_toggle(m4u_index, larb, 0); + return 0; + } +#endif + if (m4u_tee_en) + m4u_config_port_tee(pM4uPort); + else +#endif + { + ret = _m4u_config_port(PortID, pM4uPort->Virtuality, + pM4uPort->Security, pM4uPort->Distance, pM4uPort->Direction); + } + _m4u_port_clock_toggle(m4u_index, larb, 0); + + return 0; +} + +void m4u_port_array_init(struct m4u_port_array *port_array) +{ + memset(port_array, 0, sizeof(struct m4u_port_array)); +} + +int m4u_port_array_add(struct m4u_port_array *port_array, + int port, int m4u_en, int secure) +{ + if (port >= M4U_PORT_NR) { + M4UMSG("error: port_array_add, port=%d, v(%d), s(%d)\n", port, m4u_en, secure); + return -1; + } + port_array->ports[port] = M4U_PORT_ATTR_EN; + if (m4u_en) + port_array->ports[port] |= M4U_PORT_ATTR_VIRTUAL; + if (secure) + port_array->ports[port] |= M4U_PORT_ATTR_SEC; + return 0; +} + +int m4u_config_port_array(struct m4u_port_array *port_array) +{ + int port, larb, larb_port; + int ret = 0; + + unsigned int config_larb[SMI_LARB_NR]; + unsigned int regOri[SMI_LARB_NR]; + unsigned int regNew[SMI_LARB_NR]; + unsigned int change = 0; + unsigned char m4u_port_array[(M4U_PORT_NR+1)/2]; + + memset(config_larb, 0, SMI_LARB_NR * sizeof(unsigned int)); + memset(regOri, 0, SMI_LARB_NR * sizeof(unsigned int)); + memset(regNew, 0, SMI_LARB_NR * sizeof(unsigned int)); + memset(m4u_port_array, 0, (M4U_PORT_NR+1)/2 * sizeof(unsigned char)); + + for (port = 0; port < M4U_PORT_NR; port++) { + if (port_array->ports[port] && M4U_PORT_ATTR_EN != 0) { + + larb = m4u_port_2_larb_id(port); + larb_port = m4u_port_2_larb_port(port); + config_larb[larb] |= (1 << larb_port); + } + } + + for (larb = 0; larb < SMI_LARB_NR; larb++) { + if (0 != config_larb[larb]) + _m4u_port_clock_toggle(0, larb, 1); + + } + + for (port = 0; port < M4U_PORT_NR; port++) { + if (port_array->ports[port] && M4U_PORT_ATTR_EN != 0) { + unsigned int value; + + larb = m4u_port_2_larb_id(port); + larb_port = m4u_port_2_larb_port(port); + value = (!!(port_array->ports[port] && M4U_PORT_ATTR_VIRTUAL))<ports[port], value, regNew[larb], m4u_port_array[port/2]); + } + } + + for (larb = 0; larb < SMI_LARB_NR; larb++) { + if (0 != config_larb[larb]) { +#ifdef M4U_TEE_SERVICE_ENABLE + if (m4u_tee_en) + change = 1; + else +#endif + { + regOri[larb] = M4U_ReadReg32(gLarbBaseAddr[larb], SMI_LARB_MMU_EN); + M4ULOG_LOW("m4u_config_port_array 2 larb: %d ori reg: 0x%x, new reg: 0x%x\n", + larb, regOri[larb], regNew[larb]); + if (regOri[larb] != regNew[larb]) + change = 1; + } + } + M4ULOG_MID("m4u_config_port_array 1: larb: %d, [0x%x], %d\n", larb, config_larb[larb], change); + } + +#ifdef M4U_TEE_SERVICE_ENABLE + if (m4u_tee_en && 1 == change) { + m4u_config_port_array_tee(m4u_port_array); + for (larb = 0; larb < SMI_LARB_NR; larb++) { + if (0 != config_larb[larb]) + _m4u_port_clock_toggle(0, larb, 0); + + } + return ret; + } +#endif + + for (larb = 0; larb < SMI_LARB_NR; larb++) { + if (0 != config_larb[larb] && 1 == change) { + M4ULOG_MID("m4u_config_port_array larb: %d ori reg: 0x%x, new reg: 0x%x\n", + larb, regOri[larb], regNew[larb]); + spin_lock(&gM4u_reg_lock); + m4uHw_set_field_by_mask(gLarbBaseAddr[larb], SMI_LARB_MMU_EN, config_larb[larb], regNew[larb]); + spin_unlock(&gM4u_reg_lock); + } + if (0 != config_larb[larb]) + _m4u_port_clock_toggle(0, larb, 0); + } + + return ret; +} + +void m4u_get_perf_counter(int m4u_index, int m4u_slave_id, M4U_PERF_COUNT *pM4U_perf_count) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_index]; + + pM4U_perf_count->transaction_cnt = M4U_ReadReg32(m4u_base, REG_MMU_ACC_CNT(m4u_slave_id)); + pM4U_perf_count->main_tlb_miss_cnt = M4U_ReadReg32(m4u_base, REG_MMU_MAIN_MSCNT(m4u_slave_id)); + pM4U_perf_count->pfh_tlb_miss_cnt = M4U_ReadReg32(m4u_base, REG_MMU_PF_MSCNT); + pM4U_perf_count->pfh_cnt = M4U_ReadReg32(m4u_base, REG_MMU_PF_CNT); /* /> Prefetch count */ + pM4U_perf_count->rs_perf_cnt = M4U_ReadReg32(m4u_base, REG_MMU_RS_PERF_CNT(m4u_slave_id)); +} + +int m4u_monitor_start(int m4u_id) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + + M4UINFO("====m4u_monitor_start: %d======\n", m4u_id); + /* clear GMC performance counter */ + m4uHw_set_field_by_mask(m4u_base, REG_MMU_CTRL_REG, + F_MMU_CTRL_MONITOR_CLR(1), F_MMU_CTRL_MONITOR_CLR(1)); + m4uHw_set_field_by_mask(m4u_base, REG_MMU_CTRL_REG, + F_MMU_CTRL_MONITOR_CLR(1), F_MMU_CTRL_MONITOR_CLR(0)); + + /* enable GMC performance monitor */ + m4uHw_set_field_by_mask(m4u_base, REG_MMU_CTRL_REG, + F_MMU_CTRL_MONITOR_EN(1), F_MMU_CTRL_MONITOR_EN(1)); + return 0; +} + +/** + * @brief , + * @param + * @return + */ +int m4u_monitor_stop(int m4u_id) +{ + M4U_PERF_COUNT cnt; + int m4u_index = m4u_id; + unsigned long m4u_base = gM4UBaseAddr[m4u_index]; + + /* disable GMC performance monitor */ + m4uHw_set_field_by_mask(m4u_base, REG_MMU_CTRL_REG, + F_MMU_CTRL_MONITOR_EN(1), F_MMU_CTRL_MONITOR_EN(0)); + + m4u_get_perf_counter(m4u_index, 0, &cnt); + /* read register get the count */ + M4ULOG_MID("[M4U%d-%d] total:%u, main miss:%u, pfh miss(walk):%u, auto pfh:%u\n", + m4u_id, 0, + cnt.transaction_cnt, cnt.main_tlb_miss_cnt, cnt.pfh_tlb_miss_cnt, cnt.pfh_cnt); + + return 0; +} + +void m4u_print_perf_counter(int m4u_index, int m4u_slave_id, const char *msg) +{ + M4U_PERF_COUNT cnt; + + M4UINFO("====m4u performance count for %s m4u%d_%d======\n", msg, m4u_index, m4u_slave_id); + m4u_get_perf_counter(m4u_index, m4u_slave_id, &cnt); + M4UINFO("total trans=%u, main_miss=%u, pfh_miss=%u, pfh_cnt=%u, rs_perf_cnt=%u\n", + cnt.transaction_cnt, cnt.main_tlb_miss_cnt, cnt.pfh_tlb_miss_cnt, cnt.pfh_cnt, cnt.rs_perf_cnt); +} + +#define M4U_REG_BACKUP_SIZE (100*sizeof(unsigned int)) +static unsigned int *pM4URegBackUp; +static unsigned int gM4u_reg_backup_real_size; + +#define __M4U_BACKUP(base, reg, back) ((back) = M4U_ReadReg32(base, reg)) + +void __M4U_RESTORE(unsigned long base, unsigned int reg, unsigned int back) {M4U_WriteReg32(base, reg, back); } + +int m4u_reg_backup(void) +{ + unsigned int *pReg = pM4URegBackUp; + unsigned long m4u_base; + int m4u_id, m4u_slave; + int seq, mau; + unsigned int real_size; + int dist; + + for (m4u_id = 0; m4u_id < TOTAL_M4U_NUM; m4u_id++) { + m4u_base = gM4UBaseAddr[m4u_id]; + __M4U_BACKUP(m4u_base, REG_MMUg_PT_BASE , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMUg_PT_BASE_SEC , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_SEC_ABORT_INFO , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_STANDARD_AXI_MODE , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_PRIORITY , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_DCM_DIS , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_WR_LEN , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_HW_DEBUG , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_NON_BLOCKING_DIS , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_LEGACY_4KB_MODE , *(pReg++)); + for (dist = 0; dist < MMU_TOTAL_PROG_DIST_NR; dist++) + __M4U_BACKUP(m4u_base, REG_MMU_PROG_DIST(dist) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_CTRL_REG , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_IVRP_PADDR , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_INT_L2_CONTROL , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_INT_MAIN_CONTROL , *(pReg++)); + + for (m4u_slave = 0; m4u_slave < M4U_SLAVE_NUM(m4u_id); m4u_slave++) { + for (seq = 0; seq < M4U_SEQ_NUM(m4u_id); seq++) { + __M4U_BACKUP(m4u_base, REG_MMU_SQ_START(m4u_slave, seq) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_SQ_END(m4u_slave, seq) , *(pReg++)); + } + + for (mau = 0; mau < MAU_NR_PER_M4U_SLAVE; mau++) { + __M4U_BACKUP(m4u_base, REG_MMU_MAU_START(m4u_slave, mau) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_MAU_START_BIT32(m4u_slave, mau) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_MAU_END(m4u_slave, mau) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_MAU_END_BIT32(m4u_slave, mau) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_MAU_PORT_EN(m4u_slave, mau) , *(pReg++)); + } + __M4U_BACKUP(m4u_base, REG_MMU_MAU_LARB_EN(m4u_slave) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_MAU_IO(m4u_slave) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_MAU_RW(m4u_slave) , *(pReg++)); + __M4U_BACKUP(m4u_base, REG_MMU_MAU_VA(m4u_slave) , *(pReg++)); + } + } + + /* check register size (to prevent overflow) */ + real_size = (pReg - pM4URegBackUp); + if (real_size > M4U_REG_BACKUP_SIZE) + m4u_aee_print("m4u_reg overflow! %d>%d\n", real_size, (int)M4U_REG_BACKUP_SIZE); + gM4u_reg_backup_real_size = real_size; + + return 0; +} + +int m4u_reg_restore(void) +{ + unsigned int *pReg = pM4URegBackUp; + unsigned long m4u_base; + int m4u_id, m4u_slave; + int seq, mau; + unsigned int real_size; + int dist; + + for (m4u_id = 0; m4u_id < TOTAL_M4U_NUM; m4u_id++) { + m4u_base = gM4UBaseAddr[m4u_id]; + __M4U_RESTORE(m4u_base, REG_MMUg_PT_BASE , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMUg_PT_BASE_SEC , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_SEC_ABORT_INFO , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_STANDARD_AXI_MODE , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_PRIORITY , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_DCM_DIS , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_WR_LEN , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_HW_DEBUG , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_NON_BLOCKING_DIS , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_LEGACY_4KB_MODE , *(pReg++)); + for (dist = 0; dist < MMU_TOTAL_PROG_DIST_NR; dist++) + __M4U_RESTORE(m4u_base, REG_MMU_PROG_DIST(dist) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_CTRL_REG , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_IVRP_PADDR , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_INT_L2_CONTROL , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_INT_MAIN_CONTROL , *(pReg++)); + + for (m4u_slave = 0; m4u_slave < M4U_SLAVE_NUM(m4u_id); m4u_slave++) { + for (seq = 0; seq < M4U_SEQ_NUM(m4u_id); seq++) { + __M4U_RESTORE(m4u_base, REG_MMU_SQ_START(m4u_slave, seq) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_SQ_END(m4u_slave, seq) , *(pReg++)); + } + + for (mau = 0; mau < MAU_NR_PER_M4U_SLAVE; mau++) { + __M4U_RESTORE(m4u_base, REG_MMU_MAU_START(m4u_slave, mau) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_MAU_START_BIT32(m4u_slave, mau) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_MAU_END(m4u_slave, mau) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_MAU_END_BIT32(m4u_slave, mau) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_MAU_PORT_EN(m4u_slave, mau) , *(pReg++)); + } + __M4U_RESTORE(m4u_base, REG_MMU_MAU_LARB_EN(m4u_slave) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_MAU_IO(m4u_slave) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_MAU_RW(m4u_slave) , *(pReg++)); + __M4U_RESTORE(m4u_base, REG_MMU_MAU_VA(m4u_slave) , *(pReg++)); + } + } + + /* check register size (to prevent overflow) */ + real_size = (pReg - pM4URegBackUp); + if (real_size != gM4u_reg_backup_real_size) + m4u_aee_print("m4u_reg_retore %d!=%d\n", real_size, gM4u_reg_backup_real_size); + + return 0; +} + +static unsigned int larb_reg_backup_buf[SMI_LARB_NR][6]; + +void m4u_larb_backup(int larb_idx) +{ + unsigned long larb_base; + + if (larb_idx >= SMI_LARB_NR) { + M4UMSG("error: %s larb_idx = %d\n", __func__, larb_idx); + return; + } + + larb_base = gLarbBaseAddr[larb_idx]; + M4ULOG_MID("larb(%d) backup\n", larb_idx); + +#ifdef M4U_TEE_SERVICE_ENABLE + if (m4u_tee_en) + /* m4u_larb_backup_sec(larb_idx); */ +#endif + { + __M4U_BACKUP(larb_base, SMI_LARB_MMU_EN, larb_reg_backup_buf[larb_idx][0]); + __M4U_BACKUP(larb_base, SMI_LARB_SEC_EN, larb_reg_backup_buf[larb_idx][1]); + __M4U_BACKUP(larb_base, SMI_LARB_DOMN_0, larb_reg_backup_buf[larb_idx][2]); + __M4U_BACKUP(larb_base, SMI_LARB_DOMN_1, larb_reg_backup_buf[larb_idx][3]); + __M4U_BACKUP(larb_base, SMI_LARB_DOMN_2, larb_reg_backup_buf[larb_idx][4]); + __M4U_BACKUP(larb_base, SMI_LARB_DOMN_3, larb_reg_backup_buf[larb_idx][5]); + } +} + +void m4u_larb_restore(int larb_idx) +{ + unsigned long larb_base; + + if (larb_idx >= SMI_LARB_NR) { + M4UMSG("error: %s larb_idx = %d\n", __func__, larb_idx); + return; + } + + larb_base = gLarbBaseAddr[larb_idx]; + M4ULOG_MID("larb(%d) restore\n", larb_idx); + +#ifdef M4U_TEE_SERVICE_ENABLE + if (m4u_tee_en) { + /* m4u_larb_restore_sec(larb_idx); */ + } else +#endif + { + __M4U_RESTORE(larb_base, SMI_LARB_MMU_EN, larb_reg_backup_buf[larb_idx][0]); + __M4U_RESTORE(larb_base, SMI_LARB_SEC_EN, larb_reg_backup_buf[larb_idx][1]); + __M4U_RESTORE(larb_base, SMI_LARB_DOMN_0, larb_reg_backup_buf[larb_idx][2]); + __M4U_RESTORE(larb_base, SMI_LARB_DOMN_1, larb_reg_backup_buf[larb_idx][3]); + __M4U_RESTORE(larb_base, SMI_LARB_DOMN_2, larb_reg_backup_buf[larb_idx][4]); + __M4U_RESTORE(larb_base, SMI_LARB_DOMN_3, larb_reg_backup_buf[larb_idx][5]); + } +} + +void m4u_print_port_status(struct seq_file *seq, int only_print_active) +{ + int port, mmu_en, sec; + int m4u_index, larb, larb_port; + unsigned long larb_base; + + M4U_PRINT_LOG_OR_SEQ(seq, "m4u_print_port_status ========>\n"); + + larb_clock_all_on(); + + for (port = 0; port < gM4u_port_num; port++) { + m4u_index = m4u_port_2_m4u_id(port); + if (m4u_index == 0) { + larb = m4u_port_2_larb_id(port); + larb_port = m4u_port_2_larb_port(port); + larb_base = gLarbBaseAddr[larb]; + + mmu_en = m4uHw_get_field_by_mask(larb_base, SMI_LARB_MMU_EN, F_SMI_MMU_EN(larb_port, 1)); + sec = m4uHw_get_field_by_mask(larb_base, SMI_LARB_SEC_EN, F_SMI_SEC_EN(larb_port, 1)); + } else { + larb_port = m4u_port_2_larb_port(port); + mmu_en = m4uHw_get_field_by_mask(gPericfgBaseAddr, + REG_PERIAXI_BUS_CTL3, F_PERI_MMU_EN(larb_port, 1)); + } + + if (only_print_active && !mmu_en) + continue; + + M4U_PRINT_LOG_OR_SEQ(seq, "%s(%d),", m4u_get_port_name(port), !!mmu_en); + } + + larb_clock_all_off(); + + M4U_PRINT_LOG_OR_SEQ(seq, "\n"); +} + +/* +static int m4u_enable_prefetch(M4U_PORT_ID PortID) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_port_2_m4u_id(PortID)]; + m4uHw_set_field_by_mask(m4u_base, REG_MMU_CTRL_REG, F_MMU_CTRL_PFH_DIS(1), F_MMU_CTRL_PFH_DIS(0)); + return 0; +} + +static int m4u_disable_prefetch(M4U_PORT_ID PortID) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_port_2_m4u_id(PortID)]; + m4uHw_set_field_by_mask(m4u_base, REG_MMU_CTRL_REG, F_MMU_CTRL_PFH_DIS(1), F_MMU_CTRL_PFH_DIS(1)); + + return 0; +} + +static int m4u_enable_error_hang(int m4u_id) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + m4uHw_set_field_by_mask(m4u_base, REG_MMU_CTRL_REG, F_MMU_CTRL_INT_HANG_en(1), F_MMU_CTRL_INT_HANG_en(1)); + + return 0; +} + +static int m4u_disable_error_hang(int m4u_id) +{ + unsigned long m4u_base = gM4UBaseAddr[m4u_id]; + m4uHw_set_field_by_mask(m4u_base, REG_MMU_CTRL_REG, F_MMU_CTRL_INT_HANG_en(1), F_MMU_CTRL_INT_HANG_en(0)); + + return 0; +} +*/ + +int m4u_register_reclaim_callback(int port, m4u_reclaim_mva_callback_t *fn, void *data) +{ + if (port > M4U_PORT_UNKNOWN) { + M4UMSG("%s fail, port=%d\n", __func__, port); + return -1; + } + gM4uPort[port].reclaim_fn = fn; + gM4uPort[port].reclaim_data = data; + return 0; +} +int m4u_unregister_reclaim_callback(int port) +{ + if (port > M4U_PORT_UNKNOWN) { + M4UMSG("%s fail, port=%d\n", __func__, port); + return -1; + } + gM4uPort[port].reclaim_fn = NULL; + gM4uPort[port].reclaim_data = NULL; + return 0; +} + +int m4u_reclaim_notify(int port, unsigned int mva, unsigned int size) +{ + int i; + + for (i = 0; i < M4U_PORT_UNKNOWN; i++) + if (gM4uPort[i].reclaim_fn) + gM4uPort[i].reclaim_fn(port, mva, size, gM4uPort[i].reclaim_data); + return 0; +} + +int m4u_register_fault_callback(int port, m4u_fault_callback_t *fn, void *data) +{ + if (port > M4U_PORT_UNKNOWN) { + M4UMSG("%s fail, port=%d\n", __func__, port); + return -1; + } + gM4uPort[port].fault_fn = fn; + gM4uPort[port].fault_data = data; + return 0; +} + +int m4u_unregister_fault_callback(int port) +{ + if (port > M4U_PORT_UNKNOWN) { + M4UMSG("%s fail, port=%d\n", __func__, port); + return -1; + } + gM4uPort[port].fault_fn = NULL; + gM4uPort[port].fault_data = NULL; + return 0; +} + +int m4u_enable_tf(int port, bool fgenable) +{ + gM4uPort[port].enable_tf = fgenable; + return 0; +} + +/* ============================================================================== */ +static struct timer_list m4u_isr_pause_timer; + +static void m4u_isr_restart(unsigned long unused) +{ + M4UMSG("restart m4u irq\n"); + m4u_intr_modify_all(1); +} + +static int m4u_isr_pause_timer_init(void) +{ + init_timer(&m4u_isr_pause_timer); + m4u_isr_pause_timer.function = m4u_isr_restart; + return 0; +} + +static int m4u_isr_pause(int delay) +{ + m4u_intr_modify_all(0); /* disable all intr */ + m4u_isr_pause_timer.expires = jiffies + delay*HZ; /* delay seconds */ + add_timer(&m4u_isr_pause_timer); + M4UMSG("warning: stop m4u irq for %ds\n", delay); + return 0; +} + +static void m4u_isr_record(void) +{ + static int m4u_isr_cnt; + static unsigned long first_jiffies; + + /* we allow one irq in 1s, or we will disable them after 5s. */ + if (!m4u_isr_cnt || time_after(jiffies, first_jiffies + m4u_isr_cnt*HZ)) { + m4u_isr_cnt = 1; + first_jiffies = jiffies; + } else { + m4u_isr_cnt++; + if (m4u_isr_cnt >= 5) { + /* 5 irqs come in 5s, too many ! */ + /* disable irq for a while, to avoid HWT timeout */ + m4u_isr_pause(10); + m4u_isr_cnt = 0; + } + } +} + +#define MMU_INT_REPORT(mmu, mmu_2nd_id, id) M4UMSG("iommu%d_%d " #id "(0x%x) int happens!!\n", mmu, mmu_2nd_id, id) + +irqreturn_t MTK_M4U_isr(int irq, void *dev_id) +{ + unsigned long m4u_base; + unsigned int m4u_index; + + if (irq == gM4uDev->irq_num[0]) { + m4u_base = gM4UBaseAddr[0]; + m4u_index = 0; + } else { + M4UMSG("MTK_M4U_isr(), Invalid irq number %d\n", irq); + return -1; + } + + { + /* L2 interrupt */ + unsigned int regval = M4U_ReadReg32(m4u_base, REG_MMU_L2_FAULT_ST); + + M4UMSG("m4u L2 interrupt sta=0x%x\n", regval); + + if (regval&F_INT_L2_MULTI_HIT_FAULT) + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_MULTI_HIT_FAULT); + + if (regval&F_INT_L2_TABLE_WALK_FAULT) { + unsigned int fault_va, layer; + + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_TABLE_WALK_FAULT); + fault_va = M4U_ReadReg32(m4u_base, REG_MMU_TBWALK_FAULT_VA); + layer = fault_va&1; + fault_va &= (~1); + m4u_aee_print("L2 table walk fault: mva=0x%x, layer=%d\n", fault_va, layer); + } + + if (regval&F_INT_L2_PFH_DMA_FIFO_OVERFLOW) + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_PFH_DMA_FIFO_OVERFLOW); + + if (regval&F_INT_L2_MISS_DMA_FIFO_OVERFLOW) + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_MISS_DMA_FIFO_OVERFLOW); + + if (regval&F_INT_L2_INVALD_DONE) + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_INVALD_DONE); + + if (regval&F_INT_L2_PFH_OUT_FIFO_ERROR) + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_PFH_OUT_FIFO_ERROR); + + if (regval&F_INT_L2_PFH_IN_FIFO_ERROR) + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_PFH_IN_FIFO_ERROR); + + if (regval&F_INT_L2_MISS_OUT_FIFO_ERROR) + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_MISS_OUT_FIFO_ERROR); + + if (regval&F_INT_L2_MISS_IN_FIFO_ERR) + MMU_INT_REPORT(m4u_index, 0, F_INT_L2_MISS_IN_FIFO_ERR); + } + + { + unsigned int IntrSrc = M4U_ReadReg32(m4u_base, REG_MMU_MAIN_FAULT_ST); + int m4u_slave_id; + unsigned int regval; + int layer, write, m4u_port; + unsigned int fault_mva, fault_pa; + + M4UMSG("m4u main interrupt happened: sta=0x%x\n", IntrSrc); + + if (IntrSrc & (F_INT_MMU0_MAIN_MSK | F_INT_MMU0_MAU_MSK)) + m4u_slave_id = 0; + else { + m4u_clear_intr(m4u_index); + return 0; + } + + /* read error info from registers */ + fault_mva = M4U_ReadReg32(m4u_base, REG_MMU_FAULT_VA(m4u_slave_id)); + layer = !!(fault_mva & F_MMU_FAULT_VA_LAYER_BIT); + write = !!(fault_mva & F_MMU_FAULT_VA_WRITE_BIT); + fault_mva &= F_MMU_FAULT_VA_MSK; + fault_pa = M4U_ReadReg32(m4u_base, REG_MMU_INVLD_PA(m4u_slave_id)); + regval = M4U_ReadReg32(m4u_base, REG_MMU_INT_ID(m4u_slave_id)); + m4u_port = m4u_get_port_by_tf_id(m4u_index, regval); + + /* dump something quickly */ + m4u_dump_rs_info(m4u_index, m4u_slave_id); + m4u_dump_invalid_main_tlb(m4u_index, m4u_slave_id); + m4u_dump_main_tlb(m4u_index, 0); + m4u_dump_pfh_tlb(m4u_index); + + if (IntrSrc & F_INT_TRANSLATION_FAULT(m4u_slave_id)) { + int bypass_DISP_TF = 0; + + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_TRANSLATION_FAULT(m4u_slave_id)); + M4UMSG("fault: port=%s, mva=0x%x, pa=0x%x, layer=%d, wr=%d, 0x%x\n", + m4u_get_port_name(m4u_port), fault_mva, fault_pa, layer, write, regval); + + if (_is_display_port(m4u_port)) { + unsigned int valid_mva = 0; + unsigned int valid_size = 0; + unsigned int valid_mva_end = 0; + + m4u_query_mva_info(fault_mva-1, 0, &valid_mva, &valid_size); + if (0 != valid_mva && 0 != valid_size) + valid_mva_end = valid_mva+valid_size; + + if (0 != valid_mva_end && fault_mva < valid_mva_end+SZ_4K) { + M4UMSG("bypass disp TF, valid mva=0x%x, size=0x%x, mva_end=0x%x\n", + valid_mva, valid_size, valid_mva_end); + bypass_DISP_TF = 1; + } + } + + if (gM4uPort[m4u_port].enable_tf == 1 && bypass_DISP_TF == 0) { + m4u_dump_pte_nolock(m4u_get_domain_by_port(m4u_port), fault_mva); + + m4u_print_port_status(NULL, 1); + + /* call user's callback to dump user registers */ + if (m4u_port < M4U_PORT_UNKNOWN && gM4uPort[m4u_port].fault_fn) + gM4uPort[m4u_port].fault_fn(m4u_port, fault_mva, gM4uPort[m4u_port].fault_data); + + m4u_dump_buf_info(NULL); + if (m4u_port < M4U_PORT_UNKNOWN && NULL == gM4uPort[m4u_port].fault_data) { + m4u_aee_print( + "\nCRDISPATCH_KEY:M4U_%s\n, translation fault: port=%s, mva=0x%x, pa=0x%x\n", + m4u_get_port_name(m4u_port), m4u_get_port_name(m4u_port), + fault_mva, fault_pa); + } else { + m4u_aee_print( + "\nCRDISPATCH_KEY:M4U_%s\n, translation fault: port=%s, mva=0x%x, pa=0x%x\n", + (char *)gM4uPort[m4u_port].fault_data, + m4u_get_port_name(m4u_port), fault_mva, fault_pa); + } + } + + MMProfileLogEx(M4U_MMP_Events[M4U_MMP_M4U_ERROR], MMProfileFlagPulse, m4u_port, fault_mva); + } + + if (IntrSrc & F_INT_MAIN_MULTI_HIT_FAULT(m4u_slave_id)) + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_MAIN_MULTI_HIT_FAULT(m4u_slave_id)); + + if (IntrSrc & F_INT_INVALID_PHYSICAL_ADDRESS_FAULT(m4u_slave_id)) + if (!(IntrSrc & F_INT_TRANSLATION_FAULT(m4u_slave_id))) + MMU_INT_REPORT(m4u_index, m4u_slave_id, + F_INT_INVALID_PHYSICAL_ADDRESS_FAULT(m4u_slave_id)); + + if (IntrSrc & F_INT_ENTRY_REPLACEMENT_FAULT(m4u_slave_id)) + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_ENTRY_REPLACEMENT_FAULT(m4u_slave_id)); + + if (IntrSrc & F_INT_TLB_MISS_FAULT(m4u_slave_id)) + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_TLB_MISS_FAULT(m4u_slave_id)); + + if (IntrSrc & F_INT_MISS_FIFO_ERR(m4u_slave_id)) + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_MISS_FIFO_ERR(m4u_slave_id)); + + if (IntrSrc & F_INT_PFH_FIFO_ERR(m4u_slave_id)) + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_PFH_FIFO_ERR(m4u_slave_id)); + + if (IntrSrc & F_INT_MAU(m4u_slave_id, 0)) { + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_MAU(m4u_slave_id, 0)); + __mau_dump_status(m4u_index, m4u_slave_id, 0); + } + + if (IntrSrc & F_INT_MAU(m4u_slave_id, 1)) { + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_MAU(m4u_slave_id, 1)); + __mau_dump_status(m4u_index, m4u_slave_id, 1); + } + + if (IntrSrc & F_INT_MAU(m4u_slave_id, 2)) { + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_MAU(m4u_slave_id, 2)); + __mau_dump_status(m4u_index, m4u_slave_id, 2); + } + + if (IntrSrc & F_INT_MAU(m4u_slave_id, 3)) { + MMU_INT_REPORT(m4u_index, m4u_slave_id, F_INT_MAU(m4u_slave_id, 3)); + __mau_dump_status(m4u_index, m4u_slave_id, 3); + } + + m4u_clear_intr(m4u_index); + m4u_isr_record(); + } + + return IRQ_HANDLED; +} + +m4u_domain_t *m4u_get_domain_by_port(M4U_PORT_ID port) +{ + return &gM4uDomain; +} + +m4u_domain_t *m4u_get_domain_by_id(int id) +{ + return &gM4uDomain; +} + +int m4u_get_domain_nr(void) +{ + return 1; +} + +int m4u_reg_init(m4u_domain_t *m4u_domain, unsigned long ProtectPA, int m4u_id) +{ + unsigned int regval; + int i; + + M4UINFO("m4u_reg_init, ProtectPA = 0x%lx\n", ProtectPA); + + /* m4u clock is in infra domain, we never close this clock. */ + m4u_clock_on(); + +#ifdef M4U_FPGAPORTING +#if 0 + if (0 == m4u_id) { + unsigned long MMconfigBaseAddr; + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mmsys_config"); + MMconfigBaseAddr = (unsigned long)of_iomap(node, 0); + M4UINFO("MMconfigBaseAddr: 0x%lx\n", MMconfigBaseAddr); + M4U_WriteReg32(MMconfigBaseAddr, 0x108, 0xffffffff); + } +#endif +#endif + +/* ============================================= */ +/* SMI registers */ +/* ============================================= */ + /*bus selection: + control which m4u_slave each larb routes to. + this register is in smi_common domain + Threre is only one AXI channel in K2, so don't need to set + */ +/* ========================================= */ +/* larb init */ +/* ========================================= */ + if (0 == m4u_id) { + struct device_node *node = NULL; + + for (i = 0; i < SMI_LARB_NR; i++) { + node = of_find_compatible_node(NULL, NULL, gM4U_SMILARB[i]); + if (NULL == node) + M4UINFO("init larb %d error\n", i); + else { + gLarbBaseAddr[i] = (unsigned long)of_iomap(node, 0); + /* set mm engine domain */ + larb_clock_on(i); + M4U_WriteReg32(gLarbBaseAddr[i], SMI_LARB_DOMN_0, DOMAIN_VALUE); + M4U_WriteReg32(gLarbBaseAddr[i], SMI_LARB_DOMN_1, DOMAIN_VALUE); + M4U_WriteReg32(gLarbBaseAddr[i], SMI_LARB_DOMN_2, DOMAIN_VALUE); + M4U_WriteReg32(gLarbBaseAddr[i], SMI_LARB_DOMN_3, DOMAIN_VALUE); + larb_clock_off(i); + M4UINFO("init larb %d, 0x%lx\n", i, gLarbBaseAddr[i]); + } + } + } + +/* ========================================= */ +/* perisys init */ +/* ========================================= */ + if (1 == m4u_id) { + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,PERICFG"); + gPericfgBaseAddr = (unsigned long)of_iomap(node, 0); + + M4UINFO("gPericfgBaseAddr: 0x%lx\n", gPericfgBaseAddr); + } + +/* ============================================= */ +/* m4u registers */ +/* ============================================= */ + M4UINFO("m4u hw init id = %d, base address: 0x%lx, pgd_pa: 0x%x\n", + m4u_id, gM4UBaseAddr[m4u_id], (unsigned int)m4u_domain->pgd_pa); + + { + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMUg_PT_BASE, (unsigned int)m4u_domain->pgd_pa); + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMUg_PT_BASE_SEC, (unsigned int)m4u_domain->pgd_pa); + + regval = M4U_ReadReg32(gM4UBaseAddr[m4u_id], REG_MMU_CTRL_REG); + + if (0 == m4u_id) { /* mm_iommu */ + regval = regval|F_MMU_CTRL_PFH_DIS(0) + |F_MMU_CTRL_MONITOR_EN(0) + |F_MMU_CTRL_MONITOR_CLR(0) + |F_MMU_CTRL_TF_PROTECT_SEL(2) + |F_MMU_CTRL_INT_HANG_EN(0); + } + + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_CTRL_REG, regval); + + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_MMU_COHERENCE_EN, 1); + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_MMU_TABLE_WALK_DIS, 0); + + /* enable all interrupts */ + m4u_enable_intr(m4u_id); + + /* set translation fault proctection buffer address */ + if (!gM4U_4G_DRAM_Mode) + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_IVRP_PADDR, + (unsigned int)F_MMU_IVRP_PA_SET(ProtectPA)); + else + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_IVRP_PADDR, + (unsigned int)F_MMU_IVRP_4G_DRAM_PA_SET(ProtectPA)); + + /* enable DCM */ + M4U_WriteReg32(gM4UBaseAddr[m4u_id], REG_MMU_DCM_DIS, 0); + + m4u_invalid_tlb_all(m4u_id); + } + + /* special settings for mmu0 (multimedia iommu) */ + if (0 == m4u_id) { + unsigned long m4u_base = gM4UBaseAddr[0]; + /* 2 disable in-order-write */ + M4U_WriteReg32(m4u_base, REG_MMU_IN_ORDER_WR_EN, 0); + + /* 3 non-standard AXI mode */ + M4U_WriteReg32(m4u_base, REG_MMU_STANDARD_AXI_MODE, 0); + /* 4 write command throttling mode */ + m4uHw_set_field_by_mask(m4u_base, REG_MMU_WR_LEN, F_BIT_SET(5), 0); + } + + return 0; +} + +int m4u_domain_init(struct m4u_device *m4u_dev, void *priv_reserve) +{ + M4UINFO("m4u_domain_init\n"); + + memset(&gM4uDomain, 0, sizeof(gM4uDomain)); + gM4uDomain.pgsize_bitmap = M4U_PGSIZES; + mutex_init(&gM4uDomain.pgtable_mutex); + + m4u_pgtable_init(m4u_dev, &gM4uDomain); + + m4u_mvaGraph_init(priv_reserve); + + return 0; +} + +int m4u_reset(int m4u_id) +{ + m4u_invalid_tlb_all(m4u_id); + m4u_clear_intr(m4u_id); + + return 0; +} + +int m4u_hw_init(struct m4u_device *m4u_dev, int m4u_id) +{ + unsigned long pProtectVA; + phys_addr_t ProtectPA; + +#if !defined(CONFIG_MTK_CLKMGR) + int i; + + /*gM4uDev->infra_m4u = devm_clk_get(gM4uDev->pDev[m4u_id], "infra_m4u"); + if (IS_ERR(gM4uDev->infra_m4u)) { + M4UMSG("cannot get infra m4u clock\n"); + return PTR_ERR(gM4uDev->infra_m4u); + }*/ + + for (i = SMI_COMMON_CLK; i < SMI_CLK_NUM; i++) { + gM4uDev->smi_clk[i] = devm_clk_get(gM4uDev->pDev[m4u_id], smi_clk_name[i]); + if (IS_ERR(gM4uDev->smi_clk[i])) { + M4UMSG("cannot get %s clock\n", smi_clk_name[i]); + return PTR_ERR(gM4uDev->smi_clk[i]); + } + } + smi_larb_clock_prepare(); +#endif + +#ifdef M4U_4GBDRAM + gM4U_4G_DRAM_Mode = enable_4G(); +#endif + M4UMSG("4G DRAM Mode is: %d\n", gM4U_4G_DRAM_Mode); + + gM4UBaseAddr[m4u_id] = m4u_dev->m4u_base[m4u_id]; + + pProtectVA = (unsigned long) kmalloc(TF_PROTECT_BUFFER_SIZE*2, GFP_KERNEL|__GFP_ZERO); + if (NULL == (void *)pProtectVA) { + M4UMSG("Physical memory not available.\n"); + return -1; + } + pProtectVA = (pProtectVA+(TF_PROTECT_BUFFER_SIZE-1))&(~(TF_PROTECT_BUFFER_SIZE-1)); + ProtectPA = virt_to_phys((void *)pProtectVA); + if (ProtectPA & (TF_PROTECT_BUFFER_SIZE-1)) { + M4UMSG("protect buffer (0x%pa) not align.\n", &ProtectPA); + return -1; + } + + M4UINFO("protect memory va=0x%pa, pa=0x%pa.\n", &pProtectVA, &ProtectPA); + + pM4URegBackUp = kmalloc(M4U_REG_BACKUP_SIZE, GFP_KERNEL|__GFP_ZERO); + if (pM4URegBackUp == NULL) { + M4UMSG("Physical memory not available size=%d.\n", (int)M4U_REG_BACKUP_SIZE); + return -1; + } + + spin_lock_init(&gM4u_reg_lock); + + m4u_reg_init(&gM4uDomain, ProtectPA, m4u_id); + + if (request_irq(m4u_dev->irq_num[m4u_id], MTK_M4U_isr, IRQF_TRIGGER_LOW, "m4u", NULL)) { + M4UMSG("request M4U%d IRQ line failed\n", m4u_id); + return -ENODEV; + } + + M4UMSG("request_irq, irq_num=%d\n", m4u_dev->irq_num[m4u_id]); + + m4u_isr_pause_timer_init(); + + m4u_monitor_start(m4u_id); + + /* mau_start_monitor(0, 0, 0, 0, 1, 0, 0, 0x0, 0x1000, 0xffffffff, 0xffffffff); */ + /* mau_start_monitor(0, 0, 1, 1, 1, 0, 0, 0x0, 0x1000, 0xffffffff, 0xffffffff); */ + /* mau_start_monitor(0, 0, 2, 0, 0, 0, 0, 0x0, 0x1000, 0xffffffff, 0xffffffff); */ + + /* config MDP related port default use M4U */ + + if (0 == m4u_id) { + M4U_PORT_STRUCT port; + + port.Direction = 0; + port.Distance = 1; + port.domain = 0; + port.Security = 0; + port.Virtuality = 1; + + port.ePortID = M4U_PORT_MDP_RDMA; + m4u_config_port(&port); + + port.ePortID = M4U_PORT_MDP_WDMA; + m4u_config_port(&port); + + port.ePortID = M4U_PORT_MDP_WROT; + m4u_config_port(&port); + } + + return 0; +} + +int m4u_hw_deinit(struct m4u_device *m4u_dev, int m4u_id) +{ +#if !defined(CONFIG_MTK_CLKMGR) + smi_larb_clock_unprepare(); +#endif + +#if 1 + free_irq(m4u_dev->irq_num[m4u_id], NULL); +#else + free_irq(MM_IOMMU_IRQ_B_ID, NULL); + free_irq(PERISYS_IOMMU_IRQ_B_ID, NULL); +#endif + return 0; +} + +int m4u_dump_reg_for_smi_hang_issue(void) +{ + /*NOTES: m4u_monitor_start() must be called before using m4u */ + /*please check m4u_hw_init() to ensure that */ + + M4UMSG("====== dump m4u reg start =======>\n"); + + if (0 == gM4UBaseAddr[0]) { + M4UMSG("gM4UBaseAddr[0] is NULL\n"); + return 0; + } + M4UMSG("0x44 = 0x%x\n", M4U_ReadReg32(gM4UBaseAddr[0], 0x44)); + + m4u_print_perf_counter(0, 0, "m4u"); + m4u_dump_rs_info(0, 0); + + return 0; +} diff --git a/drivers/misc/mediatek/m4u/mt6755/m4u_hw.h b/drivers/misc/mediatek/m4u/mt6755/m4u_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..13aea99076e92727f37d9b7387dbfa057e3fca6f --- /dev/null +++ b/drivers/misc/mediatek/m4u/mt6755/m4u_hw.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __M4U_HW_H__ +#define __M4U_HW_H__ + +#define M4U_PGSIZES (SZ_4K | SZ_64K | SZ_1M | SZ_16M) + +#define TOTAL_M4U_NUM 1 + +#define M4U_SLAVE_NUM(m4u_id) ((m4u_id) ? 1 : 1) /* m4u0 has 1 slaves, iommu(m4u1) has 1 slave */ + +/* seq range related */ +#define SEQ_NR_PER_MM_SLAVE 8 +#define SEQ_NR_PER_PERI_SLAVE 0 + +#define M4U0_SEQ_NR (SEQ_NR_PER_MM_SLAVE*M4U_SLAVE_NUM(0)) +#define M4U1_SEQ_NR (SEQ_NR_PER_PERI_SLAVE*M4U_SLAVE_NUM(1)) +#define M4U_SEQ_NUM(m4u_id) ((m4u_id) ? M4U1_SEQ_NR : M4U0_SEQ_NR) + +#define M4U0_MAU_NR 4 + +#define M4U_SEQ_ALIGN_MSK (0x100000-1) +#define M4U_SEQ_ALIGN_SIZE 0x100000 + +/* mau related */ +#define MAU_NR_PER_M4U_SLAVE 4 + +/* smi */ +#define SMI_LARB_NR 4 + +/* prog pfh dist related */ +#define PROG_PFH_DIST 8 + +#define M4U0_PROG_PFH_NR (PROG_PFH_DIST*M4U_SLAVE_NUM(0)) +#define M4U1_PROG_PFH_NR (PROG_PFH_DIST*M4U_SLAVE_NUM(1)) +#define M4U_PROG_PFH_NUM(m4u_id) ((m4u_id) ? M4U1_PROG_PFH_NR : M4U0_PROG_PFH_NR) + +#define DOMAIN_VALUE 0x44444444 + +typedef struct _M4U_PERF_COUNT { + unsigned int transaction_cnt; + unsigned int main_tlb_miss_cnt; + unsigned int pfh_tlb_miss_cnt; + unsigned int pfh_cnt; + unsigned int rs_perf_cnt; +} M4U_PERF_COUNT; + +typedef struct __mmu_tlb { + unsigned int tag; + unsigned int desc; +} mmu_tlb_t; + +typedef struct _pfh_tlb { + unsigned int va; + unsigned int va_msk; + char layer; + char x16; + char sec; + char pfh; + char valid; + unsigned int desc[MMU_PAGE_PER_LINE]; + int set; + int way; + unsigned int page_size; + unsigned int tag; +} mmu_pfh_tlb_t; + +typedef struct { + char *name; + unsigned m4u_id:2; + unsigned m4u_slave:2; + unsigned larb_id:4; + unsigned larb_port:8; + unsigned tf_id:12; /* 12 bits */ + bool enable_tf; + m4u_reclaim_mva_callback_t *reclaim_fn; + void *reclaim_data; + m4u_fault_callback_t *fault_fn; + void *fault_data; +} m4u_port_t; + +typedef struct _M4U_RANGE_DES /* sequential entry range */ +{ + unsigned int Enabled; + M4U_PORT_ID port; + unsigned int MVAStart; + unsigned int MVAEnd; + /* unsigned int entryCount; */ +} M4U_RANGE_DES_T; + +typedef struct _M4U_MAU_STATUS /* mau entry */ +{ + bool Enabled; + M4U_PORT_ID port; + unsigned int MVAStart; + unsigned int MVAEnd; +} M4U_MAU_STATUS_T; + +typedef struct _M4U_PROG_DIST /* prog pfh dist */ +{ + unsigned int Enabled; + M4U_PORT_ID port; + unsigned int axi_id; + unsigned int dir; + unsigned int dist; + unsigned int en; + unsigned int sel; +} M4U_PROG_DIST_T; + +extern m4u_port_t gM4uPort[]; +extern int gM4u_port_num; + +static inline char *m4u_get_port_name(M4U_PORT_ID portID) +{ + if (portID < gM4u_port_num) + return gM4uPort[portID].name; + else + return "m4u_port_unknown"; +} + +static inline int m4u_get_port_by_tf_id(int m4u_id, int tf_id) +{ + int i, tf_id_old; + + tf_id_old = tf_id; + + if (m4u_id == 0) + tf_id &= F_MMU0_INT_ID_TF_MSK; + + for (i = 0; i < gM4u_port_num; i++) + if ((gM4uPort[i].tf_id == tf_id) && (gM4uPort[i].m4u_id == m4u_id)) + return i; + M4UMSG("error: m4u_id=%d, tf_id=0x%x\n", m4u_id, tf_id_old); + return gM4u_port_num; +} + +static inline int m4u_port_2_larb_port(M4U_PORT_ID port) +{ + return gM4uPort[port].larb_port; +} + +static inline int m4u_port_2_larb_id(M4U_PORT_ID port) +{ + return gM4uPort[port].larb_id; +} + +static inline int larb_2_m4u_slave_id(int larb) +{ + int i; + + for (i = 0; i < gM4u_port_num; i++) + if (gM4uPort[i].larb_id == larb) + return gM4uPort[i].m4u_slave; + return 0; +} + +static inline int m4u_port_2_m4u_id(M4U_PORT_ID port) +{ + return gM4uPort[port].m4u_id; +} + +static inline int m4u_port_2_m4u_slave_id(M4U_PORT_ID port) +{ + return gM4uPort[port].m4u_slave; +} + +static inline int larb_port_2_m4u_port(int larb, int larb_port) +{ + int i; + + for (i = 0; i < gM4u_port_num; i++) + if (gM4uPort[i].larb_id == larb && gM4uPort[i].larb_port == larb_port) + return i; + /* M4UMSG("unknown larb port: larb=%d, larb_port=%d\n", larb, larb_port); */ + return M4U_PORT_UNKNOWN; +} + +void m4u_print_perf_counter(int m4u_index, int m4u_slave_id, const char *msg); +int m4u_dump_reg(int m4u_index, unsigned int start); +void smi_common_clock_on(void); +void smi_common_clock_off(void); + +/* For build while larb0 clk has not been implemented.*/ +static inline void smi_larb0_clock_on(void) {} +static inline void smi_larb0_clock_off(void) {} + +extern struct m4u_device *gM4uDev; + +#if !defined(CONFIG_MTK_LEGACY) +extern const char *smi_clk_name[]; +#endif + +#ifdef M4U_TEE_SERVICE_ENABLE +extern int m4u_tee_en; +#endif + +#endif diff --git a/drivers/misc/mediatek/m4u/mt6755/m4u_platform.h b/drivers/misc/mediatek/m4u/mt6755/m4u_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..40b57975150c561c4850b1162a2eb5d92ef47f8e --- /dev/null +++ b/drivers/misc/mediatek/m4u/mt6755/m4u_platform.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __M4U_PORT_PRIV_H__ +#define __M4U_PORT_PRIV_H__ + +static const char * const gM4U_SMILARB[] = { + "mediatek,smi_larb0", "mediatek,smi_larb1", "mediatek,smi_larb2", "mediatek,smi_larb3"}; + + +#define M4U0_PORT_INIT(name, slave, larb, port) {\ + name, 0, slave, larb, port, (((larb)<<7)|((port)<<2)), 1\ +} + +m4u_port_t gM4uPort[] = { + + M4U0_PORT_INIT("DISP_OVL0", 0, 0, 0), + M4U0_PORT_INIT("DISP_RDMA0", 0, 0, 1), + M4U0_PORT_INIT("DISP_WDMA0", 0, 0, 2), + M4U0_PORT_INIT("DISP_OVL1", 0, 0, 3), + M4U0_PORT_INIT("DISP_RDMA1", 0, 0, 4), + M4U0_PORT_INIT("DISP_WDMA1", 0, 0, 5), + M4U0_PORT_INIT("DISP_2L_OVL0", 0, 0, 6), + M4U0_PORT_INIT("DISP_2L_OVL1", 0, 0, 7), + M4U0_PORT_INIT("MDP_RDMA", 0, 0, 8), + M4U0_PORT_INIT("MDP_WDMA", 0, 0, 9), + M4U0_PORT_INIT("MDP_WROT", 0, 0, 10), + + M4U0_PORT_INIT("VDEC_MC", 0, 1, 0), + M4U0_PORT_INIT("VDEC_PP", 0, 1, 1), + M4U0_PORT_INIT("VDEC_VLD", 0, 1, 3), + M4U0_PORT_INIT("VDEC_AVC_MV", 0, 1, 4), + M4U0_PORT_INIT("VDEC_PRED_RD", 0, 1, 5), + M4U0_PORT_INIT("VDEC_PRED_WR", 0, 1, 6), + M4U0_PORT_INIT("VDEC_PPWRAP", 0, 1, 7), + + M4U0_PORT_INIT("CAM_IMGO", 0, 2, 0), + M4U0_PORT_INIT("CAM_RRZO", 0, 2, 1), + M4U0_PORT_INIT("CAM_AAO", 0, 2, 2), + M4U0_PORT_INIT("CAM_LCSO", 0, 2, 3), + M4U0_PORT_INIT("CAM_ESFKO", 0, 2, 4), + M4U0_PORT_INIT("CAM_IMGO_S", 0, 2, 5), + M4U0_PORT_INIT("CAM_LSCI", 0, 2, 6), + M4U0_PORT_INIT("CAM_LSCI_D", 0, 2, 7), + M4U0_PORT_INIT("CAM_BPCI", 0, 2, 8), + M4U0_PORT_INIT("CAM_BPCI_D", 0, 2, 9), + M4U0_PORT_INIT("CAM_UFDI", 0, 2, 10), + M4U0_PORT_INIT("CAM_IMGI", 0, 2, 11), + M4U0_PORT_INIT("CAM_IMG2O", 0, 2, 12), + M4U0_PORT_INIT("CAM_IMG3O", 0, 2, 13), + M4U0_PORT_INIT("CAM_VIPI", 0, 2, 14), + M4U0_PORT_INIT("CAM_VIP2I", 0, 2, 15), + M4U0_PORT_INIT("CAM_VIP3I", 0, 2, 16), + M4U0_PORT_INIT("CAM_LCEI", 0, 2, 17), + M4U0_PORT_INIT("CAM_RB", 0, 2, 18), + M4U0_PORT_INIT("CAM_RP", 0, 2, 19), + M4U0_PORT_INIT("CAM_WR", 0, 2, 20), + + M4U0_PORT_INIT("VENC_RCPU", 0, 3, 0), + M4U0_PORT_INIT("VENC_REC", 0, 3, 1), + M4U0_PORT_INIT("VENC_BSDMA", 0, 3, 2), + M4U0_PORT_INIT("VENC_SV_COMV", 0, 3, 3), + M4U0_PORT_INIT("VENC_RD_COMV", 0, 3, 4), + M4U0_PORT_INIT("JPGENC_RDMA", 0, 3, 5), + M4U0_PORT_INIT("JPGENC_BSDMA", 0, 3, 6), + M4U0_PORT_INIT("JPGDEC_WDMA", 0, 3, 7), + M4U0_PORT_INIT("JPGDEC_BSDMA", 0, 3, 8), + M4U0_PORT_INIT("VENC_CUR_LUMA", 0, 3, 9), + M4U0_PORT_INIT("VENC_CUR_CHROMA", 0, 3, 10), + M4U0_PORT_INIT("VENC_REF_LUMA", 0, 3, 11), + M4U0_PORT_INIT("VENC_REF_CHROMA", 0, 3, 12), + + M4U0_PORT_INIT("UNKNOWN", 0, 4, 0), +}; + +#endif diff --git a/drivers/misc/mediatek/m4u/mt6755/m4u_port.h b/drivers/misc/mediatek/m4u/mt6755/m4u_port.h new file mode 100644 index 0000000000000000000000000000000000000000..870aaf40417fedec1a794a364f686a719b31e7dc --- /dev/null +++ b/drivers/misc/mediatek/m4u/mt6755/m4u_port.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __M4U_PORT_H__ +#define __M4U_PORT_H__ + +/* ==================================== */ +/* about portid */ +/* ==================================== */ + +enum { + M4U_PORT_DISP_OVL0 , + M4U_PORT_DISP_RDMA0 , + M4U_PORT_DISP_WDMA0 , + M4U_PORT_DISP_OVL1 , + M4U_PORT_DISP_RDMA1 , + M4U_PORT_DISP_WDMA1 , + M4U_PORT_DISP_2L_OVL0 , + M4U_PORT_DISP_2L_OVL1 , + M4U_PORT_MDP_RDMA , + M4U_PORT_MDP_WDMA , + M4U_PORT_MDP_WROT , + + M4U_PORT_HW_VDEC_MC_EXT , + M4U_PORT_HW_VDEC_PP_EXT , + M4U_PORT_HW_VDEC_VLD_EXT , + M4U_PORT_HW_VDEC_AVC_MV_EXT , + M4U_PORT_HW_VDEC_PRED_RD_EXT , + M4U_PORT_HW_VDEC_PRED_WR_EXT , + M4U_PORT_HW_VDEC_PPWRAP_EXT , + + M4U_PORT_IMGO , + M4U_PORT_RRZO , + M4U_PORT_AAO , + M4U_PORT_LCSO , + M4U_PORT_ESFKO , + M4U_PORT_IMGO_S , + M4U_PORT_LSCI , + M4U_PORT_LSCI_D , + M4U_PORT_BPCI , + M4U_PORT_BPCI_D , + M4U_PORT_UFDI , + M4U_PORT_IMGI , + M4U_PORT_IMG2O , + M4U_PORT_IMG3O , + M4U_PORT_VIPI , + M4U_PORT_VIP2I , + M4U_PORT_VIP3I , + M4U_PORT_LCEI , + M4U_PORT_RB , + M4U_PORT_RP , + M4U_PORT_WR , + + M4U_PORT_VENC_RCPU , + M4U_PORT_VENC_REC , + M4U_PORT_VENC_BSDMA , + M4U_PORT_VENC_SV_COMV , + M4U_PORT_VENC_RD_COMV , + M4U_PORT_JPGENC_RDMA , + M4U_PORT_JPGENC_BSDMA , + M4U_PORT_JPGDEC_WDMA , + M4U_PORT_JPGDEC_BSDMA , + M4U_PORT_VENC_CUR_LUMA , + M4U_PORT_VENC_CUR_CHROMA , + M4U_PORT_VENC_REF_LUMA , + M4U_PORT_VENC_REF_CHROMA , + + M4U_PORT_UNKNOWN , +}; +#define M4U_PORT_NR M4U_PORT_UNKNOWN + +#endif + diff --git a/drivers/misc/mediatek/m4u/mt6755/m4u_priv.h b/drivers/misc/mediatek/m4u/mt6755/m4u_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..96ad79507b58bbaf48e5728f79f953d25ecdf233 --- /dev/null +++ b/drivers/misc/mediatek/m4u/mt6755/m4u_priv.h @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __M4U_PRIV_H__ +#define __M4U_PRIV_H__ +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT) +#define M4U_TEE_SERVICE_ENABLE +#endif + +#include "m4u.h" +#include "m4u_reg.h" +#include "../2.0/m4u_pgtable.h" + +#define M4UMSG(string, args...) pr_err("M4U"string, ##args) +#define M4UINFO(string, args...) pr_debug("M4U"string, ##args) + +#include "m4u_hw.h" + +/* #define M4U_FPGAPORTING */ +#define M4U_PROFILE +#define M4U_4GBDRAM + +#define M4U_DVT 0 + +#ifndef M4U_PROFILE +#define MMProfileLogEx(...) +#define MMProfileEnable(...) +#define MMProfileStart(...) +#define MMP_Event unsigned int +#else +#include + +extern void MMProfileEnable(int enable); +extern void MMProfileStart(int start); + +#endif + + +#ifndef dmac_map_area +#define dmac_map_area __dma_map_area +#endif + +#ifndef dmac_unmap_area +#define dmac_unmap_area __dma_unmap_area +#endif + +#ifndef dmac_flush_range +#define dmac_flush_range __dma_flush_range +#endif + +#ifndef outer_clean_all +#define outer_clean_all(...) +#endif + +#ifndef outer_flush_all +#define outer_flush_all(...) +#endif + +#ifdef M4U_FPGAPORTING +#define enable_clock(...) +#define disable_clock(...) +#define smp_inner_dcache_flush_all(...) +#define register_larb_monitor(...) +#endif + +#ifdef M4U_TEE_SERVICE_ENABLE +extern int gM4U_L2_enable; +#endif + +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include +#endif + +#if !defined(CONFIG_MTK_CLKMGR) + +enum { + SMI_COMMON_CLK, + DISP0_SMI_LARB0_CLK, + VDEC0_VDEC_CLK, + VDEC1_LARB_CLK, + LARB2_SMI_CLK, + VENC_VENC_CLK, + VENC_LARB_CLK, + NTCMOS_VEN, + NTCMOS_VDE, + NTCMOS_ISP, + NTCMOS_DIS, + SMI_CLK_NUM, +}; + +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + +struct m4u_device { + struct miscdevice dev; + struct proc_dir_entry *m4u_dev_proc_entry; + struct device *pDev[TOTAL_M4U_NUM]; + struct dentry *debug_root; + unsigned long m4u_base[TOTAL_M4U_NUM]; + unsigned int irq_num[TOTAL_M4U_NUM]; +#if !defined(CONFIG_MTK_CLKMGR) + struct clk *infra_m4u; + struct clk *smi_clk[SMI_CLK_NUM]; +#endif +}; + +typedef struct { + imu_pgd_t *pgd; + dma_addr_t pgd_pa; + struct mutex pgtable_mutex; + unsigned int pgsize_bitmap; +} m4u_domain_t; + +typedef struct { + struct list_head link; + unsigned long va; + unsigned int mva; + unsigned int size; + M4U_PORT_ID port; + unsigned int prot; + unsigned int flags; + struct sg_table *sg_table; + + unsigned int mva_align; + unsigned int size_align; + int seq_id; + unsigned long mapped_kernel_va_for_debug; +} m4u_buf_info_t; + +typedef struct _M4U_MAU { + M4U_PORT_ID port; + bool write; + unsigned int mva; + unsigned int size; + bool enable; + bool force; +} M4U_MAU_STRUCT; + +typedef struct _M4U_TF { + M4U_PORT_ID port; + bool fgEnable; +} M4U_TF_STRUCT; + +/* ================================ */ +/* === define in m4u_mva.c========= */ + +typedef int (mva_buf_fn_t)(void *priv, unsigned int mva_start, unsigned int mva_end, void *data); + +void m4u_mvaGraph_init(void *priv_reserve); +void m4u_mvaGraph_dump_raw(void); +void m4u_mvaGraph_dump(void); +void *mva_get_priv_ext(unsigned int mva); +int mva_foreach_priv(mva_buf_fn_t *fn, void *data); +void *mva_get_priv(unsigned int mva); +unsigned int m4u_do_mva_alloc(unsigned long va, unsigned int size, void *priv); +unsigned int m4u_do_mva_alloc_fix(unsigned int mva, unsigned int size, void *priv); +int m4u_do_mva_free(unsigned int mva, unsigned int size); + +/* ================================= */ +/* ==== define in m4u_pgtable.c===== */ +void m4u_dump_pgtable(m4u_domain_t *domain, struct seq_file *seq); +void m4u_dump_pte_nolock(m4u_domain_t *domain, unsigned int mva); +void m4u_dump_pte(m4u_domain_t *domain, unsigned int mva); +int m4u_pgtable_init(struct m4u_device *m4u_dev, m4u_domain_t *m4u_domain); +int m4u_map_4K(m4u_domain_t *m4u_domain, unsigned int mva, phys_addr_t pa, unsigned int prot); +int m4u_clean_pte(m4u_domain_t *domain, unsigned int mva, unsigned int size); + +unsigned long m4u_get_pte(m4u_domain_t *domain, unsigned int mva); + + +/* ================================= */ +/* ==== define in m4u_hw.c ===== */ +void m4u_invalid_tlb_by_range(m4u_domain_t *m4u_domain, unsigned int mva_start, unsigned int mva_end); +m4u_domain_t *m4u_get_domain_by_port(M4U_PORT_ID port); +m4u_domain_t *m4u_get_domain_by_id(int id); +int m4u_get_domain_nr(void); +int m4u_reclaim_notify(int port, unsigned int mva, unsigned int size); +int m4u_hw_init(struct m4u_device *m4u_dev, int m4u_id); +int m4u_hw_deinit(struct m4u_device *m4u_dev, int m4u_id); +int m4u_reg_backup(void); +int m4u_reg_restore(void); +int m4u_insert_seq_range(M4U_PORT_ID port, unsigned int MVAStart, unsigned int MVAEnd); +int m4u_invalid_seq_range_by_id(int port, int seq_id); +void m4u_print_port_status(struct seq_file *seq, int only_print_active); + +int m4u_dump_main_tlb(int m4u_id, int m4u_slave_id); +int m4u_dump_pfh_tlb(int m4u_id); +int m4u_domain_init(struct m4u_device *m4u_dev, void *priv_reserve); + +int config_mau(M4U_MAU_STRUCT mau); +int m4u_enable_tf(int port, bool fgenable); + +extern int gM4U_4G_DRAM_Mode; + +/* ================================= */ +/* ==== define in m4u.c ===== */ +int m4u_dump_buf_info(struct seq_file *seq); +int m4u_map_sgtable(m4u_domain_t *m4u_domain, unsigned int mva, + struct sg_table *sg_table, unsigned int size, unsigned int prot); +int m4u_unmap(m4u_domain_t *domain, unsigned int mva, unsigned int size); + + +void m4u_get_pgd(m4u_client_t *client, M4U_PORT_ID port, void **pgd_va, void **pgd_pa, unsigned int *size); +unsigned long m4u_mva_to_pa(m4u_client_t *client, M4U_PORT_ID port, unsigned int mva); +int m4u_query_mva_info(unsigned int mva, unsigned int size, unsigned int *real_mva, unsigned int *real_size); + +/* ================================= */ +/* ==== define in m4u_debug.c ===== */ +int m4u_debug_init(struct m4u_device *m4u_dev); + +static inline dma_addr_t get_sg_phys(struct scatterlist *sg) +{ + dma_addr_t pa; + + pa = sg_dma_address(sg); + if (pa == 0) + pa = sg_phys(sg); + return pa; +} + +#define M4U_PGD_SIZE (16*1024) + +#define M4U_LOG_LEVEL_HIGH 3 +#define M4U_LOG_LEVEL_MID 2 +#define M4U_LOG_LEVEL_LOW 1 + +extern int gM4U_log_level; +extern int gM4U_log_to_uart; +#define _M4ULOG(level, string, args...) \ + do {\ + if (level > gM4U_log_level) {\ + if (level > gM4U_log_to_uart)\ + pr_warn("M4U"string, ##args);\ + else\ + pr_warn("M4U"string, ##args);\ + } \ + } while (0) + +#define M4ULOG_LOW(string, args...) _M4ULOG(M4U_LOG_LEVEL_LOW, string, ##args) +#define M4ULOG_MID(string, args...) _M4ULOG(M4U_LOG_LEVEL_MID, string, ##args) +#define M4ULOG_HIGH(string, args...) _M4ULOG(M4U_LOG_LEVEL_HIGH, string, ##args) + +#define M4UERR(string, args...) pr_err("M4U error: "string, ##args) + +/*aee_kernel_exception("M4U", "[M4U] error:"string,##args); */ + +#define m4u_aee_print(string, args...) do {\ + char m4u_name[100];\ + snprintf(m4u_name, 100, "[M4U]"string, ##args); \ + aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_MMPROFILE_BUFFER | DB_OPT_DUMP_DISPLAY, \ + m4u_name, "[M4U] error"string, ##args); \ + pr_err("M4U error: "string, ##args); \ +} while (0) +/*aee_kernel_warning(m4u_name, "[M4U] error:"string,##args); */ + +#define M4U_PRINT_LOG_OR_SEQ(seq_file, fmt, args...) \ + do {\ + if (seq_file)\ + seq_printf(seq_file, fmt, ##args);\ + else\ + pr_warn(fmt, ##args);\ + } while (0) + +/* ======================================= */ +/* ==== other macros ============ */ +#define M4U_GET_PAGE_NUM(va, size) ((((va)&(PAGE_SIZE-1))+(size)+(PAGE_SIZE-1))>>12) +#define M4U_PAGE_MASK 0xfffL + +typedef enum { + M4U_MMP_ALLOC_MVA = 0, + M4U_MMP_DEALLOC_MVA, + M4U_MMP_CONFIG_PORT, + M4U_MMP_M4U_ERROR, + M4U_MMP_CACHE_SYNC, + M4U_MMP_TOGGLE_CG, + M4U_MMP_MAX, +} M4U_MMP_TYPE; + +typedef struct { + M4U_PORT_ID port; + unsigned long BufAddr; + unsigned int BufSize; + unsigned int prot; + unsigned int MVAStart; + unsigned int MVAEnd; + unsigned int flags; +} M4U_MOUDLE_STRUCT; + +typedef struct { + M4U_PORT_ID port; + M4U_CACHE_SYNC_ENUM eCacheSync; + unsigned long va; + unsigned int size; + unsigned int mva; +} M4U_CACHE_STRUCT; + +typedef struct _M4U_DMA { + M4U_PORT_ID port; + M4U_DMA_TYPE eDMAType; + M4U_DMA_DIR eDMADir; + unsigned long va; + unsigned int size; + unsigned int mva; +} M4U_DMA_STRUCT; + +/* IOCTL commnad */ +#define MTK_M4U_MAGICNO 'g' +#define MTK_M4U_T_POWER_ON _IOW(MTK_M4U_MAGICNO, 0, int) +#define MTK_M4U_T_POWER_OFF _IOW(MTK_M4U_MAGICNO, 1, int) +#define MTK_M4U_T_DUMP_REG _IOW(MTK_M4U_MAGICNO, 2, int) +#define MTK_M4U_T_DUMP_INFO _IOW(MTK_M4U_MAGICNO, 3, int) +#define MTK_M4U_T_ALLOC_MVA _IOWR(MTK_M4U_MAGICNO, 4, int) +#define MTK_M4U_T_DEALLOC_MVA _IOW(MTK_M4U_MAGICNO, 5, int) +#define MTK_M4U_T_INSERT_TLB_RANGE _IOW(MTK_M4U_MAGICNO, 6, int) +#define MTK_M4U_T_INVALID_TLB_RANGE _IOW(MTK_M4U_MAGICNO, 7, int) +#define MTK_M4U_T_INVALID_TLB_ALL _IOW(MTK_M4U_MAGICNO, 8, int) +#define MTK_M4U_T_MANUAL_INSERT_ENTRY _IOW(MTK_M4U_MAGICNO, 9, int) +#define MTK_M4U_T_CACHE_SYNC _IOW(MTK_M4U_MAGICNO, 10, int) +#define MTK_M4U_T_CONFIG_PORT _IOW(MTK_M4U_MAGICNO, 11, int) +#define MTK_M4U_T_CONFIG_ASSERT _IOW(MTK_M4U_MAGICNO, 12, int) +#define MTK_M4U_T_INSERT_WRAP_RANGE _IOW(MTK_M4U_MAGICNO, 13, int) +#define MTK_M4U_T_MONITOR_START _IOW(MTK_M4U_MAGICNO, 14, int) +#define MTK_M4U_T_MONITOR_STOP _IOW(MTK_M4U_MAGICNO, 15, int) +#define MTK_M4U_T_RESET_MVA_RELEASE_TLB _IOW(MTK_M4U_MAGICNO, 16, int) +#define MTK_M4U_T_CONFIG_PORT_ROTATOR _IOW(MTK_M4U_MAGICNO, 17, int) +#define MTK_M4U_T_QUERY_MVA _IOW(MTK_M4U_MAGICNO, 18, int) +#define MTK_M4U_T_M4UDrv_CONSTRUCT _IOW(MTK_M4U_MAGICNO, 19, int) +#define MTK_M4U_T_M4UDrv_DECONSTRUCT _IOW(MTK_M4U_MAGICNO, 20, int) +#define MTK_M4U_T_DUMP_PAGETABLE _IOW(MTK_M4U_MAGICNO, 21, int) +#define MTK_M4U_T_REGISTER_BUFFER _IOW(MTK_M4U_MAGICNO, 22, int) +#define MTK_M4U_T_CACHE_FLUSH_ALL _IOW(MTK_M4U_MAGICNO, 23, int) +#define MTK_M4U_T_CONFIG_PORT_ARRAY _IOW(MTK_M4U_MAGICNO, 26, int) +#define MTK_M4U_T_CONFIG_MAU _IOW(MTK_M4U_MAGICNO, 27, int) +#define MTK_M4U_T_CONFIG_TF _IOW(MTK_M4U_MAGICNO, 28, int) +#define MTK_M4U_T_DMA_OP _IOW(MTK_M4U_MAGICNO, 29, int) + +#define MTK_M4U_T_SEC_INIT _IOW(MTK_M4U_MAGICNO, 50, int) + +#ifdef M4U_TEE_SERVICE_ENABLE +int m4u_config_port_tee(M4U_PORT_STRUCT *pM4uPort); +int m4u_larb_backup_sec(unsigned int larb_idx); +int m4u_larb_restore_sec(unsigned int larb_idx); +int m4u_config_port_array_tee(unsigned char *port_array); +int m4u_sec_init(void); +#endif + +/* #include */ +extern MMP_Event M4U_MMP_Events[M4U_MMP_MAX]; + +#if !defined(CONFIG_MTK_CLKMGR) +extern const char *smi_clk_name[]; +#endif + +#endif diff --git a/drivers/misc/mediatek/m4u/mt6755/m4u_reg.h b/drivers/misc/mediatek/m4u/mt6755/m4u_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..2c679c06362b4fc4c22e5cd5b6bf54c2d8be02ff --- /dev/null +++ b/drivers/misc/mediatek/m4u/mt6755/m4u_reg.h @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _JADE_M4U_REG_H__ +#define _JADE_M4U_REG_H__ + +#define M4U_BASE0 0xf0205000 + +#define LARB0_BASE 0xf4015000 +#define LARB1_BASE 0xf6010000 +#define LARB2_BASE 0xf5001000 +#define LARB3_BASE 0xf7001000 + +/* ================================================= */ +/* common macro definitions */ +#define F_VAL(val, msb, lsb) (((val)&((1<<(msb-lsb+1))-1))<>lsb) + +/* ===================================================== */ +/* M4U register definition */ +/* ===================================================== */ + +#define REG_MMUg_PT_BASE (0x0) + #define F_MMUg_PT_VA_MSK 0xffff0000 +#define REG_MMUg_PT_BASE_SEC (0x4) + #define F_MMUg_PT_VA_MSK_SEC 0xffff0000 + + +#define REG_MMU_PROG_EN 0x10 + #define F_MMU0_PROG_EN 1 + +#define REG_MMU_PROG_VA 0x14 + #define F_PROG_VA_LOCK_BIT (1<<11) + #define F_PROG_VA_LAYER_BIT F_BIT_SET(9) + #define F_PROG_VA_SIZE16X_BIT F_BIT_SET(8) + #define F_PROG_VA_SECURE_BIT (1<<7) + #define F_PROG_VA_MASK 0xfffff000 + +#define REG_MMU_PROG_DSC 0x18 + +#define REG_MMU_INVLD (0x20) + #define F_MMU_INV_ALL 0x2 + #define F_MMU_INV_RANGE 0x1 + +#define REG_MMU_INVLD_SA (0x24) +#define REG_MMU_INVLD_EA (0x28) + +#define REG_MMU_INVLD_SEC (0x2c) + #define F_MMU_INV_SEC_ALL 0x2 + #define F_MMU_INV_SEC_RANGE 0x1 + +#define REG_MMU_INVLD_SA_SEC (0x30) +#define REG_MMU_INVLD_EA_SEC (0x34) + +#define REG_INVLID_SEL (0x38) + #define F_MMU_INV_EN_L2 (1<<1) + #define F_MMU_INV_EN_L1 (1<<0) + +#define REG_INVLID_SEL_SEC (0x3c) + #define F_MMU_INV_SEC_DBG (1<<5) + #define F_MMU_INV_SEC_INV_INT_EN (1<<4) + #define F_MMU_INV_SEC_INV_INT_CLR (1<<3) + #define F_MMU_INV_SEC_INV_DONE (1<<2) + #define F_MMU_INV_SEC_EN_L2 (1<<1) + #define F_MMU_INV_SEC_EN_L1 (1<<0) + +#define REG_MMU_SEC_ABORT_INFO (0x40) + #define F_MMU_M4U_DOMAIN_ABORT F_BIT_VAL(en, 31) + #define F_MMU_SEC_ABORT_WR(en) F_BIT_VAL(en, 29) + #define F_MMU_SEC_ABORT_ADDR F_MSK_SHIFT(regval, 28, 17) + #define F_MMU_SEC_ABORT_DOMAIN F_MSK_SHIFT(regval, 16, 14) + #define F_MMU_SEC_ABORT_ID F_MSK_SHIFT(regval, 13, 0) + +#define REG_MMU_DUMMY (0X44) +#define REG_MMU_STANDARD_AXI_MODE (0x48) + +#define REG_MMU_PRIORITY (0x4c) + #define F_MMU_RS_FULL_ULTRA_EN F_BIT_SET(2) + #define F_MMU_AUTO_PF_ULTRA_BIT F_BIT_SET(1) + #define F_MMU_TABLE_WALK_ULTRA_BIT F_BIT_SET(0) + +#define REG_MMU_DCM_DIS (0x50) + #define F_MMU_MTLB_LOGIC_STALL_DCM F_BIT_SET(14) + #define F_MMU_RS_ENTRY_STALL_DCM F_BIT_SET(13) + #define F_MMU_FIFO_ENTRY_STALL_DCM F_BIT_SET(12) + #define F_MMU_SLICE_ENTRY_STALL_DCM F_BIT_SET(11) + #define F_MMU_ULTRA_SLICE_STALL_ENTRY_DCM F_BIT_SET(10) + #define F_MMU_L2_LOGIC_STALL_DCM F_BIT_SET(9) + #define F_MMU_TOP_STALL_DCM F_BIT_SET(8) + #define F_MMU_APB_DCM F_BIT_SET(7) + #define F_MMU_MTLB_LOGIC_DCM F_BIT_SET(6) + #define F_MMU_RS_ENTRY_DCM F_BIT_SET(5) + #define F_MMU_FIFO_ENTRY_DCM F_BIT_SET(4) + #define F_MMU_SLICE_ENTRY_DCM F_BIT_SET(3) + #define F_MMU_ULTRA_SLICE_ENTRY_DCM F_BIT_SET(2) + #define F_MMU_L2_LOGIC_DCM F_BIT_SET(1) + #define F_MMU_TOP_DCM F_BIT_SET(0) + +#define REG_MMU_WR_LEN (0x54) + #define F_MMU_MMU0_WRITE_THROTTLING_DIS F_BIT_SET(5) + #define F_MMU_MMU0_WRITE_LEN F_MSK(4, 0) + +#define REG_MMU_HW_DEBUG (0x58) + #define F_MMU_HW_DBG_L2_SCAN_ALL F_BIT_SET(1) + #define F_MMU_HW_DBG_PFQ_BRDCST F_BIT_SET(0) + +#define REG_MMU_NON_BLOCKING_DIS 0x5C + #define F_MMU_MMU0_HALF_ENTRY_MODE F_BIT_SET(1) + #define F_MMU_MMU0_BLOCKING_MODE F_BIT_SET(0) + +#define REG_MMU_LEGACY_4KB_MODE (0x60) +#define REG_MMU_DBG0 (0X64) +#define REG_MMU_DBG1 (0x68) +#define REG_MMU_DBG2 (0x6c) +#define REG_MMU_SMI_COMMON_DBG0 (0x78) + +#define REG_MMU_MMU_COHERENCE_EN 0x80 +#define REG_MMU_IN_ORDER_WR_EN 0x84 +#define REG_MMU_MMU_TABLE_WALK_DIS 0x88 +#define REG_MMU_MMU_MTLB_RESERVE_MODE_DIS 0x8c + +#define REG_MMU_READ_ENTRY 0x100 + #define F_READ_ENTRY_EN F_BIT_SET(31) + #define F_READ_ENTRY_MM0_MAIN F_BIT_SET(27) + #define F_READ_ENTRY_MMx_MAIN(id) F_BIT_SET(27+id) + #define F_READ_ENTRY_PFH F_BIT_SET(26) + #define F_READ_ENTRY_MAIN_IDX(idx) F_VAL(idx, 16, 12) + #define F_READ_ENTRY_PFH_IDX(idx) F_VAL(idx, 10, 5) + /* #define F_READ_ENTRY_PFH_HI_LO(high) F_VAL(high, 4, 4) */ + /* #define F_READ_ENTRY_PFH_PAGE(page) F_VAL(page, 3, 2) */ + #define F_READ_ENTRY_PFH_PAGE_IDX(idx) F_VAL(idx, 4, 2) + #define F_READ_ENTRY_PFH_WAY(way) F_VAL(way, 1, 0) + +#define REG_MMU_DES_RDATA 0x104 + +#define REG_MMU_PFH_TAG_RDATA 0x108 + #define F_PFH_TAG_VA_GET(mmu, tag) ((mmu == 0) ? F_MMU0_PFH_TAG_VA_GET(tag) : F_MMU1_PFH_TAG_VA_GET(tag)) + #define F_MMU0_PFH_TAG_VA_GET(tag) (F_MSK_SHIFT(tag, 14, 4)<<(MMU_SET_MSB_OFFSET(0)+1)) + #define F_MMU1_PFH_TAG_VA_GET(tag) (F_MSK_SHIFT(tag, 15, 4)<<(MMU_SET_MSB_OFFSET(1)+1)) + #define F_MMU_PFH_TAG_VA_LAYER0_MSK(mmu) ((mmu = 0) ? F_MSK(31, 29) : F_MSK(31, 28)) + #define F_PFH_TAG_LAYER_BIT F_BIT_SET(3) + #define F_PFH_TAG_16X_BIT F_BIT_SET(2) /* this bit is always 0 -- cost down. */ + #define F_PFH_TAG_SEC_BIT F_BIT_SET(1) + #define F_PFH_TAG_AUTO_PFH F_BIT_SET(0) + +/* tag related macro */ + #define MMU0_SET_ORDER 6 + #define MMU1_SET_ORDER 5 + #define MMU_SET_ORDER(mmu) ((mmu == 0) ? MMU0_SET_ORDER : MMU1_SET_ORDER) + #define MMU_SET_NR(mmu) (1<>1) + #define F_MMU_IVRP_4G_DRAM_PA_SET(PA) ((PA>>1)|(1<<31)) + +#define REG_MMU_INT_L2_CONTROL 0x120 + #define F_INT_L2_CLR_BIT (1<<12) + #define F_INT_L2_MULTI_HIT_FAULT F_BIT_SET(0) + #define F_INT_L2_TABLE_WALK_FAULT F_BIT_SET(1) + #define F_INT_L2_PFH_DMA_FIFO_OVERFLOW F_BIT_SET(2) + #define F_INT_L2_MISS_DMA_FIFO_OVERFLOW F_BIT_SET(3) + #define F_INT_L2_INVALD_DONE F_BIT_SET(4) + #define F_INT_L2_PFH_FIFO_ERROR F_BIT_SET(5) + #define F_INT_L2_MISS_FIFO_ERR F_BIT_SET(6) + +#define REG_MMU_INT_MAIN_CONTROL 0x124 + #define F_INT_TRANSLATION_FAULT(MMU) F_BIT_SET(0+(((MMU)<<1)|((MMU)<<2))) + #define F_INT_MAIN_MULTI_HIT_FAULT(MMU) F_BIT_SET(1+(((MMU)<<1)|((MMU)<<2))) + #define F_INT_INVALID_PHYSICAL_ADDRESS_FAULT(MMU) F_BIT_SET(2+(((MMU)<<1)|((MMU)<<2))) + #define F_INT_ENTRY_REPLACEMENT_FAULT(MMU) F_BIT_SET(3+(((MMU)<<1)|((MMU)<<2))) + #define F_INT_TLB_MISS_FAULT(MMU) F_BIT_SET(4+(((MMU)<<1)|((MMU)<<2))) + #define F_INT_MISS_FIFO_ERR(MMU) F_BIT_SET(5+(((MMU)<<1)|((MMU)<<2))) + #define F_INT_PFH_FIFO_ERR(MMU) F_BIT_SET(6+(((MMU)<<1)|((MMU)<<2))) + + #define F_INT_MAU(mmu, set) F_BIT_SET(7+(set)+(mmu<<2)) /* (14+(set)+(mmu*4)) */ + + #define F_INT_MMU0_MAIN_MSK F_MSK(6, 0) + #define F_INT_MMU0_MAU_MSK F_MSK(10, 7) + +#define REG_MMU_CPE_DONE_SEC 0x128 +#define REG_MMU_CPE_DONE 0x12C + +#define REG_MMU_L2_FAULT_ST 0x130 + #define F_INT_L2_MISS_IN_FIFO_ERR F_BIT_SET(8) + #define F_INT_L2_MISS_OUT_FIFO_ERROR F_BIT_SET(7) + #define F_INT_L2_PFH_IN_FIFO_ERROR F_BIT_SET(6) + #define F_INT_L2_PFH_OUT_FIFO_ERROR F_BIT_SET(5) + +#define REG_MMU_MAIN_FAULT_ST 0x134 + +#define REG_MMU_TBWALK_FAULT_VA 0x138 + #define F_MMU_TBWALK_FAULT_VA_MSK F_MSK(31, 12) + #define F_MMU_TBWALK_FAULT_LAYER(regval) F_MSK_SHIFT(regval, 0, 0) + +#define REG_MMU_FAULT_VA(mmu) (0x13c+((mmu)<<3)) + #define F_MMU_FAULT_VA_MSK F_MSK(31, 12) + #define F_MMU_FAULT_VA_WRITE_BIT F_BIT_SET(1) + #define F_MMU_FAULT_VA_LAYER_BIT F_BIT_SET(0) + +#define REG_MMU_INVLD_PA(mmu) (0x140+((mmu)<<3)) +#define REG_MMU_INT_ID(mmu) (0x150+((mmu)<<2)) + #define F_MMU0_INT_ID_TF_MSK (~0x3) /* only for MM iommu. */ + +#define REG_MMU_PF_MSCNT 0x160 +#define REG_MMU_PF_CNT 0x164 +#define REG_MMU_ACC_CNT(mmu) (0x168+(((mmu)<<3)|((mmu)<<2))) /* (0x168+((mmu)*12) */ +#define REG_MMU_MAIN_MSCNT(mmu) (0x16c+(((mmu)<<3)|((mmu)<<2))) +#define REG_MMU_RS_PERF_CNT(mmu) (0x170+(((mmu)<<3)|((mmu)<<2))) + +#define REG_MMU_PFH_VLD_0 (0x180) +#define REG_MMU_PFH_VLD(mmu, set, way) \ + (REG_MMU_PFH_VLD_0+(((set)>>5)<<2)+((way)<<((mmu == 0) \ + ? (MMU0_SET_ORDER - 3):(MMU1_SET_ORDER - 3)))) + #define F_MMU_PFH_VLD_BIT(set, way) F_BIT_SET((set)&0x1f) /* set%32 */ + +#define MMU01_SQ_OFFSET (0x600-0x300) +#define REG_MMU_SQ_START(mmu, x) (0x300+((x)<<3)+((mmu)*MMU01_SQ_OFFSET)) + #define F_SQ_VA_MASK F_MSK(31, 20) + #define F_SQ_EN_BIT (1<<19) + /* #define F_SQ_MULTI_ENTRY_VAL(x) (((x)&0xf)<<13) */ +#define REG_MMU_SQ_END(mmu, x) (0x304+((x)<<3)+((mmu)*MMU01_SQ_OFFSET)) + +#define MMU_TOTAL_RS_NR 8 +#define REG_MMU_RSx_VA(mmu, x) (0x380+((x)<<4)+((mmu)*MMU01_SQ_OFFSET)) + #define F_MMU_RSx_VA_GET(regval) ((regval)&F_MSK(31, 12)) + #define F_MMU_RSx_VA_VALID(regval) F_MSK_SHIFT(regval, 11, 11) + #define F_MMU_RSx_VA_PID(regval) F_MSK_SHIFT(regval, 9, 0) + +#define REG_MMU_RSx_PA(mmu, x) (0x384+((x)<<4)+((mmu)*MMU01_SQ_OFFSET)) + #define F_MMU_RSx_PA_GET(regval) ((regval)&F_MSK(31, 12)) + +#define REG_MMU_RSx_2ND_BASE(mmu, x) (0x388+((x)<<4)+((mmu)*MMU01_SQ_OFFSET)) + +#define REG_MMU_RSx_ST(mmu, x) (0x38c+((x)<<4)+((mmu)*MMU01_SQ_OFFSET)) + #define F_MMU_RSx_ST_LID(regval) F_MSK_SHIFT(regval, 22, 20) + #define F_MMU_RSx_ST_WRT(regval) F_MSK_SHIFT(regval, 12, 12) + #define F_MMU_RSx_ST_OTHER(regval) F_MSK_SHIFT(regval, 8, 0) + +#define REG_MMU_MAIN_TAG(mmu, x) (0x500+((x)<<2)+((mmu)*MMU01_SQ_OFFSET)) + #define F_MAIN_TLB_VA_MSK F_MSK(31, 12) + #define F_MAIN_TLB_LOCK_BIT (1<<11) + #define F_MAIN_TLB_VALID_BIT (1<<10) + #define F_MAIN_TLB_LAYER_BIT F_BIT_SET(9) + #define F_MAIN_TLB_16X_BIT F_BIT_SET(8) + #define F_MAIN_TLB_SEC_BIT F_BIT_SET(7) + #define F_MAIN_TLB_INV_DES_BIT (1<<6) + #define F_MAIN_TLB_SQ_EN_BIT (1<<5) + #define F_MAIN_TLB_SQ_INDEX_MSK F_MSK(4, 1) + #define F_MAIN_TLB_SQ_INDEX_GET(regval) F_MSK_SHIFT(regval, 4, 1) + +#define REG_MMU_MAU_START(mmu, mau) (0x900+((mau)*0x20)+((mmu)*0xa0)) +#define REG_MMU_MAU_START_BIT32(mmu, mau) (0x904+((mau)*0x20)+((mmu)*0xa0)) +#define REG_MMU_MAU_END(mmu, mau) (0x908+((mau)*0x20)+((mmu)*0xa0)) +#define REG_MMU_MAU_END_BIT32(mmu, mau) (0x90C+((mau)*0x20)+((mmu)*0xa0)) +#define REG_MMU_MAU_PORT_EN(mmu, mau) (0x910+((mau)*0x20)+((mmu)*0xa0)) +#define REG_MMU_MAU_ASSERT_ID(mmu, mau) (0x914+((mau)*0x20)+((mmu)*0xa0)) + #define F_MMU_MAU_ASSERT_ID_LARB(regval) F_MSK_SHIFT(regval, 7, 5) + #define F_MMU_MAU_ASSERT_ID_PORT(regval) F_MSK_SHIFT(regval, 4, 0) + +#define REG_MMU_MAU_ADDR(mmu, mau) (0x918+((mau)*0x20)+((mmu)*0xa0)) +#define REG_MMU_MAU_ADDR_BIT32(mmu, mau) (0x91C+((mau)*0x20)+((mmu)*0xa0)) + +#define REG_MMU_MAU_LARB_EN(mmu) (0x980+((mmu)*0xa0)) + #define F_MAU_LARB_VAL(mau, larb) ((larb)<<(mau*8)) + #define F_MAU_LARB_MSK(mau) (0xff<<(mau*8)) +#define REG_MMU_MAU_CLR(mmu) (0x984+((mmu)*0xa0)) +#define REG_MMU_MAU_IO(mmu) (0x988+((mmu)*0xa0)) + #define F_MAU_BIT_VAL(val, mau) F_BIT_VAL(val, mau) +#define REG_MMU_MAU_RW(mmu) (0x98c+((mmu)*0xa0)) +#define REG_MMU_MAU_VA(mmu) (0x990+((mmu)*0xa0)) +#define REG_MMU_MAU_ASSERT_ST(mmu) (0x994+((mmu)*0xa0)) + +#define MMU_TOTAL_PROG_DIST_NR 8 +#define REG_MMU_PROG_DIST0 0xb00 +#define REG_MMU_PROG_DIST1 0xb04 +#define REG_MMU_PROG_DIST2 0xb08 +#define REG_MMU_PROG_DIST3 0xb0c +#define REG_MMU_PROG_DIST4 0xb10 +#define REG_MMU_PROG_DIST5 0xb14 +#define REG_MMU_PROG_DIST6 0xb18 +#define REG_MMU_PROG_DIST7 0xb1c +#define REG_MMU_PROG_DIST(dist) (0xb00+((dist)<<2)) + #define F_PF_ID_COMP_SEL(sel) F_BIT_VAL(sel, 16) + #define F_PF_DIR(dir) F_BIT_VAL(dir, 15) + #define F_PF_DIST(dist) F_MSK_SHIFT(dist, 14, 11) + #define F_PF_AXI_ID_MSK (~0x3) /* only for MM iommu. */ + #define F_PF_ID_MASK(id) F_MSK_SHIFT(id, 10, 1) + #define F_PF_ID(id) F_VAL(id, 10, 1) + #define F_PF_EN(en) F_BIT_VAL(en, 0) +#define REG_MMU_SMI_ASYNC_CFG 0xb80 + +/* ================================================================ */ +/* SMI larb */ +/* ================================================================ */ + +#define SMI_LARB_MMU_EN (0xfc0) + #define F_SMI_MMU_EN(port, en) ((en)<<((port))) +#define SMI_LARB_SEC_EN (0xfc4) + #define F_SMI_SEC_EN(port, en) ((en)<<((port))) +#define SMI_LARB_DOMN_0 (0xfd0) +#define SMI_LARB_DOMN_1 (0xfd4) +#define SMI_LARB_DOMN_2 (0xfd8) +#define SMI_LARB_DOMN_3 (0xfdc) +#define REG_SMI_LARB_DOMN_OF_PORT(port) (SMI_LARB_DOMN_0+(((port)>>3)<<2)) + #define F_SMI_DOMN(port, domain) ((domain&0xf)<<(((port)&0x7)<<2)) + +/* ========================================================================= */ +/* peripheral system */ +/* ========================================================================= */ +#define REG_PERIAXI_BUS_CTL3 (0x208) + #define F_PERI_MMU_EN(port, en) ((en)<<((port))) + +#include + +static inline unsigned int COM_ReadReg32(unsigned long addr) +{ + return ioread32((void *)addr); +} + +static inline void COM_WriteReg32(unsigned long addr, unsigned int Val) +{ + mt_reg_sync_writel(Val, (void *)addr); +} + +static inline unsigned int M4U_ReadReg32(unsigned long M4uBase, unsigned int Offset) +{ + unsigned int val; + + val = COM_ReadReg32((M4uBase + Offset)); + return val; +} + +static inline void M4U_WriteReg32(unsigned long M4uBase, unsigned int Offset, unsigned int Val) +{ + /* M4UMSG("M4U_WriteReg32: M4uBase: 0x%lx, Offset:0x%x, val:0x%x\n", M4uBase, Offset, Val); */ + COM_WriteReg32((M4uBase+Offset), Val); +} + +static inline void m4uHw_set_field_by_mask(unsigned long M4UBase, unsigned int reg, + unsigned long mask, unsigned int val) +{ + unsigned int regval; + + regval = M4U_ReadReg32(M4UBase, reg); + regval = (regval & (~mask))|val; + M4U_WriteReg32(M4UBase, reg, regval); +} + +static inline unsigned int m4uHw_get_field_by_mask(unsigned long M4UBase, unsigned int reg, + unsigned int mask) +{ + return M4U_ReadReg32(M4UBase, reg)&mask; +} + +#endif diff --git a/drivers/misc/mediatek/mach/mt6755/Kconfig b/drivers/misc/mediatek/mach/mt6755/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..3c2ba6658055e11595d18cc749e156de4c466459 --- /dev/null +++ b/drivers/misc/mediatek/mach/mt6755/Kconfig @@ -0,0 +1,5 @@ +menu "MT6755 Board Support Package" + +endmenu + + diff --git a/drivers/misc/mediatek/mu3phy/mt6755/Makefile b/drivers/misc/mediatek/mu3phy/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f0b35d731a5a87f1f077f6cfe5f3b3de45227a01 --- /dev/null +++ b/drivers/misc/mediatek/mu3phy/mt6755/Makefile @@ -0,0 +1,25 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mu3d/drv \ + -I$(srctree)/drivers/misc/mediatek/mu3d/hal \ + -I$(srctree)/drivers/misc/mediatek/mu3phy + +ifeq ($(CONFIG_USB_DEBUG),y) + EXTRA_CFLAGS += -DDEBUG +endif + +#For USB HQA Driving Tuning Mode 1 Settings +#EXTRA_CFLAGS += -DMTK_USB_MODE1 + +obj-$(CONFIG_PROJECT_PHY) += mtk-phy-asic.o diff --git a/drivers/misc/mediatek/mu3phy/mt6755/mtk-phy-asic.c b/drivers/misc/mediatek/mu3phy/mt6755/mtk-phy-asic.c new file mode 100644 index 0000000000000000000000000000000000000000..24815af390533896d9e40fe09229605b7a5d870b --- /dev/null +++ b/drivers/misc/mediatek/mu3phy/mt6755/mtk-phy-asic.c @@ -0,0 +1,1285 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "mtk-phy.h" + +#ifdef CONFIG_PROJECT_PHY +/*#include */ +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include +#include +#endif +#include +#include "mtk-phy-asic.h" +#include "mu3d_hal_osal.h" +#ifdef CONFIG_MTK_UART_USB_SWITCH +#include "mu3d_hal_usb_drv.h" +#endif + +#ifdef FOR_BRING_UP +#define enable_clock(x, y) +#define disable_clock(x, y) +#define hwPowerOn(x, y, z) +#define hwPowerDown(x, y) +#define set_ada_ssusb_xtal_ck(x) +#endif + +#include + +#ifdef CONFIG_OF +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#ifndef CONFIG_MTK_CLKMGR +static struct clk *musb_clk; +#endif + +bool sib_mode = false; + +#ifdef USB_CLK_DEBUG +void __iomem *usb_debug_clk_infracfg_base; +#define MODULE_SW_CG_2_SET (usb_debug_clk_infracfg_base + 0xa4) +#define MODULE_SW_CG_2_CLR (usb_debug_clk_infracfg_base + 0xa8) +#define MODULE_SW_CG_2_STA (usb_debug_clk_infracfg_base + 0xac) +static bool get_clk_io = true; +#endif +static bool usb_enable_clock(bool enable) +{ + if (enable) { +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_PERI_USB0, "USB30"); +#else + clk_enable(musb_clk); +#endif + } else { +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_PERI_USB0, "USB30"); +#else + clk_disable(musb_clk); +#endif + } + +#ifdef USB_CLK_DEBUG + if (get_clk_io) { + struct device_node *node; + + get_clk_io = false; + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-infrasys"); + usb_debug_clk_infracfg_base = of_iomap(node, 0); + if (!usb_debug_clk_infracfg_base) + pr_err("[CLK_INFRACFG_AO] base failed\n"); + } + if (!IS_ERR(musb_clk)) + pr_err("SSUSB musb clock is okay, enabel: %d\n", enable); + else + pr_err("SSUSB musb clock is fail, enabel: %d\n", enable); + /*bit1: ssusb_top_cg_sta (0: clock enable 1: clock disable)*/ + pr_err("SSUSB MODULE_SW_CG_2_STA = 0x%08x\n", DRV_Reg32(MODULE_SW_CG_2_STA)); +#endif + return 1; +} + + +#ifdef NEVER +/*Turn on/off ADA_SSUSB_XTAL_CK 26MHz*/ +void enable_ssusb_xtal_clock(bool enable) +{ + if (enable) { + /* + * 1 *AP_PLL_CON0 =| 0x1 [0]=1: RG_LTECLKSQ_EN + * 2 Wait PLL stable (100us) + * 3 *AP_PLL_CON0 =| 0x2 [1]=1: RG_LTECLKSQ_LPF_EN + * 4 *AP_PLL_CON2 =| 0x1 [0]=1: DA_REF2USB_TX_EN + * 5 Wait PLL stable (100us) + * 6 *AP_PLL_CON2 =| 0x2 [1]=1: DA_REF2USB_TX_LPF_EN + * 7 *AP_PLL_CON2 =| 0x4 [2]=1: DA_REF2USB_TX_OUT_EN + */ + writel(readl((void __iomem *)AP_PLL_CON0) | (0x00000001), + (void __iomem *)AP_PLL_CON0); + /*Wait 100 usec */ + udelay(100); + + writel(readl((void __iomem *)AP_PLL_CON0) | (0x00000002), + (void __iomem *)AP_PLL_CON0); + + writel(readl((void __iomem *)AP_PLL_CON2) | (0x00000001), + (void __iomem *)AP_PLL_CON2); + + /*Wait 100 usec */ + udelay(100); + + writel(readl((void __iomem *)AP_PLL_CON2) | (0x00000002), + (void __iomem *)AP_PLL_CON2); + + writel(readl((void __iomem *)AP_PLL_CON2) | (0x00000004), + (void __iomem *)AP_PLL_CON2); + } else { + /* + * AP_PLL_CON2 &= 0xFFFFFFF8 [2]=0: DA_REF2USB_TX_OUT_EN + * [1]=0: DA_REF2USB_TX_LPF_EN + * [0]=0: DA_REF2USB_TX_EN + */ + /* writel(readl((void __iomem *)AP_PLL_CON2)&~(0x00000007), */ + /* (void __iomem *)AP_PLL_CON2); */ + } +} + +/*Turn on/off AD_LTEPLL_SSUSB26M_CK 26MHz*/ +void enable_ssusb26m_ck(bool enable) +{ + if (enable) { + /* + * 1 *AP_PLL_CON0 =| 0x1 [0]=1: RG_LTECLKSQ_EN + * 2 Wait PLL stable (100us) + * 3 *AP_PLL_CON0 =| 0x2 [1]=1: RG_LTECLKSQ_LPF_EN + */ + writel(readl((void __iomem *)AP_PLL_CON0) | (0x00000001), + (void __iomem *)AP_PLL_CON0); + /*Wait 100 usec */ + udelay(100); + + writel(readl((void __iomem *)AP_PLL_CON0) | (0x00000002), + (void __iomem *)AP_PLL_CON0); + + } else { + /* + * AP_PLL_CON2 &= 0xFFFFFFF8 [2]=0: DA_REF2USB_TX_OUT_EN + * [1]=0: DA_REF2USB_TX_LPF_EN + * [0]=0: DA_REF2USB_TX_EN + */ + /* writel(readl((void __iomem *)AP_PLL_CON2)&~(0x00000007), */ + /* (void __iomem *)AP_PLL_CON2); */ + } +} +#endif /* NEVER */ + +void usb20_pll_settings(bool host, bool forceOn) +{ + if (host) { + if (forceOn) { + os_printk(K_DEBUG, "%s-%d - Set USBPLL_FORCE_ON.\n", __func__, __LINE__); + /* Set RG_SUSPENDM to 1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, + RG_SUSPENDM, 1); + /* force suspendm = 1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, + FORCE_SUSPENDM, 1); +#ifndef CONFIG_MTK_TYPEC_SWITCH + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_PHYA_REG6, RG_SSUSB_RESERVE6_OFST, + RG_SSUSB_RESERVE6, 0x1); +#endif + + } else { + os_printk(K_DEBUG, "%s-%d - Clear USBPLL_FORCE_ON.\n", __func__, __LINE__); + /* Set RG_SUSPENDM to 1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, + RG_SUSPENDM, 0); + /* force suspendm = 1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, + FORCE_SUSPENDM, 0); +#ifndef CONFIG_MTK_TYPEC_SWITCH + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_PHYA_REG6, RG_SSUSB_RESERVE6_OFST, + RG_SSUSB_RESERVE6, 0x0); +#endif + return; + } + } + + os_printk(K_DEBUG, "%s-%d - Set PLL_FORCE_MODE and SIFSLV PLL_FORCE_ON.\n", __func__, + __LINE__); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR2_0, RG_SIFSLV_USB20_PLL_FORCE_MODE_OFST, + RG_SIFSLV_USB20_PLL_FORCE_MODE, 0x1); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDCR0, RG_SIFSLV_USB20_PLL_FORCE_ON_OFST, + RG_SIFSLV_USB20_PLL_FORCE_ON, 0x0); +} + +#ifdef CONFIG_MTK_UART_USB_SWITCH +bool in_uart_mode = false; +void uart_usb_switch_dump_register(void) +{ + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(1); */ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(true); + udelay(50); + +# ifdef CONFIG_MTK_FPGA + pr_debug("[MUSB]addr: 0x6B, value: %x\n", + USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYDTM0 + 0x3)); + pr_debug("[MUSB]addr: 0x6E, value: %x\n", + USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYDTM1 + 0x2)); + pr_debug("[MUSB]addr: 0x22, value: %x\n", + USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYACR4 + 0x2)); + pr_debug("[MUSB]addr: 0x68, value: %x\n", + USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYDTM0)); + pr_debug("[MUSB]addr: 0x6A, value: %x\n", + USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYDTM0 + 0x2)); + pr_debug("[MUSB]addr: 0x1A, value: %x\n", + USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYACR6 + 0x2)); +#else +#if 0 + os_printk(K_INFO, "[MUSB]addr: 0x6B, value: %x\n", U3PhyReadReg8(U3D_U2PHYDTM0 + 0x3)); + os_printk(K_INFO, "[MUSB]addr: 0x6E, value: %x\n", U3PhyReadReg8(U3D_U2PHYDTM1 + 0x2)); + os_printk(K_INFO, "[MUSB]addr: 0x22, value: %x\n", U3PhyReadReg8(U3D_U2PHYACR4 + 0x2)); + os_printk(K_INFO, "[MUSB]addr: 0x68, value: %x\n", U3PhyReadReg8(U3D_U2PHYDTM0)); + os_printk(K_INFO, "[MUSB]addr: 0x6A, value: %x\n", U3PhyReadReg8(U3D_U2PHYDTM0 + 0x2)); + os_printk(K_INFO, "[MUSB]addr: 0x1A, value: %x\n", U3PhyReadReg8(U3D_USBPHYACR6 + 0x2)); +#else + os_printk(K_INFO, "[MUSB]addr: 0x18, value: 0x%x\n", + U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6)); + os_printk(K_INFO, "[MUSB]addr: 0x20, value: 0x%x\n", + U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4)); + os_printk(K_INFO, "[MUSB]addr: 0x68, value: 0x%x\n", + U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0)); + os_printk(K_INFO, "[MUSB]addr: 0x6C, value: 0x%x\n", + U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1)); +#endif +#endif + + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(0); */ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(false); + + /*os_printk(K_INFO, "[MUSB]addr: 0x110020B0 (UART0), value: %x\n\n", + DRV_Reg8(ap_uart0_base + 0xB0)); + */ +} + +bool usb_phy_check_in_uart_mode(void) +{ + PHY_INT32 usb_port_mode; + + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(1); */ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(true); + + udelay(50); + usb_port_mode = U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0) >> RG_UART_MODE_OFST; + + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(0);*/ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(false); + os_printk(K_INFO, "%s+ usb_port_mode = %d\n", __func__, usb_port_mode); + + if (usb_port_mode == 0x1) + return true; + else + return false; +} + +void usb_phy_switch_to_uart(void) +{ + PHY_INT32 ret; + + if (usb_phy_check_in_uart_mode()) { + os_printk(K_INFO, "%s+ UART_MODE\n", __func__); + return; + } + + os_printk(K_INFO, "%s+ USB_MODE\n", __func__); + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /*---POWER-----*/ + /*AVDD18_USB_P0 is always turned on. The driver does _NOT_ need to control it. */ + /*hwPowerOn(MT6332_POWER_LDO_VUSB33, VOL_3300, "VDD33_USB_P0");*/ + ret = pmic_set_register_value(PMIC_LDO_VUSB33_EN, 0x01); + if (ret) + pr_debug("VUSB33 enable FAIL!!!\n"); +#else + /*---POWER-----*/ + /*AVDD18_USB_P0 is always turned on. The driver does _NOT_ need to control it. */ + /*hwPowerOn(MT6332_POWER_LDO_VUSB33, VOL_3300, "VDD33_USB_P0"); */ + ret = pmic_set_register_value(MT6351_PMIC_RG_VUSB33_EN, 0x01); + if (ret) + pr_debug("VUSB33 enable FAIL!!!\n"); + + /* Set RG_VUSB10_ON as 1 after VDD10 Ready */ + /*hwPowerOn(MT6331_POWER_LDO_VUSB10, VOL_1000, "VDD10_USB_P0"); */ + ret = pmic_set_register_value(MT6351_PMIC_RG_VA10_EN, 0x01); + if (ret) + pr_debug("VA10 enable FAIL!!!\n"); + + ret = pmic_set_register_value(MT6351_PMIC_RG_VA10_VOSEL, 0x02); + if (ret) + pr_debug("VA10 output selection to 1.0v FAIL!!!\n"); +#endif + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(1); */ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(true); + udelay(50); + + /* RG_USB20_BC11_SW_EN = 1'b0 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, + RG_USB20_BC11_SW_EN, 0); + + /* Set RG_SUSPENDM to 1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, RG_SUSPENDM, 1); + + /* force suspendm = 1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, 1); + + /* Set ru_uart_mode to 2'b01 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_UART_MODE_OFST, RG_UART_MODE, 1); + + /* Set RG_UART_EN to 1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 1); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 1); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_TX_OE_OFST, FORCE_UART_TX_OE, 1); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_BIAS_EN_OFST, FORCE_UART_BIAS_EN, + 1); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 1); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_TX_OE_OFST, RG_UART_TX_OE, 1); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_BIAS_EN_OFST, RG_UART_BIAS_EN, 1); + + /* Set RG_USB20_DM_100K_EN to 1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DM_100K_EN_OFST, + RG_USB20_DM_100K_EN, 1); + + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(0); */ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(false); + + /* GPIO Selection */ + DRV_WriteReg32(ap_uart0_base + 0x6E0, (DRV_Reg32(ap_uart0_base + 0x6E0) | 0x80000)); + + in_uart_mode = true; +} + + +void usb_phy_switch_to_usb(void) +{ + in_uart_mode = false; + /* GPIO Selection */ + DRV_WriteReg32(ap_uart0_base + 0x6E0, (DRV_Reg32(ap_uart0_base + 0x6E0) & 0xFFF7FFFF)); /* set */ + + /* clear force_uart_en */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 0); + + phy_init_soc(u3phy); + + /* disable the USB clock turned on in phy_init_soc() */ + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(0); */ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(false); +} +#endif + +#define RG_SSUSB_VUSB10_ON (1<<5) +#define RG_SSUSB_VUSB10_ON_OFST (5) + +#ifdef CONFIG_MTK_SIB_USB_SWITCH +void usb_phy_sib_enable_switch(bool enable) +{ + /* + * It's MD debug usage. No need to care low power. + * Thus, no power off BULK and Clock at the end of function. + * MD SIB still needs these power and clock source. + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_LDO_VUSB33_EN, 0x01); +#else + pmic_set_register_value(MT6351_PMIC_RG_VUSB33_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_VA10_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_VA10_VOSEL, 0x02); +#endif + + usb_enable_clock(true); + udelay(50); +#if !defined(CONFIG_USB_MU3D_ONLY_U2_MODE) + /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG0, RG_SSUSB_VUSB10_ON_OFST, + RG_SSUSB_VUSB10_ON, 1); +#endif + /* SSUSB_IP_SW_RST = 0 */ + U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_sif_base + 0x700), 0x00031000); + /* SSUSB_IP_HOST_PDN = 0 */ + U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_sif_base + 0x704), 0x00000000); + /* SSUSB_IP_DEV_PDN = 0 */ + U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_sif_base + 0x708), 0x00000000); + /* SSUSB_IP_PCIE_PDN = 0 */ + U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_sif_base + 0x70C), 0x00000000); + /* SSUSB_U3_PORT_DIS/SSUSB_U3_PORT_PDN = 0*/ + U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_sif_base + 0x730), 0x0000000C); + + /* + * USBMAC mode is 0x62910002 (bit 1) + * MDSIB mode is 0x62910008 (bit 3) + * 0x0629 just likes a signature. Can't be removed. + */ + if (enable) { + U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_sif2_base+0x300), 0x62910008); + sib_mode = true; + } else { + U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_sif2_base+0x300), 0x62910002); + sib_mode = false; + } +} + +bool usb_phy_sib_enable_switch_status(void) +{ + int reg; + bool ret; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_LDO_VUSB33_EN, 0x01); +#else + pmic_set_register_value(MT6351_PMIC_RG_VUSB33_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_VA10_EN, 0x01); + pmic_set_register_value(MT6351_PMIC_RG_VA10_VOSEL, 0x02); +#endif + + usb_enable_clock(true); + udelay(50); +#if !defined(CONFIG_USB_MU3D_ONLY_U2_MODE) + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG0, RG_SSUSB_VUSB10_ON_OFST, + RG_SSUSB_VUSB10_ON, 1); +#endif + + reg = U3PhyReadReg32((phys_addr_t) (uintptr_t) (u3_sif2_base+0x300)); + if (reg == 0x62910008) + ret = true; + else + ret = false; + + return ret; +} +#endif + + +/*This "power on/initial" sequence refer to "6593_USB_PORT0_PWR Sequence 20130729.xls"*/ +PHY_INT32 phy_init_soc(struct u3phy_info *info) +{ + PHY_INT32 ret; + + os_printk(K_INFO, "%s+\n", __func__); + + /*This power on sequence refers to Sheet .1 of "6593_USB_PORT0_PWR Sequence 20130729.xls" */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /*---POWER-----*/ + /*AVDD18_USB_P0 is always turned on. The driver does _NOT_ need to control it. */ + ret = pmic_set_register_value(PMIC_LDO_VUSB33_EN, 0x01); + if (ret) + pr_debug("VUSB33 enable FAIL!!!\n"); +#else + /*---POWER-----*/ + /*AVDD18_USB_P0 is always turned on. The driver does _NOT_ need to control it. */ + /*hwPowerOn(MT6332_POWER_LDO_VUSB33, VOL_3300, "VDD33_USB_P0"); */ + ret = pmic_set_register_value(MT6351_PMIC_RG_VUSB33_EN, 0x01); + if (ret) + pr_debug("VUSB33 enable FAIL!!!\n"); + + /* Set RG_VUSB10_ON as 1 after VDD10 Ready */ + /*hwPowerOn(MT6331_POWER_LDO_VUSB10, VOL_1000, "VDD10_USB_P0"); */ + ret = pmic_set_register_value(MT6351_PMIC_RG_VA10_EN, 0x01); + if (ret) + pr_debug("VA10 enable FAIL!!!\n"); + + ret = pmic_set_register_value(MT6351_PMIC_RG_VA10_VOSEL, 0x02); + if (ret) + pr_debug("VA10 output selection to 1.0v FAIL!!!\n"); +#endif + /*---CLOCK-----*/ + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(1); */ + + /* AD_LTEPLL_SSUSB26M_CK:26MHz always on */ + /* It seems that when turning on ADA_SSUSB_XTAL_CK, AD_LTEPLL_SSUSB26M_CK will also turn on. */ + /* enable_ssusb26m_ck(true); */ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(true); + + /* AD_SSUSB_48M_CK:48MHz */ + /* It seems that when turning on f_fusb30_ck, AD_SSUSB_48M_CK will also turn on. */ + + /*Wait 50 usec */ + udelay(50); +#if !defined(CONFIG_USB_MU3D_ONLY_U2_MODE) + /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG0, RG_SSUSB_VUSB10_ON_OFST, + RG_SSUSB_VUSB10_ON, 1); +#endif + /*power domain iso disable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_ISO_EN_OFST, RG_USB20_ISO_EN, 0); + +#ifdef CONFIG_MTK_UART_USB_SWITCH + if (!in_uart_mode) { + /*switch to USB function. (system register, force ip into usb mode) */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, + 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, + RG_USB20_GPIO_CTL, 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, + USB20_GPIO_MODE, 0); + /* Set ru_uart_mode to 2'b00 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_UART_MODE_OFST, RG_UART_MODE, 0); + /*dm_100k disable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DM_100K_EN_OFST, + RG_USB20_DM_100K_EN, 0); + /*Release force suspendm. (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, + 0); + } + /*DP/DM BC1.1 path Disable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, + RG_USB20_BC11_SW_EN, 0); + /*dp_100k disable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DP_100K_MODE_OFST, + RG_USB20_DP_100K_MODE, 1); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_DP_100K_EN_OFST, USB20_DP_100K_EN, 0); +#if defined(CONFIG_MTK_HDMI_SUPPORT) || defined(MTK_USB_MODE1) + os_printk(K_INFO, "%s- USB PHY Driving Tuning Mode 1 Settings.\n", __func__); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HS_100U_U3_EN_OFST, + RG_USB20_HS_100U_U3_EN, 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR1, RG_USB20_VRT_VREF_SEL_OFST, + RG_USB20_VRT_VREF_SEL, 5); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR1, RG_USB20_TERM_VREF_SEL_OFST, + RG_USB20_TERM_VREF_SEL, 5); +#else +#if !defined(CONFIG_USB_MU3D_ONLY_U2_MODE) + /*Change 100uA current switch to SSUSB */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HS_100U_U3_EN_OFST, + RG_USB20_HS_100U_U3_EN, 1); +#endif +#endif + /*OTG Enable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_OTG_VBUSCMP_EN_OFST, + RG_USB20_OTG_VBUSCMP_EN, 1); + /*Pass RX sensitivity HQA requirement */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_SQTH_OFST, RG_USB20_SQTH, 0x2); +#else + /*switch to USB function. (system register, force ip into usb mode) */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, RG_USB20_GPIO_CTL, + 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, USB20_GPIO_MODE, 0); + /*DP/DM BC1.1 path Disable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, + RG_USB20_BC11_SW_EN, 0); + /*dp_100k disable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DP_100K_MODE_OFST, + RG_USB20_DP_100K_MODE, 1); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_DP_100K_EN_OFST, USB20_DP_100K_EN, 0); + /*dm_100k disable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DM_100K_EN_OFST, + RG_USB20_DM_100K_EN, 0); +#if !defined(CONFIG_MTK_HDMI_SUPPORT) && !defined(MTK_USB_MODE1) +#if !defined(CONFIG_USB_MU3D_ONLY_U2_MODE) + /*Change 100uA current switch to SSUSB */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HS_100U_U3_EN_OFST, + RG_USB20_HS_100U_U3_EN, 1); +#endif +#endif + /*OTG Enable */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_OTG_VBUSCMP_EN_OFST, + RG_USB20_OTG_VBUSCMP_EN, 1); + /*Pass RX sensitivity HQA requirement */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_SQTH_OFST, RG_USB20_SQTH, 0x2); + /*Release force suspendm. (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, 0); +#endif + + /*Wait 800 usec */ + udelay(800); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, FORCE_VBUSVALID_OFST, FORCE_VBUSVALID, 1); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, FORCE_AVALID_OFST, FORCE_AVALID, 1); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, FORCE_SESSEND_OFST, FORCE_SESSEND, 1); + + /* USB PLL Force settings */ + usb20_pll_settings(false, false); + + os_printk(K_DEBUG, "%s-\n", __func__); + + return PHY_TRUE; +} + +PHY_INT32 u2_slew_rate_calibration(struct u3phy_info *info) +{ + PHY_INT32 i = 0; + PHY_INT32 fgRet = 0; + PHY_INT32 u4FmOut = 0; + PHY_INT32 u4Tmp = 0; + + os_printk(K_DEBUG, "%s\n", __func__); + + /* => RG_USB20_HSTX_SRCAL_EN = 1 */ + /* enable USB ring oscillator */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HSTX_SRCAL_EN_OFST, + RG_USB20_HSTX_SRCAL_EN, 1); + + /* wait 1us */ + udelay(1); + + /* => USBPHY base address + 0x110 = 1 */ + /* Enable free run clock */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) (u3_sif2_base + 0x110) + , RG_FRCK_EN_OFST, RG_FRCK_EN, 0x1); + + /* => USBPHY base address + 0x100 = 0x04 */ + /* Setting cyclecnt */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) (u3_sif2_base + 0x100) + , RG_CYCLECNT_OFST, RG_CYCLECNT, 0x400); + + /* => USBPHY base address + 0x100 = 0x01 */ + /* Enable frequency meter */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) (u3_sif2_base + 0x100) + , RG_FREQDET_EN_OFST, RG_FREQDET_EN, 0x1); + + os_printk(K_DEBUG, "Freq_Valid=(0x%08X)\n", + U3PhyReadReg32((phys_addr_t) (uintptr_t) (u3_sif2_base + 0x110))); + + mdelay(1); + + /* wait for FM detection done, set 10ms timeout */ + for (i = 0; i < 10; i++) { + /* => USBPHY base address + 0x10C = FM_OUT */ + /* Read result */ + u4FmOut = U3PhyReadReg32((phys_addr_t) (uintptr_t) (u3_sif2_base + 0x10C)); + os_printk(K_DEBUG, "FM_OUT value: u4FmOut = %d(0x%08X)\n", u4FmOut, u4FmOut); + + /* check if FM detection done */ + if (u4FmOut != 0) { + fgRet = 0; + os_printk(K_DEBUG, "FM detection done! loop = %d\n", i); + break; + } + fgRet = 1; + mdelay(1); + } + /* => USBPHY base address + 0x100 = 0x00 */ + /* Disable Frequency meter */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) (u3_sif2_base + 0x100) + , RG_FREQDET_EN_OFST, RG_FREQDET_EN, 0); + + /* => USBPHY base address + 0x110 = 0x00 */ + /* Disable free run clock */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) (u3_sif2_base + 0x110) + , RG_FRCK_EN_OFST, RG_FRCK_EN, 0); + + /* RG_USB20_HSTX_SRCTRL[2:0] = (1024/FM_OUT) * reference clock frequency * 0.028 */ + if (u4FmOut == 0) { + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HSTX_SRCTRL_OFST, + RG_USB20_HSTX_SRCTRL, 0x4); + fgRet = 1; + } else { + /* set reg = (1024/FM_OUT) * REF_CK * U2_SR_COEF_E60802 / 1000 (round to the nearest digits) */ + /* u4Tmp = (((1024 * REF_CK * U2_SR_COEF_E60802) / u4FmOut) + 500) / 1000; */ + u4Tmp = (1024 * REF_CK * U2_SR_COEF_E60802) / (u4FmOut * 1000); + os_printk(K_DEBUG, "SR calibration value u1SrCalVal = %d\n", (PHY_UINT8) u4Tmp); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HSTX_SRCTRL_OFST, + RG_USB20_HSTX_SRCTRL, u4Tmp); + } + + /* => RG_USB20_HSTX_SRCAL_EN = 0 */ + /* disable USB ring oscillator */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HSTX_SRCAL_EN_OFST, + RG_USB20_HSTX_SRCAL_EN, 0); + + return fgRet; +} + +/*This "save current" sequence refers to "6593_USB_PORT0_PWR Sequence 20130729.xls"*/ +void usb_phy_savecurrent(unsigned int clk_on) +{ + + os_printk(K_INFO, "%s clk_on=%d+\n", __func__, clk_on); + + if (sib_mode) { + pr_err("%s sib_mode can't savecurrent\n", __func__); + return; + } + +#ifdef CONFIG_MTK_UART_USB_SWITCH + if (!in_uart_mode) { + /*switch to USB function. (system register, force ip into usb mode) */ + /* force_uart_en 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_UART_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, + 0); + /* RG_UART_EN 1'b0 */ + /* U3D_U2PHYDTM1 RG_UART_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); + + /*let suspendm=1, enable usb 480MHz pll */ + /* RG_SUSPENDM 1'b1 */ + /* U3D_U2PHYDTM0 RG_SUSPENDM */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, RG_SUSPENDM, 1); + + /*force_suspendm=1 */ + /* force_suspendm 1'b1 */ + /* U3D_U2PHYDTM0 FORCE_SUSPENDM */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, + 1); + } + /* rg_usb20_gpio_ctl 1'b0 */ + /* U3D_U2PHYACR4 RG_USB20_GPIO_CTL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, RG_USB20_GPIO_CTL, + 0); + /* usb20_gpio_mode 1'b0 */ + /* U3D_U2PHYACR4 USB20_GPIO_MODE */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, USB20_GPIO_MODE, 0); +#else + /*switch to USB function. (system register, force ip into usb mode) */ + /* force_uart_en 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_UART_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 0); + /* RG_UART_EN 1'b0 */ + /* U3D_U2PHYDTM1 RG_UART_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); + /* rg_usb20_gpio_ctl 1'b0 */ + /* U3D_U2PHYACR4 RG_USB20_GPIO_CTL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, RG_USB20_GPIO_CTL, + 0); + /* usb20_gpio_mode 1'b0 */ + /* U3D_U2PHYACR4 USB20_GPIO_MODE */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, USB20_GPIO_MODE, 0); + + /*let suspendm=1, enable usb 480MHz pll */ + /* RG_SUSPENDM 1'b1 */ + /* U3D_U2PHYDTM0 RG_SUSPENDM */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, RG_SUSPENDM, 1); + + /*force_suspendm=1 */ + /* force_suspendm 1'b1 */ + /* U3D_U2PHYDTM0 FORCE_SUSPENDM */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, 1); +#endif + /*Wait USBPLL stable. */ + /* Wait 2 ms. */ + udelay(2000); + + /* RG_DPPULLDOWN 1'b1 */ + /* U3D_U2PHYDTM0 RG_DPPULLDOWN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DPPULLDOWN_OFST, RG_DPPULLDOWN, 1); + + /* RG_DMPULLDOWN 1'b1 */ + /* U3D_U2PHYDTM0 RG_DMPULLDOWN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DMPULLDOWN_OFST, RG_DMPULLDOWN, 1); + + /* RG_XCVRSEL[1:0] 2'b01 */ + /* U3D_U2PHYDTM0 RG_XCVRSEL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_XCVRSEL_OFST, RG_XCVRSEL, 0x1); + + /* RG_TERMSEL 1'b1 */ + /* U3D_U2PHYDTM0 RG_TERMSEL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_TERMSEL_OFST, RG_TERMSEL, 1); + + /* RG_DATAIN[3:0] 4'b0000 */ + /* U3D_U2PHYDTM0 RG_DATAIN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DATAIN_OFST, RG_DATAIN, 0); + + /* force_dp_pulldown 1'b1 */ + /* U3D_U2PHYDTM0 FORCE_DP_PULLDOWN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DP_PULLDOWN_OFST, FORCE_DP_PULLDOWN, + 1); + + /* force_dm_pulldown 1'b1 */ + /* U3D_U2PHYDTM0 FORCE_DM_PULLDOWN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DM_PULLDOWN_OFST, FORCE_DM_PULLDOWN, + 1); + + /* force_xcversel 1'b1 */ + /* U3D_U2PHYDTM0 FORCE_XCVRSEL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_XCVRSEL_OFST, FORCE_XCVRSEL, 1); + + /* force_termsel 1'b1 */ + /* U3D_U2PHYDTM0 FORCE_TERMSEL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_TERMSEL_OFST, FORCE_TERMSEL, 1); + + /* force_datain 1'b1 */ + /* U3D_U2PHYDTM0 FORCE_DATAIN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DATAIN_OFST, FORCE_DATAIN, 1); + + /*DP/DM BC1.1 path Disable */ + /* RG_USB20_BC11_SW_EN 1'b0 */ + /* U3D_USBPHYACR6 RG_USB20_BC11_SW_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, + RG_USB20_BC11_SW_EN, 0); + + /*OTG Disable */ + /* RG_USB20_OTG_VBUSCMP_EN 1b0 */ + /* U3D_USBPHYACR6 RG_USB20_OTG_VBUSCMP_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_OTG_VBUSCMP_EN_OFST, + RG_USB20_OTG_VBUSCMP_EN, 0); + + /*Change 100uA current switch to USB2.0 */ + /* RG_USB20_HS_100U_U3_EN 1'b0 */ + /* U3D_USBPHYACR5 RG_USB20_HS_100U_U3_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HS_100U_U3_EN_OFST, + RG_USB20_HS_100U_U3_EN, 0); + + /* wait 800us */ + udelay(800); + + /*let suspendm=0, set utmi into analog power down */ + /* RG_SUSPENDM 1'b0 */ + /* U3D_U2PHYDTM0 RG_SUSPENDM */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, RG_SUSPENDM, 0); + + /* wait 1us */ + udelay(1); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_VBUSVALID_OFST, RG_VBUSVALID, 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_AVALID_OFST, RG_AVALID, 0); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_SESSEND_OFST, RG_SESSEND, 1); + + /* USB PLL Force settings */ + usb20_pll_settings(false, false); + + /* TODO: + * Turn off internal 48Mhz PLL if there is no other hardware module is + * using the 48Mhz clock -the control register is in clock document + * Turn off SSUSB reference clock (26MHz) + */ + if (clk_on) { +#if !defined(CONFIG_USB_MU3D_ONLY_U2_MODE) + /*---CLOCK-----*/ + /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG0, RG_SSUSB_VUSB10_ON_OFST, + RG_SSUSB_VUSB10_ON, 0); +#endif + /* Wait 10 usec. */ + udelay(10); + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(false); + + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(0); */ +#if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /*---POWER-----*/ + /* Set RG_VUSB10_ON as 1 after VDD10 Ready */ + /*hwPowerDown(MT6331_POWER_LDO_VUSB10, "VDD10_USB_P0"); */ + pmic_set_register_value(MT6351_PMIC_RG_VA10_EN, 0x00); +#endif + } + + os_printk(K_INFO, "%s-\n", __func__); +} + +/*This "recovery" sequence refers to "6593_USB_PORT0_PWR Sequence 20130729.xls"*/ +void usb_phy_recover(unsigned int clk_on) +{ + PHY_INT32 ret; + + os_printk(K_DEBUG, "%s clk_on=%d+\n", __func__, clk_on); + + if (!clk_on) { +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /*---POWER-----*/ + /*AVDD18_USB_P0 is always turned on. The driver does _NOT_ need to control it. */ + ret = pmic_set_register_value(PMIC_LDO_VUSB33_EN, 0x01); + if (ret) + pr_debug("VUSB33 enable FAIL!!!\n"); +#else + /*---POWER-----*/ + /*AVDD18_USB_P0 is always turned on. The driver does _NOT_ need to control it. */ + /*hwPowerOn(MT6332_POWER_LDO_VUSB33, VOL_3300, "VDD33_USB_P0"); */ + ret = pmic_set_register_value(MT6351_PMIC_RG_VUSB33_EN, 0x01); + if (ret) + pr_debug("VUSB33 enable FAIL!!!\n"); + + /* Set RG_VUSB10_ON as 1 after VDD10 Ready */ + /*hwPowerOn(MT6331_POWER_LDO_VUSB10, VOL_1000, "VDD10_USB_P0"); */ + ret = pmic_set_register_value(MT6351_PMIC_RG_VA10_EN, 0x01); + if (ret) + pr_debug("VA10 enable FAIL!!!\n"); + + ret = pmic_set_register_value(MT6351_PMIC_RG_VA10_VOSEL, 0x02); + if (ret) + pr_debug("VA10 output selection to 1.0v FAIL!!!\n"); +#endif + /*---CLOCK-----*/ + /* ADA_SSUSB_XTAL_CK:26MHz */ + /*set_ada_ssusb_xtal_ck(1); */ + + /* AD_LTEPLL_SSUSB26M_CK:26MHz always on */ + /* It seems that when turning on ADA_SSUSB_XTAL_CK, AD_LTEPLL_SSUSB26M_CK will also turn on. */ + /* enable_ssusb26m_ck(true); */ + + /* f_fusb30_ck:125MHz */ + usb_enable_clock(true); + + /* AD_SSUSB_48M_CK:48MHz */ + /* It seems that when turning on f_fusb30_ck, AD_SSUSB_48M_CK will also turn on. */ + + /* Wait 50 usec. (PHY 3.3v & 1.8v power stable time) */ + udelay(50); +#if !defined(CONFIG_USB_MU3D_ONLY_U2_MODE) + /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG0, RG_SSUSB_VUSB10_ON_OFST, + RG_SSUSB_VUSB10_ON, 1); +#endif + } + + /*[MT6593 only]power domain iso disable */ + /* RG_USB20_ISO_EN 1'b0 */ + /* U3D_USBPHYACR6 RG_USB20_ISO_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_ISO_EN_OFST, RG_USB20_ISO_EN, 0); + +#ifdef CONFIG_MTK_UART_USB_SWITCH + if (!in_uart_mode) { + /*switch to USB function. (system register, force ip into usb mode) */ + /* force_uart_en 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_UART_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, + 0); + /* RG_UART_EN 1'b0 */ + /* U3D_U2PHYDTM1 RG_UART_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); + /*force_suspendm 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_SUSPENDM */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, + 0); + } + /* rg_usb20_gpio_ctl 1'b0 */ + /* U3D_U2PHYACR4 RG_USB20_GPIO_CTL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, RG_USB20_GPIO_CTL, + 0); + /* usb20_gpio_mode 1'b0 */ + /* U3D_U2PHYACR4 USB20_GPIO_MODE */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, USB20_GPIO_MODE, 0); +#else + /*switch to USB function. (system register, force ip into usb mode) */ + /* force_uart_en 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_UART_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 0); + /* RG_UART_EN 1'b0 */ + /* U3D_U2PHYDTM1 RG_UART_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); + /* rg_usb20_gpio_ctl 1'b0 */ + /* U3D_U2PHYACR4 RG_USB20_GPIO_CTL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, RG_USB20_GPIO_CTL, + 0); + /* usb20_gpio_mode 1'b0 */ + /* U3D_U2PHYACR4 USB20_GPIO_MODE */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, USB20_GPIO_MODE, 0); + + /*Release force suspendm. (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ + /*force_suspendm 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_SUSPENDM */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, 0); +#endif + + /* RG_DPPULLDOWN 1'b0 */ + /* U3D_U2PHYDTM0 RG_DPPULLDOWN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DPPULLDOWN_OFST, RG_DPPULLDOWN, 0); + + /* RG_DMPULLDOWN 1'b0 */ + /* U3D_U2PHYDTM0 RG_DMPULLDOWN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DMPULLDOWN_OFST, RG_DMPULLDOWN, 0); + + /* RG_XCVRSEL[1:0] 2'b00 */ + /* U3D_U2PHYDTM0 RG_XCVRSEL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_XCVRSEL_OFST, RG_XCVRSEL, 0); + + /* RG_TERMSEL 1'b0 */ + /* U3D_U2PHYDTM0 RG_TERMSEL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_TERMSEL_OFST, RG_TERMSEL, 0); + + /* RG_DATAIN[3:0] 4'b0000 */ + /* U3D_U2PHYDTM0 RG_DATAIN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DATAIN_OFST, RG_DATAIN, 0); + + /* force_dp_pulldown 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_DP_PULLDOWN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DP_PULLDOWN_OFST, FORCE_DP_PULLDOWN, + 0); + + /* force_dm_pulldown 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_DM_PULLDOWN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DM_PULLDOWN_OFST, FORCE_DM_PULLDOWN, + 0); + + /* force_xcversel 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_XCVRSEL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_XCVRSEL_OFST, FORCE_XCVRSEL, 0); + + /* force_termsel 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_TERMSEL */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_TERMSEL_OFST, FORCE_TERMSEL, 0); + + /* force_datain 1'b0 */ + /* U3D_U2PHYDTM0 FORCE_DATAIN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DATAIN_OFST, FORCE_DATAIN, 0); + + /*DP/DM BC1.1 path Disable */ + /* RG_USB20_BC11_SW_EN 1'b0 */ + /* U3D_USBPHYACR6 RG_USB20_BC11_SW_EN */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, + RG_USB20_BC11_SW_EN, 0); + + /*OTG Enable */ + /* RG_USB20_OTG_VBUSCMP_EN 1b1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_OTG_VBUSCMP_EN_OFST, + RG_USB20_OTG_VBUSCMP_EN, 1); + /*Pass RX sensitivity HQA requirement */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_SQTH_OFST, RG_USB20_SQTH, 0x2); + +#if defined(CONFIG_MTK_HDMI_SUPPORT) || defined(MTK_USB_MODE1) + os_printk(K_INFO, "%s- USB PHY Driving Tuning Mode 1 Settings.\n", __func__); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HS_100U_U3_EN_OFST, + RG_USB20_HS_100U_U3_EN, 0); +#else +#if !defined(CONFIG_USB_MU3D_ONLY_U2_MODE) + /*Change 100uA current switch to SSUSB */ + /* RG_USB20_HS_100U_U3_EN 1'b1 */ + /*U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HS_100U_U3_EN_OFST, + RG_USB20_HS_100U_U3_EN, 1);*/ +#endif +#endif + + /* + * 1 RG_SSUSB_TX_EIDLE_CM<3:0> / 1100-->1110 / low-power + * E-idle common mode(650mV to 600mV) - 0x11290b18 bit [31:28] + * 2 RG_SSUSB_CDR_BIR_LTD0[4:0] / 5'b01000-->5'b01100 / Increase BW - 0x1128095c bit [12:8] + * 3 RG_XXX_CDR_BIR_LTD1[4:0] / 5'b00010-->5'b00011 / Increase BW - 0x1128095c bit [28:24] + */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG6, RG_SSUSB_TX_EIDLE_CM_OFST, + RG_SSUSB_TX_EIDLE_CM, 0xE); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_PHYD_CDR1, RG_SSUSB_CDR_BIR_LTD0_OFST, + RG_SSUSB_CDR_BIR_LTD0, 0xC); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_PHYD_CDR1, RG_SSUSB_CDR_BIR_LTD1_OFST, + RG_SSUSB_CDR_BIR_LTD1, 0x3); + + /* + * 1.DA_SSUSB_XTAL_EXT_EN[1:0] 2'b01-->2'b10 - 0x11290c00 bit[11:10] + * 2.DA_SSUSB_XTAL_RX_PWD[9:9] -->1'b1 - 0x11280018 bit[9] + */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U3PHYA_DA_REG0, RG_SSUSB_XTAL_EXT_EN_U3_OFST, + RG_SSUSB_XTAL_EXT_EN_U3, 2); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_SPLLC_XTALCTL3, RG_SSUSB_XTAL_RX_PWD_OFST, + RG_SSUSB_XTAL_RX_PWD, 1); + + /* Wait 800 usec */ + udelay(800); + + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_VBUSVALID_OFST, RG_VBUSVALID, 1); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_AVALID_OFST, RG_AVALID, 1); + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_SESSEND_OFST, RG_SESSEND, 0); + +#ifdef CONFIG_MTK_UART_USB_SWITCH + if (in_uart_mode) { + os_printk(K_INFO, + "%s- Switch to UART mode when UART cable in inserted before boot.\n", + __func__); + usb_phy_switch_to_uart(); + } +#endif + if (get_devinfo_with_index(9) & 0x1F) { + os_printk(K_INFO, "USB HW reg: index9=0x%x\n", get_devinfo_with_index(9)); + /*PORT0 11290804[23:19]*/ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR1, RG_USB20_INTR_CAL_OFST, RG_USB20_INTR_CAL, + get_devinfo_with_index(9) & (0x1F)); + } + /* Set host disconnect threshold*/ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_DISCTH_OFST, RG_USB20_DISCTH, 0xF); + /* USB PLL Force settings */ + usb20_pll_settings(false, false); + + os_printk(K_DEBUG, "%s-\n", __func__); +} + +/* + * This function is to solve the condition described below. + * The system boot has 3 situations. + * 1. Booting without cable, so connection work called by musb_gadget_start() + * would turn off pwr/clk by musb_stop(). [REF CNT = 0] + * 2. Booting with normal cable, the pwr/clk has already turned on at initial stage. + * and also set the flag (musb->is_clk_on=1). + * So musb_start() would not turn on again. [REF CNT = 1] + * 3. Booting with OTG cable, the pwr/clk would be turned on by host one more time.[REF CNT=2] + * So device should turn off pwr/clk which are turned on during the initial stage. + * However, does _NOT_ touch the PHY registers. So we need this fake function to keep the REF CNT correct. + * NOT FOR TURN OFF PWR/CLK. + */ +void usb_fake_powerdown(unsigned int clk_on) +{ + os_printk(K_INFO, "%s clk_on=%d+\n", __func__, clk_on); + + if (clk_on) { + /*---CLOCK-----*/ + /* f_fusb30_ck:125MHz */ + usb_enable_clock(false); + + /*---POWER-----*/ + /* Set RG_VUSB10_ON as 1 after VDD10 Ready */ + /*hwPowerDown(MT6331_POWER_LDO_VUSB10, "VDD10_USB_P0"); */ +#if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /*ret = pmic_set_register_value(MT6351_PMIC_RG_VA10_EN, 0x00);*/ +#endif + } + + os_printk(K_INFO, "%s-\n", __func__); +} + +#ifdef CONFIG_USBIF_COMPLIANCE +static bool charger_det_en = true; + +void Charger_Detect_En(bool enable) +{ + charger_det_en = enable; +} +#endif + + +/* BC1.2 */ +void Charger_Detect_Init(void) +{ + os_printk(K_DEBUG, "%s+\n", __func__); + +#ifdef CONFIG_USBIF_COMPLIANCE + if (charger_det_en == true) { +#endif + /* turn on USB reference clock. */ + usb_enable_clock(true); + + /* wait 50 usec. */ + udelay(50); + + /* RG_USB20_BC11_SW_EN = 1'b1 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, + RG_USB20_BC11_SW_EN, 1); + + udelay(1); + + /* 4 14. turn off internal 48Mhz PLL. */ + usb_enable_clock(false); + +#ifdef CONFIG_USBIF_COMPLIANCE + } else { + os_printk(K_INFO, "%s do not init detection as charger_det_en is false\n", + __func__); + } +#endif + + os_printk(K_DEBUG, "%s-\n", __func__); +} + +void Charger_Detect_Release(void) +{ + os_printk(K_DEBUG, "%s+\n", __func__); + +#ifdef CONFIG_USBIF_COMPLIANCE + if (charger_det_en == true) { +#endif + /* turn on USB reference clock. */ + usb_enable_clock(true); + + /* wait 50 usec. */ + udelay(50); + + /* RG_USB20_BC11_SW_EN = 1'b0 */ + U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, + RG_USB20_BC11_SW_EN, 0); + + udelay(1); + + /* 4 14. turn off internal 48Mhz PLL. */ + usb_enable_clock(false); + +#ifdef CONFIG_USBIF_COMPLIANCE + } else { + os_printk(K_DEBUG, "%s do not release detection as charger_det_en is false\n", + __func__); + } +#endif + + os_printk(K_INFO, "%s-\n", __func__); +} + + + +#ifdef CONFIG_OF +static int mt_usb_dts_probe(struct platform_device *pdev) +{ + int retval = 0; +#ifndef CONFIG_MTK_CLKMGR + musb_clk = devm_clk_get(&pdev->dev, "sssub_clk"); + if (IS_ERR(musb_clk)) { + os_printk(K_ERR, "SSUSB cannot get musb clock\n"); + return PTR_ERR(musb_clk); + } + + os_printk(K_DEBUG, "SSUSB get musb clock ok, prepare it\n"); + retval = clk_prepare(musb_clk); + if (retval == 0) + os_printk(K_DEBUG, "musb clock prepare done\n"); + else + os_printk(K_ERR, "musb clock prepare fail\n"); +#endif + return retval; +} + +static int mt_usb_dts_remove(struct platform_device *pdev) +{ +#ifndef CONFIG_MTK_CLKMGR + clk_unprepare(musb_clk); +#endif + return 0; +} + + +static const struct of_device_id apusb_of_ids[] = { + {.compatible = "mediatek,usb3_phy",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, apusb_of_ids); + +static struct platform_driver mt_usb_dts_driver = { + .remove = mt_usb_dts_remove, + .probe = mt_usb_dts_probe, + .driver = { + .name = "mt_dts_mu3phy", + .of_match_table = apusb_of_ids, + }, +}; +MODULE_DESCRIPTION("mtu3phy MUSB PHY Layer"); +MODULE_AUTHOR("MediaTek"); +MODULE_LICENSE("GPL v2"); +module_platform_driver(mt_usb_dts_driver); + +#endif + +#endif diff --git a/drivers/misc/mediatek/mu3phy/mt6755/mtk-phy-asic.h b/drivers/misc/mediatek/mu3phy/mt6755/mtk-phy-asic.h new file mode 100644 index 0000000000000000000000000000000000000000..0274f0fca7f6a6c2de05613afdd8b9299af0e47b --- /dev/null +++ b/drivers/misc/mediatek/mu3phy/mt6755/mtk-phy-asic.h @@ -0,0 +1,3201 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef CONFIG_PROJECT_PHY +#ifndef __MTK_PROJECT_PHY__H +#define __MTK_PROJECT_PHY__H + +/* referenecd from ssusb_USB20_PHY_regmap_com_T28HPM.xls */ +#define U3D_USBPHYACR0 (SSUSB_SIFSLV_U2PHY_COM_SIV_B_BASE+0x0000) /*2:30 SIV_B */ +#define U3D_USBPHYACR1 (SSUSB_SIFSLV_U2PHY_COM_SIV_B_BASE+0x0004) /*0:23 SIV_B */ +#define U3D_USBPHYACR2 (SSUSB_SIFSLV_U2PHY_COM_SIV_B_BASE+0x0008) /*0:15 SIV_B */ +#define U3D_USBPHYACR4 (SSUSB_SIFSLV_U2PHY_COM_SIV_B_BASE+0x0010) /*0:31 SIV_B */ +#define U3D_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_SIV_B_BASE+0x0014) /*0:28 SIV_B */ +#define U3D_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_SIV_B_BASE+0x0018) /*0:31 SIV_B */ +#define U3D_U2PHYACR3 (SSUSB_SIFSLV_U2PHY_COM_SIV_B_BASE+0x001c) /*0:31 SIV_B */ +#define U3D_U2PHYACR4_0 (SSUSB_SIFSLV_U2PHY_COM_SIV_B_BASE+0x0020) /*0:5 SIV_B */ + +#define U3D_USBPHYACR2_0 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0008) /* 16:18 */ +#define U3D_U2PHYACR4 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0020) /*8:18 */ +#define U3D_U2PHYAMON0 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0024) /*0:1 */ +#define U3D_U2PHYDCR0 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0060) /*0:31 */ +#define U3D_U2PHYDCR1 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0064) /*0:31 */ +#define U3D_U2PHYDTM0 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0068) /*0:31 */ +#define U3D_U2PHYDTM1 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x006C) /*0:31 */ +#define U3D_U2PHYDMON0 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0070) /*0:7 */ +#define U3D_U2PHYDMON1 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0074) /*0:31 */ +#define U3D_U2PHYDMON2 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0078) /*0:31 */ +#define U3D_U2PHYDMON3 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x007C) /*0:31 */ +#define U3D_U2PHYBC12C (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0080) /*0:31 */ +#define U3D_U2PHYBC12C1 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0084) /*0:7 */ +#define U3D_U2PHYREGFPPC (SSUSB_SIFSLV_U2PHY_COM_BASE+0x00e0) /*0:4 */ +#define U3D_U2PHYVERSIONC (SSUSB_SIFSLV_U2PHY_COM_BASE+0x00f0) /*0:31 */ +#define U3D_U2PHYREGFCOM (SSUSB_SIFSLV_U2PHY_COM_BASE+0x00fc) /*16:31 */ + +#define U3D_USB30_PHYA_REG0 (SSUSB_USB30_PHYA_SIV_B_BASE+0x0000) +#define U3D_USB30_PHYA_REG6 (SSUSB_USB30_PHYA_SIV_B_BASE+0x0018) + +#define U3D_PHYD_CDR1 (SSUSB_SIFSLV_U3PHYD_BASE+0x5c) + +#define U3D_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE+0x0) + +#define U3D_SPLLC_XTALCTL3 (SSUSB_SIFSLV_SPLLC_BASE+0x18) +#define U3D_PHYA_REG6 (SSUSB_USB30_PHYA_SIV_B_BASE+0x18) + +#define U2_SR_COEF_E60802 28 + +/* ///////////////////////////////////////////////////////////////////////////// */ + +struct u2phy_reg_e { + /* 0x0 */ + PHY_LE32 usbphyacr0; + PHY_LE32 usbphyacr1; + PHY_LE32 usbphyacr2; + PHY_LE32 reserve0; + /* 0x10 */ + PHY_LE32 usbphyacr4; + PHY_LE32 usbphyacr5; + PHY_LE32 usbphyacr6; + PHY_LE32 u2phyacr3; + /* 0x20 */ + PHY_LE32 u2phyacr4; + PHY_LE32 u2phyamon0; + PHY_LE32 reserve1[2]; + /* 0x30~0x50 */ + PHY_LE32 reserve2[12]; + /* 0x60 */ + PHY_LE32 u2phydcr0; + PHY_LE32 u2phydcr1; + PHY_LE32 u2phydtm0; + PHY_LE32 u2phydtm1; + /* 0x70 */ + PHY_LE32 u2phydmon0; + PHY_LE32 u2phydmon1; + PHY_LE32 u2phydmon2; + PHY_LE32 u2phydmon3; + /* 0x80 */ + PHY_LE32 u2phybc12c; + PHY_LE32 u2phybc12c1; + PHY_LE32 reserve3[2]; + /* 0x90~0xd0 */ + PHY_LE32 reserve4[20]; + /* 0xe0 */ + PHY_LE32 regfppc; + PHY_LE32 reserve5[3]; + /* 0xf0 */ + PHY_LE32 versionc; + PHY_LE32 reserve6[2]; + PHY_LE32 regfcom; +}; + +/* U3D_USBPHYACR0 */ +#define RG_USB20_MPX_OUT_SEL (0x7<<28) /* 30:28 */ +#define RG_USB20_TX_PH_ROT_SEL (0x7<<24) /* 26:24 */ +#define RG_USB20_PLL_DIVEN (0x7<<20) /* 22:20 */ +#define RG_USB20_PLL_BR (0x1<<18) /* 18:18 */ +#define RG_USB20_PLL_BP (0x1<<17) /* 17:17 */ +#define RG_USB20_PLL_BLP (0x1<<16) /* 16:16 */ +#define RG_USB20_USBPLL_FORCE_ON (0x1<<15) /* 15:15 */ +#define RG_USB20_PLL_FBDIV (0x7f<<8) /* 14:8 */ +#define RG_USB20_PLL_PREDIV (0x3<<6) /* 7:6 */ +#define RG_USB20_INTR_EN (0x1<<5) /* 5:5 */ +#define RG_USB20_REF_EN (0x1<<4) /* 4:4 */ +#define RG_USB20_BGR_DIV (0x3<<2) /* 3:2 */ +#define RG_SIFSLV_CHP_EN (0x1<<1) /* 1:1 */ +#define RG_SIFSLV_BGR_EN (0x1<<0) /* 0:0 */ + +/* U3D_USBPHYACR1 */ +#define RG_USB20_INTR_CAL (0x1f<<19) /* 23:19 */ +#define RG_USB20_OTG_VBUSTH (0x7<<16) /* 18:16 */ +#define RG_USB20_VRT_VREF_SEL (0x7<<12) /* 14:12 */ +#define RG_USB20_TERM_VREF_SEL (0x7<<8) /* 10:8 */ +#define RG_USB20_MPX_SEL (0xff<<0) /* 7:0 */ + +/* U3D_USBPHYACR2 */ +#define RG_SIFSLV_MAC_BANDGAP_EN (0x1<<17) /* 17:17 */ +#define RG_SIFSLV_MAC_CHOPPER_EN (0x1<<16) /* 16:16 */ +#define RG_USB20_CLKREF_REV (0xffff<<0) /* 15:0 */ + +/* U3D_USBPHYACR2_0 */ +#define RG_SIFSLV_USB20_PLL_FORCE_MODE (0x1<<18) /* 18:18 */ + +/* U3D_USBPHYACR4 */ +#define RG_USB20_DP_ABIST_SOURCE_EN (0x1<<31) /* 31:31 */ +#define RG_USB20_DP_ABIST_SELE (0xf<<24) /* 27:24 */ +#define RG_USB20_ICUSB_EN (0x1<<16) /* 16:16 */ +#define RG_USB20_LS_CR (0x7<<12) /* 14:12 */ +#define RG_USB20_FS_CR (0x7<<8) /* 10:8 */ +#define RG_USB20_LS_SR (0x7<<4) /* 6:4 */ +#define RG_USB20_FS_SR (0x7<<0) /* 2:0 */ + +/* U3D_USBPHYACR5 */ +#define RG_USB20_DISC_FIT_EN (0x1<<28) /* 28:28 */ +#define RG_USB20_INIT_SQ_EN_DG (0x3<<26) /* 27:26 */ +#define RG_USB20_HSTX_TMODE_SEL (0x3<<24) /* 25:24 */ +#define RG_USB20_SQD (0x3<<22) /* 23:22 */ +#define RG_USB20_DISCD (0x3<<20) /* 21:20 */ +#define RG_USB20_HSTX_TMODE_EN (0x1<<19) /* 19:19 */ +#define RG_USB20_PHYD_MONEN (0x1<<18) /* 18:18 */ +#define RG_USB20_INLPBK_EN (0x1<<17) /* 17:17 */ +#define RG_USB20_CHIRP_EN (0x1<<16) /* 16:16 */ +#define RG_USB20_HSTX_SRCAL_EN (0x1<<15) /* 15:15 */ +#define RG_USB20_HSTX_SRCTRL (0x7<<12) /* 14:12 */ +#define RG_USB20_HS_100U_U3_EN (0x1<<11) /* 11:11 */ +#define RG_USB20_GBIAS_ENB (0x1<<10) /* 10:10 */ +#define RG_USB20_DM_ABIST_SOURCE_EN (0x1<<7) /* 7:7 */ +#define RG_USB20_DM_ABIST_SELE (0xf<<0) /* 3:0 */ + +/* U3D_USBPHYACR6 */ +#define RG_USB20_ISO_EN (0x1U<<31) /* 31:31 */ +#define RG_USB20_PHY_REV (0xef<<24) /* 31:24 */ +#define RG_USB20_BC11_SW_EN (0x1<<23) /* 23:23 */ +#define RG_USB20_SR_CLK_SEL (0x1<<22) /* 22:22 */ +#define RG_USB20_OTG_VBUSCMP_EN (0x1<<20) /* 20:20 */ +#define RG_USB20_OTG_ABIST_EN (0x1<<19) /* 19:19 */ +#define RG_USB20_OTG_ABIST_SELE (0x7<<16) /* 18:16 */ +#define RG_USB20_HSRX_MMODE_SELE (0x3<<12) /* 13:12 */ +#define RG_USB20_HSRX_BIAS_EN_SEL (0x3<<9) /* 10:9 */ +#define RG_USB20_HSRX_TMODE_EN (0x1<<8) /* 8:8 */ +#define RG_USB20_DISCTH (0xf<<4) /* 7:4 */ +#define RG_USB20_SQTH (0xf<<0) /* 3:0 */ + +/* U3D_U2PHYACR3 */ +#define RG_USB20_HSTX_DBIST (0xf<<28) /* 31:28 */ +#define RG_USB20_HSTX_BIST_EN (0x1<<26) /* 26:26 */ +#define RG_USB20_HSTX_I_EN_MODE (0x3<<24) /* 25:24 */ +#define RG_USB20_USB11_TMODE_EN (0x1<<19) /* 19:19 */ +#define RG_USB20_TMODE_FS_LS_TX_EN (0x1<<18) /* 18:18 */ +#define RG_USB20_TMODE_FS_LS_RCV_EN (0x1<<17) /* 17:17 */ +#define RG_USB20_TMODE_FS_LS_MODE (0x1<<16) /* 16:16 */ +#define RG_USB20_HS_TERM_EN_MODE (0x3<<13) /* 14:13 */ +#define RG_USB20_PUPD_BIST_EN (0x1<<12) /* 12:12 */ +#define RG_USB20_EN_PU_DM (0x1<<11) /* 11:11 */ +#define RG_USB20_EN_PD_DM (0x1<<10) /* 10:10 */ +#define RG_USB20_EN_PU_DP (0x1<<9) /* 9:9 */ +#define RG_USB20_EN_PD_DP (0x1<<8) /* 8:8 */ + +/* U3D_U2PHYACR4 */ +#define RG_USB20_DP_100K_MODE (0x1<<18) /* 18:18 */ +#define RG_USB20_DM_100K_EN (0x1<<17) /* 17:17 */ +#define USB20_DP_100K_EN (0x1<<16) /* 16:16 */ +#define USB20_GPIO_DM_I (0x1<<15) /* 15:15 */ +#define USB20_GPIO_DP_I (0x1<<14) /* 14:14 */ +#define USB20_GPIO_DM_OE (0x1<<13) /* 13:13 */ +#define USB20_GPIO_DP_OE (0x1<<12) /* 12:12 */ +#define RG_USB20_GPIO_CTL (0x1<<9) /* 9:9 */ +#define USB20_GPIO_MODE (0x1<<8) /* 8:8 */ +#define RG_USB20_TX_BIAS_EN (0x1<<5) /* 5:5 */ +#define RG_USB20_TX_VCMPDN_EN (0x1<<4) /* 4:4 */ +#define RG_USB20_HS_SQ_EN_MODE (0x3<<2) /* 3:2 */ +#define RG_USB20_HS_RCV_EN_MODE (0x3<<0) /* 1:0 */ + +/* U3D_U2PHYAMON0 */ +#define RGO_USB20_GPIO_DM_O (0x1<<1) /* 1:1 */ +#define RGO_USB20_GPIO_DP_O (0x1<<0) /* 0:0 */ + +/* U3D_U2PHYDCR0 */ +#define RG_USB20_CDR_TST (0x3<<30) /* 31:30 */ +#define RG_USB20_GATED_ENB (0x1<<29) /* 29:29 */ +#define RG_USB20_TESTMODE (0x3<<26) /* 27:26 */ +#define RG_SIFSLV_USB20_PLL_STABLE (0x1<<25) /* 25:25 */ +#define RG_SIFSLV_USB20_PLL_FORCE_ON (0x1<<24) /* 24:24 */ +#define RG_USB20_PHYD_RESERVE (0xffff<<8) /* 23:8 */ +#define RG_USB20_EBTHRLD (0x1<<7) /* 7:7 */ +#define RG_USB20_EARLY_HSTX_I (0x1<<6) /* 6:6 */ +#define RG_USB20_TX_TST (0x1<<5) /* 5:5 */ +#define RG_USB20_NEGEDGE_ENB (0x1<<4) /* 4:4 */ +#define RG_USB20_CDR_FILT (0xf<<0) /* 3:0 */ + +/* U3D_U2PHYDCR1 */ +#define RG_USB20_PROBE_SEL (0xff<<24) /* 31:24 */ +#define RG_USB20_DRVVBUS (0x1<<23) /* 23:23 */ +#define RG_DEBUG_EN (0x1<<22) /* 22:22 */ +#define RG_USB20_OTG_PROBE (0x3<<20) /* 21:20 */ +#define RG_USB20_SW_PLLMODE (0x3<<18) /* 19:18 */ +#define E60802_RG_USB20_SW_PLLMODE (0x3<<18) /* 19:18 */ +#define RG_USB20_BERTH (0x3<<16) /* 17:16 */ +#define RG_USB20_LBMODE (0x3<<13) /* 14:13 */ +#define RG_USB20_FORCE_TAP (0x1<<12) /* 12:12 */ +#define RG_USB20_TAPSEL (0xfff<<0) /* 11:0 */ + +/* U3D_U2PHYDTM0 */ +#define RG_UART_MODE (0x3<<30) /* 31:30 */ +#define FORCE_UART_I (0x1<<29) /* 29:29 */ +#define FORCE_UART_BIAS_EN (0x1<<28) /* 28:28 */ +#define FORCE_UART_TX_OE (0x1<<27) /* 27:27 */ +#define FORCE_UART_EN (0x1<<26) /* 26:26 */ +#define FORCE_USB_CLKEN (0x1<<25) /* 25:25 */ +#define FORCE_DRVVBUS (0x1<<24) /* 24:24 */ +#define FORCE_DATAIN (0x1<<23) /* 23:23 */ +#define FORCE_TXVALID (0x1<<22) /* 22:22 */ +#define FORCE_DM_PULLDOWN (0x1<<21) /* 21:21 */ +#define FORCE_DP_PULLDOWN (0x1<<20) /* 20:20 */ +#define FORCE_XCVRSEL (0x1<<19) /* 19:19 */ +#define FORCE_SUSPENDM (0x1<<18) /* 18:18 */ +#define FORCE_TERMSEL (0x1<<17) /* 17:17 */ +#define FORCE_OPMODE (0x1<<16) /* 16:16 */ +#define UTMI_MUXSEL (0x1<<15) /* 15:15 */ +#define RG_RESET (0x1<<14) /* 14:14 */ +#define RG_DATAIN (0xf<<10) /* 13:10 */ +#define RG_TXVALIDH (0x1<<9) /* 9:9 */ +#define RG_TXVALID (0x1<<8) /* 8:8 */ +#define RG_DMPULLDOWN (0x1<<7) /* 7:7 */ +#define RG_DPPULLDOWN (0x1<<6) /* 6:6 */ +#define RG_XCVRSEL (0x3<<4) /* 5:4 */ +#define RG_SUSPENDM (0x1<<3) /* 3:3 */ +#define RG_TERMSEL (0x1<<2) /* 2:2 */ +#define RG_OPMODE (0x3<<0) /* 1:0 */ + +/* U3D_U2PHYDTM1 */ +#define RG_USB20_PRBS7_EN (0x1<<31) /* 31:31 */ +#define RG_USB20_PRBS7_BITCNT (0x3f<<24) /* 29:24 */ +#define RG_USB20_CLK48M_EN (0x1<<23) /* 23:23 */ +#define RG_USB20_CLK60M_EN (0x1<<22) /* 22:22 */ +#define RG_UART_I (0x1<<19) /* 19:19 */ +#define RG_UART_BIAS_EN (0x1<<18) /* 18:18 */ +#define RG_UART_TX_OE (0x1<<17) /* 17:17 */ +#define RG_UART_EN (0x1<<16) /* 16:16 */ +#define RG_IP_U2_PORT_POWER (0x1<<15) /* 15:15 */ +#define FORCE_IP_U2_PORT_POWER (0x1<<14) /* 14:14 */ +#define FORCE_VBUSVALID (0x1<<13) /* 13:13 */ +#define FORCE_SESSEND (0x1<<12) /* 12:12 */ +#define FORCE_BVALID (0x1<<11) /* 11:11 */ +#define FORCE_AVALID (0x1<<10) /* 10:10 */ +#define FORCE_IDDIG (0x1<<9) /* 9:9 */ +#define FORCE_IDPULLUP (0x1<<8) /* 8:8 */ +#define RG_VBUSVALID (0x1<<5) /* 5:5 */ +#define RG_SESSEND (0x1<<4) /* 4:4 */ +#define RG_BVALID (0x1<<3) /* 3:3 */ +#define RG_AVALID (0x1<<2) /* 2:2 */ +#define RG_IDDIG (0x1<<1) /* 1:1 */ +#define RG_IDPULLUP (0x1<<0) /* 0:0 */ + +/* U3D_U2PHYDMON0 */ +#define RG_USB20_PRBS7_BERTH (0xff<<0) /* 7:0 */ + +/* U3D_U2PHYDMON1 */ +#define USB20_UART_O (0x1<<31) /* 31:31 */ +#define RGO_USB20_LB_PASS (0x1<<30) /* 30:30 */ +#define RGO_USB20_LB_DONE (0x1<<29) /* 29:29 */ +#define AD_USB20_BVALID (0x1<<28) /* 28:28 */ +#define USB20_IDDIG (0x1<<27) /* 27:27 */ +#define AD_USB20_VBUSVALID (0x1<<26) /* 26:26 */ +#define AD_USB20_SESSEND (0x1<<25) /* 25:25 */ +#define AD_USB20_AVALID (0x1<<24) /* 24:24 */ +#define USB20_LINE_STATE (0x3<<22) /* 23:22 */ +#define USB20_HST_DISCON (0x1<<21) /* 21:21 */ +#define USB20_TX_READY (0x1<<20) /* 20:20 */ +#define USB20_RX_ERROR (0x1<<19) /* 19:19 */ +#define USB20_RX_ACTIVE (0x1<<18) /* 18:18 */ +#define USB20_RX_VALIDH (0x1<<17) /* 17:17 */ +#define USB20_RX_VALID (0x1<<16) /* 16:16 */ +#define USB20_DATA_OUT (0xffff<<0) /* 15:0 */ + +/* U3D_U2PHYDMON2 */ +#define RGO_TXVALID_CNT (0xff<<24) /* 31:24 */ +#define RGO_RXACTIVE_CNT (0xff<<16) /* 23:16 */ +#define RGO_USB20_LB_BERCNT (0xff<<8) /* 15:8 */ +#define USB20_PROBE_OUT (0xff<<0) /* 7:0 */ + +/* U3D_U2PHYDMON3 */ +#define RGO_USB20_PRBS7_ERRCNT (0xffff<<16) /* 31:16 */ +#define RGO_USB20_PRBS7_DONE (0x1<<3) /* 3:3 */ +#define RGO_USB20_PRBS7_LOCK (0x1<<2) /* 2:2 */ +#define RGO_USB20_PRBS7_PASS (0x1<<1) /* 1:1 */ +#define RGO_USB20_PRBS7_PASSTH (0x1<<0) /* 0:0 */ + +/* U3D_U2PHYBC12C */ +#define RG_SIFSLV_CHGDT_DEGLCH_CNT (0xf<<28) /* 31:28 */ +#define RG_SIFSLV_CHGDT_CTRL_CNT (0xf<<24) /* 27:24 */ +#define RG_SIFSLV_CHGDT_FORCE_MODE (0x1<<16) /* 16:16 */ +#define RG_CHGDT_ISRC_LEV (0x3<<14) /* 15:14 */ +#define RG_CHGDT_VDATSRC (0x1<<13) /* 13:13 */ +#define RG_CHGDT_BGVREF_SEL (0x7<<10) /* 12:10 */ +#define RG_CHGDT_RDVREF_SEL (0x3<<8) /* 9:8 */ +#define RG_CHGDT_ISRC_DP (0x1<<7) /* 7:7 */ +#define RG_SIFSLV_CHGDT_OPOUT_DM (0x1<<6) /* 6:6 */ +#define RG_CHGDT_VDAT_DM (0x1<<5) /* 5:5 */ +#define RG_CHGDT_OPOUT_DP (0x1<<4) /* 4:4 */ +#define RG_SIFSLV_CHGDT_VDAT_DP (0x1<<3) /* 3:3 */ +#define RG_SIFSLV_CHGDT_COMP_EN (0x1<<2) /* 2:2 */ +#define RG_SIFSLV_CHGDT_OPDRV_EN (0x1<<1) /* 1:1 */ +#define RG_CHGDT_EN (0x1<<0) /* 0:0 */ + +/* U3D_U2PHYBC12C1 */ +#define RG_CHGDT_REV (0xff<<0) /* 7:0 */ + +/* U3D_REGFPPC */ +#define USB11_OTG_REG (0x1<<4) /* 4:4 */ +#define USB20_OTG_REG (0x1<<3) /* 3:3 */ +#define CHGDT_REG (0x1<<2) /* 2:2 */ +#define USB11_REG (0x1<<1) /* 1:1 */ +#define USB20_REG (0x1<<0) /* 0:0 */ + +/* U3D_VERSIONC */ +#define VERSION_CODE_REGFILE (0xff<<24) /* 31:24 */ +#define USB11_VERSION_CODE (0xff<<16) /* 23:16 */ +#define VERSION_CODE_ANA (0xff<<8) /* 15:8 */ +#define VERSION_CODE_DIG (0xff<<0) /* 7:0 */ + +/* U3D_REGFCOM */ +#define RG_PAGE (0xff<<24) /* 31:24 */ +#define I2C_MODE (0x1<<16) /* 16:16 */ + +/* OFFSET */ + +/* U3D_USBPHYACR0 */ +#define RG_USB20_MPX_OUT_SEL_OFST (28) +#define RG_USB20_TX_PH_ROT_SEL_OFST (24) +#define RG_USB20_PLL_DIVEN_OFST (20) +#define RG_USB20_PLL_BR_OFST (18) +#define RG_USB20_PLL_BP_OFST (17) +#define RG_USB20_PLL_BLP_OFST (16) +#define RG_USB20_USBPLL_FORCE_ON_OFST (15) +#define RG_USB20_PLL_FBDIV_OFST (8) +#define RG_USB20_PLL_PREDIV_OFST (6) +#define RG_USB20_INTR_EN_OFST (5) +#define RG_USB20_REF_EN_OFST (4) +#define RG_USB20_BGR_DIV_OFST (2) +#define RG_SIFSLV_CHP_EN_OFST (1) +#define RG_SIFSLV_BGR_EN_OFST (0) + +/* U3D_USBPHYACR1 */ +#define RG_USB20_INTR_CAL_OFST (19) +#define RG_USB20_OTG_VBUSTH_OFST (16) +#define RG_USB20_VRT_VREF_SEL_OFST (12) +#define RG_USB20_TERM_VREF_SEL_OFST (8) +#define RG_USB20_MPX_SEL_OFST (0) + +/* U3D_USBPHYACR2 */ +#define RG_SIFSLV_MAC_BANDGAP_EN_OFST (17) +#define RG_SIFSLV_MAC_CHOPPER_EN_OFST (16) +#define RG_USB20_CLKREF_REV_OFST (0) + +/* U3D_USBPHYACR2_0 */ +#define RG_SIFSLV_USB20_PLL_FORCE_MODE_OFST (18) + +/* U3D_USBPHYACR4 */ +#define RG_USB20_DP_ABIST_SOURCE_EN_OFST (31) +#define RG_USB20_DP_ABIST_SELE_OFST (24) +#define RG_USB20_ICUSB_EN_OFST (16) +#define RG_USB20_LS_CR_OFST (12) +#define RG_USB20_FS_CR_OFST (8) +#define RG_USB20_LS_SR_OFST (4) +#define RG_USB20_FS_SR_OFST (0) + +/* U3D_USBPHYACR5 */ +#define RG_USB20_DISC_FIT_EN_OFST (28) +#define RG_USB20_INIT_SQ_EN_DG_OFST (26) +#define RG_USB20_HSTX_TMODE_SEL_OFST (24) +#define RG_USB20_SQD_OFST (22) +#define RG_USB20_DISCD_OFST (20) +#define RG_USB20_HSTX_TMODE_EN_OFST (19) +#define RG_USB20_PHYD_MONEN_OFST (18) +#define RG_USB20_INLPBK_EN_OFST (17) +#define RG_USB20_CHIRP_EN_OFST (16) +#define RG_USB20_HSTX_SRCAL_EN_OFST (15) +#define RG_USB20_HSTX_SRCTRL_OFST (12) +#define RG_USB20_HS_100U_U3_EN_OFST (11) +#define RG_USB20_GBIAS_ENB_OFST (10) +#define RG_USB20_DM_ABIST_SOURCE_EN_OFST (7) +#define RG_USB20_DM_ABIST_SELE_OFST (0) + +/* U3D_USBPHYACR6 */ +#define RG_USB20_ISO_EN_OFST (31) +#define RG_USB20_PHY_REV_OFST (24) +#define RG_USB20_BC11_SW_EN_OFST (23) +#define RG_USB20_SR_CLK_SEL_OFST (22) +#define RG_USB20_OTG_VBUSCMP_EN_OFST (20) +#define RG_USB20_OTG_ABIST_EN_OFST (19) +#define RG_USB20_OTG_ABIST_SELE_OFST (16) +#define RG_USB20_HSRX_MMODE_SELE_OFST (12) +#define RG_USB20_HSRX_BIAS_EN_SEL_OFST (9) +#define RG_USB20_HSRX_TMODE_EN_OFST (8) +#define RG_USB20_DISCTH_OFST (4) +#define RG_USB20_SQTH_OFST (0) + +/* U3D_U2PHYACR3 */ +#define RG_USB20_HSTX_DBIST_OFST (28) +#define RG_USB20_HSTX_BIST_EN_OFST (26) +#define RG_USB20_HSTX_I_EN_MODE_OFST (24) +#define RG_USB20_USB11_TMODE_EN_OFST (19) +#define RG_USB20_TMODE_FS_LS_TX_EN_OFST (18) +#define RG_USB20_TMODE_FS_LS_RCV_EN_OFST (17) +#define RG_USB20_TMODE_FS_LS_MODE_OFST (16) +#define RG_USB20_HS_TERM_EN_MODE_OFST (13) +#define RG_USB20_PUPD_BIST_EN_OFST (12) +#define RG_USB20_EN_PU_DM_OFST (11) +#define RG_USB20_EN_PD_DM_OFST (10) +#define RG_USB20_EN_PU_DP_OFST (9) +#define RG_USB20_EN_PD_DP_OFST (8) + +/* U3D_U2PHYACR4 */ +#define RG_USB20_DP_100K_MODE_OFST (18) +#define RG_USB20_DM_100K_EN_OFST (17) +#define USB20_DP_100K_EN_OFST (16) +#define USB20_GPIO_DM_I_OFST (15) +#define USB20_GPIO_DP_I_OFST (14) +#define USB20_GPIO_DM_OE_OFST (13) +#define USB20_GPIO_DP_OE_OFST (12) +#define RG_USB20_GPIO_CTL_OFST (9) +#define USB20_GPIO_MODE_OFST (8) +#define RG_USB20_TX_BIAS_EN_OFST (5) +#define RG_USB20_TX_VCMPDN_EN_OFST (4) +#define RG_USB20_HS_SQ_EN_MODE_OFST (2) +#define RG_USB20_HS_RCV_EN_MODE_OFST (0) + +/* U3D_U2PHYAMON0 */ +#define RGO_USB20_GPIO_DM_O_OFST (1) +#define RGO_USB20_GPIO_DP_O_OFST (0) + +/* U3D_U2PHYDCR0 */ +#define RG_USB20_CDR_TST_OFST (30) +#define RG_USB20_GATED_ENB_OFST (29) +#define RG_USB20_TESTMODE_OFST (26) +#define RG_SIFSLV_USB20_PLL_STABLE_OFST (25) +#define RG_SIFSLV_USB20_PLL_FORCE_ON_OFST (24) +#define RG_USB20_PHYD_RESERVE_OFST (8) +#define RG_USB20_EBTHRLD_OFST (7) +#define RG_USB20_EARLY_HSTX_I_OFST (6) +#define RG_USB20_TX_TST_OFST (5) +#define RG_USB20_NEGEDGE_ENB_OFST (4) +#define RG_USB20_CDR_FILT_OFST (0) + +/* U3D_U2PHYDCR1 */ +#define RG_USB20_PROBE_SEL_OFST (24) +#define RG_USB20_DRVVBUS_OFST (23) +#define RG_DEBUG_EN_OFST (22) +#define RG_USB20_OTG_PROBE_OFST (20) +#define RG_USB20_SW_PLLMODE_OFST (18) +#define E60802_RG_USB20_SW_PLLMODE_OFST (18) +#define RG_USB20_BERTH_OFST (16) +#define RG_USB20_LBMODE_OFST (13) +#define RG_USB20_FORCE_TAP_OFST (12) +#define RG_USB20_TAPSEL_OFST (0) + +/* U3D_U2PHYDTM0 */ +#define RG_UART_MODE_OFST (30) +#define FORCE_UART_I_OFST (29) +#define FORCE_UART_BIAS_EN_OFST (28) +#define FORCE_UART_TX_OE_OFST (27) +#define FORCE_UART_EN_OFST (26) +#define FORCE_USB_CLKEN_OFST (25) +#define FORCE_DRVVBUS_OFST (24) +#define FORCE_DATAIN_OFST (23) +#define FORCE_TXVALID_OFST (22) +#define FORCE_DM_PULLDOWN_OFST (21) +#define FORCE_DP_PULLDOWN_OFST (20) +#define FORCE_XCVRSEL_OFST (19) +#define FORCE_SUSPENDM_OFST (18) +#define FORCE_TERMSEL_OFST (17) +#define FORCE_OPMODE_OFST (16) +#define UTMI_MUXSEL_OFST (15) +#define RG_RESET_OFST (14) +#define RG_DATAIN_OFST (10) +#define RG_TXVALIDH_OFST (9) +#define RG_TXVALID_OFST (8) +#define RG_DMPULLDOWN_OFST (7) +#define RG_DPPULLDOWN_OFST (6) +#define RG_XCVRSEL_OFST (4) +#define RG_SUSPENDM_OFST (3) +#define RG_TERMSEL_OFST (2) +#define RG_OPMODE_OFST (0) + +/* U3D_U2PHYDTM1 */ +#define RG_USB20_PRBS7_EN_OFST (31) +#define RG_USB20_PRBS7_BITCNT_OFST (24) +#define RG_USB20_CLK48M_EN_OFST (23) +#define RG_USB20_CLK60M_EN_OFST (22) +#define RG_UART_I_OFST (19) +#define RG_UART_BIAS_EN_OFST (18) +#define RG_UART_TX_OE_OFST (17) +#define RG_UART_EN_OFST (16) +#define RG_IP_U2_PORT_POWER_OFST (15) +#define FORCE_IP_U2_PORT_POWER_OFST (14) +#define FORCE_VBUSVALID_OFST (13) +#define FORCE_SESSEND_OFST (12) +#define FORCE_BVALID_OFST (11) +#define FORCE_AVALID_OFST (10) +#define FORCE_IDDIG_OFST (9) +#define FORCE_IDPULLUP_OFST (8) +#define RG_VBUSVALID_OFST (5) +#define RG_SESSEND_OFST (4) +#define RG_BVALID_OFST (3) +#define RG_AVALID_OFST (2) +#define RG_IDDIG_OFST (1) +#define RG_IDPULLUP_OFST (0) + +/* U3D_U2PHYDMON0 */ +#define RG_USB20_PRBS7_BERTH_OFST (0) + +/* U3D_U2PHYDMON1 */ +#define USB20_UART_O_OFST (31) +#define RGO_USB20_LB_PASS_OFST (30) +#define RGO_USB20_LB_DONE_OFST (29) +#define AD_USB20_BVALID_OFST (28) +#define USB20_IDDIG_OFST (27) +#define AD_USB20_VBUSVALID_OFST (26) +#define AD_USB20_SESSEND_OFST (25) +#define AD_USB20_AVALID_OFST (24) +#define USB20_LINE_STATE_OFST (22) +#define USB20_HST_DISCON_OFST (21) +#define USB20_TX_READY_OFST (20) +#define USB20_RX_ERROR_OFST (19) +#define USB20_RX_ACTIVE_OFST (18) +#define USB20_RX_VALIDH_OFST (17) +#define USB20_RX_VALID_OFST (16) +#define USB20_DATA_OUT_OFST (0) + +/* U3D_U2PHYDMON2 */ +#define RGO_TXVALID_CNT_OFST (24) +#define RGO_RXACTIVE_CNT_OFST (16) +#define RGO_USB20_LB_BERCNT_OFST (8) +#define USB20_PROBE_OUT_OFST (0) + +/* U3D_U2PHYDMON3 */ +#define RGO_USB20_PRBS7_ERRCNT_OFST (16) +#define RGO_USB20_PRBS7_DONE_OFST (3) +#define RGO_USB20_PRBS7_LOCK_OFST (2) +#define RGO_USB20_PRBS7_PASS_OFST (1) +#define RGO_USB20_PRBS7_PASSTH_OFST (0) + +/* U3D_U2PHYBC12C */ +#define RG_SIFSLV_CHGDT_DEGLCH_CNT_OFST (28) +#define RG_SIFSLV_CHGDT_CTRL_CNT_OFST (24) +#define RG_SIFSLV_CHGDT_FORCE_MODE_OFST (16) +#define RG_CHGDT_ISRC_LEV_OFST (14) +#define RG_CHGDT_VDATSRC_OFST (13) +#define RG_CHGDT_BGVREF_SEL_OFST (10) +#define RG_CHGDT_RDVREF_SEL_OFST (8) +#define RG_CHGDT_ISRC_DP_OFST (7) +#define RG_SIFSLV_CHGDT_OPOUT_DM_OFST (6) +#define RG_CHGDT_VDAT_DM_OFST (5) +#define RG_CHGDT_OPOUT_DP_OFST (4) +#define RG_SIFSLV_CHGDT_VDAT_DP_OFST (3) +#define RG_SIFSLV_CHGDT_COMP_EN_OFST (2) +#define RG_SIFSLV_CHGDT_OPDRV_EN_OFST (1) +#define RG_CHGDT_EN_OFST (0) + +/* U3D_U2PHYBC12C1 */ +#define RG_CHGDT_REV_OFST (0) + +/* U3D_REGFPPC */ +#define USB11_OTG_REG_OFST (4) +#define USB20_OTG_REG_OFST (3) +#define CHGDT_REG_OFST (2) +#define USB11_REG_OFST (1) +#define USB20_REG_OFST (0) + +/* U3D_VERSIONC */ +#define VERSION_CODE_REGFILE_OFST (24) +#define USB11_VERSION_CODE_OFST (16) +#define VERSION_CODE_ANA_OFST (8) +#define VERSION_CODE_DIG_OFST (0) + +/* U3D_REGFCOM */ +#define RG_PAGE_OFST (24) +#define I2C_MODE_OFST (16) + +/* ///////////////////////////////////////////////////////////////////////////// */ + +struct u3phya_reg_e { + /* 0x0 */ + PHY_LE32 reg0; + PHY_LE32 reg1; + PHY_LE32 reg2; + PHY_LE32 reg3; + /* 0x10 */ + PHY_LE32 reg4; + PHY_LE32 reg5; + PHY_LE32 reg6; + PHY_LE32 reg7; + /* 0x20 */ + PHY_LE32 reg8; + PHY_LE32 reg9; + PHY_LE32 rega; + PHY_LE32 regb; + /* 0x30 */ + PHY_LE32 regc; +}; + +/* U3D_reg0 */ +#define RG_SSUSB_BGR_EN (0x1<<31) /* 31:31 */ +#define RG_SSUSB_CHPEN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_BG_DIV (0x3<<28) /* 29:28 */ +#define RG_SSUSB_INTR_EN (0x1<<26) /* 26:26 */ +#define RG_SSUSB_MPX_EN (0x1<<24) /* 24:24 */ +#define RG_SSUSB_MPX_SEL (0xff<<16) /* 23:16 */ +#define RG_SSUSB_REF_EN (0x1<<15) /* 15:15 */ +#define RG_SSUSB_VRT_VREF_SEL (0xf<<11) /* 14:11 */ +#define RG_SSUSB_BG_MONEN (0x1<<8) /* 8:8 */ +#define RG_SSUSB_INT_BIAS_SEL (0x1<<7) /* 7:7 */ +#define RG_SSUSB_EXT_BIAS_SEL (0x1<<6) /* 6:6 */ +#define RG_PCIE_CLKDRV_OFFSET (0x3<<2) /* 3:2 */ +#define RG_PCIE_CLKDRV_SLEW (0x3<<0) /* 1:0 */ + +/* U3D_reg1 */ +#define RG_PCIE_CLKDRV_AMP (0x7<<29) /* 31:29 */ +#define RG_SSUSB_XTAL_TST_A2DCK_EN (0x1<<28) /* 28:28 */ +#define RG_SSUSB_XTAL_MON_EN (0x1<<27) /* 27:27 */ +#define RG_SSUSB_XTAL_HYS (0x1<<26) /* 26:26 */ +#define RG_SSUSB_XTAL_TOP_RESERVE (0xffff<<10) /* 25:10 */ +#define RG_SSUSB_SYSPLL_PREDIV (0x3<<8) /* 9:8 */ +#define RG_SSUSB_SYSPLL_POSDIV (0x3<<6) /* 7:6 */ +#define RG_SSUSB_SYSPLL_VCO_DIV_SEL (0x1<<5) /* 5:5 */ +#define RG_SSUSB_SYSPLL_VOD_EN (0x1<<4) /* 4:4 */ +#define RG_SSUSB_SYSPLL_RST_DLY (0x3<<2) /* 3:2 */ +#define RG_SSUSB_SYSPLL_BLP (0x1<<1) /* 1:1 */ +#define RG_SSUSB_SYSPLL_BP (0x1<<0) /* 0:0 */ + +/* U3D_reg2 */ +#define RG_SSUSB_SYSPLL_BR (0x1<<31) /* 31:31 */ +#define RG_SSUSB_SYSPLL_BC (0x1<<30) /* 30:30 */ +#define RG_SSUSB_SYSPLL_MONCK_EN (0x1<<29) /* 29:29 */ +#define RG_SSUSB_SYSPLL_MONVC_EN (0x1<<28) /* 28:28 */ +#define RG_SSUSB_SYSPLL_MONREF_EN (0x1<<27) /* 27:27 */ +#define RG_SSUSB_SYSPLL_SDM_IFM (0x1<<26) /* 26:26 */ +#define RG_SSUSB_SYSPLL_SDM_OUT (0x1<<25) /* 25:25 */ +#define RG_SSUSB_SYSPLL_BACK_EN (0x1<<24) /* 24:24 */ + +/* U3D_reg3 */ +#define RG_SSUSB_SYSPLL_FBDIV (0x7fffffff<<1) /* 31:1 */ +#define RG_SSUSB_SYSPLL_HR_EN (0x1<<0) /* 0:0 */ + +/* U3D_reg4 */ +#define RG_SSUSB_SYSPLL_SDM_DI_EN (0x1<<31) /* 31:31 */ +#define RG_SSUSB_SYSPLL_SDM_DI_LS (0x3<<29) /* 30:29 */ +#define RG_SSUSB_SYSPLL_SDM_ORD (0x3<<27) /* 28:27 */ +#define RG_SSUSB_SYSPLL_SDM_MODE (0x3<<25) /* 26:25 */ +#define RG_SSUSB_SYSPLL_RESERVE (0xff<<17) /* 24:17 */ +#define RG_SSUSB_SYSPLL_TOP_RESERVE (0xffff<<1) /* 16:1 */ + +/* U3D_reg5 */ +#define RG_SSUSB_TX250MCK_INVB (0x1<<31) /* 31:31 */ +#define RG_SSUSB_IDRV_ITAILOP_EN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_IDRV_CALIB (0x3f<<24) /* 29:24 */ +#define RG_SSUSB_IDEM_BIAS (0xf<<20) /* 23:20 */ +#define RG_SSUSB_TX_R50_FON (0x1<<19) /* 19:19 */ +#define RG_SSUSB_TX_SR (0x7<<16) /* 18:16 */ +#define RG_SSUSB_RXDET_RSEL (0x3<<14) /* 15:14 */ +#define RG_SSUSB_RXDET_UPDN_FORCE (0x1<<13) /* 13:13 */ +#define RG_SSUSB_RXDET_UPDN_SEL (0x1<<12) /* 12:12 */ +#define RG_SSUSB_RXDET_VTHSEL_L (0x3<<10) /* 11:10 */ +#define RG_SSUSB_RXDET_VTHSEL_H (0x3<<8) /* 9:8 */ +#define RG_SSUSB_CKMON_EN (0x1<<7) /* 7:7 */ +#define RG_SSUSB_TX_VLMON_EN (0x1<<6) /* 6:6 */ +#define RG_SSUSB_TX_VLMON_SEL (0x3<<4) /* 5:4 */ +#define RG_SSUSB_CKMON_SEL (0xf<<0) /* 3:0 */ + +/* U3D_reg6 */ +#define RG_SSUSB_TX_EIDLE_CM (0xf<<28) /* 31:28 */ +#define RG_SSUSB_RXLBTX_EN (0x1<<27) /* 27:27 */ +#define RG_SSUSB_TXLBRX_EN (0x1<<26) /* 26:26 */ +#define RG_SSUSB_RESERVE6 (0x1<<22) /* 22:22 */ +#define RG_SSUSB_RESERVE (0x3ff<<16) /* 25:16 */ +#define RG_SSUSB_PLL_POSDIV (0x3<<14) /* 15:14 */ +#define RG_SSUSB_PLL_AUTOK_LOAD (0x1<<13) /* 13:13 */ +#define RG_SSUSB_PLL_VOD_EN (0x1<<12) /* 12:12 */ +#define RG_SSUSB_PLL_MONREF_EN (0x1<<11) /* 11:11 */ +#define RG_SSUSB_PLL_MONCK_EN (0x1<<10) /* 10:10 */ +#define RG_SSUSB_PLL_MONVC_EN (0x1<<9) /* 9:9 */ +#define RG_SSUSB_PLL_RLH_EN (0x1<<8) /* 8:8 */ +#define RG_SSUSB_PLL_AUTOK_KS (0x3<<6) /* 7:6 */ +#define RG_SSUSB_PLL_AUTOK_KF (0x3<<4) /* 5:4 */ +#define RG_SSUSB_PLL_RST_DLY (0x3<<2) /* 3:2 */ + +/* U3D_reg7 */ +#define RG_SSUSB_PLL_RESERVE (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_PLL_SSC_PRD (0xffff<<0) /* 15:0 */ + +/* U3D_reg8 */ +#define RG_SSUSB_PLL_SSC_PHASE_INI (0x1<<31) /* 31:31 */ +#define RG_SSUSB_PLL_SSC_TRI_EN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_PLL_CLK_PH_INV (0x1<<29) /* 29:29 */ +#define RG_SSUSB_PLL_DDS_LPF_EN (0x1<<28) /* 28:28 */ +#define RG_SSUSB_PLL_DDS_RST_SEL (0x1<<27) /* 27:27 */ +#define RG_SSUSB_PLL_DDS_VADJ (0x1<<26) /* 26:26 */ +#define RG_SSUSB_PLL_DDS_MONEN (0x1<<25) /* 25:25 */ +#define RG_SSUSB_PLL_DDS_SEL_EXT (0x1<<24) /* 24:24 */ +#define RG_SSUSB_PLL_DDS_PI_PL_EN (0x1<<23) /* 23:23 */ +#define RG_SSUSB_PLL_DDS_FRAC_MUTE (0x7<<20) /* 22:20 */ +#define RG_SSUSB_PLL_DDS_HF_EN (0x1<<19) /* 19:19 */ +#define RG_SSUSB_PLL_DDS_C (0x7<<16) /* 18:16 */ +#define RG_SSUSB_PLL_DDS_PREDIV2 (0x1<<15) /* 15:15 */ +#define RG_SSUSB_LFPS_LPF (0x3<<13) /* 14:13 */ + +/* U3D_reg9 */ +#define RG_SSUSB_CDR_PD_DIV_BYPASS (0x1<<31) /* 31:31 */ +#define RG_SSUSB_CDR_PD_DIV_SEL (0x1<<30) /* 30:30 */ +#define RG_SSUSB_CDR_CPBIAS_SEL (0x1<<29) /* 29:29 */ +#define RG_SSUSB_CDR_OSCDET_EN (0x1<<28) /* 28:28 */ +#define RG_SSUSB_CDR_MONMUX (0x1<<27) /* 27:27 */ +#define RG_SSUSB_CDR_RST_DLY (0x3<<25) /* 26:25 */ +#define RG_SSUSB_CDR_RSTB_MANUAL (0x1<<24) /* 24:24 */ +#define RG_SSUSB_CDR_BYPASS (0x3<<22) /* 23:22 */ +#define RG_SSUSB_CDR_PI_SLEW (0x3<<20) /* 21:20 */ +#define RG_SSUSB_CDR_EPEN (0x1<<19) /* 19:19 */ +#define RG_SSUSB_CDR_AUTOK_LOAD (0x1<<18) /* 18:18 */ +#define RG_SSUSB_CDR_MONEN (0x1<<16) /* 16:16 */ +#define RG_SSUSB_CDR_MONEN_DIG (0x1<<15) /* 15:15 */ +#define RG_SSUSB_CDR_REGOD (0x3<<13) /* 14:13 */ +#define RG_SSUSB_CDR_AUTOK_KS (0x3<<11) /* 12:11 */ +#define RG_SSUSB_CDR_AUTOK_KF (0x3<<9) /* 10:9 */ +#define RG_SSUSB_RX_DAC_EN (0x1<<8) /* 8:8 */ +#define RG_SSUSB_RX_DAC_PWD (0x1<<7) /* 7:7 */ +#define RG_SSUSB_EQ_CURSEL (0x1<<6) /* 6:6 */ +#define RG_SSUSB_RX_DAC_MUX (0x1f<<1) /* 5:1 */ +#define RG_SSUSB_RX_R2T_EN (0x1<<0) /* 0:0 */ + +/* U3D_regA */ +#define RG_SSUSB_RX_T2R_EN (0x1<<31) /* 31:31 */ +#define RG_SSUSB_RX_50_LOWER (0x7<<28) /* 30:28 */ +#define RG_SSUSB_RX_50_TAR (0x3<<26) /* 27:26 */ +#define RG_SSUSB_RX_SW_CTRL (0xf<<21) /* 24:21 */ +#define RG_PCIE_SIGDET_VTH (0x3<<19) /* 20:19 */ +#define RG_PCIE_SIGDET_LPF (0x3<<17) /* 18:17 */ +#define RG_SSUSB_LFPS_MON_EN (0x1<<16) /* 16:16 */ +#define RG_SSUSB_RXAFE_DCMON_SEL (0xf<<12) /* 15:12 */ +#define RG_SSUSB_RX_P1_ENTRY_PASS (0x1<<11) /* 11:11 */ +#define RG_SSUSB_RX_PD_RST (0x1<<10) /* 10:10 */ +#define RG_SSUSB_RX_PD_RST_PASS (0x1<<9) /* 9:9 */ + +/* U3D_regB */ +#define RG_SSUSB_CDR_RESERVE (0xff<<24) /* 31:24 */ +#define RG_SSUSB_RXAFE_RESERVE (0xff<<16) /* 23:16 */ +#define RG_PCIE_RX_RESERVE (0xff<<8) /* 15:8 */ +#define RG_SSUSB_VRT_25M_EN (0x1<<7) /* 7:7 */ +#define RG_SSUSB_RX_PD_PICAL_SWAP (0x1<<6) /* 6:6 */ +#define RG_SSUSB_RX_DAC_MEAS_EN (0x1<<5) /* 5:5 */ +#define RG_SSUSB_MPX_SEL_L0 (0x1<<4) /* 4:4 */ +#define RG_SSUSB_LFPS_SLCOUT_SEL (0x1<<3) /* 3:3 */ +#define RG_SSUSB_LFPS_CMPOUT_SEL (0x1<<2) /* 2:2 */ +#define RG_PCIE_SIGDET_HF (0x3<<0) /* 1:0 */ + +/* U3D_regC */ +#define RGS_SSUSB_RX_DEBUG_RESERVE (0xff<<0) /* 7:0 */ + +/* OFFSET */ + +/* U3D_reg0 */ +#define RG_SSUSB_BGR_EN_OFST (31) +#define RG_SSUSB_CHPEN_OFST (30) +#define RG_SSUSB_BG_DIV_OFST (28) +#define RG_SSUSB_INTR_EN_OFST (26) +#define RG_SSUSB_MPX_EN_OFST (24) +#define RG_SSUSB_MPX_SEL_OFST (16) +#define RG_SSUSB_REF_EN_OFST (15) +#define RG_SSUSB_VRT_VREF_SEL_OFST (11) +#define RG_SSUSB_BG_MONEN_OFST (8) +#define RG_SSUSB_INT_BIAS_SEL_OFST (7) +#define RG_SSUSB_EXT_BIAS_SEL_OFST (6) +#define RG_PCIE_CLKDRV_OFFSET_OFST (2) +#define RG_PCIE_CLKDRV_SLEW_OFST (0) + +/* U3D_reg1 */ +#define RG_PCIE_CLKDRV_AMP_OFST (29) +#define RG_SSUSB_XTAL_TST_A2DCK_EN_OFST (28) +#define RG_SSUSB_XTAL_MON_EN_OFST (27) +#define RG_SSUSB_XTAL_HYS_OFST (26) +#define RG_SSUSB_XTAL_TOP_RESERVE_OFST (10) +#define RG_SSUSB_SYSPLL_PREDIV_OFST (8) +#define RG_SSUSB_SYSPLL_POSDIV_OFST (6) +#define RG_SSUSB_SYSPLL_VCO_DIV_SEL_OFST (5) +#define RG_SSUSB_SYSPLL_VOD_EN_OFST (4) +#define RG_SSUSB_SYSPLL_RST_DLY_OFST (2) +#define RG_SSUSB_SYSPLL_BLP_OFST (1) +#define RG_SSUSB_SYSPLL_BP_OFST (0) + +/* U3D_reg2 */ +#define RG_SSUSB_SYSPLL_BR_OFST (31) +#define RG_SSUSB_SYSPLL_BC_OFST (30) +#define RG_SSUSB_SYSPLL_MONCK_EN_OFST (29) +#define RG_SSUSB_SYSPLL_MONVC_EN_OFST (28) +#define RG_SSUSB_SYSPLL_MONREF_EN_OFST (27) +#define RG_SSUSB_SYSPLL_SDM_IFM_OFST (26) +#define RG_SSUSB_SYSPLL_SDM_OUT_OFST (25) +#define RG_SSUSB_SYSPLL_BACK_EN_OFST (24) + +/* U3D_reg3 */ +#define RG_SSUSB_SYSPLL_FBDIV_OFST (1) +#define RG_SSUSB_SYSPLL_HR_EN_OFST (0) + +/* U3D_reg4 */ +#define RG_SSUSB_SYSPLL_SDM_DI_EN_OFST (31) +#define RG_SSUSB_SYSPLL_SDM_DI_LS_OFST (29) +#define RG_SSUSB_SYSPLL_SDM_ORD_OFST (27) +#define RG_SSUSB_SYSPLL_SDM_MODE_OFST (25) +#define RG_SSUSB_SYSPLL_RESERVE_OFST (17) +#define RG_SSUSB_SYSPLL_TOP_RESERVE_OFST (1) + +/* U3D_reg5 */ +#define RG_SSUSB_TX250MCK_INVB_OFST (31) +#define RG_SSUSB_IDRV_ITAILOP_EN_OFST (30) +#define RG_SSUSB_IDRV_CALIB_OFST (24) +#define RG_SSUSB_IDEM_BIAS_OFST (20) +#define RG_SSUSB_TX_R50_FON_OFST (19) +#define RG_SSUSB_TX_SR_OFST (16) +#define RG_SSUSB_RXDET_RSEL_OFST (14) +#define RG_SSUSB_RXDET_UPDN_FORCE_OFST (13) +#define RG_SSUSB_RXDET_UPDN_SEL_OFST (12) +#define RG_SSUSB_RXDET_VTHSEL_L_OFST (10) +#define RG_SSUSB_RXDET_VTHSEL_H_OFST (8) +#define RG_SSUSB_CKMON_EN_OFST (7) +#define RG_SSUSB_TX_VLMON_EN_OFST (6) +#define RG_SSUSB_TX_VLMON_SEL_OFST (4) +#define RG_SSUSB_CKMON_SEL_OFST (0) + +/* U3D_reg6 */ +#define RG_SSUSB_TX_EIDLE_CM_OFST (28) +#define RG_SSUSB_RXLBTX_EN_OFST (27) +#define RG_SSUSB_TXLBRX_EN_OFST (26) +#define RG_SSUSB_RESERVE6_OFST (22) +#define RG_SSUSB_RESERVE_OFST (16) +#define RG_SSUSB_PLL_POSDIV_OFST (14) +#define RG_SSUSB_PLL_AUTOK_LOAD_OFST (13) +#define RG_SSUSB_PLL_VOD_EN_OFST (12) +#define RG_SSUSB_PLL_MONREF_EN_OFST (11) +#define RG_SSUSB_PLL_MONCK_EN_OFST (10) +#define RG_SSUSB_PLL_MONVC_EN_OFST (9) +#define RG_SSUSB_PLL_RLH_EN_OFST (8) +#define RG_SSUSB_PLL_AUTOK_KS_OFST (6) +#define RG_SSUSB_PLL_AUTOK_KF_OFST (4) +#define RG_SSUSB_PLL_RST_DLY_OFST (2) + +/* U3D_reg7 */ +#define RG_SSUSB_PLL_RESERVE_OFST (16) +#define RG_SSUSB_PLL_SSC_PRD_OFST (0) + +/* U3D_reg8 */ +#define RG_SSUSB_PLL_SSC_PHASE_INI_OFST (31) +#define RG_SSUSB_PLL_SSC_TRI_EN_OFST (30) +#define RG_SSUSB_PLL_CLK_PH_INV_OFST (29) +#define RG_SSUSB_PLL_DDS_LPF_EN_OFST (28) +#define RG_SSUSB_PLL_DDS_RST_SEL_OFST (27) +#define RG_SSUSB_PLL_DDS_VADJ_OFST (26) +#define RG_SSUSB_PLL_DDS_MONEN_OFST (25) +#define RG_SSUSB_PLL_DDS_SEL_EXT_OFST (24) +#define RG_SSUSB_PLL_DDS_PI_PL_EN_OFST (23) +#define RG_SSUSB_PLL_DDS_FRAC_MUTE_OFST (20) +#define RG_SSUSB_PLL_DDS_HF_EN_OFST (19) +#define RG_SSUSB_PLL_DDS_C_OFST (16) +#define RG_SSUSB_PLL_DDS_PREDIV2_OFST (15) +#define RG_SSUSB_LFPS_LPF_OFST (13) + +/* U3D_reg9 */ +#define RG_SSUSB_CDR_PD_DIV_BYPASS_OFST (31) +#define RG_SSUSB_CDR_PD_DIV_SEL_OFST (30) +#define RG_SSUSB_CDR_CPBIAS_SEL_OFST (29) +#define RG_SSUSB_CDR_OSCDET_EN_OFST (28) +#define RG_SSUSB_CDR_MONMUX_OFST (27) +#define RG_SSUSB_CDR_RST_DLY_OFST (25) +#define RG_SSUSB_CDR_RSTB_MANUAL_OFST (24) +#define RG_SSUSB_CDR_BYPASS_OFST (22) +#define RG_SSUSB_CDR_PI_SLEW_OFST (20) +#define RG_SSUSB_CDR_EPEN_OFST (19) +#define RG_SSUSB_CDR_AUTOK_LOAD_OFST (18) +#define RG_SSUSB_CDR_MONEN_OFST (16) +#define RG_SSUSB_CDR_MONEN_DIG_OFST (15) +#define RG_SSUSB_CDR_REGOD_OFST (13) +#define RG_SSUSB_CDR_AUTOK_KS_OFST (11) +#define RG_SSUSB_CDR_AUTOK_KF_OFST (9) +#define RG_SSUSB_RX_DAC_EN_OFST (8) +#define RG_SSUSB_RX_DAC_PWD_OFST (7) +#define RG_SSUSB_EQ_CURSEL_OFST (6) +#define RG_SSUSB_RX_DAC_MUX_OFST (1) +#define RG_SSUSB_RX_R2T_EN_OFST (0) + +/* U3D_regA */ +#define RG_SSUSB_RX_T2R_EN_OFST (31) +#define RG_SSUSB_RX_50_LOWER_OFST (28) +#define RG_SSUSB_RX_50_TAR_OFST (26) +#define RG_SSUSB_RX_SW_CTRL_OFST (21) +#define RG_PCIE_SIGDET_VTH_OFST (19) +#define RG_PCIE_SIGDET_LPF_OFST (17) +#define RG_SSUSB_LFPS_MON_EN_OFST (16) +#define RG_SSUSB_RXAFE_DCMON_SEL_OFST (12) +#define RG_SSUSB_RX_P1_ENTRY_PASS_OFST (11) +#define RG_SSUSB_RX_PD_RST_OFST (10) +#define RG_SSUSB_RX_PD_RST_PASS_OFST (9) + +/* U3D_regB */ +#define RG_SSUSB_CDR_RESERVE_OFST (24) +#define RG_SSUSB_RXAFE_RESERVE_OFST (16) +#define RG_PCIE_RX_RESERVE_OFST (8) +#define RG_SSUSB_VRT_25M_EN_OFST (7) +#define RG_SSUSB_RX_PD_PICAL_SWAP_OFST (6) +#define RG_SSUSB_RX_DAC_MEAS_EN_OFST (5) +#define RG_SSUSB_MPX_SEL_L0_OFST (4) +#define RG_SSUSB_LFPS_SLCOUT_SEL_OFST (3) +#define RG_SSUSB_LFPS_CMPOUT_SEL_OFST (2) +#define RG_PCIE_SIGDET_HF_OFST (0) + +/* U3D_regC */ +#define RGS_SSUSB_RX_DEBUG_RESERVE_OFST (0) + +/* ///////////////////////////////////////////////////////////////////////////// */ + +struct u3phya_da_reg_e { + /* 0x0 */ + PHY_LE32 reg0; + PHY_LE32 reg1; + PHY_LE32 reg4; + PHY_LE32 reg5; + /* 0x10 */ + PHY_LE32 reg6; + PHY_LE32 reg7; + PHY_LE32 reg8; + PHY_LE32 reg9; + /* 0x20 */ + PHY_LE32 reg10; + PHY_LE32 reg12; + PHY_LE32 reg13; + PHY_LE32 reg14; + /* 0x30 */ + PHY_LE32 reg15; + PHY_LE32 reg16; + PHY_LE32 reg19; + PHY_LE32 reg20; + /* 0x40 */ + PHY_LE32 reg21; + PHY_LE32 reg23; + PHY_LE32 reg25; + PHY_LE32 reg26; + /* 0x50 */ + PHY_LE32 reg28; + PHY_LE32 reg29; + PHY_LE32 reg30; + PHY_LE32 reg31; + /* 0x60 */ + PHY_LE32 reg32; + PHY_LE32 reg33; +}; + +/* U3D_reg0 */ +#define RG_PCIE_SPEED_PE2D (0x1<<24) /* 24:24 */ +#define RG_PCIE_SPEED_PE2H (0x1<<23) /* 23:23 */ +#define RG_PCIE_SPEED_PE1D (0x1<<22) /* 22:22 */ +#define RG_PCIE_SPEED_PE1H (0x1<<21) /* 21:21 */ +#define RG_PCIE_SPEED_U3 (0x1<<20) /* 20:20 */ +#define RG_SSUSB_XTAL_EXT_EN_PE2D (0x3<<18) /* 19:18 */ +#define RG_SSUSB_XTAL_EXT_EN_PE2H (0x3<<16) /* 17:16 */ +#define RG_SSUSB_XTAL_EXT_EN_PE1D (0x3<<14) /* 15:14 */ +#define RG_SSUSB_XTAL_EXT_EN_PE1H (0x3<<12) /* 13:12 */ +#define RG_SSUSB_XTAL_EXT_EN_U3 (0x3<<10) /* 11:10 */ +#define RG_SSUSB_CDR_REFCK_SEL_PE2D (0x3<<8) /* 9:8 */ +#define RG_SSUSB_CDR_REFCK_SEL_PE2H (0x3<<6) /* 7:6 */ +#define RG_SSUSB_CDR_REFCK_SEL_PE1D (0x3<<4) /* 5:4 */ +#define RG_SSUSB_CDR_REFCK_SEL_PE1H (0x3<<2) /* 3:2 */ +#define RG_SSUSB_CDR_REFCK_SEL_U3 (0x3<<0) /* 1:0 */ + +/* U3D_reg1 */ +#define RG_USB20_REFCK_SEL_PE2D (0x1<<30) /* 30:30 */ +#define RG_USB20_REFCK_SEL_PE2H (0x1<<29) /* 29:29 */ +#define RG_USB20_REFCK_SEL_PE1D (0x1<<28) /* 28:28 */ +#define RG_USB20_REFCK_SEL_PE1H (0x1<<27) /* 27:27 */ +#define RG_USB20_REFCK_SEL_U3 (0x1<<26) /* 26:26 */ +#define RG_PCIE_REFCK_DIV4_PE2D (0x1<<25) /* 25:25 */ +#define RG_PCIE_REFCK_DIV4_PE2H (0x1<<24) /* 24:24 */ +#define RG_PCIE_REFCK_DIV4_PE1D (0x1<<18) /* 18:18 */ +#define RG_PCIE_REFCK_DIV4_PE1H (0x1<<17) /* 17:17 */ +#define RG_PCIE_REFCK_DIV4_U3 (0x1<<16) /* 16:16 */ +#define RG_PCIE_MODE_PE2D (0x1<<8) /* 8:8 */ +#define RG_PCIE_MODE_PE2H (0x1<<3) /* 3:3 */ +#define RG_PCIE_MODE_PE1D (0x1<<2) /* 2:2 */ +#define RG_PCIE_MODE_PE1H (0x1<<1) /* 1:1 */ +#define RG_PCIE_MODE_U3 (0x1<<0) /* 0:0 */ + +/* U3D_reg4 */ +#define RG_SSUSB_PLL_DIVEN_PE2D (0x7<<22) /* 24:22 */ +#define RG_SSUSB_PLL_DIVEN_PE2H (0x7<<19) /* 21:19 */ +#define RG_SSUSB_PLL_DIVEN_PE1D (0x7<<16) /* 18:16 */ +#define RG_SSUSB_PLL_DIVEN_PE1H (0x7<<13) /* 15:13 */ +#define RG_SSUSB_PLL_DIVEN_U3 (0x7<<10) /* 12:10 */ +#define RG_SSUSB_PLL_BC_PE2D (0x3<<8) /* 9:8 */ +#define RG_SSUSB_PLL_BC_PE2H (0x3<<6) /* 7:6 */ +#define RG_SSUSB_PLL_BC_PE1D (0x3<<4) /* 5:4 */ +#define RG_SSUSB_PLL_BC_PE1H (0x3<<2) /* 3:2 */ +#define RG_SSUSB_PLL_BC_U3 (0x3<<0) /* 1:0 */ + +/* U3D_reg5 */ +#define RG_SSUSB_PLL_BR_PE2D (0x3<<30) /* 31:30 */ +#define RG_SSUSB_PLL_BR_PE2H (0x3<<28) /* 29:28 */ +#define RG_SSUSB_PLL_BR_PE1D (0x3<<26) /* 27:26 */ +#define RG_SSUSB_PLL_BR_PE1H (0x3<<24) /* 25:24 */ +#define RG_SSUSB_PLL_BR_U3 (0x3<<22) /* 23:22 */ +#define RG_SSUSB_PLL_IC_PE2D (0xf<<16) /* 19:16 */ +#define RG_SSUSB_PLL_IC_PE2H (0xf<<12) /* 15:12 */ +#define RG_SSUSB_PLL_IC_PE1D (0xf<<8) /* 11:8 */ +#define RG_SSUSB_PLL_IC_PE1H (0xf<<4) /* 7:4 */ +#define RG_SSUSB_PLL_IC_U3 (0xf<<0) /* 3:0 */ + +/* U3D_reg6 */ +#define RG_SSUSB_PLL_IR_PE2D (0xf<<24) /* 27:24 */ +#define RG_SSUSB_PLL_IR_PE2H (0xf<<16) /* 19:16 */ +#define RG_SSUSB_PLL_IR_PE1D (0xf<<8) /* 11:8 */ +#define RG_SSUSB_PLL_IR_PE1H (0xf<<4) /* 7:4 */ +#define RG_SSUSB_PLL_IR_U3 (0xf<<0) /* 3:0 */ + +/* U3D_reg7 */ +#define RG_SSUSB_PLL_BP_PE2D (0xf<<24) /* 27:24 */ +#define RG_SSUSB_PLL_BP_PE2H (0xf<<16) /* 19:16 */ +#define RG_SSUSB_PLL_BP_PE1D (0xf<<8) /* 11:8 */ +#define RG_SSUSB_PLL_BP_PE1H (0xf<<4) /* 7:4 */ +#define RG_SSUSB_PLL_BP_U3 (0xf<<0) /* 3:0 */ + +/* U3D_reg8 */ +#define RG_SSUSB_PLL_FBKSEL_PE2D (0x3<<24) /* 25:24 */ +#define RG_SSUSB_PLL_FBKSEL_PE2H (0x3<<16) /* 17:16 */ +#define RG_SSUSB_PLL_FBKSEL_PE1D (0x3<<8) /* 9:8 */ +#define RG_SSUSB_PLL_FBKSEL_PE1H (0x3<<2) /* 3:2 */ +#define RG_SSUSB_PLL_FBKSEL_U3 (0x3<<0) /* 1:0 */ + +/* U3D_reg9 */ +#define RG_SSUSB_PLL_FBKDIV_PE2H (0x7f<<24) /* 30:24 */ +#define RG_SSUSB_PLL_FBKDIV_PE1D (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_PLL_FBKDIV_PE1H (0x7f<<8) /* 14:8 */ +#define RG_SSUSB_PLL_FBKDIV_U3 (0x7f<<0) /* 6:0 */ + +/* U3D_reg10 */ +#define RG_SSUSB_PLL_PREDIV_PE2D (0x3<<26) /* 27:26 */ +#define RG_SSUSB_PLL_PREDIV_PE2H (0x3<<24) /* 25:24 */ +#define RG_SSUSB_PLL_PREDIV_PE1D (0x3<<18) /* 19:18 */ +#define RG_SSUSB_PLL_PREDIV_PE1H (0x3<<16) /* 17:16 */ +#define RG_SSUSB_PLL_PREDIV_U3 (0x3<<8) /* 9:8 */ +#define RG_SSUSB_PLL_FBKDIV_PE2D (0x7f<<0) /* 6:0 */ + +/* U3D_reg12 */ +#define RG_SSUSB_PLL_PCW_NCPO_U3 (0x7fffffff<<0) /* 30:0 */ + +/* U3D_reg13 */ +#define RG_SSUSB_PLL_PCW_NCPO_PE1H (0x7fffffff<<0) /* 30:0 */ + +/* U3D_reg14 */ +#define RG_SSUSB_PLL_PCW_NCPO_PE1D (0x7fffffff<<0) /* 30:0 */ + +/* U3D_reg15 */ +#define RG_SSUSB_PLL_PCW_NCPO_PE2H (0x7fffffff<<0) /* 30:0 */ + +/* U3D_reg16 */ +#define RG_SSUSB_PLL_PCW_NCPO_PE2D (0x7fffffff<<0) /* 30:0 */ + +/* U3D_reg19 */ +#define RG_SSUSB_PLL_SSC_DELTA1_PE1H (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_PLL_SSC_DELTA1_U3 (0xffff<<0) /* 15:0 */ + +/* U3D_reg20 */ +#define RG_SSUSB_PLL_SSC_DELTA1_PE2H (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_PLL_SSC_DELTA1_PE1D (0xffff<<0) /* 15:0 */ + +/* U3D_reg21 */ +#define RG_SSUSB_PLL_SSC_DELTA_U3 (0xffffU<<16) /* 31:16 */ +#define RG_SSUSB_PLL_SSC_DELTA1_PE2D (0xffff<<0) /* 15:0 */ + +/* U3D_reg23 */ +#define RG_SSUSB_PLL_SSC_DELTA_PE1D (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_PLL_SSC_DELTA_PE1H (0xffff<<0) /* 15:0 */ + +/* U3D_reg25 */ +#define RG_SSUSB_PLL_SSC_DELTA_PE2D (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_PLL_SSC_DELTA_PE2H (0xffff<<0) /* 15:0 */ + +/* U3D_reg26 */ +#define RG_SSUSB_PLL_REFCKDIV_PE2D (0x1<<25) /* 25:25 */ +#define RG_SSUSB_PLL_REFCKDIV_PE2H (0x1<<24) /* 24:24 */ +#define RG_SSUSB_PLL_REFCKDIV_PE1D (0x1<<16) /* 16:16 */ +#define RG_SSUSB_PLL_REFCKDIV_PE1H (0x1<<8) /* 8:8 */ +#define RG_SSUSB_PLL_REFCKDIV_U3 (0x1<<0) /* 0:0 */ + +/* U3D_reg28 */ +#define RG_SSUSB_CDR_BPA_PE2D (0x3<<24) /* 25:24 */ +#define RG_SSUSB_CDR_BPA_PE2H (0x3<<16) /* 17:16 */ +#define RG_SSUSB_CDR_BPA_PE1D (0x3<<10) /* 11:10 */ +#define RG_SSUSB_CDR_BPA_PE1H (0x3<<8) /* 9:8 */ +#define RG_SSUSB_CDR_BPA_U3 (0x3<<0) /* 1:0 */ + +/* U3D_reg29 */ +#define RG_SSUSB_CDR_BPB_PE2D (0x7<<24) /* 26:24 */ +#define RG_SSUSB_CDR_BPB_PE2H (0x7<<16) /* 18:16 */ +#define RG_SSUSB_CDR_BPB_PE1D (0x7<<6) /* 8:6 */ +#define RG_SSUSB_CDR_BPB_PE1H (0x7<<3) /* 5:3 */ +#define RG_SSUSB_CDR_BPB_U3 (0x7<<0) /* 2:0 */ + +/* U3D_reg30 */ +#define RG_SSUSB_CDR_BR_PE2D (0x7<<24) /* 26:24 */ +#define RG_SSUSB_CDR_BR_PE2H (0x7<<16) /* 18:16 */ +#define RG_SSUSB_CDR_BR_PE1D (0x7<<6) /* 8:6 */ +#define RG_SSUSB_CDR_BR_PE1H (0x7<<3) /* 5:3 */ +#define RG_SSUSB_CDR_BR_U3 (0x7<<0) /* 2:0 */ + +/* U3D_reg31 */ +#define RG_SSUSB_CDR_FBDIV_PE2H (0x7f<<24) /* 30:24 */ +#define RG_SSUSB_CDR_FBDIV_PE1D (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_CDR_FBDIV_PE1H (0x7f<<8) /* 14:8 */ +#define RG_SSUSB_CDR_FBDIV_U3 (0x7f<<0) /* 6:0 */ + +/* U3D_reg32 */ +#define RG_SSUSB_EQ_RSTEP1_PE2D (0x3<<30) /* 31:30 */ +#define RG_SSUSB_EQ_RSTEP1_PE2H (0x3<<28) /* 29:28 */ +#define RG_SSUSB_EQ_RSTEP1_PE1D (0x3<<26) /* 27:26 */ +#define RG_SSUSB_EQ_RSTEP1_PE1H (0x3<<24) /* 25:24 */ +#define RG_SSUSB_EQ_RSTEP1_U3 (0x3<<22) /* 23:22 */ +#define RG_SSUSB_LFPS_DEGLITCH_PE2D (0x3<<20) /* 21:20 */ +#define RG_SSUSB_LFPS_DEGLITCH_PE2H (0x3<<18) /* 19:18 */ +#define RG_SSUSB_LFPS_DEGLITCH_PE1D (0x3<<16) /* 17:16 */ +#define RG_SSUSB_LFPS_DEGLITCH_PE1H (0x3<<14) /* 15:14 */ +#define RG_SSUSB_LFPS_DEGLITCH_U3 (0x3<<12) /* 13:12 */ +#define RG_SSUSB_CDR_KVSEL_PE2D (0x1<<11) /* 11:11 */ +#define RG_SSUSB_CDR_KVSEL_PE2H (0x1<<10) /* 10:10 */ +#define RG_SSUSB_CDR_KVSEL_PE1D (0x1<<9) /* 9:9 */ +#define RG_SSUSB_CDR_KVSEL_PE1H (0x1<<8) /* 8:8 */ +#define RG_SSUSB_CDR_KVSEL_U3 (0x1<<7) /* 7:7 */ +#define RG_SSUSB_CDR_FBDIV_PE2D (0x7f<<0) /* 6:0 */ + +/* U3D_reg33 */ +#define RG_SSUSB_RX_CMPWD_PE2D (0x1<<26) /* 26:26 */ +#define RG_SSUSB_RX_CMPWD_PE2H (0x1<<25) /* 25:25 */ +#define RG_SSUSB_RX_CMPWD_PE1D (0x1<<24) /* 24:24 */ +#define RG_SSUSB_RX_CMPWD_PE1H (0x1<<23) /* 23:23 */ +#define RG_SSUSB_RX_CMPWD_U3 (0x1<<16) /* 16:16 */ +#define RG_SSUSB_EQ_RSTEP2_PE2D (0x3<<8) /* 9:8 */ +#define RG_SSUSB_EQ_RSTEP2_PE2H (0x3<<6) /* 7:6 */ +#define RG_SSUSB_EQ_RSTEP2_PE1D (0x3<<4) /* 5:4 */ +#define RG_SSUSB_EQ_RSTEP2_PE1H (0x3<<2) /* 3:2 */ +#define RG_SSUSB_EQ_RSTEP2_U3 (0x3<<0) /* 1:0 */ + +/* OFFSET DEFINITION */ + +/* U3D_reg0 */ +#define RG_PCIE_SPEED_PE2D_OFST (24) +#define RG_PCIE_SPEED_PE2H_OFST (23) +#define RG_PCIE_SPEED_PE1D_OFST (22) +#define RG_PCIE_SPEED_PE1H_OFST (21) +#define RG_PCIE_SPEED_U3_OFST (20) +#define RG_SSUSB_XTAL_EXT_EN_PE2D_OFST (18) +#define RG_SSUSB_XTAL_EXT_EN_PE2H_OFST (16) +#define RG_SSUSB_XTAL_EXT_EN_PE1D_OFST (14) +#define RG_SSUSB_XTAL_EXT_EN_PE1H_OFST (12) +#define RG_SSUSB_XTAL_EXT_EN_U3_OFST (10) +#define RG_SSUSB_CDR_REFCK_SEL_PE2D_OFST (8) +#define RG_SSUSB_CDR_REFCK_SEL_PE2H_OFST (6) +#define RG_SSUSB_CDR_REFCK_SEL_PE1D_OFST (4) +#define RG_SSUSB_CDR_REFCK_SEL_PE1H_OFST (2) +#define RG_SSUSB_CDR_REFCK_SEL_U3_OFST (0) + +/* U3D_reg1 */ +#define RG_USB20_REFCK_SEL_PE2D_OFST (30) +#define RG_USB20_REFCK_SEL_PE2H_OFST (29) +#define RG_USB20_REFCK_SEL_PE1D_OFST (28) +#define RG_USB20_REFCK_SEL_PE1H_OFST (27) +#define RG_USB20_REFCK_SEL_U3_OFST (26) +#define RG_PCIE_REFCK_DIV4_PE2D_OFST (25) +#define RG_PCIE_REFCK_DIV4_PE2H_OFST (24) +#define RG_PCIE_REFCK_DIV4_PE1D_OFST (18) +#define RG_PCIE_REFCK_DIV4_PE1H_OFST (17) +#define RG_PCIE_REFCK_DIV4_U3_OFST (16) +#define RG_PCIE_MODE_PE2D_OFST (8) +#define RG_PCIE_MODE_PE2H_OFST (3) +#define RG_PCIE_MODE_PE1D_OFST (2) +#define RG_PCIE_MODE_PE1H_OFST (1) +#define RG_PCIE_MODE_U3_OFST (0) + +/* U3D_reg4 */ +#define RG_SSUSB_PLL_DIVEN_PE2D_OFST (22) +#define RG_SSUSB_PLL_DIVEN_PE2H_OFST (19) +#define RG_SSUSB_PLL_DIVEN_PE1D_OFST (16) +#define RG_SSUSB_PLL_DIVEN_PE1H_OFST (13) +#define RG_SSUSB_PLL_DIVEN_U3_OFST (10) +#define RG_SSUSB_PLL_BC_PE2D_OFST (8) +#define RG_SSUSB_PLL_BC_PE2H_OFST (6) +#define RG_SSUSB_PLL_BC_PE1D_OFST (4) +#define RG_SSUSB_PLL_BC_PE1H_OFST (2) +#define RG_SSUSB_PLL_BC_U3_OFST (0) + +/* U3D_reg5 */ +#define RG_SSUSB_PLL_BR_PE2D_OFST (30) +#define RG_SSUSB_PLL_BR_PE2H_OFST (28) +#define RG_SSUSB_PLL_BR_PE1D_OFST (26) +#define RG_SSUSB_PLL_BR_PE1H_OFST (24) +#define RG_SSUSB_PLL_BR_U3_OFST (22) +#define RG_SSUSB_PLL_IC_PE2D_OFST (16) +#define RG_SSUSB_PLL_IC_PE2H_OFST (12) +#define RG_SSUSB_PLL_IC_PE1D_OFST (8) +#define RG_SSUSB_PLL_IC_PE1H_OFST (4) +#define RG_SSUSB_PLL_IC_U3_OFST (0) + +/* U3D_reg6 */ +#define RG_SSUSB_PLL_IR_PE2D_OFST (24) +#define RG_SSUSB_PLL_IR_PE2H_OFST (16) +#define RG_SSUSB_PLL_IR_PE1D_OFST (8) +#define RG_SSUSB_PLL_IR_PE1H_OFST (4) +#define RG_SSUSB_PLL_IR_U3_OFST (0) + +/* U3D_reg7 */ +#define RG_SSUSB_PLL_BP_PE2D_OFST (24) +#define RG_SSUSB_PLL_BP_PE2H_OFST (16) +#define RG_SSUSB_PLL_BP_PE1D_OFST (8) +#define RG_SSUSB_PLL_BP_PE1H_OFST (4) +#define RG_SSUSB_PLL_BP_U3_OFST (0) + +/* U3D_reg8 */ +#define RG_SSUSB_PLL_FBKSEL_PE2D_OFST (24) +#define RG_SSUSB_PLL_FBKSEL_PE2H_OFST (16) +#define RG_SSUSB_PLL_FBKSEL_PE1D_OFST (8) +#define RG_SSUSB_PLL_FBKSEL_PE1H_OFST (2) +#define RG_SSUSB_PLL_FBKSEL_U3_OFST (0) + +/* U3D_reg9 */ +#define RG_SSUSB_PLL_FBKDIV_PE2H_OFST (24) +#define RG_SSUSB_PLL_FBKDIV_PE1D_OFST (16) +#define RG_SSUSB_PLL_FBKDIV_PE1H_OFST (8) +#define RG_SSUSB_PLL_FBKDIV_U3_OFST (0) + +/* U3D_reg10 */ +#define RG_SSUSB_PLL_PREDIV_PE2D_OFST (26) +#define RG_SSUSB_PLL_PREDIV_PE2H_OFST (24) +#define RG_SSUSB_PLL_PREDIV_PE1D_OFST (18) +#define RG_SSUSB_PLL_PREDIV_PE1H_OFST (16) +#define RG_SSUSB_PLL_PREDIV_U3_OFST (8) +#define RG_SSUSB_PLL_FBKDIV_PE2D_OFST (0) + +/* U3D_reg12 */ +#define RG_SSUSB_PLL_PCW_NCPO_U3_OFST (0) + +/* U3D_reg13 */ +#define RG_SSUSB_PLL_PCW_NCPO_PE1H_OFST (0) + +/* U3D_reg14 */ +#define RG_SSUSB_PLL_PCW_NCPO_PE1D_OFST (0) + +/* U3D_reg15 */ +#define RG_SSUSB_PLL_PCW_NCPO_PE2H_OFST (0) + +/* U3D_reg16 */ +#define RG_SSUSB_PLL_PCW_NCPO_PE2D_OFST (0) + +/* U3D_reg19 */ +#define RG_SSUSB_PLL_SSC_DELTA1_PE1H_OFST (16) +#define RG_SSUSB_PLL_SSC_DELTA1_U3_OFST (0) + +/* U3D_reg20 */ +#define RG_SSUSB_PLL_SSC_DELTA1_PE2H_OFST (16) +#define RG_SSUSB_PLL_SSC_DELTA1_PE1D_OFST (0) + +/* U3D_reg21 */ +#define RG_SSUSB_PLL_SSC_DELTA_U3_OFST (16) +#define RG_SSUSB_PLL_SSC_DELTA1_PE2D_OFST (0) + +/* U3D_reg23 */ +#define RG_SSUSB_PLL_SSC_DELTA_PE1D_OFST (16) +#define RG_SSUSB_PLL_SSC_DELTA_PE1H_OFST (0) + +/* U3D_reg25 */ +#define RG_SSUSB_PLL_SSC_DELTA_PE2D_OFST (16) +#define RG_SSUSB_PLL_SSC_DELTA_PE2H_OFST (0) + +/* U3D_reg26 */ +#define RG_SSUSB_PLL_REFCKDIV_PE2D_OFST (25) +#define RG_SSUSB_PLL_REFCKDIV_PE2H_OFST (24) +#define RG_SSUSB_PLL_REFCKDIV_PE1D_OFST (16) +#define RG_SSUSB_PLL_REFCKDIV_PE1H_OFST (8) +#define RG_SSUSB_PLL_REFCKDIV_U3_OFST (0) + +/* U3D_reg28 */ +#define RG_SSUSB_CDR_BPA_PE2D_OFST (24) +#define RG_SSUSB_CDR_BPA_PE2H_OFST (16) +#define RG_SSUSB_CDR_BPA_PE1D_OFST (10) +#define RG_SSUSB_CDR_BPA_PE1H_OFST (8) +#define RG_SSUSB_CDR_BPA_U3_OFST (0) + +/* U3D_reg29 */ +#define RG_SSUSB_CDR_BPB_PE2D_OFST (24) +#define RG_SSUSB_CDR_BPB_PE2H_OFST (16) +#define RG_SSUSB_CDR_BPB_PE1D_OFST (6) +#define RG_SSUSB_CDR_BPB_PE1H_OFST (3) +#define RG_SSUSB_CDR_BPB_U3_OFST (0) + +/* U3D_reg30 */ +#define RG_SSUSB_CDR_BR_PE2D_OFST (24) +#define RG_SSUSB_CDR_BR_PE2H_OFST (16) +#define RG_SSUSB_CDR_BR_PE1D_OFST (6) +#define RG_SSUSB_CDR_BR_PE1H_OFST (3) +#define RG_SSUSB_CDR_BR_U3_OFST (0) + +/* U3D_reg31 */ +#define RG_SSUSB_CDR_FBDIV_PE2H_OFST (24) +#define RG_SSUSB_CDR_FBDIV_PE1D_OFST (16) +#define RG_SSUSB_CDR_FBDIV_PE1H_OFST (8) +#define RG_SSUSB_CDR_FBDIV_U3_OFST (0) + +/* U3D_reg32 */ +#define RG_SSUSB_EQ_RSTEP1_PE2D_OFST (30) +#define RG_SSUSB_EQ_RSTEP1_PE2H_OFST (28) +#define RG_SSUSB_EQ_RSTEP1_PE1D_OFST (26) +#define RG_SSUSB_EQ_RSTEP1_PE1H_OFST (24) +#define RG_SSUSB_EQ_RSTEP1_U3_OFST (22) +#define RG_SSUSB_LFPS_DEGLITCH_PE2D_OFST (20) +#define RG_SSUSB_LFPS_DEGLITCH_PE2H_OFST (18) +#define RG_SSUSB_LFPS_DEGLITCH_PE1D_OFST (16) +#define RG_SSUSB_LFPS_DEGLITCH_PE1H_OFST (14) +#define RG_SSUSB_LFPS_DEGLITCH_U3_OFST (12) +#define RG_SSUSB_CDR_KVSEL_PE2D_OFST (11) +#define RG_SSUSB_CDR_KVSEL_PE2H_OFST (10) +#define RG_SSUSB_CDR_KVSEL_PE1D_OFST (9) +#define RG_SSUSB_CDR_KVSEL_PE1H_OFST (8) +#define RG_SSUSB_CDR_KVSEL_U3_OFST (7) +#define RG_SSUSB_CDR_FBDIV_PE2D_OFST (0) + +/* U3D_reg33 */ +#define RG_SSUSB_RX_CMPWD_PE2D_OFST (26) +#define RG_SSUSB_RX_CMPWD_PE2H_OFST (25) +#define RG_SSUSB_RX_CMPWD_PE1D_OFST (24) +#define RG_SSUSB_RX_CMPWD_PE1H_OFST (23) +#define RG_SSUSB_RX_CMPWD_U3_OFST (16) +#define RG_SSUSB_EQ_RSTEP2_PE2D_OFST (8) +#define RG_SSUSB_EQ_RSTEP2_PE2H_OFST (6) +#define RG_SSUSB_EQ_RSTEP2_PE1D_OFST (4) +#define RG_SSUSB_EQ_RSTEP2_PE1H_OFST (2) +#define RG_SSUSB_EQ_RSTEP2_U3_OFST (0) + +/* ///////////////////////////////////////////////////////////////////////////// */ + +struct u3phyd_reg_e { + /* 0x0 */ + PHY_LE32 phyd_mix0; + PHY_LE32 phyd_mix1; + PHY_LE32 phyd_lfps0; + PHY_LE32 phyd_lfps1; + /* 0x10 */ + PHY_LE32 phyd_impcal0; + PHY_LE32 phyd_impcal1; + PHY_LE32 phyd_txpll0; + PHY_LE32 phyd_txpll1; + /* 0x20 */ + PHY_LE32 phyd_txpll2; + PHY_LE32 phyd_fl0; + PHY_LE32 phyd_mix2; + PHY_LE32 phyd_rx0; + /* 0x30 */ + PHY_LE32 phyd_t2rlb; + PHY_LE32 phyd_cppat; + PHY_LE32 phyd_mix3; + PHY_LE32 phyd_ebufctl; + /* 0x40 */ + PHY_LE32 phyd_pipe0; + PHY_LE32 phyd_pipe1; + PHY_LE32 phyd_mix4; + PHY_LE32 phyd_ckgen0; + /* 0x50 */ + PHY_LE32 phyd_mix5; + PHY_LE32 phyd_reserved; + PHY_LE32 phyd_cdr0; + PHY_LE32 phyd_cdr1; + /* 0x60 */ + PHY_LE32 phyd_pll_0; + PHY_LE32 phyd_pll_1; + PHY_LE32 phyd_bcn_det_1; + PHY_LE32 phyd_bcn_det_2; + /* 0x70 */ + PHY_LE32 eq0; + PHY_LE32 eq1; + PHY_LE32 eq2; + PHY_LE32 eq3; + /* 0x80 */ + PHY_LE32 eq_eye0; + PHY_LE32 eq_eye1; + PHY_LE32 eq_eye2; + PHY_LE32 eq_dfe0; + /* 0x90 */ + PHY_LE32 eq_dfe1; + PHY_LE32 eq_dfe2; + PHY_LE32 eq_dfe3; + PHY_LE32 reserve0; + /* 0xa0 */ + PHY_LE32 phyd_mon0; + PHY_LE32 phyd_mon1; + PHY_LE32 phyd_mon2; + PHY_LE32 phyd_mon3; + /* 0xb0 */ + PHY_LE32 phyd_mon4; + PHY_LE32 phyd_mon5; + PHY_LE32 phyd_mon6; + PHY_LE32 phyd_mon7; + /* 0xc0 */ + PHY_LE32 phya_rx_mon0; + PHY_LE32 phya_rx_mon1; + PHY_LE32 phya_rx_mon2; + PHY_LE32 phya_rx_mon3; + /* 0xd0 */ + PHY_LE32 phya_rx_mon4; + PHY_LE32 phya_rx_mon5; + PHY_LE32 phyd_cppat2; + PHY_LE32 eq_eye3; + /* 0xe0 */ + PHY_LE32 kband_out; + PHY_LE32 kband_out1; +}; + +/* U3D_PHYD_MIX0 */ +#define RG_SSUSB_P_P3_TX_NG (0x1<<31) /* 31:31 */ +#define RG_SSUSB_TSEQ_EN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_TSEQ_POLEN (0x1<<29) /* 29:29 */ +#define RG_SSUSB_TSEQ_POL (0x1<<28) /* 28:28 */ +#define RG_SSUSB_P_P3_PCLK_NG (0x1<<27) /* 27:27 */ +#define RG_SSUSB_TSEQ_TH (0x7<<24) /* 26:24 */ +#define RG_SSUSB_PRBS_BERTH (0xff<<16) /* 23:16 */ +#define RG_SSUSB_DISABLE_PHY_U2_ON (0x1<<15) /* 15:15 */ +#define RG_SSUSB_DISABLE_PHY_U2_OFF (0x1<<14) /* 14:14 */ +#define RG_SSUSB_PRBS_EN (0x1<<13) /* 13:13 */ +#define RG_SSUSB_BPSLOCK (0x1<<12) /* 12:12 */ +#define RG_SSUSB_RTCOMCNT (0xf<<8) /* 11:8 */ +#define RG_SSUSB_COMCNT (0xf<<4) /* 7:4 */ +#define RG_SSUSB_PRBSEL_CALIB (0xf<<0) /* 3:0 */ + +/* U3D_PHYD_MIX1 */ +#define RG_SSUSB_SLEEP_EN (0x1<<31) /* 31:31 */ +#define RG_SSUSB_PRBSEL_PCS (0x7<<28) /* 30:28 */ +#define RG_SSUSB_TXLFPS_PRD (0xf<<24) /* 27:24 */ +#define RG_SSUSB_P_RX_P0S_CK (0x1<<23) /* 23:23 */ +#define RG_SSUSB_P_TX_P0S_CK (0x1<<22) /* 22:22 */ +#define RG_SSUSB_PDNCTL (0x3f<<16) /* 21:16 */ +#define RG_SSUSB_TX_DRV_EN (0x1<<15) /* 15:15 */ +#define RG_SSUSB_TX_DRV_SEL (0x1<<14) /* 14:14 */ +#define RG_SSUSB_TX_DRV_DLY (0x3f<<8) /* 13:8 */ +#define RG_SSUSB_BERT_EN (0x1<<7) /* 7:7 */ +#define RG_SSUSB_SCP_TH (0x7<<4) /* 6:4 */ +#define RG_SSUSB_SCP_EN (0x1<<3) /* 3:3 */ +#define RG_SSUSB_RXANSIDEC_TEST (0x7<<0) /* 2:0 */ + +/* U3D_PHYD_LFPS0 */ +#define RG_SSUSB_LFPS_PWD (0x1<<30) /* 30:30 */ +#define RG_SSUSB_FORCE_LFPS_PWD (0x1<<29) /* 29:29 */ +#define RG_SSUSB_RXLFPS_OVF (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_P3_ENTRY_SEL (0x1<<23) /* 23:23 */ +#define RG_SSUSB_P3_ENTRY (0x1<<22) /* 22:22 */ +#define RG_SSUSB_RXLFPS_CDRSEL (0x3<<20) /* 21:20 */ +#define RG_SSUSB_RXLFPS_CDRTH (0xf<<16) /* 19:16 */ +#define RG_SSUSB_LOCK5G_BLOCK (0x1<<15) /* 15:15 */ +#define RG_SSUSB_TFIFO_EXT_D_SEL (0x1<<14) /* 14:14 */ +#define RG_SSUSB_TFIFO_NO_EXTEND (0x1<<13) /* 13:13 */ +#define RG_SSUSB_RXLFPS_LOB (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_TXLFPS_EN (0x1<<7) /* 7:7 */ +#define RG_SSUSB_TXLFPS_SEL (0x1<<6) /* 6:6 */ +#define RG_SSUSB_RXLFPS_CDRLOCK (0x1<<5) /* 5:5 */ +#define RG_SSUSB_RXLFPS_UPB (0x1f<<0) /* 4:0 */ + +/* U3D_PHYD_LFPS1 */ +#define RG_SSUSB_RX_IMP_BIAS (0xf<<28) /* 31:28 */ +#define RG_SSUSB_TX_IMP_BIAS (0xf<<24) /* 27:24 */ +#define RG_SSUSB_FWAKE_TH (0x3f<<16) /* 21:16 */ +#define RG_SSUSB_P1_ENTRY_SEL (0x1<<14) /* 14:14 */ +#define RG_SSUSB_P1_ENTRY (0x1<<13) /* 13:13 */ +#define RG_SSUSB_RXLFPS_UDF (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_RXLFPS_P0IDLETH (0xff<<0) /* 7:0 */ + +/* U3D_PHYD_IMPCAL0 */ +#define RG_SSUSB_FORCE_TX_IMPSEL (0x1<<31) /* 31:31 */ +#define RG_SSUSB_TX_IMPCAL_EN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_FORCE_TX_IMPCAL_EN (0x1<<29) /* 29:29 */ +#define RG_SSUSB_TX_IMPSEL (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_TX_IMPCAL_CALCYC (0x3f<<16) /* 21:16 */ +#define RG_SSUSB_TX_IMPCAL_STBCYC (0x1f<<10) /* 14:10 */ +#define RG_SSUSB_TX_IMPCAL_CYCCNT (0x3ff<<0) /* 9:0 */ + +/* U3D_PHYD_IMPCAL1 */ +#define RG_SSUSB_FORCE_RX_IMPSEL (0x1<<31) /* 31:31 */ +#define RG_SSUSB_RX_IMPCAL_EN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_FORCE_RX_IMPCAL_EN (0x1<<29) /* 29:29 */ +#define RG_SSUSB_RX_IMPSEL (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_RX_IMPCAL_CALCYC (0x3f<<16) /* 21:16 */ +#define RG_SSUSB_RX_IMPCAL_STBCYC (0x1f<<10) /* 14:10 */ +#define RG_SSUSB_RX_IMPCAL_CYCCNT (0x3ff<<0) /* 9:0 */ + +/* U3D_PHYD_TXPLL0 */ +#define RG_SSUSB_TXPLL_DDSEN_CYC (0x1f<<27) /* 31:27 */ +#define RG_SSUSB_TXPLL_ON (0x1<<26) /* 26:26 */ +#define RG_SSUSB_FORCE_TXPLLON (0x1<<25) /* 25:25 */ +#define RG_SSUSB_TXPLL_STBCYC (0x1ff<<16) /* 24:16 */ +#define RG_SSUSB_TXPLL_NCPOCHG_CYC (0xf<<12) /* 15:12 */ +#define RG_SSUSB_TXPLL_NCPOEN_CYC (0x3<<10) /* 11:10 */ +#define RG_SSUSB_TXPLL_DDSRSTB_CYC (0x7<<0) /* 2:0 */ + +/* U3D_PHYD_TXPLL1 */ +#define RG_SSUSB_PLL_NCPO_EN (0x1<<31) /* 31:31 */ +#define RG_SSUSB_PLL_FIFO_START_MAN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_PLL_NCPO_CHG (0x1<<28) /* 28:28 */ +#define RG_SSUSB_PLL_DDS_RSTB (0x1<<27) /* 27:27 */ +#define RG_SSUSB_PLL_DDS_PWDB (0x1<<26) /* 26:26 */ +#define RG_SSUSB_PLL_DDSEN (0x1<<25) /* 25:25 */ +#define RG_SSUSB_PLL_AUTOK_VCO (0x1<<24) /* 24:24 */ +#define RG_SSUSB_PLL_PWD (0x1<<23) /* 23:23 */ +#define RG_SSUSB_RX_AFE_PWD (0x1<<22) /* 22:22 */ +#define RG_SSUSB_PLL_TCADJ (0x3f<<16) /* 21:16 */ +#define RG_SSUSB_FORCE_CDR_TCADJ (0x1<<15) /* 15:15 */ +#define RG_SSUSB_FORCE_CDR_AUTOK_VCO (0x1<<14) /* 14:14 */ +#define RG_SSUSB_FORCE_CDR_PWD (0x1<<13) /* 13:13 */ +#define RG_SSUSB_FORCE_PLL_NCPO_EN (0x1<<12) /* 12:12 */ +#define RG_SSUSB_FORCE_PLL_FIFO_START_MAN (0x1<<11) /* 11:11 */ +#define RG_SSUSB_FORCE_PLL_NCPO_CHG (0x1<<9) /* 9:9 */ +#define RG_SSUSB_FORCE_PLL_DDS_RSTB (0x1<<8) /* 8:8 */ +#define RG_SSUSB_FORCE_PLL_DDS_PWDB (0x1<<7) /* 7:7 */ +#define RG_SSUSB_FORCE_PLL_DDSEN (0x1<<6) /* 6:6 */ +#define RG_SSUSB_FORCE_PLL_TCADJ (0x1<<5) /* 5:5 */ +#define RG_SSUSB_FORCE_PLL_AUTOK_VCO (0x1<<4) /* 4:4 */ +#define RG_SSUSB_FORCE_PLL_PWD (0x1<<3) /* 3:3 */ +#define RG_SSUSB_FLT_1_DISPERR_B (0x1<<2) /* 2:2 */ + +/* U3D_PHYD_TXPLL2 */ +#define RG_SSUSB_TX_LFPS_EN (0x1<<31) /* 31:31 */ +#define RG_SSUSB_FORCE_TX_LFPS_EN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_TX_LFPS (0x1<<29) /* 29:29 */ +#define RG_SSUSB_FORCE_TX_LFPS (0x1<<28) /* 28:28 */ +#define RG_SSUSB_RXPLL_STB (0x1<<27) /* 27:27 */ +#define RG_SSUSB_TXPLL_STB (0x1<<26) /* 26:26 */ +#define RG_SSUSB_FORCE_RXPLL_STB (0x1<<25) /* 25:25 */ +#define RG_SSUSB_FORCE_TXPLL_STB (0x1<<24) /* 24:24 */ +#define RG_SSUSB_RXPLL_REFCKSEL (0x1<<16) /* 16:16 */ +#define RG_SSUSB_RXPLL_STBMODE (0x1<<11) /* 11:11 */ +#define RG_SSUSB_RXPLL_ON (0x1<<10) /* 10:10 */ +#define RG_SSUSB_FORCE_RXPLLON (0x1<<9) /* 9:9 */ +#define RG_SSUSB_FORCE_RX_AFE_PWD (0x1<<8) /* 8:8 */ +#define RG_SSUSB_CDR_AUTOK_VCO (0x1<<7) /* 7:7 */ +#define RG_SSUSB_CDR_PWD (0x1<<6) /* 6:6 */ +#define RG_SSUSB_CDR_TCADJ (0x3f<<0) /* 5:0 */ + +/* U3D_PHYD_FL0 */ +#define RG_SSUSB_RX_FL_TARGET (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_RX_FL_CYCLECNT (0xffff<<0) /* 15:0 */ + +/* U3D_PHYD_MIX2 */ +#define RG_SSUSB_RX_EQ_RST (0x1<<31) /* 31:31 */ +#define RG_SSUSB_RX_EQ_RST_SEL (0x1<<30) /* 30:30 */ +#define RG_SSUSB_RXVAL_RST (0x1<<29) /* 29:29 */ +#define RG_SSUSB_RXVAL_CNT (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_CDROS_EN (0x1<<18) /* 18:18 */ +#define RG_SSUSB_CDR_LCKOP (0x3<<16) /* 17:16 */ +#define RG_SSUSB_RX_FL_LOCKTH (0xf<<8) /* 11:8 */ +#define RG_SSUSB_RX_FL_OFFSET (0xff<<0) /* 7:0 */ + +/* U3D_PHYD_RX0 */ +#define RG_SSUSB_T2RLB_BERTH (0xff<<24) /* 31:24 */ +#define RG_SSUSB_T2RLB_PAT (0xff<<16) /* 23:16 */ +#define RG_SSUSB_T2RLB_EN (0x1<<15) /* 15:15 */ +#define RG_SSUSB_T2RLB_BPSCRAMB (0x1<<14) /* 14:14 */ +#define RG_SSUSB_T2RLB_SERIAL (0x1<<13) /* 13:13 */ +#define RG_SSUSB_T2RLB_MODE (0x3<<11) /* 12:11 */ +#define RG_SSUSB_RX_SAOSC_EN (0x1<<10) /* 10:10 */ +#define RG_SSUSB_RX_SAOSC_EN_SEL (0x1<<9) /* 9:9 */ +#define RG_SSUSB_RX_DFE_OPTION (0x1<<8) /* 8:8 */ +#define RG_SSUSB_RX_DFE_EN (0x1<<7) /* 7:7 */ +#define RG_SSUSB_RX_DFE_EN_SEL (0x1<<6) /* 6:6 */ +#define RG_SSUSB_RX_EQ_EN (0x1<<5) /* 5:5 */ +#define RG_SSUSB_RX_EQ_EN_SEL (0x1<<4) /* 4:4 */ +#define RG_SSUSB_RX_SAOSC_RST (0x1<<3) /* 3:3 */ +#define RG_SSUSB_RX_SAOSC_RST_SEL (0x1<<2) /* 2:2 */ +#define RG_SSUSB_RX_DFE_RST (0x1<<1) /* 1:1 */ +#define RG_SSUSB_RX_DFE_RST_SEL (0x1<<0) /* 0:0 */ + +/* U3D_PHYD_T2RLB */ +#define RG_SSUSB_EQTRAIN_CH_MODE (0x1<<28) /* 28:28 */ +#define RG_SSUSB_PRB_OUT_CPPAT (0x1<<27) /* 27:27 */ +#define RG_SSUSB_BPANSIENC (0x1<<26) /* 26:26 */ +#define RG_SSUSB_VALID_EN (0x1<<25) /* 25:25 */ +#define RG_SSUSB_EBUF_SRST (0x1<<24) /* 24:24 */ +#define RG_SSUSB_K_EMP (0xf<<20) /* 23:20 */ +#define RG_SSUSB_K_FUL (0xf<<16) /* 19:16 */ +#define RG_SSUSB_T2RLB_BDATRST (0xf<<12) /* 15:12 */ +#define RG_SSUSB_P_T2RLB_SKP_EN (0x1<<10) /* 10:10 */ +#define RG_SSUSB_T2RLB_PATMODE (0x3<<8) /* 9:8 */ +#define RG_SSUSB_T2RLB_TSEQCNT (0xff<<0) /* 7:0 */ + +/* U3D_PHYD_CPPAT */ +#define RG_SSUSB_CPPAT_PROGRAM_EN (0x1<<24) /* 24:24 */ +#define RG_SSUSB_CPPAT_TOZ (0x3<<21) /* 22:21 */ +#define RG_SSUSB_CPPAT_PRBS_EN (0x1<<20) /* 20:20 */ +#define RG_SSUSB_CPPAT_OUT_TMP2 (0xf<<16) /* 19:16 */ +#define RG_SSUSB_CPPAT_OUT_TMP1 (0xff<<8) /* 15:8 */ +#define RG_SSUSB_CPPAT_OUT_TMP0 (0xff<<0) /* 7:0 */ + +/* U3D_PHYD_MIX3 */ +#define RG_SSUSB_CDR_TCADJ_MINUS (0x1<<31) /* 31:31 */ +#define RG_SSUSB_P_CDROS_EN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_P_P2_TX_DRV_DIS (0x1<<28) /* 28:28 */ +#define RG_SSUSB_CDR_TCADJ_OFFSET (0x7<<24) /* 26:24 */ +#define RG_SSUSB_PLL_TCADJ_MINUS (0x1<<23) /* 23:23 */ +#define RG_SSUSB_FORCE_PLL_BIAS_LPF_EN (0x1<<20) /* 20:20 */ +#define RG_SSUSB_PLL_BIAS_LPF_EN (0x1<<19) /* 19:19 */ +#define RG_SSUSB_PLL_TCADJ_OFFSET (0x7<<16) /* 18:16 */ +#define RG_SSUSB_FORCE_PLL_SSCEN (0x1<<15) /* 15:15 */ +#define RG_SSUSB_PLL_SSCEN (0x1<<14) /* 14:14 */ +#define RG_SSUSB_FORCE_CDR_PI_PWD (0x1<<13) /* 13:13 */ +#define RG_SSUSB_CDR_PI_PWD (0x1<<12) /* 12:12 */ +#define RG_SSUSB_CDR_PI_MODE (0x1<<11) /* 11:11 */ +#define RG_SSUSB_TXPLL_SSCEN_CYC (0x3ff<<0) /* 9:0 */ + +/* U3D_PHYD_EBUFCTL */ +#define RG_SSUSB_EBUFCTL (0xffffffff<<0) /* 31:0 */ + +/* U3D_PHYD_PIPE0 */ +#define RG_SSUSB_RXTERMINATION (0x1<<30) /* 30:30 */ +#define RG_SSUSB_RXEQTRAINING (0x1<<29) /* 29:29 */ +#define RG_SSUSB_RXPOLARITY (0x1<<28) /* 28:28 */ +#define RG_SSUSB_TXDEEMPH (0x3<<26) /* 27:26 */ +#define RG_SSUSB_POWERDOWN (0x3<<24) /* 25:24 */ +#define RG_SSUSB_TXONESZEROS (0x1<<23) /* 23:23 */ +#define RG_SSUSB_TXELECIDLE (0x1<<22) /* 22:22 */ +#define RG_SSUSB_TXDETECTRX (0x1<<21) /* 21:21 */ +#define RG_SSUSB_PIPE_SEL (0x1<<20) /* 20:20 */ +#define RG_SSUSB_TXDATAK (0xf<<16) /* 19:16 */ +#define RG_SSUSB_CDR_STABLE_SEL (0x1<<15) /* 15:15 */ +#define RG_SSUSB_CDR_STABLE (0x1<<14) /* 14:14 */ +#define RG_SSUSB_CDR_RSTB_SEL (0x1<<13) /* 13:13 */ +#define RG_SSUSB_CDR_RSTB (0x1<<12) /* 12:12 */ +#define RG_SSUSB_FRC_PIPE_POWERDOWN (0x1<<11) /* 11:11 */ +#define RG_SSUSB_P_TXBCN_DIS (0x1<<6) /* 6:6 */ +#define RG_SSUSB_P_ERROR_SEL (0x3<<4) /* 5:4 */ +#define RG_SSUSB_TXMARGIN (0x7<<1) /* 3:1 */ +#define RG_SSUSB_TXCOMPLIANCE (0x1<<0) /* 0:0 */ + +/* U3D_PHYD_PIPE1 */ +#define RG_SSUSB_TXDATA (0xffffffff<<0) /* 31:0 */ + +/* U3D_PHYD_MIX4 */ +#define RG_SSUSB_CDROS_CNT (0x3f<<24) /* 29:24 */ +#define RG_SSUSB_T2RLB_BER_EN (0x1<<16) /* 16:16 */ +#define RG_SSUSB_T2RLB_BER_RATE (0xffff<<0) /* 15:0 */ + +/* U3D_PHYD_CKGEN0 */ +#define RG_SSUSB_RFIFO_IMPLAT (0x1<<27) /* 27:27 */ +#define RG_SSUSB_TFIFO_PSEL (0x7<<24) /* 26:24 */ +#define RG_SSUSB_CKGEN_PSEL (0x3<<8) /* 9:8 */ +#define RG_SSUSB_RXCK_INV (0x1<<0) /* 0:0 */ + +/* U3D_PHYD_MIX5 */ +#define RG_SSUSB_PRB_SEL (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_RXPLL_STBCYC (0x7ff<<0) /* 10:0 */ + +/* U3D_PHYD_RESERVED */ +#define RG_SSUSB_PHYD_RESERVE (0xffffffff<<0) /* 31:0 */ + +/* U3D_PHYD_CDR0 */ +#define RG_SSUSB_CDR_BIC_LTR (0xf<<28) /* 31:28 */ +#define RG_SSUSB_CDR_BIC_LTD0 (0xf<<24) /* 27:24 */ +#define RG_SSUSB_CDR_BC_LTD1 (0x1f<<16) /* 20:16 */ +#define RG_SSUSB_CDR_BC_LTR (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_CDR_BC_LTD0 (0x1f<<0) /* 4:0 */ + +/* U3D_PHYD_CDR1 */ +#define RG_SSUSB_CDR_BIR_LTD1 (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_CDR_BIR_LTR (0x1f<<16) /* 20:16 */ +#define RG_SSUSB_CDR_BIR_LTD0 (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_CDR_BW_SEL (0x3<<6) /* 7:6 */ +#define RG_SSUSB_CDR_BIC_LTD1 (0xf<<0) /* 3:0 */ + +/* U3D_PHYD_PLL_0 */ +#define RG_SSUSB_FORCE_CDR_BAND_5G (0x1<<28) /* 28:28 */ +#define RG_SSUSB_FORCE_CDR_BAND_2P5G (0x1<<27) /* 27:27 */ +#define RG_SSUSB_FORCE_PLL_BAND_5G (0x1<<26) /* 26:26 */ +#define RG_SSUSB_FORCE_PLL_BAND_2P5G (0x1<<25) /* 25:25 */ +#define RG_SSUSB_P_EQ_T_SEL (0x3ff<<15) /* 24:15 */ +#define RG_SSUSB_PLL_ISO_EN_CYC (0x3ff<<5) /* 14:5 */ +#define RG_SSUSB_PLLBAND_RECAL (0x1<<4) /* 4:4 */ +#define RG_SSUSB_PLL_DDS_ISO_EN (0x1<<3) /* 3:3 */ +#define RG_SSUSB_FORCE_PLL_DDS_ISO_EN (0x1<<2) /* 2:2 */ +#define RG_SSUSB_PLL_DDS_PWR_ON (0x1<<1) /* 1:1 */ +#define RG_SSUSB_FORCE_PLL_DDS_PWR_ON (0x1<<0) /* 0:0 */ + +/* U3D_PHYD_PLL_1 */ +#define RG_SSUSB_CDR_BAND_5G (0xff<<24) /* 31:24 */ +#define RG_SSUSB_CDR_BAND_2P5G (0xff<<16) /* 23:16 */ +#define RG_SSUSB_PLL_BAND_5G (0xff<<8) /* 15:8 */ +#define RG_SSUSB_PLL_BAND_2P5G (0xff<<0) /* 7:0 */ + +/* U3D_PHYD_BCN_DET_1 */ +#define RG_SSUSB_P_BCN_OBS_PRD (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_U_BCN_OBS_PRD (0xffff<<0) /* 15:0 */ + +/* U3D_PHYD_BCN_DET_2 */ +#define RG_SSUSB_P_BCN_OBS_SEL (0xfff<<16) /* 27:16 */ +#define RG_SSUSB_BCN_DET_DIS (0x1<<12) /* 12:12 */ +#define RG_SSUSB_U_BCN_OBS_SEL (0xfff<<0) /* 11:0 */ + +/* U3D_EQ0 */ +#define RG_SSUSB_EQ_DLHL_LFI (0x7f<<24) /* 30:24 */ +#define RG_SSUSB_EQ_DHHL_LFI (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_EQ_DD0HOS_LFI (0x7f<<8) /* 14:8 */ +#define RG_SSUSB_EQ_DD0LOS_LFI (0x7f<<0) /* 6:0 */ + +/* U3D_EQ1 */ +#define RG_SSUSB_EQ_DD1HOS_LFI (0x7f<<24) /* 30:24 */ +#define RG_SSUSB_EQ_DD1LOS_LFI (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_EQ_DE0OS_LFI (0x7f<<8) /* 14:8 */ +#define RG_SSUSB_EQ_DE1OS_LFI (0x7f<<0) /* 6:0 */ + +/* U3D_EQ2 */ +#define RG_SSUSB_EQ_DLHLOS_LFI (0x7f<<24) /* 30:24 */ +#define RG_SSUSB_EQ_DHHLOS_LFI (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_EQ_STOPTIME (0x1<<14) /* 14:14 */ +#define RG_SSUSB_EQ_DHHL_LF_SEL (0x7<<11) /* 13:11 */ +#define RG_SSUSB_EQ_DSAOS_LF_SEL (0x7<<8) /* 10:8 */ +#define RG_SSUSB_EQ_STARTTIME (0x3<<6) /* 7:6 */ +#define RG_SSUSB_EQ_DLEQ_LF_SEL (0x7<<3) /* 5:3 */ +#define RG_SSUSB_EQ_DLHL_LF_SEL (0x7<<0) /* 2:0 */ + +/* U3D_EQ3 */ +#define RG_SSUSB_EQ_DLEQ_LFI_GEN2 (0xf<<28) /* 31:28 */ +#define RG_SSUSB_EQ_DLEQ_LFI_GEN1 (0xf<<24) /* 27:24 */ +#define RG_SSUSB_EQ_DEYE0OS_LFI (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_EQ_DEYE1OS_LFI (0x7f<<8) /* 14:8 */ +#define RG_SSUSB_EQ_TRI_DET_EN (0x1<<7) /* 7:7 */ +#define RG_SSUSB_EQ_TRI_DET_TH (0x7f<<0) /* 6:0 */ + +/* U3D_EQ_EYE0 */ +#define RG_SSUSB_EQ_EYE_XOFFSET (0x7f<<25) /* 31:25 */ +#define RG_SSUSB_EQ_EYE_MON_EN (0x1<<24) /* 24:24 */ +#define RG_SSUSB_EQ_EYE0_Y (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_EQ_EYE1_Y (0x7f<<8) /* 14:8 */ +#define RG_SSUSB_EQ_PILPO_ROUT (0x1<<7) /* 7:7 */ +#define RG_SSUSB_EQ_PI_KPGAIN (0x7<<4) /* 6:4 */ +#define RG_SSUSB_EQ_EYE_CNT_EN (0x1<<3) /* 3:3 */ + +/* U3D_EQ_EYE1 */ +#define RG_SSUSB_EQ_SIGDET (0x7f<<24) /* 30:24 */ +#define RG_SSUSB_EQ_EYE_MASK (0x3ff<<7) /* 16:7 */ + +/* U3D_EQ_EYE2 */ +#define RG_SSUSB_EQ_RX500M_CK_SEL (0x1<<31) /* 31:31 */ +#define RG_SSUSB_EQ_SD_CNT1 (0x3f<<24) /* 29:24 */ +#define RG_SSUSB_EQ_ISIFLAG_SEL (0x3<<22) /* 23:22 */ +#define RG_SSUSB_EQ_SD_CNT0 (0x3f<<16) /* 21:16 */ + +/* U3D_EQ_DFE0 */ +#define RG_SSUSB_EQ_LEQMAX (0xf<<28) /* 31:28 */ +#define RG_SSUSB_EQ_DFEX_EN (0x1<<27) /* 27:27 */ +#define RG_SSUSB_EQ_DFEX_LF_SEL (0x7<<24) /* 26:24 */ +#define RG_SSUSB_EQ_CHK_EYE_H (0x1<<23) /* 23:23 */ +#define RG_SSUSB_EQ_PIEYE_INI (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_EQ_PI90_INI (0x7f<<8) /* 14:8 */ +#define RG_SSUSB_EQ_PI0_INI (0x7f<<0) /* 6:0 */ + +/* U3D_EQ_DFE1 */ +#define RG_SSUSB_EQ_REV (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_EQ_DFEYEN_DUR (0x7<<12) /* 14:12 */ +#define RG_SSUSB_EQ_DFEXEN_DUR (0x7<<8) /* 10:8 */ +#define RG_SSUSB_EQ_DFEX_RST (0x1<<7) /* 7:7 */ +#define RG_SSUSB_EQ_GATED_RXD_B (0x1<<6) /* 6:6 */ +#define RG_SSUSB_EQ_PI90CK_SEL (0x3<<4) /* 5:4 */ +#define RG_SSUSB_EQ_DFEX_DIS (0x1<<2) /* 2:2 */ +#define RG_SSUSB_EQ_DFEYEN_STOP_DIS (0x1<<1) /* 1:1 */ +#define RG_SSUSB_EQ_DFEXEN_SEL (0x1<<0) /* 0:0 */ + +/* U3D_EQ_DFE2 */ +#define RG_SSUSB_EQ_MON_SEL (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_EQ_LEQOSC_DLYCNT (0x7<<16) /* 18:16 */ +#define RG_SSUSB_EQ_DLEQOS_LFI (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_EQ_DFE_TOG (0x1<<2) /* 2:2 */ +#define RG_SSUSB_EQ_LEQ_STOP_TO (0x3<<0) /* 1:0 */ + +/* U3D_EQ_DFE3 */ +#define RG_SSUSB_EQ_RESERVED (0xffffffff<<0) /* 31:0 */ + +/* U3D_PHYD_MON0 */ +#define RGS_SSUSB_BERT_BERC (0xffff<<16) /* 31:16 */ +#define RGS_SSUSB_LFPS (0xf<<12) /* 15:12 */ +#define RGS_SSUSB_TRAINDEC (0x7<<8) /* 10:8 */ +#define RGS_SSUSB_SCP_PAT (0xff<<0) /* 7:0 */ + +/* U3D_PHYD_MON1 */ +#define RGS_SSUSB_RX_FL_OUT (0xffff<<0) /* 15:0 */ + +/* U3D_PHYD_MON2 */ +#define RGS_SSUSB_T2RLB_ERRCNT (0xffff<<16) /* 31:16 */ +#define RGS_SSUSB_RETRACK (0xf<<12) /* 15:12 */ +#define RGS_SSUSB_RXPLL_LOCK (0x1<<10) /* 10:10 */ +#define RGS_SSUSB_CDR_VCOCAL_CPLT_D (0x1<<9) /* 9:9 */ +#define RGS_SSUSB_PLL_VCOCAL_CPLT_D (0x1<<8) /* 8:8 */ +#define RGS_SSUSB_PDNCTL (0xff<<0) /* 7:0 */ + +/* U3D_PHYD_MON3 */ +#define RGS_SSUSB_TSEQ_ERRCNT (0xffff<<16) /* 31:16 */ +#define RGS_SSUSB_PRBS_ERRCNT (0xffff<<0) /* 15:0 */ + +/* U3D_PHYD_MON4 */ +#define RGS_SSUSB_RX_LSLOCK_CNT (0xf<<24) /* 27:24 */ +#define RGS_SSUSB_SCP_DETCNT (0xff<<16) /* 23:16 */ +#define RGS_SSUSB_TSEQ_DETCNT (0xffff<<0) /* 15:0 */ + +/* U3D_PHYD_MON5 */ +#define RGS_SSUSB_EBUFMSG (0xffff<<16) /* 31:16 */ +#define RGS_SSUSB_BERT_LOCK (0x1<<15) /* 15:15 */ +#define RGS_SSUSB_SCP_DET (0x1<<14) /* 14:14 */ +#define RGS_SSUSB_TSEQ_DET (0x1<<13) /* 13:13 */ +#define RGS_SSUSB_EBUF_UDF (0x1<<12) /* 12:12 */ +#define RGS_SSUSB_EBUF_OVF (0x1<<11) /* 11:11 */ +#define RGS_SSUSB_PRBS_PASSTH (0x1<<10) /* 10:10 */ +#define RGS_SSUSB_PRBS_PASS (0x1<<9) /* 9:9 */ +#define RGS_SSUSB_PRBS_LOCK (0x1<<8) /* 8:8 */ +#define RGS_SSUSB_T2RLB_ERR (0x1<<6) /* 6:6 */ +#define RGS_SSUSB_T2RLB_PASSTH (0x1<<5) /* 5:5 */ +#define RGS_SSUSB_T2RLB_PASS (0x1<<4) /* 4:4 */ +#define RGS_SSUSB_T2RLB_LOCK (0x1<<3) /* 3:3 */ +#define RGS_SSUSB_RX_IMPCAL_DONE (0x1<<2) /* 2:2 */ +#define RGS_SSUSB_TX_IMPCAL_DONE (0x1<<1) /* 1:1 */ +#define RGS_SSUSB_RXDETECTED (0x1<<0) /* 0:0 */ + +/* U3D_PHYD_MON6 */ +#define RGS_SSUSB_SIGCAL_DONE (0x1<<30) /* 30:30 */ +#define RGS_SSUSB_SIGCAL_CAL_OUT (0x1<<29) /* 29:29 */ +#define RGS_SSUSB_SIGCAL_OFFSET (0x1f<<24) /* 28:24 */ +#define RGS_SSUSB_RX_IMP_SEL (0x1f<<16) /* 20:16 */ +#define RGS_SSUSB_TX_IMP_SEL (0x1f<<8) /* 12:8 */ +#define RGS_SSUSB_TFIFO_MSG (0xf<<4) /* 7:4 */ +#define RGS_SSUSB_RFIFO_MSG (0xf<<0) /* 3:0 */ + +/* U3D_PHYD_MON7 */ +#define RGS_SSUSB_FT_OUT (0xff<<8) /* 15:8 */ +#define RGS_SSUSB_PRB_OUT (0xff<<0) /* 7:0 */ + +/* U3D_PHYA_RX_MON0 */ +#define RGS_SSUSB_EQ_DCLEQ (0xf<<24) /* 27:24 */ +#define RGS_SSUSB_EQ_DCD0H (0x7f<<16) /* 22:16 */ +#define RGS_SSUSB_EQ_DCD0L (0x7f<<8) /* 14:8 */ +#define RGS_SSUSB_EQ_DCD1H (0x7f<<0) /* 6:0 */ + +/* U3D_PHYA_RX_MON1 */ +#define RGS_SSUSB_EQ_DCD1L (0x7f<<24) /* 30:24 */ +#define RGS_SSUSB_EQ_DCE0 (0x7f<<16) /* 22:16 */ +#define RGS_SSUSB_EQ_DCE1 (0x7f<<8) /* 14:8 */ +#define RGS_SSUSB_EQ_DCHHL (0x7f<<0) /* 6:0 */ + +/* U3D_PHYA_RX_MON2 */ +#define RGS_SSUSB_EQ_LEQ_STOP (0x1<<31) /* 31:31 */ +#define RGS_SSUSB_EQ_DCLHL (0x7f<<24) /* 30:24 */ +#define RGS_SSUSB_EQ_STATUS (0xff<<16) /* 23:16 */ +#define RGS_SSUSB_EQ_DCEYE0 (0x7f<<8) /* 14:8 */ +#define RGS_SSUSB_EQ_DCEYE1 (0x7f<<0) /* 6:0 */ + +/* U3D_PHYA_RX_MON3 */ +#define RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_0 (0xfffff<<0) /* 19:0 */ + +/* U3D_PHYA_RX_MON4 */ +#define RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_1 (0xfffff<<0) /* 19:0 */ + +/* U3D_PHYA_RX_MON5 */ +#define RGS_SSUSB_EQ_DCLEQOS (0x1f<<8) /* 12:8 */ +#define RGS_SSUSB_EQ_EYE_CNT_RDY (0x1<<7) /* 7:7 */ +#define RGS_SSUSB_EQ_PILPO (0x7f<<0) /* 6:0 */ + +/* U3D_PHYD_CPPAT2 */ +#define RG_SSUSB_CPPAT_OUT_H_TMP2 (0xf<<16) /* 19:16 */ +#define RG_SSUSB_CPPAT_OUT_H_TMP1 (0xff<<8) /* 15:8 */ +#define RG_SSUSB_CPPAT_OUT_H_TMP0 (0xff<<0) /* 7:0 */ + +/* U3D_EQ_EYE3 */ +#define RG_SSUSB_EQ_LEQ_SHIFT (0x7<<24) /* 26:24 */ +#define RG_SSUSB_EQ_EYE_CNT (0xfffff<<0) /* 19:0 */ + +/* U3D_KBAND_OUT */ +#define RGS_SSUSB_CDR_BAND_5G (0xff<<24) /* 31:24 */ +#define RGS_SSUSB_CDR_BAND_2P5G (0xff<<16) /* 23:16 */ +#define RGS_SSUSB_PLL_BAND_5G (0xff<<8) /* 15:8 */ +#define RGS_SSUSB_PLL_BAND_2P5G (0xff<<0) /* 7:0 */ + +/* U3D_KBAND_OUT1 */ +#define RGS_SSUSB_CDR_VCOCAL_FAIL (0x1<<24) /* 24:24 */ +#define RGS_SSUSB_CDR_VCOCAL_STATE (0xff<<16) /* 23:16 */ +#define RGS_SSUSB_PLL_VCOCAL_FAIL (0x1<<8) /* 8:8 */ +#define RGS_SSUSB_PLL_VCOCAL_STATE (0xff<<0) /* 7:0 */ + +/* OFFSET */ + +/* U3D_PHYD_MIX0 */ +#define RG_SSUSB_P_P3_TX_NG_OFST (31) +#define RG_SSUSB_TSEQ_EN_OFST (30) +#define RG_SSUSB_TSEQ_POLEN_OFST (29) +#define RG_SSUSB_TSEQ_POL_OFST (28) +#define RG_SSUSB_P_P3_PCLK_NG_OFST (27) +#define RG_SSUSB_TSEQ_TH_OFST (24) +#define RG_SSUSB_PRBS_BERTH_OFST (16) +#define RG_SSUSB_DISABLE_PHY_U2_ON_OFST (15) +#define RG_SSUSB_DISABLE_PHY_U2_OFF_OFST (14) +#define RG_SSUSB_PRBS_EN_OFST (13) +#define RG_SSUSB_BPSLOCK_OFST (12) +#define RG_SSUSB_RTCOMCNT_OFST (8) +#define RG_SSUSB_COMCNT_OFST (4) +#define RG_SSUSB_PRBSEL_CALIB_OFST (0) + +/* U3D_PHYD_MIX1 */ +#define RG_SSUSB_SLEEP_EN_OFST (31) +#define RG_SSUSB_PRBSEL_PCS_OFST (28) +#define RG_SSUSB_TXLFPS_PRD_OFST (24) +#define RG_SSUSB_P_RX_P0S_CK_OFST (23) +#define RG_SSUSB_P_TX_P0S_CK_OFST (22) +#define RG_SSUSB_PDNCTL_OFST (16) +#define RG_SSUSB_TX_DRV_EN_OFST (15) +#define RG_SSUSB_TX_DRV_SEL_OFST (14) +#define RG_SSUSB_TX_DRV_DLY_OFST (8) +#define RG_SSUSB_BERT_EN_OFST (7) +#define RG_SSUSB_SCP_TH_OFST (4) +#define RG_SSUSB_SCP_EN_OFST (3) +#define RG_SSUSB_RXANSIDEC_TEST_OFST (0) + +/* U3D_PHYD_LFPS0 */ +#define RG_SSUSB_LFPS_PWD_OFST (30) +#define RG_SSUSB_FORCE_LFPS_PWD_OFST (29) +#define RG_SSUSB_RXLFPS_OVF_OFST (24) +#define RG_SSUSB_P3_ENTRY_SEL_OFST (23) +#define RG_SSUSB_P3_ENTRY_OFST (22) +#define RG_SSUSB_RXLFPS_CDRSEL_OFST (20) +#define RG_SSUSB_RXLFPS_CDRTH_OFST (16) +#define RG_SSUSB_LOCK5G_BLOCK_OFST (15) +#define RG_SSUSB_TFIFO_EXT_D_SEL_OFST (14) +#define RG_SSUSB_TFIFO_NO_EXTEND_OFST (13) +#define RG_SSUSB_RXLFPS_LOB_OFST (8) +#define RG_SSUSB_TXLFPS_EN_OFST (7) +#define RG_SSUSB_TXLFPS_SEL_OFST (6) +#define RG_SSUSB_RXLFPS_CDRLOCK_OFST (5) +#define RG_SSUSB_RXLFPS_UPB_OFST (0) + +/* U3D_PHYD_LFPS1 */ +#define RG_SSUSB_RX_IMP_BIAS_OFST (28) +#define RG_SSUSB_TX_IMP_BIAS_OFST (24) +#define RG_SSUSB_FWAKE_TH_OFST (16) +#define RG_SSUSB_P1_ENTRY_SEL_OFST (14) +#define RG_SSUSB_P1_ENTRY_OFST (13) +#define RG_SSUSB_RXLFPS_UDF_OFST (8) +#define RG_SSUSB_RXLFPS_P0IDLETH_OFST (0) + +/* U3D_PHYD_IMPCAL0 */ +#define RG_SSUSB_FORCE_TX_IMPSEL_OFST (31) +#define RG_SSUSB_TX_IMPCAL_EN_OFST (30) +#define RG_SSUSB_FORCE_TX_IMPCAL_EN_OFST (29) +#define RG_SSUSB_TX_IMPSEL_OFST (24) +#define RG_SSUSB_TX_IMPCAL_CALCYC_OFST (16) +#define RG_SSUSB_TX_IMPCAL_STBCYC_OFST (10) +#define RG_SSUSB_TX_IMPCAL_CYCCNT_OFST (0) + +/* U3D_PHYD_IMPCAL1 */ +#define RG_SSUSB_FORCE_RX_IMPSEL_OFST (31) +#define RG_SSUSB_RX_IMPCAL_EN_OFST (30) +#define RG_SSUSB_FORCE_RX_IMPCAL_EN_OFST (29) +#define RG_SSUSB_RX_IMPSEL_OFST (24) +#define RG_SSUSB_RX_IMPCAL_CALCYC_OFST (16) +#define RG_SSUSB_RX_IMPCAL_STBCYC_OFST (10) +#define RG_SSUSB_RX_IMPCAL_CYCCNT_OFST (0) + +/* U3D_PHYD_TXPLL0 */ +#define RG_SSUSB_TXPLL_DDSEN_CYC_OFST (27) +#define RG_SSUSB_TXPLL_ON_OFST (26) +#define RG_SSUSB_FORCE_TXPLLON_OFST (25) +#define RG_SSUSB_TXPLL_STBCYC_OFST (16) +#define RG_SSUSB_TXPLL_NCPOCHG_CYC_OFST (12) +#define RG_SSUSB_TXPLL_NCPOEN_CYC_OFST (10) +#define RG_SSUSB_TXPLL_DDSRSTB_CYC_OFST (0) + +/* U3D_PHYD_TXPLL1 */ +#define RG_SSUSB_PLL_NCPO_EN_OFST (31) +#define RG_SSUSB_PLL_FIFO_START_MAN_OFST (30) +#define RG_SSUSB_PLL_NCPO_CHG_OFST (28) +#define RG_SSUSB_PLL_DDS_RSTB_OFST (27) +#define RG_SSUSB_PLL_DDS_PWDB_OFST (26) +#define RG_SSUSB_PLL_DDSEN_OFST (25) +#define RG_SSUSB_PLL_AUTOK_VCO_OFST (24) +#define RG_SSUSB_PLL_PWD_OFST (23) +#define RG_SSUSB_RX_AFE_PWD_OFST (22) +#define RG_SSUSB_PLL_TCADJ_OFST (16) +#define RG_SSUSB_FORCE_CDR_TCADJ_OFST (15) +#define RG_SSUSB_FORCE_CDR_AUTOK_VCO_OFST (14) +#define RG_SSUSB_FORCE_CDR_PWD_OFST (13) +#define RG_SSUSB_FORCE_PLL_NCPO_EN_OFST (12) +#define RG_SSUSB_FORCE_PLL_FIFO_START_MAN_OFST (11) +#define RG_SSUSB_FORCE_PLL_NCPO_CHG_OFST (9) +#define RG_SSUSB_FORCE_PLL_DDS_RSTB_OFST (8) +#define RG_SSUSB_FORCE_PLL_DDS_PWDB_OFST (7) +#define RG_SSUSB_FORCE_PLL_DDSEN_OFST (6) +#define RG_SSUSB_FORCE_PLL_TCADJ_OFST (5) +#define RG_SSUSB_FORCE_PLL_AUTOK_VCO_OFST (4) +#define RG_SSUSB_FORCE_PLL_PWD_OFST (3) +#define RG_SSUSB_FLT_1_DISPERR_B_OFST (2) + +/* U3D_PHYD_TXPLL2 */ +#define RG_SSUSB_TX_LFPS_EN_OFST (31) +#define RG_SSUSB_FORCE_TX_LFPS_EN_OFST (30) +#define RG_SSUSB_TX_LFPS_OFST (29) +#define RG_SSUSB_FORCE_TX_LFPS_OFST (28) +#define RG_SSUSB_RXPLL_STB_OFST (27) +#define RG_SSUSB_TXPLL_STB_OFST (26) +#define RG_SSUSB_FORCE_RXPLL_STB_OFST (25) +#define RG_SSUSB_FORCE_TXPLL_STB_OFST (24) +#define RG_SSUSB_RXPLL_REFCKSEL_OFST (16) +#define RG_SSUSB_RXPLL_STBMODE_OFST (11) +#define RG_SSUSB_RXPLL_ON_OFST (10) +#define RG_SSUSB_FORCE_RXPLLON_OFST (9) +#define RG_SSUSB_FORCE_RX_AFE_PWD_OFST (8) +#define RG_SSUSB_CDR_AUTOK_VCO_OFST (7) +#define RG_SSUSB_CDR_PWD_OFST (6) +#define RG_SSUSB_CDR_TCADJ_OFST (0) + +/* U3D_PHYD_FL0 */ +#define RG_SSUSB_RX_FL_TARGET_OFST (16) +#define RG_SSUSB_RX_FL_CYCLECNT_OFST (0) + +/* U3D_PHYD_MIX2 */ +#define RG_SSUSB_RX_EQ_RST_OFST (31) +#define RG_SSUSB_RX_EQ_RST_SEL_OFST (30) +#define RG_SSUSB_RXVAL_RST_OFST (29) +#define RG_SSUSB_RXVAL_CNT_OFST (24) +#define RG_SSUSB_CDROS_EN_OFST (18) +#define RG_SSUSB_CDR_LCKOP_OFST (16) +#define RG_SSUSB_RX_FL_LOCKTH_OFST (8) +#define RG_SSUSB_RX_FL_OFFSET_OFST (0) + +/* U3D_PHYD_RX0 */ +#define RG_SSUSB_T2RLB_BERTH_OFST (24) +#define RG_SSUSB_T2RLB_PAT_OFST (16) +#define RG_SSUSB_T2RLB_EN_OFST (15) +#define RG_SSUSB_T2RLB_BPSCRAMB_OFST (14) +#define RG_SSUSB_T2RLB_SERIAL_OFST (13) +#define RG_SSUSB_T2RLB_MODE_OFST (11) +#define RG_SSUSB_RX_SAOSC_EN_OFST (10) +#define RG_SSUSB_RX_SAOSC_EN_SEL_OFST (9) +#define RG_SSUSB_RX_DFE_OPTION_OFST (8) +#define RG_SSUSB_RX_DFE_EN_OFST (7) +#define RG_SSUSB_RX_DFE_EN_SEL_OFST (6) +#define RG_SSUSB_RX_EQ_EN_OFST (5) +#define RG_SSUSB_RX_EQ_EN_SEL_OFST (4) +#define RG_SSUSB_RX_SAOSC_RST_OFST (3) +#define RG_SSUSB_RX_SAOSC_RST_SEL_OFST (2) +#define RG_SSUSB_RX_DFE_RST_OFST (1) +#define RG_SSUSB_RX_DFE_RST_SEL_OFST (0) + +/* U3D_PHYD_T2RLB */ +#define RG_SSUSB_EQTRAIN_CH_MODE_OFST (28) +#define RG_SSUSB_PRB_OUT_CPPAT_OFST (27) +#define RG_SSUSB_BPANSIENC_OFST (26) +#define RG_SSUSB_VALID_EN_OFST (25) +#define RG_SSUSB_EBUF_SRST_OFST (24) +#define RG_SSUSB_K_EMP_OFST (20) +#define RG_SSUSB_K_FUL_OFST (16) +#define RG_SSUSB_T2RLB_BDATRST_OFST (12) +#define RG_SSUSB_P_T2RLB_SKP_EN_OFST (10) +#define RG_SSUSB_T2RLB_PATMODE_OFST (8) +#define RG_SSUSB_T2RLB_TSEQCNT_OFST (0) + +/* U3D_PHYD_CPPAT */ +#define RG_SSUSB_CPPAT_PROGRAM_EN_OFST (24) +#define RG_SSUSB_CPPAT_TOZ_OFST (21) +#define RG_SSUSB_CPPAT_PRBS_EN_OFST (20) +#define RG_SSUSB_CPPAT_OUT_TMP2_OFST (16) +#define RG_SSUSB_CPPAT_OUT_TMP1_OFST (8) +#define RG_SSUSB_CPPAT_OUT_TMP0_OFST (0) + +/* U3D_PHYD_MIX3 */ +#define RG_SSUSB_CDR_TCADJ_MINUS_OFST (31) +#define RG_SSUSB_P_CDROS_EN_OFST (30) +#define RG_SSUSB_P_P2_TX_DRV_DIS_OFST (28) +#define RG_SSUSB_CDR_TCADJ_OFFSET_OFST (24) +#define RG_SSUSB_PLL_TCADJ_MINUS_OFST (23) +#define RG_SSUSB_FORCE_PLL_BIAS_LPF_EN_OFST (20) +#define RG_SSUSB_PLL_BIAS_LPF_EN_OFST (19) +#define RG_SSUSB_PLL_TCADJ_OFFSET_OFST (16) +#define RG_SSUSB_FORCE_PLL_SSCEN_OFST (15) +#define RG_SSUSB_PLL_SSCEN_OFST (14) +#define RG_SSUSB_FORCE_CDR_PI_PWD_OFST (13) +#define RG_SSUSB_CDR_PI_PWD_OFST (12) +#define RG_SSUSB_CDR_PI_MODE_OFST (11) +#define RG_SSUSB_TXPLL_SSCEN_CYC_OFST (0) + +/* U3D_PHYD_EBUFCTL */ +#define RG_SSUSB_EBUFCTL_OFST (0) + +/* U3D_PHYD_PIPE0 */ +#define RG_SSUSB_RXTERMINATION_OFST (30) +#define RG_SSUSB_RXEQTRAINING_OFST (29) +#define RG_SSUSB_RXPOLARITY_OFST (28) +#define RG_SSUSB_TXDEEMPH_OFST (26) +#define RG_SSUSB_POWERDOWN_OFST (24) +#define RG_SSUSB_TXONESZEROS_OFST (23) +#define RG_SSUSB_TXELECIDLE_OFST (22) +#define RG_SSUSB_TXDETECTRX_OFST (21) +#define RG_SSUSB_PIPE_SEL_OFST (20) +#define RG_SSUSB_TXDATAK_OFST (16) +#define RG_SSUSB_CDR_STABLE_SEL_OFST (15) +#define RG_SSUSB_CDR_STABLE_OFST (14) +#define RG_SSUSB_CDR_RSTB_SEL_OFST (13) +#define RG_SSUSB_CDR_RSTB_OFST (12) +#define RG_SSUSB_FRC_PIPE_POWERDOWN_OFST (11) +#define RG_SSUSB_P_TXBCN_DIS_OFST (6) +#define RG_SSUSB_P_ERROR_SEL_OFST (4) +#define RG_SSUSB_TXMARGIN_OFST (1) +#define RG_SSUSB_TXCOMPLIANCE_OFST (0) + +/* U3D_PHYD_PIPE1 */ +#define RG_SSUSB_TXDATA_OFST (0) + +/* U3D_PHYD_MIX4 */ +#define RG_SSUSB_CDROS_CNT_OFST (24) +#define RG_SSUSB_T2RLB_BER_EN_OFST (16) +#define RG_SSUSB_T2RLB_BER_RATE_OFST (0) + +/* U3D_PHYD_CKGEN0 */ +#define RG_SSUSB_RFIFO_IMPLAT_OFST (27) +#define RG_SSUSB_TFIFO_PSEL_OFST (24) +#define RG_SSUSB_CKGEN_PSEL_OFST (8) +#define RG_SSUSB_RXCK_INV_OFST (0) + +/* U3D_PHYD_MIX5 */ +#define RG_SSUSB_PRB_SEL_OFST (16) +#define RG_SSUSB_RXPLL_STBCYC_OFST (0) + +/* U3D_PHYD_RESERVED */ +#define RG_SSUSB_PHYD_RESERVE_OFST (0) + +/* U3D_PHYD_CDR0 */ +#define RG_SSUSB_CDR_BIC_LTR_OFST (28) +#define RG_SSUSB_CDR_BIC_LTD0_OFST (24) +#define RG_SSUSB_CDR_BC_LTD1_OFST (16) +#define RG_SSUSB_CDR_BC_LTR_OFST (8) +#define RG_SSUSB_CDR_BC_LTD0_OFST (0) + +/* U3D_PHYD_CDR1 */ +#define RG_SSUSB_CDR_BIR_LTD1_OFST (24) +#define RG_SSUSB_CDR_BIR_LTR_OFST (16) +#define RG_SSUSB_CDR_BIR_LTD0_OFST (8) +#define RG_SSUSB_CDR_BW_SEL_OFST (6) +#define RG_SSUSB_CDR_BIC_LTD1_OFST (0) + +/* U3D_PHYD_PLL_0 */ +#define RG_SSUSB_FORCE_CDR_BAND_5G_OFST (28) +#define RG_SSUSB_FORCE_CDR_BAND_2P5G_OFST (27) +#define RG_SSUSB_FORCE_PLL_BAND_5G_OFST (26) +#define RG_SSUSB_FORCE_PLL_BAND_2P5G_OFST (25) +#define RG_SSUSB_P_EQ_T_SEL_OFST (15) +#define RG_SSUSB_PLL_ISO_EN_CYC_OFST (5) +#define RG_SSUSB_PLLBAND_RECAL_OFST (4) +#define RG_SSUSB_PLL_DDS_ISO_EN_OFST (3) +#define RG_SSUSB_FORCE_PLL_DDS_ISO_EN_OFST (2) +#define RG_SSUSB_PLL_DDS_PWR_ON_OFST (1) +#define RG_SSUSB_FORCE_PLL_DDS_PWR_ON_OFST (0) + +/* U3D_PHYD_PLL_1 */ +#define RG_SSUSB_CDR_BAND_5G_OFST (24) +#define RG_SSUSB_CDR_BAND_2P5G_OFST (16) +#define RG_SSUSB_PLL_BAND_5G_OFST (8) +#define RG_SSUSB_PLL_BAND_2P5G_OFST (0) + +/* U3D_PHYD_BCN_DET_1 */ +#define RG_SSUSB_P_BCN_OBS_PRD_OFST (16) +#define RG_SSUSB_U_BCN_OBS_PRD_OFST (0) + +/* U3D_PHYD_BCN_DET_2 */ +#define RG_SSUSB_P_BCN_OBS_SEL_OFST (16) +#define RG_SSUSB_BCN_DET_DIS_OFST (12) +#define RG_SSUSB_U_BCN_OBS_SEL_OFST (0) + +/* U3D_EQ0 */ +#define RG_SSUSB_EQ_DLHL_LFI_OFST (24) +#define RG_SSUSB_EQ_DHHL_LFI_OFST (16) +#define RG_SSUSB_EQ_DD0HOS_LFI_OFST (8) +#define RG_SSUSB_EQ_DD0LOS_LFI_OFST (0) + +/* U3D_EQ1 */ +#define RG_SSUSB_EQ_DD1HOS_LFI_OFST (24) +#define RG_SSUSB_EQ_DD1LOS_LFI_OFST (16) +#define RG_SSUSB_EQ_DE0OS_LFI_OFST (8) +#define RG_SSUSB_EQ_DE1OS_LFI_OFST (0) + +/* U3D_EQ2 */ +#define RG_SSUSB_EQ_DLHLOS_LFI_OFST (24) +#define RG_SSUSB_EQ_DHHLOS_LFI_OFST (16) +#define RG_SSUSB_EQ_STOPTIME_OFST (14) +#define RG_SSUSB_EQ_DHHL_LF_SEL_OFST (11) +#define RG_SSUSB_EQ_DSAOS_LF_SEL_OFST (8) +#define RG_SSUSB_EQ_STARTTIME_OFST (6) +#define RG_SSUSB_EQ_DLEQ_LF_SEL_OFST (3) +#define RG_SSUSB_EQ_DLHL_LF_SEL_OFST (0) + +/* U3D_EQ3 */ +#define RG_SSUSB_EQ_DLEQ_LFI_GEN2_OFST (28) +#define RG_SSUSB_EQ_DLEQ_LFI_GEN1_OFST (24) +#define RG_SSUSB_EQ_DEYE0OS_LFI_OFST (16) +#define RG_SSUSB_EQ_DEYE1OS_LFI_OFST (8) +#define RG_SSUSB_EQ_TRI_DET_EN_OFST (7) +#define RG_SSUSB_EQ_TRI_DET_TH_OFST (0) + +/* U3D_EQ_EYE0 */ +#define RG_SSUSB_EQ_EYE_XOFFSET_OFST (25) +#define RG_SSUSB_EQ_EYE_MON_EN_OFST (24) +#define RG_SSUSB_EQ_EYE0_Y_OFST (16) +#define RG_SSUSB_EQ_EYE1_Y_OFST (8) +#define RG_SSUSB_EQ_PILPO_ROUT_OFST (7) +#define RG_SSUSB_EQ_PI_KPGAIN_OFST (4) +#define RG_SSUSB_EQ_EYE_CNT_EN_OFST (3) + +/* U3D_EQ_EYE1 */ +#define RG_SSUSB_EQ_SIGDET_OFST (24) +#define RG_SSUSB_EQ_EYE_MASK_OFST (7) + +/* U3D_EQ_EYE2 */ +#define RG_SSUSB_EQ_RX500M_CK_SEL_OFST (31) +#define RG_SSUSB_EQ_SD_CNT1_OFST (24) +#define RG_SSUSB_EQ_ISIFLAG_SEL_OFST (22) +#define RG_SSUSB_EQ_SD_CNT0_OFST (16) + +/* U3D_EQ_DFE0 */ +#define RG_SSUSB_EQ_LEQMAX_OFST (28) +#define RG_SSUSB_EQ_DFEX_EN_OFST (27) +#define RG_SSUSB_EQ_DFEX_LF_SEL_OFST (24) +#define RG_SSUSB_EQ_CHK_EYE_H_OFST (23) +#define RG_SSUSB_EQ_PIEYE_INI_OFST (16) +#define RG_SSUSB_EQ_PI90_INI_OFST (8) +#define RG_SSUSB_EQ_PI0_INI_OFST (0) + +/* U3D_EQ_DFE1 */ +#define RG_SSUSB_EQ_REV_OFST (16) +#define RG_SSUSB_EQ_DFEYEN_DUR_OFST (12) +#define RG_SSUSB_EQ_DFEXEN_DUR_OFST (8) +#define RG_SSUSB_EQ_DFEX_RST_OFST (7) +#define RG_SSUSB_EQ_GATED_RXD_B_OFST (6) +#define RG_SSUSB_EQ_PI90CK_SEL_OFST (4) +#define RG_SSUSB_EQ_DFEX_DIS_OFST (2) +#define RG_SSUSB_EQ_DFEYEN_STOP_DIS_OFST (1) +#define RG_SSUSB_EQ_DFEXEN_SEL_OFST (0) + +/* U3D_EQ_DFE2 */ +#define RG_SSUSB_EQ_MON_SEL_OFST (24) +#define RG_SSUSB_EQ_LEQOSC_DLYCNT_OFST (16) +#define RG_SSUSB_EQ_DLEQOS_LFI_OFST (8) +#define RG_SSUSB_EQ_DFE_TOG_OFST (2) +#define RG_SSUSB_EQ_LEQ_STOP_TO_OFST (0) + +/* U3D_EQ_DFE3 */ +#define RG_SSUSB_EQ_RESERVED_OFST (0) + +/* U3D_PHYD_MON0 */ +#define RGS_SSUSB_BERT_BERC_OFST (16) +#define RGS_SSUSB_LFPS_OFST (12) +#define RGS_SSUSB_TRAINDEC_OFST (8) +#define RGS_SSUSB_SCP_PAT_OFST (0) + +/* U3D_PHYD_MON1 */ +#define RGS_SSUSB_RX_FL_OUT_OFST (0) + +/* U3D_PHYD_MON2 */ +#define RGS_SSUSB_T2RLB_ERRCNT_OFST (16) +#define RGS_SSUSB_RETRACK_OFST (12) +#define RGS_SSUSB_RXPLL_LOCK_OFST (10) +#define RGS_SSUSB_CDR_VCOCAL_CPLT_D_OFST (9) +#define RGS_SSUSB_PLL_VCOCAL_CPLT_D_OFST (8) +#define RGS_SSUSB_PDNCTL_OFST (0) + +/* U3D_PHYD_MON3 */ +#define RGS_SSUSB_TSEQ_ERRCNT_OFST (16) +#define RGS_SSUSB_PRBS_ERRCNT_OFST (0) + +/* U3D_PHYD_MON4 */ +#define RGS_SSUSB_RX_LSLOCK_CNT_OFST (24) +#define RGS_SSUSB_SCP_DETCNT_OFST (16) +#define RGS_SSUSB_TSEQ_DETCNT_OFST (0) + +/* U3D_PHYD_MON5 */ +#define RGS_SSUSB_EBUFMSG_OFST (16) +#define RGS_SSUSB_BERT_LOCK_OFST (15) +#define RGS_SSUSB_SCP_DET_OFST (14) +#define RGS_SSUSB_TSEQ_DET_OFST (13) +#define RGS_SSUSB_EBUF_UDF_OFST (12) +#define RGS_SSUSB_EBUF_OVF_OFST (11) +#define RGS_SSUSB_PRBS_PASSTH_OFST (10) +#define RGS_SSUSB_PRBS_PASS_OFST (9) +#define RGS_SSUSB_PRBS_LOCK_OFST (8) +#define RGS_SSUSB_T2RLB_ERR_OFST (6) +#define RGS_SSUSB_T2RLB_PASSTH_OFST (5) +#define RGS_SSUSB_T2RLB_PASS_OFST (4) +#define RGS_SSUSB_T2RLB_LOCK_OFST (3) +#define RGS_SSUSB_RX_IMPCAL_DONE_OFST (2) +#define RGS_SSUSB_TX_IMPCAL_DONE_OFST (1) +#define RGS_SSUSB_RXDETECTED_OFST (0) + +/* U3D_PHYD_MON6 */ +#define RGS_SSUSB_SIGCAL_DONE_OFST (30) +#define RGS_SSUSB_SIGCAL_CAL_OUT_OFST (29) +#define RGS_SSUSB_SIGCAL_OFFSET_OFST (24) +#define RGS_SSUSB_RX_IMP_SEL_OFST (16) +#define RGS_SSUSB_TX_IMP_SEL_OFST (8) +#define RGS_SSUSB_TFIFO_MSG_OFST (4) +#define RGS_SSUSB_RFIFO_MSG_OFST (0) + +/* U3D_PHYD_MON7 */ +#define RGS_SSUSB_FT_OUT_OFST (8) +#define RGS_SSUSB_PRB_OUT_OFST (0) + +/* U3D_PHYA_RX_MON0 */ +#define RGS_SSUSB_EQ_DCLEQ_OFST (24) +#define RGS_SSUSB_EQ_DCD0H_OFST (16) +#define RGS_SSUSB_EQ_DCD0L_OFST (8) +#define RGS_SSUSB_EQ_DCD1H_OFST (0) + +/* U3D_PHYA_RX_MON1 */ +#define RGS_SSUSB_EQ_DCD1L_OFST (24) +#define RGS_SSUSB_EQ_DCE0_OFST (16) +#define RGS_SSUSB_EQ_DCE1_OFST (8) +#define RGS_SSUSB_EQ_DCHHL_OFST (0) + +/* U3D_PHYA_RX_MON2 */ +#define RGS_SSUSB_EQ_LEQ_STOP_OFST (31) +#define RGS_SSUSB_EQ_DCLHL_OFST (24) +#define RGS_SSUSB_EQ_STATUS_OFST (16) +#define RGS_SSUSB_EQ_DCEYE0_OFST (8) +#define RGS_SSUSB_EQ_DCEYE1_OFST (0) + +/* U3D_PHYA_RX_MON3 */ +#define RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_0_OFST (0) + +/* U3D_PHYA_RX_MON4 */ +#define RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_1_OFST (0) + +/* U3D_PHYA_RX_MON5 */ +#define RGS_SSUSB_EQ_DCLEQOS_OFST (8) +#define RGS_SSUSB_EQ_EYE_CNT_RDY_OFST (7) +#define RGS_SSUSB_EQ_PILPO_OFST (0) + +/* U3D_PHYD_CPPAT2 */ +#define RG_SSUSB_CPPAT_OUT_H_TMP2_OFST (16) +#define RG_SSUSB_CPPAT_OUT_H_TMP1_OFST (8) +#define RG_SSUSB_CPPAT_OUT_H_TMP0_OFST (0) + +/* U3D_EQ_EYE3 */ +#define RG_SSUSB_EQ_LEQ_SHIFT_OFST (24) +#define RG_SSUSB_EQ_EYE_CNT_OFST (0) + +/* U3D_KBAND_OUT */ +#define RGS_SSUSB_CDR_BAND_5G_OFST (24) +#define RGS_SSUSB_CDR_BAND_2P5G_OFST (16) +#define RGS_SSUSB_PLL_BAND_5G_OFST (8) +#define RGS_SSUSB_PLL_BAND_2P5G_OFST (0) + +/* U3D_KBAND_OUT1 */ +#define RGS_SSUSB_CDR_VCOCAL_FAIL_OFST (24) +#define RGS_SSUSB_CDR_VCOCAL_STATE_OFST (16) +#define RGS_SSUSB_PLL_VCOCAL_FAIL_OFST (8) +#define RGS_SSUSB_PLL_VCOCAL_STATE_OFST (0) + +/* ///////////////////////////////////////////////////////////////////////////// */ + +struct u3phyd_bank2_reg_e { + /* 0x0 */ + PHY_LE32 b2_phyd_top1; + PHY_LE32 b2_phyd_top2; + PHY_LE32 b2_phyd_top3; + PHY_LE32 b2_phyd_top4; + /* 0x10 */ + PHY_LE32 b2_phyd_top5; + PHY_LE32 b2_phyd_top6; + PHY_LE32 b2_phyd_top7; + PHY_LE32 b2_phyd_p_sigdet1; + /* 0x20 */ + PHY_LE32 b2_phyd_p_sigdet2; + PHY_LE32 b2_phyd_p_sigdet_cal1; + PHY_LE32 b2_phyd_rxdet1; + PHY_LE32 b2_phyd_rxdet2; + /* 0x30 */ + PHY_LE32 b2_phyd_misc0; + PHY_LE32 b2_phyd_misc2; + PHY_LE32 b2_phyd_misc3; + PHY_LE32 b2_phyd_l1ss; + /* 0x40 */ + PHY_LE32 b2_rosc_0; + PHY_LE32 b2_rosc_1; + PHY_LE32 b2_rosc_2; + PHY_LE32 b2_rosc_3; + /* 0x50 */ + PHY_LE32 b2_rosc_4; + PHY_LE32 b2_rosc_5; + PHY_LE32 b2_rosc_6; + PHY_LE32 b2_rosc_7; + /* 0x60 */ + PHY_LE32 b2_rosc_8; + PHY_LE32 b2_rosc_9; + PHY_LE32 b2_rosc_a; + PHY_LE32 reserve1; + /* 0x70~0xd0 */ + PHY_LE32 reserve2[28]; + /* 0xe0 */ + PHY_LE32 phyd_version; + PHY_LE32 phyd_model; +}; + +/* U3D_B2_PHYD_TOP1 */ +#define RG_SSUSB_PCIE2_K_EMP (0xf<<28) /* 31:28 */ +#define RG_SSUSB_PCIE2_K_FUL (0xf<<24) /* 27:24 */ +#define RG_SSUSB_TX_EIDLE_LP_EN (0x1<<17) /* 17:17 */ +#define RG_SSUSB_FORCE_TX_EIDLE_LP_EN (0x1<<16) /* 16:16 */ +#define RG_SSUSB_SIGDET_EN (0x1<<15) /* 15:15 */ +#define RG_SSUSB_FORCE_SIGDET_EN (0x1<<14) /* 14:14 */ +#define RG_SSUSB_CLKRX_EN (0x1<<13) /* 13:13 */ +#define RG_SSUSB_FORCE_CLKRX_EN (0x1<<12) /* 12:12 */ +#define RG_SSUSB_CLKTX_EN (0x1<<11) /* 11:11 */ +#define RG_SSUSB_FORCE_CLKTX_EN (0x1<<10) /* 10:10 */ +#define RG_SSUSB_CLK_REQ_N_I (0x1<<9) /* 9:9 */ +#define RG_SSUSB_FORCE_CLK_REQ_N_I (0x1<<8) /* 8:8 */ +#define RG_SSUSB_RATE (0x1<<6) /* 6:6 */ +#define RG_SSUSB_FORCE_RATE (0x1<<5) /* 5:5 */ +#define RG_SSUSB_PCIE_MODE_SEL (0x1<<4) /* 4:4 */ +#define RG_SSUSB_FORCE_PCIE_MODE_SEL (0x1<<3) /* 3:3 */ +#define RG_SSUSB_PHY_MODE (0x3<<1) /* 2:1 */ +#define RG_SSUSB_FORCE_PHY_MODE (0x1<<0) /* 0:0 */ + +/* U3D_B2_PHYD_TOP2 */ +#define RG_SSUSB_FORCE_IDRV_6DB (0x1<<30) /* 30:30 */ +#define RG_SSUSB_IDRV_6DB (0x3f<<24) /* 29:24 */ +#define RG_SSUSB_FORCE_IDEM_3P5DB (0x1<<22) /* 22:22 */ +#define RG_SSUSB_IDEM_3P5DB (0x3f<<16) /* 21:16 */ +#define RG_SSUSB_FORCE_IDRV_3P5DB (0x1<<14) /* 14:14 */ +#define RG_SSUSB_IDRV_3P5DB (0x3f<<8) /* 13:8 */ +#define RG_SSUSB_FORCE_IDRV_0DB (0x1<<6) /* 6:6 */ +#define RG_SSUSB_IDRV_0DB (0x3f<<0) /* 5:0 */ + +/* U3D_B2_PHYD_TOP3 */ +#define RG_SSUSB_TX_BIASI (0x7<<25) /* 27:25 */ +#define RG_SSUSB_FORCE_TX_BIASI_EN (0x1<<24) /* 24:24 */ +#define RG_SSUSB_TX_BIASI_EN (0x1<<16) /* 16:16 */ +#define RG_SSUSB_FORCE_TX_BIASI (0x1<<13) /* 13:13 */ +#define RG_SSUSB_FORCE_IDEM_6DB (0x1<<8) /* 8:8 */ +#define RG_SSUSB_IDEM_6DB (0x3f<<0) /* 5:0 */ + +/* U3D_B2_PHYD_TOP4 */ +#define RG_SSUSB_G1_CDR_BIC_LTR (0xf<<28) /* 31:28 */ +#define RG_SSUSB_G1_CDR_BIC_LTD0 (0xf<<24) /* 27:24 */ +#define RG_SSUSB_G1_CDR_BC_LTD1 (0x1f<<16) /* 20:16 */ +#define RG_SSUSB_G1_L1SS_CDR_BW_SEL (0x3<<13) /* 14:13 */ +#define RG_SSUSB_G1_CDR_BC_LTR (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_G1_CDR_BW_SEL (0x3<<5) /* 6:5 */ +#define RG_SSUSB_G1_CDR_BC_LTD0 (0x1f<<0) /* 4:0 */ + +/* U3D_B2_PHYD_TOP5 */ +#define RG_SSUSB_G1_CDR_BIR_LTD1 (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_G1_CDR_BIR_LTR (0x1f<<16) /* 20:16 */ +#define RG_SSUSB_G1_CDR_BIR_LTD0 (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_G1_CDR_BIC_LTD1 (0xf<<0) /* 3:0 */ + +/* U3D_B2_PHYD_TOP6 */ +#define RG_SSUSB_G2_CDR_BIC_LTR (0xf<<28) /* 31:28 */ +#define RG_SSUSB_G2_CDR_BIC_LTD0 (0xf<<24) /* 27:24 */ +#define RG_SSUSB_G2_CDR_BC_LTD1 (0x1f<<16) /* 20:16 */ +#define RG_SSUSB_G2_L1SS_CDR_BW_SEL (0x3<<13) /* 14:13 */ +#define RG_SSUSB_G2_CDR_BC_LTR (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_G2_CDR_BW_SEL (0x3<<5) /* 6:5 */ +#define RG_SSUSB_G2_CDR_BC_LTD0 (0x1f<<0) /* 4:0 */ + +/* U3D_B2_PHYD_TOP7 */ +#define RG_SSUSB_G2_CDR_BIR_LTD1 (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_G2_CDR_BIR_LTR (0x1f<<16) /* 20:16 */ +#define RG_SSUSB_G2_CDR_BIR_LTD0 (0x1f<<8) /* 12:8 */ +#define RG_SSUSB_G2_CDR_BIC_LTD1 (0xf<<0) /* 3:0 */ + +/* U3D_B2_PHYD_P_SIGDET1 */ +#define RG_SSUSB_P_SIGDET_FLT_DIS (0x1<<31) /* 31:31 */ +#define RG_SSUSB_P_SIGDET_FLT_G2_DEAST_SEL (0x7f<<24) /* 30:24 */ +#define RG_SSUSB_P_SIGDET_FLT_G1_DEAST_SEL (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_P_SIGDET_FLT_P2_AST_SEL (0x7f<<8) /* 14:8 */ +#define RG_SSUSB_P_SIGDET_FLT_PX_AST_SEL (0x7f<<0) /* 6:0 */ + +/* U3D_B2_PHYD_P_SIGDET2 */ +#define RG_SSUSB_P_SIGDET_RX_VAL_S (0x1<<29) /* 29:29 */ +#define RG_SSUSB_P_SIGDET_L0S_DEAS_SEL (0x1<<28) /* 28:28 */ +#define RG_SSUSB_P_SIGDET_L0_EXIT_S (0x1<<27) /* 27:27 */ +#define RG_SSUSB_P_SIGDET_L0S_EXIT_T_S (0x3<<25) /* 26:25 */ +#define RG_SSUSB_P_SIGDET_L0S_EXIT_S (0x1<<24) /* 24:24 */ +#define RG_SSUSB_P_SIGDET_L0S_ENTRY_S (0x1<<16) /* 16:16 */ +#define RG_SSUSB_P_SIGDET_PRB_SEL (0x1<<10) /* 10:10 */ +#define RG_SSUSB_P_SIGDET_BK_SIG_T (0x3<<8) /* 9:8 */ +#define RG_SSUSB_P_SIGDET_P2_RXLFPS (0x1<<6) /* 6:6 */ +#define RG_SSUSB_P_SIGDET_NON_BK_AD (0x1<<5) /* 5:5 */ +#define RG_SSUSB_P_SIGDET_BK_B_RXEQ (0x1<<4) /* 4:4 */ +#define RG_SSUSB_P_SIGDET_G2_KO_SEL (0x3<<2) /* 3:2 */ +#define RG_SSUSB_P_SIGDET_G1_KO_SEL (0x3<<0) /* 1:0 */ + +/* U3D_B2_PHYD_P_SIGDET_CAL1 */ +#define RG_SSUSB_G2_2EIOS_DET_EN (0x1<<29) /* 29:29 */ +#define RG_SSUSB_P_SIGDET_CAL_OFFSET (0x1f<<24) /* 28:24 */ +#define RG_SSUSB_P_FORCE_SIGDET_CAL_OFFSET (0x1<<16) /* 16:16 */ +#define RG_SSUSB_P_SIGDET_CAL_EN (0x1<<8) /* 8:8 */ +#define RG_SSUSB_P_FORCE_SIGDET_CAL_EN (0x1<<3) /* 3:3 */ +#define RG_SSUSB_P_SIGDET_FLT_EN (0x1<<2) /* 2:2 */ +#define RG_SSUSB_P_SIGDET_SAMPLE_PRD (0x1<<1) /* 1:1 */ +#define RG_SSUSB_P_SIGDET_REK (0x1<<0) /* 0:0 */ + +/* U3D_B2_PHYD_RXDET1 */ +#define RG_SSUSB_RXDET_PRB_SEL (0x1<<31) /* 31:31 */ +#define RG_SSUSB_FORCE_CMDET (0x1<<30) /* 30:30 */ +#define RG_SSUSB_RXDET_EN (0x1<<29) /* 29:29 */ +#define RG_SSUSB_FORCE_RXDET_EN (0x1<<28) /* 28:28 */ +#define RG_SSUSB_RXDET_K_TWICE (0x1<<27) /* 27:27 */ +#define RG_SSUSB_RXDET_STB3_SET (0x1ff<<18) /* 26:18 */ +#define RG_SSUSB_RXDET_STB2_SET (0x1ff<<9) /* 17:9 */ +#define RG_SSUSB_RXDET_STB1_SET (0x1ff<<0) /* 8:0 */ + +/* U3D_B2_PHYD_RXDET2 */ +#define RG_SSUSB_PHYD_TRAINDEC_FORCE_CGEN (0x1<<31) /* 31:31 */ +#define RG_SSUSB_PHYD_BERTLB_FORCE_CGEN (0x1<<30) /* 30:30 */ +#define RG_SSUSB_PHYD_T2RLB_FORCE_CGEN (0x1<<29) /* 29:29 */ +#define RG_SSUSB_LCK2REF_EXT_EN (0x1<<28) /* 28:28 */ +#define RG_SSUSB_G2_LCK2REF_EXT_SEL (0xf<<24) /* 27:24 */ +#define RG_SSUSB_LCK2REF_EXT_SEL (0xf<<20) /* 23:20 */ +#define RG_SSUSB_PDN_T_SEL (0x3<<18) /* 19:18 */ +#define RG_SSUSB_RXDET_STB3_SET_P3 (0x1ff<<9) /* 17:9 */ +#define RG_SSUSB_RXDET_STB2_SET_P3 (0x1ff<<0) /* 8:0 */ + +/* U3D_B2_PHYD_MISC0 */ +#define RG_SSUSB_TX_EIDLE_LP_P0DLYCYC (0x3f<<26) /* 31:26 */ +#define RG_SSUSB_TX_SER_EN (0x1<<25) /* 25:25 */ +#define RG_SSUSB_FORCE_TX_SER_EN (0x1<<24) /* 24:24 */ +#define RG_SSUSB_TXPLL_REFCKSEL (0x1<<23) /* 23:23 */ +#define RG_SSUSB_FORCE_PLL_DDS_HF_EN (0x1<<22) /* 22:22 */ +#define RG_SSUSB_PLL_DDS_HF_EN_MAN (0x1<<21) /* 21:21 */ +#define RG_SSUSB_RXLFPS_ENTXDRV (0x1<<20) /* 20:20 */ +#define RG_SSUSB_RX_FL_UNLOCKTH (0xf<<16) /* 19:16 */ +#define RG_SSUSB_LFPS_PSEL (0x1<<15) /* 15:15 */ +#define RG_SSUSB_RX_SIGDET_EN (0x1<<14) /* 14:14 */ +#define RG_SSUSB_RX_SIGDET_EN_SEL (0x1<<13) /* 13:13 */ +#define RG_SSUSB_RX_PI_CAL_EN (0x1<<12) /* 12:12 */ +#define RG_SSUSB_RX_PI_CAL_EN_SEL (0x1<<11) /* 11:11 */ +#define RG_SSUSB_P3_CLS_CK_SEL (0x1<<10) /* 10:10 */ +#define RG_SSUSB_T2RLB_PSEL (0x3<<8) /* 9:8 */ +#define RG_SSUSB_PPCTL_PSEL (0x7<<5) /* 7:5 */ +#define RG_SSUSB_PHYD_TX_DATA_INV (0x1<<4) /* 4:4 */ +#define RG_SSUSB_BERTLB_PSEL (0x3<<2) /* 3:2 */ +#define RG_SSUSB_RETRACK_DIS (0x1<<1) /* 1:1 */ +#define RG_SSUSB_PPERRCNT_CLR (0x1<<0) /* 0:0 */ + +/* U3D_B2_PHYD_MISC2 */ +#define RG_SSUSB_FRC_PLL_DDS_PREDIV2 (0x1<<31) /* 31:31 */ +#define RG_SSUSB_FRC_PLL_DDS_IADJ (0xf<<27) /* 30:27 */ +#define RG_SSUSB_P_SIGDET_125FILTER (0x1<<26) /* 26:26 */ +#define RG_SSUSB_P_SIGDET_RST_FILTER (0x1<<25) /* 25:25 */ +#define RG_SSUSB_P_SIGDET_EID_USE_RAW (0x1<<24) /* 24:24 */ +#define RG_SSUSB_P_SIGDET_LTD_USE_RAW (0x1<<23) /* 23:23 */ +#define RG_SSUSB_EIDLE_BF_RXDET (0x1<<22) /* 22:22 */ +#define RG_SSUSB_EIDLE_LP_STBCYC (0x1ff<<13) /* 21:13 */ +#define RG_SSUSB_TX_EIDLE_LP_POSTDLY (0x3f<<7) /* 12:7 */ +#define RG_SSUSB_TX_EIDLE_LP_PREDLY (0x3f<<1) /* 6:1 */ +#define RG_SSUSB_TX_EIDLE_LP_EN_ADV (0x1<<0) /* 0:0 */ + +/* U3D_B2_PHYD_MISC3 */ +#define RGS_SSUSB_DDS_CALIB_C_STATE (0x7<<16) /* 18:16 */ +#define RGS_SSUSB_PPERRCNT (0xffff<<0) /* 15:0 */ + +/* U3D_B2_PHYD_L1SS */ +#define RG_SSUSB_L1SS_REV1 (0xff<<24) /* 31:24 */ +#define RG_SSUSB_L1SS_REV0 (0xff<<16) /* 23:16 */ +#define RG_SSUSB_P_LTD1_SLOCK_DIS (0x1<<11) /* 11:11 */ +#define RG_SSUSB_PLL_CNT_CLEAN_DIS (0x1<<10) /* 10:10 */ +#define RG_SSUSB_P_PLL_REK_SEL (0x1<<9) /* 9:9 */ +#define RG_SSUSB_TXDRV_MASKDLY (0x1<<8) /* 8:8 */ +#define RG_SSUSB_RXSTS_VAL (0x1<<7) /* 7:7 */ +#define RG_PCIE_PHY_CLKREQ_N_EN (0x1<<6) /* 6:6 */ +#define RG_PCIE_FORCE_PHY_CLKREQ_N_EN (0x1<<5) /* 5:5 */ +#define RG_PCIE_PHY_CLKREQ_N_OUT (0x1<<4) /* 4:4 */ +#define RG_PCIE_FORCE_PHY_CLKREQ_N_OUT (0x1<<3) /* 3:3 */ +#define RG_SSUSB_RXPLL_STB_PX0 (0x1<<2) /* 2:2 */ +#define RG_PCIE_L1SS_EN (0x1<<1) /* 1:1 */ +#define RG_PCIE_FORCE_L1SS_EN (0x1<<0) /* 0:0 */ + +/* U3D_B2_ROSC_0 */ +#define RG_SSUSB_RING_OSC_CNTEND (0x1ff<<23) /* 31:23 */ +#define RG_SSUSB_XTAL_OSC_CNTEND (0x7f<<16) /* 22:16 */ +#define RG_SSUSB_RING_OSC_EN (0x1<<3) /* 3:3 */ +#define RG_SSUSB_RING_OSC_FORCE_EN (0x1<<2) /* 2:2 */ +#define RG_SSUSB_FRC_RING_BYPASS_DET (0x1<<1) /* 1:1 */ +#define RG_SSUSB_RING_BYPASS_DET (0x1<<0) /* 0:0 */ + +/* U3D_B2_ROSC_1 */ +#define RG_SSUSB_RING_OSC_FRC_P3 (0x1<<20) /* 20:20 */ +#define RG_SSUSB_RING_OSC_P3 (0x1<<19) /* 19:19 */ +#define RG_SSUSB_RING_OSC_FRC_RECAL (0x3<<17) /* 18:17 */ +#define RG_SSUSB_RING_OSC_RECAL (0x1<<16) /* 16:16 */ +#define RG_SSUSB_RING_OSC_SEL (0xff<<8) /* 15:8 */ +#define RG_SSUSB_RING_OSC_FRC_SEL (0x1<<0) /* 0:0 */ + +/* U3D_B2_ROSC_2 */ +#define RG_SSUSB_RING_DET_STRCYC2 (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_RING_DET_STRCYC1 (0xffff<<0) /* 15:0 */ + +/* U3D_B2_ROSC_3 */ +#define RG_SSUSB_RING_DET_DETWIN1 (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_RING_DET_STRCYC3 (0xffff<<0) /* 15:0 */ + +/* U3D_B2_ROSC_4 */ +#define RG_SSUSB_RING_DET_DETWIN3 (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_RING_DET_DETWIN2 (0xffff<<0) /* 15:0 */ + +/* U3D_B2_ROSC_5 */ +#define RG_SSUSB_RING_DET_LBOND1 (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_RING_DET_UBOND1 (0xffff<<0) /* 15:0 */ + +/* U3D_B2_ROSC_6 */ +#define RG_SSUSB_RING_DET_LBOND2 (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_RING_DET_UBOND2 (0xffff<<0) /* 15:0 */ + +/* U3D_B2_ROSC_7 */ +#define RG_SSUSB_RING_DET_LBOND3 (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_RING_DET_UBOND3 (0xffff<<0) /* 15:0 */ + +/* U3D_B2_ROSC_8 */ +#define RG_SSUSB_RING_RESERVE (0xffff<<16) /* 31:16 */ +#define RG_SSUSB_ROSC_PROB_SEL (0xf<<2) /* 5:2 */ +#define RG_SSUSB_RING_FREQMETER_EN (0x1<<1) /* 1:1 */ +#define RG_SSUSB_RING_DET_BPS_UBOND (0x1<<0) /* 0:0 */ + +/* U3D_B2_ROSC_9 */ +#define RGS_FM_RING_CNT (0xffff<<16) /* 31:16 */ +#define RGS_SSUSB_RING_OSC_STATE (0x3<<10) /* 11:10 */ +#define RGS_SSUSB_RING_OSC_STABLE (0x1<<9) /* 9:9 */ +#define RGS_SSUSB_RING_OSC_CAL_FAIL (0x1<<8) /* 8:8 */ +#define RGS_SSUSB_RING_OSC_CAL (0xff<<0) /* 7:0 */ + +/* U3D_B2_ROSC_A */ +#define RGS_SSUSB_ROSC_PROB_OUT (0xff<<0) /* 7:0 */ + +/* U3D_PHYD_VERSION */ +#define RGS_SSUSB_PHYD_VERSION (0xffffffff<<0) /* 31:0 */ + +/* U3D_PHYD_MODEL */ +#define RGS_SSUSB_PHYD_MODEL (0xffffffff<<0) /* 31:0 */ + +/* OFFSET */ + +/* U3D_B2_PHYD_TOP1 */ +#define RG_SSUSB_PCIE2_K_EMP_OFST (28) +#define RG_SSUSB_PCIE2_K_FUL_OFST (24) +#define RG_SSUSB_TX_EIDLE_LP_EN_OFST (17) +#define RG_SSUSB_FORCE_TX_EIDLE_LP_EN_OFST (16) +#define RG_SSUSB_SIGDET_EN_OFST (15) +#define RG_SSUSB_FORCE_SIGDET_EN_OFST (14) +#define RG_SSUSB_CLKRX_EN_OFST (13) +#define RG_SSUSB_FORCE_CLKRX_EN_OFST (12) +#define RG_SSUSB_CLKTX_EN_OFST (11) +#define RG_SSUSB_FORCE_CLKTX_EN_OFST (10) +#define RG_SSUSB_CLK_REQ_N_I_OFST (9) +#define RG_SSUSB_FORCE_CLK_REQ_N_I_OFST (8) +#define RG_SSUSB_RATE_OFST (6) +#define RG_SSUSB_FORCE_RATE_OFST (5) +#define RG_SSUSB_PCIE_MODE_SEL_OFST (4) +#define RG_SSUSB_FORCE_PCIE_MODE_SEL_OFST (3) +#define RG_SSUSB_PHY_MODE_OFST (1) +#define RG_SSUSB_FORCE_PHY_MODE_OFST (0) + +/* U3D_B2_PHYD_TOP2 */ +#define RG_SSUSB_FORCE_IDRV_6DB_OFST (30) +#define RG_SSUSB_IDRV_6DB_OFST (24) +#define RG_SSUSB_FORCE_IDEM_3P5DB_OFST (22) +#define RG_SSUSB_IDEM_3P5DB_OFST (16) +#define RG_SSUSB_FORCE_IDRV_3P5DB_OFST (14) +#define RG_SSUSB_IDRV_3P5DB_OFST (8) +#define RG_SSUSB_FORCE_IDRV_0DB_OFST (6) +#define RG_SSUSB_IDRV_0DB_OFST (0) + +/* U3D_B2_PHYD_TOP3 */ +#define RG_SSUSB_TX_BIASI_OFST (25) +#define RG_SSUSB_FORCE_TX_BIASI_EN_OFST (24) +#define RG_SSUSB_TX_BIASI_EN_OFST (16) +#define RG_SSUSB_FORCE_TX_BIASI_OFST (13) +#define RG_SSUSB_FORCE_IDEM_6DB_OFST (8) +#define RG_SSUSB_IDEM_6DB_OFST (0) + +/* U3D_B2_PHYD_TOP4 */ +#define RG_SSUSB_G1_CDR_BIC_LTR_OFST (28) +#define RG_SSUSB_G1_CDR_BIC_LTD0_OFST (24) +#define RG_SSUSB_G1_CDR_BC_LTD1_OFST (16) +#define RG_SSUSB_G1_L1SS_CDR_BW_SEL_OFST (13) +#define RG_SSUSB_G1_CDR_BC_LTR_OFST (8) +#define RG_SSUSB_G1_CDR_BW_SEL_OFST (5) +#define RG_SSUSB_G1_CDR_BC_LTD0_OFST (0) + +/* U3D_B2_PHYD_TOP5 */ +#define RG_SSUSB_G1_CDR_BIR_LTD1_OFST (24) +#define RG_SSUSB_G1_CDR_BIR_LTR_OFST (16) +#define RG_SSUSB_G1_CDR_BIR_LTD0_OFST (8) +#define RG_SSUSB_G1_CDR_BIC_LTD1_OFST (0) + +/* U3D_B2_PHYD_TOP6 */ +#define RG_SSUSB_G2_CDR_BIC_LTR_OFST (28) +#define RG_SSUSB_G2_CDR_BIC_LTD0_OFST (24) +#define RG_SSUSB_G2_CDR_BC_LTD1_OFST (16) +#define RG_SSUSB_G2_L1SS_CDR_BW_SEL_OFST (13) +#define RG_SSUSB_G2_CDR_BC_LTR_OFST (8) +#define RG_SSUSB_G2_CDR_BW_SEL_OFST (5) +#define RG_SSUSB_G2_CDR_BC_LTD0_OFST (0) + +/* U3D_B2_PHYD_TOP7 */ +#define RG_SSUSB_G2_CDR_BIR_LTD1_OFST (24) +#define RG_SSUSB_G2_CDR_BIR_LTR_OFST (16) +#define RG_SSUSB_G2_CDR_BIR_LTD0_OFST (8) +#define RG_SSUSB_G2_CDR_BIC_LTD1_OFST (0) + +/* U3D_B2_PHYD_P_SIGDET1 */ +#define RG_SSUSB_P_SIGDET_FLT_DIS_OFST (31) +#define RG_SSUSB_P_SIGDET_FLT_G2_DEAST_SEL_OFST (24) +#define RG_SSUSB_P_SIGDET_FLT_G1_DEAST_SEL_OFST (16) +#define RG_SSUSB_P_SIGDET_FLT_P2_AST_SEL_OFST (8) +#define RG_SSUSB_P_SIGDET_FLT_PX_AST_SEL_OFST (0) + +/* U3D_B2_PHYD_P_SIGDET2 */ +#define RG_SSUSB_P_SIGDET_RX_VAL_S_OFST (29) +#define RG_SSUSB_P_SIGDET_L0S_DEAS_SEL_OFST (28) +#define RG_SSUSB_P_SIGDET_L0_EXIT_S_OFST (27) +#define RG_SSUSB_P_SIGDET_L0S_EXIT_T_S_OFST (25) +#define RG_SSUSB_P_SIGDET_L0S_EXIT_S_OFST (24) +#define RG_SSUSB_P_SIGDET_L0S_ENTRY_S_OFST (16) +#define RG_SSUSB_P_SIGDET_PRB_SEL_OFST (10) +#define RG_SSUSB_P_SIGDET_BK_SIG_T_OFST (8) +#define RG_SSUSB_P_SIGDET_P2_RXLFPS_OFST (6) +#define RG_SSUSB_P_SIGDET_NON_BK_AD_OFST (5) +#define RG_SSUSB_P_SIGDET_BK_B_RXEQ_OFST (4) +#define RG_SSUSB_P_SIGDET_G2_KO_SEL_OFST (2) +#define RG_SSUSB_P_SIGDET_G1_KO_SEL_OFST (0) + +/* U3D_B2_PHYD_P_SIGDET_CAL1 */ +#define RG_SSUSB_G2_2EIOS_DET_EN_OFST (29) +#define RG_SSUSB_P_SIGDET_CAL_OFFSET_OFST (24) +#define RG_SSUSB_P_FORCE_SIGDET_CAL_OFFSET_OFST (16) +#define RG_SSUSB_P_SIGDET_CAL_EN_OFST (8) +#define RG_SSUSB_P_FORCE_SIGDET_CAL_EN_OFST (3) +#define RG_SSUSB_P_SIGDET_FLT_EN_OFST (2) +#define RG_SSUSB_P_SIGDET_SAMPLE_PRD_OFST (1) +#define RG_SSUSB_P_SIGDET_REK_OFST (0) + +/* U3D_B2_PHYD_RXDET1 */ +#define RG_SSUSB_RXDET_PRB_SEL_OFST (31) +#define RG_SSUSB_FORCE_CMDET_OFST (30) +#define RG_SSUSB_RXDET_EN_OFST (29) +#define RG_SSUSB_FORCE_RXDET_EN_OFST (28) +#define RG_SSUSB_RXDET_K_TWICE_OFST (27) +#define RG_SSUSB_RXDET_STB3_SET_OFST (18) +#define RG_SSUSB_RXDET_STB2_SET_OFST (9) +#define RG_SSUSB_RXDET_STB1_SET_OFST (0) + +/* U3D_B2_PHYD_RXDET2 */ +#define RG_SSUSB_PHYD_TRAINDEC_FORCE_CGEN_OFST (31) +#define RG_SSUSB_PHYD_BERTLB_FORCE_CGEN_OFST (30) +#define RG_SSUSB_PHYD_T2RLB_FORCE_CGEN_OFST (29) +#define RG_SSUSB_LCK2REF_EXT_EN_OFST (28) +#define RG_SSUSB_G2_LCK2REF_EXT_SEL_OFST (24) +#define RG_SSUSB_LCK2REF_EXT_SEL_OFST (20) +#define RG_SSUSB_PDN_T_SEL_OFST (18) +#define RG_SSUSB_RXDET_STB3_SET_P3_OFST (9) +#define RG_SSUSB_RXDET_STB2_SET_P3_OFST (0) + +/* U3D_B2_PHYD_MISC0 */ +#define RG_SSUSB_TX_EIDLE_LP_P0DLYCYC_OFST (26) +#define RG_SSUSB_TX_SER_EN_OFST (25) +#define RG_SSUSB_FORCE_TX_SER_EN_OFST (24) +#define RG_SSUSB_TXPLL_REFCKSEL_OFST (23) +#define RG_SSUSB_FORCE_PLL_DDS_HF_EN_OFST (22) +#define RG_SSUSB_PLL_DDS_HF_EN_MAN_OFST (21) +#define RG_SSUSB_RXLFPS_ENTXDRV_OFST (20) +#define RG_SSUSB_RX_FL_UNLOCKTH_OFST (16) +#define RG_SSUSB_LFPS_PSEL_OFST (15) +#define RG_SSUSB_RX_SIGDET_EN_OFST (14) +#define RG_SSUSB_RX_SIGDET_EN_SEL_OFST (13) +#define RG_SSUSB_RX_PI_CAL_EN_OFST (12) +#define RG_SSUSB_RX_PI_CAL_EN_SEL_OFST (11) +#define RG_SSUSB_P3_CLS_CK_SEL_OFST (10) +#define RG_SSUSB_T2RLB_PSEL_OFST (8) +#define RG_SSUSB_PPCTL_PSEL_OFST (5) +#define RG_SSUSB_PHYD_TX_DATA_INV_OFST (4) +#define RG_SSUSB_BERTLB_PSEL_OFST (2) +#define RG_SSUSB_RETRACK_DIS_OFST (1) +#define RG_SSUSB_PPERRCNT_CLR_OFST (0) + +/* U3D_B2_PHYD_MISC2 */ +#define RG_SSUSB_FRC_PLL_DDS_PREDIV2_OFST (31) +#define RG_SSUSB_FRC_PLL_DDS_IADJ_OFST (27) +#define RG_SSUSB_P_SIGDET_125FILTER_OFST (26) +#define RG_SSUSB_P_SIGDET_RST_FILTER_OFST (25) +#define RG_SSUSB_P_SIGDET_EID_USE_RAW_OFST (24) +#define RG_SSUSB_P_SIGDET_LTD_USE_RAW_OFST (23) +#define RG_SSUSB_EIDLE_BF_RXDET_OFST (22) +#define RG_SSUSB_EIDLE_LP_STBCYC_OFST (13) +#define RG_SSUSB_TX_EIDLE_LP_POSTDLY_OFST (7) +#define RG_SSUSB_TX_EIDLE_LP_PREDLY_OFST (1) +#define RG_SSUSB_TX_EIDLE_LP_EN_ADV_OFST (0) + +/* U3D_B2_PHYD_MISC3 */ +#define RGS_SSUSB_DDS_CALIB_C_STATE_OFST (16) +#define RGS_SSUSB_PPERRCNT_OFST (0) + +/* U3D_B2_PHYD_L1SS */ +#define RG_SSUSB_L1SS_REV1_OFST (24) +#define RG_SSUSB_L1SS_REV0_OFST (16) +#define RG_SSUSB_P_LTD1_SLOCK_DIS_OFST (11) +#define RG_SSUSB_PLL_CNT_CLEAN_DIS_OFST (10) +#define RG_SSUSB_P_PLL_REK_SEL_OFST (9) +#define RG_SSUSB_TXDRV_MASKDLY_OFST (8) +#define RG_SSUSB_RXSTS_VAL_OFST (7) +#define RG_PCIE_PHY_CLKREQ_N_EN_OFST (6) +#define RG_PCIE_FORCE_PHY_CLKREQ_N_EN_OFST (5) +#define RG_PCIE_PHY_CLKREQ_N_OUT_OFST (4) +#define RG_PCIE_FORCE_PHY_CLKREQ_N_OUT_OFST (3) +#define RG_SSUSB_RXPLL_STB_PX0_OFST (2) +#define RG_PCIE_L1SS_EN_OFST (1) +#define RG_PCIE_FORCE_L1SS_EN_OFST (0) + +/* U3D_B2_ROSC_0 */ +#define RG_SSUSB_RING_OSC_CNTEND_OFST (23) +#define RG_SSUSB_XTAL_OSC_CNTEND_OFST (16) +#define RG_SSUSB_RING_OSC_EN_OFST (3) +#define RG_SSUSB_RING_OSC_FORCE_EN_OFST (2) +#define RG_SSUSB_FRC_RING_BYPASS_DET_OFST (1) +#define RG_SSUSB_RING_BYPASS_DET_OFST (0) + +/* U3D_B2_ROSC_1 */ +#define RG_SSUSB_RING_OSC_FRC_P3_OFST (20) +#define RG_SSUSB_RING_OSC_P3_OFST (19) +#define RG_SSUSB_RING_OSC_FRC_RECAL_OFST (17) +#define RG_SSUSB_RING_OSC_RECAL_OFST (16) +#define RG_SSUSB_RING_OSC_SEL_OFST (8) +#define RG_SSUSB_RING_OSC_FRC_SEL_OFST (0) + +/* U3D_B2_ROSC_2 */ +#define RG_SSUSB_RING_DET_STRCYC2_OFST (16) +#define RG_SSUSB_RING_DET_STRCYC1_OFST (0) + +/* U3D_B2_ROSC_3 */ +#define RG_SSUSB_RING_DET_DETWIN1_OFST (16) +#define RG_SSUSB_RING_DET_STRCYC3_OFST (0) + +/* U3D_B2_ROSC_4 */ +#define RG_SSUSB_RING_DET_DETWIN3_OFST (16) +#define RG_SSUSB_RING_DET_DETWIN2_OFST (0) + +/* U3D_B2_ROSC_5 */ +#define RG_SSUSB_RING_DET_LBOND1_OFST (16) +#define RG_SSUSB_RING_DET_UBOND1_OFST (0) + +/* U3D_B2_ROSC_6 */ +#define RG_SSUSB_RING_DET_LBOND2_OFST (16) +#define RG_SSUSB_RING_DET_UBOND2_OFST (0) + +/* U3D_B2_ROSC_7 */ +#define RG_SSUSB_RING_DET_LBOND3_OFST (16) +#define RG_SSUSB_RING_DET_UBOND3_OFST (0) + +/* U3D_B2_ROSC_8 */ +#define RG_SSUSB_RING_RESERVE_OFST (16) +#define RG_SSUSB_ROSC_PROB_SEL_OFST (2) +#define RG_SSUSB_RING_FREQMETER_EN_OFST (1) +#define RG_SSUSB_RING_DET_BPS_UBOND_OFST (0) + +/* U3D_B2_ROSC_9 */ +#define RGS_FM_RING_CNT_OFST (16) +#define RGS_SSUSB_RING_OSC_STATE_OFST (10) +#define RGS_SSUSB_RING_OSC_STABLE_OFST (9) +#define RGS_SSUSB_RING_OSC_CAL_FAIL_OFST (8) +#define RGS_SSUSB_RING_OSC_CAL_OFST (0) + +/* U3D_B2_ROSC_A */ +#define RGS_SSUSB_ROSC_PROB_OUT_OFST (0) + +/* U3D_PHYD_VERSION */ +#define RGS_SSUSB_PHYD_VERSION_OFST (0) + +/* U3D_PHYD_MODEL */ +#define RGS_SSUSB_PHYD_MODEL_OFST (0) + +/* ///////////////////////////////////////////////////////////////////////////// */ + +struct sifslv_chip_reg_e { + /* 0x0 */ + PHY_LE32 gpio_ctla; + PHY_LE32 gpio_ctlb; + PHY_LE32 gpio_ctlc; +}; + +/* ///////////////////////////////////////////////////////////////////////////// */ + +struct sifslv_fm_feg_e { + /* 0x0 */ + PHY_LE32 fmcr0; + PHY_LE32 fmcr1; + PHY_LE32 fmcr2; + PHY_LE32 fmmonr0; + /* 0X10 */ + PHY_LE32 fmmonr1; +}; + +/* U3D_FMCR0 */ +#define RG_LOCKTH (0xf<<28) /* 31:28 */ +#define RG_MONCLK_SEL (0x3<<26) /* 27:26 */ +#define RG_FM_MODE (0x1<<25) /* 25:25 */ +#define RG_FREQDET_EN (0x1<<24) /* 24:24 */ +#define RG_CYCLECNT (0xffffff<<0) /* 23:0 */ + +/* U3D_FMCR1 */ +#define RG_TARGET (0xffffffff<<0) /* 31:0 */ + +/* U3D_FMCR2 */ +#define RG_OFFSET (0xffffffff<<0) /* 31:0 */ + +/* U3D_FMMONR0 */ +#define USB_FM_OUT (0xffffffff<<0) /* 31:0 */ + +/* U3D_FMMONR1 */ +#define RG_MONCLK_SEL_2 (0x1<<9) /* 9:9 */ +#define RG_FRCK_EN (0x1<<8) /* 8:8 */ +#define USBPLL_LOCK (0x1<<1) /* 1:1 */ +#define USB_FM_VLD (0x1<<0) /* 0:0 */ + +/* OFFSET */ + +/* U3D_FMCR0 */ +#define RG_LOCKTH_OFST (28) +#define RG_MONCLK_SEL_OFST (26) +#define RG_FM_MODE_OFST (25) +#define RG_FREQDET_EN_OFST (24) +#define RG_CYCLECNT_OFST (0) + +/* U3D_FMCR1 */ +#define RG_TARGET_OFST (0) + +/* U3D_FMCR2 */ +#define RG_OFFSET_OFST (0) + +/* U3D_FMMONR0 */ +#define USB_FM_OUT_OFST (0) + +/* U3D_FMMONR1 */ +#define RG_MONCLK_SEL_2_OFST (9) +#define RG_FRCK_EN_OFST (8) +#define USBPLL_LOCK_OFST (1) +#define USB_FM_VLD_OFST (0) + +/* ///////////////////////////////////////////////////////////////////////////// */ + +struct spllc_reg_e { + /* 0x0 */ + PHY_LE32 u3d_syspll_0; + PHY_LE32 u3d_syspll_1; + PHY_LE32 u3d_syspll_2; + PHY_LE32 u3d_syspll_sdm; + /* 0x10 */ + PHY_LE32 u3d_xtalctl_1; + PHY_LE32 u3d_xtalctl_2; + PHY_LE32 u3d_xtalctl3; +}; + +/* U3D_SYSPLL_0 */ +#define RG_SSUSB_SPLL_DDSEN_CYC (0x1f<<27) /* 31:27 */ +#define RG_SSUSB_SPLL_NCPOEN_CYC (0x3<<25) /* 26:25 */ +#define RG_SSUSB_SPLL_STBCYC (0x1ff<<16) /* 24:16 */ +#define RG_SSUSB_SPLL_NCPOCHG_CYC (0xf<<12) /* 15:12 */ +#define RG_SSUSB_SYSPLL_ON (0x1<<11) /* 11:11 */ +#define RG_SSUSB_FORCE_SYSPLLON (0x1<<10) /* 10:10 */ +#define RG_SSUSB_SPLL_DDSRSTB_CYC (0x7<<0) /* 2:0 */ + +/* U3D_SYSPLL_1 */ +#define RG_SSUSB_PLL_BIAS_CYC (0xff<<24) /* 31:24 */ +#define RG_SSUSB_SYSPLL_STB (0x1<<23) /* 23:23 */ +#define RG_SSUSB_FORCE_SYSPLL_STB (0x1<<22) /* 22:22 */ +#define RG_SSUSB_SPLL_DDS_ISO_EN (0x1<<21) /* 21:21 */ +#define RG_SSUSB_FORCE_SPLL_DDS_ISO_EN (0x1<<20) /* 20:20 */ +#define RG_SSUSB_SPLL_DDS_PWR_ON (0x1<<19) /* 19:19 */ +#define RG_SSUSB_FORCE_SPLL_DDS_PWR_ON (0x1<<18) /* 18:18 */ +#define RG_SSUSB_PLL_BIAS_PWD (0x1<<17) /* 17:17 */ +#define RG_SSUSB_FORCE_PLL_BIAS_PWD (0x1<<16) /* 16:16 */ +#define RG_SSUSB_FORCE_SPLL_NCPO_EN (0x1<<15) /* 15:15 */ +#define RG_SSUSB_FORCE_SPLL_FIFO_START_MAN (0x1<<14) /* 14:14 */ +#define RG_SSUSB_FORCE_SPLL_NCPO_CHG (0x1<<12) /* 12:12 */ +#define RG_SSUSB_FORCE_SPLL_DDS_RSTB (0x1<<11) /* 11:11 */ +#define RG_SSUSB_FORCE_SPLL_DDS_PWDB (0x1<<10) /* 10:10 */ +#define RG_SSUSB_FORCE_SPLL_DDSEN (0x1<<9) /* 9:9 */ +#define RG_SSUSB_FORCE_SPLL_PWD (0x1<<8) /* 8:8 */ +#define RG_SSUSB_SPLL_NCPO_EN (0x1<<7) /* 7:7 */ +#define RG_SSUSB_SPLL_FIFO_START_MAN (0x1<<6) /* 6:6 */ +#define RG_SSUSB_SPLL_NCPO_CHG (0x1<<4) /* 4:4 */ +#define RG_SSUSB_SPLL_DDS_RSTB (0x1<<3) /* 3:3 */ +#define RG_SSUSB_SPLL_DDS_PWDB (0x1<<2) /* 2:2 */ +#define RG_SSUSB_SPLL_DDSEN (0x1<<1) /* 1:1 */ +#define RG_SSUSB_SPLL_PWD (0x1<<0) /* 0:0 */ + +/* U3D_SYSPLL_2 */ +#define RG_SSUSB_SPLL_P_ON_SEL (0x1<<11) /* 11:11 */ +#define RG_SSUSB_SPLL_FBDIV_CHG (0x1<<10) /* 10:10 */ +#define RG_SSUSB_SPLL_DDS_ISOEN_CYC (0x3ff<<0) /* 9:0 */ + +/* U3D_SYSPLL_SDM */ +#define RG_SSUSB_SPLL_SDM_ISO_EN_CYC (0x3ff<<14) /* 23:14 */ +#define RG_SSUSB_SPLL_FORCE_SDM_ISO_EN (0x1<<13) /* 13:13 */ +#define RG_SSUSB_SPLL_SDM_ISO_EN (0x1<<12) /* 12:12 */ +#define RG_SSUSB_SPLL_SDM_PWR_ON_CYC (0x3ff<<2) /* 11:2 */ +#define RG_SSUSB_SPLL_FORCE_SDM_PWR_ON (0x1<<1) /* 1:1 */ +#define RG_SSUSB_SPLL_SDM_PWR_ON (0x1<<0) /* 0:0 */ + +/* U3D_XTALCTL_1 */ +#define RG_SSUSB_BIAS_STBCYC (0x3fff<<17) /* 30:17 */ +#define RG_SSUSB_XTAL_CLK_REQ_N (0x1<<16) /* 16:16 */ +#define RG_SSUSB_XTAL_FORCE_CLK_REQ_N (0x1<<15) /* 15:15 */ +#define RG_SSUSB_XTAL_STBCYC (0x7fff<<0) /* 14:0 */ + +/* U3D_XTALCTL_2 */ +#define RG_SSUSB_INT_XTAL_SEL (0x1<<29) /* 29:29 */ +#define RG_SSUSB_BG_LPF_DLY (0x3<<27) /* 28:27 */ +#define RG_SSUSB_BG_LPF_EN (0x1<<26) /* 26:26 */ +#define RG_SSUSB_FORCE_BG_LPF_EN (0x1<<25) /* 25:25 */ +#define RG_SSUSB_P3_BIAS_PWD (0x1<<24) /* 24:24 */ +#define RG_SSUSB_PCIE_CLKDET_HIT (0x1<<20) /* 20:20 */ +#define RG_SSUSB_PCIE_CLKDET_EN (0x1<<19) /* 19:19 */ +#define RG_SSUSB_FRC_PCIE_CLKDET_EN (0x1<<18) /* 18:18 */ +#define RG_SSUSB_USB20_BIAS_EN (0x1<<17) /* 17:17 */ +#define RG_SSUSB_USB20_SLEEP (0x1<<16) /* 16:16 */ +#define RG_SSUSB_OSC_ONLY (0x1<<9) /* 9:9 */ +#define RG_SSUSB_OSC_EN (0x1<<8) /* 8:8 */ +#define RG_SSUSB_XTALBIAS_STB (0x1<<5) /* 5:5 */ +#define RG_SSUSB_FORCE_XTALBIAS_STB (0x1<<4) /* 4:4 */ +#define RG_SSUSB_BIAS_PWD (0x1<<3) /* 3:3 */ +#define RG_SSUSB_XTAL_PWD (0x1<<2) /* 2:2 */ +#define RG_SSUSB_FORCE_BIAS_PWD (0x1<<1) /* 1:1 */ +#define RG_SSUSB_FORCE_XTAL_PWD (0x1<<0) /* 0:0 */ + +/* U3D_XTALCTL3 */ +#define RG_SSUSB_XTALCTL_REV (0xf<<12) /* 15:12 */ +#define RG_SSUSB_BIASIMR_EN (0x1<<11) /* 11:11 */ +#define RG_SSUSB_FORCE_BIASIMR_EN (0x1<<10) /* 10:10 */ +#define RG_SSUSB_XTAL_RX_PWD (0x1<<9) /* 9:9 */ +#define RG_SSUSB_FRC_XTAL_RX_PWD (0x1<<8) /* 8:8 */ +#define RG_SSUSB_CKBG_PROB_SEL (0x3<<6) /* 7:6 */ +#define RG_SSUSB_XTAL_PROB_SEL (0x3<<4) /* 5:4 */ +#define RG_SSUSB_XTAL_VREGBIAS_LPF_ENB (0x1<<3) /* 3:3 */ +#define RG_SSUSB_XTAL_FRC_VREGBIAS_LPF_ENB (0x1<<2) /* 2:2 */ +#define RG_SSUSB_XTAL_VREGBIAS_PWD (0x1<<1) /* 1:1 */ +#define RG_SSUSB_XTAL_FRC_VREGBIAS_PWD (0x1<<0) /* 0:0 */ + + +/* SSUSB_SIFSLV_SPLLC FIELD OFFSET DEFINITION */ + +/* U3D_SYSPLL_0 */ +#define RG_SSUSB_SPLL_DDSEN_CYC_OFST (27) +#define RG_SSUSB_SPLL_NCPOEN_CYC_OFST (25) +#define RG_SSUSB_SPLL_STBCYC_OFST (16) +#define RG_SSUSB_SPLL_NCPOCHG_CYC_OFST (12) +#define RG_SSUSB_SYSPLL_ON_OFST (11) +#define RG_SSUSB_FORCE_SYSPLLON_OFST (10) +#define RG_SSUSB_SPLL_DDSRSTB_CYC_OFST (0) + +/* U3D_SYSPLL_1 */ +#define RG_SSUSB_PLL_BIAS_CYC_OFST (24) +#define RG_SSUSB_SYSPLL_STB_OFST (23) +#define RG_SSUSB_FORCE_SYSPLL_STB_OFST (22) +#define RG_SSUSB_SPLL_DDS_ISO_EN_OFST (21) +#define RG_SSUSB_FORCE_SPLL_DDS_ISO_EN_OFST (20) +#define RG_SSUSB_SPLL_DDS_PWR_ON_OFST (19) +#define RG_SSUSB_FORCE_SPLL_DDS_PWR_ON_OFST (18) +#define RG_SSUSB_PLL_BIAS_PWD_OFST (17) +#define RG_SSUSB_FORCE_PLL_BIAS_PWD_OFST (16) +#define RG_SSUSB_FORCE_SPLL_NCPO_EN_OFST (15) +#define RG_SSUSB_FORCE_SPLL_FIFO_START_MAN_OFST (14) +#define RG_SSUSB_FORCE_SPLL_NCPO_CHG_OFST (12) +#define RG_SSUSB_FORCE_SPLL_DDS_RSTB_OFST (11) +#define RG_SSUSB_FORCE_SPLL_DDS_PWDB_OFST (10) +#define RG_SSUSB_FORCE_SPLL_DDSEN_OFST (9) +#define RG_SSUSB_FORCE_SPLL_PWD_OFST (8) +#define RG_SSUSB_SPLL_NCPO_EN_OFST (7) +#define RG_SSUSB_SPLL_FIFO_START_MAN_OFST (6) +#define RG_SSUSB_SPLL_NCPO_CHG_OFST (4) +#define RG_SSUSB_SPLL_DDS_RSTB_OFST (3) +#define RG_SSUSB_SPLL_DDS_PWDB_OFST (2) +#define RG_SSUSB_SPLL_DDSEN_OFST (1) +#define RG_SSUSB_SPLL_PWD_OFST (0) + +/* U3D_SYSPLL_2 */ +#define RG_SSUSB_SPLL_P_ON_SEL_OFST (11) +#define RG_SSUSB_SPLL_FBDIV_CHG_OFST (10) +#define RG_SSUSB_SPLL_DDS_ISOEN_CYC_OFST (0) + +/* U3D_SYSPLL_SDM */ +#define RG_SSUSB_SPLL_SDM_ISO_EN_CYC_OFST (14) +#define RG_SSUSB_SPLL_FORCE_SDM_ISO_EN_OFST (13) +#define RG_SSUSB_SPLL_SDM_ISO_EN_OFST (12) +#define RG_SSUSB_SPLL_SDM_PWR_ON_CYC_OFST (2) +#define RG_SSUSB_SPLL_FORCE_SDM_PWR_ON_OFST (1) +#define RG_SSUSB_SPLL_SDM_PWR_ON_OFST (0) + +/* U3D_XTALCTL_1 */ +#define RG_SSUSB_BIAS_STBCYC_OFST (17) +#define RG_SSUSB_XTAL_CLK_REQ_N_OFST (16) +#define RG_SSUSB_XTAL_FORCE_CLK_REQ_N_OFST (15) +#define RG_SSUSB_XTAL_STBCYC_OFST (0) + +/* U3D_XTALCTL_2 */ +#define RG_SSUSB_INT_XTAL_SEL_OFST (29) +#define RG_SSUSB_BG_LPF_DLY_OFST (27) +#define RG_SSUSB_BG_LPF_EN_OFST (26) +#define RG_SSUSB_FORCE_BG_LPF_EN_OFST (25) +#define RG_SSUSB_P3_BIAS_PWD_OFST (24) +#define RG_SSUSB_PCIE_CLKDET_HIT_OFST (20) +#define RG_SSUSB_PCIE_CLKDET_EN_OFST (19) +#define RG_SSUSB_FRC_PCIE_CLKDET_EN_OFST (18) +#define RG_SSUSB_USB20_BIAS_EN_OFST (17) +#define RG_SSUSB_USB20_SLEEP_OFST (16) +#define RG_SSUSB_OSC_ONLY_OFST (9) +#define RG_SSUSB_OSC_EN_OFST (8) +#define RG_SSUSB_XTALBIAS_STB_OFST (5) +#define RG_SSUSB_FORCE_XTALBIAS_STB_OFST (4) +#define RG_SSUSB_BIAS_PWD_OFST (3) +#define RG_SSUSB_XTAL_PWD_OFST (2) +#define RG_SSUSB_FORCE_BIAS_PWD_OFST (1) +#define RG_SSUSB_FORCE_XTAL_PWD_OFST (0) + +/* U3D_XTALCTL3 */ +#define RG_SSUSB_XTALCTL_REV_OFST (12) +#define RG_SSUSB_BIASIMR_EN_OFST (11) +#define RG_SSUSB_FORCE_BIASIMR_EN_OFST (10) +#define RG_SSUSB_XTAL_RX_PWD_OFST (9) +#define RG_SSUSB_FRC_XTAL_RX_PWD_OFST (8) +#define RG_SSUSB_CKBG_PROB_SEL_OFST (6) +#define RG_SSUSB_XTAL_PROB_SEL_OFST (4) +#define RG_SSUSB_XTAL_VREGBIAS_LPF_ENB_OFST (3) +#define RG_SSUSB_XTAL_FRC_VREGBIAS_LPF_ENB_OFST (2) +#define RG_SSUSB_XTAL_VREGBIAS_PWD_OFST (1) +#define RG_SSUSB_XTAL_FRC_VREGBIAS_PWD_OFST (0) + +/* ///////////////////////////////////////////////////////////////////////////// */ +PHY_INT32 phy_init_soc(struct u3phy_info *info); +PHY_INT32 u2_slew_rate_calibration(struct u3phy_info *info); + +void usb_phy_savecurrent(unsigned int clk_on); +void usb_phy_recover(unsigned int clk_on); +void usb_fake_powerdown(unsigned int clk_on); +void usb20_pll_settings(bool host, bool forceOn); +extern u32 get_devinfo_with_index(u32 index); +#ifdef CONFIG_MTK_SIB_USB_SWITCH +extern void usb_phy_sib_enable_switch(bool enable); +extern bool usb_phy_sib_enable_switch_status(void); +#endif /*CONFIG_MTK_SIB_USB_SWITCH*/ + +#ifdef CONFIG_MTK_UART_USB_SWITCH +typedef enum { + PORT_MODE_USB = 0, + PORT_MODE_UART, + + PORT_MODE_MAX +} PORT_MODE; + +extern bool in_uart_mode; +extern void uart_usb_switch_dump_register(void); +extern bool usb_phy_check_in_uart_mode(void); +extern void usb_phy_switch_to_usb(void); +extern void usb_phy_switch_to_uart(void); +extern void __iomem *ap_uart0_base; +#endif + +#endif +#endif diff --git a/drivers/misc/mediatek/nfc/mt6755/Makefile b/drivers/misc/mediatek/nfc/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..64844864f8109d401ca976cdf7ac911e3f648387 --- /dev/null +++ b/drivers/misc/mediatek/nfc/mt6755/Makefile @@ -0,0 +1,15 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-$(CONFIG_NFC_MT6605) += mt6605.o +ccflags-$(CONFIG_NFC_MT6605) += -DDEBUG diff --git a/drivers/misc/mediatek/nfc/mt6755/mt6605.c b/drivers/misc/mediatek/nfc/mt6755/mt6605.c new file mode 100644 index 0000000000000000000000000000000000000000..e856e05ff3b32298760f143a68447a98564748f6 --- /dev/null +++ b/drivers/misc/mediatek/nfc/mt6755/mt6605.c @@ -0,0 +1,1306 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/*************************************************************************** + * Filename: + * --------- + * mt6605.c + * + * Project: + * -------- + * + * Description: + * ------------ + * + * Author: + * ------- + * LiangChi Huang, ext 25609, LiangChi.Huang@mediatek.com, 2012-08-09 + * + *****************************************************************************/ + +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt +/***************************************************************************** + * Include + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#endif + +/* #include */ +/* #include */ + +#ifndef CONFIG_MTK_FPGA +#include /* for clock buffer */ +#endif + +/* #include */ +/* #include */ + +#if defined(CONFIG_MTK_LEGACY) +#include +#include +#endif + +/***************************************************************************** + * Define + *****************************************************************************/ + +/* #define NFC_I2C_BUSNUM I2C_NFC_CHANNEL */ + +#define I2C_ID_NAME "mt6605" + +#define MAX_BUFFER_SIZE 255 + +#define NFC_CLIENT_TIMING 400 /* I2C speed */ + +enum { + MTK_NFC_GPIO_EN_B = 0x0, + MTK_NFC_GPIO_SYSRST_B, + MTK_NFC_GPIO_EINT, + MTK_NFC_GPIO_IRQ, + MTK_NFC_GPIO_IOCTL, + MTK_NFC_GPIO_MAX_NUM +}; + +enum { + MTK_NFC_IOCTL_READ = 0x0, + MTK_NFC_IOCTL_WRITE, + MTK_NFC_IOCTL_MAX_NUM +}; + +enum { + MTK_NFC_IOCTL_CMD_CLOCK_BUF_ENABLE = 0x0, + MTK_NFC_IOCTL_CMD_CLOCK_BUF_DISABLE, + MTK_NFC_IOCTL_CMD_EXIT_EINT, + MTK_NFC_IOCTL_CMD_GET_CHIP_ID, + MTK_NFC_IOCTL_CMD_READ_DATA, + MTK_NFC_IOCTL_CMD_MAX_NUM +}; + +enum { + MTK_NFC_PULL_LOW = 0x0, + MTK_NFC_PULL_HIGH, + MTK_NFC_PULL_INVALID, +}; + +enum { + MTK_NFC_GPIO_DIR_IN = 0x0, + MTK_NFC_GPIO_DIR_OUT, + MTK_NFC_GPIO_DIR_INVALID, +}; + +/***************************************************************************** + * Global Variable + *****************************************************************************/ +struct mt6605_dev *mt6605_dev_ptr = NULL; +struct mt6605_dev _gmt6605_dev; + +#if !defined(CONFIG_MTK_LEGACY) +struct platform_device *nfc_plt_dev = NULL; +struct pinctrl *gpctrl = NULL; +struct pinctrl_state *st_ven_h = NULL; +struct pinctrl_state *st_ven_l = NULL; +struct pinctrl_state *st_rst_h = NULL; +struct pinctrl_state *st_rst_l = NULL; +struct pinctrl_state *st_eint_h = NULL; +struct pinctrl_state *st_eint_l = NULL; +struct pinctrl_state *st_irq_init = NULL; +#endif + +/* static struct i2c_board_info nfc_board_info __initdata = */ +/* { I2C_BOARD_INFO(I2C_ID_NAME, I2C_NFC_SLAVE_7_BIT_ADDR) }; */ + +/* For DMA */ +static char *I2CDMAWriteBuf; /*= NULL;*//* unnecessary initialise */ +static dma_addr_t I2CDMAWriteBuf_pa; +static char *I2CDMAReadBuf; /*= NULL;*//* unnecessary initialise */ +static dma_addr_t I2CDMAReadBuf_pa; /* = NULL; */ + +static int fgNfcChip; /*= 0;*//* unnecessary initialise */ +int forceExitBlockingRead = 0; + +/* NFC IRQ */ +static u32 nfc_irq; +static int nfc_irq_count; /*= 0;*//* unnecessary initialise */ + +/***************************************************************************** + * Function Prototype + *****************************************************************************/ +static int mt6605_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int mt6605_remove(struct i2c_client *client); +/* static int mt6605_detect(struct i2c_client *client, */ +/* int kind, struct i2c_board_info *info); */ +static int mt6605_dev_open(struct inode *inode, struct file *filp); +static long mt6605_dev_unlocked_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); +static ssize_t mt6605_dev_read(struct file *filp, char __user *buf, + size_t count, loff_t *offset); +static ssize_t mt6605_dev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *offset); + +static int mt_nfc_probe(struct platform_device *pdev); +static int mt_nfc_remove(struct platform_device *pdev); + +/* void mt6605_dev_irq_handler(void); */ +static irqreturn_t mt6605_dev_irq_handler(int irq, void *data); /*IRQ handler */ + +/* static void mt6605_disable_irq(struct mt6605_dev *mt6605_dev); */ +#if !defined(CONFIG_MTK_LEGACY) +static int mt_nfc_pinctrl_init(struct platform_device *pdev); +static int mt_nfc_pinctrl_select(struct pinctrl *p, struct pinctrl_state *s); +static int mt_nfc_gpio_init(void); +#endif +static int mt_nfc_get_gpio_value(int gpio_num); +static int mt_nfc_get_gpio_dir(int gpio_num); + +/***************************************************************************** + * Data Structure + *****************************************************************************/ + +struct mt6605_dev { + wait_queue_head_t read_wq; + struct mutex read_mutex; + struct i2c_client *client; + struct miscdevice mt6605_device; + unsigned int ven_gpio; + unsigned int sysrstb_gpio; + unsigned int irq_gpio; /* Chip inform Host */ + unsigned int eint_gpio; /* Host inform Chip */ + bool irq_enabled; + struct mutex irq_enabled_lock; + /* spinlock_t irq_enabled_lock; */ +}; + +struct mt6605_i2c_platform_data { + unsigned int irq_gpio; /* Chip inform Host */ + unsigned int ven_gpio; + unsigned int sysrstb_gpio; + unsigned int eint_gpio; /* Host inform Chip */ +}; + +static const struct i2c_device_id mt6605_id[] = { + {I2C_ID_NAME, 0}, + {} +}; + +#ifdef CONFIG_OF +static const struct of_device_id nfc_switch_of_match[] = { + {.compatible = "mediatek,nfc"}, + {}, +}; +#endif + +/* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) */ +/* static struct i2c_client_address_data addr_data = { .forces = forces,}; */ +/* #endif */ +static struct i2c_driver mt6605_dev_driver = { + .id_table = mt6605_id, + .probe = mt6605_probe, + .remove = mt6605_remove, + /* .detect = mt6605_detect, */ + .driver = { + .name = "mt6605", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = nfc_switch_of_match, +#endif + }, +}; + +/* platform driver */ +static const struct of_device_id nfc_dev_of_match[] = { + {.compatible = "mediatek,nfc-gpio-v2",}, + {}, +}; + +static struct platform_driver mtk_nfc_platform_driver = { + .probe = mt_nfc_probe, + .remove = mt_nfc_remove, + .driver = { + .name = I2C_ID_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = nfc_dev_of_match, +#endif + }, +}; + +#if !defined(CONFIG_MTK_LEGACY) +struct mt6605_i2c_platform_data mt6605_platform_data; +#else +static struct mt6605_i2c_platform_data mt6605_platform_data = { + .irq_gpio = GPIO_IRQ_NFC_PIN, + .ven_gpio = GPIO_NFC_VENB_PIN, + .sysrstb_gpio = GPIO_NFC_RST_PIN, + .eint_gpio = GPIO_NFC_EINT_PIN, +}; +#endif + +static const struct file_operations mt6605_dev_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = mt6605_dev_read, + .write = mt6605_dev_write, + .open = mt6605_dev_open, +#ifdef CONFIG_COMPAT + .compat_ioctl = mt6605_dev_unlocked_ioctl, +#endif + .unlocked_ioctl = mt6605_dev_unlocked_ioctl, +}; + +/***************************************************************************** + * Extern Area + *****************************************************************************/ + +/***************************************************************************** + * Function + *****************************************************************************/ +static void mt6605_enable_irq(u32 irq_line) +{ + /* pr_debug("%s : irq_line=%d, nfc_irq_count=%d.\n", __func__, + irq_line, nfc_irq_count); */ + + nfc_irq_count++; /* It must set before call enable_irq */ + + enable_irq(irq_line); + + /* pr_debug("%s : nfc_irq_count = %d.\n", __func__, nfc_irq_count); */ +} + +static void mt6605_disable_irq(u32 irq_line) +{ + /* pr_debug("%s : irq_line=%d, nfc_irq_count=%d.\n", __func__, + irq_line, nfc_irq_count); */ + if (nfc_irq_count >= 1) { + disable_irq_nosync(irq_line); + nfc_irq_count--; + } else { + pr_debug("%s : disable irq fail.\n", __func__); + } + /* pr_debug("%s : nfc_irq_count = %d.\n", __func__, nfc_irq_count); */ +} + +static int mt6605_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + struct mt6605_i2c_platform_data *platform_data; + struct device_node *node; + + pr_debug("mt6605_dev_probe\n"); + + platform_data = &mt6605_platform_data; + + if (platform_data == NULL) { + pr_err("%s : nfc probe fail\n", __func__); + return -ENODEV; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + pr_err("%s : need I2C_FUNC_I2C\n", __func__); + return -ENODEV; + } +#if defined(CONFIG_MTK_LEGACY) + mt_set_gpio_mode(platform_data->irq_gpio, GPIO_IRQ_NFC_PIN_M_EINT); + mt_set_gpio_dir(platform_data->irq_gpio, GPIO_DIR_IN); + mt_set_gpio_pull_enable(platform_data->irq_gpio, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(platform_data->irq_gpio, GPIO_PULL_DOWN); + + /* ven_gpio */ + mt_set_gpio_mode(platform_data->ven_gpio, GPIO_NFC_VENB_PIN_M_GPIO); + mt_set_gpio_dir(platform_data->ven_gpio, GPIO_DIR_OUT); + mt_set_gpio_out(platform_data->ven_gpio, GPIO_OUT_ONE); + usleep_range(900, 1000); /* debug */ + + /* firm_gpio */ + mt_set_gpio_mode(platform_data->sysrstb_gpio, GPIO_NFC_RST_PIN_M_GPIO); + mt_set_gpio_dir(platform_data->sysrstb_gpio, GPIO_DIR_OUT); + mt_set_gpio_out(platform_data->sysrstb_gpio, GPIO_OUT_ONE); + usleep_range(900, 1000); /* debug */ + + /* EINT_gpio */ + mt_set_gpio_mode(platform_data->eint_gpio, GPIO_NFC_EINT_PIN_M_GPIO); + mt_set_gpio_dir(platform_data->eint_gpio, GPIO_DIR_OUT); + /* Set output High */ + mt_set_gpio_out(platform_data->eint_gpio, GPIO_OUT_ZERO); + + _gmt6605_dev.irq_gpio = platform_data->irq_gpio; + _gmt6605_dev.ven_gpio = platform_data->ven_gpio; + _gmt6605_dev.sysrstb_gpio = platform_data->sysrstb_gpio; + _gmt6605_dev.eint_gpio = platform_data->eint_gpio; +#endif + + _gmt6605_dev.client = client; + /* init mutex and queues */ + init_waitqueue_head(&_gmt6605_dev.read_wq); + mutex_init(&_gmt6605_dev.read_mutex); + /* spin_lock_init(&mt6605_dev->irq_enabled_lock); */ + mutex_init(&_gmt6605_dev.irq_enabled_lock); + +#if 0 + _gmt6605_dev.mt6605_device.minor = MISC_DYNAMIC_MINOR; + _gmt6605_dev.mt6605_device.name = "mt6605"; + _gmt6605_dev.mt6605_device.fops = &mt6605_dev_fops; + + ret = misc_register(&_gmt6605_dev.mt6605_device); + if (ret) { + pr_err("%s : misc_register failed\n", __FILE__); + goto err_misc_register; + } +#endif + +#ifdef CONFIG_64BIT + I2CDMAWriteBuf = + (char *)dma_alloc_coherent(&client->dev, MAX_BUFFER_SIZE, + &I2CDMAWriteBuf_pa, GFP_KERNEL); +#else + I2CDMAWriteBuf = + (char *)dma_alloc_coherent(NULL, MAX_BUFFER_SIZE, + &I2CDMAWriteBuf_pa, GFP_KERNEL); +#endif + + if (I2CDMAWriteBuf == NULL) { + pr_err("%s : failed to allocate dma buffer\n", __func__); + goto err_request_irq_failed; + } +#ifdef CONFIG_64BIT + I2CDMAReadBuf = + (char *)dma_alloc_coherent(&client->dev, MAX_BUFFER_SIZE, + &I2CDMAReadBuf_pa, GFP_KERNEL); +#else + I2CDMAReadBuf = + (char *)dma_alloc_coherent(NULL, MAX_BUFFER_SIZE, + &I2CDMAReadBuf_pa, GFP_KERNEL); +#endif + + if (I2CDMAReadBuf == NULL) { + pr_err("%s : failed to allocate dma buffer\n", __func__); + goto err_request_irq_failed; + } + /* request irq. the irq is set whenever the chip has data available + * for reading. it is cleared when all data has been read. + */ + + /* client->irq = CUST_EINT_IRQ_NFC_NUM; */ + /* pr_debug("%s : requesting IRQ %d\n", __func__, client->irq); */ + /* pr_debug("mt6605_Prob2\n"); */ + /* mt_eint_set_hw_debounce(CUST_EINT_IRQ_NFC_NUM, */ + /* CUST_EINT_IRQ_NFC_DEBOUNCE_CN); */ + /* mt_eint_registration(CUST_EINT_IRQ_NFC_NUM, */ + /* CUST_EINT_IRQ_NFC_TYPE, mt6605_dev_irq_handler, */ + /* 0); */ + + /* NFC IRQ settings */ + node = of_find_compatible_node(NULL, NULL, "mediatek, IRQ_NFC-eint"); + + if (node) { + + nfc_irq = irq_of_parse_and_map(node, 0); + + client->irq = nfc_irq; + + ret = + request_irq(nfc_irq, mt6605_dev_irq_handler, + IRQF_TRIGGER_NONE, "irq_nfc-eint", NULL); + + if (ret) { + + pr_err("%s : EINT IRQ LINE NOT AVAILABLE\n", __func__); + + } else { + + pr_debug("%s : set EINT finished, nfc_irq=%d", __func__, + nfc_irq); + nfc_irq_count++; + mt6605_disable_irq(nfc_irq); + enable_irq_wake(nfc_irq); + } + + } else { + pr_err("%s : can not find NFC eint compatible node\n", + __func__); + } + + /* mt_eint_unmask(CUST_EINT_IRQ_NFC_NUM); */ + /* mt6605_disable_irq(mt6605_dev); */ + /* mt_eint_mask(CUST_EINT_IRQ_NFC_NUM); */ + + i2c_set_clientdata(client, &_gmt6605_dev); + + forceExitBlockingRead = 0; + + return 0; + +err_request_irq_failed: + + /* misc_deregister(&_gmt6605_dev.mt6605_device); */ + /* err_misc_register: */ + mutex_destroy(&_gmt6605_dev.read_mutex); + /* kfree(mt6605_dev); */ + /* err_exit: */ + gpio_free(platform_data->sysrstb_gpio); + return ret; +} + +static int mt6605_remove(struct i2c_client *client) +{ + /* struct mt6605_dev *mt6605_dev; */ + + pr_debug("mt6605_remove\n"); + + if (I2CDMAWriteBuf) { +#ifdef CONFIG_64BIT + dma_free_coherent(&client->dev, MAX_BUFFER_SIZE, I2CDMAWriteBuf, + I2CDMAWriteBuf_pa); +#else + dma_free_coherent(NULL, MAX_BUFFER_SIZE, I2CDMAWriteBuf, + I2CDMAWriteBuf_pa); +#endif + I2CDMAWriteBuf = NULL; + I2CDMAWriteBuf_pa = 0; + } + + if (I2CDMAReadBuf) { +#ifdef CONFIG_64BIT + dma_free_coherent(&client->dev, MAX_BUFFER_SIZE, I2CDMAReadBuf, + I2CDMAReadBuf_pa); +#else + dma_free_coherent(NULL, MAX_BUFFER_SIZE, I2CDMAReadBuf, + I2CDMAReadBuf_pa); +#endif + I2CDMAReadBuf = NULL; + I2CDMAReadBuf_pa = 0; + } + + /* mt6605_dev = i2c_get_clientdata(client); */ + /* free_irq(client->irq, &_gmt6605_dev); */ + free_irq(nfc_irq, &_gmt6605_dev); + misc_deregister(&_gmt6605_dev.mt6605_device); + mutex_destroy(&_gmt6605_dev.read_mutex); + +#if defined(CONFIG_MTK_LEGACY) + gpio_free(_gmt6605_dev.irq_gpio); + gpio_free(_gmt6605_dev.ven_gpio); + gpio_free(_gmt6605_dev.sysrstb_gpio); + gpio_free(_gmt6605_dev.eint_gpio); +#endif + + /* kfree(mt6605_dev); */ + + return 0; +} + +static int mt_nfc_probe(struct platform_device *pdev) +{ + int ret = 0; + +#if !defined(CONFIG_MTK_LEGACY) + + nfc_plt_dev = pdev; + + pr_debug("%s : &nfc_plt_dev=%p\n", __func__, nfc_plt_dev); + + /* pinctrl init */ + ret = mt_nfc_pinctrl_init(pdev); + + /* gpio init */ + if (mt_nfc_gpio_init() != 0) + pr_debug("%s : mt_nfc_gpio_init err.\n", __func__); + +#endif + + return 0; +} + +static int mt_nfc_remove(struct platform_device *pdev) +{ + pr_debug("%s : &pdev=%p\n", __func__, pdev); + return 0; +} + +/* void mt6605_dev_irq_handler(void) */ +irqreturn_t mt6605_dev_irq_handler(int irq, void *data) +{ + struct mt6605_dev *mt6605_dev = mt6605_dev_ptr; + /* pr_debug("%s : &mt6605_dev=%p\n", __func__, mt6605_dev); */ + + if (NULL == mt6605_dev) { + pr_debug("mt6605_dev NULL.\n"); + return IRQ_HANDLED; + } + /* mt6605_disable_irq(mt6605_dev); */ + mt6605_disable_irq(nfc_irq); + + wake_up(&mt6605_dev->read_wq); + /* wake_up_interruptible(&mt6605_dev->read_wq); */ + + /* pr_debug("%s : wake_up &read_wq=%p\n", __func__, &mt6605_dev->read_wq); */ + + return IRQ_HANDLED; +} + +static ssize_t mt6605_dev_read(struct file *filp, char __user *buf, + size_t count, loff_t *offset) +{ + struct mt6605_dev *mt6605_dev = filp->private_data; + int ret = 0; + + if (count > MAX_BUFFER_SIZE) + count = MAX_BUFFER_SIZE; + + if (!mt_nfc_get_gpio_value(mt6605_dev->irq_gpio)) { + if (filp->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + pr_debug("%s : goto fail.\n", __func__); + goto fail; + } + /* mutex_lock(&mt6605_dev->irq_enabled_lock); */ + /* mt6605_dev->irq_enabled = true; */ + /* mutex_unlock(&mt6605_dev->irq_enabled_lock); */ + + mutex_lock(&mt6605_dev->read_mutex); + if (forceExitBlockingRead == 1) { + pr_debug("%s :forceExitBlockingRead.\n", __func__); + forceExitBlockingRead = 0; /* clear flag */ + mutex_unlock(&mt6605_dev->read_mutex); + goto fail; + } + mutex_unlock(&mt6605_dev->read_mutex); + + /* mt_eint_unmask(mt6605_dev->client->irq); */ + /* pr_debug("%s : mt_eint_unmask %d, IRQ, %d\n", */ + /* __func__, */ + /* mt6605_dev->client->irq, */ + /* mt_get_gpio_in(mt6605_dev->irq_gpio)); */ + + mt6605_enable_irq(nfc_irq); + + /* pr_debug("%s : enable_irq %d, irq status=%d\n", + __func__, + nfc_irq, mt_nfc_get_gpio_value(mt6605_dev->irq_gpio)); */ + + ret = wait_event_interruptible(mt6605_dev->read_wq, + (mt_nfc_get_gpio_value + (mt6605_dev->irq_gpio) + || forceExitBlockingRead)); + + /*pr_debug("%s : wait_event_interruptible ret=%d,irq status=%d\n", + __func__, ret, + mt_nfc_get_gpio_value(mt6605_dev->irq_gpio));*/ + + if (ret || forceExitBlockingRead) { + mt6605_disable_irq(nfc_irq); + pr_debug("%s : goto fail\n", __func__); + mutex_lock(&mt6605_dev->read_mutex); + if (forceExitBlockingRead == 1) { + pr_debug + ("%s:clear flag,orceExitBlockingRead\n", + __func__); + forceExitBlockingRead = 0; /* clear flag */ + } + mutex_unlock(&mt6605_dev->read_mutex); + goto fail; + } + + } + + mt6605_dev->client->addr = (mt6605_dev->client->addr & I2C_MASK_FLAG); + mt6605_dev->client->ext_flag |= I2C_DMA_FLAG; + /* mt6605_dev->client->ext_flag |= I2C_DIRECTION_FLAG; */ + /* mt6605_dev->client->ext_flag |= I2C_A_FILTER_MSG; */ + mt6605_dev->client->timing = NFC_CLIENT_TIMING; + + /* Read data */ + ret = + i2c_master_recv(mt6605_dev->client, + (unsigned char *)(uintptr_t) I2CDMAReadBuf_pa, + count); + + /* mutex_unlock(&mt6605_dev->read_mutex); */ + + /*pr_debug("%s : i2c_master_recv returned=%d, irq status=%d\n", __func__, + ret, mt_nfc_get_gpio_value(mt6605_dev->irq_gpio));*/ + + if (ret < 0) { + pr_debug("%s: i2c_master_recv returned %d, irq status=%d\n", __func__, + ret, mt_nfc_get_gpio_value(mt6605_dev->irq_gpio)); + pr_debug("%s, enable clock buffer\n", __func__); + clk_buf_ctrl(CLK_BUF_NFC, 0); + usleep_range(900, 1000); + clk_buf_ctrl(CLK_BUF_NFC, 1); + return ret; + } + + if (ret > count) { + pr_debug("%s: received too many bytes from i2c (%d)\n", + __func__, ret); + return -EIO; + } + + if (copy_to_user(buf, I2CDMAReadBuf, ret)) { + pr_debug("%s : failed to copy to user space\n", __func__); + return -EFAULT; + } + + /* pr_debug("%s: return,ret,%d\n", __func__, ret); */ + + return ret; + +fail: + /* mutex_unlock(&mt6605_dev->read_mutex); */ + pr_debug("%s: return,fail,%d\n", __func__, ret); + return ret; + +} + +static ssize_t mt6605_dev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *offset) +{ + struct mt6605_dev *mt6605_dev; + int ret = 0, ret_tmp = 0, count_ori = 0, count_remain = 0, idx = 0; + + mt6605_dev = filp->private_data; + count_ori = count; + count_remain = count_ori; + + if (count > MAX_BUFFER_SIZE) { + count = MAX_BUFFER_SIZE; + count_remain -= count; + } + + while (1) { + if (copy_from_user + (I2CDMAWriteBuf, &buf[(idx * MAX_BUFFER_SIZE)], count)) { + pr_debug("%s : failed to copy from user space.\n", + __func__); + return -EFAULT; + } + + /*pr_debug("%s : writing %zu bytes, remain bytes %d.\n", __func__, + count, count_remain); */ + + /* Write data */ + mt6605_dev->client->addr = + (mt6605_dev->client->addr & I2C_MASK_FLAG); + + mt6605_dev->client->ext_flag |= I2C_DMA_FLAG; + /* mt6605_dev->client->ext_flag |= I2C_DIRECTION_FLAG; */ + /* mt6605_dev->client->ext_flag |= I2C_A_FILTER_MSG; */ + mt6605_dev->client->timing = NFC_CLIENT_TIMING; + + ret_tmp = + i2c_master_send(mt6605_dev->client, + (unsigned char *)(uintptr_t) + I2CDMAWriteBuf_pa, count); + + if (ret_tmp != count) { + pr_debug("%s : i2c_master_send returned %d\n", __func__, + ret); + ret = -EIO; + return ret; + } + + ret += ret_tmp; + /* pr_debug("%s : ret_tmp=%d,ret=%d,count_ori=%d\n", __func__, + ret_tmp, ret, count_ori); */ + + if (ret == count_ori) { + /* pr_debug("%s : ret == count_ori\n", __func__); */ + break; + } + + if (count_remain > MAX_BUFFER_SIZE) { + count = MAX_BUFFER_SIZE; + count_remain -= MAX_BUFFER_SIZE; + } else { + count = count_remain; + count_remain = 0; + } + idx++; + } + /* + pr_debug("%s : writing %d bytes. Status %d\n", __func__, count_ori, + ret);*/ + return ret; +} + +static int mt6605_dev_open(struct inode *inode, struct file *filp) +{ + + struct mt6605_dev *mt6605_dev = + container_of(filp->private_data, struct mt6605_dev, mt6605_device); + + filp->private_data = mt6605_dev; + mt6605_dev_ptr = mt6605_dev; + + pr_debug("mt6605_dev_open,%s : %d,%d, &mt6605_dev_open=%p\n", __func__, + imajor(inode), iminor(inode), mt6605_dev_ptr); + + forceExitBlockingRead = 0; + return 0; +} + +static long mt6605_dev_unlocked_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + + struct mt6605_dev *mt6605_dev = filp->private_data; + int result = 0; + int gpio_dir, gpio_num = -1, tmp_gpio; +/* + pr_debug("mt6605_dev_unlocked_ioctl: cmd=0x%04x,arg=0x%04lx.\n", cmd, + arg); +*/ + if ((cmd & 0xFFFF) == 0xFE00) { + + mt6605_disable_irq(nfc_irq); + + pr_debug("mt6605_dev_unlocked_ioctl for disable_irq.\n"); + + return 0; + } else if ((cmd & 0xFFFF) == 0xFE01) { + + struct device_node *node; + int ret; + +#if !defined(CONFIG_MTK_LEGACY) + mt_nfc_pinctrl_select(gpctrl, st_irq_init); +#else + mt_set_gpio_mode(mt6605_dev->irq_gpio, GPIO_IRQ_NFC_PIN_M_EINT); + mt_set_gpio_dir(mt6605_dev->irq_gpio, GPIO_DIR_IN); + mt_set_gpio_pull_enable(mt6605_dev->irq_gpio, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(mt6605_dev->irq_gpio, GPIO_PULL_DOWN); +#endif + + /* mt_eint_set_hw_debounce(CUST_EINT_IRQ_NFC_NUM, */ + /* CUST_EINT_IRQ_NFC_DEBOUNCE_CN); */ + /* mt_eint_registration(CUST_EINT_IRQ_NFC_NUM, */ + /* CUST_EINT_IRQ_NFC_TYPE, */ + /* mt6605_dev_irq_handler, 0); */ + /* mt_eint_mask(CUST_EINT_IRQ_NFC_NUM); */ + + /* NFC IRQ settings */ + node = + of_find_compatible_node(NULL, NULL, + "mediatek, IRQ_NFC-eint"); + + if (node) { + + nfc_irq = irq_of_parse_and_map(node, 0); + + /* client->irq = nfc_irq; */ + + ret = + request_irq(nfc_irq, mt6605_dev_irq_handler, + IRQF_TRIGGER_NONE, "irq_nfc-eint", + NULL); + + if (ret) { + pr_err("%s : EINT IRQ LINE NOT AVAILABLE\n", + __func__); + } else { + pr_debug + ("%s : set EINT finished, nfc_irq=%d.\n", + __func__, nfc_irq); + nfc_irq_count++; + mt6605_disable_irq(nfc_irq); + enable_irq_wake(nfc_irq); + } + } else { + pr_err("%s : can not find NFC eint compatible node.\n", + __func__); + } + + pr_debug("mt6605_dev_unlocked_ioctl,Re-registered IRQ.\n"); + return 0; + } else if ((cmd & 0xFFFF) == 0xFEFF) { /* EXIT EINT */ + mutex_lock(&mt6605_dev->read_mutex); + forceExitBlockingRead = 1; + mutex_unlock(&mt6605_dev->read_mutex); + + wake_up_interruptible(&mt6605_dev->read_wq); + pr_debug("mt6605_dev_unlocked_ioctl,SW Release IRQ.\n"); + return 0; + } else if ((cmd & 0xFFFF) == 0xFEFE) { /* Get ChipID */ + return fgNfcChip; + } else if ((cmd & 0xFFFF) == 0xFEFD) { + fgNfcChip = (arg & 0xFFFF); + return 0; + } + + tmp_gpio = (((arg & 0xFF00) >> 8) & 0x00FF); + + if (tmp_gpio == MTK_NFC_GPIO_EN_B) { + gpio_num = mt6605_dev->ven_gpio; + + } else if (tmp_gpio == MTK_NFC_GPIO_SYSRST_B) { + gpio_num = mt6605_dev->sysrstb_gpio; + + } else if (tmp_gpio == MTK_NFC_GPIO_EINT) { + gpio_num = mt6605_dev->eint_gpio; + + } else if (tmp_gpio == MTK_NFC_GPIO_IRQ) { + gpio_num = mt6605_dev->irq_gpio; + + } else if (tmp_gpio == MTK_NFC_GPIO_IOCTL) { + /* IOCTL */ + int command = (arg & 0x00FF); + + switch (command) { + case MTK_NFC_IOCTL_CMD_CLOCK_BUF_ENABLE: + pr_debug("%s, enable clock buffer.\n", __func__); +#ifndef CONFIG_MTK_FPGA + /* enable nfc clock buffer */ + clk_buf_ctrl(CLK_BUF_NFC, 1); +#endif + break; + case MTK_NFC_IOCTL_CMD_CLOCK_BUF_DISABLE: + pr_debug("%s, disable clock buffer.\n", __func__); +#ifndef CONFIG_MTK_FPGA + /* disable nfc clock buffer */ + clk_buf_ctrl(CLK_BUF_NFC, 0); +#endif + break; + case MTK_NFC_IOCTL_CMD_EXIT_EINT: + pr_debug("mt6605_dev_unlocked_ioctl, EXIT EINT.\n"); + mutex_lock(&mt6605_dev->read_mutex); + forceExitBlockingRead = 1; + mutex_unlock(&mt6605_dev->read_mutex); + wake_up_interruptible(&mt6605_dev->read_wq); + pr_debug("mt6605_dev_unlocked_ioctl,SW Release IRQ\n"); + break; + case MTK_NFC_IOCTL_CMD_GET_CHIP_ID: + return fgNfcChip; + case MTK_NFC_IOCTL_CMD_READ_DATA: + pr_debug("Call mt6605_dev_irq_handler. irq=%d.\n", + mt_nfc_get_gpio_value(mt6605_dev->irq_gpio)); + if (mt_nfc_get_gpio_value(mt6605_dev->irq_gpio)) + mt6605_dev_irq_handler(nfc_irq, NULL); + break; + default: + break; + } + return 0; + } + + if ((tmp_gpio != MTK_NFC_GPIO_EN_B) && (tmp_gpio != MTK_NFC_GPIO_SYSRST_B) + && (tmp_gpio != MTK_NFC_GPIO_EINT) && (tmp_gpio != MTK_NFC_GPIO_IRQ)) { + result = MTK_NFC_PULL_INVALID; + pr_debug("%s, invalid ioctl.\n", __func__); + return result; + } + + if (-1 == gpio_num) + return 0; + + /* if (result != MTK_NFC_PULL_INVALID) { */ + if (cmd == MTK_NFC_IOCTL_READ) { + result = mt_nfc_get_gpio_value(gpio_num); + /* + if ((gpio_dir == GPIO_DIR_IN) + || (gpio_dir == GPIO_DIR_OUT)) { + result = mt_get_gpio_in(gpio_num); + } else { + result = MTK_NFC_PULL_INVALID; + } */ + + if (0 == result) + pr_debug("%s : get gpio value: %d, gpio_num: %d\n", __func__, result, gpio_num); + + /*error handler for eint_registration abnormal case */ + if (tmp_gpio == MTK_NFC_GPIO_IRQ && result == 0x01) { + pr_debug + ("%s,irq=igh call mt6605_dev_irq_handler\n", + __func__); + mt6605_dev_irq_handler(nfc_irq, NULL); + } + + } else if (cmd == MTK_NFC_IOCTL_WRITE) { + gpio_dir = mt_nfc_get_gpio_dir(gpio_num); + + if (gpio_dir == MTK_NFC_GPIO_DIR_OUT) { + int gpio_pol = (arg & 0x00FF); + + if (gpio_pol == MTK_NFC_PULL_LOW) { +#if !defined(CONFIG_MTK_LEGACY) + switch (tmp_gpio) { + case MTK_NFC_GPIO_EN_B: + result = + mt_nfc_pinctrl_select(gpctrl, + st_ven_l); + break; + + case MTK_NFC_GPIO_SYSRST_B: + result = + mt_nfc_pinctrl_select(gpctrl, + st_rst_l); + break; + + case MTK_NFC_GPIO_EINT: + result = + mt_nfc_pinctrl_select(gpctrl, + st_eint_l); + break; + + case MTK_NFC_GPIO_IRQ: + pr_debug + ("%s : IRQ cannot set.\n", + __func__); + break; + default: + pr_debug("%s : default case.\n", + __func__); + break; + } +#else + result = + mt_set_gpio_out(gpio_num, GPIO_OUT_ZERO); + /* pr_debug("%s : call mtk legacy.\n", __func__); */ +#endif + } else if (gpio_pol == MTK_NFC_PULL_HIGH) { +#if !defined(CONFIG_MTK_LEGACY) + switch (tmp_gpio) { + case MTK_NFC_GPIO_EN_B: + result = + mt_nfc_pinctrl_select(gpctrl, + st_ven_h); + break; + + case MTK_NFC_GPIO_SYSRST_B: + result = + mt_nfc_pinctrl_select(gpctrl, + st_rst_h); + break; + + case MTK_NFC_GPIO_EINT: + result = + mt_nfc_pinctrl_select(gpctrl, + st_eint_h); + break; + + case MTK_NFC_GPIO_IRQ: + pr_debug + ("%s : IRQ cannot pull.\n", + __func__); + break; + default: + pr_debug("%s : default case.\n", + __func__); + break; + } +#else + result = + mt_set_gpio_out(gpio_num, GPIO_OUT_ONE); + /* pr_debug("%s : call mtk legacy.\n", __func__); */ +#endif + } + } else { + result = MTK_NFC_PULL_INVALID; + } + } else { + result = MTK_NFC_PULL_INVALID; + } + /* } */ +/* + pr_debug("mt6605_dev_unlocked_ioctl : result=%d\n", result); +*/ + return result; +} + +#if !defined(CONFIG_MTK_LEGACY) +static int mt_nfc_pinctrl_select(struct pinctrl *p, struct pinctrl_state *s) +{ + int ret = 0; + + if (p != NULL && s != NULL) { + ret = pinctrl_select_state(p, s); + } else { + pr_debug("%s : pinctrl_select err\n", __func__); + ret = -1; + } + return ret; +} + +static int mt_nfc_pinctrl_init(struct platform_device *pdev) +{ + int ret = 0; + + gpctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(gpctrl)) { + dev_err(&pdev->dev, "Cannot find pinctrl!"); + ret = PTR_ERR(gpctrl); + goto end; + } + + st_ven_h = pinctrl_lookup_state(gpctrl, "ven_high"); + if (IS_ERR(st_ven_h)) { + ret = PTR_ERR(st_ven_h); + pr_debug("%s : pinctrl err, ven_high\n", __func__); + } + + st_ven_l = pinctrl_lookup_state(gpctrl, "ven_low"); + if (IS_ERR(st_ven_l)) { + ret = PTR_ERR(st_ven_l); + pr_debug("%s : pinctrl err, ven_low\n", __func__); + } + + st_rst_h = pinctrl_lookup_state(gpctrl, "rst_high"); + if (IS_ERR(st_rst_h)) { + ret = PTR_ERR(st_rst_h); + pr_debug("%s : pinctrl err, rst_high\n", __func__); + } + + st_rst_l = pinctrl_lookup_state(gpctrl, "rst_low"); + if (IS_ERR(st_rst_l)) { + ret = PTR_ERR(st_rst_l); + pr_debug("%s : pinctrl err, rst_low\n", __func__); + } + + st_eint_h = pinctrl_lookup_state(gpctrl, "eint_high"); + if (IS_ERR(st_eint_h)) { + ret = PTR_ERR(st_eint_h); + pr_debug("%s : pinctrl err, eint_high\n", __func__); + } + + st_eint_l = pinctrl_lookup_state(gpctrl, "eint_low"); + if (IS_ERR(st_eint_l)) { + ret = PTR_ERR(st_eint_l); + pr_debug("%s : pinctrl err, eint_low\n", __func__); + } + + st_irq_init = pinctrl_lookup_state(gpctrl, "irq_init"); + if (IS_ERR(st_irq_init)) { + ret = PTR_ERR(st_irq_init); + pr_debug("%s : pinctrl err, irq_init\n", __func__); + } + + /* select state */ + ret = mt_nfc_pinctrl_select(gpctrl, st_irq_init); + usleep_range(900, 1000); + + ret = mt_nfc_pinctrl_select(gpctrl, st_ven_h); + usleep_range(900, 1000); + + ret = mt_nfc_pinctrl_select(gpctrl, st_rst_h); + usleep_range(900, 1000); + + ret = mt_nfc_pinctrl_select(gpctrl, st_eint_l); + +end: + + return ret; +} + +static int mt_nfc_gpio_init(void) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "mediatek,nfc-gpio-v2"); + + if (node) { + of_property_read_u32_array(node, "gpio-ven", + &(mt6605_platform_data.ven_gpio), 1); + of_property_read_u32_array(node, "gpio-rst", + &(mt6605_platform_data.sysrstb_gpio), + 1); + of_property_read_u32_array(node, "gpio-eint", + &(mt6605_platform_data.eint_gpio), + 1); + of_property_read_u32_array(node, "gpio-irq", + &(mt6605_platform_data.irq_gpio), 1); + } else { + pr_debug("%s : get gpio num err.\n", __func__); + return -1; + } + + _gmt6605_dev.irq_gpio = mt6605_platform_data.irq_gpio; + _gmt6605_dev.ven_gpio = mt6605_platform_data.ven_gpio; + _gmt6605_dev.sysrstb_gpio = mt6605_platform_data.sysrstb_gpio; + _gmt6605_dev.eint_gpio = mt6605_platform_data.eint_gpio; + + return 0; +} +#endif + +static int mt_nfc_get_gpio_value(int gpio_num) +{ + int value = 0; + + if (mt_nfc_get_gpio_dir(gpio_num) != MTK_NFC_GPIO_DIR_INVALID) { +#if !defined(CONFIG_MTK_LEGACY) + value = __gpio_get_value(gpio_num); +#else + value = mt_get_gpio_in(gpio_num); +#endif + } + + return value; +} + +static int mt_nfc_get_gpio_dir(int gpio_num) +{ + if (gpio_num == mt6605_platform_data.irq_gpio) { + return MTK_NFC_GPIO_DIR_IN; /* input */ + + } else if ((gpio_num == mt6605_platform_data.ven_gpio) || + (gpio_num == mt6605_platform_data.sysrstb_gpio) || + (gpio_num == mt6605_platform_data.eint_gpio)) { + return MTK_NFC_GPIO_DIR_OUT; /* output */ + + } else { + return MTK_NFC_GPIO_DIR_INVALID; + + } +} + +/* return 0, success; return <0, fail + * md_id : modem id + * md_state : 0, on ; 1, off ; + * vsim_state : 0, on ; 1, off; + */ +int inform_nfc_vsim_change(int md_id, int md_state, int vsim_state) +{ + char send_data[] = { + 0xaa, 0x0f, 0x03, 0x00, 0x03, + 0x00, 0x00, 0xaa, 0xf0 + }; + int ret = 0; + int send_bytes = sizeof(send_data); + int retry; + + /* AA 0F 03 00 03 00 xx AA F0 */ + /* where xx is defined: */ + /* Bit[7:4] : md_id */ + /* Bit[3:2] : md_state */ + /* Bit[1:0] : vsim_state */ + + send_data[6] |= (md_id << 4); + send_data[6] |= (md_state << 2); + send_data[6] |= (vsim_state); + + pr_debug + ("%s, md_id,%d, md_state,%d, vsim_state,%d , send_data[6],0x%X.\n", + __func__, md_id, md_state, vsim_state, send_data[6]); + + /* send to mt6605 */ + _gmt6605_dev.client->addr = (_gmt6605_dev.client->addr & I2C_MASK_FLAG); + _gmt6605_dev.client->ext_flag |= I2C_DMA_FLAG; + _gmt6605_dev.client->timing = 400; + memcpy(I2CDMAWriteBuf, send_data, send_bytes); + + /* eint pull high */ +#if !defined(CONFIG_MTK_LEGACY) + mt_nfc_pinctrl_select(gpctrl, st_eint_h); +#else + ret = mt_set_gpio_out(mt6605_platform_data.eint_gpio, GPIO_OUT_ONE); +#endif + + /* sleep 5ms */ + /* msleep(5); */ + usleep_range(1800, 2000); + + for (retry = 0; retry < 10; retry++) { + /* ret = i2c_master_send(_gmt6605_dev.client, */ + /* (unsigned char *)I2CDMAWriteBuf_pa, send_bytes); */ + ret = + i2c_master_send(_gmt6605_dev.client, + (unsigned char *)(uintptr_t) + I2CDMAWriteBuf_pa, send_bytes); + if (ret == send_bytes) { + pr_debug + ("%s, send to mt6605 OK. retry %d.\n", + __func__, retry); + break; + } + pr_debug + ("%s, send to mt6605 fail. retry %d, ret %d.\n", + __func__, retry, ret); + /* sleep 2ms */ + /* msleep(2); */ + usleep_range(1800, 2000); + } + /* eint pull low */ + +#if !defined(CONFIG_MTK_LEGACY) + mt_nfc_pinctrl_select(gpctrl, st_eint_l); +#else + ret = mt_set_gpio_out(mt6605_platform_data.eint_gpio, GPIO_OUT_ZERO); +#endif + return 0; +} + +/* + * module load/unload record keeping + */ +static int __init mt6605_dev_init(void) +{ + int ret; + + pr_debug("mt6605_dev_init\n"); + /* i2c_register_board_info(NFC_I2C_BUSNUM, &nfc_board_info, 1); */ + /* pr_debug("mt6605_dev_init2\n"); */ + + platform_driver_register(&mtk_nfc_platform_driver); + + i2c_add_driver(&mt6605_dev_driver); + + _gmt6605_dev.mt6605_device.minor = MISC_DYNAMIC_MINOR; + _gmt6605_dev.mt6605_device.name = "mt6605"; + _gmt6605_dev.mt6605_device.fops = &mt6605_dev_fops; + + ret = misc_register(&_gmt6605_dev.mt6605_device); + if (ret) { + pr_debug("%s : misc_register failed\n", __FILE__); + return ret; + } + + pr_debug("mt6605_dev_init success\n"); + return 0; +} + +static void __exit mt6605_dev_exit(void) +{ + pr_debug("mt6605_dev_exit\n"); + + i2c_del_driver(&mt6605_dev_driver); +} + +module_init(mt6605_dev_init); +module_exit(mt6605_dev_exit); + +MODULE_AUTHOR("LiangChi Huang"); +MODULE_DESCRIPTION("MTK NFC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/performance/fliper/mt6755/Makefile b/drivers/misc/mediatek/performance/fliper/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9671a4bf14a777ba0723c51ec0e627dc9e594859 --- /dev/null +++ b/drivers/misc/mediatek/performance/fliper/mt6755/Makefile @@ -0,0 +1,15 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += fliper.o +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/ diff --git a/drivers/misc/mediatek/performance/fliper/mt6755/fliper.c b/drivers/misc/mediatek/performance/fliper/mt6755/fliper.c new file mode 100644 index 0000000000000000000000000000000000000000..4ff9bc7de296dd061ba6ec5da8baa445d079479d --- /dev/null +++ b/drivers/misc/mediatek/performance/fliper/mt6755/fliper.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#define SEQ_printf(m, x...)\ + do {\ + if (m)\ + seq_printf(m, x);\ + else\ + pr_debug(x);\ + } while (0) +#undef TAG +#define TAG "[SOC DVFS FLIPER]" + + +static int cg_lpm_bw_threshold, cg_hpm_bw_threshold; +static int total_lpm_bw_threshold, total_hpm_bw_threshold; +static int cg_fliper_enabled, total_fliper_enabled; +static int fliper_debug; +static int LPM_MAX_BW, HPM_MAX_BW; +static int TOTAL_LPM_BW_THRESHOLD, TOTAL_HPM_BW_THRESHOLD; + +/******* FLIPER SETTING *********/ + +int getTotalHistory(void) +{ + return BM_GetBWST(); +} + +int getCGHistory(void) +{ + return BM_GetBWST1(); +} + +int getTotalConfiguration(void) +{ + return BM_GetBW(); +} + +int getCGConfiguration(void) +{ + return BM_GetBW1(); +} + +int setTotal(const unsigned int value) +{ + int ret; + + ret = BM_SetBW(value); + + return ret; +} + +int setCG(const unsigned int value) +{ + int ret; + + ret = BM_SetBW1(value); + + return ret; +} + +void enable_cg_fliper(int enable) +{ + + if (enable) { + vcorefs_enable_perform_bw(true); + pr_debug(TAG"CG fliper enabled\n"); + + cg_fliper_enabled = 1; + } else { + vcorefs_enable_perform_bw(false); + pr_debug(TAG"CG fliper disabled\n"); + + cg_fliper_enabled = 0; + } +} + +void enable_total_fliper(int enable) +{ + + if (enable) { + vcorefs_enable_total_bw(true); + pr_debug(TAG"TOTAL fliper enabled\n"); + + total_fliper_enabled = 1; + } else { + vcorefs_enable_total_bw(false); + pr_debug(TAG"TOTAL fliper disabled\n"); + + total_fliper_enabled = 0; + } +} + +int disable_cg_fliper(void) +{ + fliper_debug = 1; + enable_cg_fliper(0); + + return 0; +} + +int cg_set_threshold(int bw1, int bw2) +{ + int lpm_threshold, hpm_threshold; + int ddr_perf = vcorefs_get_ddr_by_steps(OPPI_PERF); + int ddr_curr = vcorefs_get_curr_ddr(); + + if (bw1 <= BW_THRESHOLD_MAX && bw1 >= BW_THRESHOLD_MIN && + bw2 <= BW_THRESHOLD_MAX && bw2 >= BW_THRESHOLD_MIN) { + lpm_threshold = bw1 * THRESHOLD_SCALE / LPM_MAX_BW + 1; + hpm_threshold = bw2 * THRESHOLD_SCALE / HPM_MAX_BW; + if (lpm_threshold > 127 || lpm_threshold < 1 || hpm_threshold > 127 || hpm_threshold < 1) { + pr_debug(TAG"error set threshold out of range\n"); + return 0; + } + if (ddr_perf == ddr_curr) { + setCG(0x210080 | (hpm_threshold << 8)); + pr_debug(TAG"ddr high, Configure CG: 0x%08x\n", getCGConfiguration()); + } else { + setCG(0x210080 | (lpm_threshold << 8)); + pr_debug(TAG"ddr low, Configure CG: 0x%08x\n", getCGConfiguration()); + } + vcorefs_set_perform_bw_threshold(lpm_threshold, hpm_threshold); + pr_debug(TAG"Set CG bdw threshold %d %d -> %d %d, (%d,%d)\n", + cg_lpm_bw_threshold, cg_hpm_bw_threshold, bw1, bw2, lpm_threshold, hpm_threshold); + + cg_lpm_bw_threshold = bw1; + cg_hpm_bw_threshold = bw2; + + } else { + pr_debug(TAG"Set CG bdw threshold Error: (MAX:%d, MIN:%d)\n", + BW_THRESHOLD_MAX, BW_THRESHOLD_MIN); + } + + return 0; +} + +int total_set_threshold(int bw1, int bw2) +{ + int lpm_threshold, hpm_threshold; + int ddr_perf = vcorefs_get_ddr_by_steps(OPPI_PERF); + int ddr_curr = vcorefs_get_curr_ddr(); + + pr_debug(TAG"arg bw1=%d bw2=%d\n", bw1, bw2); + if (bw1 <= BW_THRESHOLD_MAX && bw1 >= BW_THRESHOLD_MIN && + bw2 <= BW_THRESHOLD_MAX && bw2 >= BW_THRESHOLD_MIN) { + lpm_threshold = bw1 * THRESHOLD_SCALE / LPM_MAX_BW; + hpm_threshold = bw2 * THRESHOLD_SCALE / HPM_MAX_BW; + if (lpm_threshold > 127 || lpm_threshold < 1 || hpm_threshold > 127 || hpm_threshold < 1) { + pr_debug(TAG"error set threshold out of range\n"); + return 0; + } + if (ddr_perf == ddr_curr) { + setTotal(0x2100a0 | (hpm_threshold << 8)); + pr_debug(TAG"ddr high, Configure TOTAL: 0x%08x\n", getTotalConfiguration()); + } else { + setTotal(0x2100a0 | (lpm_threshold << 8)); + pr_debug(TAG"ddr low, Configure TOTAL: 0x%08x\n", getTotalConfiguration()); + } + vcorefs_set_total_bw_threshold(lpm_threshold, hpm_threshold); + pr_debug(TAG"Set TOTAL bdw threshold %d %d-> %d %d, (%d,%d)\n", + total_lpm_bw_threshold, total_hpm_bw_threshold, bw1, bw2, lpm_threshold, hpm_threshold); + + total_lpm_bw_threshold = bw1; + total_hpm_bw_threshold = bw2; + + } else { + pr_debug(TAG"Set TOTAL bdw threshold Error: (MAX:%d, MIN:%d)\n", + BW_THRESHOLD_MAX, BW_THRESHOLD_MIN); + } + + return 0; +} + +int cg_restore_threshold(void) +{ + pr_debug(TAG"Restore CG bdw threshold %d %d -> %d %d\n", + cg_lpm_bw_threshold, cg_hpm_bw_threshold, CG_DEFAULT_LPM, CG_DEFAULT_HPM); + cg_set_threshold(CG_DEFAULT_LPM, CG_DEFAULT_HPM); + return 0; +} + +int total_restore_threshold(void) +{ + pr_debug(TAG"Restore TOTAL bdw threshold %d %d -> %d %d\n", + total_lpm_bw_threshold, total_hpm_bw_threshold, + TOTAL_LPM_BW_THRESHOLD, TOTAL_HPM_BW_THRESHOLD); + total_set_threshold(TOTAL_LPM_BW_THRESHOLD, TOTAL_HPM_BW_THRESHOLD); + return 0; +} + +static ssize_t mt_fliper_write(struct file *filp, const char *ubuf, + size_t cnt, loff_t *data) +{ + char buf[64]; + int ret; + unsigned long arg1, arg2; + char option[64], arg[10]; + int i, j; + + arg1 = 0; + arg2 = 0; + + if (cnt >= sizeof(buf)) + return -EINVAL; + + if (copy_from_user(&buf, ubuf, cnt)) + return -EFAULT; + buf[cnt] = '\0'; + + /* get option */ + for (i = 0; i < cnt && buf[i] != ' '; i++) + option[i] = buf[i]; + option[i] = '\0'; + + /* get arg1 */ + for (; i < cnt && buf[i] == ' '; i++) + ; + for (j = 0; i < cnt && buf[i] != ' '; i++, j++) + arg[j] = buf[i]; + arg[j] = '\0'; + if (j > 0) { + ret = kstrtoul(arg, 0, (unsigned long *)&arg1); + if (ret < 0) { + pr_debug(TAG"1 ret of kstrtoul is broke\n"); + return ret; + } + } + + /* get arg2 */ + for (; i < cnt && buf[i] == ' '; i++) + ; + for (j = 0; i < cnt && buf[i] != ' '; i++, j++) + arg[j] = buf[i]; + arg[j] = '\0'; + if (j > 0) { + ret = kstrtoul(arg, 0, (unsigned long *)&arg2); + if (ret < 0) { + pr_debug(TAG"2 ret of kstrtoul is broke\n"); + return ret; + } + } + + if (strncmp(option, "ENABLE_CG", 9) == 0) { + enable_cg_fliper(arg1); + } else if (strncmp(option, "ENABLE_TOTAL", 12) == 0) { + enable_total_fliper(arg1); + } else if (strncmp(option, "SET_CG_THRES", 12) == 0) { + cg_set_threshold(arg1, arg2); + } else if (strncmp(option, "SET_TOTAL_THRES", 15) == 0) { + total_set_threshold(arg1, arg2); + } else if (strncmp(option, "RESTORE_CG", 10) == 0) { + cg_restore_threshold(); + } else if (strncmp(option, "RESTORE_TOTAL", 13) == 0) { + total_restore_threshold(); + } else if (strncmp(option, "SET_CG", 6) == 0) { + setCG(arg1); + } else if (strncmp(option, "SET_TOTAL", 9) == 0) { + setTotal(arg1); + } else if (strncmp(option, "POWER_MODE", 10) == 0) { + if (!fliper_debug) { + if (arg1 == Default) { + pr_debug(TAG"POWER_MODE: default\n"); + enable_cg_fliper(1); + cg_set_threshold(CG_DEFAULT_LPM, CG_DEFAULT_HPM); + vcorefs_request_dvfs_opp(KIR_PERF, OPPI_UNREQ); + } else if (arg1 == Low_Power_Mode) { + pr_debug(TAG"POWER_MODE: LOW_POWER\n"); + enable_cg_fliper(1); + cg_set_threshold(CG_LOW_POWER_LPM, CG_LOW_POWER_HPM); + vcorefs_request_dvfs_opp(KIR_PERF, OPPI_UNREQ); + } else if (arg1 == Just_Make_Mode) { + pr_debug(TAG"POWER_MODE: JUST_MAKE\n"); + enable_cg_fliper(1); + cg_set_threshold(CG_JUST_MAKE_LPM, CG_JUST_MAKE_HPM); + vcorefs_request_dvfs_opp(KIR_PERF, OPPI_UNREQ); + } else if (arg1 == Performance_Mode) { + pr_debug(TAG"POWER_MODE: PERFORMANCE\n"); + enable_cg_fliper(1); +#if 0 + cg_set_threshold(CG_PERFORMANCE_LPM, CG_PERFORMANCE_HPM); +#else + vcorefs_request_dvfs_opp(KIR_PERF, OPPI_PERF); +#endif + } + } + } else if (strncmp(option, "DEBUG", 5) == 0) { + fliper_debug = arg1; + } else { + pr_debug(TAG"unknown option\n"); + } + + return cnt; +} + +static int mt_fliper_show(struct seq_file *m, void *v) +{ + SEQ_printf(m, "-----------------------------------------------------\n"); + SEQ_printf(m, "CG Fliper Enabled:%d, bw threshold:%d %dMB/s\n", + cg_fliper_enabled, cg_lpm_bw_threshold, cg_hpm_bw_threshold); + SEQ_printf(m, "TOTAL Fliper Enabled:%d, bw threshold:%d %dMB/s\n", + total_fliper_enabled, total_lpm_bw_threshold, total_hpm_bw_threshold); + SEQ_printf(m, "CG History: 0x%08x\n", getCGHistory()); + SEQ_printf(m, "TOTAL History: 0x%08x\n", getTotalHistory()); + SEQ_printf(m, "CG Configuration: 0x%08x\n", getCGConfiguration()); + SEQ_printf(m, "TOTAL Configuration: 0x%08x\n", getTotalConfiguration()); + SEQ_printf(m, "-----------------------------------------------------\n"); + return 0; +} +/*** Seq operation of mtprof ****/ +static int mt_fliper_open(struct inode *inode, struct file *file) +{ + return single_open(file, mt_fliper_show, inode->i_private); +} + +static const struct file_operations mt_fliper_fops = { + .open = mt_fliper_open, + .write = mt_fliper_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + static int +fliper_pm_callback(struct notifier_block *nb, + unsigned long action, void *ptr) +{ + switch (action) { + + case PM_SUSPEND_PREPARE: + break; + case PM_HIBERNATION_PREPARE: + break; + + case PM_POST_SUSPEND: + pr_debug(TAG"Resume, restore CG configuration\n"); + cg_set_threshold(cg_lpm_bw_threshold, cg_hpm_bw_threshold); + break; + + case PM_POST_HIBERNATION: + break; + + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + + +/*--------------------INIT------------------------*/ + +static int __init init_fliper(void) +{ + struct proc_dir_entry *pe; + + pr_debug(TAG"init fliper driver start\n"); + pe = proc_create("fliper", 0644, NULL, &mt_fliper_fops); + if (!pe) + return -ENOMEM; + + LPM_MAX_BW = dram_steps_freq(1) * 4; + HPM_MAX_BW = dram_steps_freq(0) * 4; + TOTAL_LPM_BW_THRESHOLD = LPM_MAX_BW * 9 / 10; + TOTAL_HPM_BW_THRESHOLD = HPM_MAX_BW * 1 / 2; + pr_debug(TAG"(LPM_MAX_BW,HPM_MAX_BW):%d,%d\n", LPM_MAX_BW, HPM_MAX_BW); + + cg_set_threshold(CG_DEFAULT_LPM, CG_DEFAULT_HPM); + total_set_threshold(TOTAL_LPM_BW_THRESHOLD, TOTAL_HPM_BW_THRESHOLD); + enable_cg_fliper(1); + enable_total_fliper(1); + + fliper_debug = 0; + + pm_notifier(fliper_pm_callback, 0); + + + pr_debug(TAG"init fliper driver done\n"); + + return 0; +} +late_initcall(init_fliper); + diff --git a/drivers/misc/mediatek/performance/perfmgr/mt6755/Makefile b/drivers/misc/mediatek/performance/perfmgr/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..aa8f80bc645a8fb7d7965ca95a5f673f965b2b6c --- /dev/null +++ b/drivers/misc/mediatek/performance/perfmgr/mt6755/Makefile @@ -0,0 +1,4 @@ +obj-y += perfmgr_boost.o \ + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach + diff --git a/drivers/misc/mediatek/performance/perfmgr/mt6755/perfmgr_boost.c b/drivers/misc/mediatek/performance/perfmgr/mt6755/perfmgr_boost.c new file mode 100644 index 0000000000000000000000000000000000000000..ae1bcb5fada1c99ba949351f7c433d929d141211 --- /dev/null +++ b/drivers/misc/mediatek/performance/perfmgr/mt6755/perfmgr_boost.c @@ -0,0 +1,52 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "mt_ppm_api.h" + +/*--------------DEFAULT SETTING-------------------*/ + +#define TARGET_CORE (3) +#define TARGET_FREQ (1014000) + +/*-----------------------------------------------*/ + +int perfmgr_get_target_core(void) +{ + return TARGET_CORE; +} + +int perfmgr_get_target_freq(void) +{ + return TARGET_FREQ; +} + +void perfmgr_boost(int enable, int core, int freq) +{ + if (enable) { + mt_ppm_sysboost_core(BOOST_BY_PERFSERV, core); + mt_ppm_sysboost_freq(BOOST_BY_PERFSERV, freq); + } else { + mt_ppm_sysboost_core(BOOST_BY_PERFSERV, 0); + mt_ppm_sysboost_freq(BOOST_BY_PERFSERV, 0); + } +} + diff --git a/drivers/misc/mediatek/pmic_wrap/mt6755/Makefile b/drivers/misc/mediatek/pmic_wrap/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4e1738ed96946cb73e5c1af1e489183332445bb0 --- /dev/null +++ b/drivers/misc/mediatek/pmic_wrap/mt6755/Makefile @@ -0,0 +1,19 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + + +ifeq ($(CONFIG_MTK_PMIC_NEW_ARCH),y) + obj-$(CONFIG_MTK_PMIC_WRAP) += pwrap_hal_v1.o +else +obj-$(CONFIG_MTK_PMIC_WRAP) += pwrap_hal.o +endif diff --git a/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal.c b/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal.c new file mode 100644 index 0000000000000000000000000000000000000000..46a563d1a7afbcba9de36cbf16d3c683f4468fc8 --- /dev/null +++ b/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal.c @@ -0,0 +1,1928 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/****************************************************************************** + * pwrap_hal.c - Linux pmic_wrapper Driver,hardware_dependent driver + * + * + * DESCRIPTION: + * This file provid the other drivers PMIC wrapper relative functions + * + ******************************************************************************/ + +/*-----start-- Driver Config-------------------------------------------------*/ +/* #define PMIC_WRAP_PRELOADER_DRIVER */ +/* #define PMIC_WRAP_LK_DRIVER */ +#define PMIC_WRAP_KERNEL_DRIVER +/*-----end -- Driver Config-------------------------------------------------*/ + +#ifdef PMIC_WRAP_PRELOADER_DRIVER +#include +#include +#include +#include "pmic_wrap_init.h" +#endif + +#ifdef PMIC_WRAP_LK_DRIVER +#include +#endif + +#ifdef PMIC_WRAP_KERNEL_DRIVER +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include +#include +#include + +#include +/* #include */ +#include "pwrap_hal.h" + +#define PMIC_WRAP_DEVICE "pmic_wrap" + +/*-----start-- global variable-----------------------------------------------*/ +#ifdef CONFIG_OF +void __iomem *pwrap_base; +static void __iomem *topckgen_reg_base; +static void __iomem *infracfg_ao_reg_base; +static void __iomem *gpio_reg_base; +static void __iomem *sleep_reg_base; +#endif + +static struct mt_pmic_wrap_driver *mt_wrp; + +static DEFINE_SPINLOCK(wrp_lock); +static DEFINE_SPINLOCK(wrp_lock_isr); +#endif /* End of #ifdef PMIC_WRAP_KERNEL_DRIVER */ + +/*-----start--Internal API---------------------------------------------------*/ +static s32 _pwrap_init_dio(u32 dio_en); +static s32 _pwrap_init_cipher(void); +static s32 _pwrap_init_reg_clock(u32 regck_sel); +static s32 _pwrap_wacs2_nochk(u32 write, u32 adr, u32 wdata, u32 *rdata); +static s32 _pwrap_reset_spislv(void); + +/*-----end --Internal API---------------------------------------------------*/ + +#ifdef PMIC_WRAP_KERNEL_DRIVER +#ifdef CONFIG_OF +static int pwrap_of_iomap(void); +static void pwrap_of_iounmap(void); +#endif +#endif /* End of #ifdef PMIC_WRAP_KERNEL_DRIVER */ + +#ifdef PMIC_WRAP_NO_PMIC +/*-pwrap debug--------------------------------------------------------------------------*/ +void pwrap_dump_all_register(void) +{ + return; +} + +#ifndef PMIC_WRAP_KERNEL_DRIVER +s32 pwrap_wacs2(u32 write, u32 adr, u32 wdata, u32 *rdata) +{ + PWRAPERR("there is no PMIC real chip,PMIC_WRAP do Nothing\n"); + return 0; +} +#endif + +/*********************************************************************************/ +/* extern API for PMIC driver, INT related control, this INT is for PMIC chip to AP */ +/*********************************************************************************/ +#ifndef PMIC_WRAP_KERNEL_DRIVER +s32 pwrap_read(u32 adr, u32 *rdata) +{ + return pwrap_wacs2(0, adr, 0, rdata); +} + +s32 pwrap_write(u32 adr, u32 wdata) +{ + return pwrap_wacs2(1, adr, wdata, 0); +} +#else +u32 mt_pmic_wrap_eint_status(void) +{ + PWRAPLOG("[PMIC2]first of all PMIC_WRAP_STAUPD_GRPEN=0x%x\n", + WRAP_RD32(PMIC_WRAP_STAUPD_GRPEN)); + PWRAPLOG("[PMIC2]first of all PMIC_WRAP_EINT_STA=0x%x\n", WRAP_RD32(PMIC_WRAP_EINT_STA)); + return WRAP_RD32(PMIC_WRAP_EINT_STA); +} + +void mt_pmic_wrap_eint_clr(int offset) +{ + if ((offset < 0) || (offset > 3)) + PWRAPERR("clear EINT flag error, only 0-3 bit\n"); + else + WRAP_WR32(PMIC_WRAP_EINT_CLR, (1 << offset)); + +} + +/* -------------------------------------------------------- */ +/* Function : pwrap_wacs2_hal() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 pwrap_wacs2_hal(u32 write, u32 adr, u32 wdata, u32 *rdata) +{ + PWRAPERR("there is no PMIC real chip,PMIC_WRAP do Nothing\n"); + return 0; +} +#endif /* End of #ifndef PMIC_WRAP_KERNEL_DRIVER */ + +/* + *pmic_wrap init,init wrap interface + * + */ +s32 pwrap_init(void) +{ + PWRAPERR("There is no PMIC real chip, PMIC_WRAP do Nothing.\n"); + return 0; +} + +s32 pwrap_read_nochk(u32 adr, u32 *rdata) +{ + return pwrap_wacs2_hal(0, adr, 0, rdata); +} + +s32 pwrap_write_nochk(u32 adr, u32 wdata) +{ + return pwrap_wacs2_hal(1, adr, wdata, 0); +} + +#ifdef PMIC_WRAP_PRELOADER_DRIVER +s32 pwrap_init_preloader(void) +{ + u32 pwrap_ret = 0, i = 0; + + PWRAPFUC(); + for (i = 0; i < 3; i++) { + pwrap_ret = pwrap_init(); + if (pwrap_ret != 0) { + printf("[PMIC_WRAP]wrap_init fail,the return value=%x.\n", pwrap_ret); + } else { + printf("[PMIC_WRAP]wrap_init pass,the return value=%x.\n", pwrap_ret); + break; /* init pass */ + } + } +#ifdef PWRAP_PRELOADER_PORTING + /* pwrap_init_for_early_porting(); */ +#endif + return 0; +} + +#ifdef PWRAP_PRELOADER_PORTING +/* -------------------------------------------------------- */ +/* Function : _pwrap_status_update_test() */ +/* Description :only for early porting */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_status_update_test_porting(void) +{ + return 0; + +} + +void pwrap_init_for_early_porting(void) +{ + +} +#endif /* PWRAP_PRELOADER_PORTING */ +#endif /* End of #ifdef PMIC_WRAP_PRELOADER_DRIVER */ + +#ifdef PMIC_WRAP_KERNEL_DRIVER +/*Interrupt handler function*/ +static irqreturn_t mt_pmic_wrap_irq(int irqno, void *dev_id) +{ + unsigned long flags = 0; + + PWRAPFUC(); + PWRAPREG("dump pwrap register\n"); + spin_lock_irqsave(&wrp_lock, flags); + /* *----------------------------------------------------------------------- */ + pwrap_dump_all_register(); + /* raise the priority of WACS2 for AP */ + WRAP_WR32(PMIC_WRAP_HARB_HPRIO, WACS2); + + /* *----------------------------------------------------------------------- */ + /* clear interrupt flag */ + WRAP_WR32(PMIC_WRAP_INT0_CLR, 0xffffffff); + WRAP_WR32(PMIC_WRAP_INT1_CLR, 0xffffffff); + PWRAPREG("INT flag 0x%x\n", WRAP_RD32(PMIC_WRAP_INT0_FLG_RAW)); + PWRAPREG("INT flag 0x%x\n", WRAP_RD32(PMIC_WRAP_INT1_FLG_RAW)); + /* BUG_ON(1); */ + spin_unlock_irqrestore(&wrp_lock, flags); + return IRQ_HANDLED; +} + +static u32 pwrap_read_test(void) +{ + return 0; +} + +static u32 pwrap_write_test(void) +{ + return 0; +} + +static void pwrap_ut(u32 ut_test) +{ + switch (ut_test) { + case 1: + /* pwrap_wacs2_para_test(); */ + pwrap_write_test(); + break; + case 2: + /* pwrap_wacs2_para_test(); */ + pwrap_read_test(); + break; + + default: + PWRAPREG("default test.\n"); + break; + } +} + +/*---------------------------------------------------------------------------*/ +static s32 mt_pwrap_show_hal(char *buf) +{ + PWRAPFUC(); + return snprintf(buf, PAGE_SIZE, "%s\n", "no implement"); +} + +/*---------------------------------------------------------------------------*/ +static s32 mt_pwrap_store_hal(const char *buf, size_t count) +{ + u32 reg_value = 0; + u32 reg_addr = 0; + u32 return_value = 0; + u32 ut_test = 0; + + if (!strncmp(buf, "-h", 2)) { + PWRAPREG + ("PWRAP debug: [-dump_reg][-trace_wacs2][-init][-rdpmic][-wrpmic][-readtest][-writetest]\n"); + PWRAPREG("PWRAP UT: [1][2]\n"); + } + /* ----------pwrap debug---------- */ + else if (!strncmp(buf, "-dump_reg", 9)) { + pwrap_dump_all_register(); + } else if (!strncmp(buf, "-trace_wacs2", 12)) { + /* pwrap_trace_wacs2(); */ + } else if (!strncmp(buf, "-init", 5)) { + return_value = pwrap_init(); + if (return_value == 0) + PWRAPREG("pwrap_init pass,return_value=%d\n", return_value); + else + PWRAPREG("pwrap_init fail,return_value=%d\n", return_value); + } else if (!strncmp(buf, "-rdpmic", 7) && (1 == sscanf(buf + 7, "%x", ®_addr))) { + /* pwrap_read_reg_on_pmic(reg_addr); */ + } else if (!strncmp(buf, "-wrpmic", 7) + && (2 == sscanf(buf + 7, "%x %x", ®_addr, ®_value))) { + /* pwrap_write_reg_on_pmic(reg_addr,reg_value); */ + } else if (!strncmp(buf, "-readtest", 9)) { + pwrap_read_test(); + } else if (!strncmp(buf, "-writetest", 10)) { + pwrap_write_test(); + } + /* ----------pwrap UT---------- */ + else if (!strncmp(buf, "-ut", 3) && (1 == sscanf(buf + 3, "%d", &ut_test))) { + pwrap_ut(ut_test); + } else { + PWRAPREG("wrong parameter\n"); + } + return count; +} +#endif /* End of #ifdef PMIC_WRAP_KERNEL_DRIVER */ +/*---------------------------------------------------------------------------*/ +#else /* Else of #ifdef PMIC_WRAP_NO_PMIC */ +/*-pwrap debug--------------------------------------------------------------------------*/ +static inline void pwrap_dump_ap_register(void) +{ + u32 i = 0; + + PWRAPREG("dump pwrap register, base=0x%p\n", PMIC_WRAP_BASE); + PWRAPREG("address : 3 2 1 0 7 6 5 4 B A 9 8 F E D C\n"); + for (i = 0; i <= PMIC_WRAP_REG_RANGE; i += 4) { + PWRAPREG("offset 0x%.3x:0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", i * 4, + WRAP_RD32(PMIC_WRAP_BASE + (i * 4) + 0), + WRAP_RD32(PMIC_WRAP_BASE + (i * 4) + 0x4), + WRAP_RD32(PMIC_WRAP_BASE + (i * 4) + 0x8), + WRAP_RD32(PMIC_WRAP_BASE + (i * 4) + 0xC)); + } +} + +static inline void pwrap_dump_pmic_register(void) +{ +#if 0 + u32 i = 0; + u32 reg_addr = 0; + u32 reg_value = 0; + + PWRAPREG("dump dewrap register\n"); + for (i = 0; i <= 14; i++) { + reg_addr = (DEW_BASE + i * 4); + reg_value = pwrap_read_nochk(reg_addr, ®_value); + PWRAPREG("0x%x=0x%x\n", reg_addr, reg_value); + } +#endif +} + +void pwrap_dump_all_register(void) +{ + pwrap_dump_ap_register(); + pwrap_dump_pmic_register(); +} + +/****************************************************************************** +pmic wrapper timeout +******************************************************************************/ +#define PWRAP_TIMEOUT +/* use the same API name with kernel driver */ +/* however,the timeout API in preloader/lk use tick instead of ns */ +#ifdef PWRAP_TIMEOUT +static u64 _pwrap_get_current_time(void) +{ +#ifdef PMIC_WRAP_KERNEL_DRIVER + return sched_clock(); /* /TODO: fix me */ +#else + return gpt4_get_current_tick(); +#endif +} + +static bool _pwrap_timeout_ns(u64 start_time_ns, u64 timeout_time_ns) +{ +#ifdef PMIC_WRAP_KERNEL_DRIVER + u64 cur_time = 0; + u64 elapse_time = 0; + + /* get current tick */ + cur_time = _pwrap_get_current_time(); /* ns */ + + /* avoid timer over flow exiting in FPGA env */ + if (cur_time < start_time_ns) { + PWRAPERR("@@@@Timer overflow! start%lld cur timer%lld\n", start_time_ns, cur_time); + start_time_ns = cur_time; + timeout_time_ns = 10000 * 1000; /* 10000us */ + PWRAPERR("@@@@reset timer! start%lld setting%lld\n", start_time_ns, + timeout_time_ns); + } + + elapse_time = cur_time - start_time_ns; + + /* check if timeout */ + if (timeout_time_ns <= elapse_time) { + /* timeout */ + PWRAPERR + ("@@@@Timeout: elapse time%lld, start%lld , current%lld, setting timer%lld\n", + elapse_time, start_time_ns, cur_time, timeout_time_ns); + return true; + } + return false; +#else + return gpt4_timeout_tick(start_time_ns, timeout_time_ns); +#endif +} + +static u64 _pwrap_time2ns(u64 time_us) +{ +#ifdef PMIC_WRAP_KERNEL_DRIVER + return time_us * 1000; +#else + return gpt4_time2tick_us(time_us); +#endif +} + +#else +static u64 _pwrap_get_current_time(void) +{ + return 0; +} + +static BOOL _pwrap_timeout_ns(u64 start_time_ns, u64 elapse_time) +{ + return false; +} + +static u64 _pwrap_time2ns(u64 time_us) +{ + return 0; +} + +#endif /* End of #ifdef PWRAP_TIMEOUT */ + +/* ##################################################################### */ +/* define macro and inline function (for do while loop) */ +/* ##################################################################### */ +typedef u32(*loop_condition_fp) (u32); /* define a function pointer */ + +static inline u32 wait_for_fsm_idle(u32 x) +{ + return GET_WACS0_FSM(x) != WACS_FSM_IDLE; +} + +static inline u32 wait_for_fsm_vldclr(u32 x) +{ + return GET_WACS0_FSM(x) != WACS_FSM_WFVLDCLR; +} + +static inline u32 wait_for_sync(u32 x) +{ + return GET_SYNC_IDLE0(x) != WACS_SYNC_IDLE; +} + +static inline u32 wait_for_idle_and_sync(u32 x) +{ + return (GET_WACS2_FSM(x) != WACS_FSM_IDLE) || (GET_SYNC_IDLE2(x) != WACS_SYNC_IDLE); +} + +static inline u32 wait_for_wrap_idle(u32 x) +{ + return (GET_WRAP_FSM(x) != 0x0) || (GET_WRAP_CH_DLE_RESTCNT(x) != 0x0); +} + +static inline u32 wait_for_wrap_state_idle(u32 x) +{ + return GET_WRAP_AG_DLE_RESTCNT(x) != 0; +} + +static inline u32 wait_for_man_idle_and_noreq(u32 x) +{ + return (GET_MAN_REQ(x) != MAN_FSM_NO_REQ) || (GET_MAN_FSM(x) != MAN_FSM_IDLE); +} + +static inline u32 wait_for_man_vldclr(u32 x) +{ + return GET_MAN_FSM(x) != MAN_FSM_WFVLDCLR; +} + +static inline u32 wait_for_cipher_ready(u32 x) +{ + return x != 3; +} + +static inline u32 wait_for_stdupd_idle(u32 x) +{ + return GET_STAUPD_FSM(x) != 0x0; +} + +#ifdef PMIC_WRAP_KERNEL_DRIVER +static inline u32 wait_for_state_ready_init(loop_condition_fp fp, u32 timeout_us, + void *wacs_register, u32 *read_reg) +#else +static inline u32 wait_for_state_ready_init(loop_condition_fp fp, u32 timeout_us, u32 wacs_register, + u32 *read_reg) +#endif +{ + u64 start_time_ns = 0, timeout_ns = 0; + u32 reg_rdata = 0x0; + + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(timeout_us); + do { + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) { + PWRAPLOG("wait_for_state_ready_init timeout when waiting for idle\n"); + return E_PWR_WAIT_IDLE_TIMEOUT; + } + reg_rdata = WRAP_RD32(wacs_register); + } while (fp(reg_rdata)); /* IDLE State */ + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +#ifdef PMIC_WRAP_KERNEL_DRIVER +static inline u32 wait_for_state_idle_init(loop_condition_fp fp, u32 timeout_us, + void *wacs_register, void *wacs_vldclr_register, + u32 *read_reg) +#else +static inline u32 wait_for_state_idle_init(loop_condition_fp fp, u32 timeout_us, u32 wacs_register, + u32 wacs_vldclr_register, u32 *read_reg) +#endif +{ + u64 start_time_ns = 0, timeout_ns = 0; + u32 reg_rdata; + + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(timeout_us); + do { + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) { + PWRAPLOG("wait_for_state_idle_init timeout when waiting for idle\n"); + pwrap_dump_ap_register(); + /* pwrap_trace_wacs2(); */ + /* BUG_ON(1); */ + return E_PWR_WAIT_IDLE_TIMEOUT; + } + reg_rdata = WRAP_RD32(wacs_register); + /* if last read command timeout,clear vldclr bit */ + /* read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;write:FSM_REQ-->idle */ + switch (GET_WACS0_FSM(reg_rdata)) { + case WACS_FSM_WFVLDCLR: + WRAP_WR32(wacs_vldclr_register, 1); + PWRAPLOG("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n"); + break; + case WACS_FSM_WFDLE: + PWRAPLOG("WACS_FSM = WACS_FSM_WFDLE\n"); + break; + case WACS_FSM_REQ: + PWRAPLOG("WACS_FSM = WACS_FSM_REQ\n"); + break; + default: + break; + } + } while (fp(reg_rdata)); /* IDLE State */ + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +#ifdef PMIC_WRAP_KERNEL_DRIVER +static inline u32 wait_for_state_idle(loop_condition_fp fp, u32 timeout_us, void *wacs_register, + void *wacs_vldclr_register, u32 *read_reg) +#else +static inline u32 wait_for_state_idle(loop_condition_fp fp, u32 timeout_us, u32 wacs_register, + u32 wacs_vldclr_register, u32 *read_reg) +#endif +{ + u64 start_time_ns = 0, timeout_ns = 0; + u64 loop_counter = 0; + u32 reg_rdata; + + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(timeout_us); + do { + loop_counter++; + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) { + PWRAPLOG + ("wait_for_state_idle timeout when waiting for idle, loop_counter = %lld\n", + loop_counter); + pwrap_dump_ap_register(); + /* pwrap_trace_wacs2(); */ + /* BUG_ON(1); */ + return E_PWR_WAIT_IDLE_TIMEOUT; + } + reg_rdata = WRAP_RD32(wacs_register); + if (GET_INIT_DONE0(reg_rdata) != WACS_INIT_DONE) { + PWRAPLOG("initialization isn't finished\n"); + return E_PWR_NOT_INIT_DONE; + } + /* if last read command timeout,clear vldclr bit */ + /* read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;write:FSM_REQ-->idle */ + switch (GET_WACS0_FSM(reg_rdata)) { + case WACS_FSM_WFVLDCLR: + WRAP_WR32(wacs_vldclr_register, 1); + PWRAPLOG("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n"); + break; + case WACS_FSM_WFDLE: + PWRAPLOG("WACS_FSM = WACS_FSM_WFDLE\n"); + break; + case WACS_FSM_REQ: + PWRAPLOG("WACS_FSM = WACS_FSM_REQ\n"); + break; + default: + break; + } + } while (fp(reg_rdata)); /* IDLE State */ + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +#ifdef PMIC_WRAP_KERNEL_DRIVER +static inline u32 wait_for_state_ready(loop_condition_fp fp, u32 timeout_us, void *wacs_register, + u32 *read_reg) +#else +static inline u32 wait_for_state_ready(loop_condition_fp fp, u32 timeout_us, u32 wacs_register, + u32 *read_reg) +#endif +{ + u64 start_time_ns = 0, timeout_ns = 0; + u64 loop_count = 0; + u32 reg_rdata; + + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(timeout_us); + do { + loop_count++; + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) { + PWRAPLOG("timeout when waiting for idle, loop_count = %lld\n", loop_count); + pwrap_dump_ap_register(); + return E_PWR_WAIT_IDLE_TIMEOUT; + } + reg_rdata = WRAP_RD32(wacs_register); + + if (GET_INIT_DONE0(reg_rdata) != WACS_INIT_DONE) { + PWRAPLOG("initialization isn't finished\n"); + return E_PWR_NOT_INIT_DONE; + } + } while (fp(reg_rdata)); /* IDLE State */ + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +#ifndef PMIC_WRAP_KERNEL_DRIVER +/* ****************************************************************************** */ +/* --external API for pmic_wrap user------------------------------------------------- */ +/* ****************************************************************************** */ +s32 pwrap_read(u32 adr, u32 *rdata) +{ + return pwrap_wacs2(0, adr, 0, rdata); +} + +s32 pwrap_write(u32 adr, u32 wdata) +{ + return pwrap_wacs2(1, adr, wdata, 0); +} +#endif + +#ifdef PMIC_WRAP_KERNEL_DRIVER +/********************************************************************************************/ +/* extern API for PMIC driver, INT related control, this INT is for PMIC chip to AP */ +/********************************************************************************************/ +u32 mt_pmic_wrap_eint_status(void) +{ + return WRAP_RD32(PMIC_WRAP_EINT_STA); +} + +void mt_pmic_wrap_eint_clr(int offset) +{ + if ((offset < 0) || (offset > 3)) + PWRAPERR("clear EINT flag error, only 0-3 bit\n"); + else + WRAP_WR32(PMIC_WRAP_EINT_CLR, (1 << offset)); + + PWRAPREG("clear EINT flag mt_pmic_wrap_eint_status=0x%x\n", WRAP_RD32(PMIC_WRAP_EINT_STA)); +} +#endif +/* -------------------------------------------------------- */ +/* Function : pwrap_wacs2() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +#ifdef PMIC_WRAP_KERNEL_DRIVER +static s32 pwrap_wacs2_hal(u32 write, u32 adr, u32 wdata, u32 *rdata) +#else +s32 pwrap_wacs2(u32 write, u32 adr, u32 wdata, u32 *rdata) +#endif +{ + /* u64 wrap_access_time=0x0; */ + u32 reg_rdata = 0; + u32 wacs_write = 0; + u32 wacs_adr = 0; + u32 wacs_cmd = 0; + u32 return_value = 0; +#ifdef PMIC_WRAP_KERNEL_DRIVER + unsigned long flags = 0; +#endif + + /* Check argument validation */ + if ((write & ~(0x1)) != 0) + return E_PWR_INVALID_RW; + if ((adr & ~(0xffff)) != 0) + return E_PWR_INVALID_ADDR; + if ((wdata & ~(0xffff)) != 0) + return E_PWR_INVALID_WDAT; + +#ifdef PMIC_WRAP_KERNEL_DRIVER + spin_lock_irqsave(&wrp_lock, flags); +#endif + + /* Check IDLE & INIT_DONE in advance */ + return_value = + wait_for_state_idle(wait_for_fsm_idle, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, + PMIC_WRAP_WACS2_VLDCLR, 0); + if (return_value != 0) { + PWRAPLOG("wait_for_fsm_idle fail,return_value=%d\n", return_value); + goto FAIL; + } + wacs_write = write << 31; + wacs_adr = (adr >> 1) << 16; + wacs_cmd = wacs_write | wacs_adr | wdata; + + WRAP_WR32(PMIC_WRAP_WACS2_CMD, wacs_cmd); + if (write == 0) { + if (NULL == rdata) { + PWRAPLOG("rdata is a NULL pointer\n"); + return_value = E_PWR_INVALID_ARG; + WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1); + goto FAIL; + } + return_value = + wait_for_state_ready(wait_for_fsm_vldclr, TIMEOUT_READ, PMIC_WRAP_WACS2_RDATA, + ®_rdata); + if (return_value != 0) { + PWRAPLOG("wait_for_fsm_vldclr fail,return_value=%d\n", return_value); + return_value += 1; /* E_PWR_NOT_INIT_DONE_READ or E_PWR_WAIT_IDLE_TIMEOUT_READ */ + goto FAIL; + } + + *rdata = GET_WACS0_RDATA(reg_rdata); + WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1); + } + +FAIL: +#ifdef PMIC_WRAP_KERNEL_DRIVER + spin_unlock_irqrestore(&wrp_lock, flags); +#endif + if (return_value != 0) { + PWRAPLOG("pwrap_wacs2 fail,return_value=%d\n", return_value); + PWRAPLOG("timeout:BUG_ON here\n"); + } + + return return_value; +} + +/* ****************************************************************************** */ +/* --internal API for pwrap_init------------------------------------------------- */ +/* ****************************************************************************** */ + +/* -------------------------------------------------------- */ +/* Function : _pwrap_wacs2_nochk() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +s32 pwrap_read_nochk(u32 adr, u32 *rdata) +{ + return _pwrap_wacs2_nochk(0, adr, 0, rdata); +} + +s32 pwrap_write_nochk(u32 adr, u32 wdata) +{ + return _pwrap_wacs2_nochk(1, adr, wdata, 0); +} + +static s32 _pwrap_wacs2_nochk(u32 write, u32 adr, u32 wdata, u32 *rdata) +{ + u32 reg_rdata = 0x0; + u32 wacs_write = 0x0; + u32 wacs_adr = 0x0; + u32 wacs_cmd = 0x0; + u32 return_value = 0x0; + /* PWRAPFUC(); */ + /* Check argument validation */ + if ((write & ~(0x1)) != 0) + return E_PWR_INVALID_RW; + if ((adr & ~(0xffff)) != 0) + return E_PWR_INVALID_ADDR; + if ((wdata & ~(0xffff)) != 0) + return E_PWR_INVALID_WDAT; + + /* Check IDLE */ + return_value = + wait_for_state_ready_init(wait_for_fsm_idle, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, + 0); + if (return_value != 0) { + PWRAPLOG("_pwrap_wacs2_nochk write command fail,return_value=%x\n", return_value); + return return_value; + } + + wacs_write = write << 31; + wacs_adr = (adr >> 1) << 16; + wacs_cmd = wacs_write | wacs_adr | wdata; + WRAP_WR32(PMIC_WRAP_WACS2_CMD, wacs_cmd); + + if (write == 0) { + if (NULL == rdata) { + PWRAPLOG("rdata is a NULL pointer\n"); + WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1); + return E_PWR_INVALID_ARG; + } + /* wait for read data ready */ + return_value = + wait_for_state_ready_init(wait_for_fsm_vldclr, TIMEOUT_READ, + PMIC_WRAP_WACS2_RDATA, ®_rdata); + if (return_value != 0) { + PWRAPLOG("wait_for_fsm_vldclr fail, return_value=%d\n", return_value); + return_value += 1; /* E_PWR_NOT_INIT_DONE_READ or E_PWR_WAIT_IDLE_TIMEOUT_READ */ + return return_value; + } + *rdata = GET_WACS0_RDATA(reg_rdata); + WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1); + } + return 0; +} + +/* -------------------------------------------------------- */ +/* Function : _pwrap_init_dio() */ +/* Description :call it in pwrap_init,mustn't check init done */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_init_dio(u32 dio_en) +{ + u32 arb_en_backup = 0x0; + u32 rdata = 0x0; + u32 return_value = 0; + + /* PWRAPFUC(); */ + arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN); + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2); /* only WACS2 */ + +#ifdef SLV_6351 + pwrap_write_nochk(MT6351_DEW_DIO_EN, dio_en); +#endif + + /* Check IDLE & INIT_DONE in advance */ + return_value = + wait_for_state_ready_init(wait_for_idle_and_sync, TIMEOUT_WAIT_IDLE, + PMIC_WRAP_WACS2_RDATA, 0); + if (return_value != 0) { + PWRAPLOG("_pwrap_init_dio fail,return_value=%x\n", return_value); + return return_value; + } + /* Enable AP DIO mode */ + WRAP_WR32(PMIC_WRAP_DIO_EN, dio_en); + /* Read Test */ +#ifdef SLV_6351 + pwrap_read_nochk(MT6351_DEW_READ_TEST, &rdata); + if (rdata != MT6351_DEFAULT_VALUE_READ_TEST) { + PWRAPLOG("[Dio_mode][Read Test] fail,dio_en = %x, READ_TEST rdata=%x, exp=0x5aa5\n", + dio_en, rdata); + return E_PWR_READ_TEST_FAIL; + } +#endif + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, arb_en_backup); + return 0; +} + +/* -------------------------------------------------------- */ +/* Function : _pwrap_init_cipher() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_init_cipher(void) +{ + u32 arb_en_backup = 0; + u32 rdata = 0; + u32 return_value = 0; + u32 start_time_ns = 0, timeout_ns = 0; + /* PWRAPFUC(); */ + arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN); + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2); /* only WACS0 */ + + WRAP_WR32(PMIC_WRAP_CIPHER_SWRST, 1); + WRAP_WR32(PMIC_WRAP_CIPHER_SWRST, 0); + WRAP_WR32(PMIC_WRAP_CIPHER_KEY_SEL, 1); + WRAP_WR32(PMIC_WRAP_CIPHER_IV_SEL, 2); + WRAP_WR32(PMIC_WRAP_CIPHER_EN, 1); + + /* Config CIPHER @ PMIC */ +#ifdef SLV_6351 + pwrap_write_nochk(MT6351_DEW_CIPHER_SWRST, 0x1); + pwrap_write_nochk(MT6351_DEW_CIPHER_SWRST, 0x0); + pwrap_write_nochk(MT6351_DEW_CIPHER_KEY_SEL, 0x1); + pwrap_write_nochk(MT6351_DEW_CIPHER_IV_SEL, 0x2); + pwrap_write_nochk(MT6351_DEW_CIPHER_EN, 0x1); +#endif + + /* wait for cipher data ready@AP */ +#ifndef CONFIG_MTK_FPGA + return_value = + wait_for_state_ready_init(wait_for_cipher_ready, TIMEOUT_WAIT_IDLE, + PMIC_WRAP_CIPHER_RDY, 0); +#else + return_value = + wait_for_state_ready_init(wait_for_cipher_ready, 0xFFFFFFFF, PMIC_WRAP_CIPHER_RDY, 0); +#endif + if (return_value != 0) { + PWRAPLOG("wait for cipher data ready@AP fail,return_value=%x\n", return_value); + return return_value; + } + /* wait for cipher data ready@PMIC */ +#ifdef SLV_6351 + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(0xFFFFFF); + do { + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) + PWRAPLOG("wait for cipher data ready@PMIC\n"); + + pwrap_read_nochk(MT6351_DEW_CIPHER_RDY, &rdata); + } while (rdata != 0x1); /* cipher_ready */ + + pwrap_write_nochk(MT6351_DEW_CIPHER_MODE, 0x1); +#endif + /* wait for cipher mode idle */ + return_value = + wait_for_state_ready_init(wait_for_idle_and_sync, TIMEOUT_WAIT_IDLE, + PMIC_WRAP_WACS2_RDATA, 0); + if (return_value != 0) { + PWRAPLOG("wait for cipher mode idle fail,return_value=%x\n", return_value); + return return_value; + } + WRAP_WR32(PMIC_WRAP_CIPHER_MODE, 1); + + /* Read Test */ +#ifdef SLV_6351 + pwrap_read_nochk(MT6351_DEW_READ_TEST, &rdata); + if (rdata != MT6351_DEFAULT_VALUE_READ_TEST) { + PWRAPLOG("_pwrap_init_cipher,read test error,error code=%x, rdata=%x\n", 1, rdata); + return E_PWR_READ_TEST_FAIL; + } +#endif + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, arb_en_backup); + return 0; +} + +/* -------------------------------------------------------- */ +/* Function : _pwrap_init_sistrobe() */ +/* Description : Initialize SI_CK_CON and SIDLY */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_init_sistrobe(void) +{ + u32 arb_en_backup = 0; + u32 rdata = 0; + s32 ind = 0; + u32 result_faulty = 0; + u64 result = 0, tmp1 = 0, tmp2 = 0; + s32 leading_one = 0; + s32 tailing_one = 0; +#ifdef ULPOSC + u64 inds = 0, indf = 0; +#endif + arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN); + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2); /* only WACS2 */ + +#ifdef ULPOSC + /* --------------------------------------------------------------------- */ + /* Scan all possible input strobe by READ_TEST */ + /* --------------------------------------------------------------------- */ + result = 0; + result_faulty = 0; + inds = 0; + indf = 0; + for (ind = 0; ind < 44; ind++) { /* 44 sampling clock edge */ + WRAP_WR32(PMIC_WRAP_SI_CK_CON, (ind >> 2) & 0xf); + WRAP_WR32(PMIC_WRAP_SIDLY, 0x3 - (ind & 0x3)); +#ifdef SLV_6351 + _pwrap_wacs2_nochk(0, MT6351_DEW_READ_TEST, 0, &rdata); + if (rdata == MT6351_DEFAULT_VALUE_READ_TEST) { + PWRAPERR + ("_pwrap_init_sistrobe [Read Test of MT6351] pass,index=%d rdata=%x\n", + ind, rdata); + result |= (0x1 << ind); + } else { + PWRAPERR + ("_pwrap_init_sistrobe [Read Test of MT6351] tuning,index=%d rdata=%x\n", + ind, rdata); + } +#endif + } + + /* --------------------------------------------------------------------- */ + /* Locate the leading one and trailing one */ + /* --------------------------------------------------------------------- */ +#if 0 + for (ind = 43; ind >= 0; ind--) { + /* if( result & (0x1 << ind) ) break; */ + if (ind > 20) { + indf = (0x1 << 20); + /* indf = (indf << ((ind - 20)%32)); */ + } else { + indf = (0x1 << (ind % 32)); + } + inds = result & indf; + if (inds) + break; + } + leading_one = ind; + + for (ind = 0; ind < 44; ind++) { + /* if( result & (0x1 << ind) ) break; */ + if (ind > 20) { + indf = (0x1 << 20); + /* indf = (indf << ((ind - 20)%32)); */ + } else { + indf = (0x1 << (ind % 32)); + } + inds = result & indf; + if (inds) + break; + } + tailing_one = ind; +#else + for (ind = 43; ind >= 0; ind--) { + if (result & (0x1 << ind)) + break; + } + leading_one = ind; + + for (ind = 0; ind < 44; ind++) { + if (result & (0x1 << ind)) + break; + } + tailing_one = ind; +#endif + + /* --------------------------------------------------------------------- */ + /* Check the continuity of pass range */ + /* --------------------------------------------------------------------- */ + tmp1 = (0x1 << (leading_one + 1)) - 1; + tmp2 = (0x1 << tailing_one) - 1; + if ((tmp1 - tmp2) != result) { + /*TERR = "[DrvPWRAP_InitSiStrobe] Fail, tmp1:%d, tmp2:%d", tmp1, tmp2 */ + PWRAPERR + ("_pwrap_init_sistrobe Fail, result = %llx, leading_one:%d, tailing_one:%d\n", + result, leading_one, tailing_one); + result_faulty = 0x1; + } + /* --------------------------------------------------------------------- */ + /* Config SICK and SIDLY to the middle point of pass range */ + /* --------------------------------------------------------------------- */ + ind = (leading_one + tailing_one) / 2; + WRAP_WR32(PMIC_WRAP_SI_CK_CON, (ind >> 2) & 0xf); + WRAP_WR32(PMIC_WRAP_SIDLY, 0x3 - (ind & 0x3)); + +#else /* Else of #ifdef ULPOSC */ + + /* --------------------------------------------------------------------- */ + /* Scan all possible input strobe by READ_TEST */ + /* --------------------------------------------------------------------- */ + for (ind = 0; ind < 24; ind++) { /* 24 sampling clock edge */ + WRAP_WR32(PMIC_WRAP_SI_CK_CON, (ind >> 2) & 0x7); + WRAP_WR32(PMIC_WRAP_SIDLY, 0x3 - (ind & 0x3)); +#ifdef SLV_6351 + _pwrap_wacs2_nochk(0, MT6351_DEW_READ_TEST, 0, &rdata); + if (rdata == MT6351_DEFAULT_VALUE_READ_TEST) { + PWRAPERR + ("_pwrap_init_sistrobe [Read Test of MT6351] pass,index=%d rdata=%x\n", + ind, rdata); + result |= (0x1 << ind); + } else { + PWRAPERR + ("_pwrap_init_sistrobe [Read Test of MT6351] tuning,index=%d rdata=%x\n", + ind, rdata); + } +#endif + } + + /* --------------------------------------------------------------------- */ + /* Locate the leading one and trailing one of PMIC 1/2 */ + /* --------------------------------------------------------------------- */ + for (ind = 23; ind >= 0; ind--) { + if (result & (0x1 << ind)) + break; + + } + leading_one = ind; + + for (ind = 0; ind < 24; ind++) { + if (result & (0x1 << ind)) + break; + } + tailing_one = ind; + + /* --------------------------------------------------------------------- */ + /* Check the continuity of pass range */ + /* --------------------------------------------------------------------- */ + tmp1 = (0x1 << (leading_one + 1)) - 1; + tmp2 = (0x1 << tailing_one) - 1; + if ((tmp1 - tmp2) != result) { + /*TERR = "[PWRAP] Check Continuity Fail at PMIC %d, result = %x, leading_one:%d, tailing_one:%d" + , i+1, result[i], leading_one[i], tailing_one[i] */ + PWRAPERR + ("_pwrap_init_sistrobe Fail, result = %llx, leading_one:%d, tailing_one:%d\n", + result, leading_one, tailing_one); + result_faulty = 0x1; + } + /* --------------------------------------------------------------------- */ + /* Config SICK and SIDLY to the middle point of pass range */ + /* --------------------------------------------------------------------- */ + if (result_faulty == 0) { + ind = (leading_one + tailing_one) / 2; + WRAP_WR32(PMIC_WRAP_SI_CK_CON, (ind >> 2) & 0x7); + WRAP_WR32(PMIC_WRAP_SIDLY, 0x3 - (ind & 0x3)); + /* --------------------------------------------------------------------- */ + /* Restore */ + /* --------------------------------------------------------------------- */ + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, arb_en_backup); + return 0; + } else { + PWRAPERR("_pwrap_init_sistrobe Fail,result_faulty=%x\n", result_faulty); + return result_faulty; + } +#endif /* End of #ifdef ULPOSC */ + +} + +/* -------------------------------------------------------- */ +/* Function : _pwrap_reset_spislv() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_reset_spislv(void) +{ + u32 ret = 0; + u32 return_value = 0; + /* PWRAPFUC(); */ + /* This driver does not using _pwrap_switch_mux */ + /* because the remaining requests are expected to fail anyway */ + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, DISABLE_ALL); + WRAP_WR32(PMIC_WRAP_WRAP_EN, DISABLE); + WRAP_WR32(PMIC_WRAP_MUX_SEL, MANUAL_MODE); + WRAP_WR32(PMIC_WRAP_MAN_EN, ENABLE); + WRAP_WR32(PMIC_WRAP_DIO_EN, DISABLE); + + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_CSL << 8)); /* 0x2100 */ + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); /* 0x2800//to reset counter */ + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_CSH << 8)); /* 0x2000 */ + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); + + return_value = + wait_for_state_ready_init(wait_for_sync, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, 0); + if (return_value != 0) { + PWRAPLOG("_pwrap_reset_spislv fail,return_value=%x\n", return_value); + ret = E_PWR_TIMEOUT; + goto timeout; + } + + WRAP_WR32(PMIC_WRAP_MAN_EN, DISABLE); + WRAP_WR32(PMIC_WRAP_MUX_SEL, WRAPPER_MODE); + +timeout: + WRAP_WR32(PMIC_WRAP_MAN_EN, DISABLE); + WRAP_WR32(PMIC_WRAP_MUX_SEL, WRAPPER_MODE); + return ret; +} + +#if 0 +static void __pwrap_soft_reset(void) +{ + PWRAPLOG("start reset wrapper\n"); + PWRAP_SOFT_RESET; + PWRAPLOG("the reset register =%x\n", WRAP_RD32(INFRA_GLOBALCON_RST0)); + PWRAPLOG("PMIC_WRAP_STAUPD_GRPEN =0x%x,it should be equal to 0xc\n", + WRAP_RD32(PMIC_WRAP_STAUPD_GRPEN)); + /* clear reset bit */ + PWRAP_CLEAR_SOFT_RESET_BIT; +} +#endif + +static s32 _pwrap_init_reg_clock(u32 regck_sel) +{ + PWRAPFUC(); + +#ifdef SLV_6351 + pwrap_write_nochk(MT6351_DEW_RDDMY_NO, 0x8); + WRAP_WR32(PMIC_WRAP_RDDMY, 0x08); +#endif + + /* Config SPI Waveform according to reg clk */ + if (regck_sel == 1) { /* 18MHz in 6328, 26Mhz in BBCHip */ + WRAP_WR32(PMIC_WRAP_CSHEXT_READ, 0x0); + /* Wait data written into register => + 4T_PMIC: consists of CSHEXT_WRITE_START+EXT_CK+CSHEXT_WRITE_END+CSLEXT_START */ + WRAP_WR32(PMIC_WRAP_CSHEXT_WRITE, 0x33); + WRAP_WR32(PMIC_WRAP_CSLEXT_START, 0x0); + WRAP_WR32(PMIC_WRAP_CSLEXT_END, 0x0); /* for PMIC site synchronizer use */ + } else { /* Safe mode */ + WRAP_WR32(PMIC_WRAP_CSHEXT_WRITE, 0xff); + WRAP_WR32(PMIC_WRAP_CSHEXT_READ, 0xff); + WRAP_WR32(PMIC_WRAP_CSLEXT_START, 0xf); + WRAP_WR32(PMIC_WRAP_CSLEXT_END, 0xf); + } + + return 0; +} + +/* + * pmic_wrap init,init wrap interface + */ +s32 pwrap_init(void) +{ + s32 sub_return = 0; + s32 sub_return1 = 0; + /* s32 ret=0; */ + u32 rdata = 0x0; + /* u32 timeout=0; */ + + PWRAPFUC(); +#ifdef PMIC_WRAP_KERNEL_DRIVER +#ifdef CONFIG_OF + sub_return = pwrap_of_iomap(); + if (sub_return) + return sub_return; +#endif +#endif + +#ifndef CONFIG_MTK_FPGA + + /* ############################### */ + /* toggle PMIC_WRAP and pwrap_spictl reset */ + /* ############################### */ + WRAP_WR32(INFRA_GLOBALCON_RST2_SET, 0x1); /* Write 1 set */ + WRAP_WR32(INFRA_GLOBALCON_RST2_CLR, 0x1); /* Write 1 clr */ + + /* ############################### */ + /* Switch GPIO to PWRAP mode => modes of PMIC_WRAP's IOs are PMIC_WRAP in default setting */ + /* ############################### */ + /* SET_GPIO_MODE (40, 1); // MI */ + /* SET_GPIO_MODE (41, 1); // MO */ + /* SET_GPIO_MODE (38, 1); // CK */ + /* SET_GPIO_MODE (39, 1); // CS */ + + /* ############################### */ + /* Set SPI_CK_freq 52MHz or 26MHz */ + /* ############################### */ +#ifdef ULPOSC + WRAP_WR32(ULPOSC_CON, 0x0001); /* Enable ulposc */ + udelay(1); + WRAP_WR32(ULPOSC_CON, 0x0003); /* Reset ulposc */ + udelay(30); + WRAP_WR32(ULPOSC_CON, 0x0001); /* Release reset ulposc */ + udelay(130); + WRAP_WR32(ULPOSC_CON, 0x0005); + WRAP_WR32(CLK_CFG_5_SET, 0x0002); /* 52MHz [1:0] */ + udelay(20); + /* WRAP_WR32(GPIO_DUMMY, 0x80000000); remove by ECO */ + WRAP_WR32(PMICW_CLOCK_CTRL, 0x0000); /* pmicw_sw_en */ + WRAP_WR32(CLK_CFG_UPDATE, 0x00080000); /* Clock configure update */ + WRAP_WR32(MODULE_SW_CG_0_SET, 0x0000000F); /* sys_ck cg enable */ + WRAP_WR32(MODULE_SW_CG_0_CLR, 0x0000000F); /* sys_ck cg disable */ +#else + WRAP_WR32(CLK_CFG_5_CLR, 0x0001); /* 26MHz [1:0] */ + WRAP_WR32(MODULE_SW_CG_0_SET, 0x0000000F); /* sys_ck cg enable */ + WRAP_WR32(MODULE_SW_CG_0_CLR, 0x0000000F); /* sys_ck cg disable */ +#endif +#endif /* End of #ifndef CONFIG_MTK_FPGA */ + + /* ############################### */ + /* Enable DCM */ + /* ############################### */ + WRAP_WR32(PMIC_WRAP_DCM_EN, 3); /* enable CRC DCM and PWRAP DCM */ + WRAP_WR32(PMIC_WRAP_DCM_DBC_PRD, DISABLE); /* No debounce */ + + /* ############################### */ + /* Reset all SPISLV */ + /* ############################### */ + sub_return = _pwrap_reset_spislv(); + if (sub_return != 0) { + PWRAPLOG("error,_pwrap_reset_spislv fail,sub_return=%x\n", sub_return); + return E_PWR_INIT_RESET_SPI; + } + /* ############################### */ + /* Enable WACS2 */ + /* ############################### */ + WRAP_WR32(PMIC_WRAP_WRAP_EN, ENABLE); /* enable wrap */ + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2); /* Only WACS2 */ + WRAP_WR32(PMIC_WRAP_WACS2_EN, ENABLE); + + /* ############################### */ + /* Input data calibration flow */ + /* ############################### */ + sub_return = _pwrap_init_sistrobe(); + if (sub_return != 0) { + PWRAPLOG("error,DrvPWRAP_InitSiStrobe fail,sub_return=%x\n", sub_return); + return E_PWR_INIT_SIDLY; + } + /* ############################### */ + /* SPI Waveform Configuration */ + /* ############################### */ + /* 0:safe mode, 1:18MHz */ + sub_return = _pwrap_init_reg_clock(1); + if (sub_return != 0) { + PWRAPLOG("error,_pwrap_init_reg_clock fail,sub_return=%x\n", sub_return); + return E_PWR_INIT_REG_CLOCK; + } + /* ############################### */ + /* Enable DIO mode */ + /* ############################### */ + sub_return = _pwrap_init_dio(1); + if (sub_return != 0) { + PWRAPLOG("_pwrap_init_dio test error,error code=%x, sub_return=%x\n", 0x11, + sub_return); + return E_PWR_INIT_DIO; + } + /* ############################### */ + /* Enable Encryption */ + /* ############################### */ + sub_return = _pwrap_init_cipher(); + if (sub_return != 0) { + PWRAPLOG("Enable Encryption fail, return=%x\n", sub_return); + return E_PWR_INIT_CIPHER; + } + /* ############################### */ + /* Write test using WACS2 */ + /* ############################### */ +#ifdef SLV_6351 + sub_return = pwrap_write_nochk(MT6351_DEW_WRITE_TEST, MT6351_WRITE_TEST_VALUE); + sub_return1 = pwrap_read_nochk(MT6351_DEW_WRITE_TEST, &rdata); + if (rdata != MT6351_WRITE_TEST_VALUE) { + PWRAPLOG + ("write test error,rdata=0x%x,exp=0xa55a,sub_return=0x%x,sub_return1=0x%x\n", + rdata, sub_return, sub_return1); + return E_PWR_INIT_WRITE_TEST; + } +#endif + + /* ############################### */ + /* Status update function initialization */ + /* 1. Signature Checking using CRC (CRC 0 only) */ + /* 2. EINT update */ + /* 3. Read back Auxadc thermal data for GPD */ + /* 4. Read back Auxadc thermal data for LTE */ + /* ############################### */ +#if 0 + sub_return = pwrap_write_nochk(MT6351_DEW_CRC_EN, ENABLE); + if (sub_return != 0) { + PWRAPLOG("Enable CRC fail, return=%x\n", sub_return); + return E_PWR_INIT_ENABLE_CRC; + } + WRAP_WR32(PMIC_WRAP_WACS2_EN, MT6351_DEW_CRC_VAL); +#endif + WRAP_WR32(PMIC_WRAP_STAUPD_GRPEN, 0x75); +#if 0 + WRAP_WR32(PMIC_WRAP_CRC_EN, ENABLE); +#endif + WRAP_WR32(PMIC_WRAP_EINT_STA0_ADR, MT6351_INT_STA); + + WRAP_WR32(PMIC_WRAP_ADC_CMD_ADDR, MT6351_AUXADC_RQST1_SET); + WRAP_WR32(PMIC_WRAP_PWRAP_ADC_CMD, 0x0100); + WRAP_WR32(PMIC_WRAP_ADC_RDATA_ADDR, MT6351_AUXADC_ADC16); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR_LATEST, MT6351_AUXADC_ADC32); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR_WP, MT6351_AUXADC_MDBG_1); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR0, MT6351_AUXADC_BUF0); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR1, MT6351_AUXADC_BUF1); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR2, MT6351_AUXADC_BUF2); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR3, MT6351_AUXADC_BUF3); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR4, MT6351_AUXADC_BUF4); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR5, MT6351_AUXADC_BUF5); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR6, MT6351_AUXADC_BUF6); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR7, MT6351_AUXADC_BUF7); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR8, MT6351_AUXADC_BUF8); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR9, MT6351_AUXADC_BUF9); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR10, MT6351_AUXADC_BUF10); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR11, MT6351_AUXADC_BUF11); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR12, MT6351_AUXADC_BUF12); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR13, MT6351_AUXADC_BUF13); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR14, MT6351_AUXADC_BUF14); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR15, MT6351_AUXADC_BUF15); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR16, MT6351_AUXADC_BUF16); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR17, MT6351_AUXADC_BUF17); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR18, MT6351_AUXADC_BUF18); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR19, MT6351_AUXADC_BUF19); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR20, MT6351_AUXADC_BUF20); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR21, MT6351_AUXADC_BUF21); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR22, MT6351_AUXADC_BUF22); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR23, MT6351_AUXADC_BUF23); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR24, MT6351_AUXADC_BUF24); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR25, MT6351_AUXADC_BUF25); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR26, MT6351_AUXADC_BUF26); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR27, MT6351_AUXADC_BUF27); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR28, MT6351_AUXADC_BUF28); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR29, MT6351_AUXADC_BUF29); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR30, MT6351_AUXADC_BUF30); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR31, MT6351_AUXADC_BUF31); + + /* ############################### */ + /* PMIC_WRAP starvation setting */ + /* ############################### */ + /* latency is smaller than 10us, pop up to group"1" first */ + WRAP_WR32(PMIC_WRAP_HARB_HPRIO, 0x0007); /* [0]:MD_HW [1]:C2K_HW [2]:MD_DVFS _HW */ + /* starvation enable */ + /* [0]=MD_HW, latency= 2.6us, target= (2.6/1.2)-1=1 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_0, 0x0401); /* [10]: enable starvation, [9:0]: target setting */ + /* [1]=C2K_HW, latency= 2.6us, target= (2.6/1.2)-1=1 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_1, 0x0401); /* [10]: enable starvation, [9:0]: target setting */ + /* [2]=MD_DVFS_HW,latency= 5.2us, target= (5.2/1.2)-1=3 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_2, 0x0403); /* [10]: enable starvation, [9:0]: target setting */ + /* [3]=WACS0(MD_SW0), latency=40us, target= (40/1.2)-1=32 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_3, 0x0420); /* [10]: enable starvation, [9:0]: target setting */ + /* [4]=SPM_HW, latency=40us, target= (40/1.2)-1=32 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_4, 0x0420); /* [10]: enable starvation, [9:0]: target setting */ + /* [5]=WACS3(C2K_SW), latency=40us, target= (40/1.2)-1=32 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_5, 0x0420); /* [10]: enable starvation, [9:0]: target setting */ + /* [6]=DCXO_CONNINF, latency=50us, target= (50/1.2)-1=40 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_6, 0x0428); /* [10]: enable starvation, [9:0]: target setting */ + /* [7]=DCXO_NFCINF, latency=50us, target= (50/1.2)-1=40 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_7, 0x0428); /* [10]: enable starvation, [9:0]: target setting */ + /* [8]=MD_ADCINF, latency=29us, target= (29/1.2)-1= 23 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_8, 0x0417); /* [10]: enable starvation, [9:0]: target setting */ + /* [9]=STAUPD, latency=428us, target= (428/1.2)-1=355 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_9, 0x0563); /* [10]: enable starvation, [9:0]: target setting */ + /* [10]=GPS_HW, latency=150us, target= (150/1.2)-1=124 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_10, 0x047C); /* [10]: enable starvation, [9:0]: target setting */ + /* [11]=WACS2(AP_SW), latency=1000us, target= (1000/1.2)-1=832 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_11, 0x0740); /* [10]: enable starvation, [9:0]: target setting */ + /* [12]=WACS1(MD_SW1), latency=1000us, target= (1000/1.2)-1=832 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_12, 0x0740); /* [10]: enable starvation, [9:0]: target setting */ + + /* ############################### */ + /* PMIC_WRAP enables */ + /* ############################### */ + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, 0x01fff); + WRAP_WR32(PMIC_WRAP_WACS0_EN, ENABLE); + WRAP_WR32(PMIC_WRAP_WACS1_EN, ENABLE); + WRAP_WR32(PMIC_WRAP_WACS3_EN, ENABLE); + WRAP_WR32(PMIC_WRAP_STAUPD_PRD, 0x5); /* 100us */ + WRAP_WR32(PMIC_WRAP_WDT_UNIT, 0xf); + WRAP_WR32(PMIC_WRAP_WDT_SRC_EN, 0xffffffff); + WRAP_WR32(PMIC_WRAP_TIMER_EN, 0x1); + /* WRAP_WR32(PMIC_WRAP_INT0_EN, 0xffffffff); */ + WRAP_WR32(PMIC_WRAP_INT0_EN, 0xfffffffD); /* FIX ME */ + WRAP_WR32(PMIC_WRAP_INT1_EN, 0x0001ffff); + + /* ############################### */ + /* Initialization Done */ + /* ############################### */ + WRAP_WR32(PMIC_WRAP_INIT_DONE0, ENABLE); /* MD SW0 */ + WRAP_WR32(PMIC_WRAP_INIT_DONE1, ENABLE); /* MD SW1 */ + WRAP_WR32(PMIC_WRAP_INIT_DONE2, ENABLE); /* AP SW */ + WRAP_WR32(PMIC_WRAP_INIT_DONE3, ENABLE); /* C2K SW */ + +#ifdef PMIC_WRAP_KERNEL_DRIVER +#ifdef CONFIG_OF + pwrap_of_iounmap(); +#endif +#endif + + return 0; +} + +#ifdef PMIC_WRAP_KERNEL_DRIVER +static irqreturn_t mt_pmic_wrap_irq(int irqno, void *dev_id) +{ + unsigned long flags = 0; + + PWRAPFUC(); + PWRAPREG("dump pwrap register\n"); + spin_lock_irqsave(&wrp_lock_isr, flags); + /* *----------------------------------------------------------------------- */ + pwrap_dump_all_register(); + /* raise the priority of WACS2 for AP */ + WRAP_WR32(PMIC_WRAP_HARB_HPRIO, WACS2); + + /* *----------------------------------------------------------------------- */ + PWRAPREG("INT flag 0x%x\n", WRAP_RD32(PMIC_WRAP_INT0_FLG_RAW)); + PWRAPREG("INT flag 0x%x\n", WRAP_RD32(PMIC_WRAP_INT1_FLG_RAW)); + /* clear interrupt flag */ + WRAP_WR32(PMIC_WRAP_INT0_CLR, 0xffffffff); + WRAP_WR32(PMIC_WRAP_INT1_CLR, 0xffffffff); + /*BUG_ON(1);*/ + spin_unlock_irqrestore(&wrp_lock_isr, flags); + return IRQ_HANDLED; +} + + +static u32 pwrap_read_test(void) +{ + u32 rdata = 0; + u32 return_value = 0; + /* Read Test */ +#ifdef SLV_6351 + return_value = pwrap_read(MT6351_DEW_READ_TEST, &rdata); + if (rdata != MT6351_DEFAULT_VALUE_READ_TEST) { + PWRAPREG("Read Test fail,rdata=0x%x, exp=0x5aa5,return_value=0x%x\n", rdata, + return_value); + return E_PWR_READ_TEST_FAIL; + } else { + PWRAPREG("Read Test pass,return_value=%d\n", return_value); + /* return 0; */ + } +#endif + + return 0; +} + +static u32 pwrap_write_test(void) +{ + u32 rdata = 0; + u32 sub_return = 0; + u32 sub_return1 = 0; + /* ############################### */ + /* Write test using WACS2 */ + /* ############################### */ +#ifdef SLV_6351 + sub_return = pwrap_write(MT6351_DEW_WRITE_TEST, MT6351_WRITE_TEST_VALUE); + PWRAPREG("after MT6351 pwrap_write\n"); + sub_return1 = pwrap_read(MT6351_DEW_WRITE_TEST, &rdata); + if ((rdata != MT6351_WRITE_TEST_VALUE) || (sub_return != 0) || (sub_return1 != 0)) { + PWRAPREG + ("write test error,rdata=0x%x,exp=0xa55a,sub_return=0x%x,sub_return1=0x%x\n", + rdata, sub_return, sub_return1); + return E_PWR_INIT_WRITE_TEST; + } else { + PWRAPREG("write MT6351 Test pass\n"); + /* return 0; */ + } +#endif + + return 0; +} + +static void pwrap_int_test(void) +{ + u32 rdata1 = 0; + u32 rdata2 = 0; + + while (1) { +#ifdef SLV_6351 + rdata1 = WRAP_RD32(PMIC_WRAP_EINT_STA); + pwrap_read(MT6351_INT_STA, &rdata2); + PWRAPREG + ("Pwrap INT status check,PMIC_WRAP_EINT_STA=0x%x,MT6351_INT_STA[0x01B4]=0x%x\n", + rdata1, rdata2); +#endif + msleep(500); + } +} + +#ifndef USER_BUILD_KERNEL +static void pwrap_read_reg_on_pmic(u32 reg_addr) +{ + u32 reg_value = 0; + u32 return_value = 0; + /* PWRAPFUC(); */ + return_value = pwrap_read(reg_addr, ®_value); + PWRAPREG("0x%x=0x%x,return_value=%x\n", reg_addr, reg_value, return_value); +} + +static void pwrap_write_reg_on_pmic(u32 reg_addr, u32 reg_value) +{ + u32 return_value = 0; + + PWRAPREG("write 0x%x to register 0x%x\n", reg_value, reg_addr); + return_value = pwrap_write(reg_addr, reg_value); + return_value = pwrap_read(reg_addr, ®_value); + /* PWRAPFUC(); */ + PWRAPREG("the result:0x%x=0x%x,return_value=%x\n", reg_addr, reg_value, return_value); +} +#endif + +static void pwrap_ut(u32 ut_test) +{ + switch (ut_test) { + case 1: + /* pwrap_wacs2_para_test(); */ + pwrap_write_test(); + break; + case 2: + /* pwrap_wacs2_para_test(); */ + pwrap_read_test(); + break; + + default: + PWRAPREG("default test.\n"); + break; + } + return; +} + +/*---------------------------------------------------------------------------*/ +static s32 mt_pwrap_show_hal(char *buf) +{ + PWRAPFUC(); + return snprintf(buf, PAGE_SIZE, "%s\n", "no implement"); +} + +/*---------------------------------------------------------------------------*/ +static s32 mt_pwrap_store_hal(const char *buf, size_t count) +{ +#ifndef USER_BUILD_KERNEL + u32 reg_value = 0; + u32 reg_addr = 0; +#endif + u32 return_value = 0; + u32 ut_test = 0; + + if (!strncmp(buf, "-h", 2)) { + PWRAPREG + ("PWRAP debug: [-dump_reg][-trace_wacs2][-init][-rdpmic][-wrpmic][-readtest][-writetest]\n"); + PWRAPREG("PWRAP UT: [1][2]\n"); + } + /* ----------pwrap debug---------- */ + else if (!strncmp(buf, "-dump_reg", 9)) { + pwrap_dump_all_register(); + } else if (!strncmp(buf, "-trace_wacs2", 12)) { + /* pwrap_trace_wacs2(); */ + } else if (!strncmp(buf, "-init", 5)) { + return_value = pwrap_init(); + if (return_value == 0) + PWRAPREG("pwrap_init pass,return_value=%d\n", return_value); + else + PWRAPREG("pwrap_init fail,return_value=%d\n", return_value); + } +#ifndef USER_BUILD_KERNEL + else if (!strncmp(buf, "-rdpmic", 7) && (1 == sscanf(buf + 7, "%x", ®_addr))) { + pwrap_read_reg_on_pmic(reg_addr); + } else if (!strncmp(buf, "-wrpmic", 7) + && (2 == sscanf(buf + 7, "%x %x", ®_addr, ®_value))) { + pwrap_write_reg_on_pmic(reg_addr, reg_value); + } +#endif + else if (!strncmp(buf, "-readtest", 9)) { + pwrap_read_test(); + } else if (!strncmp(buf, "-writetest", 10)) { + pwrap_write_test(); + } else if (!strncmp(buf, "-int", 4)) { + pwrap_int_test(); + } + /* ----------pwrap UT---------- */ + else if (!strncmp(buf, "-ut", 3) && (1 == sscanf(buf + 3, "%d", &ut_test))) { + pwrap_ut(ut_test); + } else { + PWRAPREG("wrong parameter\n"); + } + return count; +} + +/*---------------------------------------------------------------------------*/ +#endif /* End of #endif PMIC_WRAP_KERNEL_DRIVER */ + +#ifdef PMIC_WRAP_PRELOADER_DRIVER +s32 pwrap_init_preloader(void) +{ + u32 pwrap_ret = 0, i = 0; + + PWRAPFUC(); + for (i = 0; i < 3; i++) { + pwrap_ret = pwrap_init(); + if (pwrap_ret != 0) { + printf("[PMIC_WRAP]wrap_init fail,the return value=%x.\n", pwrap_ret); + } else { + printf("[PMIC_WRAP]wrap_init pass,the return value=%x.\n", pwrap_ret); + break; /* init pass */ + } + } +#ifdef PWRAP_PRELOADER_PORTING + /* pwrap_init_for_early_porting(); */ +#endif + return 0; +} + +#ifdef PWRAP_PRELOADER_PORTING +/* -------------------------------------------------------- */ +/* Function : _pwrap_status_update_test() */ +/* Description :only for early porting */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_status_update_test_porting(void) +{ + /* u32 i, j; */ + u32 rdata; + + volatile u32 delay = 1000 * 1000 * 1; + + PWRAPFUC(); + /* disable signature interrupt */ + WRAP_WR32(PMIC_WRAP_INT_EN, 0x0); +#ifdef SLV_6351 + pwrap_write(MT6351_DEW_WRITE_TEST, MT6351_WRITE_TEST_VALUE); + WRAP_WR32(PMIC_WRAP_SIG_ADR, MT6351_DEW_WRITE_TEST); + WRAP_WR32(PMIC_WRAP_SIG_VALUE, 0xAA55); +#endif + WRAP_WR32(PMIC_WRAP_SIG_MODE, 0x1); + + while (delay--) + ; + + rdata = WRAP_RD32(PMIC_WRAP_SIG_ERRVAL); +#ifdef SLV_6351 + if ((rdata & 0xFFFF) != MT6351_WRITE_TEST_VALUE) { + PWRAPLOG("MT6351 _pwrap_status_update_test error,error code=%x, rdata=%x\n", 1, + (rdata & 0xFFFF)); + /* return 1; */ + } +#endif +#ifdef SLV_6351 + WRAP_WR32(PMIC_WRAP_SIG_VALUE, MT6351_WRITE_TEST_VALUE); /* tha same as write test */ +#endif + + /* clear sig_error interrupt flag bit */ + WRAP_WR32(PMIC_WRAP_INT_CLR, 1 << 1); + + /* enable signature interrupt */ + WRAP_WR32(PMIC_WRAP_INT_EN, 0x7ffffff9); + WRAP_WR32(PMIC_WRAP_SIG_MODE, 0x0); +#ifdef SLV_6351 + WRAP_WR32(PMIC_WRAP_SIG_ADR, MT6351_DEW_CRC_VAL); +#endif + return 0; +} + +void pwrap_init_for_early_porting(void) +{ + int ret = 0; + u32 res = 0; + + PWRAPFUC(); + + ret = _pwrap_status_update_test_porting(); + if (ret == 0) { + PWRAPLOG("wrapper_StatusUpdateTest pass.\n"); + } else { + PWRAPLOG("error:wrapper_StatusUpdateTest fail.\n"); + res += 1; + } +} +#endif /* PWRAP_PRELOADER_PORTING */ +#endif /* End of #ifdef PMIC_WRAP_PRELOADER_DRIVER */ + +#ifdef PMIC_WRAP_LK_DRIVER +s32 pwrap_init_lk(void) +{ + u32 pwrap_ret = 0, i = 0; + + PWRAPFUC(); + for (i = 0; i < 3; i++) { + pwrap_ret = pwrap_init(); + if (pwrap_ret != 0) { + printf("[PMIC_WRAP]wrap_init fail,the return value=%x.\n", pwrap_ret); + } else { + printf("[PMIC_WRAP]wrap_init pass,the return value=%x.\n", pwrap_ret); + break; /* init pass */ + } + } +#ifdef PWRAP_PRELOADER_PORTING + /* pwrap_init_for_early_porting(); */ +#endif + return 0; +} +#endif + +#endif /* End of #if PMIC_WRAP_NO_PMIC */ + +#ifdef PMIC_WRAP_KERNEL_DRIVER +#ifdef CONFIG_OF +static int pwrap_of_iomap(void) +{ + /* + * Map the address of the following register base: + * TOPCKGEN, INFRACFG_AO, GPIO, SLEEP + */ + + struct device_node *topckgen_node; + struct device_node *infracfg_ao_node; + struct device_node *gpio_node; + struct device_node *sleep_node; + + topckgen_node = of_find_compatible_node(NULL, NULL, "mediatek,TOPCKGEN"); + if (!topckgen_node) { + pr_info("get TOPCKGEN failed\n"); + return -ENODEV; + } + + topckgen_reg_base = of_iomap(topckgen_node, 0); + if (!topckgen_reg_base) { + pr_info("TOPCKGEN iomap failed\n"); + return -ENOMEM; + } + + infracfg_ao_node = of_find_compatible_node(NULL, NULL, "mediatek,INFRACFG_AO"); + if (!infracfg_ao_node) { + pr_info("get INFRACFG_AO failed\n"); + return -ENODEV; + } + + infracfg_ao_reg_base = of_iomap(infracfg_ao_node, 0); + if (!infracfg_ao_reg_base) { + pr_info("INFRACFG_AO iomap failed\n"); + return -ENOMEM; + } + + gpio_node = of_find_compatible_node(NULL, NULL, "mediatek,GPIO"); + if (!gpio_node) { + pr_info("get GPIO failed\n"); + return -ENODEV; + } + + gpio_reg_base = of_iomap(gpio_node, 0); + if (!gpio_reg_base) { + pr_info("GPIO iomap failed\n"); + return -ENOMEM; + } + + sleep_node = of_find_compatible_node(NULL, NULL, "mediatek,SLEEP"); + if (!sleep_node) { + pr_info("get SLEEP failed\n"); + return -ENODEV; + } + + sleep_reg_base = of_iomap(sleep_node, 0); + if (!sleep_reg_base) { + pr_info("SLEEp iomap failed\n"); + return -ENOMEM; + } + + pr_info("TOPCKGEN reg: 0x%p\n", topckgen_reg_base); + pr_info("INFRACFG_AO reg: 0x%p\n", infracfg_ao_reg_base); + pr_info("GPIO reg: 0x%p\n", gpio_reg_base); + pr_info("SLEEP reg: 0x%p\n", sleep_reg_base); + + return 0; +} + +static void pwrap_of_iounmap(void) +{ + iounmap(topckgen_reg_base); + iounmap(infracfg_ao_reg_base); + iounmap(gpio_reg_base); + iounmap(sleep_reg_base); +} +#endif + +#define VERSION "Revision" +static int is_pwrap_init_done(void) +{ + int ret = 0; + + ret = WRAP_RD32(PMIC_WRAP_INIT_DONE2); + if (ret != 0) + return 0; + + ret = pwrap_init(); + if (ret != 0) { + PWRAPERR("init error (%d)\n", ret); + pwrap_dump_all_register(); + return ret; + } + PWRAPLOG("init successfully done (%d)\n\n", ret); + return ret; +} + +static int __init pwrap_hal_init(void) +{ + s32 ret = 0; +#ifdef CONFIG_OF + u32 pwrap_irq; + struct device_node *pwrap_node; + + pwrap_node = of_find_compatible_node(NULL, NULL, "mediatek,PWRAP"); + if (!pwrap_node) { + pr_info("PWRAP get node failed\n"); + return -ENODEV; + } + + pwrap_base = of_iomap(pwrap_node, 0); + if (!pwrap_base) { + pr_info("PWRAP iomap failed\n"); + return -ENOMEM; + } + + pwrap_irq = irq_of_parse_and_map(pwrap_node, 0); + if (!pwrap_irq) { + pr_info("PWRAP get irq fail\n"); + return -ENODEV; + } + pr_info("PWRAP reg: 0x%p, irq: %d\n", pwrap_base, pwrap_irq); +#endif + + PWRAPLOG("HAL init: version %s\n", VERSION); + mt_wrp = get_mt_pmic_wrap_drv(); + mt_wrp->store_hal = mt_pwrap_store_hal; + mt_wrp->show_hal = mt_pwrap_show_hal; + mt_wrp->wacs2_hal = pwrap_wacs2_hal; + + if (is_pwrap_init_done() == 0) { +#ifdef PMIC_WRAP_NO_PMIC +#else + + ret = + request_irq(MT_PMIC_WRAP_IRQ_ID, mt_pmic_wrap_irq, IRQF_TRIGGER_HIGH, + PMIC_WRAP_DEVICE, 0); +#endif + if (ret) { + PWRAPERR("register IRQ failed (%d)\n", ret); + return ret; + } + } else { + PWRAPERR("not init (%d)\n", ret); + } + + /* PWRAPERR("not init (%x)\n", is_pwrap_init_done); */ + + return ret; +} +postcore_initcall(pwrap_hal_init); +#endif /* End of #ifdef PMIC_WRAP_KERNEL_DRIVER */ diff --git a/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal.h b/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal.h new file mode 100644 index 0000000000000000000000000000000000000000..92b50a498a13ba16fd5986948692b6791cfa899f --- /dev/null +++ b/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal.h @@ -0,0 +1,582 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef __PWRAP_HAL_H__ +#define __PWRAP_HAL_H__ + + +/* Should not include mt_reg_base.h and mt_irq.h if using device tree */ +#ifndef CONFIG_OF +#include +#include +#endif + +#include +#include "mt-plat/sync_write.h" + + +#define PMIC_WRAP_DEBUG +/* #define PMIC_WRAP_SLIM */ + +#define PWRAPTAG "[PWRAP] " + +#ifdef PMIC_WRAP_DEBUG +#define PWRAPDEB(fmt, arg...) printk(PWRAPTAG "cpuid=%d," fmt, raw_smp_processor_id(), ##arg) +#define PWRAPFUC(fmt, arg...) printk(PWRAPTAG "cpuid=%d,%s\n", raw_smp_processor_id(), __func__) +#ifndef PMIC_WRAP_SLIM +#define PWRAPLOG(fmt, arg...) printk(PWRAPTAG fmt, ##arg) +#else +#define PWRAPLOG(fmt, arg...) +#endif + +#else /* Else of #ifdef PMIC_WRAP_DEBUG */ +#define PWRAPDEB(fmt, arg...) +#define PWRAPFUC(fmt, arg...) +#define PWRAPLOG(fmt, arg...) +#endif + +#define PWRAPREG(fmt, arg...) pr_debug(PWRAPTAG fmt, ##arg) +#define PWRAPERR(fmt, arg...) pr_debug(PWRAPTAG "ERROR,line=%d " fmt, __LINE__, ##arg) + + +/* ---start ---external API-------------------------------------------------- */ +s32 pwrap_write_nochk(u32 adr, u32 wdata); +s32 pwrap_read_nochk(u32 adr, u32 *rdata); +/* ---end ---external API---------------------------------------------------- */ + +/************************ For BringUp *********************/ +#if defined(CONFIG_MTK_FPGA) +#define PMIC_WRAP_NO_PMIC /* /TODO: Fix me //if BringUp doesn't had PMIC, need open this */ +#else +#endif +/**********************************************************/ +#if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#define SLV_6351 +#endif +/* #define ULPOSC */ + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#define PMIC_CHIP_STR "MT6353" +#endif + +#ifdef CONFIG_OF +extern void __iomem *pwrap_base; +#define PMIC_WRAP_BASE (pwrap_base) /* 0x1000D000 */ +#define MT_PMIC_WRAP_IRQ_ID (pwrap_irq) +#else +#define MT_PMIC_WRAP_IRQ_ID (PMIC_WRAP_ERR_IRQ_BIT_ID) +#define PMIC_WRAP_BASE (PWRAP_BASE) +#endif + +#define PMIC_WRAP_REG_RANGE 208 + +/* -------macro for timeout setting-------------------------------- */ +/****************************************************************************** +global variable and sys interface +******************************************************************************/ +/* #define TIMEOUT_RESET 0xFF //us */ +/* #define TIMEOUT_READ 0xFF //us */ +/* #define TIMEOUT_WAIT_IDLE 0xFF //us */ +/* #define TIMEOUT_RESET 0x7D0 //2000us */ +/* #define TIMEOUT_READ 0x7D0 //2000us */ +/* #define TIMEOUT_WAIT_IDLE 0x7D0 //2000us */ +#define TIMEOUT_RESET 0x2710 /* 10000us (> WDT TIME) */ +#define TIMEOUT_READ 0x2710 /* 10000us (> WDT TIME) */ +#define TIMEOUT_WAIT_IDLE 0x2710 /* 10000us (> WDT TIME) */ + +/* -------macro for spi clock config-------------------------------- */ +/* From reg_plateform.h */ +/* +#define TOPCKGEN_BASE (0x10000000) +#define INFRACFG_AO_BASE (0x10001000) +#define GPIO_BASE (0x10005000) +#define SLEEP_BASE (0x10006000) +*/ + +#ifdef CONFIG_OF +#define TOPCKGEN_REG_BASE (topckgen_reg_base) +#define INFRACFG_AO_REG_BASE (infracfg_ao_reg_base) +#define GPIO_REG_BASE (gpio_reg_base) +#define SLEEP_REG_BASE (sleep_reg_base) +#else +#define TOPCKGEN_REG_BASE (CKSYS_BASE) +#define INFRACFG_AO_REG_BASE (INFRACFG_AO_BASE) +#define GPIO_REG_BASE (GPIO_BASE) +#define SLEEP_REG_BASE (SLEEP_BASE) +#endif + +#define CLK_CFG_5_CLR ((TOPCKGEN_REG_BASE+0x098)) +#define CLK_CFG_5_SET ((TOPCKGEN_REG_BASE+0x094)) +#define CLK_CFG_UPDATE ((TOPCKGEN_REG_BASE+0x004)) +#define ULPOSC_CON ((SLEEP_REG_BASE+0x458)) +#define GPIO_DUMMY ((GPIO_REG_BASE+0x6C0)) +#define PMICW_CLOCK_CTRL ((INFRACFG_AO_REG_BASE+0x108)) +#define INFRA_GLOBALCON_RST2_SET ((INFRACFG_AO_REG_BASE+0x140)) +#define INFRA_GLOBALCON_RST2_CLR ((INFRACFG_AO_REG_BASE+0x144)) +#define MODULE_SW_CG_0_SET ((INFRACFG_AO_REG_BASE+0x080)) +#define MODULE_SW_CG_0_CLR ((INFRACFG_AO_REG_BASE+0x084)) + +#define PMIC_CG_TMR (1 << 0) +#define PMIC_CG_AP (1 << 1) +#define PMIC_CG_MD (1 << 2) +#define PMIC_CG_CONN (1 << 3) +#define PMIC_DCM_EN (1 << 22) + +/* PMIC_WRAP registers */ +/* From reg_PMIC_WRAP.h */ +#define PMIC_WRAP_MUX_SEL ((PMIC_WRAP_BASE+0x0)) +#define PMIC_WRAP_WRAP_EN ((PMIC_WRAP_BASE+0x4)) +#define PMIC_WRAP_DIO_EN ((PMIC_WRAP_BASE+0x8)) +#define PMIC_WRAP_SIDLY ((PMIC_WRAP_BASE+0xC)) +#define PMIC_WRAP_RDDMY ((PMIC_WRAP_BASE+0x10)) +#define PMIC_WRAP_SI_CK_CON ((PMIC_WRAP_BASE+0x14)) +#define PMIC_WRAP_CSHEXT_WRITE ((PMIC_WRAP_BASE+0x18)) +#define PMIC_WRAP_CSHEXT_READ ((PMIC_WRAP_BASE+0x1C)) +#define PMIC_WRAP_CSLEXT_START ((PMIC_WRAP_BASE+0x20)) +#define PMIC_WRAP_CSLEXT_END ((PMIC_WRAP_BASE+0x24)) +#define PMIC_WRAP_STAUPD_PRD ((PMIC_WRAP_BASE+0x28)) +#define PMIC_WRAP_STAUPD_GRPEN ((PMIC_WRAP_BASE+0x2C)) +#define PMIC_WRAP_EINT_STA0_ADR ((PMIC_WRAP_BASE+0x30)) +#define PMIC_WRAP_EINT_STA1_ADR ((PMIC_WRAP_BASE+0x34)) +#define PMIC_WRAP_EINT_STA ((PMIC_WRAP_BASE+0x38)) +#define PMIC_WRAP_EINT_CLR ((PMIC_WRAP_BASE+0x3C)) +#define PMIC_WRAP_STAUPD_MAN_TRIG ((PMIC_WRAP_BASE+0x40)) +#define PMIC_WRAP_STAUPD_STA ((PMIC_WRAP_BASE+0x44)) +#define PMIC_WRAP_WRAP_STA ((PMIC_WRAP_BASE+0x48)) +#define PMIC_WRAP_HARB_INIT ((PMIC_WRAP_BASE+0x4C)) +#define PMIC_WRAP_HARB_HPRIO ((PMIC_WRAP_BASE+0x50)) +#define PMIC_WRAP_HIPRIO_ARB_EN ((PMIC_WRAP_BASE+0x54)) +#define PMIC_WRAP_HARB_STA0 ((PMIC_WRAP_BASE+0x58)) +#define PMIC_WRAP_HARB_STA1 ((PMIC_WRAP_BASE+0x5C)) +#define PMIC_WRAP_MAN_EN ((PMIC_WRAP_BASE+0x60)) +#define PMIC_WRAP_MAN_CMD ((PMIC_WRAP_BASE+0x64)) +#define PMIC_WRAP_MAN_RDATA ((PMIC_WRAP_BASE+0x68)) +#define PMIC_WRAP_MAN_VLDCLR ((PMIC_WRAP_BASE+0x6C)) +#define PMIC_WRAP_WACS0_EN ((PMIC_WRAP_BASE+0x70)) +#define PMIC_WRAP_INIT_DONE0 ((PMIC_WRAP_BASE+0x74)) +#define PMIC_WRAP_WACS0_CMD ((PMIC_WRAP_BASE+0x78)) +#define PMIC_WRAP_WACS0_RDATA ((PMIC_WRAP_BASE+0x7C)) +#define PMIC_WRAP_WACS0_VLDCLR ((PMIC_WRAP_BASE+0x80)) +#define PMIC_WRAP_WACS1_EN ((PMIC_WRAP_BASE+0x84)) +#define PMIC_WRAP_INIT_DONE1 ((PMIC_WRAP_BASE+0x88)) +#define PMIC_WRAP_WACS1_CMD ((PMIC_WRAP_BASE+0x8C)) +#define PMIC_WRAP_WACS1_RDATA ((PMIC_WRAP_BASE+0x90)) +#define PMIC_WRAP_WACS1_VLDCLR ((PMIC_WRAP_BASE+0x94)) +#define PMIC_WRAP_WACS2_EN ((PMIC_WRAP_BASE+0x98)) +#define PMIC_WRAP_INIT_DONE2 ((PMIC_WRAP_BASE+0x9C)) +#define PMIC_WRAP_WACS2_CMD ((PMIC_WRAP_BASE+0xA0)) +#define PMIC_WRAP_WACS2_RDATA ((PMIC_WRAP_BASE+0xA4)) +#define PMIC_WRAP_WACS2_VLDCLR ((PMIC_WRAP_BASE+0xA8)) +#define PMIC_WRAP_WACS3_EN ((PMIC_WRAP_BASE+0xAC)) +#define PMIC_WRAP_INIT_DONE3 ((PMIC_WRAP_BASE+0xB0)) +#define PMIC_WRAP_WACS3_CMD ((PMIC_WRAP_BASE+0xB4)) +#define PMIC_WRAP_WACS3_RDATA ((PMIC_WRAP_BASE+0xB8)) +#define PMIC_WRAP_WACS3_VLDCLR ((PMIC_WRAP_BASE+0xBC)) +#define PMIC_WRAP_INT0_EN ((PMIC_WRAP_BASE+0xC0)) +#define PMIC_WRAP_INT0_FLG_RAW ((PMIC_WRAP_BASE+0xC4)) +#define PMIC_WRAP_INT0_FLG ((PMIC_WRAP_BASE+0xC8)) +#define PMIC_WRAP_INT0_CLR ((PMIC_WRAP_BASE+0xCC)) +#define PMIC_WRAP_INT1_EN ((PMIC_WRAP_BASE+0xD0)) +#define PMIC_WRAP_INT1_FLG_RAW ((PMIC_WRAP_BASE+0xD4)) +#define PMIC_WRAP_INT1_FLG ((PMIC_WRAP_BASE+0xD8)) +#define PMIC_WRAP_INT1_CLR ((PMIC_WRAP_BASE+0xDC)) +#define PMIC_WRAP_SIG_ADR ((PMIC_WRAP_BASE+0xE0)) +#define PMIC_WRAP_SIG_MODE ((PMIC_WRAP_BASE+0xE4)) +#define PMIC_WRAP_SIG_VALUE ((PMIC_WRAP_BASE+0xE8)) +#define PMIC_WRAP_SIG_ERRVAL ((PMIC_WRAP_BASE+0xEC)) +#define PMIC_WRAP_CRC_EN ((PMIC_WRAP_BASE+0xF0)) +#define PMIC_WRAP_TIMER_EN ((PMIC_WRAP_BASE+0xF4)) +#define PMIC_WRAP_TIMER_STA ((PMIC_WRAP_BASE+0xF8)) +#define PMIC_WRAP_WDT_UNIT ((PMIC_WRAP_BASE+0xFC)) +#define PMIC_WRAP_WDT_SRC_EN ((PMIC_WRAP_BASE+0x100)) +#define PMIC_WRAP_WDT_FLG ((PMIC_WRAP_BASE+0x104)) +#define PMIC_WRAP_DEBUG_INT_SEL ((PMIC_WRAP_BASE+0x108)) +#define PMIC_WRAP_DVFS_ADR0 ((PMIC_WRAP_BASE+0x10C)) +#define PMIC_WRAP_DVFS_WDATA0 ((PMIC_WRAP_BASE+0x110)) +#define PMIC_WRAP_DVFS_ADR1 ((PMIC_WRAP_BASE+0x114)) +#define PMIC_WRAP_DVFS_WDATA1 ((PMIC_WRAP_BASE+0x118)) +#define PMIC_WRAP_DVFS_ADR2 ((PMIC_WRAP_BASE+0x11C)) +#define PMIC_WRAP_DVFS_WDATA2 ((PMIC_WRAP_BASE+0x120)) +#define PMIC_WRAP_DVFS_ADR3 ((PMIC_WRAP_BASE+0x124)) +#define PMIC_WRAP_DVFS_WDATA3 ((PMIC_WRAP_BASE+0x128)) +#define PMIC_WRAP_DVFS_ADR4 ((PMIC_WRAP_BASE+0x12C)) +#define PMIC_WRAP_DVFS_WDATA4 ((PMIC_WRAP_BASE+0x130)) +#define PMIC_WRAP_DVFS_ADR5 ((PMIC_WRAP_BASE+0x134)) +#define PMIC_WRAP_DVFS_WDATA5 ((PMIC_WRAP_BASE+0x138)) +#define PMIC_WRAP_DVFS_ADR6 ((PMIC_WRAP_BASE+0x13C)) +#define PMIC_WRAP_DVFS_WDATA6 ((PMIC_WRAP_BASE+0x140)) +#define PMIC_WRAP_DVFS_ADR7 ((PMIC_WRAP_BASE+0x144)) +#define PMIC_WRAP_DVFS_WDATA7 ((PMIC_WRAP_BASE+0x148)) +#define PMIC_WRAP_DVFS_ADR8 ((PMIC_WRAP_BASE+0x14C)) +#define PMIC_WRAP_DVFS_WDATA8 ((PMIC_WRAP_BASE+0x150)) +#define PMIC_WRAP_DVFS_ADR9 ((PMIC_WRAP_BASE+0x154)) +#define PMIC_WRAP_DVFS_WDATA9 ((PMIC_WRAP_BASE+0x158)) +#define PMIC_WRAP_DVFS_ADR10 ((PMIC_WRAP_BASE+0x15C)) +#define PMIC_WRAP_DVFS_WDATA10 ((PMIC_WRAP_BASE+0x160)) +#define PMIC_WRAP_DVFS_ADR11 ((PMIC_WRAP_BASE+0x164)) +#define PMIC_WRAP_DVFS_WDATA11 ((PMIC_WRAP_BASE+0x168)) +#define PMIC_WRAP_DVFS_ADR12 ((PMIC_WRAP_BASE+0x16C)) +#define PMIC_WRAP_DVFS_WDATA12 ((PMIC_WRAP_BASE+0x170)) +#define PMIC_WRAP_DVFS_ADR13 ((PMIC_WRAP_BASE+0x174)) +#define PMIC_WRAP_DVFS_WDATA13 ((PMIC_WRAP_BASE+0x178)) +#define PMIC_WRAP_DVFS_ADR14 ((PMIC_WRAP_BASE+0x17C)) +#define PMIC_WRAP_DVFS_WDATA14 ((PMIC_WRAP_BASE+0x180)) +#define PMIC_WRAP_DVFS_ADR15 ((PMIC_WRAP_BASE+0x184)) +#define PMIC_WRAP_DVFS_WDATA15 ((PMIC_WRAP_BASE+0x188)) +#define PMIC_WRAP_DCXO_ENABLE ((PMIC_WRAP_BASE+0x18C)) +#define PMIC_WRAP_DCXO_CONN_ADR0 ((PMIC_WRAP_BASE+0x190)) +#define PMIC_WRAP_DCXO_CONN_WDATA0 ((PMIC_WRAP_BASE+0x194)) +#define PMIC_WRAP_DCXO_CONN_ADR1 ((PMIC_WRAP_BASE+0x198)) +#define PMIC_WRAP_DCXO_CONN_WDATA1 ((PMIC_WRAP_BASE+0x19C)) +#define PMIC_WRAP_DCXO_NFC_ADR0 ((PMIC_WRAP_BASE+0x1A0)) +#define PMIC_WRAP_DCXO_NFC_WDATA0 ((PMIC_WRAP_BASE+0x1A4)) +#define PMIC_WRAP_DCXO_NFC_ADR1 ((PMIC_WRAP_BASE+0x1A8)) +#define PMIC_WRAP_DCXO_NFC_WDATA1 ((PMIC_WRAP_BASE+0x1AC)) +#define PMIC_WRAP_SPMINF_STA ((PMIC_WRAP_BASE+0x1B0)) +#define PMIC_WRAP_CIPHER_KEY_SEL ((PMIC_WRAP_BASE+0x1B4)) +#define PMIC_WRAP_CIPHER_IV_SEL ((PMIC_WRAP_BASE+0x1B8)) +#define PMIC_WRAP_CIPHER_EN ((PMIC_WRAP_BASE+0x1BC)) +#define PMIC_WRAP_CIPHER_RDY ((PMIC_WRAP_BASE+0x1C0)) +#define PMIC_WRAP_CIPHER_MODE ((PMIC_WRAP_BASE+0x1C4)) +#define PMIC_WRAP_CIPHER_SWRST ((PMIC_WRAP_BASE+0x1C8)) +#define PMIC_WRAP_DCM_EN ((PMIC_WRAP_BASE+0x1CC)) +#define PMIC_WRAP_DCM_SPI_DBC_PRD ((PMIC_WRAP_BASE+0x1D0)) +#define PMIC_WRAP_DCM_DBC_PRD ((PMIC_WRAP_BASE+0x1D4)) +#define PMIC_WRAP_EXT_CK ((PMIC_WRAP_BASE+0x1D8)) +#define PMIC_WRAP_ADC_CMD_ADDR ((PMIC_WRAP_BASE+0x1DC)) +#define PMIC_WRAP_PWRAP_ADC_CMD ((PMIC_WRAP_BASE+0x1E0)) +#define PMIC_WRAP_ADC_RDATA_ADDR ((PMIC_WRAP_BASE+0x1E4)) +#define PMIC_WRAP_GPS_STA ((PMIC_WRAP_BASE+0x1E8)) +#define PMIC_WRAP_SWRST ((PMIC_WRAP_BASE+0x1EC)) +#define PMIC_WRAP_HARB_SLEEP_GATED_CTRL ((PMIC_WRAP_BASE+0x1F0)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR_LATEST ((PMIC_WRAP_BASE+0x1F4)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR_WP ((PMIC_WRAP_BASE+0x1F8)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR0 ((PMIC_WRAP_BASE+0x1FC)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR1 ((PMIC_WRAP_BASE+0x200)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR2 ((PMIC_WRAP_BASE+0x204)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR3 ((PMIC_WRAP_BASE+0x208)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR4 ((PMIC_WRAP_BASE+0x20C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR5 ((PMIC_WRAP_BASE+0x210)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR6 ((PMIC_WRAP_BASE+0x214)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR7 ((PMIC_WRAP_BASE+0x218)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR8 ((PMIC_WRAP_BASE+0x21C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR9 ((PMIC_WRAP_BASE+0x220)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR10 ((PMIC_WRAP_BASE+0x224)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR11 ((PMIC_WRAP_BASE+0x228)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR12 ((PMIC_WRAP_BASE+0x22C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR13 ((PMIC_WRAP_BASE+0x230)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR14 ((PMIC_WRAP_BASE+0x234)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR15 ((PMIC_WRAP_BASE+0x238)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR16 ((PMIC_WRAP_BASE+0x23C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR17 ((PMIC_WRAP_BASE+0x240)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR18 ((PMIC_WRAP_BASE+0x244)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR19 ((PMIC_WRAP_BASE+0x248)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR20 ((PMIC_WRAP_BASE+0x24C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR21 ((PMIC_WRAP_BASE+0x250)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR22 ((PMIC_WRAP_BASE+0x254)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR23 ((PMIC_WRAP_BASE+0x258)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR24 ((PMIC_WRAP_BASE+0x25C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR25 ((PMIC_WRAP_BASE+0x260)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR26 ((PMIC_WRAP_BASE+0x264)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR27 ((PMIC_WRAP_BASE+0x268)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR28 ((PMIC_WRAP_BASE+0x26C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR29 ((PMIC_WRAP_BASE+0x270)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR30 ((PMIC_WRAP_BASE+0x274)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR31 ((PMIC_WRAP_BASE+0x278)) +#define PMIC_WRAP_MD_ADC_MODE_SEL ((PMIC_WRAP_BASE+0x27C)) +#define PMIC_WRAP_MD_ADC_STA0 ((PMIC_WRAP_BASE+0x280)) +#define PMIC_WRAP_MD_ADC_STA1 ((PMIC_WRAP_BASE+0x284)) +#define PMIC_WRAP_PRIORITY_USER_SEL_0 ((PMIC_WRAP_BASE+0x288)) +#define PMIC_WRAP_PRIORITY_USER_SEL_1 ((PMIC_WRAP_BASE+0x28C)) +#define PMIC_WRAP_ARBITER_OUT_SEL_0 ((PMIC_WRAP_BASE+0x290)) +#define PMIC_WRAP_ARBITER_OUT_SEL_1 ((PMIC_WRAP_BASE+0x294)) +#define PMIC_WRAP_STARV_COUNTER_0 ((PMIC_WRAP_BASE+0x298)) +#define PMIC_WRAP_STARV_COUNTER_1 ((PMIC_WRAP_BASE+0x29C)) +#define PMIC_WRAP_STARV_COUNTER_2 ((PMIC_WRAP_BASE+0x2A0)) +#define PMIC_WRAP_STARV_COUNTER_3 ((PMIC_WRAP_BASE+0x2A4)) +#define PMIC_WRAP_STARV_COUNTER_4 ((PMIC_WRAP_BASE+0x2A8)) +#define PMIC_WRAP_STARV_COUNTER_5 ((PMIC_WRAP_BASE+0x2AC)) +#define PMIC_WRAP_STARV_COUNTER_6 ((PMIC_WRAP_BASE+0x2B0)) +#define PMIC_WRAP_STARV_COUNTER_7 ((PMIC_WRAP_BASE+0x2B4)) +#define PMIC_WRAP_STARV_COUNTER_8 ((PMIC_WRAP_BASE+0x2B8)) +#define PMIC_WRAP_STARV_COUNTER_9 ((PMIC_WRAP_BASE+0x2BC)) +#define PMIC_WRAP_STARV_COUNTER_10 ((PMIC_WRAP_BASE+0x2C0)) +#define PMIC_WRAP_STARV_COUNTER_11 ((PMIC_WRAP_BASE+0x2C4)) +#define PMIC_WRAP_STARV_COUNTER_12 ((PMIC_WRAP_BASE+0x2C8)) +#define PMIC_WRAP_STARV_COUNTER_13 ((PMIC_WRAP_BASE+0x2CC)) +#define PMIC_WRAP_STARV_COUNTER_14 ((PMIC_WRAP_BASE+0x2D0)) +#define PMIC_WRAP_STARV_COUNTER_15 ((PMIC_WRAP_BASE+0x2D4)) +#define PMIC_WRAP_STARV_COUNTER_0_STATUS ((PMIC_WRAP_BASE+0x2D8)) +#define PMIC_WRAP_STARV_COUNTER_1_STATUS ((PMIC_WRAP_BASE+0x2DC)) +#define PMIC_WRAP_STARV_COUNTER_2_STATUS ((PMIC_WRAP_BASE+0x2E0)) +#define PMIC_WRAP_STARV_COUNTER_3_STATUS ((PMIC_WRAP_BASE+0x2E4)) +#define PMIC_WRAP_STARV_COUNTER_4_STATUS ((PMIC_WRAP_BASE+0x2E8)) +#define PMIC_WRAP_STARV_COUNTER_5_STATUS ((PMIC_WRAP_BASE+0x2EC)) +#define PMIC_WRAP_STARV_COUNTER_6_STATUS ((PMIC_WRAP_BASE+0x2F0)) +#define PMIC_WRAP_STARV_COUNTER_7_STATUS ((PMIC_WRAP_BASE+0x2F4)) +#define PMIC_WRAP_STARV_COUNTER_8_STATUS ((PMIC_WRAP_BASE+0x2F8)) +#define PMIC_WRAP_STARV_COUNTER_9_STATUS ((PMIC_WRAP_BASE+0x2FC)) +#define PMIC_WRAP_STARV_COUNTER_10_STATUS ((PMIC_WRAP_BASE+0x300)) +#define PMIC_WRAP_STARV_COUNTER_11_STATUS ((PMIC_WRAP_BASE+0x304)) +#define PMIC_WRAP_STARV_COUNTER_12_STATUS ((PMIC_WRAP_BASE+0x308)) +#define PMIC_WRAP_STARV_COUNTER_13_STATUS ((PMIC_WRAP_BASE+0x30C)) +#define PMIC_WRAP_STARV_COUNTER_14_STATUS ((PMIC_WRAP_BASE+0x310)) +#define PMIC_WRAP_STARV_COUNTER_15_STATUS ((PMIC_WRAP_BASE+0x314)) +#define PMIC_WRAP_STARV_COUNTER_CLR ((PMIC_WRAP_BASE+0x318)) +#define PMIC_WRAP_STARV_PRIO_STATUS ((PMIC_WRAP_BASE+0x31C)) +#define PMIC_WRAP_DEBUG_STATUS ((PMIC_WRAP_BASE+0x320)) +#define PMIC_WRAP_DEBUG_SQUENCE_0 ((PMIC_WRAP_BASE+0x324)) +#define PMIC_WRAP_DEBUG_SQUENCE_1 ((PMIC_WRAP_BASE+0x328)) +#define PMIC_WRAP_DEBUG_SQUENCE_2 ((PMIC_WRAP_BASE+0x32C)) +#define PMIC_WRAP_DEBUG_SQUENCE_3 ((PMIC_WRAP_BASE+0x330)) +#define PMIC_WRAP_DEBUG_SQUENCE_4 ((PMIC_WRAP_BASE+0x334)) +#define PMIC_WRAP_DEBUG_SQUENCE_5 ((PMIC_WRAP_BASE+0x338)) +#define PMIC_WRAP_DEBUG_SQUENCE_6 ((PMIC_WRAP_BASE+0x33C)) + +/* -----macro for wrapper regsister-------------------------------------------------------- */ +/* From reg_PMIC_WRAP_mac.h */ +#define GET_STAUPD_DLE_CNT(x) ((x>>0) & 0x00000007) +#define GET_STAUPD_ALE_CNT(x) ((x>>3) & 0x00000007) +#define GET_STAUPD_FSM(x) ((x>>6) & 0x00000007) +#define GET_WRAP_CH_DLE_RESTCNT(x) ((x>>0) & 0x00000007) +#define GET_WRAP_CH_ALE_RESTCNT(x) ((x>>3) & 0x00000003) +#define GET_WRAP_AG_DLE_RESTCNT(x) ((x>>5) & 0x00000003) +#define GET_WRAP_CH_W(x) ((x>>7) & 0x00000001) +#define GET_WRAP_CH_REQ(x) ((x>>8) & 0x00000001) +#define GET_AG_WRAP_W(x) ((x>>9) & 0x00000001) +#define GET_AG_WRAP_REQ(x) ((x>>10) & 0x00000001) +#define GET_WRAP_FSM(x) ((x>>11) & 0x0000000f) +#define GET_HARB_WRAP_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_HARB_WRAP_ADR(x) ((x>>16) & 0x00007fff) +#define GET_HARB_WRAP_REQ(x) ((x>>31) & 0x00000001) +#define GET_HARB_DLE_EMPTY(x) ((x>>0) & 0x00000001) +#define GET_HARB_DLE_FULL(x) ((x>>1) & 0x00000001) +#define GET_HARB_VLD(x) ((x>>2) & 0x00000001) +#define GET_HARB_DLE_OWN(x) ((x>>3) & 0x0000000f) +#define GET_HARB_OWN(x) ((x>>7) & 0x0000000f) +#define GET_HARB_DLE_RESTCNT(x) ((x>>11) & 0x0000000f) +#define GET_AG_HARB_REQ(x) ((x>>15) & 0x00003fff) +#define GET_HARB_WRAP_W(x) ((x>>29) & 0x00000001) +#define GET_HARB_WRAP_REQ0(x) ((x>>30) & 0x00000001) +#define GET_SPI_WDATA(x) ((x>>0) & 0x000000ff) +#define GET_SPI_OP(x) ((x>>8) & 0x0000001f) +#define GET_SPI_W(x) ((x>>13) & 0x00000001) +#define GET_MAN_RDATA(x) ((x>>0) & 0x000000ff) +#define GET_MAN_FSM(x) ((x>>8) & 0x00000007) +#define GET_MAN_REQ(x) ((x>>11) & 0x00000001) +#define GET_WACS0_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS0_ADR(x) ((x>>16) & 0x00007fff) +#define GET_WACS0_WRITE(x) ((x>>31) & 0x00000001) +#define GET_WACS0_RDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS0_FSM(x) ((x>>16) & 0x00000007) +#define GET_WACS0_REQ(x) ((x>>19) & 0x00000001) +#define GET_SYNC_IDLE0(x) ((x>>20) & 0x00000001) +#define GET_INIT_DONE0(x) ((x>>21) & 0x00000001) +#define GET_SYS_IDLE0(x) ((x>>22) & 0x00000001) +#define GET_WACS0_FIFO_FILLCNT(x) ((x>>24) & 0x0000000f) +#define GET_WACS0_FIFO_FREECNT(x) ((x>>28) & 0x0000000f) +#define GET_WACS1_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS1_ADR(x) ((x>>16) & 0x00007fff) +#define GET_WACS1_WRITE(x) ((x>>31) & 0x00000001) +#define GET_WACS1_RDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS1_FSM(x) ((x>>16) & 0x00000007) +#define GET_WACS1_REQ(x) ((x>>19) & 0x00000001) +#define GET_SYNC_IDLE1(x) ((x>>20) & 0x00000001) +#define GET_INIT_DONE1(x) ((x>>21) & 0x00000001) +#define GET_SYS_IDLE1(x) ((x>>22) & 0x00000001) +#define GET_WACS1_FIFO_FILLCNT(x) ((x>>24) & 0x0000000f) +#define GET_WACS1_FIFO_FREECNT(x) ((x>>28) & 0x0000000f) +#define GET_WACS2_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS2_ADR(x) ((x>>16) & 0x00007fff) +#define GET_WACS2_WRITE(x) ((x>>31) & 0x00000001) +#define GET_WACS2_RDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS2_FSM(x) ((x>>16) & 0x00000007) +#define GET_WACS2_REQ(x) ((x>>19) & 0x00000001) +#define GET_SYNC_IDLE2(x) ((x>>20) & 0x00000001) +#define GET_INIT_DONE2(x) ((x>>21) & 0x00000001) +#define GET_SYS_IDLE2(x) ((x>>22) & 0x00000001) +#define GET_WACS2_FIFO_FILLCNT(x) ((x>>24) & 0x0000000f) +#define GET_WACS2_FIFO_FREECNT(x) ((x>>28) & 0x0000000f) +#define GET_WACS3_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS3_ADR(x) ((x>>16) & 0x00007fff) +#define GET_WACS3_WRITE(x) ((x>>31) & 0x00000001) +#define GET_WACS3_RDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS3_FSM(x) ((x>>16) & 0x00000007) +#define GET_WACS3_REQ(x) ((x>>19) & 0x00000001) +#define GET_SYNC_IDLE3(x) ((x>>20) & 0x00000001) +#define GET_INIT_DONE3(x) ((x>>21) & 0x00000001) +#define GET_SYS_IDLE3(x) ((x>>22) & 0x00000001) +#define GET_WACS3_FIFO_FILLCNT(x) ((x>>24) & 0x0000000f) +#define GET_WACS3_FIFO_FREECNT(x) ((x>>28) & 0x0000000f) +#define GET_PWRAP_GPS_ACK(x) ((x>>0) & 0x00000001) +#define GET_GPS_PWRAP_REQ(x) ((x>>1) & 0x00000001) +#define GET_GPSINF_DLE_CNT(x) ((x>>4) & 0x00000003) +#define GET_GPSINF_ALE_CNT(x) ((x>>6) & 0x00000003) +#define GET_GPS_INF_FSM(x) ((x>>8) & 0x00000007) +#define GET_PWRAP_GPS_WDATA(x) ((x>>17) & 0x00007fff) +#define GET_PWRAP_MD_ADC_TEMP_DATA(x) ((x>>16) & 0x0000ffff) + +/* Macros */ +#define ENABLE 1 +#define DISABLE 0 +#define DISABLE_ALL 0 + +/* HIPRIO_ARB */ +/* +[13]: WACSP2P (SCP SW) (RESERVED) +[12]: WACS1 (MD SW1) +[11]: WACS2 (AP SW) +[10]: GPSINF +[9]: STAUPD +[8]: MD_ADCINF +[7]: DCXO_NFCINF +[6]: DCXO_CONNINF +[5]: WACS3(C2K SW) +[4]: DVFSINF (SPMINF) +[3]: WACS0 (MD SW0) +[2]: MD_DVFSINF +[1]: C2kINF +[0]: MDINF +*/ +#define WACSP2P (1 << 13) /* (SCP SW) (RESERVED) */ +#define WACS1 (1 << 12) /* (MD SW1) */ +#define WACS2 (1 << 11) /* (AP SW) */ +#define GPSINF (1 << 10) +#define STAUPD (1 << 9) +#define MD_ADCINF (1 << 8) +#define DCXO_NFCINF (1 << 7) +#define DCXO_CONNINF (1 << 6) +#define WACS3 (1 << 5) /* (C2K SW) */ +#define DVFSINF (1 << 4) /* (SPMINF) */ +#define WACS0 (1 << 3) /* (MD SW0) */ +#define MD_DVFSINF (1 << 2) +#define C2KINF (1 << 1) +#define MDINF (1 << 0) + +/* MUX SEL */ +#define WRAPPER_MODE 0 +#define MANUAL_MODE 1 + +/* OP TYPE */ +#define OP_TYPE_CK 0 /* for MT6323 */ +#define OP_TYPE_CSL 1 /* for MT6320 */ +#define MSB 1 /* for MT6323 */ +#define LSB 0 /* for MT6320 */ + +/* SIG mode */ +#define CHECK_CRC 0 +#define CHECK_SIG 1 + + + +/* macro for staupd sta fsm */ +#define STAUPD_FSM_IDLE (0x00) +#define STAUPD_FSM_REQ (0x02) +#define STAUPD_FSM_WFDLE (0x04) /* wait for dle,wait for read data done, */ + +/* macro for WRAP_STA FSM */ +/* #define WRAP_STA_FSM_IDLE (0x00) */ +/* #define WRAP_STA_IDLE (0x00) */ + +/* macro for MAN_RDATA FSM */ +#define MAN_FSM_NO_REQ (0x00) +#define MAN_FSM_IDLE (0x00) +#define MAN_FSM_REQ (0x02) +#define MAN_FSM_WFDLE (0x04) /* wait for dle,wait for read data done, */ +#define MAN_FSM_WFVLDCLR (0x06) + +/* macro for WACS_FSM */ +#define WACS_FSM_IDLE (0x00) +#define WACS_FSM_REQ (0x02) +#define WACS_FSM_WFDLE (0x04) /* wait for dle,wait for read data done, */ +#define WACS_FSM_WFVLDCLR (0x06) /* finish read data , wait for valid flag clearing */ +#define WACS_INIT_DONE (0x01) +#define WACS_SYNC_IDLE (0x01) +#define WACS_SYNC_BUSY (0x00) + +/* -----macro for dewrapper defaule value------------------------------------------------------- */ +#ifdef SLV_6351 +#define MT6351_DEFAULT_VALUE_READ_TEST 0x5aa5 +#define MT6351_WRITE_TEST_VALUE 0xa55a +#else +#define PMIC_DEFAULT_VALUE_READ_TEST 0x5aa5 +#define PMIC_WRITE_TEST_VALUE 0xa55a +#endif + +/* -----macro for manual commnd -------------------------------------------------------- */ +#define OP_WR (0x1) +#define OP_RD (0x0) + +#define OP_CSH (0x0) +#define OP_CSL (0x1) +#define OP_CK (0x2) + +#define OP_OUTS (0x8) +#define OP_OUTD (0x9) +#define OP_OUTQ (0xA) + +#define OP_INS (0xC) +#define OP_INS0 (0xD) +#define OP_IND (0xE) +#define OP_INQ (0xF) + +#define OP_OS2IS (0x10) +#define OP_OS2ID (0x11) +#define OP_OS2IQ (0x12) +#define OP_OD2IS (0x13) +#define OP_OD2ID (0x14) +#define OP_OD2IQ (0x15) +#define OP_OQ2IS (0x16) +#define OP_OQ2ID (0x17) +#define OP_OQ2IQ (0x18) + +#define OP_OSNIS (0x19) +#define OP_ODNID (0x1A) + +#define E_PWR_INVALID_ARG 1 +#define E_PWR_INVALID_RW 2 +#define E_PWR_INVALID_ADDR 3 +#define E_PWR_INVALID_WDAT 4 +#define E_PWR_INVALID_OP_MANUAL 5 +#define E_PWR_NOT_IDLE_STATE 6 +#define E_PWR_NOT_INIT_DONE 7 +#define E_PWR_NOT_INIT_DONE_READ 8 +#define E_PWR_WAIT_IDLE_TIMEOUT 9 +#define E_PWR_WAIT_IDLE_TIMEOUT_READ 10 +#define E_PWR_INIT_SIDLY_FAIL 11 +#define E_PWR_RESET_TIMEOUT 12 +#define E_PWR_TIMEOUT 13 + +#define E_PWR_INIT_RESET_SPI 20 +#define E_PWR_INIT_SIDLY 21 +#define E_PWR_INIT_REG_CLOCK 22 +#define E_PWR_INIT_ENABLE_PMIC 23 +#define E_PWR_INIT_DIO 24 +#define E_PWR_INIT_CIPHER 25 +#define E_PWR_INIT_WRITE_TEST 26 +#define E_PWR_INIT_ENABLE_CRC 27 +#define E_PWR_INIT_ENABLE_DEWRAP 28 + +#define E_PWR_READ_TEST_FAIL 30 +#define E_PWR_WRITE_TEST_FAIL 31 +#define E_PWR_SWITCH_DIO 32 + +/* -----macro for read/write register -------------------------------------------------------- */ +#define WRAP_RD32(addr) __raw_readl((void *)addr) +#define WRAP_WR32(addr, val) mt_reg_sync_writel((val), ((void *)addr)) + +#define WRAP_SET_BIT(BS, REG) mt_reg_sync_writel((__raw_readl((void *)REG) | (U32)(BS)), ((void *)REG)) +#define WRAP_CLR_BIT(BS, REG) mt_reg_sync_writel((__raw_readl((void *)REG) & (~(U32)(BS))), ((void *)REG)) + + +#endif /* __PWRAP_HAL_H__ */ diff --git a/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal_d2.h b/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal_d2.h new file mode 100644 index 0000000000000000000000000000000000000000..3d06cc17aa7353bb0f87c85905223ed3d5f89d2f --- /dev/null +++ b/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal_d2.h @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef __PMIC_WRAP_REGS_2_H__ +#define __PMIC_WRAP_REGS_2_H__ + + +#define PMIC_WRAP_MUX_SEL ((unsigned int *)(PMIC_WRAP_BASE+0x0)) +#define PMIC_WRAP_WRAP_EN ((unsigned int *)(PMIC_WRAP_BASE+0x4)) +#define PMIC_WRAP_DIO_EN ((unsigned int *)(PMIC_WRAP_BASE+0x8)) +#define PMIC_WRAP_SIDLY ((unsigned int *)(PMIC_WRAP_BASE+0xC)) +#define PMIC_WRAP_RDDMY ((unsigned int *)(PMIC_WRAP_BASE+0x10)) +#define PMIC_WRAP_SI_CK_CON ((unsigned int *)(PMIC_WRAP_BASE+0x14)) +#define PMIC_WRAP_CSHEXT_WRITE ((unsigned int *)(PMIC_WRAP_BASE+0x18)) +#define PMIC_WRAP_CSHEXT_READ ((unsigned int *)(PMIC_WRAP_BASE+0x1C)) +#define PMIC_WRAP_CSLEXT_START ((unsigned int *)(PMIC_WRAP_BASE+0x20)) +#define PMIC_WRAP_CSLEXT_END ((unsigned int *)(PMIC_WRAP_BASE+0x24)) +#define PMIC_WRAP_STAUPD_PRD ((unsigned int *)(PMIC_WRAP_BASE+0x28)) +#define PMIC_WRAP_STAUPD_GRPEN ((unsigned int *)(PMIC_WRAP_BASE+0x2C)) +#define PMIC_WRAP_EINT_STA0_ADR ((unsigned int *)(PMIC_WRAP_BASE+0x30)) +#define PMIC_WRAP_EINT_STA1_ADR ((unsigned int *)(PMIC_WRAP_BASE+0x34)) +#define PMIC_WRAP_EINT_STA ((unsigned int *)(PMIC_WRAP_BASE+0x38)) +#define PMIC_WRAP_EINT_CLR ((unsigned int *)(PMIC_WRAP_BASE+0x3C)) +#define PMIC_WRAP_STAUPD_MAN_TRIG ((unsigned int *)(PMIC_WRAP_BASE+0x40)) +#define PMIC_WRAP_STAUPD_STA ((unsigned int *)(PMIC_WRAP_BASE+0x44)) +#define PMIC_WRAP_WRAP_STA ((unsigned int *)(PMIC_WRAP_BASE+0x48)) +#define PMIC_WRAP_HARB_INIT ((unsigned int *)(PMIC_WRAP_BASE+0x4C)) +#define PMIC_WRAP_HARB_HPRIO ((unsigned int *)(PMIC_WRAP_BASE+0x50)) +#define PMIC_WRAP_HIPRIO_ARB_EN ((unsigned int *)(PMIC_WRAP_BASE+0x54)) +#define PMIC_WRAP_HARB_STA0 ((unsigned int *)(PMIC_WRAP_BASE+0x58)) +#define PMIC_WRAP_HARB_STA1 ((unsigned int *)(PMIC_WRAP_BASE+0x5C)) +#define PMIC_WRAP_MAN_EN ((unsigned int *)(PMIC_WRAP_BASE+0x60)) +#define PMIC_WRAP_MAN_CMD ((unsigned int *)(PMIC_WRAP_BASE+0x64)) +#define PMIC_WRAP_MAN_RDATA ((unsigned int *)(PMIC_WRAP_BASE+0x68)) +#define PMIC_WRAP_MAN_VLDCLR ((unsigned int *)(PMIC_WRAP_BASE+0x6C)) +#define PMIC_WRAP_WACS0_EN ((unsigned int *)(PMIC_WRAP_BASE+0x70)) +#define PMIC_WRAP_INIT_DONE0 ((unsigned int *)(PMIC_WRAP_BASE+0x74)) +#define PMIC_WRAP_WACS0_CMD ((unsigned int *)(PMIC_WRAP_BASE+0x78)) +#define PMIC_WRAP_WACS0_RDATA ((unsigned int *)(PMIC_WRAP_BASE+0x7C)) +#define PMIC_WRAP_WACS0_VLDCLR ((unsigned int *)(PMIC_WRAP_BASE+0x80)) +#define PMIC_WRAP_WACS1_EN ((unsigned int *)(PMIC_WRAP_BASE+0x84)) +#define PMIC_WRAP_INIT_DONE1 ((unsigned int *)(PMIC_WRAP_BASE+0x88)) +#define PMIC_WRAP_WACS1_CMD ((unsigned int *)(PMIC_WRAP_BASE+0x8C)) +#define PMIC_WRAP_WACS1_RDATA ((unsigned int *)(PMIC_WRAP_BASE+0x90)) +#define PMIC_WRAP_WACS1_VLDCLR ((unsigned int *)(PMIC_WRAP_BASE+0x94)) +#define PMIC_WRAP_WACS2_EN ((unsigned int *)(PMIC_WRAP_BASE+0x98)) +#define PMIC_WRAP_INIT_DONE2 ((unsigned int *)(PMIC_WRAP_BASE+0x9C)) +#define PMIC_WRAP_WACS2_CMD ((unsigned int *)(PMIC_WRAP_BASE+0xA0)) +#define PMIC_WRAP_WACS2_RDATA ((unsigned int *)(PMIC_WRAP_BASE+0xA4)) +#define PMIC_WRAP_WACS2_VLDCLR ((unsigned int *)(PMIC_WRAP_BASE+0xA8)) +#define PMIC_WRAP_INT_EN ((unsigned int *)(PMIC_WRAP_BASE+0xAC)) +#define PMIC_WRAP_INT_FLG_RAW ((unsigned int *)(PMIC_WRAP_BASE+0xB0)) +#define PMIC_WRAP_INT_FLG ((unsigned int *)(PMIC_WRAP_BASE+0xB4)) +#define PMIC_WRAP_INT_CLR ((unsigned int *)(PMIC_WRAP_BASE+0xB8)) +#define PMIC_WRAP_SIG_ADR ((unsigned int *)(PMIC_WRAP_BASE+0xBC)) +#define PMIC_WRAP_SIG_MODE ((unsigned int *)(PMIC_WRAP_BASE+0xC0)) +#define PMIC_WRAP_SIG_VALUE ((unsigned int *)(PMIC_WRAP_BASE+0xC4)) +#define PMIC_WRAP_SIG_ERRVAL ((unsigned int *)(PMIC_WRAP_BASE+0xC8)) +#define PMIC_WRAP_CRC_EN ((unsigned int *)(PMIC_WRAP_BASE+0xCC)) +#define PMIC_WRAP_TIMER_EN ((unsigned int *)(PMIC_WRAP_BASE+0xD0)) +#define PMIC_WRAP_TIMER_STA ((unsigned int *)(PMIC_WRAP_BASE+0xD4)) +#define PMIC_WRAP_WDT_UNIT ((unsigned int *)(PMIC_WRAP_BASE+0xD8)) +#define PMIC_WRAP_WDT_SRC_EN ((unsigned int *)(PMIC_WRAP_BASE+0xDC)) +#define PMIC_WRAP_WDT_FLG ((unsigned int *)(PMIC_WRAP_BASE+0xE0)) +#define PMIC_WRAP_DEBUG_INT_SEL ((unsigned int *)(PMIC_WRAP_BASE+0xE4)) +#define PMIC_WRAP_DVFS_ADR0 ((unsigned int *)(PMIC_WRAP_BASE+0xE8)) +#define PMIC_WRAP_DVFS_WDATA0 ((unsigned int *)(PMIC_WRAP_BASE+0xEC)) +#define PMIC_WRAP_DVFS_ADR1 ((unsigned int *)(PMIC_WRAP_BASE+0xF0)) +#define PMIC_WRAP_DVFS_WDATA1 ((unsigned int *)(PMIC_WRAP_BASE+0xF4)) +#define PMIC_WRAP_DVFS_ADR2 ((unsigned int *)(PMIC_WRAP_BASE+0xF8)) +#define PMIC_WRAP_DVFS_WDATA2 ((unsigned int *)(PMIC_WRAP_BASE+0xFC)) +#define PMIC_WRAP_DVFS_ADR3 ((unsigned int *)(PMIC_WRAP_BASE+0x100)) +#define PMIC_WRAP_DVFS_WDATA3 ((unsigned int *)(PMIC_WRAP_BASE+0x104)) +#define PMIC_WRAP_DVFS_ADR4 ((unsigned int *)(PMIC_WRAP_BASE+0x108)) +#define PMIC_WRAP_DVFS_WDATA4 ((unsigned int *)(PMIC_WRAP_BASE+0x10C)) +#define PMIC_WRAP_DVFS_ADR5 ((unsigned int *)(PMIC_WRAP_BASE+0x110)) +#define PMIC_WRAP_DVFS_WDATA5 ((unsigned int *)(PMIC_WRAP_BASE+0x114)) +#define PMIC_WRAP_DVFS_ADR6 ((unsigned int *)(PMIC_WRAP_BASE+0x118)) +#define PMIC_WRAP_DVFS_WDATA6 ((unsigned int *)(PMIC_WRAP_BASE+0x11C)) +#define PMIC_WRAP_DVFS_ADR7 ((unsigned int *)(PMIC_WRAP_BASE+0x120)) +#define PMIC_WRAP_DVFS_WDATA7 ((unsigned int *)(PMIC_WRAP_BASE+0x124)) +#define PMIC_WRAP_DVFS_ADR8 ((unsigned int *)(PMIC_WRAP_BASE+0x128)) +#define PMIC_WRAP_DVFS_WDATA8 ((unsigned int *)(PMIC_WRAP_BASE+0x12C)) +#define PMIC_WRAP_DVFS_ADR9 ((unsigned int *)(PMIC_WRAP_BASE+0x130)) +#define PMIC_WRAP_DVFS_WDATA9 ((unsigned int *)(PMIC_WRAP_BASE+0x134)) +#define PMIC_WRAP_DVFS_ADR10 ((unsigned int *)(PMIC_WRAP_BASE+0x138)) +#define PMIC_WRAP_DVFS_WDATA10 ((unsigned int *)(PMIC_WRAP_BASE+0x13C)) +#define PMIC_WRAP_DVFS_ADR11 ((unsigned int *)(PMIC_WRAP_BASE+0x140)) +#define PMIC_WRAP_DVFS_WDATA11 ((unsigned int *)(PMIC_WRAP_BASE+0x144)) +#define PMIC_WRAP_DVFS_ADR12 ((unsigned int *)(PMIC_WRAP_BASE+0x148)) +#define PMIC_WRAP_DVFS_WDATA12 ((unsigned int *)(PMIC_WRAP_BASE+0x14C)) +#define PMIC_WRAP_DVFS_ADR13 ((unsigned int *)(PMIC_WRAP_BASE+0x150)) +#define PMIC_WRAP_DVFS_WDATA13 ((unsigned int *)(PMIC_WRAP_BASE+0x154)) +#define PMIC_WRAP_DVFS_ADR14 ((unsigned int *)(PMIC_WRAP_BASE+0x158)) +#define PMIC_WRAP_DVFS_WDATA14 ((unsigned int *)(PMIC_WRAP_BASE+0x15C)) +#define PMIC_WRAP_DVFS_ADR15 ((unsigned int *)(PMIC_WRAP_BASE+0x160)) +#define PMIC_WRAP_DVFS_WDATA15 ((unsigned int *)(PMIC_WRAP_BASE+0x164)) +#define PMIC_WRAP_SPMINF_STA ((unsigned int *)(PMIC_WRAP_BASE+0x168)) +#define PMIC_WRAP_CIPHER_KEY_SEL ((unsigned int *)(PMIC_WRAP_BASE+0x16C)) +#define PMIC_WRAP_CIPHER_IV_SEL ((unsigned int *)(PMIC_WRAP_BASE+0x170)) +#define PMIC_WRAP_CIPHER_EN ((unsigned int *)(PMIC_WRAP_BASE+0x174)) +#define PMIC_WRAP_CIPHER_RDY ((unsigned int *)(PMIC_WRAP_BASE+0x178)) +#define PMIC_WRAP_CIPHER_MODE ((unsigned int *)(PMIC_WRAP_BASE+0x17C)) +#define PMIC_WRAP_CIPHER_SWRST ((unsigned int *)(PMIC_WRAP_BASE+0x180)) +#define PMIC_WRAP_DCM_EN ((unsigned int *)(PMIC_WRAP_BASE+0x184)) +#define PMIC_WRAP_DCM_DBC_PRD ((unsigned int *)(PMIC_WRAP_BASE+0x188)) +#define PMIC_WRAP_EXT_CK ((unsigned int *)(PMIC_WRAP_BASE+0x18C)) +#define PMIC_WRAP_ADC_CMD_ADDR ((unsigned int *)(PMIC_WRAP_BASE+0x190)) +#define PMIC_WRAP_PWRAP_ADC_CMD ((unsigned int *)(PMIC_WRAP_BASE+0x194)) +#define PMIC_WRAP_ADC_RDATA_ADDR ((unsigned int *)(PMIC_WRAP_BASE+0x198)) +#define PMIC_WRAP_GPS_STA ((unsigned int *)(PMIC_WRAP_BASE+0x19C)) +#define PMIC_WRAP_SWRST ((unsigned int *)(PMIC_WRAP_BASE+0x1A0)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR_LATEST ((unsigned int *)(PMIC_WRAP_BASE+0x1A4)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR_WP ((unsigned int *)(PMIC_WRAP_BASE+0x1A8)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR0 ((unsigned int *)(PMIC_WRAP_BASE+0x1AC)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR1 ((unsigned int *)(PMIC_WRAP_BASE+0x1B0)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR2 ((unsigned int *)(PMIC_WRAP_BASE+0x1B4)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR3 ((unsigned int *)(PMIC_WRAP_BASE+0x1B8)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR4 ((unsigned int *)(PMIC_WRAP_BASE+0x1BC)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR5 ((unsigned int *)(PMIC_WRAP_BASE+0x1C0)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR6 ((unsigned int *)(PMIC_WRAP_BASE+0x1C4)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR7 ((unsigned int *)(PMIC_WRAP_BASE+0x1C8)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR8 ((unsigned int *)(PMIC_WRAP_BASE+0x1CC)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR9 ((unsigned int *)(PMIC_WRAP_BASE+0x1D0)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR10 ((unsigned int *)(PMIC_WRAP_BASE+0x1D4)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR11 ((unsigned int *)(PMIC_WRAP_BASE+0x1D8)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR12 ((unsigned int *)(PMIC_WRAP_BASE+0x1DC)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR13 ((unsigned int *)(PMIC_WRAP_BASE+0x1E0)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR14 ((unsigned int *)(PMIC_WRAP_BASE+0x1E4)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR15 ((unsigned int *)(PMIC_WRAP_BASE+0x1E8)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR16 ((unsigned int *)(PMIC_WRAP_BASE+0x1EC)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR17 ((unsigned int *)(PMIC_WRAP_BASE+0x1F0)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR18 ((unsigned int *)(PMIC_WRAP_BASE+0x1F4)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR19 ((unsigned int *)(PMIC_WRAP_BASE+0x1F8)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR20 ((unsigned int *)(PMIC_WRAP_BASE+0x1FC)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR21 ((unsigned int *)(PMIC_WRAP_BASE+0x200)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR22 ((unsigned int *)(PMIC_WRAP_BASE+0x204)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR23 ((unsigned int *)(PMIC_WRAP_BASE+0x208)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR24 ((unsigned int *)(PMIC_WRAP_BASE+0x20C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR25 ((unsigned int *)(PMIC_WRAP_BASE+0x210)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR26 ((unsigned int *)(PMIC_WRAP_BASE+0x214)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR27 ((unsigned int *)(PMIC_WRAP_BASE+0x218)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR28 ((unsigned int *)(PMIC_WRAP_BASE+0x21C)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR29 ((unsigned int *)(PMIC_WRAP_BASE+0x220)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR30 ((unsigned int *)(PMIC_WRAP_BASE+0x224)) +#define PMIC_WRAP_MD_ADC_RDATA_ADDR31 ((unsigned int *)(PMIC_WRAP_BASE+0x228)) +#define PMIC_WRAP_MD_ADC_STA0 ((unsigned int *)(PMIC_WRAP_BASE+0x22C)) +#define PMIC_WRAP_MD_ADC_STA1 ((unsigned int *)(PMIC_WRAP_BASE+0x230)) +#define PMIC_WRAP_MD_ADC_STA2 ((unsigned int *)(PMIC_WRAP_BASE+0x234)) + + + +/*-----macro for wrapper regsister------------------------*/ +#define GET_STAUPD_DLE_CNT(x) ((x>>0) & 0x00000007) +#define GET_STAUPD_ALE_CNT(x) ((x>>3) & 0x00000007) +#define GET_STAUPD_FSM(x) ((x>>6) & 0x00000007) +#define GET_WRAP_CH_DLE_RESTCNT(x) ((x>>0) & 0x00000007) +#define GET_WRAP_CH_ALE_RESTCNT(x) ((x>>3) & 0x00000003) +#define GET_WRAP_AG_DLE_RESTCNT(x) ((x>>5) & 0x00000003) +#define GET_WRAP_CH_W(x) ((x>>7) & 0x00000001) +#define GET_WRAP_CH_REQ(x) ((x>>8) & 0x00000001) +#define GET_AG_WRAP_W(x) ((x>>9) & 0x00000001) +#define GET_AG_WRAP_REQ(x) ((x>>10) & 0x00000001) +#define GET_WRAP_FSM(x) ((x>>11) & 0x0000000f) +#define GET_HARB_WRAP_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_HARB_WRAP_ADR(x) ((x>>16) & 0x00007fff) +#define GET_HARB_WRAP_REQ(x) ((x>>31) & 0x00000001) +#define GET_HARB_DLE_EMPTY(x) ((x>>0) & 0x00000001) +#define GET_HARB_DLE_FULL(x) ((x>>1) & 0x00000001) +#define GET_HARB_VLD(x) ((x>>2) & 0x00000001) +#define GET_HARB_DLE_OWN(x) ((x>>3) & 0x00000007) +#define GET_HARB_OWN(x) ((x>>6) & 0x00000007) +#define GET_HARB_DLE_RESTCNT(x) ((x>>9) & 0x00000007) +#define GET_AG_HARB_REQ(x) ((x>>12) & 0x000000ff) +#define GET_HARB_WRAP_W(x) ((x>>20) & 0x00000001) +#define GET_HARB_WRAP_REQ0(x) ((x>>21) & 0x00000001) +#define GET_SPI_WDATA(x) ((x>>0) & 0x000000ff) +#define GET_SPI_OP(x) ((x>>8) & 0x0000001f) +#define GET_SPI_W(x) ((x>>13) & 0x00000001) +#define GET_MAN_RDATA(x) ((x>>0) & 0x000000ff) +#define GET_MAN_FSM(x) ((x>>8) & 0x00000007) +#define GET_MAN_REQ(x) ((x>>11) & 0x00000001) +#define GET_WACS0_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS0_ADR(x) ((x>>16) & 0x00007fff) +#define GET_WACS0_WRITE(x) ((x>>31) & 0x00000001) +#define GET_WACS0_RDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS0_FSM(x) ((x>>16) & 0x00000007) +#define GET_WACS0_REQ(x) ((x>>19) & 0x00000001) +#define GET_SYNC_IDLE0(x) ((x>>20) & 0x00000001) +#define GET_INIT_DONE0(x) ((x>>21) & 0x00000001) +#define GET_SYS_IDLE0(x) ((x>>22) & 0x00000001) +#define GET_WACS0_FIFO_FILLCNT(x) ((x>>24) & 0x0000000f) +#define GET_WACS0_FIFO_FREECNT(x) ((x>>28) & 0x0000000f) +#define GET_WACS1_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS1_ADR(x) ((x>>16) & 0x00007fff) +#define GET_WACS1_WRITE(x) ((x>>31) & 0x00000001) +#define GET_WACS1_RDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS1_FSM(x) ((x>>16) & 0x00000007) +#define GET_WACS1_REQ(x) ((x>>19) & 0x00000001) +#define GET_SYNC_IDLE1(x) ((x>>20) & 0x00000001) +#define GET_INIT_DONE1(x) ((x>>21) & 0x00000001) +#define GET_SYS_IDLE1(x) ((x>>22) & 0x00000001) +#define GET_WACS1_FIFO_FILLCNT(x) ((x>>24) & 0x0000000f) +#define GET_WACS1_FIFO_FREECNT(x) ((x>>28) & 0x0000000f) +#define GET_WACS2_WDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS2_ADR(x) ((x>>16) & 0x00007fff) +#define GET_WACS2_WRITE(x) ((x>>31) & 0x00000001) +#define GET_WACS2_RDATA(x) ((x>>0) & 0x0000ffff) +#define GET_WACS2_FSM(x) ((x>>16) & 0x00000007) +#define GET_WACS2_REQ(x) ((x>>19) & 0x00000001) +#define GET_SYNC_IDLE2(x) ((x>>20) & 0x00000001) +#define GET_INIT_DONE2(x) ((x>>21) & 0x00000001) +#define GET_SYS_IDLE2(x) ((x>>22) & 0x00000001) +#define GET_WACS2_FIFO_FILLCNT(x) ((x>>24) & 0x0000000f) +#define GET_WACS2_FIFO_FREECNT(x) ((x>>28) & 0x0000000f) +#define GET_PWRAP_GPS_ACK(x) ((x>>0) & 0x00000001) +#define GET_GPS_PWRAP_REQ(x) ((x>>1) & 0x00000001) +#define GET_GPSINF_DLE_CNT(x) ((x>>4) & 0x00000003) +#define GET_GPSINF_ALE_CNT(x) ((x>>6) & 0x00000003) +#define GET_GPS_INF_FSM(x) ((x>>8) & 0x00000007) +#define GET_PWRAP_GPS_WDATA(x) ((x>>17) & 0x00007fff) +#define GET_PWRAP_MD_ADC_NORM_DATA(x) ((x>>0) & 0x0000ffff) +#define GET_PWRAP_MD_ADC_INIT_DATA(x) ((x>>16) & 0x0000ffff) +#define GET_BUF_MD_ADC_RDATA(x) ((x>>0) & 0x0000ffff) +#define GET_MD_ADC_BUF_WDATA(x) ((x>>16) & 0x0000ffff) + +#endif + diff --git a/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal_v1.c b/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal_v1.c new file mode 100644 index 0000000000000000000000000000000000000000..7a36ec26d06f639acb5e4ca5519e82ce99542d33 --- /dev/null +++ b/drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal_v1.c @@ -0,0 +1,1668 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/****************************************************************************** + * pwrap_hal_v1.c - Linux pmic_wrapper Driver,hardware_dependent driver + * + * + * DESCRIPTION: + * This file provid the other drivers PMIC wrapper relative functions + * + ******************************************************************************/ +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include +/* #include */ +#include "pwrap_hal.h" + +#define PMIC_WRAP_DEVICE "pmic_wrap" + +/*-----start-- global variable-----------------------------------------------*/ +#ifdef CONFIG_OF +void __iomem *pwrap_base; +static void __iomem *topckgen_reg_base; +static void __iomem *infracfg_ao_reg_base; +static void __iomem *gpio_reg_base; +static void __iomem *sleep_reg_base; +#endif + +static struct mt_pmic_wrap_driver *mt_wrp; + +static DEFINE_SPINLOCK(wrp_lock); +static DEFINE_SPINLOCK(wrp_lock_isr); + + +/*-----start--Internal API---------------------------------------------------*/ +static s32 _pwrap_init_dio(u32 dio_en); +static s32 _pwrap_init_cipher(void); +static s32 _pwrap_init_reg_clock(u32 regck_sel); +static s32 _pwrap_wacs2_nochk(u32 write, u32 adr, u32 wdata, u32 *rdata); +static s32 _pwrap_reset_spislv(void); +/*-----end --Internal API---------------------------------------------------*/ + +#ifdef CONFIG_OF +static int pwrap_of_iomap(void); +static void pwrap_of_iounmap(void); +#endif + + +#ifdef PMIC_WRAP_NO_PMIC +/*-pwrap debug--------------------------------------------------------------------------*/ +void pwrap_dump_all_register(void) +{ +} + +/*********************************************************************************/ +/* extern API for PMIC driver, INT related control, this INT is for PMIC chip to AP */ +/*********************************************************************************/ +u32 mt_pmic_wrap_eint_status(void) +{ + PWRAPLOG("[PMIC2]first of all PMIC_WRAP_STAUPD_GRPEN=0x%x\n", + WRAP_RD32(PMIC_WRAP_STAUPD_GRPEN)); + PWRAPLOG("[PMIC2]first of all PMIC_WRAP_EINT_STA=0x%x\n", WRAP_RD32(PMIC_WRAP_EINT_STA)); + return WRAP_RD32(PMIC_WRAP_EINT_STA); +} + +void mt_pmic_wrap_eint_clr(int offset) +{ + if ((offset < 0) || (offset > 3)) + PWRAPERR("clear EINT flag error, only 0-3 bit\n"); + else + WRAP_WR32(PMIC_WRAP_EINT_CLR, (1 << offset)); + +} +/* -------------------------------------------------------- */ +/* Function : pwrap_wacs2_hal() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 pwrap_wacs2_hal(u32 write, u32 adr, u32 wdata, u32 *rdata) +{ + PWRAPERR("there is no PMIC real chip,PMIC_WRAP do Nothing\n"); + return 0; +} + +/* + *pmic_wrap init,init wrap interface + * + */ +s32 pwrap_init(void) +{ + PWRAPERR("There is no PMIC real chip, PMIC_WRAP do Nothing.\n"); + return 0; +} + +s32 pwrap_read_nochk(u32 adr, u32 *rdata) +{ + return pwrap_wacs2_hal(0, adr, 0, rdata); +} + +s32 pwrap_write_nochk(u32 adr, u32 wdata) +{ + return pwrap_wacs2_hal(1, adr, wdata, 0); +} + +/*Interrupt handler function*/ +static irqreturn_t mt_pmic_wrap_irq(int irqno, void *dev_id) +{ + unsigned long flags = 0; + + PWRAPFUC(); + PWRAPREG("dump pwrap register\n"); + spin_lock_irqsave(&wrp_lock, flags); + /* *----------------------------------------------------------------------- */ + pwrap_dump_all_register(); + /* raise the priority of WACS2 for AP */ + WRAP_WR32(PMIC_WRAP_HARB_HPRIO, WACS2); + + /* *----------------------------------------------------------------------- */ + /* clear interrupt flag */ + WRAP_WR32(PMIC_WRAP_INT0_CLR, 0xffffffff); + WRAP_WR32(PMIC_WRAP_INT1_CLR, 0xffffffff); + PWRAPREG("INT flag 0x%x\n", WRAP_RD32(PMIC_WRAP_INT0_FLG_RAW)); + PWRAPREG("INT flag 0x%x\n", WRAP_RD32(PMIC_WRAP_INT1_FLG_RAW)); + /* BUG_ON(1); */ + spin_unlock_irqrestore(&wrp_lock, flags); + return IRQ_HANDLED; +} + +static u32 pwrap_read_test(void) +{ + return 0; +} + +static u32 pwrap_write_test(void) +{ + return 0; +} + +static void pwrap_ut(u32 ut_test) +{ + switch (ut_test) { + case 1: + /* pwrap_wacs2_para_test(); */ + pwrap_write_test(); + break; + case 2: + /* pwrap_wacs2_para_test(); */ + pwrap_read_test(); + break; + + default: + PWRAPREG("default test.\n"); + break; + } +} + +/*---------------------------------------------------------------------------*/ +static s32 mt_pwrap_show_hal(char *buf) +{ + PWRAPFUC(); + return snprintf(buf, PAGE_SIZE, "%s\n", "no implement"); +} + +/*---------------------------------------------------------------------------*/ +static s32 mt_pwrap_store_hal(const char *buf, size_t count) +{ + u32 reg_value = 0; + u32 reg_addr = 0; + u32 return_value = 0; + u32 ut_test = 0; + + if (!strncmp(buf, "-h", 2)) { + PWRAPREG + ("PWRAP debug: [-dump_reg][-trace_wacs2][-init][-rdpmic][-wrpmic][-readtest][-writetest]\n"); + PWRAPREG("PWRAP UT: [1][2]\n"); + } + /* ----------pwrap debug---------- */ + else if (!strncmp(buf, "-dump_reg", 9)) { + pwrap_dump_all_register(); + } else if (!strncmp(buf, "-trace_wacs2", 12)) { + /* pwrap_trace_wacs2(); */ + } else if (!strncmp(buf, "-init", 5)) { + return_value = pwrap_init(); + if (return_value == 0) + PWRAPREG("pwrap_init pass,return_value=%d\n", return_value); + else + PWRAPREG("pwrap_init fail,return_value=%d\n", return_value); + } else if (!strncmp(buf, "-rdpmic", 7) && (1 == sscanf(buf + 7, "%x", ®_addr))) { + /* pwrap_read_reg_on_pmic(reg_addr); */ + } else if (!strncmp(buf, "-wrpmic", 7) + && (2 == sscanf(buf + 7, "%x %x", ®_addr, ®_value))) { + /* pwrap_write_reg_on_pmic(reg_addr,reg_value); */ + } else if (!strncmp(buf, "-readtest", 9)) { + pwrap_read_test(); + } else if (!strncmp(buf, "-writetest", 10)) { + pwrap_write_test(); + } + /* ----------pwrap UT---------- */ + else if (!strncmp(buf, "-ut", 3) && (1 == sscanf(buf + 3, "%d", &ut_test))) { + pwrap_ut(ut_test); + } else { + PWRAPREG("wrong parameter\n"); + } + return count; +} +/*---------------------------------------------------------------------------*/ +#else /* Else of #ifdef PMIC_WRAP_NO_PMIC */ +/*-pwrap debug--------------------------------------------------------------------------*/ +static inline void pwrap_dump_ap_register(void) +{ + u32 i = 0; + + PWRAPREG("dump pwrap register, base=0x%p\n", PMIC_WRAP_BASE); + PWRAPREG("address : 3 2 1 0 7 6 5 4 B A 9 8 F E D C\n"); + for (i = 0; i <= PMIC_WRAP_REG_RANGE; i += 4) { + PWRAPREG("offset 0x%.3x:0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", i * 4, + WRAP_RD32(PMIC_WRAP_BASE + (i * 4) + 0), + WRAP_RD32(PMIC_WRAP_BASE + (i * 4) + 0x4), + WRAP_RD32(PMIC_WRAP_BASE + (i * 4) + 0x8), + WRAP_RD32(PMIC_WRAP_BASE + (i * 4) + 0xC)); + } +} + +static inline void pwrap_dump_pmic_register(void) +{ +#if 0 + u32 i = 0; + u32 reg_addr = 0; + u32 reg_value = 0; + + PWRAPREG("dump dewrap register\n"); + for (i = 0; i <= 14; i++) { + reg_addr = (DEW_BASE + i * 4); + reg_value = pwrap_read_nochk(reg_addr, ®_value); + PWRAPREG("0x%x=0x%x\n", reg_addr, reg_value); + } +#endif +} + +void pwrap_dump_all_register(void) +{ + pwrap_dump_ap_register(); + pwrap_dump_pmic_register(); +} + +/****************************************************************************** +pmic wrapper timeout +******************************************************************************/ +#define PWRAP_TIMEOUT +/* use the same API name with kernel driver */ +/* however,the timeout API in preloader/lk use tick instead of ns */ +#ifdef PWRAP_TIMEOUT +static u64 _pwrap_get_current_time(void) +{ + return sched_clock(); /* /TODO: fix me */ +} + +static bool _pwrap_timeout_ns(u64 start_time_ns, u64 timeout_time_ns) +{ + u64 cur_time = 0; + u64 elapse_time = 0; + + /* get current tick */ + cur_time = _pwrap_get_current_time(); /* ns */ + + /* avoid timer over flow exiting in FPGA env */ + if (cur_time < start_time_ns) { + PWRAPERR("@@@@Timer overflow! start%lld cur timer%lld\n", start_time_ns, cur_time); + start_time_ns = cur_time; + timeout_time_ns = 10000 * 1000; /* 10000us */ + PWRAPERR("@@@@reset timer! start%lld setting%lld\n", start_time_ns, + timeout_time_ns); + } + + elapse_time = cur_time - start_time_ns; + + /* check if timeout */ + if (timeout_time_ns <= elapse_time) { + /* timeout */ + PWRAPERR + ("@@@@Timeout: elapse time%lld, start%lld , current%lld, setting timer%lld\n", + elapse_time, start_time_ns, cur_time, timeout_time_ns); + return true; + } + return false; +} + +static u64 _pwrap_time2ns(u64 time_us) +{ + return time_us * 1000; +} + +#else +static u64 _pwrap_get_current_time(void) +{ + return 0; +} + +static BOOL _pwrap_timeout_ns(u64 start_time_ns, u64 elapse_time) +{ + return false; +} + +static u64 _pwrap_time2ns(u64 time_us) +{ + return 0; +} + +#endif /* End of #ifdef PWRAP_TIMEOUT */ + +/* ##################################################################### */ +/* define macro and inline function (for do while loop) */ +/* ##################################################################### */ +typedef u32(*loop_condition_fp) (u32); /* define a function pointer */ + +static inline u32 wait_for_fsm_idle(u32 x) +{ + return GET_WACS0_FSM(x) != WACS_FSM_IDLE; +} + +static inline u32 wait_for_fsm_vldclr(u32 x) +{ + return GET_WACS0_FSM(x) != WACS_FSM_WFVLDCLR; +} + +static inline u32 wait_for_sync(u32 x) +{ + return GET_SYNC_IDLE0(x) != WACS_SYNC_IDLE; +} + +static inline u32 wait_for_idle_and_sync(u32 x) +{ + return (GET_WACS2_FSM(x) != WACS_FSM_IDLE) || (GET_SYNC_IDLE2(x) != WACS_SYNC_IDLE); +} + +static inline u32 wait_for_wrap_idle(u32 x) +{ + return (GET_WRAP_FSM(x) != 0x0) || (GET_WRAP_CH_DLE_RESTCNT(x) != 0x0); +} + +static inline u32 wait_for_wrap_state_idle(u32 x) +{ + return GET_WRAP_AG_DLE_RESTCNT(x) != 0; +} + +static inline u32 wait_for_man_idle_and_noreq(u32 x) +{ + return (GET_MAN_REQ(x) != MAN_FSM_NO_REQ) || (GET_MAN_FSM(x) != MAN_FSM_IDLE); +} + +static inline u32 wait_for_man_vldclr(u32 x) +{ + return GET_MAN_FSM(x) != MAN_FSM_WFVLDCLR; +} + +static inline u32 wait_for_cipher_ready(u32 x) +{ + return x != 3; +} + +static inline u32 wait_for_stdupd_idle(u32 x) +{ + return GET_STAUPD_FSM(x) != 0x0; +} + +static inline u32 wait_for_state_ready_init(loop_condition_fp fp, u32 timeout_us, + void *wacs_register, u32 *read_reg) +{ + u64 start_time_ns = 0, timeout_ns = 0; + u32 reg_rdata = 0x0; + + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(timeout_us); + do { + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) { + PWRAPLOG("wait_for_state_ready_init timeout when waiting for idle\n"); + return E_PWR_WAIT_IDLE_TIMEOUT; + } + reg_rdata = WRAP_RD32(wacs_register); + } while (fp(reg_rdata)); /* IDLE State */ + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +static inline u32 wait_for_state_idle_init(loop_condition_fp fp, u32 timeout_us, + void *wacs_register, void *wacs_vldclr_register, + u32 *read_reg) +{ + u64 start_time_ns = 0, timeout_ns = 0; + u32 reg_rdata; + + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(timeout_us); + do { + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) { + PWRAPLOG("wait_for_state_idle_init timeout when waiting for idle\n"); + pwrap_dump_ap_register(); + /* pwrap_trace_wacs2(); */ + /* BUG_ON(1); */ + return E_PWR_WAIT_IDLE_TIMEOUT; + } + reg_rdata = WRAP_RD32(wacs_register); + /* if last read command timeout,clear vldclr bit */ + /* read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;write:FSM_REQ-->idle */ + switch (GET_WACS0_FSM(reg_rdata)) { + case WACS_FSM_WFVLDCLR: + WRAP_WR32(wacs_vldclr_register, 1); + PWRAPLOG("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n"); + break; + case WACS_FSM_WFDLE: + PWRAPLOG("WACS_FSM = WACS_FSM_WFDLE\n"); + break; + case WACS_FSM_REQ: + PWRAPLOG("WACS_FSM = WACS_FSM_REQ\n"); + break; + default: + break; + } + } while (fp(reg_rdata)); /* IDLE State */ + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +static inline u32 wait_for_state_idle(loop_condition_fp fp, u32 timeout_us, void *wacs_register, + void *wacs_vldclr_register, u32 *read_reg) +{ + u64 start_time_ns = 0, timeout_ns = 0; + u64 loop_counter = 0; + u32 reg_rdata; + + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(timeout_us); + do { + loop_counter++; + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) { + PWRAPLOG + ("wait_for_state_idle timeout when waiting for idle, loop_counter = %lld\n", + loop_counter); + pwrap_dump_ap_register(); + /* pwrap_trace_wacs2(); */ + /* BUG_ON(1); */ + return E_PWR_WAIT_IDLE_TIMEOUT; + } + reg_rdata = WRAP_RD32(wacs_register); + if (GET_INIT_DONE0(reg_rdata) != WACS_INIT_DONE) { + PWRAPLOG("initialization isn't finished\n"); + return E_PWR_NOT_INIT_DONE; + } + /* if last read command timeout,clear vldclr bit */ + /* read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;write:FSM_REQ-->idle */ + switch (GET_WACS0_FSM(reg_rdata)) { + case WACS_FSM_WFVLDCLR: + WRAP_WR32(wacs_vldclr_register, 1); + PWRAPLOG("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n"); + break; + case WACS_FSM_WFDLE: + PWRAPLOG("WACS_FSM = WACS_FSM_WFDLE\n"); + break; + case WACS_FSM_REQ: + PWRAPLOG("WACS_FSM = WACS_FSM_REQ\n"); + break; + default: + break; + } + } while (fp(reg_rdata)); /* IDLE State */ + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +static inline u32 wait_for_state_ready(loop_condition_fp fp, u32 timeout_us, void *wacs_register, + u32 *read_reg) +{ + u64 start_time_ns = 0, timeout_ns = 0; + u64 loop_count = 0; + u32 reg_rdata; + + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(timeout_us); + do { + loop_count++; + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) { + PWRAPLOG("timeout when waiting for idle, loop_count = %lld\n", loop_count); + pwrap_dump_ap_register(); + return E_PWR_WAIT_IDLE_TIMEOUT; + } + reg_rdata = WRAP_RD32(wacs_register); + + if (GET_INIT_DONE0(reg_rdata) != WACS_INIT_DONE) { + PWRAPLOG("initialization isn't finished\n"); + return E_PWR_NOT_INIT_DONE; + } + } while (fp(reg_rdata)); /* IDLE State */ + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +/********************************************************************************************/ +/* extern API for PMIC driver, INT related control, this INT is for PMIC chip to AP */ +/********************************************************************************************/ +u32 mt_pmic_wrap_eint_status(void) +{ + return WRAP_RD32(PMIC_WRAP_EINT_STA); +} + +void mt_pmic_wrap_eint_clr(int offset) +{ + if ((offset < 0) || (offset > 3)) + PWRAPERR("clear EINT flag error, only 0-3 bit\n"); + else + WRAP_WR32(PMIC_WRAP_EINT_CLR, (1 << offset)); + + PWRAPREG("clear EINT flag mt_pmic_wrap_eint_status=0x%x\n", WRAP_RD32(PMIC_WRAP_EINT_STA)); +} + +/* -------------------------------------------------------- */ +/* Function : pwrap_wacs2() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 pwrap_wacs2_hal(u32 write, u32 adr, u32 wdata, u32 *rdata) +{ + u32 reg_rdata = 0; + u32 wacs_write = 0; + u32 wacs_adr = 0; + u32 wacs_cmd = 0; + u32 return_value = 0; + unsigned long flags = 0; + + + /* Check argument validation */ + if ((write & ~(0x1)) != 0) + return E_PWR_INVALID_RW; + if ((adr & ~(0xffff)) != 0) + return E_PWR_INVALID_ADDR; + if ((wdata & ~(0xffff)) != 0) + return E_PWR_INVALID_WDAT; + + spin_lock_irqsave(&wrp_lock, flags); + + /* Check IDLE & INIT_DONE in advance */ + return_value = + wait_for_state_idle(wait_for_fsm_idle, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, + PMIC_WRAP_WACS2_VLDCLR, 0); + if (return_value != 0) { + PWRAPLOG("wait_for_fsm_idle fail,return_value=%d\n", return_value); + goto FAIL; + } + wacs_write = write << 31; + wacs_adr = (adr >> 1) << 16; + wacs_cmd = wacs_write | wacs_adr | wdata; + + WRAP_WR32(PMIC_WRAP_WACS2_CMD, wacs_cmd); + if (write == 0) { + if (NULL == rdata) { + PWRAPLOG("rdata is a NULL pointer\n"); + return_value = E_PWR_INVALID_ARG; + WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1); + goto FAIL; + } + return_value = + wait_for_state_ready(wait_for_fsm_vldclr, TIMEOUT_READ, PMIC_WRAP_WACS2_RDATA, + ®_rdata); + if (return_value != 0) { + PWRAPLOG("wait_for_fsm_vldclr fail,return_value=%d\n", return_value); + return_value += 1; /* E_PWR_NOT_INIT_DONE_READ or E_PWR_WAIT_IDLE_TIMEOUT_READ */ + goto FAIL; + } + + *rdata = GET_WACS0_RDATA(reg_rdata); + WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1); + } + +FAIL: + spin_unlock_irqrestore(&wrp_lock, flags); + + if (return_value != 0) { + PWRAPLOG("pwrap_wacs2 fail,return_value=%d\n", return_value); + PWRAPLOG("timeout:BUG_ON here\n"); + } + + return return_value; +} + +/* ****************************************************************************** */ +/* --internal API for pwrap_init------------------------------------------------- */ +/* ****************************************************************************** */ + +/* -------------------------------------------------------- */ +/* Function : _pwrap_wacs2_nochk() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +s32 pwrap_read_nochk(u32 adr, u32 *rdata) +{ + return _pwrap_wacs2_nochk(0, adr, 0, rdata); +} + +s32 pwrap_write_nochk(u32 adr, u32 wdata) +{ + return _pwrap_wacs2_nochk(1, adr, wdata, 0); +} + +static s32 _pwrap_wacs2_nochk(u32 write, u32 adr, u32 wdata, u32 *rdata) +{ + u32 reg_rdata = 0x0; + u32 wacs_write = 0x0; + u32 wacs_adr = 0x0; + u32 wacs_cmd = 0x0; + u32 return_value = 0x0; + /* PWRAPFUC(); */ + /* Check argument validation */ + if ((write & ~(0x1)) != 0) + return E_PWR_INVALID_RW; + if ((adr & ~(0xffff)) != 0) + return E_PWR_INVALID_ADDR; + if ((wdata & ~(0xffff)) != 0) + return E_PWR_INVALID_WDAT; + + /* Check IDLE */ + return_value = + wait_for_state_ready_init(wait_for_fsm_idle, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, + 0); + if (return_value != 0) { + PWRAPLOG("_pwrap_wacs2_nochk write command fail,return_value=%x\n", return_value); + return return_value; + } + + wacs_write = write << 31; + wacs_adr = (adr >> 1) << 16; + wacs_cmd = wacs_write | wacs_adr | wdata; + WRAP_WR32(PMIC_WRAP_WACS2_CMD, wacs_cmd); + + if (write == 0) { + if (NULL == rdata) { + PWRAPLOG("rdata is a NULL pointer\n"); + WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1); + return E_PWR_INVALID_ARG; + } + /* wait for read data ready */ + return_value = + wait_for_state_ready_init(wait_for_fsm_vldclr, TIMEOUT_READ, + PMIC_WRAP_WACS2_RDATA, ®_rdata); + if (return_value != 0) { + PWRAPLOG("wait_for_fsm_vldclr fail, return_value=%d\n", return_value); + return_value += 1; /* E_PWR_NOT_INIT_DONE_READ or E_PWR_WAIT_IDLE_TIMEOUT_READ */ + return return_value; + } + *rdata = GET_WACS0_RDATA(reg_rdata); + WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1); + } + return 0; +} + +static void _pwrap_set_rest(void) +{ + WRAP_WR32(INFRA_GLOBALCON_RST2_SET, 0x1); /* Write 1 set */ + WRAP_WR32(INFRA_GLOBALCON_RST2_CLR, 0x1); /* Write 1 clr */ +} + +static void _pwrap_set_spi_clk(void) +{ +#ifdef ULPOSC + WRAP_WR32(ULPOSC_CON, 0x0001); /* Enable ulposc */ + udelay(1); + WRAP_WR32(ULPOSC_CON, 0x0003); /* Reset ulposc */ + udelay(30); + WRAP_WR32(ULPOSC_CON, 0x0001); /* Release reset ulposc */ + udelay(130); + WRAP_WR32(ULPOSC_CON, 0x0005); + WRAP_WR32(CLK_CFG_5_SET, 0x0002); /* 52MHz [1:0] */ + udelay(20); + WRAP_WR32(PMICW_CLOCK_CTRL, 0x0000); /* pmicw_sw_en */ + WRAP_WR32(CLK_CFG_UPDATE, 0x00080000); /* Clock configure update */ + WRAP_WR32(MODULE_SW_CG_0_SET, 0x0000000F); /* sys_ck cg enable */ + WRAP_WR32(MODULE_SW_CG_0_CLR, 0x0000000F); /* sys_ck cg disable */ +#else + WRAP_WR32(CLK_CFG_5_CLR, 0x0001); /* 26MHz [1:0] */ + WRAP_WR32(MODULE_SW_CG_0_SET, 0x0000000F); /* sys_ck cg enable */ + WRAP_WR32(MODULE_SW_CG_0_CLR, 0x0000000F); /* sys_ck cg disable */ +#endif +} + +static void _pwrap_set_DCM(void) +{ + /* S32 sub_return = 0; */ + + WRAP_WR32(PMIC_WRAP_DCM_EN, 3); /* enable CRC DCM and PWRAP DCM */ + WRAP_WR32(PMIC_WRAP_DCM_DBC_PRD, DISABLE); /* No debounce */ +#if 0 + /* 0x10001074 bit[22] = 1??b0 to disable pmic clock DCM */ + sub_return = WRAP_RD32(PMIC_CLOCK_DCM); + WRAP_WR32(PMIC_CLOCK_DCM, (sub_return & 0xFFBFFFFF)); + /* PWRAPERR("Enable DCM before = %x, after= %x\n", sub_return, WRAP_RD32(PMIC_CLOCK_DCM)); */ + + /* 0x10001F0C bit[25] = 1??b1 to disable apb clock gating mechanism. */ + sub_return = WRAP_RD32(APB_CLOCK_GATING); + WRAP_WR32(APB_CLOCK_GATING, ((sub_return & 0xFDFFFFFF) | 0x02000000)); + /* PWRAPERR("disable apb clock gating before =gg %x, after= %x\n", sub_return, WRAP_RD32(APB_CLOCK_GATING)); */ +#endif +} +/* -------------------------------------------------------- */ +/* Function : _pwrap_init_dio() */ +/* Description :call it in pwrap_init,mustn't check init done */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_init_dio(u32 dio_en) +{ + u32 arb_en_backup = 0x0; + u32 rdata = 0x0; + u32 return_value = 0; + + /* PWRAPFUC(); */ + arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN); + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2); /* only WACS2 */ + + pwrap_write_nochk(PMIC_DEW_DIO_EN_ADDR, dio_en); + + /* Check IDLE & INIT_DONE in advance */ + return_value = + wait_for_state_ready_init(wait_for_idle_and_sync, TIMEOUT_WAIT_IDLE, + PMIC_WRAP_WACS2_RDATA, 0); + if (return_value != 0) { + PWRAPLOG("_pwrap_init_dio fail,return_value=%x\n", return_value); + return return_value; + } + /* Enable AP DIO mode */ + WRAP_WR32(PMIC_WRAP_DIO_EN, dio_en); + /* Read Test */ + + pwrap_read_nochk(PMIC_DEW_READ_TEST_ADDR, &rdata); + if (rdata != PMIC_DEFAULT_VALUE_READ_TEST) { + PWRAPLOG("[Dio_mode][Read Test] fail,dio_en = %x, READ_TEST rdata=%x, exp=0x5aa5\n", + dio_en, rdata); + return E_PWR_READ_TEST_FAIL; + } + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, arb_en_backup); + return 0; +} + +/* -------------------------------------------------------- */ +/* Function : _pwrap_init_cipher() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_init_cipher(void) +{ + u32 arb_en_backup = 0; + u32 rdata = 0; + u32 return_value = 0; + u32 start_time_ns = 0, timeout_ns = 0; + /* PWRAPFUC(); */ + arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN); + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2); /* only WACS0 */ + + WRAP_WR32(PMIC_WRAP_CIPHER_SWRST, 1); + WRAP_WR32(PMIC_WRAP_CIPHER_SWRST, 0); + WRAP_WR32(PMIC_WRAP_CIPHER_KEY_SEL, 1); + WRAP_WR32(PMIC_WRAP_CIPHER_IV_SEL, 2); + WRAP_WR32(PMIC_WRAP_CIPHER_EN, 1); + + /* Config CIPHER @ PMIC */ + pwrap_write_nochk(PMIC_DEW_CIPHER_SWRST_ADDR, 0x1); + pwrap_write_nochk(PMIC_DEW_CIPHER_SWRST_ADDR, 0x0); + pwrap_write_nochk(PMIC_DEW_CIPHER_KEY_SEL_ADDR, 0x1); + pwrap_write_nochk(PMIC_DEW_CIPHER_IV_SEL_ADDR, 0x2); + pwrap_write_nochk(PMIC_DEW_CIPHER_EN_ADDR, 0x1); + + + /* wait for cipher data ready@AP */ +#ifndef CONFIG_MTK_FPGA + return_value = + wait_for_state_ready_init(wait_for_cipher_ready, TIMEOUT_WAIT_IDLE, + PMIC_WRAP_CIPHER_RDY, 0); +#else + return_value = + wait_for_state_ready_init(wait_for_cipher_ready, 0xFFFFFFFF, PMIC_WRAP_CIPHER_RDY, 0); +#endif + if (return_value != 0) { + PWRAPLOG("wait for cipher data ready@AP fail,return_value=%x\n", return_value); + return return_value; + } + /* wait for cipher data ready@PMIC */ + start_time_ns = _pwrap_get_current_time(); + timeout_ns = _pwrap_time2ns(0xFFFFFF); + do { + if (_pwrap_timeout_ns(start_time_ns, timeout_ns)) + PWRAPLOG("wait for cipher data ready@PMIC\n"); + + pwrap_read_nochk(PMIC_DEW_CIPHER_RDY_ADDR, &rdata); + } while (rdata != 0x1); /* cipher_ready */ + + pwrap_write_nochk(PMIC_DEW_CIPHER_MODE_ADDR, 0x1); + + /* wait for cipher mode idle */ + return_value = + wait_for_state_ready_init(wait_for_idle_and_sync, TIMEOUT_WAIT_IDLE, + PMIC_WRAP_WACS2_RDATA, 0); + if (return_value != 0) { + PWRAPLOG("wait for cipher mode idle fail,return_value=%x\n", return_value); + return return_value; + } + WRAP_WR32(PMIC_WRAP_CIPHER_MODE, 1); + + /* Read Test */ + pwrap_read_nochk(PMIC_DEW_READ_TEST_ADDR, &rdata); + if (rdata != PMIC_DEFAULT_VALUE_READ_TEST) { + PWRAPLOG("_pwrap_init_cipher,read test error,error code=%x, rdata=%x\n", 1, rdata); + return E_PWR_READ_TEST_FAIL; + } + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, arb_en_backup); + return 0; +} + +/* -------------------------------------------------------- */ +/* Function : _pwrap_init_sistrobe() */ +/* Description : Initialize SI_CK_CON and SIDLY */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_init_sistrobe(void) +{ + u32 arb_en_backup = 0; + u32 rdata = 0; + s32 ind = 0; + u32 result_faulty = 0; + u64 result = 0, tmp1 = 0, tmp2 = 0; + s32 leading_one = 0; + s32 tailing_one = 0; + u32 ret = 0; +#ifdef ULPOSC + u64 inds = 0, indf = 0; +#endif + arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN); + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2); /* only WACS2 */ + +#ifdef ULPOSC + /* --------------------------------------------------------------------- */ + /* Scan all possible input strobe by READ_TEST */ + /* --------------------------------------------------------------------- */ + result = 0; + result_faulty = 0; + inds = 0; + indf = 0; + for (ind = 0; ind < 44; ind++) { /* 44 sampling clock edge */ + WRAP_WR32(PMIC_WRAP_SI_CK_CON, (ind >> 2) & 0xf); + WRAP_WR32(PMIC_WRAP_SIDLY, 0x3 - (ind & 0x3)); + + _pwrap_wacs2_nochk(0, PMIC_DEW_READ_TEST_ADDR, 0, &rdata); + if (rdata == PMIC_DEFAULT_VALUE_READ_TEST) { + PWRAPERR + ("_pwrap_init_sistrobe [Read Test of %s] pass,index=%d rdata=%x\n", + PMIC_CHIP_STR, ind, rdata); + result |= (0x1 << ind); + } else { + PWRAPERR + ("_pwrap_init_sistrobe [Read Test of %s] tuning,index=%d rdata=%x\n", + PMIC_CHIP_STR, ind, rdata); + } + } + + /* --------------------------------------------------------------------- */ + /* Locate the leading one and trailing one */ + /* --------------------------------------------------------------------- */ + for (ind = 43; ind >= 0; ind--) { + if (ind > 20) { + indf = (0x1 << 20); + indf = (indf << ((ind - 20)%32)); + } else { + indf = (0x1 << (ind % 32)); + } + inds = result & indf; + if (inds) + break; + } + leading_one = ind; + + for (ind = 0; ind < 44; ind++) { + if (ind > 20) { + indf = (0x1 << 20); + indf = (indf << ((ind - 20)%32)); + } else { + indf = (0x1 << (ind % 32)); + } + inds = result & indf; + if (inds) + break; + } + tailing_one = ind; + + /* --------------------------------------------------------------------- */ + /* Check the continuity of pass range */ + /* --------------------------------------------------------------------- */ + tmp1 = (0x1 << (leading_one + 1)) - 1; + tmp2 = (0x1 << tailing_one) - 1; + if ((tmp1 - tmp2) != result) { + PWRAPERR("_pwrap_init_sistrobe Fail, result = %llx, leading_one:%d, tailing_one:%d\n", + result, leading_one, tailing_one); + result_faulty = 0x1; + } + /* --------------------------------------------------------------------- */ + /* Config SICK and SIDLY to the middle point of pass range */ + /* --------------------------------------------------------------------- */ + ind = (leading_one + tailing_one) / 2; + WRAP_WR32(PMIC_WRAP_SI_CK_CON, (ind >> 2) & 0xf); + WRAP_WR32(PMIC_WRAP_SIDLY, 0x3 - (ind & 0x3)); + +#else /* Else of #ifdef ULPOSC */ + + /* --------------------------------------------------------------------- */ + /* Scan all possible input strobe by READ_TEST */ + /* --------------------------------------------------------------------- */ + for (ind = 0; ind < 24; ind++) { /* 24 sampling clock edge */ + WRAP_WR32(PMIC_WRAP_SI_CK_CON, (ind >> 2) & 0x7); + WRAP_WR32(PMIC_WRAP_SIDLY, 0x3 - (ind & 0x3)); + + _pwrap_wacs2_nochk(0, PMIC_DEW_READ_TEST_ADDR, 0, &rdata); + if (rdata == PMIC_DEFAULT_VALUE_READ_TEST) { + PWRAPERR("_pwrap_init_sistrobe [Read Test of %s] pass,index=%d rdata=%x\n", + PMIC_CHIP_STR, ind, rdata); + result |= (0x1 << ind); + } else { + PWRAPERR + ("_pwrap_init_sistrobe [Read Test of %s] tuning,index=%d rdata=%x\n", + PMIC_CHIP_STR, ind, rdata); + } + } + + /* --------------------------------------------------------------------- */ + /* Locate the leading one and trailing one of PMIC 1/2 */ + /* --------------------------------------------------------------------- */ + for (ind = 23; ind >= 0; ind--) { + if (result & (0x1 << ind)) + break; + + } + leading_one = ind; + + for (ind = 0; ind < 24; ind++) { + if (result & (0x1 << ind)) + break; + } + tailing_one = ind; + + /* --------------------------------------------------------------------- */ + /* Check the continuity of pass range */ + /* --------------------------------------------------------------------- */ + tmp1 = (0x1 << (leading_one + 1)) - 1; + tmp2 = (0x1 << tailing_one) - 1; + if ((tmp1 - tmp2) != result) { + PWRAPERR("_pwrap_init_sistrobe Fail, result = %llx, leading_one:%d, tailing_one:%d\n", + result, leading_one, tailing_one); + result_faulty = 0x1; + } + /* --------------------------------------------------------------------- */ + /* Config SICK and SIDLY to the middle point of pass range */ + /* --------------------------------------------------------------------- */ + if (result_faulty == 0) { + ind = (leading_one + tailing_one) / 2; + WRAP_WR32(PMIC_WRAP_SI_CK_CON, (ind >> 2) & 0x7); + WRAP_WR32(PMIC_WRAP_SIDLY, 0x3 - (ind & 0x3)); + /* --------------------------------------------------------------------- */ + /* Restore */ + /* --------------------------------------------------------------------- */ + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, arb_en_backup); + } else { + PWRAPERR("_pwrap_init_sistrobe Fail,result_faulty=%x\n", result_faulty); + ret = result_faulty; + } + return ret; +#endif /* End of #ifdef ULPOSC */ +} + +/* -------------------------------------------------------- */ +/* Function : _pwrap_reset_spislv() */ +/* Description : */ +/* Parameter : */ +/* Return : */ +/* -------------------------------------------------------- */ +static s32 _pwrap_reset_spislv(void) +{ + u32 ret = 0; + u32 return_value = 0; + /* PWRAPFUC(); */ + /* This driver does not using _pwrap_switch_mux */ + /* because the remaining requests are expected to fail anyway */ + + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, DISABLE_ALL); + WRAP_WR32(PMIC_WRAP_WRAP_EN, DISABLE); + WRAP_WR32(PMIC_WRAP_MUX_SEL, MANUAL_MODE); + WRAP_WR32(PMIC_WRAP_MAN_EN, ENABLE); + WRAP_WR32(PMIC_WRAP_DIO_EN, DISABLE); + + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_CSL << 8)); /* 0x2100 */ + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); /* 0x2800//to reset counter */ + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_CSH << 8)); /* 0x2000 */ + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); + WRAP_WR32(PMIC_WRAP_MAN_CMD, (OP_WR << 13) | (OP_OUTS << 8)); + + return_value = + wait_for_state_ready_init(wait_for_sync, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, 0); + if (return_value != 0) { + PWRAPLOG("_pwrap_reset_spislv fail,return_value=%x\n", return_value); + ret = E_PWR_TIMEOUT; + goto timeout; + } + + WRAP_WR32(PMIC_WRAP_MAN_EN, DISABLE); + WRAP_WR32(PMIC_WRAP_MUX_SEL, WRAPPER_MODE); + +timeout: + WRAP_WR32(PMIC_WRAP_MAN_EN, DISABLE); + WRAP_WR32(PMIC_WRAP_MUX_SEL, WRAPPER_MODE); + return ret; +} + +#if 0 +static void __pwrap_soft_reset(void) +{ + PWRAPLOG("start reset wrapper\n"); + PWRAP_SOFT_RESET; + PWRAPLOG("the reset register =%x\n", WRAP_RD32(INFRA_GLOBALCON_RST0)); + PWRAPLOG("PMIC_WRAP_STAUPD_GRPEN =0x%x,it should be equal to 0xc\n", + WRAP_RD32(PMIC_WRAP_STAUPD_GRPEN)); + /* clear reset bit */ + PWRAP_CLEAR_SOFT_RESET_BIT; +} +#endif + +static s32 _pwrap_init_reg_clock(u32 regck_sel) +{ + PWRAPFUC(); + + pwrap_write_nochk(PMIC_DEW_RDDMY_NO_ADDR, 0x8); + WRAP_WR32(PMIC_WRAP_RDDMY, 0x08); + + /* Config SPI Waveform according to reg clk */ + if (regck_sel == 1) { /* 18MHz in 6328, 26Mhz in BBCHip */ + WRAP_WR32(PMIC_WRAP_CSHEXT_READ, 0x0); + /* Wait data written into register => + 4T_PMIC: consists of CSHEXT_WRITE_START+EXT_CK+CSHEXT_WRITE_END+CSLEXT_START */ + WRAP_WR32(PMIC_WRAP_CSHEXT_WRITE, 0x33); + WRAP_WR32(PMIC_WRAP_CSLEXT_START, 0x0); + WRAP_WR32(PMIC_WRAP_CSLEXT_END, 0x0); /* for PMIC site synchronizer use */ + } else { /* Safe mode */ + WRAP_WR32(PMIC_WRAP_CSHEXT_WRITE, 0xff); + WRAP_WR32(PMIC_WRAP_CSHEXT_READ, 0xff); + WRAP_WR32(PMIC_WRAP_CSLEXT_START, 0xf); + WRAP_WR32(PMIC_WRAP_CSLEXT_END, 0xf); + } + + return 0; +} + +static void _pwrap_init_status_update(void) +{ +#if 0 + sub_return = pwrap_write_nochk(PMIC_DEW_CRC_EN_ADDR, ENABLE); + if (sub_return != 0) { + PWRAPLOG("Enable CRC fail, return=%x\n", sub_return); + return E_PWR_INIT_ENABLE_CRC; + } + WRAP_WR32(PMIC_WRAP_WACS2_EN, PMIC_DEW_CRC_VAL_ADDR); +#endif + WRAP_WR32(PMIC_WRAP_STAUPD_GRPEN, 0x75); +#if 0 + WRAP_WR32(PMIC_WRAP_CRC_EN, ENABLE); +#endif + WRAP_WR32(PMIC_WRAP_EINT_STA0_ADR, PMIC_CPU_INT_STA_ADDR); + + WRAP_WR32(PMIC_WRAP_ADC_CMD_ADDR, PMIC_LDO_LDO_RSV1_RO_ADDR); + WRAP_WR32(PMIC_WRAP_PWRAP_ADC_CMD, 0x0100); + WRAP_WR32(PMIC_WRAP_ADC_RDATA_ADDR, PMIC_AUXADC_ADC_OUT_MDRT_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR_LATEST, PMIC_AUXADC_ADC_OUT_MDRT_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR_WP, PMIC_AUXADC_MDBG_W_PTR_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR0, PMIC_AUXADC_BUF_OUT_00_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR1, PMIC_AUXADC_BUF_OUT_01_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR2, PMIC_AUXADC_BUF_OUT_02_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR3, PMIC_AUXADC_BUF_OUT_03_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR4, PMIC_AUXADC_BUF_OUT_04_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR5, PMIC_AUXADC_BUF_OUT_05_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR6, PMIC_AUXADC_BUF_OUT_06_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR7, PMIC_AUXADC_BUF_OUT_07_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR8, PMIC_AUXADC_BUF_OUT_08_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR9, PMIC_AUXADC_BUF_OUT_09_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR10, PMIC_AUXADC_BUF_OUT_10_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR11, PMIC_AUXADC_BUF_OUT_11_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR12, PMIC_AUXADC_BUF_OUT_12_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR13, PMIC_AUXADC_BUF_OUT_13_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR14, PMIC_AUXADC_BUF_OUT_14_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR15, PMIC_AUXADC_BUF_OUT_15_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR16, PMIC_AUXADC_BUF_OUT_16_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR17, PMIC_AUXADC_BUF_OUT_17_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR18, PMIC_AUXADC_BUF_OUT_18_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR19, PMIC_AUXADC_BUF_OUT_19_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR20, PMIC_AUXADC_BUF_OUT_20_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR21, PMIC_AUXADC_BUF_OUT_21_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR22, PMIC_AUXADC_BUF_OUT_22_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR23, PMIC_AUXADC_BUF_OUT_23_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR24, PMIC_AUXADC_BUF_OUT_24_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR25, PMIC_AUXADC_BUF_OUT_25_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR26, PMIC_AUXADC_BUF_OUT_26_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR27, PMIC_AUXADC_BUF_OUT_27_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR28, PMIC_AUXADC_BUF_OUT_28_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR29, PMIC_AUXADC_BUF_OUT_29_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR30, PMIC_AUXADC_BUF_OUT_30_ADDR); + WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR31, PMIC_AUXADC_BUF_OUT_31_ADDR); +} + +static void _pwrap_adjust_priority(void) +{ + WRAP_WR32(PMIC_WRAP_PRIORITY_USER_SEL_0, 0x6543C210); + WRAP_WR32(PMIC_WRAP_PRIORITY_USER_SEL_1, 0xFEDBA987); + WRAP_WR32(PMIC_WRAP_ARBITER_OUT_SEL_0, 0x87654210); + WRAP_WR32(PMIC_WRAP_ARBITER_OUT_SEL_1, 0xFED3CBA9); +} + +static void _pwrap_set_starvation(void) +{ + /* latency is smaller than 10us, pop up to group"1" first */ + WRAP_WR32(PMIC_WRAP_HARB_HPRIO, 0x0007); /* [0]:MD_HW [1]:C2K_HW [2]:MD_DVFS _HW */ + /* starvation enable */ + /* [0]=MD_HW, latency= 2.6us, target= (2.6/1.2)=2 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_0, 0x0402); /* [10]: enable starvation, [9:0]: target setting */ + /* [1]=C2K_HW, latency= 2.6us, target= (2.6/1.2)=2 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_1, 0x0402); /* [10]: enable starvation, [9:0]: target setting */ + /* [2]=MD_DVFS_HW,latency= 5.2us, target= (5.2/1.2)-1=3 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_2, 0x0403); /* [10]: enable starvation, [9:0]: target setting */ + /* [3]=WACS1(MD_SW1), latency=20us, target= (20/1.2)-1=25 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_3, 0x0414); /* [10]: enable starvation, [9:0]: target setting */ + /* [4]=WACS0(MD_SW0), latency=40us, target= (40/1.2)-1=32 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_4, 0x0420); /* [10]: enable starvation, [9:0]: target setting */ + /* [5]=SPM_HW, latency=40us, target= (40/1.2)-1=32 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_5, 0x0420); /* [10]: enable starvation, [9:0]: target setting */ + /* [6]=WACS3(C2K_SW), latency=40us, target= (40/1.2)-1=32 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_6, 0x0420); /* [10]: enable starvation, [9:0]: target setting */ + /* [7]=DCXO_CONNINF, latency=50us, target= (50/1.2)-1=40 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_7, 0x0428); /* [10]: enable starvation, [9:0]: target setting */ + /* [8]=DCXO_NFCINF, latency=50us, target= (50/1.2)-1=40 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_8, 0x0428); /* [10]: enable starvation, [9:0]: target setting */ + /* [9]=MD_ADCINF, latency=29us, target= (29/1.2)-1= 23 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_9, 0x0417); /* [10]: enable starvation, [9:0]: target setting */ + /* [10]=STAUPD, latency=428us, target= (428/1.2)-1=355 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_10, 0x0563); /* [10]: enable starvation, [9:0]: target setting */ + /* [11]=GPS_HW, latency=150us, target= (150/1.2)-1=124 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_11, 0x047C); /* [10]: enable starvation, [9:0]: target setting */ + /* [12]=WACS2(AP_SW), latency=1000us, target= (1000/1.2)-1=832 */ + WRAP_WR32(PMIC_WRAP_STARV_COUNTER_12, 0x0740); /* [10]: enable starvation, [9:0]: target setting */ +} + +static void _pwrap_set_en(void) +{ + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, 0x01fff); + WRAP_WR32(PMIC_WRAP_WACS0_EN, ENABLE); + WRAP_WR32(PMIC_WRAP_WACS1_EN, ENABLE); + WRAP_WR32(PMIC_WRAP_WACS3_EN, ENABLE); + WRAP_WR32(PMIC_WRAP_STAUPD_PRD, 0x5); /* 100us */ + WRAP_WR32(PMIC_WRAP_WDT_UNIT, 0xf); + WRAP_WR32(PMIC_WRAP_WDT_SRC_EN, 0xffffffff); + WRAP_WR32(PMIC_WRAP_TIMER_EN, 0x1); + /* WRAP_WR32(PMIC_WRAP_INT0_EN, 0xffffffff); */ + WRAP_WR32(PMIC_WRAP_INT0_EN, 0xfffffffD); /* FIX ME */ + WRAP_WR32(PMIC_WRAP_INT1_EN, 0x0001ffff); +} + +static void _pwrap_set_init_done(void) +{ + WRAP_WR32(PMIC_WRAP_INIT_DONE0, ENABLE); /* MD SW0 */ + WRAP_WR32(PMIC_WRAP_INIT_DONE1, ENABLE); /* MD SW1 */ + WRAP_WR32(PMIC_WRAP_INIT_DONE2, ENABLE); /* AP SW */ + WRAP_WR32(PMIC_WRAP_INIT_DONE3, ENABLE); /* C2K SW */ +} +/* + * pmic_wrap init,init wrap interface + */ +s32 pwrap_init(void) +{ + s32 sub_return = 0; + s32 sub_return1 = 0; + u32 rdata = 0x0; + + PWRAPFUC(); + +#ifdef CONFIG_OF + sub_return = pwrap_of_iomap(); + if (sub_return) + return sub_return; +#endif + + +#ifndef CONFIG_MTK_FPGA + /* ############################### */ + /* toggle PMIC_WRAP and pwrap_spictl reset */ + /* ############################### */ + _pwrap_set_rest(); + + /* ############################### */ + /* Set SPI_CK_freq 52MHz or 26MHz */ + /* ############################### */ + _pwrap_set_spi_clk(); +#endif + /* ############################### */ + /* Enable DCM */ + /* ############################### */ + _pwrap_set_DCM(); + + /* ############################### */ + /* Reset all SPISLV */ + /* ############################### */ + sub_return = _pwrap_reset_spislv(); + if (sub_return != 0) { + PWRAPLOG("error,_pwrap_reset_spislv fail,sub_return=%x\n", sub_return); + return E_PWR_INIT_RESET_SPI; + } + /* ############################### */ + /* Enable WACS2 */ + /* ############################### */ + WRAP_WR32(PMIC_WRAP_WRAP_EN, ENABLE); /* enable wrap */ + WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2); /* Only WACS2 */ + WRAP_WR32(PMIC_WRAP_WACS2_EN, ENABLE); + + /* ############################### */ + /* Input data calibration flow */ + /* ############################### */ + sub_return = _pwrap_init_sistrobe(); + if (sub_return != 0) { + PWRAPLOG("error,DrvPWRAP_InitSiStrobe fail,sub_return=%x\n", sub_return); + return E_PWR_INIT_SIDLY; + } + /* ############################### */ + /* SPI Waveform Configuration */ + /* ############################### */ + /* 0:safe mode, 1:18MHz */ + sub_return = _pwrap_init_reg_clock(1); + if (sub_return != 0) { + PWRAPLOG("error,_pwrap_init_reg_clock fail,sub_return=%x\n", sub_return); + return E_PWR_INIT_REG_CLOCK; + } + /* ############################### */ + /* Enable DIO mode */ + /* ############################### */ + sub_return = _pwrap_init_dio(1); + if (sub_return != 0) { + PWRAPLOG("_pwrap_init_dio test error,error code=%x, sub_return=%x\n", 0x11, + sub_return); + return E_PWR_INIT_DIO; + } + /* ############################### */ + /* Enable Encryption */ + /* ############################### */ + sub_return = _pwrap_init_cipher(); + if (sub_return != 0) { + PWRAPLOG("Enable Encryption fail, return=%x\n", sub_return); + return E_PWR_INIT_CIPHER; + } + /* ############################### */ + /* Write test using WACS2 */ + /* ############################### */ + sub_return = pwrap_write_nochk(PMIC_DEW_WRITE_TEST_ADDR, PMIC_WRITE_TEST_VALUE); + sub_return1 = pwrap_read_nochk(PMIC_DEW_WRITE_TEST_ADDR, &rdata); + if (rdata != PMIC_WRITE_TEST_VALUE) { + PWRAPLOG("write test error,rdata=0x%x,exp=0xa55a,sub_return=0x%x,sub_return1=0x%x\n", + rdata, sub_return, sub_return1); + return E_PWR_INIT_WRITE_TEST; + } + + /* ############################### */ + /* Status update function initialization */ + /* 1. Signature Checking using CRC (CRC 0 only) */ + /* 2. EINT update */ + /* 3. Read back Auxadc thermal data for GPD */ + /* 4. Read back Auxadc thermal data for LTE */ + /* ############################### */ + _pwrap_init_status_update(); + + /* ############################### */ + /* PMIC_WRAP priority adjusted */ + /* ############################### */ + _pwrap_adjust_priority(); + + /* ############################### */ + /* PMIC_WRAP starvation setting */ + /* ############################### */ + _pwrap_set_starvation(); + + /* ############################### */ + /* PMIC_WRAP enables */ + /* ############################### */ + _pwrap_set_en(); + + /* ############################### */ + /* Initialization Done */ + /* ############################### */ + _pwrap_set_init_done(); + +#ifdef CONFIG_OF + pwrap_of_iounmap(); +#endif + + return 0; +} + +static irqreturn_t mt_pmic_wrap_irq(int irqno, void *dev_id) +{ + unsigned long flags = 0; + + PWRAPFUC(); + PWRAPREG("dump pwrap register\n"); + spin_lock_irqsave(&wrp_lock_isr, flags); + /* *----------------------------------------------------------------------- */ + pwrap_dump_all_register(); + /* raise the priority of WACS2 for AP */ + WRAP_WR32(PMIC_WRAP_HARB_HPRIO, WACS2); + + /* *----------------------------------------------------------------------- */ + PWRAPREG("INT flag 0x%x\n", WRAP_RD32(PMIC_WRAP_INT0_FLG_RAW)); + PWRAPREG("INT flag 0x%x\n", WRAP_RD32(PMIC_WRAP_INT1_FLG_RAW)); + /* clear interrupt flag */ + WRAP_WR32(PMIC_WRAP_INT0_CLR, 0xffffffff); + WRAP_WR32(PMIC_WRAP_INT1_CLR, 0xffffffff); + /*BUG_ON(1);*/ + spin_unlock_irqrestore(&wrp_lock_isr, flags); + return IRQ_HANDLED; +} + + +static u32 pwrap_read_test(void) +{ + u32 rdata = 0; + u32 return_value = 0; + u32 ret = 0; + + /* Read Test */ + return_value = pwrap_read(PMIC_DEW_READ_TEST_ADDR, &rdata); + if (rdata != PMIC_DEFAULT_VALUE_READ_TEST) { + PWRAPREG("Read Test fail,rdata=0x%x, exp=0x5aa5,return_value=0x%x\n", rdata, + return_value); + ret = E_PWR_READ_TEST_FAIL; + } else { + PWRAPREG("Read Test pass,return_value=%d\n", return_value); + /* return 0; */ + } + + return ret; +} + +static u32 pwrap_write_test(void) +{ + u32 rdata = 0; + u32 sub_return = 0; + u32 sub_return1 = 0; + u32 ret = 0; + + /* ############################### */ + /* Write test using WACS2 */ + /* ############################### */ + sub_return = pwrap_write(PMIC_DEW_WRITE_TEST_ADDR, PMIC_WRITE_TEST_VALUE); + PWRAPREG("after %s pwrap_write\n", PMIC_CHIP_STR); + sub_return1 = pwrap_read(PMIC_DEW_WRITE_TEST_ADDR, &rdata); + if ((rdata != PMIC_WRITE_TEST_VALUE) || (sub_return != 0) || (sub_return1 != 0)) { + PWRAPREG("write test error,rdata=0x%x,exp=0xa55a,sub_return=0x%x,sub_return1=0x%x\n", + rdata, sub_return, sub_return1); + ret = E_PWR_INIT_WRITE_TEST; + } else { + PWRAPREG("write %s Test pass\n", PMIC_CHIP_STR); + } + + return ret; +} + +static void pwrap_int_test(void) +{ + u32 rdata1 = 0; + u32 rdata2 = 0; + + while (1) { + rdata1 = WRAP_RD32(PMIC_WRAP_EINT_STA); + pwrap_read(PMIC_CPU_INT_STA_ADDR, &rdata2); + PWRAPREG("Pwrap INT status check,PMIC_WRAP_EINT_STA=0x%x,PMIC_CPU_INT_STA_ADDR[0x01B4]=0x%x\n", + rdata1, rdata2); + msleep(500); + } +} + +#ifndef USER_BUILD_KERNEL +static void pwrap_read_reg_on_pmic(u32 reg_addr) +{ + u32 reg_value = 0; + u32 return_value = 0; + /* PWRAPFUC(); */ + return_value = pwrap_read(reg_addr, ®_value); + PWRAPREG("0x%x=0x%x,return_value=%x\n", reg_addr, reg_value, return_value); +} + +static void pwrap_write_reg_on_pmic(u32 reg_addr, u32 reg_value) +{ + u32 return_value = 0; + + PWRAPREG("write 0x%x to register 0x%x\n", reg_value, reg_addr); + return_value = pwrap_write(reg_addr, reg_value); + return_value = pwrap_read(reg_addr, ®_value); + /* PWRAPFUC(); */ + PWRAPREG("the result:0x%x=0x%x,return_value=%x\n", reg_addr, reg_value, return_value); +} +#endif + +static void pwrap_ut(u32 ut_test) +{ + switch (ut_test) { + case 1: + /* pwrap_wacs2_para_test(); */ + pwrap_write_test(); + break; + case 2: + /* pwrap_wacs2_para_test(); */ + pwrap_read_test(); + break; + + default: + PWRAPREG("default test.\n"); + break; + } +} + +/*---------------------------------------------------------------------------*/ +static s32 mt_pwrap_show_hal(char *buf) +{ + PWRAPFUC(); + return snprintf(buf, PAGE_SIZE, "%s\n", "no implement"); +} + +/*---------------------------------------------------------------------------*/ +static s32 mt_pwrap_store_hal(const char *buf, size_t count) +{ +#ifndef USER_BUILD_KERNEL + u32 reg_value = 0; + u32 reg_addr = 0; +#endif + u32 return_value = 0; + u32 ut_test = 0; + + if (!strncmp(buf, "-h", 2)) { + PWRAPREG + ("PWRAP debug: [-dump_reg][-trace_wacs2][-init][-rdpmic][-wrpmic][-readtest][-writetest]\n"); + PWRAPREG("PWRAP UT: [1][2]\n"); + } + /* ----------pwrap debug---------- */ + else if (!strncmp(buf, "-dump_reg", 9)) { + pwrap_dump_all_register(); + } else if (!strncmp(buf, "-trace_wacs2", 12)) { + /* pwrap_trace_wacs2(); */ + } else if (!strncmp(buf, "-init", 5)) { + return_value = pwrap_init(); + if (return_value == 0) + PWRAPREG("pwrap_init pass,return_value=%d\n", return_value); + else + PWRAPREG("pwrap_init fail,return_value=%d\n", return_value); + } +#ifndef USER_BUILD_KERNEL + else if (!strncmp(buf, "-rdpmic", 7) && (1 == sscanf(buf + 7, "%x", ®_addr))) { + pwrap_read_reg_on_pmic(reg_addr); + } else if (!strncmp(buf, "-wrpmic", 7) + && (2 == sscanf(buf + 7, "%x %x", ®_addr, ®_value))) { + pwrap_write_reg_on_pmic(reg_addr, reg_value); + } +#endif + else if (!strncmp(buf, "-readtest", 9)) { + pwrap_read_test(); + } else if (!strncmp(buf, "-writetest", 10)) { + pwrap_write_test(); + } else if (!strncmp(buf, "-int", 4)) { + pwrap_int_test(); + } + /* ----------pwrap UT---------- */ + else if (!strncmp(buf, "-ut", 3) && (1 == sscanf(buf + 3, "%d", &ut_test))) { + pwrap_ut(ut_test); + } else { + PWRAPREG("wrong parameter\n"); + } + return count; +} + +/*---------------------------------------------------------------------------*/ +#endif /* End of #if PMIC_WRAP_NO_PMIC */ + +#ifdef CONFIG_OF +static int pwrap_of_iomap(void) +{ + /* + * Map the address of the following register base: + * TOPCKGEN, INFRACFG_AO, GPIO, SLEEP + */ + + struct device_node *topckgen_node; + struct device_node *infracfg_ao_node; + struct device_node *gpio_node; + struct device_node *sleep_node; + + topckgen_node = of_find_compatible_node(NULL, NULL, "mediatek,TOPCKGEN"); + if (!topckgen_node) { + pr_info("get TOPCKGEN failed\n"); + return -ENODEV; + } + + topckgen_reg_base = of_iomap(topckgen_node, 0); + if (!topckgen_reg_base) { + pr_info("TOPCKGEN iomap failed\n"); + return -ENOMEM; + } + + infracfg_ao_node = of_find_compatible_node(NULL, NULL, "mediatek,INFRACFG_AO"); + if (!infracfg_ao_node) { + pr_info("get INFRACFG_AO failed\n"); + return -ENODEV; + } + + infracfg_ao_reg_base = of_iomap(infracfg_ao_node, 0); + if (!infracfg_ao_reg_base) { + pr_info("INFRACFG_AO iomap failed\n"); + return -ENOMEM; + } + + gpio_node = of_find_compatible_node(NULL, NULL, "mediatek,GPIO"); + if (!gpio_node) { + pr_info("get GPIO failed\n"); + return -ENODEV; + } + + gpio_reg_base = of_iomap(gpio_node, 0); + if (!gpio_reg_base) { + pr_info("GPIO iomap failed\n"); + return -ENOMEM; + } + + sleep_node = of_find_compatible_node(NULL, NULL, "mediatek,SLEEP"); + if (!sleep_node) { + pr_info("get SLEEP failed\n"); + return -ENODEV; + } + + sleep_reg_base = of_iomap(sleep_node, 0); + if (!sleep_reg_base) { + pr_info("SLEEp iomap failed\n"); + return -ENOMEM; + } + + pr_info("TOPCKGEN reg: 0x%p\n", topckgen_reg_base); + pr_info("INFRACFG_AO reg: 0x%p\n", infracfg_ao_reg_base); + pr_info("GPIO reg: 0x%p\n", gpio_reg_base); + pr_info("SLEEP reg: 0x%p\n", sleep_reg_base); + + return 0; +} + +static void pwrap_of_iounmap(void) +{ + iounmap(topckgen_reg_base); + iounmap(infracfg_ao_reg_base); + iounmap(gpio_reg_base); + iounmap(sleep_reg_base); +} +#endif + +#define VERSION "Revision" +static int is_pwrap_init_done(void) +{ + int ret = 0; + + ret = WRAP_RD32(PMIC_WRAP_INIT_DONE2); + if (ret != 0) + return 0; + + ret = pwrap_init(); + if (ret != 0) { + PWRAPERR("init error (%d)\n", ret); + pwrap_dump_all_register(); + return ret; + } + PWRAPLOG("init successfully done (%d)\n\n", ret); + return ret; +} + +static int __init pwrap_hal_init(void) +{ + s32 ret = 0; +#ifdef CONFIG_OF + u32 pwrap_irq; + struct device_node *pwrap_node; + + pwrap_node = of_find_compatible_node(NULL, NULL, "mediatek,PWRAP"); + if (!pwrap_node) { + pr_info("PWRAP get node failed\n"); + return -ENODEV; + } + + pwrap_base = of_iomap(pwrap_node, 0); + if (!pwrap_base) { + pr_info("PWRAP iomap failed\n"); + return -ENOMEM; + } + + pwrap_irq = irq_of_parse_and_map(pwrap_node, 0); + if (!pwrap_irq) { + pr_info("PWRAP get irq fail\n"); + return -ENODEV; + } + pr_info("PWRAP reg: 0x%p, irq: %d\n", pwrap_base, pwrap_irq); +#endif + + PWRAPLOG("HAL init: version %s\n", VERSION); + mt_wrp = get_mt_pmic_wrap_drv(); + mt_wrp->store_hal = mt_pwrap_store_hal; + mt_wrp->show_hal = mt_pwrap_show_hal; + mt_wrp->wacs2_hal = pwrap_wacs2_hal; + + if (is_pwrap_init_done() == 0) { +#ifdef PMIC_WRAP_NO_PMIC +#else + + ret = + request_irq(MT_PMIC_WRAP_IRQ_ID, mt_pmic_wrap_irq, IRQF_TRIGGER_HIGH, + PMIC_WRAP_DEVICE, 0); +#endif + if (ret) { + PWRAPERR("register IRQ failed (%d)\n", ret); + return ret; + } + } else { + PWRAPERR("not init (%d)\n", ret); + } + + /* PWRAPERR("not init (%x)\n", is_pwrap_init_done); */ + + return ret; +} +postcore_initcall(pwrap_hal_init); + diff --git a/drivers/misc/mediatek/power/mt6755/Makefile b/drivers/misc/mediatek/power/mt6755/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..e86f963a09ad27cec5e32d93dc1089f62476ce7d --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/Makefile @@ -0,0 +1,58 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ifeq ($(CONFIG_MTK_PMIC_NEW_ARCH),y) + +#obj-$(CONFIG_MTK_PMIC) += mt6311.o + +else +obj-$(CONFIG_MTK_PMIC) += pmic.o pmic_irq.o upmu_common.o pmic_auxadc.o pmic_chr_type_det.o mt6311.o pmic_initial_setting.o + +endif + +ifeq ($(CONFIG_MTK_PMIC_DVT_SUPPORT),y) + obj-$(CONFIG_MTK_PMIC) += pmic_dvt.o +endif + +obj-$(CONFIG_MTK_SMART_BATTERY) += battery_meter_hal.o +obj-$(CONFIG_MTK_SMART_BATTERY) += mtk_bif_intf.o + +ifeq ($(CONFIG_MTK_BQ24261_SUPPORT),y) + obj-$(CONFIG_MTK_SMART_BATTERY) += bq24261.o charging_hw_bq24261.o +else + ifeq ($(CONFIG_MTK_SWCHR_SUPPORT),y) + obj-$(CONFIG_MTK_SMART_BATTERY) += charging_hw_mt_sw_charger.o + else + ifeq ($(CONFIG_MTK_NCP1854_SUPPORT),y) + obj-$(CONFIG_MTK_SMART_BATTERY) += ncp1854.o charging_hw_ncp1854.o + else + ifeq ($(CONFIG_MTK_BQ24296_SUPPORT),y) + obj-$(CONFIG_MTK_SMART_BATTERY) += bq24296.o charging_hw_bq24296.o + else + ifeq ($(CONFIG_MTK_FAN5405_SUPPORT),y) + obj-$(CONFIG_MTK_SMART_BATTERY) += fan5405.o charging_hw_fan5405.o + else + ifeq ($(CONFIG_MTK_BQ25896_SUPPORT),y) + obj-$(CONFIG_MTK_SMART_BATTERY) += bq25890.o charging_hw_bq25890.o + else + ifeq ($(CONFIG_MTK_BQ24158_SUPPORT),y) + obj-$(CONFIG_MTK_SMART_BATTERY) += bq24158.o charging_hw_bq24158.o + else + obj-$(CONFIG_MTK_SMART_BATTERY) += charging_hw_pmic.o + endif + endif + endif + endif + endif + endif +endif diff --git a/drivers/misc/mediatek/power/mt6755/battery_meter_hal.c b/drivers/misc/mediatek/power/mt6755/battery_meter_hal.c new file mode 100644 index 0000000000000000000000000000000000000000..099e76e352f52fec2eace1e570483729b76e0a1b --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/battery_meter_hal.c @@ -0,0 +1,1277 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + +#include + +#include +#include +#include +#include + + + + + +/*============================================================ // +//define +//============================================================ //*/ +#define STATUS_OK 0 +#define STATUS_UNSUPPORTED -1 +#define VOLTAGE_FULL_RANGE 1800 +#define ADC_PRECISE 32768 /* 12 bits */ + +#define UNIT_FGCURRENT (158122) /* 158.122 uA */ + +/*============================================================ // +//global variable +//============================================================ //*/ +signed int chip_diff_trim_value_4_0 = 0; +signed int chip_diff_trim_value = 0; /* unit = 0.1 */ + +signed int g_hw_ocv_tune_value = 0; + +kal_bool g_fg_is_charging = 0; + +/*============================================================ // +//function prototype +//============================================================ // + +//============================================================ // +//extern variable +//============================================================ // + +//============================================================ // +//extern function +//============================================================ //*/ + +/*============================================================ // */ +void get_hw_chip_diff_trim_value(void) +{ +#if defined(CONFIG_POWER_EXT) +#else + +#if 1 + + chip_diff_trim_value_4_0 = 0; + + bm_print(BM_LOG_CRTI, "[Chip_Trim] chip_diff_trim_value_4_0=%d\n", + chip_diff_trim_value_4_0); +#else + bm_print(BM_LOG_FULL, "[Chip_Trim] need check reg number\n"); +#endif + + switch (chip_diff_trim_value_4_0) { + case 0: + chip_diff_trim_value = 1000; + break; + case 1: + chip_diff_trim_value = 1005; + break; + case 2: + chip_diff_trim_value = 1010; + break; + case 3: + chip_diff_trim_value = 1015; + break; + case 4: + chip_diff_trim_value = 1020; + break; + case 5: + chip_diff_trim_value = 1025; + break; + case 6: + chip_diff_trim_value = 1030; + break; + case 7: + chip_diff_trim_value = 1036; + break; + case 8: + chip_diff_trim_value = 1041; + break; + case 9: + chip_diff_trim_value = 1047; + break; + case 10: + chip_diff_trim_value = 1052; + break; + case 11: + chip_diff_trim_value = 1058; + break; + case 12: + chip_diff_trim_value = 1063; + break; + case 13: + chip_diff_trim_value = 1069; + break; + case 14: + chip_diff_trim_value = 1075; + break; + case 15: + chip_diff_trim_value = 1081; + break; + case 31: + chip_diff_trim_value = 995; + break; + case 30: + chip_diff_trim_value = 990; + break; + case 29: + chip_diff_trim_value = 985; + break; + case 28: + chip_diff_trim_value = 980; + break; + case 27: + chip_diff_trim_value = 975; + break; + case 26: + chip_diff_trim_value = 970; + break; + case 25: + chip_diff_trim_value = 966; + break; + case 24: + chip_diff_trim_value = 961; + break; + case 23: + chip_diff_trim_value = 956; + break; + case 22: + chip_diff_trim_value = 952; + break; + case 21: + chip_diff_trim_value = 947; + break; + case 20: + chip_diff_trim_value = 943; + break; + case 19: + chip_diff_trim_value = 938; + break; + case 18: + chip_diff_trim_value = 934; + break; + case 17: + chip_diff_trim_value = 930; + break; + default: + bm_print(BM_LOG_FULL, "[Chip_Trim] Invalid value(%d)\n", + chip_diff_trim_value_4_0); + break; + } + + bm_print(BM_LOG_CRTI, "[Chip_Trim] chip_diff_trim_value=%d\n", chip_diff_trim_value); +#endif +} + +signed int use_chip_trim_value(signed int not_trim_val) +{ +#if defined(CONFIG_POWER_EXT) + return not_trim_val; +#else + signed int ret_val = 0; + + ret_val = ((not_trim_val * chip_diff_trim_value) / 1000); + + bm_print(BM_LOG_FULL, "[use_chip_trim_value] %d -> %d\n", not_trim_val, ret_val); + + return ret_val; +#endif +} + +int get_hw_ocv(void) +{ +#if defined(CONFIG_POWER_EXT) + return 4001; + bm_print(BM_LOG_CRTI, "[get_hw_ocv] TBD\n"); +#else + signed int adc_result_reg = 0; + signed int adc_result = 0; + signed int r_val_temp = 3; /*MT6325 use 2, old chip use 4 */ + int reg_sel; +#if defined(SWCHR_POWER_PATH) + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + adc_result_reg = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR); + reg_sel = pmic_get_register_value(PMIC_RG_STRUP_AUXADC_START_SEL); + #else + adc_result_reg = pmic_get_register_value(MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR); + reg_sel = pmic_get_register_value(MT6351_PMIC_STRUP_AUXADC_START_SEL); + #endif + /*mt6325_upmu_get_rg_adc_out_wakeup_swchr(); */ + adc_result = (adc_result_reg * r_val_temp * VOLTAGE_FULL_RANGE) / ADC_PRECISE; + bm_err("[oam] get_hw_ocv (swchr) : adc_result_reg=%d, adc_result=%d, start_sel=%d\n", + adc_result_reg, adc_result, reg_sel); +#else + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + adc_result_reg = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR); + reg_sel = pmic_get_register_value(PMIC_RG_STRUP_AUXADC_START_SEL); + #else + adc_result_reg = pmic_get_register_value(MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR); + reg_sel = pmic_get_register_value(MT6351_PMIC_STRUP_AUXADC_START_SEL); + #endif + /*mt6325_upmu_get_rg_adc_out_wakeup_pchr(); */ + adc_result = (adc_result_reg * r_val_temp * VOLTAGE_FULL_RANGE) / ADC_PRECISE; + bm_err("[oam] get_hw_ocv (pchr) : adc_result_reg=%d, adc_result=%d, start_sel=%d\n", + adc_result_reg, adc_result, reg_sel); +#endif + adc_result += g_hw_ocv_tune_value; + return adc_result; +#endif +} + + +/*============================================================//*/ + +#if defined(CONFIG_POWER_EXT) + /**/ +#else + +static void dump_nter(void) +{ + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + bm_print(BM_LOG_CRTI, "[dump_nter] upmu_get_fg_nter_29_16 = 0x%x\r\n", + pmic_get_register_value(PMIC_FG_NTER_32_17)); + bm_print(BM_LOG_CRTI, "[dump_nter] upmu_get_fg_nter_15_00 = 0x%x\r\n", + pmic_get_register_value(PMIC_FG_CAR_18_03)); + #else + bm_print(BM_LOG_CRTI, "[dump_nter] MT6351_upmu_get_fg_nter_29_16 = 0x%x\r\n", + pmic_get_register_value(MT6351_PMIC_FG_NTER_32_17)); + bm_print(BM_LOG_CRTI, "[dump_nter] MT6351_upmu_get_fg_nter_15_00 = 0x%x\r\n", + pmic_get_register_value(MT6351_PMIC_FG_CAR_18_03)); + #endif +} + +static void dump_car(void) +{ + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + bm_print(BM_LOG_CRTI, "[dump_car] upmu_get_fg_car_31_16 = 0x%x\r\n", + pmic_get_register_value(PMIC_FG_CAR_34_19)); + bm_print(BM_LOG_CRTI, "[dump_car] upmu_get_fg_car_15_00 = 0x%x\r\n", + pmic_get_register_value(PMIC_FG_CAR_18_03)); + #else + bm_print(BM_LOG_CRTI, "[dump_car] upmu_get_fg_car_31_16 = 0x%x\r\n", + pmic_get_register_value(MT6351_PMIC_FG_CAR_34_19)); + bm_print(BM_LOG_CRTI, "[dump_car] upmu_get_fg_car_15_00 = 0x%x\r\n", + pmic_get_register_value(MT6351_PMIC_FG_CAR_18_03)); + #endif +} + +static unsigned int fg_get_data_ready_status(void) +{ + unsigned int ret = 0; + unsigned int temp_val = 0; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + ret = pmic_read_interface(PMIC_FG_LATCHDATA_ST, &temp_val, 0xFFFF, 0x0); + + bm_print(BM_LOG_FULL, "[fg_get_data_ready_status] Reg[0x%x]=0x%x\r\n", PMIC_FG_LATCHDATA_ST, + temp_val); + + temp_val = + (temp_val & (PMIC_FG_LATCHDATA_ST_MASK << PMIC_FG_LATCHDATA_ST_SHIFT)) + >> PMIC_FG_LATCHDATA_ST_SHIFT; +#else + ret = pmic_read_interface(MT6351_PMIC_FG_LATCHDATA_ST_ADDR, &temp_val, 0xFFFF, 0x0); + + bm_print(BM_LOG_FULL, "[fg_get_data_ready_status] Reg[0x%x]=0x%x\r\n", MT6351_PMIC_FG_LATCHDATA_ST_ADDR, + temp_val); + + temp_val = + (temp_val & (MT6351_PMIC_FG_LATCHDATA_ST_MASK << MT6351_PMIC_FG_LATCHDATA_ST_SHIFT)) + >> MT6351_PMIC_FG_LATCHDATA_ST_SHIFT; +#endif + + return temp_val; +} +#endif + +static signed int fgauge_read_current(void *data); +static signed int fgauge_initialization(void *data) +{ +#if defined(CONFIG_POWER_EXT) + /* */ +#else +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#else + unsigned int ret = 0; +#endif + signed int current_temp = 0; + int m = 0; + + get_hw_chip_diff_trim_value(); + + /* 1. HW initialization + * FGADC clock is 32768Hz from RTC + * Enable FGADC in current mode at 32768Hz with auto-calibration + * (1) Enable VA2 + * (2) Enable FGADC clock for digital + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_FGADC_ANA_CK_PDN, 0); + /* mt6325_upmu_set_rg_fgadc_ana_ck_pdn(0);*/ + pmic_set_register_value(PMIC_CLK_FGADC_DIG_CK_PDN, 0); + /* mt6325_upmu_set_rg_fgadc_dig_ck_pdn(0);*/ + +#else + pmic_set_register_value(MT6351_PMIC_RG_FGADC_ANA_CK_PDN, 0); + /* mt6325_upmu_set_rg_fgadc_ana_ck_pdn(0);*/ + pmic_set_register_value(MT6351_PMIC_RG_FGADC_DIG_CK_PDN, 0); + /* mt6325_upmu_set_rg_fgadc_dig_ck_pdn(0);*/ +#endif + /*(3) Set current mode, auto-calibration mode and 32KHz clock source */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_CAL, 0x2); + pmic_set_register_value(PMIC_FG_AUTOCALRATE, 0x2); + pmic_set_register_value(PMIC_FG_ON, 0x0); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0028, 0x00FF, 0x0); +#endif + /*(4) Enable FGADC */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_CAL, 0x2); + pmic_set_register_value(PMIC_FG_AUTOCALRATE, 0x2); + pmic_set_register_value(PMIC_FG_ON, 0x1); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0029, 0x00FF, 0x0); +#endif + + /*reset HW FG */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x1); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x1); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x1); + pmic_set_register_value(PMIC_FG_SW_CR, 0x1); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x7100, 0xFF00, 0x0); +#endif + bm_print(BM_LOG_CRTI, "******** [fgauge_initialization] reset HW FG!\n"); + + /*set FG_OSR */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_OSR, 0x8); + bm_print(BM_LOG_CRTI, "[fgauge_initialization] Reg[0x%x]=0x%x\n", PMIC_FG_OSR_ADDR, + upmu_get_reg_value(PMIC_FG_OSR_ADDR)); +#else + pmic_set_register_value(MT6351_PMIC_FG_OSR, 0x8); + bm_print(BM_LOG_CRTI, "[fgauge_initialization] Reg[0x%x]=0x%x\n", MT6351_PMIC_FG_OSR_ADDR, + upmu_get_reg_value(MT6351_PMIC_FG_OSR_ADDR)); +#endif + + /*make sure init finish */ + m = 0; + while (current_temp == 0) { + fgauge_read_current(¤t_temp); + m++; + if (m > 1000) { + bm_print(BM_LOG_CRTI, "[fgauge_initialization] timeout!\r\n"); + break; + } + } + + bm_print(BM_LOG_CRTI, "******** [fgauge_initialization] Done!\n"); +#endif + + return STATUS_OK; +} + +static signed int fgauge_read_current(void *data) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 0; +#else + unsigned short uvalue16 = 0; + signed int dvalue = 0; + int m = 0; + long long Temp_Value = 0; + signed int Current_Compensate_Value = 0; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#else + unsigned int ret = 0; +#endif + + /* HW Init + * (1) i2c_write (0x60, 0xC8, 0x01); // Enable VA2 + * (2) i2c_write (0x61, 0x15, 0x00); // Enable FGADC clock for digital + * (3) i2c_write (0x61, 0x69, 0x28); // Set current mode, auto-calibration mode and 32KHz clock source + * (4) i2c_write (0x61, 0x69, 0x29); // Enable FGADC + + * Read HW Raw Data + * (1) Set READ command + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_SW_CR, 0x0); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x1); + pmic_set_register_value(PMIC_FG_LATCHDATA_ST, 0x0); + pmic_set_register_value(PMIC_FG_SW_CLEAR, 0x0); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x0); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x0); + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x0); + pmic_set_register_value(PMIC_FG_SW_RSTCLR, 0x0); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0200, 0xFF00, 0x0); +#endif + /* (2) Keep i2c read when status = 1 (0x06) */ + m = 0; + while (fg_get_data_ready_status() == 0) { + m++; + if (m > 1000) { + bm_print(BM_LOG_FULL, + "[fgauge_read_current] fg_get_data_ready_status timeout 1 !\r\n"); + break; + } + } + /* + * (3) Read FG_CURRENT_OUT[15:08] + * (4) Read FG_CURRENT_OUT[07:00] + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + uvalue16 = pmic_get_register_value(PMIC_FG_CURRENT_OUT); /*mt6325_upmu_get_fg_current_out(); */ + +#else + uvalue16 = pmic_get_register_value(MT6351_PMIC_FG_CURRENT_OUT); /*mt6325_upmu_get_fg_current_out(); */ +#endif + bm_print(BM_LOG_FULL, "[fgauge_read_current] : FG_CURRENT = %x\r\n", uvalue16); + /* + * (5) (Read other data) + * (6) Clear status to 0 + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_SW_CLEAR, 0x1); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x0); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0800, 0xFF00, 0x0); +#endif + /* + * (7) Keep i2c read when status = 0 (0x08) + * while ( fg_get_sw_clear_status() != 0 ) + */ + m = 0; + while (fg_get_data_ready_status() != 0) { + m++; + if (m > 1000) { + bm_print(BM_LOG_FULL, + "[fgauge_read_current] fg_get_data_ready_status timeout 2 !\r\n"); + break; + } + } + /*(8) Recover original settings */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_SW_CR, 0x0); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x0); + pmic_set_register_value(PMIC_FG_LATCHDATA_ST, 0x0); + pmic_set_register_value(PMIC_FG_SW_CLEAR, 0x0); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x0); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x0); + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x0); + pmic_set_register_value(PMIC_FG_SW_RSTCLR, 0x0); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0000, 0xFF00, 0x0); +#endif + + /*calculate the real world data */ + dvalue = (unsigned int) uvalue16; + if (dvalue == 0) { + Temp_Value = (long long) dvalue; + g_fg_is_charging = KAL_FALSE; + } else if (dvalue > 32767) { + /* > 0x8000 */ + Temp_Value = (long long) (dvalue - 65535); + Temp_Value = Temp_Value - (Temp_Value * 2); + g_fg_is_charging = KAL_FALSE; + } else { + Temp_Value = (long long) dvalue; + g_fg_is_charging = KAL_TRUE; + } + + Temp_Value = Temp_Value * UNIT_FGCURRENT; + do_div(Temp_Value, 100000); + dvalue = (unsigned int) Temp_Value; + + if (g_fg_is_charging == KAL_TRUE) + bm_print(BM_LOG_FULL, "[fgauge_read_current] current(charging) = %d mA\r\n", + dvalue); + else + bm_print(BM_LOG_FULL, "[fgauge_read_current] current(discharging) = %d mA\r\n", + dvalue); + + /* Auto adjust value */ + if (batt_meter_cust_data.r_fg_value != 20) { + bm_print(BM_LOG_FULL, + "[fgauge_read_current] Auto adjust value due to the Rfg is %d\n Ori current=%d, ", + batt_meter_cust_data.r_fg_value, dvalue); + + dvalue = (dvalue * 20) / batt_meter_cust_data.r_fg_value; + + bm_print(BM_LOG_FULL, "[fgauge_read_current] new current=%d\n", dvalue); + } + + /* K current */ + if (batt_meter_cust_data.r_fg_board_slope != batt_meter_cust_data.r_fg_board_base) + dvalue = + ((dvalue * batt_meter_cust_data.r_fg_board_base) + + (batt_meter_cust_data.r_fg_board_slope / 2)) / + batt_meter_cust_data.r_fg_board_slope; + + /* current compensate */ + if (g_fg_is_charging == KAL_TRUE) + dvalue = dvalue + Current_Compensate_Value; + else + dvalue = dvalue - Current_Compensate_Value; + + + bm_print(BM_LOG_FULL, "[fgauge_read_current] ori current=%d\n", dvalue); + + dvalue = ((dvalue * batt_meter_cust_data.car_tune_value) / 100); + + dvalue = use_chip_trim_value(dvalue); + + bm_print(BM_LOG_FULL, "[fgauge_read_current] final current=%d (ratio=%d)\n", + dvalue, batt_meter_cust_data.car_tune_value); + + *(signed int *) (data) = dvalue; +#endif + + return STATUS_OK; + } + + + +signed int fgauge_read_IM_current(void *data) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 0; +#else + unsigned short uvalue16 = 0; + signed int dvalue = 0; + /*int m = 0;*/ + long long Temp_Value = 0; + signed int Current_Compensate_Value = 0; + /*unsigned int ret = 0;*/ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + uvalue16 = pmic_get_register_value(PMIC_FG_R_CURR); +#else + uvalue16 = pmic_get_register_value(MT6351_PMIC_FG_R_CURR); +#endif + + bm_print(BM_LOG_FULL, "[fgauge_read_IM_current] : FG_CURRENT = %x\r\n", + uvalue16); + + /*calculate the real world data */ + dvalue = (unsigned int) uvalue16; + if (dvalue == 0) { + Temp_Value = (long long) dvalue; + g_fg_is_charging = KAL_FALSE; + } else if (dvalue > 32767) { + /* > 0x8000 */ + Temp_Value = (long long) (dvalue - 65535); + Temp_Value = Temp_Value - (Temp_Value * 2); + g_fg_is_charging = KAL_FALSE; + } else { + Temp_Value = (long long) dvalue; + g_fg_is_charging = KAL_TRUE; + } + + Temp_Value = Temp_Value * UNIT_FGCURRENT; + do_div(Temp_Value, 100000); + dvalue = (unsigned int) Temp_Value; + + if (g_fg_is_charging == KAL_TRUE) + bm_print(BM_LOG_FULL, + "[fgauge_read_IM_current] current(charging) = %d mA\r\n", + dvalue); + else + bm_print(BM_LOG_FULL, + "[fgauge_read_IM_current] current(discharging) = %d mA\r\n", + dvalue); + + /* Auto adjust value */ + if (batt_meter_cust_data.r_fg_value != 20) { + bm_print(BM_LOG_FULL, + "[fgauge_read_IM_current] Auto adjust value due to the Rfg is %d\n Ori current=%d, ", + batt_meter_cust_data.r_fg_value, dvalue); + + dvalue = (dvalue * 20) / batt_meter_cust_data.r_fg_value; + + bm_print(BM_LOG_FULL, "[fgauge_read_IM_current] new current=%d\n", + dvalue); + } + + /* K current */ + if (batt_meter_cust_data.r_fg_board_slope != batt_meter_cust_data.r_fg_board_base) + dvalue = + ((dvalue * batt_meter_cust_data.r_fg_board_base) + + (batt_meter_cust_data.r_fg_board_slope / 2)) / + batt_meter_cust_data.r_fg_board_slope; + + /* current compensate */ + if (g_fg_is_charging == KAL_TRUE) + dvalue = dvalue + Current_Compensate_Value; + else + dvalue = dvalue - Current_Compensate_Value; + + bm_print(BM_LOG_FULL, "[fgauge_read_IM_current] ori current=%d\n", dvalue); + + dvalue = ((dvalue * batt_meter_cust_data.car_tune_value) / 100); + + dvalue = use_chip_trim_value(dvalue); + + bm_print(BM_LOG_FULL, "[fgauge_read_IM_current] final current=%d (ratio=%d)\n", + dvalue, batt_meter_cust_data.car_tune_value); + + *(signed int *) (data) = dvalue; +#endif + + return STATUS_OK; +} + + +static signed int fgauge_read_current_sign(void *data) +{ + *(kal_bool *) (data) = g_fg_is_charging; + + return STATUS_OK; +} + +static signed int fgauge_read_columb(void *data); + +signed int fgauge_set_columb_interrupt_internal(void *data, int reset) +{ +#if defined(CONFIG_POWER_EXT) + return STATUS_OK; +#else + + unsigned int uvalue32_CAR = 0; + unsigned int uvalue32_CAR_MSB = 0; + signed int upperbound = 0, lowbound = 0; + + signed short m; + unsigned int car = *(unsigned int *) (data); +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#else + unsigned int ret = 0; +#endif + signed int value32_CAR; + + bm_print(BM_LOG_FULL, "fgauge_set_columb_interrupt_internal car=%d\n", car); + + + if (car == 0) { +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_RG_INT_EN_FG_BAT_H, 0); + pmic_set_register_value(PMIC_RG_INT_EN_FG_BAT_L, 0); + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] low:[0xcae]=0x%x 0x%x high:[0xcb0]=0x%x 0x%x now:0x%x 0x%x %d %d \r\n", + pmic_get_register_value(PMIC_FG_BLTR_15_00), + pmic_get_register_value(PMIC_FG_BLTR_31_16), + pmic_get_register_value(PMIC_FG_BFTR_15_00), + pmic_get_register_value(PMIC_FG_BFTR_31_16), + pmic_get_register_value(PMIC_FG_CAR_18_03), + pmic_get_register_value(PMIC_FG_CAR_34_19), + pmic_get_register_value(PMIC_RG_INT_EN_FG_BAT_L), + pmic_get_register_value(PMIC_RG_INT_EN_FG_BAT_H)); + +#else + pmic_set_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H, 0); + pmic_set_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_L, 0); + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] low:[0xcae]=0x%x 0x%x high:[0xcb0]=0x%x 0x%x now:0x%x 0x%x %d %d \r\n", + pmic_get_register_value(MT6351_PMIC_FG_BLTR_15_00), + pmic_get_register_value(MT6351_PMIC_FG_BLTR_31_16), + pmic_get_register_value(MT6351_PMIC_FG_BFTR_15_00), + pmic_get_register_value(MT6351_PMIC_FG_BFTR_31_16), + pmic_get_register_value(MT6351_PMIC_FG_CAR_18_03), + pmic_get_register_value(MT6351_PMIC_FG_CAR_34_19), + pmic_get_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_L), + pmic_get_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H)); +#endif + return STATUS_OK; + } + + if (car == 0x1ffff) { +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_RG_INT_EN_FG_BAT_H, 1); + pmic_set_register_value(PMIC_RG_INT_EN_FG_BAT_L, 1); + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] low:[0xcae]=0x%x 0x%x high:[0xcb0]=0x%x 0x%x now:0x%x 0x%x %d %d \r\n", + pmic_get_register_value(PMIC_FG_BLTR_15_00), + pmic_get_register_value(PMIC_FG_BLTR_31_16), + pmic_get_register_value(PMIC_FG_BFTR_15_00), + pmic_get_register_value(PMIC_FG_BFTR_31_16), + pmic_get_register_value(PMIC_FG_CAR_18_03), + pmic_get_register_value(PMIC_FG_CAR_34_19), + pmic_get_register_value(PMIC_RG_INT_EN_FG_BAT_L), + pmic_get_register_value(PMIC_RG_INT_EN_FG_BAT_H)); + +#else + pmic_set_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H, 1); + pmic_set_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_L, 1); + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] low:[0xcae]=0x%x 0x%x high:[0xcb0]=0x%x 0x%x now:0x%x 0x%x %d %d \r\n", + pmic_get_register_value(MT6351_PMIC_FG_BLTR_15_00), + pmic_get_register_value(MT6351_PMIC_FG_BLTR_31_16), + pmic_get_register_value(MT6351_PMIC_FG_BFTR_15_00), + pmic_get_register_value(MT6351_PMIC_FG_BFTR_31_16), + pmic_get_register_value(MT6351_PMIC_FG_CAR_18_03), + pmic_get_register_value(MT6351_PMIC_FG_CAR_34_19), + pmic_get_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_L), + pmic_get_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H)); +#endif + return STATUS_OK; + } + +/* + * HW Init + * (1) i2c_write (0x60, 0xC8, 0x01); // Enable VA2 + * (2) i2c_write (0x61, 0x15, 0x00); // Enable FGADC clock for digital + * (3) i2c_write (0x61, 0x69, 0x28); // Set current mode, auto-calibration mode and 32KHz clock source + * (4) i2c_write (0x61, 0x69, 0x29); // Enable FGADC + + * Read HW Raw Data + * (1) Set READ command + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (reset == 0) { + pmic_set_register_value(PMIC_FG_SW_CR, 0x0); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x1); + pmic_set_register_value(PMIC_FG_LATCHDATA_ST, 0x0); + pmic_set_register_value(PMIC_FG_SW_CLEAR, 0x0); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x0); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x0); + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x0); + pmic_set_register_value(PMIC_FG_SW_RSTCLR, 0x0); + } else { + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x1); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x1); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x1); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x1); + pmic_set_register_value(PMIC_FG_SW_CR, 0x1); + } +#else + if (reset == 0) + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0200, 0xFF00, 0x0); + else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x7300, 0xFF00, 0x0); +#endif + /*(2) Keep i2c read when status = 1 (0x06) */ + m = 0; + while (fg_get_data_ready_status() == 0) { + m++; + if (m > 1000) { + bm_print(BM_LOG_FULL, + "[fgauge_set_columb_interrupt] fg_get_data_ready_status timeout 1 !"); + break; + } + } +/* + * (3) Read FG_CURRENT_OUT[28:14] + * (4) Read FG_CURRENT_OUT[31] + */ + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + value32_CAR = (pmic_get_register_value(PMIC_FG_CAR_18_03)); + value32_CAR |= ((pmic_get_register_value(PMIC_FG_CAR_34_19)) & 0xffff) << 16; + + uvalue32_CAR_MSB = (pmic_get_register_value(PMIC_FG_CAR_34_19) & 0x8000) >> 15; + + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] FG_CAR = 0x%x uvalue32_CAR_MSB:0x%x 0x%x 0x%x\r\n", + uvalue32_CAR, uvalue32_CAR_MSB, (pmic_get_register_value(PMIC_FG_CAR_18_03)), + (pmic_get_register_value(PMIC_FG_CAR_34_19))); + + #else + value32_CAR = (pmic_get_register_value(MT6351_PMIC_FG_CAR_18_03)); + value32_CAR |= ((pmic_get_register_value(MT6351_PMIC_FG_CAR_34_19)) & 0xffff) << 16; + + uvalue32_CAR_MSB = (pmic_get_register_value(MT6351_PMIC_FG_CAR_34_19) & 0x8000) >> 15; + + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] FG_CAR = 0x%x uvalue32_CAR_MSB:0x%x 0x%x 0x%x\r\n", + uvalue32_CAR, uvalue32_CAR_MSB, (pmic_get_register_value(MT6351_PMIC_FG_CAR_18_03)), + (pmic_get_register_value(MT6351_PMIC_FG_CAR_34_19))); + #endif + + /*restore use_chip_trim_value() */ + car = car * 0x4d14; + + upperbound = value32_CAR; + lowbound = value32_CAR; + + + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] upper = 0x%x:%d low=0x%x:%d car=0x%x:%d\r\n", + upperbound, upperbound, lowbound, lowbound, car, car); + + upperbound = upperbound + car; + lowbound = lowbound - car; + + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt]final upper = 0x%x:%d low=0x%x:%d car=0x%x:%d\r\n", + upperbound, upperbound, lowbound, lowbound, car, car); +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_BLTR_15_00, lowbound & 0xffff); + pmic_set_register_value(PMIC_FG_BLTR_31_16, (lowbound & 0xffff0000) >> 16); + pmic_set_register_value(PMIC_FG_BFTR_15_00, upperbound & 0xffff); + pmic_set_register_value(PMIC_FG_BFTR_31_16, (upperbound & 0xffff0000) >> 16); + mdelay(1); + pmic_set_register_value(PMIC_RG_INT_EN_FG_BAT_H, 1); + pmic_set_register_value(PMIC_RG_INT_EN_FG_BAT_L, 1); + + + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] low:[0xcae]=0x%x 0x%x high:[0xcb0]=0x%x 0x%x\r\n", + pmic_get_register_value(PMIC_FG_BLTR_15_00), pmic_get_register_value(PMIC_FG_BLTR_31_16), + pmic_get_register_value(PMIC_FG_BFTR_15_00), pmic_get_register_value(PMIC_FG_BFTR_31_16)); + +#else + pmic_set_register_value(MT6351_PMIC_FG_BLTR_15_00, lowbound & 0xffff); + pmic_set_register_value(MT6351_PMIC_FG_BLTR_31_16, (lowbound & 0xffff0000) >> 16); + pmic_set_register_value(MT6351_PMIC_FG_BFTR_15_00, upperbound & 0xffff); + pmic_set_register_value(MT6351_PMIC_FG_BFTR_31_16, (upperbound & 0xffff0000) >> 16); + mdelay(1); + pmic_set_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H, 1); + pmic_set_register_value(MT6351_PMIC_RG_INT_EN_FG_BAT_L, 1); + + + bm_print(BM_LOG_CRTI, + "[fgauge_set_columb_interrupt] low:[0xcae]=0x%x 0x%x high:[0xcb0]=0x%x 0x%x\r\n", + pmic_get_register_value(MT6351_PMIC_FG_BLTR_15_00), + pmic_get_register_value(MT6351_PMIC_FG_BLTR_31_16), + pmic_get_register_value(MT6351_PMIC_FG_BFTR_15_00), + pmic_get_register_value(MT6351_PMIC_FG_BFTR_31_16)); +#endif + + return STATUS_OK; +#endif + +} + + +static signed int fgauge_set_columb_interrupt(void *data) +{ + return fgauge_set_columb_interrupt_internal(data, 0); +} + +static signed int fgauge_read_columb_internal(void *data, int reset, int precise) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 0; +#else + unsigned int uvalue32_CAR = 0; + unsigned int uvalue32_CAR_MSB = 0; + signed int dvalue_CAR = 0; + int m = 0; + long long Temp_Value = 0; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#else + unsigned int ret = 0; +#endif +/* + * HW Init + * (1) i2c_write (0x60, 0xC8, 0x01); // Enable VA2 + * (2) i2c_write (0x61, 0x15, 0x00); // Enable FGADC clock for digital + * (3) i2c_write (0x61, 0x69, 0x28); // Set current mode, auto-calibration mode and 32KHz clock source + * (4) i2c_write (0x61, 0x69, 0x29); // Enable FGADC + + * Read HW Raw Data + * (1) Set READ command + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + if (reset == 0) { + pmic_set_register_value(PMIC_FG_SW_CR, 0x0); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x1); + pmic_set_register_value(PMIC_FG_LATCHDATA_ST, 0x0); + pmic_set_register_value(PMIC_FG_SW_CLEAR, 0x0); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x0); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x0); + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x0); + pmic_set_register_value(PMIC_FG_SW_RSTCLR, 0x0); + } else { + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x1); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x1); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x1); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x1); + pmic_set_register_value(PMIC_FG_SW_CR, 0x1); + } +#else + if (reset == 0) + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0200, 0xFF00, 0x0); + else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x7300, 0xFF00, 0x0); +#endif + + /*(2) Keep i2c read when status = 1 (0x06) */ + m = 0; + while (fg_get_data_ready_status() == 0) { + m++; + if (m > 1000) { + bm_print(BM_LOG_FULL, + "[fgauge_read_columb_internal] fg_get_data_ready_status timeout 1 !\r\n"); + break; + } + } +/* + * (3) Read FG_CURRENT_OUT[28:14] + * (4) Read FG_CURRENT_OUT[31] + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + uvalue32_CAR = (pmic_get_register_value(PMIC_FG_CAR_18_03)) >> 11; + uvalue32_CAR |= ((pmic_get_register_value(PMIC_FG_CAR_34_19)) & 0x0FFF) << 5; + + uvalue32_CAR_MSB = (pmic_get_register_value(PMIC_FG_CAR_34_19) & 0x8000) >> 15; +#else + uvalue32_CAR = (pmic_get_register_value(MT6351_PMIC_FG_CAR_18_03)) >> 11; + uvalue32_CAR |= ((pmic_get_register_value(MT6351_PMIC_FG_CAR_34_19)) & 0x0FFF) << 5; + + uvalue32_CAR_MSB = (pmic_get_register_value(MT6351_PMIC_FG_CAR_34_19) & 0x8000) >> 15; +#endif + + bm_print(BM_LOG_FULL, "[fgauge_read_columb_internal] FG_CAR = 0x%x\r\n", + uvalue32_CAR); + bm_print(BM_LOG_FULL, + "[fgauge_read_columb_internal] uvalue32_CAR_MSB = 0x%x\r\n", + uvalue32_CAR_MSB); +/* + * (5) (Read other data) + * (6) Clear status to 0 + */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_SW_CR, 0x0); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x0); + pmic_set_register_value(PMIC_FG_LATCHDATA_ST, 0x0); + pmic_set_register_value(PMIC_FG_SW_CLEAR, 0x1); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x0); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x0); + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x0); + pmic_set_register_value(PMIC_FG_SW_RSTCLR, 0x0); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0800, 0xFF00, 0x0); +#endif +/* + * (7) Keep i2c read when status = 0 (0x08) + * while ( fg_get_sw_clear_status() != 0 ) + */ + m = 0; + while (fg_get_data_ready_status() != 0) { + m++; + if (m > 1000) { + bm_print(BM_LOG_FULL, + "[fgauge_read_columb_internal] fg_get_data_ready_status timeout 2 !\r\n"); + break; + } + } + /*(8) Recover original settings */ +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_SW_CR, 0x0); + pmic_set_register_value(PMIC_FG_SW_READ_PRE, 0x0); + pmic_set_register_value(PMIC_FG_LATCHDATA_ST, 0x0); + pmic_set_register_value(PMIC_FG_SW_CLEAR, 0x0); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x0); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x0); + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x0); + pmic_set_register_value(PMIC_FG_SW_RSTCLR, 0x0); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x0000, 0xFF00, 0x0); +#endif + +/*calculate the real world data */ + dvalue_CAR = (signed int) uvalue32_CAR; + + if (uvalue32_CAR == 0) { + Temp_Value = 0; + } else if (uvalue32_CAR == 0x1ffff) { + Temp_Value = 0; + } else if (uvalue32_CAR_MSB == 0x1) { + /* dis-charging */ + Temp_Value = (long long) (dvalue_CAR - 0x1ffff); /* keep negative value */ + Temp_Value = Temp_Value - (Temp_Value * 2); + } else { + /*charging */ + Temp_Value = (long long) dvalue_CAR; + } + +#if 0 + Temp_Value = (((Temp_Value * 35986) / 10) + (5)) / 10; /*[28:14]'s LSB=359.86 uAh */ +#else + Temp_Value = Temp_Value * 35986; + do_div(Temp_Value, 10); + Temp_Value = Temp_Value + 5; + do_div(Temp_Value, 10); +#endif + +#if 0 + dvalue_CAR = Temp_Value / 1000; /*mAh */ +#else + /*dvalue_CAR = (Temp_Value/8)/1000; mAh, due to FG_OSR=0x8*/ + if (precise == 0) { + do_div(Temp_Value, 8); + do_div(Temp_Value, 1000); + } else { + do_div(Temp_Value, 8); + do_div(Temp_Value, 100); + } + + if (uvalue32_CAR_MSB == 0x1) + dvalue_CAR = (signed int) (Temp_Value - (Temp_Value * 2)); /* keep negative value */ + else + dvalue_CAR = (signed int) Temp_Value; +#endif + + bm_print(BM_LOG_FULL, "[fgauge_read_columb_internal] dvalue_CAR = %d\r\n", + dvalue_CAR); + + /*#if (OSR_SELECT_7 == 1) */ + + + +/*Auto adjust value*/ + if (batt_meter_cust_data.r_fg_value != 20) { + bm_print(BM_LOG_FULL, + "[fgauge_read_columb_internal] Auto adjust value deu to the Rfg is %d\n Ori CAR=%d, ", + batt_meter_cust_data.r_fg_value, dvalue_CAR); + + dvalue_CAR = (dvalue_CAR * 20) / batt_meter_cust_data.r_fg_value; + + bm_print(BM_LOG_FULL, "[fgauge_read_columb_internal] new CAR=%d\n", + dvalue_CAR); + } + + dvalue_CAR = ((dvalue_CAR * batt_meter_cust_data.car_tune_value) / 100); + + dvalue_CAR = use_chip_trim_value(dvalue_CAR); + + bm_print(BM_LOG_FULL, "[fgauge_read_columb_internal] final dvalue_CAR = %d\r\n", + dvalue_CAR); + + dump_nter(); + dump_car(); + + *(signed int *) (data) = dvalue_CAR; +#endif + + return STATUS_OK; +} + +static signed int fgauge_read_columb(void *data) +{ + return fgauge_read_columb_internal(data, 0, 0); +} + +static signed int fgauge_read_columb_accurate(void *data) +{ + +#if defined(SOC_BY_3RD_FG) + *(kal_int32 *)(data) = bq27531_get_remaincap(); + return STATUS_OK; + +#else + return fgauge_read_columb_internal(data, 0, 1); +#endif +} + + +static signed int fgauge_hw_reset(void *data) +{ +#if defined(CONFIG_POWER_EXT) + /**/ +#else + volatile unsigned int val_car = 1; + unsigned int val_car_temp = 1; +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#else + unsigned int ret = 0; +#endif + + bm_print(BM_LOG_FULL, "[fgauge_hw_reset] : Start \r\n"); + + while (val_car != 0x0) { +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_FG_CHARGE_RST, 0x1); + pmic_set_register_value(PMIC_FG_TIME_RST, 0x1); + pmic_set_register_value(PMIC_FG_OFFSET_RST, 0x1); + pmic_set_register_value(PMIC_FG_SW_CR, 0x1); +#else + ret = pmic_config_interface(MT6351_FGADC_CON0, 0x7100, 0xFF00, 0x0); +#endif + fgauge_read_columb_internal(&val_car_temp, 1, 0); + val_car = val_car_temp; + bm_print(BM_LOG_FULL, "#"); + } + + bm_print(BM_LOG_FULL, "[fgauge_hw_reset] : End \r\n"); +#endif + + return STATUS_OK; +} + +static signed int read_adc_v_bat_sense(void *data) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 4201; +#else +#if defined(SWCHR_POWER_PATH) + *(signed int *) (data) = + PMIC_IMM_GetOneChannelValue(PMIC_AUX_ISENSE_AP, *(signed int *) (data), 1); +#else + *(signed int *) (data) = + PMIC_IMM_GetOneChannelValue(PMIC_AUX_BATSNS_AP, *(signed int *) (data), 1); +#endif +#endif + + return STATUS_OK; +} + + + +static signed int read_adc_v_i_sense(void *data) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 4202; +#else +#if defined(SWCHR_POWER_PATH) + *(signed int *) (data) = + PMIC_IMM_GetOneChannelValue(PMIC_AUX_BATSNS_AP, *(signed int *) (data), 1); +#else + *(signed int *) (data) = + PMIC_IMM_GetOneChannelValue(PMIC_AUX_ISENSE_AP, *(signed int *) (data), 1); +#endif +#endif + + return STATUS_OK; +} + +static signed int read_adc_v_bat_temp(void *data) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 0; +#else +#if defined(MTK_PCB_TBAT_FEATURE) + /* no HW support */ +#else + bm_print(BM_LOG_FULL, + "[read_adc_v_bat_temp] return PMIC_IMM_GetOneChannelValue(4,times,1);\n"); + *(signed int *) (data) = + PMIC_IMM_GetOneChannelValue(PMIC_AUX_BATON_AP, *(signed int *) (data), 1); +#endif +#endif + + return STATUS_OK; +} + +static signed int read_adc_v_charger(void *data) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 5001; +#else + signed int val; + + val = PMIC_IMM_GetOneChannelValue(PMIC_AUX_VCDT_AP, *(signed int *) (data), 1); + val = + (((batt_meter_cust_data.r_charger_1 + + batt_meter_cust_data.r_charger_2) * 100 * val) / + batt_meter_cust_data.r_charger_2) / 100; + *(signed int *) (data) = val; +#endif + + return STATUS_OK; +} + +static signed int read_hw_ocv(void *data) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 3999; +#else +#if 0 + *(signed int *) (data) = PMIC_IMM_GetOneChannelValue(AUX_BATSNS_AP, 5, 1); + bm_print(BM_LOG_CRTI, "[read_hw_ocv] By SW AUXADC for bring up\n"); +#else + *(signed int *) (data) = get_hw_ocv(); +#endif +#endif + + return STATUS_OK; +} + +static signed int read_is_hw_ocv_ready(void *data) +{ +#if defined(CONFIG_POWER_EXT) + *(signed int *) (data) = 0; +#else +#if defined(SWCHR_POWER_PATH) + *(signed int *) (data) = pmic_get_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR); + bm_err("[read_is_hw_ocv_ready] is_hw_ocv_ready(SWCHR) %d\n", *(signed int *) (data)); + pmic_set_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, 1); + mdelay(1); + pmic_set_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, 0); +#else + *(signed int *) (data) = pmic_get_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR); + bm_err("[read_is_hw_ocv_ready] is_hw_ocv_ready(PCHR) %d\n", *(signed int *) (data)); + pmic_set_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, 1); + mdelay(1); + pmic_set_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, 0); +#endif +#endif + + return STATUS_OK; +} + +static signed int dump_register_fgadc(void *data) +{ + return STATUS_OK; +} + +static signed int read_battery_plug_out_status(void *data) +{ + *(signed int *)(data) = is_battery_remove_pmic(); + + return STATUS_OK; +} + + +static signed int(*bm_func[BATTERY_METER_CMD_NUMBER]) (void *data); + +signed int bm_ctrl_cmd(BATTERY_METER_CTRL_CMD cmd, void *data) +{ + signed int status = STATUS_UNSUPPORTED; + static signed int init = -1; + + if (init == -1) { + init = 0; + bm_func[BATTERY_METER_CMD_HW_FG_INIT] = fgauge_initialization; + bm_func[BATTERY_METER_CMD_GET_HW_FG_CURRENT] = fgauge_read_current; + bm_func[BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN] = fgauge_read_current_sign; + bm_func[BATTERY_METER_CMD_GET_HW_FG_CAR] = fgauge_read_columb; + bm_func[BATTERY_METER_CMD_HW_RESET] = fgauge_hw_reset; + bm_func[BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE] = read_adc_v_bat_sense; + bm_func[BATTERY_METER_CMD_GET_ADC_V_I_SENSE] = read_adc_v_i_sense; + bm_func[BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP] = read_adc_v_bat_temp; + bm_func[BATTERY_METER_CMD_GET_ADC_V_CHARGER] = read_adc_v_charger; + bm_func[BATTERY_METER_CMD_GET_HW_OCV] = read_hw_ocv; + bm_func[BATTERY_METER_CMD_DUMP_REGISTER] = dump_register_fgadc; + bm_func[BATTERY_METER_CMD_SET_COLUMB_INTERRUPT] = fgauge_set_columb_interrupt; + bm_func[BATTERY_METER_CMD_GET_BATTERY_PLUG_STATUS] = read_battery_plug_out_status; + bm_func[BATTERY_METER_CMD_GET_HW_FG_CAR_ACT] = fgauge_read_columb_accurate; + bm_func[BATTERY_METER_CMD_GET_IS_HW_OCV_READY] = read_is_hw_ocv_ready; + } + + if (cmd < BATTERY_METER_CMD_NUMBER) { + if (bm_func[cmd] != NULL) + status = bm_func[cmd] (data); + else + status = STATUS_UNSUPPORTED; + } else + status = STATUS_UNSUPPORTED; + + return status; +} diff --git a/drivers/misc/mediatek/power/mt6755/bq24158.c b/drivers/misc/mediatek/power/mt6755/bq24158.c new file mode 100755 index 0000000000000000000000000000000000000000..7376d3818713e05ce2a9c43f3ab564ee831dc1d4 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/bq24158.c @@ -0,0 +1,729 @@ +#include +#include +#include +#include +#include +#include +#include /* For init/exit macros */ +#include /* For MODULE_ marcros */ +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include + +#include "bq24158.h" + +/********************************************************** + * + * [I2C Slave Setting] + * + *********************************************************/ +#define bq24158_SLAVE_ADDR_WRITE 0xD4 +#define bq24158_SLAVE_ADDR_Read 0xD5 + +static struct i2c_client *new_client = NULL; +static const struct i2c_device_id bq24158_i2c_id[] = {{"bq24158",0},{}}; +kal_bool chargin_hw_init_done = KAL_FALSE; +static int bq24158_driver_probe(struct i2c_client *client, const struct i2c_device_id *id); +#ifdef CONFIG_OF +static const struct of_device_id bq24158_of_match[] = { + {.compatible = "mediatek,swithing_charger",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, bq24158_of_match); +#endif + +static struct i2c_driver bq24158_driver = { + .driver = { + .name = "bq24158", +#ifdef CONFIG_OF + .of_match_table = bq24158_of_match, +#endif + + }, + .probe = bq24158_driver_probe, + .id_table = bq24158_i2c_id, +}; + +/********************************************************** + * + * [Global Variable] + * + *********************************************************/ +unsigned char bq24158_reg[bq24158_REG_NUM] = {0}; + +static DEFINE_MUTEX(bq24158_i2c_access); +/********************************************************** + * + * [I2C Function For Read/Write bq24158] + * + *********************************************************/ +int bq24158_read_byte(unsigned char cmd, unsigned char *returnData) +{ + char cmd_buf[1]={0x00}; + char readData = 0; + int ret=0; + + if (new_client == NULL) + return -1; + + mutex_lock(&bq24158_i2c_access); + + //new_client->addr = ((new_client->addr) & I2C_MASK_FLAG) | I2C_WR_FLAG; + new_client->ext_flag=((new_client->ext_flag ) & I2C_MASK_FLAG ) | I2C_WR_FLAG | I2C_DIRECTION_FLAG; + + cmd_buf[0] = cmd; + ret = i2c_master_send(new_client, &cmd_buf[0], ((1 << 8 ) | 1)); + if (ret < 0) + { + //new_client->addr = new_client->addr & I2C_MASK_FLAG; + new_client->ext_flag=0; + + mutex_unlock(&bq24158_i2c_access); + return 0; + } + + readData = cmd_buf[0]; + *returnData = readData; + + //new_client->addr = new_client->addr & I2C_MASK_FLAG; + new_client->ext_flag=0; + + mutex_unlock(&bq24158_i2c_access); + return 1; +} + +int bq24158_write_byte(unsigned char cmd, unsigned char writeData) +{ + char write_data[2] = {0}; + int ret=0; + + if (new_client == NULL) + return -1; + + mutex_lock(&bq24158_i2c_access); + + write_data[0] = cmd; + write_data[1] = writeData; + + new_client->ext_flag=((new_client->ext_flag ) & I2C_MASK_FLAG ) | I2C_DIRECTION_FLAG; + + ret = i2c_master_send(new_client, write_data, 2); + if (ret < 0) + { + + new_client->ext_flag=0; + mutex_unlock(&bq24158_i2c_access); + return 0; + } + + new_client->ext_flag=0; + mutex_unlock(&bq24158_i2c_access); + return 1; +} + +/********************************************************** + * + * [Read / Write Function] + * + *********************************************************/ +int bq24158_read_interface (unsigned char RegNum, unsigned char *val, unsigned char MASK, unsigned char SHIFT) +{ + unsigned char bq24158_reg = 0; + int ret = 0; + + battery_xlog_printk(BAT_LOG_FULL,"--------------------------------------------------\n"); + + ret = bq24158_read_byte(RegNum, &bq24158_reg); + + battery_xlog_printk(BAT_LOG_FULL,"[bq24158_read_interface] Reg[%x]=0x%x\n", RegNum, bq24158_reg); + + bq24158_reg &= (MASK << SHIFT); + *val = (bq24158_reg >> SHIFT); + + battery_xlog_printk(BAT_LOG_FULL,"[bq24158_read_interface] val=0x%x\n", *val); + + return ret; +} + +int bq24158_config_interface (unsigned char RegNum, unsigned char val, unsigned char MASK, unsigned char SHIFT) +{ + unsigned char bq24158_reg = 0; + int ret = 0; + + battery_xlog_printk(BAT_LOG_FULL,"--------------------------------------------------\n"); + + ret = bq24158_read_byte(RegNum, &bq24158_reg); + battery_xlog_printk(BAT_LOG_FULL,"[bq24158_config_interface] Reg[%x]=0x%x\n", RegNum, bq24158_reg); + + bq24158_reg &= ~(MASK << SHIFT); + bq24158_reg |= (val << SHIFT); + + if(RegNum == bq24158_CON4 && val == 1 && MASK ==CON4_RESET_MASK && SHIFT == CON4_RESET_SHIFT) + { + // RESET bit + } + else if(RegNum == bq24158_CON4) + { + bq24158_reg &= ~0x80; //RESET bit read returs 1, so clear it + } + + + ret = bq24158_write_byte(RegNum, bq24158_reg); + battery_xlog_printk(BAT_LOG_FULL,"[bq24158_config_interface] write Reg[%x]=0x%x\n", RegNum, bq24158_reg); + + // Check + //bq24158_read_byte(RegNum, &bq24158_reg); + //printk("[bq24158_config_interface] Check Reg[%x]=0x%x\n", RegNum, bq24158_reg); + + return ret; +} + +//write one register directly +int bq24158_config_interface_liao (unsigned char RegNum, unsigned char val) +{ + int ret = 0; + + ret = bq24158_write_byte(RegNum, val); + + return ret; +} + +/********************************************************** + * + * [Internal Function] + * + *********************************************************/ +//CON0---------------------------------------------------- + +void bq24158_set_tmr_rst(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON0), + (unsigned char)(val), + (unsigned char)(CON0_TMR_RST_MASK), + (unsigned char)(CON0_TMR_RST_SHIFT) + ); +} + + unsigned int bq24158_get_otg_status(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON0), + (&val), + (unsigned char)(CON0_OTG_MASK), + (unsigned char)(CON0_OTG_SHIFT) + ); + return val; +} + +void bq24158_set_en_stat(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON0), + (unsigned char)(val), + (unsigned char)(CON0_EN_STAT_MASK), + (unsigned char)(CON0_EN_STAT_SHIFT) + ); +} + +unsigned int bq24158_get_chip_status(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON0), + (&val), + (unsigned char)(CON0_STAT_MASK), + (unsigned char)(CON0_STAT_SHIFT) + ); + return val; +} + +unsigned int bq24158_get_boost_status(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON0), + (&val), + (unsigned char)(CON0_BOOST_MASK), + (unsigned char)(CON0_BOOST_SHIFT) + ); + return val; +} + +unsigned int bq24158_get_fault_status(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON0), + (&val), + (unsigned char)(CON0_FAULT_MASK), + (unsigned char)(CON0_FAULT_SHIFT) + ); + return val; +} + +//CON1---------------------------------------------------- + +void bq24158_set_input_charging_current(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON1), + (unsigned char)(val), + (unsigned char)(CON1_LIN_LIMIT_MASK), + (unsigned char)(CON1_LIN_LIMIT_SHIFT) + ); +} + +void bq24158_set_v_low(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON1), + (unsigned char)(val), + (unsigned char)(CON1_LOW_V_MASK), + (unsigned char)(CON1_LOW_V_SHIFT) + ); +} + +void bq24158_set_te(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON1), + (unsigned char)(val), + (unsigned char)(CON1_TE_MASK), + (unsigned char)(CON1_TE_SHIFT) + ); +} + +void bq24158_set_ce(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON1), + (unsigned char)(val), + (unsigned char)(CON1_CE_MASK), + (unsigned char)(CON1_CE_SHIFT) + ); +} + +void bq24158_set_hz_mode(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON1), + (unsigned char)(val), + (unsigned char)(CON1_HZ_MODE_MASK), + (unsigned char)(CON1_HZ_MODE_SHIFT) + ); +} + +void bq24158_set_opa_mode(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON1), + (unsigned char)(val), + (unsigned char)(CON1_OPA_MODE_MASK), + (unsigned char)(CON1_OPA_MODE_SHIFT) + ); +} + +//CON2---------------------------------------------------- + +void bq24158_set_oreg(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON2), + (unsigned char)(val), + (unsigned char)(CON2_OREG_MASK), + (unsigned char)(CON2_OREG_SHIFT) + ); +} + +void bq24158_set_otg_pl(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON2), + (unsigned char)(val), + (unsigned char)(CON2_OTG_PL_MASK), + (unsigned char)(CON2_OTG_PL_SHIFT) + ); +} + +void bq24158_set_otg_en(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON2), + (unsigned char)(val), + (unsigned char)(CON2_OTG_EN_MASK), + (unsigned char)(CON2_OTG_EN_SHIFT) + ); +} + +//CON3---------------------------------------------------- + +unsigned int bq24158_get_vender_code(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON3), + (&val), + (unsigned char)(CON3_VENDER_CODE_MASK), + (unsigned char)(CON3_VENDER_CODE_SHIFT) + ); + return val; +} + +unsigned int bq24158_get_pn(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON3), + (&val), + (unsigned char)(CON3_PIN_MASK), + (unsigned char)(CON3_PIN_SHIFT) + ); + return val; +} + +unsigned int bq24158_get_revision(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON3), + (&val), + (unsigned char)(CON3_REVISION_MASK), + (unsigned char)(CON3_REVISION_SHIFT) + ); + return val; +} + +//CON4---------------------------------------------------- + +void bq24158_set_reset(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON4), + (unsigned char)(val), + (unsigned char)(CON4_RESET_MASK), + (unsigned char)(CON4_RESET_SHIFT) + ); +} + +void bq24158_set_iocharge(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON4), + (unsigned char)(val), + (unsigned char)(CON4_I_CHR_MASK), + (unsigned char)(CON4_I_CHR_SHIFT) + ); +} + +void bq24158_set_iterm(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON4), + (unsigned char)(val), + (unsigned char)(CON4_I_TERM_MASK), + (unsigned char)(CON4_I_TERM_SHIFT) + ); +} + +//CON5---------------------------------------------------- + +void bq24158_set_dis_vreg(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON5), + (unsigned char)(val), + (unsigned char)(CON5_DIS_VREG_MASK), + (unsigned char)(CON5_DIS_VREG_SHIFT) + ); +} + +void bq24158_set_io_level(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON5), + (unsigned char)(val), + (unsigned char)(CON5_IO_LEVEL_MASK), + (unsigned char)(CON5_IO_LEVEL_SHIFT) + ); +} + +unsigned int bq24158_get_sp_status(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON5), + (&val), + (unsigned char)(CON5_SP_STATUS_MASK), + (unsigned char)(CON5_SP_STATUS_SHIFT) + ); + return val; +} + +unsigned int bq24158_get_en_level(void) +{ + int ret=0; + unsigned char val=0; + + ret=bq24158_read_interface( (unsigned char)(bq24158_CON5), + (&val), + (unsigned char)(CON5_EN_LEVEL_MASK), + (unsigned char)(CON5_EN_LEVEL_SHIFT) + ); + return val; +} + +void bq24158_set_vsp(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON5), + (unsigned char)(val), + (unsigned char)(CON5_VSP_MASK), + (unsigned char)(CON5_VSP_SHIFT) + ); +} + +//CON6---------------------------------------------------- + +void bq24158_set_i_safe(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON6), + (unsigned char)(val), + (unsigned char)(CON6_ISAFE_MASK), + (unsigned char)(CON6_ISAFE_SHIFT) + ); +} + +void bq24158_set_v_safe(unsigned int val) +{ + int ret=0; + + ret=bq24158_config_interface( (unsigned char)(bq24158_CON6), + (unsigned char)(val), + (unsigned char)(CON6_VSAFE_MASK), + (unsigned char)(CON6_VSAFE_SHIFT) + ); +} + +/********************************************************** + * + * [Internal Function] + * + *********************************************************/ +void bq24158_dump_register(void) +{ + int i=0; + printk("[bq24158] "); + for (i=0;i 3) + { + reg_value = simple_strtoul((pvalue+1),NULL,16); + battery_xlog_printk(BAT_LOG_FULL,"[store_bq24158_access] write bq24158 reg 0x%x with value 0x%x !\n",reg_address,reg_value); + ret=bq24158_config_interface(reg_address, reg_value, 0xFF, 0x0); + } + else + { + ret=bq24158_read_interface(reg_address, &g_reg_value_bq24158, 0xFF, 0x0); + battery_xlog_printk(BAT_LOG_FULL,"[store_bq24158_access] read bq24158 reg 0x%x with value 0x%x !\n",reg_address,g_reg_value_bq24158); + battery_xlog_printk(BAT_LOG_FULL,"[store_bq24158_access] Please use \"cat bq24158_access\" to get value\r\n"); + } + } + return count; +} +static DEVICE_ATTR(bq24158_access, 0664, show_bq24158_access, store_bq24158_access); //664 + +static int bq24158_user_space_probe(struct platform_device *dev) +{ + int ret_device_file = 0; + + battery_xlog_printk(BAT_LOG_CRTI,"******** bq24158_user_space_probe!! ********\n" ); + + ret_device_file = device_create_file(&(dev->dev), &dev_attr_bq24158_access); + + return 0; +} + +struct platform_device bq24158_user_space_device = { + .name = "bq24158-user", + .id = -1, +}; + +static struct platform_driver bq24158_user_space_driver = { + .probe = bq24158_user_space_probe, + .driver = { + .name = "bq24158-user", + }, +}; + + +//static struct i2c_board_info __initdata i2c_bq24158 = { I2C_BOARD_INFO("bq24158", (bq24158_SLAVE_ADDR_WRITE>>1))}; + +static int __init bq24158_init(void) +{ + int ret=0; + + battery_xlog_printk(BAT_LOG_CRTI,"[bq24158_init] init start\n"); + + //i2c_register_board_info(BQ24158_BUSNUM, &i2c_bq24158, 1); + + if(i2c_add_driver(&bq24158_driver)!=0) + { + battery_xlog_printk(BAT_LOG_CRTI,"[bq24158_init] failed to register bq24158 i2c driver.\n"); + } + else + { + battery_xlog_printk(BAT_LOG_CRTI,"[bq24158_init] Success to register bq24158 i2c driver.\n"); + } + + // bq24158 user space access interface + ret = platform_device_register(&bq24158_user_space_device); + if (ret) { + battery_xlog_printk(BAT_LOG_CRTI,"****[bq24158_init] Unable to device register(%d)\n", ret); + return ret; + } + ret = platform_driver_register(&bq24158_user_space_driver); + if (ret) { + battery_xlog_printk(BAT_LOG_CRTI,"****[bq24158_init] Unable to register driver (%d)\n", ret); + return ret; + } + + return 0; +} + +static void __exit bq24158_exit(void) +{ + i2c_del_driver(&bq24158_driver); +} + +module_init(bq24158_init); +module_exit(bq24158_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("I2C bq24158 Driver"); +MODULE_AUTHOR("James Lo"); diff --git a/drivers/misc/mediatek/power/mt6755/bq24158.h b/drivers/misc/mediatek/power/mt6755/bq24158.h new file mode 100755 index 0000000000000000000000000000000000000000..414bbbbe51566456de94192607e8e6060167beb0 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/bq24158.h @@ -0,0 +1,179 @@ +/***************************************************************************** +* +* Filename: +* --------- +* bq24158.h +* +* Project: +* -------- +* Android +* +* Description: +* ------------ +* bq24158 header file +* +* Author: +* ------- +* +****************************************************************************/ + +#ifndef _bq24158_SW_H_ +#define _bq24158_SW_H_ + +//#define HIGH_BATTERY_VOLTAGE_SUPPORT + +#define bq24158_CON0 0x00 +#define bq24158_CON1 0x01 +#define bq24158_CON2 0x02 +#define bq24158_CON3 0x03 +#define bq24158_CON4 0x04 +#define bq24158_CON5 0x05 +#define bq24158_CON6 0x06 +#define bq24158_REG_NUM 7 + + +/********************************************************** + * + * [MASK/SHIFT] + * + *********************************************************/ +//CON0 +#define CON0_TMR_RST_MASK 0x01 +#define CON0_TMR_RST_SHIFT 7 + +#define CON0_OTG_MASK 0x01 +#define CON0_OTG_SHIFT 7 + +#define CON0_EN_STAT_MASK 0x01 +#define CON0_EN_STAT_SHIFT 6 + +#define CON0_STAT_MASK 0x03 +#define CON0_STAT_SHIFT 4 + +#define CON0_BOOST_MASK 0x01 +#define CON0_BOOST_SHIFT 3 + +#define CON0_FAULT_MASK 0x07 +#define CON0_FAULT_SHIFT 0 + +//CON1 +#define CON1_LIN_LIMIT_MASK 0x03 +#define CON1_LIN_LIMIT_SHIFT 6 + +#define CON1_LOW_V_MASK 0x03 +#define CON1_LOW_V_SHIFT 4 + +#define CON1_TE_MASK 0x01 +#define CON1_TE_SHIFT 3 + +#define CON1_CE_MASK 0x01 +#define CON1_CE_SHIFT 2 + +#define CON1_HZ_MODE_MASK 0x01 +#define CON1_HZ_MODE_SHIFT 1 + +#define CON1_OPA_MODE_MASK 0x01 +#define CON1_OPA_MODE_SHIFT 0 + +//CON2 +#define CON2_OREG_MASK 0x3F +#define CON2_OREG_SHIFT 2 + +#define CON2_OTG_PL_MASK 0x01 +#define CON2_OTG_PL_SHIFT 1 + +#define CON2_OTG_EN_MASK 0x01 +#define CON2_OTG_EN_SHIFT 0 + +//CON3 +#define CON3_VENDER_CODE_MASK 0x07 +#define CON3_VENDER_CODE_SHIFT 5 + +#define CON3_PIN_MASK 0x03 +#define CON3_PIN_SHIFT 3 + +#define CON3_REVISION_MASK 0x07 +#define CON3_REVISION_SHIFT 0 + +//CON4 +#define CON4_RESET_MASK 0x01 +#define CON4_RESET_SHIFT 7 + +#define CON4_I_CHR_MASK 0x07 +#define CON4_I_CHR_SHIFT 4 + +#define CON4_I_TERM_MASK 0x07 +#define CON4_I_TERM_SHIFT 0 + +//CON5 +#define CON5_DIS_VREG_MASK 0x01 +#define CON5_DIS_VREG_SHIFT 6 + +#define CON5_IO_LEVEL_MASK 0x01 +#define CON5_IO_LEVEL_SHIFT 5 + +#define CON5_SP_STATUS_MASK 0x01 +#define CON5_SP_STATUS_SHIFT 4 + +#define CON5_EN_LEVEL_MASK 0x01 +#define CON5_EN_LEVEL_SHIFT 3 + +#define CON5_VSP_MASK 0x07 +#define CON5_VSP_SHIFT 0 + +//CON6 +#define CON6_ISAFE_MASK 0x07 +#define CON6_ISAFE_SHIFT 4 + +#define CON6_VSAFE_MASK 0x0F +#define CON6_VSAFE_SHIFT 0 + +/********************************************************** + * + * [Extern Function] + * + *********************************************************/ +//CON0---------------------------------------------------- +extern void bq24158_set_tmr_rst(unsigned int val); +extern unsigned int bq24158_get_otg_status(void); +extern void bq24158_set_en_stat(unsigned int val); +extern unsigned int bq24158_get_chip_status(void); +extern unsigned int bq24158_get_boost_status(void); +extern unsigned int bq24158_get_fault_status(void); +//CON1---------------------------------------------------- +extern void bq24158_set_input_charging_current(unsigned int val); +extern void bq24158_set_v_low(unsigned int val); +extern void bq24158_set_te(unsigned int val); +extern void bq24158_set_ce(unsigned int val); +extern void bq24158_set_hz_mode(unsigned int val); +extern void bq24158_set_opa_mode(unsigned int val); +//CON2---------------------------------------------------- +extern void bq24158_set_oreg(unsigned int val); +extern void bq24158_set_otg_pl(unsigned int val); +extern void bq24158_set_otg_en(unsigned int val); +//CON3---------------------------------------------------- +extern unsigned int bq24158_get_vender_code(void); +extern unsigned int bq24158_get_pn(void); +extern unsigned int bq24158_get_revision(void); +//CON4---------------------------------------------------- +extern void bq24158_set_reset(unsigned int val); +extern void bq24158_set_iocharge(unsigned int val); +extern void bq24158_set_iterm(unsigned int val); +//CON5---------------------------------------------------- +extern void bq24158_set_dis_vreg(unsigned int val); +extern void bq24158_set_io_level(unsigned int val); +extern unsigned int bq24158_get_sp_status(void); +extern unsigned int bq24158_get_en_level(void); +extern void bq24158_set_vsp(unsigned int val); +//CON6---------------------------------------------------- +extern void bq24158_set_i_safe(unsigned int val); +extern void bq24158_set_v_safe(unsigned int val); +//--------------------------------------------------------- +extern void bq24158_dump_register(void); +extern int bq24158_config_interface_liao (unsigned char RegNum, unsigned char val); + +extern int bq24158_read_interface (unsigned char RegNum, unsigned char *val, unsigned char MASK, unsigned char SHIFT); +extern int bq24158_config_interface (unsigned char RegNum, unsigned char val, unsigned char MASK, unsigned char SHIFT); + +#endif // _bq24158_SW_H_ + diff --git a/drivers/misc/mediatek/power/mt6755/bq25890.c b/drivers/misc/mediatek/power/mt6755/bq25890.c new file mode 100644 index 0000000000000000000000000000000000000000..616fc9e026b42d47d36f87749ab2d7b43ebe1e86 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/bq25890.c @@ -0,0 +1,1200 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include /* For init/exit macros */ +#include /* For MODULE_ marcros */ +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include +#include +#include +#include "bq25890.h" +/********************************************************** + * + * [I2C Slave Setting] + * + *********************************************************/ + +#ifdef CONFIG_OF +#else + +#define bq25890_SLAVE_ADDR_WRITE 0xD6 +#define bq25890_SLAVE_ADDR_Read 0xD7 + +#ifdef I2C_SWITHING_CHARGER_CHANNEL +#define bq25890_BUSNUM I2C_SWITHING_CHARGER_CHANNEL +#else +#define bq25890_BUSNUM 0 +#endif + +#endif +static struct i2c_client *new_client; +static const struct i2c_device_id bq25890_i2c_id[] = { {"bq25890", 0}, {} }; + +kal_bool chargin_hw_init_done = false; +static int bq25890_driver_probe(struct i2c_client *client, const struct i2c_device_id *id); + + +/********************************************************** + * + * [Global Variable] + * + *********************************************************/ +unsigned char bq25890_reg[bq25890_REG_NUM] = { 0 }; + +static DEFINE_MUTEX(bq25890_i2c_access); +static DEFINE_MUTEX(bq25890_access_mutex); + +int g_bq25890_hw_exist = 0; + +/********************************************************** + * + * [I2C Function For Read/Write bq25890] + * + *********************************************************/ +#ifdef CONFIG_MTK_I2C_EXTENSION +unsigned int bq25890_read_byte(unsigned char cmd, unsigned char *returnData) +{ + char cmd_buf[1] = { 0x00 }; + char readData = 0; + int ret = 0; + + mutex_lock(&bq25890_i2c_access); + + /* new_client->addr = ((new_client->addr) & I2C_MASK_FLAG) | I2C_WR_FLAG; */ + new_client->ext_flag = + ((new_client->ext_flag) & I2C_MASK_FLAG) | I2C_WR_FLAG | I2C_DIRECTION_FLAG; + + cmd_buf[0] = cmd; + ret = i2c_master_send(new_client, &cmd_buf[0], (1 << 8 | 1)); + if (ret < 0) { + /* new_client->addr = new_client->addr & I2C_MASK_FLAG; */ + new_client->ext_flag = 0; + mutex_unlock(&bq25890_i2c_access); + + return 0; + } + + readData = cmd_buf[0]; + *returnData = readData; + + /* new_client->addr = new_client->addr & I2C_MASK_FLAG; */ + new_client->ext_flag = 0; + mutex_unlock(&bq25890_i2c_access); + + return 1; +} + +unsigned int bq25890_write_byte(unsigned char cmd, unsigned char writeData) +{ + char write_data[2] = { 0 }; + int ret = 0; + + mutex_lock(&bq25890_i2c_access); + + write_data[0] = cmd; + write_data[1] = writeData; + + new_client->ext_flag = ((new_client->ext_flag) & I2C_MASK_FLAG) | I2C_DIRECTION_FLAG; + + ret = i2c_master_send(new_client, write_data, 2); + if (ret < 0) { + new_client->ext_flag = 0; + mutex_unlock(&bq25890_i2c_access); + return 0; + } + + new_client->ext_flag = 0; + mutex_unlock(&bq25890_i2c_access); + return 1; +} +#else +unsigned int bq25890_read_byte(unsigned char cmd, unsigned char *returnData) +{ + unsigned char xfers = 2; + int ret, retries = 1; + + mutex_lock(&bq25890_i2c_access); + + do { + struct i2c_msg msgs[2] = { + { + .addr = new_client->addr, + .flags = 0, + .len = 1, + .buf = &cmd, + }, + { + + .addr = new_client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = returnData, + } + }; + + /* + * Avoid sending the segment addr to not upset non-compliant + * DDC monitors. + */ + ret = i2c_transfer(new_client->adapter, msgs, xfers); + + if (ret == -ENXIO) { + battery_log(BAT_LOG_CRTI, "skipping non-existent adapter %s\n", new_client->adapter->name); + break; + } + } while (ret != xfers && --retries); + + mutex_unlock(&bq25890_i2c_access); + + return ret == xfers ? 1 : -1; +} + +unsigned int bq25890_write_byte(unsigned char cmd, unsigned char writeData) +{ + unsigned char xfers = 1; + int ret, retries = 1; + unsigned char buf[8]; + + mutex_lock(&bq25890_i2c_access); + + buf[0] = cmd; + memcpy(&buf[1], &writeData, 1); + + do { + struct i2c_msg msgs[1] = { + { + .addr = new_client->addr, + .flags = 0, + .len = 1 + 1, + .buf = buf, + }, + }; + + /* + * Avoid sending the segment addr to not upset non-compliant + * DDC monitors. + */ + ret = i2c_transfer(new_client->adapter, msgs, xfers); + + if (ret == -ENXIO) { + battery_log(BAT_LOG_CRTI, "skipping non-existent adapter %s\n", new_client->adapter->name); + break; + } + } while (ret != xfers && --retries); + + mutex_unlock(&bq25890_i2c_access); + + return ret == xfers ? 1 : -1; +} +#endif +/********************************************************** + * + * [Read / Write Function] + * + *********************************************************/ +unsigned int bq25890_read_interface(unsigned char RegNum, unsigned char *val, unsigned char MASK, + unsigned char SHIFT) +{ + unsigned char bq25890_reg = 0; + unsigned int ret = 0; + + ret = bq25890_read_byte(RegNum, &bq25890_reg); + + battery_log(BAT_LOG_FULL, "[bq25890_read_interface] Reg[%x]=0x%x\n", RegNum, bq25890_reg); + + bq25890_reg &= (MASK << SHIFT); + *val = (bq25890_reg >> SHIFT); + + battery_log(BAT_LOG_FULL, "[bq25890_read_interface] val=0x%x\n", *val); + + return ret; +} + +unsigned int bq25890_config_interface(unsigned char RegNum, unsigned char val, unsigned char MASK, + unsigned char SHIFT) +{ + unsigned char bq25890_reg = 0; + unsigned char bq25890_reg_ori = 0; + unsigned int ret = 0; + + mutex_lock(&bq25890_access_mutex); + ret = bq25890_read_byte(RegNum, &bq25890_reg); + + bq25890_reg_ori = bq25890_reg; + bq25890_reg &= ~(MASK << SHIFT); + bq25890_reg |= (val << SHIFT); + + ret = bq25890_write_byte(RegNum, bq25890_reg); + mutex_unlock(&bq25890_access_mutex); + battery_log(BAT_LOG_FULL, "[bq25890_config_interface] write Reg[%x]=0x%x from 0x%x\n", RegNum, + bq25890_reg, bq25890_reg_ori); + + /* Check */ + /* bq25890_read_byte(RegNum, &bq25890_reg); */ + /* printk("[bq25890_config_interface] Check Reg[%x]=0x%x\n", RegNum, bq25890_reg); */ + + return ret; +} + +/* write one register directly */ +unsigned int bq25890_reg_config_interface(unsigned char RegNum, unsigned char val) +{ + unsigned int ret = 0; + + ret = bq25890_write_byte(RegNum, val); + + return ret; +} + +/********************************************************** + * + * [Internal Function] + * + *********************************************************/ +/* CON0---------------------------------------------------- */ + +void bq25890_set_en_hiz(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON0), + (unsigned char) (val), + (unsigned char) (CON0_EN_HIZ_MASK), + (unsigned char) (CON0_EN_HIZ_SHIFT) + ); +} + +void bq25890_set_en_ilim(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON0), + (unsigned char) (val), + (unsigned char) (CON0_EN_ILIM_MASK), + (unsigned char) (CON0_EN_ILIM_SHIFT) + ); +} + +void bq25890_set_iinlim(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON0), + (val), + (unsigned char) (CON0_IINLIM_MASK), + (unsigned char) (CON0_IINLIM_SHIFT) + ); +} + +unsigned int bq25890_get_iinlim(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON0), + (&val), + (unsigned char) (CON0_IINLIM_MASK), (unsigned char) (CON0_IINLIM_SHIFT) + ); + return val; +} + + + +/* CON1---------------------------------------------------- */ + +void bq25890_ADC_start(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON2), + (unsigned char) (val), + (unsigned char) (CON2_CONV_START_MASK), + (unsigned char) (CON2_CONV_START_SHIFT) + ); +} + +void bq25890_set_ADC_rate(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON2), + (unsigned char) (val), + (unsigned char) (CON2_CONV_RATE_MASK), + (unsigned char) (CON2_CONV_RATE_SHIFT) + ); +} + +void bq25890_set_vindpm_os(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON1), + (unsigned char) (val), + (unsigned char) (CON1_VINDPM_OS_MASK), + (unsigned char) (CON1_VINDPM_OS_SHIFT) + ); +} + +/* CON2---------------------------------------------------- */ + +void bq25890_set_ico_en_start(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON2), + (unsigned char) (val), + (unsigned char) (CON2_ICO_EN_MASK), + (unsigned char) (CON2_ICO_EN_RATE_SHIFT) + ); +} + + + +/* CON3---------------------------------------------------- */ + +void bq25890_wd_reset(unsigned int val) +{ + unsigned int ret = 0; + + + ret = bq25890_config_interface((unsigned char) (bq25890_CON3), + (val), + (unsigned char) (CON3_WD_MASK), (unsigned char) (CON3_WD_SHIFT) + ); + +} + +void bq25890_otg_en(unsigned int val) +{ + unsigned int ret = 0; + + + ret = bq25890_config_interface((unsigned char) (bq25890_CON3), + (val), + (unsigned char) (CON3_OTG_CONFIG_MASK), + (unsigned char) (CON3_OTG_CONFIG_SHIFT) + ); + +} + +void bq25890_chg_en(unsigned int val) +{ + unsigned int ret = 0; + + + ret = bq25890_config_interface((unsigned char) (bq25890_CON3), + (val), + (unsigned char) (CON3_CHG_CONFIG_MASK), + (unsigned char) (CON3_CHG_CONFIG_SHIFT) + ); + +} + +unsigned int bq25890_get_chg_en(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON3), + (&val), + (unsigned char) (CON3_CHG_CONFIG_MASK), + (unsigned char) (CON3_CHG_CONFIG_SHIFT) + ); + return val; +} + + +void bq25890_set_sys_min(unsigned int val) +{ + unsigned int ret = 0; + + + ret = bq25890_config_interface((unsigned char) (bq25890_CON3), + (val), + (unsigned char) (CON3_SYS_V_LIMIT_MASK), + (unsigned char) (CON3_SYS_V_LIMIT_SHIFT) + ); + +} + +/* CON4---------------------------------------------------- */ + +void bq25890_en_pumpx(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON4), + (unsigned char) (val), + (unsigned char) (CON4_EN_PUMPX_MASK), + (unsigned char) (CON4_EN_PUMPX_SHIFT) + ); +} + + +void bq25890_set_ichg(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON4), + (unsigned char) (val), + (unsigned char) (CON4_ICHG_MASK), (unsigned char) (CON4_ICHG_SHIFT) + ); +} + +unsigned int bq25890_get_reg_ichg(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON4), + (&val), + (unsigned char) (CON4_ICHG_MASK), (unsigned char) (CON4_ICHG_SHIFT) + ); + return val; +} + +/* CON5---------------------------------------------------- */ + +void bq25890_set_iprechg(unsigned int val) +{ + unsigned int ret = 0; + + + ret = bq25890_config_interface((unsigned char) (bq25890_CON5), + (val), + (unsigned char) (CON5_IPRECHG_MASK), + (unsigned char) (CON5_IPRECHG_SHIFT) + ); + +} + +void bq25890_set_iterml(unsigned int val) +{ + unsigned int ret = 0; + + + ret = bq25890_config_interface((unsigned char) (bq25890_CON5), + (val), + (unsigned char) (CON5_ITERM_MASK), (unsigned char) (CON5_ITERM_SHIFT) + ); + +} + + + +/* CON6---------------------------------------------------- */ + +void bq25890_set_vreg(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON6), + (unsigned char) (val), + (unsigned char) (CON6_VREG_MASK), + (unsigned char) (CON6_VREG_SHIFT) + ); +} + +unsigned int bq25890_get_vreg(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON6), + (&val), + (unsigned char) (CON6_VREG_MASK), (unsigned char) (CON6_VREG_SHIFT) + ); + return val; +} + +void bq25890_set_batlowv(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON6), + (unsigned char) (val), + (unsigned char) (CON6_BATLOWV_MASK), + (unsigned char) (CON6_BATLOWV_SHIFT) + ); +} + +void bq25890_set_vrechg(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON6), + (unsigned char) (val), + (unsigned char) (CON6_VRECHG_MASK), + (unsigned char) (CON6_VRECHG_SHIFT) + ); +} + +/* CON7---------------------------------------------------- */ + + +void bq25890_en_term_chg(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON7), + (unsigned char) (val), + (unsigned char) (CON7_EN_TERM_CHG_MASK), + (unsigned char) (CON7_EN_TERM_CHG_SHIFT) + ); +} + +void bq25890_en_state_dis(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON7), + (unsigned char) (val), + (unsigned char) (CON7_STAT_DIS_MASK), + (unsigned char) (CON7_STAT_DIS_SHIFT) + ); +} + +void bq25890_set_wd_timer(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON7), + (unsigned char) (val), + (unsigned char) (CON7_WTG_TIM_SET_MASK), + (unsigned char) (CON7_WTG_TIM_SET_SHIFT) + ); +} + +void bq25890_en_chg_timer(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON7), + (unsigned char) (val), + (unsigned char) (CON7_EN_TIMER_MASK), + (unsigned char) (CON7_EN_TIMER_SHIFT) + ); +} + +unsigned int bq25890_get_chg_timer_enable(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON7), + &val, + (unsigned char) (CON7_EN_TIMER_MASK), + (unsigned char) (CON7_EN_TIMER_SHIFT)); + + return val; +} + +void bq25890_set_chg_timer(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON7), + (unsigned char) (val), + (unsigned char) (CON7_SET_CHG_TIM_MASK), + (unsigned char) (CON7_SET_CHG_TIM_SHIFT) + ); +} + +/* CON8--------------------------------------------------- */ +void bq25890_set_thermal_regulation(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON8), + (unsigned char) (val), + (unsigned char) (CON8_TREG_MASK), (unsigned char) (CON8_TREG_SHIFT) + ); +} + +void bq25890_set_VBAT_clamp(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON8), + (unsigned char) (val), + (unsigned char) (CON8_VCLAMP_MASK), + (unsigned char) (CON8_VCLAMP_SHIFT) + ); +} + +void bq25890_set_VBAT_IR_compensation(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON8), + (unsigned char) (val), + (unsigned char) (CON8_BAT_COMP_MASK), + (unsigned char) (CON8_BAT_COMP_SHIFT) + ); +} + +/* CON9---------------------------------------------------- */ +void bq25890_pumpx_up(unsigned int val) +{ + unsigned int ret = 0; + + bq25890_en_pumpx(1); + if (val == 1) { + ret = bq25890_config_interface((unsigned char) (bq25890_CON9), + (unsigned char) (1), + (unsigned char) (CON9_PUMPX_UP), + (unsigned char) (CON9_PUMPX_UP_SHIFT) + ); + } else { + ret = bq25890_config_interface((unsigned char) (bq25890_CON9), + (unsigned char) (1), + (unsigned char) (CON9_PUMPX_DN), + (unsigned char) (CON9_PUMPX_DN_SHIFT) + ); + } + + /* Input current limit = 500 mA, changes after PE+ detection */ + bq25890_set_iinlim(0x08); + + /* CC mode current = 2048 mA */ + bq25890_set_ichg(0x20); + + msleep(3000); +} + +void bq25890_set_force_ico(void) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CON9), + (unsigned char) (1), + (unsigned char) (FORCE_ICO_MASK), + (unsigned char) (FORCE_ICO__SHIFT) + ); +} + +/* CONA---------------------------------------------------- */ +void bq25890_set_boost_ilim(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CONA), + (unsigned char) (val), + (unsigned char) (CONA_BOOST_ILIM_MASK), + (unsigned char) (CONA_BOOST_ILIM_SHIFT) + ); +} + +void bq25890_set_boost_vlim(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_CONA), + (unsigned char) (val), + (unsigned char) (CONA_BOOST_VLIM_MASK), + (unsigned char) (CONA_BOOST_VLIM_SHIFT) + ); +} + +/* CONB---------------------------------------------------- */ + + +unsigned int bq25890_get_vbus_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONB), + (&val), + (unsigned char) (CONB_VBUS_STAT_MASK), + (unsigned char) (CONB_VBUS_STAT_SHIFT) + ); + return val; +} + + +unsigned int bq25890_get_chrg_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONB), + (&val), + (unsigned char) (CONB_CHRG_STAT_MASK), + (unsigned char) (CONB_CHRG_STAT_SHIFT) + ); + return val; +} + +unsigned int bq25890_get_pg_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONB), + (&val), + (unsigned char) (CONB_PG_STAT_MASK), + (unsigned char) (CONB_PG_STAT_SHIFT) + ); + return val; +} + + + +unsigned int bq25890_get_sdp_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONB), + (&val), + (unsigned char) (CONB_SDP_STAT_MASK), + (unsigned char) (CONB_SDP_STAT_SHIFT) + ); + return val; +} + +unsigned int bq25890_get_vsys_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONB), + (&val), + (unsigned char) (CONB_VSYS_STAT_MASK), + (unsigned char) (CONB_VSYS_STAT_SHIFT) + ); + return val; +} + +/* CON0C---------------------------------------------------- */ +unsigned int bq25890_get_wdt_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONC), + (&val), + (unsigned char) (CONB_WATG_STAT_MASK), + (unsigned char) (CONB_WATG_STAT_SHIFT) + ); + return val; +} + +unsigned int bq25890_get_boost_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONC), + (&val), + (unsigned char) (CONB_BOOST_STAT_MASK), + (unsigned char) (CONB_BOOST_STAT_SHIFT) + ); + return val; +} + +unsigned int bq25890_get_chrg_fault_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONC), + (&val), + (unsigned char) (CONC_CHRG_FAULT_MASK), + (unsigned char) (CONC_CHRG_FAULT_SHIFT) + ); + return val; +} + +unsigned int bq25890_get_bat_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONC), + (&val), + (unsigned char) (CONB_BAT_STAT_MASK), + (unsigned char) (CONB_BAT_STAT_SHIFT) + ); + return val; +} + + +/* COND */ +void bq25890_set_force_vindpm(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_COND), + (unsigned char) (val), + (unsigned char) (COND_FORCE_VINDPM_MASK), + (unsigned char) (COND_FORCE_VINDPM_SHIFT) + ); +} + +void bq25890_set_vindpm(unsigned int val) +{ + unsigned int ret = 0; + + ret = bq25890_config_interface((unsigned char) (bq25890_COND), + (unsigned char) (val), + (unsigned char) (COND_VINDPM_MASK), + (unsigned char) (COND_VINDPM_SHIFT) + ); +} + +unsigned int bq25890_get_vindpm(void) +{ + int ret = 0; + unsigned char val = 0; + + + ret = bq25890_read_interface((unsigned char) (bq25890_COND), + (&val), + (unsigned char) (COND_VINDPM_MASK), + (unsigned char) (COND_VINDPM_SHIFT)); + return val; +} + +/* CONDE */ +unsigned int bq25890_get_vbat(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CONE), + (&val), + (unsigned char) (CONE_VBAT_MASK), (unsigned char) (CONE_VBAT_SHIFT) + ); + return val; +} + +/* CON11 */ +unsigned int bq25890_get_vbus(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON11), + (&val), + (unsigned char) (CON11_VBUS_MASK), (unsigned char) (CON11_VBUS_SHIFT) + ); + return val; +} + +/* CON12 */ +unsigned int bq25890_get_ichg(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON12), + (&val), + (unsigned char) (CONB_ICHG_STAT_MASK), + (unsigned char) (CONB_ICHG_STAT_SHIFT) + ); + return val; +} + + + +/* CON13 /// */ + + +unsigned int bq25890_get_idpm_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON13), + (&val), + (unsigned char) (CON13_IDPM_STAT_MASK), + (unsigned char) (CON13_IDPM_STAT_SHIFT) + ); + return val; +} + +unsigned int bq25890_get_vdpm_state(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface((unsigned char) (bq25890_CON13), + (&val), + (unsigned char) (CON13_VDPM_STAT_MASK), + (unsigned char) (CON13_VDPM_STAT_SHIFT) + ); + return val; +} + + + + +/********************************************************** + * + * [Internal Function] + * + *********************************************************/ +void bq25890_hw_component_detect(void) +{ + unsigned int ret = 0; + unsigned char val = 0; + + ret = bq25890_read_interface(0x03, &val, 0xFF, 0x0); + + if (val == 0) + g_bq25890_hw_exist = 0; + else + g_bq25890_hw_exist = 1; + + pr_debug("[bq25890_hw_component_detect] exist=%d, Reg[0x03]=0x%x\n", + g_bq25890_hw_exist, val); +} + +int is_bq25890_exist(void) +{ + pr_debug("[is_bq25890_exist] g_bq25890_hw_exist=%d\n", g_bq25890_hw_exist); + + return g_bq25890_hw_exist; +} + +void bq25890_dump_register(void) +{ + unsigned char i = 0; + unsigned char ichg = 0; + unsigned char ichg_reg = 0; + unsigned char iinlim = 0; + unsigned char vbat = 0; + unsigned char chrg_state = 0; + unsigned char chr_en = 0; + unsigned char vbus = 0; + unsigned char vdpm = 0; + unsigned char fault = 0; + + if (Enable_BATDRV_LOG == BAT_LOG_FULL) { + bq25890_ADC_start(1); + for (i = 0; i < bq25890_REG_NUM; i++) + bq25890_read_byte(i, &bq25890_reg[i]); + battery_log(BAT_LOG_CRTI, + "[bq25890 reg@][0x0]=0x%x [0x1]=0x%x [0x2]=0x%x [0x3]=0x%x [0x4]=0x%x [0x5]=0x%x\n", + bq25890_reg[0], bq25890_reg[0x1], bq25890_reg[0x2], bq25890_reg[0x3], + bq25890_reg[0x4], bq25890_reg[0x5]); + battery_log(BAT_LOG_CRTI, + "[bq25890 reg@][0x6]=0x%x [0x7]=0x%x [0x8]=0x%x [0x9]=0x%x [0xa]=0x%x [0xb]=0x%x\n", + bq25890_reg[0x6], bq25890_reg[0x7], bq25890_reg[0x8], bq25890_reg[0x9], + bq25890_reg[0xa], bq25890_reg[0xb]); + battery_log(BAT_LOG_CRTI, + "[bq25890 reg@][0xc]=0x%x [0xd]=0x%x [0xe]=0x%x [0xf]=0x%x [0x10]=0x%x [0x11]=0x%x\n", + bq25890_reg[0xc], bq25890_reg[0xd], bq25890_reg[0xe], bq25890_reg[0xf], + bq25890_reg[0x10], bq25890_reg[0x11]); + battery_log(BAT_LOG_CRTI, + "[bq25890 reg@][0x11]=0x%x [0x12]=0x%x [0x13]=0x%x [0x14]=0x%x\n", + bq25890_reg[0x11], bq25890_reg[0x12], bq25890_reg[0x13], bq25890_reg[0x14]); + } + + + bq25890_ADC_start(1); + iinlim = bq25890_get_iinlim(); + chrg_state = bq25890_get_chrg_state(); + chr_en = bq25890_get_chg_en(); + ichg_reg = bq25890_get_reg_ichg(); + ichg = bq25890_get_ichg(); + vbat = bq25890_get_vbat(); + vbus = bq25890_get_vbus(); + vdpm = bq25890_get_vdpm_state(); + fault = bq25890_get_chrg_fault_state(); + battery_log(BAT_LOG_CRTI, + "[PE+]Ibat=%d, Ilim=%d, Vbus=%d, err=%d, Ichg=%d, Vbat=%d, ChrStat=%d, CHGEN=%d, VDPM=%d\n", + ichg_reg * 64, iinlim * 50 + 100, vbus * 100 + 2600, fault, + ichg * 50, vbat * 20 + 2304, chrg_state, chr_en, vdpm); + +} + +void bq25890_hw_init(void) +{ + /*battery_log(BAT_LOG_CRTI, "[bq25890_hw_init] After HW init\n");*/ + bq25890_dump_register(); +} + +static int bq25890_driver_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + battery_log(BAT_LOG_CRTI, "[bq25890_driver_probe]\n"); + + new_client = client; + + /* --------------------- */ + bq25890_hw_component_detect(); + bq25890_dump_register(); + /* bq25890_hw_init(); //move to charging_hw_xxx.c */ + chargin_hw_init_done = true; + + /* Hook chr_control_interface with battery's interface */ + battery_charging_control = chr_control_interface; + return 0; +} + +/********************************************************** + * + * [platform_driver API] + * + *********************************************************/ +unsigned char g_reg_value_bq25890 = 0; +static ssize_t show_bq25890_access(struct device *dev, struct device_attribute *attr, char *buf) +{ + battery_log(BAT_LOG_CRTI, "[show_bq25890_access] 0x%x\n", g_reg_value_bq25890); + return sprintf(buf, "%u\n", g_reg_value_bq25890); +} + +static ssize_t store_bq25890_access(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + char *pvalue = NULL, *addr, *val; + unsigned int reg_value = 0; + unsigned int reg_address = 0; + + battery_log(BAT_LOG_CRTI, "[store_bq25890_access]\n"); + + if (buf != NULL && size != 0) { + battery_log(BAT_LOG_CRTI, "[store_bq25890_access] buf is %s and size is %zu\n", buf, + size); + + pvalue = (char *)buf; + if (size > 3) { + addr = strsep(&pvalue, " "); + ret = kstrtou32(addr, 16, (unsigned int *)®_address); + } else + ret = kstrtou32(pvalue, 16, (unsigned int *)®_address); + + if (size > 3) { + val = strsep(&pvalue, " "); + ret = kstrtou32(val, 16, (unsigned int *)®_value); + battery_log(BAT_LOG_CRTI, + "[store_bq25890_access] write bq25890 reg 0x%x with value 0x%x !\n", + (unsigned int) reg_address, reg_value); + ret = bq25890_config_interface(reg_address, reg_value, 0xFF, 0x0); + } else { + ret = bq25890_read_interface(reg_address, &g_reg_value_bq25890, 0xFF, 0x0); + battery_log(BAT_LOG_CRTI, + "[store_bq25890_access] read bq25890 reg 0x%x with value 0x%x !\n", + (unsigned int) reg_address, g_reg_value_bq25890); + battery_log(BAT_LOG_CRTI, + "[store_bq25890_access] Please use \"cat bq25890_access\" to get value\r\n"); + } + } + return size; +} + +static DEVICE_ATTR(bq25890_access, 0664, show_bq25890_access, store_bq25890_access); /* 664 */ + +static int bq25890_user_space_probe(struct platform_device *dev) +{ + int ret_device_file = 0; + + battery_log(BAT_LOG_CRTI, "******** bq25890_user_space_probe!! ********\n"); + + ret_device_file = device_create_file(&(dev->dev), &dev_attr_bq25890_access); + + return 0; +} + +struct platform_device bq25890_user_space_device = { + .name = "bq25890-user", + .id = -1, +}; + +static struct platform_driver bq25890_user_space_driver = { + .probe = bq25890_user_space_probe, + .driver = { + .name = "bq25890-user", + }, +}; + +#ifdef CONFIG_OF +static const struct of_device_id bq25890_of_match[] = { + {.compatible = "mediatek,SWITHING_CHARGER"}, + {}, +}; +#else +static struct i2c_board_info i2c_bq25890 __initdata = { + I2C_BOARD_INFO("bq25890", (bq25890_SLAVE_ADDR_WRITE >> 1)) +}; +#endif + +static struct i2c_driver bq25890_driver = { + .driver = { + .name = "bq25890", +#ifdef CONFIG_OF + .of_match_table = bq25890_of_match, +#endif + }, + .probe = bq25890_driver_probe, + .id_table = bq25890_i2c_id, +}; + +static int __init bq25890_init(void) +{ + int ret = 0; + + /* i2c registeration using DTS instead of boardinfo*/ +#ifdef CONFIG_OF + battery_log(BAT_LOG_CRTI, "[bq25890_init] init start with i2c DTS"); +#else + battery_log(BAT_LOG_CRTI, "[bq25890_init] init start. ch=%d\n", bq25890_BUSNUM); + i2c_register_board_info(bq25890_BUSNUM, &i2c_bq25890, 1); +#endif + if (i2c_add_driver(&bq25890_driver) != 0) { + battery_log(BAT_LOG_CRTI, + "[bq25890_init] failed to register bq25890 i2c driver.\n"); + } else { + battery_log(BAT_LOG_CRTI, + "[bq25890_init] Success to register bq25890 i2c driver.\n"); + } + + /* bq25890 user space access interface */ + ret = platform_device_register(&bq25890_user_space_device); + if (ret) { + battery_log(BAT_LOG_CRTI, "****[bq25890_init] Unable to device register(%d)\n", + ret); + return ret; + } + ret = platform_driver_register(&bq25890_user_space_driver); + if (ret) { + battery_log(BAT_LOG_CRTI, "****[bq25890_init] Unable to register driver (%d)\n", + ret); + return ret; + } + + return 0; +} + +static void __exit bq25890_exit(void) +{ + i2c_del_driver(&bq25890_driver); +} +module_init(bq25890_init); +module_exit(bq25890_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("I2C bq25890 Driver"); +MODULE_AUTHOR("will cai "); diff --git a/drivers/misc/mediatek/power/mt6755/bq25890.h b/drivers/misc/mediatek/power/mt6755/bq25890.h new file mode 100644 index 0000000000000000000000000000000000000000..e7e433f6b93aa8855deffb74ddf83a222834fddf --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/bq25890.h @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/***************************************************************************** +* +* Filename: +* --------- +* bq25890.h +* +* Project: +* -------- +* Android +* +* Description: +* ------------ +* bq25890 header file +* +* Author: +* ------- +* +****************************************************************************/ +#ifndef _bq25890_SW_H_ +#define _bq25890_SW_H_ + +#define bq25890_CON0 0x00 +#define bq25890_CON1 0x01 +#define bq25890_CON2 0x02 +#define bq25890_CON3 0x03 +#define bq25890_CON4 0x04 +#define bq25890_CON5 0x05 +#define bq25890_CON6 0x06 +#define bq25890_CON7 0x07 +#define bq25890_CON8 0x08 +#define bq25890_CON9 0x09 +#define bq25890_CONA 0x0A +#define bq25890_CONB 0x0B +#define bq25890_CONC 0x0C +#define bq25890_COND 0x0D +#define bq25890_CONE 0x0E +#define bq25890_CON11 0X11 +#define bq25890_CON12 0x12 +#define bq25890_CON13 0x13 + + + + +#define bq25890_REG_NUM 21 +#define CON1_RESET_MASK 0x1 +#define CON1_RESET_SHIFT 7 + + + + + + +/* CON0 */ +#define CON0_EN_HIZ_MASK 0x1 +#define CON0_EN_HIZ_SHIFT 7 + +#define CON0_EN_ILIM_MASK 0x1 +#define CON0_EN_ILIM_SHIFT 6 + +#define CON0_IINLIM_MASK 0x3F +#define CON0_IINLIM_SHIFT 0 + + +/* CON1 */ +#define CON1_VINDPM_OS_MASK 0x1F +#define CON1_VINDPM_OS_SHIFT 0 + + +/* CON2 */ +#define CON2_CONV_START_MASK 0x1 +#define CON2_CONV_START_SHIFT 7 + +#define CON2_CONV_RATE_MASK 0x1 +#define CON2_CONV_RATE_SHIFT 6 + +#define CON2_BOOST_FREQ_MASK 0x1 +#define CON2_BOOST_FREQ_SHIFT 5 + +#define CON2_ICO_EN_MASK 0x1 +#define CON2_ICO_EN_RATE_SHIFT 4 + +#define CON2_HVDCP_EN_MASK 0x1 +#define CON2_HVDCP_EN_SHIFT 3 + +#define CON2_MAX_EN_MASK 0x1 +#define CON2_MAX_EN_SHIFT 2 + +#define CON2_FORCE_DPDM_MASK 0x1 +#define CON2_FORCE_DPDM_SHIFT 1 + +#define CON2_AUTO_DPDM_EN_MASK 0x1 +#define CON2_AUTO_DPDM_EN_SHIFT 0 + + + + +/* CON3 */ +#define CON3_BAT_LOADEN_MASK 0x1 +#define CON3_BAT_LOADEN_SHIFT 7 + +#define CON3_WD_MASK 0x1 +#define CON3_WD_SHIFT 6 + +#define CON3_OTG_CONFIG_MASK 0x1 +#define CON3_OTG_CONFIG_SHIFT 5 + +#define CON3_CHG_CONFIG_MASK 0x1 +#define CON3_CHG_CONFIG_SHIFT 4 + +#define CON3_SYS_V_LIMIT_MASK 0x7 +#define CON3_SYS_V_LIMIT_SHIFT 1 + + + +/* CON4 */ +#define CON4_EN_PUMPX_MASK 0x1 +#define CON4_EN_PUMPX_SHIFT 7 + +#define CON4_ICHG_MASK 0x7F +#define CON4_ICHG_SHIFT 0 + +/* CON5 */ +#define CON5_IPRECHG_MASK 0xF +#define CON5_IPRECHG_SHIFT 4 + +#define CON5_ITERM_MASK 0xF +#define CON5_ITERM_SHIFT 0 + + + +/* CON6 */ +#define CON6_VREG_MASK 0x3F +#define CON6_VREG_SHIFT 2 + +#define CON6_BATLOWV_MASK 0x1 +#define CON6_BATLOWV_SHIFT 1 + +#define CON6_VRECHG_MASK 0x1 +#define CON6_VRECHG_SHIFT 0 + +/* CON7 */ + +#define CON7_EN_TERM_CHG_MASK 0x1 +#define CON7_EN_TERM_CHG_SHIFT 7 + +#define CON7_STAT_DIS_MASK 0x1 +#define CON7_STAT_DIS_SHIFT 6 + +#define CON7_WTG_TIM_SET_MASK 0x3 +#define CON7_WTG_TIM_SET_SHIFT 4 + +#define CON7_EN_TIMER_MASK 0x1 +#define CON7_EN_TIMER_SHIFT 3 + +#define CON7_SET_CHG_TIM_MASK 0x3 +#define CON7_SET_CHG_TIM_SHIFT 1 + +#define CON7_JEITA_ISET_MASK 0x1 +#define CON7_JEITA_ISET_SHIFT 0 +/* CON8 */ +#define CON8_TREG_MASK 0x3 +#define CON8_TREG_SHIFT 0 + +#define CON8_VCLAMP_MASK 0x7 +#define CON8_VCLAMP_SHIFT 2 + +#define CON8_BAT_COMP_MASK 0x7 +#define CON8_BAT_COMP_SHIFT 5 +/* CON9 */ + +#define CON9_PUMPX_UP 0x1 +#define CON9_PUMPX_UP_SHIFT 1 + +#define CON9_PUMPX_DN 0x1 +#define CON9_PUMPX_DN_SHIFT 0 + +#define FORCE_ICO_MASK 0x1 +#define FORCE_ICO__SHIFT 7 + + +/* CONA */ +#define CONA_BOOST_VLIM_MASK 0xF +#define CONA_BOOST_VLIM_SHIFT 4 + +#define CONA_BOOST_ILIM_MASK 0x07 +#define CONA_BOOST_ILIM_SHIFT 0 + + +/* CONB */ + +#define CONB_VBUS_STAT_MASK 0x7 +#define CONB_VBUS_STAT_SHIFT 5 + +#define CONB_CHRG_STAT_MASK 0x3 +#define CONB_CHRG_STAT_SHIFT 3 + +#define CONB_PG_STAT_MASK 0x1 +#define CONB_PG_STAT_SHIFT 2 + +#define CONB_SDP_STAT_MASK 0x1 +#define CONB_SDP_STAT_SHIFT 1 + +#define CONB_VSYS_STAT_MASK 0x1 +#define CONB_VSYS_STAT_SHIFT 0 + + +/* CONC */ + +#define CONB_WATG_STAT_MASK 0x1 +#define CONB_WATG_STAT_SHIFT 7 + +#define CONB_BOOST_STAT_MASK 0x1 +#define CONB_BOOST_STAT_SHIFT 6 + +#define CONC_CHRG_FAULT_MASK 0x3 +#define CONC_CHRG_FAULT_SHIFT 4 + +#define CONB_BAT_STAT_MASK 0x1 +#define CONB_BAT_STAT_SHIFT 3 + +/* COND */ +#define COND_FORCE_VINDPM_MASK 0x01 +#define COND_FORCE_VINDPM_SHIFT 7 + +#define COND_VINDPM_MASK 0x7F +#define COND_VINDPM_SHIFT 0 + +/* CONE */ +#define CONE_VBAT_MASK 0x7F +#define CONE_VBAT_SHIFT 0 + +/* CON11 */ +#define CON11_VBUS_MASK 0x7F +#define CON11_VBUS_SHIFT 0 +/* CON12 */ + +#define CONB_ICHG_STAT_MASK 0x7F +#define CONB_ICHG_STAT_SHIFT 0 + +/* CON13 */ +#define CON13_IDPM_STAT_MASK 0x1 +#define CON13_IDPM_STAT_SHIFT 6 + +#define CON13_VDPM_STAT_MASK 0x1 +#define CON13_VDPM_STAT_SHIFT 7 + + +/********************************************************** + * + * [Extern Function] + * + *********************************************************/ +/* CON0---------------------------------------------------- */ +extern void bq25890_set_en_hiz(unsigned int val); +extern void bq25890_set_en_ilim(unsigned int val); +extern void bq25890_set_iinlim(unsigned int val); +extern unsigned int bq25890_get_iinlim(void); + +/* CON1---------------------------------------------------- */ + +/* CON2---------------------------------------------------- */ +extern void bq25890_ADC_start(unsigned int val); +extern void bq25890_set_ADC_rate(unsigned int val); +extern void bq25890_set_ico_en_start(unsigned int val); +/* */ + + +/* CON3---------------------------------------------------- */ +/* willcai */ +extern void bq25890_wd_reset(unsigned int val); +extern void bq25890_otg_en(unsigned int val); +extern void bq25890_chg_en(unsigned int val); +extern void bq25890_set_sys_min(unsigned int val); +/* */ + + +/* CON4---------------------------------------------------- */ + +/* willcai */ +extern void bq25890_en_pumpx(unsigned int val); +extern void bq25890_set_ichg(unsigned int val); +unsigned int bq25890_get_reg_ichg(void); + +/* */ + +/* CON5---------------------------------------------------- */ + +/* willcai */ +extern void bq25890_set_iprechg(unsigned int val); +extern void bq25890_set_iterml(unsigned int val); +/* */ + + +/* CON6---------------------------------------------------- */ +/* willcai */ +extern void bq25890_set_vreg(unsigned int val); +extern void bq25890_set_batlowv(unsigned int val); +extern void bq25890_set_vrechg(unsigned int val); +extern unsigned int bq25890_get_vreg(void); + + + +/* con7 */ + +extern void bq25890_en_term_chg(unsigned int val); +extern void bq25890_en_state_dis(unsigned int val); +extern void bq25890_set_wd_timer(unsigned int val); +extern void bq25890_en_chg_timer(unsigned int val); +extern unsigned int bq25890_get_chg_timer_enable(void); + +extern void bq25890_set_chg_timer(unsigned int val); + + +/* con8 */ +extern void bq25890_set_thermal_regulation(unsigned int val); +extern void bq25890_set_VBAT_clamp(unsigned int val); +extern void bq25890_set_VBAT_IR_compensation(unsigned int val); +/* con9 */ +void bq25890_pumpx_up(unsigned int val); + + + + +/* --------------------------------------------------------- */ +extern void bq25890_dump_register(void); +extern unsigned int bq25890_reg_config_interface(unsigned char RegNum, unsigned char val); + +extern unsigned int bq25890_read_interface(unsigned char RegNum, unsigned char *val, unsigned char MASK, + unsigned char SHIFT); +extern unsigned int bq25890_config_interface(unsigned char RegNum, unsigned char val, unsigned char MASK, + unsigned char SHIFT); +/* +*static void hw_bc11_dump_register(void); +*static void hw_bc11_init(void); +*static U32 hw_bc11_DCD(void); +*static U32 hw_bc11_stepA1(void); +*static U32 hw_bc11_stepB1(void); +*static U32 hw_bc11_stepC1(void); +*static U32 hw_bc11_stepA2(void); +*static U32 hw_bc11_stepB2(void); +*static void hw_bc11_done(void); +*/ +/* CONA */ +extern void bq25890_set_boost_ilim(unsigned int val); +extern void bq25890_set_boost_vlim(unsigned int val); + +/* CONB */ +unsigned int bq25890_get_vbus_state(void); +unsigned int bq25890_get_chrg_state(void); +unsigned int bq25890_get_pg_state(void); +unsigned int bq25890_get_sdp_state(void); +unsigned int bq25890_get_vsys_state(void); +unsigned int bq25890_get_wdt_state(void); +unsigned int bq25890_get_boost_state(void); +unsigned int bq25890_get_chrg_fault_state(void); +unsigned int bq25890_get_bat_state(void); +unsigned int bq25890_get_ichg(void); + +/* CON0D */ +extern void bq25890_set_force_vindpm(unsigned int val); +extern void bq25890_set_vindpm(unsigned int val); +extern unsigned int bq25890_get_vindpm(void); + +/* CON11 */ +extern unsigned int bq25890_get_vbus(void); + +/* aggregated APIs */ +extern void bq25890_hw_init(void); +extern void bq25890_charging_enable(unsigned int bEnable); +extern void bq25890_dump_register(void); +extern unsigned int bq25890_get_chrg_stat(void); + + +/*CON13*/ +unsigned int bq25890_get_idpm_state(void); +unsigned int bq25890_get_vdpm_state(void); + +/*Added for debuging to check power off caller*/ +extern void dump_stack(void); +#endif diff --git a/drivers/misc/mediatek/power/mt6755/charging_hw_bq24158.c b/drivers/misc/mediatek/power/mt6755/charging_hw_bq24158.c new file mode 100755 index 0000000000000000000000000000000000000000..3e39fba66ad127963d819a975fb9701f9c35d3da --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/charging_hw_bq24158.c @@ -0,0 +1,666 @@ +/***************************************************************************** + * + * Filename: + * --------- + * charging_pmic.c + * + * Project: + * -------- + * ALPS_Software + * + * Description: + * ------------ + * This file implements the interface between BMT and ADC scheduler. + * + * Author: + * ------- + * Oscar Liu + * + *============================================================================ + * $Revision: 1.0 $ + * $Modtime: 11 Aug 2005 10:28:16 $ + * $Log: //mtkvs01/vmdata/Maui_sw/archives/mcu/hal/peripheral/inc/bmt_chr_setting.h-arc $ + * HISTORY + * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! + *------------------------------------------------------------------------------ + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! + *============================================================================ + ****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bq24158.h" +#include + +// ============================================================ // +//define +// ============================================================ // +#define STATUS_OK 0 +#define STATUS_UNSUPPORTED -1 +#define GETARRAYNUM(array) (sizeof(array)/sizeof(array[0])) + + +// ============================================================ // +//global variable +// ============================================================ // +//static CHARGER_TYPE g_charger_type = CHARGER_UNKNOWN; +#if defined(MTK_WIRELESS_CHARGER_SUPPORT) +#define WIRELESS_CHARGER_EXIST_STATE 0 +int wireless_charger_gpio_number = (168 | 0x80000000); +#endif + +#if 0 +#define GPIO_SWCHARGER_EN_PIN (GPIO5 | 0x80000000) +#define GPIO_SWCHARGER_EN_PIN_M_GPIO GPIO_MODE_00 + + +int gpio_number = GPIO_SWCHARGER_EN_PIN; +int gpio_off_mode = GPIO_SWCHARGER_EN_PIN_M_GPIO; +int gpio_on_mode = GPIO_SWCHARGER_EN_PIN_M_GPIO; +int gpio_off_dir = GPIO_DIR_OUT; +int gpio_off_out = GPIO_OUT_ONE; +int gpio_on_dir = GPIO_DIR_OUT; +int gpio_on_out = GPIO_OUT_ZERO; +#endif + +kal_bool charging_type_det_done = KAL_TRUE; + +const unsigned int VBAT_CV_VTH[]= +{ + BATTERY_VOLT_03_500000_V, BATTERY_VOLT_03_520000_V, BATTERY_VOLT_03_540000_V, BATTERY_VOLT_03_560000_V, + BATTERY_VOLT_03_580000_V, BATTERY_VOLT_03_600000_V, BATTERY_VOLT_03_620000_V, BATTERY_VOLT_03_640000_V, + BATTERY_VOLT_03_660000_V, BATTERY_VOLT_03_680000_V, BATTERY_VOLT_03_700000_V, BATTERY_VOLT_03_720000_V, + BATTERY_VOLT_03_740000_V, BATTERY_VOLT_03_760000_V, BATTERY_VOLT_03_780000_V, BATTERY_VOLT_03_800000_V, + BATTERY_VOLT_03_820000_V, BATTERY_VOLT_03_840000_V, BATTERY_VOLT_03_860000_V, BATTERY_VOLT_03_880000_V, + BATTERY_VOLT_03_900000_V, BATTERY_VOLT_03_920000_V, BATTERY_VOLT_03_940000_V, BATTERY_VOLT_03_960000_V, + BATTERY_VOLT_03_980000_V, BATTERY_VOLT_04_000000_V, BATTERY_VOLT_04_020000_V, BATTERY_VOLT_04_040000_V, + BATTERY_VOLT_04_060000_V, BATTERY_VOLT_04_080000_V, BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_120000_V, + BATTERY_VOLT_04_140000_V, BATTERY_VOLT_04_160000_V, BATTERY_VOLT_04_180000_V, BATTERY_VOLT_04_200000_V, + BATTERY_VOLT_04_220000_V, BATTERY_VOLT_04_240000_V, BATTERY_VOLT_04_260000_V, BATTERY_VOLT_04_280000_V, + BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_320000_V, BATTERY_VOLT_04_340000_V, BATTERY_VOLT_04_360000_V, + BATTERY_VOLT_04_380000_V, BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_420000_V, BATTERY_VOLT_04_440000_V + +}; + +const unsigned int CS_VTH[]= +{ + CHARGE_CURRENT_550_00_MA, CHARGE_CURRENT_650_00_MA, CHARGE_CURRENT_750_00_MA, CHARGE_CURRENT_850_00_MA, + CHARGE_CURRENT_950_00_MA, CHARGE_CURRENT_1050_00_MA, CHARGE_CURRENT_1150_00_MA, CHARGE_CURRENT_1250_00_MA +}; + +const unsigned int INPUT_CS_VTH[]= +{ + CHARGE_CURRENT_100_00_MA, CHARGE_CURRENT_500_00_MA, CHARGE_CURRENT_800_00_MA, CHARGE_CURRENT_MAX +}; + +const unsigned int VCDT_HV_VTH[]= +{ + BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_500000_V, BATTERY_VOLT_04_550000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_06_000000_V, BATTERY_VOLT_06_500000_V, BATTERY_VOLT_07_000000_V, + BATTERY_VOLT_07_500000_V, BATTERY_VOLT_08_500000_V, BATTERY_VOLT_09_500000_V, BATTERY_VOLT_10_500000_V +}; + +static unsigned int charging_error = false; +// ============================================================ // +// function prototype +// ============================================================ // + +static unsigned int charging_get_error_state(void); +static unsigned int charging_set_error_state(void *data); + +// ============================================================ // +//extern variable +// ============================================================ // + +// ============================================================ // +//extern function +// ============================================================ // +extern bool mt_usb_is_device(void); +extern void Charger_Detect_Init(void); +extern void Charger_Detect_Release(void); +extern int hw_charging_get_charger_type(void); +extern void mt_power_off(void); + +extern bool get_usb_current_unlimited(void); + +// ============================================================ // +unsigned int charging_value_to_parameter(const unsigned int *parameter, const unsigned int array_size, const unsigned int val) +{ + if (val < array_size) + { + return parameter[val]; + } + else + { + battery_xlog_printk(BAT_LOG_CRTI, "Can't find the parameter \r\n"); + return parameter[0]; + } +} + + +unsigned int charging_parameter_to_value(const unsigned int *parameter, const unsigned int array_size, const unsigned int val) +{ + unsigned int i; + + for(i=0;i CHARGE_CURRENT_500_00_MA) + { + register_value = 0x3; + } + else + { + array_size = GETARRAYNUM(INPUT_CS_VTH); + set_chr_current = bmt_find_closest_level(INPUT_CS_VTH, array_size, *(unsigned int *)data); + register_value = charging_parameter_to_value(INPUT_CS_VTH, array_size ,set_chr_current); + } + + bq24158_set_input_charging_current(register_value); + + return status; +} + + +static unsigned int charging_get_charging_status(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int ret_val; + + ret_val = bq24158_get_chip_status(); + + if(ret_val == 0x2) + *(unsigned int *)data = KAL_TRUE; + else + *(unsigned int *)data = KAL_FALSE; + + return status; +} + + +static unsigned int charging_reset_watch_dog_timer(void *data) +{ + unsigned int status = STATUS_OK; + + bq24158_set_tmr_rst(1); + + return status; +} + + +static unsigned int charging_set_hv_threshold(void *data) +{ + unsigned int status = STATUS_OK; + + unsigned int set_hv_voltage; + unsigned int array_size; + unsigned short register_value; + unsigned int voltage = *(unsigned int*)(data); + + array_size = GETARRAYNUM(VCDT_HV_VTH); + set_hv_voltage = bmt_find_closest_level(VCDT_HV_VTH, array_size, voltage); + register_value = charging_parameter_to_value(VCDT_HV_VTH, array_size ,set_hv_voltage); + pmic_set_register_value(PMIC_RG_VCDT_HV_VTH,register_value); + + return status; +} + + +static unsigned int charging_get_hv_status(void *data) +{ + unsigned int status = STATUS_OK; + + *(kal_bool*)(data) = pmic_get_register_value(PMIC_RGS_VCDT_HV_DET); + + return status; +} + + +static unsigned int charging_get_battery_status(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int val = 0; +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool*)(data) = 0; // battery exist + battery_log(BAT_LOG_CRTI,"bat exist for evb\n"); +#else + val=pmic_get_register_value(PMIC_BATON_TDET_EN); + battery_log(BAT_LOG_FULL,"[charging_get_battery_status] BATON_TDET_EN = %d\n", val); + if (val) { + pmic_set_register_value(PMIC_BATON_TDET_EN,1); + pmic_set_register_value(PMIC_RG_BATON_EN,1); + *(kal_bool*)(data) = pmic_get_register_value(PMIC_RGS_BATON_UNDET); + } else { + *(kal_bool*)(data) = KAL_FALSE; + } +#endif + + return status; + +} + + +static unsigned int charging_get_charger_det_status(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_MTK_FPGA) + *(kal_bool*)(data) = 1; + battery_log(BAT_LOG_CRTI,"chr exist for fpga\n"); +#else + *(kal_bool*)(data) = pmic_get_register_value(PMIC_RGS_CHRDET); +#endif + + return status; + +} + + +kal_bool charging_type_detection_done(void) +{ + return charging_type_det_done; +} + + +static unsigned int charging_get_charger_type(void *data) +{ + unsigned int status = STATUS_OK; +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(CHARGER_TYPE*)(data) = STANDARD_HOST; +#else + *(CHARGER_TYPE*)(data) = hw_charging_get_charger_type(); +#endif + return status; +} + +static unsigned int charging_get_is_pcm_timer_trigger(void *data) +{ + unsigned int status = STATUS_OK; + + if(slp_get_wake_reason() == WR_PCM_TIMER) + *(kal_bool*)(data) = KAL_TRUE; + else + *(kal_bool*)(data) = KAL_FALSE; + + battery_xlog_printk(BAT_LOG_CRTI, "slp_get_wake_reason=%d\n", slp_get_wake_reason()); + + return status; +} + +static unsigned int charging_set_platform_reset(void *data) +{ + unsigned int status = STATUS_OK; + + battery_xlog_printk(BAT_LOG_CRTI, "charging_set_platform_reset\n"); + + arch_reset(0,NULL); + + return status; +} + +static unsigned int charging_get_platform_boot_mode(void *data) +{ + unsigned int status = STATUS_OK; + + *(unsigned int*)(data) = get_boot_mode(); + + battery_xlog_printk(BAT_LOG_CRTI, "get_boot_mode=%d\n", get_boot_mode()); + + return status; +} + +static unsigned int charging_set_power_off(void *data) +{ + unsigned int status = STATUS_OK; + + battery_xlog_printk(BAT_LOG_CRTI, "charging_set_power_off\n"); + mt_power_off(); + + return status; +} + +static unsigned int charging_get_power_source(void *data) +{ + unsigned int status = STATUS_UNSUPPORTED; + + return status; +} + +static unsigned int charging_get_csdac_full_flag(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static unsigned int charging_set_ta_current_pattern(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static unsigned int charging_get_error_state(void) +{ + return charging_error; +} + +static unsigned int charging_set_error_state(void *data) +{ + unsigned int status = STATUS_OK; + charging_error = *(unsigned int*)(data); + + return status; +} + +static unsigned int charging_enable_otg(void *data) +{ + int ret = 0; + unsigned int enable = 0; + + enable = *((unsigned int *)data); + bq24158_set_otg_en(enable); + + return ret; +} + +static unsigned int (*charging_func[CHARGING_CMD_NUMBER]) (void *data); + +/* Vanzo:yangbinbin on: Mon, 17 Oct 2016 11:32:32 +0800 + * TODO: replace this line with your comment +static unsigned int (* const charging_func[CHARGING_CMD_NUMBER])(void *data)= +{ + charging_func[CHARGING_CMD_INIT] = charging_hw_init; + charging_func[CHARGING_CMD_DUMP_REGISTER] = charging_dump_register; + charging_func[CHARGING_CMD_ENABLE] = charging_enable; + charging_func[CHARGING_CMD_SET_CV_VOLTAGE] = charging_set_cv_voltage; + charging_func[CHARGING_CMD_GET_CURRENT] = charging_get_current; + charging_func[CHARGING_CMD_SET_CURRENT] = charging_set_current; + charging_func[CHARGING_CMD_SET_INPUT_CURRENT] = charging_set_input_current; + charging_func[CHARGING_CMD_GET_CHARGING_STATUS] = charging_get_charging_status; + charging_func[CHARGING_CMD_RESET_WATCH_DOG_TIMER] = charging_reset_watch_dog_timer; + charging_func[CHARGING_CMD_SET_HV_THRESHOLD] = charging_set_hv_threshold; + charging_func[CHARGING_CMD_GET_HV_STATUS] = charging_get_hv_status; + charging_func[CHARGING_CMD_GET_BATTERY_STATUS] = charging_get_battery_status; + charging_func[CHARGING_CMD_GET_CHARGER_DET_STATUS] = charging_get_charger_det_status; + charging_func[CHARGING_CMD_GET_CHARGER_TYPE] = charging_get_charger_type; + charging_func[CHARGING_CMD_GET_IS_PCM_TIMER_TRIGGER] = charging_get_is_pcm_timer_trigger; + charging_func[CHARGING_CMD_SET_PLATFORM_RESET] = charging_set_platform_reset; + charging_func[CHARGING_CMD_GET_PLATFORM_BOOT_MODE] = charging_get_platform_boot_mode; + charging_func[CHARGING_CMD_SET_POWER_OFF] = charging_set_power_off; + charging_func[CHARGING_CMD_GET_POWER_SOURCE] = charging_get_power_source; + charging_func[CHARGING_CMD_GET_CSDAC_FALL_FLAG] = charging_get_csdac_full_flag; + charging_func[CHARGING_CMD_SET_TA_CURRENT_PATTERN] = charging_set_ta_current_pattern; + charging_func[CHARGING_CMD_SET_ERROR_STATE] = charging_set_error_state; + charging_func[CHARGING_CMD_ENABLE_OTG] = charging_enable_otg; +}; + */ +// End of Vanzo: yangbinbin + + +/* + * FUNCTION + * Internal_chr_control_handler + * + * DESCRIPTION + * This function is called to set the charger hw + * + * CALLS + * + * PARAMETERS + * None + * + * RETURNS + * + * + * GLOBALS AFFECTED + * None + */ +signed int chr_control_interface(CHARGING_CTRL_CMD cmd, void *data) +{ + signed int status; + static signed int init = -1; + + if (init == -1) { + init = 0; + charging_func[CHARGING_CMD_INIT] = charging_hw_init; + charging_func[CHARGING_CMD_DUMP_REGISTER] = charging_dump_register; + charging_func[CHARGING_CMD_ENABLE] = charging_enable; + charging_func[CHARGING_CMD_SET_CV_VOLTAGE] = charging_set_cv_voltage; + charging_func[CHARGING_CMD_GET_CURRENT] = charging_get_current; + charging_func[CHARGING_CMD_SET_CURRENT] = charging_set_current; + charging_func[CHARGING_CMD_SET_INPUT_CURRENT] = charging_set_input_current; + charging_func[CHARGING_CMD_GET_CHARGING_STATUS] = charging_get_charging_status; + charging_func[CHARGING_CMD_RESET_WATCH_DOG_TIMER] = charging_reset_watch_dog_timer; + charging_func[CHARGING_CMD_SET_HV_THRESHOLD] = charging_set_hv_threshold; + charging_func[CHARGING_CMD_GET_HV_STATUS] = charging_get_hv_status; + charging_func[CHARGING_CMD_GET_BATTERY_STATUS] = charging_get_battery_status; + charging_func[CHARGING_CMD_GET_CHARGER_DET_STATUS] = charging_get_charger_det_status; + charging_func[CHARGING_CMD_GET_CHARGER_TYPE] = charging_get_charger_type; + charging_func[CHARGING_CMD_GET_IS_PCM_TIMER_TRIGGER] = charging_get_is_pcm_timer_trigger; + charging_func[CHARGING_CMD_SET_PLATFORM_RESET] = charging_set_platform_reset; + charging_func[CHARGING_CMD_GET_PLATFORM_BOOT_MODE] = charging_get_platform_boot_mode; + charging_func[CHARGING_CMD_SET_POWER_OFF] = charging_set_power_off; + charging_func[CHARGING_CMD_GET_POWER_SOURCE] = charging_get_power_source; + charging_func[CHARGING_CMD_GET_CSDAC_FALL_FLAG] = charging_get_csdac_full_flag; + charging_func[CHARGING_CMD_SET_TA_CURRENT_PATTERN] = charging_set_ta_current_pattern; + charging_func[CHARGING_CMD_SET_ERROR_STATE] = charging_set_error_state; + charging_func[CHARGING_CMD_ENABLE_OTG] = charging_enable_otg; + } + + if (cmd < CHARGING_CMD_NUMBER) { + if (charging_func[cmd] != NULL) + status = charging_func[cmd](data); + else { + battery_log(BAT_LOG_CRTI, "[chr_control_interface]cmd:%d not supported\n", cmd); + status = STATUS_UNSUPPORTED; + } + } else + status = STATUS_UNSUPPORTED; + + return status; +} diff --git a/drivers/misc/mediatek/power/mt6755/charging_hw_bq25890.c b/drivers/misc/mediatek/power/mt6755/charging_hw_bq25890.c new file mode 100644 index 0000000000000000000000000000000000000000..49e281731b5f97dd58465713a1cf14de967d9045 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/charging_hw_bq25890.c @@ -0,0 +1,1523 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bq25890.h" +#include +#include "mtk_bif_intf.h" +/* ============================================================ // */ +/* Define */ +/* ============================================================ // */ +#define STATUS_OK 0 +#define STATUS_UNSUPPORTED -1 +#define STATUS_FAIL -2 +#define GETARRAYNUM(array) (sizeof(array)/sizeof(array[0])) + +/* ============================================================ // */ +/* Global variable */ +/* ============================================================ // */ + +#if defined(MTK_WIRELESS_CHARGER_SUPPORT) +#define WIRELESS_CHARGER_EXIST_STATE 0 + +#if defined(GPIO_PWR_AVAIL_WLC) +/*K.S.?*/ +unsigned int wireless_charger_gpio_number = GPIO_PWR_AVAIL_WLC; +#else +unsigned int wireless_charger_gpio_number = 0; +#endif + +#endif + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else +static CHARGER_TYPE g_charger_type = CHARGER_UNKNOWN; +#endif + +kal_bool charging_type_det_done = KAL_TRUE; + +/*BQ25890 REG06 VREG[5:0]*/ +const unsigned int VBAT_CV_VTH[] = { + 3840000, 3856000, 3872000, 3888000, + 3904000, 3920000, 3936000, 3952000, + 3968000, 3984000, 4000000, 4016000, + 4032000, 4048000, 4064000, 4080000, + 4096000, 4112000, 4128000, 4144000, + 4160000, 4176000, 4192000, 4208000, + 4224000, 4240000, 4256000, 4272000, + 4288000, 4304000, 4320000, 4336000, + 4352000, 4368000, 4384000, 4400000, + 4416000, 4432000, 4448000, 4464000, + 4480000, 4496000, 4512000, 4528000, + 4544000, 4560000, 4576000, 4592000, + 4608000 +}; + +/*BQ25890 REG04 ICHG[6:0]*/ +const unsigned int CS_VTH[] = { + 0, 6400, 12800, 19200, + 25600, 32000, 38400, 44800, + 51200, 57600, 64000, 70400, + 76800, 83200, 89600, 96000, + 102400, 108800, 115200, 121600, + 128000, 134400, 140800, 147200, + 153600, 160000, 166400, 172800, + 179200, 185600, 192000, 198400, + 204800, 211200, 217600, 224000, + 230400, 236800, 243200, 249600, + 256000, 262400, 268800, 275200, + 281600, 288000, 294400, 300800, + 307200, 313600, 320000, 326400, + 332800, 339200, 345600, 352000, + 358400, 364800, 371200, 377600, + 384000, 390400, 396800, 403200, + 409600, 416000, 422400, 428800, + 435200, 441600, 448000, 454400, + 460800, 467200, 473600, 480000, + 486400, 492800, 499200, 505600 +}; + +/*BQ25890 REG00 IINLIM[5:0]*/ +const unsigned int INPUT_CS_VTH[] = { + 10000, 15000, 20000, 25000, + 30000, 35000, 40000, 45000, + 50000, 55000, 60000, 65000, + 70000, 75000, 80000, 85000, + 90000, 95000, 100000, 105000, + 110000, 115000, 120000, 125000, + 130000, 135000, 140000, 145000, + 150000, 155000, 160000, 165000, + 170000, 175000, 180000, 185000, + 190000, 195000, 200000, 200500, + 210000, 215000, 220000, 225000, + 230000, 235000, 240000, 245000, + 250000, 255000, 260000, 265000, + 270000, 275000, 280000, 285000, + 290000, 295000, 300000, 305000, + 310000, 315000, 320000, 325000 +}; + +const unsigned int VCDT_HV_VTH[] = { + BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_300000_V, + BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_500000_V, + BATTERY_VOLT_04_550000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_06_000000_V, BATTERY_VOLT_06_500000_V, + BATTERY_VOLT_07_000000_V, + BATTERY_VOLT_07_500000_V, BATTERY_VOLT_08_500000_V, BATTERY_VOLT_09_500000_V, + BATTERY_VOLT_10_500000_V +}; + +const unsigned int VINDPM_REG[] = { + 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400, 3500, 3600, 3700, 3800, 3900, 4000, + 4100, 4200, 4300, 4400, 4500, 4600, 4700, 4800, 4900, 5000, 5100, 5200, 5300, 5400, 5500, + 5600, 5700, 5800, 5900, 6000, 6100, 6200, 6300, 6400, 6500, 6600, 6700, 6800, 6900, 7000, + 7100, 7200, 7300, 7400, 7500, 7600, 7700, 7800, 7900, 8000, 8100, 8200, 8300, 8400, 8500, + 8600, 8700, 8800, 8900, 9000, 9100, 9200, 9300, 9400, 9500, 9600, 9700, 9800, 9900, 10000, + 10100, 10200, 10300, 10400, 10500, 10600, 10700, 10800, 10900, 11000, 11100, 11200, 11300, + 11400, 11500, 11600, 11700, 11800, 11900, 12000, 12100, 12200, 12300, 12400, 12500, 12600, + 12700, 12800, 12900, 13000, 13100, 13200, 13300, 13400, 13500, 13600, 13700, 13800, 13900, + 14000, 14100, 14200, 14300, 14400, 14500, 14600, 14700, 14800, 14900, 15000, 15100, 15200, + 15300 +}; + +/* BQ25896 REG0A BOOST_LIM[2:0], mA */ +const unsigned int BOOST_CURRENT_LIMIT[] = { + 500, 750, 1200, 1400, 1650, +}; + + +/* BQ25896 REG08 VCLAMP, mV */ +const unsigned int IRCMP_VOLT_CLAMP[] = { + 0, 32, 64, 128, 160, 192, 224, +}; + +/* BQ25896 REG08 BAT_COMP, mohm */ +const unsigned int IRCMP_RESISTOR[] = { + 0, 20, 40, 60, 80, 100, 120, 140, +}; + +#ifdef CONFIG_MTK_DUAL_INPUT_CHARGER_SUPPORT +#ifndef CUST_GPIO_VIN_SEL +#define CUST_GPIO_VIN_SEL 18 +#endif +DISO_IRQ_Data DISO_IRQ; +int g_diso_state = 0; +int vin_sel_gpio_number = (CUST_GPIO_VIN_SEL | 0x80000000); +static char *DISO_state_s[8] = { + "IDLE", + "OTG_ONLY", + "USB_ONLY", + "USB_WITH_OTG", + "DC_ONLY", + "DC_WITH_OTG", + "DC_WITH_USB", + "DC_USB_OTG", +}; +#endif + +/* ============================================================ // */ +/* function prototype */ +/* ============================================================ // */ + + +/* ============================================================ // */ +/* extern variable */ +/* ============================================================ // */ + +/* ============================================================ // */ +/* extern function */ +/* ============================================================ // */ +/* extern unsigned int upmu_get_reg_value(unsigned int reg); upmu_common.h, _not_ used */ +/* extern bool mt_usb_is_device(void); _not_ used */ +/* extern void Charger_Detect_Init(void); _not_ used */ +/* extern void Charger_Detect_Release(void); _not_ used */ +/* extern int hw_charging_get_charger_type(void); included in charging.h*/ +/* extern void mt_power_off(void); _not_ used */ +/* extern unsigned int mt6311_get_chip_id(void); _not_ used*/ +/* extern int is_mt6311_exist(void); _not_ used */ +/* extern int is_mt6311_sw_ready(void); _not_ used */ +static unsigned int charging_error; +static unsigned int charging_get_error_state(void); +static int charging_set_error_state(void *data); +static int charging_set_vindpm(void *data); +static unsigned int g_input_current; +DEFINE_MUTEX(g_input_current_mutex); + +/* ============================================================ // */ +unsigned int charging_value_to_parameter(const unsigned int *parameter, const unsigned int array_size, + const unsigned int val) +{ + if (val < array_size) + return parameter[val]; + + battery_log(BAT_LOG_CRTI, "Can't find the parameter \r\n"); + return parameter[0]; + +} + +unsigned int charging_parameter_to_value(const unsigned int *parameter, const unsigned int array_size, + const unsigned int val) +{ + unsigned int i; + + battery_log(BAT_LOG_FULL, "array_size = %d \r\n", array_size); + + for (i = 0; i < array_size; i++) { + if (val == *(parameter + i)) + return i; + } + + battery_log(BAT_LOG_CRTI, "NO register value match \r\n"); + /* TODO: ASSERT(0); // not find the value */ + return 0; +} + +static unsigned int bmt_find_closest_level(const unsigned int *pList, unsigned int number, + unsigned int level) +{ + unsigned int i; + unsigned int max_value_in_last_element; + + if (pList[0] < pList[1]) + max_value_in_last_element = KAL_TRUE; + else + max_value_in_last_element = KAL_FALSE; + + if (max_value_in_last_element == KAL_TRUE) { + for (i = (number - 1); i != 0; i--) { /* max value in the last element */ + if (pList[i] <= level) { + battery_log(2, "zzf_%d<=%d i=%d\n", pList[i], level, i); + return pList[i]; + } + } + + battery_log(BAT_LOG_CRTI, "Can't find closest level \r\n"); + return pList[0]; + /* return CHARGE_CURRENT_0_00_MA; */ + } else { + for (i = 0; i < number; i++) { /* max value in the first element */ + if (pList[i] <= level) + return pList[i]; + } + + battery_log(BAT_LOG_CRTI, "Can't find closest level \r\n"); + return pList[number - 1]; + /* return CHARGE_CURRENT_0_00_MA; */ + } +} +#if !defined(CONFIG_POWER_EXT) +static unsigned int is_chr_det(void) +{ + unsigned int val = 0; + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + val = pmic_get_register_value(PMIC_RGS_CHRDET); +#else + val = pmic_get_register_value(MT6351_PMIC_RGS_CHRDET); +#endif + battery_log(BAT_LOG_CRTI, "[is_chr_det] %d\n", val); + + return val; +} +#endif + +static int charging_hw_init(void *data) +{ + int status = STATUS_OK; + + bq25890_config_interface(bq25890_COND, 0x1, 0x1, 7); /* vindpm vth 0:relative 1:absolute */ + + +#if defined(MTK_WIRELESS_CHARGER_SUPPORT) + if (wireless_charger_gpio_number != 0) { +#ifdef CONFIG_MTK_LEGACY + mt_set_gpio_mode(wireless_charger_gpio_number, 0); /* 0:GPIO mode */ + mt_set_gpio_dir(wireless_charger_gpio_number, 0); /* 0: input, 1: output */ +#else +/*K.S. way here*/ +#endif + } +#endif + +#ifdef CONFIG_MTK_DUAL_INPUT_CHARGER_SUPPORT +#ifdef CONFIG_MTK_LEGACY + mt_set_gpio_mode(vin_sel_gpio_number, 0); /* 0:GPIO mode */ + mt_set_gpio_dir(vin_sel_gpio_number, 0); /* 0: input, 1: output */ +#else +/*K.S. way here*/ +#endif +#endif + return status; +} + +static int charging_get_bif_vbat(void *data); + +static int charging_dump_register(void *data) +{ + int status = STATUS_OK; + + battery_log(BAT_LOG_FULL, "charging_dump_register\r\n"); + bq25890_dump_register(); + + /*unsigned int vbat; + charging_get_bif_vbat(&vbat); + battery_log(BAT_LOG_CRTI,"[BIF] vbat=%d mV\n", vbat); */ + + + return status; +} + +static int charging_enable(void *data) +{ + int status = STATUS_OK; + unsigned int enable = *(unsigned int *) (data); + + if (KAL_TRUE == enable) { + /* bq25890_config_interface(bq25890_CON3, 0x1, 0x1, 4); //enable charging */ + bq25890_set_en_hiz(0x0); + bq25890_chg_en(enable); + } else { + /* bq25890_config_interface(bq25890_CON3, 0x0, 0x1, 4); //enable charging */ + bq25890_chg_en(enable); + if (charging_get_error_state()) + battery_log(BAT_LOG_CRTI, "[charging_enable] under test mode: disable charging\n"); + + /*bq25890_set_en_hiz(0x1);*/ + } + + return status; +} + +static int charging_set_cv_voltage(void *data) +{ + int status; + unsigned short int array_size; + unsigned int set_cv_voltage; + unsigned short int register_value; + /*static kal_int16 pre_register_value; */ + + array_size = GETARRAYNUM(VBAT_CV_VTH); + status = STATUS_OK; + /*pre_register_value = -1; */ + set_cv_voltage = bmt_find_closest_level(VBAT_CV_VTH, array_size, *(unsigned int *) data); + register_value = + charging_parameter_to_value(VBAT_CV_VTH, GETARRAYNUM(VBAT_CV_VTH), set_cv_voltage); + battery_log(BAT_LOG_CRTI, "charging_set_cv_voltage register_value=0x%x %d %d\n", + register_value, *(unsigned int *) data, set_cv_voltage); + bq25890_set_vreg(register_value); + + return status; +} + + +static int charging_get_current(void *data) +{ + int status = STATUS_OK; + unsigned int array_size; + /*unsigned char reg_value; */ + unsigned int val; + + /*Get current level */ + array_size = GETARRAYNUM(CS_VTH); + val = bq25890_get_reg_ichg(); + *(unsigned int *)data = charging_value_to_parameter(CS_VTH, array_size, val); + + return status; +} + + +static int charging_set_current(void *data) +{ + int status = STATUS_OK; + unsigned int set_chr_current; + unsigned int array_size; + unsigned int register_value; + unsigned int current_value = *(unsigned int *) data; + + array_size = GETARRAYNUM(CS_VTH); + set_chr_current = bmt_find_closest_level(CS_VTH, array_size, current_value); + register_value = charging_parameter_to_value(CS_VTH, array_size, set_chr_current); + battery_log(BAT_LOG_FULL, "charging_set_ICHG:%d\n", register_value); + + bq25890_set_ichg(register_value); + + return status; +} + +static int charging_set_input_current(void *data) +{ + int status = STATUS_OK; + unsigned int current_value = *(unsigned int *) data; + unsigned int set_chr_current; + unsigned int array_size; + unsigned int register_value; + + mutex_lock(&g_input_current_mutex); + array_size = GETARRAYNUM(INPUT_CS_VTH); + set_chr_current = bmt_find_closest_level(INPUT_CS_VTH, array_size, current_value); + g_input_current = set_chr_current; + register_value = charging_parameter_to_value(INPUT_CS_VTH, array_size, set_chr_current); + battery_log(BAT_LOG_FULL, "charging_set_input_current:%d\n", register_value); + bq25890_set_iinlim(register_value); + mutex_unlock(&g_input_current_mutex); + + /*For USB_IF compliance test only when USB is in suspend(Ibus < 2.5mA) or unconfigured(Ibus < 70mA) states*/ +#ifdef CONFIG_USBIF_COMPLIANCE + if (current_value < CHARGE_CURRENT_100_00_MA) + register_value = 0x7f; + else + register_value = 0x13; + + charging_set_vindpm(®ister_value); +#endif + + return status; +} + +static int charging_get_charging_status(void *data) +{ + int status = STATUS_OK; + unsigned char reg_value; + + bq25890_read_interface(bq25890_CONB, ®_value, 0x3, 3); /* ICHG to BAT */ + + if (reg_value == 0x3) /* check if chrg done */ + *(unsigned int *) data = KAL_TRUE; + else + *(unsigned int *) data = KAL_FALSE; + + return status; +} + +static int charging_reset_watch_dog_timer(void *data) +{ + int status = STATUS_OK; + + bq25890_config_interface(bq25890_CON3, 0x1, 0x1, 6); /* reset watchdog timer */ + + return status; +} + +static int charging_set_hv_threshold(void *data) +{ + int status = STATUS_OK; + unsigned int set_hv_voltage; + unsigned int array_size; + unsigned short int register_value; + unsigned int voltage = *(unsigned int *) (data); + + array_size = GETARRAYNUM(VCDT_HV_VTH); + set_hv_voltage = bmt_find_closest_level(VCDT_HV_VTH, array_size, voltage); + register_value = charging_parameter_to_value(VCDT_HV_VTH, array_size, set_hv_voltage); +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_RG_VCDT_HV_VTH, register_value); +#else + pmic_set_register_value(MT6351_PMIC_RG_VCDT_HV_VTH, register_value); +#endif + + return status; +} + + +static int charging_get_hv_status(void *data) +{ + int status = STATUS_OK; + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + *(kal_bool *) (data) = pmic_get_register_value(PMIC_RGS_VCDT_HV_DET); +#else + *(kal_bool *) (data) = pmic_get_register_value(MT6351_PMIC_RGS_VCDT_HV_DET); +#endif + return status; +} + + +static int charging_get_battery_status(void *data) +{ + int status = STATUS_OK; +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = 0; + battery_log(BAT_LOG_CRTI, "bat exist for evb\n"); +#else + unsigned int val = 0; + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + val = pmic_get_register_value(PMIC_BATON_TDET_EN); + battery_log(BAT_LOG_FULL, "[charging_get_battery_status] BATON_TDET_EN = %d\n", val); + if (val) { + pmic_set_register_value(PMIC_BATON_TDET_EN, 1); + pmic_set_register_value(PMIC_RG_BATON_EN, 1); + *(kal_bool *) (data) = pmic_get_register_value(PMIC_RGS_BATON_UNDET); + } else { + *(kal_bool *) (data) = KAL_FALSE; + } +#else + val = pmic_get_register_value(MT6351_PMIC_BATON_TDET_EN); + battery_log(BAT_LOG_FULL, "[charging_get_battery_status] BATON_TDET_EN = %d\n", val); + if (val) { + pmic_set_register_value(MT6351_PMIC_BATON_TDET_EN, 1); + pmic_set_register_value(MT6351_PMIC_RG_BATON_EN, 1); + *(kal_bool *) (data) = pmic_get_register_value(MT6351_PMIC_RGS_BATON_UNDET); + } else { + *(kal_bool *) (data) = KAL_FALSE; + } +#endif +#endif + return status; +} + + +static int charging_get_charger_det_status(void *data) +{ + int status = STATUS_OK; + +#if defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = 1; + battery_log(BAT_LOG_CRTI, "chr exist for fpga\n"); +#else +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + *(kal_bool *) (data) = pmic_get_register_value_nolock(PMIC_RGS_CHRDET); +#else + *(kal_bool *) (data) = pmic_get_register_value_nolock(MT6351_PMIC_RGS_CHRDET); +#endif +#endif + return status; +} + + +kal_bool charging_type_detection_done(void) +{ + return charging_type_det_done; +} + + +static int charging_get_charger_type(void *data) +{ + int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(CHARGER_TYPE *) (data) = STANDARD_HOST; +#else +#if defined(MTK_WIRELESS_CHARGER_SUPPORT) + int wireless_state = 0; + + if (wireless_charger_gpio_number != 0) { +#ifdef CONFIG_MTK_LEGACY + wireless_state = mt_get_gpio_in(wireless_charger_gpio_number); +#else +/*K.S. way here*/ +#endif + if (wireless_state == WIRELESS_CHARGER_EXIST_STATE) { + *(CHARGER_TYPE *) (data) = WIRELESS_CHARGER; + battery_log(BAT_LOG_CRTI, "WIRELESS_CHARGER!\n"); + return status; + } + } else { + battery_log(BAT_LOG_CRTI, "wireless_charger_gpio_number=%d\n", wireless_charger_gpio_number); + } + + if (g_charger_type != CHARGER_UNKNOWN && g_charger_type != WIRELESS_CHARGER) { + *(CHARGER_TYPE *) (data) = g_charger_type; + battery_log(BAT_LOG_CRTI, "return %d!\n", g_charger_type); + return status; + } +#endif + + if (is_chr_det() == 0) { + g_charger_type = CHARGER_UNKNOWN; + *(CHARGER_TYPE *) (data) = CHARGER_UNKNOWN; + battery_log(BAT_LOG_CRTI, "[charging_get_charger_type] return CHARGER_UNKNOWN\n"); + return status; + } + + charging_type_det_done = KAL_FALSE; + *(CHARGER_TYPE *) (data) = hw_charging_get_charger_type(); + charging_type_det_done = KAL_TRUE; + g_charger_type = *(CHARGER_TYPE *) (data); + +#endif + + return status; +} + +static int charging_get_is_pcm_timer_trigger(void *data) +{ + int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = KAL_FALSE; +#else + if (slp_get_wake_reason() == WR_PCM_TIMER) + *(kal_bool *) (data) = KAL_TRUE; + else + *(kal_bool *) (data) = KAL_FALSE; + + battery_log(BAT_LOG_CRTI, "slp_get_wake_reason=%d\n", slp_get_wake_reason()); +#endif + + return status; +} + +static int charging_set_platform_reset(void *data) +{ + int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + battery_log(BAT_LOG_CRTI, "charging_set_platform_reset\n"); + kernel_restart("battery service reboot system"); +#endif + + return status; +} + +static int charging_get_platform_boot_mode(void *data) +{ + int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + *(unsigned int *) (data) = get_boot_mode(); + + battery_log(BAT_LOG_CRTI, "get_boot_mode=%d\n", get_boot_mode()); +#endif + + return status; +} + +static int charging_set_power_off(void *data) +{ + int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + /*added dump_stack to see who the caller is */ + dump_stack(); + battery_log(BAT_LOG_CRTI, "charging_set_power_off\n"); + kernel_power_off(); +#endif + + return status; +} + +static int charging_get_power_source(void *data) +{ + int status = STATUS_OK; + +#if 0 /* #if defined(MTK_POWER_EXT_DETECT) */ + if (MT_BOARD_PHONE == mt_get_board_type()) + *(kal_bool *) data = KAL_FALSE; + else + *(kal_bool *) data = KAL_TRUE; +#else + *(kal_bool *) data = KAL_FALSE; +#endif + + return status; +} + +static int charging_get_csdac_full_flag(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static int charging_set_ta_current_pattern(void *data) +{ + kal_bool pumpup; + unsigned int increase; + + pumpup = *(kal_bool *) (data); + if (pumpup == KAL_TRUE) + increase = 1; + else + increase = 0; + /*unsigned int charging_status = KAL_FALSE; */ +#if 1 + bq25890_pumpx_up(increase); + battery_log(BAT_LOG_FULL, "Pumping up adaptor..."); + +#else + if (increase == KAL_TRUE) { + bq25890_set_ichg(0x0); /* 64mA */ + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 1"); + msleep(85); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 1"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 2"); + msleep(85); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 2"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 3"); + msleep(281); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 3"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 4"); + msleep(281); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 4"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 5"); + msleep(281); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 5"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 6"); + msleep(485); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 6"); + msleep(50); + + battery_log(BAT_LOG_CRTI, "mtk_ta_increase() end\n"); + + bq25890_set_ichg(0x8); /* 512mA */ + msleep(200); + } else { + bq25890_set_ichg(0x0); /* 64mA */ + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 1"); + msleep(281); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 1"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 2"); + msleep(281); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 2"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 3"); + msleep(281); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 3"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 4"); + msleep(85); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 4"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 5"); + msleep(85); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 5"); + msleep(85); + + bq25890_set_ichg(0x8); /* 512mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 6"); + msleep(485); + + bq25890_set_ichg(0x0); /* 64mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 6"); + msleep(50); + + battery_log(BAT_LOG_CRTI, "mtk_ta_decrease() end\n"); + + bq25890_set_ichg(0x8); /* 512mA */ + } +#endif + return STATUS_OK; +} + +static int charging_set_vindpm(void *data) +{ + int status = STATUS_OK; + unsigned int v = *(unsigned int *) data; + + bq25890_set_vindpm(v); + + return status; +} + +static int charging_set_vbus_ovp_en(void *data) +{ + int status = STATUS_OK; + unsigned int e = *(unsigned int *) data; + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_RG_VCDT_HV_EN, e); +#else + pmic_set_register_value(MT6351_PMIC_RG_VCDT_HV_EN, e); +#endif + + return status; +} + +static int charging_get_bif_vbat(void *data) +{ + int ret = 0; + u32 vbat = 0; + + ret = mtk_bif_get_vbat(&vbat); + if (ret < 0) + return STATUS_UNSUPPORTED; + + *((u32 *)data) = vbat; + + return STATUS_OK; +} + +static int charging_get_bif_tbat(void *data) +{ + int ret = 0, tbat = 0; + + ret = mtk_bif_get_tbat(&tbat); + if (ret < 0) + return STATUS_UNSUPPORTED; + + *((int *)data) = tbat; + + return STATUS_OK; +} + +static int charging_diso_init(void *data) +{ + int status = STATUS_OK; + +#if defined(MTK_DUAL_INPUT_CHARGER_SUPPORT) + struct device_node *node; + DISO_ChargerStruct *pDISO_data = (DISO_ChargerStruct *) data; + + int ret; + /* Initialization DISO Struct */ + pDISO_data->diso_state.cur_otg_state = DISO_OFFLINE; + pDISO_data->diso_state.cur_vusb_state = DISO_OFFLINE; + pDISO_data->diso_state.cur_vdc_state = DISO_OFFLINE; + + pDISO_data->diso_state.pre_otg_state = DISO_OFFLINE; + pDISO_data->diso_state.pre_vusb_state = DISO_OFFLINE; + pDISO_data->diso_state.pre_vdc_state = DISO_OFFLINE; + + pDISO_data->chr_get_diso_state = KAL_FALSE; + + pDISO_data->hv_voltage = VBUS_MAX_VOLTAGE; + + /* Initial AuxADC IRQ */ + DISO_IRQ.vdc_measure_channel.number = AP_AUXADC_DISO_VDC_CHANNEL; + DISO_IRQ.vusb_measure_channel.number = AP_AUXADC_DISO_VUSB_CHANNEL; + DISO_IRQ.vdc_measure_channel.period = AUXADC_CHANNEL_DELAY_PERIOD; + DISO_IRQ.vusb_measure_channel.period = AUXADC_CHANNEL_DELAY_PERIOD; + DISO_IRQ.vdc_measure_channel.debounce = AUXADC_CHANNEL_DEBOUNCE; + DISO_IRQ.vusb_measure_channel.debounce = AUXADC_CHANNEL_DEBOUNCE; + + /* use default threshold voltage, if use high voltage,maybe refine */ + DISO_IRQ.vusb_measure_channel.falling_threshold = VBUS_MIN_VOLTAGE / 1000; + DISO_IRQ.vdc_measure_channel.falling_threshold = VDC_MIN_VOLTAGE / 1000; + DISO_IRQ.vusb_measure_channel.rising_threshold = VBUS_MIN_VOLTAGE / 1000; + DISO_IRQ.vdc_measure_channel.rising_threshold = VDC_MIN_VOLTAGE / 1000; + + node = of_find_compatible_node(NULL, NULL, "mediatek,AUXADC"); + if (!node) { + battery_log(BAT_LOG_CRTI, "[diso_adc]: of_find_compatible_node failed!!\n"); + } else { + pDISO_data->irq_line_number = irq_of_parse_and_map(node, 0); + battery_log(BAT_LOG_FULL, "[diso_adc]: IRQ Number: 0x%x\n", + pDISO_data->irq_line_number); + } + + mt_irq_set_sens(pDISO_data->irq_line_number, MT_EDGE_SENSITIVE); + mt_irq_set_polarity(pDISO_data->irq_line_number, MT_POLARITY_LOW); + + ret = request_threaded_irq(pDISO_data->irq_line_number, diso_auxadc_irq_handler, + pDISO_data->irq_callback_func, IRQF_ONESHOT, "DISO_ADC_IRQ", + NULL); + + if (ret) { + battery_log(BAT_LOG_CRTI, "[diso_adc]: request_irq failed.\n"); + } else { + set_vdc_auxadc_irq(DISO_IRQ_DISABLE, 0); + set_vusb_auxadc_irq(DISO_IRQ_DISABLE, 0); + battery_log(BAT_LOG_FULL, "[diso_adc]: diso_init success.\n"); + } + +#if defined(MTK_DISCRETE_SWITCH) && defined(MTK_DSC_USE_EINT) + battery_log(BAT_LOG_CRTI, "[diso_eint]vdc eint irq registitation\n"); + mt_eint_set_hw_debounce(CUST_EINT_VDC_NUM, CUST_EINT_VDC_DEBOUNCE_CN); + mt_eint_registration(CUST_EINT_VDC_NUM, CUST_EINTF_TRIGGER_LOW, vdc_eint_handler, 0); + mt_eint_mask(CUST_EINT_VDC_NUM); +#endif +#endif + + return status; +} + +static int charging_get_diso_state(void *data) +{ + int status = STATUS_OK; + +#if defined(MTK_DUAL_INPUT_CHARGER_SUPPORT) + int diso_state = 0x0; + DISO_ChargerStruct *pDISO_data = (DISO_ChargerStruct *) data; + + _get_diso_interrupt_state(); + diso_state = g_diso_state; + battery_log(BAT_LOG_FULL, "[do_chrdet_int_task] current diso state is %s!\n", + DISO_state_s[diso_state]); + if (((diso_state >> 1) & 0x3) != 0x0) { + switch (diso_state) { + case USB_ONLY: + set_vdc_auxadc_irq(DISO_IRQ_DISABLE, 0); + set_vusb_auxadc_irq(DISO_IRQ_DISABLE, 0); +#ifdef MTK_DISCRETE_SWITCH +#ifdef MTK_DSC_USE_EINT + mt_eint_unmask(CUST_EINT_VDC_NUM); +#else + set_vdc_auxadc_irq(DISO_IRQ_ENABLE, 1); +#endif +#endif + pDISO_data->diso_state.cur_vusb_state = DISO_ONLINE; + pDISO_data->diso_state.cur_vdc_state = DISO_OFFLINE; + pDISO_data->diso_state.cur_otg_state = DISO_OFFLINE; + break; + case DC_ONLY: + set_vdc_auxadc_irq(DISO_IRQ_DISABLE, 0); + set_vusb_auxadc_irq(DISO_IRQ_DISABLE, 0); + set_vusb_auxadc_irq(DISO_IRQ_ENABLE, DISO_IRQ_RISING); + pDISO_data->diso_state.cur_vusb_state = DISO_OFFLINE; + pDISO_data->diso_state.cur_vdc_state = DISO_ONLINE; + pDISO_data->diso_state.cur_otg_state = DISO_OFFLINE; + break; + case DC_WITH_USB: + set_vdc_auxadc_irq(DISO_IRQ_DISABLE, 0); + set_vusb_auxadc_irq(DISO_IRQ_DISABLE, 0); + set_vusb_auxadc_irq(DISO_IRQ_ENABLE, DISO_IRQ_FALLING); + pDISO_data->diso_state.cur_vusb_state = DISO_ONLINE; + pDISO_data->diso_state.cur_vdc_state = DISO_ONLINE; + pDISO_data->diso_state.cur_otg_state = DISO_OFFLINE; + break; + case DC_WITH_OTG: + set_vdc_auxadc_irq(DISO_IRQ_DISABLE, 0); + set_vusb_auxadc_irq(DISO_IRQ_DISABLE, 0); + pDISO_data->diso_state.cur_vusb_state = DISO_OFFLINE; + pDISO_data->diso_state.cur_vdc_state = DISO_ONLINE; + pDISO_data->diso_state.cur_otg_state = DISO_ONLINE; + break; + default: /* OTG only also can trigger vcdt IRQ */ + pDISO_data->diso_state.cur_vusb_state = DISO_OFFLINE; + pDISO_data->diso_state.cur_vdc_state = DISO_OFFLINE; + pDISO_data->diso_state.cur_otg_state = DISO_ONLINE; + battery_log(BAT_LOG_FULL, " switch load vcdt irq triggerd by OTG Boost!\n"); + break; /* OTG plugin no need battery sync action */ + } + } + + if (DISO_ONLINE == pDISO_data->diso_state.cur_vdc_state) + pDISO_data->hv_voltage = VDC_MAX_VOLTAGE; + else + pDISO_data->hv_voltage = VBUS_MAX_VOLTAGE; +#endif + + return status; +} + +static unsigned int charging_get_error_state(void) +{ + return charging_error; +} + +static int charging_set_hiz_swchr(void *data); +static int charging_set_error_state(void *data) +{ + int status = STATUS_OK; + + charging_error = *(unsigned int *) (data); + charging_set_hiz_swchr(&charging_error); + + return status; +} + +static int charging_set_chrind_ck_pdn(void *data) +{ + int status = STATUS_OK; + unsigned int pwr_dn; + + pwr_dn = *(unsigned int *) data; + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pmic_set_register_value(PMIC_CLK_DRV_CHRIND_CK_PDN, pwr_dn); +#else + pmic_set_register_value(PMIC_RG_DRV_CHRIND_CK_PDN, pwr_dn); +#endif + + return status; +} + +static int charging_sw_init(void *data) +{ + int status = STATUS_OK; + /*put here anything needed to be init upon battery_common driver probe*/ + mtk_bif_init(); + + bq25890_config_interface(bq25890_CON0, 0x01, 0x01, 6); /* enable ilimit Pin */ + /*DPM*/ bq25890_config_interface(bq25890_CON1, 0x6, 0xF, 0); /* Vindpm offset 600MV */ + bq25890_config_interface(bq25890_COND, 0x1, 0x1, 7); /* vindpm vth 0:relative 1:absolute */ + + /*CC mode */ + bq25890_config_interface(bq25890_CON4, 0x08, 0x7F, 0); /* ICHG (0x08)512mA --> (0x20)2.048mA */ + /*Vbus current limit */ + bq25890_config_interface(bq25890_CON0, 0x3F, 0x3F, 0); /* input current limit, IINLIM, 3.25A */ + + /* absolute VINDPM = 2.6 + code x 0.1 =4.5V;K2 24261 4.452V */ + bq25890_config_interface(bq25890_COND, 0x13, 0x7F, 0); + + /*CV mode */ + bq25890_config_interface(bq25890_CON6, 0x20, 0x3F, 2); /* VREG=CV 4.352V (default 4.208V) */ + + /* upmu_set_rg_vcdt_hv_en(0); */ + + /* The following setting is moved from HW_INIT */ + bq25890_config_interface(bq25890_CON2, 0x1, 0x1, 4); /* disable ico Algorithm -->bear:en */ + bq25890_config_interface(bq25890_CON2, 0x0, 0x1, 3); /* disable HV DCP for gq25897 */ + bq25890_config_interface(bq25890_CON2, 0x0, 0x1, 2); /* disbale MaxCharge for gq25897 */ + bq25890_config_interface(bq25890_CON2, 0x0, 0x1, 1); /* disable DPDM detection */ + + bq25890_config_interface(bq25890_CON7, 0x1, 0x3, 4); /* enable watch dog 40 secs 0x1 */ + bq25890_config_interface(bq25890_CON7, 0x1, 0x1, 3); /* enable charging timer safety timer */ + bq25890_config_interface(bq25890_CON7, 0x2, 0x3, 1); /* charging timer 12h */ + + bq25890_config_interface(bq25890_CON2, 0x0, 0x1, 5); /* boost freq 1.5MHz when OTG_CONFIG=1 */ + bq25890_config_interface(bq25890_CONA, 0x7, 0xF, 4); /* boost voltagte 4.998V default */ + bq25890_config_interface(bq25890_CONA, 0x3, 0x7, 0); /* boost current limit 1.3A */ +#ifdef CONFIG_MTK_BIF_SUPPORT + bq25890_config_interface(bq25890_CON8, 0x0, 0x7, 5); /* disable ir_comp_resistance */ + bq25890_config_interface(bq25890_CON8, 0x0, 0x7, 2); /* disable ir_comp_vdamp */ +#else + bq25890_config_interface(bq25890_CON8, 0x4, 0x7, 5); /* enable ir_comp_resistance */ + bq25890_config_interface(bq25890_CON8, 0x6, 0x7, 2); /* enable ir_comp_vdamp */ +#endif + bq25890_config_interface(bq25890_CON8, 0x3, 0x3, 0); /* thermal 120 default */ + + bq25890_config_interface(bq25890_CON9, 0x0, 0x1, 4); /* JEITA_VSET: VREG-200mV */ + bq25890_config_interface(bq25890_CON7, 0x1, 0x1, 0); /* JEITA_ISet : 20% x ICHG */ + + bq25890_config_interface(bq25890_CON3, 0x5, 0x7, 1); /* System min voltage default 3.5V */ + + /*PreCC mode */ + bq25890_config_interface(bq25890_CON5, 0x1, 0xF, 4); /* precharge current default 128mA */ + bq25890_config_interface(bq25890_CON6, 0x1, 0x1, 1); /* precharge2cc voltage,BATLOWV, 3.0V */ + /*CV mode */ + bq25890_config_interface(bq25890_CON6, 0x0, 0x1, 0); /* recharge voltage@VRECHG=CV-100MV */ + bq25890_config_interface(bq25890_CON7, 0x1, 0x1, 7); /* disable ICHG termination detect */ + bq25890_config_interface(bq25890_CON5, 0x1, 0x7, 0); /* termianation current default 128mA */ + + return status; +} + +static int charging_enable_safetytimer(void *data) +{ + int status = STATUS_OK; + unsigned int en; + + en = *(unsigned int *) data; + bq25890_en_chg_timer(en); + + return status; +} + +static int charging_set_hiz_swchr(void *data) +{ + int status = STATUS_OK; + unsigned int en; + unsigned int vindpm; + + en = *(unsigned int *) data; + if (en == 1) + vindpm = 0x7F; + else + vindpm = 0x13; + + charging_set_vindpm(&vindpm); + /*bq25890_set_en_hiz(en);*/ + + return status; +} + +static int charging_get_is_power_path_enable(void *data); +static int charging_set_vindpm_voltage(void *data) +{ + int status = STATUS_OK; + unsigned int vindpm; + unsigned int array_size; + bool is_power_path_enable = true; + int ret = 0; + + array_size = GETARRAYNUM(VINDPM_REG); + vindpm = bmt_find_closest_level(VINDPM_REG, array_size, *(unsigned int *) data); + vindpm = charging_parameter_to_value(VINDPM_REG, array_size, vindpm); + + /* + * Since BQ25896 uses vindpm to turn off power path + * If power path is disabled, do not adjust mivr + */ + ret = charging_get_is_power_path_enable(&is_power_path_enable); + if (ret == 0 && !is_power_path_enable) { + battery_log(BAT_LOG_CRTI, + "%s: power path is disable, skip setting vindpm = %d\n", + __func__, vindpm); + return 0; + } + + charging_set_vindpm(&vindpm); + /*bq25890_set_en_hiz(en);*/ + + return status; +} + +static int charging_set_ta20_reset(void *data) +{ + bq25890_set_vindpm(0x13); + bq25890_set_ichg(8); + + bq25890_set_ico_en_start(0); + bq25890_set_iinlim(0x0); + msleep(250); + bq25890_set_iinlim(0xc); + bq25890_set_ico_en_start(1); + return STATUS_OK; +} + +struct timespec ptime[13]; +static int cptime[13][2]; + +static int dtime(int i) +{ + struct timespec time; + + time = timespec_sub(ptime[i], ptime[i-1]); + return time.tv_nsec/1000000; +} + +#define PEOFFTIME 40 +#define PEONTIME 90 + +static int charging_set_ta20_current_pattern(void *data) +{ + int value; + int i, j = 0; + int flag; + CHR_VOLTAGE_ENUM chr_vol = *(CHR_VOLTAGE_ENUM *) data; + + + bq25890_set_vindpm(0x13); + bq25890_set_ichg(8); + bq25890_set_ico_en_start(0); + + usleep_range(1000, 1200); + value = (chr_vol - CHR_VOLT_05_500000_V) / CHR_VOLT_00_500000_V; + + bq25890_set_iinlim(0x0); + msleep(70); + + get_monotonic_boottime(&ptime[j++]); + for (i = 4; i >= 0; i--) { + flag = value & (1 << i); + + if (flag == 0) { + bq25890_set_iinlim(0xc); + msleep(PEOFFTIME); + get_monotonic_boottime(&ptime[j]); + cptime[j][0] = PEOFFTIME; + cptime[j][1] = dtime(j); + if (cptime[j][1] < 30 || cptime[j][1] > 65) { + battery_log(BAT_LOG_CRTI, + "charging_set_ta20_current_pattern fail1: idx:%d target:%d actual:%d\n", + i, PEOFFTIME, cptime[j][1]); + return STATUS_FAIL; + } + j++; + bq25890_set_iinlim(0x0); + msleep(PEONTIME); + get_monotonic_boottime(&ptime[j]); + cptime[j][0] = PEONTIME; + cptime[j][1] = dtime(j); + if (cptime[j][1] < 90 || cptime[j][1] > 115) { + battery_log(BAT_LOG_CRTI, + "charging_set_ta20_current_pattern fail2: idx:%d target:%d actual:%d\n", + i, PEOFFTIME, cptime[j][1]); + return STATUS_FAIL; + } + j++; + + } else { + bq25890_set_iinlim(0xc); + msleep(PEONTIME); + get_monotonic_boottime(&ptime[j]); + cptime[j][0] = PEONTIME; + cptime[j][1] = dtime(j); + if (cptime[j][1] < 90 || cptime[j][1] > 115) { + battery_log(BAT_LOG_CRTI, + "charging_set_ta20_current_pattern fail3: idx:%d target:%d actual:%d\n", + i, PEOFFTIME, cptime[j][1]); + return STATUS_FAIL; + } + j++; + bq25890_set_iinlim(0x0); + msleep(PEOFFTIME); + get_monotonic_boottime(&ptime[j]); + cptime[j][0] = PEOFFTIME; + cptime[j][1] = dtime(j); + if (cptime[j][1] < 30 || cptime[j][1] > 65) { + battery_log(BAT_LOG_CRTI, + "charging_set_ta20_current_pattern fail4: idx:%d target:%d actual:%d\n", + i, PEOFFTIME, cptime[j][1]); + return STATUS_FAIL; + } + j++; + } + } + + bq25890_set_iinlim(0xc); + msleep(160); + get_monotonic_boottime(&ptime[j]); + cptime[j][0] = 160; + cptime[j][1] = dtime(j); + if (cptime[j][1] < 150 || cptime[j][1] > 240) { + battery_log(BAT_LOG_CRTI, + "charging_set_ta20_current_pattern fail5: idx:%d target:%d actual:%d\n", + i, PEOFFTIME, cptime[j][1]); + return STATUS_FAIL; + } + j++; + + bq25890_set_iinlim(0x0); + msleep(30); + bq25890_set_iinlim(0xc); + + battery_log(BAT_LOG_CRTI, + "[charging_set_ta20_current_pattern]:chr_vol:%d bit:%d time:%3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d!!\n", + chr_vol, value, + cptime[1][0], cptime[2][0], cptime[3][0], cptime[4][0], cptime[5][0], + cptime[6][0], cptime[7][0], cptime[8][0], cptime[9][0], cptime[10][0], cptime[11][0]); + + battery_log(BAT_LOG_CRTI, + "[charging_set_ta20_current_pattern2]:chr_vol:%d bit:%d time:%3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d!!\n", + chr_vol, value, + cptime[1][1], cptime[2][1], cptime[3][1], cptime[4][1], cptime[5][1], + cptime[6][1], cptime[7][1], cptime[8][1], cptime[9][1], cptime[10][1], cptime[11][1]); + + + bq25890_set_ico_en_start(1); + bq25890_set_iinlim(0x3f); + + return STATUS_OK; +} + +static int charging_set_dp(void *data) +{ + unsigned int status = STATUS_OK; + +#ifndef CONFIG_POWER_EXT + unsigned int en; + + en = *(int *) data; + hw_charging_enable_dp_voltage(en); +#endif + + return status; +} + +static int charging_get_charger_temperature(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static int charging_set_boost_current_limit(void *data) +{ + int ret = 0; + unsigned int current_limit = 0, reg_ilim = 0; + + current_limit = *((unsigned int *)data); + current_limit = bmt_find_closest_level(BOOST_CURRENT_LIMIT, + ARRAY_SIZE(BOOST_CURRENT_LIMIT), current_limit); + reg_ilim = charging_parameter_to_value(BOOST_CURRENT_LIMIT, + ARRAY_SIZE(BOOST_CURRENT_LIMIT), current_limit); + bq25890_set_boost_ilim(reg_ilim); + + return ret; +} + +static int charging_enable_otg(void *data) +{ + int ret = 0; + unsigned int enable = 0; + + enable = *((unsigned int *)data); + bq25890_otg_en(enable); + + return ret; +} + +static int charging_enable_power_path(void *data) +{ + int ret = 0; + unsigned int enable = 0; + + enable = *((unsigned int *)data); + bq25890_set_force_vindpm(1); + if (enable) + bq25890_set_vindpm(0x13); + else + bq25890_set_vindpm(0x7F); + + return ret; +} + +static int charging_get_bif_is_exist(void *data) +{ + int bif_exist = 0; + + bif_exist = mtk_bif_is_hw_exist(); + *(bool *)data = bif_exist; + + return 0; +} + +static int charging_get_input_current(void *data) +{ + int ret = 0; + + *((u32 *)data) = g_input_current; + + return ret; +} + +static int charging_enable_direct_charge(void *data) +{ + return -ENOTSUPP; +} + +static int charging_get_is_power_path_enable(void *data) +{ + int ret = 0; + u32 reg_vindpm = 0; + + reg_vindpm = bq25890_get_vindpm(); + *((bool *)data) = (reg_vindpm == 0x7F) ? false : true; + + return ret; +} + +static int charging_get_is_safetytimer_enable(void *data) +{ + int ret = 0; + u32 reg_safetytimer = 0; + + reg_safetytimer = bq25890_get_chg_timer_enable(); + *((bool *)data) = (reg_safetytimer) ? true : false; + + return ret; +} + +static int charging_set_pwrstat_led_en(void *data) +{ + int ret = 0; + unsigned int led_en; + + led_en = *(unsigned int *) data; + + pmic_set_register_value(PMIC_CHRIND_MODE, 0x2); /* register mode */ + pmic_set_register_value(PMIC_CHRIND_EN_SEL, !led_en); /* 0: Auto, 1: SW */ + pmic_set_register_value(PMIC_CHRIND_EN, led_en); + + return ret; +} + +static int charging_get_ibus(void *data) +{ + return -ENOTSUPP; +} + +static int charging_get_vbus(void *data) +{ + return -ENOTSUPP; +} + +static int charging_reset_dc_watch_dog_timer(void *data) +{ + return -ENOTSUPP; +} + +static int charging_run_aicl(void *data) +{ + return -ENOTSUPP; +} + +static int charging_set_ircmp_resistor(void *data) +{ + u32 resistor = 0; + u8 reg_resistor = 0; + + resistor = *((unsigned int *)data); + resistor = bmt_find_closest_level(IRCMP_RESISTOR, + ARRAY_SIZE(IRCMP_RESISTOR), resistor); + reg_resistor = charging_parameter_to_value(IRCMP_RESISTOR, + ARRAY_SIZE(IRCMP_RESISTOR), resistor); + bq25890_set_VBAT_IR_compensation(reg_resistor); + + return 0; +} + +static int charging_set_ircmp_volt_clamp(void *data) +{ + u32 volt_clamp = 0; + u8 reg_volt_clamp = 0; + + volt_clamp = *((unsigned int *)data); + volt_clamp = bmt_find_closest_level(IRCMP_VOLT_CLAMP, + ARRAY_SIZE(IRCMP_VOLT_CLAMP), volt_clamp); + reg_volt_clamp = charging_parameter_to_value(IRCMP_VOLT_CLAMP, + ARRAY_SIZE(IRCMP_VOLT_CLAMP), volt_clamp); + bq25890_set_VBAT_clamp(reg_volt_clamp); + + return 0; +} + +static int (*const charging_func[CHARGING_CMD_NUMBER]) (void *data) = { + charging_hw_init, charging_dump_register, charging_enable, charging_set_cv_voltage, + charging_get_current, charging_set_current, charging_set_input_current, + charging_get_charging_status, charging_reset_watch_dog_timer, + charging_set_hv_threshold, charging_get_hv_status, charging_get_battery_status, + charging_get_charger_det_status, charging_get_charger_type, + charging_get_is_pcm_timer_trigger, charging_set_platform_reset, + charging_get_platform_boot_mode, charging_set_power_off, + charging_get_power_source, charging_get_csdac_full_flag, + charging_set_ta_current_pattern, charging_set_error_state, charging_diso_init, + charging_get_diso_state, charging_set_vindpm_voltage, charging_set_vbus_ovp_en, + charging_get_bif_vbat, charging_set_chrind_ck_pdn, charging_sw_init, charging_enable_safetytimer, + charging_set_hiz_swchr, charging_get_bif_tbat, charging_set_ta20_reset, + charging_set_ta20_current_pattern, charging_set_dp, charging_get_charger_temperature, + charging_set_boost_current_limit, charging_enable_otg, charging_enable_power_path, + charging_get_bif_is_exist, charging_get_input_current, charging_enable_direct_charge, + charging_get_is_power_path_enable, charging_get_is_safetytimer_enable, + charging_set_pwrstat_led_en, charging_get_ibus, charging_get_vbus, + charging_reset_dc_watch_dog_timer, charging_run_aicl, charging_set_ircmp_resistor, + charging_set_ircmp_volt_clamp, +}; + +/* +* FUNCTION +* Internal_chr_control_handler +* +* DESCRIPTION +* This function is called to set the charger hw +* +* CALLS +* +* PARAMETERS +* None +* +* RETURNS +* +* +* GLOBALS AFFECTED +* None +*/ +int chr_control_interface(CHARGING_CTRL_CMD cmd, void *data) +{ + int status; + + if (cmd < CHARGING_CMD_NUMBER) { + if (charging_func[cmd] != NULL) + status = charging_func[cmd](data); + else { + battery_log(BAT_LOG_CRTI, "[chr_control_interface]cmd:%d not supported\n", cmd); + status = STATUS_UNSUPPORTED; + } + } else + status = STATUS_UNSUPPORTED; + + return status; +} diff --git a/drivers/misc/mediatek/power/mt6755/charging_hw_ncp1854.c b/drivers/misc/mediatek/power/mt6755/charging_hw_ncp1854.c new file mode 100755 index 0000000000000000000000000000000000000000..007f977e1c78fb72fa1c447c1bd85725351375a4 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/charging_hw_ncp1854.c @@ -0,0 +1,803 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ncp1854.h" + +/* ============================================================ // */ +/* Define */ +/* ============================================================ // */ +#define STATUS_OK 0 +#define STATUS_FAIL 1 +#define STATUS_UNSUPPORTED -1 +#define GETARRAYNUM(array) (sizeof(array)/sizeof(array[0])) + + +/* ============================================================ // */ +/* Global variable */ +/* ============================================================ // */ + +#if defined(MTK_WIRELESS_CHARGER_SUPPORT) +#define WIRELESS_CHARGER_EXIST_STATE 0 + +#if defined(GPIO_PWR_AVAIL_WLC) +unsigned int wireless_charger_gpio_number = GPIO_PWR_AVAIL_WLC; +#else +unsigned int wireless_charger_gpio_number = 0; +#endif + +#endif + +/* As 82 platform mach/charging.h could not cover all voltage setting, just hardcoded below settings */ +const unsigned int VBAT_CV_VTH[] = { + 3300000, 3325000, 3350000, 3375000, + 3400000, 3425000, 3450000, 3475000, + 3500000, 3525000, 3550000, 3575000, + 3600000, 3625000, 3650000, 3675000, + 3700000, 3725000, 3750000, 3775000, + 3800000, 3825000, 3850000, 3875000, + 3900000, 3925000, 3950000, 3975000, + 4000000, 4025000, 4050000, 4075000, + 4100000, 4125000, 4150000, 4175000, + 4200000, 4225000, 4250000, 4275000, + 4300000, 4325000, 4350000, 4375000, + 4400000, 4425000, 4450000, 4475000, +}; + +/* hardcoded current define which defined in NCP1854 IC spec, as common define doesnot cover all define + * double confirmed with onsemi register set in spec has issue,below is the correct setting */ +const unsigned int CS_VTH[] = { + 45000, 50000, 60000, 70000, + 80000, 90000, 100000, 110000, + 120000, 130000, 140000, 150000, + 160000, 170000, 180000, 190000 +}; + +const unsigned int INPUT_CS_VTH[] = { + CHARGE_CURRENT_100_00_MA, CHARGE_CURRENT_500_00_MA +}; + +const unsigned int INPUT_CS_VTH_TA[] = { + CHARGE_CURRENT_600_00_MA, CHARGE_CURRENT_700_00_MA, CHARGE_CURRENT_800_00_MA, + CHARGE_CURRENT_900_00_MA, CHARGE_CURRENT_1000_00_MA, CHARGE_CURRENT_1100_00_MA, + CHARGE_CURRENT_1200_00_MA, CHARGE_CURRENT_1300_00_MA, CHARGE_CURRENT_1400_00_MA, + CHARGE_CURRENT_1500_00_MA, CHARGE_CURRENT_1600_00_MA, 170000, + 180000, 190000, 200000 +}; + +const unsigned int VCDT_HV_VTH[] = { + BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_300000_V, + BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_500000_V, + BATTERY_VOLT_04_550000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_06_000000_V, BATTERY_VOLT_06_500000_V, + BATTERY_VOLT_07_000000_V, + BATTERY_VOLT_07_500000_V, BATTERY_VOLT_08_500000_V, BATTERY_VOLT_09_500000_V, + BATTERY_VOLT_10_500000_V +}; + +/* ============================================================ // */ +/* function prototype */ +/* ============================================================ // */ + +/* ============================================================ // */ +/* extern variable */ +/* ============================================================ // */ + +/* ============================================================ // */ +/* extern function */ +/* ============================================================ // */ +unsigned int current_high_flag = 0; + +/* ============================================================ // */ +unsigned int charging_value_to_parameter(const unsigned int *parameter, const unsigned int array_size, + const unsigned int val) +{ + unsigned int temp_param; + + if (val < array_size) { + temp_param = parameter[val]; + } else { + battery_log(BAT_LOG_CRTI, "Can't find the parameter \r\n"); + temp_param = parameter[0]; + } + return temp_param; +} + +unsigned int charging_parameter_to_value(const unsigned int *parameter, const unsigned int array_size, + const unsigned int val) +{ + unsigned int i; + + battery_log(BAT_LOG_FULL, "array_size = %d \r\n", array_size); + + for (i = 0; i < array_size; i++) { + if (val == *(parameter + i)) + return i; + } + + battery_log(BAT_LOG_CRTI, "NO register value match. val=%d\r\n", val); + + return 0; +} + +static unsigned int bmt_find_closest_level(const unsigned int *pList, unsigned int number, + unsigned int level) +{ + unsigned int i, temp_param; + unsigned int max_value_in_last_element; + + if (pList[0] < pList[1]) + max_value_in_last_element = KAL_TRUE; + else + max_value_in_last_element = KAL_FALSE; + + if (max_value_in_last_element == KAL_TRUE) { + /* max value in the last element */ + for (i = (number - 1); i != 0; i--) { + if (pList[i] <= level) + return pList[i]; + } + + battery_log(BAT_LOG_CRTI, "Can't find closest level, small value first \r\n"); + temp_param = pList[0]; + } else { + /* max value in the first element */ + for (i = 0; i < number; i++) { + if (pList[i] <= level) + return pList[i]; + } + + battery_log(BAT_LOG_CRTI, "Can't find closest level, large value first \r\n"); + temp_param = pList[number - 1]; + } + return temp_param; +} + +static unsigned int charging_hw_init(void *data) +{ + unsigned int ncp1854_status; + unsigned int status = STATUS_OK; + + pr_notice("[BATTERY:ncp1854] ChargerHwInit_ncp1854\n"); + + ncp1854_status = ncp1854_get_chip_status(); + ncp1854_set_trans_en(0); + ncp1854_set_tj_warn_opt(0x0); /* set at disabled, by MT6325 BATON */ + /* ncp1854_set_int_mask(0x0); //disable all interrupt */ + ncp1854_set_int_mask(0x1); /* enable all interrupt for boost mode status monitor */ + /* ncp1854_set_tchg_rst(0x1); //reset charge timer */ + ncp1854_set_chgto_dis(0x1); /* disable charge timer */ + /* WEAK WAIT, WEAK SAFE, WEAK CHARGE */ + if ((ncp1854_status == 0x8) || (ncp1854_status == 0x9) || (ncp1854_status == 0xA)) + ncp1854_set_ctrl_vbat(0x1C); /* VCHG = 4.0V */ + +/* Vanzo:zhangqingzhan on: Mon, 26 Dec 2016 14:32:32 +0800 + * fix bug #126376 + ncp1854_set_ieoc(0x6); // cut off current = 100mA + */ + ncp1854_set_ieoc(0x0); /* cut off current = 250mA */ +// End of Vanzo: zhangqingzhan + ncp1854_set_iweak(0x3); /* weak charge current = 300mA */ + + ncp1854_set_aicl_en(0x1); /* enable AICL as PT team suggest */ + ncp1854_set_iinset_pin_en(0x0); /* Input current limit and AICL control by I2C */ + ncp1854_set_ctrl_vfet(0x3); /* VFET = 3.4V */ + +#if defined(MTK_WIRELESS_CHARGER_SUPPORT) + if (wireless_charger_gpio_number != 0) { + mt_set_gpio_mode(wireless_charger_gpio_number, 0); /* 0:GPIO mode */ + mt_set_gpio_dir(wireless_charger_gpio_number, 0); /* 0: input, 1: output */ + } +#endif + + return status; +} + +static unsigned int charging_dump_register(void *data) +{ + unsigned int status = STATUS_OK; + + pr_notice("charging_dump_register\r\n"); + + ncp1854_dump_register(); + + return status; +} + +static unsigned int charging_enable(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int enable = *(unsigned int *) (data); + + if (KAL_TRUE == enable) { + ncp1854_set_chg_en(0x1); /* charger enable */ + /* Set SPM = 1 */ +#ifdef GPIO_SWCHARGER_EN_PIN + mt_set_gpio_mode(GPIO_SWCHARGER_EN_PIN, GPIO_MODE_00); + mt_set_gpio_dir(GPIO_SWCHARGER_EN_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_SWCHARGER_EN_PIN, GPIO_OUT_ONE); +#endif + } else { +#if defined(CONFIG_USB_MTK_HDRC_HCD) + if (mt_usb_is_device()) { +#endif + ncp1854_set_chg_en(0x0); /* charger disable */ +#if defined(CONFIG_USB_MTK_HDRC_HCD) + } +#endif + } + + return status; +} + +static unsigned int charging_set_cv_voltage(void *data) +{ + unsigned int status = STATUS_OK; + unsigned short register_value; + unsigned int cv_value = *(unsigned int *) (data); + unsigned int array_size; + unsigned int set_chr_cv; + + if (batt_cust_data.high_battery_voltage_support) + cv_value = BATTERY_VOLT_04_350000_V; + + /* use nearest value */ + array_size = GETARRAYNUM(VBAT_CV_VTH); + set_chr_cv = bmt_find_closest_level(VBAT_CV_VTH, array_size, cv_value); + + register_value = + charging_parameter_to_value(VBAT_CV_VTH, GETARRAYNUM(VBAT_CV_VTH), set_chr_cv); + + ncp1854_set_ctrl_vbat(register_value); + + return status; +} + + +static unsigned int charging_get_current(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int array_size; + unsigned char ret_val = 0; + + /* Get current level */ + /* ret_val = ncp1854_get_ichg(); */ + /* ncp1854_read_interface(NCP1854_CON15, &ret_val, CON15_ICHG_MASK, CON15_ICHG_SHIFT); */ + /* Parsing */ + /* ret_val = (ret_val*100) + 400; */ + + array_size = GETARRAYNUM(CS_VTH); + ret_val = ncp1854_get_ichg(); /* IINLIM */ + if (current_high_flag == 1) + *(unsigned int *) data = + charging_value_to_parameter(CS_VTH, array_size, ret_val) + 160000; + else + *(unsigned int *) data = charging_value_to_parameter(CS_VTH, array_size, ret_val); + + return status; +} + +static unsigned int charging_set_current(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int set_chr_current; + unsigned int array_size; + unsigned int register_value; + unsigned int current_value = *(unsigned int *) data; + + array_size = GETARRAYNUM(CS_VTH); + if (current_value <= 190000) { + set_chr_current = bmt_find_closest_level(CS_VTH, array_size, current_value); + register_value = charging_parameter_to_value(CS_VTH, array_size, set_chr_current); + current_high_flag = 0x0; + } else { + set_chr_current = + bmt_find_closest_level(CS_VTH, array_size, current_value - 160000); + register_value = charging_parameter_to_value(CS_VTH, array_size, set_chr_current); + current_high_flag = 0x1; + } + + /* current set by SW and disable automatic charge current */ + /* ncp1854_set_aicl_en(0x0); //disable AICL */ + /* set which register first? mmz */ + ncp1854_set_ichg_high(current_high_flag); + ncp1854_set_ichg(register_value); + + return status; +} + +static unsigned int charging_set_input_current(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int set_chr_current; + unsigned int array_size; + unsigned int register_value; + unsigned int current_value = *(unsigned int *) data; + + if (current_value < 60000) { + array_size = GETARRAYNUM(INPUT_CS_VTH); + set_chr_current = bmt_find_closest_level(INPUT_CS_VTH, array_size, current_value); + register_value = + charging_parameter_to_value(INPUT_CS_VTH, array_size, set_chr_current); + ncp1854_set_iinlim(register_value); + ncp1854_set_iinlim_ta(0x0); + } else { + array_size = GETARRAYNUM(INPUT_CS_VTH_TA); + set_chr_current = + bmt_find_closest_level(INPUT_CS_VTH_TA, array_size, current_value); + register_value = + charging_parameter_to_value(INPUT_CS_VTH_TA, array_size, set_chr_current); + ncp1854_set_iinlim_ta(register_value); + } + + ncp1854_set_iinlim_en(0x1); /* enable input current limit */ + return status; +} + +static unsigned int charging_get_charging_status(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int ret_val; + + ret_val = ncp1854_get_chip_status(); + /* check whether chargeing DONE */ + if (ret_val == 0x6) + *(unsigned int *) data = KAL_TRUE; + else + *(unsigned int *) data = KAL_FALSE; + + return status; +} + +void kick_charger_wdt(void) +{ + ncp1854_set_wdto_dis(0x0); +} + +static unsigned int charging_reset_watch_dog_timer(void *data) +{ + unsigned int status = STATUS_OK; + + battery_log(BAT_LOG_FULL, "charging_reset_watch_dog_timer\r\n"); + + kick_charger_wdt(); + return status; +} + +static unsigned int charging_set_hv_threshold(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int set_hv_voltage; + unsigned int array_size; + unsigned short register_value; + unsigned int voltage = *(unsigned int *) (data); + + array_size = GETARRAYNUM(VCDT_HV_VTH); + set_hv_voltage = bmt_find_closest_level(VCDT_HV_VTH, array_size, voltage); + register_value = charging_parameter_to_value(VCDT_HV_VTH, array_size, set_hv_voltage); + pmic_set_register_value(PMIC_RG_VCDT_HV_VTH, register_value); + return status; +} + +static unsigned int charging_get_hv_status(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = 0; + pr_notice("[charging_get_hv_status] charger ok for bring up.\n"); +#else + *(kal_bool *) (data) = pmic_get_register_value(PMIC_RGS_VCDT_HV_DET); +#endif + + return status; +} + +static unsigned int charging_get_battery_status(void *data) +{ + unsigned int status = STATUS_OK; +#if !defined(CONFIG_POWER_EXT) + unsigned int val = 0; +#endif + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = 0; /* battery exist */ + battery_log(BAT_LOG_CRTI, "[charging_get_battery_status] battery exist for bring up.\n"); +#else + val = pmic_get_register_value(PMIC_BATON_TDET_EN); + battery_log(BAT_LOG_FULL, "[charging_get_battery_status] BATON_TDET_EN = %d\n", val); + if (val) { + pmic_set_register_value(PMIC_BATON_TDET_EN, 1); + pmic_set_register_value(PMIC_RG_BATON_EN, 1); + *(kal_bool *) (data) = pmic_get_register_value(PMIC_RGS_BATON_UNDET); + } else { + *(kal_bool *) (data) = KAL_FALSE; + } +#endif + + return status; +} + +static unsigned int charging_get_charger_det_status(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int val = 0; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + val = 1; + battery_log(BAT_LOG_CRTI, "[charging_get_charger_det_status] chr exist for fpga.\n"); +#else + val = pmic_get_register_value(PMIC_RGS_CHRDET); +#endif + + *(kal_bool *) (data) = val; + + return status; +} + +static unsigned int charging_get_charger_type(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(CHARGER_TYPE *) (data) = STANDARD_HOST; +#else + *(CHARGER_TYPE *) (data) = hw_charging_get_charger_type(); +#endif + + return status; +} + +static unsigned int charging_get_is_pcm_timer_trigger(void *data) +{ + unsigned int status = STATUS_OK; + /* +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = KAL_FALSE; +#else + +if (slp_get_wake_reason() == WR_PCM_TIMER) + *(kal_bool *) (data) = KAL_TRUE; + else + *(kal_bool *) (data) = KAL_FALSE; + + battery_log(BAT_LOG_CRTI, "slp_get_wake_reason=%d\n", slp_get_wake_reason()); + +#endif + */ + return status; +} + +static unsigned int charging_set_platform_reset(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + battery_log(BAT_LOG_CRTI, "charging_set_platform_reset\n"); + + kernel_restart("battery service reboot system"); + /* arch_reset(0,NULL); */ +#endif + + return status; +} + +static unsigned int charging_get_platform_boot_mode(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + *(unsigned int *) (data) = get_boot_mode(); + + battery_log(BAT_LOG_CRTI, "get_boot_mode=%d\n", get_boot_mode()); +#endif + + return status; +} + +static unsigned int charging_set_power_off(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + battery_log(BAT_LOG_CRTI, "charging_set_power_off\n"); + kernel_power_off(); +#endif + + return status; +} + +static unsigned int charging_get_power_source(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static unsigned int charging_get_csdac_full_flag(void *data) +{ + return STATUS_UNSUPPORTED; +} + + +static unsigned int charging_set_ta_current_pattern(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int increase = *(unsigned int *) (data); + +#if defined(HIGH_BATTERY_VOLTAGE_SUPPORT) + BATTERY_VOLTAGE_ENUM cv_voltage = BATTERY_VOLT_04_350000_V; +#else + BATTERY_VOLTAGE_ENUM cv_voltage = BATTERY_VOLT_04_200000_V; +#endif + + charging_set_cv_voltage(&cv_voltage); /* Set CV */ + ncp1854_set_ichg(0x01); /* Set charging current 500ma */ + ncp1854_set_ichg_high(0x00); + + ncp1854_set_iinlim_ta(0x00); + ncp1854_set_iinlim(0x01); /* set charging iinlim 500ma */ + + ncp1854_set_iinlim_en(0x01); /* enable iinlim */ + ncp1854_set_chg_en(0x01); /* Enable Charging */ + + /* ncp1854_dump_register(); */ + + if (increase == KAL_TRUE) { + ncp1854_set_iinlim(0x0); /* 100mA */ + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 1"); + msleep(85); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 1"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 2"); + msleep(85); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 2"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 3"); + msleep(281); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 3"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 4"); + msleep(281); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 4"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 5"); + msleep(281); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 5"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 6"); + msleep(485); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 6"); + msleep(50); + + battery_log(BAT_LOG_CRTI, "mtk_ta_increase() end\n"); + + ncp1854_set_iinlim(0x1); /* 500mA */ + msleep(200); + } else { + ncp1854_set_iinlim(0x0); /* 100mA */ + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 1"); + msleep(281); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 1"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 2"); + msleep(281); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 2"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 3"); + msleep(281); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 3"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 4"); + msleep(85); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 4"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 5"); + msleep(85); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 5"); + msleep(85); + + ncp1854_set_iinlim(0x1); /* 500mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 6"); + msleep(485); + + ncp1854_set_iinlim(0x0); /* 100mA */ + battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 6"); + msleep(50); + + battery_log(BAT_LOG_CRTI, "mtk_ta_decrease() end\n"); + + ncp1854_set_iinlim(0x1); /* 500mA */ + } + + return status; +} + +static unsigned int charging_set_error_state(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static unsigned int charging_diso_init(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static unsigned int charging_get_diso_state(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static unsigned int charging_set_vindpm(void *data) +{ + return STATUS_OK; +} + +static unsigned int charging_set_vbus_ovp_en(void *data) +{ + return STATUS_OK; +} + +static unsigned int charging_enable_otg(void *data) +{ + int ret = 0; + unsigned int enable = 0; + + enable = *((unsigned int *)data); + ncp1854_set_otg_en(enable); + + return ret; +} + +static unsigned int (*charging_func[CHARGING_CMD_NUMBER]) (void *data); + +/* Vanzo:yangbinbin on: Mon, 17 Oct 2016 12:25:34 +0800 + * TODO: replace this line with your comment + static unsigned int (*const charging_func[CHARGING_CMD_NUMBER]) (void *data) = { + charging_hw_init, + charging_dump_register, + charging_enable, + charging_set_cv_voltage, + charging_get_current, + charging_set_current, + charging_set_input_current, + charging_get_charging_status, + charging_reset_watch_dog_timer, + charging_set_hv_threshold, + charging_get_hv_status, + charging_get_battery_status, + charging_get_charger_det_status, + charging_get_charger_type, + charging_get_is_pcm_timer_trigger, + charging_set_platform_reset, + charging_get_platform_boot_mode, + charging_set_power_off, + charging_get_power_source, + charging_get_csdac_full_flag, + charging_set_ta_current_pattern, + charging_set_error_state, + charging_diso_init, + charging_get_diso_state + }; + */ +// End of Vanzo: yangbinbin + +/* + * FUNCTION + * Internal_chr_control_handler + * + * DESCRIPTION + * This function is called to set the charger hw + * + * CALLS + * + * PARAMETERS + * None + * + * RETURNS + * + * + * GLOBALS AFFECTED + * None + */ +signed int chr_control_interface(CHARGING_CTRL_CMD cmd, void *data) +{ + signed int status; + static signed int init = -1; + + if (init == -1) { + init = 0; + charging_func[CHARGING_CMD_INIT] = charging_hw_init; + charging_func[CHARGING_CMD_DUMP_REGISTER] = charging_dump_register; + charging_func[CHARGING_CMD_ENABLE] = charging_enable; + charging_func[CHARGING_CMD_SET_CV_VOLTAGE] = charging_set_cv_voltage; + charging_func[CHARGING_CMD_GET_CURRENT] = charging_get_current; + charging_func[CHARGING_CMD_SET_CURRENT] = charging_set_current; + charging_func[CHARGING_CMD_SET_INPUT_CURRENT] = charging_set_input_current; + charging_func[CHARGING_CMD_GET_CHARGING_STATUS] = charging_get_charging_status; + charging_func[CHARGING_CMD_RESET_WATCH_DOG_TIMER] = charging_reset_watch_dog_timer; + charging_func[CHARGING_CMD_SET_HV_THRESHOLD] = charging_set_hv_threshold; + charging_func[CHARGING_CMD_GET_HV_STATUS] = charging_get_hv_status; + charging_func[CHARGING_CMD_GET_BATTERY_STATUS] = charging_get_battery_status; + charging_func[CHARGING_CMD_GET_CHARGER_DET_STATUS] = charging_get_charger_det_status; + charging_func[CHARGING_CMD_GET_CHARGER_TYPE] = charging_get_charger_type; + charging_func[CHARGING_CMD_GET_IS_PCM_TIMER_TRIGGER] = charging_get_is_pcm_timer_trigger; + charging_func[CHARGING_CMD_SET_PLATFORM_RESET] = charging_set_platform_reset; + charging_func[CHARGING_CMD_GET_PLATFORM_BOOT_MODE] = charging_get_platform_boot_mode; + charging_func[CHARGING_CMD_SET_POWER_OFF] = charging_set_power_off; + charging_func[CHARGING_CMD_GET_POWER_SOURCE] = charging_get_power_source; + charging_func[CHARGING_CMD_GET_CSDAC_FALL_FLAG] = charging_get_csdac_full_flag; + charging_func[CHARGING_CMD_SET_TA_CURRENT_PATTERN] = charging_set_ta_current_pattern; + charging_func[CHARGING_CMD_SET_ERROR_STATE] = charging_set_error_state; + charging_func[CHARGING_CMD_DISO_INIT] = charging_diso_init; + charging_func[CHARGING_CMD_GET_DISO_STATE] = charging_get_diso_state; + charging_func[CHARGING_CMD_SET_VINDPM] = charging_set_vindpm; + charging_func[CHARGING_CMD_SET_VBUS_OVP_EN] = charging_set_vbus_ovp_en; + charging_func[CHARGING_CMD_ENABLE_OTG] = charging_enable_otg; + } + + if (cmd < CHARGING_CMD_NUMBER) { + if (charging_func[cmd] != NULL) + status = charging_func[cmd](data); + else { + battery_log(BAT_LOG_CRTI, "[chr_control_interface]cmd:%d not supported\n", cmd); + status = STATUS_UNSUPPORTED; + } + } else + status = STATUS_UNSUPPORTED; + + return status; +} diff --git a/drivers/misc/mediatek/power/mt6755/charging_hw_pmic.c b/drivers/misc/mediatek/power/mt6755/charging_hw_pmic.c new file mode 100644 index 0000000000000000000000000000000000000000..40c277068663b70416ac98a44d5cb1b5e97df8f3 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/charging_hw_pmic.c @@ -0,0 +1,1676 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* ============================================================ */ +/*define */ +/* ============================================================ */ +#define STATUS_OK 0 +#define STATUS_FAIL 1 +#define STATUS_UNSUPPORTED -1 +#define GETARRAYNUM(array) (sizeof(array)/sizeof(array[0])) +/* ============================================================ */ +/*global variable */ +/* ============================================================ */ +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +kal_bool chargin_hw_init_done = KAL_TRUE; +kal_bool charging_type_det_done = KAL_TRUE; + +unsigned int Default_VBAT_CV_VTH; + +unsigned int const *VBAT_CV_VTH; + +const unsigned int VBAT_CV_VTH_C[] = { + BATTERY_VOLT_03_787500_V, BATTERY_VOLT_03_812500_V, BATTERY_VOLT_03_862500_V, + BATTERY_VOLT_03_912500_V, + BATTERY_VOLT_04_012500_V, BATTERY_VOLT_04_062500_V, BATTERY_VOLT_04_112500_V, + BATTERY_VOLT_04_137500_V, + BATTERY_VOLT_04_150000_V, BATTERY_VOLT_04_162500_V, BATTERY_VOLT_04_175000_V, + BATTERY_VOLT_04_187500_V, + BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_212500_V, BATTERY_VOLT_04_225000_V, + BATTERY_VOLT_04_237500_V, + + BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_262500_V, BATTERY_VOLT_04_275000_V, + BATTERY_VOLT_04_287500_V, + BATTERY_VOLT_04_312500_V, BATTERY_VOLT_04_337500_V, BATTERY_VOLT_04_362500_V, + BATTERY_VOLT_04_387500_V, + BATTERY_VOLT_04_412500_V, BATTERY_VOLT_04_437500_V +}; + +const unsigned int VBAT_CV_VTH_D[] = { + BATTERY_VOLT_03_775000_V, BATTERY_VOLT_03_800000_V, BATTERY_VOLT_03_850000_V, + BATTERY_VOLT_03_900000_V, + BATTERY_VOLT_04_000000_V, BATTERY_VOLT_04_050000_V, BATTERY_VOLT_04_100000_V, + BATTERY_VOLT_04_125000_V, + BATTERY_VOLT_04_137500_V, BATTERY_VOLT_04_150000_V, BATTERY_VOLT_04_162500_V, + BATTERY_VOLT_04_175000_V, + BATTERY_VOLT_04_187500_V, BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_212500_V, + BATTERY_VOLT_04_225000_V, + + BATTERY_VOLT_04_237500_V, BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_262500_V, + BATTERY_VOLT_04_275000_V, + BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_325000_V, BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_375000_V, + BATTERY_VOLT_04_440000_V, BATTERY_VOLT_04_425000_V +}; + +const unsigned int VBAT_CV_VTH_E[] = { + BATTERY_VOLT_03_762500_V, BATTERY_VOLT_03_787500_V, BATTERY_VOLT_03_837500_V, + BATTERY_VOLT_03_887500_V, + BATTERY_VOLT_03_987500_V, BATTERY_VOLT_04_037500_V, BATTERY_VOLT_04_087500_V, + BATTERY_VOLT_04_112500_V, + BATTERY_VOLT_04_125000_V, BATTERY_VOLT_04_137500_V, BATTERY_VOLT_04_150000_V, + BATTERY_VOLT_04_162500_V, + BATTERY_VOLT_04_175000_V, BATTERY_VOLT_04_187500_V, BATTERY_VOLT_04_200000_V, + BATTERY_VOLT_04_212500_V, + + BATTERY_VOLT_04_225000_V, BATTERY_VOLT_04_237500_V, BATTERY_VOLT_04_250000_V, + BATTERY_VOLT_04_262500_V, + BATTERY_VOLT_04_287500_V, BATTERY_VOLT_04_312500_V, BATTERY_VOLT_04_337500_V, + BATTERY_VOLT_04_362500_V, + BATTERY_VOLT_04_387500_V, BATTERY_VOLT_04_412500_V +}; + +const unsigned int VBAT_CV_VTH_F[] = { + BATTERY_VOLT_03_750000_V, BATTERY_VOLT_03_775000_V, BATTERY_VOLT_03_825000_V, + BATTERY_VOLT_03_875000_V, + BATTERY_VOLT_03_975000_V, BATTERY_VOLT_04_025000_V, BATTERY_VOLT_04_075000_V, + BATTERY_VOLT_04_100000_V, + BATTERY_VOLT_04_112500_V, BATTERY_VOLT_04_125000_V, BATTERY_VOLT_04_137500_V, + BATTERY_VOLT_04_150000_V, + BATTERY_VOLT_04_162500_V, BATTERY_VOLT_04_175000_V, BATTERY_VOLT_04_187500_V, + BATTERY_VOLT_04_200000_V, + + BATTERY_VOLT_04_212500_V, BATTERY_VOLT_04_225000_V, BATTERY_VOLT_04_237500_V, + BATTERY_VOLT_04_250000_V, + BATTERY_VOLT_04_275000_V, BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_325000_V, + BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_375000_V, BATTERY_VOLT_04_400000_V +}; + +const unsigned int VBAT_CV_VTH_B[] = { + BATTERY_VOLT_03_800000_V, BATTERY_VOLT_03_825000_V, BATTERY_VOLT_03_875000_V, + BATTERY_VOLT_03_925000_V, + BATTERY_VOLT_04_025000_V, BATTERY_VOLT_04_075000_V, BATTERY_VOLT_04_125000_V, + BATTERY_VOLT_04_150000_V, + BATTERY_VOLT_04_162500_V, BATTERY_VOLT_04_175000_V, BATTERY_VOLT_04_187500_V, + BATTERY_VOLT_04_200000_V, + BATTERY_VOLT_04_212500_V, BATTERY_VOLT_04_225000_V, BATTERY_VOLT_04_237500_V, + BATTERY_VOLT_04_250000_V, + + BATTERY_VOLT_04_262500_V, BATTERY_VOLT_04_275000_V, BATTERY_VOLT_04_287500_V, + BATTERY_VOLT_04_300000_V, + BATTERY_VOLT_04_325000_V, BATTERY_VOLT_04_350000_V, BATTERY_VOLT_04_375000_V, + BATTERY_VOLT_04_400000_V, + BATTERY_VOLT_04_425000_V, BATTERY_VOLT_04_450000_V +}; + +const unsigned int VBAT_CV_VTH_A[] = { + BATTERY_VOLT_03_812500_V, BATTERY_VOLT_03_837500_V, BATTERY_VOLT_03_887500_V, + BATTERY_VOLT_03_937500_V, + BATTERY_VOLT_04_037500_V, BATTERY_VOLT_04_087500_V, BATTERY_VOLT_04_137500_V, + BATTERY_VOLT_04_162500_V, + BATTERY_VOLT_04_175000_V, BATTERY_VOLT_04_187500_V, BATTERY_VOLT_04_200000_V, + BATTERY_VOLT_04_212500_V, + BATTERY_VOLT_04_225000_V, BATTERY_VOLT_04_237500_V, BATTERY_VOLT_04_250000_V, + BATTERY_VOLT_04_262500_V, + + BATTERY_VOLT_04_275000_V, BATTERY_VOLT_04_287500_V, BATTERY_VOLT_04_300000_V, + BATTERY_VOLT_04_312500_V, + BATTERY_VOLT_04_337500_V, BATTERY_VOLT_04_362500_V, BATTERY_VOLT_04_387500_V, + BATTERY_VOLT_04_412500_V, + BATTERY_VOLT_04_437500_V, BATTERY_VOLT_04_462500_V +}; + +const unsigned int VBAT_CV_VTH_9[] = { + BATTERY_VOLT_03_825000_V, BATTERY_VOLT_03_850000_V, BATTERY_VOLT_03_900000_V, + BATTERY_VOLT_03_950000_V, + BATTERY_VOLT_04_050000_V, BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_150000_V, + BATTERY_VOLT_04_175000_V, + BATTERY_VOLT_04_187500_V, BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_212500_V, + BATTERY_VOLT_04_225000_V, + BATTERY_VOLT_04_237500_V, BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_262500_V, + BATTERY_VOLT_04_275000_V, + + BATTERY_VOLT_04_287500_V, BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_312500_V, + BATTERY_VOLT_04_325000_V, + BATTERY_VOLT_04_350000_V, BATTERY_VOLT_04_375000_V, BATTERY_VOLT_04_400000_V, + BATTERY_VOLT_04_425000_V, + BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_475000_V +}; + +const unsigned int CS_VTH[] = { + CHARGE_CURRENT_2000_00_MA, CHARGE_CURRENT_1600_00_MA, CHARGE_CURRENT_1500_00_MA, + CHARGE_CURRENT_1350_00_MA, + CHARGE_CURRENT_1200_00_MA, CHARGE_CURRENT_1100_00_MA, CHARGE_CURRENT_1000_00_MA, + CHARGE_CURRENT_900_00_MA, + CHARGE_CURRENT_800_00_MA, CHARGE_CURRENT_700_00_MA, CHARGE_CURRENT_650_00_MA, + CHARGE_CURRENT_550_00_MA, + CHARGE_CURRENT_450_00_MA, CHARGE_CURRENT_300_00_MA, CHARGE_CURRENT_200_00_MA, + CHARGE_CURRENT_70_00_MA +}; + + +const unsigned int VCDT_HV_VTH[] = { + BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_300000_V, + BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_500000_V, + BATTERY_VOLT_04_550000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_06_000000_V, BATTERY_VOLT_06_500000_V, + BATTERY_VOLT_07_000000_V, + BATTERY_VOLT_07_500000_V, BATTERY_VOLT_08_500000_V, BATTERY_VOLT_09_500000_V, + BATTERY_VOLT_10_500000_V +}; + +unsigned int charging_value_to_parameter(const unsigned int *parameter, + const unsigned int array_size, const unsigned int val) +{ + if (val < array_size) + return parameter[val]; + + battery_log(BAT_LOG_CRTI, "Can't find the parameter \r\n"); + return parameter[0]; + +} + + +unsigned int charging_parameter_to_value(const unsigned int *parameter, + const unsigned int array_size, const unsigned int val) +{ + unsigned int i; + + for (i = 0; i < array_size; i++) { + if (val == *(parameter + i)) + return i; + } + + battery_log(BAT_LOG_CRTI, "NO register value match %d %d\r\n", *parameter, val); + + WARN(1, "NO register value match\n"); + return 0; +} + + +static unsigned int bmt_find_closest_level(const unsigned int *pList, unsigned int number, + unsigned int level) +{ + unsigned int i; + unsigned int max_value_in_last_element; + + if (pList[0] < pList[1]) + max_value_in_last_element = KAL_TRUE; + else + max_value_in_last_element = KAL_FALSE; + + if (max_value_in_last_element == KAL_TRUE) { + for (i = (number - 1); i != 0; i--) { + if (pList[i] <= level) + return pList[i]; + } + + battery_log(BAT_LOG_CRTI, "Can't find closest level \r\n"); + return pList[0]; + } + + for (i = 0; i < number; i++) { + if (pList[i] <= level) + return pList[i]; + } + + battery_log(BAT_LOG_CRTI, "Can't find closest level \r\n"); + return pList[number - 1]; + +} + +static unsigned int charging_hw_init(void *data) +{ + unsigned int status = STATUS_OK; + + pmic_set_register_value(PMIC_RG_CHRWDT_TD, 0); /* CHRWDT_TD, 4s */ + pmic_set_register_value(PMIC_RG_CHRWDT_INT_EN, 1); /* CHRWDT_INT_EN */ + pmic_set_register_value(PMIC_RG_CHRWDT_EN, 1); /* CHRWDT_EN */ + pmic_set_register_value(PMIC_RG_CHRWDT_WR, 1); /* CHRWDT_WR */ + + pmic_set_register_value(PMIC_RG_VCDT_MODE, 0); /* VCDT_MODE */ + pmic_set_register_value(PMIC_RG_VCDT_HV_EN, 1); /* VCDT_HV_EN */ + + pmic_set_register_value(PMIC_RG_USBDL_SET, 0); /* force leave USBDL mode */ + pmic_set_register_value(PMIC_RG_USBDL_RST, 1); /* force leave USBDL mode */ + + pmic_set_register_value(PMIC_RG_BC11_BB_CTRL, 1); /* BC11_BB_CTRL */ + pmic_set_register_value(PMIC_RG_BC11_RST, 1); /* BC11_RST */ + + pmic_set_register_value(PMIC_RG_CSDAC_MODE, 1); /* CSDAC_MODE */ + pmic_set_register_value(PMIC_RG_VBAT_OV_EN, 1); /* VBAT_OV_EN */ + +#ifdef HIGH_BATTERY_VOLTAGE_SUPPORT + pmic_set_register_value(PMIC_RG_VBAT_OV_VTH, 3); /* VBAT_OV_VTH, 4.4V, */ +#else + pmic_set_register_value(PMIC_RG_VBAT_OV_VTH, 2); /* VBAT_OV_VTH, 4.3V, */ +#endif + pmic_set_register_value(PMIC_RG_BATON_EN, 1); /* BATON_EN */ + +#if 0 + /* Tim, for TBAT */ + pmic_set_register_value(PMIC_RG_BATON_HT_EN, 0);/* BATON_HT_EN */ +#endif + + pmic_set_register_value(PMIC_RG_ULC_DET_EN, 1); /* RG_ULC_DET_EN=1 */ + pmic_set_register_value(PMIC_RG_LOW_ICH_DB, 1); /* RG_LOW_ICH_DB=000001'b */ + + +#if defined(CONFIG_MTK_PUMP_EXPRESS_SUPPORT) + pmic_set_register_value(PMIC_RG_CSDAC_DLY, 0); /* CSDAC_DLY */ + pmic_set_register_value(PMIC_RG_CSDAC_STP, 1); /* CSDAC_STP */ + pmic_set_register_value(PMIC_RG_CSDAC_STP_INC, 1); /* CSDAC_STP_INC */ + pmic_set_register_value(PMIC_RG_CSDAC_STP_DEC, 7); /* CSDAC_STP_DEC */ + pmic_set_register_value(PMIC_RG_CS_EN, 1); /* CS_EN */ + + pmic_set_register_value(PMIC_RG_HWCV_EN, 1); + pmic_set_register_value(PMIC_RG_VBAT_CV_EN, 1); /* CV_EN */ + + pmic_set_register_value(PMIC_RG_CHR_EN, 1); /* CHR_EN */ + pmic_set_register_value(PMIC_RG_CSDAC_EN, 1); /* CSDAC_EN */ +#endif + + return status; +} + + +static unsigned int charging_dump_register(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int i = 0; + + for (i = MT6353_CHR_CON0; i <= MT6353_CHR_CON10; i += 10) + battery_log(BAT_LOG_CRTI, + "[0x%x]=0x%x,[0x%x]=0x%x,[0x%x]=0x%x,[0x%x]=0x%x,[0x%x]=0x%x \r\n", i, + upmu_get_reg_value(i), i + 2, upmu_get_reg_value(i + 2), i + 4, + upmu_get_reg_value(i + 4), i + 6, upmu_get_reg_value(i + 6), i + 8, + upmu_get_reg_value(i + 8)); + + + battery_log(BAT_LOG_CRTI, "Default_VBAT_CV_VTH=%d \r\n", Default_VBAT_CV_VTH); + + for (i = 0; i <= 48; i = i + 10) + battery_log(BAT_LOG_CRTI, "%d %d %d %d %d %d %d %d %d %d \r\n", + VBAT_CV_VTH[i] / 1000, VBAT_CV_VTH[i + 1] / 1000, + VBAT_CV_VTH[i + 2] / 1000, VBAT_CV_VTH[i + 3] / 1000, + VBAT_CV_VTH[i + 4] / 1000, VBAT_CV_VTH[i + 5] / 1000, + VBAT_CV_VTH[i + 6] / 1000, VBAT_CV_VTH[i + 7] / 1000, + VBAT_CV_VTH[i + 8] / 1000, VBAT_CV_VTH[i + 9] / 1000); + + return status; +} + + +static unsigned int charging_enable(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int enable = *(unsigned int *)(data); + + if (KAL_TRUE == enable) { + pmic_set_register_value(PMIC_RG_CSDAC_DLY, 4); /* CSDAC_DLY */ + pmic_set_register_value(PMIC_RG_CSDAC_STP, 1); /* CSDAC_STP */ + pmic_set_register_value(PMIC_RG_CSDAC_STP_INC, 1); /* CSDAC_STP_INC */ + pmic_set_register_value(PMIC_RG_CSDAC_STP_DEC, 2); /* CSDAC_STP_DEC */ + pmic_set_register_value(PMIC_RG_CS_EN, 1); /* CS_EN, check me */ + + pmic_set_register_value(PMIC_RG_HWCV_EN, 1); + + pmic_set_register_value(PMIC_RG_VBAT_CV_EN, 1); /* CV_EN */ + pmic_set_register_value(PMIC_RG_CSDAC_EN, 1); /* CSDAC_EN */ + + pmic_set_register_value(PMIC_RG_PCHR_FLAG_EN, 1); /* enable debug falg output */ + + pmic_set_register_value(PMIC_RG_CHR_EN, 1); /* CHR_EN */ + + pmic_set_register_value(PMIC_RG_CSDAC_MODE, 1); /*CSDAC_MODE */ + pmic_set_register_value(PMIC_RG_CSDAC_EN, 1); /* CSDAC_EN */ + + + if (Enable_BATDRV_LOG == BAT_LOG_FULL) + charging_dump_register(NULL); + } else { + pmic_set_register_value(PMIC_RG_CHRWDT_INT_EN, 0); /* CHRWDT_INT_EN */ + pmic_set_register_value(PMIC_RG_CHRWDT_EN, 0); /* CHRWDT_EN */ + pmic_set_register_value(PMIC_RG_CHRWDT_FLAG_WR, 0); /* CHRWDT_FLAG */ + pmic_set_register_value(PMIC_RG_CSDAC_EN, 0); /* CSDAC_EN */ + pmic_set_register_value(PMIC_RG_CHR_EN, 0); /* CHR_EN */ + pmic_set_register_value(PMIC_RG_HWCV_EN, 0); /* RG_HWCV_EN */ + } + return status; +} + + + +static unsigned int charging_set_cv_voltage(void *data) +{ + unsigned int status = STATUS_OK; + short int register_value; + + + unsigned int set_cv_voltage; + unsigned int array_size; + + array_size = GETARRAYNUM(VBAT_CV_VTH_F); + set_cv_voltage = bmt_find_closest_level(VBAT_CV_VTH, array_size, *(unsigned int *)data); + + + register_value = charging_parameter_to_value(VBAT_CV_VTH, array_size, set_cv_voltage); + + /* battery_set_cv_voltage(VBAT_CV_VTH[register_value]); */ + + pmic_set_register_value(PMIC_RG_VBAT_CV_VTH, register_value); + + battery_log(BAT_LOG_CRTI, + "[charging_set_cv_voltage] [0x%x]=0x%x, [0x%x]=0x%x input:%d output:%d\n", + 0xf92, upmu_get_reg_value(0xf92), 0xf98, upmu_get_reg_value(0xf98), + *(unsigned int *)data, set_cv_voltage); + + + return status; +} + + +static unsigned int charging_get_current(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int array_size; + unsigned int reg_value; + + array_size = GETARRAYNUM(CS_VTH); + reg_value = pmic_get_register_value(PMIC_RG_CS_VTH); /*RG_CS_VTH */ + *(unsigned int *)data = charging_value_to_parameter(CS_VTH, array_size, reg_value); + + return status; +} + + +static unsigned int charging_set_current(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int set_chr_current; + unsigned int array_size; + unsigned int register_value; + + array_size = GETARRAYNUM(CS_VTH); + set_chr_current = bmt_find_closest_level(CS_VTH, array_size, *(unsigned int *)data); + register_value = charging_parameter_to_value(CS_VTH, array_size, set_chr_current); + pmic_set_register_value(PMIC_RG_CS_VTH, register_value); + + return status; +} + + +static unsigned int charging_set_input_current(void *data) +{ + unsigned int status = STATUS_OK; + return status; +} + +static unsigned int charging_get_charging_status(void *data) +{ + unsigned int status = STATUS_OK; + return status; +} + + +static unsigned int charging_reset_watch_dog_timer(void *data) +{ + unsigned int status = STATUS_OK; + + pmic_set_register_value(PMIC_RG_CHRWDT_TD, 0); /* CHRWDT_TD, 4s */ + pmic_set_register_value(PMIC_RG_CHRWDT_WR, 1); /* CHRWDT_WR */ + pmic_set_register_value(PMIC_RG_CHRWDT_INT_EN, 1); /* CHRWDT_INT_EN */ + pmic_set_register_value(PMIC_RG_CHRWDT_EN, 1); /* CHRWDT_EN */ + pmic_set_register_value(PMIC_RG_CHRWDT_FLAG_WR, 1); /* CHRWDT_WR */ + + return status; +} + + +static unsigned int charging_set_hv_threshold(void *data) +{ + unsigned int status = STATUS_OK; + + unsigned int set_hv_voltage; + unsigned int array_size; + short int register_value; + unsigned int voltage = *(unsigned int *)(data); + + array_size = GETARRAYNUM(VCDT_HV_VTH); + set_hv_voltage = bmt_find_closest_level(VCDT_HV_VTH, array_size, voltage); + register_value = charging_parameter_to_value(VCDT_HV_VTH, array_size, set_hv_voltage); + pmic_set_register_value(PMIC_RG_VCDT_HV_VTH, register_value); + + return status; +} + + +static unsigned int charging_get_hv_status(void *data) +{ + unsigned int status = STATUS_OK; + + *(kal_bool *) (data) = pmic_get_register_value(PMIC_RGS_VCDT_HV_DET); + return status; +} + + +static unsigned int charging_get_battery_status(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int val = 0; +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = 0; + battery_log(BAT_LOG_CRTI, "bat exist for evb\n"); +#else + val = pmic_get_register_value(PMIC_BATON_TDET_EN); + battery_log(BAT_LOG_FULL, "[charging_get_battery_status] BATON_TDET_EN = %d\n", val); + if (val) { + pmic_set_register_value(PMIC_BATON_TDET_EN, 1); + pmic_set_register_value(PMIC_RG_BATON_EN, 1); + *(kal_bool *) (data) = pmic_get_register_value(PMIC_RGS_BATON_UNDET); + } else { + *(kal_bool *) (data) = KAL_FALSE; + } +#endif + + return status; +} + + +static unsigned int charging_get_charger_det_status(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = 1; + battery_log(BAT_LOG_CRTI, "chr exist for fpga\n"); +#else + *(kal_bool *) (data) = pmic_get_register_value(PMIC_RGS_CHRDET); +#endif + return status; +} + + +kal_bool charging_type_detection_done(void) +{ + return charging_type_det_done; +} + + +static unsigned int charging_get_charger_type(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(CHARGER_TYPE *) (data) = STANDARD_HOST; +#else + *(CHARGER_TYPE *) (data) = hw_charging_get_charger_type(); +#endif + + return status; +} + +static unsigned int charging_get_is_pcm_timer_trigger(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = KAL_FALSE; +#else + if (slp_get_wake_reason() == WR_PCM_TIMER) + *(kal_bool *) (data) = KAL_TRUE; + else + *(kal_bool *) (data) = KAL_FALSE; + + battery_log(BAT_LOG_CRTI, "slp_get_wake_reason=%d\n", slp_get_wake_reason()); +#endif + + return status; +} + +static unsigned int charging_set_platform_reset(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + battery_log(BAT_LOG_CRTI, "charging_set_platform_reset\n"); + kernel_restart("battery service reboot system"); +#endif + + return status; +} + +static unsigned int charging_get_platform_boot_mode(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + *(unsigned int *)(data) = get_boot_mode(); + + battery_log(BAT_LOG_CRTI, "get_boot_mode=%d\n", get_boot_mode()); +#endif + + return status; +} + +static unsigned int charging_set_power_off(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + battery_log(BAT_LOG_CRTI, "charging_set_power_off\n"); + kernel_power_off(); +#endif + + return status; +} + +static unsigned int charging_get_power_source(void *data) +{ + unsigned int status = STATUS_OK; + + *(kal_bool *) data = KAL_FALSE; + + return status; +} + +static unsigned int charging_get_csdac_full_flag(void *data) +{ + unsigned int status = STATUS_OK; + *(kal_bool *) data = KAL_FALSE; + return status; +} + +static unsigned int charging_set_ta_current_pattern(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int increase = *(unsigned int *)(data); + unsigned int debug_val = 0; + unsigned char count = 0; + + pmic_set_register_value(PMIC_RG_CS_VTH, 0xc); + + if (increase == KAL_TRUE) { + /* Set communication mode high/low current */ + pmic_set_register_value(PMIC_RG_CM_CS_VTHH, 0xa); /* 650mA */ + pmic_set_register_value(PMIC_RG_CM_CS_VTHL, 0xf); /* 70mA */ + + /* Set CM_VINC high period time (HPRD1, HPRD2) */ + pmic_set_register_value(PMIC_RG_CM_VINC_HPRD1, 9); /* 100ms */ + pmic_set_register_value(PMIC_RG_CM_VINC_HPRD2, 9); /* 100ms */ + + /* Set CM_VINC high period time (HPRD3, HPRD4) */ + pmic_set_register_value(PMIC_RG_CM_VINC_HPRD3, 29); /* 300ms */ + pmic_set_register_value(PMIC_RG_CM_VINC_HPRD4, 29); /* 300ms */ + + /* Set CM_VINC high period time (HPRD5, HPRD6) */ + pmic_set_register_value(PMIC_RG_CM_VINC_HPRD5, 29); /* 300ms */ + pmic_set_register_value(PMIC_RG_CM_VINC_HPRD6, 49); /* 500ms */ + + /* Enable CM_VINC interrupt */ + + pmic_set_register_value(PMIC_RG_INT_EN_PCHR_CM_VINC, 1); + + /* Select PCHR debug flag to monitor abnormal abort */ + pmic_set_register_value(PMIC_RG_PCHR_FLAG_SEL, 0x2e); + + /* Enable PCHR debug flag */ + pmic_set_register_value(PMIC_RG_PCHR_FLAG_EN, 0x1); + + /* Trigger CM VINC mode */ + pmic_set_register_value(PMIC_RG_CM_VINC_TRIG, 0x1); + + /* wait for interrupt */ + while (pmic_get_register_value(PMIC_PCHR_CM_VINC_STATUS) != 1) { + msleep(50); + count++; + if (count > 42) + break; + } + } else { + /* Set communication mode high/low current */ + pmic_set_register_value(PMIC_RG_CM_CS_VTHH, 0xa); /* 650mA */ + pmic_set_register_value(PMIC_RG_CM_CS_VTHL, 0xf); /* 70mA */ + + /* Set CM_VINC high period time (HPRD1, HPRD2) */ + pmic_set_register_value(PMIC_RG_CM_VDEC_HPRD1, 29); /* 100ms */ + pmic_set_register_value(PMIC_RG_CM_VDEC_HPRD2, 29); /* 100ms */ + + /* Set CM_VINC high period time (HPRD3, HPRD4) */ + pmic_set_register_value(PMIC_RG_CM_VDEC_HPRD3, 29); /* 300ms */ + pmic_set_register_value(PMIC_RG_CM_VDEC_HPRD4, 9); /* 300ms */ + + /* Set CM_VINC high period time (HPRD5, HPRD6) */ + pmic_set_register_value(PMIC_RG_CM_VDEC_HPRD5, 9); /* 300ms */ + pmic_set_register_value(PMIC_RG_CM_VDEC_HPRD6, 49); /* 500ms */ + + + + /* Enable CM_VINC interrupt */ + + pmic_set_register_value(PMIC_RG_INT_EN_PCHR_CM_VDEC, 1); + + /* Select PCHR debug flag to monitor abnormal abort */ + pmic_set_register_value(PMIC_RG_PCHR_FLAG_SEL, 0x2e); + + /* Enable PCHR debug flag */ + pmic_set_register_value(PMIC_RG_PCHR_FLAG_EN, 0x1); + + /* Trigger CM VINC mode */ + pmic_set_register_value(PMIC_RG_CM_VDEC_TRIG, 0x1); + + /* wait for interrupt */ + while (pmic_get_register_value(PMIC_PCHR_CM_VDEC_STATUS) != 1) { + msleep(50); + count++; + if (count > 42) + break; + } + } + + debug_val = pmic_get_register_value(PMIC_RGS_PCHR_FLAG_OUT); + battery_log(BAT_LOG_CRTI, "[charging_set_ta_current_pattern] debug_val=0x%x cnt=%d\n", + debug_val, count); + if (count > 10 || debug_val != 0) + status = STATUS_FAIL; + return status; +} + +static unsigned int charging_set_error_state(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static unsigned int charging_sw_init(void *data) +{ + unsigned int regValue; + + VBAT_CV_VTH = VBAT_CV_VTH_D; + + regValue = pmic_get_register_value(PMIC_RG_VBAT_CV_VTH); + + if (regValue == 0xe) + VBAT_CV_VTH = VBAT_CV_VTH_E; + else if (regValue == 0xd) + VBAT_CV_VTH = VBAT_CV_VTH_D; + else if (regValue == 0xc) + VBAT_CV_VTH = VBAT_CV_VTH_C; + else if (regValue == 0xf) + VBAT_CV_VTH = VBAT_CV_VTH_F; + else if (regValue == 0xb) + VBAT_CV_VTH = VBAT_CV_VTH_B; + else if (regValue == 0xa) + VBAT_CV_VTH = VBAT_CV_VTH_A; + else if (regValue == 0x9) + VBAT_CV_VTH = VBAT_CV_VTH_9; + + Default_VBAT_CV_VTH = regValue; + battery_log(BAT_LOG_CRTI, "[charging_sw_init] regValue=0x%x\n", regValue); + + return STATUS_OK; +} + + +static unsigned int (*charging_func[CHARGING_CMD_NUMBER]) (void *data); + + + /* + * FUNCTION + * Internal_chr_control_handler + * + * DESCRIPTION + * This function is called to set the charger hw + * + * CALLS + * + * PARAMETERS + * None + * + * RETURNS + * + * + * GLOBALS AFFECTED + * None + */ +signed int chr_control_interface(CHARGING_CTRL_CMD cmd, void *data) +{ + signed int status; + static signed int init = -1; + + if (init == -1) { + init = 0; + charging_func[CHARGING_CMD_INIT] = charging_hw_init; + charging_func[CHARGING_CMD_DUMP_REGISTER] = charging_dump_register; + charging_func[CHARGING_CMD_ENABLE] = charging_enable; + charging_func[CHARGING_CMD_SET_CV_VOLTAGE] = charging_set_cv_voltage; + charging_func[CHARGING_CMD_GET_CURRENT] = charging_get_current; + charging_func[CHARGING_CMD_SET_CURRENT] = charging_set_current; + charging_func[CHARGING_CMD_SET_INPUT_CURRENT] = charging_set_input_current; + charging_func[CHARGING_CMD_GET_CHARGING_STATUS] = charging_get_charging_status; + charging_func[CHARGING_CMD_RESET_WATCH_DOG_TIMER] = charging_reset_watch_dog_timer; + charging_func[CHARGING_CMD_SET_HV_THRESHOLD] = charging_set_hv_threshold; + charging_func[CHARGING_CMD_GET_HV_STATUS] = charging_get_hv_status; + charging_func[CHARGING_CMD_GET_BATTERY_STATUS] = charging_get_battery_status; + charging_func[CHARGING_CMD_GET_CHARGER_DET_STATUS] = + charging_get_charger_det_status; + charging_func[CHARGING_CMD_GET_CHARGER_TYPE] = charging_get_charger_type; + charging_func[CHARGING_CMD_GET_IS_PCM_TIMER_TRIGGER] = + charging_get_is_pcm_timer_trigger; + charging_func[CHARGING_CMD_SET_PLATFORM_RESET] = charging_set_platform_reset; + charging_func[CHARGING_CMD_GET_PLATFORM_BOOT_MODE] = + charging_get_platform_boot_mode; + charging_func[CHARGING_CMD_SET_POWER_OFF] = charging_set_power_off; + charging_func[CHARGING_CMD_GET_POWER_SOURCE] = charging_get_power_source; + charging_func[CHARGING_CMD_GET_CSDAC_FALL_FLAG] = charging_get_csdac_full_flag; + charging_func[CHARGING_CMD_SET_TA_CURRENT_PATTERN] = + charging_set_ta_current_pattern; + charging_func[CHARGING_CMD_SET_ERROR_STATE] = charging_set_error_state; + charging_func[CHARGING_CMD_SW_INIT] = charging_sw_init; + } + + if (cmd < CHARGING_CMD_NUMBER) { + if (charging_func[cmd] != NULL) + status = charging_func[cmd] (data); + else { + battery_log(BAT_LOG_CRTI, + "[chr_control_interface] cmd:%d does not support\n", cmd); + return STATUS_UNSUPPORTED; + } + } else { + battery_log(BAT_LOG_CRTI, "[chr_control_interface] cmd:%d is not legal\n", cmd); + return STATUS_UNSUPPORTED; + } + return status; + +} + +#else +kal_bool chargin_hw_init_done = KAL_TRUE; +kal_bool charging_type_det_done = KAL_TRUE; + +unsigned int Default_VBAT_CV_VTH; + +unsigned int const *VBAT_CV_VTH; + + +const unsigned int VBAT_CV_VTH_F[] = { + BATTERY_VOLT_03_500000_V, BATTERY_VOLT_03_600000_V, BATTERY_VOLT_03_700000_V, + BATTERY_VOLT_03_800000_V, + BATTERY_VOLT_03_850000_V, BATTERY_VOLT_03_900000_V, BATTERY_VOLT_04_000000_V, + BATTERY_VOLT_04_050000_V, + BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_125000_V, BATTERY_VOLT_04_137500_V, + BATTERY_VOLT_04_150000_V, + BATTERY_VOLT_04_162500_V, BATTERY_VOLT_04_175000_V, BATTERY_VOLT_04_187500_V, + BATTERY_VOLT_04_200000_V, + + BATTERY_VOLT_04_212500_V, BATTERY_VOLT_04_225000_V, BATTERY_VOLT_04_237500_V, + BATTERY_VOLT_04_250000_V, + BATTERY_VOLT_04_262500_V, BATTERY_VOLT_04_275000_V, BATTERY_VOLT_04_287500_V, + BATTERY_VOLT_04_300000_V, + BATTERY_VOLT_04_312500_V, BATTERY_VOLT_04_325000_V, BATTERY_VOLT_04_337500_V, + BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_362500_V, BATTERY_VOLT_04_375000_V, BATTERY_VOLT_04_387500_V, + BATTERY_VOLT_04_400000_V, + + BATTERY_VOLT_04_412500_V, BATTERY_VOLT_04_425000_V, BATTERY_VOLT_04_437500_V, + BATTERY_VOLT_04_450000_V, + BATTERY_VOLT_04_462500_V, BATTERY_VOLT_04_475000_V, BATTERY_VOLT_04_487500_V, + BATTERY_VOLT_04_500000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V +}; + +const unsigned int VBAT_CV_VTH_E[] = { + BATTERY_VOLT_03_500000_V, BATTERY_VOLT_03_600000_V, BATTERY_VOLT_03_700000_V, + BATTERY_VOLT_03_800000_V, + BATTERY_VOLT_03_850000_V, BATTERY_VOLT_03_900000_V, BATTERY_VOLT_04_000000_V, + BATTERY_VOLT_04_050000_V, + BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_137500_V, BATTERY_VOLT_04_150000_V, + BATTERY_VOLT_04_162500_V, + BATTERY_VOLT_04_175000_V, BATTERY_VOLT_04_187500_V, BATTERY_VOLT_04_200000_V, + BATTERY_VOLT_04_212500_V, + + BATTERY_VOLT_04_225000_V, BATTERY_VOLT_04_237500_V, BATTERY_VOLT_04_250000_V, + BATTERY_VOLT_04_262500_V, + BATTERY_VOLT_04_275000_V, BATTERY_VOLT_04_287500_V, BATTERY_VOLT_04_300000_V, + BATTERY_VOLT_04_312500_V, + BATTERY_VOLT_04_325000_V, BATTERY_VOLT_04_337500_V, BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_362500_V, + BATTERY_VOLT_04_375000_V, BATTERY_VOLT_04_387500_V, BATTERY_VOLT_04_400000_V, + BATTERY_VOLT_04_412500_V, + + BATTERY_VOLT_04_425000_V, BATTERY_VOLT_04_437500_V, BATTERY_VOLT_04_450000_V, + BATTERY_VOLT_04_462500_V, + BATTERY_VOLT_04_475000_V, BATTERY_VOLT_04_487500_V, BATTERY_VOLT_04_500000_V, + BATTERY_VOLT_04_512500_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V +}; + +const unsigned int VBAT_CV_VTH_D[] = { + BATTERY_VOLT_03_500000_V, BATTERY_VOLT_03_600000_V, BATTERY_VOLT_03_700000_V, + BATTERY_VOLT_03_800000_V, + BATTERY_VOLT_03_850000_V, BATTERY_VOLT_03_900000_V, BATTERY_VOLT_04_000000_V, + BATTERY_VOLT_04_050000_V, + BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_150000_V, BATTERY_VOLT_04_162500_V, + BATTERY_VOLT_04_175000_V, + BATTERY_VOLT_04_187500_V, BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_212500_V, + BATTERY_VOLT_04_225000_V, + + BATTERY_VOLT_04_237500_V, BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_262500_V, + BATTERY_VOLT_04_275000_V, + BATTERY_VOLT_04_287500_V, BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_312500_V, + BATTERY_VOLT_04_325000_V, + BATTERY_VOLT_04_337500_V, BATTERY_VOLT_04_350000_V, BATTERY_VOLT_04_362500_V, + BATTERY_VOLT_04_375000_V, + BATTERY_VOLT_04_387500_V, BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_412500_V, + BATTERY_VOLT_04_425000_V, + + BATTERY_VOLT_04_437500_V, BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_462500_V, + BATTERY_VOLT_04_475000_V, + BATTERY_VOLT_04_487500_V, BATTERY_VOLT_04_500000_V, BATTERY_VOLT_04_512500_V, + BATTERY_VOLT_04_525000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V +}; + +const unsigned int VBAT_CV_VTH_C[] = { + BATTERY_VOLT_03_500000_V, BATTERY_VOLT_03_600000_V, BATTERY_VOLT_03_700000_V, + BATTERY_VOLT_03_800000_V, + BATTERY_VOLT_03_850000_V, BATTERY_VOLT_03_900000_V, BATTERY_VOLT_04_000000_V, + BATTERY_VOLT_04_050000_V, + BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_162500_V, BATTERY_VOLT_04_175000_V, + BATTERY_VOLT_04_187500_V, + BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_212500_V, BATTERY_VOLT_04_225000_V, + BATTERY_VOLT_04_237500_V, + + BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_262500_V, BATTERY_VOLT_04_275000_V, + BATTERY_VOLT_04_287500_V, + BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_312500_V, BATTERY_VOLT_04_325000_V, + BATTERY_VOLT_04_337500_V, + BATTERY_VOLT_04_350000_V, BATTERY_VOLT_04_362500_V, BATTERY_VOLT_04_375000_V, + BATTERY_VOLT_04_387500_V, + BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_412500_V, BATTERY_VOLT_04_425000_V, + BATTERY_VOLT_04_437500_V, + + BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_462500_V, BATTERY_VOLT_04_475000_V, + BATTERY_VOLT_04_487500_V, + BATTERY_VOLT_04_500000_V, BATTERY_VOLT_04_512500_V, BATTERY_VOLT_04_525000_V, + BATTERY_VOLT_04_537500_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V +}; + +const unsigned int VBAT_CV_VTH_10[] = { + BATTERY_VOLT_03_500000_V, BATTERY_VOLT_03_600000_V, BATTERY_VOLT_03_700000_V, + BATTERY_VOLT_03_800000_V, + BATTERY_VOLT_03_850000_V, BATTERY_VOLT_03_900000_V, BATTERY_VOLT_04_000000_V, + BATTERY_VOLT_04_050000_V, + BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_112500_V, BATTERY_VOLT_04_125000_V, + BATTERY_VOLT_04_137500_V, + BATTERY_VOLT_04_150000_V, BATTERY_VOLT_04_162500_V, BATTERY_VOLT_04_175000_V, + BATTERY_VOLT_04_187500_V, + + BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_212500_V, BATTERY_VOLT_04_225000_V, + BATTERY_VOLT_04_237500_V, + BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_262500_V, BATTERY_VOLT_04_275000_V, + BATTERY_VOLT_04_287500_V, + BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_312500_V, BATTERY_VOLT_04_325000_V, + BATTERY_VOLT_04_337500_V, + BATTERY_VOLT_04_350000_V, BATTERY_VOLT_04_362500_V, BATTERY_VOLT_04_375000_V, + BATTERY_VOLT_04_387500_V, + + BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_412500_V, BATTERY_VOLT_04_425000_V, + BATTERY_VOLT_04_437500_V, + BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_462500_V, BATTERY_VOLT_04_475000_V, + BATTERY_VOLT_04_500000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V +}; + +const unsigned int VBAT_CV_VTH_11[] = { + BATTERY_VOLT_03_500000_V, BATTERY_VOLT_03_600000_V, BATTERY_VOLT_03_700000_V, + BATTERY_VOLT_03_800000_V, + BATTERY_VOLT_03_850000_V, BATTERY_VOLT_03_900000_V, BATTERY_VOLT_04_000000_V, + BATTERY_VOLT_04_050000_V, + BATTERY_VOLT_04_087500_V, BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_112500_V, + BATTERY_VOLT_04_125000_V, + BATTERY_VOLT_04_137500_V, BATTERY_VOLT_04_150000_V, BATTERY_VOLT_04_162500_V, + BATTERY_VOLT_04_175000_V, + + BATTERY_VOLT_04_187500_V, BATTERY_VOLT_04_200000_V, BATTERY_VOLT_04_212500_V, + BATTERY_VOLT_04_225000_V, + BATTERY_VOLT_04_237500_V, BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_262500_V, + BATTERY_VOLT_04_275000_V, + BATTERY_VOLT_04_287500_V, BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_312500_V, + BATTERY_VOLT_04_325000_V, + BATTERY_VOLT_04_337500_V, BATTERY_VOLT_04_350000_V, BATTERY_VOLT_04_362500_V, + BATTERY_VOLT_04_375000_V, + + BATTERY_VOLT_04_387500_V, BATTERY_VOLT_04_400000_V, BATTERY_VOLT_04_412500_V, + BATTERY_VOLT_04_425000_V, + BATTERY_VOLT_04_437500_V, BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_462500_V, + BATTERY_VOLT_04_500000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V +}; + +const unsigned int VBAT_CV_VTH_12[] = { + BATTERY_VOLT_03_500000_V, BATTERY_VOLT_03_600000_V, BATTERY_VOLT_03_700000_V, + BATTERY_VOLT_03_800000_V, + BATTERY_VOLT_03_850000_V, BATTERY_VOLT_03_900000_V, BATTERY_VOLT_04_000000_V, + BATTERY_VOLT_04_050000_V, + BATTERY_VOLT_04_075000_V, BATTERY_VOLT_04_087500_V, BATTERY_VOLT_04_100000_V, + BATTERY_VOLT_04_112500_V, + BATTERY_VOLT_04_125000_V, BATTERY_VOLT_04_137500_V, BATTERY_VOLT_04_150000_V, + BATTERY_VOLT_04_162500_V, + + BATTERY_VOLT_04_175000_V, BATTERY_VOLT_04_187500_V, BATTERY_VOLT_04_200000_V, + BATTERY_VOLT_04_212500_V, + BATTERY_VOLT_04_225000_V, BATTERY_VOLT_04_237500_V, BATTERY_VOLT_04_250000_V, + BATTERY_VOLT_04_262500_V, + BATTERY_VOLT_04_275000_V, BATTERY_VOLT_04_287500_V, BATTERY_VOLT_04_300000_V, + BATTERY_VOLT_04_312500_V, + BATTERY_VOLT_04_325000_V, BATTERY_VOLT_04_337500_V, BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_362500_V, + + BATTERY_VOLT_04_375000_V, BATTERY_VOLT_04_387500_V, BATTERY_VOLT_04_400000_V, + BATTERY_VOLT_04_412500_V, + BATTERY_VOLT_04_425000_V, BATTERY_VOLT_04_437500_V, BATTERY_VOLT_04_450000_V, + BATTERY_VOLT_04_500000_V, + BATTERY_VOLT_04_600000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, BATTERY_VOLT_10_500000_V, + BATTERY_VOLT_10_500000_V +}; + + +const unsigned int CS_VTH[] = { + CHARGE_CURRENT_2000_00_MA, CHARGE_CURRENT_1600_00_MA, CHARGE_CURRENT_1500_00_MA, + CHARGE_CURRENT_1350_00_MA, + CHARGE_CURRENT_1200_00_MA, CHARGE_CURRENT_1100_00_MA, CHARGE_CURRENT_1000_00_MA, + CHARGE_CURRENT_900_00_MA, + CHARGE_CURRENT_800_00_MA, CHARGE_CURRENT_700_00_MA, CHARGE_CURRENT_650_00_MA, + CHARGE_CURRENT_550_00_MA, + CHARGE_CURRENT_450_00_MA, CHARGE_CURRENT_300_00_MA, CHARGE_CURRENT_200_00_MA, + CHARGE_CURRENT_70_00_MA +}; + + +const unsigned int VCDT_HV_VTH[] = { + BATTERY_VOLT_04_000000_V, BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_150000_V, + BATTERY_VOLT_04_200000_V, + BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_350000_V, + BATTERY_VOLT_04_400000_V, + BATTERY_VOLT_04_450000_V, BATTERY_VOLT_06_000000_V, BATTERY_VOLT_06_500000_V, + BATTERY_VOLT_07_000000_V, + BATTERY_VOLT_07_500000_V, BATTERY_VOLT_08_500000_V, BATTERY_VOLT_09_500000_V, + BATTERY_VOLT_10_500000_V +}; + +unsigned int charging_value_to_parameter(const unsigned int *parameter, + const unsigned int array_size, const unsigned int val) +{ + if (val < array_size) { + return parameter[val]; + } else { + battery_log(BAT_LOG_CRTI, "Can't find the parameter \r\n"); + return parameter[0]; + } +} + + +unsigned int charging_parameter_to_value(const unsigned int *parameter, + const unsigned int array_size, const unsigned int val) +{ + unsigned int i; + + for (i = 0; i < array_size; i++) { + if (val == *(parameter + i)) + return i; + } + + battery_log(BAT_LOG_CRTI, "NO register value match %d %d\r\n", *parameter, val); + + WARN(1, "NO register value match\n"); + return 0; +} + + +static unsigned int bmt_find_closest_level(const unsigned int *pList, unsigned int number, + unsigned int level) +{ + unsigned int i; + unsigned int max_value_in_last_element; + + if (pList[0] < pList[1]) + max_value_in_last_element = KAL_TRUE; + else + max_value_in_last_element = KAL_FALSE; + + if (max_value_in_last_element == KAL_TRUE) { + for (i = (number - 1); i != 0; i--) { + if (pList[i] <= level) + return pList[i]; + } + + battery_log(BAT_LOG_CRTI, "Can't find closest level \r\n"); + return pList[0]; + } else { + for (i = 0; i < number; i++) { + if (pList[i] <= level) + return pList[i]; + } + + battery_log(BAT_LOG_CRTI, "Can't find closest level \r\n"); + return pList[number - 1]; + } +} + +static unsigned int charging_hw_init(void *data) +{ + unsigned int status = STATUS_OK; + + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_TD, 0); /* CHRWDT_TD, 4s */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_INT_EN, 1); /* CHRWDT_INT_EN */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_EN, 1); /* CHRWDT_EN */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_WR, 1); /* CHRWDT_WR */ + + pmic_set_register_value(MT6351_PMIC_RG_VCDT_MODE, 0); /* VCDT_MODE */ + pmic_set_register_value(MT6351_PMIC_RG_VCDT_HV_EN, 1); /* VCDT_HV_EN */ + + pmic_set_register_value(MT6351_PMIC_RG_USBDL_SET, 0); /* force leave USBDL mode */ + pmic_set_register_value(MT6351_PMIC_RG_USBDL_RST, 1); /* force leave USBDL mode */ + + pmic_set_register_value(MT6351_PMIC_RG_BC11_BB_CTRL, 1); /* BC11_BB_CTRL */ + pmic_set_register_value(MT6351_PMIC_RG_BC11_RST, 1); /* BC11_RST */ + + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_MODE, 1); /* CSDAC_MODE */ + pmic_set_register_value(MT6351_PMIC_RG_VBAT_OV_EN, 1); /* VBAT_OV_EN */ + +#if 0 +#ifdef HIGH_BATTERY_VOLTAGE_SUPPORT + pmic_set_register_value(MT6351_PMIC_RG_VBAT_OV_VTH, 4);/* VBAT_OV_VTH, 4.4V, */ +#else + pmic_set_register_value(MT6351_PMIC_RG_VBAT_OV_VTH, 2);/* VBAT_OV_VTH, 4.3V, */ +#endif +#endif + + pmic_set_register_value(MT6351_PMIC_RG_BATON_EN, 1); /* BATON_EN */ + + /* Tim, for TBAT */ + pmic_set_register_value(MT6351_PMIC_RG_BATON_HT_EN, 0); /* BATON_HT_EN */ + + pmic_set_register_value(MT6351_PMIC_RG_ULC_DET_EN, 1); /* RG_ULC_DET_EN=1 */ + pmic_set_register_value(MT6351_PMIC_RG_LOW_ICH_DB, 1); /* RG_LOW_ICH_DB=000001'b */ + + +#if defined(CONFIG_MTK_PUMP_EXPRESS_SUPPORT) + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_DLY, 0); /* CSDAC_DLY */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_STP, 1); /* CSDAC_STP */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_STP_INC, 1); /* CSDAC_STP_INC */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_STP_DEC, 7); /* CSDAC_STP_DEC */ + pmic_set_register_value(MT6351_PMIC_RG_CS_EN, 1); /* CS_EN */ + + pmic_set_register_value(MT6351_PMIC_RG_HWCV_EN, 1); + pmic_set_register_value(MT6351_PMIC_RG_VBAT_CV_EN, 1); /* CV_EN */ + + pmic_set_register_value(MT6351_PMIC_RG_NORM_CHR_EN, 1); /* CHR_EN */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_EN, 1); /* CSDAC_EN */ +#endif + + return status; +} + + +static unsigned int charging_dump_register(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int i = 0; + + for (i = MT6351_CHR_CON0; i <= MT6351_CHR_CON40; i += 10) + battery_log(BAT_LOG_CRTI, + "[0x%x]=0x%x,[0x%x]=0x%x,[0x%x]=0x%x,[0x%x]=0x%x,[0x%x]=0x%x \r\n", i, + upmu_get_reg_value(i), i + 2, upmu_get_reg_value(i + 2), i + 4, + upmu_get_reg_value(i + 4), i + 6, upmu_get_reg_value(i + 6), i + 8, + upmu_get_reg_value(i + 8)); + + + battery_log(BAT_LOG_CRTI, "Default_VBAT_CV_VTH=%d \r\n", Default_VBAT_CV_VTH); + + for (i = 0; i <= 48; i = i + 10) + battery_log(BAT_LOG_CRTI, "%d %d %d %d %d %d %d %d %d %d \r\n", + VBAT_CV_VTH[i] / 1000, VBAT_CV_VTH[i + 1] / 1000, + VBAT_CV_VTH[i + 2] / 1000, VBAT_CV_VTH[i + 3] / 1000, + VBAT_CV_VTH[i + 4] / 1000, VBAT_CV_VTH[i + 5] / 1000, + VBAT_CV_VTH[i + 6] / 1000, VBAT_CV_VTH[i + 7] / 1000, + VBAT_CV_VTH[i + 8] / 1000, VBAT_CV_VTH[i + 9] / 1000); + + return status; +} + + +static unsigned int charging_enable(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int enable = *(unsigned int *)(data); + + if (KAL_TRUE == enable) { + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_DLY, 4); /* CSDAC_DLY */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_STP, 1); /* CSDAC_STP */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_STP_INC, 1); /* CSDAC_STP_INC */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_STP_DEC, 2); /* CSDAC_STP_DEC */ + pmic_set_register_value(MT6351_PMIC_RG_CS_EN, 1); /* CS_EN, check me */ + + pmic_set_register_value(MT6351_PMIC_RG_HWCV_EN, 1); + + pmic_set_register_value(MT6351_PMIC_RG_VBAT_CV_EN, 1); /* CV_EN */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_EN, 1); /* CSDAC_EN */ + + pmic_set_register_value(MT6351_PMIC_RG_PCHR_FLAG_EN, 1); /* enable debug falg output */ + + pmic_set_register_value(MT6351_PMIC_RG_NORM_CHR_EN, 1); /* CHR_EN */ + + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_MODE, 1); /*CSDAC_MODE */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_EN, 1); /* CSDAC_EN */ + + + if (Enable_BATDRV_LOG == BAT_LOG_FULL) + charging_dump_register(NULL); + } else { + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_INT_EN, 0); /* CHRWDT_INT_EN */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_EN, 0); /* CHRWDT_EN */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_FLAG_WR, 0); /* CHRWDT_FLAG */ + pmic_set_register_value(MT6351_PMIC_RG_CSDAC_EN, 0); /* CSDAC_EN */ + pmic_set_register_value(MT6351_PMIC_RG_NORM_CHR_EN, 0); /* CHR_EN */ + pmic_set_register_value(MT6351_PMIC_RG_HWCV_EN, 0); /* RG_HWCV_EN */ + } + return status; +} + + + +static unsigned int charging_set_cv_voltage(void *data) +{ + unsigned int status = STATUS_OK; + short int register_value; + + + unsigned int set_cv_voltage; + unsigned int array_size; + + array_size = GETARRAYNUM(VBAT_CV_VTH_F); + set_cv_voltage = bmt_find_closest_level(VBAT_CV_VTH, array_size, *(unsigned int *)data); + + + register_value = charging_parameter_to_value(VBAT_CV_VTH, array_size, set_cv_voltage); + + /* battery_set_cv_voltage(VBAT_CV_VTH[register_value]); */ + + pmic_set_register_value(MT6351_PMIC_RG_VBAT_NORM_CV_VTH, register_value); + + battery_log(BAT_LOG_CRTI, + "[charging_set_cv_voltage] [0x%x]=0x%x, [0x%x]=0x%x input:%d output:%d\n", + 0xf7e, upmu_get_reg_value(0xf7e), 0xf84, upmu_get_reg_value(0xf84), + *(unsigned int *)data, set_cv_voltage); + + + return status; +} + + +static unsigned int charging_get_current(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int array_size; + unsigned int reg_value; + + array_size = GETARRAYNUM(CS_VTH); + reg_value = pmic_get_register_value(MT6351_PMIC_RG_NORM_CS_VTH); /*RG_CS_VTH */ + *(unsigned int *)data = charging_value_to_parameter(CS_VTH, array_size, reg_value); + + return status; +} + + +static unsigned int charging_set_current(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int set_chr_current; + unsigned int array_size; + unsigned int register_value; + + array_size = GETARRAYNUM(CS_VTH); + set_chr_current = bmt_find_closest_level(CS_VTH, array_size, *(unsigned int *)data); + register_value = charging_parameter_to_value(CS_VTH, array_size, set_chr_current); + pmic_set_register_value(MT6351_PMIC_RG_NORM_CS_VTH, register_value); + + return status; +} + + +static unsigned int charging_set_input_current(void *data) +{ + unsigned int status = STATUS_OK; + return status; +} + +static unsigned int charging_get_charging_status(void *data) +{ + unsigned int status = STATUS_OK; + return status; +} + + +static unsigned int charging_reset_watch_dog_timer(void *data) +{ + unsigned int status = STATUS_OK; + + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_TD, 0); /* CHRWDT_TD, 4s */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_WR, 1); /* CHRWDT_WR */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_INT_EN, 1); /* CHRWDT_INT_EN */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_EN, 1); /* CHRWDT_EN */ + pmic_set_register_value(MT6351_PMIC_RG_CHRWDT_FLAG_WR, 1); /* CHRWDT_WR */ + + return status; +} + + +static unsigned int charging_set_hv_threshold(void *data) +{ + unsigned int status = STATUS_OK; + + unsigned int set_hv_voltage; + unsigned int array_size; + short int register_value; + unsigned int voltage = *(unsigned int *)(data); + + array_size = GETARRAYNUM(VCDT_HV_VTH); + set_hv_voltage = bmt_find_closest_level(VCDT_HV_VTH, array_size, voltage); + register_value = charging_parameter_to_value(VCDT_HV_VTH, array_size, set_hv_voltage); + pmic_set_register_value(MT6351_PMIC_RG_VCDT_HV_VTH, register_value); + + return status; +} + + +static unsigned int charging_get_hv_status(void *data) +{ + unsigned int status = STATUS_OK; + + *(kal_bool *) (data) = pmic_get_register_value(MT6351_PMIC_RGS_VCDT_HV_DET); + return status; +} + + +static unsigned int charging_get_battery_status(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int val = 0; +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = 0; + battery_log(BAT_LOG_CRTI, "bat exist for evb\n"); +#else + val = pmic_get_register_value(MT6351_PMIC_BATON_TDET_EN); + battery_log(BAT_LOG_FULL, "[charging_get_battery_status] BATON_TDET_EN = %d\n", val); + if (val) { + pmic_set_register_value(MT6351_PMIC_BATON_TDET_EN, 1); + pmic_set_register_value(MT6351_PMIC_RG_BATON_EN, 1); + *(kal_bool *) (data) = pmic_get_register_value(MT6351_PMIC_RGS_BATON_UNDET); + } else { + *(kal_bool *) (data) = KAL_FALSE; + } +#endif + + return status; +} + + +static unsigned int charging_get_charger_det_status(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = 1; + battery_log(BAT_LOG_CRTI, "chr exist for fpga\n"); +#else + *(kal_bool *) (data) = pmic_get_register_value(MT6351_PMIC_RGS_CHRDET); +#endif + return status; +} + + +kal_bool charging_type_detection_done(void) +{ + return charging_type_det_done; +} + + +static unsigned int charging_get_charger_type(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(CHARGER_TYPE *) (data) = STANDARD_HOST; +#else + *(CHARGER_TYPE *) (data) = hw_charging_get_charger_type(); +#endif + + return status; +} + +static unsigned int charging_get_is_pcm_timer_trigger(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + *(kal_bool *) (data) = KAL_FALSE; +#else + if (slp_get_wake_reason() == WR_PCM_TIMER) + *(kal_bool *) (data) = KAL_TRUE; + else + *(kal_bool *) (data) = KAL_FALSE; + + battery_log(BAT_LOG_CRTI, "slp_get_wake_reason=%d\n", slp_get_wake_reason()); +#endif + + return status; +} + +static unsigned int charging_set_platform_reset(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + battery_log(BAT_LOG_CRTI, "charging_set_platform_reset\n"); + kernel_restart("battery service reboot system"); +#endif + + return status; +} + +static unsigned int charging_get_platform_boot_mode(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + *(unsigned int *)(data) = get_boot_mode(); + + battery_log(BAT_LOG_CRTI, "get_boot_mode=%d\n", get_boot_mode()); +#endif + + return status; +} + +static unsigned int charging_set_power_off(void *data) +{ + unsigned int status = STATUS_OK; + +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) +#else + battery_log(BAT_LOG_CRTI, "charging_set_power_off\n"); + kernel_power_off(); +#endif + + return status; +} + +static unsigned int charging_get_power_source(void *data) +{ + unsigned int status = STATUS_OK; + + *(kal_bool *) data = KAL_FALSE; + + return status; +} + +static unsigned int charging_get_csdac_full_flag(void *data) +{ + unsigned int status = STATUS_OK; + *(kal_bool *) data = KAL_FALSE; + return status; +} + +static unsigned int charging_set_ta_current_pattern(void *data) +{ + unsigned int status = STATUS_OK; + unsigned int increase = *(unsigned int *)(data); + unsigned int debug_val = 0; + unsigned char count = 0; + + pmic_set_register_value(MT6351_PMIC_RG_NORM_CS_VTH, 0xc); + + if (increase == KAL_TRUE) { + /* Set communication mode high/low current */ + pmic_set_register_value(MT6351_PMIC_RG_CM_CS_VTHH, 0xa); /* 650mA */ + pmic_set_register_value(MT6351_PMIC_RG_CM_CS_VTHL, 0xf); /* 70mA */ + + /* Set CM_VINC high period time (HPRD1, HPRD2) */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VINC_HPRD1, 9); /* 100ms */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VINC_HPRD2, 9); /* 100ms */ + + /* Set CM_VINC high period time (HPRD3, HPRD4) */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VINC_HPRD3, 29); /* 300ms */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VINC_HPRD4, 29); /* 300ms */ + + /* Set CM_VINC high period time (HPRD5, HPRD6) */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VINC_HPRD5, 29); /* 300ms */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VINC_HPRD6, 49); /* 500ms */ + + /* Enable CM_VINC interrupt */ + + pmic_set_register_value(MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC, 1); + + /* Select PCHR debug flag to monitor abnormal abort */ + pmic_set_register_value(MT6351_PMIC_RG_PCHR_FLAG_SEL, 0x2e); + + /* Enable PCHR debug flag */ + pmic_set_register_value(MT6351_PMIC_RG_PCHR_FLAG_EN, 0x1); + + /* Trigger CM VINC mode */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VINC_TRIG, 0x1); + + /* wait for interrupt */ + while (pmic_get_register_value(MT6351_PMIC_PCHR_CM_VINC_STATUS) != 1) { + msleep(50); + count++; + if (count > 42) + break; + } + } else { + /* Set communication mode high/low current */ + pmic_set_register_value(MT6351_PMIC_RG_CM_CS_VTHH, 0xa); /* 650mA */ + pmic_set_register_value(MT6351_PMIC_RG_CM_CS_VTHL, 0xf); /* 70mA */ + + /* Set CM_VINC high period time (HPRD1, HPRD2) */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VDEC_HPRD1, 29); /* 100ms */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VDEC_HPRD2, 29); /* 100ms */ + + /* Set CM_VINC high period time (HPRD3, HPRD4) */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VDEC_HPRD3, 29); /* 300ms */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VDEC_HPRD4, 9); /* 300ms */ + + /* Set CM_VINC high period time (HPRD5, HPRD6) */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VDEC_HPRD5, 9); /* 300ms */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VDEC_HPRD6, 49); /* 500ms */ + + + + /* Enable CM_VINC interrupt */ + + pmic_set_register_value(MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC, 1); + + /* Select PCHR debug flag to monitor abnormal abort */ + pmic_set_register_value(MT6351_PMIC_RG_PCHR_FLAG_SEL, 0x2e); + + /* Enable PCHR debug flag */ + pmic_set_register_value(MT6351_PMIC_RG_PCHR_FLAG_EN, 0x1); + + /* Trigger CM VINC mode */ + pmic_set_register_value(MT6351_PMIC_RG_CM_VDEC_TRIG, 0x1); + + /* wait for interrupt */ + while (pmic_get_register_value(MT6351_PMIC_PCHR_CM_VDEC_STATUS) != 1) { + msleep(50); + count++; + if (count > 42) + break; + } + } + + debug_val = pmic_get_register_value(MT6351_PMIC_RGS_PCHR_FLAG_OUT); + battery_log(BAT_LOG_CRTI, "[charging_set_ta_current_pattern] debug_val=0x%x cnt=%d\n", + debug_val, count); + if (count > 10 || debug_val != 0) + status = STATUS_FAIL; + return status; +} + +static unsigned int charging_set_error_state(void *data) +{ + return STATUS_UNSUPPORTED; +} + +static unsigned int charging_sw_init(void *data) +{ + unsigned int regValue; + + VBAT_CV_VTH = VBAT_CV_VTH_F; + + regValue = pmic_get_register_value(MT6351_PMIC_RG_VBAT_NORM_CV_VTH); + + if (regValue == 0xe) + VBAT_CV_VTH = VBAT_CV_VTH_E; + else if (regValue == 0xd) + VBAT_CV_VTH = VBAT_CV_VTH_D; + else if (regValue == 0xc) + VBAT_CV_VTH = VBAT_CV_VTH_C; + else if (regValue == 0x10) + VBAT_CV_VTH = VBAT_CV_VTH_10; + else if (regValue == 0x11) + VBAT_CV_VTH = VBAT_CV_VTH_11; + else if (regValue == 0x12) + VBAT_CV_VTH = VBAT_CV_VTH_12; + + Default_VBAT_CV_VTH = regValue; + battery_log(BAT_LOG_CRTI, "[charging_sw_init] regValue=0x%x\n", regValue); + + return STATUS_OK; +} + + +static unsigned int (*charging_func[CHARGING_CMD_NUMBER]) (void *data); + + + /* + * FUNCTION + * Internal_chr_control_handler + * + * DESCRIPTION + * This function is called to set the charger hw + * + * CALLS + * + * PARAMETERS + * None + * + * RETURNS + * + * + * GLOBALS AFFECTED + * None + */ +signed int chr_control_interface(CHARGING_CTRL_CMD cmd, void *data) +{ + signed int status; + static signed int init = -1; + + if (init == -1) { + init = 0; + charging_func[CHARGING_CMD_INIT] = charging_hw_init; + charging_func[CHARGING_CMD_DUMP_REGISTER] = charging_dump_register; + charging_func[CHARGING_CMD_ENABLE] = charging_enable; + charging_func[CHARGING_CMD_SET_CV_VOLTAGE] = charging_set_cv_voltage; + charging_func[CHARGING_CMD_GET_CURRENT] = charging_get_current; + charging_func[CHARGING_CMD_SET_CURRENT] = charging_set_current; + charging_func[CHARGING_CMD_SET_INPUT_CURRENT] = charging_set_input_current; + charging_func[CHARGING_CMD_GET_CHARGING_STATUS] = charging_get_charging_status; + charging_func[CHARGING_CMD_RESET_WATCH_DOG_TIMER] = charging_reset_watch_dog_timer; + charging_func[CHARGING_CMD_SET_HV_THRESHOLD] = charging_set_hv_threshold; + charging_func[CHARGING_CMD_GET_HV_STATUS] = charging_get_hv_status; + charging_func[CHARGING_CMD_GET_BATTERY_STATUS] = charging_get_battery_status; + charging_func[CHARGING_CMD_GET_CHARGER_DET_STATUS] = + charging_get_charger_det_status; + charging_func[CHARGING_CMD_GET_CHARGER_TYPE] = charging_get_charger_type; + charging_func[CHARGING_CMD_GET_IS_PCM_TIMER_TRIGGER] = + charging_get_is_pcm_timer_trigger; + charging_func[CHARGING_CMD_SET_PLATFORM_RESET] = charging_set_platform_reset; + charging_func[CHARGING_CMD_GET_PLATFORM_BOOT_MODE] = + charging_get_platform_boot_mode; + charging_func[CHARGING_CMD_SET_POWER_OFF] = charging_set_power_off; + charging_func[CHARGING_CMD_GET_POWER_SOURCE] = charging_get_power_source; + charging_func[CHARGING_CMD_GET_CSDAC_FALL_FLAG] = charging_get_csdac_full_flag; + charging_func[CHARGING_CMD_SET_TA_CURRENT_PATTERN] = + charging_set_ta_current_pattern; + charging_func[CHARGING_CMD_SET_ERROR_STATE] = charging_set_error_state; + charging_func[CHARGING_CMD_SW_INIT] = charging_sw_init; + } + + if (cmd < CHARGING_CMD_NUMBER) { + if (charging_func[cmd] != NULL) + status = charging_func[cmd] (data); + else { + battery_log(BAT_LOG_CRTI, + "[chr_control_interface] cmd:%d does not support\n", cmd); + return STATUS_UNSUPPORTED; + } + } else { + battery_log(BAT_LOG_CRTI, "[chr_control_interface] cmd:%d is not legal\n", cmd); + return STATUS_UNSUPPORTED; + } + return status; + +} +#endif diff --git a/drivers/misc/mediatek/power/mt6755/mt6311.c b/drivers/misc/mediatek/power/mt6755/mt6311.c new file mode 100644 index 0000000000000000000000000000000000000000..8248436612b6bd8c0db26185b81ffd5cd53704c1 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/mt6311.c @@ -0,0 +1,7391 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if defined CONFIG_MTK_LEGACY +#include +#endif +#include +/*#include TBD*/ + +#include +#include "mt6311.h" + +#include + +#if defined(CONFIG_MTK_FPGA) +#else +#if defined CONFIG_MTK_LEGACY +/*#include TBD*/ +/*#include TBD*/ +#endif +#endif + +/********************************************************** + * + * [I2C Slave Setting] + * + *********************************************************/ +#define mt6311_SLAVE_ADDR_WRITE 0xD6 +#define mt6311_SLAVE_ADDR_Read 0xD7 + +#define I2C_EXT_BUCK_CHANNEL 3 /*TBD for bring up only, need to change to DTS*/ + +#ifdef I2C_EXT_BUCK_CHANNEL +#define mt6311_BUSNUM I2C_EXT_BUCK_CHANNEL +#else +#define mt6311_BUSNUM 4 +#endif + +static struct i2c_client *new_client; +static const struct i2c_device_id mt6311_i2c_id[] = { {"mt6311", 0}, {} }; + +#ifdef CONFIG_OF +static const struct of_device_id mt6311_of_ids[] = { + {.compatible = "mediatek,ext_buck"}, + {}, +}; +#endif + +static int mt6311_driver_probe(struct i2c_client *client, const struct i2c_device_id *id); + +static struct i2c_driver mt6311_driver = { + .driver = { + .name = "mt6311", +#ifdef CONFIG_OF + .of_match_table = mt6311_of_ids, +#endif + }, + .probe = mt6311_driver_probe, + .id_table = mt6311_i2c_id, +}; + +/********************************************************** + * + * [Global Variable] + * + *********************************************************/ +static DEFINE_MUTEX(mt6311_i2c_access); +static DEFINE_MUTEX(mt6311_lock_mutex); + +int g_mt6311_driver_ready = 0; +int g_mt6311_hw_exist = 0; + +unsigned int g_mt6311_cid = 0; +/* +extern unsigned int upmu_get_reg_value(unsigned int reg); +extern void battery_oc_protect_reinit(void); +*/ +#define PMICTAG "[MT6311] " +#if defined PMIC_DEBUG_PR_DBG +#define PMICLOG1(fmt, arg...) pr_err(PMICTAG fmt, ##arg) +#else +#define PMICLOG1(fmt, arg...) +#endif + +/********************************************************** + * + * [I2C Function For Read/Write mt6311] + * + *********************************************************/ +unsigned int mt6311_read_byte(unsigned char cmd, unsigned char *returnData) +{ + char cmd_buf[1] = { 0x00 }; + char readData = 0; + int ret = 0; + + mutex_lock(&mt6311_i2c_access); +#if 1 + new_client->ext_flag = + ((new_client-> + ext_flag) & I2C_MASK_FLAG) | I2C_WR_FLAG | I2C_PUSHPULL_FLAG | I2C_HS_FLAG; + new_client->timing = 3400; +#else + new_client->ext_flag = + ((new_client-> + ext_flag) & I2C_MASK_FLAG) | I2C_WR_FLAG | I2C_PUSHPULL_FLAG; + new_client->timing = 100; +#endif + + cmd_buf[0] = cmd; + ret = i2c_master_send(new_client, &cmd_buf[0], (1 << 8 | 1)); + if (ret < 0) { + PMICLOG1("[mt6311_read_byte] ret=%d\n", ret); + + new_client->ext_flag = 0; + mutex_unlock(&mt6311_i2c_access); + return ret; + } + + readData = cmd_buf[0]; + *returnData = readData; + + new_client->ext_flag = 0; + + mutex_unlock(&mt6311_i2c_access); + return 1; +} + +unsigned int mt6311_write_byte(unsigned char cmd, unsigned char writeData) +{ + char write_data[2] = { 0 }; + int ret = 0; + + mutex_lock(&mt6311_i2c_access); + + write_data[0] = cmd; + write_data[1] = writeData; + +#if 1 + new_client->ext_flag = + ((new_client-> + ext_flag) & I2C_MASK_FLAG) | I2C_DIRECTION_FLAG | I2C_PUSHPULL_FLAG | I2C_HS_FLAG; + new_client->timing = 3400; +#else + new_client->ext_flag = + ((new_client-> + ext_flag) & I2C_MASK_FLAG) | I2C_PUSHPULL_FLAG; + new_client->timing = 100; +#endif + + ret = i2c_master_send(new_client, write_data, 2); + if (ret < 0) { + PMICLOG1("[mt6311_write_byte] ret=%d\n", ret); + + new_client->ext_flag = 0; + mutex_unlock(&mt6311_i2c_access); + return ret; + } + + new_client->ext_flag = 0; + mutex_unlock(&mt6311_i2c_access); + return 1; +} + +/* + * [Read / Write Function] + */ +unsigned int mt6311_read_interface(unsigned char RegNum, unsigned char *val, unsigned char MASK, unsigned char SHIFT) +{ +#if 0 + PMICLOG1("[mt6311_read_interface] HW no mt6311\n"); + *val = 0; + return 1; +#else + unsigned char mt6311_reg = 0; + unsigned int ret = 0; + + /* PMICLOG1("--------------------------------------------------\n"); */ + + ret = mt6311_read_byte(RegNum, &mt6311_reg); + + /* PMICLOG1("[mt6311_read_interface] Reg[%x]=0x%x\n", RegNum, mt6311_reg); */ + + mt6311_reg &= (MASK << SHIFT); + *val = (mt6311_reg >> SHIFT); + + /* PMICLOG1("[mt6311_read_interface] val=0x%x\n", *val); */ + + return ret; +#endif +} + +unsigned int mt6311_config_interface(unsigned char RegNum, unsigned char val, unsigned char MASK, unsigned char SHIFT) +{ +#if 0 + PMICLOG1("[mt6311_config_interface] HW no mt6311\n"); + return 1; +#else + unsigned char mt6311_reg = 0; + unsigned int ret = 0; + + /*PMICLOG1("--------------------------------------------------\n"); */ + + ret = mt6311_read_byte(RegNum, &mt6311_reg); + /* PMICLOG1("[mt6311_config_interface] Reg[%x]=0x%x\n", RegNum, mt6311_reg);*/ + + mt6311_reg &= ~(MASK << SHIFT); + mt6311_reg |= (val << SHIFT); + + ret = mt6311_write_byte(RegNum, mt6311_reg); + /*PMICLOG1("[mt6311_config_interface] write Reg[%x]=0x%x\n", RegNum, mt6311_reg);*/ + + /* Check*/ + /*ret = mt6311_read_byte(RegNum, &mt6311_reg); + PMICLOG1("[mt6311_config_interface] Check Reg[%x]=0x%x\n", RegNum, mt6311_reg); + */ + + return ret; +#endif +} + +void mt6311_set_reg_value(unsigned int reg, unsigned int reg_val) +{ + unsigned int ret = 0; + + ret = mt6311_config_interface((unsigned char) reg, (unsigned char) reg_val, 0xFF, 0x0); +} + +unsigned int mt6311_get_reg_value(unsigned int reg) +{ + unsigned int ret = 0; + unsigned char reg_val = 0; + + ret = mt6311_read_interface((unsigned char) reg, ®_val, 0xFF, 0x0); + + return reg_val; +} + +/* + * [APIs] + */ +void mt6311_lock(void) +{ + mutex_lock(&mt6311_lock_mutex); +} + +void mt6311_unlock(void) +{ + mutex_unlock(&mt6311_lock_mutex); +} + +unsigned char mt6311_get_cid(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_CID), + (&val), + (unsigned char) (MT6311_PMIC_CID_MASK), + (unsigned char) (MT6311_PMIC_CID_SHIFT) + ); + if (ret < 0) { + PMICLOG1("[mt6311_get_cid] ret=%d\n", ret); + mt6311_unlock(); + return ret; + } + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_swcid(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_SWCID), + (&val), + (unsigned char) (MT6311_PMIC_SWCID_MASK), + (unsigned char) (MT6311_PMIC_SWCID_SHIFT) + ); + if (ret < 0) { + PMICLOG1("[mt6311_get_swcid] ret=%d\n", ret); + mt6311_unlock(); + return ret; + } + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_hwcid(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_HWCID), + (&val), + (unsigned char) (MT6311_PMIC_HWCID_MASK), + (unsigned char) (MT6311_PMIC_HWCID_SHIFT) + ); + if (ret < 0) { + PMICLOG1("[mt6311_get_hwcid] ret=%d\n", ret); + mt6311_unlock(); + return ret; + } + mt6311_unlock(); + + return val; +} + +void mt6311_set_gpio0_dir(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_GPIO_CFG), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_GPIO0_DIR_MASK), + (unsigned char) (MT6311_PMIC_GPIO0_DIR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_gpio1_dir(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_GPIO_CFG), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_GPIO1_DIR_MASK), + (unsigned char) (MT6311_PMIC_GPIO1_DIR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_gpio0_dinv(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_GPIO_CFG), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_GPIO0_DINV_MASK), + (unsigned char) (MT6311_PMIC_GPIO0_DINV_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_gpio1_dinv(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_GPIO_CFG), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_GPIO1_DINV_MASK), + (unsigned char) (MT6311_PMIC_GPIO1_DINV_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_gpio0_dout(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_GPIO_CFG), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_GPIO0_DOUT_MASK), + (unsigned char) (MT6311_PMIC_GPIO0_DOUT_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_gpio1_dout(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_GPIO_CFG), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_GPIO1_DOUT_MASK), + (unsigned char) (MT6311_PMIC_GPIO1_DOUT_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_gpio0_din(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_GPIO_CFG), + (&val), + (unsigned char) (MT6311_PMIC_GPIO0_DIN_MASK), + (unsigned char) (MT6311_PMIC_GPIO0_DIN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_gpio1_din(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_GPIO_CFG), + (&val), + (unsigned char) (MT6311_PMIC_GPIO1_DIN_MASK), + (unsigned char) (MT6311_PMIC_GPIO1_DIN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_gpio0_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_GPIO_MODE), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_GPIO0_MODE_MASK), + (unsigned char) (MT6311_PMIC_GPIO0_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_gpio1_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_GPIO_MODE), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_GPIO1_MODE_MASK), + (unsigned char) (MT6311_PMIC_GPIO1_MODE_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_test_out(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_TEST_OUT), + (&val), + (unsigned char) (MT6311_PMIC_TEST_OUT_MASK), + (unsigned char) (MT6311_PMIC_TEST_OUT_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_mon_grp_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TEST_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_MON_GRP_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_MON_GRP_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_mon_flag_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TEST_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_MON_FLAG_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_MON_FLAG_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_dig_testmode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TEST_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_DIG_TESTMODE_MASK), + (unsigned char) (MT6311_PMIC_DIG_TESTMODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_pmu_testmode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TEST_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_PMU_TESTMODE_MASK), + (unsigned char) (MT6311_PMIC_PMU_TESTMODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_srclken_in_hw_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_SRCLKEN_IN_HW_MODE_MASK), + (unsigned char) (MT6311_PMIC_RG_SRCLKEN_IN_HW_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_srclken_in_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_SRCLKEN_IN_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_SRCLKEN_IN_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_lp_hw_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_LP_HW_MODE_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_LP_HW_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_lp_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_LP_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_LP_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_osc_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_OSC_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_OSC_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_osc_en_hw_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_OSC_EN_HW_MODE_MASK), + (unsigned char) (MT6311_PMIC_RG_OSC_EN_HW_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_srclken_in_sync_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_SRCLKEN_IN_SYNC_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_SRCLKEN_IN_SYNC_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_rsv_hw_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_RSV_HW_MODE_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_RSV_HW_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_ref_ck_tstsel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKTST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_REF_CK_TSTSEL_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_REF_CK_TSTSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_fqmtr_ck_tstsel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKTST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_FQMTR_CK_TSTSEL_MASK), + (unsigned char) (MT6311_PMIC_RG_FQMTR_CK_TSTSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_smps_ck_tstsel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKTST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_SMPS_CK_TSTSEL_MASK), + (unsigned char) (MT6311_PMIC_RG_SMPS_CK_TSTSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_pmu75k_ck_tstsel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKTST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_PMU75K_CK_TSTSEL_MASK), + (unsigned char) (MT6311_PMIC_RG_PMU75K_CK_TSTSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_smps_ck_tst_dis(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKTST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_SMPS_CK_TST_DIS_MASK), + (unsigned char) (MT6311_PMIC_RG_SMPS_CK_TST_DIS_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_pmu75k_ck_tst_dis(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKTST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_PMU75K_CK_TST_DIS_MASK), + (unsigned char) (MT6311_PMIC_RG_PMU75K_CK_TST_DIS_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_ana_auto_off_dis(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKTST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_ref_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_REF_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_REF_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_1m_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_1M_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_1M_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_intrp_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_INTRP_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_INTRP_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_75k_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_75K_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_75K_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_ana_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_ANA_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_ANA_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_trim_75k_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_TRIM_75K_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_TRIM_75K_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_auxadc_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_AUXADC_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_AUXADC_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_auxadc_1m_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_AUXADC_1M_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_AUXADC_1M_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_stb_75k_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STB_75K_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_STB_75K_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_fqmtr_ck_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_FQMTR_CK_PDN_MASK), + (unsigned char) (MT6311_PMIC_RG_FQMTR_CK_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_top_ckpdn_con2_rsv(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKPDN_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_TOP_CKPDN_CON2_RSV_MASK), + (unsigned char) (MT6311_PMIC_TOP_CKPDN_CON2_RSV_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_buck_1m_ck_pdn_hwen(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKHWEN_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BUCK_1M_CK_PDN_HWEN_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_1M_CK_PDN_HWEN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_ck_pdn_hwen(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CKHWEN_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_CK_PDN_HWEN_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_CK_PDN_HWEN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_auxadc_rst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_RST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_AUXADC_RST_MASK), + (unsigned char) (MT6311_PMIC_RG_AUXADC_RST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_fqmtr_rst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_RST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_FQMTR_RST_MASK), + (unsigned char) (MT6311_PMIC_RG_FQMTR_RST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_clk_trim_rst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_RST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_CLK_TRIM_RST_MASK), + (unsigned char) (MT6311_PMIC_RG_CLK_TRIM_RST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_man_rst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_RST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_MAN_RST_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_MAN_RST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_wdtrstb_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_RST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_WDTRSTB_MODE_MASK), + (unsigned char) (MT6311_PMIC_RG_WDTRSTB_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_wdtrstb_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_RST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_WDTRSTB_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_WDTRSTB_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_wdtrstb_status_clr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_RST_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_WDTRSTB_STATUS_CLR_MASK), + (unsigned char) (MT6311_PMIC_WDTRSTB_STATUS_CLR_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_wdtrstb_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_TOP_RST_CON), + (&val), + (unsigned char) (MT6311_PMIC_WDTRSTB_STATUS_MASK), + (unsigned char) (MT6311_PMIC_WDTRSTB_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_int_pol(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_INT_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_INT_POL_MASK), + (unsigned char) (MT6311_PMIC_RG_INT_POL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_int_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_INT_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_INT_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_INT_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_i2c_config(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_INT_CON), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_I2C_CONFIG_MASK), + (unsigned char) (MT6311_PMIC_I2C_CONFIG_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_rg_lbat_min_int_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_TOP_INT_MON), + (&val), + (unsigned char) (MT6311_PMIC_RG_LBAT_MIN_INT_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RG_LBAT_MIN_INT_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_lbat_max_int_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_TOP_INT_MON), + (&val), + (unsigned char) (MT6311_PMIC_RG_LBAT_MAX_INT_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RG_LBAT_MAX_INT_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_thr_l_int_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_TOP_INT_MON), + (&val), + (unsigned char) (MT6311_PMIC_RG_THR_L_INT_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RG_THR_L_INT_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_thr_h_int_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_TOP_INT_MON), + (&val), + (unsigned char) (MT6311_PMIC_RG_THR_H_INT_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RG_THR_H_INT_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_buck_oc_int_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_TOP_INT_MON), + (&val), + (unsigned char) (MT6311_PMIC_RG_BUCK_OC_INT_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RG_BUCK_OC_INT_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_thr_det_dis(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_THR_DET_DIS_MASK), + (unsigned char) (MT6311_PMIC_THR_DET_DIS_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_thr_hwpdn_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_THR_HWPDN_EN_MASK), + (unsigned char) (MT6311_PMIC_THR_HWPDN_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_dig0_rsv0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_DIG0_RSV0_MASK), + (unsigned char) (MT6311_PMIC_STRUP_DIG0_RSV0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_usbdl_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_USBDL_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_USBDL_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_test_strup(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_TEST_STRUP_MASK), + (unsigned char) (MT6311_PMIC_RG_TEST_STRUP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_test_strup_thr_in(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_TEST_STRUP_THR_IN_MASK), + (unsigned char) (MT6311_PMIC_RG_TEST_STRUP_THR_IN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_dig1_rsv0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_DIG1_RSV0_MASK), + (unsigned char) (MT6311_PMIC_STRUP_DIG1_RSV0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_thr_test(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_THR_TEST_MASK), + (unsigned char) (MT6311_PMIC_THR_TEST_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_pmu_thr_deb(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON2), + (&val), + (unsigned char) (MT6311_PMIC_PMU_THR_DEB_MASK), + (unsigned char) (MT6311_PMIC_PMU_THR_DEB_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_pmu_thr_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON2), + (&val), + (unsigned char) (MT6311_PMIC_PMU_THR_STATUS_MASK), + (unsigned char) (MT6311_PMIC_PMU_THR_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_strup_pwron(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_PWRON_MASK), + (unsigned char) (MT6311_PMIC_STRUP_PWRON_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_pwron_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_PWRON_SEL_MASK), + (unsigned char) (MT6311_PMIC_STRUP_PWRON_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_bias_gen_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BIAS_GEN_EN_MASK), + (unsigned char) (MT6311_PMIC_BIAS_GEN_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_bias_gen_en_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BIAS_GEN_EN_SEL_MASK), + (unsigned char) (MT6311_PMIC_BIAS_GEN_EN_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rtc_xosc32_enb_sw(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RTC_XOSC32_ENB_SW_MASK), + (unsigned char) (MT6311_PMIC_RTC_XOSC32_ENB_SW_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rtc_xosc32_enb_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RTC_XOSC32_ENB_SEL_MASK), + (unsigned char) (MT6311_PMIC_RTC_XOSC32_ENB_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_dig_io_pg_force(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_DIG_IO_PG_FORCE_MASK), + (unsigned char) (MT6311_PMIC_STRUP_DIG_IO_PG_FORCE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_dduvlo_deb_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_DDUVLO_DEB_EN_MASK), + (unsigned char) (MT6311_PMIC_DDUVLO_DEB_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_pwrbb_deb_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_PWRBB_DEB_EN_MASK), + (unsigned char) (MT6311_PMIC_PWRBB_DEB_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_osc_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_OSC_EN_MASK), + (unsigned char) (MT6311_PMIC_STRUP_OSC_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_osc_en_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_OSC_EN_SEL_MASK), + (unsigned char) (MT6311_PMIC_STRUP_OSC_EN_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_ft_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_FT_CTRL_MASK), + (unsigned char) (MT6311_PMIC_STRUP_FT_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_pwron_force(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_PWRON_FORCE_MASK), + (unsigned char) (MT6311_PMIC_STRUP_PWRON_FORCE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_bias_gen_en_force(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BIAS_GEN_EN_FORCE_MASK), + (unsigned char) (MT6311_PMIC_BIAS_GEN_EN_FORCE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_pg_h2l_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_PG_H2L_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_PG_H2L_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_pg_h2l_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_PG_H2L_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_PG_H2L_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vbiasn_pg_h2l_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VBIASN_PG_H2L_EN_MASK), + (unsigned char) (MT6311_PMIC_VBIASN_PG_H2L_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_pg_enb(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_PG_ENB_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_PG_ENB_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_pg_enb(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_PG_ENB_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_PG_ENB_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vbiasn_pg_enb(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VBIASN_PG_ENB_MASK), + (unsigned char) (MT6311_PMIC_VBIASN_PG_ENB_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_ext_pmic_en_pg_enb(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EXT_PMIC_EN_PG_ENB_MASK), + (unsigned char) (MT6311_PMIC_RG_EXT_PMIC_EN_PG_ENB_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_pre_pwron_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_PRE_PWRON_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_PRE_PWRON_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_pre_pwron_swctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_PRE_PWRON_SWCTRL_MASK), + (unsigned char) (MT6311_PMIC_RG_PRE_PWRON_SWCTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_clr_just_rst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_CLR_JUST_RST_MASK), + (unsigned char) (MT6311_PMIC_CLR_JUST_RST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_uvlo_l2h_deb_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_UVLO_L2H_DEB_EN_MASK), + (unsigned char) (MT6311_PMIC_UVLO_L2H_DEB_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_bgr_test_ckin_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BGR_TEST_CKIN_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_BGR_TEST_CKIN_EN_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_osc_en(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON7), + (&val), + (unsigned char) (MT6311_PMIC_QI_OSC_EN_MASK), + (unsigned char) (MT6311_PMIC_QI_OSC_EN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_strup_pmu_pwron_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_PMU_PWRON_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_PMU_PWRON_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_pmu_pwron_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_PMU_PWRON_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_PMU_PWRON_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_auxadc_start_sw(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_AUXADC_START_SW_MASK), + (unsigned char) (MT6311_PMIC_STRUP_AUXADC_START_SW_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_auxadc_rstb_sw(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_AUXADC_RSTB_SW_MASK), + (unsigned char) (MT6311_PMIC_STRUP_AUXADC_RSTB_SW_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_auxadc_start_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_AUXADC_START_SEL_MASK), + (unsigned char) (MT6311_PMIC_STRUP_AUXADC_START_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_auxadc_rstb_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_AUXADC_RSTB_SEL_MASK), + (unsigned char) (MT6311_PMIC_STRUP_AUXADC_RSTB_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_pwroff_preoff_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_PWROFF_PREOFF_EN_MASK), + (unsigned char) (MT6311_PMIC_STRUP_PWROFF_PREOFF_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_strup_pwroff_seq_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_PWROFF_SEQ_EN_MASK), + (unsigned char) (MT6311_PMIC_STRUP_PWROFF_SEQ_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_sys_latch_en_swctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_SYS_LATCH_EN_SWCTRL_MASK), + (unsigned char) (MT6311_PMIC_RG_SYS_LATCH_EN_SWCTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_sys_latch_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_SYS_LATCH_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_SYS_LATCH_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_onoff_en_swctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_ONOFF_EN_SWCTRL_MASK), + (unsigned char) (MT6311_PMIC_RG_ONOFF_EN_SWCTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_onoff_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_ONOFF_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_ONOFF_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_pwron_cond_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_PWRON_COND_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_PWRON_COND_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_pwron_cond_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_PWRON_COND_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_PWRON_COND_EN_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_strup_pg_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON11), + (&val), + (unsigned char) (MT6311_PMIC_STRUP_PG_STATUS_MASK), + (unsigned char) (MT6311_PMIC_STRUP_PG_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_strup_pg_status_clr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_STRUP_PG_STATUS_CLR_MASK), + (unsigned char) (MT6311_PMIC_STRUP_PG_STATUS_CLR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_rsv_swreg(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON12), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_RSV_SWREG_MASK), + (unsigned char) (MT6311_PMIC_RG_RSV_SWREG_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_vdvfs11_pg_deb(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON13), + (&val), + (unsigned char) (MT6311_PMIC_VDVFS11_PG_DEB_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_PG_DEB_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_vdvfs12_pg_deb(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON13), + (&val), + (unsigned char) (MT6311_PMIC_VDVFS12_PG_DEB_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_PG_DEB_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_vbiasn_pg_deb(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON13), + (&val), + (unsigned char) (MT6311_PMIC_VBIASN_PG_DEB_MASK), + (unsigned char) (MT6311_PMIC_VBIASN_PG_DEB_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_strup_ro_rsv0(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON13), + (&val), + (unsigned char) (MT6311_PMIC_STRUP_RO_RSV0_MASK), + (unsigned char) (MT6311_PMIC_STRUP_RO_RSV0_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_strup_thr_110_clr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_110_CLR_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_110_CLR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_thr_125_clr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_125_CLR_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_125_CLR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_thr_110_irq_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_110_IRQ_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_110_IRQ_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_thr_125_irq_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_125_IRQ_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_125_IRQ_EN_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_rg_strup_thr_110_irq_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON14), + (&val), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_110_IRQ_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_110_IRQ_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_strup_thr_125_irq_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_STRUP_CON14), + (&val), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_125_IRQ_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_125_IRQ_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_thermal_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_THERMAL_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_THERMAL_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_thermal_en_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_THERMAL_EN_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_THERMAL_EN_SEL_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_rg_osc_75k_trim(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_TOP_CLK_TRIM0), + (&val), + (unsigned char) (MT6311_PMIC_RG_OSC_75K_TRIM_MASK), + (unsigned char) (MT6311_PMIC_RG_OSC_75K_TRIM_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_osc_75k_trim(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CLK_TRIM1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_OSC_75K_TRIM_MASK), + (unsigned char) (MT6311_PMIC_OSC_75K_TRIM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_osc_75k_trim_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CLK_TRIM1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_OSC_75K_TRIM_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_OSC_75K_TRIM_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_osc_75k_trim_rate(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_TOP_CLK_TRIM1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_OSC_75K_TRIM_RATE_MASK), + (unsigned char) (MT6311_PMIC_RG_OSC_75K_TRIM_RATE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_addr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_ADDR_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_ADDR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_din(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DIN_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DIN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_dm(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DM_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_pgm(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_PGM_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_PGM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_pgm_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_PGM_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_PGM_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_prog_pkey(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_PROG_PKEY_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_PROG_PKEY_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_rd_pkey(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_RD_PKEY_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_RD_PKEY_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_pgm_src(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_PGM_SRC_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_PGM_SRC_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_din_src(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DIN_SRC_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DIN_SRC_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_rd_trig(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_RD_TRIG_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_RD_TRIG_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_rd_rdy_bypass(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_RD_RDY_BYPASS_MASK), + (unsigned char) (MT6311_PMIC_RG_RD_RDY_BYPASS_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_skip_efuse_out(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_SKIP_EFUSE_OUT_MASK), + (unsigned char) (MT6311_PMIC_RG_SKIP_EFUSE_OUT_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_rg_efuse_rd_ack(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_CON12), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_RD_ACK_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_RD_ACK_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_rd_busy(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_CON12), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_RD_BUSY_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_RD_BUSY_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_efuse_write_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_CON13), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_WRITE_MODE_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_WRITE_MODE_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_rg_efuse_dout_0_7(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_0_7), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_0_7_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_0_7_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_8_15(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_8_15), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_8_15_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_8_15_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_16_23(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_16_23), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_16_23_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_16_23_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_24_31(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_24_31), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_24_31_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_24_31_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_32_39(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_32_39), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_32_39_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_32_39_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_40_47(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_40_47), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_40_47_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_40_47_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_48_55(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_48_55), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_48_55_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_48_55_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_56_63(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_56_63), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_56_63_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_56_63_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_64_71(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_64_71), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_64_71_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_64_71_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_72_79(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_72_79), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_72_79_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_72_79_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_80_87(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_80_87), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_80_87_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_80_87_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_88_95(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_88_95), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_88_95_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_88_95_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_96_103(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_96_103), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_96_103_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_96_103_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_104_111(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_104_111), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_104_111_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_104_111_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_112_119(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_112_119), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_112_119_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_112_119_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rg_efuse_dout_120_127(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_EFUSE_DOUT_120_127), + (&val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_120_127_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_DOUT_120_127_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_efuse_val_0_7(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_0_7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_0_7_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_0_7_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_8_15(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_8_15), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_8_15_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_8_15_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_16_23(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_16_23), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_16_23_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_16_23_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_24_31(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_24_31), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_24_31_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_24_31_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_32_39(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_32_39), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_32_39_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_32_39_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_40_47(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_40_47), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_40_47_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_40_47_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_48_55(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_48_55), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_48_55_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_48_55_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_56_63(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_56_63), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_56_63_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_56_63_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_64_71(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_64_71), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_64_71_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_64_71_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_72_79(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_72_79), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_72_79_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_72_79_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_80_87(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_80_87), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_80_87_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_80_87_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_88_95(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_88_95), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_88_95_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_88_95_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_96_103(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_96_103), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_96_103_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_96_103_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_104_111(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_104_111), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_104_111_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_104_111_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_112_119(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_112_119), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_112_119_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_112_119_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_efuse_val_120_127(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_EFUSE_VAL_120_127), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_120_127_MASK), + (unsigned char) (MT6311_PMIC_RG_EFUSE_VAL_120_127_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_buck_dig0_rsv0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BUCK_DIG0_RSV0_MASK), + (unsigned char) (MT6311_PMIC_BUCK_DIG0_RSV0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vsleep_src0_8(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VSLEEP_SRC0_8_MASK), + (unsigned char) (MT6311_PMIC_VSLEEP_SRC0_8_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vsleep_src1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VSLEEP_SRC1_MASK), + (unsigned char) (MT6311_PMIC_VSLEEP_SRC1_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vsleep_src0_7_0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VSLEEP_SRC0_7_0_MASK), + (unsigned char) (MT6311_PMIC_VSLEEP_SRC0_7_0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_r2r_src0_8(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_R2R_SRC0_8_MASK), + (unsigned char) (MT6311_PMIC_R2R_SRC0_8_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_r2r_src1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_R2R_SRC1_MASK), + (unsigned char) (MT6311_PMIC_R2R_SRC1_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_r2r_src0_7_0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_R2R_SRC0_7_0_MASK), + (unsigned char) (MT6311_PMIC_R2R_SRC0_7_0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_buck_osc_sel_src0_8(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BUCK_OSC_SEL_SRC0_8_MASK), + (unsigned char) (MT6311_PMIC_BUCK_OSC_SEL_SRC0_8_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_srclken_dly_src1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_SRCLKEN_DLY_SRC1_MASK), + (unsigned char) (MT6311_PMIC_SRCLKEN_DLY_SRC1_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_buck_osc_sel_src0_7_0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BUCK_OSC_SEL_SRC0_7_0_MASK), + (unsigned char) (MT6311_PMIC_BUCK_OSC_SEL_SRC0_7_0_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_vdvfs12_dig_mon(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_BUCK_ALL_CON7), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_DIG_MON_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_DIG_MON_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_qi_vdvfs11_dig_mon(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_BUCK_ALL_CON8), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_DIG_MON_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_DIG_MON_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs11_oc_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_oc_deg_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_DEG_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_DEG_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_oc_wnd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_WND_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_WND_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_oc_thd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_THD_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_THD_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_oc_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_oc_deg_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_DEG_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_DEG_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_oc_wnd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_WND_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_WND_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_oc_thd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_THD_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_THD_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_oc_flag_clr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_FLAG_CLR_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_FLAG_CLR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_oc_flag_clr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_FLAG_CLR_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_FLAG_CLR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_oc_rg_status_clr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_RG_STATUS_CLR_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_RG_STATUS_CLR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_oc_rg_status_clr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_RG_STATUS_CLR_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_RG_STATUS_CLR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_oc_flag_clr_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_FLAG_CLR_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_FLAG_CLR_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_oc_flag_clr_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_FLAG_CLR_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_FLAG_CLR_SEL_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_vdvfs11_oc_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_BUCK_ALL_CON20), + (&val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_STATUS_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_vdvfs12_oc_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_BUCK_ALL_CON20), + (&val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_STATUS_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs11_oc_int_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON21), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_INT_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_OC_INT_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_oc_int_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON21), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_INT_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_OC_INT_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_en_oc_sdn_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON22), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_EN_OC_SDN_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_EN_OC_SDN_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_en_oc_sdn_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON22), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_EN_OC_SDN_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_EN_OC_SDN_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_buck_test_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON23), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BUCK_TEST_MODE_MASK), + (unsigned char) (MT6311_PMIC_BUCK_TEST_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_buck_dig1_rsv0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON23), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BUCK_DIG1_RSV0_MASK), + (unsigned char) (MT6311_PMIC_BUCK_DIG1_RSV0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_qi_vdvfs11_vsleep(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON24), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_VSLEEP_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_VSLEEP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_qi_vdvfs12_vsleep(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_ALL_CON24), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_VSLEEP_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_VSLEEP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_buck_ana_dig0_rsv0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_ANA_RSV_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_BUCK_ANA_DIG0_RSV0_MASK), + (unsigned char) (MT6311_PMIC_BUCK_ANA_DIG0_RSV0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_thrdet_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_THRDET_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_THRDET_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_thr_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_THR_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_thr_tmode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_THR_TMODE_MASK), + (unsigned char) (MT6311_PMIC_RG_THR_TMODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_iref_trim(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_IREF_TRIM_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_IREF_TRIM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_uvlo_vthl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_UVLO_VTHL_MASK), + (unsigned char) (MT6311_PMIC_RG_UVLO_VTHL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_uvlo_vthh(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_UVLO_VTHH_MASK), + (unsigned char) (MT6311_PMIC_RG_UVLO_VTHH_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_bgr_unchop(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BGR_UNCHOP_MASK), + (unsigned char) (MT6311_PMIC_RG_BGR_UNCHOP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_bgr_unchop_ph(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BGR_UNCHOP_PH_MASK), + (unsigned char) (MT6311_PMIC_RG_BGR_UNCHOP_PH_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_bgr_rsel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BGR_RSEL_MASK), + (unsigned char) (MT6311_PMIC_RG_BGR_RSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_bgr_trim(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BGR_TRIM_MASK), + (unsigned char) (MT6311_PMIC_RG_BGR_TRIM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_bgr_test_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BGR_TEST_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_BGR_TEST_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_bgr_test_rstb(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BGR_TEST_RSTB_MASK), + (unsigned char) (MT6311_PMIC_RG_BGR_TEST_RSTB_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_trimh(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TRIMH_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TRIMH_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_triml(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TRIML_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TRIML_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_trimh(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_TRIMH_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_TRIMH_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_triml(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_TRIML_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_TRIML_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_vsleep(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_VSLEEP_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_VSLEEP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_vsleep(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_VSLEEP_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_VSLEEP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_bgr_osc_cal(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_BGR_OSC_CAL_MASK), + (unsigned char) (MT6311_PMIC_RG_BGR_OSC_CAL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_strup_rsv(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_STRUP_RSV_MASK), + (unsigned char) (MT6311_PMIC_RG_STRUP_RSV_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vref_lp_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VREF_LP_MODE_MASK), + (unsigned char) (MT6311_PMIC_RG_VREF_LP_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_testmode_swen(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_TESTMODE_SWEN_MASK), + (unsigned char) (MT6311_PMIC_RG_TESTMODE_SWEN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdig18_vosel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDIG18_VOSEL_MASK), + (unsigned char) (MT6311_PMIC_RG_VDIG18_VOSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdig18_cal(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON12), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDIG18_CAL_MASK), + (unsigned char) (MT6311_PMIC_RG_VDIG18_CAL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_osc_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_STRUP_ANA_CON12), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_OSC_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_OSC_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_ndis_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VBIASN_ANA_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_NDIS_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_NDIS_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_vosel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VBIASN_ANA_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_VOSEL_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_VOSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_rc(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_RC_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_RC_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_rc(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_RC_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_RC_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_csr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_CSR_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_CSR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_csr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_CSR_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_CSR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_pfm_csr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_PFM_CSR_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_PFM_CSR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_pfm_csr(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_PFM_CSR_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_PFM_CSR_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_slp(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_SLP_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_SLP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_slp(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_SLP_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_SLP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_uvp_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_UVP_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_UVP_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_uvp_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_UVP_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_UVP_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_modeset(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_MODESET_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_MODESET_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_modeset(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_MODESET_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_MODESET_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_ndis_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_NDIS_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_NDIS_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_ndis_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_NDIS_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_NDIS_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_trans_bst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TRANS_BST_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TRANS_BST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_trans_bst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_TRANS_BST_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_TRANS_BST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_csm_n(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_CSM_N_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_CSM_N_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_csm_p(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_CSM_P_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_CSM_P_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_csm_n(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_CSM_N_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_CSM_N_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_csm_p(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_CSM_P_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_CSM_P_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_zxos_trim(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_ZXOS_TRIM_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_ZXOS_TRIM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_zxos_trim(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_ZXOS_TRIM_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_ZXOS_TRIM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_oc_off(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_OC_OFF_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_OC_OFF_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_oc_off(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_OC_OFF_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_OC_OFF_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_phs_shed_trim(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_PHS_SHED_TRIM_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_PHS_SHED_TRIM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_f2phs(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_F2PHS_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_F2PHS_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_rs_force_off(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_RS_FORCE_OFF_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_RS_FORCE_OFF_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs12_rs_force_off(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_RS_FORCE_OFF_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS12_RS_FORCE_OFF_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_tm_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TM_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TM_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs11_tm_ugsns(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TM_UGSNS_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS11_TM_UGSNS_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vdvfs1_fbn_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS1_ANA_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VDVFS1_FBN_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_VDVFS1_FBN_SEL_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_rgs_vdvfs11_enpwm_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS1_ANA_CON12), + (&val), + (unsigned char) (MT6311_PMIC_RGS_VDVFS11_ENPWM_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RGS_VDVFS11_ENPWM_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_rgs_vdvfs12_enpwm_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS1_ANA_CON12), + (&val), + (unsigned char) (MT6311_PMIC_RGS_VDVFS12_ENPWM_STATUS_MASK), + (unsigned char) (MT6311_PMIC_RGS_VDVFS12_ENPWM_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_ni_vdvfs1_count(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS1_ANA_CON12), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS1_COUNT_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS1_COUNT_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs11_dig0_rsv0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_DIG0_RSV0_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_DIG0_RSV0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_en_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_EN_CTRL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_EN_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_vosel_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_CTRL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_dig0_rsv1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_DIG0_RSV1_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_DIG0_RSV1_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_burst_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_CTRL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_en_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_EN_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_EN_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_vosel_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_dig0_rsv2(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_DIG0_RSV2_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_DIG0_RSV2_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_burst_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_stbtd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_STBTD_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_STBTD_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_vdvfs11_stb(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS11_CON9), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_STB_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_STB_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_qi_vdvfs11_en(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS11_CON9), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_EN_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_EN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_qi_vdvfs11_oc_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS11_CON9), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_OC_STATUS_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_OC_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs11_sfchg_rrate(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_SFCHG_RRATE_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_SFCHG_RRATE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_sfchg_ren(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_SFCHG_REN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_SFCHG_REN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_sfchg_frate(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_SFCHG_FRATE_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_SFCHG_FRATE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_sfchg_fen(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_SFCHG_FEN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_SFCHG_FEN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_vosel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON12), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_vosel_on(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON13), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_ON_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_ON_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_vosel_sleep(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_SLEEP_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_VOSEL_SLEEP_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_ni_vdvfs11_vosel(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS11_CON15), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS11_VOSEL_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS11_VOSEL_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs11_burst_sleep(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON16), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_SLEEP_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_SLEEP_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_vdvfs11_burst(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS11_CON16), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_BURST_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS11_BURST_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs11_burst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON17), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_burst_on(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON17), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_ON_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_BURST_ON_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_vsleep_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_VSLEEP_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_VSLEEP_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_r2r_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_R2R_PDN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_R2R_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_vsleep_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_VSLEEP_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_VSLEEP_SEL_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_ni_vdvfs11_r2r_pdn(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS11_CON18), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS11_R2R_PDN_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS11_R2R_PDN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_ni_vdvfs11_vsleep_sel(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS11_CON18), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS11_VSLEEP_SEL_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS11_VSLEEP_SEL_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs11_trans_td(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_TRANS_TD_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_TRANS_TD_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_trans_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_TRANS_CTRL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_TRANS_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs11_trans_once(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS11_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS11_TRANS_ONCE_MASK), + (unsigned char) (MT6311_PMIC_VDVFS11_TRANS_ONCE_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_ni_vdvfs11_vosel_trans(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS11_CON19), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS11_VOSEL_TRANS_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS11_VOSEL_TRANS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs12_dig0_rsv0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_DIG0_RSV0_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_DIG0_RSV0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_en_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_EN_CTRL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_EN_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_vosel_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_CTRL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_dig0_rsv1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_DIG0_RSV1_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_DIG0_RSV1_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_burst_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_CTRL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_en_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_EN_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_EN_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_vosel_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_dig0_rsv2(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_DIG0_RSV2_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_DIG0_RSV2_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_burst_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_stbtd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_STBTD_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_STBTD_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_vdvfs12_stb(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS12_CON9), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_STB_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_STB_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_qi_vdvfs12_en(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS12_CON9), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_EN_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_EN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_qi_vdvfs12_oc_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS12_CON9), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_OC_STATUS_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_OC_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs12_sfchg_rrate(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_SFCHG_RRATE_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_SFCHG_RRATE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_sfchg_ren(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_SFCHG_REN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_SFCHG_REN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_sfchg_frate(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_SFCHG_FRATE_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_SFCHG_FRATE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_sfchg_fen(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_SFCHG_FEN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_SFCHG_FEN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_vosel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON12), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_vosel_on(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON13), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_ON_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_ON_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_vosel_sleep(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_SLEEP_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_VOSEL_SLEEP_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_ni_vdvfs12_vosel(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS12_CON15), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS12_VOSEL_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS12_VOSEL_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs12_burst_sleep(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON16), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_SLEEP_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_SLEEP_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_vdvfs12_burst(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS12_CON16), + (&val), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_BURST_MASK), + (unsigned char) (MT6311_PMIC_QI_VDVFS12_BURST_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs12_burst(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON17), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_burst_on(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON17), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_ON_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_BURST_ON_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_vsleep_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_VSLEEP_EN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_VSLEEP_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_r2r_pdn(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_R2R_PDN_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_R2R_PDN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_vsleep_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_VSLEEP_SEL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_VSLEEP_SEL_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_ni_vdvfs12_r2r_pdn(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS12_CON18), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS12_R2R_PDN_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS12_R2R_PDN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_ni_vdvfs12_vsleep_sel(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS12_CON18), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS12_VSLEEP_SEL_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS12_VSLEEP_SEL_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_vdvfs12_trans_td(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_TRANS_TD_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_TRANS_TD_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_trans_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_TRANS_CTRL_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_TRANS_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_vdvfs12_trans_once(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_VDVFS12_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_VDVFS12_TRANS_ONCE_MASK), + (unsigned char) (MT6311_PMIC_VDVFS12_TRANS_ONCE_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_ni_vdvfs12_vosel_trans(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_VDVFS12_CON19), + (&val), + (unsigned char) (MT6311_PMIC_NI_VDVFS12_VOSEL_TRANS_MASK), + (unsigned char) (MT6311_PMIC_NI_VDVFS12_VOSEL_TRANS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_k_rst_done(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_RST_DONE_MASK), + (unsigned char) (MT6311_PMIC_K_RST_DONE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_map_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_MAP_SEL_MASK), + (unsigned char) (MT6311_PMIC_K_MAP_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_once_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_ONCE_EN_MASK), + (unsigned char) (MT6311_PMIC_K_ONCE_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_once(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_ONCE_MASK), + (unsigned char) (MT6311_PMIC_K_ONCE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_start_manual(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_START_MANUAL_MASK), + (unsigned char) (MT6311_PMIC_K_START_MANUAL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_src_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_SRC_SEL_MASK), + (unsigned char) (MT6311_PMIC_K_SRC_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_auto_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_AUTO_EN_MASK), + (unsigned char) (MT6311_PMIC_K_AUTO_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_inv(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_INV_MASK), + (unsigned char) (MT6311_PMIC_K_INV_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_control_smps(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_CONTROL_SMPS_MASK), + (unsigned char) (MT6311_PMIC_K_CONTROL_SMPS_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_smps_osc_cal(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_BUCK_K_CON2), + (&val), + (unsigned char) (MT6311_PMIC_QI_SMPS_OSC_CAL_MASK), + (unsigned char) (MT6311_PMIC_QI_SMPS_OSC_CAL_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_k_result(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_BUCK_K_CON3), + (&val), + (unsigned char) (MT6311_PMIC_K_RESULT_MASK), + (unsigned char) (MT6311_PMIC_K_RESULT_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_k_done(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_BUCK_K_CON3), + (&val), + (unsigned char) (MT6311_PMIC_K_DONE_MASK), + (unsigned char) (MT6311_PMIC_K_DONE_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_k_control(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_BUCK_K_CON3), + (&val), + (unsigned char) (MT6311_PMIC_K_CONTROL_MASK), + (unsigned char) (MT6311_PMIC_K_CONTROL_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_k_buck_ck_cnt_8(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_BUCK_CK_CNT_8_MASK), + (unsigned char) (MT6311_PMIC_K_BUCK_CK_CNT_8_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_k_buck_ck_cnt_7_0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_BUCK_K_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_K_BUCK_CK_CNT_7_0_MASK), + (unsigned char) (MT6311_PMIC_K_BUCK_CK_CNT_7_0_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_auxadc_adc_out_ch0(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_ADC0), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_OUT_CH0_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_OUT_CH0_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_adc_rdy_ch0(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_ADC0), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_RDY_CH0_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_RDY_CH0_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_adc_out_ch1(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_ADC1), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_OUT_CH1_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_OUT_CH1_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_adc_rdy_ch1(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_ADC1), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_RDY_CH1_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_RDY_CH1_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_adc_out_csm(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_ADC2), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_OUT_CSM_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_OUT_CSM_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_adc_rdy_csm(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_ADC2), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_RDY_CSM_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_RDY_CSM_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_adc_out_div2(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_ADC3), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_OUT_DIV2_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_OUT_DIV2_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_adc_rdy_div2(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_ADC3), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_RDY_DIV2_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_RDY_DIV2_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_adc_busy_in(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_STA0), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_BUSY_IN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_BUSY_IN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_auxadc_rqst_ch0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_RQST0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_RQST_CH0_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_RQST_CH0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_rqst_ch1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_RQST0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_RQST_CH1_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_RQST_CH1_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_rqst_ch2(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_RQST0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_RQST_CH2_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_RQST_CH2_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_en_csm_sw(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_EN_CSM_SW_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_EN_CSM_SW_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_en_csm_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_EN_CSM_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_EN_CSM_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_test_auxadc(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_TEST_AUXADC_MASK), + (unsigned char) (MT6311_PMIC_RG_TEST_AUXADC_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_ck_aon_gps(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_CK_AON_GPS_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_CK_AON_GPS_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_ck_aon_md(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_CK_AON_MD_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_CK_AON_MD_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_ck_aon(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_CK_AON_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_CK_AON_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_ck_on_extd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_CK_ON_EXTD_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_CK_ON_EXTD_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_spl_num(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_SPL_NUM_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_SPL_NUM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_avg_num_small(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_AVG_NUM_SMALL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_AVG_NUM_SMALL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_avg_num_large(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_AVG_NUM_LARGE_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_AVG_NUM_LARGE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_avg_num_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_AVG_NUM_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_AVG_NUM_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_trim_ch0_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_TRIM_CH0_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_TRIM_CH0_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_trim_ch1_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_TRIM_CH1_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_TRIM_CH1_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_trim_ch2_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_TRIM_CH2_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_TRIM_CH2_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_trim_ch3_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON5), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_TRIM_CH3_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_TRIM_CH3_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_con6_rsv0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_CON6_RSV0_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_CON6_RSV0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_adc_2s_comp_enb(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_ADC_2S_COMP_ENB_MASK), + (unsigned char) (MT6311_PMIC_RG_ADC_2S_COMP_ENB_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_adc_trim_comp(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_ADC_TRIM_COMP_MASK), + (unsigned char) (MT6311_PMIC_RG_ADC_TRIM_COMP_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_out_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_OUT_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_OUT_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_adc_pwdb_swctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_PWDB_SWCTRL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_PWDB_SWCTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_qi_vdvfs1_csm_en_sw(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_QI_VDVFS1_CSM_EN_SW_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_QI_VDVFS1_CSM_EN_SW_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_qi_vdvfs11_csm_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_QI_VDVFS11_CSM_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_QI_VDVFS11_CSM_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_qi_vdvfs12_csm_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON6), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_QI_VDVFS12_CSM_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_QI_VDVFS12_CSM_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_sw_gain_trim(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON7), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_SW_GAIN_TRIM_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_SW_GAIN_TRIM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_sw_offset_trim(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON8), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_SW_OFFSET_TRIM_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_SW_OFFSET_TRIM_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_rng_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_RNG_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_RNG_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_data_reuse_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_DATA_REUSE_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_DATA_REUSE_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_test_mode(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_TEST_MODE_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_TEST_MODE_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_bit_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_BIT_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_BIT_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_start_sw(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_START_SW_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_START_SW_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_start_swctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_START_SWCTRL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_START_SWCTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_adc_pwdb(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON9), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_PWDB_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADC_PWDB_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_ad_auxadc_comp(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_CON10), + (&val), + (unsigned char) (MT6311_PMIC_AD_AUXADC_COMP_MASK), + (unsigned char) (MT6311_PMIC_AD_AUXADC_COMP_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_auxadc_da_dac_swctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON10), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_DA_DAC_SWCTRL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_DA_DAC_SWCTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_da_dac(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON11), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_DA_DAC_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_DA_DAC_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_swctrl_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON12), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_SWCTRL_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_SWCTRL_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_chsel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON12), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_CHSEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_CHSEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_adcin_baton_ted_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON12), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ADCIN_BATON_TED_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADCIN_BATON_TED_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_adcin_chrin_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON13), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ADCIN_CHRIN_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADCIN_CHRIN_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_adcin_batsns_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON13), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ADCIN_BATSNS_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADCIN_BATSNS_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_adcin_cs_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON13), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ADCIN_CS_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ADCIN_CS_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_dac_extd_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_DAC_EXTD_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_DAC_EXTD_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_dac_extd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_DAC_EXTD_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_DAC_EXTD_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_dig1_rsv1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON14), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_DIG1_RSV1_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_DIG1_RSV1_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_dig0_rsv1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON15), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_DIG0_RSV1_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_DIG0_RSV1_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_auxadc_ro_rsv1(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_CON15), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_RO_RSV1_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_RO_RSV1_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_lbat_max_irq(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_CON15), + (&val), + (unsigned char) (MT6311_PMIC_LBAT_MAX_IRQ_MASK), + (unsigned char) (MT6311_PMIC_LBAT_MAX_IRQ_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_lbat_min_irq(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_CON15), + (&val), + (unsigned char) (MT6311_PMIC_LBAT_MIN_IRQ_MASK), + (unsigned char) (MT6311_PMIC_LBAT_MIN_IRQ_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_auxadc_autorpt_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON15), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_AUTORPT_EN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_AUTORPT_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_autorpt_prd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON16), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_AUTORPT_PRD_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_AUTORPT_PRD_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_debt_min(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON17), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DEBT_MIN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DEBT_MIN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_debt_max(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON18), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DEBT_MAX_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DEBT_MAX_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_det_prd_7_0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON19), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DET_PRD_7_0_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DET_PRD_7_0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_det_prd_15_8(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON20), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DET_PRD_15_8_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DET_PRD_15_8_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_det_prd_19_16(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON21), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DET_PRD_19_16_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DET_PRD_19_16_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_auxadc_lbat_max_irq_b(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_CON22), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_MAX_IRQ_B_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_MAX_IRQ_B_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_auxadc_lbat_en_max(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON22), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_EN_MAX_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_EN_MAX_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_irq_en_max(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON22), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_IRQ_EN_MAX_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_IRQ_EN_MAX_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_volt_max_0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON22), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_VOLT_MAX_0_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_VOLT_MAX_0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_volt_max_1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON23), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_VOLT_MAX_1_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_VOLT_MAX_1_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_auxadc_lbat_min_irq_b(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_CON24), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_MIN_IRQ_B_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_MIN_IRQ_B_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_auxadc_lbat_en_min(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON24), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_EN_MIN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_EN_MIN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_irq_en_min(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON24), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_IRQ_EN_MIN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_IRQ_EN_MIN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_volt_min_0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON24), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_VOLT_MIN_0_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_VOLT_MIN_0_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_lbat_volt_min_1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON25), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_VOLT_MIN_1_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_VOLT_MIN_1_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_auxadc_lbat_debounce_count_max(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_CON26), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_auxadc_lbat_debounce_count_min(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_AUXADC_CON27), + (&val), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_auxadc_enpwm1_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON28), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ENPWM1_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ENPWM1_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_enpwm1_sw(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON28), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ENPWM1_SW_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ENPWM1_SW_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_enpwm2_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON28), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ENPWM2_SEL_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ENPWM2_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_auxadc_enpwm2_sw(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_AUXADC_CON28), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_AUXADC_ENPWM2_SW_MASK), + (unsigned char) (MT6311_PMIC_AUXADC_ENPWM2_SW_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_vbiasn_oc_status(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_LDO_CON0), + (&val), + (unsigned char) (MT6311_PMIC_QI_VBIASN_OC_STATUS_MASK), + (unsigned char) (MT6311_PMIC_QI_VBIASN_OC_STATUS_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_vbiasn_on_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_ON_CTRL_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_ON_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_mode_set(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_MODE_SET_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_MODE_SET_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_mode_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_MODE_CTRL_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_MODE_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_stbtd(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_STBTD_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_STBTD_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_vbiasn_mode(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_LDO_CON0), + (&val), + (unsigned char) (MT6311_PMIC_QI_VBIASN_MODE_MASK), + (unsigned char) (MT6311_PMIC_QI_VBIASN_MODE_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_qi_vbiasn_en(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_LDO_CON0), + (&val), + (unsigned char) (MT6311_PMIC_QI_VBIASN_EN_MASK), + (unsigned char) (MT6311_PMIC_QI_VBIASN_EN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_qi_vbiasn_ocfb_en(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_LDO_OCFB0), + (&val), + (unsigned char) (MT6311_PMIC_QI_VBIASN_OCFB_EN_MASK), + (unsigned char) (MT6311_PMIC_QI_VBIASN_OCFB_EN_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_vbiasn_ocfb_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_OCFB0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_OCFB_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_OCFB_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_ldo_degtd_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_OCFB0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_LDO_DEGTD_SEL_MASK), + (unsigned char) (MT6311_PMIC_LDO_DEGTD_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_dis_sel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_DIS_SEL_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_DIS_SEL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_trans_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_TRANS_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_TRANS_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_trans_ctrl(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_TRANS_CTRL_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_TRANS_CTRL_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_rg_vbiasn_trans_once(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_TRANS_ONCE_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_TRANS_ONCE_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_qi_vbiasn_chr(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_LDO_CON2), + (&val), + (unsigned char) (MT6311_PMIC_QI_VBIASN_CHR_MASK), + (unsigned char) (MT6311_PMIC_QI_VBIASN_CHR_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_rg_vbiasn_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON3), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_RG_VBIASN_EN_MASK), + (unsigned char) (MT6311_PMIC_RG_VBIASN_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_ldo_rsv(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_LDO_CON4), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_LDO_RSV_MASK), + (unsigned char) (MT6311_PMIC_LDO_RSV_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_fqmtr_tcksel(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_FQMTR_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_FQMTR_TCKSEL_MASK), + (unsigned char) (MT6311_PMIC_FQMTR_TCKSEL_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_fqmtr_busy(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_FQMTR_CON0), + (&val), + (unsigned char) (MT6311_PMIC_FQMTR_BUSY_MASK), + (unsigned char) (MT6311_PMIC_FQMTR_BUSY_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +void mt6311_set_fqmtr_en(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_FQMTR_CON0), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_FQMTR_EN_MASK), + (unsigned char) (MT6311_PMIC_FQMTR_EN_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_fqmtr_winset_1(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_FQMTR_CON1), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_FQMTR_WINSET_1_MASK), + (unsigned char) (MT6311_PMIC_FQMTR_WINSET_1_SHIFT) + ); + mt6311_unlock(); +} + +void mt6311_set_fqmtr_winset_0(unsigned char val) +{ + unsigned char ret = 0; + + mt6311_lock(); + ret = mt6311_config_interface((unsigned char) (MT6311_FQMTR_CON2), + (unsigned char) (val), + (unsigned char) (MT6311_PMIC_FQMTR_WINSET_0_MASK), + (unsigned char) (MT6311_PMIC_FQMTR_WINSET_0_SHIFT) + ); + mt6311_unlock(); +} + +unsigned char mt6311_get_fqmtr_data_1(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_FQMTR_CON3), + (&val), + (unsigned char) (MT6311_PMIC_FQMTR_DATA_1_MASK), + (unsigned char) (MT6311_PMIC_FQMTR_DATA_1_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +unsigned char mt6311_get_fqmtr_data_0(void) +{ + unsigned char ret = 0; + unsigned char val = 0; + + mt6311_lock(); + ret = mt6311_read_interface((unsigned char) (MT6311_FQMTR_CON4), + (&val), + (unsigned char) (MT6311_PMIC_FQMTR_DATA_0_MASK), + (unsigned char) (MT6311_PMIC_FQMTR_DATA_0_SHIFT) + ); + mt6311_unlock(); + + return val; +} + +/* + * [Internal Function] + */ +void mt6311_dump_register(void) +{ +#if 0 + unsigned char i = 0x0; + unsigned char i_max = 0x2; /*0xD5*/ + + for (i = 0x0; i <= i_max; i++) + pr_debug("[0x%x]=0x%x ", i, mt6311_get_reg_value(i)); +#endif +} + +int get_mt6311_i2c_ch_num(void) +{ + return mt6311_BUSNUM; +} + +unsigned int update_mt6311_chip_id(void) +{ + unsigned int id = 0; + unsigned int id_l = 0; + unsigned int id_r = 0; + + id_l = mt6311_get_cid(); + if (id_l < 0) { + PMICLOG1("[update_mt6311_chip_id] id_l=%d\n", id_l); + return id_l; + } + id_r = mt6311_get_swcid(); + if (id_r < 0) { + PMICLOG1("[update_mt6311_chip_id] id_r=%d\n", id_r); + return id_r; + } + id = ((id_l << 8) | (id_r)); + + g_mt6311_cid = id; + + PMICLOG1("[update_mt6311_chip_id] id_l=0x%x, id_r=0x%x, id=0x%x\n", id_l, id_r, id); + + return id; +} + +unsigned int mt6311_get_chip_id(void) +{ + unsigned int ret = 0; + + if (g_mt6311_cid == 0) { + ret = update_mt6311_chip_id(); + if (ret < 0) { + g_mt6311_hw_exist = 0; + PMICLOG1("[mt6311_get_chip_id] ret=%d hw_exist:%d\n", ret, g_mt6311_hw_exist); + return ret; + } + } + + PMICLOG1("[mt6311_get_chip_id] g_mt6311_cid=0x%x\n", g_mt6311_cid); + + return g_mt6311_cid; +} + +void mt6311_hw_init(void) +{ + unsigned int ret = 0; + + PMICLOG1("[mt6311_hw_init] 20140513, CC Lee\n"); + + /*put init setting from DE/SA*/ + /*ret=mt6311_config_interface(0x04,0x11,0xFF,0); set pin to interrupt, DVT only*/ + + if (mt6311_get_chip_id() >= PMIC6311_E1_CID_CODE) { + PMICLOG1("[mt6311_hw_init] 6311 PMIC Chip = 0x%x\n", mt6311_get_chip_id()); + PMICLOG1("[mt6311_hw_init] 2014-08-13\n"); + + /*put init setting from DE/SA*/ + + ret = mt6311_config_interface(0x4, 0x2, 0x7, 3); /* [5:3]: GPIO1_MODE; CC, initial INT function*/ + ret = mt6311_config_interface(0x1F, 0x0, 0x1, 0); /* [0:0]: VDVFS11_PG_H2L_EN; Ricky*/ + ret = mt6311_config_interface(0x1F, 0x0, 0x1, 1); /* [1:1]: VDVFS12_PG_H2L_EN; Ricky*/ + ret = mt6311_config_interface(0x1F, 0x0, 0x1, 2); /* [2:2]: VBIASN_PG_H2L_EN; Ricky*/ + ret = mt6311_config_interface(0x6A, 0x2, 0x7, 0); + ret = mt6311_config_interface(0x6D, 0x3, 0x3, 5); + /* [6:5]: RG_UVLO_VTHL; Ricky, for K2/D3T UVLO issues_0.2V for PCB drop. 20150306*/ + ret = mt6311_config_interface(0x6E, 0x3, 0x3, 0); + /* [1:0]: RG_UVLO_VTHH; Ricky, for K2/D3T UVLO issues_0.2V for PCB drop. 20150306*/ + ret = mt6311_config_interface(0x8B, 0x1, 0x7F, 0); + /* [6:0]: VDVFS11_SFCHG_RRATE; Johnson, for DVFS slew rate rising=0.67us,20150305*/ + ret = mt6311_config_interface(0x8C, 0x5, 0x7F, 0); + /* [6:0]: VDVFS11_VOSEL_ON; Setting by DVFS owner, 1.15V forD3T init. Johnson, 20150409*/ + ret = mt6311_config_interface(0x94, 0x3, 0x3, 0); + /* [1:0]: VDVFS11_TRANS_TD; Johnson, for DVFS sof change, falling 50us,,20150305 */ + ret = mt6311_config_interface(0x94, 0x1, 0x3, 4); + ret = mt6311_config_interface(0xCF, 0x0, 0x1, 0); + ret = mt6311_config_interface(0x8E, 0x40, 0x7F, 0); + ret = mt6311_config_interface(0x8F, 0x10, 0x7F, 0); + ret = mt6311_config_interface(0x88, 0x0, 0x1, 0); + ret = mt6311_config_interface(0x88, 0x1, 0x1, 1); + ret = mt6311_config_interface(0x93, 0x1, 0x1, 0); + ret = mt6311_config_interface(0x8D, 0x10, 0x7F, 0); + +#if 1 + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x04, mt6311_get_reg_value(0x04)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x15, mt6311_get_reg_value(0x15)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x1F, mt6311_get_reg_value(0x1F)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x6A, mt6311_get_reg_value(0x6A)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x8B, mt6311_get_reg_value(0x8B)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x8C, mt6311_get_reg_value(0x8C)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x94, mt6311_get_reg_value(0x94)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x93, mt6311_get_reg_value(0x93)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0xCF, mt6311_get_reg_value(0xCF)); + PMICLOG1("[mt6311] [0x%x]=0x%x\n", 0x88, mt6311_get_reg_value(0x88)); +#endif + } else { + PMICLOG1("[mt6311_hw_init] Unknown PMIC Chip (0x%x)\n", mt6311_get_chip_id()); + } +} + +unsigned int mt6311_hw_component_detect(void) +{ + unsigned int ret = 0, chip_id = 0; + + ret = update_mt6311_chip_id(); + if (ret < 0) { + g_mt6311_hw_exist = 0; + PMICLOG1("[update_mt6311_chip_id] ret=%d hw_exist:%d\n", ret, g_mt6311_hw_exist); + return ret; + } + + chip_id = mt6311_get_chip_id(); + if (chip_id < 0) { + PMICLOG1("[mt6311_get_chip_id] ret=%d\n", chip_id); + return chip_id; + } + if ((chip_id == PMIC6311_E1_CID_CODE) || + (chip_id == PMIC6311_E2_CID_CODE) || + (chip_id == PMIC6311_E3_CID_CODE) + ){ + g_mt6311_hw_exist = 1; + } else + g_mt6311_hw_exist = 0; + PMICLOG1("[mt6311_hw_component_detect] exist=%d\n", g_mt6311_hw_exist); + return 0; +} + +int is_mt6311_sw_ready(void) +{ + /*PMICLOG1("g_mt6311_driver_ready=%d\n", g_mt6311_driver_ready);*/ + + return g_mt6311_driver_ready; +} + +int is_mt6311_exist(void) +{ + /*PMICLOG1("g_mt6311_hw_exist=%d\n", g_mt6311_hw_exist);*/ + + return g_mt6311_hw_exist; +} + +/* + * mt6311 interrupt + */ +#if 1 + +int g_mt6311_irq = 0; + +#ifdef CUST_EINT_EXT_BUCK_OC_NUM +unsigned int g_eint_pmic_mt6311_num = CUST_EINT_EXT_BUCK_OC_NUM; +#else +unsigned int g_eint_pmic_mt6311_num = 14; /*FPGA:0, phn:14*/ +#endif + +#ifdef CUST_EINT_EXT_BUCK_OC_DEBOUNCE_CN +unsigned int g_cust_eint_mt_pmic_mt6311_debounce_cn = CUST_EINT_EXT_BUCK_OC_DEBOUNCE_CN; +#else +unsigned int g_cust_eint_mt_pmic_mt6311_debounce_cn = 1; +#endif + +#ifdef CUST_EINT_EXT_BUCK_OC_TYPE +unsigned int g_cust_eint_mt_pmic_mt6311_type = CUST_EINT_EXT_BUCK_OC_TYPE; +#else +unsigned int g_cust_eint_mt_pmic_mt6311_type = 4; +#endif + +#ifdef CUST_EINT_EXT_BUCK_OC_DEBOUNCE_EN +unsigned int g_cust_eint_mt_pmic_mt6311_debounce_en = CUST_EINT_EXT_BUCK_OC_DEBOUNCE_EN; +#else +unsigned int g_cust_eint_mt_pmic_mt6311_debounce_en = 1; +#endif + +static DEFINE_MUTEX(pmic_mutex_mt6311); +static struct task_struct *pmic_6311_thread_handle; +struct wake_lock pmicThread_lock_mt6311; + +void wake_up_pmic_mt6311(void) +{ + PMICLOG1("[wake_up_pmic_mt6311]\n"); + wake_up_process(pmic_6311_thread_handle); + wake_lock(&pmicThread_lock_mt6311); +} +EXPORT_SYMBOL(wake_up_pmic_mt6311); + +void mt_pmic_eint_irq_mt6311(void) +{ + PMICLOG1("[mt_pmic_eint_irq_mt6311] receive interrupt\n"); + wake_up_pmic_mt6311(); +} + +void mt6311_int_test(void) +{ + pr_debug("[mt6311_int_test] start\n"); + + mt6311_config_interface(0x20, 0x0F, 0xFF, 0); /* pg dis */ + mt6311_set_rg_auxadc_ck_pdn(0); + mt6311_set_rg_auxadc_1m_ck_pdn(0); + mt6311_config_interface(0xB5, 0xC0, 0xFF, 0); /* cc EN */ + mt6311_config_interface(0xAE, 0x03, 0xFF, 0); /* ADC EN */ + mt6311_config_interface(0xAE, 0x00, 0xFF, 0); /* ADC CLR */ + + mt6311_set_auxadc_lbat_irq_en_max(0); + mt6311_set_auxadc_lbat_irq_en_min(0); + mt6311_set_auxadc_lbat_en_max(0); + mt6311_set_auxadc_lbat_en_min(0); + + mt6311_set_auxadc_lbat_volt_max_1(0); + mt6311_set_auxadc_lbat_volt_max_0(0); + mt6311_set_auxadc_lbat_volt_min_1(0); + mt6311_set_auxadc_lbat_volt_min_0(0); + mt6311_set_auxadc_lbat_det_prd_19_16(0); + mt6311_set_auxadc_lbat_det_prd_15_8(0); + mt6311_set_auxadc_lbat_det_prd_7_0(0x1); + mt6311_set_auxadc_lbat_debt_min(0x1); + mt6311_set_auxadc_lbat_debt_max(0x1); + + mt6311_set_rg_int_pol(0); /* high active */ + mt6311_set_rg_int_en(1); + + mt6311_set_auxadc_lbat_irq_en_max(1); + mt6311_set_auxadc_lbat_irq_en_min(0); + mt6311_set_auxadc_lbat_en_max(1); + mt6311_set_auxadc_lbat_en_min(0); + + pr_debug("[mt6311_int_test] done, wait for interrupt..\n"); +} + +void cust_pmic_interrupt_en_setting_mt6311(void) +{ +#if 1 + mt6311_set_rg_int_pol(0); /* high active */ + mt6311_set_rg_int_en(1); +#endif + +#if 0 + mt6311_int_test(); +#endif +} + +void mt6311_lbat_min_int_handler(void) +{ + /*unsigned int ret=0;*/ + PMICLOG1("[mt6311_lbat_min_int_handler]....\n"); + /*ret=mt6311_config_interface(MT6311_TOP_INT_MON,0x1,0x1,0);*/ +} + +void mt6311_lbat_max_int_handler(void) +{ + /*unsigned int ret=0;*/ + PMICLOG1("[mt6311_lbat_max_int_handler]....\n"); + +#if 0 + mt6311_set_auxadc_lbat_irq_en_max(0); + mt6311_set_auxadc_lbat_irq_en_min(0); + mt6311_set_auxadc_lbat_en_max(0); + mt6311_set_auxadc_lbat_en_min(0); + mt6311_set_rg_int_en(0); +#endif + + /*ret=mt6311_config_interface(MT6311_TOP_INT_MON,0x1,0x1,1);*/ +} + +unsigned int thr_l_int_status = 0; +unsigned int thr_h_int_status = 0; + +void mt6311_clr_thr_l_int_status(void) +{ + thr_l_int_status = 0; + PMICLOG1("[mt6311_clr_thr_l_int_status]....\n"); +} + +void mt6311_clr_thr_h_int_status(void) +{ + thr_h_int_status = 0; + PMICLOG1("[mt6311_clr_thr_h_int_status]....\n"); +} + +unsigned int mt6311_get_thr_l_int_status(void) +{ + PMICLOG1("[mt6311_get_thr_l_int_status]....\n"); + + return thr_l_int_status; +} + +unsigned int mt6311_get_thr_h_int_status(void) +{ + PMICLOG1("[mt6311_get_thr_h_int_status]....\n"); + + return thr_h_int_status; +} + +void mt6311_thr_l_int_handler(void) +{ + /*unsigned int ret=0;*/ + thr_l_int_status = 1; + PMICLOG1("[mt6311_thr_l_int_handler]....\n"); + /*return thr_l_int_status;*/ + + /*ret=mt6311_config_interface(MT6311_TOP_INT_MON,0x1,0x1,2);*/ +} + +void mt6311_thr_h_int_handler(void) +{ + /*unsigned int ret=0;*/ + thr_h_int_status = 1; + PMICLOG1("[mt6311_thr_h_int_handler]....\n"); + /*ret=mt6311_config_interface(MT6311_TOP_INT_MON,0x1,0x1,3);*/ +} + +void mt6311_buck_oc_int_handler(void) +{ + /*unsigned int ret=0;*/ + PMICLOG1("[mt6311_buck_oc_int_handler]....\n"); + /*ret=mt6311_config_interface(MT6311_TOP_INT_MON,0x1,0x1,4);*/ +} + +static void mt6311_int_handler(void) +{ + unsigned int ret = 0; + unsigned char mt6311_int_status_val_0 = 0; + + /*--------------------------------------------------------------------------------*/ + ret = mt6311_read_interface(MT6311_TOP_INT_MON, (&mt6311_int_status_val_0), 0xFF, 0x0); + PMICLOG1("[MT6311_INT] mt6311_int_status_val_0=0x%x\n", mt6311_int_status_val_0); + + if ((((mt6311_int_status_val_0) & (0x01)) >> 0) == 1) + mt6311_lbat_min_int_handler(); + if ((((mt6311_int_status_val_0) & (0x02)) >> 1) == 1) + mt6311_lbat_max_int_handler(); + if ((((mt6311_int_status_val_0) & (0x04)) >> 2) == 1) + mt6311_thr_l_int_handler(); + if ((((mt6311_int_status_val_0) & (0x08)) >> 3) == 1) + mt6311_thr_h_int_handler(); + if ((((mt6311_int_status_val_0) & (0x10)) >> 4) == 1) + mt6311_buck_oc_int_handler(); +} + +static int pmic_thread_kthread_mt6311(void *x) +{ + unsigned int ret = 0; + unsigned char mt6311_int_status_val_0 = 0; + struct sched_param param = {.sched_priority = 98 }; + + sched_setscheduler(current, SCHED_FIFO, ¶m); + set_current_state(TASK_INTERRUPTIBLE); + + PMICLOG1("[MT6311_INT] enter\n"); + + /* Run on a process content */ + while (1) { + mutex_lock(&pmic_mutex_mt6311); + + mt6311_int_handler(); + + cust_pmic_interrupt_en_setting_mt6311(); + + ret = + mt6311_read_interface(MT6311_TOP_INT_MON, (&mt6311_int_status_val_0), 0xFF, + 0x0); + + PMICLOG1("[MT6311_INT] after ,mt6311_int_status_val_0=0x%x\n", + mt6311_int_status_val_0); + + mdelay(1); + + mutex_unlock(&pmic_mutex_mt6311); + wake_unlock(&pmicThread_lock_mt6311); + + set_current_state(TASK_INTERRUPTIBLE); + + /* mt_eint_unmask(g_eint_pmic_mt6311_num);*/ + if (g_mt6311_irq != 0) + enable_irq(g_mt6311_irq); + + schedule(); + } + + return 0; +} + +irqreturn_t mt6311_eint_handler(int irq, void *desc) +{ + mt_pmic_eint_irq_mt6311(); + + disable_irq_nosync(irq); + return IRQ_HANDLED; +} + +void mt6311_eint_setting(void) +{ + /*ON/OFF interrupt*/ + int ret; + + cust_pmic_interrupt_en_setting_mt6311(); + +#if 1 + g_mt6311_irq = mt_gpio_to_irq(g_eint_pmic_mt6311_num); + + mt_gpio_set_debounce(g_eint_pmic_mt6311_num, g_cust_eint_mt_pmic_mt6311_debounce_cn); + + ret = request_irq(g_mt6311_irq, mt6311_eint_handler, g_cust_eint_mt_pmic_mt6311_type, "mt6311-eint", NULL); + if (ret) + PMICLOG1("[CUST_EINT] Fail to register an irq=%d , err=%d\n", g_mt6311_irq, ret); + + PMICLOG1("[CUST_EINT] CUST_EINT_MT_PMIC_MT6311_NUM=%d\n", g_eint_pmic_mt6311_num); + PMICLOG1("[CUST_EINT] CUST_EINT_PMIC_DEBOUNCE_CN=%d\n", + g_cust_eint_mt_pmic_mt6311_debounce_cn); + PMICLOG1("[CUST_EINT] CUST_EINT_PMIC_TYPE=%d\n", g_cust_eint_mt_pmic_mt6311_type); + PMICLOG1("[CUST_EINT] CUST_EINT_PMIC_DEBOUNCE_EN=%d\n", + g_cust_eint_mt_pmic_mt6311_debounce_en); +#else + mt_eint_set_hw_debounce(g_eint_pmic_mt6311_num, g_cust_eint_mt_pmic_mt6311_debounce_cn); + + mt_eint_registration(g_eint_pmic_mt6311_num, g_cust_eint_mt_pmic_mt6311_type, + mt_pmic_eint_irq_mt6311, 0); + + mt_eint_unmask(g_eint_pmic_mt6311_num); + + PMICLOG1("[CUST_EINT] CUST_EINT_MT_PMIC_MT6311_NUM=%d\n", g_eint_pmic_mt6311_num); + PMICLOG1("[CUST_EINT] CUST_EINT_PMIC_DEBOUNCE_CN=%d\n", + g_cust_eint_mt_pmic_mt6311_debounce_cn); + PMICLOG1("[CUST_EINT] CUST_EINT_PMIC_TYPE=%d\n", g_cust_eint_mt_pmic_mt6311_type); + PMICLOG1("[CUST_EINT] CUST_EINT_PMIC_DEBOUNCE_EN=%d\n", + g_cust_eint_mt_pmic_mt6311_debounce_en); +#endif + + /*for all interrupt events, turn on interrupt module clock*/ +#if 0 + /*mt6311_set_rg_intrp_ck_pdn(0);*/ /* not used in mt6311 */ +#else + mt6311_set_rg_int_pol(0); /* high active*/ + mt6311_set_rg_int_en(1); +#endif +} + +void mt6311_eint_init(void) +{ + /*---------------------*/ +#if defined(CONFIG_MTK_FPGA) + PMICLOG1("[MT6311_EINT] disable when CONFIG_MTK_FPGA\n"); +#else + /*PMIC Interrupt Service*/ + pmic_6311_thread_handle = + kthread_create(pmic_thread_kthread_mt6311, (void *)NULL, "pmic_6311_thread"); + if (IS_ERR(pmic_6311_thread_handle)) { + pmic_6311_thread_handle = NULL; + PMICLOG1("[MT6311_EINT] creation fails\n"); + } else { + wake_up_process(pmic_6311_thread_handle); + PMICLOG1("[MT6311_EINT] kthread_create Done\n"); + } + + /*mt6311_eint_setting();*/ + PMICLOG1("[MT6311_EINT] TBD\n"); +#endif + +} + +#endif /* EINT */ + +/* + * mt6311 probe + */ + +static int mt6311_driver_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int err = 0; + unsigned int ret = 0; + + PMICLOG1("[mt6311_driver_probe]\n"); + + new_client = client; + + /*--------------------- */ + /* force change GPIO to SDA/SCA mode */ + + ret = mt6311_hw_component_detect(); + if (ret < 0) { + err = -ENOMEM; + goto exit; + } + if (g_mt6311_hw_exist == 1) { + mt6311_hw_init(); + mt6311_dump_register(); + + mt6311_eint_init(); + + } + g_mt6311_driver_ready = 1; + + PMICLOG1("[mt6311_driver_probe] g_mt6311_hw_exist=%d, g_mt6311_driver_ready=%d\n", + g_mt6311_hw_exist, g_mt6311_driver_ready); + + PMIC_INIT_SETTING_V1(); + + if (g_mt6311_hw_exist == 0) { +#ifdef BATTERY_OC_PROTECT + /*re-init battery oc protect point for platform without extbuck*/ + battery_oc_protect_reinit(); +#endif + PMICLOG1("[mt6311_driver_probe] return err\n"); + return err; + } + + return 0; + +exit: + PMICLOG1("[mt6311_driver_probe] exit: return err\n"); + PMIC_INIT_SETTING_V1(); + return err; +} + +/* + * [platform_driver API] + */ +#ifdef mt6311_AUTO_DETECT_DISABLE + /* TBD */ +#else +/* + * mt6311_access + */ +unsigned char g_reg_value_mt6311 = 0; +static ssize_t show_mt6311_access(struct device *dev, struct device_attribute *attr, char *buf) +{ + PMICLOG1("[show_mt6311_access] 0x%x\n", g_reg_value_mt6311); + return sprintf(buf, "%u\n", g_reg_value_mt6311); +} + +static ssize_t store_mt6311_access(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + char *pvalue = NULL, *addr, *val; + unsigned int reg_value = 0; + unsigned int reg_address = 0; + + pr_err("[store_mt6311_access]\n"); + + if (buf != NULL && size != 0) { + /*PMICLOG1("[store_mt6311_access] buf is %s and size is %d\n",buf,size);*/ + /*reg_address = simple_strtoul(buf, &pvalue, 16);*/ + + pvalue = (char *)buf; + if (size > 5) { + addr = strsep(&pvalue, " "); + ret = kstrtou32(addr, 16, (unsigned int *)®_address); + } else + ret = kstrtou32(pvalue, 16, (unsigned int *)®_address); + /*ret = kstrtoul(buf, 16, (unsigned long *)®_address);*/ + + if (size > 5) { + /*reg_value = simple_strtoul((pvalue + 1), NULL, 16);*/ + val = strsep(&pvalue, " "); + ret = kstrtou32(val, 16, (unsigned int *)®_value); + pr_err("[store_mt6311_access] write mt6311 reg 0x%x with value 0x%x !\n", + reg_address, reg_value); + + ret = mt6311_config_interface(reg_address, reg_value, 0xFF, 0x0); + } else { + ret = mt6311_read_interface(reg_address, &g_reg_value_mt6311, 0xFF, 0x0); + + pr_err("[store_mt6311_access] read mt6311 reg 0x%x with value 0x%x !\n", + reg_address, g_reg_value_mt6311); + pr_err + ("[store_mt6311_access] use \"cat mt6311_access\" to get value(decimal)\r\n"); + } + } + return size; +} + +static DEVICE_ATTR(mt6311_access, 0664, show_mt6311_access, store_mt6311_access); /*664*/ + +/* + * mt6311_vosel_pin + */ +int g_mt6311_vosel_pin = 0; +static ssize_t show_mt6311_vosel_pin(struct device *dev, struct device_attribute *attr, char *buf) +{ + pr_err("[show_mt6311_vosel_pin] g_mt6311_vosel_pin=%d\n", g_mt6311_vosel_pin); + return sprintf(buf, "%u\n", g_mt6311_vosel_pin); +} + +static ssize_t store_mt6311_vosel_pin(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int val = 0, ret; + char *pvalue = NULL; + + pr_err("[store_mt6311_vosel_pin]\n"); + + /*val = simple_strtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + + g_mt6311_vosel_pin = val; + + pr_err("[store_mt6311_vosel_pin] g_mt6311_vosel_pin(%d)\n", g_mt6311_vosel_pin); + + return size; +} + +static DEVICE_ATTR(mt6311_vosel_pin, 0664, show_mt6311_vosel_pin, store_mt6311_vosel_pin); /*664*/ + +/* + * mt6311_user_space_probe + */ +static int mt6311_user_space_probe(struct platform_device *dev) +{ + int ret_device_file = 0; + + PMICLOG1("******** mt6311_user_space_probe!! ********\n"); + + ret_device_file = device_create_file(&(dev->dev), &dev_attr_mt6311_access); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_mt6311_vosel_pin); + + return 0; +} + +struct platform_device mt6311_user_space_device = { + .name = "mt6311-user", + .id = -1, +}; + +static struct platform_driver mt6311_user_space_driver = { + .probe = mt6311_user_space_probe, + .driver = { + .name = "mt6311-user", + }, +}; + +/*static struct i2c_board_info i2c_mt6311 __initdata = +{ I2C_BOARD_INFO("mt6311", (mt6311_SLAVE_ADDR_WRITE >> 1)) };*/ /* auto add by dts */ + +#endif + +static int __init mt6311_init(void) +{ +#ifdef mt6311_AUTO_DETECT_DISABLE + + PMICLOG1("[mt6311_init] mt6311_AUTO_DETECT_DISABLE\n"); + g_mt6311_hw_exist = 0; + g_mt6311_driver_ready = 1; + +#else + + int ret = 0; + + wake_lock_init(&pmicThread_lock_mt6311, WAKE_LOCK_SUSPEND, + "pmicThread_lock_mt6311 wakelock"); + { + PMICLOG1("[mt6311_init] init start. ch=%d!!\n", mt6311_BUSNUM); + + /*i2c_register_board_info(mt6311_BUSNUM, &i2c_mt6311, 1);*/ + + if (i2c_add_driver(&mt6311_driver) != 0) + PMICLOG1("[mt6311_init] failed to register mt6311 i2c driver.\n"); + else + PMICLOG1("[mt6311_init] Success to register mt6311 i2c driver.\n"); + + /* mt6311 user space access interface*/ + ret = platform_device_register(&mt6311_user_space_device); + if (ret) { + PMICLOG1("****[mt6311_init] Unable to device register(%d)\n", ret); + return ret; + } + ret = platform_driver_register(&mt6311_user_space_driver); + if (ret) { + PMICLOG1("****[mt6311_init] Unable to register driver (%d)\n", ret); + return ret; + } + } +#endif + + return 0; +} + +static void __exit mt6311_exit(void) +{ + i2c_del_driver(&mt6311_driver); +} +module_init(mt6311_init); +module_exit(mt6311_exit); + +MODULE_AUTHOR("Argus Lin"); +MODULE_DESCRIPTION("MT PMIC Device Driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/mediatek/power/mt6755/mt6311.h b/drivers/misc/mediatek/power/mt6755/mt6311.h new file mode 100644 index 0000000000000000000000000000000000000000..aaa27cba873dede1b1c40553e141a742316b691a --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/mt6311.h @@ -0,0 +1,1723 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** +* +* Filename: +* --------- +* mt6311.h +* +* Project: +* -------- +* Android +* +* Description: +* ------------ +* mt6311 header file +* +* Author: +* ------- +* +****************************************************************************/ + +#ifndef _mt6311_SW_H_ +#define _mt6311_SW_H_ + +#define PMIC6311_E1_CID_CODE 0x0110 +#define PMIC6311_E2_CID_CODE 0x0120 +#define PMIC6311_E3_CID_CODE 0x0130 + + +/* Basic */ +extern void mt6311_dump_register(void); +extern unsigned int mt6311_read_interface(unsigned char RegNum, + unsigned char *val, + unsigned char MASK, + unsigned char SHIFT); +extern unsigned int mt6311_config_interface(unsigned char RegNum, + unsigned char val, + unsigned char MASK, + unsigned char SHIFT); + +/*---------------------- AUTO GEN ---------------------------*/ + +/* Define */ +#define PMIC_REG_BASE (0x00000000) + +#define MT6311_CID ((unsigned int)(PMIC_REG_BASE+0x00)) +#define MT6311_SWCID ((unsigned int)(PMIC_REG_BASE+0x01)) +#define MT6311_HWCID ((unsigned int)(PMIC_REG_BASE+0x02)) +#define MT6311_GPIO_CFG ((unsigned int)(PMIC_REG_BASE+0x03)) +#define MT6311_GPIO_MODE ((unsigned int)(PMIC_REG_BASE+0x04)) +#define MT6311_TEST_OUT ((unsigned int)(PMIC_REG_BASE+0x05)) +#define MT6311_TEST_CON0 ((unsigned int)(PMIC_REG_BASE+0x06)) +#define MT6311_TEST_CON1 ((unsigned int)(PMIC_REG_BASE+0x07)) +#define MT6311_TEST_CON2 ((unsigned int)(PMIC_REG_BASE+0x08)) +#define MT6311_TEST_CON3 ((unsigned int)(PMIC_REG_BASE+0x09)) +#define MT6311_TOP_CON ((unsigned int)(PMIC_REG_BASE+0x0A)) +#define MT6311_TOP_CKTST_CON ((unsigned int)(PMIC_REG_BASE+0x0B)) +#define MT6311_TOP_CKPDN_CON1 ((unsigned int)(PMIC_REG_BASE+0x0C)) +#define MT6311_TOP_CKPDN_CON1_SET ((unsigned int)(PMIC_REG_BASE+0x0D)) +#define MT6311_TOP_CKPDN_CON1_CLR ((unsigned int)(PMIC_REG_BASE+0x0E)) +#define MT6311_TOP_CKPDN_CON2 ((unsigned int)(PMIC_REG_BASE+0x0F)) +#define MT6311_TOP_CKPDN_CON2_SET ((unsigned int)(PMIC_REG_BASE+0x10)) +#define MT6311_TOP_CKPDN_CON2_CLR ((unsigned int)(PMIC_REG_BASE+0x11)) +#define MT6311_TOP_CKHWEN_CON ((unsigned int)(PMIC_REG_BASE+0x12)) +#define MT6311_TOP_CKHWEN_CON_SET ((unsigned int)(PMIC_REG_BASE+0x13)) +#define MT6311_TOP_CKHWEN_CON_CLR ((unsigned int)(PMIC_REG_BASE+0x14)) +#define MT6311_TOP_RST_CON ((unsigned int)(PMIC_REG_BASE+0x15)) +#define MT6311_TOP_RST_CON_SET ((unsigned int)(PMIC_REG_BASE+0x16)) +#define MT6311_TOP_RST_CON_CLR ((unsigned int)(PMIC_REG_BASE+0x17)) +#define MT6311_TOP_INT_CON ((unsigned int)(PMIC_REG_BASE+0x18)) +#define MT6311_TOP_INT_MON ((unsigned int)(PMIC_REG_BASE+0x19)) +#define MT6311_STRUP_CON0 ((unsigned int)(PMIC_REG_BASE+0x1A)) +#define MT6311_STRUP_CON1 ((unsigned int)(PMIC_REG_BASE+0x1B)) +#define MT6311_STRUP_CON2 ((unsigned int)(PMIC_REG_BASE+0x1C)) +#define MT6311_STRUP_CON3 ((unsigned int)(PMIC_REG_BASE+0x1D)) +#define MT6311_STRUP_CON4 ((unsigned int)(PMIC_REG_BASE+0x1E)) +#define MT6311_STRUP_CON5 ((unsigned int)(PMIC_REG_BASE+0x1F)) +#define MT6311_STRUP_CON6 ((unsigned int)(PMIC_REG_BASE+0x20)) +#define MT6311_STRUP_CON7 ((unsigned int)(PMIC_REG_BASE+0x21)) +#define MT6311_STRUP_CON8 ((unsigned int)(PMIC_REG_BASE+0x22)) +#define MT6311_STRUP_CON9 ((unsigned int)(PMIC_REG_BASE+0x23)) +#define MT6311_STRUP_CON10 ((unsigned int)(PMIC_REG_BASE+0x24)) +#define MT6311_STRUP_CON11 ((unsigned int)(PMIC_REG_BASE+0x25)) +#define MT6311_STRUP_CON12 ((unsigned int)(PMIC_REG_BASE+0x26)) +#define MT6311_STRUP_CON13 ((unsigned int)(PMIC_REG_BASE+0x27)) +#define MT6311_STRUP_CON14 ((unsigned int)(PMIC_REG_BASE+0x28)) +#define MT6311_TOP_CLK_TRIM0 ((unsigned int)(PMIC_REG_BASE+0x29)) +#define MT6311_TOP_CLK_TRIM1 ((unsigned int)(PMIC_REG_BASE+0x2A)) +#define MT6311_EFUSE_CON0 ((unsigned int)(PMIC_REG_BASE+0x2B)) +#define MT6311_EFUSE_CON1 ((unsigned int)(PMIC_REG_BASE+0x2C)) +#define MT6311_EFUSE_CON2 ((unsigned int)(PMIC_REG_BASE+0x2D)) +#define MT6311_EFUSE_CON3 ((unsigned int)(PMIC_REG_BASE+0x2E)) +#define MT6311_EFUSE_CON4 ((unsigned int)(PMIC_REG_BASE+0x2F)) +#define MT6311_EFUSE_CON5 ((unsigned int)(PMIC_REG_BASE+0x30)) +#define MT6311_EFUSE_CON6 ((unsigned int)(PMIC_REG_BASE+0x31)) +#define MT6311_EFUSE_CON7 ((unsigned int)(PMIC_REG_BASE+0x32)) +#define MT6311_EFUSE_CON8 ((unsigned int)(PMIC_REG_BASE+0x33)) +#define MT6311_EFUSE_CON9 ((unsigned int)(PMIC_REG_BASE+0x34)) +#define MT6311_EFUSE_CON10 ((unsigned int)(PMIC_REG_BASE+0x35)) +#define MT6311_EFUSE_CON11 ((unsigned int)(PMIC_REG_BASE+0x36)) +#define MT6311_EFUSE_CON12 ((unsigned int)(PMIC_REG_BASE+0x37)) +#define MT6311_EFUSE_CON13 ((unsigned int)(PMIC_REG_BASE+0x38)) +#define MT6311_EFUSE_DOUT_0_7 ((unsigned int)(PMIC_REG_BASE+0x39)) +#define MT6311_EFUSE_DOUT_8_15 ((unsigned int)(PMIC_REG_BASE+0x3A)) +#define MT6311_EFUSE_DOUT_16_23 ((unsigned int)(PMIC_REG_BASE+0x3B)) +#define MT6311_EFUSE_DOUT_24_31 ((unsigned int)(PMIC_REG_BASE+0x3C)) +#define MT6311_EFUSE_DOUT_32_39 ((unsigned int)(PMIC_REG_BASE+0x3D)) +#define MT6311_EFUSE_DOUT_40_47 ((unsigned int)(PMIC_REG_BASE+0x3E)) +#define MT6311_EFUSE_DOUT_48_55 ((unsigned int)(PMIC_REG_BASE+0x3F)) +#define MT6311_EFUSE_DOUT_56_63 ((unsigned int)(PMIC_REG_BASE+0x40)) +#define MT6311_EFUSE_DOUT_64_71 ((unsigned int)(PMIC_REG_BASE+0x41)) +#define MT6311_EFUSE_DOUT_72_79 ((unsigned int)(PMIC_REG_BASE+0x42)) +#define MT6311_EFUSE_DOUT_80_87 ((unsigned int)(PMIC_REG_BASE+0x43)) +#define MT6311_EFUSE_DOUT_88_95 ((unsigned int)(PMIC_REG_BASE+0x44)) +#define MT6311_EFUSE_DOUT_96_103 ((unsigned int)(PMIC_REG_BASE+0x45)) +#define MT6311_EFUSE_DOUT_104_111 ((unsigned int)(PMIC_REG_BASE+0x46)) +#define MT6311_EFUSE_DOUT_112_119 ((unsigned int)(PMIC_REG_BASE+0x47)) +#define MT6311_EFUSE_DOUT_120_127 ((unsigned int)(PMIC_REG_BASE+0x48)) +#define MT6311_EFUSE_VAL_0_7 ((unsigned int)(PMIC_REG_BASE+0x49)) +#define MT6311_EFUSE_VAL_8_15 ((unsigned int)(PMIC_REG_BASE+0x4A)) +#define MT6311_EFUSE_VAL_16_23 ((unsigned int)(PMIC_REG_BASE+0x4B)) +#define MT6311_EFUSE_VAL_24_31 ((unsigned int)(PMIC_REG_BASE+0x4C)) +#define MT6311_EFUSE_VAL_32_39 ((unsigned int)(PMIC_REG_BASE+0x4D)) +#define MT6311_EFUSE_VAL_40_47 ((unsigned int)(PMIC_REG_BASE+0x4E)) +#define MT6311_EFUSE_VAL_48_55 ((unsigned int)(PMIC_REG_BASE+0x4F)) +#define MT6311_EFUSE_VAL_56_63 ((unsigned int)(PMIC_REG_BASE+0x50)) +#define MT6311_EFUSE_VAL_64_71 ((unsigned int)(PMIC_REG_BASE+0x51)) +#define MT6311_EFUSE_VAL_72_79 ((unsigned int)(PMIC_REG_BASE+0x52)) +#define MT6311_EFUSE_VAL_80_87 ((unsigned int)(PMIC_REG_BASE+0x53)) +#define MT6311_EFUSE_VAL_88_95 ((unsigned int)(PMIC_REG_BASE+0x54)) +#define MT6311_EFUSE_VAL_96_103 ((unsigned int)(PMIC_REG_BASE+0x55)) +#define MT6311_EFUSE_VAL_104_111 ((unsigned int)(PMIC_REG_BASE+0x56)) +#define MT6311_EFUSE_VAL_112_119 ((unsigned int)(PMIC_REG_BASE+0x57)) +#define MT6311_EFUSE_VAL_120_127 ((unsigned int)(PMIC_REG_BASE+0x58)) +#define MT6311_BUCK_ALL_CON0 ((unsigned int)(PMIC_REG_BASE+0x59)) +#define MT6311_BUCK_ALL_CON1 ((unsigned int)(PMIC_REG_BASE+0x5A)) +#define MT6311_BUCK_ALL_CON2 ((unsigned int)(PMIC_REG_BASE+0x5B)) +#define MT6311_BUCK_ALL_CON3 ((unsigned int)(PMIC_REG_BASE+0x5C)) +#define MT6311_BUCK_ALL_CON4 ((unsigned int)(PMIC_REG_BASE+0x5D)) +#define MT6311_BUCK_ALL_CON5 ((unsigned int)(PMIC_REG_BASE+0x5E)) +#define MT6311_BUCK_ALL_CON6 ((unsigned int)(PMIC_REG_BASE+0x5F)) +#define MT6311_BUCK_ALL_CON7 ((unsigned int)(PMIC_REG_BASE+0x60)) +#define MT6311_BUCK_ALL_CON8 ((unsigned int)(PMIC_REG_BASE+0x61)) +#define MT6311_BUCK_ALL_CON9 ((unsigned int)(PMIC_REG_BASE+0x62)) +#define MT6311_BUCK_ALL_CON10 ((unsigned int)(PMIC_REG_BASE+0x63)) +#define MT6311_BUCK_ALL_CON18 ((unsigned int)(PMIC_REG_BASE+0x64)) +#define MT6311_BUCK_ALL_CON19 ((unsigned int)(PMIC_REG_BASE+0x65)) +#define MT6311_BUCK_ALL_CON20 ((unsigned int)(PMIC_REG_BASE+0x66)) +#define MT6311_BUCK_ALL_CON21 ((unsigned int)(PMIC_REG_BASE+0x67)) +#define MT6311_BUCK_ALL_CON22 ((unsigned int)(PMIC_REG_BASE+0x68)) +#define MT6311_BUCK_ALL_CON23 ((unsigned int)(PMIC_REG_BASE+0x69)) +#define MT6311_BUCK_ALL_CON24 ((unsigned int)(PMIC_REG_BASE+0x6A)) +#define MT6311_ANA_RSV_CON0 ((unsigned int)(PMIC_REG_BASE+0x6B)) +#define MT6311_STRUP_ANA_CON0 ((unsigned int)(PMIC_REG_BASE+0x6C)) +#define MT6311_STRUP_ANA_CON1 ((unsigned int)(PMIC_REG_BASE+0x6D)) +#define MT6311_STRUP_ANA_CON2 ((unsigned int)(PMIC_REG_BASE+0x6E)) +#define MT6311_STRUP_ANA_CON3 ((unsigned int)(PMIC_REG_BASE+0x6F)) +#define MT6311_STRUP_ANA_CON4 ((unsigned int)(PMIC_REG_BASE+0x70)) +#define MT6311_STRUP_ANA_CON5 ((unsigned int)(PMIC_REG_BASE+0x71)) +#define MT6311_STRUP_ANA_CON6 ((unsigned int)(PMIC_REG_BASE+0x72)) +#define MT6311_STRUP_ANA_CON7 ((unsigned int)(PMIC_REG_BASE+0x73)) +#define MT6311_STRUP_ANA_CON8 ((unsigned int)(PMIC_REG_BASE+0x74)) +#define MT6311_STRUP_ANA_CON9 ((unsigned int)(PMIC_REG_BASE+0x75)) +#define MT6311_STRUP_ANA_CON10 ((unsigned int)(PMIC_REG_BASE+0x76)) +#define MT6311_STRUP_ANA_CON11 ((unsigned int)(PMIC_REG_BASE+0x77)) +#define MT6311_STRUP_ANA_CON12 ((unsigned int)(PMIC_REG_BASE+0x78)) +#define MT6311_VBIASN_ANA_CON0 ((unsigned int)(PMIC_REG_BASE+0x79)) +#define MT6311_VDVFS1_ANA_CON0 ((unsigned int)(PMIC_REG_BASE+0x7A)) +#define MT6311_VDVFS1_ANA_CON1 ((unsigned int)(PMIC_REG_BASE+0x7B)) +#define MT6311_VDVFS1_ANA_CON2 ((unsigned int)(PMIC_REG_BASE+0x7C)) +#define MT6311_VDVFS1_ANA_CON3 ((unsigned int)(PMIC_REG_BASE+0x7D)) +#define MT6311_VDVFS1_ANA_CON4 ((unsigned int)(PMIC_REG_BASE+0x7E)) +#define MT6311_VDVFS1_ANA_CON5 ((unsigned int)(PMIC_REG_BASE+0x7F)) +#define MT6311_VDVFS1_ANA_CON6 ((unsigned int)(PMIC_REG_BASE+0x80)) +#define MT6311_VDVFS1_ANA_CON7 ((unsigned int)(PMIC_REG_BASE+0x81)) +#define MT6311_VDVFS1_ANA_CON8 ((unsigned int)(PMIC_REG_BASE+0x82)) +#define MT6311_VDVFS1_ANA_CON9 ((unsigned int)(PMIC_REG_BASE+0x83)) +#define MT6311_VDVFS1_ANA_CON10 ((unsigned int)(PMIC_REG_BASE+0x84)) +#define MT6311_VDVFS1_ANA_CON11 ((unsigned int)(PMIC_REG_BASE+0x85)) +#define MT6311_VDVFS1_ANA_CON12 ((unsigned int)(PMIC_REG_BASE+0x86)) +#define MT6311_VDVFS11_CON0 ((unsigned int)(PMIC_REG_BASE+0x87)) +#define MT6311_VDVFS11_CON7 ((unsigned int)(PMIC_REG_BASE+0x88)) +#define MT6311_VDVFS11_CON8 ((unsigned int)(PMIC_REG_BASE+0x89)) +#define MT6311_VDVFS11_CON9 ((unsigned int)(PMIC_REG_BASE+0x8A)) +#define MT6311_VDVFS11_CON10 ((unsigned int)(PMIC_REG_BASE+0x8B)) +#define MT6311_VDVFS11_CON11 ((unsigned int)(PMIC_REG_BASE+0x8C)) +#define MT6311_VDVFS11_CON12 ((unsigned int)(PMIC_REG_BASE+0x8D)) +#define MT6311_VDVFS11_CON13 ((unsigned int)(PMIC_REG_BASE+0x8E)) +#define MT6311_VDVFS11_CON14 ((unsigned int)(PMIC_REG_BASE+0x8F)) +#define MT6311_VDVFS11_CON15 ((unsigned int)(PMIC_REG_BASE+0x90)) +#define MT6311_VDVFS11_CON16 ((unsigned int)(PMIC_REG_BASE+0x91)) +#define MT6311_VDVFS11_CON17 ((unsigned int)(PMIC_REG_BASE+0x92)) +#define MT6311_VDVFS11_CON18 ((unsigned int)(PMIC_REG_BASE+0x93)) +#define MT6311_VDVFS11_CON19 ((unsigned int)(PMIC_REG_BASE+0x94)) +#define MT6311_VDVFS12_CON0 ((unsigned int)(PMIC_REG_BASE+0x95)) +#define MT6311_VDVFS12_CON7 ((unsigned int)(PMIC_REG_BASE+0x96)) +#define MT6311_VDVFS12_CON8 ((unsigned int)(PMIC_REG_BASE+0x97)) +#define MT6311_VDVFS12_CON9 ((unsigned int)(PMIC_REG_BASE+0x98)) +#define MT6311_VDVFS12_CON10 ((unsigned int)(PMIC_REG_BASE+0x99)) +#define MT6311_VDVFS12_CON11 ((unsigned int)(PMIC_REG_BASE+0x9A)) +#define MT6311_VDVFS12_CON12 ((unsigned int)(PMIC_REG_BASE+0x9B)) +#define MT6311_VDVFS12_CON13 ((unsigned int)(PMIC_REG_BASE+0x9C)) +#define MT6311_VDVFS12_CON14 ((unsigned int)(PMIC_REG_BASE+0x9D)) +#define MT6311_VDVFS12_CON15 ((unsigned int)(PMIC_REG_BASE+0x9E)) +#define MT6311_VDVFS12_CON16 ((unsigned int)(PMIC_REG_BASE+0x9F)) +#define MT6311_VDVFS12_CON17 ((unsigned int)(PMIC_REG_BASE+0xA0)) +#define MT6311_VDVFS12_CON18 ((unsigned int)(PMIC_REG_BASE+0xA1)) +#define MT6311_VDVFS12_CON19 ((unsigned int)(PMIC_REG_BASE+0xA2)) +#define MT6311_BUCK_K_CON0 ((unsigned int)(PMIC_REG_BASE+0xA3)) +#define MT6311_BUCK_K_CON1 ((unsigned int)(PMIC_REG_BASE+0xA4)) +#define MT6311_BUCK_K_CON2 ((unsigned int)(PMIC_REG_BASE+0xA5)) +#define MT6311_BUCK_K_CON3 ((unsigned int)(PMIC_REG_BASE+0xA6)) +#define MT6311_BUCK_K_CON4 ((unsigned int)(PMIC_REG_BASE+0xA7)) +#define MT6311_BUCK_K_CON5 ((unsigned int)(PMIC_REG_BASE+0xA8)) +#define MT6311_AUXADC_ADC0 ((unsigned int)(PMIC_REG_BASE+0xA9)) +#define MT6311_AUXADC_ADC1 ((unsigned int)(PMIC_REG_BASE+0xAA)) +#define MT6311_AUXADC_ADC2 ((unsigned int)(PMIC_REG_BASE+0xAB)) +#define MT6311_AUXADC_ADC3 ((unsigned int)(PMIC_REG_BASE+0xAC)) +#define MT6311_AUXADC_STA0 ((unsigned int)(PMIC_REG_BASE+0xAD)) +#define MT6311_AUXADC_RQST0 ((unsigned int)(PMIC_REG_BASE+0xAE)) +#define MT6311_AUXADC_CON0 ((unsigned int)(PMIC_REG_BASE+0xAF)) +#define MT6311_AUXADC_CON1 ((unsigned int)(PMIC_REG_BASE+0xB0)) +#define MT6311_AUXADC_CON2 ((unsigned int)(PMIC_REG_BASE+0xB1)) +#define MT6311_AUXADC_CON3 ((unsigned int)(PMIC_REG_BASE+0xB2)) +#define MT6311_AUXADC_CON4 ((unsigned int)(PMIC_REG_BASE+0xB3)) +#define MT6311_AUXADC_CON5 ((unsigned int)(PMIC_REG_BASE+0xB4)) +#define MT6311_AUXADC_CON6 ((unsigned int)(PMIC_REG_BASE+0xB5)) +#define MT6311_AUXADC_CON7 ((unsigned int)(PMIC_REG_BASE+0xB6)) +#define MT6311_AUXADC_CON8 ((unsigned int)(PMIC_REG_BASE+0xB7)) +#define MT6311_AUXADC_CON9 ((unsigned int)(PMIC_REG_BASE+0xB8)) +#define MT6311_AUXADC_CON10 ((unsigned int)(PMIC_REG_BASE+0xB9)) +#define MT6311_AUXADC_CON11 ((unsigned int)(PMIC_REG_BASE+0xBA)) +#define MT6311_AUXADC_CON12 ((unsigned int)(PMIC_REG_BASE+0xBB)) +#define MT6311_AUXADC_CON13 ((unsigned int)(PMIC_REG_BASE+0xBC)) +#define MT6311_AUXADC_CON14 ((unsigned int)(PMIC_REG_BASE+0xBD)) +#define MT6311_AUXADC_CON15 ((unsigned int)(PMIC_REG_BASE+0xBE)) +#define MT6311_AUXADC_CON16 ((unsigned int)(PMIC_REG_BASE+0xBF)) +#define MT6311_AUXADC_CON17 ((unsigned int)(PMIC_REG_BASE+0xC0)) +#define MT6311_AUXADC_CON18 ((unsigned int)(PMIC_REG_BASE+0xC1)) +#define MT6311_AUXADC_CON19 ((unsigned int)(PMIC_REG_BASE+0xC2)) +#define MT6311_AUXADC_CON20 ((unsigned int)(PMIC_REG_BASE+0xC3)) +#define MT6311_AUXADC_CON21 ((unsigned int)(PMIC_REG_BASE+0xC4)) +#define MT6311_AUXADC_CON22 ((unsigned int)(PMIC_REG_BASE+0xC5)) +#define MT6311_AUXADC_CON23 ((unsigned int)(PMIC_REG_BASE+0xC6)) +#define MT6311_AUXADC_CON24 ((unsigned int)(PMIC_REG_BASE+0xC7)) +#define MT6311_AUXADC_CON25 ((unsigned int)(PMIC_REG_BASE+0xC8)) +#define MT6311_AUXADC_CON26 ((unsigned int)(PMIC_REG_BASE+0xC9)) +#define MT6311_AUXADC_CON27 ((unsigned int)(PMIC_REG_BASE+0xCA)) +#define MT6311_AUXADC_CON28 ((unsigned int)(PMIC_REG_BASE+0xCB)) +#define MT6311_LDO_CON0 ((unsigned int)(PMIC_REG_BASE+0xCC)) +#define MT6311_LDO_OCFB0 ((unsigned int)(PMIC_REG_BASE+0xCD)) +#define MT6311_LDO_CON2 ((unsigned int)(PMIC_REG_BASE+0xCE)) +#define MT6311_LDO_CON3 ((unsigned int)(PMIC_REG_BASE+0xCF)) +#define MT6311_LDO_CON4 ((unsigned int)(PMIC_REG_BASE+0xD0)) +#define MT6311_FQMTR_CON0 ((unsigned int)(PMIC_REG_BASE+0xD1)) +#define MT6311_FQMTR_CON1 ((unsigned int)(PMIC_REG_BASE+0xD2)) +#define MT6311_FQMTR_CON2 ((unsigned int)(PMIC_REG_BASE+0xD3)) +#define MT6311_FQMTR_CON3 ((unsigned int)(PMIC_REG_BASE+0xD4)) +#define MT6311_FQMTR_CON4 ((unsigned int)(PMIC_REG_BASE+0xD5)) +/* mask is HEX; shift is Integer */ +#define MT6311_PMIC_CID_MASK 0xFF +#define MT6311_PMIC_CID_SHIFT 0 +#define MT6311_PMIC_SWCID_MASK 0xFF +#define MT6311_PMIC_SWCID_SHIFT 0 +#define MT6311_PMIC_HWCID_MASK 0xFF +#define MT6311_PMIC_HWCID_SHIFT 0 +#define MT6311_PMIC_GPIO0_DIR_MASK 0x1 +#define MT6311_PMIC_GPIO0_DIR_SHIFT 0 +#define MT6311_PMIC_GPIO1_DIR_MASK 0x1 +#define MT6311_PMIC_GPIO1_DIR_SHIFT 1 +#define MT6311_PMIC_GPIO0_DINV_MASK 0x1 +#define MT6311_PMIC_GPIO0_DINV_SHIFT 2 +#define MT6311_PMIC_GPIO1_DINV_MASK 0x1 +#define MT6311_PMIC_GPIO1_DINV_SHIFT 3 +#define MT6311_PMIC_GPIO0_DOUT_MASK 0x1 +#define MT6311_PMIC_GPIO0_DOUT_SHIFT 4 +#define MT6311_PMIC_GPIO1_DOUT_MASK 0x1 +#define MT6311_PMIC_GPIO1_DOUT_SHIFT 5 +#define MT6311_PMIC_GPIO0_DIN_MASK 0x1 +#define MT6311_PMIC_GPIO0_DIN_SHIFT 6 +#define MT6311_PMIC_GPIO1_DIN_MASK 0x1 +#define MT6311_PMIC_GPIO1_DIN_SHIFT 7 +#define MT6311_PMIC_GPIO0_MODE_MASK 0x7 +#define MT6311_PMIC_GPIO0_MODE_SHIFT 0 +#define MT6311_PMIC_GPIO1_MODE_MASK 0x7 +#define MT6311_PMIC_GPIO1_MODE_SHIFT 3 +#define MT6311_PMIC_TEST_OUT_MASK 0x3 +#define MT6311_PMIC_TEST_OUT_SHIFT 0 +#define MT6311_PMIC_RG_MON_GRP_SEL_MASK 0xF +#define MT6311_PMIC_RG_MON_GRP_SEL_SHIFT 0 +#define MT6311_PMIC_RG_MON_FLAG_SEL_MASK 0xFF +#define MT6311_PMIC_RG_MON_FLAG_SEL_SHIFT 0 +#define MT6311_PMIC_DIG_TESTMODE_MASK 0x1 +#define MT6311_PMIC_DIG_TESTMODE_SHIFT 0 +#define MT6311_PMIC_PMU_TESTMODE_MASK 0x1 +#define MT6311_PMIC_PMU_TESTMODE_SHIFT 0 +#define MT6311_PMIC_RG_SRCLKEN_IN_HW_MODE_MASK 0x1 +#define MT6311_PMIC_RG_SRCLKEN_IN_HW_MODE_SHIFT 0 +#define MT6311_PMIC_RG_SRCLKEN_IN_EN_MASK 0x1 +#define MT6311_PMIC_RG_SRCLKEN_IN_EN_SHIFT 1 +#define MT6311_PMIC_RG_BUCK_LP_HW_MODE_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_LP_HW_MODE_SHIFT 2 +#define MT6311_PMIC_RG_BUCK_LP_EN_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_LP_EN_SHIFT 3 +#define MT6311_PMIC_RG_OSC_EN_MASK 0x1 +#define MT6311_PMIC_RG_OSC_EN_SHIFT 4 +#define MT6311_PMIC_RG_OSC_EN_HW_MODE_MASK 0x1 +#define MT6311_PMIC_RG_OSC_EN_HW_MODE_SHIFT 5 +#define MT6311_PMIC_RG_SRCLKEN_IN_SYNC_EN_MASK 0x1 +#define MT6311_PMIC_RG_SRCLKEN_IN_SYNC_EN_SHIFT 6 +#define MT6311_PMIC_RG_STRUP_RSV_HW_MODE_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_RSV_HW_MODE_SHIFT 7 +#define MT6311_PMIC_RG_BUCK_REF_CK_TSTSEL_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_REF_CK_TSTSEL_SHIFT 0 +#define MT6311_PMIC_RG_FQMTR_CK_TSTSEL_MASK 0x1 +#define MT6311_PMIC_RG_FQMTR_CK_TSTSEL_SHIFT 1 +#define MT6311_PMIC_RG_SMPS_CK_TSTSEL_MASK 0x1 +#define MT6311_PMIC_RG_SMPS_CK_TSTSEL_SHIFT 2 +#define MT6311_PMIC_RG_PMU75K_CK_TSTSEL_MASK 0x1 +#define MT6311_PMIC_RG_PMU75K_CK_TSTSEL_SHIFT 3 +#define MT6311_PMIC_RG_SMPS_CK_TST_DIS_MASK 0x1 +#define MT6311_PMIC_RG_SMPS_CK_TST_DIS_SHIFT 4 +#define MT6311_PMIC_RG_PMU75K_CK_TST_DIS_MASK 0x1 +#define MT6311_PMIC_RG_PMU75K_CK_TST_DIS_SHIFT 5 +#define MT6311_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_SHIFT 6 +#define MT6311_PMIC_RG_BUCK_REF_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_REF_CK_PDN_SHIFT 0 +#define MT6311_PMIC_RG_BUCK_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_CK_PDN_SHIFT 1 +#define MT6311_PMIC_RG_BUCK_1M_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_1M_CK_PDN_SHIFT 2 +#define MT6311_PMIC_RG_INTRP_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_INTRP_CK_PDN_SHIFT 3 +#define MT6311_PMIC_RG_EFUSE_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_CK_PDN_SHIFT 4 +#define MT6311_PMIC_RG_STRUP_75K_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_75K_CK_PDN_SHIFT 5 +#define MT6311_PMIC_RG_BUCK_ANA_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_ANA_CK_PDN_SHIFT 6 +#define MT6311_PMIC_RG_TRIM_75K_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_TRIM_75K_CK_PDN_SHIFT 7 +#define MT6311_PMIC_TOP_CKPDN_CON1_SET_MASK 0xFF +#define MT6311_PMIC_TOP_CKPDN_CON1_SET_SHIFT 0 +#define MT6311_PMIC_TOP_CKPDN_CON1_CLR_MASK 0xFF +#define MT6311_PMIC_TOP_CKPDN_CON1_CLR_SHIFT 0 +#define MT6311_PMIC_RG_AUXADC_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_AUXADC_CK_PDN_SHIFT 0 +#define MT6311_PMIC_RG_AUXADC_1M_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_AUXADC_1M_CK_PDN_SHIFT 1 +#define MT6311_PMIC_RG_STB_75K_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_STB_75K_CK_PDN_SHIFT 2 +#define MT6311_PMIC_RG_FQMTR_CK_PDN_MASK 0x1 +#define MT6311_PMIC_RG_FQMTR_CK_PDN_SHIFT 3 +#define MT6311_PMIC_TOP_CKPDN_CON2_RSV_MASK 0xF +#define MT6311_PMIC_TOP_CKPDN_CON2_RSV_SHIFT 4 +#define MT6311_PMIC_TOP_CKPDN_CON2_SET_MASK 0xFF +#define MT6311_PMIC_TOP_CKPDN_CON2_SET_SHIFT 0 +#define MT6311_PMIC_TOP_CKPDN_CON2_CLR_MASK 0xFF +#define MT6311_PMIC_TOP_CKPDN_CON2_CLR_SHIFT 0 +#define MT6311_PMIC_RG_BUCK_1M_CK_PDN_HWEN_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_1M_CK_PDN_HWEN_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_CK_PDN_HWEN_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_CK_PDN_HWEN_SHIFT 1 +#define MT6311_PMIC_TOP_CKHWEN_CON_SET_MASK 0x3 +#define MT6311_PMIC_TOP_CKHWEN_CON_SET_SHIFT 0 +#define MT6311_PMIC_TOP_CKHWEN_CON_CLR_MASK 0x3 +#define MT6311_PMIC_TOP_CKHWEN_CON_CLR_SHIFT 0 +#define MT6311_PMIC_RG_AUXADC_RST_MASK 0x1 +#define MT6311_PMIC_RG_AUXADC_RST_SHIFT 0 +#define MT6311_PMIC_RG_FQMTR_RST_MASK 0x1 +#define MT6311_PMIC_RG_FQMTR_RST_SHIFT 1 +#define MT6311_PMIC_RG_CLK_TRIM_RST_MASK 0x1 +#define MT6311_PMIC_RG_CLK_TRIM_RST_SHIFT 2 +#define MT6311_PMIC_RG_EFUSE_MAN_RST_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_MAN_RST_SHIFT 3 +#define MT6311_PMIC_RG_WDTRSTB_MODE_MASK 0x1 +#define MT6311_PMIC_RG_WDTRSTB_MODE_SHIFT 4 +#define MT6311_PMIC_RG_WDTRSTB_EN_MASK 0x1 +#define MT6311_PMIC_RG_WDTRSTB_EN_SHIFT 5 +#define MT6311_PMIC_WDTRSTB_STATUS_CLR_MASK 0x1 +#define MT6311_PMIC_WDTRSTB_STATUS_CLR_SHIFT 6 +#define MT6311_PMIC_WDTRSTB_STATUS_MASK 0x1 +#define MT6311_PMIC_WDTRSTB_STATUS_SHIFT 7 +#define MT6311_PMIC_TOP_RST_CON_SET_MASK 0xFF +#define MT6311_PMIC_TOP_RST_CON_SET_SHIFT 0 +#define MT6311_PMIC_TOP_RST_CON_CLR_MASK 0xFF +#define MT6311_PMIC_TOP_RST_CON_CLR_SHIFT 0 +#define MT6311_PMIC_RG_INT_POL_MASK 0x1 +#define MT6311_PMIC_RG_INT_POL_SHIFT 0 +#define MT6311_PMIC_RG_INT_EN_MASK 0x1 +#define MT6311_PMIC_RG_INT_EN_SHIFT 1 +#define MT6311_PMIC_I2C_CONFIG_MASK 0x1 +#define MT6311_PMIC_I2C_CONFIG_SHIFT 2 +#define MT6311_PMIC_RG_LBAT_MIN_INT_STATUS_MASK 0x1 +#define MT6311_PMIC_RG_LBAT_MIN_INT_STATUS_SHIFT 0 +#define MT6311_PMIC_RG_LBAT_MAX_INT_STATUS_MASK 0x1 +#define MT6311_PMIC_RG_LBAT_MAX_INT_STATUS_SHIFT 1 +#define MT6311_PMIC_RG_THR_L_INT_STATUS_MASK 0x1 +#define MT6311_PMIC_RG_THR_L_INT_STATUS_SHIFT 2 +#define MT6311_PMIC_RG_THR_H_INT_STATUS_MASK 0x1 +#define MT6311_PMIC_RG_THR_H_INT_STATUS_SHIFT 3 +#define MT6311_PMIC_RG_BUCK_OC_INT_STATUS_MASK 0x1 +#define MT6311_PMIC_RG_BUCK_OC_INT_STATUS_SHIFT 4 +#define MT6311_PMIC_THR_DET_DIS_MASK 0x1 +#define MT6311_PMIC_THR_DET_DIS_SHIFT 0 +#define MT6311_PMIC_THR_HWPDN_EN_MASK 0x1 +#define MT6311_PMIC_THR_HWPDN_EN_SHIFT 1 +#define MT6311_PMIC_STRUP_DIG0_RSV0_MASK 0x3F +#define MT6311_PMIC_STRUP_DIG0_RSV0_SHIFT 2 +#define MT6311_PMIC_RG_USBDL_EN_MASK 0x1 +#define MT6311_PMIC_RG_USBDL_EN_SHIFT 0 +#define MT6311_PMIC_RG_TEST_STRUP_MASK 0x1 +#define MT6311_PMIC_RG_TEST_STRUP_SHIFT 1 +#define MT6311_PMIC_RG_TEST_STRUP_THR_IN_MASK 0x1 +#define MT6311_PMIC_RG_TEST_STRUP_THR_IN_SHIFT 2 +#define MT6311_PMIC_STRUP_DIG1_RSV0_MASK 0x1F +#define MT6311_PMIC_STRUP_DIG1_RSV0_SHIFT 3 +#define MT6311_PMIC_THR_TEST_MASK 0x3 +#define MT6311_PMIC_THR_TEST_SHIFT 0 +#define MT6311_PMIC_PMU_THR_DEB_MASK 0x7 +#define MT6311_PMIC_PMU_THR_DEB_SHIFT 2 +#define MT6311_PMIC_PMU_THR_STATUS_MASK 0x7 +#define MT6311_PMIC_PMU_THR_STATUS_SHIFT 5 +#define MT6311_PMIC_STRUP_PWRON_MASK 0x1 +#define MT6311_PMIC_STRUP_PWRON_SHIFT 0 +#define MT6311_PMIC_STRUP_PWRON_SEL_MASK 0x1 +#define MT6311_PMIC_STRUP_PWRON_SEL_SHIFT 1 +#define MT6311_PMIC_BIAS_GEN_EN_MASK 0x1 +#define MT6311_PMIC_BIAS_GEN_EN_SHIFT 2 +#define MT6311_PMIC_BIAS_GEN_EN_SEL_MASK 0x1 +#define MT6311_PMIC_BIAS_GEN_EN_SEL_SHIFT 3 +#define MT6311_PMIC_RTC_XOSC32_ENB_SW_MASK 0x1 +#define MT6311_PMIC_RTC_XOSC32_ENB_SW_SHIFT 4 +#define MT6311_PMIC_RTC_XOSC32_ENB_SEL_MASK 0x1 +#define MT6311_PMIC_RTC_XOSC32_ENB_SEL_SHIFT 5 +#define MT6311_PMIC_STRUP_DIG_IO_PG_FORCE_MASK 0x1 +#define MT6311_PMIC_STRUP_DIG_IO_PG_FORCE_SHIFT 6 +#define MT6311_PMIC_DDUVLO_DEB_EN_MASK 0x1 +#define MT6311_PMIC_DDUVLO_DEB_EN_SHIFT 0 +#define MT6311_PMIC_PWRBB_DEB_EN_MASK 0x1 +#define MT6311_PMIC_PWRBB_DEB_EN_SHIFT 1 +#define MT6311_PMIC_STRUP_OSC_EN_MASK 0x1 +#define MT6311_PMIC_STRUP_OSC_EN_SHIFT 2 +#define MT6311_PMIC_STRUP_OSC_EN_SEL_MASK 0x1 +#define MT6311_PMIC_STRUP_OSC_EN_SEL_SHIFT 3 +#define MT6311_PMIC_STRUP_FT_CTRL_MASK 0x3 +#define MT6311_PMIC_STRUP_FT_CTRL_SHIFT 4 +#define MT6311_PMIC_STRUP_PWRON_FORCE_MASK 0x1 +#define MT6311_PMIC_STRUP_PWRON_FORCE_SHIFT 6 +#define MT6311_PMIC_BIAS_GEN_EN_FORCE_MASK 0x1 +#define MT6311_PMIC_BIAS_GEN_EN_FORCE_SHIFT 7 +#define MT6311_PMIC_VDVFS11_PG_H2L_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_PG_H2L_EN_SHIFT 0 +#define MT6311_PMIC_VDVFS12_PG_H2L_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_PG_H2L_EN_SHIFT 1 +#define MT6311_PMIC_VBIASN_PG_H2L_EN_MASK 0x1 +#define MT6311_PMIC_VBIASN_PG_H2L_EN_SHIFT 2 +#define MT6311_PMIC_VDVFS11_PG_ENB_MASK 0x1 +#define MT6311_PMIC_VDVFS11_PG_ENB_SHIFT 0 +#define MT6311_PMIC_VDVFS12_PG_ENB_MASK 0x1 +#define MT6311_PMIC_VDVFS12_PG_ENB_SHIFT 1 +#define MT6311_PMIC_VBIASN_PG_ENB_MASK 0x1 +#define MT6311_PMIC_VBIASN_PG_ENB_SHIFT 2 +#define MT6311_PMIC_RG_EXT_PMIC_EN_PG_ENB_MASK 0x1 +#define MT6311_PMIC_RG_EXT_PMIC_EN_PG_ENB_SHIFT 3 +#define MT6311_PMIC_RG_PRE_PWRON_EN_MASK 0x1 +#define MT6311_PMIC_RG_PRE_PWRON_EN_SHIFT 0 +#define MT6311_PMIC_RG_PRE_PWRON_SWCTRL_MASK 0x1 +#define MT6311_PMIC_RG_PRE_PWRON_SWCTRL_SHIFT 1 +#define MT6311_PMIC_CLR_JUST_RST_MASK 0x1 +#define MT6311_PMIC_CLR_JUST_RST_SHIFT 4 +#define MT6311_PMIC_UVLO_L2H_DEB_EN_MASK 0x1 +#define MT6311_PMIC_UVLO_L2H_DEB_EN_SHIFT 5 +#define MT6311_PMIC_RG_BGR_TEST_CKIN_EN_MASK 0x1 +#define MT6311_PMIC_RG_BGR_TEST_CKIN_EN_SHIFT 6 +#define MT6311_PMIC_QI_OSC_EN_MASK 0x1 +#define MT6311_PMIC_QI_OSC_EN_SHIFT 7 +#define MT6311_PMIC_RG_STRUP_PMU_PWRON_SEL_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_PMU_PWRON_SEL_SHIFT 0 +#define MT6311_PMIC_RG_STRUP_PMU_PWRON_EN_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_PMU_PWRON_EN_SHIFT 1 +#define MT6311_PMIC_STRUP_AUXADC_START_SW_MASK 0x1 +#define MT6311_PMIC_STRUP_AUXADC_START_SW_SHIFT 4 +#define MT6311_PMIC_STRUP_AUXADC_RSTB_SW_MASK 0x1 +#define MT6311_PMIC_STRUP_AUXADC_RSTB_SW_SHIFT 5 +#define MT6311_PMIC_STRUP_AUXADC_START_SEL_MASK 0x1 +#define MT6311_PMIC_STRUP_AUXADC_START_SEL_SHIFT 6 +#define MT6311_PMIC_STRUP_AUXADC_RSTB_SEL_MASK 0x1 +#define MT6311_PMIC_STRUP_AUXADC_RSTB_SEL_SHIFT 7 +#define MT6311_PMIC_STRUP_PWROFF_PREOFF_EN_MASK 0x1 +#define MT6311_PMIC_STRUP_PWROFF_PREOFF_EN_SHIFT 0 +#define MT6311_PMIC_STRUP_PWROFF_SEQ_EN_MASK 0x1 +#define MT6311_PMIC_STRUP_PWROFF_SEQ_EN_SHIFT 1 +#define MT6311_PMIC_RG_SYS_LATCH_EN_SWCTRL_MASK 0x1 +#define MT6311_PMIC_RG_SYS_LATCH_EN_SWCTRL_SHIFT 2 +#define MT6311_PMIC_RG_SYS_LATCH_EN_MASK 0x1 +#define MT6311_PMIC_RG_SYS_LATCH_EN_SHIFT 3 +#define MT6311_PMIC_RG_ONOFF_EN_SWCTRL_MASK 0x1 +#define MT6311_PMIC_RG_ONOFF_EN_SWCTRL_SHIFT 4 +#define MT6311_PMIC_RG_ONOFF_EN_MASK 0x1 +#define MT6311_PMIC_RG_ONOFF_EN_SHIFT 5 +#define MT6311_PMIC_RG_STRUP_PWRON_COND_SEL_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_PWRON_COND_SEL_SHIFT 6 +#define MT6311_PMIC_RG_STRUP_PWRON_COND_EN_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_PWRON_COND_EN_SHIFT 7 +#define MT6311_PMIC_STRUP_PG_STATUS_MASK 0x1 +#define MT6311_PMIC_STRUP_PG_STATUS_SHIFT 0 +#define MT6311_PMIC_STRUP_PG_STATUS_CLR_MASK 0x1 +#define MT6311_PMIC_STRUP_PG_STATUS_CLR_SHIFT 1 +#define MT6311_PMIC_RG_RSV_SWREG_MASK 0xFF +#define MT6311_PMIC_RG_RSV_SWREG_SHIFT 0 +#define MT6311_PMIC_VDVFS11_PG_DEB_MASK 0x1 +#define MT6311_PMIC_VDVFS11_PG_DEB_SHIFT 0 +#define MT6311_PMIC_VDVFS12_PG_DEB_MASK 0x1 +#define MT6311_PMIC_VDVFS12_PG_DEB_SHIFT 1 +#define MT6311_PMIC_VBIASN_PG_DEB_MASK 0x1 +#define MT6311_PMIC_VBIASN_PG_DEB_SHIFT 2 +#define MT6311_PMIC_STRUP_RO_RSV0_MASK 0x1F +#define MT6311_PMIC_STRUP_RO_RSV0_SHIFT 3 +#define MT6311_PMIC_RG_STRUP_THR_110_CLR_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_THR_110_CLR_SHIFT 0 +#define MT6311_PMIC_RG_STRUP_THR_125_CLR_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_THR_125_CLR_SHIFT 1 +#define MT6311_PMIC_RG_STRUP_THR_110_IRQ_EN_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_THR_110_IRQ_EN_SHIFT 2 +#define MT6311_PMIC_RG_STRUP_THR_125_IRQ_EN_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_THR_125_IRQ_EN_SHIFT 3 +#define MT6311_PMIC_RG_STRUP_THR_110_IRQ_STATUS_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_THR_110_IRQ_STATUS_SHIFT 4 +#define MT6311_PMIC_RG_STRUP_THR_125_IRQ_STATUS_MASK 0x1 +#define MT6311_PMIC_RG_STRUP_THR_125_IRQ_STATUS_SHIFT 5 +#define MT6311_PMIC_RG_THERMAL_EN_MASK 0x1 +#define MT6311_PMIC_RG_THERMAL_EN_SHIFT 6 +#define MT6311_PMIC_RG_THERMAL_EN_SEL_MASK 0x1 +#define MT6311_PMIC_RG_THERMAL_EN_SEL_SHIFT 7 +#define MT6311_PMIC_RG_OSC_75K_TRIM_MASK 0x1F +#define MT6311_PMIC_RG_OSC_75K_TRIM_SHIFT 0 +#define MT6311_PMIC_OSC_75K_TRIM_MASK 0x1F +#define MT6311_PMIC_OSC_75K_TRIM_SHIFT 0 +#define MT6311_PMIC_RG_OSC_75K_TRIM_EN_MASK 0x1 +#define MT6311_PMIC_RG_OSC_75K_TRIM_EN_SHIFT 5 +#define MT6311_PMIC_RG_OSC_75K_TRIM_RATE_MASK 0x3 +#define MT6311_PMIC_RG_OSC_75K_TRIM_RATE_SHIFT 6 +#define MT6311_PMIC_RG_EFUSE_ADDR_MASK 0x7F +#define MT6311_PMIC_RG_EFUSE_ADDR_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DIN_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_DIN_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DM_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_DM_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_PGM_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_PGM_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_PGM_EN_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_PGM_EN_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_PROG_PKEY_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_PROG_PKEY_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_RD_PKEY_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_RD_PKEY_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_PGM_SRC_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_PGM_SRC_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DIN_SRC_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_DIN_SRC_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_RD_TRIG_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_RD_TRIG_SHIFT 0 +#define MT6311_PMIC_RG_RD_RDY_BYPASS_MASK 0x1 +#define MT6311_PMIC_RG_RD_RDY_BYPASS_SHIFT 0 +#define MT6311_PMIC_RG_SKIP_EFUSE_OUT_MASK 0x1 +#define MT6311_PMIC_RG_SKIP_EFUSE_OUT_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_RD_ACK_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_RD_ACK_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_RD_BUSY_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_RD_BUSY_SHIFT 2 +#define MT6311_PMIC_RG_EFUSE_WRITE_MODE_MASK 0x1 +#define MT6311_PMIC_RG_EFUSE_WRITE_MODE_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_0_7_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_0_7_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_8_15_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_8_15_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_16_23_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_16_23_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_24_31_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_24_31_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_32_39_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_32_39_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_40_47_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_40_47_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_48_55_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_48_55_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_56_63_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_56_63_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_64_71_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_64_71_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_72_79_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_72_79_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_80_87_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_80_87_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_88_95_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_88_95_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_96_103_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_96_103_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_104_111_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_104_111_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_112_119_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_112_119_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_DOUT_120_127_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_DOUT_120_127_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_0_7_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_0_7_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_8_15_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_8_15_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_16_23_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_16_23_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_24_31_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_24_31_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_32_39_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_32_39_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_40_47_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_40_47_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_48_55_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_48_55_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_56_63_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_56_63_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_64_71_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_64_71_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_72_79_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_72_79_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_80_87_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_80_87_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_88_95_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_88_95_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_96_103_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_96_103_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_104_111_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_104_111_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_112_119_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_112_119_SHIFT 0 +#define MT6311_PMIC_RG_EFUSE_VAL_120_127_MASK 0xFF +#define MT6311_PMIC_RG_EFUSE_VAL_120_127_SHIFT 0 +#define MT6311_PMIC_BUCK_DIG0_RSV0_MASK 0xFF +#define MT6311_PMIC_BUCK_DIG0_RSV0_SHIFT 0 +#define MT6311_PMIC_VSLEEP_SRC0_8_MASK 0x1 +#define MT6311_PMIC_VSLEEP_SRC0_8_SHIFT 0 +#define MT6311_PMIC_VSLEEP_SRC1_MASK 0xF +#define MT6311_PMIC_VSLEEP_SRC1_SHIFT 1 +#define MT6311_PMIC_VSLEEP_SRC0_7_0_MASK 0xFF +#define MT6311_PMIC_VSLEEP_SRC0_7_0_SHIFT 0 +#define MT6311_PMIC_R2R_SRC0_8_MASK 0x1 +#define MT6311_PMIC_R2R_SRC0_8_SHIFT 0 +#define MT6311_PMIC_R2R_SRC1_MASK 0xF +#define MT6311_PMIC_R2R_SRC1_SHIFT 1 +#define MT6311_PMIC_R2R_SRC0_7_0_MASK 0xFF +#define MT6311_PMIC_R2R_SRC0_7_0_SHIFT 0 +#define MT6311_PMIC_BUCK_OSC_SEL_SRC0_8_MASK 0x1 +#define MT6311_PMIC_BUCK_OSC_SEL_SRC0_8_SHIFT 0 +#define MT6311_PMIC_SRCLKEN_DLY_SRC1_MASK 0xF +#define MT6311_PMIC_SRCLKEN_DLY_SRC1_SHIFT 1 +#define MT6311_PMIC_BUCK_OSC_SEL_SRC0_7_0_MASK 0xFF +#define MT6311_PMIC_BUCK_OSC_SEL_SRC0_7_0_SHIFT 0 +#define MT6311_PMIC_QI_VDVFS12_DIG_MON_MASK 0xFF +#define MT6311_PMIC_QI_VDVFS12_DIG_MON_SHIFT 0 +#define MT6311_PMIC_QI_VDVFS11_DIG_MON_MASK 0xFF +#define MT6311_PMIC_QI_VDVFS11_DIG_MON_SHIFT 0 +#define MT6311_PMIC_VDVFS11_OC_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_OC_EN_SHIFT 0 +#define MT6311_PMIC_VDVFS11_OC_DEG_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_OC_DEG_EN_SHIFT 1 +#define MT6311_PMIC_VDVFS11_OC_WND_MASK 0x3 +#define MT6311_PMIC_VDVFS11_OC_WND_SHIFT 2 +#define MT6311_PMIC_VDVFS11_OC_THD_MASK 0x3 +#define MT6311_PMIC_VDVFS11_OC_THD_SHIFT 6 +#define MT6311_PMIC_VDVFS12_OC_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_OC_EN_SHIFT 0 +#define MT6311_PMIC_VDVFS12_OC_DEG_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_OC_DEG_EN_SHIFT 1 +#define MT6311_PMIC_VDVFS12_OC_WND_MASK 0x3 +#define MT6311_PMIC_VDVFS12_OC_WND_SHIFT 2 +#define MT6311_PMIC_VDVFS12_OC_THD_MASK 0x3 +#define MT6311_PMIC_VDVFS12_OC_THD_SHIFT 6 +#define MT6311_PMIC_VDVFS11_OC_FLAG_CLR_MASK 0x1 +#define MT6311_PMIC_VDVFS11_OC_FLAG_CLR_SHIFT 0 +#define MT6311_PMIC_VDVFS12_OC_FLAG_CLR_MASK 0x1 +#define MT6311_PMIC_VDVFS12_OC_FLAG_CLR_SHIFT 1 +#define MT6311_PMIC_VDVFS11_OC_RG_STATUS_CLR_MASK 0x1 +#define MT6311_PMIC_VDVFS11_OC_RG_STATUS_CLR_SHIFT 2 +#define MT6311_PMIC_VDVFS12_OC_RG_STATUS_CLR_MASK 0x1 +#define MT6311_PMIC_VDVFS12_OC_RG_STATUS_CLR_SHIFT 3 +#define MT6311_PMIC_VDVFS11_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6311_PMIC_VDVFS11_OC_FLAG_CLR_SEL_SHIFT 0 +#define MT6311_PMIC_VDVFS12_OC_FLAG_CLR_SEL_MASK 0x1 +#define MT6311_PMIC_VDVFS12_OC_FLAG_CLR_SEL_SHIFT 1 +#define MT6311_PMIC_VDVFS11_OC_STATUS_MASK 0x1 +#define MT6311_PMIC_VDVFS11_OC_STATUS_SHIFT 0 +#define MT6311_PMIC_VDVFS12_OC_STATUS_MASK 0x1 +#define MT6311_PMIC_VDVFS12_OC_STATUS_SHIFT 1 +#define MT6311_PMIC_VDVFS11_OC_INT_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_OC_INT_EN_SHIFT 0 +#define MT6311_PMIC_VDVFS12_OC_INT_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_OC_INT_EN_SHIFT 1 +#define MT6311_PMIC_VDVFS11_EN_OC_SDN_SEL_MASK 0x1 +#define MT6311_PMIC_VDVFS11_EN_OC_SDN_SEL_SHIFT 0 +#define MT6311_PMIC_VDVFS12_EN_OC_SDN_SEL_MASK 0x1 +#define MT6311_PMIC_VDVFS12_EN_OC_SDN_SEL_SHIFT 1 +#define MT6311_PMIC_BUCK_TEST_MODE_MASK 0x1 +#define MT6311_PMIC_BUCK_TEST_MODE_SHIFT 0 +#define MT6311_PMIC_BUCK_DIG1_RSV0_MASK 0x7F +#define MT6311_PMIC_BUCK_DIG1_RSV0_SHIFT 1 +#define MT6311_PMIC_QI_VDVFS11_VSLEEP_MASK 0x7 +#define MT6311_PMIC_QI_VDVFS11_VSLEEP_SHIFT 0 +#define MT6311_PMIC_QI_VDVFS12_VSLEEP_MASK 0x7 +#define MT6311_PMIC_QI_VDVFS12_VSLEEP_SHIFT 3 +#define MT6311_PMIC_BUCK_ANA_DIG0_RSV0_MASK 0xFF +#define MT6311_PMIC_BUCK_ANA_DIG0_RSV0_SHIFT 0 +#define MT6311_PMIC_RG_THRDET_SEL_MASK 0x1 +#define MT6311_PMIC_RG_THRDET_SEL_SHIFT 0 +#define MT6311_PMIC_RG_STRUP_THR_SEL_MASK 0x3 +#define MT6311_PMIC_RG_STRUP_THR_SEL_SHIFT 1 +#define MT6311_PMIC_RG_THR_TMODE_MASK 0x1 +#define MT6311_PMIC_RG_THR_TMODE_SHIFT 3 +#define MT6311_PMIC_RG_STRUP_IREF_TRIM_MASK 0x1F +#define MT6311_PMIC_RG_STRUP_IREF_TRIM_SHIFT 0 +#define MT6311_PMIC_RG_UVLO_VTHL_MASK 0x3 +#define MT6311_PMIC_RG_UVLO_VTHL_SHIFT 5 +#define MT6311_PMIC_RG_UVLO_VTHH_MASK 0x3 +#define MT6311_PMIC_RG_UVLO_VTHH_SHIFT 0 +#define MT6311_PMIC_RG_BGR_UNCHOP_MASK 0x1 +#define MT6311_PMIC_RG_BGR_UNCHOP_SHIFT 2 +#define MT6311_PMIC_RG_BGR_UNCHOP_PH_MASK 0x1 +#define MT6311_PMIC_RG_BGR_UNCHOP_PH_SHIFT 3 +#define MT6311_PMIC_RG_BGR_RSEL_MASK 0x7 +#define MT6311_PMIC_RG_BGR_RSEL_SHIFT 4 +#define MT6311_PMIC_RG_BGR_TRIM_MASK 0x1F +#define MT6311_PMIC_RG_BGR_TRIM_SHIFT 0 +#define MT6311_PMIC_RG_BGR_TEST_EN_MASK 0x1 +#define MT6311_PMIC_RG_BGR_TEST_EN_SHIFT 5 +#define MT6311_PMIC_RG_BGR_TEST_RSTB_MASK 0x1 +#define MT6311_PMIC_RG_BGR_TEST_RSTB_SHIFT 6 +#define MT6311_PMIC_RG_VDVFS11_TRIMH_MASK 0x1F +#define MT6311_PMIC_RG_VDVFS11_TRIMH_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS11_TRIML_MASK 0x1F +#define MT6311_PMIC_RG_VDVFS11_TRIML_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_TRIMH_MASK 0x1F +#define MT6311_PMIC_RG_VDVFS12_TRIMH_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_TRIML_MASK 0x1F +#define MT6311_PMIC_RG_VDVFS12_TRIML_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS11_VSLEEP_MASK 0x7 +#define MT6311_PMIC_RG_VDVFS11_VSLEEP_SHIFT 5 +#define MT6311_PMIC_RG_VDVFS12_VSLEEP_MASK 0x7 +#define MT6311_PMIC_RG_VDVFS12_VSLEEP_SHIFT 0 +#define MT6311_PMIC_RG_BGR_OSC_CAL_MASK 0x3F +#define MT6311_PMIC_RG_BGR_OSC_CAL_SHIFT 0 +#define MT6311_PMIC_RG_STRUP_RSV_MASK 0xFF +#define MT6311_PMIC_RG_STRUP_RSV_SHIFT 0 +#define MT6311_PMIC_RG_VREF_LP_MODE_MASK 0x1 +#define MT6311_PMIC_RG_VREF_LP_MODE_SHIFT 0 +#define MT6311_PMIC_RG_TESTMODE_SWEN_MASK 0x1 +#define MT6311_PMIC_RG_TESTMODE_SWEN_SHIFT 1 +#define MT6311_PMIC_RG_VDIG18_VOSEL_MASK 0x7 +#define MT6311_PMIC_RG_VDIG18_VOSEL_SHIFT 2 +#define MT6311_PMIC_RG_VDIG18_CAL_MASK 0xF +#define MT6311_PMIC_RG_VDIG18_CAL_SHIFT 0 +#define MT6311_PMIC_RG_OSC_SEL_MASK 0x1 +#define MT6311_PMIC_RG_OSC_SEL_SHIFT 4 +#define MT6311_PMIC_RG_VBIASN_NDIS_EN_MASK 0x1 +#define MT6311_PMIC_RG_VBIASN_NDIS_EN_SHIFT 0 +#define MT6311_PMIC_RG_VBIASN_VOSEL_MASK 0x1F +#define MT6311_PMIC_RG_VBIASN_VOSEL_SHIFT 1 +#define MT6311_PMIC_RG_VDVFS11_RC_MASK 0xF +#define MT6311_PMIC_RG_VDVFS11_RC_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_RC_MASK 0xF +#define MT6311_PMIC_RG_VDVFS12_RC_SHIFT 4 +#define MT6311_PMIC_RG_VDVFS11_CSR_MASK 0x3 +#define MT6311_PMIC_RG_VDVFS11_CSR_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_CSR_MASK 0x3 +#define MT6311_PMIC_RG_VDVFS12_CSR_SHIFT 2 +#define MT6311_PMIC_RG_VDVFS11_PFM_CSR_MASK 0x3 +#define MT6311_PMIC_RG_VDVFS11_PFM_CSR_SHIFT 4 +#define MT6311_PMIC_RG_VDVFS12_PFM_CSR_MASK 0x3 +#define MT6311_PMIC_RG_VDVFS12_PFM_CSR_SHIFT 6 +#define MT6311_PMIC_RG_VDVFS11_SLP_MASK 0x3 +#define MT6311_PMIC_RG_VDVFS11_SLP_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_SLP_MASK 0x3 +#define MT6311_PMIC_RG_VDVFS12_SLP_SHIFT 2 +#define MT6311_PMIC_RG_VDVFS11_UVP_EN_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS11_UVP_EN_SHIFT 4 +#define MT6311_PMIC_RG_VDVFS12_UVP_EN_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS12_UVP_EN_SHIFT 5 +#define MT6311_PMIC_RG_VDVFS11_MODESET_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS11_MODESET_SHIFT 6 +#define MT6311_PMIC_RG_VDVFS12_MODESET_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS12_MODESET_SHIFT 7 +#define MT6311_PMIC_RG_VDVFS11_NDIS_EN_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS11_NDIS_EN_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_NDIS_EN_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS12_NDIS_EN_SHIFT 1 +#define MT6311_PMIC_RG_VDVFS11_TRANS_BST_MASK 0xFF +#define MT6311_PMIC_RG_VDVFS11_TRANS_BST_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_TRANS_BST_MASK 0xFF +#define MT6311_PMIC_RG_VDVFS12_TRANS_BST_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS11_CSM_N_MASK 0xF +#define MT6311_PMIC_RG_VDVFS11_CSM_N_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS11_CSM_P_MASK 0xF +#define MT6311_PMIC_RG_VDVFS11_CSM_P_SHIFT 4 +#define MT6311_PMIC_RG_VDVFS12_CSM_N_MASK 0xF +#define MT6311_PMIC_RG_VDVFS12_CSM_N_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_CSM_P_MASK 0xF +#define MT6311_PMIC_RG_VDVFS12_CSM_P_SHIFT 4 +#define MT6311_PMIC_RG_VDVFS11_ZXOS_TRIM_MASK 0x3F +#define MT6311_PMIC_RG_VDVFS11_ZXOS_TRIM_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS12_ZXOS_TRIM_MASK 0x3F +#define MT6311_PMIC_RG_VDVFS12_ZXOS_TRIM_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS11_OC_OFF_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS11_OC_OFF_SHIFT 6 +#define MT6311_PMIC_RG_VDVFS12_OC_OFF_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS12_OC_OFF_SHIFT 7 +#define MT6311_PMIC_RG_VDVFS11_PHS_SHED_TRIM_MASK 0xF +#define MT6311_PMIC_RG_VDVFS11_PHS_SHED_TRIM_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS11_F2PHS_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS11_F2PHS_SHIFT 4 +#define MT6311_PMIC_RG_VDVFS11_RS_FORCE_OFF_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS11_RS_FORCE_OFF_SHIFT 5 +#define MT6311_PMIC_RG_VDVFS12_RS_FORCE_OFF_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS12_RS_FORCE_OFF_SHIFT 6 +#define MT6311_PMIC_RG_VDVFS11_TM_EN_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS11_TM_EN_SHIFT 7 +#define MT6311_PMIC_RG_VDVFS11_TM_UGSNS_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS11_TM_UGSNS_SHIFT 0 +#define MT6311_PMIC_RG_VDVFS1_FBN_SEL_MASK 0x1 +#define MT6311_PMIC_RG_VDVFS1_FBN_SEL_SHIFT 1 +#define MT6311_PMIC_RGS_VDVFS11_ENPWM_STATUS_MASK 0x1 +#define MT6311_PMIC_RGS_VDVFS11_ENPWM_STATUS_SHIFT 0 +#define MT6311_PMIC_RGS_VDVFS12_ENPWM_STATUS_MASK 0x1 +#define MT6311_PMIC_RGS_VDVFS12_ENPWM_STATUS_SHIFT 1 +#define MT6311_PMIC_NI_VDVFS1_COUNT_MASK 0x1 +#define MT6311_PMIC_NI_VDVFS1_COUNT_SHIFT 2 +#define MT6311_PMIC_VDVFS11_DIG0_RSV0_MASK 0xFF +#define MT6311_PMIC_VDVFS11_DIG0_RSV0_SHIFT 0 +#define MT6311_PMIC_VDVFS11_EN_CTRL_MASK 0x1 +#define MT6311_PMIC_VDVFS11_EN_CTRL_SHIFT 0 +#define MT6311_PMIC_VDVFS11_VOSEL_CTRL_MASK 0x1 +#define MT6311_PMIC_VDVFS11_VOSEL_CTRL_SHIFT 1 +#define MT6311_PMIC_VDVFS11_DIG0_RSV1_MASK 0x1 +#define MT6311_PMIC_VDVFS11_DIG0_RSV1_SHIFT 2 +#define MT6311_PMIC_VDVFS11_BURST_CTRL_MASK 0x1 +#define MT6311_PMIC_VDVFS11_BURST_CTRL_SHIFT 3 +#define MT6311_PMIC_VDVFS11_EN_SEL_MASK 0x3 +#define MT6311_PMIC_VDVFS11_EN_SEL_SHIFT 0 +#define MT6311_PMIC_VDVFS11_VOSEL_SEL_MASK 0x3 +#define MT6311_PMIC_VDVFS11_VOSEL_SEL_SHIFT 2 +#define MT6311_PMIC_VDVFS11_DIG0_RSV2_MASK 0x3 +#define MT6311_PMIC_VDVFS11_DIG0_RSV2_SHIFT 4 +#define MT6311_PMIC_VDVFS11_BURST_SEL_MASK 0x3 +#define MT6311_PMIC_VDVFS11_BURST_SEL_SHIFT 6 +#define MT6311_PMIC_VDVFS11_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_EN_SHIFT 0 +#define MT6311_PMIC_VDVFS11_STBTD_MASK 0x3 +#define MT6311_PMIC_VDVFS11_STBTD_SHIFT 1 +#define MT6311_PMIC_QI_VDVFS11_STB_MASK 0x1 +#define MT6311_PMIC_QI_VDVFS11_STB_SHIFT 3 +#define MT6311_PMIC_QI_VDVFS11_EN_MASK 0x1 +#define MT6311_PMIC_QI_VDVFS11_EN_SHIFT 4 +#define MT6311_PMIC_QI_VDVFS11_OC_STATUS_MASK 0x1 +#define MT6311_PMIC_QI_VDVFS11_OC_STATUS_SHIFT 7 +#define MT6311_PMIC_VDVFS11_SFCHG_RRATE_MASK 0x7F +#define MT6311_PMIC_VDVFS11_SFCHG_RRATE_SHIFT 0 +#define MT6311_PMIC_VDVFS11_SFCHG_REN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_SFCHG_REN_SHIFT 7 +#define MT6311_PMIC_VDVFS11_SFCHG_FRATE_MASK 0x7F +#define MT6311_PMIC_VDVFS11_SFCHG_FRATE_SHIFT 0 +#define MT6311_PMIC_VDVFS11_SFCHG_FEN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_SFCHG_FEN_SHIFT 7 +#define MT6311_PMIC_VDVFS11_VOSEL_MASK 0x7F +#define MT6311_PMIC_VDVFS11_VOSEL_SHIFT 0 +#define MT6311_PMIC_VDVFS11_VOSEL_ON_MASK 0x7F +#define MT6311_PMIC_VDVFS11_VOSEL_ON_SHIFT 0 +#define MT6311_PMIC_VDVFS11_VOSEL_SLEEP_MASK 0x7F +#define MT6311_PMIC_VDVFS11_VOSEL_SLEEP_SHIFT 0 +#define MT6311_PMIC_NI_VDVFS11_VOSEL_MASK 0x7F +#define MT6311_PMIC_NI_VDVFS11_VOSEL_SHIFT 0 +#define MT6311_PMIC_VDVFS11_BURST_SLEEP_MASK 0x7 +#define MT6311_PMIC_VDVFS11_BURST_SLEEP_SHIFT 0 +#define MT6311_PMIC_QI_VDVFS11_BURST_MASK 0x7 +#define MT6311_PMIC_QI_VDVFS11_BURST_SHIFT 4 +#define MT6311_PMIC_VDVFS11_BURST_MASK 0x7 +#define MT6311_PMIC_VDVFS11_BURST_SHIFT 0 +#define MT6311_PMIC_VDVFS11_BURST_ON_MASK 0x7 +#define MT6311_PMIC_VDVFS11_BURST_ON_SHIFT 4 +#define MT6311_PMIC_VDVFS11_VSLEEP_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_VSLEEP_EN_SHIFT 0 +#define MT6311_PMIC_VDVFS11_R2R_PDN_MASK 0x1 +#define MT6311_PMIC_VDVFS11_R2R_PDN_SHIFT 1 +#define MT6311_PMIC_VDVFS11_VSLEEP_SEL_MASK 0x1 +#define MT6311_PMIC_VDVFS11_VSLEEP_SEL_SHIFT 2 +#define MT6311_PMIC_NI_VDVFS11_R2R_PDN_MASK 0x1 +#define MT6311_PMIC_NI_VDVFS11_R2R_PDN_SHIFT 3 +#define MT6311_PMIC_NI_VDVFS11_VSLEEP_SEL_MASK 0x1 +#define MT6311_PMIC_NI_VDVFS11_VSLEEP_SEL_SHIFT 4 +#define MT6311_PMIC_VDVFS11_TRANS_TD_MASK 0x3 +#define MT6311_PMIC_VDVFS11_TRANS_TD_SHIFT 0 +#define MT6311_PMIC_VDVFS11_TRANS_CTRL_MASK 0x3 +#define MT6311_PMIC_VDVFS11_TRANS_CTRL_SHIFT 4 +#define MT6311_PMIC_VDVFS11_TRANS_ONCE_MASK 0x1 +#define MT6311_PMIC_VDVFS11_TRANS_ONCE_SHIFT 6 +#define MT6311_PMIC_NI_VDVFS11_VOSEL_TRANS_MASK 0x1 +#define MT6311_PMIC_NI_VDVFS11_VOSEL_TRANS_SHIFT 7 +#define MT6311_PMIC_VDVFS12_DIG0_RSV0_MASK 0xFF +#define MT6311_PMIC_VDVFS12_DIG0_RSV0_SHIFT 0 +#define MT6311_PMIC_VDVFS12_EN_CTRL_MASK 0x1 +#define MT6311_PMIC_VDVFS12_EN_CTRL_SHIFT 0 +#define MT6311_PMIC_VDVFS12_VOSEL_CTRL_MASK 0x1 +#define MT6311_PMIC_VDVFS12_VOSEL_CTRL_SHIFT 1 +#define MT6311_PMIC_VDVFS12_DIG0_RSV1_MASK 0x1 +#define MT6311_PMIC_VDVFS12_DIG0_RSV1_SHIFT 2 +#define MT6311_PMIC_VDVFS12_BURST_CTRL_MASK 0x1 +#define MT6311_PMIC_VDVFS12_BURST_CTRL_SHIFT 3 +#define MT6311_PMIC_VDVFS12_EN_SEL_MASK 0x3 +#define MT6311_PMIC_VDVFS12_EN_SEL_SHIFT 0 +#define MT6311_PMIC_VDVFS12_VOSEL_SEL_MASK 0x3 +#define MT6311_PMIC_VDVFS12_VOSEL_SEL_SHIFT 2 +#define MT6311_PMIC_VDVFS12_DIG0_RSV2_MASK 0x3 +#define MT6311_PMIC_VDVFS12_DIG0_RSV2_SHIFT 4 +#define MT6311_PMIC_VDVFS12_BURST_SEL_MASK 0x3 +#define MT6311_PMIC_VDVFS12_BURST_SEL_SHIFT 6 +#define MT6311_PMIC_VDVFS12_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_EN_SHIFT 0 +#define MT6311_PMIC_VDVFS12_STBTD_MASK 0x3 +#define MT6311_PMIC_VDVFS12_STBTD_SHIFT 1 +#define MT6311_PMIC_QI_VDVFS12_STB_MASK 0x1 +#define MT6311_PMIC_QI_VDVFS12_STB_SHIFT 3 +#define MT6311_PMIC_QI_VDVFS12_EN_MASK 0x1 +#define MT6311_PMIC_QI_VDVFS12_EN_SHIFT 4 +#define MT6311_PMIC_QI_VDVFS12_OC_STATUS_MASK 0x1 +#define MT6311_PMIC_QI_VDVFS12_OC_STATUS_SHIFT 7 +#define MT6311_PMIC_VDVFS12_SFCHG_RRATE_MASK 0x7F +#define MT6311_PMIC_VDVFS12_SFCHG_RRATE_SHIFT 0 +#define MT6311_PMIC_VDVFS12_SFCHG_REN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_SFCHG_REN_SHIFT 7 +#define MT6311_PMIC_VDVFS12_SFCHG_FRATE_MASK 0x7F +#define MT6311_PMIC_VDVFS12_SFCHG_FRATE_SHIFT 0 +#define MT6311_PMIC_VDVFS12_SFCHG_FEN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_SFCHG_FEN_SHIFT 7 +#define MT6311_PMIC_VDVFS12_VOSEL_MASK 0x7F +#define MT6311_PMIC_VDVFS12_VOSEL_SHIFT 0 +#define MT6311_PMIC_VDVFS12_VOSEL_ON_MASK 0x7F +#define MT6311_PMIC_VDVFS12_VOSEL_ON_SHIFT 0 +#define MT6311_PMIC_VDVFS12_VOSEL_SLEEP_MASK 0x7F +#define MT6311_PMIC_VDVFS12_VOSEL_SLEEP_SHIFT 0 +#define MT6311_PMIC_NI_VDVFS12_VOSEL_MASK 0x7F +#define MT6311_PMIC_NI_VDVFS12_VOSEL_SHIFT 0 +#define MT6311_PMIC_VDVFS12_BURST_SLEEP_MASK 0x7 +#define MT6311_PMIC_VDVFS12_BURST_SLEEP_SHIFT 0 +#define MT6311_PMIC_QI_VDVFS12_BURST_MASK 0x7 +#define MT6311_PMIC_QI_VDVFS12_BURST_SHIFT 4 +#define MT6311_PMIC_VDVFS12_BURST_MASK 0x7 +#define MT6311_PMIC_VDVFS12_BURST_SHIFT 0 +#define MT6311_PMIC_VDVFS12_BURST_ON_MASK 0x7 +#define MT6311_PMIC_VDVFS12_BURST_ON_SHIFT 4 +#define MT6311_PMIC_VDVFS12_VSLEEP_EN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_VSLEEP_EN_SHIFT 0 +#define MT6311_PMIC_VDVFS12_R2R_PDN_MASK 0x1 +#define MT6311_PMIC_VDVFS12_R2R_PDN_SHIFT 1 +#define MT6311_PMIC_VDVFS12_VSLEEP_SEL_MASK 0x1 +#define MT6311_PMIC_VDVFS12_VSLEEP_SEL_SHIFT 2 +#define MT6311_PMIC_NI_VDVFS12_R2R_PDN_MASK 0x1 +#define MT6311_PMIC_NI_VDVFS12_R2R_PDN_SHIFT 3 +#define MT6311_PMIC_NI_VDVFS12_VSLEEP_SEL_MASK 0x1 +#define MT6311_PMIC_NI_VDVFS12_VSLEEP_SEL_SHIFT 4 +#define MT6311_PMIC_VDVFS12_TRANS_TD_MASK 0x3 +#define MT6311_PMIC_VDVFS12_TRANS_TD_SHIFT 0 +#define MT6311_PMIC_VDVFS12_TRANS_CTRL_MASK 0x3 +#define MT6311_PMIC_VDVFS12_TRANS_CTRL_SHIFT 4 +#define MT6311_PMIC_VDVFS12_TRANS_ONCE_MASK 0x1 +#define MT6311_PMIC_VDVFS12_TRANS_ONCE_SHIFT 6 +#define MT6311_PMIC_NI_VDVFS12_VOSEL_TRANS_MASK 0x1 +#define MT6311_PMIC_NI_VDVFS12_VOSEL_TRANS_SHIFT 7 +#define MT6311_PMIC_K_RST_DONE_MASK 0x1 +#define MT6311_PMIC_K_RST_DONE_SHIFT 0 +#define MT6311_PMIC_K_MAP_SEL_MASK 0x1 +#define MT6311_PMIC_K_MAP_SEL_SHIFT 1 +#define MT6311_PMIC_K_ONCE_EN_MASK 0x1 +#define MT6311_PMIC_K_ONCE_EN_SHIFT 2 +#define MT6311_PMIC_K_ONCE_MASK 0x1 +#define MT6311_PMIC_K_ONCE_SHIFT 3 +#define MT6311_PMIC_K_START_MANUAL_MASK 0x1 +#define MT6311_PMIC_K_START_MANUAL_SHIFT 4 +#define MT6311_PMIC_K_SRC_SEL_MASK 0x1 +#define MT6311_PMIC_K_SRC_SEL_SHIFT 5 +#define MT6311_PMIC_K_AUTO_EN_MASK 0x1 +#define MT6311_PMIC_K_AUTO_EN_SHIFT 6 +#define MT6311_PMIC_K_INV_MASK 0x1 +#define MT6311_PMIC_K_INV_SHIFT 7 +#define MT6311_PMIC_K_CONTROL_SMPS_MASK 0x3F +#define MT6311_PMIC_K_CONTROL_SMPS_SHIFT 0 +#define MT6311_PMIC_QI_SMPS_OSC_CAL_MASK 0x3F +#define MT6311_PMIC_QI_SMPS_OSC_CAL_SHIFT 0 +#define MT6311_PMIC_K_RESULT_MASK 0x1 +#define MT6311_PMIC_K_RESULT_SHIFT 0 +#define MT6311_PMIC_K_DONE_MASK 0x1 +#define MT6311_PMIC_K_DONE_SHIFT 1 +#define MT6311_PMIC_K_CONTROL_MASK 0x3F +#define MT6311_PMIC_K_CONTROL_SHIFT 2 +#define MT6311_PMIC_K_BUCK_CK_CNT_8_MASK 0x1 +#define MT6311_PMIC_K_BUCK_CK_CNT_8_SHIFT 0 +#define MT6311_PMIC_K_BUCK_CK_CNT_7_0_MASK 0xFF +#define MT6311_PMIC_K_BUCK_CK_CNT_7_0_SHIFT 0 +#define MT6311_PMIC_AUXADC_ADC_OUT_CH0_MASK 0x3F +#define MT6311_PMIC_AUXADC_ADC_OUT_CH0_SHIFT 0 +#define MT6311_PMIC_AUXADC_ADC_RDY_CH0_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADC_RDY_CH0_SHIFT 7 +#define MT6311_PMIC_AUXADC_ADC_OUT_CH1_MASK 0x3F +#define MT6311_PMIC_AUXADC_ADC_OUT_CH1_SHIFT 0 +#define MT6311_PMIC_AUXADC_ADC_RDY_CH1_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADC_RDY_CH1_SHIFT 7 +#define MT6311_PMIC_AUXADC_ADC_OUT_CSM_MASK 0x3F +#define MT6311_PMIC_AUXADC_ADC_OUT_CSM_SHIFT 0 +#define MT6311_PMIC_AUXADC_ADC_RDY_CSM_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADC_RDY_CSM_SHIFT 7 +#define MT6311_PMIC_AUXADC_ADC_OUT_DIV2_MASK 0x3F +#define MT6311_PMIC_AUXADC_ADC_OUT_DIV2_SHIFT 0 +#define MT6311_PMIC_AUXADC_ADC_RDY_DIV2_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADC_RDY_DIV2_SHIFT 7 +#define MT6311_PMIC_AUXADC_ADC_BUSY_IN_MASK 0xFF +#define MT6311_PMIC_AUXADC_ADC_BUSY_IN_SHIFT 0 +#define MT6311_PMIC_AUXADC_RQST_CH0_MASK 0x1 +#define MT6311_PMIC_AUXADC_RQST_CH0_SHIFT 0 +#define MT6311_PMIC_AUXADC_RQST_CH1_MASK 0x1 +#define MT6311_PMIC_AUXADC_RQST_CH1_SHIFT 1 +#define MT6311_PMIC_AUXADC_RQST_CH2_MASK 0x1 +#define MT6311_PMIC_AUXADC_RQST_CH2_SHIFT 2 +#define MT6311_PMIC_AUXADC_EN_CSM_SW_MASK 0x1 +#define MT6311_PMIC_AUXADC_EN_CSM_SW_SHIFT 0 +#define MT6311_PMIC_AUXADC_EN_CSM_SEL_MASK 0x1 +#define MT6311_PMIC_AUXADC_EN_CSM_SEL_SHIFT 1 +#define MT6311_PMIC_RG_TEST_AUXADC_MASK 0x1 +#define MT6311_PMIC_RG_TEST_AUXADC_SHIFT 2 +#define MT6311_PMIC_AUXADC_CK_AON_GPS_MASK 0x1 +#define MT6311_PMIC_AUXADC_CK_AON_GPS_SHIFT 3 +#define MT6311_PMIC_AUXADC_CK_AON_MD_MASK 0x1 +#define MT6311_PMIC_AUXADC_CK_AON_MD_SHIFT 4 +#define MT6311_PMIC_AUXADC_CK_AON_MASK 0x1 +#define MT6311_PMIC_AUXADC_CK_AON_SHIFT 5 +#define MT6311_PMIC_AUXADC_CK_ON_EXTD_MASK 0x3F +#define MT6311_PMIC_AUXADC_CK_ON_EXTD_SHIFT 0 +#define MT6311_PMIC_AUXADC_SPL_NUM_MASK 0xFF +#define MT6311_PMIC_AUXADC_SPL_NUM_SHIFT 0 +#define MT6311_PMIC_AUXADC_AVG_NUM_SMALL_MASK 0x7 +#define MT6311_PMIC_AUXADC_AVG_NUM_SMALL_SHIFT 0 +#define MT6311_PMIC_AUXADC_AVG_NUM_LARGE_MASK 0x7 +#define MT6311_PMIC_AUXADC_AVG_NUM_LARGE_SHIFT 3 +#define MT6311_PMIC_AUXADC_AVG_NUM_SEL_MASK 0xFF +#define MT6311_PMIC_AUXADC_AVG_NUM_SEL_SHIFT 0 +#define MT6311_PMIC_AUXADC_TRIM_CH0_SEL_MASK 0x3 +#define MT6311_PMIC_AUXADC_TRIM_CH0_SEL_SHIFT 0 +#define MT6311_PMIC_AUXADC_TRIM_CH1_SEL_MASK 0x3 +#define MT6311_PMIC_AUXADC_TRIM_CH1_SEL_SHIFT 2 +#define MT6311_PMIC_AUXADC_TRIM_CH2_SEL_MASK 0x3 +#define MT6311_PMIC_AUXADC_TRIM_CH2_SEL_SHIFT 4 +#define MT6311_PMIC_AUXADC_TRIM_CH3_SEL_MASK 0x3 +#define MT6311_PMIC_AUXADC_TRIM_CH3_SEL_SHIFT 6 +#define MT6311_PMIC_AUXADC_CON6_RSV0_MASK 0x1 +#define MT6311_PMIC_AUXADC_CON6_RSV0_SHIFT 0 +#define MT6311_PMIC_RG_ADC_2S_COMP_ENB_MASK 0x1 +#define MT6311_PMIC_RG_ADC_2S_COMP_ENB_SHIFT 1 +#define MT6311_PMIC_RG_ADC_TRIM_COMP_MASK 0x1 +#define MT6311_PMIC_RG_ADC_TRIM_COMP_SHIFT 2 +#define MT6311_PMIC_AUXADC_OUT_SEL_MASK 0x1 +#define MT6311_PMIC_AUXADC_OUT_SEL_SHIFT 3 +#define MT6311_PMIC_AUXADC_ADC_PWDB_SWCTRL_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADC_PWDB_SWCTRL_SHIFT 4 +#define MT6311_PMIC_AUXADC_QI_VDVFS1_CSM_EN_SW_MASK 0x1 +#define MT6311_PMIC_AUXADC_QI_VDVFS1_CSM_EN_SW_SHIFT 5 +#define MT6311_PMIC_AUXADC_QI_VDVFS11_CSM_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_QI_VDVFS11_CSM_EN_SHIFT 6 +#define MT6311_PMIC_AUXADC_QI_VDVFS12_CSM_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_QI_VDVFS12_CSM_EN_SHIFT 7 +#define MT6311_PMIC_AUXADC_SW_GAIN_TRIM_MASK 0xFF +#define MT6311_PMIC_AUXADC_SW_GAIN_TRIM_SHIFT 0 +#define MT6311_PMIC_AUXADC_SW_OFFSET_TRIM_MASK 0xFF +#define MT6311_PMIC_AUXADC_SW_OFFSET_TRIM_SHIFT 0 +#define MT6311_PMIC_AUXADC_RNG_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_RNG_EN_SHIFT 0 +#define MT6311_PMIC_AUXADC_DATA_REUSE_SEL_MASK 0x3 +#define MT6311_PMIC_AUXADC_DATA_REUSE_SEL_SHIFT 1 +#define MT6311_PMIC_AUXADC_TEST_MODE_MASK 0x1 +#define MT6311_PMIC_AUXADC_TEST_MODE_SHIFT 3 +#define MT6311_PMIC_AUXADC_BIT_SEL_MASK 0x1 +#define MT6311_PMIC_AUXADC_BIT_SEL_SHIFT 4 +#define MT6311_PMIC_AUXADC_START_SW_MASK 0x1 +#define MT6311_PMIC_AUXADC_START_SW_SHIFT 5 +#define MT6311_PMIC_AUXADC_START_SWCTRL_MASK 0x1 +#define MT6311_PMIC_AUXADC_START_SWCTRL_SHIFT 6 +#define MT6311_PMIC_AUXADC_ADC_PWDB_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADC_PWDB_SHIFT 7 +#define MT6311_PMIC_AD_AUXADC_COMP_MASK 0x1 +#define MT6311_PMIC_AD_AUXADC_COMP_SHIFT 0 +#define MT6311_PMIC_AUXADC_DA_DAC_SWCTRL_MASK 0x1 +#define MT6311_PMIC_AUXADC_DA_DAC_SWCTRL_SHIFT 1 +#define MT6311_PMIC_AUXADC_DA_DAC_MASK 0xFF +#define MT6311_PMIC_AUXADC_DA_DAC_SHIFT 0 +#define MT6311_PMIC_AUXADC_SWCTRL_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_SWCTRL_EN_SHIFT 0 +#define MT6311_PMIC_AUXADC_CHSEL_MASK 0xF +#define MT6311_PMIC_AUXADC_CHSEL_SHIFT 1 +#define MT6311_PMIC_AUXADC_ADCIN_BATON_TED_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADCIN_BATON_TED_EN_SHIFT 5 +#define MT6311_PMIC_AUXADC_ADCIN_CHRIN_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADCIN_CHRIN_EN_SHIFT 0 +#define MT6311_PMIC_AUXADC_ADCIN_BATSNS_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADCIN_BATSNS_EN_SHIFT 1 +#define MT6311_PMIC_AUXADC_ADCIN_CS_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_ADCIN_CS_EN_SHIFT 2 +#define MT6311_PMIC_AUXADC_DAC_EXTD_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_DAC_EXTD_EN_SHIFT 0 +#define MT6311_PMIC_AUXADC_DAC_EXTD_MASK 0xF +#define MT6311_PMIC_AUXADC_DAC_EXTD_SHIFT 1 +#define MT6311_PMIC_AUXADC_DIG1_RSV1_MASK 0x7 +#define MT6311_PMIC_AUXADC_DIG1_RSV1_SHIFT 5 +#define MT6311_PMIC_AUXADC_DIG0_RSV1_MASK 0xF +#define MT6311_PMIC_AUXADC_DIG0_RSV1_SHIFT 0 +#define MT6311_PMIC_AUXADC_RO_RSV1_MASK 0x1 +#define MT6311_PMIC_AUXADC_RO_RSV1_SHIFT 4 +#define MT6311_PMIC_LBAT_MAX_IRQ_MASK 0x1 +#define MT6311_PMIC_LBAT_MAX_IRQ_SHIFT 5 +#define MT6311_PMIC_LBAT_MIN_IRQ_MASK 0x1 +#define MT6311_PMIC_LBAT_MIN_IRQ_SHIFT 6 +#define MT6311_PMIC_AUXADC_AUTORPT_EN_MASK 0x1 +#define MT6311_PMIC_AUXADC_AUTORPT_EN_SHIFT 7 +#define MT6311_PMIC_AUXADC_AUTORPT_PRD_MASK 0xFF +#define MT6311_PMIC_AUXADC_AUTORPT_PRD_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_DEBT_MIN_MASK 0xFF +#define MT6311_PMIC_AUXADC_LBAT_DEBT_MIN_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_DEBT_MAX_MASK 0xFF +#define MT6311_PMIC_AUXADC_LBAT_DEBT_MAX_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_DET_PRD_7_0_MASK 0xFF +#define MT6311_PMIC_AUXADC_LBAT_DET_PRD_7_0_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_DET_PRD_15_8_MASK 0xFF +#define MT6311_PMIC_AUXADC_LBAT_DET_PRD_15_8_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_DET_PRD_19_16_MASK 0xF +#define MT6311_PMIC_AUXADC_LBAT_DET_PRD_19_16_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_MAX_IRQ_B_MASK 0x1 +#define MT6311_PMIC_AUXADC_LBAT_MAX_IRQ_B_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_EN_MAX_MASK 0x1 +#define MT6311_PMIC_AUXADC_LBAT_EN_MAX_SHIFT 1 +#define MT6311_PMIC_AUXADC_LBAT_IRQ_EN_MAX_MASK 0x1 +#define MT6311_PMIC_AUXADC_LBAT_IRQ_EN_MAX_SHIFT 2 +#define MT6311_PMIC_AUXADC_LBAT_VOLT_MAX_0_MASK 0xF +#define MT6311_PMIC_AUXADC_LBAT_VOLT_MAX_0_SHIFT 3 +#define MT6311_PMIC_AUXADC_LBAT_VOLT_MAX_1_MASK 0xFF +#define MT6311_PMIC_AUXADC_LBAT_VOLT_MAX_1_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_MIN_IRQ_B_MASK 0x1 +#define MT6311_PMIC_AUXADC_LBAT_MIN_IRQ_B_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_EN_MIN_MASK 0x1 +#define MT6311_PMIC_AUXADC_LBAT_EN_MIN_SHIFT 1 +#define MT6311_PMIC_AUXADC_LBAT_IRQ_EN_MIN_MASK 0x1 +#define MT6311_PMIC_AUXADC_LBAT_IRQ_EN_MIN_SHIFT 2 +#define MT6311_PMIC_AUXADC_LBAT_VOLT_MIN_0_MASK 0xF +#define MT6311_PMIC_AUXADC_LBAT_VOLT_MIN_0_SHIFT 3 +#define MT6311_PMIC_AUXADC_LBAT_VOLT_MIN_1_MASK 0xFF +#define MT6311_PMIC_AUXADC_LBAT_VOLT_MIN_1_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_MASK 0xFF +#define MT6311_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_SHIFT 0 +#define MT6311_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_MASK 0xFF +#define MT6311_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_SHIFT 0 +#define MT6311_PMIC_AUXADC_ENPWM1_SEL_MASK 0x1 +#define MT6311_PMIC_AUXADC_ENPWM1_SEL_SHIFT 0 +#define MT6311_PMIC_AUXADC_ENPWM1_SW_MASK 0x1 +#define MT6311_PMIC_AUXADC_ENPWM1_SW_SHIFT 1 +#define MT6311_PMIC_AUXADC_ENPWM2_SEL_MASK 0x1 +#define MT6311_PMIC_AUXADC_ENPWM2_SEL_SHIFT 2 +#define MT6311_PMIC_AUXADC_ENPWM2_SW_MASK 0x1 +#define MT6311_PMIC_AUXADC_ENPWM2_SW_SHIFT 3 +#define MT6311_PMIC_QI_VBIASN_OC_STATUS_MASK 0x1 +#define MT6311_PMIC_QI_VBIASN_OC_STATUS_SHIFT 0 +#define MT6311_PMIC_RG_VBIASN_ON_CTRL_MASK 0x1 +#define MT6311_PMIC_RG_VBIASN_ON_CTRL_SHIFT 1 +#define MT6311_PMIC_RG_VBIASN_MODE_SET_MASK 0x1 +#define MT6311_PMIC_RG_VBIASN_MODE_SET_SHIFT 2 +#define MT6311_PMIC_RG_VBIASN_MODE_CTRL_MASK 0x1 +#define MT6311_PMIC_RG_VBIASN_MODE_CTRL_SHIFT 3 +#define MT6311_PMIC_RG_VBIASN_STBTD_MASK 0x3 +#define MT6311_PMIC_RG_VBIASN_STBTD_SHIFT 4 +#define MT6311_PMIC_QI_VBIASN_MODE_MASK 0x1 +#define MT6311_PMIC_QI_VBIASN_MODE_SHIFT 6 +#define MT6311_PMIC_QI_VBIASN_EN_MASK 0x1 +#define MT6311_PMIC_QI_VBIASN_EN_SHIFT 7 +#define MT6311_PMIC_QI_VBIASN_OCFB_EN_MASK 0x1 +#define MT6311_PMIC_QI_VBIASN_OCFB_EN_SHIFT 3 +#define MT6311_PMIC_RG_VBIASN_OCFB_EN_MASK 0x1 +#define MT6311_PMIC_RG_VBIASN_OCFB_EN_SHIFT 5 +#define MT6311_PMIC_LDO_DEGTD_SEL_MASK 0x3 +#define MT6311_PMIC_LDO_DEGTD_SEL_SHIFT 6 +#define MT6311_PMIC_RG_VBIASN_DIS_SEL_MASK 0x3 +#define MT6311_PMIC_RG_VBIASN_DIS_SEL_SHIFT 0 +#define MT6311_PMIC_RG_VBIASN_TRANS_EN_MASK 0x1 +#define MT6311_PMIC_RG_VBIASN_TRANS_EN_SHIFT 2 +#define MT6311_PMIC_RG_VBIASN_TRANS_CTRL_MASK 0x3 +#define MT6311_PMIC_RG_VBIASN_TRANS_CTRL_SHIFT 4 +#define MT6311_PMIC_RG_VBIASN_TRANS_ONCE_MASK 0x1 +#define MT6311_PMIC_RG_VBIASN_TRANS_ONCE_SHIFT 6 +#define MT6311_PMIC_QI_VBIASN_CHR_MASK 0x1 +#define MT6311_PMIC_QI_VBIASN_CHR_SHIFT 7 +#define MT6311_PMIC_RG_VBIASN_EN_MASK 0x1 +#define MT6311_PMIC_RG_VBIASN_EN_SHIFT 0 +#define MT6311_PMIC_LDO_RSV_MASK 0xFF +#define MT6311_PMIC_LDO_RSV_SHIFT 0 +#define MT6311_PMIC_FQMTR_TCKSEL_MASK 0x7 +#define MT6311_PMIC_FQMTR_TCKSEL_SHIFT 0 +#define MT6311_PMIC_FQMTR_BUSY_MASK 0x1 +#define MT6311_PMIC_FQMTR_BUSY_SHIFT 3 +#define MT6311_PMIC_FQMTR_EN_MASK 0x1 +#define MT6311_PMIC_FQMTR_EN_SHIFT 7 +#define MT6311_PMIC_FQMTR_WINSET_1_MASK 0xFF +#define MT6311_PMIC_FQMTR_WINSET_1_SHIFT 0 +#define MT6311_PMIC_FQMTR_WINSET_0_MASK 0xFF +#define MT6311_PMIC_FQMTR_WINSET_0_SHIFT 0 +#define MT6311_PMIC_FQMTR_DATA_1_MASK 0xFF +#define MT6311_PMIC_FQMTR_DATA_1_SHIFT 0 +#define MT6311_PMIC_FQMTR_DATA_0_MASK 0xFF +#define MT6311_PMIC_FQMTR_DATA_0_SHIFT 0 + + + +/* + *APIs + */ +extern unsigned char mt6311_get_cid(void); +extern unsigned char mt6311_get_swcid(void); +extern unsigned char mt6311_get_hwcid(void); +extern void mt6311_set_gpio0_dir(unsigned char val); +extern void mt6311_set_gpio1_dir(unsigned char val); +extern void mt6311_set_gpio0_dinv(unsigned char val); +extern void mt6311_set_gpio1_dinv(unsigned char val); +extern void mt6311_set_gpio0_dout(unsigned char val); +extern void mt6311_set_gpio1_dout(unsigned char val); +extern unsigned char mt6311_get_gpio0_din(void); +extern unsigned char mt6311_get_gpio1_din(void); +extern void mt6311_set_gpio0_mode(unsigned char val); +extern void mt6311_set_gpio1_mode(unsigned char val); +extern unsigned char mt6311_get_test_out(void); +extern void mt6311_set_rg_mon_grp_sel(unsigned char val); +extern void mt6311_set_rg_mon_flag_sel(unsigned char val); +extern void mt6311_set_dig_testmode(unsigned char val); +extern void mt6311_set_pmu_testmode(unsigned char val); +extern void mt6311_set_rg_srclken_in_hw_mode(unsigned char val); +extern void mt6311_set_rg_srclken_in_en(unsigned char val); +extern void mt6311_set_rg_buck_lp_hw_mode(unsigned char val); +extern void mt6311_set_rg_buck_lp_en(unsigned char val); +extern void mt6311_set_rg_osc_en(unsigned char val); +extern void mt6311_set_rg_osc_en_hw_mode(unsigned char val); +extern void mt6311_set_rg_srclken_in_sync_en(unsigned char val); +extern void mt6311_set_rg_strup_rsv_hw_mode(unsigned char val); +extern void mt6311_set_rg_buck_ref_ck_tstsel(unsigned char val); +extern void mt6311_set_rg_fqmtr_ck_tstsel(unsigned char val); +extern void mt6311_set_rg_smps_ck_tstsel(unsigned char val); +extern void mt6311_set_rg_pmu75k_ck_tstsel(unsigned char val); +extern void mt6311_set_rg_smps_ck_tst_dis(unsigned char val); +extern void mt6311_set_rg_pmu75k_ck_tst_dis(unsigned char val); +extern void mt6311_set_rg_buck_ana_auto_off_dis(unsigned char val); +extern void mt6311_set_rg_buck_ref_ck_pdn(unsigned char val); +extern void mt6311_set_rg_buck_ck_pdn(unsigned char val); +extern void mt6311_set_rg_buck_1m_ck_pdn(unsigned char val); +extern void mt6311_set_rg_intrp_ck_pdn(unsigned char val); +extern void mt6311_set_rg_efuse_ck_pdn(unsigned char val); +extern void mt6311_set_rg_strup_75k_ck_pdn(unsigned char val); +extern void mt6311_set_rg_buck_ana_ck_pdn(unsigned char val); +extern void mt6311_set_rg_trim_75k_ck_pdn(unsigned char val); +extern void mt6311_set_rg_auxadc_ck_pdn(unsigned char val); +extern void mt6311_set_rg_auxadc_1m_ck_pdn(unsigned char val); +extern void mt6311_set_rg_stb_75k_ck_pdn(unsigned char val); +extern void mt6311_set_rg_fqmtr_ck_pdn(unsigned char val); +extern void mt6311_set_top_ckpdn_con2_rsv(unsigned char val); +extern void mt6311_set_rg_buck_1m_ck_pdn_hwen(unsigned char val); +extern void mt6311_set_rg_efuse_ck_pdn_hwen(unsigned char val); +extern void mt6311_set_rg_auxadc_rst(unsigned char val); +extern void mt6311_set_rg_fqmtr_rst(unsigned char val); +extern void mt6311_set_rg_clk_trim_rst(unsigned char val); +extern void mt6311_set_rg_efuse_man_rst(unsigned char val); +extern void mt6311_set_rg_wdtrstb_mode(unsigned char val); +extern void mt6311_set_rg_wdtrstb_en(unsigned char val); +extern void mt6311_set_wdtrstb_status_clr(unsigned char val); +extern unsigned char mt6311_get_wdtrstb_status(void); +extern void mt6311_set_rg_int_pol(unsigned char val); +extern void mt6311_set_rg_int_en(unsigned char val); +extern void mt6311_set_i2c_config(unsigned char val); +extern unsigned char mt6311_get_rg_lbat_min_int_status(void); +extern unsigned char mt6311_get_rg_lbat_max_int_status(void); +extern unsigned char mt6311_get_rg_thr_l_int_status(void); +extern unsigned char mt6311_get_rg_thr_h_int_status(void); +extern unsigned char mt6311_get_rg_buck_oc_int_status(void); +extern void mt6311_set_thr_det_dis(unsigned char val); +extern void mt6311_set_thr_hwpdn_en(unsigned char val); +extern void mt6311_set_strup_dig0_rsv0(unsigned char val); +extern void mt6311_set_rg_usbdl_en(unsigned char val); +extern void mt6311_set_rg_test_strup(unsigned char val); +extern void mt6311_set_rg_test_strup_thr_in(unsigned char val); +extern void mt6311_set_strup_dig1_rsv0(unsigned char val); +extern void mt6311_set_thr_test(unsigned char val); +extern unsigned char mt6311_get_pmu_thr_deb(void); +extern unsigned char mt6311_get_pmu_thr_status(void); +extern void mt6311_set_strup_pwron(unsigned char val); +extern void mt6311_set_strup_pwron_sel(unsigned char val); +extern void mt6311_set_bias_gen_en(unsigned char val); +extern void mt6311_set_bias_gen_en_sel(unsigned char val); +extern void mt6311_set_rtc_xosc32_enb_sw(unsigned char val); +extern void mt6311_set_rtc_xosc32_enb_sel(unsigned char val); +extern void mt6311_set_strup_dig_io_pg_force(unsigned char val); +extern void mt6311_set_dduvlo_deb_en(unsigned char val); +extern void mt6311_set_pwrbb_deb_en(unsigned char val); +extern void mt6311_set_strup_osc_en(unsigned char val); +extern void mt6311_set_strup_osc_en_sel(unsigned char val); +extern void mt6311_set_strup_ft_ctrl(unsigned char val); +extern void mt6311_set_strup_pwron_force(unsigned char val); +extern void mt6311_set_bias_gen_en_force(unsigned char val); +extern void mt6311_set_vdvfs11_pg_h2l_en(unsigned char val); +extern void mt6311_set_vdvfs12_pg_h2l_en(unsigned char val); +extern void mt6311_set_vbiasn_pg_h2l_en(unsigned char val); +extern void mt6311_set_vdvfs11_pg_enb(unsigned char val); +extern void mt6311_set_vdvfs12_pg_enb(unsigned char val); +extern void mt6311_set_vbiasn_pg_enb(unsigned char val); +extern void mt6311_set_rg_ext_pmic_en_pg_enb(unsigned char val); +extern void mt6311_set_rg_pre_pwron_en(unsigned char val); +extern void mt6311_set_rg_pre_pwron_swctrl(unsigned char val); +extern void mt6311_set_clr_just_rst(unsigned char val); +extern void mt6311_set_uvlo_l2h_deb_en(unsigned char val); +extern void mt6311_set_rg_bgr_test_ckin_en(unsigned char val); +extern unsigned char mt6311_get_qi_osc_en(void); +extern void mt6311_set_rg_strup_pmu_pwron_sel(unsigned char val); +extern void mt6311_set_rg_strup_pmu_pwron_en(unsigned char val); +extern void mt6311_set_strup_auxadc_start_sw(unsigned char val); +extern void mt6311_set_strup_auxadc_rstb_sw(unsigned char val); +extern void mt6311_set_strup_auxadc_start_sel(unsigned char val); +extern void mt6311_set_strup_auxadc_rstb_sel(unsigned char val); +extern void mt6311_set_strup_pwroff_preoff_en(unsigned char val); +extern void mt6311_set_strup_pwroff_seq_en(unsigned char val); +extern void mt6311_set_rg_sys_latch_en_swctrl(unsigned char val); +extern void mt6311_set_rg_sys_latch_en(unsigned char val); +extern void mt6311_set_rg_onoff_en_swctrl(unsigned char val); +extern void mt6311_set_rg_onoff_en(unsigned char val); +extern void mt6311_set_rg_strup_pwron_cond_sel(unsigned char val); +extern void mt6311_set_rg_strup_pwron_cond_en(unsigned char val); +extern unsigned char mt6311_get_strup_pg_status(void); +extern void mt6311_set_strup_pg_status_clr(unsigned char val); +extern void mt6311_set_rg_rsv_swreg(unsigned char val); +extern unsigned char mt6311_get_vdvfs11_pg_deb(void); +extern unsigned char mt6311_get_vdvfs12_pg_deb(void); +extern unsigned char mt6311_get_vbiasn_pg_deb(void); +extern unsigned char mt6311_get_strup_ro_rsv0(void); +extern void mt6311_set_rg_strup_thr_110_clr(unsigned char val); +extern void mt6311_set_rg_strup_thr_125_clr(unsigned char val); +extern void mt6311_set_rg_strup_thr_110_irq_en(unsigned char val); +extern void mt6311_set_rg_strup_thr_125_irq_en(unsigned char val); +extern unsigned char mt6311_get_rg_strup_thr_110_irq_status(void); +extern unsigned char mt6311_get_rg_strup_thr_125_irq_status(void); +extern void mt6311_set_rg_thermal_en(unsigned char val); +extern void mt6311_set_rg_thermal_en_sel(unsigned char val); +extern unsigned char mt6311_get_rg_osc_75k_trim(void); +extern void mt6311_set_osc_75k_trim(unsigned char val); +extern void mt6311_set_rg_osc_75k_trim_en(unsigned char val); +extern void mt6311_set_rg_osc_75k_trim_rate(unsigned char val); +extern void mt6311_set_rg_efuse_addr(unsigned char val); +extern void mt6311_set_rg_efuse_din(unsigned char val); +extern void mt6311_set_rg_efuse_dm(unsigned char val); +extern void mt6311_set_rg_efuse_pgm(unsigned char val); +extern void mt6311_set_rg_efuse_pgm_en(unsigned char val); +extern void mt6311_set_rg_efuse_prog_pkey(unsigned char val); +extern void mt6311_set_rg_efuse_rd_pkey(unsigned char val); +extern void mt6311_set_rg_efuse_pgm_src(unsigned char val); +extern void mt6311_set_rg_efuse_din_src(unsigned char val); +extern void mt6311_set_rg_efuse_rd_trig(unsigned char val); +extern void mt6311_set_rg_rd_rdy_bypass(unsigned char val); +extern void mt6311_set_rg_skip_efuse_out(unsigned char val); +extern unsigned char mt6311_get_rg_efuse_rd_ack(void); +extern unsigned char mt6311_get_rg_efuse_rd_busy(void); +extern void mt6311_set_rg_efuse_write_mode(unsigned char val); +extern unsigned char mt6311_get_rg_efuse_dout_0_7(void); +extern unsigned char mt6311_get_rg_efuse_dout_8_15(void); +extern unsigned char mt6311_get_rg_efuse_dout_16_23(void); +extern unsigned char mt6311_get_rg_efuse_dout_24_31(void); +extern unsigned char mt6311_get_rg_efuse_dout_32_39(void); +extern unsigned char mt6311_get_rg_efuse_dout_40_47(void); +extern unsigned char mt6311_get_rg_efuse_dout_48_55(void); +extern unsigned char mt6311_get_rg_efuse_dout_56_63(void); +extern unsigned char mt6311_get_rg_efuse_dout_64_71(void); +extern unsigned char mt6311_get_rg_efuse_dout_72_79(void); +extern unsigned char mt6311_get_rg_efuse_dout_80_87(void); +extern unsigned char mt6311_get_rg_efuse_dout_88_95(void); +extern unsigned char mt6311_get_rg_efuse_dout_96_103(void); +extern unsigned char mt6311_get_rg_efuse_dout_104_111(void); +extern unsigned char mt6311_get_rg_efuse_dout_112_119(void); +extern unsigned char mt6311_get_rg_efuse_dout_120_127(void); +extern void mt6311_set_rg_efuse_val_0_7(unsigned char val); +extern void mt6311_set_rg_efuse_val_8_15(unsigned char val); +extern void mt6311_set_rg_efuse_val_16_23(unsigned char val); +extern void mt6311_set_rg_efuse_val_24_31(unsigned char val); +extern void mt6311_set_rg_efuse_val_32_39(unsigned char val); +extern void mt6311_set_rg_efuse_val_40_47(unsigned char val); +extern void mt6311_set_rg_efuse_val_48_55(unsigned char val); +extern void mt6311_set_rg_efuse_val_56_63(unsigned char val); +extern void mt6311_set_rg_efuse_val_64_71(unsigned char val); +extern void mt6311_set_rg_efuse_val_72_79(unsigned char val); +extern void mt6311_set_rg_efuse_val_80_87(unsigned char val); +extern void mt6311_set_rg_efuse_val_88_95(unsigned char val); +extern void mt6311_set_rg_efuse_val_96_103(unsigned char val); +extern void mt6311_set_rg_efuse_val_104_111(unsigned char val); +extern void mt6311_set_rg_efuse_val_112_119(unsigned char val); +extern void mt6311_set_rg_efuse_val_120_127(unsigned char val); +extern void mt6311_set_buck_dig0_rsv0(unsigned char val); +extern void mt6311_set_vsleep_src0_8(unsigned char val); +extern void mt6311_set_vsleep_src1(unsigned char val); +extern void mt6311_set_vsleep_src0_7_0(unsigned char val); +extern void mt6311_set_r2r_src0_8(unsigned char val); +extern void mt6311_set_r2r_src1(unsigned char val); +extern void mt6311_set_r2r_src0_7_0(unsigned char val); +extern void mt6311_set_buck_osc_sel_src0_8(unsigned char val); +extern void mt6311_set_srclken_dly_src1(unsigned char val); +extern void mt6311_set_buck_osc_sel_src0_7_0(unsigned char val); +extern unsigned char mt6311_get_qi_vdvfs12_dig_mon(void); +extern unsigned char mt6311_get_qi_vdvfs11_dig_mon(void); +extern void mt6311_set_vdvfs11_oc_en(unsigned char val); +extern void mt6311_set_vdvfs11_oc_deg_en(unsigned char val); +extern void mt6311_set_vdvfs11_oc_wnd(unsigned char val); +extern void mt6311_set_vdvfs11_oc_thd(unsigned char val); +extern void mt6311_set_vdvfs12_oc_en(unsigned char val); +extern void mt6311_set_vdvfs12_oc_deg_en(unsigned char val); +extern void mt6311_set_vdvfs12_oc_wnd(unsigned char val); +extern void mt6311_set_vdvfs12_oc_thd(unsigned char val); +extern void mt6311_set_vdvfs11_oc_flag_clr(unsigned char val); +extern void mt6311_set_vdvfs12_oc_flag_clr(unsigned char val); +extern void mt6311_set_vdvfs11_oc_rg_status_clr(unsigned char val); +extern void mt6311_set_vdvfs12_oc_rg_status_clr(unsigned char val); +extern void mt6311_set_vdvfs11_oc_flag_clr_sel(unsigned char val); +extern void mt6311_set_vdvfs12_oc_flag_clr_sel(unsigned char val); +extern unsigned char mt6311_get_vdvfs11_oc_status(void); +extern unsigned char mt6311_get_vdvfs12_oc_status(void); +extern void mt6311_set_vdvfs11_oc_int_en(unsigned char val); +extern void mt6311_set_vdvfs12_oc_int_en(unsigned char val); +extern void mt6311_set_vdvfs11_en_oc_sdn_sel(unsigned char val); +extern void mt6311_set_vdvfs12_en_oc_sdn_sel(unsigned char val); +extern void mt6311_set_buck_test_mode(unsigned char val); +extern void mt6311_set_buck_dig1_rsv0(unsigned char val); +extern void mt6311_set_qi_vdvfs11_vsleep(unsigned char val); +extern void mt6311_set_qi_vdvfs12_vsleep(unsigned char val); +extern void mt6311_set_buck_ana_dig0_rsv0(unsigned char val); +extern void mt6311_set_rg_thrdet_sel(unsigned char val); +extern void mt6311_set_rg_strup_thr_sel(unsigned char val); +extern void mt6311_set_rg_thr_tmode(unsigned char val); +extern void mt6311_set_rg_strup_iref_trim(unsigned char val); +extern void mt6311_set_rg_uvlo_vthl(unsigned char val); +extern void mt6311_set_rg_uvlo_vthh(unsigned char val); +extern void mt6311_set_rg_bgr_unchop(unsigned char val); +extern void mt6311_set_rg_bgr_unchop_ph(unsigned char val); +extern void mt6311_set_rg_bgr_rsel(unsigned char val); +extern void mt6311_set_rg_bgr_trim(unsigned char val); +extern void mt6311_set_rg_bgr_test_en(unsigned char val); +extern void mt6311_set_rg_bgr_test_rstb(unsigned char val); +extern void mt6311_set_rg_vdvfs11_trimh(unsigned char val); +extern void mt6311_set_rg_vdvfs11_triml(unsigned char val); +extern void mt6311_set_rg_vdvfs12_trimh(unsigned char val); +extern void mt6311_set_rg_vdvfs12_triml(unsigned char val); +extern void mt6311_set_rg_vdvfs11_vsleep(unsigned char val); +extern void mt6311_set_rg_vdvfs12_vsleep(unsigned char val); +extern void mt6311_set_rg_bgr_osc_cal(unsigned char val); +extern void mt6311_set_rg_strup_rsv(unsigned char val); +extern void mt6311_set_rg_vref_lp_mode(unsigned char val); +extern void mt6311_set_rg_testmode_swen(unsigned char val); +extern void mt6311_set_rg_vdig18_vosel(unsigned char val); +extern void mt6311_set_rg_vdig18_cal(unsigned char val); +extern void mt6311_set_rg_osc_sel(unsigned char val); +extern void mt6311_set_rg_vbiasn_ndis_en(unsigned char val); +extern void mt6311_set_rg_vbiasn_vosel(unsigned char val); +extern void mt6311_set_rg_vdvfs11_rc(unsigned char val); +extern void mt6311_set_rg_vdvfs12_rc(unsigned char val); +extern void mt6311_set_rg_vdvfs11_csr(unsigned char val); +extern void mt6311_set_rg_vdvfs12_csr(unsigned char val); +extern void mt6311_set_rg_vdvfs11_pfm_csr(unsigned char val); +extern void mt6311_set_rg_vdvfs12_pfm_csr(unsigned char val); +extern void mt6311_set_rg_vdvfs11_slp(unsigned char val); +extern void mt6311_set_rg_vdvfs12_slp(unsigned char val); +extern void mt6311_set_rg_vdvfs11_uvp_en(unsigned char val); +extern void mt6311_set_rg_vdvfs12_uvp_en(unsigned char val); +extern void mt6311_set_rg_vdvfs11_modeset(unsigned char val); +extern void mt6311_set_rg_vdvfs12_modeset(unsigned char val); +extern void mt6311_set_rg_vdvfs11_ndis_en(unsigned char val); +extern void mt6311_set_rg_vdvfs12_ndis_en(unsigned char val); +extern void mt6311_set_rg_vdvfs11_trans_bst(unsigned char val); +extern void mt6311_set_rg_vdvfs12_trans_bst(unsigned char val); +extern void mt6311_set_rg_vdvfs11_csm_n(unsigned char val); +extern void mt6311_set_rg_vdvfs11_csm_p(unsigned char val); +extern void mt6311_set_rg_vdvfs12_csm_n(unsigned char val); +extern void mt6311_set_rg_vdvfs12_csm_p(unsigned char val); +extern void mt6311_set_rg_vdvfs11_zxos_trim(unsigned char val); +extern void mt6311_set_rg_vdvfs12_zxos_trim(unsigned char val); +extern void mt6311_set_rg_vdvfs11_oc_off(unsigned char val); +extern void mt6311_set_rg_vdvfs12_oc_off(unsigned char val); +extern void mt6311_set_rg_vdvfs11_phs_shed_trim(unsigned char val); +extern void mt6311_set_rg_vdvfs11_f2phs(unsigned char val); +extern void mt6311_set_rg_vdvfs11_rs_force_off(unsigned char val); +extern void mt6311_set_rg_vdvfs12_rs_force_off(unsigned char val); +extern void mt6311_set_rg_vdvfs11_tm_en(unsigned char val); +extern void mt6311_set_rg_vdvfs11_tm_ugsns(unsigned char val); +extern void mt6311_set_rg_vdvfs1_fbn_sel(unsigned char val); +extern unsigned char mt6311_get_rgs_vdvfs11_enpwm_status(void); +extern unsigned char mt6311_get_rgs_vdvfs12_enpwm_status(void); +extern unsigned char mt6311_get_ni_vdvfs1_count(void); +extern void mt6311_set_vdvfs11_dig0_rsv0(unsigned char val); +extern void mt6311_set_vdvfs11_en_ctrl(unsigned char val); +extern void mt6311_set_vdvfs11_vosel_ctrl(unsigned char val); +extern void mt6311_set_vdvfs11_dig0_rsv1(unsigned char val); +extern void mt6311_set_vdvfs11_burst_ctrl(unsigned char val); +extern void mt6311_set_vdvfs11_en_sel(unsigned char val); +extern void mt6311_set_vdvfs11_vosel_sel(unsigned char val); +extern void mt6311_set_vdvfs11_dig0_rsv2(unsigned char val); +extern void mt6311_set_vdvfs11_burst_sel(unsigned char val); +extern void mt6311_set_vdvfs11_en(unsigned char val); +extern void mt6311_set_vdvfs11_stbtd(unsigned char val); +extern unsigned char mt6311_get_qi_vdvfs11_stb(void); +extern unsigned char mt6311_get_qi_vdvfs11_en(void); +extern unsigned char mt6311_get_qi_vdvfs11_oc_status(void); +extern void mt6311_set_vdvfs11_sfchg_rrate(unsigned char val); +extern void mt6311_set_vdvfs11_sfchg_ren(unsigned char val); +extern void mt6311_set_vdvfs11_sfchg_frate(unsigned char val); +extern void mt6311_set_vdvfs11_sfchg_fen(unsigned char val); +extern void mt6311_set_vdvfs11_vosel(unsigned char val); +extern void mt6311_set_vdvfs11_vosel_on(unsigned char val); +extern void mt6311_set_vdvfs11_vosel_sleep(unsigned char val); +extern unsigned char mt6311_get_ni_vdvfs11_vosel(void); +extern void mt6311_set_vdvfs11_burst_sleep(unsigned char val); +extern unsigned char mt6311_get_qi_vdvfs11_burst(void); +extern void mt6311_set_vdvfs11_burst(unsigned char val); +extern void mt6311_set_vdvfs11_burst_on(unsigned char val); +extern void mt6311_set_vdvfs11_vsleep_en(unsigned char val); +extern void mt6311_set_vdvfs11_r2r_pdn(unsigned char val); +extern void mt6311_set_vdvfs11_vsleep_sel(unsigned char val); +extern unsigned char mt6311_get_ni_vdvfs11_r2r_pdn(void); +extern unsigned char mt6311_get_ni_vdvfs11_vsleep_sel(void); +extern void mt6311_set_vdvfs11_trans_td(unsigned char val); +extern void mt6311_set_vdvfs11_trans_ctrl(unsigned char val); +extern void mt6311_set_vdvfs11_trans_once(unsigned char val); +extern unsigned char mt6311_get_ni_vdvfs11_vosel_trans(void); +extern void mt6311_set_vdvfs12_dig0_rsv0(unsigned char val); +extern void mt6311_set_vdvfs12_en_ctrl(unsigned char val); +extern void mt6311_set_vdvfs12_vosel_ctrl(unsigned char val); +extern void mt6311_set_vdvfs12_dig0_rsv1(unsigned char val); +extern void mt6311_set_vdvfs12_burst_ctrl(unsigned char val); +extern void mt6311_set_vdvfs12_en_sel(unsigned char val); +extern void mt6311_set_vdvfs12_vosel_sel(unsigned char val); +extern void mt6311_set_vdvfs12_dig0_rsv2(unsigned char val); +extern void mt6311_set_vdvfs12_burst_sel(unsigned char val); +extern void mt6311_set_vdvfs12_en(unsigned char val); +extern void mt6311_set_vdvfs12_stbtd(unsigned char val); +extern unsigned char mt6311_get_qi_vdvfs12_stb(void); +extern unsigned char mt6311_get_qi_vdvfs12_en(void); +extern unsigned char mt6311_get_qi_vdvfs12_oc_status(void); +extern void mt6311_set_vdvfs12_sfchg_rrate(unsigned char val); +extern void mt6311_set_vdvfs12_sfchg_ren(unsigned char val); +extern void mt6311_set_vdvfs12_sfchg_frate(unsigned char val); +extern void mt6311_set_vdvfs12_sfchg_fen(unsigned char val); +extern void mt6311_set_vdvfs12_vosel(unsigned char val); +extern void mt6311_set_vdvfs12_vosel_on(unsigned char val); +extern void mt6311_set_vdvfs12_vosel_sleep(unsigned char val); +extern unsigned char mt6311_get_ni_vdvfs12_vosel(void); +extern void mt6311_set_vdvfs12_burst_sleep(unsigned char val); +extern unsigned char mt6311_get_qi_vdvfs12_burst(void); +extern void mt6311_set_vdvfs12_burst(unsigned char val); +extern void mt6311_set_vdvfs12_burst_on(unsigned char val); +extern void mt6311_set_vdvfs12_vsleep_en(unsigned char val); +extern void mt6311_set_vdvfs12_r2r_pdn(unsigned char val); +extern void mt6311_set_vdvfs12_vsleep_sel(unsigned char val); +extern unsigned char mt6311_get_ni_vdvfs12_r2r_pdn(void); +extern unsigned char mt6311_get_ni_vdvfs12_vsleep_sel(void); +extern void mt6311_set_vdvfs12_trans_td(unsigned char val); +extern void mt6311_set_vdvfs12_trans_ctrl(unsigned char val); +extern void mt6311_set_vdvfs12_trans_once(unsigned char val); +extern unsigned char mt6311_get_ni_vdvfs12_vosel_trans(void); +extern void mt6311_set_k_rst_done(unsigned char val); +extern void mt6311_set_k_map_sel(unsigned char val); +extern void mt6311_set_k_once_en(unsigned char val); +extern void mt6311_set_k_once(unsigned char val); +extern void mt6311_set_k_start_manual(unsigned char val); +extern void mt6311_set_k_src_sel(unsigned char val); +extern void mt6311_set_k_auto_en(unsigned char val); +extern void mt6311_set_k_inv(unsigned char val); +extern void mt6311_set_k_control_smps(unsigned char val); +extern unsigned char mt6311_get_qi_smps_osc_cal(void); +extern unsigned char mt6311_get_k_result(void); +extern unsigned char mt6311_get_k_done(void); +extern unsigned char mt6311_get_k_control(void); +extern void mt6311_set_k_buck_ck_cnt_8(unsigned char val); +extern void mt6311_set_k_buck_ck_cnt_7_0(unsigned char val); +extern unsigned char mt6311_get_auxadc_adc_out_ch0(void); +extern unsigned char mt6311_get_auxadc_adc_rdy_ch0(void); +extern unsigned char mt6311_get_auxadc_adc_out_ch1(void); +extern unsigned char mt6311_get_auxadc_adc_rdy_ch1(void); +extern unsigned char mt6311_get_auxadc_adc_out_csm(void); +extern unsigned char mt6311_get_auxadc_adc_rdy_csm(void); +extern unsigned char mt6311_get_auxadc_adc_out_div2(void); +extern unsigned char mt6311_get_auxadc_adc_rdy_div2(void); +extern unsigned char mt6311_get_auxadc_adc_busy_in(void); +extern void mt6311_set_auxadc_rqst_ch0(unsigned char val); +extern void mt6311_set_auxadc_rqst_ch1(unsigned char val); +extern void mt6311_set_auxadc_rqst_ch2(unsigned char val); +extern void mt6311_set_auxadc_en_csm_sw(unsigned char val); +extern void mt6311_set_auxadc_en_csm_sel(unsigned char val); +extern void mt6311_set_rg_test_auxadc(unsigned char val); +extern void mt6311_set_auxadc_ck_aon_gps(unsigned char val); +extern void mt6311_set_auxadc_ck_aon_md(unsigned char val); +extern void mt6311_set_auxadc_ck_aon(unsigned char val); +extern void mt6311_set_auxadc_ck_on_extd(unsigned char val); +extern void mt6311_set_auxadc_spl_num(unsigned char val); +extern void mt6311_set_auxadc_avg_num_small(unsigned char val); +extern void mt6311_set_auxadc_avg_num_large(unsigned char val); +extern void mt6311_set_auxadc_avg_num_sel(unsigned char val); +extern void mt6311_set_auxadc_trim_ch0_sel(unsigned char val); +extern void mt6311_set_auxadc_trim_ch1_sel(unsigned char val); +extern void mt6311_set_auxadc_trim_ch2_sel(unsigned char val); +extern void mt6311_set_auxadc_trim_ch3_sel(unsigned char val); +extern void mt6311_set_auxadc_con6_rsv0(unsigned char val); +extern void mt6311_set_rg_adc_2s_comp_enb(unsigned char val); +extern void mt6311_set_rg_adc_trim_comp(unsigned char val); +extern void mt6311_set_auxadc_out_sel(unsigned char val); +extern void mt6311_set_auxadc_adc_pwdb_swctrl(unsigned char val); +extern void mt6311_set_auxadc_qi_vdvfs1_csm_en_sw(unsigned char val); +extern void mt6311_set_auxadc_qi_vdvfs11_csm_en(unsigned char val); +extern void mt6311_set_auxadc_qi_vdvfs12_csm_en(unsigned char val); +extern void mt6311_set_auxadc_sw_gain_trim(unsigned char val); +extern void mt6311_set_auxadc_sw_offset_trim(unsigned char val); +extern void mt6311_set_auxadc_rng_en(unsigned char val); +extern void mt6311_set_auxadc_data_reuse_sel(unsigned char val); +extern void mt6311_set_auxadc_test_mode(unsigned char val); +extern void mt6311_set_auxadc_bit_sel(unsigned char val); +extern void mt6311_set_auxadc_start_sw(unsigned char val); +extern void mt6311_set_auxadc_start_swctrl(unsigned char val); +extern void mt6311_set_auxadc_adc_pwdb(unsigned char val); +extern unsigned char mt6311_get_ad_auxadc_comp(void); +extern void mt6311_set_auxadc_da_dac_swctrl(unsigned char val); +extern void mt6311_set_auxadc_da_dac(unsigned char val); +extern void mt6311_set_auxadc_swctrl_en(unsigned char val); +extern void mt6311_set_auxadc_chsel(unsigned char val); +extern void mt6311_set_auxadc_adcin_baton_ted_en(unsigned char val); +extern void mt6311_set_auxadc_adcin_chrin_en(unsigned char val); +extern void mt6311_set_auxadc_adcin_batsns_en(unsigned char val); +extern void mt6311_set_auxadc_adcin_cs_en(unsigned char val); +extern void mt6311_set_auxadc_dac_extd_en(unsigned char val); +extern void mt6311_set_auxadc_dac_extd(unsigned char val); +extern void mt6311_set_auxadc_dig1_rsv1(unsigned char val); +extern void mt6311_set_auxadc_dig0_rsv1(unsigned char val); +extern unsigned char mt6311_get_auxadc_ro_rsv1(void); +extern unsigned char mt6311_get_lbat_max_irq(void); +extern unsigned char mt6311_get_lbat_min_irq(void); +extern void mt6311_set_auxadc_autorpt_en(unsigned char val); +extern void mt6311_set_auxadc_autorpt_prd(unsigned char val); +extern void mt6311_set_auxadc_lbat_debt_min(unsigned char val); +extern void mt6311_set_auxadc_lbat_debt_max(unsigned char val); +extern void mt6311_set_auxadc_lbat_det_prd_7_0(unsigned char val); +extern void mt6311_set_auxadc_lbat_det_prd_15_8(unsigned char val); +extern void mt6311_set_auxadc_lbat_det_prd_19_16(unsigned char val); +extern unsigned char mt6311_get_auxadc_lbat_max_irq_b(void); +extern void mt6311_set_auxadc_lbat_en_max(unsigned char val); +extern void mt6311_set_auxadc_lbat_irq_en_max(unsigned char val); +extern void mt6311_set_auxadc_lbat_volt_max_0(unsigned char val); +extern void mt6311_set_auxadc_lbat_volt_max_1(unsigned char val); +extern unsigned char mt6311_get_auxadc_lbat_min_irq_b(void); +extern void mt6311_set_auxadc_lbat_en_min(unsigned char val); +extern void mt6311_set_auxadc_lbat_irq_en_min(unsigned char val); +extern void mt6311_set_auxadc_lbat_volt_min_0(unsigned char val); +extern void mt6311_set_auxadc_lbat_volt_min_1(unsigned char val); +extern unsigned char mt6311_get_auxadc_lbat_debounce_count_max(void); +extern unsigned char mt6311_get_auxadc_lbat_debounce_count_min(void); +extern void mt6311_set_auxadc_enpwm1_sel(unsigned char val); +extern void mt6311_set_auxadc_enpwm1_sw(unsigned char val); +extern void mt6311_set_auxadc_enpwm2_sel(unsigned char val); +extern void mt6311_set_auxadc_enpwm2_sw(unsigned char val); +extern unsigned char mt6311_get_qi_vbiasn_oc_status(void); +extern void mt6311_set_rg_vbiasn_on_ctrl(unsigned char val); +extern void mt6311_set_rg_vbiasn_mode_set(unsigned char val); +extern void mt6311_set_rg_vbiasn_mode_ctrl(unsigned char val); +extern void mt6311_set_rg_vbiasn_stbtd(unsigned char val); +extern unsigned char mt6311_get_qi_vbiasn_mode(void); +extern unsigned char mt6311_get_qi_vbiasn_en(void); +extern unsigned char mt6311_get_qi_vbiasn_ocfb_en(void); +extern void mt6311_set_rg_vbiasn_ocfb_en(unsigned char val); +extern void mt6311_set_ldo_degtd_sel(unsigned char val); +extern void mt6311_set_rg_vbiasn_dis_sel(unsigned char val); +extern void mt6311_set_rg_vbiasn_trans_en(unsigned char val); +extern void mt6311_set_rg_vbiasn_trans_ctrl(unsigned char val); +extern void mt6311_set_rg_vbiasn_trans_once(unsigned char val); +extern unsigned char mt6311_get_qi_vbiasn_chr(void); +extern void mt6311_set_rg_vbiasn_en(unsigned char val); +extern void mt6311_set_ldo_rsv(unsigned char val); +extern void mt6311_set_fqmtr_tcksel(unsigned char val); +extern unsigned char mt6311_get_fqmtr_busy(void); +extern void mt6311_set_fqmtr_en(unsigned char val); +extern void mt6311_set_fqmtr_winset_1(unsigned char val); +extern void mt6311_set_fqmtr_winset_0(unsigned char val); +extern unsigned char mt6311_get_fqmtr_data_1(void); +extern unsigned char mt6311_get_fqmtr_data_0(void); + +extern void mt6311_clr_thr_l_int_status(void); +extern void mt6311_clr_thr_h_int_status(void); +extern unsigned int mt6311_get_thr_l_int_status(void); +extern unsigned int mt6311_get_thr_h_int_status(void); + +extern void mt6311_thr_l_int_handler(void); +extern void mt6311_thr_h_int_handler(void); +/*---move from mt6311.c---*/ +extern unsigned int upmu_get_reg_value(unsigned int reg); +extern void battery_oc_protect_reinit(void); +/*------------------------*/ +extern unsigned int mt_gpio_to_irq(unsigned int gpio); +extern int mt_gpio_set_debounce(unsigned gpio, unsigned debounce); + +#endif /* _mt6311_SW_H_*/ + diff --git a/drivers/misc/mediatek/power/mt6755/mtk_bif_intf.c b/drivers/misc/mediatek/power/mt6755/mtk_bif_intf.c new file mode 100644 index 0000000000000000000000000000000000000000..05f13f309056db848cc73a11463277ef37d2c3fc --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/mtk_bif_intf.c @@ -0,0 +1,613 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#include +#include +#include +#include +#include +#include "mtk_bif_intf.h" + +#ifdef CONFIG_MTK_BIF_SUPPORT +static bool bif_exist; +static bool bif_checked; + +/* BIF related functions */ +#define BC (0x400) +#define SDA (0x600) +#define ERA (0x100) +#define WRA (0x200) +#define RRA (0x300) +#define WD (0x000) + +/* Bus commands */ +#define BUSRESET (0x00) +#define RBL2 (0x22) +#define RBL4 (0x24) + +/* BIF slave address */ +#define MW3790 (0x00) +#define MW3790_VBAT (0x0114) +#define MW3790_TBAT (0x0193) + +static int bif_set_cmd(u16 bif_cmd[], int bif_cmd_len) +{ + int i = 0, con_index = 0; + u32 ret = 0; + + for (i = 0; i < bif_cmd_len; i++) { + ret = pmic_config_interface(MT6351_BIF_CON0 + con_index, + bif_cmd[i], 0x07FF, 0); + if (ret != 0) { + battery_log(BAT_LOG_CRTI, "%s: failed, bif_cmd[%d]\n", + __func__, i); + return -EIO; + } + con_index += 0x2; + } + battery_log(BAT_LOG_FULL, "%s: OK\n", __func__); + + return 0; +} + +static int bif_reset_irq(void) +{ + int ret = 0; + u32 reg_irq = 0, retry_cnt = 0; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + pmic_set_register_value(PMIC_BIF_IRQ_CLR, 1); + + /* Wait until IRQ is cleared */ + do { + reg_irq = pmic_get_register_value(PMIC_BIF_IRQ); + retry_cnt++; + usleep_range(50, 100); + } while ((reg_irq != 0) && (retry_cnt < 5)); + + if (reg_irq == 0) + battery_log(BAT_LOG_FULL, "%s: OK\n", __func__); + else { + ret = -EIO; + battery_log(BAT_LOG_CRTI, + "%s: failed, PMIC_BIF_IRQ_CLR = 0x%02X\n", + __func__, reg_irq); + } + + pmic_set_register_value(PMIC_BIF_IRQ_CLR, 0); + + return ret; +} + +static int bif_waitfor_slave(void) +{ + int ret = 0; + u32 reg_irq = 0, retry_cnt = 0; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + do { + reg_irq = pmic_get_register_value(PMIC_BIF_IRQ); + retry_cnt++; + usleep_range(100, 500); + } while ((reg_irq == 0) && (retry_cnt < 5)); + + + /* Success */ + if (reg_irq == 1) + battery_log(BAT_LOG_FULL, + "%s: OK, retry_cnt = %d\n", __func__, retry_cnt); + else { /* Failed */ + ret = -EIO; + battery_log(BAT_LOG_CRTI, + "%s: failed, PMIC_BIF_IRQ = 0x%02X, retry_cnt = %d\n", + __func__, reg_irq, retry_cnt); + } + + /* Reset IRQ */ + ret = bif_reset_irq(); + + return ret; +} + +static int bif_powerup_slave(void) +{ + int ret = 0; + u32 bat_lost = 0, total_valid = 0, timeout = 0, retry_cnt = 0; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + do { + pmic_set_register_value(PMIC_BIF_POWER_UP, 1); + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 1); + + ret = bif_waitfor_slave(); + if (ret < 0) + goto _err; + + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 0); + pmic_set_register_value(PMIC_BIF_POWER_UP, 0); + + bat_lost = pmic_get_register_value(PMIC_BIF_BAT_LOST); + total_valid = pmic_get_register_value(PMIC_BIF_TOTAL_VALID); + timeout = pmic_get_register_value(PMIC_BIF_TIMEOUT); + + retry_cnt++; + } while ((bat_lost == 1 || total_valid == 1 || timeout == 1) + && (retry_cnt < 50)); + + /* Success */ + if (bat_lost == 0 && total_valid == 0 && timeout == 0) { + battery_log(BAT_LOG_FULL, + "%s: OK, retry_cnt = %d\n", __func__, retry_cnt); + return ret; + } + +_err: + /* Failed */ + battery_log(BAT_LOG_CRTI, "%s: failed, retry_cnt = %d, ret = %d\n", + __func__, retry_cnt, ret); + return ret; +} + +static int bif_reset_slave(void) +{ + int ret = 0; + u16 bif_cmd[1] = {0}; + u32 bat_lost = 0, total_valid = 0, timeout = 0, retry_cnt = 0; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + + /* Set command sequence */ + bif_cmd[0] = BC | BUSRESET; + ret = bif_set_cmd(bif_cmd, 1); + if (ret < 0) + goto _err; + + do { + /* Command setting : 1 write command */ + pmic_set_register_value(PMIC_BIF_TRASFER_NUM, 1); + pmic_set_register_value(PMIC_BIF_COMMAND_TYPE, 0); + + /* Command set trigger */ + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 1); + + /* Command sent, wait for slave */ + ret = bif_waitfor_slave(); + if (ret < 0) + goto _err; + + /* Command clear trigger */ + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 0); + + /* Check transaction completeness */ + bat_lost = pmic_get_register_value(PMIC_BIF_BAT_LOST); + total_valid = pmic_get_register_value(PMIC_BIF_TOTAL_VALID); + timeout = pmic_get_register_value(PMIC_BIF_TIMEOUT); + + retry_cnt++; + } while ((bat_lost == 1 || total_valid == 1 || timeout == 1) + && (retry_cnt < 50)); + + + if (bat_lost == 0 && total_valid == 0 && timeout == 0) { + battery_log(BAT_LOG_FULL, "%s: OK, retry_cnt = %d\n", + __func__, retry_cnt); + return ret; + } + + +_err: + battery_log(BAT_LOG_CRTI, "%s: failed, retry_cnt = %d, ret = %d\n", + __func__, retry_cnt, ret); + return ret; +} + +/* BIF write 8 transaction */ +static int bif_write8(u16 addr, u8 *data) +{ + int ret = 0; + u8 era, wra; + u16 bif_cmd[4] = {0, 0, 0, 0}; + u32 bat_lost = 0, total_valid = 0, timeout = 0, retry_cnt = 0; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + + + /* Set Extended & Write Register Address */ + era = (addr & 0xFF00) >> 8; + wra = addr & 0x00FF; + battery_log(BAT_LOG_FULL, "%s: ERA = 0x%02x, WRA = 0x%02x\n", + __func__, era, wra); + + /* Set command sequence */ + bif_cmd[0] = SDA | MW3790; + bif_cmd[1] = ERA | era; /* Extended Register Address [15:8] */ + bif_cmd[2] = WRA | wra; /* Write Register Address [7:0] */ + bif_cmd[3] = WD | *data; /* Data */ + + + ret = bif_set_cmd(bif_cmd, 4); + if (ret < 0) + goto _err; + + do { + /* Set 1 byte write command */ + pmic_set_register_value(PMIC_BIF_TRASFER_NUM, 4); + pmic_set_register_value(PMIC_BIF_COMMAND_TYPE, 0); + + /* Set trigger to start transaction */ + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 1); + + /* Command sent, wait for slave */ + ret = bif_waitfor_slave(); + if (ret < 0) + goto _err; + + /* Clear trigger */ + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 0); + + /* Check transaction completeness */ + bat_lost = pmic_get_register_value(PMIC_BIF_BAT_LOST); + total_valid = pmic_get_register_value(PMIC_BIF_TOTAL_VALID); + timeout = pmic_get_register_value(PMIC_BIF_TIMEOUT); + + retry_cnt++; + } while ((bat_lost == 1 || total_valid == 1 || timeout == 1) + && (retry_cnt < 50)); + + + if (bat_lost == 0 && total_valid == 0 && timeout == 0) { + battery_log(BAT_LOG_FULL, "%s: OK, retry_cnt = %d\n", + __func__, retry_cnt); + return ret; + } + +_err: + battery_log(BAT_LOG_CRTI, "%s: failed, retry_cnt = %d, ret = %d", + __func__, retry_cnt, ret); + battery_log(BAT_LOG_CRTI, + "%s: bat_lost = %d, timeout = %d, total_valid = %d\n", + __func__, bat_lost, timeout, total_valid); + + return ret; +} + +/* BIF read 8 transaction */ +static int bif_read8(u16 addr, u8 *data) +{ + int ret = 0; + u8 era, rra, _data; + u16 bif_cmd[3] = {0, 0, 0}; + u32 bat_lost = 0, total_valid = 0, timeout = 0, retry_cnt = 0; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + + /* Set Extended & Read Register Address */ + era = (addr & 0xFF00) >> 8; + rra = addr & 0x00FF; + battery_log(BAT_LOG_FULL, "%s: ERA = 0x%02x, RRA = 0x%02x\n", + __func__, era, rra); + + /* Set command sequence */ + bif_cmd[0] = SDA | MW3790; + bif_cmd[1] = ERA | era; /* [15:8] */ + bif_cmd[2] = RRA | rra; /* [ 7:0] */ + + ret = bif_set_cmd(bif_cmd, 3); + if (ret < 0) + goto _err; + do { + /* Command setting : 3 transactions for 1 byte read command(1) */ + pmic_set_register_value(PMIC_BIF_TRASFER_NUM, 3); + pmic_set_register_value(PMIC_BIF_COMMAND_TYPE, 1); + pmic_set_register_value(PMIC_BIF_READ_EXPECT_NUM, 1); + + /* Command set trigger */ + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 1); + + /* Command sent; wait for slave */ + ret = bif_waitfor_slave(); + if (ret < 0) + goto _err; + + /* Command clear trigger */ + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 0); + + /* Check transaction completeness */ + bat_lost = pmic_get_register_value(PMIC_BIF_BAT_LOST); + total_valid = pmic_get_register_value(PMIC_BIF_TOTAL_VALID); + timeout = pmic_get_register_value(PMIC_BIF_TIMEOUT); + + retry_cnt++; + } while ((bat_lost == 1 || total_valid == 1 || timeout == 1) + && (retry_cnt < 50)); + + + /* Read data */ + if (bat_lost == 0 && total_valid == 0 && timeout == 0) { + _data = pmic_get_register_value(PMIC_BIF_DATA_0); + battery_log(BAT_LOG_FULL, + "%s: OK, data = 0x%02X, retry_cnt = %d\n", + __func__, _data, retry_cnt); + *data = _data & 0xFF; + return ret; + } + +_err: + battery_log(BAT_LOG_CRTI, "%s: failed, retry_cnt = %d, ret = %d\n", + __func__, retry_cnt, ret); + battery_log(BAT_LOG_CRTI, + "%s: failed, bat_lost = %d, timeout = %d, totoal_valid = %d\n", + __func__, bat_lost, timeout, total_valid); + + return ret; +} + +/* Bif read 16 transaction*/ +static int bif_read16(u16 addr, u16 *data) +{ + int ret = 0; + u8 era, rra; + u16 bif_cmd[4] = {0, 0, 0, 0}; + u8 _data[2] = {0, 0}; /* 2 bytes data */ + u32 bat_lost = 0, total_valid = 0, timeout = 0, retry_cnt = 0; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + + /* Set Extended & Read Register Address */ + era = (addr & 0xFF00) >> 8; + rra = addr & 0x00FF; + battery_log(BAT_LOG_FULL, "%s: ERA = 0x%02x, RRA= 0x%02x\n", + __func__, era, rra); + + /* Set command sequence */ + bif_cmd[0] = SDA | MW3790; + bif_cmd[1] = BC | RBL2; /* Read back 2 bytes */ + bif_cmd[2] = ERA | era; /* [15:8] */ + bif_cmd[3] = RRA | rra; /* [ 7:0] */ + + + ret = bif_set_cmd(bif_cmd, 4); + if (ret < 0) + goto _err; + do { + /* Command setting : 4 transactions for 2 byte read command(1) */ + pmic_set_register_value(PMIC_BIF_TRASFER_NUM, 4); + pmic_set_register_value(PMIC_BIF_COMMAND_TYPE, 1); + pmic_set_register_value(PMIC_BIF_READ_EXPECT_NUM, 2); + + /* Command set trigger */ + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 1); + + /* Command sent; wait for slave */ + ret = bif_waitfor_slave(); + if (ret < 0) + goto _err; + + /* Command clear trigger */ + pmic_set_register_value(PMIC_BIF_TRASACT_TRIGGER, 0); + + /* Check transaction completeness */ + bat_lost = pmic_get_register_value(PMIC_BIF_BAT_LOST); + total_valid = pmic_get_register_value(PMIC_BIF_TOTAL_VALID); + timeout = pmic_get_register_value(PMIC_BIF_TIMEOUT); + + retry_cnt++; + } while ((bat_lost == 1 || total_valid == 1 || timeout == 1) + && (retry_cnt < 50)); + + + /* Read data */ + if (bat_lost == 0 && total_valid == 0 && timeout == 0) { + _data[0] = pmic_get_register_value(PMIC_BIF_DATA_0); + _data[1] = pmic_get_register_value(PMIC_BIF_DATA_1); + *data = ((_data[0] & 0xFF) << 8) | (_data[1] & 0xFF); + battery_log(BAT_LOG_FULL, + "%s: OK, data = 0x%02x, 0x%02x, retry_cnt = %d\n", + __func__, _data[0], _data[1], retry_cnt); + return ret; + } + +_err: + battery_log(BAT_LOG_CRTI, "%s: failed, retry_cnt = %d, ret = %d\n", + __func__, retry_cnt, ret); + battery_log(BAT_LOG_CRTI, + "%s: bat_lost = %d, timeout = %d, totoal_valid = %d\n", + __func__, bat_lost, timeout, total_valid); + + return ret; +} + +static int bif_adc_enable(void) +{ + int ret = 0; + u8 reg = 0x18; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + ret = bif_write8(0x0110, ®); + if (ret < 0) + goto _err; + + mdelay(50); + + reg = 0x98; + ret = bif_write8(0x0110, ®); + if (ret < 0) + goto _err; + + mdelay(50); + + battery_log(BAT_LOG_FULL, "%s: OK\n", __func__); + return ret; + +_err: + battery_log(BAT_LOG_CRTI, "%s: failed, ret = %d\n", __func__, ret); + return ret; +} + +/* BIF init function called only at the first time*/ +static int bif_init(void) +{ + int ret = 0; + + /* Disable BIF interrupt */ + pmic_set_register_value(PMIC_INT_CON0_CLR, 0x4000); + + /* Enable BIF clock */ + pmic_set_register_value(PMIC_TOP_CKPDN_CON2_CLR, 0x0070); + + /* Enable HT protection */ + pmic_set_register_value(PMIC_RG_BATON_HT_EN, 1); + + mdelay(50); + + /* Enable RX filter function */ + pmic_set_register_value(MT6351_PMIC_BIF_RX_DEG_EN, 0x8000); + pmic_set_register_value(MT6351_PMIC_BIF_RX_DEG_WND, 0x17); + pmic_set_register_value(PMIC_RG_BATON_EN, 0x1); + pmic_set_register_value(PMIC_BATON_TDET_EN, 0x1); + pmic_set_register_value(PMIC_RG_BATON_HT_EN_DLY_TIME, 0x1); + + + /* Wake up BIF slave */ + ret = bif_powerup_slave(); + if (ret < 0) + goto _err; + + mdelay(10); + + /* Reset BIF slave */ + ret = bif_reset_slave(); + if (ret < 0) + goto _err; + + mdelay(50); + + battery_log(BAT_LOG_FULL, "%s: OK\n", __func__); + return ret; + +_err: + battery_log(BAT_LOG_CRTI, "%s: failed, ret = %d", __func__, ret); + return ret; +} + +int mtk_bif_init(void) +{ + int ret = 0; + u32 vbat = 0; + + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + + if (bif_checked) + return ret; + + /* Initiate BIF */ + ret = bif_init(); + if (ret < 0) + goto _err; + + /* Read VBAT to check existence of BIF */ + ret = mtk_bif_get_vbat(&vbat); + if (ret == 0 && vbat != 0) { + battery_log(BAT_LOG_CRTI, "%s: BIF battery detected\n", + __func__); + bif_exist = true; + bif_checked = true; + return ret; + } + +_err: + battery_log(BAT_LOG_CRTI, "%s: BIF battery _NOT_ detected\n", __func__); + bif_exist = false; + bif_checked = true; + + return ret; +} + +int mtk_bif_get_vbat(unsigned int *vbat) +{ + int ret = 0; + u16 _vbat = 0; + + /* Prevent ADC & BIF read at the same time */ + lockadcch3(); + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + + if (bif_checked && !bif_exist) { + ret = -ENOTSUPP; + goto _err; + } + + /* Enable ADC */ + ret = bif_adc_enable(); + if (ret < 0) + goto _err; + + /* Read Data */ + ret = bif_read16(MW3790_VBAT, &_vbat); + if (ret < 0 || _vbat == 0) + goto _err; + + *vbat = _vbat; + battery_log(BAT_LOG_FULL, "%s: OK, vbat = %dmV\n", __func__, _vbat); + unlockadcch3(); + return ret; + +_err: + *vbat = 0; + battery_log(BAT_LOG_CRTI, "%s: failed, ret = %d\n", __func__, ret); + unlockadcch3(); + return ret; +} + +int mtk_bif_get_tbat(int *tbat) +{ + int ret = 0; + s8 _tbat = 0; + + /* Prevent ADC & BIF read at the same time */ + lockadcch3(); + battery_log(BAT_LOG_FULL, "%s: starts\n", __func__); + + if (!bif_exist) { + ret = -ENOTSUPP; + goto _err; + } + + /* Enable ADC */ + ret = bif_adc_enable(); + if (ret < 0) + goto _err; + + /* Read Data */ + ret = bif_read8(MW3790_TBAT, &_tbat); + if (ret < 0) + goto _err; + + *tbat = _tbat; + battery_log(BAT_LOG_FULL, "%s: OK, tbat = %d(degree)\n", + __func__, _tbat); + unlockadcch3(); + return ret; + +_err: + *tbat = 0; + battery_log(BAT_LOG_CRTI, "%s: failed, ret = %d\n", __func__, ret); + unlockadcch3(); + return ret; +} + +bool mtk_bif_is_hw_exist(void) +{ + return bif_exist; +} +#endif diff --git a/drivers/misc/mediatek/power/mt6755/mtk_bif_intf.h b/drivers/misc/mediatek/power/mt6755/mtk_bif_intf.h new file mode 100644 index 0000000000000000000000000000000000000000..04563bd33cd6b857eb9ddc1327c7f6ff77c2763e --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/mtk_bif_intf.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef __MTK_BIF_INTF_H +#define __MTK_BIF_INTF_H + +#ifdef CONFIG_MTK_BIF_SUPPORT +#include + +extern int mtk_bif_init(void); +extern int mtk_bif_get_vbat(unsigned int *vbat); +extern int mtk_bif_get_tbat(int *tbat); +extern bool mtk_bif_is_hw_exist(void); + +#else /* Not CONFIG_MTK_BIF_SUPPORT */ + +static inline int mtk_bif_init(void) +{ + return -ENOTSUPP; +} + +static inline int mtk_bif_get_vbat(unsigned int *vbat) +{ + *vbat = 0; + return -ENOTSUPP; +} + +static inline int mtk_bif_get_tbat(int *tbat) +{ + *tbat = 0; + return -ENOTSUPP; +} + +static inline bool mtk_bif_is_hw_exist(void) +{ + return false; +} + +#endif /* CONFIG_MTK_BIF_SUPPORT */ +#endif /* __MTK_BIF_INTF_H */ diff --git a/drivers/misc/mediatek/power/mt6755/ncp1854.c b/drivers/misc/mediatek/power/mt6755/ncp1854.c new file mode 100755 index 0000000000000000000000000000000000000000..d824e744f99e3dd44133105d277aebfedbf43807 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/ncp1854.c @@ -0,0 +1,740 @@ +#include +#include +#include +#include +#include +#include +#include /* For init/exit macros */ +#include /* For MODULE_ marcros */ +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include +#include "ncp1854.h" + +/********************************************************** + * + * [I2C Slave Setting] + * + *********************************************************/ +#define NCP1854_SLAVE_ADDR_WRITE 0x6C +#define NCP1854_SLAVE_ADDR_READ 0x6D + +static struct i2c_client *new_client; +static const struct i2c_device_id ncp1854_i2c_id[] = { {"ncp1854", 0}, {} }; + +kal_bool chargin_hw_init_done = KAL_FALSE; +static int ncp1854_driver_probe(struct i2c_client *client, const struct i2c_device_id *id); + +#ifdef CONFIG_OF +static const struct of_device_id ncp1854_of_match[] = { + {.compatible = "mediatek,swithing_charger",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, ncp1854_of_match); +#endif + +static struct i2c_driver ncp1854_driver = { + .driver = { + .name = "ncp1854", +#ifdef CONFIG_OF + .of_match_table = ncp1854_of_match, +#endif + }, + .probe = ncp1854_driver_probe, + .id_table = ncp1854_i2c_id, +}; + +/********************************************************** + * + * [Global Variable] + * + *********************************************************/ +unsigned char ncp1854_reg[ncp1854_REG_NUM] = { 0 }; + +static DEFINE_MUTEX(ncp1854_i2c_access); +/********************************************************** + * + * [I2C Function For Read/Write ncp1854] + * + *********************************************************/ +int ncp1854_read_byte(unsigned char cmd, unsigned char *returnData) +{ + char cmd_buf[1] = { 0x00 }; + char readData = 0; + int ret = 0; + + mutex_lock(&ncp1854_i2c_access); + + /* new_client->addr = ((new_client->addr) & I2C_MASK_FLAG) | I2C_WR_FLAG; */ + new_client->ext_flag = + ((new_client->ext_flag) & I2C_MASK_FLAG) | I2C_WR_FLAG | I2C_DIRECTION_FLAG; + + cmd_buf[0] = cmd; + ret = i2c_master_send(new_client, &cmd_buf[0], (1 << 8 | 1)); + if (ret < 0) { + /* new_client->addr = new_client->addr & I2C_MASK_FLAG; */ + new_client->ext_flag = 0; + + mutex_unlock(&ncp1854_i2c_access); + return 0; + } + + readData = cmd_buf[0]; + *returnData = readData; + + /* new_client->addr = new_client->addr & I2C_MASK_FLAG; */ + new_client->ext_flag = 0; + + mutex_unlock(&ncp1854_i2c_access); + return 1; +} + +int ncp1854_write_byte(unsigned char cmd, unsigned char writeData) +{ + char write_data[2] = { 0 }; + int ret = 0; + + mutex_lock(&ncp1854_i2c_access); + + write_data[0] = cmd; + write_data[1] = writeData; + + new_client->ext_flag = ((new_client->ext_flag) & I2C_MASK_FLAG) | I2C_DIRECTION_FLAG; + + ret = i2c_master_send(new_client, write_data, 2); + if (ret < 0) { + new_client->ext_flag = 0; + mutex_unlock(&ncp1854_i2c_access); + return 0; + } + + new_client->ext_flag = 0; + mutex_unlock(&ncp1854_i2c_access); + return 1; +} + +/********************************************************** + * + * [Read / Write Function] + * + *********************************************************/ +unsigned int ncp1854_read_interface(unsigned char RegNum, unsigned char *val, unsigned char MASK, + unsigned char SHIFT) +{ + unsigned char ncp1854_reg = 0; + int ret = 0; + + battery_log(BAT_LOG_FULL, "--------------------------------------------------\n"); + + ret = ncp1854_read_byte(RegNum, &ncp1854_reg); + + battery_log(BAT_LOG_FULL, "[ncp1854_read_interface] Reg[%x]=0x%x\n", RegNum, ncp1854_reg); + + ncp1854_reg &= (MASK << SHIFT); + *val = (ncp1854_reg >> SHIFT); + battery_log(BAT_LOG_FULL, "[ncp1854_read_interface] Val=0x%x\n", *val); + + return ret; +} + +unsigned int ncp1854_config_interface(unsigned char RegNum, unsigned char val, unsigned char MASK, + unsigned char SHIFT) +{ + unsigned char ncp1854_reg = 0; + int ret = 0; + + battery_log(BAT_LOG_FULL, "--------------------------------------------------\n"); + + ret = ncp1854_read_byte(RegNum, &ncp1854_reg); + battery_log(BAT_LOG_FULL, "[ncp1854_config_interface] Reg[%x]=0x%x\n", RegNum, ncp1854_reg); + + ncp1854_reg &= ~(MASK << SHIFT); + ncp1854_reg |= (val << SHIFT); + + ret = ncp1854_write_byte(RegNum, ncp1854_reg); + battery_log(BAT_LOG_FULL, "[ncp18546_config_interface] Write Reg[%x]=0x%x\n", RegNum, ncp1854_reg); + + /* Check */ + /* ncp1854_read_byte(RegNum, &ncp1854_reg); */ + /* battery_log(BAT_LOG_FULL, "[ncp1854_config_interface] Check Reg[%x]=0x%x\n", RegNum, ncp1854_reg); */ + + return ret; +} + +/********************************************************** + * + * [Internal Function] + * + *********************************************************/ +/* CON0 */ +unsigned int ncp1854_get_chip_status(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = ncp1854_read_interface((unsigned char) (NCP1854_CON0), + (unsigned char *) (&val), + (unsigned char) (CON0_STATE_MASK), (unsigned char) (CON0_STATE_SHIFT) + ); + return val; +} + +unsigned int ncp1854_get_batfet(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = ncp1854_read_interface((unsigned char) (NCP1854_CON0), + (unsigned char *) (&val), + (unsigned char) (CON0_BATFET_MASK), (unsigned char) (CON0_BATFET_SHIFT) + ); + return val; +} + +unsigned int ncp1854_get_statint(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = ncp1854_read_interface((unsigned char) (NCP1854_CON0), + (unsigned char *) (&val), + (unsigned char) (CON0_STATINT_MASK), + (unsigned char) (CON0_STATINT_SHIFT) + ); + return val; +} + +unsigned int ncp1854_get_faultint(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = ncp1854_read_interface((unsigned char) (NCP1854_CON0), + (unsigned char *) (&val), + (unsigned char) (CON0_FAULTINT_MASK), + (unsigned char) (CON0_FAULTINT_SHIFT) + ); + return val; +} + +/* CON1 */ +void ncp1854_set_reset(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1), + (unsigned char) (val), + (unsigned char) (CON1_REG_RST_MASK), + (unsigned char) (CON1_REG_RST_SHIFT) + ); +} + +void ncp1854_set_chg_en(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1), + (unsigned char) (val), + (unsigned char) (CON1_CHG_EN_MASK), + (unsigned char) (CON1_CHG_EN_SHIFT) + ); +} + +void ncp1854_set_otg_en(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1), + (unsigned char) (val), + (unsigned char) (CON1_OTG_EN_MASK), + (unsigned char) (CON1_OTG_EN_SHIFT) + ); +} + +unsigned int ncp1854_get_otg_en(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = ncp1854_read_interface((unsigned char) (NCP1854_CON1), + (unsigned char *) (&val), + (unsigned char) (CON1_OTG_EN_MASK), (unsigned char) (CON1_OTG_EN_SHIFT) + ); + return val; +} + +void ncp1854_set_fctry_mode(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1), + (unsigned char) (val), + (unsigned char) (CON1_FCTRY_MOD_MASK), + (unsigned char) (CON1_FCTRY_MOD_SHIFT) + ); +} + +void ncp1854_set_tj_warn_opt(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1), + (unsigned char) (val), + (unsigned char) (CON1_TJ_WARN_OPT_MASK), + (unsigned char) (CON1_TJ_WARN_OPT_SHIFT) + ); +} + +unsigned int ncp1854_get_usb_cfg(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = ncp1854_read_interface((unsigned char) (NCP1854_CON1), + (unsigned char *) (&val), + (unsigned char) (CON1_JEITA_OPT_MASK), + (unsigned char) (CON1_JEITA_OPT_SHIFT) + ); + return val; +} + +void ncp1854_set_tchg_rst(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1), + (unsigned char) (val), + (unsigned char) (CON1_TCHG_RST_MASK), + (unsigned char) (CON1_TCHG_RST_SHIFT) + ); +} + +void ncp1854_set_int_mask(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1), + (unsigned char) (val), + (unsigned char) (CON1_INT_MASK_MASK), + (unsigned char) (CON1_INT_MASK_SHIFT) + ); +} + +/* CON2 */ +void ncp1854_set_wdto_dis(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2), + (unsigned char) (val), + (unsigned char) (CON2_WDTO_DIS_MASK), + (unsigned char) (CON2_WDTO_DIS_SHIFT) + ); +} + +void ncp1854_set_chgto_dis(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2), + (unsigned char) (val), + (unsigned char) (CON2_CHGTO_DIS_MASK), + (unsigned char) (CON2_CHGTO_DIS_SHIFT) + ); +} + +void ncp1854_set_pwr_path(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2), + (unsigned char) (val), + (unsigned char) (CON2_PWR_PATH_MASK), + (unsigned char) (CON2_PWR_PATH_SHIFT) + ); +} + +void ncp1854_set_trans_en(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2), + (unsigned char) (val), + (unsigned char) (CON2_TRANS_EN_MASK), + (unsigned char) (CON2_TRANS_EN_SHIFT) + ); +} + +void ncp1854_set_iinset_pin_en(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2), + (unsigned char) (val), + (unsigned char) (CON2_IINSET_PIN_EN_MASK), + (unsigned char) (CON2_IINSET_PIN_EN_SHIFT) + ); +} + +void ncp1854_set_iinlim_en(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2), + (unsigned char) (val), + (unsigned char) (CON2_IINLIM_EN_MASK), + (unsigned char) (CON2_IINLIM_EN_SHIFT) + ); +} + +void ncp1854_set_aicl_en(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2), + (unsigned char) (val), + (unsigned char) (CON2_AICL_EN_MASK), + (unsigned char) (CON2_AICL_EN_SHIFT) + ); +} + +/* CON8 */ +unsigned int ncp1854_get_vfet_ok(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = ncp1854_read_interface((unsigned char) (NCP1854_CON8), + (unsigned char *) (&val), + (unsigned char) (CON8_VFET_OK_MASK), + (unsigned char) (CON8_VFET_OK_SHIFT) + ); + return val; +} + + +/* CON14 */ +void ncp1854_set_ctrl_vbat(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON14), + (unsigned char) (val), + (unsigned char) (CON14_CTRL_VBAT_MASK), + (unsigned char) (CON14_CTRL_VBAT_SHIFT) + ); +} + +/* CON15 */ +void ncp1854_set_ichg_high(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON15), + (unsigned char) (val), + (unsigned char) (CON15_ICHG_HIGH_MASK), + (unsigned char) (CON15_ICHG_HIGH_SHIFT) + ); +} + +void ncp1854_set_ieoc(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON15), + (unsigned char) (val), + (unsigned char) (CON15_IEOC_MASK), (unsigned char) (CON15_IEOC_SHIFT) + ); +} + +void ncp1854_set_ichg(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON15), + (unsigned char) (val), + (unsigned char) (CON15_ICHG_MASK), (unsigned char) (CON15_ICHG_SHIFT) + ); +} + +unsigned int ncp1854_get_ichg(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = ncp1854_read_interface((unsigned char) NCP1854_CON15, + (unsigned char *) &val, + (unsigned char) CON15_ICHG_MASK, (unsigned char) CON15_ICHG_SHIFT); + return val; +} + +/* CON16 */ +void ncp1854_set_iweak(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON16), + (unsigned char) (val), + (unsigned char) (CON16_IWEAK_MASK), + (unsigned char) (CON16_IWEAK_SHIFT) + ); +} + +void ncp1854_set_ctrl_vfet(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON16), + (unsigned char) (val), + (unsigned char) (CON16_CTRL_VFET_MASK), + (unsigned char) (CON16_CTRL_VFET_SHIFT) + ); +} + +void ncp1854_set_iinlim(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON16), + (unsigned char) (val), + (unsigned char) (CON16_IINLIM_MASK), + (unsigned char) (CON16_IINLIM_SHIFT) + ); +} + +/* CON17 */ +void ncp1854_set_iinlim_ta(unsigned int val) +{ + unsigned int ret = 0; + + ret = ncp1854_config_interface((unsigned char) (NCP1854_CON17), + (unsigned char) (val), + (unsigned char) (CON17_IINLIM_TA_MASK), + (unsigned char) (CON17_IINLIM_TA_SHIFT) + ); +} + +/********************************************************** + * + * [Internal Function] + * + *********************************************************/ +void ncp1854_dump_register(void) +{ + int i = 0; + + for (i = 0; i < ncp1854_REG_NUM; i++) { + if ((i == 3) || (i == 4) || (i == 5) || (i == 6)) /* do not dump read clear status register */ + continue; + if ((i == 10) || (i == 11) || (i == 12) || (i == 13)) /* do not dump interrupt mask bit register */ + continue; + ncp1854_read_byte(i, &ncp1854_reg[i]); + battery_log(BAT_LOG_CRTI, "[ncp1854_dump_register] Reg[0x%X]=0x%X\n", i, ncp1854_reg[i]); + } +} + +void ncp1854_read_register(int i) +{ + ncp1854_read_byte(i, &ncp1854_reg[i]); + battery_log(BAT_LOG_FULL, "[ncp1854_read_register] Reg[0x%X]=0x%X\n", i, ncp1854_reg[i]); +} + +#if 0 +static void ncp1854_parse_customer_setting(void) +{ +#ifdef CONFIG_OF + unsigned int val; + struct device_node *np; + struct pinctrl *pinctrl; + struct pinctrl_state *pinctrl_drvvbus_init; + struct pinctrl_state *pinctrl_drvvbus_low; + + /* check customer setting */ + np = new_client->dev.of_node; + if (np) { + if (of_property_read_u32(np, "disable_ncp1854_fctry_mod", &val) == 0) { + if (val) + ncp1854_set_fctry_mode(0x0); + + battery_log(BAT_LOG_FULL, "%s: disable factory mode, %d\n", __func__, val); + } + } + + pinctrl = devm_pinctrl_get(&new_client->dev); + if (IS_ERR(pinctrl)) { + battery_log(BAT_LOG_CRTI, "[%s]Cannot find drvvbus pinctrl, err=%d\n", + __func__, (int)PTR_ERR(pinctrl)); + return; + } + + pinctrl_drvvbus_init = pinctrl_lookup_state(pinctrl, "drvvbus_init"); + if (IS_ERR(pinctrl_drvvbus_init)) { + battery_log(BAT_LOG_CRTI, "[%s]Cannot find drvvbus_init state, err=%d\n", + __func__, (int)PTR_ERR(pinctrl_drvvbus_init)); + return; + } + + pinctrl_drvvbus_low = pinctrl_lookup_state(pinctrl, "drvvbus_low"); + if (IS_ERR(pinctrl_drvvbus_low)) { + battery_log(BAT_LOG_CRTI, "[%s]Cannot find drvvbus_low state, err=%d\n", + __func__, (int)PTR_ERR(pinctrl_drvvbus_low)); + return; + } + + pinctrl_select_state(pinctrl, pinctrl_drvvbus_init); + pinctrl_select_state(pinctrl, pinctrl_drvvbus_low); + devm_pinctrl_put(pinctrl); + battery_log(BAT_LOG_FULL, "[%s]pinctrl_select_state success\n", __func__); +#endif +} +#endif + +static int ncp1854_driver_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int err = 0; + + battery_log(BAT_LOG_CRTI, "[ncp1854_driver_probe]\n"); + + new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + + if (!new_client) { + err = -ENOMEM; + goto exit; + } + memset(new_client, 0, sizeof(struct i2c_client)); + + new_client = client; + + chargin_hw_init_done = KAL_TRUE; + + //ncp1854_parse_customer_setting(); + + return 0; + +exit: + return err; + +} + +/********************************************************** + * + * [platform_driver API] + * + *********************************************************/ +unsigned char g_reg_value_ncp1854 = 0; +static ssize_t show_ncp1854_access(struct device *dev, struct device_attribute *attr, char *buf) +{ + battery_log(BAT_LOG_CRTI, "[show_ncp1854_access] 0x%x\n", g_reg_value_ncp1854); + return sprintf(buf, "%u\n", g_reg_value_ncp1854); +} + +static ssize_t store_ncp1854_access(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + char *pvalue = NULL, *addr, *val; + unsigned int reg_value = 0; + unsigned int reg_address = 0; + + battery_log(BAT_LOG_CRTI, "[store_ncp1854_access]\n"); + + if (buf != NULL && size != 0) { + battery_log(BAT_LOG_CRTI, "[store_ncp1854_access] buf is %s and size is %d\n", buf, (int)size); + /*reg_address = kstrtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + if (size > 3) { + addr = strsep(&pvalue, " "); + ret = kstrtou32(addr, 16, (unsigned int *)®_address); + } else + ret = kstrtou32(pvalue, 16, (unsigned int *)®_address); + + if (size > 3) { + val = strsep(&pvalue, " "); + ret = kstrtou32(val, 16, (unsigned int *)®_value); + + battery_log(BAT_LOG_CRTI, + "[store_ncp1854_access] write ncp1854 reg 0x%x with value 0x%x !\n", + reg_address, reg_value); + ret = ncp1854_config_interface(reg_address, reg_value, 0xFF, 0x0); + } else { + ret = ncp1854_read_interface(reg_address, &g_reg_value_ncp1854, 0xFF, 0x0); + battery_log(BAT_LOG_CRTI, + "[store_ncp1854_access] read ncp1854 reg 0x%x with value 0x%x !\n", + reg_address, g_reg_value_ncp1854); + battery_log(BAT_LOG_CRTI, + "[store_ncp1854_access] Please use \"cat ncp1854_access\" to get value\r\n"); + } + } + return size; +} + +static DEVICE_ATTR(ncp1854_access, 0664, show_ncp1854_access, store_ncp1854_access); /* 664 */ + +static int ncp1854_user_space_probe(struct platform_device *dev) +{ + int ret_device_file = 0; + + battery_log(BAT_LOG_CRTI, "******** ncp1854_user_space_probe!! ********\n"); + + ret_device_file = device_create_file(&(dev->dev), &dev_attr_ncp1854_access); + + return 0; +} + +struct platform_device ncp1854_user_space_device = { + .name = "ncp1854-user", + .id = -1, +}; + +static struct platform_driver ncp1854_user_space_driver = { + .probe = ncp1854_user_space_probe, + .driver = { + .name = "ncp1854-user", + }, +}; + +static int __init ncp1854_init(void) +{ + int ret = 0; + + battery_log(BAT_LOG_CRTI, "[ncp1854_init] init start\n"); + + if (i2c_add_driver(&ncp1854_driver) != 0) + battery_log(BAT_LOG_CRTI, "[ncp1854_init] failed to register ncp1854 i2c driver.\n"); + else + battery_log(BAT_LOG_CRTI, "[ncp1854_init] Success to register ncp1854 i2c driver.\n"); + + /* ncp1854 user space access interface */ + ret = platform_device_register(&ncp1854_user_space_device); + if (ret) { + battery_log(BAT_LOG_CRTI, "****[ncp1854_init] Unable to device register(%d)\n", ret); + return ret; + } + ret = platform_driver_register(&ncp1854_user_space_driver); + if (ret) { + battery_log(BAT_LOG_CRTI, "****[ncp1854_init] Unable to register driver (%d)\n", ret); + return ret; + } + + return 0; +} + +static void __exit ncp1854_exit(void) +{ + i2c_del_driver(&ncp1854_driver); +} + +module_init(ncp1854_init); +module_exit(ncp1854_exit); +/* subsys_initcall(ncp1854_subsys_init); */ + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("I2C ncp1854 Driver"); +MODULE_AUTHOR("YT Lee"); diff --git a/drivers/misc/mediatek/power/mt6755/ncp1854.h b/drivers/misc/mediatek/power/mt6755/ncp1854.h new file mode 100755 index 0000000000000000000000000000000000000000..4d161c67099b7270cfbb4264891a043671144e9d --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/ncp1854.h @@ -0,0 +1,307 @@ +/***************************************************************************** +* +* Filename: +* --------- +* ncp1854.h +* +* Project: +* -------- +* Android +* +* Description: +* ------------ +* ncp1854 header file +* +* Author: +* ------- +* +****************************************************************************/ + +#ifndef _NCP1854_SW_H_ +#define _NCP1854_SW_H_ + +#define NCP1854_CON0 0x00 +#define NCP1854_CON1 0x01 +#define NCP1854_CON2 0x02 +#define NCP1854_CON3 0x03 +#define NCP1854_CON4 0x04 +#define NCP1854_CON5 0x05 +#define NCP1854_CON6 0x06 +#define NCP1854_CON7 0x07 +#define NCP1854_CON8 0x08 +#define NCP1854_CON9 0x09 +#define NCP1854_CON10 0x0A +#define NCP1854_CON11 0x0B +#define NCP1854_CON12 0x0C +#define NCP1854_CON13 0x0D +#define NCP1854_CON14 0x0E +#define NCP1854_CON15 0x0F +#define NCP1854_CON16 0x10 +#define NCP1854_CON17 0x11 +#define NCP1854_CON18 0x12 +#define ncp1854_REG_NUM 18 + +/********************************************************** + * + * [MASK/SHIFT] + * + *********************************************************/ +/* CON0 */ +#define CON0_STATE_MASK 0x0F +#define CON0_STATE_SHIFT 4 + +#define CON0_BATFET_MASK 0x01 +#define CON0_BATFET_SHIFT 3 + +#define CON0_STATINT_MASK 0x01 +#define CON0_STATINT_SHIFT 1 + +#define CON0_FAULTINT_MASK 0x01 +#define CON0_FAULTINT_SHIFT 0 + +/* CON1 */ +#define CON1_REG_RST_MASK 0x01 +#define CON1_REG_RST_SHIFT 7 + +#define CON1_CHG_EN_MASK 0x01 +#define CON1_CHG_EN_SHIFT 6 + +#define CON1_OTG_EN_MASK 0x01 +#define CON1_OTG_EN_SHIFT 5 + +#define CON1_FCTRY_MOD_MASK 0x01 +#define CON1_FCTRY_MOD_SHIFT 4 + +#define CON1_TJ_WARN_OPT_MASK 0x01 +#define CON1_TJ_WARN_OPT_SHIFT 3 + +#define CON1_JEITA_OPT_MASK 0x01 +#define CON1_JEITA_OPT_SHIFT 2 + +#define CON1_TCHG_RST_MASK 0x01 +#define CON1_TCHG_RST_SHIFT 1 + +#define CON1_INT_MASK_MASK 0x01 +#define CON1_INT_MASK_SHIFT 0 + +/* CON2 */ +#define CON2_WDTO_DIS_MASK 0x01 +#define CON2_WDTO_DIS_SHIFT 7 + +#define CON2_CHGTO_DIS_MASK 0x01 +#define CON2_CHGTO_DIS_SHIFT 6 + +#define CON2_PWR_PATH_MASK 0x01 +#define CON2_PWR_PATH_SHIFT 5 + +#define CON2_TRANS_EN_MASK 0x01 +#define CON2_TRANS_EN_SHIFT 4 + +#define CON2_IINSET_PIN_EN_MASK 0x01 +#define CON2_IINSET_PIN_EN_SHIFT 2 + +#define CON2_IINLIM_EN_MASK 0x01 +#define CON2_IINLIM_EN_SHIFT 1 + +#define CON2_AICL_EN_MASK 0x01 +#define CON2_AICL_EN_SHIFT 0 + +/* CON3 */ +/* Status flag */ + +/* CON4 */ +/* Status flag */ + +/* CON5 */ +/* Status flag */ + +/* CON6 */ +/* Boost mode interrupt */ +#define CON6_VOBSTOL2_MASK 0x01 +#define CON6_VOBSTOL2_SHIFT 3 + +#define CON6_VOBSTOL1_MASK 0x01 +#define CON6_VOBSTOL1_SHIFT 2 + +#define CON6_VBUSOV_MASK 0x01 +#define CON6_VBUSOV_SHIFT 1 + +#define CON6_VBAT_NOK_MASK 0x01 +#define CON6_VBAT_NOK_SHIFT 0 + +/* CON7 */ +/* Status flag */ + +/* CON8 */ +#define CON8_NTC_RMV_MASK 0x01 +#define CON8_NTC_RMV_SHIFT 7 + +#define CON8_VBAT_OV_MASK 0x01 +#define CON8_VBAT_OV_SHIFT 6 + +#define CON8_VRECHG_OK_MASK 0x01 +#define CON8_VRECHG_OK_SHIFT 5 + +#define CON8_VFET_OK_MASK 0x01 +#define CON8_VFET_OK_SHIFT 4 + +#define CON8_VPRE_OK_MASK 0x01 +#define CON8_VPRE_OK_SHIFT 3 + +#define CON8_VSAFE_OK_MASK 0x01 +#define CON8_VSAFE_OK_SHIFT 2 + +#define CON8_IEOC_OK_MASK 0x01 +#define CON8_IEOC_OK_SHIFT 1 + +/* CON9 */ +#define CON9_TSD_MASK 0x01 +#define CON9_TSD_SHIFT 3 + +#define CON9_TM2_MASK 0x01 +#define CON9_TM2_SHIFT 2 + +#define CON9_TM1_MASK 0x01 +#define CON9_TM1_SHIFT 1 + +#define CON9_TWARN_MASK 0x01 +#define CON9_TWARN_SHIFT 0 + +/* CON10 */ +/* Interrupt mask */ + +/* CON11 */ +/* Interrupt mask */ + +/* CON12 */ +/* Interrupt mask */ + +/* CON13 */ +/* Interrupt mask */ + +/* CON14 */ +#define CON14_CTRL_VBAT_MASK 0x3F +#define CON14_CTRL_VBAT_SHIFT 0 + +/* CON15 */ +#define CON15_ICHG_HIGH_MASK 0x01 +#define CON15_ICHG_HIGH_SHIFT 7 + +#define CON15_IEOC_MASK 0x07 +#define CON15_IEOC_SHIFT 4 + +#define CON15_ICHG_MASK 0x0F +#define CON15_ICHG_SHIFT 0 + +/* CON16 */ +#define CON16_IWEAK_MASK 0x03 +#define CON16_IWEAK_SHIFT 5 + +#define CON16_CTRL_VFET_MASK 0x07 +#define CON16_CTRL_VFET_SHIFT 2 + +#define CON16_IINLIM_MASK 0x3 +#define CON16_IINLIM_SHIFT 0 + +/* CON17 */ +#define CON17_IINLIM_TA_MASK 0x0F +#define CON17_IINLIM_TA_SHIFT 4 + +/* CON18 */ +#define CON18_BATCOLD_MASK 0x07 +#define CON18_BATCOLD_SHIFT 5 + +#define CON18_BATHOT_MASK 0x07 +#define CON18_BATHOT_SHIFT 2 + +#define CON18_BATCHIL_MASK 0x01 +#define CON18_BATCHIL_SHIFT 1 + +#define CON18_BATWARM_MASK 0x01 +#define CON18_BATWARM_SHIFT 0 + +/********************************************************** + * + * [Extern Function] + * + *********************************************************/ +#define NCP1854_REG_NUM 18 +extern unsigned char ncp1854_reg[NCP1854_REG_NUM]; + +/* CON0 */ +extern unsigned int ncp1854_get_chip_status(void); + +extern unsigned int ncp1854_get_batfet(void); + +extern unsigned int ncp1854_get_statint(void); + +extern unsigned int ncp1854_get_faultint(void); + + +/* CON1 */ +extern void ncp1854_set_reset(unsigned int val); + +extern void ncp1854_set_chg_en(unsigned int val); + +extern void ncp1854_set_otg_en(unsigned int val); + +extern unsigned int ncp1854_get_otg_en(void); + +extern void ncp1854_set_fctry_mode(unsigned int val); + + +extern void ncp1854_set_tj_warn_opt(unsigned int val); + +extern unsigned int ncp1854_get_usb_cfg(void); + +extern void ncp1854_set_tchg_rst(unsigned int val); + +extern void ncp1854_set_int_mask(unsigned int val); + +/* CON2 */ +extern void ncp1854_set_wdto_dis(unsigned int val); + +extern void ncp1854_set_chgto_dis(unsigned int val); + +extern void ncp1854_set_pwr_path(unsigned int val); + +extern void ncp1854_set_trans_en(unsigned int val); + +extern void ncp1854_set_chg_halt(unsigned int val); + +extern void ncp1854_set_iinset_pin_en(unsigned int val); + +extern void ncp1854_set_iinlim_en(unsigned int val); + +extern void ncp1854_set_aicl_en(unsigned int val); + +/* CON8 */ +extern unsigned int ncp1854_get_vfet_ok(void); + +/* CON14 */ +extern void ncp1854_set_ctrl_vbat(unsigned int val); + +/* CON15 */ +extern void ncp1854_set_ieoc(unsigned int val); + +extern void ncp1854_set_ichg_high(unsigned int val); + +extern void ncp1854_set_ichg(unsigned int val); + +extern unsigned int ncp1854_get_ichg(void); + +/* CON16 */ +extern void ncp1854_set_iweak(unsigned int val); + +extern void ncp1854_set_ctrl_vfet(unsigned int val); + +extern void ncp1854_set_iinlim(unsigned int val); + +/* CON17 */ +extern void ncp1854_set_iinlim_ta(unsigned int val); + +extern void ncp1854_dump_register(void); + +extern void ncp1854_read_register(int i); + +#endif /* _NCP1854_SW_H_ */ diff --git a/drivers/misc/mediatek/power/mt6755/pmic.c b/drivers/misc/mediatek/power/mt6755/pmic.c new file mode 100644 index 0000000000000000000000000000000000000000..b36e33e77b44f451f126cf20dc95304f0a08ea58 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/pmic.c @@ -0,0 +1,4993 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * pmic.c + * + * Project: + * -------- + * Android_Software + * + * Description: + * ------------ + * This Module defines PMIC functions + * + * Author: + * ------- + * Argus Lin + * + ****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* +#if !defined CONFIG_HAS_WAKELOCKS +#include included in linux/device.h +#else +*/ +#include +/*#endif*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#include +#include +#endif +#include + +#if !defined CONFIG_MTK_LEGACY +#include +#include +#endif +#include +#include "pmic.h" +#include "pmic_irq.h" +/*#include TBD*/ +#include +#if defined CONFIG_MTK_LEGACY +#include +#endif +#include +#include + +#include + +#include "pmic_dvt.h" + +#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) +#include +#include +/*#include TBD*/ +#include +#endif + +#if defined(CONFIG_MTK_SMART_BATTERY) +#include +#include +#include +#endif +#include "mt6311.h" +#include +#include +#include + +/***************************************************************************** + * PMIC extern variable + ******************************************************************************/ +static struct mtk_regulator mtk_bucks[]; +/***************************************************************************** + * Global variable + ******************************************************************************/ +unsigned int g_pmic_pad_vbif28_vol = 1; +/***************************************************************************** + * PMIC related define + ******************************************************************************/ +static DEFINE_MUTEX(pmic_lock_mutex); +#define PMIC_EINT_SERVICE + +/***************************************************************************** + * PMIC read/write APIs + ******************************************************************************/ +#if 0 /*defined(CONFIG_MTK_FPGA)*/ + /* no CONFIG_PMIC_HW_ACCESS_EN */ +#else +#define CONFIG_PMIC_HW_ACCESS_EN +#endif +/* +#define PMICTAG "[PMIC] " +#if defined PMIC_DEBUG_PR_DBG +#define PMICLOG(fmt, arg...) pr_err(PMICTAG fmt, ##arg) +#else +#define PMICLOG(fmt, arg...) +#endif +*/ +#define PMIC_UT 0 +#ifdef CONFIG_OF +#if !defined CONFIG_MTK_LEGACY +/* +static int pmic_mt_cust_probe(struct platform_device *pdev); +static int pmic_mt_cust_remove(struct platform_device *pdev); +static int pmic_regulator_ldo_init(struct platform_device *pdev); +*/ +#endif +#endif /* End of #ifdef CONFIG_OF */ + +static DEFINE_MUTEX(pmic_access_mutex); +/*--- Global suspend state ---*/ +static bool pmic_suspend_state; + +int pmic_force_vcore_pwm(bool enable) +{ + int val, val1, val2, ret; + + ret = pmic_read_interface_nolock(0x44e, &val, 0xFFFF, 0x0); + ret = pmic_read_interface_nolock(0x450, &val1, 0xFFFF, 0x0); + ret = pmic_read_interface_nolock(0x452, &val2, 0xFFFF, 0x0); + pr_err("[pmic]pre force_vcore_pwm:0x%x, 0x%x, 0x%x\n", val, val1, val2); + + if (enable == true) { + ret = pmic_config_interface_nolock(0x450, 0x0, 0x7, 0); + ret = pmic_config_interface_nolock(0x452, 0x0, 0x1, 3); + ret = pmic_config_interface_nolock(0x44e, 0x1, 0x1, 1); + } else { + ret = pmic_config_interface_nolock(0x44e, 0x0, 0x1, 1); + ret = pmic_config_interface_nolock(0x450, 0x4, 0x7, 0); + ret = pmic_config_interface_nolock(0x452, 0x1, 0x1, 3); + } + + ret = pmic_read_interface_nolock(0x44e, &val, 0xFFFF, 0x0); + ret = pmic_read_interface_nolock(0x450, &val1, 0xFFFF, 0x0); + ret = pmic_read_interface_nolock(0x452, &val2, 0xFFFF, 0x0); + pr_err("[pmic]post force_vcore_pwm:0x%x, 0x%x, 0x%x\n", val, val1, val2); + + return 0; +} + +void vmd1_pmic_setting_on(void) +{ + /* VSRAM_MD on */ + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_EN, 1); /* 0x0654[0]=0, 0:Disable, 1:Enable */ + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN, 1); /* 0x0662[8]=0, 0:SW control, 1:HW control */ + + /* VMD1 on */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_EN, 1); /* 0x0640[0]=0, 0:Disable, 1:Enable */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_VSLEEP_EN, 1); /* 0x064E[8]=0, 0:SW control, 1:HW control */ + + /* VMODEM on */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_EN, 1); /* 0x062C[0]=0, 0:Disable, 1:Enable */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN, 1); /* 0x063A[8]=0, 0:SW control, 1:HW control */ + + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON, 0x50);/*E1 1.0V; offset:0x65A */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VOSEL_ON, 0x40);/* 1.0V; offset: 0x632 */ + udelay(300); + + pmic_set_register_value(MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL, 1);/* HW mode, bit[1]; offset: 0x650 */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL, 1);/* HW mode, bit[1]; offset: 0x63C */ + pmic_set_register_value(MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL, 1);/* HW mode, bit[1]; offset: 0x628 */ +} + +unsigned int pmic_read_vbif28_volt(unsigned int *val) +{ + if (g_pmic_pad_vbif28_vol != 0x1) { + *val = g_pmic_pad_vbif28_vol; + return 1; + } else + return 0; +} + +unsigned int pmic_get_vbif28_volt(void) +{ + return g_pmic_pad_vbif28_vol; +} + +unsigned int pmic_read_interface(unsigned int RegNum, unsigned int *val, unsigned int MASK, unsigned int SHIFT) +{ + unsigned int return_value = 0; + +#if defined(CONFIG_PMIC_HW_ACCESS_EN) + unsigned int pmic_reg = 0; + unsigned int rdata; + + if ((pmic_suspend_state == true) && irqs_disabled()) + return pmic_read_interface_nolock(RegNum, val, MASK, SHIFT); + + mutex_lock(&pmic_access_mutex); + + /*mt_read_byte(RegNum, &pmic_reg);*/ + return_value = pwrap_wacs2(0, (RegNum), 0, &rdata); + pmic_reg = rdata; + if (return_value != 0) { + PMICLOG("[pmic_read_interface] Reg[%x]= pmic_wrap read data fail\n", RegNum); + mutex_unlock(&pmic_access_mutex); + return return_value; + } + /*PMICLOG"[pmic_read_interface] Reg[%x]=0x%x\n", RegNum, pmic_reg);*/ + + pmic_reg &= (MASK << SHIFT); + *val = (pmic_reg >> SHIFT); + /*PMICLOG"[pmic_read_interface] val=0x%x\n", *val);*/ + + mutex_unlock(&pmic_access_mutex); +#else + /*PMICLOG("[pmic_read_interface] Can not access HW PMIC\n");*/ +#endif + + return return_value; +} + +int en_buck_vsleep_dbg = 0; +unsigned int pmic_buck_vsleep_to_swctrl(unsigned int buck_num, unsigned int vsleep_addr, + unsigned int vsleep_mask, unsigned int vsleep_shift) +{ + unsigned int return_value = 0; + unsigned int pmic_reg = 0; + unsigned int rdata; + + return_value = pwrap_wacs2(0, (vsleep_addr), 0, &rdata); + pmic_reg = rdata; + mtk_bucks[buck_num].vsleep_en_saved = rdata; + if (en_buck_vsleep_dbg == 1) { + pr_err("[pmic]vsleep %s_vsleep[0x%x]=0x%x, 0x%x\n", mtk_bucks[buck_num].desc.name, + vsleep_addr, mtk_bucks[buck_num].vsleep_en_saved, rdata); + } + pmic_reg &= ~(vsleep_mask << vsleep_shift); + pmic_reg |= (0 << vsleep_shift); + + return_value = pwrap_wacs2(1, (vsleep_addr), pmic_reg, &rdata); + if (en_buck_vsleep_dbg == 1) { + udelay(1000); + return_value = pwrap_wacs2(0, (vsleep_addr), 0, &rdata); + pr_err("[pmic]vsleep.b %s_vsleep[0x%x]=0x%x, 0x%x\n", mtk_bucks[buck_num].desc.name, + vsleep_addr, mtk_bucks[buck_num].vsleep_en_saved, pmic_reg); + } + return 0; +} +unsigned int pmic_buck_vsleep_restore(unsigned int buck_num, unsigned int vsleep_addr, + unsigned int vsleep_mask, unsigned int vsleep_shift) +{ + unsigned int return_value = 0; + unsigned int pmic_reg = 0; + unsigned int rdata = 0; + + if (mtk_bucks[buck_num].vsleep_en_saved != 0x0fffffff) { + if (vsleep_addr == MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_ADDR) + mtk_bucks[buck_num].vsleep_en_saved |= 0x13; + pmic_reg &= ~(vsleep_mask << vsleep_shift); + pmic_reg |= (mtk_bucks[buck_num].vsleep_en_saved); + return_value = pwrap_wacs2(1, (vsleep_addr), pmic_reg, &rdata); + if (en_buck_vsleep_dbg == 1) { + pr_err("[pmic]restore %s_vsleep[0x%x]=0x%x, 0x%x\n", mtk_bucks[buck_num].desc.name, + vsleep_addr, mtk_bucks[buck_num].vsleep_en_saved, rdata); + } + mtk_bucks[buck_num].vsleep_en_saved = 0x0fffffff; + } else { + if (en_buck_vsleep_dbg == 1) { + pr_err("[pmic]bypass %s_vsleep[0x%x]=0x%x, 0x%x\n", mtk_bucks[buck_num].desc.name, + vsleep_addr, mtk_bucks[buck_num].vsleep_en_saved, rdata); + } + } + return 0; +} +unsigned int pmic_config_interface_buck_vsleep_check(unsigned int RegNum, + unsigned int val, unsigned int MASK, unsigned int SHIFT) +{ + + switch (RegNum) { + case MT6351_PMIC_BUCK_VCORE_EN_ADDR: + if ((val & 0x1) == 0x0) { /* buck off */ + pmic_buck_vsleep_to_swctrl(0, + MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_SHIFT); + } else if ((val & 0x1) == 0x1) { /* buck on */ + pmic_buck_vsleep_restore(0, + MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_SHIFT); + } + break; + case MT6351_PMIC_BUCK_VGPU_EN_ADDR: + if ((val & 0x1) == 0x0) { + pmic_buck_vsleep_to_swctrl(1, + MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_SHIFT); + } else if ((val & 0x1) == 0x1) { + pmic_buck_vsleep_restore(1, + MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_SHIFT); + } + break; + case MT6351_PMIC_BUCK_VMODEM_EN_ADDR: + if ((val & 0x1) == 0x0) { + pmic_buck_vsleep_to_swctrl(2, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_SHIFT); + + } else if ((val & 0x1) == 0x1) { + pmic_buck_vsleep_restore(2, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_SHIFT); + } + break; + case MT6351_PMIC_BUCK_VMD1_EN_ADDR: + if ((val & 0x1) == 0x0) { + pmic_buck_vsleep_to_swctrl(3, + MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_SHIFT); + + } else if ((val & 0x1) == 0x1) { + pmic_buck_vsleep_restore(3, + MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_SHIFT); + } + break; + case MT6351_PMIC_BUCK_VSRAM_MD_EN_ADDR: + if ((val & 0x1) == 0x0) { + pmic_buck_vsleep_to_swctrl(4, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_SHIFT); + + } else if ((val & 0x1) == 0x1) { + pmic_buck_vsleep_restore(4, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_SHIFT); + } + break; + case MT6351_PMIC_BUCK_VS1_EN_ADDR: + if ((val & 0x1) == 0x0) { + pmic_buck_vsleep_to_swctrl(5, + MT6351_PMIC_BUCK_VS1_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VS1_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VS1_VSLEEP_EN_SHIFT); + + } else if ((val & 0x1) == 0x1) { + pmic_buck_vsleep_restore(5, + MT6351_PMIC_BUCK_VS1_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VS1_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VS1_VSLEEP_EN_SHIFT); + } + break; + case MT6351_PMIC_BUCK_VS2_EN_ADDR: + if ((val & 0x1) == 0x0) { + pmic_buck_vsleep_to_swctrl(6, + MT6351_PMIC_BUCK_VS2_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VS2_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VS2_VSLEEP_EN_SHIFT); + } else if ((val & 0x1) == 0x1) { + pmic_buck_vsleep_restore(6, + MT6351_PMIC_BUCK_VS2_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VS2_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VS2_VSLEEP_EN_SHIFT); + } + + break; + case MT6351_PMIC_BUCK_VPA_EN_ADDR: + if ((val & 0x1) == 0x0) { + pmic_buck_vsleep_to_swctrl(7, + MT6351_PMIC_BUCK_VPA_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VPA_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VPA_VSLEEP_EN_SHIFT); + + } else if ((val & 0x1) == 0x1) { + pmic_buck_vsleep_restore(7, + MT6351_PMIC_BUCK_VPA_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VPA_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VPA_VSLEEP_EN_SHIFT); + } + break; + case MT6351_PMIC_BUCK_VSRAM_PROC_EN_ADDR: + if ((val & 0x1) == 0x0) { + pmic_buck_vsleep_to_swctrl(8, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_SHIFT); + + } else if ((val & 0x1) == 0x1) { + pmic_buck_vsleep_restore(8, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_SHIFT); + } + break; + default: + /* bypass buck vsleep en check */ + break; + } + return 0; +} + +unsigned int pmic_config_interface(unsigned int RegNum, unsigned int val, unsigned int MASK, unsigned int SHIFT) +{ + unsigned int return_value = 0; + +#if defined(CONFIG_PMIC_HW_ACCESS_EN) + unsigned int pmic_reg = 0; + unsigned int rdata; + + if ((pmic_suspend_state == true) && irqs_disabled()) + return pmic_config_interface_nolock(RegNum, val, MASK, SHIFT); + + mutex_lock(&pmic_access_mutex); + + /*1. mt_read_byte(RegNum, &pmic_reg);*/ + return_value = pwrap_wacs2(0, (RegNum), 0, &rdata); + pmic_reg = rdata; + if (return_value != 0) { + PMICLOG("[pmic_config_interface] Reg[%x]= pmic_wrap read data fail\n", RegNum); + mutex_unlock(&pmic_access_mutex); + return return_value; + } + /*PMICLOG"[pmic_config_interface] Reg[%x]=0x%x\n", RegNum, pmic_reg);*/ + + pmic_reg &= ~(MASK << SHIFT); + pmic_reg |= (val << SHIFT); + + /*2. mt_write_byte(RegNum, pmic_reg);*/ + pmic_config_interface_buck_vsleep_check(RegNum, val, MASK, SHIFT); + return_value = pwrap_wacs2(1, (RegNum), pmic_reg, &rdata); + if (return_value != 0) { + PMICLOG("[pmic_config_interface] Reg[%x]= pmic_wrap read data fail\n", RegNum); + mutex_unlock(&pmic_access_mutex); + return return_value; + } + /*PMICLOG"[pmic_config_interface] write Reg[%x]=0x%x\n", RegNum, pmic_reg);*/ + +#if 0 + /*3. Double Check*/ + /*mt_read_byte(RegNum, &pmic_reg);*/ + return_value = pwrap_wacs2(0, (RegNum), 0, &rdata); + pmic_reg = rdata; + if (return_value != 0) { + PMICLOG("[pmic_config_interface] Reg[%x]= pmic_wrap write data fail\n", RegNum); + mutex_unlock(&pmic_access_mutex); + return return_value; + } + PMICLOG("[pmic_config_interface] Reg[%x]=0x%x\n", RegNum, pmic_reg); +#endif + + mutex_unlock(&pmic_access_mutex); +#else + /*PMICLOG("[pmic_config_interface] Can not access HW PMIC\n");*/ +#endif + + return return_value; +} + +unsigned int pmic_read_interface_nolock(unsigned int RegNum, unsigned int *val, unsigned int MASK, unsigned int SHIFT) +{ + unsigned int return_value = 0; + +#if defined(CONFIG_PMIC_HW_ACCESS_EN) + unsigned int pmic_reg = 0; + unsigned int rdata; + + + /*mt_read_byte(RegNum, &pmic_reg); */ + return_value = pwrap_wacs2(0, (RegNum), 0, &rdata); + pmic_reg = rdata; + if (return_value != 0) { + PMICLOG("[pmic_read_interface] Reg[%x]= pmic_wrap read data fail\n", RegNum); + mutex_unlock(&pmic_access_mutex); + return return_value; + } + /*PMICLOG"[pmic_read_interface] Reg[%x]=0x%x\n", RegNum, pmic_reg); */ + + pmic_reg &= (MASK << SHIFT); + *val = (pmic_reg >> SHIFT); + /*PMICLOG"[pmic_read_interface] val=0x%x\n", *val); */ + +#else + /*PMICLOG("[pmic_read_interface] Can not access HW PMIC\n"); */ +#endif + + return return_value; +} + +unsigned int pmic_config_interface_nolock(unsigned int RegNum, unsigned int val, unsigned int MASK, unsigned int SHIFT) +{ + unsigned int return_value = 0; + +#if defined(CONFIG_PMIC_HW_ACCESS_EN) + unsigned int pmic_reg = 0; + unsigned int rdata; + + /* pmic wrapper has spinlock protection. pmic do not to do it again */ + + /*1. mt_read_byte(RegNum, &pmic_reg); */ + return_value = pwrap_wacs2(0, (RegNum), 0, &rdata); + pmic_reg = rdata; + if (return_value != 0) { + PMICLOG("[pmic_config_interface] Reg[%x]= pmic_wrap read data fail\n", RegNum); + mutex_unlock(&pmic_access_mutex); + return return_value; + } + /*PMICLOG"[pmic_config_interface] Reg[%x]=0x%x\n", RegNum, pmic_reg); */ + + pmic_reg &= ~(MASK << SHIFT); + pmic_reg |= (val << SHIFT); + + /*2. mt_write_byte(RegNum, pmic_reg); */ + pmic_config_interface_buck_vsleep_check(RegNum, val, MASK, SHIFT); + return_value = pwrap_wacs2(1, (RegNum), pmic_reg, &rdata); + if (return_value != 0) { + PMICLOG("[pmic_config_interface] Reg[%x]= pmic_wrap read data fail\n", RegNum); + mutex_unlock(&pmic_access_mutex); + return return_value; + } + /*PMICLOG"[pmic_config_interface] write Reg[%x]=0x%x\n", RegNum, pmic_reg); */ + +#if 0 + /*3. Double Check */ + /*mt_read_byte(RegNum, &pmic_reg); */ + return_value = pwrap_wacs2(0, (RegNum), 0, &rdata); + pmic_reg = rdata; + if (return_value != 0) { + PMICLOG("[pmic_config_interface] Reg[%x]= pmic_wrap write data fail\n", RegNum); + mutex_unlock(&pmic_access_mutex); + return return_value; + } + PMICLOG("[pmic_config_interface] Reg[%x]=0x%x\n", RegNum, pmic_reg); +#endif + +#else + /*PMICLOG("[pmic_config_interface] Can not access HW PMIC\n"); */ +#endif + + return return_value; +} + +/***************************************************************************** + * PMIC lock/unlock APIs + ******************************************************************************/ +void pmic_lock(void) +{ + mutex_lock(&pmic_lock_mutex); +} + +void pmic_unlock(void) +{ + mutex_unlock(&pmic_lock_mutex); +} + +unsigned int upmu_get_reg_value(unsigned int reg) +{ + unsigned int ret = 0; + unsigned int reg_val = 0; + + ret = pmic_read_interface(reg, ®_val, 0xFFFF, 0x0); + + return reg_val; +} +EXPORT_SYMBOL(upmu_get_reg_value); + +void upmu_set_reg_value(unsigned int reg, unsigned int reg_val) +{ + unsigned int ret = 0; + + ret = pmic_config_interface(reg, reg_val, 0xFFFF, 0x0); +} + +unsigned int get_pmic_mt6325_cid(void) +{ + return 0; +} + +unsigned int get_mt6325_pmic_chip_version(void) +{ + return 0; +} + +/********************************************************** + * + * [Internal Function] + * + *********************************************************/ +void mt6351_dump_register(void) +{ + unsigned int i = 0; + + PMICLOG("dump PMIC 6351 register\n"); + + for (i = 0; i <= 0x0fae; i = i + 10) { + pr_debug + ("Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x\n", + i, upmu_get_reg_value(i), i + 1, upmu_get_reg_value(i + 1), i + 2, + upmu_get_reg_value(i + 2), i + 3, upmu_get_reg_value(i + 3), i + 4, + upmu_get_reg_value(i + 4)); + + pr_debug + ("Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x Reg[0x%x]=0x%x\n", + i + 5, upmu_get_reg_value(i + 5), i + 6, upmu_get_reg_value(i + 6), i + 7, + upmu_get_reg_value(i + 7), i + 8, upmu_get_reg_value(i + 8), i + 9, + upmu_get_reg_value(i + 9)); + } + +} + +/***************************************************************************** + * workaround for vio18 drop issue in E1 + ******************************************************************************/ + +static const unsigned char mt6351_VIO[] = { + 12, 13, 14, 15, 0, 1, 2, 3, 8, 8, 8, 8, 8, 9, 10, 11 +}; + +static unsigned char vio18_cal; + +void upmu_set_rg_vio18_cal(unsigned int en) +{ +#if defined MT6328 + unsigned int chip_version = 0; + + chip_version = pmic_get_register_value(PMIC_SWCID); + + if (chip_version == PMIC6351_E1_CID_CODE) { + if (en == 1) + pmic_set_register_value(PMIC_RG_VIO18_CAL, mt6351_VIO[vio18_cal]); + else + pmic_set_register_value(PMIC_RG_VIO18_CAL, vio18_cal); + } + +#endif +} +EXPORT_SYMBOL(upmu_set_rg_vio18_cal); + + +static const unsigned char mt6351_VIO_1_84[] = { + 14, 15, 0, 1, 2, 3, 4, 5, 8, 8, 8, 9, 10, 11, 12, 13 +}; + + + +void upmu_set_rg_vio18_184(void) +{ + PMICLOG("[upmu_set_rg_vio18_184] old cal=%d new cal=%d.\r\n", vio18_cal, + mt6351_VIO_1_84[vio18_cal]); + pmic_set_register_value(PMIC_RG_VIO18_CAL, mt6351_VIO_1_84[vio18_cal]); + +} + + +static const unsigned char mt6351_VMC_1_86[] = { + 14, 15, 0, 1, 2, 3, 4, 5, 8, 8, 8, 9, 10, 11, 12, 13 +}; + + +static unsigned char vmc_cal; + +void upmu_set_rg_vmc_184(unsigned char x) +{ + + PMICLOG("[upmu_set_rg_vio18_184] old cal=%d new cal=%d.\r\n", vmc_cal, + mt6351_VMC_1_86[vmc_cal]); + if (x == 0) { + pmic_set_register_value(PMIC_RG_VMC_CAL, vmc_cal); + PMICLOG("[upmu_set_rg_vio18_184]:0 old cal=%d new cal=%d.\r\n", vmc_cal, vmc_cal); + } else { + pmic_set_register_value(PMIC_RG_VMC_CAL, mt6351_VMC_1_86[vmc_cal]); + PMICLOG("[upmu_set_rg_vio18_184]:1 old cal=%d new cal=%d.\r\n", vmc_cal, + mt6351_VMC_1_86[vmc_cal]); + } +} + + +static unsigned char vcamd_cal; + +static const unsigned char mt6351_vcamd[] = { + 1, 2, 3, 4, 5, 6, 7, 7, 9, 10, 11, 12, 13, 14, 15, 0 +}; + + +void upmu_set_rg_vcamd(unsigned char x) +{ + + PMICLOG("[upmu_set_rg_vcamd] old cal=%d new cal=%d.\r\n", vcamd_cal, + mt6351_vcamd[vcamd_cal]); + if (x == 0) { + pmic_set_register_value(PMIC_RG_VCAMD_CAL, vcamd_cal); + PMICLOG("[upmu_set_rg_vcamd]:0 old cal=%d new cal=%d.\r\n", vcamd_cal, vcamd_cal); + } else { + pmic_set_register_value(PMIC_RG_VCAMD_CAL, mt6351_vcamd[vcamd_cal]); + PMICLOG("[upmu_set_rg_vcamd]:1 old cal=%d new cal=%d.\r\n", vcamd_cal, + mt6351_vcamd[vcamd_cal]); + } +} + + + + +/***************************************************************************** + * workaround for VMC voltage list + ******************************************************************************/ +int pmic_read_VMC_efuse(void) +{ + unsigned int val; + + pmic_set_register_value(PMIC_RG_EFUSE_CK_PDN_HWEN, 0); + pmic_set_register_value(PMIC_RG_EFUSE_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_OTP_RD_SW, 1); + + pmic_set_register_value(PMIC_RG_OTP_PA, 0xd * 2); + udelay(100); + if (pmic_get_register_value(PMIC_RG_OTP_RD_TRIG) == 0) + pmic_set_register_value(PMIC_RG_OTP_RD_TRIG, 1); + else + pmic_set_register_value(PMIC_RG_OTP_RD_TRIG, 0); + udelay(300); + while (pmic_get_register_value(PMIC_RG_OTP_RD_BUSY) == 1) + ; + udelay(1000); + val = pmic_get_register_value(PMIC_RG_OTP_DOUT_SW); + + val = val * 0x80; + pmic_set_register_value(PMIC_RG_EFUSE_CK_PDN_HWEN, 1); + pmic_set_register_value(PMIC_RG_EFUSE_CK_PDN, 1); + + return val; +} + +/***************************************************************************** + * upmu_interrupt_chrdet_int_en + ******************************************************************************/ +void upmu_interrupt_chrdet_int_en(unsigned int val) +{ + PMICLOG("[upmu_interrupt_chrdet_int_en] val=%d.\r\n", val); + + /*mt6325_upmu_set_rg_int_en_chrdet(val); */ + pmic_set_register_value(PMIC_RG_INT_EN_CHRDET, val); +} +EXPORT_SYMBOL(upmu_interrupt_chrdet_int_en); + + +/***************************************************************************** + * PMIC charger detection + ******************************************************************************/ +unsigned int upmu_get_rgs_chrdet(void) +{ + unsigned int val = 0; + + /*val = mt6325_upmu_get_rgs_chrdet();*/ + val = pmic_get_register_value(PMIC_RGS_CHRDET); + PMICLOG("[upmu_get_rgs_chrdet] CHRDET status = %d\n", val); + + return val; +} + +/***************************************************************************** + * mt-pmic dev_attr APIs + ******************************************************************************/ +unsigned int g_reg_value = 0; +static ssize_t show_pmic_access(struct device *dev, struct device_attribute *attr, char *buf) +{ + pr_err("[show_pmic_access] 0x%x\n", g_reg_value); + return sprintf(buf, "%u\n", g_reg_value); +} + +static ssize_t store_pmic_access(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + int ret = 0; + char *pvalue = NULL, *addr, *val; + unsigned int reg_value = 0; + unsigned int reg_address = 0; + + pr_err("[store_pmic_access]\n"); + if (buf != NULL && size != 0) { + pr_err("[store_pmic_access] buf is %s\n", buf); + /*reg_address = simple_strtoul(buf, &pvalue, 16);*/ + + pvalue = (char *)buf; + if (size > 5) { + addr = strsep(&pvalue, " "); + ret = kstrtou32(addr, 16, (unsigned int *)®_address); + } else + ret = kstrtou32(pvalue, 16, (unsigned int *)®_address); + + if (size > 5) { + /*reg_value = simple_strtoul((pvalue + 1), NULL, 16);*/ + /*pvalue = (char *)buf + 1;*/ + val = strsep(&pvalue, " "); + ret = kstrtou32(val, 16, (unsigned int *)®_value); + + pr_err("[store_pmic_access] write PMU reg 0x%x with value 0x%x !\n", + reg_address, reg_value); + ret = pmic_config_interface(reg_address, reg_value, 0xFFFF, 0x0); + } else { + ret = pmic_read_interface(reg_address, &g_reg_value, 0xFFFF, 0x0); + pr_err("[store_pmic_access] read PMU reg 0x%x with value 0x%x !\n", + reg_address, g_reg_value); + pr_err("[store_pmic_access] use \"cat pmic_access\" to get value(decimal)\r\n"); + } + } + return size; +} + +static DEVICE_ATTR(pmic_access, 0664, show_pmic_access, store_pmic_access); /*664*/ + +/* + * DVT entry + */ +unsigned char g_reg_value_pmic = 0; + +static ssize_t show_pmic_dvt(struct device *dev, struct device_attribute *attr, char *buf) +{ + pr_err("[show_pmic_dvt] 0x%x\n", g_reg_value_pmic); + return sprintf(buf, "%u\n", g_reg_value_pmic); +} + +static ssize_t store_pmic_dvt(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + int ret = 0; + char *pvalue = NULL; + unsigned int test_item = 0; + + pr_err("[store_pmic_dvt]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_pmic_dvt] buf is %s and size is %zu\n", buf, size); + + /*test_item = simple_strtoul(buf, &pvalue, 10);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&test_item); + pr_err("[store_pmic_dvt] test_item=%d\n", test_item); + +#ifdef MTK_PMIC_DVT_SUPPORT + pmic_dvt_entry(test_item); +#else + pr_err("[store_pmic_dvt] no define MTK_PMIC_DVT_SUPPORT\n"); +#endif + } + return size; +} + +static DEVICE_ATTR(pmic_dvt, 0664, show_pmic_dvt, store_pmic_dvt); + +/* + * auxadc + */ +unsigned char g_auxadc_pmic = 0; + +static ssize_t show_pmic_auxadc(struct device *dev, struct device_attribute *attr, char *buf) +{ + pr_err("[show_pmic_auxadc] 0x%x\n", g_auxadc_pmic); + return sprintf(buf, "%u\n", g_auxadc_pmic); +} + +static ssize_t store_pmic_auxadc(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + int ret = 0, i, j; + char *pvalue = NULL; + unsigned int val = 0; + + pr_err("[store_pmic_auxadc]\n"); + + if (buf != NULL && size != 0) { + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + for (i = 0; i < val; i++) { + + for (j = 0; j < 16; j++) { + pr_err("[PMIC_AUXADC] [%d]=%d\n", j, PMIC_IMM_GetOneChannelValue(j, 0, 0)); + mdelay(5); + } + pr_err("[PMIC_AUXADC] [%d]=%d\n", j, PMIC_IMM_GetOneChannelValue(PMIC_AUX_CH4_DCXO, 0, 0)); + } + } + return size; +} + +static DEVICE_ATTR(pmic_auxadc_ut, 0664, show_pmic_auxadc, store_pmic_auxadc); + +/***************************************************************************** + * PMIC6351 linux reguplator driver + ******************************************************************************/ + +static int mtk_regulator_enable(struct regulator_dev *rdev) +{ + const struct regulator_desc *rdesc = rdev->desc; + struct mtk_regulator *mreg; + unsigned int add = 0, val = 0; + + mreg = container_of(rdesc, struct mtk_regulator, desc); + if (mreg->en_reg != 0) { + pmic_set_register_value(mreg->en_reg, 1); + add = pmu_flags_table[mreg->en_reg].offset; + val = upmu_get_reg_value(add); + } + + PMICLOG("regulator_enable(name=%s id=%d en_reg=%x vol_reg=%x) [%x]=0x%x\n", rdesc->name, + rdesc->id, mreg->en_reg, mreg->vol_reg, add, val); + + return 0; +} + +static int mtk_regulator_disable(struct regulator_dev *rdev) +{ + const struct regulator_desc *rdesc = rdev->desc; + struct mtk_regulator *mreg; + unsigned int add = 0, val = 0; + + mreg = container_of(rdesc, struct mtk_regulator, desc); + + if (rdev->use_count == 0) { + PMICLOG("regulator name=%s should not disable( use_count=%d)\n", rdesc->name, + rdev->use_count); + return -1; + } + + if (mreg->en_reg != 0) { + pmic_set_register_value(mreg->en_reg, 0); + add = pmu_flags_table[mreg->en_reg].offset; + val = upmu_get_reg_value(add); + } + + PMICLOG("regulator_disable(name=%s id=%d en_reg=%x vol_reg=%x use_count=%d) [%x]=0x%x\n", + rdesc->name, rdesc->id, mreg->en_reg, mreg->vol_reg, rdev->use_count, add, val); + + return 0; +} + +static int mtk_regulator_is_enabled(struct regulator_dev *rdev) +{ + const struct regulator_desc *rdesc = rdev->desc; + struct mtk_regulator *mreg; + int en; + + mreg = container_of(rdesc, struct mtk_regulator, desc); + + en = pmic_get_register_value(mreg->en_reg); + + PMICLOG("[PMIC]regulator_is_enabled(name=%s id=%d en_reg=%x vol_reg=%x en=%d)\n", + rdesc->name, rdesc->id, mreg->en_reg, mreg->vol_reg, en); + + return en; +} + +static int mtk_regulator_get_voltage_sel(struct regulator_dev *rdev) +{ + const struct regulator_desc *rdesc = rdev->desc; + struct mtk_regulator *mreg; + unsigned char regVal = 0; + const int *pVoltage; + int voltage = 0; + unsigned int add = 0, val = 9; + + mreg = container_of(rdesc, struct mtk_regulator, desc); + + if (mreg->desc.n_voltages != 1) { + if (mreg->vol_reg != 0) { + regVal = pmic_get_register_value(mreg->vol_reg); + if (mreg->pvoltages != NULL) { + pVoltage = (const int *)mreg->pvoltages; + /*HW LDO sequence issue, we need to change it */ + if ((strcmp(mreg->desc.name, "va18") == 0) | + (strcmp(mreg->desc.name, "vtcxo24") == 0) | + (strcmp(mreg->desc.name, "vtcxo28") == 0) | + (strcmp(mreg->desc.name, "vcn28") == 0) | + (strcmp(mreg->desc.name, "vxo22") == 0) | + (strcmp(mreg->desc.name, "vbif28") == 0)) { + PMICLOG("mtk_regulator_get_voltage_sel(name=%s selector=%d)\n", + mreg->desc.name, regVal); + if (regVal == 0) + regVal = 3; + else if (regVal == 1) + regVal = 2; + else if (regVal == 2) + regVal = 1; + else if (regVal == 3) + regVal = 0; + } + voltage = pVoltage[regVal]; + add = pmu_flags_table[mreg->en_reg].offset; + val = upmu_get_reg_value(add); + } else { + voltage = mreg->desc.min_uV + mreg->desc.uV_step * regVal; + } + } else { + PMICLOG + ("regulator_get_voltage_sel bugl(name=%s id=%d en_reg=%x vol_reg=%x)\n", + rdesc->name, rdesc->id, mreg->en_reg, mreg->vol_reg); + } + } else { + if (mreg->vol_reg != 0) { + regVal = 0; + pVoltage = (const int *)mreg->pvoltages; + voltage = pVoltage[regVal]; + } else { + PMICLOG + ("regulator_get_voltage_sel bugl(name=%s id=%d en_reg=%x vol_reg=%x)\n", + rdesc->name, rdesc->id, mreg->en_reg, mreg->vol_reg); + } + } + /*HW LDO sequence issue, we need to change it */ + if ((strcmp(mreg->desc.name, "va18") == 0) | + (strcmp(mreg->desc.name, "vtcxo24") == 0) | + (strcmp(mreg->desc.name, "vtcxo28") == 0) | + (strcmp(mreg->desc.name, "vcn28") == 0) | + (strcmp(mreg->desc.name, "vxo22") == 0) | + (strcmp(mreg->desc.name, "vbif28") == 0)) { + PMICLOG("mtk_regulator_get_voltage_sel_restore(name=%s selector=%d)\n", + mreg->desc.name, regVal); + if (regVal == 0) + regVal = 3; + else if (regVal == 1) + regVal = 2; + else if (regVal == 2) + regVal = 1; + else if (regVal == 3) + regVal = 0; + } + PMICLOG + ("regulator_get_voltage_sel(name=%s id=%d en_reg=%x vol_reg=%x reg/sel:%d voltage:%d [0x%x]=0x%x)\n", + rdesc->name, rdesc->id, mreg->en_reg, mreg->vol_reg, regVal, voltage, add, val); + + return regVal; +} + +static int mtk_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) +{ + const struct regulator_desc *rdesc = rdev->desc; + struct mtk_regulator *mreg; + + mreg = container_of(rdesc, struct mtk_regulator, desc); + + mreg->vosel.cur_sel = selector; + + PMICLOG("regulator_set_voltage_sel(name=%s id=%d en_reg=%x vol_reg=%x selector=%d)\n", + rdesc->name, rdesc->id, mreg->en_reg, mreg->vol_reg, selector); + +#if 0 + if (strcmp(rdesc->name, "VCAMD") == 0) { + + if (selector == 3) + upmu_set_rg_vcamd(1); + else + upmu_set_rg_vcamd(0); + } +#endif + /*HW LDO sequence issue, we need to change it */ +/* + if ((strcmp(mreg->desc.name, "va18") == 0) | + (strcmp(mreg->desc.name, "vtcxo24") == 0) | + (strcmp(mreg->desc.name, "vtcxo28") == 0) | + (strcmp(mreg->desc.name, "vcn28") == 0) | + (strcmp(mreg->desc.name, "vxo22") == 0) | + (strcmp(mreg->desc.name, "vbif28") == 0)) { + PMICLOG("regulator_set_voltage_sel (name=%s selector=%d)\n", + rdesc->name, selector); + if (selector == 0) + selector = 3; + else if (selector == 1) + selector = 2; + else if (selector == 2) + selector = 1; + else if (selector == 3) + selector = 0; + } +*/ + pr_err("regulator_set_voltage_sel(name=%s selector=%d)\n", + rdesc->name, selector); + if (mreg->vol_reg != 0) + pmic_set_register_value(mreg->vol_reg, selector); + + return 0; +} + +static int mtk_regulator_list_voltage(struct regulator_dev *rdev, unsigned selector) +{ + const struct regulator_desc *rdesc = rdev->desc; + struct mtk_regulator *mreg; + const int *pVoltage; + int voltage = 0; + + mreg = container_of(rdesc, struct mtk_regulator, desc); + + if (mreg->desc.n_voltages != 1) { + if (mreg->vol_reg != 0) { + if (mreg->pvoltages != NULL) { + pVoltage = (const int *)mreg->pvoltages; + /*HW LDO sequence issue, we need to change it */ + if ((strcmp(mreg->desc.name, "va18") == 0) | + (strcmp(mreg->desc.name, "vtcxo24") == 0) | + (strcmp(mreg->desc.name, "vtcxo28") == 0) | + (strcmp(mreg->desc.name, "vcn28") == 0) | + (strcmp(mreg->desc.name, "vxo22") == 0) | + (strcmp(mreg->desc.name, "vbif28") == 0)) { + PMICLOG("mtk_regulator_list_voltage(name=%s selector=%d)\n", + mreg->desc.name, selector); + if (selector == 0) + selector = 3; + else if (selector == 1) + selector = 2; + else if (selector == 2) + selector = 1; + else if (selector == 3) + selector = 0; + } + voltage = pVoltage[selector]; + } else { + voltage = mreg->desc.min_uV + mreg->desc.uV_step * selector; + } + } else { + PMICLOG + ("mtk_regulator_list_voltage bugl(name=%s id=%d en_reg=%x vol_reg=%x)\n", + rdesc->name, rdesc->id, mreg->en_reg, mreg->vol_reg); + } + } else { + pVoltage = (const int *)mreg->pvoltages; + voltage = pVoltage[0]; + } + return voltage; +} + + + + +static struct regulator_ops mtk_regulator_ops = { + .enable = mtk_regulator_enable, + .disable = mtk_regulator_disable, + .is_enabled = mtk_regulator_is_enabled, + .get_voltage_sel = mtk_regulator_get_voltage_sel, + .set_voltage_sel = mtk_regulator_set_voltage_sel, + .list_voltage = mtk_regulator_list_voltage, +}; + +static ssize_t show_LDO_STATUS(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mtk_regulator *mreg; + unsigned int ret_value = 0; + + mreg = container_of(attr, struct mtk_regulator, en_att); + + ret_value = pmic_get_register_value(mreg->en_reg); + + pr_debug("[EM] LDO_%s_STATUS : %d\n", mreg->desc.name, ret_value); + return sprintf(buf, "%u\n", ret_value); +} + +static ssize_t store_LDO_STATUS(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + PMICLOG("[EM] Not Support Write Function\n"); + return size; +} + +static ssize_t show_LDO_VOLTAGE(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mtk_regulator *mreg; + const int *pVoltage; + + unsigned short regVal; + unsigned int ret_value = 0; + + mreg = container_of(attr, struct mtk_regulator, voltage_att); + + if (mreg->desc.n_voltages != 1) { + if (mreg->vol_reg != 0) { + regVal = pmic_get_register_value(mreg->vol_reg); + if (mreg->pvoltages != NULL) { + pVoltage = (const int *)mreg->pvoltages; + /*HW LDO sequence issue, we need to change it */ + if ((strcmp(mreg->desc.name, "va18") == 0) | + (strcmp(mreg->desc.name, "vtcxo24") == 0) | + (strcmp(mreg->desc.name, "vtcxo28") == 0) | + (strcmp(mreg->desc.name, "vcn28") == 0) | + (strcmp(mreg->desc.name, "vxo22") == 0) | + (strcmp(mreg->desc.name, "vbif28") == 0)) { + PMICLOG("show_LDO_VOLTAGE(name=%s selector=%d)\n", + mreg->desc.name, regVal); + if (regVal == 0) + regVal = 3; + else if (regVal == 1) + regVal = 2; + else if (regVal == 2) + regVal = 1; + else if (regVal == 3) + regVal = 0; + } + ret_value = pVoltage[regVal]; + } else { + ret_value = mreg->desc.min_uV + mreg->desc.uV_step * regVal; + } + } else { + PMICLOG("[EM][ERROR] LDO_%s_VOLTAGE : voltage=0 vol_reg=0\n", + mreg->desc.name); + } + } else { + pVoltage = (const int *)mreg->pvoltages; + ret_value = pVoltage[0]; + } + + ret_value = ret_value / 1000; + pr_err("[EM] LDO_%s_VOLTAGE : %d\n", mreg->desc.name, ret_value); + return sprintf(buf, "%u\n", ret_value); + +} + +static ssize_t store_LDO_VOLTAGE(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + PMICLOG("[EM] Not Support Write Function\n"); + return size; +} + +static ssize_t show_BUCK_STATUS(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mtk_regulator *mreg; + unsigned int ret_value = 0; + + mreg = container_of(attr, struct mtk_regulator, en_att); + + ret_value = pmic_get_register_value(mreg->qi_en_reg); + + pr_debug("[EM] BUCK_%s_STATUS : %d\n", mreg->desc.name, ret_value); + return sprintf(buf, "%u\n", ret_value); +} + +static ssize_t store_BUCK_STATUS(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + PMICLOG("[EM] Not Support Write Function\n"); + return size; +} + +static ssize_t show_BUCK_VOLTAGE(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct mtk_regulator *mreg; + const int *pVoltage; + + unsigned short regVal; + unsigned int ret_value = 0; + + mreg = container_of(attr, struct mtk_regulator, voltage_att); + + if (mreg->desc.n_voltages != 1) { + if (mreg->qi_vol_reg != 0) { + regVal = pmic_get_register_value(mreg->qi_vol_reg); + if (mreg->pvoltages != NULL) { + pVoltage = (const int *)mreg->pvoltages; + ret_value = pVoltage[regVal]; + } else { + ret_value = mreg->desc.min_uV + mreg->desc.uV_step * regVal; + } + } else { + pr_debug("[EM][ERROR] buck_%s_VOLTAGE : voltage=0 vol_reg=0\n", + mreg->desc.name); + } + } else { + pVoltage = (const int *)mreg->pvoltages; + ret_value = pVoltage[0]; + } + + ret_value = ret_value / 1000; + pr_debug("[EM] BUCK_%s_VOLTAGE : %d\n", mreg->desc.name, ret_value); + return sprintf(buf, "%u\n", ret_value); +} + +static ssize_t store_BUCK_VOLTAGE(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + PMICLOG("[EM] Not Support Write Function\n"); + return size; +} + +/*LDO setting*/ +static const int mt6351_VA18_voltages[] = { + 1800000, + 2200000, + 2375000, + 2800000, +}; +static const int mt6351_VCAMA_voltages[] = { + 1500000, + 1800000, + 2500000, + 2800000, +}; + +static const int mt6351_VCN33_voltages[] = { + 3300000, + 3400000, + 3500000, + 3600000, +}; + +static const int mt6351_VEFUSE_voltages[] = { + 1200000, + 1300000, + 1700000, + 1800000, + 1860000, + 2760000, + 3000000, + 3100000, +}; + +/*VSIM1 & VSIM2*/ +static const int mt6351_VSIM1_voltages[] = { + 1200000, + 1300000, + 1700000, + 1800000, + 1860000, + 2760000, + 3000000, + 3100000, +}; + +static const int mt6351_VEMC33_voltages[] = { + 3000000, + 3300000, +}; + +static const int mt6351_VMCH_voltages[] = { + 3000000, + 3300000, +}; + +static const int mt6351_VMC_voltages[] = { + 1200000, + 1300000, + 1500000, + 1800000, + 2000000, + 2900000, + 3000000, + 3300000, +}; + +static const int mt6351_VMC_E1_1_voltages[] = { + 2500000, + 2900000, + 3000000, + 3300000, +}; + +static const int mt6351_VMC_E1_2_voltages[] = { + 1300000, + 1800000, + 2900000, + 3300000, +}; + + +/*VCAM_AF & VIBR*/ +static const int mt6351_VCAM_AF_voltages[] = { + 1200000, + 1300000, + 1500000, + 1800000, + 2000000, + 2800000, + 3000000, + 3300000, +}; + +static const int mt6351_VGP1_voltages[] = { + 1200000, + 1300000, + 1500000, + 1800000, + 2500000, + 2800000, + 3000000, + 3300000, +}; + +static const int mt6351_VXO22_voltages[] = { + 1800000, + 2200000, + 2375000, + 2800000, +}; + +static const int mt6351_VCAMD_voltages[] = { + 900000, + 950000, + 1000000, + 1050000, + 1100000, + 1200000, + 1210000, +}; + +static const int mt6351_VA10_voltages[] = { + 900000, + 950000, + 1000000, + 1050000, + 1200000, + 1500000, + 1800000, +}; + +static const int mt6351_VRF18_1_voltages[] = { + 1000000, + 1200000, + 1300000, + 1500000, + 1800000, + 1810000, +}; + +static const int mt6351_VGP3_voltages[] = { + 1000000, + 1050000, + 1100000, + 1220000, + 1300000, + 1500000, + 1800000, + 1810000, +}; + +static const int mt6351_VCAM_IO_voltages[] = { + 900000, + 950000, + 1000000, + 1050000, + 1200000, + 1500000, + 1800000, +}; + +static const int mt6351_VM_voltages[] = { + 1800000, + 2900000, + 3000000, + 3300000, +}; + +static const int mt6351_1v8_voltages[] = { + 1800000, +}; + +static const int mt6351_2v8_voltages[] = { + 2800000, +}; + +static const int mt6351_3v3_voltages[] = { + 3300000, +}; + +static const int mt6351_1v825_voltages[] = { + 1825000, +}; + +static const int mt6351_rf18_voltages[] = { + 1000000, + 1050000, + 1100000, + 1220000, + 1300000, + 1500000, + 1800000, + 1810000, +}; + +struct mtk_regulator mtk_ldos[] = { + PMIC_LDO_GEN1(va18, PMIC_RG_VA18_EN, PMIC_RG_VA18_VOSEL, + mt6351_VA18_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vtcxo24, PMIC_RG_VTCXO24_EN, PMIC_RG_VTCXO24_VOSEL, + mt6351_VA18_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vtcxo28, PMIC_RG_VTCXO28_EN, + PMIC_RG_VTCXO28_VOSEL, mt6351_VA18_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vcn28, PMIC_RG_VCN28_EN, PMIC_RG_VCN28_VOSEL, + mt6351_VA18_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vcama, PMIC_RG_VCAMA_EN, PMIC_RG_VCAMA_VOSEL, + mt6351_VCAMA_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vusb33, PMIC_RG_VUSB33_EN, NULL, mt6351_3v3_voltages, 1, PMIC_EN), + PMIC_LDO_GEN1(vsim1, PMIC_RG_VSIM1_EN, PMIC_RG_VSIM1_VOSEL, + mt6351_VSIM1_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vsim2, PMIC_RG_VSIM2_EN, PMIC_RG_VSIM2_VOSEL, + mt6351_VSIM1_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vemc, PMIC_RG_VEMC_EN, PMIC_RG_VEMC_VOSEL, + mt6351_VEMC33_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vmch, PMIC_RG_VMCH_EN, PMIC_RG_VMCH_VOSEL, + mt6351_VMCH_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vio28, PMIC_RG_VIO28_EN, NULL, mt6351_2v8_voltages, 1, PMIC_EN), + PMIC_LDO_GEN1(vibr, PMIC_RG_VIBR_EN, PMIC_RG_VIBR_VOSEL, + mt6351_VCAM_AF_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vcamd, PMIC_RG_VCAMD_EN, PMIC_RG_VCAMD_VOSEL, + mt6351_VCAMD_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vrf18, PMIC_RG_VRF18_EN, PMIC_RG_VRF18_VOSEL, + mt6351_rf18_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vio18, PMIC_RG_VIO18_EN, NULL, mt6351_1v8_voltages, 1, PMIC_EN), + PMIC_LDO_GEN1(vcn18, PMIC_RG_VCN18_EN, PMIC_RG_VCN18_VOSEL, + mt6351_VCAM_IO_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vcamio, PMIC_RG_VCAMIO_EN, PMIC_RG_VCAMIO_VOSEL, + mt6351_VCAM_IO_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vsram_proc, PMIC_RG_VSRAM_PROC_EN, PMIC_BUCK_VSRAM_PROC_VOSEL, + mt6351_2v8_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vxo22, PMIC_RG_VXO22_EN, PMIC_RG_VXO22_VOSEL, + mt6351_VA18_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vrf12, PMIC_RG_VRF12_EN, PMIC_RG_VRF12_VOSEL, + mt6351_VCAM_IO_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(va10, PMIC_RG_VA10_EN, PMIC_RG_VA10_VOSEL, + mt6351_VA10_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vdram, PMIC_RG_VDRAM_EN, PMIC_RG_VDRAM_VOSEL, + mt6351_VCAMD_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vmipi, PMIC_RG_VMIPI_EN, PMIC_RG_VMIPI_VOSEL, + mt6351_VA10_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vgp3, PMIC_RG_VGP3_EN, PMIC_RG_VGP3_VOSEL, + mt6351_VGP3_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vbif28, PMIC_RG_VBIF28_EN, PMIC_RG_VBIF28_VOSEL, + mt6351_VA18_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vefuse, PMIC_RG_VEFUSE_EN, PMIC_RG_VEFUSE_VOSEL, + mt6351_VEFUSE_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vcn33_bt, PMIC_RG_VCN33_EN_BT, PMIC_RG_VCN33_VOSEL, + mt6351_VCN33_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vcn33_wifi, PMIC_RG_VCN33_EN_WIFI, PMIC_RG_VCN33_VOSEL, + mt6351_VCN33_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vldo28, PMIC_RG_VLDO28_EN_0, NULL, mt6351_2v8_voltages, 1, PMIC_EN), + PMIC_LDO_GEN1(vmc, PMIC_RG_VMC_EN, PMIC_RG_VMC_VOSEL, + mt6351_VMC_voltages, 1, PMIC_EN_VOL), + PMIC_LDO_GEN1(vldo28_0, PMIC_RG_VLDO28_EN_0, NULL, mt6351_2v8_voltages, 1, PMIC_EN), + PMIC_LDO_GEN1(vldo28_1, PMIC_RG_VLDO28_EN_1, NULL, mt6351_2v8_voltages, 1, PMIC_EN), +}; + +static struct mtk_regulator mtk_bucks[] = { + PMIC_BUCK_GEN(VCORE, PMIC_BUCK_VCORE_EN, PMIC_BUCK_VCORE_VOSEL, 600000, + 1393750, 6250), + PMIC_BUCK_GEN(VGPU, PMIC_BUCK_VGPU_EN, PMIC_BUCK_VGPU_VOSEL, 600000, + 1393750, 6250), + PMIC_BUCK_GEN(VMODEM, PMIC_BUCK_VMODEM_EN, PMIC_BUCK_VMODEM_VOSEL, 600000, + 1393750, 6250), + PMIC_BUCK_GEN(VMD1, PMIC_BUCK_VMD1_EN, PMIC_BUCK_VMD1_VOSEL, 600000, + 1393750, 6250), + PMIC_BUCK_GEN(VSRAM_MD, PMIC_BUCK_VSRAM_MD_EN, PMIC_BUCK_VSRAM_MD_VOSEL, + 600000, 1393750, 6250), + PMIC_BUCK_GEN(VS1, PMIC_BUCK_VS1_EN, PMIC_BUCK_VS1_VOSEL, 600000, 1393750, + 6250), + PMIC_BUCK_GEN(VS2, PMIC_BUCK_VS2_EN, PMIC_BUCK_VS2_VOSEL, 600000, 1393750, + 6250), + PMIC_BUCK_GEN(VPA, PMIC_BUCK_VPA_EN, PMIC_BUCK_VPA_VOSEL, 600000, 1393750, + 6250), + PMIC_BUCK_GEN(VSRAM_PROC, PMIC_BUCK_VSRAM_PROC_EN, + PMIC_BUCK_VSRAM_PROC_VOSEL, 600000, 1393750, 6250), +}; + +#if !defined CONFIG_MTK_LEGACY +#ifdef CONFIG_OF +/* +#define PMIC_REGULATOR_OF_MATCH(_name, _id) \ +[MT6328_POWER_LDO_##_id] = { \ + .name = #_name, \ + .driver_data = &mtk_ldos[MT6328_POWER_LDO_##_id], \ +} +*/ +#define PMIC_REGULATOR_OF_MATCH(_name, _id) \ + { \ + .name = #_name, \ + .driver_data = &mtk_ldos[MT6351_POWER_LDO_##_id], \ + } + +static struct of_regulator_match pmic_regulator_matches[] = { + PMIC_REGULATOR_OF_MATCH(ldo_va18, VA18), + PMIC_REGULATOR_OF_MATCH(ldo_vtcxo24, VTCXO24), + PMIC_REGULATOR_OF_MATCH(ldo_vtcxo28, VTCXO28), + PMIC_REGULATOR_OF_MATCH(ldo_vcn28, VCN28), + PMIC_REGULATOR_OF_MATCH(ldo_vcama, VCAMA), + PMIC_REGULATOR_OF_MATCH(ldo_vusb33, VUSB33), + PMIC_REGULATOR_OF_MATCH(ldo_vsim1, VSIM1), + PMIC_REGULATOR_OF_MATCH(ldo_vsim2, VSIM2), + PMIC_REGULATOR_OF_MATCH(ldo_vemc, VEMC), + PMIC_REGULATOR_OF_MATCH(ldo_vmch, VMCH), + PMIC_REGULATOR_OF_MATCH(ldo_vio28, VIO28), + PMIC_REGULATOR_OF_MATCH(ldo_vibr, VIBR), + PMIC_REGULATOR_OF_MATCH(ldo_vcamd, VCAMD), + PMIC_REGULATOR_OF_MATCH(ldo_vrf18, VRF18), + PMIC_REGULATOR_OF_MATCH(ldo_vio18, VIO18), + PMIC_REGULATOR_OF_MATCH(ldo_vcn18, VCN18), + PMIC_REGULATOR_OF_MATCH(ldo_vcamio, VCAMIO), + PMIC_REGULATOR_OF_MATCH(ldo_vsram_proc, VSRAM_PROC), + PMIC_REGULATOR_OF_MATCH(ldo_vxo22, VXO22), + PMIC_REGULATOR_OF_MATCH(ldo_vrf12, VRF12), + PMIC_REGULATOR_OF_MATCH(ldo_va10, VA10), + PMIC_REGULATOR_OF_MATCH(ldo_vdram, VDRAM), + PMIC_REGULATOR_OF_MATCH(ldo_vmipi, VMIPI), + PMIC_REGULATOR_OF_MATCH(ldo_vgp3, VGP3), + PMIC_REGULATOR_OF_MATCH(ldo_vbif28, VBIF28), + PMIC_REGULATOR_OF_MATCH(ldo_vefuse, VEFUSE), + PMIC_REGULATOR_OF_MATCH(ldo_vcn33_bt, VCN33_BT), + PMIC_REGULATOR_OF_MATCH(ldo_vcn33_wifi, VCN33_WIFI), + PMIC_REGULATOR_OF_MATCH(ldo_vldo28, VLDO28), + PMIC_REGULATOR_OF_MATCH(ldo_vmc, VMC), + PMIC_REGULATOR_OF_MATCH(ldo_vldo28_0, VLDO28), + PMIC_REGULATOR_OF_MATCH(ldo_vldo28_1, VLDO28), +}; +#endif /* End of #ifdef CONFIG_OF */ +#endif /* End of #if !defined CONFIG_MTK_LEGACY */ + +#if !defined CONFIG_MTK_LEGACY +#ifdef CONFIG_OF +struct platform_device mt_pmic_device = { + .name = "pmic_regulator", + .id = -1, +}; + +static const struct platform_device_id pmic_regulator_id[] = { + {"pmic_regulator", 0}, + {}, +}; + +static const struct of_device_id pmic_cust_of_ids[] = { + {.compatible = "mediatek,mt6351",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, pmic_cust_of_ids); + +static int pmic_regulator_ldo_init(struct platform_device *pdev) +{ + struct device_node *np, *regulators; + int matched, i = 0, ret; + + pdev->dev.of_node = of_find_compatible_node(NULL, NULL, "mediatek,mt_pmic"); + np = of_node_get(pdev->dev.of_node); + if (!np) + return -EINVAL; + + regulators = of_get_child_by_name(np, "ldo_regulators"); + if (!regulators) { + PMICLOG("[PMIC]regulators node not found\n"); + ret = -EINVAL; + goto out; + } + matched = of_regulator_match(&pdev->dev, regulators, + pmic_regulator_matches, + ARRAY_SIZE(pmic_regulator_matches)); + if ((matched < 0) || (matched != MT65XX_POWER_COUNT_END)) { + pr_err("[PMIC]Error parsing regulator init data: %d %d\n", matched, + MT65XX_POWER_COUNT_END); + return matched; + } + + for (i = 0; i < ARRAY_SIZE(pmic_regulator_matches); i++) { + if (mtk_ldos[i].isUsedable == 1) { + mtk_ldos[i].config.dev = &(pdev->dev); + mtk_ldos[i].config.init_data = pmic_regulator_matches[i].init_data; + mtk_ldos[i].config.of_node = pmic_regulator_matches[i].of_node; + mtk_ldos[i].config.driver_data = pmic_regulator_matches[i].driver_data; + mtk_ldos[i].desc.owner = THIS_MODULE; + + mtk_ldos[i].rdev = + regulator_register(&mtk_ldos[i].desc, &mtk_ldos[i].config); + if (IS_ERR(mtk_ldos[i].rdev)) { + ret = PTR_ERR(mtk_ldos[i].rdev); + pr_warn("[regulator_register] failed to register %s (%d)\n", + mtk_ldos[i].desc.name, ret); + } else { + PMICLOG("[regulator_register] pass to register %s\n", + mtk_ldos[i].desc.name); + + mtk_ldos[i].vosel.def_sel = mtk_regulator_get_voltage_sel(mtk_ldos[i].rdev); + mtk_ldos[i].vosel.cur_sel = mtk_ldos[i].vosel.def_sel; + } + + PMICLOG("[PMIC]mtk_ldos[%d].config.init_data min_uv:%d max_uv:%d\n", i, + mtk_ldos[i].config.init_data->constraints.min_uV, + mtk_ldos[i].config.init_data->constraints.max_uV); + } + } + of_node_put(regulators); + return 0; + +out: + of_node_put(np); + return ret; +} + +static int pmic_mt_cust_probe(struct platform_device *pdev) +{ + struct device_node *np, *nproot, *regulators, *child; +#ifdef non_ks + const struct of_device_id *match; +#endif + int ret; + unsigned int i = 0, default_on; + + PMICLOG("[PMIC]pmic_mt_cust_probe %s %s\n", pdev->name, pdev->id_entry->name); +#ifdef non_ks + /* check if device_id is matched */ + match = of_match_device(pmic_cust_of_ids, &pdev->dev); + if (!match) { + pr_warn("[PMIC]pmic_cust_of_ids do not matched\n"); + return -EINVAL; + } + + /* check customer setting */ + nproot = of_find_compatible_node(NULL, NULL, "mediatek,mt6328"); + if (nproot == NULL) { + pr_info("[PMIC]pmic_mt_cust_probe get node failed\n"); + return -ENOMEM; + } + + np = of_node_get(nproot); + if (!np) { + pr_info("[PMIC]pmic_mt_cust_probe of_node_get fail\n"); + return -ENODEV; + } + + regulators = of_find_node_by_name(np, "regulators"); + if (!regulators) { + pr_info("[PMIC]failed to find regulators node\n"); + ret = -ENODEV; + goto out; + } + for_each_child_of_node(regulators, child) { + /* check ldo regualtors and set it */ + for (i = 0; i < ARRAY_SIZE(pmic_regulator_matches); i++) { + /* compare dt name & ldos name */ + if (!of_node_cmp(child->name, pmic_regulator_matches[i].name)) { + PMICLOG("[PMIC]%s regulator_matches %s\n", child->name, + (char *)of_get_property(child, "regulator-name", NULL)); + break; + } + } + if (i == ARRAY_SIZE(pmic_regulator_matches)) + continue; + if (!of_property_read_u32(child, "regulator-default-on", &default_on)) { + switch (default_on) { + case 0: + /* skip */ + PMICLOG("[PMIC]%s regulator_skip %s\n", child->name, + pmic_regulator_matches[i].name); + break; + case 1: + /* turn ldo off */ + pmic_set_register_value(mtk_ldos[i].en_reg, false); + PMICLOG("[PMIC]%s default is off\n", + (char *)of_get_property(child, "regulator-name", NULL)); + break; + case 2: + /* turn ldo on */ + pmic_set_register_value(mtk_ldos[i].en_reg, true); + PMICLOG("[PMIC]%s default is on\n", + (char *)of_get_property(child, "regulator-name", NULL)); + break; + default: + break; + } + } + } + of_node_put(regulators); + PMICLOG("[PMIC]pmic_mt_cust_probe done\n"); + return 0; +#else + nproot = of_find_compatible_node(NULL, NULL, "mediatek,mt_pmic"); + if (nproot == NULL) { + pr_info("[PMIC]pmic_mt_cust_probe get node failed\n"); + return -ENOMEM; + } + + np = of_node_get(nproot); + if (!np) { + pr_info("[PMIC]pmic_mt_cust_probe of_node_get fail\n"); + return -ENODEV; + } + + regulators = of_get_child_by_name(np, "ldo_regulators"); + if (!regulators) { + PMICLOG("[PMIC]pmic_mt_cust_probe ldo regulators node not found\n"); + ret = -ENODEV; + goto out; + } + + for_each_child_of_node(regulators, child) { + /* check ldo regualtors and set it */ + if (!of_property_read_u32(child, "regulator-default-on", &default_on)) { + switch (default_on) { + case 0: + /* skip */ + PMICLOG("[PMIC]%s regulator_skip %s\n", child->name, + pmic_regulator_matches[i].name); + break; + case 1: + /* turn ldo off */ + pmic_set_register_value(mtk_ldos[i].en_reg, false); + PMICLOG("[PMIC]%s default is off\n", + (char *)of_get_property(child, "regulator-name", NULL)); + break; + case 2: + /* turn ldo on */ + pmic_set_register_value(mtk_ldos[i].en_reg, true); + PMICLOG("[PMIC]%s default is on\n", + (char *)of_get_property(child, "regulator-name", NULL)); + break; + default: + break; + } + } + } + of_node_put(regulators); + pr_err("[PMIC]pmic_mt_cust_probe done\n"); + return 0; +#endif +out: + of_node_put(np); + return ret; +} + +static int pmic_mt_cust_remove(struct platform_device *pdev) +{ + /*platform_driver_unregister(&mt_pmic_driver);*/ + return 0; +} + +static struct platform_driver mt_pmic_driver = { + .driver = { + .name = "pmic_regulator", + .owner = THIS_MODULE, + .of_match_table = pmic_cust_of_ids, + }, + .probe = pmic_mt_cust_probe, + .remove = pmic_mt_cust_remove, +/* .id_table = pmic_regulator_id,*/ +}; +#endif /* End of #ifdef CONFIG_OF */ +#endif /* End of #if !defined CONFIG_MTK_LEGACY */ + +void pmic_regulator_suspend(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) { + if (mtk_ldos[i].vol_reg != 0) { + mtk_ldos[i].vosel.cur_sel = mtk_regulator_get_voltage_sel(mtk_ldos[i].rdev); + if (mtk_ldos[i].vosel.cur_sel != mtk_ldos[i].vosel.def_sel) { + mtk_ldos[i].vosel.restore = true; + pr_err("pmic_regulator_suspend(name=%s id=%d default_sel=%d current_sel=%d)\n", + mtk_ldos[i].rdev->desc->name, mtk_ldos[i].rdev->desc->id, + mtk_ldos[i].vosel.def_sel, mtk_ldos[i].vosel.cur_sel); + } else + mtk_ldos[i].vosel.restore = false; + } + } +} + +void pmic_regulator_resume(void) +{ + int i, selector; + + for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) { + if (mtk_ldos[i].vol_reg != 0) { + if (mtk_ldos[i].vosel.restore == true) { + /*-- regulator voltage changed? --*/ + selector = mtk_ldos[i].vosel.cur_sel; + pmic_set_register_value(mtk_ldos[i].vol_reg, selector); + pr_err("pmic_regulator_resume(name=%s id=%d default_sel=%d current_sel=%d)\n", + mtk_ldos[i].rdev->desc->name, mtk_ldos[i].rdev->desc->id, + mtk_ldos[i].vosel.def_sel, mtk_ldos[i].vosel.cur_sel); + } + } + } +} + +static int pmic_regulator_pm_event(struct notifier_block *notifier, unsigned long pm_event, void *unused) +{ + switch (pm_event) { + case PM_HIBERNATION_PREPARE: /* Going to hibernate */ + pr_warn("[%s] pm_event %lu (IPOH_Start)\n", __func__, pm_event); + pmic_regulator_suspend(); + return NOTIFY_DONE; + + case PM_POST_HIBERNATION: /* Hibernation finished */ + pr_warn("[%s] pm_event %lu (IPOH_End)\n", __func__, pm_event); + pmic_regulator_resume(); + return NOTIFY_DONE; + } + return NOTIFY_OK; +} + +static struct notifier_block pmic_regulator_pm_notifier_block = { + .notifier_call = pmic_regulator_pm_event, + .priority = 0, +}; + +void mtk_regulator_init(struct platform_device *dev) +{ +#if defined CONFIG_MTK_LEGACY + int i = 0; + int isEn = 0; +#endif + int ret = 0; + + /*workaround for VMC voltage */ + if (pmic_get_register_value(PMIC_SWCID) == PMIC6351_E1_CID_CODE) { + if (pmic_read_VMC_efuse() != 0) { + PMICLOG("VMC voltage use E1_2 voltage table\n"); + mtk_ldos[MT6351_POWER_LDO_VMC].pvoltages = (void *)mt6351_VMC_E1_2_voltages; + } else { + PMICLOG("VMC voltage use E1_1 voltage table\n"); + mtk_ldos[MT6351_POWER_LDO_VMC].pvoltages = (void *)mt6351_VMC_E1_1_voltages; + } + } +/*workaround for VIO18*/ + vio18_cal = pmic_get_register_value(PMIC_RG_VIO18_CAL); + vmc_cal = pmic_get_register_value(PMIC_RG_VMC_CAL); + vcamd_cal = pmic_get_register_value(PMIC_RG_VCAMD_CAL); + +#if !defined CONFIG_MTK_LEGACY +#ifdef CONFIG_OF + pmic_regulator_ldo_init(dev); +#endif +#else + for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) { + if (mtk_ldos[i].isUsedable == 1) { + mtk_ldos[i].config.dev = &(dev->dev); + mtk_ldos[i].config.init_data = &mtk_ldos[i].init_data; + if (mtk_ldos[i].desc.n_voltages != 1) { + const int *pVoltage; + + if (mtk_ldos[i].vol_reg != 0) { + if (mtk_ldos[i].pvoltages != NULL) { + pVoltage = (const int *)mtk_ldos[i].pvoltages; + mtk_ldos[i].init_data.constraints.max_uV = + pVoltage[mtk_ldos[i].desc.n_voltages - 1]; + mtk_ldos[i].init_data.constraints.min_uV = + pVoltage[0]; + } else { + mtk_ldos[i].init_data.constraints.max_uV = + (mtk_ldos[i].desc.n_voltages - + 1) * mtk_ldos[i].desc.uV_step + + mtk_ldos[i].desc.min_uV; + mtk_ldos[i].init_data.constraints.min_uV = + mtk_ldos[i].desc.min_uV; + PMICLOG("test man_uv:%d min_uv:%d\n", + (mtk_ldos[i].desc.n_voltages - + 1) * mtk_ldos[i].desc.uV_step + + mtk_ldos[i].desc.min_uV, + mtk_ldos[i].desc.min_uV); + } + } + PMICLOG("min_uv:%d max_uv:%d\n", + mtk_ldos[i].init_data.constraints.min_uV, + mtk_ldos[i].init_data.constraints.max_uV); + } + + mtk_ldos[i].desc.owner = THIS_MODULE; + + mtk_ldos[i].rdev = + regulator_register(&mtk_ldos[i].desc, &mtk_ldos[i].config); + if (IS_ERR(mtk_ldos[i].rdev)) { + ret = PTR_ERR(mtk_ldos[i].rdev); + PMICLOG("[regulator_register] failed to register %s (%d)\n", + mtk_ldos[i].desc.name, ret); + } else { + PMICLOG("[regulator_register] pass to register %s\n", + mtk_ldos[i].desc.name); + } + mtk_ldos[i].reg = regulator_get(&(dev->dev), mtk_ldos[i].desc.name); + isEn = regulator_is_enabled(mtk_ldos[i].reg); + if (isEn != 0) { + PMICLOG("[regulator] %s is default on\n", mtk_ldos[i].desc.name); + /*ret=regulator_enable(mtk_ldos[i].reg);*/ + } + } + } +#endif /* End of #if !defined CONFIG_MTK_LEGACY */ + ret = register_pm_notifier(&pmic_regulator_pm_notifier_block); + if (ret) + PMICLOG("****failed to register PM notifier %d\n", ret); + +} + + + +void PMIC6351_regulator_test(void) +{ + int i = 0, j; + int ret1, ret2; + struct regulator *reg; + + for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) { + if (mtk_ldos[i].isUsedable == 1) { + reg = mtk_ldos[i].reg; + PMICLOG("[regulator enable test] %s\n", mtk_ldos[i].desc.name); + + ret1 = regulator_enable(reg); + ret2 = regulator_is_enabled(reg); + + if (ret2 == pmic_get_register_value(mtk_ldos[i].en_reg)) { + PMICLOG("[enable test pass]\n"); + } else { + PMICLOG("[enable test fail] ret = %d enable = %d addr:0x%x reg:0x%x\n", + ret1, ret2, pmu_flags_table[mtk_ldos[i].en_reg].offset, + pmic_get_register_value(mtk_ldos[i].en_reg)); + } + + ret1 = regulator_disable(reg); + ret2 = regulator_is_enabled(reg); + + if (ret2 == pmic_get_register_value(mtk_ldos[i].en_reg)) { + PMICLOG("[disable test pass]\n"); + } else { + PMICLOG("[disable test fail] ret = %d enable = %d addr:0x%x reg:0x%x\n", + ret1, ret2, pmu_flags_table[mtk_ldos[i].en_reg].offset, + pmic_get_register_value(mtk_ldos[i].en_reg)); + } + + } + } + + for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) { + const int *pVoltage; + + reg = mtk_ldos[i].reg; + if (mtk_ldos[i].isUsedable == 1) { + PMICLOG("[regulator voltage test] %s voltage:%d\n", + mtk_ldos[i].desc.name, mtk_ldos[i].desc.n_voltages); + + if (mtk_ldos[i].pvoltages != NULL) { + pVoltage = (const int *)mtk_ldos[i].pvoltages; + + for (j = 0; j < mtk_ldos[i].desc.n_voltages; j++) { + int rvoltage; + + regulator_set_voltage(reg, pVoltage[j], pVoltage[j]); + rvoltage = regulator_get_voltage(reg); + + + if ((j == pmic_get_register_value(mtk_ldos[i].vol_reg)) + && (pVoltage[j] == rvoltage)) { + PMICLOG + ("[%d:%d]:pass set_voltage:%d rvoltage:%d\n", + j, + pmic_get_register_value(mtk_ldos + [i].vol_reg), + pVoltage[j], rvoltage); + + } else { + PMICLOG + ("[%d:%d]:fail set_voltage:%d rvoltage:%d\n", + j, + pmic_get_register_value(mtk_ldos + [i].vol_reg), + pVoltage[j], rvoltage); + } + } + } + } + } + + +} + +/*#if defined CONFIG_MTK_LEGACY*/ +int getHwVoltage(MT65XX_POWER powerId) +{ +#if defined CONFIG_MTK_LEGACY + struct regulator *reg; + + + if (powerId >= ARRAY_SIZE(mtk_ldos)) + return -100; + + if (mtk_ldos[powerId].isUsedable != true) + return -101; + + reg = mtk_ldos[powerId].reg; + + return regulator_get_voltage(reg); +#else + return -1; +#endif +} +EXPORT_SYMBOL(getHwVoltage); + +int isHwPowerOn(MT65XX_POWER powerId) +{ +#if defined CONFIG_MTK_LEGACY + struct regulator *reg; + + if (powerId >= ARRAY_SIZE(mtk_ldos)) + return -100; + + if (mtk_ldos[powerId].isUsedable != true) + return -101; + + reg = mtk_ldos[powerId].reg; + + return regulator_is_enabled(reg); +#else + return -1; +#endif + +} +EXPORT_SYMBOL(isHwPowerOn); + +bool hwPowerOn(MT65XX_POWER powerId, int powerVolt, char *mode_name) +{ +#if defined CONFIG_MTK_LEGACY + struct regulator *reg; + int ret1, ret2; + + if (powerId >= ARRAY_SIZE(mtk_ldos)) + return false; + + if (mtk_ldos[powerId].isUsedable != true) + return false; + + reg = mtk_ldos[powerId].reg; + + ret2 = regulator_set_voltage(reg, powerVolt, powerVolt); + + if (ret2 != 0) { + PMICLOG("hwPowerOn:%s can't set the same volt %d again.", mtk_ldos[powerId].desc.name, powerVolt); + PMICLOG("Or please check:%s volt %d is correct.", mtk_ldos[powerId].desc.name, powerVolt); + } + + ret1 = regulator_enable(reg); + + if (ret1 != 0) + PMICLOG("hwPowerOn:%s enable fail", mtk_ldos[powerId].desc.name); + + PMICLOG("hwPowerOn:%d:%s volt:%d name:%s cnt:%d", powerId, mtk_ldos[powerId].desc.name, + powerVolt, mode_name, mtk_ldos[powerId].rdev->use_count); + return true; +#else + return false; +#endif +} +EXPORT_SYMBOL(hwPowerOn); + +bool hwPowerDown(MT65XX_POWER powerId, char *mode_name) +{ +#if defined CONFIG_MTK_LEGACY + struct regulator *reg; + int ret1; + + if (powerId >= ARRAY_SIZE(mtk_ldos)) + return false; + + if (mtk_ldos[powerId].isUsedable != true) + return false; + reg = mtk_ldos[powerId].reg; + ret1 = regulator_disable(reg); + + if (ret1 != 0) + PMICLOG("hwPowerOn err:ret1:%d ", ret1); + + PMICLOG("hwPowerDown:%d:%s name:%s cnt:%d", powerId, mtk_ldos[powerId].desc.name, mode_name, + mtk_ldos[powerId].rdev->use_count); + return true; +#else + return false; +#endif +} +EXPORT_SYMBOL(hwPowerDown); + +bool hwPowerSetVoltage(MT65XX_POWER powerId, int powerVolt, char *mode_name) +{ +#if defined CONFIG_MTK_LEGACY + struct regulator *reg; + int ret1; + + if (powerId >= ARRAY_SIZE(mtk_ldos)) + return false; + + reg = mtk_ldos[powerId].reg; + + ret1 = regulator_set_voltage(reg, powerVolt, powerVolt); + + if (ret1 != 0) { + PMICLOG("hwPowerSetVoltage:%s can't set the same voltage %d", mtk_ldos[powerId].desc.name, + powerVolt); + } + + + PMICLOG("hwPowerSetVoltage:%d:%s name:%s cnt:%d", powerId, mtk_ldos[powerId].desc.name, + mode_name, mtk_ldos[powerId].rdev->use_count); + return true; +#else + return false; +#endif +} +EXPORT_SYMBOL(hwPowerSetVoltage); + +/*#endif*/ /* End of #if defined CONFIG_MTK_LEGACY */ + +#if PMIC_UT +/* UT test code TBD */ +void low_bat_test(LOW_BATTERY_LEVEL level_val) +{ + pr_err("[low_bat_test] get %d\n", level_val); +} + +void bat_oc_test(BATTERY_OC_LEVEL level_val) +{ + pr_err("[bat_oc_test] get %d\n", level_val); +} + +void bat_per_test(BATTERY_PERCENT_LEVEL level_val) +{ + pr_err("[bat_per_test] get %d\n", level_val); +} +#endif + +/***************************************************************************** + * Low battery call back function + ******************************************************************************/ +#define LBCB_NUM 16 + +#ifndef DISABLE_LOW_BATTERY_PROTECT +#define LOW_BATTERY_PROTECT +#endif + +int g_lowbat_int_bottom = 0; + +#ifdef LOW_BATTERY_PROTECT +/* ex. 3400/5400*4096*/ +#define BAT_HV_THD (POWER_INT0_VOLT*4096/5400) /*ex: 3400mV*/ +#define BAT_LV_1_THD (POWER_INT1_VOLT*4096/5400) /*ex: 3250mV*/ +#define BAT_LV_2_THD (POWER_INT2_VOLT*4096/5400) /*ex: 3000mV*/ + +int g_low_battery_level = 0; +int g_low_battery_stop = 0; +/*give one change to ignore DLPT power off. battery voltage may return to 3.25 or higher +because loading become light. */ +int g_low_battery_if_power_off = 0; + +struct low_battery_callback_table { + void *lbcb; +}; + +struct low_battery_callback_table lbcb_tb[] = { + {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, + {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL} +}; +#endif +void (*low_battery_callback)(LOW_BATTERY_LEVEL); + +void register_low_battery_notify(void (*low_battery_callback) (LOW_BATTERY_LEVEL), + LOW_BATTERY_PRIO prio_val) +{ +#ifdef LOW_BATTERY_PROTECT + PMICLOG("[register_low_battery_notify] start\n"); + + lbcb_tb[prio_val].lbcb = low_battery_callback; + + pr_err("[register_low_battery_notify] prio_val=%d\n", prio_val); +#endif /*end of #ifdef LOW_BATTERY_PROTECT */ +} +#ifdef LOW_BATTERY_PROTECT +void exec_low_battery_callback(LOW_BATTERY_LEVEL low_battery_level) +{ /*0:no limit */ + int i = 0; + + if (g_low_battery_stop == 1) { + pr_err("[exec_low_battery_callback] g_low_battery_stop=%d\n", g_low_battery_stop); + } else { + pr_debug("[exec_low_battery_callback] prio_val=%d,low_battery=%d\n", i, low_battery_level); + for (i = 0; i < LBCB_NUM; i++) { + if (lbcb_tb[i].lbcb != NULL) { + low_battery_callback = lbcb_tb[i].lbcb; + low_battery_callback(low_battery_level); + /* + pr_debug + ("[exec_low_battery_callback] prio_val=%d,low_battery=%d\n", + i, low_battery_level); + */ + } + } + } +} + +void lbat_min_en_setting(int en_val) +{ + pmic_set_register_value(PMIC_AUXADC_LBAT_EN_MIN, en_val); + pmic_set_register_value(PMIC_AUXADC_LBAT_IRQ_EN_MIN, en_val); + pmic_set_register_value(PMIC_RG_INT_EN_BAT_L, en_val); +} + +void lbat_max_en_setting(int en_val) +{ + pmic_set_register_value(PMIC_AUXADC_LBAT_EN_MAX, en_val); + pmic_set_register_value(PMIC_AUXADC_LBAT_IRQ_EN_MAX, en_val); + pmic_set_register_value(PMIC_RG_INT_EN_BAT_H, en_val); +} + +void low_battery_protect_init(void) +{ + /*default setting */ + pmic_set_register_value(PMIC_AUXADC_LBAT_DEBT_MIN, 0); + pmic_set_register_value(PMIC_AUXADC_LBAT_DEBT_MAX, 0); + pmic_set_register_value(PMIC_AUXADC_LBAT_DET_PRD_15_0, 1); + pmic_set_register_value(PMIC_AUXADC_LBAT_DET_PRD_19_16, 0); + + pmic_set_register_value(PMIC_AUXADC_LBAT_VOLT_MAX, BAT_HV_THD); + pmic_set_register_value(PMIC_AUXADC_LBAT_VOLT_MIN, BAT_LV_1_THD); + + lbat_min_en_setting(1); + lbat_max_en_setting(0); + + pr_err("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_AUXADC_LBAT3, upmu_get_reg_value(MT6351_AUXADC_LBAT3), + MT6351_AUXADC_LBAT4, upmu_get_reg_value(MT6351_AUXADC_LBAT4), + MT6351_INT_CON0, upmu_get_reg_value(MT6351_INT_CON0) + ); + + pr_err("[low_battery_protect_init] %d mV, %d mV, %d mV\n", + POWER_INT0_VOLT, POWER_INT1_VOLT, POWER_INT2_VOLT); + PMICLOG("[low_battery_protect_init] Done\n"); + +} + +#endif /*#ifdef LOW_BATTERY_PROTECT*/ + +/***************************************************************************** + * Battery OC call back function + ******************************************************************************/ +#define OCCB_NUM 16 + +#ifndef DISABLE_BATTERY_OC_PROTECT +#define BATTERY_OC_PROTECT +#endif + +#ifdef BATTERY_OC_PROTECT +/* ex. Ireg = 65535 - (I * 950000uA / 2 / 158.122 / CAR_TUNE_VALUE * 100)*/ +/* (950000/2/158.122)*100~=300400*/ + +#if defined(CONFIG_MTK_SMART_BATTERY) +#define BAT_OC_H_THD \ +(65535-((300400*POWER_BAT_OC_CURRENT_H/1000)/batt_meter_cust_data.car_tune_value)) /*ex: 4670mA*/ +#define BAT_OC_L_THD \ +(65535-((300400*POWER_BAT_OC_CURRENT_L/1000)/batt_meter_cust_data.car_tune_value)) /*ex: 5500mA*/ + +#define BAT_OC_H_THD_RE \ +(65535-((300400*POWER_BAT_OC_CURRENT_H_RE/1000)/batt_meter_cust_data.car_tune_value)) /*ex: 3400mA*/ +#define BAT_OC_L_THD_RE \ +(65535-((300400*POWER_BAT_OC_CURRENT_L_RE/1000)/batt_meter_cust_data.car_tune_value)) /*ex: 4000mA*/ +#else +#define BAT_OC_H_THD 0xc047 +#define BAT_OC_L_THD 0xb4f4 +#define BAT_OC_H_THD_RE 0xc047 +#define BAT_OC_L_THD_RE 0xb4f4 +#endif /* end of #if defined(CONFIG_MTK_SMART_BATTERY) */ +int g_battery_oc_level = 0; +int g_battery_oc_stop = 0; + +struct battery_oc_callback_table { + void *occb; +}; + +struct battery_oc_callback_table occb_tb[] = { + {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, + {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL} +}; +#endif /*end of #ifdef BATTERY_OC_PROTECT*/ +void (*battery_oc_callback)(BATTERY_OC_LEVEL); + +void register_battery_oc_notify(void (*battery_oc_callback) (BATTERY_OC_LEVEL), + BATTERY_OC_PRIO prio_val) +{ +#ifdef BATTERY_OC_PROTECT + PMICLOG("[register_battery_oc_notify] start\n"); + + occb_tb[prio_val].occb = battery_oc_callback; + + pr_err("[register_battery_oc_notify] prio_val=%d\n", prio_val); +#endif +} + +void exec_battery_oc_callback(BATTERY_OC_LEVEL battery_oc_level) +{ /*0:no limit */ +#ifdef BATTERY_OC_PROTECT + int i = 0; + + if (g_battery_oc_stop == 1) { + pr_err("[exec_battery_oc_callback] g_battery_oc_stop=%d\n", g_battery_oc_stop); + } else { + for (i = 0; i < OCCB_NUM; i++) { + if (occb_tb[i].occb != NULL) { + battery_oc_callback = occb_tb[i].occb; + battery_oc_callback(battery_oc_level); + pr_err + ("[exec_battery_oc_callback] prio_val=%d,battery_oc_level=%d\n", + i, battery_oc_level); + } + } + } +#endif +} +#ifdef BATTERY_OC_PROTECT +void bat_oc_h_en_setting(int en_val) +{ + pmic_set_register_value(PMIC_RG_INT_EN_FG_CUR_H, en_val); + /* mt6325_upmu_set_rg_int_en_fg_cur_h(en_val); */ +} + +void bat_oc_l_en_setting(int en_val) +{ + pmic_set_register_value(PMIC_RG_INT_EN_FG_CUR_L, en_val); + /*mt6325_upmu_set_rg_int_en_fg_cur_l(en_val); */ +} + +void battery_oc_protect_init(void) +{ + pmic_set_register_value(PMIC_FG_CUR_HTH, BAT_OC_H_THD); + /*mt6325_upmu_set_fg_cur_hth(BAT_OC_H_THD); */ + pmic_set_register_value(PMIC_FG_CUR_LTH, BAT_OC_L_THD); + /*mt6325_upmu_set_fg_cur_lth(BAT_OC_L_THD); */ + + bat_oc_h_en_setting(0); + bat_oc_l_en_setting(1); + + pr_err("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_PMIC_FG_CUR_HTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_HTH_ADDR), + MT6351_PMIC_FG_CUR_LTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_LTH_ADDR), + MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR, upmu_get_reg_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR) + ); + + pr_err("[battery_oc_protect_init] %d mA, %d mA\n", + POWER_BAT_OC_CURRENT_H, POWER_BAT_OC_CURRENT_L); + PMICLOG("[battery_oc_protect_init] Done\n"); +} + +void battery_oc_protect_reinit(void) +{ +#ifdef BATTERY_OC_PROTECT + pmic_set_register_value(PMIC_FG_CUR_HTH, BAT_OC_H_THD_RE); + /*mt6325_upmu_set_fg_cur_hth(BAT_OC_H_THD_RE); */ + pmic_set_register_value(PMIC_FG_CUR_LTH, BAT_OC_L_THD_RE); + /*mt6325_upmu_set_fg_cur_lth(BAT_OC_L_THD_RE); */ + + pr_err("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_PMIC_FG_CUR_HTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_HTH_ADDR), + MT6351_PMIC_FG_CUR_LTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_LTH_ADDR), + MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR, upmu_get_reg_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR) + ); + + pr_err("[battery_oc_protect_reinit] %d mA, %d mA\n", + POWER_BAT_OC_CURRENT_H_RE, POWER_BAT_OC_CURRENT_L_RE); + pr_err("[battery_oc_protect_reinit] Done\n"); +#else + pr_warn("[battery_oc_protect_reinit] no define BATTERY_OC_PROTECT\n"); +#endif +} +#endif /* #ifdef BATTERY_OC_PROTECT */ + + +/***************************************************************************** + * 15% notify service + ******************************************************************************/ +#ifndef DISABLE_BATTERY_PERCENT_PROTECT +#define BATTERY_PERCENT_PROTECT +#endif + +#ifdef BATTERY_PERCENT_PROTECT +static struct hrtimer bat_percent_notify_timer; +static struct task_struct *bat_percent_notify_thread; +static bool bat_percent_notify_flag; +static DECLARE_WAIT_QUEUE_HEAD(bat_percent_notify_waiter); +#endif +#if !defined CONFIG_HAS_WAKELOCKS +struct wakeup_source bat_percent_notify_lock; +#else +struct wake_lock bat_percent_notify_lock; +#endif + +static DEFINE_MUTEX(bat_percent_notify_mutex); + +#ifdef BATTERY_PERCENT_PROTECT +/*extern unsigned int bat_get_ui_percentage(void);*/ + +#define BPCB_NUM 16 + +int g_battery_percent_level = 0; +int g_battery_percent_stop = 0; + +#define BAT_PERCENT_LINIT 15 + +struct battery_percent_callback_table { + void *bpcb; +}; + +struct battery_percent_callback_table bpcb_tb[] = { + {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, + {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL} +}; +#endif /* end of #ifdef BATTERY_PERCENT_PROTECT */ +void (*battery_percent_callback)(BATTERY_PERCENT_LEVEL); + +void register_battery_percent_notify(void (*battery_percent_callback)(BATTERY_PERCENT_LEVEL), + BATTERY_PERCENT_PRIO prio_val) +{ +#ifdef BATTERY_PERCENT_PROTECT + PMICLOG("[register_battery_percent_notify] start\n"); + + bpcb_tb[prio_val].bpcb = battery_percent_callback; + + pr_err("[register_battery_percent_notify] prio_val=%d\n", prio_val); + + if ((g_battery_percent_stop == 0) && (g_battery_percent_level == 1)) { +#ifdef DISABLE_DLPT_FEATURE + pr_err("[register_battery_percent_notify] level l happen\n"); + battery_percent_callback(BATTERY_PERCENT_LEVEL_1); +#else + if (prio_val == BATTERY_PERCENT_PRIO_FLASHLIGHT) { + pr_err("[register_battery_percent_notify at DLPT] level l happen\n"); + battery_percent_callback(BATTERY_PERCENT_LEVEL_1); + } +#endif + } +#endif /* end of #ifdef BATTERY_PERCENT_PROTECT */ +} + +#ifdef BATTERY_PERCENT_PROTECT +void exec_battery_percent_callback(BATTERY_PERCENT_LEVEL battery_percent_level) +{ /*0:no limit */ +#ifdef DISABLE_DLPT_FEATURE + int i = 0; +#endif + + if (g_battery_percent_stop == 1) { + pr_err("[exec_battery_percent_callback] g_battery_percent_stop=%d\n", + g_battery_percent_stop); + } else { +#ifdef DISABLE_DLPT_FEATURE + for (i = 0; i < BPCB_NUM; i++) { + if (bpcb_tb[i].bpcb != NULL) { + battery_percent_callback = bpcb_tb[i].bpcb; + battery_percent_callback(battery_percent_level); + pr_err + ("[exec_battery_percent_callback] prio_val=%d,battery_percent_level=%d\n", + i, battery_percent_level); + } + } +#else + battery_percent_callback = bpcb_tb[BATTERY_PERCENT_PRIO_FLASHLIGHT].bpcb; + battery_percent_callback(battery_percent_level); + pr_err + ("[exec_battery_percent_callback at DLPT] prio_val=%d,battery_percent_level=%d\n", + BATTERY_PERCENT_PRIO_FLASHLIGHT, battery_percent_level); +#endif + } +} + +int bat_percent_notify_handler(void *unused) +{ + ktime_t ktime; + int bat_per_val = 0; + + do { + ktime = ktime_set(10, 0); + + wait_event_interruptible(bat_percent_notify_waiter, + (bat_percent_notify_flag == true)); + +#if !defined CONFIG_HAS_WAKELOCKS + __pm_stay_awake(&bat_percent_notify_lock); +#else + wake_lock(&bat_percent_notify_lock); +#endif + mutex_lock(&bat_percent_notify_mutex); + +#if defined(CONFIG_MTK_SMART_BATTERY) + bat_per_val = bat_get_ui_percentage(); +#endif + if ((upmu_get_rgs_chrdet() == 0) && (g_battery_percent_level == 0) + && (bat_per_val <= BAT_PERCENT_LINIT)) { + g_battery_percent_level = 1; + exec_battery_percent_callback(BATTERY_PERCENT_LEVEL_1); + } else if ((g_battery_percent_level == 1) && (bat_per_val > BAT_PERCENT_LINIT)) { + g_battery_percent_level = 0; + exec_battery_percent_callback(BATTERY_PERCENT_LEVEL_0); + } else { + } + bat_percent_notify_flag = false; + + PMICLOG("bat_per_level=%d,bat_per_val=%d\n", g_battery_percent_level, bat_per_val); + + mutex_unlock(&bat_percent_notify_mutex); +#if !defined CONFIG_HAS_WAKELOCKS + __pm_relax(&bat_percent_notify_lock); +#else + wake_unlock(&bat_percent_notify_lock); +#endif + + hrtimer_start(&bat_percent_notify_timer, ktime, HRTIMER_MODE_REL); + + } while (!kthread_should_stop()); + + return 0; +} + +enum hrtimer_restart bat_percent_notify_task(struct hrtimer *timer) +{ + bat_percent_notify_flag = true; + wake_up_interruptible(&bat_percent_notify_waiter); + PMICLOG("bat_percent_notify_task is called\n"); + + return HRTIMER_NORESTART; +} + +void bat_percent_notify_init(void) +{ + ktime_t ktime; + + ktime = ktime_set(20, 0); + hrtimer_init(&bat_percent_notify_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + bat_percent_notify_timer.function = bat_percent_notify_task; + hrtimer_start(&bat_percent_notify_timer, ktime, HRTIMER_MODE_REL); + + bat_percent_notify_thread = + kthread_run(bat_percent_notify_handler, 0, "bat_percent_notify_thread"); + if (IS_ERR(bat_percent_notify_thread)) + pr_err("Failed to create bat_percent_notify_thread\n"); + else + pr_err("Create bat_percent_notify_thread : done\n"); +} +#endif /* #ifdef BATTERY_PERCENT_PROTECT */ + +/***************************************************************************** + * DLPT service + ******************************************************************************/ +#ifndef DISABLE_DLPT_FEATURE +#define DLPT_FEATURE_SUPPORT +#endif + +#ifdef DLPT_FEATURE_SUPPORT + +unsigned int ptim_bat_vol = 0; +signed int ptim_R_curr = 0; +int ptim_imix = 0; +int ptim_rac_val_avg = 0; + +signed int pmic_ptimretest = 0; + + + +unsigned int ptim_cnt = 0; + +signed int count_time_out_adc_imp = 36; +unsigned int count_adc_imp = 0; + + +int do_ptim_internal(bool isSuspend, unsigned int *bat, signed int *cur) +{ + unsigned int vbat_reg; + int ret = 0; + + count_adc_imp = 0; + /*PMICLOG("[do_ptim] start\n"); */ + + /*pmic_set_register_value(PMIC_RG_AUXADC_RST,1); */ + /*pmic_set_register_value(PMIC_RG_AUXADC_RST,0); */ + + upmu_set_reg_value(0x0eac, 0x0006); + + pmic_set_register_value(PMIC_AUXADC_IMP_AUTORPT_PRD, 6); + pmic_set_register_value(PMIC_RG_AUXADC_SMPS_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN, 0); + + pmic_set_register_value(PMIC_RG_AUXADC_CK_PDN_HWEN, 0); + pmic_set_register_value(PMIC_RG_AUXADC_CK_PDN, 0); + + pmic_set_register_value(PMIC_AUXADC_CLR_IMP_CNT_STOP, 1); + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_CLR, 1); + + /*restore to initial state */ + pmic_set_register_value(PMIC_AUXADC_CLR_IMP_CNT_STOP, 0); + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_CLR, 0); + + /*set issue interrupt */ + /*pmic_set_register_value(PMIC_RG_INT_EN_AUXADC_IMP,1); */ + +#if defined(SWCHR_POWER_PATH) + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_CHSEL, 1); +#else + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_CHSEL, 0); +#endif + pmic_set_register_value(PMIC_AUXADC_IMP_AUTORPT_EN, 1); + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_CNT, 3); + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_MODE, 1); + +/* MT6351_PMICLOG("[do_ptim] end %d %d\n",pmic_get_register_value +(MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN),pmic_get_register_value( +MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN));*/ + + while (pmic_get_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_STATUS) == 0) { + /*MT6351_PMICLOG("[do_ptim] MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS= %d\n", + pmic_get_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_STATUS)); */ + if ((count_adc_imp++) > count_time_out_adc_imp) { + pr_err("do_ptim over %d times/ms\n", count_adc_imp); + ret = 1; + break; + } + mdelay(1); + } + + /*disable */ + pmic_set_register_value(PMIC_AUXADC_IMP_AUTORPT_EN, 0); /*typo */ + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_MODE, 0); + + /*clear irq */ + pmic_set_register_value(PMIC_AUXADC_CLR_IMP_CNT_STOP, 1); + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_CLR, 1); + pmic_set_register_value(PMIC_AUXADC_CLR_IMP_CNT_STOP, 0); + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_CLR, 0); + + /*PMICLOG("[do_ptim2] 0xee8=0x%x 0x2c6=0x%x\n", upmu_get_reg_value + (0xee8),upmu_get_reg_value(0x2c6));*/ + + + /*pmic_set_register_value(PMIC_RG_INT_STATUS_AUXADC_IMP,1);write 1 to clear ! */ + /*pmic_set_register_value(PMIC_RG_INT_EN_AUXADC_IMP,0); */ + + + vbat_reg = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_IMP_AVG); + /*ptim_bat_vol = (vbat_reg * 3 * 18000) / 32768;*/ + *bat = (vbat_reg * 3 * 18000) / 32768; + +#if defined(CONFIG_MTK_SMART_BATTERY) + fgauge_read_IM_current((void *)cur); +#else + *cur = 0; +#endif +/* pr_err("do_ptim_internal : bat %d cur %d\n", *bat, *cur); */ + +#if defined(SWCHR_POWER_PATH) +/* pr_err("do_ptim_internal test: bat %d cur %d\n", *bat, *cur); */ +#endif + + + + return ret; +} + +int do_ptim(bool isSuspend) +{ + int ret; + + if (isSuspend == false) + pmic_auxadc_lock(); + + ret = do_ptim_internal(isSuspend, &ptim_bat_vol, &ptim_R_curr); + + if (isSuspend == false) + pmic_auxadc_unlock(); + return ret; +} + +int do_ptim_ex(bool isSuspend, unsigned int *bat, signed int *cur) +{ + int ret; + + if (isSuspend == false) + pmic_auxadc_lock(); + + ret = do_ptim_internal(isSuspend, bat, cur); + + if (isSuspend == false) + pmic_auxadc_unlock(); + return ret; +} + +void get_ptim_value(bool isSuspend, unsigned int *bat, signed int *cur) +{ + if (isSuspend == false) + pmic_auxadc_lock(); + *bat = ptim_bat_vol; + *cur = ptim_R_curr; + if (isSuspend == false) + pmic_auxadc_unlock(); +} + + + +void enable_dummy_load(unsigned int en) +{ + + if (en == 1) { + /*1. disable isink pdn */ + pmic_set_register_value(PMIC_RG_DRV_ISINK3_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_DRV_ISINK2_CK_PDN, 0); + /* + pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_PDN, 0); + */ + pmic_set_register_value(PMIC_RG_DRV_32K_CK_PDN, 0); + + /*1. disable isink pdn */ + pmic_set_register_value(PMIC_RG_DRV_CHRIND_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_DRV_ISINK7_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_DRV_ISINK6_CK_PDN, 0); + /* + pmic_set_register_value(PMIC_RG_DRV_ISINK5_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_DRV_ISINK4_CK_PDN, 0); + */ + + /* enable isink step */ + pmic_set_register_value(PMIC_ISINK_CH2_STEP, 0x7); + pmic_set_register_value(PMIC_ISINK_CH3_STEP, 0x7); + pmic_set_register_value(PMIC_ISINK_CH6_STEP, 0x7); + pmic_set_register_value(PMIC_ISINK_CH7_STEP, 0x7); + + /*enable isink */ + pmic_set_register_value(PMIC_ISINK_CH7_BIAS_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CH6_BIAS_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CH3_BIAS_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CH2_BIAS_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CHOP7_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CHOP6_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CHOP3_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CHOP2_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CH7_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CH6_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CH3_EN, 0x1); + pmic_set_register_value(PMIC_ISINK_CH2_EN, 0x1); + /*PMICLOG("[enable dummy load]\n"); */ + } else { + /*upmu_set_reg_value(0x828,0x0cc0); */ +#if defined MT6328 + pmic_set_register_value(PMIC_ISINK_CH2_EN, 0); + pmic_set_register_value(PMIC_ISINK_CH3_EN, 0); +#endif + pmic_set_register_value(PMIC_ISINK_CH7_EN, 0); + pmic_set_register_value(PMIC_ISINK_CH6_EN, 0); + pmic_set_register_value(PMIC_ISINK_CH3_EN, 0); + pmic_set_register_value(PMIC_ISINK_CH2_EN, 0); + pmic_set_register_value(PMIC_ISINK_CHOP7_EN, 0); + pmic_set_register_value(PMIC_ISINK_CHOP6_EN, 0); + pmic_set_register_value(PMIC_ISINK_CHOP3_EN, 0); + pmic_set_register_value(PMIC_ISINK_CHOP2_EN, 0); + pmic_set_register_value(PMIC_ISINK_CH7_BIAS_EN, 0); + pmic_set_register_value(PMIC_ISINK_CH6_BIAS_EN, 0); + pmic_set_register_value(PMIC_ISINK_CH3_BIAS_EN, 0); + pmic_set_register_value(PMIC_ISINK_CH2_BIAS_EN, 0); + + /*1. enable isink pdn */ + pmic_set_register_value(PMIC_RG_DRV_ISINK3_CK_PDN, 0x1); + pmic_set_register_value(PMIC_RG_DRV_ISINK2_CK_PDN, 0x1); + pmic_set_register_value(PMIC_RG_DRV_32K_CK_PDN, 0x1); + + /*1. enable isink pdn */ + pmic_set_register_value(PMIC_RG_DRV_CHRIND_CK_PDN, 0x1); + pmic_set_register_value(PMIC_RG_DRV_ISINK7_CK_PDN, 0x1); + pmic_set_register_value(PMIC_RG_DRV_ISINK6_CK_PDN, 0x1); + + /*pmic_set_register_value(PMIC_RG_VIBR_EN,0); */ + /*PMICLOG("[disable dummy load]\n"); */ + } + +} + +#endif /* #ifdef DLPT_FEATURE_SUPPORT */ + +#ifdef DLPT_FEATURE_SUPPORT +static struct hrtimer dlpt_notify_timer; +static struct task_struct *dlpt_notify_thread; +static bool dlpt_notify_flag; +static DECLARE_WAIT_QUEUE_HEAD(dlpt_notify_waiter); +#endif +#if !defined CONFIG_HAS_WAKELOCKS +struct wakeup_source dlpt_notify_lock; +#else +struct wake_lock dlpt_notify_lock; +#endif +static DEFINE_MUTEX(dlpt_notify_mutex); + +#ifdef DLPT_FEATURE_SUPPORT +#define DLPT_NUM 16 +/* This define is used to filter smallest and largest voltage and current. +To avoid auxadc measurement interference issue. */ +#define DLPT_SORT_IMIX_VOLT_CURR 1 + + +int g_dlpt_stop = 0; +unsigned int g_dlpt_val = 0; + +int g_dlpt_start = 0; + + +int g_imix_val = 0; +int g_imix_val_pre = 0; +int g_low_per_timer = 0; +int g_low_per_timeout_val = 60; + + +int g_lbatInt1 = POWER_INT2_VOLT * 10; + +struct dlpt_callback_table { + void *dlpt_cb; +}; + +struct dlpt_callback_table dlpt_cb_tb[] = { + {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, + {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL} +}; + +void (*dlpt_callback)(unsigned int); + +void register_dlpt_notify(void (*dlpt_callback) (unsigned int), DLPT_PRIO prio_val) +{ + PMICLOG("[register_dlpt_notify] start\n"); + + dlpt_cb_tb[prio_val].dlpt_cb = dlpt_callback; + + pr_err("[register_dlpt_notify] prio_val=%d\n", prio_val); + + if ((g_dlpt_stop == 0) && (g_dlpt_val != 0)) { + pr_err("[register_dlpt_notify] dlpt happen\n"); + dlpt_callback(g_dlpt_val); + } +} + +void exec_dlpt_callback(unsigned int dlpt_val) +{ + int i = 0; + + g_dlpt_val = dlpt_val; + + if (g_dlpt_stop == 1) { + pr_err("[exec_dlpt_callback] g_dlpt_stop=%d\n", g_dlpt_stop); + } else { + for (i = 0; i < DLPT_NUM; i++) { + if (dlpt_cb_tb[i].dlpt_cb != NULL) { + dlpt_callback = dlpt_cb_tb[i].dlpt_cb; + dlpt_callback(g_dlpt_val); + /* pr_debug("[exec_dlpt_callback] g_dlpt_val=%d\n", g_dlpt_val); */ + } + } + } +} + +/* +int get_dlpt_iavg(int is_use_zcv) +{ + int bat_cap_val = 0; + int zcv_val = 0; + int vsys_min_2_val = POWER_INT2_VOLT; + int rbat_val = 0; + int rdc_val = 0; + int iavg_val = 0; + + bat_cap_val = bat_get_ui_percentage(); + + if(is_use_zcv == 1) + zcv_val = fgauge_read_v_by_d(100-bat_cap_val); + else + { + #if defined(SWCHR_POWER_PATH) + zcv_val = PMIC_IMM_GetOneChannelValue(MT6351_PMIC_AUX_ISENSE_AP,5,1); + #else + zcv_val = PMIC_IMM_GetOneChannelValue(MT6351_PMIC_AUX_BATSNS_AP,5,1); + #endif + } + rbat_val = fgauge_read_r_bat_by_v(zcv_val); + rdc_val = CUST_R_FG_OFFSET+R_FG_VALUE+rbat_val; + + if(rdc_val==0) + rdc_val=1; + iavg_val = ((zcv_val-vsys_min_2_val)*1000)/rdc_val; + + return iavg_val; +} + +int get_real_volt(int val)*/ /*0.1mV*/ +/* +{ + int ret = 0; + ret = val&0x7FFF; + ret = (ret*4*1800*10)/32768; + return ret; +} + +int get_real_curr(int val)*/ /*0.1mA*/ +/* +{ + + int ret=0; + + if ( val > 32767 ) { + ret = val-65535; + ret = ret-(ret*2); + } else + ret = val; + ret = ret*158122; + do_div(ret, 100000); + ret = (ret*20)/R_FG_VALUE; + ret = ((ret*CAR_TUNE_VALUE)/100); + + return ret; +} +*/ +int get_rac_val(void) +{ + int volt_1 = 0; + int volt_2 = 0; + int curr_1 = 0; + int curr_2 = 0; + int rac_cal = 0; + int ret = 0; + bool retry_state = false; + int retry_count = 0; + + do { + /*adc and fg-------------------------------------------------------- */ + do_ptim(true); + + pmic_spm_crit2("[1,Trigger ADC PTIM mode] volt1=%d, curr_1=%d\n", ptim_bat_vol, + ptim_R_curr); + volt_1 = ptim_bat_vol; + curr_1 = ptim_R_curr; + + pmic_spm_crit2("[2,enable dummy load]"); + enable_dummy_load(1); + mdelay(50); + /*Wait --------------------------------------------------------------*/ + + /*adc and fg-------------------------------------------------------- */ + do_ptim(true); + + pmic_spm_crit2("[3,Trigger ADC PTIM mode again] volt2=%d, curr_2=%d\n", + ptim_bat_vol, ptim_R_curr); + volt_2 = ptim_bat_vol; + curr_2 = ptim_R_curr; + + /*Disable dummy load-------------------------------------------------*/ + enable_dummy_load(0); + + /*Calculate Rac------------------------------------------------------ */ + if ((curr_2 - curr_1) >= 700 && (curr_2 - curr_1) <= 1200 + && (volt_1 - volt_2) >= 80) { + /*40.0mA */ + rac_cal = ((volt_1 - volt_2) * 1000) / (curr_2 - curr_1); /*m-ohm */ + + if (rac_cal < 0) + ret = (rac_cal - (rac_cal * 2)) * 1; + else + ret = rac_cal * 1; + + } else { + ret = -1; + pmic_spm_crit2("[4,Calculate Rac] bypass due to (curr_x-curr_y) < 40mA\n"); + } + + pmic_spm_crit2 + ("volt_1 = %d,volt_2 = %d,curr_1 = %d,curr_2 = %d,rac_cal = %d,ret = %d,retry_count = %d\n", + volt_1, volt_2, curr_1, curr_2, rac_cal, ret, retry_count); + + pmic_spm_crit2(" %d,%d,%d,%d,%d,%d,%d\n", + volt_1, volt_2, curr_1, curr_2, rac_cal, ret, retry_count); + + + /*------------------------*/ + retry_count++; + + if ((retry_count < 3) && (ret == -1)) + retry_state = true; + else + retry_state = false; + + } while (retry_state == true); + + return ret; +} + +int get_dlpt_imix_spm(void) +{ +#if defined(CONFIG_MTK_SMART_BATTERY) + int rac_val[5], rac_val_avg; +#if 0 + int volt[5], curr[5]; + int volt_avg = 0, curr_avg = 0; + int imix; +#endif + int i; + static unsigned int pre_ui_soc = 101; + unsigned int ui_soc; + + ui_soc = bat_get_ui_percentage(); + + if (ui_soc != pre_ui_soc) { + pre_ui_soc = ui_soc; + } else { + pmic_spm_crit2("[dlpt_R] pre_SOC=%d SOC=%d skip\n", pre_ui_soc, ui_soc); + return 0; + } + + + for (i = 0; i < 2; i++) { + rac_val[i] = get_rac_val(); + if (rac_val[i] == -1) + return -1; + } + + /*rac_val_avg=rac_val[0]+rac_val[1]+rac_val[2]+rac_val[3]+rac_val[4];*/ + /*rac_val_avg=rac_val_avg/5;*/ + /*PMICLOG("[dlpt_R] %d,%d,%d,%d,%d %d\n",rac_val[0],rac_val[1],rac_val[2],rac_val[3],rac_val[4],rac_val_avg);*/ + + rac_val_avg = rac_val[0] + rac_val[1]; + rac_val_avg = rac_val_avg / 2; + /*pmic_spm_crit2("[dlpt_R] %d,%d,%d\n", rac_val[0], rac_val[1], rac_val_avg);*/ + pr_err("[dlpt_R] %d,%d,%d\n", rac_val[0], rac_val[1], rac_val_avg); + + if (rac_val_avg > 100) + ptim_rac_val_avg = rac_val_avg; + +/* + for(i=0;i<5;i++) + { + do_ptim(); + + volt[i]=ptim_bat_vol; + curr[i]=ptim_R_curr; + volt_avg+=ptim_bat_vol; + curr_avg+=ptim_R_curr; + } + + volt_avg=volt_avg/5; + curr_avg=curr_avg/5; + + imix=curr_avg+(volt_avg-g_lbatInt1)*1000/ptim_rac_val_avg; + + pmic_spm_crit2("[dlpt_Imix] %d,%d,%d,%d,%d,%d,%d\n",volt_avg,curr_avg,g_lbatInt1, + ptim_rac_val_avg,imix,BMT_status.SOC,bat_get_ui_percentage()); + + ptim_imix=imix; +*/ +#endif /* end of #if defined(CONFIG_MTK_SMART_BATTERY) */ + return 0; + +} + +#if DLPT_SORT_IMIX_VOLT_CURR +void pmic_swap(int *a, int *b) +{ + int temp = *a; + *a = *b; + *b = temp; +} + + +void pmic_quicksort(int *data, int left, int right) +{ + int pivot, i, j; + + if (left >= right) + return; + + pivot = data[left]; + + i = left + 1; + j = right; + + while (1) { + while (i <= right) { + if (data[i] > pivot) + break; + i = i + 1; + } + + while (j > left) { + if (data[j] < pivot) + break; + j = j - 1; + } + + if (i > j) + break; + + pmic_swap(&data[i], &data[j]); + } + + pmic_swap(&data[left], &data[j]); + + pmic_quicksort(data, left, j - 1); + pmic_quicksort(data, j + 1, right); +} +#endif /* end of DLPT_SORT_IMIX_VOLT_CURR*/ +int get_dlpt_imix(void) +{ + /* int rac_val[5], rac_val_avg; */ + int volt[5], curr[5], volt_avg = 0, curr_avg = 0; + int imix; +#if 0 /* debug only */ + int val, val1, val2, val3, val4, val5, ret_val; +#endif + int i, count_do_ptim = 0; + + for (i = 0; i < 5; i++) { + /*adc and fg-------------------------------------------------------- */ + /* do_ptim(false); */ + while (do_ptim(false)) { + if ((count_do_ptim >= 2) && (count_do_ptim < 4)) + pr_err("do_ptim more than twice times\n"); + else if (count_do_ptim > 3) { + pr_err("do_ptim more than five times\n"); + BUG_ON(1); + } else + ; + count_do_ptim++; + } + + volt[i] = ptim_bat_vol; + curr[i] = ptim_R_curr; +#if !DLPT_SORT_IMIX_VOLT_CURR + volt_avg += ptim_bat_vol; + curr_avg += ptim_R_curr; +#endif +#if 0 /* debug only */ + PMICLOG("[get_dlpt_imix:%d] %d,%d,%d,%d\n", i, volt[i], curr[i], volt_avg, curr_avg); + ret_val = pmic_read_interface((unsigned int)(MT6351_AUXADC_ADC29), (&val), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(MT6351_AUXADC_ADC30), (&val1), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(MT6351_FGADC_CON25), (&val2), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(MT6351_AUXADC_IMP0), (&val3), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(MT6351_AUXADC_CON2), (&val4), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(MT6351_AUXADC_LBAT1), (&val5), (0xffff), 0); + pr_debug("[get_dlpt_imix after ptim]MT6351_AUXADC_ADC29 0x%x:0x%x, MT6351_AUXADC_ADC30 0x%x:0x%x, MT6351_FGADC_CON25 0x%x:0x%x\n", + MT6351_AUXADC_ADC29, val, MT6351_AUXADC_ADC30, val1, MT6351_FGADC_CON25, val2); + pr_debug("[get_dlpt_imix after ptim]MT6351_AUXADC_IMP0 0x%x:0x%x, MT6351_AUXADC_CON2 0x%x:0x%x, MT6351_AUXADC_LBAT1 0x%x:0x%x\n", + MT6351_AUXADC_IMP0, val3, MT6351_AUXADC_CON2, val4, MT6351_AUXADC_LBAT1, val5); + ret_val = pmic_read_interface((unsigned int)(MT6351_AUXADC_LBAT2), (&val), (0xffff), 0); + pr_debug("[get_dlpt_imix after ptim]MT6351_AUXADC_LBAT2 0x%x:0x%x\n", + MT6351_AUXADC_LBAT2, val); +#endif + } +#if !DLPT_SORT_IMIX_VOLT_CURR + volt_avg = volt_avg / 5; + curr_avg = curr_avg / 5; +#else + pmic_quicksort(volt, 0, 4); + pmic_quicksort(curr, 0, 4); + volt_avg = volt[1] + volt[2] + volt[3]; + curr_avg = curr[1] + curr[2] + curr[3]; + volt_avg = volt_avg / 3; + curr_avg = curr_avg / 3; +#endif /* end of DLPT_SORT_IMIX_VOLT_CURR*/ + imix = (curr_avg + (volt_avg - g_lbatInt1) * 1000 / ptim_rac_val_avg) / 10; + +#if defined(CONFIG_MTK_SMART_BATTERY) + pr_debug("[get_dlpt_imix] %d,%d,%d,%d,%d,%d,%d\n", volt_avg, curr_avg, g_lbatInt1, + ptim_rac_val_avg, imix, BMT_status.SOC, bat_get_ui_percentage()); +#endif + + ptim_imix = imix; + + return ptim_imix; + +} + + + +int get_dlpt_imix_charging(void) +{ + + int zcv_val = 0; + int vsys_min_1_val = POWER_INT2_VOLT; + int imix_val = 0; +#if defined(SWCHR_POWER_PATH) + zcv_val = PMIC_IMM_GetOneChannelValue(PMIC_AUX_ISENSE_AP, 5, 1); +#else + zcv_val = PMIC_IMM_GetOneChannelValue(PMIC_AUX_BATSNS_AP, 5, 1); +#endif + + imix_val = (zcv_val - vsys_min_1_val) * 1000 / ptim_rac_val_avg * 9 / 10; + PMICLOG("[dlpt] get_dlpt_imix_charging %d %d %d %d\n", + imix_val, zcv_val, vsys_min_1_val, ptim_rac_val_avg); + + return imix_val; +} + + +int dlpt_check_power_off(void) +{ + int ret = 0; + + ret = 0; + if (g_dlpt_start == 0) { + PMICLOG("[dlpt_check_power_off] not start\n"); + } else { +#ifdef LOW_BATTERY_PROTECT + if (g_low_battery_level == 2 && g_lowbat_int_bottom == 1) { + /*1st time receive battery voltage < 3.1V, record it */ + if (g_low_battery_if_power_off == 0) { + g_low_battery_if_power_off++; + pr_err("[dlpt_check_power_off] %d\n", g_low_battery_if_power_off); + } else { + /*2nd time receive battery voltage < 3.1V, wait FG to call power off */ + ret = 1; + pr_err("[dlpt_check_power_off] %d %d\n", ret, g_low_battery_if_power_off); + } + } else { + ret = 0; + /* battery voltage > 3.1V, ignore it */ + g_low_battery_if_power_off = 0; + } +#endif + + PMICLOG("[dlpt_check_power_off]"); + PMICLOG("ptim_imix=%d, POWEROFF_BAT_CURRENT=%d", ptim_imix, POWEROFF_BAT_CURRENT); +#ifdef LOW_BATTERY_PROTECT + PMICLOG(" g_low_battery_level=%d,ret=%d,g_lowbat_int_bottom=%d\n", g_low_battery_level, ret, + g_lowbat_int_bottom); +#endif + } + + return ret; +} + + + +int dlpt_notify_handler(void *unused) +{ + ktime_t ktime; + int pre_ui_soc = 0; + int cur_ui_soc = 0; + int diff_ui_soc = 1; + +#if defined(CONFIG_MTK_SMART_BATTERY) + pre_ui_soc = bat_get_ui_percentage(); +#endif + cur_ui_soc = pre_ui_soc; + + do { + ktime = ktime_set(10, 0); + + wait_event_interruptible(dlpt_notify_waiter, (dlpt_notify_flag == true)); + +#if !defined CONFIG_HAS_WAKELOCKS + __pm_stay_awake(&dlpt_notify_lock); +#else + wake_lock(&dlpt_notify_lock); +#endif + mutex_lock(&dlpt_notify_mutex); + /*---------------------------------*/ + +#if defined(CONFIG_MTK_SMART_BATTERY) + cur_ui_soc = bat_get_ui_percentage(); +#endif + + if (cur_ui_soc <= 1) { + g_low_per_timer += 10; + if (g_low_per_timer > g_low_per_timeout_val) + g_low_per_timer = 0; + PMICLOG("[DLPT] g_low_per_timer=%d,g_low_per_timeout_val=%d\n", + g_low_per_timer, g_low_per_timeout_val); + } else { + g_low_per_timer = 0; + } + + PMICLOG("[dlpt_notify_handler] %d %d %d %d %d\n", pre_ui_soc, cur_ui_soc, + g_imix_val, g_low_per_timer, g_low_per_timeout_val); +/* can enable for ricky's request for >1% battery change TBD + if( ((pre_ui_soc-cur_ui_soc)>=diff_ui_soc) || + ((cur_ui_soc-pre_ui_soc)>=diff_ui_soc) || + (g_imix_val == 0) || + (g_imix_val == -1) || + ( (cur_ui_soc <= 1) && (g_low_per_timer >= g_low_per_timeout_val) ) + + ) +*/ + { + + PMICLOG("[DLPT] is running\n"); + if (ptim_rac_val_avg == 0) + pr_err("[DLPT] ptim_rac_val_avg=0 , skip\n"); + else { + if (upmu_get_rgs_chrdet()) { + g_imix_val = get_dlpt_imix_charging(); + } else { + g_imix_val = get_dlpt_imix(); + +/* + if(g_imix_val != -1) { + if(g_imix_val_pre <= 0) + g_imix_val_pre=g_imix_val; + + if(g_imix_val > g_imix_val_pre) { + PMICLOG("[DLPT] g_imix_val=%d,g_imix_val_pre=%d\n", g_imix_val, g_imix_val_pre); + g_imix_val=g_imix_val_pre; + } + else + g_imix_val_pre=g_imix_val; + } +*/ + } + + /*Notify*/ + if (g_imix_val >= 1) { + if (g_imix_val > IMAX_MAX_VALUE) + g_imix_val = IMAX_MAX_VALUE; + exec_dlpt_callback(g_imix_val); + } else { + exec_dlpt_callback(1); + PMICLOG("[DLPT] return 1\n"); + } + + pre_ui_soc = cur_ui_soc; + + pr_err("[DLPT_final] %d,%d,%d,%d,%d,%d\n", + g_imix_val, g_imix_val_pre, pre_ui_soc, cur_ui_soc, + diff_ui_soc, IMAX_MAX_VALUE); + } + + } + + g_dlpt_start = 1; + dlpt_notify_flag = false; + + /*---------------------------------*/ + mutex_unlock(&dlpt_notify_mutex); +#if !defined CONFIG_HAS_WAKELOCKS + __pm_relax(&dlpt_notify_lock); +#else + wake_unlock(&dlpt_notify_lock); +#endif + + hrtimer_start(&dlpt_notify_timer, ktime, HRTIMER_MODE_REL); + + } while (!kthread_should_stop()); + + return 0; +} + +enum hrtimer_restart dlpt_notify_task(struct hrtimer *timer) +{ + dlpt_notify_flag = true; + wake_up_interruptible(&dlpt_notify_waiter); + PMICLOG("dlpt_notify_task is called\n"); + + return HRTIMER_NORESTART; +} + +int get_system_loading_ma(void) +{ + int fg_val = 0; + + if (g_dlpt_start == 0) + PMICLOG("get_system_loading_ma not ready\n"); + else { +#if defined(CONFIG_MTK_SMART_BATTERY) + fg_val = battery_meter_get_battery_current(); + fg_val = fg_val / 10; + if (battery_meter_get_battery_current_sign() == 1) + fg_val = 0 - fg_val; /* charging*/ + PMICLOG("[get_system_loading_ma] fg_val=%d\n", fg_val); +#endif + } + + return fg_val; +} + + +void dlpt_notify_init(void) +{ + ktime_t ktime; + + ktime = ktime_set(30, 0); + hrtimer_init(&dlpt_notify_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + dlpt_notify_timer.function = dlpt_notify_task; + hrtimer_start(&dlpt_notify_timer, ktime, HRTIMER_MODE_REL); + + dlpt_notify_thread = kthread_run(dlpt_notify_handler, 0, "dlpt_notify_thread"); + if (IS_ERR(dlpt_notify_thread)) + pr_err("Failed to create dlpt_notify_thread\n"); + else + pr_err("Create dlpt_notify_thread : done\n"); + + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 0); + + /*re-init UVLO volt */ + switch (POWER_UVLO_VOLT_LEVEL) { + case 2500: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 0); + break; + case 2550: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 1); + break; + case 2600: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 2); + break; + case 2650: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 3); + break; + case 2700: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 4); + break; + case 2750: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 5); + break; + case 2800: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 6); + break; + case 2850: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 7); + break; + case 2900: + pmic_set_register_value(PMIC_RG_UVLO_VTHL, 8); + break; + default: + PMICLOG("Invalid value(%d)\n", POWER_UVLO_VOLT_LEVEL); + break; + } + pr_err("POWER_UVLO_VOLT_LEVEL=%d, [0x%x]=0x%x\n", + POWER_UVLO_VOLT_LEVEL, MT6351_CHR_CON17, upmu_get_reg_value(MT6351_CHR_CON17)); +} + +#else +int get_dlpt_imix_spm(void) +{ + return 1; +} + + +#endif /*#ifdef DLPT_FEATURE_SUPPORT */ + +int pmic_rdy = 0, usb_rdy = 0; +void pmic_enable_charger_detection_int(int x) +{ + + if (x == 0) { + pmic_rdy = 1; + PMICLOG("[pmic_enable_charger_detection_int] PMIC\n"); + } else if (x == 1) { + usb_rdy = 1; + PMICLOG("[pmic_enable_charger_detection_int] USB\n"); + } + + PMICLOG("[pmic_enable_charger_detection_int] pmic_rdy=%d usb_rdy=%d\n", pmic_rdy, usb_rdy); + if (pmic_rdy == 1 && usb_rdy == 1) { +#if defined(CONFIG_MTK_SMART_BATTERY) + wake_up_bat(); +#endif + PMICLOG("[pmic_enable_charger_detection_int] enable charger detection interrupt\n"); + } +} + +bool is_charger_detection_rdy(void) +{ + + if (pmic_rdy == 1 && usb_rdy == 1) + return true; + else + return false; +} + +int is_ext_buck2_exist(void) +{ +#if defined(CONFIG_MTK_FPGA) + return 0; +#else +#if !defined CONFIG_MTK_LEGACY + return gpiod_get_value(gpio_to_desc(130)); + /*return __gpio_get_value(130);*/ + /*return mt_get_gpio_in(130);*/ +#else + return 0; +#endif +#endif +} + +int is_ext_vbat_boost_exist(void) +{ + return 0; +} + +int is_ext_swchr_exist(void) +{ + return 0; +} + + +/***************************************************************************** + * Enternal SWCHR + ******************************************************************************/ +/* +#ifdef MTK_BQ24261_SUPPORT +extern int is_bq24261_exist(void); +#endif + +int is_ext_swchr_exist(void) +{ + #ifdef MTK_BQ24261_SUPPORT + if (is_bq24261_exist() == 1) + return 1; + else + return 0; + #else + PMICLOG("[is_ext_swchr_exist] no define any HW\n"); + return 0; + #endif +} +*/ + +/***************************************************************************** + * Enternal VBAT Boost status + ******************************************************************************/ +/* +extern int is_tps6128x_sw_ready(void); +extern int is_tps6128x_exist(void); + +int is_ext_vbat_boost_sw_ready(void) +{ + if( (is_tps6128x_sw_ready()==1) ) + return 1; + else + return 0; +} + +int is_ext_vbat_boost_exist(void) +{ + if( (is_tps6128x_exist()==1) ) + return 1; + else + return 0; +} + +*/ + +/***************************************************************************** + * Enternal BUCK status + ******************************************************************************/ + +int get_ext_buck_i2c_ch_num(void) +{ + if (is_mt6311_exist() == 1) + return get_mt6311_i2c_ch_num(); + else + return -1; +} + +int is_ext_buck_sw_ready(void) +{ + if ((is_mt6311_sw_ready() == 1)) + return 1; + else + return 0; +} + +int is_ext_buck_exist(void) +{ + if ((is_mt6311_exist() == 1)) + return 1; + else + return 0; +} + +/***************************************************************************** + * FTM + ******************************************************************************/ +#define PMIC_DEVNAME "pmic_ftm" +#define Get_IS_EXT_BUCK_EXIST _IOW('k', 20, int) +#define Get_IS_EXT_VBAT_BOOST_EXIST _IOW('k', 21, int) +#define Get_IS_EXT_SWCHR_EXIST _IOW('k', 22, int) +#define Get_IS_EXT_BUCK2_EXIST _IOW('k', 23, int) + + +static struct class *pmic_class; +static struct cdev *pmic_cdev; +static int pmic_major; +static dev_t pmic_devno; + +static long pmic_ftm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int *user_data_addr; + int ret = 0; + int adc_in_data[2] = { 1, 1 }; + int adc_out_data[2] = { 1, 1 }; + + switch (cmd) { + /*#if defined(FTM_EXT_BUCK_CHECK)*/ + case Get_IS_EXT_BUCK_EXIST: + user_data_addr = (int *)arg; + ret = copy_from_user(adc_in_data, user_data_addr, 8); + adc_out_data[0] = is_ext_buck_exist(); + ret = copy_to_user(user_data_addr, adc_out_data, 8); + PMICLOG("[pmic_ftm_ioctl] Get_IS_EXT_BUCK_EXIST:%d\n", adc_out_data[0]); + break; + /*#endif*/ + + /*#if defined(FTM_EXT_VBAT_BOOST_CHECK)*/ + case Get_IS_EXT_VBAT_BOOST_EXIST: + user_data_addr = (int *)arg; + ret = copy_from_user(adc_in_data, user_data_addr, 8); + adc_out_data[0] = is_ext_vbat_boost_exist(); + ret = copy_to_user(user_data_addr, adc_out_data, 8); + PMICLOG("[pmic_ftm_ioctl] Get_IS_EXT_VBAT_BOOST_EXIST:%d\n", adc_out_data[0]); + break; + /*#endif*/ + + /*#if defined(FEATURE_FTM_SWCHR_HW_DETECT)*/ + case Get_IS_EXT_SWCHR_EXIST: + user_data_addr = (int *)arg; + ret = copy_from_user(adc_in_data, user_data_addr, 8); + adc_out_data[0] = is_ext_swchr_exist(); + ret = copy_to_user(user_data_addr, adc_out_data, 8); + PMICLOG("[pmic_ftm_ioctl] Get_IS_EXT_SWCHR_EXIST:%d\n", adc_out_data[0]); + break; + /*#endif*/ + case Get_IS_EXT_BUCK2_EXIST: + user_data_addr = (int *)arg; + ret = copy_from_user(adc_in_data, user_data_addr, 8); + adc_out_data[0] = is_ext_buck2_exist(); + ret = copy_to_user(user_data_addr, adc_out_data, 8); + PMICLOG("[pmic_ftm_ioctl] Get_IS_EXT_BUCK2_EXIST:%d\n", adc_out_data[0]); + break; + default: + PMICLOG("[pmic_ftm_ioctl] Error ID\n"); + break; + } + + return 0; +} +#ifdef CONFIG_COMPAT +static long pmic_ftm_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + switch (cmd) { + /*#if defined(FTM_EXT_BUCK_CHECK) */ + case Get_IS_EXT_BUCK_EXIST: + case Get_IS_EXT_VBAT_BOOST_EXIST: + case Get_IS_EXT_SWCHR_EXIST: + case Get_IS_EXT_BUCK2_EXIST: + ret = file->f_op->unlocked_ioctl(file, cmd, arg); + break; + default: + PMICLOG("[pmic_ftm_compat_ioctl] Error ID\n"); + break; + } + + return 0; +} +#endif +static int pmic_ftm_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int pmic_ftm_release(struct inode *inode, struct file *file) +{ + return 0; +} + + +static const struct file_operations pmic_ftm_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = pmic_ftm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = pmic_ftm_compat_ioctl, +#endif + .open = pmic_ftm_open, + .release = pmic_ftm_release, +}; + +void pmic_ftm_init(void) +{ + struct class_device *class_dev = NULL; + int ret = 0; + + ret = alloc_chrdev_region(&pmic_devno, 0, 1, PMIC_DEVNAME); + if (ret) + PMICLOG("[pmic_ftm_init] Error: Can't Get Major number for pmic_ftm\n"); + + pmic_cdev = cdev_alloc(); + pmic_cdev->owner = THIS_MODULE; + pmic_cdev->ops = &pmic_ftm_fops; + + ret = cdev_add(pmic_cdev, pmic_devno, 1); + if (ret) + PMICLOG("[pmic_ftm_init] Error: cdev_add\n"); + + pmic_major = MAJOR(pmic_devno); + pmic_class = class_create(THIS_MODULE, PMIC_DEVNAME); + + class_dev = (struct class_device *)device_create(pmic_class, + NULL, pmic_devno, NULL, PMIC_DEVNAME); + + PMICLOG("[pmic_ftm_init] Done\n"); +} + + + + +/***************************************************************************** + * HW Setting + ******************************************************************************/ +unsigned short is_battery_remove = 0; +unsigned short is_wdt_reboot_pmic = 0; +unsigned short is_wdt_reboot_pmic_chk = 0; + +unsigned short is_battery_remove_pmic(void) +{ + return is_battery_remove; +} + +void PMIC_CUSTOM_SETTING_V1(void) +{ +#if 0 +#if defined CONFIG_MTK_LEGACY +#if defined(CONFIG_MTK_FPGA) +#else + pmu_drv_tool_customization_init(); /* legacy DCT only */ +#endif +#endif +#endif +} + + +/***************************************************************************** + * Dump all LDO status + ******************************************************************************/ +void dump_ldo_status_read_debug(void) +{ + int i, j; + int en = 0; + int voltage_reg = 0; + int voltage = 0; + const int *pVoltage; + + pr_debug("********** BUCK/LDO status dump [1:ON,0:OFF]**********\n"); + + for (i = 0; i < ARRAY_SIZE(mtk_bucks); i++) { + if (mtk_bucks[i].qi_en_reg != 0) + en = pmic_get_register_value(mtk_bucks[i].qi_en_reg); + else + en = -1; + + if (mtk_bucks[i].qi_vol_reg != 0) { + voltage_reg = pmic_get_register_value(mtk_bucks[i].qi_vol_reg); + voltage = + mtk_bucks[i].desc.min_uV + mtk_bucks[i].desc.uV_step * voltage_reg; + } else { + voltage_reg = -1; + voltage = -1; + } + pr_err("%s status:%d voltage:%duv voltage_reg:%d\n", + mtk_bucks[i].desc.name, en, voltage, voltage_reg); + } + + for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) { + if (mtk_ldos[i].en_reg != 0) + en = pmic_get_register_value(mtk_ldos[i].en_reg); + else + en = -1; + + if (mtk_ldos[i].desc.n_voltages != 1) { + if (mtk_ldos[i].vol_reg != 0) { + voltage_reg = pmic_get_register_value(mtk_ldos[i].vol_reg); + if (mtk_ldos[i].pvoltages != NULL) { + pVoltage = (const int *)mtk_ldos[i].pvoltages; + /*HW LDO sequence issue, we need to change it */ + if ((strcmp(mtk_ldos[i].desc.name, "va18") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vtcxo24") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vtcxo28") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vcn28") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vxo22") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vbif28") == 0)) { + pr_err("dump_ldo_status_read_debug(name=%s selector=%d)\n", + mtk_ldos[i].desc.name, voltage_reg); + if (voltage_reg == 0) + voltage_reg = 3; + else if (voltage_reg == 1) + voltage_reg = 2; + else if (voltage_reg == 2) + voltage_reg = 1; + else if (voltage_reg == 3) + voltage_reg = 0; + } + voltage = pVoltage[voltage_reg]; + } else { + voltage = + mtk_ldos[i].desc.min_uV + + mtk_ldos[i].desc.uV_step * voltage_reg; + } + } else { + voltage_reg = -1; + voltage = -1; + } + } else { + pVoltage = (const int *)mtk_ldos[i].pvoltages; + voltage = pVoltage[0]; + } + + pr_err("%s status:%d voltage:%duv voltage_reg:%d\n", + mtk_ldos[i].desc.name, en, voltage, voltage_reg); + } + + for (i = 0; i < interrupts_size; i++) { + for (j = 0; j < PMIC_INT_WIDTH; j++) { + + PMICLOG("[PMIC_INT][%s] interrupt issue times: %d\n", + interrupts[i].interrupts[j].name, + interrupts[i].interrupts[j].times); + } + } + + PMICLOG("Power Good Status=0x%x.\n", upmu_get_reg_value(0x21c)); + PMICLOG("OC Status=0x%x.\n", upmu_get_reg_value(0x214)); + PMICLOG("Thermal Status=0x%x.\n", upmu_get_reg_value(0x21e)); +} + +static int proc_utilization_show(struct seq_file *m, void *v) +{ + int i, j; + int en = 0; + int voltage_reg = 0; + int voltage = 0; + const int *pVoltage; + + seq_puts(m, "********** BUCK/LDO status dump [1:ON,0:OFF]**********\n"); + + for (i = 0; i < ARRAY_SIZE(mtk_bucks); i++) { + if (mtk_bucks[i].qi_en_reg != 0) + en = pmic_get_register_value(mtk_bucks[i].qi_en_reg); + else + en = -1; + + if (mtk_bucks[i].qi_vol_reg != 0) { + voltage_reg = pmic_get_register_value(mtk_bucks[i].qi_vol_reg); + voltage = + mtk_bucks[i].desc.min_uV + mtk_bucks[i].desc.uV_step * voltage_reg; + } else { + voltage_reg = -1; + voltage = -1; + } + seq_printf(m, "%s status:%d voltage:%duv voltage_reg:%d\n", + mtk_bucks[i].desc.name, en, voltage, voltage_reg); + } + + for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) { + if (mtk_ldos[i].en_reg != 0) + en = pmic_get_register_value(mtk_ldos[i].en_reg); + else + en = -1; + + if (mtk_ldos[i].desc.n_voltages != 1) { + if (mtk_ldos[i].vol_reg != 0) { + voltage_reg = pmic_get_register_value(mtk_ldos[i].vol_reg); + if (mtk_ldos[i].pvoltages != NULL) { + pVoltage = (const int *)mtk_ldos[i].pvoltages; + /*HW LDO sequence issue, we need to change it */ + if ((strcmp(mtk_ldos[i].desc.name, "va18") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vtcxo24") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vtcxo28") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vcn28") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vxo22") == 0) | + (strcmp(mtk_ldos[i].desc.name, "vbif28") == 0)) { + pr_err("dump_ldo_status_read_debug(name=%s selector=%d)\n", + mtk_ldos[i].desc.name, voltage_reg); + if (voltage_reg == 0) + voltage_reg = 3; + else if (voltage_reg == 1) + voltage_reg = 2; + else if (voltage_reg == 2) + voltage_reg = 1; + else if (voltage_reg == 3) + voltage_reg = 0; + } + voltage = pVoltage[voltage_reg]; + } else { + voltage = + mtk_ldos[i].desc.min_uV + + mtk_ldos[i].desc.uV_step * voltage_reg; + } + } else { + voltage_reg = -1; + voltage = -1; + } + } else { + pVoltage = (const int *)mtk_ldos[i].pvoltages; + voltage = pVoltage[0]; + } + seq_printf(m, "%s status:%d voltage:%duv voltage_reg:%d\n", + mtk_ldos[i].desc.name, en, voltage, voltage_reg); + } + + for (i = 0; i < interrupts_size; i++) { + for (j = 0; j < PMIC_INT_WIDTH; j++) { + + seq_printf(m, "[PMIC_INT][%s] interrupt issue times: %d\n", + interrupts[i].interrupts[j].name, + interrupts[i].interrupts[j].times); + } + } + seq_printf(m, "Power Good Status=0x%x.\n", upmu_get_reg_value(0x21c)); + seq_printf(m, "OC Status=0x%x.\n", upmu_get_reg_value(0x214)); + seq_printf(m, "Thermal Status=0x%x.\n", upmu_get_reg_value(0x21e)); + + return 0; +} + +static int proc_utilization_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_utilization_show, NULL); +} + +static const struct file_operations pmic_debug_proc_fops = { + .open = proc_utilization_open, + .read = seq_read, +}; + +static int proc_dump_register_show(struct seq_file *m, void *v) +{ + int i; + + seq_puts(m, "********** dump PMIC registers**********\n"); + + for (i = 0; i <= 0x0fae; i = i + 10) { + seq_printf(m, "Reg[%x]=0x%x Reg[%x]=0x%x Reg[%x]=0x%x Reg[%x]=0x%x Reg[%x]=0x%x\n", + i, upmu_get_reg_value(i), i + 1, upmu_get_reg_value(i + 1), i + 2, + upmu_get_reg_value(i + 2), i + 3, upmu_get_reg_value(i + 3), i + 4, + upmu_get_reg_value(i + 4)); + + seq_printf(m, "Reg[%x]=0x%x Reg[%x]=0x%x Reg[%x]=0x%x Reg[%x]=0x%x Reg[%x]=0x%x\n", + i + 5, upmu_get_reg_value(i + 5), i + 6, upmu_get_reg_value(i + 6), + i + 7, upmu_get_reg_value(i + 7), i + 8, upmu_get_reg_value(i + 8), + i + 9, upmu_get_reg_value(i + 9)); + } + + return 0; +} + +static int proc_dump_register_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_dump_register_show, NULL); +} + +static const struct file_operations pmic_dump_register_proc_fops = { + .open = proc_dump_register_open, + .read = seq_read, +}; + +void pmic_debug_init(void) +{ + struct proc_dir_entry *mt_pmic_dir; + + mt_pmic_dir = proc_mkdir("mt_pmic", NULL); + if (!mt_pmic_dir) { + PMICLOG("fail to mkdir /proc/mt_pmic\n"); + return; + } + + proc_create("dump_ldo_status", S_IRUGO | S_IWUSR, mt_pmic_dir, &pmic_debug_proc_fops); + PMICLOG("proc_create pmic_debug_proc_fops\n"); + + proc_create("dump_pmic_reg", S_IRUGO | S_IWUSR, mt_pmic_dir, &pmic_dump_register_proc_fops); + PMICLOG("proc_create pmic_dump_register_proc_fops\n"); + + + +} + +static bool pwrkey_detect_flag; +static struct hrtimer pwrkey_detect_timer; +static struct task_struct *pwrkey_detect_thread; +static DECLARE_WAIT_QUEUE_HEAD(pwrkey_detect_waiter); + +#define BAT_MS_TO_NS(x) (x * 1000 * 1000) + +enum hrtimer_restart pwrkey_detect_sw_workaround(struct hrtimer *timer) +{ + pwrkey_detect_flag = true; + + wake_up_interruptible(&pwrkey_detect_waiter); + return HRTIMER_NORESTART; +} + +int pwrkey_detect_sw_thread_handler(void *unused) +{ + ktime_t ktime; + + do { + ktime = ktime_set(3, BAT_MS_TO_NS(1000)); + + + + wait_event_interruptible(pwrkey_detect_waiter, (pwrkey_detect_flag == true)); + + /*PMICLOG("=>charger_hv_detect_sw_workaround\n"); */ + if (pmic_get_register_value(PMIC_RG_STRUP_75K_CK_PDN) == 1) { + PMICLOG("charger_hv_detect_sw_workaround =0x%x\n", + upmu_get_reg_value(0x24e)); + pmic_set_register_value(PMIC_RG_STRUP_75K_CK_PDN, 0); + } + + + hrtimer_start(&pwrkey_detect_timer, ktime, HRTIMER_MODE_REL); + + } while (!kthread_should_stop()); + + return 0; + +} + + + +void pwrkey_sw_workaround_init(void) +{ + ktime_t ktime; + + ktime = ktime_set(0, BAT_MS_TO_NS(2000)); + hrtimer_init(&pwrkey_detect_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + pwrkey_detect_timer.function = pwrkey_detect_sw_workaround; + hrtimer_start(&pwrkey_detect_timer, ktime, HRTIMER_MODE_REL); + + pwrkey_detect_thread = + kthread_run(pwrkey_detect_sw_thread_handler, 0, "mtk pwrkey_sw_workaround_init"); + + if (IS_ERR(pwrkey_detect_thread)) + PMICLOG("[%s]: failed to create pwrkey_detect_thread thread\n", __func__); + +} + +#ifdef LOW_BATTERY_PROTECT +/***************************************************************************** + * low battery protect UT + ******************************************************************************/ +static ssize_t show_low_battery_protect_ut(struct device *dev, struct device_attribute *attr, + char *buf) +{ + PMICLOG("[show_low_battery_protect_ut] g_low_battery_level=%d\n", g_low_battery_level); + return sprintf(buf, "%u\n", g_low_battery_level); +} + +static ssize_t store_low_battery_protect_ut(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + char *pvalue = NULL; + unsigned int val = 0; + + pr_err("[store_low_battery_protect_ut]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_low_battery_protect_ut] buf is %s and size is %zu\n", buf, size); + /*val = simple_strtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + if (val <= 2) { + pr_err("[store_low_battery_protect_ut] your input is %d\n", val); + exec_low_battery_callback(val); + } else { + pr_err("[store_low_battery_protect_ut] wrong number (%d)\n", val); + } + } + return size; +} + +static DEVICE_ATTR(low_battery_protect_ut, 0664, show_low_battery_protect_ut, store_low_battery_protect_ut); /*664*/ + +/***************************************************************************** + * low battery protect stop + ******************************************************************************/ +static ssize_t show_low_battery_protect_stop(struct device *dev, struct device_attribute *attr, + char *buf) +{ + PMICLOG("[show_low_battery_protect_stop] g_low_battery_stop=%d\n", g_low_battery_stop); + return sprintf(buf, "%u\n", g_low_battery_stop); +} + +static ssize_t store_low_battery_protect_stop(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + char *pvalue = NULL; + unsigned int val = 0; + + pr_err("[store_low_battery_protect_stop]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_low_battery_protect_stop] buf is %s and size is %zu\n", buf, size); + /*val = simple_strtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + if ((val != 0) && (val != 1)) + val = 0; + g_low_battery_stop = val; + pr_err("[store_low_battery_protect_stop] g_low_battery_stop=%d\n", + g_low_battery_stop); + } + return size; +} + +static DEVICE_ATTR(low_battery_protect_stop, 0664, + show_low_battery_protect_stop, store_low_battery_protect_stop); /*664*/ + +/* + * low battery protect level + */ +static ssize_t show_low_battery_protect_level(struct device *dev, struct device_attribute *attr, + char *buf) +{ + PMICLOG("[show_low_battery_protect_level] g_low_battery_level=%d\n", g_low_battery_level); + return sprintf(buf, "%u\n", g_low_battery_level); +} + +static ssize_t store_low_battery_protect_level(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + PMICLOG("[store_low_battery_protect_level] g_low_battery_level=%d\n", g_low_battery_level); + + return size; +} + +static DEVICE_ATTR(low_battery_protect_level, 0664, + show_low_battery_protect_level, store_low_battery_protect_level); /*664*/ +#endif + +#ifdef BATTERY_OC_PROTECT +/***************************************************************************** + * battery OC protect UT + ******************************************************************************/ +static ssize_t show_battery_oc_protect_ut(struct device *dev, struct device_attribute *attr, + char *buf) +{ + PMICLOG("[show_battery_oc_protect_ut] g_battery_oc_level=%d\n", g_battery_oc_level); + return sprintf(buf, "%u\n", g_battery_oc_level); +} + +static ssize_t store_battery_oc_protect_ut(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + char *pvalue = NULL; + unsigned int val = 0; + + pr_err("[store_battery_oc_protect_ut]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_battery_oc_protect_ut] buf is %s and size is %zu\n", buf, size); + /*val = simple_strtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + if (val <= 1) { + pr_err("[store_battery_oc_protect_ut] your input is %d\n", val); + exec_battery_oc_callback(val); + } else { + pr_err("[store_battery_oc_protect_ut] wrong number (%d)\n", val); + } + } + return size; +} + +static DEVICE_ATTR(battery_oc_protect_ut, 0664, + show_battery_oc_protect_ut, store_battery_oc_protect_ut); /*664*/ + +/***************************************************************************** + * battery OC protect stop + ******************************************************************************/ +static ssize_t show_battery_oc_protect_stop(struct device *dev, struct device_attribute *attr, + char *buf) +{ + PMICLOG("[show_battery_oc_protect_stop] g_battery_oc_stop=%d\n", g_battery_oc_stop); + return sprintf(buf, "%u\n", g_battery_oc_stop); +} + +static ssize_t store_battery_oc_protect_stop(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + char *pvalue = NULL; + unsigned int val = 0; + + pr_err("[store_battery_oc_protect_stop]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_battery_oc_protect_stop] buf is %s and size is %zu\n", buf, size); + /*val = simple_strtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + if ((val != 0) && (val != 1)) + val = 0; + g_battery_oc_stop = val; + pr_err("[store_battery_oc_protect_stop] g_battery_oc_stop=%d\n", + g_battery_oc_stop); + } + return size; +} + +static DEVICE_ATTR(battery_oc_protect_stop, 0664, + show_battery_oc_protect_stop, store_battery_oc_protect_stop); /*664*/ + +/***************************************************************************** + * battery OC protect level + ******************************************************************************/ +static ssize_t show_battery_oc_protect_level(struct device *dev, struct device_attribute *attr, + char *buf) +{ + PMICLOG("[show_battery_oc_protect_level] g_battery_oc_level=%d\n", g_battery_oc_level); + return sprintf(buf, "%u\n", g_battery_oc_level); +} + +static ssize_t store_battery_oc_protect_level(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + PMICLOG("[store_battery_oc_protect_level] g_battery_oc_level=%d\n", g_battery_oc_level); + + return size; +} + +static DEVICE_ATTR(battery_oc_protect_level, 0664, + show_battery_oc_protect_level, store_battery_oc_protect_level); /*664*/ +#endif + +#ifdef BATTERY_PERCENT_PROTECT +/***************************************************************************** + * battery percent protect UT + ******************************************************************************/ +static ssize_t show_battery_percent_ut(struct device *dev, struct device_attribute *attr, + char *buf) +{ + /*show_battery_percent_protect_ut*/ + PMICLOG("[show_battery_percent_protect_ut] g_battery_percent_level=%d\n", + g_battery_percent_level); + return sprintf(buf, "%u\n", g_battery_percent_level); +} + +static ssize_t store_battery_percent_ut(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + char *pvalue = NULL; + unsigned int val = 0; + /*store_battery_percent_protect_ut*/ + pr_err("[store_battery_percent_protect_ut]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_battery_percent_protect_ut] buf is %s and size is %zu\n", buf, + size); + /*val = simple_strtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + if (val <= 1) { + pr_err("[store_battery_percent_protect_ut] your input is %d\n", val); + exec_battery_percent_callback(val); + } else { + pr_err("[store_battery_percent_protect_ut] wrong number (%d)\n", val); + } + } + return size; +} + +static DEVICE_ATTR(battery_percent_protect_ut, 0664, + show_battery_percent_ut, store_battery_percent_ut); /*664*/ + +/* + * battery percent protect stop + ******************************************************************************/ +static ssize_t show_battery_percent_stop(struct device *dev, struct device_attribute *attr, + char *buf) +{ + /*show_battery_percent_protect_stop*/ + PMICLOG("[show_battery_percent_protect_stop] g_battery_percent_stop=%d\n", + g_battery_percent_stop); + return sprintf(buf, "%u\n", g_battery_percent_stop); +} + +static ssize_t store_battery_percent_stop(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + char *pvalue = NULL; + unsigned int val = 0; + /*store_battery_percent_protect_stop*/ + pr_err("[store_battery_percent_protect_stop]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_battery_percent_protect_stop] buf is %s and size is %zu\n", buf, + size); + /*val = simple_strtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + if ((val != 0) && (val != 1)) + val = 0; + g_battery_percent_stop = val; + pr_err("[store_battery_percent_protect_stop] g_battery_percent_stop=%d\n", + g_battery_percent_stop); + } + return size; +} + +static DEVICE_ATTR(battery_percent_protect_stop, 0664, + show_battery_percent_stop, store_battery_percent_stop); /*664*/ + +/* + * battery percent protect level + ******************************************************************************/ +static ssize_t show_battery_percent_level(struct device *dev, struct device_attribute *attr, + char *buf) +{ + /*show_battery_percent_protect_level*/ + PMICLOG("[show_battery_percent_protect_level] g_battery_percent_level=%d\n", + g_battery_percent_level); + return sprintf(buf, "%u\n", g_battery_percent_level); +} + +static ssize_t store_battery_percent_level(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + /*store_battery_percent_protect_level*/ + PMICLOG("[store_battery_percent_protect_level] g_battery_percent_level=%d\n", + g_battery_percent_level); + + return size; +} + +static DEVICE_ATTR(battery_percent_protect_level, 0664, + show_battery_percent_level, store_battery_percent_level); /*664*/ +#endif + +#ifdef DLPT_FEATURE_SUPPORT +/***************************************************************************** + * DLPT UT + ******************************************************************************/ +static ssize_t show_dlpt_ut(struct device *dev, struct device_attribute *attr, char *buf) +{ + PMICLOG("[show_dlpt_ut] g_dlpt_val=%d\n", g_dlpt_val); + return sprintf(buf, "%u\n", g_dlpt_val); +} + +static ssize_t store_dlpt_ut(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + char *pvalue = NULL; + unsigned int val = 0; + int ret = 0; + + pr_err("[store_dlpt_ut]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_dlpt_ut] buf is %s and size is %zu\n", buf, size); + /*val = simple_strtoul(buf, &pvalue, 10);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 10, (unsigned int *)&val); + + pr_err("[store_dlpt_ut] your input is %d\n", val); + exec_dlpt_callback(val); + } + return size; +} + +static DEVICE_ATTR(dlpt_ut, 0664, show_dlpt_ut, store_dlpt_ut); /*664*/ + +/***************************************************************************** + * DLPT stop + ******************************************************************************/ +static ssize_t show_dlpt_stop(struct device *dev, struct device_attribute *attr, char *buf) +{ + PMICLOG("[show_dlpt_stop] g_dlpt_stop=%d\n", g_dlpt_stop); + return sprintf(buf, "%u\n", g_dlpt_stop); +} + +static ssize_t store_dlpt_stop(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + char *pvalue = NULL; + unsigned int val = 0; + int ret = 0; + + pr_err("[store_dlpt_stop]\n"); + + if (buf != NULL && size != 0) { + pr_err("[store_dlpt_stop] buf is %s and size is %zu\n", buf, size); + /*val = simple_strtoul(buf, &pvalue, 16);*/ + pvalue = (char *)buf; + ret = kstrtou32(pvalue, 16, (unsigned int *)&val); + if ((val != 0) && (val != 1)) + val = 0; + g_dlpt_stop = val; + pr_err("[store_dlpt_stop] g_dlpt_stop=%d\n", g_dlpt_stop); + } + return size; +} + +static DEVICE_ATTR(dlpt_stop, 0664, show_dlpt_stop, store_dlpt_stop); /*664 */ + +/***************************************************************************** + * DLPT level + ******************************************************************************/ +static ssize_t show_dlpt_level(struct device *dev, struct device_attribute *attr, char *buf) +{ + PMICLOG("[show_dlpt_level] g_dlpt_val=%d\n", g_dlpt_val); + return sprintf(buf, "%u\n", g_dlpt_val); +} + +static ssize_t store_dlpt_level(struct device *dev, struct device_attribute *attr, const char *buf, + size_t size) +{ + PMICLOG("[store_dlpt_level] g_dlpt_val=%d\n", g_dlpt_val); + + return size; +} + +static DEVICE_ATTR(dlpt_level, 0664, show_dlpt_level, store_dlpt_level); /*664*/ +#endif + +/***************************************************************************** + * system function + ******************************************************************************/ +#ifdef DLPT_FEATURE_SUPPORT +static unsigned long pmic_node; + +static int fb_early_init_dt_get_chosen(unsigned long node, const char *uname, int depth, void *data) +{ + if (depth != 1 || (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; + pmic_node = node; + return 1; +} +#endif /*end of #ifdef DLPT_FEATURE_SUPPORT*/ +static int pmic_mt_probe(struct platform_device *dev) +{ + int ret_device_file = 0, i; +#ifdef DLPT_FEATURE_SUPPORT + const int *pimix = NULL; + int len = 0; +#endif +#if defined(CONFIG_MTK_SMART_BATTERY) + struct device_node *np; + u32 val; + char *path = "/bus/BAT_METTER"; + + np = of_find_node_by_path(path); + if (of_property_read_u32(np, "car_tune_value", &val) == 0) { + batt_meter_cust_data.car_tune_value = (int)val; + PMICLOG("Get car_tune_value from DT: %d\n", + batt_meter_cust_data.car_tune_value); + } else { + batt_meter_cust_data.car_tune_value = CAR_TUNE_VALUE; + PMICLOG("Get car_tune_value from cust header\n"); + } +#endif + /*--- initailize pmic_suspend_state ---*/ + pmic_suspend_state = false; +#ifdef DLPT_FEATURE_SUPPORT + if (of_scan_flat_dt(fb_early_init_dt_get_chosen, NULL) > 0) + pimix = of_get_flat_dt_prop(pmic_node, "atag,imix_r", &len); + if (pimix == NULL) { + pr_err(" pimix==NULL len=%d\n", len); + } else { + pr_err(" pimix=%d\n", *pimix); + ptim_rac_val_avg = *pimix; + } + + PMICLOG("******** MT pmic driver probe!! ********%d\n", ptim_rac_val_avg); + pr_debug("[PMIC]pmic_mt_probe %s %s\n", dev->name, dev->id_entry->name); +#endif /* #ifdef DLPT_FEATURE_SUPPORT */ + /*get PMIC CID */ + pr_debug + ("PMIC CID=0x%x PowerGoodStatus = 0x%x OCStatus = 0x%x ThermalStatus = 0x%x rsvStatus = 0x%x\n", + pmic_get_register_value(PMIC_SWCID), upmu_get_reg_value(0x21c), + upmu_get_reg_value(0x214), upmu_get_reg_value(0x21e), upmu_get_reg_value(0x2a6)); + + /* upmu_set_reg_value(0x2a6, 0xff); */ /* TBD */ + + /*pmic initial setting */ +#if 0 + PMIC_INIT_SETTING_V1(); + PMICLOG("[PMIC_INIT_SETTING_V1] Done\n"); +#else + PMICLOG("[PMIC_INIT_SETTING_V1] delay to MT6311 init\n"); +#endif +#if !defined CONFIG_MTK_LEGACY +/* replace by DTS*/ +#else + PMIC_CUSTOM_SETTING_V1(); + PMICLOG("[PMIC_CUSTOM_SETTING_V1] Done\n"); +#endif /*End of #if !defined CONFIG_MTK_LEGACY */ + + +/*#if defined(CONFIG_MTK_FPGA)*/ +#if 0 + PMICLOG("[PMIC_EINT_SETTING] disable when CONFIG_MTK_FPGA\n"); +#else + /*PMIC Interrupt Service*/ + pmic_thread_handle = kthread_create(pmic_thread_kthread, (void *)NULL, "pmic_thread"); + if (IS_ERR(pmic_thread_handle)) { + pmic_thread_handle = NULL; + PMICLOG("[pmic_thread_kthread_mt6325] creation fails\n"); + } else { + PMICLOG("[pmic_thread_kthread_mt6325] kthread_create Done\n"); + } + + PMIC_EINT_SETTING(); + PMICLOG("[PMIC_EINT_SETTING] Done\n"); +#endif + + + mtk_regulator_init(dev); + +#ifdef LOW_BATTERY_PROTECT + low_battery_protect_init(); +#else + pr_err("[PMIC] no define LOW_BATTERY_PROTECT\n"); +#endif + +#ifdef BATTERY_OC_PROTECT + battery_oc_protect_init(); +#else + pr_err("[PMIC] no define BATTERY_OC_PROTECT\n"); +#endif + +#ifdef BATTERY_PERCENT_PROTECT + bat_percent_notify_init(); +#else + pr_err("[PMIC] no define BATTERY_PERCENT_PROTECT\n"); +#endif + +#ifdef DLPT_FEATURE_SUPPORT + dlpt_notify_init(); +#else + pr_err("[PMIC] no define DLPT_FEATURE_SUPPORT\n"); +#endif + +#if 0 /* jade do not use 26MHz for auxadc */ + pmic_set_register_value(PMIC_AUXADC_CK_AON, 1); + pmic_set_register_value(PMIC_RG_CLKSQ_EN_AUX_AP_MODE, 0); + PMICLOG("[PMIC] auxadc 26M test : Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_AUXADC_CON0, upmu_get_reg_value(MT6351_AUXADC_CON0), + MT6351_TOP_CLKSQ, upmu_get_reg_value(MT6351_TOP_CLKSQ) + ); +#endif + + pmic_debug_init(); + PMICLOG("[PMIC] pmic_debug_init : done.\n"); + + pmic_ftm_init(); + + + + /*EM BUCK voltage & Status*/ + for (i = 0; i < ARRAY_SIZE(mtk_bucks); i++) { + /*PMICLOG("[PMIC] register buck id=%d\n",i);*/ + ret_device_file = device_create_file(&(dev->dev), &mtk_bucks[i].en_att); + ret_device_file = device_create_file(&(dev->dev), &mtk_bucks[i].voltage_att); + mtk_bucks[i].vsleep_en_saved = 0x0fffffff; + } + + /*EM ldo voltage & Status*/ + for (i = 0; i < ARRAY_SIZE(mtk_ldos); i++) { + /*PMICLOG("[PMIC] register ldo id=%d\n",i);*/ + ret_device_file = device_create_file(&(dev->dev), &mtk_ldos[i].en_att); + ret_device_file = device_create_file(&(dev->dev), &mtk_ldos[i].voltage_att); + } + + ret_device_file = device_create_file(&(dev->dev), &dev_attr_pmic_access); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_pmic_dvt); + +#ifdef LOW_BATTERY_PROTECT + ret_device_file = device_create_file(&(dev->dev), &dev_attr_low_battery_protect_ut); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_low_battery_protect_stop); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_low_battery_protect_level); +#endif + +#ifdef BATTERY_OC_PROTECT + ret_device_file = device_create_file(&(dev->dev), &dev_attr_battery_oc_protect_ut); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_battery_oc_protect_stop); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_battery_oc_protect_level); +#endif + +#ifdef BATTERY_PERCENT_PROTECT + ret_device_file = device_create_file(&(dev->dev), &dev_attr_battery_percent_protect_ut); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_battery_percent_protect_stop); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_battery_percent_protect_level); +#endif + +#ifdef DLPT_FEATURE_SUPPORT + ret_device_file = device_create_file(&(dev->dev), &dev_attr_dlpt_ut); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_dlpt_stop); + ret_device_file = device_create_file(&(dev->dev), &dev_attr_dlpt_level); +#endif + + ret_device_file = device_create_file(&(dev->dev), &dev_attr_pmic_auxadc_ut); + + PMICLOG("[PMIC] device_create_file for EM : done.\n"); + +#if PMIC_UT /* UT TBD */ +#ifdef LOW_BATTERY_PROTECT + register_low_battery_notify(&low_bat_test, LOW_BATTERY_PRIO_CPU_B); + PMICLOG("register_low_battery_notify:done\n"); +#endif +#ifdef BATTERY_OC_PROTECT + register_battery_oc_notify(&bat_oc_test, BATTERY_OC_PRIO_CPU_B); + PMICLOG("register_battery_oc_notify:done\n"); +#endif +#ifdef BATTERY_PERCENT_PROTECT + register_battery_percent_notify(&bat_per_test, BATTERY_PERCENT_PRIO_CPU_B); + PMICLOG("register_battery_percent_notify:done\n"); +#endif +#endif + /*pwrkey_sw_workaround_init(); */ + return 0; +} + +static int pmic_mt_remove(struct platform_device *dev) +{ + PMICLOG("******** MT pmic driver remove!! ********\n"); + + return 0; +} + +static void pmic_mt_shutdown(struct platform_device *dev) +{ + PMICLOG("******** MT pmic driver shutdown!! ********\n"); + vmd1_pmic_setting_on(); +} + +static int pmic_mt_suspend(struct platform_device *dev, pm_message_t state) +{ + pmic_suspend_state = true; + + PMICLOG("******** MT pmic driver suspend!! ********\n"); + +#ifdef LOW_BATTERY_PROTECT + lbat_min_en_setting(0); + lbat_max_en_setting(0); + + PMICLOG("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_AUXADC_LBAT3, upmu_get_reg_value(MT6351_AUXADC_LBAT3), + MT6351_AUXADC_LBAT4, upmu_get_reg_value(MT6351_AUXADC_LBAT4), + MT6351_INT_CON0, upmu_get_reg_value(MT6351_INT_CON0) + ); +#endif + +#ifdef BATTERY_OC_PROTECT + bat_oc_h_en_setting(0); + bat_oc_l_en_setting(0); + + PMICLOG("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_PMIC_FG_CUR_HTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_HTH_ADDR), + MT6351_PMIC_FG_CUR_LTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_LTH_ADDR), + MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR, upmu_get_reg_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR) + ); +#endif + + return 0; +} + +static int pmic_mt_resume(struct platform_device *dev) +{ + pmic_suspend_state = false; + + PMICLOG("******** MT pmic driver resume!! ********\n"); + +#ifdef LOW_BATTERY_PROTECT + lbat_min_en_setting(0); + lbat_max_en_setting(0); + mdelay(1); + + if (g_low_battery_level == 1) { + lbat_min_en_setting(1); + lbat_max_en_setting(1); + } else if (g_low_battery_level == 2) { + /*lbat_min_en_setting(0);*/ + lbat_max_en_setting(1); + } else { /*0*/ + lbat_min_en_setting(1); + /*lbat_max_en_setting(0);*/ + } + + PMICLOG("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_AUXADC_LBAT3, upmu_get_reg_value(MT6351_AUXADC_LBAT3), + MT6351_AUXADC_LBAT4, upmu_get_reg_value(MT6351_AUXADC_LBAT4), + MT6351_INT_CON0, upmu_get_reg_value(MT6351_INT_CON0) + ); +#endif + +#ifdef BATTERY_OC_PROTECT + bat_oc_h_en_setting(0); + bat_oc_l_en_setting(0); + mdelay(1); + + if (g_battery_oc_level == 1) + bat_oc_h_en_setting(1); + else + bat_oc_l_en_setting(1); + + PMICLOG("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_PMIC_FG_CUR_HTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_HTH_ADDR), + MT6351_PMIC_FG_CUR_LTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_LTH_ADDR), + MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR, upmu_get_reg_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR) + ); +#endif + + return 0; +} + +struct platform_device pmic_mt_device = { + .name = "mt-pmic", + .id = -1, +}; + +static struct platform_driver pmic_mt_driver = { + .probe = pmic_mt_probe, + .remove = pmic_mt_remove, + .shutdown = pmic_mt_shutdown, + /*#ifdef CONFIG_PM*/ + .suspend = pmic_mt_suspend, + .resume = pmic_mt_resume, + /*#endif*/ + .driver = { + .name = "mt-pmic", + }, +}; + +static DEFINE_MUTEX(pmic_efuse_lock_mutex); +unsigned int pmic_Read_Efuse_HPOffset(int i) +{ + unsigned int ret = 0; + unsigned int reg_val = 0; + unsigned int efusevalue; + + pr_debug("pmic_Read_Efuse_HPOffset(+)\n"); + mutex_lock(&pmic_efuse_lock_mutex); + /*1. enable efuse ctrl engine clock */ + pmic_config_interface(MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_ADDR, 0x00, + MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_SHIFT); + pmic_config_interface(MT6351_PMIC_RG_EFUSE_CK_PDN_ADDR, 0x00, + MT6351_PMIC_RG_EFUSE_CK_PDN_MASK, MT6351_PMIC_RG_EFUSE_CK_PDN_SHIFT); + /*2. */ + pmic_config_interface(MT6351_PMIC_RG_OTP_RD_SW_ADDR, 0x01, + MT6351_PMIC_RG_OTP_RD_SW_MASK, MT6351_PMIC_RG_OTP_RD_SW_SHIFT); + + /*3. set row to read */ + pmic_config_interface(MT6351_PMIC_RG_OTP_PA_ADDR, i*2, + MT6351_PMIC_RG_OTP_PA_MASK, MT6351_PMIC_RG_OTP_PA_SHIFT); + /*4. Toggle */ + udelay(100); + ret = pmic_read_interface(MT6351_PMIC_RG_OTP_RD_TRIG_ADDR, ®_val, + MT6351_PMIC_RG_OTP_RD_TRIG_MASK, MT6351_PMIC_RG_OTP_RD_TRIG_SHIFT); + + if (reg_val == 0) { + pmic_config_interface(MT6351_PMIC_RG_OTP_RD_TRIG_ADDR, 1, + MT6351_PMIC_RG_OTP_RD_TRIG_MASK, MT6351_PMIC_RG_OTP_RD_TRIG_SHIFT); + } else{ + pmic_config_interface(MT6351_PMIC_RG_OTP_RD_TRIG_ADDR, 0, + MT6351_PMIC_RG_OTP_RD_TRIG_MASK, MT6351_PMIC_RG_OTP_RD_TRIG_SHIFT); + } + + /*5. polling Reg[0x61A] */ + udelay(300); + do { + ret = pmic_read_interface(MT6351_PMIC_RG_OTP_RD_BUSY_ADDR, ®_val, + MT6351_PMIC_RG_OTP_RD_BUSY_MASK, MT6351_PMIC_RG_OTP_RD_BUSY_SHIFT); + } while (reg_val == 1); + udelay(1000); /*Need to delay at least 1ms for 0x61A and than can read 0xC18 */ + /*6. read data */ + ret = pmic_read_interface(MT6351_PMIC_RG_OTP_DOUT_SW_ADDR, &efusevalue, + MT6351_PMIC_RG_OTP_DOUT_SW_MASK, MT6351_PMIC_RG_OTP_DOUT_SW_SHIFT); + + pr_debug("HPoffset : efuse=0x%x\n", efusevalue); + /*7. Disable efuse ctrl engine clock */ + pmic_config_interface(MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_ADDR, 0x01, + MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_SHIFT); + pmic_config_interface(MT6351_PMIC_RG_EFUSE_CK_PDN_ADDR, 0x01, + MT6351_PMIC_RG_EFUSE_CK_PDN_MASK, MT6351_PMIC_RG_EFUSE_CK_PDN_SHIFT); + + mutex_unlock(&pmic_efuse_lock_mutex); + return efusevalue; +} + +/***************************************************************************** + * PMIC mudule init/exit + ******************************************************************************/ +static int __init pmic_mt_init(void) +{ + int ret; + +#if !defined CONFIG_HAS_WAKELOCKS + wakeup_source_init(&pmicThread_lock, "pmicThread_lock_mt6328 wakelock"); + wakeup_source_init(&bat_percent_notify_lock, "bat_percent_notify_lock wakelock"); +#else + wake_lock_init(&pmicThread_lock, WAKE_LOCK_SUSPEND, "pmicThread_lock_mt6328 wakelock"); + wake_lock_init(&bat_percent_notify_lock, WAKE_LOCK_SUSPEND, + "bat_percent_notify_lock wakelock"); +#endif + +#if !defined CONFIG_HAS_WAKELOCKS + wakeup_source_init(&dlpt_notify_lock, "dlpt_notify_lock wakelock"); +#else + wake_lock_init(&dlpt_notify_lock, WAKE_LOCK_SUSPEND, "dlpt_notify_lock wakelock"); +#endif + +#if !defined CONFIG_MTK_LEGACY +#ifdef CONFIG_OF + PMICLOG("pmic_regulator_init_OF\n"); + + /* PMIC device driver register*/ + ret = platform_device_register(&pmic_mt_device); + if (ret) { + PMICLOG("****[pmic_mt_init] Unable to device register(%d)\n", ret); + return ret; + } + ret = platform_driver_register(&pmic_mt_driver); + if (ret) { + PMICLOG("****[pmic_mt_init] Unable to register driver (%d)\n", ret); + return ret; + } + ret = platform_driver_register(&mt_pmic_driver); + if (ret) { + PMICLOG("****[pmic_mt_init] Unable to register driver by DT(%d)\n", ret); + return ret; + } +#endif /* End of #ifdef CONFIG_OF */ +#else + PMICLOG("pmic_regulator_init\n"); + /* PMIC device driver register*/ + ret = platform_device_register(&pmic_mt_device); + if (ret) { + PMICLOG("****[pmic_mt_init] Unable to device register(%d)\n", ret); + return ret; + } + ret = platform_driver_register(&pmic_mt_driver); + if (ret) { + PMICLOG("****[pmic_mt_init] Unable to register driver (%d)\n", ret); + return ret; + } +#endif /* End of #if !defined CONFIG_MTK_LEGACY */ + + + pmic_auxadc_init(); + + pr_debug("****[pmic_mt_init] Initialization : DONE !!\n"); + + return 0; +} + +static void __exit pmic_mt_exit(void) +{ +#if !defined CONFIG_MTK_LEGACY +#ifdef CONFIG_OF + platform_driver_unregister(&mt_pmic_driver); +#endif +#endif /* End of #if !defined CONFIG_MTK_LEGACY */ +} +fs_initcall(pmic_mt_init); + +/*module_init(pmic_mt_init);*/ +module_exit(pmic_mt_exit); + +MODULE_AUTHOR("Argus Lin"); +MODULE_DESCRIPTION("MT PMIC Device Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/power/mt6755/pmic.h b/drivers/misc/mediatek/power/mt6755/pmic.h new file mode 100644 index 0000000000000000000000000000000000000000..85a5a433a2f9fa475c3e594fb5620f037b5e9272 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/pmic.h @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _PMIC_SW_H_ +#define _PMIC_SW_H_ + + +#define PMIC_DEBUG + +#include +#include +/* + * The CHIP INFO + */ +#define PMIC6351_E1_CID_CODE 0x5110 +#define PMIC6351_E2_CID_CODE 0x5120 +#define PMIC6351_E3_CID_CODE 0x5130 + + +#define pmic_emerg(fmt, args...) pr_emerg("[SPM-PMIC] " fmt, ##args) +#define pmic_alert(fmt, args...) pr_alert("[SPM-PMIC] " fmt, ##args) +#define pmic_crit(fmt, args...) pr_crit("[SPM-PMIC] " fmt, ##args) +#define pmic_err(fmt, args...) pr_err("[SPM-PMIC] " fmt, ##args) +#define pmic_warn(fmt, args...) pr_warn("[SPM-PMIC] " fmt, ##args) +#define pmic_notice(fmt, args...) pr_notice("[SPM-PMIC] " fmt, ##args) +#define pmic_info(fmt, args...) pr_info("[SPM-PMIC] " fmt, ##args) +#define pmic_debug(fmt, args...) pr_debug("[SPM-PMIC] " fmt, ##args) /* pr_debug show nothing */ + +/* just use in suspend flow for important log due to console suspend */ +#if defined PMIC_DEBUG_PR_DBG +#define pmic_spm_crit2(fmt, args...) \ +do { \ + aee_sram_printk(fmt, ##args); \ + pmic_crit(fmt, ##args); \ +} while (0) +#else +#define pmic_spm_crit2(fmt, args...) \ +do { \ + aee_sram_printk(fmt, ##args); \ +} while (0) +#endif + +/*#define PMIC_DEBUG_PR_DBG*/ + +#define PMICTAG "[PMIC] " +#ifdef PMIC_DEBUG +#define PMICDEB(fmt, arg...) pr_debug(PMICTAG "cpuid=%d, " fmt, raw_smp_processor_id(), ##arg) +#define PMICFUC(fmt, arg...) pr_debug(PMICTAG "cpuid=%d, %s\n", raw_smp_processor_id(), __func__) +#endif /*-- defined PMIC_DEBUG --*/ +#if defined PMIC_DEBUG_PR_DBG +#define PMICLOG(fmt, arg...) pr_err(PMICTAG fmt, ##arg) +#else +#define PMICLOG(fmt, arg...) +#endif /*-- defined PMIC_DEBUG_PR_DBG --*/ +#define PMICERR(fmt, arg...) pr_debug(PMICTAG "ERROR,line=%d " fmt, __LINE__, ##arg) +#define PMICREG(fmt, arg...) pr_debug(PMICTAG fmt, ##arg) + +#define PMIC_EN REGULATOR_CHANGE_STATUS +#define PMIC_VOL REGULATOR_CHANGE_VOLTAGE +#define PMIC_EN_VOL 9 + +#define PMIC_INT_WIDTH 16 + +#define GETSIZE(array) (sizeof(array)/sizeof(array[0])) + +/* PMIC EXTERN VARIABLE */ +/*----- LOW_BATTERY_PROTECT -----*/ +extern int g_lowbat_int_bottom; +extern int g_low_battery_level; +/*----- BATTERY_OC_PROTECT -----*/ +extern int g_battery_oc_level; + +/* PMIC EXTERN FUNCTIONS */ +/*----- LOW_BATTERY_PROTECT -----*/ +extern void lbat_min_en_setting(int en_val); +extern void lbat_max_en_setting(int en_val); +extern void exec_low_battery_callback(LOW_BATTERY_LEVEL low_battery_level); +/*----- BATTERY_OC_PROTECT -----*/ +extern void exec_battery_oc_callback(BATTERY_OC_LEVEL battery_oc_level); +extern void bat_oc_h_en_setting(int en_val); +extern void bat_oc_l_en_setting(int en_val); +/*----- CHRDET_PROTECT -----*/ +#ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING +extern unsigned int upmu_get_rgs_chrdet(void); +#endif +/*----- PMIC thread -----*/ +extern void pmic_enable_charger_detection_int(int x); +/*----- LDO OC -----*/ +extern void msdc_sd_power_off(void); + +/* extern functions */ +extern void mt_power_off(void); +extern const PMU_FLAG_TABLE_ENTRY pmu_flags_table[]; +extern unsigned int bat_get_ui_percentage(void); +extern signed int fgauge_read_IM_current(void *data); +extern void pmic_auxadc_lock(void); +extern void pmic_auxadc_unlock(void); +extern unsigned int bat_get_ui_percentage(void); +extern signed int fgauge_read_v_by_d(int d_val); +extern signed int fgauge_read_r_bat_by_v(signed int voltage); +/*extern PMU_ChargerStruct BMT_status;*//*have defined in battery_common.h */ +extern void kpd_pwrkey_pmic_handler(unsigned long pressed); +extern void kpd_pmic_rstkey_handler(unsigned long pressed); +extern int is_mt6311_sw_ready(void); +extern int is_mt6311_exist(void); +extern int get_mt6311_i2c_ch_num(void); +extern bool crystal_exist_status(void); +#if !defined CONFIG_MTK_LEGACY +extern void pmu_drv_tool_customization_init(void); +#endif +extern int batt_init_cust_data(void); + +extern unsigned int mt_gpio_to_irq(unsigned int gpio); +extern int mt_gpio_set_debounce(unsigned gpio, unsigned debounce); +/*---------------------------------------------------*/ + +/* controllable voltage , not fixed step */ +#define PMIC_LDO_GEN1(_name, en, vol, array, use, mode) \ + { \ + .desc = { \ + .name = #_name, \ + .n_voltages = (sizeof(array)/sizeof(array[0])), \ + .ops = &mtk_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + }, \ + .init_data = { \ + .constraints = { \ + .valid_ops_mask = (mode), \ + }, \ + }, \ + .en_att = __ATTR(LDO_##_name##_STATUS, 0664, show_LDO_STATUS, store_LDO_STATUS), \ + .voltage_att = __ATTR(LDO_##_name##_VOLTAGE, 0664, show_LDO_VOLTAGE, store_LDO_VOLTAGE), \ + .pvoltages = (void *)(array), \ + .en_reg = (PMU_FLAGS_LIST_ENUM)(en), \ + .vol_reg = (PMU_FLAGS_LIST_ENUM)(vol), \ + .isUsedable = (use), \ + } +/* controllable voltage , fixed step */ +#define PMIC_LDO_GEN2(_name, en, vol, min, max, step, use, mode) \ + { \ + .desc = { \ + .name = #_name, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .ops = &mtk_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = (min), \ + .uV_step = (step), \ + }, \ + .init_data = { \ + .constraints = { \ + .valid_ops_mask = (mode), \ + }, \ + }, \ + .en_att = __ATTR(LDO_##_name##_STATUS, 0664, show_LDO_STATUS, store_LDO_STATUS), \ + .voltage_att = __ATTR(LDO_##_name##_VOLTAGE, 0664, show_LDO_VOLTAGE, store_LDO_VOLTAGE), \ + .en_reg = (en), \ + .vol_reg = (vol), \ + .isUsedable = (use), \ + } + +#define PMIC_BUCK_GEN(_name, en, vol, min, max, step) \ + { \ + .desc = { \ + .name = #_name, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .min_uV = (min), \ + .uV_step = (step), \ + }, \ + .en_att = __ATTR(BUCK_##_name##_STATUS, 0664, show_BUCK_STATUS, store_BUCK_STATUS), \ + .voltage_att = __ATTR(BUCK_##_name##_VOLTAGE, 0664, show_BUCK_VOLTAGE, store_BUCK_VOLTAGE), \ + .qi_en_reg = (en), \ + .qi_vol_reg = (vol), \ + .isUsedable = 0, \ + } + +/* fixed voltage */ +#define PMIC_LDO_GEN3(_name, en, fixvoltage, use, mode) \ + { \ + .desc = { \ + .name = #_name, \ + .n_voltages = 1, \ + .ops = &mtk_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + }, \ + .init_data = { \ + .constraints = { \ + .valid_ops_mask = (mode), \ + }, \ + }, \ + .en_att = __ATTR(LDO_##_name##_STATUS, 0664, show_LDO_STATUS, store_LDO_STATUS), \ + .voltage_att = __ATTR(LDO_##_name##_VOLTAGE, 0664, show_LDO_VOLTAGE, store_LDO_VOLTAGE), \ + .en_reg = (en), \ + .fixedVoltage_uv = (fixvoltage), \ + .isUsedable = (use), \ + } + +struct mtk_regulator_vosel { + unsigned int def_sel; /*-- default vosel --*/ + unsigned int cur_sel; /*-- current vosel --*/ + bool restore; +}; + +struct mtk_regulator { + struct regulator_desc desc; + struct regulator_init_data init_data; + struct regulator_config config; + struct device_attribute en_att; + struct device_attribute voltage_att; + struct regulator_dev *rdev; + PMU_FLAGS_LIST_ENUM en_reg; + PMU_FLAGS_LIST_ENUM vol_reg; + PMU_FLAGS_LIST_ENUM qi_en_reg; + PMU_FLAGS_LIST_ENUM qi_vol_reg; + const void *pvoltages; + bool isUsedable; + struct regulator *reg; + /*--- Add to record selector ---*/ + struct mtk_regulator_vosel vosel; + int vsleep_en_saved; +}; + + + +#define PMIC_INTERRUPT_WIDTH 16 + +#define PMIC_S_INT_GEN(_name) \ + { \ + .name = #_name, \ + } + +#define PMIC_M_INTS_GEN(adr, enA, setA, clearA, interrupt) \ + { \ + .address = adr, \ + .en = enA, \ + .set = setA, \ + .clear = clearA, \ + .interrupts = interrupt, \ + } + +struct pmic_interrupt_bit { + const char *name; + void (*callback)(void); + unsigned int times; +}; + +struct pmic_interrupts { + unsigned int address; + unsigned int en; + unsigned int set; + unsigned int clear; + struct pmic_interrupt_bit *interrupts; +}; + + +/* controllable voltage , not fixed step */ +/* +#define PMIC_LDO_GEN1(_name, en, vol, array, use) \ + { \ + .desc = { \ + .name = #_name, \ + .n_voltages = (sizeof(array)/sizeof(array[0])), \ + .ops = &mtk_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ + .en_att = __ATTR(LDO_##_name##_STATUS, 0664, show_LDO_STATUS, store_LDO_STATUS), \ + .voltage_att = __ATTR(LDO_##_name##_VOLTAGE, 0664, show_LDO_VOLTAGE, store_LDO_VOLTAGE), \ + .pvoltages = array, \ + .en_reg = (en), \ + .vol_reg = (vol), \ + .isUsedable = (use), \ + } +*/ +/* fixed voltage */ +/* +#define PMIC_LDO_GEN2(_name, en, fixvoltage, use) \ + { \ + .desc = { \ + .name = #_name, \ + .n_voltages = 1, \ + .ops = &mtk_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ + .en_att = __ATTR(LDO_##_name##_STATUS, 0664, show_LDO_STATUS, store_LDO_STATUS), \ + .voltage_att = __ATTR(LDO_##_name##_VOLTAGE, 0664, show_LDO_VOLTAGE, store_LDO_VOLTAGE), \ + .en_reg = (en), \ + .fixedVoltage_uv = (fixvoltage), \ + .isUsedable = (use), \ + } +*/ +/* controllable voltage , fixed step */ +/* +#define PMIC_LDO_GEN3(_name, en, vol, min, max, step, use) \ + { \ + .desc = { \ + .name = #_name, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .ops = &mtk_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = (min), \ + .uV_step = (step), \ + }, \ + .en_att = __ATTR(LDO_##_name##_STATUS, 0664, show_LDO_STATUS, store_LDO_STATUS), \ + .voltage_att = __ATTR(LDO_##_name##_VOLTAGE, 0664, show_LDO_VOLTAGE, store_LDO_VOLTAGE), \ + .en_reg = (en), \ + .vol_reg = (vol), \ + .isUsedable = (use), \ + } + +#define PMIC_BUCK_GEN(_name, en, vol, min, max, step) \ + { \ + .desc = { \ + .name = #_name, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .min_uV = (min), \ + .uV_step = (step), \ + }, \ + .en_att = __ATTR(BUCK_##_name##_STATUS, 0664, show_BUCK_STATUS, store_BUCK_STATUS), \ + .voltage_att = __ATTR(BUCK_##_name##_VOLTAGE, 0664, show_BUCK_VOLTAGE, store_BUCK_VOLTAGE), \ + .en_reg = (en), \ + .vol_reg = (vol), \ + .isUsedable = 0, \ + } + +*/ + +#endif /* _PMIC_SW_H_ */ diff --git a/drivers/misc/mediatek/power/mt6755/pmic_auxadc.c b/drivers/misc/mediatek/power/mt6755/pmic_auxadc.c new file mode 100644 index 0000000000000000000000000000000000000000..a26f19e1e0c819b59a9c19d1e383cb6998d850e0 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/pmic_auxadc.c @@ -0,0 +1,731 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +/*#include TBD*/ +#include +#if defined CONFIG_MTK_LEGACY +#include +#endif +/*#include TBD*/ +#include + +#if defined(CONFIG_MTK_SMART_BATTERY) +#include +#include +#endif +#include +/*#include */ + +#include +#include + + +/* + * PMIC-AUXADC related define + */ +#define VOLTAGE_FULL_RANGE 1800 +#define VOLTAGE_FULL_RANGE_6311 3200 +#define ADC_PRECISE 32768 /* 15 bits*/ +#define ADC_PRECISE_CH7 131072 /* 17 bits*/ +#define ADC_PRECISE_6311 4096 /* 12 bits*/ + +/* + * PMIC-AUXADC global variable + */ + +#define PMICTAG "[Auxadc] " +#if defined PMIC_DEBUG_PR_DBG +#define PMICLOG2(fmt, arg...) pr_err(PMICTAG fmt, ##arg) +#else +#define PMICLOG2(fmt, arg...) +#endif + +signed int count_time_out = 15; +struct wake_lock pmicAuxadc_irq_lock; +/*static DEFINE_SPINLOCK(pmic_adc_lock);*/ +static DEFINE_MUTEX(pmic_adc_mutex); +static DEFINE_MUTEX(auxadc_ch3_mutex); + +void pmic_auxadc_init(void) +{ + /*signed int adc_busy;*/ + wake_lock_init(&pmicAuxadc_irq_lock, WAKE_LOCK_SUSPEND, "pmicAuxadc irq wakelock"); + + pmic_set_register_value(PMIC_AUXADC_AVG_NUM_LARGE, 6); /* 1.3ms */ + pmic_set_register_value(PMIC_AUXADC_AVG_NUM_SMALL, 2); /* 0.8ms */ + + pmic_set_register_value(PMIC_AUXADC_AVG_NUM_SEL, 0x83); /* 0.8ms */ + + pmic_set_register_value(PMIC_AUXADC_VBUF_EN, 0x1); + + PMICLOG2("****[pmic_auxadc_init] DONE\n"); +} + +void lockadcch3(void) +{ + mutex_lock(&auxadc_ch3_mutex); +} + +void unlockadcch3(void) +{ + mutex_unlock(&auxadc_ch3_mutex); +} + +void pmic_auxadc_lock(void) +{ + wake_lock(&pmicAuxadc_irq_lock); + mutex_lock(&pmic_adc_mutex); +} + +void pmic_auxadc_unlock(void) +{ + mutex_unlock(&pmic_adc_mutex); + wake_unlock(&pmicAuxadc_irq_lock); +} + +void pmic_auxadc_debug(int index) +{ + int ret_val = 0, val, val1, val2, val3, val4; + int val5, val6, val7; + ret_val = pmic_read_interface((unsigned int)(0x0240), (&val), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x0282), (&val1), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x025e), (&val2), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x023a), (&val3), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x0ea2), (&val4), (0xffff), 0); + pr_err("[pmic_auxadc_debug]%d 0x0240:0x%x, 0x0282:0x%x, 0x025e:0x%x , 0x023a:0x%x , 0x0ea2:0x%x\n", + index, val, val1, val2, val3, val4); + ret_val = pmic_read_interface(MT6351_TOP_CKPDN_CON2, &val, + MT6351_PMIC_TOP_CKPDN_CON2_CLR_MASK, MT6351_PMIC_TOP_CKPDN_CON2_CLR_SHIFT); + ret_val = pmic_read_interface(MT6351_PMIC_RG_BATON_HT_EN_ADDR, &val1, 0xFFFF, 0x0); + ret_val = pmic_read_interface(MT6351_LDO_VBIF28_CON0, &val2, 0xFFFF, 0x0); + ret_val = pmic_read_interface(MT6351_TOP_CKHWEN_CON0, &val3, 0xFFFF, 0x0); + ret_val = pmic_read_interface(MT6351_TOP_RST_MISC, &val4, 0xFFFF, 0x0); + pr_err("[pmic_auxadc_debug] _TOP_CKPDN_CON2:0x%x BIF_BAT_CON0:0x%x LDO_VBIF28:0x%x 0x282:0x%x 0x2b6:0x%x\n", + val, val1, val2, val3, val4); + /* bATON debug register */ + ret_val = pmic_read_interface((unsigned int)(0x0f86), (&val), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x024a), (&val1), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x0b74), (&val2), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x0a86), (&val3), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x0eb2), (&val4), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x025e), (&val5), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x0e98), (&val6), (0xffff), 0); + ret_val = pmic_read_interface((unsigned int)(0x0eaa), (&val7), (0xffff), 0); + pr_err("[pmic_auxadc_debug]%d 0x0f86:0x%x, 0x024a:0x%x, 0x0b74:0x%x , 0x0a86:0x%x , 0x0eb2:0x%x\n", + index, val, val1, val2, val3, val4); + pr_err("[pmic_auxadc_debug] 0x025e:0x%x, 0x0e98:0x%x, 0x0eaa:0x%x\n", + val5, val6, val7); +} + +signed int PMIC_IMM_GetCurrent(void) +{ + signed int ret = 0; + int count = 0; + signed int batsns, isense; + signed int ADC_I_SENSE = 1; /* 1 measure time*/ + signed int ADC_BAT_SENSE = 1; /* 1 measure time*/ + signed int ICharging = 0; + /*pmic_auxadc_debug(1);*/ + pmic_set_register_value(PMIC_AUXADC_CK_AON, 1); + pmic_set_register_value(PMIC_RG_AUXADC_SMPS_CK_PDN, 0); +/* maybe used for debug + pmic_set_register_value(PMIC_RG_AUXADC_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN, 0); +*/ + wake_lock(&pmicAuxadc_irq_lock); + mutex_lock(&pmic_adc_mutex); + ret = pmic_config_interface(MT6351_AUXADC_RQST0_SET, 0x3, 0xffff, 0); + + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH0_BY_AP) != 1) { + /*msleep(1);*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[PMIC_IMM_GetCurrent] batsns Time out!\n"); + break; + } + } + batsns = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH0_BY_AP); + if (batsns == 0) { + pr_err("[AUXADC]impedence-B(%x, %x)\n", + pmic_get_register_value(PMIC_RG_VBIF28_ON_CTRL), + pmic_get_register_value(PMIC_RG_VBIF28_EN)); + pmic_auxadc_debug(0x20); + } + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH1_BY_AP) != 1) { + /*msleep(1);*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[PMIC_IMM_GetCurrent] isense Time out!\n"); + break; + } + } + isense = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH1_BY_AP); + if (isense == 0) { + pr_err("[AUXADC]impedence-I(%x, %x)\n", + pmic_get_register_value(PMIC_RG_VBIF28_ON_CTRL), + pmic_get_register_value(PMIC_RG_VBIF28_EN)); + pmic_auxadc_debug(0x21); + } + + ADC_BAT_SENSE = (batsns * 3 * VOLTAGE_FULL_RANGE) / 32768; + ADC_I_SENSE = (isense * 3 * VOLTAGE_FULL_RANGE) / 32768; + +#if defined(CONFIG_MTK_SMART_BATTERY) + ICharging = + (ADC_I_SENSE - ADC_BAT_SENSE + + g_I_SENSE_offset) * 1000 / batt_meter_cust_data.cust_r_sense; +#endif + + mutex_unlock(&pmic_adc_mutex); + wake_unlock(&pmicAuxadc_irq_lock); + /* + pmic_set_register_value(PMIC_RG_AUXADC_SMPS_CK_PDN, 0x1); + */ + + return ICharging; + +} + + + +/* + * PMIC-AUXADC + */ +unsigned int PMIC_IMM_GetOneChannelValue(pmic_adc_ch_list_enum dwChannel, int deCount, int trimd) +{ + signed int ret = 0; + signed int ret_data; + signed int r_val_temp = 0; + signed int adc_result = 0; + int count = 0; + unsigned int busy; + /* + PMIC_AUX_BATSNS_AP = 0x000, + PMIC_AUX_ISENSE_AP, + PMIC_AUX_VCDT_AP, + PMIC_AUX_BATON_AP, + PMIC_AUX_CH4, + PMIC_AUX_VACCDET_AP, + PMIC_AUX_CH6, + PMIC_AUX_TSX, + PMIC_AUX_CH8, + PMIC_AUX_CH9, + PMIC_AUX_CH10, + PMIC_AUX_CH11, + PMIC_AUX_CH12, + PMIC_AUX_CH13, + PMIC_AUX_CH14, + PMIC_AUX_CH15, + BATSNS 3v-4.5v + ISENSE 1.5-4.5v + BATON 0-1.8v + VCDT 4v-14v + ACCDET 1.8v + GPS 1.8v + + */ + /*pmic_auxadc_debug(2);*/ + pmic_set_register_value(PMIC_AUXADC_CK_AON, 1); + pmic_set_register_value(PMIC_RG_AUXADC_SMPS_CK_PDN, 0); +/* maybe used for debug + pmic_set_register_value(PMIC_RG_AUXADC_CK_PDN, 0); + pmic_set_register_value(PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN, 0); +*/ + if (dwChannel == PMIC_AUX_CH4_DCXO) { + PMICLOG2("[AUXADC] ch:PMIC_AUX_CH4_DCXO\n"); + ret = pmic_set_register_value(PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL, 0x1); + dwChannel = 4; + } else if (dwChannel == PMIC_AUX_CH4) { + ret = pmic_set_register_value(PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL, 0); + } +#if defined PMIC_DVT_TC_EN + /* only used for PMIC_DVT */ + pmic_set_register_value(PMIC_STRUP_AUXADC_START_SEL, 1); + pmic_set_register_value(PMIC_STRUP_AUXADC_RSTB_SW, 1); + pmic_set_register_value(PMIC_STRUP_AUXADC_RSTB_SEL, 1); + /* END only used for PMIC_DVT */ +#endif + wake_lock(&pmicAuxadc_irq_lock); + mutex_lock(&pmic_adc_mutex); + + + if (dwChannel == 3) + mutex_lock(&auxadc_ch3_mutex); + /*ret=pmic_config_interface(MT6351_TOP_CLKSQ_SET,(1<<2),0xffff,0); */ + ret = pmic_config_interface(MT6351_AUXADC_RQST0_SET, (1 << dwChannel), 0xffff, 0); + + + busy = upmu_get_reg_value(MT6351_AUXADC_STA0); + udelay(50); + + switch (dwChannel) { + case 0: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH0_BY_AP) != 1) { + /*msleep(1);*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH0_BY_AP); + break; + case 1: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH1_BY_AP) != 1) { + /*msleep(1);*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH1_BY_AP); + break; + case 2: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH2) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH2); + break; + case 3: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH3) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH3); + if (ret_data < 0x100) { + pr_err("[AUXADC]VBIF28_ON_CTL, EN(%x, %x)\n", + pmic_get_register_value(PMIC_RG_VBIF28_ON_CTRL), + pmic_get_register_value(PMIC_RG_VBIF28_EN)); + pmic_auxadc_debug(0x22); + } + mutex_unlock(&auxadc_ch3_mutex); + break; + case 4: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH4) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH4); + break; + case 5: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH5) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH5); + break; + case 6: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH6) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH6); + break; + case 7: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH7_BY_AP) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH7_BY_AP); + break; + case 8: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH8) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH8); + break; + case 9: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH9) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH9); + break; + case 10: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH10) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH10); + break; + case 11: + /* MT6351 ch3 bug, wei-lin request us to add below code */ + if (g_pmic_pad_vbif28_vol == 0x1) { + ret = pmic_set_register_value(PMIC_BATON_TDET_EN, 0); + ret = pmic_set_register_value(PMIC_TOP_CKPDN_CON2_CLR, 0x70); + /* mt6351 sw workaround, PAD_VBIF28 SWITCH TURN ON */ + pmic_set_register_value(PMIC_RG_ADCIN_VSEN_MUX_EN, 1); + mdelay(3); /* delay 1~3ms */ + } + + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH11) != 1) { + usleep_range(1000, 1200); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH11); + break; + case 12: + case 13: + case 14: + case 15: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH12_15) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH12_15); + break; + + + default: + PMICLOG2("[AUXADC] Invalid channel value(%d,%d)\n", dwChannel, trimd); + mutex_unlock(&pmic_adc_mutex); + wake_unlock(&pmicAuxadc_irq_lock); + return -1; + break; + } + + switch (dwChannel) { + case 0: + r_val_temp = 3; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 32768; + break; + case 1: + r_val_temp = 3; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 32768; + break; + case 2: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 3: + r_val_temp = 2; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + if (adc_result < 0x200) { + pr_err("[AUXADC] ch3 high bat temp(%x, %x, %x)\n", adc_result, + ret_data, pmic_get_register_value(PMIC_BATON_TDET_EN)); + pmic_auxadc_debug(0x23); + } + break; + case 4: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 5: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 6: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 7: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 32768; + break; + case 8: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 9: +#if 0 + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; +#endif + /* jade requester allen lin/tai-chun, ch9 return raw data for audio */ + r_val_temp = 1; + adc_result = (ret_data * r_val_temp); + break; + case 10: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 11: + r_val_temp = 2; + g_pmic_pad_vbif28_vol = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + if ((g_pmic_pad_vbif28_vol < 2700) || (g_pmic_pad_vbif28_vol >= 2912)) { + pr_err("[AUXADC] VBIF28_def_volt(%x, %x, %x)\n", g_pmic_pad_vbif28_vol, + ret_data, pmic_get_register_value(PMIC_BATON_TDET_EN)); + g_pmic_pad_vbif28_vol = 2770; + } + /* mt6351 sw workaround, PAD_VBIF28 SWITCH TURN ON */ + pmic_set_register_value(PMIC_RG_ADCIN_VSEN_MUX_EN, 0); + ret = pmic_set_register_value(PMIC_RG_VBIF28_ON_CTRL, 1); + ret = pmic_set_register_value(PMIC_RG_VBIF28_MODE_CTRL, 1); + ret = pmic_set_register_value(PMIC_RG_VBIF28_EN, 0); + ret = pmic_set_register_value(PMIC_TOP_CKPDN_CON2_SET, 0x70); + mdelay(3); /* delay 1~3ms */ + ret = pmic_set_register_value(PMIC_BATON_TDET_EN, 0x1); + break; + case 12: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 13: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 14: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 15: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 16: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + default: + PMICLOG2("[AUXADC] Invalid channel value(%d,%d)\n", dwChannel, trimd); + mutex_unlock(&pmic_adc_mutex); + wake_unlock(&pmicAuxadc_irq_lock); + return -1; + break; + } + PMICLOG2("[AUXADC] ch:%d(%x, %x, %x, %x)\n", dwChannel, adc_result, + ret_data, g_pmic_pad_vbif28_vol, pmic_get_register_value(PMIC_BATON_TDET_EN)); + mutex_unlock(&pmic_adc_mutex); + wake_unlock(&pmicAuxadc_irq_lock); + /* + pmic_set_register_value(PMIC_RG_AUXADC_SMPS_CK_PDN, 0x1); + */ + /*PMICLOG2("[AUXADC] ch=%d raw=%d data=%d\n", dwChannel, ret_data,adc_result);*/ + + /*return ret_data;*/ + return adc_result; + +} + +unsigned int PMIC_IMM_GetOneChannelValueMD(unsigned char dwChannel, int deCount, int trimd) +{ + signed int ret = 0; + signed int ret_data; + signed int r_val_temp = 0; + signed int adc_result = 0; + int count = 0; + /* + CH0: BATSNS + CH1: ISENSE + CH4: PMIC TEMP + CH7: TSX by MD + CH8: TSX by GPS + + */ + + if (dwChannel != 0 && dwChannel != 1 && dwChannel != 4 && dwChannel != 7 && dwChannel != 8) + return -1; + + + wake_lock(&pmicAuxadc_irq_lock); + mutex_lock(&pmic_adc_mutex); + ret = pmic_config_interface(MT6351_TOP_CLKSQ_SET, (1 << 3), 0xffff, 0); + ret = pmic_config_interface(MT6351_AUXADC_RQST1_SET, (1 << dwChannel), 0xffff, 0); + mutex_unlock(&pmic_adc_mutex); + wake_unlock(&pmicAuxadc_irq_lock); + udelay(10); + + switch (dwChannel) { + case 0: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH0_BY_MD) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[PMIC_IMM_GetOneChannelValueMD] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH0_BY_MD); + break; + case 1: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH1_BY_MD) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[PMIC_IMM_GetOneChannelValueMD] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH1_BY_MD); + break; + case 4: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH4_BY_MD) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[PMIC_IMM_GetOneChannelValueMD] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH4_BY_MD); + break; + case 7: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH7_BY_MD) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[PMIC_IMM_GetOneChannelValueMD] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH7_BY_MD); + break; + case 8: + while (pmic_get_register_value(PMIC_AUXADC_ADC_RDY_CH7_BY_GPS) != 1) { + /*msleep(1)*/ + usleep_range(1300, 1500); + if ((count++) > count_time_out) { + PMICLOG2("[PMIC_IMM_GetOneChannelValueMD] (%d) Time out!\n", + dwChannel); + break; + } + } + ret_data = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_CH7_BY_GPS); + break; + + + default: + PMICLOG2("[AUXADC] Invalid channel value(%d,%d)\n", dwChannel, trimd); + wake_unlock(&pmicAuxadc_irq_lock); + return -1; + break; + } + + switch (dwChannel) { + case 0: + r_val_temp = 3; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 32768; + break; + case 1: + r_val_temp = 3; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 32768; + break; + case 4: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 4096; + break; + case 7: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 32768; + break; + case 8: + r_val_temp = 1; + adc_result = (ret_data * r_val_temp * VOLTAGE_FULL_RANGE) / 32768; + break; + default: + PMICLOG2("[AUXADC] Invalid channel value(%d,%d)\n", dwChannel, trimd); + wake_unlock(&pmicAuxadc_irq_lock); + return -1; + break; + } + + wake_unlock(&pmicAuxadc_irq_lock); + + PMICLOG2("[AUXADC] PMIC_IMM_GetOneChannelValueMD ch=%d raw=%d data=%d\n", dwChannel, + ret_data, adc_result); + + return ret_data; + /*return adc_result;*/ + +} diff --git a/drivers/misc/mediatek/power/mt6755/pmic_chr_type_det.c b/drivers/misc/mediatek/power/mt6755/pmic_chr_type_det.c new file mode 100644 index 0000000000000000000000000000000000000000..c290f5ffd716cb56e8df19e7f181c2630c6a74a3 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/pmic_chr_type_det.c @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#if defined CONFIG_MTK_LEGACY +/*#include TBD*/ +#endif +/*#include TBD*/ +#include +#if defined(CONFIG_MTK_SMART_BATTERY) +#include +#endif +#include +#include + +#ifdef CONFIG_MTK_USB2JTAG_SUPPORT +#include +#endif + + +/* ============================================================ // */ +/* extern function */ +/* ============================================================ // */ +bool is_dcp_type = false; +#if defined(CONFIG_POWER_EXT) || defined(CONFIG_MTK_FPGA) + +int hw_charging_get_charger_type(void) +{ + return STANDARD_HOST; +} + +#else + +/*static void hw_bc11_dump_register(void) +{ + + battery_log(BAT_LOG_FULL, "Reg[0x%x]=0x%x,Reg[0x%x]=0x%x\n", + MT6325_CHR_CON20, upmu_get_reg_value(MT6325_CHR_CON20), + MT6325_CHR_CON21, upmu_get_reg_value(MT6325_CHR_CON21) + ); + +} +*/ +static void hw_bc11_init(void) +{ + int timeout_count = 20; + + msleep(200); + /* add make sure USB Ready */ + if (is_usb_rdy() == KAL_FALSE) { + battery_log(BAT_LOG_CRTI, "CDP, block\n"); + while (is_usb_rdy() == KAL_FALSE) { + msleep(100); + timeout_count--; + if (!timeout_count) { + battery_log(BAT_LOG_CRTI, "CDP, TIMEOUT!!!\n"); + break; + } + } + battery_log(BAT_LOG_CRTI, "CDP, free\n"); + } else + battery_log(BAT_LOG_CRTI, "CDP, PASS\n"); + +#ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING + /* add delay to make sure android init.rc finish */ + if (get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT + || get_boot_mode() == LOW_POWER_OFF_CHARGING_BOOT) { + msleep(1000); + } +#endif + +#if defined(CONFIG_MTK_SMART_BATTERY) + Charger_Detect_Init(); +#endif + /* RG_bc11_BIAS_EN=1 */ + bc11_set_register_value(PMIC_RG_BC11_BIAS_EN, 1); + /* RG_bc11_VSRC_EN[1:0]=00 */ + bc11_set_register_value(PMIC_RG_BC11_VSRC_EN, 0); + /* RG_bc11_VREF_VTH = [1:0]=00 */ + bc11_set_register_value(PMIC_RG_BC11_VREF_VTH, 0); + /* RG_bc11_CMP_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0); + /* RG_bc11_IPU_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPU_EN, 0); + /* RG_bc11_IPD_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPD_EN, 0); + /* bc11_RST=1 */ + bc11_set_register_value(PMIC_RG_BC11_RST, 1); + /* bc11_BB_CTRL=1 */ + bc11_set_register_value(PMIC_RG_BC11_BB_CTRL, 1); + + msleep(50); + /* mdelay(50); */ +/* + if (Enable_BATDRV_LOG == BAT_LOG_FULL) { + battery_log(BAT_LOG_FULL, "hw_bc11_init() \r\n"); + hw_bc11_dump_register(); + }*/ + +} + + +static unsigned int hw_bc11_DCD(void) +{ + unsigned int wChargerAvail = 0; + + /* RG_bc11_IPU_EN[1.0] = 10 */ + bc11_set_register_value(PMIC_RG_BC11_IPU_EN, 0x2); + /* RG_bc11_IPD_EN[1.0] = 01 */ + bc11_set_register_value(PMIC_RG_BC11_IPD_EN, 0x1); + /* RG_bc11_VREF_VTH = [1:0]=01 */ + bc11_set_register_value(PMIC_RG_BC11_VREF_VTH, 0x1); + /* RG_bc11_CMP_EN[1.0] = 10 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x2); + + msleep(80); + /* mdelay(80); */ + + wChargerAvail = bc11_get_register_value(PMIC_RGS_BC11_CMP_OUT); + +/* if (Enable_BATDRV_LOG == BAT_LOG_FULL) { + battery_log(BAT_LOG_FULL, "hw_bc11_DCD() \r\n"); + hw_bc11_dump_register(); + }*/ + /* RG_bc11_IPU_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPU_EN, 0x0); + /* RG_bc11_IPD_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPD_EN, 0x0); + /* RG_bc11_CMP_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x0); + /* RG_bc11_VREF_VTH = [1:0]=00 */ + bc11_set_register_value(PMIC_RG_BC11_VREF_VTH, 0x0); + + + return wChargerAvail; +} + + +static unsigned int hw_bc11_stepA1(void) +{ + unsigned int wChargerAvail = 0; + + /* RG_bc11_IPD_EN[1.0] = 01 */ + bc11_set_register_value(PMIC_RG_BC11_IPD_EN, 0x1); + /* RG_bc11_VREF_VTH = [1:0]=00 */ + bc11_set_register_value(PMIC_RG_BC11_VREF_VTH, 0x0); + /* RG_bc11_CMP_EN[1.0] = 01 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x1); + + msleep(80); + /* mdelay(80); */ + + wChargerAvail = bc11_get_register_value(PMIC_RGS_BC11_CMP_OUT); + +/* if (Enable_BATDRV_LOG == BAT_LOG_FULL) { + battery_log(BAT_LOG_FULL, "hw_bc11_stepA1() \r\n"); + hw_bc11_dump_register(); + }*/ + /* RG_bc11_IPD_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPD_EN, 0x0); + /* RG_bc11_CMP_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x0); + + return wChargerAvail; +} + + +static unsigned int hw_bc11_stepA2(void) +{ + unsigned int wChargerAvail = 0; + + /* RG_bc11_VSRC_EN[1.0] = 10 */ + bc11_set_register_value(PMIC_RG_BC11_VSRC_EN, 0x2); + /* RG_bc11_IPD_EN[1:0] = 01 */ + bc11_set_register_value(PMIC_RG_BC11_IPD_EN, 0x1); + /* RG_bc11_VREF_VTH = [1:0]=00 */ + bc11_set_register_value(PMIC_RG_BC11_VREF_VTH, 0x0); + /* RG_bc11_CMP_EN[1.0] = 01 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x1); + + msleep(80); + /* mdelay(80); */ + + wChargerAvail = bc11_get_register_value(PMIC_RGS_BC11_CMP_OUT); + +/* if (Enable_BATDRV_LOG == BAT_LOG_FULL) { + battery_log(BAT_LOG_FULL, "hw_bc11_stepA2() \r\n"); + hw_bc11_dump_register(); + }*/ + /* RG_bc11_VSRC_EN[1:0]=00 */ + bc11_set_register_value(PMIC_RG_BC11_VSRC_EN, 0x0); + /* RG_bc11_IPD_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPD_EN, 0x0); + /* RG_bc11_CMP_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x0); + + return wChargerAvail; +} + + +static unsigned int hw_bc11_stepB2(void) +{ + unsigned int wChargerAvail = 0; + + /* RG_bc11_IPU_EN[1:0]=10 */ + bc11_set_register_value(PMIC_RG_BC11_IPU_EN, 0x2); + /* RG_bc11_VREF_VTH = [1:0]=01 */ + bc11_set_register_value(PMIC_RG_BC11_VREF_VTH, 0x1); + /* RG_bc11_CMP_EN[1.0] = 01 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x1); + + msleep(80); + /* mdelay(80); */ + + wChargerAvail = bc11_get_register_value(PMIC_RGS_BC11_CMP_OUT); + +/* if (Enable_BATDRV_LOG == BAT_LOG_FULL) { + battery_log(BAT_LOG_FULL, "hw_bc11_stepB2() \r\n"); + hw_bc11_dump_register(); + }*/ + + + if (!wChargerAvail) { + /* RG_bc11_VSRC_EN[1.0] = 10 */ + /* mt6325_upmu_set_rg_bc11_vsrc_en(0x2); */ + bc11_set_register_value(PMIC_RG_BC11_VSRC_EN, 0x2); + } + /* RG_bc11_IPU_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPU_EN, 0x0); + /* RG_bc11_CMP_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x0); + /* RG_bc11_VREF_VTH = [1:0]=00 */ + bc11_set_register_value(PMIC_RG_BC11_VREF_VTH, 0x0); + + + return wChargerAvail; +} + + +static void hw_bc11_done(void) +{ + /* RG_bc11_VSRC_EN[1:0]=00 */ + bc11_set_register_value(PMIC_RG_BC11_VSRC_EN, 0x0); + /* RG_bc11_VREF_VTH = [1:0]=0 */ + bc11_set_register_value(PMIC_RG_BC11_VREF_VTH, 0x0); + /* RG_bc11_CMP_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_CMP_EN, 0x0); + /* RG_bc11_IPU_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPU_EN, 0x0); + /* RG_bc11_IPD_EN[1.0] = 00 */ + bc11_set_register_value(PMIC_RG_BC11_IPD_EN, 0x0); + /* RG_bc11_BIAS_EN=0 */ + bc11_set_register_value(PMIC_RG_BC11_BIAS_EN, 0x0); + + + Charger_Detect_Release(); + +/* if (Enable_BATDRV_LOG == BAT_LOG_FULL) { + battery_log(BAT_LOG_FULL, "hw_bc11_done() \r\n"); + hw_bc11_dump_register(); + }*/ + +} + + +void hw_charging_enable_dp_voltage(int ison) +{ + static int cnt; + + if (ison == 1) { + if (cnt == 0) + cnt = 1; + hw_bc11_init(); + bc11_set_register_value(PMIC_RG_BC11_VSRC_EN, 0x2); + } else if (cnt == 1) { + hw_bc11_done(); + cnt = 0; + } +} + + + + +int hw_charging_get_charger_type(void) +{ +#if 0 + return STANDARD_HOST; + /* return STANDARD_CHARGER; //adaptor */ +#else + CHARGER_TYPE CHR_Type_num = CHARGER_UNKNOWN; + +#ifdef CONFIG_MTK_USB2JTAG_SUPPORT + if (usb2jtag_mode()) { + pr_err("[USB2JTAG] in usb2jtag mode, skip charger detection\n"); + return STANDARD_HOST; + } +#endif + + /********* Step initial ***************/ + hw_bc11_init(); + + /********* Step DCD ***************/ + if (1 == hw_bc11_DCD()) { + /********* Step A1 ***************/ + if (1 == hw_bc11_stepA1()) { + CHR_Type_num = APPLE_2_1A_CHARGER; + /*battery_log(1, "step A1 : Apple 2.1A CHARGER!\r\n");*/ + } else { + CHR_Type_num = NONSTANDARD_CHARGER; + /*battery_log(1, "step A1 : Non STANDARD CHARGER!\r\n");*/ + } + } else { + /********* Step A2 ***************/ + if (1 == hw_bc11_stepA2()) { + /********* Step B2 ***************/ + if (1 == hw_bc11_stepB2()) { + is_dcp_type = true; + CHR_Type_num = STANDARD_CHARGER; + /*battery_log(1, "step B2 : STANDARD CHARGER!\r\n");*/ + } else { + CHR_Type_num = CHARGING_HOST; + /*battery_log(1, "step B2 : Charging Host!\r\n");*/ + } + } else { + CHR_Type_num = STANDARD_HOST; + /*battery_log(1, "step A2 : Standard USB Host!\r\n");*/ + } + + } + + /********* Finally setting *******************************/ + hw_bc11_done(); + + return CHR_Type_num; +#endif +} +#endif diff --git a/drivers/misc/mediatek/power/mt6755/pmic_dvt.h b/drivers/misc/mediatek/power/mt6755/pmic_dvt.h new file mode 100644 index 0000000000000000000000000000000000000000..8eff44d36d65e27d634cf0a02963360f34ea7616 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/pmic_dvt.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _PMIC_DVT_H_ +#define _PMIC_DVT_H_ +extern void pmic_dvt_entry(int test_id); +#endif /* _PMIC_DVT_H_ */ diff --git a/drivers/misc/mediatek/power/mt6755/pmic_initial_setting.c b/drivers/misc/mediatek/power/mt6755/pmic_initial_setting.c new file mode 100644 index 0000000000000000000000000000000000000000..d91f2cc13511ab2b10074dbbb6008236796960f5 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/pmic_initial_setting.c @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * pmic.c + * + * Project: + * -------- + * Android_Software + * + * Description: + * ------------ + * This Module defines PMIC functions + * + * Author: + * ------- + * Argus Lin + * + ****************************************************************************/ +#include "linux/delay.h" +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#include +#endif +#define PMIC_32K_LESS_DETECT_V1 1 +#define PMIC_CO_TSX_V1 1 + +#define PMIC_READ_REGISTER_UINT32(reg) (*(volatile uint32_t *const)(reg)) +#define PMIC_INREG32(x) PMIC_READ_REGISTER_UINT32((uint32_t *)((void *)(x))) +#define PMIC_WRITE_REGISTER_UINT32(reg, val) ((*(volatile uint32_t *const)(reg)) = (val)) +#define PMIC_OUTREG32(x, y) PMIC_WRITE_REGISTER_UINT32((uint32_t *)((void *)(x)), (uint32_t)(y)) + +#define PMIC_DRV_Reg32(addr) PMIC_INREG32(addr) +#define PMIC_DRV_WriteReg32(addr, data) PMIC_OUTREG32(addr, data) + +int PMIC_MD_INIT_SETTING_V1(void) +{ + unsigned int ret = 0; + unsigned int pmic_reg = 0; +#if PMIC_CO_TSX_V1 + struct device_node *modem_temp_node = NULL; + void __iomem *modem_temp_base = NULL; +#endif + +#if PMIC_32K_LESS_DETECT_V1 + + /* 32k less crystal auto detect start */ + ret |= pmic_config_interface(0x701E, 0x1, 0x1, 0); + ret |= pmic_config_interface(0x701E, 0x3, 0xF, 1); + ret = pmic_read_interface(0x7000, &pmic_reg, 0xffff, 0); + ret |= pmic_config_interface(0x701E, 0x0, 0x1, 0); + ret = pmic_config_interface(0xA04, 0x1, 0x1, 3); + if ((pmic_reg & 0x200) == 0x200) { + /* VCTCXO on MT6176 , OFF XO on MT6351 + HW control, use srclken_0 */ + + ret = pmic_config_interface(0xA04, 0x0, 0x7, 11); + pr_err("[PMIC] VCTCXO on MT6176 , OFF XO on MT6351\n"); + } else { + /* HW control, use srclken_1, for LP */ + ret = pmic_config_interface(0xA04, 0x1, 0x1, 4); + ret = pmic_config_interface(0xA04, 0x1, 0x7, 11); + pr_err("[PMIC] VCTCXO 0x7000=0x%x\n", pmic_reg); + } +#endif + +#if PMIC_CO_TSX_V1 + modem_temp_node = of_find_compatible_node(NULL, NULL, "mediatek,MODEM_TEMP_SHARE"); + + if (modem_temp_node == NULL) { + pr_err("PMIC get modem_temp_node failed\n"); + modem_temp_base = 0; + } else { + modem_temp_base = of_iomap(modem_temp_node, 0); + } + /* modem temp */ + PMIC_DRV_WriteReg32(modem_temp_base, 0x011f); + pr_err("[PMIC] TEMP_SHARE_CTRL:0x%x\n", PMIC_DRV_Reg32(modem_temp_base)); + /* modem temp */ + PMIC_DRV_WriteReg32(modem_temp_base + 0x04, 0x013f); + /* modem temp */ + PMIC_DRV_WriteReg32(modem_temp_base, 0x0); + pr_err("[PMIC] TEMP_SHARE_CTRL:0x%x _RATIO:0x%x\n", PMIC_DRV_Reg32(modem_temp_base), + PMIC_DRV_Reg32(modem_temp_base + 0x04)); +#endif + return ret; +} + +void PMIC_upmu_set_rg_baton_en(unsigned int val) +{ + unsigned int ret = 0; + + ret = pmic_config_interface((unsigned int)(MT6351_PMIC_RG_BATON_EN_ADDR), + (unsigned int)(val), + (unsigned int)(MT6351_PMIC_RG_BATON_EN_MASK), + (unsigned int)(MT6351_PMIC_RG_BATON_EN_SHIFT) + ); +} + +void PMIC_upmu_set_baton_tdet_en(unsigned int val) +{ + unsigned int ret = 0; + + ret = pmic_config_interface((unsigned int)(MT6351_PMIC_BATON_TDET_EN_ADDR), + (unsigned int)(val), + (unsigned int)(MT6351_PMIC_BATON_TDET_EN_MASK), + (unsigned int)(MT6351_PMIC_BATON_TDET_EN_SHIFT) + ); +} + +unsigned int PMIC_upmu_get_rgs_baton_undet(void) +{ + unsigned int ret = 0; + unsigned int val = 0; + + ret = pmic_read_interface((unsigned int)(MT6351_PMIC_RGS_BATON_UNDET_ADDR), + (&val), + (unsigned int)(MT6351_PMIC_RGS_BATON_UNDET_MASK), + (unsigned int)(MT6351_PMIC_RGS_BATON_UNDET_SHIFT) + ); + return val; +} + +int PMIC_check_battery(void) +{ + unsigned int val = 0; + + /* ask shin-shyu programming guide */ + PMIC_upmu_set_rg_baton_en(1); + PMIC_upmu_set_baton_tdet_en(1); + val = PMIC_upmu_get_rgs_baton_undet(); + if (val == 0) { + pr_debug("bat is exist.\n"); + return 1; + } + pr_debug("bat NOT exist.\n"); + return 0; +} + +void PMIC_INIT_SETTING_V1(void) +{ + unsigned int chip_version = 0; + unsigned int ret = 0; + + chip_version = pmic_get_register_value(PMIC_SWCID); + + /* This flag is used for fg to judge if battery even removed manually */ + is_battery_remove = !pmic_get_register_value(PMIC_STRUP_PWROFF_SEQ_EN); + is_wdt_reboot_pmic = pmic_get_register_value(PMIC_WDTRSTB_STATUS); + pmic_set_register_value(PMIC_TOP_RST_MISC_SET, 0x8); + is_wdt_reboot_pmic_chk = pmic_get_register_value(PMIC_WDTRSTB_STATUS); + pmic_set_register_value(PMIC_TOP_RST_MISC_CLR, 0x8); + /*--------------------------------------------------------*/ + + pr_err("[PMIC] 6351 PMIC Chip = 0x%x\n", chip_version); + pr_err("[PMIC] 2015-06-17...\n"); + pr_err("[PMIC] is_battery_remove =%d is_wdt_reboot=%d\n", + is_battery_remove, is_wdt_reboot_pmic); + pr_err("[PMIC] is_wdt_reboot_chk=%d\n", + is_wdt_reboot_pmic_chk); + + pmic_set_register_value(PMIC_TOP_RST_MISC_SET, 0x1); + +ret = pmic_config_interface(0x8, 0x1, 0x1, 0); +ret = pmic_config_interface(0xA, 0x1, 0x1, 1); +ret = pmic_config_interface(0xA, 0x1, 0x1, 2); +ret = pmic_config_interface(0xA, 0x1, 0x1, 3); +ret = pmic_config_interface(0xA, 0x1, 0x1, 4); +ret = pmic_config_interface(0xA, 0x1, 0x1, 5); +ret = pmic_config_interface(0xA, 0x1, 0x1, 7); +ret = pmic_config_interface(0xA, 0x1, 0x1, 8); +ret = pmic_config_interface(0xA, 0x1, 0x1, 10); +ret = pmic_config_interface(0xA, 0x1, 0x1, 11); +ret = pmic_config_interface(0xA, 0x1, 0x1, 12); +ret = pmic_config_interface(0xA, 0x1, 0x1, 13); +ret = pmic_config_interface(0xA, 0x1, 0x1, 14); +ret = pmic_config_interface(0xA, 0x1, 0x1, 15); +ret = pmic_config_interface(0x18, 0x1, 0x1, 5); +ret = pmic_config_interface(0x1C, 0x1, 0x1, 7); +ret = pmic_config_interface(0x1E, 0x1, 0x1, 0); +ret = pmic_config_interface(0x1E, 0x1, 0x1, 1); +ret = pmic_config_interface(0x2C, 0x1, 0x1, 15); +ret = pmic_config_interface(0x32, 0x1, 0x1, 2); +ret = pmic_config_interface(0x32, 0x1, 0x1, 3); +ret = pmic_config_interface(0x204, 0x1, 0x1, 4); +ret = pmic_config_interface(0x204, 0x1, 0x1, 5); +ret = pmic_config_interface(0x204, 0x1, 0x1, 6); +ret = pmic_config_interface(0x226, 0x1, 0x1, 0); +ret = pmic_config_interface(0x228, 0x1, 0x1, 0); +ret = pmic_config_interface(0x228, 0x1, 0x1, 1); +ret = pmic_config_interface(0x228, 0x1, 0x1, 2); +ret = pmic_config_interface(0x228, 0x1, 0x1, 3); +ret = pmic_config_interface(0x23A, 0x0, 0x1, 9); +ret = pmic_config_interface(0x23A, 0x1, 0x1, 11); +ret = pmic_config_interface(0x240, 0x1, 0x1, 2); +ret = pmic_config_interface(0x240, 0x1, 0x1, 3); +ret = pmic_config_interface(0x240, 0x0, 0x1, 10); +ret = pmic_config_interface(0x246, 0x1, 0x1, 13); +ret = pmic_config_interface(0x246, 0x1, 0x1, 14); +ret = pmic_config_interface(0x24C, 0x0, 0x1, 2); +ret = pmic_config_interface(0x258, 0x0, 0x1, 5); +ret = pmic_config_interface(0x258, 0x1, 0x1, 8); +ret = pmic_config_interface(0x258, 0x0, 0x1, 14); +ret = pmic_config_interface(0x25E, 0x1, 0x1, 9); +ret = pmic_config_interface(0x25E, 0x0, 0x1, 10); +ret = pmic_config_interface(0x282, 0x0, 0x1, 3); +ret = pmic_config_interface(0x282, 0x0, 0x1, 4); +ret = pmic_config_interface(0x282, 0x0, 0x1, 10); +ret = pmic_config_interface(0x282, 0x0, 0x1, 11); +ret = pmic_config_interface(0x28E, 0x0, 0x1, 4); +ret = pmic_config_interface(0x410, 0x8, 0x3F, 8); +ret = pmic_config_interface(0x414, 0x3, 0x3, 4); +ret = pmic_config_interface(0x422, 0x1, 0x1, 7); +ret = pmic_config_interface(0x436, 0x0, 0x3, 2); +ret = pmic_config_interface(0x450, 0xF, 0xF, 11); +ret = pmic_config_interface(0x452, 0x1, 0x1, 3); +ret = pmic_config_interface(0x456, 0x1, 0x1, 7); +ret = pmic_config_interface(0x45C, 0x1, 0x1, 1); +ret = pmic_config_interface(0x45E, 0x400, 0xFFFF, 0); +ret = pmic_config_interface(0x464, 0xF, 0xF, 11); +ret = pmic_config_interface(0x466, 0x1, 0x1, 3); +ret = pmic_config_interface(0x466, 0x5, 0x7, 9); +ret = pmic_config_interface(0x46A, 0x1, 0x1, 7); +ret = pmic_config_interface(0x470, 0x1, 0x1, 1); +ret = pmic_config_interface(0x472, 0x400, 0xFFFF, 0); +ret = pmic_config_interface(0x478, 0xF, 0xF, 11); +ret = pmic_config_interface(0x47A, 0x2, 0x7, 6); +ret = pmic_config_interface(0x47E, 0x1, 0x1, 1); +ret = pmic_config_interface(0x480, 0x1, 0x7, 4); +ret = pmic_config_interface(0x484, 0x1, 0x1, 1); +ret = pmic_config_interface(0x48C, 0xF, 0xF, 11); +ret = pmic_config_interface(0x48E, 0x2, 0x7, 6); +ret = pmic_config_interface(0x492, 0x1, 0x1, 1); +ret = pmic_config_interface(0x494, 0x1, 0x7, 4); +ret = pmic_config_interface(0x498, 0x1, 0x1, 1); +ret = pmic_config_interface(0x4A0, 0xF, 0xF, 11); +ret = pmic_config_interface(0x4A2, 0x2, 0x7, 6); +ret = pmic_config_interface(0x4A6, 0x1, 0x1, 1); +ret = pmic_config_interface(0x4A8, 0x1, 0x7, 4); +ret = pmic_config_interface(0x4AC, 0x1, 0x1, 1); +ret = pmic_config_interface(0x4B6, 0x6, 0x7, 6); +ret = pmic_config_interface(0x4C2, 0x10, 0xFFFF, 0); +ret = pmic_config_interface(0x4C8, 0xF, 0xF, 11); +ret = pmic_config_interface(0x4CA, 0x5, 0x7, 6); +ret = pmic_config_interface(0x4CE, 0x1, 0x1, 1); +ret = pmic_config_interface(0x4D0, 0x1, 0x7, 4); +ret = pmic_config_interface(0x4DC, 0x3, 0x3, 0); +ret = pmic_config_interface(0x4DC, 0x2, 0x3, 4); +ret = pmic_config_interface(0x4DC, 0x0, 0x1, 10); +ret = pmic_config_interface(0x4DC, 0x1, 0x3, 14); +ret = pmic_config_interface(0x4E0, 0x0, 0x3, 14); +ret = pmic_config_interface(0x4E2, 0x88, 0xFF, 8); +ret = pmic_config_interface(0x600, 0x1, 0x1, 1); +ret = pmic_config_interface(0x606, 0x11, 0x7F, 0); +ret = pmic_config_interface(0x606, 0x4, 0x7F, 8); +ret = pmic_config_interface(0x60C, 0x10, 0x7F, 0); +ret = pmic_config_interface(0x612, 0x3, 0x3, 0); +ret = pmic_config_interface(0x612, 0x1, 0x1, 8); +ret = pmic_config_interface(0x61A, 0x11, 0x7F, 0); +ret = pmic_config_interface(0x61A, 0x4, 0x7F, 8); +ret = pmic_config_interface(0x620, 0x10, 0x7F, 0); +ret = pmic_config_interface(0x626, 0x3, 0x3, 0); +ret = pmic_config_interface(0x626, 0x1, 0x3, 4); +ret = pmic_config_interface(0x62E, 0x11, 0x7F, 0); +ret = pmic_config_interface(0x62E, 0x4, 0x7F, 8); +ret = pmic_config_interface(0x634, 0x10, 0x7F, 0); +ret = pmic_config_interface(0x63A, 0x3, 0x3, 0); +ret = pmic_config_interface(0x63A, 0x1, 0x3, 4); +ret = pmic_config_interface(0x63A, 0x1, 0x1, 8); +ret = pmic_config_interface(0x642, 0x11, 0x7F, 0); +ret = pmic_config_interface(0x642, 0x4, 0x7F, 8); +ret = pmic_config_interface(0x646, 0x30, 0x7F, 0); +ret = pmic_config_interface(0x648, 0x10, 0x7F, 0); +ret = pmic_config_interface(0x64E, 0x3, 0x3, 0); +ret = pmic_config_interface(0x64E, 0x1, 0x3, 4); +ret = pmic_config_interface(0x64E, 0x1, 0x1, 8); +ret = pmic_config_interface(0x656, 0x11, 0x7F, 0); +ret = pmic_config_interface(0x656, 0x4, 0x7F, 8); +ret = pmic_config_interface(0x65C, 0x10, 0x7F, 0); +ret = pmic_config_interface(0x662, 0x3, 0x3, 0); +ret = pmic_config_interface(0x662, 0x1, 0x3, 4); +ret = pmic_config_interface(0x662, 0x1, 0x1, 8); +ret = pmic_config_interface(0x676, 0x1, 0x1, 8); +ret = pmic_config_interface(0x68A, 0x1, 0x1, 8); +ret = pmic_config_interface(0x692, 0x0, 0x7F, 0); +ret = pmic_config_interface(0x692, 0x1, 0x7F, 8); +ret = pmic_config_interface(0x69E, 0x0, 0x3, 0); +ret = pmic_config_interface(0x6A0, 0x1, 0x1, 1); +ret = pmic_config_interface(0x6A6, 0x11, 0x7F, 0); +ret = pmic_config_interface(0x6A6, 0x4, 0x7F, 8); +ret = pmic_config_interface(0x6AC, 0x35, 0x7F, 0); +ret = pmic_config_interface(0x6B2, 0x3, 0x3, 0); +ret = pmic_config_interface(0x6B2, 0x1, 0x3, 4); +ret = pmic_config_interface(0x6B2, 0x0, 0x1, 8); +ret = pmic_config_interface(0xA00, 0x1, 0x1, 2); +ret = pmic_config_interface(0xA00, 0x0, 0x7, 5); +ret = pmic_config_interface(0xA02, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA04, 0x1, 0x1, 3); +ret = pmic_config_interface(0xA04, 0x0, 0x7, 11); +ret = pmic_config_interface(0xA06, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA08, 0x1, 0x1, 3); +ret = pmic_config_interface(0xA08, 0x1, 0x7, 11); +ret = pmic_config_interface(0xA0A, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA0E, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA14, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA16, 0x1, 0x1, 2); +ret = pmic_config_interface(0xA16, 0x0, 0x7, 5); +ret = pmic_config_interface(0xA18, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA1E, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA24, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA2A, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA30, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA34, 0x1, 0x1, 2); +ret = pmic_config_interface(0xA34, 0x0, 0x7, 5); +ret = pmic_config_interface(0xA36, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA3C, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA46, 0x1, 0x1, 3); +ret = pmic_config_interface(0xA46, 0x1, 0x7, 11); +ret = pmic_config_interface(0xA48, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA4C, 0x1, 0x1, 2); +ret = pmic_config_interface(0xA4C, 0x0, 0x7, 5); +ret = pmic_config_interface(0xA4E, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA54, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA5A, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA66, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA68, 0x1, 0x1, 3); +ret = pmic_config_interface(0xA68, 0x1, 0x7, 11); +ret = pmic_config_interface(0xA6E, 0x1, 0x1, 2); +ret = pmic_config_interface(0xA6E, 0x0, 0x7, 5); +ret = pmic_config_interface(0xA74, 0x1, 0x1, 1); +ret = pmic_config_interface(0xA74, 0x1, 0x1, 2); +ret = pmic_config_interface(0xA74, 0x0, 0x1, 3); +ret = pmic_config_interface(0xA74, 0x0, 0x7, 5); +ret = pmic_config_interface(0xA7C, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA82, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA86, 0x0, 0x1, 3); +ret = pmic_config_interface(0xA88, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA8E, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA94, 0x1, 0x1, 9); +ret = pmic_config_interface(0xA9C, 0x1, 0x1, 2); +ret = pmic_config_interface(0xA9C, 0x0, 0x7, 5); +ret = pmic_config_interface(0xA9E, 0x1, 0x1, 9); +ret = pmic_config_interface(0xAAC, 0x1, 0x1, 9); +ret = pmic_config_interface(0xB10, 0x2, 0x7, 8); +ret = pmic_config_interface(0xCC4, 0x1, 0x1, 8); +ret = pmic_config_interface(0xCC4, 0x1, 0x1, 9); +ret = pmic_config_interface(0xCC8, 0x1F, 0xFFFF, 0); +ret = pmic_config_interface(0xCCA, 0x14, 0xFF, 0); +ret = pmic_config_interface(0xCCC, 0xFF, 0xFF, 8); +ret = pmic_config_interface(0xCE2, 0x1, 0x7FFF, 0); +ret = pmic_config_interface(0xCE4, 0xBCAC, 0xFFFF, 0); +ret = pmic_config_interface(0xEA2, 0x0, 0x1, 13); +ret = pmic_config_interface(0xEA2, 0x0, 0x1, 14); +ret = pmic_config_interface(0xEA2, 0x0, 0x1, 15); +ret = pmic_config_interface(0xEAA, 0x83, 0xFFF, 0); +ret = pmic_config_interface(0xEAA, 0x0, 0x1, 13); +ret = pmic_config_interface(0xEAA, 0x1, 0x1, 15); +ret = pmic_config_interface(0xEB2, 0x1, 0x3, 4); +ret = pmic_config_interface(0xEB2, 0x3, 0x3, 6); +ret = pmic_config_interface(0xEB2, 0x1, 0x3, 8); +ret = pmic_config_interface(0xEB2, 0x1, 0x3, 10); +ret = pmic_config_interface(0xEB2, 0x1, 0x3, 12); +ret = pmic_config_interface(0xEB2, 0x2, 0x3, 14); +ret = pmic_config_interface(0xEB4, 0x1, 0x3, 0); +ret = pmic_config_interface(0xEB4, 0x1, 0x3, 2); +ret = pmic_config_interface(0xEB4, 0x1, 0x3, 4); +ret = pmic_config_interface(0xEB4, 0x3, 0x3, 6); +ret = pmic_config_interface(0xEC6, 0x1, 0x1, 14); +ret = pmic_config_interface(0xF16, 0xC, 0x3FF, 0); +ret = pmic_config_interface(0xF16, 0x0, 0x1, 15); +ret = pmic_config_interface(0xF1C, 0xC, 0x3FF, 0); +ret = pmic_config_interface(0xF1C, 0x1, 0x1, 15); +ret = pmic_config_interface(0xF20, 0x1, 0x1, 2); +ret = pmic_config_interface(0xF7A, 0xB, 0xF, 4); +ret = pmic_config_interface(0xF84, 0x4, 0xF, 1); +ret = pmic_config_interface(0xF92, 0x3, 0xF, 0); +ret = pmic_config_interface(0xFA0, 0x1, 0x1, 1); +ret = pmic_config_interface(0xFA4, 0x0, 0x7, 4); +ret = pmic_config_interface(0xFAA, 0x1, 0x1, 2); +ret = pmic_config_interface(0xFAA, 0x1, 0x1, 6); +ret = pmic_config_interface(0xFAA, 0x1, 0x1, 7); + +ret = PMIC_IMM_GetOneChannelValue(PMIC_AUX_CH11, 5, 0); + +/***************************************************** + * below programming is used for MD setting + *****************************************************/ + PMIC_MD_INIT_SETTING_V1(); +} diff --git a/drivers/misc/mediatek/power/mt6755/pmic_irq.c b/drivers/misc/mediatek/power/mt6755/pmic_irq.c new file mode 100644 index 0000000000000000000000000000000000000000..39d8e3a9b64291c004756a7f5a885f43bbdbf398 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/pmic_irq.c @@ -0,0 +1,721 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/***************************************************************************** + * + * Filename: + * --------- + * pmic_irq.c + * + * Project: + * -------- + * Android_Software + * + * Description: + * ------------ + * This Module defines PMIC functions + * + * Author: + * ------- + * Jimmy-YJ Huang + * + ****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#include +#include +#include +#include +#endif +#include + +#include +#include "pmic.h" +/*#include TBD*/ +#include +#include +#include + +#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) +#include +#include +/*#include TBD*/ +#include +#endif + +#if defined(CONFIG_MTK_SMART_BATTERY) +#include +#include +#include +#endif +#include "mt6311.h" +#include +#include + +/***************************************************************************** + * Global variable + ******************************************************************************/ +int g_pmic_irq; +unsigned int g_eint_pmic_num = 150; +unsigned int g_cust_eint_mt_pmic_debounce_cn = 1; +unsigned int g_cust_eint_mt_pmic_type = 4; +unsigned int g_cust_eint_mt_pmic_debounce_en = 1; + +/***************************************************************************** + * PMIC extern variable + ******************************************************************************/ +#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) +static bool long_pwrkey_press; +static unsigned long timer_pre; +static unsigned long timer_pos; +#define LONG_PWRKEY_PRESS_TIME_UNIT 500 /*500ms */ +#define LONG_PWRKEY_PRESS_TIME_US 1000000 /*500ms */ +#endif + +/***************************************************************************** + * PMIC extern function + ******************************************************************************/ + +#define PMIC_DEBUG_PR_DBG +/* +#define PMICTAG "[PMIC] " +#if defined PMIC_DEBUG_PR_DBG +#define PMICLOG(fmt, arg...) pr_err(PMICTAG fmt, ##arg) +#else +#define PMICLOG(fmt, arg...) +#endif +*/ +#ifndef CONFIG_KEYBOARD_MTK /* fix kpd build error only */ +void kpd_pwrkey_pmic_handler(unsigned long pressed) +{} +void kpd_pmic_rstkey_handler(unsigned long pressed) +{} +#endif + +/***************************************************************************** + * interrupt Setting + ******************************************************************************/ +static struct pmic_interrupt_bit interrupt_status0[] = { + PMIC_S_INT_GEN(RG_INT_STATUS_PWRKEY), + PMIC_S_INT_GEN(RG_INT_STATUS_HOMEKEY), + PMIC_S_INT_GEN(RG_INT_STATUS_PWRKEY_R), + PMIC_S_INT_GEN(RG_INT_STATUS_HOMEKEY_R), + PMIC_S_INT_GEN(RG_INT_STATUS_THR_H), + PMIC_S_INT_GEN(RG_INT_STATUS_THR_L), + PMIC_S_INT_GEN(RG_INT_STATUS_BAT_H), + PMIC_S_INT_GEN(RG_INT_STATUS_BAT_L), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(RG_INT_STATUS_RTC), + PMIC_S_INT_GEN(RG_INT_STATUS_AUDIO), + PMIC_S_INT_GEN(RG_INT_STATUS_MAD), + PMIC_S_INT_GEN(RG_INT_STATUS_ACCDET), + PMIC_S_INT_GEN(RG_INT_STATUS_ACCDET_EINT), + PMIC_S_INT_GEN(RG_INT_STATUS_ACCDET_NEGV), + PMIC_S_INT_GEN(RG_INT_STATUS_NI_LBAT_INT), +}; + +static struct pmic_interrupt_bit interrupt_status1[] = { + PMIC_S_INT_GEN(RG_INT_STATUS_VCORE_OC), + PMIC_S_INT_GEN(RG_INT_STATUS_VGPU_OC), + PMIC_S_INT_GEN(RG_INT_STATUS_VSRAM_MD_OC), + PMIC_S_INT_GEN(RG_INT_STATUS_VMODEM_OC), + PMIC_S_INT_GEN(RG_INT_STATUS_VM1_OC), + PMIC_S_INT_GEN(RG_INT_STATUS_VS1_OC), + PMIC_S_INT_GEN(RG_INT_STATUS_VS2_OC), + PMIC_S_INT_GEN(RG_INT_STATUS_VPA_OC), + PMIC_S_INT_GEN(RG_INT_STATUS_VCORE_PREOC), + PMIC_S_INT_GEN(RG_INT_STATUS_VGPU_PREOC), + PMIC_S_INT_GEN(RG_INT_STATUS_VSRAM_MD_PREOC), + PMIC_S_INT_GEN(RG_INT_STATUS_VMODEM_PREOC), + PMIC_S_INT_GEN(RG_INT_STATUS_VM1_PREOC), + PMIC_S_INT_GEN(RG_INT_STATUS_VS1_PREOC), + PMIC_S_INT_GEN(RG_INT_STATUS_VS2_PREOC), + PMIC_S_INT_GEN(RG_INT_STATUS_LDO_OC), +}; + +static struct pmic_interrupt_bit interrupt_status2[] = { + PMIC_S_INT_GEN(RG_INT_STATUS_JEITA_HOT), + PMIC_S_INT_GEN(RG_INT_STATUS_JEITA_WARM), + PMIC_S_INT_GEN(RG_INT_STATUS_JEITA_COOL), + PMIC_S_INT_GEN(RG_INT_STATUS_JEITA_COLD), + PMIC_S_INT_GEN(RG_INT_STATUS_AUXADC_IMP), + PMIC_S_INT_GEN(RG_INT_STATUS_NAG_C_DLTV), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(RG_INT_STATUS_OV), + PMIC_S_INT_GEN(RG_INT_STATUS_BVALID_DET), + PMIC_S_INT_GEN(RG_INT_STATUS_RGS_BATON_HV), + PMIC_S_INT_GEN(RG_INT_STATUS_VBATON_UNDET), + PMIC_S_INT_GEN(RG_INT_STATUS_WATCHDOG), + PMIC_S_INT_GEN(RG_INT_STATUS_PCHR_CM_VDEC), + PMIC_S_INT_GEN(RG_INT_STATUS_CHRDET), + PMIC_S_INT_GEN(RG_INT_STATUS_PCHR_CM_VINC), +}; + +static struct pmic_interrupt_bit interrupt_status3[] = { + PMIC_S_INT_GEN(RG_INT_STATUS_FG_BAT_H), + PMIC_S_INT_GEN(RG_INT_STATUS_FG_BAT_L), + PMIC_S_INT_GEN(RG_INT_STATUS_FG_CUR_H), + PMIC_S_INT_GEN(RG_INT_STATUS_FG_CUR_L), + PMIC_S_INT_GEN(RG_INT_STATUS_FG_ZCV), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), + PMIC_S_INT_GEN(NO_USE), +}; + +struct pmic_interrupts interrupts[] = { + PMIC_M_INTS_GEN(MT6351_INT_STATUS0, MT6351_INT_CON0, MT6351_INT_CON0_SET, + MT6351_INT_CON0_CLR, interrupt_status0), + PMIC_M_INTS_GEN(MT6351_INT_STATUS1, MT6351_INT_CON1, MT6351_INT_CON1_SET, + MT6351_INT_CON1_CLR, interrupt_status1), + PMIC_M_INTS_GEN(MT6351_INT_STATUS2, MT6351_INT_CON2, MT6351_INT_CON2_SET, + MT6351_INT_CON2_CLR, interrupt_status2), + PMIC_M_INTS_GEN(MT6351_INT_STATUS3, MT6351_INT_CON3, MT6351_INT_CON3_SET, + MT6351_INT_CON3_CLR, interrupt_status3), +}; + +int interrupts_size = ARRAY_SIZE(interrupts); + +/***************************************************************************** + * PWRKEY Int Handler + ******************************************************************************/ +void pwrkey_int_handler(void) +{ + + PMICLOG("[pwrkey_int_handler] Press pwrkey %d\n", + pmic_get_register_value(PMIC_PWRKEY_DEB)); + +#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) + if (get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT) + timer_pre = sched_clock(); +#endif +#if defined(CONFIG_MTK_FPGA) +#else + kpd_pwrkey_pmic_handler(0x1); +#endif +} + +void pwrkey_int_handler_r(void) +{ + PMICLOG("[pwrkey_int_handler_r] Release pwrkey %d\n", + pmic_get_register_value(PMIC_PWRKEY_DEB)); +#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) + if (get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT && timer_pre != 0) { + timer_pos = sched_clock(); + if (timer_pos - timer_pre >= + LONG_PWRKEY_PRESS_TIME_UNIT * LONG_PWRKEY_PRESS_TIME_US) { + long_pwrkey_press = true; + } + PMICLOG + ("timer_pos = %ld, timer_pre = %ld, timer_pos-timer_pre = %ld, long_pwrkey_press = %d\r\n", + timer_pos, timer_pre, timer_pos - timer_pre, long_pwrkey_press); + if (long_pwrkey_press) { /*500ms */ + PMICLOG + ("Power Key Pressed during kernel power off charging, reboot OS\r\n"); + arch_reset(0, NULL); + } + } +#endif +#if defined(CONFIG_MTK_FPGA) +#else + kpd_pwrkey_pmic_handler(0x0); +#endif +} + +/***************************************************************************** + * Homekey Int Handler + ******************************************************************************/ +void homekey_int_handler(void) +{ + PMICLOG("[homekey_int_handler] Press homekey %d\n", + pmic_get_register_value(PMIC_HOMEKEY_DEB)); +#if defined(CONFIG_MTK_FPGA) +#else + kpd_pmic_rstkey_handler(0x1); +#endif +} + +void homekey_int_handler_r(void) +{ + PMICLOG("[homekey_int_handler_r] Release homekey %d\n", + pmic_get_register_value(PMIC_HOMEKEY_DEB)); +#if defined(CONFIG_MTK_FPGA) +#else + kpd_pmic_rstkey_handler(0x0); +#endif +} + +/***************************************************************************** + * Chrdet Int Handler + ******************************************************************************/ +void chrdet_int_handler(void) +{ + PMICLOG("[chrdet_int_handler]CHRDET status = %d....\n", + pmic_get_register_value(PMIC_RGS_CHRDET)); + +#ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING + if (!upmu_get_rgs_chrdet()) { + int boot_mode = 0; + + boot_mode = get_boot_mode(); + + if (boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT + || boot_mode == LOW_POWER_OFF_CHARGING_BOOT) { + PMICLOG("[chrdet_int_handler] Unplug Charger/USB\n"); + mt_power_off(); + } + } +#endif + pmic_set_register_value(PMIC_RG_USBDL_RST, 1); +#if defined(CONFIG_MTK_SMART_BATTERY) + do_chrdet_int_task(); +#endif + +} + +/***************************************************************************** + * Auxadc Int Handler + ******************************************************************************/ +void auxadc_imp_int_handler_r(void) +{ + PMICLOG("auxadc_imp_int_handler_r() =%d\n", + pmic_get_register_value(PMIC_AUXADC_ADC_OUT_IMP)); + /*clear IRQ */ + pmic_set_register_value(PMIC_AUXADC_CLR_IMP_CNT_STOP, 1); + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_CLR, 1); + /*restore to initial state */ + pmic_set_register_value(PMIC_AUXADC_CLR_IMP_CNT_STOP, 0); + pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_CLR, 0); + /*turn off interrupt */ + pmic_set_register_value(PMIC_RG_INT_EN_AUXADC_IMP, 0); + +} + +/***************************************************************************** + * Ldo OC Int Handler + ******************************************************************************/ +void ldo_oc_int_handler(void) +{ + if (pmic_get_register_value(PMIC_OC_STATUS_VMCH)) + msdc_sd_power_off(); +} + +/***************************************************************************** + * Low battery call back function + ******************************************************************************/ +#define LBCB_NUM 16 + +#ifndef DISABLE_LOW_BATTERY_PROTECT +#define LOW_BATTERY_PROTECT +#endif + +#ifdef LOW_BATTERY_PROTECT +/* ex. 3400/5400*4096*/ +#define BAT_HV_THD (POWER_INT0_VOLT*4096/5400) /*ex: 3400mV*/ +#define BAT_LV_1_THD (POWER_INT1_VOLT*4096/5400) /*ex: 3250mV*/ +#define BAT_LV_2_THD (POWER_INT2_VOLT*4096/5400) /*ex: 3000mV*/ +#endif + +void bat_h_int_handler(void) +{ + g_lowbat_int_bottom = 0; + + PMICLOG("[bat_h_int_handler]....\n"); + + /*sub-task*/ +#ifdef LOW_BATTERY_PROTECT + g_low_battery_level = 0; + exec_low_battery_callback(LOW_BATTERY_LEVEL_0); + +#if 0 + lbat_max_en_setting(0); + mdelay(1); + lbat_min_en_setting(1); +#else + pmic_set_register_value(PMIC_AUXADC_LBAT_VOLT_MIN, BAT_LV_1_THD); + + lbat_min_en_setting(0); + lbat_max_en_setting(0); + mdelay(1); + lbat_min_en_setting(1); +#endif + + PMICLOG("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_AUXADC_LBAT3, upmu_get_reg_value(MT6351_AUXADC_LBAT3), + MT6351_AUXADC_LBAT4, upmu_get_reg_value(MT6351_AUXADC_LBAT4), + MT6351_INT_CON0, upmu_get_reg_value(MT6351_INT_CON0) + ); +#endif + +} + +void bat_l_int_handler(void) +{ + PMICLOG("[bat_l_int_handler]....\n"); + + /*sub-task*/ +#ifdef LOW_BATTERY_PROTECT + g_low_battery_level++; + if (g_low_battery_level > 2) + g_low_battery_level = 2; + + if (g_low_battery_level == 1) + exec_low_battery_callback(LOW_BATTERY_LEVEL_1); + else if (g_low_battery_level == 2) { + exec_low_battery_callback(LOW_BATTERY_LEVEL_2); + g_lowbat_int_bottom = 1; + } else + PMICLOG("[bat_l_int_handler]err,g_low_battery_level=%d\n", g_low_battery_level); + +#if 0 + lbat_min_en_setting(0); + mdelay(1); + lbat_max_en_setting(1); +#else + + pmic_set_register_value(PMIC_AUXADC_LBAT_VOLT_MIN, BAT_LV_2_THD); + + lbat_min_en_setting(0); + lbat_max_en_setting(0); + mdelay(1); + if (g_low_battery_level < 2) + lbat_min_en_setting(1); + lbat_max_en_setting(1); +#endif + + PMICLOG("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_AUXADC_LBAT3, upmu_get_reg_value(MT6351_AUXADC_LBAT3), + MT6351_AUXADC_LBAT4, upmu_get_reg_value(MT6351_AUXADC_LBAT4), + MT6351_INT_CON0, upmu_get_reg_value(MT6351_INT_CON0) + ); +#endif + +} + +/***************************************************************************** + * Battery OC call back function + ******************************************************************************/ + +#ifndef DISABLE_BATTERY_OC_PROTECT +#define BATTERY_OC_PROTECT +#endif + +void fg_cur_h_int_handler(void) +{ + PMICLOG("[fg_cur_h_int_handler]....\n"); + + /*sub-task*/ +#ifdef BATTERY_OC_PROTECT + g_battery_oc_level = 0; + exec_battery_oc_callback(BATTERY_OC_LEVEL_0); + bat_oc_h_en_setting(0); + bat_oc_l_en_setting(0); + mdelay(1); + bat_oc_l_en_setting(1); + + PMICLOG("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_PMIC_FG_CUR_HTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_HTH_ADDR), + MT6351_PMIC_FG_CUR_LTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_LTH_ADDR), + MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR, upmu_get_reg_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR) + ); +#endif +} + +void fg_cur_l_int_handler(void) +{ + PMICLOG("[fg_cur_l_int_handler]....\n"); + + /*sub-task*/ +#ifdef BATTERY_OC_PROTECT + g_battery_oc_level = 1; + exec_battery_oc_callback(BATTERY_OC_LEVEL_1); + bat_oc_h_en_setting(0); + bat_oc_l_en_setting(0); + mdelay(1); + bat_oc_h_en_setting(1); + + PMICLOG("Reg[0x%x]=0x%x, Reg[0x%x]=0x%x, Reg[0x%x]=0x%x\n", + MT6351_PMIC_FG_CUR_HTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_HTH_ADDR), + MT6351_PMIC_FG_CUR_LTH_ADDR, upmu_get_reg_value(MT6351_PMIC_FG_CUR_LTH_ADDR), + MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR, upmu_get_reg_value(MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR) + ); +#endif +} + +/***************************************************************************** + * PMIC Interrupt service + ******************************************************************************/ +static DEFINE_MUTEX(pmic_mutex); +struct task_struct *pmic_thread_handle; + +#if !defined CONFIG_HAS_WAKELOCKS +struct wakeup_source pmicThread_lock; +#else +struct wake_lock pmicThread_lock; +#endif + +void wake_up_pmic(void) +{ + PMICLOG("[%s]\n", __func__); + if (pmic_thread_handle != NULL) { +#if !defined CONFIG_HAS_WAKELOCKS + __pm_stay_awake(&pmicThread_lock); +#else + wake_lock(&pmicThread_lock); +#endif + wake_up_process(pmic_thread_handle); + } else { + pr_err(PMICTAG "[%s] pmic_thread_handle not ready\n", __func__); + return; + } +} +EXPORT_SYMBOL(wake_up_pmic); + +irqreturn_t mt_pmic_eint_irq(int irq, void *desc) +{ + disable_irq_nosync(irq); + PMICLOG("[mt_pmic_eint_irq] disable PMIC irq\n"); + wake_up_pmic(); + return IRQ_HANDLED; +} + +void pmic_enable_interrupt(unsigned int intNo, unsigned int en, char *str) +{ + unsigned int shift, no; + + shift = intNo / PMIC_INT_WIDTH; + no = intNo % PMIC_INT_WIDTH; + + if (shift >= ARRAY_SIZE(interrupts)) { + PMICLOG("[pmic_enable_interrupt] fail intno=%d \r\n", intNo); + return; + } + + PMICLOG("[pmic_enable_interrupt] intno=%d en=%d str=%s shf=%d no=%d [0x%x]=0x%x\r\n", + intNo, en, str, shift, no, interrupts[shift].en, + upmu_get_reg_value(interrupts[shift].en)); + + if (en == 1) + pmic_config_interface(interrupts[shift].set, 0x1, 0x1, no); + else if (en == 0) + pmic_config_interface(interrupts[shift].clear, 0x1, 0x1, no); + + PMICLOG("[pmic_enable_interrupt] after [0x%x]=0x%x\r\n", + interrupts[shift].en, upmu_get_reg_value(interrupts[shift].en)); + +} + +void pmic_register_interrupt_callback(unsigned int intNo, void (EINT_FUNC_PTR) (void)) +{ + unsigned int shift, no; + + shift = intNo / PMIC_INT_WIDTH; + no = intNo % PMIC_INT_WIDTH; + + if (shift >= ARRAY_SIZE(interrupts)) { + PMICLOG("[pmic_register_interrupt_callback] fail intno=%d\r\n", intNo); + return; + } + + PMICLOG("[pmic_register_interrupt_callback] intno=%d\r\n", intNo); + + interrupts[shift].interrupts[no].callback = EINT_FUNC_PTR; + +} + +void PMIC_EINT_SETTING(void) +{ + struct device_node *node = NULL; + int ret = 0; + u32 ints[2] = { 0, 0 }; + + upmu_set_reg_value(MT6351_INT_CON0, 0); + upmu_set_reg_value(MT6351_INT_CON1, 0); + upmu_set_reg_value(MT6351_INT_CON2, 0); + upmu_set_reg_value(MT6351_INT_CON3, 0); + + /*enable pwrkey/homekey interrupt */ + upmu_set_reg_value(MT6351_INT_CON0_SET, 0xf); + + /*for all interrupt events, turn on interrupt module clock */ + pmic_set_register_value(PMIC_RG_INTRP_CK_PDN, 0); + + /*For BUCK OC related interrupt, please turn on pwmoc_6m_ck (6MHz) */ + pmic_set_register_value(PMIC_RG_PWMOC_6M_CK_PDN, 0); + + pmic_register_interrupt_callback(0, pwrkey_int_handler); + pmic_register_interrupt_callback(1, homekey_int_handler); + pmic_register_interrupt_callback(2, pwrkey_int_handler_r); + pmic_register_interrupt_callback(3, homekey_int_handler_r); + + pmic_register_interrupt_callback(6, bat_h_int_handler); + pmic_register_interrupt_callback(7, bat_l_int_handler); + + /*pmic_register_interrupt_callback(31, ldo_oc_int_handler);*/ + pmic_register_interrupt_callback(46, chrdet_int_handler); + + pmic_register_interrupt_callback(50, fg_cur_h_int_handler); + pmic_register_interrupt_callback(51, fg_cur_l_int_handler); + + pmic_enable_interrupt(0, 1, "PMIC"); + pmic_enable_interrupt(1, 1, "PMIC"); + pmic_enable_interrupt(2, 1, "PMIC"); + pmic_enable_interrupt(3, 1, "PMIC"); +#ifdef LOW_BATTERY_PROTECT + /* move to lbat_xxx_en_setting */ +#else + /* pmic_enable_interrupt(6, 1, "PMIC"); */ + /* pmic_enable_interrupt(7, 1, "PMIC"); */ +#endif + /*pmic_enable_interrupt(31, 1, "PMIC");*/ + pmic_enable_interrupt(46, 1, "PMIC"); +#ifdef BATTERY_OC_PROTECT + /* move to bat_oc_x_en_setting */ +#else + /* pmic_enable_interrupt(50, 1, "PMIC"); */ + /* pmic_enable_interrupt(51, 1, "PMIC"); */ +#endif + + /*mt_eint_set_hw_debounce(g_eint_pmic_num, g_cust_eint_mt_pmic_debounce_cn);*/ + /*mt_eint_registration(g_eint_pmic_num, g_cust_eint_mt_pmic_type, mt_pmic_eint_irq, 0);*/ + /*mt_eint_unmask(g_eint_pmic_num);*/ + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6351-pmic"); + if (node) { + of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints)); + /* mt_gpio_set_debounce(ints[0], ints[1]); */ + + g_pmic_irq = irq_of_parse_and_map(node, 0); + ret = request_irq(g_pmic_irq, (irq_handler_t) mt_pmic_eint_irq, IRQF_TRIGGER_NONE, "pmic-eint", NULL); + if (ret > 0) + pr_err(PMICTAG "EINT IRQ LINENNOT AVAILABLE\n"); + enable_irq_wake(g_pmic_irq); + } else + pr_err(PMICTAG "can't find compatible node\n"); + + PMICLOG("[CUST_EINT] CUST_EINT_MT_PMIC_MT6325_NUM=%d\n", g_eint_pmic_num); + PMICLOG("[CUST_EINT] CUST_EINT_PMIC_DEBOUNCE_CN=%d\n", g_cust_eint_mt_pmic_debounce_cn); + PMICLOG("[CUST_EINT] CUST_EINT_PMIC_TYPE=%d\n", g_cust_eint_mt_pmic_type); + PMICLOG("[CUST_EINT] CUST_EINT_PMIC_DEBOUNCE_EN=%d\n", g_cust_eint_mt_pmic_debounce_en); + +} + +static void pmic_int_handler(void) +{ + unsigned char i, j; + unsigned int ret; + + for (i = 0; i < ARRAY_SIZE(interrupts); i++) { + unsigned int int_status_val = 0; + + int_status_val = upmu_get_reg_value(interrupts[i].address); + pr_err(PMICTAG "[PMIC_INT] addr[0x%x]=0x%x\n", interrupts[i].address, int_status_val); + + for (j = 0; j < PMIC_INT_WIDTH; j++) { + if ((int_status_val) & (1 << j)) { + PMICLOG("[PMIC_INT][%s]\n", interrupts[i].interrupts[j].name); + if (interrupts[i].interrupts[j].callback != NULL) { + interrupts[i].interrupts[j].callback(); + interrupts[i].interrupts[j].times++; + } + ret = pmic_config_interface(interrupts[i].address, 0x1, 0x1, j); + } + } + } +} + +int pmic_thread_kthread(void *x) +{ + unsigned int i; + unsigned int int_status_val = 0; + unsigned int pwrap_eint_status = 0; + struct sched_param param = {.sched_priority = 98 }; + + sched_setscheduler(current, SCHED_FIFO, ¶m); + set_current_state(TASK_INTERRUPTIBLE); + + PMICLOG("[PMIC_INT] enter\n"); + + pmic_enable_charger_detection_int(0); + + /* Run on a process content */ + while (1) { + mutex_lock(&pmic_mutex); + + pwrap_eint_status = pmic_wrap_eint_status(); + PMICLOG("[PMIC_INT] pwrap_eint_status=0x%x\n", pwrap_eint_status); + + pmic_int_handler(); + + pmic_wrap_eint_clr(0x0); + /*PMICLOG("[PMIC_INT] pmic_wrap_eint_clr(0x0);\n");*/ + + for (i = 0; i < ARRAY_SIZE(interrupts); i++) { + int_status_val = upmu_get_reg_value(interrupts[i].address); + PMICLOG("[PMIC_INT] after ,int_status_val[0x%x]=0x%x\n", + interrupts[i].address, int_status_val); + } + + + mdelay(1); + + mutex_unlock(&pmic_mutex); +#if !defined CONFIG_HAS_WAKELOCKS + __pm_relax(&pmicThread_lock); +#else + wake_unlock(&pmicThread_lock); +#endif + + set_current_state(TASK_INTERRUPTIBLE); +/* +#ifdef CONFIG_MTK_LEGACY + mt_eint_unmask(g_eint_pmic_num); +#else +*/ + if (g_pmic_irq != 0) + enable_irq(g_pmic_irq); +/*#endif*/ + schedule(); + } + + return 0; +} + + +MODULE_AUTHOR("Jimmy-YJ Huang"); +MODULE_DESCRIPTION("MT PMIC Interrupt Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/power/mt6755/pmic_irq.h b/drivers/misc/mediatek/power/mt6755/pmic_irq.h new file mode 100644 index 0000000000000000000000000000000000000000..fcb3c701063fba162f8fb18c5fb67e3a7b650547 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/pmic_irq.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __PMIC_IRQ_H +#define __PMIC_IRQ_H + +/* pmic irq extern variable */ +extern struct task_struct *pmic_thread_handle; +#if !defined CONFIG_HAS_WAKELOCKS +extern struct wakeup_source pmicThread_lock; +#else +extern struct wake_lock pmicThread_lock; +#endif +extern int interrupts_size; +extern struct pmic_interrupts interrupts[]; +/* pmic irq extern functions */ +extern void PMIC_EINT_SETTING(void); +extern int pmic_thread_kthread(void *x); + +#endif /*--PMIC_IRQ_H--*/ diff --git a/drivers/misc/mediatek/power/mt6755/upmu_common.c b/drivers/misc/mediatek/power/mt6755/upmu_common.c new file mode 100644 index 0000000000000000000000000000000000000000..ce6be146e8b1f19198058f97bfc704961092a6a5 --- /dev/null +++ b/drivers/misc/mediatek/power/mt6755/upmu_common.c @@ -0,0 +1,7408 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + +#include +#include +#include + +const PMU_FLAG_TABLE_ENTRY pmu_flags_table[] = { + {PMIC_THR_DET_DIS, MT6351_PMIC_THR_DET_DIS_ADDR, MT6351_PMIC_THR_DET_DIS_MASK, + MT6351_PMIC_THR_DET_DIS_SHIFT}, + {PMIC_THR_TEST, MT6351_PMIC_THR_TEST_ADDR, MT6351_PMIC_THR_TEST_MASK, + MT6351_PMIC_THR_TEST_SHIFT}, + {PMIC_THR_HWPDN_EN, MT6351_PMIC_THR_HWPDN_EN_ADDR, MT6351_PMIC_THR_HWPDN_EN_MASK, + MT6351_PMIC_THR_HWPDN_EN_SHIFT}, + {PMIC_STRUP_THERMAL_DEB_SEL, MT6351_PMIC_STRUP_THERMAL_DEB_SEL_ADDR, + MT6351_PMIC_STRUP_THERMAL_DEB_SEL_MASK, MT6351_PMIC_STRUP_THERMAL_DEB_SEL_SHIFT}, + {PMIC_USBDL, MT6351_PMIC_USBDL_ADDR, MT6351_PMIC_USBDL_MASK, + MT6351_PMIC_USBDL_SHIFT}, + {PMIC_PMU_THERMAL_DEB, MT6351_PMIC_PMU_THERMAL_DEB_ADDR, + MT6351_PMIC_PMU_THERMAL_DEB_MASK, MT6351_PMIC_PMU_THERMAL_DEB_SHIFT}, + {PMIC_PMU_THR_DEB, MT6351_PMIC_PMU_THR_DEB_ADDR, MT6351_PMIC_PMU_THR_DEB_MASK, + MT6351_PMIC_PMU_THR_DEB_SHIFT}, + {PMIC_PMU_THR_STATUS, MT6351_PMIC_PMU_THR_STATUS_ADDR, + MT6351_PMIC_PMU_THR_STATUS_MASK, MT6351_PMIC_PMU_THR_STATUS_SHIFT}, + {PMIC_STRUP_THER_DEB_RMAX, MT6351_PMIC_STRUP_THER_DEB_RMAX_ADDR, + MT6351_PMIC_STRUP_THER_DEB_RMAX_MASK, MT6351_PMIC_STRUP_THER_DEB_RMAX_SHIFT}, + {PMIC_STRUP_THER_DEB_FMAX, MT6351_PMIC_STRUP_THER_DEB_FMAX_ADDR, + MT6351_PMIC_STRUP_THER_DEB_FMAX_MASK, MT6351_PMIC_STRUP_THER_DEB_FMAX_SHIFT}, + {PMIC_DDUVLO_DEB_EN, MT6351_PMIC_DDUVLO_DEB_EN_ADDR, + MT6351_PMIC_DDUVLO_DEB_EN_MASK, MT6351_PMIC_DDUVLO_DEB_EN_SHIFT}, + {PMIC_PWRBB_DEB_EN, MT6351_PMIC_PWRBB_DEB_EN_ADDR, MT6351_PMIC_PWRBB_DEB_EN_MASK, + MT6351_PMIC_PWRBB_DEB_EN_SHIFT}, + {PMIC_STRUP_OSC_EN, MT6351_PMIC_STRUP_OSC_EN_ADDR, MT6351_PMIC_STRUP_OSC_EN_MASK, + MT6351_PMIC_STRUP_OSC_EN_SHIFT}, + {PMIC_STRUP_OSC_EN_SEL, MT6351_PMIC_STRUP_OSC_EN_SEL_ADDR, + MT6351_PMIC_STRUP_OSC_EN_SEL_MASK, MT6351_PMIC_STRUP_OSC_EN_SEL_SHIFT}, + {PMIC_STRUP_FT_CTRL, MT6351_PMIC_STRUP_FT_CTRL_ADDR, + MT6351_PMIC_STRUP_FT_CTRL_MASK, MT6351_PMIC_STRUP_FT_CTRL_SHIFT}, + {PMIC_STRUP_PWRON_FORCE, MT6351_PMIC_STRUP_PWRON_FORCE_ADDR, + MT6351_PMIC_STRUP_PWRON_FORCE_MASK, MT6351_PMIC_STRUP_PWRON_FORCE_SHIFT}, + {PMIC_BIAS_GEN_EN_FORCE, MT6351_PMIC_BIAS_GEN_EN_FORCE_ADDR, + MT6351_PMIC_BIAS_GEN_EN_FORCE_MASK, MT6351_PMIC_BIAS_GEN_EN_FORCE_SHIFT}, + {PMIC_STRUP_PWRON, MT6351_PMIC_STRUP_PWRON_ADDR, MT6351_PMIC_STRUP_PWRON_MASK, + MT6351_PMIC_STRUP_PWRON_SHIFT}, + {PMIC_STRUP_PWRON_SEL, MT6351_PMIC_STRUP_PWRON_SEL_ADDR, + MT6351_PMIC_STRUP_PWRON_SEL_MASK, MT6351_PMIC_STRUP_PWRON_SEL_SHIFT}, + {PMIC_BIAS_GEN_EN, MT6351_PMIC_BIAS_GEN_EN_ADDR, MT6351_PMIC_BIAS_GEN_EN_MASK, + MT6351_PMIC_BIAS_GEN_EN_SHIFT}, + {PMIC_BIAS_GEN_EN_SEL, MT6351_PMIC_BIAS_GEN_EN_SEL_ADDR, + MT6351_PMIC_BIAS_GEN_EN_SEL_MASK, MT6351_PMIC_BIAS_GEN_EN_SEL_SHIFT}, + {PMIC_RTC_XOSC32_ENB_SW, MT6351_PMIC_RTC_XOSC32_ENB_SW_ADDR, + MT6351_PMIC_RTC_XOSC32_ENB_SW_MASK, MT6351_PMIC_RTC_XOSC32_ENB_SW_SHIFT}, + {PMIC_RTC_XOSC32_ENB_SEL, MT6351_PMIC_RTC_XOSC32_ENB_SEL_ADDR, + MT6351_PMIC_RTC_XOSC32_ENB_SEL_MASK, MT6351_PMIC_RTC_XOSC32_ENB_SEL_SHIFT}, + {PMIC_STRUP_DIG_IO_PG_FORCE, MT6351_PMIC_STRUP_DIG_IO_PG_FORCE_ADDR, + MT6351_PMIC_STRUP_DIG_IO_PG_FORCE_MASK, MT6351_PMIC_STRUP_DIG_IO_PG_FORCE_SHIFT}, + {PMIC_RG_STRUP_VUSB33_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VUSB33_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VUSB33_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VUSB33_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VGPU_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VGPU_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VGPU_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VGPU_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VDRAM_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VDRAM_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VDRAM_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VDRAM_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_MASK, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN_MASK, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VA10_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VA10_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VA10_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VA10_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VEMC_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VEMC_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VEMC_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VEMC_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VS2_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VS2_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VS2_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VS2_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VMODEM_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VMODEM_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VMODEM_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VMODEM_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VMD1_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VMD1_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VMD1_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VMD1_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VCORE_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VCORE_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VCORE_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VCORE_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VA18_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VA18_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VA18_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VA18_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VS1_PG_H2L_EN, MT6351_PMIC_RG_STRUP_VS1_PG_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VS1_PG_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VS1_PG_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VTCXO24_PG_ENB, MT6351_PMIC_RG_STRUP_VTCXO24_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VTCXO24_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VTCXO24_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VUSB33_PG_ENB, MT6351_PMIC_RG_STRUP_VUSB33_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VUSB33_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VUSB33_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VGPU_PG_ENB, MT6351_PMIC_RG_STRUP_VGPU_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VGPU_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VGPU_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VDRAM_PG_ENB, MT6351_PMIC_RG_STRUP_VDRAM_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VDRAM_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VDRAM_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VSRAM_PROC_PG_ENB, MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_MASK, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VSRAM_MD_PG_ENB, MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VIO28_PG_ENB, MT6351_PMIC_RG_STRUP_VIO28_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VIO28_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VIO28_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VA10_PG_ENB, MT6351_PMIC_RG_STRUP_VA10_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VA10_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VA10_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VEMC_PG_ENB, MT6351_PMIC_RG_STRUP_VEMC_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VEMC_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VEMC_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VIO18_PG_ENB, MT6351_PMIC_RG_STRUP_VIO18_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VIO18_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VIO18_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VS2_PG_ENB, MT6351_PMIC_RG_STRUP_VS2_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VS2_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VS2_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VMODEM_PG_ENB, MT6351_PMIC_RG_STRUP_VMODEM_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VMODEM_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VMODEM_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VMD1_PG_ENB, MT6351_PMIC_RG_STRUP_VMD1_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VMD1_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VMD1_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VCORE_PG_ENB, MT6351_PMIC_RG_STRUP_VCORE_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VCORE_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VCORE_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VA18_PG_ENB, MT6351_PMIC_RG_STRUP_VA18_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VA18_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VA18_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VS1_PG_ENB, MT6351_PMIC_RG_STRUP_VS1_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VS1_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VS1_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VXO22_PG_ENB, MT6351_PMIC_RG_STRUP_VXO22_PG_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VXO22_PG_ENB_MASK, MT6351_PMIC_RG_STRUP_VXO22_PG_ENB_SHIFT}, + {PMIC_RG_STRUP_VGPU_OC_H2L_EN, MT6351_PMIC_RG_STRUP_VGPU_OC_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VGPU_OC_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VGPU_OC_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN, MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN_MASK, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VS2_OC_H2L_EN, MT6351_PMIC_RG_STRUP_VS2_OC_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VS2_OC_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VS2_OC_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VMODEM_OC_H2L_EN, MT6351_PMIC_RG_STRUP_VMODEM_OC_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VMODEM_OC_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VMODEM_OC_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VMD1_OC_H2L_EN, MT6351_PMIC_RG_STRUP_VMD1_OC_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VMD1_OC_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VMD1_OC_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VCORE_OC_H2L_EN, MT6351_PMIC_RG_STRUP_VCORE_OC_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VCORE_OC_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VCORE_OC_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VS1_OC_H2L_EN, MT6351_PMIC_RG_STRUP_VS1_OC_H2L_EN_ADDR, + MT6351_PMIC_RG_STRUP_VS1_OC_H2L_EN_MASK, MT6351_PMIC_RG_STRUP_VS1_OC_H2L_EN_SHIFT}, + {PMIC_RG_STRUP_VGPU_OC_ENB, MT6351_PMIC_RG_STRUP_VGPU_OC_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VGPU_OC_ENB_MASK, MT6351_PMIC_RG_STRUP_VGPU_OC_ENB_SHIFT}, + {PMIC_RG_STRUP_VSRAM_MD_OC_ENB, MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_ENB_MASK, MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_ENB_SHIFT}, + {PMIC_RG_STRUP_VS2_OC_ENB, MT6351_PMIC_RG_STRUP_VS2_OC_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VS2_OC_ENB_MASK, MT6351_PMIC_RG_STRUP_VS2_OC_ENB_SHIFT}, + {PMIC_RG_STRUP_VMODEM_OC_ENB, MT6351_PMIC_RG_STRUP_VMODEM_OC_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VMODEM_OC_ENB_MASK, MT6351_PMIC_RG_STRUP_VMODEM_OC_ENB_SHIFT}, + {PMIC_RG_STRUP_VMD1_OC_ENB, MT6351_PMIC_RG_STRUP_VMD1_OC_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VMD1_OC_ENB_MASK, MT6351_PMIC_RG_STRUP_VMD1_OC_ENB_SHIFT}, + {PMIC_RG_STRUP_VCORE_OC_ENB, MT6351_PMIC_RG_STRUP_VCORE_OC_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VCORE_OC_ENB_MASK, MT6351_PMIC_RG_STRUP_VCORE_OC_ENB_SHIFT}, + {PMIC_RG_STRUP_VS1_OC_ENB, MT6351_PMIC_RG_STRUP_VS1_OC_ENB_ADDR, + MT6351_PMIC_RG_STRUP_VS1_OC_ENB_MASK, MT6351_PMIC_RG_STRUP_VS1_OC_ENB_SHIFT}, + {PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VDRAM_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VXO22_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VGPU_OC_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VSRAM_MD_OC_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VS2_OC_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VS2_OC_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VS2_OC_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VS2_OC_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VMODEM_OC_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VMD1_OC_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VCORE_OC_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VS1_OC_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VS1_OC_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VS1_OC_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VS1_OC_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VTCXO24_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VUSB33_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VGPU_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VSRAM_DRAM_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VSRAM_PROC_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VSRAM_MD_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VIO28_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VA10_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VA10_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VA10_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VA10_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VEMC_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VIO18_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VS2_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VS2_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VS2_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VS2_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS, + MT6351_PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VMODEM_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VMD1_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VCORE_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VA18_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VA18_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VA18_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VA18_PG_DEB_BYPASS_SHIFT}, + {PMIC_RG_STRUP_VS1_PG_DEB_BYPASS, MT6351_PMIC_RG_STRUP_VS1_PG_DEB_BYPASS_ADDR, + MT6351_PMIC_RG_STRUP_VS1_PG_DEB_BYPASS_MASK, + MT6351_PMIC_RG_STRUP_VS1_PG_DEB_BYPASS_SHIFT}, + {PMIC_CLR_JUST_RST, MT6351_PMIC_CLR_JUST_RST_ADDR, MT6351_PMIC_CLR_JUST_RST_MASK, + MT6351_PMIC_CLR_JUST_RST_SHIFT}, + {PMIC_UVLO_L2H_DEB_EN, MT6351_PMIC_UVLO_L2H_DEB_EN_ADDR, + MT6351_PMIC_UVLO_L2H_DEB_EN_MASK, MT6351_PMIC_UVLO_L2H_DEB_EN_SHIFT}, + {PMIC_JUST_PWRKEY_RST, MT6351_PMIC_JUST_PWRKEY_RST_ADDR, + MT6351_PMIC_JUST_PWRKEY_RST_MASK, MT6351_PMIC_JUST_PWRKEY_RST_SHIFT}, + {PMIC_DA_QI_OSC_EN, MT6351_PMIC_DA_QI_OSC_EN_ADDR, MT6351_PMIC_DA_QI_OSC_EN_MASK, + MT6351_PMIC_DA_QI_OSC_EN_SHIFT}, + {PMIC_STRUP_EXT_PMIC_EN, MT6351_PMIC_STRUP_EXT_PMIC_EN_ADDR, + MT6351_PMIC_STRUP_EXT_PMIC_EN_MASK, MT6351_PMIC_STRUP_EXT_PMIC_EN_SHIFT}, + {PMIC_STRUP_EXT_PMIC_SEL, MT6351_PMIC_STRUP_EXT_PMIC_SEL_ADDR, + MT6351_PMIC_STRUP_EXT_PMIC_SEL_MASK, MT6351_PMIC_STRUP_EXT_PMIC_SEL_SHIFT}, + {PMIC_STRUP_CON8_RSV0, MT6351_PMIC_STRUP_CON8_RSV0_ADDR, + MT6351_PMIC_STRUP_CON8_RSV0_MASK, MT6351_PMIC_STRUP_CON8_RSV0_SHIFT}, + {PMIC_DA_QI_EXT_PMIC_EN, MT6351_PMIC_DA_QI_EXT_PMIC_EN_ADDR, + MT6351_PMIC_DA_QI_EXT_PMIC_EN_MASK, MT6351_PMIC_DA_QI_EXT_PMIC_EN_SHIFT}, + {PMIC_STRUP_AUXADC_START_SW, MT6351_PMIC_STRUP_AUXADC_START_SW_ADDR, + MT6351_PMIC_STRUP_AUXADC_START_SW_MASK, MT6351_PMIC_STRUP_AUXADC_START_SW_SHIFT}, + {PMIC_STRUP_AUXADC_RSTB_SW, MT6351_PMIC_STRUP_AUXADC_RSTB_SW_ADDR, + MT6351_PMIC_STRUP_AUXADC_RSTB_SW_MASK, MT6351_PMIC_STRUP_AUXADC_RSTB_SW_SHIFT}, + {PMIC_STRUP_AUXADC_START_SEL, MT6351_PMIC_STRUP_AUXADC_START_SEL_ADDR, + MT6351_PMIC_STRUP_AUXADC_START_SEL_MASK, MT6351_PMIC_STRUP_AUXADC_START_SEL_SHIFT}, + {PMIC_STRUP_AUXADC_RSTB_SEL, MT6351_PMIC_STRUP_AUXADC_RSTB_SEL_ADDR, + MT6351_PMIC_STRUP_AUXADC_RSTB_SEL_MASK, MT6351_PMIC_STRUP_AUXADC_RSTB_SEL_SHIFT}, + {PMIC_STRUP_PWROFF_SEQ_EN, MT6351_PMIC_STRUP_PWROFF_SEQ_EN_ADDR, + MT6351_PMIC_STRUP_PWROFF_SEQ_EN_MASK, MT6351_PMIC_STRUP_PWROFF_SEQ_EN_SHIFT}, + {PMIC_STRUP_PWROFF_PREOFF_EN, MT6351_PMIC_STRUP_PWROFF_PREOFF_EN_ADDR, + MT6351_PMIC_STRUP_PWROFF_PREOFF_EN_MASK, MT6351_PMIC_STRUP_PWROFF_PREOFF_EN_SHIFT}, + {PMIC_STRUP_PP_EN, MT6351_PMIC_STRUP_PP_EN_ADDR, MT6351_PMIC_STRUP_PP_EN_MASK, + MT6351_PMIC_STRUP_PP_EN_SHIFT}, + {PMIC_STRUP_PP_EN_SEL, MT6351_PMIC_STRUP_PP_EN_SEL_ADDR, + MT6351_PMIC_STRUP_PP_EN_SEL_MASK, MT6351_PMIC_STRUP_PP_EN_SEL_SHIFT}, + {PMIC_STRUP_DIG0_RSV0, MT6351_PMIC_STRUP_DIG0_RSV0_ADDR, + MT6351_PMIC_STRUP_DIG0_RSV0_MASK, MT6351_PMIC_STRUP_DIG0_RSV0_SHIFT}, + {PMIC_STRUP_DIG1_RSV0, MT6351_PMIC_STRUP_DIG1_RSV0_ADDR, + MT6351_PMIC_STRUP_DIG1_RSV0_MASK, MT6351_PMIC_STRUP_DIG1_RSV0_SHIFT}, + {PMIC_RG_RSV_SWREG, MT6351_PMIC_RG_RSV_SWREG_ADDR, MT6351_PMIC_RG_RSV_SWREG_MASK, + MT6351_PMIC_RG_RSV_SWREG_SHIFT}, + {PMIC_STRUP_PP_EN_PWROFF_CNT, MT6351_PMIC_STRUP_PP_EN_PWROFF_CNT_ADDR, + MT6351_PMIC_STRUP_PP_EN_PWROFF_CNT_MASK, MT6351_PMIC_STRUP_PP_EN_PWROFF_CNT_SHIFT}, + {PMIC_STRUP_UVLO_U1U2_SEL, MT6351_PMIC_STRUP_UVLO_U1U2_SEL_ADDR, + MT6351_PMIC_STRUP_UVLO_U1U2_SEL_MASK, MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SHIFT}, + {PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL, MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL_ADDR, + MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL_MASK, + MT6351_PMIC_STRUP_UVLO_U1U2_SEL_SWCTRL_SHIFT}, + {PMIC_STRUP_AUXADC_RPCNT_MAX, MT6351_PMIC_STRUP_AUXADC_RPCNT_MAX_ADDR, + MT6351_PMIC_STRUP_AUXADC_RPCNT_MAX_MASK, MT6351_PMIC_STRUP_AUXADC_RPCNT_MAX_SHIFT}, + {PMIC_RG_STRUP_THR_OVER_110_CLR, MT6351_PMIC_RG_STRUP_THR_OVER_110_CLR_ADDR, + MT6351_PMIC_RG_STRUP_THR_OVER_110_CLR_MASK, MT6351_PMIC_RG_STRUP_THR_OVER_110_CLR_SHIFT}, + {PMIC_RG_STRUP_THR_110_CLR, MT6351_PMIC_RG_STRUP_THR_110_CLR_ADDR, + MT6351_PMIC_RG_STRUP_THR_110_CLR_MASK, MT6351_PMIC_RG_STRUP_THR_110_CLR_SHIFT}, + {PMIC_RG_STRUP_THR_125_CLR, MT6351_PMIC_RG_STRUP_THR_125_CLR_ADDR, + MT6351_PMIC_RG_STRUP_THR_125_CLR_MASK, MT6351_PMIC_RG_STRUP_THR_125_CLR_SHIFT}, + {PMIC_RG_STRUP_THR_CLR, MT6351_PMIC_RG_STRUP_THR_CLR_ADDR, + MT6351_PMIC_RG_STRUP_THR_CLR_MASK, MT6351_PMIC_RG_STRUP_THR_CLR_SHIFT}, + {PMIC_RG_STRUP_THR_OVER_110_IRQ_EN, MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_EN_ADDR, + MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_EN_MASK, + MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_EN_SHIFT}, + {PMIC_RG_STRUP_THR_110_IRQ_EN, MT6351_PMIC_RG_STRUP_THR_110_IRQ_EN_ADDR, + MT6351_PMIC_RG_STRUP_THR_110_IRQ_EN_MASK, MT6351_PMIC_RG_STRUP_THR_110_IRQ_EN_SHIFT}, + {PMIC_RG_STRUP_THR_125_IRQ_EN, MT6351_PMIC_RG_STRUP_THR_125_IRQ_EN_ADDR, + MT6351_PMIC_RG_STRUP_THR_125_IRQ_EN_MASK, MT6351_PMIC_RG_STRUP_THR_125_IRQ_EN_SHIFT}, + {PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS, + MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS_ADDR, + MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS_MASK, + MT6351_PMIC_RG_STRUP_THR_OVER_110_IRQ_STATUS_SHIFT}, + {PMIC_RG_STRUP_THR_110_IRQ_STATUS, MT6351_PMIC_RG_STRUP_THR_110_IRQ_STATUS_ADDR, + MT6351_PMIC_RG_STRUP_THR_110_IRQ_STATUS_MASK, + MT6351_PMIC_RG_STRUP_THR_110_IRQ_STATUS_SHIFT}, + {PMIC_RG_STRUP_THR_125_IRQ_STATUS, MT6351_PMIC_RG_STRUP_THR_125_IRQ_STATUS_ADDR, + MT6351_PMIC_RG_STRUP_THR_125_IRQ_STATUS_MASK, + MT6351_PMIC_RG_STRUP_THR_125_IRQ_STATUS_SHIFT}, + {PMIC_STRUP_PG_STATUS_CLR, MT6351_PMIC_STRUP_PG_STATUS_CLR_ADDR, + MT6351_PMIC_STRUP_PG_STATUS_CLR_MASK, MT6351_PMIC_STRUP_PG_STATUS_CLR_SHIFT}, + {PMIC_RG_STRUP_LONG_PRESS_EXT_SEL, MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_ADDR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_MASK, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_SEL_SHIFT}, + {PMIC_RG_STRUP_LONG_PRESS_EXT_TD, MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_TD_ADDR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_TD_MASK, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_TD_SHIFT}, + {PMIC_RG_STRUP_LONG_PRESS_EXT_EN, MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_EN_ADDR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_EN_MASK, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_EN_SHIFT}, + {PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_ADDR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_MASK, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_CHR_CTRL_SHIFT}, + {PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL_ADDR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL_MASK, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRKY_CTRL_SHIFT}, + {PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_ADDR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_MASK, + MT6351_PMIC_RG_STRUP_LONG_PRESS_EXT_PWRBB_CTRL_SHIFT}, + {PMIC_RG_STRUP_ENVTEM, MT6351_PMIC_RG_STRUP_ENVTEM_ADDR, + MT6351_PMIC_RG_STRUP_ENVTEM_MASK, MT6351_PMIC_RG_STRUP_ENVTEM_SHIFT}, + {PMIC_RG_STRUP_ENVTEM_CTRL, MT6351_PMIC_RG_STRUP_ENVTEM_CTRL_ADDR, + MT6351_PMIC_RG_STRUP_ENVTEM_CTRL_MASK, MT6351_PMIC_RG_STRUP_ENVTEM_CTRL_SHIFT}, + {PMIC_RG_STRUP_PWRKEY_COUNT_RESET, MT6351_PMIC_RG_STRUP_PWRKEY_COUNT_RESET_ADDR, + MT6351_PMIC_RG_STRUP_PWRKEY_COUNT_RESET_MASK, + MT6351_PMIC_RG_STRUP_PWRKEY_COUNT_RESET_SHIFT}, + {PMIC_RGS_ANA_CHIP_ID, MT6351_PMIC_RGS_ANA_CHIP_ID_ADDR, + MT6351_PMIC_RGS_ANA_CHIP_ID_MASK, MT6351_PMIC_RGS_ANA_CHIP_ID_SHIFT}, + {PMIC_RG_PP_EN_DRVSEL, MT6351_PMIC_RG_PP_EN_DRVSEL_ADDR, + MT6351_PMIC_RG_PP_EN_DRVSEL_MASK, MT6351_PMIC_RG_PP_EN_DRVSEL_SHIFT}, + {PMIC_RG_FCHR_PU_EN, MT6351_PMIC_RG_FCHR_PU_EN_ADDR, + MT6351_PMIC_RG_FCHR_PU_EN_MASK, MT6351_PMIC_RG_FCHR_PU_EN_SHIFT}, + {PMIC_RG_PMU_RSV, MT6351_PMIC_RG_PMU_RSV_ADDR, MT6351_PMIC_RG_PMU_RSV_MASK, + MT6351_PMIC_RG_PMU_RSV_SHIFT}, + {PMIC_RG_FCHR_KEYDET_EN, MT6351_PMIC_RG_FCHR_KEYDET_EN_ADDR, + MT6351_PMIC_RG_FCHR_KEYDET_EN_MASK, MT6351_PMIC_RG_FCHR_KEYDET_EN_SHIFT}, + {PMIC_RG_EN_DRVSEL, MT6351_PMIC_RG_EN_DRVSEL_ADDR, MT6351_PMIC_RG_EN_DRVSEL_MASK, + MT6351_PMIC_RG_EN_DRVSEL_SHIFT}, + {PMIC_RG_RST_DRVSEL, MT6351_PMIC_RG_RST_DRVSEL_ADDR, + MT6351_PMIC_RG_RST_DRVSEL_MASK, MT6351_PMIC_RG_RST_DRVSEL_SHIFT}, + {PMIC_RG_STRUP_IREF_TRIM, MT6351_PMIC_RG_STRUP_IREF_TRIM_ADDR, + MT6351_PMIC_RG_STRUP_IREF_TRIM_MASK, MT6351_PMIC_RG_STRUP_IREF_TRIM_SHIFT}, + {PMIC_RG_VREF_BG, MT6351_PMIC_RG_VREF_BG_ADDR, MT6351_PMIC_RG_VREF_BG_MASK, + MT6351_PMIC_RG_VREF_BG_SHIFT}, + {PMIC_RG_THR_TMODE, MT6351_PMIC_RG_THR_TMODE_ADDR, MT6351_PMIC_RG_THR_TMODE_MASK, + MT6351_PMIC_RG_THR_TMODE_SHIFT}, + {PMIC_RG_STRUP_THR_SEL, MT6351_PMIC_RG_STRUP_THR_SEL_ADDR, + MT6351_PMIC_RG_STRUP_THR_SEL_MASK, MT6351_PMIC_RG_STRUP_THR_SEL_SHIFT}, + {PMIC_RG_THRDET_SEL, MT6351_PMIC_RG_THRDET_SEL_ADDR, + MT6351_PMIC_RG_THRDET_SEL_MASK, MT6351_PMIC_RG_THRDET_SEL_SHIFT}, + {PMIC_HWCID, MT6351_PMIC_HWCID_ADDR, MT6351_PMIC_HWCID_MASK, + MT6351_PMIC_HWCID_SHIFT}, + {PMIC_SWCID, MT6351_PMIC_SWCID_ADDR, MT6351_PMIC_SWCID_MASK, + MT6351_PMIC_SWCID_SHIFT}, + {PMIC_RG_SRCLKEN_IN0_EN, MT6351_PMIC_RG_SRCLKEN_IN0_EN_ADDR, + MT6351_PMIC_RG_SRCLKEN_IN0_EN_MASK, MT6351_PMIC_RG_SRCLKEN_IN0_EN_SHIFT}, + {PMIC_RG_SRCLKEN_IN1_EN, MT6351_PMIC_RG_SRCLKEN_IN1_EN_ADDR, + MT6351_PMIC_RG_SRCLKEN_IN1_EN_MASK, MT6351_PMIC_RG_SRCLKEN_IN1_EN_SHIFT}, + {PMIC_RG_OSC_SEL, MT6351_PMIC_RG_OSC_SEL_ADDR, MT6351_PMIC_RG_OSC_SEL_MASK, + MT6351_PMIC_RG_OSC_SEL_SHIFT}, + {PMIC_RG_SRCLKEN_IN2_EN, MT6351_PMIC_RG_SRCLKEN_IN2_EN_ADDR, + MT6351_PMIC_RG_SRCLKEN_IN2_EN_MASK, MT6351_PMIC_RG_SRCLKEN_IN2_EN_SHIFT}, + {PMIC_RG_SRCLKEN_IN0_HW_MODE, MT6351_PMIC_RG_SRCLKEN_IN0_HW_MODE_ADDR, + MT6351_PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK, MT6351_PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT}, + {PMIC_RG_SRCLKEN_IN1_HW_MODE, MT6351_PMIC_RG_SRCLKEN_IN1_HW_MODE_ADDR, + MT6351_PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK, MT6351_PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT}, + {PMIC_RG_OSC_SEL_HW_MODE, MT6351_PMIC_RG_OSC_SEL_HW_MODE_ADDR, + MT6351_PMIC_RG_OSC_SEL_HW_MODE_MASK, MT6351_PMIC_RG_OSC_SEL_HW_MODE_SHIFT}, + {PMIC_RG_SRCLKEN_IN_SYNC_EN, MT6351_PMIC_RG_SRCLKEN_IN_SYNC_EN_ADDR, + MT6351_PMIC_RG_SRCLKEN_IN_SYNC_EN_MASK, MT6351_PMIC_RG_SRCLKEN_IN_SYNC_EN_SHIFT}, + {PMIC_RG_OSC_EN_AUTO_OFF, MT6351_PMIC_RG_OSC_EN_AUTO_OFF_ADDR, + MT6351_PMIC_RG_OSC_EN_AUTO_OFF_MASK, MT6351_PMIC_RG_OSC_EN_AUTO_OFF_SHIFT}, + {PMIC_TEST_OUT, MT6351_PMIC_TEST_OUT_ADDR, MT6351_PMIC_TEST_OUT_MASK, + MT6351_PMIC_TEST_OUT_SHIFT}, + {PMIC_RG_MON_FLAG_SEL, MT6351_PMIC_RG_MON_FLAG_SEL_ADDR, + MT6351_PMIC_RG_MON_FLAG_SEL_MASK, MT6351_PMIC_RG_MON_FLAG_SEL_SHIFT}, + {PMIC_RG_MON_GRP_SEL, MT6351_PMIC_RG_MON_GRP_SEL_ADDR, + MT6351_PMIC_RG_MON_GRP_SEL_MASK, MT6351_PMIC_RG_MON_GRP_SEL_SHIFT}, + {PMIC_RG_NANDTREE_MODE, MT6351_PMIC_RG_NANDTREE_MODE_ADDR, + MT6351_PMIC_RG_NANDTREE_MODE_MASK, MT6351_PMIC_RG_NANDTREE_MODE_SHIFT}, + {PMIC_RG_TEST_AUXADC, MT6351_PMIC_RG_TEST_AUXADC_ADDR, + MT6351_PMIC_RG_TEST_AUXADC_MASK, MT6351_PMIC_RG_TEST_AUXADC_SHIFT}, + {PMIC_RG_EFUSE_MODE, MT6351_PMIC_RG_EFUSE_MODE_ADDR, + MT6351_PMIC_RG_EFUSE_MODE_MASK, MT6351_PMIC_RG_EFUSE_MODE_SHIFT}, + {PMIC_RG_TEST_STRUP, MT6351_PMIC_RG_TEST_STRUP_ADDR, + MT6351_PMIC_RG_TEST_STRUP_MASK, MT6351_PMIC_RG_TEST_STRUP_SHIFT}, + {PMIC_TESTMODE_SW, MT6351_PMIC_TESTMODE_SW_ADDR, MT6351_PMIC_TESTMODE_SW_MASK, + MT6351_PMIC_TESTMODE_SW_SHIFT}, + {PMIC_EN_STATUS_VLDO28, MT6351_PMIC_EN_STATUS_VLDO28_ADDR, + MT6351_PMIC_EN_STATUS_VLDO28_MASK, MT6351_PMIC_EN_STATUS_VLDO28_SHIFT}, + {PMIC_EN_STATUS_VIO28, MT6351_PMIC_EN_STATUS_VIO28_ADDR, + MT6351_PMIC_EN_STATUS_VIO28_MASK, MT6351_PMIC_EN_STATUS_VIO28_SHIFT}, + {PMIC_EN_STATUS_VMCH, MT6351_PMIC_EN_STATUS_VMCH_ADDR, + MT6351_PMIC_EN_STATUS_VMCH_MASK, MT6351_PMIC_EN_STATUS_VMCH_SHIFT}, + {PMIC_EN_STATUS_VMC, MT6351_PMIC_EN_STATUS_VMC_ADDR, + MT6351_PMIC_EN_STATUS_VMC_MASK, MT6351_PMIC_EN_STATUS_VMC_SHIFT}, + {PMIC_EN_STATUS_VEMC, MT6351_PMIC_EN_STATUS_VEMC_ADDR, + MT6351_PMIC_EN_STATUS_VEMC_MASK, MT6351_PMIC_EN_STATUS_VEMC_SHIFT}, + {PMIC_EN_STATUS_VSIM2, MT6351_PMIC_EN_STATUS_VSIM2_ADDR, + MT6351_PMIC_EN_STATUS_VSIM2_MASK, MT6351_PMIC_EN_STATUS_VSIM2_SHIFT}, + {PMIC_EN_STATUS_VSIM1, MT6351_PMIC_EN_STATUS_VSIM1_ADDR, + MT6351_PMIC_EN_STATUS_VSIM1_MASK, MT6351_PMIC_EN_STATUS_VSIM1_SHIFT}, + {PMIC_EN_STATUS_VEFUSE, MT6351_PMIC_EN_STATUS_VEFUSE_ADDR, + MT6351_PMIC_EN_STATUS_VEFUSE_MASK, MT6351_PMIC_EN_STATUS_VEFUSE_SHIFT}, + {PMIC_EN_STATUS_VUSB33, MT6351_PMIC_EN_STATUS_VUSB33_ADDR, + MT6351_PMIC_EN_STATUS_VUSB33_MASK, MT6351_PMIC_EN_STATUS_VUSB33_SHIFT}, + {PMIC_EN_STATUS_VCN33, MT6351_PMIC_EN_STATUS_VCN33_ADDR, + MT6351_PMIC_EN_STATUS_VCN33_MASK, MT6351_PMIC_EN_STATUS_VCN33_SHIFT}, + {PMIC_EN_STATUS_VCAMA, MT6351_PMIC_EN_STATUS_VCAMA_ADDR, + MT6351_PMIC_EN_STATUS_VCAMA_MASK, MT6351_PMIC_EN_STATUS_VCAMA_SHIFT}, + {PMIC_EN_STATUS_VCN28, MT6351_PMIC_EN_STATUS_VCN28_ADDR, + MT6351_PMIC_EN_STATUS_VCN28_MASK, MT6351_PMIC_EN_STATUS_VCN28_SHIFT}, + {PMIC_EN_STATUS_VTCXO24, MT6351_PMIC_EN_STATUS_VTCXO24_ADDR, + MT6351_PMIC_EN_STATUS_VTCXO24_MASK, MT6351_PMIC_EN_STATUS_VTCXO24_SHIFT}, + {PMIC_EN_STATUS_VTCXO28, MT6351_PMIC_EN_STATUS_VTCXO28_ADDR, + MT6351_PMIC_EN_STATUS_VTCXO28_MASK, MT6351_PMIC_EN_STATUS_VTCXO28_SHIFT}, + {PMIC_EN_STATUS_VA18, MT6351_PMIC_EN_STATUS_VA18_ADDR, + MT6351_PMIC_EN_STATUS_VA18_MASK, MT6351_PMIC_EN_STATUS_VA18_SHIFT}, + {PMIC_EN_STATUS_VRTC, MT6351_PMIC_EN_STATUS_VRTC_ADDR, + MT6351_PMIC_EN_STATUS_VRTC_MASK, MT6351_PMIC_EN_STATUS_VRTC_SHIFT}, + {PMIC_EN_STATUS_VBIF28, MT6351_PMIC_EN_STATUS_VBIF28_ADDR, + MT6351_PMIC_EN_STATUS_VBIF28_MASK, MT6351_PMIC_EN_STATUS_VBIF28_SHIFT}, + {PMIC_EN_STATUS_VGP3, MT6351_PMIC_EN_STATUS_VGP3_ADDR, + MT6351_PMIC_EN_STATUS_VGP3_MASK, MT6351_PMIC_EN_STATUS_VGP3_SHIFT}, + {PMIC_EN_STATUS_VMIPI, MT6351_PMIC_EN_STATUS_VMIPI_ADDR, + MT6351_PMIC_EN_STATUS_VMIPI_MASK, MT6351_PMIC_EN_STATUS_VMIPI_SHIFT}, + {PMIC_EN_STATUS_VDRAM, MT6351_PMIC_EN_STATUS_VDRAM_ADDR, + MT6351_PMIC_EN_STATUS_VDRAM_MASK, MT6351_PMIC_EN_STATUS_VDRAM_SHIFT}, + {PMIC_EN_STATUS_VA10, MT6351_PMIC_EN_STATUS_VA10_ADDR, + MT6351_PMIC_EN_STATUS_VA10_MASK, MT6351_PMIC_EN_STATUS_VA10_SHIFT}, + {PMIC_EN_STATUS_VRF12, MT6351_PMIC_EN_STATUS_VRF12_ADDR, + MT6351_PMIC_EN_STATUS_VRF12_MASK, MT6351_PMIC_EN_STATUS_VRF12_SHIFT}, + {PMIC_EN_STATUS_VXO22, MT6351_PMIC_EN_STATUS_VXO22_ADDR, + MT6351_PMIC_EN_STATUS_VXO22_MASK, MT6351_PMIC_EN_STATUS_VXO22_SHIFT}, + {PMIC_EN_STATUS_VSRAM_PROC, MT6351_PMIC_EN_STATUS_VSRAM_PROC_ADDR, + MT6351_PMIC_EN_STATUS_VSRAM_PROC_MASK, MT6351_PMIC_EN_STATUS_VSRAM_PROC_SHIFT}, + {PMIC_EN_STATUS_VCAMIO, MT6351_PMIC_EN_STATUS_VCAMIO_ADDR, + MT6351_PMIC_EN_STATUS_VCAMIO_MASK, MT6351_PMIC_EN_STATUS_VCAMIO_SHIFT}, + {PMIC_EN_STATUS_VCN18, MT6351_PMIC_EN_STATUS_VCN18_ADDR, + MT6351_PMIC_EN_STATUS_VCN18_MASK, MT6351_PMIC_EN_STATUS_VCN18_SHIFT}, + {PMIC_EN_STATUS_VIO18, MT6351_PMIC_EN_STATUS_VIO18_ADDR, + MT6351_PMIC_EN_STATUS_VIO18_MASK, MT6351_PMIC_EN_STATUS_VIO18_SHIFT}, + {PMIC_EN_STATUS_VRF18, MT6351_PMIC_EN_STATUS_VRF18_ADDR, + MT6351_PMIC_EN_STATUS_VRF18_MASK, MT6351_PMIC_EN_STATUS_VRF18_SHIFT}, + {PMIC_EN_STATUS_VCAMD, MT6351_PMIC_EN_STATUS_VCAMD_ADDR, + MT6351_PMIC_EN_STATUS_VCAMD_MASK, MT6351_PMIC_EN_STATUS_VCAMD_SHIFT}, + {PMIC_EN_STATUS_VIBR, MT6351_PMIC_EN_STATUS_VIBR_ADDR, + MT6351_PMIC_EN_STATUS_VIBR_MASK, MT6351_PMIC_EN_STATUS_VIBR_SHIFT}, + {PMIC_OC_STATUS_VIBR, MT6351_PMIC_OC_STATUS_VIBR_ADDR, + MT6351_PMIC_OC_STATUS_VIBR_MASK, MT6351_PMIC_OC_STATUS_VIBR_SHIFT}, + {PMIC_OC_STATUS_VLDO28, MT6351_PMIC_OC_STATUS_VLDO28_ADDR, + MT6351_PMIC_OC_STATUS_VLDO28_MASK, MT6351_PMIC_OC_STATUS_VLDO28_SHIFT}, + {PMIC_OC_STATUS_VIO28, MT6351_PMIC_OC_STATUS_VIO28_ADDR, + MT6351_PMIC_OC_STATUS_VIO28_MASK, MT6351_PMIC_OC_STATUS_VIO28_SHIFT}, + {PMIC_OC_STATUS_VMC, MT6351_PMIC_OC_STATUS_VMC_ADDR, + MT6351_PMIC_OC_STATUS_VMC_MASK, MT6351_PMIC_OC_STATUS_VMC_SHIFT}, + {PMIC_OC_STATUS_VMCH, MT6351_PMIC_OC_STATUS_VMCH_ADDR, + MT6351_PMIC_OC_STATUS_VMCH_MASK, MT6351_PMIC_OC_STATUS_VMCH_SHIFT}, + {PMIC_OC_STATUS_VEMC, MT6351_PMIC_OC_STATUS_VEMC_ADDR, + MT6351_PMIC_OC_STATUS_VEMC_MASK, MT6351_PMIC_OC_STATUS_VEMC_SHIFT}, + {PMIC_OC_STATUS_VSIM2, MT6351_PMIC_OC_STATUS_VSIM2_ADDR, + MT6351_PMIC_OC_STATUS_VSIM2_MASK, MT6351_PMIC_OC_STATUS_VSIM2_SHIFT}, + {PMIC_OC_STATUS_VSIM1, MT6351_PMIC_OC_STATUS_VSIM1_ADDR, + MT6351_PMIC_OC_STATUS_VSIM1_MASK, MT6351_PMIC_OC_STATUS_VSIM1_SHIFT}, + {PMIC_OC_STATUS_VEFUSE, MT6351_PMIC_OC_STATUS_VEFUSE_ADDR, + MT6351_PMIC_OC_STATUS_VEFUSE_MASK, MT6351_PMIC_OC_STATUS_VEFUSE_SHIFT}, + {PMIC_OC_STATUS_VUSB33, MT6351_PMIC_OC_STATUS_VUSB33_ADDR, + MT6351_PMIC_OC_STATUS_VUSB33_MASK, MT6351_PMIC_OC_STATUS_VUSB33_SHIFT}, + {PMIC_OC_STATUS_VCN33, MT6351_PMIC_OC_STATUS_VCN33_ADDR, + MT6351_PMIC_OC_STATUS_VCN33_MASK, MT6351_PMIC_OC_STATUS_VCN33_SHIFT}, + {PMIC_OC_STATUS_VCAMA, MT6351_PMIC_OC_STATUS_VCAMA_ADDR, + MT6351_PMIC_OC_STATUS_VCAMA_MASK, MT6351_PMIC_OC_STATUS_VCAMA_SHIFT}, + {PMIC_OC_STATUS_VCN28, MT6351_PMIC_OC_STATUS_VCN28_ADDR, + MT6351_PMIC_OC_STATUS_VCN28_MASK, MT6351_PMIC_OC_STATUS_VCN28_SHIFT}, + {PMIC_OC_STATUS_VTCXO24, MT6351_PMIC_OC_STATUS_VTCXO24_ADDR, + MT6351_PMIC_OC_STATUS_VTCXO24_MASK, MT6351_PMIC_OC_STATUS_VTCXO24_SHIFT}, + {PMIC_OC_STATUS_VTCXO28, MT6351_PMIC_OC_STATUS_VTCXO28_ADDR, + MT6351_PMIC_OC_STATUS_VTCXO28_MASK, MT6351_PMIC_OC_STATUS_VTCXO28_SHIFT}, + {PMIC_OC_STATUS_VA18, MT6351_PMIC_OC_STATUS_VA18_ADDR, + MT6351_PMIC_OC_STATUS_VA18_MASK, MT6351_PMIC_OC_STATUS_VA18_SHIFT}, + {PMIC_OC_STATUS_VBIF28, MT6351_PMIC_OC_STATUS_VBIF28_ADDR, + MT6351_PMIC_OC_STATUS_VBIF28_MASK, MT6351_PMIC_OC_STATUS_VBIF28_SHIFT}, + {PMIC_OC_STATUS_VGP3, MT6351_PMIC_OC_STATUS_VGP3_ADDR, + MT6351_PMIC_OC_STATUS_VGP3_MASK, MT6351_PMIC_OC_STATUS_VGP3_SHIFT}, + {PMIC_OC_STATUS_VMIPI, MT6351_PMIC_OC_STATUS_VMIPI_ADDR, + MT6351_PMIC_OC_STATUS_VMIPI_MASK, MT6351_PMIC_OC_STATUS_VMIPI_SHIFT}, + {PMIC_OC_STATUS_VDRAM, MT6351_PMIC_OC_STATUS_VDRAM_ADDR, + MT6351_PMIC_OC_STATUS_VDRAM_MASK, MT6351_PMIC_OC_STATUS_VDRAM_SHIFT}, + {PMIC_OC_STATUS_VA10, MT6351_PMIC_OC_STATUS_VA10_ADDR, + MT6351_PMIC_OC_STATUS_VA10_MASK, MT6351_PMIC_OC_STATUS_VA10_SHIFT}, + {PMIC_OC_STATUS_VRF12, MT6351_PMIC_OC_STATUS_VRF12_ADDR, + MT6351_PMIC_OC_STATUS_VRF12_MASK, MT6351_PMIC_OC_STATUS_VRF12_SHIFT}, + {PMIC_OC_STATUS_VXO22, MT6351_PMIC_OC_STATUS_VXO22_ADDR, + MT6351_PMIC_OC_STATUS_VXO22_MASK, MT6351_PMIC_OC_STATUS_VXO22_SHIFT}, + {PMIC_OC_STATUS_VSRAM_PROC, MT6351_PMIC_OC_STATUS_VSRAM_PROC_ADDR, + MT6351_PMIC_OC_STATUS_VSRAM_PROC_MASK, MT6351_PMIC_OC_STATUS_VSRAM_PROC_SHIFT}, + {PMIC_OC_STATUS_VCAMIO, MT6351_PMIC_OC_STATUS_VCAMIO_ADDR, + MT6351_PMIC_OC_STATUS_VCAMIO_MASK, MT6351_PMIC_OC_STATUS_VCAMIO_SHIFT}, + {PMIC_OC_STATUS_VCN18, MT6351_PMIC_OC_STATUS_VCN18_ADDR, + MT6351_PMIC_OC_STATUS_VCN18_MASK, MT6351_PMIC_OC_STATUS_VCN18_SHIFT}, + {PMIC_OC_STATUS_VIO18, MT6351_PMIC_OC_STATUS_VIO18_ADDR, + MT6351_PMIC_OC_STATUS_VIO18_MASK, MT6351_PMIC_OC_STATUS_VIO18_SHIFT}, + {PMIC_OC_STATUS_VRF18, MT6351_PMIC_OC_STATUS_VRF18_ADDR, + MT6351_PMIC_OC_STATUS_VRF18_MASK, MT6351_PMIC_OC_STATUS_VRF18_SHIFT}, + {PMIC_OC_STATUS_VCAMD, MT6351_PMIC_OC_STATUS_VCAMD_ADDR, + MT6351_PMIC_OC_STATUS_VCAMD_MASK, MT6351_PMIC_OC_STATUS_VCAMD_SHIFT}, + {PMIC_VA18_PG_DEB, MT6351_PMIC_VA18_PG_DEB_ADDR, MT6351_PMIC_VA18_PG_DEB_MASK, + MT6351_PMIC_VA18_PG_DEB_SHIFT}, + {PMIC_VCORE_PG_DEB, MT6351_PMIC_VCORE_PG_DEB_ADDR, MT6351_PMIC_VCORE_PG_DEB_MASK, + MT6351_PMIC_VCORE_PG_DEB_SHIFT}, + {PMIC_VMD1_PG_DEB, MT6351_PMIC_VMD1_PG_DEB_ADDR, MT6351_PMIC_VMD1_PG_DEB_MASK, + MT6351_PMIC_VMD1_PG_DEB_SHIFT}, + {PMIC_VMODEM_PG_DEB, MT6351_PMIC_VMODEM_PG_DEB_ADDR, + MT6351_PMIC_VMODEM_PG_DEB_MASK, MT6351_PMIC_VMODEM_PG_DEB_SHIFT}, + {PMIC_VS2_PG_DEB, MT6351_PMIC_VS2_PG_DEB_ADDR, MT6351_PMIC_VS2_PG_DEB_MASK, + MT6351_PMIC_VS2_PG_DEB_SHIFT}, + {PMIC_VIO18_PG_DEB, MT6351_PMIC_VIO18_PG_DEB_ADDR, MT6351_PMIC_VIO18_PG_DEB_MASK, + MT6351_PMIC_VIO18_PG_DEB_SHIFT}, + {PMIC_VEMC_PG_DEB, MT6351_PMIC_VEMC_PG_DEB_ADDR, MT6351_PMIC_VEMC_PG_DEB_MASK, + MT6351_PMIC_VEMC_PG_DEB_SHIFT}, + {PMIC_VA10_PG_DEB, MT6351_PMIC_VA10_PG_DEB_ADDR, MT6351_PMIC_VA10_PG_DEB_MASK, + MT6351_PMIC_VA10_PG_DEB_SHIFT}, + {PMIC_VIO28_PG_DEB, MT6351_PMIC_VIO28_PG_DEB_ADDR, MT6351_PMIC_VIO28_PG_DEB_MASK, + MT6351_PMIC_VIO28_PG_DEB_SHIFT}, + {PMIC_VSRAM_MD_PG_DEB, MT6351_PMIC_VSRAM_MD_PG_DEB_ADDR, + MT6351_PMIC_VSRAM_MD_PG_DEB_MASK, MT6351_PMIC_VSRAM_MD_PG_DEB_SHIFT}, + {PMIC_VSRAM_PROC_PG_DEB, MT6351_PMIC_VSRAM_PROC_PG_DEB_ADDR, + MT6351_PMIC_VSRAM_PROC_PG_DEB_MASK, MT6351_PMIC_VSRAM_PROC_PG_DEB_SHIFT}, + {PMIC_VDRAM_PG_DEB, MT6351_PMIC_VDRAM_PG_DEB_ADDR, MT6351_PMIC_VDRAM_PG_DEB_MASK, + MT6351_PMIC_VDRAM_PG_DEB_SHIFT}, + {PMIC_VGPU_PG_DEB, MT6351_PMIC_VGPU_PG_DEB_ADDR, MT6351_PMIC_VGPU_PG_DEB_MASK, + MT6351_PMIC_VGPU_PG_DEB_SHIFT}, + {PMIC_VUSB33_PG_DEB, MT6351_PMIC_VUSB33_PG_DEB_ADDR, + MT6351_PMIC_VUSB33_PG_DEB_MASK, MT6351_PMIC_VUSB33_PG_DEB_SHIFT}, + {PMIC_VXO22_PG_DEB, MT6351_PMIC_VXO22_PG_DEB_ADDR, MT6351_PMIC_VXO22_PG_DEB_MASK, + MT6351_PMIC_VXO22_PG_DEB_SHIFT}, + {PMIC_VTCXO24_PG_DEB, MT6351_PMIC_VTCXO24_PG_DEB_ADDR, + MT6351_PMIC_VTCXO24_PG_DEB_MASK, MT6351_PMIC_VTCXO24_PG_DEB_SHIFT}, + {PMIC_VS1_PG_DEB, MT6351_PMIC_VS1_PG_DEB_ADDR, MT6351_PMIC_VS1_PG_DEB_MASK, + MT6351_PMIC_VS1_PG_DEB_SHIFT}, + {PMIC_STRUP_VA18_PG_STATUS, MT6351_PMIC_STRUP_VA18_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VA18_PG_STATUS_MASK, MT6351_PMIC_STRUP_VA18_PG_STATUS_SHIFT}, + {PMIC_STRUP_VCORE_PG_STATUS, MT6351_PMIC_STRUP_VCORE_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VCORE_PG_STATUS_MASK, MT6351_PMIC_STRUP_VCORE_PG_STATUS_SHIFT}, + {PMIC_STRUP_VMD1_PG_STATUS, MT6351_PMIC_STRUP_VMD1_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VMD1_PG_STATUS_MASK, MT6351_PMIC_STRUP_VMD1_PG_STATUS_SHIFT}, + {PMIC_STRUP_VMODEM_PG_STATUS, MT6351_PMIC_STRUP_VMODEM_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VMODEM_PG_STATUS_MASK, MT6351_PMIC_STRUP_VMODEM_PG_STATUS_SHIFT}, + {PMIC_STRUP_VS2_PG_STATUS, MT6351_PMIC_STRUP_VS2_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VS2_PG_STATUS_MASK, MT6351_PMIC_STRUP_VS2_PG_STATUS_SHIFT}, + {PMIC_STRUP_VIO18_PG_STATUS, MT6351_PMIC_STRUP_VIO18_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VIO18_PG_STATUS_MASK, MT6351_PMIC_STRUP_VIO18_PG_STATUS_SHIFT}, + {PMIC_STRUP_VEMC_PG_STATUS, MT6351_PMIC_STRUP_VEMC_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VEMC_PG_STATUS_MASK, MT6351_PMIC_STRUP_VEMC_PG_STATUS_SHIFT}, + {PMIC_STRUP_VA10_PG_STATUS, MT6351_PMIC_STRUP_VA10_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VA10_PG_STATUS_MASK, MT6351_PMIC_STRUP_VA10_PG_STATUS_SHIFT}, + {PMIC_STRUP_VIO28_PG_STATUS, MT6351_PMIC_STRUP_VIO28_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VIO28_PG_STATUS_MASK, MT6351_PMIC_STRUP_VIO28_PG_STATUS_SHIFT}, + {PMIC_STRUP_VSRAM_MD_PG_STATUS, MT6351_PMIC_STRUP_VSRAM_MD_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VSRAM_MD_PG_STATUS_MASK, MT6351_PMIC_STRUP_VSRAM_MD_PG_STATUS_SHIFT}, + {PMIC_STRUP_VSRAM_PROC_PG_STATUS, MT6351_PMIC_STRUP_VSRAM_PROC_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VSRAM_PROC_PG_STATUS_MASK, + MT6351_PMIC_STRUP_VSRAM_PROC_PG_STATUS_SHIFT}, + {PMIC_STRUP_VDRAM_PG_STATUS, MT6351_PMIC_STRUP_VDRAM_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VDRAM_PG_STATUS_MASK, MT6351_PMIC_STRUP_VDRAM_PG_STATUS_SHIFT}, + {PMIC_STRUP_VGPU_PG_STATUS, MT6351_PMIC_STRUP_VGPU_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VGPU_PG_STATUS_MASK, MT6351_PMIC_STRUP_VGPU_PG_STATUS_SHIFT}, + {PMIC_STRUP_VUSB33_PG_STATUS, MT6351_PMIC_STRUP_VUSB33_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VUSB33_PG_STATUS_MASK, MT6351_PMIC_STRUP_VUSB33_PG_STATUS_SHIFT}, + {PMIC_STRUP_VXO22_PG_STATUS, MT6351_PMIC_STRUP_VXO22_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VXO22_PG_STATUS_MASK, MT6351_PMIC_STRUP_VXO22_PG_STATUS_SHIFT}, + {PMIC_STRUP_VTCXO24_PG_STATUS, MT6351_PMIC_STRUP_VTCXO24_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VTCXO24_PG_STATUS_MASK, MT6351_PMIC_STRUP_VTCXO24_PG_STATUS_SHIFT}, + {PMIC_STRUP_VS1_PG_STATUS, MT6351_PMIC_STRUP_VS1_PG_STATUS_ADDR, + MT6351_PMIC_STRUP_VS1_PG_STATUS_MASK, MT6351_PMIC_STRUP_VS1_PG_STATUS_SHIFT}, + {PMIC_THERMAL_BACK110, MT6351_PMIC_THERMAL_BACK110_ADDR, + MT6351_PMIC_THERMAL_BACK110_MASK, MT6351_PMIC_THERMAL_BACK110_SHIFT}, + {PMIC_THERMAL_OVER110, MT6351_PMIC_THERMAL_OVER110_ADDR, + MT6351_PMIC_THERMAL_OVER110_MASK, MT6351_PMIC_THERMAL_OVER110_SHIFT}, + {PMIC_THERMAL_OVER125, MT6351_PMIC_THERMAL_OVER125_ADDR, + MT6351_PMIC_THERMAL_OVER125_MASK, MT6351_PMIC_THERMAL_OVER125_SHIFT}, + {PMIC_STRUP_THERMAL_STATUS, MT6351_PMIC_STRUP_THERMAL_STATUS_ADDR, + MT6351_PMIC_STRUP_THERMAL_STATUS_MASK, MT6351_PMIC_STRUP_THERMAL_STATUS_SHIFT}, + {PMIC_PMU_TEST_MODE_SCAN, MT6351_PMIC_PMU_TEST_MODE_SCAN_ADDR, + MT6351_PMIC_PMU_TEST_MODE_SCAN_MASK, MT6351_PMIC_PMU_TEST_MODE_SCAN_SHIFT}, + {PMIC_PWRKEY_DEB, MT6351_PMIC_PWRKEY_DEB_ADDR, MT6351_PMIC_PWRKEY_DEB_MASK, + MT6351_PMIC_PWRKEY_DEB_SHIFT}, + {PMIC_HOMEKEY_DEB, MT6351_PMIC_HOMEKEY_DEB_ADDR, MT6351_PMIC_HOMEKEY_DEB_MASK, + MT6351_PMIC_HOMEKEY_DEB_SHIFT}, + {PMIC_RTC_XTAL_DET_DONE, MT6351_PMIC_RTC_XTAL_DET_DONE_ADDR, + MT6351_PMIC_RTC_XTAL_DET_DONE_MASK, MT6351_PMIC_RTC_XTAL_DET_DONE_SHIFT}, + {PMIC_XOSC32_ENB_DET, MT6351_PMIC_XOSC32_ENB_DET_ADDR, + MT6351_PMIC_XOSC32_ENB_DET_MASK, MT6351_PMIC_XOSC32_ENB_DET_SHIFT}, + {PMIC_RTC_XTAL_DET_RSV, MT6351_PMIC_RTC_XTAL_DET_RSV_ADDR, + MT6351_PMIC_RTC_XTAL_DET_RSV_MASK, MT6351_PMIC_RTC_XTAL_DET_RSV_SHIFT}, + {PMIC_RG_PMU_TDSEL, MT6351_PMIC_RG_PMU_TDSEL_ADDR, MT6351_PMIC_RG_PMU_TDSEL_MASK, + MT6351_PMIC_RG_PMU_TDSEL_SHIFT}, + {PMIC_RG_SPI_TDSEL, MT6351_PMIC_RG_SPI_TDSEL_ADDR, MT6351_PMIC_RG_SPI_TDSEL_MASK, + MT6351_PMIC_RG_SPI_TDSEL_SHIFT}, + {PMIC_RG_AUD_TDSEL, MT6351_PMIC_RG_AUD_TDSEL_ADDR, MT6351_PMIC_RG_AUD_TDSEL_MASK, + MT6351_PMIC_RG_AUD_TDSEL_SHIFT}, + {PMIC_RG_E32CAL_TDSEL, MT6351_PMIC_RG_E32CAL_TDSEL_ADDR, + MT6351_PMIC_RG_E32CAL_TDSEL_MASK, MT6351_PMIC_RG_E32CAL_TDSEL_SHIFT}, + {PMIC_RG_PMU_RDSEL, MT6351_PMIC_RG_PMU_RDSEL_ADDR, MT6351_PMIC_RG_PMU_RDSEL_MASK, + MT6351_PMIC_RG_PMU_RDSEL_SHIFT}, + {PMIC_RG_SPI_RDSEL, MT6351_PMIC_RG_SPI_RDSEL_ADDR, MT6351_PMIC_RG_SPI_RDSEL_MASK, + MT6351_PMIC_RG_SPI_RDSEL_SHIFT}, + {PMIC_RG_AUD_RDSEL, MT6351_PMIC_RG_AUD_RDSEL_ADDR, MT6351_PMIC_RG_AUD_RDSEL_MASK, + MT6351_PMIC_RG_AUD_RDSEL_SHIFT}, + {PMIC_RG_E32CAL_RDSEL, MT6351_PMIC_RG_E32CAL_RDSEL_ADDR, + MT6351_PMIC_RG_E32CAL_RDSEL_MASK, MT6351_PMIC_RG_E32CAL_RDSEL_SHIFT}, + {PMIC_RG_SMT_WDTRSTB_IN, MT6351_PMIC_RG_SMT_WDTRSTB_IN_ADDR, + MT6351_PMIC_RG_SMT_WDTRSTB_IN_MASK, MT6351_PMIC_RG_SMT_WDTRSTB_IN_SHIFT}, + {PMIC_RG_SMT_HOMEKEY, MT6351_PMIC_RG_SMT_HOMEKEY_ADDR, + MT6351_PMIC_RG_SMT_HOMEKEY_MASK, MT6351_PMIC_RG_SMT_HOMEKEY_SHIFT}, + {PMIC_RG_SMT_SRCLKEN_IN0, MT6351_PMIC_RG_SMT_SRCLKEN_IN0_ADDR, + MT6351_PMIC_RG_SMT_SRCLKEN_IN0_MASK, MT6351_PMIC_RG_SMT_SRCLKEN_IN0_SHIFT}, + {PMIC_RG_SMT_SRCLKEN_IN1, MT6351_PMIC_RG_SMT_SRCLKEN_IN1_ADDR, + MT6351_PMIC_RG_SMT_SRCLKEN_IN1_MASK, MT6351_PMIC_RG_SMT_SRCLKEN_IN1_SHIFT}, + {PMIC_RG_SMT_RTC_32K1V8_0, MT6351_PMIC_RG_SMT_RTC_32K1V8_0_ADDR, + MT6351_PMIC_RG_SMT_RTC_32K1V8_0_MASK, MT6351_PMIC_RG_SMT_RTC_32K1V8_0_SHIFT}, + {PMIC_RG_SMT_RTC_32K1V8_1, MT6351_PMIC_RG_SMT_RTC_32K1V8_1_ADDR, + MT6351_PMIC_RG_SMT_RTC_32K1V8_1_MASK, MT6351_PMIC_RG_SMT_RTC_32K1V8_1_SHIFT}, + {PMIC_RG_SMT_SPI_CLK, MT6351_PMIC_RG_SMT_SPI_CLK_ADDR, + MT6351_PMIC_RG_SMT_SPI_CLK_MASK, MT6351_PMIC_RG_SMT_SPI_CLK_SHIFT}, + {PMIC_RG_SMT_SPI_CSN, MT6351_PMIC_RG_SMT_SPI_CSN_ADDR, + MT6351_PMIC_RG_SMT_SPI_CSN_MASK, MT6351_PMIC_RG_SMT_SPI_CSN_SHIFT}, + {PMIC_RG_SMT_SPI_MOSI, MT6351_PMIC_RG_SMT_SPI_MOSI_ADDR, + MT6351_PMIC_RG_SMT_SPI_MOSI_MASK, MT6351_PMIC_RG_SMT_SPI_MOSI_SHIFT}, + {PMIC_RG_SMT_SPI_MISO, MT6351_PMIC_RG_SMT_SPI_MISO_ADDR, + MT6351_PMIC_RG_SMT_SPI_MISO_MASK, MT6351_PMIC_RG_SMT_SPI_MISO_SHIFT}, + {PMIC_RG_SMT_AUD_CLK, MT6351_PMIC_RG_SMT_AUD_CLK_ADDR, + MT6351_PMIC_RG_SMT_AUD_CLK_MASK, MT6351_PMIC_RG_SMT_AUD_CLK_SHIFT}, + {PMIC_RG_SMT_AUD_DAT_MOSI, MT6351_PMIC_RG_SMT_AUD_DAT_MOSI_ADDR, + MT6351_PMIC_RG_SMT_AUD_DAT_MOSI_MASK, MT6351_PMIC_RG_SMT_AUD_DAT_MOSI_SHIFT}, + {PMIC_RG_SMT_AUD_DAT_MISO, MT6351_PMIC_RG_SMT_AUD_DAT_MISO_ADDR, + MT6351_PMIC_RG_SMT_AUD_DAT_MISO_MASK, MT6351_PMIC_RG_SMT_AUD_DAT_MISO_SHIFT}, + {PMIC_RG_SMT_ANC_DAT_MOSI, MT6351_PMIC_RG_SMT_ANC_DAT_MOSI_ADDR, + MT6351_PMIC_RG_SMT_ANC_DAT_MOSI_MASK, MT6351_PMIC_RG_SMT_ANC_DAT_MOSI_SHIFT}, + {PMIC_RG_SMT_VOW_CLK_MISO, MT6351_PMIC_RG_SMT_VOW_CLK_MISO_ADDR, + MT6351_PMIC_RG_SMT_VOW_CLK_MISO_MASK, MT6351_PMIC_RG_SMT_VOW_CLK_MISO_SHIFT}, + {PMIC_RG_SMT_ENBB, MT6351_PMIC_RG_SMT_ENBB_ADDR, MT6351_PMIC_RG_SMT_ENBB_MASK, + MT6351_PMIC_RG_SMT_ENBB_SHIFT}, + {PMIC_RG_SMT_XOSC_EN, MT6351_PMIC_RG_SMT_XOSC_EN_ADDR, + MT6351_PMIC_RG_SMT_XOSC_EN_MASK, MT6351_PMIC_RG_SMT_XOSC_EN_SHIFT}, + {PMIC_RG_OCTL_SRCLKEN_IN0, MT6351_PMIC_RG_OCTL_SRCLKEN_IN0_ADDR, + MT6351_PMIC_RG_OCTL_SRCLKEN_IN0_MASK, MT6351_PMIC_RG_OCTL_SRCLKEN_IN0_SHIFT}, + {PMIC_RG_OCTL_SRCLKEN_IN1, MT6351_PMIC_RG_OCTL_SRCLKEN_IN1_ADDR, + MT6351_PMIC_RG_OCTL_SRCLKEN_IN1_MASK, MT6351_PMIC_RG_OCTL_SRCLKEN_IN1_SHIFT}, + {PMIC_RG_OCTL_RTC_32K1V8_0, MT6351_PMIC_RG_OCTL_RTC_32K1V8_0_ADDR, + MT6351_PMIC_RG_OCTL_RTC_32K1V8_0_MASK, MT6351_PMIC_RG_OCTL_RTC_32K1V8_0_SHIFT}, + {PMIC_RG_OCTL_RTC_32K1V8_1, MT6351_PMIC_RG_OCTL_RTC_32K1V8_1_ADDR, + MT6351_PMIC_RG_OCTL_RTC_32K1V8_1_MASK, MT6351_PMIC_RG_OCTL_RTC_32K1V8_1_SHIFT}, + {PMIC_RG_OCTL_SPI_CLK, MT6351_PMIC_RG_OCTL_SPI_CLK_ADDR, + MT6351_PMIC_RG_OCTL_SPI_CLK_MASK, MT6351_PMIC_RG_OCTL_SPI_CLK_SHIFT}, + {PMIC_RG_OCTL_SPI_CSN, MT6351_PMIC_RG_OCTL_SPI_CSN_ADDR, + MT6351_PMIC_RG_OCTL_SPI_CSN_MASK, MT6351_PMIC_RG_OCTL_SPI_CSN_SHIFT}, + {PMIC_RG_OCTL_SPI_MOSI, MT6351_PMIC_RG_OCTL_SPI_MOSI_ADDR, + MT6351_PMIC_RG_OCTL_SPI_MOSI_MASK, MT6351_PMIC_RG_OCTL_SPI_MOSI_SHIFT}, + {PMIC_RG_OCTL_SPI_MISO, MT6351_PMIC_RG_OCTL_SPI_MISO_ADDR, + MT6351_PMIC_RG_OCTL_SPI_MISO_MASK, MT6351_PMIC_RG_OCTL_SPI_MISO_SHIFT}, + {PMIC_RG_OCTL_AUD_DAT_MOSI, MT6351_PMIC_RG_OCTL_AUD_DAT_MOSI_ADDR, + MT6351_PMIC_RG_OCTL_AUD_DAT_MOSI_MASK, MT6351_PMIC_RG_OCTL_AUD_DAT_MOSI_SHIFT}, + {PMIC_RG_OCTL_AUD_DAT_MISO, MT6351_PMIC_RG_OCTL_AUD_DAT_MISO_ADDR, + MT6351_PMIC_RG_OCTL_AUD_DAT_MISO_MASK, MT6351_PMIC_RG_OCTL_AUD_DAT_MISO_SHIFT}, + {PMIC_RG_OCTL_AUD_CLK, MT6351_PMIC_RG_OCTL_AUD_CLK_ADDR, + MT6351_PMIC_RG_OCTL_AUD_CLK_MASK, MT6351_PMIC_RG_OCTL_AUD_CLK_SHIFT}, + {PMIC_RG_OCTL_ANC_DAT_MOSI, MT6351_PMIC_RG_OCTL_ANC_DAT_MOSI_ADDR, + MT6351_PMIC_RG_OCTL_ANC_DAT_MOSI_MASK, MT6351_PMIC_RG_OCTL_ANC_DAT_MOSI_SHIFT}, + {PMIC_RG_OCTL_HOMEKEY, MT6351_PMIC_RG_OCTL_HOMEKEY_ADDR, + MT6351_PMIC_RG_OCTL_HOMEKEY_MASK, MT6351_PMIC_RG_OCTL_HOMEKEY_SHIFT}, + {PMIC_RG_OCTL_ENBB, MT6351_PMIC_RG_OCTL_ENBB_ADDR, MT6351_PMIC_RG_OCTL_ENBB_MASK, + MT6351_PMIC_RG_OCTL_ENBB_SHIFT}, + {PMIC_RG_OCTL_XOSC_EN, MT6351_PMIC_RG_OCTL_XOSC_EN_ADDR, + MT6351_PMIC_RG_OCTL_XOSC_EN_MASK, MT6351_PMIC_RG_OCTL_XOSC_EN_SHIFT}, + {PMIC_RG_OCTL_VOW_CLK_MISO, MT6351_PMIC_RG_OCTL_VOW_CLK_MISO_ADDR, + MT6351_PMIC_RG_OCTL_VOW_CLK_MISO_MASK, MT6351_PMIC_RG_OCTL_VOW_CLK_MISO_SHIFT}, + {PMIC_TOP_STATUS, MT6351_PMIC_TOP_STATUS_ADDR, MT6351_PMIC_TOP_STATUS_MASK, + MT6351_PMIC_TOP_STATUS_SHIFT}, + {PMIC_TOP_STATUS_SET, MT6351_PMIC_TOP_STATUS_SET_ADDR, + MT6351_PMIC_TOP_STATUS_SET_MASK, MT6351_PMIC_TOP_STATUS_SET_SHIFT}, + {PMIC_TOP_STATUS_CLR, MT6351_PMIC_TOP_STATUS_CLR_ADDR, + MT6351_PMIC_TOP_STATUS_CLR_MASK, MT6351_PMIC_TOP_STATUS_CLR_SHIFT}, + {PMIC_RG_G_SMPS_PD_CK_PDN, MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_ADDR, + MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_MASK, MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_SHIFT}, + {PMIC_RG_G_SMPS_AUD_CK_PDN, MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_ADDR, + MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_MASK, MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_SHIFT}, + {PMIC_RG_G_DRV_2M_CK_PDN, MT6351_PMIC_RG_G_DRV_2M_CK_PDN_ADDR, + MT6351_PMIC_RG_G_DRV_2M_CK_PDN_MASK, MT6351_PMIC_RG_G_DRV_2M_CK_PDN_SHIFT}, + {PMIC_RG_DRV_32K_CK_PDN, MT6351_PMIC_RG_DRV_32K_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_32K_CK_PDN_MASK, MT6351_PMIC_RG_DRV_32K_CK_PDN_SHIFT}, + {PMIC_RG_DRV_ISINK0_CK_PDN, MT6351_PMIC_RG_DRV_ISINK0_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_ISINK0_CK_PDN_MASK, MT6351_PMIC_RG_DRV_ISINK0_CK_PDN_SHIFT}, + {PMIC_RG_DRV_ISINK1_CK_PDN, MT6351_PMIC_RG_DRV_ISINK1_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_ISINK1_CK_PDN_MASK, MT6351_PMIC_RG_DRV_ISINK1_CK_PDN_SHIFT}, + {PMIC_RG_DRV_ISINK2_CK_PDN, MT6351_PMIC_RG_DRV_ISINK2_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_ISINK2_CK_PDN_MASK, MT6351_PMIC_RG_DRV_ISINK2_CK_PDN_SHIFT}, + {PMIC_RG_DRV_ISINK3_CK_PDN, MT6351_PMIC_RG_DRV_ISINK3_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_ISINK3_CK_PDN_MASK, MT6351_PMIC_RG_DRV_ISINK3_CK_PDN_SHIFT}, + {PMIC_RG_AUXADC_1M_CK_PDN, MT6351_PMIC_RG_AUXADC_1M_CK_PDN_ADDR, + MT6351_PMIC_RG_AUXADC_1M_CK_PDN_MASK, MT6351_PMIC_RG_AUXADC_1M_CK_PDN_SHIFT}, + {PMIC_RG_AUXADC_SMPS_CK_PDN, MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_ADDR, + MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_MASK, MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_SHIFT}, + {PMIC_RG_AUXADC_RNG_CK_PDN, MT6351_PMIC_RG_AUXADC_RNG_CK_PDN_ADDR, + MT6351_PMIC_RG_AUXADC_RNG_CK_PDN_MASK, MT6351_PMIC_RG_AUXADC_RNG_CK_PDN_SHIFT}, + {PMIC_RG_AUXADC_26M_CK_PDN, MT6351_PMIC_RG_AUXADC_26M_CK_PDN_ADDR, + MT6351_PMIC_RG_AUXADC_26M_CK_PDN_MASK, MT6351_PMIC_RG_AUXADC_26M_CK_PDN_SHIFT}, + {PMIC_RG_AUDNCP_CK_PDN, MT6351_PMIC_RG_AUDNCP_CK_PDN_ADDR, + MT6351_PMIC_RG_AUDNCP_CK_PDN_MASK, MT6351_PMIC_RG_AUDNCP_CK_PDN_SHIFT}, + {PMIC_RG_AUDIF_CK_PDN, MT6351_PMIC_RG_AUDIF_CK_PDN_ADDR, + MT6351_PMIC_RG_AUDIF_CK_PDN_MASK, MT6351_PMIC_RG_AUDIF_CK_PDN_SHIFT}, + {PMIC_RG_AUD_CK_PDN, MT6351_PMIC_RG_AUD_CK_PDN_ADDR, + MT6351_PMIC_RG_AUD_CK_PDN_MASK, MT6351_PMIC_RG_AUD_CK_PDN_SHIFT}, + {PMIC_RG_ZCD13M_CK_PDN, MT6351_PMIC_RG_ZCD13M_CK_PDN_ADDR, + MT6351_PMIC_RG_ZCD13M_CK_PDN_MASK, MT6351_PMIC_RG_ZCD13M_CK_PDN_SHIFT}, + {PMIC_TOP_CKPDN_CON0_SET, MT6351_PMIC_TOP_CKPDN_CON0_SET_ADDR, + MT6351_PMIC_TOP_CKPDN_CON0_SET_MASK, MT6351_PMIC_TOP_CKPDN_CON0_SET_SHIFT}, + {PMIC_TOP_CKPDN_CON0_CLR, MT6351_PMIC_TOP_CKPDN_CON0_CLR_ADDR, + MT6351_PMIC_TOP_CKPDN_CON0_CLR_MASK, MT6351_PMIC_TOP_CKPDN_CON0_CLR_SHIFT}, + {PMIC_RG_RTC_32K_CK_PDN, MT6351_PMIC_RG_RTC_32K_CK_PDN_ADDR, + MT6351_PMIC_RG_RTC_32K_CK_PDN_MASK, MT6351_PMIC_RG_RTC_32K_CK_PDN_SHIFT}, + {PMIC_RG_RTC_MCLK_PDN, MT6351_PMIC_RG_RTC_MCLK_PDN_ADDR, + MT6351_PMIC_RG_RTC_MCLK_PDN_MASK, MT6351_PMIC_RG_RTC_MCLK_PDN_SHIFT}, + {PMIC_RG_RTC_75K_CK_PDN, MT6351_PMIC_RG_RTC_75K_CK_PDN_ADDR, + MT6351_PMIC_RG_RTC_75K_CK_PDN_MASK, MT6351_PMIC_RG_RTC_75K_CK_PDN_SHIFT}, + {PMIC_RG_RTCDET_CK_PDN, MT6351_PMIC_RG_RTCDET_CK_PDN_ADDR, + MT6351_PMIC_RG_RTCDET_CK_PDN_MASK, MT6351_PMIC_RG_RTCDET_CK_PDN_SHIFT}, + {PMIC_RG_RTC32K_1V8_0_O_PDN, MT6351_PMIC_RG_RTC32K_1V8_0_O_PDN_ADDR, + MT6351_PMIC_RG_RTC32K_1V8_0_O_PDN_MASK, MT6351_PMIC_RG_RTC32K_1V8_0_O_PDN_SHIFT}, + {PMIC_RG_RTC32K_1V8_1_O_PDN, MT6351_PMIC_RG_RTC32K_1V8_1_O_PDN_ADDR, + MT6351_PMIC_RG_RTC32K_1V8_1_O_PDN_MASK, MT6351_PMIC_RG_RTC32K_1V8_1_O_PDN_SHIFT}, + {PMIC_RG_RTC_2SEC_OFF_DET_PDN, MT6351_PMIC_RG_RTC_2SEC_OFF_DET_PDN_ADDR, + MT6351_PMIC_RG_RTC_2SEC_OFF_DET_PDN_MASK, MT6351_PMIC_RG_RTC_2SEC_OFF_DET_PDN_SHIFT}, + {PMIC_RG_FQMTR_CK_PDN, MT6351_PMIC_RG_FQMTR_CK_PDN_ADDR, + MT6351_PMIC_RG_FQMTR_CK_PDN_MASK, MT6351_PMIC_RG_FQMTR_CK_PDN_SHIFT}, + {PMIC_RG_STB_1M_CK_PDN, MT6351_PMIC_RG_STB_1M_CK_PDN_ADDR, + MT6351_PMIC_RG_STB_1M_CK_PDN_MASK, MT6351_PMIC_RG_STB_1M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_1M_CK_PDN, MT6351_PMIC_RG_BUCK_1M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_1M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_1M_CK_PDN_SHIFT}, + {PMIC_RG_AUXADC_CK_PDN, MT6351_PMIC_RG_AUXADC_CK_PDN_ADDR, + MT6351_PMIC_RG_AUXADC_CK_PDN_MASK, MT6351_PMIC_RG_AUXADC_CK_PDN_SHIFT}, + {PMIC_RG_PWMOC_6M_CK_PDN, MT6351_PMIC_RG_PWMOC_6M_CK_PDN_ADDR, + MT6351_PMIC_RG_PWMOC_6M_CK_PDN_MASK, MT6351_PMIC_RG_PWMOC_6M_CK_PDN_SHIFT}, + {PMIC_RG_PWMOC_AUD_6M_CK_PDN, MT6351_PMIC_RG_PWMOC_AUD_6M_CK_PDN_ADDR, + MT6351_PMIC_RG_PWMOC_AUD_6M_CK_PDN_MASK, MT6351_PMIC_RG_PWMOC_AUD_6M_CK_PDN_SHIFT}, + {PMIC_TOP_CKPDN_CON1_SET, MT6351_PMIC_TOP_CKPDN_CON1_SET_ADDR, + MT6351_PMIC_TOP_CKPDN_CON1_SET_MASK, MT6351_PMIC_TOP_CKPDN_CON1_SET_SHIFT}, + {PMIC_TOP_CKPDN_CON1_CLR, MT6351_PMIC_TOP_CKPDN_CON1_CLR_ADDR, + MT6351_PMIC_TOP_CKPDN_CON1_CLR_MASK, MT6351_PMIC_TOP_CKPDN_CON1_CLR_SHIFT}, + {PMIC_RG_FGADC_ANA_CK_PDN, MT6351_PMIC_RG_FGADC_ANA_CK_PDN_ADDR, + MT6351_PMIC_RG_FGADC_ANA_CK_PDN_MASK, MT6351_PMIC_RG_FGADC_ANA_CK_PDN_SHIFT}, + {PMIC_RG_FGADC_DIG_CK_PDN, MT6351_PMIC_RG_FGADC_DIG_CK_PDN_ADDR, + MT6351_PMIC_RG_FGADC_DIG_CK_PDN_MASK, MT6351_PMIC_RG_FGADC_DIG_CK_PDN_SHIFT}, + {PMIC_RG_BIF_X72_CK_PDN, MT6351_PMIC_RG_BIF_X72_CK_PDN_ADDR, + MT6351_PMIC_RG_BIF_X72_CK_PDN_MASK, MT6351_PMIC_RG_BIF_X72_CK_PDN_SHIFT}, + {PMIC_RG_BIF_X4_CK_PDN, MT6351_PMIC_RG_BIF_X4_CK_PDN_ADDR, + MT6351_PMIC_RG_BIF_X4_CK_PDN_MASK, MT6351_PMIC_RG_BIF_X4_CK_PDN_SHIFT}, + {PMIC_RG_BIF_X1_CK_PDN, MT6351_PMIC_RG_BIF_X1_CK_PDN_ADDR, + MT6351_PMIC_RG_BIF_X1_CK_PDN_MASK, MT6351_PMIC_RG_BIF_X1_CK_PDN_SHIFT}, + {PMIC_RG_PCHR_32K_CK_PDN, MT6351_PMIC_RG_PCHR_32K_CK_PDN_ADDR, + MT6351_PMIC_RG_PCHR_32K_CK_PDN_MASK, MT6351_PMIC_RG_PCHR_32K_CK_PDN_SHIFT}, + {PMIC_RG_ACCDET_CK_PDN, MT6351_PMIC_RG_ACCDET_CK_PDN_ADDR, + MT6351_PMIC_RG_ACCDET_CK_PDN_MASK, MT6351_PMIC_RG_ACCDET_CK_PDN_SHIFT}, + {PMIC_RG_FQMTR_32K_CK_PDN, MT6351_PMIC_RG_FQMTR_32K_CK_PDN_ADDR, + MT6351_PMIC_RG_FQMTR_32K_CK_PDN_MASK, MT6351_PMIC_RG_FQMTR_32K_CK_PDN_SHIFT}, + {PMIC_RG_INTRP_CK_PDN, MT6351_PMIC_RG_INTRP_CK_PDN_ADDR, + MT6351_PMIC_RG_INTRP_CK_PDN_MASK, MT6351_PMIC_RG_INTRP_CK_PDN_SHIFT}, + {PMIC_RG_RTC_26M_CK_PDN, MT6351_PMIC_RG_RTC_26M_CK_PDN_ADDR, + MT6351_PMIC_RG_RTC_26M_CK_PDN_MASK, MT6351_PMIC_RG_RTC_26M_CK_PDN_SHIFT}, + {PMIC_RG_RTC_EOSC32_CK_PDN, MT6351_PMIC_RG_RTC_EOSC32_CK_PDN_ADDR, + MT6351_PMIC_RG_RTC_EOSC32_CK_PDN_MASK, MT6351_PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT}, + {PMIC_RG_TRIM_75K_CK_PDN, MT6351_PMIC_RG_TRIM_75K_CK_PDN_ADDR, + MT6351_PMIC_RG_TRIM_75K_CK_PDN_MASK, MT6351_PMIC_RG_TRIM_75K_CK_PDN_SHIFT}, + {PMIC_RG_STRUP_LBAT_SEL_CK_PDN, MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_PDN_ADDR, + MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_PDN_MASK, MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_PDN_SHIFT}, + {PMIC_TOP_CKPDN_CON2_SET, MT6351_PMIC_TOP_CKPDN_CON2_SET_ADDR, + MT6351_PMIC_TOP_CKPDN_CON2_SET_MASK, MT6351_PMIC_TOP_CKPDN_CON2_SET_SHIFT}, + {PMIC_TOP_CKPDN_CON2_CLR, MT6351_PMIC_TOP_CKPDN_CON2_CLR_ADDR, + MT6351_PMIC_TOP_CKPDN_CON2_CLR_MASK, MT6351_PMIC_TOP_CKPDN_CON2_CLR_SHIFT}, + {PMIC_RG_STRUP_75K_CK_PDN, MT6351_PMIC_RG_STRUP_75K_CK_PDN_ADDR, + MT6351_PMIC_RG_STRUP_75K_CK_PDN_MASK, MT6351_PMIC_RG_STRUP_75K_CK_PDN_SHIFT}, + {PMIC_RG_STRUP_32K_CK_PDN, MT6351_PMIC_RG_STRUP_32K_CK_PDN_ADDR, + MT6351_PMIC_RG_STRUP_32K_CK_PDN_MASK, MT6351_PMIC_RG_STRUP_32K_CK_PDN_SHIFT}, + {PMIC_RG_EFUSE_CK_PDN, MT6351_PMIC_RG_EFUSE_CK_PDN_ADDR, + MT6351_PMIC_RG_EFUSE_CK_PDN_MASK, MT6351_PMIC_RG_EFUSE_CK_PDN_SHIFT}, + {PMIC_RG_SMPS_CK_DIV_PDN, MT6351_PMIC_RG_SMPS_CK_DIV_PDN_ADDR, + MT6351_PMIC_RG_SMPS_CK_DIV_PDN_MASK, MT6351_PMIC_RG_SMPS_CK_DIV_PDN_SHIFT}, + {PMIC_RG_SPI_CK_PDN, MT6351_PMIC_RG_SPI_CK_PDN_ADDR, + MT6351_PMIC_RG_SPI_CK_PDN_MASK, MT6351_PMIC_RG_SPI_CK_PDN_SHIFT}, + {PMIC_RG_BGR_TEST_CK_PDN, MT6351_PMIC_RG_BGR_TEST_CK_PDN_ADDR, + MT6351_PMIC_RG_BGR_TEST_CK_PDN_MASK, MT6351_PMIC_RG_BGR_TEST_CK_PDN_SHIFT}, + {PMIC_RG_FGADC_FT_CK_PDN, MT6351_PMIC_RG_FGADC_FT_CK_PDN_ADDR, + MT6351_PMIC_RG_FGADC_FT_CK_PDN_MASK, MT6351_PMIC_RG_FGADC_FT_CK_PDN_SHIFT}, + {PMIC_RG_PCHR_TEST_CK_PDN, MT6351_PMIC_RG_PCHR_TEST_CK_PDN_ADDR, + MT6351_PMIC_RG_PCHR_TEST_CK_PDN_MASK, MT6351_PMIC_RG_PCHR_TEST_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_32K_CK_PDN, MT6351_PMIC_RG_BUCK_32K_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_32K_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_32K_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_ANA_CK_PDN, MT6351_PMIC_RG_BUCK_ANA_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_ANA_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_ANA_CK_PDN_SHIFT}, + {PMIC_RG_EOSC_CALI_TEST_CK_PDN, MT6351_PMIC_RG_EOSC_CALI_TEST_CK_PDN_ADDR, + MT6351_PMIC_RG_EOSC_CALI_TEST_CK_PDN_MASK, MT6351_PMIC_RG_EOSC_CALI_TEST_CK_PDN_SHIFT}, + {PMIC_RG_G_SMPS_TEST_CK_PDN, MT6351_PMIC_RG_G_SMPS_TEST_CK_PDN_ADDR, + MT6351_PMIC_RG_G_SMPS_TEST_CK_PDN_MASK, MT6351_PMIC_RG_G_SMPS_TEST_CK_PDN_SHIFT}, + {PMIC_TOP_CKPDN_CON3_RSV, MT6351_PMIC_TOP_CKPDN_CON3_RSV_ADDR, + MT6351_PMIC_TOP_CKPDN_CON3_RSV_MASK, MT6351_PMIC_TOP_CKPDN_CON3_RSV_SHIFT}, + {PMIC_TOP_CKPDN_CON3_SET, MT6351_PMIC_TOP_CKPDN_CON3_SET_ADDR, + MT6351_PMIC_TOP_CKPDN_CON3_SET_MASK, MT6351_PMIC_TOP_CKPDN_CON3_SET_SHIFT}, + {PMIC_TOP_CKPDN_CON3_CLR, MT6351_PMIC_TOP_CKPDN_CON3_CLR_ADDR, + MT6351_PMIC_TOP_CKPDN_CON3_CLR_MASK, MT6351_PMIC_TOP_CKPDN_CON3_CLR_SHIFT}, + {PMIC_RG_BUCK_9M_CK_PDN, MT6351_PMIC_RG_BUCK_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_9M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_9M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_MASK, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VPA_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VMODEM_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VCORE_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VGPU_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_SHIFT}, + {PMIC_TOP_CKPDN_CON4_RSV, MT6351_PMIC_TOP_CKPDN_CON4_RSV_ADDR, + MT6351_PMIC_TOP_CKPDN_CON4_RSV_MASK, MT6351_PMIC_TOP_CKPDN_CON4_RSV_SHIFT}, + {PMIC_TOP_CKPDN_CON4_SET, MT6351_PMIC_TOP_CKPDN_CON4_SET_ADDR, + MT6351_PMIC_TOP_CKPDN_CON4_SET_MASK, MT6351_PMIC_TOP_CKPDN_CON4_SET_SHIFT}, + {PMIC_TOP_CKPDN_CON4_CLR, MT6351_PMIC_TOP_CKPDN_CON4_CLR_ADDR, + MT6351_PMIC_TOP_CKPDN_CON4_CLR_MASK, MT6351_PMIC_TOP_CKPDN_CON4_CLR_SHIFT}, + {PMIC_RG_LDO_CALI_75K_CK_PDN, MT6351_PMIC_RG_LDO_CALI_75K_CK_PDN_ADDR, + MT6351_PMIC_RG_LDO_CALI_75K_CK_PDN_MASK, MT6351_PMIC_RG_LDO_CALI_75K_CK_PDN_SHIFT}, + {PMIC_RG_INTRP_PRE_OC_CK_PDN, MT6351_PMIC_RG_INTRP_PRE_OC_CK_PDN_ADDR, + MT6351_PMIC_RG_INTRP_PRE_OC_CK_PDN_MASK, MT6351_PMIC_RG_INTRP_PRE_OC_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VS2_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VS1_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VMD1_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN, MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_MASK, + MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_SHIFT}, + {PMIC_RG_VOW32K_CK_PDN, MT6351_PMIC_RG_VOW32K_CK_PDN_ADDR, + MT6351_PMIC_RG_VOW32K_CK_PDN_MASK, MT6351_PMIC_RG_VOW32K_CK_PDN_SHIFT}, + {PMIC_RG_VOW12M_CK_PDN, MT6351_PMIC_RG_VOW12M_CK_PDN_ADDR, + MT6351_PMIC_RG_VOW12M_CK_PDN_MASK, MT6351_PMIC_RG_VOW12M_CK_PDN_SHIFT}, + {PMIC_RG_AUD18M_CK_PDN, MT6351_PMIC_RG_AUD18M_CK_PDN_ADDR, + MT6351_PMIC_RG_AUD18M_CK_PDN_MASK, MT6351_PMIC_RG_AUD18M_CK_PDN_SHIFT}, + {PMIC_RG_DRV_ISINK4_CK_PDN, MT6351_PMIC_RG_DRV_ISINK4_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_ISINK4_CK_PDN_MASK, MT6351_PMIC_RG_DRV_ISINK4_CK_PDN_SHIFT}, + {PMIC_RG_DRV_ISINK5_CK_PDN, MT6351_PMIC_RG_DRV_ISINK5_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_ISINK5_CK_PDN_MASK, MT6351_PMIC_RG_DRV_ISINK5_CK_PDN_SHIFT}, + {PMIC_RG_DRV_ISINK6_CK_PDN, MT6351_PMIC_RG_DRV_ISINK6_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_ISINK6_CK_PDN_MASK, MT6351_PMIC_RG_DRV_ISINK6_CK_PDN_SHIFT}, + {PMIC_RG_DRV_ISINK7_CK_PDN, MT6351_PMIC_RG_DRV_ISINK7_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_ISINK7_CK_PDN_MASK, MT6351_PMIC_RG_DRV_ISINK7_CK_PDN_SHIFT}, + {PMIC_RG_DRV_CHRIND_CK_PDN, MT6351_PMIC_RG_DRV_CHRIND_CK_PDN_ADDR, + MT6351_PMIC_RG_DRV_CHRIND_CK_PDN_MASK, MT6351_PMIC_RG_DRV_CHRIND_CK_PDN_SHIFT}, + {PMIC_RG_BUCK_AUD_1M_CK_PDN, MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_ADDR, + MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_MASK, MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_SHIFT}, + {PMIC_RG_STB_AUD_1M_CK_PDN, MT6351_PMIC_RG_STB_AUD_1M_CK_PDN_ADDR, + MT6351_PMIC_RG_STB_AUD_1M_CK_PDN_MASK, MT6351_PMIC_RG_STB_AUD_1M_CK_PDN_SHIFT}, + {PMIC_TOP_CKPDN_CON5_SET, MT6351_PMIC_TOP_CKPDN_CON5_SET_ADDR, + MT6351_PMIC_TOP_CKPDN_CON5_SET_MASK, MT6351_PMIC_TOP_CKPDN_CON5_SET_SHIFT}, + {PMIC_TOP_CKPDN_CON5_CLR, MT6351_PMIC_TOP_CKPDN_CON5_CLR_ADDR, + MT6351_PMIC_TOP_CKPDN_CON5_CLR_MASK, MT6351_PMIC_TOP_CKPDN_CON5_CLR_SHIFT}, + {PMIC_RG_AUDIF_CK_CKSEL, MT6351_PMIC_RG_AUDIF_CK_CKSEL_ADDR, + MT6351_PMIC_RG_AUDIF_CK_CKSEL_MASK, MT6351_PMIC_RG_AUDIF_CK_CKSEL_SHIFT}, + {PMIC_RG_AUD_CK_CKSEL, MT6351_PMIC_RG_AUD_CK_CKSEL_ADDR, + MT6351_PMIC_RG_AUD_CK_CKSEL_MASK, MT6351_PMIC_RG_AUD_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_ISINK0_CK_CKSEL, MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_ISINK0_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_ISINK1_CK_CKSEL, MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_ISINK1_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_ISINK2_CK_CKSEL, MT6351_PMIC_RG_DRV_ISINK2_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK2_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_ISINK2_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_ISINK3_CK_CKSEL, MT6351_PMIC_RG_DRV_ISINK3_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK3_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_ISINK3_CK_CKSEL_SHIFT}, + {PMIC_RG_FQMTR_CK_CKSEL, MT6351_PMIC_RG_FQMTR_CK_CKSEL_ADDR, + MT6351_PMIC_RG_FQMTR_CK_CKSEL_MASK, MT6351_PMIC_RG_FQMTR_CK_CKSEL_SHIFT}, + {PMIC_RG_75K_32K_SEL, MT6351_PMIC_RG_75K_32K_SEL_ADDR, + MT6351_PMIC_RG_75K_32K_SEL_MASK, MT6351_PMIC_RG_75K_32K_SEL_SHIFT}, + {PMIC_RG_AUXADC_CK_CKSEL, MT6351_PMIC_RG_AUXADC_CK_CKSEL_ADDR, + MT6351_PMIC_RG_AUXADC_CK_CKSEL_MASK, MT6351_PMIC_RG_AUXADC_CK_CKSEL_SHIFT}, + {PMIC_RG_OSC_SEL_HW_SRC_SEL, MT6351_PMIC_RG_OSC_SEL_HW_SRC_SEL_ADDR, + MT6351_PMIC_RG_OSC_SEL_HW_SRC_SEL_MASK, MT6351_PMIC_RG_OSC_SEL_HW_SRC_SEL_SHIFT}, + {PMIC_RG_SRCLKEN_SRC_SEL, MT6351_PMIC_RG_SRCLKEN_SRC_SEL_ADDR, + MT6351_PMIC_RG_SRCLKEN_SRC_SEL_MASK, MT6351_PMIC_RG_SRCLKEN_SRC_SEL_SHIFT}, + {PMIC_TOP_CKSEL_CON_SET, MT6351_PMIC_TOP_CKSEL_CON_SET_ADDR, + MT6351_PMIC_TOP_CKSEL_CON_SET_MASK, MT6351_PMIC_TOP_CKSEL_CON_SET_SHIFT}, + {PMIC_TOP_CKSEL_CON_CLR, MT6351_PMIC_TOP_CKSEL_CON_CLR_ADDR, + MT6351_PMIC_TOP_CKSEL_CON_CLR_MASK, MT6351_PMIC_TOP_CKSEL_CON_CLR_SHIFT}, + {PMIC_RG_STRUP_75K_CK_CKSEL, MT6351_PMIC_RG_STRUP_75K_CK_CKSEL_ADDR, + MT6351_PMIC_RG_STRUP_75K_CK_CKSEL_MASK, MT6351_PMIC_RG_STRUP_75K_CK_CKSEL_SHIFT}, + {PMIC_RG_BGR_TEST_CK_CKSEL, MT6351_PMIC_RG_BGR_TEST_CK_CKSEL_ADDR, + MT6351_PMIC_RG_BGR_TEST_CK_CKSEL_MASK, MT6351_PMIC_RG_BGR_TEST_CK_CKSEL_SHIFT}, + {PMIC_RG_PCHR_TEST_CK_CKSEL, MT6351_PMIC_RG_PCHR_TEST_CK_CKSEL_ADDR, + MT6351_PMIC_RG_PCHR_TEST_CK_CKSEL_MASK, MT6351_PMIC_RG_PCHR_TEST_CK_CKSEL_SHIFT}, + {PMIC_RG_FGADC_ANA_CK_CKSEL, MT6351_PMIC_RG_FGADC_ANA_CK_CKSEL_ADDR, + MT6351_PMIC_RG_FGADC_ANA_CK_CKSEL_MASK, MT6351_PMIC_RG_FGADC_ANA_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_ISINK4_CK_CKSEL, MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_ISINK4_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_ISINK5_CK_CKSEL, MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_ISINK5_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_ISINK6_CK_CKSEL, MT6351_PMIC_RG_DRV_ISINK6_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK6_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_ISINK6_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_ISINK7_CK_CKSEL, MT6351_PMIC_RG_DRV_ISINK7_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK7_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_ISINK7_CK_CKSEL_SHIFT}, + {PMIC_RG_DRV_CHRIND_CK_CKSEL, MT6351_PMIC_RG_DRV_CHRIND_CK_CKSEL_ADDR, + MT6351_PMIC_RG_DRV_CHRIND_CK_CKSEL_MASK, MT6351_PMIC_RG_DRV_CHRIND_CK_CKSEL_SHIFT}, + {PMIC_RG_TOP_CKSEL_CON1_RSV, MT6351_PMIC_RG_TOP_CKSEL_CON1_RSV_ADDR, + MT6351_PMIC_RG_TOP_CKSEL_CON1_RSV_MASK, MT6351_PMIC_RG_TOP_CKSEL_CON1_RSV_SHIFT}, + {PMIC_TOP_CKSEL_CON1_SET, MT6351_PMIC_TOP_CKSEL_CON1_SET_ADDR, + MT6351_PMIC_TOP_CKSEL_CON1_SET_MASK, MT6351_PMIC_TOP_CKSEL_CON1_SET_SHIFT}, + {PMIC_TOP_CKSEL_CON1_CLR, MT6351_PMIC_TOP_CKSEL_CON1_CLR_ADDR, + MT6351_PMIC_TOP_CKSEL_CON1_CLR_MASK, MT6351_PMIC_TOP_CKSEL_CON1_CLR_SHIFT}, + {PMIC_RG_SRCVOLTEN_SW, MT6351_PMIC_RG_SRCVOLTEN_SW_ADDR, + MT6351_PMIC_RG_SRCVOLTEN_SW_MASK, MT6351_PMIC_RG_SRCVOLTEN_SW_SHIFT}, + {PMIC_RG_BUCK_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_OSC_SEL_SW_MASK, MT6351_PMIC_RG_BUCK_OSC_SEL_SW_SHIFT}, + {PMIC_RG_VOWEN_SW, MT6351_PMIC_RG_VOWEN_SW_ADDR, MT6351_PMIC_RG_VOWEN_SW_MASK, + MT6351_PMIC_RG_VOWEN_SW_SHIFT}, + {PMIC_RG_SRCVOLTEN_MODE, MT6351_PMIC_RG_SRCVOLTEN_MODE_ADDR, + MT6351_PMIC_RG_SRCVOLTEN_MODE_MASK, MT6351_PMIC_RG_SRCVOLTEN_MODE_SHIFT}, + {PMIC_RG_BUCK_OSC_SEL_MODE, MT6351_PMIC_RG_BUCK_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_OSC_SEL_MODE_MASK, MT6351_PMIC_RG_BUCK_OSC_SEL_MODE_SHIFT}, + {PMIC_RG_VOWEN_MODE, MT6351_PMIC_RG_VOWEN_MODE_ADDR, + MT6351_PMIC_RG_VOWEN_MODE_MASK, MT6351_PMIC_RG_VOWEN_MODE_SHIFT}, + {PMIC_RG_TOP_CKSEL_CON2_RSV, MT6351_PMIC_RG_TOP_CKSEL_CON2_RSV_ADDR, + MT6351_PMIC_RG_TOP_CKSEL_CON2_RSV_MASK, MT6351_PMIC_RG_TOP_CKSEL_CON2_RSV_SHIFT}, + {PMIC_RG_BUCK_VMD1_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_SW_MASK, MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VMD1_OSC_SEL_MODE, MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_MODE_MASK, MT6351_PMIC_RG_BUCK_VMD1_OSC_SEL_MODE_SHIFT}, + {PMIC_TOP_CKSEL_CON2_SET, MT6351_PMIC_TOP_CKSEL_CON2_SET_ADDR, + MT6351_PMIC_TOP_CKSEL_CON2_SET_MASK, MT6351_PMIC_TOP_CKSEL_CON2_SET_SHIFT}, + {PMIC_TOP_CKSEL_CON2_CLR, MT6351_PMIC_TOP_CKSEL_CON2_CLR_ADDR, + MT6351_PMIC_TOP_CKSEL_CON2_CLR_MASK, MT6351_PMIC_TOP_CKSEL_CON2_CLR_SHIFT}, + {PMIC_RG_BUCK_VCORE_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_SW_MASK, MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW_MASK, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VPA_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_SW_MASK, MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VMODEM_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_SW_MASK, MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VGPU_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_SW_MASK, MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW_MASK, + MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VS2_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_SW_MASK, MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VS1_OSC_SEL_SW, MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_SW_ADDR, + MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_SW_MASK, MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_SW_SHIFT}, + {PMIC_RG_BUCK_VCORE_OSC_SEL_MODE, MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_MODE_MASK, + MT6351_PMIC_RG_BUCK_VCORE_OSC_SEL_MODE_SHIFT}, + {PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE_MASK, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_OSC_SEL_MODE_SHIFT}, + {PMIC_RG_BUCK_VPA_OSC_SEL_MODE, MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_MODE_MASK, MT6351_PMIC_RG_BUCK_VPA_OSC_SEL_MODE_SHIFT}, + {PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE, MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE_MASK, + MT6351_PMIC_RG_BUCK_VMODEM_OSC_SEL_MODE_SHIFT}, + {PMIC_RG_BUCK_VGPU_OSC_SEL_MODE, MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_MODE_MASK, MT6351_PMIC_RG_BUCK_VGPU_OSC_SEL_MODE_SHIFT}, + {PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE, + MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE_MASK, + MT6351_PMIC_RG_BUCK_VSRAM_MD_OSC_SEL_MODE_SHIFT}, + {PMIC_RG_BUCK_VS2_OSC_SEL_MODE, MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_MODE_MASK, MT6351_PMIC_RG_BUCK_VS2_OSC_SEL_MODE_SHIFT}, + {PMIC_RG_BUCK_VS1_OSC_SEL_MODE, MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_MODE_ADDR, + MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_MODE_MASK, MT6351_PMIC_RG_BUCK_VS1_OSC_SEL_MODE_SHIFT}, + {PMIC_TOP_CKSEL_CON3_SET, MT6351_PMIC_TOP_CKSEL_CON3_SET_ADDR, + MT6351_PMIC_TOP_CKSEL_CON3_SET_MASK, MT6351_PMIC_TOP_CKSEL_CON3_SET_SHIFT}, + {PMIC_TOP_CKSEL_CON3_CLR, MT6351_PMIC_TOP_CKSEL_CON3_CLR_ADDR, + MT6351_PMIC_TOP_CKSEL_CON3_CLR_MASK, MT6351_PMIC_TOP_CKSEL_CON3_CLR_SHIFT}, + {PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL, MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL_ADDR, + MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL_MASK, + MT6351_PMIC_RG_STRUP_LBAT_SEL_CK_DIVSEL_SHIFT}, + {PMIC_TOP_CKDIVSEL_CON_RSV, MT6351_PMIC_TOP_CKDIVSEL_CON_RSV_ADDR, + MT6351_PMIC_TOP_CKDIVSEL_CON_RSV_MASK, MT6351_PMIC_TOP_CKDIVSEL_CON_RSV_SHIFT}, + {PMIC_RG_BIF_X4_CK_DIVSEL, MT6351_PMIC_RG_BIF_X4_CK_DIVSEL_ADDR, + MT6351_PMIC_RG_BIF_X4_CK_DIVSEL_MASK, MT6351_PMIC_RG_BIF_X4_CK_DIVSEL_SHIFT}, + {PMIC_RG_REG_CK_DIVSEL, MT6351_PMIC_RG_REG_CK_DIVSEL_ADDR, + MT6351_PMIC_RG_REG_CK_DIVSEL_MASK, MT6351_PMIC_RG_REG_CK_DIVSEL_SHIFT}, + {PMIC_TOP_CKDIVSEL_CON0_RSV, MT6351_PMIC_TOP_CKDIVSEL_CON0_RSV_ADDR, + MT6351_PMIC_TOP_CKDIVSEL_CON0_RSV_MASK, MT6351_PMIC_TOP_CKDIVSEL_CON0_RSV_SHIFT}, + {PMIC_TOP_CKDIVSEL_CON0_SET, MT6351_PMIC_TOP_CKDIVSEL_CON0_SET_ADDR, + MT6351_PMIC_TOP_CKDIVSEL_CON0_SET_MASK, MT6351_PMIC_TOP_CKDIVSEL_CON0_SET_SHIFT}, + {PMIC_TOP_CKDIVSEL_CON0_CLR, MT6351_PMIC_TOP_CKDIVSEL_CON0_CLR_ADDR, + MT6351_PMIC_TOP_CKDIVSEL_CON0_CLR_MASK, MT6351_PMIC_TOP_CKDIVSEL_CON0_CLR_SHIFT}, + {PMIC_RG_AUXADC_SMPS_CK_DIVSEL, MT6351_PMIC_RG_AUXADC_SMPS_CK_DIVSEL_ADDR, + MT6351_PMIC_RG_AUXADC_SMPS_CK_DIVSEL_MASK, MT6351_PMIC_RG_AUXADC_SMPS_CK_DIVSEL_SHIFT}, + {PMIC_RG_AUXADC_26M_CK_DIVSEL, MT6351_PMIC_RG_AUXADC_26M_CK_DIVSEL_ADDR, + MT6351_PMIC_RG_AUXADC_26M_CK_DIVSEL_MASK, MT6351_PMIC_RG_AUXADC_26M_CK_DIVSEL_SHIFT}, + {PMIC_RG_BUCK_9M_CK_DIVSEL, MT6351_PMIC_RG_BUCK_9M_CK_DIVSEL_ADDR, + MT6351_PMIC_RG_BUCK_9M_CK_DIVSEL_MASK, MT6351_PMIC_RG_BUCK_9M_CK_DIVSEL_SHIFT}, + {PMIC_TOP_CKDIVSEL_CON1_SET, MT6351_PMIC_TOP_CKDIVSEL_CON1_SET_ADDR, + MT6351_PMIC_TOP_CKDIVSEL_CON1_SET_MASK, MT6351_PMIC_TOP_CKDIVSEL_CON1_SET_SHIFT}, + {PMIC_TOP_CKDIVSEL_CON1_CLR, MT6351_PMIC_TOP_CKDIVSEL_CON1_CLR_ADDR, + MT6351_PMIC_TOP_CKDIVSEL_CON1_CLR_MASK, MT6351_PMIC_TOP_CKDIVSEL_CON1_CLR_SHIFT}, + {PMIC_RG_G_SMPS_PD_CK_PDN_HWEN, MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_G_SMPS_PD_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN, MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_G_SMPS_AUD_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_G_DRV_2M_CK_PDN_HWEN, MT6351_PMIC_RG_G_DRV_2M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_G_DRV_2M_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_G_DRV_2M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_AUXADC_CK_PDN_HWEN, MT6351_PMIC_RG_AUXADC_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_AUXADC_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_AUXADC_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN, MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_1M_CK_PDN_HWEN, MT6351_PMIC_RG_BUCK_1M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_1M_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_BUCK_1M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_EFUSE_CK_PDN_HWEN, MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_EFUSE_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_RTC_26M_CK_PDN_HWEN, MT6351_PMIC_RG_RTC_26M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_RTC_26M_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_RTC_26M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_AUXADC_26M_CK_PDN_HWEN, MT6351_PMIC_RG_AUXADC_26M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_AUXADC_26M_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_AUXADC_26M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_AUXADC_CK_CKSEL_HWEN, MT6351_PMIC_RG_AUXADC_CK_CKSEL_HWEN_ADDR, + MT6351_PMIC_RG_AUXADC_CK_CKSEL_HWEN_MASK, MT6351_PMIC_RG_AUXADC_CK_CKSEL_HWEN_SHIFT}, + {PMIC_TOP_CKHWEN_CON0_RSV, MT6351_PMIC_TOP_CKHWEN_CON0_RSV_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON0_RSV_MASK, MT6351_PMIC_TOP_CKHWEN_CON0_RSV_SHIFT}, + {PMIC_TOP_CKHWEN_CON0_SET, MT6351_PMIC_TOP_CKHWEN_CON0_SET_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON0_SET_MASK, MT6351_PMIC_TOP_CKHWEN_CON0_SET_SHIFT}, + {PMIC_TOP_CKHWEN_CON0_CLR, MT6351_PMIC_TOP_CKHWEN_CON0_CLR_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON0_CLR_MASK, MT6351_PMIC_TOP_CKHWEN_CON0_CLR_SHIFT}, + {PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VSRAM_PROC_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN, MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VPA_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VMODEM_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN, MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VCORE_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN, MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VGPU_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_TOP_CKHWEN_CON1_RSV, MT6351_PMIC_TOP_CKHWEN_CON1_RSV_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON1_RSV_MASK, MT6351_PMIC_TOP_CKHWEN_CON1_RSV_SHIFT}, + {PMIC_TOP_CKHWEN_CON1_SET, MT6351_PMIC_TOP_CKHWEN_CON1_SET_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON1_SET_MASK, MT6351_PMIC_TOP_CKHWEN_CON1_SET_SHIFT}, + {PMIC_TOP_CKHWEN_CON1_CLR, MT6351_PMIC_TOP_CKHWEN_CON1_CLR_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON1_CLR_MASK, MT6351_PMIC_TOP_CKHWEN_CON1_CLR_SHIFT}, + {PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN, MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VS2_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN, MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VS1_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN, MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VMD1_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN, + MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_VSRAM_MD_9M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_AUD18M_CK_PDN_HWEN, MT6351_PMIC_RG_AUD18M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_AUD18M_CK_PDN_HWEN_MASK, MT6351_PMIC_RG_AUD18M_CK_PDN_HWEN_SHIFT}, + {PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN, MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN_ADDR, + MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN_MASK, + MT6351_PMIC_RG_BUCK_AUD_1M_CK_PDN_HWEN_SHIFT}, + {PMIC_TOP_CKHWEN_CON2_RSV, MT6351_PMIC_TOP_CKHWEN_CON2_RSV_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON2_RSV_MASK, MT6351_PMIC_TOP_CKHWEN_CON2_RSV_SHIFT}, + {PMIC_TOP_CKHWEN_CON2_SET, MT6351_PMIC_TOP_CKHWEN_CON2_SET_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON2_SET_MASK, MT6351_PMIC_TOP_CKHWEN_CON2_SET_SHIFT}, + {PMIC_TOP_CKHWEN_CON2_CLR, MT6351_PMIC_TOP_CKHWEN_CON2_CLR_ADDR, + MT6351_PMIC_TOP_CKHWEN_CON2_CLR_MASK, MT6351_PMIC_TOP_CKHWEN_CON2_CLR_SHIFT}, + {PMIC_RG_PMU75K_CK_TST_DIS, MT6351_PMIC_RG_PMU75K_CK_TST_DIS_ADDR, + MT6351_PMIC_RG_PMU75K_CK_TST_DIS_MASK, MT6351_PMIC_RG_PMU75K_CK_TST_DIS_SHIFT}, + {PMIC_RG_SMPS_CK_TST_DIS, MT6351_PMIC_RG_SMPS_CK_TST_DIS_ADDR, + MT6351_PMIC_RG_SMPS_CK_TST_DIS_MASK, MT6351_PMIC_RG_SMPS_CK_TST_DIS_SHIFT}, + {PMIC_RG_AUD26M_CK_TST_DIS, MT6351_PMIC_RG_AUD26M_CK_TST_DIS_ADDR, + MT6351_PMIC_RG_AUD26M_CK_TST_DIS_MASK, MT6351_PMIC_RG_AUD26M_CK_TST_DIS_SHIFT}, + {PMIC_RG_RTC32K_CK_TST_DIS, MT6351_PMIC_RG_RTC32K_CK_TST_DIS_ADDR, + MT6351_PMIC_RG_RTC32K_CK_TST_DIS_MASK, MT6351_PMIC_RG_RTC32K_CK_TST_DIS_SHIFT}, + {PMIC_RG_FG_CK_TST_DIS, MT6351_PMIC_RG_FG_CK_TST_DIS_ADDR, + MT6351_PMIC_RG_FG_CK_TST_DIS_MASK, MT6351_PMIC_RG_FG_CK_TST_DIS_SHIFT}, + {PMIC_RG_RTC26M_CK_TST_DIS, MT6351_PMIC_RG_RTC26M_CK_TST_DIS_ADDR, + MT6351_PMIC_RG_RTC26M_CK_TST_DIS_MASK, MT6351_PMIC_RG_RTC26M_CK_TST_DIS_SHIFT}, + {PMIC_RG_VOW12M_CK_TST_DIS, MT6351_PMIC_RG_VOW12M_CK_TST_DIS_ADDR, + MT6351_PMIC_RG_VOW12M_CK_TST_DIS_MASK, MT6351_PMIC_RG_VOW12M_CK_TST_DIS_SHIFT}, + {PMIC_TOP_CKTST_CON0_RSV, MT6351_PMIC_TOP_CKTST_CON0_RSV_ADDR, + MT6351_PMIC_TOP_CKTST_CON0_RSV_MASK, MT6351_PMIC_TOP_CKTST_CON0_RSV_SHIFT}, + {PMIC_RG_BUCK_ANA_AUTO_OFF_DIS, MT6351_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_ADDR, + MT6351_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_MASK, MT6351_PMIC_RG_BUCK_ANA_AUTO_OFF_DIS_SHIFT}, + {PMIC_RG_DRV_ISINK0_CK_TSTSEL, MT6351_PMIC_RG_DRV_ISINK0_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK0_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_ISINK0_CK_TSTSEL_SHIFT}, + {PMIC_RG_DRV_ISINK1_CK_TSTSEL, MT6351_PMIC_RG_DRV_ISINK1_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK1_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_ISINK1_CK_TSTSEL_SHIFT}, + {PMIC_RG_DRV_ISINK2_CK_TSTSEL, MT6351_PMIC_RG_DRV_ISINK2_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK2_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_ISINK2_CK_TSTSEL_SHIFT}, + {PMIC_RG_DRV_ISINK3_CK_TSTSEL, MT6351_PMIC_RG_DRV_ISINK3_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK3_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_ISINK3_CK_TSTSEL_SHIFT}, + {PMIC_RG_FQMTR_CK_TSTSEL, MT6351_PMIC_RG_FQMTR_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_FQMTR_CK_TSTSEL_MASK, MT6351_PMIC_RG_FQMTR_CK_TSTSEL_SHIFT}, + {PMIC_RG_RTCDET_CK_TSTSEL, MT6351_PMIC_RG_RTCDET_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_RTCDET_CK_TSTSEL_MASK, MT6351_PMIC_RG_RTCDET_CK_TSTSEL_SHIFT}, + {PMIC_RG_PMU75K_CK_TSTSEL, MT6351_PMIC_RG_PMU75K_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_PMU75K_CK_TSTSEL_MASK, MT6351_PMIC_RG_PMU75K_CK_TSTSEL_SHIFT}, + {PMIC_RG_SMPS_CK_TSTSEL, MT6351_PMIC_RG_SMPS_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_SMPS_CK_TSTSEL_MASK, MT6351_PMIC_RG_SMPS_CK_TSTSEL_SHIFT}, + {PMIC_RG_AUD26M_CK_TSTSEL, MT6351_PMIC_RG_AUD26M_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_AUD26M_CK_TSTSEL_MASK, MT6351_PMIC_RG_AUD26M_CK_TSTSEL_SHIFT}, + {PMIC_RG_AUDIF_CK_TSTSEL, MT6351_PMIC_RG_AUDIF_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_AUDIF_CK_TSTSEL_MASK, MT6351_PMIC_RG_AUDIF_CK_TSTSEL_SHIFT}, + {PMIC_RG_AUD_CK_TSTSEL, MT6351_PMIC_RG_AUD_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_AUD_CK_TSTSEL_MASK, MT6351_PMIC_RG_AUD_CK_TSTSEL_SHIFT}, + {PMIC_RG_STRUP_75K_CK_TSTSEL, MT6351_PMIC_RG_STRUP_75K_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_STRUP_75K_CK_TSTSEL_MASK, MT6351_PMIC_RG_STRUP_75K_CK_TSTSEL_SHIFT}, + {PMIC_RG_RTC32K_CK_TSTSEL, MT6351_PMIC_RG_RTC32K_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_RTC32K_CK_TSTSEL_MASK, MT6351_PMIC_RG_RTC32K_CK_TSTSEL_SHIFT}, + {PMIC_RG_PCHR_TEST_CK_TSTSEL, MT6351_PMIC_RG_PCHR_TEST_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_PCHR_TEST_CK_TSTSEL_MASK, MT6351_PMIC_RG_PCHR_TEST_CK_TSTSEL_SHIFT}, + {PMIC_RG_BGR_TEST_CK_TSTSEL, MT6351_PMIC_RG_BGR_TEST_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_BGR_TEST_CK_TSTSEL_MASK, MT6351_PMIC_RG_BGR_TEST_CK_TSTSEL_SHIFT}, + {PMIC_RG_FG_CK_TSTSEL, MT6351_PMIC_RG_FG_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_FG_CK_TSTSEL_MASK, MT6351_PMIC_RG_FG_CK_TSTSEL_SHIFT}, + {PMIC_RG_FGADC_ANA_CK_TSTSEL, MT6351_PMIC_RG_FGADC_ANA_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_FGADC_ANA_CK_TSTSEL_MASK, MT6351_PMIC_RG_FGADC_ANA_CK_TSTSEL_SHIFT}, + {PMIC_RG_RTC26M_CK_TSTSEL, MT6351_PMIC_RG_RTC26M_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_RTC26M_CK_TSTSEL_MASK, MT6351_PMIC_RG_RTC26M_CK_TSTSEL_SHIFT}, + {PMIC_RG_RTC_EOSC32_CK_TSTSEL, MT6351_PMIC_RG_RTC_EOSC32_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_RTC_EOSC32_CK_TSTSEL_MASK, MT6351_PMIC_RG_RTC_EOSC32_CK_TSTSEL_SHIFT}, + {PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL, MT6351_PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL_MASK, + MT6351_PMIC_RG_EOSC_CALI_TEST_CK_TSTSEL_SHIFT}, + {PMIC_RG_AUXADC_CK_TSTSEL, MT6351_PMIC_RG_AUXADC_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_AUXADC_CK_TSTSEL_MASK, MT6351_PMIC_RG_AUXADC_CK_TSTSEL_SHIFT}, + {PMIC_RG_AUXADC_SMPS_CK_TSTSEL, MT6351_PMIC_RG_AUXADC_SMPS_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_AUXADC_SMPS_CK_TSTSEL_MASK, MT6351_PMIC_RG_AUXADC_SMPS_CK_TSTSEL_SHIFT}, + {PMIC_RG_AUXADC_26M_CK_TSTSEL, MT6351_PMIC_RG_AUXADC_26M_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_AUXADC_26M_CK_TSTSEL_MASK, MT6351_PMIC_RG_AUXADC_26M_CK_TSTSEL_SHIFT}, + {PMIC_RG_VOW12M_CK_TSTSEL, MT6351_PMIC_RG_VOW12M_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_VOW12M_CK_TSTSEL_MASK, MT6351_PMIC_RG_VOW12M_CK_TSTSEL_SHIFT}, + {PMIC_RG_DRV_ISINK4_CK_TSTSEL, MT6351_PMIC_RG_DRV_ISINK4_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK4_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_ISINK4_CK_TSTSEL_SHIFT}, + {PMIC_RG_DRV_ISINK5_CK_TSTSEL, MT6351_PMIC_RG_DRV_ISINK5_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK5_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_ISINK5_CK_TSTSEL_SHIFT}, + {PMIC_RG_DRV_ISINK6_CK_TSTSEL, MT6351_PMIC_RG_DRV_ISINK6_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK6_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_ISINK6_CK_TSTSEL_SHIFT}, + {PMIC_RG_DRV_ISINK7_CK_TSTSEL, MT6351_PMIC_RG_DRV_ISINK7_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_ISINK7_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_ISINK7_CK_TSTSEL_SHIFT}, + {PMIC_RG_DRV_CHRIND_CK_TSTSEL, MT6351_PMIC_RG_DRV_CHRIND_CK_TSTSEL_ADDR, + MT6351_PMIC_RG_DRV_CHRIND_CK_TSTSEL_MASK, MT6351_PMIC_RG_DRV_CHRIND_CK_TSTSEL_SHIFT}, + {PMIC_TOP_CKTST_CON2_RSV, MT6351_PMIC_TOP_CKTST_CON2_RSV_ADDR, + MT6351_PMIC_TOP_CKTST_CON2_RSV_MASK, MT6351_PMIC_TOP_CKTST_CON2_RSV_SHIFT}, + {PMIC_RG_CLKSQ_EN_AUD, MT6351_PMIC_RG_CLKSQ_EN_AUD_ADDR, + MT6351_PMIC_RG_CLKSQ_EN_AUD_MASK, MT6351_PMIC_RG_CLKSQ_EN_AUD_SHIFT}, + {PMIC_RG_CLKSQ_EN_FQR, MT6351_PMIC_RG_CLKSQ_EN_FQR_ADDR, + MT6351_PMIC_RG_CLKSQ_EN_FQR_MASK, MT6351_PMIC_RG_CLKSQ_EN_FQR_SHIFT}, + {PMIC_RG_CLKSQ_EN_AUX_AP, MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_ADDR, + MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MASK, MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_SHIFT}, + {PMIC_RG_CLKSQ_EN_AUX_MD, MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_ADDR, + MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MASK, MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_SHIFT}, + {PMIC_RG_CLKSQ_EN_AUX_GPS, MT6351_PMIC_RG_CLKSQ_EN_AUX_GPS_ADDR, + MT6351_PMIC_RG_CLKSQ_EN_AUX_GPS_MASK, MT6351_PMIC_RG_CLKSQ_EN_AUX_GPS_SHIFT}, + {PMIC_RG_CLKSQ_EN_AUX_RSV, MT6351_PMIC_RG_CLKSQ_EN_AUX_RSV_ADDR, + MT6351_PMIC_RG_CLKSQ_EN_AUX_RSV_MASK, MT6351_PMIC_RG_CLKSQ_EN_AUX_RSV_SHIFT}, + {PMIC_RG_CLKSQ_EN_AUX_AP_MODE, MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MODE_ADDR, + MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MODE_MASK, MT6351_PMIC_RG_CLKSQ_EN_AUX_AP_MODE_SHIFT}, + {PMIC_RG_CLKSQ_EN_AUX_MD_MODE, MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MODE_ADDR, + MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MODE_MASK, MT6351_PMIC_RG_CLKSQ_EN_AUX_MD_MODE_SHIFT}, + {PMIC_RG_CLKSQ_IN_SEL_VA18, MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_ADDR, + MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_MASK, MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SHIFT}, + {PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL, MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_ADDR, + MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_MASK, + MT6351_PMIC_RG_CLKSQ_IN_SEL_VA18_SWCTRL_SHIFT}, + {PMIC_TOP_CLKSQ_RSV, MT6351_PMIC_TOP_CLKSQ_RSV_ADDR, + MT6351_PMIC_TOP_CLKSQ_RSV_MASK, MT6351_PMIC_TOP_CLKSQ_RSV_SHIFT}, + {PMIC_DA_CLKSQ_EN_VA18, MT6351_PMIC_DA_CLKSQ_EN_VA18_ADDR, + MT6351_PMIC_DA_CLKSQ_EN_VA18_MASK, MT6351_PMIC_DA_CLKSQ_EN_VA18_SHIFT}, + {PMIC_TOP_CLKSQ_SET, MT6351_PMIC_TOP_CLKSQ_SET_ADDR, + MT6351_PMIC_TOP_CLKSQ_SET_MASK, MT6351_PMIC_TOP_CLKSQ_SET_SHIFT}, + {PMIC_TOP_CLKSQ_CLR, MT6351_PMIC_TOP_CLKSQ_CLR_ADDR, + MT6351_PMIC_TOP_CLKSQ_CLR_MASK, MT6351_PMIC_TOP_CLKSQ_CLR_SHIFT}, + {PMIC_RG_CLKSQ_RTC_EN, MT6351_PMIC_RG_CLKSQ_RTC_EN_ADDR, + MT6351_PMIC_RG_CLKSQ_RTC_EN_MASK, MT6351_PMIC_RG_CLKSQ_RTC_EN_SHIFT}, + {PMIC_RG_CLKSQ_RTC_EN_HW_MODE, MT6351_PMIC_RG_CLKSQ_RTC_EN_HW_MODE_ADDR, + MT6351_PMIC_RG_CLKSQ_RTC_EN_HW_MODE_MASK, MT6351_PMIC_RG_CLKSQ_RTC_EN_HW_MODE_SHIFT}, + {PMIC_TOP_CLKSQ_RTC_RSV0, MT6351_PMIC_TOP_CLKSQ_RTC_RSV0_ADDR, + MT6351_PMIC_TOP_CLKSQ_RTC_RSV0_MASK, MT6351_PMIC_TOP_CLKSQ_RTC_RSV0_SHIFT}, + {PMIC_RG_ENBB_SEL, MT6351_PMIC_RG_ENBB_SEL_ADDR, MT6351_PMIC_RG_ENBB_SEL_MASK, + MT6351_PMIC_RG_ENBB_SEL_SHIFT}, + {PMIC_RG_XOSC_EN_SEL, MT6351_PMIC_RG_XOSC_EN_SEL_ADDR, + MT6351_PMIC_RG_XOSC_EN_SEL_MASK, MT6351_PMIC_RG_XOSC_EN_SEL_SHIFT}, + {PMIC_TOP_CLKSQ_RTC_RSV1, MT6351_PMIC_TOP_CLKSQ_RTC_RSV1_ADDR, + MT6351_PMIC_TOP_CLKSQ_RTC_RSV1_MASK, MT6351_PMIC_TOP_CLKSQ_RTC_RSV1_SHIFT}, + {PMIC_DA_CLKSQ_EN_VDIG18, MT6351_PMIC_DA_CLKSQ_EN_VDIG18_ADDR, + MT6351_PMIC_DA_CLKSQ_EN_VDIG18_MASK, MT6351_PMIC_DA_CLKSQ_EN_VDIG18_SHIFT}, + {PMIC_TOP_CLKSQ_RTC_SET, MT6351_PMIC_TOP_CLKSQ_RTC_SET_ADDR, + MT6351_PMIC_TOP_CLKSQ_RTC_SET_MASK, MT6351_PMIC_TOP_CLKSQ_RTC_SET_SHIFT}, + {PMIC_TOP_CLKSQ_RTC_CLR, MT6351_PMIC_TOP_CLKSQ_RTC_CLR_ADDR, + MT6351_PMIC_TOP_CLKSQ_RTC_CLR_MASK, MT6351_PMIC_TOP_CLKSQ_RTC_CLR_SHIFT}, + {PMIC_OSC_75K_TRIM, MT6351_PMIC_OSC_75K_TRIM_ADDR, MT6351_PMIC_OSC_75K_TRIM_MASK, + MT6351_PMIC_OSC_75K_TRIM_SHIFT}, + {PMIC_RG_OSC_75K_TRIM_EN, MT6351_PMIC_RG_OSC_75K_TRIM_EN_ADDR, + MT6351_PMIC_RG_OSC_75K_TRIM_EN_MASK, MT6351_PMIC_RG_OSC_75K_TRIM_EN_SHIFT}, + {PMIC_RG_OSC_75K_TRIM_RATE, MT6351_PMIC_RG_OSC_75K_TRIM_RATE_ADDR, + MT6351_PMIC_RG_OSC_75K_TRIM_RATE_MASK, MT6351_PMIC_RG_OSC_75K_TRIM_RATE_SHIFT}, + {PMIC_DA_OSC_75K_TRIM, MT6351_PMIC_DA_OSC_75K_TRIM_ADDR, + MT6351_PMIC_DA_OSC_75K_TRIM_MASK, MT6351_PMIC_DA_OSC_75K_TRIM_SHIFT}, + {PMIC_RG_EFUSE_MAN_RST, MT6351_PMIC_RG_EFUSE_MAN_RST_ADDR, + MT6351_PMIC_RG_EFUSE_MAN_RST_MASK, MT6351_PMIC_RG_EFUSE_MAN_RST_SHIFT}, + {PMIC_RG_AUXADC_RST, MT6351_PMIC_RG_AUXADC_RST_ADDR, + MT6351_PMIC_RG_AUXADC_RST_MASK, MT6351_PMIC_RG_AUXADC_RST_SHIFT}, + {PMIC_RG_AUXADC_REG_RST, MT6351_PMIC_RG_AUXADC_REG_RST_ADDR, + MT6351_PMIC_RG_AUXADC_REG_RST_MASK, MT6351_PMIC_RG_AUXADC_REG_RST_SHIFT}, + {PMIC_RG_AUDIO_RST, MT6351_PMIC_RG_AUDIO_RST_ADDR, MT6351_PMIC_RG_AUDIO_RST_MASK, + MT6351_PMIC_RG_AUDIO_RST_SHIFT}, + {PMIC_RG_ACCDET_RST, MT6351_PMIC_RG_ACCDET_RST_ADDR, + MT6351_PMIC_RG_ACCDET_RST_MASK, MT6351_PMIC_RG_ACCDET_RST_SHIFT}, + {PMIC_RG_BIF_RST, MT6351_PMIC_RG_BIF_RST_ADDR, MT6351_PMIC_RG_BIF_RST_MASK, + MT6351_PMIC_RG_BIF_RST_SHIFT}, + {PMIC_RG_DRIVER_RST, MT6351_PMIC_RG_DRIVER_RST_ADDR, + MT6351_PMIC_RG_DRIVER_RST_MASK, MT6351_PMIC_RG_DRIVER_RST_SHIFT}, + {PMIC_RG_FGADC_RST, MT6351_PMIC_RG_FGADC_RST_ADDR, MT6351_PMIC_RG_FGADC_RST_MASK, + MT6351_PMIC_RG_FGADC_RST_SHIFT}, + {PMIC_RG_FQMTR_RST, MT6351_PMIC_RG_FQMTR_RST_ADDR, MT6351_PMIC_RG_FQMTR_RST_MASK, + MT6351_PMIC_RG_FQMTR_RST_SHIFT}, + {PMIC_RG_RTC_RST, MT6351_PMIC_RG_RTC_RST_ADDR, MT6351_PMIC_RG_RTC_RST_MASK, + MT6351_PMIC_RG_RTC_RST_SHIFT}, + {PMIC_RG_CHRWDT_RST, MT6351_PMIC_RG_CHRWDT_RST_ADDR, + MT6351_PMIC_RG_CHRWDT_RST_MASK, MT6351_PMIC_RG_CHRWDT_RST_SHIFT}, + {PMIC_RG_ZCD_RST, MT6351_PMIC_RG_ZCD_RST_ADDR, MT6351_PMIC_RG_ZCD_RST_MASK, + MT6351_PMIC_RG_ZCD_RST_SHIFT}, + {PMIC_RG_AUDNCP_RST, MT6351_PMIC_RG_AUDNCP_RST_ADDR, + MT6351_PMIC_RG_AUDNCP_RST_MASK, MT6351_PMIC_RG_AUDNCP_RST_SHIFT}, + {PMIC_RG_CLK_TRIM_RST, MT6351_PMIC_RG_CLK_TRIM_RST_ADDR, + MT6351_PMIC_RG_CLK_TRIM_RST_MASK, MT6351_PMIC_RG_CLK_TRIM_RST_SHIFT}, + {PMIC_RG_LDO_CALI_RST, MT6351_PMIC_RG_LDO_CALI_RST_ADDR, + MT6351_PMIC_RG_LDO_CALI_RST_MASK, MT6351_PMIC_RG_LDO_CALI_RST_SHIFT}, + {PMIC_TOP_RST_CON0_SET, MT6351_PMIC_TOP_RST_CON0_SET_ADDR, + MT6351_PMIC_TOP_RST_CON0_SET_MASK, MT6351_PMIC_TOP_RST_CON0_SET_SHIFT}, + {PMIC_TOP_RST_CON0_CLR, MT6351_PMIC_TOP_RST_CON0_CLR_ADDR, + MT6351_PMIC_TOP_RST_CON0_CLR_MASK, MT6351_PMIC_TOP_RST_CON0_CLR_SHIFT}, + {PMIC_RG_STRUP_LONG_PRESS_RST, MT6351_PMIC_RG_STRUP_LONG_PRESS_RST_ADDR, + MT6351_PMIC_RG_STRUP_LONG_PRESS_RST_MASK, MT6351_PMIC_RG_STRUP_LONG_PRESS_RST_SHIFT}, + {PMIC_TOP_RST_CON1_RSV, MT6351_PMIC_TOP_RST_CON1_RSV_ADDR, + MT6351_PMIC_TOP_RST_CON1_RSV_MASK, MT6351_PMIC_TOP_RST_CON1_RSV_SHIFT}, + {PMIC_TOP_RST_CON1_SET, MT6351_PMIC_TOP_RST_CON1_SET_ADDR, + MT6351_PMIC_TOP_RST_CON1_SET_MASK, MT6351_PMIC_TOP_RST_CON1_SET_SHIFT}, + {PMIC_TOP_RST_CON1_CLR, MT6351_PMIC_TOP_RST_CON1_CLR_ADDR, + MT6351_PMIC_TOP_RST_CON1_CLR_MASK, MT6351_PMIC_TOP_RST_CON1_CLR_SHIFT}, + {PMIC_RG_CHR_LDO_DET_MODE, MT6351_PMIC_RG_CHR_LDO_DET_MODE_ADDR, + MT6351_PMIC_RG_CHR_LDO_DET_MODE_MASK, MT6351_PMIC_RG_CHR_LDO_DET_MODE_SHIFT}, + {PMIC_RG_CHR_LDO_DET_SW, MT6351_PMIC_RG_CHR_LDO_DET_SW_ADDR, + MT6351_PMIC_RG_CHR_LDO_DET_SW_MASK, MT6351_PMIC_RG_CHR_LDO_DET_SW_SHIFT}, + {PMIC_RG_CHRWDT_FLAG_MODE, MT6351_PMIC_RG_CHRWDT_FLAG_MODE_ADDR, + MT6351_PMIC_RG_CHRWDT_FLAG_MODE_MASK, MT6351_PMIC_RG_CHRWDT_FLAG_MODE_SHIFT}, + {PMIC_RG_CHRWDT_FLAG_SW, MT6351_PMIC_RG_CHRWDT_FLAG_SW_ADDR, + MT6351_PMIC_RG_CHRWDT_FLAG_SW_MASK, MT6351_PMIC_RG_CHRWDT_FLAG_SW_SHIFT}, + {PMIC_TOP_RST_CON2_RSV, MT6351_PMIC_TOP_RST_CON2_RSV_ADDR, + MT6351_PMIC_TOP_RST_CON2_RSV_MASK, MT6351_PMIC_TOP_RST_CON2_RSV_SHIFT}, + {PMIC_RG_WDTRSTB_EN, MT6351_PMIC_RG_WDTRSTB_EN_ADDR, + MT6351_PMIC_RG_WDTRSTB_EN_MASK, MT6351_PMIC_RG_WDTRSTB_EN_SHIFT}, + {PMIC_RG_WDTRSTB_MODE, MT6351_PMIC_RG_WDTRSTB_MODE_ADDR, + MT6351_PMIC_RG_WDTRSTB_MODE_MASK, MT6351_PMIC_RG_WDTRSTB_MODE_SHIFT}, + {PMIC_WDTRSTB_STATUS, MT6351_PMIC_WDTRSTB_STATUS_ADDR, + MT6351_PMIC_WDTRSTB_STATUS_MASK, MT6351_PMIC_WDTRSTB_STATUS_SHIFT}, + {PMIC_WDTRSTB_STATUS_CLR, MT6351_PMIC_WDTRSTB_STATUS_CLR_ADDR, + MT6351_PMIC_WDTRSTB_STATUS_CLR_MASK, MT6351_PMIC_WDTRSTB_STATUS_CLR_SHIFT}, + {PMIC_RG_WDTRSTB_FB_EN, MT6351_PMIC_RG_WDTRSTB_FB_EN_ADDR, + MT6351_PMIC_RG_WDTRSTB_FB_EN_MASK, MT6351_PMIC_RG_WDTRSTB_FB_EN_SHIFT}, + {PMIC_RG_WDTRSTB_DEB, MT6351_PMIC_RG_WDTRSTB_DEB_ADDR, + MT6351_PMIC_RG_WDTRSTB_DEB_MASK, MT6351_PMIC_RG_WDTRSTB_DEB_SHIFT}, + {PMIC_RG_HOMEKEY_RST_EN, MT6351_PMIC_RG_HOMEKEY_RST_EN_ADDR, + MT6351_PMIC_RG_HOMEKEY_RST_EN_MASK, MT6351_PMIC_RG_HOMEKEY_RST_EN_SHIFT}, + {PMIC_RG_PWRKEY_RST_EN, MT6351_PMIC_RG_PWRKEY_RST_EN_ADDR, + MT6351_PMIC_RG_PWRKEY_RST_EN_MASK, MT6351_PMIC_RG_PWRKEY_RST_EN_SHIFT}, + {PMIC_RG_PWRRST_TMR_DIS, MT6351_PMIC_RG_PWRRST_TMR_DIS_ADDR, + MT6351_PMIC_RG_PWRRST_TMR_DIS_MASK, MT6351_PMIC_RG_PWRRST_TMR_DIS_SHIFT}, + {PMIC_RG_PWRKEY_RST_TD, MT6351_PMIC_RG_PWRKEY_RST_TD_ADDR, + MT6351_PMIC_RG_PWRKEY_RST_TD_MASK, MT6351_PMIC_RG_PWRKEY_RST_TD_SHIFT}, + {PMIC_TOP_RST_MISC_RSV, MT6351_PMIC_TOP_RST_MISC_RSV_ADDR, + MT6351_PMIC_TOP_RST_MISC_RSV_MASK, MT6351_PMIC_TOP_RST_MISC_RSV_SHIFT}, + {PMIC_TOP_RST_MISC_SET, MT6351_PMIC_TOP_RST_MISC_SET_ADDR, + MT6351_PMIC_TOP_RST_MISC_SET_MASK, MT6351_PMIC_TOP_RST_MISC_SET_SHIFT}, + {PMIC_TOP_RST_MISC_CLR, MT6351_PMIC_TOP_RST_MISC_CLR_ADDR, + MT6351_PMIC_TOP_RST_MISC_CLR_MASK, MT6351_PMIC_TOP_RST_MISC_CLR_SHIFT}, + {PMIC_VPWRIN_RSTB_STATUS, MT6351_PMIC_VPWRIN_RSTB_STATUS_ADDR, + MT6351_PMIC_VPWRIN_RSTB_STATUS_MASK, MT6351_PMIC_VPWRIN_RSTB_STATUS_SHIFT}, + {PMIC_DDLO_RSTB_STATUS, MT6351_PMIC_DDLO_RSTB_STATUS_ADDR, + MT6351_PMIC_DDLO_RSTB_STATUS_MASK, MT6351_PMIC_DDLO_RSTB_STATUS_SHIFT}, + {PMIC_UVLO_RSTB_STATUS, MT6351_PMIC_UVLO_RSTB_STATUS_ADDR, + MT6351_PMIC_UVLO_RSTB_STATUS_MASK, MT6351_PMIC_UVLO_RSTB_STATUS_SHIFT}, + {PMIC_RTC_DDLO_RSTB_STATUS, MT6351_PMIC_RTC_DDLO_RSTB_STATUS_ADDR, + MT6351_PMIC_RTC_DDLO_RSTB_STATUS_MASK, MT6351_PMIC_RTC_DDLO_RSTB_STATUS_SHIFT}, + {PMIC_CHRWDT_REG_RSTB_STATUS, MT6351_PMIC_CHRWDT_REG_RSTB_STATUS_ADDR, + MT6351_PMIC_CHRWDT_REG_RSTB_STATUS_MASK, MT6351_PMIC_CHRWDT_REG_RSTB_STATUS_SHIFT}, + {PMIC_CHRDET_REG_RSTB_STATUS, MT6351_PMIC_CHRDET_REG_RSTB_STATUS_ADDR, + MT6351_PMIC_CHRDET_REG_RSTB_STATUS_MASK, MT6351_PMIC_CHRDET_REG_RSTB_STATUS_SHIFT}, + {PMIC_TOP_RST_STATUS_RSV, MT6351_PMIC_TOP_RST_STATUS_RSV_ADDR, + MT6351_PMIC_TOP_RST_STATUS_RSV_MASK, MT6351_PMIC_TOP_RST_STATUS_RSV_SHIFT}, + {PMIC_TOP_RST_STATUS_SET, MT6351_PMIC_TOP_RST_STATUS_SET_ADDR, + MT6351_PMIC_TOP_RST_STATUS_SET_MASK, MT6351_PMIC_TOP_RST_STATUS_SET_SHIFT}, + {PMIC_TOP_RST_STATUS_CLR, MT6351_PMIC_TOP_RST_STATUS_CLR_ADDR, + MT6351_PMIC_TOP_RST_STATUS_CLR_MASK, MT6351_PMIC_TOP_RST_STATUS_CLR_SHIFT}, + {PMIC_RG_INT_EN_PWRKEY, MT6351_PMIC_RG_INT_EN_PWRKEY_ADDR, + MT6351_PMIC_RG_INT_EN_PWRKEY_MASK, MT6351_PMIC_RG_INT_EN_PWRKEY_SHIFT}, + {PMIC_RG_INT_EN_HOMEKEY, MT6351_PMIC_RG_INT_EN_HOMEKEY_ADDR, + MT6351_PMIC_RG_INT_EN_HOMEKEY_MASK, MT6351_PMIC_RG_INT_EN_HOMEKEY_SHIFT}, + {PMIC_RG_INT_EN_PWRKEY_R, MT6351_PMIC_RG_INT_EN_PWRKEY_R_ADDR, + MT6351_PMIC_RG_INT_EN_PWRKEY_R_MASK, MT6351_PMIC_RG_INT_EN_PWRKEY_R_SHIFT}, + {PMIC_RG_INT_EN_HOMEKEY_R, MT6351_PMIC_RG_INT_EN_HOMEKEY_R_ADDR, + MT6351_PMIC_RG_INT_EN_HOMEKEY_R_MASK, MT6351_PMIC_RG_INT_EN_HOMEKEY_R_SHIFT}, + {PMIC_RG_INT_EN_THR_H, MT6351_PMIC_RG_INT_EN_THR_H_ADDR, + MT6351_PMIC_RG_INT_EN_THR_H_MASK, MT6351_PMIC_RG_INT_EN_THR_H_SHIFT}, + {PMIC_RG_INT_EN_THR_L, MT6351_PMIC_RG_INT_EN_THR_L_ADDR, + MT6351_PMIC_RG_INT_EN_THR_L_MASK, MT6351_PMIC_RG_INT_EN_THR_L_SHIFT}, + {PMIC_RG_INT_EN_BAT_H, MT6351_PMIC_RG_INT_EN_BAT_H_ADDR, + MT6351_PMIC_RG_INT_EN_BAT_H_MASK, MT6351_PMIC_RG_INT_EN_BAT_H_SHIFT}, + {PMIC_RG_INT_EN_BAT_L, MT6351_PMIC_RG_INT_EN_BAT_L_ADDR, + MT6351_PMIC_RG_INT_EN_BAT_L_MASK, MT6351_PMIC_RG_INT_EN_BAT_L_SHIFT}, + {PMIC_RG_INT_EN_RTC, MT6351_PMIC_RG_INT_EN_RTC_ADDR, + MT6351_PMIC_RG_INT_EN_RTC_MASK, MT6351_PMIC_RG_INT_EN_RTC_SHIFT}, + {PMIC_RG_INT_EN_AUDIO, MT6351_PMIC_RG_INT_EN_AUDIO_ADDR, + MT6351_PMIC_RG_INT_EN_AUDIO_MASK, MT6351_PMIC_RG_INT_EN_AUDIO_SHIFT}, + {PMIC_RG_INT_EN_MAD, MT6351_PMIC_RG_INT_EN_MAD_ADDR, + MT6351_PMIC_RG_INT_EN_MAD_MASK, MT6351_PMIC_RG_INT_EN_MAD_SHIFT}, + {PMIC_RG_INT_EN_ACCDET, MT6351_PMIC_RG_INT_EN_ACCDET_ADDR, + MT6351_PMIC_RG_INT_EN_ACCDET_MASK, MT6351_PMIC_RG_INT_EN_ACCDET_SHIFT}, + {PMIC_RG_INT_EN_ACCDET_EINT, MT6351_PMIC_RG_INT_EN_ACCDET_EINT_ADDR, + MT6351_PMIC_RG_INT_EN_ACCDET_EINT_MASK, MT6351_PMIC_RG_INT_EN_ACCDET_EINT_SHIFT}, + {PMIC_RG_INT_EN_ACCDET_NEGV, MT6351_PMIC_RG_INT_EN_ACCDET_NEGV_ADDR, + MT6351_PMIC_RG_INT_EN_ACCDET_NEGV_MASK, MT6351_PMIC_RG_INT_EN_ACCDET_NEGV_SHIFT}, + {PMIC_RG_INT_EN_NI_LBAT_INT, MT6351_PMIC_RG_INT_EN_NI_LBAT_INT_ADDR, + MT6351_PMIC_RG_INT_EN_NI_LBAT_INT_MASK, MT6351_PMIC_RG_INT_EN_NI_LBAT_INT_SHIFT}, + {PMIC_INT_CON0_SET, MT6351_PMIC_INT_CON0_SET_ADDR, MT6351_PMIC_INT_CON0_SET_MASK, + MT6351_PMIC_INT_CON0_SET_SHIFT}, + {PMIC_INT_CON0_CLR, MT6351_PMIC_INT_CON0_CLR_ADDR, MT6351_PMIC_INT_CON0_CLR_MASK, + MT6351_PMIC_INT_CON0_CLR_SHIFT}, + {PMIC_RG_INT_EN_VCORE_OC, MT6351_PMIC_RG_INT_EN_VCORE_OC_ADDR, + MT6351_PMIC_RG_INT_EN_VCORE_OC_MASK, MT6351_PMIC_RG_INT_EN_VCORE_OC_SHIFT}, + {PMIC_RG_INT_EN_VGPU_OC, MT6351_PMIC_RG_INT_EN_VGPU_OC_ADDR, + MT6351_PMIC_RG_INT_EN_VGPU_OC_MASK, MT6351_PMIC_RG_INT_EN_VGPU_OC_SHIFT}, + {PMIC_RG_INT_EN_VSRAM_MD_OC, MT6351_PMIC_RG_INT_EN_VSRAM_MD_OC_ADDR, + MT6351_PMIC_RG_INT_EN_VSRAM_MD_OC_MASK, MT6351_PMIC_RG_INT_EN_VSRAM_MD_OC_SHIFT}, + {PMIC_RG_INT_EN_VMODEM_OC, MT6351_PMIC_RG_INT_EN_VMODEM_OC_ADDR, + MT6351_PMIC_RG_INT_EN_VMODEM_OC_MASK, MT6351_PMIC_RG_INT_EN_VMODEM_OC_SHIFT}, + {PMIC_RG_INT_EN_VM1_OC, MT6351_PMIC_RG_INT_EN_VM1_OC_ADDR, + MT6351_PMIC_RG_INT_EN_VM1_OC_MASK, MT6351_PMIC_RG_INT_EN_VM1_OC_SHIFT}, + {PMIC_RG_INT_EN_VS1_OC, MT6351_PMIC_RG_INT_EN_VS1_OC_ADDR, + MT6351_PMIC_RG_INT_EN_VS1_OC_MASK, MT6351_PMIC_RG_INT_EN_VS1_OC_SHIFT}, + {PMIC_RG_INT_EN_VS2_OC, MT6351_PMIC_RG_INT_EN_VS2_OC_ADDR, + MT6351_PMIC_RG_INT_EN_VS2_OC_MASK, MT6351_PMIC_RG_INT_EN_VS2_OC_SHIFT}, + {PMIC_RG_INT_EN_VPA_OC, MT6351_PMIC_RG_INT_EN_VPA_OC_ADDR, + MT6351_PMIC_RG_INT_EN_VPA_OC_MASK, MT6351_PMIC_RG_INT_EN_VPA_OC_SHIFT}, + {PMIC_RG_INT_EN_VCORE_PREOC, MT6351_PMIC_RG_INT_EN_VCORE_PREOC_ADDR, + MT6351_PMIC_RG_INT_EN_VCORE_PREOC_MASK, MT6351_PMIC_RG_INT_EN_VCORE_PREOC_SHIFT}, + {PMIC_RG_INT_EN_VGPU_PREOC, MT6351_PMIC_RG_INT_EN_VGPU_PREOC_ADDR, + MT6351_PMIC_RG_INT_EN_VGPU_PREOC_MASK, MT6351_PMIC_RG_INT_EN_VGPU_PREOC_SHIFT}, + {PMIC_RG_INT_EN_VSRAM_MD_PREOC, MT6351_PMIC_RG_INT_EN_VSRAM_MD_PREOC_ADDR, + MT6351_PMIC_RG_INT_EN_VSRAM_MD_PREOC_MASK, MT6351_PMIC_RG_INT_EN_VSRAM_MD_PREOC_SHIFT}, + {PMIC_RG_INT_EN_VMODEM_PREOC, MT6351_PMIC_RG_INT_EN_VMODEM_PREOC_ADDR, + MT6351_PMIC_RG_INT_EN_VMODEM_PREOC_MASK, MT6351_PMIC_RG_INT_EN_VMODEM_PREOC_SHIFT}, + {PMIC_RG_INT_EN_VM1_PREOC, MT6351_PMIC_RG_INT_EN_VM1_PREOC_ADDR, + MT6351_PMIC_RG_INT_EN_VM1_PREOC_MASK, MT6351_PMIC_RG_INT_EN_VM1_PREOC_SHIFT}, + {PMIC_RG_INT_EN_VS1_PREOC, MT6351_PMIC_RG_INT_EN_VS1_PREOC_ADDR, + MT6351_PMIC_RG_INT_EN_VS1_PREOC_MASK, MT6351_PMIC_RG_INT_EN_VS1_PREOC_SHIFT}, + {PMIC_RG_INT_EN_VS2_PREOC, MT6351_PMIC_RG_INT_EN_VS2_PREOC_ADDR, + MT6351_PMIC_RG_INT_EN_VS2_PREOC_MASK, MT6351_PMIC_RG_INT_EN_VS2_PREOC_SHIFT}, + {PMIC_RG_INT_EN_LDO_OC, MT6351_PMIC_RG_INT_EN_LDO_OC_ADDR, + MT6351_PMIC_RG_INT_EN_LDO_OC_MASK, MT6351_PMIC_RG_INT_EN_LDO_OC_SHIFT}, + {PMIC_INT_CON1_SET, MT6351_PMIC_INT_CON1_SET_ADDR, MT6351_PMIC_INT_CON1_SET_MASK, + MT6351_PMIC_INT_CON1_SET_SHIFT}, + {PMIC_INT_CON1_CLR, MT6351_PMIC_INT_CON1_CLR_ADDR, MT6351_PMIC_INT_CON1_CLR_MASK, + MT6351_PMIC_INT_CON1_CLR_SHIFT}, + {PMIC_RG_INT_EN_JEITA_HOT, MT6351_PMIC_RG_INT_EN_JEITA_HOT_ADDR, + MT6351_PMIC_RG_INT_EN_JEITA_HOT_MASK, MT6351_PMIC_RG_INT_EN_JEITA_HOT_SHIFT}, + {PMIC_RG_INT_EN_JEITA_WARM, MT6351_PMIC_RG_INT_EN_JEITA_WARM_ADDR, + MT6351_PMIC_RG_INT_EN_JEITA_WARM_MASK, MT6351_PMIC_RG_INT_EN_JEITA_WARM_SHIFT}, + {PMIC_RG_INT_EN_JEITA_COOL, MT6351_PMIC_RG_INT_EN_JEITA_COOL_ADDR, + MT6351_PMIC_RG_INT_EN_JEITA_COOL_MASK, MT6351_PMIC_RG_INT_EN_JEITA_COOL_SHIFT}, + {PMIC_RG_INT_EN_JEITA_COLD, MT6351_PMIC_RG_INT_EN_JEITA_COLD_ADDR, + MT6351_PMIC_RG_INT_EN_JEITA_COLD_MASK, MT6351_PMIC_RG_INT_EN_JEITA_COLD_SHIFT}, + {PMIC_RG_INT_EN_AUXADC_IMP, MT6351_PMIC_RG_INT_EN_AUXADC_IMP_ADDR, + MT6351_PMIC_RG_INT_EN_AUXADC_IMP_MASK, MT6351_PMIC_RG_INT_EN_AUXADC_IMP_SHIFT}, + {PMIC_RG_INT_EN_NAG_C_DLTV, MT6351_PMIC_RG_INT_EN_NAG_C_DLTV_ADDR, + MT6351_PMIC_RG_INT_EN_NAG_C_DLTV_MASK, MT6351_PMIC_RG_INT_EN_NAG_C_DLTV_SHIFT}, + {PMIC_RG_INT_EN_OV, MT6351_PMIC_RG_INT_EN_OV_ADDR, MT6351_PMIC_RG_INT_EN_OV_MASK, + MT6351_PMIC_RG_INT_EN_OV_SHIFT}, + {PMIC_RG_INT_EN_BVALID_DET, MT6351_PMIC_RG_INT_EN_BVALID_DET_ADDR, + MT6351_PMIC_RG_INT_EN_BVALID_DET_MASK, MT6351_PMIC_RG_INT_EN_BVALID_DET_SHIFT}, + {PMIC_RG_INT_EN_RGS_BATON_HV, MT6351_PMIC_RG_INT_EN_RGS_BATON_HV_ADDR, + MT6351_PMIC_RG_INT_EN_RGS_BATON_HV_MASK, MT6351_PMIC_RG_INT_EN_RGS_BATON_HV_SHIFT}, + {PMIC_RG_INT_EN_VBATON_UNDET, MT6351_PMIC_RG_INT_EN_VBATON_UNDET_ADDR, + MT6351_PMIC_RG_INT_EN_VBATON_UNDET_MASK, MT6351_PMIC_RG_INT_EN_VBATON_UNDET_SHIFT}, + {PMIC_RG_INT_EN_WATCHDOG, MT6351_PMIC_RG_INT_EN_WATCHDOG_ADDR, + MT6351_PMIC_RG_INT_EN_WATCHDOG_MASK, MT6351_PMIC_RG_INT_EN_WATCHDOG_SHIFT}, + {PMIC_RG_INT_EN_PCHR_CM_VDEC, MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC_ADDR, + MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC_MASK, MT6351_PMIC_RG_INT_EN_PCHR_CM_VDEC_SHIFT}, + {PMIC_RG_INT_EN_CHRDET, MT6351_PMIC_RG_INT_EN_CHRDET_ADDR, + MT6351_PMIC_RG_INT_EN_CHRDET_MASK, MT6351_PMIC_RG_INT_EN_CHRDET_SHIFT}, + {PMIC_RG_INT_EN_PCHR_CM_VINC, MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC_ADDR, + MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC_MASK, MT6351_PMIC_RG_INT_EN_PCHR_CM_VINC_SHIFT}, + {PMIC_INT_CON2_SET, MT6351_PMIC_INT_CON2_SET_ADDR, MT6351_PMIC_INT_CON2_SET_MASK, + MT6351_PMIC_INT_CON2_SET_SHIFT}, + {PMIC_INT_CON2_CLR, MT6351_PMIC_INT_CON2_CLR_ADDR, MT6351_PMIC_INT_CON2_CLR_MASK, + MT6351_PMIC_INT_CON2_CLR_SHIFT}, + {PMIC_RG_INT_EN_FG_BAT_H, MT6351_PMIC_RG_INT_EN_FG_BAT_H_ADDR, + MT6351_PMIC_RG_INT_EN_FG_BAT_H_MASK, MT6351_PMIC_RG_INT_EN_FG_BAT_H_SHIFT}, + {PMIC_RG_INT_EN_FG_BAT_L, MT6351_PMIC_RG_INT_EN_FG_BAT_L_ADDR, + MT6351_PMIC_RG_INT_EN_FG_BAT_L_MASK, MT6351_PMIC_RG_INT_EN_FG_BAT_L_SHIFT}, + {PMIC_RG_INT_EN_FG_CUR_H, MT6351_PMIC_RG_INT_EN_FG_CUR_H_ADDR, + MT6351_PMIC_RG_INT_EN_FG_CUR_H_MASK, MT6351_PMIC_RG_INT_EN_FG_CUR_H_SHIFT}, + {PMIC_RG_INT_EN_FG_CUR_L, MT6351_PMIC_RG_INT_EN_FG_CUR_L_ADDR, + MT6351_PMIC_RG_INT_EN_FG_CUR_L_MASK, MT6351_PMIC_RG_INT_EN_FG_CUR_L_SHIFT}, + {PMIC_RG_INT_EN_FG_ZCV, MT6351_PMIC_RG_INT_EN_FG_ZCV_ADDR, + MT6351_PMIC_RG_INT_EN_FG_ZCV_MASK, MT6351_PMIC_RG_INT_EN_FG_ZCV_SHIFT}, + {PMIC_INT_CON3_SET, MT6351_PMIC_INT_CON3_SET_ADDR, MT6351_PMIC_INT_CON3_SET_MASK, + MT6351_PMIC_INT_CON3_SET_SHIFT}, + {PMIC_INT_CON3_CLR, MT6351_PMIC_INT_CON3_CLR_ADDR, MT6351_PMIC_INT_CON3_CLR_MASK, + MT6351_PMIC_INT_CON3_CLR_SHIFT}, + {PMIC_POLARITY, MT6351_PMIC_POLARITY_ADDR, MT6351_PMIC_POLARITY_MASK, + MT6351_PMIC_POLARITY_SHIFT}, + {PMIC_RG_HOMEKEY_INT_SEL, MT6351_PMIC_RG_HOMEKEY_INT_SEL_ADDR, + MT6351_PMIC_RG_HOMEKEY_INT_SEL_MASK, MT6351_PMIC_RG_HOMEKEY_INT_SEL_SHIFT}, + {PMIC_RG_PWRKEY_INT_SEL, MT6351_PMIC_RG_PWRKEY_INT_SEL_ADDR, + MT6351_PMIC_RG_PWRKEY_INT_SEL_MASK, MT6351_PMIC_RG_PWRKEY_INT_SEL_SHIFT}, + {PMIC_RG_CHRDET_INT_SEL, MT6351_PMIC_RG_CHRDET_INT_SEL_ADDR, + MT6351_PMIC_RG_CHRDET_INT_SEL_MASK, MT6351_PMIC_RG_CHRDET_INT_SEL_SHIFT}, + {PMIC_RG_PCHR_CM_VINC_POLARITY_RSV, MT6351_PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_ADDR, + MT6351_PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_MASK, + MT6351_PMIC_RG_PCHR_CM_VINC_POLARITY_RSV_SHIFT}, + {PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV, MT6351_PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_ADDR, + MT6351_PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_MASK, + MT6351_PMIC_RG_PCHR_CM_VDEC_POLARITY_RSV_SHIFT}, + {PMIC_INT_MISC_CON_SET, MT6351_PMIC_INT_MISC_CON_SET_ADDR, + MT6351_PMIC_INT_MISC_CON_SET_MASK, MT6351_PMIC_INT_MISC_CON_SET_SHIFT}, + {PMIC_INT_MISC_CON_CLR, MT6351_PMIC_INT_MISC_CON_CLR_ADDR, + MT6351_PMIC_INT_MISC_CON_CLR_MASK, MT6351_PMIC_INT_MISC_CON_CLR_SHIFT}, + {PMIC_RG_INT_STATUS_PWRKEY, MT6351_PMIC_RG_INT_STATUS_PWRKEY_ADDR, + MT6351_PMIC_RG_INT_STATUS_PWRKEY_MASK, MT6351_PMIC_RG_INT_STATUS_PWRKEY_SHIFT}, + {PMIC_RG_INT_STATUS_HOMEKEY, MT6351_PMIC_RG_INT_STATUS_HOMEKEY_ADDR, + MT6351_PMIC_RG_INT_STATUS_HOMEKEY_MASK, MT6351_PMIC_RG_INT_STATUS_HOMEKEY_SHIFT}, + {PMIC_RG_INT_STATUS_PWRKEY_R, MT6351_PMIC_RG_INT_STATUS_PWRKEY_R_ADDR, + MT6351_PMIC_RG_INT_STATUS_PWRKEY_R_MASK, MT6351_PMIC_RG_INT_STATUS_PWRKEY_R_SHIFT}, + {PMIC_RG_INT_STATUS_HOMEKEY_R, MT6351_PMIC_RG_INT_STATUS_HOMEKEY_R_ADDR, + MT6351_PMIC_RG_INT_STATUS_HOMEKEY_R_MASK, MT6351_PMIC_RG_INT_STATUS_HOMEKEY_R_SHIFT}, + {PMIC_RG_INT_STATUS_THR_H, MT6351_PMIC_RG_INT_STATUS_THR_H_ADDR, + MT6351_PMIC_RG_INT_STATUS_THR_H_MASK, MT6351_PMIC_RG_INT_STATUS_THR_H_SHIFT}, + {PMIC_RG_INT_STATUS_THR_L, MT6351_PMIC_RG_INT_STATUS_THR_L_ADDR, + MT6351_PMIC_RG_INT_STATUS_THR_L_MASK, MT6351_PMIC_RG_INT_STATUS_THR_L_SHIFT}, + {PMIC_RG_INT_STATUS_BAT_H, MT6351_PMIC_RG_INT_STATUS_BAT_H_ADDR, + MT6351_PMIC_RG_INT_STATUS_BAT_H_MASK, MT6351_PMIC_RG_INT_STATUS_BAT_H_SHIFT}, + {PMIC_RG_INT_STATUS_BAT_L, MT6351_PMIC_RG_INT_STATUS_BAT_L_ADDR, + MT6351_PMIC_RG_INT_STATUS_BAT_L_MASK, MT6351_PMIC_RG_INT_STATUS_BAT_L_SHIFT}, + {PMIC_RG_INT_STATUS_RTC, MT6351_PMIC_RG_INT_STATUS_RTC_ADDR, + MT6351_PMIC_RG_INT_STATUS_RTC_MASK, MT6351_PMIC_RG_INT_STATUS_RTC_SHIFT}, + {PMIC_RG_INT_STATUS_AUDIO, MT6351_PMIC_RG_INT_STATUS_AUDIO_ADDR, + MT6351_PMIC_RG_INT_STATUS_AUDIO_MASK, MT6351_PMIC_RG_INT_STATUS_AUDIO_SHIFT}, + {PMIC_RG_INT_STATUS_MAD, MT6351_PMIC_RG_INT_STATUS_MAD_ADDR, + MT6351_PMIC_RG_INT_STATUS_MAD_MASK, MT6351_PMIC_RG_INT_STATUS_MAD_SHIFT}, + {PMIC_RG_INT_STATUS_ACCDET, MT6351_PMIC_RG_INT_STATUS_ACCDET_ADDR, + MT6351_PMIC_RG_INT_STATUS_ACCDET_MASK, MT6351_PMIC_RG_INT_STATUS_ACCDET_SHIFT}, + {PMIC_RG_INT_STATUS_ACCDET_EINT, MT6351_PMIC_RG_INT_STATUS_ACCDET_EINT_ADDR, + MT6351_PMIC_RG_INT_STATUS_ACCDET_EINT_MASK, MT6351_PMIC_RG_INT_STATUS_ACCDET_EINT_SHIFT}, + {PMIC_RG_INT_STATUS_ACCDET_NEGV, MT6351_PMIC_RG_INT_STATUS_ACCDET_NEGV_ADDR, + MT6351_PMIC_RG_INT_STATUS_ACCDET_NEGV_MASK, MT6351_PMIC_RG_INT_STATUS_ACCDET_NEGV_SHIFT}, + {PMIC_RG_INT_STATUS_NI_LBAT_INT, MT6351_PMIC_RG_INT_STATUS_NI_LBAT_INT_ADDR, + MT6351_PMIC_RG_INT_STATUS_NI_LBAT_INT_MASK, MT6351_PMIC_RG_INT_STATUS_NI_LBAT_INT_SHIFT}, + {PMIC_RG_INT_STATUS_VCORE_OC, MT6351_PMIC_RG_INT_STATUS_VCORE_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VCORE_OC_MASK, MT6351_PMIC_RG_INT_STATUS_VCORE_OC_SHIFT}, + {PMIC_RG_INT_STATUS_VGPU_OC, MT6351_PMIC_RG_INT_STATUS_VGPU_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VGPU_OC_MASK, MT6351_PMIC_RG_INT_STATUS_VGPU_OC_SHIFT}, + {PMIC_RG_INT_STATUS_VSRAM_MD_OC, MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_OC_MASK, MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_OC_SHIFT}, + {PMIC_RG_INT_STATUS_VMODEM_OC, MT6351_PMIC_RG_INT_STATUS_VMODEM_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VMODEM_OC_MASK, MT6351_PMIC_RG_INT_STATUS_VMODEM_OC_SHIFT}, + {PMIC_RG_INT_STATUS_VM1_OC, MT6351_PMIC_RG_INT_STATUS_VM1_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VM1_OC_MASK, MT6351_PMIC_RG_INT_STATUS_VM1_OC_SHIFT}, + {PMIC_RG_INT_STATUS_VS1_OC, MT6351_PMIC_RG_INT_STATUS_VS1_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VS1_OC_MASK, MT6351_PMIC_RG_INT_STATUS_VS1_OC_SHIFT}, + {PMIC_RG_INT_STATUS_VS2_OC, MT6351_PMIC_RG_INT_STATUS_VS2_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VS2_OC_MASK, MT6351_PMIC_RG_INT_STATUS_VS2_OC_SHIFT}, + {PMIC_RG_INT_STATUS_VPA_OC, MT6351_PMIC_RG_INT_STATUS_VPA_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VPA_OC_MASK, MT6351_PMIC_RG_INT_STATUS_VPA_OC_SHIFT}, + {PMIC_RG_INT_STATUS_VCORE_PREOC, MT6351_PMIC_RG_INT_STATUS_VCORE_PREOC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VCORE_PREOC_MASK, MT6351_PMIC_RG_INT_STATUS_VCORE_PREOC_SHIFT}, + {PMIC_RG_INT_STATUS_VGPU_PREOC, MT6351_PMIC_RG_INT_STATUS_VGPU_PREOC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VGPU_PREOC_MASK, MT6351_PMIC_RG_INT_STATUS_VGPU_PREOC_SHIFT}, + {PMIC_RG_INT_STATUS_VSRAM_MD_PREOC, MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_PREOC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_PREOC_MASK, + MT6351_PMIC_RG_INT_STATUS_VSRAM_MD_PREOC_SHIFT}, + {PMIC_RG_INT_STATUS_VMODEM_PREOC, MT6351_PMIC_RG_INT_STATUS_VMODEM_PREOC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VMODEM_PREOC_MASK, + MT6351_PMIC_RG_INT_STATUS_VMODEM_PREOC_SHIFT}, + {PMIC_RG_INT_STATUS_VM1_PREOC, MT6351_PMIC_RG_INT_STATUS_VM1_PREOC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VM1_PREOC_MASK, MT6351_PMIC_RG_INT_STATUS_VM1_PREOC_SHIFT}, + {PMIC_RG_INT_STATUS_VS1_PREOC, MT6351_PMIC_RG_INT_STATUS_VS1_PREOC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VS1_PREOC_MASK, MT6351_PMIC_RG_INT_STATUS_VS1_PREOC_SHIFT}, + {PMIC_RG_INT_STATUS_VS2_PREOC, MT6351_PMIC_RG_INT_STATUS_VS2_PREOC_ADDR, + MT6351_PMIC_RG_INT_STATUS_VS2_PREOC_MASK, MT6351_PMIC_RG_INT_STATUS_VS2_PREOC_SHIFT}, + {PMIC_RG_INT_STATUS_LDO_OC, MT6351_PMIC_RG_INT_STATUS_LDO_OC_ADDR, + MT6351_PMIC_RG_INT_STATUS_LDO_OC_MASK, MT6351_PMIC_RG_INT_STATUS_LDO_OC_SHIFT}, + {PMIC_RG_INT_STATUS_JEITA_HOT, MT6351_PMIC_RG_INT_STATUS_JEITA_HOT_ADDR, + MT6351_PMIC_RG_INT_STATUS_JEITA_HOT_MASK, MT6351_PMIC_RG_INT_STATUS_JEITA_HOT_SHIFT}, + {PMIC_RG_INT_STATUS_JEITA_WARM, MT6351_PMIC_RG_INT_STATUS_JEITA_WARM_ADDR, + MT6351_PMIC_RG_INT_STATUS_JEITA_WARM_MASK, MT6351_PMIC_RG_INT_STATUS_JEITA_WARM_SHIFT}, + {PMIC_RG_INT_STATUS_JEITA_COOL, MT6351_PMIC_RG_INT_STATUS_JEITA_COOL_ADDR, + MT6351_PMIC_RG_INT_STATUS_JEITA_COOL_MASK, MT6351_PMIC_RG_INT_STATUS_JEITA_COOL_SHIFT}, + {PMIC_RG_INT_STATUS_JEITA_COLD, MT6351_PMIC_RG_INT_STATUS_JEITA_COLD_ADDR, + MT6351_PMIC_RG_INT_STATUS_JEITA_COLD_MASK, MT6351_PMIC_RG_INT_STATUS_JEITA_COLD_SHIFT}, + {PMIC_RG_INT_STATUS_AUXADC_IMP, MT6351_PMIC_RG_INT_STATUS_AUXADC_IMP_ADDR, + MT6351_PMIC_RG_INT_STATUS_AUXADC_IMP_MASK, MT6351_PMIC_RG_INT_STATUS_AUXADC_IMP_SHIFT}, + {PMIC_RG_INT_STATUS_NAG_C_DLTV, MT6351_PMIC_RG_INT_STATUS_NAG_C_DLTV_ADDR, + MT6351_PMIC_RG_INT_STATUS_NAG_C_DLTV_MASK, MT6351_PMIC_RG_INT_STATUS_NAG_C_DLTV_SHIFT}, + {PMIC_RG_INT_STATUS_OV, MT6351_PMIC_RG_INT_STATUS_OV_ADDR, + MT6351_PMIC_RG_INT_STATUS_OV_MASK, MT6351_PMIC_RG_INT_STATUS_OV_SHIFT}, + {PMIC_RG_INT_STATUS_BVALID_DET, MT6351_PMIC_RG_INT_STATUS_BVALID_DET_ADDR, + MT6351_PMIC_RG_INT_STATUS_BVALID_DET_MASK, MT6351_PMIC_RG_INT_STATUS_BVALID_DET_SHIFT}, + {PMIC_RG_INT_STATUS_RGS_BATON_HV, MT6351_PMIC_RG_INT_STATUS_RGS_BATON_HV_ADDR, + MT6351_PMIC_RG_INT_STATUS_RGS_BATON_HV_MASK, + MT6351_PMIC_RG_INT_STATUS_RGS_BATON_HV_SHIFT}, + {PMIC_RG_INT_STATUS_VBATON_UNDET, MT6351_PMIC_RG_INT_STATUS_VBATON_UNDET_ADDR, + MT6351_PMIC_RG_INT_STATUS_VBATON_UNDET_MASK, + MT6351_PMIC_RG_INT_STATUS_VBATON_UNDET_SHIFT}, + {PMIC_RG_INT_STATUS_WATCHDOG, MT6351_PMIC_RG_INT_STATUS_WATCHDOG_ADDR, + MT6351_PMIC_RG_INT_STATUS_WATCHDOG_MASK, MT6351_PMIC_RG_INT_STATUS_WATCHDOG_SHIFT}, + {PMIC_RG_INT_STATUS_PCHR_CM_VDEC, MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VDEC_ADDR, + MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VDEC_MASK, + MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VDEC_SHIFT}, + {PMIC_RG_INT_STATUS_CHRDET, MT6351_PMIC_RG_INT_STATUS_CHRDET_ADDR, + MT6351_PMIC_RG_INT_STATUS_CHRDET_MASK, MT6351_PMIC_RG_INT_STATUS_CHRDET_SHIFT}, + {PMIC_RG_INT_STATUS_PCHR_CM_VINC, MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VINC_ADDR, + MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VINC_MASK, + MT6351_PMIC_RG_INT_STATUS_PCHR_CM_VINC_SHIFT}, + {PMIC_RG_INT_STATUS_FG_BAT_H, MT6351_PMIC_RG_INT_STATUS_FG_BAT_H_ADDR, + MT6351_PMIC_RG_INT_STATUS_FG_BAT_H_MASK, MT6351_PMIC_RG_INT_STATUS_FG_BAT_H_SHIFT}, + {PMIC_RG_INT_STATUS_FG_BAT_L, MT6351_PMIC_RG_INT_STATUS_FG_BAT_L_ADDR, + MT6351_PMIC_RG_INT_STATUS_FG_BAT_L_MASK, MT6351_PMIC_RG_INT_STATUS_FG_BAT_L_SHIFT}, + {PMIC_RG_INT_STATUS_FG_CUR_H, MT6351_PMIC_RG_INT_STATUS_FG_CUR_H_ADDR, + MT6351_PMIC_RG_INT_STATUS_FG_CUR_H_MASK, MT6351_PMIC_RG_INT_STATUS_FG_CUR_H_SHIFT}, + {PMIC_RG_INT_STATUS_FG_CUR_L, MT6351_PMIC_RG_INT_STATUS_FG_CUR_L_ADDR, + MT6351_PMIC_RG_INT_STATUS_FG_CUR_L_MASK, MT6351_PMIC_RG_INT_STATUS_FG_CUR_L_SHIFT}, + {PMIC_RG_INT_STATUS_FG_ZCV, MT6351_PMIC_RG_INT_STATUS_FG_ZCV_ADDR, + MT6351_PMIC_RG_INT_STATUS_FG_ZCV_MASK, MT6351_PMIC_RG_INT_STATUS_FG_ZCV_SHIFT}, + {PMIC_OC_GEAR_LDO, MT6351_PMIC_OC_GEAR_LDO_ADDR, MT6351_PMIC_OC_GEAR_LDO_MASK, + MT6351_PMIC_OC_GEAR_LDO_SHIFT}, + {PMIC_FQMTR_TCKSEL, MT6351_PMIC_FQMTR_TCKSEL_ADDR, MT6351_PMIC_FQMTR_TCKSEL_MASK, + MT6351_PMIC_FQMTR_TCKSEL_SHIFT}, + {PMIC_FQMTR_BUSY, MT6351_PMIC_FQMTR_BUSY_ADDR, MT6351_PMIC_FQMTR_BUSY_MASK, + MT6351_PMIC_FQMTR_BUSY_SHIFT}, + {PMIC_FQMTR_EN, MT6351_PMIC_FQMTR_EN_ADDR, MT6351_PMIC_FQMTR_EN_MASK, + MT6351_PMIC_FQMTR_EN_SHIFT}, + {PMIC_FQMTR_WINSET, MT6351_PMIC_FQMTR_WINSET_ADDR, MT6351_PMIC_FQMTR_WINSET_MASK, + MT6351_PMIC_FQMTR_WINSET_SHIFT}, + {PMIC_FQMTR_DATA, MT6351_PMIC_FQMTR_DATA_ADDR, MT6351_PMIC_FQMTR_DATA_MASK, + MT6351_PMIC_FQMTR_DATA_SHIFT}, + {PMIC_RG_SLP_RW_EN, MT6351_PMIC_RG_SLP_RW_EN_ADDR, MT6351_PMIC_RG_SLP_RW_EN_MASK, + MT6351_PMIC_RG_SLP_RW_EN_SHIFT}, + {PMIC_RG_SPI_RSV, MT6351_PMIC_RG_SPI_RSV_ADDR, MT6351_PMIC_RG_SPI_RSV_MASK, + MT6351_PMIC_RG_SPI_RSV_SHIFT}, + {PMIC_DEW_DIO_EN, MT6351_PMIC_DEW_DIO_EN_ADDR, MT6351_PMIC_DEW_DIO_EN_MASK, + MT6351_PMIC_DEW_DIO_EN_SHIFT}, + {PMIC_DEW_READ_TEST, MT6351_PMIC_DEW_READ_TEST_ADDR, + MT6351_PMIC_DEW_READ_TEST_MASK, MT6351_PMIC_DEW_READ_TEST_SHIFT}, + {PMIC_DEW_WRITE_TEST, MT6351_PMIC_DEW_WRITE_TEST_ADDR, + MT6351_PMIC_DEW_WRITE_TEST_MASK, MT6351_PMIC_DEW_WRITE_TEST_SHIFT}, + {PMIC_DEW_CRC_SWRST, MT6351_PMIC_DEW_CRC_SWRST_ADDR, + MT6351_PMIC_DEW_CRC_SWRST_MASK, MT6351_PMIC_DEW_CRC_SWRST_SHIFT}, + {PMIC_DEW_CRC_EN, MT6351_PMIC_DEW_CRC_EN_ADDR, MT6351_PMIC_DEW_CRC_EN_MASK, + MT6351_PMIC_DEW_CRC_EN_SHIFT}, + {PMIC_DEW_CRC_VAL, MT6351_PMIC_DEW_CRC_VAL_ADDR, MT6351_PMIC_DEW_CRC_VAL_MASK, + MT6351_PMIC_DEW_CRC_VAL_SHIFT}, + {PMIC_DEW_DBG_MON_SEL, MT6351_PMIC_DEW_DBG_MON_SEL_ADDR, + MT6351_PMIC_DEW_DBG_MON_SEL_MASK, MT6351_PMIC_DEW_DBG_MON_SEL_SHIFT}, + {PMIC_DEW_CIPHER_KEY_SEL, MT6351_PMIC_DEW_CIPHER_KEY_SEL_ADDR, + MT6351_PMIC_DEW_CIPHER_KEY_SEL_MASK, MT6351_PMIC_DEW_CIPHER_KEY_SEL_SHIFT}, + {PMIC_DEW_CIPHER_IV_SEL, MT6351_PMIC_DEW_CIPHER_IV_SEL_ADDR, + MT6351_PMIC_DEW_CIPHER_IV_SEL_MASK, MT6351_PMIC_DEW_CIPHER_IV_SEL_SHIFT}, + {PMIC_DEW_CIPHER_EN, MT6351_PMIC_DEW_CIPHER_EN_ADDR, + MT6351_PMIC_DEW_CIPHER_EN_MASK, MT6351_PMIC_DEW_CIPHER_EN_SHIFT}, + {PMIC_DEW_CIPHER_RDY, MT6351_PMIC_DEW_CIPHER_RDY_ADDR, + MT6351_PMIC_DEW_CIPHER_RDY_MASK, MT6351_PMIC_DEW_CIPHER_RDY_SHIFT}, + {PMIC_DEW_CIPHER_MODE, MT6351_PMIC_DEW_CIPHER_MODE_ADDR, + MT6351_PMIC_DEW_CIPHER_MODE_MASK, MT6351_PMIC_DEW_CIPHER_MODE_SHIFT}, + {PMIC_DEW_CIPHER_SWRST, MT6351_PMIC_DEW_CIPHER_SWRST_ADDR, + MT6351_PMIC_DEW_CIPHER_SWRST_MASK, MT6351_PMIC_DEW_CIPHER_SWRST_SHIFT}, + {PMIC_DEW_RDDMY_NO, MT6351_PMIC_DEW_RDDMY_NO_ADDR, MT6351_PMIC_DEW_RDDMY_NO_MASK, + MT6351_PMIC_DEW_RDDMY_NO_SHIFT}, + {PMIC_INT_TYPE_CON0, MT6351_PMIC_INT_TYPE_CON0_ADDR, + MT6351_PMIC_INT_TYPE_CON0_MASK, MT6351_PMIC_INT_TYPE_CON0_SHIFT}, + {PMIC_INT_TYPE_CON0_SET, MT6351_PMIC_INT_TYPE_CON0_SET_ADDR, + MT6351_PMIC_INT_TYPE_CON0_SET_MASK, MT6351_PMIC_INT_TYPE_CON0_SET_SHIFT}, + {PMIC_INT_TYPE_CON0_CLR, MT6351_PMIC_INT_TYPE_CON0_CLR_ADDR, + MT6351_PMIC_INT_TYPE_CON0_CLR_MASK, MT6351_PMIC_INT_TYPE_CON0_CLR_SHIFT}, + {PMIC_INT_TYPE_CON1, MT6351_PMIC_INT_TYPE_CON1_ADDR, + MT6351_PMIC_INT_TYPE_CON1_MASK, MT6351_PMIC_INT_TYPE_CON1_SHIFT}, + {PMIC_INT_TYPE_CON1_SET, MT6351_PMIC_INT_TYPE_CON1_SET_ADDR, + MT6351_PMIC_INT_TYPE_CON1_SET_MASK, MT6351_PMIC_INT_TYPE_CON1_SET_SHIFT}, + {PMIC_INT_TYPE_CON1_CLR, MT6351_PMIC_INT_TYPE_CON1_CLR_ADDR, + MT6351_PMIC_INT_TYPE_CON1_CLR_MASK, MT6351_PMIC_INT_TYPE_CON1_CLR_SHIFT}, + {PMIC_INT_TYPE_CON2, MT6351_PMIC_INT_TYPE_CON2_ADDR, + MT6351_PMIC_INT_TYPE_CON2_MASK, MT6351_PMIC_INT_TYPE_CON2_SHIFT}, + {PMIC_INT_TYPE_CON2_SET, MT6351_PMIC_INT_TYPE_CON2_SET_ADDR, + MT6351_PMIC_INT_TYPE_CON2_SET_MASK, MT6351_PMIC_INT_TYPE_CON2_SET_SHIFT}, + {PMIC_INT_TYPE_CON2_CLR, MT6351_PMIC_INT_TYPE_CON2_CLR_ADDR, + MT6351_PMIC_INT_TYPE_CON2_CLR_MASK, MT6351_PMIC_INT_TYPE_CON2_CLR_SHIFT}, + {PMIC_INT_TYPE_CON3, MT6351_PMIC_INT_TYPE_CON3_ADDR, + MT6351_PMIC_INT_TYPE_CON3_MASK, MT6351_PMIC_INT_TYPE_CON3_SHIFT}, + {PMIC_INT_TYPE_CON3_SET, MT6351_PMIC_INT_TYPE_CON3_SET_ADDR, + MT6351_PMIC_INT_TYPE_CON3_SET_MASK, MT6351_PMIC_INT_TYPE_CON3_SET_SHIFT}, + {PMIC_INT_TYPE_CON3_CLR, MT6351_PMIC_INT_TYPE_CON3_CLR_ADDR, + MT6351_PMIC_INT_TYPE_CON3_CLR_MASK, MT6351_PMIC_INT_TYPE_CON3_CLR_SHIFT}, + {PMIC_CPU_INT_STA, MT6351_PMIC_CPU_INT_STA_ADDR, MT6351_PMIC_CPU_INT_STA_MASK, + MT6351_PMIC_CPU_INT_STA_SHIFT}, + {PMIC_MD32_INT_STA, MT6351_PMIC_MD32_INT_STA_ADDR, MT6351_PMIC_MD32_INT_STA_MASK, + MT6351_PMIC_MD32_INT_STA_SHIFT}, + {PMIC_BUCK_LDO_FT_TESTMODE_EN, MT6351_PMIC_BUCK_LDO_FT_TESTMODE_EN_ADDR, + MT6351_PMIC_BUCK_LDO_FT_TESTMODE_EN_MASK, MT6351_PMIC_BUCK_LDO_FT_TESTMODE_EN_SHIFT}, + {PMIC_BUCK_ALL_CON0_RSV1, MT6351_PMIC_BUCK_ALL_CON0_RSV1_ADDR, + MT6351_PMIC_BUCK_ALL_CON0_RSV1_MASK, MT6351_PMIC_BUCK_ALL_CON0_RSV1_SHIFT}, + {PMIC_BUCK_ALL_CON0_RSV0, MT6351_PMIC_BUCK_ALL_CON0_RSV0_ADDR, + MT6351_PMIC_BUCK_ALL_CON0_RSV0_MASK, MT6351_PMIC_BUCK_ALL_CON0_RSV0_SHIFT}, + {PMIC_BUCK_BUCK_RSV, MT6351_PMIC_BUCK_BUCK_RSV_ADDR, + MT6351_PMIC_BUCK_BUCK_RSV_MASK, MT6351_PMIC_BUCK_BUCK_RSV_SHIFT}, + {PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL, + MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL_ADDR, + MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL_MASK, + MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRCLKEN_SEL_SHIFT}, + {PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL, + MT6351_PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL_ADDR, + MT6351_PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL_MASK, + MT6351_PMIC_BUCK_BUCK_R2R_PDN_SRCLKEN_SEL_SHIFT}, + {PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL, MT6351_PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL_ADDR, + MT6351_PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL_MASK, + MT6351_PMIC_BUCK_BUCK_VSLEEP_SRCLKEN_SEL_SHIFT}, + {PMIC_BUCK_ALL_CON2_RSV0, MT6351_PMIC_BUCK_ALL_CON2_RSV0_ADDR, + MT6351_PMIC_BUCK_ALL_CON2_RSV0_MASK, MT6351_PMIC_BUCK_ALL_CON2_RSV0_SHIFT}, + {PMIC_BUCK_VSLEEP_SRC0, MT6351_PMIC_BUCK_VSLEEP_SRC0_ADDR, + MT6351_PMIC_BUCK_VSLEEP_SRC0_MASK, MT6351_PMIC_BUCK_VSLEEP_SRC0_SHIFT}, + {PMIC_BUCK_VSLEEP_SRC1, MT6351_PMIC_BUCK_VSLEEP_SRC1_ADDR, + MT6351_PMIC_BUCK_VSLEEP_SRC1_MASK, MT6351_PMIC_BUCK_VSLEEP_SRC1_SHIFT}, + {PMIC_BUCK_R2R_SRC0, MT6351_PMIC_BUCK_R2R_SRC0_ADDR, + MT6351_PMIC_BUCK_R2R_SRC0_MASK, MT6351_PMIC_BUCK_R2R_SRC0_SHIFT}, + {PMIC_BUCK_R2R_SRC1, MT6351_PMIC_BUCK_R2R_SRC1_ADDR, + MT6351_PMIC_BUCK_R2R_SRC1_MASK, MT6351_PMIC_BUCK_R2R_SRC1_SHIFT}, + {PMIC_BUCK_BUCK_OSC_SEL_SRC0, MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRC0_ADDR, + MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRC0_MASK, MT6351_PMIC_BUCK_BUCK_OSC_SEL_SRC0_SHIFT}, + {PMIC_BUCK_SRCLKEN_DLY_SRC1, MT6351_PMIC_BUCK_SRCLKEN_DLY_SRC1_ADDR, + MT6351_PMIC_BUCK_SRCLKEN_DLY_SRC1_MASK, MT6351_PMIC_BUCK_SRCLKEN_DLY_SRC1_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB, MT6351_PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB_MASK, MT6351_PMIC_BUCK_VS2_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB, MT6351_PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB_MASK, MT6351_PMIC_BUCK_VS1_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB, + MT6351_PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB_MASK, + MT6351_PMIC_BUCK_VSRAM_MD_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB, MT6351_PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB_MASK, + MT6351_PMIC_BUCK_VMD1_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB, MT6351_PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB_MASK, MT6351_PMIC_BUCK_VPA_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB, MT6351_PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB_MASK, + MT6351_PMIC_BUCK_VMODEM_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB, MT6351_PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB_MASK, + MT6351_PMIC_BUCK_VGPU_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB, MT6351_PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB_ADDR, + MT6351_PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB_MASK, + MT6351_PMIC_BUCK_VCORE_BIN2GRAY_MAP_ENB_SHIFT}, + {PMIC_BUCK_VPA_VOSEL_DLC011, MT6351_PMIC_BUCK_VPA_VOSEL_DLC011_ADDR, + MT6351_PMIC_BUCK_VPA_VOSEL_DLC011_MASK, MT6351_PMIC_BUCK_VPA_VOSEL_DLC011_SHIFT}, + {PMIC_BUCK_VPA_VOSEL_DLC111, MT6351_PMIC_BUCK_VPA_VOSEL_DLC111_ADDR, + MT6351_PMIC_BUCK_VPA_VOSEL_DLC111_MASK, MT6351_PMIC_BUCK_VPA_VOSEL_DLC111_SHIFT}, + {PMIC_BUCK_VPA_DLC_MAP_EN, MT6351_PMIC_BUCK_VPA_DLC_MAP_EN_ADDR, + MT6351_PMIC_BUCK_VPA_DLC_MAP_EN_MASK, MT6351_PMIC_BUCK_VPA_DLC_MAP_EN_SHIFT}, + {PMIC_BUCK_VPA_VOSEL_DLC001, MT6351_PMIC_BUCK_VPA_VOSEL_DLC001_ADDR, + MT6351_PMIC_BUCK_VPA_VOSEL_DLC001_MASK, MT6351_PMIC_BUCK_VPA_VOSEL_DLC001_SHIFT}, + {PMIC_BUCK_VPA_DLC, MT6351_PMIC_BUCK_VPA_DLC_ADDR, MT6351_PMIC_BUCK_VPA_DLC_MASK, + MT6351_PMIC_BUCK_VPA_DLC_SHIFT}, + {PMIC_DA_NI_VPA_DLC, MT6351_PMIC_DA_NI_VPA_DLC_ADDR, + MT6351_PMIC_DA_NI_VPA_DLC_MASK, MT6351_PMIC_DA_NI_VPA_DLC_SHIFT}, + {PMIC_BUCK_VPA_DVS_TRANS_TD, MT6351_PMIC_BUCK_VPA_DVS_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VPA_DVS_TRANS_TD_MASK, MT6351_PMIC_BUCK_VPA_DVS_TRANS_TD_SHIFT}, + {PMIC_BUCK_VPA_DVS_TRANS_CTRL, MT6351_PMIC_BUCK_VPA_DVS_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VPA_DVS_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VPA_DVS_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VPA_DVS_TRANS_ONCE, MT6351_PMIC_BUCK_VPA_DVS_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VPA_DVS_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VPA_DVS_TRANS_ONCE_SHIFT}, + {PMIC_DA_NI_VPA_DVS_TRANST, MT6351_PMIC_DA_NI_VPA_DVS_TRANST_ADDR, + MT6351_PMIC_DA_NI_VPA_DVS_TRANST_MASK, MT6351_PMIC_DA_NI_VPA_DVS_TRANST_SHIFT}, + {PMIC_BUCK_VPA_DIG0_RSV5, MT6351_PMIC_BUCK_VPA_DIG0_RSV5_ADDR, + MT6351_PMIC_BUCK_VPA_DIG0_RSV5_MASK, MT6351_PMIC_BUCK_VPA_DIG0_RSV5_SHIFT}, + {PMIC_BUCK_VPA_DIG1_RSV5, MT6351_PMIC_BUCK_VPA_DIG1_RSV5_ADDR, + MT6351_PMIC_BUCK_VPA_DIG1_RSV5_MASK, MT6351_PMIC_BUCK_VPA_DIG1_RSV5_SHIFT}, + {PMIC_BUCK_VCORE_VOSEL_AUD, MT6351_PMIC_BUCK_VCORE_VOSEL_AUD_ADDR, + MT6351_PMIC_BUCK_VCORE_VOSEL_AUD_MASK, MT6351_PMIC_BUCK_VCORE_VOSEL_AUD_SHIFT}, + {PMIC_BUCK_VCORE_DVFS_DONE, MT6351_PMIC_BUCK_VCORE_DVFS_DONE_ADDR, + MT6351_PMIC_BUCK_VCORE_DVFS_DONE_MASK, MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SHIFT}, + {PMIC_BUCK_VCORE_DVFS_DONE_SW, MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SW_ADDR, + MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SW_MASK, MT6351_PMIC_BUCK_VCORE_DVFS_DONE_SW_SHIFT}, + {PMIC_BUCK_VCORE_DVFS_DONE_STA, MT6351_PMIC_BUCK_VCORE_DVFS_DONE_STA_ADDR, + MT6351_PMIC_BUCK_VCORE_DVFS_DONE_STA_MASK, MT6351_PMIC_BUCK_VCORE_DVFS_DONE_STA_SHIFT}, + {PMIC_BUCK_VSRAM_MD_VOSEL_AUD, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_AUD_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_AUD_MASK, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_AUD_SHIFT}, + {PMIC_BUCK_VSRAM_MD_DVFS_DONE, MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_MASK, MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SHIFT}, + {PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW, MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW_MASK, + MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_SW_SHIFT}, + {PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA, MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA_MASK, + MT6351_PMIC_BUCK_VSRAM_MD_DVFS_DONE_STA_SHIFT}, + {PMIC_BUCK_VCORE_OC_STATUS, MT6351_PMIC_BUCK_VCORE_OC_STATUS_ADDR, + MT6351_PMIC_BUCK_VCORE_OC_STATUS_MASK, MT6351_PMIC_BUCK_VCORE_OC_STATUS_SHIFT}, + {PMIC_BUCK_VGPU_OC_STATUS, MT6351_PMIC_BUCK_VGPU_OC_STATUS_ADDR, + MT6351_PMIC_BUCK_VGPU_OC_STATUS_MASK, MT6351_PMIC_BUCK_VGPU_OC_STATUS_SHIFT}, + {PMIC_BUCK_VMODEM_OC_STATUS, MT6351_PMIC_BUCK_VMODEM_OC_STATUS_ADDR, + MT6351_PMIC_BUCK_VMODEM_OC_STATUS_MASK, MT6351_PMIC_BUCK_VMODEM_OC_STATUS_SHIFT}, + {PMIC_BUCK_VMD1_OC_STATUS, MT6351_PMIC_BUCK_VMD1_OC_STATUS_ADDR, + MT6351_PMIC_BUCK_VMD1_OC_STATUS_MASK, MT6351_PMIC_BUCK_VMD1_OC_STATUS_SHIFT}, + {PMIC_BUCK_VSRAM_MD_OC_STATUS, MT6351_PMIC_BUCK_VSRAM_MD_OC_STATUS_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_OC_STATUS_MASK, MT6351_PMIC_BUCK_VSRAM_MD_OC_STATUS_SHIFT}, + {PMIC_BUCK_VS1_OC_STATUS, MT6351_PMIC_BUCK_VS1_OC_STATUS_ADDR, + MT6351_PMIC_BUCK_VS1_OC_STATUS_MASK, MT6351_PMIC_BUCK_VS1_OC_STATUS_SHIFT}, + {PMIC_BUCK_VS2_OC_STATUS, MT6351_PMIC_BUCK_VS2_OC_STATUS_ADDR, + MT6351_PMIC_BUCK_VS2_OC_STATUS_MASK, MT6351_PMIC_BUCK_VS2_OC_STATUS_SHIFT}, + {PMIC_BUCK_VPA_OC_STATUS, MT6351_PMIC_BUCK_VPA_OC_STATUS_ADDR, + MT6351_PMIC_BUCK_VPA_OC_STATUS_MASK, MT6351_PMIC_BUCK_VPA_OC_STATUS_SHIFT}, + {PMIC_BUCK_VCORE_OC_INT_EN, MT6351_PMIC_BUCK_VCORE_OC_INT_EN_ADDR, + MT6351_PMIC_BUCK_VCORE_OC_INT_EN_MASK, MT6351_PMIC_BUCK_VCORE_OC_INT_EN_SHIFT}, + {PMIC_BUCK_VGPU_OC_INT_EN, MT6351_PMIC_BUCK_VGPU_OC_INT_EN_ADDR, + MT6351_PMIC_BUCK_VGPU_OC_INT_EN_MASK, MT6351_PMIC_BUCK_VGPU_OC_INT_EN_SHIFT}, + {PMIC_BUCK_VMODEM_OC_INT_EN, MT6351_PMIC_BUCK_VMODEM_OC_INT_EN_ADDR, + MT6351_PMIC_BUCK_VMODEM_OC_INT_EN_MASK, MT6351_PMIC_BUCK_VMODEM_OC_INT_EN_SHIFT}, + {PMIC_BUCK_VMD1_OC_INT_EN, MT6351_PMIC_BUCK_VMD1_OC_INT_EN_ADDR, + MT6351_PMIC_BUCK_VMD1_OC_INT_EN_MASK, MT6351_PMIC_BUCK_VMD1_OC_INT_EN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_OC_INT_EN, MT6351_PMIC_BUCK_VSRAM_MD_OC_INT_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_OC_INT_EN_MASK, MT6351_PMIC_BUCK_VSRAM_MD_OC_INT_EN_SHIFT}, + {PMIC_BUCK_VS1_OC_INT_EN, MT6351_PMIC_BUCK_VS1_OC_INT_EN_ADDR, + MT6351_PMIC_BUCK_VS1_OC_INT_EN_MASK, MT6351_PMIC_BUCK_VS1_OC_INT_EN_SHIFT}, + {PMIC_BUCK_VS2_OC_INT_EN, MT6351_PMIC_BUCK_VS2_OC_INT_EN_ADDR, + MT6351_PMIC_BUCK_VS2_OC_INT_EN_MASK, MT6351_PMIC_BUCK_VS2_OC_INT_EN_SHIFT}, + {PMIC_BUCK_VPA_OC_INT_EN, MT6351_PMIC_BUCK_VPA_OC_INT_EN_ADDR, + MT6351_PMIC_BUCK_VPA_OC_INT_EN_MASK, MT6351_PMIC_BUCK_VPA_OC_INT_EN_SHIFT}, + {PMIC_BUCK_VCORE_EN_OC_SDN_SEL, MT6351_PMIC_BUCK_VCORE_EN_OC_SDN_SEL_ADDR, + MT6351_PMIC_BUCK_VCORE_EN_OC_SDN_SEL_MASK, MT6351_PMIC_BUCK_VCORE_EN_OC_SDN_SEL_SHIFT}, + {PMIC_BUCK_VGPU_EN_OC_SDN_SEL, MT6351_PMIC_BUCK_VGPU_EN_OC_SDN_SEL_ADDR, + MT6351_PMIC_BUCK_VGPU_EN_OC_SDN_SEL_MASK, MT6351_PMIC_BUCK_VGPU_EN_OC_SDN_SEL_SHIFT}, + {PMIC_BUCK_VMODEM_EN_OC_SDN_SEL, MT6351_PMIC_BUCK_VMODEM_EN_OC_SDN_SEL_ADDR, + MT6351_PMIC_BUCK_VMODEM_EN_OC_SDN_SEL_MASK, MT6351_PMIC_BUCK_VMODEM_EN_OC_SDN_SEL_SHIFT}, + {PMIC_BUCK_VMD1_EN_OC_SDN_SEL, MT6351_PMIC_BUCK_VMD1_EN_OC_SDN_SEL_ADDR, + MT6351_PMIC_BUCK_VMD1_EN_OC_SDN_SEL_MASK, MT6351_PMIC_BUCK_VMD1_EN_OC_SDN_SEL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL, MT6351_PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL_MASK, + MT6351_PMIC_BUCK_VSRAM_MD_EN_OC_SDN_SEL_SHIFT}, + {PMIC_BUCK_VS1_EN_OC_SDN_SEL, MT6351_PMIC_BUCK_VS1_EN_OC_SDN_SEL_ADDR, + MT6351_PMIC_BUCK_VS1_EN_OC_SDN_SEL_MASK, MT6351_PMIC_BUCK_VS1_EN_OC_SDN_SEL_SHIFT}, + {PMIC_BUCK_VS2_EN_OC_SDN_SEL, MT6351_PMIC_BUCK_VS2_EN_OC_SDN_SEL_ADDR, + MT6351_PMIC_BUCK_VS2_EN_OC_SDN_SEL_MASK, MT6351_PMIC_BUCK_VS2_EN_OC_SDN_SEL_SHIFT}, + {PMIC_BUCK_VPA_EN_OC_SDN_SEL, MT6351_PMIC_BUCK_VPA_EN_OC_SDN_SEL_ADDR, + MT6351_PMIC_BUCK_VPA_EN_OC_SDN_SEL_MASK, MT6351_PMIC_BUCK_VPA_EN_OC_SDN_SEL_SHIFT}, + {PMIC_BUCK_VCORE_OC_FLAG_CLR, MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_ADDR, + MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_MASK, MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SHIFT}, + {PMIC_BUCK_VGPU_OC_FLAG_CLR, MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_ADDR, + MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_MASK, MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SHIFT}, + {PMIC_BUCK_VMODEM_OC_FLAG_CLR, MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_ADDR, + MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_MASK, MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SHIFT}, + {PMIC_BUCK_VMD1_OC_FLAG_CLR, MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_ADDR, + MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_MASK, MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SHIFT}, + {PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR, MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_MASK, MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SHIFT}, + {PMIC_BUCK_VS1_OC_FLAG_CLR, MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_ADDR, + MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_MASK, MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SHIFT}, + {PMIC_BUCK_VS2_OC_FLAG_CLR, MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_ADDR, + MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_MASK, MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SHIFT}, + {PMIC_BUCK_VPA_OC_FLAG_CLR, MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_ADDR, + MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_MASK, MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SHIFT}, + {PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL, MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_ADDR, + MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_MASK, + MT6351_PMIC_BUCK_VCORE_OC_FLAG_CLR_SEL_SHIFT}, + {PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL, MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL_ADDR, + MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL_MASK, MT6351_PMIC_BUCK_VGPU_OC_FLAG_CLR_SEL_SHIFT}, + {PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL, MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL_ADDR, + MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL_MASK, + MT6351_PMIC_BUCK_VMODEM_OC_FLAG_CLR_SEL_SHIFT}, + {PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL, MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL_ADDR, + MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL_MASK, MT6351_PMIC_BUCK_VMD1_OC_FLAG_CLR_SEL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL, + MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL_MASK, + MT6351_PMIC_BUCK_VSRAM_MD_OC_FLAG_CLR_SEL_SHIFT}, + {PMIC_BUCK_VS1_OC_FLAG_CLR_SEL, MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_ADDR, + MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_MASK, MT6351_PMIC_BUCK_VS1_OC_FLAG_CLR_SEL_SHIFT}, + {PMIC_BUCK_VS2_OC_FLAG_CLR_SEL, MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SEL_ADDR, + MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SEL_MASK, MT6351_PMIC_BUCK_VS2_OC_FLAG_CLR_SEL_SHIFT}, + {PMIC_BUCK_VPA_OC_FLAG_CLR_SEL, MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_ADDR, + MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_MASK, MT6351_PMIC_BUCK_VPA_OC_FLAG_CLR_SEL_SHIFT}, + {PMIC_BUCK_VCORE_OC_DEG_EN, MT6351_PMIC_BUCK_VCORE_OC_DEG_EN_ADDR, + MT6351_PMIC_BUCK_VCORE_OC_DEG_EN_MASK, MT6351_PMIC_BUCK_VCORE_OC_DEG_EN_SHIFT}, + {PMIC_BUCK_VCORE_OC_WND, MT6351_PMIC_BUCK_VCORE_OC_WND_ADDR, + MT6351_PMIC_BUCK_VCORE_OC_WND_MASK, MT6351_PMIC_BUCK_VCORE_OC_WND_SHIFT}, + {PMIC_BUCK_VCORE_OC_THD, MT6351_PMIC_BUCK_VCORE_OC_THD_ADDR, + MT6351_PMIC_BUCK_VCORE_OC_THD_MASK, MT6351_PMIC_BUCK_VCORE_OC_THD_SHIFT}, + {PMIC_BUCK_VGPU_OC_DEG_EN, MT6351_PMIC_BUCK_VGPU_OC_DEG_EN_ADDR, + MT6351_PMIC_BUCK_VGPU_OC_DEG_EN_MASK, MT6351_PMIC_BUCK_VGPU_OC_DEG_EN_SHIFT}, + {PMIC_BUCK_VGPU_OC_WND, MT6351_PMIC_BUCK_VGPU_OC_WND_ADDR, + MT6351_PMIC_BUCK_VGPU_OC_WND_MASK, MT6351_PMIC_BUCK_VGPU_OC_WND_SHIFT}, + {PMIC_BUCK_VGPU_OC_THD, MT6351_PMIC_BUCK_VGPU_OC_THD_ADDR, + MT6351_PMIC_BUCK_VGPU_OC_THD_MASK, MT6351_PMIC_BUCK_VGPU_OC_THD_SHIFT}, + {PMIC_BUCK_VMODEM_OC_DEG_EN, MT6351_PMIC_BUCK_VMODEM_OC_DEG_EN_ADDR, + MT6351_PMIC_BUCK_VMODEM_OC_DEG_EN_MASK, MT6351_PMIC_BUCK_VMODEM_OC_DEG_EN_SHIFT}, + {PMIC_BUCK_VMODEM_OC_WND, MT6351_PMIC_BUCK_VMODEM_OC_WND_ADDR, + MT6351_PMIC_BUCK_VMODEM_OC_WND_MASK, MT6351_PMIC_BUCK_VMODEM_OC_WND_SHIFT}, + {PMIC_BUCK_VMODEM_OC_THD, MT6351_PMIC_BUCK_VMODEM_OC_THD_ADDR, + MT6351_PMIC_BUCK_VMODEM_OC_THD_MASK, MT6351_PMIC_BUCK_VMODEM_OC_THD_SHIFT}, + {PMIC_BUCK_VMD1_OC_DEG_EN, MT6351_PMIC_BUCK_VMD1_OC_DEG_EN_ADDR, + MT6351_PMIC_BUCK_VMD1_OC_DEG_EN_MASK, MT6351_PMIC_BUCK_VMD1_OC_DEG_EN_SHIFT}, + {PMIC_BUCK_VMD1_OC_WND, MT6351_PMIC_BUCK_VMD1_OC_WND_ADDR, + MT6351_PMIC_BUCK_VMD1_OC_WND_MASK, MT6351_PMIC_BUCK_VMD1_OC_WND_SHIFT}, + {PMIC_BUCK_VMD1_OC_THD, MT6351_PMIC_BUCK_VMD1_OC_THD_ADDR, + MT6351_PMIC_BUCK_VMD1_OC_THD_MASK, MT6351_PMIC_BUCK_VMD1_OC_THD_SHIFT}, + {PMIC_BUCK_VSRAM_MD_OC_DEG_EN, MT6351_PMIC_BUCK_VSRAM_MD_OC_DEG_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_OC_DEG_EN_MASK, MT6351_PMIC_BUCK_VSRAM_MD_OC_DEG_EN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_OC_WND, MT6351_PMIC_BUCK_VSRAM_MD_OC_WND_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_OC_WND_MASK, MT6351_PMIC_BUCK_VSRAM_MD_OC_WND_SHIFT}, + {PMIC_BUCK_VSRAM_MD_OC_THD, MT6351_PMIC_BUCK_VSRAM_MD_OC_THD_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_OC_THD_MASK, MT6351_PMIC_BUCK_VSRAM_MD_OC_THD_SHIFT}, + {PMIC_BUCK_VS1_OC_DEG_EN, MT6351_PMIC_BUCK_VS1_OC_DEG_EN_ADDR, + MT6351_PMIC_BUCK_VS1_OC_DEG_EN_MASK, MT6351_PMIC_BUCK_VS1_OC_DEG_EN_SHIFT}, + {PMIC_BUCK_VS1_OC_WND, MT6351_PMIC_BUCK_VS1_OC_WND_ADDR, + MT6351_PMIC_BUCK_VS1_OC_WND_MASK, MT6351_PMIC_BUCK_VS1_OC_WND_SHIFT}, + {PMIC_BUCK_VS1_OC_THD, MT6351_PMIC_BUCK_VS1_OC_THD_ADDR, + MT6351_PMIC_BUCK_VS1_OC_THD_MASK, MT6351_PMIC_BUCK_VS1_OC_THD_SHIFT}, + {PMIC_BUCK_VS2_OC_DEG_EN, MT6351_PMIC_BUCK_VS2_OC_DEG_EN_ADDR, + MT6351_PMIC_BUCK_VS2_OC_DEG_EN_MASK, MT6351_PMIC_BUCK_VS2_OC_DEG_EN_SHIFT}, + {PMIC_BUCK_VS2_OC_WND, MT6351_PMIC_BUCK_VS2_OC_WND_ADDR, + MT6351_PMIC_BUCK_VS2_OC_WND_MASK, MT6351_PMIC_BUCK_VS2_OC_WND_SHIFT}, + {PMIC_BUCK_VS2_OC_THD, MT6351_PMIC_BUCK_VS2_OC_THD_ADDR, + MT6351_PMIC_BUCK_VS2_OC_THD_MASK, MT6351_PMIC_BUCK_VS2_OC_THD_SHIFT}, + {PMIC_BUCK_VPA_OC_DEG_EN, MT6351_PMIC_BUCK_VPA_OC_DEG_EN_ADDR, + MT6351_PMIC_BUCK_VPA_OC_DEG_EN_MASK, MT6351_PMIC_BUCK_VPA_OC_DEG_EN_SHIFT}, + {PMIC_BUCK_VPA_OC_WND, MT6351_PMIC_BUCK_VPA_OC_WND_ADDR, + MT6351_PMIC_BUCK_VPA_OC_WND_MASK, MT6351_PMIC_BUCK_VPA_OC_WND_SHIFT}, + {PMIC_BUCK_VPA_OC_THD, MT6351_PMIC_BUCK_VPA_OC_THD_ADDR, + MT6351_PMIC_BUCK_VPA_OC_THD_MASK, MT6351_PMIC_BUCK_VPA_OC_THD_SHIFT}, + {PMIC_RG_SMPS_TESTMODE_B, MT6351_PMIC_RG_SMPS_TESTMODE_B_ADDR, + MT6351_PMIC_RG_SMPS_TESTMODE_B_MASK, MT6351_PMIC_RG_SMPS_TESTMODE_B_SHIFT}, + {PMIC_RG_VPA_BURSTH, MT6351_PMIC_RG_VPA_BURSTH_ADDR, + MT6351_PMIC_RG_VPA_BURSTH_MASK, MT6351_PMIC_RG_VPA_BURSTH_SHIFT}, + {PMIC_RG_VPA_BURSTL, MT6351_PMIC_RG_VPA_BURSTL_ADDR, + MT6351_PMIC_RG_VPA_BURSTL_MASK, MT6351_PMIC_RG_VPA_BURSTL_SHIFT}, + {PMIC_RG_VPA_TRIMH, MT6351_PMIC_RG_VPA_TRIMH_ADDR, MT6351_PMIC_RG_VPA_TRIMH_MASK, + MT6351_PMIC_RG_VPA_TRIMH_SHIFT}, + {PMIC_RG_VPA_TRIML, MT6351_PMIC_RG_VPA_TRIML_ADDR, MT6351_PMIC_RG_VPA_TRIML_MASK, + MT6351_PMIC_RG_VPA_TRIML_SHIFT}, + {PMIC_RG_VPA_TRIM_REF, MT6351_PMIC_RG_VPA_TRIM_REF_ADDR, + MT6351_PMIC_RG_VPA_TRIM_REF_MASK, MT6351_PMIC_RG_VPA_TRIM_REF_SHIFT}, + {PMIC_RG_VCORE_TRIMH, MT6351_PMIC_RG_VCORE_TRIMH_ADDR, + MT6351_PMIC_RG_VCORE_TRIMH_MASK, MT6351_PMIC_RG_VCORE_TRIMH_SHIFT}, + {PMIC_RG_VCORE_TRIML, MT6351_PMIC_RG_VCORE_TRIML_ADDR, + MT6351_PMIC_RG_VCORE_TRIML_MASK, MT6351_PMIC_RG_VCORE_TRIML_SHIFT}, + {PMIC_RG_VCORE_VSLEEP, MT6351_PMIC_RG_VCORE_VSLEEP_ADDR, + MT6351_PMIC_RG_VCORE_VSLEEP_MASK, MT6351_PMIC_RG_VCORE_VSLEEP_SHIFT}, + {PMIC_RG_VGPU_TRIMH, MT6351_PMIC_RG_VGPU_TRIMH_ADDR, + MT6351_PMIC_RG_VGPU_TRIMH_MASK, MT6351_PMIC_RG_VGPU_TRIMH_SHIFT}, + {PMIC_RG_VGPU_TRIML, MT6351_PMIC_RG_VGPU_TRIML_ADDR, + MT6351_PMIC_RG_VGPU_TRIML_MASK, MT6351_PMIC_RG_VGPU_TRIML_SHIFT}, + {PMIC_RG_VGPU_VSLEEP, MT6351_PMIC_RG_VGPU_VSLEEP_ADDR, + MT6351_PMIC_RG_VGPU_VSLEEP_MASK, MT6351_PMIC_RG_VGPU_VSLEEP_SHIFT}, + {PMIC_RG_VSRAM_MD_TRIMH, MT6351_PMIC_RG_VSRAM_MD_TRIMH_ADDR, + MT6351_PMIC_RG_VSRAM_MD_TRIMH_MASK, MT6351_PMIC_RG_VSRAM_MD_TRIMH_SHIFT}, + {PMIC_RG_VSRAM_MD_TRIML, MT6351_PMIC_RG_VSRAM_MD_TRIML_ADDR, + MT6351_PMIC_RG_VSRAM_MD_TRIML_MASK, MT6351_PMIC_RG_VSRAM_MD_TRIML_SHIFT}, + {PMIC_RG_VSRAM_MD_VSLEEP, MT6351_PMIC_RG_VSRAM_MD_VSLEEP_ADDR, + MT6351_PMIC_RG_VSRAM_MD_VSLEEP_MASK, MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SHIFT}, + {PMIC_RG_VMODEM_TRIMH, MT6351_PMIC_RG_VMODEM_TRIMH_ADDR, + MT6351_PMIC_RG_VMODEM_TRIMH_MASK, MT6351_PMIC_RG_VMODEM_TRIMH_SHIFT}, + {PMIC_RG_VMODEM_TRIML, MT6351_PMIC_RG_VMODEM_TRIML_ADDR, + MT6351_PMIC_RG_VMODEM_TRIML_MASK, MT6351_PMIC_RG_VMODEM_TRIML_SHIFT}, + {PMIC_RG_VMODEM_VSLEEP, MT6351_PMIC_RG_VMODEM_VSLEEP_ADDR, + MT6351_PMIC_RG_VMODEM_VSLEEP_MASK, MT6351_PMIC_RG_VMODEM_VSLEEP_SHIFT}, + {PMIC_RG_VMD1_TRIMH, MT6351_PMIC_RG_VMD1_TRIMH_ADDR, + MT6351_PMIC_RG_VMD1_TRIMH_MASK, MT6351_PMIC_RG_VMD1_TRIMH_SHIFT}, + {PMIC_RG_VMD1_TRIML, MT6351_PMIC_RG_VMD1_TRIML_ADDR, + MT6351_PMIC_RG_VMD1_TRIML_MASK, MT6351_PMIC_RG_VMD1_TRIML_SHIFT}, + {PMIC_RG_VMD1_VSLEEP, MT6351_PMIC_RG_VMD1_VSLEEP_ADDR, + MT6351_PMIC_RG_VMD1_VSLEEP_MASK, MT6351_PMIC_RG_VMD1_VSLEEP_SHIFT}, + {PMIC_RG_VS1_TRIMH, MT6351_PMIC_RG_VS1_TRIMH_ADDR, MT6351_PMIC_RG_VS1_TRIMH_MASK, + MT6351_PMIC_RG_VS1_TRIMH_SHIFT}, + {PMIC_RG_VS1_TRIML, MT6351_PMIC_RG_VS1_TRIML_ADDR, MT6351_PMIC_RG_VS1_TRIML_MASK, + MT6351_PMIC_RG_VS1_TRIML_SHIFT}, + {PMIC_RG_VS1_VSLEEP, MT6351_PMIC_RG_VS1_VSLEEP_ADDR, + MT6351_PMIC_RG_VS1_VSLEEP_MASK, MT6351_PMIC_RG_VS1_VSLEEP_SHIFT}, + {PMIC_RG_VS2_TRIML, MT6351_PMIC_RG_VS2_TRIML_ADDR, MT6351_PMIC_RG_VS2_TRIML_MASK, + MT6351_PMIC_RG_VS2_TRIML_SHIFT}, + {PMIC_RG_VS2_VSLEEP, MT6351_PMIC_RG_VS2_VSLEEP_ADDR, + MT6351_PMIC_RG_VS2_VSLEEP_MASK, MT6351_PMIC_RG_VS2_VSLEEP_SHIFT}, + {PMIC_RG_VSRAM_PROCESSOR_TRIMH, MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIMH_ADDR, + MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIMH_MASK, MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIMH_SHIFT}, + {PMIC_RG_VSRAM_PROCESSOR_TRIML, MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIML_ADDR, + MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIML_MASK, MT6351_PMIC_RG_VSRAM_PROCESSOR_TRIML_SHIFT}, + {PMIC_RG_VSRAM_PROCESSOR_VSLEEP, MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_ADDR, + MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_MASK, MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SHIFT}, + {PMIC_RG_VCORE_VSLEEP_SEL, MT6351_PMIC_RG_VCORE_VSLEEP_SEL_ADDR, + MT6351_PMIC_RG_VCORE_VSLEEP_SEL_MASK, MT6351_PMIC_RG_VCORE_VSLEEP_SEL_SHIFT}, + {PMIC_RG_VGPU_VSLEEP_SEL, MT6351_PMIC_RG_VGPU_VSLEEP_SEL_ADDR, + MT6351_PMIC_RG_VGPU_VSLEEP_SEL_MASK, MT6351_PMIC_RG_VGPU_VSLEEP_SEL_SHIFT}, + {PMIC_RG_VSRAM_MD_VSLEEP_SEL, MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SEL_ADDR, + MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SEL_MASK, MT6351_PMIC_RG_VSRAM_MD_VSLEEP_SEL_SHIFT}, + {PMIC_RG_VMODEM_VSLEEP_SEL, MT6351_PMIC_RG_VMODEM_VSLEEP_SEL_ADDR, + MT6351_PMIC_RG_VMODEM_VSLEEP_SEL_MASK, MT6351_PMIC_RG_VMODEM_VSLEEP_SEL_SHIFT}, + {PMIC_RG_VMD1_VSLEEP_SEL, MT6351_PMIC_RG_VMD1_VSLEEP_SEL_ADDR, + MT6351_PMIC_RG_VMD1_VSLEEP_SEL_MASK, MT6351_PMIC_RG_VMD1_VSLEEP_SEL_SHIFT}, + {PMIC_RG_VS1_VSLEEP_SEL, MT6351_PMIC_RG_VS1_VSLEEP_SEL_ADDR, + MT6351_PMIC_RG_VS1_VSLEEP_SEL_MASK, MT6351_PMIC_RG_VS1_VSLEEP_SEL_SHIFT}, + {PMIC_RG_VS2_VSLEEP_SEL, MT6351_PMIC_RG_VS2_VSLEEP_SEL_ADDR, + MT6351_PMIC_RG_VS2_VSLEEP_SEL_MASK, MT6351_PMIC_RG_VS2_VSLEEP_SEL_SHIFT}, + {PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL, + MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL_ADDR, + MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL_MASK, + MT6351_PMIC_RG_VSRAM_PROCESSOR_VSLEEP_SEL_SHIFT}, + {PMIC_RG_VOUTDET_EN, MT6351_PMIC_RG_VOUTDET_EN_ADDR, + MT6351_PMIC_RG_VOUTDET_EN_MASK, MT6351_PMIC_RG_VOUTDET_EN_SHIFT}, + {PMIC_RG_VS2_TRIMH, MT6351_PMIC_RG_VS2_TRIMH_ADDR, MT6351_PMIC_RG_VS2_TRIMH_MASK, + MT6351_PMIC_RG_VS2_TRIMH_SHIFT}, + {PMIC_RG_VCORE_MODESET, MT6351_PMIC_RG_VCORE_MODESET_ADDR, + MT6351_PMIC_RG_VCORE_MODESET_MASK, MT6351_PMIC_RG_VCORE_MODESET_SHIFT}, + {PMIC_RG_VCORE_NDIS_EN, MT6351_PMIC_RG_VCORE_NDIS_EN_ADDR, + MT6351_PMIC_RG_VCORE_NDIS_EN_MASK, MT6351_PMIC_RG_VCORE_NDIS_EN_SHIFT}, + {PMIC_RG_VCORE_VRF18_SSTART_EN, MT6351_PMIC_RG_VCORE_VRF18_SSTART_EN_ADDR, + MT6351_PMIC_RG_VCORE_VRF18_SSTART_EN_MASK, MT6351_PMIC_RG_VCORE_VRF18_SSTART_EN_SHIFT}, + {PMIC_RG_VCORE_AUTO_MODE, MT6351_PMIC_RG_VCORE_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VCORE_AUTO_MODE_MASK, MT6351_PMIC_RG_VCORE_AUTO_MODE_SHIFT}, + {PMIC_RG_VCORE_RZSEL0, MT6351_PMIC_RG_VCORE_RZSEL0_ADDR, + MT6351_PMIC_RG_VCORE_RZSEL0_MASK, MT6351_PMIC_RG_VCORE_RZSEL0_SHIFT}, + {PMIC_RG_VCORE_RZSEL1, MT6351_PMIC_RG_VCORE_RZSEL1_ADDR, + MT6351_PMIC_RG_VCORE_RZSEL1_MASK, MT6351_PMIC_RG_VCORE_RZSEL1_SHIFT}, + {PMIC_RG_VCORE_CCSEL0, MT6351_PMIC_RG_VCORE_CCSEL0_ADDR, + MT6351_PMIC_RG_VCORE_CCSEL0_MASK, MT6351_PMIC_RG_VCORE_CCSEL0_SHIFT}, + {PMIC_RG_VCORE_CCSEL1, MT6351_PMIC_RG_VCORE_CCSEL1_ADDR, + MT6351_PMIC_RG_VCORE_CCSEL1_MASK, MT6351_PMIC_RG_VCORE_CCSEL1_SHIFT}, + {PMIC_RG_VCORE_CSL, MT6351_PMIC_RG_VCORE_CSL_ADDR, MT6351_PMIC_RG_VCORE_CSL_MASK, + MT6351_PMIC_RG_VCORE_CSL_SHIFT}, + {PMIC_RG_VCORE_SLP, MT6351_PMIC_RG_VCORE_SLP_ADDR, MT6351_PMIC_RG_VCORE_SLP_MASK, + MT6351_PMIC_RG_VCORE_SLP_SHIFT}, + {PMIC_RG_VCORE_ADRC_FEN, MT6351_PMIC_RG_VCORE_ADRC_FEN_ADDR, + MT6351_PMIC_RG_VCORE_ADRC_FEN_MASK, MT6351_PMIC_RG_VCORE_ADRC_FEN_SHIFT}, + {PMIC_RG_VCORE_VCCAP_CLAMP_FEN, MT6351_PMIC_RG_VCORE_VCCAP_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VCORE_VCCAP_CLAMP_FEN_MASK, MT6351_PMIC_RG_VCORE_VCCAP_CLAMP_FEN_SHIFT}, + {PMIC_RG_VCORE_VC_CLAMP_FEN, MT6351_PMIC_RG_VCORE_VC_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VCORE_VC_CLAMP_FEN_MASK, MT6351_PMIC_RG_VCORE_VC_CLAMP_FEN_SHIFT}, + {PMIC_RG_VCORE_PREOC_SEL, MT6351_PMIC_RG_VCORE_PREOC_SEL_ADDR, + MT6351_PMIC_RG_VCORE_PREOC_SEL_MASK, MT6351_PMIC_RG_VCORE_PREOC_SEL_SHIFT}, + {PMIC_RG_VCORE_PFMOC, MT6351_PMIC_RG_VCORE_PFMOC_ADDR, + MT6351_PMIC_RG_VCORE_PFMOC_MASK, MT6351_PMIC_RG_VCORE_PFMOC_SHIFT}, + {PMIC_RG_VCORE_CSR, MT6351_PMIC_RG_VCORE_CSR_ADDR, MT6351_PMIC_RG_VCORE_CSR_MASK, + MT6351_PMIC_RG_VCORE_CSR_SHIFT}, + {PMIC_RG_VCORE_ZXOS_TRIM, MT6351_PMIC_RG_VCORE_ZXOS_TRIM_ADDR, + MT6351_PMIC_RG_VCORE_ZXOS_TRIM_MASK, MT6351_PMIC_RG_VCORE_ZXOS_TRIM_SHIFT}, + {PMIC_RG_VCORE_CSM_N, MT6351_PMIC_RG_VCORE_CSM_N_ADDR, + MT6351_PMIC_RG_VCORE_CSM_N_MASK, MT6351_PMIC_RG_VCORE_CSM_N_SHIFT}, + {PMIC_RG_VCORE_CSM_P, MT6351_PMIC_RG_VCORE_CSM_P_ADDR, + MT6351_PMIC_RG_VCORE_CSM_P_MASK, MT6351_PMIC_RG_VCORE_CSM_P_SHIFT}, + {PMIC_RG_VCORE_PFMSR_EH, MT6351_PMIC_RG_VCORE_PFMSR_EH_ADDR, + MT6351_PMIC_RG_VCORE_PFMSR_EH_MASK, MT6351_PMIC_RG_VCORE_PFMSR_EH_SHIFT}, + {PMIC_RG_VCORE_NLIM_GATING, MT6351_PMIC_RG_VCORE_NLIM_GATING_ADDR, + MT6351_PMIC_RG_VCORE_NLIM_GATING_MASK, MT6351_PMIC_RG_VCORE_NLIM_GATING_SHIFT}, + {PMIC_RG_VCORE_PWRSR_EH, MT6351_PMIC_RG_VCORE_PWRSR_EH_ADDR, + MT6351_PMIC_RG_VCORE_PWRSR_EH_MASK, MT6351_PMIC_RG_VCORE_PWRSR_EH_SHIFT}, + {PMIC_RG_VCORE_HS_VTHDET, MT6351_PMIC_RG_VCORE_HS_VTHDET_ADDR, + MT6351_PMIC_RG_VCORE_HS_VTHDET_MASK, MT6351_PMIC_RG_VCORE_HS_VTHDET_SHIFT}, + {PMIC_RG_VCORE_PG_GATING, MT6351_PMIC_RG_VCORE_PG_GATING_ADDR, + MT6351_PMIC_RG_VCORE_PG_GATING_MASK, MT6351_PMIC_RG_VCORE_PG_GATING_SHIFT}, + {PMIC_RG_VCORE_HS_ONSPEED_EH, MT6351_PMIC_RG_VCORE_HS_ONSPEED_EH_ADDR, + MT6351_PMIC_RG_VCORE_HS_ONSPEED_EH_MASK, MT6351_PMIC_RG_VCORE_HS_ONSPEED_EH_SHIFT}, + {PMIC_RG_VCORE_NLIM_TRIMMING, MT6351_PMIC_RG_VCORE_NLIM_TRIMMING_ADDR, + MT6351_PMIC_RG_VCORE_NLIM_TRIMMING_MASK, MT6351_PMIC_RG_VCORE_NLIM_TRIMMING_SHIFT}, + {PMIC_RG_VCORE_DLC, MT6351_PMIC_RG_VCORE_DLC_ADDR, MT6351_PMIC_RG_VCORE_DLC_MASK, + MT6351_PMIC_RG_VCORE_DLC_SHIFT}, + {PMIC_RG_VCORE_DLC_N, MT6351_PMIC_RG_VCORE_DLC_N_ADDR, + MT6351_PMIC_RG_VCORE_DLC_N_MASK, MT6351_PMIC_RG_VCORE_DLC_N_SHIFT}, + {PMIC_RG_VCORE_PFM_RIP, MT6351_PMIC_RG_VCORE_PFM_RIP_ADDR, + MT6351_PMIC_RG_VCORE_PFM_RIP_MASK, MT6351_PMIC_RG_VCORE_PFM_RIP_SHIFT}, + {PMIC_RG_VCORE_TRAN_BST, MT6351_PMIC_RG_VCORE_TRAN_BST_ADDR, + MT6351_PMIC_RG_VCORE_TRAN_BST_MASK, MT6351_PMIC_RG_VCORE_TRAN_BST_SHIFT}, + {PMIC_RG_VCORE_DTS_ENB, MT6351_PMIC_RG_VCORE_DTS_ENB_ADDR, + MT6351_PMIC_RG_VCORE_DTS_ENB_MASK, MT6351_PMIC_RG_VCORE_DTS_ENB_SHIFT}, + {PMIC_RG_VCORE_MIN_OFF, MT6351_PMIC_RG_VCORE_MIN_OFF_ADDR, + MT6351_PMIC_RG_VCORE_MIN_OFF_MASK, MT6351_PMIC_RG_VCORE_MIN_OFF_SHIFT}, + {PMIC_RG_VCORE_1P35UP_SEL_EN, MT6351_PMIC_RG_VCORE_1P35UP_SEL_EN_ADDR, + MT6351_PMIC_RG_VCORE_1P35UP_SEL_EN_MASK, MT6351_PMIC_RG_VCORE_1P35UP_SEL_EN_SHIFT}, + {PMIC_RG_VCORE_DLC_AUTO_MODE, MT6351_PMIC_RG_VCORE_DLC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VCORE_DLC_AUTO_MODE_MASK, MT6351_PMIC_RG_VCORE_DLC_AUTO_MODE_SHIFT}, + {PMIC_RG_VCORE_DLC_SEL, MT6351_PMIC_RG_VCORE_DLC_SEL_ADDR, + MT6351_PMIC_RG_VCORE_DLC_SEL_MASK, MT6351_PMIC_RG_VCORE_DLC_SEL_SHIFT}, + {PMIC_RG_VCORE_SRC_AUTO_MODE, MT6351_PMIC_RG_VCORE_SRC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VCORE_SRC_AUTO_MODE_MASK, MT6351_PMIC_RG_VCORE_SRC_AUTO_MODE_SHIFT}, + {PMIC_RG_VCORE_UGP_SR, MT6351_PMIC_RG_VCORE_UGP_SR_ADDR, + MT6351_PMIC_RG_VCORE_UGP_SR_MASK, MT6351_PMIC_RG_VCORE_UGP_SR_SHIFT}, + {PMIC_RG_VCORE_LGN_SR, MT6351_PMIC_RG_VCORE_LGN_SR_ADDR, + MT6351_PMIC_RG_VCORE_LGN_SR_MASK, MT6351_PMIC_RG_VCORE_LGN_SR_SHIFT}, + {PMIC_RG_VCORE_UGP_SR_PFM, MT6351_PMIC_RG_VCORE_UGP_SR_PFM_ADDR, + MT6351_PMIC_RG_VCORE_UGP_SR_PFM_MASK, MT6351_PMIC_RG_VCORE_UGP_SR_PFM_SHIFT}, + {PMIC_RG_VCORE_LGN_SR_PFM, MT6351_PMIC_RG_VCORE_LGN_SR_PFM_ADDR, + MT6351_PMIC_RG_VCORE_LGN_SR_PFM_MASK, MT6351_PMIC_RG_VCORE_LGN_SR_PFM_SHIFT}, + {PMIC_RG_VCORE_UGD_VTHSEL, MT6351_PMIC_RG_VCORE_UGD_VTHSEL_ADDR, + MT6351_PMIC_RG_VCORE_UGD_VTHSEL_MASK, MT6351_PMIC_RG_VCORE_UGD_VTHSEL_SHIFT}, + {PMIC_RG_VCORE_FNLX_SNS, MT6351_PMIC_RG_VCORE_FNLX_SNS_ADDR, + MT6351_PMIC_RG_VCORE_FNLX_SNS_MASK, MT6351_PMIC_RG_VCORE_FNLX_SNS_SHIFT}, + {PMIC_RG_VCORE_VDIFF_ENLOWIQ, MT6351_PMIC_RG_VCORE_VDIFF_ENLOWIQ_ADDR, + MT6351_PMIC_RG_VCORE_VDIFF_ENLOWIQ_MASK, MT6351_PMIC_RG_VCORE_VDIFF_ENLOWIQ_SHIFT}, + {PMIC_RG_VCORE_PFMOC_FWUPOFF, MT6351_PMIC_RG_VCORE_PFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VCORE_PFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VCORE_PFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VCORE_PWFMOC_FWUPOFF, MT6351_PMIC_RG_VCORE_PWFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VCORE_PWFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VCORE_PWFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VCORE_CP_FWUPOFF, MT6351_PMIC_RG_VCORE_CP_FWUPOFF_ADDR, + MT6351_PMIC_RG_VCORE_CP_FWUPOFF_MASK, MT6351_PMIC_RG_VCORE_CP_FWUPOFF_SHIFT}, + {PMIC_RG_VCORE_ZX_GATING, MT6351_PMIC_RG_VCORE_ZX_GATING_ADDR, + MT6351_PMIC_RG_VCORE_ZX_GATING_MASK, MT6351_PMIC_RG_VCORE_ZX_GATING_SHIFT}, + {PMIC_RG_VCORE_RSV, MT6351_PMIC_RG_VCORE_RSV_ADDR, MT6351_PMIC_RG_VCORE_RSV_MASK, + MT6351_PMIC_RG_VCORE_RSV_SHIFT}, + {PMIC_RG_VCORE_PREOC_TRIMMING, MT6351_PMIC_RG_VCORE_PREOC_TRIMMING_ADDR, + MT6351_PMIC_RG_VCORE_PREOC_TRIMMING_MASK, MT6351_PMIC_RG_VCORE_PREOC_TRIMMING_SHIFT}, + {PMIC_RG_VCORE_AZC_EN, MT6351_PMIC_RG_VCORE_AZC_EN_ADDR, + MT6351_PMIC_RG_VCORE_AZC_EN_MASK, MT6351_PMIC_RG_VCORE_AZC_EN_SHIFT}, + {PMIC_RG_VCORE_AZC_DELAY, MT6351_PMIC_RG_VCORE_AZC_DELAY_ADDR, + MT6351_PMIC_RG_VCORE_AZC_DELAY_MASK, MT6351_PMIC_RG_VCORE_AZC_DELAY_SHIFT}, + {PMIC_RG_VCORE_AZC_HOLD_ENB, MT6351_PMIC_RG_VCORE_AZC_HOLD_ENB_ADDR, + MT6351_PMIC_RG_VCORE_AZC_HOLD_ENB_MASK, MT6351_PMIC_RG_VCORE_AZC_HOLD_ENB_SHIFT}, + {PMIC_RGS_QI_VCORE_OC_STATUS, MT6351_PMIC_RGS_QI_VCORE_OC_STATUS_ADDR, + MT6351_PMIC_RGS_QI_VCORE_OC_STATUS_MASK, MT6351_PMIC_RGS_QI_VCORE_OC_STATUS_SHIFT}, + {PMIC_RGS_QI_VCORE_DIG_MON, MT6351_PMIC_RGS_QI_VCORE_DIG_MON_ADDR, + MT6351_PMIC_RGS_QI_VCORE_DIG_MON_MASK, MT6351_PMIC_RGS_QI_VCORE_DIG_MON_SHIFT}, + {PMIC_RGS_VCORE_ENPWM_STATUS, MT6351_PMIC_RGS_VCORE_ENPWM_STATUS_ADDR, + MT6351_PMIC_RGS_VCORE_ENPWM_STATUS_MASK, MT6351_PMIC_RGS_VCORE_ENPWM_STATUS_SHIFT}, + {PMIC_RGS_QI_VCORE_PREOC, MT6351_PMIC_RGS_QI_VCORE_PREOC_ADDR, + MT6351_PMIC_RGS_QI_VCORE_PREOC_MASK, MT6351_PMIC_RGS_QI_VCORE_PREOC_SHIFT}, + {PMIC_RG_VGPU_MODESET, MT6351_PMIC_RG_VGPU_MODESET_ADDR, + MT6351_PMIC_RG_VGPU_MODESET_MASK, MT6351_PMIC_RG_VGPU_MODESET_SHIFT}, + {PMIC_RG_VGPU_NDIS_EN, MT6351_PMIC_RG_VGPU_NDIS_EN_ADDR, + MT6351_PMIC_RG_VGPU_NDIS_EN_MASK, MT6351_PMIC_RG_VGPU_NDIS_EN_SHIFT}, + {PMIC_RG_VGPU_VRF18_SSTART_EN, MT6351_PMIC_RG_VGPU_VRF18_SSTART_EN_ADDR, + MT6351_PMIC_RG_VGPU_VRF18_SSTART_EN_MASK, MT6351_PMIC_RG_VGPU_VRF18_SSTART_EN_SHIFT}, + {PMIC_RG_VGPU_AUTO_MODE, MT6351_PMIC_RG_VGPU_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VGPU_AUTO_MODE_MASK, MT6351_PMIC_RG_VGPU_AUTO_MODE_SHIFT}, + {PMIC_RG_VGPU_RZSEL0, MT6351_PMIC_RG_VGPU_RZSEL0_ADDR, + MT6351_PMIC_RG_VGPU_RZSEL0_MASK, MT6351_PMIC_RG_VGPU_RZSEL0_SHIFT}, + {PMIC_RG_VGPU_RZSEL1, MT6351_PMIC_RG_VGPU_RZSEL1_ADDR, + MT6351_PMIC_RG_VGPU_RZSEL1_MASK, MT6351_PMIC_RG_VGPU_RZSEL1_SHIFT}, + {PMIC_RG_VGPU_CCSEL0, MT6351_PMIC_RG_VGPU_CCSEL0_ADDR, + MT6351_PMIC_RG_VGPU_CCSEL0_MASK, MT6351_PMIC_RG_VGPU_CCSEL0_SHIFT}, + {PMIC_RG_VGPU_CCSEL1, MT6351_PMIC_RG_VGPU_CCSEL1_ADDR, + MT6351_PMIC_RG_VGPU_CCSEL1_MASK, MT6351_PMIC_RG_VGPU_CCSEL1_SHIFT}, + {PMIC_RG_VGPU_CSL, MT6351_PMIC_RG_VGPU_CSL_ADDR, MT6351_PMIC_RG_VGPU_CSL_MASK, + MT6351_PMIC_RG_VGPU_CSL_SHIFT}, + {PMIC_RG_VGPU_SLP, MT6351_PMIC_RG_VGPU_SLP_ADDR, MT6351_PMIC_RG_VGPU_SLP_MASK, + MT6351_PMIC_RG_VGPU_SLP_SHIFT}, + {PMIC_RG_VGPU_ADRC_FEN, MT6351_PMIC_RG_VGPU_ADRC_FEN_ADDR, + MT6351_PMIC_RG_VGPU_ADRC_FEN_MASK, MT6351_PMIC_RG_VGPU_ADRC_FEN_SHIFT}, + {PMIC_RG_VGPU_VCCAP_CLAMP_FEN, MT6351_PMIC_RG_VGPU_VCCAP_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VGPU_VCCAP_CLAMP_FEN_MASK, MT6351_PMIC_RG_VGPU_VCCAP_CLAMP_FEN_SHIFT}, + {PMIC_RG_VGPU_VC_CLAMP_FEN, MT6351_PMIC_RG_VGPU_VC_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VGPU_VC_CLAMP_FEN_MASK, MT6351_PMIC_RG_VGPU_VC_CLAMP_FEN_SHIFT}, + {PMIC_RG_VGPU_PREOC_SEL, MT6351_PMIC_RG_VGPU_PREOC_SEL_ADDR, + MT6351_PMIC_RG_VGPU_PREOC_SEL_MASK, MT6351_PMIC_RG_VGPU_PREOC_SEL_SHIFT}, + {PMIC_RG_VGPU_PFMOC, MT6351_PMIC_RG_VGPU_PFMOC_ADDR, + MT6351_PMIC_RG_VGPU_PFMOC_MASK, MT6351_PMIC_RG_VGPU_PFMOC_SHIFT}, + {PMIC_RG_VGPU_CSR, MT6351_PMIC_RG_VGPU_CSR_ADDR, MT6351_PMIC_RG_VGPU_CSR_MASK, + MT6351_PMIC_RG_VGPU_CSR_SHIFT}, + {PMIC_RG_VGPU_ZXOS_TRIM, MT6351_PMIC_RG_VGPU_ZXOS_TRIM_ADDR, + MT6351_PMIC_RG_VGPU_ZXOS_TRIM_MASK, MT6351_PMIC_RG_VGPU_ZXOS_TRIM_SHIFT}, + {PMIC_RG_VGPU_CSM_N, MT6351_PMIC_RG_VGPU_CSM_N_ADDR, + MT6351_PMIC_RG_VGPU_CSM_N_MASK, MT6351_PMIC_RG_VGPU_CSM_N_SHIFT}, + {PMIC_RG_VGPU_CSM_P, MT6351_PMIC_RG_VGPU_CSM_P_ADDR, + MT6351_PMIC_RG_VGPU_CSM_P_MASK, MT6351_PMIC_RG_VGPU_CSM_P_SHIFT}, + {PMIC_RG_VGPU_PFMSR_EH, MT6351_PMIC_RG_VGPU_PFMSR_EH_ADDR, + MT6351_PMIC_RG_VGPU_PFMSR_EH_MASK, MT6351_PMIC_RG_VGPU_PFMSR_EH_SHIFT}, + {PMIC_RG_VGPU_NLIM_GATING, MT6351_PMIC_RG_VGPU_NLIM_GATING_ADDR, + MT6351_PMIC_RG_VGPU_NLIM_GATING_MASK, MT6351_PMIC_RG_VGPU_NLIM_GATING_SHIFT}, + {PMIC_RG_VGPU_PWRSR_EH, MT6351_PMIC_RG_VGPU_PWRSR_EH_ADDR, + MT6351_PMIC_RG_VGPU_PWRSR_EH_MASK, MT6351_PMIC_RG_VGPU_PWRSR_EH_SHIFT}, + {PMIC_RG_VGPU_HS_VTHDET, MT6351_PMIC_RG_VGPU_HS_VTHDET_ADDR, + MT6351_PMIC_RG_VGPU_HS_VTHDET_MASK, MT6351_PMIC_RG_VGPU_HS_VTHDET_SHIFT}, + {PMIC_RG_VGPU_PG_GATING, MT6351_PMIC_RG_VGPU_PG_GATING_ADDR, + MT6351_PMIC_RG_VGPU_PG_GATING_MASK, MT6351_PMIC_RG_VGPU_PG_GATING_SHIFT}, + {PMIC_RG_VGPU_HS_ONSPEED_EH, MT6351_PMIC_RG_VGPU_HS_ONSPEED_EH_ADDR, + MT6351_PMIC_RG_VGPU_HS_ONSPEED_EH_MASK, MT6351_PMIC_RG_VGPU_HS_ONSPEED_EH_SHIFT}, + {PMIC_RG_VGPU_NLIM_TRIMMING, MT6351_PMIC_RG_VGPU_NLIM_TRIMMING_ADDR, + MT6351_PMIC_RG_VGPU_NLIM_TRIMMING_MASK, MT6351_PMIC_RG_VGPU_NLIM_TRIMMING_SHIFT}, + {PMIC_RG_VGPU_DLC, MT6351_PMIC_RG_VGPU_DLC_ADDR, MT6351_PMIC_RG_VGPU_DLC_MASK, + MT6351_PMIC_RG_VGPU_DLC_SHIFT}, + {PMIC_RG_VGPU_DLC_N, MT6351_PMIC_RG_VGPU_DLC_N_ADDR, + MT6351_PMIC_RG_VGPU_DLC_N_MASK, MT6351_PMIC_RG_VGPU_DLC_N_SHIFT}, + {PMIC_RG_VGPU_PFM_RIP, MT6351_PMIC_RG_VGPU_PFM_RIP_ADDR, + MT6351_PMIC_RG_VGPU_PFM_RIP_MASK, MT6351_PMIC_RG_VGPU_PFM_RIP_SHIFT}, + {PMIC_RG_VGPU_TRAN_BST, MT6351_PMIC_RG_VGPU_TRAN_BST_ADDR, + MT6351_PMIC_RG_VGPU_TRAN_BST_MASK, MT6351_PMIC_RG_VGPU_TRAN_BST_SHIFT}, + {PMIC_RG_VGPU_DTS_ENB, MT6351_PMIC_RG_VGPU_DTS_ENB_ADDR, + MT6351_PMIC_RG_VGPU_DTS_ENB_MASK, MT6351_PMIC_RG_VGPU_DTS_ENB_SHIFT}, + {PMIC_RG_VGPU_MIN_OFF, MT6351_PMIC_RG_VGPU_MIN_OFF_ADDR, + MT6351_PMIC_RG_VGPU_MIN_OFF_MASK, MT6351_PMIC_RG_VGPU_MIN_OFF_SHIFT}, + {PMIC_RG_VGPU_1P35UP_SEL_EN, MT6351_PMIC_RG_VGPU_1P35UP_SEL_EN_ADDR, + MT6351_PMIC_RG_VGPU_1P35UP_SEL_EN_MASK, MT6351_PMIC_RG_VGPU_1P35UP_SEL_EN_SHIFT}, + {PMIC_RG_VGPU_DLC_AUTO_MODE, MT6351_PMIC_RG_VGPU_DLC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VGPU_DLC_AUTO_MODE_MASK, MT6351_PMIC_RG_VGPU_DLC_AUTO_MODE_SHIFT}, + {PMIC_RG_VGPU_DLC_SEL, MT6351_PMIC_RG_VGPU_DLC_SEL_ADDR, + MT6351_PMIC_RG_VGPU_DLC_SEL_MASK, MT6351_PMIC_RG_VGPU_DLC_SEL_SHIFT}, + {PMIC_RG_VGPU_SRC_AUTO_MODE, MT6351_PMIC_RG_VGPU_SRC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VGPU_SRC_AUTO_MODE_MASK, MT6351_PMIC_RG_VGPU_SRC_AUTO_MODE_SHIFT}, + {PMIC_RG_VGPU_UGP_SR, MT6351_PMIC_RG_VGPU_UGP_SR_ADDR, + MT6351_PMIC_RG_VGPU_UGP_SR_MASK, MT6351_PMIC_RG_VGPU_UGP_SR_SHIFT}, + {PMIC_RG_VGPU_LGN_SR, MT6351_PMIC_RG_VGPU_LGN_SR_ADDR, + MT6351_PMIC_RG_VGPU_LGN_SR_MASK, MT6351_PMIC_RG_VGPU_LGN_SR_SHIFT}, + {PMIC_RG_VGPU_UGP_SR_PFM, MT6351_PMIC_RG_VGPU_UGP_SR_PFM_ADDR, + MT6351_PMIC_RG_VGPU_UGP_SR_PFM_MASK, MT6351_PMIC_RG_VGPU_UGP_SR_PFM_SHIFT}, + {PMIC_RG_VGPU_LGN_SR_PFM, MT6351_PMIC_RG_VGPU_LGN_SR_PFM_ADDR, + MT6351_PMIC_RG_VGPU_LGN_SR_PFM_MASK, MT6351_PMIC_RG_VGPU_LGN_SR_PFM_SHIFT}, + {PMIC_RG_VGPU_UGD_VTHSEL, MT6351_PMIC_RG_VGPU_UGD_VTHSEL_ADDR, + MT6351_PMIC_RG_VGPU_UGD_VTHSEL_MASK, MT6351_PMIC_RG_VGPU_UGD_VTHSEL_SHIFT}, + {PMIC_RG_VGPU_FNLX_SNS, MT6351_PMIC_RG_VGPU_FNLX_SNS_ADDR, + MT6351_PMIC_RG_VGPU_FNLX_SNS_MASK, MT6351_PMIC_RG_VGPU_FNLX_SNS_SHIFT}, + {PMIC_RG_VGPU_VDIFF_ENLOWIQ, MT6351_PMIC_RG_VGPU_VDIFF_ENLOWIQ_ADDR, + MT6351_PMIC_RG_VGPU_VDIFF_ENLOWIQ_MASK, MT6351_PMIC_RG_VGPU_VDIFF_ENLOWIQ_SHIFT}, + {PMIC_RG_VGPU_PFMOC_FWUPOFF, MT6351_PMIC_RG_VGPU_PFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VGPU_PFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VGPU_PFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VGPU_PWFMOC_FWUPOFF, MT6351_PMIC_RG_VGPU_PWFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VGPU_PWFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VGPU_PWFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VGPU_CP_FWUPOFF, MT6351_PMIC_RG_VGPU_CP_FWUPOFF_ADDR, + MT6351_PMIC_RG_VGPU_CP_FWUPOFF_MASK, MT6351_PMIC_RG_VGPU_CP_FWUPOFF_SHIFT}, + {PMIC_RG_VGPU_ZX_GATING, MT6351_PMIC_RG_VGPU_ZX_GATING_ADDR, + MT6351_PMIC_RG_VGPU_ZX_GATING_MASK, MT6351_PMIC_RG_VGPU_ZX_GATING_SHIFT}, + {PMIC_RG_VGPU_RSV, MT6351_PMIC_RG_VGPU_RSV_ADDR, MT6351_PMIC_RG_VGPU_RSV_MASK, + MT6351_PMIC_RG_VGPU_RSV_SHIFT}, + {PMIC_RG_VGPU_PREOC_TRIMMING, MT6351_PMIC_RG_VGPU_PREOC_TRIMMING_ADDR, + MT6351_PMIC_RG_VGPU_PREOC_TRIMMING_MASK, MT6351_PMIC_RG_VGPU_PREOC_TRIMMING_SHIFT}, + {PMIC_RG_VGPU_AZC_EN, MT6351_PMIC_RG_VGPU_AZC_EN_ADDR, + MT6351_PMIC_RG_VGPU_AZC_EN_MASK, MT6351_PMIC_RG_VGPU_AZC_EN_SHIFT}, + {PMIC_RG_VGPU_AZC_DELAY, MT6351_PMIC_RG_VGPU_AZC_DELAY_ADDR, + MT6351_PMIC_RG_VGPU_AZC_DELAY_MASK, MT6351_PMIC_RG_VGPU_AZC_DELAY_SHIFT}, + {PMIC_RG_VGPU_AZC_HOLD_ENB, MT6351_PMIC_RG_VGPU_AZC_HOLD_ENB_ADDR, + MT6351_PMIC_RG_VGPU_AZC_HOLD_ENB_MASK, MT6351_PMIC_RG_VGPU_AZC_HOLD_ENB_SHIFT}, + {PMIC_RGS_QI_VGPU_OC_STATUS, MT6351_PMIC_RGS_QI_VGPU_OC_STATUS_ADDR, + MT6351_PMIC_RGS_QI_VGPU_OC_STATUS_MASK, MT6351_PMIC_RGS_QI_VGPU_OC_STATUS_SHIFT}, + {PMIC_RGS_QI_VGPU_DIG_MON, MT6351_PMIC_RGS_QI_VGPU_DIG_MON_ADDR, + MT6351_PMIC_RGS_QI_VGPU_DIG_MON_MASK, MT6351_PMIC_RGS_QI_VGPU_DIG_MON_SHIFT}, + {PMIC_RGS_VGPU_ENPWM_STATUS, MT6351_PMIC_RGS_VGPU_ENPWM_STATUS_ADDR, + MT6351_PMIC_RGS_VGPU_ENPWM_STATUS_MASK, MT6351_PMIC_RGS_VGPU_ENPWM_STATUS_SHIFT}, + {PMIC_RGS_QI_VGPU_PREOC, MT6351_PMIC_RGS_QI_VGPU_PREOC_ADDR, + MT6351_PMIC_RGS_QI_VGPU_PREOC_MASK, MT6351_PMIC_RGS_QI_VGPU_PREOC_SHIFT}, + {PMIC_RG_VSRAM_MD_MODESET, MT6351_PMIC_RG_VSRAM_MD_MODESET_ADDR, + MT6351_PMIC_RG_VSRAM_MD_MODESET_MASK, MT6351_PMIC_RG_VSRAM_MD_MODESET_SHIFT}, + {PMIC_RG_VSRAM_MD_NDIS_EN, MT6351_PMIC_RG_VSRAM_MD_NDIS_EN_ADDR, + MT6351_PMIC_RG_VSRAM_MD_NDIS_EN_MASK, MT6351_PMIC_RG_VSRAM_MD_NDIS_EN_SHIFT}, + {PMIC_RG_VSRAM_MD_VRF18_SSTART_EN, MT6351_PMIC_RG_VSRAM_MD_VRF18_SSTART_EN_ADDR, + MT6351_PMIC_RG_VSRAM_MD_VRF18_SSTART_EN_MASK, + MT6351_PMIC_RG_VSRAM_MD_VRF18_SSTART_EN_SHIFT}, + {PMIC_RG_VSRAM_MD_AUTO_MODE, MT6351_PMIC_RG_VSRAM_MD_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VSRAM_MD_AUTO_MODE_MASK, MT6351_PMIC_RG_VSRAM_MD_AUTO_MODE_SHIFT}, + {PMIC_RG_VSRAM_MD_RZSEL0, MT6351_PMIC_RG_VSRAM_MD_RZSEL0_ADDR, + MT6351_PMIC_RG_VSRAM_MD_RZSEL0_MASK, MT6351_PMIC_RG_VSRAM_MD_RZSEL0_SHIFT}, + {PMIC_RG_VSRAM_MD_RZSEL1, MT6351_PMIC_RG_VSRAM_MD_RZSEL1_ADDR, + MT6351_PMIC_RG_VSRAM_MD_RZSEL1_MASK, MT6351_PMIC_RG_VSRAM_MD_RZSEL1_SHIFT}, + {PMIC_RG_VSRAM_MD_CCSEL0, MT6351_PMIC_RG_VSRAM_MD_CCSEL0_ADDR, + MT6351_PMIC_RG_VSRAM_MD_CCSEL0_MASK, MT6351_PMIC_RG_VSRAM_MD_CCSEL0_SHIFT}, + {PMIC_RG_VSRAM_MD_CCSEL1, MT6351_PMIC_RG_VSRAM_MD_CCSEL1_ADDR, + MT6351_PMIC_RG_VSRAM_MD_CCSEL1_MASK, MT6351_PMIC_RG_VSRAM_MD_CCSEL1_SHIFT}, + {PMIC_RG_VSRAM_MD_CSL, MT6351_PMIC_RG_VSRAM_MD_CSL_ADDR, + MT6351_PMIC_RG_VSRAM_MD_CSL_MASK, MT6351_PMIC_RG_VSRAM_MD_CSL_SHIFT}, + {PMIC_RG_VSRAM_MD_SLP, MT6351_PMIC_RG_VSRAM_MD_SLP_ADDR, + MT6351_PMIC_RG_VSRAM_MD_SLP_MASK, MT6351_PMIC_RG_VSRAM_MD_SLP_SHIFT}, + {PMIC_RG_VSRAM_MD_ADRC_FEN, MT6351_PMIC_RG_VSRAM_MD_ADRC_FEN_ADDR, + MT6351_PMIC_RG_VSRAM_MD_ADRC_FEN_MASK, MT6351_PMIC_RG_VSRAM_MD_ADRC_FEN_SHIFT}, + {PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN, MT6351_PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN_MASK, + MT6351_PMIC_RG_VSRAM_MD_VCCAP_CLAMP_FEN_SHIFT}, + {PMIC_RG_VSRAM_MD_VC_CLAMP_FEN, MT6351_PMIC_RG_VSRAM_MD_VC_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VSRAM_MD_VC_CLAMP_FEN_MASK, MT6351_PMIC_RG_VSRAM_MD_VC_CLAMP_FEN_SHIFT}, + {PMIC_RG_VSRAM_MD_PFMOC, MT6351_PMIC_RG_VSRAM_MD_PFMOC_ADDR, + MT6351_PMIC_RG_VSRAM_MD_PFMOC_MASK, MT6351_PMIC_RG_VSRAM_MD_PFMOC_SHIFT}, + {PMIC_RG_VSRAM_MD_CSR, MT6351_PMIC_RG_VSRAM_MD_CSR_ADDR, + MT6351_PMIC_RG_VSRAM_MD_CSR_MASK, MT6351_PMIC_RG_VSRAM_MD_CSR_SHIFT}, + {PMIC_RG_VSRAM_MD_ZXOS_TRIM, MT6351_PMIC_RG_VSRAM_MD_ZXOS_TRIM_ADDR, + MT6351_PMIC_RG_VSRAM_MD_ZXOS_TRIM_MASK, MT6351_PMIC_RG_VSRAM_MD_ZXOS_TRIM_SHIFT}, + {PMIC_RG_VSRAM_MD_PFMSR_EH, MT6351_PMIC_RG_VSRAM_MD_PFMSR_EH_ADDR, + MT6351_PMIC_RG_VSRAM_MD_PFMSR_EH_MASK, MT6351_PMIC_RG_VSRAM_MD_PFMSR_EH_SHIFT}, + {PMIC_RG_VSRAM_MD_NLIM_GATING, MT6351_PMIC_RG_VSRAM_MD_NLIM_GATING_ADDR, + MT6351_PMIC_RG_VSRAM_MD_NLIM_GATING_MASK, MT6351_PMIC_RG_VSRAM_MD_NLIM_GATING_SHIFT}, + {PMIC_RG_VSRAM_MD_PWRSR_EH, MT6351_PMIC_RG_VSRAM_MD_PWRSR_EH_ADDR, + MT6351_PMIC_RG_VSRAM_MD_PWRSR_EH_MASK, MT6351_PMIC_RG_VSRAM_MD_PWRSR_EH_SHIFT}, + {PMIC_RG_VSRAM_MD_HS_VTHDET, MT6351_PMIC_RG_VSRAM_MD_HS_VTHDET_ADDR, + MT6351_PMIC_RG_VSRAM_MD_HS_VTHDET_MASK, MT6351_PMIC_RG_VSRAM_MD_HS_VTHDET_SHIFT}, + {PMIC_RG_VSRAM_MD_PG_GATING, MT6351_PMIC_RG_VSRAM_MD_PG_GATING_ADDR, + MT6351_PMIC_RG_VSRAM_MD_PG_GATING_MASK, MT6351_PMIC_RG_VSRAM_MD_PG_GATING_SHIFT}, + {PMIC_RG_VSRAM_MD_HS_ONSPEED_EH, MT6351_PMIC_RG_VSRAM_MD_HS_ONSPEED_EH_ADDR, + MT6351_PMIC_RG_VSRAM_MD_HS_ONSPEED_EH_MASK, MT6351_PMIC_RG_VSRAM_MD_HS_ONSPEED_EH_SHIFT}, + {PMIC_RG_VSRAM_MD_NLIM_TRIMMING, MT6351_PMIC_RG_VSRAM_MD_NLIM_TRIMMING_ADDR, + MT6351_PMIC_RG_VSRAM_MD_NLIM_TRIMMING_MASK, MT6351_PMIC_RG_VSRAM_MD_NLIM_TRIMMING_SHIFT}, + {PMIC_RG_VSRAM_MD_DLC, MT6351_PMIC_RG_VSRAM_MD_DLC_ADDR, + MT6351_PMIC_RG_VSRAM_MD_DLC_MASK, MT6351_PMIC_RG_VSRAM_MD_DLC_SHIFT}, + {PMIC_RG_VSRAM_MD_DLC_N, MT6351_PMIC_RG_VSRAM_MD_DLC_N_ADDR, + MT6351_PMIC_RG_VSRAM_MD_DLC_N_MASK, MT6351_PMIC_RG_VSRAM_MD_DLC_N_SHIFT}, + {PMIC_RG_VSRAM_MD_PFM_RIP, MT6351_PMIC_RG_VSRAM_MD_PFM_RIP_ADDR, + MT6351_PMIC_RG_VSRAM_MD_PFM_RIP_MASK, MT6351_PMIC_RG_VSRAM_MD_PFM_RIP_SHIFT}, + {PMIC_RG_VSRAM_MD_TRAN_BST, MT6351_PMIC_RG_VSRAM_MD_TRAN_BST_ADDR, + MT6351_PMIC_RG_VSRAM_MD_TRAN_BST_MASK, MT6351_PMIC_RG_VSRAM_MD_TRAN_BST_SHIFT}, + {PMIC_RG_VSRAM_MD_DTS_ENB, MT6351_PMIC_RG_VSRAM_MD_DTS_ENB_ADDR, + MT6351_PMIC_RG_VSRAM_MD_DTS_ENB_MASK, MT6351_PMIC_RG_VSRAM_MD_DTS_ENB_SHIFT}, + {PMIC_RG_VSRAM_MD_MIN_OFF, MT6351_PMIC_RG_VSRAM_MD_MIN_OFF_ADDR, + MT6351_PMIC_RG_VSRAM_MD_MIN_OFF_MASK, MT6351_PMIC_RG_VSRAM_MD_MIN_OFF_SHIFT}, + {PMIC_RG_VSRAM_MD_1P35UP_SEL_EN, MT6351_PMIC_RG_VSRAM_MD_1P35UP_SEL_EN_ADDR, + MT6351_PMIC_RG_VSRAM_MD_1P35UP_SEL_EN_MASK, MT6351_PMIC_RG_VSRAM_MD_1P35UP_SEL_EN_SHIFT}, + {PMIC_RG_VSRAM_MD_DLC_AUTO_MODE, MT6351_PMIC_RG_VSRAM_MD_DLC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VSRAM_MD_DLC_AUTO_MODE_MASK, MT6351_PMIC_RG_VSRAM_MD_DLC_AUTO_MODE_SHIFT}, + {PMIC_RG_VSRAM_MD_DLC_SEL, MT6351_PMIC_RG_VSRAM_MD_DLC_SEL_ADDR, + MT6351_PMIC_RG_VSRAM_MD_DLC_SEL_MASK, MT6351_PMIC_RG_VSRAM_MD_DLC_SEL_SHIFT}, + {PMIC_RG_VSRAM_MD_SRC_AUTO_MODE, MT6351_PMIC_RG_VSRAM_MD_SRC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VSRAM_MD_SRC_AUTO_MODE_MASK, MT6351_PMIC_RG_VSRAM_MD_SRC_AUTO_MODE_SHIFT}, + {PMIC_RG_VSRAM_MD_UGP_SR, MT6351_PMIC_RG_VSRAM_MD_UGP_SR_ADDR, + MT6351_PMIC_RG_VSRAM_MD_UGP_SR_MASK, MT6351_PMIC_RG_VSRAM_MD_UGP_SR_SHIFT}, + {PMIC_RG_VSRAM_MD_LGN_SR, MT6351_PMIC_RG_VSRAM_MD_LGN_SR_ADDR, + MT6351_PMIC_RG_VSRAM_MD_LGN_SR_MASK, MT6351_PMIC_RG_VSRAM_MD_LGN_SR_SHIFT}, + {PMIC_RG_VSRAM_MD_UGP_SR_PFM, MT6351_PMIC_RG_VSRAM_MD_UGP_SR_PFM_ADDR, + MT6351_PMIC_RG_VSRAM_MD_UGP_SR_PFM_MASK, MT6351_PMIC_RG_VSRAM_MD_UGP_SR_PFM_SHIFT}, + {PMIC_RG_VSRAM_MD_LGN_SR_PFM, MT6351_PMIC_RG_VSRAM_MD_LGN_SR_PFM_ADDR, + MT6351_PMIC_RG_VSRAM_MD_LGN_SR_PFM_MASK, MT6351_PMIC_RG_VSRAM_MD_LGN_SR_PFM_SHIFT}, + {PMIC_RG_VSRAM_MD_UGD_VTHSEL, MT6351_PMIC_RG_VSRAM_MD_UGD_VTHSEL_ADDR, + MT6351_PMIC_RG_VSRAM_MD_UGD_VTHSEL_MASK, MT6351_PMIC_RG_VSRAM_MD_UGD_VTHSEL_SHIFT}, + {PMIC_RG_VSRAM_MD_FNLX_SNS, MT6351_PMIC_RG_VSRAM_MD_FNLX_SNS_ADDR, + MT6351_PMIC_RG_VSRAM_MD_FNLX_SNS_MASK, MT6351_PMIC_RG_VSRAM_MD_FNLX_SNS_SHIFT}, + {PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ, MT6351_PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ_ADDR, + MT6351_PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ_MASK, MT6351_PMIC_RG_VSRAM_MD_VDIFF_ENLOWIQ_SHIFT}, + {PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF, MT6351_PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VSRAM_MD_PFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF, MT6351_PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF_MASK, + MT6351_PMIC_RG_VSRAM_MD_PWFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VSRAM_MD_CP_FWUPOFF, MT6351_PMIC_RG_VSRAM_MD_CP_FWUPOFF_ADDR, + MT6351_PMIC_RG_VSRAM_MD_CP_FWUPOFF_MASK, MT6351_PMIC_RG_VSRAM_MD_CP_FWUPOFF_SHIFT}, + {PMIC_RG_VSRAM_MD_ZX_GATING, MT6351_PMIC_RG_VSRAM_MD_ZX_GATING_ADDR, + MT6351_PMIC_RG_VSRAM_MD_ZX_GATING_MASK, MT6351_PMIC_RG_VSRAM_MD_ZX_GATING_SHIFT}, + {PMIC_RG_VSRAM_MD_RSV, MT6351_PMIC_RG_VSRAM_MD_RSV_ADDR, + MT6351_PMIC_RG_VSRAM_MD_RSV_MASK, MT6351_PMIC_RG_VSRAM_MD_RSV_SHIFT}, + {PMIC_RG_VSRAM_MD_AZC_EN, MT6351_PMIC_RG_VSRAM_MD_AZC_EN_ADDR, + MT6351_PMIC_RG_VSRAM_MD_AZC_EN_MASK, MT6351_PMIC_RG_VSRAM_MD_AZC_EN_SHIFT}, + {PMIC_RG_VSRAM_MD_AZC_DELAY, MT6351_PMIC_RG_VSRAM_MD_AZC_DELAY_ADDR, + MT6351_PMIC_RG_VSRAM_MD_AZC_DELAY_MASK, MT6351_PMIC_RG_VSRAM_MD_AZC_DELAY_SHIFT}, + {PMIC_RG_VSRAM_MD_AZC_HOLD_ENB, MT6351_PMIC_RG_VSRAM_MD_AZC_HOLD_ENB_ADDR, + MT6351_PMIC_RG_VSRAM_MD_AZC_HOLD_ENB_MASK, MT6351_PMIC_RG_VSRAM_MD_AZC_HOLD_ENB_SHIFT}, + {PMIC_RGS_QI_VSRAM_MD_OC_STATUS, MT6351_PMIC_RGS_QI_VSRAM_MD_OC_STATUS_ADDR, + MT6351_PMIC_RGS_QI_VSRAM_MD_OC_STATUS_MASK, MT6351_PMIC_RGS_QI_VSRAM_MD_OC_STATUS_SHIFT}, + {PMIC_RGS_QI_VSRAM_MD_DIG_MON, MT6351_PMIC_RGS_QI_VSRAM_MD_DIG_MON_ADDR, + MT6351_PMIC_RGS_QI_VSRAM_MD_DIG_MON_MASK, MT6351_PMIC_RGS_QI_VSRAM_MD_DIG_MON_SHIFT}, + {PMIC_RGS_VSRAM_MD_ENPWM_STATUS, MT6351_PMIC_RGS_VSRAM_MD_ENPWM_STATUS_ADDR, + MT6351_PMIC_RGS_VSRAM_MD_ENPWM_STATUS_MASK, MT6351_PMIC_RGS_VSRAM_MD_ENPWM_STATUS_SHIFT}, + {PMIC_RG_VMODEM_MODESET, MT6351_PMIC_RG_VMODEM_MODESET_ADDR, + MT6351_PMIC_RG_VMODEM_MODESET_MASK, MT6351_PMIC_RG_VMODEM_MODESET_SHIFT}, + {PMIC_RG_VMODEM_NDIS_EN, MT6351_PMIC_RG_VMODEM_NDIS_EN_ADDR, + MT6351_PMIC_RG_VMODEM_NDIS_EN_MASK, MT6351_PMIC_RG_VMODEM_NDIS_EN_SHIFT}, + {PMIC_RG_VMODEM_VRF18_SSTART_EN, MT6351_PMIC_RG_VMODEM_VRF18_SSTART_EN_ADDR, + MT6351_PMIC_RG_VMODEM_VRF18_SSTART_EN_MASK, MT6351_PMIC_RG_VMODEM_VRF18_SSTART_EN_SHIFT}, + {PMIC_RG_VMODEM_AUTO_MODE, MT6351_PMIC_RG_VMODEM_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VMODEM_AUTO_MODE_MASK, MT6351_PMIC_RG_VMODEM_AUTO_MODE_SHIFT}, + {PMIC_RG_VMODEM_RZSEL0, MT6351_PMIC_RG_VMODEM_RZSEL0_ADDR, + MT6351_PMIC_RG_VMODEM_RZSEL0_MASK, MT6351_PMIC_RG_VMODEM_RZSEL0_SHIFT}, + {PMIC_RG_VMODEM_RZSEL1, MT6351_PMIC_RG_VMODEM_RZSEL1_ADDR, + MT6351_PMIC_RG_VMODEM_RZSEL1_MASK, MT6351_PMIC_RG_VMODEM_RZSEL1_SHIFT}, + {PMIC_RG_VMODEM_CCSEL0, MT6351_PMIC_RG_VMODEM_CCSEL0_ADDR, + MT6351_PMIC_RG_VMODEM_CCSEL0_MASK, MT6351_PMIC_RG_VMODEM_CCSEL0_SHIFT}, + {PMIC_RG_VMODEM_CCSEL1, MT6351_PMIC_RG_VMODEM_CCSEL1_ADDR, + MT6351_PMIC_RG_VMODEM_CCSEL1_MASK, MT6351_PMIC_RG_VMODEM_CCSEL1_SHIFT}, + {PMIC_RG_VMODEM_CSL, MT6351_PMIC_RG_VMODEM_CSL_ADDR, + MT6351_PMIC_RG_VMODEM_CSL_MASK, MT6351_PMIC_RG_VMODEM_CSL_SHIFT}, + {PMIC_RG_VMODEM_SLP, MT6351_PMIC_RG_VMODEM_SLP_ADDR, + MT6351_PMIC_RG_VMODEM_SLP_MASK, MT6351_PMIC_RG_VMODEM_SLP_SHIFT}, + {PMIC_RG_VMODEM_ADRC_FEN, MT6351_PMIC_RG_VMODEM_ADRC_FEN_ADDR, + MT6351_PMIC_RG_VMODEM_ADRC_FEN_MASK, MT6351_PMIC_RG_VMODEM_ADRC_FEN_SHIFT}, + {PMIC_RG_VMODEM_VCCAP_CLAMP_FEN, MT6351_PMIC_RG_VMODEM_VCCAP_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VMODEM_VCCAP_CLAMP_FEN_MASK, MT6351_PMIC_RG_VMODEM_VCCAP_CLAMP_FEN_SHIFT}, + {PMIC_RG_VMODEM_VC_CLAMP_FEN, MT6351_PMIC_RG_VMODEM_VC_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VMODEM_VC_CLAMP_FEN_MASK, MT6351_PMIC_RG_VMODEM_VC_CLAMP_FEN_SHIFT}, + {PMIC_RG_VMODEM_PFMOC, MT6351_PMIC_RG_VMODEM_PFMOC_ADDR, + MT6351_PMIC_RG_VMODEM_PFMOC_MASK, MT6351_PMIC_RG_VMODEM_PFMOC_SHIFT}, + {PMIC_RG_VMODEM_CSR, MT6351_PMIC_RG_VMODEM_CSR_ADDR, + MT6351_PMIC_RG_VMODEM_CSR_MASK, MT6351_PMIC_RG_VMODEM_CSR_SHIFT}, + {PMIC_RG_VMODEM_ZXOS_TRIM, MT6351_PMIC_RG_VMODEM_ZXOS_TRIM_ADDR, + MT6351_PMIC_RG_VMODEM_ZXOS_TRIM_MASK, MT6351_PMIC_RG_VMODEM_ZXOS_TRIM_SHIFT}, + {PMIC_RG_VMODEM_PFMSR_EH, MT6351_PMIC_RG_VMODEM_PFMSR_EH_ADDR, + MT6351_PMIC_RG_VMODEM_PFMSR_EH_MASK, MT6351_PMIC_RG_VMODEM_PFMSR_EH_SHIFT}, + {PMIC_RG_VMODEM_NLIM_GATING, MT6351_PMIC_RG_VMODEM_NLIM_GATING_ADDR, + MT6351_PMIC_RG_VMODEM_NLIM_GATING_MASK, MT6351_PMIC_RG_VMODEM_NLIM_GATING_SHIFT}, + {PMIC_RG_VMODEM_PWRSR_EH, MT6351_PMIC_RG_VMODEM_PWRSR_EH_ADDR, + MT6351_PMIC_RG_VMODEM_PWRSR_EH_MASK, MT6351_PMIC_RG_VMODEM_PWRSR_EH_SHIFT}, + {PMIC_RG_VMODEM_HS_VTHDET, MT6351_PMIC_RG_VMODEM_HS_VTHDET_ADDR, + MT6351_PMIC_RG_VMODEM_HS_VTHDET_MASK, MT6351_PMIC_RG_VMODEM_HS_VTHDET_SHIFT}, + {PMIC_RG_VMODEM_PG_GATING, MT6351_PMIC_RG_VMODEM_PG_GATING_ADDR, + MT6351_PMIC_RG_VMODEM_PG_GATING_MASK, MT6351_PMIC_RG_VMODEM_PG_GATING_SHIFT}, + {PMIC_RG_VMODEM_HS_ONSPEED_EH, MT6351_PMIC_RG_VMODEM_HS_ONSPEED_EH_ADDR, + MT6351_PMIC_RG_VMODEM_HS_ONSPEED_EH_MASK, MT6351_PMIC_RG_VMODEM_HS_ONSPEED_EH_SHIFT}, + {PMIC_RG_VMODEM_NLIM_TRIMMING, MT6351_PMIC_RG_VMODEM_NLIM_TRIMMING_ADDR, + MT6351_PMIC_RG_VMODEM_NLIM_TRIMMING_MASK, MT6351_PMIC_RG_VMODEM_NLIM_TRIMMING_SHIFT}, + {PMIC_RG_VMODEM_DLC, MT6351_PMIC_RG_VMODEM_DLC_ADDR, + MT6351_PMIC_RG_VMODEM_DLC_MASK, MT6351_PMIC_RG_VMODEM_DLC_SHIFT}, + {PMIC_RG_VMODEM_DLC_N, MT6351_PMIC_RG_VMODEM_DLC_N_ADDR, + MT6351_PMIC_RG_VMODEM_DLC_N_MASK, MT6351_PMIC_RG_VMODEM_DLC_N_SHIFT}, + {PMIC_RG_VMODEM_PFM_RIP, MT6351_PMIC_RG_VMODEM_PFM_RIP_ADDR, + MT6351_PMIC_RG_VMODEM_PFM_RIP_MASK, MT6351_PMIC_RG_VMODEM_PFM_RIP_SHIFT}, + {PMIC_RG_VMODEM_TRAN_BST, MT6351_PMIC_RG_VMODEM_TRAN_BST_ADDR, + MT6351_PMIC_RG_VMODEM_TRAN_BST_MASK, MT6351_PMIC_RG_VMODEM_TRAN_BST_SHIFT}, + {PMIC_RG_VMODEM_DTS_ENB, MT6351_PMIC_RG_VMODEM_DTS_ENB_ADDR, + MT6351_PMIC_RG_VMODEM_DTS_ENB_MASK, MT6351_PMIC_RG_VMODEM_DTS_ENB_SHIFT}, + {PMIC_RG_VMODEM_MIN_OFF, MT6351_PMIC_RG_VMODEM_MIN_OFF_ADDR, + MT6351_PMIC_RG_VMODEM_MIN_OFF_MASK, MT6351_PMIC_RG_VMODEM_MIN_OFF_SHIFT}, + {PMIC_RG_VMODEM_1P35UP_SEL_EN, MT6351_PMIC_RG_VMODEM_1P35UP_SEL_EN_ADDR, + MT6351_PMIC_RG_VMODEM_1P35UP_SEL_EN_MASK, MT6351_PMIC_RG_VMODEM_1P35UP_SEL_EN_SHIFT}, + {PMIC_RG_VMODEM_DLC_AUTO_MODE, MT6351_PMIC_RG_VMODEM_DLC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VMODEM_DLC_AUTO_MODE_MASK, MT6351_PMIC_RG_VMODEM_DLC_AUTO_MODE_SHIFT}, + {PMIC_RG_VMODEM_DLC_SEL, MT6351_PMIC_RG_VMODEM_DLC_SEL_ADDR, + MT6351_PMIC_RG_VMODEM_DLC_SEL_MASK, MT6351_PMIC_RG_VMODEM_DLC_SEL_SHIFT}, + {PMIC_RG_VMODEM_SRC_AUTO_MODE, MT6351_PMIC_RG_VMODEM_SRC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VMODEM_SRC_AUTO_MODE_MASK, MT6351_PMIC_RG_VMODEM_SRC_AUTO_MODE_SHIFT}, + {PMIC_RG_VMODEM_UGP_SR, MT6351_PMIC_RG_VMODEM_UGP_SR_ADDR, + MT6351_PMIC_RG_VMODEM_UGP_SR_MASK, MT6351_PMIC_RG_VMODEM_UGP_SR_SHIFT}, + {PMIC_RG_VMODEM_LGN_SR, MT6351_PMIC_RG_VMODEM_LGN_SR_ADDR, + MT6351_PMIC_RG_VMODEM_LGN_SR_MASK, MT6351_PMIC_RG_VMODEM_LGN_SR_SHIFT}, + {PMIC_RG_VMODEM_UGP_SR_PFM, MT6351_PMIC_RG_VMODEM_UGP_SR_PFM_ADDR, + MT6351_PMIC_RG_VMODEM_UGP_SR_PFM_MASK, MT6351_PMIC_RG_VMODEM_UGP_SR_PFM_SHIFT}, + {PMIC_RG_VMODEM_LGN_SR_PFM, MT6351_PMIC_RG_VMODEM_LGN_SR_PFM_ADDR, + MT6351_PMIC_RG_VMODEM_LGN_SR_PFM_MASK, MT6351_PMIC_RG_VMODEM_LGN_SR_PFM_SHIFT}, + {PMIC_RG_VMODEM_UGD_VTHSEL, MT6351_PMIC_RG_VMODEM_UGD_VTHSEL_ADDR, + MT6351_PMIC_RG_VMODEM_UGD_VTHSEL_MASK, MT6351_PMIC_RG_VMODEM_UGD_VTHSEL_SHIFT}, + {PMIC_RG_VMODEM_FNLX_SNS, MT6351_PMIC_RG_VMODEM_FNLX_SNS_ADDR, + MT6351_PMIC_RG_VMODEM_FNLX_SNS_MASK, MT6351_PMIC_RG_VMODEM_FNLX_SNS_SHIFT}, + {PMIC_RG_VMODEM_VDIFF_ENLOWIQ, MT6351_PMIC_RG_VMODEM_VDIFF_ENLOWIQ_ADDR, + MT6351_PMIC_RG_VMODEM_VDIFF_ENLOWIQ_MASK, MT6351_PMIC_RG_VMODEM_VDIFF_ENLOWIQ_SHIFT}, + {PMIC_RG_VMODEM_PFMOC_FWUPOFF, MT6351_PMIC_RG_VMODEM_PFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VMODEM_PFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VMODEM_PFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VMODEM_PWFMOC_FWUPOFF, MT6351_PMIC_RG_VMODEM_PWFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VMODEM_PWFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VMODEM_PWFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VMODEM_CP_FWUPOFF, MT6351_PMIC_RG_VMODEM_CP_FWUPOFF_ADDR, + MT6351_PMIC_RG_VMODEM_CP_FWUPOFF_MASK, MT6351_PMIC_RG_VMODEM_CP_FWUPOFF_SHIFT}, + {PMIC_RG_VMODEM_ZX_GATING, MT6351_PMIC_RG_VMODEM_ZX_GATING_ADDR, + MT6351_PMIC_RG_VMODEM_ZX_GATING_MASK, MT6351_PMIC_RG_VMODEM_ZX_GATING_SHIFT}, + {PMIC_RG_VMODEM_RSV, MT6351_PMIC_RG_VMODEM_RSV_ADDR, + MT6351_PMIC_RG_VMODEM_RSV_MASK, MT6351_PMIC_RG_VMODEM_RSV_SHIFT}, + {PMIC_RG_VMODEM_AZC_EN, MT6351_PMIC_RG_VMODEM_AZC_EN_ADDR, + MT6351_PMIC_RG_VMODEM_AZC_EN_MASK, MT6351_PMIC_RG_VMODEM_AZC_EN_SHIFT}, + {PMIC_RG_VMODEM_AZC_DELAY, MT6351_PMIC_RG_VMODEM_AZC_DELAY_ADDR, + MT6351_PMIC_RG_VMODEM_AZC_DELAY_MASK, MT6351_PMIC_RG_VMODEM_AZC_DELAY_SHIFT}, + {PMIC_RG_VMODEM_AZC_HOLD_ENB, MT6351_PMIC_RG_VMODEM_AZC_HOLD_ENB_ADDR, + MT6351_PMIC_RG_VMODEM_AZC_HOLD_ENB_MASK, MT6351_PMIC_RG_VMODEM_AZC_HOLD_ENB_SHIFT}, + {PMIC_RGS_QI_VMODEM_OC_STATUS, MT6351_PMIC_RGS_QI_VMODEM_OC_STATUS_ADDR, + MT6351_PMIC_RGS_QI_VMODEM_OC_STATUS_MASK, MT6351_PMIC_RGS_QI_VMODEM_OC_STATUS_SHIFT}, + {PMIC_RGS_QI_VMODEM_DIG_MON, MT6351_PMIC_RGS_QI_VMODEM_DIG_MON_ADDR, + MT6351_PMIC_RGS_QI_VMODEM_DIG_MON_MASK, MT6351_PMIC_RGS_QI_VMODEM_DIG_MON_SHIFT}, + {PMIC_RGS_VMODEM_ENPWM_STATUS, MT6351_PMIC_RGS_VMODEM_ENPWM_STATUS_ADDR, + MT6351_PMIC_RGS_VMODEM_ENPWM_STATUS_MASK, MT6351_PMIC_RGS_VMODEM_ENPWM_STATUS_SHIFT}, + {PMIC_RG_VMD1_MODESET, MT6351_PMIC_RG_VMD1_MODESET_ADDR, + MT6351_PMIC_RG_VMD1_MODESET_MASK, MT6351_PMIC_RG_VMD1_MODESET_SHIFT}, + {PMIC_RG_VMD1_NDIS_EN, MT6351_PMIC_RG_VMD1_NDIS_EN_ADDR, + MT6351_PMIC_RG_VMD1_NDIS_EN_MASK, MT6351_PMIC_RG_VMD1_NDIS_EN_SHIFT}, + {PMIC_RG_VMD1_VRF18_SSTART_EN, MT6351_PMIC_RG_VMD1_VRF18_SSTART_EN_ADDR, + MT6351_PMIC_RG_VMD1_VRF18_SSTART_EN_MASK, MT6351_PMIC_RG_VMD1_VRF18_SSTART_EN_SHIFT}, + {PMIC_RG_VMD1_AUTO_MODE, MT6351_PMIC_RG_VMD1_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VMD1_AUTO_MODE_MASK, MT6351_PMIC_RG_VMD1_AUTO_MODE_SHIFT}, + {PMIC_RG_VMD1_RZSEL0, MT6351_PMIC_RG_VMD1_RZSEL0_ADDR, + MT6351_PMIC_RG_VMD1_RZSEL0_MASK, MT6351_PMIC_RG_VMD1_RZSEL0_SHIFT}, + {PMIC_RG_VMD1_RZSEL1, MT6351_PMIC_RG_VMD1_RZSEL1_ADDR, + MT6351_PMIC_RG_VMD1_RZSEL1_MASK, MT6351_PMIC_RG_VMD1_RZSEL1_SHIFT}, + {PMIC_RG_VMD1_CCSEL0, MT6351_PMIC_RG_VMD1_CCSEL0_ADDR, + MT6351_PMIC_RG_VMD1_CCSEL0_MASK, MT6351_PMIC_RG_VMD1_CCSEL0_SHIFT}, + {PMIC_RG_VMD1_CCSEL1, MT6351_PMIC_RG_VMD1_CCSEL1_ADDR, + MT6351_PMIC_RG_VMD1_CCSEL1_MASK, MT6351_PMIC_RG_VMD1_CCSEL1_SHIFT}, + {PMIC_RG_VMD1_CSL, MT6351_PMIC_RG_VMD1_CSL_ADDR, MT6351_PMIC_RG_VMD1_CSL_MASK, + MT6351_PMIC_RG_VMD1_CSL_SHIFT}, + {PMIC_RG_VMD1_SLP, MT6351_PMIC_RG_VMD1_SLP_ADDR, MT6351_PMIC_RG_VMD1_SLP_MASK, + MT6351_PMIC_RG_VMD1_SLP_SHIFT}, + {PMIC_RG_VMD1_ADRC_FEN, MT6351_PMIC_RG_VMD1_ADRC_FEN_ADDR, + MT6351_PMIC_RG_VMD1_ADRC_FEN_MASK, MT6351_PMIC_RG_VMD1_ADRC_FEN_SHIFT}, + {PMIC_RG_VMD1_VCCAP_CLAMP_FEN, MT6351_PMIC_RG_VMD1_VCCAP_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VMD1_VCCAP_CLAMP_FEN_MASK, MT6351_PMIC_RG_VMD1_VCCAP_CLAMP_FEN_SHIFT}, + {PMIC_RG_VMD1_VC_CLAMP_FEN, MT6351_PMIC_RG_VMD1_VC_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VMD1_VC_CLAMP_FEN_MASK, MT6351_PMIC_RG_VMD1_VC_CLAMP_FEN_SHIFT}, + {PMIC_RG_VMD1_PFMOC, MT6351_PMIC_RG_VMD1_PFMOC_ADDR, + MT6351_PMIC_RG_VMD1_PFMOC_MASK, MT6351_PMIC_RG_VMD1_PFMOC_SHIFT}, + {PMIC_RG_VMD1_CSR, MT6351_PMIC_RG_VMD1_CSR_ADDR, MT6351_PMIC_RG_VMD1_CSR_MASK, + MT6351_PMIC_RG_VMD1_CSR_SHIFT}, + {PMIC_RG_VMD1_ZXOS_TRIM, MT6351_PMIC_RG_VMD1_ZXOS_TRIM_ADDR, + MT6351_PMIC_RG_VMD1_ZXOS_TRIM_MASK, MT6351_PMIC_RG_VMD1_ZXOS_TRIM_SHIFT}, + {PMIC_RG_VMD1_PFMSR_EH, MT6351_PMIC_RG_VMD1_PFMSR_EH_ADDR, + MT6351_PMIC_RG_VMD1_PFMSR_EH_MASK, MT6351_PMIC_RG_VMD1_PFMSR_EH_SHIFT}, + {PMIC_RG_VMD1_NLIM_GATING, MT6351_PMIC_RG_VMD1_NLIM_GATING_ADDR, + MT6351_PMIC_RG_VMD1_NLIM_GATING_MASK, MT6351_PMIC_RG_VMD1_NLIM_GATING_SHIFT}, + {PMIC_RG_VMD1_PWRSR_EH, MT6351_PMIC_RG_VMD1_PWRSR_EH_ADDR, + MT6351_PMIC_RG_VMD1_PWRSR_EH_MASK, MT6351_PMIC_RG_VMD1_PWRSR_EH_SHIFT}, + {PMIC_RG_VMD1_HS_VTHDET, MT6351_PMIC_RG_VMD1_HS_VTHDET_ADDR, + MT6351_PMIC_RG_VMD1_HS_VTHDET_MASK, MT6351_PMIC_RG_VMD1_HS_VTHDET_SHIFT}, + {PMIC_RG_VMD1_PG_GATING, MT6351_PMIC_RG_VMD1_PG_GATING_ADDR, + MT6351_PMIC_RG_VMD1_PG_GATING_MASK, MT6351_PMIC_RG_VMD1_PG_GATING_SHIFT}, + {PMIC_RG_VMD1_HS_ONSPEED_EH, MT6351_PMIC_RG_VMD1_HS_ONSPEED_EH_ADDR, + MT6351_PMIC_RG_VMD1_HS_ONSPEED_EH_MASK, MT6351_PMIC_RG_VMD1_HS_ONSPEED_EH_SHIFT}, + {PMIC_RG_VMD1_NLIM_TRIMMING, MT6351_PMIC_RG_VMD1_NLIM_TRIMMING_ADDR, + MT6351_PMIC_RG_VMD1_NLIM_TRIMMING_MASK, MT6351_PMIC_RG_VMD1_NLIM_TRIMMING_SHIFT}, + {PMIC_RG_VMD1_DLC, MT6351_PMIC_RG_VMD1_DLC_ADDR, MT6351_PMIC_RG_VMD1_DLC_MASK, + MT6351_PMIC_RG_VMD1_DLC_SHIFT}, + {PMIC_RG_VMD1_DLC_N, MT6351_PMIC_RG_VMD1_DLC_N_ADDR, + MT6351_PMIC_RG_VMD1_DLC_N_MASK, MT6351_PMIC_RG_VMD1_DLC_N_SHIFT}, + {PMIC_RG_VMD1_PFM_RIP, MT6351_PMIC_RG_VMD1_PFM_RIP_ADDR, + MT6351_PMIC_RG_VMD1_PFM_RIP_MASK, MT6351_PMIC_RG_VMD1_PFM_RIP_SHIFT}, + {PMIC_RG_VMD1_TRAN_BST, MT6351_PMIC_RG_VMD1_TRAN_BST_ADDR, + MT6351_PMIC_RG_VMD1_TRAN_BST_MASK, MT6351_PMIC_RG_VMD1_TRAN_BST_SHIFT}, + {PMIC_RG_VMD1_DTS_ENB, MT6351_PMIC_RG_VMD1_DTS_ENB_ADDR, + MT6351_PMIC_RG_VMD1_DTS_ENB_MASK, MT6351_PMIC_RG_VMD1_DTS_ENB_SHIFT}, + {PMIC_RG_VMD1_MIN_OFF, MT6351_PMIC_RG_VMD1_MIN_OFF_ADDR, + MT6351_PMIC_RG_VMD1_MIN_OFF_MASK, MT6351_PMIC_RG_VMD1_MIN_OFF_SHIFT}, + {PMIC_RG_VMD1_1P35UP_SEL_EN, MT6351_PMIC_RG_VMD1_1P35UP_SEL_EN_ADDR, + MT6351_PMIC_RG_VMD1_1P35UP_SEL_EN_MASK, MT6351_PMIC_RG_VMD1_1P35UP_SEL_EN_SHIFT}, + {PMIC_RG_VMD1_DLC_AUTO_MODE, MT6351_PMIC_RG_VMD1_DLC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VMD1_DLC_AUTO_MODE_MASK, MT6351_PMIC_RG_VMD1_DLC_AUTO_MODE_SHIFT}, + {PMIC_RG_VMD1_DLC_SEL, MT6351_PMIC_RG_VMD1_DLC_SEL_ADDR, + MT6351_PMIC_RG_VMD1_DLC_SEL_MASK, MT6351_PMIC_RG_VMD1_DLC_SEL_SHIFT}, + {PMIC_RG_VMD1_SRC_AUTO_MODE, MT6351_PMIC_RG_VMD1_SRC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VMD1_SRC_AUTO_MODE_MASK, MT6351_PMIC_RG_VMD1_SRC_AUTO_MODE_SHIFT}, + {PMIC_RG_VMD1_UGP_SR, MT6351_PMIC_RG_VMD1_UGP_SR_ADDR, + MT6351_PMIC_RG_VMD1_UGP_SR_MASK, MT6351_PMIC_RG_VMD1_UGP_SR_SHIFT}, + {PMIC_RG_VMD1_LGN_SR, MT6351_PMIC_RG_VMD1_LGN_SR_ADDR, + MT6351_PMIC_RG_VMD1_LGN_SR_MASK, MT6351_PMIC_RG_VMD1_LGN_SR_SHIFT}, + {PMIC_RG_VMD1_UGP_SR_PFM, MT6351_PMIC_RG_VMD1_UGP_SR_PFM_ADDR, + MT6351_PMIC_RG_VMD1_UGP_SR_PFM_MASK, MT6351_PMIC_RG_VMD1_UGP_SR_PFM_SHIFT}, + {PMIC_RG_VMD1_LGN_SR_PFM, MT6351_PMIC_RG_VMD1_LGN_SR_PFM_ADDR, + MT6351_PMIC_RG_VMD1_LGN_SR_PFM_MASK, MT6351_PMIC_RG_VMD1_LGN_SR_PFM_SHIFT}, + {PMIC_RG_VMD1_UGD_VTHSEL, MT6351_PMIC_RG_VMD1_UGD_VTHSEL_ADDR, + MT6351_PMIC_RG_VMD1_UGD_VTHSEL_MASK, MT6351_PMIC_RG_VMD1_UGD_VTHSEL_SHIFT}, + {PMIC_RG_VMD1_FNLX_SNS, MT6351_PMIC_RG_VMD1_FNLX_SNS_ADDR, + MT6351_PMIC_RG_VMD1_FNLX_SNS_MASK, MT6351_PMIC_RG_VMD1_FNLX_SNS_SHIFT}, + {PMIC_RG_VMD1_VDIFF_ENLOWIQ, MT6351_PMIC_RG_VMD1_VDIFF_ENLOWIQ_ADDR, + MT6351_PMIC_RG_VMD1_VDIFF_ENLOWIQ_MASK, MT6351_PMIC_RG_VMD1_VDIFF_ENLOWIQ_SHIFT}, + {PMIC_RG_VMD1_PFMOC_FWUPOFF, MT6351_PMIC_RG_VMD1_PFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VMD1_PFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VMD1_PFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VMD1_PWFMOC_FWUPOFF, MT6351_PMIC_RG_VMD1_PWFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VMD1_PWFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VMD1_PWFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VMD1_CP_FWUPOFF, MT6351_PMIC_RG_VMD1_CP_FWUPOFF_ADDR, + MT6351_PMIC_RG_VMD1_CP_FWUPOFF_MASK, MT6351_PMIC_RG_VMD1_CP_FWUPOFF_SHIFT}, + {PMIC_RG_VMD1_ZX_GATING, MT6351_PMIC_RG_VMD1_ZX_GATING_ADDR, + MT6351_PMIC_RG_VMD1_ZX_GATING_MASK, MT6351_PMIC_RG_VMD1_ZX_GATING_SHIFT}, + {PMIC_RG_VMD1_RSV, MT6351_PMIC_RG_VMD1_RSV_ADDR, MT6351_PMIC_RG_VMD1_RSV_MASK, + MT6351_PMIC_RG_VMD1_RSV_SHIFT}, + {PMIC_RG_VMD1_AZC_EN, MT6351_PMIC_RG_VMD1_AZC_EN_ADDR, + MT6351_PMIC_RG_VMD1_AZC_EN_MASK, MT6351_PMIC_RG_VMD1_AZC_EN_SHIFT}, + {PMIC_RG_VMD1_AZC_DELAY, MT6351_PMIC_RG_VMD1_AZC_DELAY_ADDR, + MT6351_PMIC_RG_VMD1_AZC_DELAY_MASK, MT6351_PMIC_RG_VMD1_AZC_DELAY_SHIFT}, + {PMIC_RG_VMD1_AZC_HOLD_ENB, MT6351_PMIC_RG_VMD1_AZC_HOLD_ENB_ADDR, + MT6351_PMIC_RG_VMD1_AZC_HOLD_ENB_MASK, MT6351_PMIC_RG_VMD1_AZC_HOLD_ENB_SHIFT}, + {PMIC_RGS_QI_VMD1_OC_STATUS, MT6351_PMIC_RGS_QI_VMD1_OC_STATUS_ADDR, + MT6351_PMIC_RGS_QI_VMD1_OC_STATUS_MASK, MT6351_PMIC_RGS_QI_VMD1_OC_STATUS_SHIFT}, + {PMIC_RGS_QI_VMD1_DIG_MON, MT6351_PMIC_RGS_QI_VMD1_DIG_MON_ADDR, + MT6351_PMIC_RGS_QI_VMD1_DIG_MON_MASK, MT6351_PMIC_RGS_QI_VMD1_DIG_MON_SHIFT}, + {PMIC_RGS_VMD1_ENPWM_STATUS, MT6351_PMIC_RGS_VMD1_ENPWM_STATUS_ADDR, + MT6351_PMIC_RGS_VMD1_ENPWM_STATUS_MASK, MT6351_PMIC_RGS_VMD1_ENPWM_STATUS_SHIFT}, + {PMIC_RG_VS1_MODESET, MT6351_PMIC_RG_VS1_MODESET_ADDR, + MT6351_PMIC_RG_VS1_MODESET_MASK, MT6351_PMIC_RG_VS1_MODESET_SHIFT}, + {PMIC_RG_VS1_NDIS_EN, MT6351_PMIC_RG_VS1_NDIS_EN_ADDR, + MT6351_PMIC_RG_VS1_NDIS_EN_MASK, MT6351_PMIC_RG_VS1_NDIS_EN_SHIFT}, + {PMIC_RG_VS1_VRF18_SSTART_EN, MT6351_PMIC_RG_VS1_VRF18_SSTART_EN_ADDR, + MT6351_PMIC_RG_VS1_VRF18_SSTART_EN_MASK, MT6351_PMIC_RG_VS1_VRF18_SSTART_EN_SHIFT}, + {PMIC_RG_VS1_AUTO_MODE, MT6351_PMIC_RG_VS1_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VS1_AUTO_MODE_MASK, MT6351_PMIC_RG_VS1_AUTO_MODE_SHIFT}, + {PMIC_RG_VS1_RZSEL0, MT6351_PMIC_RG_VS1_RZSEL0_ADDR, + MT6351_PMIC_RG_VS1_RZSEL0_MASK, MT6351_PMIC_RG_VS1_RZSEL0_SHIFT}, + {PMIC_RG_VS1_RZSEL1, MT6351_PMIC_RG_VS1_RZSEL1_ADDR, + MT6351_PMIC_RG_VS1_RZSEL1_MASK, MT6351_PMIC_RG_VS1_RZSEL1_SHIFT}, + {PMIC_RG_VS1_CCSEL0, MT6351_PMIC_RG_VS1_CCSEL0_ADDR, + MT6351_PMIC_RG_VS1_CCSEL0_MASK, MT6351_PMIC_RG_VS1_CCSEL0_SHIFT}, + {PMIC_RG_VS1_CCSEL1, MT6351_PMIC_RG_VS1_CCSEL1_ADDR, + MT6351_PMIC_RG_VS1_CCSEL1_MASK, MT6351_PMIC_RG_VS1_CCSEL1_SHIFT}, + {PMIC_RG_VS1_CSL, MT6351_PMIC_RG_VS1_CSL_ADDR, MT6351_PMIC_RG_VS1_CSL_MASK, + MT6351_PMIC_RG_VS1_CSL_SHIFT}, + {PMIC_RG_VS1_SLP, MT6351_PMIC_RG_VS1_SLP_ADDR, MT6351_PMIC_RG_VS1_SLP_MASK, + MT6351_PMIC_RG_VS1_SLP_SHIFT}, + {PMIC_RG_VS1_ADRC_FEN, MT6351_PMIC_RG_VS1_ADRC_FEN_ADDR, + MT6351_PMIC_RG_VS1_ADRC_FEN_MASK, MT6351_PMIC_RG_VS1_ADRC_FEN_SHIFT}, + {PMIC_RG_VS1_VCCAP_CLAMP_FEN, MT6351_PMIC_RG_VS1_VCCAP_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VS1_VCCAP_CLAMP_FEN_MASK, MT6351_PMIC_RG_VS1_VCCAP_CLAMP_FEN_SHIFT}, + {PMIC_RG_VS1_VC_CLAMP_FEN, MT6351_PMIC_RG_VS1_VC_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VS1_VC_CLAMP_FEN_MASK, MT6351_PMIC_RG_VS1_VC_CLAMP_FEN_SHIFT}, + {PMIC_RG_VS1_PFMOC, MT6351_PMIC_RG_VS1_PFMOC_ADDR, MT6351_PMIC_RG_VS1_PFMOC_MASK, + MT6351_PMIC_RG_VS1_PFMOC_SHIFT}, + {PMIC_RG_VS1_CSR, MT6351_PMIC_RG_VS1_CSR_ADDR, MT6351_PMIC_RG_VS1_CSR_MASK, + MT6351_PMIC_RG_VS1_CSR_SHIFT}, + {PMIC_RG_VS1_ZXOS_TRIM, MT6351_PMIC_RG_VS1_ZXOS_TRIM_ADDR, + MT6351_PMIC_RG_VS1_ZXOS_TRIM_MASK, MT6351_PMIC_RG_VS1_ZXOS_TRIM_SHIFT}, + {PMIC_RG_VS1_PFMSR_EH, MT6351_PMIC_RG_VS1_PFMSR_EH_ADDR, + MT6351_PMIC_RG_VS1_PFMSR_EH_MASK, MT6351_PMIC_RG_VS1_PFMSR_EH_SHIFT}, + {PMIC_RG_VS1_NLIM_GATING, MT6351_PMIC_RG_VS1_NLIM_GATING_ADDR, + MT6351_PMIC_RG_VS1_NLIM_GATING_MASK, MT6351_PMIC_RG_VS1_NLIM_GATING_SHIFT}, + {PMIC_RG_VS1_PWRSR_EH, MT6351_PMIC_RG_VS1_PWRSR_EH_ADDR, + MT6351_PMIC_RG_VS1_PWRSR_EH_MASK, MT6351_PMIC_RG_VS1_PWRSR_EH_SHIFT}, + {PMIC_RG_VS1_HS_VTHDET, MT6351_PMIC_RG_VS1_HS_VTHDET_ADDR, + MT6351_PMIC_RG_VS1_HS_VTHDET_MASK, MT6351_PMIC_RG_VS1_HS_VTHDET_SHIFT}, + {PMIC_RG_VS1_PG_GATING, MT6351_PMIC_RG_VS1_PG_GATING_ADDR, + MT6351_PMIC_RG_VS1_PG_GATING_MASK, MT6351_PMIC_RG_VS1_PG_GATING_SHIFT}, + {PMIC_RG_VS1_HS_ONSPEED_EH, MT6351_PMIC_RG_VS1_HS_ONSPEED_EH_ADDR, + MT6351_PMIC_RG_VS1_HS_ONSPEED_EH_MASK, MT6351_PMIC_RG_VS1_HS_ONSPEED_EH_SHIFT}, + {PMIC_RG_VS1_NLIM_TRIMMING, MT6351_PMIC_RG_VS1_NLIM_TRIMMING_ADDR, + MT6351_PMIC_RG_VS1_NLIM_TRIMMING_MASK, MT6351_PMIC_RG_VS1_NLIM_TRIMMING_SHIFT}, + {PMIC_RG_VS1_DLC, MT6351_PMIC_RG_VS1_DLC_ADDR, MT6351_PMIC_RG_VS1_DLC_MASK, + MT6351_PMIC_RG_VS1_DLC_SHIFT}, + {PMIC_RG_VS1_DLC_N, MT6351_PMIC_RG_VS1_DLC_N_ADDR, MT6351_PMIC_RG_VS1_DLC_N_MASK, + MT6351_PMIC_RG_VS1_DLC_N_SHIFT}, + {PMIC_RG_VS1_PFM_RIP, MT6351_PMIC_RG_VS1_PFM_RIP_ADDR, + MT6351_PMIC_RG_VS1_PFM_RIP_MASK, MT6351_PMIC_RG_VS1_PFM_RIP_SHIFT}, + {PMIC_RG_VS1_TRAN_BST, MT6351_PMIC_RG_VS1_TRAN_BST_ADDR, + MT6351_PMIC_RG_VS1_TRAN_BST_MASK, MT6351_PMIC_RG_VS1_TRAN_BST_SHIFT}, + {PMIC_RG_VS1_DTS_ENB, MT6351_PMIC_RG_VS1_DTS_ENB_ADDR, + MT6351_PMIC_RG_VS1_DTS_ENB_MASK, MT6351_PMIC_RG_VS1_DTS_ENB_SHIFT}, + {PMIC_RG_VS1_MIN_OFF, MT6351_PMIC_RG_VS1_MIN_OFF_ADDR, + MT6351_PMIC_RG_VS1_MIN_OFF_MASK, MT6351_PMIC_RG_VS1_MIN_OFF_SHIFT}, + {PMIC_RG_VS1_1P35UP_SEL_EN, MT6351_PMIC_RG_VS1_1P35UP_SEL_EN_ADDR, + MT6351_PMIC_RG_VS1_1P35UP_SEL_EN_MASK, MT6351_PMIC_RG_VS1_1P35UP_SEL_EN_SHIFT}, + {PMIC_RG_VS1_DLC_AUTO_MODE, MT6351_PMIC_RG_VS1_DLC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VS1_DLC_AUTO_MODE_MASK, MT6351_PMIC_RG_VS1_DLC_AUTO_MODE_SHIFT}, + {PMIC_RG_VS1_DLC_SEL, MT6351_PMIC_RG_VS1_DLC_SEL_ADDR, + MT6351_PMIC_RG_VS1_DLC_SEL_MASK, MT6351_PMIC_RG_VS1_DLC_SEL_SHIFT}, + {PMIC_RG_VS1_SRC_AUTO_MODE, MT6351_PMIC_RG_VS1_SRC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VS1_SRC_AUTO_MODE_MASK, MT6351_PMIC_RG_VS1_SRC_AUTO_MODE_SHIFT}, + {PMIC_RG_VS1_UGP_SR, MT6351_PMIC_RG_VS1_UGP_SR_ADDR, + MT6351_PMIC_RG_VS1_UGP_SR_MASK, MT6351_PMIC_RG_VS1_UGP_SR_SHIFT}, + {PMIC_RG_VS1_LGN_SR, MT6351_PMIC_RG_VS1_LGN_SR_ADDR, + MT6351_PMIC_RG_VS1_LGN_SR_MASK, MT6351_PMIC_RG_VS1_LGN_SR_SHIFT}, + {PMIC_RG_VS1_UGP_SR_PFM, MT6351_PMIC_RG_VS1_UGP_SR_PFM_ADDR, + MT6351_PMIC_RG_VS1_UGP_SR_PFM_MASK, MT6351_PMIC_RG_VS1_UGP_SR_PFM_SHIFT}, + {PMIC_RG_VS1_LGN_SR_PFM, MT6351_PMIC_RG_VS1_LGN_SR_PFM_ADDR, + MT6351_PMIC_RG_VS1_LGN_SR_PFM_MASK, MT6351_PMIC_RG_VS1_LGN_SR_PFM_SHIFT}, + {PMIC_RG_VS1_UGD_VTHSEL, MT6351_PMIC_RG_VS1_UGD_VTHSEL_ADDR, + MT6351_PMIC_RG_VS1_UGD_VTHSEL_MASK, MT6351_PMIC_RG_VS1_UGD_VTHSEL_SHIFT}, + {PMIC_RG_VS1_FNLX_SNS, MT6351_PMIC_RG_VS1_FNLX_SNS_ADDR, + MT6351_PMIC_RG_VS1_FNLX_SNS_MASK, MT6351_PMIC_RG_VS1_FNLX_SNS_SHIFT}, + {PMIC_RG_VS1_VDIFF_ENLOWIQ, MT6351_PMIC_RG_VS1_VDIFF_ENLOWIQ_ADDR, + MT6351_PMIC_RG_VS1_VDIFF_ENLOWIQ_MASK, MT6351_PMIC_RG_VS1_VDIFF_ENLOWIQ_SHIFT}, + {PMIC_RG_VS1_PFMOC_FWUPOFF, MT6351_PMIC_RG_VS1_PFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VS1_PFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VS1_PFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VS1_PWFMOC_FWUPOFF, MT6351_PMIC_RG_VS1_PWFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VS1_PWFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VS1_PWFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VS1_CP_FWUPOFF, MT6351_PMIC_RG_VS1_CP_FWUPOFF_ADDR, + MT6351_PMIC_RG_VS1_CP_FWUPOFF_MASK, MT6351_PMIC_RG_VS1_CP_FWUPOFF_SHIFT}, + {PMIC_RG_VS1_ZX_GATING, MT6351_PMIC_RG_VS1_ZX_GATING_ADDR, + MT6351_PMIC_RG_VS1_ZX_GATING_MASK, MT6351_PMIC_RG_VS1_ZX_GATING_SHIFT}, + {PMIC_RG_VS1_RSV, MT6351_PMIC_RG_VS1_RSV_ADDR, MT6351_PMIC_RG_VS1_RSV_MASK, + MT6351_PMIC_RG_VS1_RSV_SHIFT}, + {PMIC_RG_VS1_AZC_EN, MT6351_PMIC_RG_VS1_AZC_EN_ADDR, + MT6351_PMIC_RG_VS1_AZC_EN_MASK, MT6351_PMIC_RG_VS1_AZC_EN_SHIFT}, + {PMIC_RG_VS1_AZC_DELAY, MT6351_PMIC_RG_VS1_AZC_DELAY_ADDR, + MT6351_PMIC_RG_VS1_AZC_DELAY_MASK, MT6351_PMIC_RG_VS1_AZC_DELAY_SHIFT}, + {PMIC_RG_VS1_AZC_HOLD_ENB, MT6351_PMIC_RG_VS1_AZC_HOLD_ENB_ADDR, + MT6351_PMIC_RG_VS1_AZC_HOLD_ENB_MASK, MT6351_PMIC_RG_VS1_AZC_HOLD_ENB_SHIFT}, + {PMIC_RGS_QI_VS1_OC_STATUS, MT6351_PMIC_RGS_QI_VS1_OC_STATUS_ADDR, + MT6351_PMIC_RGS_QI_VS1_OC_STATUS_MASK, MT6351_PMIC_RGS_QI_VS1_OC_STATUS_SHIFT}, + {PMIC_RGS_QI_VS1_DIG_MON, MT6351_PMIC_RGS_QI_VS1_DIG_MON_ADDR, + MT6351_PMIC_RGS_QI_VS1_DIG_MON_MASK, MT6351_PMIC_RGS_QI_VS1_DIG_MON_SHIFT}, + {PMIC_RGS_VS1_ENPWM_STATUS, MT6351_PMIC_RGS_VS1_ENPWM_STATUS_ADDR, + MT6351_PMIC_RGS_VS1_ENPWM_STATUS_MASK, MT6351_PMIC_RGS_VS1_ENPWM_STATUS_SHIFT}, + {PMIC_RG_VS2_MODESET, MT6351_PMIC_RG_VS2_MODESET_ADDR, + MT6351_PMIC_RG_VS2_MODESET_MASK, MT6351_PMIC_RG_VS2_MODESET_SHIFT}, + {PMIC_RG_VS2_NDIS_EN, MT6351_PMIC_RG_VS2_NDIS_EN_ADDR, + MT6351_PMIC_RG_VS2_NDIS_EN_MASK, MT6351_PMIC_RG_VS2_NDIS_EN_SHIFT}, + {PMIC_RG_VS2_VRF18_SSTART_EN, MT6351_PMIC_RG_VS2_VRF18_SSTART_EN_ADDR, + MT6351_PMIC_RG_VS2_VRF18_SSTART_EN_MASK, MT6351_PMIC_RG_VS2_VRF18_SSTART_EN_SHIFT}, + {PMIC_RG_VS2_AUTO_MODE, MT6351_PMIC_RG_VS2_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VS2_AUTO_MODE_MASK, MT6351_PMIC_RG_VS2_AUTO_MODE_SHIFT}, + {PMIC_RG_VS2_RZSEL0, MT6351_PMIC_RG_VS2_RZSEL0_ADDR, + MT6351_PMIC_RG_VS2_RZSEL0_MASK, MT6351_PMIC_RG_VS2_RZSEL0_SHIFT}, + {PMIC_RG_VS2_RZSEL1, MT6351_PMIC_RG_VS2_RZSEL1_ADDR, + MT6351_PMIC_RG_VS2_RZSEL1_MASK, MT6351_PMIC_RG_VS2_RZSEL1_SHIFT}, + {PMIC_RG_VS2_CCSEL0, MT6351_PMIC_RG_VS2_CCSEL0_ADDR, + MT6351_PMIC_RG_VS2_CCSEL0_MASK, MT6351_PMIC_RG_VS2_CCSEL0_SHIFT}, + {PMIC_RG_VS2_CCSEL1, MT6351_PMIC_RG_VS2_CCSEL1_ADDR, + MT6351_PMIC_RG_VS2_CCSEL1_MASK, MT6351_PMIC_RG_VS2_CCSEL1_SHIFT}, + {PMIC_RG_VS2_CSL, MT6351_PMIC_RG_VS2_CSL_ADDR, MT6351_PMIC_RG_VS2_CSL_MASK, + MT6351_PMIC_RG_VS2_CSL_SHIFT}, + {PMIC_RG_VS2_SLP, MT6351_PMIC_RG_VS2_SLP_ADDR, MT6351_PMIC_RG_VS2_SLP_MASK, + MT6351_PMIC_RG_VS2_SLP_SHIFT}, + {PMIC_RG_VS2_ADRC_FEN, MT6351_PMIC_RG_VS2_ADRC_FEN_ADDR, + MT6351_PMIC_RG_VS2_ADRC_FEN_MASK, MT6351_PMIC_RG_VS2_ADRC_FEN_SHIFT}, + {PMIC_RG_VS2_VCCAP_CLAMP_FEN, MT6351_PMIC_RG_VS2_VCCAP_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VS2_VCCAP_CLAMP_FEN_MASK, MT6351_PMIC_RG_VS2_VCCAP_CLAMP_FEN_SHIFT}, + {PMIC_RG_VS2_VC_CLAMP_FEN, MT6351_PMIC_RG_VS2_VC_CLAMP_FEN_ADDR, + MT6351_PMIC_RG_VS2_VC_CLAMP_FEN_MASK, MT6351_PMIC_RG_VS2_VC_CLAMP_FEN_SHIFT}, + {PMIC_RG_VS2_PFMOC, MT6351_PMIC_RG_VS2_PFMOC_ADDR, MT6351_PMIC_RG_VS2_PFMOC_MASK, + MT6351_PMIC_RG_VS2_PFMOC_SHIFT}, + {PMIC_RG_VS2_CSR, MT6351_PMIC_RG_VS2_CSR_ADDR, MT6351_PMIC_RG_VS2_CSR_MASK, + MT6351_PMIC_RG_VS2_CSR_SHIFT}, + {PMIC_RG_VS2_ZXOS_TRIM, MT6351_PMIC_RG_VS2_ZXOS_TRIM_ADDR, + MT6351_PMIC_RG_VS2_ZXOS_TRIM_MASK, MT6351_PMIC_RG_VS2_ZXOS_TRIM_SHIFT}, + {PMIC_RG_VS2_PFMSR_EH, MT6351_PMIC_RG_VS2_PFMSR_EH_ADDR, + MT6351_PMIC_RG_VS2_PFMSR_EH_MASK, MT6351_PMIC_RG_VS2_PFMSR_EH_SHIFT}, + {PMIC_RG_VS2_NLIM_GATING, MT6351_PMIC_RG_VS2_NLIM_GATING_ADDR, + MT6351_PMIC_RG_VS2_NLIM_GATING_MASK, MT6351_PMIC_RG_VS2_NLIM_GATING_SHIFT}, + {PMIC_RG_VS2_PWRSR_EH, MT6351_PMIC_RG_VS2_PWRSR_EH_ADDR, + MT6351_PMIC_RG_VS2_PWRSR_EH_MASK, MT6351_PMIC_RG_VS2_PWRSR_EH_SHIFT}, + {PMIC_RG_VS2_HS_VTHDET, MT6351_PMIC_RG_VS2_HS_VTHDET_ADDR, + MT6351_PMIC_RG_VS2_HS_VTHDET_MASK, MT6351_PMIC_RG_VS2_HS_VTHDET_SHIFT}, + {PMIC_RG_VS2_PG_GATING, MT6351_PMIC_RG_VS2_PG_GATING_ADDR, + MT6351_PMIC_RG_VS2_PG_GATING_MASK, MT6351_PMIC_RG_VS2_PG_GATING_SHIFT}, + {PMIC_RG_VS2_HS_ONSPEED_EH, MT6351_PMIC_RG_VS2_HS_ONSPEED_EH_ADDR, + MT6351_PMIC_RG_VS2_HS_ONSPEED_EH_MASK, MT6351_PMIC_RG_VS2_HS_ONSPEED_EH_SHIFT}, + {PMIC_RG_VS2_NLIM_TRIMMING, MT6351_PMIC_RG_VS2_NLIM_TRIMMING_ADDR, + MT6351_PMIC_RG_VS2_NLIM_TRIMMING_MASK, MT6351_PMIC_RG_VS2_NLIM_TRIMMING_SHIFT}, + {PMIC_RG_VS2_DLC, MT6351_PMIC_RG_VS2_DLC_ADDR, MT6351_PMIC_RG_VS2_DLC_MASK, + MT6351_PMIC_RG_VS2_DLC_SHIFT}, + {PMIC_RG_VS2_DLC_N, MT6351_PMIC_RG_VS2_DLC_N_ADDR, MT6351_PMIC_RG_VS2_DLC_N_MASK, + MT6351_PMIC_RG_VS2_DLC_N_SHIFT}, + {PMIC_RG_VS2_PFM_RIP, MT6351_PMIC_RG_VS2_PFM_RIP_ADDR, + MT6351_PMIC_RG_VS2_PFM_RIP_MASK, MT6351_PMIC_RG_VS2_PFM_RIP_SHIFT}, + {PMIC_RG_VS2_TRAN_BST, MT6351_PMIC_RG_VS2_TRAN_BST_ADDR, + MT6351_PMIC_RG_VS2_TRAN_BST_MASK, MT6351_PMIC_RG_VS2_TRAN_BST_SHIFT}, + {PMIC_RG_VS2_DTS_ENB, MT6351_PMIC_RG_VS2_DTS_ENB_ADDR, + MT6351_PMIC_RG_VS2_DTS_ENB_MASK, MT6351_PMIC_RG_VS2_DTS_ENB_SHIFT}, + {PMIC_RG_VS2_MIN_OFF, MT6351_PMIC_RG_VS2_MIN_OFF_ADDR, + MT6351_PMIC_RG_VS2_MIN_OFF_MASK, MT6351_PMIC_RG_VS2_MIN_OFF_SHIFT}, + {PMIC_RG_VS2_1P35UP_SEL_EN, MT6351_PMIC_RG_VS2_1P35UP_SEL_EN_ADDR, + MT6351_PMIC_RG_VS2_1P35UP_SEL_EN_MASK, MT6351_PMIC_RG_VS2_1P35UP_SEL_EN_SHIFT}, + {PMIC_RG_VS2_DLC_AUTO_MODE, MT6351_PMIC_RG_VS2_DLC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VS2_DLC_AUTO_MODE_MASK, MT6351_PMIC_RG_VS2_DLC_AUTO_MODE_SHIFT}, + {PMIC_RG_VS2_DLC_SEL, MT6351_PMIC_RG_VS2_DLC_SEL_ADDR, + MT6351_PMIC_RG_VS2_DLC_SEL_MASK, MT6351_PMIC_RG_VS2_DLC_SEL_SHIFT}, + {PMIC_RG_VS2_SRC_AUTO_MODE, MT6351_PMIC_RG_VS2_SRC_AUTO_MODE_ADDR, + MT6351_PMIC_RG_VS2_SRC_AUTO_MODE_MASK, MT6351_PMIC_RG_VS2_SRC_AUTO_MODE_SHIFT}, + {PMIC_RG_VS2_UGP_SR, MT6351_PMIC_RG_VS2_UGP_SR_ADDR, + MT6351_PMIC_RG_VS2_UGP_SR_MASK, MT6351_PMIC_RG_VS2_UGP_SR_SHIFT}, + {PMIC_RG_VS2_LGN_SR, MT6351_PMIC_RG_VS2_LGN_SR_ADDR, + MT6351_PMIC_RG_VS2_LGN_SR_MASK, MT6351_PMIC_RG_VS2_LGN_SR_SHIFT}, + {PMIC_RG_VS2_UGP_SR_PFM, MT6351_PMIC_RG_VS2_UGP_SR_PFM_ADDR, + MT6351_PMIC_RG_VS2_UGP_SR_PFM_MASK, MT6351_PMIC_RG_VS2_UGP_SR_PFM_SHIFT}, + {PMIC_RG_VS2_LGN_SR_PFM, MT6351_PMIC_RG_VS2_LGN_SR_PFM_ADDR, + MT6351_PMIC_RG_VS2_LGN_SR_PFM_MASK, MT6351_PMIC_RG_VS2_LGN_SR_PFM_SHIFT}, + {PMIC_RG_VS2_UGD_VTHSEL, MT6351_PMIC_RG_VS2_UGD_VTHSEL_ADDR, + MT6351_PMIC_RG_VS2_UGD_VTHSEL_MASK, MT6351_PMIC_RG_VS2_UGD_VTHSEL_SHIFT}, + {PMIC_RG_VS2_FNLX_SNS, MT6351_PMIC_RG_VS2_FNLX_SNS_ADDR, + MT6351_PMIC_RG_VS2_FNLX_SNS_MASK, MT6351_PMIC_RG_VS2_FNLX_SNS_SHIFT}, + {PMIC_RG_VS2_VDIFF_ENLOWIQ, MT6351_PMIC_RG_VS2_VDIFF_ENLOWIQ_ADDR, + MT6351_PMIC_RG_VS2_VDIFF_ENLOWIQ_MASK, MT6351_PMIC_RG_VS2_VDIFF_ENLOWIQ_SHIFT}, + {PMIC_RG_VS2_PFMOC_FWUPOFF, MT6351_PMIC_RG_VS2_PFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VS2_PFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VS2_PFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VS2_PWFMOC_FWUPOFF, MT6351_PMIC_RG_VS2_PWFMOC_FWUPOFF_ADDR, + MT6351_PMIC_RG_VS2_PWFMOC_FWUPOFF_MASK, MT6351_PMIC_RG_VS2_PWFMOC_FWUPOFF_SHIFT}, + {PMIC_RG_VS2_CP_FWUPOFF, MT6351_PMIC_RG_VS2_CP_FWUPOFF_ADDR, + MT6351_PMIC_RG_VS2_CP_FWUPOFF_MASK, MT6351_PMIC_RG_VS2_CP_FWUPOFF_SHIFT}, + {PMIC_RG_VS2_ZX_GATING, MT6351_PMIC_RG_VS2_ZX_GATING_ADDR, + MT6351_PMIC_RG_VS2_ZX_GATING_MASK, MT6351_PMIC_RG_VS2_ZX_GATING_SHIFT}, + {PMIC_RG_VS2_RSV, MT6351_PMIC_RG_VS2_RSV_ADDR, MT6351_PMIC_RG_VS2_RSV_MASK, + MT6351_PMIC_RG_VS2_RSV_SHIFT}, + {PMIC_RG_VS2_AZC_EN, MT6351_PMIC_RG_VS2_AZC_EN_ADDR, + MT6351_PMIC_RG_VS2_AZC_EN_MASK, MT6351_PMIC_RG_VS2_AZC_EN_SHIFT}, + {PMIC_RG_VS2_AZC_DELAY, MT6351_PMIC_RG_VS2_AZC_DELAY_ADDR, + MT6351_PMIC_RG_VS2_AZC_DELAY_MASK, MT6351_PMIC_RG_VS2_AZC_DELAY_SHIFT}, + {PMIC_RG_VS2_AZC_HOLD_ENB, MT6351_PMIC_RG_VS2_AZC_HOLD_ENB_ADDR, + MT6351_PMIC_RG_VS2_AZC_HOLD_ENB_MASK, MT6351_PMIC_RG_VS2_AZC_HOLD_ENB_SHIFT}, + {PMIC_RGS_QI_VS2_OC_STATUS, MT6351_PMIC_RGS_QI_VS2_OC_STATUS_ADDR, + MT6351_PMIC_RGS_QI_VS2_OC_STATUS_MASK, MT6351_PMIC_RGS_QI_VS2_OC_STATUS_SHIFT}, + {PMIC_RGS_QI_VS2_DIG_MON, MT6351_PMIC_RGS_QI_VS2_DIG_MON_ADDR, + MT6351_PMIC_RGS_QI_VS2_DIG_MON_MASK, MT6351_PMIC_RGS_QI_VS2_DIG_MON_SHIFT}, + {PMIC_RGS_VS2_ENPWM_STATUS, MT6351_PMIC_RGS_VS2_ENPWM_STATUS_ADDR, + MT6351_PMIC_RGS_VS2_ENPWM_STATUS_MASK, MT6351_PMIC_RGS_VS2_ENPWM_STATUS_SHIFT}, + {PMIC_RG_VPA_NDIS_EN, MT6351_PMIC_RG_VPA_NDIS_EN_ADDR, + MT6351_PMIC_RG_VPA_NDIS_EN_MASK, MT6351_PMIC_RG_VPA_NDIS_EN_SHIFT}, + {PMIC_RG_VPA_MODESET, MT6351_PMIC_RG_VPA_MODESET_ADDR, + MT6351_PMIC_RG_VPA_MODESET_MASK, MT6351_PMIC_RG_VPA_MODESET_SHIFT}, + {PMIC_RG_VPA_CC, MT6351_PMIC_RG_VPA_CC_ADDR, MT6351_PMIC_RG_VPA_CC_MASK, + MT6351_PMIC_RG_VPA_CC_SHIFT}, + {PMIC_RG_VPA_CSR, MT6351_PMIC_RG_VPA_CSR_ADDR, MT6351_PMIC_RG_VPA_CSR_MASK, + MT6351_PMIC_RG_VPA_CSR_SHIFT}, + {PMIC_RG_VPA_CSMIR, MT6351_PMIC_RG_VPA_CSMIR_ADDR, MT6351_PMIC_RG_VPA_CSMIR_MASK, + MT6351_PMIC_RG_VPA_CSMIR_SHIFT}, + {PMIC_RG_VPA_CSL, MT6351_PMIC_RG_VPA_CSL_ADDR, MT6351_PMIC_RG_VPA_CSL_MASK, + MT6351_PMIC_RG_VPA_CSL_SHIFT}, + {PMIC_RG_VPA_SLP, MT6351_PMIC_RG_VPA_SLP_ADDR, MT6351_PMIC_RG_VPA_SLP_MASK, + MT6351_PMIC_RG_VPA_SLP_SHIFT}, + {PMIC_RG_VPA_AZC_EN, MT6351_PMIC_RG_VPA_AZC_EN_ADDR, + MT6351_PMIC_RG_VPA_AZC_EN_MASK, MT6351_PMIC_RG_VPA_AZC_EN_SHIFT}, + {PMIC_RG_VPA_CP_FWUPOFF, MT6351_PMIC_RG_VPA_CP_FWUPOFF_ADDR, + MT6351_PMIC_RG_VPA_CP_FWUPOFF_MASK, MT6351_PMIC_RG_VPA_CP_FWUPOFF_SHIFT}, + {PMIC_RG_VPA_AZC_DELAY, MT6351_PMIC_RG_VPA_AZC_DELAY_ADDR, + MT6351_PMIC_RG_VPA_AZC_DELAY_MASK, MT6351_PMIC_RG_VPA_AZC_DELAY_SHIFT}, + {PMIC_RG_VPA_RZSEL, MT6351_PMIC_RG_VPA_RZSEL_ADDR, MT6351_PMIC_RG_VPA_RZSEL_MASK, + MT6351_PMIC_RG_VPA_RZSEL_SHIFT}, + {PMIC_RG_VPA_ZXREF, MT6351_PMIC_RG_VPA_ZXREF_ADDR, MT6351_PMIC_RG_VPA_ZXREF_MASK, + MT6351_PMIC_RG_VPA_ZXREF_SHIFT}, + {PMIC_RG_VPA_NLIM_SEL, MT6351_PMIC_RG_VPA_NLIM_SEL_ADDR, + MT6351_PMIC_RG_VPA_NLIM_SEL_MASK, MT6351_PMIC_RG_VPA_NLIM_SEL_SHIFT}, + {PMIC_RG_VPA_HZP, MT6351_PMIC_RG_VPA_HZP_ADDR, MT6351_PMIC_RG_VPA_HZP_MASK, + MT6351_PMIC_RG_VPA_HZP_SHIFT}, + {PMIC_RG_VPA_BWEX_GAT, MT6351_PMIC_RG_VPA_BWEX_GAT_ADDR, + MT6351_PMIC_RG_VPA_BWEX_GAT_MASK, MT6351_PMIC_RG_VPA_BWEX_GAT_SHIFT}, + {PMIC_RG_VPA_SLEW, MT6351_PMIC_RG_VPA_SLEW_ADDR, MT6351_PMIC_RG_VPA_SLEW_MASK, + MT6351_PMIC_RG_VPA_SLEW_SHIFT}, + {PMIC_RG_VPA_SLEW_NMOS, MT6351_PMIC_RG_VPA_SLEW_NMOS_ADDR, + MT6351_PMIC_RG_VPA_SLEW_NMOS_MASK, MT6351_PMIC_RG_VPA_SLEW_NMOS_SHIFT}, + {PMIC_RG_VPA_MIN_ON, MT6351_PMIC_RG_VPA_MIN_ON_ADDR, + MT6351_PMIC_RG_VPA_MIN_ON_MASK, MT6351_PMIC_RG_VPA_MIN_ON_SHIFT}, + {PMIC_RG_VPA_VBAT_DEL, MT6351_PMIC_RG_VPA_VBAT_DEL_ADDR, + MT6351_PMIC_RG_VPA_VBAT_DEL_MASK, MT6351_PMIC_RG_VPA_VBAT_DEL_SHIFT}, + {PMIC_RGS_VPA_AZC_VOS_SEL, MT6351_PMIC_RGS_VPA_AZC_VOS_SEL_ADDR, + MT6351_PMIC_RGS_VPA_AZC_VOS_SEL_MASK, MT6351_PMIC_RGS_VPA_AZC_VOS_SEL_SHIFT}, + {PMIC_RG_VPA_MIN_PK, MT6351_PMIC_RG_VPA_MIN_PK_ADDR, + MT6351_PMIC_RG_VPA_MIN_PK_MASK, MT6351_PMIC_RG_VPA_MIN_PK_SHIFT}, + {PMIC_RG_VPA_RSV1, MT6351_PMIC_RG_VPA_RSV1_ADDR, MT6351_PMIC_RG_VPA_RSV1_MASK, + MT6351_PMIC_RG_VPA_RSV1_SHIFT}, + {PMIC_RG_VPA_RSV2, MT6351_PMIC_RG_VPA_RSV2_ADDR, MT6351_PMIC_RG_VPA_RSV2_MASK, + MT6351_PMIC_RG_VPA_RSV2_SHIFT}, + {PMIC_RGS_QI_VPA_OC_STATUS, MT6351_PMIC_RGS_QI_VPA_OC_STATUS_ADDR, + MT6351_PMIC_RGS_QI_VPA_OC_STATUS_MASK, MT6351_PMIC_RGS_QI_VPA_OC_STATUS_SHIFT}, + {PMIC_BUCK_VCORE_EN_CTRL, MT6351_PMIC_BUCK_VCORE_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VCORE_EN_CTRL_MASK, MT6351_PMIC_BUCK_VCORE_EN_CTRL_SHIFT}, + {PMIC_BUCK_VCORE_VOSEL_CTRL, MT6351_PMIC_BUCK_VCORE_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VCORE_VOSEL_CTRL_MASK, MT6351_PMIC_BUCK_VCORE_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VCORE_EN_SEL, MT6351_PMIC_BUCK_VCORE_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VCORE_EN_SEL_MASK, MT6351_PMIC_BUCK_VCORE_EN_SEL_SHIFT}, + {PMIC_BUCK_VCORE_VOSEL_SEL, MT6351_PMIC_BUCK_VCORE_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VCORE_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VCORE_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VCORE_EN, MT6351_PMIC_BUCK_VCORE_EN_ADDR, + MT6351_PMIC_BUCK_VCORE_EN_MASK, MT6351_PMIC_BUCK_VCORE_EN_SHIFT}, + {PMIC_BUCK_VCORE_STBTD, MT6351_PMIC_BUCK_VCORE_STBTD_ADDR, + MT6351_PMIC_BUCK_VCORE_STBTD_MASK, MT6351_PMIC_BUCK_VCORE_STBTD_SHIFT}, + {PMIC_DA_VCORE_STB, MT6351_PMIC_DA_VCORE_STB_ADDR, MT6351_PMIC_DA_VCORE_STB_MASK, + MT6351_PMIC_DA_VCORE_STB_SHIFT}, + {PMIC_DA_QI_VCORE_EN, MT6351_PMIC_DA_QI_VCORE_EN_ADDR, + MT6351_PMIC_DA_QI_VCORE_EN_MASK, MT6351_PMIC_DA_QI_VCORE_EN_SHIFT}, + {PMIC_BUCK_VCORE_SFCHG_FRATE, MT6351_PMIC_BUCK_VCORE_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VCORE_SFCHG_FRATE_MASK, MT6351_PMIC_BUCK_VCORE_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VCORE_SFCHG_FEN, MT6351_PMIC_BUCK_VCORE_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VCORE_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VCORE_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VCORE_SFCHG_RRATE, MT6351_PMIC_BUCK_VCORE_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VCORE_SFCHG_RRATE_MASK, MT6351_PMIC_BUCK_VCORE_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VCORE_SFCHG_REN, MT6351_PMIC_BUCK_VCORE_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VCORE_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VCORE_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VCORE_VOSEL, MT6351_PMIC_BUCK_VCORE_VOSEL_ADDR, + MT6351_PMIC_BUCK_VCORE_VOSEL_MASK, MT6351_PMIC_BUCK_VCORE_VOSEL_SHIFT}, + {PMIC_BUCK_VCORE_VOSEL_ON, MT6351_PMIC_BUCK_VCORE_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VCORE_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VCORE_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VCORE_VOSEL_SLEEP, MT6351_PMIC_BUCK_VCORE_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VCORE_VOSEL_SLEEP_MASK, MT6351_PMIC_BUCK_VCORE_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VCORE_VOSEL, MT6351_PMIC_DA_NI_VCORE_VOSEL_ADDR, + MT6351_PMIC_DA_NI_VCORE_VOSEL_MASK, MT6351_PMIC_DA_NI_VCORE_VOSEL_SHIFT}, + {PMIC_DA_NI_VCORE_VOSEL_SYNC, MT6351_PMIC_DA_NI_VCORE_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VCORE_VOSEL_SYNC_MASK, MT6351_PMIC_DA_NI_VCORE_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VCORE_TRANS_TD, MT6351_PMIC_BUCK_VCORE_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VCORE_TRANS_TD_MASK, MT6351_PMIC_BUCK_VCORE_TRANS_TD_SHIFT}, + {PMIC_BUCK_VCORE_TRANS_CTRL, MT6351_PMIC_BUCK_VCORE_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VCORE_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VCORE_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VCORE_TRANS_ONCE, MT6351_PMIC_BUCK_VCORE_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VCORE_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VCORE_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VCORE_DVS_EN, MT6351_PMIC_DA_QI_VCORE_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VCORE_DVS_EN_MASK, MT6351_PMIC_DA_QI_VCORE_DVS_EN_SHIFT}, + {PMIC_BUCK_VCORE_VSLEEP_EN, MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VCORE_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VCORE_R2R_PDN, MT6351_PMIC_BUCK_VCORE_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VCORE_R2R_PDN_MASK, MT6351_PMIC_BUCK_VCORE_R2R_PDN_SHIFT}, + {PMIC_BUCK_VCORE_VSLEEP_SEL, MT6351_PMIC_BUCK_VCORE_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VCORE_VSLEEP_SEL_MASK, MT6351_PMIC_BUCK_VCORE_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VCORE_R2R_PDN, MT6351_PMIC_DA_NI_VCORE_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VCORE_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VCORE_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VCORE_VSLEEP_SEL, MT6351_PMIC_DA_NI_VCORE_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VCORE_VSLEEP_SEL_MASK, MT6351_PMIC_DA_NI_VCORE_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_VGPU_EN_CTRL, MT6351_PMIC_BUCK_VGPU_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VGPU_EN_CTRL_MASK, MT6351_PMIC_BUCK_VGPU_EN_CTRL_SHIFT}, + {PMIC_BUCK_VGPU_VOSEL_CTRL, MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_MASK, MT6351_PMIC_BUCK_VGPU_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VGPU_EN_SEL, MT6351_PMIC_BUCK_VGPU_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VGPU_EN_SEL_MASK, MT6351_PMIC_BUCK_VGPU_EN_SEL_SHIFT}, + {PMIC_BUCK_VGPU_VOSEL_SEL, MT6351_PMIC_BUCK_VGPU_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VGPU_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VGPU_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VGPU_EN, MT6351_PMIC_BUCK_VGPU_EN_ADDR, MT6351_PMIC_BUCK_VGPU_EN_MASK, + MT6351_PMIC_BUCK_VGPU_EN_SHIFT}, + {PMIC_BUCK_VGPU_STBTD, MT6351_PMIC_BUCK_VGPU_STBTD_ADDR, + MT6351_PMIC_BUCK_VGPU_STBTD_MASK, MT6351_PMIC_BUCK_VGPU_STBTD_SHIFT}, + {PMIC_DA_VGPU_STB, MT6351_PMIC_DA_VGPU_STB_ADDR, MT6351_PMIC_DA_VGPU_STB_MASK, + MT6351_PMIC_DA_VGPU_STB_SHIFT}, + {PMIC_DA_QI_VGPU_EN, MT6351_PMIC_DA_QI_VGPU_EN_ADDR, + MT6351_PMIC_DA_QI_VGPU_EN_MASK, MT6351_PMIC_DA_QI_VGPU_EN_SHIFT}, + {PMIC_BUCK_VGPU_SFCHG_FRATE, MT6351_PMIC_BUCK_VGPU_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VGPU_SFCHG_FRATE_MASK, MT6351_PMIC_BUCK_VGPU_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VGPU_SFCHG_FEN, MT6351_PMIC_BUCK_VGPU_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VGPU_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VGPU_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VGPU_SFCHG_RRATE, MT6351_PMIC_BUCK_VGPU_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VGPU_SFCHG_RRATE_MASK, MT6351_PMIC_BUCK_VGPU_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VGPU_SFCHG_REN, MT6351_PMIC_BUCK_VGPU_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VGPU_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VGPU_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VGPU_VOSEL, MT6351_PMIC_BUCK_VGPU_VOSEL_ADDR, + MT6351_PMIC_BUCK_VGPU_VOSEL_MASK, MT6351_PMIC_BUCK_VGPU_VOSEL_SHIFT}, + {PMIC_BUCK_VGPU_VOSEL_ON, MT6351_PMIC_BUCK_VGPU_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VGPU_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VGPU_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VGPU_VOSEL_SLEEP, MT6351_PMIC_BUCK_VGPU_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VGPU_VOSEL_SLEEP_MASK, MT6351_PMIC_BUCK_VGPU_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VGPU_VOSEL, MT6351_PMIC_DA_NI_VGPU_VOSEL_ADDR, + MT6351_PMIC_DA_NI_VGPU_VOSEL_MASK, MT6351_PMIC_DA_NI_VGPU_VOSEL_SHIFT}, + {PMIC_DA_NI_VGPU_VOSEL_SYNC, MT6351_PMIC_DA_NI_VGPU_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VGPU_VOSEL_SYNC_MASK, MT6351_PMIC_DA_NI_VGPU_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VGPU_TRANS_TD, MT6351_PMIC_BUCK_VGPU_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VGPU_TRANS_TD_MASK, MT6351_PMIC_BUCK_VGPU_TRANS_TD_SHIFT}, + {PMIC_BUCK_VGPU_TRANS_CTRL, MT6351_PMIC_BUCK_VGPU_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VGPU_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VGPU_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VGPU_TRANS_ONCE, MT6351_PMIC_BUCK_VGPU_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VGPU_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VGPU_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VGPU_DVS_EN, MT6351_PMIC_DA_QI_VGPU_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VGPU_DVS_EN_MASK, MT6351_PMIC_DA_QI_VGPU_DVS_EN_SHIFT}, + {PMIC_BUCK_VGPU_VSLEEP_EN, MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VGPU_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VGPU_R2R_PDN, MT6351_PMIC_BUCK_VGPU_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VGPU_R2R_PDN_MASK, MT6351_PMIC_BUCK_VGPU_R2R_PDN_SHIFT}, + {PMIC_BUCK_VGPU_VSLEEP_SEL, MT6351_PMIC_BUCK_VGPU_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VGPU_VSLEEP_SEL_MASK, MT6351_PMIC_BUCK_VGPU_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VGPU_R2R_PDN, MT6351_PMIC_DA_NI_VGPU_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VGPU_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VGPU_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VGPU_VSLEEP_SEL, MT6351_PMIC_DA_NI_VGPU_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VGPU_VSLEEP_SEL_MASK, MT6351_PMIC_DA_NI_VGPU_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_VMODEM_EN_CTRL, MT6351_PMIC_BUCK_VMODEM_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VMODEM_EN_CTRL_MASK, MT6351_PMIC_BUCK_VMODEM_EN_CTRL_SHIFT}, + {PMIC_BUCK_VMODEM_VOSEL_CTRL, MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL_MASK, MT6351_PMIC_BUCK_VMODEM_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VMODEM_EN_SEL, MT6351_PMIC_BUCK_VMODEM_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VMODEM_EN_SEL_MASK, MT6351_PMIC_BUCK_VMODEM_EN_SEL_SHIFT}, + {PMIC_BUCK_VMODEM_VOSEL_SEL, MT6351_PMIC_BUCK_VMODEM_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VMODEM_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VMODEM_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VMODEM_EN, MT6351_PMIC_BUCK_VMODEM_EN_ADDR, + MT6351_PMIC_BUCK_VMODEM_EN_MASK, MT6351_PMIC_BUCK_VMODEM_EN_SHIFT}, + {PMIC_BUCK_VMODEM_STBTD, MT6351_PMIC_BUCK_VMODEM_STBTD_ADDR, + MT6351_PMIC_BUCK_VMODEM_STBTD_MASK, MT6351_PMIC_BUCK_VMODEM_STBTD_SHIFT}, + {PMIC_DA_VMODEM_STB, MT6351_PMIC_DA_VMODEM_STB_ADDR, + MT6351_PMIC_DA_VMODEM_STB_MASK, MT6351_PMIC_DA_VMODEM_STB_SHIFT}, + {PMIC_DA_QI_VMODEM_EN, MT6351_PMIC_DA_QI_VMODEM_EN_ADDR, + MT6351_PMIC_DA_QI_VMODEM_EN_MASK, MT6351_PMIC_DA_QI_VMODEM_EN_SHIFT}, + {PMIC_BUCK_VMODEM_SFCHG_FRATE, MT6351_PMIC_BUCK_VMODEM_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VMODEM_SFCHG_FRATE_MASK, MT6351_PMIC_BUCK_VMODEM_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VMODEM_SFCHG_FEN, MT6351_PMIC_BUCK_VMODEM_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VMODEM_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VMODEM_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VMODEM_SFCHG_RRATE, MT6351_PMIC_BUCK_VMODEM_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VMODEM_SFCHG_RRATE_MASK, MT6351_PMIC_BUCK_VMODEM_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VMODEM_SFCHG_REN, MT6351_PMIC_BUCK_VMODEM_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VMODEM_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VMODEM_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VMODEM_VOSEL, MT6351_PMIC_BUCK_VMODEM_VOSEL_ADDR, + MT6351_PMIC_BUCK_VMODEM_VOSEL_MASK, MT6351_PMIC_BUCK_VMODEM_VOSEL_SHIFT}, + {PMIC_BUCK_VMODEM_VOSEL_ON, MT6351_PMIC_BUCK_VMODEM_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VMODEM_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VMODEM_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VMODEM_VOSEL_SLEEP, MT6351_PMIC_BUCK_VMODEM_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VMODEM_VOSEL_SLEEP_MASK, MT6351_PMIC_BUCK_VMODEM_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VMODEM_VOSEL, MT6351_PMIC_DA_NI_VMODEM_VOSEL_ADDR, + MT6351_PMIC_DA_NI_VMODEM_VOSEL_MASK, MT6351_PMIC_DA_NI_VMODEM_VOSEL_SHIFT}, + {PMIC_DA_NI_VMODEM_VOSEL_SYNC, MT6351_PMIC_DA_NI_VMODEM_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VMODEM_VOSEL_SYNC_MASK, MT6351_PMIC_DA_NI_VMODEM_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VMODEM_TRANS_TD, MT6351_PMIC_BUCK_VMODEM_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VMODEM_TRANS_TD_MASK, MT6351_PMIC_BUCK_VMODEM_TRANS_TD_SHIFT}, + {PMIC_BUCK_VMODEM_TRANS_CTRL, MT6351_PMIC_BUCK_VMODEM_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VMODEM_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VMODEM_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VMODEM_TRANS_ONCE, MT6351_PMIC_BUCK_VMODEM_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VMODEM_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VMODEM_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VMODEM_DVS_EN, MT6351_PMIC_DA_QI_VMODEM_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VMODEM_DVS_EN_MASK, MT6351_PMIC_DA_QI_VMODEM_DVS_EN_SHIFT}, + {PMIC_BUCK_VMODEM_VSLEEP_EN, MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VMODEM_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VMODEM_R2R_PDN, MT6351_PMIC_BUCK_VMODEM_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VMODEM_R2R_PDN_MASK, MT6351_PMIC_BUCK_VMODEM_R2R_PDN_SHIFT}, + {PMIC_BUCK_VMODEM_VSLEEP_SEL, MT6351_PMIC_BUCK_VMODEM_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VMODEM_VSLEEP_SEL_MASK, MT6351_PMIC_BUCK_VMODEM_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VMODEM_R2R_PDN, MT6351_PMIC_DA_NI_VMODEM_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VMODEM_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VMODEM_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VMODEM_VSLEEP_SEL, MT6351_PMIC_DA_NI_VMODEM_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VMODEM_VSLEEP_SEL_MASK, MT6351_PMIC_DA_NI_VMODEM_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_VMD1_EN_CTRL, MT6351_PMIC_BUCK_VMD1_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VMD1_EN_CTRL_MASK, MT6351_PMIC_BUCK_VMD1_EN_CTRL_SHIFT}, + {PMIC_BUCK_VMD1_VOSEL_CTRL, MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL_MASK, MT6351_PMIC_BUCK_VMD1_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VMD1_EN_SEL, MT6351_PMIC_BUCK_VMD1_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VMD1_EN_SEL_MASK, MT6351_PMIC_BUCK_VMD1_EN_SEL_SHIFT}, + {PMIC_BUCK_VMD1_VOSEL_SEL, MT6351_PMIC_BUCK_VMD1_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VMD1_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VMD1_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VMD1_EN, MT6351_PMIC_BUCK_VMD1_EN_ADDR, MT6351_PMIC_BUCK_VMD1_EN_MASK, + MT6351_PMIC_BUCK_VMD1_EN_SHIFT}, + {PMIC_BUCK_VMD1_STBTD, MT6351_PMIC_BUCK_VMD1_STBTD_ADDR, + MT6351_PMIC_BUCK_VMD1_STBTD_MASK, MT6351_PMIC_BUCK_VMD1_STBTD_SHIFT}, + {PMIC_DA_VMD1_STB, MT6351_PMIC_DA_VMD1_STB_ADDR, MT6351_PMIC_DA_VMD1_STB_MASK, + MT6351_PMIC_DA_VMD1_STB_SHIFT}, + {PMIC_DA_QI_VMD1_EN, MT6351_PMIC_DA_QI_VMD1_EN_ADDR, + MT6351_PMIC_DA_QI_VMD1_EN_MASK, MT6351_PMIC_DA_QI_VMD1_EN_SHIFT}, + {PMIC_BUCK_VMD1_SFCHG_FRATE, MT6351_PMIC_BUCK_VMD1_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VMD1_SFCHG_FRATE_MASK, MT6351_PMIC_BUCK_VMD1_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VMD1_SFCHG_FEN, MT6351_PMIC_BUCK_VMD1_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VMD1_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VMD1_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VMD1_SFCHG_RRATE, MT6351_PMIC_BUCK_VMD1_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VMD1_SFCHG_RRATE_MASK, MT6351_PMIC_BUCK_VMD1_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VMD1_SFCHG_REN, MT6351_PMIC_BUCK_VMD1_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VMD1_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VMD1_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VMD1_VOSEL, MT6351_PMIC_BUCK_VMD1_VOSEL_ADDR, + MT6351_PMIC_BUCK_VMD1_VOSEL_MASK, MT6351_PMIC_BUCK_VMD1_VOSEL_SHIFT}, + {PMIC_BUCK_VMD1_VOSEL_ON, MT6351_PMIC_BUCK_VMD1_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VMD1_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VMD1_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VMD1_VOSEL_SLEEP, MT6351_PMIC_BUCK_VMD1_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VMD1_VOSEL_SLEEP_MASK, MT6351_PMIC_BUCK_VMD1_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VMD1_VOSEL, MT6351_PMIC_DA_NI_VMD1_VOSEL_ADDR, + MT6351_PMIC_DA_NI_VMD1_VOSEL_MASK, MT6351_PMIC_DA_NI_VMD1_VOSEL_SHIFT}, + {PMIC_DA_NI_VMD1_VOSEL_SYNC, MT6351_PMIC_DA_NI_VMD1_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VMD1_VOSEL_SYNC_MASK, MT6351_PMIC_DA_NI_VMD1_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VMD1_TRANS_TD, MT6351_PMIC_BUCK_VMD1_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VMD1_TRANS_TD_MASK, MT6351_PMIC_BUCK_VMD1_TRANS_TD_SHIFT}, + {PMIC_BUCK_VMD1_TRANS_CTRL, MT6351_PMIC_BUCK_VMD1_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VMD1_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VMD1_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VMD1_TRANS_ONCE, MT6351_PMIC_BUCK_VMD1_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VMD1_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VMD1_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VMD1_DVS_EN, MT6351_PMIC_DA_QI_VMD1_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VMD1_DVS_EN_MASK, MT6351_PMIC_DA_QI_VMD1_DVS_EN_SHIFT}, + {PMIC_BUCK_VMD1_VSLEEP_EN, MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VMD1_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VMD1_R2R_PDN, MT6351_PMIC_BUCK_VMD1_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VMD1_R2R_PDN_MASK, MT6351_PMIC_BUCK_VMD1_R2R_PDN_SHIFT}, + {PMIC_BUCK_VMD1_VSLEEP_SEL, MT6351_PMIC_BUCK_VMD1_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VMD1_VSLEEP_SEL_MASK, MT6351_PMIC_BUCK_VMD1_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VMD1_R2R_PDN, MT6351_PMIC_DA_NI_VMD1_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VMD1_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VMD1_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VMD1_VSLEEP_SEL, MT6351_PMIC_DA_NI_VMD1_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VMD1_VSLEEP_SEL_MASK, MT6351_PMIC_DA_NI_VMD1_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_EN_CTRL, MT6351_PMIC_BUCK_VSRAM_MD_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_EN_CTRL_MASK, MT6351_PMIC_BUCK_VSRAM_MD_EN_CTRL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_VOSEL_CTRL, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL_MASK, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_EN_SEL, MT6351_PMIC_BUCK_VSRAM_MD_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_EN_SEL_MASK, MT6351_PMIC_BUCK_VSRAM_MD_EN_SEL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_VOSEL_SEL, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_EN, MT6351_PMIC_BUCK_VSRAM_MD_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_EN_MASK, MT6351_PMIC_BUCK_VSRAM_MD_EN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_STBTD, MT6351_PMIC_BUCK_VSRAM_MD_STBTD_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_STBTD_MASK, MT6351_PMIC_BUCK_VSRAM_MD_STBTD_SHIFT}, + {PMIC_DA_VSRAM_MD_STB, MT6351_PMIC_DA_VSRAM_MD_STB_ADDR, + MT6351_PMIC_DA_VSRAM_MD_STB_MASK, MT6351_PMIC_DA_VSRAM_MD_STB_SHIFT}, + {PMIC_DA_QI_VSRAM_MD_EN, MT6351_PMIC_DA_QI_VSRAM_MD_EN_ADDR, + MT6351_PMIC_DA_QI_VSRAM_MD_EN_MASK, MT6351_PMIC_DA_QI_VSRAM_MD_EN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_SFCHG_FRATE, MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FRATE_MASK, MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VSRAM_MD_SFCHG_FEN, MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_SFCHG_RRATE, MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_RRATE_MASK, MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VSRAM_MD_SFCHG_REN, MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VSRAM_MD_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_VOSEL, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_MASK, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_VOSEL_ON, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP_MASK, MT6351_PMIC_BUCK_VSRAM_MD_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VSRAM_MD_VOSEL, MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_ADDR, + MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_MASK, MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SHIFT}, + {PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC, MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC_MASK, MT6351_PMIC_DA_NI_VSRAM_MD_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VSRAM_MD_TRANS_TD, MT6351_PMIC_BUCK_VSRAM_MD_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_TRANS_TD_MASK, MT6351_PMIC_BUCK_VSRAM_MD_TRANS_TD_SHIFT}, + {PMIC_BUCK_VSRAM_MD_TRANS_CTRL, MT6351_PMIC_BUCK_VSRAM_MD_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VSRAM_MD_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VSRAM_MD_TRANS_ONCE, MT6351_PMIC_BUCK_VSRAM_MD_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VSRAM_MD_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VSRAM_MD_DVS_EN, MT6351_PMIC_DA_QI_VSRAM_MD_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VSRAM_MD_DVS_EN_MASK, MT6351_PMIC_DA_QI_VSRAM_MD_DVS_EN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_VSLEEP_EN, MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_R2R_PDN, MT6351_PMIC_BUCK_VSRAM_MD_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_R2R_PDN_MASK, MT6351_PMIC_BUCK_VSRAM_MD_R2R_PDN_SHIFT}, + {PMIC_BUCK_VSRAM_MD_VSLEEP_SEL, MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_SEL_MASK, MT6351_PMIC_BUCK_VSRAM_MD_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VSRAM_MD_R2R_PDN, MT6351_PMIC_DA_NI_VSRAM_MD_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VSRAM_MD_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VSRAM_MD_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL, MT6351_PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL_MASK, MT6351_PMIC_DA_NI_VSRAM_MD_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_VS1_EN_CTRL, MT6351_PMIC_BUCK_VS1_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VS1_EN_CTRL_MASK, MT6351_PMIC_BUCK_VS1_EN_CTRL_SHIFT}, + {PMIC_BUCK_VS1_VOSEL_CTRL, MT6351_PMIC_BUCK_VS1_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VS1_VOSEL_CTRL_MASK, MT6351_PMIC_BUCK_VS1_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VS1_EN_SEL, MT6351_PMIC_BUCK_VS1_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VS1_EN_SEL_MASK, MT6351_PMIC_BUCK_VS1_EN_SEL_SHIFT}, + {PMIC_BUCK_VS1_VOSEL_SEL, MT6351_PMIC_BUCK_VS1_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VS1_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VS1_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VS1_EN, MT6351_PMIC_BUCK_VS1_EN_ADDR, MT6351_PMIC_BUCK_VS1_EN_MASK, + MT6351_PMIC_BUCK_VS1_EN_SHIFT}, + {PMIC_BUCK_VS1_STBTD, MT6351_PMIC_BUCK_VS1_STBTD_ADDR, + MT6351_PMIC_BUCK_VS1_STBTD_MASK, MT6351_PMIC_BUCK_VS1_STBTD_SHIFT}, + {PMIC_DA_VS1_STB, MT6351_PMIC_DA_VS1_STB_ADDR, MT6351_PMIC_DA_VS1_STB_MASK, + MT6351_PMIC_DA_VS1_STB_SHIFT}, + {PMIC_DA_QI_VS1_EN, MT6351_PMIC_DA_QI_VS1_EN_ADDR, MT6351_PMIC_DA_QI_VS1_EN_MASK, + MT6351_PMIC_DA_QI_VS1_EN_SHIFT}, + {PMIC_BUCK_VS1_SFCHG_FRATE, MT6351_PMIC_BUCK_VS1_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VS1_SFCHG_FRATE_MASK, MT6351_PMIC_BUCK_VS1_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VS1_SFCHG_FEN, MT6351_PMIC_BUCK_VS1_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VS1_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VS1_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VS1_SFCHG_RRATE, MT6351_PMIC_BUCK_VS1_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VS1_SFCHG_RRATE_MASK, MT6351_PMIC_BUCK_VS1_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VS1_SFCHG_REN, MT6351_PMIC_BUCK_VS1_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VS1_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VS1_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VS1_VOSEL, MT6351_PMIC_BUCK_VS1_VOSEL_ADDR, + MT6351_PMIC_BUCK_VS1_VOSEL_MASK, MT6351_PMIC_BUCK_VS1_VOSEL_SHIFT}, + {PMIC_BUCK_VS1_VOSEL_ON, MT6351_PMIC_BUCK_VS1_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VS1_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VS1_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VS1_VOSEL_SLEEP, MT6351_PMIC_BUCK_VS1_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VS1_VOSEL_SLEEP_MASK, MT6351_PMIC_BUCK_VS1_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VS1_VOSEL, MT6351_PMIC_DA_NI_VS1_VOSEL_ADDR, + MT6351_PMIC_DA_NI_VS1_VOSEL_MASK, MT6351_PMIC_DA_NI_VS1_VOSEL_SHIFT}, + {PMIC_DA_NI_VS1_VOSEL_SYNC, MT6351_PMIC_DA_NI_VS1_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VS1_VOSEL_SYNC_MASK, MT6351_PMIC_DA_NI_VS1_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VS1_TRANS_TD, MT6351_PMIC_BUCK_VS1_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VS1_TRANS_TD_MASK, MT6351_PMIC_BUCK_VS1_TRANS_TD_SHIFT}, + {PMIC_BUCK_VS1_TRANS_CTRL, MT6351_PMIC_BUCK_VS1_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VS1_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VS1_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VS1_TRANS_ONCE, MT6351_PMIC_BUCK_VS1_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VS1_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VS1_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VS1_DVS_EN, MT6351_PMIC_DA_QI_VS1_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VS1_DVS_EN_MASK, MT6351_PMIC_DA_QI_VS1_DVS_EN_SHIFT}, + {PMIC_BUCK_VS1_VSLEEP_EN, MT6351_PMIC_BUCK_VS1_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VS1_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VS1_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VS1_R2R_PDN, MT6351_PMIC_BUCK_VS1_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VS1_R2R_PDN_MASK, MT6351_PMIC_BUCK_VS1_R2R_PDN_SHIFT}, + {PMIC_BUCK_VS1_VSLEEP_SEL, MT6351_PMIC_BUCK_VS1_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VS1_VSLEEP_SEL_MASK, MT6351_PMIC_BUCK_VS1_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VS1_R2R_PDN, MT6351_PMIC_DA_NI_VS1_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VS1_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VS1_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VS1_VSLEEP_SEL, MT6351_PMIC_DA_NI_VS1_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VS1_VSLEEP_SEL_MASK, MT6351_PMIC_DA_NI_VS1_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_VS2_EN_CTRL, MT6351_PMIC_BUCK_VS2_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VS2_EN_CTRL_MASK, MT6351_PMIC_BUCK_VS2_EN_CTRL_SHIFT}, + {PMIC_BUCK_VS2_VOSEL_CTRL, MT6351_PMIC_BUCK_VS2_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VS2_VOSEL_CTRL_MASK, MT6351_PMIC_BUCK_VS2_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VS2_EN_SEL, MT6351_PMIC_BUCK_VS2_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VS2_EN_SEL_MASK, MT6351_PMIC_BUCK_VS2_EN_SEL_SHIFT}, + {PMIC_BUCK_VS2_VOSEL_SEL, MT6351_PMIC_BUCK_VS2_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VS2_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VS2_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VS2_EN, MT6351_PMIC_BUCK_VS2_EN_ADDR, MT6351_PMIC_BUCK_VS2_EN_MASK, + MT6351_PMIC_BUCK_VS2_EN_SHIFT}, + {PMIC_BUCK_VS2_STBTD, MT6351_PMIC_BUCK_VS2_STBTD_ADDR, + MT6351_PMIC_BUCK_VS2_STBTD_MASK, MT6351_PMIC_BUCK_VS2_STBTD_SHIFT}, + {PMIC_DA_VS2_STB, MT6351_PMIC_DA_VS2_STB_ADDR, MT6351_PMIC_DA_VS2_STB_MASK, + MT6351_PMIC_DA_VS2_STB_SHIFT}, + {PMIC_DA_QI_VS2_EN, MT6351_PMIC_DA_QI_VS2_EN_ADDR, MT6351_PMIC_DA_QI_VS2_EN_MASK, + MT6351_PMIC_DA_QI_VS2_EN_SHIFT}, + {PMIC_BUCK_VS2_SFCHG_FRATE, MT6351_PMIC_BUCK_VS2_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VS2_SFCHG_FRATE_MASK, MT6351_PMIC_BUCK_VS2_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VS2_SFCHG_FEN, MT6351_PMIC_BUCK_VS2_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VS2_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VS2_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VS2_SFCHG_RRATE, MT6351_PMIC_BUCK_VS2_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VS2_SFCHG_RRATE_MASK, MT6351_PMIC_BUCK_VS2_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VS2_SFCHG_REN, MT6351_PMIC_BUCK_VS2_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VS2_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VS2_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VS2_VOSEL, MT6351_PMIC_BUCK_VS2_VOSEL_ADDR, + MT6351_PMIC_BUCK_VS2_VOSEL_MASK, MT6351_PMIC_BUCK_VS2_VOSEL_SHIFT}, + {PMIC_BUCK_VS2_VOSEL_ON, MT6351_PMIC_BUCK_VS2_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VS2_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VS2_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VS2_VOSEL_SLEEP, MT6351_PMIC_BUCK_VS2_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VS2_VOSEL_SLEEP_MASK, MT6351_PMIC_BUCK_VS2_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VS2_VOSEL, MT6351_PMIC_DA_NI_VS2_VOSEL_ADDR, + MT6351_PMIC_DA_NI_VS2_VOSEL_MASK, MT6351_PMIC_DA_NI_VS2_VOSEL_SHIFT}, + {PMIC_DA_NI_VS2_VOSEL_SYNC, MT6351_PMIC_DA_NI_VS2_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VS2_VOSEL_SYNC_MASK, MT6351_PMIC_DA_NI_VS2_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VS2_TRANS_TD, MT6351_PMIC_BUCK_VS2_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VS2_TRANS_TD_MASK, MT6351_PMIC_BUCK_VS2_TRANS_TD_SHIFT}, + {PMIC_BUCK_VS2_TRANS_CTRL, MT6351_PMIC_BUCK_VS2_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VS2_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VS2_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VS2_TRANS_ONCE, MT6351_PMIC_BUCK_VS2_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VS2_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VS2_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VS2_DVS_EN, MT6351_PMIC_DA_QI_VS2_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VS2_DVS_EN_MASK, MT6351_PMIC_DA_QI_VS2_DVS_EN_SHIFT}, + {PMIC_BUCK_VS2_VSLEEP_EN, MT6351_PMIC_BUCK_VS2_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VS2_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VS2_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VS2_R2R_PDN, MT6351_PMIC_BUCK_VS2_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VS2_R2R_PDN_MASK, MT6351_PMIC_BUCK_VS2_R2R_PDN_SHIFT}, + {PMIC_BUCK_VS2_VSLEEP_SEL, MT6351_PMIC_BUCK_VS2_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VS2_VSLEEP_SEL_MASK, MT6351_PMIC_BUCK_VS2_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VS2_R2R_PDN, MT6351_PMIC_DA_NI_VS2_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VS2_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VS2_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VS2_VSLEEP_SEL, MT6351_PMIC_DA_NI_VS2_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VS2_VSLEEP_SEL_MASK, MT6351_PMIC_DA_NI_VS2_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_VPA_EN_CTRL, MT6351_PMIC_BUCK_VPA_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VPA_EN_CTRL_MASK, MT6351_PMIC_BUCK_VPA_EN_CTRL_SHIFT}, + {PMIC_BUCK_VPA_VOSEL_CTRL, MT6351_PMIC_BUCK_VPA_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VPA_VOSEL_CTRL_MASK, MT6351_PMIC_BUCK_VPA_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VPA_EN_SEL, MT6351_PMIC_BUCK_VPA_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VPA_EN_SEL_MASK, MT6351_PMIC_BUCK_VPA_EN_SEL_SHIFT}, + {PMIC_BUCK_VPA_VOSEL_SEL, MT6351_PMIC_BUCK_VPA_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VPA_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VPA_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VPA_EN, MT6351_PMIC_BUCK_VPA_EN_ADDR, MT6351_PMIC_BUCK_VPA_EN_MASK, + MT6351_PMIC_BUCK_VPA_EN_SHIFT}, + {PMIC_BUCK_VPA_STBTD, MT6351_PMIC_BUCK_VPA_STBTD_ADDR, + MT6351_PMIC_BUCK_VPA_STBTD_MASK, MT6351_PMIC_BUCK_VPA_STBTD_SHIFT}, + {PMIC_DA_VPA_STB, MT6351_PMIC_DA_VPA_STB_ADDR, MT6351_PMIC_DA_VPA_STB_MASK, + MT6351_PMIC_DA_VPA_STB_SHIFT}, + {PMIC_DA_QI_VPA_EN, MT6351_PMIC_DA_QI_VPA_EN_ADDR, MT6351_PMIC_DA_QI_VPA_EN_MASK, + MT6351_PMIC_DA_QI_VPA_EN_SHIFT}, + {PMIC_BUCK_VPA_SFCHG_FRATE, MT6351_PMIC_BUCK_VPA_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VPA_SFCHG_FRATE_MASK, MT6351_PMIC_BUCK_VPA_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VPA_SFCHG_FEN, MT6351_PMIC_BUCK_VPA_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VPA_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VPA_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VPA_SFCHG_RRATE, MT6351_PMIC_BUCK_VPA_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VPA_SFCHG_RRATE_MASK, MT6351_PMIC_BUCK_VPA_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VPA_SFCHG_REN, MT6351_PMIC_BUCK_VPA_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VPA_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VPA_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VPA_VOSEL, MT6351_PMIC_BUCK_VPA_VOSEL_ADDR, + MT6351_PMIC_BUCK_VPA_VOSEL_MASK, MT6351_PMIC_BUCK_VPA_VOSEL_SHIFT}, + {PMIC_BUCK_VPA_VOSEL_ON, MT6351_PMIC_BUCK_VPA_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VPA_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VPA_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VPA_VOSEL_SLEEP, MT6351_PMIC_BUCK_VPA_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VPA_VOSEL_SLEEP_MASK, MT6351_PMIC_BUCK_VPA_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VPA_VOSEL_GRAY, MT6351_PMIC_DA_NI_VPA_VOSEL_GRAY_ADDR, + MT6351_PMIC_DA_NI_VPA_VOSEL_GRAY_MASK, MT6351_PMIC_DA_NI_VPA_VOSEL_GRAY_SHIFT}, + {PMIC_DA_NI_VPA_VOSEL_SYNC, MT6351_PMIC_DA_NI_VPA_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VPA_VOSEL_SYNC_MASK, MT6351_PMIC_DA_NI_VPA_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VPA_TRANS_TD, MT6351_PMIC_BUCK_VPA_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VPA_TRANS_TD_MASK, MT6351_PMIC_BUCK_VPA_TRANS_TD_SHIFT}, + {PMIC_BUCK_VPA_TRANS_CTRL, MT6351_PMIC_BUCK_VPA_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VPA_TRANS_CTRL_MASK, MT6351_PMIC_BUCK_VPA_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VPA_TRANS_ONCE, MT6351_PMIC_BUCK_VPA_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VPA_TRANS_ONCE_MASK, MT6351_PMIC_BUCK_VPA_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VPA_DVS_EN, MT6351_PMIC_DA_QI_VPA_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VPA_DVS_EN_MASK, MT6351_PMIC_DA_QI_VPA_DVS_EN_SHIFT}, + {PMIC_BUCK_VPA_VSLEEP_EN, MT6351_PMIC_BUCK_VPA_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VPA_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VPA_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VPA_R2R_PDN, MT6351_PMIC_BUCK_VPA_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VPA_R2R_PDN_MASK, MT6351_PMIC_BUCK_VPA_R2R_PDN_SHIFT}, + {PMIC_BUCK_VPA_VSLEEP_SEL, MT6351_PMIC_BUCK_VPA_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VPA_VSLEEP_SEL_MASK, MT6351_PMIC_BUCK_VPA_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VPA_R2R_PDN, MT6351_PMIC_DA_NI_VPA_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VPA_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VPA_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VPA_VSLEEP_SEL, MT6351_PMIC_DA_NI_VPA_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VPA_VSLEEP_SEL_MASK, MT6351_PMIC_DA_NI_VPA_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_EN_CTRL, MT6351_PMIC_BUCK_VSRAM_PROC_EN_CTRL_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_EN_CTRL_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_EN_CTRL_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL, MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_CTRL_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_EN_SEL, MT6351_PMIC_BUCK_VSRAM_PROC_EN_SEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_EN_SEL_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_EN_SEL_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_VOSEL_SEL, MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SEL_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SEL_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_EN, MT6351_PMIC_BUCK_VSRAM_PROC_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_EN_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_EN_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_STBTD, MT6351_PMIC_BUCK_VSRAM_PROC_STBTD_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_STBTD_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_STBTD_SHIFT}, + {PMIC_DA_VSRAM_PROC_STB, MT6351_PMIC_DA_VSRAM_PROC_STB_ADDR, + MT6351_PMIC_DA_VSRAM_PROC_STB_MASK, MT6351_PMIC_DA_VSRAM_PROC_STB_SHIFT}, + {PMIC_DA_QI_VSRAM_PROC_EN_RSV, MT6351_PMIC_DA_QI_VSRAM_PROC_EN_RSV_ADDR, + MT6351_PMIC_DA_QI_VSRAM_PROC_EN_RSV_MASK, MT6351_PMIC_DA_QI_VSRAM_PROC_EN_RSV_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE, MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FRATE_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_SFCHG_FEN, MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FEN_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FEN_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_FEN_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE, MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_RRATE_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_SFCHG_REN, MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_REN_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_REN_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_SFCHG_REN_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_VOSEL, MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_VOSEL_ON, MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_ON_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP, MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_VOSEL_SLEEP_SHIFT}, + {PMIC_DA_NI_VSRAM_PROC_VOSEL, MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_ADDR, + MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_MASK, MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SHIFT}, + {PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC, MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC_ADDR, + MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC_MASK, + MT6351_PMIC_DA_NI_VSRAM_PROC_VOSEL_SYNC_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_TRANS_TD, MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_TD_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_TD_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_TD_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_TRANS_CTRL, MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_CTRL_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_CTRL_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_CTRL_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_TRANS_ONCE, MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_ONCE_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_ONCE_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_TRANS_ONCE_SHIFT}, + {PMIC_DA_QI_VSRAM_PROC_DVS_EN, MT6351_PMIC_DA_QI_VSRAM_PROC_DVS_EN_ADDR, + MT6351_PMIC_DA_QI_VSRAM_PROC_DVS_EN_MASK, MT6351_PMIC_DA_QI_VSRAM_PROC_DVS_EN_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_VSLEEP_EN, MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_EN_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_R2R_PDN, MT6351_PMIC_BUCK_VSRAM_PROC_R2R_PDN_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_R2R_PDN_MASK, MT6351_PMIC_BUCK_VSRAM_PROC_R2R_PDN_SHIFT}, + {PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL, MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL_ADDR, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL_MASK, + MT6351_PMIC_BUCK_VSRAM_PROC_VSLEEP_SEL_SHIFT}, + {PMIC_DA_NI_VSRAM_PROC_R2R_PDN, MT6351_PMIC_DA_NI_VSRAM_PROC_R2R_PDN_ADDR, + MT6351_PMIC_DA_NI_VSRAM_PROC_R2R_PDN_MASK, MT6351_PMIC_DA_NI_VSRAM_PROC_R2R_PDN_SHIFT}, + {PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL, MT6351_PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_ADDR, + MT6351_PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_MASK, + MT6351_PMIC_DA_NI_VSRAM_PROC_VSLEEP_SEL_SHIFT}, + {PMIC_BUCK_K_RST_DONE, MT6351_PMIC_BUCK_K_RST_DONE_ADDR, + MT6351_PMIC_BUCK_K_RST_DONE_MASK, MT6351_PMIC_BUCK_K_RST_DONE_SHIFT}, + {PMIC_BUCK_K_MAP_SEL, MT6351_PMIC_BUCK_K_MAP_SEL_ADDR, + MT6351_PMIC_BUCK_K_MAP_SEL_MASK, MT6351_PMIC_BUCK_K_MAP_SEL_SHIFT}, + {PMIC_BUCK_K_ONCE_EN, MT6351_PMIC_BUCK_K_ONCE_EN_ADDR, + MT6351_PMIC_BUCK_K_ONCE_EN_MASK, MT6351_PMIC_BUCK_K_ONCE_EN_SHIFT}, + {PMIC_BUCK_K_ONCE, MT6351_PMIC_BUCK_K_ONCE_ADDR, MT6351_PMIC_BUCK_K_ONCE_MASK, + MT6351_PMIC_BUCK_K_ONCE_SHIFT}, + {PMIC_BUCK_K_START_MANUAL, MT6351_PMIC_BUCK_K_START_MANUAL_ADDR, + MT6351_PMIC_BUCK_K_START_MANUAL_MASK, MT6351_PMIC_BUCK_K_START_MANUAL_SHIFT}, + {PMIC_BUCK_K_SRC_SEL, MT6351_PMIC_BUCK_K_SRC_SEL_ADDR, + MT6351_PMIC_BUCK_K_SRC_SEL_MASK, MT6351_PMIC_BUCK_K_SRC_SEL_SHIFT}, + {PMIC_BUCK_K_AUTO_EN, MT6351_PMIC_BUCK_K_AUTO_EN_ADDR, + MT6351_PMIC_BUCK_K_AUTO_EN_MASK, MT6351_PMIC_BUCK_K_AUTO_EN_SHIFT}, + {PMIC_BUCK_K_INV, MT6351_PMIC_BUCK_K_INV_ADDR, MT6351_PMIC_BUCK_K_INV_MASK, + MT6351_PMIC_BUCK_K_INV_SHIFT}, + {PMIC_BUCK_K_CONTROL_SMPS, MT6351_PMIC_BUCK_K_CONTROL_SMPS_ADDR, + MT6351_PMIC_BUCK_K_CONTROL_SMPS_MASK, MT6351_PMIC_BUCK_K_CONTROL_SMPS_SHIFT}, + {PMIC_K_RESULT, MT6351_PMIC_K_RESULT_ADDR, MT6351_PMIC_K_RESULT_MASK, + MT6351_PMIC_K_RESULT_SHIFT}, + {PMIC_K_DONE, MT6351_PMIC_K_DONE_ADDR, MT6351_PMIC_K_DONE_MASK, + MT6351_PMIC_K_DONE_SHIFT}, + {PMIC_K_CONTROL, MT6351_PMIC_K_CONTROL_ADDR, MT6351_PMIC_K_CONTROL_MASK, + MT6351_PMIC_K_CONTROL_SHIFT}, + {PMIC_DA_QI_SMPS_OSC_CAL, MT6351_PMIC_DA_QI_SMPS_OSC_CAL_ADDR, + MT6351_PMIC_DA_QI_SMPS_OSC_CAL_MASK, MT6351_PMIC_DA_QI_SMPS_OSC_CAL_SHIFT}, + {PMIC_BUCK_K_BUCK_CK_CNT, MT6351_PMIC_BUCK_K_BUCK_CK_CNT_ADDR, + MT6351_PMIC_BUCK_K_BUCK_CK_CNT_MASK, MT6351_PMIC_BUCK_K_BUCK_CK_CNT_SHIFT}, + {PMIC_WDTDBG_CLR, MT6351_PMIC_WDTDBG_CLR_ADDR, MT6351_PMIC_WDTDBG_CLR_MASK, + MT6351_PMIC_WDTDBG_CLR_SHIFT}, + {PMIC_WDTDBG_CON0_RSV0, MT6351_PMIC_WDTDBG_CON0_RSV0_ADDR, + MT6351_PMIC_WDTDBG_CON0_RSV0_MASK, MT6351_PMIC_WDTDBG_CON0_RSV0_SHIFT}, + {PMIC_VGPU_VOSEL_WDTDBG, MT6351_PMIC_VGPU_VOSEL_WDTDBG_ADDR, + MT6351_PMIC_VGPU_VOSEL_WDTDBG_MASK, MT6351_PMIC_VGPU_VOSEL_WDTDBG_SHIFT}, + {PMIC_VCORE_VOSEL_WDTDBG, MT6351_PMIC_VCORE_VOSEL_WDTDBG_ADDR, + MT6351_PMIC_VCORE_VOSEL_WDTDBG_MASK, MT6351_PMIC_VCORE_VOSEL_WDTDBG_SHIFT}, + {PMIC_VMD1_VOSEL_WDTDBG, MT6351_PMIC_VMD1_VOSEL_WDTDBG_ADDR, + MT6351_PMIC_VMD1_VOSEL_WDTDBG_MASK, MT6351_PMIC_VMD1_VOSEL_WDTDBG_SHIFT}, + {PMIC_VMODEM_VOSEL_WDTDBG, MT6351_PMIC_VMODEM_VOSEL_WDTDBG_ADDR, + MT6351_PMIC_VMODEM_VOSEL_WDTDBG_MASK, MT6351_PMIC_VMODEM_VOSEL_WDTDBG_SHIFT}, + {PMIC_VSRAM_PROC_VOSEL_WDTDBG, MT6351_PMIC_VSRAM_PROC_VOSEL_WDTDBG_ADDR, + MT6351_PMIC_VSRAM_PROC_VOSEL_WDTDBG_MASK, MT6351_PMIC_VSRAM_PROC_VOSEL_WDTDBG_SHIFT}, + {PMIC_VSRAM_MD_VOSEL_WDTDBG, MT6351_PMIC_VSRAM_MD_VOSEL_WDTDBG_ADDR, + MT6351_PMIC_VSRAM_MD_VOSEL_WDTDBG_MASK, MT6351_PMIC_VSRAM_MD_VOSEL_WDTDBG_SHIFT}, + {PMIC_RG_AUDZCDENABLE, MT6351_PMIC_RG_AUDZCDENABLE_ADDR, + MT6351_PMIC_RG_AUDZCDENABLE_MASK, MT6351_PMIC_RG_AUDZCDENABLE_SHIFT}, + {PMIC_RG_AUDZCDGAINSTEPTIME, MT6351_PMIC_RG_AUDZCDGAINSTEPTIME_ADDR, + MT6351_PMIC_RG_AUDZCDGAINSTEPTIME_MASK, MT6351_PMIC_RG_AUDZCDGAINSTEPTIME_SHIFT}, + {PMIC_RG_AUDZCDGAINSTEPSIZE, MT6351_PMIC_RG_AUDZCDGAINSTEPSIZE_ADDR, + MT6351_PMIC_RG_AUDZCDGAINSTEPSIZE_MASK, MT6351_PMIC_RG_AUDZCDGAINSTEPSIZE_SHIFT}, + {PMIC_RG_AUDZCDTIMEOUTMODESEL, MT6351_PMIC_RG_AUDZCDTIMEOUTMODESEL_ADDR, + MT6351_PMIC_RG_AUDZCDTIMEOUTMODESEL_MASK, MT6351_PMIC_RG_AUDZCDTIMEOUTMODESEL_SHIFT}, + {PMIC_RG_AUDZCDCLKSEL_VAUDP15, MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP15_ADDR, + MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP15_MASK, MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP15_SHIFT}, + {PMIC_RG_AUDZCDMUXSEL_VAUDP15, MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP15_ADDR, + MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP15_MASK, MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP15_SHIFT}, + {PMIC_RG_AUDLOLGAIN, MT6351_PMIC_RG_AUDLOLGAIN_ADDR, + MT6351_PMIC_RG_AUDLOLGAIN_MASK, MT6351_PMIC_RG_AUDLOLGAIN_SHIFT}, + {PMIC_RG_AUDLORGAIN, MT6351_PMIC_RG_AUDLORGAIN_ADDR, + MT6351_PMIC_RG_AUDLORGAIN_MASK, MT6351_PMIC_RG_AUDLORGAIN_SHIFT}, + {PMIC_RG_AUDHPLGAIN, MT6351_PMIC_RG_AUDHPLGAIN_ADDR, + MT6351_PMIC_RG_AUDHPLGAIN_MASK, MT6351_PMIC_RG_AUDHPLGAIN_SHIFT}, + {PMIC_RG_AUDHPRGAIN, MT6351_PMIC_RG_AUDHPRGAIN_ADDR, + MT6351_PMIC_RG_AUDHPRGAIN_MASK, MT6351_PMIC_RG_AUDHPRGAIN_SHIFT}, + {PMIC_RG_AUDHSGAIN, MT6351_PMIC_RG_AUDHSGAIN_ADDR, MT6351_PMIC_RG_AUDHSGAIN_MASK, + MT6351_PMIC_RG_AUDHSGAIN_SHIFT}, + {PMIC_RG_AUDIVLGAIN, MT6351_PMIC_RG_AUDIVLGAIN_ADDR, + MT6351_PMIC_RG_AUDIVLGAIN_MASK, MT6351_PMIC_RG_AUDIVLGAIN_SHIFT}, + {PMIC_RG_AUDIVRGAIN, MT6351_PMIC_RG_AUDIVRGAIN_ADDR, + MT6351_PMIC_RG_AUDIVRGAIN_MASK, MT6351_PMIC_RG_AUDIVRGAIN_SHIFT}, + {PMIC_RG_AUDINTGAIN1, MT6351_PMIC_RG_AUDINTGAIN1_ADDR, + MT6351_PMIC_RG_AUDINTGAIN1_MASK, MT6351_PMIC_RG_AUDINTGAIN1_SHIFT}, + {PMIC_RG_AUDINTGAIN2, MT6351_PMIC_RG_AUDINTGAIN2_ADDR, + MT6351_PMIC_RG_AUDINTGAIN2_MASK, MT6351_PMIC_RG_AUDINTGAIN2_SHIFT}, + {PMIC_RG_A_TRIM_EN, MT6351_PMIC_RG_A_TRIM_EN_ADDR, MT6351_PMIC_RG_A_TRIM_EN_MASK, + MT6351_PMIC_RG_A_TRIM_EN_SHIFT}, + {PMIC_RG_A_TRIM_SEL, MT6351_PMIC_RG_A_TRIM_SEL_ADDR, + MT6351_PMIC_RG_A_TRIM_SEL_MASK, MT6351_PMIC_RG_A_TRIM_SEL_SHIFT}, + {PMIC_RG_A_ISINKS_RSV, MT6351_PMIC_RG_A_ISINKS_RSV_ADDR, + MT6351_PMIC_RG_A_ISINKS_RSV_MASK, MT6351_PMIC_RG_A_ISINKS_RSV_SHIFT}, + {PMIC_RG_B_TRIM_EN, MT6351_PMIC_RG_B_TRIM_EN_ADDR, MT6351_PMIC_RG_B_TRIM_EN_MASK, + MT6351_PMIC_RG_B_TRIM_EN_SHIFT}, + {PMIC_RG_B_TRIM_SEL, MT6351_PMIC_RG_B_TRIM_SEL_ADDR, + MT6351_PMIC_RG_B_TRIM_SEL_MASK, MT6351_PMIC_RG_B_TRIM_SEL_SHIFT}, + {PMIC_RG_B_ISINKS_RSV, MT6351_PMIC_RG_B_ISINKS_RSV_ADDR, + MT6351_PMIC_RG_B_ISINKS_RSV_MASK, MT6351_PMIC_RG_B_ISINKS_RSV_SHIFT}, + {PMIC_ISINK_DIM0_FSEL, MT6351_PMIC_ISINK_DIM0_FSEL_ADDR, + MT6351_PMIC_ISINK_DIM0_FSEL_MASK, MT6351_PMIC_ISINK_DIM0_FSEL_SHIFT}, + {PMIC_ISINK0_RSV1, MT6351_PMIC_ISINK0_RSV1_ADDR, MT6351_PMIC_ISINK0_RSV1_MASK, + MT6351_PMIC_ISINK0_RSV1_SHIFT}, + {PMIC_ISINK0_RSV0, MT6351_PMIC_ISINK0_RSV0_ADDR, MT6351_PMIC_ISINK0_RSV0_MASK, + MT6351_PMIC_ISINK0_RSV0_SHIFT}, + {PMIC_ISINK_DIM0_DUTY, MT6351_PMIC_ISINK_DIM0_DUTY_ADDR, + MT6351_PMIC_ISINK_DIM0_DUTY_MASK, MT6351_PMIC_ISINK_DIM0_DUTY_SHIFT}, + {PMIC_ISINK_CH0_STEP, MT6351_PMIC_ISINK_CH0_STEP_ADDR, + MT6351_PMIC_ISINK_CH0_STEP_MASK, MT6351_PMIC_ISINK_CH0_STEP_SHIFT}, + {PMIC_ISINK_BREATH0_TF2_SEL, MT6351_PMIC_ISINK_BREATH0_TF2_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH0_TF2_SEL_MASK, MT6351_PMIC_ISINK_BREATH0_TF2_SEL_SHIFT}, + {PMIC_ISINK_BREATH0_TF1_SEL, MT6351_PMIC_ISINK_BREATH0_TF1_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH0_TF1_SEL_MASK, MT6351_PMIC_ISINK_BREATH0_TF1_SEL_SHIFT}, + {PMIC_ISINK_BREATH0_TR2_SEL, MT6351_PMIC_ISINK_BREATH0_TR2_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH0_TR2_SEL_MASK, MT6351_PMIC_ISINK_BREATH0_TR2_SEL_SHIFT}, + {PMIC_ISINK_BREATH0_TR1_SEL, MT6351_PMIC_ISINK_BREATH0_TR1_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH0_TR1_SEL_MASK, MT6351_PMIC_ISINK_BREATH0_TR1_SEL_SHIFT}, + {PMIC_ISINK_BREATH0_TOFF_SEL, MT6351_PMIC_ISINK_BREATH0_TOFF_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH0_TOFF_SEL_MASK, MT6351_PMIC_ISINK_BREATH0_TOFF_SEL_SHIFT}, + {PMIC_ISINK_BREATH0_TON_SEL, MT6351_PMIC_ISINK_BREATH0_TON_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH0_TON_SEL_MASK, MT6351_PMIC_ISINK_BREATH0_TON_SEL_SHIFT}, + {PMIC_ISINK_DIM1_FSEL, MT6351_PMIC_ISINK_DIM1_FSEL_ADDR, + MT6351_PMIC_ISINK_DIM1_FSEL_MASK, MT6351_PMIC_ISINK_DIM1_FSEL_SHIFT}, + {PMIC_ISINK1_RSV1, MT6351_PMIC_ISINK1_RSV1_ADDR, MT6351_PMIC_ISINK1_RSV1_MASK, + MT6351_PMIC_ISINK1_RSV1_SHIFT}, + {PMIC_ISINK1_RSV0, MT6351_PMIC_ISINK1_RSV0_ADDR, MT6351_PMIC_ISINK1_RSV0_MASK, + MT6351_PMIC_ISINK1_RSV0_SHIFT}, + {PMIC_ISINK_DIM1_DUTY, MT6351_PMIC_ISINK_DIM1_DUTY_ADDR, + MT6351_PMIC_ISINK_DIM1_DUTY_MASK, MT6351_PMIC_ISINK_DIM1_DUTY_SHIFT}, + {PMIC_ISINK_CH1_STEP, MT6351_PMIC_ISINK_CH1_STEP_ADDR, + MT6351_PMIC_ISINK_CH1_STEP_MASK, MT6351_PMIC_ISINK_CH1_STEP_SHIFT}, + {PMIC_ISINK_BREATH1_TF2_SEL, MT6351_PMIC_ISINK_BREATH1_TF2_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH1_TF2_SEL_MASK, MT6351_PMIC_ISINK_BREATH1_TF2_SEL_SHIFT}, + {PMIC_ISINK_BREATH1_TF1_SEL, MT6351_PMIC_ISINK_BREATH1_TF1_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH1_TF1_SEL_MASK, MT6351_PMIC_ISINK_BREATH1_TF1_SEL_SHIFT}, + {PMIC_ISINK_BREATH1_TR2_SEL, MT6351_PMIC_ISINK_BREATH1_TR2_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH1_TR2_SEL_MASK, MT6351_PMIC_ISINK_BREATH1_TR2_SEL_SHIFT}, + {PMIC_ISINK_BREATH1_TR1_SEL, MT6351_PMIC_ISINK_BREATH1_TR1_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH1_TR1_SEL_MASK, MT6351_PMIC_ISINK_BREATH1_TR1_SEL_SHIFT}, + {PMIC_ISINK_BREATH1_TOFF_SEL, MT6351_PMIC_ISINK_BREATH1_TOFF_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH1_TOFF_SEL_MASK, MT6351_PMIC_ISINK_BREATH1_TOFF_SEL_SHIFT}, + {PMIC_ISINK_BREATH1_TON_SEL, MT6351_PMIC_ISINK_BREATH1_TON_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH1_TON_SEL_MASK, MT6351_PMIC_ISINK_BREATH1_TON_SEL_SHIFT}, + {PMIC_ISINK_DIM4_FSEL, MT6351_PMIC_ISINK_DIM4_FSEL_ADDR, + MT6351_PMIC_ISINK_DIM4_FSEL_MASK, MT6351_PMIC_ISINK_DIM4_FSEL_SHIFT}, + {PMIC_ISINK4_RSV1, MT6351_PMIC_ISINK4_RSV1_ADDR, MT6351_PMIC_ISINK4_RSV1_MASK, + MT6351_PMIC_ISINK4_RSV1_SHIFT}, + {PMIC_ISINK4_RSV0, MT6351_PMIC_ISINK4_RSV0_ADDR, MT6351_PMIC_ISINK4_RSV0_MASK, + MT6351_PMIC_ISINK4_RSV0_SHIFT}, + {PMIC_ISINK_DIM4_DUTY, MT6351_PMIC_ISINK_DIM4_DUTY_ADDR, + MT6351_PMIC_ISINK_DIM4_DUTY_MASK, MT6351_PMIC_ISINK_DIM4_DUTY_SHIFT}, + {PMIC_ISINK_CH4_STEP, MT6351_PMIC_ISINK_CH4_STEP_ADDR, + MT6351_PMIC_ISINK_CH4_STEP_MASK, MT6351_PMIC_ISINK_CH4_STEP_SHIFT}, + {PMIC_ISINK_BREATH4_TF2_SEL, MT6351_PMIC_ISINK_BREATH4_TF2_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH4_TF2_SEL_MASK, MT6351_PMIC_ISINK_BREATH4_TF2_SEL_SHIFT}, + {PMIC_ISINK_BREATH4_TF1_SEL, MT6351_PMIC_ISINK_BREATH4_TF1_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH4_TF1_SEL_MASK, MT6351_PMIC_ISINK_BREATH4_TF1_SEL_SHIFT}, + {PMIC_ISINK_BREATH4_TR2_SEL, MT6351_PMIC_ISINK_BREATH4_TR2_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH4_TR2_SEL_MASK, MT6351_PMIC_ISINK_BREATH4_TR2_SEL_SHIFT}, + {PMIC_ISINK_BREATH4_TR1_SEL, MT6351_PMIC_ISINK_BREATH4_TR1_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH4_TR1_SEL_MASK, MT6351_PMIC_ISINK_BREATH4_TR1_SEL_SHIFT}, + {PMIC_ISINK_BREATH4_TOFF_SEL, MT6351_PMIC_ISINK_BREATH4_TOFF_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH4_TOFF_SEL_MASK, MT6351_PMIC_ISINK_BREATH4_TOFF_SEL_SHIFT}, + {PMIC_ISINK_BREATH4_TON_SEL, MT6351_PMIC_ISINK_BREATH4_TON_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH4_TON_SEL_MASK, MT6351_PMIC_ISINK_BREATH4_TON_SEL_SHIFT}, + {PMIC_ISINK_DIM5_FSEL, MT6351_PMIC_ISINK_DIM5_FSEL_ADDR, + MT6351_PMIC_ISINK_DIM5_FSEL_MASK, MT6351_PMIC_ISINK_DIM5_FSEL_SHIFT}, + {PMIC_ISINK5_RSV1, MT6351_PMIC_ISINK5_RSV1_ADDR, MT6351_PMIC_ISINK5_RSV1_MASK, + MT6351_PMIC_ISINK5_RSV1_SHIFT}, + {PMIC_ISINK5_RSV0, MT6351_PMIC_ISINK5_RSV0_ADDR, MT6351_PMIC_ISINK5_RSV0_MASK, + MT6351_PMIC_ISINK5_RSV0_SHIFT}, + {PMIC_ISINK_DIM5_DUTY, MT6351_PMIC_ISINK_DIM5_DUTY_ADDR, + MT6351_PMIC_ISINK_DIM5_DUTY_MASK, MT6351_PMIC_ISINK_DIM5_DUTY_SHIFT}, + {PMIC_ISINK_CH5_STEP, MT6351_PMIC_ISINK_CH5_STEP_ADDR, + MT6351_PMIC_ISINK_CH5_STEP_MASK, MT6351_PMIC_ISINK_CH5_STEP_SHIFT}, + {PMIC_ISINK_BREATH5_TF2_SEL, MT6351_PMIC_ISINK_BREATH5_TF2_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH5_TF2_SEL_MASK, MT6351_PMIC_ISINK_BREATH5_TF2_SEL_SHIFT}, + {PMIC_ISINK_BREATH5_TF1_SEL, MT6351_PMIC_ISINK_BREATH5_TF1_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH5_TF1_SEL_MASK, MT6351_PMIC_ISINK_BREATH5_TF1_SEL_SHIFT}, + {PMIC_ISINK_BREATH5_TR2_SEL, MT6351_PMIC_ISINK_BREATH5_TR2_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH5_TR2_SEL_MASK, MT6351_PMIC_ISINK_BREATH5_TR2_SEL_SHIFT}, + {PMIC_ISINK_BREATH5_TR1_SEL, MT6351_PMIC_ISINK_BREATH5_TR1_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH5_TR1_SEL_MASK, MT6351_PMIC_ISINK_BREATH5_TR1_SEL_SHIFT}, + {PMIC_ISINK_BREATH5_TOFF_SEL, MT6351_PMIC_ISINK_BREATH5_TOFF_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH5_TOFF_SEL_MASK, MT6351_PMIC_ISINK_BREATH5_TOFF_SEL_SHIFT}, + {PMIC_ISINK_BREATH5_TON_SEL, MT6351_PMIC_ISINK_BREATH5_TON_SEL_ADDR, + MT6351_PMIC_ISINK_BREATH5_TON_SEL_MASK, MT6351_PMIC_ISINK_BREATH5_TON_SEL_SHIFT}, + {PMIC_AD_NI_B_ISINK1_STATUS, MT6351_PMIC_AD_NI_B_ISINK1_STATUS_ADDR, + MT6351_PMIC_AD_NI_B_ISINK1_STATUS_MASK, MT6351_PMIC_AD_NI_B_ISINK1_STATUS_SHIFT}, + {PMIC_AD_NI_B_ISINK0_STATUS, MT6351_PMIC_AD_NI_B_ISINK0_STATUS_ADDR, + MT6351_PMIC_AD_NI_B_ISINK0_STATUS_MASK, MT6351_PMIC_AD_NI_B_ISINK0_STATUS_SHIFT}, + {PMIC_AD_NI_A_ISINK1_STATUS, MT6351_PMIC_AD_NI_A_ISINK1_STATUS_ADDR, + MT6351_PMIC_AD_NI_A_ISINK1_STATUS_MASK, MT6351_PMIC_AD_NI_A_ISINK1_STATUS_SHIFT}, + {PMIC_AD_NI_A_ISINK0_STATUS, MT6351_PMIC_AD_NI_A_ISINK0_STATUS_ADDR, + MT6351_PMIC_AD_NI_A_ISINK0_STATUS_MASK, MT6351_PMIC_AD_NI_A_ISINK0_STATUS_SHIFT}, + {PMIC_ISINK_PHASE0_DLY_EN, MT6351_PMIC_ISINK_PHASE0_DLY_EN_ADDR, + MT6351_PMIC_ISINK_PHASE0_DLY_EN_MASK, MT6351_PMIC_ISINK_PHASE0_DLY_EN_SHIFT}, + {PMIC_ISINK_PHASE1_DLY_EN, MT6351_PMIC_ISINK_PHASE1_DLY_EN_ADDR, + MT6351_PMIC_ISINK_PHASE1_DLY_EN_MASK, MT6351_PMIC_ISINK_PHASE1_DLY_EN_SHIFT}, + {PMIC_ISINK_PHASE4_DLY_EN, MT6351_PMIC_ISINK_PHASE4_DLY_EN_ADDR, + MT6351_PMIC_ISINK_PHASE4_DLY_EN_MASK, MT6351_PMIC_ISINK_PHASE4_DLY_EN_SHIFT}, + {PMIC_ISINK_PHASE5_DLY_EN, MT6351_PMIC_ISINK_PHASE5_DLY_EN_ADDR, + MT6351_PMIC_ISINK_PHASE5_DLY_EN_MASK, MT6351_PMIC_ISINK_PHASE5_DLY_EN_SHIFT}, + {PMIC_ISINK_PHASE_DLY_TC, MT6351_PMIC_ISINK_PHASE_DLY_TC_ADDR, + MT6351_PMIC_ISINK_PHASE_DLY_TC_MASK, MT6351_PMIC_ISINK_PHASE_DLY_TC_SHIFT}, + {PMIC_ISINK_CHOP0_SW, MT6351_PMIC_ISINK_CHOP0_SW_ADDR, + MT6351_PMIC_ISINK_CHOP0_SW_MASK, MT6351_PMIC_ISINK_CHOP0_SW_SHIFT}, + {PMIC_ISINK_CHOP1_SW, MT6351_PMIC_ISINK_CHOP1_SW_ADDR, + MT6351_PMIC_ISINK_CHOP1_SW_MASK, MT6351_PMIC_ISINK_CHOP1_SW_SHIFT}, + {PMIC_ISINK_CHOP4_SW, MT6351_PMIC_ISINK_CHOP4_SW_ADDR, + MT6351_PMIC_ISINK_CHOP4_SW_MASK, MT6351_PMIC_ISINK_CHOP4_SW_SHIFT}, + {PMIC_ISINK_CHOP5_SW, MT6351_PMIC_ISINK_CHOP5_SW_ADDR, + MT6351_PMIC_ISINK_CHOP5_SW_MASK, MT6351_PMIC_ISINK_CHOP5_SW_SHIFT}, + {PMIC_ISINK_SFSTR5_EN, MT6351_PMIC_ISINK_SFSTR5_EN_ADDR, + MT6351_PMIC_ISINK_SFSTR5_EN_MASK, MT6351_PMIC_ISINK_SFSTR5_EN_SHIFT}, + {PMIC_ISINK_SFSTR5_TC, MT6351_PMIC_ISINK_SFSTR5_TC_ADDR, + MT6351_PMIC_ISINK_SFSTR5_TC_MASK, MT6351_PMIC_ISINK_SFSTR5_TC_SHIFT}, + {PMIC_ISINK_SFSTR4_EN, MT6351_PMIC_ISINK_SFSTR4_EN_ADDR, + MT6351_PMIC_ISINK_SFSTR4_EN_MASK, MT6351_PMIC_ISINK_SFSTR4_EN_SHIFT}, + {PMIC_ISINK_SFSTR4_TC, MT6351_PMIC_ISINK_SFSTR4_TC_ADDR, + MT6351_PMIC_ISINK_SFSTR4_TC_MASK, MT6351_PMIC_ISINK_SFSTR4_TC_SHIFT}, + {PMIC_ISINK_SFSTR1_EN, MT6351_PMIC_ISINK_SFSTR1_EN_ADDR, + MT6351_PMIC_ISINK_SFSTR1_EN_MASK, MT6351_PMIC_ISINK_SFSTR1_EN_SHIFT}, + {PMIC_ISINK_SFSTR1_TC, MT6351_PMIC_ISINK_SFSTR1_TC_ADDR, + MT6351_PMIC_ISINK_SFSTR1_TC_MASK, MT6351_PMIC_ISINK_SFSTR1_TC_SHIFT}, + {PMIC_ISINK_SFSTR0_EN, MT6351_PMIC_ISINK_SFSTR0_EN_ADDR, + MT6351_PMIC_ISINK_SFSTR0_EN_MASK, MT6351_PMIC_ISINK_SFSTR0_EN_SHIFT}, + {PMIC_ISINK_SFSTR0_TC, MT6351_PMIC_ISINK_SFSTR0_TC_ADDR, + MT6351_PMIC_ISINK_SFSTR0_TC_MASK, MT6351_PMIC_ISINK_SFSTR0_TC_SHIFT}, + {PMIC_ISINK_CH0_EN, MT6351_PMIC_ISINK_CH0_EN_ADDR, MT6351_PMIC_ISINK_CH0_EN_MASK, + MT6351_PMIC_ISINK_CH0_EN_SHIFT}, + {PMIC_ISINK_CH1_EN, MT6351_PMIC_ISINK_CH1_EN_ADDR, MT6351_PMIC_ISINK_CH1_EN_MASK, + MT6351_PMIC_ISINK_CH1_EN_SHIFT}, + {PMIC_ISINK_CH4_EN, MT6351_PMIC_ISINK_CH4_EN_ADDR, MT6351_PMIC_ISINK_CH4_EN_MASK, + MT6351_PMIC_ISINK_CH4_EN_SHIFT}, + {PMIC_ISINK_CH5_EN, MT6351_PMIC_ISINK_CH5_EN_ADDR, MT6351_PMIC_ISINK_CH5_EN_MASK, + MT6351_PMIC_ISINK_CH5_EN_SHIFT}, + {PMIC_ISINK_CHOP0_EN, MT6351_PMIC_ISINK_CHOP0_EN_ADDR, + MT6351_PMIC_ISINK_CHOP0_EN_MASK, MT6351_PMIC_ISINK_CHOP0_EN_SHIFT}, + {PMIC_ISINK_CHOP1_EN, MT6351_PMIC_ISINK_CHOP1_EN_ADDR, + MT6351_PMIC_ISINK_CHOP1_EN_MASK, MT6351_PMIC_ISINK_CHOP1_EN_SHIFT}, + {PMIC_ISINK_CHOP4_EN, MT6351_PMIC_ISINK_CHOP4_EN_ADDR, + MT6351_PMIC_ISINK_CHOP4_EN_MASK, MT6351_PMIC_ISINK_CHOP4_EN_SHIFT}, + {PMIC_ISINK_CHOP5_EN, MT6351_PMIC_ISINK_CHOP5_EN_ADDR, + MT6351_PMIC_ISINK_CHOP5_EN_MASK, MT6351_PMIC_ISINK_CHOP5_EN_SHIFT}, + {PMIC_ISINK_CH0_BIAS_EN, MT6351_PMIC_ISINK_CH0_BIAS_EN_ADDR, + MT6351_PMIC_ISINK_CH0_BIAS_EN_MASK, MT6351_PMIC_ISINK_CH0_BIAS_EN_SHIFT}, + {PMIC_ISINK_CH1_BIAS_EN, MT6351_PMIC_ISINK_CH1_BIAS_EN_ADDR, + MT6351_PMIC_ISINK_CH1_BIAS_EN_MASK, MT6351_PMIC_ISINK_CH1_BIAS_EN_SHIFT}, + {PMIC_ISINK_CH4_BIAS_EN, MT6351_PMIC_ISINK_CH4_BIAS_EN_ADDR, + MT6351_PMIC_ISINK_CH4_BIAS_EN_MASK, MT6351_PMIC_ISINK_CH4_BIAS_EN_SHIFT}, + {PMIC_ISINK_CH5_BIAS_EN, MT6351_PMIC_ISINK_CH5_BIAS_EN_ADDR, + MT6351_PMIC_ISINK_CH5_BIAS_EN_MASK, MT6351_PMIC_ISINK_CH5_BIAS_EN_SHIFT}, + {PMIC_ISINK_RSV, MT6351_PMIC_ISINK_RSV_ADDR, MT6351_PMIC_ISINK_RSV_MASK, + MT6351_PMIC_ISINK_RSV_SHIFT}, + {PMIC_ISINK_CH5_MODE, MT6351_PMIC_ISINK_CH5_MODE_ADDR, + MT6351_PMIC_ISINK_CH5_MODE_MASK, MT6351_PMIC_ISINK_CH5_MODE_SHIFT}, + {PMIC_ISINK_CH4_MODE, MT6351_PMIC_ISINK_CH4_MODE_ADDR, + MT6351_PMIC_ISINK_CH4_MODE_MASK, MT6351_PMIC_ISINK_CH4_MODE_SHIFT}, + {PMIC_ISINK_CH1_MODE, MT6351_PMIC_ISINK_CH1_MODE_ADDR, + MT6351_PMIC_ISINK_CH1_MODE_MASK, MT6351_PMIC_ISINK_CH1_MODE_SHIFT}, + {PMIC_ISINK_CH0_MODE, MT6351_PMIC_ISINK_CH0_MODE_ADDR, + MT6351_PMIC_ISINK_CH0_MODE_MASK, MT6351_PMIC_ISINK_CH0_MODE_SHIFT}, + {PMIC_DA_QI_A_ISINKS_CH0_STEP, MT6351_PMIC_DA_QI_A_ISINKS_CH0_STEP_ADDR, + MT6351_PMIC_DA_QI_A_ISINKS_CH0_STEP_MASK, MT6351_PMIC_DA_QI_A_ISINKS_CH0_STEP_SHIFT}, + {PMIC_DA_QI_A_ISINKS_CH1_STEP, MT6351_PMIC_DA_QI_A_ISINKS_CH1_STEP_ADDR, + MT6351_PMIC_DA_QI_A_ISINKS_CH1_STEP_MASK, MT6351_PMIC_DA_QI_A_ISINKS_CH1_STEP_SHIFT}, + {PMIC_DA_QI_B_ISINKS_CH0_STEP, MT6351_PMIC_DA_QI_B_ISINKS_CH0_STEP_ADDR, + MT6351_PMIC_DA_QI_B_ISINKS_CH0_STEP_MASK, MT6351_PMIC_DA_QI_B_ISINKS_CH0_STEP_SHIFT}, + {PMIC_DA_QI_B_ISINKS_CH1_STEP, MT6351_PMIC_DA_QI_B_ISINKS_CH1_STEP_ADDR, + MT6351_PMIC_DA_QI_B_ISINKS_CH1_STEP_MASK, MT6351_PMIC_DA_QI_B_ISINKS_CH1_STEP_SHIFT}, + {PMIC_ISINK2_RSV1, MT6351_PMIC_ISINK2_RSV1_ADDR, MT6351_PMIC_ISINK2_RSV1_MASK, + MT6351_PMIC_ISINK2_RSV1_SHIFT}, + {PMIC_ISINK2_RSV0, MT6351_PMIC_ISINK2_RSV0_ADDR, MT6351_PMIC_ISINK2_RSV0_MASK, + MT6351_PMIC_ISINK2_RSV0_SHIFT}, + {PMIC_ISINK_CH2_STEP, MT6351_PMIC_ISINK_CH2_STEP_ADDR, + MT6351_PMIC_ISINK_CH2_STEP_MASK, MT6351_PMIC_ISINK_CH2_STEP_SHIFT}, + {PMIC_ISINK3_RSV1, MT6351_PMIC_ISINK3_RSV1_ADDR, MT6351_PMIC_ISINK3_RSV1_MASK, + MT6351_PMIC_ISINK3_RSV1_SHIFT}, + {PMIC_ISINK3_RSV0, MT6351_PMIC_ISINK3_RSV0_ADDR, MT6351_PMIC_ISINK3_RSV0_MASK, + MT6351_PMIC_ISINK3_RSV0_SHIFT}, + {PMIC_ISINK_CH3_STEP, MT6351_PMIC_ISINK_CH3_STEP_ADDR, + MT6351_PMIC_ISINK_CH3_STEP_MASK, MT6351_PMIC_ISINK_CH3_STEP_SHIFT}, + {PMIC_ISINK6_RSV1, MT6351_PMIC_ISINK6_RSV1_ADDR, MT6351_PMIC_ISINK6_RSV1_MASK, + MT6351_PMIC_ISINK6_RSV1_SHIFT}, + {PMIC_ISINK6_RSV0, MT6351_PMIC_ISINK6_RSV0_ADDR, MT6351_PMIC_ISINK6_RSV0_MASK, + MT6351_PMIC_ISINK6_RSV0_SHIFT}, + {PMIC_ISINK_CH6_STEP, MT6351_PMIC_ISINK_CH6_STEP_ADDR, + MT6351_PMIC_ISINK_CH6_STEP_MASK, MT6351_PMIC_ISINK_CH6_STEP_SHIFT}, + {PMIC_ISINK7_RSV1, MT6351_PMIC_ISINK7_RSV1_ADDR, MT6351_PMIC_ISINK7_RSV1_MASK, + MT6351_PMIC_ISINK7_RSV1_SHIFT}, + {PMIC_ISINK7_RSV0, MT6351_PMIC_ISINK7_RSV0_ADDR, MT6351_PMIC_ISINK7_RSV0_MASK, + MT6351_PMIC_ISINK7_RSV0_SHIFT}, + {PMIC_ISINK_CH7_STEP, MT6351_PMIC_ISINK_CH7_STEP_ADDR, + MT6351_PMIC_ISINK_CH7_STEP_MASK, MT6351_PMIC_ISINK_CH7_STEP_SHIFT}, + {PMIC_AD_NI_B_ISINK3_STATUS, MT6351_PMIC_AD_NI_B_ISINK3_STATUS_ADDR, + MT6351_PMIC_AD_NI_B_ISINK3_STATUS_MASK, MT6351_PMIC_AD_NI_B_ISINK3_STATUS_SHIFT}, + {PMIC_AD_NI_B_ISINK2_STATUS, MT6351_PMIC_AD_NI_B_ISINK2_STATUS_ADDR, + MT6351_PMIC_AD_NI_B_ISINK2_STATUS_MASK, MT6351_PMIC_AD_NI_B_ISINK2_STATUS_SHIFT}, + {PMIC_AD_NI_A_ISINK3_STATUS, MT6351_PMIC_AD_NI_A_ISINK3_STATUS_ADDR, + MT6351_PMIC_AD_NI_A_ISINK3_STATUS_MASK, MT6351_PMIC_AD_NI_A_ISINK3_STATUS_SHIFT}, + {PMIC_AD_NI_A_ISINK2_STATUS, MT6351_PMIC_AD_NI_A_ISINK2_STATUS_ADDR, + MT6351_PMIC_AD_NI_A_ISINK2_STATUS_MASK, MT6351_PMIC_AD_NI_A_ISINK2_STATUS_SHIFT}, + {PMIC_ISINK_CHOP7_SW, MT6351_PMIC_ISINK_CHOP7_SW_ADDR, + MT6351_PMIC_ISINK_CHOP7_SW_MASK, MT6351_PMIC_ISINK_CHOP7_SW_SHIFT}, + {PMIC_ISINK_CHOP6_SW, MT6351_PMIC_ISINK_CHOP6_SW_ADDR, + MT6351_PMIC_ISINK_CHOP6_SW_MASK, MT6351_PMIC_ISINK_CHOP6_SW_SHIFT}, + {PMIC_ISINK_CHOP3_SW, MT6351_PMIC_ISINK_CHOP3_SW_ADDR, + MT6351_PMIC_ISINK_CHOP3_SW_MASK, MT6351_PMIC_ISINK_CHOP3_SW_SHIFT}, + {PMIC_ISINK_CHOP2_SW, MT6351_PMIC_ISINK_CHOP2_SW_ADDR, + MT6351_PMIC_ISINK_CHOP2_SW_MASK, MT6351_PMIC_ISINK_CHOP2_SW_SHIFT}, + {PMIC_ISINK_CH7_EN, MT6351_PMIC_ISINK_CH7_EN_ADDR, MT6351_PMIC_ISINK_CH7_EN_MASK, + MT6351_PMIC_ISINK_CH7_EN_SHIFT}, + {PMIC_ISINK_CH6_EN, MT6351_PMIC_ISINK_CH6_EN_ADDR, MT6351_PMIC_ISINK_CH6_EN_MASK, + MT6351_PMIC_ISINK_CH6_EN_SHIFT}, + {PMIC_ISINK_CH3_EN, MT6351_PMIC_ISINK_CH3_EN_ADDR, MT6351_PMIC_ISINK_CH3_EN_MASK, + MT6351_PMIC_ISINK_CH3_EN_SHIFT}, + {PMIC_ISINK_CH2_EN, MT6351_PMIC_ISINK_CH2_EN_ADDR, MT6351_PMIC_ISINK_CH2_EN_MASK, + MT6351_PMIC_ISINK_CH2_EN_SHIFT}, + {PMIC_ISINK_CHOP7_EN, MT6351_PMIC_ISINK_CHOP7_EN_ADDR, + MT6351_PMIC_ISINK_CHOP7_EN_MASK, MT6351_PMIC_ISINK_CHOP7_EN_SHIFT}, + {PMIC_ISINK_CHOP6_EN, MT6351_PMIC_ISINK_CHOP6_EN_ADDR, + MT6351_PMIC_ISINK_CHOP6_EN_MASK, MT6351_PMIC_ISINK_CHOP6_EN_SHIFT}, + {PMIC_ISINK_CHOP3_EN, MT6351_PMIC_ISINK_CHOP3_EN_ADDR, + MT6351_PMIC_ISINK_CHOP3_EN_MASK, MT6351_PMIC_ISINK_CHOP3_EN_SHIFT}, + {PMIC_ISINK_CHOP2_EN, MT6351_PMIC_ISINK_CHOP2_EN_ADDR, + MT6351_PMIC_ISINK_CHOP2_EN_MASK, MT6351_PMIC_ISINK_CHOP2_EN_SHIFT}, + {PMIC_ISINK_CH7_BIAS_EN, MT6351_PMIC_ISINK_CH7_BIAS_EN_ADDR, + MT6351_PMIC_ISINK_CH7_BIAS_EN_MASK, MT6351_PMIC_ISINK_CH7_BIAS_EN_SHIFT}, + {PMIC_ISINK_CH6_BIAS_EN, MT6351_PMIC_ISINK_CH6_BIAS_EN_ADDR, + MT6351_PMIC_ISINK_CH6_BIAS_EN_MASK, MT6351_PMIC_ISINK_CH6_BIAS_EN_SHIFT}, + {PMIC_ISINK_CH3_BIAS_EN, MT6351_PMIC_ISINK_CH3_BIAS_EN_ADDR, + MT6351_PMIC_ISINK_CH3_BIAS_EN_MASK, MT6351_PMIC_ISINK_CH3_BIAS_EN_SHIFT}, + {PMIC_ISINK_CH2_BIAS_EN, MT6351_PMIC_ISINK_CH2_BIAS_EN_ADDR, + MT6351_PMIC_ISINK_CH2_BIAS_EN_MASK, MT6351_PMIC_ISINK_CH2_BIAS_EN_SHIFT}, + {PMIC_CHRIND_DIM_FSEL, MT6351_PMIC_CHRIND_DIM_FSEL_ADDR, + MT6351_PMIC_CHRIND_DIM_FSEL_MASK, MT6351_PMIC_CHRIND_DIM_FSEL_SHIFT}, + {PMIC_CHRIND_RSV1, MT6351_PMIC_CHRIND_RSV1_ADDR, MT6351_PMIC_CHRIND_RSV1_MASK, + MT6351_PMIC_CHRIND_RSV1_SHIFT}, + {PMIC_CHRIND_RSV0, MT6351_PMIC_CHRIND_RSV0_ADDR, MT6351_PMIC_CHRIND_RSV0_MASK, + MT6351_PMIC_CHRIND_RSV0_SHIFT}, + {PMIC_CHRIND_DIM_DUTY, MT6351_PMIC_CHRIND_DIM_DUTY_ADDR, + MT6351_PMIC_CHRIND_DIM_DUTY_MASK, MT6351_PMIC_CHRIND_DIM_DUTY_SHIFT}, + {PMIC_CHRIND_STEP, MT6351_PMIC_CHRIND_STEP_ADDR, MT6351_PMIC_CHRIND_STEP_MASK, + MT6351_PMIC_CHRIND_STEP_SHIFT}, + {PMIC_CHRIND_BREATH_TF2_SEL, MT6351_PMIC_CHRIND_BREATH_TF2_SEL_ADDR, + MT6351_PMIC_CHRIND_BREATH_TF2_SEL_MASK, MT6351_PMIC_CHRIND_BREATH_TF2_SEL_SHIFT}, + {PMIC_CHRIND_BREATH_TF1_SEL, MT6351_PMIC_CHRIND_BREATH_TF1_SEL_ADDR, + MT6351_PMIC_CHRIND_BREATH_TF1_SEL_MASK, MT6351_PMIC_CHRIND_BREATH_TF1_SEL_SHIFT}, + {PMIC_CHRIND_BREATH_TR2_SEL, MT6351_PMIC_CHRIND_BREATH_TR2_SEL_ADDR, + MT6351_PMIC_CHRIND_BREATH_TR2_SEL_MASK, MT6351_PMIC_CHRIND_BREATH_TR2_SEL_SHIFT}, + {PMIC_CHRIND_BREATH_TR1_SEL, MT6351_PMIC_CHRIND_BREATH_TR1_SEL_ADDR, + MT6351_PMIC_CHRIND_BREATH_TR1_SEL_MASK, MT6351_PMIC_CHRIND_BREATH_TR1_SEL_SHIFT}, + {PMIC_CHRIND_BREATH_TOFF_SEL, MT6351_PMIC_CHRIND_BREATH_TOFF_SEL_ADDR, + MT6351_PMIC_CHRIND_BREATH_TOFF_SEL_MASK, MT6351_PMIC_CHRIND_BREATH_TOFF_SEL_SHIFT}, + {PMIC_CHRIND_BREATH_TON_SEL, MT6351_PMIC_CHRIND_BREATH_TON_SEL_ADDR, + MT6351_PMIC_CHRIND_BREATH_TON_SEL_MASK, MT6351_PMIC_CHRIND_BREATH_TON_SEL_SHIFT}, + {PMIC_CHRIND_SFSTR_EN, MT6351_PMIC_CHRIND_SFSTR_EN_ADDR, + MT6351_PMIC_CHRIND_SFSTR_EN_MASK, MT6351_PMIC_CHRIND_SFSTR_EN_SHIFT}, + {PMIC_CHRIND_SFSTR_TC, MT6351_PMIC_CHRIND_SFSTR_TC_ADDR, + MT6351_PMIC_CHRIND_SFSTR_TC_MASK, MT6351_PMIC_CHRIND_SFSTR_TC_SHIFT}, + {PMIC_CHRIND_EN_SEL, MT6351_PMIC_CHRIND_EN_SEL_ADDR, + MT6351_PMIC_CHRIND_EN_SEL_MASK, MT6351_PMIC_CHRIND_EN_SEL_SHIFT}, + {PMIC_CHRIND_EN, MT6351_PMIC_CHRIND_EN_ADDR, MT6351_PMIC_CHRIND_EN_MASK, + MT6351_PMIC_CHRIND_EN_SHIFT}, + {PMIC_CHRIND_CHOP_EN, MT6351_PMIC_CHRIND_CHOP_EN_ADDR, + MT6351_PMIC_CHRIND_CHOP_EN_MASK, MT6351_PMIC_CHRIND_CHOP_EN_SHIFT}, + {PMIC_CHRIND_MODE, MT6351_PMIC_CHRIND_MODE_ADDR, MT6351_PMIC_CHRIND_MODE_MASK, + MT6351_PMIC_CHRIND_MODE_SHIFT}, + {PMIC_CHRIND_CHOP_SW, MT6351_PMIC_CHRIND_CHOP_SW_ADDR, + MT6351_PMIC_CHRIND_CHOP_SW_MASK, MT6351_PMIC_CHRIND_CHOP_SW_SHIFT}, + {PMIC_CHRIND_BIAS_EN, MT6351_PMIC_CHRIND_BIAS_EN_ADDR, + MT6351_PMIC_CHRIND_BIAS_EN_MASK, MT6351_PMIC_CHRIND_BIAS_EN_SHIFT}, + {PMIC_RG_VA18_MODE_SET, MT6351_PMIC_RG_VA18_MODE_SET_ADDR, + MT6351_PMIC_RG_VA18_MODE_SET_MASK, MT6351_PMIC_RG_VA18_MODE_SET_SHIFT}, + {PMIC_RG_VA18_EN, MT6351_PMIC_RG_VA18_EN_ADDR, MT6351_PMIC_RG_VA18_EN_MASK, + MT6351_PMIC_RG_VA18_EN_SHIFT}, + {PMIC_RG_VA18_MODE_CTRL, MT6351_PMIC_RG_VA18_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VA18_MODE_CTRL_MASK, MT6351_PMIC_RG_VA18_MODE_CTRL_SHIFT}, + {PMIC_RG_VA18_ON_CTRL, MT6351_PMIC_RG_VA18_ON_CTRL_ADDR, + MT6351_PMIC_RG_VA18_ON_CTRL_MASK, MT6351_PMIC_RG_VA18_ON_CTRL_SHIFT}, + {PMIC_RG_VA18_SRCLK_MODE_SEL, MT6351_PMIC_RG_VA18_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VA18_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VA18_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VA18_MODE, MT6351_PMIC_DA_QI_VA18_MODE_ADDR, + MT6351_PMIC_DA_QI_VA18_MODE_MASK, MT6351_PMIC_DA_QI_VA18_MODE_SHIFT}, + {PMIC_RG_VA18_STBTD, MT6351_PMIC_RG_VA18_STBTD_ADDR, + MT6351_PMIC_RG_VA18_STBTD_MASK, MT6351_PMIC_RG_VA18_STBTD_SHIFT}, + {PMIC_RG_VA18_SRCLK_EN_SEL, MT6351_PMIC_RG_VA18_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VA18_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VA18_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VA18_STB, MT6351_PMIC_DA_QI_VA18_STB_ADDR, + MT6351_PMIC_DA_QI_VA18_STB_MASK, MT6351_PMIC_DA_QI_VA18_STB_SHIFT}, + {PMIC_DA_QI_VA18_EN, MT6351_PMIC_DA_QI_VA18_EN_ADDR, + MT6351_PMIC_DA_QI_VA18_EN_MASK, MT6351_PMIC_DA_QI_VA18_EN_SHIFT}, + {PMIC_RG_VA18_AUXADC_PWDB_EN, MT6351_PMIC_RG_VA18_AUXADC_PWDB_EN_ADDR, + MT6351_PMIC_RG_VA18_AUXADC_PWDB_EN_MASK, MT6351_PMIC_RG_VA18_AUXADC_PWDB_EN_SHIFT}, + {PMIC_RG_VA18_OCFB_EN, MT6351_PMIC_RG_VA18_OCFB_EN_ADDR, + MT6351_PMIC_RG_VA18_OCFB_EN_MASK, MT6351_PMIC_RG_VA18_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VA18_OCFB_EN, MT6351_PMIC_DA_QI_VA18_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VA18_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VA18_OCFB_EN_SHIFT}, + {PMIC_RG_VTCXO24_MODE_SET, MT6351_PMIC_RG_VTCXO24_MODE_SET_ADDR, + MT6351_PMIC_RG_VTCXO24_MODE_SET_MASK, MT6351_PMIC_RG_VTCXO24_MODE_SET_SHIFT}, + {PMIC_RG_VTCXO24_EN, MT6351_PMIC_RG_VTCXO24_EN_ADDR, + MT6351_PMIC_RG_VTCXO24_EN_MASK, MT6351_PMIC_RG_VTCXO24_EN_SHIFT}, + {PMIC_RG_VTCXO24_MODE_CTRL, MT6351_PMIC_RG_VTCXO24_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VTCXO24_MODE_CTRL_MASK, MT6351_PMIC_RG_VTCXO24_MODE_CTRL_SHIFT}, + {PMIC_RG_VTCXO24_ON_CTRL, MT6351_PMIC_RG_VTCXO24_ON_CTRL_ADDR, + MT6351_PMIC_RG_VTCXO24_ON_CTRL_MASK, MT6351_PMIC_RG_VTCXO24_ON_CTRL_SHIFT}, + {PMIC_RG_VTCXO24_SWITCH, MT6351_PMIC_RG_VTCXO24_SWITCH_ADDR, + MT6351_PMIC_RG_VTCXO24_SWITCH_MASK, MT6351_PMIC_RG_VTCXO24_SWITCH_SHIFT}, + {PMIC_RG_VTCXO24_SRCLK_MODE_SEL, MT6351_PMIC_RG_VTCXO24_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VTCXO24_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VTCXO24_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VTCXO24_MODE, MT6351_PMIC_DA_QI_VTCXO24_MODE_ADDR, + MT6351_PMIC_DA_QI_VTCXO24_MODE_MASK, MT6351_PMIC_DA_QI_VTCXO24_MODE_SHIFT}, + {PMIC_RG_VTCXO24_STBTD, MT6351_PMIC_RG_VTCXO24_STBTD_ADDR, + MT6351_PMIC_RG_VTCXO24_STBTD_MASK, MT6351_PMIC_RG_VTCXO24_STBTD_SHIFT}, + {PMIC_RG_VTCXO24_SRCLK_EN_SEL, MT6351_PMIC_RG_VTCXO24_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VTCXO24_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VTCXO24_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VTCXO24_STB, MT6351_PMIC_DA_QI_VTCXO24_STB_ADDR, + MT6351_PMIC_DA_QI_VTCXO24_STB_MASK, MT6351_PMIC_DA_QI_VTCXO24_STB_SHIFT}, + {PMIC_DA_QI_VTCXO24_EN, MT6351_PMIC_DA_QI_VTCXO24_EN_ADDR, + MT6351_PMIC_DA_QI_VTCXO24_EN_MASK, MT6351_PMIC_DA_QI_VTCXO24_EN_SHIFT}, + {PMIC_RG_VTCXO24_OCFB_EN, MT6351_PMIC_RG_VTCXO24_OCFB_EN_ADDR, + MT6351_PMIC_RG_VTCXO24_OCFB_EN_MASK, MT6351_PMIC_RG_VTCXO24_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VTCXO24_OCFB_EN, MT6351_PMIC_DA_QI_VTCXO24_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VTCXO24_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VTCXO24_OCFB_EN_SHIFT}, + {PMIC_RG_VTCXO28_MODE_SET, MT6351_PMIC_RG_VTCXO28_MODE_SET_ADDR, + MT6351_PMIC_RG_VTCXO28_MODE_SET_MASK, MT6351_PMIC_RG_VTCXO28_MODE_SET_SHIFT}, + {PMIC_RG_VTCXO28_EN, MT6351_PMIC_RG_VTCXO28_EN_ADDR, + MT6351_PMIC_RG_VTCXO28_EN_MASK, MT6351_PMIC_RG_VTCXO28_EN_SHIFT}, + {PMIC_RG_VTCXO28_MODE_CTRL, MT6351_PMIC_RG_VTCXO28_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VTCXO28_MODE_CTRL_MASK, MT6351_PMIC_RG_VTCXO28_MODE_CTRL_SHIFT}, + {PMIC_RG_VTCXO28_ON_CTRL, MT6351_PMIC_RG_VTCXO28_ON_CTRL_ADDR, + MT6351_PMIC_RG_VTCXO28_ON_CTRL_MASK, MT6351_PMIC_RG_VTCXO28_ON_CTRL_SHIFT}, + {PMIC_RG_VTCXO28_SRCLK_MODE_SEL, MT6351_PMIC_RG_VTCXO28_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VTCXO28_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VTCXO28_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VTCXO28_MODE, MT6351_PMIC_DA_QI_VTCXO28_MODE_ADDR, + MT6351_PMIC_DA_QI_VTCXO28_MODE_MASK, MT6351_PMIC_DA_QI_VTCXO28_MODE_SHIFT}, + {PMIC_RG_VTCXO28_STBTD, MT6351_PMIC_RG_VTCXO28_STBTD_ADDR, + MT6351_PMIC_RG_VTCXO28_STBTD_MASK, MT6351_PMIC_RG_VTCXO28_STBTD_SHIFT}, + {PMIC_RG_VTCXO28_SRCLK_EN_SEL, MT6351_PMIC_RG_VTCXO28_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VTCXO28_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VTCXO28_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VTCXO28_STB, MT6351_PMIC_DA_QI_VTCXO28_STB_ADDR, + MT6351_PMIC_DA_QI_VTCXO28_STB_MASK, MT6351_PMIC_DA_QI_VTCXO28_STB_SHIFT}, + {PMIC_DA_QI_VTCXO28_EN, MT6351_PMIC_DA_QI_VTCXO28_EN_ADDR, + MT6351_PMIC_DA_QI_VTCXO28_EN_MASK, MT6351_PMIC_DA_QI_VTCXO28_EN_SHIFT}, + {PMIC_RG_VTCXO28_OCFB_EN, MT6351_PMIC_RG_VTCXO28_OCFB_EN_ADDR, + MT6351_PMIC_RG_VTCXO28_OCFB_EN_MASK, MT6351_PMIC_RG_VTCXO28_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VTCXO28_OCFB_EN, MT6351_PMIC_DA_QI_VTCXO28_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VTCXO28_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VTCXO28_OCFB_EN_SHIFT}, + {PMIC_RG_VCN28_MODE_SET, MT6351_PMIC_RG_VCN28_MODE_SET_ADDR, + MT6351_PMIC_RG_VCN28_MODE_SET_MASK, MT6351_PMIC_RG_VCN28_MODE_SET_SHIFT}, + {PMIC_RG_VCN28_EN, MT6351_PMIC_RG_VCN28_EN_ADDR, MT6351_PMIC_RG_VCN28_EN_MASK, + MT6351_PMIC_RG_VCN28_EN_SHIFT}, + {PMIC_RG_VCN28_MODE_CTRL, MT6351_PMIC_RG_VCN28_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VCN28_MODE_CTRL_MASK, MT6351_PMIC_RG_VCN28_MODE_CTRL_SHIFT}, + {PMIC_RG_VCN28_ON_CTRL, MT6351_PMIC_RG_VCN28_ON_CTRL_ADDR, + MT6351_PMIC_RG_VCN28_ON_CTRL_MASK, MT6351_PMIC_RG_VCN28_ON_CTRL_SHIFT}, + {PMIC_RG_VCN28_SRCLK_MODE_SEL, MT6351_PMIC_RG_VCN28_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VCN28_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VCN28_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VCN28_MODE, MT6351_PMIC_DA_QI_VCN28_MODE_ADDR, + MT6351_PMIC_DA_QI_VCN28_MODE_MASK, MT6351_PMIC_DA_QI_VCN28_MODE_SHIFT}, + {PMIC_RG_VCN28_STBTD, MT6351_PMIC_RG_VCN28_STBTD_ADDR, + MT6351_PMIC_RG_VCN28_STBTD_MASK, MT6351_PMIC_RG_VCN28_STBTD_SHIFT}, + {PMIC_RG_VCN28_SRCLK_EN_SEL, MT6351_PMIC_RG_VCN28_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VCN28_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VCN28_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VCN28_STB, MT6351_PMIC_DA_QI_VCN28_STB_ADDR, + MT6351_PMIC_DA_QI_VCN28_STB_MASK, MT6351_PMIC_DA_QI_VCN28_STB_SHIFT}, + {PMIC_DA_QI_VCN28_EN, MT6351_PMIC_DA_QI_VCN28_EN_ADDR, + MT6351_PMIC_DA_QI_VCN28_EN_MASK, MT6351_PMIC_DA_QI_VCN28_EN_SHIFT}, + {PMIC_RG_VCN28_OCFB_EN, MT6351_PMIC_RG_VCN28_OCFB_EN_ADDR, + MT6351_PMIC_RG_VCN28_OCFB_EN_MASK, MT6351_PMIC_RG_VCN28_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VCN28_OCFB_EN, MT6351_PMIC_DA_QI_VCN28_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VCN28_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VCN28_OCFB_EN_SHIFT}, + {PMIC_RG_VCN28_DUMMY_LOAD_EN, MT6351_PMIC_RG_VCN28_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VCN28_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VCN28_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VCN28_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VCN28_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VCN28_DUMMY_LOAD, MT6351_PMIC_RG_VCN28_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VCN28_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VCN28_DUMMY_LOAD, MT6351_PMIC_DA_QI_VCN28_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VCN28_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VCN28_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCAMA_EN, MT6351_PMIC_RG_VCAMA_EN_ADDR, MT6351_PMIC_RG_VCAMA_EN_MASK, + MT6351_PMIC_RG_VCAMA_EN_SHIFT}, + {PMIC_RG_VCAMA_ON_CTRL, MT6351_PMIC_RG_VCAMA_ON_CTRL_ADDR, + MT6351_PMIC_RG_VCAMA_ON_CTRL_MASK, MT6351_PMIC_RG_VCAMA_ON_CTRL_SHIFT}, + {PMIC_RG_VCAMA_SRCLK_MODE_SEL, MT6351_PMIC_RG_VCAMA_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VCAMA_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VCAMA_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VCAMA_MODE, MT6351_PMIC_DA_QI_VCAMA_MODE_ADDR, + MT6351_PMIC_DA_QI_VCAMA_MODE_MASK, MT6351_PMIC_DA_QI_VCAMA_MODE_SHIFT}, + {PMIC_RG_VCAMA_STBTD, MT6351_PMIC_RG_VCAMA_STBTD_ADDR, + MT6351_PMIC_RG_VCAMA_STBTD_MASK, MT6351_PMIC_RG_VCAMA_STBTD_SHIFT}, + {PMIC_RG_VCAMA_SRCLK_EN_SEL, MT6351_PMIC_RG_VCAMA_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VCAMA_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VCAMA_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VCAMA_STB, MT6351_PMIC_DA_QI_VCAMA_STB_ADDR, + MT6351_PMIC_DA_QI_VCAMA_STB_MASK, MT6351_PMIC_DA_QI_VCAMA_STB_SHIFT}, + {PMIC_DA_QI_VCAMA_EN, MT6351_PMIC_DA_QI_VCAMA_EN_ADDR, + MT6351_PMIC_DA_QI_VCAMA_EN_MASK, MT6351_PMIC_DA_QI_VCAMA_EN_SHIFT}, + {PMIC_RG_VCAMA_OCFB_EN, MT6351_PMIC_RG_VCAMA_OCFB_EN_ADDR, + MT6351_PMIC_RG_VCAMA_OCFB_EN_MASK, MT6351_PMIC_RG_VCAMA_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VCAMA_OCFB_EN, MT6351_PMIC_DA_QI_VCAMA_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VCAMA_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VCAMA_OCFB_EN_SHIFT}, + {PMIC_RG_VUSB33_MODE_SET, MT6351_PMIC_RG_VUSB33_MODE_SET_ADDR, + MT6351_PMIC_RG_VUSB33_MODE_SET_MASK, MT6351_PMIC_RG_VUSB33_MODE_SET_SHIFT}, + {PMIC_RG_VUSB33_EN, MT6351_PMIC_RG_VUSB33_EN_ADDR, MT6351_PMIC_RG_VUSB33_EN_MASK, + MT6351_PMIC_RG_VUSB33_EN_SHIFT}, + {PMIC_RG_VUSB33_MODE_CTRL, MT6351_PMIC_RG_VUSB33_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VUSB33_MODE_CTRL_MASK, MT6351_PMIC_RG_VUSB33_MODE_CTRL_SHIFT}, + {PMIC_RG_VUSB33_ON_CTRL, MT6351_PMIC_RG_VUSB33_ON_CTRL_ADDR, + MT6351_PMIC_RG_VUSB33_ON_CTRL_MASK, MT6351_PMIC_RG_VUSB33_ON_CTRL_SHIFT}, + {PMIC_RG_VUSB33_SRCLK_MODE_SEL, MT6351_PMIC_RG_VUSB33_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VUSB33_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VUSB33_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VUSB33_MODE, MT6351_PMIC_DA_QI_VUSB33_MODE_ADDR, + MT6351_PMIC_DA_QI_VUSB33_MODE_MASK, MT6351_PMIC_DA_QI_VUSB33_MODE_SHIFT}, + {PMIC_RG_VUSB33_STBTD, MT6351_PMIC_RG_VUSB33_STBTD_ADDR, + MT6351_PMIC_RG_VUSB33_STBTD_MASK, MT6351_PMIC_RG_VUSB33_STBTD_SHIFT}, + {PMIC_RG_VUSB33_SRCLK_EN_SEL, MT6351_PMIC_RG_VUSB33_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VUSB33_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VUSB33_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VUSB33_STB, MT6351_PMIC_DA_QI_VUSB33_STB_ADDR, + MT6351_PMIC_DA_QI_VUSB33_STB_MASK, MT6351_PMIC_DA_QI_VUSB33_STB_SHIFT}, + {PMIC_DA_QI_VUSB33_EN, MT6351_PMIC_DA_QI_VUSB33_EN_ADDR, + MT6351_PMIC_DA_QI_VUSB33_EN_MASK, MT6351_PMIC_DA_QI_VUSB33_EN_SHIFT}, + {PMIC_RG_VUSB33_OCFB_EN, MT6351_PMIC_RG_VUSB33_OCFB_EN_ADDR, + MT6351_PMIC_RG_VUSB33_OCFB_EN_MASK, MT6351_PMIC_RG_VUSB33_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VUSB33_OCFB_EN, MT6351_PMIC_DA_QI_VUSB33_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VUSB33_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VUSB33_OCFB_EN_SHIFT}, + {PMIC_RG_VUSB33_DUMMY_LOAD_EN, MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VUSB33_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VUSB33_DUMMY_LOAD, MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VUSB33_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VUSB33_DUMMY_LOAD, MT6351_PMIC_DA_QI_VUSB33_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VUSB33_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VUSB33_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VSIM1_MODE_SET, MT6351_PMIC_RG_VSIM1_MODE_SET_ADDR, + MT6351_PMIC_RG_VSIM1_MODE_SET_MASK, MT6351_PMIC_RG_VSIM1_MODE_SET_SHIFT}, + {PMIC_RG_VSIM1_EN, MT6351_PMIC_RG_VSIM1_EN_ADDR, MT6351_PMIC_RG_VSIM1_EN_MASK, + MT6351_PMIC_RG_VSIM1_EN_SHIFT}, + {PMIC_RG_VSIM1_MODE_CTRL, MT6351_PMIC_RG_VSIM1_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VSIM1_MODE_CTRL_MASK, MT6351_PMIC_RG_VSIM1_MODE_CTRL_SHIFT}, + {PMIC_RG_VSIM1_ON_CTRL, MT6351_PMIC_RG_VSIM1_ON_CTRL_ADDR, + MT6351_PMIC_RG_VSIM1_ON_CTRL_MASK, MT6351_PMIC_RG_VSIM1_ON_CTRL_SHIFT}, + {PMIC_RG_VSIM1_SRCLK_MODE_SEL, MT6351_PMIC_RG_VSIM1_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VSIM1_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VSIM1_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VSIM1_MODE, MT6351_PMIC_DA_QI_VSIM1_MODE_ADDR, + MT6351_PMIC_DA_QI_VSIM1_MODE_MASK, MT6351_PMIC_DA_QI_VSIM1_MODE_SHIFT}, + {PMIC_RG_VSIM1_STBTD, MT6351_PMIC_RG_VSIM1_STBTD_ADDR, + MT6351_PMIC_RG_VSIM1_STBTD_MASK, MT6351_PMIC_RG_VSIM1_STBTD_SHIFT}, + {PMIC_RG_VSIM1_SRCLK_EN_SEL, MT6351_PMIC_RG_VSIM1_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VSIM1_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VSIM1_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VSIM1_STB, MT6351_PMIC_DA_QI_VSIM1_STB_ADDR, + MT6351_PMIC_DA_QI_VSIM1_STB_MASK, MT6351_PMIC_DA_QI_VSIM1_STB_SHIFT}, + {PMIC_DA_QI_VSIM1_EN, MT6351_PMIC_DA_QI_VSIM1_EN_ADDR, + MT6351_PMIC_DA_QI_VSIM1_EN_MASK, MT6351_PMIC_DA_QI_VSIM1_EN_SHIFT}, + {PMIC_RG_VSIM1_OCFB_EN, MT6351_PMIC_RG_VSIM1_OCFB_EN_ADDR, + MT6351_PMIC_RG_VSIM1_OCFB_EN_MASK, MT6351_PMIC_RG_VSIM1_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VSIM1_OCFB_EN, MT6351_PMIC_DA_QI_VSIM1_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VSIM1_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VSIM1_OCFB_EN_SHIFT}, + {PMIC_RG_VSIM1_DUMMY_LOAD_EN, MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VSIM1_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VSIM1_DUMMY_LOAD, MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VSIM1_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VSIM1_DUMMY_LOAD, MT6351_PMIC_DA_QI_VSIM1_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VSIM1_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VSIM1_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VSIM2_MODE_SET, MT6351_PMIC_RG_VSIM2_MODE_SET_ADDR, + MT6351_PMIC_RG_VSIM2_MODE_SET_MASK, MT6351_PMIC_RG_VSIM2_MODE_SET_SHIFT}, + {PMIC_RG_VSIM2_EN, MT6351_PMIC_RG_VSIM2_EN_ADDR, MT6351_PMIC_RG_VSIM2_EN_MASK, + MT6351_PMIC_RG_VSIM2_EN_SHIFT}, + {PMIC_RG_VSIM2_MODE_CTRL, MT6351_PMIC_RG_VSIM2_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VSIM2_MODE_CTRL_MASK, MT6351_PMIC_RG_VSIM2_MODE_CTRL_SHIFT}, + {PMIC_RG_VSIM2_ON_CTRL, MT6351_PMIC_RG_VSIM2_ON_CTRL_ADDR, + MT6351_PMIC_RG_VSIM2_ON_CTRL_MASK, MT6351_PMIC_RG_VSIM2_ON_CTRL_SHIFT}, + {PMIC_RG_VSIM2_SRCLK_MODE_SEL, MT6351_PMIC_RG_VSIM2_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VSIM2_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VSIM2_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VSIM2_MODE, MT6351_PMIC_DA_QI_VSIM2_MODE_ADDR, + MT6351_PMIC_DA_QI_VSIM2_MODE_MASK, MT6351_PMIC_DA_QI_VSIM2_MODE_SHIFT}, + {PMIC_RG_VSIM2_STBTD, MT6351_PMIC_RG_VSIM2_STBTD_ADDR, + MT6351_PMIC_RG_VSIM2_STBTD_MASK, MT6351_PMIC_RG_VSIM2_STBTD_SHIFT}, + {PMIC_RG_VSIM2_SRCLK_EN_SEL, MT6351_PMIC_RG_VSIM2_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VSIM2_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VSIM2_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VSIM2_STB, MT6351_PMIC_DA_QI_VSIM2_STB_ADDR, + MT6351_PMIC_DA_QI_VSIM2_STB_MASK, MT6351_PMIC_DA_QI_VSIM2_STB_SHIFT}, + {PMIC_DA_QI_VSIM2_EN, MT6351_PMIC_DA_QI_VSIM2_EN_ADDR, + MT6351_PMIC_DA_QI_VSIM2_EN_MASK, MT6351_PMIC_DA_QI_VSIM2_EN_SHIFT}, + {PMIC_RG_VSIM2_OCFB_EN, MT6351_PMIC_RG_VSIM2_OCFB_EN_ADDR, + MT6351_PMIC_RG_VSIM2_OCFB_EN_MASK, MT6351_PMIC_RG_VSIM2_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VSIM2_OCFB_EN, MT6351_PMIC_DA_QI_VSIM2_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VSIM2_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VSIM2_OCFB_EN_SHIFT}, + {PMIC_RG_VSIM2_DUMMY_LOAD_EN, MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VSIM2_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VSIM2_DUMMY_LOAD, MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VSIM2_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VSIM2_DUMMY_LOAD, MT6351_PMIC_DA_QI_VSIM2_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VSIM2_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VSIM2_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VEMC_MODE_SET, MT6351_PMIC_RG_VEMC_MODE_SET_ADDR, + MT6351_PMIC_RG_VEMC_MODE_SET_MASK, MT6351_PMIC_RG_VEMC_MODE_SET_SHIFT}, + {PMIC_RG_VEMC_EN, MT6351_PMIC_RG_VEMC_EN_ADDR, MT6351_PMIC_RG_VEMC_EN_MASK, + MT6351_PMIC_RG_VEMC_EN_SHIFT}, + {PMIC_RG_VEMC_MODE_CTRL, MT6351_PMIC_RG_VEMC_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VEMC_MODE_CTRL_MASK, MT6351_PMIC_RG_VEMC_MODE_CTRL_SHIFT}, + {PMIC_RG_VEMC_ON_CTRL, MT6351_PMIC_RG_VEMC_ON_CTRL_ADDR, + MT6351_PMIC_RG_VEMC_ON_CTRL_MASK, MT6351_PMIC_RG_VEMC_ON_CTRL_SHIFT}, + {PMIC_RG_VEMC_SRCLK_MODE_SEL, MT6351_PMIC_RG_VEMC_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VEMC_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VEMC_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VEMC_MODE, MT6351_PMIC_DA_QI_VEMC_MODE_ADDR, + MT6351_PMIC_DA_QI_VEMC_MODE_MASK, MT6351_PMIC_DA_QI_VEMC_MODE_SHIFT}, + {PMIC_RG_VEMC_STBTD, MT6351_PMIC_RG_VEMC_STBTD_ADDR, + MT6351_PMIC_RG_VEMC_STBTD_MASK, MT6351_PMIC_RG_VEMC_STBTD_SHIFT}, + {PMIC_RG_VEMC_SRCLK_EN_SEL, MT6351_PMIC_RG_VEMC_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VEMC_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VEMC_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VEMC_STB, MT6351_PMIC_DA_QI_VEMC_STB_ADDR, + MT6351_PMIC_DA_QI_VEMC_STB_MASK, MT6351_PMIC_DA_QI_VEMC_STB_SHIFT}, + {PMIC_DA_QI_VEMC_EN, MT6351_PMIC_DA_QI_VEMC_EN_ADDR, + MT6351_PMIC_DA_QI_VEMC_EN_MASK, MT6351_PMIC_DA_QI_VEMC_EN_SHIFT}, + {PMIC_RG_VEMC_OCFB_EN, MT6351_PMIC_RG_VEMC_OCFB_EN_ADDR, + MT6351_PMIC_RG_VEMC_OCFB_EN_MASK, MT6351_PMIC_RG_VEMC_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VEMC_OCFB_EN, MT6351_PMIC_DA_QI_VEMC_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VEMC_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VEMC_OCFB_EN_SHIFT}, + {PMIC_RG_VEMC_DUMMY_LOAD_EN, MT6351_PMIC_RG_VEMC_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VEMC_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VEMC_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VEMC_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VEMC_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VEMC_DUMMY_LOAD, MT6351_PMIC_RG_VEMC_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VEMC_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VEMC_DUMMY_LOAD, MT6351_PMIC_DA_QI_VEMC_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VEMC_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VEMC_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VMCH_MODE_SET, MT6351_PMIC_RG_VMCH_MODE_SET_ADDR, + MT6351_PMIC_RG_VMCH_MODE_SET_MASK, MT6351_PMIC_RG_VMCH_MODE_SET_SHIFT}, + {PMIC_RG_VMCH_EN, MT6351_PMIC_RG_VMCH_EN_ADDR, MT6351_PMIC_RG_VMCH_EN_MASK, + MT6351_PMIC_RG_VMCH_EN_SHIFT}, + {PMIC_RG_VMCH_MODE_CTRL, MT6351_PMIC_RG_VMCH_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VMCH_MODE_CTRL_MASK, MT6351_PMIC_RG_VMCH_MODE_CTRL_SHIFT}, + {PMIC_RG_VMCH_ON_CTRL, MT6351_PMIC_RG_VMCH_ON_CTRL_ADDR, + MT6351_PMIC_RG_VMCH_ON_CTRL_MASK, MT6351_PMIC_RG_VMCH_ON_CTRL_SHIFT}, + {PMIC_RG_VMCH_SRCLK_MODE_SEL, MT6351_PMIC_RG_VMCH_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VMCH_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VMCH_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VMCH_MODE, MT6351_PMIC_DA_QI_VMCH_MODE_ADDR, + MT6351_PMIC_DA_QI_VMCH_MODE_MASK, MT6351_PMIC_DA_QI_VMCH_MODE_SHIFT}, + {PMIC_RG_VMCH_STBTD, MT6351_PMIC_RG_VMCH_STBTD_ADDR, + MT6351_PMIC_RG_VMCH_STBTD_MASK, MT6351_PMIC_RG_VMCH_STBTD_SHIFT}, + {PMIC_RG_VMCH_SRCLK_EN_SEL, MT6351_PMIC_RG_VMCH_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VMCH_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VMCH_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VMCH_STB, MT6351_PMIC_DA_QI_VMCH_STB_ADDR, + MT6351_PMIC_DA_QI_VMCH_STB_MASK, MT6351_PMIC_DA_QI_VMCH_STB_SHIFT}, + {PMIC_DA_QI_VMCH_EN, MT6351_PMIC_DA_QI_VMCH_EN_ADDR, + MT6351_PMIC_DA_QI_VMCH_EN_MASK, MT6351_PMIC_DA_QI_VMCH_EN_SHIFT}, + {PMIC_RG_VMCH_OCFB_EN, MT6351_PMIC_RG_VMCH_OCFB_EN_ADDR, + MT6351_PMIC_RG_VMCH_OCFB_EN_MASK, MT6351_PMIC_RG_VMCH_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VMCH_OCFB_EN, MT6351_PMIC_DA_QI_VMCH_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VMCH_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VMCH_OCFB_EN_SHIFT}, + {PMIC_RG_VMCH_DUMMY_LOAD_EN, MT6351_PMIC_RG_VMCH_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VMCH_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VMCH_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VMCH_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VMCH_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VMCH_DUMMY_LOAD, MT6351_PMIC_RG_VMCH_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VMCH_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VMCH_DUMMY_LOAD, MT6351_PMIC_DA_QI_VMCH_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VMCH_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VMCH_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VIO28_MODE_SET, MT6351_PMIC_RG_VIO28_MODE_SET_ADDR, + MT6351_PMIC_RG_VIO28_MODE_SET_MASK, MT6351_PMIC_RG_VIO28_MODE_SET_SHIFT}, + {PMIC_RG_VIO28_EN, MT6351_PMIC_RG_VIO28_EN_ADDR, MT6351_PMIC_RG_VIO28_EN_MASK, + MT6351_PMIC_RG_VIO28_EN_SHIFT}, + {PMIC_RG_VIO28_MODE_CTRL, MT6351_PMIC_RG_VIO28_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VIO28_MODE_CTRL_MASK, MT6351_PMIC_RG_VIO28_MODE_CTRL_SHIFT}, + {PMIC_RG_VIO28_ON_CTRL, MT6351_PMIC_RG_VIO28_ON_CTRL_ADDR, + MT6351_PMIC_RG_VIO28_ON_CTRL_MASK, MT6351_PMIC_RG_VIO28_ON_CTRL_SHIFT}, + {PMIC_RG_VIO28_SRCLK_MODE_SEL, MT6351_PMIC_RG_VIO28_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VIO28_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VIO28_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VIO28_MODE, MT6351_PMIC_DA_QI_VIO28_MODE_ADDR, + MT6351_PMIC_DA_QI_VIO28_MODE_MASK, MT6351_PMIC_DA_QI_VIO28_MODE_SHIFT}, + {PMIC_RG_VIO28_STBTD, MT6351_PMIC_RG_VIO28_STBTD_ADDR, + MT6351_PMIC_RG_VIO28_STBTD_MASK, MT6351_PMIC_RG_VIO28_STBTD_SHIFT}, + {PMIC_RG_VIO28_SRCLK_EN_SEL, MT6351_PMIC_RG_VIO28_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VIO28_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VIO28_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VIO28_STB, MT6351_PMIC_DA_QI_VIO28_STB_ADDR, + MT6351_PMIC_DA_QI_VIO28_STB_MASK, MT6351_PMIC_DA_QI_VIO28_STB_SHIFT}, + {PMIC_DA_QI_VIO28_EN, MT6351_PMIC_DA_QI_VIO28_EN_ADDR, + MT6351_PMIC_DA_QI_VIO28_EN_MASK, MT6351_PMIC_DA_QI_VIO28_EN_SHIFT}, + {PMIC_RG_VIO28_OCFB_EN, MT6351_PMIC_RG_VIO28_OCFB_EN_ADDR, + MT6351_PMIC_RG_VIO28_OCFB_EN_MASK, MT6351_PMIC_RG_VIO28_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VIO28_OCFB_EN, MT6351_PMIC_DA_QI_VIO28_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VIO28_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VIO28_OCFB_EN_SHIFT}, + {PMIC_RG_VIO28_DUMMY_LOAD_EN, MT6351_PMIC_RG_VIO28_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VIO28_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VIO28_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VIO28_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VIO28_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VIO28_DUMMY_LOAD, MT6351_PMIC_RG_VIO28_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VIO28_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VIO28_DUMMY_LOAD, MT6351_PMIC_DA_QI_VIO28_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VIO28_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VIO28_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VIBR_MODE_SET, MT6351_PMIC_RG_VIBR_MODE_SET_ADDR, + MT6351_PMIC_RG_VIBR_MODE_SET_MASK, MT6351_PMIC_RG_VIBR_MODE_SET_SHIFT}, + {PMIC_RG_VIBR_EN, MT6351_PMIC_RG_VIBR_EN_ADDR, MT6351_PMIC_RG_VIBR_EN_MASK, + MT6351_PMIC_RG_VIBR_EN_SHIFT}, + {PMIC_RG_VIBR_MODE_CTRL, MT6351_PMIC_RG_VIBR_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VIBR_MODE_CTRL_MASK, MT6351_PMIC_RG_VIBR_MODE_CTRL_SHIFT}, + {PMIC_RG_VIBR_ON_CTRL, MT6351_PMIC_RG_VIBR_ON_CTRL_ADDR, + MT6351_PMIC_RG_VIBR_ON_CTRL_MASK, MT6351_PMIC_RG_VIBR_ON_CTRL_SHIFT}, + {PMIC_RG_VIBR_THER_SDN_EN, MT6351_PMIC_RG_VIBR_THER_SDN_EN_ADDR, + MT6351_PMIC_RG_VIBR_THER_SDN_EN_MASK, MT6351_PMIC_RG_VIBR_THER_SDN_EN_SHIFT}, + {PMIC_RG_VIBR_SRCLK_MODE_SEL, MT6351_PMIC_RG_VIBR_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VIBR_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VIBR_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VIBR_MODE, MT6351_PMIC_DA_QI_VIBR_MODE_ADDR, + MT6351_PMIC_DA_QI_VIBR_MODE_MASK, MT6351_PMIC_DA_QI_VIBR_MODE_SHIFT}, + {PMIC_RG_VIBR_STBTD, MT6351_PMIC_RG_VIBR_STBTD_ADDR, + MT6351_PMIC_RG_VIBR_STBTD_MASK, MT6351_PMIC_RG_VIBR_STBTD_SHIFT}, + {PMIC_RG_VIBR_SRCLK_EN_SEL, MT6351_PMIC_RG_VIBR_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VIBR_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VIBR_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VIBR_STB, MT6351_PMIC_DA_QI_VIBR_STB_ADDR, + MT6351_PMIC_DA_QI_VIBR_STB_MASK, MT6351_PMIC_DA_QI_VIBR_STB_SHIFT}, + {PMIC_DA_QI_VIBR_EN, MT6351_PMIC_DA_QI_VIBR_EN_ADDR, + MT6351_PMIC_DA_QI_VIBR_EN_MASK, MT6351_PMIC_DA_QI_VIBR_EN_SHIFT}, + {PMIC_RG_VIBR_OCFB_EN, MT6351_PMIC_RG_VIBR_OCFB_EN_ADDR, + MT6351_PMIC_RG_VIBR_OCFB_EN_MASK, MT6351_PMIC_RG_VIBR_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VIBR_OCFB_EN, MT6351_PMIC_DA_QI_VIBR_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VIBR_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VIBR_OCFB_EN_SHIFT}, + {PMIC_RG_VIBR_DUMMY_LOAD_EN, MT6351_PMIC_RG_VIBR_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VIBR_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VIBR_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VIBR_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VIBR_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VIBR_DUMMY_LOAD, MT6351_PMIC_RG_VIBR_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VIBR_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VIBR_DUMMY_LOAD, MT6351_PMIC_DA_QI_VIBR_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VIBR_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VIBR_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCAMD_MODE_SET, MT6351_PMIC_RG_VCAMD_MODE_SET_ADDR, + MT6351_PMIC_RG_VCAMD_MODE_SET_MASK, MT6351_PMIC_RG_VCAMD_MODE_SET_SHIFT}, + {PMIC_RG_VCAMD_EN, MT6351_PMIC_RG_VCAMD_EN_ADDR, MT6351_PMIC_RG_VCAMD_EN_MASK, + MT6351_PMIC_RG_VCAMD_EN_SHIFT}, + {PMIC_RG_VCAMD_MODE_CTRL, MT6351_PMIC_RG_VCAMD_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VCAMD_MODE_CTRL_MASK, MT6351_PMIC_RG_VCAMD_MODE_CTRL_SHIFT}, + {PMIC_RG_VCAMD_SRCLK_MODE_SEL, MT6351_PMIC_RG_VCAMD_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VCAMD_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VCAMD_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VCAMD_MODE, MT6351_PMIC_DA_QI_VCAMD_MODE_ADDR, + MT6351_PMIC_DA_QI_VCAMD_MODE_MASK, MT6351_PMIC_DA_QI_VCAMD_MODE_SHIFT}, + {PMIC_RG_VCAMD_STBTD, MT6351_PMIC_RG_VCAMD_STBTD_ADDR, + MT6351_PMIC_RG_VCAMD_STBTD_MASK, MT6351_PMIC_RG_VCAMD_STBTD_SHIFT}, + {PMIC_DA_QI_VCAMD_STB, MT6351_PMIC_DA_QI_VCAMD_STB_ADDR, + MT6351_PMIC_DA_QI_VCAMD_STB_MASK, MT6351_PMIC_DA_QI_VCAMD_STB_SHIFT}, + {PMIC_DA_QI_VCAMD_EN, MT6351_PMIC_DA_QI_VCAMD_EN_ADDR, + MT6351_PMIC_DA_QI_VCAMD_EN_MASK, MT6351_PMIC_DA_QI_VCAMD_EN_SHIFT}, + {PMIC_RG_VCAMD_OCFB_EN, MT6351_PMIC_RG_VCAMD_OCFB_EN_ADDR, + MT6351_PMIC_RG_VCAMD_OCFB_EN_MASK, MT6351_PMIC_RG_VCAMD_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VCAMD_OCFB_EN, MT6351_PMIC_DA_QI_VCAMD_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VCAMD_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VCAMD_OCFB_EN_SHIFT}, + {PMIC_RG_VCAMD_DUMMY_LOAD_EN, MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VCAMD_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VCAMD_DUMMY_LOAD, MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VCAMD_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VCAMD_DUMMY_LOAD, MT6351_PMIC_DA_QI_VCAMD_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VCAMD_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VCAMD_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VRF18_MODE_SET, MT6351_PMIC_RG_VRF18_MODE_SET_ADDR, + MT6351_PMIC_RG_VRF18_MODE_SET_MASK, MT6351_PMIC_RG_VRF18_MODE_SET_SHIFT}, + {PMIC_RG_VRF18_EN, MT6351_PMIC_RG_VRF18_EN_ADDR, MT6351_PMIC_RG_VRF18_EN_MASK, + MT6351_PMIC_RG_VRF18_EN_SHIFT}, + {PMIC_RG_VRF18_MODE_CTRL, MT6351_PMIC_RG_VRF18_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VRF18_MODE_CTRL_MASK, MT6351_PMIC_RG_VRF18_MODE_CTRL_SHIFT}, + {PMIC_RG_VRF18_ON_CTRL, MT6351_PMIC_RG_VRF18_ON_CTRL_ADDR, + MT6351_PMIC_RG_VRF18_ON_CTRL_MASK, MT6351_PMIC_RG_VRF18_ON_CTRL_SHIFT}, + {PMIC_RG_VRF18_SRCLK_MODE_SEL, MT6351_PMIC_RG_VRF18_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VRF18_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VRF18_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VRF18_MODE, MT6351_PMIC_DA_QI_VRF18_MODE_ADDR, + MT6351_PMIC_DA_QI_VRF18_MODE_MASK, MT6351_PMIC_DA_QI_VRF18_MODE_SHIFT}, + {PMIC_RG_VRF18_STBTD, MT6351_PMIC_RG_VRF18_STBTD_ADDR, + MT6351_PMIC_RG_VRF18_STBTD_MASK, MT6351_PMIC_RG_VRF18_STBTD_SHIFT}, + {PMIC_RG_VRF18_SRCLK_EN_SEL, MT6351_PMIC_RG_VRF18_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VRF18_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VRF18_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VRF18_STB, MT6351_PMIC_DA_QI_VRF18_STB_ADDR, + MT6351_PMIC_DA_QI_VRF18_STB_MASK, MT6351_PMIC_DA_QI_VRF18_STB_SHIFT}, + {PMIC_DA_QI_VRF18_EN, MT6351_PMIC_DA_QI_VRF18_EN_ADDR, + MT6351_PMIC_DA_QI_VRF18_EN_MASK, MT6351_PMIC_DA_QI_VRF18_EN_SHIFT}, + {PMIC_RG_VRF18_OCFB_EN, MT6351_PMIC_RG_VRF18_OCFB_EN_ADDR, + MT6351_PMIC_RG_VRF18_OCFB_EN_MASK, MT6351_PMIC_RG_VRF18_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VRF18_OCFB_EN, MT6351_PMIC_DA_QI_VRF18_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VRF18_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VRF18_OCFB_EN_SHIFT}, + {PMIC_RG_VRF18_DUMMY_LOAD_EN, MT6351_PMIC_RG_VRF18_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VRF18_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VRF18_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VRF18_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VRF18_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VRF18_DUMMY_LOAD, MT6351_PMIC_RG_VRF18_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VRF18_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VRF18_DUMMY_LOAD, MT6351_PMIC_DA_QI_VRF18_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VRF18_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VRF18_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VIO18_MODE_SET, MT6351_PMIC_RG_VIO18_MODE_SET_ADDR, + MT6351_PMIC_RG_VIO18_MODE_SET_MASK, MT6351_PMIC_RG_VIO18_MODE_SET_SHIFT}, + {PMIC_RG_VIO18_EN, MT6351_PMIC_RG_VIO18_EN_ADDR, MT6351_PMIC_RG_VIO18_EN_MASK, + MT6351_PMIC_RG_VIO18_EN_SHIFT}, + {PMIC_RG_VIO18_MODE_CTRL, MT6351_PMIC_RG_VIO18_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VIO18_MODE_CTRL_MASK, MT6351_PMIC_RG_VIO18_MODE_CTRL_SHIFT}, + {PMIC_RG_VIO18_ON_CTRL, MT6351_PMIC_RG_VIO18_ON_CTRL_ADDR, + MT6351_PMIC_RG_VIO18_ON_CTRL_MASK, MT6351_PMIC_RG_VIO18_ON_CTRL_SHIFT}, + {PMIC_RG_VIO18_SRCLK_MODE_SEL, MT6351_PMIC_RG_VIO18_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VIO18_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VIO18_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VIO18_MODE, MT6351_PMIC_DA_QI_VIO18_MODE_ADDR, + MT6351_PMIC_DA_QI_VIO18_MODE_MASK, MT6351_PMIC_DA_QI_VIO18_MODE_SHIFT}, + {PMIC_RG_VIO18_STBTD, MT6351_PMIC_RG_VIO18_STBTD_ADDR, + MT6351_PMIC_RG_VIO18_STBTD_MASK, MT6351_PMIC_RG_VIO18_STBTD_SHIFT}, + {PMIC_RG_VIO18_SRCLK_EN_SEL, MT6351_PMIC_RG_VIO18_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VIO18_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VIO18_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VIO18_STB, MT6351_PMIC_DA_QI_VIO18_STB_ADDR, + MT6351_PMIC_DA_QI_VIO18_STB_MASK, MT6351_PMIC_DA_QI_VIO18_STB_SHIFT}, + {PMIC_DA_QI_VIO18_EN, MT6351_PMIC_DA_QI_VIO18_EN_ADDR, + MT6351_PMIC_DA_QI_VIO18_EN_MASK, MT6351_PMIC_DA_QI_VIO18_EN_SHIFT}, + {PMIC_RG_VIO18_OCFB_EN, MT6351_PMIC_RG_VIO18_OCFB_EN_ADDR, + MT6351_PMIC_RG_VIO18_OCFB_EN_MASK, MT6351_PMIC_RG_VIO18_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VIO18_OCFB_EN, MT6351_PMIC_DA_QI_VIO18_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VIO18_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VIO18_OCFB_EN_SHIFT}, + {PMIC_RG_VIO18_DUMMY_LOAD_EN, MT6351_PMIC_RG_VIO18_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VIO18_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VIO18_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VIO18_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VIO18_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VIO18_DUMMY_LOAD, MT6351_PMIC_RG_VIO18_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VIO18_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VIO18_DUMMY_LOAD, MT6351_PMIC_DA_QI_VIO18_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VIO18_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VIO18_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCN18_MODE_SET, MT6351_PMIC_RG_VCN18_MODE_SET_ADDR, + MT6351_PMIC_RG_VCN18_MODE_SET_MASK, MT6351_PMIC_RG_VCN18_MODE_SET_SHIFT}, + {PMIC_RG_VCN18_EN, MT6351_PMIC_RG_VCN18_EN_ADDR, MT6351_PMIC_RG_VCN18_EN_MASK, + MT6351_PMIC_RG_VCN18_EN_SHIFT}, + {PMIC_RG_VCN18_MODE_CTRL, MT6351_PMIC_RG_VCN18_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VCN18_MODE_CTRL_MASK, MT6351_PMIC_RG_VCN18_MODE_CTRL_SHIFT}, + {PMIC_RG_VCN18_ON_CTRL, MT6351_PMIC_RG_VCN18_ON_CTRL_ADDR, + MT6351_PMIC_RG_VCN18_ON_CTRL_MASK, MT6351_PMIC_RG_VCN18_ON_CTRL_SHIFT}, + {PMIC_RG_VCN18_SRCLK_MODE_SEL, MT6351_PMIC_RG_VCN18_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VCN18_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VCN18_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VCN18_MODE, MT6351_PMIC_DA_QI_VCN18_MODE_ADDR, + MT6351_PMIC_DA_QI_VCN18_MODE_MASK, MT6351_PMIC_DA_QI_VCN18_MODE_SHIFT}, + {PMIC_RG_VCN18_STBTD, MT6351_PMIC_RG_VCN18_STBTD_ADDR, + MT6351_PMIC_RG_VCN18_STBTD_MASK, MT6351_PMIC_RG_VCN18_STBTD_SHIFT}, + {PMIC_RG_VCN18_SRCLK_EN_SEL, MT6351_PMIC_RG_VCN18_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VCN18_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VCN18_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VCN18_STB, MT6351_PMIC_DA_QI_VCN18_STB_ADDR, + MT6351_PMIC_DA_QI_VCN18_STB_MASK, MT6351_PMIC_DA_QI_VCN18_STB_SHIFT}, + {PMIC_DA_QI_VCN18_EN, MT6351_PMIC_DA_QI_VCN18_EN_ADDR, + MT6351_PMIC_DA_QI_VCN18_EN_MASK, MT6351_PMIC_DA_QI_VCN18_EN_SHIFT}, + {PMIC_RG_VCN18_OCFB_EN, MT6351_PMIC_RG_VCN18_OCFB_EN_ADDR, + MT6351_PMIC_RG_VCN18_OCFB_EN_MASK, MT6351_PMIC_RG_VCN18_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VCN18_OCFB_EN, MT6351_PMIC_DA_QI_VCN18_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VCN18_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VCN18_OCFB_EN_SHIFT}, + {PMIC_RG_VCN18_DUMMY_LOAD_EN, MT6351_PMIC_RG_VCN18_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VCN18_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VCN18_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VCN18_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VCN18_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VCN18_DUMMY_LOAD, MT6351_PMIC_RG_VCN18_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VCN18_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VCN18_DUMMY_LOAD, MT6351_PMIC_DA_QI_VCN18_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VCN18_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VCN18_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCAMIO_MODE_SET, MT6351_PMIC_RG_VCAMIO_MODE_SET_ADDR, + MT6351_PMIC_RG_VCAMIO_MODE_SET_MASK, MT6351_PMIC_RG_VCAMIO_MODE_SET_SHIFT}, + {PMIC_RG_VCAMIO_EN, MT6351_PMIC_RG_VCAMIO_EN_ADDR, MT6351_PMIC_RG_VCAMIO_EN_MASK, + MT6351_PMIC_RG_VCAMIO_EN_SHIFT}, + {PMIC_RG_VCAMIO_MODE_CTRL, MT6351_PMIC_RG_VCAMIO_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VCAMIO_MODE_CTRL_MASK, MT6351_PMIC_RG_VCAMIO_MODE_CTRL_SHIFT}, + {PMIC_RG_VCAMIO_SRCLK_MODE_SEL, MT6351_PMIC_RG_VCAMIO_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VCAMIO_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VCAMIO_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VCAMIO_MODE, MT6351_PMIC_DA_QI_VCAMIO_MODE_ADDR, + MT6351_PMIC_DA_QI_VCAMIO_MODE_MASK, MT6351_PMIC_DA_QI_VCAMIO_MODE_SHIFT}, + {PMIC_RG_VCAMIO_STBTD, MT6351_PMIC_RG_VCAMIO_STBTD_ADDR, + MT6351_PMIC_RG_VCAMIO_STBTD_MASK, MT6351_PMIC_RG_VCAMIO_STBTD_SHIFT}, + {PMIC_DA_QI_VCAMIO_STB, MT6351_PMIC_DA_QI_VCAMIO_STB_ADDR, + MT6351_PMIC_DA_QI_VCAMIO_STB_MASK, MT6351_PMIC_DA_QI_VCAMIO_STB_SHIFT}, + {PMIC_DA_QI_VCAMIO_EN, MT6351_PMIC_DA_QI_VCAMIO_EN_ADDR, + MT6351_PMIC_DA_QI_VCAMIO_EN_MASK, MT6351_PMIC_DA_QI_VCAMIO_EN_SHIFT}, + {PMIC_RG_VCAMIO_OCFB_EN, MT6351_PMIC_RG_VCAMIO_OCFB_EN_ADDR, + MT6351_PMIC_RG_VCAMIO_OCFB_EN_MASK, MT6351_PMIC_RG_VCAMIO_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VCAMIO_OCFB_EN, MT6351_PMIC_DA_QI_VCAMIO_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VCAMIO_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VCAMIO_OCFB_EN_SHIFT}, + {PMIC_RG_VCAMIO_DUMMY_LOAD_EN, MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VCAMIO_DUMMY_LOAD, MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VCAMIO_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VCAMIO_DUMMY_LOAD, MT6351_PMIC_DA_QI_VCAMIO_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VCAMIO_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VCAMIO_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VSRAM_PROC_MODE_SET, MT6351_PMIC_RG_VSRAM_PROC_MODE_SET_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_MODE_SET_MASK, MT6351_PMIC_RG_VSRAM_PROC_MODE_SET_SHIFT}, + {PMIC_RG_VSRAM_PROC_EN, MT6351_PMIC_RG_VSRAM_PROC_EN_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_EN_MASK, MT6351_PMIC_RG_VSRAM_PROC_EN_SHIFT}, + {PMIC_RG_VSRAM_PROC_MODE_CTRL, MT6351_PMIC_RG_VSRAM_PROC_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_MODE_CTRL_MASK, MT6351_PMIC_RG_VSRAM_PROC_MODE_CTRL_SHIFT}, + {PMIC_RG_VSRAM_PROC_ON_CTRL, MT6351_PMIC_RG_VSRAM_PROC_ON_CTRL_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_ON_CTRL_MASK, MT6351_PMIC_RG_VSRAM_PROC_ON_CTRL_SHIFT}, + {PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL, MT6351_PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL_MASK, + MT6351_PMIC_RG_VSRAM_PROC_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VSRAM_PROC_MODE, MT6351_PMIC_DA_QI_VSRAM_PROC_MODE_ADDR, + MT6351_PMIC_DA_QI_VSRAM_PROC_MODE_MASK, MT6351_PMIC_DA_QI_VSRAM_PROC_MODE_SHIFT}, + {PMIC_RG_VSRAM_PROC_STBTD, MT6351_PMIC_RG_VSRAM_PROC_STBTD_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_STBTD_MASK, MT6351_PMIC_RG_VSRAM_PROC_STBTD_SHIFT}, + {PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL, MT6351_PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL_MASK, + MT6351_PMIC_RG_VSRAM_PROC_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VSRAM_PROC_STB, MT6351_PMIC_DA_QI_VSRAM_PROC_STB_ADDR, + MT6351_PMIC_DA_QI_VSRAM_PROC_STB_MASK, MT6351_PMIC_DA_QI_VSRAM_PROC_STB_SHIFT}, + {PMIC_DA_QI_VSRAM_PROC_EN, MT6351_PMIC_DA_QI_VSRAM_PROC_EN_ADDR, + MT6351_PMIC_DA_QI_VSRAM_PROC_EN_MASK, MT6351_PMIC_DA_QI_VSRAM_PROC_EN_SHIFT}, + {PMIC_RG_VSRAM_PROC_OCFB_EN, MT6351_PMIC_RG_VSRAM_PROC_OCFB_EN_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_OCFB_EN_MASK, MT6351_PMIC_RG_VSRAM_PROC_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VSRAM_PROC_OCFB_EN, MT6351_PMIC_DA_QI_VSRAM_PROC_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VSRAM_PROC_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VSRAM_PROC_OCFB_EN_SHIFT}, + {PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN, MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN_MASK, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL_MASK, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VSRAM_PROC_DUMMY_LOAD, MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VSRAM_PROC_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD, MT6351_PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD_MASK, + MT6351_PMIC_DA_QI_VSRAM_PROC_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VXO22_MODE_SET, MT6351_PMIC_RG_VXO22_MODE_SET_ADDR, + MT6351_PMIC_RG_VXO22_MODE_SET_MASK, MT6351_PMIC_RG_VXO22_MODE_SET_SHIFT}, + {PMIC_RG_VXO22_EN, MT6351_PMIC_RG_VXO22_EN_ADDR, MT6351_PMIC_RG_VXO22_EN_MASK, + MT6351_PMIC_RG_VXO22_EN_SHIFT}, + {PMIC_RG_VXO22_MODE_CTRL, MT6351_PMIC_RG_VXO22_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VXO22_MODE_CTRL_MASK, MT6351_PMIC_RG_VXO22_MODE_CTRL_SHIFT}, + {PMIC_RG_VXO22_ON_CTRL, MT6351_PMIC_RG_VXO22_ON_CTRL_ADDR, + MT6351_PMIC_RG_VXO22_ON_CTRL_MASK, MT6351_PMIC_RG_VXO22_ON_CTRL_SHIFT}, + {PMIC_RG_VXO22_SWITCH, MT6351_PMIC_RG_VXO22_SWITCH_ADDR, + MT6351_PMIC_RG_VXO22_SWITCH_MASK, MT6351_PMIC_RG_VXO22_SWITCH_SHIFT}, + {PMIC_RG_VXO22_SRCLK_MODE_SEL, MT6351_PMIC_RG_VXO22_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VXO22_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VXO22_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VXO22_MODE, MT6351_PMIC_DA_QI_VXO22_MODE_ADDR, + MT6351_PMIC_DA_QI_VXO22_MODE_MASK, MT6351_PMIC_DA_QI_VXO22_MODE_SHIFT}, + {PMIC_RG_VXO22_STBTD, MT6351_PMIC_RG_VXO22_STBTD_ADDR, + MT6351_PMIC_RG_VXO22_STBTD_MASK, MT6351_PMIC_RG_VXO22_STBTD_SHIFT}, + {PMIC_RG_VXO22_SRCLK_EN_SEL, MT6351_PMIC_RG_VXO22_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VXO22_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VXO22_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VXO22_STB, MT6351_PMIC_DA_QI_VXO22_STB_ADDR, + MT6351_PMIC_DA_QI_VXO22_STB_MASK, MT6351_PMIC_DA_QI_VXO22_STB_SHIFT}, + {PMIC_DA_QI_VXO22_EN, MT6351_PMIC_DA_QI_VXO22_EN_ADDR, + MT6351_PMIC_DA_QI_VXO22_EN_MASK, MT6351_PMIC_DA_QI_VXO22_EN_SHIFT}, + {PMIC_RG_VXO22_OCFB_EN, MT6351_PMIC_RG_VXO22_OCFB_EN_ADDR, + MT6351_PMIC_RG_VXO22_OCFB_EN_MASK, MT6351_PMIC_RG_VXO22_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VXO22_OCFB_EN, MT6351_PMIC_DA_QI_VXO22_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VXO22_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VXO22_OCFB_EN_SHIFT}, + {PMIC_RG_VRF12_MODE_SET, MT6351_PMIC_RG_VRF12_MODE_SET_ADDR, + MT6351_PMIC_RG_VRF12_MODE_SET_MASK, MT6351_PMIC_RG_VRF12_MODE_SET_SHIFT}, + {PMIC_RG_VRF12_EN, MT6351_PMIC_RG_VRF12_EN_ADDR, MT6351_PMIC_RG_VRF12_EN_MASK, + MT6351_PMIC_RG_VRF12_EN_SHIFT}, + {PMIC_RG_VRF12_MODE_CTRL, MT6351_PMIC_RG_VRF12_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VRF12_MODE_CTRL_MASK, MT6351_PMIC_RG_VRF12_MODE_CTRL_SHIFT}, + {PMIC_RG_VRF12_ON_CTRL, MT6351_PMIC_RG_VRF12_ON_CTRL_ADDR, + MT6351_PMIC_RG_VRF12_ON_CTRL_MASK, MT6351_PMIC_RG_VRF12_ON_CTRL_SHIFT}, + {PMIC_RG_VRF12_SRCLK_MODE_SEL, MT6351_PMIC_RG_VRF12_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VRF12_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VRF12_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VRF12_MODE, MT6351_PMIC_DA_QI_VRF12_MODE_ADDR, + MT6351_PMIC_DA_QI_VRF12_MODE_MASK, MT6351_PMIC_DA_QI_VRF12_MODE_SHIFT}, + {PMIC_RG_VRF12_STBTD, MT6351_PMIC_RG_VRF12_STBTD_ADDR, + MT6351_PMIC_RG_VRF12_STBTD_MASK, MT6351_PMIC_RG_VRF12_STBTD_SHIFT}, + {PMIC_RG_VRF12_SRCLK_EN_SEL, MT6351_PMIC_RG_VRF12_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VRF12_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VRF12_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VRF12_STB, MT6351_PMIC_DA_QI_VRF12_STB_ADDR, + MT6351_PMIC_DA_QI_VRF12_STB_MASK, MT6351_PMIC_DA_QI_VRF12_STB_SHIFT}, + {PMIC_DA_QI_VRF12_EN, MT6351_PMIC_DA_QI_VRF12_EN_ADDR, + MT6351_PMIC_DA_QI_VRF12_EN_MASK, MT6351_PMIC_DA_QI_VRF12_EN_SHIFT}, + {PMIC_RG_VRF12_OCFB_EN, MT6351_PMIC_RG_VRF12_OCFB_EN_ADDR, + MT6351_PMIC_RG_VRF12_OCFB_EN_MASK, MT6351_PMIC_RG_VRF12_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VRF12_OCFB_EN, MT6351_PMIC_DA_QI_VRF12_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VRF12_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VRF12_OCFB_EN_SHIFT}, + {PMIC_RG_VRF12_DUMMY_LOAD_EN, MT6351_PMIC_RG_VRF12_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VRF12_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VRF12_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VRF12_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VRF12_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VRF12_DUMMY_LOAD, MT6351_PMIC_RG_VRF12_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VRF12_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VRF12_DUMMY_LOAD, MT6351_PMIC_DA_QI_VRF12_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VRF12_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VRF12_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VA10_MODE_SET, MT6351_PMIC_RG_VA10_MODE_SET_ADDR, + MT6351_PMIC_RG_VA10_MODE_SET_MASK, MT6351_PMIC_RG_VA10_MODE_SET_SHIFT}, + {PMIC_RG_VA10_EN, MT6351_PMIC_RG_VA10_EN_ADDR, MT6351_PMIC_RG_VA10_EN_MASK, + MT6351_PMIC_RG_VA10_EN_SHIFT}, + {PMIC_RG_VA10_MODE_CTRL, MT6351_PMIC_RG_VA10_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VA10_MODE_CTRL_MASK, MT6351_PMIC_RG_VA10_MODE_CTRL_SHIFT}, + {PMIC_RG_VA10_ON_CTRL, MT6351_PMIC_RG_VA10_ON_CTRL_ADDR, + MT6351_PMIC_RG_VA10_ON_CTRL_MASK, MT6351_PMIC_RG_VA10_ON_CTRL_SHIFT}, + {PMIC_RG_VA10_SRCLK_MODE_SEL, MT6351_PMIC_RG_VA10_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VA10_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VA10_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VA10_MODE, MT6351_PMIC_DA_QI_VA10_MODE_ADDR, + MT6351_PMIC_DA_QI_VA10_MODE_MASK, MT6351_PMIC_DA_QI_VA10_MODE_SHIFT}, + {PMIC_RG_VA10_STBTD, MT6351_PMIC_RG_VA10_STBTD_ADDR, + MT6351_PMIC_RG_VA10_STBTD_MASK, MT6351_PMIC_RG_VA10_STBTD_SHIFT}, + {PMIC_RG_VA10_SRCLK_EN_SEL, MT6351_PMIC_RG_VA10_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VA10_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VA10_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VA10_STB, MT6351_PMIC_DA_QI_VA10_STB_ADDR, + MT6351_PMIC_DA_QI_VA10_STB_MASK, MT6351_PMIC_DA_QI_VA10_STB_SHIFT}, + {PMIC_DA_QI_VA10_EN, MT6351_PMIC_DA_QI_VA10_EN_ADDR, + MT6351_PMIC_DA_QI_VA10_EN_MASK, MT6351_PMIC_DA_QI_VA10_EN_SHIFT}, + {PMIC_RG_VA10_OCFB_EN, MT6351_PMIC_RG_VA10_OCFB_EN_ADDR, + MT6351_PMIC_RG_VA10_OCFB_EN_MASK, MT6351_PMIC_RG_VA10_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VA10_OCFB_EN, MT6351_PMIC_DA_QI_VA10_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VA10_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VA10_OCFB_EN_SHIFT}, + {PMIC_RG_VA10_DUMMY_LOAD_EN, MT6351_PMIC_RG_VA10_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VA10_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VA10_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VA10_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VA10_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VA10_DUMMY_LOAD, MT6351_PMIC_RG_VA10_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VA10_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VA10_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VA10_DUMMY_LOAD, MT6351_PMIC_DA_QI_VA10_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VA10_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VA10_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VDRAM_MODE_SET, MT6351_PMIC_RG_VDRAM_MODE_SET_ADDR, + MT6351_PMIC_RG_VDRAM_MODE_SET_MASK, MT6351_PMIC_RG_VDRAM_MODE_SET_SHIFT}, + {PMIC_RG_VDRAM_EN, MT6351_PMIC_RG_VDRAM_EN_ADDR, MT6351_PMIC_RG_VDRAM_EN_MASK, + MT6351_PMIC_RG_VDRAM_EN_SHIFT}, + {PMIC_RG_VDRAM_MODE_CTRL, MT6351_PMIC_RG_VDRAM_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VDRAM_MODE_CTRL_MASK, MT6351_PMIC_RG_VDRAM_MODE_CTRL_SHIFT}, + {PMIC_RG_VDRAM_ON_CTRL, MT6351_PMIC_RG_VDRAM_ON_CTRL_ADDR, + MT6351_PMIC_RG_VDRAM_ON_CTRL_MASK, MT6351_PMIC_RG_VDRAM_ON_CTRL_SHIFT}, + {PMIC_RG_VDRAM_SRCLK_MODE_SEL, MT6351_PMIC_RG_VDRAM_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VDRAM_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VDRAM_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VDRAM_MODE, MT6351_PMIC_DA_QI_VDRAM_MODE_ADDR, + MT6351_PMIC_DA_QI_VDRAM_MODE_MASK, MT6351_PMIC_DA_QI_VDRAM_MODE_SHIFT}, + {PMIC_RG_VDRAM_STBTD, MT6351_PMIC_RG_VDRAM_STBTD_ADDR, + MT6351_PMIC_RG_VDRAM_STBTD_MASK, MT6351_PMIC_RG_VDRAM_STBTD_SHIFT}, + {PMIC_RG_VDRAM_SRCLK_EN_SEL, MT6351_PMIC_RG_VDRAM_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VDRAM_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VDRAM_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VDRAM_STB, MT6351_PMIC_DA_QI_VDRAM_STB_ADDR, + MT6351_PMIC_DA_QI_VDRAM_STB_MASK, MT6351_PMIC_DA_QI_VDRAM_STB_SHIFT}, + {PMIC_DA_QI_VDRAM_EN, MT6351_PMIC_DA_QI_VDRAM_EN_ADDR, + MT6351_PMIC_DA_QI_VDRAM_EN_MASK, MT6351_PMIC_DA_QI_VDRAM_EN_SHIFT}, + {PMIC_RG_VDRAM_OCFB_EN, MT6351_PMIC_RG_VDRAM_OCFB_EN_ADDR, + MT6351_PMIC_RG_VDRAM_OCFB_EN_MASK, MT6351_PMIC_RG_VDRAM_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VDRAM_OCFB_EN, MT6351_PMIC_DA_QI_VDRAM_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VDRAM_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VDRAM_OCFB_EN_SHIFT}, + {PMIC_RG_VDRAM_DUMMY_LOAD_EN, MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VDRAM_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VDRAM_DUMMY_LOAD, MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VDRAM_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VDRAM_DUMMY_LOAD, MT6351_PMIC_DA_QI_VDRAM_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VDRAM_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VDRAM_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VMIPI_MODE_SET, MT6351_PMIC_RG_VMIPI_MODE_SET_ADDR, + MT6351_PMIC_RG_VMIPI_MODE_SET_MASK, MT6351_PMIC_RG_VMIPI_MODE_SET_SHIFT}, + {PMIC_RG_VMIPI_EN, MT6351_PMIC_RG_VMIPI_EN_ADDR, MT6351_PMIC_RG_VMIPI_EN_MASK, + MT6351_PMIC_RG_VMIPI_EN_SHIFT}, + {PMIC_RG_VMIPI_MODE_CTRL, MT6351_PMIC_RG_VMIPI_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VMIPI_MODE_CTRL_MASK, MT6351_PMIC_RG_VMIPI_MODE_CTRL_SHIFT}, + {PMIC_RG_VMIPI_ON_CTRL, MT6351_PMIC_RG_VMIPI_ON_CTRL_ADDR, + MT6351_PMIC_RG_VMIPI_ON_CTRL_MASK, MT6351_PMIC_RG_VMIPI_ON_CTRL_SHIFT}, + {PMIC_RG_VMIPI_SRCLK_MODE_SEL, MT6351_PMIC_RG_VMIPI_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VMIPI_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VMIPI_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VMIPI_MODE, MT6351_PMIC_DA_QI_VMIPI_MODE_ADDR, + MT6351_PMIC_DA_QI_VMIPI_MODE_MASK, MT6351_PMIC_DA_QI_VMIPI_MODE_SHIFT}, + {PMIC_RG_VMIPI_STBTD, MT6351_PMIC_RG_VMIPI_STBTD_ADDR, + MT6351_PMIC_RG_VMIPI_STBTD_MASK, MT6351_PMIC_RG_VMIPI_STBTD_SHIFT}, + {PMIC_RG_VMIPI_SRCLK_EN_SEL, MT6351_PMIC_RG_VMIPI_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VMIPI_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VMIPI_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VMIPI_STB, MT6351_PMIC_DA_QI_VMIPI_STB_ADDR, + MT6351_PMIC_DA_QI_VMIPI_STB_MASK, MT6351_PMIC_DA_QI_VMIPI_STB_SHIFT}, + {PMIC_DA_QI_VMIPI_EN, MT6351_PMIC_DA_QI_VMIPI_EN_ADDR, + MT6351_PMIC_DA_QI_VMIPI_EN_MASK, MT6351_PMIC_DA_QI_VMIPI_EN_SHIFT}, + {PMIC_RG_VMIPI_OCFB_EN, MT6351_PMIC_RG_VMIPI_OCFB_EN_ADDR, + MT6351_PMIC_RG_VMIPI_OCFB_EN_MASK, MT6351_PMIC_RG_VMIPI_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VMIPI_OCFB_EN, MT6351_PMIC_DA_QI_VMIPI_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VMIPI_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VMIPI_OCFB_EN_SHIFT}, + {PMIC_RG_VMIPI_DUMMY_LOAD_EN, MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VMIPI_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VMIPI_DUMMY_LOAD, MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VMIPI_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VMIPI_DUMMY_LOAD, MT6351_PMIC_DA_QI_VMIPI_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VMIPI_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VMIPI_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VGP3_MODE_SET, MT6351_PMIC_RG_VGP3_MODE_SET_ADDR, + MT6351_PMIC_RG_VGP3_MODE_SET_MASK, MT6351_PMIC_RG_VGP3_MODE_SET_SHIFT}, + {PMIC_RG_VGP3_EN, MT6351_PMIC_RG_VGP3_EN_ADDR, MT6351_PMIC_RG_VGP3_EN_MASK, + MT6351_PMIC_RG_VGP3_EN_SHIFT}, + {PMIC_RG_VGP3_MODE_CTRL, MT6351_PMIC_RG_VGP3_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VGP3_MODE_CTRL_MASK, MT6351_PMIC_RG_VGP3_MODE_CTRL_SHIFT}, + {PMIC_RG_VGP3_ON_CTRL, MT6351_PMIC_RG_VGP3_ON_CTRL_ADDR, + MT6351_PMIC_RG_VGP3_ON_CTRL_MASK, MT6351_PMIC_RG_VGP3_ON_CTRL_SHIFT}, + {PMIC_RG_VGP3_SRCLK_MODE_SEL, MT6351_PMIC_RG_VGP3_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VGP3_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VGP3_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VGP3_MODE, MT6351_PMIC_DA_QI_VGP3_MODE_ADDR, + MT6351_PMIC_DA_QI_VGP3_MODE_MASK, MT6351_PMIC_DA_QI_VGP3_MODE_SHIFT}, + {PMIC_RG_VGP3_STBTD, MT6351_PMIC_RG_VGP3_STBTD_ADDR, + MT6351_PMIC_RG_VGP3_STBTD_MASK, MT6351_PMIC_RG_VGP3_STBTD_SHIFT}, + {PMIC_RG_VGP3_SRCLK_EN_SEL, MT6351_PMIC_RG_VGP3_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VGP3_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VGP3_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VGP3_STB, MT6351_PMIC_DA_QI_VGP3_STB_ADDR, + MT6351_PMIC_DA_QI_VGP3_STB_MASK, MT6351_PMIC_DA_QI_VGP3_STB_SHIFT}, + {PMIC_DA_QI_VGP3_EN, MT6351_PMIC_DA_QI_VGP3_EN_ADDR, + MT6351_PMIC_DA_QI_VGP3_EN_MASK, MT6351_PMIC_DA_QI_VGP3_EN_SHIFT}, + {PMIC_RG_VGP3_OCFB_EN, MT6351_PMIC_RG_VGP3_OCFB_EN_ADDR, + MT6351_PMIC_RG_VGP3_OCFB_EN_MASK, MT6351_PMIC_RG_VGP3_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VGP3_OCFB_EN, MT6351_PMIC_DA_QI_VGP3_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VGP3_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VGP3_OCFB_EN_SHIFT}, + {PMIC_RG_VGP3_DUMMY_LOAD_EN, MT6351_PMIC_RG_VGP3_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VGP3_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VGP3_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VGP3_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VGP3_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VGP3_DUMMY_LOAD, MT6351_PMIC_RG_VGP3_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VGP3_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VGP3_DUMMY_LOAD, MT6351_PMIC_DA_QI_VGP3_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VGP3_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VGP3_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VBIF28_MODE_SET, MT6351_PMIC_RG_VBIF28_MODE_SET_ADDR, + MT6351_PMIC_RG_VBIF28_MODE_SET_MASK, MT6351_PMIC_RG_VBIF28_MODE_SET_SHIFT}, + {PMIC_RG_VBIF28_EN, MT6351_PMIC_RG_VBIF28_EN_ADDR, MT6351_PMIC_RG_VBIF28_EN_MASK, + MT6351_PMIC_RG_VBIF28_EN_SHIFT}, + {PMIC_RG_VBIF28_MODE_CTRL, MT6351_PMIC_RG_VBIF28_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VBIF28_MODE_CTRL_MASK, MT6351_PMIC_RG_VBIF28_MODE_CTRL_SHIFT}, + {PMIC_RG_VBIF28_ON_CTRL, MT6351_PMIC_RG_VBIF28_ON_CTRL_ADDR, + MT6351_PMIC_RG_VBIF28_ON_CTRL_MASK, MT6351_PMIC_RG_VBIF28_ON_CTRL_SHIFT}, + {PMIC_RG_VBIF28_SRCLK_MODE_SEL, MT6351_PMIC_RG_VBIF28_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VBIF28_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VBIF28_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VBIF28_MODE, MT6351_PMIC_DA_QI_VBIF28_MODE_ADDR, + MT6351_PMIC_DA_QI_VBIF28_MODE_MASK, MT6351_PMIC_DA_QI_VBIF28_MODE_SHIFT}, + {PMIC_RG_VBIF28_STBTD, MT6351_PMIC_RG_VBIF28_STBTD_ADDR, + MT6351_PMIC_RG_VBIF28_STBTD_MASK, MT6351_PMIC_RG_VBIF28_STBTD_SHIFT}, + {PMIC_RG_VBIF28_SRCLK_EN_SEL, MT6351_PMIC_RG_VBIF28_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VBIF28_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VBIF28_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VBIF28_STB, MT6351_PMIC_DA_QI_VBIF28_STB_ADDR, + MT6351_PMIC_DA_QI_VBIF28_STB_MASK, MT6351_PMIC_DA_QI_VBIF28_STB_SHIFT}, + {PMIC_DA_QI_VBIF28_EN, MT6351_PMIC_DA_QI_VBIF28_EN_ADDR, + MT6351_PMIC_DA_QI_VBIF28_EN_MASK, MT6351_PMIC_DA_QI_VBIF28_EN_SHIFT}, + {PMIC_RG_VBIF28_OCFB_EN, MT6351_PMIC_RG_VBIF28_OCFB_EN_ADDR, + MT6351_PMIC_RG_VBIF28_OCFB_EN_MASK, MT6351_PMIC_RG_VBIF28_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VBIF28_OCFB_EN, MT6351_PMIC_DA_QI_VBIF28_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VBIF28_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VBIF28_OCFB_EN_SHIFT}, + {PMIC_RG_VBIF28_DUMMY_LOAD_EN, MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VBIF28_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VBIF28_DUMMY_LOAD, MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VBIF28_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VBIF28_DUMMY_LOAD, MT6351_PMIC_DA_QI_VBIF28_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VBIF28_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VBIF28_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VEFUSE_MODE_SET, MT6351_PMIC_RG_VEFUSE_MODE_SET_ADDR, + MT6351_PMIC_RG_VEFUSE_MODE_SET_MASK, MT6351_PMIC_RG_VEFUSE_MODE_SET_SHIFT}, + {PMIC_RG_VEFUSE_EN, MT6351_PMIC_RG_VEFUSE_EN_ADDR, MT6351_PMIC_RG_VEFUSE_EN_MASK, + MT6351_PMIC_RG_VEFUSE_EN_SHIFT}, + {PMIC_RG_VEFUSE_MODE_CTRL, MT6351_PMIC_RG_VEFUSE_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VEFUSE_MODE_CTRL_MASK, MT6351_PMIC_RG_VEFUSE_MODE_CTRL_SHIFT}, + {PMIC_RG_VEFUSE_SRCLK_MODE_SEL, MT6351_PMIC_RG_VEFUSE_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VEFUSE_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VEFUSE_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VEFUSE_MODE, MT6351_PMIC_DA_QI_VEFUSE_MODE_ADDR, + MT6351_PMIC_DA_QI_VEFUSE_MODE_MASK, MT6351_PMIC_DA_QI_VEFUSE_MODE_SHIFT}, + {PMIC_RG_VEFUSE_STBTD, MT6351_PMIC_RG_VEFUSE_STBTD_ADDR, + MT6351_PMIC_RG_VEFUSE_STBTD_MASK, MT6351_PMIC_RG_VEFUSE_STBTD_SHIFT}, + {PMIC_DA_QI_VEFUSE_STB, MT6351_PMIC_DA_QI_VEFUSE_STB_ADDR, + MT6351_PMIC_DA_QI_VEFUSE_STB_MASK, MT6351_PMIC_DA_QI_VEFUSE_STB_SHIFT}, + {PMIC_DA_QI_VEFUSE_EN, MT6351_PMIC_DA_QI_VEFUSE_EN_ADDR, + MT6351_PMIC_DA_QI_VEFUSE_EN_MASK, MT6351_PMIC_DA_QI_VEFUSE_EN_SHIFT}, + {PMIC_RG_VEFUSE_OCFB_EN, MT6351_PMIC_RG_VEFUSE_OCFB_EN_ADDR, + MT6351_PMIC_RG_VEFUSE_OCFB_EN_MASK, MT6351_PMIC_RG_VEFUSE_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VEFUSE_OCFB_EN, MT6351_PMIC_DA_QI_VEFUSE_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VEFUSE_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VEFUSE_OCFB_EN_SHIFT}, + {PMIC_RG_VEFUSE_DUMMY_LOAD_EN, MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VEFUSE_DUMMY_LOAD, MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VEFUSE_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VEFUSE_DUMMY_LOAD, MT6351_PMIC_DA_QI_VEFUSE_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VEFUSE_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VEFUSE_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCN33_MODE_SET, MT6351_PMIC_RG_VCN33_MODE_SET_ADDR, + MT6351_PMIC_RG_VCN33_MODE_SET_MASK, MT6351_PMIC_RG_VCN33_MODE_SET_SHIFT}, + {PMIC_RG_VCN33_MODE_CTRL, MT6351_PMIC_RG_VCN33_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VCN33_MODE_CTRL_MASK, MT6351_PMIC_RG_VCN33_MODE_CTRL_SHIFT}, + {PMIC_RG_VCN33_SRCLK_MODE_SEL, MT6351_PMIC_RG_VCN33_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VCN33_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VCN33_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VCN33_MODE, MT6351_PMIC_DA_QI_VCN33_MODE_ADDR, + MT6351_PMIC_DA_QI_VCN33_MODE_MASK, MT6351_PMIC_DA_QI_VCN33_MODE_SHIFT}, + {PMIC_RG_VCN33_STBTD, MT6351_PMIC_RG_VCN33_STBTD_ADDR, + MT6351_PMIC_RG_VCN33_STBTD_MASK, MT6351_PMIC_RG_VCN33_STBTD_SHIFT}, + {PMIC_DA_QI_VCN33_STB, MT6351_PMIC_DA_QI_VCN33_STB_ADDR, + MT6351_PMIC_DA_QI_VCN33_STB_MASK, MT6351_PMIC_DA_QI_VCN33_STB_SHIFT}, + {PMIC_DA_QI_VCN33_EN, MT6351_PMIC_DA_QI_VCN33_EN_ADDR, + MT6351_PMIC_DA_QI_VCN33_EN_MASK, MT6351_PMIC_DA_QI_VCN33_EN_SHIFT}, + {PMIC_RG_VCN33_OCFB_EN, MT6351_PMIC_RG_VCN33_OCFB_EN_ADDR, + MT6351_PMIC_RG_VCN33_OCFB_EN_MASK, MT6351_PMIC_RG_VCN33_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VCN33_OCFB_EN, MT6351_PMIC_DA_QI_VCN33_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VCN33_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VCN33_OCFB_EN_SHIFT}, + {PMIC_RG_VCN33_DUMMY_LOAD_EN, MT6351_PMIC_RG_VCN33_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VCN33_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VCN33_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VCN33_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VCN33_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VCN33_DUMMY_LOAD, MT6351_PMIC_RG_VCN33_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VCN33_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VCN33_DUMMY_LOAD, MT6351_PMIC_DA_QI_VCN33_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VCN33_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VCN33_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VCN33_EN_BT, MT6351_PMIC_RG_VCN33_EN_BT_ADDR, + MT6351_PMIC_RG_VCN33_EN_BT_MASK, MT6351_PMIC_RG_VCN33_EN_BT_SHIFT}, + {PMIC_RG_VCN33_ON_CTRL_BT, MT6351_PMIC_RG_VCN33_ON_CTRL_BT_ADDR, + MT6351_PMIC_RG_VCN33_ON_CTRL_BT_MASK, MT6351_PMIC_RG_VCN33_ON_CTRL_BT_SHIFT}, + {PMIC_RG_VCN33_SRCLK_EN_SEL_BT, MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_BT_ADDR, + MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_BT_MASK, MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_BT_SHIFT}, + {PMIC_RG_VCN33_EN_WIFI, MT6351_PMIC_RG_VCN33_EN_WIFI_ADDR, + MT6351_PMIC_RG_VCN33_EN_WIFI_MASK, MT6351_PMIC_RG_VCN33_EN_WIFI_SHIFT}, + {PMIC_RG_VCN33_ON_CTRL_WIFI, MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI_ADDR, + MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI_MASK, MT6351_PMIC_RG_VCN33_ON_CTRL_WIFI_SHIFT}, + {PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI, MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI_ADDR, + MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI_MASK, + MT6351_PMIC_RG_VCN33_SRCLK_EN_SEL_WIFI_SHIFT}, + {PMIC_RG_VLDO28_MODE_SET, MT6351_PMIC_RG_VLDO28_MODE_SET_ADDR, + MT6351_PMIC_RG_VLDO28_MODE_SET_MASK, MT6351_PMIC_RG_VLDO28_MODE_SET_SHIFT}, + {PMIC_RG_VLDO28_MODE_CTRL, MT6351_PMIC_RG_VLDO28_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VLDO28_MODE_CTRL_MASK, MT6351_PMIC_RG_VLDO28_MODE_CTRL_SHIFT}, + {PMIC_RG_VLDO28_ON_CTRL, MT6351_PMIC_RG_VLDO28_ON_CTRL_ADDR, + MT6351_PMIC_RG_VLDO28_ON_CTRL_MASK, MT6351_PMIC_RG_VLDO28_ON_CTRL_SHIFT}, + {PMIC_RG_VLDO28_SRCLK_MODE_SEL, MT6351_PMIC_RG_VLDO28_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VLDO28_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VLDO28_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VLDO28_MODE, MT6351_PMIC_DA_QI_VLDO28_MODE_ADDR, + MT6351_PMIC_DA_QI_VLDO28_MODE_MASK, MT6351_PMIC_DA_QI_VLDO28_MODE_SHIFT}, + {PMIC_RG_VLDO28_STBTD, MT6351_PMIC_RG_VLDO28_STBTD_ADDR, + MT6351_PMIC_RG_VLDO28_STBTD_MASK, MT6351_PMIC_RG_VLDO28_STBTD_SHIFT}, + {PMIC_DA_QI_VLDO28_STB, MT6351_PMIC_DA_QI_VLDO28_STB_ADDR, + MT6351_PMIC_DA_QI_VLDO28_STB_MASK, MT6351_PMIC_DA_QI_VLDO28_STB_SHIFT}, + {PMIC_DA_QI_VLDO28_EN, MT6351_PMIC_DA_QI_VLDO28_EN_ADDR, + MT6351_PMIC_DA_QI_VLDO28_EN_MASK, MT6351_PMIC_DA_QI_VLDO28_EN_SHIFT}, + {PMIC_RG_VLDO28_OCFB_EN, MT6351_PMIC_RG_VLDO28_OCFB_EN_ADDR, + MT6351_PMIC_RG_VLDO28_OCFB_EN_MASK, MT6351_PMIC_RG_VLDO28_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VLDO28_OCFB_EN, MT6351_PMIC_DA_QI_VLDO28_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VLDO28_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VLDO28_OCFB_EN_SHIFT}, + {PMIC_RG_VLDO28_DUMMY_LOAD_EN, MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VLDO28_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VLDO28_DUMMY_LOAD, MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VLDO28_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VLDO28_DUMMY_LOAD, MT6351_PMIC_DA_QI_VLDO28_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VLDO28_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VLDO28_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VLDO28_EN_0, MT6351_PMIC_RG_VLDO28_EN_0_ADDR, + MT6351_PMIC_RG_VLDO28_EN_0_MASK, MT6351_PMIC_RG_VLDO28_EN_0_SHIFT}, + {PMIC_RG_VLDO28_ON_CTRL_0, MT6351_PMIC_RG_VLDO28_ON_CTRL_0_ADDR, + MT6351_PMIC_RG_VLDO28_ON_CTRL_0_MASK, MT6351_PMIC_RG_VLDO28_ON_CTRL_0_SHIFT}, + {PMIC_RG_VLDO28_SRCLK_EN_SEL_0, MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_0_ADDR, + MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_0_MASK, MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_0_SHIFT}, + {PMIC_RG_VLDO28_EN_1, MT6351_PMIC_RG_VLDO28_EN_1_ADDR, + MT6351_PMIC_RG_VLDO28_EN_1_MASK, MT6351_PMIC_RG_VLDO28_EN_1_SHIFT}, + {PMIC_RG_VLDO28_ON_CTRL_1, MT6351_PMIC_RG_VLDO28_ON_CTRL_1_ADDR, + MT6351_PMIC_RG_VLDO28_ON_CTRL_1_MASK, MT6351_PMIC_RG_VLDO28_ON_CTRL_1_SHIFT}, + {PMIC_RG_VLDO28_SRCLK_EN_SEL_1, MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_1_ADDR, + MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_1_MASK, MT6351_PMIC_RG_VLDO28_SRCLK_EN_SEL_1_SHIFT}, + {PMIC_RG_LDO_RSV1, MT6351_PMIC_RG_LDO_RSV1_ADDR, MT6351_PMIC_RG_LDO_RSV1_MASK, + MT6351_PMIC_RG_LDO_RSV1_SHIFT}, + {PMIC_RG_LDO_RSV0, MT6351_PMIC_RG_LDO_RSV0_ADDR, MT6351_PMIC_RG_LDO_RSV0_MASK, + MT6351_PMIC_RG_LDO_RSV0_SHIFT}, + {PMIC_RG_LDO_RSV2, MT6351_PMIC_RG_LDO_RSV2_ADDR, MT6351_PMIC_RG_LDO_RSV2_MASK, + MT6351_PMIC_RG_LDO_RSV2_SHIFT}, + {PMIC_RG_VMC_MODE_SET, MT6351_PMIC_RG_VMC_MODE_SET_ADDR, + MT6351_PMIC_RG_VMC_MODE_SET_MASK, MT6351_PMIC_RG_VMC_MODE_SET_SHIFT}, + {PMIC_RG_VMC_EN, MT6351_PMIC_RG_VMC_EN_ADDR, MT6351_PMIC_RG_VMC_EN_MASK, + MT6351_PMIC_RG_VMC_EN_SHIFT}, + {PMIC_RG_VMC_MODE_CTRL, MT6351_PMIC_RG_VMC_MODE_CTRL_ADDR, + MT6351_PMIC_RG_VMC_MODE_CTRL_MASK, MT6351_PMIC_RG_VMC_MODE_CTRL_SHIFT}, + {PMIC_RG_VMC_ON_CTRL, MT6351_PMIC_RG_VMC_ON_CTRL_ADDR, + MT6351_PMIC_RG_VMC_ON_CTRL_MASK, MT6351_PMIC_RG_VMC_ON_CTRL_SHIFT}, + {PMIC_RG_VMC_SRCLK_MODE_SEL, MT6351_PMIC_RG_VMC_SRCLK_MODE_SEL_ADDR, + MT6351_PMIC_RG_VMC_SRCLK_MODE_SEL_MASK, MT6351_PMIC_RG_VMC_SRCLK_MODE_SEL_SHIFT}, + {PMIC_DA_QI_VMC_MODE, MT6351_PMIC_DA_QI_VMC_MODE_ADDR, + MT6351_PMIC_DA_QI_VMC_MODE_MASK, MT6351_PMIC_DA_QI_VMC_MODE_SHIFT}, + {PMIC_RG_VMC_STBTD, MT6351_PMIC_RG_VMC_STBTD_ADDR, MT6351_PMIC_RG_VMC_STBTD_MASK, + MT6351_PMIC_RG_VMC_STBTD_SHIFT}, + {PMIC_RG_VMC_SRCLK_EN_SEL, MT6351_PMIC_RG_VMC_SRCLK_EN_SEL_ADDR, + MT6351_PMIC_RG_VMC_SRCLK_EN_SEL_MASK, MT6351_PMIC_RG_VMC_SRCLK_EN_SEL_SHIFT}, + {PMIC_DA_QI_VMC_STB, MT6351_PMIC_DA_QI_VMC_STB_ADDR, + MT6351_PMIC_DA_QI_VMC_STB_MASK, MT6351_PMIC_DA_QI_VMC_STB_SHIFT}, + {PMIC_DA_QI_VMC_EN, MT6351_PMIC_DA_QI_VMC_EN_ADDR, MT6351_PMIC_DA_QI_VMC_EN_MASK, + MT6351_PMIC_DA_QI_VMC_EN_SHIFT}, + {PMIC_RG_VMC_OCFB_EN, MT6351_PMIC_RG_VMC_OCFB_EN_ADDR, + MT6351_PMIC_RG_VMC_OCFB_EN_MASK, MT6351_PMIC_RG_VMC_OCFB_EN_SHIFT}, + {PMIC_DA_QI_VMC_OCFB_EN, MT6351_PMIC_DA_QI_VMC_OCFB_EN_ADDR, + MT6351_PMIC_DA_QI_VMC_OCFB_EN_MASK, MT6351_PMIC_DA_QI_VMC_OCFB_EN_SHIFT}, + {PMIC_RG_VMC_DUMMY_LOAD_EN, MT6351_PMIC_RG_VMC_DUMMY_LOAD_EN_ADDR, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_EN_MASK, MT6351_PMIC_RG_VMC_DUMMY_LOAD_EN_SHIFT}, + {PMIC_RG_VMC_DUMMY_LOAD_CTRL, MT6351_PMIC_RG_VMC_DUMMY_LOAD_CTRL_ADDR, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_CTRL_MASK, MT6351_PMIC_RG_VMC_DUMMY_LOAD_CTRL_SHIFT}, + {PMIC_RG_VMC_DUMMY_LOAD, MT6351_PMIC_RG_VMC_DUMMY_LOAD_ADDR, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_MASK, MT6351_PMIC_RG_VMC_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL_ADDR, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL_MASK, + MT6351_PMIC_RG_VMC_DUMMY_LOAD_SRCLKEN_SEL_SHIFT}, + {PMIC_DA_QI_VMC_DUMMY_LOAD, MT6351_PMIC_DA_QI_VMC_DUMMY_LOAD_ADDR, + MT6351_PMIC_DA_QI_VMC_DUMMY_LOAD_MASK, MT6351_PMIC_DA_QI_VMC_DUMMY_LOAD_SHIFT}, + {PMIC_RG_VMC_TRANS_EN, MT6351_PMIC_RG_VMC_TRANS_EN_ADDR, + MT6351_PMIC_RG_VMC_TRANS_EN_MASK, MT6351_PMIC_RG_VMC_TRANS_EN_SHIFT}, + {PMIC_RG_VMC_TRANS_CTRL, MT6351_PMIC_RG_VMC_TRANS_CTRL_ADDR, + MT6351_PMIC_RG_VMC_TRANS_CTRL_MASK, MT6351_PMIC_RG_VMC_TRANS_CTRL_SHIFT}, + {PMIC_RG_VMC_TRANS_ONCE, MT6351_PMIC_RG_VMC_TRANS_ONCE_ADDR, + MT6351_PMIC_RG_VMC_TRANS_ONCE_MASK, MT6351_PMIC_RG_VMC_TRANS_ONCE_SHIFT}, + {PMIC_RG_VMC_INT_DIS_SEL, MT6351_PMIC_RG_VMC_INT_DIS_SEL_ADDR, + MT6351_PMIC_RG_VMC_INT_DIS_SEL_MASK, MT6351_PMIC_RG_VMC_INT_DIS_SEL_SHIFT}, + {PMIC_DA_QI_VMC_INT_DIS, MT6351_PMIC_DA_QI_VMC_INT_DIS_ADDR, + MT6351_PMIC_DA_QI_VMC_INT_DIS_MASK, MT6351_PMIC_DA_QI_VMC_INT_DIS_SHIFT}, + {PMIC_RG_LDO_MANUAL_OFS_SEL, MT6351_PMIC_RG_LDO_MANUAL_OFS_SEL_ADDR, + MT6351_PMIC_RG_LDO_MANUAL_OFS_SEL_MASK, MT6351_PMIC_RG_LDO_MANUAL_OFS_SEL_SHIFT}, + {PMIC_RG_LDO_MANUAL_OFS_EN, MT6351_PMIC_RG_LDO_MANUAL_OFS_EN_ADDR, + MT6351_PMIC_RG_LDO_MANUAL_OFS_EN_MASK, MT6351_PMIC_RG_LDO_MANUAL_OFS_EN_SHIFT}, + {PMIC_RG_LDO_CALI_RSV, MT6351_PMIC_RG_LDO_CALI_RSV_ADDR, + MT6351_PMIC_RG_LDO_CALI_RSV_MASK, MT6351_PMIC_RG_LDO_CALI_RSV_SHIFT}, + {PMIC_RG_LDO_CALI_MODE_SEL, MT6351_PMIC_RG_LDO_CALI_MODE_SEL_ADDR, + MT6351_PMIC_RG_LDO_CALI_MODE_SEL_MASK, MT6351_PMIC_RG_LDO_CALI_MODE_SEL_SHIFT}, + {PMIC_RG_LDO_MANUAL_MODE, MT6351_PMIC_RG_LDO_MANUAL_MODE_ADDR, + MT6351_PMIC_RG_LDO_MANUAL_MODE_MASK, MT6351_PMIC_RG_LDO_MANUAL_MODE_SHIFT}, + {PMIC_RG_LDO_AUTO_START, MT6351_PMIC_RG_LDO_AUTO_START_ADDR, + MT6351_PMIC_RG_LDO_AUTO_START_MASK, MT6351_PMIC_RG_LDO_AUTO_START_SHIFT}, + {PMIC_RG_LDO_CALI_CLR, MT6351_PMIC_RG_LDO_CALI_CLR_ADDR, + MT6351_PMIC_RG_LDO_CALI_CLR_MASK, MT6351_PMIC_RG_LDO_CALI_CLR_SHIFT}, + {PMIC_LDO_CALI_INC_COUNT, MT6351_PMIC_LDO_CALI_INC_COUNT_ADDR, + MT6351_PMIC_LDO_CALI_INC_COUNT_MASK, MT6351_PMIC_LDO_CALI_INC_COUNT_SHIFT}, + {PMIC_LDO_K_START, MT6351_PMIC_LDO_K_START_ADDR, MT6351_PMIC_LDO_K_START_MASK, + MT6351_PMIC_LDO_K_START_SHIFT}, + {PMIC_LDO_CALI_DONE, MT6351_PMIC_LDO_CALI_DONE_ADDR, + MT6351_PMIC_LDO_CALI_DONE_MASK, MT6351_PMIC_LDO_CALI_DONE_SHIFT}, + {PMIC_LDO_CALI_CNT, MT6351_PMIC_LDO_CALI_CNT_ADDR, MT6351_PMIC_LDO_CALI_CNT_MASK, + MT6351_PMIC_LDO_CALI_CNT_SHIFT}, + {PMIC_LDO_CALI_EFUSE_EN, MT6351_PMIC_LDO_CALI_EFUSE_EN_ADDR, + MT6351_PMIC_LDO_CALI_EFUSE_EN_MASK, MT6351_PMIC_LDO_CALI_EFUSE_EN_SHIFT}, + {PMIC_DA_QI_VIO18_OFS_CAL_EN, MT6351_PMIC_DA_QI_VIO18_OFS_CAL_EN_ADDR, + MT6351_PMIC_DA_QI_VIO18_OFS_CAL_EN_MASK, MT6351_PMIC_DA_QI_VIO18_OFS_CAL_EN_SHIFT}, + {PMIC_AD_QI_VIO18_CAL_INDI, MT6351_PMIC_AD_QI_VIO18_CAL_INDI_ADDR, + MT6351_PMIC_AD_QI_VIO18_CAL_INDI_MASK, MT6351_PMIC_AD_QI_VIO18_CAL_INDI_SHIFT}, + {PMIC_DA_QI_VIO18_OFS_SEL, MT6351_PMIC_DA_QI_VIO18_OFS_SEL_ADDR, + MT6351_PMIC_DA_QI_VIO18_OFS_SEL_MASK, MT6351_PMIC_DA_QI_VIO18_OFS_SEL_SHIFT}, + {PMIC_LDO_DEGTD_SEL, MT6351_PMIC_LDO_DEGTD_SEL_ADDR, + MT6351_PMIC_LDO_DEGTD_SEL_MASK, MT6351_PMIC_LDO_DEGTD_SEL_SHIFT}, + {PMIC_RG_VRTC_EN, MT6351_PMIC_RG_VRTC_EN_ADDR, MT6351_PMIC_RG_VRTC_EN_MASK, + MT6351_PMIC_RG_VRTC_EN_SHIFT}, + {PMIC_DA_QI_VRTC_EN, MT6351_PMIC_DA_QI_VRTC_EN_ADDR, + MT6351_PMIC_DA_QI_VRTC_EN_MASK, MT6351_PMIC_DA_QI_VRTC_EN_SHIFT}, + {PMIC_RG_ALDO_RESEV, MT6351_PMIC_RG_ALDO_RESEV_ADDR, + MT6351_PMIC_RG_ALDO_RESEV_MASK, MT6351_PMIC_RG_ALDO_RESEV_SHIFT}, + {PMIC_RG_DLDO_RESEV, MT6351_PMIC_RG_DLDO_RESEV_ADDR, + MT6351_PMIC_RG_DLDO_RESEV_MASK, MT6351_PMIC_RG_DLDO_RESEV_SHIFT}, + {PMIC_RG_SLDO_RESEV195, MT6351_PMIC_RG_SLDO_RESEV195_ADDR, + MT6351_PMIC_RG_SLDO_RESEV195_MASK, MT6351_PMIC_RG_SLDO_RESEV195_SHIFT}, + {PMIC_RG_SLDO_2_RESEV195, MT6351_PMIC_RG_SLDO_2_RESEV195_ADDR, + MT6351_PMIC_RG_SLDO_2_RESEV195_MASK, MT6351_PMIC_RG_SLDO_2_RESEV195_SHIFT}, + {PMIC_RG_SLDO_RESEV135, MT6351_PMIC_RG_SLDO_RESEV135_ADDR, + MT6351_PMIC_RG_SLDO_RESEV135_MASK, MT6351_PMIC_RG_SLDO_RESEV135_SHIFT}, + {PMIC_RG_SLDO_2_RESEV135, MT6351_PMIC_RG_SLDO_2_RESEV135_ADDR, + MT6351_PMIC_RG_SLDO_2_RESEV135_MASK, MT6351_PMIC_RG_SLDO_2_RESEV135_SHIFT}, + {PMIC_RG_VXO22_CAL, MT6351_PMIC_RG_VXO22_CAL_ADDR, MT6351_PMIC_RG_VXO22_CAL_MASK, + MT6351_PMIC_RG_VXO22_CAL_SHIFT}, + {PMIC_RG_VXO22_VOSEL, MT6351_PMIC_RG_VXO22_VOSEL_ADDR, + MT6351_PMIC_RG_VXO22_VOSEL_MASK, MT6351_PMIC_RG_VXO22_VOSEL_SHIFT}, + {PMIC_RG_VXO22_NDIS_EN, MT6351_PMIC_RG_VXO22_NDIS_EN_ADDR, + MT6351_PMIC_RG_VXO22_NDIS_EN_MASK, MT6351_PMIC_RG_VXO22_NDIS_EN_SHIFT}, + {PMIC_RG_VTCXO28_CAL, MT6351_PMIC_RG_VTCXO28_CAL_ADDR, + MT6351_PMIC_RG_VTCXO28_CAL_MASK, MT6351_PMIC_RG_VTCXO28_CAL_SHIFT}, + {PMIC_RG_VTCXO28_VOSEL, MT6351_PMIC_RG_VTCXO28_VOSEL_ADDR, + MT6351_PMIC_RG_VTCXO28_VOSEL_MASK, MT6351_PMIC_RG_VTCXO28_VOSEL_SHIFT}, + {PMIC_RG_VTCXO28_NDIS_EN, MT6351_PMIC_RG_VTCXO28_NDIS_EN_ADDR, + MT6351_PMIC_RG_VTCXO28_NDIS_EN_MASK, MT6351_PMIC_RG_VTCXO28_NDIS_EN_SHIFT}, + {PMIC_RG_VTCXO24_CAL, MT6351_PMIC_RG_VTCXO24_CAL_ADDR, + MT6351_PMIC_RG_VTCXO24_CAL_MASK, MT6351_PMIC_RG_VTCXO24_CAL_SHIFT}, + {PMIC_RG_VTCXO24_VOSEL, MT6351_PMIC_RG_VTCXO24_VOSEL_ADDR, + MT6351_PMIC_RG_VTCXO24_VOSEL_MASK, MT6351_PMIC_RG_VTCXO24_VOSEL_SHIFT}, + {PMIC_RG_VTCXO24_NDIS_EN, MT6351_PMIC_RG_VTCXO24_NDIS_EN_ADDR, + MT6351_PMIC_RG_VTCXO24_NDIS_EN_MASK, MT6351_PMIC_RG_VTCXO24_NDIS_EN_SHIFT}, + {PMIC_RG_VBIF28_CAL, MT6351_PMIC_RG_VBIF28_CAL_ADDR, + MT6351_PMIC_RG_VBIF28_CAL_MASK, MT6351_PMIC_RG_VBIF28_CAL_SHIFT}, + {PMIC_RG_VBIF28_VOSEL, MT6351_PMIC_RG_VBIF28_VOSEL_ADDR, + MT6351_PMIC_RG_VBIF28_VOSEL_MASK, MT6351_PMIC_RG_VBIF28_VOSEL_SHIFT}, + {PMIC_RG_VBIF28_NDIS_EN, MT6351_PMIC_RG_VBIF28_NDIS_EN_ADDR, + MT6351_PMIC_RG_VBIF28_NDIS_EN_MASK, MT6351_PMIC_RG_VBIF28_NDIS_EN_SHIFT}, + {PMIC_RG_VCN28_CAL, MT6351_PMIC_RG_VCN28_CAL_ADDR, MT6351_PMIC_RG_VCN28_CAL_MASK, + MT6351_PMIC_RG_VCN28_CAL_SHIFT}, + {PMIC_RG_VCN28_VOSEL, MT6351_PMIC_RG_VCN28_VOSEL_ADDR, + MT6351_PMIC_RG_VCN28_VOSEL_MASK, MT6351_PMIC_RG_VCN28_VOSEL_SHIFT}, + {PMIC_RG_VCN28_NDIS_EN, MT6351_PMIC_RG_VCN28_NDIS_EN_ADDR, + MT6351_PMIC_RG_VCN28_NDIS_EN_MASK, MT6351_PMIC_RG_VCN28_NDIS_EN_SHIFT}, + {PMIC_RG_VMCH_CAL, MT6351_PMIC_RG_VMCH_CAL_ADDR, MT6351_PMIC_RG_VMCH_CAL_MASK, + MT6351_PMIC_RG_VMCH_CAL_SHIFT}, + {PMIC_RG_VMCH_VOSEL, MT6351_PMIC_RG_VMCH_VOSEL_ADDR, + MT6351_PMIC_RG_VMCH_VOSEL_MASK, MT6351_PMIC_RG_VMCH_VOSEL_SHIFT}, + {PMIC_RG_VMCH_NDIS_EN, MT6351_PMIC_RG_VMCH_NDIS_EN_ADDR, + MT6351_PMIC_RG_VMCH_NDIS_EN_MASK, MT6351_PMIC_RG_VMCH_NDIS_EN_SHIFT}, + {PMIC_RG_VMCH_OC_TRIM, MT6351_PMIC_RG_VMCH_OC_TRIM_ADDR, + MT6351_PMIC_RG_VMCH_OC_TRIM_MASK, MT6351_PMIC_RG_VMCH_OC_TRIM_SHIFT}, + {PMIC_RG_VMCH_N2LP_EHC_V18, MT6351_PMIC_RG_VMCH_N2LP_EHC_V18_ADDR, + MT6351_PMIC_RG_VMCH_N2LP_EHC_V18_MASK, MT6351_PMIC_RG_VMCH_N2LP_EHC_V18_SHIFT}, + {PMIC_RG_VEMC_CAL, MT6351_PMIC_RG_VEMC_CAL_ADDR, MT6351_PMIC_RG_VEMC_CAL_MASK, + MT6351_PMIC_RG_VEMC_CAL_SHIFT}, + {PMIC_RG_VEMC_VOSEL, MT6351_PMIC_RG_VEMC_VOSEL_ADDR, + MT6351_PMIC_RG_VEMC_VOSEL_MASK, MT6351_PMIC_RG_VEMC_VOSEL_SHIFT}, + {PMIC_RG_VEMC_NDIS_EN, MT6351_PMIC_RG_VEMC_NDIS_EN_ADDR, + MT6351_PMIC_RG_VEMC_NDIS_EN_MASK, MT6351_PMIC_RG_VEMC_NDIS_EN_SHIFT}, + {PMIC_RG_VEMC_OC_TRIM, MT6351_PMIC_RG_VEMC_OC_TRIM_ADDR, + MT6351_PMIC_RG_VEMC_OC_TRIM_MASK, MT6351_PMIC_RG_VEMC_OC_TRIM_SHIFT}, + {PMIC_RG_VEMC_N2LP_EHC_V18, MT6351_PMIC_RG_VEMC_N2LP_EHC_V18_ADDR, + MT6351_PMIC_RG_VEMC_N2LP_EHC_V18_MASK, MT6351_PMIC_RG_VEMC_N2LP_EHC_V18_SHIFT}, + {PMIC_RG_VCAMA_CAL, MT6351_PMIC_RG_VCAMA_CAL_ADDR, MT6351_PMIC_RG_VCAMA_CAL_MASK, + MT6351_PMIC_RG_VCAMA_CAL_SHIFT}, + {PMIC_RG_VCAMA_VOSEL, MT6351_PMIC_RG_VCAMA_VOSEL_ADDR, + MT6351_PMIC_RG_VCAMA_VOSEL_MASK, MT6351_PMIC_RG_VCAMA_VOSEL_SHIFT}, + {PMIC_RG_VCAMA_NDIS_EN, MT6351_PMIC_RG_VCAMA_NDIS_EN_ADDR, + MT6351_PMIC_RG_VCAMA_NDIS_EN_MASK, MT6351_PMIC_RG_VCAMA_NDIS_EN_SHIFT}, + {PMIC_RG_VCAMA_FBSEL, MT6351_PMIC_RG_VCAMA_FBSEL_ADDR, + MT6351_PMIC_RG_VCAMA_FBSEL_MASK, MT6351_PMIC_RG_VCAMA_FBSEL_SHIFT}, + {PMIC_RG_VCN33_CAL, MT6351_PMIC_RG_VCN33_CAL_ADDR, MT6351_PMIC_RG_VCN33_CAL_MASK, + MT6351_PMIC_RG_VCN33_CAL_SHIFT}, + {PMIC_RG_VCN33_VOSEL, MT6351_PMIC_RG_VCN33_VOSEL_ADDR, + MT6351_PMIC_RG_VCN33_VOSEL_MASK, MT6351_PMIC_RG_VCN33_VOSEL_SHIFT}, + {PMIC_RG_VCN33_NDIS_EN, MT6351_PMIC_RG_VCN33_NDIS_EN_ADDR, + MT6351_PMIC_RG_VCN33_NDIS_EN_MASK, MT6351_PMIC_RG_VCN33_NDIS_EN_SHIFT}, + {PMIC_RG_VCN33_N2LP_EHC_V18, MT6351_PMIC_RG_VCN33_N2LP_EHC_V18_ADDR, + MT6351_PMIC_RG_VCN33_N2LP_EHC_V18_MASK, MT6351_PMIC_RG_VCN33_N2LP_EHC_V18_SHIFT}, + {PMIC_RG_VIO28_CAL, MT6351_PMIC_RG_VIO28_CAL_ADDR, MT6351_PMIC_RG_VIO28_CAL_MASK, + MT6351_PMIC_RG_VIO28_CAL_SHIFT}, + {PMIC_RG_VIO28_VOSEL, MT6351_PMIC_RG_VIO28_VOSEL_ADDR, + MT6351_PMIC_RG_VIO28_VOSEL_MASK, MT6351_PMIC_RG_VIO28_VOSEL_SHIFT}, + {PMIC_RG_VIO28_NDIS_EN, MT6351_PMIC_RG_VIO28_NDIS_EN_ADDR, + MT6351_PMIC_RG_VIO28_NDIS_EN_MASK, MT6351_PMIC_RG_VIO28_NDIS_EN_SHIFT}, + {PMIC_RG_VIO28_LP_HIGH_SPEED_ENB, MT6351_PMIC_RG_VIO28_LP_HIGH_SPEED_ENB_ADDR, + MT6351_PMIC_RG_VIO28_LP_HIGH_SPEED_ENB_MASK, + MT6351_PMIC_RG_VIO28_LP_HIGH_SPEED_ENB_SHIFT}, + {PMIC_RG_VMC_CAL, MT6351_PMIC_RG_VMC_CAL_ADDR, MT6351_PMIC_RG_VMC_CAL_MASK, + MT6351_PMIC_RG_VMC_CAL_SHIFT}, + {PMIC_RG_VMC_VOSEL, MT6351_PMIC_RG_VMC_VOSEL_ADDR, MT6351_PMIC_RG_VMC_VOSEL_MASK, + MT6351_PMIC_RG_VMC_VOSEL_SHIFT}, + {PMIC_RG_VMC_NDIS_EN, MT6351_PMIC_RG_VMC_NDIS_EN_ADDR, + MT6351_PMIC_RG_VMC_NDIS_EN_MASK, MT6351_PMIC_RG_VMC_NDIS_EN_SHIFT}, + {PMIC_RG_VMC_LP_HIGH_SPEED_ENB, MT6351_PMIC_RG_VMC_LP_HIGH_SPEED_ENB_ADDR, + MT6351_PMIC_RG_VMC_LP_HIGH_SPEED_ENB_MASK, MT6351_PMIC_RG_VMC_LP_HIGH_SPEED_ENB_SHIFT}, + {PMIC_RG_VIBR_CAL, MT6351_PMIC_RG_VIBR_CAL_ADDR, MT6351_PMIC_RG_VIBR_CAL_MASK, + MT6351_PMIC_RG_VIBR_CAL_SHIFT}, + {PMIC_RG_VIBR_VOSEL, MT6351_PMIC_RG_VIBR_VOSEL_ADDR, + MT6351_PMIC_RG_VIBR_VOSEL_MASK, MT6351_PMIC_RG_VIBR_VOSEL_SHIFT}, + {PMIC_RG_VIBR_NDIS_EN, MT6351_PMIC_RG_VIBR_NDIS_EN_ADDR, + MT6351_PMIC_RG_VIBR_NDIS_EN_MASK, MT6351_PMIC_RG_VIBR_NDIS_EN_SHIFT}, + {PMIC_RG_VIBR_LP_HIGH_SPEED_ENB, MT6351_PMIC_RG_VIBR_LP_HIGH_SPEED_ENB_ADDR, + MT6351_PMIC_RG_VIBR_LP_HIGH_SPEED_ENB_MASK, MT6351_PMIC_RG_VIBR_LP_HIGH_SPEED_ENB_SHIFT}, + {PMIC_RG_VUSB33_CAL, MT6351_PMIC_RG_VUSB33_CAL_ADDR, + MT6351_PMIC_RG_VUSB33_CAL_MASK, MT6351_PMIC_RG_VUSB33_CAL_SHIFT}, + {PMIC_RG_VUSB33_NDIS_EN, MT6351_PMIC_RG_VUSB33_NDIS_EN_ADDR, + MT6351_PMIC_RG_VUSB33_NDIS_EN_MASK, MT6351_PMIC_RG_VUSB33_NDIS_EN_SHIFT}, + {PMIC_RG_VUSB33_OC_TRIM, MT6351_PMIC_RG_VUSB33_OC_TRIM_ADDR, + MT6351_PMIC_RG_VUSB33_OC_TRIM_MASK, MT6351_PMIC_RG_VUSB33_OC_TRIM_SHIFT}, + {PMIC_RG_VSIM1_CAL, MT6351_PMIC_RG_VSIM1_CAL_ADDR, MT6351_PMIC_RG_VSIM1_CAL_MASK, + MT6351_PMIC_RG_VSIM1_CAL_SHIFT}, + {PMIC_RG_VSIM1_VOSEL, MT6351_PMIC_RG_VSIM1_VOSEL_ADDR, + MT6351_PMIC_RG_VSIM1_VOSEL_MASK, MT6351_PMIC_RG_VSIM1_VOSEL_SHIFT}, + {PMIC_RG_VSIM1_NDIS_EN, MT6351_PMIC_RG_VSIM1_NDIS_EN_ADDR, + MT6351_PMIC_RG_VSIM1_NDIS_EN_MASK, MT6351_PMIC_RG_VSIM1_NDIS_EN_SHIFT}, + {PMIC_RG_VSIM1_STB_CAL, MT6351_PMIC_RG_VSIM1_STB_CAL_ADDR, + MT6351_PMIC_RG_VSIM1_STB_CAL_MASK, MT6351_PMIC_RG_VSIM1_STB_CAL_SHIFT}, + {PMIC_RG_VSIM1_STB_SEL, MT6351_PMIC_RG_VSIM1_STB_SEL_ADDR, + MT6351_PMIC_RG_VSIM1_STB_SEL_MASK, MT6351_PMIC_RG_VSIM1_STB_SEL_SHIFT}, + {PMIC_RG_VSIM1_OC_TRIM, MT6351_PMIC_RG_VSIM1_OC_TRIM_ADDR, + MT6351_PMIC_RG_VSIM1_OC_TRIM_MASK, MT6351_PMIC_RG_VSIM1_OC_TRIM_SHIFT}, + {PMIC_RG_VSIM1_NDIS_EN_INT, MT6351_PMIC_RG_VSIM1_NDIS_EN_INT_ADDR, + MT6351_PMIC_RG_VSIM1_NDIS_EN_INT_MASK, MT6351_PMIC_RG_VSIM1_NDIS_EN_INT_SHIFT}, + {PMIC_RG_EFUSE_SIM1_MODE, MT6351_PMIC_RG_EFUSE_SIM1_MODE_ADDR, + MT6351_PMIC_RG_EFUSE_SIM1_MODE_MASK, MT6351_PMIC_RG_EFUSE_SIM1_MODE_SHIFT}, + {PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB, MT6351_PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB_ADDR, + MT6351_PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB_MASK, + MT6351_PMIC_RG_VSIM1_LP_HIGH_SPEED_ENB_SHIFT}, + {PMIC_RG_VSIM2_CAL, MT6351_PMIC_RG_VSIM2_CAL_ADDR, MT6351_PMIC_RG_VSIM2_CAL_MASK, + MT6351_PMIC_RG_VSIM2_CAL_SHIFT}, + {PMIC_RG_VSIM2_VOSEL, MT6351_PMIC_RG_VSIM2_VOSEL_ADDR, + MT6351_PMIC_RG_VSIM2_VOSEL_MASK, MT6351_PMIC_RG_VSIM2_VOSEL_SHIFT}, + {PMIC_RG_VSIM2_NDIS_EN, MT6351_PMIC_RG_VSIM2_NDIS_EN_ADDR, + MT6351_PMIC_RG_VSIM2_NDIS_EN_MASK, MT6351_PMIC_RG_VSIM2_NDIS_EN_SHIFT}, + {PMIC_RG_VSIM2_STB_CAL, MT6351_PMIC_RG_VSIM2_STB_CAL_ADDR, + MT6351_PMIC_RG_VSIM2_STB_CAL_MASK, MT6351_PMIC_RG_VSIM2_STB_CAL_SHIFT}, + {PMIC_RG_VSIM2_STB_SEL, MT6351_PMIC_RG_VSIM2_STB_SEL_ADDR, + MT6351_PMIC_RG_VSIM2_STB_SEL_MASK, MT6351_PMIC_RG_VSIM2_STB_SEL_SHIFT}, + {PMIC_RG_VSIM2_OC_TRIM, MT6351_PMIC_RG_VSIM2_OC_TRIM_ADDR, + MT6351_PMIC_RG_VSIM2_OC_TRIM_MASK, MT6351_PMIC_RG_VSIM2_OC_TRIM_SHIFT}, + {PMIC_RG_VSIM2_NDIS_EN_INT, MT6351_PMIC_RG_VSIM2_NDIS_EN_INT_ADDR, + MT6351_PMIC_RG_VSIM2_NDIS_EN_INT_MASK, MT6351_PMIC_RG_VSIM2_NDIS_EN_INT_SHIFT}, + {PMIC_RG_EFUSE_VSIM2_MODE, MT6351_PMIC_RG_EFUSE_VSIM2_MODE_ADDR, + MT6351_PMIC_RG_EFUSE_VSIM2_MODE_MASK, MT6351_PMIC_RG_EFUSE_VSIM2_MODE_SHIFT}, + {PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB, MT6351_PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB_ADDR, + MT6351_PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB_MASK, + MT6351_PMIC_RG_VSIM2_LP_HIGH_SPEED_ENB_SHIFT}, + {PMIC_RG_VEFUSE_CAL, MT6351_PMIC_RG_VEFUSE_CAL_ADDR, + MT6351_PMIC_RG_VEFUSE_CAL_MASK, MT6351_PMIC_RG_VEFUSE_CAL_SHIFT}, + {PMIC_RG_VEFUSE_VOSEL, MT6351_PMIC_RG_VEFUSE_VOSEL_ADDR, + MT6351_PMIC_RG_VEFUSE_VOSEL_MASK, MT6351_PMIC_RG_VEFUSE_VOSEL_SHIFT}, + {PMIC_RG_VEFUSE_NDIS_EN, MT6351_PMIC_RG_VEFUSE_NDIS_EN_ADDR, + MT6351_PMIC_RG_VEFUSE_NDIS_EN_MASK, MT6351_PMIC_RG_VEFUSE_NDIS_EN_SHIFT}, + {PMIC_RG_VEFUSE_STB_CAL, MT6351_PMIC_RG_VEFUSE_STB_CAL_ADDR, + MT6351_PMIC_RG_VEFUSE_STB_CAL_MASK, MT6351_PMIC_RG_VEFUSE_STB_CAL_SHIFT}, + {PMIC_RG_VEFUSE_STB_SEL, MT6351_PMIC_RG_VEFUSE_STB_SEL_ADDR, + MT6351_PMIC_RG_VEFUSE_STB_SEL_MASK, MT6351_PMIC_RG_VEFUSE_STB_SEL_SHIFT}, + {PMIC_RG_VEFUSE_OC_TRIM, MT6351_PMIC_RG_VEFUSE_OC_TRIM_ADDR, + MT6351_PMIC_RG_VEFUSE_OC_TRIM_MASK, MT6351_PMIC_RG_VEFUSE_OC_TRIM_SHIFT}, + {PMIC_RG_VEFUSE_NDIS_EN_INT, MT6351_PMIC_RG_VEFUSE_NDIS_EN_INT_ADDR, + MT6351_PMIC_RG_VEFUSE_NDIS_EN_INT_MASK, MT6351_PMIC_RG_VEFUSE_NDIS_EN_INT_SHIFT}, + {PMIC_RG_EFUSE_MODE_1, MT6351_PMIC_RG_EFUSE_MODE_1_ADDR, + MT6351_PMIC_RG_EFUSE_MODE_1_MASK, MT6351_PMIC_RG_EFUSE_MODE_1_SHIFT}, + {PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB, MT6351_PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB_ADDR, + MT6351_PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB_MASK, + MT6351_PMIC_RG_VEFUSE_LP_HIGH_SPEED_ENB_SHIFT}, + {PMIC_RG_VA18_CAL, MT6351_PMIC_RG_VA18_CAL_ADDR, MT6351_PMIC_RG_VA18_CAL_MASK, + MT6351_PMIC_RG_VA18_CAL_SHIFT}, + {PMIC_RG_VA18_VOSEL, MT6351_PMIC_RG_VA18_VOSEL_ADDR, + MT6351_PMIC_RG_VA18_VOSEL_MASK, MT6351_PMIC_RG_VA18_VOSEL_SHIFT}, + {PMIC_RG_VA18_NDIS_EN, MT6351_PMIC_RG_VA18_NDIS_EN_ADDR, + MT6351_PMIC_RG_VA18_NDIS_EN_MASK, MT6351_PMIC_RG_VA18_NDIS_EN_SHIFT}, + {PMIC_RG_VGP3_CAL, MT6351_PMIC_RG_VGP3_CAL_ADDR, MT6351_PMIC_RG_VGP3_CAL_MASK, + MT6351_PMIC_RG_VGP3_CAL_SHIFT}, + {PMIC_RG_VGP3_VOSEL, MT6351_PMIC_RG_VGP3_VOSEL_ADDR, + MT6351_PMIC_RG_VGP3_VOSEL_MASK, MT6351_PMIC_RG_VGP3_VOSEL_SHIFT}, + {PMIC_RG_VGP3_NDIS_EN, MT6351_PMIC_RG_VGP3_NDIS_EN_ADDR, + MT6351_PMIC_RG_VGP3_NDIS_EN_MASK, MT6351_PMIC_RG_VGP3_NDIS_EN_SHIFT}, + {PMIC_RG_VGP3_FT_DNMC_EN, MT6351_PMIC_RG_VGP3_FT_DNMC_EN_ADDR, + MT6351_PMIC_RG_VGP3_FT_DNMC_EN_MASK, MT6351_PMIC_RG_VGP3_FT_DNMC_EN_SHIFT}, + {PMIC_RG_VCAMD_CAL, MT6351_PMIC_RG_VCAMD_CAL_ADDR, MT6351_PMIC_RG_VCAMD_CAL_MASK, + MT6351_PMIC_RG_VCAMD_CAL_SHIFT}, + {PMIC_RG_VCAMD_VOSEL, MT6351_PMIC_RG_VCAMD_VOSEL_ADDR, + MT6351_PMIC_RG_VCAMD_VOSEL_MASK, MT6351_PMIC_RG_VCAMD_VOSEL_SHIFT}, + {PMIC_RG_VCAMD_NDIS_EN, MT6351_PMIC_RG_VCAMD_NDIS_EN_ADDR, + MT6351_PMIC_RG_VCAMD_NDIS_EN_MASK, MT6351_PMIC_RG_VCAMD_NDIS_EN_SHIFT}, + {PMIC_RG_VCAMD_RSV, MT6351_PMIC_RG_VCAMD_RSV_ADDR, MT6351_PMIC_RG_VCAMD_RSV_MASK, + MT6351_PMIC_RG_VCAMD_RSV_SHIFT}, + {PMIC_RG_VCAMD_OC_TRIM, MT6351_PMIC_RG_VCAMD_OC_TRIM_ADDR, + MT6351_PMIC_RG_VCAMD_OC_TRIM_MASK, MT6351_PMIC_RG_VCAMD_OC_TRIM_SHIFT}, + {PMIC_RG_VIO18_CAL, MT6351_PMIC_RG_VIO18_CAL_ADDR, MT6351_PMIC_RG_VIO18_CAL_MASK, + MT6351_PMIC_RG_VIO18_CAL_SHIFT}, + {PMIC_RG_VIO18_NDIS_EN, MT6351_PMIC_RG_VIO18_NDIS_EN_ADDR, + MT6351_PMIC_RG_VIO18_NDIS_EN_MASK, MT6351_PMIC_RG_VIO18_NDIS_EN_SHIFT}, + {PMIC_RG_VIO18_FT_DNMC_EN, MT6351_PMIC_RG_VIO18_FT_DNMC_EN_ADDR, + MT6351_PMIC_RG_VIO18_FT_DNMC_EN_MASK, MT6351_PMIC_RG_VIO18_FT_DNMC_EN_SHIFT}, + {PMIC_RG_VRF18_CAL, MT6351_PMIC_RG_VRF18_CAL_ADDR, MT6351_PMIC_RG_VRF18_CAL_MASK, + MT6351_PMIC_RG_VRF18_CAL_SHIFT}, + {PMIC_RG_VRF18_VOSEL, MT6351_PMIC_RG_VRF18_VOSEL_ADDR, + MT6351_PMIC_RG_VRF18_VOSEL_MASK, MT6351_PMIC_RG_VRF18_VOSEL_SHIFT}, + {PMIC_RG_VRF18_NDIS_EN, MT6351_PMIC_RG_VRF18_NDIS_EN_ADDR, + MT6351_PMIC_RG_VRF18_NDIS_EN_MASK, MT6351_PMIC_RG_VRF18_NDIS_EN_SHIFT}, + {PMIC_RG_VRF18_FT_DNMC_EN, MT6351_PMIC_RG_VRF18_FT_DNMC_EN_ADDR, + MT6351_PMIC_RG_VRF18_FT_DNMC_EN_MASK, MT6351_PMIC_RG_VRF18_FT_DNMC_EN_SHIFT}, + {PMIC_RG_VRF12_CAL, MT6351_PMIC_RG_VRF12_CAL_ADDR, MT6351_PMIC_RG_VRF12_CAL_MASK, + MT6351_PMIC_RG_VRF12_CAL_SHIFT}, + {PMIC_RG_VRF12_VOSEL, MT6351_PMIC_RG_VRF12_VOSEL_ADDR, + MT6351_PMIC_RG_VRF12_VOSEL_MASK, MT6351_PMIC_RG_VRF12_VOSEL_SHIFT}, + {PMIC_RG_VRF12_NDIS_EN, MT6351_PMIC_RG_VRF12_NDIS_EN_ADDR, + MT6351_PMIC_RG_VRF12_NDIS_EN_MASK, MT6351_PMIC_RG_VRF12_NDIS_EN_SHIFT}, + {PMIC_RG_VRF12_STB_SEL, MT6351_PMIC_RG_VRF12_STB_SEL_ADDR, + MT6351_PMIC_RG_VRF12_STB_SEL_MASK, MT6351_PMIC_RG_VRF12_STB_SEL_SHIFT}, + {PMIC_RG_VA10_CAL, MT6351_PMIC_RG_VA10_CAL_ADDR, MT6351_PMIC_RG_VA10_CAL_MASK, + MT6351_PMIC_RG_VA10_CAL_SHIFT}, + {PMIC_RG_VA10_VOSEL, MT6351_PMIC_RG_VA10_VOSEL_ADDR, + MT6351_PMIC_RG_VA10_VOSEL_MASK, MT6351_PMIC_RG_VA10_VOSEL_SHIFT}, + {PMIC_RG_VA10_NDIS_EN, MT6351_PMIC_RG_VA10_NDIS_EN_ADDR, + MT6351_PMIC_RG_VA10_NDIS_EN_MASK, MT6351_PMIC_RG_VA10_NDIS_EN_SHIFT}, + {PMIC_RG_VA10_STB_SEL, MT6351_PMIC_RG_VA10_STB_SEL_ADDR, + MT6351_PMIC_RG_VA10_STB_SEL_MASK, MT6351_PMIC_RG_VA10_STB_SEL_SHIFT}, + {PMIC_RG_VCAMIO_CAL, MT6351_PMIC_RG_VCAMIO_CAL_ADDR, + MT6351_PMIC_RG_VCAMIO_CAL_MASK, MT6351_PMIC_RG_VCAMIO_CAL_SHIFT}, + {PMIC_RG_VCAMIO_VOSEL, MT6351_PMIC_RG_VCAMIO_VOSEL_ADDR, + MT6351_PMIC_RG_VCAMIO_VOSEL_MASK, MT6351_PMIC_RG_VCAMIO_VOSEL_SHIFT}, + {PMIC_RG_VCAMIO_NDIS_EN, MT6351_PMIC_RG_VCAMIO_NDIS_EN_ADDR, + MT6351_PMIC_RG_VCAMIO_NDIS_EN_MASK, MT6351_PMIC_RG_VCAMIO_NDIS_EN_SHIFT}, + {PMIC_RG_VCAMIO_STB_SEL, MT6351_PMIC_RG_VCAMIO_STB_SEL_ADDR, + MT6351_PMIC_RG_VCAMIO_STB_SEL_MASK, MT6351_PMIC_RG_VCAMIO_STB_SEL_SHIFT}, + {PMIC_RG_VCN18_CAL, MT6351_PMIC_RG_VCN18_CAL_ADDR, MT6351_PMIC_RG_VCN18_CAL_MASK, + MT6351_PMIC_RG_VCN18_CAL_SHIFT}, + {PMIC_RG_VCN18_VOSEL, MT6351_PMIC_RG_VCN18_VOSEL_ADDR, + MT6351_PMIC_RG_VCN18_VOSEL_MASK, MT6351_PMIC_RG_VCN18_VOSEL_SHIFT}, + {PMIC_RG_VCN18_NDIS_EN, MT6351_PMIC_RG_VCN18_NDIS_EN_ADDR, + MT6351_PMIC_RG_VCN18_NDIS_EN_MASK, MT6351_PMIC_RG_VCN18_NDIS_EN_SHIFT}, + {PMIC_RG_VCN18_STB_SEL, MT6351_PMIC_RG_VCN18_STB_SEL_ADDR, + MT6351_PMIC_RG_VCN18_STB_SEL_MASK, MT6351_PMIC_RG_VCN18_STB_SEL_SHIFT}, + {PMIC_RG_VMIPI_CAL, MT6351_PMIC_RG_VMIPI_CAL_ADDR, MT6351_PMIC_RG_VMIPI_CAL_MASK, + MT6351_PMIC_RG_VMIPI_CAL_SHIFT}, + {PMIC_RG_VMIPI_VOSEL, MT6351_PMIC_RG_VMIPI_VOSEL_ADDR, + MT6351_PMIC_RG_VMIPI_VOSEL_MASK, MT6351_PMIC_RG_VMIPI_VOSEL_SHIFT}, + {PMIC_RG_VMIPI_NDIS_EN, MT6351_PMIC_RG_VMIPI_NDIS_EN_ADDR, + MT6351_PMIC_RG_VMIPI_NDIS_EN_MASK, MT6351_PMIC_RG_VMIPI_NDIS_EN_SHIFT}, + {PMIC_RG_VMIPI_STB_SEL, MT6351_PMIC_RG_VMIPI_STB_SEL_ADDR, + MT6351_PMIC_RG_VMIPI_STB_SEL_MASK, MT6351_PMIC_RG_VMIPI_STB_SEL_SHIFT}, + {PMIC_RG_VSRAM_PROC_NDIS_EN, MT6351_PMIC_RG_VSRAM_PROC_NDIS_EN_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_NDIS_EN_MASK, MT6351_PMIC_RG_VSRAM_PROC_NDIS_EN_SHIFT}, + {PMIC_RG_VSRAM_PROC_NDIS_PLCUR, MT6351_PMIC_RG_VSRAM_PROC_NDIS_PLCUR_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_NDIS_PLCUR_MASK, MT6351_PMIC_RG_VSRAM_PROC_NDIS_PLCUR_SHIFT}, + {PMIC_RG_VSRAM_PROC_STB_SEL, MT6351_PMIC_RG_VSRAM_PROC_STB_SEL_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_STB_SEL_MASK, MT6351_PMIC_RG_VSRAM_PROC_STB_SEL_SHIFT}, + {PMIC_RG_VSRAM_PROC_PLCUR_EN, MT6351_PMIC_RG_VSRAM_PROC_PLCUR_EN_ADDR, + MT6351_PMIC_RG_VSRAM_PROC_PLCUR_EN_MASK, MT6351_PMIC_RG_VSRAM_PROC_PLCUR_EN_SHIFT}, + {PMIC_RG_VDRAM_CAL, MT6351_PMIC_RG_VDRAM_CAL_ADDR, MT6351_PMIC_RG_VDRAM_CAL_MASK, + MT6351_PMIC_RG_VDRAM_CAL_SHIFT}, + {PMIC_RG_VDRAM_VOSEL, MT6351_PMIC_RG_VDRAM_VOSEL_ADDR, + MT6351_PMIC_RG_VDRAM_VOSEL_MASK, MT6351_PMIC_RG_VDRAM_VOSEL_SHIFT}, + {PMIC_RG_VDRAM_NDIS_EN, MT6351_PMIC_RG_VDRAM_NDIS_EN_ADDR, + MT6351_PMIC_RG_VDRAM_NDIS_EN_MASK, MT6351_PMIC_RG_VDRAM_NDIS_EN_SHIFT}, + {PMIC_RG_VDRAM_RSV, MT6351_PMIC_RG_VDRAM_RSV_ADDR, MT6351_PMIC_RG_VDRAM_RSV_MASK, + MT6351_PMIC_RG_VDRAM_RSV_SHIFT}, + {PMIC_RG_VDRAM_OC_TRIM, MT6351_PMIC_RG_VDRAM_OC_TRIM_ADDR, + MT6351_PMIC_RG_VDRAM_OC_TRIM_MASK, MT6351_PMIC_RG_VDRAM_OC_TRIM_SHIFT}, + {PMIC_RG_VLDO28_CAL, MT6351_PMIC_RG_VLDO28_CAL_ADDR, + MT6351_PMIC_RG_VLDO28_CAL_MASK, MT6351_PMIC_RG_VLDO28_CAL_SHIFT}, + {PMIC_RG_VLDO28_NDIS_EN, MT6351_PMIC_RG_VLDO28_NDIS_EN_ADDR, + MT6351_PMIC_RG_VLDO28_NDIS_EN_MASK, MT6351_PMIC_RG_VLDO28_NDIS_EN_SHIFT}, + {PMIC_RG_VLDO28_OC_TRIM, MT6351_PMIC_RG_VLDO28_OC_TRIM_ADDR, + MT6351_PMIC_RG_VLDO28_OC_TRIM_MASK, MT6351_PMIC_RG_VLDO28_OC_TRIM_SHIFT}, + {PMIC_RG_VLDO28_N2LP_EHC_V18, MT6351_PMIC_RG_VLDO28_N2LP_EHC_V18_ADDR, + MT6351_PMIC_RG_VLDO28_N2LP_EHC_V18_MASK, MT6351_PMIC_RG_VLDO28_N2LP_EHC_V18_SHIFT}, + {PMIC_BIF_COMMAND_0, MT6351_PMIC_BIF_COMMAND_0_ADDR, + MT6351_PMIC_BIF_COMMAND_0_MASK, MT6351_PMIC_BIF_COMMAND_0_SHIFT}, + {PMIC_BIF_COMMAND_1, MT6351_PMIC_BIF_COMMAND_1_ADDR, + MT6351_PMIC_BIF_COMMAND_1_MASK, MT6351_PMIC_BIF_COMMAND_1_SHIFT}, + {PMIC_BIF_COMMAND_2, MT6351_PMIC_BIF_COMMAND_2_ADDR, + MT6351_PMIC_BIF_COMMAND_2_MASK, MT6351_PMIC_BIF_COMMAND_2_SHIFT}, + {PMIC_BIF_COMMAND_3, MT6351_PMIC_BIF_COMMAND_3_ADDR, + MT6351_PMIC_BIF_COMMAND_3_MASK, MT6351_PMIC_BIF_COMMAND_3_SHIFT}, + {PMIC_BIF_COMMAND_4, MT6351_PMIC_BIF_COMMAND_4_ADDR, + MT6351_PMIC_BIF_COMMAND_4_MASK, MT6351_PMIC_BIF_COMMAND_4_SHIFT}, + {PMIC_BIF_COMMAND_5, MT6351_PMIC_BIF_COMMAND_5_ADDR, + MT6351_PMIC_BIF_COMMAND_5_MASK, MT6351_PMIC_BIF_COMMAND_5_SHIFT}, + {PMIC_BIF_COMMAND_6, MT6351_PMIC_BIF_COMMAND_6_ADDR, + MT6351_PMIC_BIF_COMMAND_6_MASK, MT6351_PMIC_BIF_COMMAND_6_SHIFT}, + {PMIC_BIF_COMMAND_7, MT6351_PMIC_BIF_COMMAND_7_ADDR, + MT6351_PMIC_BIF_COMMAND_7_MASK, MT6351_PMIC_BIF_COMMAND_7_SHIFT}, + {PMIC_BIF_COMMAND_8, MT6351_PMIC_BIF_COMMAND_8_ADDR, + MT6351_PMIC_BIF_COMMAND_8_MASK, MT6351_PMIC_BIF_COMMAND_8_SHIFT}, + {PMIC_BIF_COMMAND_9, MT6351_PMIC_BIF_COMMAND_9_ADDR, + MT6351_PMIC_BIF_COMMAND_9_MASK, MT6351_PMIC_BIF_COMMAND_9_SHIFT}, + {PMIC_BIF_COMMAND_10, MT6351_PMIC_BIF_COMMAND_10_ADDR, + MT6351_PMIC_BIF_COMMAND_10_MASK, MT6351_PMIC_BIF_COMMAND_10_SHIFT}, + {PMIC_BIF_COMMAND_11, MT6351_PMIC_BIF_COMMAND_11_ADDR, + MT6351_PMIC_BIF_COMMAND_11_MASK, MT6351_PMIC_BIF_COMMAND_11_SHIFT}, + {PMIC_BIF_COMMAND_12, MT6351_PMIC_BIF_COMMAND_12_ADDR, + MT6351_PMIC_BIF_COMMAND_12_MASK, MT6351_PMIC_BIF_COMMAND_12_SHIFT}, + {PMIC_BIF_COMMAND_13, MT6351_PMIC_BIF_COMMAND_13_ADDR, + MT6351_PMIC_BIF_COMMAND_13_MASK, MT6351_PMIC_BIF_COMMAND_13_SHIFT}, + {PMIC_BIF_COMMAND_14, MT6351_PMIC_BIF_COMMAND_14_ADDR, + MT6351_PMIC_BIF_COMMAND_14_MASK, MT6351_PMIC_BIF_COMMAND_14_SHIFT}, + {PMIC_BIF_RSV, MT6351_PMIC_BIF_RSV_ADDR, MT6351_PMIC_BIF_RSV_MASK, + MT6351_PMIC_BIF_RSV_SHIFT}, + {PMIC_BIF_COMMAND_TYPE, MT6351_PMIC_BIF_COMMAND_TYPE_ADDR, + MT6351_PMIC_BIF_COMMAND_TYPE_MASK, MT6351_PMIC_BIF_COMMAND_TYPE_SHIFT}, + {PMIC_BIF_TRASFER_NUM, MT6351_PMIC_BIF_TRASFER_NUM_ADDR, + MT6351_PMIC_BIF_TRASFER_NUM_MASK, MT6351_PMIC_BIF_TRASFER_NUM_SHIFT}, + {PMIC_BIF_LOGIC_0_SET, MT6351_PMIC_BIF_LOGIC_0_SET_ADDR, + MT6351_PMIC_BIF_LOGIC_0_SET_MASK, MT6351_PMIC_BIF_LOGIC_0_SET_SHIFT}, + {PMIC_BIF_LOGIC_1_SET, MT6351_PMIC_BIF_LOGIC_1_SET_ADDR, + MT6351_PMIC_BIF_LOGIC_1_SET_MASK, MT6351_PMIC_BIF_LOGIC_1_SET_SHIFT}, + {PMIC_BIF_STOP_SET, MT6351_PMIC_BIF_STOP_SET_ADDR, MT6351_PMIC_BIF_STOP_SET_MASK, + MT6351_PMIC_BIF_STOP_SET_SHIFT}, + {PMIC_BIF_DEBOUNCE_WND, MT6351_PMIC_BIF_DEBOUNCE_WND_ADDR, + MT6351_PMIC_BIF_DEBOUNCE_WND_MASK, MT6351_PMIC_BIF_DEBOUNCE_WND_SHIFT}, + {PMIC_BIF_DEBOUNCE_THD, MT6351_PMIC_BIF_DEBOUNCE_THD_ADDR, + MT6351_PMIC_BIF_DEBOUNCE_THD_MASK, MT6351_PMIC_BIF_DEBOUNCE_THD_SHIFT}, + {PMIC_BIF_DEBOUNCE_EN, MT6351_PMIC_BIF_DEBOUNCE_EN_ADDR, + MT6351_PMIC_BIF_DEBOUNCE_EN_MASK, MT6351_PMIC_BIF_DEBOUNCE_EN_SHIFT}, + {PMIC_BIF_READ_EXPECT_NUM, MT6351_PMIC_BIF_READ_EXPECT_NUM_ADDR, + MT6351_PMIC_BIF_READ_EXPECT_NUM_MASK, MT6351_PMIC_BIF_READ_EXPECT_NUM_SHIFT}, + {PMIC_BIF_TRASACT_TRIGGER, MT6351_PMIC_BIF_TRASACT_TRIGGER_ADDR, + MT6351_PMIC_BIF_TRASACT_TRIGGER_MASK, MT6351_PMIC_BIF_TRASACT_TRIGGER_SHIFT}, + {PMIC_BIF_DATA_NUM, MT6351_PMIC_BIF_DATA_NUM_ADDR, MT6351_PMIC_BIF_DATA_NUM_MASK, + MT6351_PMIC_BIF_DATA_NUM_SHIFT}, + {PMIC_BIF_RESPONSE, MT6351_PMIC_BIF_RESPONSE_ADDR, MT6351_PMIC_BIF_RESPONSE_MASK, + MT6351_PMIC_BIF_RESPONSE_SHIFT}, + {PMIC_BIF_DATA_0, MT6351_PMIC_BIF_DATA_0_ADDR, MT6351_PMIC_BIF_DATA_0_MASK, + MT6351_PMIC_BIF_DATA_0_SHIFT}, + {PMIC_BIF_ACK_0, MT6351_PMIC_BIF_ACK_0_ADDR, MT6351_PMIC_BIF_ACK_0_MASK, + MT6351_PMIC_BIF_ACK_0_SHIFT}, + {PMIC_BIF_ERROR_0, MT6351_PMIC_BIF_ERROR_0_ADDR, MT6351_PMIC_BIF_ERROR_0_MASK, + MT6351_PMIC_BIF_ERROR_0_SHIFT}, + {PMIC_BIF_DATA_1, MT6351_PMIC_BIF_DATA_1_ADDR, MT6351_PMIC_BIF_DATA_1_MASK, + MT6351_PMIC_BIF_DATA_1_SHIFT}, + {PMIC_BIF_ACK_1, MT6351_PMIC_BIF_ACK_1_ADDR, MT6351_PMIC_BIF_ACK_1_MASK, + MT6351_PMIC_BIF_ACK_1_SHIFT}, + {PMIC_BIF_ERROR_1, MT6351_PMIC_BIF_ERROR_1_ADDR, MT6351_PMIC_BIF_ERROR_1_MASK, + MT6351_PMIC_BIF_ERROR_1_SHIFT}, + {PMIC_BIF_DATA_2, MT6351_PMIC_BIF_DATA_2_ADDR, MT6351_PMIC_BIF_DATA_2_MASK, + MT6351_PMIC_BIF_DATA_2_SHIFT}, + {PMIC_BIF_ACK_2, MT6351_PMIC_BIF_ACK_2_ADDR, MT6351_PMIC_BIF_ACK_2_MASK, + MT6351_PMIC_BIF_ACK_2_SHIFT}, + {PMIC_BIF_ERROR_2, MT6351_PMIC_BIF_ERROR_2_ADDR, MT6351_PMIC_BIF_ERROR_2_MASK, + MT6351_PMIC_BIF_ERROR_2_SHIFT}, + {PMIC_BIF_DATA_3, MT6351_PMIC_BIF_DATA_3_ADDR, MT6351_PMIC_BIF_DATA_3_MASK, + MT6351_PMIC_BIF_DATA_3_SHIFT}, + {PMIC_BIF_ACK_3, MT6351_PMIC_BIF_ACK_3_ADDR, MT6351_PMIC_BIF_ACK_3_MASK, + MT6351_PMIC_BIF_ACK_3_SHIFT}, + {PMIC_BIF_ERROR_3, MT6351_PMIC_BIF_ERROR_3_ADDR, MT6351_PMIC_BIF_ERROR_3_MASK, + MT6351_PMIC_BIF_ERROR_3_SHIFT}, + {PMIC_BIF_DATA_4, MT6351_PMIC_BIF_DATA_4_ADDR, MT6351_PMIC_BIF_DATA_4_MASK, + MT6351_PMIC_BIF_DATA_4_SHIFT}, + {PMIC_BIF_ACK_4, MT6351_PMIC_BIF_ACK_4_ADDR, MT6351_PMIC_BIF_ACK_4_MASK, + MT6351_PMIC_BIF_ACK_4_SHIFT}, + {PMIC_BIF_ERROR_4, MT6351_PMIC_BIF_ERROR_4_ADDR, MT6351_PMIC_BIF_ERROR_4_MASK, + MT6351_PMIC_BIF_ERROR_4_SHIFT}, + {PMIC_BIF_DATA_5, MT6351_PMIC_BIF_DATA_5_ADDR, MT6351_PMIC_BIF_DATA_5_MASK, + MT6351_PMIC_BIF_DATA_5_SHIFT}, + {PMIC_BIF_ACK_5, MT6351_PMIC_BIF_ACK_5_ADDR, MT6351_PMIC_BIF_ACK_5_MASK, + MT6351_PMIC_BIF_ACK_5_SHIFT}, + {PMIC_BIF_ERROR_5, MT6351_PMIC_BIF_ERROR_5_ADDR, MT6351_PMIC_BIF_ERROR_5_MASK, + MT6351_PMIC_BIF_ERROR_5_SHIFT}, + {PMIC_BIF_DATA_6, MT6351_PMIC_BIF_DATA_6_ADDR, MT6351_PMIC_BIF_DATA_6_MASK, + MT6351_PMIC_BIF_DATA_6_SHIFT}, + {PMIC_BIF_ACK_6, MT6351_PMIC_BIF_ACK_6_ADDR, MT6351_PMIC_BIF_ACK_6_MASK, + MT6351_PMIC_BIF_ACK_6_SHIFT}, + {PMIC_BIF_ERROR_6, MT6351_PMIC_BIF_ERROR_6_ADDR, MT6351_PMIC_BIF_ERROR_6_MASK, + MT6351_PMIC_BIF_ERROR_6_SHIFT}, + {PMIC_BIF_DATA_7, MT6351_PMIC_BIF_DATA_7_ADDR, MT6351_PMIC_BIF_DATA_7_MASK, + MT6351_PMIC_BIF_DATA_7_SHIFT}, + {PMIC_BIF_ACK_7, MT6351_PMIC_BIF_ACK_7_ADDR, MT6351_PMIC_BIF_ACK_7_MASK, + MT6351_PMIC_BIF_ACK_7_SHIFT}, + {PMIC_BIF_ERROR_7, MT6351_PMIC_BIF_ERROR_7_ADDR, MT6351_PMIC_BIF_ERROR_7_MASK, + MT6351_PMIC_BIF_ERROR_7_SHIFT}, + {PMIC_BIF_DATA_8, MT6351_PMIC_BIF_DATA_8_ADDR, MT6351_PMIC_BIF_DATA_8_MASK, + MT6351_PMIC_BIF_DATA_8_SHIFT}, + {PMIC_BIF_ACK_8, MT6351_PMIC_BIF_ACK_8_ADDR, MT6351_PMIC_BIF_ACK_8_MASK, + MT6351_PMIC_BIF_ACK_8_SHIFT}, + {PMIC_BIF_ERROR_8, MT6351_PMIC_BIF_ERROR_8_ADDR, MT6351_PMIC_BIF_ERROR_8_MASK, + MT6351_PMIC_BIF_ERROR_8_SHIFT}, + {PMIC_BIF_DATA_9, MT6351_PMIC_BIF_DATA_9_ADDR, MT6351_PMIC_BIF_DATA_9_MASK, + MT6351_PMIC_BIF_DATA_9_SHIFT}, + {PMIC_BIF_ACK_9, MT6351_PMIC_BIF_ACK_9_ADDR, MT6351_PMIC_BIF_ACK_9_MASK, + MT6351_PMIC_BIF_ACK_9_SHIFT}, + {PMIC_BIF_ERROR_9, MT6351_PMIC_BIF_ERROR_9_ADDR, MT6351_PMIC_BIF_ERROR_9_MASK, + MT6351_PMIC_BIF_ERROR_9_SHIFT}, + {PMIC_BIF_TEST_MODE0, MT6351_PMIC_BIF_TEST_MODE0_ADDR, + MT6351_PMIC_BIF_TEST_MODE0_MASK, MT6351_PMIC_BIF_TEST_MODE0_SHIFT}, + {PMIC_BIF_TEST_MODE1, MT6351_PMIC_BIF_TEST_MODE1_ADDR, + MT6351_PMIC_BIF_TEST_MODE1_MASK, MT6351_PMIC_BIF_TEST_MODE1_SHIFT}, + {PMIC_BIF_TEST_MODE2, MT6351_PMIC_BIF_TEST_MODE2_ADDR, + MT6351_PMIC_BIF_TEST_MODE2_MASK, MT6351_PMIC_BIF_TEST_MODE2_SHIFT}, + {PMIC_BIF_TEST_MODE3, MT6351_PMIC_BIF_TEST_MODE3_ADDR, + MT6351_PMIC_BIF_TEST_MODE3_MASK, MT6351_PMIC_BIF_TEST_MODE3_SHIFT}, + {PMIC_BIF_TEST_MODE4, MT6351_PMIC_BIF_TEST_MODE4_ADDR, + MT6351_PMIC_BIF_TEST_MODE4_MASK, MT6351_PMIC_BIF_TEST_MODE4_SHIFT}, + {PMIC_BIF_TEST_MODE5, MT6351_PMIC_BIF_TEST_MODE5_ADDR, + MT6351_PMIC_BIF_TEST_MODE5_MASK, MT6351_PMIC_BIF_TEST_MODE5_SHIFT}, + {PMIC_BIF_TEST_MODE6, MT6351_PMIC_BIF_TEST_MODE6_ADDR, + MT6351_PMIC_BIF_TEST_MODE6_MASK, MT6351_PMIC_BIF_TEST_MODE6_SHIFT}, + {PMIC_BIF_TEST_MODE7, MT6351_PMIC_BIF_TEST_MODE7_ADDR, + MT6351_PMIC_BIF_TEST_MODE7_MASK, MT6351_PMIC_BIF_TEST_MODE7_SHIFT}, + {PMIC_BIF_TEST_MODE8, MT6351_PMIC_BIF_TEST_MODE8_ADDR, + MT6351_PMIC_BIF_TEST_MODE8_MASK, MT6351_PMIC_BIF_TEST_MODE8_SHIFT}, + {PMIC_BIF_BAT_LOST_SW, MT6351_PMIC_BIF_BAT_LOST_SW_ADDR, + MT6351_PMIC_BIF_BAT_LOST_SW_MASK, MT6351_PMIC_BIF_BAT_LOST_SW_SHIFT}, + {PMIC_BIF_RX_DATA_SW, MT6351_PMIC_BIF_RX_DATA_SW_ADDR, + MT6351_PMIC_BIF_RX_DATA_SW_MASK, MT6351_PMIC_BIF_RX_DATA_SW_SHIFT}, + {PMIC_BIF_TX_DATA_SW, MT6351_PMIC_BIF_TX_DATA_SW_ADDR, + MT6351_PMIC_BIF_TX_DATA_SW_MASK, MT6351_PMIC_BIF_TX_DATA_SW_SHIFT}, + {PMIC_BIF_RX_EN_SW, MT6351_PMIC_BIF_RX_EN_SW_ADDR, MT6351_PMIC_BIF_RX_EN_SW_MASK, + MT6351_PMIC_BIF_RX_EN_SW_SHIFT}, + {PMIC_BIF_TX_EN_SW, MT6351_PMIC_BIF_TX_EN_SW_ADDR, MT6351_PMIC_BIF_TX_EN_SW_MASK, + MT6351_PMIC_BIF_TX_EN_SW_SHIFT}, + {PMIC_BIF_BACK_NORMAL, MT6351_PMIC_BIF_BACK_NORMAL_ADDR, + MT6351_PMIC_BIF_BACK_NORMAL_MASK, MT6351_PMIC_BIF_BACK_NORMAL_SHIFT}, + {PMIC_BIF_IRQ_CLR, MT6351_PMIC_BIF_IRQ_CLR_ADDR, MT6351_PMIC_BIF_IRQ_CLR_MASK, + MT6351_PMIC_BIF_IRQ_CLR_SHIFT}, + {PMIC_BIF_BAT_LOST_GATED, MT6351_PMIC_BIF_BAT_LOST_GATED_ADDR, + MT6351_PMIC_BIF_BAT_LOST_GATED_MASK, MT6351_PMIC_BIF_BAT_LOST_GATED_SHIFT}, + {PMIC_BIF_IRQ, MT6351_PMIC_BIF_IRQ_ADDR, MT6351_PMIC_BIF_IRQ_MASK, + MT6351_PMIC_BIF_IRQ_SHIFT}, + {PMIC_BIF_TIMEOUT, MT6351_PMIC_BIF_TIMEOUT_ADDR, MT6351_PMIC_BIF_TIMEOUT_MASK, + MT6351_PMIC_BIF_TIMEOUT_SHIFT}, + {PMIC_BIF_BAT_LOST, MT6351_PMIC_BIF_BAT_LOST_ADDR, MT6351_PMIC_BIF_BAT_LOST_MASK, + MT6351_PMIC_BIF_BAT_LOST_SHIFT}, + {PMIC_BIF_TOTAL_VALID, MT6351_PMIC_BIF_TOTAL_VALID_ADDR, + MT6351_PMIC_BIF_TOTAL_VALID_MASK, MT6351_PMIC_BIF_TOTAL_VALID_SHIFT}, + {PMIC_BIF_BUS_STATUS, MT6351_PMIC_BIF_BUS_STATUS_ADDR, + MT6351_PMIC_BIF_BUS_STATUS_MASK, MT6351_PMIC_BIF_BUS_STATUS_SHIFT}, + {PMIC_BIF_POWER_UP_COUNT, MT6351_PMIC_BIF_POWER_UP_COUNT_ADDR, + MT6351_PMIC_BIF_POWER_UP_COUNT_MASK, MT6351_PMIC_BIF_POWER_UP_COUNT_SHIFT}, + {PMIC_BIF_POWER_UP, MT6351_PMIC_BIF_POWER_UP_ADDR, MT6351_PMIC_BIF_POWER_UP_MASK, + MT6351_PMIC_BIF_POWER_UP_SHIFT}, + {PMIC_BIF_RX_ERROR_UNKNOWN, MT6351_PMIC_BIF_RX_ERROR_UNKNOWN_ADDR, + MT6351_PMIC_BIF_RX_ERROR_UNKNOWN_MASK, MT6351_PMIC_BIF_RX_ERROR_UNKNOWN_SHIFT}, + {PMIC_BIF_RX_ERROR_INSUFF, MT6351_PMIC_BIF_RX_ERROR_INSUFF_ADDR, + MT6351_PMIC_BIF_RX_ERROR_INSUFF_MASK, MT6351_PMIC_BIF_RX_ERROR_INSUFF_SHIFT}, + {PMIC_BIF_RX_ERROR_LOWPHASE, MT6351_PMIC_BIF_RX_ERROR_LOWPHASE_ADDR, + MT6351_PMIC_BIF_RX_ERROR_LOWPHASE_MASK, MT6351_PMIC_BIF_RX_ERROR_LOWPHASE_SHIFT}, + {PMIC_BIF_RX_STATE, MT6351_PMIC_BIF_RX_STATE_ADDR, MT6351_PMIC_BIF_RX_STATE_MASK, + MT6351_PMIC_BIF_RX_STATE_SHIFT}, + {PMIC_BIF_FLOW_CTL_STATE, MT6351_PMIC_BIF_FLOW_CTL_STATE_ADDR, + MT6351_PMIC_BIF_FLOW_CTL_STATE_MASK, MT6351_PMIC_BIF_FLOW_CTL_STATE_SHIFT}, + {PMIC_BIF_TX_STATE, MT6351_PMIC_BIF_TX_STATE_ADDR, MT6351_PMIC_BIF_TX_STATE_MASK, + MT6351_PMIC_BIF_TX_STATE_SHIFT}, + {PMIC_AD_QI_BIF_RX_DATA, MT6351_PMIC_AD_QI_BIF_RX_DATA_ADDR, + MT6351_PMIC_AD_QI_BIF_RX_DATA_MASK, MT6351_PMIC_AD_QI_BIF_RX_DATA_SHIFT}, + {PMIC_DA_QI_BIF_RX_EN, MT6351_PMIC_DA_QI_BIF_RX_EN_ADDR, + MT6351_PMIC_DA_QI_BIF_RX_EN_MASK, MT6351_PMIC_DA_QI_BIF_RX_EN_SHIFT}, + {PMIC_DA_QI_BIF_TX_DATA, MT6351_PMIC_DA_QI_BIF_TX_DATA_ADDR, + MT6351_PMIC_DA_QI_BIF_TX_DATA_MASK, MT6351_PMIC_DA_QI_BIF_TX_DATA_SHIFT}, + {PMIC_DA_QI_BIF_TX_EN, MT6351_PMIC_DA_QI_BIF_TX_EN_ADDR, + MT6351_PMIC_DA_QI_BIF_TX_EN_MASK, MT6351_PMIC_DA_QI_BIF_TX_EN_SHIFT}, + {PMIC_BIF_TX_DATA_FIANL, MT6351_PMIC_BIF_TX_DATA_FIANL_ADDR, + MT6351_PMIC_BIF_TX_DATA_FIANL_MASK, MT6351_PMIC_BIF_TX_DATA_FIANL_SHIFT}, + {PMIC_BIF_RX_DATA_SAMPLING, MT6351_PMIC_BIF_RX_DATA_SAMPLING_ADDR, + MT6351_PMIC_BIF_RX_DATA_SAMPLING_MASK, MT6351_PMIC_BIF_RX_DATA_SAMPLING_SHIFT}, + {PMIC_BIF_RX_DATA_RECOVERY, MT6351_PMIC_BIF_RX_DATA_RECOVERY_ADDR, + MT6351_PMIC_BIF_RX_DATA_RECOVERY_MASK, MT6351_PMIC_BIF_RX_DATA_RECOVERY_SHIFT}, + {PMIC_RG_BATON_HT_EN, MT6351_PMIC_RG_BATON_HT_EN_ADDR, + MT6351_PMIC_RG_BATON_HT_EN_MASK, MT6351_PMIC_RG_BATON_HT_EN_SHIFT}, + {PMIC_RG_BATON_HT_EN_DLY_TIME, MT6351_PMIC_RG_BATON_HT_EN_DLY_TIME_ADDR, + MT6351_PMIC_RG_BATON_HT_EN_DLY_TIME_MASK, MT6351_PMIC_RG_BATON_HT_EN_DLY_TIME_SHIFT}, + {PMIC_DA_QI_BATON_HT_EN, MT6351_PMIC_DA_QI_BATON_HT_EN_ADDR, + MT6351_PMIC_DA_QI_BATON_HT_EN_MASK, MT6351_PMIC_DA_QI_BATON_HT_EN_SHIFT}, + {PMIC_BIF_TIMEOUT_SET, MT6351_PMIC_BIF_TIMEOUT_SET_ADDR, + MT6351_PMIC_BIF_TIMEOUT_SET_MASK, MT6351_PMIC_BIF_TIMEOUT_SET_SHIFT}, + {PMIC_BIF_RX_DEG_WND, MT6351_PMIC_BIF_RX_DEG_WND_ADDR, + MT6351_PMIC_BIF_RX_DEG_WND_MASK, MT6351_PMIC_BIF_RX_DEG_WND_SHIFT}, + {PMIC_BIF_RX_DEG_EN, MT6351_PMIC_BIF_RX_DEG_EN_ADDR, + MT6351_PMIC_BIF_RX_DEG_EN_MASK, MT6351_PMIC_BIF_RX_DEG_EN_SHIFT}, + {PMIC_BIF_RSV1, MT6351_PMIC_BIF_RSV1_ADDR, MT6351_PMIC_BIF_RSV1_MASK, + MT6351_PMIC_BIF_RSV1_SHIFT}, + {PMIC_BIF_RSV0, MT6351_PMIC_BIF_RSV0_ADDR, MT6351_PMIC_BIF_RSV0_MASK, + MT6351_PMIC_BIF_RSV0_SHIFT}, + {PMIC_RG_OTP_PA, MT6351_PMIC_RG_OTP_PA_ADDR, MT6351_PMIC_RG_OTP_PA_MASK, + MT6351_PMIC_RG_OTP_PA_SHIFT}, + {PMIC_RG_OTP_PDIN, MT6351_PMIC_RG_OTP_PDIN_ADDR, MT6351_PMIC_RG_OTP_PDIN_MASK, + MT6351_PMIC_RG_OTP_PDIN_SHIFT}, + {PMIC_RG_OTP_PTM, MT6351_PMIC_RG_OTP_PTM_ADDR, MT6351_PMIC_RG_OTP_PTM_MASK, + MT6351_PMIC_RG_OTP_PTM_SHIFT}, + {PMIC_RG_OTP_PWE, MT6351_PMIC_RG_OTP_PWE_ADDR, MT6351_PMIC_RG_OTP_PWE_MASK, + MT6351_PMIC_RG_OTP_PWE_SHIFT}, + {PMIC_RG_OTP_PPROG, MT6351_PMIC_RG_OTP_PPROG_ADDR, MT6351_PMIC_RG_OTP_PPROG_MASK, + MT6351_PMIC_RG_OTP_PPROG_SHIFT}, + {PMIC_RG_OTP_PWE_SRC, MT6351_PMIC_RG_OTP_PWE_SRC_ADDR, + MT6351_PMIC_RG_OTP_PWE_SRC_MASK, MT6351_PMIC_RG_OTP_PWE_SRC_SHIFT}, + {PMIC_RG_OTP_PROG_PKEY, MT6351_PMIC_RG_OTP_PROG_PKEY_ADDR, + MT6351_PMIC_RG_OTP_PROG_PKEY_MASK, MT6351_PMIC_RG_OTP_PROG_PKEY_SHIFT}, + {PMIC_RG_OTP_RD_PKEY, MT6351_PMIC_RG_OTP_RD_PKEY_ADDR, + MT6351_PMIC_RG_OTP_RD_PKEY_MASK, MT6351_PMIC_RG_OTP_RD_PKEY_SHIFT}, + {PMIC_RG_OTP_RD_TRIG, MT6351_PMIC_RG_OTP_RD_TRIG_ADDR, + MT6351_PMIC_RG_OTP_RD_TRIG_MASK, MT6351_PMIC_RG_OTP_RD_TRIG_SHIFT}, + {PMIC_RG_RD_RDY_BYPASS, MT6351_PMIC_RG_RD_RDY_BYPASS_ADDR, + MT6351_PMIC_RG_RD_RDY_BYPASS_MASK, MT6351_PMIC_RG_RD_RDY_BYPASS_SHIFT}, + {PMIC_RG_SKIP_OTP_OUT, MT6351_PMIC_RG_SKIP_OTP_OUT_ADDR, + MT6351_PMIC_RG_SKIP_OTP_OUT_MASK, MT6351_PMIC_RG_SKIP_OTP_OUT_SHIFT}, + {PMIC_RG_OTP_RD_SW, MT6351_PMIC_RG_OTP_RD_SW_ADDR, MT6351_PMIC_RG_OTP_RD_SW_MASK, + MT6351_PMIC_RG_OTP_RD_SW_SHIFT}, + {PMIC_RG_OTP_DOUT_SW, MT6351_PMIC_RG_OTP_DOUT_SW_ADDR, + MT6351_PMIC_RG_OTP_DOUT_SW_MASK, MT6351_PMIC_RG_OTP_DOUT_SW_SHIFT}, + {PMIC_RG_OTP_RD_BUSY, MT6351_PMIC_RG_OTP_RD_BUSY_ADDR, + MT6351_PMIC_RG_OTP_RD_BUSY_MASK, MT6351_PMIC_RG_OTP_RD_BUSY_SHIFT}, + {PMIC_RG_OTP_RD_ACK, MT6351_PMIC_RG_OTP_RD_ACK_ADDR, + MT6351_PMIC_RG_OTP_RD_ACK_MASK, MT6351_PMIC_RG_OTP_RD_ACK_SHIFT}, + {PMIC_RG_OTP_PA_SW, MT6351_PMIC_RG_OTP_PA_SW_ADDR, MT6351_PMIC_RG_OTP_PA_SW_MASK, + MT6351_PMIC_RG_OTP_PA_SW_SHIFT}, + {PMIC_RG_OTP_DOUT_0_15, MT6351_PMIC_RG_OTP_DOUT_0_15_ADDR, + MT6351_PMIC_RG_OTP_DOUT_0_15_MASK, MT6351_PMIC_RG_OTP_DOUT_0_15_SHIFT}, + {PMIC_RG_OTP_DOUT_16_31, MT6351_PMIC_RG_OTP_DOUT_16_31_ADDR, + MT6351_PMIC_RG_OTP_DOUT_16_31_MASK, MT6351_PMIC_RG_OTP_DOUT_16_31_SHIFT}, + {PMIC_RG_OTP_DOUT_32_47, MT6351_PMIC_RG_OTP_DOUT_32_47_ADDR, + MT6351_PMIC_RG_OTP_DOUT_32_47_MASK, MT6351_PMIC_RG_OTP_DOUT_32_47_SHIFT}, + {PMIC_RG_OTP_DOUT_48_63, MT6351_PMIC_RG_OTP_DOUT_48_63_ADDR, + MT6351_PMIC_RG_OTP_DOUT_48_63_MASK, MT6351_PMIC_RG_OTP_DOUT_48_63_SHIFT}, + {PMIC_RG_OTP_DOUT_64_79, MT6351_PMIC_RG_OTP_DOUT_64_79_ADDR, + MT6351_PMIC_RG_OTP_DOUT_64_79_MASK, MT6351_PMIC_RG_OTP_DOUT_64_79_SHIFT}, + {PMIC_RG_OTP_DOUT_80_95, MT6351_PMIC_RG_OTP_DOUT_80_95_ADDR, + MT6351_PMIC_RG_OTP_DOUT_80_95_MASK, MT6351_PMIC_RG_OTP_DOUT_80_95_SHIFT}, + {PMIC_RG_OTP_DOUT_96_111, MT6351_PMIC_RG_OTP_DOUT_96_111_ADDR, + MT6351_PMIC_RG_OTP_DOUT_96_111_MASK, MT6351_PMIC_RG_OTP_DOUT_96_111_SHIFT}, + {PMIC_RG_OTP_DOUT_112_127, MT6351_PMIC_RG_OTP_DOUT_112_127_ADDR, + MT6351_PMIC_RG_OTP_DOUT_112_127_MASK, MT6351_PMIC_RG_OTP_DOUT_112_127_SHIFT}, + {PMIC_RG_OTP_DOUT_128_143, MT6351_PMIC_RG_OTP_DOUT_128_143_ADDR, + MT6351_PMIC_RG_OTP_DOUT_128_143_MASK, MT6351_PMIC_RG_OTP_DOUT_128_143_SHIFT}, + {PMIC_RG_OTP_DOUT_144_159, MT6351_PMIC_RG_OTP_DOUT_144_159_ADDR, + MT6351_PMIC_RG_OTP_DOUT_144_159_MASK, MT6351_PMIC_RG_OTP_DOUT_144_159_SHIFT}, + {PMIC_RG_OTP_DOUT_160_175, MT6351_PMIC_RG_OTP_DOUT_160_175_ADDR, + MT6351_PMIC_RG_OTP_DOUT_160_175_MASK, MT6351_PMIC_RG_OTP_DOUT_160_175_SHIFT}, + {PMIC_RG_OTP_DOUT_176_191, MT6351_PMIC_RG_OTP_DOUT_176_191_ADDR, + MT6351_PMIC_RG_OTP_DOUT_176_191_MASK, MT6351_PMIC_RG_OTP_DOUT_176_191_SHIFT}, + {PMIC_RG_OTP_DOUT_192_207, MT6351_PMIC_RG_OTP_DOUT_192_207_ADDR, + MT6351_PMIC_RG_OTP_DOUT_192_207_MASK, MT6351_PMIC_RG_OTP_DOUT_192_207_SHIFT}, + {PMIC_RG_OTP_DOUT_208_223, MT6351_PMIC_RG_OTP_DOUT_208_223_ADDR, + MT6351_PMIC_RG_OTP_DOUT_208_223_MASK, MT6351_PMIC_RG_OTP_DOUT_208_223_SHIFT}, + {PMIC_RG_OTP_DOUT_224_239, MT6351_PMIC_RG_OTP_DOUT_224_239_ADDR, + MT6351_PMIC_RG_OTP_DOUT_224_239_MASK, MT6351_PMIC_RG_OTP_DOUT_224_239_SHIFT}, + {PMIC_RG_OTP_DOUT_240_255, MT6351_PMIC_RG_OTP_DOUT_240_255_ADDR, + MT6351_PMIC_RG_OTP_DOUT_240_255_MASK, MT6351_PMIC_RG_OTP_DOUT_240_255_SHIFT}, + {PMIC_RG_OTP_DOUT_256_271, MT6351_PMIC_RG_OTP_DOUT_256_271_ADDR, + MT6351_PMIC_RG_OTP_DOUT_256_271_MASK, MT6351_PMIC_RG_OTP_DOUT_256_271_SHIFT}, + {PMIC_RG_OTP_DOUT_272_287, MT6351_PMIC_RG_OTP_DOUT_272_287_ADDR, + MT6351_PMIC_RG_OTP_DOUT_272_287_MASK, MT6351_PMIC_RG_OTP_DOUT_272_287_SHIFT}, + {PMIC_RG_OTP_DOUT_288_303, MT6351_PMIC_RG_OTP_DOUT_288_303_ADDR, + MT6351_PMIC_RG_OTP_DOUT_288_303_MASK, MT6351_PMIC_RG_OTP_DOUT_288_303_SHIFT}, + {PMIC_RG_OTP_DOUT_304_319, MT6351_PMIC_RG_OTP_DOUT_304_319_ADDR, + MT6351_PMIC_RG_OTP_DOUT_304_319_MASK, MT6351_PMIC_RG_OTP_DOUT_304_319_SHIFT}, + {PMIC_RG_OTP_DOUT_320_335, MT6351_PMIC_RG_OTP_DOUT_320_335_ADDR, + MT6351_PMIC_RG_OTP_DOUT_320_335_MASK, MT6351_PMIC_RG_OTP_DOUT_320_335_SHIFT}, + {PMIC_RG_OTP_DOUT_336_351, MT6351_PMIC_RG_OTP_DOUT_336_351_ADDR, + MT6351_PMIC_RG_OTP_DOUT_336_351_MASK, MT6351_PMIC_RG_OTP_DOUT_336_351_SHIFT}, + {PMIC_RG_OTP_DOUT_352_367, MT6351_PMIC_RG_OTP_DOUT_352_367_ADDR, + MT6351_PMIC_RG_OTP_DOUT_352_367_MASK, MT6351_PMIC_RG_OTP_DOUT_352_367_SHIFT}, + {PMIC_RG_OTP_DOUT_368_383, MT6351_PMIC_RG_OTP_DOUT_368_383_ADDR, + MT6351_PMIC_RG_OTP_DOUT_368_383_MASK, MT6351_PMIC_RG_OTP_DOUT_368_383_SHIFT}, + {PMIC_RG_OTP_DOUT_384_399, MT6351_PMIC_RG_OTP_DOUT_384_399_ADDR, + MT6351_PMIC_RG_OTP_DOUT_384_399_MASK, MT6351_PMIC_RG_OTP_DOUT_384_399_SHIFT}, + {PMIC_RG_OTP_DOUT_400_415, MT6351_PMIC_RG_OTP_DOUT_400_415_ADDR, + MT6351_PMIC_RG_OTP_DOUT_400_415_MASK, MT6351_PMIC_RG_OTP_DOUT_400_415_SHIFT}, + {PMIC_RG_OTP_DOUT_416_431, MT6351_PMIC_RG_OTP_DOUT_416_431_ADDR, + MT6351_PMIC_RG_OTP_DOUT_416_431_MASK, MT6351_PMIC_RG_OTP_DOUT_416_431_SHIFT}, + {PMIC_RG_OTP_DOUT_432_447, MT6351_PMIC_RG_OTP_DOUT_432_447_ADDR, + MT6351_PMIC_RG_OTP_DOUT_432_447_MASK, MT6351_PMIC_RG_OTP_DOUT_432_447_SHIFT}, + {PMIC_RG_OTP_DOUT_448_463, MT6351_PMIC_RG_OTP_DOUT_448_463_ADDR, + MT6351_PMIC_RG_OTP_DOUT_448_463_MASK, MT6351_PMIC_RG_OTP_DOUT_448_463_SHIFT}, + {PMIC_RG_OTP_DOUT_464_479, MT6351_PMIC_RG_OTP_DOUT_464_479_ADDR, + MT6351_PMIC_RG_OTP_DOUT_464_479_MASK, MT6351_PMIC_RG_OTP_DOUT_464_479_SHIFT}, + {PMIC_RG_OTP_DOUT_480_495, MT6351_PMIC_RG_OTP_DOUT_480_495_ADDR, + MT6351_PMIC_RG_OTP_DOUT_480_495_MASK, MT6351_PMIC_RG_OTP_DOUT_480_495_SHIFT}, + {PMIC_RG_OTP_DOUT_496_511, MT6351_PMIC_RG_OTP_DOUT_496_511_ADDR, + MT6351_PMIC_RG_OTP_DOUT_496_511_MASK, MT6351_PMIC_RG_OTP_DOUT_496_511_SHIFT}, + {PMIC_RG_OTP_VAL_0_15, MT6351_PMIC_RG_OTP_VAL_0_15_ADDR, + MT6351_PMIC_RG_OTP_VAL_0_15_MASK, MT6351_PMIC_RG_OTP_VAL_0_15_SHIFT}, + {PMIC_RG_OTP_VAL_16_31, MT6351_PMIC_RG_OTP_VAL_16_31_ADDR, + MT6351_PMIC_RG_OTP_VAL_16_31_MASK, MT6351_PMIC_RG_OTP_VAL_16_31_SHIFT}, + {PMIC_RG_OTP_VAL_32_47, MT6351_PMIC_RG_OTP_VAL_32_47_ADDR, + MT6351_PMIC_RG_OTP_VAL_32_47_MASK, MT6351_PMIC_RG_OTP_VAL_32_47_SHIFT}, + {PMIC_RG_OTP_VAL_48_63, MT6351_PMIC_RG_OTP_VAL_48_63_ADDR, + MT6351_PMIC_RG_OTP_VAL_48_63_MASK, MT6351_PMIC_RG_OTP_VAL_48_63_SHIFT}, + {PMIC_RG_OTP_VAL_64_79, MT6351_PMIC_RG_OTP_VAL_64_79_ADDR, + MT6351_PMIC_RG_OTP_VAL_64_79_MASK, MT6351_PMIC_RG_OTP_VAL_64_79_SHIFT}, + {PMIC_RG_OTP_VAL_80_95, MT6351_PMIC_RG_OTP_VAL_80_95_ADDR, + MT6351_PMIC_RG_OTP_VAL_80_95_MASK, MT6351_PMIC_RG_OTP_VAL_80_95_SHIFT}, + {PMIC_RG_OTP_VAL_96_111, MT6351_PMIC_RG_OTP_VAL_96_111_ADDR, + MT6351_PMIC_RG_OTP_VAL_96_111_MASK, MT6351_PMIC_RG_OTP_VAL_96_111_SHIFT}, + {PMIC_RG_OTP_VAL_112_127, MT6351_PMIC_RG_OTP_VAL_112_127_ADDR, + MT6351_PMIC_RG_OTP_VAL_112_127_MASK, MT6351_PMIC_RG_OTP_VAL_112_127_SHIFT}, + {PMIC_RG_OTP_VAL_128_143, MT6351_PMIC_RG_OTP_VAL_128_143_ADDR, + MT6351_PMIC_RG_OTP_VAL_128_143_MASK, MT6351_PMIC_RG_OTP_VAL_128_143_SHIFT}, + {PMIC_RG_OTP_VAL_144_159, MT6351_PMIC_RG_OTP_VAL_144_159_ADDR, + MT6351_PMIC_RG_OTP_VAL_144_159_MASK, MT6351_PMIC_RG_OTP_VAL_144_159_SHIFT}, + {PMIC_RG_OTP_VAL_160_175, MT6351_PMIC_RG_OTP_VAL_160_175_ADDR, + MT6351_PMIC_RG_OTP_VAL_160_175_MASK, MT6351_PMIC_RG_OTP_VAL_160_175_SHIFT}, + {PMIC_RG_OTP_VAL_176_191, MT6351_PMIC_RG_OTP_VAL_176_191_ADDR, + MT6351_PMIC_RG_OTP_VAL_176_191_MASK, MT6351_PMIC_RG_OTP_VAL_176_191_SHIFT}, + {PMIC_RG_OTP_VAL_192_207, MT6351_PMIC_RG_OTP_VAL_192_207_ADDR, + MT6351_PMIC_RG_OTP_VAL_192_207_MASK, MT6351_PMIC_RG_OTP_VAL_192_207_SHIFT}, + {PMIC_RG_OTP_VAL_208_223, MT6351_PMIC_RG_OTP_VAL_208_223_ADDR, + MT6351_PMIC_RG_OTP_VAL_208_223_MASK, MT6351_PMIC_RG_OTP_VAL_208_223_SHIFT}, + {PMIC_RG_OTP_VAL_224_239, MT6351_PMIC_RG_OTP_VAL_224_239_ADDR, + MT6351_PMIC_RG_OTP_VAL_224_239_MASK, MT6351_PMIC_RG_OTP_VAL_224_239_SHIFT}, + {PMIC_RG_OTP_VAL_240_255, MT6351_PMIC_RG_OTP_VAL_240_255_ADDR, + MT6351_PMIC_RG_OTP_VAL_240_255_MASK, MT6351_PMIC_RG_OTP_VAL_240_255_SHIFT}, + {PMIC_RG_OTP_VAL_256_271, MT6351_PMIC_RG_OTP_VAL_256_271_ADDR, + MT6351_PMIC_RG_OTP_VAL_256_271_MASK, MT6351_PMIC_RG_OTP_VAL_256_271_SHIFT}, + {PMIC_RG_OTP_VAL_272_287, MT6351_PMIC_RG_OTP_VAL_272_287_ADDR, + MT6351_PMIC_RG_OTP_VAL_272_287_MASK, MT6351_PMIC_RG_OTP_VAL_272_287_SHIFT}, + {PMIC_RG_OTP_VAL_288_303, MT6351_PMIC_RG_OTP_VAL_288_303_ADDR, + MT6351_PMIC_RG_OTP_VAL_288_303_MASK, MT6351_PMIC_RG_OTP_VAL_288_303_SHIFT}, + {PMIC_RG_OTP_VAL_304_319, MT6351_PMIC_RG_OTP_VAL_304_319_ADDR, + MT6351_PMIC_RG_OTP_VAL_304_319_MASK, MT6351_PMIC_RG_OTP_VAL_304_319_SHIFT}, + {PMIC_RG_OTP_VAL_320_335, MT6351_PMIC_RG_OTP_VAL_320_335_ADDR, + MT6351_PMIC_RG_OTP_VAL_320_335_MASK, MT6351_PMIC_RG_OTP_VAL_320_335_SHIFT}, + {PMIC_RG_OTP_VAL_336_351, MT6351_PMIC_RG_OTP_VAL_336_351_ADDR, + MT6351_PMIC_RG_OTP_VAL_336_351_MASK, MT6351_PMIC_RG_OTP_VAL_336_351_SHIFT}, + {PMIC_RG_OTP_VAL_352_367, MT6351_PMIC_RG_OTP_VAL_352_367_ADDR, + MT6351_PMIC_RG_OTP_VAL_352_367_MASK, MT6351_PMIC_RG_OTP_VAL_352_367_SHIFT}, + {PMIC_RG_OTP_VAL_368_383, MT6351_PMIC_RG_OTP_VAL_368_383_ADDR, + MT6351_PMIC_RG_OTP_VAL_368_383_MASK, MT6351_PMIC_RG_OTP_VAL_368_383_SHIFT}, + {PMIC_RG_OTP_VAL_384_399, MT6351_PMIC_RG_OTP_VAL_384_399_ADDR, + MT6351_PMIC_RG_OTP_VAL_384_399_MASK, MT6351_PMIC_RG_OTP_VAL_384_399_SHIFT}, + {PMIC_RG_OTP_VAL_400_415, MT6351_PMIC_RG_OTP_VAL_400_415_ADDR, + MT6351_PMIC_RG_OTP_VAL_400_415_MASK, MT6351_PMIC_RG_OTP_VAL_400_415_SHIFT}, + {PMIC_RG_OTP_VAL_416_431, MT6351_PMIC_RG_OTP_VAL_416_431_ADDR, + MT6351_PMIC_RG_OTP_VAL_416_431_MASK, MT6351_PMIC_RG_OTP_VAL_416_431_SHIFT}, + {PMIC_RG_OTP_VAL_432_447, MT6351_PMIC_RG_OTP_VAL_432_447_ADDR, + MT6351_PMIC_RG_OTP_VAL_432_447_MASK, MT6351_PMIC_RG_OTP_VAL_432_447_SHIFT}, + {PMIC_RG_OTP_VAL_448_463, MT6351_PMIC_RG_OTP_VAL_448_463_ADDR, + MT6351_PMIC_RG_OTP_VAL_448_463_MASK, MT6351_PMIC_RG_OTP_VAL_448_463_SHIFT}, + {PMIC_RG_OTP_VAL_464_479, MT6351_PMIC_RG_OTP_VAL_464_479_ADDR, + MT6351_PMIC_RG_OTP_VAL_464_479_MASK, MT6351_PMIC_RG_OTP_VAL_464_479_SHIFT}, + {PMIC_RG_OTP_VAL_480_495, MT6351_PMIC_RG_OTP_VAL_480_495_ADDR, + MT6351_PMIC_RG_OTP_VAL_480_495_MASK, MT6351_PMIC_RG_OTP_VAL_480_495_SHIFT}, + {PMIC_RG_OTP_VAL_496_511, MT6351_PMIC_RG_OTP_VAL_496_511_ADDR, + MT6351_PMIC_RG_OTP_VAL_496_511_MASK, MT6351_PMIC_RG_OTP_VAL_496_511_SHIFT}, + {PMIC_MIX_EOSC32_STP_LPDTB, MT6351_PMIC_MIX_EOSC32_STP_LPDTB_ADDR, + MT6351_PMIC_MIX_EOSC32_STP_LPDTB_MASK, MT6351_PMIC_MIX_EOSC32_STP_LPDTB_SHIFT}, + {PMIC_MIX_EOSC32_STP_LPDEN, MT6351_PMIC_MIX_EOSC32_STP_LPDEN_ADDR, + MT6351_PMIC_MIX_EOSC32_STP_LPDEN_MASK, MT6351_PMIC_MIX_EOSC32_STP_LPDEN_SHIFT}, + {PMIC_MIX_XOSC32_STP_PWDB, MT6351_PMIC_MIX_XOSC32_STP_PWDB_ADDR, + MT6351_PMIC_MIX_XOSC32_STP_PWDB_MASK, MT6351_PMIC_MIX_XOSC32_STP_PWDB_SHIFT}, + {PMIC_MIX_XOSC32_STP_LPDTB, MT6351_PMIC_MIX_XOSC32_STP_LPDTB_ADDR, + MT6351_PMIC_MIX_XOSC32_STP_LPDTB_MASK, MT6351_PMIC_MIX_XOSC32_STP_LPDTB_SHIFT}, + {PMIC_MIX_XOSC32_STP_LPDEN, MT6351_PMIC_MIX_XOSC32_STP_LPDEN_ADDR, + MT6351_PMIC_MIX_XOSC32_STP_LPDEN_MASK, MT6351_PMIC_MIX_XOSC32_STP_LPDEN_SHIFT}, + {PMIC_MIX_XOSC32_STP_LPDRST, MT6351_PMIC_MIX_XOSC32_STP_LPDRST_ADDR, + MT6351_PMIC_MIX_XOSC32_STP_LPDRST_MASK, MT6351_PMIC_MIX_XOSC32_STP_LPDRST_SHIFT}, + {PMIC_MIX_XOSC32_STP_CALI, MT6351_PMIC_MIX_XOSC32_STP_CALI_ADDR, + MT6351_PMIC_MIX_XOSC32_STP_CALI_MASK, MT6351_PMIC_MIX_XOSC32_STP_CALI_SHIFT}, + {PMIC_STMP_MODE, MT6351_PMIC_STMP_MODE_ADDR, MT6351_PMIC_STMP_MODE_MASK, + MT6351_PMIC_STMP_MODE_SHIFT}, + {PMIC_MIX_EOSC32_STP_CHOP_EN, MT6351_PMIC_MIX_EOSC32_STP_CHOP_EN_ADDR, + MT6351_PMIC_MIX_EOSC32_STP_CHOP_EN_MASK, MT6351_PMIC_MIX_EOSC32_STP_CHOP_EN_SHIFT}, + {PMIC_MIX_DCXO_STP_LVSH_EN, MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_ADDR, + MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_MASK, MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_SHIFT}, + {PMIC_MIX_PMU_STP_DDLO_VRTC, MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_ADDR, + MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_MASK, MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_SHIFT}, + {PMIC_MIX_PMU_STP_DDLO_VRTC_EN, MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_EN_ADDR, + MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_EN_MASK, MT6351_PMIC_MIX_PMU_STP_DDLO_VRTC_EN_SHIFT}, + {PMIC_MIX_RTC_STP_XOSC32_ENB, MT6351_PMIC_MIX_RTC_STP_XOSC32_ENB_ADDR, + MT6351_PMIC_MIX_RTC_STP_XOSC32_ENB_MASK, MT6351_PMIC_MIX_RTC_STP_XOSC32_ENB_SHIFT}, + {PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE, + MT6351_PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_ADDR, + MT6351_PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_MASK, + MT6351_PMIC_MIX_DCXO_STP_TEST_DEGLITCH_MODE_SHIFT}, + {PMIC_MIX_EOSC32_STP_RSV, MT6351_PMIC_MIX_EOSC32_STP_RSV_ADDR, + MT6351_PMIC_MIX_EOSC32_STP_RSV_MASK, MT6351_PMIC_MIX_EOSC32_STP_RSV_SHIFT}, + {PMIC_MIX_EOSC32_VCT_EN, MT6351_PMIC_MIX_EOSC32_VCT_EN_ADDR, + MT6351_PMIC_MIX_EOSC32_VCT_EN_MASK, MT6351_PMIC_MIX_EOSC32_VCT_EN_SHIFT}, + {PMIC_MIX_EOSC32_OPT, MT6351_PMIC_MIX_EOSC32_OPT_ADDR, + MT6351_PMIC_MIX_EOSC32_OPT_MASK, MT6351_PMIC_MIX_EOSC32_OPT_SHIFT}, + {PMIC_MIX_DCXO_STP_LVSH_EN_INT, MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_INT_ADDR, + MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_INT_MASK, MT6351_PMIC_MIX_DCXO_STP_LVSH_EN_INT_SHIFT}, + {PMIC_MIX_RTC_GPIO_COREDETB, MT6351_PMIC_MIX_RTC_GPIO_COREDETB_ADDR, + MT6351_PMIC_MIX_RTC_GPIO_COREDETB_MASK, MT6351_PMIC_MIX_RTC_GPIO_COREDETB_SHIFT}, + {PMIC_MIX_RTC_GPIO_F32KOB, MT6351_PMIC_MIX_RTC_GPIO_F32KOB_ADDR, + MT6351_PMIC_MIX_RTC_GPIO_F32KOB_MASK, MT6351_PMIC_MIX_RTC_GPIO_F32KOB_SHIFT}, + {PMIC_MIX_RTC_GPIO_GPO, MT6351_PMIC_MIX_RTC_GPIO_GPO_ADDR, + MT6351_PMIC_MIX_RTC_GPIO_GPO_MASK, MT6351_PMIC_MIX_RTC_GPIO_GPO_SHIFT}, + {PMIC_MIX_RTC_GPIO_OE, MT6351_PMIC_MIX_RTC_GPIO_OE_ADDR, + MT6351_PMIC_MIX_RTC_GPIO_OE_MASK, MT6351_PMIC_MIX_RTC_GPIO_OE_SHIFT}, + {PMIC_MIX_RTC_STP_DEBUG_OUT, MT6351_PMIC_MIX_RTC_STP_DEBUG_OUT_ADDR, + MT6351_PMIC_MIX_RTC_STP_DEBUG_OUT_MASK, MT6351_PMIC_MIX_RTC_STP_DEBUG_OUT_SHIFT}, + {PMIC_MIX_RTC_STP_DEBUG_SEL, MT6351_PMIC_MIX_RTC_STP_DEBUG_SEL_ADDR, + MT6351_PMIC_MIX_RTC_STP_DEBUG_SEL_MASK, MT6351_PMIC_MIX_RTC_STP_DEBUG_SEL_SHIFT}, + {PMIC_MIX_RTC_STP_K_EOSC32_EN, MT6351_PMIC_MIX_RTC_STP_K_EOSC32_EN_ADDR, + MT6351_PMIC_MIX_RTC_STP_K_EOSC32_EN_MASK, MT6351_PMIC_MIX_RTC_STP_K_EOSC32_EN_SHIFT}, + {PMIC_MIX_RTC_STP_EMBCK_SEL, MT6351_PMIC_MIX_RTC_STP_EMBCK_SEL_ADDR, + MT6351_PMIC_MIX_RTC_STP_EMBCK_SEL_MASK, MT6351_PMIC_MIX_RTC_STP_EMBCK_SEL_SHIFT}, + {PMIC_MIX_STP_BBWAKEUP, MT6351_PMIC_MIX_STP_BBWAKEUP_ADDR, + MT6351_PMIC_MIX_STP_BBWAKEUP_MASK, MT6351_PMIC_MIX_STP_BBWAKEUP_SHIFT}, + {PMIC_MIX_STP_RTC_DDLO, MT6351_PMIC_MIX_STP_RTC_DDLO_ADDR, + MT6351_PMIC_MIX_STP_RTC_DDLO_MASK, MT6351_PMIC_MIX_STP_RTC_DDLO_SHIFT}, + {PMIC_MIX_RTC_XOSC32_ENB, MT6351_PMIC_MIX_RTC_XOSC32_ENB_ADDR, + MT6351_PMIC_MIX_RTC_XOSC32_ENB_MASK, MT6351_PMIC_MIX_RTC_XOSC32_ENB_SHIFT}, + {PMIC_MIX_EFUSE_XOSC32_ENB_OPT, MT6351_PMIC_MIX_EFUSE_XOSC32_ENB_OPT_ADDR, + MT6351_PMIC_MIX_EFUSE_XOSC32_ENB_OPT_MASK, MT6351_PMIC_MIX_EFUSE_XOSC32_ENB_OPT_SHIFT}, + {PMIC_FG_ON, MT6351_PMIC_FG_ON_ADDR, MT6351_PMIC_FG_ON_MASK, + MT6351_PMIC_FG_ON_SHIFT}, + {PMIC_FG_CAL, MT6351_PMIC_FG_CAL_ADDR, MT6351_PMIC_FG_CAL_MASK, + MT6351_PMIC_FG_CAL_SHIFT}, + {PMIC_FG_AUTOCALRATE, MT6351_PMIC_FG_AUTOCALRATE_ADDR, + MT6351_PMIC_FG_AUTOCALRATE_MASK, MT6351_PMIC_FG_AUTOCALRATE_SHIFT}, + {PMIC_FG_SW_CR, MT6351_PMIC_FG_SW_CR_ADDR, MT6351_PMIC_FG_SW_CR_MASK, + MT6351_PMIC_FG_SW_CR_SHIFT}, + {PMIC_FG_SW_READ_PRE, MT6351_PMIC_FG_SW_READ_PRE_ADDR, + MT6351_PMIC_FG_SW_READ_PRE_MASK, MT6351_PMIC_FG_SW_READ_PRE_SHIFT}, + {PMIC_FG_LATCHDATA_ST, MT6351_PMIC_FG_LATCHDATA_ST_ADDR, + MT6351_PMIC_FG_LATCHDATA_ST_MASK, MT6351_PMIC_FG_LATCHDATA_ST_SHIFT}, + {PMIC_FG_SW_CLEAR, MT6351_PMIC_FG_SW_CLEAR_ADDR, MT6351_PMIC_FG_SW_CLEAR_MASK, + MT6351_PMIC_FG_SW_CLEAR_SHIFT}, + {PMIC_FG_OFFSET_RST, MT6351_PMIC_FG_OFFSET_RST_ADDR, + MT6351_PMIC_FG_OFFSET_RST_MASK, MT6351_PMIC_FG_OFFSET_RST_SHIFT}, + {PMIC_FG_TIME_RST, MT6351_PMIC_FG_TIME_RST_ADDR, MT6351_PMIC_FG_TIME_RST_MASK, + MT6351_PMIC_FG_TIME_RST_SHIFT}, + {PMIC_FG_CHARGE_RST, MT6351_PMIC_FG_CHARGE_RST_ADDR, + MT6351_PMIC_FG_CHARGE_RST_MASK, MT6351_PMIC_FG_CHARGE_RST_SHIFT}, + {PMIC_FG_SW_RSTCLR, MT6351_PMIC_FG_SW_RSTCLR_ADDR, MT6351_PMIC_FG_SW_RSTCLR_MASK, + MT6351_PMIC_FG_SW_RSTCLR_SHIFT}, + {PMIC_FG_CAR_34_19, MT6351_PMIC_FG_CAR_34_19_ADDR, MT6351_PMIC_FG_CAR_34_19_MASK, + MT6351_PMIC_FG_CAR_34_19_SHIFT}, + {PMIC_FG_CAR_18_03, MT6351_PMIC_FG_CAR_18_03_ADDR, MT6351_PMIC_FG_CAR_18_03_MASK, + MT6351_PMIC_FG_CAR_18_03_SHIFT}, + {PMIC_FG_CAR_02_00, MT6351_PMIC_FG_CAR_02_00_ADDR, MT6351_PMIC_FG_CAR_02_00_MASK, + MT6351_PMIC_FG_CAR_02_00_SHIFT}, + {PMIC_FG_NTER_32_17, MT6351_PMIC_FG_NTER_32_17_ADDR, + MT6351_PMIC_FG_NTER_32_17_MASK, MT6351_PMIC_FG_NTER_32_17_SHIFT}, + {PMIC_FG_NTER_16_01, MT6351_PMIC_FG_NTER_16_01_ADDR, + MT6351_PMIC_FG_NTER_16_01_MASK, MT6351_PMIC_FG_NTER_16_01_SHIFT}, + {PMIC_FG_NTER_00, MT6351_PMIC_FG_NTER_00_ADDR, MT6351_PMIC_FG_NTER_00_MASK, + MT6351_PMIC_FG_NTER_00_SHIFT}, + {PMIC_FG_BLTR_31_16, MT6351_PMIC_FG_BLTR_31_16_ADDR, + MT6351_PMIC_FG_BLTR_31_16_MASK, MT6351_PMIC_FG_BLTR_31_16_SHIFT}, + {PMIC_FG_BLTR_15_00, MT6351_PMIC_FG_BLTR_15_00_ADDR, + MT6351_PMIC_FG_BLTR_15_00_MASK, MT6351_PMIC_FG_BLTR_15_00_SHIFT}, + {PMIC_FG_BFTR_31_16, MT6351_PMIC_FG_BFTR_31_16_ADDR, + MT6351_PMIC_FG_BFTR_31_16_MASK, MT6351_PMIC_FG_BFTR_31_16_SHIFT}, + {PMIC_FG_BFTR_15_00, MT6351_PMIC_FG_BFTR_15_00_ADDR, + MT6351_PMIC_FG_BFTR_15_00_MASK, MT6351_PMIC_FG_BFTR_15_00_SHIFT}, + {PMIC_FG_CURRENT_OUT, MT6351_PMIC_FG_CURRENT_OUT_ADDR, + MT6351_PMIC_FG_CURRENT_OUT_MASK, MT6351_PMIC_FG_CURRENT_OUT_SHIFT}, + {PMIC_FG_ADJUST_OFFSET_VALUE, MT6351_PMIC_FG_ADJUST_OFFSET_VALUE_ADDR, + MT6351_PMIC_FG_ADJUST_OFFSET_VALUE_MASK, MT6351_PMIC_FG_ADJUST_OFFSET_VALUE_SHIFT}, + {PMIC_FG_OFFSET, MT6351_PMIC_FG_OFFSET_ADDR, MT6351_PMIC_FG_OFFSET_MASK, + MT6351_PMIC_FG_OFFSET_SHIFT}, + {PMIC_RG_FGANALOGTEST, MT6351_PMIC_RG_FGANALOGTEST_ADDR, + MT6351_PMIC_RG_FGANALOGTEST_MASK, MT6351_PMIC_RG_FGANALOGTEST_SHIFT}, + {PMIC_RG_FGRINTMODE, MT6351_PMIC_RG_FGRINTMODE_ADDR, + MT6351_PMIC_RG_FGRINTMODE_MASK, MT6351_PMIC_RG_FGRINTMODE_SHIFT}, + {PMIC_RG_SPARE, MT6351_PMIC_RG_SPARE_ADDR, MT6351_PMIC_RG_SPARE_MASK, + MT6351_PMIC_RG_SPARE_SHIFT}, + {PMIC_FG_OSR, MT6351_PMIC_FG_OSR_ADDR, MT6351_PMIC_FG_OSR_MASK, + MT6351_PMIC_FG_OSR_SHIFT}, + {PMIC_FG_ADJ_OFFSET_EN, MT6351_PMIC_FG_ADJ_OFFSET_EN_ADDR, + MT6351_PMIC_FG_ADJ_OFFSET_EN_MASK, MT6351_PMIC_FG_ADJ_OFFSET_EN_SHIFT}, + {PMIC_FG_ADC_AUTORST, MT6351_PMIC_FG_ADC_AUTORST_ADDR, + MT6351_PMIC_FG_ADC_AUTORST_MASK, MT6351_PMIC_FG_ADC_AUTORST_SHIFT}, + {PMIC_FG_FIR1BYPASS, MT6351_PMIC_FG_FIR1BYPASS_ADDR, + MT6351_PMIC_FG_FIR1BYPASS_MASK, MT6351_PMIC_FG_FIR1BYPASS_SHIFT}, + {PMIC_FG_FIR2BYPASS, MT6351_PMIC_FG_FIR2BYPASS_ADDR, + MT6351_PMIC_FG_FIR2BYPASS_MASK, MT6351_PMIC_FG_FIR2BYPASS_SHIFT}, + {PMIC_FG_L_CUR_INT_STS, MT6351_PMIC_FG_L_CUR_INT_STS_ADDR, + MT6351_PMIC_FG_L_CUR_INT_STS_MASK, MT6351_PMIC_FG_L_CUR_INT_STS_SHIFT}, + {PMIC_FG_H_CUR_INT_STS, MT6351_PMIC_FG_H_CUR_INT_STS_ADDR, + MT6351_PMIC_FG_H_CUR_INT_STS_MASK, MT6351_PMIC_FG_H_CUR_INT_STS_SHIFT}, + {PMIC_FG_L_INT_STS, MT6351_PMIC_FG_L_INT_STS_ADDR, MT6351_PMIC_FG_L_INT_STS_MASK, + MT6351_PMIC_FG_L_INT_STS_SHIFT}, + {PMIC_FG_H_INT_STS, MT6351_PMIC_FG_H_INT_STS_ADDR, MT6351_PMIC_FG_H_INT_STS_MASK, + MT6351_PMIC_FG_H_INT_STS_SHIFT}, + {PMIC_FG_ADC_RSTDETECT, MT6351_PMIC_FG_ADC_RSTDETECT_ADDR, + MT6351_PMIC_FG_ADC_RSTDETECT_MASK, MT6351_PMIC_FG_ADC_RSTDETECT_SHIFT}, + {PMIC_FG_SLP_EN, MT6351_PMIC_FG_SLP_EN_ADDR, MT6351_PMIC_FG_SLP_EN_MASK, + MT6351_PMIC_FG_SLP_EN_SHIFT}, + {PMIC_FG_ZCV_DET_EN, MT6351_PMIC_FG_ZCV_DET_EN_ADDR, + MT6351_PMIC_FG_ZCV_DET_EN_MASK, MT6351_PMIC_FG_ZCV_DET_EN_SHIFT}, + {PMIC_RG_FG_AUXADC_R, MT6351_PMIC_RG_FG_AUXADC_R_ADDR, + MT6351_PMIC_RG_FG_AUXADC_R_MASK, MT6351_PMIC_RG_FG_AUXADC_R_SHIFT}, + {PMIC_DA_FGADC_EN, MT6351_PMIC_DA_FGADC_EN_ADDR, MT6351_PMIC_DA_FGADC_EN_MASK, + MT6351_PMIC_DA_FGADC_EN_SHIFT}, + {PMIC_DA_FGCAL_EN, MT6351_PMIC_DA_FGCAL_EN_ADDR, MT6351_PMIC_DA_FGCAL_EN_MASK, + MT6351_PMIC_DA_FGCAL_EN_SHIFT}, + {PMIC_DA_FG_RST, MT6351_PMIC_DA_FG_RST_ADDR, MT6351_PMIC_DA_FG_RST_MASK, + MT6351_PMIC_DA_FG_RST_SHIFT}, + {PMIC_FG_CIC2, MT6351_PMIC_FG_CIC2_ADDR, MT6351_PMIC_FG_CIC2_MASK, + MT6351_PMIC_FG_CIC2_SHIFT}, + {PMIC_FG_SLP_CUR_TH, MT6351_PMIC_FG_SLP_CUR_TH_ADDR, + MT6351_PMIC_FG_SLP_CUR_TH_MASK, MT6351_PMIC_FG_SLP_CUR_TH_SHIFT}, + {PMIC_FG_SLP_TIME, MT6351_PMIC_FG_SLP_TIME_ADDR, MT6351_PMIC_FG_SLP_TIME_MASK, + MT6351_PMIC_FG_SLP_TIME_SHIFT}, + {PMIC_FG_SRCVOLTEN_FTIME, MT6351_PMIC_FG_SRCVOLTEN_FTIME_ADDR, + MT6351_PMIC_FG_SRCVOLTEN_FTIME_MASK, MT6351_PMIC_FG_SRCVOLTEN_FTIME_SHIFT}, + {PMIC_FG_DET_TIME, MT6351_PMIC_FG_DET_TIME_ADDR, MT6351_PMIC_FG_DET_TIME_MASK, + MT6351_PMIC_FG_DET_TIME_SHIFT}, + {PMIC_FG_ZCV_CAR_34_19, MT6351_PMIC_FG_ZCV_CAR_34_19_ADDR, + MT6351_PMIC_FG_ZCV_CAR_34_19_MASK, MT6351_PMIC_FG_ZCV_CAR_34_19_SHIFT}, + {PMIC_FG_ZCV_CAR_18_03, MT6351_PMIC_FG_ZCV_CAR_18_03_ADDR, + MT6351_PMIC_FG_ZCV_CAR_18_03_MASK, MT6351_PMIC_FG_ZCV_CAR_18_03_SHIFT}, + {PMIC_FG_ZCV_CAR_02_00, MT6351_PMIC_FG_ZCV_CAR_02_00_ADDR, + MT6351_PMIC_FG_ZCV_CAR_02_00_MASK, MT6351_PMIC_FG_ZCV_CAR_02_00_SHIFT}, + {PMIC_FG_ZCV_CURR, MT6351_PMIC_FG_ZCV_CURR_ADDR, MT6351_PMIC_FG_ZCV_CURR_MASK, + MT6351_PMIC_FG_ZCV_CURR_SHIFT}, + {PMIC_FG_R_CURR, MT6351_PMIC_FG_R_CURR_ADDR, MT6351_PMIC_FG_R_CURR_MASK, + MT6351_PMIC_FG_R_CURR_SHIFT}, + {PMIC_FG_MODE, MT6351_PMIC_FG_MODE_ADDR, MT6351_PMIC_FG_MODE_MASK, + MT6351_PMIC_FG_MODE_SHIFT}, + {PMIC_FG_RST_SW, MT6351_PMIC_FG_RST_SW_ADDR, MT6351_PMIC_FG_RST_SW_MASK, + MT6351_PMIC_FG_RST_SW_SHIFT}, + {PMIC_FG_FGCAL_EN_SW, MT6351_PMIC_FG_FGCAL_EN_SW_ADDR, + MT6351_PMIC_FG_FGCAL_EN_SW_MASK, MT6351_PMIC_FG_FGCAL_EN_SW_SHIFT}, + {PMIC_FG_FGADC_EN_SW, MT6351_PMIC_FG_FGADC_EN_SW_ADDR, + MT6351_PMIC_FG_FGADC_EN_SW_MASK, MT6351_PMIC_FG_FGADC_EN_SW_SHIFT}, + {PMIC_FG_RSV1, MT6351_PMIC_FG_RSV1_ADDR, MT6351_PMIC_FG_RSV1_MASK, + MT6351_PMIC_FG_RSV1_SHIFT}, + {PMIC_FG_TEST_MODE0, MT6351_PMIC_FG_TEST_MODE0_ADDR, + MT6351_PMIC_FG_TEST_MODE0_MASK, MT6351_PMIC_FG_TEST_MODE0_SHIFT}, + {PMIC_FG_TEST_MODE1, MT6351_PMIC_FG_TEST_MODE1_ADDR, + MT6351_PMIC_FG_TEST_MODE1_MASK, MT6351_PMIC_FG_TEST_MODE1_SHIFT}, + {PMIC_FG_GAIN, MT6351_PMIC_FG_GAIN_ADDR, MT6351_PMIC_FG_GAIN_MASK, + MT6351_PMIC_FG_GAIN_SHIFT}, + {PMIC_FG_CUR_HTH, MT6351_PMIC_FG_CUR_HTH_ADDR, MT6351_PMIC_FG_CUR_HTH_MASK, + MT6351_PMIC_FG_CUR_HTH_SHIFT}, + {PMIC_FG_CUR_LTH, MT6351_PMIC_FG_CUR_LTH_ADDR, MT6351_PMIC_FG_CUR_LTH_MASK, + MT6351_PMIC_FG_CUR_LTH_SHIFT}, + {PMIC_FG_ZCV_DET_TIME, MT6351_PMIC_FG_ZCV_DET_TIME_ADDR, + MT6351_PMIC_FG_ZCV_DET_TIME_MASK, MT6351_PMIC_FG_ZCV_DET_TIME_SHIFT}, + {PMIC_FG_ZCV_CAR_TH_33_19, MT6351_PMIC_FG_ZCV_CAR_TH_33_19_ADDR, + MT6351_PMIC_FG_ZCV_CAR_TH_33_19_MASK, MT6351_PMIC_FG_ZCV_CAR_TH_33_19_SHIFT}, + {PMIC_FG_ZCV_CAR_TH_18_03, MT6351_PMIC_FG_ZCV_CAR_TH_18_03_ADDR, + MT6351_PMIC_FG_ZCV_CAR_TH_18_03_MASK, MT6351_PMIC_FG_ZCV_CAR_TH_18_03_SHIFT}, + {PMIC_FG_ZCV_CAR_TH_02_00, MT6351_PMIC_FG_ZCV_CAR_TH_02_00_ADDR, + MT6351_PMIC_FG_ZCV_CAR_TH_02_00_MASK, MT6351_PMIC_FG_ZCV_CAR_TH_02_00_SHIFT}, + {PMIC_SYSTEM_INFO_CON0, MT6351_PMIC_SYSTEM_INFO_CON0_ADDR, + MT6351_PMIC_SYSTEM_INFO_CON0_MASK, MT6351_PMIC_SYSTEM_INFO_CON0_SHIFT}, + {PMIC_SYSTEM_INFO_CON1, MT6351_PMIC_SYSTEM_INFO_CON1_ADDR, + MT6351_PMIC_SYSTEM_INFO_CON1_MASK, MT6351_PMIC_SYSTEM_INFO_CON1_SHIFT}, + {PMIC_SYSTEM_INFO_CON2, MT6351_PMIC_SYSTEM_INFO_CON2_ADDR, + MT6351_PMIC_SYSTEM_INFO_CON2_MASK, MT6351_PMIC_SYSTEM_INFO_CON2_SHIFT}, + {PMIC_SYSTEM_INFO_CON3, MT6351_PMIC_SYSTEM_INFO_CON3_ADDR, + MT6351_PMIC_SYSTEM_INFO_CON3_MASK, MT6351_PMIC_SYSTEM_INFO_CON3_SHIFT}, + {PMIC_SYSTEM_INFO_CON4, MT6351_PMIC_SYSTEM_INFO_CON4_ADDR, + MT6351_PMIC_SYSTEM_INFO_CON4_MASK, MT6351_PMIC_SYSTEM_INFO_CON4_SHIFT}, + {PMIC_RG_AUDDACLPWRUP_VAUDP32, MT6351_PMIC_RG_AUDDACLPWRUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDDACLPWRUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDDACLPWRUP_VAUDP32_SHIFT}, + {PMIC_RG_AUDDACRPWRUP_VAUDP32, MT6351_PMIC_RG_AUDDACRPWRUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDDACRPWRUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDDACRPWRUP_VAUDP32_SHIFT}, + {PMIC_RG_AUD_DAC_PWR_UP_VA32, MT6351_PMIC_RG_AUD_DAC_PWR_UP_VA32_ADDR, + MT6351_PMIC_RG_AUD_DAC_PWR_UP_VA32_MASK, MT6351_PMIC_RG_AUD_DAC_PWR_UP_VA32_SHIFT}, + {PMIC_RG_AUD_DAC_PWL_UP_VA32, MT6351_PMIC_RG_AUD_DAC_PWL_UP_VA32_ADDR, + MT6351_PMIC_RG_AUD_DAC_PWL_UP_VA32_MASK, MT6351_PMIC_RG_AUD_DAC_PWL_UP_VA32_SHIFT}, + {PMIC_RG_AUDHSPWRUP_VAUDP32, MT6351_PMIC_RG_AUDHSPWRUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHSPWRUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDHSPWRUP_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPLPWRUP_VAUDP32, MT6351_PMIC_RG_AUDHPLPWRUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPLPWRUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPLPWRUP_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPRPWRUP_VAUDP32, MT6351_PMIC_RG_AUDHPRPWRUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPRPWRUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPRPWRUP_VAUDP32_SHIFT}, + {PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32, MT6351_PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHSMUXINPUTSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32, MT6351_PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHPLMUXINPUTSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32, MT6351_PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHPRMUXINPUTSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDHSSCDISABLE_VAUDP32, MT6351_PMIC_RG_AUDHSSCDISABLE_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHSSCDISABLE_VAUDP32_MASK, MT6351_PMIC_RG_AUDHSSCDISABLE_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPLSCDISABLE_VAUDP32, MT6351_PMIC_RG_AUDHPLSCDISABLE_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPLSCDISABLE_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHPLSCDISABLE_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPRSCDISABLE_VAUDP32, MT6351_PMIC_RG_AUDHPRSCDISABLE_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPRSCDISABLE_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHPRSCDISABLE_VAUDP32_SHIFT}, + {PMIC_RG_AUDHSBSCCURRENT_VAUDP32, MT6351_PMIC_RG_AUDHSBSCCURRENT_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHSBSCCURRENT_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHSBSCCURRENT_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPLBSCCURRENT_VAUDP32, MT6351_PMIC_RG_AUDHPLBSCCURRENT_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPLBSCCURRENT_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHPLBSCCURRENT_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPRBSCCURRENT_VAUDP32, MT6351_PMIC_RG_AUDHPRBSCCURRENT_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPRBSCCURRENT_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHPRBSCCURRENT_VAUDP32_SHIFT}, + {PMIC_RG_AUDHSSTARTUP_VAUDP32, MT6351_PMIC_RG_AUDHSSTARTUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHSSTARTUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDHSSTARTUP_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPSTARTUP_VAUDP32, MT6351_PMIC_RG_AUDHPSTARTUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPSTARTUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPSTARTUP_VAUDP32_SHIFT}, + {PMIC_RG_AUDBGBON_VAUDP32, MT6351_PMIC_RG_AUDBGBON_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDBGBON_VAUDP32_MASK, MT6351_PMIC_RG_AUDBGBON_VAUDP32_SHIFT}, + {PMIC_RG_PRECHARGEBUF_EN_VAUDP32, MT6351_PMIC_RG_PRECHARGEBUF_EN_VAUDP32_ADDR, + MT6351_PMIC_RG_PRECHARGEBUF_EN_VAUDP32_MASK, + MT6351_PMIC_RG_PRECHARGEBUF_EN_VAUDP32_SHIFT}, + {PMIC_RG_HSINPUTSTBENH_VAUDP32, MT6351_PMIC_RG_HSINPUTSTBENH_VAUDP32_ADDR, + MT6351_PMIC_RG_HSINPUTSTBENH_VAUDP32_MASK, MT6351_PMIC_RG_HSINPUTSTBENH_VAUDP32_SHIFT}, + {PMIC_RG_HSOUTPUTSTBENH_VAUDP32, MT6351_PMIC_RG_HSOUTPUTSTBENH_VAUDP32_ADDR, + MT6351_PMIC_RG_HSOUTPUTSTBENH_VAUDP32_MASK, MT6351_PMIC_RG_HSOUTPUTSTBENH_VAUDP32_SHIFT}, + {PMIC_RG_HSINPUTRESET0_VAUDP32, MT6351_PMIC_RG_HSINPUTRESET0_VAUDP32_ADDR, + MT6351_PMIC_RG_HSINPUTRESET0_VAUDP32_MASK, MT6351_PMIC_RG_HSINPUTRESET0_VAUDP32_SHIFT}, + {PMIC_RG_HSOUTPUTRESET0_VAUDP32, MT6351_PMIC_RG_HSOUTPUTRESET0_VAUDP32_ADDR, + MT6351_PMIC_RG_HSOUTPUTRESET0_VAUDP32_MASK, MT6351_PMIC_RG_HSOUTPUTRESET0_VAUDP32_SHIFT}, + {PMIC_RG_HSOUT_SHORTVCM_VAUDP32, MT6351_PMIC_RG_HSOUT_SHORTVCM_VAUDP32_ADDR, + MT6351_PMIC_RG_HSOUT_SHORTVCM_VAUDP32_MASK, MT6351_PMIC_RG_HSOUT_SHORTVCM_VAUDP32_SHIFT}, + {PMIC_RG_HPINPUTSTBENH_VAUDP32, MT6351_PMIC_RG_HPINPUTSTBENH_VAUDP32_ADDR, + MT6351_PMIC_RG_HPINPUTSTBENH_VAUDP32_MASK, MT6351_PMIC_RG_HPINPUTSTBENH_VAUDP32_SHIFT}, + {PMIC_RG_HPOUTPUTSTBENH_VAUDP32, MT6351_PMIC_RG_HPOUTPUTSTBENH_VAUDP32_ADDR, + MT6351_PMIC_RG_HPOUTPUTSTBENH_VAUDP32_MASK, MT6351_PMIC_RG_HPOUTPUTSTBENH_VAUDP32_SHIFT}, + {PMIC_RG_HPINPUTRESET0_VAUDP32, MT6351_PMIC_RG_HPINPUTRESET0_VAUDP32_ADDR, + MT6351_PMIC_RG_HPINPUTRESET0_VAUDP32_MASK, MT6351_PMIC_RG_HPINPUTRESET0_VAUDP32_SHIFT}, + {PMIC_RG_HPOUTPUTRESET0_VAUDP32, MT6351_PMIC_RG_HPOUTPUTRESET0_VAUDP32_ADDR, + MT6351_PMIC_RG_HPOUTPUTRESET0_VAUDP32_MASK, MT6351_PMIC_RG_HPOUTPUTRESET0_VAUDP32_SHIFT}, + {PMIC_RG_HPOUT_SHORTVCM_VAUDP32, MT6351_PMIC_RG_HPOUT_SHORTVCM_VAUDP32_ADDR, + MT6351_PMIC_RG_HPOUT_SHORTVCM_VAUDP32_MASK, MT6351_PMIC_RG_HPOUT_SHORTVCM_VAUDP32_SHIFT}, + {PMIC_RG_HPOUTSTB_RSEL_VAUDP32, MT6351_PMIC_RG_HPOUTSTB_RSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_HPOUTSTB_RSEL_VAUDP32_MASK, MT6351_PMIC_RG_HPOUTSTB_RSEL_VAUDP32_SHIFT}, + {PMIC_RG_LINENOISEENH_VAUDP32, MT6351_PMIC_RG_LINENOISEENH_VAUDP32_ADDR, + MT6351_PMIC_RG_LINENOISEENH_VAUDP32_MASK, MT6351_PMIC_RG_LINENOISEENH_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPLTRIM_VAUDP32, MT6351_PMIC_RG_AUDHPLTRIM_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPLTRIM_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPLTRIM_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPRTRIM_VAUDP32, MT6351_PMIC_RG_AUDHPRTRIM_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPRTRIM_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPRTRIM_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPTRIM_EN_VAUDP32, MT6351_PMIC_RG_AUDHPTRIM_EN_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPTRIM_EN_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPTRIM_EN_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPLFINETRIM_VAUDP32, MT6351_PMIC_RG_AUDHPLFINETRIM_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPLFINETRIM_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPLFINETRIM_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPRFINETRIM_VAUDP32, MT6351_PMIC_RG_AUDHPRFINETRIM_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPRFINETRIM_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPRFINETRIM_VAUDP32_SHIFT}, + {PMIC_RG_AUDLOLPWRUP_VAUDP32, MT6351_PMIC_RG_AUDLOLPWRUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDLOLPWRUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDLOLPWRUP_VAUDP32_SHIFT}, + {PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32, MT6351_PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32_MASK, + MT6351_PMIC_RG_AUDLOLMUXINPUTSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDLOLSCDISABLE_VAUDP32, MT6351_PMIC_RG_AUDLOLSCDISABLE_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDLOLSCDISABLE_VAUDP32_MASK, + MT6351_PMIC_RG_AUDLOLSCDISABLE_VAUDP32_SHIFT}, + {PMIC_RG_AUDLOLBSCCURRENT_VAUDP32, MT6351_PMIC_RG_AUDLOLBSCCURRENT_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDLOLBSCCURRENT_VAUDP32_MASK, + MT6351_PMIC_RG_AUDLOLBSCCURRENT_VAUDP32_SHIFT}, + {PMIC_RG_AUDLOSTARTUP_VAUDP32, MT6351_PMIC_RG_AUDLOSTARTUP_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDLOSTARTUP_VAUDP32_MASK, MT6351_PMIC_RG_AUDLOSTARTUP_VAUDP32_SHIFT}, + {PMIC_RG_LOINPUTSTBENH_VAUDP32, MT6351_PMIC_RG_LOINPUTSTBENH_VAUDP32_ADDR, + MT6351_PMIC_RG_LOINPUTSTBENH_VAUDP32_MASK, MT6351_PMIC_RG_LOINPUTSTBENH_VAUDP32_SHIFT}, + {PMIC_RG_LOOUTPUTSTBENH_VAUDP32, MT6351_PMIC_RG_LOOUTPUTSTBENH_VAUDP32_ADDR, + MT6351_PMIC_RG_LOOUTPUTSTBENH_VAUDP32_MASK, MT6351_PMIC_RG_LOOUTPUTSTBENH_VAUDP32_SHIFT}, + {PMIC_RG_LOINPUTRESET0_VAUDP32, MT6351_PMIC_RG_LOINPUTRESET0_VAUDP32_ADDR, + MT6351_PMIC_RG_LOINPUTRESET0_VAUDP32_MASK, MT6351_PMIC_RG_LOINPUTRESET0_VAUDP32_SHIFT}, + {PMIC_RG_LOOUTPUTRESET0_VAUDP32, MT6351_PMIC_RG_LOOUTPUTRESET0_VAUDP32_ADDR, + MT6351_PMIC_RG_LOOUTPUTRESET0_VAUDP32_MASK, MT6351_PMIC_RG_LOOUTPUTRESET0_VAUDP32_SHIFT}, + {PMIC_RG_LOOUT_SHORTVCM_VAUDP32, MT6351_PMIC_RG_LOOUT_SHORTVCM_VAUDP32_ADDR, + MT6351_PMIC_RG_LOOUT_SHORTVCM_VAUDP32_MASK, MT6351_PMIC_RG_LOOUT_SHORTVCM_VAUDP32_SHIFT}, + {PMIC_RG_LOOUTSTB_RSEL_VAUDP32, MT6351_PMIC_RG_LOOUTSTB_RSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_LOOUTSTB_RSEL_VAUDP32_MASK, MT6351_PMIC_RG_LOOUTSTB_RSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDLOLTRIM_VAUDP32, MT6351_PMIC_RG_AUDLOLTRIM_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDLOLTRIM_VAUDP32_MASK, MT6351_PMIC_RG_AUDLOLTRIM_VAUDP32_SHIFT}, + {PMIC_RG_AUDLOTRIM_EN_VAUDP32, MT6351_PMIC_RG_AUDLOTRIM_EN_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDLOTRIM_EN_VAUDP32_MASK, MT6351_PMIC_RG_AUDLOTRIM_EN_VAUDP32_SHIFT}, + {PMIC_RG_AUDLOLFINETRIM_VAUDP32, MT6351_PMIC_RG_AUDLOLFINETRIM_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDLOLFINETRIM_VAUDP32_MASK, MT6351_PMIC_RG_AUDLOLFINETRIM_VAUDP32_SHIFT}, + {PMIC_RG_AUDTRIMBUF_EN_VAUDP32, MT6351_PMIC_RG_AUDTRIMBUF_EN_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDTRIMBUF_EN_VAUDP32_MASK, MT6351_PMIC_RG_AUDTRIMBUF_EN_VAUDP32_SHIFT}, + {PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32, + MT6351_PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_MASK, + MT6351_PMIC_RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32, + MT6351_PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32_MASK, + MT6351_PMIC_RG_AUDTRIMBUF_GAINSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPSPKDET_EN_VAUDP32, MT6351_PMIC_RG_AUDHPSPKDET_EN_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPSPKDET_EN_VAUDP32_MASK, MT6351_PMIC_RG_AUDHPSPKDET_EN_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32, + MT6351_PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32, + MT6351_PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_MASK, + MT6351_PMIC_RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_SHIFT}, + {PMIC_RG_ABIDEC_RSVD0_VA32, MT6351_PMIC_RG_ABIDEC_RSVD0_VA32_ADDR, + MT6351_PMIC_RG_ABIDEC_RSVD0_VA32_MASK, MT6351_PMIC_RG_ABIDEC_RSVD0_VA32_SHIFT}, + {PMIC_RG_ABIDEC_RSVD1_VA32, MT6351_PMIC_RG_ABIDEC_RSVD1_VA32_ADDR, + MT6351_PMIC_RG_ABIDEC_RSVD1_VA32_MASK, MT6351_PMIC_RG_ABIDEC_RSVD1_VA32_SHIFT}, + {PMIC_RG_ABIDEC_RSVD0_VAUDP32, MT6351_PMIC_RG_ABIDEC_RSVD0_VAUDP32_ADDR, + MT6351_PMIC_RG_ABIDEC_RSVD0_VAUDP32_MASK, MT6351_PMIC_RG_ABIDEC_RSVD0_VAUDP32_SHIFT}, + {PMIC_RG_ABIDEC_RSVD1_VAUDP32, MT6351_PMIC_RG_ABIDEC_RSVD1_VAUDP32_ADDR, + MT6351_PMIC_RG_ABIDEC_RSVD1_VAUDP32_MASK, MT6351_PMIC_RG_ABIDEC_RSVD1_VAUDP32_SHIFT}, + {PMIC_RG_AUDZCDMUXSEL_VAUDP32, MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP32_MASK, MT6351_PMIC_RG_AUDZCDMUXSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDZCDCLKSEL_VAUDP32, MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP32_MASK, MT6351_PMIC_RG_AUDZCDCLKSEL_VAUDP32_SHIFT}, + {PMIC_RG_AUDBIASADJ_0_VAUDP32, MT6351_PMIC_RG_AUDBIASADJ_0_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDBIASADJ_0_VAUDP32_MASK, MT6351_PMIC_RG_AUDBIASADJ_0_VAUDP32_SHIFT}, + {PMIC_RG_AUDBIASADJ_1_VAUDP32, MT6351_PMIC_RG_AUDBIASADJ_1_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDBIASADJ_1_VAUDP32_MASK, MT6351_PMIC_RG_AUDBIASADJ_1_VAUDP32_SHIFT}, + {PMIC_RG_AUDIBIASPWRDN_VAUDP32, MT6351_PMIC_RG_AUDIBIASPWRDN_VAUDP32_ADDR, + MT6351_PMIC_RG_AUDIBIASPWRDN_VAUDP32_MASK, MT6351_PMIC_RG_AUDIBIASPWRDN_VAUDP32_SHIFT}, + {PMIC_RG_RSTB_DECODER_VA32, MT6351_PMIC_RG_RSTB_DECODER_VA32_ADDR, + MT6351_PMIC_RG_RSTB_DECODER_VA32_MASK, MT6351_PMIC_RG_RSTB_DECODER_VA32_SHIFT}, + {PMIC_RG_SEL_DECODER_96K_VA32, MT6351_PMIC_RG_SEL_DECODER_96K_VA32_ADDR, + MT6351_PMIC_RG_SEL_DECODER_96K_VA32_MASK, MT6351_PMIC_RG_SEL_DECODER_96K_VA32_SHIFT}, + {PMIC_RG_SEL_DELAY_VCORE, MT6351_PMIC_RG_SEL_DELAY_VCORE_ADDR, + MT6351_PMIC_RG_SEL_DELAY_VCORE_MASK, MT6351_PMIC_RG_SEL_DELAY_VCORE_SHIFT}, + {PMIC_RG_AUDGLB_PWRDN_VA32, MT6351_PMIC_RG_AUDGLB_PWRDN_VA32_ADDR, + MT6351_PMIC_RG_AUDGLB_PWRDN_VA32_MASK, MT6351_PMIC_RG_AUDGLB_PWRDN_VA32_SHIFT}, + {PMIC_RG_LCLDO_DEC_EN_VA32, MT6351_PMIC_RG_LCLDO_DEC_EN_VA32_ADDR, + MT6351_PMIC_RG_LCLDO_DEC_EN_VA32_MASK, MT6351_PMIC_RG_LCLDO_DEC_EN_VA32_SHIFT}, + {PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18, MT6351_PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18_ADDR, + MT6351_PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18_MASK, + MT6351_PMIC_RG_LCLDO_DEC_PDDIS_EN_VA18_SHIFT}, + {PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18, + MT6351_PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18_ADDR, + MT6351_PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18_MASK, + MT6351_PMIC_RG_LCLDO_DEC_REMOTE_SENSE_VA18_SHIFT}, + {PMIC_RG_AUDPMU_RSVD_VA18, MT6351_PMIC_RG_AUDPMU_RSVD_VA18_ADDR, + MT6351_PMIC_RG_AUDPMU_RSVD_VA18_MASK, MT6351_PMIC_RG_AUDPMU_RSVD_VA18_SHIFT}, + {PMIC_RG_NVREG_EN_VAUDP32, MT6351_PMIC_RG_NVREG_EN_VAUDP32_ADDR, + MT6351_PMIC_RG_NVREG_EN_VAUDP32_MASK, MT6351_PMIC_RG_NVREG_EN_VAUDP32_SHIFT}, + {PMIC_RG_NVREG_PULL0V_VAUDP32, MT6351_PMIC_RG_NVREG_PULL0V_VAUDP32_ADDR, + MT6351_PMIC_RG_NVREG_PULL0V_VAUDP32_MASK, MT6351_PMIC_RG_NVREG_PULL0V_VAUDP32_SHIFT}, + {PMIC_RG_AUDGLB_LP2_VOW_EN_VA32, MT6351_PMIC_RG_AUDGLB_LP2_VOW_EN_VA32_ADDR, + MT6351_PMIC_RG_AUDGLB_LP2_VOW_EN_VA32_MASK, MT6351_PMIC_RG_AUDGLB_LP2_VOW_EN_VA32_SHIFT}, + {PMIC_RG_AUDPREAMPLON, MT6351_PMIC_RG_AUDPREAMPLON_ADDR, + MT6351_PMIC_RG_AUDPREAMPLON_MASK, MT6351_PMIC_RG_AUDPREAMPLON_SHIFT}, + {PMIC_RG_AUDPREAMPLDCCEN, MT6351_PMIC_RG_AUDPREAMPLDCCEN_ADDR, + MT6351_PMIC_RG_AUDPREAMPLDCCEN_MASK, MT6351_PMIC_RG_AUDPREAMPLDCCEN_SHIFT}, + {PMIC_RG_AUDPREAMPLDCPRECHARGE, MT6351_PMIC_RG_AUDPREAMPLDCPRECHARGE_ADDR, + MT6351_PMIC_RG_AUDPREAMPLDCPRECHARGE_MASK, MT6351_PMIC_RG_AUDPREAMPLDCPRECHARGE_SHIFT}, + {PMIC_RG_AUDPREAMPLPGATEST, MT6351_PMIC_RG_AUDPREAMPLPGATEST_ADDR, + MT6351_PMIC_RG_AUDPREAMPLPGATEST_MASK, MT6351_PMIC_RG_AUDPREAMPLPGATEST_SHIFT}, + {PMIC_RG_AUDPREAMPLINPUTSEL, MT6351_PMIC_RG_AUDPREAMPLINPUTSEL_ADDR, + MT6351_PMIC_RG_AUDPREAMPLINPUTSEL_MASK, MT6351_PMIC_RG_AUDPREAMPLINPUTSEL_SHIFT}, + {PMIC_RG_AUDPREAMPLVSCALE, MT6351_PMIC_RG_AUDPREAMPLVSCALE_ADDR, + MT6351_PMIC_RG_AUDPREAMPLVSCALE_MASK, MT6351_PMIC_RG_AUDPREAMPLVSCALE_SHIFT}, + {PMIC_RG_AUDPREAMPLGAIN, MT6351_PMIC_RG_AUDPREAMPLGAIN_ADDR, + MT6351_PMIC_RG_AUDPREAMPLGAIN_MASK, MT6351_PMIC_RG_AUDPREAMPLGAIN_SHIFT}, + {PMIC_RG_AUDADCLPWRUP, MT6351_PMIC_RG_AUDADCLPWRUP_ADDR, + MT6351_PMIC_RG_AUDADCLPWRUP_MASK, MT6351_PMIC_RG_AUDADCLPWRUP_SHIFT}, + {PMIC_RG_AUDADCLINPUTSEL, MT6351_PMIC_RG_AUDADCLINPUTSEL_ADDR, + MT6351_PMIC_RG_AUDADCLINPUTSEL_MASK, MT6351_PMIC_RG_AUDADCLINPUTSEL_SHIFT}, + {PMIC_RG_AUDPREAMPRON, MT6351_PMIC_RG_AUDPREAMPRON_ADDR, + MT6351_PMIC_RG_AUDPREAMPRON_MASK, MT6351_PMIC_RG_AUDPREAMPRON_SHIFT}, + {PMIC_RG_AUDPREAMPRDCCEN, MT6351_PMIC_RG_AUDPREAMPRDCCEN_ADDR, + MT6351_PMIC_RG_AUDPREAMPRDCCEN_MASK, MT6351_PMIC_RG_AUDPREAMPRDCCEN_SHIFT}, + {PMIC_RG_AUDPREAMPRDCPRECHARGE, MT6351_PMIC_RG_AUDPREAMPRDCPRECHARGE_ADDR, + MT6351_PMIC_RG_AUDPREAMPRDCPRECHARGE_MASK, MT6351_PMIC_RG_AUDPREAMPRDCPRECHARGE_SHIFT}, + {PMIC_RG_AUDPREAMPRPGATEST, MT6351_PMIC_RG_AUDPREAMPRPGATEST_ADDR, + MT6351_PMIC_RG_AUDPREAMPRPGATEST_MASK, MT6351_PMIC_RG_AUDPREAMPRPGATEST_SHIFT}, + {PMIC_RG_AUDPREAMPRINPUTSEL, MT6351_PMIC_RG_AUDPREAMPRINPUTSEL_ADDR, + MT6351_PMIC_RG_AUDPREAMPRINPUTSEL_MASK, MT6351_PMIC_RG_AUDPREAMPRINPUTSEL_SHIFT}, + {PMIC_RG_AUDPREAMPRVSCALE, MT6351_PMIC_RG_AUDPREAMPRVSCALE_ADDR, + MT6351_PMIC_RG_AUDPREAMPRVSCALE_MASK, MT6351_PMIC_RG_AUDPREAMPRVSCALE_SHIFT}, + {PMIC_RG_AUDPREAMPRGAIN, MT6351_PMIC_RG_AUDPREAMPRGAIN_ADDR, + MT6351_PMIC_RG_AUDPREAMPRGAIN_MASK, MT6351_PMIC_RG_AUDPREAMPRGAIN_SHIFT}, + {PMIC_RG_AUDADCRPWRUP, MT6351_PMIC_RG_AUDADCRPWRUP_ADDR, + MT6351_PMIC_RG_AUDADCRPWRUP_MASK, MT6351_PMIC_RG_AUDADCRPWRUP_SHIFT}, + {PMIC_RG_AUDADCRINPUTSEL, MT6351_PMIC_RG_AUDADCRINPUTSEL_ADDR, + MT6351_PMIC_RG_AUDADCRINPUTSEL_MASK, MT6351_PMIC_RG_AUDADCRINPUTSEL_SHIFT}, + {PMIC_RG_AUDULHALFBIAS, MT6351_PMIC_RG_AUDULHALFBIAS_ADDR, + MT6351_PMIC_RG_AUDULHALFBIAS_MASK, MT6351_PMIC_RG_AUDULHALFBIAS_SHIFT}, + {PMIC_RG_AUDGLBVOWLPWEN, MT6351_PMIC_RG_AUDGLBVOWLPWEN_ADDR, + MT6351_PMIC_RG_AUDGLBVOWLPWEN_MASK, MT6351_PMIC_RG_AUDGLBVOWLPWEN_SHIFT}, + {PMIC_RG_AUDPREAMPLPEN, MT6351_PMIC_RG_AUDPREAMPLPEN_ADDR, + MT6351_PMIC_RG_AUDPREAMPLPEN_MASK, MT6351_PMIC_RG_AUDPREAMPLPEN_SHIFT}, + {PMIC_RG_AUDADC1STSTAGELPEN, MT6351_PMIC_RG_AUDADC1STSTAGELPEN_ADDR, + MT6351_PMIC_RG_AUDADC1STSTAGELPEN_MASK, MT6351_PMIC_RG_AUDADC1STSTAGELPEN_SHIFT}, + {PMIC_RG_AUDADC2NDSTAGELPEN, MT6351_PMIC_RG_AUDADC2NDSTAGELPEN_ADDR, + MT6351_PMIC_RG_AUDADC2NDSTAGELPEN_MASK, MT6351_PMIC_RG_AUDADC2NDSTAGELPEN_SHIFT}, + {PMIC_RG_AUDADCFLASHLPEN, MT6351_PMIC_RG_AUDADCFLASHLPEN_ADDR, + MT6351_PMIC_RG_AUDADCFLASHLPEN_MASK, MT6351_PMIC_RG_AUDADCFLASHLPEN_SHIFT}, + {PMIC_RG_AUDPREAMPIDDTEST, MT6351_PMIC_RG_AUDPREAMPIDDTEST_ADDR, + MT6351_PMIC_RG_AUDPREAMPIDDTEST_MASK, MT6351_PMIC_RG_AUDPREAMPIDDTEST_SHIFT}, + {PMIC_RG_AUDADC1STSTAGEIDDTEST, MT6351_PMIC_RG_AUDADC1STSTAGEIDDTEST_ADDR, + MT6351_PMIC_RG_AUDADC1STSTAGEIDDTEST_MASK, MT6351_PMIC_RG_AUDADC1STSTAGEIDDTEST_SHIFT}, + {PMIC_RG_AUDADC2NDSTAGEIDDTEST, MT6351_PMIC_RG_AUDADC2NDSTAGEIDDTEST_ADDR, + MT6351_PMIC_RG_AUDADC2NDSTAGEIDDTEST_MASK, MT6351_PMIC_RG_AUDADC2NDSTAGEIDDTEST_SHIFT}, + {PMIC_RG_AUDADCREFBUFIDDTEST, MT6351_PMIC_RG_AUDADCREFBUFIDDTEST_ADDR, + MT6351_PMIC_RG_AUDADCREFBUFIDDTEST_MASK, MT6351_PMIC_RG_AUDADCREFBUFIDDTEST_SHIFT}, + {PMIC_RG_AUDADCFLASHIDDTEST, MT6351_PMIC_RG_AUDADCFLASHIDDTEST_ADDR, + MT6351_PMIC_RG_AUDADCFLASHIDDTEST_MASK, MT6351_PMIC_RG_AUDADCFLASHIDDTEST_SHIFT}, + {PMIC_RG_AUDADCDAC0P25FS, MT6351_PMIC_RG_AUDADCDAC0P25FS_ADDR, + MT6351_PMIC_RG_AUDADCDAC0P25FS_MASK, MT6351_PMIC_RG_AUDADCDAC0P25FS_SHIFT}, + {PMIC_RG_AUDADCCLKSEL, MT6351_PMIC_RG_AUDADCCLKSEL_ADDR, + MT6351_PMIC_RG_AUDADCCLKSEL_MASK, MT6351_PMIC_RG_AUDADCCLKSEL_SHIFT}, + {PMIC_RG_AUDADCCLKSOURCE, MT6351_PMIC_RG_AUDADCCLKSOURCE_ADDR, + MT6351_PMIC_RG_AUDADCCLKSOURCE_MASK, MT6351_PMIC_RG_AUDADCCLKSOURCE_SHIFT}, + {PMIC_RG_AUDADCCLKGENMODE, MT6351_PMIC_RG_AUDADCCLKGENMODE_ADDR, + MT6351_PMIC_RG_AUDADCCLKGENMODE_MASK, MT6351_PMIC_RG_AUDADCCLKGENMODE_SHIFT}, + {PMIC_RG_AUDADCCLKRSTB, MT6351_PMIC_RG_AUDADCCLKRSTB_ADDR, + MT6351_PMIC_RG_AUDADCCLKRSTB_MASK, MT6351_PMIC_RG_AUDADCCLKRSTB_SHIFT}, + {PMIC_RG_AUDPREAMPAAFEN, MT6351_PMIC_RG_AUDPREAMPAAFEN_ADDR, + MT6351_PMIC_RG_AUDPREAMPAAFEN_MASK, MT6351_PMIC_RG_AUDPREAMPAAFEN_SHIFT}, + {PMIC_RG_DCCVCMBUFLPMODSEL, MT6351_PMIC_RG_DCCVCMBUFLPMODSEL_ADDR, + MT6351_PMIC_RG_DCCVCMBUFLPMODSEL_MASK, MT6351_PMIC_RG_DCCVCMBUFLPMODSEL_SHIFT}, + {PMIC_RG_DCCVCMBUFLPSWEN, MT6351_PMIC_RG_DCCVCMBUFLPSWEN_ADDR, + MT6351_PMIC_RG_DCCVCMBUFLPSWEN_MASK, MT6351_PMIC_RG_DCCVCMBUFLPSWEN_SHIFT}, + {PMIC_RG_AUDSPAREPGA, MT6351_PMIC_RG_AUDSPAREPGA_ADDR, + MT6351_PMIC_RG_AUDSPAREPGA_MASK, MT6351_PMIC_RG_AUDSPAREPGA_SHIFT}, + {PMIC_RG_AUDADC1STSTAGESDENB, MT6351_PMIC_RG_AUDADC1STSTAGESDENB_ADDR, + MT6351_PMIC_RG_AUDADC1STSTAGESDENB_MASK, MT6351_PMIC_RG_AUDADC1STSTAGESDENB_SHIFT}, + {PMIC_RG_AUDADC2NDSTAGERESET, MT6351_PMIC_RG_AUDADC2NDSTAGERESET_ADDR, + MT6351_PMIC_RG_AUDADC2NDSTAGERESET_MASK, MT6351_PMIC_RG_AUDADC2NDSTAGERESET_SHIFT}, + {PMIC_RG_AUDADC3RDSTAGERESET, MT6351_PMIC_RG_AUDADC3RDSTAGERESET_ADDR, + MT6351_PMIC_RG_AUDADC3RDSTAGERESET_MASK, MT6351_PMIC_RG_AUDADC3RDSTAGERESET_SHIFT}, + {PMIC_RG_AUDADCFSRESET, MT6351_PMIC_RG_AUDADCFSRESET_ADDR, + MT6351_PMIC_RG_AUDADCFSRESET_MASK, MT6351_PMIC_RG_AUDADCFSRESET_SHIFT}, + {PMIC_RG_AUDADCWIDECM, MT6351_PMIC_RG_AUDADCWIDECM_ADDR, + MT6351_PMIC_RG_AUDADCWIDECM_MASK, MT6351_PMIC_RG_AUDADCWIDECM_SHIFT}, + {PMIC_RG_AUDADCNOPATEST, MT6351_PMIC_RG_AUDADCNOPATEST_ADDR, + MT6351_PMIC_RG_AUDADCNOPATEST_MASK, MT6351_PMIC_RG_AUDADCNOPATEST_SHIFT}, + {PMIC_RG_AUDADCBYPASS, MT6351_PMIC_RG_AUDADCBYPASS_ADDR, + MT6351_PMIC_RG_AUDADCBYPASS_MASK, MT6351_PMIC_RG_AUDADCBYPASS_SHIFT}, + {PMIC_RG_AUDADCFFBYPASS, MT6351_PMIC_RG_AUDADCFFBYPASS_ADDR, + MT6351_PMIC_RG_AUDADCFFBYPASS_MASK, MT6351_PMIC_RG_AUDADCFFBYPASS_SHIFT}, + {PMIC_RG_AUDADCDACFBCURRENT, MT6351_PMIC_RG_AUDADCDACFBCURRENT_ADDR, + MT6351_PMIC_RG_AUDADCDACFBCURRENT_MASK, MT6351_PMIC_RG_AUDADCDACFBCURRENT_SHIFT}, + {PMIC_RG_AUDADCDACIDDTEST, MT6351_PMIC_RG_AUDADCDACIDDTEST_ADDR, + MT6351_PMIC_RG_AUDADCDACIDDTEST_MASK, MT6351_PMIC_RG_AUDADCDACIDDTEST_SHIFT}, + {PMIC_RG_AUDADCDACNRZ, MT6351_PMIC_RG_AUDADCDACNRZ_ADDR, + MT6351_PMIC_RG_AUDADCDACNRZ_MASK, MT6351_PMIC_RG_AUDADCDACNRZ_SHIFT}, + {PMIC_RG_AUDADCNODEM, MT6351_PMIC_RG_AUDADCNODEM_ADDR, + MT6351_PMIC_RG_AUDADCNODEM_MASK, MT6351_PMIC_RG_AUDADCNODEM_SHIFT}, + {PMIC_RG_AUDADCDACTEST, MT6351_PMIC_RG_AUDADCDACTEST_ADDR, + MT6351_PMIC_RG_AUDADCDACTEST_MASK, MT6351_PMIC_RG_AUDADCDACTEST_SHIFT}, + {PMIC_RG_AUDADCTESTDATA, MT6351_PMIC_RG_AUDADCTESTDATA_ADDR, + MT6351_PMIC_RG_AUDADCTESTDATA_MASK, MT6351_PMIC_RG_AUDADCTESTDATA_SHIFT}, + {PMIC_RG_AUDRCTUNEL, MT6351_PMIC_RG_AUDRCTUNEL_ADDR, + MT6351_PMIC_RG_AUDRCTUNEL_MASK, MT6351_PMIC_RG_AUDRCTUNEL_SHIFT}, + {PMIC_RG_AUDRCTUNELSEL, MT6351_PMIC_RG_AUDRCTUNELSEL_ADDR, + MT6351_PMIC_RG_AUDRCTUNELSEL_MASK, MT6351_PMIC_RG_AUDRCTUNELSEL_SHIFT}, + {PMIC_RG_AUDRCTUNER, MT6351_PMIC_RG_AUDRCTUNER_ADDR, + MT6351_PMIC_RG_AUDRCTUNER_MASK, MT6351_PMIC_RG_AUDRCTUNER_SHIFT}, + {PMIC_RG_AUDRCTUNERSEL, MT6351_PMIC_RG_AUDRCTUNERSEL_ADDR, + MT6351_PMIC_RG_AUDRCTUNERSEL_MASK, MT6351_PMIC_RG_AUDRCTUNERSEL_SHIFT}, + {PMIC_RG_AUDSPAREVA30, MT6351_PMIC_RG_AUDSPAREVA30_ADDR, + MT6351_PMIC_RG_AUDSPAREVA30_MASK, MT6351_PMIC_RG_AUDSPAREVA30_SHIFT}, + {PMIC_RG_AUDSPAREVA18, MT6351_PMIC_RG_AUDSPAREVA18_ADDR, + MT6351_PMIC_RG_AUDSPAREVA18_MASK, MT6351_PMIC_RG_AUDSPAREVA18_SHIFT}, + {PMIC_RG_AUDDIGMICEN, MT6351_PMIC_RG_AUDDIGMICEN_ADDR, + MT6351_PMIC_RG_AUDDIGMICEN_MASK, MT6351_PMIC_RG_AUDDIGMICEN_SHIFT}, + {PMIC_RG_AUDDIGMICBIAS, MT6351_PMIC_RG_AUDDIGMICBIAS_ADDR, + MT6351_PMIC_RG_AUDDIGMICBIAS_MASK, MT6351_PMIC_RG_AUDDIGMICBIAS_SHIFT}, + {PMIC_RG_DMICHPCLKEN, MT6351_PMIC_RG_DMICHPCLKEN_ADDR, + MT6351_PMIC_RG_DMICHPCLKEN_MASK, MT6351_PMIC_RG_DMICHPCLKEN_SHIFT}, + {PMIC_RG_AUDDIGMICPDUTY, MT6351_PMIC_RG_AUDDIGMICPDUTY_ADDR, + MT6351_PMIC_RG_AUDDIGMICPDUTY_MASK, MT6351_PMIC_RG_AUDDIGMICPDUTY_SHIFT}, + {PMIC_RG_AUDDIGMICNDUTY, MT6351_PMIC_RG_AUDDIGMICNDUTY_ADDR, + MT6351_PMIC_RG_AUDDIGMICNDUTY_MASK, MT6351_PMIC_RG_AUDDIGMICNDUTY_SHIFT}, + {PMIC_RG_DMICMONEN, MT6351_PMIC_RG_DMICMONEN_ADDR, MT6351_PMIC_RG_DMICMONEN_MASK, + MT6351_PMIC_RG_DMICMONEN_SHIFT}, + {PMIC_RG_DMICMONSEL, MT6351_PMIC_RG_DMICMONSEL_ADDR, + MT6351_PMIC_RG_DMICMONSEL_MASK, MT6351_PMIC_RG_DMICMONSEL_SHIFT}, + {PMIC_RG_AUDSPAREVMIC, MT6351_PMIC_RG_AUDSPAREVMIC_ADDR, + MT6351_PMIC_RG_AUDSPAREVMIC_MASK, MT6351_PMIC_RG_AUDSPAREVMIC_SHIFT}, + {PMIC_RG_AUDPWDBMICBIAS0, MT6351_PMIC_RG_AUDPWDBMICBIAS0_ADDR, + MT6351_PMIC_RG_AUDPWDBMICBIAS0_MASK, MT6351_PMIC_RG_AUDPWDBMICBIAS0_SHIFT}, + {PMIC_RG_AUDMICBIAS0DCSW0P1EN, MT6351_PMIC_RG_AUDMICBIAS0DCSW0P1EN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS0DCSW0P1EN_MASK, MT6351_PMIC_RG_AUDMICBIAS0DCSW0P1EN_SHIFT}, + {PMIC_RG_AUDMICBIAS0DCSW0P2EN, MT6351_PMIC_RG_AUDMICBIAS0DCSW0P2EN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS0DCSW0P2EN_MASK, MT6351_PMIC_RG_AUDMICBIAS0DCSW0P2EN_SHIFT}, + {PMIC_RG_AUDMICBIAS0DCSW0NEN, MT6351_PMIC_RG_AUDMICBIAS0DCSW0NEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS0DCSW0NEN_MASK, MT6351_PMIC_RG_AUDMICBIAS0DCSW0NEN_SHIFT}, + {PMIC_RG_AUDMICBIAS0VREF, MT6351_PMIC_RG_AUDMICBIAS0VREF_ADDR, + MT6351_PMIC_RG_AUDMICBIAS0VREF_MASK, MT6351_PMIC_RG_AUDMICBIAS0VREF_SHIFT}, + {PMIC_RG_AUDMICBIAS0LOWPEN, MT6351_PMIC_RG_AUDMICBIAS0LOWPEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS0LOWPEN_MASK, MT6351_PMIC_RG_AUDMICBIAS0LOWPEN_SHIFT}, + {PMIC_RG_AUDPWDBMICBIAS2, MT6351_PMIC_RG_AUDPWDBMICBIAS2_ADDR, + MT6351_PMIC_RG_AUDPWDBMICBIAS2_MASK, MT6351_PMIC_RG_AUDPWDBMICBIAS2_SHIFT}, + {PMIC_RG_AUDMICBIAS2DCSW2P1EN, MT6351_PMIC_RG_AUDMICBIAS2DCSW2P1EN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS2DCSW2P1EN_MASK, MT6351_PMIC_RG_AUDMICBIAS2DCSW2P1EN_SHIFT}, + {PMIC_RG_AUDMICBIAS2DCSW2P2EN, MT6351_PMIC_RG_AUDMICBIAS2DCSW2P2EN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS2DCSW2P2EN_MASK, MT6351_PMIC_RG_AUDMICBIAS2DCSW2P2EN_SHIFT}, + {PMIC_RG_AUDMICBIAS2DCSW2NEN, MT6351_PMIC_RG_AUDMICBIAS2DCSW2NEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS2DCSW2NEN_MASK, MT6351_PMIC_RG_AUDMICBIAS2DCSW2NEN_SHIFT}, + {PMIC_RG_AUDMICBIAS2VREF, MT6351_PMIC_RG_AUDMICBIAS2VREF_ADDR, + MT6351_PMIC_RG_AUDMICBIAS2VREF_MASK, MT6351_PMIC_RG_AUDMICBIAS2VREF_SHIFT}, + {PMIC_RG_AUDMICBIAS2LOWPEN, MT6351_PMIC_RG_AUDMICBIAS2LOWPEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS2LOWPEN_MASK, MT6351_PMIC_RG_AUDMICBIAS2LOWPEN_SHIFT}, + {PMIC_RG_AUDPWDBMICBIAS1, MT6351_PMIC_RG_AUDPWDBMICBIAS1_ADDR, + MT6351_PMIC_RG_AUDPWDBMICBIAS1_MASK, MT6351_PMIC_RG_AUDPWDBMICBIAS1_SHIFT}, + {PMIC_RG_AUDMICBIAS1DCSW1PEN, MT6351_PMIC_RG_AUDMICBIAS1DCSW1PEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS1DCSW1PEN_MASK, MT6351_PMIC_RG_AUDMICBIAS1DCSW1PEN_SHIFT}, + {PMIC_RG_AUDMICBIAS1DCSW1NEN, MT6351_PMIC_RG_AUDMICBIAS1DCSW1NEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS1DCSW1NEN_MASK, MT6351_PMIC_RG_AUDMICBIAS1DCSW1NEN_SHIFT}, + {PMIC_RG_AUDMICBIAS1VREF, MT6351_PMIC_RG_AUDMICBIAS1VREF_ADDR, + MT6351_PMIC_RG_AUDMICBIAS1VREF_MASK, MT6351_PMIC_RG_AUDMICBIAS1VREF_SHIFT}, + {PMIC_RG_AUDMICBIAS1LOWPEN, MT6351_PMIC_RG_AUDMICBIAS1LOWPEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS1LOWPEN_MASK, MT6351_PMIC_RG_AUDMICBIAS1LOWPEN_SHIFT}, + {PMIC_RG_AUDMICBIAS1DCSW3PEN, MT6351_PMIC_RG_AUDMICBIAS1DCSW3PEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS1DCSW3PEN_MASK, MT6351_PMIC_RG_AUDMICBIAS1DCSW3PEN_SHIFT}, + {PMIC_RG_AUDMICBIAS1DCSW3NEN, MT6351_PMIC_RG_AUDMICBIAS1DCSW3NEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS1DCSW3NEN_MASK, MT6351_PMIC_RG_AUDMICBIAS1DCSW3NEN_SHIFT}, + {PMIC_RG_AUDMICBIAS2DCSW3PEN, MT6351_PMIC_RG_AUDMICBIAS2DCSW3PEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS2DCSW3PEN_MASK, MT6351_PMIC_RG_AUDMICBIAS2DCSW3PEN_SHIFT}, + {PMIC_RG_AUDMICBIAS2DCSW3NEN, MT6351_PMIC_RG_AUDMICBIAS2DCSW3NEN_ADDR, + MT6351_PMIC_RG_AUDMICBIAS2DCSW3NEN_MASK, MT6351_PMIC_RG_AUDMICBIAS2DCSW3NEN_SHIFT}, + {PMIC_RG_BANDGAPGEN, MT6351_PMIC_RG_BANDGAPGEN_ADDR, + MT6351_PMIC_RG_BANDGAPGEN_MASK, MT6351_PMIC_RG_BANDGAPGEN_SHIFT}, + {PMIC_RG_AUDACCDETMICBIAS0PULLLOW, MT6351_PMIC_RG_AUDACCDETMICBIAS0PULLLOW_ADDR, + MT6351_PMIC_RG_AUDACCDETMICBIAS0PULLLOW_MASK, + MT6351_PMIC_RG_AUDACCDETMICBIAS0PULLLOW_SHIFT}, + {PMIC_RG_AUDACCDETMICBIAS1PULLLOW, MT6351_PMIC_RG_AUDACCDETMICBIAS1PULLLOW_ADDR, + MT6351_PMIC_RG_AUDACCDETMICBIAS1PULLLOW_MASK, + MT6351_PMIC_RG_AUDACCDETMICBIAS1PULLLOW_SHIFT}, + {PMIC_RG_AUDACCDETMICBIAS2PULLLOW, MT6351_PMIC_RG_AUDACCDETMICBIAS2PULLLOW_ADDR, + MT6351_PMIC_RG_AUDACCDETMICBIAS2PULLLOW_MASK, + MT6351_PMIC_RG_AUDACCDETMICBIAS2PULLLOW_SHIFT}, + {PMIC_RG_AUDACCDETVIN1PULLLOW, MT6351_PMIC_RG_AUDACCDETVIN1PULLLOW_ADDR, + MT6351_PMIC_RG_AUDACCDETVIN1PULLLOW_MASK, MT6351_PMIC_RG_AUDACCDETVIN1PULLLOW_SHIFT}, + {PMIC_RG_AUDACCDETVTHACAL, MT6351_PMIC_RG_AUDACCDETVTHACAL_ADDR, + MT6351_PMIC_RG_AUDACCDETVTHACAL_MASK, MT6351_PMIC_RG_AUDACCDETVTHACAL_SHIFT}, + {PMIC_RG_AUDACCDETVTHBCAL, MT6351_PMIC_RG_AUDACCDETVTHBCAL_ADDR, + MT6351_PMIC_RG_AUDACCDETVTHBCAL_MASK, MT6351_PMIC_RG_AUDACCDETVTHBCAL_SHIFT}, + {PMIC_RG_ACCDET1SEL, MT6351_PMIC_RG_ACCDET1SEL_ADDR, + MT6351_PMIC_RG_ACCDET1SEL_MASK, MT6351_PMIC_RG_ACCDET1SEL_SHIFT}, + {PMIC_RG_ACCDET2SEL, MT6351_PMIC_RG_ACCDET2SEL_ADDR, + MT6351_PMIC_RG_ACCDET2SEL_MASK, MT6351_PMIC_RG_ACCDET2SEL_SHIFT}, + {PMIC_RG_SWBUFMODSEL, MT6351_PMIC_RG_SWBUFMODSEL_ADDR, + MT6351_PMIC_RG_SWBUFMODSEL_MASK, MT6351_PMIC_RG_SWBUFMODSEL_SHIFT}, + {PMIC_RG_SWBUFSWEN, MT6351_PMIC_RG_SWBUFSWEN_ADDR, MT6351_PMIC_RG_SWBUFSWEN_MASK, + MT6351_PMIC_RG_SWBUFSWEN_SHIFT}, + {PMIC_RG_EINTCOMPVTH, MT6351_PMIC_RG_EINTCOMPVTH_ADDR, + MT6351_PMIC_RG_EINTCOMPVTH_MASK, MT6351_PMIC_RG_EINTCOMPVTH_SHIFT}, + {PMIC_RG_EINTCONFIGACCDET, MT6351_PMIC_RG_EINTCONFIGACCDET_ADDR, + MT6351_PMIC_RG_EINTCONFIGACCDET_MASK, MT6351_PMIC_RG_EINTCONFIGACCDET_SHIFT}, + {PMIC_RG_NVDETCMPEN, MT6351_PMIC_RG_NVDETCMPEN_ADDR, + MT6351_PMIC_RG_NVDETCMPEN_MASK, MT6351_PMIC_RG_NVDETCMPEN_SHIFT}, + {PMIC_RG_NVDETVTH, MT6351_PMIC_RG_NVDETVTH_ADDR, MT6351_PMIC_RG_NVDETVTH_MASK, + MT6351_PMIC_RG_NVDETVTH_SHIFT}, + {PMIC_RG_NVMODSEL, MT6351_PMIC_RG_NVMODSEL_ADDR, MT6351_PMIC_RG_NVMODSEL_MASK, + MT6351_PMIC_RG_NVMODSEL_SHIFT}, + {PMIC_RG_NVCMPSWEN, MT6351_PMIC_RG_NVCMPSWEN_ADDR, MT6351_PMIC_RG_NVCMPSWEN_MASK, + MT6351_PMIC_RG_NVCMPSWEN_SHIFT}, + {PMIC_RG_AUDENCSPAREVA30, MT6351_PMIC_RG_AUDENCSPAREVA30_ADDR, + MT6351_PMIC_RG_AUDENCSPAREVA30_MASK, MT6351_PMIC_RG_AUDENCSPAREVA30_SHIFT}, + {PMIC_RG_AUDENCSPAREVA18, MT6351_PMIC_RG_AUDENCSPAREVA18_ADDR, + MT6351_PMIC_RG_AUDENCSPAREVA18_MASK, MT6351_PMIC_RG_AUDENCSPAREVA18_SHIFT}, + {PMIC_RG_PLL_EN, MT6351_PMIC_RG_PLL_EN_ADDR, MT6351_PMIC_RG_PLL_EN_MASK, + MT6351_PMIC_RG_PLL_EN_SHIFT}, + {PMIC_RG_PLLBS_RST, MT6351_PMIC_RG_PLLBS_RST_ADDR, MT6351_PMIC_RG_PLLBS_RST_MASK, + MT6351_PMIC_RG_PLLBS_RST_SHIFT}, + {PMIC_RG_PLL_DCKO_SEL, MT6351_PMIC_RG_PLL_DCKO_SEL_ADDR, + MT6351_PMIC_RG_PLL_DCKO_SEL_MASK, MT6351_PMIC_RG_PLL_DCKO_SEL_SHIFT}, + {PMIC_RG_PLL_DIV1, MT6351_PMIC_RG_PLL_DIV1_ADDR, MT6351_PMIC_RG_PLL_DIV1_MASK, + MT6351_PMIC_RG_PLL_DIV1_SHIFT}, + {PMIC_RG_PLL_RLATCH_EN, MT6351_PMIC_RG_PLL_RLATCH_EN_ADDR, + MT6351_PMIC_RG_PLL_RLATCH_EN_MASK, MT6351_PMIC_RG_PLL_RLATCH_EN_SHIFT}, + {PMIC_RG_PLL_PDIV1_EN, MT6351_PMIC_RG_PLL_PDIV1_EN_ADDR, + MT6351_PMIC_RG_PLL_PDIV1_EN_MASK, MT6351_PMIC_RG_PLL_PDIV1_EN_SHIFT}, + {PMIC_RG_PLL_PDIV1, MT6351_PMIC_RG_PLL_PDIV1_ADDR, MT6351_PMIC_RG_PLL_PDIV1_MASK, + MT6351_PMIC_RG_PLL_PDIV1_SHIFT}, + {PMIC_RG_PLL_BC, MT6351_PMIC_RG_PLL_BC_ADDR, MT6351_PMIC_RG_PLL_BC_MASK, + MT6351_PMIC_RG_PLL_BC_SHIFT}, + {PMIC_RG_PLL_BP, MT6351_PMIC_RG_PLL_BP_ADDR, MT6351_PMIC_RG_PLL_BP_MASK, + MT6351_PMIC_RG_PLL_BP_SHIFT}, + {PMIC_RG_PLL_BR, MT6351_PMIC_RG_PLL_BR_ADDR, MT6351_PMIC_RG_PLL_BR_MASK, + MT6351_PMIC_RG_PLL_BR_SHIFT}, + {PMIC_RG_CKO_SEL, MT6351_PMIC_RG_CKO_SEL_ADDR, MT6351_PMIC_RG_CKO_SEL_MASK, + MT6351_PMIC_RG_CKO_SEL_SHIFT}, + {PMIC_RG_PLL_IBSEL, MT6351_PMIC_RG_PLL_IBSEL_ADDR, MT6351_PMIC_RG_PLL_IBSEL_MASK, + MT6351_PMIC_RG_PLL_IBSEL_SHIFT}, + {PMIC_RG_PLL_CKT_SEL, MT6351_PMIC_RG_PLL_CKT_SEL_ADDR, + MT6351_PMIC_RG_PLL_CKT_SEL_MASK, MT6351_PMIC_RG_PLL_CKT_SEL_SHIFT}, + {PMIC_RG_PLL_VCT_EN, MT6351_PMIC_RG_PLL_VCT_EN_ADDR, + MT6351_PMIC_RG_PLL_VCT_EN_MASK, MT6351_PMIC_RG_PLL_VCT_EN_SHIFT}, + {PMIC_RG_PLL_CKT_EN, MT6351_PMIC_RG_PLL_CKT_EN_ADDR, + MT6351_PMIC_RG_PLL_CKT_EN_MASK, MT6351_PMIC_RG_PLL_CKT_EN_SHIFT}, + {PMIC_RG_PLL_HPM_EN, MT6351_PMIC_RG_PLL_HPM_EN_ADDR, + MT6351_PMIC_RG_PLL_HPM_EN_MASK, MT6351_PMIC_RG_PLL_HPM_EN_SHIFT}, + {PMIC_RG_PLL_DCHP_EN, MT6351_PMIC_RG_PLL_DCHP_EN_ADDR, + MT6351_PMIC_RG_PLL_DCHP_EN_MASK, MT6351_PMIC_RG_PLL_DCHP_EN_SHIFT}, + {PMIC_RG_PLL_CDIV, MT6351_PMIC_RG_PLL_CDIV_ADDR, MT6351_PMIC_RG_PLL_CDIV_MASK, + MT6351_PMIC_RG_PLL_CDIV_SHIFT}, + {PMIC_RG_VCOBAND, MT6351_PMIC_RG_VCOBAND_ADDR, MT6351_PMIC_RG_VCOBAND_MASK, + MT6351_PMIC_RG_VCOBAND_SHIFT}, + {PMIC_RG_CKDRV_EN, MT6351_PMIC_RG_CKDRV_EN_ADDR, MT6351_PMIC_RG_CKDRV_EN_MASK, + MT6351_PMIC_RG_CKDRV_EN_SHIFT}, + {PMIC_RG_PLL_DCHP_AEN, MT6351_PMIC_RG_PLL_DCHP_AEN_ADDR, + MT6351_PMIC_RG_PLL_DCHP_AEN_MASK, MT6351_PMIC_RG_PLL_DCHP_AEN_SHIFT}, + {PMIC_RG_PLL_RSVA, MT6351_PMIC_RG_PLL_RSVA_ADDR, MT6351_PMIC_RG_PLL_RSVA_MASK, + MT6351_PMIC_RG_PLL_RSVA_SHIFT}, + {PMIC_RGS_AUDRCTUNELREAD, MT6351_PMIC_RGS_AUDRCTUNELREAD_ADDR, + MT6351_PMIC_RGS_AUDRCTUNELREAD_MASK, MT6351_PMIC_RGS_AUDRCTUNELREAD_SHIFT}, + {PMIC_RGS_AUDRCTUNERREAD, MT6351_PMIC_RGS_AUDRCTUNERREAD_ADDR, + MT6351_PMIC_RGS_AUDRCTUNERREAD_MASK, MT6351_PMIC_RGS_AUDRCTUNERREAD_SHIFT}, + {PMIC_RG_DIVCKS_CHG, MT6351_PMIC_RG_DIVCKS_CHG_ADDR, + MT6351_PMIC_RG_DIVCKS_CHG_MASK, MT6351_PMIC_RG_DIVCKS_CHG_SHIFT}, + {PMIC_RG_DIVCKS_ON, MT6351_PMIC_RG_DIVCKS_ON_ADDR, MT6351_PMIC_RG_DIVCKS_ON_MASK, + MT6351_PMIC_RG_DIVCKS_ON_SHIFT}, + {PMIC_RG_DIVCKS_PRG, MT6351_PMIC_RG_DIVCKS_PRG_ADDR, + MT6351_PMIC_RG_DIVCKS_PRG_MASK, MT6351_PMIC_RG_DIVCKS_PRG_SHIFT}, + {PMIC_RG_DIVCKS_PWD_NCP, MT6351_PMIC_RG_DIVCKS_PWD_NCP_ADDR, + MT6351_PMIC_RG_DIVCKS_PWD_NCP_MASK, MT6351_PMIC_RG_DIVCKS_PWD_NCP_SHIFT}, + {PMIC_RG_DIVCKS_PWD_NCP_ST_SEL, MT6351_PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_ADDR, + MT6351_PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_MASK, MT6351_PMIC_RG_DIVCKS_PWD_NCP_ST_SEL_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH0, MT6351_PMIC_AUXADC_ADC_OUT_CH0_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH0_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH0_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH0, MT6351_PMIC_AUXADC_ADC_RDY_CH0_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH0_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH0_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH1, MT6351_PMIC_AUXADC_ADC_OUT_CH1_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH1_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH1_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH1, MT6351_PMIC_AUXADC_ADC_RDY_CH1_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH1_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH1_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH2, MT6351_PMIC_AUXADC_ADC_OUT_CH2_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH2_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH2_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH2, MT6351_PMIC_AUXADC_ADC_RDY_CH2_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH2_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH2_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH3, MT6351_PMIC_AUXADC_ADC_OUT_CH3_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH3_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH3_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH3, MT6351_PMIC_AUXADC_ADC_RDY_CH3_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH3_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH3_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH4, MT6351_PMIC_AUXADC_ADC_OUT_CH4_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH4_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH4_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH4, MT6351_PMIC_AUXADC_ADC_RDY_CH4_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH4_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH4_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH5, MT6351_PMIC_AUXADC_ADC_OUT_CH5_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH5_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH5_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH5, MT6351_PMIC_AUXADC_ADC_RDY_CH5_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH5_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH5_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH6, MT6351_PMIC_AUXADC_ADC_OUT_CH6_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH6_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH6_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH6, MT6351_PMIC_AUXADC_ADC_RDY_CH6_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH6_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH6_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH7, MT6351_PMIC_AUXADC_ADC_OUT_CH7_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH7_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH7_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH7, MT6351_PMIC_AUXADC_ADC_RDY_CH7_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH7_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH7_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH8, MT6351_PMIC_AUXADC_ADC_OUT_CH8_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH8_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH8_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH8, MT6351_PMIC_AUXADC_ADC_RDY_CH8_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH8_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH8_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH9, MT6351_PMIC_AUXADC_ADC_OUT_CH9_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH9_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH9_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH9, MT6351_PMIC_AUXADC_ADC_RDY_CH9_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH9_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH9_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH10, MT6351_PMIC_AUXADC_ADC_OUT_CH10_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH10_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH10_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH10, MT6351_PMIC_AUXADC_ADC_RDY_CH10_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH10_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH10_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH11, MT6351_PMIC_AUXADC_ADC_OUT_CH11_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH11_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH11_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH11, MT6351_PMIC_AUXADC_ADC_RDY_CH11_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH11_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH11_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH12_15, MT6351_PMIC_AUXADC_ADC_OUT_CH12_15_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH12_15_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH12_15_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH12_15, MT6351_PMIC_AUXADC_ADC_RDY_CH12_15_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH12_15_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH12_15_SHIFT}, + {PMIC_AUXADC_ADC_OUT_THR_HW, MT6351_PMIC_AUXADC_ADC_OUT_THR_HW_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_THR_HW_MASK, MT6351_PMIC_AUXADC_ADC_OUT_THR_HW_SHIFT}, + {PMIC_AUXADC_ADC_RDY_THR_HW, MT6351_PMIC_AUXADC_ADC_RDY_THR_HW_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_THR_HW_MASK, MT6351_PMIC_AUXADC_ADC_RDY_THR_HW_SHIFT}, + {PMIC_AUXADC_ADC_OUT_LBAT, MT6351_PMIC_AUXADC_ADC_OUT_LBAT_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_LBAT_MASK, MT6351_PMIC_AUXADC_ADC_OUT_LBAT_SHIFT}, + {PMIC_AUXADC_ADC_RDY_LBAT, MT6351_PMIC_AUXADC_ADC_RDY_LBAT_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_LBAT_MASK, MT6351_PMIC_AUXADC_ADC_RDY_LBAT_SHIFT}, + {PMIC_AUXADC_ADC_OUT_LBAT2, MT6351_PMIC_AUXADC_ADC_OUT_LBAT2_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_LBAT2_MASK, MT6351_PMIC_AUXADC_ADC_OUT_LBAT2_SHIFT}, + {PMIC_AUXADC_ADC_RDY_LBAT2, MT6351_PMIC_AUXADC_ADC_RDY_LBAT2_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_LBAT2_MASK, MT6351_PMIC_AUXADC_ADC_RDY_LBAT2_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH7_BY_GPS, MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_GPS_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH7_BY_GPS, MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_GPS_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH7_BY_MD, MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH7_BY_MD, MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH7_BY_AP, MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_AP_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH7_BY_AP_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH7_BY_AP, MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_AP_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH7_BY_AP_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH4_BY_MD, MT6351_PMIC_AUXADC_ADC_OUT_CH4_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH4_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH4_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH4_BY_MD, MT6351_PMIC_AUXADC_ADC_RDY_CH4_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH4_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH4_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR, MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_MASK, + MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_PCHR_SHIFT}, + {PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR, MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_MASK, + MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR_SHIFT}, + {PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR, MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_MASK, + MT6351_PMIC_AUXADC_ADC_OUT_WAKEUP_SWCHR_SHIFT}, + {PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR, MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_MASK, + MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH0_BY_MD, MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH0_BY_MD, MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH0_BY_AP, MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_AP_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH0_BY_AP_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH0_BY_AP, MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_AP_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH0_BY_AP_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH1_BY_MD, MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH1_BY_MD, MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_OUT_CH1_BY_AP, MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_AP_MASK, MT6351_PMIC_AUXADC_ADC_OUT_CH1_BY_AP_SHIFT}, + {PMIC_AUXADC_ADC_RDY_CH1_BY_AP, MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_AP_MASK, MT6351_PMIC_AUXADC_ADC_RDY_CH1_BY_AP_SHIFT}, + {PMIC_AUXADC_ADC_OUT_VISMPS0, MT6351_PMIC_AUXADC_ADC_OUT_VISMPS0_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_VISMPS0_MASK, MT6351_PMIC_AUXADC_ADC_OUT_VISMPS0_SHIFT}, + {PMIC_AUXADC_ADC_RDY_VISMPS0, MT6351_PMIC_AUXADC_ADC_RDY_VISMPS0_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_VISMPS0_MASK, MT6351_PMIC_AUXADC_ADC_RDY_VISMPS0_SHIFT}, + {PMIC_AUXADC_ADC_OUT_FGADC1, MT6351_PMIC_AUXADC_ADC_OUT_FGADC1_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_FGADC1_MASK, MT6351_PMIC_AUXADC_ADC_OUT_FGADC1_SHIFT}, + {PMIC_AUXADC_ADC_RDY_FGADC1, MT6351_PMIC_AUXADC_ADC_RDY_FGADC1_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_FGADC1_MASK, MT6351_PMIC_AUXADC_ADC_RDY_FGADC1_SHIFT}, + {PMIC_AUXADC_ADC_OUT_FGADC2, MT6351_PMIC_AUXADC_ADC_OUT_FGADC2_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_FGADC2_MASK, MT6351_PMIC_AUXADC_ADC_OUT_FGADC2_SHIFT}, + {PMIC_AUXADC_ADC_RDY_FGADC2, MT6351_PMIC_AUXADC_ADC_RDY_FGADC2_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_FGADC2_MASK, MT6351_PMIC_AUXADC_ADC_RDY_FGADC2_SHIFT}, + {PMIC_AUXADC_ADC_OUT_IMP, MT6351_PMIC_AUXADC_ADC_OUT_IMP_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_IMP_MASK, MT6351_PMIC_AUXADC_ADC_OUT_IMP_SHIFT}, + {PMIC_AUXADC_ADC_RDY_IMP, MT6351_PMIC_AUXADC_ADC_RDY_IMP_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_IMP_MASK, MT6351_PMIC_AUXADC_ADC_RDY_IMP_SHIFT}, + {PMIC_AUXADC_ADC_OUT_IMP_AVG, MT6351_PMIC_AUXADC_ADC_OUT_IMP_AVG_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_IMP_AVG_MASK, MT6351_PMIC_AUXADC_ADC_OUT_IMP_AVG_SHIFT}, + {PMIC_AUXADC_ADC_RDY_IMP_AVG, MT6351_PMIC_AUXADC_ADC_RDY_IMP_AVG_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_IMP_AVG_MASK, MT6351_PMIC_AUXADC_ADC_RDY_IMP_AVG_SHIFT}, + {PMIC_AUXADC_ADC_OUT_RAW, MT6351_PMIC_AUXADC_ADC_OUT_RAW_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_RAW_MASK, MT6351_PMIC_AUXADC_ADC_OUT_RAW_SHIFT}, + {PMIC_AUXADC_ADC_OUT_MDRT, MT6351_PMIC_AUXADC_ADC_OUT_MDRT_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_MDRT_MASK, MT6351_PMIC_AUXADC_ADC_OUT_MDRT_SHIFT}, + {PMIC_AUXADC_ADC_RDY_MDRT, MT6351_PMIC_AUXADC_ADC_RDY_MDRT_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_MDRT_MASK, MT6351_PMIC_AUXADC_ADC_RDY_MDRT_SHIFT}, + {PMIC_AUXADC_ADC_OUT_MDBG, MT6351_PMIC_AUXADC_ADC_OUT_MDBG_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_MDBG_MASK, MT6351_PMIC_AUXADC_ADC_OUT_MDBG_SHIFT}, + {PMIC_AUXADC_ADC_RDY_MDBG, MT6351_PMIC_AUXADC_ADC_RDY_MDBG_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_MDBG_MASK, MT6351_PMIC_AUXADC_ADC_RDY_MDBG_SHIFT}, + {PMIC_AUXADC_ADC_OUT_JEITA, MT6351_PMIC_AUXADC_ADC_OUT_JEITA_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_JEITA_MASK, MT6351_PMIC_AUXADC_ADC_OUT_JEITA_SHIFT}, + {PMIC_AUXADC_ADC_RDY_JEITA, MT6351_PMIC_AUXADC_ADC_RDY_JEITA_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_JEITA_MASK, MT6351_PMIC_AUXADC_ADC_RDY_JEITA_SHIFT}, + {PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS, MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_MASK, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_GPS_SHIFT}, + {PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS, MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_MASK, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_GPS_SHIFT}, + {PMIC_AUXADC_ADC_OUT_DCXO_BY_MD, MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_RDY_DCXO_BY_MD, MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_MASK, MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_MD_SHIFT}, + {PMIC_AUXADC_ADC_OUT_DCXO_BY_AP, MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_MASK, MT6351_PMIC_AUXADC_ADC_OUT_DCXO_BY_AP_SHIFT}, + {PMIC_AUXADC_ADC_RDY_DCXO_BY_AP, MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_MASK, MT6351_PMIC_AUXADC_ADC_RDY_DCXO_BY_AP_SHIFT}, + {PMIC_AUXADC_ADC_OUT_DCXO_MDRT, MT6351_PMIC_AUXADC_ADC_OUT_DCXO_MDRT_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_DCXO_MDRT_MASK, MT6351_PMIC_AUXADC_ADC_OUT_DCXO_MDRT_SHIFT}, + {PMIC_AUXADC_ADC_RDY_DCXO_MDRT, MT6351_PMIC_AUXADC_ADC_RDY_DCXO_MDRT_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_DCXO_MDRT_MASK, MT6351_PMIC_AUXADC_ADC_RDY_DCXO_MDRT_SHIFT}, + {PMIC_AUXADC_ADC_OUT_NAG, MT6351_PMIC_AUXADC_ADC_OUT_NAG_ADDR, + MT6351_PMIC_AUXADC_ADC_OUT_NAG_MASK, MT6351_PMIC_AUXADC_ADC_OUT_NAG_SHIFT}, + {PMIC_AUXADC_ADC_RDY_NAG, MT6351_PMIC_AUXADC_ADC_RDY_NAG_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_NAG_MASK, MT6351_PMIC_AUXADC_ADC_RDY_NAG_SHIFT}, + {PMIC_AUXADC_BUF_OUT_00, MT6351_PMIC_AUXADC_BUF_OUT_00_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_00_MASK, MT6351_PMIC_AUXADC_BUF_OUT_00_SHIFT}, + {PMIC_AUXADC_BUF_RDY_00, MT6351_PMIC_AUXADC_BUF_RDY_00_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_00_MASK, MT6351_PMIC_AUXADC_BUF_RDY_00_SHIFT}, + {PMIC_AUXADC_BUF_OUT_01, MT6351_PMIC_AUXADC_BUF_OUT_01_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_01_MASK, MT6351_PMIC_AUXADC_BUF_OUT_01_SHIFT}, + {PMIC_AUXADC_BUF_RDY_01, MT6351_PMIC_AUXADC_BUF_RDY_01_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_01_MASK, MT6351_PMIC_AUXADC_BUF_RDY_01_SHIFT}, + {PMIC_AUXADC_BUF_OUT_02, MT6351_PMIC_AUXADC_BUF_OUT_02_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_02_MASK, MT6351_PMIC_AUXADC_BUF_OUT_02_SHIFT}, + {PMIC_AUXADC_BUF_RDY_02, MT6351_PMIC_AUXADC_BUF_RDY_02_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_02_MASK, MT6351_PMIC_AUXADC_BUF_RDY_02_SHIFT}, + {PMIC_AUXADC_BUF_OUT_03, MT6351_PMIC_AUXADC_BUF_OUT_03_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_03_MASK, MT6351_PMIC_AUXADC_BUF_OUT_03_SHIFT}, + {PMIC_AUXADC_BUF_RDY_03, MT6351_PMIC_AUXADC_BUF_RDY_03_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_03_MASK, MT6351_PMIC_AUXADC_BUF_RDY_03_SHIFT}, + {PMIC_AUXADC_BUF_OUT_04, MT6351_PMIC_AUXADC_BUF_OUT_04_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_04_MASK, MT6351_PMIC_AUXADC_BUF_OUT_04_SHIFT}, + {PMIC_AUXADC_BUF_RDY_04, MT6351_PMIC_AUXADC_BUF_RDY_04_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_04_MASK, MT6351_PMIC_AUXADC_BUF_RDY_04_SHIFT}, + {PMIC_AUXADC_BUF_OUT_05, MT6351_PMIC_AUXADC_BUF_OUT_05_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_05_MASK, MT6351_PMIC_AUXADC_BUF_OUT_05_SHIFT}, + {PMIC_AUXADC_BUF_RDY_05, MT6351_PMIC_AUXADC_BUF_RDY_05_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_05_MASK, MT6351_PMIC_AUXADC_BUF_RDY_05_SHIFT}, + {PMIC_AUXADC_BUF_OUT_06, MT6351_PMIC_AUXADC_BUF_OUT_06_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_06_MASK, MT6351_PMIC_AUXADC_BUF_OUT_06_SHIFT}, + {PMIC_AUXADC_BUF_RDY_06, MT6351_PMIC_AUXADC_BUF_RDY_06_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_06_MASK, MT6351_PMIC_AUXADC_BUF_RDY_06_SHIFT}, + {PMIC_AUXADC_BUF_OUT_07, MT6351_PMIC_AUXADC_BUF_OUT_07_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_07_MASK, MT6351_PMIC_AUXADC_BUF_OUT_07_SHIFT}, + {PMIC_AUXADC_BUF_RDY_07, MT6351_PMIC_AUXADC_BUF_RDY_07_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_07_MASK, MT6351_PMIC_AUXADC_BUF_RDY_07_SHIFT}, + {PMIC_AUXADC_BUF_OUT_08, MT6351_PMIC_AUXADC_BUF_OUT_08_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_08_MASK, MT6351_PMIC_AUXADC_BUF_OUT_08_SHIFT}, + {PMIC_AUXADC_BUF_RDY_08, MT6351_PMIC_AUXADC_BUF_RDY_08_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_08_MASK, MT6351_PMIC_AUXADC_BUF_RDY_08_SHIFT}, + {PMIC_AUXADC_BUF_OUT_09, MT6351_PMIC_AUXADC_BUF_OUT_09_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_09_MASK, MT6351_PMIC_AUXADC_BUF_OUT_09_SHIFT}, + {PMIC_AUXADC_BUF_RDY_09, MT6351_PMIC_AUXADC_BUF_RDY_09_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_09_MASK, MT6351_PMIC_AUXADC_BUF_RDY_09_SHIFT}, + {PMIC_AUXADC_BUF_OUT_10, MT6351_PMIC_AUXADC_BUF_OUT_10_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_10_MASK, MT6351_PMIC_AUXADC_BUF_OUT_10_SHIFT}, + {PMIC_AUXADC_BUF_RDY_10, MT6351_PMIC_AUXADC_BUF_RDY_10_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_10_MASK, MT6351_PMIC_AUXADC_BUF_RDY_10_SHIFT}, + {PMIC_AUXADC_BUF_OUT_11, MT6351_PMIC_AUXADC_BUF_OUT_11_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_11_MASK, MT6351_PMIC_AUXADC_BUF_OUT_11_SHIFT}, + {PMIC_AUXADC_BUF_RDY_11, MT6351_PMIC_AUXADC_BUF_RDY_11_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_11_MASK, MT6351_PMIC_AUXADC_BUF_RDY_11_SHIFT}, + {PMIC_AUXADC_BUF_OUT_12, MT6351_PMIC_AUXADC_BUF_OUT_12_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_12_MASK, MT6351_PMIC_AUXADC_BUF_OUT_12_SHIFT}, + {PMIC_AUXADC_BUF_RDY_12, MT6351_PMIC_AUXADC_BUF_RDY_12_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_12_MASK, MT6351_PMIC_AUXADC_BUF_RDY_12_SHIFT}, + {PMIC_AUXADC_BUF_OUT_13, MT6351_PMIC_AUXADC_BUF_OUT_13_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_13_MASK, MT6351_PMIC_AUXADC_BUF_OUT_13_SHIFT}, + {PMIC_AUXADC_BUF_RDY_13, MT6351_PMIC_AUXADC_BUF_RDY_13_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_13_MASK, MT6351_PMIC_AUXADC_BUF_RDY_13_SHIFT}, + {PMIC_AUXADC_BUF_OUT_14, MT6351_PMIC_AUXADC_BUF_OUT_14_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_14_MASK, MT6351_PMIC_AUXADC_BUF_OUT_14_SHIFT}, + {PMIC_AUXADC_BUF_RDY_14, MT6351_PMIC_AUXADC_BUF_RDY_14_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_14_MASK, MT6351_PMIC_AUXADC_BUF_RDY_14_SHIFT}, + {PMIC_AUXADC_BUF_OUT_15, MT6351_PMIC_AUXADC_BUF_OUT_15_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_15_MASK, MT6351_PMIC_AUXADC_BUF_OUT_15_SHIFT}, + {PMIC_AUXADC_BUF_RDY_15, MT6351_PMIC_AUXADC_BUF_RDY_15_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_15_MASK, MT6351_PMIC_AUXADC_BUF_RDY_15_SHIFT}, + {PMIC_AUXADC_BUF_OUT_16, MT6351_PMIC_AUXADC_BUF_OUT_16_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_16_MASK, MT6351_PMIC_AUXADC_BUF_OUT_16_SHIFT}, + {PMIC_AUXADC_BUF_RDY_16, MT6351_PMIC_AUXADC_BUF_RDY_16_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_16_MASK, MT6351_PMIC_AUXADC_BUF_RDY_16_SHIFT}, + {PMIC_AUXADC_BUF_OUT_17, MT6351_PMIC_AUXADC_BUF_OUT_17_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_17_MASK, MT6351_PMIC_AUXADC_BUF_OUT_17_SHIFT}, + {PMIC_AUXADC_BUF_RDY_17, MT6351_PMIC_AUXADC_BUF_RDY_17_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_17_MASK, MT6351_PMIC_AUXADC_BUF_RDY_17_SHIFT}, + {PMIC_AUXADC_BUF_OUT_18, MT6351_PMIC_AUXADC_BUF_OUT_18_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_18_MASK, MT6351_PMIC_AUXADC_BUF_OUT_18_SHIFT}, + {PMIC_AUXADC_BUF_RDY_18, MT6351_PMIC_AUXADC_BUF_RDY_18_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_18_MASK, MT6351_PMIC_AUXADC_BUF_RDY_18_SHIFT}, + {PMIC_AUXADC_BUF_OUT_19, MT6351_PMIC_AUXADC_BUF_OUT_19_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_19_MASK, MT6351_PMIC_AUXADC_BUF_OUT_19_SHIFT}, + {PMIC_AUXADC_BUF_RDY_19, MT6351_PMIC_AUXADC_BUF_RDY_19_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_19_MASK, MT6351_PMIC_AUXADC_BUF_RDY_19_SHIFT}, + {PMIC_AUXADC_BUF_OUT_20, MT6351_PMIC_AUXADC_BUF_OUT_20_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_20_MASK, MT6351_PMIC_AUXADC_BUF_OUT_20_SHIFT}, + {PMIC_AUXADC_BUF_RDY_20, MT6351_PMIC_AUXADC_BUF_RDY_20_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_20_MASK, MT6351_PMIC_AUXADC_BUF_RDY_20_SHIFT}, + {PMIC_AUXADC_BUF_OUT_21, MT6351_PMIC_AUXADC_BUF_OUT_21_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_21_MASK, MT6351_PMIC_AUXADC_BUF_OUT_21_SHIFT}, + {PMIC_AUXADC_BUF_RDY_21, MT6351_PMIC_AUXADC_BUF_RDY_21_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_21_MASK, MT6351_PMIC_AUXADC_BUF_RDY_21_SHIFT}, + {PMIC_AUXADC_BUF_OUT_22, MT6351_PMIC_AUXADC_BUF_OUT_22_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_22_MASK, MT6351_PMIC_AUXADC_BUF_OUT_22_SHIFT}, + {PMIC_AUXADC_BUF_RDY_22, MT6351_PMIC_AUXADC_BUF_RDY_22_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_22_MASK, MT6351_PMIC_AUXADC_BUF_RDY_22_SHIFT}, + {PMIC_AUXADC_BUF_OUT_23, MT6351_PMIC_AUXADC_BUF_OUT_23_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_23_MASK, MT6351_PMIC_AUXADC_BUF_OUT_23_SHIFT}, + {PMIC_AUXADC_BUF_RDY_23, MT6351_PMIC_AUXADC_BUF_RDY_23_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_23_MASK, MT6351_PMIC_AUXADC_BUF_RDY_23_SHIFT}, + {PMIC_AUXADC_BUF_OUT_24, MT6351_PMIC_AUXADC_BUF_OUT_24_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_24_MASK, MT6351_PMIC_AUXADC_BUF_OUT_24_SHIFT}, + {PMIC_AUXADC_BUF_RDY_24, MT6351_PMIC_AUXADC_BUF_RDY_24_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_24_MASK, MT6351_PMIC_AUXADC_BUF_RDY_24_SHIFT}, + {PMIC_AUXADC_BUF_OUT_25, MT6351_PMIC_AUXADC_BUF_OUT_25_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_25_MASK, MT6351_PMIC_AUXADC_BUF_OUT_25_SHIFT}, + {PMIC_AUXADC_BUF_RDY_25, MT6351_PMIC_AUXADC_BUF_RDY_25_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_25_MASK, MT6351_PMIC_AUXADC_BUF_RDY_25_SHIFT}, + {PMIC_AUXADC_BUF_OUT_26, MT6351_PMIC_AUXADC_BUF_OUT_26_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_26_MASK, MT6351_PMIC_AUXADC_BUF_OUT_26_SHIFT}, + {PMIC_AUXADC_BUF_RDY_26, MT6351_PMIC_AUXADC_BUF_RDY_26_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_26_MASK, MT6351_PMIC_AUXADC_BUF_RDY_26_SHIFT}, + {PMIC_AUXADC_BUF_OUT_27, MT6351_PMIC_AUXADC_BUF_OUT_27_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_27_MASK, MT6351_PMIC_AUXADC_BUF_OUT_27_SHIFT}, + {PMIC_AUXADC_BUF_RDY_27, MT6351_PMIC_AUXADC_BUF_RDY_27_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_27_MASK, MT6351_PMIC_AUXADC_BUF_RDY_27_SHIFT}, + {PMIC_AUXADC_BUF_OUT_28, MT6351_PMIC_AUXADC_BUF_OUT_28_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_28_MASK, MT6351_PMIC_AUXADC_BUF_OUT_28_SHIFT}, + {PMIC_AUXADC_BUF_RDY_28, MT6351_PMIC_AUXADC_BUF_RDY_28_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_28_MASK, MT6351_PMIC_AUXADC_BUF_RDY_28_SHIFT}, + {PMIC_AUXADC_BUF_OUT_29, MT6351_PMIC_AUXADC_BUF_OUT_29_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_29_MASK, MT6351_PMIC_AUXADC_BUF_OUT_29_SHIFT}, + {PMIC_AUXADC_BUF_RDY_29, MT6351_PMIC_AUXADC_BUF_RDY_29_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_29_MASK, MT6351_PMIC_AUXADC_BUF_RDY_29_SHIFT}, + {PMIC_AUXADC_BUF_OUT_30, MT6351_PMIC_AUXADC_BUF_OUT_30_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_30_MASK, MT6351_PMIC_AUXADC_BUF_OUT_30_SHIFT}, + {PMIC_AUXADC_BUF_RDY_30, MT6351_PMIC_AUXADC_BUF_RDY_30_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_30_MASK, MT6351_PMIC_AUXADC_BUF_RDY_30_SHIFT}, + {PMIC_AUXADC_BUF_OUT_31, MT6351_PMIC_AUXADC_BUF_OUT_31_ADDR, + MT6351_PMIC_AUXADC_BUF_OUT_31_MASK, MT6351_PMIC_AUXADC_BUF_OUT_31_SHIFT}, + {PMIC_AUXADC_BUF_RDY_31, MT6351_PMIC_AUXADC_BUF_RDY_31_ADDR, + MT6351_PMIC_AUXADC_BUF_RDY_31_MASK, MT6351_PMIC_AUXADC_BUF_RDY_31_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN, MT6351_PMIC_AUXADC_ADC_BUSY_IN_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_LBAT, MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_LBAT2, MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT2_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT2_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_LBAT2_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_VISMPS0, MT6351_PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_MASK, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_VISMPS0_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_WAKEUP, MT6351_PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_WAKEUP_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT, MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_MASK, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_MDRT_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_MASK, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_AP_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_MASK, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MD_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS, MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_MASK, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_DCXO_GPS_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_JEITA, MT6351_PMIC_AUXADC_ADC_BUSY_IN_JEITA_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_JEITA_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_JEITA_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_MDRT, MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDRT_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDRT_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDRT_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_MDBG, MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDBG_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDBG_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_MDBG_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_SHARE, MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHARE_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHARE_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_SHARE_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_IMP, MT6351_PMIC_AUXADC_ADC_BUSY_IN_IMP_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_IMP_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_IMP_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_FGADC1, MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC1_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC1_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC1_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_FGADC2, MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC2_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC2_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_FGADC2_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_GPS_AP, MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_AP_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_GPS_MD, MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MD_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_GPS, MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_GPS_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_THR_HW, MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_HW_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_HW_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_HW_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_THR_MD, MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_MD_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_MD_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_THR_MD_SHIFT}, + {PMIC_AUXADC_ADC_BUSY_IN_NAG, MT6351_PMIC_AUXADC_ADC_BUSY_IN_NAG_ADDR, + MT6351_PMIC_AUXADC_ADC_BUSY_IN_NAG_MASK, MT6351_PMIC_AUXADC_ADC_BUSY_IN_NAG_SHIFT}, + {PMIC_AUXADC_RQST_CH0, MT6351_PMIC_AUXADC_RQST_CH0_ADDR, + MT6351_PMIC_AUXADC_RQST_CH0_MASK, MT6351_PMIC_AUXADC_RQST_CH0_SHIFT}, + {PMIC_AUXADC_RQST_CH1, MT6351_PMIC_AUXADC_RQST_CH1_ADDR, + MT6351_PMIC_AUXADC_RQST_CH1_MASK, MT6351_PMIC_AUXADC_RQST_CH1_SHIFT}, + {PMIC_AUXADC_RQST_CH2, MT6351_PMIC_AUXADC_RQST_CH2_ADDR, + MT6351_PMIC_AUXADC_RQST_CH2_MASK, MT6351_PMIC_AUXADC_RQST_CH2_SHIFT}, + {PMIC_AUXADC_RQST_CH3, MT6351_PMIC_AUXADC_RQST_CH3_ADDR, + MT6351_PMIC_AUXADC_RQST_CH3_MASK, MT6351_PMIC_AUXADC_RQST_CH3_SHIFT}, + {PMIC_AUXADC_RQST_CH4, MT6351_PMIC_AUXADC_RQST_CH4_ADDR, + MT6351_PMIC_AUXADC_RQST_CH4_MASK, MT6351_PMIC_AUXADC_RQST_CH4_SHIFT}, + {PMIC_AUXADC_RQST_CH5, MT6351_PMIC_AUXADC_RQST_CH5_ADDR, + MT6351_PMIC_AUXADC_RQST_CH5_MASK, MT6351_PMIC_AUXADC_RQST_CH5_SHIFT}, + {PMIC_AUXADC_RQST_CH6, MT6351_PMIC_AUXADC_RQST_CH6_ADDR, + MT6351_PMIC_AUXADC_RQST_CH6_MASK, MT6351_PMIC_AUXADC_RQST_CH6_SHIFT}, + {PMIC_AUXADC_RQST_CH7, MT6351_PMIC_AUXADC_RQST_CH7_ADDR, + MT6351_PMIC_AUXADC_RQST_CH7_MASK, MT6351_PMIC_AUXADC_RQST_CH7_SHIFT}, + {PMIC_AUXADC_RQST_CH8, MT6351_PMIC_AUXADC_RQST_CH8_ADDR, + MT6351_PMIC_AUXADC_RQST_CH8_MASK, MT6351_PMIC_AUXADC_RQST_CH8_SHIFT}, + {PMIC_AUXADC_RQST_CH9, MT6351_PMIC_AUXADC_RQST_CH9_ADDR, + MT6351_PMIC_AUXADC_RQST_CH9_MASK, MT6351_PMIC_AUXADC_RQST_CH9_SHIFT}, + {PMIC_AUXADC_RQST_CH10, MT6351_PMIC_AUXADC_RQST_CH10_ADDR, + MT6351_PMIC_AUXADC_RQST_CH10_MASK, MT6351_PMIC_AUXADC_RQST_CH10_SHIFT}, + {PMIC_AUXADC_RQST_CH11, MT6351_PMIC_AUXADC_RQST_CH11_ADDR, + MT6351_PMIC_AUXADC_RQST_CH11_MASK, MT6351_PMIC_AUXADC_RQST_CH11_SHIFT}, + {PMIC_AUXADC_RQST_CH12, MT6351_PMIC_AUXADC_RQST_CH12_ADDR, + MT6351_PMIC_AUXADC_RQST_CH12_MASK, MT6351_PMIC_AUXADC_RQST_CH12_SHIFT}, + {PMIC_AUXADC_RQST_CH13, MT6351_PMIC_AUXADC_RQST_CH13_ADDR, + MT6351_PMIC_AUXADC_RQST_CH13_MASK, MT6351_PMIC_AUXADC_RQST_CH13_SHIFT}, + {PMIC_AUXADC_RQST_CH14, MT6351_PMIC_AUXADC_RQST_CH14_ADDR, + MT6351_PMIC_AUXADC_RQST_CH14_MASK, MT6351_PMIC_AUXADC_RQST_CH14_SHIFT}, + {PMIC_AUXADC_RQST_CH15, MT6351_PMIC_AUXADC_RQST_CH15_ADDR, + MT6351_PMIC_AUXADC_RQST_CH15_MASK, MT6351_PMIC_AUXADC_RQST_CH15_SHIFT}, + {PMIC_AUXADC_RQST0_SET, MT6351_PMIC_AUXADC_RQST0_SET_ADDR, + MT6351_PMIC_AUXADC_RQST0_SET_MASK, MT6351_PMIC_AUXADC_RQST0_SET_SHIFT}, + {PMIC_AUXADC_RQST0_CLR, MT6351_PMIC_AUXADC_RQST0_CLR_ADDR, + MT6351_PMIC_AUXADC_RQST0_CLR_MASK, MT6351_PMIC_AUXADC_RQST0_CLR_SHIFT}, + {PMIC_AUXADC_RQST_CH0_BY_MD, MT6351_PMIC_AUXADC_RQST_CH0_BY_MD_ADDR, + MT6351_PMIC_AUXADC_RQST_CH0_BY_MD_MASK, MT6351_PMIC_AUXADC_RQST_CH0_BY_MD_SHIFT}, + {PMIC_AUXADC_RQST_CH1_BY_MD, MT6351_PMIC_AUXADC_RQST_CH1_BY_MD_ADDR, + MT6351_PMIC_AUXADC_RQST_CH1_BY_MD_MASK, MT6351_PMIC_AUXADC_RQST_CH1_BY_MD_SHIFT}, + {PMIC_AUXADC_RQST_RSV0, MT6351_PMIC_AUXADC_RQST_RSV0_ADDR, + MT6351_PMIC_AUXADC_RQST_RSV0_MASK, MT6351_PMIC_AUXADC_RQST_RSV0_SHIFT}, + {PMIC_AUXADC_RQST_CH4_BY_MD, MT6351_PMIC_AUXADC_RQST_CH4_BY_MD_ADDR, + MT6351_PMIC_AUXADC_RQST_CH4_BY_MD_MASK, MT6351_PMIC_AUXADC_RQST_CH4_BY_MD_SHIFT}, + {PMIC_AUXADC_RQST_CH7_BY_MD, MT6351_PMIC_AUXADC_RQST_CH7_BY_MD_ADDR, + MT6351_PMIC_AUXADC_RQST_CH7_BY_MD_MASK, MT6351_PMIC_AUXADC_RQST_CH7_BY_MD_SHIFT}, + {PMIC_AUXADC_RQST_CH7_BY_GPS, MT6351_PMIC_AUXADC_RQST_CH7_BY_GPS_ADDR, + MT6351_PMIC_AUXADC_RQST_CH7_BY_GPS_MASK, MT6351_PMIC_AUXADC_RQST_CH7_BY_GPS_SHIFT}, + {PMIC_AUXADC_RQST_DCXO_BY_MD, MT6351_PMIC_AUXADC_RQST_DCXO_BY_MD_ADDR, + MT6351_PMIC_AUXADC_RQST_DCXO_BY_MD_MASK, MT6351_PMIC_AUXADC_RQST_DCXO_BY_MD_SHIFT}, + {PMIC_AUXADC_RQST_DCXO_BY_GPS, MT6351_PMIC_AUXADC_RQST_DCXO_BY_GPS_ADDR, + MT6351_PMIC_AUXADC_RQST_DCXO_BY_GPS_MASK, MT6351_PMIC_AUXADC_RQST_DCXO_BY_GPS_SHIFT}, + {PMIC_AUXADC_RQST_RSV1, MT6351_PMIC_AUXADC_RQST_RSV1_ADDR, + MT6351_PMIC_AUXADC_RQST_RSV1_MASK, MT6351_PMIC_AUXADC_RQST_RSV1_SHIFT}, + {PMIC_AUXADC_RQST1_SET, MT6351_PMIC_AUXADC_RQST1_SET_ADDR, + MT6351_PMIC_AUXADC_RQST1_SET_MASK, MT6351_PMIC_AUXADC_RQST1_SET_SHIFT}, + {PMIC_AUXADC_RQST1_CLR, MT6351_PMIC_AUXADC_RQST1_CLR_ADDR, + MT6351_PMIC_AUXADC_RQST1_CLR_MASK, MT6351_PMIC_AUXADC_RQST1_CLR_SHIFT}, + {PMIC_AUXADC_CK_ON_EXTD, MT6351_PMIC_AUXADC_CK_ON_EXTD_ADDR, + MT6351_PMIC_AUXADC_CK_ON_EXTD_MASK, MT6351_PMIC_AUXADC_CK_ON_EXTD_SHIFT}, + {PMIC_AUXADC_SRCLKEN_SRC_SEL, MT6351_PMIC_AUXADC_SRCLKEN_SRC_SEL_ADDR, + MT6351_PMIC_AUXADC_SRCLKEN_SRC_SEL_MASK, MT6351_PMIC_AUXADC_SRCLKEN_SRC_SEL_SHIFT}, + {PMIC_AUXADC_ADC_PWDB, MT6351_PMIC_AUXADC_ADC_PWDB_ADDR, + MT6351_PMIC_AUXADC_ADC_PWDB_MASK, MT6351_PMIC_AUXADC_ADC_PWDB_SHIFT}, + {PMIC_AUXADC_ADC_PWDB_SWCTRL, MT6351_PMIC_AUXADC_ADC_PWDB_SWCTRL_ADDR, + MT6351_PMIC_AUXADC_ADC_PWDB_SWCTRL_MASK, MT6351_PMIC_AUXADC_ADC_PWDB_SWCTRL_SHIFT}, + {PMIC_AUXADC_STRUP_CK_ON_ENB, MT6351_PMIC_AUXADC_STRUP_CK_ON_ENB_ADDR, + MT6351_PMIC_AUXADC_STRUP_CK_ON_ENB_MASK, MT6351_PMIC_AUXADC_STRUP_CK_ON_ENB_SHIFT}, + {PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_ADDR, + MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_MASK, MT6351_PMIC_AUXADC_ADC_RDY_WAKEUP_CLR_SHIFT}, + {PMIC_AUXADC_SRCLKEN_CK_EN, MT6351_PMIC_AUXADC_SRCLKEN_CK_EN_ADDR, + MT6351_PMIC_AUXADC_SRCLKEN_CK_EN_MASK, MT6351_PMIC_AUXADC_SRCLKEN_CK_EN_SHIFT}, + {PMIC_AUXADC_CK_AON_GPS, MT6351_PMIC_AUXADC_CK_AON_GPS_ADDR, + MT6351_PMIC_AUXADC_CK_AON_GPS_MASK, MT6351_PMIC_AUXADC_CK_AON_GPS_SHIFT}, + {PMIC_AUXADC_CK_AON_MD, MT6351_PMIC_AUXADC_CK_AON_MD_ADDR, + MT6351_PMIC_AUXADC_CK_AON_MD_MASK, MT6351_PMIC_AUXADC_CK_AON_MD_SHIFT}, + {PMIC_AUXADC_CK_AON, MT6351_PMIC_AUXADC_CK_AON_ADDR, + MT6351_PMIC_AUXADC_CK_AON_MASK, MT6351_PMIC_AUXADC_CK_AON_SHIFT}, + {PMIC_AUXADC_CON0_SET, MT6351_PMIC_AUXADC_CON0_SET_ADDR, + MT6351_PMIC_AUXADC_CON0_SET_MASK, MT6351_PMIC_AUXADC_CON0_SET_SHIFT}, + {PMIC_AUXADC_CON0_CLR, MT6351_PMIC_AUXADC_CON0_CLR_ADDR, + MT6351_PMIC_AUXADC_CON0_CLR_MASK, MT6351_PMIC_AUXADC_CON0_CLR_SHIFT}, + {PMIC_AUXADC_AVG_NUM_SMALL, MT6351_PMIC_AUXADC_AVG_NUM_SMALL_ADDR, + MT6351_PMIC_AUXADC_AVG_NUM_SMALL_MASK, MT6351_PMIC_AUXADC_AVG_NUM_SMALL_SHIFT}, + {PMIC_AUXADC_AVG_NUM_LARGE, MT6351_PMIC_AUXADC_AVG_NUM_LARGE_ADDR, + MT6351_PMIC_AUXADC_AVG_NUM_LARGE_MASK, MT6351_PMIC_AUXADC_AVG_NUM_LARGE_SHIFT}, + {PMIC_AUXADC_SPL_NUM, MT6351_PMIC_AUXADC_SPL_NUM_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_MASK, MT6351_PMIC_AUXADC_SPL_NUM_SHIFT}, + {PMIC_AUXADC_AVG_NUM_SEL, MT6351_PMIC_AUXADC_AVG_NUM_SEL_ADDR, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_MASK, MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHIFT}, + {PMIC_AUXADC_AVG_NUM_SEL_SHARE, MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHARE_ADDR, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHARE_MASK, MT6351_PMIC_AUXADC_AVG_NUM_SEL_SHARE_SHIFT}, + {PMIC_AUXADC_AVG_NUM_SEL_LBAT, MT6351_PMIC_AUXADC_AVG_NUM_SEL_LBAT_ADDR, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_LBAT_MASK, MT6351_PMIC_AUXADC_AVG_NUM_SEL_LBAT_SHIFT}, + {PMIC_AUXADC_AVG_NUM_SEL_VISMPS, MT6351_PMIC_AUXADC_AVG_NUM_SEL_VISMPS_ADDR, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_VISMPS_MASK, MT6351_PMIC_AUXADC_AVG_NUM_SEL_VISMPS_SHIFT}, + {PMIC_AUXADC_AVG_NUM_SEL_WAKEUP, MT6351_PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_ADDR, + MT6351_PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_MASK, MT6351_PMIC_AUXADC_AVG_NUM_SEL_WAKEUP_SHIFT}, + {PMIC_AUXADC_SPL_NUM_LARGE, MT6351_PMIC_AUXADC_SPL_NUM_LARGE_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_LARGE_MASK, MT6351_PMIC_AUXADC_SPL_NUM_LARGE_SHIFT}, + {PMIC_AUXADC_SPL_NUM_SLEEP, MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_MASK, MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SHIFT}, + {PMIC_AUXADC_SPL_NUM_SLEEP_SEL, MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SEL_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SEL_MASK, MT6351_PMIC_AUXADC_SPL_NUM_SLEEP_SEL_SHIFT}, + {PMIC_AUXADC_SPL_NUM_SEL, MT6351_PMIC_AUXADC_SPL_NUM_SEL_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_MASK, MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHIFT}, + {PMIC_AUXADC_SPL_NUM_SEL_SHARE, MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHARE_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHARE_MASK, MT6351_PMIC_AUXADC_SPL_NUM_SEL_SHARE_SHIFT}, + {PMIC_AUXADC_SPL_NUM_SEL_LBAT, MT6351_PMIC_AUXADC_SPL_NUM_SEL_LBAT_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_LBAT_MASK, MT6351_PMIC_AUXADC_SPL_NUM_SEL_LBAT_SHIFT}, + {PMIC_AUXADC_SPL_NUM_SEL_VISMPS, MT6351_PMIC_AUXADC_SPL_NUM_SEL_VISMPS_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_VISMPS_MASK, MT6351_PMIC_AUXADC_SPL_NUM_SEL_VISMPS_SHIFT}, + {PMIC_AUXADC_SPL_NUM_SEL_WAKEUP, MT6351_PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_ADDR, + MT6351_PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_MASK, MT6351_PMIC_AUXADC_SPL_NUM_SEL_WAKEUP_SHIFT}, + {PMIC_AUXADC_TRIM_CH0_SEL, MT6351_PMIC_AUXADC_TRIM_CH0_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH0_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH0_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH1_SEL, MT6351_PMIC_AUXADC_TRIM_CH1_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH1_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH1_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH2_SEL, MT6351_PMIC_AUXADC_TRIM_CH2_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH2_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH2_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH3_SEL, MT6351_PMIC_AUXADC_TRIM_CH3_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH3_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH3_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH4_SEL, MT6351_PMIC_AUXADC_TRIM_CH4_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH4_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH4_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH5_SEL, MT6351_PMIC_AUXADC_TRIM_CH5_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH5_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH5_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH6_SEL, MT6351_PMIC_AUXADC_TRIM_CH6_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH6_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH6_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH7_SEL, MT6351_PMIC_AUXADC_TRIM_CH7_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH7_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH7_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH8_SEL, MT6351_PMIC_AUXADC_TRIM_CH8_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH8_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH8_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH9_SEL, MT6351_PMIC_AUXADC_TRIM_CH9_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH9_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH9_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH10_SEL, MT6351_PMIC_AUXADC_TRIM_CH10_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH10_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH10_SEL_SHIFT}, + {PMIC_AUXADC_TRIM_CH11_SEL, MT6351_PMIC_AUXADC_TRIM_CH11_SEL_ADDR, + MT6351_PMIC_AUXADC_TRIM_CH11_SEL_MASK, MT6351_PMIC_AUXADC_TRIM_CH11_SEL_SHIFT}, + {PMIC_AUXADC_ADC_2S_COMP_ENB, MT6351_PMIC_AUXADC_ADC_2S_COMP_ENB_ADDR, + MT6351_PMIC_AUXADC_ADC_2S_COMP_ENB_MASK, MT6351_PMIC_AUXADC_ADC_2S_COMP_ENB_SHIFT}, + {PMIC_AUXADC_ADC_TRIM_COMP, MT6351_PMIC_AUXADC_ADC_TRIM_COMP_ADDR, + MT6351_PMIC_AUXADC_ADC_TRIM_COMP_MASK, MT6351_PMIC_AUXADC_ADC_TRIM_COMP_SHIFT}, + {PMIC_AUXADC_SW_GAIN_TRIM, MT6351_PMIC_AUXADC_SW_GAIN_TRIM_ADDR, + MT6351_PMIC_AUXADC_SW_GAIN_TRIM_MASK, MT6351_PMIC_AUXADC_SW_GAIN_TRIM_SHIFT}, + {PMIC_AUXADC_SW_OFFSET_TRIM, MT6351_PMIC_AUXADC_SW_OFFSET_TRIM_ADDR, + MT6351_PMIC_AUXADC_SW_OFFSET_TRIM_MASK, MT6351_PMIC_AUXADC_SW_OFFSET_TRIM_SHIFT}, + {PMIC_AUXADC_RNG_EN, MT6351_PMIC_AUXADC_RNG_EN_ADDR, + MT6351_PMIC_AUXADC_RNG_EN_MASK, MT6351_PMIC_AUXADC_RNG_EN_SHIFT}, + {PMIC_AUXADC_DATA_REUSE_SEL, MT6351_PMIC_AUXADC_DATA_REUSE_SEL_ADDR, + MT6351_PMIC_AUXADC_DATA_REUSE_SEL_MASK, MT6351_PMIC_AUXADC_DATA_REUSE_SEL_SHIFT}, + {PMIC_AUXADC_TEST_MODE, MT6351_PMIC_AUXADC_TEST_MODE_ADDR, + MT6351_PMIC_AUXADC_TEST_MODE_MASK, MT6351_PMIC_AUXADC_TEST_MODE_SHIFT}, + {PMIC_AUXADC_BIT_SEL, MT6351_PMIC_AUXADC_BIT_SEL_ADDR, + MT6351_PMIC_AUXADC_BIT_SEL_MASK, MT6351_PMIC_AUXADC_BIT_SEL_SHIFT}, + {PMIC_AUXADC_START_SW, MT6351_PMIC_AUXADC_START_SW_ADDR, + MT6351_PMIC_AUXADC_START_SW_MASK, MT6351_PMIC_AUXADC_START_SW_SHIFT}, + {PMIC_AUXADC_START_SWCTRL, MT6351_PMIC_AUXADC_START_SWCTRL_ADDR, + MT6351_PMIC_AUXADC_START_SWCTRL_MASK, MT6351_PMIC_AUXADC_START_SWCTRL_SHIFT}, + {PMIC_AUXADC_TS_VBE_SEL, MT6351_PMIC_AUXADC_TS_VBE_SEL_ADDR, + MT6351_PMIC_AUXADC_TS_VBE_SEL_MASK, MT6351_PMIC_AUXADC_TS_VBE_SEL_SHIFT}, + {PMIC_AUXADC_TS_VBE_SEL_SWCTRL, MT6351_PMIC_AUXADC_TS_VBE_SEL_SWCTRL_ADDR, + MT6351_PMIC_AUXADC_TS_VBE_SEL_SWCTRL_MASK, MT6351_PMIC_AUXADC_TS_VBE_SEL_SWCTRL_SHIFT}, + {PMIC_AUXADC_VBUF_EN, MT6351_PMIC_AUXADC_VBUF_EN_ADDR, + MT6351_PMIC_AUXADC_VBUF_EN_MASK, MT6351_PMIC_AUXADC_VBUF_EN_SHIFT}, + {PMIC_AUXADC_VBUF_EN_SWCTRL, MT6351_PMIC_AUXADC_VBUF_EN_SWCTRL_ADDR, + MT6351_PMIC_AUXADC_VBUF_EN_SWCTRL_MASK, MT6351_PMIC_AUXADC_VBUF_EN_SWCTRL_SHIFT}, + {PMIC_AUXADC_OUT_SEL, MT6351_PMIC_AUXADC_OUT_SEL_ADDR, + MT6351_PMIC_AUXADC_OUT_SEL_MASK, MT6351_PMIC_AUXADC_OUT_SEL_SHIFT}, + {PMIC_AUXADC_DA_DAC, MT6351_PMIC_AUXADC_DA_DAC_ADDR, + MT6351_PMIC_AUXADC_DA_DAC_MASK, MT6351_PMIC_AUXADC_DA_DAC_SHIFT}, + {PMIC_AUXADC_DA_DAC_SWCTRL, MT6351_PMIC_AUXADC_DA_DAC_SWCTRL_ADDR, + MT6351_PMIC_AUXADC_DA_DAC_SWCTRL_MASK, MT6351_PMIC_AUXADC_DA_DAC_SWCTRL_SHIFT}, + {PMIC_AD_AUXADC_COMP, MT6351_PMIC_AD_AUXADC_COMP_ADDR, + MT6351_PMIC_AD_AUXADC_COMP_MASK, MT6351_PMIC_AD_AUXADC_COMP_SHIFT}, + {PMIC_RG_VBUF_EXTEN, MT6351_PMIC_RG_VBUF_EXTEN_ADDR, + MT6351_PMIC_RG_VBUF_EXTEN_MASK, MT6351_PMIC_RG_VBUF_EXTEN_SHIFT}, + {PMIC_RG_VBUF_CALEN, MT6351_PMIC_RG_VBUF_CALEN_ADDR, + MT6351_PMIC_RG_VBUF_CALEN_MASK, MT6351_PMIC_RG_VBUF_CALEN_SHIFT}, + {PMIC_RG_VBUF_BYP, MT6351_PMIC_RG_VBUF_BYP_ADDR, MT6351_PMIC_RG_VBUF_BYP_MASK, + MT6351_PMIC_RG_VBUF_BYP_SHIFT}, + {PMIC_RG_AUX_RSV, MT6351_PMIC_RG_AUX_RSV_ADDR, MT6351_PMIC_RG_AUX_RSV_MASK, + MT6351_PMIC_RG_AUX_RSV_SHIFT}, + {PMIC_RG_AUXADC_CALI, MT6351_PMIC_RG_AUXADC_CALI_ADDR, + MT6351_PMIC_RG_AUXADC_CALI_MASK, MT6351_PMIC_RG_AUXADC_CALI_SHIFT}, + {PMIC_AUXADC_ADCIN_VSEN_EN, MT6351_PMIC_AUXADC_ADCIN_VSEN_EN_ADDR, + MT6351_PMIC_AUXADC_ADCIN_VSEN_EN_MASK, MT6351_PMIC_AUXADC_ADCIN_VSEN_EN_SHIFT}, + {PMIC_AUXADC_ADCIN_VBAT_EN, MT6351_PMIC_AUXADC_ADCIN_VBAT_EN_ADDR, + MT6351_PMIC_AUXADC_ADCIN_VBAT_EN_MASK, MT6351_PMIC_AUXADC_ADCIN_VBAT_EN_SHIFT}, + {PMIC_AUXADC_ADCIN_VSEN_MUX_EN, MT6351_PMIC_AUXADC_ADCIN_VSEN_MUX_EN_ADDR, + MT6351_PMIC_AUXADC_ADCIN_VSEN_MUX_EN_MASK, MT6351_PMIC_AUXADC_ADCIN_VSEN_MUX_EN_SHIFT}, + {PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN, + MT6351_PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_ADDR, + MT6351_PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_MASK, + MT6351_PMIC_AUXADC_ADCIN_VSEN_EXT_BATON_EN_SHIFT}, + {PMIC_AUXADC_ADCIN_CHR_EN, MT6351_PMIC_AUXADC_ADCIN_CHR_EN_ADDR, + MT6351_PMIC_AUXADC_ADCIN_CHR_EN_MASK, MT6351_PMIC_AUXADC_ADCIN_CHR_EN_SHIFT}, + {PMIC_AUXADC_ADCIN_BATON_TDET_EN, MT6351_PMIC_AUXADC_ADCIN_BATON_TDET_EN_ADDR, + MT6351_PMIC_AUXADC_ADCIN_BATON_TDET_EN_MASK, + MT6351_PMIC_AUXADC_ADCIN_BATON_TDET_EN_SHIFT}, + {PMIC_AUXADC_ACCDET_ANASWCTRL_EN, MT6351_PMIC_AUXADC_ACCDET_ANASWCTRL_EN_ADDR, + MT6351_PMIC_AUXADC_ACCDET_ANASWCTRL_EN_MASK, + MT6351_PMIC_AUXADC_ACCDET_ANASWCTRL_EN_SHIFT}, + {PMIC_AUXADC_DIG0_RSV0, MT6351_PMIC_AUXADC_DIG0_RSV0_ADDR, + MT6351_PMIC_AUXADC_DIG0_RSV0_MASK, MT6351_PMIC_AUXADC_DIG0_RSV0_SHIFT}, + {PMIC_AUXADC_CHSEL, MT6351_PMIC_AUXADC_CHSEL_ADDR, MT6351_PMIC_AUXADC_CHSEL_MASK, + MT6351_PMIC_AUXADC_CHSEL_SHIFT}, + {PMIC_AUXADC_SWCTRL_EN, MT6351_PMIC_AUXADC_SWCTRL_EN_ADDR, + MT6351_PMIC_AUXADC_SWCTRL_EN_MASK, MT6351_PMIC_AUXADC_SWCTRL_EN_SHIFT}, + {PMIC_AUXADC_SOURCE_LBAT_SEL, MT6351_PMIC_AUXADC_SOURCE_LBAT_SEL_ADDR, + MT6351_PMIC_AUXADC_SOURCE_LBAT_SEL_MASK, MT6351_PMIC_AUXADC_SOURCE_LBAT_SEL_SHIFT}, + {PMIC_AUXADC_SOURCE_LBAT2_SEL, MT6351_PMIC_AUXADC_SOURCE_LBAT2_SEL_ADDR, + MT6351_PMIC_AUXADC_SOURCE_LBAT2_SEL_MASK, MT6351_PMIC_AUXADC_SOURCE_LBAT2_SEL_SHIFT}, + {PMIC_AUXADC_DIG0_RSV2, MT6351_PMIC_AUXADC_DIG0_RSV2_ADDR, + MT6351_PMIC_AUXADC_DIG0_RSV2_MASK, MT6351_PMIC_AUXADC_DIG0_RSV2_SHIFT}, + {PMIC_AUXADC_DIG1_RSV2, MT6351_PMIC_AUXADC_DIG1_RSV2_ADDR, + MT6351_PMIC_AUXADC_DIG1_RSV2_MASK, MT6351_PMIC_AUXADC_DIG1_RSV2_SHIFT}, + {PMIC_AUXADC_DAC_EXTD, MT6351_PMIC_AUXADC_DAC_EXTD_ADDR, + MT6351_PMIC_AUXADC_DAC_EXTD_MASK, MT6351_PMIC_AUXADC_DAC_EXTD_SHIFT}, + {PMIC_AUXADC_DAC_EXTD_EN, MT6351_PMIC_AUXADC_DAC_EXTD_EN_ADDR, + MT6351_PMIC_AUXADC_DAC_EXTD_EN_MASK, MT6351_PMIC_AUXADC_DAC_EXTD_EN_SHIFT}, + {PMIC_AUXADC_PMU_THR_PDN_SW, MT6351_PMIC_AUXADC_PMU_THR_PDN_SW_ADDR, + MT6351_PMIC_AUXADC_PMU_THR_PDN_SW_MASK, MT6351_PMIC_AUXADC_PMU_THR_PDN_SW_SHIFT}, + {PMIC_AUXADC_PMU_THR_PDN_SEL, MT6351_PMIC_AUXADC_PMU_THR_PDN_SEL_ADDR, + MT6351_PMIC_AUXADC_PMU_THR_PDN_SEL_MASK, MT6351_PMIC_AUXADC_PMU_THR_PDN_SEL_SHIFT}, + {PMIC_AUXADC_PMU_THR_PDN_STATUS, MT6351_PMIC_AUXADC_PMU_THR_PDN_STATUS_ADDR, + MT6351_PMIC_AUXADC_PMU_THR_PDN_STATUS_MASK, MT6351_PMIC_AUXADC_PMU_THR_PDN_STATUS_SHIFT}, + {PMIC_AUXADC_DIG0_RSV1, MT6351_PMIC_AUXADC_DIG0_RSV1_ADDR, + MT6351_PMIC_AUXADC_DIG0_RSV1_MASK, MT6351_PMIC_AUXADC_DIG0_RSV1_SHIFT}, + {PMIC_AUXADC_START_SHADE_NUM, MT6351_PMIC_AUXADC_START_SHADE_NUM_ADDR, + MT6351_PMIC_AUXADC_START_SHADE_NUM_MASK, MT6351_PMIC_AUXADC_START_SHADE_NUM_SHIFT}, + {PMIC_AUXADC_START_SHADE_EN, MT6351_PMIC_AUXADC_START_SHADE_EN_ADDR, + MT6351_PMIC_AUXADC_START_SHADE_EN_MASK, MT6351_PMIC_AUXADC_START_SHADE_EN_SHIFT}, + {PMIC_AUXADC_START_SHADE_SEL, MT6351_PMIC_AUXADC_START_SHADE_SEL_ADDR, + MT6351_PMIC_AUXADC_START_SHADE_SEL_MASK, MT6351_PMIC_AUXADC_START_SHADE_SEL_SHIFT}, + {PMIC_AUXADC_AUTORPT_PRD, MT6351_PMIC_AUXADC_AUTORPT_PRD_ADDR, + MT6351_PMIC_AUXADC_AUTORPT_PRD_MASK, MT6351_PMIC_AUXADC_AUTORPT_PRD_SHIFT}, + {PMIC_AUXADC_AUTORPT_EN, MT6351_PMIC_AUXADC_AUTORPT_EN_ADDR, + MT6351_PMIC_AUXADC_AUTORPT_EN_MASK, MT6351_PMIC_AUXADC_AUTORPT_EN_SHIFT}, + {PMIC_AUXADC_LBAT_DEBT_MAX, MT6351_PMIC_AUXADC_LBAT_DEBT_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT_DEBT_MAX_MASK, MT6351_PMIC_AUXADC_LBAT_DEBT_MAX_SHIFT}, + {PMIC_AUXADC_LBAT_DEBT_MIN, MT6351_PMIC_AUXADC_LBAT_DEBT_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT_DEBT_MIN_MASK, MT6351_PMIC_AUXADC_LBAT_DEBT_MIN_SHIFT}, + {PMIC_AUXADC_LBAT_DET_PRD_15_0, MT6351_PMIC_AUXADC_LBAT_DET_PRD_15_0_ADDR, + MT6351_PMIC_AUXADC_LBAT_DET_PRD_15_0_MASK, MT6351_PMIC_AUXADC_LBAT_DET_PRD_15_0_SHIFT}, + {PMIC_AUXADC_LBAT_DET_PRD_19_16, MT6351_PMIC_AUXADC_LBAT_DET_PRD_19_16_ADDR, + MT6351_PMIC_AUXADC_LBAT_DET_PRD_19_16_MASK, MT6351_PMIC_AUXADC_LBAT_DET_PRD_19_16_SHIFT}, + {PMIC_AUXADC_LBAT_VOLT_MAX, MT6351_PMIC_AUXADC_LBAT_VOLT_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT_VOLT_MAX_MASK, MT6351_PMIC_AUXADC_LBAT_VOLT_MAX_SHIFT}, + {PMIC_AUXADC_LBAT_IRQ_EN_MAX, MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MAX_MASK, MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MAX_SHIFT}, + {PMIC_AUXADC_LBAT_EN_MAX, MT6351_PMIC_AUXADC_LBAT_EN_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT_EN_MAX_MASK, MT6351_PMIC_AUXADC_LBAT_EN_MAX_SHIFT}, + {PMIC_AUXADC_LBAT_MAX_IRQ_B, MT6351_PMIC_AUXADC_LBAT_MAX_IRQ_B_ADDR, + MT6351_PMIC_AUXADC_LBAT_MAX_IRQ_B_MASK, MT6351_PMIC_AUXADC_LBAT_MAX_IRQ_B_SHIFT}, + {PMIC_AUXADC_LBAT_VOLT_MIN, MT6351_PMIC_AUXADC_LBAT_VOLT_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT_VOLT_MIN_MASK, MT6351_PMIC_AUXADC_LBAT_VOLT_MIN_SHIFT}, + {PMIC_AUXADC_LBAT_IRQ_EN_MIN, MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MIN_MASK, MT6351_PMIC_AUXADC_LBAT_IRQ_EN_MIN_SHIFT}, + {PMIC_AUXADC_LBAT_EN_MIN, MT6351_PMIC_AUXADC_LBAT_EN_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT_EN_MIN_MASK, MT6351_PMIC_AUXADC_LBAT_EN_MIN_SHIFT}, + {PMIC_AUXADC_LBAT_MIN_IRQ_B, MT6351_PMIC_AUXADC_LBAT_MIN_IRQ_B_ADDR, + MT6351_PMIC_AUXADC_LBAT_MIN_IRQ_B_MASK, MT6351_PMIC_AUXADC_LBAT_MIN_IRQ_B_SHIFT}, + {PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX, + MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_MASK, + MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MAX_SHIFT}, + {PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN, + MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_MASK, + MT6351_PMIC_AUXADC_LBAT_DEBOUNCE_COUNT_MIN_SHIFT}, + {PMIC_AUXADC_ACCDET_AUTO_SPL, MT6351_PMIC_AUXADC_ACCDET_AUTO_SPL_ADDR, + MT6351_PMIC_AUXADC_ACCDET_AUTO_SPL_MASK, MT6351_PMIC_AUXADC_ACCDET_AUTO_SPL_SHIFT}, + {PMIC_AUXADC_ACCDET_AUTO_RQST_CLR, MT6351_PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_ADDR, + MT6351_PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_MASK, + MT6351_PMIC_AUXADC_ACCDET_AUTO_RQST_CLR_SHIFT}, + {PMIC_AUXADC_ACCDET_DIG1_RSV0, MT6351_PMIC_AUXADC_ACCDET_DIG1_RSV0_ADDR, + MT6351_PMIC_AUXADC_ACCDET_DIG1_RSV0_MASK, MT6351_PMIC_AUXADC_ACCDET_DIG1_RSV0_SHIFT}, + {PMIC_AUXADC_ACCDET_DIG0_RSV0, MT6351_PMIC_AUXADC_ACCDET_DIG0_RSV0_ADDR, + MT6351_PMIC_AUXADC_ACCDET_DIG0_RSV0_MASK, MT6351_PMIC_AUXADC_ACCDET_DIG0_RSV0_SHIFT}, + {PMIC_AUXADC_THR_DEBT_MAX, MT6351_PMIC_AUXADC_THR_DEBT_MAX_ADDR, + MT6351_PMIC_AUXADC_THR_DEBT_MAX_MASK, MT6351_PMIC_AUXADC_THR_DEBT_MAX_SHIFT}, + {PMIC_AUXADC_THR_DEBT_MIN, MT6351_PMIC_AUXADC_THR_DEBT_MIN_ADDR, + MT6351_PMIC_AUXADC_THR_DEBT_MIN_MASK, MT6351_PMIC_AUXADC_THR_DEBT_MIN_SHIFT}, + {PMIC_AUXADC_THR_DET_PRD_15_0, MT6351_PMIC_AUXADC_THR_DET_PRD_15_0_ADDR, + MT6351_PMIC_AUXADC_THR_DET_PRD_15_0_MASK, MT6351_PMIC_AUXADC_THR_DET_PRD_15_0_SHIFT}, + {PMIC_AUXADC_THR_DET_PRD_19_16, MT6351_PMIC_AUXADC_THR_DET_PRD_19_16_ADDR, + MT6351_PMIC_AUXADC_THR_DET_PRD_19_16_MASK, MT6351_PMIC_AUXADC_THR_DET_PRD_19_16_SHIFT}, + {PMIC_AUXADC_THR_VOLT_MAX, MT6351_PMIC_AUXADC_THR_VOLT_MAX_ADDR, + MT6351_PMIC_AUXADC_THR_VOLT_MAX_MASK, MT6351_PMIC_AUXADC_THR_VOLT_MAX_SHIFT}, + {PMIC_AUXADC_THR_IRQ_EN_MAX, MT6351_PMIC_AUXADC_THR_IRQ_EN_MAX_ADDR, + MT6351_PMIC_AUXADC_THR_IRQ_EN_MAX_MASK, MT6351_PMIC_AUXADC_THR_IRQ_EN_MAX_SHIFT}, + {PMIC_AUXADC_THR_EN_MAX, MT6351_PMIC_AUXADC_THR_EN_MAX_ADDR, + MT6351_PMIC_AUXADC_THR_EN_MAX_MASK, MT6351_PMIC_AUXADC_THR_EN_MAX_SHIFT}, + {PMIC_AUXADC_THR_MAX_IRQ_B, MT6351_PMIC_AUXADC_THR_MAX_IRQ_B_ADDR, + MT6351_PMIC_AUXADC_THR_MAX_IRQ_B_MASK, MT6351_PMIC_AUXADC_THR_MAX_IRQ_B_SHIFT}, + {PMIC_AUXADC_THR_VOLT_MIN, MT6351_PMIC_AUXADC_THR_VOLT_MIN_ADDR, + MT6351_PMIC_AUXADC_THR_VOLT_MIN_MASK, MT6351_PMIC_AUXADC_THR_VOLT_MIN_SHIFT}, + {PMIC_AUXADC_THR_IRQ_EN_MIN, MT6351_PMIC_AUXADC_THR_IRQ_EN_MIN_ADDR, + MT6351_PMIC_AUXADC_THR_IRQ_EN_MIN_MASK, MT6351_PMIC_AUXADC_THR_IRQ_EN_MIN_SHIFT}, + {PMIC_AUXADC_THR_EN_MIN, MT6351_PMIC_AUXADC_THR_EN_MIN_ADDR, + MT6351_PMIC_AUXADC_THR_EN_MIN_MASK, MT6351_PMIC_AUXADC_THR_EN_MIN_SHIFT}, + {PMIC_AUXADC_THR_MIN_IRQ_B, MT6351_PMIC_AUXADC_THR_MIN_IRQ_B_ADDR, + MT6351_PMIC_AUXADC_THR_MIN_IRQ_B_MASK, MT6351_PMIC_AUXADC_THR_MIN_IRQ_B_SHIFT}, + {PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX, + MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_ADDR, + MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_MASK, + MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MAX_SHIFT}, + {PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN, + MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_ADDR, + MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_MASK, + MT6351_PMIC_AUXADC_THR_DEBOUNCE_COUNT_MIN_SHIFT}, + {PMIC_EFUSE_GAIN_CH4_TRIM, MT6351_PMIC_EFUSE_GAIN_CH4_TRIM_ADDR, + MT6351_PMIC_EFUSE_GAIN_CH4_TRIM_MASK, MT6351_PMIC_EFUSE_GAIN_CH4_TRIM_SHIFT}, + {PMIC_EFUSE_OFFSET_CH4_TRIM, MT6351_PMIC_EFUSE_OFFSET_CH4_TRIM_ADDR, + MT6351_PMIC_EFUSE_OFFSET_CH4_TRIM_MASK, MT6351_PMIC_EFUSE_OFFSET_CH4_TRIM_SHIFT}, + {PMIC_EFUSE_GAIN_CH0_TRIM, MT6351_PMIC_EFUSE_GAIN_CH0_TRIM_ADDR, + MT6351_PMIC_EFUSE_GAIN_CH0_TRIM_MASK, MT6351_PMIC_EFUSE_GAIN_CH0_TRIM_SHIFT}, + {PMIC_EFUSE_OFFSET_CH0_TRIM, MT6351_PMIC_EFUSE_OFFSET_CH0_TRIM_ADDR, + MT6351_PMIC_EFUSE_OFFSET_CH0_TRIM_MASK, MT6351_PMIC_EFUSE_OFFSET_CH0_TRIM_SHIFT}, + {PMIC_EFUSE_GAIN_CH7_TRIM, MT6351_PMIC_EFUSE_GAIN_CH7_TRIM_ADDR, + MT6351_PMIC_EFUSE_GAIN_CH7_TRIM_MASK, MT6351_PMIC_EFUSE_GAIN_CH7_TRIM_SHIFT}, + {PMIC_EFUSE_OFFSET_CH7_TRIM, MT6351_PMIC_EFUSE_OFFSET_CH7_TRIM_ADDR, + MT6351_PMIC_EFUSE_OFFSET_CH7_TRIM_MASK, MT6351_PMIC_EFUSE_OFFSET_CH7_TRIM_SHIFT}, + {PMIC_AUXADC_FGADC_START_SW, MT6351_PMIC_AUXADC_FGADC_START_SW_ADDR, + MT6351_PMIC_AUXADC_FGADC_START_SW_MASK, MT6351_PMIC_AUXADC_FGADC_START_SW_SHIFT}, + {PMIC_AUXADC_FGADC_START_SEL, MT6351_PMIC_AUXADC_FGADC_START_SEL_ADDR, + MT6351_PMIC_AUXADC_FGADC_START_SEL_MASK, MT6351_PMIC_AUXADC_FGADC_START_SEL_SHIFT}, + {PMIC_AUXADC_FGADC_R_SW, MT6351_PMIC_AUXADC_FGADC_R_SW_ADDR, + MT6351_PMIC_AUXADC_FGADC_R_SW_MASK, MT6351_PMIC_AUXADC_FGADC_R_SW_SHIFT}, + {PMIC_AUXADC_FGADC_R_SEL, MT6351_PMIC_AUXADC_FGADC_R_SEL_ADDR, + MT6351_PMIC_AUXADC_FGADC_R_SEL_MASK, MT6351_PMIC_AUXADC_FGADC_R_SEL_SHIFT}, + {PMIC_AUXADC_DBG_DIG0_RSV2, MT6351_PMIC_AUXADC_DBG_DIG0_RSV2_ADDR, + MT6351_PMIC_AUXADC_DBG_DIG0_RSV2_MASK, MT6351_PMIC_AUXADC_DBG_DIG0_RSV2_SHIFT}, + {PMIC_AUXADC_DBG_DIG1_RSV2, MT6351_PMIC_AUXADC_DBG_DIG1_RSV2_ADDR, + MT6351_PMIC_AUXADC_DBG_DIG1_RSV2_MASK, MT6351_PMIC_AUXADC_DBG_DIG1_RSV2_SHIFT}, + {PMIC_AUXADC_IMPEDANCE_CNT, MT6351_PMIC_AUXADC_IMPEDANCE_CNT_ADDR, + MT6351_PMIC_AUXADC_IMPEDANCE_CNT_MASK, MT6351_PMIC_AUXADC_IMPEDANCE_CNT_SHIFT}, + {PMIC_AUXADC_IMPEDANCE_CHSEL, MT6351_PMIC_AUXADC_IMPEDANCE_CHSEL_ADDR, + MT6351_PMIC_AUXADC_IMPEDANCE_CHSEL_MASK, MT6351_PMIC_AUXADC_IMPEDANCE_CHSEL_SHIFT}, + {PMIC_AUXADC_IMPEDANCE_IRQ_CLR, MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_CLR_ADDR, + MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_CLR_MASK, MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_CLR_SHIFT}, + {PMIC_AUXADC_IMPEDANCE_IRQ_STATUS, MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_ADDR, + MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_MASK, + MT6351_PMIC_AUXADC_IMPEDANCE_IRQ_STATUS_SHIFT}, + {PMIC_AUXADC_CLR_IMP_CNT_STOP, MT6351_PMIC_AUXADC_CLR_IMP_CNT_STOP_ADDR, + MT6351_PMIC_AUXADC_CLR_IMP_CNT_STOP_MASK, MT6351_PMIC_AUXADC_CLR_IMP_CNT_STOP_SHIFT}, + {PMIC_AUXADC_IMPEDANCE_MODE, MT6351_PMIC_AUXADC_IMPEDANCE_MODE_ADDR, + MT6351_PMIC_AUXADC_IMPEDANCE_MODE_MASK, MT6351_PMIC_AUXADC_IMPEDANCE_MODE_SHIFT}, + {PMIC_AUXADC_IMP_AUTORPT_PRD, MT6351_PMIC_AUXADC_IMP_AUTORPT_PRD_ADDR, + MT6351_PMIC_AUXADC_IMP_AUTORPT_PRD_MASK, MT6351_PMIC_AUXADC_IMP_AUTORPT_PRD_SHIFT}, + {PMIC_AUXADC_IMP_AUTORPT_EN, MT6351_PMIC_AUXADC_IMP_AUTORPT_EN_ADDR, + MT6351_PMIC_AUXADC_IMP_AUTORPT_EN_MASK, MT6351_PMIC_AUXADC_IMP_AUTORPT_EN_SHIFT}, + {PMIC_AUXADC_VISMPS0_DEBT_MAX, MT6351_PMIC_AUXADC_VISMPS0_DEBT_MAX_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_DEBT_MAX_MASK, MT6351_PMIC_AUXADC_VISMPS0_DEBT_MAX_SHIFT}, + {PMIC_AUXADC_VISMPS0_DEBT_MIN, MT6351_PMIC_AUXADC_VISMPS0_DEBT_MIN_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_DEBT_MIN_MASK, MT6351_PMIC_AUXADC_VISMPS0_DEBT_MIN_SHIFT}, + {PMIC_AUXADC_VISMPS0_DET_PRD_15_0, MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_15_0_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_15_0_MASK, + MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_15_0_SHIFT}, + {PMIC_AUXADC_VISMPS0_DET_PRD_19_16, MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_19_16_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_19_16_MASK, + MT6351_PMIC_AUXADC_VISMPS0_DET_PRD_19_16_SHIFT}, + {PMIC_AUXADC_VISMPS0_VOLT_MAX, MT6351_PMIC_AUXADC_VISMPS0_VOLT_MAX_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_VOLT_MAX_MASK, MT6351_PMIC_AUXADC_VISMPS0_VOLT_MAX_SHIFT}, + {PMIC_AUXADC_VISMPS0_IRQ_EN_MAX, MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_MASK, MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MAX_SHIFT}, + {PMIC_AUXADC_VISMPS0_EN_MAX, MT6351_PMIC_AUXADC_VISMPS0_EN_MAX_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_EN_MAX_MASK, MT6351_PMIC_AUXADC_VISMPS0_EN_MAX_SHIFT}, + {PMIC_AUXADC_VISMPS0_MAX_IRQ_B, MT6351_PMIC_AUXADC_VISMPS0_MAX_IRQ_B_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_MAX_IRQ_B_MASK, MT6351_PMIC_AUXADC_VISMPS0_MAX_IRQ_B_SHIFT}, + {PMIC_AUXADC_VISMPS0_VOLT_MIN, MT6351_PMIC_AUXADC_VISMPS0_VOLT_MIN_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_VOLT_MIN_MASK, MT6351_PMIC_AUXADC_VISMPS0_VOLT_MIN_SHIFT}, + {PMIC_AUXADC_VISMPS0_IRQ_EN_MIN, MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_MASK, MT6351_PMIC_AUXADC_VISMPS0_IRQ_EN_MIN_SHIFT}, + {PMIC_AUXADC_VISMPS0_EN_MIN, MT6351_PMIC_AUXADC_VISMPS0_EN_MIN_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_EN_MIN_MASK, MT6351_PMIC_AUXADC_VISMPS0_EN_MIN_SHIFT}, + {PMIC_AUXADC_VISMPS0_MIN_IRQ_B, MT6351_PMIC_AUXADC_VISMPS0_MIN_IRQ_B_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_MIN_IRQ_B_MASK, MT6351_PMIC_AUXADC_VISMPS0_MIN_IRQ_B_SHIFT}, + {PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX, + MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_MASK, + MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MAX_SHIFT}, + {PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN, + MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_ADDR, + MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_MASK, + MT6351_PMIC_AUXADC_VISMPS0_DEBOUNCE_COUNT_MIN_SHIFT}, + {PMIC_AUXADC_LBAT2_DEBT_MAX, MT6351_PMIC_AUXADC_LBAT2_DEBT_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT2_DEBT_MAX_MASK, MT6351_PMIC_AUXADC_LBAT2_DEBT_MAX_SHIFT}, + {PMIC_AUXADC_LBAT2_DEBT_MIN, MT6351_PMIC_AUXADC_LBAT2_DEBT_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT2_DEBT_MIN_MASK, MT6351_PMIC_AUXADC_LBAT2_DEBT_MIN_SHIFT}, + {PMIC_AUXADC_LBAT2_DET_PRD_15_0, MT6351_PMIC_AUXADC_LBAT2_DET_PRD_15_0_ADDR, + MT6351_PMIC_AUXADC_LBAT2_DET_PRD_15_0_MASK, MT6351_PMIC_AUXADC_LBAT2_DET_PRD_15_0_SHIFT}, + {PMIC_AUXADC_LBAT2_DET_PRD_19_16, MT6351_PMIC_AUXADC_LBAT2_DET_PRD_19_16_ADDR, + MT6351_PMIC_AUXADC_LBAT2_DET_PRD_19_16_MASK, + MT6351_PMIC_AUXADC_LBAT2_DET_PRD_19_16_SHIFT}, + {PMIC_AUXADC_LBAT2_VOLT_MAX, MT6351_PMIC_AUXADC_LBAT2_VOLT_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT2_VOLT_MAX_MASK, MT6351_PMIC_AUXADC_LBAT2_VOLT_MAX_SHIFT}, + {PMIC_AUXADC_LBAT2_IRQ_EN_MAX, MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MAX_MASK, MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MAX_SHIFT}, + {PMIC_AUXADC_LBAT2_EN_MAX, MT6351_PMIC_AUXADC_LBAT2_EN_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT2_EN_MAX_MASK, MT6351_PMIC_AUXADC_LBAT2_EN_MAX_SHIFT}, + {PMIC_AUXADC_LBAT2_MAX_IRQ_B, MT6351_PMIC_AUXADC_LBAT2_MAX_IRQ_B_ADDR, + MT6351_PMIC_AUXADC_LBAT2_MAX_IRQ_B_MASK, MT6351_PMIC_AUXADC_LBAT2_MAX_IRQ_B_SHIFT}, + {PMIC_AUXADC_LBAT2_VOLT_MIN, MT6351_PMIC_AUXADC_LBAT2_VOLT_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT2_VOLT_MIN_MASK, MT6351_PMIC_AUXADC_LBAT2_VOLT_MIN_SHIFT}, + {PMIC_AUXADC_LBAT2_IRQ_EN_MIN, MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MIN_MASK, MT6351_PMIC_AUXADC_LBAT2_IRQ_EN_MIN_SHIFT}, + {PMIC_AUXADC_LBAT2_EN_MIN, MT6351_PMIC_AUXADC_LBAT2_EN_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT2_EN_MIN_MASK, MT6351_PMIC_AUXADC_LBAT2_EN_MIN_SHIFT}, + {PMIC_AUXADC_LBAT2_MIN_IRQ_B, MT6351_PMIC_AUXADC_LBAT2_MIN_IRQ_B_ADDR, + MT6351_PMIC_AUXADC_LBAT2_MIN_IRQ_B_MASK, MT6351_PMIC_AUXADC_LBAT2_MIN_IRQ_B_SHIFT}, + {PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX, + MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_ADDR, + MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_MASK, + MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MAX_SHIFT}, + {PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN, + MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_ADDR, + MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_MASK, + MT6351_PMIC_AUXADC_LBAT2_DEBOUNCE_COUNT_MIN_SHIFT}, + {PMIC_AUXADC_MDBG_DET_PRD, MT6351_PMIC_AUXADC_MDBG_DET_PRD_ADDR, + MT6351_PMIC_AUXADC_MDBG_DET_PRD_MASK, MT6351_PMIC_AUXADC_MDBG_DET_PRD_SHIFT}, + {PMIC_AUXADC_MDBG_DET_EN, MT6351_PMIC_AUXADC_MDBG_DET_EN_ADDR, + MT6351_PMIC_AUXADC_MDBG_DET_EN_MASK, MT6351_PMIC_AUXADC_MDBG_DET_EN_SHIFT}, + {PMIC_AUXADC_MDBG_R_PTR, MT6351_PMIC_AUXADC_MDBG_R_PTR_ADDR, + MT6351_PMIC_AUXADC_MDBG_R_PTR_MASK, MT6351_PMIC_AUXADC_MDBG_R_PTR_SHIFT}, + {PMIC_AUXADC_MDBG_W_PTR, MT6351_PMIC_AUXADC_MDBG_W_PTR_ADDR, + MT6351_PMIC_AUXADC_MDBG_W_PTR_MASK, MT6351_PMIC_AUXADC_MDBG_W_PTR_SHIFT}, + {PMIC_AUXADC_MDBG_BUF_LENGTH, MT6351_PMIC_AUXADC_MDBG_BUF_LENGTH_ADDR, + MT6351_PMIC_AUXADC_MDBG_BUF_LENGTH_MASK, MT6351_PMIC_AUXADC_MDBG_BUF_LENGTH_SHIFT}, + {PMIC_AUXADC_MDRT_DET_PRD, MT6351_PMIC_AUXADC_MDRT_DET_PRD_ADDR, + MT6351_PMIC_AUXADC_MDRT_DET_PRD_MASK, MT6351_PMIC_AUXADC_MDRT_DET_PRD_SHIFT}, + {PMIC_AUXADC_MDRT_DET_EN, MT6351_PMIC_AUXADC_MDRT_DET_EN_ADDR, + MT6351_PMIC_AUXADC_MDRT_DET_EN_MASK, MT6351_PMIC_AUXADC_MDRT_DET_EN_SHIFT}, + {PMIC_AUXADC_MDRT_DET_WKUP_START_CNT, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_ADDR, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_MASK, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CNT_SHIFT}, + {PMIC_AUXADC_MDRT_DET_WKUP_START_CLR, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_ADDR, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_MASK, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_CLR_SHIFT}, + {PMIC_AUXADC_MDRT_DET_WKUP_START, MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_ADDR, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_MASK, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SHIFT}, + {PMIC_AUXADC_MDRT_DET_WKUP_START_SEL, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_ADDR, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_MASK, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_START_SEL_SHIFT}, + {PMIC_AUXADC_MDRT_DET_WKUP_EN, MT6351_PMIC_AUXADC_MDRT_DET_WKUP_EN_ADDR, + MT6351_PMIC_AUXADC_MDRT_DET_WKUP_EN_MASK, MT6351_PMIC_AUXADC_MDRT_DET_WKUP_EN_SHIFT}, + {PMIC_AUXADC_MDRT_DET_SRCLKEN_IND, MT6351_PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_ADDR, + MT6351_PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_MASK, + MT6351_PMIC_AUXADC_MDRT_DET_SRCLKEN_IND_SHIFT}, + {PMIC_AUXADC_JEITA_IRQ_EN, MT6351_PMIC_AUXADC_JEITA_IRQ_EN_ADDR, + MT6351_PMIC_AUXADC_JEITA_IRQ_EN_MASK, MT6351_PMIC_AUXADC_JEITA_IRQ_EN_SHIFT}, + {PMIC_AUXADC_JEITA_EN, MT6351_PMIC_AUXADC_JEITA_EN_ADDR, + MT6351_PMIC_AUXADC_JEITA_EN_MASK, MT6351_PMIC_AUXADC_JEITA_EN_SHIFT}, + {PMIC_AUXADC_JEITA_DET_PRD, MT6351_PMIC_AUXADC_JEITA_DET_PRD_ADDR, + MT6351_PMIC_AUXADC_JEITA_DET_PRD_MASK, MT6351_PMIC_AUXADC_JEITA_DET_PRD_SHIFT}, + {PMIC_AUXADC_JEITA_DEBT, MT6351_PMIC_AUXADC_JEITA_DEBT_ADDR, + MT6351_PMIC_AUXADC_JEITA_DEBT_MASK, MT6351_PMIC_AUXADC_JEITA_DEBT_SHIFT}, + {PMIC_AUXADC_JEITA_MIPI_DIS, MT6351_PMIC_AUXADC_JEITA_MIPI_DIS_ADDR, + MT6351_PMIC_AUXADC_JEITA_MIPI_DIS_MASK, MT6351_PMIC_AUXADC_JEITA_MIPI_DIS_SHIFT}, + {PMIC_AUXADC_JEITA_VOLT_HOT, MT6351_PMIC_AUXADC_JEITA_VOLT_HOT_ADDR, + MT6351_PMIC_AUXADC_JEITA_VOLT_HOT_MASK, MT6351_PMIC_AUXADC_JEITA_VOLT_HOT_SHIFT}, + {PMIC_AUXADC_JEITA_HOT_IRQ, MT6351_PMIC_AUXADC_JEITA_HOT_IRQ_ADDR, + MT6351_PMIC_AUXADC_JEITA_HOT_IRQ_MASK, MT6351_PMIC_AUXADC_JEITA_HOT_IRQ_SHIFT}, + {PMIC_AUXADC_JEITA_VOLT_WARM, MT6351_PMIC_AUXADC_JEITA_VOLT_WARM_ADDR, + MT6351_PMIC_AUXADC_JEITA_VOLT_WARM_MASK, MT6351_PMIC_AUXADC_JEITA_VOLT_WARM_SHIFT}, + {PMIC_AUXADC_JEITA_WARM_IRQ, MT6351_PMIC_AUXADC_JEITA_WARM_IRQ_ADDR, + MT6351_PMIC_AUXADC_JEITA_WARM_IRQ_MASK, MT6351_PMIC_AUXADC_JEITA_WARM_IRQ_SHIFT}, + {PMIC_AUXADC_JEITA_VOLT_COOL, MT6351_PMIC_AUXADC_JEITA_VOLT_COOL_ADDR, + MT6351_PMIC_AUXADC_JEITA_VOLT_COOL_MASK, MT6351_PMIC_AUXADC_JEITA_VOLT_COOL_SHIFT}, + {PMIC_AUXADC_JEITA_COOL_IRQ, MT6351_PMIC_AUXADC_JEITA_COOL_IRQ_ADDR, + MT6351_PMIC_AUXADC_JEITA_COOL_IRQ_MASK, MT6351_PMIC_AUXADC_JEITA_COOL_IRQ_SHIFT}, + {PMIC_AUXADC_JEITA_VOLT_COLD, MT6351_PMIC_AUXADC_JEITA_VOLT_COLD_ADDR, + MT6351_PMIC_AUXADC_JEITA_VOLT_COLD_MASK, MT6351_PMIC_AUXADC_JEITA_VOLT_COLD_SHIFT}, + {PMIC_AUXADC_JEITA_COLD_IRQ, MT6351_PMIC_AUXADC_JEITA_COLD_IRQ_ADDR, + MT6351_PMIC_AUXADC_JEITA_COLD_IRQ_MASK, MT6351_PMIC_AUXADC_JEITA_COLD_IRQ_SHIFT}, + {PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD_ADDR, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD_MASK, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COLD_SHIFT}, + {PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL_ADDR, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL_MASK, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_COOL_SHIFT}, + {PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM_ADDR, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM_MASK, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_WARM_SHIFT}, + {PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT_ADDR, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT_MASK, + MT6351_PMIC_AUXADC_JEITA_DEBOUNCE_COUNT_HOT_SHIFT}, + {PMIC_AUXADC_DCXO_MDRT_DET_PRD, MT6351_PMIC_AUXADC_DCXO_MDRT_DET_PRD_ADDR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_PRD_MASK, MT6351_PMIC_AUXADC_DCXO_MDRT_DET_PRD_SHIFT}, + {PMIC_AUXADC_DCXO_MDRT_DET_EN, MT6351_PMIC_AUXADC_DCXO_MDRT_DET_EN_ADDR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_EN_MASK, MT6351_PMIC_AUXADC_DCXO_MDRT_DET_EN_SHIFT}, + {PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_ADDR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_MASK, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CNT_SHIFT}, + {PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_ADDR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_MASK, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_CLR_SHIFT}, + {PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN, MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_ADDR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_MASK, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_EN_SHIFT}, + {PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_ADDR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_MASK, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SEL_SHIFT}, + {PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_ADDR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_MASK, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_WKUP_START_SHIFT}, + {PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_ADDR, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_MASK, + MT6351_PMIC_AUXADC_DCXO_MDRT_DET_SRCLKEN_IND_SHIFT}, + {PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL, MT6351_PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_ADDR, + MT6351_PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_MASK, + MT6351_PMIC_AUXADC_DCXO_CH4_MUX_AP_SEL_SHIFT}, + {PMIC_AUXADC_NAG_EN, MT6351_PMIC_AUXADC_NAG_EN_ADDR, + MT6351_PMIC_AUXADC_NAG_EN_MASK, MT6351_PMIC_AUXADC_NAG_EN_SHIFT}, + {PMIC_AUXADC_NAG_CLR, MT6351_PMIC_AUXADC_NAG_CLR_ADDR, + MT6351_PMIC_AUXADC_NAG_CLR_MASK, MT6351_PMIC_AUXADC_NAG_CLR_SHIFT}, + {PMIC_AUXADC_NAG_VBAT1_SEL, MT6351_PMIC_AUXADC_NAG_VBAT1_SEL_ADDR, + MT6351_PMIC_AUXADC_NAG_VBAT1_SEL_MASK, MT6351_PMIC_AUXADC_NAG_VBAT1_SEL_SHIFT}, + {PMIC_AUXADC_NAG_PRD, MT6351_PMIC_AUXADC_NAG_PRD_ADDR, + MT6351_PMIC_AUXADC_NAG_PRD_MASK, MT6351_PMIC_AUXADC_NAG_PRD_SHIFT}, + {PMIC_AUXADC_NAG_IRQ_EN, MT6351_PMIC_AUXADC_NAG_IRQ_EN_ADDR, + MT6351_PMIC_AUXADC_NAG_IRQ_EN_MASK, MT6351_PMIC_AUXADC_NAG_IRQ_EN_SHIFT}, + {PMIC_AUXADC_NAG_C_DLTV_IRQ, MT6351_PMIC_AUXADC_NAG_C_DLTV_IRQ_ADDR, + MT6351_PMIC_AUXADC_NAG_C_DLTV_IRQ_MASK, MT6351_PMIC_AUXADC_NAG_C_DLTV_IRQ_SHIFT}, + {PMIC_AUXADC_NAG_ZCV, MT6351_PMIC_AUXADC_NAG_ZCV_ADDR, + MT6351_PMIC_AUXADC_NAG_ZCV_MASK, MT6351_PMIC_AUXADC_NAG_ZCV_SHIFT}, + {PMIC_AUXADC_NAG_C_DLTV_TH_15_0, MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_15_0_ADDR, + MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_15_0_MASK, MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_15_0_SHIFT}, + {PMIC_AUXADC_NAG_C_DLTV_TH_26_16, MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_26_16_ADDR, + MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_26_16_MASK, + MT6351_PMIC_AUXADC_NAG_C_DLTV_TH_26_16_SHIFT}, + {PMIC_AUXADC_NAG_CNT_15_0, MT6351_PMIC_AUXADC_NAG_CNT_15_0_ADDR, + MT6351_PMIC_AUXADC_NAG_CNT_15_0_MASK, MT6351_PMIC_AUXADC_NAG_CNT_15_0_SHIFT}, + {PMIC_AUXADC_NAG_CNT_25_16, MT6351_PMIC_AUXADC_NAG_CNT_25_16_ADDR, + MT6351_PMIC_AUXADC_NAG_CNT_25_16_MASK, MT6351_PMIC_AUXADC_NAG_CNT_25_16_SHIFT}, + {PMIC_AUXADC_NAG_DLTV, MT6351_PMIC_AUXADC_NAG_DLTV_ADDR, + MT6351_PMIC_AUXADC_NAG_DLTV_MASK, MT6351_PMIC_AUXADC_NAG_DLTV_SHIFT}, + {PMIC_AUXADC_NAG_C_DLTV_15_0, MT6351_PMIC_AUXADC_NAG_C_DLTV_15_0_ADDR, + MT6351_PMIC_AUXADC_NAG_C_DLTV_15_0_MASK, MT6351_PMIC_AUXADC_NAG_C_DLTV_15_0_SHIFT}, + {PMIC_AUXADC_NAG_C_DLTV_26_16, MT6351_PMIC_AUXADC_NAG_C_DLTV_26_16_ADDR, + MT6351_PMIC_AUXADC_NAG_C_DLTV_26_16_MASK, MT6351_PMIC_AUXADC_NAG_C_DLTV_26_16_SHIFT}, + {PMIC_AD_AUDACCDETCMPOC, MT6351_PMIC_AD_AUDACCDETCMPOC_ADDR, + MT6351_PMIC_AD_AUDACCDETCMPOC_MASK, MT6351_PMIC_AD_AUDACCDETCMPOC_SHIFT}, + {PMIC_RG_AUDACCDETANASWCTRLENB, MT6351_PMIC_RG_AUDACCDETANASWCTRLENB_ADDR, + MT6351_PMIC_RG_AUDACCDETANASWCTRLENB_MASK, MT6351_PMIC_RG_AUDACCDETANASWCTRLENB_SHIFT}, + {PMIC_RG_ACCDETSEL, MT6351_PMIC_RG_ACCDETSEL_ADDR, MT6351_PMIC_RG_ACCDETSEL_MASK, + MT6351_PMIC_RG_ACCDETSEL_SHIFT}, + {PMIC_RG_AUDACCDETSWCTRL, MT6351_PMIC_RG_AUDACCDETSWCTRL_ADDR, + MT6351_PMIC_RG_AUDACCDETSWCTRL_MASK, MT6351_PMIC_RG_AUDACCDETSWCTRL_SHIFT}, + {PMIC_RG_AUDACCDETTVDET, MT6351_PMIC_RG_AUDACCDETTVDET_ADDR, + MT6351_PMIC_RG_AUDACCDETTVDET_MASK, MT6351_PMIC_RG_AUDACCDETTVDET_SHIFT}, + {PMIC_AUDACCDETAUXADCSWCTRL, MT6351_PMIC_AUDACCDETAUXADCSWCTRL_ADDR, + MT6351_PMIC_AUDACCDETAUXADCSWCTRL_MASK, MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SHIFT}, + {PMIC_AUDACCDETAUXADCSWCTRL_SEL, MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SEL_ADDR, + MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SEL_MASK, MT6351_PMIC_AUDACCDETAUXADCSWCTRL_SEL_SHIFT}, + {PMIC_RG_AUDACCDETRSV, MT6351_PMIC_RG_AUDACCDETRSV_ADDR, + MT6351_PMIC_RG_AUDACCDETRSV_MASK, MT6351_PMIC_RG_AUDACCDETRSV_SHIFT}, + {PMIC_ACCDET_EN, MT6351_PMIC_ACCDET_EN_ADDR, MT6351_PMIC_ACCDET_EN_MASK, + MT6351_PMIC_ACCDET_EN_SHIFT}, + {PMIC_ACCDET_SEQ_INIT, MT6351_PMIC_ACCDET_SEQ_INIT_ADDR, + MT6351_PMIC_ACCDET_SEQ_INIT_MASK, MT6351_PMIC_ACCDET_SEQ_INIT_SHIFT}, + {PMIC_ACCDET_EINTDET_EN, MT6351_PMIC_ACCDET_EINTDET_EN_ADDR, + MT6351_PMIC_ACCDET_EINTDET_EN_MASK, MT6351_PMIC_ACCDET_EINTDET_EN_SHIFT}, + {PMIC_ACCDET_EINT_SEQ_INIT, MT6351_PMIC_ACCDET_EINT_SEQ_INIT_ADDR, + MT6351_PMIC_ACCDET_EINT_SEQ_INIT_MASK, MT6351_PMIC_ACCDET_EINT_SEQ_INIT_SHIFT}, + {PMIC_ACCDET_NEGVDET_EN, MT6351_PMIC_ACCDET_NEGVDET_EN_ADDR, + MT6351_PMIC_ACCDET_NEGVDET_EN_MASK, MT6351_PMIC_ACCDET_NEGVDET_EN_SHIFT}, + {PMIC_ACCDET_NEGVDET_EN_CTRL, MT6351_PMIC_ACCDET_NEGVDET_EN_CTRL_ADDR, + MT6351_PMIC_ACCDET_NEGVDET_EN_CTRL_MASK, MT6351_PMIC_ACCDET_NEGVDET_EN_CTRL_SHIFT}, + {PMIC_ACCDET_ANASWCTRL_SEL, MT6351_PMIC_ACCDET_ANASWCTRL_SEL_ADDR, + MT6351_PMIC_ACCDET_ANASWCTRL_SEL_MASK, MT6351_PMIC_ACCDET_ANASWCTRL_SEL_SHIFT}, + {PMIC_ACCDET_CMP_PWM_EN, MT6351_PMIC_ACCDET_CMP_PWM_EN_ADDR, + MT6351_PMIC_ACCDET_CMP_PWM_EN_MASK, MT6351_PMIC_ACCDET_CMP_PWM_EN_SHIFT}, + {PMIC_ACCDET_VTH_PWM_EN, MT6351_PMIC_ACCDET_VTH_PWM_EN_ADDR, + MT6351_PMIC_ACCDET_VTH_PWM_EN_MASK, MT6351_PMIC_ACCDET_VTH_PWM_EN_SHIFT}, + {PMIC_ACCDET_MBIAS_PWM_EN, MT6351_PMIC_ACCDET_MBIAS_PWM_EN_ADDR, + MT6351_PMIC_ACCDET_MBIAS_PWM_EN_MASK, MT6351_PMIC_ACCDET_MBIAS_PWM_EN_SHIFT}, + {PMIC_ACCDET_EINT_PWM_EN, MT6351_PMIC_ACCDET_EINT_PWM_EN_ADDR, + MT6351_PMIC_ACCDET_EINT_PWM_EN_MASK, MT6351_PMIC_ACCDET_EINT_PWM_EN_SHIFT}, + {PMIC_ACCDET_CMP_PWM_IDLE, MT6351_PMIC_ACCDET_CMP_PWM_IDLE_ADDR, + MT6351_PMIC_ACCDET_CMP_PWM_IDLE_MASK, MT6351_PMIC_ACCDET_CMP_PWM_IDLE_SHIFT}, + {PMIC_ACCDET_VTH_PWM_IDLE, MT6351_PMIC_ACCDET_VTH_PWM_IDLE_ADDR, + MT6351_PMIC_ACCDET_VTH_PWM_IDLE_MASK, MT6351_PMIC_ACCDET_VTH_PWM_IDLE_SHIFT}, + {PMIC_ACCDET_MBIAS_PWM_IDLE, MT6351_PMIC_ACCDET_MBIAS_PWM_IDLE_ADDR, + MT6351_PMIC_ACCDET_MBIAS_PWM_IDLE_MASK, MT6351_PMIC_ACCDET_MBIAS_PWM_IDLE_SHIFT}, + {PMIC_ACCDET_EINT_PWM_IDLE, MT6351_PMIC_ACCDET_EINT_PWM_IDLE_ADDR, + MT6351_PMIC_ACCDET_EINT_PWM_IDLE_MASK, MT6351_PMIC_ACCDET_EINT_PWM_IDLE_SHIFT}, + {PMIC_ACCDET_PWM_WIDTH, MT6351_PMIC_ACCDET_PWM_WIDTH_ADDR, + MT6351_PMIC_ACCDET_PWM_WIDTH_MASK, MT6351_PMIC_ACCDET_PWM_WIDTH_SHIFT}, + {PMIC_ACCDET_PWM_THRESH, MT6351_PMIC_ACCDET_PWM_THRESH_ADDR, + MT6351_PMIC_ACCDET_PWM_THRESH_MASK, MT6351_PMIC_ACCDET_PWM_THRESH_SHIFT}, + {PMIC_ACCDET_RISE_DELAY, MT6351_PMIC_ACCDET_RISE_DELAY_ADDR, + MT6351_PMIC_ACCDET_RISE_DELAY_MASK, MT6351_PMIC_ACCDET_RISE_DELAY_SHIFT}, + {PMIC_ACCDET_FALL_DELAY, MT6351_PMIC_ACCDET_FALL_DELAY_ADDR, + MT6351_PMIC_ACCDET_FALL_DELAY_MASK, MT6351_PMIC_ACCDET_FALL_DELAY_SHIFT}, + {PMIC_ACCDET_DEBOUNCE0, MT6351_PMIC_ACCDET_DEBOUNCE0_ADDR, + MT6351_PMIC_ACCDET_DEBOUNCE0_MASK, MT6351_PMIC_ACCDET_DEBOUNCE0_SHIFT}, + {PMIC_ACCDET_DEBOUNCE1, MT6351_PMIC_ACCDET_DEBOUNCE1_ADDR, + MT6351_PMIC_ACCDET_DEBOUNCE1_MASK, MT6351_PMIC_ACCDET_DEBOUNCE1_SHIFT}, + {PMIC_ACCDET_DEBOUNCE2, MT6351_PMIC_ACCDET_DEBOUNCE2_ADDR, + MT6351_PMIC_ACCDET_DEBOUNCE2_MASK, MT6351_PMIC_ACCDET_DEBOUNCE2_SHIFT}, + {PMIC_ACCDET_DEBOUNCE3, MT6351_PMIC_ACCDET_DEBOUNCE3_ADDR, + MT6351_PMIC_ACCDET_DEBOUNCE3_MASK, MT6351_PMIC_ACCDET_DEBOUNCE3_SHIFT}, + {PMIC_ACCDET_DEBOUNCE4, MT6351_PMIC_ACCDET_DEBOUNCE4_ADDR, + MT6351_PMIC_ACCDET_DEBOUNCE4_MASK, MT6351_PMIC_ACCDET_DEBOUNCE4_SHIFT}, + {PMIC_ACCDET_IVAL_CUR_IN, MT6351_PMIC_ACCDET_IVAL_CUR_IN_ADDR, + MT6351_PMIC_ACCDET_IVAL_CUR_IN_MASK, MT6351_PMIC_ACCDET_IVAL_CUR_IN_SHIFT}, + {PMIC_ACCDET_EINT_IVAL_CUR_IN, MT6351_PMIC_ACCDET_EINT_IVAL_CUR_IN_ADDR, + MT6351_PMIC_ACCDET_EINT_IVAL_CUR_IN_MASK, MT6351_PMIC_ACCDET_EINT_IVAL_CUR_IN_SHIFT}, + {PMIC_ACCDET_IVAL_SAM_IN, MT6351_PMIC_ACCDET_IVAL_SAM_IN_ADDR, + MT6351_PMIC_ACCDET_IVAL_SAM_IN_MASK, MT6351_PMIC_ACCDET_IVAL_SAM_IN_SHIFT}, + {PMIC_ACCDET_EINT_IVAL_SAM_IN, MT6351_PMIC_ACCDET_EINT_IVAL_SAM_IN_ADDR, + MT6351_PMIC_ACCDET_EINT_IVAL_SAM_IN_MASK, MT6351_PMIC_ACCDET_EINT_IVAL_SAM_IN_SHIFT}, + {PMIC_ACCDET_IVAL_MEM_IN, MT6351_PMIC_ACCDET_IVAL_MEM_IN_ADDR, + MT6351_PMIC_ACCDET_IVAL_MEM_IN_MASK, MT6351_PMIC_ACCDET_IVAL_MEM_IN_SHIFT}, + {PMIC_ACCDET_EINT_IVAL_MEM_IN, MT6351_PMIC_ACCDET_EINT_IVAL_MEM_IN_ADDR, + MT6351_PMIC_ACCDET_EINT_IVAL_MEM_IN_MASK, MT6351_PMIC_ACCDET_EINT_IVAL_MEM_IN_SHIFT}, + {PMIC_ACCDET_EINT_IVAL_SEL, MT6351_PMIC_ACCDET_EINT_IVAL_SEL_ADDR, + MT6351_PMIC_ACCDET_EINT_IVAL_SEL_MASK, MT6351_PMIC_ACCDET_EINT_IVAL_SEL_SHIFT}, + {PMIC_ACCDET_IVAL_SEL, MT6351_PMIC_ACCDET_IVAL_SEL_ADDR, + MT6351_PMIC_ACCDET_IVAL_SEL_MASK, MT6351_PMIC_ACCDET_IVAL_SEL_SHIFT}, + {PMIC_ACCDET_IRQ, MT6351_PMIC_ACCDET_IRQ_ADDR, MT6351_PMIC_ACCDET_IRQ_MASK, + MT6351_PMIC_ACCDET_IRQ_SHIFT}, + {PMIC_ACCDET_NEGV_IRQ, MT6351_PMIC_ACCDET_NEGV_IRQ_ADDR, + MT6351_PMIC_ACCDET_NEGV_IRQ_MASK, MT6351_PMIC_ACCDET_NEGV_IRQ_SHIFT}, + {PMIC_ACCDET_EINT_IRQ, MT6351_PMIC_ACCDET_EINT_IRQ_ADDR, + MT6351_PMIC_ACCDET_EINT_IRQ_MASK, MT6351_PMIC_ACCDET_EINT_IRQ_SHIFT}, + {PMIC_ACCDET_IRQ_CLR, MT6351_PMIC_ACCDET_IRQ_CLR_ADDR, + MT6351_PMIC_ACCDET_IRQ_CLR_MASK, MT6351_PMIC_ACCDET_IRQ_CLR_SHIFT}, + {PMIC_ACCDET_NEGV_IRQ_CLR, MT6351_PMIC_ACCDET_NEGV_IRQ_CLR_ADDR, + MT6351_PMIC_ACCDET_NEGV_IRQ_CLR_MASK, MT6351_PMIC_ACCDET_NEGV_IRQ_CLR_SHIFT}, + {PMIC_ACCDET_EINT_IRQ_CLR, MT6351_PMIC_ACCDET_EINT_IRQ_CLR_ADDR, + MT6351_PMIC_ACCDET_EINT_IRQ_CLR_MASK, MT6351_PMIC_ACCDET_EINT_IRQ_CLR_SHIFT}, + {PMIC_ACCDET_EINT_IRQ_POLARITY, MT6351_PMIC_ACCDET_EINT_IRQ_POLARITY_ADDR, + MT6351_PMIC_ACCDET_EINT_IRQ_POLARITY_MASK, MT6351_PMIC_ACCDET_EINT_IRQ_POLARITY_SHIFT}, + {PMIC_ACCDET_TEST_MODE0, MT6351_PMIC_ACCDET_TEST_MODE0_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE0_MASK, MT6351_PMIC_ACCDET_TEST_MODE0_SHIFT}, + {PMIC_ACCDET_TEST_MODE1, MT6351_PMIC_ACCDET_TEST_MODE1_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE1_MASK, MT6351_PMIC_ACCDET_TEST_MODE1_SHIFT}, + {PMIC_ACCDET_TEST_MODE2, MT6351_PMIC_ACCDET_TEST_MODE2_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE2_MASK, MT6351_PMIC_ACCDET_TEST_MODE2_SHIFT}, + {PMIC_ACCDET_TEST_MODE3, MT6351_PMIC_ACCDET_TEST_MODE3_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE3_MASK, MT6351_PMIC_ACCDET_TEST_MODE3_SHIFT}, + {PMIC_ACCDET_TEST_MODE4, MT6351_PMIC_ACCDET_TEST_MODE4_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE4_MASK, MT6351_PMIC_ACCDET_TEST_MODE4_SHIFT}, + {PMIC_ACCDET_TEST_MODE5, MT6351_PMIC_ACCDET_TEST_MODE5_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE5_MASK, MT6351_PMIC_ACCDET_TEST_MODE5_SHIFT}, + {PMIC_ACCDET_PWM_SEL, MT6351_PMIC_ACCDET_PWM_SEL_ADDR, + MT6351_PMIC_ACCDET_PWM_SEL_MASK, MT6351_PMIC_ACCDET_PWM_SEL_SHIFT}, + {PMIC_ACCDET_IN_SW, MT6351_PMIC_ACCDET_IN_SW_ADDR, MT6351_PMIC_ACCDET_IN_SW_MASK, + MT6351_PMIC_ACCDET_IN_SW_SHIFT}, + {PMIC_ACCDET_CMP_EN_SW, MT6351_PMIC_ACCDET_CMP_EN_SW_ADDR, + MT6351_PMIC_ACCDET_CMP_EN_SW_MASK, MT6351_PMIC_ACCDET_CMP_EN_SW_SHIFT}, + {PMIC_ACCDET_VTH_EN_SW, MT6351_PMIC_ACCDET_VTH_EN_SW_ADDR, + MT6351_PMIC_ACCDET_VTH_EN_SW_MASK, MT6351_PMIC_ACCDET_VTH_EN_SW_SHIFT}, + {PMIC_ACCDET_MBIAS_EN_SW, MT6351_PMIC_ACCDET_MBIAS_EN_SW_ADDR, + MT6351_PMIC_ACCDET_MBIAS_EN_SW_MASK, MT6351_PMIC_ACCDET_MBIAS_EN_SW_SHIFT}, + {PMIC_ACCDET_PWM_EN_SW, MT6351_PMIC_ACCDET_PWM_EN_SW_ADDR, + MT6351_PMIC_ACCDET_PWM_EN_SW_MASK, MT6351_PMIC_ACCDET_PWM_EN_SW_SHIFT}, + {PMIC_ACCDET_IN, MT6351_PMIC_ACCDET_IN_ADDR, MT6351_PMIC_ACCDET_IN_MASK, + MT6351_PMIC_ACCDET_IN_SHIFT}, + {PMIC_ACCDET_CUR_IN, MT6351_PMIC_ACCDET_CUR_IN_ADDR, + MT6351_PMIC_ACCDET_CUR_IN_MASK, MT6351_PMIC_ACCDET_CUR_IN_SHIFT}, + {PMIC_ACCDET_SAM_IN, MT6351_PMIC_ACCDET_SAM_IN_ADDR, + MT6351_PMIC_ACCDET_SAM_IN_MASK, MT6351_PMIC_ACCDET_SAM_IN_SHIFT}, + {PMIC_ACCDET_MEM_IN, MT6351_PMIC_ACCDET_MEM_IN_ADDR, + MT6351_PMIC_ACCDET_MEM_IN_MASK, MT6351_PMIC_ACCDET_MEM_IN_SHIFT}, + {PMIC_ACCDET_STATE, MT6351_PMIC_ACCDET_STATE_ADDR, MT6351_PMIC_ACCDET_STATE_MASK, + MT6351_PMIC_ACCDET_STATE_SHIFT}, + {PMIC_ACCDET_MBIAS_CLK, MT6351_PMIC_ACCDET_MBIAS_CLK_ADDR, + MT6351_PMIC_ACCDET_MBIAS_CLK_MASK, MT6351_PMIC_ACCDET_MBIAS_CLK_SHIFT}, + {PMIC_ACCDET_VTH_CLK, MT6351_PMIC_ACCDET_VTH_CLK_ADDR, + MT6351_PMIC_ACCDET_VTH_CLK_MASK, MT6351_PMIC_ACCDET_VTH_CLK_SHIFT}, + {PMIC_ACCDET_CMP_CLK, MT6351_PMIC_ACCDET_CMP_CLK_ADDR, + MT6351_PMIC_ACCDET_CMP_CLK_MASK, MT6351_PMIC_ACCDET_CMP_CLK_SHIFT}, + {PMIC_DA_NI_AUDACCDETAUXADCSWCTRL, MT6351_PMIC_DA_NI_AUDACCDETAUXADCSWCTRL_ADDR, + MT6351_PMIC_DA_NI_AUDACCDETAUXADCSWCTRL_MASK, + MT6351_PMIC_DA_NI_AUDACCDETAUXADCSWCTRL_SHIFT}, + {PMIC_ACCDET_EINT_DEB_SEL, MT6351_PMIC_ACCDET_EINT_DEB_SEL_ADDR, + MT6351_PMIC_ACCDET_EINT_DEB_SEL_MASK, MT6351_PMIC_ACCDET_EINT_DEB_SEL_SHIFT}, + {PMIC_ACCDET_EINT_DEBOUNCE, MT6351_PMIC_ACCDET_EINT_DEBOUNCE_ADDR, + MT6351_PMIC_ACCDET_EINT_DEBOUNCE_MASK, MT6351_PMIC_ACCDET_EINT_DEBOUNCE_SHIFT}, + {PMIC_ACCDET_EINT_PWM_THRESH, MT6351_PMIC_ACCDET_EINT_PWM_THRESH_ADDR, + MT6351_PMIC_ACCDET_EINT_PWM_THRESH_MASK, MT6351_PMIC_ACCDET_EINT_PWM_THRESH_SHIFT}, + {PMIC_ACCDET_EINT_PWM_WIDTH, MT6351_PMIC_ACCDET_EINT_PWM_WIDTH_ADDR, + MT6351_PMIC_ACCDET_EINT_PWM_WIDTH_MASK, MT6351_PMIC_ACCDET_EINT_PWM_WIDTH_SHIFT}, + {PMIC_ACCDET_NEGV_THRESH, MT6351_PMIC_ACCDET_NEGV_THRESH_ADDR, + MT6351_PMIC_ACCDET_NEGV_THRESH_MASK, MT6351_PMIC_ACCDET_NEGV_THRESH_SHIFT}, + {PMIC_ACCDET_EINT_PWM_FALL_DELAY, MT6351_PMIC_ACCDET_EINT_PWM_FALL_DELAY_ADDR, + MT6351_PMIC_ACCDET_EINT_PWM_FALL_DELAY_MASK, + MT6351_PMIC_ACCDET_EINT_PWM_FALL_DELAY_SHIFT}, + {PMIC_ACCDET_EINT_PWM_RISE_DELAY, MT6351_PMIC_ACCDET_EINT_PWM_RISE_DELAY_ADDR, + MT6351_PMIC_ACCDET_EINT_PWM_RISE_DELAY_MASK, + MT6351_PMIC_ACCDET_EINT_PWM_RISE_DELAY_SHIFT}, + {PMIC_ACCDET_TEST_MODE13, MT6351_PMIC_ACCDET_TEST_MODE13_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE13_MASK, MT6351_PMIC_ACCDET_TEST_MODE13_SHIFT}, + {PMIC_ACCDET_TEST_MODE12, MT6351_PMIC_ACCDET_TEST_MODE12_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE12_MASK, MT6351_PMIC_ACCDET_TEST_MODE12_SHIFT}, + {PMIC_ACCDET_NVDETECTOUT_SW, MT6351_PMIC_ACCDET_NVDETECTOUT_SW_ADDR, + MT6351_PMIC_ACCDET_NVDETECTOUT_SW_MASK, MT6351_PMIC_ACCDET_NVDETECTOUT_SW_SHIFT}, + {PMIC_ACCDET_TEST_MODE11, MT6351_PMIC_ACCDET_TEST_MODE11_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE11_MASK, MT6351_PMIC_ACCDET_TEST_MODE11_SHIFT}, + {PMIC_ACCDET_TEST_MODE10, MT6351_PMIC_ACCDET_TEST_MODE10_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE10_MASK, MT6351_PMIC_ACCDET_TEST_MODE10_SHIFT}, + {PMIC_ACCDET_EINTCMPOUT_SW, MT6351_PMIC_ACCDET_EINTCMPOUT_SW_ADDR, + MT6351_PMIC_ACCDET_EINTCMPOUT_SW_MASK, MT6351_PMIC_ACCDET_EINTCMPOUT_SW_SHIFT}, + {PMIC_ACCDET_TEST_MODE9, MT6351_PMIC_ACCDET_TEST_MODE9_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE9_MASK, MT6351_PMIC_ACCDET_TEST_MODE9_SHIFT}, + {PMIC_ACCDET_TEST_MODE8, MT6351_PMIC_ACCDET_TEST_MODE8_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE8_MASK, MT6351_PMIC_ACCDET_TEST_MODE8_SHIFT}, + {PMIC_ACCDET_AUXADC_CTRL_SW, MT6351_PMIC_ACCDET_AUXADC_CTRL_SW_ADDR, + MT6351_PMIC_ACCDET_AUXADC_CTRL_SW_MASK, MT6351_PMIC_ACCDET_AUXADC_CTRL_SW_SHIFT}, + {PMIC_ACCDET_TEST_MODE7, MT6351_PMIC_ACCDET_TEST_MODE7_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE7_MASK, MT6351_PMIC_ACCDET_TEST_MODE7_SHIFT}, + {PMIC_ACCDET_TEST_MODE6, MT6351_PMIC_ACCDET_TEST_MODE6_ADDR, + MT6351_PMIC_ACCDET_TEST_MODE6_MASK, MT6351_PMIC_ACCDET_TEST_MODE6_SHIFT}, + {PMIC_ACCDET_EINTCMP_EN_SW, MT6351_PMIC_ACCDET_EINTCMP_EN_SW_ADDR, + MT6351_PMIC_ACCDET_EINTCMP_EN_SW_MASK, MT6351_PMIC_ACCDET_EINTCMP_EN_SW_SHIFT}, + {PMIC_ACCDET_EINT_STATE, MT6351_PMIC_ACCDET_EINT_STATE_ADDR, + MT6351_PMIC_ACCDET_EINT_STATE_MASK, MT6351_PMIC_ACCDET_EINT_STATE_SHIFT}, + {PMIC_ACCDET_AUXADC_DEBOUNCE_END, MT6351_PMIC_ACCDET_AUXADC_DEBOUNCE_END_ADDR, + MT6351_PMIC_ACCDET_AUXADC_DEBOUNCE_END_MASK, + MT6351_PMIC_ACCDET_AUXADC_DEBOUNCE_END_SHIFT}, + {PMIC_ACCDET_AUXADC_CONNECT_PRE, MT6351_PMIC_ACCDET_AUXADC_CONNECT_PRE_ADDR, + MT6351_PMIC_ACCDET_AUXADC_CONNECT_PRE_MASK, MT6351_PMIC_ACCDET_AUXADC_CONNECT_PRE_SHIFT}, + {PMIC_ACCDET_EINT_CUR_IN, MT6351_PMIC_ACCDET_EINT_CUR_IN_ADDR, + MT6351_PMIC_ACCDET_EINT_CUR_IN_MASK, MT6351_PMIC_ACCDET_EINT_CUR_IN_SHIFT}, + {PMIC_ACCDET_EINT_SAM_IN, MT6351_PMIC_ACCDET_EINT_SAM_IN_ADDR, + MT6351_PMIC_ACCDET_EINT_SAM_IN_MASK, MT6351_PMIC_ACCDET_EINT_SAM_IN_SHIFT}, + {PMIC_ACCDET_EINT_MEM_IN, MT6351_PMIC_ACCDET_EINT_MEM_IN_ADDR, + MT6351_PMIC_ACCDET_EINT_MEM_IN_MASK, MT6351_PMIC_ACCDET_EINT_MEM_IN_SHIFT}, + {PMIC_AD_NVDETECTOUT, MT6351_PMIC_AD_NVDETECTOUT_ADDR, + MT6351_PMIC_AD_NVDETECTOUT_MASK, MT6351_PMIC_AD_NVDETECTOUT_SHIFT}, + {PMIC_AD_EINTCMPOUT, MT6351_PMIC_AD_EINTCMPOUT_ADDR, + MT6351_PMIC_AD_EINTCMPOUT_MASK, MT6351_PMIC_AD_EINTCMPOUT_SHIFT}, + {PMIC_DA_NI_EINTCMPEN, MT6351_PMIC_DA_NI_EINTCMPEN_ADDR, + MT6351_PMIC_DA_NI_EINTCMPEN_MASK, MT6351_PMIC_DA_NI_EINTCMPEN_SHIFT}, + {PMIC_ACCDET_NEGV_COUNT_IN, MT6351_PMIC_ACCDET_NEGV_COUNT_IN_ADDR, + MT6351_PMIC_ACCDET_NEGV_COUNT_IN_MASK, MT6351_PMIC_ACCDET_NEGV_COUNT_IN_SHIFT}, + {PMIC_ACCDET_NEGV_EN_FINAL, MT6351_PMIC_ACCDET_NEGV_EN_FINAL_ADDR, + MT6351_PMIC_ACCDET_NEGV_EN_FINAL_MASK, MT6351_PMIC_ACCDET_NEGV_EN_FINAL_SHIFT}, + {PMIC_ACCDET_NEGV_COUNT_END, MT6351_PMIC_ACCDET_NEGV_COUNT_END_ADDR, + MT6351_PMIC_ACCDET_NEGV_COUNT_END_MASK, MT6351_PMIC_ACCDET_NEGV_COUNT_END_SHIFT}, + {PMIC_ACCDET_NEGV_MINU, MT6351_PMIC_ACCDET_NEGV_MINU_ADDR, + MT6351_PMIC_ACCDET_NEGV_MINU_MASK, MT6351_PMIC_ACCDET_NEGV_MINU_SHIFT}, + {PMIC_ACCDET_NEGV_ADD, MT6351_PMIC_ACCDET_NEGV_ADD_ADDR, + MT6351_PMIC_ACCDET_NEGV_ADD_MASK, MT6351_PMIC_ACCDET_NEGV_ADD_SHIFT}, + {PMIC_ACCDET_NEGV_CMP, MT6351_PMIC_ACCDET_NEGV_CMP_ADDR, + MT6351_PMIC_ACCDET_NEGV_CMP_MASK, MT6351_PMIC_ACCDET_NEGV_CMP_SHIFT}, + {PMIC_ACCDET_CUR_DEB, MT6351_PMIC_ACCDET_CUR_DEB_ADDR, + MT6351_PMIC_ACCDET_CUR_DEB_MASK, MT6351_PMIC_ACCDET_CUR_DEB_SHIFT}, + {PMIC_ACCDET_EINT_CUR_DEB, MT6351_PMIC_ACCDET_EINT_CUR_DEB_ADDR, + MT6351_PMIC_ACCDET_EINT_CUR_DEB_MASK, MT6351_PMIC_ACCDET_EINT_CUR_DEB_SHIFT}, + {PMIC_ACCDET_RSV_CON0, MT6351_PMIC_ACCDET_RSV_CON0_ADDR, + MT6351_PMIC_ACCDET_RSV_CON0_MASK, MT6351_PMIC_ACCDET_RSV_CON0_SHIFT}, + {PMIC_ACCDET_RSV_CON1, MT6351_PMIC_ACCDET_RSV_CON1_ADDR, + MT6351_PMIC_ACCDET_RSV_CON1_MASK, MT6351_PMIC_ACCDET_RSV_CON1_SHIFT}, + {PMIC_ACCDET_AUXADC_CONNECT_TIME, MT6351_PMIC_ACCDET_AUXADC_CONNECT_TIME_ADDR, + MT6351_PMIC_ACCDET_AUXADC_CONNECT_TIME_MASK, + MT6351_PMIC_ACCDET_AUXADC_CONNECT_TIME_SHIFT}, + {PMIC_RG_VCDT_HV_EN, MT6351_PMIC_RG_VCDT_HV_EN_ADDR, + MT6351_PMIC_RG_VCDT_HV_EN_MASK, MT6351_PMIC_RG_VCDT_HV_EN_SHIFT}, + {PMIC_RGS_CHR_LDO_DET, MT6351_PMIC_RGS_CHR_LDO_DET_ADDR, + MT6351_PMIC_RGS_CHR_LDO_DET_MASK, MT6351_PMIC_RGS_CHR_LDO_DET_SHIFT}, + {PMIC_RG_PCHR_AUTOMODE, MT6351_PMIC_RG_PCHR_AUTOMODE_ADDR, + MT6351_PMIC_RG_PCHR_AUTOMODE_MASK, MT6351_PMIC_RG_PCHR_AUTOMODE_SHIFT}, + {PMIC_RG_CSDAC_EN, MT6351_PMIC_RG_CSDAC_EN_ADDR, MT6351_PMIC_RG_CSDAC_EN_MASK, + MT6351_PMIC_RG_CSDAC_EN_SHIFT}, + {PMIC_RG_NORM_CHR_EN, MT6351_PMIC_RG_NORM_CHR_EN_ADDR, + MT6351_PMIC_RG_NORM_CHR_EN_MASK, MT6351_PMIC_RG_NORM_CHR_EN_SHIFT}, + {PMIC_RGS_CHRDET, MT6351_PMIC_RGS_CHRDET_ADDR, MT6351_PMIC_RGS_CHRDET_MASK, + MT6351_PMIC_RGS_CHRDET_SHIFT}, + {PMIC_RGS_VCDT_LV_DET, MT6351_PMIC_RGS_VCDT_LV_DET_ADDR, + MT6351_PMIC_RGS_VCDT_LV_DET_MASK, MT6351_PMIC_RGS_VCDT_LV_DET_SHIFT}, + {PMIC_RGS_VCDT_HV_DET, MT6351_PMIC_RGS_VCDT_HV_DET_ADDR, + MT6351_PMIC_RGS_VCDT_HV_DET_MASK, MT6351_PMIC_RGS_VCDT_HV_DET_SHIFT}, + {PMIC_RG_VCDT_LV_VTH, MT6351_PMIC_RG_VCDT_LV_VTH_ADDR, + MT6351_PMIC_RG_VCDT_LV_VTH_MASK, MT6351_PMIC_RG_VCDT_LV_VTH_SHIFT}, + {PMIC_RG_VCDT_HV_VTH, MT6351_PMIC_RG_VCDT_HV_VTH_ADDR, + MT6351_PMIC_RG_VCDT_HV_VTH_MASK, MT6351_PMIC_RG_VCDT_HV_VTH_SHIFT}, + {PMIC_RG_VBAT_CV_EN, MT6351_PMIC_RG_VBAT_CV_EN_ADDR, + MT6351_PMIC_RG_VBAT_CV_EN_MASK, MT6351_PMIC_RG_VBAT_CV_EN_SHIFT}, + {PMIC_RG_VBAT_CC_EN, MT6351_PMIC_RG_VBAT_CC_EN_ADDR, + MT6351_PMIC_RG_VBAT_CC_EN_MASK, MT6351_PMIC_RG_VBAT_CC_EN_SHIFT}, + {PMIC_RG_CS_EN, MT6351_PMIC_RG_CS_EN_ADDR, MT6351_PMIC_RG_CS_EN_MASK, + MT6351_PMIC_RG_CS_EN_SHIFT}, + {PMIC_RGS_CS_DET, MT6351_PMIC_RGS_CS_DET_ADDR, MT6351_PMIC_RGS_CS_DET_MASK, + MT6351_PMIC_RGS_CS_DET_SHIFT}, + {PMIC_RGS_VBAT_CV_DET, MT6351_PMIC_RGS_VBAT_CV_DET_ADDR, + MT6351_PMIC_RGS_VBAT_CV_DET_MASK, MT6351_PMIC_RGS_VBAT_CV_DET_SHIFT}, + {PMIC_RGS_VBAT_CC_DET, MT6351_PMIC_RGS_VBAT_CC_DET_ADDR, + MT6351_PMIC_RGS_VBAT_CC_DET_MASK, MT6351_PMIC_RGS_VBAT_CC_DET_SHIFT}, + {PMIC_RG_VBAT_NORM_CV_VTH, MT6351_PMIC_RG_VBAT_NORM_CV_VTH_ADDR, + MT6351_PMIC_RG_VBAT_NORM_CV_VTH_MASK, MT6351_PMIC_RG_VBAT_NORM_CV_VTH_SHIFT}, + {PMIC_RG_VBAT_CC_VTH, MT6351_PMIC_RG_VBAT_CC_VTH_ADDR, + MT6351_PMIC_RG_VBAT_CC_VTH_MASK, MT6351_PMIC_RG_VBAT_CC_VTH_SHIFT}, + {PMIC_RG_NORM_CS_VTH, MT6351_PMIC_RG_NORM_CS_VTH_ADDR, + MT6351_PMIC_RG_NORM_CS_VTH_MASK, MT6351_PMIC_RG_NORM_CS_VTH_SHIFT}, + {PMIC_RG_PCHR_TOHTC, MT6351_PMIC_RG_PCHR_TOHTC_ADDR, + MT6351_PMIC_RG_PCHR_TOHTC_MASK, MT6351_PMIC_RG_PCHR_TOHTC_SHIFT}, + {PMIC_RG_PCHR_TOLTC, MT6351_PMIC_RG_PCHR_TOLTC_ADDR, + MT6351_PMIC_RG_PCHR_TOLTC_MASK, MT6351_PMIC_RG_PCHR_TOLTC_SHIFT}, + {PMIC_RG_VBAT_OV_EN, MT6351_PMIC_RG_VBAT_OV_EN_ADDR, + MT6351_PMIC_RG_VBAT_OV_EN_MASK, MT6351_PMIC_RG_VBAT_OV_EN_SHIFT}, + {PMIC_RG_VBAT_OV_VTH, MT6351_PMIC_RG_VBAT_OV_VTH_ADDR, + MT6351_PMIC_RG_VBAT_OV_VTH_MASK, MT6351_PMIC_RG_VBAT_OV_VTH_SHIFT}, + {PMIC_RG_VBAT_OV_DEG, MT6351_PMIC_RG_VBAT_OV_DEG_ADDR, + MT6351_PMIC_RG_VBAT_OV_DEG_MASK, MT6351_PMIC_RG_VBAT_OV_DEG_SHIFT}, + {PMIC_RGS_VBAT_OV_DET, MT6351_PMIC_RGS_VBAT_OV_DET_ADDR, + MT6351_PMIC_RGS_VBAT_OV_DET_MASK, MT6351_PMIC_RGS_VBAT_OV_DET_SHIFT}, + {PMIC_RG_BATON_EN, MT6351_PMIC_RG_BATON_EN_ADDR, MT6351_PMIC_RG_BATON_EN_MASK, + MT6351_PMIC_RG_BATON_EN_SHIFT}, + {PMIC_RG_BATON_HT_EN_RSV0, MT6351_PMIC_RG_BATON_HT_EN_RSV0_ADDR, + MT6351_PMIC_RG_BATON_HT_EN_RSV0_MASK, MT6351_PMIC_RG_BATON_HT_EN_RSV0_SHIFT}, + {PMIC_BATON_TDET_EN, MT6351_PMIC_BATON_TDET_EN_ADDR, + MT6351_PMIC_BATON_TDET_EN_MASK, MT6351_PMIC_BATON_TDET_EN_SHIFT}, + {PMIC_RG_BATON_HT_TRIM, MT6351_PMIC_RG_BATON_HT_TRIM_ADDR, + MT6351_PMIC_RG_BATON_HT_TRIM_MASK, MT6351_PMIC_RG_BATON_HT_TRIM_SHIFT}, + {PMIC_RG_BATON_HT_TRIM_SET, MT6351_PMIC_RG_BATON_HT_TRIM_SET_ADDR, + MT6351_PMIC_RG_BATON_HT_TRIM_SET_MASK, MT6351_PMIC_RG_BATON_HT_TRIM_SET_SHIFT}, + {PMIC_RG_BATON_TDET_EN, MT6351_PMIC_RG_BATON_TDET_EN_ADDR, + MT6351_PMIC_RG_BATON_TDET_EN_MASK, MT6351_PMIC_RG_BATON_TDET_EN_SHIFT}, + {PMIC_RG_CSDAC_DATA, MT6351_PMIC_RG_CSDAC_DATA_ADDR, + MT6351_PMIC_RG_CSDAC_DATA_MASK, MT6351_PMIC_RG_CSDAC_DATA_SHIFT}, + {PMIC_RG_FRC_CSVTH_USBDL, MT6351_PMIC_RG_FRC_CSVTH_USBDL_ADDR, + MT6351_PMIC_RG_FRC_CSVTH_USBDL_MASK, MT6351_PMIC_RG_FRC_CSVTH_USBDL_SHIFT}, + {PMIC_RGS_PCHR_FLAG_OUT, MT6351_PMIC_RGS_PCHR_FLAG_OUT_ADDR, + MT6351_PMIC_RGS_PCHR_FLAG_OUT_MASK, MT6351_PMIC_RGS_PCHR_FLAG_OUT_SHIFT}, + {PMIC_RG_PCHR_FLAG_EN, MT6351_PMIC_RG_PCHR_FLAG_EN_ADDR, + MT6351_PMIC_RG_PCHR_FLAG_EN_MASK, MT6351_PMIC_RG_PCHR_FLAG_EN_SHIFT}, + {PMIC_RG_OTG_BVALID_EN, MT6351_PMIC_RG_OTG_BVALID_EN_ADDR, + MT6351_PMIC_RG_OTG_BVALID_EN_MASK, MT6351_PMIC_RG_OTG_BVALID_EN_SHIFT}, + {PMIC_RGS_OTG_BVALID_DET, MT6351_PMIC_RGS_OTG_BVALID_DET_ADDR, + MT6351_PMIC_RGS_OTG_BVALID_DET_MASK, MT6351_PMIC_RGS_OTG_BVALID_DET_SHIFT}, + {PMIC_RG_PCHR_FLAG_SEL, MT6351_PMIC_RG_PCHR_FLAG_SEL_ADDR, + MT6351_PMIC_RG_PCHR_FLAG_SEL_MASK, MT6351_PMIC_RG_PCHR_FLAG_SEL_SHIFT}, + {PMIC_RG_PCHR_TESTMODE, MT6351_PMIC_RG_PCHR_TESTMODE_ADDR, + MT6351_PMIC_RG_PCHR_TESTMODE_MASK, MT6351_PMIC_RG_PCHR_TESTMODE_SHIFT}, + {PMIC_RG_CSDAC_TESTMODE, MT6351_PMIC_RG_CSDAC_TESTMODE_ADDR, + MT6351_PMIC_RG_CSDAC_TESTMODE_MASK, MT6351_PMIC_RG_CSDAC_TESTMODE_SHIFT}, + {PMIC_RG_PCHR_RST, MT6351_PMIC_RG_PCHR_RST_ADDR, MT6351_PMIC_RG_PCHR_RST_MASK, + MT6351_PMIC_RG_PCHR_RST_SHIFT}, + {PMIC_RG_PCHR_FT_CTRL, MT6351_PMIC_RG_PCHR_FT_CTRL_ADDR, + MT6351_PMIC_RG_PCHR_FT_CTRL_MASK, MT6351_PMIC_RG_PCHR_FT_CTRL_SHIFT}, + {PMIC_RG_CHRWDT_TD, MT6351_PMIC_RG_CHRWDT_TD_ADDR, MT6351_PMIC_RG_CHRWDT_TD_MASK, + MT6351_PMIC_RG_CHRWDT_TD_SHIFT}, + {PMIC_RG_CHRWDT_EN, MT6351_PMIC_RG_CHRWDT_EN_ADDR, MT6351_PMIC_RG_CHRWDT_EN_MASK, + MT6351_PMIC_RG_CHRWDT_EN_SHIFT}, + {PMIC_RG_CHRWDT_WR, MT6351_PMIC_RG_CHRWDT_WR_ADDR, MT6351_PMIC_RG_CHRWDT_WR_MASK, + MT6351_PMIC_RG_CHRWDT_WR_SHIFT}, + {PMIC_RG_PCHR_RV, MT6351_PMIC_RG_PCHR_RV_ADDR, MT6351_PMIC_RG_PCHR_RV_MASK, + MT6351_PMIC_RG_PCHR_RV_SHIFT}, + {PMIC_RG_CHRWDT_INT_EN, MT6351_PMIC_RG_CHRWDT_INT_EN_ADDR, + MT6351_PMIC_RG_CHRWDT_INT_EN_MASK, MT6351_PMIC_RG_CHRWDT_INT_EN_SHIFT}, + {PMIC_RG_CHRWDT_FLAG_WR, MT6351_PMIC_RG_CHRWDT_FLAG_WR_ADDR, + MT6351_PMIC_RG_CHRWDT_FLAG_WR_MASK, MT6351_PMIC_RG_CHRWDT_FLAG_WR_SHIFT}, + {PMIC_RGS_CHRWDT_OUT, MT6351_PMIC_RGS_CHRWDT_OUT_ADDR, + MT6351_PMIC_RGS_CHRWDT_OUT_MASK, MT6351_PMIC_RGS_CHRWDT_OUT_SHIFT}, + {PMIC_RG_USBDL_RST, MT6351_PMIC_RG_USBDL_RST_ADDR, MT6351_PMIC_RG_USBDL_RST_MASK, + MT6351_PMIC_RG_USBDL_RST_SHIFT}, + {PMIC_RG_USBDL_SET, MT6351_PMIC_RG_USBDL_SET_ADDR, MT6351_PMIC_RG_USBDL_SET_MASK, + MT6351_PMIC_RG_USBDL_SET_SHIFT}, + {PMIC_RG_ADCIN_VSEN_MUX_EN, MT6351_PMIC_RG_ADCIN_VSEN_MUX_EN_ADDR, + MT6351_PMIC_RG_ADCIN_VSEN_MUX_EN_MASK, MT6351_PMIC_RG_ADCIN_VSEN_MUX_EN_SHIFT}, + {PMIC_RG_ADCIN_VSEN_EXT_BATON_EN, MT6351_PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_ADDR, + MT6351_PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_MASK, + MT6351_PMIC_RG_ADCIN_VSEN_EXT_BATON_EN_SHIFT}, + {PMIC_RG_ADCIN_VBAT_EN, MT6351_PMIC_RG_ADCIN_VBAT_EN_ADDR, + MT6351_PMIC_RG_ADCIN_VBAT_EN_MASK, MT6351_PMIC_RG_ADCIN_VBAT_EN_SHIFT}, + {PMIC_RG_ADCIN_VSEN_EN, MT6351_PMIC_RG_ADCIN_VSEN_EN_ADDR, + MT6351_PMIC_RG_ADCIN_VSEN_EN_MASK, MT6351_PMIC_RG_ADCIN_VSEN_EN_SHIFT}, + {PMIC_RG_ADCIN_CHR_EN, MT6351_PMIC_RG_ADCIN_CHR_EN_ADDR, + MT6351_PMIC_RG_ADCIN_CHR_EN_MASK, MT6351_PMIC_RG_ADCIN_CHR_EN_SHIFT}, + {PMIC_RG_UVLO_VTHL, MT6351_PMIC_RG_UVLO_VTHL_ADDR, MT6351_PMIC_RG_UVLO_VTHL_MASK, + MT6351_PMIC_RG_UVLO_VTHL_SHIFT}, + {PMIC_RG_UVLO_VH_LAT, MT6351_PMIC_RG_UVLO_VH_LAT_ADDR, + MT6351_PMIC_RG_UVLO_VH_LAT_MASK, MT6351_PMIC_RG_UVLO_VH_LAT_SHIFT}, + {PMIC_RG_LBAT_INT_VTH, MT6351_PMIC_RG_LBAT_INT_VTH_ADDR, + MT6351_PMIC_RG_LBAT_INT_VTH_MASK, MT6351_PMIC_RG_LBAT_INT_VTH_SHIFT}, + {PMIC_RG_BGR_RSEL, MT6351_PMIC_RG_BGR_RSEL_ADDR, MT6351_PMIC_RG_BGR_RSEL_MASK, + MT6351_PMIC_RG_BGR_RSEL_SHIFT}, + {PMIC_RG_BGR_UNCHOP_PH, MT6351_PMIC_RG_BGR_UNCHOP_PH_ADDR, + MT6351_PMIC_RG_BGR_UNCHOP_PH_MASK, MT6351_PMIC_RG_BGR_UNCHOP_PH_SHIFT}, + {PMIC_RG_BGR_UNCHOP, MT6351_PMIC_RG_BGR_UNCHOP_ADDR, + MT6351_PMIC_RG_BGR_UNCHOP_MASK, MT6351_PMIC_RG_BGR_UNCHOP_SHIFT}, + {PMIC_RG_BC11_BB_CTRL, MT6351_PMIC_RG_BC11_BB_CTRL_ADDR, + MT6351_PMIC_RG_BC11_BB_CTRL_MASK, MT6351_PMIC_RG_BC11_BB_CTRL_SHIFT}, + {PMIC_RG_BC11_RST, MT6351_PMIC_RG_BC11_RST_ADDR, MT6351_PMIC_RG_BC11_RST_MASK, + MT6351_PMIC_RG_BC11_RST_SHIFT}, + {PMIC_RG_BC11_VSRC_EN, MT6351_PMIC_RG_BC11_VSRC_EN_ADDR, + MT6351_PMIC_RG_BC11_VSRC_EN_MASK, MT6351_PMIC_RG_BC11_VSRC_EN_SHIFT}, + {PMIC_RGS_BC11_CMP_OUT, MT6351_PMIC_RGS_BC11_CMP_OUT_ADDR, + MT6351_PMIC_RGS_BC11_CMP_OUT_MASK, MT6351_PMIC_RGS_BC11_CMP_OUT_SHIFT}, + {PMIC_RG_BC11_VREF_VTH, MT6351_PMIC_RG_BC11_VREF_VTH_ADDR, + MT6351_PMIC_RG_BC11_VREF_VTH_MASK, MT6351_PMIC_RG_BC11_VREF_VTH_SHIFT}, + {PMIC_RG_BC11_CMP_EN, MT6351_PMIC_RG_BC11_CMP_EN_ADDR, + MT6351_PMIC_RG_BC11_CMP_EN_MASK, MT6351_PMIC_RG_BC11_CMP_EN_SHIFT}, + {PMIC_RG_BC11_IPD_EN, MT6351_PMIC_RG_BC11_IPD_EN_ADDR, + MT6351_PMIC_RG_BC11_IPD_EN_MASK, MT6351_PMIC_RG_BC11_IPD_EN_SHIFT}, + {PMIC_RG_BC11_IPU_EN, MT6351_PMIC_RG_BC11_IPU_EN_ADDR, + MT6351_PMIC_RG_BC11_IPU_EN_MASK, MT6351_PMIC_RG_BC11_IPU_EN_SHIFT}, + {PMIC_RG_BC11_BIAS_EN, MT6351_PMIC_RG_BC11_BIAS_EN_ADDR, + MT6351_PMIC_RG_BC11_BIAS_EN_MASK, MT6351_PMIC_RG_BC11_BIAS_EN_SHIFT}, + {PMIC_RG_CSDAC_STP_INC, MT6351_PMIC_RG_CSDAC_STP_INC_ADDR, + MT6351_PMIC_RG_CSDAC_STP_INC_MASK, MT6351_PMIC_RG_CSDAC_STP_INC_SHIFT}, + {PMIC_RG_CSDAC_STP_DEC, MT6351_PMIC_RG_CSDAC_STP_DEC_ADDR, + MT6351_PMIC_RG_CSDAC_STP_DEC_MASK, MT6351_PMIC_RG_CSDAC_STP_DEC_SHIFT}, + {PMIC_RG_CSDAC_DLY, MT6351_PMIC_RG_CSDAC_DLY_ADDR, MT6351_PMIC_RG_CSDAC_DLY_MASK, + MT6351_PMIC_RG_CSDAC_DLY_SHIFT}, + {PMIC_RG_CSDAC_STP, MT6351_PMIC_RG_CSDAC_STP_ADDR, MT6351_PMIC_RG_CSDAC_STP_MASK, + MT6351_PMIC_RG_CSDAC_STP_SHIFT}, + {PMIC_RG_LOW_ICH_DB, MT6351_PMIC_RG_LOW_ICH_DB_ADDR, + MT6351_PMIC_RG_LOW_ICH_DB_MASK, MT6351_PMIC_RG_LOW_ICH_DB_SHIFT}, + {PMIC_RG_CHRIND_ON, MT6351_PMIC_RG_CHRIND_ON_ADDR, MT6351_PMIC_RG_CHRIND_ON_MASK, + MT6351_PMIC_RG_CHRIND_ON_SHIFT}, + {PMIC_RG_CHRIND_DIMMING, MT6351_PMIC_RG_CHRIND_DIMMING_ADDR, + MT6351_PMIC_RG_CHRIND_DIMMING_MASK, MT6351_PMIC_RG_CHRIND_DIMMING_SHIFT}, + {PMIC_RG_CV_MODE, MT6351_PMIC_RG_CV_MODE_ADDR, MT6351_PMIC_RG_CV_MODE_MASK, + MT6351_PMIC_RG_CV_MODE_SHIFT}, + {PMIC_RG_VCDT_MODE, MT6351_PMIC_RG_VCDT_MODE_ADDR, MT6351_PMIC_RG_VCDT_MODE_MASK, + MT6351_PMIC_RG_VCDT_MODE_SHIFT}, + {PMIC_RG_CSDAC_MODE, MT6351_PMIC_RG_CSDAC_MODE_ADDR, + MT6351_PMIC_RG_CSDAC_MODE_MASK, MT6351_PMIC_RG_CSDAC_MODE_SHIFT}, + {PMIC_RG_TRACKING_EN, MT6351_PMIC_RG_TRACKING_EN_ADDR, + MT6351_PMIC_RG_TRACKING_EN_MASK, MT6351_PMIC_RG_TRACKING_EN_SHIFT}, + {PMIC_RG_HWCV_EN, MT6351_PMIC_RG_HWCV_EN_ADDR, MT6351_PMIC_RG_HWCV_EN_MASK, + MT6351_PMIC_RG_HWCV_EN_SHIFT}, + {PMIC_RG_ULC_DET_EN, MT6351_PMIC_RG_ULC_DET_EN_ADDR, + MT6351_PMIC_RG_ULC_DET_EN_MASK, MT6351_PMIC_RG_ULC_DET_EN_SHIFT}, + {PMIC_RG_BGR_TRIM_EN, MT6351_PMIC_RG_BGR_TRIM_EN_ADDR, + MT6351_PMIC_RG_BGR_TRIM_EN_MASK, MT6351_PMIC_RG_BGR_TRIM_EN_SHIFT}, + {PMIC_RG_ICHRG_TRIM, MT6351_PMIC_RG_ICHRG_TRIM_ADDR, + MT6351_PMIC_RG_ICHRG_TRIM_MASK, MT6351_PMIC_RG_ICHRG_TRIM_SHIFT}, + {PMIC_RG_BGR_TRIM, MT6351_PMIC_RG_BGR_TRIM_ADDR, MT6351_PMIC_RG_BGR_TRIM_MASK, + MT6351_PMIC_RG_BGR_TRIM_SHIFT}, + {PMIC_RG_OVP_TRIM, MT6351_PMIC_RG_OVP_TRIM_ADDR, MT6351_PMIC_RG_OVP_TRIM_MASK, + MT6351_PMIC_RG_OVP_TRIM_SHIFT}, + {PMIC_RG_CHR_OSC_TRIM, MT6351_PMIC_RG_CHR_OSC_TRIM_ADDR, + MT6351_PMIC_RG_CHR_OSC_TRIM_MASK, MT6351_PMIC_RG_CHR_OSC_TRIM_SHIFT}, + {PMIC_DA_QI_BGR_EXT_BUF_EN, MT6351_PMIC_DA_QI_BGR_EXT_BUF_EN_ADDR, + MT6351_PMIC_DA_QI_BGR_EXT_BUF_EN_MASK, MT6351_PMIC_DA_QI_BGR_EXT_BUF_EN_SHIFT}, + {PMIC_RG_BGR_TEST_EN, MT6351_PMIC_RG_BGR_TEST_EN_ADDR, + MT6351_PMIC_RG_BGR_TEST_EN_MASK, MT6351_PMIC_RG_BGR_TEST_EN_SHIFT}, + {PMIC_RG_BGR_TEST_RSTB, MT6351_PMIC_RG_BGR_TEST_RSTB_ADDR, + MT6351_PMIC_RG_BGR_TEST_RSTB_MASK, MT6351_PMIC_RG_BGR_TEST_RSTB_SHIFT}, + {PMIC_RG_DAC_USBDL_MAX, MT6351_PMIC_RG_DAC_USBDL_MAX_ADDR, + MT6351_PMIC_RG_DAC_USBDL_MAX_MASK, MT6351_PMIC_RG_DAC_USBDL_MAX_SHIFT}, + {PMIC_RG_CM_VDEC_TRIG, MT6351_PMIC_RG_CM_VDEC_TRIG_ADDR, + MT6351_PMIC_RG_CM_VDEC_TRIG_MASK, MT6351_PMIC_RG_CM_VDEC_TRIG_SHIFT}, + {PMIC_PCHR_CM_VDEC_STATUS, MT6351_PMIC_PCHR_CM_VDEC_STATUS_ADDR, + MT6351_PMIC_PCHR_CM_VDEC_STATUS_MASK, MT6351_PMIC_PCHR_CM_VDEC_STATUS_SHIFT}, + {PMIC_RG_CM_VINC_TRIG, MT6351_PMIC_RG_CM_VINC_TRIG_ADDR, + MT6351_PMIC_RG_CM_VINC_TRIG_MASK, MT6351_PMIC_RG_CM_VINC_TRIG_SHIFT}, + {PMIC_PCHR_CM_VINC_STATUS, MT6351_PMIC_PCHR_CM_VINC_STATUS_ADDR, + MT6351_PMIC_PCHR_CM_VINC_STATUS_MASK, MT6351_PMIC_PCHR_CM_VINC_STATUS_SHIFT}, + {PMIC_RG_CM_VDEC_HPRD1, MT6351_PMIC_RG_CM_VDEC_HPRD1_ADDR, + MT6351_PMIC_RG_CM_VDEC_HPRD1_MASK, MT6351_PMIC_RG_CM_VDEC_HPRD1_SHIFT}, + {PMIC_RG_CM_VDEC_HPRD2, MT6351_PMIC_RG_CM_VDEC_HPRD2_ADDR, + MT6351_PMIC_RG_CM_VDEC_HPRD2_MASK, MT6351_PMIC_RG_CM_VDEC_HPRD2_SHIFT}, + {PMIC_RG_CM_VDEC_HPRD3, MT6351_PMIC_RG_CM_VDEC_HPRD3_ADDR, + MT6351_PMIC_RG_CM_VDEC_HPRD3_MASK, MT6351_PMIC_RG_CM_VDEC_HPRD3_SHIFT}, + {PMIC_RG_CM_VDEC_HPRD4, MT6351_PMIC_RG_CM_VDEC_HPRD4_ADDR, + MT6351_PMIC_RG_CM_VDEC_HPRD4_MASK, MT6351_PMIC_RG_CM_VDEC_HPRD4_SHIFT}, + {PMIC_RG_CM_VDEC_HPRD5, MT6351_PMIC_RG_CM_VDEC_HPRD5_ADDR, + MT6351_PMIC_RG_CM_VDEC_HPRD5_MASK, MT6351_PMIC_RG_CM_VDEC_HPRD5_SHIFT}, + {PMIC_RG_CM_VDEC_HPRD6, MT6351_PMIC_RG_CM_VDEC_HPRD6_ADDR, + MT6351_PMIC_RG_CM_VDEC_HPRD6_MASK, MT6351_PMIC_RG_CM_VDEC_HPRD6_SHIFT}, + {PMIC_RG_CM_VINC_HPRD1, MT6351_PMIC_RG_CM_VINC_HPRD1_ADDR, + MT6351_PMIC_RG_CM_VINC_HPRD1_MASK, MT6351_PMIC_RG_CM_VINC_HPRD1_SHIFT}, + {PMIC_RG_CM_VINC_HPRD2, MT6351_PMIC_RG_CM_VINC_HPRD2_ADDR, + MT6351_PMIC_RG_CM_VINC_HPRD2_MASK, MT6351_PMIC_RG_CM_VINC_HPRD2_SHIFT}, + {PMIC_RG_CM_VINC_HPRD3, MT6351_PMIC_RG_CM_VINC_HPRD3_ADDR, + MT6351_PMIC_RG_CM_VINC_HPRD3_MASK, MT6351_PMIC_RG_CM_VINC_HPRD3_SHIFT}, + {PMIC_RG_CM_VINC_HPRD4, MT6351_PMIC_RG_CM_VINC_HPRD4_ADDR, + MT6351_PMIC_RG_CM_VINC_HPRD4_MASK, MT6351_PMIC_RG_CM_VINC_HPRD4_SHIFT}, + {PMIC_RG_CM_VINC_HPRD5, MT6351_PMIC_RG_CM_VINC_HPRD5_ADDR, + MT6351_PMIC_RG_CM_VINC_HPRD5_MASK, MT6351_PMIC_RG_CM_VINC_HPRD5_SHIFT}, + {PMIC_RG_CM_VINC_HPRD6, MT6351_PMIC_RG_CM_VINC_HPRD6_ADDR, + MT6351_PMIC_RG_CM_VINC_HPRD6_MASK, MT6351_PMIC_RG_CM_VINC_HPRD6_SHIFT}, + {PMIC_RG_CM_LPRD, MT6351_PMIC_RG_CM_LPRD_ADDR, MT6351_PMIC_RG_CM_LPRD_MASK, + MT6351_PMIC_RG_CM_LPRD_SHIFT}, + {PMIC_RG_CM_CS_VTHL, MT6351_PMIC_RG_CM_CS_VTHL_ADDR, + MT6351_PMIC_RG_CM_CS_VTHL_MASK, MT6351_PMIC_RG_CM_CS_VTHL_SHIFT}, + {PMIC_RG_CM_CS_VTHH, MT6351_PMIC_RG_CM_CS_VTHH_ADDR, + MT6351_PMIC_RG_CM_CS_VTHH_MASK, MT6351_PMIC_RG_CM_CS_VTHH_SHIFT}, + {PMIC_RG_PCHR_RSV, MT6351_PMIC_RG_PCHR_RSV_ADDR, MT6351_PMIC_RG_PCHR_RSV_MASK, + MT6351_PMIC_RG_PCHR_RSV_SHIFT}, + {PMIC_RG_ENVTEM_D, MT6351_PMIC_RG_ENVTEM_D_ADDR, MT6351_PMIC_RG_ENVTEM_D_MASK, + MT6351_PMIC_RG_ENVTEM_D_SHIFT}, + {PMIC_RG_ENVTEM_EN, MT6351_PMIC_RG_ENVTEM_EN_ADDR, MT6351_PMIC_RG_ENVTEM_EN_MASK, + MT6351_PMIC_RG_ENVTEM_EN_SHIFT}, + {PMIC_RGS_BATON_HV, MT6351_PMIC_RGS_BATON_HV_ADDR, MT6351_PMIC_RGS_BATON_HV_MASK, + MT6351_PMIC_RGS_BATON_HV_SHIFT}, + {PMIC_RG_HW_VTH_CTRL, MT6351_PMIC_RG_HW_VTH_CTRL_ADDR, + MT6351_PMIC_RG_HW_VTH_CTRL_MASK, MT6351_PMIC_RG_HW_VTH_CTRL_SHIFT}, + {PMIC_RG_HW_VTH2, MT6351_PMIC_RG_HW_VTH2_ADDR, MT6351_PMIC_RG_HW_VTH2_MASK, + MT6351_PMIC_RG_HW_VTH2_SHIFT}, + {PMIC_RG_HW_VTH1, MT6351_PMIC_RG_HW_VTH1_ADDR, MT6351_PMIC_RG_HW_VTH1_MASK, + MT6351_PMIC_RG_HW_VTH1_SHIFT}, + {PMIC_RG_CM_VDEC_INT_EN, MT6351_PMIC_RG_CM_VDEC_INT_EN_ADDR, + MT6351_PMIC_RG_CM_VDEC_INT_EN_MASK, MT6351_PMIC_RG_CM_VDEC_INT_EN_SHIFT}, + {PMIC_RG_CM_VINC_INT_EN, MT6351_PMIC_RG_CM_VINC_INT_EN_ADDR, + MT6351_PMIC_RG_CM_VINC_INT_EN_MASK, MT6351_PMIC_RG_CM_VINC_INT_EN_SHIFT}, + {PMIC_RG_QI_BATON_LT_EN, MT6351_PMIC_RG_QI_BATON_LT_EN_ADDR, + MT6351_PMIC_RG_QI_BATON_LT_EN_MASK, MT6351_PMIC_RG_QI_BATON_LT_EN_SHIFT}, + {PMIC_RGS_BATON_UNDET, MT6351_PMIC_RGS_BATON_UNDET_ADDR, + MT6351_PMIC_RGS_BATON_UNDET_MASK, MT6351_PMIC_RGS_BATON_UNDET_SHIFT}, + {PMIC_RG_JW_CS_VTH, MT6351_PMIC_RG_JW_CS_VTH_ADDR, MT6351_PMIC_RG_JW_CS_VTH_MASK, + MT6351_PMIC_RG_JW_CS_VTH_SHIFT}, + {PMIC_RG_JW_CV_VTH, MT6351_PMIC_RG_JW_CV_VTH_ADDR, MT6351_PMIC_RG_JW_CV_VTH_MASK, + MT6351_PMIC_RG_JW_CV_VTH_SHIFT}, + {PMIC_RG_JC_CS_VTH, MT6351_PMIC_RG_JC_CS_VTH_ADDR, MT6351_PMIC_RG_JC_CS_VTH_MASK, + MT6351_PMIC_RG_JC_CS_VTH_SHIFT}, + {PMIC_RG_JC_CV_VTH, MT6351_PMIC_RG_JC_CV_VTH_ADDR, MT6351_PMIC_RG_JC_CV_VTH_MASK, + MT6351_PMIC_RG_JC_CV_VTH_SHIFT}, + {PMIC_RG_BC11_ACA_EN, MT6351_PMIC_RG_BC11_ACA_EN_ADDR, + MT6351_PMIC_RG_BC11_ACA_EN_MASK, MT6351_PMIC_RG_BC11_ACA_EN_SHIFT}, + {PMIC_RG_JEITA_EN, MT6351_PMIC_RG_JEITA_EN_ADDR, MT6351_PMIC_RG_JEITA_EN_MASK, + MT6351_PMIC_RG_JEITA_EN_SHIFT}, + {PMIC_RG_VCDT_TRIM, MT6351_PMIC_RG_VCDT_TRIM_ADDR, MT6351_PMIC_RG_VCDT_TRIM_MASK, + MT6351_PMIC_RG_VCDT_TRIM_SHIFT}, + {PMIC_RGS_BC11_ID_FLOAT, MT6351_PMIC_RGS_BC11_ID_FLOAT_ADDR, + MT6351_PMIC_RGS_BC11_ID_FLOAT_MASK, MT6351_PMIC_RGS_BC11_ID_FLOAT_SHIFT}, + {PMIC_RGS_BC11_ID_A, MT6351_PMIC_RGS_BC11_ID_A_ADDR, + MT6351_PMIC_RGS_BC11_ID_A_MASK, MT6351_PMIC_RGS_BC11_ID_A_SHIFT}, + {PMIC_RGS_BC11_ID_B, MT6351_PMIC_RGS_BC11_ID_B_ADDR, + MT6351_PMIC_RGS_BC11_ID_B_MASK, MT6351_PMIC_RGS_BC11_ID_B_SHIFT}, + {PMIC_RGS_BC11_ID_C, MT6351_PMIC_RGS_BC11_ID_C_ADDR, + MT6351_PMIC_RGS_BC11_ID_C_MASK, MT6351_PMIC_RGS_BC11_ID_C_SHIFT}, + {PMIC_RGS_BC11_ID_GND, MT6351_PMIC_RGS_BC11_ID_GND_ADDR, + MT6351_PMIC_RGS_BC11_ID_GND_MASK, MT6351_PMIC_RGS_BC11_ID_GND_SHIFT}, + {PMIC_RGS_BC11_ACA_OTG_DET, MT6351_PMIC_RGS_BC11_ACA_OTG_DET_ADDR, + MT6351_PMIC_RGS_BC11_ACA_OTG_DET_MASK, MT6351_PMIC_RGS_BC11_ACA_OTG_DET_SHIFT}, + {PMIC_RG_INDICATOR_TRIM, MT6351_PMIC_RG_INDICATOR_TRIM_ADDR, + MT6351_PMIC_RG_INDICATOR_TRIM_MASK, MT6351_PMIC_RG_INDICATOR_TRIM_SHIFT}, + {PMIC_EOSC_CALI_START, MT6351_PMIC_EOSC_CALI_START_ADDR, + MT6351_PMIC_EOSC_CALI_START_MASK, MT6351_PMIC_EOSC_CALI_START_SHIFT}, + {PMIC_EOSC_CALI_TD, MT6351_PMIC_EOSC_CALI_TD_ADDR, MT6351_PMIC_EOSC_CALI_TD_MASK, + MT6351_PMIC_EOSC_CALI_TD_SHIFT}, + {PMIC_EOSC_CALI_TEST, MT6351_PMIC_EOSC_CALI_TEST_ADDR, + MT6351_PMIC_EOSC_CALI_TEST_MASK, MT6351_PMIC_EOSC_CALI_TEST_SHIFT}, + {PMIC_EOSC_CALI_DCXO_RDY_TD, MT6351_PMIC_EOSC_CALI_DCXO_RDY_TD_ADDR, + MT6351_PMIC_EOSC_CALI_DCXO_RDY_TD_MASK, MT6351_PMIC_EOSC_CALI_DCXO_RDY_TD_SHIFT}, + {PMIC_FRC_VTCXO0_ON, MT6351_PMIC_FRC_VTCXO0_ON_ADDR, + MT6351_PMIC_FRC_VTCXO0_ON_MASK, MT6351_PMIC_FRC_VTCXO0_ON_SHIFT}, + {PMIC_EOSC_CALI_RSV, MT6351_PMIC_EOSC_CALI_RSV_ADDR, + MT6351_PMIC_EOSC_CALI_RSV_MASK, MT6351_PMIC_EOSC_CALI_RSV_SHIFT}, + {PMIC_VRTC_PWM_MODE, MT6351_PMIC_VRTC_PWM_MODE_ADDR, + MT6351_PMIC_VRTC_PWM_MODE_MASK, MT6351_PMIC_VRTC_PWM_MODE_SHIFT}, + {PMIC_VRTC_PWM_RSV, MT6351_PMIC_VRTC_PWM_RSV_ADDR, MT6351_PMIC_VRTC_PWM_RSV_MASK, + MT6351_PMIC_VRTC_PWM_RSV_SHIFT}, + {PMIC_VRTC_PWM_L_DUTY, MT6351_PMIC_VRTC_PWM_L_DUTY_ADDR, + MT6351_PMIC_VRTC_PWM_L_DUTY_MASK, MT6351_PMIC_VRTC_PWM_L_DUTY_SHIFT}, + {PMIC_VRTC_PWM_H_DUTY, MT6351_PMIC_VRTC_PWM_H_DUTY_ADDR, + MT6351_PMIC_VRTC_PWM_H_DUTY_MASK, MT6351_PMIC_VRTC_PWM_H_DUTY_SHIFT}, + {PMIC_VRTC_CAP_SEL, MT6351_PMIC_VRTC_CAP_SEL_ADDR, MT6351_PMIC_VRTC_CAP_SEL_MASK, + MT6351_PMIC_VRTC_CAP_SEL_SHIFT}, +}; + + +unsigned short mt6351_set_register_value(PMU_FLAGS_LIST_ENUM flagname, unsigned int val) +{ + const PMU_FLAG_TABLE_ENTRY *pFlag = &pmu_flags_table[flagname]; + unsigned int ret = 0; + + + if (pFlag->flagname != flagname) { + pr_notice("[pmu_set_register_value]pmic flag idx error\n"); + return 1; + } + + ret = pmic_config_interface((pFlag->offset), + (unsigned int) (val), + (unsigned int) (pFlag->mask), (unsigned int) (pFlag->shift) + ); + + return 0; +} + + +unsigned short mt6351_get_register_value(PMU_FLAGS_LIST_ENUM flagname) +{ + const PMU_FLAG_TABLE_ENTRY *pFlag = &pmu_flags_table[flagname]; + unsigned int val; + unsigned int ret; + + ret = + pmic_read_interface((unsigned int) pFlag->offset, &val, (unsigned int) (pFlag->mask), + (unsigned int) (pFlag->shift)); + + return val; +} + +unsigned short mt6351_get_register_value_nolock(PMU_FLAGS_LIST_ENUM flagname) +{ + const PMU_FLAG_TABLE_ENTRY *pFlag = &pmu_flags_table[flagname]; + unsigned int val; + unsigned int ret; + + ret = + pmic_read_interface_nolock((unsigned int) pFlag->offset, &val, (unsigned int) (pFlag->mask), + (unsigned int) (pFlag->shift)); + + return val; +} + +unsigned short pmic_set_register_value(PMU_FLAGS_LIST_ENUM flagname, unsigned int val) +{ + return mt6351_set_register_value(flagname, val); +} + +unsigned short pmic_get_register_value(PMU_FLAGS_LIST_ENUM flagname) +{ + return mt6351_get_register_value(flagname); +} + +unsigned short pmic_get_register_value_nolock(PMU_FLAGS_LIST_ENUM flagname) +{ + return mt6351_get_register_value_nolock(flagname); +} + +unsigned short bc11_set_register_value(PMU_FLAGS_LIST_ENUM flagname, unsigned int val) +{ + return mt6351_set_register_value(flagname, val); +} + + +unsigned short bc11_get_register_value(PMU_FLAGS_LIST_ENUM flagname) +{ + return mt6351_get_register_value(flagname); +} diff --git a/drivers/misc/mediatek/power_gs/mt6755/Makefile b/drivers/misc/mediatek/power_gs/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ba2b8a61e96e2c0518366ad6839e48db1b1c9d4e --- /dev/null +++ b/drivers/misc/mediatek/power_gs/mt6755/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ifdef CONFIG_MTK_PMIC_CHIP_MT6353 +obj-y += mt_power_gs_6353_array.o +else +obj-y += mt_power_gs_6351_array.o +endif diff --git a/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_6351_array.c b/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_6351_array.c new file mode 100644 index 0000000000000000000000000000000000000000..ec4bbaf64dafb4f99f4e1201bff8516d63e64e97 --- /dev/null +++ b/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_6351_array.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/* This file is generated by GenLP_setting.pl v1.5.7 */ + +#include +#include +#include + +const unsigned int MT6351_PMIC_REG_gs_early_suspend_deep_idle_mode_data[] = { +/* Address Mask Golden Setting Value */ + 0x0016, 0x0080, 0x0000,/* STRUP_CON11 */ + 0x0204, 0x0270, 0x0070,/* TOP_CON */ + 0x023A, 0xFFFF, 0xFEFC,/* TOP_CKPDN_CON0 */ + 0x0240, 0x1FFF, 0x00AC,/* TOP_CKPDN_CON1 */ + 0x0246, 0xFEFC, 0x7470,/* TOP_CKPDN_CON2 */ + 0x024C, 0x0FFF, 0x0DE4,/* TOP_CKPDN_CON3 */ + 0x0252, 0x006F, 0x0000,/* TOP_CKPDN_CON4 */ + 0x0258, 0x7FDF, 0x3FC0,/* TOP_CKPDN_CON5 */ + 0x025E, 0xF400, 0x0000,/* TOP_CKSEL_CON0 */ + 0x0282, 0x0CFF, 0x00F7,/* TOP_CKHWEN_CON0 */ + 0x0288, 0x0037, 0x0037,/* TOP_CKHWEN_CON1 */ + 0x028E, 0x002F, 0x002F,/* TOP_CKHWEN_CON2 */ + 0x029A, 0x0F3F, 0x0100,/* TOP_CLKSQ */ + 0x02A0, 0x0002, 0x0002,/* TOP_CLKSQ_RTC */ + 0x02EA, 0x8000, 0x0000,/* FQMTR_CON0 */ + 0x0600, 0x0001, 0x0000,/* BUCK_VCORE_CON0 */ + 0x0602, 0x0038, 0x0000,/* BUCK_VCORE_CON1 */ + 0x0604, 0x0001, 0x0001,/* BUCK_VCORE_CON2 */ + 0x0612, 0x0100, 0x0100,/* BUCK_VCORE_CON9 */ + 0x0614, 0x0001, 0x0000,/* BUCK_VGPU_CON0 */ + 0x0618, 0x0001, 0x0000,/* BUCK_VGPU_CON2 */ + 0x0626, 0x0100, 0x0000,/* BUCK_VGPU_CON9 */ + 0x0628, 0x0001, 0x0000,/* BUCK_VMODEM_CON0 */ + 0x062C, 0x0001, 0x0000,/* BUCK_VMODEM_CON2 */ + 0x063A, 0x0100, 0x0000,/* BUCK_VMODEM_CON9 */ + 0x063C, 0x0001, 0x0000,/* BUCK_VMD1_CON0 */ + 0x0640, 0x0001, 0x0000,/* BUCK_VMD1_CON2 */ + 0x064E, 0x0100, 0x0000,/* BUCK_VMD1_CON9 */ + 0x0650, 0x0001, 0x0000,/* BUCK_VSRAM_MD_CON0 */ + 0x0654, 0x0001, 0x0000,/* BUCK_VSRAM_MD_CON2 */ + 0x0662, 0x0100, 0x0000,/* BUCK_VSRAM_MD_CON9 */ + 0x0664, 0x0001, 0x0000,/* BUCK_VS1_CON0 */ + 0x0666, 0x0038, 0x0000,/* BUCK_VS1_CON1 */ + 0x0668, 0x0001, 0x0001,/* BUCK_VS1_CON2 */ + 0x0676, 0x0100, 0x0100,/* BUCK_VS1_CON9 */ + 0x0678, 0x0001, 0x0000,/* BUCK_VS2_CON0 */ + 0x067A, 0x0038, 0x0000,/* BUCK_VS2_CON1 */ + 0x067C, 0x0001, 0x0001,/* BUCK_VS2_CON2 */ + 0x068A, 0x0100, 0x0100,/* BUCK_VS2_CON9 */ + 0x068C, 0x0001, 0x0000,/* BUCK_VPA_CON0 */ + 0x0690, 0x0001, 0x0001,/* BUCK_VPA_CON2 */ + 0x069E, 0x0100, 0x0000,/* BUCK_VPA_CON9 */ + 0x0836, 0x000F, 0x0000,/* ISINK_EN_CTRL */ + 0x0848, 0x000F, 0x0000,/* ISINK_EN_CTRL_SMPL */ + 0x0852, 0x0010, 0x0000,/* CHRIND_EN_CTRL */ + 0x0A00, 0x00EE, 0x0006,/* LDO_VA18_CON0 */ + 0x0A04, 0x380C, 0x0008,/* LDO_VTCXO24_CON0 */ + 0x0A08, 0x380C, 0x0808,/* LDO_VTCXO28_CON0 */ + 0x0A0C, 0x000E, 0x0000,/* LDO_VCN28_CON0 */ + 0x0A12, 0x000A, 0x0000,/* LDO_VCAMA_CON0 */ + 0x0A16, 0x00EE, 0x0006,/* LDO_VUSB33_CON0 */ + 0x0A1C, 0x000E, 0x0000,/* LDO_VSIM1_CON0 */ + 0x0A22, 0x000E, 0x0000,/* LDO_VSIM2_CON0 */ + 0x0A28, 0x000E, 0x0000,/* LDO_VEMC_CON0 */ + 0x0A2E, 0x000E, 0x0000,/* LDO_VMCH_CON0 */ + 0x0A34, 0x00EE, 0x0006,/* LDO_VIO28_CON0 */ + 0x0A3A, 0x000E, 0x0000,/* LDO_VIBR_CON0 */ + 0x0A40, 0x0006, 0x0000,/* LDO_VCAMD_CON0 */ + 0x0A46, 0x380C, 0x0808,/* LDO_VRF18_CON0 */ + 0x0A4C, 0x00EE, 0x0006,/* LDO_VIO18_CON0 */ + 0x0A52, 0x000E, 0x0000,/* LDO_VCN18_CON0 */ + 0x0A58, 0x0006, 0x0000,/* LDO_VCAMIO_CON0 */ + 0x0A5E, 0x000E, 0x0000,/* LDO_VSRAM_PROC_CON0 */ + 0x0A64, 0x000E, 0x0000,/* LDO_VXO22_CON0 */ + 0x0A68, 0x380C, 0x0808,/* LDO_VRF12_CON0 */ + 0x0A6E, 0x00EE, 0x0006,/* LDO_VA10_CON0 */ + 0x0A74, 0x00EE, 0x0006,/* LDO_VDRAM_CON0 */ + 0x0A7A, 0x00EE, 0x0024,/* LDO_VMIPI_CON0 */ + 0x0A80, 0x000E, 0x0000,/* LDO_VGP3_CON0 */ + 0x0A86, 0x000E, 0x0000,/* LDO_VBIF28_CON0 */ + 0x0A8C, 0x0006, 0x0000,/* LDO_VEFUSE_CON0 */ + 0x0A92, 0x0004, 0x0000,/* LDO_VCN33_CON0 */ + 0x0A98, 0x000A, 0x0000,/* LDO_VCN33_CON3 */ + 0x0A9A, 0x000A, 0x0000,/* LDO_VCN33_CON4 */ + 0x0A9C, 0x00EC, 0x0004,/* LDO_VLDO28_CON0 */ + 0x0AA2, 0x0002, 0x0002,/* LDO_VLDO28_CON3 */ + 0x0AA4, 0x0002, 0x0002,/* LDO_VLDO28_CON4 */ + 0x0AAA, 0x000E, 0x0000,/* LDO_VMC_CON0 */ + 0x0CA4, 0x0001, 0x0000,/* FGADC_CON0 */ + 0x0CC8, 0xFFFF, 0x0024,/* FGADC_CON18 */ + 0x0D04, 0x1000, 0x1000,/* AUDDEC_ANA_CON9 */ + 0x0F48, 0x0001, 0x0000/* ACCDET_CON1 */ +}; + +const unsigned int *MT6351_PMIC_REG_gs_early_suspend_deep_idle_mode = + MT6351_PMIC_REG_gs_early_suspend_deep_idle_mode_data; + +unsigned int MT6351_PMIC_REG_gs_early_suspend_deep_idle_mode_len = 246; + +const unsigned int MT6351_PMIC_REG_gs_flightmode_suspend_mode_data[] = { +/* Address Mask Golden Setting Value */ + 0x0016, 0x0080, 0x0000,/* STRUP_CON11 */ + 0x0204, 0x0270, 0x0070,/* TOP_CON */ + 0x023A, 0xFFFF, 0xFCCC,/* TOP_CKPDN_CON0 */ + 0x0240, 0x1FFF, 0x00AC,/* TOP_CKPDN_CON1 */ + 0x0246, 0xFEFC, 0x7070,/* TOP_CKPDN_CON2 */ + 0x024C, 0x0FFF, 0x0DE0,/* TOP_CKPDN_CON3 */ + 0x0252, 0x006F, 0x0000,/* TOP_CKPDN_CON4 */ + 0x0258, 0x7FDF, 0x39C0,/* TOP_CKPDN_CON5 */ + 0x025E, 0xF400, 0x0000,/* TOP_CKSEL_CON0 */ + 0x0282, 0x0CFF, 0x30E7,/* TOP_CKHWEN_CON0 */ + 0x0288, 0x0037, 0x0037,/* TOP_CKHWEN_CON1 */ + 0x028E, 0x002F, 0x002F,/* TOP_CKHWEN_CON2 */ + 0x029A, 0x0F3F, 0x0000,/* TOP_CLKSQ */ + 0x02A0, 0x0002, 0x0002,/* TOP_CLKSQ_RTC */ + 0x02EA, 0x8000, 0x0000,/* FQMTR_CON0 */ + 0x0600, 0x0001, 0x0000,/* BUCK_VCORE_CON0 */ + 0x0602, 0x0038, 0x0000,/* BUCK_VCORE_CON1 */ + 0x0604, 0x0001, 0x0001,/* BUCK_VCORE_CON2 */ + 0x0612, 0x0100, 0x0100,/* BUCK_VCORE_CON9 */ + 0x0614, 0x0001, 0x0000,/* BUCK_VGPU_CON0 */ + 0x0618, 0x0001, 0x0000,/* BUCK_VGPU_CON2 */ + 0x0626, 0x0100, 0x0000,/* BUCK_VGPU_CON9 */ + 0x0628, 0x0001, 0x0000,/* BUCK_VMODEM_CON0 */ + 0x062C, 0x0001, 0x3021,/* BUCK_VMODEM_CON2 */ + 0x063A, 0x0100, 0x0113,/* BUCK_VMODEM_CON9 */ + 0x063C, 0x0001, 0x0000,/* BUCK_VMD1_CON0 */ + 0x0640, 0x0001, 0x3021,/* BUCK_VMD1_CON2 */ + 0x064E, 0x0100, 0x0113,/* BUCK_VMD1_CON9 */ + 0x0650, 0x0001, 0x0000,/* BUCK_VSRAM_MD_CON0 */ + 0x0654, 0x0001, 0x3021,/* BUCK_VSRAM_MD_CON2 */ + 0x0662, 0x0100, 0x0113,/* BUCK_VSRAM_MD_CON9 */ + 0x0664, 0x0001, 0x0000,/* BUCK_VS1_CON0 */ + 0x0666, 0x0038, 0x0000,/* BUCK_VS1_CON1 */ + 0x0668, 0x0001, 0x0001,/* BUCK_VS1_CON2 */ + 0x0676, 0x0100, 0x0100,/* BUCK_VS1_CON9 */ + 0x0678, 0x0001, 0x0000,/* BUCK_VS2_CON0 */ + 0x067A, 0x0038, 0x0000,/* BUCK_VS2_CON1 */ + 0x067C, 0x0001, 0x0001,/* BUCK_VS2_CON2 */ + 0x068A, 0x0100, 0x0100,/* BUCK_VS2_CON9 */ + 0x068C, 0x0001, 0x0000,/* BUCK_VPA_CON0 */ + 0x0690, 0x0001, 0x0000,/* BUCK_VPA_CON2 */ + 0x069E, 0x0100, 0x0000,/* BUCK_VPA_CON9 */ + 0x06B2, 0x0100, 0x0000,/* BUCK_VSRAM_PROC_CON9 */ + 0x0836, 0x000F, 0x0000,/* ISINK_EN_CTRL */ + 0x0848, 0x000F, 0x0000,/* ISINK_EN_CTRL_SMPL */ + 0x0852, 0x0010, 0x0000,/* CHRIND_EN_CTRL */ + 0x0A00, 0x00EE, 0x0006,/* LDO_VA18_CON0 */ + 0x0A04, 0x380C, 0x0008,/* LDO_VTCXO24_CON0 */ + 0x0A08, 0x380C, 0x0808,/* LDO_VTCXO28_CON0 */ + 0x0A0C, 0x000E, 0x0000,/* LDO_VCN28_CON0 */ + 0x0A12, 0x000A, 0x0000,/* LDO_VCAMA_CON0 */ + 0x0A16, 0x00EE, 0x0006,/* LDO_VUSB33_CON0 */ + 0x0A1C, 0x000E, 0xDB63,/* LDO_VSIM1_CON0 */ + 0x0A22, 0x000E, 0x0000,/* LDO_VSIM2_CON0 */ + 0x0A28, 0x000E, 0x0000,/* LDO_VEMC_CON0 */ + 0x0A2E, 0x000E, 0x0000,/* LDO_VMCH_CON0 */ + 0x0A34, 0x00EE, 0x0006,/* LDO_VIO28_CON0 */ + 0x0A3A, 0x000E, 0x0000,/* LDO_VIBR_CON0 */ + 0x0A40, 0x0006, 0x0000,/* LDO_VCAMD_CON0 */ + 0x0A46, 0x380C, 0x0808,/* LDO_VRF18_CON0 */ + 0x0A4C, 0x00EE, 0x0006,/* LDO_VIO18_CON0 */ + 0x0A52, 0x000E, 0x0000,/* LDO_VCN18_CON0 */ + 0x0A58, 0x0006, 0x0000,/* LDO_VCAMIO_CON0 */ + 0x0A5E, 0x000E, 0xDA62,/* LDO_VSRAM_PROC_CON0 */ + 0x0A64, 0x000E, 0x1A62,/* LDO_VXO22_CON0 */ + 0x0A68, 0x380C, 0x0808,/* LDO_VRF12_CON0 */ + 0x0A6E, 0x00EE, 0x0006,/* LDO_VA10_CON0 */ + 0x0A74, 0x00EE, 0x0006,/* LDO_VDRAM_CON0 */ + 0x0A7A, 0x000A, 0x0A68,/* LDO_VMIPI_CON0 */ + 0x0A80, 0x000E, 0x0000,/* LDO_VGP3_CON0 */ + 0x0A86, 0x000E, 0xDA6C,/* LDO_VBIF28_CON0 */ + 0x0A8C, 0x0006, 0x0000,/* LDO_VEFUSE_CON0 */ + 0x0A92, 0x0004, 0x0000,/* LDO_VCN33_CON0 */ + 0x0A98, 0x000A, 0x0000,/* LDO_VCN33_CON3 */ + 0x0A9A, 0x000A, 0x0000,/* LDO_VCN33_CON4 */ + 0x0A9C, 0x00EC, 0x0004,/* LDO_VLDO28_CON0 */ + 0x0AA2, 0x0002, 0x1800,/* LDO_VLDO28_CON3 */ + 0x0AA4, 0x0002, 0x1800,/* LDO_VLDO28_CON4 */ + 0x0AAA, 0x000E, 0x0000,/* LDO_VMC_CON0 */ + 0x0CA4, 0x0001, 0x0029,/* FGADC_CON0 */ + 0x0CC8, 0xFFFF, 0x001F,/* FGADC_CON18 */ + 0x0D04, 0x1000, 0x1000,/* AUDDEC_ANA_CON9 */ + 0x0F48, 0x0001, 0x0000/* ACCDET_CON1 */ +}; + +const unsigned int *MT6351_PMIC_REG_gs_flightmode_suspend_mode = + MT6351_PMIC_REG_gs_flightmode_suspend_mode_data; + +unsigned int MT6351_PMIC_REG_gs_flightmode_suspend_mode_len = 249; diff --git a/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_6353_array.c b/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_6353_array.c new file mode 100644 index 0000000000000000000000000000000000000000..f76e54b17de4f937ec741fd61c685d27cc20f326 --- /dev/null +++ b/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_6353_array.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +/* This file is generated by GenLP_setting.pl v1.5.7 */ + +#include +#include +#include + +const unsigned int MT6353_PMIC_REG_gs_early_suspend_deep_idle_mode_data[] = { +/* Address Mask Golden Setting Value */ + 0x0204, 0x0270, 0x0070,/* TOP_CON */ + 0x0244, 0x0005, 0x0000,/* TOP_CLKSQ */ + 0x0256, 0x0003, 0x0002,/* CLK_PDN_CON0 */ + 0x025C, 0x0001, 0x0001,/* CLK_PDN_CON1 */ + 0x026E, 0xFB9E, 0xF214,/* CLK_CKPDN_CON0 */ + 0x0274, 0x722B, 0x100A,/* CLK_CKPDN_CON1 */ + 0x027A, 0xDFF9, 0x0901,/* CLK_CKPDN_CON2 */ + 0x0280, 0x00DB, 0x00CA,/* CLK_CKPDN_CON3 */ + 0x0286, 0x3FF7, 0x3DE1,/* CLK_CKPDN_HWEN_CON0 */ + 0x028C, 0x0100, 0x0100,/* CLK_CKSEL_CON0 */ + 0x02E0, 0x0001, 0x0000,/* SPK_CON0 */ + 0x0308, 0x8000, 0x0000,/* FQMTR_CON0 */ + 0x0326, 0x0003, 0x0000,/* ISINK_EN_CTRL */ + 0x0332, 0x000C, 0x0000,/* ISINK_EN_CTRL_SMPL */ + 0x033C, 0x0010, 0x0000,/* CHRIND_EN_CTRL */ + 0x0600, 0x0003, 0x0002,/* BUCK_VPROC_HWM_CON0 */ + 0x0602, 0x0038, 0x0000,/* BUCK_VPROC_HWM_CON1 */ + 0x0604, 0x0001, 0x0001,/* BUCK_VPROC_EN_CON0 */ + 0x0610, 0x0100, 0x0100,/* BUCK_VPROC_LPW_CON0 */ + 0x0612, 0x0003, 0x0002,/* BUCK_VS1_HWM_CON0 */ + 0x0618, 0x0038, 0x0000,/* BUCK_VS1_HWM_CON1 */ + 0x061A, 0x0001, 0x0001,/* BUCK_VS1_EN_CON0 */ + 0x0626, 0x0100, 0x0100,/* BUCK_VS1_LPW_CON0 */ + 0x0628, 0x0003, 0x0002,/* BUCK_VCORE_HWM_CON0 */ + 0x062A, 0x0038, 0x0000,/* BUCK_VCORE_HWM_CON1 */ + 0x062C, 0x0001, 0x0001,/* BUCK_VCORE_EN_CON0 */ + 0x0638, 0x0100, 0x0100,/* BUCK_VCORE_LPW_CON0 */ + 0x063A, 0x0001, 0x0000,/* BUCK_VCORE2_HWM_CON0 */ + 0x063E, 0x0001, 0x0000,/* BUCK_VCORE2_EN_CON0 */ + 0x064C, 0x0001, 0x0000,/* BUCK_VPA_EN_CON0 */ + 0x0A06, 0x0010, 0x0010,/* LDO_VTCXO24_SW_CON0 */ + 0x0A0E, 0x000A, 0x0000,/* LDO_SHARE_VCN33_CON0 */ + 0x0A10, 0x000A, 0x0000,/* LDO_SHARE_VCN33_CON1 */ + 0x0A16, 0x0002, 0x0002,/* LDO_SHARE_VLDO28_CON0 */ + 0x0A18, 0x0002, 0x0002,/* LDO_SHARE_VLDO28_CON1 */ + 0x0A20, 0x003A, 0x0002,/* LDO_VSRAM_PROC_HWM_CON0 */ + 0x0A2C, 0x0100, 0x0100,/* LDO_VSRAM_PROC_LPW_CON0 */ + 0x0A30, 0x000A, 0x0000,/* LDO2_TREF_CON0 */ + 0x0A32, 0x3808, 0x0808,/* LDO3_VTCXO28_CON0 */ + 0x0A36, 0x3808, 0x0008,/* LDO3_VTCXO24_CON0 */ + 0x0A3A, 0x00EE, 0x0006,/* LDO3_VXO22_CON0 */ + 0x0A3E, 0x3808, 0x0808,/* LDO3_VRF18_CON0 */ + 0x0A42, 0x3808, 0x0808,/* LDO3_VRF12_CON0 */ + 0x0A48, 0x000A, 0x0000,/* LDO3_VCN28_CON0 */ + 0x0A4C, 0x000A, 0x0000,/* LDO3_VCN18_CON0 */ + 0x0A50, 0x0002, 0x0000,/* LDO0_VCAMA_CON0 */ + 0x0A54, 0x0002, 0x0000,/* LDO0_VCAMIO_CON0 */ + 0x0A58, 0x0002, 0x0000,/* LDO0_VCAMD_CON0 */ + 0x0A5C, 0x00EE, 0x0006,/* LDO3_VAUX18_CON0 */ + 0x0A60, 0x00EE, 0x0006,/* LDO3_VAUD28_CON0 */ + 0x0A64, 0x00EE, 0x0006,/* LDO3_VSRAM_PROC_CON0 */ + 0x0A68, 0x00E6, 0x0006,/* LDO1_VDRAM_CON0 */ + 0x0A6E, 0x0002, 0x0000,/* LDO1_VSIM1_CON0 */ + 0x0A72, 0x0002, 0x0000,/* LDO1_VSIM2_CON0 */ + 0x0A76, 0x00E6, 0x0006,/* LDO1_VIO28_CON0 */ + 0x0A7A, 0x0002, 0x0000,/* LDO1_VMC_CON0 */ + 0x0A80, 0x0002, 0x0000,/* LDO1_VMCH_CON0 */ + 0x0A86, 0x00E6, 0x0006,/* LDO1_VUSB33_CON0 */ + 0x0A8A, 0x0002, 0x0000,/* LDO1_VEMC33_CON0 */ + 0x0A90, 0x00E6, 0x0006,/* LDO1_VIO18_CON0 */ + 0x0A94, 0x0002, 0x0000,/* LDO0_VIBR_CON0 */ + 0x0CA4, 0x0001, 0x0000,/* FGADC_CON0 */ + 0x0D02, 0x0002, 0x0002,/* AUDDEC_ANA_CON8 */ + 0x0F5A, 0x0001, 0x0000 /* ACCDET_CON1 */ +}; + +const unsigned int *MT6353_PMIC_REG_gs_early_suspend_deep_idle_mode = + MT6353_PMIC_REG_gs_early_suspend_deep_idle_mode_data; + +unsigned int MT6353_PMIC_REG_gs_early_suspend_deep_idle_mode_len = 192; + +const unsigned int MT6353_PMIC_REG_gs_flightmode_suspend_mode_data[] = { +/* Address Mask Golden Setting Value */ + 0x0204, 0x0270, 0x0070,/* TOP_CON */ + 0x0244, 0x0005, 0x0000,/* TOP_CLKSQ */ + 0x0256, 0x0003, 0x0002,/* CLK_PDN_CON0 */ + 0x025C, 0x0001, 0x0001,/* CLK_PDN_CON1 */ + 0x026E, 0xFB9E, 0xF214,/* CLK_CKPDN_CON0 */ + 0x0274, 0x722B, 0x100A,/* CLK_CKPDN_CON1 */ + 0x027A, 0xDFF9, 0x0901,/* CLK_CKPDN_CON2 */ + 0x0280, 0x00DB, 0x00CA,/* CLK_CKPDN_CON3 */ + 0x0286, 0x3FF7, 0x3DE1,/* CLK_CKPDN_HWEN_CON0 */ + 0x028C, 0x0100, 0x0100,/* CLK_CKSEL_CON0 */ + 0x02E0, 0x0001, 0x0000,/* SPK_CON0 */ + 0x0308, 0x8000, 0x0000,/* FQMTR_CON0 */ + 0x0326, 0x0003, 0x0000,/* ISINK_EN_CTRL */ + 0x0332, 0x000C, 0x0000,/* ISINK_EN_CTRL_SMPL */ + 0x033C, 0x0010, 0x0000,/* CHRIND_EN_CTRL */ + 0x0600, 0x0003, 0x0002,/* BUCK_VPROC_HWM_CON0 */ + 0x0602, 0x0038, 0x0000,/* BUCK_VPROC_HWM_CON1 */ + 0x0604, 0x0001, 0x0001,/* BUCK_VPROC_EN_CON0 */ + 0x0610, 0x0100, 0x0100,/* BUCK_VPROC_LPW_CON0 */ + 0x0612, 0x0003, 0x0002,/* BUCK_VS1_HWM_CON0 */ + 0x0618, 0x0038, 0x0000,/* BUCK_VS1_HWM_CON1 */ + 0x061A, 0x0001, 0x0001,/* BUCK_VS1_EN_CON0 */ + 0x0626, 0x0100, 0x0100,/* BUCK_VS1_LPW_CON0 */ + 0x0628, 0x0003, 0x0002,/* BUCK_VCORE_HWM_CON0 */ + 0x062A, 0x0038, 0x0000,/* BUCK_VCORE_HWM_CON1 */ + 0x062C, 0x0001, 0x0001,/* BUCK_VCORE_EN_CON0 */ + 0x0638, 0x0100, 0x0100,/* BUCK_VCORE_LPW_CON0 */ + 0x063A, 0x0001, 0x0000,/* BUCK_VCORE2_HWM_CON0 */ + 0x063E, 0x0001, 0x0000,/* BUCK_VCORE2_EN_CON0 */ + 0x064C, 0x0001, 0x0000,/* BUCK_VPA_EN_CON0 */ + 0x0A06, 0x0010, 0x0010,/* LDO_VTCXO24_SW_CON0 */ + 0x0A0E, 0x000A, 0x0000,/* LDO_SHARE_VCN33_CON0 */ + 0x0A10, 0x000A, 0x0000,/* LDO_SHARE_VCN33_CON1 */ + 0x0A16, 0x0002, 0x0000,/* LDO_SHARE_VLDO28_CON0 */ + 0x0A18, 0x0002, 0x0000,/* LDO_SHARE_VLDO28_CON1 */ + 0x0A20, 0x003A, 0x0002,/* LDO_VSRAM_PROC_HWM_CON0 */ + 0x0A2C, 0x0100, 0x0100,/* LDO_VSRAM_PROC_LPW_CON0 */ + 0x0A30, 0x000A, 0x0000,/* LDO2_TREF_CON0 */ + 0x0A32, 0x3808, 0x0808,/* LDO3_VTCXO28_CON0 */ + 0x0A36, 0x3808, 0x0008,/* LDO3_VTCXO24_CON0 */ + 0x0A3A, 0x00EE, 0x0006,/* LDO3_VXO22_CON0 */ + 0x0A3E, 0x3808, 0x0808,/* LDO3_VRF18_CON0 */ + 0x0A42, 0x3808, 0x0808,/* LDO3_VRF12_CON0 */ + 0x0A48, 0x000A, 0x0000,/* LDO3_VCN28_CON0 */ + 0x0A4C, 0x000A, 0x0000,/* LDO3_VCN18_CON0 */ + 0x0A50, 0x0002, 0x0000,/* LDO0_VCAMA_CON0 */ + 0x0A54, 0x0002, 0x0000,/* LDO0_VCAMIO_CON0 */ + 0x0A58, 0x0002, 0x0000,/* LDO0_VCAMD_CON0 */ + 0x0A5C, 0x00EE, 0x0006,/* LDO3_VAUX18_CON0 */ + 0x0A60, 0x00EE, 0x0006,/* LDO3_VAUD28_CON0 */ + 0x0A64, 0x00EE, 0x0006,/* LDO3_VSRAM_PROC_CON0 */ + 0x0A68, 0x00E6, 0x0006,/* LDO1_VDRAM_CON0 */ + 0x0A6E, 0x0002, 0x0000,/* LDO1_VSIM1_CON0 */ + 0x0A72, 0x0002, 0x0000,/* LDO1_VSIM2_CON0 */ + 0x0A76, 0x00E6, 0x0006,/* LDO1_VIO28_CON0 */ + 0x0A7A, 0x0002, 0x0000,/* LDO1_VMC_CON0 */ + 0x0A80, 0x0002, 0x0000,/* LDO1_VMCH_CON0 */ + 0x0A86, 0x00E6, 0x0006,/* LDO1_VUSB33_CON0 */ + 0x0A8A, 0x0002, 0x0000,/* LDO1_VEMC33_CON0 */ + 0x0A90, 0x00E6, 0x0006,/* LDO1_VIO18_CON0 */ + 0x0A94, 0x0002, 0x0000,/* LDO0_VIBR_CON0 */ + 0x0CA4, 0x0001, 0x0000,/* FGADC_CON0 */ + 0x0D02, 0x0002, 0x0002,/* AUDDEC_ANA_CON8 */ + 0x0F5A, 0x0001, 0x0000 /* ACCDET_CON1 */ +}; + +const unsigned int *MT6353_PMIC_REG_gs_flightmode_suspend_mode = MT6353_PMIC_REG_gs_flightmode_suspend_mode_data; + +unsigned int MT6353_PMIC_REG_gs_flightmode_suspend_mode_len = 192; diff --git a/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_array.h b/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_array.h new file mode 100644 index 0000000000000000000000000000000000000000..6111f506c915ccad4518ef19b09cebc75c0aa086 --- /dev/null +++ b/drivers/misc/mediatek/power_gs/mt6755/mt_power_gs_array.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#if defined CONFIG_MTK_PMIC_CHIP_MT6353 + +extern const unsigned int *MT6353_PMIC_REG_gs_flightmode_suspend_mode; +extern unsigned int MT6353_PMIC_REG_gs_flightmode_suspend_mode_len; +extern const unsigned int *MT6353_PMIC_REG_gs_early_suspend_deep_idle_mode; +extern unsigned int MT6353_PMIC_REG_gs_early_suspend_deep_idle_mode_len; + +#else + +extern const unsigned int *MT6351_PMIC_REG_gs_flightmode_suspend_mode; +extern unsigned int MT6351_PMIC_REG_gs_flightmode_suspend_mode_len; +extern const unsigned int *MT6351_PMIC_REG_gs_early_suspend_deep_idle_mode; +extern unsigned int MT6351_PMIC_REG_gs_early_suspend_deep_idle_mode_len; + +#endif diff --git a/drivers/misc/mediatek/pwm/mt6755/Makefile b/drivers/misc/mediatek/pwm/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..24f4f350bd7a4fe365299ccdc032feeb48a65169 --- /dev/null +++ b/drivers/misc/mediatek/pwm/mt6755/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-$(CONFIG_MTK_PWM) := mt_pwm_hal.o diff --git a/drivers/misc/mediatek/pwm/mt6755/mt_pwm_hal.c b/drivers/misc/mediatek/pwm/mt6755/mt_pwm_hal.c new file mode 100644 index 0000000000000000000000000000000000000000..59e5b6cec8671c975da72afd20cd7161256c9246 --- /dev/null +++ b/drivers/misc/mediatek/pwm/mt6755/mt_pwm_hal.c @@ -0,0 +1,569 @@ +/******************************************************************************* +* mt_pwm.c PWM Drvier +* +* Copyright (c) 2012, Media Teck.inc +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public Licence, +* version 2, as publish by the Free Software Foundation. +* +* This program is distributed and in hope it will be useful, but WITHOUT +* ANY WARRNTY; without even the implied warranty of MERCHANTABITLITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ + +#include + +#include +#include +#include +#if !defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif + + +/********************************** +* Global data +***********************************/ +enum { + PWM_CON, + PWM_HDURATION, + PWM_LDURATION, + PWM_GDURATION, + PWM_BUF0_BASE_ADDR, + PWM_BUF0_SIZE, + PWM_BUF1_BASE_ADDR, + PWM_BUF1_SIZE, + PWM_SEND_DATA0, + PWM_SEND_DATA1, + PWM_WAVE_NUM, + PWM_DATA_WIDTH, + PWM_THRESH, + PWM_SEND_WAVENUM, + PWM_VALID +} PWM_REG_OFF; + +#if defined(CONFIG_MTK_CLKMGR) +int pwm_power_id[] = { + MT_CG_INFRA_PWM1, + MT_CG_INFRA_PWM2, + MT_CG_INFRA_PWM3, + MT_CG_INFRA_PWM4, + MT_CG_INFRA_PWM_HCLK, + MT_CG_PERI_PWM + }; + +#define PWM_CG 5 + +#endif +#ifdef CONFIG_OF +unsigned long PWM_register[PWM_NUM] = {}; +#else +unsigned long PWM_register[PWM_NUM] = { + (PWM_BASE+0x0010), /* PWM1 register base, 15 registers */ + (PWM_BASE+0x0050), /* PWM2 register base 15 registers */ + (PWM_BASE+0x0090), /* PWM3 register base 15 registers */ + (PWM_BASE+0x00d0), /* PWM4 register base 13 registers */ +}; +#endif +/**************************************************************/ + +#if !defined(CONFIG_MTK_CLKMGR) +enum { + PWM1_CLK, + PWM2_CLK, + PWM3_CLK, + PWM4_CLK, + PWM_HCLK_CLK, + PWM_CLK, + PWM_CLK_NUM, +}; + +const char *pwm_clk_name[] = { + "PWM1-main", "PWM2-main", "PWM3-main", "PWM4-main", "PWM-HCLK-main", "PWM-main" +}; + +struct clk *pwm_clk[PWM_CLK_NUM]; + +void mt_pwm_power_on_hal(u32 pwm_no, bool pmic_pad, unsigned long *power_flag) +{ + int clk_en_ret; + + if (0 == (*power_flag)) { + pr_debug("[PWM][CCF]enable clk_pwm_main:%p\n", pwm_clk[PWM_CLK]); + clk_en_ret = clk_prepare_enable(pwm_clk[PWM_CLK]); + pr_debug("[PWM][CCF]enable clk_pwm_hclk:%p\n", pwm_clk[PWM_HCLK_CLK]); + clk_en_ret = clk_prepare_enable(pwm_clk[PWM_HCLK_CLK]); + set_bit(PWM_CLK_NUM, power_flag); + } + if (!test_bit(pwm_no, power_flag)) { + pr_debug("[PWM][CCF]enable clk_pwm_num:%p\n", pwm_clk[pwm_no]); + clk_en_ret = clk_prepare_enable(pwm_clk[pwm_no]); + if (clk_en_ret) { + pr_err("[PWM][CCF]enable clk_pwm_num failed. ret:%d, clk_pwm_num:%p\n", + clk_en_ret, pwm_clk[pwm_no]); + } + set_bit(pwm_no, power_flag); + } +} + +void mt_pwm_power_off_hal(u32 pwm_no, bool pmic_pad, unsigned long *power_flag) +{ + if (test_bit(pwm_no, power_flag)) { + pr_debug("[PWM][CCF]disable clk_pwm_num:%p\n", pwm_clk[pwm_no]); + clk_disable_unprepare(pwm_clk[pwm_no]); + clear_bit(pwm_no, power_flag); + } + if (BIT(PWM_CLK_NUM) == (*power_flag)) { + pr_debug("[PWM][CCF]disable clk_pwm_hclk:%p\n", pwm_clk[PWM_HCLK_CLK]); + clk_disable_unprepare(pwm_clk[PWM_HCLK_CLK]); + pr_debug("[PWM][CCF]disable clk_pwm_main:%p\n", pwm_clk[PWM_CLK]); + clk_disable_unprepare(pwm_clk[PWM_CLK]); + clear_bit(PWM_CLK_NUM, power_flag); + } +} + +#else +void mt_pwm_power_on_hal(u32 pwm_no, bool pmic_pad, unsigned long *power_flag) +{ + if (0 == (*power_flag)) { + PWMDBG("enable_clock: main\n"); + enable_clock(pwm_power_id[PWM_CG], "PWM"); + set_bit(PWM_CG, power_flag); + } + if (!test_bit(pwm_no, power_flag)) { + PWMDBG("enable_clock: %d\n", pwm_no); + + enable_clock(pwm_power_id[pwm_no], "PWM"); + + set_bit(pwm_no, power_flag); + PWMDBG("enable_clock PWM%d\n", pwm_no+1); + } +} + +void mt_pwm_power_off_hal(u32 pwm_no, bool pmic_pad, unsigned long *power_flag) +{ + if (test_bit(pwm_no, power_flag)) { + PWMDBG("disable_clock: %d\n", pwm_no); + disable_clock(pwm_power_id[pwm_no], "PWM"); + clear_bit(pwm_no, power_flag); + PWMDBG("disable_clock PWM%d\n", pwm_no+1); + } + if (BIT(PWM_CG) == (*power_flag)) { + PWMDBG("disable_clock: main\n"); + disable_clock(pwm_power_id[PWM_CG], "PWM"); + clear_bit(PWM_CG, power_flag); + } +} +#endif + +void mt_pwm_init_power_flag(unsigned long *power_flag) +{ +#ifdef CONFIG_OF + PWM_register[PWM1] = (unsigned long)pwm_base + 0x0010; + PWM_register[PWM2] = (unsigned long)pwm_base + 0x0050; + PWM_register[PWM3] = (unsigned long)pwm_base + 0x0090; + PWM_register[PWM4] = (unsigned long)pwm_base + 0x00d0; +#endif +} + +s32 mt_pwm_sel_pmic_hal(u32 pwm_no) +{ + PWMDBG("mt_pwm_sel_pmic\n"); + return -EINVALID; +} + +s32 mt_pwm_sel_ap_hal(u32 pwm_no) +{ + PWMDBG("mt_pwm_sel_ap\n"); + return -EINVALID; +} + +void mt_set_pwm_enable_hal(u32 pwm_no) +{ + SETREG32(PWM_ENABLE, 1 << pwm_no); +} + +void mt_set_pwm_disable_hal(u32 pwm_no) +{ + CLRREG32(PWM_ENABLE, 1 << pwm_no); +} + +void mt_set_pwm_enable_seqmode_hal(void) +{ +} + +void mt_set_pwm_disable_seqmode_hal(void) +{ +} + +s32 mt_set_pwm_test_sel_hal(u32 val) +{ + return 0; +} + +void mt_set_pwm_clk_hal(u32 pwm_no, u32 clksrc, u32 div) +{ + unsigned long reg_con; + + reg_con = PWM_register[pwm_no] + 4 * PWM_CON; + MASKREG32(reg_con, PWM_CON_CLKDIV_MASK, div); + if ((clksrc & 0x80000000) != 0) { + clksrc &= ~(0x80000000); + if (clksrc == CLK_BLOCK_BY_1625_OR_32K) { /* old mode: 26M/1625 = 16KHz */ + CLRREG32(reg_con, 1 << PWM_CON_CLKSEL_OLD_OFFSET); /* bit 4: 0 */ + SETREG32(reg_con, 1 << PWM_CON_CLKSEL_OFFSET); /* bit 3: 1 */ + } else { /* old mode 32k clk */ + SETREG32(reg_con, 1 << PWM_CON_CLKSEL_OLD_OFFSET); + SETREG32(reg_con, 1 << PWM_CON_CLKSEL_OFFSET); + } + } else { + CLRREG32(reg_con, 1 << PWM_CON_CLKSEL_OLD_OFFSET); + if (clksrc == CLK_BLOCK) + CLRREG32(reg_con, 1 << PWM_CON_CLKSEL_OFFSET); + else if (clksrc == CLK_BLOCK_BY_1625_OR_32K) + SETREG32(reg_con, 1 << PWM_CON_CLKSEL_OFFSET); + } +} + +s32 mt_get_pwm_clk_hal(u32 pwm_no) +{ + s32 clk, clksrc, clkdiv; + unsigned long reg_con, reg_val, reg_en; + + reg_con = PWM_register[pwm_no] + 4 * PWM_CON; + + reg_val = INREG32(reg_con); + reg_en = INREG32(PWM_ENABLE); + + if (((reg_val & PWM_CON_CLKSEL_MASK) >> PWM_CON_CLKSEL_OFFSET) == 1) + if (((reg_en & PWM_CON_OLD_MODE_MASK) >> PWM_CON_OLD_MODE_OFFSET) == 1) + clksrc = 32 * 1024; + else + clksrc = BLOCK_CLK; + else + clksrc = BLOCK_CLK / 1625; + + clkdiv = 2 << (reg_val & PWM_CON_CLKDIV_MASK); + if (clkdiv <= 0) { + PWMDBG("clkdiv less zero, not valid\n"); + return -ERROR; + } + + clk = clksrc / clkdiv; + PWMDBG("CLK is :%d\n", clk); + return clk; +} + +s32 mt_set_pwm_con_datasrc_hal(u32 pwm_no, u32 val) +{ + unsigned long reg_con; + + reg_con = PWM_register[pwm_no] + 4 * PWM_CON; + if (val == PWM_FIFO) + CLRREG32(reg_con, 1 << PWM_CON_SRCSEL_OFFSET); + else if (val == MEMORY) + SETREG32(reg_con, 1 << PWM_CON_SRCSEL_OFFSET); + else + return 1; + return 0; +} + +s32 mt_set_pwm_con_mode_hal(u32 pwm_no, u32 val) +{ + unsigned long reg_con; + + reg_con = PWM_register[pwm_no] + 4 * PWM_CON; + if (val == PERIOD) + CLRREG32(reg_con, 1 << PWM_CON_MODE_OFFSET); + else if (val == RAND) + SETREG32(reg_con, 1 << PWM_CON_MODE_OFFSET); + else + return 1; + return 0; +} + +s32 mt_set_pwm_con_idleval_hal(u32 pwm_no, uint16_t val) +{ + unsigned long reg_con; + + reg_con = PWM_register[pwm_no] + 4 * PWM_CON; + if (val == IDLE_TRUE) + SETREG32(reg_con, 1 << PWM_CON_IDLE_VALUE_OFFSET); + else if (val == IDLE_FALSE) + CLRREG32(reg_con, 1 << PWM_CON_IDLE_VALUE_OFFSET); + else + return 1; + return 0; +} + +s32 mt_set_pwm_con_guardval_hal(u32 pwm_no, uint16_t val) +{ + unsigned long reg_con; + + reg_con = PWM_register[pwm_no] + 4 * PWM_CON; + if (val == GUARD_TRUE) + SETREG32(reg_con, 1 << PWM_CON_GUARD_VALUE_OFFSET); + else if (val == GUARD_FALSE) + CLRREG32(reg_con, 1 << PWM_CON_GUARD_VALUE_OFFSET); + else + return 1; + return 0; +} + +void mt_set_pwm_con_stpbit_hal(u32 pwm_no, u32 stpbit, u32 srcsel) +{ + unsigned long reg_con; + + reg_con = PWM_register[pwm_no] + 4 * PWM_CON; + if (srcsel == PWM_FIFO) + MASKREG32(reg_con, PWM_CON_STOP_BITS_MASK, stpbit << PWM_CON_STOP_BITS_OFFSET); + if (srcsel == MEMORY) + MASKREG32(reg_con, PWM_CON_STOP_BITS_MASK & (0x1f << PWM_CON_STOP_BITS_OFFSET), + stpbit << PWM_CON_STOP_BITS_OFFSET); +} + +s32 mt_set_pwm_con_oldmode_hal(u32 pwm_no, u32 val) +{ + unsigned long reg_con; + + reg_con = PWM_register[pwm_no] + 4 * PWM_CON; + if (val == OLDMODE_DISABLE) + CLRREG32(reg_con, 1 << PWM_CON_OLD_MODE_OFFSET); + else if (val == OLDMODE_ENABLE) + SETREG32(reg_con, 1 << PWM_CON_OLD_MODE_OFFSET); + else + return 1; + return 0; +} + +void mt_set_pwm_HiDur_hal(u32 pwm_no, uint16_t DurVal) +{ /* only low 16 bits are valid */ + unsigned long reg_HiDur; + + reg_HiDur = PWM_register[pwm_no] + 4 * PWM_HDURATION; + OUTREG32(reg_HiDur, DurVal); +} + +void mt_set_pwm_LowDur_hal(u32 pwm_no, uint16_t DurVal) +{ + unsigned long reg_LowDur; + + reg_LowDur = PWM_register[pwm_no] + 4 * PWM_LDURATION; + OUTREG32(reg_LowDur, DurVal); +} + +void mt_set_pwm_GuardDur_hal(u32 pwm_no, uint16_t DurVal) +{ + unsigned long reg_GuardDur; + + reg_GuardDur = PWM_register[pwm_no] + 4 * PWM_GDURATION; + OUTREG32(reg_GuardDur, DurVal); +} + +void mt_set_pwm_send_data0_hal(u32 pwm_no, u32 data) +{ + unsigned long reg_data0; + + reg_data0 = PWM_register[pwm_no] + 4 * PWM_SEND_DATA0; + OUTREG32(reg_data0, data); +} + +void mt_set_pwm_send_data1_hal(u32 pwm_no, u32 data) +{ + unsigned long reg_data1; + + reg_data1 = PWM_register[pwm_no] + 4 * PWM_SEND_DATA1; + OUTREG32(reg_data1, data); +} + +void mt_set_pwm_wave_num_hal(u32 pwm_no, uint16_t num) +{ + unsigned long reg_wave_num; + + reg_wave_num = PWM_register[pwm_no] + 4 * PWM_WAVE_NUM; + OUTREG32(reg_wave_num, num); +} + +void mt_set_pwm_data_width_hal(u32 pwm_no, uint16_t width) +{ + unsigned long reg_data_width; + + reg_data_width = PWM_register[pwm_no] + 4 * PWM_DATA_WIDTH; + OUTREG32(reg_data_width, width); +} + +void mt_set_pwm_thresh_hal(u32 pwm_no, uint16_t thresh) +{ + unsigned long reg_thresh; + + reg_thresh = PWM_register[pwm_no] + 4 * PWM_THRESH; + OUTREG32(reg_thresh, thresh); +} + +s32 mt_get_pwm_send_wavenum_hal(u32 pwm_no) +{ + unsigned long reg_send_wavenum; + + reg_send_wavenum = PWM_register[pwm_no] + 4 * PWM_SEND_WAVENUM; + return INREG32(reg_send_wavenum); +} + +void mt_set_intr_enable_hal(u32 pwm_intr_enable_bit) +{ + SETREG32(PWM_INT_ENABLE, 1 << pwm_intr_enable_bit); +} + +s32 mt_get_intr_status_hal(u32 pwm_intr_status_bit) +{ + int ret; + + ret = INREG32(PWM_INT_STATUS); + ret = (ret >> pwm_intr_status_bit) & 0x01; + return ret; +} + +void mt_set_intr_ack_hal(u32 pwm_intr_ack_bit) +{ + SETREG32(PWM_INT_ACK, 1 << pwm_intr_ack_bit); +} + +void mt_set_pwm_buf0_addr_hal(u32 pwm_no, dma_addr_t addr) +{ + unsigned long reg_buff0_addr; + + /*pr_debug("[PWM]buf0 addr:%p\n", addr);*/ + + reg_buff0_addr = PWM_register[pwm_no] + 4 * PWM_BUF0_BASE_ADDR; + /*OUTREG32(reg_buff0_addr, addr);*/ + /*OUTREG32_DMA(reg_buff0_addr, addr);*/ + OUTREG32(reg_buff0_addr, (dma_addr_t)addr); +} + +void mt_set_pwm_buf0_size_hal(u32 pwm_no, uint16_t size) +{ + unsigned long reg_buff0_size; + + reg_buff0_size = PWM_register[pwm_no] + 4 * PWM_BUF0_SIZE; + OUTREG32(reg_buff0_size, size); +} + +void mt_pwm_dump_regs_hal(void) +{ + int i; + unsigned long reg_val; + + reg_val = INREG32(PWM_ENABLE); + PWMMSG("\r\n[PWM_ENABLE is:%lx]\n\r ", reg_val); + reg_val = INREG32(PWM_CK_26M_SEL); + PWMMSG("\r\n[PWM_26M_SEL is:%lx]\n\r ", reg_val); + /*PWMDBG("peri pdn0 clock: 0x%x\n", INREG32(INFRA_PDN_STA0));*/ + + for (i = PWM1; i < PWM_MAX; i++) { + reg_val = INREG32(PWM_register[i] + 4 * PWM_CON); + PWMMSG("\r\n[PWM%d_CON is:%lx]\r\n", i + 1, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_HDURATION); + PWMMSG("[PWM%d_HDURATION is:%lx]\r\n", i + 1, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_LDURATION); + PWMMSG("[PWM%d_LDURATION is:%lx]\r\n", i + 1, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_GDURATION); + PWMMSG("[PWM%d_GDURATION is:%lx]\r\n", i + 1, reg_val); + + reg_val = INREG32(PWM_register[i] + 4 * PWM_BUF0_BASE_ADDR); + PWMMSG("\r\n[PWM%d_BUF0_BASE_ADDR is:%lx]\r\n", i, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_BUF0_SIZE); + PWMMSG("\r\n[PWM%d_BUF0_SIZE is:%lx]\r\n", i, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_BUF1_BASE_ADDR); + PWMMSG("\r\n[PWM%d_BUF1_BASE_ADDR is:%lx]\r\n", i, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_BUF1_SIZE); + PWMMSG("\r\n[PWM%d_BUF1_SIZE is:%lx]\r\n", i + 1, reg_val); + + reg_val = INREG32(PWM_register[i] + 4 * PWM_SEND_DATA0); + PWMMSG("[PWM%d_SEND_DATA0 is:%lx]\r\n", i + 1, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_SEND_DATA1); + PWMMSG("[PWM%d_PWM_SEND_DATA1 is:%lx]\r\n", i + 1, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_WAVE_NUM); + PWMMSG("[PWM%d_WAVE_NUM is:%lx]\r\n", i + 1, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_DATA_WIDTH); + PWMMSG("[PWM%d_WIDTH is:%lx]\r\n", i + 1, reg_val); + + reg_val = INREG32(PWM_register[i] + 4 * PWM_THRESH); + PWMMSG("[PWM%d_THRESH is:%lx]\r\n", i + 1, reg_val); + reg_val = INREG32(PWM_register[i] + 4 * PWM_SEND_WAVENUM); + PWMMSG("[PWM%d_SEND_WAVENUM is:%lx]\r\n", i + 1, reg_val); + + } +} + +void pwm_debug_store_hal(void) +{ + /* dump clock status */ + /*PWMDBG("peri pdn0 clock: 0x%x\n", INREG32(INFRA_PDN_STA0));*/ +} + +void pwm_debug_show_hal(void) +{ + mt_pwm_dump_regs_hal(); +} + +/*----------3dLCM support-----------*/ +/* + base pwm2, select pwm3&4&5 same as pwm2 or inversion of pwm2 + */ +void mt_set_pwm_3dlcm_enable_hal(u8 enable) +{ + SETREG32(PWM_3DLCM, 1 << PWM_3DLCM_ENABLE_OFFSET); +} + +/* + set "pwm_no" inversion of pwm base or not + */ +void mt_set_pwm_3dlcm_inv_hal(u32 pwm_no, u8 inv) +{ + /*set "pwm_no" as auxiliary first */ + SETREG32(PWM_3DLCM, 1 << (pwm_no + 16)); + + if (inv) + SETREG32(PWM_3DLCM, 1 << (pwm_no + 1)); + else + CLRREG32(PWM_3DLCM, 1 << (pwm_no + 1)); +} + +void mt_set_pwm_3dlcm_base_hal(u32 pwm_no) +{ + CLRREG32(PWM_3DLCM, 0x7F << 8); + SETREG32(PWM_3DLCM, 1 << (pwm_no + 8)); +} + +void mt_pwm_26M_clk_enable_hal(u32 enable) +{ + unsigned long reg_con; + + /* select 66M or 26M */ + reg_con = (unsigned long)PWM_CK_26M_SEL; + if (enable) + SETREG32(reg_con, 1 << PWM_CK_26M_SEL_OFFSET); + else + CLRREG32(reg_con, 1 << PWM_CK_26M_SEL_OFFSET); + +} + +#if !defined(CONFIG_MTK_CLKMGR) +int mt_get_pwm_clk_src(struct platform_device *pdev) +{ + int i; + + for (i = PWM1_CLK; i < PWM_CLK_NUM; i++) { + pwm_clk[i] = devm_clk_get(&pdev->dev, pwm_clk_name[i]); + pr_err("[PWM] get %s clock, %p\n", pwm_clk_name[i], pwm_clk[i]); + if (IS_ERR(pwm_clk[i])) { + PWMDBG("cannot get %s clock\n", pwm_clk_name[i]); + return PTR_ERR(pwm_clk[i]); + } + } + return 0; +} +#endif diff --git a/drivers/misc/mediatek/secmem/mt6755/secmem_plat.h b/drivers/misc/mediatek/secmem/mt6755/secmem_plat.h new file mode 100644 index 0000000000000000000000000000000000000000..5d06fe5255041a5e7a1299b052ecb7b0c1c9d29c --- /dev/null +++ b/drivers/misc/mediatek/secmem/mt6755/secmem_plat.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef SECMEM_PLATFORM_H +#define SECMEM_PLATFORM_H + +/* Enable the support of secure memory dump detail */ +#define SECMEM_DEBUG_DUMP + +/* Enable secure memory test interface */ +/* #define SECMEM_DEBUG_INTERFACE */ + +/* Enable secure memory API */ +#define SECMEM_KERNEL_API + +#endif /* end of SECMEM_PLATFORM_H */ diff --git a/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP.c b/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP.c new file mode 100644 index 0000000000000000000000000000000000000000..93a5453a7cb1cd877114d834eb9b677591660723 --- /dev/null +++ b/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP.c @@ -0,0 +1,607 @@ +/* +* Copyright (C) 2015 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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. +* +* You should have received a copy of the GNU General Public License +* along with this program. +* If not, see . +*/ + +/******************************************************************************* + * + * Filename: + * --------- + * AudDrv_Kernelc + * + * Project: + * -------- + * Audio smart pa Function + * + * Description: + * ------------ + * Audio register + * + * Author: + * ------- + * Chipeng Chang + * + *------------------------------------------------------------------------------ + * + * + *******************************************************************************/ + + +/***************************************************************************** + * C O M P I L E R F L A G S + *****************************************************************************/ + + +/***************************************************************************** + * E X T E R N A L R E F E R E N C E S + *****************************************************************************/ +#include "AudDrv_NXP.h" +#include + +#define TFA_I2C_CHANNEL (3) + +#ifdef CONFIG_MTK_NXP_TFA9890 +#define ECODEC_SLAVE_ADDR_WRITE 0x68 +#define ECODEC_SLAVE_ADDR_READ 0x69 +#else +#define ECODEC_SLAVE_ADDR_WRITE 0x6c +#define ECODEC_SLAVE_ADDR_READ 0x6d +#endif + +#define I2C_MASTER_CLOCK 400 +#define NXPEXTSPK_I2C_DEVNAME "mtksmartpa" + +/***************************************************************************** +* DEFINE AND CONSTANT +****************************************************************************** +*/ + +#define AUDDRV_NXPSPK_NAME "mtksmartpa" +#define AUDDRV_AUTHOR "MediaTek WCX" +#define RW_BUFFER_LENGTH (256) + +#define smart_set_gpio(x) (x|0x80000000) + +/***************************************************************************** +* V A R I A B L E D E L A R A T I O N +*******************************************************************************/ + +/* I2C variable */ +static struct i2c_client *new_client; +static char WriteBuffer[RW_BUFFER_LENGTH]; +static char ReadBuffer[RW_BUFFER_LENGTH]; + +static void *TfaI2CDMABuf_va; +static dma_addr_t TfaI2CDMABuf_pa; + +static int AudDrv_nxpspk_open(struct inode *inode, struct file *fp); +static long AudDrv_nxpspk_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); +static ssize_t AudDrv_nxpspk_read(struct file *fp, char __user *data, size_t count, loff_t *offset); +static ssize_t AudDrv_nxpspk_write(struct file *fp, const char __user *data, size_t count, loff_t *offset); + +static const struct file_operations AudDrv_nxpspk_fops = { + .owner = THIS_MODULE, + .open = AudDrv_nxpspk_open, + .unlocked_ioctl = AudDrv_nxpspk_ioctl, + .write = AudDrv_nxpspk_write, + .read = AudDrv_nxpspk_read, +}; + + +#ifdef CONFIG_OF +static unsigned int pin_ext_dac_rst, pin_ext_hp_en, pin_nxpspk_lrck, pin_nxpspk_bck, pin_nxpspk_datai, pin_nxpspk_datao; +static unsigned int pin_ext_dac_rst_mode, pin_ext_hp_en_mode, pin_nxpspk_lrck_mode; +static unsigned int pin_nxpspk_bck_mode, pin_nxpspk_datai_mode, pin_nxpspk_datao_mode; + +static int smartpa_parse_gpio(void) +{ + struct device_node *node = NULL; + + pr_debug("+%s\n", __func__); + node = of_find_compatible_node(NULL, NULL, "mediatek,mtksmartpa"); + if (node) { + if (of_property_read_u32_index(node, "aud_ext_dacrst_gpio", 0, &pin_ext_dac_rst)) + pr_debug("aud_ext_dacrst_gpio get pin fail!!!\n"); + + if (of_property_read_u32_index(node, "aud_ext_dacrst_gpio", 1, &pin_ext_dac_rst_mode)) + pr_debug("aud_ext_dacrst_gpio get pin_mode fail!!!\n"); + + pr_debug("pin_ext_dac_rst = %u pin_ext_dac_rst_mode = %u\n", pin_ext_dac_rst, pin_ext_dac_rst_mode); + + if (of_property_read_u32_index(node, "aud_ext_hpen_gpio", 0, &pin_ext_hp_en)) + pr_debug("aud_ext_hpen_gpio get pin fail!!!\n"); + + if (of_property_read_u32_index(node, "aud_ext_hpen_gpio", 1, &pin_ext_hp_en_mode)) + pr_debug("aud_ext_hpen_gpio get pin_mode fail!!!\n"); + + pr_debug("pin_ext_hp_en = %u pin_ext_hp_en_mode = %u\n", pin_ext_hp_en, pin_ext_hp_en_mode); + + if (of_property_read_u32_index(node, "nxpws_gpio", 0, &pin_nxpspk_lrck)) + pr_debug("nxpws_gpio get pin fail!!!\n"); + + if (of_property_read_u32_index(node, "nxpws_gpio", 1, &pin_nxpspk_lrck_mode)) + pr_debug("nxpws_gpio get pin_mode fail!!!\n"); + + pr_debug("pin_nxpspk_lrck = %u pin_nxpspk_lrck_mode = %u\n", pin_nxpspk_lrck, pin_nxpspk_lrck_mode); + + if (of_property_read_u32_index(node, "nxpclk_gpio", 0, &pin_nxpspk_bck)) + pr_debug("nxpclk_gpio get pin fail!!!\n"); + + if (of_property_read_u32_index(node, "nxpclk_gpio", 1, &pin_nxpspk_bck_mode)) + pr_debug("nxpclk_gpio get pin_mode fail!!!\n"); + + pr_debug("pin_nxpspk_bck = %u pin_nxpspk_bck_mode = %u\n", pin_nxpspk_bck, pin_nxpspk_bck_mode); + + if (of_property_read_u32_index(node, "nxpdatai_gpio", 0, &pin_nxpspk_datai)) + pr_debug("nxpdatai_gpio get pin fail!!!\n"); + + if (of_property_read_u32_index(node, "nxpdatai_gpio", 1, &pin_nxpspk_datai_mode)) + pr_debug("nxpdatai_gpio get pin_mode fail!!!\n"); + + pr_debug("pin_nxpspk_bck = %u pin_nxpspk_bck_mode = %u\n", pin_nxpspk_bck, pin_nxpspk_bck_mode); + + if (of_property_read_u32_index(node, "nxpdatao_gpio", 0, &pin_nxpspk_datao)) + pr_debug("nxpdatao_gpio get pin fail!!!\n"); + + if (of_property_read_u32_index(node, "nxpdatao_gpio", 1, &pin_nxpspk_datao_mode)) + pr_debug("nxpdatao_gpio get pin_mode fail!!!\n"); + + pr_debug("pin_nxpspk_datao = %u pin_nxpspk_datao_mode = %u\n", pin_nxpspk_datao, pin_nxpspk_datao_mode); + } else { + pr_debug("Auddrv_OF_ParseGPIO node NULL!!!\n"); + return -1; + } + pr_debug("-%s\n", __func__); + return 0; +} + +#endif + + +/* new I2C register method */ +const struct i2c_device_id nxpExt_i2c_id[] = { {NXPEXTSPK_I2C_DEVNAME, 0}, {} }; +struct i2c_board_info __initdata nxpExt_dev = { I2C_BOARD_INFO(NXPEXTSPK_I2C_DEVNAME, 0x36) }; + +/* function declration */ +static int NXPExtSpk_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int NXPExtSpk_i2c_remove(struct i2c_client *client); +static int AudDrv_NXPSpk_Init(void); +static bool NXPExtSpk_Register(void); +static int NXPExtSpk_registerI2C(void); + +static int NXPExtSpk_i2c_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + strcpy(info->type, NXPEXTSPK_I2C_DEVNAME); + return 0; +} + +static int NXPExtSpk_i2c_suspend(struct i2c_client *client, pm_message_t msg) +{ + return 0; +} + +static int NXPExtSpk_i2c_resume(struct i2c_client *client) +{ + return 0; +} + +/* i2c driver */ +static struct i2c_driver NXPExtSpk_i2c_driver = { + .probe = NXPExtSpk_i2c_probe, + .remove = NXPExtSpk_i2c_remove, + .detect = NXPExtSpk_i2c_detect, + .suspend = NXPExtSpk_i2c_suspend, + .resume = NXPExtSpk_i2c_resume, + .id_table = nxpExt_i2c_id, + .driver = { + .name = NXPEXTSPK_I2C_DEVNAME, + }, +}; + + +static int NXPExtSpk_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + new_client = client; + new_client->timing = 400; + + pr_debug("NXPExtSpk_i2c_probe\n"); + +#ifdef CONFIG_MTK_NXP_TFA9890 + mt_set_gpio_mode(GPIO_AUD_EXTDAC_RST_PIN/*GPIO130*/, GPIO_MODE_00); + mt_set_gpio_out(GPIO_AUD_EXTDAC_RST_PIN/*GPIO130*/, GPIO_OUT_ZERO); + usleep_range(2); + mt_set_gpio_out(GPIO_AUD_EXTDAC_RST_PIN/*GPIO130*/, GPIO_OUT_ONE); + usleep_range(2); + mt_set_gpio_out(GPIO_AUD_EXTDAC_RST_PIN/*GPIO130*/, GPIO_OUT_ZERO); + usleep_range(10); +#endif + + TfaI2CDMABuf_va = dma_alloc_coherent(NULL, 4096, &TfaI2CDMABuf_pa, GFP_KERNEL); + if (TfaI2CDMABuf_va == NULL) { + NXP_ERROR("dma_alloc_coherent error\n"); + NXP_INFO("i2c_probe failed\n"); + return -1; + } + NXP_INFO("i2c_probe success\n"); + return 0; +} + +static int NXPExtSpk_i2c_remove(struct i2c_client *client) +{ + new_client = NULL; + i2c_unregister_device(client); + i2c_del_driver(&NXPExtSpk_i2c_driver); + if (TfaI2CDMABuf_va != NULL) { + dma_free_coherent(NULL, 4096, TfaI2CDMABuf_va, TfaI2CDMABuf_pa); + TfaI2CDMABuf_va = NULL; + TfaI2CDMABuf_pa = 0; + } + usleep_range(1); +#ifdef CONFIG_MTK_NXP_TFA9890 + mt_set_gpio_mode(GPIO_AUD_EXTHP_EN_PIN, GPIO_MODE_00); + mt_set_gpio_dir(GPIO_AUD_EXTHP_EN_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_AUD_EXTHP_EN_PIN, GPIO_OUT_ZERO); +#endif + return 0; +} + +/* read write implementation */ +/* read one register */ +/* +ssize_t NXPSpk_read_byte(u8 addr, u8 *returnData) +{ + char cmd_buf[1] = { 0x00 }; + char readData = 0; + int ret = 0; + + cmd_buf[0] = addr; + if (!new_client) { + pr_debug("NXPSpk_read_byte I2C client not initialized!!"); + return -1; + } + ret = i2c_master_send(new_client, &cmd_buf[0], 1); + if (ret < 0) { + pr_debug("NXPSpk_read_byte read sends command error!!\n"); + return -1; + } + ret = i2c_master_recv(new_client, &readData, 1); + if (ret < 0) { + pr_debug("NXPSpk_read_byte reads recv data error!!\n"); + return -1; + } + *returnData = readData; + return 0; +} +*/ + +/* write register */ +ssize_t NXPExt_write_byte(u8 addr, u8 writeData) +{ + char write_data[2] = { 0 }; + int ret = 0; + + if (new_client == NULL) { + pr_debug("I2C client not initialized!!"); + return -1; + } + write_data[0] = addr; /* ex. 0x01 */ + write_data[1] = writeData; + ret = i2c_master_send(new_client, write_data, 2); + if (ret < 0) { + pr_debug("write sends command error!!"); + return -1; + } + /* pr_debug("addr 0x%x data 0x%x\n", addr, writeData); */ + return 0; +} + +static int NXPExtSpk_registerI2C(void) +{ + pr_debug("NXPExtSpk_registerI2C\n"); + +#ifdef CONFIG_MTK_NXP_TFA9890 + mt_set_gpio_mode(GPIO_AUD_EXTHP_EN_PIN, GPIO_MODE_00); + mt_set_gpio_dir(GPIO_AUD_EXTHP_EN_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_AUD_EXTHP_EN_PIN, GPIO_OUT_ONE); + usleep_range(1); +#endif + + i2c_register_board_info(TFA_I2C_CHANNEL, &nxpExt_dev, 1); + if (i2c_add_driver(&NXPExtSpk_i2c_driver)) { + pr_debug("fail to add device into i2c"); + return -1; + } + return 0; +} + + +bool NXPExtSpk_Register(void) +{ + pr_debug("NXPExtSpk_Register\n"); + NXPExtSpk_registerI2C(); + return true; +} + +int AudDrv_NXPSpk_Init(void) +{ + pr_debug("Set GPIO for AFE I2S output to external DAC\n"); + mt_set_gpio_mode(smart_set_gpio(pin_nxpspk_lrck) , pin_nxpspk_lrck_mode); + mt_set_gpio_mode(smart_set_gpio(pin_nxpspk_bck), pin_nxpspk_bck_mode); + mt_set_gpio_mode(smart_set_gpio(pin_nxpspk_datai), pin_nxpspk_datai_mode); + mt_set_gpio_mode(smart_set_gpio(pin_nxpspk_datao), pin_nxpspk_datao_mode); + return 0; +} + +/***************************************************************************** + * FILE OPERATION FUNCTION + * AudDrv_nxpspk_ioctl + * + * DESCRIPTION + * IOCTL Msg handle + * + ***************************************************************************** + */ +static long AudDrv_nxpspk_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + switch (cmd) { + default: { + ret = -1; + break; + } + } + return ret; +} + +static int AudDrv_nxpspk_probe(struct platform_device *dev) +{ + int ret = 0; + + pr_debug("AudDrv_nxpspk_probe\n"); + if (ret < 0) + pr_debug("AudDrv_nxpspk_probe request_irq MT6582_AP_BT_CVSD_IRQ_LINE Fail\n"); + + smartpa_parse_gpio(); + NXPExtSpk_Register(); + AudDrv_NXPSpk_Init(); + + memset((void *)WriteBuffer, 0, RW_BUFFER_LENGTH); + memset((void *)ReadBuffer, 0, RW_BUFFER_LENGTH); + + pr_debug("-AudDrv_nxpspk_probe\n"); + return 0; +} + +static int AudDrv_nxpspk_open(struct inode *inode, struct file *fp) +{ + return 0; +} + +static int nxp_i2c_master_send(const struct i2c_client *client, const char *buf, int count) +{ + int ret; + struct i2c_adapter *adap = client->adapter; + struct i2c_msg msg; + + msg.timing = I2C_MASTER_CLOCK; + + if (count <= 8) + msg.addr = client->addr & I2C_MASK_FLAG; + else + msg.addr = client->addr & (I2C_MASK_FLAG|I2C_DMA_FLAG); + + msg.flags = client->flags & I2C_M_TEN; + + msg.len = count; + msg.buf = (char *)buf; + msg.ext_flag = client->ext_flag; + ret = i2c_transfer(adap, &msg, 1); + + /* + * If everything went ok (i.e. 1 msg transmitted), return #bytes + * transmitted, else error code. + */ + return (ret == 1) ? count : ret; +} + +static int nxp_i2c_master_recv(const struct i2c_client *client, char *buf, int count) +{ + struct i2c_adapter *adap = client->adapter; + struct i2c_msg msg; + int ret; + + msg.timing = I2C_MASTER_CLOCK; + msg.flags = client->flags & I2C_M_TEN; + msg.flags |= I2C_M_RD; + msg.len = count; + msg.ext_flag = client->ext_flag; + msg.buf = (char *)buf; + + if (count <= 8) + msg.addr = client->addr & I2C_MASK_FLAG; + else + msg.addr = client->addr & (I2C_MASK_FLAG|I2C_DMA_FLAG); + + ret = i2c_transfer(adap, &msg, 1); + + /* + * If everything went ok (i.e. 1 msg received), return #bytes received, + * else error code. + */ + return (ret == 1) ? count : ret; +} + +static ssize_t AudDrv_nxpspk_write(struct file *fp, const char __user *data, size_t count, loff_t *offset) + +{ + int i = 0; + int ret; + char *tmp; + char *TfaI2CDMABuf = (char *)TfaI2CDMABuf_va; + + tmp = kmalloc(count, GFP_KERNEL); + if (tmp == NULL) + return -ENOMEM; + if (copy_from_user(tmp, data, count)) { + kfree(tmp); + return -EFAULT; + } + + + for (i = 0; i < count; i++) + TfaI2CDMABuf[i] = tmp[i]; + + if (count <= 8) + ret = nxp_i2c_master_send(new_client, tmp, count); + else + ret = nxp_i2c_master_send(new_client, (char *)TfaI2CDMABuf_pa, count); + + kfree(tmp); + return ret; +} + +static ssize_t AudDrv_nxpspk_read(struct file *fp, char __user *data, size_t count, loff_t *offset) +{ + int i = 0; + char *tmp; + char *TfaI2CDMABuf = (char *)TfaI2CDMABuf_va; + int ret = 0; + + if (count > 8192) + count = 8192; + + tmp = kmalloc(count, GFP_KERNEL); + if (tmp == NULL) + return -ENOMEM; + + if (count <= 8) + ret = nxp_i2c_master_recv(new_client, tmp, count); + else { + ret = nxp_i2c_master_recv(new_client, (char *)TfaI2CDMABuf_pa, count); + for (i = 0; i < count; i++) + tmp[i] = TfaI2CDMABuf[i]; + } + + if (ret >= 0) + ret = copy_to_user(data, tmp, count) ? (-EFAULT) : ret; + kfree(tmp); + + return ret; +} + +/************************************************************************** + * STRUCT + * File Operations and misc device + * + **************************************************************************/ + +#ifdef CONFIG_MTK_NXP_TFA9890 +static struct miscdevice AudDrv_nxpspk_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "smartpa_i2c", + .fops = &AudDrv_nxpspk_fops, +}; +#else +static struct miscdevice AudDrv_nxpspk_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "nxpspk", + .fops = &AudDrv_nxpspk_fops, +}; +#endif + +/*************************************************************************** + * FUNCTION + * AudDrv_nxpspk_mod_init / AudDrv_nxpspk_mod_exit + * + * DESCRIPTION + * Module init and de-init (only be called when system boot up) + * + **************************************************************************/ + +#ifdef CONFIG_OF +static const struct of_device_id mtk_smart_pa_of_ids[] = { + { .compatible = "mediatek,mtksmartpa", }, + {} +}; +#endif + +static struct platform_driver AudDrv_nxpspk = { + .probe = AudDrv_nxpspk_probe, + .driver = { + .name = NXPEXTSPK_I2C_DEVNAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = mtk_smart_pa_of_ids, +#endif + }, +}; + +#ifndef CONFIG_OF +static struct platform_device *AudDrv_NXPSpk_dev; +#endif + +int AudDrv_nxpspk_mod_init(void) +{ + int ret = 0; + + pr_debug("+AudDrv_nxpspk_mod_init\n"); + +#ifndef CONFIG_OF + pr_debug("platform_device_alloc\n"); + AudDrv_NXPSpk_dev = platform_device_alloc("AudioMTKNXPSPK", -1); + if (!AudDrv_NXPSpk_dev) + return -ENOMEM; + + pr_debug("platform_device_add\n"); + + ret = platform_device_add(AudDrv_NXPSpk_dev); + if (ret != 0) { + platform_device_put(AudDrv_NXPSpk_dev); + return ret; + } +#endif + /* Register platform DRIVER */ + + ret = platform_driver_register(&AudDrv_nxpspk); + if (ret) { + pr_debug("AudDrv Fail:%d - Register DRIVER\n", ret); + return ret; + } + /* register MISC device */ + ret = misc_register(&AudDrv_nxpspk_device); + if (ret) { + pr_debug("AudDrv_nxpspk_mod_init misc_register Fail:%d\n", ret); + return ret; + } + + pr_debug("-AudDrv_nxpspk_mod_init\n"); + return 0; +} + +void AudDrv_nxpspk_mod_exit(void) +{ + pr_debug("+AudDrv_nxpspk_mod_exit\n"); + + pr_debug("-AudDrv_nxpspk_mod_exit\n"); +} + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(AUDDRV_NXPSPK_NAME); +MODULE_AUTHOR(AUDDRV_AUTHOR); + +module_init(AudDrv_nxpspk_mod_init); +module_exit(AudDrv_nxpspk_mod_exit); + diff --git a/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP.h b/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP.h new file mode 100644 index 0000000000000000000000000000000000000000..f3ff167f21d1b02912109da49a9e750a4483b922 --- /dev/null +++ b/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP.h @@ -0,0 +1,107 @@ +/* +* Copyright (C) 2015 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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. +* +* You should have received a copy of the GNU General Public License +* along with this program. +* If not, see . +*/ + +#ifndef AUDDRV_NXPSPK_H +#define AUDDRV_NXPSPK_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************** + * C O M P I L E R F L A G S + *****************************************************************************/ + + +/***************************************************************************** + * E X T E R N A L R E F E R E N C E S + *****************************************************************************/ + + +/***************************************************************************** + * D A T A T Y P E S + *****************************************************************************/ +static char const *const kAudioNXPSpkName = "/dev/nxpspk"; + + +typedef struct { + unsigned char data0; + unsigned char data1; + unsigned char data2; + unsigned char data3; +} Aud_Buffer_Control; + +extern int mt_set_gpio_mode(int pin, int mode); +extern int mt_set_gpio_dir(int pin, int mode); +extern int mt_set_gpio_out(int pin, int mode); + +/*below is control message*/ +#define AUD_NXP_IOC_MAGIC 'C' + +#define SET_NXP_REG _IOWR(AUD_NXP_IOC_MAGIC, 0x00, Aud_Buffer_Control*) +#define GET_NXP_REG _IOWR(AUD_NXP_IOC_MAGIC, 0x01, Aud_Buffer_Control*) + +/* Pre-defined definition */ +#define NXP_DEBUG_ON +#define NXP_DEBUG_ARRAY_ON +#define NXP_DEBUG_FUNC_ON + + +/*Log define*/ +#define NXP_INFO(fmt, arg...) pr_debug("<<-NXP-INFO->> "fmt"\n", ##arg) +#define NXP_ERROR(fmt, arg...) pr_debug("<<-NXP-ERROR->> "fmt"\n", ##arg) + +/****************************PART4:UPDATE define*******************************/ +#define TFA9890_DEVICEID 0x0080 + +/*error no*/ +#define ERROR_NO_FILE 2 /*ENOENT*/ +#define ERROR_FILE_READ 23 /*ENFILE*/ +#define ERROR_FILE_TYPE 21 /*EISDIR*/ +#define ERROR_GPIO_REQUEST 4 /*EINTR*/ +#define ERROR_I2C_TRANSFER 5 /*EIO*/ +#define ERROR_NO_RESPONSE 16 /*EBUSY*/ +#define ERROR_TIMEOUT 110 /*ETIMEDOUT*/ + +#endif + + diff --git a/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP_ioctl.h b/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP_ioctl.h new file mode 100644 index 0000000000000000000000000000000000000000..be2ae45ca70ec86e5bfb09e2934f0c386c74ff10 --- /dev/null +++ b/drivers/misc/mediatek/smartpa/mt6755/AudDrv_NXP_ioctl.h @@ -0,0 +1,47 @@ +/* +* Copyright (C) 2015 MediaTek Inc. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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. +* +* You should have received a copy of the GNU General Public License +* along with this program. +* If not, see . +*/ + +#ifndef _AUDDRV_NXP_IOCTL_MSG_H +#define _AUDDRV_NXP_IOCTL_MSG_H + + +/***************************************************************************** +* C O M P I L E R F L A G S +****************************************************************************** +*/ + + +/***************************************************************************** +* C O N S T A N T S +****************************************************************************** +*/ + +/* below is control message */ +#define AUD_DRV_NXP_IOC_MAGIC 'C' + +/***************************************************************************** +* D A T A T Y P E S +****************************************************************************** +*/ + +/***************************************************************************** +* F U N C T I O N D E F I N I T I O N +****************************************************************************** +*/ + + +#endif diff --git a/drivers/misc/mediatek/smartpa/mt6755/Makefile b/drivers/misc/mediatek/smartpa/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..39ae7a273cb11b16134bb19081b62f05ad874c41 --- /dev/null +++ b/drivers/misc/mediatek/smartpa/mt6755/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MTK_SOUND) += AudDrv_NXP.o \ No newline at end of file diff --git a/drivers/misc/mediatek/systracker/mt6755/Makefile b/drivers/misc/mediatek/systracker/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d3092a5a1652e209451f21940c46af7ccae5adfb --- /dev/null +++ b/drivers/misc/mediatek/systracker/mt6755/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y := systracker_platform.o diff --git a/drivers/misc/mediatek/systracker/mt6755/systracker_platform.c b/drivers/misc/mediatek/systracker/mt6755/systracker_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..2e17d945eb285f75fd16b6667d600d3ab3fd15ba --- /dev/null +++ b/drivers/misc/mediatek/systracker/mt6755/systracker_platform.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../systracker_v2.h" + +#ifdef SYSTRACKER_TEST_SUIT +void __iomem *p1; +void __iomem *mm_area1; +#endif + +#ifdef CONFIG_ARM64 +static int read_timeout_handler(unsigned long addr, + unsigned int fsr, struct pt_regs *regs) +{ + int i = 0; + +#ifdef SYSTRACKER_TEST_SUIT + systracker_test_cleanup(); +#endif + + pr_err("%s:%d: read timeout\n", __func__, __LINE__); + aee_dump_backtrace(regs, NULL); + + if (readl(IOMEM(BUS_DBG_CON)) & + (BUS_DBG_CON_IRQ_AR_STA0|BUS_DBG_CON_IRQ_AR_STA1)) { + for (i = 0; i < BUS_DBG_NUM_TRACKER; i++) { + pr_err("AR_TRACKER Timeout Entry[%d]: ReadAddr:0x%x,", + i, + readl(IOMEM(BUS_DBG_AR_TRACK_L(i)))); + + pr_err("Length:0x%x, TransactionID:0x%x!\n", + readl(IOMEM(BUS_DBG_AR_TRACK_H(i))), + readl(IOMEM(BUS_DBG_AR_TRANS_TID(i)))); + } + } + + /* return -1 to indicate kernel go on its flow */ + return -1; +} + +static void write_timeout_handler(struct pt_regs *regs, void *priv) +{ + int i = 0; + +#ifdef SYSTRACKER_TEST_SUIT + systracker_test_cleanup(); +#endif + + pr_debug("%s:%d: write timeout\n", __func__, __LINE__); + aee_dump_backtrace(regs, NULL); + + if (readl(IOMEM(BUS_DBG_CON)) & + ((BUS_DBG_CON_IRQ_AW_STA0|BUS_DBG_CON_IRQ_AW_STA1))) { + for (i = 0; i < BUS_DBG_NUM_TRACKER; i++) { + pr_err("AW_TRACKER Timeout Entry[%d]: WriteAddr:0x%x, ", + i, + readl(IOMEM(BUS_DBG_AW_TRACK_L(i)))); + pr_err("Length:0x%x, TransactionID:0x%x!\n", + readl(IOMEM(BUS_DBG_AW_TRACK_H(i))), + readl(IOMEM(BUS_DBG_AW_TRANS_TID(i)))); + } + } +} + +static int systracker_platform_hook_fault(void) +{ + int ret = 0; + + /* We use ARM64's synchroneous external abort for read timeout */ + hook_fault_code(0x10, + read_timeout_handler, + SIGTRAP, + 0, + "Systracker debug exception"); + + /* for 64bit, we should register async abort handler */ + ret = register_async_abort_handler(write_timeout_handler, NULL); + if (ret) { + pr_warn("%s:%d: register_async_abort_handler failed\n", + __func__, + __LINE__); + return -1; + } + + return 0; +} +#else +int systracker_handler(unsigned long addr, + unsigned int fsr, + struct pt_regs *regs) +{ + int i; + +#ifdef SYSTRACKER_TEST_SUIT + writel(readl(p1) & ~(0x1 << 6), p1); +#endif + + aee_dump_backtrace(regs, NULL); + if (readl(IOMEM(BUS_DBG_CON)) & + (BUS_DBG_CON_IRQ_AR_STA0|BUS_DBG_CON_IRQ_AR_STA1)) { + for (i = 0; i < BUS_DBG_NUM_TRACKER; i++) { + pr_err("AR_TRACKER Timeout Entry[%d]: ReadAddr:0x%x, ", + i, + readl(IOMEM(BUS_DBG_AR_TRACK_L(i)))); + pr_err("Length:0x%x, TransactionID:0x%x!\n", + readl(IOMEM(BUS_DBG_AR_TRACK_H(i))), + readl(IOMEM(BUS_DBG_AR_TRANS_TID(i)))); + } + } + + if (readl(IOMEM(BUS_DBG_CON)) & + (BUS_DBG_CON_IRQ_AW_STA0|BUS_DBG_CON_IRQ_AW_STA1)) { + for (i = 0; i < BUS_DBG_NUM_TRACKER; i++) { + pr_err("AW_TRACKER Timeout Entry[%d]: WriteAddr:0x%x, ", + i, + readl(IOMEM(BUS_DBG_AW_TRACK_L(i)))); + pr_err("Length:0x%x, TransactionID:0x%x!\n", + readl(IOMEM(BUS_DBG_AW_TRACK_H(i))), + readl(IOMEM(BUS_DBG_AW_TRANS_TID(i)))); + } + } + + return -1; +} + +/* ARM32 version */ +static int systracker_platform_hook_fault(void) +{ + +#ifdef CONFIG_ARM_LPAE + hook_fault_code(0x10, + systracker_handler, + SIGTRAP, + 0, + "Systracker debug exception"); + hook_fault_code(0x11, + systracker_handler, + SIGTRAP, + 0, + "Systracker debug exception"); +#else + hook_fault_code(0x8, + systracker_handler, + SIGTRAP, + 0, + "Systracker debug exception"); + hook_fault_code(0x16, + systracker_handler, + SIGTRAP, + 0, + "Systracker debug exception"); +#endif + return 0; +} +#endif + +#ifdef SYSTRACKER_TEST_SUIT +void __iomem *p1; +void __iomem *mm_area1; + +static int systracker_platform_test_init(void) +{ + p1 = ioremap(0x10000220, 0x4); + /* use mmsys reg base for our test */ + mm_area1 = ioremap(0x14000000, 0x4); + + return 0; +} + +static void systracker_platform_test_cleanup(void) +{ + writel(readl(p1) & ~(0x1 << 6), p1); +} + +static void systracker_platform_wp_test(void) +{ + void __iomem *ptr; + /* use eint reg base as our watchpoint */ + ptr = ioremap(0x1000b000, 0x4); + pr_debug("%s:%d: we got p = 0x%p\n", __func__, __LINE__, ptr); + systracker_set_watchpoint_addr(0x1000b000); + systracker_watchpoint_enable(); + /* touch it */ + writel(0, ptr); + pr_debug("after we touched watchpoint\n"); + iounmap(ptr); +} + +static void systracker_platform_read_timeout_test(void) +{ + /* FIXME: testing + track_config.enable_slave_err = 0; + systracker_enable(); + */ + + writel(readl(p1) | (0x1 << 6), p1); + readl(mm_area1); + writel(readl(p1) & ~(0x1 << 6), p1); +} + +static void systracker_platform_write_timeout_test(void) +{ + writel(readl(p1) | (0x1 << 6), p1); + writel(0x0, mm_area1); + writel(readl(p1) & ~(0x1 << 6), p1); +} + +static void systracker_platform_withrecord_test(void) +{ + writel(readl(IOMEM(BUS_DBG_CON)) | + BUS_DBG_CON_HALT_ON_EN, IOMEM(BUS_DBG_CON)); + writel(readl(p1) | (0x1 << 6), p1); + readl(mm_area1); +#if 0 + /* FIXME: related function not ready on FPGA */ + wdt_arch_reset(1); +#endif +} + +static void systracker_platform_notimeout_test(void) +{ + writel(readl(p1) | (0x1 << 6), p1); + /* disable timeout */ + writel(readl(IOMEM(BUS_DBG_CON)) & + ~(BUS_DBG_CON_TIMEOUT_EN), IOMEM(BUS_DBG_CON)); + /* read it, should cause bus hang */ + readl(mm_area1); + /* never come back */ + pr_alert("failed??\n"); +} +#endif +/* end of SYSTRACKER_TEST_SUIT */ + +/* + * mt_systracker_init: initialize driver. + * Always return 0. + */ +static int __init mt_systracker_init(void) +{ + struct mt_systracker_driver *systracker_drv; + + systracker_drv = get_mt_systracker_drv(); + + systracker_drv->systracker_hook_fault = + systracker_platform_hook_fault; +#ifdef SYSTRACKER_TEST_SUIT + systracker_drv->systracker_test_init = + systracker_platform_test_init; + systracker_drv->systracker_test_cleanup = + systracker_platform_test_cleanup; + systracker_drv->systracker_wp_test = + systracker_platform_wp_test; + systracker_drv->systracker_read_timeout_test = + systracker_platform_read_timeout_test; + systracker_drv->systracker_write_timeout_test = + systracker_platform_write_timeout_test; + systracker_drv->systracker_withrecord_test = + systracker_platform_withrecord_test; + systracker_drv->systracker_notimeout_test = + systracker_platform_notimeout_test; +#endif + return 0; +} + +arch_initcall(mt_systracker_init); +MODULE_DESCRIPTION("system tracker driver v2.0"); diff --git a/drivers/misc/mediatek/thermal/mt6755/Makefile b/drivers/misc/mediatek/thermal/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..82fe0cc1efccc6f960710ac88309199fa04d6a80 --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += src/ diff --git a/drivers/misc/mediatek/thermal/mt6755/inc/mt_cl_amddulthro.h b/drivers/misc/mediatek/thermal/mt6755/inc/mt_cl_amddulthro.h new file mode 100644 index 0000000000000000000000000000000000000000..c1fcc8649bc1353628077fc46bcaf5767d047402 --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/inc/mt_cl_amddulthro.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +extern int amddulthro_backoff(int level); diff --git a/drivers/misc/mediatek/thermal/mt6755/inc/mt_cooler_setting.h b/drivers/misc/mediatek/thermal/mt6755/inc/mt_cooler_setting.h new file mode 100644 index 0000000000000000000000000000000000000000..49c10102f3613e449fd1d9f52ce02f0f67b867bb --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/inc/mt_cooler_setting.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MTK_COOLER_SETTING_H +#define _MTK_COOLER_SETTING_H + +/*============================================================= + * CONFIG (SW related) + *=============================================================*/ + /* mtk_cooler_mutt.c */ +/* 1: turn on MD throttle V2 cooler; 0: turn off */ +#define FEATURE_MUTT_V2 (1) + +/* mtk_cooler_mutt.c */ +/* 1: turn on MD Thermal Warning Notification; 0: turn off */ +#define FEATURE_THERMAL_DIAG (1) + +/* mtk_cooler_mutt.c */ +/* 1: turn on adaptive MD throttle cooler; 0: turn off */ +#define FEATURE_ADAPTIVE_MUTT (0) + +#endif /* _MTK_COOLER_SETTING_H */ diff --git a/drivers/misc/mediatek/thermal/mt6755/inc/mt_ts_setting.h b/drivers/misc/mediatek/thermal/mt6755/inc/mt_ts_setting.h new file mode 100644 index 0000000000000000000000000000000000000000..eaef428de475f6e7d7180fd8b97518f8a4f14f96 --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/inc/mt_ts_setting.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MTK_TS_SETTING_H +#define _MTK_TS_SETTING_H + +/*============================================================= + * CONFIG (SW related) + *=============================================================*/ +/* mtk_ts_pa.c */ +/* 1: turn on MD UL throughput update; 0: turn off */ +#define Feature_Thro_update (1) + + +#endif /* _MTK_TS_SETTING_H */ diff --git a/drivers/misc/mediatek/thermal/mt6755/inc/tmp_6311buck.h b/drivers/misc/mediatek/thermal/mt6755/inc/tmp_6311buck.h new file mode 100644 index 0000000000000000000000000000000000000000..40a1536342d729ea78a226c4036b067f7b9d33f8 --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/inc/tmp_6311buck.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +extern int is_ext_buck_exist(void); diff --git a/drivers/misc/mediatek/thermal/mt6755/inc/tmp_battery.h b/drivers/misc/mediatek/thermal/mt6755/inc/tmp_battery.h new file mode 100644 index 0000000000000000000000000000000000000000..61eef762e99fc1a1dada8259e2a4dd24e58a51e4 --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/inc/tmp_battery.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +/* Extern two API functions from battery driver to limit max charging current. */ +/** + * return value means charging current in mA + * -1 means error + * Implementation in mt_battery.c and mt_battery_fan5405.c + */ +extern int get_bat_charging_current_level(void); + +/** + * current_limit means limit of charging current in mA + * -1 means no limit + * Implementation in mt_battery.c and mt_battery_fan5405.c + */ +extern int set_bat_charging_current_limit(int current_limit); +extern CHARGER_TYPE mt_get_charger_type(void); + +extern int read_tbat_value(void); + diff --git a/drivers/misc/mediatek/thermal/mt6755/inc/tmp_bts.h b/drivers/misc/mediatek/thermal/mt6755/inc/tmp_bts.h new file mode 100644 index 0000000000000000000000000000000000000000..12815b4048295c1912118f859b92836b1240cfc4 --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/inc/tmp_bts.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +extern int IMM_GetOneChannelValue(int dwChannel, int data[4], int *rawdata); +extern int IMM_IsAdcInitReady(void); diff --git a/drivers/misc/mediatek/thermal/mt6755/inc/tscpu_settings.h b/drivers/misc/mediatek/thermal/mt6755/inc/tscpu_settings.h new file mode 100644 index 0000000000000000000000000000000000000000..b923f075bf4997ee16c6060c370f880efecd65c6 --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/inc/tscpu_settings.h @@ -0,0 +1,597 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "mt_gpufreq.h" + +#include +#include +/*============================================================= + * Genernal + *=============================================================*/ +#define MIN(_a_, _b_) ((_a_) > (_b_) ? (_b_) : (_a_)) +#define MAX(_a_, _b_) ((_a_) > (_b_) ? (_a_) : (_b_)) +#define _BIT_(_bit_) (unsigned)(1 << (_bit_)) +#define _BITMASK_(_bits_) (((unsigned) -1 >> (31 - ((1) ? _bits_))) & ~((1U << ((0) ? _bits_)) - 1)) + +/*============================================================= + * CONFIG (SW related) + *=============================================================*/ +#define ENALBE_SW_FILTER (1) +#define ATM_USES_PPM (1) + +#define THERMAL_GET_AHB_BUS_CLOCK (0) +#define THERMAL_PERFORMANCE_PROFILE (0) + +/* 1: turn on GPIO toggle monitor; 0: turn off */ +#define THERMAL_GPIO_OUT_TOGGLE (0) + +/* 1: turn on adaptive AP cooler; 0: turn off */ +#define CPT_ADAPTIVE_AP_COOLER (1) + +/* 1: turn on supports to MET logging; 0: turn off */ +#define CONFIG_SUPPORT_MET_MTKTSCPU (0) + +/* Thermal controller HW filtering function. Only 1, 2, 4, 8, 16 are valid values, +they means one reading is a avg of X samples */ +#define THERMAL_CONTROLLER_HW_FILTER (1) /* 1, 2, 4, 8, 16 */ + +/* 1: turn on thermal controller HW thermal protection; 0: turn off */ +#define THERMAL_CONTROLLER_HW_TP (1) + +/* 1: turn on fast polling in this sw module; 0: turn off */ +#define MTKTSCPU_FAST_POLLING (1) + +#if CPT_ADAPTIVE_AP_COOLER +#define MAX_CPT_ADAPTIVE_COOLERS (3) + +#define THERMAL_HEADROOM (0) +#define CONTINUOUS_TM (1) +#define DYNAMIC_GET_GPU_POWER (1) + +/* 1: turn on precise power budgeting; 0: turn off */ +#define PRECISE_HYBRID_POWER_BUDGET (1) +#endif + +/* 1: thermal driver fast polling, use hrtimer; 0: turn off */ +/* #define THERMAL_DRV_FAST_POLL_HRTIMER (1) */ + +/* 1: thermal driver update temp to MET directly, use hrtimer; 0: turn off */ +#define THERMAL_DRV_UPDATE_TEMP_DIRECT_TO_MET (1) +/*============================================================= + * Chip related + *=============================================================*/ +/* double check */ +#define TS_CONFIGURE TS_CON1_TM /*depend on CPU design*/ +#define TS_CONFIGURE_P TS_CON1_P /*depend on CPU design*/ +#define TS_TURN_ON 0xFFFFFFCF /*turn on TS_CON1[5:4] 2'b 00 11001111 -> 0xCF ~(0x30)*/ +#define TS_TURN_OFF 0x00000030 /*turn off thermal*/ +/*chip dependent*/ +#define ADDRESS_INDEX_0 8 /*0x10206184*/ +#define ADDRESS_INDEX_1 7 /*0x10206180*/ +#define ADDRESS_INDEX_2 9 /*0x10206188*/ + +#define CLEAR_TEMP 26111 + +/* TSCON1 bit table */ +#define TSCON0_bit_6_7_00 0x00 /* TSCON0[7:6]=2'b00 */ +#define TSCON0_bit_6_7_01 0x40 /* TSCON0[7:6]=2'b01 */ +#define TSCON0_bit_6_7_10 0x80 /* TSCON0[7:6]=2'b10 */ +#define TSCON0_bit_6_7_11 0xc0 /* TSCON0[7:6]=2'b11 */ +#define TSCON0_bit_6_7_MASK 0xc0 + +#define TSCON1_bit_4_5_00 0x00 /* TSCON1[5:4]=2'b00 */ +#define TSCON1_bit_4_5_01 0x10 /* TSCON1[5:4]=2'b01 */ +#define TSCON1_bit_4_5_10 0x20 /* TSCON1[5:4]=2'b10 */ +#define TSCON1_bit_4_5_11 0x30 /* TSCON1[5:4]=2'b11 */ +#define TSCON1_bit_4_5_MASK 0x30 + +#define TSCON1_bit_0_2_000 0x00 /* TSCON1[2:0]=3'b000 */ +#define TSCON1_bit_0_2_001 0x01 /* TSCON1[2:0]=3'b001 */ +#define TSCON1_bit_0_2_010 0x02 /* TSCON1[2:0]=3'b010 */ +#define TSCON1_bit_0_2_011 0x03 /* TSCON1[2:0]=3'b011 */ +#define TSCON1_bit_0_2_100 0x04 /* TSCON1[2:0]=3'b100 */ +#define TSCON1_bit_0_2_101 0x05 /* TSCON1[2:0]=3'b101 */ +#define TSCON1_bit_0_2_110 0x06 /* TSCON1[2:0]=3'b110 */ +#define TSCON1_bit_0_2_111 0x07 /* TSCON1[2:0]=3'b111 */ +#define TSCON1_bit_0_2_MASK 0x07 + + +/* ADC value to mcu */ +/* chip dependent */ +#define TEMPADC_MCU1 ((0x30&TSCON1_bit_4_5_00)|(0x07&TSCON1_bit_0_2_000)) +#define TEMPADC_MCU2 ((0x30&TSCON1_bit_4_5_00)|(0x07&TSCON1_bit_0_2_001)) +#define TEMPADC_MCU3 ((0x30&TSCON1_bit_4_5_00)|(0x07&TSCON1_bit_0_2_010)) +#define TEMPADC_MCU4 ((0x30&TSCON1_bit_4_5_00)|(0x07&TSCON1_bit_0_2_011)) +#define TEMPADC_ABB ((0x30&TSCON1_bit_4_5_01)|(0x07&TSCON1_bit_0_2_000)) + +#define TS_FILL(n) {#n, n} +#define TS_LEN_ARRAY(name) (sizeof(name)/sizeof(name[0])) +#define MAX_TS_NAME 20 + +#define CPU_COOLER_NUM 34 +#define MTK_TS_CPU_RT (0) + +#ifdef CONFIG_MTK_RAM_CONSOLE +#define CONFIG_THERMAL_AEE_RR_REC (1) +#else +#define CONFIG_THERMAL_AEE_RR_REC (0) +#endif +/*============================================================= + *REG ACCESS + *=============================================================*/ + +#define thermal_setl(addr, val) mt_reg_sync_writel(readl(addr) | (val), ((void *)addr)) +#define thermal_clrl(addr, val) mt_reg_sync_writel(readl(addr) & ~(val), ((void *)addr)) + +#define MTKTSCPU_TEMP_CRIT 120000 /* 120.000 degree Celsius */ + +#define y_curr_repeat_times 1 +#define THERMAL_NAME "mtk-thermal" + +#define TS_MS_TO_NS(x) (x * 1000 * 1000) + +#if THERMAL_GET_AHB_BUS_CLOCK +#define THERMAL_MODULE_SW_CG_SET (therm_clk_infracfg_ao_base + 0x88) +#define THERMAL_MODULE_SW_CG_CLR (therm_clk_infracfg_ao_base + 0x8C) +#define THERMAL_MODULE_SW_CG_STA (therm_clk_infracfg_ao_base + 0x94) + +#define THERMAL_CG (therm_clk_infracfg_ao_base + 0x80) +#define THERMAL_DCM (therm_clk_infracfg_ao_base + 0x70) +#endif +/*============================================================= + *LOG + *=============================================================*/ +#define TSCPU_LOG_TAG "[CPU_Thermal]" + +#define tscpu_dprintk(fmt, args...) \ + do { \ + if (tscpu_debug_log) { \ + pr_debug(TSCPU_LOG_TAG fmt, ##args); \ + } \ + } while (0) + +#define tscpu_printk(fmt, args...) pr_debug(TSCPU_LOG_TAG fmt, ##args) +#define tscpu_warn(fmt, args...) pr_warn(TSCPU_LOG_TAG fmt, ##args) + +/*============================================================= + * Structures + *=============================================================*/ + +/* Align with thermal_sensor_name struct @ Mt_thermal.h */ +typedef enum thermal_sensor_enum { + MCU1 = 0, + MCU2, + MCU3, + MCU4, + ABB, + ENUM_MAX, +} ts_e; + +typedef struct { + char ts_name[MAX_TS_NAME]; + ts_e type; +} thermal_sensor_t; + +typedef struct { + thermal_sensor_t ts[ENUM_MAX]; + int ts_number; +} bank_t; + +#if (CONFIG_THERMAL_AEE_RR_REC == 1) +enum thermal_state { + TSCPU_SUSPEND = 0, + TSCPU_RESUME = 1, + TSCPU_NORMAL = 2, + TSCPU_INIT = 3, + TSCPU_PAUSE = 4, + TSCPU_RELEASE = 5 +}; +enum atm_state { + ATM_WAKEUP = 0, + ATM_CPULIMIT = 1, + ATM_GPULIMIT = 2, + ATM_DONE = 3, +}; +#endif + +struct mtk_cpu_power_info { + unsigned int cpufreq_khz; + unsigned int cpufreq_ncpu; + unsigned int cpufreq_power; +}; + +/*============================================================= + * Shared variables + *=============================================================*/ +/*In src/mtk_tc.c*/ +extern int tscpu_debug_log; +extern const struct of_device_id mt_thermal_of_match[2]; +extern int tscpu_bank_ts[THERMAL_BANK_NUM][ENUM_MAX]; +extern bank_t tscpu_g_bank[THERMAL_BANK_NUM]; +extern int tscpu_polling_trip_temp1; +extern int tscpu_polling_trip_temp2; +extern int tscpu_polling_factor1; +extern int tscpu_polling_factor2; +#if MTKTSCPU_FAST_POLLING +/* Combined fast_polling_trip_temp and fast_polling_factor, +it means polling_delay will be 1/5 of original interval +after mtktscpu reports > 65C w/o exit point */ +extern int fast_polling_trip_temp; +extern int fast_polling_trip_temp_high; +extern int fast_polling_factor; +extern int tscpu_cur_fp_factor; +extern int tscpu_next_fp_factor; +#endif + +/*In common/thermal_zones/mtk_ts_cpu.c*/ +extern void __iomem *therm_clk_infracfg_ao_base; +extern int Num_of_GPU_OPP; +extern struct mt_gpufreq_power_table_info *mtk_gpu_power; +extern int tscpu_read_curr_temp; +#if MTKTSCPU_FAST_POLLING +extern int tscpu_cur_fp_factor; +#endif + +#if !defined(CONFIG_MTK_CLKMGR) +extern struct clk *therm_main; /* main clock for Thermal */ +#endif + +#if CPT_ADAPTIVE_AP_COOLER +extern int tscpu_g_curr_temp; +extern int tscpu_g_prev_temp; +#if (THERMAL_HEADROOM == 1) || (CONTINUOUS_TM == 1) +extern int bts_cur_temp; /* in mtk_ts_bts.c */ +#endif + +#if PRECISE_HYBRID_POWER_BUDGET +/* tscpu_prev_cpu_temp: previous CPUSYS temperature + tscpu_curr_cpu_temp: current CPUSYS temperature + tscpu_prev_gpu_temp: previous GPUSYS temperature + tscpu_curr_gpu_temp: current GPUSYS temperature + */ +extern int tscpu_prev_cpu_temp, tscpu_prev_gpu_temp; +extern int tscpu_curr_cpu_temp, tscpu_curr_gpu_temp; +#endif + +#endif + +#ifdef CONFIG_OF +extern u32 thermal_irq_number; +extern void __iomem *thermal_base; +extern void __iomem *auxadc_ts_base; +extern void __iomem *infracfg_ao_base; +extern void __iomem *th_apmixed_base; +extern void __iomem *INFRACFG_AO_base; + +extern int thermal_phy_base; +extern int auxadc_ts_phy_base; +extern int apmixed_phy_base; +extern int pericfg_phy_base; +#endif +extern char *adaptive_cooler_name; + +/*common/coolers/mtk_cooler_atm.c*/ +extern unsigned int adaptive_cpu_power_limit; +extern unsigned int adaptive_gpu_power_limit; +extern int TARGET_TJS[MAX_CPT_ADAPTIVE_COOLERS]; + +/*common/coolers/mtk_cooler_dtm.c*/ +extern unsigned int static_cpu_power_limit; +extern unsigned int static_gpu_power_limit; +extern int tscpu_cpu_dmips[CPU_COOLER_NUM]; +/*============================================================= + * Shared functions + *=============================================================*/ +/*In common/thermal_zones/mtk_ts_cpu.c*/ +extern void tscpu_print_all_temperature(int isDprint); +extern void tscpu_update_tempinfo(void); +#if THERMAL_GPIO_OUT_TOGGLE +void tscpu_set_GPIO_toggle_for_monitor(void); +#endif +extern void tscpu_thermal_tempADCPNP(int adc, int order); +extern int tscpu_thermal_ADCValueOfMcu(ts_e type); +extern void tscpu_thermal_enable_all_periodoc_sensing_point(thermal_bank_name bank_num); +extern void tscpu_update_tempinfo(void); +extern int tscpu_max_temperature(void); + +/*In src/mtk_tc.c*/ +extern int get_io_reg_base(void); +extern void tscpu_config_all_tc_hw_protect(int temperature, int temperature2); +extern void tscpu_reset_thermal(void); +extern void tscpu_thermal_initial_all_bank(void); +extern int tscpu_switch_bank(thermal_bank_name bank); +extern void tscpu_thermal_read_bank_temp(thermal_bank_name bank, ts_e type, int order); +extern void tscpu_thermal_cal_prepare(void); +extern void tscpu_thermal_cal_prepare_2(__u32 ret); +extern irqreturn_t tscpu_thermal_all_bank_interrupt_handler(int irq, void *dev_id); +extern int tscpu_thermal_clock_on(void); +extern int tscpu_thermal_clock_off(void); +extern int tscpu_read_temperature_info(struct seq_file *m, void *v); +extern int tscpu_thermal_fast_init(void); +extern int tscpu_get_curr_temp(void); +extern void thermal_get_AHB_clk_info(void); + +/* +In drivers/misc/mediatek/gpu/hal/mtk_gpu_utility.c +It's not our api, ask them to provide header file +*/ +extern bool mtk_get_gpu_loading(unsigned int *pLoading); +/* +In drivers/misc/mediatek/auxadc/mt_auxadc.c +It's not our api, ask them to provide header file +*/ +extern int IMM_IsAdcInitReady(void); +/*aee related*/ +#if (CONFIG_THERMAL_AEE_RR_REC == 1) +extern void aee_rr_rec_thermal_temp1(u8 val); +extern void aee_rr_rec_thermal_temp2(u8 val); +extern void aee_rr_rec_thermal_temp3(u8 val); +extern void aee_rr_rec_thermal_temp4(u8 val); +extern void aee_rr_rec_thermal_temp5(u8 val); +extern void aee_rr_rec_thermal_status(u8 val); +extern void aee_rr_rec_thermal_ATM_status(u8 val); +extern void aee_rr_rec_thermal_ktime(u64 val); + +extern u8 aee_rr_curr_thermal_temp1(void); +extern u8 aee_rr_curr_thermal_temp2(void); +extern u8 aee_rr_curr_thermal_temp3(void); +extern u8 aee_rr_curr_thermal_temp4(void); +extern u8 aee_rr_curr_thermal_temp5(void); +extern u8 aee_rr_curr_thermal_status(void); +extern u8 aee_rr_curr_thermal_ATM_status(void); +extern u64 aee_rr_curr_thermal_ktime(void); +#endif + +/*============================================================= + * Register macro for internal use + *=============================================================*/ + +#if 1 +extern void __iomem *thermal_base; +extern void __iomem *auxadc_base; +extern void __iomem *infracfg_ao_base; +extern void __iomem *apmixed_base; +extern void __iomem *INFRACFG_AO_base; + +#define THERM_CTRL_BASE_2 thermal_base +#define AUXADC_BASE_2 auxadc_ts_base +#define INFRACFG_AO_BASE_2 infracfg_ao_base +#define APMIXED_BASE_2 th_apmixed_base +#else +#include +#define AUXADC_BASE_2 AUXADC_BASE +#define THERM_CTRL_BASE_2 THERM_CTRL_BASE +#define PERICFG_BASE_2 PERICFG_BASE +#define APMIXED_BASE_2 APMIXED_BASE +#endif + +#define MT6752_EVB_BUILD_PASS /*Jerry fix build error FIX_ME*/ + +/******************************************************************************* + * AUXADC Register Definition + ******************************************************************************/ +/*K2 AUXADC_BASE: 0xF1001000 from Vincent Liang 2014.5.8*/ + +#define AUXADC_CON0_V (AUXADC_BASE_2 + 0x000) /*yes, 0x11003000*/ +#define AUXADC_CON1_V (AUXADC_BASE_2 + 0x004) +#define AUXADC_CON1_SET_V (AUXADC_BASE_2 + 0x008) +#define AUXADC_CON1_CLR_V (AUXADC_BASE_2 + 0x00C) +#define AUXADC_CON2_V (AUXADC_BASE_2 + 0x010) +/*#define AUXADC_CON3_V (AUXADC_BASE_2 + 0x014)*/ +#define AUXADC_DAT0_V (AUXADC_BASE_2 + 0x014) +#define AUXADC_DAT1_V (AUXADC_BASE_2 + 0x018) +#define AUXADC_DAT2_V (AUXADC_BASE_2 + 0x01C) +#define AUXADC_DAT3_V (AUXADC_BASE_2 + 0x020) +#define AUXADC_DAT4_V (AUXADC_BASE_2 + 0x024) +#define AUXADC_DAT5_V (AUXADC_BASE_2 + 0x028) +#define AUXADC_DAT6_V (AUXADC_BASE_2 + 0x02C) +#define AUXADC_DAT7_V (AUXADC_BASE_2 + 0x030) +#define AUXADC_DAT8_V (AUXADC_BASE_2 + 0x034) +#define AUXADC_DAT9_V (AUXADC_BASE_2 + 0x038) +#define AUXADC_DAT10_V (AUXADC_BASE_2 + 0x03C) +#define AUXADC_DAT11_V (AUXADC_BASE_2 + 0x040) +#define AUXADC_MISC_V (AUXADC_BASE_2 + 0x094) + +#define AUXADC_CON0_P (auxadc_ts_phy_base + 0x000) +#define AUXADC_CON1_P (auxadc_ts_phy_base + 0x004) +#define AUXADC_CON1_SET_P (auxadc_ts_phy_base + 0x008) +#define AUXADC_CON1_CLR_P (auxadc_ts_phy_base + 0x00C) +#define AUXADC_CON2_P (auxadc_ts_phy_base + 0x010) +/*#define AUXADC_CON3_P (auxadc_ts_phy_base + 0x014)*/ +#define AUXADC_DAT0_P (auxadc_ts_phy_base + 0x014) +#define AUXADC_DAT1_P (auxadc_ts_phy_base + 0x018) +#define AUXADC_DAT2_P (auxadc_ts_phy_base + 0x01C) +#define AUXADC_DAT3_P (auxadc_ts_phy_base + 0x020) +#define AUXADC_DAT4_P (auxadc_ts_phy_base + 0x024) +#define AUXADC_DAT5_P (auxadc_ts_phy_base + 0x028) +#define AUXADC_DAT6_P (auxadc_ts_phy_base + 0x02C) +#define AUXADC_DAT7_P (auxadc_ts_phy_base + 0x030) +#define AUXADC_DAT8_P (auxadc_ts_phy_base + 0x034) +#define AUXADC_DAT9_P (auxadc_ts_phy_base + 0x038) +#define AUXADC_DAT10_P (auxadc_ts_phy_base + 0x03C) +#define AUXADC_DAT11_P (auxadc_ts_phy_base + 0x040) + +#define AUXADC_MISC_P (auxadc_ts_phy_base + 0x094) + +/* +#define AUXADC_CON0_P (AUXADC_BASE_2 + 0x000 - 0xE0000000) +#define AUXADC_CON1_P (AUXADC_BASE_2 + 0x004 - 0xE0000000) +#define AUXADC_CON1_SET_P (AUXADC_BASE_2 + 0x008 - 0xE0000000) +#define AUXADC_CON1_CLR_P (AUXADC_BASE_2 + 0x00C - 0xE0000000) +#define AUXADC_CON2_P (AUXADC_BASE_2 + 0x010 - 0xE0000000) +#define AUXADC_CON3_P (AUXADC_BASE_2 + 0x014 - 0x30000000) +#define AUXADC_DAT0_P (AUXADC_BASE_2 + 0x014 - 0xE0000000) +#define AUXADC_DAT1_P (AUXADC_BASE_2 + 0x018 - 0xE0000000) +#define AUXADC_DAT2_P (AUXADC_BASE_2 + 0x01C - 0xE0000000) +#define AUXADC_DAT3_P (AUXADC_BASE_2 + 0x020 - 0xE0000000) +#define AUXADC_DAT4_P (AUXADC_BASE_2 + 0x024 - 0xE0000000) +#define AUXADC_DAT5_P (AUXADC_BASE_2 + 0x028 - 0xE0000000) +#define AUXADC_DAT6_P (AUXADC_BASE_2 + 0x02C - 0xE0000000) +#define AUXADC_DAT7_P (AUXADC_BASE_2 + 0x030 - 0xE0000000) +#define AUXADC_DAT8_P (AUXADC_BASE_2 + 0x034 - 0xE0000000) +#define AUXADC_DAT9_P (AUXADC_BASE_2 + 0x038 - 0xE0000000) +#define AUXADC_DAT10_P (AUXADC_BASE_2 + 0x03C - 0xE0000000) +#define AUXADC_DAT11_P (AUXADC_BASE_2 + 0x040 - 0xE0000000) + +#define AUXADC_MISC_P (AUXADC_BASE_2 + 0x094 - 0xE0000000) +*/ +/******************************************************************************* + * Peripheral Configuration Register Definition + ******************************************************************************/ + +/*APB Module infracfg_ao*/ +/*#define INFRACFG_AO_BASE (0xF0001000)*/ +#define INFRA_GLOBALCON_RST_0_SET (INFRACFG_AO_BASE_2 + 0x120) /*yes, 0x10001000*/ +#define INFRA_GLOBALCON_RST_0_CLR (INFRACFG_AO_BASE_2 + 0x124) /*yes, 0x10001000*/ +#define INFRA_GLOBALCON_RST_0_STA (INFRACFG_AO_BASE_2 + 0x128) /*yes, 0x10001000*/ +/******************************************************************************* + * APMixedSys Configuration Register Definition + ******************************************************************************/ +/*K2 APMIXED_BASE: 0x1000C000 from KJ 2014.5.8 TODO: FIXME*/ +#define TS_CON0_TM (APMIXED_BASE_2 + 0x600) /*yes 0x10209000*/ +#define TS_CON1_TM (APMIXED_BASE_2 + 0x604) +#define TS_CON0_P (apmixed_phy_base + 0x600) +#define TS_CON1_P (apmixed_phy_base + 0x604) +/* +#define TS_CON0 (APMIXED_BASE_2 + 0x800) +#define TS_CON1 (APMIXED_BASE_2 + 0x804) +#define TS_CON2 (APMIXED_BASE_2 + 0x808) +#define TS_CON3 (APMIXED_BASE_2 + 0x80C) +*/ + +/******************************************************************************* + * Thermal Controller Register Definition + ******************************************************************************/ +#define TEMPMONCTL0 (THERM_CTRL_BASE_2 + 0x000) /*yes 0xF100B000*/ +#define TEMPMONCTL1 (THERM_CTRL_BASE_2 + 0x004) +#define TEMPMONCTL2 (THERM_CTRL_BASE_2 + 0x008) +#define TEMPMONINT (THERM_CTRL_BASE_2 + 0x00C) +#define TEMPMONINTSTS (THERM_CTRL_BASE_2 + 0x010) +#define TEMPMONIDET0 (THERM_CTRL_BASE_2 + 0x014) +#define TEMPMONIDET1 (THERM_CTRL_BASE_2 + 0x018) +#define TEMPMONIDET2 (THERM_CTRL_BASE_2 + 0x01C) +#define TEMPH2NTHRE (THERM_CTRL_BASE_2 + 0x024) +#define TEMPHTHRE (THERM_CTRL_BASE_2 + 0x028) +#define TEMPCTHRE (THERM_CTRL_BASE_2 + 0x02C) +#define TEMPOFFSETH (THERM_CTRL_BASE_2 + 0x030) +#define TEMPOFFSETL (THERM_CTRL_BASE_2 + 0x034) +#define TEMPMSRCTL0 (THERM_CTRL_BASE_2 + 0x038) +#define TEMPMSRCTL1 (THERM_CTRL_BASE_2 + 0x03C) +#define TEMPAHBPOLL (THERM_CTRL_BASE_2 + 0x040) +#define TEMPAHBTO (THERM_CTRL_BASE_2 + 0x044) +#define TEMPADCPNP0 (THERM_CTRL_BASE_2 + 0x048) +#define TEMPADCPNP1 (THERM_CTRL_BASE_2 + 0x04C) +#define TEMPADCPNP2 (THERM_CTRL_BASE_2 + 0x050) +#define TEMPADCPNP3 (THERM_CTRL_BASE_2 + 0x0B4) + +#define TEMPADCMUX (THERM_CTRL_BASE_2 + 0x054) +#define TEMPADCEXT (THERM_CTRL_BASE_2 + 0x058) +#define TEMPADCEXT1 (THERM_CTRL_BASE_2 + 0x05C) +#define TEMPADCEN (THERM_CTRL_BASE_2 + 0x060) +#define TEMPPNPMUXADDR (THERM_CTRL_BASE_2 + 0x064) +#define TEMPADCMUXADDR (THERM_CTRL_BASE_2 + 0x068) +#define TEMPADCEXTADDR (THERM_CTRL_BASE_2 + 0x06C) +#define TEMPADCEXT1ADDR (THERM_CTRL_BASE_2 + 0x070) +#define TEMPADCENADDR (THERM_CTRL_BASE_2 + 0x074) +#define TEMPADCVALIDADDR (THERM_CTRL_BASE_2 + 0x078) +#define TEMPADCVOLTADDR (THERM_CTRL_BASE_2 + 0x07C) +#define TEMPRDCTRL (THERM_CTRL_BASE_2 + 0x080) +#define TEMPADCVALIDMASK (THERM_CTRL_BASE_2 + 0x084) +#define TEMPADCVOLTAGESHIFT (THERM_CTRL_BASE_2 + 0x088) +#define TEMPADCWRITECTRL (THERM_CTRL_BASE_2 + 0x08C) +#define TEMPMSR0 (THERM_CTRL_BASE_2 + 0x090) +#define TEMPMSR1 (THERM_CTRL_BASE_2 + 0x094) +#define TEMPMSR2 (THERM_CTRL_BASE_2 + 0x098) +#define TEMPMSR3 (THERM_CTRL_BASE_2 + 0x0B8) + +#define TEMPIMMD0 (THERM_CTRL_BASE_2 + 0x0A0) +#define TEMPIMMD1 (THERM_CTRL_BASE_2 + 0x0A4) +#define TEMPIMMD2 (THERM_CTRL_BASE_2 + 0x0A8) +#define TEMPIMMD3 (THERM_CTRL_BASE_2 + 0x0BC) + + +#define TEMPPROTCTL (THERM_CTRL_BASE_2 + 0x0C0) +#define TEMPPROTTA (THERM_CTRL_BASE_2 + 0x0C4) +#define TEMPPROTTB (THERM_CTRL_BASE_2 + 0x0C8) +#define TEMPPROTTC (THERM_CTRL_BASE_2 + 0x0CC) + +#define TEMPSPARE0 (THERM_CTRL_BASE_2 + 0x0F0) +#define TEMPSPARE1 (THERM_CTRL_BASE_2 + 0x0F4) +#define TEMPSPARE2 (THERM_CTRL_BASE_2 + 0x0F8) +#define TEMPSPARE3 (THERM_CTRL_BASE_2 + 0x0FC) + +#define PTPCORESEL (THERM_CTRL_BASE_2 + 0x400) +#define THERMINTST (THERM_CTRL_BASE_2 + 0x404) +#define PTPODINTST (THERM_CTRL_BASE_2 + 0x408) +#define THSTAGE0ST (THERM_CTRL_BASE_2 + 0x40C) +#define THSTAGE1ST (THERM_CTRL_BASE_2 + 0x410) +#define THSTAGE2ST (THERM_CTRL_BASE_2 + 0x414) +#define THAHBST0 (THERM_CTRL_BASE_2 + 0x418) +#define THAHBST1 (THERM_CTRL_BASE_2 + 0x41C) /*Only for DE debug*/ +#define PTPSPARE0 (THERM_CTRL_BASE_2 + 0x420) +#define PTPSPARE1 (THERM_CTRL_BASE_2 + 0x424) +#define PTPSPARE2 (THERM_CTRL_BASE_2 + 0x428) +#define PTPSPARE3 (THERM_CTRL_BASE_2 + 0x42C) +#define THSLPEVEB (THERM_CTRL_BASE_2 + 0x430) + + +#define PTPSPARE0_P (thermal_phy_base + 0x420) +#define PTPSPARE1_P (thermal_phy_base + 0x424) +#define PTPSPARE2_P (thermal_phy_base + 0x428) +#define PTPSPARE3_P (thermal_phy_base + 0x42C) + +/******************************************************************************* + * Thermal Controller Register Mask Definition + ******************************************************************************/ +#define THERMAL_ENABLE_SEN0 0x1 +#define THERMAL_ENABLE_SEN1 0x2 +#define THERMAL_ENABLE_SEN2 0x4 +#define THERMAL_MONCTL0_MASK 0x00000007 + +#define THERMAL_PUNT_MASK 0x00000FFF +#define THERMAL_FSINTVL_MASK 0x03FF0000 +#define THERMAL_SPINTVL_MASK 0x000003FF +#define THERMAL_MON_INT_MASK 0x0007FFFF + +#define THERMAL_MON_CINTSTS0 0x000001 +#define THERMAL_MON_HINTSTS0 0x000002 +#define THERMAL_MON_LOINTSTS0 0x000004 +#define THERMAL_MON_HOINTSTS0 0x000008 +#define THERMAL_MON_NHINTSTS0 0x000010 +#define THERMAL_MON_CINTSTS1 0x000020 +#define THERMAL_MON_HINTSTS1 0x000040 +#define THERMAL_MON_LOINTSTS1 0x000080 +#define THERMAL_MON_HOINTSTS1 0x000100 +#define THERMAL_MON_NHINTSTS1 0x000200 +#define THERMAL_MON_CINTSTS2 0x000400 +#define THERMAL_MON_HINTSTS2 0x000800 +#define THERMAL_MON_LOINTSTS2 0x001000 +#define THERMAL_MON_HOINTSTS2 0x002000 +#define THERMAL_MON_NHINTSTS2 0x004000 +#define THERMAL_MON_TOINTSTS 0x008000 +#define THERMAL_MON_IMMDINTSTS0 0x010000 +#define THERMAL_MON_IMMDINTSTS1 0x020000 +#define THERMAL_MON_IMMDINTSTS2 0x040000 +#define THERMAL_MON_FILTINTSTS0 0x080000 +#define THERMAL_MON_FILTINTSTS1 0x100000 +#define THERMAL_MON_FILTINTSTS2 0x200000 + + +#define THERMAL_tri_SPM_State0 0x20000000 +#define THERMAL_tri_SPM_State1 0x40000000 +#define THERMAL_tri_SPM_State2 0x80000000 + + +#define THERMAL_MSRCTL0_MASK 0x00000007 +#define THERMAL_MSRCTL1_MASK 0x00000038 +#define THERMAL_MSRCTL2_MASK 0x000001C0 diff --git a/drivers/misc/mediatek/thermal/mt6755/inc/tspmic_settings.h b/drivers/misc/mediatek/thermal/mt6755/inc/tspmic_settings.h new file mode 100644 index 0000000000000000000000000000000000000000..09021d73d8ee6c11e9504e5a33059037af263fca --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/inc/tspmic_settings.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include + +/*============================================================= + * Genernal + *=============================================================*/ +#define MIN(_a_, _b_) ((_a_) > (_b_) ? (_b_) : (_a_)) +#define MAX(_a_, _b_) ((_a_) > (_b_) ? (_a_) : (_b_)) +#define _BIT_(_bit_) (unsigned)(1 << (_bit_)) +#define _BITMASK_(_bits_) (((unsigned) -1 >> (31 - ((1) ? _bits_))) & ~((1U << ((0) ? _bits_)) - 1)) + +#define mtktspmic_TEMP_CRIT 150000 /* 150.000 degree Celsius */ +#define mtktstsx_TEMP_CRIT 150000 /* 150.000 degree Celsius */ +#define y_pmic_repeat_times 1 + +#define mtktspmic_info(fmt, args...) pr_debug("[Power/PMIC_Thermal] " fmt, ##args) + + +#define mtktspmic_dprintk(fmt, args...) \ +do { \ + if (mtktspmic_debug_log) { \ + pr_debug("[Power/PMIC_Thermal] " fmt, ##args);\ + } \ +} while (0) + +#define mtktstsx_dprintk(fmt, args...) pr_debug("[TSX_Thermal] " fmt, ##args) + +#define mtktstsx_info(fmt, args...) pr_debug("[TSX_Thermal] " fmt, ##args) + +extern int mtktspmic_debug_log; +extern int mtktstsx_debug_log; +extern void mtktspmic_cali_prepare(void); +extern void mtktspmic_cali_prepare2(void); +extern int mtktspmic_get_hw_temp(void); +extern int mtktstsx_get_hw_temp(void); +extern u32 pmic_Read_Efuse_HPOffset(int i); diff --git a/drivers/misc/mediatek/thermal/mt6755/src/Makefile b/drivers/misc/mediatek/thermal/mt6755/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7570e075f61ee2cdf237b1b4d37543524ffc2f07 --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/src/Makefile @@ -0,0 +1,27 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +THERMAL_CHIP_DRIVER_DIR := $(srctree)/drivers/misc/mediatek/thermal/$(MTK_PLATFORM) +ccflags-y += -I$(THERMAL_CHIP_DRIVER_DIR)/inc +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/gpu/hal/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/thermal/fakeHeader/ + +obj-$(CONFIG_THERMAL) += mtk_tc.o + +ifeq ($(CONFIG_MTK_PMIC_CHIP_MT6353),y) +obj-$(CONFIG_THERMAL) += mtk_pmic_mt6353_efuse.o +else +obj-$(CONFIG_THERMAL) += mtk_pmic_efuse.o +endif + diff --git a/drivers/misc/mediatek/thermal/mt6755/src/mtk_pmic_efuse.c b/drivers/misc/mediatek/thermal/mt6755/src/mtk_pmic_efuse.c new file mode 100644 index 0000000000000000000000000000000000000000..ec3299f58eaf56972def147c25d0902f4316ef8d --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/src/mtk_pmic_efuse.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt-plat/mtk_thermal_monitor.h" +#include "mach/mt_thermal.h" +#include +#include +/*============================================================= + *Local variable definition + *=============================================================*/ +int mtktspmic_debug_log = 0; +int mtktstsx_debug_log = 0; +/* Cali */ +static __s32 g_o_vts; +static __s32 g_degc_cali; +static __s32 g_adc_cali_en; +static __s32 g_o_slope; +static __s32 g_o_slope_sign; +static __s32 g_id; +static __s32 g_slope1 = 1; +static __s32 g_slope2 = 1; +static __s32 g_intercept; + +static DEFINE_MUTEX(TSPMIC_lock); +static int pre_temp1 = 0, PMIC_counter; +/*=============================================================*/ + +static __s32 pmic_raw_to_temp(__u32 ret) +{ + __s32 y_curr = ret; + __s32 t_current; + + t_current = g_intercept + ((g_slope1 * y_curr) / (g_slope2)); + mtktspmic_dprintk("[pmic_raw_to_temp] t_current=%d\n", t_current); + return t_current; +} + +static void mtktspmic_read_efuse(void) +{ + __u32 efusevalue[3]; + + mtktspmic_info("[mtktspmic_read_efuse] start\n"); + /* + 0x0 512 527 + 0x1 528 543 + Thermal data from 512 to 539 + */ + efusevalue[0] = pmic_Read_Efuse_HPOffset(0x0); + efusevalue[1] = pmic_Read_Efuse_HPOffset(0x1); + mtktspmic_info("[mtktspmic_read_efuse]6351_efuse:\n" + "efusevalue[0]=0x%x\n" + "efusevalue[1]=0x%x\n\n", efusevalue[0], efusevalue[1]); + + g_adc_cali_en = (efusevalue[0] & _BIT_(0)); + g_degc_cali = ((efusevalue[0] & _BITMASK_(6:1)) >> 1); + g_o_vts = ((efusevalue[1] & _BITMASK_(3 : 0)) << 9) + ((efusevalue[0] & _BITMASK_(15:7)) >> 7); + g_o_slope_sign = ((efusevalue[1] & _BIT_(4)) >> 4); + g_o_slope = ((efusevalue[1] & _BITMASK_(10:5)) >> 5); + g_id = ((efusevalue[1] & _BIT_(11)) >> 11); + + /* Note: O_SLOPE is signed integer. */ + /* O_SLOPE_SIGN=1 ' it is Negative. */ + /* O_SLOPE_SIGN=0 ' it is Positive. */ + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_o_vts = %x\n", g_o_vts); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_degc_cali = %x\n", g_degc_cali); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_adc_cali_en = %x\n", g_adc_cali_en); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_o_slope = %x\n", g_o_slope); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_o_slope_sign = %x\n", g_o_slope_sign); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_id = %x\n", g_id); + + mtktspmic_info("[mtktspmic_read_efuse] end\n"); +} + +void mtktspmic_cali_prepare(void) +{ + mtktspmic_read_efuse(); + + if (g_id == 0) + g_o_slope = 0; + + /* g_adc_cali_en=0;//FIX ME */ + + if (g_adc_cali_en == 0) { /* no calibration */ + g_o_vts = 1600; + g_degc_cali = 50; + g_o_slope = 0; + g_o_slope_sign = 0; + } + + /*SW workaround patch for mt6755 E2*/ + if (g_degc_cali < 38 || g_degc_cali > 60) + g_degc_cali = 53; + + mtktspmic_info("g_o_vts = 0x%x\n", g_o_vts); + mtktspmic_info("g_degc_cali = 0x%x\n", g_degc_cali); + mtktspmic_info("g_adc_cali_en = 0x%x\n", g_adc_cali_en); + mtktspmic_info("g_o_slope = 0x%x\n", g_o_slope); + mtktspmic_info("g_o_slope_sign = 0x%x\n", g_o_slope_sign); + mtktspmic_info("g_id = 0x%x\n", g_id); + +} + +void mtktspmic_cali_prepare2(void) +{ + + __s32 vbe_t; + + g_slope1 = (100 * 1000); /* 1000 is for 0.001 degree */ + + /* + 0.001598 -> 0.00160, for expression compatiable only + This change is confirmed with DE Wei-Lin Chen + */ + if (g_o_slope_sign == 0) + g_slope2 = -(160 + g_o_slope); + else + g_slope2 = -(160 - g_o_slope); + + vbe_t = (-1) * ((((g_o_vts) * 1800)) / 4096) * 1000; + + if (g_o_slope_sign == 0) + g_intercept = (vbe_t * 100) / (-(160 + g_o_slope)); /*0.001 degree */ + else + g_intercept = (vbe_t * 100) / (-(160 - g_o_slope)); /*0.001 degree */ + + g_intercept = g_intercept + (g_degc_cali * (1000 / 2)); /* 1000 is for 0.1 degree */ + + mtktspmic_info("[Thermal calibration] SLOPE1=%d SLOPE2=%d INTERCEPT=%d, Vbe = %d\n", + g_slope1, g_slope2, g_intercept, vbe_t); +} + +int mtktspmic_get_hw_temp(void) +{ + int temp = 0, temp1 = 0; + + mutex_lock(&TSPMIC_lock); + + temp = PMIC_IMM_GetOneChannelValue(PMIC_AUX_CH4, y_pmic_repeat_times, 2); + + temp1 = pmic_raw_to_temp(temp); + + mtktspmic_dprintk("[mtktspmic_get_hw_temp] Raw=%d, T=%d\n", temp, temp1); + + if ((temp1 > 100000) || (temp1 < -30000)) + mtktspmic_info("[mtktspmic_get_hw_temp] raw=%d, PMIC T=%d", temp, temp1); + + if ((temp1 > 150000) || (temp1 < -50000)) { + mtktspmic_info("[mtktspmic_get_hw_temp] temp(%d) too high, drop this data!\n", + temp1); + temp1 = pre_temp1; + } else if ((PMIC_counter != 0) + && (((pre_temp1 - temp1) > 30000) || ((temp1 - pre_temp1) > 30000))) { + mtktspmic_info("[mtktspmic_get_hw_temp] temp diff too large, drop this data\n"); + temp1 = pre_temp1; + } else { + /* update previous temp */ + pre_temp1 = temp1; + mtktspmic_dprintk("[mtktspmic_get_hw_temp] pre_temp1=%d\n", pre_temp1); + + if (PMIC_counter == 0) + PMIC_counter++; + } + + mutex_unlock(&TSPMIC_lock); + + return temp1; +} + +int mtktstsx_get_hw_temp(void) +{ + int temp = 0, temp1 = 0; + + mutex_lock(&TSPMIC_lock); + + temp = PMIC_IMM_GetOneChannelValue(PMIC_AUX_TSX, y_pmic_repeat_times, 2); + + + pr_warn("[mtktspmic_get_hw_temp] Raw=%d, T=%d\n", temp, temp1); +#if 0 + if ((temp1 > 100000) || (temp1 < -30000)) + mtktspmic_info("[mtktspmic_get_hw_temp] raw=%d, PMIC T=%d", temp, temp1); + + if ((temp1 > 150000) || (temp1 < -50000)) { + mtktspmic_info("[mtktspmic_get_hw_temp] temp(%d) too high, drop this data!\n", + temp1); + temp1 = pre_temp1; + } else if ((PMIC_counter != 0) + && (((pre_temp1 - temp1) > 30000) || ((temp1 - pre_temp1) > 30000))) { + mtktspmic_info("[mtktspmic_get_hw_temp] temp diff too large, drop this data\n"); + temp1 = pre_temp1; + } else { + /* update previous temp */ + pre_temp1 = temp1; + mtktspmic_dprintk("[mtktspmic_get_hw_temp] pre_temp1=%d\n", pre_temp1); + + if (PMIC_counter == 0) + PMIC_counter++; + } +#endif + mutex_unlock(&TSPMIC_lock); + + + return temp; +} + + + + + diff --git a/drivers/misc/mediatek/thermal/mt6755/src/mtk_pmic_mt6353_efuse.c b/drivers/misc/mediatek/thermal/mt6755/src/mtk_pmic_mt6353_efuse.c new file mode 100644 index 0000000000000000000000000000000000000000..916b6b69093328f5250dd511c3f37f556fa3551a --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/src/mtk_pmic_mt6353_efuse.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt-plat/mtk_thermal_monitor.h" +#include "mtk_thermal_typedefs.h" +#include "mach/mt_thermal.h" +#include +#include +/*============================================================= + *Local variable definition + *=============================================================*/ +int mtktspmic_debug_log = 0; +int mtktstsx_debug_log = 0; +/* Cali */ +static kal_int32 g_o_vts; +static kal_int32 g_degc_cali; +static kal_int32 g_adc_cali_en; +static kal_int32 g_o_slope; +static kal_int32 g_o_slope_sign; +static kal_int32 g_id; +static kal_int32 g_slope1 = 1; +static kal_int32 g_slope2 = 1; +static kal_int32 g_intercept; + +static DEFINE_MUTEX(TSPMIC_lock); +static int pre_temp1 = 0, PMIC_counter; +/*=============================================================*/ + +static kal_int32 pmic_raw_to_temp(kal_uint32 ret) +{ + kal_int32 y_curr = ret; + kal_int32 t_current; + + t_current = g_intercept + ((g_slope1 * y_curr) / (g_slope2)); + mtktspmic_dprintk("[pmic_raw_to_temp] t_current=%d\n", t_current); + return t_current; +} + +static void mtktspmic_read_efuse(void) +{ + U32 efusevalue[3]; + + mtktspmic_info("[mtktspmic_read_efuse] start\n"); + /* + 0x0 512 527 + 0x1 528 543 + Thermal data from 512 to 539 + */ + /* The register setting of MT6353 is same as MT6351 */ + efusevalue[0] = pmic_Read_Efuse_HPOffset(0x0); + efusevalue[1] = pmic_Read_Efuse_HPOffset(0x1); + mtktspmic_info("[mtktspmic_read_efuse]6351_efuse:\n" + "efusevalue[0]=0x%x\n" + "efusevalue[1]=0x%x\n\n", efusevalue[0], efusevalue[1]); + + g_adc_cali_en = (efusevalue[0] & _BIT_(0)); + g_degc_cali = ((efusevalue[0] & _BITMASK_(6:1)) >> 1); + g_o_vts = ((efusevalue[1] & _BITMASK_(3 : 0)) << 9) + ((efusevalue[0] & _BITMASK_(15:7)) >> 7); + g_o_slope_sign = ((efusevalue[1] & _BIT_(4)) >> 4); + g_o_slope = ((efusevalue[1] & _BITMASK_(10:5)) >> 5); + g_id = ((efusevalue[1] & _BIT_(11)) >> 11); + + /* Note: O_SLOPE is signed integer. */ + /* O_SLOPE_SIGN=1 ' it is Negative. */ + /* O_SLOPE_SIGN=0 ' it is Positive. */ + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_o_vts = %x\n", g_o_vts); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_degc_cali = %x\n", g_degc_cali); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_adc_cali_en = %x\n", g_adc_cali_en); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_o_slope = %x\n", g_o_slope); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_o_slope_sign = %x\n", g_o_slope_sign); + mtktspmic_info("[mtktspmic_read_efuse]6328_efuse: g_id = %x\n", g_id); + + mtktspmic_info("[mtktspmic_read_efuse] end\n"); +} + +void mtktspmic_cali_prepare(void) +{ + mtktspmic_read_efuse(); + + if (g_id == 0) + g_o_slope = 0; + + /* g_adc_cali_en=0;//FIX ME */ + + if (g_adc_cali_en == 0) { /* no calibration */ + g_o_vts = 1600; + g_degc_cali = 50; + g_o_slope = 0; + g_o_slope_sign = 0; + } + + /*SW workaround patch for mt6755 E2*/ + if (g_degc_cali < 38 || g_degc_cali > 60) + g_degc_cali = 53; + + mtktspmic_info("g_o_vts = 0x%x\n", g_o_vts); + mtktspmic_info("g_degc_cali = 0x%x\n", g_degc_cali); + mtktspmic_info("g_adc_cali_en = 0x%x\n", g_adc_cali_en); + mtktspmic_info("g_o_slope = 0x%x\n", g_o_slope); + mtktspmic_info("g_o_slope_sign = 0x%x\n", g_o_slope_sign); + mtktspmic_info("g_id = 0x%x\n", g_id); + +} + +void mtktspmic_cali_prepare2(void) +{ + + kal_int32 vbe_t; + + g_slope1 = (100 * 1000); /* 1000 is for 0.001 degree */ + + /* + The coefficient is 0.00171 + */ + if (g_o_slope_sign == 0) + g_slope2 = -(171 + g_o_slope); + else + g_slope2 = -(171 - g_o_slope); + + vbe_t = (-1) * ((((g_o_vts) * 1800)) / 4096) * 1000; + + if (g_o_slope_sign == 0) + g_intercept = (vbe_t * 100) / (-(171 + g_o_slope)); /*0.001 degree */ + else + g_intercept = (vbe_t * 100) / (-(171 - g_o_slope)); /*0.001 degree */ + + g_intercept = g_intercept + (g_degc_cali * (1000 / 2)); /* 1000 is for 0.1 degree */ + + mtktspmic_info("[Thermal calibration] SLOPE1=%d SLOPE2=%d INTERCEPT=%d, Vbe = %d\n", + g_slope1, g_slope2, g_intercept, vbe_t); +} + +int mtktspmic_get_hw_temp(void) +{ + int temp = 0, temp1 = 0; + + mutex_lock(&TSPMIC_lock); + + temp = PMIC_IMM_GetOneChannelValue(PMIC_AUX_CH4, y_pmic_repeat_times, 2); + + temp1 = pmic_raw_to_temp(temp); + + mtktspmic_dprintk("[mtktspmic_get_hw_temp] Raw=%d, T=%d\n", temp, temp1); + + if ((temp1 > 100000) || (temp1 < -30000)) + mtktspmic_info("[mtktspmic_get_hw_temp] raw=%d, PMIC T=%d", temp, temp1); + + if ((temp1 > 150000) || (temp1 < -50000)) { + mtktspmic_info("[mtktspmic_get_hw_temp] temp(%d) too high, drop this data!\n", + temp1); + temp1 = pre_temp1; + } else if ((PMIC_counter != 0) + && (((pre_temp1 - temp1) > 30000) || ((temp1 - pre_temp1) > 30000))) { + mtktspmic_info("[mtktspmic_get_hw_temp] temp diff too large, drop this data\n"); + temp1 = pre_temp1; + } else { + /* update previous temp */ + pre_temp1 = temp1; + mtktspmic_dprintk("[mtktspmic_get_hw_temp] pre_temp1=%d\n", pre_temp1); + + if (PMIC_counter == 0) + PMIC_counter++; + } + + mutex_unlock(&TSPMIC_lock); + + return temp1; +} diff --git a/drivers/misc/mediatek/thermal/mt6755/src/mtk_tc.c b/drivers/misc/mediatek/thermal/mt6755/src/mtk_tc.c new file mode 100644 index 0000000000000000000000000000000000000000..b4937ce3c51ea552e0f80e22a29fb596a0cb4b4b --- /dev/null +++ b/drivers/misc/mediatek/thermal/mt6755/src/mtk_tc.c @@ -0,0 +1,1287 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define DEBUG 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt-plat/mtk_thermal_monitor.h" +#include +#include +#include "mach/mt_thermal.h" + +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif + +#include +#include +#include +#include + +#include +#define __MT_MTK_TS_CPU_C__ +#include + +/* 1: turn on RT kthread for thermal protection in this sw module; 0: turn off */ +#if MTK_TS_CPU_RT +#include +#include +#endif + +#ifdef CONFIG_OF +#include +#include +#include +#endif +#define __MT_MTK_TS_CPU_C__ + +#include +/*============================================================= + *Local variable definition + *=============================================================*/ +/* +Bank0 : CPU_mp0 (TS_MCU4) +Bank1 : SOC+GPU (TS_MCU1, TS_MCU3, TS_MCU2) +Bank2 : CPU_mp1 (TS_MCU4) +*/ + +int tscpu_bank_ts[THERMAL_BANK_NUM][ENUM_MAX]; +static int tscpu_bank_ts_r[THERMAL_BANK_NUM][ENUM_MAX]; + +/* chip dependent */ +bank_t tscpu_g_bank[THERMAL_BANK_NUM] = { + [0] = { + .ts = {TS_FILL(MCU4)}, + .ts_number = 1}, + [1] = { + .ts = {TS_FILL(MCU1), TS_FILL(MCU3), TS_FILL(MCU2)}, + .ts_number = 3}, + [2] = { + .ts = {TS_FILL(MCU4)}, + .ts_number = 1}, +}; + +#ifdef CONFIG_OF +const struct of_device_id mt_thermal_of_match[2] = { + {.compatible = "mediatek,mt6755-therm_ctrl",}, + {}, +}; +#endif + +int tscpu_debug_log = 0; + +#if MTK_TS_CPU_RT +static struct task_struct *ktp_thread_handle; +#endif + +static __s32 g_adc_ge_t; +static __s32 g_adc_oe_t; +static __s32 g_o_vtsmcu1; +static __s32 g_o_vtsmcu2; +static __s32 g_o_vtsmcu3; +static __s32 g_o_vtsmcu4; +static __s32 g_o_vtsabb; +static __s32 g_degc_cali; +static __s32 g_adc_cali_en_t; +static __s32 g_o_slope; +static __s32 g_o_slope_sign; +static __s32 g_id; + +static __s32 g_ge; +static __s32 g_oe; +static __s32 g_gain; + +static __s32 g_x_roomt[THERMAL_SENSOR_NUM] = { 0 }; + +static __u32 calefuse1; +static __u32 calefuse2; +static __u32 calefuse3; + +/** + * If curr_temp >= tscpu_polling_trip_temp1, use interval + * else if cur_temp >= tscpu_polling_trip_temp2 && curr_temp < tscpu_polling_trip_temp1, + * use interval*tscpu_polling_factor1 + * else, use interval*tscpu_polling_factor2 + */ +/* chip dependent */ +int tscpu_polling_trip_temp1 = 30000; +int tscpu_polling_trip_temp2 = 20000; +int tscpu_polling_factor1 = 1; +int tscpu_polling_factor2 = 2; + +#if MTKTSCPU_FAST_POLLING +/* Combined fast_polling_trip_temp and fast_polling_factor, +it means polling_delay will be 1/5 of original interval +after mtktscpu reports > 65C w/o exit point */ + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +int fast_polling_trip_temp = 50000; +#else +int fast_polling_trip_temp = 70000; +#endif + +int fast_polling_factor = 4; +int tscpu_cur_fp_factor = 1; +int tscpu_next_fp_factor = 1; +#endif + +#if PRECISE_HYBRID_POWER_BUDGET +/* tscpu_prev_cpu_temp: previous CPUSYS temperature + tscpu_curr_cpu_temp: current CPUSYS temperature + tscpu_prev_gpu_temp: previous GPUSYS temperature + tscpu_curr_gpu_temp: current GPUSYS temperature + */ +int tscpu_prev_cpu_temp = 0, tscpu_prev_gpu_temp = 0; +int tscpu_curr_cpu_temp = 0, tscpu_curr_gpu_temp = 0; +#endif + +/*============================================================= + * Local function declartation + *=============================================================*/ +static __s32 temperature_to_raw_room(__u32 ret); +static void set_tc_trigger_hw_protect(int temperature, int temperature2); +/*============================================================= + *Weak functions + *=============================================================*/ +void __attribute__ ((weak)) +mt_ptp_lock(unsigned long *flags) +{ + pr_err("[Power/CPU_Thermal]%s doesn't exist\n", __func__); +} + +void __attribute__ ((weak)) +mt_ptp_unlock(unsigned long *flags) +{ + pr_err("[Power/CPU_Thermal]%s doesn't exist\n", __func__); +} + +/*=============================================================*/ +/* chip dependent */ +int tscpu_thermal_clock_on(void) +{ + /*Use CCF instead*/ + int ret = -1; + tscpu_dprintk("tscpu_thermal_clock_on\n"); + +#if defined(CONFIG_MTK_CLKMGR) + /*ret = enable_clock(MT_CG_PERI_THERM, "THERMAL"); */ +#else + tscpu_dprintk("CCF_thermal_clock_on\n"); + ret = clk_prepare_enable(therm_main); + if (ret) + tscpu_printk("Cannot enable thermal clock.\n"); +#endif + return ret; +} + +/* chip dependent */ +int tscpu_thermal_clock_off(void) +{ +/*Use CCF instead*/ + int ret = -1; + tscpu_dprintk("tscpu_thermal_clock_off\n"); + +#if defined(CONFIG_MTK_CLKMGR) + /*ret = disable_clock(MT_CG_PERI_THERM, "THERMAL"); */ +#else + tscpu_dprintk("CCF_thermal_clock_off\n"); + clk_disable_unprepare(therm_main); +#endif + return ret; +} + +/* TODO: FIXME */ +void get_thermal_slope_intercept(struct TS_PTPOD *ts_info, thermal_bank_name ts_bank) +{ + unsigned int temp0, temp1, temp2; + struct TS_PTPOD ts_ptpod; + __s32 x_roomt; + + tscpu_dprintk("get_thermal_slope_intercept\n"); + + /* chip dependent */ + + /* + Bank0 : CPU_mp0 (TS_MCU4) + Bank1 : SOC+GPU (TS_MCU1, TS_MCU3, TS_MCU2) + Bank2 : CPU_mp1 (TS_MCU4) + */ + /* + If there are two or more sensors in a bank, choose the sensor calibration value of + the dominant sensor. You can observe it in the thermal doc provided by Thermal DE. + For example, + Bank 1 is for SOC + GPU. Observe all scenarios related to GPU tests to + determine which sensor is the highest temperature in all tests. + Then, It is the dominant sensor. + (Confirmed by Thermal DE Alfred Tsai) + */ + switch (ts_bank) { + case THERMAL_BANK0: + x_roomt = g_x_roomt[3]; + break; + case THERMAL_BANK1: + x_roomt = g_x_roomt[2]; + break; + case THERMAL_BANK2: + x_roomt = g_x_roomt[3]; + break; + default: /*choose high temp */ + x_roomt = g_x_roomt[3]; + break; + } + + /* + The equations in this function are confirmed by Thermal DE Alfred Tsai. + Don't have to change until using next generation thermal sensors. + */ + + temp0 = (10000 * 100000 / g_gain) * 15 / 18; + + if (g_o_slope_sign == 0) + temp1 = temp0 / (165 + g_o_slope); + else + temp1 = temp0 / (165 - g_o_slope); + + ts_ptpod.ts_MTS = temp1; + + temp0 = (g_degc_cali * 10 / 2); + temp1 = ((10000 * 100000 / 4096 / g_gain) * g_oe + x_roomt * 10) * 15 / 18; + + if (g_o_slope_sign == 0) + temp2 = temp1 * 10 / (165 + g_o_slope); + else + temp2 = temp1 * 10 / (165 - g_o_slope); + + ts_ptpod.ts_BTS = (temp0 + temp2 - 250) * 4 / 10; + + + ts_info->ts_MTS = ts_ptpod.ts_MTS; + ts_info->ts_BTS = ts_ptpod.ts_BTS; + tscpu_dprintk("ts_MTS=%d, ts_BTS=%d\n", ts_ptpod.ts_MTS, ts_ptpod.ts_BTS); + + +} +EXPORT_SYMBOL(get_thermal_slope_intercept); + +/* chip dependent */ +void mtkts_dump_cali_info(void) +{ + tscpu_printk("[cal] g_adc_ge_t = 0x%d\n", g_adc_ge_t); + tscpu_printk("[cal] g_adc_oe_t = 0x%d\n", g_adc_oe_t); + tscpu_printk("[cal] g_degc_cali = 0x%d\n", g_degc_cali); + tscpu_printk("[cal] g_adc_cali_en_t = 0x%d\n", g_adc_cali_en_t); + tscpu_printk("[cal] g_o_slope = 0x%d\n", g_o_slope); + tscpu_printk("[cal] g_o_slope_sign = 0x%d\n", g_o_slope_sign); + tscpu_printk("[cal] g_id = 0x%d\n", g_id); + + tscpu_printk("[cal] g_o_vtsmcu1 = 0x%d\n", g_o_vtsmcu1); + tscpu_printk("[cal] g_o_vtsmcu2 = 0x%d\n", g_o_vtsmcu2); + tscpu_printk("[cal] g_o_vtsmcu3 = 0x%d\n", g_o_vtsmcu3); + tscpu_printk("[cal] g_o_vtsmcu4 = 0x%d\n", g_o_vtsmcu4); + tscpu_printk("[cal] g_o_vtsabb = 0x%d\n", g_o_vtsabb); +} + +void eDataCorrector(void) +{ + /* Confirmed with DE Kj Hsiao and DS Lin + ADC_GE_T [9:0] Default:512 265 ~ 758 + ADC_OE_T [9:0] Default:512 265 ~ 758 + O_VTSMCU1 (9b) Default:260 -8 ~ 484 + O_VTSMCU2 (9b) Default:260 -8 ~ 484 + O_VTSMCU3 (9b) Default:260 -8 ~ 484 + O_VTS MCU4(9b) Default:260 -8 ~ 484 + O_VTS ABB(9b) Default:260 -8 ~ 484 + DEGC_cali(6b) Default:40 1 ~ 63 + ADC_CALI_EN_T (1b) + O_SLOPE_SIGN (1b) Default:0 + O_SLOPE (6b) Default:0 + ID (1b) + */ + if (g_adc_ge_t < 265 || g_adc_ge_t > 758) { + tscpu_warn("[thermal] Bad efuse data, g_adc_ge_t\n"); + g_adc_ge_t = 512; + } + if (g_adc_oe_t < 265 || g_adc_oe_t > 758) { + tscpu_warn("[thermal] Bad efuse data, g_adc_oe_t\n"); + g_adc_oe_t = 512; + } + if (g_o_vtsmcu1 < -8 || g_o_vtsmcu1 > 484) { + tscpu_warn("[thermal] Bad efuse data, g_o_vtsmcu1\n"); + g_o_vtsmcu1 = 260; + } + if (g_o_vtsmcu2 < -8 || g_o_vtsmcu2 > 484) { + tscpu_warn("[thermal] Bad efuse data, g_o_vtsmcu2\n"); + g_o_vtsmcu2 = 260; + } + if (g_o_vtsmcu3 < -8 || g_o_vtsmcu3 > 484) { + tscpu_warn("[thermal] Bad efuse data, g_o_vtsmcu3\n"); + g_o_vtsmcu3 = 260; + } + if (g_o_vtsmcu4 < -8 || g_o_vtsmcu4 > 484) { + tscpu_warn("[thermal] Bad efuse data, g_o_vtsmcu4\n"); + g_o_vtsmcu4 = 260; + } + if (g_o_vtsabb < -8 || g_o_vtsabb > 484) { + tscpu_warn("[thermal] Bad efuse data, g_o_vtsabb\n"); + g_o_vtsabb = 260; + } + if (g_degc_cali < 1 || g_degc_cali > 63) { + tscpu_warn("[thermal] Bad efuse data, g_degc_cali\n"); + g_degc_cali = 40; + } +} + +void tscpu_thermal_cal_prepare(void) +{ + __u32 temp0 = 0, temp1 = 0, temp2 = 0; + + temp0 = get_devinfo_with_index(ADDRESS_INDEX_0); + temp1 = get_devinfo_with_index(ADDRESS_INDEX_1); + temp2 = get_devinfo_with_index(ADDRESS_INDEX_2); + + + pr_debug("[calibration] temp0=0x%x, temp1=0x%x, temp2=0x%x\n", temp0, temp1, temp2); + + /* + chip dependent + ADC_GE_T [9:0] *(0x10206184)[31:22] + ADC_OE_T [9:0] *(0x10206184)[21:12] + */ + g_adc_ge_t = ((temp0 & _BITMASK_(31:22)) >> 22); + g_adc_oe_t = ((temp0 & _BITMASK_(21:12)) >> 12); + + /* + O_VTSMCU1 (9b) *(0x10206180)[25:17] + O_VTSMCU2 (9b) *(0x10206180)[16:8] + O_VTSMCU3 (9b) *(0x10206184)[8:0] + O_VTSMCU4 (9b) *(0x10206188)[31:23] + O_VTSABB (9b) *(0x10206188)[22:14] + */ + g_o_vtsmcu1 = ((temp1 & _BITMASK_(25:17)) >> 17); + g_o_vtsmcu2 = ((temp1 & _BITMASK_(16:8)) >> 8); + g_o_vtsmcu3 = (temp0 & _BITMASK_(8:0)); + g_o_vtsmcu4 = ((temp2 & _BITMASK_(31:23)) >> 23); + g_o_vtsabb = ((temp2 & _BITMASK_(22:14)) >> 14); + + /* + DEGC_cali (6b) *(0x10206180)[6:1] + ADC_CALI_EN_T(1b) *(0x10206180)[0] + */ + g_degc_cali = ((temp1 & _BITMASK_(6:1)) >> 1); + g_adc_cali_en_t = (temp1 & _BIT_(0)); + + /* + O_SLOPE_SIGN (1b) *(0x10206180)[7] + O_SLOPE (6b) *(0x10206180)[31:26] + */ + g_o_slope_sign = ((temp1 & _BIT_(7)) >> 7); + g_o_slope = ((temp1 & _BITMASK_(31:26)) >> 26); + + /*ID (1b) *(0x10206184)[9] */ + g_id = ((temp0 & _BIT_(9)) >> 9); + + /* + Check ID bit + If ID=0 (TSMC sample) , ignore O_SLOPE EFuse value and set O_SLOPE=0. + If ID=1 (non-TSMC sample), read O_SLOPE EFuse value for following calculation. + */ + if (g_id == 0) + g_o_slope = 0; + + + if (g_adc_cali_en_t == 1) { + /*thermal_enable = true; */ + eDataCorrector(); + } else { + tscpu_warn("This sample is not Thermal calibrated\n"); + g_adc_ge_t = 512; + g_adc_oe_t = 512; + g_o_vtsmcu1 = 260; + g_o_vtsmcu2 = 260; + g_o_vtsmcu3 = 260; + g_o_vtsmcu4 = 260; + g_o_vtsabb = 260; + g_degc_cali = 40; + g_o_slope_sign = 0; + g_o_slope = 0; + } + + /*mtkts_dump_cali_info();*/ +} + +void tscpu_thermal_cal_prepare_2(__u32 ret) +{ + __s32 format_1 = 0, format_2 = 0, format_3 = 0, format_4 = 0, format_5 = 0; + + /* tscpu_printk("tscpu_thermal_cal_prepare_2\n"); */ + g_ge = ((g_adc_ge_t - 512) * 10000) / 4096; /* ge * 10000 */ + g_oe = (g_adc_oe_t - 512); + + g_gain = (10000 + g_ge); + + format_1 = (g_o_vtsmcu1 + 3350 - g_oe); + format_2 = (g_o_vtsmcu2 + 3350 - g_oe); + format_3 = (g_o_vtsmcu3 + 3350 - g_oe); + format_4 = (g_o_vtsmcu4 + 3350 - g_oe); + format_5 = (g_o_vtsabb + 3350 - g_oe); + + + g_x_roomt[0] = (((format_1 * 10000) / 4096) * 10000) / g_gain; /* x_roomt * 10000 */ + g_x_roomt[1] = (((format_2 * 10000) / 4096) * 10000) / g_gain; /* x_roomt * 10000 */ + g_x_roomt[2] = (((format_3 * 10000) / 4096) * 10000) / g_gain; /* x_roomt * 10000 */ + g_x_roomt[3] = (((format_4 * 10000) / 4096) * 10000) / g_gain; /* x_roomt * 10000 */ + g_x_roomt[4] = (((format_5 * 10000) / 4096) * 10000) / g_gain; /* x_roomt * 10000 */ + + /* + tscpu_printk("[cal] g_ge = 0x%x\n",g_ge); + tscpu_printk("[cal] g_gain = 0x%x\n",g_gain); + + tscpu_printk("[cal] g_x_roomt1 = 0x%x\n",g_x_roomt[0]); + tscpu_printk("[cal] g_x_roomt2 = 0x%x\n",g_x_roomt[1]); + tscpu_printk("[cal] g_x_roomt3 = 0x%x\n",g_x_roomt[2]); + tscpu_printk("[cal] g_x_roomt4 = 0x%x\n",g_x_roomt[3]); + tscpu_printk("[cal] g_x_roomt5 = 0x%x\n",g_x_roomt[4]); + */ +} + +#if THERMAL_CONTROLLER_HW_TP +static __s32 temperature_to_raw_room(__u32 ret) +{ + /* Ycurr = [(Tcurr - DEGC_cali/2)*(165+O_slope)*(18/15)*(1/10000)+X_roomtabb]*Gain*4096 + OE */ + + __s32 t_curr = ret; + __s32 format_1 = 0; + __s32 format_2 = 0; + __s32 format_3[THERMAL_SENSOR_NUM] = { 0 }; + __s32 format_4[THERMAL_SENSOR_NUM] = { 0 }; + __s32 i, index = 0, temp = 0; + + /* tscpu_dprintk("temperature_to_raw_room\n"); */ + + if (g_o_slope_sign == 0) { /* O_SLOPE is Positive. */ + format_1 = t_curr - (g_degc_cali * 1000 / 2); + format_2 = format_1 * (165 + g_o_slope) * 18 / 15; + format_2 = format_2 - 2 * format_2; + + for (i = 0; i < THERMAL_SENSOR_NUM; i++) { + format_3[i] = format_2 / 1000 + g_x_roomt[i] * 10; + format_4[i] = (format_3[i] * 4096 / 10000 * g_gain) / 100000 + g_oe; + } + + } else { /* O_SLOPE is Negative. */ + format_1 = t_curr - (g_degc_cali * 1000 / 2); + format_2 = format_1 * (165 - g_o_slope) * 18 / 15; + format_2 = format_2 - 2 * format_2; + + for (i = 0; i < THERMAL_SENSOR_NUM; i++) { + format_3[i] = format_2 / 1000 + g_x_roomt[i] * 10; + format_4[i] = (format_3[i] * 4096 / 10000 * g_gain) / 100000 + g_oe; + /* tscpu_dprintk("[roomt%d] format_1=%d, format_2=%d, format_3=%d, format_4=%d\n", + i, format_1, format_2, format_3[i], format_4[i]); */ + } + + /* tscpu_dprintk("temperature_to_raw_abb format_1=%d, format_2=%d, format_3=%d, format_4=%d\n", + format_1, format_2, format_3, format_4); */ + } + + + temp = 0; + for (i = 0; i < THERMAL_SENSOR_NUM; i++) { + if (temp < format_4[i]) { + temp = format_4[i]; + index = i; + } + } + + /* tscpu_dprintk("[Temperature_to_raw_roomt] temperature=%d, raw[%d]=%d", ret, index, format_4[index]); */ + return format_4[index]; + +} +#endif + +static __s32 raw_to_temperature_roomt(__u32 ret, thermal_sensor_name ts_name) +{ + __s32 t_current = 0; + __s32 y_curr = ret; + __s32 format_1 = 0; + __s32 format_2 = 0; + __s32 format_3 = 0; + __s32 format_4 = 0; + __s32 xtoomt = 0; + + + xtoomt = g_x_roomt[ts_name]; + + /* tscpu_dprintk("raw_to_temperature_room,ts_num=%d,xtoomt=%d\n",ts_name,xtoomt); */ + + if (ret == 0) + return 0; + + format_1 = ((g_degc_cali * 10) >> 1); + format_2 = (y_curr - g_oe); + + format_3 = (((((format_2) * 10000) >> 12) * 10000) / g_gain) - xtoomt; + format_3 = format_3 * 15 / 18; + + + if (g_o_slope_sign == 0) + format_4 = ((format_3 * 100) / (165 + g_o_slope)); /* uint = 0.1 deg */ + else + format_4 = ((format_3 * 100) / (165 - g_o_slope)); /* uint = 0.1 deg */ + + format_4 = format_4 - (format_4 << 1); + + + t_current = format_1 + format_4; /* uint = 0.1 deg */ + + /* tscpu_dprintk("raw_to_temperature_room,t_current=%d\n",t_current); */ + return t_current; +} + +/* +Bank0 : CPU_mp0 (TS_MCU4) +Bank1 : SOC+GPU (TS_MCU1, TS_MCU3, TS_MCU2) +Bank2 : CPU_mp1 (TS_MCU4) +*/ +/* chip dependent */ +int get_immediate_cpu0_wrap(void) +{ + int curr_temp; + + curr_temp = tscpu_bank_ts[THERMAL_BANK0][MCU4]; + tscpu_dprintk("get_immediate_cpu_wrap curr_temp=%d\n", curr_temp); + + return curr_temp; +} + +int get_immediate_gpu_wrap(void) +{ + int curr_temp; + + curr_temp = MAX(tscpu_bank_ts[THERMAL_BANK1][MCU1], tscpu_bank_ts[THERMAL_BANK1][MCU3]); + curr_temp = MAX(curr_temp, tscpu_bank_ts[THERMAL_BANK1][MCU2]); + tscpu_dprintk("get_immediate_gpu_wrap curr_temp=%d\n", curr_temp); + + return curr_temp; +} + +int get_immediate_cpu1_wrap(void) +{ + int curr_temp; + + curr_temp = tscpu_bank_ts[THERMAL_BANK2][MCU4]; + tscpu_dprintk("get_immediate_soc_wrap curr_temp=%d\n", curr_temp); + + return curr_temp; +} + +/* +Bank0 : CPU_mp0 (TS_MCU4) +Bank1 : SOC+GPU (TS_MCU1, TS_MCU3, TS_MCU2) +Bank2 : CPU_mp1 (TS_MCU4) +*/ +/* chip dependent */ +int get_immediate_ts1_wrap(void) +{ + int curr_temp; + + curr_temp = tscpu_bank_ts[THERMAL_BANK1][MCU1]; + tscpu_dprintk("get_immediate_ts1_wrap curr_temp=%d\n", curr_temp); + + return curr_temp; +} + +int get_immediate_ts2_wrap(void) +{ + int curr_temp; + + curr_temp = tscpu_bank_ts[THERMAL_BANK1][MCU2]; + tscpu_dprintk("get_immediate_ts1_wrap curr_temp=%d\n", curr_temp); + + return curr_temp; +} + +int get_immediate_ts3_wrap(void) +{ + int curr_temp; + + curr_temp = tscpu_bank_ts[THERMAL_BANK1][MCU3]; + tscpu_dprintk("get_immediate_ts3_wrap curr_temp=%d\n", curr_temp); + + return curr_temp; +} + +int get_immediate_ts4_wrap(void) +{ + int curr_temp; + + curr_temp = tscpu_bank_ts[THERMAL_BANK0][MCU4]; + tscpu_dprintk("get_immediate_ts2_wrap curr_temp=%d\n", curr_temp); + + return curr_temp; +} + +static void thermal_interrupt_handler(int bank) +{ + __u32 ret = 0; + unsigned long flags; + + mt_ptp_lock(&flags); + + tscpu_switch_bank(bank); + + ret = readl(TEMPMONINTSTS); + /* pr_debug("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); */ + tscpu_printk("thermal_interrupt_handler,bank=0x%08x,ret=0x%08x\n", bank, ret); + /* pr_debug("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); */ + + /* ret2 = readl(THERMINTST); */ + /* pr_debug("thermal_interrupt_handler : THERMINTST = 0x%x\n", ret2); */ + + + /* for SPM reset debug */ + /* dump_spm_reg(); */ + + /* tscpu_printk("thermal_isr: [Interrupt trigger]: status = 0x%x\n", ret); */ + if (ret & THERMAL_MON_CINTSTS0) + tscpu_dprintk("thermal_isr: thermal sensor point 0 - cold interrupt trigger\n"); + + if (ret & THERMAL_MON_HINTSTS0) + tscpu_dprintk("<<>>: thermal sensor point 0 - hot interrupt trigger\n"); + + if (ret & THERMAL_MON_HINTSTS1) + tscpu_dprintk("<<>>: thermal sensor point 1 - hot interrupt trigger\n"); + + if (ret & THERMAL_MON_HINTSTS2) + tscpu_dprintk("<<>>: thermal sensor point 2 - hot interrupt trigger\n"); + + if (ret & THERMAL_tri_SPM_State0) + tscpu_dprintk("thermal_isr: Thermal state0 to trigger SPM state0\n"); + + if (ret & THERMAL_tri_SPM_State1) { + /* tscpu_printk("thermal_isr: Thermal state1 to trigger SPM state1\n"); */ +#if MTK_TS_CPU_RT + /* tscpu_printk("THERMAL_tri_SPM_State1, T=%d,%d,%d\n", CPU_TS_MCU2_T, GPU_TS_MCU1_T, LTE_TS_MCU3_T); */ + wake_up_process(ktp_thread_handle); +#endif + } + if (ret & THERMAL_tri_SPM_State2) + tscpu_printk("thermal_isr: Thermal state2 to trigger SPM state2\n"); + + mt_ptp_unlock(&flags); + +} + +irqreturn_t tscpu_thermal_all_bank_interrupt_handler(int irq, void *dev_id) +{ + __u32 ret = 0, i, mask = 1; + + + ret = readl(THERMINTST); + ret = ret & 0xF; + + pr_debug("thermal_interrupt_handler : THERMINTST = 0x%x\n", ret); + + for (i = 0; i < TS_LEN_ARRAY(tscpu_g_bank); i++) { + mask = 1 << i; + if ((ret & mask) == 0) + thermal_interrupt_handler(i); + } + + return IRQ_HANDLED; +} + +static void thermal_reset_and_initial(void) +{ + + /* pr_debug( "thermal_reset_and_initial\n"); */ + + /* tscpu_thermal_clock_on(); */ + + /* Calculating period unit in Module clock x 256, and the Module clock */ + /* will be changed to 26M when Infrasys enters Sleep mode. */ + /* mt_reg_sync_writel(0x000003FF, TEMPMONCTL1); // counting unit is 1023 * 15.15ns ~ 15.5us */ + + + /* bus clock 66M counting unit is 4*15.15ns* 256 = 15513.6 ms=15.5us */ + /* mt_reg_sync_writel(0x00000004, TEMPMONCTL1);*/ + /* bus clock 66M counting unit is 12*15.15ns* 256 = 46.540us */ + mt_reg_sync_writel(0x0000000C, TEMPMONCTL1); + /*bus clock 66M counting unit is 4*15.15ns* 256 = 15513.6 ms=15.5us */ + /* mt_reg_sync_writel(0x000001FF, TEMPMONCTL1);*/ + +#if THERMAL_CONTROLLER_HW_FILTER == 2 + mt_reg_sync_writel(0x07E007E0, TEMPMONCTL2); /* both filt and sen interval is 2016*15.5us = 31.25ms */ + mt_reg_sync_writel(0x001F7972, TEMPAHBPOLL); /* poll is set to 31.25ms */ + mt_reg_sync_writel(0x00000049, TEMPMSRCTL0); /* temperature sampling control, 2 out of 4 samples */ +#elif THERMAL_CONTROLLER_HW_FILTER == 4 + mt_reg_sync_writel(0x050A050A, TEMPMONCTL2); /* both filt and sen interval is 20ms */ + mt_reg_sync_writel(0x001424C4, TEMPAHBPOLL); /* poll is set to 20ms */ + mt_reg_sync_writel(0x000000DB, TEMPMSRCTL0); /* temperature sampling control, 4 out of 6 samples */ +#elif THERMAL_CONTROLLER_HW_FILTER == 8 + mt_reg_sync_writel(0x03390339, TEMPMONCTL2); /* both filt and sen interval is 12.5ms */ + mt_reg_sync_writel(0x000C96FA, TEMPAHBPOLL); /* poll is set to 12.5ms */ + mt_reg_sync_writel(0x00000124, TEMPMSRCTL0); /* temperature sampling control, 8 out of 10 samples */ +#elif THERMAL_CONTROLLER_HW_FILTER == 16 + mt_reg_sync_writel(0x01C001C0, TEMPMONCTL2); /* both filt and sen interval is 6.94ms */ + mt_reg_sync_writel(0x0006FE8B, TEMPAHBPOLL); /* poll is set to 458379*15.15= 6.94ms */ + mt_reg_sync_writel(0x0000016D, TEMPMSRCTL0); /* temperature sampling control, 16 out of 18 samples */ +#else /* default 1 */ + /* filt interval is 1 * 46.540us = 46.54us, sen interval is 429 * 46.540us = 19.96ms */ + mt_reg_sync_writel(0x000101AD, TEMPMONCTL2); + /* filt interval is 1 * 46.540us = 46.54us, sen interval is 858 * 46.540us = 39.93ms + * mt_reg_sync_writel(0x0001035A, TEMPMONCTL2); + *filt interval is 1 * 46.540us = 46.54us, sen interval is 1287 * 46.540us = 59.89 ms + * mt_reg_sync_writel(0x00010507, TEMPMONCTL2); + *poll is set to 1 * 46.540us = 46.540us + * mt_reg_sync_writel(0x00000001, TEMPAHBPOLL);*/ + mt_reg_sync_writel(0x00000300, TEMPAHBPOLL); /* poll is set to 10u */ + mt_reg_sync_writel(0x00000000, TEMPMSRCTL0); /* temperature sampling control, 1 sample */ +#endif + + mt_reg_sync_writel(0xFFFFFFFF, TEMPAHBTO); /* exceed this polling time, IRQ would be inserted */ + + mt_reg_sync_writel(0x00000000, TEMPMONIDET0); /* times for interrupt occurrance */ + mt_reg_sync_writel(0x00000000, TEMPMONIDET1); /* times for interrupt occurrance */ + + + /* this value will be stored to TEMPPNPMUXADDR (TEMPSPARE0) automatically by hw */ + mt_reg_sync_writel(0x800, TEMPADCMUX); + mt_reg_sync_writel((__u32) AUXADC_CON1_CLR_P, TEMPADCMUXADDR); /* AHB address for auxadc mux selection */ + /* mt_reg_sync_writel(0x1100100C, TEMPADCMUXADDR);// AHB address for auxadc mux selection */ + + mt_reg_sync_writel(0x800, TEMPADCEN); /* AHB value for auxadc enable */ + /* AHB address for auxadc enable (channel 0 immediate mode selected) */ + mt_reg_sync_writel((__u32) AUXADC_CON1_SET_P, TEMPADCENADDR); + /* mt_reg_sync_writel(0x11001008, TEMPADCENADDR); + *AHB address for auxadc enable (channel 0 immediate mode selected) + *this value will be stored to TEMPADCENADDR automatically by hw */ + + + mt_reg_sync_writel((__u32) AUXADC_DAT11_P, TEMPADCVALIDADDR); /* AHB address for auxadc valid bit */ + mt_reg_sync_writel((__u32) AUXADC_DAT11_P, TEMPADCVOLTADDR); /* AHB address for auxadc voltage output */ + /* mt_reg_sync_writel(0x11001040, TEMPADCVALIDADDR); // AHB address for auxadc valid bit */ + /* mt_reg_sync_writel(0x11001040, TEMPADCVOLTADDR); // AHB address for auxadc voltage output */ + + + mt_reg_sync_writel(0x0, TEMPRDCTRL); /* read valid & voltage are at the same register */ + /* indicate where the valid bit is (the 12th bit is valid bit and 1 is valid) */ + mt_reg_sync_writel(0x0000002C, TEMPADCVALIDMASK); + mt_reg_sync_writel(0x0, TEMPADCVOLTAGESHIFT); /* do not need to shift */ + /* mt_reg_sync_writel(0x2, TEMPADCWRITECTRL); // enable auxadc mux write transaction */ + +} + +/* Refactor */ +static int thermal_config_Bank(void) +{ + int i, j = 0; + int ret = -1; + __u32 temp = 0; + + /* AuxADC Initialization,ref MT6592_AUXADC.doc // TODO: check this line */ + temp = readl(AUXADC_CON0_V); /* Auto set enable for CH11 */ + temp &= 0xFFFFF7FF; /* 0: Not AUTOSET mode */ + mt_reg_sync_writel(temp, AUXADC_CON0_V); /* disable auxadc channel 11 synchronous mode */ + mt_reg_sync_writel(0x800, AUXADC_CON1_CLR_V); /* disable auxadc channel 11 immediate mode */ + + + for (i = 0; i < TS_LEN_ARRAY(tscpu_g_bank); i++) { + ret = tscpu_switch_bank(i); + thermal_reset_and_initial(); + + for (j = 0; j < tscpu_g_bank[i].ts_number; j++) { + tscpu_dprintk("%s i %d, j %d\n", __func__, i, j); + tscpu_thermal_tempADCPNP(tscpu_thermal_ADCValueOfMcu + (tscpu_g_bank[i].ts[j].type), j); + } + + mt_reg_sync_writel(TS_CONFIGURE_P, TEMPPNPMUXADDR); + mt_reg_sync_writel(0x3, TEMPADCWRITECTRL); + } + + mt_reg_sync_writel(0x800, AUXADC_CON1_SET_V); + + for (i = 0; i < TS_LEN_ARRAY(tscpu_g_bank); i++) { + ret = tscpu_switch_bank(i); + tscpu_thermal_enable_all_periodoc_sensing_point(i); + } + + return ret; +} + + +/** + * temperature2 to set the middle threshold for interrupting CPU. -275000 to disable it. + */ +static void set_tc_trigger_hw_protect(int temperature, int temperature2) +{ + int temp = 0; + int raw_high, raw_middle, raw_low; + + + /* temperature2=80000; test only */ + tscpu_dprintk("set_tc_trigger_hw_protect t1=%d t2=%d\n", temperature, temperature2); + + + /* temperature to trigger SPM state2 */ + raw_high = temperature_to_raw_room(temperature); + if (temperature2 > -275000) + raw_middle = temperature_to_raw_room(temperature2); + raw_low = temperature_to_raw_room(5000); + + + temp = readl(TEMPMONINT); + /* tscpu_printk("set_tc_trigger_hw_protect 1 TEMPMONINT:temp=0x%x\n",temp); */ + /* mt_reg_sync_writel(temp & 0x1FFFFFFF, TEMPMONINT); // disable trigger SPM interrupt */ + mt_reg_sync_writel(temp & 0x00000000, TEMPMONINT); /* disable trigger SPM interrupt */ + + + /* mt_reg_sync_writel(0x60000, TEMPPROTCTL);// set hot to wakeup event control */ + /* mt_reg_sync_writel(0x20000, TEMPPROTCTL);// set hot to wakeup event control */ + mt_reg_sync_writel(0x20000, TEMPPROTCTL); /* set hot to wakeup event control */ + + mt_reg_sync_writel(raw_low, TEMPPROTTA); + if (temperature2 > -275000) + mt_reg_sync_writel(raw_middle, TEMPPROTTB); /* register will remain unchanged if -275000... */ + + + mt_reg_sync_writel(raw_high, TEMPPROTTC); /* set hot to HOT wakeup event */ + + + /*trigger cold ,normal and hot interrupt */ + /* remove for temp mt_reg_sync_writel(temp | 0xE0000000, TEMPMONINT); // enable trigger SPM interrupt */ + /*Only trigger hot interrupt */ +#if defined(CONFIG_ARCH_MT6755)/*remove Tj=100C shutdown*/ + mt_reg_sync_writel(temp | 0x80000000, TEMPMONINT); /* enable trigger Hot SPM interrupt */ +#else + if (temperature2 > -275000) + mt_reg_sync_writel(temp | 0xC0000000, TEMPMONINT); /* enable trigger middle & Hot SPM interrupt */ + else + mt_reg_sync_writel(temp | 0x80000000, TEMPMONINT); /* enable trigger Hot SPM interrupt */ +#endif +} + + +static int read_tc_raw_and_temp(volatile u32 *tempmsr_name, thermal_sensor_name ts_name, + int *ts_raw) +{ + int temp = 0, raw = 0; + + raw = (tempmsr_name != 0) ? (readl((tempmsr_name)) & 0x0fff) : 0; + temp = (tempmsr_name != 0) ? raw_to_temperature_roomt(raw, ts_name) : 0; + + *ts_raw = raw; + tscpu_dprintk("read_tc_raw_temp,ts_raw=%d,temp=%d\n", *ts_raw, temp * 100); + + return temp * 100; +} + + +void tscpu_thermal_read_bank_temp(thermal_bank_name bank, ts_e type, int order) +{ + + tscpu_dprintk("%s bank %d type %d order %d\n", __func__, bank, type, order); + + switch (order) { + case 0: + tscpu_bank_ts[bank][type] = + read_tc_raw_and_temp((volatile u32 *)TEMPMSR0, type, + &tscpu_bank_ts_r[bank][type]); + tscpu_dprintk("%s order %d bank %d type %d tscpu_bank_ts %d tscpu_bank_ts_r %d\n", + __func__, order, bank, type, tscpu_bank_ts[bank][type], + tscpu_bank_ts_r[bank][type]); + break; + case 1: + tscpu_bank_ts[bank][type] = + read_tc_raw_and_temp((volatile u32 *)TEMPMSR1, type, + &tscpu_bank_ts_r[bank][type]); + tscpu_dprintk("%s order %d bank %d type %d tscpu_bank_ts %d tscpu_bank_ts_r %d\n", + __func__, order, bank, type, tscpu_bank_ts[bank][type], + tscpu_bank_ts_r[bank][type]); + break; + case 2: + tscpu_bank_ts[bank][type] = + read_tc_raw_and_temp((volatile u32 *)TEMPMSR2, type, + &tscpu_bank_ts_r[bank][type]); + tscpu_dprintk("%s order %d bank %d type %d tscpu_bank_ts %d tscpu_bank_ts_r %d\n", + __func__, order, bank, type, tscpu_bank_ts[bank][type], + tscpu_bank_ts_r[bank][type]); + break; + case 3: + tscpu_bank_ts[bank][type] = + read_tc_raw_and_temp((volatile u32 *)TEMPMSR3, type, + &tscpu_bank_ts_r[bank][type]); + tscpu_dprintk("%s order %d bank %d type %d tscpu_bank_ts %d tscpu_bank_ts_r %d\n", + __func__, order, bank, type, tscpu_bank_ts[bank][type], + tscpu_bank_ts_r[bank][type]); + break; + default: + tscpu_bank_ts[bank][type] = + read_tc_raw_and_temp((volatile u32 *)TEMPMSR0, type, + &tscpu_bank_ts_r[bank][type]); + tscpu_dprintk("%s order %d bank %d type %d tscpu_bank_ts %d tscpu_bank_ts_r %d\n", + __func__, order, bank, type, tscpu_bank_ts[bank][type], + tscpu_bank_ts_r[bank][type]); + break; + } +} + +int tscpu_thermal_fast_init(void) +{ + __u32 temp = 0; + __u32 cunt = 0; + /* __u32 temp1 = 0,temp2 = 0,temp3 = 0,count=0; */ + + /* tscpu_printk( "tscpu_thermal_fast_init\n"); */ + + + temp = 0xDA1; + mt_reg_sync_writel((0x00001000 + temp), PTPSPARE2); /* write temp to spare register */ + + mt_reg_sync_writel(1, TEMPMONCTL1); /* counting unit is 320 * 31.25us = 10ms */ + mt_reg_sync_writel(1, TEMPMONCTL2); /* sensing interval is 200 * 10ms = 2000ms */ + mt_reg_sync_writel(1, TEMPAHBPOLL); /* polling interval to check if temperature sense is ready */ + + mt_reg_sync_writel(0x000000FF, TEMPAHBTO); /* exceed this polling time, IRQ would be inserted */ + mt_reg_sync_writel(0x00000000, TEMPMONIDET0); /* times for interrupt occurrance */ + mt_reg_sync_writel(0x00000000, TEMPMONIDET1); /* times for interrupt occurrance */ + + mt_reg_sync_writel(0x0000000, TEMPMSRCTL0); /* temperature measurement sampling control */ + + /* this value will be stored to TEMPPNPMUXADDR (TEMPSPARE0) automatically by hw */ + mt_reg_sync_writel(0x1, TEMPADCPNP0); + mt_reg_sync_writel(0x2, TEMPADCPNP1); + mt_reg_sync_writel(0x3, TEMPADCPNP2); + mt_reg_sync_writel(0x4, TEMPADCPNP3); + +#if 0 + mt_reg_sync_writel(0x1100B420, TEMPPNPMUXADDR); /* AHB address for pnp sensor mux selection */ + mt_reg_sync_writel(0x1100B420, TEMPADCMUXADDR); /* AHB address for auxadc mux selection */ + mt_reg_sync_writel(0x1100B424, TEMPADCENADDR); /* AHB address for auxadc enable */ + mt_reg_sync_writel(0x1100B428, TEMPADCVALIDADDR); /* AHB address for auxadc valid bit */ + mt_reg_sync_writel(0x1100B428, TEMPADCVOLTADDR); /* AHB address for auxadc voltage output */ + +#else + mt_reg_sync_writel((__u32) PTPSPARE0_P, TEMPPNPMUXADDR); /* AHB address for pnp sensor mux selection */ + mt_reg_sync_writel((__u32) PTPSPARE0_P, TEMPADCMUXADDR); /* AHB address for auxadc mux selection */ + mt_reg_sync_writel((__u32) PTPSPARE1_P, TEMPADCENADDR); /* AHB address for auxadc enable */ + mt_reg_sync_writel((__u32) PTPSPARE2_P, TEMPADCVALIDADDR); /* AHB address for auxadc valid bit */ + mt_reg_sync_writel((__u32) PTPSPARE2_P, TEMPADCVOLTADDR); /* AHB address for auxadc voltage output */ +#endif + mt_reg_sync_writel(0x0, TEMPRDCTRL); /* read valid & voltage are at the same register */ + /* indicate where the valid bit is (the 12th bit is valid bit and 1 is valid) */ + mt_reg_sync_writel(0x0000002C, TEMPADCVALIDMASK); + mt_reg_sync_writel(0x0, TEMPADCVOLTAGESHIFT); /* do not need to shift */ + mt_reg_sync_writel(0x3, TEMPADCWRITECTRL); /* enable auxadc mux & pnp write transaction */ + + + /* enable all interrupt except filter sense and immediate sense interrupt */ + mt_reg_sync_writel(0x00000000, TEMPMONINT); + + + mt_reg_sync_writel(0x0000000F, TEMPMONCTL0); /* enable all sensing point (sensing point 2 is unused) */ + + + cunt = 0; + temp = readl(TEMPMSR0) & 0x0fff; + while (temp != 0xDA1 && cunt < 20) { + cunt++; + /* pr_debug("[Power/CPU_Thermal]0 temp=%d,cunt=%d\n",temp,cunt); */ + temp = readl(TEMPMSR0) & 0x0fff; + } + + cunt = 0; + temp = readl(TEMPMSR1) & 0x0fff; + while (temp != 0xDA1 && cunt < 20) { + cunt++; + /* pr_debug("[Power/CPU_Thermal]1 temp=%d,cunt=%d\n",temp,cunt); */ + temp = readl(TEMPMSR1) & 0x0fff; + } + + cunt = 0; + temp = readl(TEMPMSR2) & 0x0fff; + while (temp != 0xDA1 && cunt < 20) { + cunt++; + /* pr_debug("[Power/CPU_Thermal]2 temp=%d,cunt=%d\n",temp,cunt); */ + temp = readl(TEMPMSR2) & 0x0fff; + } + + cunt = 0; + temp = readl(TEMPMSR3) & 0x0fff; + while (temp != 0xDA1 && cunt < 20) { + cunt++; + /* pr_debug("[Power/CPU_Thermal]3 temp=%d,cunt=%d\n",temp,cunt); */ + temp = readl(TEMPMSR3) & 0x0fff; + } + + + + + return 0; +} + +int tscpu_switch_bank(thermal_bank_name bank) +{ + /* tscpu_dprintk( "tscpu_switch_bank =bank=%d\n",bank); */ + + switch (bank) { + case THERMAL_BANK0: /* CPU (TSMCU2) */ + thermal_clrl(PTPCORESEL, 0xF); /* bank0 */ + break; + case THERMAL_BANK1: /* GPU (TSMCU1) */ + thermal_clrl(PTPCORESEL, 0xF); + thermal_setl(PTPCORESEL, 0x1); /* bank1 */ + break; + case THERMAL_BANK2: /* LTE (TSMCU3) */ + thermal_clrl(PTPCORESEL, 0xF); + thermal_setl(PTPCORESEL, 0x2); /* bank2 */ + break; + default: + thermal_clrl(PTPCORESEL, 0xF); /* bank0 */ + break; + } + return 0; +} + +void tscpu_thermal_initial_all_bank(void) +{ + unsigned long flags; + + mt_ptp_lock(&flags); + + thermal_config_Bank(); + + mt_ptp_unlock(&flags); +} + +void tscpu_config_all_tc_hw_protect(int temperature, int temperature2) +{ + int i = 0; + int wd_api_ret; + unsigned long flags; + struct wd_api *wd_api; + + tscpu_dprintk("tscpu_config_all_tc_hw_protect,temperature=%d,temperature2=%d,\n", + temperature, temperature2); + +#if THERMAL_PERFORMANCE_PROFILE + struct timeval begin, end; + unsigned long val; + + do_gettimeofday(&begin); +#endif + /*spend 860~1463 us */ + /*Thermal need to config to direct reset mode + this API provide by Weiqi Fu(RGU SW owner). */ + + wd_api_ret = get_wd_api(&wd_api); + if (wd_api_ret >= 0) { + wd_api->wd_thermal_direct_mode_config(WD_REQ_DIS, WD_REQ_RST_MODE); /* reset mode */ + } else { + tscpu_warn("%d FAILED TO GET WD API\n", __LINE__); + BUG(); + } + +#if THERMAL_PERFORMANCE_PROFILE + do_gettimeofday(&end); + + /* Get milliseconds */ + pr_debug("resume time spent, sec : %lu , usec : %lu\n", (end.tv_sec - begin.tv_sec), + (end.tv_usec - begin.tv_usec)); +#endif + + mt_ptp_lock(&flags); + + for (i = 0; i < TS_LEN_ARRAY(tscpu_g_bank); i++) { + tscpu_switch_bank(i); + + set_tc_trigger_hw_protect(temperature, temperature2); /* Move thermal HW protection ahead... */ + } + + mt_ptp_unlock(&flags); + + + /*Thermal need to config to direct reset mode + this API provide by Weiqi Fu(RGU SW owner). */ + wd_api->wd_thermal_direct_mode_config(WD_REQ_EN, WD_REQ_RST_MODE); /* reset mode */ + +} + +void tscpu_reset_thermal(void) +{ + int temp = 0; + /* reset thremal ctrl */ + temp = readl(INFRA_GLOBALCON_RST_0_SET); + temp |= 0x00000001; /* 1: Enables thermal control software reset */ + mt_reg_sync_writel(temp, INFRA_GLOBALCON_RST_0_SET); + + /* un reset */ + temp = readl(INFRA_GLOBALCON_RST_0_CLR); + temp |= 0x00000001; /* 1: Enable reset Disables thermal control software reset */ + mt_reg_sync_writel(temp, INFRA_GLOBALCON_RST_0_CLR); +} + +int tscpu_read_temperature_info(struct seq_file *m, void *v) +{ + + + seq_printf(m, "current temp:%d\n", tscpu_read_curr_temp); + seq_printf(m, "calefuse1:0x%x\n", calefuse1); + seq_printf(m, "calefuse2:0x%x\n", calefuse2); + seq_printf(m, "calefuse3:0x%x\n", calefuse3); + seq_printf(m, "g_adc_ge_t:%d\n", g_adc_ge_t); + seq_printf(m, "g_adc_oe_t:%d\n", g_adc_oe_t); + seq_printf(m, "g_degc_cali:%d\n", g_degc_cali); + seq_printf(m, "g_adc_cali_en_t:%d\n", g_adc_cali_en_t); + seq_printf(m, "g_o_slope:%d\n", g_o_slope); + seq_printf(m, "g_o_slope_sign:%d\n", g_o_slope_sign); + seq_printf(m, "g_id:%d\n", g_id); + seq_printf(m, "g_o_vtsmcu1:%d\n", g_o_vtsmcu1); + seq_printf(m, "g_o_vtsmcu2:%d\n", g_o_vtsmcu2); + seq_printf(m, "g_o_vtsabb:%d\n", g_o_vtsabb); + + return 0; +} + +int tscpu_get_curr_temp(void) +{ + tscpu_update_tempinfo(); + +#if PRECISE_HYBRID_POWER_BUDGET + /* update CPU/GPU temp data whenever TZ times out... + If the update timing is aligned to TZ polling, + this segment should be moved to TZ code instead of thermal controller driver + */ + tscpu_prev_cpu_temp = tscpu_curr_cpu_temp; + tscpu_prev_gpu_temp = tscpu_curr_gpu_temp; + + /* It is platform dependent which TS is better to present CPU/GPU temperature */ + tscpu_curr_cpu_temp = get_immediate_ts4_wrap(); /* TS4 for Jade GPU */ + tscpu_curr_gpu_temp = get_immediate_ts3_wrap(); /* TS3 for Jade CPU */ +#endif + + return tscpu_max_temperature(); +} + +#ifdef CONFIG_OF +int get_io_reg_base(void) +{ + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-therm_ctrl"); + BUG_ON(node == 0); + if (node) { + /* Setup IO addresses */ + thermal_base = of_iomap(node, 0); + /*tscpu_printk("[THERM_CTRL] thermal_base=0x%p\n",thermal_base); */ + } + + /*get thermal irq num */ + thermal_irq_number = irq_of_parse_and_map(node, 0); + /*tscpu_printk("[THERM_CTRL] thermal_irq_number=%d\n", thermal_irq_number);*/ + if (!thermal_irq_number) { + tscpu_printk("[THERM_CTRL] get irqnr failed=%d\n", thermal_irq_number); + return 0; + } + + of_property_read_u32(node, "reg", &thermal_phy_base); + /*tscpu_printk("[THERM_CTRL] thermal_base thermal_phy_base=0x%x\n",thermal_phy_base); */ + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-auxadc"); + BUG_ON(node == 0); + if (node) { + /* Setup IO addresses */ + auxadc_ts_base = of_iomap(node, 0); + /*tscpu_printk("[THERM_CTRL] auxadc_ts_base=0x%p\n",auxadc_ts_base); */ + } + of_property_read_u32(node, "reg", &auxadc_ts_phy_base); + /*tscpu_printk("[THERM_CTRL] auxadc_ts_phy_base=0x%x\n",auxadc_ts_phy_base); */ + + node = of_find_compatible_node(NULL, NULL, "mediatek,INFRACFG_AO"); + BUG_ON(node == 0); + if (node) { + /* Setup IO addresses */ + infracfg_ao_base = of_iomap(node, 0); + /*tscpu_printk("[THERM_CTRL] infracfg_ao_base=0x%p\n",infracfg_ao_base); */ + } + + + node = of_find_compatible_node(NULL, NULL, "mediatek,APMIXED"); + BUG_ON(node == 0); + if (node) { + /* Setup IO addresses */ + th_apmixed_base = of_iomap(node, 0); + /*tscpu_printk("[THERM_CTRL] th_apmixed_base=0x%p\n",th_apmixed_base); */ + } + of_property_read_u32(node, "reg", &apmixed_phy_base); + /*tscpu_printk("[THERM_CTRL] apmixed_phy_base=0x%x\n",apmixed_phy_base); */ + +#if THERMAL_GET_AHB_BUS_CLOCK + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-infrasys"); + if (!node) { + pr_err("[CLK_INFRACFG_AO] find node failed\n"); + return 0; + } + + therm_clk_infracfg_ao_base = of_iomap(node, 0); + if (!therm_clk_infracfg_ao_base) { + pr_err("[CLK_INFRACFG_AO] base failed\n"); + return 0; + } +#endif + return 1; +} +#endif + +#if THERMAL_GET_AHB_BUS_CLOCK +void thermal_get_AHB_clk_info(void) +{ + int cg = 0, dcm = 0, cg_freq = 0; + int clockSource = 136, ahbClk = 0; /*Need to confirm with DE*/ + + cg = readl(THERMAL_CG); + dcm = readl(THERMAL_DCM); + + /*The following rule may change, you need to confirm with DE. + These are for mt6755, and confirmed with DE Justin Gu */ + cg_freq = dcm & _BITMASK_(9:5); + + if ((cg_freq & _BIT_(4)) == 1) + ahbClk = clockSource / 2; + else if ((cg_freq & _BIT_(3)) == 1) + ahbClk = clockSource / 4; + else if ((cg_freq & _BIT_(2)) == 1) + ahbClk = clockSource / 8; + else if ((cg_freq & _BIT_(1)) == 1) + ahbClk = clockSource / 16; + else + ahbClk = clockSource / 32; + + /*tscpu_printk("cg %d dcm %d\n", ((cg & _BIT_(10)) >> 10), dcm);*/ + /*tscpu_printk("AHB bus clock= %d MHz\n", ahbClk);*/ +} +#endif diff --git a/drivers/misc/mediatek/uart/mt6755/Makefile b/drivers/misc/mediatek/uart/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b27456b2576317cfbe72dd1ff772d2e1362c8537 --- /dev/null +++ b/drivers/misc/mediatek/uart/mt6755/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +#ccflags-y += -DCONFIG_MTK_FPGA +#ccflags-y += -DFIX_TO_26M + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/uart +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(CONFIG_MTK_PLATFORM) + +obj-$(CONFIG_MTK_SERIAL) := platform_uart.o diff --git a/drivers/misc/mediatek/uart/mt6755/platform_uart.c b/drivers/misc/mediatek/uart/mt6755/platform_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..c6c5e37d3863c1d0a4142188386d162618885936 --- /dev/null +++ b/drivers/misc/mediatek/uart/mt6755/platform_uart.c @@ -0,0 +1,2617 @@ +/* mediatek/platform/mt6755/kernel/drivers/uart/uart.c + * + * (C) Copyright 2008 + * MediaTek + * MingHsien Hsieh + * + * MT6755 UART Driver + * + * 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 +#include +#include +#include + +#if defined(CONFIG_MTK_CLKMGR) && !defined(CONFIG_MTK_FPGA) +#include +#include +#endif /* defined(CONFIG_MTK_CLKMGR) && !defined(CONFIG_MTK_FPGA)*/ + +#if defined(CONFIG_MTK_LEGACY) && !defined(CONFIG_MTK_FPGA) +#include "mach/mt_gpio.h" +#include +#endif /* defined(CONFIG_MTK_LEGACY) && !defined(CONFIG_MTK_FPGA)*/ + +#include +#include "include/mtk_uart.h" +#include "include/mtk_uart_intf.h" +#include +#include +#include +#include + +#if !defined(CONFIG_MTK_LEGACY) +/* #include */ + +#if defined(ENABLE_CONSOLE_DEBUG) +static unsigned long uart_infra_base; +#endif /*--ENABLE_CONSOLE_DEBUG--*/ + +struct pinctrl *ppinctrl_uart[UART_NR]; +/* pinctrl-names from dtsi.GPIO operations: rx set, rx clear, tx set, tx clear */ +char *uart_gpio_cmds[UART_NR][4] = { + {"uart0_rx_set", "uart0_rx_clear", "uart0_tx_set", "uart0_tx_clear"}, + {"uart1_rx_set", "uart1_rx_clear", "uart1_tx_set", "uart1_tx_clear"}, +#if 0 +#if !defined(CONFIG_MTK_FPGA) + {"uart2_rx_set", "uart2_rx_clear", "uart2_tx_set", "uart2_tx_clear"}, + {"uart3_rx_set", "uart3_rx_clear", "uart3_tx_set", "uart3_tx_clear"}, +#endif /* !defined (CONFIG_MTK_FPGA) */ +#endif +}; + +void set_uart_pinctrl(int idx, struct pinctrl *ppinctrl) +{ + pr_debug("[UART%d][CCF]%s(%d,%p), UART_NR:%d\n", idx, __func__, idx, ppinctrl, UART_NR); + if (idx >= UART_NR) + return; + ppinctrl_uart[idx] = ppinctrl; +} +#endif /* !defined(CONFIG_MTK_LEGACY) */ + +#if !defined(CONFIG_MTK_FPGA) && !defined(CONFIG_MTK_CLKMGR) +/* struct clk *clk_uart_main; */ +struct clk *clk_uart_dma; +void set_uart_dma_clk(int idx, struct clk *dma_clk) +{ + pr_debug("[UART%d][CCF]enabled clk_uart%d_dma:%p\n", idx, idx, dma_clk); + clk_uart_dma = dma_clk; +} +#endif /* !defined(CONFIG_MTK_FPGA) && !defined(CONFIG_MTK_CLKMGR) */ + +#ifdef ENABLE_RAW_DATA_DUMP +static void save_tx_raw_data(struct mtk_uart *uart, void *addr); +static void reset_rx_raw_data(struct mtk_uart *uart); +static void save_rx_raw_data(struct mtk_uart *uart, const unsigned char *chars, size_t size); +volatile unsigned int stop_update = 0; +unsigned int curr_record = -1; +volatile unsigned int curr_idx; +#define RECORD_NUMBER 10 +#define RECORD_LENGTH 1032 +unsigned char uart_history[RECORD_NUMBER][RECORD_LENGTH]; +unsigned int uart_history_cnt[RECORD_NUMBER]; +spinlock_t tx_history_lock, rx_history_lock; + +unsigned int curr_rx_record = -1; +volatile unsigned int curr_rx_idx; +unsigned char uart_rx_history[RECORD_NUMBER][RECORD_LENGTH]; +unsigned int uart_rx_history_cnt[RECORD_NUMBER]; +#endif +/*---------------------------------------------------------------------------*/ +static struct mtk_uart_setting mtk_uart_default_settings[] = { + { + /* .tx_mode = UART_NON_DMA, .rx_mode = UART_RX_VFIFO_DMA, .dma_mode = UART_DMA_MODE_0, */ + .tx_mode = UART_TX_VFIFO_DMA, .rx_mode = UART_RX_VFIFO_DMA, .dma_mode = UART_DMA_MODE_0, + /* .tx_mode = UART_NON_DMA, .rx_mode = UART_NON_DMA, .dma_mode = UART_DMA_MODE_0, */ + .tx_trig = UART_FCR_TXFIFO_1B_TRI, .rx_trig = UART_FCR_RXFIFO_12B_TRI, + + /* .uart_base = AP_UART0_BASE, .irq_num = UART0_IRQ_BIT_ID, .irq_sen = MT_LEVEL_SENSITIVE, */ +#if defined(CONFIG_MTK_CLKMGR) && !defined(CONFIG_MTK_FPGA) + .set_bit = PDN_FOR_UART1, .clr_bit = PDN_FOR_UART1, .pll_id = PDN_FOR_UART1, +#endif /* defined(CONFIG_MTK_CLKMGR) || defined(CONFIG_MTK_FPGA) */ + .sysrq = FALSE, .hw_flow = TRUE, .vff = TRUE, + }, + { + .tx_mode = UART_TX_VFIFO_DMA, .rx_mode = UART_RX_VFIFO_DMA, .dma_mode = UART_DMA_MODE_0, + .tx_trig = UART_FCR_TXFIFO_1B_TRI, .rx_trig = UART_FCR_RXFIFO_12B_TRI, + + /* .uart_base = AP_UART1_BASE, .irq_num = UART1_IRQ_BIT_ID, .irq_sen = MT_LEVEL_SENSITIVE, */ +#if defined(CONFIG_MTK_CLKMGR) && !defined(CONFIG_MTK_FPGA) + .set_bit = PDN_FOR_UART2, .clr_bit = PDN_FOR_UART2, .pll_id = PDN_FOR_UART2, +#endif /* defined(CONFIG_MTK_CLKMGR) || defined(CONFIG_MTK_FPGA) */ + .sysrq = FALSE, .hw_flow = TRUE, .vff = TRUE, + }, +#if 0 + { + .tx_mode = UART_TX_VFIFO_DMA, .rx_mode = UART_RX_VFIFO_DMA, .dma_mode = UART_DMA_MODE_0, + .tx_trig = UART_FCR_TXFIFO_1B_TRI, .rx_trig = UART_FCR_RXFIFO_12B_TRI, + + /* .uart_base = AP_UART2_BASE, .irq_num = UART2_IRQ_BIT_ID, .irq_sen = MT_LEVEL_SENSITIVE, */ + .set_bit = PDN_FOR_UART3, .clr_bit = PDN_FOR_UART3, .pll_id = PDN_FOR_UART3, + .sysrq = FALSE, .hw_flow = FALSE, .vff = TRUE, /* UART3 */ + }, + { + .tx_mode = UART_NON_DMA, .rx_mode = UART_NON_DMA, .dma_mode = UART_DMA_MODE_0, + .tx_trig = UART_FCR_TXFIFO_1B_TRI, .rx_trig = UART_FCR_RXFIFO_12B_TRI, + + /* .uart_base = AP_UART3_BASE, .irq_num = UART3_IRQ_BIT_ID, .irq_sen = MT_LEVEL_SENSITIVE, */ + .set_bit = PDN_FOR_UART4, .clr_bit = PDN_FOR_UART4, .pll_id = PDN_FOR_UART4, + .sysrq = FALSE, .hw_flow = FALSE, .vff = FALSE, /* UART4 */ + }, +#endif +}; + +/*---------------------------------------------------------------------------*/ +static unsigned long mtk_uart_evt_mask[] = { + DBG_EVT_NONE, + DBG_EVT_NONE, + DBG_EVT_NONE, + DBG_EVT_NONE, +}; + +/*---------------------------------------------------------------------------*/ +static unsigned long mtk_uart_lsr_status[] = { + 0, /* UART1 */ + 0, /* UART2 */ + 0, /* UART3 */ + 0, /* UART4 */ +}; + +/*---------------------------------------------------------------------------*/ +#if defined(CONFIG_MTK_SERIAL_MODEM_TEST) + /* #define HW_MISC (CONFIG_BASE+0x0020) // mtk does NOT has this register */ + /* unsigned char mask[UART_NR] = { 1 << 3, 1 << 4, 1 << 5, 1 << 6}; */ +static unsigned int modem_uart[UART_NR] = { 1, 0, 0, 1}; +#endif +/*---------------------------------------------------------------------------*/ +/* uart control blocks */ +static struct mtk_uart mtk_uarts[UART_NR]; +/*---------------------------------------------------------------------------*/ +struct mtk_uart_setting *get_uart_default_settings(int idx) +{ + return &mtk_uart_default_settings[idx]; +} + +/*---------------------------------------------------------------------------*/ +void set_uart_default_settings(int idx) +{ + struct device_node *node = NULL; +#if defined(ENABLE_CONSOLE_DEBUG) + struct device_node *np = NULL; + struct device_node *npnode = NULL; +#endif /*--ENABLE_CONSOLE_DEBUG--*/ + unsigned int irq_info[3] = { 0, 0, 0 }; + u32 phys_base; + + switch (idx) { + case 0: + node = of_find_node_by_name(NULL, "apuart0"); + break; + case 1: + node = of_find_node_by_name(NULL, "apuart1"); + break; +/* + case 2: + node = of_find_node_by_name(NULL, "apuart2"); + break; + case 3: + node = of_find_node_by_name(NULL, "apuart3"); + break; +*/ + default: + break; + } + + if (node) { + /* iomap registers */ + mtk_uart_default_settings[idx].uart_base = (unsigned long)of_iomap(node, 0); + /* get IRQ ID */ + mtk_uart_default_settings[idx].irq_num = irq_of_parse_and_map(node, 0); + } + + /* phys registers */ + if (of_property_read_u32_index(node, "reg", 0, &phys_base)) + pr_debug("[UART%d] get phys regs from DTS fail!!\n", idx); + + mtk_uart_default_settings[idx].uart_phys_base = phys_base; + + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) + pr_debug("[UART%d] get irq flags from DTS fail!!\n", idx); + + mtk_uart_default_settings[idx].irq_flags = (unsigned long)irq_info[2]; + pr_debug("[UART%d] phys_regs=0x%lx, regs=0x%lx, irq=%d, irq_flags=0x%lx\n", idx, + mtk_uart_default_settings[idx].uart_phys_base, mtk_uart_default_settings[idx].uart_base, + mtk_uart_default_settings[idx].irq_num, mtk_uart_default_settings[idx].irq_flags); + +#if defined(ENABLE_CONSOLE_DEBUG) + if (!idx) { + np = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-infrasys"); + npnode = of_node_get(np); + if (npnode) { + uart_infra_base = (unsigned long)of_iomap(npnode, 0); + of_node_put(npnode); + of_node_put(np); + } else { + pr_err("uart infrasys node = NULL\n"); + of_node_put(np); + } + } +#endif /*--ENABLE_CONSOLE_DEBUG--*/ +} + +/*---------------------------------------------------------------------------*/ +void *get_apdma_uart0_base(void) +{ + struct device_node *node = NULL; + void *base; + + node = of_find_node_by_name(NULL, "apuart0"); + base = of_iomap(node, 1); + + pr_debug("[UART] apdma uart0 base=0x%p\n", base); + return base; +} + +/*---------------------------------------------------------------------------*/ +unsigned int get_uart_vfifo_irq_id(int idx) +{ + struct device_node *node = NULL; + unsigned int irq_id; + + switch (idx) { + case 0: + case 1: + node = of_find_node_by_name(NULL, "apuart0"); + break; + case 2: + case 3: + node = of_find_node_by_name(NULL, "apuart1"); + break; + case 4: + case 5: + node = of_find_node_by_name(NULL, "apuart2"); + break; + case 6: + case 7: + node = of_find_node_by_name(NULL, "apuart3"); + break; + default: + break; + } + if (idx % 2 == 0) + irq_id = irq_of_parse_and_map(node, 1); + else + irq_id = irq_of_parse_and_map(node, 2); + pr_debug("[UART_DMA%d] irq=%d\n", idx, irq_id); + + return irq_id; +} + +/*---------------------------------------------------------------------------*/ +unsigned long get_uart_evt_mask(int idx) +{ + return mtk_uart_evt_mask[idx]; +} + +/*---------------------------------------------------------------------------*/ +void set_uart_evt_mask(int idx, int value) +{ + mtk_uart_evt_mask[idx] = value; +} + +/*---------------------------------------------------------------------------*/ +unsigned long get_uart_lsr_status(int idx) +{ + return mtk_uart_lsr_status[idx]; +} + +/*---------------------------------------------------------------------------*/ +void set_uart_lsr_status(int idx, int value) +{ + mtk_uart_lsr_status[idx] = value; +} + +/*---------------------------------------------------------------------------*/ +unsigned int get_modem_uart(int idx) +{ +#if defined(CONFIG_MTK_SERIAL_MODEM_TEST) + return modem_uart[idx]; +#else + return 0; +#endif +} + +/*---------------------------------------------------------------------------*/ +#ifdef UART_FCR_USING_SW_BACK_UP +static inline void __write_fcr_register(struct mtk_uart *uart, u32 data) +{ + unsigned long base = uart->base; + + uart->fcr_back_up = data & (~(3 << 1)); + reg_sync_writel(data, UART_FCR); +} + +static inline void sync_write_fcr_register(struct mtk_uart *uart, u32 data) +{ + unsigned long base = uart->base; + + uart->fcr_back_up = data & (~(3 << 1)); + reg_sync_writel(data, UART_FCR); +} + +static inline u32 __read_fcr_register(struct mtk_uart *uart) +{ + return uart->fcr_back_up; +} + +static inline void __set_fcr_register(struct mtk_uart *uart, u32 mask) +{ + unsigned long base = uart->base; + u32 new_setting = (uart->fcr_back_up) | mask; + + uart->fcr_back_up = new_setting & (~(3 << 1)); + reg_sync_writel(new_setting, UART_FCR); +} + +static inline void __clr_fcr_register(struct mtk_uart *uart, u32 mask) +{ + unsigned long base = uart->base; + u32 new_setting = (uart->fcr_back_up) & (~mask); + + uart->fcr_back_up = new_setting & (~(3 << 1)); + reg_sync_writel(new_setting, UART_FCR); +} +#else +static inline void __write_fcr_register(struct mtk_uart *uart, u32 data) +{ + unsigned long base = uart->base; + + reg_sync_writel(data, UART_FCR); +} + +static inline void sync_write_fcr_register(struct mtk_uart *uart, u32 data) +{ + unsigned long base = uart->base; + + reg_sync_writel(data, UART_FCR); +} + +static inline u32 __read_fcr_register(struct mtk_uart *uart) +{ + unsigned long base = uart->base; + + return UART_READ32(UART_FCR_RD); +} + +static inline void __set_fcr_register(struct mtk_uart *uart, u32 mask) +{ + unsigned long base = uart->base; + u32 new_setting = UART_READ32(UART_FCR_RD) | mask; + + reg_sync_writel(new_setting, UART_FCR); +} + +static inline void __clr_fcr_register(struct mtk_uart *uart, u32 mask) +{ + unsigned long base = uart->base; + u32 new_setting = UART_READ32(UART_FCR_RD) & (~mask); + + reg_sync_writel(new_setting, UART_FCR); +} +#endif /* End of UART_FCR_USING_SW_BACK_UP */ +/*---------------------------------------------------------------------------*/ +static inline void dump_reg(struct mtk_uart *uart, const char *caller) +{ +#ifdef ENABLE_DEBUG + unsigned long flags; + unsigned long base = uart->base; + u32 lcr = UART_READ32(UART_LCR); + u32 uratefix = UART_READ32(UART_RATE_FIX_AD); + u32 uhspeed = UART_READ32(UART_HIGHSPEED); + u32 usamplecnt = UART_READ32(UART_SAMPLE_COUNT); + u32 usamplepnt = UART_READ32(UART_SAMPLE_POINT); + u32 udll, udlh; + u32 ier = UART_READ32(UART_IER); + + spin_lock_irqsave(&mtk_console_lock, flags); + reg_sync_writel((lcr | UART_LCR_DLAB), UART_LCR); + udll = UART_READ32(UART_DLL); + udlh = UART_READ32(UART_DLH); + mb(); /* make sure the DLL/DLH have been read */ + reg_sync_writel(lcr, UART_LCR); /* DLAB end */ + spin_unlock_irqrestore(&mtk_console_lock, flags); + mb(); + + MSG(CFG, "%s: RATEFIX(%02X); HSPEED(%02X); CNT(%02X); PNT(%02X); DLH(%02X), DLL(%02X), IER(%02X)\n", + caller, uratefix, uhspeed, usamplecnt, usamplepnt, udlh, udll, ier); +#endif +} + +#if defined(ENABLE_CONSOLE_DEBUG) +void dump_console_reg(struct mtk_uart *uart, char *s) +{ + unsigned long base; + u32 lsr = 0, escape_en = 0, clk = 0; + u32 hs = 0, sc = 0, dll = 0, dlm = 0; + u32 infra = 0; + char dump_uart[63]; + + memset(dump_uart, 0x00, sizeof(dump_uart)); + base = uart->base; + + if (uart_infra_base) { + infra = UART_INFRA_READ32(UART_INFRA(uart_infra_base)); + infra = ((infra >> 22) & 0x3); + } + + /*--uart 0 clk default enable--*/ + if (uart->poweron_count) { + lsr = UART_READ32(UART_LSR); + escape_en = UART_READ32(UART_ESCAPE_EN); + clk = uart->poweron_count; + hs = UART_READ32(UART_HIGHSPEED); + sc = UART_READ32(UART_SAMPLE_COUNT); + reg_sync_writel(0x1, UART_FEATURE_SEL); + dll = UART_READ32(UART_DLL_E); + dlm = UART_READ32(UART_DLH_E); + } else + clk = 0; + + /*scnprintf(dump_uart, sizeof(dump_uart), + "uart0,lsr=%d,es_en=%d,clk=%d,hs=%d,sc=%d,dll=%d,dlm=%d, dl=%d, dlh=%d\n", + lsr, escape_en, clk, hs, sc, dll, dlm, uart->registers.dll, uart->registers.dlh);*/ + scnprintf(dump_uart, sizeof(dump_uart), + "lsr=%d,hs=%d,sc=%d,dl=%d,dm=%d,cnt1=%d,cnt2=%d,infra=%x,clk=%d\n", + lsr, hs, sc, dll, dlm, uart->cnt1, uart->cnt2, infra, clk); + + strcpy(s, dump_uart); + + /*aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_DEFAULT | DB_OPT_FTRACE, + "Dump Uart Reg", "%s", dump_uart);*/ +} +#endif /*--ENABLE_CONSOLE_DEBUG--*/ + +void dump_uart_reg(void) +{ + struct mtk_uart *uart; + unsigned int i; + unsigned long base; + u32 lsr, escape_en; + + for (i = 0; i < UART_NR; i++) { + uart = &mtk_uarts[i]; + base = uart->base; + if (uart->poweron_count > 0) { + lsr = UART_READ32(UART_LSR); + escape_en = UART_READ32(UART_ESCAPE_EN); + pr_debug("[UART%d] LSR=0x%x ESCAPE_EN=0x%x\n", uart->nport, lsr, escape_en); + } else + pr_debug("[UART%d] clock is off\n", uart->nport); + } + +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_console_setting_switch(struct mtk_uart *uart) +{ +#ifdef CONFIG_MTK_SERIAL_CONSOLE + /* if(uart->nport == 0){ */ /* UART1 as log port */ + uart->setting->tx_mode = UART_NON_DMA; + uart->setting->rx_mode = UART_NON_DMA; + uart->tx_mode = UART_NON_DMA; + uart->rx_mode = UART_NON_DMA; + mtk_uart_enable_dpidle(uart); + /* } */ +#endif +} + +/****************************************************************************** + * Virtual FIFO implementation +******************************************************************************/ +#if defined(ENABLE_VFIFO) +/*---------------------------------------------------------------------------*/ +int mtk_uart_vfifo_enable(struct mtk_uart *uart, struct mtk_uart_vfifo *vfifo) +{ + unsigned long base = uart->base; + + if (!vfifo) { + MSG(ERR, "null\n"); + return -EINVAL; + } else if (vfifo->type != UART_RX_VFIFO && vfifo->type != UART_TX_VFIFO) { + MSG(ERR, "unknown type: %d\n", vfifo->type); + return -EINVAL; + } + /* + * NOTE: For FCR is a read only register reason, + * special read/write/set/clr function need to use + */ + /*UART_SET_BITS(UART_FCR_FIFO_INIT, UART_FCR); + UART_CLR_BITS(UART_FCR_DMA1, UART_FCR); */ + __set_fcr_register(uart, UART_FCR_FIFO_INIT); + __clr_fcr_register(uart, UART_FCR_DMA1); + + if (vfifo->type == UART_RX_VFIFO) + UART_SET_BITS(UART_RX_DMA_EN | UART_TO_CNT_AUTORST, UART_DMA_EN); + else if (vfifo->type == UART_TX_VFIFO) + UART_SET_BITS(UART_TX_DMA_EN, UART_DMA_EN); + mb(); + + return 0; +} + +/*---------------------------------------------------------------------------*/ +int mtk_uart_vfifo_disable(struct mtk_uart *uart, struct mtk_uart_vfifo *vfifo) +{ + unsigned long base = uart->base; + + if (!vfifo) { + MSG(ERR, "null\n"); + return -EINVAL; + } else if (vfifo->type != UART_RX_VFIFO && vfifo->type != UART_TX_VFIFO) { + MSG(ERR, "unknown type: %d\n", vfifo->type); + return -EINVAL; + } else if (vfifo->type == UART_RX_VFIFO) { + UART_CLR_BITS(UART_RX_DMA_EN | UART_TO_CNT_AUTORST, UART_DMA_EN); + } else if (vfifo->type == UART_TX_VFIFO) { + UART_CLR_BITS(UART_TX_DMA_EN, UART_DMA_EN); + } + mb(); + return 0; +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_vfifo_enable_tx_intr(struct mtk_uart *uart) +{ + reg_sync_writel(VFF_TX_INT_EN_B, VFF_INT_EN(uart->tx_vfifo->base)); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_vfifo_disable_tx_intr(struct mtk_uart *uart) +{ + reg_sync_writel(0x00, VFF_INT_EN(uart->tx_vfifo->base)); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_vfifo_clear_tx_intr(struct mtk_uart_vfifo *vfifo) +{ + reg_sync_writel(0x00, VFF_INT_FLAG(vfifo->base)); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_vfifo_clear_rx_intr(struct mtk_uart_vfifo *vfifo) +{ + reg_sync_writel(0x03, VFF_INT_FLAG(vfifo->base)); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_vfifo_enable_rx_intr(struct mtk_uart *uart) +{ + reg_sync_writel(VFF_RX_INT_EN0_B | VFF_RX_INT_EN1_B, VFF_INT_EN(uart->rx_vfifo->base)); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_vfifo_disable_rx_intr(struct mtk_uart *uart) +{ + reg_sync_writel(0x00, VFF_INT_EN(uart->rx_vfifo->base)); +} + +/*---------------------------------------------------------------------------*/ +int mtk_uart_vfifo_is_full(struct mtk_uart_vfifo *vfifo) +{ + return (UART_READ32(VFF_LEFT_SIZE(vfifo->base)) <= 16) ? (1) : (0); +} + +/*---------------------------------------------------------------------------*/ +int mtk_uart_vfifo_is_empty(struct mtk_uart_vfifo *vfifo) +{ + return (UART_READ32(VFF_VALID_SIZE(vfifo->base)) == 0) ? (1) : (0); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_vfifo_write_byte(struct mtk_uart *uart, unsigned int byte) +{ + void *addr, *base = uart->tx_vfifo->base; + unsigned int wpt = UART_READ32(VFF_WPT(base)); + + addr = (void *)((wpt & 0xffff) + uart->tx_vfifo->addr); + reg_sync_writeb((unsigned char)byte, addr); + mb(); /* make sure write point updated after VFIFO written. */ +#ifdef ENABLE_RAW_DATA_DUMP + save_tx_raw_data(uart, addr); +#endif + if ((wpt & 0xffff) == (UART_READ32(VFF_LEN(base)) - 1)) + reg_sync_writel((~wpt) & 0x10000, VFF_WPT(base)); + else + reg_sync_writel(wpt + 1, VFF_WPT(base)); +} + +/*---------------------------------------------------------------------------*/ +unsigned int mtk_uart_vfifo_read_byte(struct mtk_uart *uart) +{ + void *addr, *base = uart->rx_vfifo->base; + unsigned int ch; + + addr = (void *)(UART_READ16(VFF_RPT(base)) + uart->rx_vfifo->addr); + ch = UART_READ8(addr); + mb(); /* make sure read point updated after VFIFO read. */ + if (UART_READ16(VFF_RPT(base)) == (UART_READ32(VFF_LEN(base)) - 1)) + reg_sync_writel(~(UART_READ32(VFF_RPT(base))) & 0x10000, VFF_RPT(base)); + else + reg_sync_writel(UART_READ32(VFF_RPT(base)) + 1, VFF_RPT(base)); + + return ch; +} + +/*---------------------------------------------------------------------------*/ +int mtk_uart_vfifo_get_counts(struct mtk_uart_vfifo *vfifo) +{ + return UART_READ32(VFF_VALID_SIZE(vfifo->base)); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_tx_vfifo_flush(struct mtk_uart *uart, int timeout) +{ + struct mtk_uart_dma *dma = &uart->dma_tx; + struct mtk_uart_vfifo *vfifo = dma->vfifo; + void *base = vfifo->base; + +#ifdef ENABE_HRTIMER_FLUSH + if (dma && uart) { + if (UART_READ32(VFF_FLUSH(base)) == 0) { + reg_sync_writel(VFF_FLUSH_B, VFF_FLUSH(base)); + if (!timeout) + hrtimer_try_to_cancel(&vfifo->flush); + MSG(MSC, "flush [%5X.%5X]\n", UART_READ32(VFF_RPT(base)), UART_READ32(VFF_WPT(base))); + } else { + /*the ns used to transfer the data in TX VFIFO */ + u32 size = UART_READ32(VFF_VALID_SIZE(base)); + s64 t = size * 10 * (NSEC_PER_SEC / uart->baudrate); + ktime_t cur = ktime_get(); + ktime_t nxt = ktime_add_ns(cur, t); + + hrtimer_try_to_cancel(&vfifo->flush); + hrtimer_start(&vfifo->flush, nxt, HRTIMER_MODE_ABS); +#if defined(ENABLE_VFIFO_DEBUG) + { + struct timespec a = ktime_to_timespec(cur); + struct timespec b = ktime_to_timespec(nxt); + + MSG(MSC, "start: [%ld %ld] [%ld %ld] [%d %lld]\n", + a.tv_sec, a.tv_nsec, b.tv_sec, b.tv_nsec, size, t); + } +#endif + } + } else { + MSG(ERR, "%p, %p\n", dma, uart); + /* del_timer(&dma->vfifo->timer); */ + } +#else + if (dma && uart) { + if (UART_READ32(VFF_FLUSH(base)) == 0) { + reg_sync_writel(VFF_FLUSH_B, VFF_FLUSH(base)); + MSG(MSC, "flush [%5X.%5X]\n", UART_READ32(VFF_RPT(base)), UART_READ32(VFF_WPT(base))); + } + } else { + MSG(ERR, "%p, %p\n", dma, uart); + } +#endif /* ENABE_HRTIMER_FLUSH */ +} + +/*---------------------------------------------------------------------------*/ +static void mtk_uart_dma_vfifo_tx_tasklet_byte(unsigned long arg) +{ + struct mtk_uart *uart = (struct mtk_uart *)arg; + struct uart_port *port = &uart->port; + /* struct mtk_uart_dma *dma = &uart->dma_tx; */ + struct mtk_uart_vfifo *vfifo = uart->tx_vfifo; + struct circ_buf *xmit = &port->state->xmit; + unsigned int len, count, size, left, chk = 0; + ktime_t begin, end; + struct timespec a, b; + + size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + left = vfifo->size - mtk_uart_vfifo_get_counts(vfifo); + left = (left > 16) ? (left - 16) : (0); /*prevent from CPU lock */ + len = count = left < size ? left : size; + + if (!len) { + chk = 1; + MSG(DMA, ">>>>> zero size <<<<<\n"); + } + + DGBUF_INIT(vfifo); + begin = ktime_get(); + a = ktime_to_timespec(begin); + while (len--) { + /*DMA limitation. + Workaround: Polling flush bit to zero, set 1s timeout */ + while (UART_READ32(VFF_FLUSH(vfifo->base))) { + end = ktime_get(); + b = ktime_to_timespec(end); + if ((b.tv_sec - a.tv_sec) > 1 || ((b.tv_sec - a.tv_sec) == 1 && b.tv_nsec > a.tv_nsec)) { + pr_debug("[UART%d] Polling flush timeout\n", port->line); + return; + } + } + DGBUF_PUSH_CH(vfifo, (char)xmit->buf[xmit->tail]); + uart->write_byte(uart, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } +#if defined(ENABLE_VFIFO_DEBUG) + if (UART_DEBUG_EVT(DBG_EVT_DMA) && UART_DEBUG_EVT(DBG_EVT_BUF)) { + char str[4] = { 0 }; + + if (count >= 4) { + str[0] = vfifo->cur->dat[0]; + str[1] = vfifo->cur->dat[1]; + str[2] = vfifo->cur->dat[vfifo->cur->idx - 2]; + str[3] = vfifo->cur->dat[vfifo->cur->idx - 1]; + } else { + int idx; + + for (idx = 0; idx < count; idx++) + str[idx] = vfifo->cur->dat[idx]; + for (; idx < 4; idx++) + str[idx] = 0; + } + MSG(DMA, "TX[%4d]: %4d/%4d [%05X-%05X] (%02X %02X .. %02X %02X)\n", + size, count, left, UART_READ32(VFF_WPT(vfifo->base)), UART_READ32(VFF_RPT(vfifo->base)), + str[0], str[1], str[2], str[3]); + } else { + MSG(DMA, "TX[%4d]: %4d/%4d [%05X-%05X]\n", + size, count, left, UART_READ32(VFF_WPT(vfifo->base)), UART_READ32(VFF_RPT(vfifo->base))); + } +#endif + +#if defined(ENABLE_VFIFO_DEBUG) + if (UART_DEBUG_EVT(DBG_EVT_DAT) && UART_DEBUG_EVT(DBG_EVT_BUF)) { + int i; + + pr_debug("[UART%d_TX] %4d bytes:", uart->nport, vfifo->cur->idx); + for (i = 0; i < vfifo->cur->idx; i++) { + if (i % 16 == 0) + pr_debug("\n"); + pr_debug("%.2x ", (unsigned char)vfifo->cur->dat[i]); + } + pr_debug("\n"); + } +#endif + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + +} + +/*---------------------------------------------------------------------------*/ +/*static int mtk_uart_vfifo_write_string(struct mtk_uart *uart, const unsigned char *chars, size_t size) +{ + void *addr, *base = uart->tx_vfifo->base; + unsigned int wpt = UART_READ32(VFF_WPT(base)); + unsigned int num_to_end; + + addr = (void*)((wpt&0xffff)+uart->tx_vfifo->addr); + num_to_end = UART_READ32(VFF_LEN(base)) - (wpt&0xffff); + if(num_to_end >= size){ + memcpy(addr, chars, size); + mb(); //make sure write point updated after VFIFO written. + reg_sync_writel( wpt+(unsigned int)size, VFF_WPT(base)); + }else{ + memcpy(addr, chars, num_to_end); + memcpy(uart->tx_vfifo->addr, &chars[num_to_end], (unsigned int)size - num_to_end); + mb(); //make sure write point updated after VFIFO written. + wpt = ((~wpt)&0x10000)+ (unsigned int)size - num_to_end; + reg_sync_writel(wpt, VFF_WPT(base)); + } + + return size; +}*/ +/*---------------------------------------------------------------------------*/ +/*static void mtk_uart_dma_vfifo_tx_tasklet_str(unsigned long arg) +{ + struct mtk_uart *uart = (struct mtk_uart *)arg; + struct uart_port *port = &uart->port; + //struct mtk_uart_dma *dma = &uart->dma_tx; + struct mtk_uart_vfifo *vfifo = uart->tx_vfifo; + struct circ_buf *xmit = &port->state->xmit; + unsigned int len, count, size, left, chk = 0; + + size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + left = vfifo->size - mtk_uart_vfifo_get_counts(vfifo); + left = (left > 16) ? (left-16) : (0); + len = count = left < size ? left : size; + + if (!len) { + chk = 1; + MSG(DMA,">>>>> zero size <<<<<\n"); + } + + DGBUF_INIT(vfifo); + + mtk_uart_vfifo_write_string(uart, &xmit->buf[xmit->tail], size); + DGBUF_PUSH_STR(vfifo, &xmit->buf[xmit->tail], size); + xmit->tail = (xmit->tail+size) & (UART_XMIT_SIZE - 1); + port->icount.tx += size; + +#if defined(ENABLE_VFIFO_DEBUG) + if (UART_DEBUG_EVT(DBG_EVT_DMA) && UART_DEBUG_EVT(DBG_EVT_BUF)) { + char str[4] = {0}; + if (count >= 4) { + str[0] = vfifo->cur->dat[0]; + str[1] = vfifo->cur->dat[1]; + str[2] = vfifo->cur->dat[vfifo->cur->idx-2]; + str[3] = vfifo->cur->dat[vfifo->cur->idx-1]; + } else { + int idx; + for (idx = 0; idx < count; idx++) + str[idx] = vfifo->cur->dat[idx]; + for (; idx < 4; idx++) + str[idx] = 0; + } + MSG(DMA, "TX[%4d]: %4d/%4d [%05X-%05X] (%02X %02X .. %02X %02X)\n", + size, count, left, UART_READ32(VFF_WPT(vfifo->base)), UART_READ32(VFF_RPT(vfifo->base)), + str[0], str[1], str[2], str[3]); + } else { + MSG(DMA, "TX[%4d]: %4d/%4d [%05X-%05X]\n", + size, count, left, UART_READ32(VFF_WPT(vfifo->base)), UART_READ32(VFF_RPT(vfifo->base))); + } +#endif + +#if defined(ENABLE_VFIFO_DEBUG) + if (UART_DEBUG_EVT(DBG_EVT_DAT) && UART_DEBUG_EVT(DBG_EVT_BUF)) { + int i; + pr_debug("[UART%d_TX] %4d bytes:", uart->nport, vfifo->cur->idx); + for (i = 0; i < vfifo->cur->idx; i++) { + if (i % 16 == 0) + pr_debug("\n"); + pr_debug("%.2x ", (unsigned char)vfifo->cur->dat[i]); + } + pr_debug("\n"); + } +#endif + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + +}*/ +/*---------------------------------------------------------------------------*/ +void mtk_uart_dma_vfifo_tx_tasklet(unsigned long arg) +{ + struct mtk_uart *uart = (struct mtk_uart *)arg; + struct uart_port *port = &uart->port; + struct mtk_uart_dma *dma = &uart->dma_tx; + struct mtk_uart_vfifo *vfifo = uart->tx_vfifo; + struct circ_buf *xmit = &port->state->xmit; + int txcount = port->icount.tx; + void *base = vfifo->base; + unsigned long flags; + + spin_lock_irqsave(&vfifo->iolock, flags); + if (atomic_inc_and_test(&vfifo->entry) > 1) { + MSG(ERR, "tx entry!!\n"); + tasklet_schedule(&vfifo->dma->tasklet); + } else { + while (UART_READ32(VFF_LEFT_SIZE(base)) >= vfifo->trig) { + /* deal with x_char first */ + if (unlikely(port->x_char)) { + MSG(INFO, "detect x_char!!\n"); + uart->write_byte(uart, port->x_char); + port->icount.tx++; + port->x_char = 0; + break; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + uart->pending_tx_reqs = 0; + atomic_set(&dma->free, 1); + complete(&dma->done); + break; + } + mtk_uart_dma_vfifo_tx_tasklet_byte(arg); + } + if (txcount != port->icount.tx) { + mtk_uart_vfifo_enable_tx_intr(uart); + mtk_uart_tx_vfifo_flush(uart, 0); + } + } + atomic_dec(&vfifo->entry); + spin_unlock_irqrestore(&vfifo->iolock, flags); +} + +/*---------------------------------------------------------------------------*/ +/*static void mtk_uart_dma_vfifo_rx_tasklet_byte(unsigned long arg) +{ + struct mtk_uart *uart = (struct mtk_uart*)arg; + struct uart_port *port = &uart->port; + struct mtk_uart_vfifo *vfifo = uart->rx_vfifo; + struct tty_struct *tty = uart->port.state->port.tty; + int count, left; + unsigned int ch, flag, status; + unsigned long flags; + + MSG_FUNC_ENTRY(); + + count = left = mtk_uart_vfifo_get_counts(vfifo); + + spin_lock_irqsave(&port->lock, flags); + + DGBUF_INIT(vfifo); + while (!mtk_uart_vfifo_is_empty(vfifo) && count > 0) { + + status = uart->read_status(uart); + status = mtk_uart_filter_line_status(uart); + + ch = uart->read_byte(uart); + flag = TTY_NORMAL; + + if (status & UART_LSR_BI) { + MSG(INFO, "Break Interrupt!!!\n"); + port->icount.brk++; + if (uart_handle_break(port)) + continue; + flag = TTY_BREAK; + } else if (status & UART_LSR_PE) { + MSG(INFO, "Parity Error!!!\n"); + port->icount.parity++; + flag = TTY_PARITY; + } else if (status & UART_LSR_FE) { + MSG(INFO, "Frame Error!!!\n"); + port->icount.frame++; + flag = TTY_FRAME; + } else if (status & UART_LSR_OE) { + MSG(INFO, "Overrun!!!\n"); + port->icount.overrun++; + flag = TTY_OVERRUN; + } + port->icount.rx++; + count--; + DGBUF_PUSH_CH(vfifo, ch); + if (!tty_insert_flip_char(tty, ch, flag)) + MSG(ERR, "tty_insert_flip_char: no space\n"); + } + tty_flip_buffer_push(tty); + +#if defined(ENABLE_VFIFO_DEBUG) + if (UART_DEBUG_EVT(DBG_EVT_DMA) && UART_DEBUG_EVT(DBG_EVT_BUF)) { + char str[4] = {0}; + if (count >= 4) { + str[0] = vfifo->cur->dat[0]; + str[1] = vfifo->cur->dat[1]; + str[2] = vfifo->cur->dat[vfifo->cur->idx-2]; + str[3] = vfifo->cur->dat[vfifo->cur->idx-1]; + } else { + int idx; + for (idx = 0; idx < count; idx++) + str[idx] = vfifo->cur->dat[idx]; + for (; idx < 4; idx++) + str[idx] = 0; + } + MSG(DMA, "RX[%4d]: %4d bytes from VFIFO [%4d] (%02X %02X .. %02X %02X) %d\n", + left, left - count, mtk_uart_vfifo_get_counts(vfifo), str[0], str[1], str[2], str[3], + UART_READ32(VFF_VALID_SIZE(vfifo->base))); + } else { + MSG(DMA, "RX[%4d]: %4d bytes from VFIFO [%4d] %d\n", + left, left - count, mtk_uart_vfifo_get_counts(vfifo), + UART_READ32(VFF_VALID_SIZE(vfifo->base))); + } +#endif + + spin_unlock_irqrestore(&port->lock, flags); + +#if defined(ENABLE_VFIFO_DEBUG) + if (UART_DEBUG_EVT(DBG_EVT_DAT) && UART_DEBUG_EVT(DBG_EVT_BUF)) { + int i; + pr_debug("[UART%d_RX] %4d bytes:", uart->nport, vfifo->cur->idx); + + for (i = 0; i < vfifo->cur->idx; i++) { + if (i % 16 == 0) + pr_debug("\n"); + pr_debug("%.2x ", (unsigned char)vfifo->cur->dat[i]); + } + pr_debug("\n"); + + } +#endif +}*/ +/*---------------------------------------------------------------------------*/ +/* A duplicate of tty_insert_flip_string. */ +/* The only difference is the function will accept one extra variable for */ +/* indicating the current line status. */ +/*---------------------------------------------------------------------------*/ +static int mtk_uart_tty_insert_flip_string(struct mtk_uart *uart, const unsigned char *chars, size_t size) +{ + struct tty_struct *tty = uart->port.state->port.tty; + struct uart_port *port = &uart->port; + u32 status, flag; + int copied = 0; + + status = uart->read_status(uart); + status = mtk_uart_filter_line_status(uart); + + flag = TTY_NORMAL; + /* error handling routine */ + if (status & UART_LSR_BI) { + MSG(ERR, "Break Interrupt!!\n"); + port->icount.brk++; + if (uart_handle_break(port)) + return 0; + flag = TTY_BREAK; + } else if (status & UART_LSR_PE) { + MSG(ERR, "Parity Error!!!\n"); + port->icount.parity++; + flag = TTY_PARITY; + } else if (status & UART_LSR_FE) { + MSG(ERR, "Frame Error!!!\n"); + port->icount.frame++; + flag = TTY_FRAME; + } else if (status & UART_LSR_OE) { + MSG(ERR, "Overrun!!!\n"); + port->icount.overrun++; + flag = TTY_OVERRUN; + } +#ifdef ENABLE_RAW_DATA_DUMP + save_rx_raw_data(uart, chars, size); +#endif + + if (flag == TTY_NORMAL) { + copied = tty_insert_flip_string(tty->port, chars, size); + } else { + MSG(ERR, "error occurs\n"); + copied += tty_insert_flip_string(tty->port, chars, size - 1); + copied += tty_insert_flip_char(tty->port, chars[size - 1], flag); + } + port->icount.rx += copied; + return copied; +} + +/*---------------------------------------------------------------------------*/ +static void mtk_uart_dma_vfifo_rx_tasklet_str(unsigned long arg) +{ + struct mtk_uart *uart = (struct mtk_uart *)arg; + struct uart_port *port = &uart->port; + struct mtk_uart_vfifo *vfifo = uart->rx_vfifo; + struct tty_struct *tty = uart->port.state->port.tty; + int count, left; + unsigned int rxptr, txptr, txreg, rxreg; + unsigned long flags; + unsigned char *ptr; + void *base = vfifo->base; + + MSG_FUNC_ENTRY(); + + spin_lock_irqsave(&port->lock, flags); + + rxreg = UART_READ32(VFF_RPT(base)); + txreg = UART_READ32(VFF_WPT(base)); + rxptr = rxreg & 0x0000FFFF; + txptr = txreg & 0x0000FFFF; + count = left = ((rxreg ^ txreg) & 0x00010000) ? (txptr + vfifo->size - rxptr) : (txptr - rxptr); + + DGBUF_INIT(vfifo); + +#ifdef ENABLE_RAW_DATA_DUMP + reset_rx_raw_data(uart); +#endif + + if ((rxptr + count) <= txptr) { + ptr = (unsigned char *)(rxptr + vfifo->addr); + mtk_uart_tty_insert_flip_string(uart, ptr, count); + DGBUF_PUSH_STR(vfifo, ptr, count); + } else { + ptr = (unsigned char *)(rxptr + vfifo->addr); + mtk_uart_tty_insert_flip_string(uart, ptr, vfifo->size - rxptr); + DGBUF_PUSH_STR(vfifo, ptr, vfifo->size - rxptr); + if (txptr) { + ptr = (unsigned char *)(vfifo->addr); + mtk_uart_tty_insert_flip_string(uart, ptr, txptr); + DGBUF_PUSH_STR(vfifo, ptr, txptr); + } + } + mb(); /* make sure read point updated after VFIFO read. */ + reg_sync_writel(txreg, VFF_RPT(base)); + tty_flip_buffer_push(tty->port); + +#if defined(ENABLE_VFIFO_DEBUG) + if (UART_DEBUG_EVT(DBG_EVT_DMA) && UART_DEBUG_EVT(DBG_EVT_BUF)) { + char str[4] = { 0 }; + + if (count >= 4) { + str[0] = vfifo->cur->dat[0]; + str[1] = vfifo->cur->dat[1]; + str[2] = vfifo->cur->dat[vfifo->cur->idx - 2]; + str[3] = vfifo->cur->dat[vfifo->cur->idx - 1]; + } else { + int idx; + + for (idx = 0; idx < count; idx++) + str[idx] = vfifo->cur->dat[idx]; + for (; idx < 4; idx++) + str[idx] = 0; + } + MSG(DMA, "RX[%4d]: [%5X..%5X] [%5X..%5X] (%02X %02X .. %02X %02X) [%d]\n", + left, rxreg, txreg, UART_READ32(VFF_RPT(base)), UART_READ32(VFF_WPT(base)), + str[0], str[1], str[2], str[3], UART_READ32(VFF_FLUSH(base))); + } else { + MSG(DMA, "RX[%4d]: [%5X..%5X] [%5X..%5X] [%d] [%4X.%4X]\n", + left, rxreg, txreg, UART_READ32(VFF_RPT(base)), UART_READ32(VFF_WPT(base)), + UART_READ32(VFF_FLUSH(base)), UART_READ32(VFF_VALID_SIZE(base)), UART_READ32(VFF_LEFT_SIZE(base))); + } +#endif + spin_unlock_irqrestore(&port->lock, flags); + +#if defined(ENABLE_VFIFO_DEBUG) + if (UART_DEBUG_EVT(DBG_EVT_DAT) && UART_DEBUG_EVT(DBG_EVT_BUF)) { + int i; + + pr_debug("[UART%d_RX] %4d bytes:", uart->nport, vfifo->cur->idx); + + for (i = 0; i < vfifo->cur->idx; i++) { + if (i % 16 == 0) + pr_debug("\n"); + pr_debug("%.2x ", (unsigned char)vfifo->cur->dat[i]); + } + pr_debug("\n"); + + } +#endif +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_dma_vfifo_rx_tasklet(unsigned long arg) +{ /*the function will be called through dma irq or tasklet_schedule */ + struct mtk_uart *uart = (struct mtk_uart *)arg; + struct mtk_uart_vfifo *vfifo = uart->rx_vfifo; + unsigned long flags; + + MSG(DMA, "%d, %x, %x\n", uart->read_allow(uart), UART_READ32(VFF_VALID_SIZE(vfifo->base)), vfifo->trig); + spin_lock_irqsave(&vfifo->iolock, flags); + if (atomic_inc_and_test(&vfifo->entry) > 1) { + MSG(ERR, "rx entry!!\n"); + tasklet_schedule(&vfifo->dma->tasklet); + } else { + if (uart->read_allow(uart)) + mtk_uart_dma_vfifo_rx_tasklet_str(arg); + } + atomic_dec(&vfifo->entry); + spin_unlock_irqrestore(&vfifo->iolock, flags); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_dma_setup(struct mtk_uart *uart, struct mtk_uart_dma *dma) +{ + void *base; + + if (!dma) + return; + + if (dma->mode == UART_RX_VFIFO_DMA || dma->mode == UART_TX_VFIFO_DMA) { + if (!dma->vfifo) { + MSG(ERR, "null\n"); + return; + } + base = dma->vfifo->base; + reg_sync_writel(dma->vfifo->dmahd, VFF_ADDR(base)); + reg_sync_writel(dma->vfifo->trig, VFF_THRE(base)); + reg_sync_writel(dma->vfifo->size, VFF_LEN(base)); + if (enable_4G()) + reg_sync_writel(1, VFF_4G_DRAM_SUPPORT(base)); + + if (dma->vfifo->type == UART_RX_VFIFO) + /* reg_sync_writel(VFF_RX_INT_EN0_B, VFF_INT_EN(base)); */ + reg_sync_writel(VFF_RX_INT_EN0_B | VFF_RX_INT_EN1_B, VFF_INT_EN(base)); + mb(); + } +} + +/*---------------------------------------------------------------------------*/ +int mtk_uart_dma_start(struct mtk_uart *uart, struct mtk_uart_dma *dma) +{ + void *base; + + MSG_FUNC_ENTRY(); + + if (!dma) + return -1; + + if (!atomic_read(&dma->free)) + return -1; + + if (dma->mode == UART_TX_VFIFO_DMA || dma->mode == UART_RX_VFIFO_DMA) { + if (!dma->vfifo) { + MSG(ERR, "null\n"); + return -EINVAL; + } + base = dma->vfifo->base; + reg_sync_writel(VFF_INT_FLAG_CLR_B, VFF_INT_FLAG(base)); + reg_sync_writel(VFF_EN_B, VFF_EN(base)); + + if (UART_READ32(VFF_EN(base)) != VFF_EN_B) + MSG(ERR, "Start DMA fail\n"); + } + + atomic_set(&dma->free, 0); + init_completion(&dma->done); + + return 0; +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_stop_dma(struct mtk_uart_dma *dma) +{ + int polling_cnt = 0; + struct mtk_uart *uart = dma->uart; + void *base; + + if (!dma) + return; + if (dma->mode == UART_RX_VFIFO_DMA || dma->mode == UART_TX_VFIFO_DMA) { + MSG(DMA, "stop dma (%d)\n", dma->mode); + if (!dma->vfifo) { + MSG(ERR, "null\n"); + return; + } + base = dma->vfifo->base; + + /*set flush as 1 -> wait until flush is 0 */ + reg_sync_writel(VFF_FLUSH_CLR_B, VFF_FLUSH(base)); + while (UART_READ32(VFF_FLUSH(base))) { + polling_cnt++; + if (polling_cnt > 10000) { + pr_debug("mtk_uart_stop_dma: polling VFF_FLUSH fail VFF_DEBUG_STATUS=0x%x\n", + UART_READ32(VFF_DEBUG_STATUS(base))); + break; + } + } + + polling_cnt = 0; + /*set stop as 1 -> wait until en is 0 -> set stop as 0 */ + reg_sync_writel(VFF_STOP_B, VFF_STOP(base)); + while (UART_READ32(VFF_EN(base))) { + polling_cnt++; + if (polling_cnt > 10000) { + pr_debug("mtk_uart_stop_dma: polling VFF_EN fail VFF_DEBUG_STATUS=0x%x\n", + UART_READ32(VFF_DEBUG_STATUS(base))); + break; + } + } + reg_sync_writel(VFF_STOP_CLR_B, VFF_STOP(base)); + + reg_sync_writel(VFF_INT_EN_CLR_B, VFF_INT_EN(base)); + reg_sync_writel(VFF_INT_FLAG_CLR_B, VFF_INT_FLAG(base)); + } else { + MSG(ERR, "unknown mode: %d\n", dma->mode); + } +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_reset_dma(struct mtk_uart_dma *dma) +{ + struct mtk_uart *uart = dma->uart; + void *base; + + if (!dma) + return; + + if (dma->mode == UART_RX_VFIFO_DMA || dma->mode == UART_TX_VFIFO_DMA) { + if (!dma->vfifo) { + MSG(ERR, "null\n"); + return; + } + base = dma->vfifo->base; + /* mt65xx_req_vff_dma(dma->vfifo->ch, NULL, NULL); */ + reg_sync_writel(0, VFF_ADDR(base)); + reg_sync_writel(0, VFF_THRE(base)); + reg_sync_writel(0, VFF_LEN(base)); + /*set warm_rst as 1 -> wait until en is 0 */ + reg_sync_writel(VFF_WARM_RST_B, VFF_RST(base)); + while (UART_READ32(VFF_EN(base))) + ; + + /* Reset write point for tx dma */ + if (dma->mode == UART_TX_VFIFO_DMA) + reg_sync_writel(0, VFF_WPT(base)); + else if (dma->mode == UART_RX_VFIFO_DMA) + reg_sync_writel(0, VFF_RPT(base)); + } else + MSG(ERR, "unknown mode: %d\n", dma->mode); +} +#endif /*defined(ENABLE_VFIFO) */ +/*---------------------------------------------------------------------------*/ +void mtk_uart_fifo_init(struct mtk_uart *uart) +{ + /* + * NOTE: For FCR is a read only register reason, + * special read/write/set/clr function need to use + */ + /* UART_SET_BITS(UART_FCR_FIFO_INIT, UART_FCR); */ + __set_fcr_register(uart, UART_FCR_FIFO_INIT); + mb(); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_fifo_flush(struct mtk_uart *uart) +{ + /* + * NOTE: For FCR is a read only register reason, + * special read/write/set/clr function need to use + */ + /* UART_SET_BITS(UART_FCR_CLRR | UART_FCR_CLRT, UART_FCR); */ + __set_fcr_register(uart, UART_FCR_CLRR | UART_FCR_CLRT); + mb(); +} + +/*---------------------------------------------------------------------------*/ +int mtk_uart_data_ready(struct mtk_uart *uart) +{ + if ((uart->read_status(uart) & UART_LSR_DR)) + return 1; + else + return 0; +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_fifo_set_trig(struct mtk_uart *uart, int tx_level, int rx_level) +{ + unsigned long base = uart->base; + unsigned long tmp1; + unsigned long flags; + + tmp1 = UART_READ32(UART_LCR); + spin_lock_irqsave(&mtk_console_lock, flags); + reg_sync_writel(0xbf, UART_LCR); + UART_SET_BITS(UART_EFR_EN, UART_EFR); + reg_sync_writel(tmp1, UART_LCR); + spin_unlock_irqrestore(&mtk_console_lock, flags); + MSG(INFO, "%s(EFR) = %04X\n", __func__, UART_READ32(UART_EFR)); + + /* + * NOTE: For FCR is a read only register reason, + * special read/write/set/clr function need to use + */ + /* reg_sync_writel(UART_FCR_FIFO_INIT|tx_level|rx_level, UART_FCR); */ + sync_write_fcr_register(uart, UART_FCR_FIFO_INIT | tx_level | rx_level); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_set_mode(struct mtk_uart *uart, int mode) +{ + /* + * NOTE: For FCR is a read only register reason, + * special read/write/set/clr function need to use + */ + if (mode == UART_DMA_MODE_0) { + /* UART_CLR_BITS(UART_FCR_DMA1, UART_FCR); */ + __clr_fcr_register(uart, UART_FCR_DMA1); + } else if (mode == UART_DMA_MODE_1) { + /* UART_SET_BITS(UART_FCR_DMA1, UART_FCR); */ + __set_fcr_register(uart, UART_FCR_DMA1); + } + mb(); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_set_auto_baud(struct mtk_uart *uart) +{ + unsigned long base = uart->base; + + MSG_FUNC_ENTRY(); + + switch (uart->sysclk) { + case MTK_SYSCLK_13: + reg_sync_writel(UART_AUTOBADUSAM_13M, UART_AUTOBAUD_SAMPLE); + break; + case MTK_SYSCLK_26: + reg_sync_writel(UART_AUTOBADUSAM_26M, UART_AUTOBAUD_SAMPLE); + break; + case MTK_SYSCLK_52: + reg_sync_writel(UART_AUTOBADUSAM_52M, UART_AUTOBAUD_SAMPLE); + break; + default: + dev_err(uart->port.dev, "SYSCLK = %ldMHZ doesn't support autobaud\n", uart->sysclk); + return; + } + reg_sync_writel(0x01, UART_AUTOBAUD_EN); /* Enable Auto Baud */ +} + +/*---------------------------------------------------------------------------*/ +static void mtk_uart_cal_baud(struct mtk_uart *uart, int baudrate, int highspeed) +{ + unsigned long base = uart->base; + u32 remainder, uartclk = 0, divisor = 0; + u32 lcr = UART_READ32(UART_LCR); + unsigned long flags; + +#ifdef UART_USING_FIX_CLK_ENABLE + if (baudrate <= 1000000) { /* Using 16.25 fix clock */ + uartclk = uart->sysclk >> 2; + reg_sync_writel(0x03, UART_RATE_FIX_AD); + } else { /* >1M, Using 65 clock */ + uartclk = uart->sysclk; + reg_sync_writel(0x00, UART_RATE_FIX_AD); + } + if (3 == highspeed) + UART_SET_BITS(UART_MCR_DCM_EN, UART_MCR); /* Enable UART DCM */ + else + UART_CLR_BITS(UART_MCR_DCM_EN, UART_MCR); /* Disable UART DCM */ +#else /* UART_Fix_clk_DISABLE */ + uartclk = uart->sysclk; + reg_sync_writel(0x00, UART_RATE_FIX_AD); +#endif /* UART_USING_FIX_CLK_ENABLE */ + + spin_lock_irqsave(&mtk_console_lock, flags); + if (highspeed == 0) { + /* uartclk = uart->sysclk; */ + /* reg_sync_writel(0x00, UART_RATE_FIX_AD); */ + reg_sync_writel(0x00, UART_HIGHSPEED); /*divider is 16 */ + divisor = (uartclk >> 4) / (u32) baudrate; + remainder = (uartclk >> 4) % (u32) baudrate; + if (remainder >= (u32) (baudrate * 8)) + divisor += 1; + reg_sync_writel(lcr | UART_LCR_DLAB, UART_LCR); + reg_sync_writel((divisor & 0xFF), UART_DLL); + reg_sync_writel(((divisor >> 8) & 0xFF), UART_DLH); + reg_sync_writel(lcr, UART_LCR); + } else if (highspeed == 1) { + /* uartclk = uart->sysclk; */ + /* reg_sync_writel(0x00, UART_RATE_FIX_AD); */ + reg_sync_writel(0x01, UART_HIGHSPEED); /*divider is 8 */ + divisor = (uartclk >> 3) / (u32) baudrate; + remainder = (uartclk >> 3) % (u32) baudrate; + if (remainder >= (u32) (baudrate * 4)) + divisor += 1; + reg_sync_writel(lcr | UART_LCR_DLAB, UART_LCR); + reg_sync_writel((divisor & 0xFF), UART_DLL); + reg_sync_writel(((divisor >> 8) & 0xFF), UART_DLH); + reg_sync_writel(lcr, UART_LCR); + } else if (highspeed == 2) { + /* uartclk = uart->sysclk; */ + /* reg_sync_writel(0x00, UART_RATE_FIX_AD); */ + reg_sync_writel(0x02, UART_HIGHSPEED); /*divider is 4 */ + divisor = (uartclk >> 2) / (u32) baudrate; + remainder = (uartclk >> 2) % (u32) baudrate; + if (remainder >= (u32) (baudrate * 2)) + divisor += 1; + reg_sync_writel(lcr | UART_LCR_DLAB, UART_LCR); + reg_sync_writel((divisor & 0x00FF), UART_DLL); + reg_sync_writel(((divisor >> 8) & 0x00FF), UART_DLH); + reg_sync_writel(lcr, UART_LCR); + } else if (highspeed == 3) { + u32 sample_count, sample_point, high_div, tmp; +#if defined(ENABLE_FRACTIONAL) + u32 fraction; + u16 fraction_L_mapping[] = { 0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF }; + u16 fraction_M_mapping[] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0x3 }; +#endif + + /* uartclk = uart->sysclk; */ + /* reg_sync_writel(0x00, UART_RATE_FIX_AD); */ + reg_sync_writel(0x03, UART_HIGHSPEED); + tmp = (uartclk) / (u32) baudrate; + high_div = (tmp >> 8) + 1; + divisor = (uartclk) / (baudrate * high_div); + +#if defined(ENABLE_FRACTIONAL) + fraction = ((uartclk * 10) / baudrate) % 10; /*count fraction to set fractoin register */ + reg_sync_writel(fraction_L_mapping[fraction], UART_FRACDIV_L); + reg_sync_writel(fraction_M_mapping[fraction], UART_FRACDIV_M); +#else + remainder = (uartclk) % (baudrate * high_div); + if (remainder >= ((baudrate * high_div) >> 1)) + divisor += 1; +#endif + + sample_count = divisor - 1; + sample_point = (sample_count - 1) >> 1; + reg_sync_writel(lcr | UART_LCR_DLAB, UART_LCR); + reg_sync_writel((high_div & 0x00FF), UART_DLL); + reg_sync_writel(((high_div >> 8) & 0x00FF), UART_DLH); + reg_sync_writel(lcr, UART_LCR); + reg_sync_writel(sample_count, UART_SAMPLE_COUNT); + reg_sync_writel(sample_point, UART_SAMPLE_POINT); + /* + * NOTICE: We found some chip, that is using lower clock, may not have enough time to check stop bit. + * In order to improve compatibility, the guard time register + * is enabled which is used to extend the stop bit. + */ + if (baudrate >= 3000000) + reg_sync_writel(0x12, UART_GUARD); + } + spin_unlock_irqrestore(&mtk_console_lock, flags); + + MSG(CFG, "BaudRate = %d, SysClk = %d, Divisor = %d, %04X/%04X\n", baudrate, uartclk, divisor, + UART_READ32(UART_IER), UART_READ32(UART_LCR)); + dump_reg(uart, __func__); + mb(); /*to ensure the setting is written */ +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_baud_setting(struct mtk_uart *uart, int baudrate) +{ + u32 uartclk; +#if defined(CONFIG_MTK_FPGA) + u32 tmp_div; +#endif + uartclk = uart->sysclk; + +#if defined(CONFIG_MTK_FPGA) + tmp_div = (uartclk) / (unsigned int)baudrate; + if (tmp_div > 255) + mtk_uart_cal_baud(uart, baudrate, 2); + else + mtk_uart_cal_baud(uart, baudrate, 3); +#else + /* Fix clock, using new settings */ +#ifdef UART_USING_FIX_CLK_ENABLE + if (baudrate < 115200) + mtk_uart_cal_baud(uart, baudrate, 0); + else + mtk_uart_cal_baud(uart, baudrate, 3); +#else /* UART_Fix_Clock_DISABLE */ + if (baudrate <= 115200) + mtk_uart_cal_baud(uart, baudrate, 0); + else if (baudrate <= 460800) + mtk_uart_cal_baud(uart, baudrate, 2); + else + mtk_uart_cal_baud(uart, baudrate, 3); +#endif /* End of UART_DCM_CONFIG */ +#endif +} + +/*---------------------------------------------------------------------------*/ +#if defined(ENABLE_DEBUG) +/*---------------------------------------------------------------------------*/ +static u32 UART_READ_EFR(struct mtk_uart *uart) +{ + unsigned long base = uart->base; + u32 efr, lcr = UART_READ32(UART_LCR); + unsigned long flags; + + spin_lock_irqsave(&mtk_console_lock, flags); + reg_sync_writel(0xbf, UART_LCR); + efr = UART_READ32(UART_EFR); + reg_sync_writel(lcr, UART_LCR); + spin_unlock_irqrestore(&mtk_console_lock, flags); + return efr; +} + +/*---------------------------------------------------------------------------*/ +#endif +/*---------------------------------------------------------------------------*/ +void mtk_uart_set_flow_ctrl(struct mtk_uart *uart, int mode) +{ + unsigned long base = uart->base, old; + unsigned int tmp = UART_READ32(UART_LCR); + unsigned long flags; + + MSG(CFG, "%s: %04X\n", __func__, UART_READ_EFR(uart)); + + spin_lock_irqsave(&mtk_console_lock, flags); + switch (mode) { + case UART_FC_NONE: + reg_sync_writel(UART_ESCAPE_CH, UART_ESCAPE_DAT); + reg_sync_writel(0x00, UART_ESCAPE_EN); + reg_sync_writel(0xbf, UART_LCR); + old = UART_READ32(UART_EFR); + old &= ~(UART_EFR_AUTO_RTSCTS | UART_EFR_XON12_XOFF12); + reg_sync_writel(old, UART_EFR); + reg_sync_writel(tmp, UART_LCR); + mtk_uart_disable_intrs(uart, UART_IER_XOFFI | UART_IER_RTSI | UART_IER_CTSI); + break; + case UART_FC_HW: + reg_sync_writel(UART_ESCAPE_CH, UART_ESCAPE_DAT); + reg_sync_writel(0x00, UART_ESCAPE_EN); + UART_SET_BITS(UART_MCR_RTS, UART_MCR); + reg_sync_writel(0xbf, UART_LCR); + /*disable all flow control setting */ + old = UART_READ32(UART_EFR); + old &= ~(UART_EFR_AUTO_RTSCTS | UART_EFR_XON12_XOFF12); + reg_sync_writel(old, UART_EFR); + /*enable hw flow control */ + old = UART_READ32(UART_EFR); + reg_sync_writel(old | UART_EFR_AUTO_RTSCTS, UART_EFR); + reg_sync_writel(tmp, UART_LCR); + mtk_uart_disable_intrs(uart, UART_IER_XOFFI); + mtk_uart_enable_intrs(uart, UART_IER_CTSI | UART_IER_RTSI); + break; + case UART_FC_SW: /*MTK software flow control */ + reg_sync_writel(UART_ESCAPE_CH, UART_ESCAPE_DAT); + reg_sync_writel(0x01, UART_ESCAPE_EN); + reg_sync_writel(0xbf, UART_LCR); + /*dsiable all flow control setting */ + old = UART_READ32(UART_EFR); + old &= ~(UART_EFR_AUTO_RTSCTS | UART_EFR_XON12_XOFF12); + reg_sync_writel(old, UART_EFR); + /*enable sw flow control */ + old = UART_READ32(UART_EFR); + reg_sync_writel(old | UART_EFR_XON1_XOFF1, UART_EFR); + reg_sync_writel(START_CHAR(uart->port.state->port.tty), UART_XON1); + reg_sync_writel(STOP_CHAR(uart->port.state->port.tty), UART_XOFF1); + reg_sync_writel(tmp, UART_LCR); + mtk_uart_disable_intrs(uart, UART_IER_CTSI | UART_IER_RTSI); + mtk_uart_enable_intrs(uart, UART_IER_XOFFI); + break; + } + spin_unlock_irqrestore(&mtk_console_lock, flags); + mb(); /*to ensure the setting is written */ + uart->fctl_mode = mode; +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_power_up(struct mtk_uart *uart) +{ +#ifndef CONFIG_MTK_FPGA + struct mtk_uart_setting *setting; + +#if !defined(CONFIG_MTK_CLKMGR) + int clk_en_ret = 0; +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + + setting = uart->setting; + + if (!uart || uart->nport >= UART_NR) + return; + + if (uart->poweron_count > 0) { + MSG(FUC, "%s(%d)\n", __func__, uart->poweron_count); + } else { +#ifdef POWER_FEATURE + +#if !defined(CONFIG_MTK_CLKMGR) + clk_en_ret = clk_prepare_enable(setting->clk_uart_main); + if (clk_en_ret) { + pr_err("[UART%d][CCF]enable clk_uart_main failed. ret:%d, clk_main:%p\n", uart->nport, + clk_en_ret, setting->clk_uart_main); + } else { + pr_debug("[UART%d][CCF]enabled clk_uart%d_main:%p\n", uart->nport, uart->nport, + setting->clk_uart_main); + if ((uart != console_port) + && (uart->tx_mode == UART_TX_VFIFO_DMA || uart->rx_mode == UART_RX_VFIFO_DMA)) { + clk_en_ret = clk_prepare_enable(clk_uart_dma); + if (clk_en_ret) { + pr_err("[UART%d][CCF]enable clk_uart_main failed. ret:%d, clk_dma:%p\n", + uart->nport, clk_en_ret, clk_uart_dma); + } else { + pr_debug("[UART%d][CCF]enabled clk_uart_dma:%p\n", uart->nport, clk_uart_dma); + } + } + } + +#else /* !defined(CONFIG_MTK_CLKMGR) */ + if (0 != enable_clock(setting->pll_id, "UART")) + MSG(ERR, "power on fail!!\n"); + if ((uart != console_port) + && (uart->tx_mode == UART_TX_VFIFO_DMA || uart->rx_mode == UART_RX_VFIFO_DMA)) { + if (0 != enable_clock(PDN_FOR_DMA, "VFIFO")) + MSG(ERR, "power on dma fail!\n"); + } +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + + uart->poweron_count++; +#endif + } + MSG(FUC, "%s(%d) => up\n", __func__, uart->poweron_count); +#endif /* End of CONFIG_MTK_FPGA */ +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_power_down(struct mtk_uart *uart) +{ +#ifndef CONFIG_MTK_FPGA + struct mtk_uart_setting *setting; + + setting = uart->setting; + + if (!uart || uart->nport >= UART_NR) + return; + + if (uart->poweron_count == 0) { + MSG(FUC, "%s(%d)\n", __func__, uart->poweron_count); + } else { +#ifdef POWER_FEATURE +#if !defined(CONFIG_MTK_CLKMGR) + pr_debug("[UART%d][CCF]disable clk_uart%d_main:%p\n", uart->nport, uart->nport, + setting->clk_uart_main); + + clk_disable_unprepare(setting->clk_uart_main); + if ((uart != console_port) + && (uart->tx_mode == UART_TX_VFIFO_DMA || uart->rx_mode == UART_RX_VFIFO_DMA)) { + clk_disable_unprepare(clk_uart_dma); + pr_debug("[UART%d][CCF]disable clk_uart_dma:%p\n", uart->nport, clk_uart_dma); + } +#else /* !defined(CONFIG_MTK_CLKMGR) */ + if (0 != disable_clock(setting->pll_id, "UART")) + MSG(ERR, "power off fail!!\n"); + if ((uart != console_port) + && (uart->tx_mode == UART_TX_VFIFO_DMA || uart->rx_mode == UART_RX_VFIFO_DMA)) { + if (0 != disable_clock(PDN_FOR_DMA, "VFIFO")) + MSG(ERR, "power off dma fail!\n"); + } +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + uart->poweron_count--; +#endif + MSG(FUC, "%s(%d) => dn\n", __func__, uart->poweron_count); + } +#endif /* End of CONFIG_MTK_FPGA */ +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_config(struct mtk_uart *uart, int datalen, int stop, int parity) +{ + unsigned long base = uart->base; + unsigned int val = 0; + + switch (datalen) { + case 5: + val |= UART_WLS_5; + break; + case 6: + val |= UART_WLS_6; + break; + case 7: + val |= UART_WLS_7; + break; + case 8: + default: + val |= UART_WLS_8; + break; + } + + if (stop == 2 || (datalen == 5 && stop == 1)) + val |= UART_2_STOP; + + if (parity == 1) + val |= UART_ODD_PARITY; + else if (parity == 2) + val |= UART_EVEN_PARITY; + + reg_sync_writel(val, UART_LCR); +} + +/*---------------------------------------------------------------------------*/ +unsigned int mtk_uart_read_status(struct mtk_uart *uart) +{ + unsigned long base = uart->base; + + uart->line_status = UART_READ32(UART_LSR); + return uart->line_status; +} + +/*---------------------------------------------------------------------------*/ +unsigned int mtk_uart_read_allow(struct mtk_uart *uart) +{ + return uart->line_status & UART_LSR_DR; +} + +/*---------------------------------------------------------------------------*/ +/* Note: + * 1. FIFO mode: + * -THRE=1 : when free space in FIFO is reduced blow its trigger level + * -THRE=0 : when free space in FIFO is more than its trigger level + * 2. non-FIFO mode: + * -THRE=1 : when tx holding register is empty + * -THRE=0 : when tx holding register is not empty + */ +unsigned int mtk_uart_write_allow(struct mtk_uart *uart) +{ + unsigned long base = uart->base; + + return UART_READ32(UART_LSR) & UART_LSR_THRE; +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_enable_intrs(struct mtk_uart *uart, long mask) +{ /*assume UART_EFR_EN is on */ + unsigned long base = uart->base; + + UART_SET_BITS(mask, UART_IER); + mb(); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_disable_intrs(struct mtk_uart *uart, long mask) +{ /*assume UART_EFR_EN is on */ + unsigned long base = uart->base; + + UART_CLR_BITS(mask, UART_IER); + mb(); +} + +/*---------------------------------------------------------------------------*/ +unsigned int mtk_uart_read_byte(struct mtk_uart *uart) +{ + unsigned long base = uart->base; + + return UART_READ32(UART_RBR); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_write_byte(struct mtk_uart *uart, unsigned int byte) +{ + unsigned long base = uart->base; + + reg_sync_writel(byte, UART_THR); +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_usb_rx_sel(unsigned int uart_port, unsigned int enable) +{ + unsigned long base = mtk_uart_default_settings[uart_port - 1].uart_base; + + reg_sync_writel(enable, UART_RX_SEL); +} + +/*---------------------------------------------------------------------------*/ +unsigned int mtk_uart_filter_line_status(struct mtk_uart *uart) +{ + struct uart_port *port = &uart->port; + unsigned int status; + unsigned int lsr = uart->line_status; + + mtk_uart_lsr_status[uart->nport] |= lsr; + status = UART_LSR_BI | UART_LSR_PE | UART_LSR_FE | UART_LSR_OE; + +#ifdef ENABLE_DEBUG + if ((lsr & UART_LSR_BI) || (lsr & UART_LSR_PE) || (lsr & UART_LSR_FE) || (lsr & UART_LSR_OE)) { + MSG(ERR, "LSR: BI=%d, FE=%d, PE=%d, OE=%d, DR=%d\n", + (lsr & UART_LSR_BI) >> 4, (lsr & UART_LSR_FE) >> 3, + (lsr & UART_LSR_PE) >> 2, (lsr & UART_LSR_OE) >> 1, lsr & UART_LSR_DR); + } +#endif + status &= port->read_status_mask; + status &= ~port->ignore_status_mask; + status &= lsr; + + return status; +} + +/*---------------------------------------------------------------------------*/ +int mtk_uart_get_interrupt(struct mtk_uart *uart) +{ + unsigned int intrs; + unsigned long base = uart->base; + + intrs = UART_READ32(UART_IIR); + return intrs; +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_intr_last_check(struct mtk_uart *uart, int intrs) +{ +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_get_modem_status(struct mtk_uart *uart) +{ + unsigned long base = uart->base; + struct uart_port *port = &uart->port; + unsigned int status, delta; + + status = UART_READ32(UART_MSR); + status &= UART_MSR_DSR | UART_MSR_CTS | UART_MSR_DCD | UART_MSR_RI; + + MSG(INFO, "MSR: DCD(%d), RI(%d), DSR(%d), CTS(%d)\n", + status & UART_MSR_DCD ? 1 : 0, + status & UART_MSR_RI ? 1 : 0, status & UART_MSR_DSR ? 1 : 0, status & UART_MSR_CTS ? 1 : 0); + + delta = status ^ uart->old_status; + + if (!delta) + return; + + if (uart->ms_enable) { + if (delta & UART_MSR_DCD) + uart_handle_dcd_change(port, status & UART_MSR_DCD); + if (delta & UART_MSR_CTS) + uart_handle_cts_change(port, status & UART_MSR_CTS); + if (delta & UART_MSR_DSR) + port->icount.dsr++; + if (delta & UART_MSR_RI) + port->icount.rng++; + } + + uart->old_status = status; +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_rx_pre_handler(struct mtk_uart *uart, int intrs) +{ + unsigned long base = uart->base; + u32 tmp, lsr_status; + + if (intrs == UART_IIR_CTI) { + /* IMPORTANT: this is a fix for HW Bug. + * Without the function call, the RX data timeout interrupt will be + * triggered again and again.Hence, the purpose of this function call + * is to clear Rx data timeout interrupt + */ + tmp = UART_READ32(UART_DMA_EN); +#if defined(ENABLE_VFIFO) + MSG(DMA, "rx timeout: %x, %4d\n", tmp, mtk_uart_vfifo_get_counts(uart->rx_vfifo)); +#endif + /* mtk_uart_dma_vfifo_rx_tasklet((unsigned long)uart); */ + } else if ((intrs == UART_IIR_RLS) && !uart->read_allow(uart)) { + tmp = UART_READ32(UART_LSR); + MSG(DMA, "LSR=%X\n", tmp); + lsr_status = get_uart_lsr_status(uart->nport); + lsr_status |= tmp; + set_uart_lsr_status(uart->nport, lsr_status); + } else { +#if defined(ENABLE_VFIFO) + MSG(DMA, "RX = %4d, [%4x]\n", mtk_uart_vfifo_get_counts(uart->rx_vfifo), intrs); +#endif + } +} + +/* set the modem control lines. */ +void mtk_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct mtk_uart *uart = (struct mtk_uart *)port; + unsigned long base = uart->base; + unsigned int val; + + val = UART_READ32(UART_MCR); + + if (mctrl & TIOCM_DTR) + val |= UART_MCR_DTR; + else + val &= ~UART_MCR_DTR; + + if (mctrl & TIOCM_RTS) + val |= UART_MCR_RTS; + else + val &= ~UART_MCR_RTS; + + if (mctrl & TIOCM_OUT1) + val |= UART_MCR_OUT1; + else + val &= ~UART_MCR_OUT1; + + if (mctrl & TIOCM_OUT2) + val |= UART_MCR_OUT2; + else + val &= ~UART_MCR_OUT2; + + if (mctrl & TIOCM_LOOP) + val |= UART_MCR_LOOP; + else + val &= ~UART_MCR_LOOP; + + reg_sync_writel(val, UART_MCR); + + MSG(CFG, "MCR: DTR(%d), RTS(%d), OUT1(%d), OUT2(%d), LOOP(%d)\n", + val & UART_MCR_DTR ? 1 : 0, + val & UART_MCR_RTS ? 1 : 0, + val & UART_MCR_OUT1 ? 1 : 0, val & UART_MCR_OUT2 ? 1 : 0, val & UART_MCR_LOOP ? 1 : 0); +} + +/*---------------------------------------------------------------------------*/ +/* return the current state of modem contrl inputs */ +unsigned int mtk_uart_get_mctrl(struct uart_port *port) +{ + struct mtk_uart *uart = (struct mtk_uart *)port; + unsigned long base = uart->base; + unsigned int status; + unsigned int result = 0; + + status = UART_READ32(UART_MSR); + + MSG(INFO, "MSR: DCD(%d), RI(%d), DSR(%d), CTS(%d)\n", + status & UART_MSR_DCD ? 1 : 0, + status & UART_MSR_RI ? 1 : 0, status & UART_MSR_DSR ? 1 : 0, status & UART_MSR_CTS ? 1 : 0); + + if (status & UART_MSR_DCD) + result |= TIOCM_CAR; /* DCD. (data carrier detect) */ + if (status & UART_MSR_RI) + result |= TIOCM_RI; + if (status & UART_MSR_DSR) + result |= TIOCM_DSR; + if (status & UART_MSR_CTS) + result |= TIOCM_CTS; + + status = UART_READ32(UART_MCR); + + MSG(INFO, "MSR: OUT1(%d), OUT2(%d), LOOP(%d)\n", + status & UART_MCR_OUT1 ? 1 : 0, status & UART_MCR_OUT2 ? 1 : 0, status & UART_MCR_LOOP ? 1 : 0); + + if (status & UART_MCR_OUT2) + result |= TIOCM_OUT2; + if (status & UART_MCR_OUT1) + result |= TIOCM_OUT1; + if (status & UART_MCR_LOOP) + result |= TIOCM_LOOP; + + return result; +} + +/*---------------------------------------------------------------------------*/ +/* stop receiving characters + * note: port->lock has been taken by serial core layer + */ +void mtk_uart_stop_rx(struct uart_port *port) +{ + struct mtk_uart *uart = (struct mtk_uart *)port; + struct mtk_uart_dma *dma = &uart->dma_rx; + + MSG_FUNC_ENTRY(); + if (uart->rx_mode == UART_NON_DMA) { + mtk_uart_disable_intrs(uart, UART_IER_ERBFI); + } else { +#if defined(ENABLE_VFIFO) + /* According to serial_core.c, stop_rx is to stop interrupt + * Hence, RX received interrupt and dma interrupt is clear + */ + mtk_uart_disable_intrs(uart, UART_IER_ERBFI); + reg_sync_writel(VFF_INT_EN_CLR_B, VFF_INT_EN(dma->vfifo->base)); + atomic_set(&dma->free, 1); + complete(&dma->done); +#endif + } + uart->rx_stop = 1; +} + +/*---------------------------------------------------------------------------*/ +/* control the transmission of a break signal */ +void mtk_uart_break_ctl(struct uart_port *port, int break_state) +{ + struct mtk_uart *uart = (struct mtk_uart *)port; + unsigned long base = uart->base; + + unsigned long flags; + + MSG_FUNC_ENTRY(); + + spin_lock_irqsave(&port->lock, flags); + + if (break_state) + UART_SET_BITS(UART_LCR_BREAK, UART_LCR); + else + UART_CLR_BITS(UART_LCR_BREAK, UART_LCR); + mb(); + spin_unlock_irqrestore(&port->lock, flags); +} + +/*---------------------------------------------------------------------------*/ +#ifdef ATE_FACTORY_ENABLE +void mtk_uart_is_ate_factory_mode(struct mtk_uart *uart) +{ + if ((0 == uart->nport) && (ATE_FACTORY_MODE == get_boot_mode())) { + unsigned long base = uart->base; + /* MD may set these bit, reset it */ + UART_CLR_BITS(UART_RX_DMA_EN | UART_TO_CNT_AUTORST | UART_TX_DMA_EN, UART_DMA_EN); + mb(); + } +} +#endif /* ATE_FACTORY_ENABLE */ +/*---------------------------------------------------------------------------*/ +void mtk_uart_enable_sleep(struct mtk_uart *uart) +{ + unsigned long base = uart->base; + + reg_sync_writel(0x1, UART_SLEEP_EN); + pr_debug("SLEEP_EN = 0x%x\n", UART_READ32(UART_SLEEP_EN)); +} + +/*---------------------------------------------------------------------------*/ + +#ifdef ENABLE_RAW_DATA_DUMP +void mtk_uart_init_debug_spinlock(void) +{ + spin_lock_init(&tx_history_lock); + spin_lock_init(&rx_history_lock); +} + +void reset_tx_raw_data(struct mtk_uart *uart) +{ + unsigned long flags; + if (uart->nport == 2) { + spin_lock_irqsave(&tx_history_lock, flags); + if (!stop_update) { + curr_record++; + curr_idx = 0; + if (curr_record >= RECORD_NUMBER) + curr_record = 0; + uart_history_cnt[curr_record] = 0; + for (curr_idx = 0; curr_idx < RECORD_LENGTH; curr_idx++) + uart_history[curr_record][curr_idx] = 0; + curr_idx = 0; + } + spin_unlock_irqrestore(&tx_history_lock, flags); + } +} + +static void save_tx_raw_data(struct mtk_uart *uart, void *addr) +{ + unsigned long flags; + if (uart->nport == 2) { + spin_lock_irqsave(&tx_history_lock, flags); + if (!stop_update) { + if (curr_idx < RECORD_LENGTH) { + uart_history[curr_record][curr_idx] = UART_READ8(addr); + curr_idx++; + uart_history_cnt[curr_record] = curr_idx; + } + } + spin_unlock_irqrestore(&tx_history_lock, flags); + } +} + +static void reset_rx_raw_data(struct mtk_uart *uart) +{ + unsigned long flags; + if (uart->nport == 2) { + spin_lock_irqsave(&rx_history_lock, flags); + if (!stop_update) { + curr_rx_record++; + curr_rx_idx = 0; + if (curr_rx_record >= RECORD_NUMBER) + curr_rx_record = 0; + uart_rx_history_cnt[curr_rx_record] = 0; + for (curr_rx_idx = 0; curr_rx_idx < RECORD_LENGTH; curr_rx_idx++) + uart_rx_history[curr_rx_record][curr_rx_idx] = 0; + curr_rx_idx = 0; + } + spin_unlock_irqrestore(&rx_history_lock, flags); + } +} + +static void save_rx_raw_data(struct mtk_uart *uart, const unsigned char *chars, size_t size) +{ + unsigned long flags; + int i; + if (uart->nport == 2) { + spin_lock_irqsave(&rx_history_lock, flags); + if (!stop_update) { + for (i = 0; (curr_rx_idx < RECORD_LENGTH) && (i < size); i++, curr_rx_idx++) + uart_rx_history[curr_rx_record][curr_rx_idx] = chars[i]; + uart_rx_history_cnt[curr_rx_record] = curr_rx_idx; + } + spin_unlock_irqrestore(&rx_history_lock, flags); + } +} + +void stop_log(void) +{ + unsigned long flags; + unsigned long rx_flags; + + spin_lock_irqsave(&tx_history_lock, flags); + spin_lock_irqsave(&rx_history_lock, rx_flags); + stop_update = 1; + spin_unlock_irqrestore(&rx_history_lock, rx_flags); + spin_unlock_irqrestore(&tx_history_lock, flags); +} +EXPORT_SYMBOL(stop_log); + +void dump_uart_history(void) +{ + int i, j; + unsigned long flags; + unsigned long rx_flags; + int curr, rx_curr; + + spin_lock_irqsave(&tx_history_lock, flags); + spin_lock_irqsave(&rx_history_lock, rx_flags); + stop_update = 1; + spin_unlock_irqrestore(&rx_history_lock, rx_flags); + spin_unlock_irqrestore(&tx_history_lock, flags); + curr = curr_record + 1; + if (curr >= RECORD_NUMBER) + curr = 0; + rx_curr = curr_rx_record + 1; + if (rx_curr >= RECORD_NUMBER) + rx_curr = 0; + + for (i = 0; i < RECORD_NUMBER; i++) { + pr_debug("\nTX rec%03d:", i); + for (j = 0; j < uart_history_cnt[curr]; j++) { + if ((j % 0xF) == 0) + pr_debug("\n"); + pr_debug("%02x ", uart_history[curr][j]); + } + msleep(20); + curr++; + if (curr >= RECORD_NUMBER) + curr = 0; + } + for (i = 0; i < RECORD_NUMBER; i++) { + pr_debug("\nRX rec%03d:", i); + for (j = 0; j < uart_rx_history_cnt[rx_curr]; j++) { + if ((j % 0xF) == 0) + pr_debug("\n"); + pr_debug("%02x ", uart_rx_history[rx_curr][j]); + } + msleep(20); + rx_curr++; + if (rx_curr >= RECORD_NUMBER) + rx_curr = 0; + } +} +EXPORT_SYMBOL(dump_uart_history); +#else +void stop_log(void) +{ + /* dummy API */ +} + +void dump_uart_history(void) +{ + /* dummy API */ +} +#endif + +/*---------------------------------------------------------------------------*/ +void mtk_uart_save(struct mtk_uart *uart) +{ +#ifdef CONFIG_PM + unsigned long base; + unsigned long flags; + + base = uart->base; + + /* DLL may be changed by console write. To avoid this, use spinlock */ + spin_lock_irqsave(&mtk_console_lock, flags); + uart->registers.lcr = UART_READ32(UART_LCR); + + reg_sync_writel(0xbf, UART_LCR); + uart->registers.efr = UART_READ32(UART_EFR); + reg_sync_writel(uart->registers.lcr, UART_LCR); + uart->registers.fcr = UART_READ32(UART_FCR_RD); + + /* baudrate */ + uart->registers.highspeed = UART_READ32(UART_HIGHSPEED); + uart->registers.fracdiv_l = UART_READ32(UART_FRACDIV_L); + uart->registers.fracdiv_m = UART_READ32(UART_FRACDIV_M); + reg_sync_writel(uart->registers.lcr | UART_LCR_DLAB, UART_LCR); + uart->registers.dll = UART_READ32(UART_DLL); + uart->registers.dlh = UART_READ32(UART_DLH); + reg_sync_writel(uart->registers.lcr, UART_LCR); + uart->registers.sample_count = UART_READ32(UART_SAMPLE_COUNT); + uart->registers.sample_point = UART_READ32(UART_SAMPLE_POINT); + uart->registers.guard = UART_READ32(UART_GUARD); + + /* flow control */ + uart->registers.escape_en = UART_READ32(UART_ESCAPE_EN); + uart->registers.mcr = UART_READ32(UART_MCR); + uart->registers.ier = UART_READ32(UART_IER); + + uart->registers.rx_sel = UART_READ32(UART_RX_SEL); + + spin_unlock_irqrestore(&mtk_console_lock, flags); +#endif +} + +void mtk_uart_restore(void) +{ +#ifdef CONFIG_PM + unsigned long base; + unsigned long flags; + struct mtk_uart *uart; + + uart = console_port; + base = uart->base; + + mtk_uart_power_up(uart); + spin_lock_irqsave(&mtk_console_lock, flags); + reg_sync_writel(0xbf, UART_LCR); + reg_sync_writel(uart->registers.efr, UART_EFR); + reg_sync_writel(uart->registers.lcr, UART_LCR); + reg_sync_writel(uart->registers.fcr, UART_FCR); + + /* baudrate */ + reg_sync_writel(uart->registers.highspeed, UART_HIGHSPEED); + reg_sync_writel(uart->registers.fracdiv_l, UART_FRACDIV_L); + reg_sync_writel(uart->registers.fracdiv_m, UART_FRACDIV_M); + reg_sync_writel(uart->registers.lcr | UART_LCR_DLAB, UART_LCR); + reg_sync_writel(uart->registers.dll, UART_DLL); + reg_sync_writel(uart->registers.dlh, UART_DLH); + reg_sync_writel(uart->registers.lcr, UART_LCR); + reg_sync_writel(uart->registers.sample_count, UART_SAMPLE_COUNT); + reg_sync_writel(uart->registers.sample_point, UART_SAMPLE_POINT); + reg_sync_writel(uart->registers.guard, UART_GUARD); + + /* flow control */ + reg_sync_writel(uart->registers.escape_en, UART_ESCAPE_EN); + reg_sync_writel(uart->registers.mcr, UART_MCR); + reg_sync_writel(uart->registers.ier, UART_IER); + + reg_sync_writel(uart->registers.rx_sel, UART_RX_SEL); + + spin_unlock_irqrestore(&mtk_console_lock, flags); +#endif +} + +#if !defined(CONFIG_MTK_LEGACY) && !defined(CONFIG_MTK_FPGA) +void switch_uart_gpio(int uartport, int gpioopid) +{ + struct pinctrl *ppinctrl = NULL; + struct pinctrl_state *pins_uart = NULL; + + if ((uartport >= UART_NR) || (uartport > 3)) { + pr_err("[UART%d][PinC]%s: port error!!\n", uartport, __func__); + return; + } + + ppinctrl = ppinctrl_uart[uartport]; + if (IS_ERR(ppinctrl)) { + pr_err("[UART%d][PinC]%s get pinctrl fail!! err:%ld\n", uartport, __func__, PTR_ERR(ppinctrl)); + return; + } + + pins_uart = pinctrl_lookup_state(ppinctrl, uart_gpio_cmds[uartport][gpioopid]); + + if (IS_ERR(pins_uart)) { + pr_err("[UART%d][PinC]%s pinctrl_lockup(%d, %s) fail!! pctrl:%p, err:%ld\n", uartport, __func__, + uartport, uart_gpio_cmds[uartport][gpioopid], ppinctrl, PTR_ERR(pins_uart)); + return; + } + + pinctrl_select_state(ppinctrl, pins_uart); + +} +#endif /* !defined(CONFIG_MTK_LEGACY) && !defined(CONFIG_MTK_FPGA) */ + +void mtk_uart_switch_tx_to_gpio(struct mtk_uart *uart) +{ +#if defined(CONFIG_PM) && !defined(CONFIG_MTK_FPGA) && !defined(CONFIG_MTK_LEGACY) + int uart_gpio_op = 0; /* URAT RX SET */ +#endif /* defined(CONFIG_PM) && !defined(CONFIG_MTK_FPGA) && !defined(CONFIG_MTK_LEGACY) */ + int uartport = uart->nport; + /* pr_debug("[UART]%s port:0x%x\n", __func__, uartport); */ + + if (uartport > 3) { + pr_err("[UART%d] %s fail!! port:%d", uartport, __func__, uartport); + return; + } +#ifdef CONFIG_PM +#ifndef CONFIG_MTK_FPGA +#if defined(CONFIG_MTK_LEGACY) + switch (uart->nport) { + case 0: +#ifdef GPIO_UART_UTXD0_PIN + mt_set_gpio_out(GPIO_UART_UTXD0_PIN, GPIO_OUT_ONE); + mt_set_gpio_mode(GPIO_UART_UTXD0_PIN, GPIO_UART_UTXD0_PIN_M_GPIO); +#else + pr_debug("GPIO_UART_UTXD0_PIN is not properly set\n"); +#endif + break; + case 1: +#ifdef GPIO_UART_UTXD1_PIN + mt_set_gpio_out(GPIO_UART_UTXD1_PIN, GPIO_OUT_ONE); + mt_set_gpio_mode(GPIO_UART_UTXD1_PIN, GPIO_UART_UTXD1_PIN_M_GPIO); +#else + pr_debug("GPIO_UART_UTXD1_PIN is not properly set\n"); +#endif + break; + case 2: +#ifdef GPIO_UART_UTXD2_PIN + mt_set_gpio_out(GPIO_UART_UTXD2_PIN, GPIO_OUT_ONE); + mt_set_gpio_mode(GPIO_UART_UTXD2_PIN, GPIO_UART_UTXD2_PIN_M_GPIO); +#else + pr_debug("GPIO_UART_UTXD2_PIN is not properly set\n"); +#endif + break; + case 3: +#ifdef GPIO_UART_UTXD3_PIN + mt_set_gpio_out(GPIO_UART_UTXD3_PIN, GPIO_OUT_ONE); + mt_set_gpio_mode(GPIO_UART_UTXD3_PIN, GPIO_UART_UTXD3_PIN_M_GPIO); +#else + pr_debug("GPIO_UART_UTXD3_PIN is not properly set\n"); +#endif + break; + default: + break; + } + +#else /* defined(CONFIG_MTK_LEGACY) */ + /*pr_debug("[UART%d][PinC]%s call switch_uart_gpio(%d, %d)\n", uartport, __func__, uartport, uart_gpio_op);*/ + switch_uart_gpio(uartport, uart_gpio_op); +#endif /* defined(CONFIG_MTK_LEGACY) */ + +#endif +#endif +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_switch_to_tx(struct mtk_uart *uart) +{ +#if defined(CONFIG_PM) && !defined(CONFIG_MTK_FPGA) && !defined(CONFIG_MTK_LEGACY) + int uart_gpio_op = 0; /* URAT RX SET */ +#endif /* defined(CONFIG_PM) && !defined(CONFIG_MTK_FPGA) && !defined(CONFIG_MTK_LEGACY) */ + int uartport = uart->nport; + /* pr_debug("[UART]%s port:0x%x\n", __func__, uartport);*/ + + if (uartport > 3) { + pr_err("[UART%d] %s fail!! port:%d", uartport, __func__, uartport); + return; + } +#ifdef CONFIG_PM +#ifndef CONFIG_MTK_FPGA +#if defined(CONFIG_MTK_LEGACY) + switch (uart->nport) { + case 0: +#ifdef GPIO_UART_UTXD0_PIN + mt_set_gpio_mode(GPIO_UART_UTXD0_PIN, GPIO_UART_UTXD0_PIN_M_UTXD); +#else + pr_debug("GPIO_UART_UTXD0_PIN is not properly set p2\n"); +#endif + break; + case 1: +#ifdef GPIO_UART_UTXD1_PIN + mt_set_gpio_mode(GPIO_UART_UTXD1_PIN, GPIO_UART_UTXD1_PIN_M_UTXD); +#else + pr_debug("GPIO_UART_UTXD1_PIN is not properly set p2\n"); +#endif + break; + case 2: +#ifdef GPIO_UART_UTXD2_PIN + mt_set_gpio_mode(GPIO_UART_UTXD2_PIN, GPIO_UART_UTXD2_PIN_M_UTXD); +#else + pr_debug("GPIO_UART_UTXD2_PIN is not properly set p2\n"); +#endif + break; + case 3: +#ifdef GPIO_UART_UTXD3_PIN + mt_set_gpio_mode(GPIO_UART_UTXD3_PIN, GPIO_UART_UTXD3_PIN_M_UTXD); +#else + pr_debug("GPIO_UART_UTXD3_PIN is not properly set p3\n"); +#endif + break; + default: + break; + } + +#else /* defined(CONFIG_MTK_LEGACY) */ + pr_debug("[UART%d][PinC]%s call switch_uart_gpio(%d, %d)\n", uartport, __func__, uartport, uart_gpio_op); + switch_uart_gpio(uartport, uart_gpio_op); +#endif /* defined(CONFIG_MTK_LEGACY) */ +#endif +#endif +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_switch_rx_to_gpio(struct mtk_uart *uart) +{ +#if defined(CONFIG_PM) && !defined(CONFIG_MTK_FPGA) && !defined(CONFIG_MTK_LEGACY) + int uart_gpio_op = 1; /* URAT RX Clear */ +#endif /* !defined(CONFIG_MTK_LEGACY) */ + int uartport = uart->nport; + /* pr_debug("[UART]%s port:0x%x\n", __func__, uartport); */ + + if (uartport > 3) { + pr_err("[UART%d] %s fail!! port:%d", uartport, __func__, uartport); + return; + } +#ifdef CONFIG_PM +#ifndef CONFIG_MTK_FPGA +#if defined(CONFIG_MTK_LEGACY) + switch (uart->nport) { + case 0: +#ifdef GPIO_UART_URXD0_PIN + mt_set_gpio_mode(GPIO_UART_URXD0_PIN, GPIO_UART_URXD0_PIN_M_GPIO); +#else + pr_debug("GPIO_UART_URXD0_PIN is not properly set\n"); +#endif + break; + case 1: +#ifdef GPIO_UART_URXD1_PIN + mt_set_gpio_mode(GPIO_UART_URXD1_PIN, GPIO_UART_URXD1_PIN_M_GPIO); +#else + pr_debug("GPIO_UART_URXD1_PIN is not properly set\n"); +#endif + break; + case 2: +#ifdef GPIO_UART_URXD2_PIN + mt_set_gpio_mode(GPIO_UART_URXD2_PIN, GPIO_UART_URXD2_PIN_M_GPIO); +#else + pr_debug("GPIO_UART_URXD2_PIN is not properly set\n"); +#endif + break; + case 3: +#ifdef GPIO_UART_URXD3_PIN + mt_set_gpio_mode(GPIO_UART_URXD3_PIN, GPIO_UART_URXD3_PIN_M_GPIO); +#else + pr_debug("GPIO_UART_URXD3_PIN is not properly set\n"); +#endif + break; + default: + break; + } + +#else /* defined(CONFIG_MTK_LEGACY) */ + pr_debug("[UART%d][PinC]%s call switch_uart_gpio(%d, %d)\n", uartport, __func__, uartport, uart_gpio_op); + switch_uart_gpio(uartport, uart_gpio_op); +#endif /* defined(CONFIG_MTK_LEGACY) */ + +#endif +#endif +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_switch_to_rx(struct mtk_uart *uart) +{ +#if defined(CONFIG_PM) && !defined(CONFIG_MTK_FPGA) && !defined(CONFIG_MTK_LEGACY) + int uart_gpio_op = 0; /* URAT RX SET */ +#endif /* !defined(CONFIG_MTK_LEGACY) */ + int uartport = uart->nport; + /* pr_debug("[UART]%s port:0x%x\n", __func__, uartport);*/ + + if (uartport > 3) { + pr_err("[UART%d] %s fail!! port:%d", uartport, __func__, uartport); + return; + } +#ifdef CONFIG_PM +#ifndef CONFIG_MTK_FPGA +#if defined(CONFIG_MTK_LEGACY) + switch (uartport) { + case 0: +#ifdef GPIO_UART_URXD0_PIN + mt_set_gpio_mode(GPIO_UART_URXD0_PIN, GPIO_UART_URXD0_PIN_M_URXD); +#else /* GPIO_UART_URXD0_PIN */ + pr_debug("GPIO_UART_URXD0_PIN is not properly set p2\n"); +#endif /* GPIO_UART_URXD0_PIN */ + break; + + case 1: +#ifdef GPIO_UART_URXD1_PIN + mt_set_gpio_mode(GPIO_UART_URXD1_PIN, GPIO_UART_URXD1_PIN_M_URXD); +#else /* GPIO_UART_URXD1_PIN */ + pr_debug("GPIO_UART_URXD1_PIN is not properly set p2\n"); +#endif /* GPIO_UART_URXD1_PIN */ + break; + + case 2: +#ifdef GPIO_UART_URXD2_PIN + mt_set_gpio_mode(GPIO_UART_URXD2_PIN, GPIO_UART_URXD2_PIN_M_URXD); +#else + pr_debug("GPIO_UART_URXD2_PIN is not properly set p2\n"); +#endif + break; + + case 3: +#ifdef GPIO_UART_URXD3_PIN + mt_set_gpio_mode(GPIO_UART_URXD3_PIN, GPIO_UART_URXD3_PIN_M_URXD); +#else + pr_debug("GPIO_UART_URXD3_PIN is not properly set p2\n"); +#endif + break; + default: + break; + } + +#else /* defined(CONFIG_MTK_LEGACY) */ + pr_debug("[UART%d][PinC]%s call switch_uart_gpio(%d, %d)\n", uartport, __func__, uartport, uart_gpio_op); + switch_uart_gpio(uartport, uart_gpio_op); +#endif /* defined(CONFIG_MTK_LEGACY) */ +#endif +#endif +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_enable_dpidle(struct mtk_uart *uart) +{ +/* FIX-ME early porting */ +#ifndef CONFIG_MTK_FPGA +#if defined(CONFIG_MTK_CLKMGR) + enable_dpidle_by_bit(uart->setting->pll_id); + enable_soidle_by_bit(uart->setting->pll_id); +#endif +#endif +} + +/*---------------------------------------------------------------------------*/ +void mtk_uart_disable_dpidle(struct mtk_uart *uart) +{ +/* FIX-ME early porting */ +#ifndef CONFIG_MTK_FPGA +#if defined(CONFIG_MTK_CLKMGR) + disable_dpidle_by_bit(uart->setting->pll_id); + disable_soidle_by_bit(uart->setting->pll_id); +#endif +#endif +} + +/*---------------------------------------------------------------------------*/ +int mtk_uart_plat_info_query(const char str[]) +{ + return 0; +} diff --git a/drivers/misc/mediatek/uart/mt6755/platform_uart.h b/drivers/misc/mediatek/uart/mt6755/platform_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..1e2366e29a2826832af94d5bebbaea44c13cb913 --- /dev/null +++ b/drivers/misc/mediatek/uart/mt6755/platform_uart.h @@ -0,0 +1,478 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MTK_PLAT_UART_H__ +#define __MTK_PLAT_UART_H__ + +#include +#include + +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + +/****************************************************************************** + * Function Configuration +******************************************************************************/ +#define ENABLE_DEBUG +#define ENABLE_VFIFO +/* Fix-me: marked for early porting */ +#define POWER_FEATURE /*control power-on/power-off */ +#define ENABLE_FRACTIONAL +#define ENABLE_SYSFS +/* #define UART_USING_FIX_CLK_ENABLE */ +#define UART_FCR_USING_SW_BACK_UP +#define ENABLE_UART_SLEEP +/*---------------------------------------------------------------------------*/ +#if defined(WMT_PLAT_ALPS) +#define ENABLE_RAW_DATA_DUMP +#endif +/*---------------------------------------------------------------------------*/ +#if defined(ENABLE_VFIFO) && defined(ENABLE_DEBUG) +#define ENABLE_VFIFO_DEBUG +#endif + +#define ENABLE_CONSOLE_DEBUG +#if defined(ENABLE_CONSOLE_DEBUG) +#define UART_INFRA(_b) (_b+0x0090) +#define UART_INFRA_READ32(REG) (*(volatile unsigned int *)(REG)) +#endif /*--ENABLE_CONSOLE_DEBUG--*/ + +/****************************************************************************** + * MACRO & CONSTANT +******************************************************************************/ +#define DBG_TAG "[UART] " +#define CFG_UART_AUTOBAUD 0 +/*---------------------------------------------------------------------------*/ +#define UART_VFIFO_SIZE 8192 +#define UART_VFIFO_ALERT_LEN 0x3f +/*---------------------------------------------------------------------------*/ +#define UART_MAX_TX_PENDING 1024 +/*---------------------------------------------------------------------------*/ +#define UART_MAJOR 204 +#define UART_MINOR 209 +#if defined(CONFIG_MTK_FPGA) +#define UART_NR 2 +#else +#define UART_NR 2 +#endif + +#ifndef FALSE +#define FALSE (0) +#endif +#ifndef TRUE +#define TRUE (1) +#endif +/*---------------------------------------------------------------------------*/ +#define WAIT_UART_ACK_TIMES 10 +/*---------------------------------------------------------------------------*/ +#define IRQF_LEVEL_TRIGGER_POLARITY IRQF_TRIGGER_LOW +#define IRQF_EDGE_TRIGGER_POLARITY IRQF_TRIGGER_FALLING +/*---- Macro defination remap -----------------------------------------------*/ +/*------ IRQ Section -----------------------*/ +#ifndef CONFIG_OF +#define UART1_IRQ_ID UART0_IRQ_BIT_ID +#define UART2_IRQ_ID UART1_IRQ_BIT_ID +#define UART3_IRQ_ID UART2_IRQ_BIT_ID +#define UART4_IRQ_ID UART3_IRQ_BIT_ID + +#define UART1_VFF_TX_IRQ_ID AP_DMA_UART0_TX_IRQ_BIT_ID +#define UART1_VFF_RX_IRQ_ID AP_DMA_UART0_RX_IRQ_BIT_ID +#define UART2_VFF_TX_IRQ_ID AP_DMA_UART1_TX_IRQ_BIT_ID +#define UART2_VFF_RX_IRQ_ID AP_DMA_UART1_RX_IRQ_BIT_ID +#define UART3_VFF_TX_IRQ_ID AP_DMA_UART2_TX_IRQ_BIT_ID +#define UART3_VFF_RX_IRQ_ID AP_DMA_UART2_RX_IRQ_BIT_ID +#endif +/*------ PDN Section -----------------------*/ +#if defined(CONFIG_MTK_CLKMGR) && !defined(CONFIG_MTK_FPGA) +#define PDN_FOR_UART1 MT_CG_INFRA_UART0 +#define PDN_FOR_UART2 MT_CG_INFRA_UART1 +/* +#define PDN_FOR_UART3 MT_CG_INFRA_UART2 +#define PDN_FOR_UART4 MT_CG_INFRA_UART3 +*/ +#define PDN_FOR_DMA MT_CG_INFRA_APDMA +#endif + +#if (defined(CONFIG_FIQ_DEBUGGER_CONSOLE) && defined(CONFIG_FIQ_DEBUGGER)) +#define DEFAULT_FIQ_UART_PORT (3) +#endif + +/* For ATE factory feature */ +#ifdef ATE_FACTORY_ENABLE +#define ATE_FACTORY_MODE 6 +#endif +/*---------------------------------------------------------------------------*/ +#define MTK_SYSCLK_65 65000000 +#define MTK_SYSCLK_49_4 49400000 +#define MTK_SYSCLK_58_5 58500000 +#define MTK_SYSCLK_52 52000000 +#define MTK_SYSCLK_26 26000000 +#define MTK_SYSCLK_13 13000000 +#define MTK_SYSCLK_6144 61440000 +#define MTK_SYSCLK_3072 30720000 +#define MTK_SYSCLK_1536 15360000 +/*---------------------------------------------------------------------------*/ +/*FIXME: MT6593 FPGA porting*/ +#ifdef CONFIG_MTK_FPGA +#ifdef FIX_TO_26M +#define UART_SYSCLK MTK_SYSCLK_26 +#else +#define UART_SYSCLK 12000000 +#endif +#else +#define UART_SYSCLK MTK_SYSCLK_26 +#endif + +/*---------------------------------------------------------------------------*/ +#define ISWEXT (0x80000000) /*extended bit in c_iflag */ +/*---------------------------------------------------------------------------*/ +/*the size definition of VFF*/ +#define C_UART1_VFF_TX_SIZE (1024) /*the size must be 8-byte alignment */ +#define C_UART1_VFF_RX_SIZE (1024) /*the size must be 8-byte alignment */ +#define C_UART2_VFF_TX_SIZE (8192) /*the size must be 8-byte alignment */ +#define C_UART2_VFF_RX_SIZE (8192) /*the size must be 8-byte alignment */ +#define C_UART3_VFF_TX_SIZE (8192) /*the size must be 8-byte alignment */ +#define C_UART3_VFF_RX_SIZE (8192) /*the size must be 8-byte alignment */ +#define C_UART4_VFF_TX_SIZE (1024) /*the size must be 8-byte alignment */ +#define C_UART4_VFF_RX_SIZE (1024) /*the size must be 8-byte alignment */ +/****************************************************************************** + * LOG SETTING +******************************************************************************/ +/* Debug message event */ +#define DBG_EVT_NONE 0x00000000 /* No event */ +#define DBG_EVT_DMA 0x00000001 /* DMA related event */ +#define DBG_EVT_INT 0x00000002 /* UART INT event */ +#define DBG_EVT_CFG 0x00000004 /* UART CFG event */ +#define DBG_EVT_FUC 0x00000008 /* Function event */ +#define DBG_EVT_INFO 0x00000010 /* information event */ +#define DBG_EVT_ERR 0x00000020 /* Error event */ +#define DBG_EVT_DAT 0x00000040 /* data dump to uart */ +#define DBG_EVT_BUF 0x00000080 /* data dump to buffer */ +#define DBG_EVT_MSC 0x00000100 /* misc log */ +#define DBG_EVT_ALL 0xffffffff +/*---------------------------------------------------------------------------*/ +#ifdef ENABLE_DEBUG +/*---------------------------------------------------------------------------*/ +#define MSG(evt, fmt, args...) \ +do { \ + if ((DBG_EVT_##evt) & uart->evt_mask) { \ + const char *s = #evt; \ + if (DBG_EVT_##evt & DBG_EVT_ERR) \ + pr_err(" [UART%d]:%c:%4d: " fmt , \ + uart->nport, s[0], __LINE__, ##args); \ + else \ + pr_debug(" [UART%d]:%c: " fmt , uart->nport, s[0], ##args); \ + } \ +} while (0) +/*---------------------------------------------------------------------------*/ +#define UART_DEBUG_EVT(evt) ((evt) & uart->evt_mask) +/*---------------------------------------------------------------------------*/ +#define MSG_FUNC_ENTRY(f) MSG(FUC, "%s\n", __func__) +#define MSG_RAW pr_debug +/*---------------------------------------------------------------------------*/ +#else /* release mode: only enable error log */ +#define MSG(evt, fmt, args...) MSG##evt(fmt, ##args) +#define MSGERR(fmt, args...) pr_err(" [UART%d]:E:%4d: " fmt, uart->nport, __LINE__, ##args) +#define MSGDMA(fmt, args...) +#define MSGCFG(fmt, args...) +#define MSGFUC(fmt, args...) +#define MSGINFO(fmt, args...) +#define MSGDAT(fmt, args...) +#define MSGMSC(fmt, args...) +#define MSG_RAW(fmt, args...) +#define MSG_FUNC_ENTRY(f) do {} while (0) +#endif /**/ +#define MSG_ERR(fmt, args...) pr_err("[UARTX]:E:%4d: " fmt, __LINE__, ##args) +#define MSG_TRC(fmt, args...) pr_debug("[UARTX]:T: " fmt, ##args) +#define DEV_TRC(fmt, args...) pr_debug("[UART%d]:T: " fmt, uart->nport, ##args) +#define DEV_ERR(fmt, args...) pr_err("[UART%d]:E: " fmt, uart->nport, ##args) +/*---------------------------------------------------------------------------*/ +#define DRV_NAME "mtk-uart" +/*---------------------------------------------------------------------------*/ +/****************************************************************************** + * ENUM & STRUCT +******************************************************************************/ +/* uart port ids */ +enum { + UART_PORT0 = 0, + UART_PORT1, + UART_PORT2, + UART_PORT3, + UART_PORT_NUM, +}; +/*---------------------------------------------------------------------------*/ +#define UART_FIFO_SIZE (16) +/*---------------------------------------------------------------------------*/ +#define UART_RBR (unsigned long)(base+0x00) /* Read only */ +#define UART_THR (unsigned long)(base+0x00) /* Write only */ +#define UART_IER (unsigned long)(base+0x04) +#define UART_IIR (unsigned long)(base+0x08) /* Read only */ +#define UART_FCR (unsigned long)(base+0x08) /* Write only */ +#define UART_LCR (unsigned long)(base+0x0c) +#define UART_MCR (unsigned long)(base+0x10) +#define UART_LSR (unsigned long)(base+0x14) +#define UART_MSR (unsigned long)(base+0x18) +#define UART_SCR (unsigned long)(base+0x1c) +#define UART_DLL (unsigned long)(base+0x00) /* Only when LCR.DLAB = 1 */ +#define UART_DLH (unsigned long)(base+0x04) /* Only when LCR.DLAB = 1 */ +#define UART_EFR (unsigned long)(base+0x08) /* Only when LCR = 0xbf */ +#define UART_XON1 (unsigned long)(base+0x10) /* Only when LCR = 0xbf */ +#define UART_XON2 (unsigned long)(base+0x14) /* Only when LCR = 0xbf */ +#define UART_XOFF1 (unsigned long)(base+0x18) /* Only when LCR = 0xbf */ +#define UART_XOFF2 (unsigned long)(base+0x1c) /* Only when LCR = 0xbf */ +#define UART_AUTOBAUD_EN (unsigned long)(base+0x20) +#define UART_HIGHSPEED (unsigned long)(base+0x24) +#define UART_SAMPLE_COUNT (unsigned long)(base+0x28) +#define UART_SAMPLE_POINT (unsigned long)(base+0x2c) +#define UART_AUTOBAUD_REG (unsigned long)(base+0x30) +#define UART_RATE_FIX_AD (unsigned long)(base+0x34) +#define UART_AUTOBAUD_SAMPLE (unsigned long)(base+0x38) +#define UART_GUARD (unsigned long)(base+0x3c) +#define UART_ESCAPE_DAT (unsigned long)(base+0x40) +#define UART_ESCAPE_EN (unsigned long)(base+0x44) +#define UART_SLEEP_EN (unsigned long)(base+0x48) +#define UART_DMA_EN (unsigned long)(base+0x4c) +#define UART_RXTRI_AD (unsigned long)(base+0x50) +#define UART_FRACDIV_L (unsigned long)(base+0x54) +#define UART_FRACDIV_M (unsigned long)(base+0x58) +#define UART_FCR_RD (unsigned long)(base+0x5C) +#define UART_ACTIVE_EN (unsigned long)(base+0x60) +#define UART_DLL_E (unsigned long)(base+0x90) +#define UART_DLH_E (unsigned long)(base+0x94) +#define UART_FEATURE_SEL (unsigned long)(base+0x9C) +#define UART_RX_SEL (unsigned long)(base+0xB0) +#define UART_SLEEP_REQ (unsigned long)(base+0xB4) +#define UART_SLEEP_ACK (unsigned long)(base+0xB8) + +/* system level, not related to hardware */ +#define UST_DUMMY_READ (1 << 31) +/*---------------------------------------------------------------------------*/ +/* For MT6589, both RX and TX will not use port to send or receive data */ +/* IER */ +#define UART_IER_ERBFI (1 << 0) /* RX buffer conatins data int. */ +#define UART_IER_ETBEI (1 << 1) /* TX FIFO threshold trigger int. */ +#define UART_IER_ELSI (1 << 2) /* BE, FE, PE, or OE int. */ +#define UART_IER_EDSSI (1 << 3) /* CTS change (DCTS) int. */ +/* When set "1", enable flow control triggered by RX FIFO full when VFIFO_EN is set. */ +#define UART_IER_VFF_FC_EN (1 << 4) +#define UART_IER_XOFFI (1 << 5) +#define UART_IER_RTSI (1 << 6) +#define UART_IER_CTSI (1 << 7) + +#define UART_IER_ALL_INTS (UART_IER_ERBFI|UART_IER_ETBEI|UART_IER_ELSI|\ + UART_IER_EDSSI|UART_IER_XOFFI|UART_IER_RTSI|\ + UART_IER_CTSI) +#define UART_IER_HW_NORMALINTS (UART_IER_ERBFI|UART_IER_ELSI|UART_IER_EDSSI|UART_IER_VFF_FC_EN) +#define UART_IER_HW_ALLINTS (UART_IER_ERBFI|UART_IER_ETBEI| \ + UART_IER_ELSI|UART_IER_EDSSI) +/*---------------------------------------------------------------------------*/ +/* FCR */ +#define UART_FCR_FIFOE (1 << 0) +#define UART_FCR_CLRR (1 << 1) +#define UART_FCR_CLRT (1 << 2) +#define UART_FCR_DMA1 (1 << 3) +#define UART_FCR_RXFIFO_1B_TRI (0 << 6) +#define UART_FCR_RXFIFO_6B_TRI (1 << 6) +#define UART_FCR_RXFIFO_12B_TRI (2 << 6) +#define UART_FCR_RXFIFO_RX_TRI (3 << 6) +#define UART_FCR_TXFIFO_1B_TRI (0 << 4) +#define UART_FCR_TXFIFO_4B_TRI (1 << 4) +#define UART_FCR_TXFIFO_8B_TRI (2 << 4) +#define UART_FCR_TXFIFO_14B_TRI (3 << 4) + +#define UART_FCR_FIFO_INIT (UART_FCR_FIFOE|UART_FCR_CLRR|UART_FCR_CLRT) +#define UART_FCR_NORMAL (UART_FCR_FIFO_INIT | \ + UART_FCR_TXFIFO_4B_TRI| \ + UART_FCR_RXFIFO_12B_TRI) +/*---------------------------------------------------------------------------*/ +/* LCR */ +#define UART_LCR_BREAK (1 << 6) +#define UART_LCR_DLAB (1 << 7) + +#define UART_WLS_5 (0 << 0) +#define UART_WLS_6 (1 << 0) +#define UART_WLS_7 (2 << 0) +#define UART_WLS_8 (3 << 0) +#define UART_WLS_MASK (3 << 0) + +#define UART_1_STOP (0 << 2) +#define UART_2_STOP (1 << 2) +#define UART_1_5_STOP (1 << 2) /* Only when WLS=5 */ +#define UART_STOP_MASK (1 << 2) + +#define UART_NONE_PARITY (0 << 3) +#define UART_ODD_PARITY (0x1 << 3) +#define UART_EVEN_PARITY (0x3 << 3) +#define UART_MARK_PARITY (0x5 << 3) +#define UART_SPACE_PARITY (0x7 << 3) +#define UART_PARITY_MASK (0x7 << 3) +/*---------------------------------------------------------------------------*/ +/* MCR */ +#define UART_MCR_DTR (1 << 0) +#define UART_MCR_RTS (1 << 1) +#define UART_MCR_OUT1 (1 << 2) +#define UART_MCR_OUT2 (1 << 3) +#define UART_MCR_LOOP (1 << 4) +#define UART_MCR_DCM_EN (1 << 5) /* MT6589 move to bit5 */ +#define UART_MCR_XOFF (1 << 7) /* read only */ +#define UART_MCR_NORMAL (UART_MCR_DTR|UART_MCR_RTS) +/*---------------------------------------------------------------------------*/ +/* LSR */ +#define UART_LSR_DR (1 << 0) +#define UART_LSR_OE (1 << 1) +#define UART_LSR_PE (1 << 2) +#define UART_LSR_FE (1 << 3) +#define UART_LSR_BI (1 << 4) +#define UART_LSR_THRE (1 << 5) +#define UART_LSR_TEMT (1 << 6) +#define UART_LSR_FIFOERR (1 << 7) +/*---------------------------------------------------------------------------*/ +/* MSR */ +#define UART_MSR_DCTS (1 << 0) +#define UART_MSR_DDSR (1 << 1) +#define UART_MSR_TERI (1 << 2) +#define UART_MSR_DDCD (1 << 3) +#define UART_MSR_CTS (1 << 4) +#define UART_MSR_DSR (1 << 5) +#define UART_MSR_RI (1 << 6) +#define UART_MSR_DCD (1 << 7) +/*---------------------------------------------------------------------------*/ +/* EFR */ +#define UART_EFR_EN (1 << 4) +#define UART_EFR_AUTO_RTS (1 << 6) +#define UART_EFR_AUTO_CTS (1 << 7) +#define UART_EFR_SW_CTRL_MASK (0xf << 0) + +#define UART_EFR_NO_SW_CTRL (0) +#define UART_EFR_NO_FLOW_CTRL (0) +#define UART_EFR_AUTO_RTSCTS (UART_EFR_AUTO_RTS|UART_EFR_AUTO_CTS) +#define UART_EFR_XON1_XOFF1 (0xa) /* TX/RX XON1/XOFF1 flow control */ +#define UART_EFR_XON2_XOFF2 (0x5) /* TX/RX XON2/XOFF2 flow control */ +#define UART_EFR_XON12_XOFF12 (0xf) /* TX/RX XON1,2/XOFF1,2 flow control */ + +#define UART_EFR_XON1_XOFF1_MASK (0xa) +#define UART_EFR_XON2_XOFF2_MASK (0x5) +/*---------------------------------------------------------------------------*/ +/* IIR (Read Only) */ +#define UART_IIR_NO_INT_PENDING (0x01) +#define UART_IIR_RLS (0x06) /* Receiver Line Status */ +#define UART_IIR_RDA (0x04) /* Receive Data Available */ +#define UART_IIR_CTI (0x0C) /* Character Timeout Indicator */ +#define UART_IIR_THRE (0x02) /* Transmit Holding Register Empty */ +#define UART_IIR_MS (0x00) /* Check Modem Status Register */ +#define UART_IIR_SW_FLOW_CTRL (0x10) /* Receive XOFF characters */ +#define UART_IIR_HW_FLOW_CTRL (0x20) /* CTS or RTS Rising Edge */ +#define UART_IIR_FIFO_EN (0xc0) +#define UART_IIR_INT_MASK (0x3f) +/*---------------------------------------------------------------------------*/ +/* RateFix */ +#define UART_RATE_FIX (1 << 0) +/* #define UART_AUTORATE_FIX (1 << 1) */ +#define UART_FREQ_SEL (1 << 1) + +#define UART_RATE_FIX_13M (1 << 0) /* means UARTclk = APBclk / 4 */ +#define UART_AUTORATE_FIX_13M (1 << 1) +#define UART_FREQ_SEL_13M (1 << 2) +#define UART_RATE_FIX_ALL_13M (UART_RATE_FIX_13M|UART_AUTORATE_FIX_13M| \ + UART_FREQ_SEL_13M) + +#define UART_RATE_FIX_26M (0 << 0) /* means UARTclk = APBclk / 2 */ +#define UART_AUTORATE_FIX_26M (0 << 1) +#define UART_FREQ_SEL_26M (0 << 2) + +#define UART_RATE_FIX_16M25 (UART_FREQ_SEL|UART_RATE_FIX) + +#define UART_RATE_FIX_32M5 (UART_RATE_FIX) +/*---------------------------------------------------------------------------*/ +/* Autobaud sample */ +#define UART_AUTOBADUSAM_13M 7 +#define UART_AUTOBADUSAM_26M 15 +#define UART_AUTOBADUSAM_52M 31 +/* #define UART_AUTOBADUSAM_52M 29 CHECKME! 28 or 29 ? */ +#define UART_AUTOBAUDSAM_58_5M 31 /* CHECKME! 31 or 32 ? */ +/*---------------------------------------------------------------------------*/ +/* DMA enable */ +#define UART_RX_DMA_EN (1 << 0) +#define UART_TX_DMA_EN (1 << 1) +#define UART_TO_CNT_AUTORST (1 << 2) +/*---------------------------------------------------------------------------*/ +/* Escape character*/ +#define UART_ESCAPE_CH 0x77 +/*---------------------------------------------------------------------------*/ +/* Request UART to sleep*/ +#define UART_CLK_OFF_REQ (1 << 0) +/*---------------------------------------------------------------------------*/ +/* UART sleep ack*/ +#define UART_CLK_OFF_ACK (1 << 0) +/*---------------------------------------------------------------------------*/ +/* Debugging */ +typedef struct { + u32 NINT:1; + u32 ID:5; + u32 FIFOE:2; + u32 dummy:24; +} UART_IIR_REG; +/*---------------------------------------------------------------------------*/ +#ifndef CONFIG_OF +#define VFF_BASE_CH_S (6) +#define VFF_BASE_CH(n) (AP_DMA_BASE+0x0080*(n+1+VFF_BASE_CH_S)) +#endif +#define VFF_INT_FLAG(_b) (_b+0x0000) +#define VFF_INT_EN(_b) (_b+0x0004) +#define VFF_EN(_b) (_b+0x0008) +#define VFF_RST(_b) (_b+0x000C) +#define VFF_STOP(_b) (_b+0x0010) +#define VFF_FLUSH(_b) (_b+0x0014) +#define VFF_ADDR(_b) (_b+0x001C) +#define VFF_LEN(_b) (_b+0x0024) +#define VFF_THRE(_b) (_b+0x0028) +#define VFF_WPT(_b) (_b+0x002C) +#define VFF_RPT(_b) (_b+0x0030) +#define VFF_W_INT_BUF_SIZE(_b) (_b+0x0034) +#define VFF_INT_BUF_SIZE(_b) (_b+0x0038) +#define VFF_VALID_SIZE(_b) (_b+0x003C) +#define VFF_LEFT_SIZE(_b) (_b+0x0040) +#define VFF_DEBUG_STATUS(_b) (_b+0x0050) +#define VFF_4G_DRAM_SUPPORT(_b) (_b+0x0054) +#define VFF_VPORT_BASE 0xF7070000 +#define VFF_VPORT_CH(id) (VFF_VPORT_BASE + (id) * 0x00000080) +/*---------------------------------------------------------------------------*/ +/*VFF_INT_FLAG */ +#define VFF_RX_INT_FLAG0_B (1 << 0) /*rx_vff_valid_size >= rx_vff_thre */ +/*when UART issues flush to DMA and all data in UART VFIFO is transferred to VFF */ +#define VFF_RX_INT_FLAG1_B (1 << 1) +#define VFF_TX_INT_FLAG0_B (1 << 0) /*tx_vff_left_size >= tx_vff_thrs */ +#define VFF_INT_FLAG_CLR_B (0 << 0) +/*VFF_INT_EN*/ +#define VFF_RX_INT_EN0_B (1 << 0) /*rx_vff_valid_size >= rx_vff_thre */ +/*when UART issues flush to DMA and all data in UART VFIFO is transferred to VFF */ +#define VFF_RX_INT_EN1_B (1 << 1) +#define VFF_TX_INT_EN_B (1 << 0) /*tx_vff_left_size >= tx_vff_thrs */ +#define VFF_INT_EN_CLR_B (0 << 0) +/*VFF_RST*/ +#define VFF_WARM_RST_B (1 << 0) +#define VFF_HARD_RST_B (1 << 1) +/*VFF_EN*/ +#define VFF_EN_B (1 << 0) +/*VFF_STOP*/ +#define VFF_STOP_B (1 << 0) +#define VFF_STOP_CLR_B (0 << 0) +/*VFF_FLUSH*/ +#define VFF_FLUSH_B (1 << 0) +#define VFF_FLUSH_CLR_B (0 << 0) + +#define VFF_TX_THRE(n) ((n)*7/8) /*tx_vff_left_size >= tx_vff_thrs */ +#define VFF_RX_THRE(n) ((n)*3/4) /* trigger level of rx vfifo */ +/*---------------------------------------------------------------------------*/ +#endif /* MTK_UART_H */ diff --git a/drivers/misc/mediatek/usb11/mt6755/Makefile b/drivers/misc/mediatek/usb11/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d9739173efd039f7893ce3ebdef8faad8b6d4ffd --- /dev/null +++ b/drivers/misc/mediatek/usb11/mt6755/Makefile @@ -0,0 +1,5 @@ +obj-y := musbfsh_core.o +obj-$(CONFIG_MTK_USBFSH) += musbfsh_mt65xx.o musbfsh_debugfs.o + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/usb11/ +ccflags-y += -I$(srctree)/drivers/usb/core/ diff --git a/drivers/misc/mediatek/usb11/mt6755/musbfsh_core.c b/drivers/misc/mediatek/usb11/mt6755/musbfsh_core.c new file mode 100644 index 0000000000000000000000000000000000000000..12a71f2959f4c6dd3eddcbc1b976b9dfabe41d19 --- /dev/null +++ b/drivers/misc/mediatek/usb11/mt6755/musbfsh_core.c @@ -0,0 +1,2868 @@ +/* + * MUSB OTG driver core code + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * Copyright 2015 Mediatek Inc. + * Marvin Lin + * Arvin Wang + * Vincent Fan + * Bryant Lu + * Yu-Chang Wang + * Macpaul Lin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Inventra (Multipoint) Dual-Role Controller Driver for Linux. + * + * This consists of a Host Controller Driver (HCD) and a peripheral + * controller driver implementing the "Gadget" API; OTG support is + * in the works. These are normal Linux-USB controller drivers which + * use IRQs and have no dedicated thread. + * + * This version of the driver has only been used with products from + * Texas Instruments. Those products integrate the Inventra logic + * with other DMA, IRQ, and bus modules, as well as other logic that + * needs to be reflected in this driver. + * + * + * NOTE: the original Mentor code here was pretty much a collection + * of mechanisms that don't seem to have been fully integrated/working + * for *any* Linux kernel version. This version aims at Linux 2.6.now, + * Key open issues include: + * + * - Lack of host-side transaction scheduling, for all transfer types. + * The hardware doesn't do it; instead, software must. + * + * This is not an issue for OTG devices that don't support external + * hubs, but for more "normal" USB hosts it's a user issue that the + * "multipoint" support doesn't scale in the expected ways. That + * includes DaVinci EVM in a common non-OTG mode. + * + * * Control and bulk use dedicated endpoints, and there's as + * yet no mechanism to either (a) reclaim the hardware when + * peripherals are NAKing, which gets complicated with bulk + * endpoints, or (b) use more than a single bulk endpoint in + * each direction. + * + * RESULT: one device may be perceived as blocking another one. + * + * * Interrupt and isochronous will dynamically allocate endpoint + * hardware, but (a) there's no record keeping for bandwidth; + * (b) in the common case that few endpoints are available, there + * is no mechanism to reuse endpoints to talk to multiple devices. + * + * RESULT: At one extreme, bandwidth can be overcommitted in + * some hardware configurations, no faults will be reported. + * At the other extreme, the bandwidth capabilities which do + * exist tend to be severely undercommitted. You can't yet hook + * up both a keyboard and a mouse to an external USB hub. + */ + +/* + * This gets many kinds of configuration information: + * - Kconfig for everything user-configurable + * - platform_device for addressing, irq, and platform_data + * - platform_data is mostly for board-specific informarion + * (plus recentrly, SOC or family details) + * + * Most of the conditional compilation will (someday) vanish. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARM +#include +#include +#include +#endif + +#include "musbfsh_core.h" +#include "musbfsh_host.h" +#include "musbfsh_dma.h" +#include "musbfsh_hsdma.h" +#include "musbfsh_mt65xx.h" +#include "usb.h" + +#include +#include +#include + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + +struct my_attr skip_session_req_attr = { + .attr.name = "skip_session_req", + .attr.mode = 0644, +#ifdef MTK_ICUSB_SKIP_SESSION_REQ + .value = 1 +#else + .value = 0 +#endif +}; + +struct my_attr skip_enable_session_attr = { + .attr.name = "skip_enable_session", + .attr.mode = 0644, +#ifdef MTK_ICUSB_SKIP_ENABLE_SESSION + .value = 1 +#else + .value = 0 +#endif +}; + +struct my_attr skip_mac_init_attr = { + .attr.name = "skip_mac_init", + .attr.mode = 0644, +#ifdef MTK_ICUSB_SKIP_MAC_INIT + .value = 1 +#else + .value = 0 +#endif +}; + +struct my_attr hw_dbg_attr = { + .attr.name = "hw_dbg", + .attr.mode = 0644, +#ifdef MTK_ICUSB_HW_DBG + .value = 1 +#else + .value = 0 +#endif +}; + +#endif + +static int __init musbfsh_dts_probe(struct platform_device *pdev); + +static const struct of_device_id apusb11_of_ids[] = { + {.compatible = "mediatek,ICUSB",}, + {}, +}; + +static struct platform_driver musbfsh_dts_driver = { + .driver = { + .name = "musb11_dts", + .of_match_table = apusb11_of_ids, + }, + .probe = musbfsh_dts_probe, +}; + +#ifdef CONFIG_MTK_USBFSH + +#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia, Mediatek" +#define DRIVER_DESC "MT65xx USB1.1 Host Controller Driver" + +#define MUSBFSH_VERSION "6.0" + +#define DRIVER_INFO DRIVER_DESC ", v" MUSBFSH_VERSION + +#define MUSBFSH_DRIVER_NAME "musbfsh_hdrc" +const char musbfsh_driver_name[] = MUSBFSH_DRIVER_NAME; + +MODULE_DESCRIPTION(DRIVER_INFO); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" MUSBFSH_DRIVER_NAME); + +struct wake_lock musbfsh_suspend_lock; +struct musbfsh *g_musbfsh; +static u64 usb11_dmamask = DMA_BIT_MASK(32); + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +/* extern void slp_infra_en(bool en); */ +#ifdef CONFIG_PM +static int suspend_cnt = 0, resume_cnt; +#endif +#endif + +DEFINE_SPINLOCK(musbfs_io_lock); + +static struct musbfsh *mtk_musbfsh; +int is_musbfsh_rh(struct usb_device *udev) +{ + struct usb_device *rhdev; + struct usb_hcd *hcd; + + if (!mtk_musbfsh) { + MYDBG("mtk_musbfsh is NULL!\n"); + return 0; + } + + hcd = musbfsh_to_hcd(mtk_musbfsh); + rhdev = hcd->self.root_hub; + return (udev == rhdev) ? 1 : 0; +} + +#ifdef MTK_DT_USB_SUPPORT +extern void request_wakeup_md_timeout(unsigned int dev_id, + unsigned int dev_sub_id); +#endif +void mt65xx_usb11_suspend_resume_test(void) +{ + u8 power; + u32 frame_number; + + MYDBG("begin\n"); + + power = musbfsh_readb((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_POWER); + /* power &= ~MUSBFSH_POWER_RESUME; */ + power |= MUSBFSH_POWER_ENSUSPEND; + power |= MUSBFSH_POWER_SUSPENDM; + musbfsh_writeb((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_POWER, power); + + frame_number = + musbfsh_readw((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + mdelay(12); + MYDBG("suspend done\n"); + frame_number = + musbfsh_readw((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + mdelay(1000); + MYDBG("start resuming\n"); + +#ifdef MTK_DT_USB_SUPPORT + MYDBG("request md wake up\n"); + request_wakeup_md_timeout(0, 0); +#endif + + power = musbfsh_readb((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_POWER); + power &= ~MUSBFSH_POWER_SUSPENDM; + power |= MUSBFSH_POWER_RESUME; + musbfsh_writeb((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_POWER, power); + MYDBG(""); + + mdelay(12); + MYDBG("stop resuming\n"); + + power = musbfsh_readb((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_POWER); + power &= ~MUSBFSH_POWER_RESUME; + musbfsh_writeb((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_POWER, power); + + frame_number = + musbfsh_readw((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_FRAME); + MYDBG("frame_number: %d\n", frame_number); + + mdelay(3); + + frame_number = + musbfsh_readw((unsigned char __iomem *)mtk_musbfsh->mregs, + MUSBFSH_FRAME); + MYDBG("frame_number: %d\n", frame_number); + + MYDBG("end\n"); +} + +#ifdef MTK_DT_USB_SUPPORT +static int ext_usb_wkup_irq; + +/* + * wx, seconds for hold wake lock and suspend schedule, + * please also check cdc-acm.c to sync, they should be the same + */ +#define USB_WAKE_TIME 5 +struct wake_lock usb_resume_lock; + +void release_usb11_wakelock(void) +{ + MYDBG("\n"); + if (musbfsh_wake_lock_hold) + wake_unlock(&musbfsh_suspend_lock); +} + +irqreturn_t remote_wakeup_irq(unsigned irq, struct irq_desc *desc) +{ + musbfsh_eint_cnt++; + MYDBG("cpuid:%d\n", smp_processor_id()); +#if 0 + u8 power, devctl; + unsigned long flags; + + if (!mtk_musbfsh) { + MYDBG("\n"); /* 04404_test */ + return; + } + MYDBG("\n"); /* 04404_test */ + spin_lock_irqsave(&mtk_musbfsh->lock, flags); + + devctl = musbfsh_readb(mtk_musbfsh->mregs, MUSBFSH_DEVCTL); + if (devctl & MUSBFSH_DEVCTL_HM) { + wake_lock_timeout(&usb_resume_lock, USB_WAKE_TIME * HZ); + musbfsh_set_power(mtk_musbfsh, 1); + power = musbfsh_readb(mtk_musbfsh->mregs, MUSBFSH_POWER); + WARNING("Remote wakeup! power=0x%x\n", power); + if (!(power & MUSBFSH_POWER_SUSPENDM)) { + MYDBG("\n"); /* 04404_test */ + goto out; + } + + /* remote wakeup? later, GetPortStatus + * will stop RESUME signaling + */ + power &= ~MUSBFSH_POWER_SUSPENDM; + musbfsh_writeb(mtk_musbfsh->mregs, MUSBFSH_POWER, + power | MUSBFSH_POWER_RESUME); + + mtk_musbfsh->port1_status |= (USB_PORT_STAT_C_SUSPEND << 16) + | MUSBFSH_PORT_STAT_RESUME; + mtk_musbfsh->rh_timer = jiffies + msecs_to_jiffies(20); + + mtk_musbfsh->is_active = 1; + usb_hcd_resume_root_hub(musbfsh_to_hcd(mtk_musbfsh)); + } +out: + spin_unlock_irqrestore(&mtk_musbfsh->lock, flags); +#endif + + /* disable_irq_nosync(irq); // for non-automatic mask */ + return IRQ_HANDLED; +} + +void get_eint_ext_usb_wkup_irq(void) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, + "mediatek, DT_EXT_MD_WK_UP_USB-eint"); + if (node) { + /* this step will set irq feature by dtsi */ + ext_usb_wkup_irq = irq_of_parse_and_map(node, 0); + if (!ext_usb_wkup_irq) { + MYDBG("can't irq_of_parse_and_map!\n"); + return; + } + + } else { + MYDBG("can't find node\n"); + } +} + +void register_eint_usb_p1_wakeup_callback(void) +{ + int ret; + + if (!ext_usb_wkup_irq) { + MYDBG("no ext_usb_wkup_irq\n"); + return; + } + /* still could chg feature here */ + ret = request_irq(ext_usb_wkup_irq, (irq_handler_t)remote_wakeup_irq, + IRQF_TRIGGER_FALLING, + "DT_EXT_MD_WK_UP_USB-eint", NULL); + if (ret > 0) { + MYDBG("eint irq %d not available\n", ext_usb_wkup_irq); + return; + } + +} +#endif + + +/* #define ORG_SUSPEND_RESUME_TEST */ +#ifdef ORG_SUSPEND_RESUME_TEST +#define USB_BASE 0xF1200000 +void mt65xx_usb20_suspend_resume_test(void) +{ + u8 power; + u32 frame_number; + unsigned char __iomem *mregs = g_musbfsh->mregs; + + MYDBG("begin\n"); + + power = musbfsh_readb(mregs, MUSBFSH_POWER); + /* power &= ~MUSBFSH_POWER_RESUME; */ + power |= MUSBFSH_POWER_ENSUSPEND; + power |= MUSBFSH_POWER_SUSPENDM; + musbfsh_writeb(mregs, MUSBFSH_POWER, power); + + frame_number = musbfsh_readw(mregs, MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + mdelay(12); + MYDBG("suspend done\n"); + frame_number = musbfsh_readw(mregs, MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + mdelay(1000); + MYDBG("start resuming\n"); + + power = musbfsh_readb(mregs, MUSBFSH_POWER); + power &= ~MUSBFSH_POWER_SUSPENDM; + power |= MUSBFSH_POWER_RESUME; + musbfsh_writeb(mregs, MUSBFSH_POWER, power); + MYDBG(""); + + mdelay(12); + MYDBG("stop resuming\n"); + + power = musbfsh_readb(mregs, MUSBFSH_POWER); + power &= ~MUSBFSH_POWER_RESUME; + musbfsh_writeb(mregs, MUSBFSH_POWER, power); + + frame_number = musbfsh_readw(mregs, MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + mdelay(3); + + frame_number = musbfsh_readw(mregs, MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + MYDBG("end\n"); +} +#endif + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +static int usb11_enabled; + +unsigned char g_usb_clk_reg_before, g_usb_clk_reg_after; +unsigned char g_FS_EOF1_before, g_FS_EOF1_after; + +#define USB_BASE 0xF1200000 +void mt65xx_usb20_suspend_resume_test(void) +{ + u8 power; + u32 frame_number; + unsigned char __iomem *mregs = g_musbfsh->mregs; + + MYDBG("begin\n"); + + power = musbfsh_readb(mregs, MUSBFSH_POWER); + /* power &= ~MUSBFSH_POWER_RESUME; */ + power |= MUSBFSH_POWER_ENSUSPEND; + power |= MUSBFSH_POWER_SUSPENDM; + musbfsh_writeb(mregs, MUSBFSH_POWER, power); + + frame_number = musbfsh_readw(mregs, MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + mdelay(12); + MYDBG("suspend done\n"); + frame_number = musbfsh_readw(mregs, MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + mdelay(1000); + MYDBG("start resuming\n"); + + power = musbfsh_readb(mregs, MUSBFSH_POWER); + power &= ~MUSBFSH_POWER_SUSPENDM; + power |= MUSBFSH_POWER_RESUME; + musbfsh_writeb(mregs, MUSBFSH_POWER, power); + MYDBG(""); + + mdelay(12); + MYDBG("stop resuming\n"); + + power = musbfsh_readb(mregs, MUSBFSH_POWER); + power &= ~MUSBFSH_POWER_RESUME; + musbfsh_writeb(mregs, MUSBFSH_POWER, power); + + frame_number = musbfsh_readw(mregs, MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + mdelay(3); + + frame_number = musbfsh_readw(mregs, MUSBFSH_FRAME); + MYDBG("frame_number : %d\n", frame_number); + + MYDBG("end\n"); + +} + + +void musbfsh_root_disc_procedure(void) +{ + MYDBG(""); + usb_hcd_resume_root_hub(musbfsh_to_hcd(g_musbfsh)); + musbfsh_root_disconnect(g_musbfsh); +} + +void ic_usb_clk_chg(void) +{ + /* b01 for 69 MHZ, b10 for 41.6MHZ */ + g_usb_clk_reg_before = __raw_readb((void __iomem *)0xF000014C); + g_usb_clk_reg_after = g_usb_clk_reg_before & (~0x1); + g_usb_clk_reg_after = g_usb_clk_reg_after | 0x2; + __raw_writeb(g_usb_clk_reg_after, (void __iomem *)0xF000014C); +} + +void musbfsh_open_vsim_power(int on) +{ + if (on) { + pmic_set_register_value(PMIC_RG_VSIM1_VOSEL, 0x7); + pmic_set_register_value(PMIC_RG_VSIM1_EN, 1); + /* + * hwPowerOn(MT6351_POWER_LDO_VSIM1, + * VOL_3100*1000, "USB11-SIM"); + */ + } else { + pmic_set_register_value(PMIC_RG_VSIM1_EN, 0); + /* hwPowerDown(MT6351_POWER_LDO_VSIM1, "USB11-SIM"); */ + } + MYDBG("%s = %d\n", __func__, on); +} + +void musbfsh_open_vsim_power1(int on) +{ + if (on) { + pmic_set_register_value(PMIC_RG_VSIM1_VOSEL, 0x7); + pmic_set_register_value(PMIC_RG_VSIM1_EN, 1); + /* + * hwPowerOn(MT6351_POWER_LDO_VSIM1, + * VOL_3100*1000, "USB11-SIM"); + */ + + } else { + pmic_set_register_value(PMIC_RG_VSIM1_EN, 0); + /*hwPowerDown(MT6351_POWER_LDO_VSIM1, "USB11-SIM"); */ + } + MYDBG("musbfsh_open_vsim_power = %d\n", on); +} + +void musbfsh_start_session_pure(void) +{ + u8 devctl; + unsigned char __iomem *mregs; + + MYDBG(""); + mregs = g_musbfsh->mregs; + devctl = musbfsh_readb(mregs, MUSBFSH_DEVCTL); + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(mregs, MUSBFSH_DEVCTL, devctl); + + MYDBG("[IC-USB]start session PURE\n"); +} + +void musbfsh_init_phy_by_voltage(enum PHY_VOLTAGE_TYPE phy_volt) +{ + MYDBG(""); + if (!usb11_enabled) { + usb11_enabled = 1; + mt65xx_usb11_enable_clk_pll_pw(); + } + + set_usb_phy_voltage(phy_volt); + mt65xx_usb11_phy_poweron(); + +} + +void musbfsh_start_session(void) +{ + u8 devctl; + unsigned char __iomem *mregs; + + mregs = g_musbfsh->mregs; + /* clear session */ + devctl = musbfsh_readb(mregs, MUSBFSH_DEVCTL); + musbfsh_writeb(mregs, MUSBFSH_DEVCTL, + (devctl & (~MUSBFSH_DEVCTL_SESSION))); + + USB11PHY_SET8(0x6c, 0x10); + USB11PHY_CLR8(0x6c, 0x2E); + USB11PHY_SET8(0x6d, 0x3E); + mdelay(5); + devctl = musbfsh_readb(mregs, MUSBFSH_DEVCTL); + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(mregs, MUSBFSH_DEVCTL, devctl); + + USB11PHY_CLR8(0x6c, 0x10); + USB11PHY_SET8(0x6c, 0x2c); + USB11PHY_SET8(0x6d, 0x3e); + +#ifdef MTK_ICUSB_TAKE_WAKE_LOCK + MYDBG("[IC-USB]start session, wake_lock taken feature enalbed\n"); +#else + MYDBG("[IC-USB]start session, wake_lock taken feature disalbed\n"); +#endif +} + +void musbfsh_stop_session(void) +{ + u8 devctl; + unsigned char __iomem *mregs; + + MYDBG(""); + mregs = g_musbfsh->mregs; + devctl = musbfsh_readb(mregs, MUSBFSH_DEVCTL); + devctl &= ~(MUSBFSH_DEVCTL_SESSION); + musbfsh_writeb(mregs, MUSBFSH_DEVCTL, devctl); + + MYDBG("[IC_USB] stop session\n"); +} + +#if defined(MTK_ICUSB_BABBLE_RECOVER) || defined(MTK_SMARTBOOK_SUPPORT) +static struct timer_list babble_recover_timer; +static void babble_recover_func(unsigned long _musbfsh) +{ + int flags = 0; + u8 devctl = 0; + struct musbfsh *musbfsh = (struct musbfsh *)_musbfsh; + + WARNING("execute babble_recover_func!\n"); + + /* + * mdelay here for waiting hardware state machine, + * jiffies controlled call-back might not be accurate. + */ + mdelay(20); + + spin_lock_irqsave(&musbfsh->lock, flags); + + mt65xx_usb11_mac_phy_babble_recover(musbfsh); + + mdelay(1); + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(musbfsh->mregs, MUSBFSH_DEVCTL, devctl); + + del_timer(&babble_recover_timer); + + spin_unlock_irqrestore(&musbfsh->lock, flags); +} +#endif + + + + +static int musbfsh_core_init1(struct musbfsh *musbfsh); +static void musbfsh_generic_disable(struct musbfsh *musbfsh); +void musbfsh_mac_init(void) +{ + struct timeval tv_begin, tv_end; + + do_gettimeofday(&tv_begin); + + MYDBG(""); + + musbfsh_generic_disable(g_musbfsh); + + musbfsh_writeb(g_musbfsh->mregs, + MUSBFSH_HSDMA_DMA_INTR_UNMASK_SET, 0xff); + + musbfsh_core_init1(g_musbfsh); + + musbfsh_start(g_musbfsh); + + do_gettimeofday(&tv_end); + MYDBG("time spent, sec : %d, usec : %d\n", + (unsigned int)(tv_end.tv_sec - tv_begin.tv_sec), + (unsigned int)(tv_end.tv_usec - tv_begin.tv_usec)); + +} + +int is_usb11_enabled(void) +{ + return usb11_enabled; +} + +void set_usb11_enabled(void) +{ + usb11_enabled = 1; +} +#endif + +#if 0 /* IC_USB from SS5 */ +#ifdef IC_USB +static ssize_t show_start(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "start session under IC-USB mode\n"); +} + +static ssize_t store_start(struct device *dev, struct device_attribute *attr, + const char *buf, + size_t size) +{ + char *pvalue = NULL; + unsigned long value = 0; + int ret; + size_t count = 0; + unsigned char __iomem *usb11_base = USB11_BASE; + u8 devctl = musbfsh_readb(usb11_base, MUSBFSH_DEVCTL); + + ret = kstrtoul(&pvalue, 10, &value); + + if (ret) + return ERR_PTR(-EINVAL); + + count = pvalue - buf; + + if (*pvalue && isspace(*pvalue)) + count++; + + if (count == size) { + if (value) { + WARNING("[IC-USB]start session\n"); + /* wx? why not wait until device connected */ + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(usb11_base, MUSBFSH_DEVCTL, devctl); + WARNING("[IC-USB]power on VSIM\n"); + hwPowerOn(MT65XX_POWER_LDO_VSIM, VOL_3000, "USB11-SIM"); + } + } + return size; +} + +static DEVICE_ATTR(start, 0666, show_start, store_start); +#endif +#endif + +/*-------------------------------------------------------------------------*/ + +static inline struct musbfsh *dev_to_musbfsh(struct device *dev) +{ + return hcd_to_musbfsh(dev_get_drvdata(dev)); +} + + +/*-------------------------------------------------------------------------*/ +/* #ifdef CONFIG_MUSBFSH_PIO_ONLY */ +/* + * Load an endpoint's FIFO + */ +void musbfsh_write_fifo(struct musbfsh_hw_ep *hw_ep, u16 len, const u8 *src) +{ + void __iomem *fifo = hw_ep->fifo; + + prefetch((u8 *) src); + INFO("%cX ep%d fifo %p count %d buf %p\n", 'T', + hw_ep->epnum, fifo, len, src); + + /* we can't assume unaligned reads work */ + if (likely((0x01 & (unsigned long)src) == 0)) { + u16 index = 0; + + /* best case is 32bit-aligned source address */ + if ((0x02 & (unsigned long)src) == 0) { + if (len >= 4) { + /* writesl(fifo, src + index, len >> 2); */ + iowrite32_rep(fifo, src + index, len >> 2); + index += len & ~0x03; + } + if (len & 0x02) { + musbfsh_writew(fifo, 0, *(u16 *) &src[index]); + index += 2; + } + } else { + if (len >= 2) { + /* writesw(fifo, src + index, len >> 1); */ + iowrite16_rep(fifo, src + index, len >> 1); + index += len & ~0x01; + } + } + if (len & 0x01) + musbfsh_writeb(fifo, 0, src[index]); + } else { + /* byte aligned */ + /* writesb(fifo, src, len); */ + iowrite8_rep(fifo, src, len); + } + +} + +/* + * Unload an endpoint's FIFO + */ +void musbfsh_read_fifo(struct musbfsh_hw_ep *hw_ep, u16 len, u8 *dst) +{ + void __iomem *fifo = hw_ep->fifo; + + INFO("%cX ep%d fifo %p count %d buf %p\n", 'R', + hw_ep->epnum, fifo, len, dst); + + /* we can't assume unaligned writes work */ + if (likely((0x01 & (unsigned long)dst) == 0)) { + u16 index = 0; + + /* best case is 32bit-aligned destination address */ + if ((0x02 & (unsigned long)dst) == 0) { + if (len >= 4) { + /* readsl(fifo, dst, len >> 2); */ + ioread32_rep(fifo, dst, len >> 2); + index = len & ~0x03; + } + if (len & 0x02) { + *(u16 *) &dst[index] = musbfsh_readw(fifo, 0); + index += 2; + } + } else { + if (len >= 2) { + /* readsw(fifo, dst, len >> 1); */ + ioread16_rep(fifo, dst, len >> 1); + index = len & ~0x01; + } + } + if (len & 0x01) + dst[index] = musbfsh_readb(fifo, 0); + } else { + /* byte aligned */ + /* readsb(fifo, dst, len); */ + ioread8_rep(fifo, dst, len); + } +} + + +/* for high speed test mode; see USB 2.0 spec 7.1.20 */ +static const u8 musbfsh_test_packet[53] = { + /* implicit SYNC then DATA0 to start */ + + /* JKJKJKJK x9 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* JJKKJJKK x8 */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + /* JJJJKKKK x8 */ + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + /* JJJJJJJKKKKKKK x8 */ + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + /* JJJJJJJK x8 */ + 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, + /* JKKKKKKK x10, JK */ + 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e + /* implicit CRC16 then EOP to end */ +}; + +void musbfsh_load_testpacket(struct musbfsh *musbfsh) +{ + void __iomem *regs = musbfsh->endpoints[0].regs; + + musbfsh_ep_select(musbfsh->mregs, 0); /* should be implemented */ + musbfsh_write_fifo(musbfsh->control_ep, sizeof(musbfsh_test_packet), + musbfsh_test_packet); + musbfsh_writew(regs, MUSBFSH_CSR0, MUSBFSH_CSR0_TXPKTRDY); +} + +/* + * Interrupt Service Routine to record USB "global" interrupts. + * Since these do not happen often and signify things of + * paramount importance, it seems OK to check them individually; + * the order of the tests is specified in the manual + * + * @param musb instance pointer + * @param int_usb register contents + * @param devctl + * @param power + */ + +/* #define MUSBFSH_DBG_REG */ +static irqreturn_t musbfsh_stage0_irq(struct musbfsh *musbfsh, u8 int_usb, + u8 devctl, u8 power) +{ + void __iomem *mregs = musbfsh->mregs; + +#if 0 + u8 intusbe = musbfsh_readb(musbfsh->mregs, MUSBFSH_INTRUSBE); + + MYDBG("devctl : %x, power : %x, int_usb : %x, intusbe : %x\n", + devctl, power, int_usb, + intusbe); +#endif + +#ifdef MUSBFSH_DBG_REG + int i; + u32 addr[] = {0x60, 0x74, 0x620, 0x630}; + + for (i = 0; i < sizeof(addr) / sizeof(u32); i++) { + WARNING("dbg addr : %x, val : %x\n", addr[i], + musbfsh_readl(musbfsh->mregs, addr[i])); + } +#endif + + irqreturn_t handled = IRQ_NONE; + + /* in host mode, the peripheral may issue remote wakeup. + * in peripheral mode, the host may resume the link. + * spurious RESUME irqs happen too, paired with SUSPEND. + */ + if (int_usb & MUSBFSH_INTR_RESUME) { + handled = IRQ_HANDLED; + WARNING("RESUME!\n"); + + if (devctl & MUSBFSH_DEVCTL_HM) { + /* + * remote wakeup? later, GetPortStatus + * will stop RESUME signaling + */ + + if (power & MUSBFSH_POWER_SUSPENDM) { + /* spurious */ + musbfsh->int_usb &= ~MUSBFSH_INTR_SUSPEND; + WARNING("Spurious SUSPENDM\n"); + } + + power &= ~MUSBFSH_POWER_SUSPENDM; + musbfsh_writeb(mregs, MUSBFSH_POWER, power | + MUSBFSH_POWER_RESUME); + + musbfsh->port1_status |= (USB_PORT_STAT_C_SUSPEND << 16) + | MUSBFSH_PORT_STAT_RESUME; + musbfsh->rh_timer = jiffies + msecs_to_jiffies(20); + + musbfsh->is_active = 1; + usb_hcd_resume_root_hub(musbfsh_to_hcd(musbfsh)); + } + } + + /* see manual for the order of the tests */ + if (int_usb & MUSBFSH_INTR_SESSREQ) { + /* will not run to here */ + WARNING("SESSION_REQUEST\n"); + + /* IRQ arrives from ID pin sense or (later, if VBUS power + * is removed) SRP. responses are time critical: + * - turn on VBUS (with silicon-specific mechanism) + * - go through A_WAIT_VRISE + * - ... to A_WAIT_BCON. + * a_wait_vrise_tmout triggers VBUS_ERROR transitions + */ + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + if (skip_session_req_attr.value) { + MYDBG("SESSION_REQUEST SKIPPED FOR IC USB\n"); + } else { + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(mregs, MUSBFSH_DEVCTL, devctl); + musbfsh->ep0_stage = MUSBFSH_EP0_START; + musbfsh_set_vbus(musbfsh, 1); + } +#else + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(mregs, MUSBFSH_DEVCTL, devctl); + musbfsh->ep0_stage = MUSBFSH_EP0_START; + musbfsh_set_vbus(musbfsh, 1); +#endif + + + handled = IRQ_HANDLED; + } + + if (int_usb & MUSBFSH_INTR_VBUSERROR) { + int ignore = 0; + char *s; + + /* During connection as an A-Device, we may see a short + * current spikes causing voltage drop, because of cable + * and peripheral capacitance combined with vbus draw. + * (So: less common with truly self-powered devices, where + * vbus doesn't act like a power supply.) + * + * Such spikes are short; usually less than ~500 usec, max + * of ~2 msec. That is, they're not sustained overcurrent + * errors, though they're reported using VBUSERROR irqs. + * + * Workarounds: (a) hardware: use self powered devices. + * (b) software: ignore non-repeated VBUS errors. + * + * REVISIT: do delays from lots of DEBUG_KERNEL checks + * make trouble here, keeping VBUS < 4.4V ? + */ + if (musbfsh->vbuserr_retry) { + musbfsh->vbuserr_retry--; + ignore = 1; + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(mregs, MUSBFSH_DEVCTL, devctl); + } else { + musbfsh->port1_status |= + USB_PORT_STAT_OVERCURRENT | + (USB_PORT_STAT_C_OVERCURRENT << 16); + } + + switch (devctl & MUSBFSH_DEVCTL_VBUS) { + case 0 << MUSBFSH_DEVCTL_VBUS_SHIFT: + s = "vbuserr_retry, + musbfsh->port1_status); + + /* go through A_WAIT_VFALL then start a new session */ + if (!ignore) + musbfsh_set_vbus(musbfsh, 0); + handled = IRQ_HANDLED; + } + + if (int_usb & MUSBFSH_INTR_CONNECT) { + struct usb_hcd *hcd = musbfsh_to_hcd(musbfsh); + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + set_usb11_sts_connect(); +#endif + +#ifndef CONFIG_MTK_ICUSB_SUPPORT +#ifndef MTK_DT_USB_SUPPORT + wake_lock(&musbfsh_suspend_lock); +#endif +#endif + + handled = IRQ_HANDLED; + musbfsh->is_active = 1; + musbfsh->ep0_stage = MUSBFSH_EP0_START; + musbfsh->port1_status &= + ~(USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED | + USB_PORT_STAT_ENABLE); + musbfsh->port1_status |= + USB_PORT_STAT_CONNECTION | + (USB_PORT_STAT_C_CONNECTION << 16); + + /* high vs full speed is just a guess until after reset */ + if (devctl & MUSBFSH_DEVCTL_LSDEV) + musbfsh->port1_status |= USB_PORT_STAT_LOW_SPEED; + + if (hcd->status_urb) + usb_hcd_poll_rh_status(hcd); + else + usb_hcd_resume_root_hub(hcd); + + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +#define OPSTATE_MODE 0x04 +#define OSR_INTE 0x80 +#define OSR_START 0x01 + + if (hw_dbg_attr.value) { + /* start hw debugging */ + u8 opr_csr = musbfsh_readb(mregs, 0x610); + + opr_csr |= OPSTATE_MODE; + opr_csr |= OSR_INTE; + opr_csr |= OSR_START; + musbfsh_writeb(mregs, 0x610, opr_csr); + } else { + MYDBG(""); + } +#if 0 + WARNING("CONNECT! devctl 0x%02x, g_usb_clk_reg_before: %x\n", + devctl, g_usb_clk_reg_before); + WARNING("g_usb_clk_reg_after: %x, 0xF000014C: %x\n", + g_usb_clk_reg_after, __raw_readb(0xF000014C)); + WARNING("g_FS_EOF1_before: %x, g_FS_EOF1_after :%x\n", + g_FS_EOF1_before, g_FS_EOF1_after); +#endif +#endif + mtk_musbfsh = musbfsh; +#ifdef MTK_DT_USB_SUPPORT + /* wx, need to be done before EINT unmask */ + wake_lock_init(&usb_resume_lock, WAKE_LOCK_SUSPEND, + "USB11 wakelock"); + register_eint_usb_p1_wakeup_callback(); +#endif + WARNING("CONNECT ! devctl 0x%02x\n", devctl); + + } + + if (int_usb & MUSBFSH_INTR_DISCONNECT) { + WARNING("DISCONNECT !devctl %02x\n", devctl); +#ifdef CONFIG_MTK_ICUSB_SUPPORT + if (!check_usb11_sts_disconnect_done()) + set_usb11_sts_disconnecting(); + mt65xx_usb11_mac_reset_and_phy_stress_set(); +#endif + handled = IRQ_HANDLED; + usb_hcd_resume_root_hub(musbfsh_to_hcd(musbfsh)); + musbfsh_root_disconnect(musbfsh); + + +#ifndef CONFIG_MTK_ICUSB_SUPPORT +#ifndef MTK_DT_USB_SUPPORT + wake_unlock(&musbfsh_suspend_lock); +#endif +#endif + } + + /* mentor saves a bit: bus reset and babble share the same irq. + * only host sees babble; only peripheral sees bus reset. + */ + if (int_usb & MUSBFSH_INTR_BABBLE) { + handled = IRQ_HANDLED; + /* + * Looks like non-HS BABBLE can be ignored, but + * HS BABBLE is an error condition. For HS the solution + * is to avoid babble in the first place and fix what + * caused BABBLE. When HS BABBLE happens we can only + * stop the session. + */ + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +#define OSR_START 0x01 + + if (hw_dbg_attr.value) { + unsigned int dbg_regs[] = { /* debug registers */ + 0x640, 0x644, 0x648, 0x64C, + 0x650, 0x654, 0x658, 0x65C + }; + int i; + u8 op_state; + u8 opr_csr = musbfsh_readb(mregs, 0x610); + + /* stop hw debugging */ + opr_csr &= ~OSR_START; + musbfsh_writeb(mregs, 0x610, opr_csr); + + udelay(100); + + /* dump result */ + WARNING("BABBLE!, dump dbg register\n"); + + for (i = 0; i < sizeof(dbg_regs) / sizeof(int); i++) + pr_err("offset=%x, value=%x\n", dbg_regs[i], + musbfsh_readl(mregs, dbg_regs[i])); + + op_state = (u8) musbfsh_readb(mregs, (unsigned)0x620); + WARNING("BABBLE!, op_state : %x\n", + (unsigned int)op_state); + } else { + MYDBG(""); + } +#endif +#if defined(MTK_ICUSB_BABBLE_RECOVER) || defined(MTK_SMARTBOOK_SUPPORT) + /* call mt65xx_usb11_mac_phy_babble_clear at first */ + mt65xx_usb11_mac_phy_babble_clear(musbfsh); + + /* run babble_recover 20ms later */ + /* musbfsh->rh_timer = jiffies + msecs_to_jiffies(100); */ + + WARNING("BABBLE! schedule babble_recover\n"); + + usb_hcd_resume_root_hub(musbfsh_to_hcd(musbfsh)); + musbfsh_root_disconnect(musbfsh); + + mod_timer(&babble_recover_timer, + jiffies + msecs_to_jiffies(5000)); +#else + if (devctl & (MUSBFSH_DEVCTL_FSDEV | MUSBFSH_DEVCTL_LSDEV)) { + ERR("BABBLE devctl: %02x\n", devctl); + /* + * musbfsh_writeb(musbfsh->mregs, + * MUSBFSH_INTRUSBE, 0xf3); + */ + } else { + ERR("Stopping host session -- babble, devctl : %x\n", + devctl); + musbfsh_writeb(musbfsh->mregs, MUSBFSH_DEVCTL, 0); + } +#endif + } + + return handled; +} + + +/* +* Program the HDRC to start (enable interrupts, dma, etc.). +*/ +void musbfsh_start(struct musbfsh *musbfsh) +{ + void __iomem *regs = musbfsh->mregs; /* base address of usb mac */ + u8 devctl = musbfsh_readb(regs, MUSBFSH_DEVCTL); + u8 power = musbfsh_readb(regs, MUSBFSH_POWER); + int int_level1 = 0; + + WARNING("<== devctl 0x%02x\n", devctl); + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +#if 0 + /* no automatically stop session when babble */ + unsigned char result = musbfsh_readb(regs, 0x74); + + result &= ~(0x40); + musbfsh_writeb(regs, 0x74, result); + + /* macpual test from web , TI solution */ + g_FS_EOF1_before = musbfsh_readb(regs, 0x7D); + musbfsh_writeb(regs, 0x7D, 0xB4); + g_FS_EOF1_after = musbfsh_readb(regs, 0x7D); +#endif +#endif + + /* Set INT enable registers, enable interrupts */ + musbfsh_writew(regs, MUSBFSH_INTRTXE, musbfsh->epmask); + musbfsh_writew(regs, MUSBFSH_INTRRXE, musbfsh->epmask & 0xfffe); + + musbfsh_writeb(regs, MUSBFSH_INTRUSBE, 0xf7); + + /* enable level 1 interrupts */ + musbfsh_writew(regs, USB11_L1INTM, 0x000f); + int_level1 = musbfsh_readw(musbfsh->mregs, USB11_L1INTM); + INFO("Level 1 Interrupt Mask 0x%x\n", int_level1); + int_level1 = musbfsh_readw(musbfsh->mregs, USB11_L1INTP); + INFO("Level 1 Interrupt Polarity 0x%x\n", int_level1); + + /* flush pending interrupts */ + musbfsh_writew(regs, MUSBFSH_INTRTX, 0xffff); + musbfsh_writew(regs, MUSBFSH_INTRRX, 0xffff); + musbfsh_writeb(regs, MUSBFSH_INTRUSB, 0xff); + musbfsh_writeb(regs, MUSBFSH_HSDMA_INTR, 0xff); + + musbfsh->is_active = 0; + musbfsh->is_multipoint = 1; + + /* need to enable the VBUS */ +#ifndef MTK_DT_USB_SUPPORT + musbfsh_set_vbus(musbfsh, 1); +#endif + musbfsh_platform_enable(musbfsh); + +#if 0 /* IC_USB from SS5 */ +#ifndef IC_USB + /* start session, assume ID pin is hard-wired to ground */ + /* wx? why not wait until device connected */ + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(regs, MUSBFSH_DEVCTL, devctl); +#endif +#endif + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + if (skip_enable_session_attr.value) { + MYDBG("SESSION ENABLE SKIPPED FOR IC USB\n"); + } else { + /* start session, assume ID pin is hard-wired to ground */ + /* wx? why not wait until device connected */ + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(regs, MUSBFSH_DEVCTL, devctl); + } +#else + /* start session, assume ID pin is hard-wired to ground */ + /* wx? why not wait until device connected */ + devctl |= MUSBFSH_DEVCTL_SESSION; + musbfsh_writeb(regs, MUSBFSH_DEVCTL, devctl); +#endif + + /* disable high speed negotiate */ + power |= MUSBFSH_POWER_HSENAB; + power |= MUSBFSH_POWER_SOFTCONN; + + /* wx, not necessary for USB11 host */ + /* power &= ~(MUSBFSH_POWER_HSENAB); */ + /* + * enable SUSPENDM, this will put PHY into low power mode, + * not so "low" as save current mode, + * but it will be able to detect line state + * (remote wakeup/connect/disconnect) + */ + power |= MUSBFSH_POWER_ENSUSPEND; + musbfsh_writeb(regs, MUSBFSH_POWER, power); + +#ifdef MUSBFSH_DBG_REG + /* stop auto clear session */ + u32 tmp = musbfsh_readl(regs, 0x74); + + WARNING("tmp :%x, 1\n", tmp); + tmp &= ~(1 << 6); + WARNING("tmp :%x, 2\n", tmp); + musbfsh_writeb(regs, 0x74, tmp); + tmp = musbfsh_readl(regs, 0x74); + WARNING("tmp :%x, 3\n", tmp); + + int i; + u32 addr[] = {0x60, 0x74, 0x620, 0x630}; + + for (i = 0; i < sizeof(addr) / sizeof(u32); i++) { + WARNING("dbg addr : %x, val : %x\n", + addr[i], musbfsh_readl(regs, addr[i])); + } +#endif + + +#ifndef CONFIG_MTK_ICUSB_SUPPORT + devctl = musbfsh_readb(regs, MUSBFSH_DEVCTL); + power = musbfsh_readb(regs, MUSBFSH_POWER); + WARNING(" musb ready. devctl=0x%x, power=0x%x\n", devctl, power); + mdelay(500); /* wx? */ +#endif + +} + + +static void musbfsh_generic_disable(struct musbfsh *musbfsh) +{ + void __iomem *mregs = musbfsh->mregs; + u16 temp; + + INFO("%s++\r\n", __func__); + /* disable interrupts */ + musbfsh_writeb(mregs, MUSBFSH_INTRUSBE, 0); + musbfsh_writew(mregs, MUSBFSH_INTRTXE, 0); + musbfsh_writew(mregs, MUSBFSH_INTRRXE, 0); + + /* off */ + musbfsh_writeb(mregs, MUSBFSH_DEVCTL, 0); + + /* flush pending interrupts */ + temp = musbfsh_readb(mregs, MUSBFSH_INTRUSB); + temp = musbfsh_readw(mregs, MUSBFSH_INTRTX); + temp = musbfsh_readw(mregs, MUSBFSH_INTRRX); +} + + +/* + * Make the HDRC stop (disable interrupts, etc.); + * reversible by musbfsh_start + * called on gadget driver unregister + * with controller locked, irqs blocked + * acts as a NOP unless some role activated the hardware + */ +void musbfsh_stop(struct musbfsh *musbfsh) +{ + /* stop IRQs, timers, ... */ + musbfsh_platform_disable(musbfsh); + musbfsh_generic_disable(musbfsh); + INFO("HDRC disabled\n"); + + /* FIXME + * - mark host and/or peripheral drivers unusable/inactive + * - disable DMA (and enable it in HdrcStart) + * - make sure we can musbfsh_start() after musbfsh_stop(); with + * OTG mode, gadget driver module rmmod/modprobe cycles that + * - ... + */ + musbfsh_platform_try_idle(musbfsh, 0); +} + +static void musbfsh_shutdown(struct platform_device *pdev) +{ + struct musbfsh *musbfsh = dev_to_musbfsh(&pdev->dev); + unsigned long flags; + + INFO("%s++\r\n", __func__); + spin_lock_irqsave(&musbfsh->lock, flags); + musbfsh_platform_disable(musbfsh); + musbfsh_generic_disable(musbfsh); + musbfsh_set_vbus(musbfsh, 0); + musbfsh_set_power(musbfsh, 0); + spin_unlock_irqrestore(&musbfsh->lock, flags); + + /* FIXME power down */ +} + +/* + * tables defining fifo_mode values. define more if you like. + * for host side, make sure both halves of ep1 are set up. + */ + +/* fits in 4KB */ +#define MAXFIFOSIZE 8096 + +static struct musbfsh_fifo_cfg epx_cfg[] __initdata = { + {.hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, +}; + +static struct musbfsh_fifo_cfg ep0_cfg __initdata = { + .style = FIFO_RXTX, .maxpacket = 64, +}; + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +static struct musbfsh_fifo_cfg ep0_cfg1 = { + .style = FIFO_RXTX, .maxpacket = 64, +}; + +static struct musbfsh_fifo_cfg epx_cfg1[] = { + {.hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, + .mode = BUF_SINGLE + }, + {.hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, + .mode = BUF_SINGLE + }, +}; + +static int fifo_setup1(struct musbfsh *musbfsh, struct musbfsh_hw_ep *hw_ep, + const struct musbfsh_fifo_cfg *cfg, u16 offset) +{ + void __iomem *mbase = musbfsh->mregs; + int size = 0; + u16 maxpacket = cfg->maxpacket; + u16 c_off = offset >> 3; + u8 c_size; /* will be written into the fifo register */ + + INFO("%s++,hw_ep->epnum=%d,cfg->hw_ep_num=%d\r\n", + __func__, hw_ep->epnum, + cfg->hw_ep_num); + /* expect hw_ep has already been zero-initialized */ + + size = ffs(max_t(u16, maxpacket, 8)) - 1; + maxpacket = 1 << size; + + c_size = size - 3; + if (cfg->mode == BUF_DOUBLE) { + if ((offset + (maxpacket << 1)) > MAXFIFOSIZE) + return -EMSGSIZE; + c_size |= MUSBFSH_FIFOSZ_DPB; + } else { + if ((offset + maxpacket) > MAXFIFOSIZE) + return -EMSGSIZE; + } + + /* configure the FIFO */ + musbfsh_writeb(mbase, MUSBFSH_INDEX, hw_ep->epnum); + /* EP0 reserved endpoint for control, bidirectional; + * EP1 reserved for bulk, two unidirection halves. + */ + if (hw_ep->epnum == 1) + musbfsh->bulk_ep = hw_ep; + /* REVISIT error check: be sure ep0 can both rx and tx ... */ + switch (cfg->style) { + case FIFO_TX: + musbfsh_write_txfifosz(mbase, c_size); + musbfsh_write_txfifoadd(mbase, c_off); + hw_ep->tx_double_buffered = !!(c_size & MUSBFSH_FIFOSZ_DPB); + hw_ep->max_packet_sz_tx = maxpacket; + break; + case FIFO_RX: + musbfsh_write_rxfifosz(mbase, c_size); + musbfsh_write_rxfifoadd(mbase, c_off); + hw_ep->rx_double_buffered = !!(c_size & MUSBFSH_FIFOSZ_DPB); + hw_ep->max_packet_sz_rx = maxpacket; + break; + case FIFO_RXTX: + musbfsh_write_txfifosz(mbase, c_size); + musbfsh_write_txfifoadd(mbase, c_off); + hw_ep->rx_double_buffered = !!(c_size & MUSBFSH_FIFOSZ_DPB); + hw_ep->max_packet_sz_rx = maxpacket; + + musbfsh_write_rxfifosz(mbase, c_size); + musbfsh_write_rxfifoadd(mbase, c_off); + hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; + hw_ep->max_packet_sz_tx = maxpacket; + hw_ep->is_shared_fifo = true; + break; + } + + /* NOTE rx and tx endpoint irqs aren't managed separately, + * which happens to be ok + */ + musbfsh->epmask |= (1 << hw_ep->epnum); + + return offset + (maxpacket << ((c_size & MUSBFSH_FIFOSZ_DPB) ? 1 : 0)); +} +#endif +/* + * configure a fifo; for non-shared endpoints, this may be called + * once for a tx fifo and once for an rx fifo. + * + * returns negative errno or offset for next fifo. + */ +static int __init fifo_setup(struct musbfsh *musbfsh, + struct musbfsh_hw_ep *hw_ep, + const struct musbfsh_fifo_cfg *cfg, u16 offset) +{ + void __iomem *mbase = musbfsh->mregs; + int size = 0; + u16 maxpacket = cfg->maxpacket; + u16 c_off = offset >> 3; + u8 c_size; /* will be written into the fifo register */ + + INFO("%s++,hw_ep->epnum=%d,cfg->hw_ep_num=%d\r\n", + __func__, hw_ep->epnum, cfg->hw_ep_num); + + /* expect hw_ep has already been zero-initialized */ + + size = ffs(max_t(u16, maxpacket, 8)) - 1; + maxpacket = 1 << size; + + c_size = size - 3; + if (cfg->mode == BUF_DOUBLE) { + if ((offset + (maxpacket << 1)) > MAXFIFOSIZE) + return -EMSGSIZE; + c_size |= MUSBFSH_FIFOSZ_DPB; + } else { + if ((offset + maxpacket) > MAXFIFOSIZE) + return -EMSGSIZE; + } + + /* configure the FIFO */ + musbfsh_writeb(mbase, MUSBFSH_INDEX, hw_ep->epnum); + /* EP0 reserved endpoint for control, bidirectional; + * EP1 reserved for bulk, two unidirection halves. + */ + if (hw_ep->epnum == 1) + musbfsh->bulk_ep = hw_ep; + /* REVISIT error check: be sure ep0 can both rx and tx ... */ + switch (cfg->style) { + case FIFO_TX: + musbfsh_write_txfifosz(mbase, c_size); + musbfsh_write_txfifoadd(mbase, c_off); + hw_ep->tx_double_buffered = !!(c_size & MUSBFSH_FIFOSZ_DPB); + hw_ep->max_packet_sz_tx = maxpacket; + break; + case FIFO_RX: + musbfsh_write_rxfifosz(mbase, c_size); + musbfsh_write_rxfifoadd(mbase, c_off); + hw_ep->rx_double_buffered = !!(c_size & MUSBFSH_FIFOSZ_DPB); + hw_ep->max_packet_sz_rx = maxpacket; + break; + case FIFO_RXTX: + musbfsh_write_txfifosz(mbase, c_size); + musbfsh_write_txfifoadd(mbase, c_off); + hw_ep->rx_double_buffered = !!(c_size & MUSBFSH_FIFOSZ_DPB); + hw_ep->max_packet_sz_rx = maxpacket; + + musbfsh_write_rxfifosz(mbase, c_size); + musbfsh_write_rxfifoadd(mbase, c_off); + hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; + hw_ep->max_packet_sz_tx = maxpacket; + hw_ep->is_shared_fifo = true; + break; + } + + /* NOTE rx and tx endpoint irqs aren't managed separately, + * which happens to be ok + */ + musbfsh->epmask |= (1 << hw_ep->epnum); + + return offset + (maxpacket << ((c_size & MUSBFSH_FIFOSZ_DPB) ? 1 : 0)); +} + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +static int ep_config_from_table1(struct musbfsh *musbfsh) +{ + const struct musbfsh_fifo_cfg *cfg = NULL; + unsigned i = 0; + unsigned n = 0; + int offset; + struct musbfsh_hw_ep *hw_ep = musbfsh->endpoints; + + INFO("musbfsh: %s++\r\n", __func__); + + /* modification from org */ + musbfsh->config->fifo_cfg = epx_cfg1; + musbfsh->config->fifo_cfg_size = + sizeof(epx_cfg1) / sizeof(struct musbfsh_fifo_cfg); + + if (musbfsh->config->fifo_cfg) { + cfg = musbfsh->config->fifo_cfg; + n = musbfsh->config->fifo_cfg_size; + INFO("musbfsh:fifo_cfg, n=%d\n", n); + goto done; + } + +done: + offset = fifo_setup1(musbfsh, hw_ep, &ep0_cfg1, 0); + /* assert(offset > 0) */ + + /* NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would + * be better than static musbfsh->config->num_eps and DYN_FIFO_SIZE... + */ + + for (i = 0; i < n; i++) { + u8 epn = cfg->hw_ep_num; + + if (epn >= MUSBFSH_C_NUM_EPS) { + ERR("%s: invalid ep %d\n", musbfsh_driver_name, epn); + return -EINVAL; + } + offset = fifo_setup1(musbfsh, hw_ep + epn, cfg++, offset); + if (offset < 0) { + ERR("%s: mem overrun, ep %d\n", + musbfsh_driver_name, epn); + return -EINVAL; + } + + epn++; /* include ep0 */ + musbfsh->nr_endpoints = max(epn, musbfsh->nr_endpoints); + } + INFO("%s: %d/%d max ep, %d/%d memory\n", + musbfsh_driver_name, n + 1, musbfsh->config->num_eps * 2 - 1, + offset, MAXFIFOSIZE); + + if (!musbfsh->bulk_ep) { + ERR("%s: missing bulk\n", musbfsh_driver_name); + return -EINVAL; + } + return 0; +} +#endif + +static int __init ep_config_from_table(struct musbfsh *musbfsh) +{ + const struct musbfsh_fifo_cfg *cfg = NULL; + unsigned i = 0; + unsigned n = 0; + int offset; + struct musbfsh_hw_ep *hw_ep = musbfsh->endpoints; + + INFO("musbfsh: %s: ++\r\n", __func__); + if (musbfsh->config->fifo_cfg) { + cfg = musbfsh->config->fifo_cfg; + n = musbfsh->config->fifo_cfg_size; + INFO("musbfsh:fifo_cfg, n=%d\n", n); + goto done; + } + +done: + offset = fifo_setup(musbfsh, hw_ep, &ep0_cfg, 0); + /* assert(offset > 0) */ + + /* + * NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would + * be better than static musbfsh->config->num_eps and DYN_FIFO_SIZE... + */ + + for (i = 0; i < n; i++) { + u8 epn = cfg->hw_ep_num; + + if (epn >= MUSBFSH_C_NUM_EPS) { + ERR("%s: invalid ep %d\n", musbfsh_driver_name, epn); + return -EINVAL; + } + offset = fifo_setup(musbfsh, hw_ep + epn, cfg++, offset); + if (offset < 0) { + ERR("%s: mem overrun, ep %d\n", + musbfsh_driver_name, epn); + return -EINVAL; + } + + epn++; /* include ep0 */ + musbfsh->nr_endpoints = max(epn, musbfsh->nr_endpoints); + } + INFO("%s: %d/%d max ep, %d/%d memory\n", + musbfsh_driver_name, n + 1, musbfsh->config->num_eps * 2 - 1, + offset, MAXFIFOSIZE); + + if (!musbfsh->bulk_ep) { + ERR("%s: missing bulk\n", musbfsh_driver_name); + return -EINVAL; + } + return 0; +} + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +static int musbfsh_core_init1(struct musbfsh *musbfsh) +{ + void __iomem *mbase = musbfsh->mregs; + int status = 0; + int i; + + INFO("%s\r\n", __func__); + /* configure ep0 */ + musbfsh_configure_ep0(musbfsh); + + /* discover endpoint configuration */ + /* will update in func: ep_config_from_table */ + musbfsh->nr_endpoints = 1; + musbfsh->epmask = 1; + + status = ep_config_from_table1(musbfsh); + if (status < 0) + return status; + + /* finish init, and print endpoint config */ + for (i = 0; i < musbfsh->nr_endpoints; i++) { + struct musbfsh_hw_ep *hw_ep = musbfsh->endpoints + i; + + hw_ep->fifo = MUSBFSH_FIFO_OFFSET(i) + mbase; + hw_ep->regs = MUSBFSH_EP_OFFSET(i, 0) + mbase; + hw_ep->rx_reinit = 1; + hw_ep->tx_reinit = 1; + + if (hw_ep->max_packet_sz_tx) { + INFO("%s: hw_ep %d%s, %smax %d,and hw_ep->epnum=%d\n", + musbfsh_driver_name, i, + hw_ep->is_shared_fifo ? "shared" : "tx", + hw_ep->tx_double_buffered + ? "doublebuffer, " : "", hw_ep->max_packet_sz_tx, + hw_ep->epnum); + } + if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) { + INFO("%s: hw_ep %d%s, %smax %d,and hw_ep->epnum=%d\n", + musbfsh_driver_name, i, + "rx", + hw_ep->rx_double_buffered + ? "doublebuffer, " : "", hw_ep->max_packet_sz_rx, + hw_ep->epnum); + } + if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx)) + INFO("hw_ep %d not configured\n", i); + } + return 0; +} +#endif + + +/* Initialize MUSB (M)HDRC part of the USB hardware subsystem; + * configure endpoints, or take their config from silicon + */ +static int __init musbfsh_core_init(struct musbfsh *musbfsh) +{ + void __iomem *mbase = musbfsh->mregs; + int status = 0; + int i; + + INFO("%s\r\n", __func__); + /* configure ep0 */ + musbfsh_configure_ep0(musbfsh); + + /* discover endpoint configuration */ + /* will update in func: ep_config_from_table */ + musbfsh->nr_endpoints = 1; + musbfsh->epmask = 1; + + status = ep_config_from_table(musbfsh); + if (status < 0) + return status; + + /* finish init, and print endpoint config */ + for (i = 0; i < musbfsh->nr_endpoints; i++) { + struct musbfsh_hw_ep *hw_ep = musbfsh->endpoints + i; + + hw_ep->fifo = MUSBFSH_FIFO_OFFSET(i) + mbase; + hw_ep->regs = MUSBFSH_EP_OFFSET(i, 0) + mbase; + hw_ep->rx_reinit = 1; + hw_ep->tx_reinit = 1; + + if (hw_ep->max_packet_sz_tx) { + INFO("%s: hw_ep %d%s, %smax %d,and hw_ep->epnum=%d\n", + musbfsh_driver_name, i, + hw_ep->is_shared_fifo ? "shared" : "tx", + hw_ep->tx_double_buffered + ? "doublebuffer, " : "", hw_ep->max_packet_sz_tx, + hw_ep->epnum); + } + if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) { + INFO("%s: hw_ep %d%s, %smax %d,and hw_ep->epnum=%d\n", + musbfsh_driver_name, i, + "rx", + hw_ep->rx_double_buffered + ? "doublebuffer, " : "", hw_ep->max_packet_sz_rx, + hw_ep->epnum); + } + if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx)) + INFO("hw_ep %d not configured\n", i); + } + return 0; +} + +void musbfsh_read_clear_generic_interrupt(struct musbfsh *musbfsh) +{ + musbfsh->int_usb = musbfsh_readb(musbfsh->mregs, MUSBFSH_INTRUSB); + musbfsh->int_tx = musbfsh_readw(musbfsh->mregs, MUSBFSH_INTRTX); + musbfsh->int_rx = musbfsh_readw(musbfsh->mregs, MUSBFSH_INTRRX); + musbfsh->int_dma = musbfsh_readb(musbfsh->mregs, MUSBFSH_HSDMA_INTR); + INFO("** musbfsh::IRQ! usb%04x tx%04x rx%04x dma%04x\n", + musbfsh->int_usb, musbfsh->int_tx, musbfsh->int_rx, + musbfsh->int_dma); + /* clear interrupt status */ + musbfsh_writew(musbfsh->mregs, MUSBFSH_INTRTX, musbfsh->int_tx); + musbfsh_writew(musbfsh->mregs, MUSBFSH_INTRRX, musbfsh->int_rx); + musbfsh_writeb(musbfsh->mregs, MUSBFSH_INTRUSB, musbfsh->int_usb); + musbfsh_writeb(musbfsh->mregs, MUSBFSH_HSDMA_INTR, musbfsh->int_dma); +} + +void musbfsh_read_clear_generic_interrupt_tmp(struct musbfsh *musbfsh) +{ + int i = 0; + + while (i++ < 5) { + musbfsh->int_usb = + musbfsh_readb(musbfsh->mregs, MUSBFSH_INTRUSB); + musbfsh->int_tx = + musbfsh_readw(musbfsh->mregs, MUSBFSH_INTRTX); + musbfsh->int_rx = + musbfsh_readw(musbfsh->mregs, MUSBFSH_INTRRX); + musbfsh->int_dma = + musbfsh_readb(musbfsh->mregs, MUSBFSH_HSDMA_INTR); + WARNING("** musbfsh::IRQ! usb%04x tx%04x rx%04x dma%04x\n", + musbfsh->int_usb, musbfsh->int_tx, musbfsh->int_rx, + musbfsh->int_dma); + /* clear interrupt status */ + musbfsh_writew(musbfsh->mregs, MUSBFSH_INTRTX, musbfsh->int_tx); + musbfsh_writew(musbfsh->mregs, MUSBFSH_INTRRX, musbfsh->int_rx); + musbfsh_writeb(musbfsh->mregs, + MUSBFSH_INTRUSB, musbfsh->int_usb); + musbfsh_writeb(musbfsh->mregs, + MUSBFSH_HSDMA_INTR, musbfsh->int_dma); + } +} + +static irqreturn_t generic_interrupt(int irq, void *__hci) +{ + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + struct musbfsh *musbfsh = __hci; + u16 int_level1 = 0; + + INFO("musbfsh:generic_interrupt++\r\n"); +#ifdef CONFIG_MTK_ICUSB_SUPPORT +#if 0 + if (mt65xx_check_usb11_clk_status()) { + dump_stack(); + BUG(); + } +#endif +#endif + spin_lock_irqsave(&musbfsh->lock, flags); + + musbfsh_read_clear_generic_interrupt(musbfsh); + int_level1 = musbfsh_readw(musbfsh->mregs, USB11_L1INTS); + INFO("Level 1 Interrupt Status 0x%x\n", int_level1); + + if (musbfsh->int_usb || musbfsh->int_tx || musbfsh->int_rx) + retval = musbfsh_interrupt(musbfsh); + if (musbfsh->int_dma) + retval = musbfsh_dma_controller_irq(irq, + musbfsh->musbfsh_dma_controller); + + spin_unlock_irqrestore(&musbfsh->lock, flags); + return retval; +} + +/* + * handle all the irqs defined by the HDRC core. for now we expect: other + * irq sources (phy, dma, etc) will be handled first, musbfsh->int_* values + * will be assigned, and the irq will already have been acked. + * + * called in irq context with spinlock held, irqs blocked + */ +irqreturn_t musbfsh_interrupt(struct musbfsh *musbfsh) +{ + irqreturn_t retval = IRQ_NONE; + u8 devctl, power; + int ep_num; + u32 reg; + + devctl = musbfsh_readb(musbfsh->mregs, MUSBFSH_DEVCTL); + power = musbfsh_readb(musbfsh->mregs, MUSBFSH_POWER); + + INFO("** musbfsh::devctl 0x%x power 0x%x\n", devctl, power); + + /* the core can interrupt us for multiple reasons; docs have + * a generic interrupt flowchart to follow + */ + if (musbfsh->int_usb) { + retval |= musbfsh_stage0_irq(musbfsh, musbfsh->int_usb, + devctl, power); + } + + /* "stage 1" is handling endpoint irqs */ + + /* handle endpoint 0 first */ + if (musbfsh->int_tx & 1) + retval |= musbfsh_h_ep0_irq(musbfsh); + + /* RX on endpoints 1-15 */ + reg = musbfsh->int_rx >> 1; + ep_num = 1; + while (reg) { + if (reg & 1) { + /* musbfsh_ep_select(musbfsh->mregs, ep_num); */ + /* REVISIT just retval = ep->rx_irq(...) */ + retval = IRQ_HANDLED; + /* the real ep_num */ + musbfsh_host_rx(musbfsh, ep_num); + } + + reg >>= 1; + ep_num++; + } + + /* TX on endpoints 1-15 */ + reg = musbfsh->int_tx >> 1; + ep_num = 1; + while (reg) { + if (reg & 1) { + /* musbfsh_ep_select(musbfsh->mregs, ep_num); */ + /* REVISIT just retval |= ep->tx_irq(...) */ + retval = IRQ_HANDLED; + musbfsh_host_tx(musbfsh, ep_num); + } + reg >>= 1; + ep_num++; + } + return retval; +} + +#ifndef CONFIG_MUSBFSH_PIO_ONLY +static bool use_dma __initdata = 1; + +/* "modprobe ... use_dma=0" etc */ +module_param(use_dma, bool, 0); +MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); + +#else +#define use_dma 0 +#endif + +void musbfsh_dma_completion(struct musbfsh *musbfsh, u8 epnum, u8 transmit) +{ + INFO("%s++\r\n", __func__); + /* called with controller lock already held */ + + /* endpoints 1..15 */ + if (transmit) + musbfsh_host_tx(musbfsh, epnum); + else + musbfsh_host_rx(musbfsh, epnum); +} + +/* + * Init support + */ + +static struct musbfsh *__init alloc_instance(struct device *dev, + struct musbfsh_hdrc_config *config, + void __iomem *mbase) +{ + struct musbfsh *musbfsh; + struct musbfsh_hw_ep *ep; + int epnum; + struct usb_hcd *hcd; + + INFO("%s++\r\n", __func__); + hcd = usb_create_hcd(&musbfsh_hc_driver, dev, dev_name(dev)); + if (!hcd) + return NULL; + /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ + + musbfsh = hcd_to_musbfsh(hcd); + INIT_LIST_HEAD(&musbfsh->control); + INIT_LIST_HEAD(&musbfsh->in_bulk); + INIT_LIST_HEAD(&musbfsh->out_bulk); + + hcd->uses_new_polling = 1; + hcd->has_tt = 1; + + musbfsh->vbuserr_retry = VBUSERR_RETRY_COUNT; + + musbfsh->mregs = mbase; + musbfsh->ctrl_base = mbase; + /* will be update after return from this func */ + musbfsh->nIrq = -ENODEV; + musbfsh->config = config; + BUG_ON(musbfsh->config->num_eps > MUSBFSH_C_NUM_EPS); + for (epnum = 0, ep = musbfsh->endpoints; + epnum < musbfsh->config->num_eps; epnum++, ep++) { + ep->musbfsh = musbfsh; + ep->epnum = epnum; + } + + musbfsh->controller = dev; + return musbfsh; +} + +static void musbfsh_free(struct musbfsh *musbfsh) +{ + /* this has multiple entry modes. it handles fault cleanup after + * probe(), where things may be partially set up, as well as rmmod + * cleanup after everything's been de-activated. + */ + INFO("%s++\r\n", __func__); + if (musbfsh->nIrq >= 0) { + if (musbfsh->irq_wake) + disable_irq_wake(musbfsh->nIrq); + free_irq(musbfsh->nIrq, musbfsh); + } + if (is_dma_capable() && musbfsh->dma_controller) { + struct dma_controller *c = musbfsh->dma_controller; + + (void)c->stop(c); + musbfsh_dma_controller_destroy(c); + } + usb_put_hcd(musbfsh_to_hcd(musbfsh)); + kfree(musbfsh); +} + +/* + * Perform generic per-controller initialization. + * + * @pDevice: the controller (already clocked, etc) + * @nIrq: irq + * @mregs: virtual address of controller registers, + * not yet corrected for platform-specific offsets + */ +static int __init musbfsh_init_controller(struct device *dev, + int nIrq, void __iomem *ctrl, + void __iomem *pbase) +{ + int status; + struct musbfsh *musbfsh; + struct musbfsh_hdrc_platform_data *plat = dev->platform_data; + struct usb_hcd *hcd; + +#if 0 + struct musbfsh_hdrc_config *config; + struct device_node *np = dev->of_node; +#endif + + WARNING("%s++\r\n", __func__); + /* The driver might handle more features than the board; OK. + * Fail when the board needs a feature that's not enabled. + */ + +#if 0 + plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL); + if (!plat) + goto fail0; + + config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL); + if (!config) + goto fail0; + + of_property_read_u32(np, "mode", (u32 *) &plat->mode); + + /* __deprecated */ + /* of_property_read_u32(np, "dma_channels", + (u32 *)&config->dma_channels); */ + of_property_read_u32(np, "num_eps", (u32 *) &config->num_eps); + config->multipoint = of_property_read_bool(np, "multipoint"); + /* __deprecated */ + /* config->dyn_fifo = of_property_read_bool(np, "dyn_fifo"); */ + /* __deprecated */ + /* config->soft_con = of_property_read_bool(np, "soft_con"); */ + /* config->dma = of_property_read_bool(np, "dma"); //__deprecated */ + + plat->config = config; + +#endif + + dev->platform_data = plat; + if (!plat) { + dev_dbg(dev, "no platform_data?\n"); + status = -ENODEV; + goto fail0; + } + + /* allocate */ + musbfsh = alloc_instance(dev, plat->config, ctrl); + if (!musbfsh) { + status = -ENOMEM; + goto fail0; + } + spin_lock_init(&musbfsh->lock); + musbfsh->phy_base = pbase; + musbfsh->board_mode = plat->mode; + musbfsh->config->fifo_cfg = epx_cfg; + musbfsh->config->fifo_cfg_size = + sizeof(epx_cfg) / sizeof(struct musbfsh_fifo_cfg); + /* + * The musbfsh_platform_init() call: + * - adjusts musbfsh->mregs and musbfsh->isr if needed, + * - may initialize an integrated tranceiver + * - initializes musbfsh->xceiv, usually by otg_get_transceiver() + * - activates clocks. + * - stops powering VBUS + * - assigns musbfsh->board_set_vbus if host mode is enabled + * + * There are various transceiver configurations. Blackfin, + * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses + * external/discrete ones in various flavors (twl4030 family, + * isp1504, non-OTG, etc) mostly hooking up through ULPI. + */ + musbfsh->isr = generic_interrupt; + status = musbfsh_platform_init(musbfsh); + if (status < 0) { + ERR("musbfsh_platform_init fail!status=%d", status); + goto fail1; + } + + if (!musbfsh->isr) { + status = -ENODEV; + goto fail2; + } +#ifndef CONFIG_MUSBFSH_PIO_ONLY + INFO("DMA mode\n"); + if (use_dma && dev->dma_mask) { + struct dma_controller *c; + + /* only software config */ + c = musbfsh_dma_controller_create(musbfsh, musbfsh->mregs); + musbfsh->dma_controller = c; + if (c) + (void)c->start(c); /* do nothing in fact */ + } +#else + INFO("PIO mode\n"); +#endif + + /* ideally this would be abstracted in platform setup */ + if (!is_dma_capable() || !musbfsh->dma_controller) + dev->dma_mask = NULL; + + /* be sure interrupts are disabled before connecting ISR */ + /* wz, need implement in MT65xx, but not power off! */ + musbfsh_platform_disable(musbfsh); + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + if (skip_mac_init_attr.value) { + MYDBG("skip musbfsh_generic_disable(), musbfsh_core_init()\n"); + } else { + /* must power on the USB module */ + musbfsh_generic_disable(musbfsh); + + /* setup musb parts of the core (especially endpoints) */ + status = musbfsh_core_init(musbfsh); + if (status < 0) { + ERR("musbfsh_core_init fail!"); + goto fail2; + } + } +#else + /* must power on the USB module */ + musbfsh_generic_disable(musbfsh); + + /* setup musb parts of the core (especially endpoints) */ + status = musbfsh_core_init(musbfsh); + if (status < 0) { + ERR("musbfsh_core_init fail!"); + goto fail2; + } +#endif + + /* attach to the IRQ */ + /* + * wx? usb_add_hcd will also try do request_irq, + * if hcd_driver.irq is set + */ + if (request_irq(nIrq, musbfsh->isr, IRQF_TRIGGER_LOW, + dev_name(dev), musbfsh)) { + dev_err(dev, "musbfsh::request_irq %d failed!\n", nIrq); + status = -ENODEV; + goto fail2; + } + + /* update the musbfsh->nIrq after request_irq ! */ + musbfsh->nIrq = nIrq; + + /* FIXME this handles wakeup irqs wrong */ + /* wx, need to be replaced by modifying kernel/core/mt6573_ost.c */ + if (enable_irq_wake(nIrq) == 0) { + musbfsh->irq_wake = 1; + /* wx? usb_add_hcd will do this any way */ + device_init_wakeup(dev, 1); + } else { + musbfsh->irq_wake = 0; + } + + /* host side needs more setup */ + hcd = musbfsh_to_hcd(musbfsh); + /* plat->power can be set to 0,so the power is set to 500ma. */ + hcd->power_budget = 2 * (plat->power ? plat->power : 250); + + /* + * For the host-only role, we can activate right away. + * (We expect the ID pin to be forcibly grounded!!) + * Otherwise, wait till the gadget driver hooks up. + */ + /* Important!! */ + status = usb_add_hcd(musbfsh_to_hcd(musbfsh), -1, 0); + + if (status < 0) { + ERR("musbfsh::usb_add_hcd fail!"); + goto fail2; + } + + dev_info(dev, "USB controller at %p using %s, IRQ %d\n", + ctrl, (is_dma_capable() && musbfsh->dma_controller) + ? "DMA" : "PIO", musbfsh->nIrq); + +#if defined(MTK_ICUSB_BABBLE_RECOVER) || defined(MTK_SMARTBOOK_SUPPORT) + init_timer(&babble_recover_timer); + babble_recover_timer.function = babble_recover_func; + babble_recover_timer.data = (unsigned long)musbfsh; +#endif + + g_musbfsh = musbfsh; +#ifdef CONFIG_MUSBFSH_DEBUG_FS + status = musbfsh_init_debugfs(musbfsh); + if (status < 0) + goto fail2; + create_musbfsh_cmd_proc_entry(); +#endif + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + set_usb_phy_voltage(VOL_50); + mt65xx_usb11_phy_savecurrent(); + mt65xx_usb11_disable_clk_pll_pw(); + create_ic_usb_cmd_proc_entry(); + +#ifdef MTK_ICUSB_TAKE_WAKE_LOCK + wake_lock(&musbfsh_suspend_lock); +#else + MYDBG("skip wake_lock(&musbfsh_suspend_lock)\n"); +#endif + + MYDBG("end of %s(), build time : %s\n", __func__, __TIME__); + +#endif +#ifdef MTK_DT_USB_SUPPORT + get_eint_ext_usb_wkup_irq(); + + /* temporialy for DSDA bring up */ + if (musbfsh_wake_lock_hold) { + wake_lock(&musbfsh_suspend_lock); + MYDBG("force wake_lock(&musbfsh_suspend_lock)\n"); + } + create_dsda_tmp_entry(); +#endif + + + return 0; + + +fail2: + if (musbfsh->irq_wake) + device_init_wakeup(dev, 0); + musbfsh_platform_exit(musbfsh); + +fail1: + dev_err(musbfsh->controller, "%s: failed with status %d\n", + __func__, status); + musbfsh_free(musbfsh); + +fail0: + dev_err(dev, "failed to initialize musb\n"); + return status; + +} + +/*-------------------------------------------------------------------------*/ + +/* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just + * bridge to a platform device; this driver then suffices. + */ + +#ifndef CONFIG_MUSBFSH_PIO_ONLY +static u64 *orig_dma_mask; +#endif + +#ifndef CONFIG_MTK_CLKMGR +struct clk *musb_clk11; +struct clk *musb_clk30; +#endif + +static int __init musbfsh_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int status; + int irq; + unsigned char __iomem *base; + unsigned char __iomem *pbase; + struct device_node *node = NULL; + + INFO("%s++\r\n", __func__); + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + /* test usb clk effect */ + /* ic_usb_clk_chg(); */ +#endif + +#ifndef CONFIG_MUSBFSH_PIO_ONLY /* using DMA */ + /* clobbered by use_dma=n */ +#ifdef CONFIG_OF + dev->dma_mask = &usb11_dmamask; + dev->coherent_dma_mask = usb11_dmamask; +#endif + orig_dma_mask = dev->dma_mask; + +#endif + +#ifdef CONFIG_OF + node = of_find_compatible_node(NULL, NULL, "mediatek,icusb"); + + if (node == NULL) { + pr_info("USB get node failed\n"); + return -1; + } + base = of_iomap(node, 0); + irq = irq_of_parse_and_map(node, 0); + pbase = of_iomap(node, 1); +#else + irq = MT_USB1_IRQ_ID; + base = (unsigned char __iomem *)USB11_BASE; + pbase = (unsigned char __iomem *)USB11_PHY_ADDR; +#endif + /* + * after init the controller, + * the USB should already be powered on! + */ + status = musbfsh_init_controller(dev, irq, base, pbase); + if (status < 0) + ERR("musbfsh_probe failed with status %d\n", status); + INFO("%s--\r\n", __func__); +#if 0 /* IC_USB from SS5 */ +#ifdef IC_USB + device_create_file(dev, &dev_attr_start); + WARNING("IC-USB is enabled\n"); +#endif +#endif + return status; +} + +static int __exit musbfsh_remove(struct platform_device *pdev) +{ + struct musbfsh *musbfsh = dev_to_musbfsh(&pdev->dev); + void __iomem *ctrl_base = musbfsh->ctrl_base; + + INFO("%s++\r\n", __func__); + /* this gets called on rmmod. + * - Host mode: host may still be active + * - Peripheral mode: peripheral is deactivated (or never-activated) + * - OTG mode: both roles are deactivated (or never-activated) + */ +#ifdef CONFIG_MUSBFSH_DEBUG_FS + musbfsh_exit_debugfs(musbfsh); +#endif + musbfsh_shutdown(pdev); + if (musbfsh->board_mode == MUSBFSH_HOST) + usb_remove_hcd(musbfsh_to_hcd(musbfsh)); + musbfsh_writeb(musbfsh->mregs, MUSBFSH_DEVCTL, 0); + musbfsh_platform_exit(musbfsh); + musbfsh_writeb(musbfsh->mregs, MUSBFSH_DEVCTL, 0); + + musbfsh_free(musbfsh); + iounmap(ctrl_base); + device_init_wakeup(&pdev->dev, 0); +#ifndef CONFIG_MUSBFSH_PIO_ONLY + pdev->dev.dma_mask = orig_dma_mask; +#endif + return 0; +} + +#ifdef CONFIG_PM + +static void musbfsh_save_context(struct musbfsh *musbfsh) +{ + int i; + void __iomem *musbfsh_base = musbfsh->mregs; + void __iomem *epio; + + musbfsh->context.power = musbfsh_readb(musbfsh_base, MUSBFSH_POWER); + musbfsh->context.intrtxe = musbfsh_readw(musbfsh_base, MUSBFSH_INTRTXE); + musbfsh->context.intrrxe = musbfsh_readw(musbfsh_base, MUSBFSH_INTRRXE); + musbfsh->context.intrusbe = + musbfsh_readb(musbfsh_base, MUSBFSH_INTRUSBE); + musbfsh->context.index = musbfsh_readb(musbfsh_base, MUSBFSH_INDEX); + musbfsh->context.devctl = musbfsh_readb(musbfsh_base, MUSBFSH_DEVCTL); + + musbfsh->context.l1_int = musbfsh_readl(musbfsh_base, USB11_L1INTM); + + for (i = 0; i < MUSBFSH_C_NUM_EPS - 1; ++i) { + struct musbfsh_hw_ep *hw_ep; + + hw_ep = &musbfsh->endpoints[i]; + if (!hw_ep) + continue; + + epio = hw_ep->regs; + if (!epio) + continue; + + musbfsh_writeb(musbfsh_base, MUSBFSH_INDEX, i); + musbfsh->context.index_regs[i].txmaxp = + musbfsh_readw(epio, MUSBFSH_TXMAXP); + musbfsh->context.index_regs[i].txcsr = + musbfsh_readw(epio, MUSBFSH_TXCSR); + musbfsh->context.index_regs[i].rxmaxp = + musbfsh_readw(epio, MUSBFSH_RXMAXP); + musbfsh->context.index_regs[i].rxcsr = + musbfsh_readw(epio, MUSBFSH_RXCSR); + + if (musbfsh->dyn_fifo) { + musbfsh->context.index_regs[i].txfifoadd = + musbfsh_read_txfifoadd(musbfsh_base); + musbfsh->context.index_regs[i].rxfifoadd = + musbfsh_read_rxfifoadd(musbfsh_base); + musbfsh->context.index_regs[i].txfifosz = + musbfsh_read_txfifosz(musbfsh_base); + musbfsh->context.index_regs[i].rxfifosz = + musbfsh_read_rxfifosz(musbfsh_base); + } + } +} + +static void musbfsh_write_dynfifo_size(struct musbfsh *musbfsh, int i) +{ + void __iomem *musbfsh_base = musbfsh->mregs; + + musbfsh_write_txfifosz(musbfsh_base, + musbfsh->context.index_regs[i].txfifosz); + musbfsh_write_rxfifosz(musbfsh_base, + musbfsh->context.index_regs[i].rxfifosz); + musbfsh_write_txfifoadd(musbfsh_base, + musbfsh->context.index_regs[i].txfifoadd); + musbfsh_write_rxfifoadd(musbfsh_base, + musbfsh->context.index_regs[i].rxfifoadd); +} + +static void musbfsh_restore_context(struct musbfsh *musbfsh) +{ + int i; + void __iomem *musbfsh_base = musbfsh->mregs; + void __iomem *epio; + + musbfsh_writeb(musbfsh_base, MUSBFSH_POWER, musbfsh->context.power); + musbfsh_writew(musbfsh_base, MUSBFSH_INTRTXE, musbfsh->context.intrtxe); + musbfsh_writew(musbfsh_base, MUSBFSH_INTRRXE, musbfsh->context.intrrxe); + musbfsh_writeb(musbfsh_base, MUSBFSH_INTRUSBE, + musbfsh->context.intrusbe); + musbfsh_writeb(musbfsh_base, MUSBFSH_DEVCTL, musbfsh->context.devctl); + + for (i = 0; i < MUSBFSH_C_NUM_EPS - 1; ++i) { + struct musbfsh_hw_ep *hw_ep; + + hw_ep = &musbfsh->endpoints[i]; + if (!hw_ep) + continue; + + epio = hw_ep->regs; + if (!epio) + continue; + + musbfsh_writeb(musbfsh_base, MUSBFSH_INDEX, i); + musbfsh_writew(epio, MUSBFSH_TXMAXP, + musbfsh->context.index_regs[i].txmaxp); + musbfsh_writew(epio, MUSBFSH_TXCSR, + musbfsh->context.index_regs[i].txcsr); + musbfsh_writew(epio, MUSBFSH_RXMAXP, + musbfsh->context.index_regs[i].rxmaxp); + musbfsh_writew(epio, MUSBFSH_RXCSR, + musbfsh->context.index_regs[i].rxcsr); + + if (musbfsh->dyn_fifo) + musbfsh_write_dynfifo_size(musbfsh, i); + } + + musbfsh_writeb(musbfsh_base, MUSBFSH_INDEX, musbfsh->context.index); + mb(); /* need to sync registers for later DMA transfer */ + /* + * Enable all interrupts at DMA + * Caution: The DMA Reg type is WRITE to SET or CLEAR + */ + musbfsh_writel(musbfsh->mregs, MUSBFSH_HSDMA_INTR, + 0xFF | (0xFF << MUSBFSH_DMA_INTR_UNMASK_SET_OFFSET)); + /* mb(); */ + musbfsh_writel(musbfsh_base, USB11_L1INTM, musbfsh->context.l1_int); +} + + + +static int musbfsh_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + /* unsigned long flags; */ + struct musbfsh *musbfsh = dev_to_musbfsh(&pdev->dev); + + MYDBG(""); + /* MYDBG("cpuid:%d\n", smp_processor_id()); */ + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + if (!usb11_enabled) { + MYDBG("usb11 is not enabled"); + return 0; + } +#endif + + /* spin_lock_irqsave(&musbfsh->lock, flags); */ +#ifndef CONFIG_MTK_ICUSB_SUPPORT + musbfsh_set_vbus(musbfsh, 0); /* disable VBUS */ +#endif + +#ifdef CONFIG_SMP + /* + * wx, clearn IRQ before closing clock. + * Prevent SMP issue: clock is disabled on CPU1, + * but ISR is running on CPU0 and failed to clear interrupt + */ + disable_irq(musbfsh->nIrq); + musbfsh_save_context(musbfsh); + musbfsh_read_clear_generic_interrupt(musbfsh); + /* musbfsh_read_clear_generic_interrupt_tmp(musbfsh); */ +#endif + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + /* mt65xx_usb11_mac_phy_dump(); */ + mt65xx_usb11_phy_savecurrent(); + mt65xx_usb11_disable_clk_pll_pw(); + suspend_cnt++; +#else + musbfsh_set_power(musbfsh, 0); +#endif + /* spin_unlock_irqrestore(&musbfsh->lock, flags); */ + return 0; +} + +static int musbfsh_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + /* unsigned long flags; */ + struct musbfsh *musbfsh = dev_to_musbfsh(&pdev->dev); + + MYDBG(""); + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + MYDBG("suspend_cnt : %d, resume_cnt :%d\n", suspend_cnt, resume_cnt); + if (!usb11_enabled) { + MYDBG("usb11 is not enabled"); + return 0; + } +#endif + /* spin_lock_irqsave(&musbfsh->lock, flags); */ +#ifdef CONFIG_MTK_ICUSB_SUPPORT + resume_cnt++; + mt65xx_usb11_enable_clk_pll_pw(); + mt65xx_usb11_phy_recover(); + /* mt65xx_usb11_mac_phy_dump(); */ +#else + musbfsh_set_vbus(musbfsh, 1); /* enable VBUS */ + musbfsh_set_power(musbfsh, 1); +#endif + +#ifdef CONFIG_SMP + musbfsh_restore_context(musbfsh); + enable_irq(musbfsh->nIrq); +#endif + /* spin_unlock_irqrestore(&musbfsh->lock, flags); */ + return 0; +} + +static const struct dev_pm_ops musbfsh_dev_pm_ops = { + .suspend = musbfsh_suspend, + .resume = musbfsh_resume, +}; + +#define MUSBFSH_DEV_PM_OPS (&musbfsh_dev_pm_ops) +#else +#define MUSBFSH_DEV_PM_OPS NULL +#endif + +static struct platform_driver musbfsh_driver = { + .driver = { + .name = "musbfsh", + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .pm = MUSBFSH_DEV_PM_OPS, + }, + .probe = musbfsh_probe, + .remove = __exit_p(musbfsh_remove), + .shutdown = musbfsh_shutdown, +}; + +static struct musbfsh_hdrc_config musbfsh_config_mt65xx = { + .multipoint = false, + .dyn_fifo = true, + .soft_con = true, + .dma = true, + .num_eps = 6, + .dma_channels = 4, +}; + +static struct musbfsh_hdrc_platform_data usb_data_mt65xx = { + .mode = 1, + .config = &musbfsh_config_mt65xx, +}; + + +static struct platform_device mt_usb11_dev = { + .name = "musbfsh", + .id = -1, + .dev = { + .platform_data = &usb_data_mt65xx, + .dma_mask = &usb11_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .release = musbfsh_hcd_release, + }, +}; + +static int __init musbfsh_dts_probe(struct platform_device *pdev) +{ + int retval; + + musb_clk11 = devm_clk_get(&pdev->dev, "USB11-CLOCK"); + musb_clk30 = devm_clk_get(&pdev->dev, "SSUSB-CLOCK"); + + if (IS_ERR(musb_clk11)) { + dev_err(&pdev->dev, "USB11 cannot get musb clock\n"); + } else { + dev_err(&pdev->dev, "USB11 get musb clock ok, prepare it\n"); + if (clk_prepare(musb_clk11) == 0) + dev_err(&pdev->dev, "musb11 clock prepare done\n"); + else + dev_err(&pdev->dev, "musb11 clock prepare fail\n"); + } + + if (IS_ERR(musb_clk30)) { + dev_err(&pdev->dev, "USB30 cannot get musb clock\n"); + } else { + dev_err(&pdev->dev, "USB30 get musb clock ok, prepare it\n"); + + if (clk_prepare(musb_clk30) == 0) + dev_err(&pdev->dev, "musb30 clock prepare done\n"); + else + dev_err(&pdev->dev, "musb30 clock prepare fail\n"); + } + + retval = platform_device_register(&mt_usb11_dev); + if (retval != 0) + ERR("musbfsh_dts_probe failed with status %d\n", retval); + return retval; +} + +static int __init musbfsh_init(void) +{ + int retval; + + if (usb_disabled()) /* based on the config variable. */ + return 0; + WARNING("MUSBFSH is enabled\n"); + wake_lock_init(&musbfsh_suspend_lock, WAKE_LOCK_SUSPEND, "usb11 host"); + + retval = platform_driver_register(&musbfsh_driver); + if (retval != 0) { + ERR("musbfsh_init with status %d\n", retval); + return retval; + } + + retval = platform_driver_register(&musbfsh_dts_driver); + if (retval != 0) { + ERR("musbfsh_init with status %d\n", retval); + platform_driver_unregister(&musbfsh_driver); + return retval; + } + return 0; + +} + +/* + * make us init after usbcore and i2c (transceivers, regulators, etc) + * and before usb gadget and host-side drivers start to register + */ +module_init(musbfsh_init); + +static void __exit musbfsh_cleanup(void) +{ + wake_lock_destroy(&musbfsh_suspend_lock); + platform_driver_unregister(&musbfsh_driver); + platform_driver_unregister(&musbfsh_dts_driver); +} +module_exit(musbfsh_cleanup); + +int musbfsh_debug = 0; +module_param(musbfsh_debug, int, 0644); +#ifdef MTK_DT_USB_SUPPORT +module_param(musbfsh_eint_cnt, int, 0644); +module_param(musbfsh_skip_phy, int, 0644); +module_param(musbfsh_skip_clk, int, 0644); +module_param(musbfsh_wake_lock_hold, int, 0644); +module_param(musbfsh_skip_port_suspend, int, 0644); +module_param(musbfsh_skip_port_resume, int, 0644); +#endif + +#else + +static void usb11_phy_savecurrent(unsigned char __iomem *pbase) +{ + /* + * 4 1. swtich to USB function. + * (system register, force ip into usb mode.) + */ + USB11PHY_CLR8(pbase + 0x96b, 0x04); + USB11PHY_CLR8(pbase + 0x96e, 0x01); + USB11PHY_CLR8(pbase + 0x921, 0x2); + USB11PHY_CLR8(pbase + 0x921, 0x1); + + /* RG_SUSPENDM=1; */ + USB11PHY_SET8(pbase + 0x968, 0x08); + /* 4 2. release force suspendm. */ + USB11PHY_SET8(pbase + 0x96a, 0x04); + /* 4 3. RG_DPPULLDOWN./RG_DMPULLDOWN. */ + USB11PHY_SET8(pbase + 0x968, 0xc0); + /* 4 4. RG_XCVRSEL[1:0] =2'b01. */ + USB11PHY_CLR8(pbase + 0x968, 0x30); + USB11PHY_SET8(pbase + 0x968, 0x10); + /* 4 5. RG_TERMSEL = 1'b1 */ + USB11PHY_SET8(pbase + 0x968, 0x04); + /* 4 6. RG_DATAIN[3:0]=4'b0000 */ + USB11PHY_CLR8(pbase + 0x969, 0x3c); + /* + * 4 7. force_dp_pulldown, force_dm_pulldown, + * force_xcversel, force_termsel. + */ + USB11PHY_SET8(pbase + 0x96a, 0xba); + + /* 4 8.RG_USB20_BC11_SW_EN 1'b0 */ + USB11PHY_CLR8(pbase + 0x91a, 0x80); + /* 4 9.RG_USB20_OTG_VBUSSCMP_EN 1'b0 */ + USB11PHY_CLR8(pbase + 0x91a, 0x10); + /* 4 10. delay 800us. */ + udelay(800); + /* 4 11. rg_usb20_pll_stable = 1 */ + USB11PHY_SET8(pbase + 0x963, 0x02); + + udelay(1); + + USB11PHY_CLR8(pbase + 0x96C, 0x2C); + USB11PHY_SET8(pbase + 0x96C, 0x10); + USB11PHY_CLR8(pbase + 0x96D, 0x3C); + + /* RG_SUSPENDM=0; */ + USB11PHY_CLR8(pbase + 0x968, 0x08); + + /* 4 13. wait 1us */ + udelay(1); +} + + +static int __init musbfsh_dts_probe(struct platform_device *pdev) +{ + unsigned char __iomem *pbase; + +#ifdef CONFIG_OF + if (pdev->dev.of_node == NULL) { + pr_info("USB get node failed\n"); + return -1; + } + pbase = of_iomap(pdev->dev.of_node, 1); + musb_clk11 = devm_clk_get(&pdev->dev, "USB11-CLOCK"); + if (IS_ERR(musb_clk11)) { + dev_err(&pdev->dev, "USB11 cannot get musb clock\n"); + } else { + dev_err(&pdev->dev, "USB11 get musb clock ok, prepare it\n"); + if (clk_prepare(musb_clk11) == 0) + dev_err(&pdev->dev, "musb11 clock prepare done\n"); + else + dev_err(&pdev->dev, "musb11 clock prepare fail\n"); + } +#else + pbase = (unsigned char __iomem *)USB11_PHY_ADDR; +#endif +/* enable_clock (MT_CG_INFRA_USB, "USB11"); */ +/* enable_clock (MT_CG_INFRA_ICUSB, "USB11"); */ +/* enable_clock (MT_CG_INFRA_USB_MCU, "USB11"); */ + clk_enable(musb_clk11); + usb11_phy_savecurrent(pbase); +/* disable_clock (MT_CG_INFRA_USB_MCU, "USB11"); */ +/* disable_clock (MT_CG_INFRA_ICUSB, "USB11"); */ +/* disable_clock (MT_CG_INFRA_USB, "USB11"); */ + clk_disable(musb_clk11); + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static int __init musbfsh_init(void) +{ + pr_info("MUSBFSH DUMMY Driver is enabled\n"); + return platform_driver_register(&musbfsh_dts_driver); +} + +/* make us init after usbcore and i2c (transceivers, regulators, etc) + * and before usb gadget and host-side drivers start to register + */ +module_init(musbfsh_init); + +static void __exit musbfsh_cleanup(void) +{ + platform_driver_unregister(&musbfsh_dts_driver); +} +module_exit(musbfsh_cleanup); + +#endif diff --git a/drivers/misc/mediatek/usb11/mt6755/musbfsh_core.h b/drivers/misc/mediatek/usb11/mt6755/musbfsh_core.h new file mode 100644 index 0000000000000000000000000000000000000000..d049cf7bc1a4a2a4834b3bfd365de9ac8f8ff7cb --- /dev/null +++ b/drivers/misc/mediatek/usb11/mt6755/musbfsh_core.h @@ -0,0 +1,340 @@ +/* + * MUSB OTG driver defines + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * Copyright 2015 Mediatek Inc. + * Marvin Lin + * Arvin Wang + * Vincent Fan + * Bryant Lu + * Yu-Chang Wang + * Macpaul Lin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __MUSBFSH_CORE_H__ +#define __MUSBFSH_CORE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct musbfsh; +struct musbfsh_hw_ep; +struct musbfsh_ep; + +#define MYDBG(fmt, args...) pr_warn("MTK_ICUSB [DBG], <%s(), %d> " fmt, \ + __func__, __LINE__, ## args) + +/* Helper defines for struct musbfsh->hwvers */ +#define MUSBFSH_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) +#define MUSBFSH_HWVERS_MINOR(x) (x & 0x3ff) +#define MUSBFSH_HWVERS_RC 0x8000 +#define MUSBFSH_HWVERS_1300 0x52C +#define MUSBFSH_HWVERS_1400 0x590 +#define MUSBFSH_HWVERS_1800 0x720 +#define MUSBFSH_HWVERS_1900 0x784 +#define MUSBFSH_HWVERS_2000 0x800 + +#include "musbfsh.h" +#include "musbfsh_io.h" +#include "musbfsh_regs.h" +#include "musbfsh_debug.h" + +/* HOST ROLE */ + +#define is_host_capable() (1) + +extern irqreturn_t musbfsh_h_ep0_irq(struct musbfsh *); +extern void musbfsh_host_tx(struct musbfsh *, u8); +extern void musbfsh_host_rx(struct musbfsh *, u8); +/* + * void musbfsh_dma_completion(struct musbfsh *musbfsh, u8 epnum, u8 transmit); + */ + +/* CONSTANTS */ + +#ifndef MUSBFSH_C_NUM_EPS +#define MUSBFSH_C_NUM_EPS ((u8)16) +#endif + +#ifndef MUSBFSH_MAX_END0_PACKET +#define MUSBFSH_MAX_END0_PACKET ((u16)MUSBFSH_EP0_FIFOSIZE) +#endif + +/* host side ep0 states */ +enum musbfsh_h_ep0_state { + MUSBFSH_EP0_IDLE, + MUSBFSH_EP0_START, /* expect ack of setup */ + MUSBFSH_EP0_IN, /* expect IN DATA */ + MUSBFSH_EP0_OUT, /* expect ack of OUT DATA */ + MUSBFSH_EP0_STATUS, /* expect ack of STATUS */ +} __packed; + +/* REGISTER ACCESS */ + +/* "indexed" mapping: INDEX register controls register bank select */ +#define musbfsh_ep_select(_mbase, _epnum) \ + musbfsh_writeb((_mbase), MUSBFSH_INDEX, (_epnum)) +#define MUSBFSH_EP_OFFSET MUSBFSH_INDEXED_OFFSET + +/* FUNCTIONS */ + +#define test_devctl_hst_mode(_x) \ + (musbfsh_readb((_x)->mregs, MUSBFSH_DEVCTL)&MUSBFSH_DEVCTL_HM) + +/* TYPES */ + +/* + * struct musbfsh_hw_ep - endpoint hardware (bidirectional) + * + * Ordered slightly for better cacheline locality. + */ +struct musbfsh_hw_ep { + struct musbfsh *musbfsh; + void __iomem *fifo; + void __iomem *regs; + /* index in musbfsh->endpoints[] */ + u8 epnum; + /* hardware configuration, possibly dynamic */ + bool is_shared_fifo; + bool tx_double_buffered; + bool rx_double_buffered; + u16 max_packet_sz_tx; + u16 max_packet_sz_rx; + struct dma_channel *tx_channel; + struct dma_channel *rx_channel; + void __iomem *target_regs; + /* currently scheduled peripheral endpoint */ + struct musbfsh_qh *in_qh; + struct musbfsh_qh *out_qh; + u8 rx_reinit; + u8 tx_reinit; +}; + +struct musbfsh_csr_regs { + /* FIFO registers */ + u16 txmaxp, txcsr, rxmaxp, rxcsr; + u16 rxfifoadd, txfifoadd; + u8 txtype, txinterval, rxtype, rxinterval; + u8 rxfifosz, txfifosz; + u8 txfunaddr, txhubaddr, txhubport; + u8 rxfunaddr, rxhubaddr, rxhubport; +}; + +struct musbfsh_context_registers { + + u8 power; + u16 intrtxe, intrrxe; + u8 intrusbe; + u16 frame; + u8 index, testmode; + + u8 devctl, busctl, misc; + u32 otg_interfsel; + u32 l1_int; + + struct musbfsh_csr_regs index_regs[MUSBFSH_C_NUM_EPS]; +}; + +/* + * struct musb - Driver instance data. + */ +struct musbfsh { + /* device lock */ + spinlock_t lock; + struct musbfsh_context_registers context; + irqreturn_t (*isr)(int, void *); + +/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ +#define MUSBFSH_PORT_STAT_RESUME (1 << 31) + + u32 port1_status; + + unsigned long rh_timer; + enum musbfsh_h_ep0_state ep0_stage; + + /* bulk traffic normally dedicates endpoint hardware, and each + * direction has its own ring of host side endpoints. + * we try to progress the transfer at the head of each endpoint's + * queue until it completes or NAKs too much; then we try the next + * endpoint. + */ + struct musbfsh_hw_ep *bulk_ep; + struct list_head control; /* of musbfsh_qh */ + struct list_head in_bulk; /* of musbfsh_qh */ + struct list_head out_bulk; /* of musbfsh_qh */ + + /* called with IRQs blocked; ON/nonzero implies starting a session, + * and waiting at least a_wait_vrise_tmout. + */ + void (*board_set_vbus)(struct musbfsh *, int is_on); + + struct dma_controller *dma_controller; + struct musbfsh_dma_controller *musbfsh_dma_controller; + + struct device *controller; + void __iomem *ctrl_base; + void __iomem *phy_base; + void __iomem *mregs; + + /* passed down from chip/board specific irq handlers */ + u8 int_usb; + u16 int_rx; + u16 int_tx; + u8 int_dma; + + int nIrq; + unsigned irq_wake:1; + + struct musbfsh_hw_ep endpoints[MUSBFSH_C_NUM_EPS]; +#define control_ep endpoints + +#define VBUSERR_RETRY_COUNT 3 + u16 vbuserr_retry; + u16 epmask; + u8 nr_endpoints; + + u8 board_mode; /* enum musbfsh_mode */ + int (*board_set_power)(int state); + bool is_host; + unsigned is_multipoint:1; + + unsigned long idle_timeout; /* Next timeout in jiffies */ + + /* active means connected and not suspended */ + unsigned is_active:1; + unsigned ignore_disconnect:1; /* during bus resets */ + unsigned dyn_fifo:1; /* dynamic FIFO supported? */ + + struct musbfsh_hdrc_config *config; +}; + +static inline void musbfsh_set_vbus(struct musbfsh *musbfsh, int is_on) +{ + INFO("musbfsh_set_vbus++, is_on=%d\r\n", is_on); + if (musbfsh->board_set_vbus) + musbfsh->board_set_vbus(musbfsh, is_on); +} + +static inline void musbfsh_set_power(struct musbfsh *musbfsh, int is_on) +{ + INFO("musbfsh_set_power++, is_on=%d\r\n", is_on); + if (musbfsh->board_set_power) + musbfsh->board_set_power(is_on); +} + +static inline void musbfsh_configure_ep0(struct musbfsh *musbfsh) +{ + musbfsh->endpoints[0].max_packet_sz_tx = MUSBFSH_EP0_FIFOSIZE; + musbfsh->endpoints[0].max_packet_sz_rx = MUSBFSH_EP0_FIFOSIZE; + musbfsh->endpoints[0].is_shared_fifo = true; +} + +/* Glue it together */ + +extern const char musbfsh_driver_name[]; + +extern void musbfsh_start(struct musbfsh *musbfsh); +extern void musbfsh_stop(struct musbfsh *musbfsh); + +extern void musbfsh_write_fifo(struct musbfsh_hw_ep *ep, u16 len, + const u8 *src); +extern void musbfsh_read_fifo(struct musbfsh_hw_ep *ep, u16 len, u8 *dst); + +extern void musbfsh_load_testpacket(struct musbfsh *); + +extern irqreturn_t musbfsh_interrupt(struct musbfsh *); + +extern void musbfsh_platform_enable(struct musbfsh *musbfsh); +extern void musbfsh_platform_disable(struct musbfsh *musbfsh); + +#define musbfsh_platform_try_idle(x, y) do {} while (0) + +#define musbfsh_platform_get_vbus_status(x) 0 + +extern int __init musbfsh_platform_init(struct musbfsh *musbfsh); +extern int musbfsh_platform_exit(struct musbfsh *musbfsh); + +#define CONFIG_MUSBFSH_DEBUG_FS +#ifdef CONFIG_MUSBFSH_DEBUG_FS +int musbfsh_init_debugfs(struct musbfsh *musb); +void musbfsh_exit_debugfs(struct musbfsh *musb); +void create_musbfsh_cmd_proc_entry(void); +#else +static inline int musbfsh_init_debugfs(struct musbfsh *musbfsh) +{ + return 0; +} + +static inline void musbfsh_exit_debugfs(struct musbfsh *musbfsh) +{ +} + +static inline void create_musbfsh_cmd_proc_entry(void) +{ +} +#endif /* CONFIG_MUSBFSH_DEBUG_FS */ + +#ifdef MTK_DT_USB_SUPPORT +#include +#include +#include +#include + +void create_dsda_tmp_entry(void); + +int musbfsh_skip_phy = 1; +int musbfsh_skip_clk = 0; +int musbfsh_eint_cnt = 0; +int musbfsh_skip_port_suspend = 0; +int musbfsh_skip_port_resume = 0; +int musbfsh_wake_lock_hold = 0; +#endif + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +#include "musbfsh_icusb.h" +extern void musbfsh_init_phy_by_voltage(enum PHY_VOLTAGE_TYPE); +extern void musbfsh_open_vsim_power(int on); +extern void musbfsh_open_vsim_power1(int on); +extern void musbfsh_start_session(void); +#endif + +#ifdef CONFIG_MTK_USBFSH +extern irqreturn_t musbfsh_dma_controller_irq(int irq, void *private_data); +#endif + +#endif /* __MUSBFSH_CORE_H__ */ diff --git a/drivers/misc/mediatek/usb11/mt6755/musbfsh_debugfs.c b/drivers/misc/mediatek/usb11/mt6755/musbfsh_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..3fa63be7c66adb7d6304c4f18101138a32ddd760 --- /dev/null +++ b/drivers/misc/mediatek/usb11/mt6755/musbfsh_debugfs.c @@ -0,0 +1,420 @@ +/* + * MUSB OTG driver debugfs support + * + * Copyright 2010 Nokia Corporation + * Contact: Felipe Balbi + * + * Copyright 2015 Mediatek Inc. + * Marvin Lin + * Arvin Wang + * Vincent Fan + * Bryant Lu + * Yu-Chang Wang + * Macpaul Lin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include +#include +#include + +#include + +#include "musbfsh_core.h" +#include "musbfsh_host.h" + +#ifdef CONFIG_MUSBFSH_DEBUG_FS +#include +#include "usb.h" + +struct musbfsh_register_map { + char *name; + unsigned offset; + unsigned size; +}; + +static const struct musbfsh_register_map musbfsh_regmap[] = { + {"FAddr", 0x00, 8}, + {"Power", 0x01, 8}, + {"Frame", 0x0c, 16}, + {"Index", 0x0e, 8}, + {"Testmode", 0x0f, 8}, + {"TxMaxPp", 0x10, 16}, + {"TxCSRp", 0x12, 16}, + {"RxMaxPp", 0x14, 16}, + {"RxCSR", 0x16, 16}, + {"RxCount", 0x18, 16}, + {"ConfigData", 0x1f, 8}, + {"DevCtl", 0x60, 8}, + {"MISC", 0x61, 8}, + {"TxFIFOsz", 0x62, 8}, + {"RxFIFOsz", 0x63, 8}, + {"TxFIFOadd", 0x64, 16}, + {"RxFIFOadd", 0x66, 16}, + {"VControl", 0x68, 32}, + {"HWVers", 0x6C, 16}, + {"EPInfo", 0x78, 8}, + {"RAMInfo", 0x79, 8}, + {"LinkInfo", 0x7A, 8}, + {"VPLen", 0x7B, 8}, + {"HS_EOF1", 0x7C, 8}, + {"FS_EOF1", 0x7D, 8}, + {"LS_EOF1", 0x7E, 8}, + {"SOFT_RST", 0x7F, 8}, + {"DMA_CNTLch0", 0x204, 16}, + {"DMA_ADDRch0", 0x208, 32}, + {"DMA_COUNTch0", 0x20C, 32}, + {"DMA_CNTLch1", 0x214, 16}, + {"DMA_ADDRch1", 0x218, 32}, + {"DMA_COUNTch1", 0x21C, 32}, + {"DMA_CNTLch2", 0x224, 16}, + {"DMA_ADDRch2", 0x228, 32}, + {"DMA_COUNTch2", 0x22C, 32}, + {"DMA_CNTLch3", 0x234, 16}, + {"DMA_ADDRch3", 0x238, 32}, + {"DMA_COUNTch3", 0x23C, 32}, + {"DMA_CNTLch4", 0x244, 16}, + {"DMA_ADDRch4", 0x248, 32}, + {"DMA_COUNTch4", 0x24C, 32}, + {"DMA_CNTLch5", 0x254, 16}, + {"DMA_ADDRch5", 0x258, 32}, + {"DMA_COUNTch5", 0x25C, 32}, + {"DMA_CNTLch6", 0x264, 16}, + {"DMA_ADDRch6", 0x268, 32}, + {"DMA_COUNTch6", 0x26C, 32}, + {"DMA_CNTLch7", 0x274, 16}, + {"DMA_ADDRch7", 0x278, 32}, + {"DMA_COUNTch7", 0x27C, 32}, + {"DBG_PRB0", 0x620, 32}, + {} /* Terminating Entry */ +}; + +static const struct musbfsh_register_map musbfsh_phyregmap[] = { + {"USBPHYACR0", 0x00, 32}, + {"USBPHYACR1", 0x04, 32}, + {"USBPHYACR2", 0x08, 32}, + {"USBPHYACR4", 0x10, 32}, + {"USBPHYACR5", 0x14, 32}, + {"USBPHYACR6", 0x18, 32}, + {"U2PHYACR3", 0x1c, 32}, + {"U2PHYACR4", 0x20, 32}, + {"U2PHYAMON0", 0x24, 32}, + {"U2PHYDCR0", 0x60, 32}, + {"U2PHYDCR1", 0x64, 32}, + {"U2PHYDTM0", 0x68, 32}, + {"U2PHYDTM1", 0x6c, 32}, + {"U2PHYDMON0", 0x70, 32}, + {"U2PHYDMON1", 0x74, 32}, + {"U2PHYDMON2", 0x78, 32}, + {"U2PHYDMON3", 0x7c, 32}, + {"REGFCOM", 0xfc, 32}, + {} /* Terminating Entry */ +}; + +static struct dentry *musbfsh_debugfs_root; + +static int musbfsh_regdump_show(struct seq_file *s, void *unused) +{ + struct musbfsh *musbfsh = s->private; + unsigned i; + + seq_puts(s, "MUSBFSH (M)HDRC Register Dump\n"); + + for (i = 0; i < ARRAY_SIZE(musbfsh_regmap); i++) { + switch (musbfsh_regmap[i].size) { + case 8: + seq_printf(s, "%-12s: %02x\n", musbfsh_regmap[i].name, + musbfsh_readb(musbfsh->mregs, + musbfsh_regmap[i].offset)); + break; + case 16: + seq_printf(s, "%-12s: %04x\n", musbfsh_regmap[i].name, + musbfsh_readw(musbfsh->mregs, + musbfsh_regmap[i].offset)); + break; + case 32: + seq_printf(s, "%-12s: %08x\n", musbfsh_regmap[i].name, + musbfsh_readl(musbfsh->mregs, + musbfsh_regmap[i].offset)); + break; + } + } + + return 0; +} + + +static int musbfsh_phyregdump_show(struct seq_file *s, void *unused) +{ + struct musbfsh *musbfsh = s->private; + unsigned i; + + seq_puts(s, "MUSBFSH (M)HDRC PhyRegister Dump\n"); + + for (i = 0; i < ARRAY_SIZE(musbfsh_phyregmap); i++) { + switch (musbfsh_phyregmap[i].size) { + case 8: + seq_printf(s, "%-12s: %02x\n", + musbfsh_phyregmap[i].name, + musbfsh_readb(musbfsh->phy_base + 0x900, + musbfsh_phyregmap[i].offset)); + break; + case 16: + seq_printf(s, "%-12s: %04x\n", + musbfsh_phyregmap[i].name, + musbfsh_readw(musbfsh->phy_base + 0x900, + musbfsh_phyregmap[i].offset)); + break; + case 32: + seq_printf(s, "%-12s: %08x\n", + musbfsh_phyregmap[i].name, + musbfsh_readl(musbfsh->phy_base + 0x900, + musbfsh_phyregmap[i].offset)); + break; + } + } + + return 0; +} + + +static int musbfsh_regdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, musbfsh_regdump_show, inode->i_private); +} + +static int musbfsh_phyregdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, musbfsh_phyregdump_show, inode->i_private); +} + +static int musbfsh_test_mode_show(struct seq_file *s, void *unused) +{ + struct musbfsh *musbfsh = s->private; + unsigned test; + + test = musbfsh_readb(musbfsh->mregs, MUSBFSH_TESTMODE); + + if (test & MUSBFSH_TEST_FORCE_HOST) + seq_puts(s, "force host\n"); + + if (test & MUSBFSH_TEST_FIFO_ACCESS) + seq_puts(s, "fifo access\n"); + + if (test & MUSBFSH_TEST_FORCE_FS) + seq_puts(s, "force full-speed\n"); + + if (test & MUSBFSH_TEST_FORCE_HS) + seq_puts(s, "force high-speed\n"); + + if (test & MUSBFSH_TEST_PACKET) + seq_puts(s, "test packet\n"); + + if (test & MUSBFSH_TEST_K) + seq_puts(s, "test K\n"); + + if (test & MUSBFSH_TEST_J) + seq_puts(s, "test J\n"); + + if (test & MUSBFSH_TEST_SE0_NAK) + seq_puts(s, "test SE0 NAK\n"); + + return 0; +} + +static const struct file_operations musbfsh_regdump_fops = { + .open = musbfsh_regdump_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations musbfsh_phyregdump_fops = { + .open = musbfsh_phyregdump_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int musbfsh_test_mode_open(struct inode *inode, struct file *file) +{ + return single_open(file, musbfsh_test_mode_show, inode->i_private); +} + +static ssize_t musbfsh_test_mode_write(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct musbfsh *musbfsh = s->private; + u8 test = 0; + char buf[18]; + + memset(buf, 0x00, sizeof(buf)); + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "force host", 9)) + test = MUSBFSH_TEST_FORCE_HOST; + + if (!strncmp(buf, "fifo access", 11)) + test = MUSBFSH_TEST_FIFO_ACCESS; + + if (!strncmp(buf, "force full-speed", 15)) + test = MUSBFSH_TEST_FORCE_FS; + + if (!strncmp(buf, "force high-speed", 15)) + test = MUSBFSH_TEST_FORCE_HS; + + if (!strncmp(buf, "test packet", 10)) { + test = MUSBFSH_TEST_PACKET; + musbfsh_load_testpacket(musbfsh); + } + + if (!strncmp(buf, "test K", 6)) + test = MUSBFSH_TEST_K; + + if (!strncmp(buf, "test J", 6)) + test = MUSBFSH_TEST_J; + + if (!strncmp(buf, "test SE0 NAK", 12)) + test = MUSBFSH_TEST_SE0_NAK; + + musbfsh_writeb(musbfsh->mregs, MUSBFSH_TESTMODE, test); + + return count; +} + + +ssize_t musbfsh_musbfsh_cmd_proc_entry(struct file *file_ptr, + const char __user *user_buffer, + size_t count, loff_t *position) +{ + char cmd; + + if (copy_from_user(&cmd, user_buffer, 1)) + return 0; + + switch (cmd) { +#ifdef CONFIG_MTK_ICUSB_SUPPORT + case 'k': /* enable vsim power */ + musbfsh_open_vsim_power(1); + musbfsh_init_phy_by_voltage(VOL_33); + musbfsh_start_session(); + break; + case 'p': /* enable vsim power */ + musbfsh_open_vsim_power1(1); + musbfsh_init_phy_by_voltage(VOL_33); + musbfsh_start_session(); + break; +#endif + default: + MYDBG("Command unsupported.\n"); + break; + } + + return count; +} + + +static const struct file_operations musbfsh_ic_usb_cmd_proc_fops = { + .write = musbfsh_musbfsh_cmd_proc_entry +}; + +void create_musbfsh_cmd_proc_entry(void) +{ + struct proc_dir_entry *prEntry; + + MYDBG(""); + prEntry = proc_create("MUSBFSH_CMD_ENTRY", 0660, 0, + &musbfsh_ic_usb_cmd_proc_fops); + if (prEntry) + MYDBG("add /proc/MUSBFSH_CMD_ENTRY ok\n"); + else + MYDBG("add /proc/MUSBFSH_CMD_ENTRY fail\n"); +} + + +static const struct file_operations musbfsh_test_mode_fops = { + .open = musbfsh_test_mode_open, + .write = musbfsh_test_mode_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int musbfsh_init_debugfs(struct musbfsh *musbfsh) +{ + struct dentry *root; + struct dentry *file; + int ret; + + root = debugfs_create_dir("musbfsh", NULL); + if (!root) { + ret = -ENOMEM; + goto err0; + } + + file = debugfs_create_file("regdump", S_IRUGO, root, musbfsh, + &musbfsh_regdump_fops); + if (!file) { + ret = -ENOMEM; + goto err1; + } + + file = debugfs_create_file("regdumpphy", S_IRUGO, root, musbfsh, + &musbfsh_phyregdump_fops); + if (!file) { + ret = -ENOMEM; + goto err1; + } + + file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, + root, musbfsh, &musbfsh_test_mode_fops); + if (!file) { + ret = -ENOMEM; + goto err1; + } + + musbfsh_debugfs_root = root; + + return 0; + +err1: + debugfs_remove_recursive(root); + +err0: + return ret; +} + +void /* __init_or_exit */ musbfsh_exit_debugfs(struct musbfsh *musbfsh) +{ + debugfs_remove_recursive(musbfsh_debugfs_root); +} + +#endif diff --git a/drivers/misc/mediatek/usb11/mt6755/musbfsh_mt65xx.c b/drivers/misc/mediatek/usb11/mt6755/musbfsh_mt65xx.c new file mode 100644 index 0000000000000000000000000000000000000000..94336425f2515f14410e8a1dea84452ad23905d0 --- /dev/null +++ b/drivers/misc/mediatek/usb11/mt6755/musbfsh_mt65xx.c @@ -0,0 +1,1343 @@ +/* + * Driver for Special USB-PHY of MUSB HOST peripheral + * + * The power sequence and programming bits were different from SoC. + * Please use the coorsponding USB-PHY API for your SoC. + * This driver includes Mediatek MUSB DT/ICUSB support. + * + * Copyright 2015 Mediatek Inc. + * Marvin Lin + * Arvin Wang + * Vincent Fan + * Bryant Lu + * Yu-Chang Wang + * Macpaul Lin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "musbfsh_core.h" +#include "musbfsh_mt65xx.h" +#include "mach/emi_mpu.h" +#include + +#include "musbfsh_host.h" +#include "usb.h" +#include +#include +#include + +#define FRA (48) +#define PARA (25) + +bool musbfsh_power = false; + +#ifdef MTK_DT_USB_SUPPORT +void usb_p1_switch_to_modem(void) +{ +#ifdef GPIO_EXT_USB_SW2 + mt_set_gpio_mode(GPIO_EXT_USB_SW2, GPIO_MODE_GPIO); + mt_set_gpio_dir(GPIO_EXT_USB_SW2, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_EXT_USB_SW2, GPIO_OUT_ONE); +#endif +} +#endif + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +enum PHY_VOLTAGE_TYPE g_phy_voltage = VOL_50; + +int common_regs_16[] = {0x00, 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0B, + 0x0C, 0x0E, 0x0F}; +int version_regs_16[] = {0x60, 0x61, 0x62, 0x63, 0x64, 0x66, 0x6C, 0x6E}; +int hwconfig_regs_16[] = {0x70, 0x72, 0x74, 0x78, 0x79, 0x7A, 0x7B, 0x7C, + 0x7D, 0x7E, 0x7F}; +int toggle_regs_32[] = {0x80, 0x84}; +int level1_regs_32[] = {0xA0, 0xA4, 0xA8, 0xAC}; +int epcsr_regs_16_1[] = {0x102, 0x108, 0x10B, 0x10F}; +int epcsr_regs_16_2[] = {0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10B, 0x10C, + 0x10D, 0x10F}; +int dma_regs_32_1[] = {0x200, 0x210, 0x220}; +int dma_regs_32_2[] = {0x204, 0x208, 0x20C, 0x280, 0x284}; +int hhub_regs_32[] = {0x480, 0x482, 0x484, 0x486}; + +int debug_regs_32[] = { + 0x600, 0x604, 0x605, 0x606, 0x610, 0x612, 0x614, 0x616, + 0x620, 0x622, 0x624, 0x626, 0x628, 0x62A, + 0x62B, 0x62D, 0x630, 0x632, 0x634, 0x636, 0x640, 0x684, 0x688, 0x690, + 0x700 +}; +int phy_regs_32[] = { + 0x00, 0x04, 0x08, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x60, 0x64, 0x68, 0x6c, + 0x70, 0x74, 0x78, 0x7c, 0xfc +}; +int phy_regs_32_port0[] = {0x00, 0x04, 0x08, 0x18}; + +void mt65xx_usb11_mac_phy_dump(void) +{ +#if 0 + struct musbfsh *musbfsh = g_musbfsh; + int i = 0; + int j = 0; + + MYDBG(""); + WARNING("MAC register dump!\n"); + pr_debug("common register region:\n"); + for (i = 0; i < sizeof(common_regs_16) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", common_regs_16[i], + musbfsh_readw(musbfsh->mregs, common_regs_16[i])); + } + + pr_debug("OTG/D FIFO/Version registers region:\n"); + for (i = 0; i < sizeof(version_regs_16) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", version_regs_16[i], + musbfsh_readw(musbfsh->mregs, version_regs_16[i])); + } + pr_debug("HW configuration registers region:\n"); + for (i = 0; i < sizeof(hwconfig_regs_16) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", hwconfig_regs_16[i], + musbfsh_readw(musbfsh->mregs, hwconfig_regs_16[i])); + } + + pr_debug("Toggle registers region:\n"); + for (i = 0; i < sizeof(toggle_regs_32) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", toggle_regs_32[i], + musbfsh_readl(musbfsh->mregs, toggle_regs_32[i])); + } + + pr_debug("Level1 registers region:\n"); + for (i = 0; i < sizeof(level1_regs_32) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", level1_regs_32[i], + musbfsh_readl(musbfsh->mregs, level1_regs_32[i])); + } + + pr_debug("EP CSR registers region:\n"); + for (i = 0; i < sizeof(epcsr_regs_16_1) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", epcsr_regs_16_1[i], + musbfsh_readw(musbfsh->mregs, epcsr_regs_16_1[i])); + } + + for (i = 0; i <= sizeof(epcsr_regs_16_2) / sizeof(int); i++) { + for (j = 1; j <= 5; j++) { + pr_debug("offset=%x, value=%x\n", + epcsr_regs_16_2[i] + j * 0x10, + musbfsh_readw(musbfsh->mregs, + epcsr_regs_16_2[i] + j * 0x10)); + } + } + + pr_debug("DMA registers region:\n"); + for (i = 0; i < sizeof(dma_regs_32_1) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", dma_regs_32_1[i], + musbfsh_readl(musbfsh->mregs, dma_regs_32_1[i])); + } + for (i = 0; i <= sizeof(dma_regs_32_2) / sizeof(int); i++) { + for (j = 0; j < 4; j++) { + pr_debug("offset=%x, value=%x\n", + dma_regs_32_2[i] + j * 0x10, + musbfsh_readl(musbfsh->mregs, + dma_regs_32_2[i] + j * 0x10)); + } + } + + pr_debug("Rx count registers region:\n"); + for (i = 1; i <= 5; i++) { + pr_debug("offset=%x, value=%x\n", 0x300 + i * 4, + musbfsh_readl(musbfsh->mregs, 0x300 + i * 4)); + } + pr_debug("Debug registers region:\n"); + for (i = 0; i < sizeof(debug_regs_32) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", debug_regs_32[i], + musbfsh_readl(musbfsh->mregs, debug_regs_32[i])); + } + + WARNING("PHY register dump!\n"); + pr_debug("PHY registers region:\n"); + for (i = 0; i < sizeof(phy_regs_32) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", phy_regs_32[i], + __raw_readl(USB11_PHY_ADDR + phy_regs_32[i])); + } + + WARNING("PHY register dump PORT0!\n"); + pr_debug("PHY registers region PORT0:\n"); + for (i = 0; i < sizeof(phy_regs_32_port0) / sizeof(int); i++) { + pr_debug("offset=%x, value=%x\n", phy_regs_32_port0[i], + __raw_readl(USB_SIF_BASE + 0x800 + + phy_regs_32_port0[i])); + } + MYDBG(""); +#endif +} + +void mt65xx_usb11_mac_reset_and_phy_stress_set(void) +{ + struct timeval tv_begin, tv_end; + + do_gettimeofday(&tv_begin); + MYDBG(""); +#if 0 + musbfsh_root_disc_procedure(); + mdelay(2000); /* wait disc procedure done */ +#else + MYDBG("skip musbfsh_root_disc_procedure()\n"); +#endif + + reset_usb11_phy_power_negotiation_status(); + + /* mt65xx_usb11_mac_phy_dump(); */ + +#if 1 + USB11PHY_SET8(0x69, 0x40); + mdelay(100); + USB11PHY_CLR8(0x69, 0x40); + mdelay(100); +#else + MYDBG("skip mac reset bit for testing\n"); +#endif + + /* clear 3.3V bias off ==> 3.3V */ + USB11PHY_CLR8(0x15, 0x04); + set_usb_phy_voltage(VOL_50); + mt65xx_usb11_phy_savecurrent(); /* usb normal save current */ + + mdelay(2); + + /* mt65xx_usb11_mac_phy_dump(); */ + + do_gettimeofday(&tv_end); + MYDBG("time spent, sec : %d, usec : %d\n", + (unsigned int)(tv_end.tv_sec - tv_begin.tv_sec), + (unsigned int)(tv_end.tv_usec - tv_begin.tv_usec)); +} + +void mt65xx_usb11_mac_phy_babble_clear(struct musbfsh *musbfsh) +{ + USB11PHY_SET8(0x6D, force_usb11_avalid | force_usb11_bvalid | + force_usb11_sessend | force_usb11_vbusvalid); + + USB11PHY_CLR8(0x6C, RG_USB11_AVALID | RG_USB11_BVALID | + RG_USB11_VBUSVALID); + USB11PHY_SET8(0x6C, RG_USB11_SESSEND); +} + +void mt65xx_usb11_mac_phy_babble_recover(struct musbfsh *musbfsh) +{ + USB11PHY_SET8(0x6D, force_usb11_avalid | force_usb11_bvalid | + force_usb11_sessend | force_usb11_vbusvalid); + + USB11PHY_CLR8(0x6C, RG_USB11_SESSEND); + USB11PHY_SET8(0x6C, RG_USB11_AVALID | RG_USB11_BVALID | + RG_USB11_VBUSVALID); +} + + +int mt65xx_check_usb11_clk_status(void) +{ + int status = __raw_readl((void __iomem *)0xf0003018); + + if (status & (0x1 << 11)) + /* MYDBG("status : %x, usb11 clk off\n", status); */ + return 1; + + /* MYDBG("status : %x, usb11 clk on\n", status); */ + return 0; +} + +void usb11_phy_set_test(void) +{ + char result; + + MYDBG(""); + + result = USB11PHY_READ8(0x12); + MYDBG("result : %x\n", result); + + /* RG_USB20_ICUSB_EN, b0 */ + USB11PHY_CLR8(0x12, 0x01); + + result = USB11PHY_READ8(0x12); + MYDBG("result : %x\n", result); + + /* RG_USB20_ICUSB_EN, b1 */ + USB11PHY_SET8(0x12, 0x01); + + result = USB11PHY_READ8(0x12); + MYDBG("result : %x\n", result); +} + +enum PHY_VOLTAGE_TYPE get_usb11_phy_voltage(void) +{ + MYDBG(""); + dump_stack(); + return g_phy_voltage; +} + +void set_usb_phy_voltage(enum PHY_VOLTAGE_TYPE phy_volt) +{ + MYDBG(""); + g_phy_voltage = phy_volt; +} + +void mt65xx_usb11_disable_clk_pll_pw(void) +{ + MYDBG(""); +#if 0 + MYDBG("skip---\n"); +#else + /* + * disable MAC before PHY to avoid funny interrupts like VBUS_ERR, + * if UPLL is occupied by port0 + */ + mt65xx_usb11_clock_enable(false); + +#endif + + musbfsh_power = false; +} + +void mt65xx_usb11_enable_clk_pll_pw(void) +{ + MYDBG(""); +#if 0 + MYDBG("skip---\n"); +#else + udelay(300); + + /* + * disable MAC before PHY to avoid funny interrupts like VBUS_ERR, + * if UPLL is occupied by port0 + */ + mt65xx_usb11_clock_enable(true); +#endif + + musbfsh_power = true; +} + +void mt65xx_usb11_phy_poweron_common(int icusb, int bias_off) +{ + MYDBG("icusb : %d, bias_off : %d\n", icusb, bias_off); + + + /* special for 95 phy */ + USB11PHY_CLR8(0x6c, 0x02); /* RG_IDDIG = 0 */ + USB11PHY_SET8(0x6d, 0x02); /* force_iddig = 1 */ + + /* set smae value with 40nm, RG_USB20_DISCD */ +#if 0 + USB11PHY_SET8(0x16, 0x20); +#endif + + /* switch to USB function. (system register, force ip into usb mode. */ + USB11PHY_CLR8(0x6b, 0x04); + USB11PHY_CLR8(0x6e, 0x01); + USB11PHY_CLR8(0x21, 0x2); + USB11PHY_CLR8(0x21, 0x1); + + /* clear force suspendm. */ + USB11PHY_CLR8(0x6a, 0x04); + + /* RG_DPPULLDOWN = 1'b0 */ + USB11PHY_CLR8(0x68, 0x40); + /* RG_DMPULLDOWN = 1'b0 */ + USB11PHY_CLR8(0x68, 0x80); + /* RG_XCVRSEL = 2'b00 */ + USB11PHY_CLR8(0x68, 0x30); + /* RG_TERMSEL = 1'b0 */ + USB11PHY_CLR8(0x68, 0x04); + /* RG_DATAIN[3:0] = 4'b0000 */ + USB11PHY_CLR8(0x69, 0x3c); + + /* force_dp_pulldown = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x10); + /* force_dm_pulldown = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x20); + /* force_xcversel = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x08); + /* force_termsel = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x02); + /* force_datain = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x80); + + /* RG_USB20_BC11_SW_EN, b0 */ + USB11PHY_CLR8(0x1a, 0x80); + + /* RG_USB20_INTR_E, b1 */ + USB11PHY_SET8(0x00, 0x20); + + /* RG_SUSPENDM, b1 */ + USB11PHY_SET8(0x68, 0x08); + + /* set force suspendm. */ + USB11PHY_SET8(0x6a, 0x04); + + mdelay(2); + + if (icusb) { + MYDBG(""); + /* RG_USB20_ICUSB_EN, b1 */ + USB11PHY_SET8(0x12, 0x01); + + if (bias_off) { + MYDBG(""); + /* set 3.3V bias off ==> 1.8V */ + USB11PHY_SET8(0x15, 0x04); + } else { + MYDBG(""); + /* clear 3.3V bias off ==> 3.3V */ + USB11PHY_CLR8(0x15, 0x04); + } + } + /* RG_USB20_OTG_VBUSSCMP_EN 1'b1 */ + USB11PHY_SET8(0x1a, 0x10); + /* from ROM code set up */ + /* RG_SET */ + USB11PHY_SET8(0x6C, 0x2C); + USB11PHY_CLR8(0x6C, 0x10); + /* force setting */ + USB11PHY_SET8(0x6D, 0x3C); + + udelay(800); + if (!icusb) { + MYDBG(""); + usb11_hs_slew_rate_cal(); + } + + mdelay(2); + + /* release force suspendm. */ + USB11PHY_CLR8(0x6a, 0x04); + /* mt65xx_usb11_mac_phy_dump(); */ + + + if (skip_mac_init_attr.value) { + MYDBG("perform musbfsh_mac_init()\n"); + musbfsh_mac_init(); + } else { + MYDBG("not perform musbfsh_mac_init()\n"); + } + + /* mt65xx_usb11_mac_phy_dump(); */ +} + + +void mt65xx_usb11_phy_savecurrent_common(int icusb, int bias_off) +{ + MYDBG("icusb : %d, bias_off : %d\n", icusb, bias_off); + if (icusb) { + /* + * Switch to USB function. + * (system register) + * force ip into usb mode. + */ + USB11PHY_CLR8(0x6b, 0x04); + USB11PHY_CLR8(0x6e, 0x01); + USB11PHY_CLR8(0x21, 0x2); + USB11PHY_CLR8(0x21, 0x1); + + /* release force suspendm. */ + USB11PHY_CLR8(0x6a, 0x04); + + /* RG_USB20_BC11_SW_EN, b0 */ + USB11PHY_CLR8(0x1a, 0x80); + + /* RG_USB20_ICUSB_EN, b0 */ + USB11PHY_CLR8(0x12, 0x01); + + if (bias_off) { + /* + * set 3.3V bias off + * RG_USB20_GBIAS_ENB ==> 3.3V bias OFF + */ + USB11PHY_SET8(0x15, 0x04); + } else { + /* + * set 3.3V bias off + * RG_USB20_GBIAS_ENB ==> 3.3V bias ON + */ + USB11PHY_CLR8(0x15, 0x04); + } + + /* force suspendm = 1. */ + USB11PHY_SET8(0x6a, 0x04); + + /* wait 2ms */ + mdelay(2); + } else { /* from mt65xx_usb11_phy_savecurrent() */ + MYDBG(""); + + /* + * 4 1. + * Swtich to USB function. (system register) + * force ip into usb mode. + */ + USB11PHY_CLR8(0x6b, 0x04); + USB11PHY_CLR8(0x6e, 0x01); + USB11PHY_CLR8(0x21, 0x2); + USB11PHY_CLR8(0x21, 0x1); + + /* 4 2. release force suspendm. */ + USB11PHY_SET8(0x68, 0x08); + USB11PHY_SET8(0x6a, 0x04); + /* clear 3.3V bias off ==> 3.3V */ + USB11PHY_CLR8(0x15, 0x04); + /* RG_USB20_ICUSB_EN, b0 */ + USB11PHY_CLR8(0x12, 0x01); + + /* 4 3. RG_DPPULLDOWN./RG_DMPULLDOWN. */ + USB11PHY_SET8(0x68, 0xc0); + /* 4 4. RG_XCVRSEL[1:0] =2'b01. */ + USB11PHY_CLR8(0x68, 0x30); + USB11PHY_SET8(0x68, 0x10); + /* 4 5. RG_TERMSEL = 1'b1 */ + USB11PHY_SET8(0x68, 0x04); + /* 4 6. RG_DATAIN[3:0]=4'b0000 */ + USB11PHY_CLR8(0x69, 0x3c); + /* + * 4 7. force_dp_pulldown, force_dm_pulldown, + * force_xcversel, force_termsel. + */ + USB11PHY_SET8(0x6a, 0xba); + + /* 4 8.RG_USB20_BC11_SW_EN 1'b0 */ + USB11PHY_CLR8(0x1a, 0x80); + /* 4 9.RG_USB20_OTG_VBUSSCMP_EN 1'b0 */ + USB11PHY_CLR8(0x1a, 0x10); + /* 4 10. delay 800us. */ + udelay(800); + /* 4 11. rg_usb20_pll_stable = 1 */ + USB11PHY_SET8(0x63, 0x02); + + udelay(1); + + USB11PHY_CLR8(0x6C, 0x2C); + USB11PHY_SET8(0x6C, 0x10); + USB11PHY_CLR8(0x6D, 0x3C); + /* RG_SUSPENDM=0; */ + USB11PHY_CLR8(0x68, 0x08); + + + /* 4 13. wait 1us */ + udelay(1); + } +} + +void mt65xx_usb11_phy_recover_common(int icusb, int bias_off) +{ + MYDBG("icusb : %d, bias_off : %d\n", icusb, bias_off); + if (icusb) { + /* + * Switch to USB function. + * (system register) + * force ip into usb mode. + */ + USB11PHY_CLR8(0x6b, 0x04); + USB11PHY_CLR8(0x6e, 0x01); + USB11PHY_CLR8(0x21, 0x2); + USB11PHY_CLR8(0x21, 0x1); + + /* RG_USB20_BC11_SW_EN 1'b0 */ + USB11PHY_CLR8(0x1a, 0x80); + + /* RG_USB20_ICUSB_EN, b1 */ + USB11PHY_SET8(0x12, 0x01); + + if (bias_off) { + /* + * set 3.3V bias off + * RG_USB20_GBIAS_ENB ==> 3.3V bias OFF + */ + USB11PHY_SET8(0x15, 0x04); + } else { + /* + * clear 3.3V bias off + * RG_USB20_GBIAS_ENB ==> 3.3V bias ON + */ + USB11PHY_CLR8(0x15, 0x04); + } + + /* release force suspendm. */ + USB11PHY_CLR8(0x6a, 0x04); + + /* wait 2ms */ + mdelay(2); + } else { /* from mt65xx_usb11_phy_recover() */ + MYDBG(""); + /* + * 4 1. swtich to USB function. + * (system register) + * force ip into usb mode. + */ + /* force_uart_en = 1'b0 */ + USB11PHY_CLR8(0x6b, 0x04); + /* RG_UART_EN = 1'b0 */ + USB11PHY_CLR8(0x6e, 0x1); + /* rg_usb20_gpio_ctl = 1'b0 */ + USB11PHY_CLR8(0x21, 0x2); + /* usb20_gpio_mode = 1'b0 */ + USB11PHY_CLR8(0x21, 0x1); + + + /* 4 5. Release force suspendm. */ + USB11PHY_CLR8(0x6a, 0x04); + + /* 4 6. RG_DPPULLDOWN = 1'b0 */ + USB11PHY_CLR8(0x68, 0x40); + /* 4 7. RG_DMPULLDOWN = 1'b0 */ + USB11PHY_CLR8(0x68, 0x80); + /* 4 8. RG_XCVRSEL = 2'b00 */ + USB11PHY_CLR8(0x68, 0x30); + /* 4 9. RG_TERMSEL = 1'b0 */ + USB11PHY_CLR8(0x68, 0x04); + /* 4 10. RG_DATAIN[3:0] = 4'b0000 */ + USB11PHY_CLR8(0x69, 0x3c); + + /* 4 11. force_dp_pulldown = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x10); + /* 4 12. force_dm_pulldown = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x20); + /* 4 13. force_xcversel = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x08); + /* 4 14. force_termsel = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x02); + /* 4 15. force_datain = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x80); + + /* 4 16. RG_USB20_BC11_SW_EN 1'b0 */ + USB11PHY_CLR8(0x1a, 0x80); + + USB11PHY_SET8(0x18, 0x02); + /* 4 17. RG_USB20_OTG_VBUSSCMP_EN 1'b1 */ + USB11PHY_SET8(0x1a, 0x10); + + USB11PHY_SET8(0x6C, 0x2C); + USB11PHY_SET8(0x6D, 0x3C); + /* <4> 18. wait 800 usec. */ + udelay(800); + + usb11_hs_slew_rate_cal(); + } +} + +void mt65xx_usb11_phy_poweron_volt_30(void) +{ + MYDBG(""); + mt65xx_usb11_phy_poweron_common(1, 0); +} + +void mt65xx_usb11_phy_savecurrent_volt_30(void) +{ + MYDBG(""); + mt65xx_usb11_phy_savecurrent_common(1, 0); +} + +void mt65xx_usb11_phy_recover_volt_30(void) +{ + MYDBG(""); + mt65xx_usb11_phy_recover_common(1, 0); +} + +void mt65xx_usb11_phy_poweron_volt_18(void) +{ + MYDBG(""); + mt65xx_usb11_phy_poweron_common(1, 1); +} + +void mt65xx_usb11_phy_savecurrent_volt_18(void) +{ + MYDBG(""); + mt65xx_usb11_phy_savecurrent_common(1, 1); +} + +void mt65xx_usb11_phy_recover_volt_18(void) +{ + MYDBG(""); + mt65xx_usb11_phy_recover_common(1, 1); +} + +void mt65xx_usb11_phy_poweron_volt_50(void) +{ + MYDBG(""); + mt65xx_usb11_phy_poweron_common(0, 0); +} + +void mt65xx_usb11_phy_recover_volt_50(void) +{ + MYDBG(""); + mt65xx_usb11_phy_recover_common(0, 0); +} + +void mt65xx_usb11_phy_savecurrent_volt_50(void) +{ + MYDBG(""); + mt65xx_usb11_phy_savecurrent_common(0, 0); +} +#endif + +void usb11_hs_slew_rate_cal(void) +{ + unsigned long data; + unsigned long x; + unsigned char value; + unsigned long start_time, timeout; + unsigned int timeout_flag = 0; + + /* marked becoz FS device, FIXME to check this function correctness */ +#ifdef MTK_DT_USB_SUPPORT + MYDBG("\n"); + return; +#endif + /* 4 s1:enable usb ring oscillator. */ + USB11PHY_WRITE8(0x15, 0x80); + + /* 4 s2:wait 1us. */ + udelay(1); + + /* 4 s3:enable free run clock */ + USB11PHY_WRITE8(0xf00 - 0x900 + 0x11, 0x01); + /* 4 s4:setting cyclecnt. */ + USB11PHY_WRITE8(0xf00 - 0x900 + 0x01, 0x04); + /* 4 s5:enable frequency meter */ + USB11PHY_SET8(0xf00 - 0x900 + 0x03, 0x05); + + /* 4 s6:wait for frequency valid. */ + start_time = jiffies; + timeout = jiffies + 3 * HZ; + while (!(USB11PHY_READ8(0xf00 - 0x900 + 0x10) & 0x1)) { + if (time_after(jiffies, timeout)) { + timeout_flag = 1; + break; + } + } + + /* 4 s7: read result. */ + if (timeout_flag) { + pr_err("[USBPHY] Slew Rate Calibration: Timeout\n"); + value = 0x4; + } else { + data = USB11PHY_READ32(0xf00 - 0x900 + 0x0c); + x = ((1024 * FRA * PARA) / data); + value = (unsigned char)(x / 1000); + if ((x - value * 1000) / 100 >= 5) + value += 1; + /* + * printk("%s: FM_OUT =%d, x=%d,value=%d\n", + * __func__, data, x, value); + */ + } + + /* 4 s8: disable Frequency and run clock. */ + /* disable frequency meter */ + USB11PHY_CLR8(0xf00 - 0x900 + 0x03, 0x05); + /* disable free run clock */ + USB11PHY_CLR8(0xf00 - 0x900 + 0x11, 0x01); + + /* 4 s9: */ + USB11PHY_WRITE8(0x15, value << 4); + + /* 4 s10:disable usb ring oscillator. */ + USB11PHY_CLR8(0x15, 0x80); +} + + +void mt65xx_usb11_phy_poweron(void) +{ +#ifdef CONFIG_MTK_ICUSB_SUPPORT + enum PHY_VOLTAGE_TYPE phy_volt = get_usb11_phy_voltage(); + struct timeval tv_begin, tv_end; +#endif + WARNING("mt65xx_usb11_phy_poweron++\r\n"); +#ifdef CONFIG_MTK_ICUSB_SUPPORT + do_gettimeofday(&tv_begin); + + if (phy_volt == VOL_33) + mt65xx_usb11_phy_poweron_volt_30(); + else if (phy_volt == VOL_18) + mt65xx_usb11_phy_poweron_volt_18(); + else if (phy_volt == VOL_50) + mt65xx_usb11_phy_poweron_volt_50(); + else + MYDBG(""); + + do_gettimeofday(&tv_end); + MYDBG("time spent, sec : %d, usec : %d\n", + (unsigned int)(tv_end.tv_sec - tv_begin.tv_sec), + (unsigned int)(tv_end.tv_usec - tv_begin.tv_usec)); +#else + /* move pll to func calling mt65xx_usb11_phy_poweron() */ +#if 0 + /* udelay(100); // PHY power stable time */ +#if 0 + /* reverse preloader's sin @mt6575_usbphy.c */ + USB11PHY_CLR8(U1PHTCR2 + 3, force_usb11_avalid | force_usb11_bvalid | + force_usb11_sessend | force_usb11_vbusvalid); + USB11PHY_CLR8(U1PHTCR2 + 2, RG_USB11_AVALID | RG_USB11_BVALID | + RG_USB11_SESSEND | RG_USB11_VBUSVALID); + USB11PHY_CLR8(U1PHYCR1 + 2, force_usb11_en_fs_ls_rcv | + force_usb11_en_fs_ls_tx); + + /**************************************/ + + USB11PHY_SET8(U1PHYCR0 + 1, RG_USB11_FSLS_ENBGRI); + + USB11PHY_SET8(U1PHTCR2 + 3, force_usb11_avalid | force_usb11_sessend | + force_usb11_vbusvalid); + USB11PHY_SET8(U1PHTCR2 + 2, RG_USB11_AVALID | RG_USB11_VBUSVALID); + USB11PHY_CLR8(U1PHTCR2 + 2, RG_USB11_SESSEND); +#endif + + +#if 0 + /* HQA LOOPBACK TEST. */ + USB11PHY_CLR8(0x1a, 0x80); + USB11PHY_CLR8(0x68, 0x08); + + USB11PHY_CLR8(0x68, 0x03); + USB11PHY_SET8(0x68, 0x10); + + USB11PHY_SET8(0x68, 0x04); + USB11PHY_CLR8(0x69, 0x03); + USB11PHY_CLR8(0x69, 0x3C); + + USB11PHY_SET8(0x68, 0x80); + + USB11PHY_SET8(0x6a, 0x04); + USB11PHY_SET8(0x6a, 0x01); + USB11PHY_SET8(0x6a, 0x08); + USB11PHY_SET8(0x6a, 0x02); + + USB11PHY_SET8(0x6a, 0x40); + USB11PHY_SET8(0x6a, 0x80); + USB11PHY_SET8(0x6a, 0x30); + + USB11PHY_SET8(0x68, 0x08); + udelay(50); + + USB11PHY_SET8(0x63, 0x02); + udelay(1); + + USB11PHY_SET8(0x63, 0x02); + USB11PHY_SET8(0x63, 0x04); + USB11PHY_CLR8(0x63, 0x08); + +#endif + + + +#if 0 + /* HQA LOOPBACK TEST. */ + USB11PHY_CLR8(0x1a, 0x80); + USB11PHY_CLR8(0x68, 0x08); + + USB11PHY_CLR8(0x68, 0x03); + USB11PHY_CLR8(0x68, 0x30); + + USB11PHY_CLR8(0x68, 0x04); + USB11PHY_CLR8(0x69, 0x03); + USB11PHY_CLR8(0x69, 0x3C); + + USB11PHY_CLR8(0x68, 0xC0); + + USB11PHY_SET8(0x6a, 0x04); + USB11PHY_SET8(0x6a, 0x01); + USB11PHY_SET8(0x6a, 0x08); + USB11PHY_SET8(0x6a, 0x02); + + USB11PHY_SET8(0x6a, 0x40); + USB11PHY_SET8(0x6a, 0x80); + USB11PHY_SET8(0x6a, 0x30); + + USB11PHY_SET8(0x68, 0x08); + udelay(50); + + USB11PHY_SET8(0x63, 0x02); + udelay(1); + + USB11PHY_SET8(0x63, 0x02); + USB11PHY_SET8(0x63, 0x04); + USB11PHY_CLR8(0x63, 0x08); + + usb11_hs_slew_rate_cal(); + +#endif + + udelay(50); +#endif + + USB11PHY_CLR8(0x6b, 0x04); + USB11PHY_CLR8(0x6e, 0x01); + + USB11PHY_CLR8(0x1a, 0x80); + + /* remove in MT6588 ????? + USBPHY_CLR8(0x02, 0x7f); + USBPHY_SET8(0x02, 0x09); + USBPHY_CLR8(0x22, 0x03); + */ + + USB11PHY_CLR8(0x6a, 0x04); + /* USBPHY_SET8(0x1b, 0x08); */ + + /* force VBUS Valid */ + USB11PHY_SET8(0x6C, 0x2C); + USB11PHY_SET8(0x6D, 0x3C); + + udelay(800); +#endif + +} + +void mt65xx_usb11_phy_savecurrent(void) +{ +#ifdef CONFIG_MTK_ICUSB_SUPPORT + enum PHY_VOLTAGE_TYPE phy_volt = get_usb11_phy_voltage(); +#endif + WARNING("%s++\r\n", __func__); +#ifdef CONFIG_MTK_ICUSB_SUPPORT + if (phy_volt == VOL_33) + mt65xx_usb11_phy_savecurrent_volt_30(); + else if (phy_volt == VOL_18) + mt65xx_usb11_phy_savecurrent_volt_18(); + else if (phy_volt == VOL_50) + mt65xx_usb11_phy_savecurrent_volt_50(); + else + MYDBG(""); +#else + + /* + * 4 1. swtich to USB function. + * (system register, force ip into usb mode. + */ + USB11PHY_CLR8(0x6b, 0x04); + USB11PHY_CLR8(0x6e, 0x01); + USB11PHY_CLR8(0x21, 0x2); + USB11PHY_CLR8(0x21, 0x1); + + /* 4 2. release force suspendm. */ + /* RG_SUSPENDM, b1 */ + USB11PHY_SET8(0x68, 0x08); + USB11PHY_SET8(0x6a, 0x04); + /* 4 3. RG_DPPULLDOWN./RG_DMPULLDOWN. */ + USB11PHY_SET8(0x68, 0xc0); + /* 4 4. RG_XCVRSEL[1:0] =2'b01. */ + USB11PHY_CLR8(0x68, 0x30); + USB11PHY_SET8(0x68, 0x10); + /* 4 5. RG_TERMSEL = 1'b1 */ + USB11PHY_SET8(0x68, 0x04); + /* 4 6. RG_DATAIN[3:0]=4'b0000 */ + USB11PHY_CLR8(0x69, 0x3c); + /* + * 4 7. + * force_dp_pulldown, force_dm_pulldown, force_xcversel,force_termsel. + */ + USB11PHY_SET8(0x6a, 0xba); + + /* 4 8.RG_USB20_BC11_SW_EN 1'b0 */ + USB11PHY_CLR8(0x1a, 0x80); + /* 4 9.RG_USB20_OTG_VBUSSCMP_EN 1'b0 */ + USB11PHY_CLR8(0x1a, 0x10); + /* 4 10. delay 800us. */ + udelay(800); + /* 4 11. rg_usb20_pll_stable = 1 */ + USB11PHY_SET8(0x63, 0x02); + + udelay(1); + /* 4 12. force suspendm = 1. */ + USB11PHY_SET8(0x6a, 0x04); + + USB11PHY_CLR8(0x6C, 0x2C); + USB11PHY_SET8(0x6C, 0x10); + USB11PHY_CLR8(0x6D, 0x3C); + /* RG_SUSPENDM=0; */ + USB11PHY_CLR8(0x68, 0x08); + + /* 4 13. wait 1us */ + udelay(1); + +#endif +} + +void mt65xx_usb11_phy_recover(void) +{ +#ifdef CONFIG_MTK_ICUSB_SUPPORT + enum PHY_VOLTAGE_TYPE phy_volt = get_usb11_phy_voltage(); +#endif + + WARNING("mt65xx_usb11_phy_recover++\r\n"); +#ifdef CONFIG_MTK_ICUSB_SUPPORT + if (phy_volt == VOL_33) + mt65xx_usb11_phy_recover_volt_30(); + else if (phy_volt == VOL_18) + mt65xx_usb11_phy_recover_volt_18(); + else if (phy_volt == VOL_50) + mt65xx_usb11_phy_recover_volt_50(); + else + MYDBG(""); +#else + + /* special for 95 phy */ + USB11PHY_CLR8(0x6c, 0x02); /* RG_IDDIG = 0 */ + USB11PHY_SET8(0x6d, 0x02); /* force_iddig = 1 */ + + /* move 4.1, 4.2 to func calling mt65xx_usb11_phy_recover() */ +#if 0 + /* 4 1. turn on USB reference clock. */ + +#if 0 + USB11PHY_SET8(U1PHTCR2 + 3, + force_usb11_avalid | + force_usb11_sessend | + force_usb11_vbusvalid); + USB11PHY_SET8(U1PHTCR2 + 2, RG_USB11_AVALID | RG_USB11_VBUSVALID); + USB11PHY_CLR8(U1PHTCR2 + 2, RG_USB11_SESSEND); + + USB11PHY_CLR8(U1PHYCR1 + 2, force_usb11_en_fs_ls_rcv | + force_usb11_en_fs_ls_tx); + USB11PHY_CLR8(U1PHYCR1 + 3, RG_USB11_EN_FS_LS_RCV | + RG_USB11_EN_FS_LS_TX); + + USB11PHY_SET8(U1PHYCR0 + 1, RG_USB11_FSLS_ENBGRI); + + udelay(100); +#endif + + /* 4 2. wait 50 usec. */ + udelay(50); +#endif + /* + * 4 1. switch to USB function. + * (system register, force ip into usb mode) + */ + /* force_uart_en = 1'b0 */ + USB11PHY_CLR8(0x6b, 0x04); + /* RG_UART_EN = 1'b0 */ + USB11PHY_CLR8(0x6e, 0x1); + /* rg_usb20_gpio_ctl = 1'b0 */ + USB11PHY_CLR8(0x21, 0x2); + /* usb20_gpio_mode = 1'b0 */ + USB11PHY_CLR8(0x21, 0x1); + + /* 4 2. Release force suspendm. */ + USB11PHY_CLR8(0x6a, 0x04); + + /* 4 3. RG_DPPULLDOWN = 1'b0 */ + USB11PHY_CLR8(0x68, 0x40); + /* 4 4. RG_DMPULLDOWN = 1'b0 */ + USB11PHY_CLR8(0x68, 0x80); + /* 4 5. RG_XCVRSEL = 2'b00 */ + USB11PHY_CLR8(0x68, 0x30); + /* 4 6. RG_TERMSEL = 1'b0 */ + USB11PHY_CLR8(0x68, 0x04); + /* 4 7. RG_DATAIN[3:0] = 4'b0000 */ + USB11PHY_CLR8(0x69, 0x3c); + + /* 4 8. force_dp_pulldown = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x10); + /* 4 9. force_dm_pulldown = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x20); + /* 4 11. force_xcversel = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x08); + /* 4 12. force_termsel = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x02); + /* 4 13. force_datain = 1b'0 */ + USB11PHY_CLR8(0x6a, 0x80); + + /* 4 14. RG_USB20_BC11_SW_EN 1'b0 */ + USB11PHY_CLR8(0x1a, 0x80); + + /* pure host don't have to set this, and it is power-saved */ +#ifdef MTK_DT_USB_SUPPORT + /* 4 17. RG_USB20_OTG_VBUSSCMP_EN 1'b1 */ + USB11PHY_CLR8(0x1a, 0x10); +#else + /* 4 17. RG_USB20_OTG_VBUSSCMP_EN 1'b1 */ + USB11PHY_SET8(0x1a, 0x10); +#endif + + USB11PHY_SET8(0x6C, 0x2C); + USB11PHY_SET8(0x6D, 0x3C); + /* <4> 18. wait 800 usec. */ + udelay(800); + + usb11_hs_slew_rate_cal(); +#endif +} + +#define USB_CLK_DEBUG +#ifdef USB_CLK_DEBUG +void __iomem *usb11_debug_clk_infracfg_base; +#define MODULE_SW_CG_2_SET (usb11_debug_clk_infracfg_base + 0x80) +#define MODULE_SW_CG_2_CLR (usb11_debug_clk_infracfg_base + 0x84) +#define MODULE_SW_CG_2_STA (usb11_debug_clk_infracfg_base + 0x90) +static bool get_clk_io = true; +#endif + + +#ifdef CONFIG_MTK_FPGA +void mt65xx_usb11_clock_enable(bool enable) +{ +} + +#else +static bool clock_enabled; + +static int enable_cnt; +static int disable_cnt; + +#define MTK_USB11_CLKNODE "mediatek,mt6755-infrasys" + +void mt65xx_usb11_clock_enable(bool enable) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-infrasys"); + /* WARNING("mt65xx_usb11_clock_enable++\r\n"); */ + /* dump_stack(); */ + MYDBG("enable_cnt : %d, disable_cnt : %d\n", enable_cnt, disable_cnt); + if (enable) { + enable_cnt++; + if (clock_enabled) /* already enable */ + return; + + MYDBG(""); + /* enable_clock (MT_CG_INFRA_USB, "USB11"); */ + /* enable_clock (MT_CG_INFRA_ICUSB, "USB11"); */ + /* enable_clock (MT_CG_INFRA_USB_MCU, "USB11"); */ + #ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_INFRA_ICUSB, "USB11"); + #else + clk_enable(musb_clk11); + clk_enable(musb_clk30); + #endif + clock_enabled = true; + + #ifdef USB_CLK_DEBUG + if (get_clk_io) { + get_clk_io = false; + usb11_debug_clk_infracfg_base = of_iomap(node, + 0); + if (!usb11_debug_clk_infracfg_base) + pr_err("[CLK_INFRACFG_AO] is NULL\n"); + } + if (!IS_ERR(musb_clk11)) + pr_debug("USB11 musb clock okay, enable: %d\n", + enable); + else + pr_err("USB11 musb clock fail, enable: %d\n", + enable); + /* + * bit1: ssusb_top_cg_sta: + * 0: clock enable + * 1: clock disable + */ + pr_debug("USB11 MODULE_SW_CG_2_STA = 0x%08x\n", + readl(MODULE_SW_CG_2_STA)); + #endif + } else { + disable_cnt++; + if (!clock_enabled) /* already disabled. */ + return; + + MYDBG(""); + /* disable_clock (MT_CG_INFRA_USB_MCU, "USB11"); */ + /* disable_clock (MT_CG_INFRA_ICUSB, "USB11"); */ + /* disable_clock (MT_CG_INFRA_USB, "USB11"); */ + + #ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_INFRA_ICUSB, "USB11"); + #else + clk_disable(musb_clk11); + clk_disable(musb_clk30); + #endif + clock_enabled = false; + } +} +#endif + +int mt65xx_usb11_poweron(int on) +{ + static bool recover; + int retval = 0; + + WARNING("%s++\r\n", __func__); + + if (on) { + if (musbfsh_power) { + retval = 1; /* already powered on */ + } else { +#ifdef MTK_DT_USB_SUPPORT + if (!musbfsh_skip_clk) { +#endif + mt65xx_usb11_clock_enable(true); +#ifdef MTK_DT_USB_SUPPORT + } +#endif + if (!recover) { + udelay(50); + mt65xx_usb11_phy_recover(); + recover = true; + } else { + udelay(50); + +#ifdef MTK_DT_USB_SUPPORT + if (!musbfsh_skip_phy) { +#endif + mt65xx_usb11_phy_recover(); +#ifdef MTK_DT_USB_SUPPORT + } +#endif + } + MYDBG(""); +/* dump_stack(); */ + + musbfsh_power = true; + } + } else { + if (!musbfsh_power) { + retval = 1; /* already powered off */ + } else { +#ifdef MTK_DT_USB_SUPPORT + if (!musbfsh_skip_phy) { +#endif + mt65xx_usb11_phy_savecurrent(); +#ifdef MTK_DT_USB_SUPPORT + } +#endif +#ifdef MTK_DT_USB_SUPPORT + if (!musbfsh_skip_clk) { +#endif + mt65xx_usb11_clock_enable(false); +#ifdef MTK_DT_USB_SUPPORT + } +#endif + + MYDBG(""); +/* dump_stack(); */ + + musbfsh_power = false; + } + } + return retval; +} + +void mt65xx_usb11_vbus(struct musbfsh *musbfsh, int is_on) +{ + /* static int oned = 0; */ + WARNING("%s, is_on=%d\r\n", __func__, is_on); +#if 0 + /* should set GPIO_OTG_DRVVBUS_PIN as gpio mode. */ + /* mt_set_gpio_mode(GPIO67,0); */ + mt_set_gpio_dir(GPIO_OTG_DRVVBUS_PIN, GPIO_DIR_OUT); + if (is_on) { + if (oned) + return; + mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN, GPIO_OUT_ONE); + oned = 1; + } else { + if (!oned) + return; + mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN, GPIO_OUT_ZERO); + oned = 0; + } +#endif +} + +int musbfsh_platform_init(struct musbfsh *musbfsh) +{ + /* + * used for EVB usb p1 vbus, enable this result in port0 function fail + * alternative way is to connect as device by port0 to PC, + * vbus share port0 and port1, so vbus will be ok + */ + /* enable_drv_vbus_through_u3(); */ + + /* + * could enable this for icusb flow testing, be sure with dummy MD + * coz MD will control vsim too + * VSIM1 give PHY power and SIM vcc + */ + /* hwPowerOn(MT6331_POWER_LDO_VSIM1, VOL_3000, "USB11"); */ + + MYDBG(""); + + WARNING("%s++\n", __func__); + if (!musbfsh) { + ERR("musbfsh_platform_init,error,musbfsh is NULL"); + return -1; + } + musbfsh->board_set_vbus = mt65xx_usb11_vbus; + musbfsh->board_set_power = mt65xx_usb11_poweron; + +#ifdef MTK_DT_USB_SUPPORT + hwPowerOn(MT6325_POWER_LDO_VUSB33, VOL_3300, "V33_USB_P1_DSDA"); + usb_p1_switch_to_modem(); +#endif +#ifndef CONFIG_MTK_ICUSB_SUPPORT + /* + * VSIM1 is used for PHY I/O power, icusb flow should not invole this, + * it shoulde be controlled by MD + */ + /* hwPowerOn(MT6331_POWER_LDO_VSIM1, VOL_3000, "USB11"); */ +#endif + + +#ifdef CONFIG_MTK_ICUSB_SUPPORT + /* only power_on, clk, pll for MAC, no phy power on */ + pr_debug("%s, only clk and pll, no phy_power_on\n", + __func__); + mt65xx_usb11_clock_enable(true); +#else + mt65xx_usb11_poweron(true); +#endif + return 0; +} + +int musbfsh_platform_exit(struct musbfsh *musbfsh) +{ + INFO("%s++\r\n", __func__); + mt65xx_usb11_poweron(false); + /* put it here because we can't shutdown PHY power during suspend */ + /* hwPowerDown(MT6331_POWER_LDO_VSIM1, "USB11"); */ +#ifdef MTK_DT_USB_SUPPORT + hwPowerDown(MT6325_POWER_LDO_VUSB33, "V33_USB_P1_DSDA"); +#endif + return 0; +} + +void musbfsh_platform_enable(struct musbfsh *musbfsh) +{ + INFO("%s++\r\n", __func__); +} + +void musbfsh_platform_disable(struct musbfsh *musbfsh) +{ + INFO("%s++\r\n", __func__); +} + +void musbfsh_hcd_release(struct device *dev) +{ + INFO("%s++, dev = %p.\n", __func__, dev); +} diff --git a/drivers/misc/mediatek/usb11/mt6755/musbfsh_mt65xx.h b/drivers/misc/mediatek/usb11/mt6755/musbfsh_mt65xx.h new file mode 100644 index 0000000000000000000000000000000000000000..5d64f19194b9d93838855b235b6687ca1874189e --- /dev/null +++ b/drivers/misc/mediatek/usb11/mt6755/musbfsh_mt65xx.h @@ -0,0 +1,145 @@ +/* + * Driver for Special USB-PHY of MUSB HOST peripheral + * + * The power sequence and programming bits were different from SoC. + * Please use the coorsponding USB-PHY API for your SoC. + * This driver includes Mediatek MUSB DT/ICUSB support. + * + * Copyright 2015 Mediatek Inc. + * Marvin Lin + * Arvin Wang + * Vincent Fan + * Bryant Lu + * Yu-Chang Wang + * Macpaul Lin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MUSBFSH_MT65XX_H__ +#define __MUSBFSH_MT65XX_H__ +/* #include */ + +/* #define IC_USB */ + +/* Level 1 interrupts: */ +#define USB11_L1INTS 0xA0 +#define USB11_L1INTM 0xA4 +#define USB11_L1INTP 0xA8 +#define MUSBFSH_DMA_INTR_UNMASK_CLR_OFFSET (16) +#define MUSBFSH_DMA_INTR_UNMASK_SET_OFFSET (24) +#define USB11_BASE USB3_BASE +/* USB11 PHY registers: */ +#define USB11_PHY_ADDR (USB_SIF_BASE + 0x900) + +#define U1PHYCR0 0xC0 + +/* @U1PHYCR0+1, 1:power on or recovery; 0:save current */ +#define RG_USB11_FSLS_ENBGRI 0x08 + +#define U1PHYCR1 0xC4 +#define force_usb11_en_fs_ls_rcv 0x04 /* @U1PHYCR1+2 */ +#define force_usb11_en_fs_ls_tx 0x02 /* @U1PHYCR1+2 */ +#define RG_USB11_EN_FS_LS_RCV 0x04 /* @U1PHYCR1+3 */ +#define RG_USB11_EN_FS_LS_TX 0x02 /* @U1PHYCR1+3 */ + +#define U1PHTCR2 0xC8 +#define force_usb11_dm_rpu 0x01 +#define force_usb11_dp_rpu 0x02 +#define force_usb11_dm_rpd 0x04 +#define force_usb11_dp_rpd 0x08 +#define RG_USB11_DM_RPU 0x10 +#define RG_USB11_DP_RPU 0x20 +#define RG_USB11_DM_RPD 0x40 +#define RG_USB11_DP_RPD 0x80 +#define RG_USB11_AVALID 0x04 /* @U1PHYCR2+2 */ +#define RG_USB11_BVALID 0x08 /* @U1PHYCR2+2 */ +#define RG_USB11_SESSEND 0x10 /* @U1PHYCR2+2 */ +#define RG_USB11_VBUSVALID 0x20 /* @U1PHYCR2+2 */ +#define force_usb11_avalid 0x04 /* @U1PHYCR2+3 */ +#define force_usb11_bvalid 0x08 /* @U1PHYCR2+3 */ +#define force_usb11_sessend 0x10 /* @U1PHYCR2+3 */ +#define force_usb11_vbusvalid 0x20 /* @U1PHYCR2+3 */ + +#ifdef CONFIG_MTK_USBFSH +extern struct musbfsh *g_musbfsh; +#define USB11PHY_READ32(offset) __raw_readl((void __iomem *) \ + (((unsigned long)g_musbfsh->phy_base)+0x800+offset)) +#define USB11PHY_READ8(offset) __raw_readb((void __iomem *) \ + (((unsigned long)g_musbfsh->phy_base)+0x800+offset)) +#define USB11PHY_WRITE8(offset, value) __raw_writeb(value, (void __iomem *) \ + (((unsigned long)g_musbfsh->phy_base)+0x800+offset)) +#ifndef CONFIG_MTK_CLKMGR +extern struct clk *musb_clk11; +extern struct clk *musb_clk30; +#endif +#else +#define USB11PHY_READ32(offset) __raw_readl(offset) +#define USB11PHY_READ8(offset) __raw_readb(offset) +#define USB11PHY_WRITE8(offset, value) __raw_writeb(value, offset) +#endif + +#define USB11PHY_SET8(offset, mask) USB11PHY_WRITE8((offset), \ + USB11PHY_READ8(offset) | (mask)) +#define USB11PHY_CLR8(offset, mask) USB11PHY_WRITE8((offset), \ + USB11PHY_READ8(offset) & (~(mask))) + +#ifdef CONFIG_MTK_ICUSB_SUPPORT +#include "musbfsh_icusb.h" + +void mt65xx_usb11_phy_poweron(void); +void mt65xx_usb11_phy_recover(void); +void mt65xx_usb11_phy_savecurrent(void); +void mt65xx_usb11_enable_clk_pll_pw(void); +void mt65xx_usb11_disable_clk_pll_pw(void); + +void mt65xx_usb11_mac_phy_dump(void); +void mt65xx_usb11_mac_phy_babble_clear(struct musbfsh *musbfsh); +void mt65xx_usb11_mac_phy_babble_recover(struct musbfsh *musbfsh); +void mt65xx_usb11_mac_reset_and_phy_stress_set(void); + +int mt65xx_check_usb11_clk_status(void); + +void set_usb11_enabled(void); +void set_usb_phy_voltage(enum PHY_VOLTAGE_TYPE phy_volt); +void reset_usb11_phy_power_negotiation_status(void); +void usb11_hs_slew_rate_cal(void); + +void create_ic_usb_cmd_proc_entry(void); +void set_usb11_sts_disconnecting(void); +void create_icusb_sysfs_attr(void); +void set_usb11_sts_connect(void); +int check_usb11_sts_disconnect_done(void); + +void musbfsh_mac_init(void); +void musbfsh_root_disc_procedure(void); + +extern enum PHY_VOLTAGE_TYPE g_phy_voltage; +/* extern struct musbfsh *g_musbfsh; */ + +#endif /* CONFIG_MTK_ICUSB_SUPPORT */ + +extern void musbfsh_hcd_release(struct device *dev); + +#endif /* __MUSBFSH_MT65XX_H__ */ diff --git a/drivers/misc/mediatek/usb2jtag/mt6755/Makefile b/drivers/misc/mediatek/usb2jtag/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7054dce1de59fd67aff02a6c5bdf53420d03ed72 --- /dev/null +++ b/drivers/misc/mediatek/usb2jtag/mt6755/Makefile @@ -0,0 +1 @@ +obj-y += usb2jtag_platform.o diff --git a/drivers/misc/mediatek/usb2jtag/mt6755/usb2jtag_platform.c b/drivers/misc/mediatek/usb2jtag/mt6755/usb2jtag_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..23c83219a22d0599cb40955a984920ce3b4e698c --- /dev/null +++ b/drivers/misc/mediatek/usb2jtag/mt6755/usb2jtag_platform.c @@ -0,0 +1,80 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include +#include +#include "../usb2jtag_v1.h" +#include +#include + +static int mt_usb2jtag_hw_init(void) +{ + unsigned int ret = 0; + struct device_node *node = NULL; + + void __iomem *INFRA_AO_BASE; + void __iomem *USB0PSIF2_BASE; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-infrasys"); + if (!node) { + pr_err("[USB2JTAG] map node @ infrasys failed\n"); + return -1; + } + INFRA_AO_BASE = of_iomap(node, 0); + if (!INFRA_AO_BASE) { + pr_err("[USB2JTAG] iomap infrasys base failed\n"); + return -1; + } + node = of_find_compatible_node(NULL, NULL, "mediatek,usb0p_sif2"); + if (!node) { + pr_err("[USB2JTAG] map node @ usb0p_sif2 failed\n"); + return -1; + } + + USB0PSIF2_BASE = of_iomap(node, 0); + if (!node) { + pr_err("[USB2JTAG] iomap usb0p_sif2 base failed\n"); + return -1; + } +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + ret = pmic_set_register_value(PMIC_LDO_VUSB33_EN, 0x01); +#else /* for pmic mt6351 setting */ + ret |= pmic_set_register_value(MT6351_PMIC_RG_VUSB33_EN, 0x01); + ret |= pmic_set_register_value(MT6351_PMIC_RG_VA10_EN, 0x01); + ret |= pmic_set_register_value(MT6351_PMIC_RG_VA10_VOSEL, 0x02); +#endif + if (ret) { + pr_err("[USB2JTAG] USB2JTAGE Voltage config failed\n"); + BUG_ON(1); + } + + writew(readl(INFRA_AO_BASE + 0xF00) | 0x1 << 14, INFRA_AO_BASE + 0xF00); + writel(0x00100488 , USB0PSIF2_BASE + 0x818); + writel(0x6F, USB0PSIF2_BASE + 0x800); + writel(0x0, USB0PSIF2_BASE + 0x808); + writel(0xFF1A, USB0PSIF2_BASE + 0x820); + return 0; +} + +static int __init mt_usb2jtag_platform_init(void) +{ + struct mt_usb2jtag_driver *mt_usb2jtag_drv; + + mt_usb2jtag_drv = get_mt_usb2jtag_drv(); + mt_usb2jtag_drv->usb2jtag_init = mt_usb2jtag_hw_init; + mt_usb2jtag_drv->usb2jtag_suspend = NULL; + mt_usb2jtag_drv->usb2jtag_resume = NULL; + + return 0; +} + +arch_initcall(mt_usb2jtag_platform_init); diff --git a/drivers/misc/mediatek/vibrator/mt6755/Makefile b/drivers/misc/mediatek/vibrator/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..678e5ab6a438b9be36aab83fafcf760f055891b7 --- /dev/null +++ b/drivers/misc/mediatek/vibrator/mt6755/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + + +obj-$(CONFIG_MTK_VIBRATOR) := vibrator.o +#ccflags-y := -Idrivers/staging/android/ diff --git a/drivers/misc/mediatek/vibrator/mt6755/vibrator.c b/drivers/misc/mediatek/vibrator/mt6755/vibrator.c new file mode 100644 index 0000000000000000000000000000000000000000..d3e73b7bea833c316b5eeb7d099cce2cf9bca7b0 --- /dev/null +++ b/drivers/misc/mediatek/vibrator/mt6755/vibrator.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, +i * 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. + */ + +/****************************************************************************** + * mt6575_vibrator.c - MT6575 Android Linux Vibrator Device Driver + * + * Copyright 2009-2010 MediaTek Co.,Ltd. + * + * DESCRIPTION: + * This file provid the other drivers vibrator relative functions + * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vibrator.h" + +struct vibrator_hw *pvib_cust = NULL; + +static int debug_enable_vib_hal = 1; +/* #define pr_fmt(fmt) "[vibrator]"fmt */ +#define VIB_DEBUG(format, args...) do { \ + if (debug_enable_vib_hal) {\ + pr_debug(format, ##args);\ + } \ +} while (0) + +void vibr_Enable_HW(void) +{ +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_LDO_VIBR_EN, 1); /* [bit 1]: VIBR_EN, 1=enable */ +#else + pmic_set_register_value(MT6351_PMIC_RG_VIBR_EN, 1); /* [bit 1]: VIBR_EN, 1=enable */ +#endif +} + +void vibr_Disable_HW(void) +{ +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_LDO_VIBR_EN, 0); /* [bit 1]: VIBR_EN, 1=enable */ +#else + pmic_set_register_value(MT6351_PMIC_RG_VIBR_EN, 0); /* [bit 1]: VIBR_EN, 1=enable */ +#endif +} + +/****************************************** +* Set RG_VIBR_VOSEL Output voltage select +* hw->vib_vol: Voltage selection +* 3'b000: 1.2V +* 3'b001: 1.3V +* 3'b010: 1.5V +* 3'b011: 1.8V +* 3'b100: 2.0V, if PMIC6353, 2.5V +* 3'b101: 2.8V +* 3'b110: 3.0V +* 3'b111: 3.3V +*******************************************/ +struct vibrator_hw *get_cust_vibrator_dtsi(void) +{ + int ret; + struct device_node *led_node = NULL; + + if (pvib_cust == NULL) { + pvib_cust = kmalloc(sizeof(struct vibrator_hw), GFP_KERNEL); + if (pvib_cust == NULL) { + VIB_DEBUG("get_cust_vibrator_dtsi kmalloc fail\n"); + goto out; + } + + led_node = + of_find_compatible_node(NULL, NULL, "mediatek,vibrator"); + if (!led_node) { + VIB_DEBUG("Cannot find vibrator node from dts\n"); + kfree(pvib_cust); + pvib_cust = NULL; + goto out; + } else { + ret = + of_property_read_u32(led_node, "vib_timer", + &(pvib_cust->vib_timer)); + if (!ret) { + VIB_DEBUG + ("The vibrator timer from dts is : %d\n", + pvib_cust->vib_timer); + } else { + pvib_cust->vib_timer = 25; + } +#ifdef CUST_VIBR_LIMIT + ret = + of_property_read_u32(led_node, "vib_limit", + &(pvib_cust->vib_limit)); + if (!ret) { + VIB_DEBUG + ("The vibrator limit from dts is : %d\n", + pvib_cust->vib_limit); + } else { + pvib_cust->vib_limit = 9; + } +#endif + +#ifdef CUST_VIBR_VOL + ret = + of_property_read_u32(led_node, "vib_vol", + &(pvib_cust->vib_vol)); + if (!ret) { + VIB_DEBUG("The vibrator vol from dts is : %d\n", + pvib_cust->vib_vol); + } else { + pvib_cust->vib_vol = 0x05; + } +#endif + } + } + + out: + return pvib_cust; +} + +void vibr_power_set(void) +{ +#ifdef CUST_VIBR_VOL + struct vibrator_hw *hw = get_cust_vibrator_dtsi(); + + VIB_DEBUG("vibr_init: vibrator set voltage = %d\n", hw->vib_vol); +#ifdef CONFIG_MTK_PMIC_CHIP_MT6353 + pmic_set_register_value(PMIC_RG_VIBR_VOSEL, hw->vib_vol); +#else + pmic_set_register_value(MT6351_PMIC_RG_VIBR_VOSEL, hw->vib_vol); +#endif +#endif +} + +struct vibrator_hw *mt_get_cust_vibrator_hw(void) +{ + struct vibrator_hw *hw = get_cust_vibrator_dtsi(); + return hw; +} diff --git a/drivers/misc/mediatek/vibrator/mt6755/vibrator.h b/drivers/misc/mediatek/vibrator/mt6755/vibrator.h new file mode 100644 index 0000000000000000000000000000000000000000..a3dfad741172b68e30daa10c4188bbf5206d447f --- /dev/null +++ b/drivers/misc/mediatek/vibrator/mt6755/vibrator.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __CUST_VIBRATOR_H__ +#define __CUST_VIBRATOR_H__ + + +#define CUST_VIBR_LIMIT +#define CUST_VIBR_VOL + +enum vib_strength { + VOL_1_2 = 0, + VOL_1_3, + VOL_1_5, + VOL_1_8, + VOL_2_0, + VOL_2_8, + VOL_3_0, + VOL_3_3, +}; + +struct vibrator_hw { + int vib_timer; +#ifdef CUST_VIBR_LIMIT + int vib_limit; +#endif +#ifdef CUST_VIBR_VOL + int vib_vol; +#endif +}; + +#endif diff --git a/drivers/misc/mediatek/vibrator/mt6755/vibrator_hal.h b/drivers/misc/mediatek/vibrator/mt6755/vibrator_hal.h new file mode 100644 index 0000000000000000000000000000000000000000..75bec369a6d34e805bb25bc8557c847a6e6e166d --- /dev/null +++ b/drivers/misc/mediatek/vibrator/mt6755/vibrator_hal.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/********************************************* +HAL API +**********************************************/ + +void vibr_Enable_HW(void); +void vibr_Disable_HW(void); +void vibr_power_set(void); +struct vibrator_hw *mt_get_cust_vibrator_hw(void); diff --git a/drivers/misc/mediatek/video/mt6755/Makefile b/drivers/misc/mediatek/video/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2c9e73ab69fceacf2fd349a6334a2165992a86ea --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/Makefile @@ -0,0 +1,98 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += ddp_ovl.o \ + ddp_rdma.o \ + ddp_wdma.o \ + ddp_dsi.o \ + ddp_dpi.o \ + ddp_clkmgr.o \ + ddp_drv.o \ + ddp_path.o \ + ddp_dump.o \ + ddp_manager.o \ + ddp_irq.o \ + ddp_info.o \ + ddp_color_format.o \ + ddp_pwm_mux.o \ + ddp_mmp.o \ + ddp_met.o \ + mtkfb_console.o \ + disp_assert_layer.o \ + mtkfb.o \ + disp_debug.o \ + primary_display.o \ + disp_lowpower.o \ + disp_recovery.o \ + disp_lcm.o \ + disp_utils.o \ + mtk_disp_mgr.o \ + mtk_ovl.o \ + compat_mtk_disp_mgr.o \ + mtk_mira.o \ + disp_helper.o \ + disp_dts_gpio.o + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/video/include/ \ + -I$(srctree)/drivers/misc/mediatek/video/common/ \ + -I$(srctree)/drivers/misc/mediatek/video/common/rdma10/ \ + -I$(srctree)/drivers/misc/mediatek/video/common/wdma10/ \ + -I$(srctree)/drivers/misc/mediatek/video/$(MTK_PLATFORM)/ \ + -I$(srctree)/drivers/misc/mediatek/sync/ \ + -I$(srctree)/drivers/misc/mediatek/m4u/$(MTK_PLATFORM) \ + -I$(srctree)/drivers/misc/mediatek/cmdq/v2/ \ + -I$(srctree)/drivers/misc/mediatek/cmdq/v2/$(MTK_PLATFORM)/ \ + -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/mach/ \ + -I$(srctree)/drivers/staging/android/ion/ \ + -I$(srctree)/drivers/staging/android/ion/mtk/ \ + -I$(srctree)/drivers/misc/mediatek/ext_disp/ \ + -I$(srctree)/drivers/misc/mediatek/ext_disp/v1/ \ + -I$(srctree)/drivers/misc/mediatek/ext_disp/$(MTK_PLATFORM)/ \ + -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/ \ + -I$(srctree)/drivers/misc/mediatek/base/power/include/ \ + -I$(srctree)/drivers/misc/mediatek/m4u/$(MTK_PLATFORM)/ \ + -I$(srctree)/drivers/misc/mediatek/include/mt-plat \ + -I$(srctree)/drivers/misc/mediatek/mmp/ + +ccflags-$(CONFIG_MTK_LCM) += -I$(srctree)/drivers/misc/mediatek/lcm/inc/ + +ifeq ($(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT),y) +ifeq ($(CONFIG_TRUSTONIC_TEE_SUPPORT),y) +include $(srctree)/drivers/misc/mediatek/gud/Makefile.include +ccflags-y += \ + -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/trustzone/tplay/Tltplay/public/ + +endif +endif + +ifeq ($(CONFIG_MTK_INTERNAL_HDMI_SUPPORT), y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/hdmi/ +endif +ifeq ($(CONFIG_MTK_INTERNAL_MHL_SUPPORT), y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/mhltx/ +endif +ifeq ($(CONFIG_MTK_DITHERING_SUPPORT), y) +ccflags-y += -DDITHERING_SUPPORT +endif + +ifeq ($(CONFIG_MTK_GPU_SUPPORT), y) +ccflags-y += -DHWGPU_SUPPORT +endif + +ifeq ($(CONFIG_MMPROFILE),y) +ccflags-y += -DDEFAULT_MMP_ENABLE +endif + +ccflags-y += -DMET_USER_EVENT_SUPPORT + +#ccflags-y += -DDEBUG diff --git a/drivers/misc/mediatek/video/mt6755/compat_mtk_disp_mgr.c b/drivers/misc/mediatek/video/mt6755/compat_mtk_disp_mgr.c new file mode 100644 index 0000000000000000000000000000000000000000..e401029e766dce67dc8182a89ed59ac16692f8c4 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/compat_mtk_disp_mgr.c @@ -0,0 +1,1360 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "compat_mtk_disp_mgr.h" + +#include "disp_log.h" +#include "disp_debug.h" +#include "mtkfb_debug.h" +#include "primary_display.h" +#include "disp_recorder.h" +#include "mtkfb_fence.h" +#include "disp_drv_platform.h" + + +#ifdef CONFIG_COMPAT +static int compat_get_disp_caps_info( + struct compat_disp_caps_info __user *data32, + disp_caps_info __user *data) +{ + compat_uint_t u; + int err = 0; + + err = get_user(u, &(data32->output_mode)); + err |= put_user(u, &(data->output_mode)); + + err |= get_user(u, &(data32->output_pass)); + err |= put_user(u, &(data->output_pass)); + + err |= get_user(u, &(data32->max_layer_num)); + err |= put_user(u, &(data->max_layer_num)); + +#ifdef CONFIG_FOR_SOURCE_PQ + err |= get_user(u, &(data32->max_pq_num)); + err |= put_user(u, &(data->max_pq_num)); +#endif + + err |= get_user(u, &(data32->disp_feature)); + err |= put_user(u, &(data->disp_feature)); + + err |= get_user(u, &(data32->is_support_frame_cfg_ioctl)); + err |= put_user(u, &(data->is_support_frame_cfg_ioctl)); + + err |= get_user(u, &(data32->is_output_rotated)); + err |= put_user(u, &(data->is_output_rotated)); + + return err; +} + +static int compat_put_disp_caps_info( + struct compat_disp_caps_info __user *data32, + disp_caps_info __user *data) +{ + compat_uint_t u; + int err = 0; + + err = get_user(u, &(data->output_mode)); + err |= put_user(u, &(data32->output_mode)); + + err |= get_user(u, &(data->output_pass)); + err |= put_user(u, &(data32->output_pass)); + + err |= get_user(u, &(data->max_layer_num)); + err |= put_user(u, &(data32->max_layer_num)); + +#ifdef CONFIG_FOR_SOURCE_PQ + err |= get_user(u, &(data->max_pq_num)); + err |= put_user(u, &(data32->max_pq_num)); +#endif + + err |= get_user(u, &(data->disp_feature)); + err |= put_user(u, &(data32->disp_feature)); + + err |= get_user(u, &(data->is_support_frame_cfg_ioctl)); + err |= put_user(u, &(data32->is_support_frame_cfg_ioctl)); + + err |= get_user(u, &(data->is_output_rotated)); + err |= put_user(u, &(data32->is_output_rotated)); + + return err; +} + +/* +static int compat_get_disp_session_layer_num_config( + struct compat_disp_session_layer_num_config __user *data32, + disp_session_layer_num_config __user *data) +{ + compat_uint_t u; + int err = 0; + + err = get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + + err |= get_user(u, &(data32->max_layer_num)); + err |= put_user(u, &(data->max_layer_num)); + + return err; +} + +static int compat_put_disp_session_layer_num_config( + struct compat_disp_session_layer_num_config __user *data32, + disp_session_layer_num_config __user *data) +{ + compat_uint_t u; + int err = 0; + + err = get_user(u, &(data->session_id)); + err |= put_user(u, &(data32->session_id)); + + err |= get_user(u, &(data->max_layer_num)); + err |= put_user(u, &(data32->max_layer_num)); + + return err; +} +*/ +static int compat_get_disp_output_config(struct compat_disp_output_config __user *data32, + disp_output_config __user *data) +{ + compat_uint_t u; + compat_uptr_t p; + unsigned long ptr; + int err = 0; + + err |= get_user(p, &(data32->va)); + ptr = p; + err |= put_user((void *)ptr, &(data->va)); + + err |= get_user(p, &(data32->pa)); + ptr = p; + err |= put_user((void *)ptr, &(data->pa)); + + err |= get_user(u, &(data32->fmt)); + err |= put_user(u, &(data->fmt)); + + err |= get_user(u, &(data32->x)); + err |= put_user(u, &(data->x)); + + err |= get_user(u, &(data32->y)); + err |= put_user(u, &(data->y)); + + err |= get_user(u, &(data32->width)); + err |= put_user(u, &(data->width)); + + err |= get_user(u, &(data32->height)); + err |= put_user(u, &(data->height)); + + err |= get_user(u, &(data32->pitch)); + err |= put_user(u, &(data->pitch)); + + err |= get_user(u, &(data32->pitchUV)); + err |= put_user(u, &(data->pitchUV)); + + err |= get_user(u, &(data32->security)); + err |= put_user(u, &(data->security)); + + err |= get_user(u, &(data32->buff_idx)); + err |= put_user(u, &(data->buff_idx)); + + err |= get_user(u, &(data32->interface_idx)); + err |= put_user(u, &(data->interface_idx)); + + err |= get_user(u, &(data32->frm_sequence)); + err |= put_user(u, &(data->frm_sequence)); + + return err; +} +#if 0 +static int compat_put_disp_output_config(struct compat_disp_output_config __user *data32, + disp_output_config __user *data) +{ + compat_uint_t u; + compat_uptr_t p; + int err = 0; + + err |= get_user(p, &(data->va)); + err |= put_user(p, &(data32->va)); + + err |= get_user(p, &(data->pa)); + err |= put_user(p, &(data32->pa)); + + err |= get_user(u, &(data->fmt)); + err |= put_user(u, &(data32->fmt)); + + err |= get_user(u, &(data->x)); + err |= put_user(u, &(data32->x)); + + err |= get_user(u, &(data->y)); + err |= put_user(u, &(data32->y)); + + err |= get_user(u, &(data->width)); + err |= put_user(u, &(data32->width)); + + err |= get_user(u, &(data->height)); + err |= put_user(u, &(data32->height)); + + err |= get_user(u, &(data->pitch)); + err |= put_user(u, &(data32->pitch)); + + err |= get_user(u, &(data->pitchUV)); + err |= put_user(u, &(data32->pitchUV)); + + err |= get_user(u, &(data->security)); + err |= put_user(u, &(data32->security)); + + err |= get_user(u, &(data->buff_idx)); + err |= put_user(u, &(data32->buff_idx)); + + err |= get_user(u, &(data->interface_idx)); + err |= put_user(u, &(data32->interface_idx)); + + err |= get_user(u, &(data->frm_sequence)); + err |= put_user(u, &(data32->frm_sequence)); + + return err; +} +#endif +static int compat_get_disp_session_output_config(struct compat_disp_session_output_config __user *data32, + disp_session_output_config __user *data) +{ + compat_uint_t u; + int err = 0; + + err = get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + err |= compat_get_disp_output_config(&data32->config, &data->config); + + return err; +} +#if 0 +static int compat_put_disp_session_output_config(struct compat_disp_session_output_config __user *data32, + disp_session_output_config __user *data) +{ + compat_uint_t u; + int err = 0; + + err = get_user(u, &(data->session_id)); + err |= put_user(u, &(data32->session_id)); + err |= compat_put_disp_output_config(&data32->config, &data->config); + + return err; +} +#endif +static int compat_get_disp_input_config(struct compat_disp_input_config __user *data32, + disp_input_config __user *data) +{ + compat_uint_t u; + compat_uptr_t p; + compat_ushort_t s; + uint8_t c; + unsigned long ptr; + int err = 0; + + err |= get_user(p, &(data32->src_base_addr)); + ptr = p; + err |= put_user((void *)ptr, &(data->src_base_addr)); + + err |= get_user(p, &(data32->src_phy_addr)); + ptr = p; + err |= put_user((void *)ptr, &(data->src_phy_addr)); + + err |= get_user(u, &(data32->buffer_source)); + err |= put_user(u, &(data->buffer_source)); + + err |= get_user(u, &(data32->security)); + err |= put_user(u, &(data->security)); + + err |= get_user(u, &(data32->src_fmt)); + err |= put_user(u, &(data->src_fmt)); + + err |= get_user(u, &(data32->src_alpha)); + err |= put_user(u, &(data->src_alpha)); + + err |= get_user(u, &(data32->dst_alpha)); + err |= put_user(u, &(data->dst_alpha)); + + err |= get_user(u, &(data32->yuv_range)); + err |= put_user(u, &(data->yuv_range)); + + err |= get_user(u, &(data32->layer_rotation)); + err |= put_user(u, &(data->layer_rotation)); + + err |= get_user(u, &(data32->layer_type)); + err |= put_user(u, &(data->layer_type)); + + err |= get_user(u, &(data32->video_rotation)); + err |= put_user(u, &(data->video_rotation)); + + err |= get_user(u, &(data32->next_buff_idx)); + err |= put_user(u, &(data->next_buff_idx)); + + err |= get_user(u, &(data32->src_color_key)); + err |= put_user(u, &(data->src_color_key)); + + err |= get_user(u, &(data32->frm_sequence)); + err |= put_user(u, &(data->frm_sequence)); + + err |= get_user(p, &(data32->dirty_roi_addr)); + ptr = p; + err |= put_user((void *)ptr, &(data->dirty_roi_addr)); + + err |= get_user(s, &(data32->dirty_roi_num)); + err |= put_user(s, &(data->dirty_roi_num)); + + err |= get_user(s, &(data32->src_pitch)); + err |= put_user(s, &(data->src_pitch)); + + err |= get_user(s, &(data32->src_offset_x)); + err |= put_user(s, &(data->src_offset_x)); + + err |= get_user(s, &(data32->src_offset_y)); + err |= put_user(s, &(data->src_offset_y)); + + err |= get_user(s, &(data32->src_width)); + err |= put_user(s, &(data->src_width)); + + err |= get_user(s, &(data32->src_height)); + err |= put_user(s, &(data->src_height)); + + err |= get_user(s, &(data32->tgt_offset_x)); + err |= put_user(s, &(data->tgt_offset_x)); + + err |= get_user(s, &(data32->tgt_offset_y)); + err |= put_user(s, &(data->tgt_offset_y)); + + err |= get_user(s, &(data32->tgt_width)); + err |= put_user(s, &(data->tgt_width)); + + err |= get_user(s, &(data32->tgt_height)); + err |= put_user(s, &(data->tgt_height)); + + err |= get_user(c, &(data32->alpha_enable)); + err |= put_user(c, &(data->alpha_enable)); + + err |= get_user(c, &(data32->alpha)); + err |= put_user(c, &(data->alpha)); + + err |= get_user(c, &(data32->sur_aen)); + err |= put_user(c, &(data->sur_aen)); + + err |= get_user(c, &(data32->src_use_color_key)); + err |= put_user(c, &(data->src_use_color_key)); + + err |= get_user(c, &(data32->layer_id)); + err |= put_user(c, &(data->layer_id)); + + err |= get_user(c, &(data32->layer_enable)); + err |= put_user(c, &(data->layer_enable)); + + err |= get_user(c, &(data32->src_direct_link)); + err |= put_user(c, &(data->src_direct_link)); + + err |= get_user(c, &(data32->identity)); + err |= put_user(c, &(data->identity)); + + err |= get_user(c, &(data32->connected_type)); + err |= put_user(c, &(data->connected_type)); + + err |= get_user(c, &(data32->isTdshp)); + err |= put_user(c, &(data->isTdshp)); + + return err; +} + +static int compat_get_disp_session_input_config( + struct compat_disp_session_input_config __user *data32, + disp_session_input_config __user *data) +{ + compat_uint_t u; + compat_long_t l; + int err; + int j; + + err = get_user(u, &(data32->setter)); + err |= put_user(u, &(data->setter)); + + err |= get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + + err |= get_user(l, &(data32->config_layer_num)); + err |= put_user(l, &(data->config_layer_num)); + + for (j = 0; j < ARRAY_SIZE(data32->config); j++) + err |= compat_get_disp_input_config(&data32->config[j], &data->config[j]); + + return err; +} +#if 0 +static int compat_put_disp_input_config(struct compat_disp_input_config __user *data32, + disp_input_config __user *data) +{ + compat_uint_t u; + compat_int_t i; + compat_uptr_t p; + int err = 0; + + err |= get_user(u, &(data->layer_id)); + err |= put_user(u, &(data32->layer_id)); + + err |= get_user(u, &(data->layer_enable)); + err |= put_user(u, &(data32->layer_enable)); + + err |= get_user(u, &(data->buffer_source)); + err |= put_user(u, &(data32->buffer_source)); + + err |= get_user(p, &(data->src_base_addr)); + err |= put_user(p, &(data32->src_base_addr)); + + err |= get_user(p, &(data->src_phy_addr)); + err |= put_user(p, &(data32->src_phy_addr)); + + err |= get_user(u, &(data->src_direct_link)); + err |= put_user(u, &(data32->src_direct_link)); + + err |= get_user(u, &(data->src_fmt)); + err |= put_user(u, &(data32->src_fmt)); + + err |= get_user(u, &(data->src_use_color_key)); + err |= put_user(u, &(data32->src_use_color_key)); + + err |= get_user(u, &(data->src_pitch)); + err |= put_user(u, &(data32->src_pitch)); + + err |= get_user(u, &(data->src_offset_x)); + err |= put_user(u, &(data32->src_offset_x)); + + err |= get_user(u, &(data->src_offset_y)); + err |= put_user(u, &(data32->src_offset_y)); + + err |= get_user(u, &(data->src_width)); + err |= put_user(u, &(data32->src_width)); + + err |= get_user(u, &(data->src_height)); + err |= put_user(u, &(data32->src_height)); + + err |= get_user(u, &(data->tgt_offset_x)); + err |= put_user(u, &(data32->tgt_offset_x)); + + err |= get_user(u, &(data->tgt_offset_y)); + err |= put_user(u, &(data32->tgt_offset_y)); + + err |= get_user(u, &(data->tgt_width)); + err |= put_user(u, &(data32->tgt_width)); + + err |= get_user(u, &(data->tgt_height)); + err |= put_user(u, &(data32->tgt_height)); + + err |= get_user(u, &(data->layer_rotation)); + err |= put_user(u, &(data32->layer_rotation)); + + err |= get_user(u, &(data->layer_type)); + err |= put_user(u, &(data32->layer_type)); + + err |= get_user(u, &(data->video_rotation)); + err |= put_user(u, &(data32->video_rotation)); + + err |= get_user(u, &(data->isTdshp)); + err |= put_user(u, &(data32->isTdshp)); + + err |= get_user(u, &(data->next_buff_idx)); + err |= put_user(u, &(data32->next_buff_idx)); + + err |= get_user(i, &(data->identity)); + err |= put_user(i, &(data32->identity)); + + err |= get_user(i, &(data->connected_type)); + err |= put_user(i, &(data32->connected_type)); + + err |= get_user(u, &(data->security)); + err |= put_user(u, &(data32->security)); + + err |= get_user(u, &(data->alpha_enable)); + err |= put_user(u, &(data32->alpha_enable)); + + err |= get_user(u, &(data->alpha)); + err |= put_user(u, &(data32->alpha)); + + err |= get_user(u, &(data->sur_aen)); + err |= put_user(u, &(data32->sur_aen)); + + err |= get_user(u, &(data->src_alpha)); + err |= put_user(u, &(data32->src_alpha)); + + err |= get_user(u, &(data->dst_alpha)); + err |= put_user(u, &(data32->dst_alpha)); + + err |= get_user(i, &(data->frm_sequence)); + err |= put_user(i, &(data32->frm_sequence)); + + err |= get_user(u, &(data->yuv_range)); + err |= put_user(u, &(data32->yuv_range)); + + return err; +} + +static int compat_put_disp_session_input_config( + struct compat_disp_session_input_config __user *data32, + disp_session_input_config __user *data) +{ + compat_uint_t u; + compat_long_t l; + int err; + int j; + + err = get_user(u, &(data->setter)); + err |= put_user(u, &(data32->setter)); + + err |= get_user(u, &(data->session_id)); + err |= put_user(u, &(data32->session_id)); + + err |= get_user(l, &(data->config_layer_num)); + err |= put_user(l, &(data32->config_layer_num)); + + for (j = 0; j < ARRAY_SIZE(data32->config); j++) + err |= compat_put_disp_input_config(&data32->config[j], &data->config[j]); + + return err; +} +#endif +static int compat_get_disp_session_vsync_config( + struct compat_disp_session_vsync_config __user *data32, + disp_session_vsync_config __user *data) +{ + compat_uint_t u; + compat_u64 u64; + int err; + + err = get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + + err |= get_user(u, &(data32->vsync_cnt)); + err |= put_user(u, &(data->vsync_cnt)); + + err |= get_user(u64, &(data32->vsync_ts)); + err |= put_user(u64, &(data->vsync_ts)); + + err |= get_user(u, &(data32->lcm_fps)); + err |= put_user(u, &(data->lcm_fps)); + + return err; +} + +static int compat_put_disp_session_vsync_config( + struct compat_disp_session_vsync_config __user *data32, + disp_session_vsync_config __user *data) +{ + compat_uint_t u; + compat_u64 u64; + int err; + + err = get_user(u, &(data->session_id)); + err |= put_user(u, &(data32->session_id)); + + err |= get_user(u, &(data->vsync_cnt)); + err |= put_user(u, &(data32->vsync_cnt)); + + err |= get_user(u64, &(data->vsync_ts)); + err |= put_user(u64, &(data32->vsync_ts)); + + err |= get_user(u, &(data->lcm_fps)); + err |= put_user(u, &(data32->lcm_fps)); + + return err; +} + + +static int compat_get_disp_session_info( + struct compat_disp_session_info __user *data32, + disp_session_info __user *data) +{ + compat_uint_t u; + compat_int_t i; + int err; + + err = get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + + err |= get_user(u, &(data32->maxLayerNum)); + err |= put_user(u, &(data->maxLayerNum)); + + err |= get_user(u, &(data32->isHwVsyncAvailable)); + err |= put_user(u, &(data->isHwVsyncAvailable)); + + err |= get_user(i, &(data32->displayType)); + err |= put_user(i, &(data->displayType)); + + err |= get_user(u, &(data32->displayWidth)); + err |= put_user(u, &(data->displayWidth)); + + err |= get_user(u, &(data32->displayHeight)); + err |= put_user(u, &(data->displayHeight)); + + err |= get_user(i, &(data32->displayFormat)); + err |= put_user(i, &(data->displayFormat)); + + err |= get_user(u, &(data32->displayMode)); + err |= put_user(u, &(data->displayMode)); + + err |= get_user(i, &(data32->vsyncFPS)); + err |= put_user(i, &(data->vsyncFPS)); + + err |= get_user(u, &(data32->physicalWidth)); + err |= put_user(u, &(data->physicalWidth)); + + err |= get_user(i, &(data32->physicalHeight)); + err |= put_user(i, &(data->physicalHeight)); + + + err |= get_user(i, &(data32->isConnected)); + err |= put_user(i, &(data->isConnected)); + + err |= get_user(u, &(data32->isHDCPSupported)); + err |= put_user(u, &(data->isHDCPSupported)); + + err |= get_user(i, &(data32->isOVLDisabled)); + err |= put_user(i, &(data->isOVLDisabled)); + + err |= get_user(i, &(data32->is3DSupport)); + err |= put_user(i, &(data->is3DSupport)); + + err |= get_user(u, &(data32->const_layer_num)); + err |= put_user(u, &(data->const_layer_num)); + + return err; + +} + +static int compat_put_disp_session_info( + struct compat_disp_session_info __user *data32, + disp_session_info __user *data) +{ + compat_uint_t u; + compat_int_t i; + int err; + + err = get_user(u, &(data->session_id)); + err |= put_user(u, &(data32->session_id)); + + err |= get_user(u, &(data->maxLayerNum)); + err |= put_user(u, &(data32->maxLayerNum)); + + err |= get_user(u, &(data->isHwVsyncAvailable)); + err |= put_user(u, &(data32->isHwVsyncAvailable)); + + err |= get_user(i, &(data->displayType)); + err |= put_user(i, &(data32->displayType)); + + err |= get_user(u, &(data->displayWidth)); + err |= put_user(u, &(data32->displayWidth)); + + err |= get_user(u, &(data->displayHeight)); + err |= put_user(u, &(data32->displayHeight)); + + err |= get_user(i, &(data->displayFormat)); + err |= put_user(i, &(data32->displayFormat)); + + err |= get_user(u, &(data->displayMode)); + err |= put_user(u, &(data32->displayMode)); + + err |= get_user(i, &(data->vsyncFPS)); + err |= put_user(i, &(data32->vsyncFPS)); + + err |= get_user(u, &(data->physicalWidth)); + err |= put_user(u, &(data32->physicalWidth)); + + err |= get_user(i, &(data->physicalHeight)); + err |= put_user(i, &(data32->physicalHeight)); + + + err |= get_user(i, &(data->isConnected)); + err |= put_user(i, &(data32->isConnected)); + + err |= get_user(u, &(data->isHDCPSupported)); + err |= put_user(u, &(data32->isHDCPSupported)); + + err |= get_user(i, &(data->isOVLDisabled)); + err |= put_user(i, &(data32->isOVLDisabled)); + + err |= get_user(i, &(data->is3DSupport)); + err |= put_user(i, &(data32->is3DSupport)); + return err; + +} + +static int compat_get_disp_buffer_info( + struct compat_disp_buffer_info __user *data32, + disp_buffer_info __user *data) +{ + compat_uint_t u; + compat_int_t i; + int err; + + err = get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + + err |= get_user(u, &(data32->layer_id)); + err |= put_user(u, &(data->layer_id)); + + err |= get_user(u, &(data32->layer_en)); + err |= put_user(u, &(data->layer_en)); + + err |= get_user(i, &(data32->ion_fd)); + err |= put_user(i, &(data->ion_fd)); + + err |= get_user(u, &(data32->cache_sync)); + err |= put_user(u, &(data->cache_sync)); + + err |= get_user(u, &(data32->index)); + err |= put_user(u, &(data->index)); + + err |= get_user(i, &(data32->fence_fd)); + err |= put_user(i, &(data->fence_fd)); + + err |= get_user(u, &(data32->interface_index)); + err |= put_user(u, &(data->interface_index)); + + err |= get_user(i, &(data32->interface_fence_fd)); + err |= put_user(i, &(data->interface_fence_fd)); + + return err; + +} + +static int compat_put_disp_buffer_info( + struct compat_disp_buffer_info __user *data32, + disp_buffer_info __user *data) +{ + compat_uint_t u; + compat_int_t i; + int err; + + err = get_user(u, &(data->session_id)); + err |= put_user(u, &(data32->session_id)); + + err |= get_user(u, &(data->layer_id)); + err |= put_user(u, &(data32->layer_id)); + + err |= get_user(u, &(data->layer_en)); + err |= put_user(u, &(data32->layer_en)); + + err |= get_user(i, &(data->ion_fd)); + err |= put_user(i, &(data32->ion_fd)); + + err |= get_user(u, &(data->cache_sync)); + err |= put_user(u, &(data32->cache_sync)); + + err |= get_user(u, &(data->index)); + err |= put_user(u, &(data32->index)); + + err |= get_user(i, &(data->fence_fd)); + err |= put_user(i, &(data32->fence_fd)); + + err |= get_user(u, &(data->interface_index)); + err |= put_user(u, &(data32->interface_index)); + + err |= get_user(i, &(data->interface_fence_fd)); + err |= put_user(i, &(data32->interface_fence_fd)); + + return err; + +} + +static int compat_get_disp_present_fence(struct compat_disp_present_fence __user *data32, + disp_present_fence __user *data) +{ + compat_uint_t u; + int err; + + err = get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + + err |= get_user(u, &(data32->present_fence_fd)); + err |= put_user(u, &(data->present_fence_fd)); + + err |= get_user(u, &(data32->present_fence_index)); + err |= put_user(u, &(data->present_fence_index)); + + return err; +} + + +static int compat_put_disp_present_fence( + struct compat_disp_present_fence __user *data32, + disp_present_fence __user *data) +{ + compat_uint_t u; + int err; + + err = get_user(u, &(data->session_id)); + err |= put_user(u, &(data32->session_id)); + + err |= get_user(u, &(data->present_fence_fd)); + err |= put_user(u, &(data32->present_fence_fd)); + + err |= get_user(u, &(data->present_fence_index)); + err |= put_user(u, &(data32->present_fence_index)); + + return err; +} + + +static int compat_get_disp_session_config( + struct compat_disp_session_config __user *data32, + disp_session_config __user *data) +{ + + compat_uint_t u; + compat_int_t i; + int err; + + err = get_user(u, &(data32->type)); + err |= put_user(u, &(data->type)); + + err |= get_user(u, &(data32->device_id)); + err |= put_user(u, &(data->device_id)); + + err |= get_user(u, &(data32->mode)); + err |= put_user(u, &(data->mode)); + + err |= get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + + err |= get_user(u, &(data32->user)); + err |= put_user(u, &(data->user)); + + err |= get_user(u, &(data32->present_fence_idx)); + err |= put_user(u, &(data->present_fence_idx)); + + err |= get_user(u, &(data32->dc_type)); + err |= put_user(u, &(data->dc_type)); + + err |= get_user(i, &(data32->need_merge)); + err |= put_user(i, &(data->need_merge)); + + return err; + +} + +static int compat_put_disp_session_config( + struct compat_disp_session_config __user *data32, + disp_session_config __user *data) +{ + + compat_uint_t u; + compat_int_t i; + int err; + + err = get_user(u, &(data->type)); + err |= put_user(u, &(data32->type)); + + err |= get_user(u, &(data->device_id)); + err |= put_user(u, &(data32->device_id)); + + err |= get_user(u, &(data->mode)); + err |= put_user(u, &(data32->mode)); + + err |= get_user(u, &(data->session_id)); + err |= put_user(u, &(data32->session_id)); + + err |= get_user(u, &(data->user)); + err |= put_user(u, &(data32->user)); + + err |= get_user(u, &(data->present_fence_idx)); + err |= put_user(u, &(data32->present_fence_idx)); + + err |= get_user(u, &(data->dc_type)); + err |= put_user(u, &(data32->dc_type)); + + err |= get_user(i, &(data->need_merge)); + err |= put_user(i, &(data32->need_merge)); + + return err; +} + +static int compat_get_disp_frame_cfg(struct compat_disp_frame_cfg_t __user *data32, + struct disp_frame_cfg_t __user *data) +{ + compat_uint_t u; + int err; + int j; + + err = get_user(u, &(data32->setter)); + err |= put_user(u, &(data->setter)); + + err |= get_user(u, &(data32->session_id)); + err |= put_user(u, &(data->session_id)); + + err |= get_user(u, &(data32->input_layer_num)); + err |= put_user(u, &(data->input_layer_num)); + + for (j = 0; j < ARRAY_SIZE(data32->input_cfg); j++) + err |= compat_get_disp_input_config(&data32->input_cfg[j], &data->input_cfg[j]); + + err |= get_user(u, &(data32->overlap_layer_num)); + err |= put_user(u, &(data->overlap_layer_num)); + + err |= get_user(u, &(data32->const_layer_num)); + err |= put_user(u, &(data->const_layer_num)); + + for (j = 0; j < ARRAY_SIZE(data32->const_layer); j++) + err |= compat_get_disp_input_config(&data32->const_layer[j], &data->const_layer[j]); + + err |= get_user(u, &(data32->output_en)); + err |= put_user(u, &(data->output_en)); + + err |= compat_get_disp_output_config(&data32->output_cfg, &data->output_cfg); + + err |= get_user(u, &(data32->mode)); + err |= put_user(u, &(data->mode)); + + err |= get_user(u, &(data32->present_fence_idx)); + err |= put_user(u, &(data->present_fence_idx)); + + err |= get_user(u, &(data32->tigger_mode)); + err |= put_user(u, &(data->tigger_mode)); + + err |= get_user(u, &(data32->user)); + err |= put_user(u, &(data->user)); + + return err; +} + + +int _compat_ioctl_create_session(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_session_config __user *data32; + disp_session_config __user *data; + + DISPDBG("COMPAT_DISP_IOCTL_CREATE_SESSION\n"); + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(disp_session_config)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_session_config(data32, data); + if (err) { + DISPERR("compat_get_disp_session_config fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_CREATE_SESSION, (unsigned long)data); + + err = compat_put_disp_session_config(data32, data); + + if (err) { + DISPERR("compat_put_disp_session_config fail!\n"); + return err; + } + return ret; +} + +int _compat_ioctl_destroy_session(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_session_config *data32 __user; + disp_session_config *data __user; + + DISPDBG("COMPAT_DISP_IOCTL_DESTROY_SESSION\n"); + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(disp_session_config)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_session_config(data32, data); + if (err) { + DISPERR("compat_get_disp_session_config fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_DESTROY_SESSION, (unsigned long)data); + + return ret; +} + + +int _compat_ioctl_trigger_session(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_session_config *data32 __user; + + disp_session_config *data __user; + + DISPDBG("COMPAT_DISP_IOCTL_TRIGGER_SESSION\n"); + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(disp_session_config)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_session_config(data32, data); + if (err) { + DISPERR("compat_get_disp_session_config fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_TRIGGER_SESSION, (unsigned long)data); + return ret; +} + + +int _compat_ioctl_prepare_present_fence(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_present_fence *data32 __user; + + disp_present_fence *data __user; + + DISPDBG("COMPAT_DISP_IOCTL_TRIGGER_SESSION\n"); + + data32 = compat_ptr(arg); + + data = compat_alloc_user_space(sizeof(disp_present_fence)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_present_fence(data32, data); + if (err) { + DISPERR("compat_get_disp_present_fence fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_GET_PRESENT_FENCE, (unsigned long)data); + + err = compat_put_disp_present_fence(data32, data); + + if (err) { + DISPERR("compat_put_disp_present_fence fail!\n"); + return err; + } + + return ret; +} + +int _compat_ioctl_get_info(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_session_info *data32 __user; + + disp_session_info *data __user; + + DISPDBG("COMPAT_DISP_IOCTL_GET_INFO\n"); + data32 = compat_ptr(arg); + + data = compat_alloc_user_space(sizeof(disp_session_info)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_session_info(data32, data); + if (err) { + DISPERR("compat_get_disp_session_info fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_GET_SESSION_INFO, (unsigned long)data); + + err = compat_put_disp_session_info(data32, data); + + if (err) { + DISPERR("compat_put_disp_session_info fail!\n"); + return err; + } + + return ret; +} + + +int _compat_ioctl_prepare_buffer(struct file *file, unsigned long arg, ePREPARE_FENCE_TYPE type) +{ + int ret = 0; + int err = 0; + + struct compat_disp_buffer_info *data32 __user; + + disp_buffer_info *data __user; + + DISPDBG("COMPAT_DISP_IOCTL_PREPARE_BUFFER\n"); + data32 = compat_ptr(arg); + + data = compat_alloc_user_space(sizeof(disp_buffer_info)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_buffer_info(data32, data); + if (err) { + DISPERR("compat_get_disp_buffer_info fail!\n"); + return err; + } + + if (PREPARE_INPUT_FENCE == type) + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_PREPARE_INPUT_BUFFER, (unsigned long)data); + else + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_PREPARE_OUTPUT_BUFFER, (unsigned long)data); + + err = compat_put_disp_buffer_info(data32, data); + + if (err) { + DISPERR("compat_put_disp_buffer_info fail!\n"); + return err; + } + + return ret; + +} + + +int _compat_ioctl_wait_vsync(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_session_vsync_config *data32 __user; + + disp_session_vsync_config *data __user; + + DISPDBG("COMPAT_DISP_IOCTL_WAIT_VSYNC\n"); + + data32 = (struct compat_disp_session_vsync_config *)compat_ptr(arg); + + data = compat_alloc_user_space(sizeof(disp_session_vsync_config)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_session_vsync_config(data32, data); + if (err) { + DISPERR("compat_get_disp_buffer_info fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_WAIT_FOR_VSYNC, (unsigned long)data); + + err = compat_put_disp_session_vsync_config(data32, data); + if (err) { + DISPERR("%s put fail!\n", __func__); + return err; + } + + return ret; +} + +int _compat_ioctl_set_input_buffer(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_session_input_config *data32 __user; + + disp_session_input_config *data __user; + DISPDBG("COMPAT_DISP_IOCTL_SET_INPUT_BUFFER\n"); + data32 = (struct compat_disp_session_input_config *)compat_ptr(arg); + data = compat_alloc_user_space(sizeof(disp_session_input_config)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_session_input_config(data32, data); + if (err) { + DISPERR("compat_get_disp_session_input_config fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_SET_INPUT_BUFFER, (unsigned long)data); + return ret; +} + +int _compat_ioctl_get_display_caps(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_caps_info *data32 __user; + + disp_caps_info *data __user; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(disp_caps_info)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + err = compat_get_disp_caps_info(data32, data); + if (err) { + DISPERR("compat_get_disp_caps_info fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_GET_DISPLAY_CAPS, (unsigned long)data); + + err = compat_put_disp_caps_info(data32, data); + + if (err) { + DISPERR("compat_put_disp_caps_info fail!\n"); + return err; + } + + return ret; +} + +int _compat_ioctl_set_vsync(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + int *pdata; + + compat_uint_t *data32 __user; + + unsigned int data __user; + + data32 = compat_ptr(arg); + + if (get_user(data, data32)) { + DISPERR("compat_get_fps fail!\n"); + return err; + } + pdata = &data; + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_SET_VSYNC_FPS, (unsigned long)pdata); + return ret; +} + +int _compat_ioctl_set_session_mode(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + + struct compat_disp_session_config *data32 __user; + disp_session_config *data __user; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(disp_session_config)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_session_config(data32, data); + if (err) { + DISPERR("compat_get_disp_session_config fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_SET_SESSION_MODE, (unsigned long)data); + + return ret; +} + +int _compat_ioctl_set_output_buffer(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + struct compat_disp_session_output_config *data32 __user; + disp_session_output_config *data __user; + + DISPDBG("COMPAT_DISP_IOCTL_SET_OUTPUT_BUFFER\n"); + + data32 = (struct compat_disp_session_output_config *)compat_ptr(arg); + data = compat_alloc_user_space(sizeof(disp_session_output_config)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_session_output_config(data32, data); + if (err) { + DISPERR("compat_get_disp__session_output_config fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_SET_OUTPUT_BUFFER, (unsigned long)data); + + return ret; +} + +int _compat_ioctl_frame_config(struct file *file, unsigned long arg) +{ + int ret = 0; + int err = 0; + struct compat_disp_frame_cfg_t __user *data32; + struct disp_frame_cfg_t __user *data; + + DISPDBG("%s\n", __func__); + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(struct disp_frame_cfg_t)); + + if (data == NULL) { + DISPERR("compat_alloc_user_space fail!\n"); + return -EFAULT; + } + + err = compat_get_disp_frame_cfg(data32, data); + if (err) { + DISPERR("compat_get_disp_frame_cfg fail!\n"); + return err; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_FRAME_CONFIG, (unsigned long)data); + return ret; +} + + +int _compat_ioctl_screen_freeze(struct file *file, unsigned long arg) +{ + int ret = 0; + compat_uint_t __user *data32; + unsigned int data; + + data32 = compat_ptr(arg); + if (get_user(data, data32)) { + pr_err("screen_freeze get_user failed\n"); + ret = -EFAULT; + } + + ret = file->f_op->unlocked_ioctl(file, DISP_IOCTL_SCREEN_FREEZE, (unsigned long)data); + pr_debug("compat screen_freeze ret %d\n", ret); + return ret; +} +#endif diff --git a/drivers/misc/mediatek/video/mt6755/compat_mtk_disp_mgr.h b/drivers/misc/mediatek/video/mt6755/compat_mtk_disp_mgr.h new file mode 100644 index 0000000000000000000000000000000000000000..504c4e6fb89ab0d98a8e562d1baa72f0a41bf6f8 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/compat_mtk_disp_mgr.h @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _COMPAT_MTK_DISP_MGR_H_ +#define _COMPAT_MTK_DISP_MGR_H_ +#include +#include +#include +#include +#include +#include "mtk_disp_mgr.h" + +#include "disp_session.h" + +#ifdef CONFIG_COMPAT + +struct compat_disp_session_config { + compat_uint_t type; + compat_uint_t device_id; + compat_uint_t mode; + compat_uint_t session_id; + compat_uint_t user; + compat_uint_t present_fence_idx; + compat_uint_t dc_type; + compat_int_t need_merge; + compat_int_t tigger_mode; +}; + +struct compat_disp_input_config { + compat_uptr_t src_base_addr; + compat_uptr_t src_phy_addr; + compat_uint_t buffer_source; + compat_uint_t security; + compat_uint_t src_fmt; + compat_uint_t src_alpha; + compat_uint_t dst_alpha; + compat_uint_t yuv_range; + + compat_uint_t layer_rotation; + compat_uint_t layer_type; + compat_uint_t video_rotation; + + compat_uint_t next_buff_idx; + + compat_uint_t src_color_key; + compat_uint_t frm_sequence; + + compat_uptr_t dirty_roi_addr; + compat_ushort_t dirty_roi_num; + + compat_ushort_t src_pitch; + compat_ushort_t src_offset_x, src_offset_y; + compat_ushort_t src_width, src_height; + compat_ushort_t tgt_offset_x, tgt_offset_y; + compat_ushort_t tgt_width, tgt_height; + + u8 alpha_enable; + u8 alpha; + u8 sur_aen; + u8 src_use_color_key; + u8 layer_id; + u8 layer_enable; + + u8 src_direct_link; + u8 isTdshp; + u8 identity; + u8 connected_type; +}; + +struct compat_disp_output_config { + compat_uptr_t va; + compat_uptr_t pa; + compat_uint_t fmt; + compat_uint_t x; + compat_uint_t y; + compat_uint_t width; + compat_uint_t height; + compat_uint_t pitch; + compat_uint_t pitchUV; + compat_uint_t security; + compat_uint_t buff_idx; + compat_uint_t interface_idx; + compat_uint_t frm_sequence; +}; + +struct compat_disp_session_input_config { + compat_uint_t setter; + compat_uint_t session_id; + compat_uint_t config_layer_num; + struct compat_disp_input_config config[8]; +}; + +struct compat_disp_present_fence { + + compat_uint_t session_id; + compat_uint_t present_fence_fd; + compat_uint_t present_fence_index; +}; + +struct compat_disp_session_vsync_config { + compat_uint_t session_id; + compat_uint_t vsync_cnt; + compat_u64 vsync_ts; + compat_uint_t lcm_fps; +}; + +struct compat_disp_session_layer_num_config { + compat_uint_t session_id; + compat_uint_t max_layer_num; +}; + +struct compat_disp_caps_info { + compat_uint_t output_mode; + compat_uint_t output_pass; + compat_uint_t max_layer_num; +#ifdef CONFIG_FOR_SOURCE_PQ + compat_uint_t max_pq_num; +#endif + compat_uint_t disp_feature; + compat_uint_t is_support_frame_cfg_ioctl; + compat_uint_t is_output_rotated; +}; + +struct compat_disp_buffer_info { + + compat_uint_t session_id; + + compat_uint_t layer_id; + compat_uint_t layer_en; + compat_int_t ion_fd; + compat_uint_t cache_sync; + compat_uint_t index; + compat_int_t fence_fd; + compat_uint_t interface_index; + compat_int_t interface_fence_fd; +}; +struct compat_disp_session_output_config { + compat_uint_t session_id; + struct compat_disp_output_config config; +}; + +struct compat_disp_frame_cfg_t { + compat_uint_t setter; + compat_uint_t session_id; + + /* input config */ + compat_uint_t input_layer_num; + struct compat_disp_input_config input_cfg[8]; + compat_uint_t overlap_layer_num; + + /* constant layer */ + compat_uint_t const_layer_num; + struct compat_disp_input_config const_layer[1]; + + /* output config */ + compat_int_t output_en; + struct compat_disp_output_config output_cfg; + + /* trigger config */ + compat_uint_t mode; + compat_uint_t present_fence_idx; + compat_uint_t tigger_mode; + compat_uint_t user; +}; + +struct compat_disp_session_info { + compat_uint_t session_id; + compat_uint_t maxLayerNum; + compat_uint_t isHwVsyncAvailable; + compat_uint_t displayType; + compat_uint_t displayWidth; + compat_uint_t displayHeight; + compat_uint_t displayFormat; + compat_uint_t displayMode; + compat_uint_t vsyncFPS; + compat_uint_t physicalWidth; + compat_uint_t physicalHeight; + compat_uint_t isConnected; + compat_uint_t isHDCPSupported; + compat_uint_t isOVLDisabled; + compat_uint_t is3DSupport; + compat_uint_t const_layer_num; + /* updateFPS: fps of HWC trigger display */ + /* notes: for better Accuracy, updateFPS = real_fps*100 */ + compat_uint_t updateFPS; + compat_uint_t is_updateFPS_stable; +}; + +int _compat_ioctl_prepare_present_fence(struct file *file, unsigned long arg); +int _compat_ioctl_trigger_session(struct file *file, unsigned long arg); +int _compat_ioctl_destroy_session(struct file *file, unsigned long arg); +int _compat_ioctl_create_session(struct file *file, unsigned long arg); +int _compat_ioctl_get_info(struct file *file, unsigned long arg); +int _compat_ioctl_prepare_buffer(struct file *file, unsigned long arg, ePREPARE_FENCE_TYPE type); +int _compat_ioctl_wait_vsync(struct file *file, unsigned long arg); +int _compat_ioctl_set_input_buffer(struct file *file, unsigned long arg); +int _compat_ioctl_get_display_caps(struct file *file, unsigned long arg); +int _compat_ioctl_set_vsync(struct file *file, unsigned long arg); +int _compat_ioctl_set_output_buffer(struct file *file, unsigned long arg); +int _compat_ioctl_set_session_mode(struct file *file, unsigned long arg); +int _compat_ioctl_frame_config(struct file *file, unsigned long arg); +int _compat_ioctl_screen_freeze(struct file *file, unsigned long arg); + +#define COMPAT_DISP_IOCTL_CREATE_SESSION DISP_IOW(201, struct compat_disp_session_config) +#define COMPAT_DISP_IOCTL_DESTROY_SESSION DISP_IOW(202, struct compat_disp_session_config) +#define COMPAT_DISP_IOCTL_TRIGGER_SESSION DISP_IOW(203, struct compat_disp_session_config) +#define COMPAT_DISP_IOCTL_PREPARE_INPUT_BUFFER DISP_IOW(204, struct compat_disp_buffer_info) +#define COMPAT_DISP_IOCTL_PREPARE_OUTPUT_BUFFER DISP_IOW(205, struct compat_disp_buffer_info) +#define COMPAT_DISP_IOCTL_SET_INPUT_BUFFER DISP_IOW(206, struct compat_disp_session_input_config) +#define COMPAT_DISP_IOCTL_SET_OUTPUT_BUFFER DISP_IOW(207, struct compat_disp_session_output_config) +#define COMPAT_DISP_IOCTL_GET_SESSION_INFO DISP_IOW(208, struct compat_disp_session_info) +#define COMPAT_DISP_IOCTL_SET_SESSION_MODE DISP_IOW(209, struct compat_disp_session_config) +#define COMPAT_DISP_IOCTL_GET_SESSION_MODE DISP_IOW(210, struct compat_disp_session_config) +#define COMPAT_DISP_IOCTL_SET_SESSION_TYPE DISP_IOW(211, struct compat_disp_session_config) +#define COMPAT_DISP_IOCTL_GET_SESSION_TYPE DISP_IOW(212, struct compat_disp_session_config) +#define COMPAT_DISP_IOCTL_WAIT_FOR_VSYNC DISP_IOW(213, struct compat_disp_session_vsync_config) +#define COMPAT_DISP_IOCTL_SET_MAX_LAYER_NUM DISP_IOW(214, struct compat_disp_session_layer_num_config) +#define COMPAT_DISP_IOCTL_SET_VSYNC_FPS DISP_IOW(215, compat_uint_t) +#define COMPAT_DISP_IOCTL_GET_PRESENT_FENCE DISP_IOW(216, struct compat_disp_present_fence) +#define COMPAT_DISP_IOCTL_GET_IS_DRIVER_SUSPEND DISP_IOW(217, compat_uint_t) +#define COMPAT_DISP_IOCTL_GET_DISPLAY_CAPS DISP_IOW(218, struct compat_disp_caps_info) +#define COMPAT_DISP_IOCTL_FRAME_CONFIG DISP_IOW(220, struct compat_disp_session_output_config) +#define COMPAT_DISP_IOCTL_SCREEN_FREEZE DISP_IOW(223, compat_uint_t) + +#endif +#endif /*_COMPAT_MTK_DISP_MGR_H_*/ diff --git a/drivers/misc/mediatek/video/mt6755/data_digit.c b/drivers/misc/mediatek/video/mt6755/data_digit.c new file mode 100644 index 0000000000000000000000000000000000000000..41dded8d51dd8b0c6cec1db4ca7e3b15fc2c0369 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/data_digit.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "disp_debug.h" +#include "mtkfb_debug.h" + +#ifdef DISP_ENABLE_LAYER_FRAME +unsigned char data_digit[816] = { +0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1F, +0xF0, 0x0F, 0xE3, 0xC7, 0xE7, 0xE3, +0xC7, 0xE3, 0xCF, 0xF3, 0xCF, 0xF3, +0x8F, 0xF1, 0x8F, 0xF1, 0x8F, 0xF1, +0x8F, 0xF1, 0x8F, 0xF1, 0x8F, 0xF1, +0xCF, 0xF3, 0xCF, 0xF3, 0xC7, 0xE3, +0xC7, 0xE7, 0xE3, 0xC7, 0xF0, 0x0F, +0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, +0xF0, 0x3F, 0xE0, 0x3F, 0xE6, 0x3F, +0xFE, 0x3F, 0xFE, 0x3F, 0xFE, 0x3F, +0xFE, 0x3F, 0xFE, 0x3F, 0xFE, 0x3F, +0xFE, 0x3F, 0xFE, 0x3F, 0xFE, 0x3F, +0xFE, 0x3F, 0xFE, 0x3F, 0xFE, 0x3F, +0xFE, 0x3F, 0xFE, 0x3F, 0xE0, 0x03, +0xE0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F, +0xE0, 0x0F, 0xE7, 0xC7, 0xFF, 0xE3, +0xFF, 0xF3, 0xFF, 0xF3, 0xFF, 0xF3, +0xFF, 0xE3, 0xFF, 0xE7, 0xFF, 0xC7, +0xFF, 0x8F, 0xFF, 0x1F, 0xFE, 0x3F, +0xFC, 0x7F, 0xF8, 0xFF, 0xF1, 0xFF, +0xE3, 0xFF, 0xC7, 0xFF, 0x80, 0x03, +0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, +0xE0, 0x0F, 0xEF, 0x87, 0xFF, 0xC7, +0xFF, 0xE7, 0xFF, 0xE7, 0xFF, 0xE7, +0xFF, 0xC7, 0xFF, 0x8F, 0xF0, 0x3F, +0xF0, 0x1F, 0xFF, 0x87, 0xFF, 0xE7, +0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xE3, +0xDF, 0xE7, 0xCF, 0x87, 0xE0, 0x0F, +0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, +0xFF, 0x0F, 0xFF, 0x0F, 0xFE, 0x4F, +0xFC, 0xCF, 0xFC, 0xCF, 0xF9, 0xCF, +0xF3, 0xCF, 0xF3, 0xCF, 0xE7, 0xCF, +0xCF, 0xCF, 0xCF, 0xCF, 0x9F, 0xCF, +0x00, 0x01, 0x00, 0x01, 0xFF, 0xCF, +0xFF, 0xCF, 0xFF, 0xCF, 0xFF, 0xCF, +0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, +0xE0, 0x07, 0xE7, 0xFF, 0xE7, 0xFF, +0xE7, 0xFF, 0xE7, 0xFF, 0xE7, 0xFF, +0xE7, 0xFF, 0xE0, 0x3F, 0xE0, 0x0F, +0xFF, 0x87, 0xFF, 0xE3, 0xFF, 0xE3, +0xFF, 0xF3, 0xFF, 0xE3, 0xFF, 0xE3, +0xFF, 0xE7, 0xEF, 0x87, 0xE0, 0x0F, +0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, +0xFC, 0x07, 0xF0, 0xF7, 0xF3, 0xFF, +0xE3, 0xFF, 0xE7, 0xFF, 0xC7, 0xFF, +0xCF, 0xFF, 0xCC, 0x1F, 0xC8, 0x07, +0xC3, 0xE3, 0xC7, 0xF3, 0xCF, 0xF1, +0xCF, 0xF1, 0xCF, 0xF1, 0xCF, 0xF1, +0xE7, 0xF3, 0xE3, 0xC3, 0xF0, 0x07, +0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, +0x80, 0x03, 0xFF, 0xE3, 0xFF, 0xE7, +0xFF, 0xE7, 0xFF, 0xC7, 0xFF, 0xCF, +0xFF, 0x8F, 0xFF, 0x9F, 0xFF, 0x1F, +0xFF, 0x3F, 0xFF, 0x3F, 0xFE, 0x3F, +0xFE, 0x7F, 0xFC, 0x7F, 0xFC, 0xFF, +0xF8, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF, +0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F, +0xF0, 0x07, 0xE3, 0xC7, 0xC7, 0xE3, +0xC7, 0xE3, 0xC7, 0xE3, 0xE7, 0xE7, +0xE3, 0xC7, 0xF0, 0x0F, 0xFC, 0x3F, +0xF0, 0x0F, 0xE3, 0xC7, 0xC7, 0xE3, +0xCF, 0xF3, 0xCF, 0xF3, 0xCF, 0xF3, +0xCF, 0xF3, 0xC3, 0xC3, 0xE0, 0x07, +0xF8, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, +0xF0, 0x0F, 0xE3, 0xC7, 0xC7, 0xE7, +0xCF, 0xF3, 0x8F, 0xF3, 0x8F, 0xF3, +0xCF, 0xF3, 0xC7, 0xE3, 0xC3, 0xC3, +0xE0, 0x13, 0xF8, 0x33, 0xFF, 0xF3, +0xFF, 0xF3, 0xFF, 0xE3, 0xFF, 0xE7, +0xFF, 0xC7, 0xEF, 0x8F, 0xE0, 0x1F, +0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF8, 0x3F, 0xE0, 0x0F, +0xE7, 0x8F, 0xFF, 0xC7, 0xFF, 0xC7, +0xFF, 0xE7, 0xF8, 0x07, 0xE0, 0x07, +0xC7, 0xE7, 0xCF, 0xE7, 0x8F, 0xC7, +0x8F, 0xC7, 0xC7, 0x87, 0xC0, 0x27, +0xF0, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0x8F, 0xFF, 0x8F, 0xFF, +0x8F, 0xFF, 0x8F, 0xFF, 0x8F, 0xFF, +0x8F, 0xFF, 0x8F, 0xFF, 0x8C, 0x1F, +0x88, 0x07, 0x83, 0xC3, 0x87, 0xE3, +0x8F, 0xF3, 0x8F, 0xF1, 0x8F, 0xF1, +0x8F, 0xF1, 0x8F, 0xF1, 0x8F, 0xF3, +0x8F, 0xF3, 0x87, 0xE3, 0x83, 0xC7, +0x80, 0x0F, 0x8C, 0x1F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFC, 0x0F, 0xF0, 0x07, +0xE1, 0xF7, 0xE7, 0xFF, 0xC7, 0xFF, +0xCF, 0xFF, 0xCF, 0xFF, 0x8F, 0xFF, +0xCF, 0xFF, 0xCF, 0xFF, 0xC7, 0xFF, +0xC7, 0xFF, 0xE1, 0xF7, 0xF0, 0x07, +0xFC, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xF1, 0xFF, 0xF1, 0xFF, 0xF1, +0xFF, 0xF1, 0xFF, 0xF1, 0xFF, 0xF1, +0xFF, 0xF1, 0xF8, 0x31, 0xF0, 0x01, +0xE3, 0xC1, 0xC7, 0xE1, 0xCF, 0xF1, +0xCF, 0xF1, 0x8F, 0xF1, 0x8F, 0xF1, +0x8F, 0xF1, 0x8F, 0xF1, 0xCF, 0xF1, +0xC7, 0xE1, 0xE3, 0xC1, 0xE0, 0x11, +0xF8, 0x31, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1F, +0xF0, 0x0F, 0xE3, 0xC7, 0xC7, 0xE7, +0xCF, 0xE3, 0xCF, 0xE3, 0x80, 0x03, +0x80, 0x03, 0x8F, 0xFF, 0xCF, 0xFF, +0xCF, 0xFF, 0xC7, 0xF7, 0xE3, 0xE7, +0xF0, 0x0F, 0xF8, 0x1F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFE, 0x1F, 0xF8, 0x1F, +0xF9, 0xFF, 0xF1, 0xFF, 0xF1, 0xFF, +0xF1, 0xFF, 0xF1, 0xFF, 0xC0, 0x3F, +0xC0, 0x3F, 0xF1, 0xFF, 0xF1, 0xFF, +0xF1, 0xFF, 0xF1, 0xFF, 0xF1, 0xFF, +0xF1, 0xFF, 0xF1, 0xFF, 0xF1, 0xFF, +0xF1, 0xFF, 0xF1, 0xFF, 0xF1, 0xFF, +0xF1, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF3, 0xFF, 0xE1, 0xFF, +0xE1, 0xFF, 0xE1, 0xFF, 0xF3, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_clkmgr.c b/drivers/misc/mediatek/video/mt6755/ddp_clkmgr.c new file mode 100644 index 0000000000000000000000000000000000000000..4ed7e74155b78cd5b8025327b688f0b8e5f9b0c3 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_clkmgr.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "ddp_clkmgr.h" +#include "disp_log.h" +#include +#include +#include +#include +#include "ddp_reg.h" + +#ifndef CONFIG_MTK_CLKMGR + +#define clk_readl(addr) DRV_Reg32(addr) +#define clk_writel(addr, val) mt_reg_sync_writel(val, addr) +#define clk_setl(addr, val) mt_reg_sync_writel(clk_readl(addr) | (val), addr) +#define clk_clrl(addr, val) mt_reg_sync_writel(clk_readl(addr) & ~(val), addr) + +static struct clk *ddp_clk[MAX_DISP_CLK_CNT]; + +static void __iomem *ddp_apmixed_base; +#ifndef AP_PLL_CON0 +#define AP_PLL_CON0 (ddp_apmixed_base + 0x00) +#endif + + +unsigned int parsed_apmixed = 0; +int ddp_set_clk_handle(struct clk *pclk, unsigned int n) +{ + int ret = 0; + + if (n >= MAX_DISP_CLK_CNT) { + DISPERR("DISPSYS CLK id=%d is more than MAX_DISP_CLK_CNT\n", n); + return -1; + } + ddp_clk[n] = pclk; + DISPMSG("ddp_clk[%d] %p\n", n, ddp_clk[n]); + return ret; +} + +int ddp_clk_prepare(eDDP_CLK_ID id) +{ + int ret = 0; + + if (NULL == ddp_clk[id]) { + DISPERR("DISPSYS CLK %d NULL\n", id); + return -1; + } + ret = clk_prepare(ddp_clk[id]); + if (ret) + DISPERR("DISPSYS CLK prepare failed: errno %d id %d\n", ret, id); + + return ret; +} + +int ddp_clk_unprepare(eDDP_CLK_ID id) +{ + int ret = 0; + + if (NULL == ddp_clk[id]) { + DISPERR("DISPSYS CLK %d NULL\n", id); + return -1; + } + clk_unprepare(ddp_clk[id]); + return ret; +} + +int ddp_clk_enable(eDDP_CLK_ID id) +{ + int ret = 0; + + if (NULL == ddp_clk[id]) { + DISPERR("DISPSYS CLK %d NULL\n", id); + return -1; + } + + ret = clk_enable(ddp_clk[id]); + if (ret) + DISPERR("DISPSYS CLK enable failed: errno %d id=%d\n", ret, id); + + return ret; +} + +int ddp_clk_disable(eDDP_CLK_ID id) +{ + int ret = 0; + + if (NULL == ddp_clk[id]) { + DISPERR("DISPSYS CLK %d NULL\n", id); + return -1; + } + clk_disable(ddp_clk[id]); + return ret; +} + +int ddp_clk_prepare_enable(eDDP_CLK_ID id) +{ + int ret = 0; + + if (NULL == ddp_clk[id]) { + DISPERR("DISPSYS CLK %d NULL\n", id); + return -1; + } + ret = clk_prepare_enable(ddp_clk[id]); + if (ret) + DISPERR("DISPSYS CLK prepare failed: errno %d\n", ret); + + return ret; +} + +int ddp_clk_disable_unprepare(eDDP_CLK_ID id) +{ + int ret = 0; + + if (NULL == ddp_clk[id]) { + DISPERR("DISPSYS CLK %d NULL\n", id); + return -1; + } + clk_disable_unprepare(ddp_clk[id]); + return ret; +} +int ddp_clk_set_parent(eDDP_CLK_ID id, eDDP_CLK_ID parent) +{ + if ((NULL == ddp_clk[id]) || (NULL == ddp_clk[parent])) { + DISPERR("DISPSYS CLK %d or parent %d NULL\n", id, parent); + return -1; + } + return clk_set_parent(ddp_clk[id], ddp_clk[parent]); +} + +int ddp_set_mipi26m(int en) +{ + int ret = 0; + + ret = ddp_parse_apmixed_base(); + if (ret) + return -1; + if (en) + clk_setl(AP_PLL_CON0, 1 << 12); + else + clk_clrl(AP_PLL_CON0, 1 << 12); + return ret; +} + +int ddp_parse_apmixed_base(void) +{ + int ret = 0; + struct device_node *node; + + if (parsed_apmixed) + return ret; + + + node = of_find_compatible_node(NULL, NULL, "mediatek,APMIXED"); + if (!node) { + DISPERR("[DDP_APMIXED] DISP find apmixed node failed\n"); + return -1; + } + ddp_apmixed_base = of_iomap(node, 0); + if (!ddp_apmixed_base) { + DISPERR("[DDP_APMIXED] DISP apmixed base failed\n"); + return -1; + } + parsed_apmixed = 1; + return ret; +} + +#endif /* CONFIG_MTK_CLKMGR */ diff --git a/drivers/misc/mediatek/video/mt6755/ddp_clkmgr.h b/drivers/misc/mediatek/video/mt6755/ddp_clkmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..4e94ce198df1ec572c641177f193d2d6cd627633 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_clkmgr.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DDP_CLK_MGR_H__ +#define __DDP_CLK_MGR_H__ + +#ifndef CONFIG_MTK_CLKMGR +#include +#endif + + +typedef enum disp_clk_id { + DISP0_SMI_COMMON = 0, + DISP0_SMI_LARB0, + DISP0_DISP_OVL0, + DISP0_DISP_OVL1, + DISP0_DISP_RDMA0, + DISP0_DISP_RDMA1, + DISP0_DISP_WDMA0, + DISP0_DISP_COLOR, + DISP0_DISP_CCORR, + DISP0_DISP_AAL, + DISP0_DISP_GAMMA, + DISP0_DISP_DITHER, + DISP0_DISP_UFOE_MOUT, + DISP0_DISP_WDMA1, + DISP0_DISP_2L_OVL0, + DISP0_DISP_2L_OVL1, + DISP0_DISP_OVL0_MOUT, + DISP1_DSI_ENGINE, + DISP1_DSI_DIGITAL, + DISP1_DPI_ENGINE, + DISP1_DPI_PIXEL, + DISP_PWM, + DISP_MTCMOS_CLK, + MUX_DPI0, + TVDPLL_D2, + TVDPLL_D4, + TVDPLL_D8, + TVDPLL_D16, + DPI_CK, + MUX_PWM, + UNIVPLL2_D4, + ULPOSC_D2, + ULPOSC_D8, + MUX_MM, + MM_VENCPLL, + SYSPLL2_D2, + MAX_DISP_CLK_CNT +} eDDP_CLK_ID; + +#ifndef CONFIG_MTK_CLKMGR + +int ddp_clk_prepare(eDDP_CLK_ID id); +int ddp_clk_unprepare(eDDP_CLK_ID id); +int ddp_clk_enable(eDDP_CLK_ID id); +int ddp_clk_disable(eDDP_CLK_ID id); +int ddp_clk_prepare_enable(eDDP_CLK_ID id); +int ddp_clk_disable_unprepare(eDDP_CLK_ID id); +int ddp_clk_set_parent(eDDP_CLK_ID id, eDDP_CLK_ID parent); +int ddp_set_clk_handle(struct clk *pclk, unsigned int n); +int ddp_parse_apmixed_base(void); +int ddp_set_mipi26m(int en); + +#endif /* CONFIG_MTK_CLKMGR */ + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_color_format.c b/drivers/misc/mediatek/video/mt6755/ddp_color_format.c new file mode 100644 index 0000000000000000000000000000000000000000..e493bf167fc7b77bc0fd17c8093dccfaee3b7589 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_color_format.c @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "color_fmt" +#include +#include +#include "ddp_info.h" +#include "disp_log.h" + +char *unified_color_fmt_name(enum UNIFIED_COLOR_FMT fmt) +{ + switch (fmt) { + case UFMT_Y8: + return "Y8"; + case UFMT_RGBA4444: + return "RGBA4444"; + case UFMT_RGBA5551: + return "RGBA5551"; + case UFMT_RGB565: + return "RGB565"; + case UFMT_BGR565: + return "BGR565"; + case UFMT_RGB888: + return "RGB888"; + case UFMT_BGR888: + return "BGR888"; + case UFMT_RGBA8888: + return "RGBA8888"; + case UFMT_BGRA8888: + return "BGRA8888"; + case UFMT_ARGB8888: + return "ARGB8888"; + case UFMT_ABGR8888: + return "ABGR8888"; + case UFMT_RGBX8888: + return "RGBX8888"; + case UFMT_BGRX8888: + return "BGRX8888"; + case UFMT_XRGB8888: + return "XRGB8888"; + case UFMT_XBGR8888: + return "XBGR8888"; + case UFMT_AYUV: + return "AYUV"; + case UFMT_YUV: + return "YUV"; + case UFMT_UYVY: + return "UYVY"; + case UFMT_VYUY: + return "VYUY"; + case UFMT_YUYV: + return "YUYV"; + case UFMT_YVYU: + return "YVYU"; + case UFMT_UYVY_BLK: + return "UYVY_BLK"; + case UFMT_VYUY_BLK: + return "VYUY_BLK"; + case UFMT_YUY2_BLK: + return "YUY2_BLK"; + case UFMT_YVYU_BLK: + return "YVYU_BLK"; + case UFMT_YV12: + return "YV12"; + case UFMT_I420: + return "I420"; + case UFMT_YV16: + return "YV16"; + case UFMT_I422: + return "I422"; + case UFMT_YV24: + return "YV24"; + case UFMT_I444: + return "I444"; + case UFMT_NV12: + return "NV12"; + case UFMT_NV21: + return "NV21"; + case UFMT_NV12_BLK: + return "NV12_BLK"; + case UFMT_NV21_BLK: + return "NV21_BLK"; + case UFMT_NV12_BLK_FLD: + return "NV12_BLK_FLD"; + case UFMT_NV21_BLK_FLD: + return "NV21_BLK_FLD"; + case UFMT_NV16: + return "NV16"; + case UFMT_NV61: + return "NV61"; + case UFMT_NV24: + return "NV24"; + case UFMT_NV42: + return "NV42"; + case UFMT_PARGB8888: + return "PARGB8888"; + case UFMT_PABGR8888: + return "PABGR8888"; + case UFMT_PRGBA8888: + return "PRGBA8888"; + case UFMT_PBGRA8888: + return "PBGRA8888"; + default: + return "fmt_unknown"; + } +} + + +static enum UNIFIED_COLOR_FMT display_engine_supported_color[] = { + /* ovl/rdma supported */ + UFMT_RGB565, UFMT_BGR565, + UFMT_RGB888, UFMT_BGR888, + UFMT_RGBA8888, UFMT_BGRA8888, + UFMT_ARGB8888, UFMT_ABGR8888, + UFMT_XRGB8888, UFMT_RGBX8888, + UFMT_PARGB8888, UFMT_PABGR8888, + UFMT_PRGBA8888, UFMT_PBGRA8888, + UFMT_UYVY, UFMT_VYUY, + UFMT_YUYV, UFMT_YVYU, + /* wdma supported */ + UFMT_YV12, UFMT_I420, + UFMT_NV12, UFMT_NV21, +}; + +int is_unified_color_fmt_supported(enum UNIFIED_COLOR_FMT ufmt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(display_engine_supported_color); i++) { + if (ufmt == display_engine_supported_color[i]) + return 1; + } + return 0; +} + +enum UNIFIED_COLOR_FMT display_fmt_reg_to_unified_fmt(int fmt_reg_val, int byteswap, int rgbswap) +{ + int i; + enum UNIFIED_COLOR_FMT ufmt; + + for (i = 0; i < ARRAY_SIZE(display_engine_supported_color); i++) { + ufmt = display_engine_supported_color[i]; + if (UFMT_GET_FORMAT(ufmt) == fmt_reg_val && UFMT_GET_BYTESWAP(ufmt) == byteswap && + UFMT_GET_RGBSWAP(ufmt) == rgbswap) + return ufmt; + } + DISPERR("unknown_fmt fmt=%d, byteswap=%d, rgbswap=%d\n", fmt_reg_val, byteswap, rgbswap); + return UFMT_UNKNOWN; +} + +enum UNIFIED_COLOR_FMT disp_fmt_to_unified_fmt(DISP_FORMAT src_fmt) +{ + switch (src_fmt) { + case DISP_FORMAT_RGB565: + return UFMT_RGB565; + case DISP_FORMAT_RGB888: + return UFMT_RGB888; + case DISP_FORMAT_BGR888: + return UFMT_BGR888; + case DISP_FORMAT_ARGB8888: + return UFMT_ARGB8888; + case DISP_FORMAT_ABGR8888: + return UFMT_ABGR8888; + case DISP_FORMAT_RGBA8888: + return UFMT_RGBA8888; + case DISP_FORMAT_BGRA8888: + return UFMT_BGRA8888; + case DISP_FORMAT_YUV422: + return UFMT_YUYV; + case DISP_FORMAT_XRGB8888: + return UFMT_XRGB8888; + case DISP_FORMAT_XBGR8888: + return UFMT_XBGR8888; + case DISP_FORMAT_RGBX8888: + return UFMT_RGBX8888; + case DISP_FORMAT_BGRX8888: + return UFMT_BGRX8888; + case DISP_FORMAT_UYVY: + return UFMT_UYVY; + case DISP_FORMAT_YUV420_P: + return UFMT_I420; + case DISP_FORMAT_YV12: + return UFMT_YV12; + case DISP_FORMAT_PARGB8888: + return UFMT_PARGB8888; + case DISP_FORMAT_PABGR8888: + return UFMT_PABGR8888; + case DISP_FORMAT_PRGBA8888: + return UFMT_PRGBA8888; + case DISP_FORMAT_PBGRA8888: + return UFMT_PBGRA8888; + default: + DISPERR("Invalid color format: 0x%x\n", src_fmt); + BUG(); + return UFMT_UNKNOWN; + } +} + +int ufmt_disable_X_channel(enum UNIFIED_COLOR_FMT src_fmt, enum UNIFIED_COLOR_FMT *dst_fmt, + int *const_bld) +{ + int ret = 1; + + switch (src_fmt) { + case UFMT_XRGB8888: + *dst_fmt = UFMT_ARGB8888; + if (const_bld) + *const_bld = 1; + break; + case UFMT_XBGR8888: + *dst_fmt = UFMT_ABGR8888; + if (const_bld) + *const_bld = 1; + break; + case UFMT_RGBX8888: + *dst_fmt = UFMT_RGBA8888; + if (const_bld) + *const_bld = 1; + break; + case UFMT_BGRX8888: + *dst_fmt = UFMT_BGRA8888; + if (const_bld) + *const_bld = 1; + break; + default: + *dst_fmt = src_fmt; + if (const_bld) + *const_bld = 0; + ret = 0; + break; + } + return ret; +} +int ufmt_disable_P(enum UNIFIED_COLOR_FMT src_fmt, enum UNIFIED_COLOR_FMT *dst_fmt) +{ + int ret = 1; + + switch (src_fmt) { + case UFMT_PARGB8888: + *dst_fmt = UFMT_ARGB8888; + break; + case UFMT_PABGR8888: + *dst_fmt = UFMT_ABGR8888; + break; + case UFMT_PRGBA8888: + *dst_fmt = UFMT_RGBA8888; + break; + case UFMT_PBGRA8888: + *dst_fmt = UFMT_BGRA8888; + break; + default: + *dst_fmt = src_fmt; + ret = 0; + break; + } + return ret; +} +unsigned int ufmt_get_rgb(unsigned int fmt) +{ + return UFMT_GET_RGB(fmt); +} +unsigned int ufmt_get_bpp(unsigned int fmt) +{ + return UFMT_GET_bpp(fmt); +} +unsigned int ufmt_get_block(unsigned int fmt) +{ + return UFMT_GET_BLOCK(fmt); +} +unsigned int ufmt_get_vdo(unsigned int fmt) +{ + return UFMT_GET_VDO(fmt); +} +unsigned int ufmt_get_format(unsigned int fmt) +{ + return UFMT_GET_FORMAT(fmt); +} +unsigned int ufmt_get_byteswap(unsigned int fmt) +{ + return UFMT_GET_BYTESWAP(fmt); +} +unsigned int ufmt_get_rgbswap(unsigned int fmt) +{ + return UFMT_GET_RGBSWAP(fmt); +} +unsigned int ufmt_get_id(unsigned int fmt) +{ + return UFMT_GET_ID(fmt); +} +unsigned int ufmt_get_Bpp(unsigned int fmt) +{ + return UFMT_GET_Bpp(fmt); +} +unsigned int ufmt_is_old_fmt(unsigned int fmt) +{ + int old_fmt = 0; + + switch (fmt) { + case UFMT_PARGB8888: + old_fmt = 1; + break; + case UFMT_PABGR8888: + old_fmt = 1; + break; + case UFMT_PRGBA8888: + old_fmt = 1; + break; + case UFMT_PBGRA8888: + old_fmt = 1; + break; + default: + old_fmt = 0; + break; + } + return old_fmt; +} + diff --git a/drivers/misc/mediatek/video/mt6755/ddp_dpi.c b/drivers/misc/mediatek/video/mt6755/ddp_dpi.c new file mode 100644 index 0000000000000000000000000000000000000000..0163913ccfd93ab74258ccaf04b1ceb3791f94c5 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_dpi.c @@ -0,0 +1,817 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef BUILD_UBOOT +#define ENABLE_DSI_INTERRUPT 0 + +#include +#else +#include +#include +#include +#include + +#include "cmdq_record.h" +#endif + +#include +/*#include */ +#include + +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include "ddp_clkmgr.h" +#endif +#include + +#include +#include +#include + +#include +#include + +#include "mtkfb.h" +#include "ddp_drv.h" +#include "ddp_hal.h" +#include "ddp_manager.h" +#include "ddp_dpi_reg.h" +#include "ddp_dpi.h" +#include "ddp_reg.h" +#include "disp_log.h" +#include "disp_debug.h" +#include "mtkfb_debug.h" +#ifndef LOG_TAG +#define LOG_TAG "DPI" +#endif + +#define ENABLE_DPI_INTERRUPT 0 + +#ifndef CONFIG_MTK_CLKMGR +static void __iomem *clk_apmixed_base; +#ifndef TVDPLL_CON0 +#define TVDPLL_CON0 (clk_apmixed_base + 0x270) +#endif +#ifndef TVDPLL_CON1 +#define TVDPLL_CON1 (clk_apmixed_base + 0x274) +#endif +#endif + +#define DPI_SMT +static int cache_bg_parameter; + +#undef LCD_BASE +#define LCD_BASE (0xF4024000) +#define DPI_REG_OFFSET(r) offsetof(struct DPI_REGS, r) +#define REG_ADDR(base, offset) (((BYTE *)(base)) + (offset)) + +#ifdef INREG32 +#undef INREG32 +#define INREG32(x) (__raw_readl((unsigned long *)(x))) +#endif + +#define DPI_OUTREG32(cmdq, addr, val) DISP_REG_SET(cmdq, addr, val) +#define DPI_OUTREGBIT(cmdq, TYPE, REG, bit, value) \ + do {\ + TYPE r;\ + TYPE v;\ + if (cmdq) { \ + *(unsigned int *)(&r) = ((unsigned int)0x00000000); r.bit = ~(r.bit); \ + *(unsigned int *)(&v) = ((unsigned int)0x00000000); v.bit = value; \ + DISP_REG_MASK(cmdq, ®, AS_UINT32(&v), AS_UINT32(&r)); \ + } else { \ + mt_reg_sync_writel(INREG32(®), &r); r.bit = (value); DISP_REG_SET(cmdq, ®, INREG32(&r)); \ + } \ + } while (0) + +#define DPI_MASKREG32(cmdq, REG, MASK, VALUE) DISP_REG_MASK((cmdq), (REG), (VALUE), (MASK)) + +static int s_isDpiPowerOn = FALSE; +static int s_isDpiStart = FALSE; +static int s_isDpiConfig = FALSE; + +static int dpi_vsync_irq_count; +static int dpi_undflow_irq_count; + +/*static DPI_REGS regBackup;*/ +struct DPI_REGS *DPI_REG = 0; +static const LCM_UTIL_FUNCS lcm_utils_dpi; + +const unsigned BACKUP_DPI_REG_OFFSETS[] = { + DPI_REG_OFFSET(INT_ENABLE), + DPI_REG_OFFSET(CNTL), + DPI_REG_OFFSET(SIZE), + + DPI_REG_OFFSET(TGEN_HWIDTH), + DPI_REG_OFFSET(TGEN_HPORCH), + DPI_REG_OFFSET(TGEN_VWIDTH_LODD), + DPI_REG_OFFSET(TGEN_VPORCH_LODD), + + DPI_REG_OFFSET(BG_HCNTL), + DPI_REG_OFFSET(BG_VCNTL), + DPI_REG_OFFSET(BG_COLOR), + + DPI_REG_OFFSET(TGEN_VWIDTH_LEVEN), + DPI_REG_OFFSET(TGEN_VPORCH_LEVEN), + DPI_REG_OFFSET(TGEN_VWIDTH_RODD), + + DPI_REG_OFFSET(TGEN_VPORCH_RODD), + DPI_REG_OFFSET(TGEN_VWIDTH_REVEN), + + DPI_REG_OFFSET(TGEN_VPORCH_REVEN), + DPI_REG_OFFSET(ESAV_VTIM_LOAD), + DPI_REG_OFFSET(ESAV_VTIM_ROAD), + DPI_REG_OFFSET(ESAV_FTIM), +}; + +/*the static functions declare*/ +static void lcm_udelay(unsigned us) +{ + udelay(us); +} + +static void lcm_mdelay(unsigned ms) +{ + msleep(ms); +} + +static void lcm_set_reset_pin(unsigned value) +{ +#ifndef DPI_SMT + DPI_OUTREG32(0, MMSYS_CONFIG_BASE + 0x150, value); +#endif +} + +static void lcm_send_cmd(unsigned cmd) +{ +#ifndef DPI_SMT + DPI_OUTREG32(0, LCD_BASE + 0x0F80, cmd); +#endif +} + +static void lcm_send_data(unsigned data) +{ +#ifndef DPI_SMT + DPI_OUTREG32(0, LCD_BASE + 0x0F90, data); +#endif +} + +/* +static void _BackupDPIRegisters(void) +{ + UINT32 i; + DPI_REGS *reg = ®Backup; + + for (i = 0; i < ARY_SIZE(BACKUP_DPI_REG_OFFSETS); ++i) + { + DPI_OUTREG32(0, REG_ADDR(reg, BACKUP_DPI_REG_OFFSETS[i]), \ + AS_UINT32(REG_ADDR(DPI_REG, BACKUP_DPI_REG_OFFSETS[i]))); + } +} + +static void _RestoreDPIRegisters(void) +{ + UINT32 i; + DPI_REGS *reg = ®Backup; + + for (i = 0; i < ARY_SIZE(BACKUP_DPI_REG_OFFSETS); ++i) + { + DPI_OUTREG32(0, REG_ADDR(DPI_REG, BACKUP_DPI_REG_OFFSETS[i]), \ + AS_UINT32(REG_ADDR(reg, BACKUP_DPI_REG_OFFSETS[i]))); + } +} +*/ + +/*the functions declare*/ +/*DPI clock setting - use TVDPLL provide DPI clock*/ +enum DPI_STATUS ddp_dpi_ConfigPclk(cmdqRecHandle cmdq, unsigned int clk_req, enum DPI_POLARITY polarity) +{ + unsigned clksrc = 0; + unsigned prediv = 0x8016D89E; + unsigned con0 = 0xC0000121; + struct DPI_REG_OUTPUT_SETTING ctrl = DPI_REG->OUTPUT_SETTING; + struct device_node *node; + + switch (clk_req) { + case DPI_CLK_480p: + { +#ifdef CONFIG_MTK_CLKMGR + clksrc = 2; +#else + clksrc = TVDPLL_D4; +#endif + prediv = 0x8010A1EB; + con0 = 0xC0000131; + break; + } + case DPI_CLK_EINK_85: + { +#ifdef CONFIG_MTK_CLKMGR + clksrc = 1; +#else + clksrc = TVDPLL_D2; +#endif + prediv = 0x800AC40E; + con0 = 0xC0000131; + break; + } + case DPI_CLK_EINK_100: + { +#ifdef CONFIG_MTK_CLKMGR + clksrc = 1; +#else + clksrc = TVDPLL_D2; +#endif + prediv = 0x800CAA74; + con0 = 0xC0000131; + break; + } + case DPI_CLK_720p: + { +#ifdef CONFIG_MTK_CLKMGR + clksrc = 2; +#else + clksrc = TVDPLL_D4; +#endif + break; + } + case DPI_CLK_1080p: + { +#ifdef CONFIG_MTK_CLKMGR + clksrc = 1; +#else + clksrc = TVDPLL_D2; +#endif + break; + } + default: + { + DISPERR("[DPI]unknown clock frequency: %d\n", clk_req); + break; + } + } + + DISPMSG("[DPI]TVDPLL clock setting clk %d, clksrc: %d\n", clk_req, clksrc); + +#ifdef CONFIG_MTK_CLKMGR + clkmux_sel(MT_MUX_DPI0, clksrc, "DPI"); +#else + ddp_clk_enable(MUX_DPI0); + ddp_clk_set_parent(MUX_DPI0, clksrc); + ddp_clk_disable(MUX_DPI0); + + /* apmixed */ + node = of_find_compatible_node(NULL, NULL, "mediatek,APMIXED"); + if (!node) + pr_debug("[CLK_APMIXED] find node failed\n"); + + clk_apmixed_base = of_iomap(node, 0); + if (!clk_apmixed_base) + pr_debug("[CLK_APMIXED] base failed\n"); + else { + DPI_OUTREG32(NULL, clk_apmixed_base + 0x270, con0); /* TVDPLL enable */ + DPI_OUTREG32(NULL, clk_apmixed_base + 0x274, prediv); /* set TVDPLL output clock frequency */ + } +#endif + + /*DPI_OUTREG32(NULL, TVDPLL_CON0, con0);*//* TVDPLL enable */ + /*DPI_OUTREG32(NULL, TVDPLL_CON1, prediv); *//* set TVDPLL output clock frequency */ + /*IO driving setting */ + /*DPI_MASKREG32(NULL, DISPSYS_IO_DRIVING, 0x3C00, 0x0);*/ + + /*DPI output clock polarity */ + ctrl.CLK_POL = (DPI_POLARITY_FALLING == polarity) ? 1 : 0; + DPI_OUTREGBIT(cmdq, struct DPI_REG_OUTPUT_SETTING, DPI_REG->OUTPUT_SETTING, CLK_POL, ctrl.CLK_POL); + + return DPI_STATUS_OK; +} + +enum DPI_STATUS ddp_dpi_ConfigDE(cmdqRecHandle cmdq, enum DPI_POLARITY polarity) +{ + struct DPI_REG_OUTPUT_SETTING pol = DPI_REG->OUTPUT_SETTING; + + pol.DE_POL = (DPI_POLARITY_FALLING == polarity) ? 1 : 0; + DPI_OUTREGBIT(cmdq, struct DPI_REG_OUTPUT_SETTING, DPI_REG->OUTPUT_SETTING, DE_POL, pol.DE_POL); + + return DPI_STATUS_OK; +} + +enum DPI_STATUS ddp_dpi_ConfigVsync(cmdqRecHandle cmdq, enum DPI_POLARITY polarity, unsigned pulseWidth, + unsigned backPorch, unsigned frontPorch) +{ + struct DPI_REG_TGEN_VWIDTH_LODD vwidth_lodd = DPI_REG->TGEN_VWIDTH_LODD; + struct DPI_REG_TGEN_VPORCH_LODD vporch_lodd = DPI_REG->TGEN_VPORCH_LODD; + struct DPI_REG_OUTPUT_SETTING pol = DPI_REG->OUTPUT_SETTING; + struct DPI_REG_CNTL VS = DPI_REG->CNTL; + + pol.VSYNC_POL = (DPI_POLARITY_FALLING == polarity) ? 1 : 0; + vwidth_lodd.VPW_LODD = pulseWidth; + vporch_lodd.VBP_LODD = backPorch; + vporch_lodd.VFP_LODD = frontPorch; + + VS.VS_LODD_EN = 1; + VS.VS_LEVEN_EN = 0; + VS.VS_RODD_EN = 0; + VS.VS_REVEN_EN = 0; + + DPI_OUTREGBIT(cmdq, struct DPI_REG_OUTPUT_SETTING, DPI_REG->OUTPUT_SETTING, VSYNC_POL, + pol.VSYNC_POL); + + DPI_OUTREGBIT(cmdq, struct DPI_REG_TGEN_VWIDTH_LODD, DPI_REG->TGEN_VWIDTH_LODD, VPW_LODD, + vwidth_lodd.VPW_LODD); + + + DPI_OUTREGBIT(cmdq, struct DPI_REG_TGEN_VPORCH_LODD, DPI_REG->TGEN_VPORCH_LODD, VBP_LODD, + vporch_lodd.VBP_LODD); + DPI_OUTREGBIT(cmdq, struct DPI_REG_TGEN_VPORCH_LODD, DPI_REG->TGEN_VPORCH_LODD, VFP_LODD, + vporch_lodd.VFP_LODD); + + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, VS_LODD_EN, VS.VS_LODD_EN); + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, VS_LEVEN_EN, VS.VS_LEVEN_EN); + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, VS_RODD_EN, VS.VS_RODD_EN); + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, VS_REVEN_EN, VS.VS_REVEN_EN); + + return DPI_STATUS_OK; +} + +enum DPI_STATUS ddp_dpi_ConfigHsync(cmdqRecHandle cmdq, enum DPI_POLARITY polarity, unsigned pulseWidth, + unsigned backPorch, unsigned frontPorch) +{ + struct DPI_REG_TGEN_HPORCH hporch = DPI_REG->TGEN_HPORCH; + struct DPI_REG_OUTPUT_SETTING pol = DPI_REG->OUTPUT_SETTING; + + hporch.HBP = backPorch; + hporch.HFP = frontPorch; + pol.HSYNC_POL = (DPI_POLARITY_FALLING == polarity) ? 1 : 0; + DPI_REG->TGEN_HWIDTH = pulseWidth; + + DPI_OUTREG32(cmdq, &DPI_REG->TGEN_HWIDTH, pulseWidth); + + DPI_OUTREGBIT(cmdq, struct DPI_REG_TGEN_HPORCH, DPI_REG->TGEN_HPORCH, HBP, hporch.HBP); + DPI_OUTREGBIT(cmdq, struct DPI_REG_TGEN_HPORCH, DPI_REG->TGEN_HPORCH, HFP, hporch.HFP); + + DPI_OUTREGBIT(cmdq, struct DPI_REG_OUTPUT_SETTING, DPI_REG->OUTPUT_SETTING, HSYNC_POL, + pol.HSYNC_POL); + + return DPI_STATUS_OK; +} + +enum DPI_STATUS ddp_dpi_ConfigDualEdge(cmdqRecHandle cmdq, bool enable, unsigned mode) +{ + struct DPI_REG_OUTPUT_SETTING ctrl = DPI_REG->OUTPUT_SETTING; + struct DPI_REG_DDR_SETTING ddr_setting = DPI_REG->DDR_SETTING; + + ctrl.DUAL_EDGE_SEL = enable; + DPI_OUTREGBIT(cmdq, struct DPI_REG_OUTPUT_SETTING, DPI_REG->OUTPUT_SETTING, DUAL_EDGE_SEL, + ctrl.DUAL_EDGE_SEL); + + ddr_setting.DDR_4PHASE = 1; + ddr_setting.DDR_EN = 1; + DPI_OUTREGBIT(cmdq, struct DPI_REG_DDR_SETTING, DPI_REG->DDR_SETTING, DDR_4PHASE, + ddr_setting.DDR_4PHASE); + DPI_OUTREGBIT(cmdq, struct DPI_REG_DDR_SETTING, DPI_REG->DDR_SETTING, DDR_EN, ddr_setting.DDR_EN); + + return DPI_STATUS_OK; +} + +enum DPI_STATUS ddp_dpi_ConfigBG(cmdqRecHandle cmdq, bool enable, int BG_W, int BG_H) +{ + if (enable == false) { + struct DPI_REG_CNTL pol = DPI_REG->CNTL; + + pol.BG_EN = 0; + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, BG_EN, pol.BG_EN); + + } else { + struct DPI_REG_CNTL pol = DPI_REG->CNTL; + struct DPI_REG_BG_HCNTL pol2 = DPI_REG->BG_HCNTL; + struct DPI_REG_BG_VCNTL pol3 = DPI_REG->BG_VCNTL; + struct DPI_REG_BG_COLOR pol4 = DPI_REG->BG_COLOR; + + pol.BG_EN = 1; + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, BG_EN, pol.BG_EN); + + pol2.BG_RIGHT = BG_W / 2; + pol2.BG_LEFT = BG_W - pol2.BG_RIGHT; + DPI_OUTREGBIT(cmdq, struct DPI_REG_BG_HCNTL, DPI_REG->BG_HCNTL, BG_RIGHT, pol2.BG_RIGHT); + DPI_OUTREGBIT(cmdq, struct DPI_REG_BG_HCNTL, DPI_REG->BG_HCNTL, BG_LEFT, pol2.BG_LEFT); + + pol3.BG_BOT = BG_H / 2; + pol3.BG_TOP = BG_H - pol3.BG_BOT; + DPI_OUTREGBIT(cmdq, struct DPI_REG_BG_VCNTL, DPI_REG->BG_VCNTL, BG_BOT, pol3.BG_BOT); + DPI_OUTREGBIT(cmdq, struct DPI_REG_BG_VCNTL, DPI_REG->BG_VCNTL, BG_TOP, pol3.BG_TOP); + + pol4.BG_B = 0; + pol4.BG_G = 0; + pol4.BG_R = 0; + DPI_OUTREGBIT(cmdq, struct DPI_REG_BG_COLOR, DPI_REG->BG_COLOR, BG_B, pol4.BG_B); + DPI_OUTREGBIT(cmdq, struct DPI_REG_BG_COLOR, DPI_REG->BG_COLOR, BG_G, pol4.BG_G); + DPI_OUTREGBIT(cmdq, struct DPI_REG_BG_COLOR, DPI_REG->BG_COLOR, BG_R, pol4.BG_R); + } + + return DPI_STATUS_OK; +} + +enum DPI_STATUS ddp_dpi_ConfigSize(cmdqRecHandle cmdq, unsigned width, unsigned height) +{ + struct DPI_REG_SIZE size = DPI_REG->SIZE; + + size.WIDTH = width; + size.HEIGHT = height; + DPI_OUTREGBIT(cmdq, struct DPI_REG_SIZE, DPI_REG->SIZE, WIDTH, size.WIDTH); + DPI_OUTREGBIT(cmdq, struct DPI_REG_SIZE, DPI_REG->SIZE, HEIGHT, size.HEIGHT); + + return DPI_STATUS_OK; +} + +enum DPI_STATUS ddp_dpi_EnableColorBar(void) +{ + /*enable internal pattern - color bar */ + DPI_OUTREG32(0, DISPSYS_DPI_BASE + 0xF00, 0x41); + + return DPI_STATUS_OK; +} + +enum DPI_STATUS ddp_dpi_EnableINT(cmdqRecHandle cmdq, unsigned irq_bit, unsigned value) +{ + struct DPI_REG_INTERRUPT enInt = DPI_REG->INT_ENABLE; + + if (irq_bit&0x1) { + enInt.VSYNC = value; + DPI_OUTREGBIT(cmdq, struct DPI_REG_INTERRUPT, DPI_REG->INT_ENABLE, VSYNC, enInt.VSYNC); + } + + if (irq_bit & 0x2) { + enInt.VDE = value; + DPI_OUTREGBIT(cmdq, struct DPI_REG_INTERRUPT, DPI_REG->INT_ENABLE, VDE, enInt.VDE); + } + + return DPI_STATUS_OK; +} + +int ddp_dpi_power_on(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + int ret = 0; + + DISPMSG("[DPI]ddp_dpi_power_on, s_isDpiPowerOn %d\n", s_isDpiPowerOn); + if (!s_isDpiPowerOn) { +#ifdef CONFIG_MTK_CLKMGR + ret += enable_clock(MT_CG_DISP1_DPI_PIXEL, "DPI"); + ret += enable_clock(MT_CG_DISP1_DPI_ENGINE, "DPI"); +#else + ret += ddp_clk_enable(DISP1_DPI_PIXEL); + /*ret += ddp_clk_enable(DISP1_DPI_ENGINE);*/ +#endif + if (ret > 0) + DISPERR("[DPI]power manager API return FALSE\n"); + + /* _RestoreDPIRegisters(); */ + s_isDpiPowerOn = TRUE; + } + + return 0; +} + +int ddp_dpi_power_off(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + int ret = 0; + + DISPMSG("[DPI]ddp_dpi_power_off, s_isDpiPowerOn %d\n", s_isDpiPowerOn); + if (s_isDpiPowerOn) { +#ifdef CONFIG_MTK_CLKMGR + /* _BackupDPIRegisters(); */ + ret += disable_clock(MT_CG_DISP1_DPI_PIXEL, "DPI"); + ret += disable_clock(MT_CG_DISP1_DPI_ENGINE, "DPI"); +#else + ddp_clk_disable(DISP1_DPI_PIXEL); + /*ddp_clk_disable(DISP1_DPI_ENGINE);*/ +#endif + if (ret > 0) + DISPERR("[DPI]power manager API return FALSE\n"); + + s_isDpiPowerOn = FALSE; + } + + return 0; + +} + +int ddp_dpi_config(DISP_MODULE_ENUM module, disp_ddp_path_config *config, void *cmdq_handle) +{ + if (s_isDpiConfig == FALSE) { + LCM_DPI_PARAMS *dpi_config = &(config->dispif_config.dpi); + + DISPMSG("[DPI]ddp_dpi_config DPI status:%x, width:%d, height:%d\n", INREG32(&DPI_REG->STATUS), + dpi_config->width, dpi_config->height); + + ddp_dpi_ConfigPclk(cmdq_handle, dpi_config->dpi_clock, dpi_config->clk_pol); + ddp_dpi_ConfigSize(cmdq_handle, dpi_config->width, dpi_config->height); + /*ddp_dpi_ConfigBG(cmdq_handle, true, dpi_config->bg_width, dpi_config->bg_height);*/ + cache_bg_parameter = dpi_config->bg_width << 16 | dpi_config->bg_height; + DISPMSG("[DPI]bg_width: %d, bg_height: %d\n", dpi_config->bg_width, dpi_config->bg_height); + + ddp_dpi_ConfigDE(cmdq_handle, dpi_config->de_pol); + ddp_dpi_ConfigVsync(cmdq_handle, dpi_config->vsync_pol, + dpi_config->vsync_pulse_width, dpi_config->vsync_back_porch, + dpi_config->vsync_front_porch); + ddp_dpi_ConfigHsync(cmdq_handle, dpi_config->hsync_pol, + dpi_config->hsync_pulse_width, dpi_config->hsync_back_porch, + dpi_config->hsync_front_porch); + + ddp_dpi_ConfigDualEdge(cmdq_handle, dpi_config->i2x_en, dpi_config->i2x_edge); + + s_isDpiConfig = TRUE; + DISPDBG("[DPI]ddp_dpi_config done\n"); + } + + if (s_isDpiConfig == TRUE) { + LCM_DPI_PARAMS *dpi_config = &(config->dispif_config.dpi); + int now_bg_parameters = dpi_config->bg_width << 16 | dpi_config->bg_height; + + DISPDBG("[DPI]now_bg_parameters: 0x%x, cache_bg_parameter: 0x%x\n", now_bg_parameters, + cache_bg_parameter); + + if (now_bg_parameters != cache_bg_parameter) { + DISPMSG("[DPI]Need to rechange DPI BG\n"); + + + ddp_dpi_ConfigSize(cmdq_handle, dpi_config->width, dpi_config->height); + ddp_dpi_ConfigBG(cmdq_handle, true, dpi_config->bg_width, + dpi_config->bg_height); + cache_bg_parameter = now_bg_parameters; + } + /*ddp_dpi_dump(DISP_MODULE_DPI, 1);*/ + } + + return 0; +} + +int ddp_dpi_reset(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + struct DPI_REG_RST reset; + + DISPDBG("[DPI]ddp_dpi_reset\n"); + + reset = DPI_REG->DPI_RST; + reset.RST = 1; + DPI_OUTREGBIT(cmdq_handle, struct DPI_REG_RST, DPI_REG->DPI_RST, RST, reset.RST); + + + reset.RST = 0; + DPI_OUTREGBIT(cmdq_handle, struct DPI_REG_RST, DPI_REG->DPI_RST, RST, reset.RST); + + return 0; +} + +int ddp_dpi_start(DISP_MODULE_ENUM module, void *cmdq) +{ + return 0; +} + +int ddp_dpi_trigger(DISP_MODULE_ENUM module, void *cmdq) +{ + if (s_isDpiStart == FALSE) { + DISPMSG("[DPI]ddp_dpi_start\n"); + /*enable vsync interrupt*/ + ddp_dpi_EnableINT(cmdq, 1, 1); + ddp_dpi_reset(module, cmdq); + /*enable DPI */ + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE, 0x00000001); + + s_isDpiStart = TRUE; + } + return 0; +} + +int ddp_dpi_stop(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + DISPMSG("[DPI]ddp_dpi_stop\n"); + + /*disable DPI and background, and reset DPI */ + ddp_dpi_EnableINT(cmdq_handle, 1, 0); + DPI_OUTREG32(cmdq_handle, DISPSYS_DPI_BASE, 0x00000000); + + ddp_dpi_ConfigBG(cmdq_handle, false, 0, 0); + ddp_dpi_reset(module, cmdq_handle); + + s_isDpiStart = FALSE; + s_isDpiConfig = FALSE; + dpi_vsync_irq_count = 0; + dpi_undflow_irq_count = 0; + + return 0; +} + +int ddp_dpi_is_busy(DISP_MODULE_ENUM module) +{ + unsigned int status = INREG32(DISPSYS_DPI_BASE + 0x40); + + return (status & (0x1 << 16) ? 1 : 0); +} + +int ddp_dpi_is_idle(DISP_MODULE_ENUM module) +{ + return !ddp_dpi_is_busy(module); +} + +#if ENABLE_DPI_INTERRUPT +irqreturn_t _DPI_InterruptHandler(int irq, void *dev_id) +{ + unsigned int status = (unsigned int)readDPIIntrStatus(); + + if (status & 0x01) { + unsigned int checkSumNum = (INREG32(DISPSYS_DPI_BASE + 0x48) & 0x00FFFFFF); + + dpi_vsync_irq_count++; + if (dpi_vsync_irq_count > 30) + dpi_vsync_irq_count = 0; + } else if ((status >> 1) & 0x01) { + /*DISPMSG("status.VDE interrupt coming\n");*/ + } else if ((status >> 2) & 0x01) { + /*DISPMSG("status.UNDERFLOW interrupt coming\n");*/ + } + + ClearDPIIntrStatus(); + return IRQ_HANDLED; +} + +#endif + +int ddp_dpi_init(DISP_MODULE_ENUM module, void *cmdq) +{ + struct device_node *node; + + DISPMSG("[DPI]ddp_dpi_init +\n"); + +#if 0 /* /def MTKFB_FPGA_ONLY */ + + DPI_OUTREG32(cmdq, MMSYS_CONFIG_BASE + 0x108, 0xffffffff); + DPI_OUTREG32(cmdq, MMSYS_CONFIG_BASE + 0x118, 0xffffffff); + /* DPI_OUTREG32(cmdq, MMSYS_CONFIG_BASE+0xC08, 0xffffffff); */ + + DPI_OUTREG32(cmdq, LCD_BASE + 0x001C, 0x00ffffff); + DPI_OUTREG32(cmdq, LCD_BASE + 0x0028, 0x010000C0); + DPI_OUTREG32(cmdq, LCD_BASE + 0x002C, 0x1); + DPI_OUTREG32(cmdq, LCD_BASE + 0x002C, 0x0); + + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE + 0x14, 0x00000000); + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE + 0x1C, 0x00000005); + + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE + 0x20, 0x0000001A); + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE + 0x24, 0x001A001A); + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE + 0x28, 0x0000000A); + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE + 0x2C, 0x000A000A); + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE + 0x08, 0x00000007); + + DPI_OUTREG32(cmdq, DISPSYS_DPI_BASE + 0x00, 0x00000000); +#else + /* /_BackupDPIRegisters(); */ + ddp_dpi_power_on(DISP_MODULE_DPI, cmdq); +#endif + +#if ENABLE_DPI_INTERRUPT + if (request_irq(DPI0_IRQ_BIT_ID, + _DPI_InterruptHandler, IRQF_TRIGGER_LOW, "mtkdpi", NULL) < 0) { + DISPERR("[DPI]fail to request DPI irq\n"); + return DPI_STATUS_ERROR; + } + + struct DPI_REG_INTERRUPT enInt = DPI_REG->INT_ENABLE; + + enInt.VSYNC = 1; + DPI_OUTREGBIT(cmdq, struct DPI_REG_INTERRUPT, DPI_REG->INT_ENABLE, VSYNC, enInt.VSYNC); +#endif + +#ifndef CONFIG_MTK_CLKMGR + /* apmixed */ + node = of_find_compatible_node(NULL, NULL, "mediatek,APMIXED"); + if (!node) + pr_debug("[CLK_APMIXED] find node failed\n"); + + clk_apmixed_base = of_iomap(node, 0); + if (!clk_apmixed_base) + pr_debug("[CLK_APMIXED] base failed\n"); +#endif + + DISPDBG("[DPI]ddp_dpi_init done\n"); + + return 0; +} + +int ddp_dpi_deinit(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + DISPMSG("[DPI]ddp_dpi_deinit +\n"); + ddp_dpi_stop(DISP_MODULE_DPI, cmdq_handle); + ddp_dpi_power_off(DISP_MODULE_DPI, cmdq_handle); + + return 0; +} + +int ddp_dpi_set_lcm_utils(DISP_MODULE_ENUM module, LCM_DRIVER *lcm_drv) +{ + LCM_UTIL_FUNCS *utils = NULL; + + DISPFUNC(); + if (lcm_drv == NULL) { + DISPERR("[DPI]lcm_drv is null !\n"); + return -1; + } + + utils = (LCM_UTIL_FUNCS *)&lcm_utils_dpi; + + utils->set_reset_pin = lcm_set_reset_pin; + utils->udelay = lcm_udelay; + utils->mdelay = lcm_mdelay; + utils->send_cmd = lcm_send_cmd, + utils->send_data = lcm_send_data, lcm_drv->set_util_funcs(utils); + + return 0; +} + +int ddp_dpi_build_cmdq(DISP_MODULE_ENUM module, void *cmdq_trigger_handle, CMDQ_STATE state) +{ + return 0; +} + +int ddp_dpi_dump(DISP_MODULE_ENUM module, int level) +{ + unsigned i; + + DISPDMP("---------- Start dump DPI registers ----------\n"); + + for (i = 0; i <= 0x50; i += 4) + DISPDMP("DPI+%04x : 0x%08x\n", i, INREG32(DISPSYS_DPI_BASE + i)); + + for (i = 0x68; i <= 0x7C; i += 4) + DISPDMP("DPI+%04x : 0x%08x\n", i, INREG32(DISPSYS_DPI_BASE + i)); + + DISPDMP("DPI+Color Bar : 0x%04x : 0x%08x\n", 0xF00, INREG32(DISPSYS_DPI_BASE + 0xF00)); + /*DISPDMP("DPI Addr IO Driving : 0x%08x\n", INREG32(DISPSYS_IO_DRIVING));*/ + /*DISPDMP("DPI TVDPLL CON0 : 0x%08x\n", INREG32(DDP_REG_TVDPLL_CON0));*/ + /*DISPDMP("DPI TVDPLL CON1 : 0x%08x\n", INREG32(DDP_REG_TVDPLL_CON1));*/ + /*DISPDMP("DPI TVDPLL CON6 : 0x%08x\n", INREG32(DDP_REG_TVDPLL_CON6));*/ + DISPDMP("DPI MMSYS_CG_CON1:0x%08x\n", INREG32(DISP_REG_CONFIG_MMSYS_CG_CON1)); + return 0; +} + + +int ddp_dpi_ioctl(DISP_MODULE_ENUM module, void *cmdq_handle, DDP_IOCTL_NAME ioctl_cmd, + void *params) +{ + int ret = 0; + + DISPDBG("[DPI]DPI ioctl : % d\n", ioctl_cmd); + + switch (ioctl_cmd) { + case DDP_DPI_FACTORY_TEST: + { + disp_ddp_path_config *config_info = (disp_ddp_path_config *) params; + + ddp_path_top_clock_on(); + ddp_dpi_power_on(module, NULL); + ddp_dpi_stop(module, NULL); + ddp_dpi_config(module, config_info, NULL); + ddp_dpi_EnableColorBar(); + + ddp_dpi_trigger(module, NULL); + ddp_dpi_start(module, NULL); + ddp_dpi_dump(module, 1); + break; + } + default: + break; + } + + return ret; +} + +DDP_MODULE_DRIVER ddp_driver_dpi = { + .module = DISP_MODULE_DPI, + .init = ddp_dpi_init, + .deinit = ddp_dpi_deinit, + .config = ddp_dpi_config, + .build_cmdq = ddp_dpi_build_cmdq, + .trigger = ddp_dpi_trigger, + .start = ddp_dpi_start, + .stop = ddp_dpi_stop, + .reset = ddp_dpi_reset, + .power_on = ddp_dpi_power_on, + .power_off = ddp_dpi_power_off, + .is_idle = ddp_dpi_is_idle, + .is_busy = ddp_dpi_is_busy, + .dump_info = ddp_dpi_dump, + .set_lcm_utils = ddp_dpi_set_lcm_utils, + .ioctl = ddp_dpi_ioctl +}; + diff --git a/drivers/misc/mediatek/video/mt6755/ddp_dpi.h b/drivers/misc/mediatek/video/mt6755/ddp_dpi.h new file mode 100644 index 0000000000000000000000000000000000000000..ce30f44d01ac9952219a1cf2664f1b4a4a129a38 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_dpi.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DDP_DPI_H__ +#define __DDP_DPI_H__ + +/*#include */ +#include + +#include "lcm_drv.h" +#include "ddp_info.h" +#include "cmdq_record.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef NULL +#define NULL (0) +#endif + +#define DPI_PHY_ADDR 0x14012000 + +#define DPI_CHECK_RET(expr) \ + do { \ + enum DPI_STATUS ret = (expr); \ + ASSERT(DPI_STATUS_OK == ret); \ + } while (0) \ + +/*for legacy DPI Driver*/ +enum LCD_IF_ID { + LCD_IF_PARALLEL_0 = 0, + LCD_IF_PARALLEL_1 = 1, + LCD_IF_PARALLEL_2 = 2, + LCD_IF_SERIAL_0 = 3, + LCD_IF_SERIAL_1 = 4, + + LCD_IF_ALL = 0xFF, +}; + +struct LCD_REG_CMD_ADDR { + unsigned rsv_0:4; + unsigned addr:4; + unsigned rsv_8:24; +}; + +struct LCD_REG_DAT_ADDR { + unsigned rsv_0:4; + unsigned addr:4; + unsigned rsv_8:24; +}; + +enum LCD_IF_FMT_COLOR_ORDER { + LCD_IF_FMT_COLOR_ORDER_RGB = 0, + LCD_IF_FMT_COLOR_ORDER_BGR = 1, +}; + + +enum LCD_IF_FMT_TRANS_SEQ { + LCD_IF_FMT_TRANS_SEQ_MSB_FIRST = 0, + LCD_IF_FMT_TRANS_SEQ_LSB_FIRST = 1, +}; + + +enum LCD_IF_FMT_PADDING { + LCD_IF_FMT_PADDING_ON_LSB = 0, + LCD_IF_FMT_PADDING_ON_MSB = 1, +}; + + +enum LCD_IF_FORMAT { + LCD_IF_FORMAT_RGB332 = 0, + LCD_IF_FORMAT_RGB444 = 1, + LCD_IF_FORMAT_RGB565 = 2, + LCD_IF_FORMAT_RGB666 = 3, + LCD_IF_FORMAT_RGB888 = 4, +}; + +enum LCD_IF_WIDTH { + LCD_IF_WIDTH_8_BITS = 0, + LCD_IF_WIDTH_9_BITS = 2, + LCD_IF_WIDTH_16_BITS = 1, + LCD_IF_WIDTH_18_BITS = 3, + LCD_IF_WIDTH_24_BITS = 4, + LCD_IF_WIDTH_32_BITS = 5, +}; + +enum DPI_STATUS { + DPI_STATUS_OK = 0, + + DPI_STATUS_ERROR, +}; + +enum DPI_POLARITY { + DPI_POLARITY_RISING = 0, + DPI_POLARITY_FALLING = 1 +}; + +enum DPI_RGB_ORDER { + DPI_RGB_ORDER_RGB = 0, + DPI_RGB_ORDER_BGR = 1, +}; + +enum DPI_CLK_FREQ { + DPI_CLK_480p = 27027, + DPI_CLK_EINK_85 = 34989, + DPI_CLK_EINK_100 = 41164, + DPI_CLK_480p_3D = 27027 * 2, + DPI_CLK_720p = 74250, + DPI_CLK_1080p = 148500 +}; + +struct LCD_REG_WROI_CON { + unsigned RGB_ORDER:1; + unsigned BYTE_ORDER:1; + unsigned PADDING:1; + unsigned DATA_FMT:3; + unsigned IF_FMT:2; + unsigned COMMAND:5; + unsigned rsv_13:2; + unsigned ENC:1; + unsigned rsv_16:8; + unsigned SEND_RES_MODE:1; + unsigned IF_24:1; + unsigned rsv_6:6; +}; + +int ddp_dpi_stop(DISP_MODULE_ENUM module, void *cmdq_handle); +int ddp_dpi_power_on(DISP_MODULE_ENUM module, void *cmdq_handle); +int ddp_dpi_power_off(DISP_MODULE_ENUM module, void *cmdq_handle); +int ddp_dpi_dump(DISP_MODULE_ENUM module, int level); +int ddp_dpi_start(DISP_MODULE_ENUM module, void *cmdq); +int ddp_dpi_init(DISP_MODULE_ENUM module, void *cmdq); +int ddp_dpi_deinit(DISP_MODULE_ENUM module, void *cmdq_handle); +int ddp_dpi_config(DISP_MODULE_ENUM module, disp_ddp_path_config *config, + void *cmdq_handle); +int ddp_dpi_trigger(DISP_MODULE_ENUM module, void *cmdq); +int ddp_dpi_reset(DISP_MODULE_ENUM module, void *cmdq_handle); +int ddp_dpi_ioctl(DISP_MODULE_ENUM module, void *cmdq_handle, DDP_IOCTL_NAME ioctl_cmd, + void *params); + +int _Enable_Interrupt(void); + +#ifdef __cplusplus +} +#endif +#endif /*__DPI_DRV_H__*/ diff --git a/drivers/misc/mediatek/video/mt6755/ddp_dpi_reg.h b/drivers/misc/mediatek/video/mt6755/ddp_dpi_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..425f6cdb621241d4118e4ea3777782a0e331d1cf --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_dpi_reg.h @@ -0,0 +1,510 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DDP_DPI_REG_H__ +#define __DDP_DPI_REG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct DPI_REG_EN { + unsigned EN:1; + unsigned rsv_1:31; +}; + +struct DPI_REG_RST { + unsigned RST:1; + unsigned rsv_1:31; +}; + +struct DPI_REG_INTERRUPT { + unsigned VSYNC:1; + unsigned VDE:1; + unsigned UNDERFLOW:1; + unsigned rsv_3:29; +}; + +struct DPI_REG_CNTL { + unsigned BG_EN:1; + unsigned RGB_SWAP:1; + unsigned INTL_EN:1; + unsigned TDFP_EN:1; + unsigned CLPF_EN:1; + unsigned YUV422_EN:1; + unsigned RGB2YUV_EN:1; + unsigned rsv_7:1; + unsigned EMBSYNC_EN:1; + unsigned rsv_9:3; + unsigned PIXREP:4; + unsigned VS_LODD_EN:1; + unsigned VS_LEVEN_EN:1; + unsigned VS_RODD_EN:1; + unsigned VS_REVEN_EN:1; + unsigned FAKE_DE_LODD:1; + unsigned FAKE_DE_LEVEN:1; + unsigned FAKE_DE_RODD:1; + unsigned FAKE_DE_REVEN:1; + unsigned rsv_24:8; +}; + +struct DPI_REG_OUTPUT_SETTING { + unsigned CH_SWAP:3; + unsigned BIT_SWAP:1; + unsigned B_MASK:1; + unsigned G_MASK:1; + unsigned R_MASK:1; + unsigned rsv_7:1; + unsigned DE_MASK:1; + unsigned HS_MASK:1; + unsigned VS_MASK:1; + unsigned rsv_11:1; + unsigned DE_POL:1; + unsigned HSYNC_POL:1; + unsigned VSYNC_POL:1; + unsigned CLK_POL:1; + unsigned DPI_O_EN:1; + unsigned DUAL_EDGE_SEL:1; + unsigned OUT_BIT:2; + unsigned YC_MAP:3; + unsigned rsv_23:9; +}; + +struct DPI_REG_SIZE { + unsigned WIDTH:13; + unsigned rsv_13:3; + unsigned HEIGHT:13; + unsigned rsv_28:3; +}; + +struct DPI_REG_DDR_SETTING { + unsigned DDR_EN:1; + unsigned DDR_SEL:1; + unsigned DDR_4PHASE:1; + unsigned DATA_THROT:1; + unsigned DDR_WIDTH:2; + unsigned rsv_6:2; + unsigned DDR_PAD_MODE:1; + unsigned rsv_9:23; +}; + +struct DPI_REG_TGEN_HPORCH { + unsigned HBP:12; + unsigned rsv_12:4; + unsigned HFP:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_TGEN_VWIDTH_LODD { + unsigned VPW_LODD:12; + unsigned rsv_12:4; + unsigned VPW_HALF_LODD:1; + unsigned rsv_17:15; +}; + +struct DPI_REG_TGEN_VPORCH_LODD { + unsigned VBP_LODD:12; + unsigned rsv_12:4; + unsigned VFP_LODD:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_BG_HCNTL { + unsigned BG_RIGHT:13; + unsigned rsv_13:3; + unsigned BG_LEFT:13; + unsigned rsv_29:3; +}; + +struct DPI_REG_BG_VCNTL { + unsigned BG_BOT:13; + unsigned rsv_13:3; + unsigned BG_TOP:13; + unsigned rsv_29:3; +}; + + +struct DPI_REG_BG_COLOR { + unsigned BG_B:8; + unsigned BG_G:8; + unsigned BG_R:8; + unsigned rsv_24:8; +}; + +struct DPI_REG_FIFO_CTL { + unsigned FIFO_VALID_SET:5; + unsigned rsv_5:3; + unsigned FIFO_RST_SEL:1; + unsigned rsv_9:23; +}; + +struct DPI_REG_STATUS { + unsigned V_CNT:13; + unsigned rsv_13:3; + unsigned DPI_BUSY:1; + unsigned OUT_EN:1; + unsigned rsv_18:2; + unsigned FIELD:1; + unsigned TDLR:1; + unsigned rsv_22:10; +}; + +struct DPI_REG_TMODE { + unsigned OEN_EN:1; + unsigned rsv_1:31; +}; + +struct DPI_REG_CHKSUM { + unsigned CHKSUM:24; + unsigned rsv_24:6; + unsigned CHKSUM_RDY:1; + unsigned CHKSUM_EN:1; +}; + +struct DPI_REG_TGEN_VWIDTH_LEVEN { + unsigned VPW_LEVEN:12; + unsigned rsv_12:4; + unsigned VPW_HALF_LEVEN:1; + unsigned rsv_17:15; +}; + +struct DPI_REG_TGEN_VPORCH_LEVEN { + unsigned VBP_LEVEN:12; + unsigned rsv_12:4; + unsigned VFP_LEVEN:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_TGEN_VWIDTH_RODD { + unsigned VPW_RODD:12; + unsigned rsv_12:4; + unsigned VPW_HALF_RODD:1; + unsigned rsv_17:15; +}; + +struct DPI_REG_TGEN_VPORCH_RODD { + unsigned VBP_RODD:12; + unsigned rsv_12:4; + unsigned VFP_RODD:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_TGEN_VWIDTH_REVEN { + unsigned VPW_REVEN:12; + unsigned rsv_12:4; + unsigned VPW_HALF_REVEN:1; + unsigned rsv_17:15; +}; + +struct DPI_REG_TGEN_VPORCH_REVEN { + unsigned VBP_REVEN:12; + unsigned rsv_12:4; + unsigned VFP_REVEN:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_ESAV_VTIM_LOAD { + unsigned ESAV_VOFST_LODD:12; + unsigned rsv_12:4; + unsigned ESAV_VWID_LODD:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_ESAV_VTIM_LEVEN { + unsigned ESAV_VVOFST_LEVEN:12; + unsigned rsv_12:4; + unsigned ESAV_VWID_LEVEN:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_ESAV_VTIM_ROAD { + unsigned ESAV_VOFST_RODD:12; + unsigned rsv_12:4; + unsigned ESAV_VWID_RODD:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_ESAV_VTIM_REVEN { + unsigned ESAV_VOFST_REVEN:12; + unsigned rsv_12:4; + unsigned ESAV_VWID_REVEN:12; + unsigned rsv_28:4; +}; + + +struct DPI_REG_ESAV_FTIM { + unsigned ESAV_FOFST_ODD:12; + unsigned rsv_12:4; + unsigned ESAV_FOFST_EVEN:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_CLPF_SETTING { + unsigned CLPF_TYPE:2; + unsigned rsv2:2; + unsigned ROUND_EN:1; + unsigned rsv5:27; +}; + +struct DPI_REG_Y_LIMIT { + unsigned Y_LIMIT_BOT:12; + unsigned rsv12:4; + unsigned Y_LIMIT_TOP:12; + unsigned rsv28:4; +}; + +struct DPI_REG_C_LIMIT { + unsigned C_LIMIT_BOT:12; + unsigned rsv12:4; + unsigned C_LIMIT_TOP:12; + unsigned rsv28:4; +}; + +struct DPI_REG_YUV422_SETTING { + unsigned UV_SWAP:1; + unsigned rsv1:3; + unsigned CR_DELSEL:1; + unsigned CB_DELSEL:1; + unsigned Y_DELSEL:1; + unsigned DE_DELSEL:1; + unsigned rsv8:24; +}; + +struct DPI_REG_EMBSYNC_SETTING { + unsigned EMBVSYNC_R_CR:1; + unsigned EMBVSYNC_G_Y:1; + unsigned EMBVSYNC_B_CB:1; + unsigned rsv_3:1; + unsigned ESAV_F_INV:1; + unsigned ESAV_V_INV:1; + unsigned ESAV_H_INV:1; + unsigned rsv_7:1; + unsigned ESAV_CODE_MAN:1; + unsigned rsv_9:3; + unsigned VS_OUT_SEL:3; + unsigned rsv_15:1; + unsigned EMBSYNC_OPT:1; + unsigned rsv_17:15; +}; + +struct DPI_REG_ESAV_CODE_SET0 { + unsigned ESAV_CODE0:12; + unsigned rsv_12:4; + unsigned ESAV_CODE1:12; + unsigned rsv_28:4; +}; + +struct DPI_REG_ESAV_CODE_SET1 { + unsigned ESAV_CODE2:12; + unsigned rsv_12:4; + unsigned ESAV_CODE3_MSB:1; + unsigned rsv_17:15; +}; + +struct DPI_REG_PATTERN { + unsigned PAT_EN:1; + unsigned rsv_1:3; + unsigned PAT_SEL:3; + unsigned rsv_6:1; + unsigned PAT_B_MAN:8; + unsigned PAT_G_MAN:8; + unsigned PAT_R_MAN:8; +}; + +/*not be used*/ +struct DPI_REG_TGEN_HCNTL { + unsigned HPW:8; + unsigned HBP:8; + unsigned HFP:8; + unsigned HSYNC_POL:1; + unsigned DE_POL:1; + unsigned rsv_26:6; +}; + +struct DPI_REG_TGEN_VCNTL { + unsigned VPW:8; + unsigned VBP:8; + unsigned VFP:8; + unsigned VSYNC_POL:1; + unsigned rsv_25:7; +}; +/*not be used end*/ + +struct DPI_REG_MATRIX_COEFF_SET0 { + unsigned MATRIX_C00:13; + unsigned rsv_13:3; + unsigned MATRIX_C01:13; + unsigned rsv_29:3; +}; + +struct DPI_REG_MATRIX_COEFF_SET1 { + unsigned MATRIX_C02:13; + unsigned rsv_13:3; + unsigned MATRIX_C10:13; + unsigned rsv_29:3; +}; + +struct DPI_REG_MATRIX_COEFF_SET2 { + unsigned MATRIX_C11:13; + unsigned rsv_13:3; + unsigned MATRIX_C12:13; + unsigned rsv_29:3; +}; + +struct DPI_REG_MATRIX_COEFF_SET3 { + unsigned MATRIX_C20:13; + unsigned rsv_13:3; + unsigned MATRIX_C21:13; + unsigned rsv_29:3; +}; + +struct DPI_REG_MATRIX_COEFF_SET4 { + unsigned MATRIX_C22:13; + unsigned rsv_13:19; +}; + +struct DPI_REG_MATRIX_PREADD_SET0 { + unsigned MATRIX_PRE_ADD_0:9; + unsigned rsv_9:7; + unsigned MATRIX_PRE_ADD_1:9; + unsigned rsv_24:7; +}; + +struct DPI_REG_MATRIX_PREADD_SET1 { + unsigned MATRIX_PRE_ADD_2:9; + unsigned rsv_9:23; +}; + +struct DPI_REG_MATRIX_POSTADD_SET0 { + unsigned MATRIX_POST_ADD_0:13; + unsigned rsv_13:3; + unsigned MATRIX_POST_ADD_1:13; + unsigned rsv_24:3; +}; + +struct DPI_REG_MATRIX_POSTADD_SET1 { + unsigned MATRIX_POST_ADD_2:13; + unsigned rsv_13:19; +}; + +struct DPI_REG_MATRIX_SET { + unsigned INT_MATRIX_SEL :5; + unsigned rsv_3 :3; + unsigned MATRIX_BIT :2; + unsigned rsv_2 :2; + unsigned EXT_MATRIX_EN :1; + unsigned rsv_19 :19; +}; + +struct DPI_REG_MATRIX_COEF { + unsigned MATRIX_COFEF_00 :13; + unsigned rsv_13 :3; + unsigned MATRIX_COFEF_01 :13; + unsigned rsv_29 :3; +}; + +struct DPI_REG_MATRIX_COEF_ONE { + unsigned MATRIX_COFEF_00 :13; + unsigned rsv_19 :19; +}; + + +struct DPI_REG_MATRIX_OFFSET { + unsigned MATRIX_OFFSET_0 :13; + unsigned rsv_3 :3; + unsigned MATRIX_OFFSET_1 :13; + unsigned rsv :3; +}; + +struct DPI_REG_MATRIX_OFFSET_ONE { + unsigned MATRIX_OFFSET_0 :13; + unsigned rsv_19 :19; +}; + +struct DPI_REGS { + struct DPI_REG_EN DPI_EN; /*0000*/ + struct DPI_REG_RST DPI_RST; /*0004*/ + struct DPI_REG_INTERRUPT INT_ENABLE; /* 0008*/ + struct DPI_REG_INTERRUPT INT_STATUS; /*000C*/ + struct DPI_REG_CNTL CNTL; /*0010*/ + struct DPI_REG_OUTPUT_SETTING OUTPUT_SETTING; /*0014*/ + struct DPI_REG_SIZE SIZE; /*0018*/ + struct DPI_REG_DDR_SETTING DDR_SETTING; /*001c*/ + + unsigned TGEN_HWIDTH; /*0020*/ + struct DPI_REG_TGEN_HPORCH TGEN_HPORCH; /*0024*/ + struct DPI_REG_TGEN_VWIDTH_LODD TGEN_VWIDTH_LODD; /* 0028*/ + struct DPI_REG_TGEN_VPORCH_LODD TGEN_VPORCH_LODD; /*002C*/ + + struct DPI_REG_BG_HCNTL BG_HCNTL; /*0030*/ + struct DPI_REG_BG_VCNTL BG_VCNTL; /* 0034*/ + struct DPI_REG_BG_COLOR BG_COLOR; /*0038*/ + struct DPI_REG_FIFO_CTL FIFO_CTL; /*003C*/ + + struct DPI_REG_STATUS STATUS; /*0040*/ + struct DPI_REG_TMODE TMODE; /*0044*/ + struct DPI_REG_CHKSUM CHKSUM; /*0048*/ + unsigned rsv_4C; + unsigned DUMMY; /*0050*/ + unsigned rsv_54[5]; + + struct DPI_REG_TGEN_VWIDTH_LEVEN TGEN_VWIDTH_LEVEN; /*0068*/ + struct DPI_REG_TGEN_VPORCH_LEVEN TGEN_VPORCH_LEVEN; /* 006C*/ + + struct DPI_REG_TGEN_VWIDTH_RODD TGEN_VWIDTH_RODD; /*0070*/ + struct DPI_REG_TGEN_VPORCH_RODD TGEN_VPORCH_RODD; /*0074*/ + struct DPI_REG_TGEN_VWIDTH_REVEN TGEN_VWIDTH_REVEN; /*0078*/ + struct DPI_REG_TGEN_VPORCH_REVEN TGEN_VPORCH_REVEN; /*007C*/ + struct DPI_REG_ESAV_VTIM_LOAD ESAV_VTIM_LOAD; /*0080*/ + struct DPI_REG_ESAV_VTIM_LEVEN ESAV_VTIM_LEVEN; /*0084*/ + struct DPI_REG_ESAV_VTIM_ROAD ESAV_VTIM_ROAD; /*0088*/ + struct DPI_REG_ESAV_VTIM_REVEN ESAV_VTIM_REVEN; /*008C*/ + + struct DPI_REG_ESAV_FTIM ESAV_FTIM; /*0090*/ + struct DPI_REG_CLPF_SETTING CLPF_SETTING; /*0094*/ + struct DPI_REG_Y_LIMIT Y_LIMIT; /*0098*/ + struct DPI_REG_C_LIMIT C_LIMIT; /*009C*/ + struct DPI_REG_YUV422_SETTING YUV422_SETTING; /*00A0*/ + struct DPI_REG_EMBSYNC_SETTING EMBSYNC_SETTING; /*00A4*/ + struct DPI_REG_ESAV_CODE_SET0 ESAV_CODE_SET0; /*00A8*/ + struct DPI_REG_ESAV_CODE_SET1 ESAV_CODE_SET1; /*00AC*/ + + unsigned rsv_4; /* 00B0*/ + + struct DPI_REG_MATRIX_SET MATRIX_SET; /*00B4*/ + struct DPI_REG_MATRIX_COEF MATRIX_COEF_00; /*00B8*/ + struct DPI_REG_MATRIX_COEF MATRIX_COEF_02; /*00BC*/ + struct DPI_REG_MATRIX_COEF MATRIX_COEF_11; /*00C0*/ + struct DPI_REG_MATRIX_COEF MATRIX_COEF_20; /*00C4*/ + struct DPI_REG_MATRIX_COEF_ONE MATRIX_COEF_22; /*00C8*/ + struct DPI_REG_MATRIX_OFFSET MATRIX_IN_OFFSET_0; /*00CC*/ + struct DPI_REG_MATRIX_OFFSET_ONE MATRIX_IN_OFFSET_2; /*00D0*/ + struct DPI_REG_MATRIX_OFFSET MATRIX_OUT_OFFSET_0; /*00D4*/ + struct DPI_REG_MATRIX_OFFSET_ONE MATRIX_OUT_OFFSET_2; /*00D8*/ + +}; + +extern struct DPI_REGS *DPI_REG; + +/* +STATIC_ASSERT((offsetof(struct DPI_REGS, SIZE) == 0x0018)); +STATIC_ASSERT((offsetof(struct DPI_REGS, BG_COLOR) == 0x0038)); +STATIC_ASSERT((offsetof(struct DPI_REGS, TGEN_VWIDTH_RODD) == 0x0070)); +STATIC_ASSERT((offsetof(struct DPI_REGS, ESAV_CODE_SET1) == 0x00AC)); +*/ +#ifdef __cplusplus +} +#endif +#endif /*__DPI_REG_H__*/ diff --git a/drivers/misc/mediatek/video/mt6755/ddp_drv.c b/drivers/misc/mediatek/video/mt6755/ddp_drv.c new file mode 100644 index 0000000000000000000000000000000000000000..1ad88396ab2b4737db4754c19e62a10a7ea24a69 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_drv.c @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "ddp_drv" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* ION */ +/* #include */ +/* #include */ +/* #include */ +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include "ddp_clkmgr.h" +#endif +#include +#include "m4u.h" + +#include "ddp_drv.h" +#include "ddp_reg.h" +#include "ddp_hal.h" +#include "disp_log.h" +#include "ddp_irq.h" +#include "ddp_info.h" +#include "ddp_dpi_reg.h" +#include "disp_helper.h" + + +#define DISP_DEVNAME "DISPSYS" +/* device and driver */ +static dev_t disp_devno; +static struct cdev *disp_cdev; +static struct class *disp_class; + +typedef struct { + pid_t open_pid; + pid_t open_tgid; + struct list_head testList; + spinlock_t node_lock; +} disp_node_struct; + +static struct platform_device mydev; +static struct dispsys_device *dispsys_dev; +unsigned int dispsys_irq[DISP_REG_NUM] = { 0 }; +volatile unsigned long dispsys_reg[DISP_REG_NUM] = { 0 }; + +volatile unsigned long mipi_tx_reg = 0; +volatile unsigned long dsi_reg_va = 0; +/* from DTS, for debug */ +unsigned long ddp_reg_pa_base[DISP_REG_NUM] = { + 0x14000000, /*CONFIG*/ + 0x14008000, /*OVL0 */ + 0x14009000, /*OVL1 */ + 0x1400A000, /*RDMA0 */ + 0x1400B000, /*RDMA1 */ + 0x1400C000, /*WDMA0 */ + 0x1400D000, /*COLOR*/ + 0x1400E000, /*CCORR*/ + 0x1400F000, /*AAL*/ + 0x14010000, /*GAMMA*/ + 0x14011000, /*DITHER*/ + 0x14012000, /*DSI0 */ + 0x14013000, /*DPI0 */ + 0x1100E000, /*PWM*/ + 0x14014000, /*MUTEX*/ + 0x14015000, /*SMI_LARB0 */ + 0x14016000, /*SMI_COMMON */ + 0x14017000, /*WDMA1 */ + 0x14018000, /*OVL0_2L */ + 0x14019000, /*OVL1_2L */ + 0x10215000 /*MIPITX*/ +}; + +#ifndef CONFIG_MTK_CLKMGR +/* + * Note: The name order of the disp_clk_name[] must be synced with + * the enum ddp_clk_id(ddp_clkmgr.h) in case get the wrong clock. + */ +const char *disp_clk_name[MAX_DISP_CLK_CNT] = { + "DISP0_SMI_COMMON", + "DISP0_SMI_LARB0", + "DISP0_DISP_OVL0", + "DISP0_DISP_OVL1", + "DISP0_DISP_RDMA0", + "DISP0_DISP_RDMA1", + "DISP0_DISP_WDMA0", + "DISP0_DISP_COLOR", + "DISP0_DISP_CCORR", + "DISP0_DISP_AAL", + "DISP0_DISP_GAMMA", + "DISP0_DISP_DITHER", + "DISP0_DISP_UFOE_MOUT", + "DISP0_DISP_WDMA1", + "DISP0_DISP_2L_OVL0", + "DISP0_DISP_2L_OVL1", + "DISP0_DISP_OVL0_MOUT", + "DISP1_DSI_ENGINE", + "DISP1_DSI_DIGITAL", + "DISP1_DPI_ENGINE", + "DISP1_DPI_PIXEL", + "DISP_PWM", + "DISP_MTCMOS_CLK", + "MUX_DPI0", + "TVDPLL_D2", + "TVDPLL_D4", + "TVDPLL_D8", + "TVDPLL_D16", + "DPI_CK", + "MUX_PWM", + "UNIVPLL2_D4", + "OSC_D2", + "OSC_D8", + "MUX_MM", + "MM_VENCPLL", + "SYSPLL2_D2" +}; + +#endif +/* +static unsigned int ddp_ms2jiffies(unsigned long ms) +{ + return (ms * HZ + 512) >> 10; +} +*/ + +struct dispsys_device { + void __iomem *regs[DISP_REG_NUM]; + struct device *dev; + int irq[DISP_REG_NUM]; +#ifndef CONFIG_MTK_CLKMGR + struct clk *disp_clk[MAX_DISP_CLK_CNT]; +#endif +}; + + +static int disp_is_intr_enable(DISP_REG_ENUM module) +{ + switch (module) { + case DISP_REG_OVL0: + case DISP_REG_OVL1: + case DISP_REG_OVL0_2L: + case DISP_REG_OVL1_2L: + case DISP_REG_RDMA0: + case DISP_REG_RDMA1: + /*case DISP_REG_WDMA0:*/ + case DISP_REG_WDMA1: + case DISP_REG_MUTEX: + case DISP_REG_DSI0: + case DISP_REG_DPI0: + case DISP_REG_AAL: + return 1; + + case DISP_REG_COLOR: + case DISP_REG_CCORR: + case DISP_REG_GAMMA: + case DISP_REG_DITHER: + case DISP_REG_PWM: + case DISP_REG_CONFIG: + case DISP_REG_SMI_LARB0: + case DISP_REG_SMI_COMMON: + case DISP_REG_MIPI: + return 0; + + case DISP_REG_WDMA0: +#if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT) + return 0; +#else + return 1; +#endif + default: + return 0; + } +} + +m4u_callback_ret_t disp_m4u_callback(int port, unsigned int mva, void *data) +{ + DISP_MODULE_ENUM module = DISP_MODULE_OVL0; + m4u_callback_ret_t ret; + + ret = M4U_CALLBACK_HANDLED; + DISPERR("fault call port=%d, mva=0x%x, data=0x%p\n", port, mva, data); + switch (port) { + case M4U_PORT_DISP_OVL0: + module = DISP_MODULE_OVL0; + break; + case M4U_PORT_DISP_RDMA0: + module = DISP_MODULE_RDMA0; + break; + case M4U_PORT_DISP_WDMA0: + module = DISP_MODULE_WDMA0; + break; + case M4U_PORT_DISP_OVL1: + module = DISP_MODULE_OVL1; + break; + case M4U_PORT_DISP_RDMA1: + module = DISP_MODULE_RDMA1; + break; + case M4U_PORT_DISP_WDMA1: + module = DISP_MODULE_WDMA1; + break; + case M4U_PORT_DISP_2L_OVL0: + module = DISP_MODULE_OVL0_2L; + break; + case M4U_PORT_DISP_2L_OVL1: + module = DISP_MODULE_OVL1_2L; + break; + default: + ret = M4U_CALLBACK_NOT_HANDLED; + DISPERR("unknown port=%d\n", port); + } + ddp_dump_analysis(module); + ddp_dump_reg(module); + return ret; +} + + +struct device *disp_get_device(void) +{ + return dispsys_dev->dev; +} + +static int disp_probe(struct platform_device *pdev) +{ + struct class_device; + int i; + static unsigned int disp_probe_cnt; + + if (disp_probe_cnt != 0) + return 0; + + /* save pdev for disp_probe_1 */ + memcpy(&mydev, pdev, sizeof(mydev)); + + if (dispsys_dev) { + DISPERR("%s: dispsys_dev=0x%p\n", __func__, dispsys_dev); + BUG(); + } + + dispsys_dev = kmalloc(sizeof(struct dispsys_device), GFP_KERNEL); + if (!dispsys_dev) { + DISPERR("Unable to allocate dispsys_dev\n"); + return -ENOMEM; + } + +#ifndef CONFIG_MTK_CLKMGR + for (i = 0; i < MAX_DISP_CLK_CNT; i++) { + DISPMSG("DISPSYS get clock %s\n", disp_clk_name[i]); + dispsys_dev->disp_clk[i] = devm_clk_get(&pdev->dev, disp_clk_name[i]); + if (IS_ERR(dispsys_dev->disp_clk[i])) + DISPERR("%s:%d, DISPSYS get %d,%s clock error!!!\n", + __FILE__, __LINE__, i, disp_clk_name[i]); + else { + if (!ddp_set_clk_handle(dispsys_dev->disp_clk[i], i)) { + switch (i) { + case MUX_MM: + case MM_VENCPLL: + case SYSPLL2_D2: + break; /* no need prepare_enable here */ + case DISP0_SMI_COMMON: + case DISP0_SMI_LARB0: + case DISP_MTCMOS_CLK: + ddp_clk_prepare_enable(i); + break; + default: + ddp_clk_prepare(i); + break; + } + } + } + } +#endif /* CONFIG_MTK_CLKMGR */ + disp_probe_cnt++; + + return 0; +} +static int __init disp_probe_1(void) +{ + struct class_device; + int ret; + int i; + struct platform_device *pdev = &mydev; + + + disp_helper_option_init(); + + if (!dispsys_dev) { + DISPERR("%s: dispsys_dev=NULL\n", __func__); + BUG(); + } + + dispsys_dev->dev = &pdev->dev; + + /* iomap registers and irq */ + for (i = 0; i < DISP_REG_NUM; i++) { + struct resource res; + + dispsys_dev->regs[i] = of_iomap(pdev->dev.of_node, i); + if (!dispsys_dev->regs[i]) { + DISPERR("Unable to ioremap registers, of_iomap fail, i=%d\n", i); + return -ENOMEM; + } + dispsys_reg[i] = (unsigned long)dispsys_dev->regs[i]; + /* check physical register */ + of_address_to_resource(pdev->dev.of_node, i, &res); + if (ddp_reg_pa_base[i] != res.start) + DISPERR("DT err, i=%d, module=%s, map_addr=%p, reg_pa=0x%lx!=0x%pa\n", + i, ddp_get_reg_module_name(i), dispsys_dev->regs[i], + ddp_reg_pa_base[i], &res.start); + + /* get IRQ ID and request IRQ */ + dispsys_dev->irq[i] = irq_of_parse_and_map(pdev->dev.of_node, i); + dispsys_irq[i] = dispsys_dev->irq[i]; + + DISPMSG("DT, i=%d, module=%s, map_addr=%p, map_irq=%d, reg_pa=0x%lx\n", + i, ddp_get_reg_module_name(i), dispsys_dev->regs[i], dispsys_dev->irq[i], + ddp_reg_pa_base[i]); + } + /* mipi tx reg map here */ + dsi_reg_va = dispsys_reg[DISP_REG_DSI0]; + mipi_tx_reg = dispsys_reg[DISP_REG_MIPI]; + DPI_REG = (struct DPI_REGS *)dispsys_reg[DISP_REG_DPI0]; + + /* //// power on MMSYS for early porting */ +#ifdef CONFIG_MTK_FPGA + pr_debug("[DISP Probe] power MMSYS:0x%lx,0x%lx\n", DISP_REG_CONFIG_MMSYS_CG_CLR0, + DISP_REG_CONFIG_MMSYS_CG_CLR1); + DISP_REG_SET(NULL, DISP_REG_CONFIG_MMSYS_CG_CLR0, 0xFFFFFFFF); + DISP_REG_SET(NULL, DISP_REG_CONFIG_MMSYS_CG_CLR1, 0xFFFFFFFF); + /* DISP_REG_SET(NULL,DISPSYS_CONFIG_BASE + 0xC04,0x1C000);//fpga should set this register */ +#endif + /* init arrays */ + ddp_path_init(); + + for (i = 0; i < DISP_REG_NUM; i++) { + if (disp_is_intr_enable(i) == 1) { + /* IRQF_TRIGGER_NONE dose not take effect here, real trigger mode set in dts file */ + ret = request_irq(dispsys_dev->irq[i], (irq_handler_t) disp_irq_handler, + IRQF_TRIGGER_NONE, ddp_get_reg_module_name(i), NULL); + if (ret) { + DISPERR + ("Unable to request IRQ, request_irq fail, i=%d, irq=%d\n", + i, dispsys_dev->irq[i]); + return ret; + } + DISPMSG("irq enabled, module=%s, irq=%d\n", + ddp_get_reg_module_name(i), dispsys_dev->irq[i]); + } + } + + /* init M4U callback */ + DISPMSG("register m4u callback\n"); + m4u_register_fault_callback(M4U_PORT_DISP_OVL0, disp_m4u_callback, 0); + m4u_register_fault_callback(M4U_PORT_DISP_RDMA0, disp_m4u_callback, 0); + m4u_register_fault_callback(M4U_PORT_DISP_WDMA0, disp_m4u_callback, 0); + m4u_register_fault_callback(M4U_PORT_DISP_OVL1, disp_m4u_callback, 0); + m4u_register_fault_callback(M4U_PORT_DISP_RDMA1, disp_m4u_callback, 0); + m4u_register_fault_callback(M4U_PORT_DISP_WDMA1, disp_m4u_callback, 0); + m4u_register_fault_callback(M4U_PORT_DISP_2L_OVL0, disp_m4u_callback, 0); + m4u_register_fault_callback(M4U_PORT_DISP_2L_OVL1, disp_m4u_callback, 0); + + + DISPMSG("dispsys probe done.\n"); + /* NOT_REFERENCED(class_dev); */ + return 0; +} + +static int disp_remove(struct platform_device *pdev) +{ + return 0; +} + +static void disp_shutdown(struct platform_device *pdev) +{ + /* Nothing yet */ +} + + +/* PM suspend */ +static int disp_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + return 0; +} + +/* PM resume */ +static int disp_resume(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id dispsys_of_ids[] = { + {.compatible = "mediatek,DISPSYS",}, + {} +}; + +static struct platform_driver dispsys_of_driver = { + .driver = { + .name = DISP_DEVNAME, + .owner = THIS_MODULE, + .of_match_table = dispsys_of_ids, + }, + .probe = disp_probe, + .remove = disp_remove, + .shutdown = disp_shutdown, + .suspend = disp_suspend, + .resume = disp_resume, +}; + +static int __init disp_init(void) +{ + int ret = 0; + + DISPMSG("Register the disp driver\n"); + init_log_buffer(); + if (platform_driver_register(&dispsys_of_driver)) { + DISPERR("failed to register disp driver\n"); + /* platform_device_unregister(&disp_device); */ + ret = -ENODEV; + return ret; + } + DISPMSG("disp driver init done\n"); + return 0; +} + +static void __exit disp_exit(void) +{ +#ifndef CONFIG_MTK_CLKMGR + int i = 0; + + for (i = 0; i < MAX_DISP_CLK_CNT; i++) + ddp_clk_unprepare(i); +#endif + cdev_del(disp_cdev); + unregister_chrdev_region(disp_devno, 1); + + platform_driver_unregister(&dispsys_of_driver); + + device_destroy(disp_class, disp_devno); + class_destroy(disp_class); + +} + +#ifndef MTK_FB_DO_NOTHING +arch_initcall(disp_init); +module_init(disp_probe_1); +module_exit(disp_exit); +#endif +MODULE_AUTHOR("Tzu-Meng, Chung "); +MODULE_DESCRIPTION("Display subsystem Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/video/mt6755/ddp_drv.h b/drivers/misc/mediatek/video/mt6755/ddp_drv.h new file mode 100644 index 0000000000000000000000000000000000000000..bd4244838f7c65cb9d8c4bc74866981d3c648d0a --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_drv.h @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#ifndef __DDP_DRV_H__ +#define __DDP_DRV_H__ +#include +#include "ddp_hal.h" +#include "ddp_aal.h" +#include "ddp_gamma.h" +#include "disp_event.h" + +typedef struct { + unsigned int reg; + unsigned int val; + unsigned int mask; +} DISP_WRITE_REG; + +typedef struct { + unsigned int reg; + unsigned int val; + unsigned int mask; +} DISP_READ_REG; + +#if 0 +typedef struct { + DISP_MODULE_ENUM module; + unsigned int timeout_ms; /* timeout, unit is ms */ +} disp_wait_irq_struct; +#endif + +typedef struct DISP_EXEC_COMMAND { + int taskID; + uint32_t scenario; + uint32_t priority; + uint32_t engineFlag; + uint32_t *pFrameBaseSW; + uint32_t *pTileBaseSW; + uint32_t blockSize; +} DISP_EXEC_COMMAND; + + +/* PQ */ +#define COLOR_TUNING_INDEX 19 +#define THSHP_TUNING_INDEX 12 +#define THSHP_PARAM_MAX 83 +#define PARTIAL_Y_INDEX 10 + +#define GLOBAL_SAT_SIZE 10 +#define CONTRAST_SIZE 10 +#define BRIGHTNESS_SIZE 10 +#define PARTIAL_Y_SIZE 16 +#define PQ_HUE_ADJ_PHASE_CNT 4 +#define PQ_SAT_ADJ_PHASE_CNT 4 +#define PQ_PARTIALS_CONTROL 5 +#define PURP_TONE_SIZE 3 +#define SKIN_TONE_SIZE 8 /* (-6) */ +#define GRASS_TONE_SIZE 6 /* (-2) */ +#define SKY_TONE_SIZE 3 +#define CCORR_COEF_CNT 4 /* ccorr feature */ + + +typedef struct { + unsigned int u4SHPGain; /* 0 : min , 9 : max. */ + unsigned int u4SatGain; /* 0 : min , 9 : max. */ + unsigned int u4PartialY; /* 0 : min , 9 : max. */ + unsigned int u4HueAdj[PQ_HUE_ADJ_PHASE_CNT]; + unsigned int u4SatAdj[PQ_SAT_ADJ_PHASE_CNT]; + unsigned int u4Contrast; /* 0 : min , 9 : max. */ + unsigned int u4Brightness; /* 0 : min , 9 : max. */ + unsigned int u4Ccorr; /* 0 : min , 3 : max. ccorr feature */ +} DISP_PQ_PARAM; + +typedef struct { + int split_en; + int start_x; + int start_y; + int end_x; + int end_y; +} DISP_PQ_WIN_PARAM; + +typedef struct { + int image; + int video; + int camera; +} DISP_PQ_MAPPING_PARAM; + +typedef struct { + unsigned int en; + unsigned int pos_x; + unsigned int pos_y; +} MDP_COLOR_CAP; + +typedef struct { + unsigned int TDS_GAIN_MID; + unsigned int TDS_GAIN_HIGH; + unsigned int TDS_COR_GAIN; + unsigned int TDS_COR_THR; + unsigned int TDS_COR_ZERO; + unsigned int TDS_GAIN; + unsigned int TDS_COR_VALUE; +} MDP_TDSHP_REG; + +typedef struct { + unsigned int GLOBAL_SAT[GLOBAL_SAT_SIZE]; + unsigned int CONTRAST[CONTRAST_SIZE]; + unsigned int BRIGHTNESS[BRIGHTNESS_SIZE]; + unsigned int PARTIAL_Y[PARTIAL_Y_INDEX][PARTIAL_Y_SIZE]; + unsigned int PURP_TONE_S[COLOR_TUNING_INDEX][PQ_PARTIALS_CONTROL][PURP_TONE_SIZE]; + unsigned int SKIN_TONE_S[COLOR_TUNING_INDEX][PQ_PARTIALS_CONTROL][SKIN_TONE_SIZE]; + unsigned int GRASS_TONE_S[COLOR_TUNING_INDEX][PQ_PARTIALS_CONTROL][GRASS_TONE_SIZE]; + unsigned int SKY_TONE_S[COLOR_TUNING_INDEX][PQ_PARTIALS_CONTROL][SKY_TONE_SIZE]; + unsigned int PURP_TONE_H[COLOR_TUNING_INDEX][PURP_TONE_SIZE]; + unsigned int SKIN_TONE_H[COLOR_TUNING_INDEX][SKIN_TONE_SIZE]; + unsigned int GRASS_TONE_H[COLOR_TUNING_INDEX][GRASS_TONE_SIZE]; + unsigned int SKY_TONE_H[COLOR_TUNING_INDEX][SKY_TONE_SIZE]; + unsigned int CCORR_COEF[CCORR_COEF_CNT][3][3]; +} DISPLAY_PQ_T; + +typedef struct { + unsigned int GLOBAL_SAT; + unsigned int CONTRAST; + unsigned int BRIGHTNESS; + unsigned int PARTIAL_Y[PARTIAL_Y_SIZE]; + unsigned int PURP_TONE_S[PQ_PARTIALS_CONTROL][PURP_TONE_SIZE]; + unsigned int SKIN_TONE_S[PQ_PARTIALS_CONTROL][SKIN_TONE_SIZE]; + unsigned int GRASS_TONE_S[PQ_PARTIALS_CONTROL][GRASS_TONE_SIZE]; + unsigned int SKY_TONE_S[PQ_PARTIALS_CONTROL][SKY_TONE_SIZE]; + unsigned int PURP_TONE_H[PURP_TONE_SIZE]; + unsigned int SKIN_TONE_H[SKIN_TONE_SIZE]; + unsigned int GRASS_TONE_H[GRASS_TONE_SIZE]; + unsigned int SKY_TONE_H[SKY_TONE_SIZE]; +} DISPLAY_COLOR_REG_T; + +typedef struct { + + unsigned int entry[THSHP_TUNING_INDEX][THSHP_PARAM_MAX]; + +} DISPLAY_TDSHP_T; + +typedef enum { + DS_en = 0, + iUpSlope, + iUpThreshold, + iDownSlope, + iDownThreshold, + iISO_en, + iISO_thr1, + iISO_thr0, + iISO_thr3, + iISO_thr2, + iISO_IIR_alpha, + iCorZero_clip2, + iCorZero_clip1, + iCorZero_clip0, + iCorThr_clip2, + iCorThr_clip1, + iCorThr_clip0, + iCorGain_clip2, + iCorGain_clip1, + iCorGain_clip0, + iGain_clip2, + iGain_clip1, + iGain_clip0, + PQ_DS_INDEX_MAX +} PQ_DS_index_t; + + +typedef struct { + + int param[PQ_DS_INDEX_MAX]; + +} DISP_PQ_DS_PARAM; + +typedef enum { + BlackEffectEnable = 0, + WhiteEffectEnable, + StrongBlackEffect, + StrongWhiteEffect, + AdaptiveBlackEffect, + AdaptiveWhiteEffect, + ScenceChangeOnceEn, + ScenceChangeControlEn, + ScenceChangeControl, + ScenceChangeTh1, + ScenceChangeTh2, + ScenceChangeTh3, + ContentSmooth1, + ContentSmooth2, + ContentSmooth3, + MiddleRegionGain1, + MiddleRegionGain2, + BlackRegionGain1, + BlackRegionGain2, + BlackRegionRange, + BlackEffectLevel, + BlackEffectParam1, + BlackEffectParam2, + BlackEffectParam3, + BlackEffectParam4, + WhiteRegionGain1, + WhiteRegionGain2, + WhiteRegionRange, + WhiteEffectLevel, + WhiteEffectParam1, + WhiteEffectParam2, + WhiteEffectParam3, + WhiteEffectParam4, + ContrastAdjust1, + ContrastAdjust2, + DCChangeSpeedLevel, + ProtectRegionEffect, + DCChangeSpeedLevel2, + ProtectRegionWeight, + DCEnable +} PQ_DC_index_t; + +typedef struct { + + int param[40]; + +} DISP_PQ_DC_PARAM; + + +/* OD */ +typedef struct { + unsigned int size; + unsigned int type; + unsigned int ret; + unsigned int param0; + unsigned int param1; + unsigned int param2; + unsigned int param3; +} DISP_OD_CMD; + +typedef enum { + DISP_INTERLACE_FORMAT_NONE, + DISP_INTERLACE_FORMAT_TOP_FIELD, + DISP_INTERLACE_FORMAT_BOTTOM_FIELD +} DISP_INTERLACE_FORMAT; + + +extern unsigned int dispsys_irq[DISP_REG_NUM]; +extern volatile unsigned long dispsys_reg[DISP_REG_NUM]; +struct device *disp_get_device(void); + + + +#define DISP_IOCTL_MAGIC 'x' +/* also defined in atci_pq_cmd.h */ +#define DISP_IOCTL_WRITE_REG _IOW(DISP_IOCTL_MAGIC, 1, DISP_WRITE_REG) +#define DISP_IOCTL_READ_REG _IOWR(DISP_IOCTL_MAGIC, 2, DISP_READ_REG) +/* also defined in atci_pq_cmd.h */ +/* #define DISP_IOCTL_WAIT_IRQ _IOR (DISP_IOCTL_MAGIC, 3, disp_wait_irq_struct) */ +#define DISP_IOCTL_DUMP_REG _IOR(DISP_IOCTL_MAGIC, 4, int) +#define DISP_IOCTL_LOCK_THREAD _IOR(DISP_IOCTL_MAGIC, 5, int) +#define DISP_IOCTL_UNLOCK_THREAD _IOR(DISP_IOCTL_MAGIC, 6, int) +#define DISP_IOCTL_MARK_CMQ _IOR(DISP_IOCTL_MAGIC, 7, int) +#define DISP_IOCTL_WAIT_CMQ _IOR(DISP_IOCTL_MAGIC, 8, int) +#define DISP_IOCTL_SYNC_REG _IOR(DISP_IOCTL_MAGIC, 9, int) + +#define DISP_IOCTL_LOCK_MUTEX _IOW(DISP_IOCTL_MAGIC, 20, int) +#define DISP_IOCTL_UNLOCK_MUTEX _IOR(DISP_IOCTL_MAGIC, 21, int) + +#define DISP_IOCTL_LOCK_RESOURCE _IOW(DISP_IOCTL_MAGIC, 25, int) +#define DISP_IOCTL_UNLOCK_RESOURCE _IOR(DISP_IOCTL_MAGIC, 26, int) + +#define DISP_IOCTL_SET_INTR _IOR(DISP_IOCTL_MAGIC, 10, int) +#define DISP_IOCTL_TEST_PATH _IOR(DISP_IOCTL_MAGIC, 11, int) + +#define DISP_IOCTL_CLOCK_ON _IOR(DISP_IOCTL_MAGIC, 12, int) +#define DISP_IOCTL_CLOCK_OFF _IOR(DISP_IOCTL_MAGIC, 13, int) + +#define DISP_IOCTL_RUN_DPF _IOW(DISP_IOCTL_MAGIC, 30, int) +#define DISP_IOCTL_CHECK_OVL _IOR(DISP_IOCTL_MAGIC, 31, int) + +#define DISP_IOCTL_EXEC_COMMAND _IOW(DISP_IOCTL_MAGIC, 33, DISP_EXEC_COMMAND) +#define DISP_IOCTL_RESOURCE_REQUIRE _IOR(DISP_IOCTL_MAGIC, 34, int) + +/* Add for AAL control - S */ +/* 0 : disable AAL event, 1 : enable AAL event */ +#define DISP_IOCTL_AAL_EVENTCTL _IOW(DISP_IOCTL_MAGIC, 15 , int) +/* Get AAL statistics data. */ +#define DISP_IOCTL_AAL_GET_HIST _IOR(DISP_IOCTL_MAGIC, 16 , DISP_AAL_HIST) +/* Update AAL setting */ +#define DISP_IOCTL_AAL_SET_PARAM _IOW(DISP_IOCTL_MAGIC, 17 , DISP_AAL_PARAM) +#define DISP_IOCTL_AAL_INIT_REG _IOW(DISP_IOCTL_MAGIC, 18 , DISP_AAL_INITREG) +#define DISP_IOCTL_SET_GAMMALUT _IOW(DISP_IOCTL_MAGIC, 23 , DISP_GAMMA_LUT_T) +#define DISP_IOCTL_SET_CCORR _IOW(DISP_IOCTL_MAGIC, 24 , DISP_CCORR_COEF_T) + + +/* Add for AAL control - E */ +/*----------------------------------------------------------------------------- + DDP Kernel Mode API (for Kernel Trap) + -----------------------------------------------------------------------------*/ +/* DDPK Bitblit */ +/* #define DISP_IOCTL_G_WAIT_REQUEST _IOR (DISP_IOCTL_MAGIC , 40 , DDPIOCTL_DdpkBitbltConfig) */ +/* #define DISP_IOCTL_T_INFORM_DONE _IOW (DISP_IOCTL_MAGIC , 41 , DDPIOCTL_DdpkBitbltInformDone) */ + +#define DISP_IOCTL_SET_CLKON _IOW(DISP_IOCTL_MAGIC, 50 , DISP_MODULE_ENUM) +#define DISP_IOCTL_SET_CLKOFF _IOW(DISP_IOCTL_MAGIC, 51 , DISP_MODULE_ENUM) + +#define DISP_IOCTL_MUTEX_CONTROL _IOW(DISP_IOCTL_MAGIC, 55 , int) /* also defined in atci_pq_cmd.h */ +#define DISP_IOCTL_GET_LCMINDEX _IOR(DISP_IOCTL_MAGIC, 56 , int) + +/* PQ setting */ +#define DISP_IOCTL_SET_PQPARAM _IOW(DISP_IOCTL_MAGIC, 60 , DISP_PQ_PARAM) +#define DISP_IOCTL_GET_PQPARAM _IOR(DISP_IOCTL_MAGIC, 61 , DISP_PQ_PARAM) +#define DISP_IOCTL_GET_PQINDEX _IOR(DISP_IOCTL_MAGIC, 63, DISPLAY_PQ_T) +#define DISP_IOCTL_SET_PQINDEX _IOW(DISP_IOCTL_MAGIC, 64 , DISPLAY_PQ_T) +#define DISP_IOCTL_SET_TDSHPINDEX _IOW(DISP_IOCTL_MAGIC, 65 , DISPLAY_TDSHP_T) +#define DISP_IOCTL_GET_TDSHPINDEX _IOR(DISP_IOCTL_MAGIC, 66 , DISPLAY_TDSHP_T) +#define DISP_IOCTL_SET_PQ_CAM_PARAM _IOW(DISP_IOCTL_MAGIC, 67 , DISP_PQ_PARAM) +#define DISP_IOCTL_GET_PQ_CAM_PARAM _IOR(DISP_IOCTL_MAGIC, 68 , DISP_PQ_PARAM) +#define DISP_IOCTL_SET_PQ_GAL_PARAM _IOW(DISP_IOCTL_MAGIC, 69 , DISP_PQ_PARAM) +#define DISP_IOCTL_GET_PQ_GAL_PARAM _IOR(DISP_IOCTL_MAGIC, 70 , DISP_PQ_PARAM) + +#define DISP_IOCTL_PQ_SET_BYPASS_COLOR _IOW(DISP_IOCTL_MAGIC, 71 , int) +#define DISP_IOCTL_PQ_SET_WINDOW _IOW(DISP_IOCTL_MAGIC, 72 , DISP_PQ_WIN_PARAM) +#define DISP_IOCTL_PQ_GET_TDSHP_FLAG _IOR(DISP_IOCTL_MAGIC, 73 , int) +#define DISP_IOCTL_PQ_SET_TDSHP_FLAG _IOW(DISP_IOCTL_MAGIC, 74 , int) +#define DISP_IOCTL_PQ_GET_DC_PARAM _IOR(DISP_IOCTL_MAGIC, 75, DISP_PQ_DC_PARAM) +#define DISP_IOCTL_PQ_SET_DC_PARAM _IOW(DISP_IOCTL_MAGIC, 76, DISP_PQ_DC_PARAM) +#define DISP_IOCTL_WRITE_SW_REG _IOW(DISP_IOCTL_MAGIC, 77, DISP_WRITE_REG) /* also defined in atci_pq_cmd.h */ +#define DISP_IOCTL_READ_SW_REG _IOWR(DISP_IOCTL_MAGIC, 78, DISP_READ_REG) /* also defined in atci_pq_cmd.h */ +#define DISP_IOCTL_SET_COLOR_REG _IOWR(DISP_IOCTL_MAGIC, 79, DISPLAY_COLOR_REG_T) + +/* OD */ +#define DISP_IOCTL_OD_CTL _IOWR(DISP_IOCTL_MAGIC, 80 , DISP_OD_CMD) + +/* OVL */ +#define DISP_IOCTL_OVL_ENABLE_CASCADE _IOW(DISP_IOCTL_MAGIC, 90 , int) +#define DISP_IOCTL_OVL_DISABLE_CASCADE _IOW(DISP_IOCTL_MAGIC, 91 , int) + +/*PQ setting*/ +#define DISP_IOCTL_PQ_GET_DS_PARAM _IOR(DISP_IOCTL_MAGIC, 100, DISP_PQ_DS_PARAM) +#define DISP_IOCTL_PQ_GET_MDP_COLOR_CAP _IOR(DISP_IOCTL_MAGIC, 101, MDP_COLOR_CAP) +#define DISP_IOCTL_PQ_GET_MDP_TDSHP_REG _IOR(DISP_IOCTL_MAGIC, 102, MDP_TDSHP_REG) + +/*secure video path implementation: the handle value*/ +#define DISP_IOCTL_SET_TPLAY_HANDLE _IOW(DISP_IOCTL_MAGIC, 200, unsigned int) +#endif + diff --git a/drivers/misc/mediatek/video/mt6755/ddp_dsi.c b/drivers/misc/mediatek/video/mt6755/ddp_dsi.c new file mode 100644 index 0000000000000000000000000000000000000000..a481d66a9dada1778013689e1954db3b808ce032 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_dsi.c @@ -0,0 +1,4553 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "DSI" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "disp_log.h" +#include "disp_drv_platform.h" +#include "mtkfb.h" +#include "ddp_drv.h" +#include "ddp_manager.h" +#include "ddp_dump.h" +#include "ddp_irq.h" +#include "ddp_dsi.h" +#include "ddp_mmp.h" +#include "disp_helper.h" +#include "ddp_reg.h" +#include "disp_debug.h" +#include "mtkfb_debug.h" +#ifdef CONFIG_MTK_LEGACY +#include +#else +#include "disp_dts_gpio.h" +#endif +#include +#ifndef CONFIG_MTK_CLKMGR +#include "ddp_clkmgr.h" +#endif + + +#define DSI_OUTREG32(cmdq, addr, val) DISP_REG_SET(cmdq, addr, val) +#define DSI_BACKUPREG32(cmdq, hSlot, idx, addr) DISP_REG_BACKUP(cmdq, hSlot, idx, addr) +#define DSI_POLLREG32(cmdq, addr, mask, value) DISP_REG_CMDQ_POLLING(cmdq, addr, value, mask) +#define DSI_INREG32(type, addr) INREG32(addr) +#define DSI_READREG32(type, dst, src) mt_reg_sync_writel(INREG32(src), dst) + +static int dsi_reg_op_debug; +#define DSI_MASKREG32(cmdq, REG, MASK, VALUE) DISP_REG_MASK((cmdq), (REG), (VALUE), (MASK)) + +#define DSI_OUTREGBIT(cmdq, TYPE, REG, bit, value) \ + {\ + do {\ + TYPE r;\ + TYPE v;\ + if (cmdq) {\ + *(unsigned int *)(&r) = ((unsigned int)0x00000000); \ + r.bit = ~(r.bit); \ + *(unsigned int *)(&v) = ((unsigned int)0x00000000); \ + v.bit = value; \ + DISP_REG_MASK(cmdq, ®, AS_UINT32(&v), AS_UINT32(&r)); \ + } else { \ + mt_reg_sync_writel(INREG32(®), &r); \ + r.bit = (value); \ + DISP_REG_SET(cmdq, ®, INREG32(&r)); \ + } \ + } while (0);\ + } + +#ifdef CONFIG_FPGA_EARLY_PORTING +#define MIPITX_Write60384(slave_addr, write_addr, write_data) \ +{ \ + DISPMSG("MIPITX_Write60384:0x%x,0x%x,0x%x\n", slave_addr, write_addr, write_data); \ + mt_reg_sync_writel(0x2, MIPITX_BASE+0x14); \ + mt_reg_sync_writel(0x1, MIPITX_BASE+0x18); \ + mt_reg_sync_writel(((unsigned int)slave_addr << 0x1), MIPITX_BASE+0x04); \ + mt_reg_sync_writel(write_addr, MIPITX_BASE+0x0); \ + mt_reg_sync_writel(write_data, MIPITX_BASE+0x0); \ + mt_reg_sync_writel(0x1, MIPITX_BASE+0x24); \ + while ((INREG32(MIPITX_BASE+0xC)&0x1) != 0x1)\ + ; \ + mt_reg_sync_writel(0xFF, MIPITX_BASE+0xC); \ + \ + mt_reg_sync_writel(0x1, MIPITX_BASE+0x14); \ + mt_reg_sync_writel(0x1, MIPITX_BASE+0x18); \ + mt_reg_sync_writel(((unsigned int)slave_addr << 0x1), MIPITX_BASE+0x04); \ + mt_reg_sync_writel(write_addr, MIPITX_BASE+0x0); \ + mt_reg_sync_writel(0x1, MIPITX_BASE+0x24); \ + while ((INREG32(MIPITX_BASE+0xC)&0x1) != 0x1)\ + ; \ + mt_reg_sync_writel(0xFF, MIPITX_BASE+0xC); \ + \ + mt_reg_sync_writel(0x1, MIPITX_BASE+0x14); \ + mt_reg_sync_writel(0x1, MIPITX_BASE+0x18); \ + mt_reg_sync_writel(((unsigned int)slave_addr << 0x1)+1, MIPITX_BASE+0x04); \ + mt_reg_sync_writel(0x1, MIPITX_BASE+0x24); \ + while ((INREG32(MIPITX_BASE+0xC)&0x1) != 0x1)\ + ; \ + mt_reg_sync_writel(0xFF, MIPITX_BASE+0xC); \ + \ + DISPMSG("MIPI write data = 0x%x, read data = 0x%x\n", write_data, INREG32(MIPITX_BASE)); \ + if (INREG32(MIPITX_BASE) == write_data) \ + DISPMSG("MIPI write success\n"); \ + else \ + DISPMSG("MIPI write fail\n"); \ +} + +#define MIPITX_INREG32(addr) \ +({ \ + unsigned int val = 0;\ + if (0)\ + val = INREG32(addr); \ + if (dsi_reg_op_debug) \ + DISPMSG("[mipitx/inreg]%p=0x%08x\n", (void *)addr, val); \ + val; \ +}) + + #define MIPITX_OUTREG32(addr, val) {\ + if (dsi_reg_op_debug) \ + DISPMSG("[mipitx/reg]%p=0x%08x\n", (void *)addr, val); \ + if (0) \ + mt_reg_sync_writel(val, addr); \ + } + +#define MIPITX_OUTREGBIT(TYPE, REG, bit, value) {\ + do { \ + TYPE r;\ + if (0) \ + mt_reg_sync_writel(INREG32(®), &r); \ + *(unsigned long *)(&r) = ((unsigned long)0x00000000); \ + r.bit = value; \ + MIPITX_OUTREG32(®, AS_UINT32(&r)); \ + } while (0);\ + } + +#define MIPITX_MASKREG32(x, y, z) MIPITX_OUTREG32(x, (MIPITX_INREG32(x)&~(y))|(z)) +#else +#define MIPITX_INREG32(addr) \ +({ \ + unsigned int val = 0; val = INREG32(addr);\ + if (dsi_reg_op_debug) \ + DISPMSG("[mipitx/inreg]%p=0x%08x\n", (void *)addr, val); \ + val; }) + +#define MIPITX_OUTREG32(addr, val) \ + {\ + do { \ + if (dsi_reg_op_debug) { \ + DISPMSG("[mipitx/reg]%p=0x%08x\n", (void *)addr, val);\ + } \ + mt_reg_sync_writel(val, addr);\ + } while (0);\ + } + +#define MIPITX_OUTREGBIT(TYPE, REG, bit, value) \ + {\ + do { \ + TYPE r;\ + mt_reg_sync_writel(INREG32(®), &r); \ + r.bit = value; \ + MIPITX_OUTREG32(®, AS_UINT32(&r)); \ + } while (0);\ + } + +#define MIPITX_MASKREG32(x, y, z) MIPITX_OUTREG32(x, (MIPITX_INREG32(x)&~(y))|(z)) +#endif + + typedef struct { + unsigned int lcm_width; + unsigned int lcm_height; + cmdqRecHandle *handle; + bool enable; + DSI_REGS regBackup; + unsigned int cmdq_size; + LCM_DSI_PARAMS dsi_params; + } +t_dsi_context; + +t_dsi_context _dsi_context[DSI_INTERFACE_NUM]; + +#define DSI_MODULE_BEGIN(x) 0 /* (x == DISP_MODULE_DSIDUAL?0:DSI_MODULE_to_ID(x)) */ +#define DSI_MODULE_END(x) 0 /* (x == DISP_MODULE_DSIDUAL?1:DSI_MODULE_to_ID(x)) */ +#define DSI_MODULE_to_ID(x) 0 /* (x == DISP_MODULE_DSI0?0:1) */ +#define DIFF_CLK_LANE_LP (0x10) + +PDSI_REGS DSI_REG[2]; +PDSI_PHY_REGS DSI_PHY_REG[2]; +PDSI_CMDQ_REGS DSI_CMDQ_REG[2]; +PDSI_VM_CMDQ_REGS DSI_VM_CMD_REG[2]; + +static wait_queue_head_t _dsi_cmd_done_wait_queue[2]; +static wait_queue_head_t _dsi_dcs_read_wait_queue[2]; +static wait_queue_head_t _dsi_wait_bta_te[2]; +static wait_queue_head_t _dsi_wait_ext_te[2]; +static wait_queue_head_t _dsi_wait_vm_done_queue[2]; +static wait_queue_head_t _dsi_wait_vm_cmd_done_queue[2]; +static wait_queue_head_t _dsi_wait_sleep_out_done_queue[2]; +static bool waitRDDone; +static bool wait_vm_cmd_done; +static bool wait_sleep_out_done; +static int s_isDsiPowerOn; +static int dsi_currect_mode; +static int dsi_force_config; +static int dsi0_te_enable = 1; +static const LCM_UTIL_FUNCS lcm_utils_dsi0; +unsigned int clock_lane = 0;/*MIPITX_DSI_CLOCK_LANE*/ +unsigned int data_lane3 = 0;/*MIPITX_DSI_DATA_LANE3*/ +unsigned int data_lane2 = 0;/*MIPITX_DSI_DATA_LANE2*/ +unsigned int data_lane1 = 0;/*MIPITX_DSI_DATA_LANE1*/ +unsigned int data_lane0 = 0;/*MIPITX_DSI_DATA_LANE0*/ + +atomic_t PMaster_enable = ATOMIC_INIT(0); + +static const char *_dsi_cmd_mode_parse_state(unsigned int state) +{ + switch (state) { + case 0x0001: + return "idle"; + case 0x0002: + return "Reading command queue for header"; + case 0x0004: + return "Sending type-0 command"; + case 0x0008: + return "Waiting frame data from RDMA for type-1 command"; + case 0x0010: + return "Sending type-1 command"; + case 0x0020: + return "Sending type-2 command"; + case 0x0040: + return "Reading command queue for data"; + case 0x0080: + return "Sending type-3 command"; + case 0x0100: + return "Sending BTA"; + case 0x0200: + return "Waiting RX-read data "; + case 0x0400: + return "Waiting SW RACK for RX-read data"; + case 0x0800: + return "Waiting TE"; + case 0x1000: + return "Get TE "; + case 0x2000: + return "Waiting SW RACK for TE"; + case 0x4000: + return "Waiting external TE"; + default: + return "unknown"; + } +} + +static const char *_dsi_vdo_mode_parse_state(unsigned int state) +{ + switch (state) { + case 0x0001: + return "Video mode idle"; + case 0x0002: + return "Sync start packet"; + case 0x0004: + return "Hsync active"; + case 0x0008: + return "Sync end packet"; + case 0x0010: + return "Hsync back porch"; + case 0x0020: + return "Video data period"; + case 0x0040: + return "Hsync front porch"; + case 0x0080: + return "BLLP"; + case 0x0100: + return "--"; + case 0x0200: + return "Mix mode using command mode transmission"; + case 0x0400: + return "Command transmission in BLLP"; + default: + return "unknown"; + } + +} + +DSI_STATUS DSI_DumpRegisters(DISP_MODULE_ENUM module, int level) +{ + uint32_t i; + unsigned int DSI_DBG6_Status; + unsigned int DSI_DBG7_Status; + unsigned int DSI_DBG8_Status; + unsigned int DSI_DBG9_Status; + + if (level >= 0) { + if (module == DISP_MODULE_DSI0) { + if (DSI_REG[0]->DSI_MODE_CTRL.MODE == CMD_MODE) { + DSI_DBG6_Status = + (INREG32(DDP_REG_BASE_DSI0 + 0x160)) & 0xffff; + DISPDMP("DSI0 state6(cmd mode):%s\n", + _dsi_cmd_mode_parse_state(DSI_DBG6_Status)); + + } else { + DSI_DBG7_Status = + (INREG32(DDP_REG_BASE_DSI0 + 0x164)) & 0xff; + DISPDMP("DSI0 state7(vdo mode):%s\n", + _dsi_vdo_mode_parse_state(DSI_DBG7_Status)); + } + DSI_DBG8_Status = + (INREG32(DDP_REG_BASE_DSI0 + 0x168)) & 0x3fff; + DISPDMP("DSI0 state8 WORD_COUNTER(cmd mode):%s\n", + _dsi_cmd_mode_parse_state(DSI_DBG8_Status)); + DSI_DBG9_Status = + (INREG32(DDP_REG_BASE_DSI0 + 0x16C)) & 0x3fffff; + DISPDMP("DSI0 state9 LINE_COUNTER(cmd mode):%s\n", + _dsi_cmd_mode_parse_state(DSI_DBG9_Status)); + } + } + if (level >= 1) { + if (module == DISP_MODULE_DSI0) { + DSI_DBG6_Status = + (INREG32(DDP_REG_BASE_DSI0 + 0x160)) & 0xffff; + + DISPDMP("== START: DISP DSI0 registers ==\n"); + + for (i = 0; i < sizeof(DSI_REGS); i += 16) { + DISPDMP("DSI0: 0x%04x=0x%08x,0x%04x=0x%08x,0x%04x=0x%08x,0x%04x=0x%08x\n", + i, INREG32(DDP_REG_BASE_DSI0 + i), + i + 0x04, INREG32(DDP_REG_BASE_DSI0 + i + 0x4), + i + 0x08, INREG32(DDP_REG_BASE_DSI0 + i + 0x8), + i + 0x0c, INREG32(DDP_REG_BASE_DSI0 + i + 0xc)); + } + + for (i = 0; i < sizeof(DSI_CMDQ_REGS); i += 16) { + DISPDMP("DSI_CMD+%04x : 0x%08x 0x%08x 0x%08x 0x%08x\n", i, + INREG32((DDP_REG_BASE_DSI0 + 0x200 + i)), + INREG32((DDP_REG_BASE_DSI0 + 0x200 + i + 0x4)), + INREG32((DDP_REG_BASE_DSI0 + 0x200 + i + 0x8)), + INREG32((DDP_REG_BASE_DSI0 + 0x200 + i + 0xc))); + } + +#ifndef CONFIG_FPGA_EARLY_PORTING + for (i = 0; i < sizeof(DSI_PHY_REGS); i += 16) { + DISPDMP("DSI_PHY: 0x%04x=0x%08x,0x%04x=0x%08x,0x%04x=0x%08x,0x%04x=0x%08x\n", + i, INREG32((MIPITX_BASE + i)), + i + 0x4, INREG32((MIPITX_BASE + i + 0x4)), + i + 0x8, INREG32((MIPITX_BASE + i + 0x8)), + i + 0xc, INREG32((MIPITX_BASE + i + 0xc))); + } + DISPDMP("-- END: DISP DSI0 registers --\n"); +#endif + } + } + + return DSI_STATUS_OK; +} + +static void _DSI_INTERNAL_IRQ_Handler(DISP_MODULE_ENUM module, unsigned int param) +{ + int i = 0; + DSI_INT_STATUS_REG status; + DSI_TXRX_CTRL_REG txrx_ctrl; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + status = *(PDSI_INT_STATUS_REG) & param; + if (status.RD_RDY) { + /* /write clear RD_RDY interrupt */ + + /* / write clear RD_RDY interrupt must be before DSI_RACK */ + /* / because CMD_DONE will raise after DSI_RACK, */ + /* / so write clear RD_RDY after that will clear CMD_DONE too */ + /*do + { + ///send read ACK + //DSI_REG->DSI_RACK.DSI_RACK = 1; + DSI_OUTREGBIT(NULL, DSI_RACK_REG,DSI_REG[i]->DSI_RACK,DSI_RACK,1); + DISPMSG("send read ACK\n"); + } while(DSI_REG[i]->DSI_INTSTA.BUSY); */ + waitRDDone = true; + wake_up_interruptible(&_dsi_dcs_read_wait_queue[i]); + } + + if (status.CMD_DONE) { + /* DISPMSG("[callback]%s cmd dome\n", ddp_get_module_name(module)); */ + wake_up_interruptible(&_dsi_cmd_done_wait_queue[i]); + } + + if (status.TE_RDY) { + DSI_OUTREG32(NULL, &txrx_ctrl, INREG32(&DSI_REG[i]->DSI_TXRX_CTRL)); + if (txrx_ctrl.EXT_TE_EN == 1) { + /* DISPMSG("[callback]%s EXT te\n", ddp_get_module_name(module)); */ + wake_up_interruptible(&_dsi_wait_ext_te[i]); + } else { + wake_up_interruptible(&_dsi_wait_bta_te[i]); + } + } + + if (status.VM_DONE) + wake_up_interruptible(&_dsi_wait_vm_done_queue[i]); + if (status.VM_CMD_DONE) { + wait_vm_cmd_done = true; + wake_up_interruptible(&_dsi_wait_vm_cmd_done_queue[i]); + } + if (status.SLEEPOUT_DONE) { + wait_sleep_out_done = true; + wake_up_interruptible(&_dsi_wait_sleep_out_done_queue[i]); + } + } +} + +static DSI_STATUS DSI_Reset(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = 0; + unsigned int irq_en[2]; + /* DSI_RESET Protect: backup & disable dsi interrupt */ + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + irq_en[i] = AS_UINT32(&DSI_REG[i]->DSI_INTEN); + DSI_OUTREG32(NULL, &DSI_REG[i]->DSI_INTEN, 0); + DISPDBG("DSI_RESET backup dsi%d irq:0x%08x ", i, irq_en[i]); + } + + /* do reset */ + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_COM_CTRL_REG, DSI_REG[i]->DSI_COM_CTRL, DSI_RESET, 1); + DSI_OUTREGBIT(cmdq, DSI_COM_CTRL_REG, DSI_REG[i]->DSI_COM_CTRL, DSI_RESET, 0); + } + + /* DSI_RESET Protect: restore dsi interrupt */ + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREG32(NULL, &DSI_REG[i]->DSI_INTEN, irq_en[i]); + DISPDBG("DSI_RESET restore dsi%d irq:0x%08x ", i, + AS_UINT32(&DSI_REG[i]->DSI_INTEN)); + } + return DSI_STATUS_OK; +} + +static int _dsi_is_video_mode(DISP_MODULE_ENUM module) +{ + int i = DSI_MODULE_BEGIN(module); + + if (DSI_REG[i]->DSI_MODE_CTRL.MODE == CMD_MODE) + return 0; + else + return 1; +} + +static DSI_STATUS DSI_SetMode(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, unsigned int mode) +{ + int i = 0; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) + DSI_OUTREGBIT(cmdq, DSI_MODE_CTRL_REG, DSI_REG[i]->DSI_MODE_CTRL, MODE, mode); + + return DSI_STATUS_OK; +} +static DSI_STATUS DSI_SetSwitchMode(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, unsigned int mode) +{ + int i = 0; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (mode == 0) { /* V2C */ + DSI_OUTREGBIT(cmdq, DSI_MODE_CTRL_REG, DSI_REG[i]->DSI_MODE_CTRL, + V2C_SWITCH_ON, 1); + } else /* C2V */ + DSI_OUTREGBIT(cmdq, DSI_MODE_CTRL_REG, DSI_REG[i]->DSI_MODE_CTRL, + C2V_SWITCH_ON, 1); + + } + + return DSI_STATUS_OK; +} +void DSI_lane0_ULP_mode(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, bool enter) +{ + int i = 0; + + ASSERT(cmdq == NULL); + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (enter) { + DSI_OUTREGBIT(cmdq, DSI_PHY_LD0CON_REG, DSI_REG[i]->DSI_PHY_LD0CON, + L0_RM_TRIG_EN, 0); + mdelay(1); + DSI_OUTREGBIT(cmdq, DSI_PHY_LD0CON_REG, DSI_REG[i]->DSI_PHY_LD0CON, + Lx_ULPM_AS_L0, 1); + DSI_OUTREGBIT(cmdq, DSI_PHY_LD0CON_REG, DSI_REG[i]->DSI_PHY_LD0CON, + L0_ULPM_EN, 0); + DSI_OUTREGBIT(cmdq, DSI_PHY_LD0CON_REG, DSI_REG[i]->DSI_PHY_LD0CON, + L0_ULPM_EN, 1); + mdelay(1); + } else { + DSI_OUTREGBIT(cmdq, DSI_PHY_LD0CON_REG, DSI_REG[i]->DSI_PHY_LD0CON, + L0_ULPM_EN, 0); + mdelay(1); + DSI_OUTREGBIT(cmdq, DSI_PHY_LD0CON_REG, DSI_REG[i]->DSI_PHY_LD0CON, + Lx_ULPM_AS_L0, 0); + DSI_OUTREGBIT(cmdq, DSI_PHY_LD0CON_REG, DSI_REG[i]->DSI_PHY_LD0CON, + L0_WAKEUP_EN, 1); + mdelay(1); + DSI_OUTREGBIT(cmdq, DSI_PHY_LD0CON_REG, DSI_REG[i]->DSI_PHY_LD0CON, + L0_WAKEUP_EN, 0); + mdelay(1); + } + } +} + + +void DSI_clk_ULP_mode(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, bool enter) +{ + int i = 0; + + ASSERT(cmdq == NULL); + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (enter) { + DSI_OUTREGBIT(cmdq, DSI_PHY_LCCON_REG, DSI_REG[i]->DSI_PHY_LCCON, + LC_ULPM_EN, 0); + mdelay(1); + DSI_OUTREGBIT(cmdq, DSI_PHY_LCCON_REG, DSI_REG[i]->DSI_PHY_LCCON, + LC_ULPM_EN, 1); + mdelay(1); + } else { + DSI_OUTREGBIT(cmdq, DSI_PHY_LCCON_REG, DSI_REG[i]->DSI_PHY_LCCON, + LC_ULPM_EN, 0); + mdelay(1); + DSI_OUTREGBIT(cmdq, DSI_PHY_LCCON_REG, DSI_REG[i]->DSI_PHY_LCCON, + LC_WAKEUP_EN, 1); + mdelay(1); + DSI_OUTREGBIT(cmdq, DSI_PHY_LCCON_REG, DSI_REG[i]->DSI_PHY_LCCON, + LC_WAKEUP_EN, 0); + mdelay(1); + } + } +} + +bool DSI_clk_HS_state(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = DSI_MODULE_BEGIN(module); + DSI_PHY_LCCON_REG tmpreg; + + DSI_READREG32(PDSI_PHY_LCCON_REG, &tmpreg, &DSI_REG[i]->DSI_PHY_LCCON); + return tmpreg.LC_HS_TX_EN ? true : false; +} + +void DSI_clk_HS_mode(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, bool enter) +{ + int i = 0; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (enter) { + DSI_OUTREGBIT(cmdq, DSI_PHY_LCCON_REG, DSI_REG[i]->DSI_PHY_LCCON, + LC_HS_TX_EN, 1); + } else if (!enter) { + DSI_OUTREGBIT(cmdq, DSI_PHY_LCCON_REG, DSI_REG[i]->DSI_PHY_LCCON, + LC_HS_TX_EN, 0); + } + } +} + +int DSI_WaitVMDone(DISP_MODULE_ENUM module) +{ + int i = 0; + static const long WAIT_TIMEOUT = 2 * HZ; /* 2 sec */ + int ret = 0; + + /*...dsi video is always in busy state... */ + if (_dsi_is_video_mode(module)) { + DISPMSG("DSI_WaitVMDone error: should set DSI to CMD mode firstly\n"); + return -1; + } + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + ret = + wait_event_interruptible_timeout(_dsi_wait_vm_done_queue[i], + !(DSI_REG[i]->DSI_INTSTA.BUSY), WAIT_TIMEOUT); + if (0 == ret) { + DISPERR("dsi wait VM done timeout\n"); + DSI_DumpRegisters(module, 1); + DSI_Reset(module, NULL); + return -1; + } + } + return 0; +} + +static void DSI_WaitForNotBusy(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = 0; + unsigned int count = 0; + unsigned int tmp = 0; + static const long WAIT_TIMEOUT = 2 * HZ; /* 2 sec */ + int ret = 0; + + if (cmdq) { + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) + DSI_POLLREG32(cmdq, &DSI_REG[i]->DSI_INTSTA, 0x80000000, 0x0); + return; + } + + + /*...dsi video is always in busy state... */ + if (_dsi_is_video_mode(module)) + return; +#if defined(MTK_NO_DISP_IN_LK) + i = DSI_MODULE_BEGIN(module); + while (1) { + tmp = INREG32(&DSI_REG[i]->DSI_INTSTA); + if (!(tmp & 0x80000000)) + break; + + /* if(count %1000) */ + /* DISPMSG("dsi state:0x%08x, 0x%08x\n", tmp, INREG32(&DSI_REG[i]->DSI_STATE_DBG6)); */ + + /* msleep(1); */ + + if (count++ > 1000000000) { + DISPERR("dsi wait not busy timeout\n"); + DSI_DumpRegisters(module, 1); + DSI_Reset(module, NULL); + break; + } + } +#else + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + ret = + wait_event_interruptible_timeout(_dsi_cmd_done_wait_queue[i], + !(DSI_REG[i]->DSI_INTSTA.BUSY), WAIT_TIMEOUT); + if (0 == ret) { + DISPERR("dsi wait not busy timeout\n"); + DSI_DumpRegisters(module, 1); + DSI_Reset(module, NULL); + break; + } + while (1) { + tmp = INREG32(&DSI_REG[i]->DSI_INTSTA); + if (!(tmp & 0x80000000)) + break; + if (count++ > 1000000000) { + DISPERR("dsi timeout on polling no busy\n"); + DSI_Reset(module, NULL); + break; + } + } + } +#endif +} + +DSI_STATUS DSI_SleepOut(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = 0; + /* wake_up_prd *1024*cycle time > 1ms */ + int wake_up_prd = (_dsi_context[i].dsi_params.PLL_CLOCK * 2 * 1000) / (1024 * 8) + 0x1; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_MODE_CTRL_REG, DSI_REG[i]->DSI_MODE_CTRL, SLEEP_MODE, 1); + DSI_OUTREGBIT(cmdq, DSI_TIME_CON0_REG, DSI_REG[i]->DSI_TIME_CON0, UPLS_WAKEUP_PRD, wake_up_prd); + } + DISPDBG("DSI_SleepOut\n"); + return DSI_STATUS_OK; +} + +DSI_STATUS DSI_Wakeup(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = 0; + int ret = 0; + int cnt = 0; + + DISPDBG("DSI_Wakeup+\n"); + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + wait_sleep_out_done = false; + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[i]->DSI_START, SLEEPOUT_START, 0); + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[i]->DSI_START, SLEEPOUT_START, 1); + do { + cnt++; + ret = + wait_event_interruptible_timeout(_dsi_wait_sleep_out_done_queue[i], + wait_sleep_out_done, 2 * HZ); + } while (ret <= 0 && cnt <= 2); + + if (ret == 0) { + DISPERR("dsi wait sleep out timeout\n"); + DSI_DumpRegisters(module, 2); + DSI_Reset(module, NULL); + } else if (ret < 0) { + DISPERR("dsi wait sleep out weake up by signal ret %d\n", ret); + mdelay(5); + } + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[i]->DSI_START, SLEEPOUT_START, 0); + DSI_OUTREGBIT(cmdq, DSI_MODE_CTRL_REG, DSI_REG[i]->DSI_MODE_CTRL, SLEEP_MODE, 0); + } + DISPDBG("DSI_Wakeup-\n"); + return DSI_STATUS_OK; +} + +DSI_STATUS DSI_BackupRegisters(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = 0; + DSI_REGS *regs = NULL; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + regs = &(_dsi_context[i].regBackup); + + DSI_OUTREG32(cmdq, ®s->DSI_INTEN, AS_UINT32(&DSI_REG[i]->DSI_INTEN)); + DSI_OUTREG32(cmdq, ®s->DSI_MODE_CTRL, AS_UINT32(&DSI_REG[i]->DSI_MODE_CTRL)); + DSI_OUTREG32(cmdq, ®s->DSI_TXRX_CTRL, AS_UINT32(&DSI_REG[i]->DSI_TXRX_CTRL)); + DSI_OUTREG32(cmdq, ®s->DSI_PSCTRL, AS_UINT32(&DSI_REG[i]->DSI_PSCTRL)); + + DSI_OUTREG32(cmdq, ®s->DSI_VSA_NL, AS_UINT32(&DSI_REG[i]->DSI_VSA_NL)); + DSI_OUTREG32(cmdq, ®s->DSI_VBP_NL, AS_UINT32(&DSI_REG[i]->DSI_VBP_NL)); + DSI_OUTREG32(cmdq, ®s->DSI_VFP_NL, AS_UINT32(&DSI_REG[i]->DSI_VFP_NL)); + DSI_OUTREG32(cmdq, ®s->DSI_VACT_NL, AS_UINT32(&DSI_REG[i]->DSI_VACT_NL)); + + DSI_OUTREG32(cmdq, ®s->DSI_HSA_WC, AS_UINT32(&DSI_REG[i]->DSI_HSA_WC)); + DSI_OUTREG32(cmdq, ®s->DSI_HBP_WC, AS_UINT32(&DSI_REG[i]->DSI_HBP_WC)); + DSI_OUTREG32(cmdq, ®s->DSI_HFP_WC, AS_UINT32(&DSI_REG[i]->DSI_HFP_WC)); + DSI_OUTREG32(cmdq, ®s->DSI_BLLP_WC, AS_UINT32(&DSI_REG[i]->DSI_BLLP_WC)); + + DSI_OUTREG32(cmdq, ®s->DSI_HSTX_CKL_WC, AS_UINT32(&DSI_REG[i]->DSI_HSTX_CKL_WC)); + DSI_OUTREG32(cmdq, ®s->DSI_MEM_CONTI, AS_UINT32(&DSI_REG[i]->DSI_MEM_CONTI)); + + DSI_OUTREG32(cmdq, ®s->DSI_PHY_TIMECON0, + AS_UINT32(&DSI_REG[i]->DSI_PHY_TIMECON0)); + DSI_OUTREG32(cmdq, ®s->DSI_PHY_TIMECON1, + AS_UINT32(&DSI_REG[i]->DSI_PHY_TIMECON1)); + DSI_OUTREG32(cmdq, ®s->DSI_PHY_TIMECON2, + AS_UINT32(&DSI_REG[i]->DSI_PHY_TIMECON2)); + DSI_OUTREG32(cmdq, ®s->DSI_PHY_TIMECON3, + AS_UINT32(&DSI_REG[i]->DSI_PHY_TIMECON3)); + DSI_OUTREG32(cmdq, ®s->DSI_VM_CMD_CON, AS_UINT32(&DSI_REG[i]->DSI_VM_CMD_CON)); + } + + return DSI_STATUS_OK; +} + +DSI_STATUS DSI_RestoreRegisters(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = 0; + DSI_REGS *regs = NULL; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + regs = &(_dsi_context[i].regBackup); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_INTEN, AS_UINT32(®s->DSI_INTEN)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_MODE_CTRL, AS_UINT32(®s->DSI_MODE_CTRL)); + /* can not restore lane_num here */ + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_TXRX_CTRL, + AS_UINT32(®s->DSI_TXRX_CTRL) & 0xFFFFFFC3); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PSCTRL, AS_UINT32(®s->DSI_PSCTRL)); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VSA_NL, AS_UINT32(®s->DSI_VSA_NL)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VBP_NL, AS_UINT32(®s->DSI_VBP_NL)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VFP_NL, AS_UINT32(®s->DSI_VFP_NL)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VACT_NL, AS_UINT32(®s->DSI_VACT_NL)); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HSA_WC, AS_UINT32(®s->DSI_HSA_WC)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HBP_WC, AS_UINT32(®s->DSI_HBP_WC)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HFP_WC, AS_UINT32(®s->DSI_HFP_WC)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_BLLP_WC, AS_UINT32(®s->DSI_BLLP_WC)); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HSTX_CKL_WC, AS_UINT32(®s->DSI_HSTX_CKL_WC)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_MEM_CONTI, AS_UINT32(®s->DSI_MEM_CONTI)); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON0, + AS_UINT32(®s->DSI_PHY_TIMECON0)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON1, + AS_UINT32(®s->DSI_PHY_TIMECON1)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON2, + AS_UINT32(®s->DSI_PHY_TIMECON2)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON3, + AS_UINT32(®s->DSI_PHY_TIMECON3)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VM_CMD_CON, AS_UINT32(®s->DSI_VM_CMD_CON)); + DISPDBG("DSI_RestoreRegisters VM_CMD_EN %d TS_VFP_EN %d\n", + regs->DSI_VM_CMD_CON.VM_CMD_EN, regs->DSI_VM_CMD_CON.TS_VFP_EN); + } + return DSI_STATUS_OK; +} + +DSI_STATUS DSI_BIST_Pattern_Test(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, bool enable, + unsigned int color) +{ + int i = 0; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (enable) { + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_BIST_PATTERN, color); + /* DSI_OUTREG32(&DSI_REG->DSI_BIST_CON, AS_UINT32(&temp_reg)); */ + /* DSI_OUTREGBIT(DSI_BIST_CON_REG, DSI_REG->DSI_BIST_CON, SELF_PAT_MODE, 1); */ + DSI_OUTREGBIT(cmdq, DSI_BIST_CON_REG, DSI_REG[i]->DSI_BIST_CON, + SELF_PAT_MODE, 1); + + if (!_dsi_is_video_mode(module)) { + DSI_T0_INS t0; + + t0.CONFG = 0x09; + t0.Data_ID = 0x39; + t0.Data0 = 0x2c; + t0.Data1 = 0; + + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[i]->data[0], AS_UINT32(&t0)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_CMDQ_SIZE, 1); + + /* DSI_OUTREGBIT(DSI_START_REG,DSI_REG->DSI_START,DSI_START,0); */ + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_START, 0); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_START, 1); + /* DSI_OUTREGBIT(DSI_START_REG,DSI_REG->DSI_START,DSI_START,1); */ + } + } else { + /* if disable dsi pattern, need enable mutex, can't just start dsi */ + /* so we just disable pattern bit, do not start dsi here */ + /* DSI_WaitForNotBusy(module,cmdq); */ + /* DSI_OUTREGBIT(cmdq, DSI_BIST_CON_REG, DSI_REG[i]->DSI_BIST_CON, SELF_PAT_MODE, 0); */ + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_BIST_CON, 0x00); + } + + } + return DSI_STATUS_OK; +} + +int ddp_dsi_porch_setting(DISP_MODULE_ENUM module, void *handle, + DSI_PORCH_TYPE type, unsigned int value) +{ + int ret = 0; + + if (DISP_MODULE_DSI0 == module) { + if (DSI_VFP == type) { + DISPMSG("set dsi vfp to %d\n", value); + DSI_OUTREG32(handle, &DSI_REG[0]->DSI_VFP_NL, value); + } + if (DSI_VSA == type) { + DISPMSG("set dsi vsa to %d\n", value); + DSI_OUTREG32(handle, &DSI_REG[0]->DSI_VSA_NL, value); + } + if (DSI_VBP == type) { + DISPMSG("set dsi vbp to %d\n", value); + DSI_OUTREG32(handle, &DSI_REG[0]->DSI_VBP_NL, value); + } + if (DSI_VACT == type) { + DISPMSG("set dsi vact to %d\n", value); + DSI_OUTREG32(handle, &DSI_REG[0]->DSI_VACT_NL, value); + } + if (DSI_HFP == type) { + DISPMSG("set dsi hfp to %d\n", value); + DSI_OUTREG32(handle, &DSI_REG[0]->DSI_HFP_WC, value); + } + if (DSI_HSA == type) { + DISPMSG("set dsi hsa to %d\n", value); + DSI_OUTREG32(handle, &DSI_REG[0]->DSI_HSA_WC, value); + } + if (DSI_HBP == type) { + DISPMSG("set dsi hbp to %d\n", value); + DSI_OUTREG32(handle, &DSI_REG[0]->DSI_HBP_WC, value); + } + if (DSI_BLLP == type) { + DISPMSG("set dsi bllp to %d\n", value); + DSI_OUTREG32(handle, &DSI_REG[0]->DSI_BLLP_WC, value); + } + } + return ret; +} + +void DSI_Config_VDO_Timing(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, LCM_DSI_PARAMS *dsi_params) +{ + int i = 0; + unsigned int line_byte = 0; + unsigned int horizontal_sync_active_byte = 0; + unsigned int horizontal_backporch_byte = 0; + unsigned int horizontal_frontporch_byte = 0; + unsigned int horizontal_bllp_byte = 0; + unsigned int dsiTmpBufBpp = 0; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (dsi_params->data_format.format == LCM_DSI_FORMAT_RGB565) + dsiTmpBufBpp = 2; + else + dsiTmpBufBpp = 3; + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VSA_NL, dsi_params->vertical_sync_active); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VBP_NL, dsi_params->vertical_backporch); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VFP_NL, dsi_params->vertical_frontporch); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_VACT_NL, dsi_params->vertical_active_line); + + line_byte = + (dsi_params->horizontal_sync_active + dsi_params->horizontal_backporch + + dsi_params->horizontal_frontporch + + dsi_params->horizontal_active_pixel) * dsiTmpBufBpp; + horizontal_sync_active_byte = + (dsi_params->horizontal_sync_active * dsiTmpBufBpp - 4); + + if (dsi_params->mode == SYNC_EVENT_VDO_MODE || dsi_params->mode == BURST_VDO_MODE + || dsi_params->switch_mode == SYNC_EVENT_VDO_MODE + || dsi_params->switch_mode == BURST_VDO_MODE) { + ASSERT((dsi_params->horizontal_backporch + + dsi_params->horizontal_sync_active) * dsiTmpBufBpp > 9); + horizontal_backporch_byte = + ((dsi_params->horizontal_backporch + + dsi_params->horizontal_sync_active) * dsiTmpBufBpp - 10); + } else { + ASSERT(dsi_params->horizontal_sync_active * dsiTmpBufBpp > 9); + horizontal_sync_active_byte = + (dsi_params->horizontal_sync_active * dsiTmpBufBpp - 10); + + ASSERT(dsi_params->horizontal_backporch * dsiTmpBufBpp > 9); + horizontal_backporch_byte = + (dsi_params->horizontal_backporch * dsiTmpBufBpp - 10); + } + + ASSERT(dsi_params->horizontal_frontporch * dsiTmpBufBpp > 11); + horizontal_frontporch_byte = + (dsi_params->horizontal_frontporch * dsiTmpBufBpp - 12); + horizontal_bllp_byte = (dsi_params->horizontal_bllp * dsiTmpBufBpp); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HSA_WC, + ALIGN_TO((horizontal_sync_active_byte), 4)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HBP_WC, + ALIGN_TO((horizontal_backporch_byte), 4)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HFP_WC, + ALIGN_TO((horizontal_frontporch_byte), 4)); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_BLLP_WC, ALIGN_TO((horizontal_bllp_byte), 4)); + } +} + +void DSI_Set_LFR(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, unsigned int mode, + unsigned int type, unsigned int enable, unsigned int skip_num) +{ + /* LFR_MODE 0 disable,1 static mode ,2 dynamic mode 3,both */ + unsigned int i = 0; + + /* DISPMSG("module=%d,mode=%d,type=%d,enable=%d,skip_num=%d\n",module,mode,type,enable,skip_num); */ + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_LFR_CON_REG, DSI_REG[i]->DSI_LFR_CON, LFR_MODE, mode); + DSI_OUTREGBIT(cmdq, DSI_LFR_CON_REG, DSI_REG[i]->DSI_LFR_CON, LFR_TYPE, 0); + DSI_OUTREGBIT(cmdq, DSI_LFR_CON_REG, DSI_REG[i]->DSI_LFR_CON, LFR_UPDATE, 1); + DSI_OUTREGBIT(cmdq, DSI_LFR_CON_REG, DSI_REG[i]->DSI_LFR_CON, LFR_VSE_DIS, 0); + DSI_OUTREGBIT(cmdq, DSI_LFR_CON_REG, DSI_REG[i]->DSI_LFR_CON, LFR_SKIP_NUM, + skip_num); + DSI_OUTREGBIT(cmdq, DSI_LFR_CON_REG, DSI_REG[i]->DSI_LFR_CON, LFR_EN, enable); + } +} + +void DSI_LFR_UPDATE(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + unsigned int i = 0; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_LFR_CON_REG, DSI_REG[i]->DSI_LFR_CON, LFR_UPDATE, 0); + DSI_OUTREGBIT(cmdq, DSI_LFR_CON_REG, DSI_REG[i]->DSI_LFR_CON, LFR_UPDATE, 1); + } +} + +int DSI_LFR_Status_Check(void) +{ + unsigned int status = 0; + + DSI_LFR_STA_REG lfr_skip_sta; + + lfr_skip_sta = DSI_REG[0]->DSI_LFR_STA; + status = lfr_skip_sta.LFR_SKIP_STA; + DISPMSG("LFR_SKIP_CNT 0x%x LFR_SKIP_STA 0x%x,status 0x%x\n", lfr_skip_sta.LFR_SKIP_CNT, + lfr_skip_sta.LFR_SKIP_STA, status); + + return status; +} + +int _dsi_ps_type_to_bpp(LCM_PS_TYPE ps) +{ + switch (ps) { + case LCM_PACKED_PS_16BIT_RGB565: + return 2; + case LCM_LOOSELY_PS_18BIT_RGB666: + return 3; + case LCM_PACKED_PS_24BIT_RGB888: + return 3; + case LCM_PACKED_PS_18BIT_RGB666: + return 3; + default: + break; + } + return 0; +} + +DSI_STATUS DSI_PS_Control(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, + LCM_DSI_PARAMS *dsi_params, int w, int h) +{ + int i = 0; + unsigned int ps_sel_bitvalue = 0; + /* /TODO: parameter checking */ + ASSERT(_dsi_ps_type_to_bpp(dsi_params->PS) <= PACKED_PS_18BIT_RGB666); + + if (_dsi_ps_type_to_bpp(dsi_params->PS) > LOOSELY_PS_18BIT_RGB666) + ps_sel_bitvalue = (5 - dsi_params->PS); + else + ps_sel_bitvalue = dsi_params->PS; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_VACT_NL_REG, DSI_REG[i]->DSI_VACT_NL, VACT_NL, h); + if (dsi_params->ufoe_enable && dsi_params->ufoe_params.lr_mode_en != 1) { + if (dsi_params->ufoe_params.compress_ratio == 3) { + unsigned int ufoe_internal_width = w + w % 4; + + if (ufoe_internal_width % 3 == 0) { + DSI_OUTREGBIT(cmdq, DSI_PSCTRL_REG, DSI_REG[i]->DSI_PSCTRL, + DSI_PS_WC, + (ufoe_internal_width / 3) * + _dsi_ps_type_to_bpp(dsi_params->PS)); + } else { + unsigned int temp_w = ufoe_internal_width / 3 + 1; + + temp_w = ((temp_w % 2) == 1) ? (temp_w + 1) : temp_w; + DSI_OUTREGBIT(cmdq, DSI_PSCTRL_REG, DSI_REG[i]->DSI_PSCTRL, + DSI_PS_WC, + temp_w * _dsi_ps_type_to_bpp(dsi_params->PS)); + } + } else /* 1/2 */ + DSI_OUTREGBIT(cmdq, DSI_PSCTRL_REG, DSI_REG[i]->DSI_PSCTRL, + DSI_PS_WC, + (w + + w % 4) / 2 * _dsi_ps_type_to_bpp(dsi_params->PS)); + } else { + DSI_OUTREGBIT(cmdq, DSI_PSCTRL_REG, DSI_REG[i]->DSI_PSCTRL, DSI_PS_WC, + w * _dsi_ps_type_to_bpp(dsi_params->PS)); + } + + DSI_OUTREGBIT(cmdq, DSI_PSCTRL_REG, DSI_REG[i]->DSI_PSCTRL, DSI_PS_SEL, + ps_sel_bitvalue); + } + + return DSI_STATUS_OK; +} + +DSI_STATUS DSI_TXRX_Control(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, + LCM_DSI_PARAMS *dsi_params) +{ + int i = 0; + unsigned int lane_num_bitvalue = 0; + int lane_num = dsi_params->LANE_NUM; + int vc_num = 0; + bool null_packet_en = false; + bool dis_eotp_en = false; + bool hstx_cklp_en = dsi_params->cont_clock ? false : true; + int max_return_size = 0; + + switch (lane_num) { + case LCM_ONE_LANE: + lane_num_bitvalue = 0x1; + break; + case LCM_TWO_LANE: + lane_num_bitvalue = 0x3; + break; + case LCM_THREE_LANE: + lane_num_bitvalue = 0x7; + break; + case LCM_FOUR_LANE: + lane_num_bitvalue = 0xF; + break; + default: + ASSERT(0); + break; + } + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, VC_NUM, vc_num); + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, DIS_EOT, + dis_eotp_en); + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, BLLP_EN, + null_packet_en); + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, MAX_RTN_SIZE, + max_return_size); + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, HSTX_CKLP_EN, + hstx_cklp_en); + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, LANE_NUM, + lane_num_bitvalue); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_MEM_CONTI, DSI_WMEM_CONTI); + if (CMD_MODE == dsi_params->mode + || (CMD_MODE != dsi_params->mode && dsi_params->eint_disable)) { + if (dsi_params->ext_te_edge == LCM_POLARITY_FALLING) { + /*use ext te falling edge */ + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, + EXT_TE_EDGE, 1); + } + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, EXT_TE_EN, + 1); + } else { + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, EXT_TE_EDGE, 0); + DSI_OUTREGBIT(cmdq, DSI_TXRX_CTRL_REG, DSI_REG[i]->DSI_TXRX_CTRL, EXT_TE_EN, 0); + } + } + return DSI_STATUS_OK; +} + +int MIPITX_IsEnabled(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = 0; + int ret = 0; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0.RG_DSI0_MPPLL_PLL_EN) + ret++; + } + + DISPDBG("MIPITX for %s is %s\n", ddp_get_module_name(module), ret ? "on" : "off"); + return ret; +} + +unsigned int dsi_phy_get_clk(DISP_MODULE_ENUM module) +{ + int i = 0; + int j = 0; + unsigned int pcw = DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2.RG_DSI0_MPPLL_SDM_PCW_H; + unsigned int prediv = (1 << (DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0.RG_DSI0_MPPLL_PREDIV)); + unsigned int posdiv = (1 << (DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0.RG_DSI0_MPPLL_POSDIV)); + unsigned int txdiv0 = (1 << (DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0.RG_DSI0_MPPLL_TXDIV0)); + unsigned int txdiv1 = (1 << (DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0.RG_DSI0_MPPLL_TXDIV1)); + + DISPMSG("%s, pcw: %d, prediv: %d, posdiv: %d, txdiv0: %d, txdiv1: %d\n", __func__, pcw, + prediv, posdiv, txdiv0, txdiv1); + j = prediv * 4 * txdiv0 * txdiv1; + if (j > 0) + return 26 * pcw / j; + return 0; +} + +void DSI_PHY_clk_change(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, LCM_DSI_PARAMS *dsi_params) +{ + int i = 0; + unsigned int j = 0; + unsigned int data_Rate = dsi_params->PLL_CLOCK*2; + unsigned int txdiv = 0; + unsigned int txdiv0 = 0; + unsigned int txdiv1 = 0; + unsigned int pcw = 0; + unsigned int delta1 = 5; + /*Delta1 is SSC range, default is 0%~-5%*/ + unsigned int pdelta1 = 0; + + DISPFUNC(); + DISPMSG("New mipitx Data Rate=%d\n", data_Rate); + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (0 != data_Rate) { + if (data_Rate > 1250) { + DISPMSG("mipitx Data Rate exceed limitation(%d)\n", data_Rate); + ASSERT(0); + } else if (data_Rate >= 500) { + txdiv = 1; + txdiv0 = 0; + txdiv1 = 0; + } else if (data_Rate >= 250) { + txdiv = 2; + txdiv0 = 1; + txdiv1 = 0; + } else if (data_Rate >= 125) { + txdiv = 4; + txdiv0 = 2; + txdiv1 = 0; + } else if (data_Rate > 62) { + txdiv = 8; + txdiv0 = 2; + txdiv1 = 1; + } else if (data_Rate >= 50) { + txdiv = 16; + txdiv0 = 2; + txdiv1 = 2; + } else { + DISPMSG("dataRate is too low(%d)\n", data_Rate); + ASSERT(0); + } + + /*1. PLL TXDIV Config*/ + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON0_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, + RG_DSI0_MPPLL_TXDIV0, txdiv0); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON0_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, + RG_DSI0_MPPLL_TXDIV1, txdiv1); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON0_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, + RG_DSI0_MPPLL_PREDIV, 0); + + /* 2. PLL PCW Config */ + /* + PCW bit 24~30 = floor(pcw) + PCW bit 16~23 = (pcw - floor(pcw))*256 + PCW bit 8~15 = (pcw*256 - floor(pcw)*256)*256 + PCW bit 8~15 = (pcw*256*256 - floor(pcw)*256*256)*256 + */ + /* pcw = data_Rate*4*txdiv/(26*2);//Post DIV =4, so need data_Rate*4*/ + pcw = data_Rate*txdiv/13; + + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON2_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_H, (pcw & 0x7F)); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON2_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_16_23, ((256*(data_Rate*txdiv%13)/13) & 0xFF)); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON2_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_8_15, + ((256*(256*(data_Rate*txdiv%13)%13)/13) & 0xFF)); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON2_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_0_7, + ((256*(256*(256*(data_Rate*txdiv%13)%13)%13)/13) & 0xFF)); + + /*3. SSC Config*/ + if (1 != dsi_params->ssc_disable) { + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_PH_INIT, 1); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_PRD, 0x1B1);/*//PRD=ROUND(pmod) = 433;*/ + if (0 != dsi_params->ssc_range) + delta1 = dsi_params->ssc_range; + ASSERT(delta1 <= 8); + pdelta1 = (delta1*data_Rate*txdiv*262144+281664)/563329; + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON3_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON3, + RG_DSI0_MPPLL_SDM_SSC_DELTA, pdelta1); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON3_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON3, + RG_DSI0_MPPLL_SDM_SSC_DELTA1, pdelta1); + DISPMSG("PLL config:data_rate=%d,txdiv=%d,pcw=%d,delta1=%d,pdelta1=0x%x\n", + data_Rate, txdiv, DSI_INREG32(PMIPITX_DSI_PLL_CON2_REG, + &DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2), + delta1, pdelta1); + } + } else {/*not use*/ + /*1. PLL TXDIV Config*/ + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON0_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, + RG_DSI0_MPPLL_TXDIV0, dsi_params->pll_div1); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON0_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, + RG_DSI0_MPPLL_TXDIV1, dsi_params->pll_div2); + /*2. PLL PCW Config*/ + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON2_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_H, ((dsi_params->fbk_div) << 2)); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON2_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_16_23, 0); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON2_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_8_15, 0); + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON2_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_0_7, 0); + /*3. SSC Config*/ + /*why no ssc config*/ + } + + DSI_OUTREGBIT(cmdq, MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_FRA_EN, 1); + /*4. delay >30ns, need check, cmdq writewithmask 80ns * 9*/ + /*for(j = 0; j < 10; j++) */ + /*//DSI_OUTREG32(cmdq,&DSI_CMDQ_REG[0]->data[127],1);*/ + /*// 5. DSI_PLL_CHG = 0 */ + DSI_OUTREG32(cmdq, &DSI_PHY_REG[i]->MIPITX_DSI_PLL_CHG, 0); + /*6. delay >20us , need check*/ + for (j = 0; j < 250; j++) + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[0]->data[126], 1); + + /*7. DSI_PLL_CHG = 1 */ + DSI_OUTREG32(cmdq, &DSI_PHY_REG[i]->MIPITX_DSI_PLL_CHG, 1); + } +} +void DSI_PHY_clk_setting(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, LCM_DSI_PARAMS *dsi_params) +{ +#ifdef CONFIG_FPGA_EARLY_PORTING +#if 0 + MIPITX_Write60384(0x18, 0x00, 0x10); + MIPITX_Write60384(0x20, 0x42, 0x01); + MIPITX_Write60384(0x20, 0x43, 0x01); + MIPITX_Write60384(0x20, 0x05, 0x01); + MIPITX_Write60384(0x20, 0x22, 0x01); + MIPITX_Write60384(0x30, 0x44, 0x83); + MIPITX_Write60384(0x30, 0x40, 0x82); + MIPITX_Write60384(0x30, 0x00, 0x03); + MIPITX_Write60384(0x30, 0x68, 0x03); + MIPITX_Write60384(0x30, 0x68, 0x01); + MIPITX_Write60384(0x30, 0x50, 0x80); + MIPITX_Write60384(0x30, 0x51, 0x01); + MIPITX_Write60384(0x30, 0x54, 0x01); + MIPITX_Write60384(0x30, 0x58, 0x00); + MIPITX_Write60384(0x30, 0x59, 0x00); + MIPITX_Write60384(0x30, 0x5a, 0x00); + MIPITX_Write60384(0x30, 0x5b, (dsi_params->fbk_div) << 2); + MIPITX_Write60384(0x30, 0x04, 0x11); + MIPITX_Write60384(0x30, 0x08, 0x01); + MIPITX_Write60384(0x30, 0x0C, 0x01); + MIPITX_Write60384(0x30, 0x10, 0x01); + MIPITX_Write60384(0x30, 0x14, 0x01); + MIPITX_Write60384(0x30, 0x64, 0x20); + MIPITX_Write60384(0x30, 0x50, 0x81); + MIPITX_Write60384(0x30, 0x28, 0x00); + mdelay(500); + DISPMSG("PLL setting finish!!\n"); + + DISP_REG_SET(NULL, DISP_REG_CONFIG_MMSYS_LCM_RST_B, 0); + DISP_REG_SET(NULL, DISP_REG_CONFIG_MMSYS_LCM_RST_B, 1); + DSI_OUTREG32(cmdq, &DSI_REG[0]->DSI_COM_CTRL, 0x5); + DSI_OUTREG32(cmdq, &DSI_REG[0]->DSI_COM_CTRL, 0x0); +#endif +#else +#if 0 + MIPITX_OUTREG32(0x10215044, 0x88492483); + MIPITX_OUTREG32(0x10215040, 0x00000002); + mdelay(10); + MIPITX_OUTREG32(0x10215000, 0x00000403); + MIPITX_OUTREG32(0x10215068, 0x00000003); + MIPITX_OUTREG32(0x10215068, 0x00000001); + + mdelay(10); + MIPITX_OUTREG32(0x10215050, 0x00000000); + mdelay(10); + MIPITX_OUTREG32(0x10215054, 0x00000003); + MIPITX_OUTREG32(0x10215058, 0x60000000); + MIPITX_OUTREG32(0x1021505c, 0x00000000); + + MIPITX_OUTREG32(0x10215004, 0x00000803); + MIPITX_OUTREG32(0x10215008, 0x00000801); + MIPITX_OUTREG32(0x1021500c, 0x00000801); + MIPITX_OUTREG32(0x10215010, 0x00000801); + MIPITX_OUTREG32(0x10215014, 0x00000801); + + MIPITX_OUTREG32(0x10215050, 0x00000001); + + mdelay(10); + + + MIPITX_OUTREG32(0x10215064, 0x00000020); + return 0; +#endif + + int i = 0; + unsigned int data_Rate = dsi_params->PLL_CLOCK * 2; + unsigned int txdiv = 0; + unsigned int txdiv0 = 0; + unsigned int txdiv1 = 0; + unsigned int pcw = 0; +/* unsigned int fmod = 30;//Fmod = 30KHz by default */ + unsigned int delta1 = 5; /* Delta1 is SSC range, default is 0%~-5% */ + unsigned int pdelta1 = 0; +/* u32 m_hw_res3 = 0; + u32 temp1 = 0; + u32 temp2 = 0; + u32 temp3 = 0; + u32 temp4 = 0; + u32 temp5 = 0; + u32 lnt = 0;*/ + + /* temp1~5 is used for impedence calibration, not enable now */ +#if 0 + m_hw_res3 = INREG32(0xF0206180); + temp1 = (m_hw_res3 >> 28) & 0xF; + temp2 = (m_hw_res3 >> 24) & 0xF; + temp3 = (m_hw_res3 >> 20) & 0xF; + temp4 = (m_hw_res3 >> 16) & 0xF; + temp5 = (m_hw_res3 >> 12) & 0xF; +#endif + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + /* step 0 */ + MIPITX_OUTREGBIT(MIPITX_DSI_CLOCK_LANE_REG, DSI_PHY_REG[i]->MIPITX_DSI_CLOCK_LANE, + RG_DSI_LNTC_RT_CODE, (clock_lane>>8) & 0xf); + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE3_REG, DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE3, + RG_DSI_LNT3_RT_CODE, (data_lane3>>8) & 0xf); + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE2_REG, DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE2, + RG_DSI_LNT2_RT_CODE, (data_lane2>>8) & 0xf); + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE1_REG, DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE1, + RG_DSI_LNT1_RT_CODE, (data_lane1>>8) & 0xf); + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE0_REG, DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE0, + RG_DSI_LNT0_RT_CODE, (data_lane0>>8) & 0xf); + + DISPMSG("PLL config: clk=0x%x,lan3=0x%x,lan2=0x%x,lan1=0x%x,lan0=0x%x\n", + INREG32(&DSI_PHY_REG[i]->MIPITX_DSI_CLOCK_LANE), + INREG32(&DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE3), + INREG32(&DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE2), + INREG32(&DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE1), + INREG32(&DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE0)); + /* step 1 */ + /* MIPITX_MASKREG32(APMIXED_BASE+0x00, (0x1<<6), 1); */ + + /* step 2 */ + MIPITX_OUTREGBIT(MIPITX_DSI_BG_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_BG_CON, + RG_DSI_BG_CORE_EN, 1); + MIPITX_OUTREGBIT(MIPITX_DSI_BG_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_BG_CON, + RG_DSI_BG_CKEN, 1); + + /* step 3 */ + mdelay(1); + + /* step 4 */ + MIPITX_OUTREGBIT(MIPITX_DSI_TOP_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_TOP_CON, + RG_DSI_LNT_HS_BIAS_EN, 1); + + /* step 5 */ + MIPITX_OUTREGBIT(MIPITX_DSI_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_CON, + RG_DSI_CKG_LDOOUT_EN, 1); + MIPITX_OUTREGBIT(MIPITX_DSI_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_CON, + RG_DSI_LDOCORE_EN, 1); + + /* step 6 */ + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_PWR_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_PWR, + DA_DSI_MPPLL_SDM_PWR_ON, 1); + + /* step 7 */ + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_PWR_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_PWR, + DA_DSI_MPPLL_SDM_ISO_EN, 0); + mdelay(1); + + if (0 != data_Rate) { + if (data_Rate > 1250) { + DISPMSG("mipitx Data Rate exceed limitation(%d)\n", data_Rate); + ASSERT(0); + } else if (data_Rate >= 500) { + txdiv = 1; + txdiv0 = 0; + txdiv1 = 0; + } else if (data_Rate >= 250) { + txdiv = 2; + txdiv0 = 1; + txdiv1 = 0; + } else if (data_Rate >= 125) { + txdiv = 4; + txdiv0 = 2; + txdiv1 = 0; + } else if (data_Rate > 62) { + txdiv = 8; + txdiv0 = 2; + txdiv1 = 1; + } else if (data_Rate >= 50) { + txdiv = 16; + txdiv0 = 2; + txdiv1 = 2; + } else { + DISPMSG("dataRate is too low(%d)\n", data_Rate); + ASSERT(0); + } + + /* step 8 */ + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, RG_DSI0_MPPLL_TXDIV0, + txdiv0); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, RG_DSI0_MPPLL_TXDIV1, + txdiv1); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, RG_DSI0_MPPLL_PREDIV, + 0); + + + /* step 10 */ + /* PLL PCW config */ + /* + PCW bit 24~30 = floor(pcw) + PCW bit 16~23 = (pcw - floor(pcw))*256 + PCW bit 8~15 = (pcw*256 - floor(pcw)*256)*256 + PCW bit 8~15 = (pcw*256*256 - floor(pcw)*256*256)*256 + */ + /* pcw = data_Rate*4*txdiv/(26*2);//Post DIV =4, so need data_Rate*4 */ + pcw = data_Rate * txdiv / 13; + + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON2_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_H, (pcw & 0x7F)); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON2_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_16_23, + ((256 * (data_Rate * txdiv % 13) / 13) & 0xFF)); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON2_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_8_15, + ((256 * (256 * (data_Rate * txdiv % 13) % 13) / + 13) & 0xFF)); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON2_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, + RG_DSI0_MPPLL_SDM_PCW_0_7, + ((256 * + (256 * (256 * (data_Rate * txdiv % 13) % 13) % 13) / + 13) & 0xFF)); + + if (1 != dsi_params->ssc_disable) { + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON1_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_PH_INIT, 1); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_PRD, 0x1B1); /* PRD=ROUND(pmod) = 433; */ + if (0 != dsi_params->ssc_range) + delta1 = dsi_params->ssc_range; + ASSERT(delta1 <= 8); + pdelta1 = (delta1 * data_Rate * txdiv * 262144 + 281664) / 563329; + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON3_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON3, + RG_DSI0_MPPLL_SDM_SSC_DELTA, pdelta1); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON3_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON3, + RG_DSI0_MPPLL_SDM_SSC_DELTA1, pdelta1); + DISPMSG + ("PLL config:data_rate=%d,txdiv=%d,pcw=%d,delta1=%d,pdelta1=0x%x\n", + data_Rate, txdiv, DSI_INREG32(PMIPITX_DSI_PLL_CON2_REG, + &DSI_PHY_REG[i]-> + MIPITX_DSI_PLL_CON2), delta1, + pdelta1); + } + } else { + DISPERR("[dsi_dsi.c] PLL clock should not be 0!!!\n"); + ASSERT(0); + } + + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_FRA_EN, 1); + + /* step 11 */ + MIPITX_OUTREGBIT(MIPITX_DSI_CLOCK_LANE_REG, DSI_PHY_REG[i]->MIPITX_DSI_CLOCK_LANE, + RG_DSI_LNTC_LDOOUT_EN, 1); + + /* step 12 */ + if (dsi_params->LANE_NUM > 0) { + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE0, + RG_DSI_LNT0_LDOOUT_EN, 1); + } + /* step 13 */ + if (dsi_params->LANE_NUM > 1) { + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE1_REG, + DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE1, + RG_DSI_LNT1_LDOOUT_EN, 1); + } + /* step 14 */ + if (dsi_params->LANE_NUM > 2) { + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE2_REG, + DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE2, + RG_DSI_LNT2_LDOOUT_EN, 1); + } + /* step 15 */ + if (dsi_params->LANE_NUM > 3) { + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE3_REG, + DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE3, + RG_DSI_LNT3_LDOOUT_EN, 1); + } + /* step 16 */ + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, + RG_DSI0_MPPLL_PLL_EN, 1); + + /* step 17 */ + mdelay(1); + + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CHG_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CHG, + RG_DSI0_MPPLL_SDM_PCW_CHG, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CHG_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_CHG, + RG_DSI0_MPPLL_SDM_PCW_CHG, 1); + + if ((0 != data_Rate) && (1 != dsi_params->ssc_disable)) { + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON1_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_EN, 1); + } else { + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON1_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_EN, 0); + } + + /* step 18 */ + MIPITX_OUTREGBIT(MIPITX_DSI_TOP_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_TOP_CON, + RG_DSI_PAD_TIE_LOW_EN, 0); + + mdelay(1); + } +#endif +} + + + +void DSI_PHY_TIMCONFIG(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, LCM_DSI_PARAMS *dsi_params) +{ + +#ifdef CONFIG_FPGA_EARLY_PORTING + return 0; +#endif + + DSI_PHY_TIMCON0_REG timcon0; + DSI_PHY_TIMCON1_REG timcon1; + DSI_PHY_TIMCON2_REG timcon2; + DSI_PHY_TIMCON3_REG timcon3; + int i = 0; + unsigned int lane_no; + unsigned int cycle_time; + unsigned int ui; + unsigned int hs_trail_m, hs_trail_n; +#if 0 + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON0, 0x140f0708); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON1, 0x10280c20); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON2, 0x14280000); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON3, 0x00101a06); + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_PHY_TIMECON4, 0x00023000); + } + return; +#endif + lane_no = dsi_params->LANE_NUM; + if (0 != dsi_params->PLL_CLOCK) { + ui = 1000 / (dsi_params->PLL_CLOCK * 2) + 0x01; + cycle_time = 8000 / (dsi_params->PLL_CLOCK * 2) + 0x01; + DISPMSG + ("[DISP] - kernel - DSI_PHY_TIMCONFIG, Cycle Time = %d(ns), Unit Interval = %d(ns). , lane# = %d\n", + cycle_time, ui, lane_no); + } else { + DISPERR("[dsi_dsi.c] PLL clock should not be 0!!!\n"); + ASSERT(0); + } + + /* div2_real=div2 ? div2*0x02 : 0x1; */ + /* cycle_time = (1000 * div2 * div1 * pre_div * post_div)/ (fbk_sel * (fbk_div+0x01) * 26) + 1; */ + /* ui = (1000 * div2 * div1 * pre_div * post_div)/ (fbk_sel * (fbk_div+0x01) * 26 * 2) + 1; */ +#define NS_TO_CYCLE(n, c) ((n) / (c)) + + hs_trail_m = 1; + hs_trail_n = + (dsi_params->HS_TRAIL == 0) ? NS_TO_CYCLE(((hs_trail_m * 0x4 * ui) + 0x50), + cycle_time) : dsi_params->HS_TRAIL; + /* +3 is recommended from designer becauase of HW latency */ + timcon0.HS_TRAIL = (hs_trail_m > hs_trail_n) ? hs_trail_m : hs_trail_n; + + timcon0.HS_PRPR = + (dsi_params->HS_PRPR == 0) ? NS_TO_CYCLE((0x40 + 0x5 * ui), + cycle_time) : dsi_params->HS_PRPR; + /* HS_PRPR can't be 1. */ + if (timcon0.HS_PRPR < 1) + timcon0.HS_PRPR = 1; + + timcon0.HS_ZERO = + (dsi_params->HS_ZERO == 0) ? NS_TO_CYCLE((0xC8 + 0x0a * ui), + cycle_time) : dsi_params->HS_ZERO; + if (timcon0.HS_ZERO > timcon0.HS_PRPR) + timcon0.HS_ZERO -= timcon0.HS_PRPR; + + timcon0.LPX = (dsi_params->LPX == 0) ? NS_TO_CYCLE(0x50, cycle_time) : dsi_params->LPX; + if (timcon0.LPX < 1) + timcon0.LPX = 1; + + /* timcon1.TA_SACK = (dsi_params->TA_SACK == 0) ? 1 : dsi_params->TA_SACK; */ + timcon1.TA_GET = (dsi_params->TA_GET == 0) ? (0x5 * timcon0.LPX) : dsi_params->TA_GET; + timcon1.TA_SURE = + (dsi_params->TA_SURE == 0) ? (0x3 * timcon0.LPX / 0x2) : dsi_params->TA_SURE; + timcon1.TA_GO = (dsi_params->TA_GO == 0) ? (0x4 * timcon0.LPX) : dsi_params->TA_GO; + /* -------------------------------------------------------------- */ + /* NT35510 need fine tune timing */ + /* Data_hs_exit = 60 ns + 128UI */ + /* Clk_post = 60 ns + 128 UI. */ + /* -------------------------------------------------------------- */ + timcon1.DA_HS_EXIT = + (dsi_params->DA_HS_EXIT == 0) ? (0x2 * timcon0.LPX) : dsi_params->DA_HS_EXIT; + + timcon2.CLK_TRAIL = + ((dsi_params->CLK_TRAIL == 0) ? NS_TO_CYCLE(0x60, + cycle_time) : dsi_params->CLK_TRAIL) + 0x01; + /* CLK_TRAIL can't be 1. */ + if (timcon2.CLK_TRAIL < 2) + timcon2.CLK_TRAIL = 2; + + /* timcon2.LPX_WAIT = (dsi_params->LPX_WAIT == 0) ? 1 : dsi_params->LPX_WAIT; */ + timcon2.CONT_DET = dsi_params->CONT_DET; + timcon2.CLK_ZERO = + (dsi_params->CLK_ZERO == 0) ? NS_TO_CYCLE(0x190, cycle_time) : dsi_params->CLK_ZERO; + + timcon3.CLK_HS_PRPR = + (dsi_params->CLK_HS_PRPR == 0) ? NS_TO_CYCLE(0x40, + cycle_time) : dsi_params->CLK_HS_PRPR; + if (timcon3.CLK_HS_PRPR < 1) + timcon3.CLK_HS_PRPR = 1; + timcon3.CLK_HS_EXIT = + (dsi_params->CLK_HS_EXIT == 0) ? (0x2 * timcon0.LPX) : dsi_params->CLK_HS_EXIT; + timcon3.CLK_HS_POST = + (dsi_params->CLK_HS_POST == 0) ? NS_TO_CYCLE((0x60 + 0x34 * ui), + cycle_time) : dsi_params->CLK_HS_POST; + + DISPMSG( + "[DISP] - kernel - DSI_PHY_TIMCONFIG, HS_TRAIL = %d, HS_ZERO = %d, HS_PRPR = %d, LPX = %d, TA_GET = %d, TA_SURE = %d, TA_GO = %d, CLK_TRAIL = %d, CLK_ZERO = %d, CLK_HS_PRPR = %d\n", + timcon0.HS_TRAIL, timcon0.HS_ZERO, timcon0.HS_PRPR, timcon0.LPX, + timcon1.TA_GET, timcon1.TA_SURE, timcon1.TA_GO, timcon2.CLK_TRAIL, + timcon2.CLK_ZERO, timcon3.CLK_HS_PRPR); + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON0_REG, DSI_REG[i]->DSI_PHY_TIMECON0, LPX, + timcon0.LPX); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON0_REG, DSI_REG[i]->DSI_PHY_TIMECON0, HS_PRPR, + timcon0.HS_PRPR); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON0_REG, DSI_REG[i]->DSI_PHY_TIMECON0, HS_ZERO, + timcon0.HS_ZERO); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON0_REG, DSI_REG[i]->DSI_PHY_TIMECON0, HS_TRAIL, + timcon0.HS_TRAIL); + + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON1_REG, DSI_REG[i]->DSI_PHY_TIMECON1, TA_GO, + timcon1.TA_GO); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON1_REG, DSI_REG[i]->DSI_PHY_TIMECON1, TA_SURE, + timcon1.TA_SURE); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON1_REG, DSI_REG[i]->DSI_PHY_TIMECON1, TA_GET, + timcon1.TA_GET); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON1_REG, DSI_REG[i]->DSI_PHY_TIMECON1, DA_HS_EXIT, + timcon1.DA_HS_EXIT); + + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON2_REG, DSI_REG[i]->DSI_PHY_TIMECON2, CONT_DET, + timcon2.CONT_DET); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON2_REG, DSI_REG[i]->DSI_PHY_TIMECON2, CLK_ZERO, + timcon2.CLK_ZERO); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON2_REG, DSI_REG[i]->DSI_PHY_TIMECON2, CLK_TRAIL, + timcon2.CLK_TRAIL); + + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON3_REG, DSI_REG[i]->DSI_PHY_TIMECON3, CLK_HS_PRPR, + timcon3.CLK_HS_PRPR); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON3_REG, DSI_REG[i]->DSI_PHY_TIMECON3, CLK_HS_POST, + timcon3.CLK_HS_POST); + DSI_OUTREGBIT(cmdq, DSI_PHY_TIMCON3_REG, DSI_REG[i]->DSI_PHY_TIMECON3, CLK_HS_EXIT, + timcon3.CLK_HS_EXIT); + DISPMSG("%s, 0x%08x,0x%08x,0x%08x,0x%08x\n", __func__, + INREG32(&DSI_REG[i]->DSI_PHY_TIMECON0), + INREG32(&DSI_REG[i]->DSI_PHY_TIMECON1), + INREG32(&DSI_REG[i]->DSI_PHY_TIMECON2), + INREG32(&DSI_REG[i]->DSI_PHY_TIMECON3)); + } +} + + +void DSI_PHY_clk_switch(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, int on) +{ + int i = 0; + + /* can't use cmdq for this */ + ASSERT(cmdq == NULL); + + if (on) { + DSI_PHY_clk_setting(module, cmdq, &(_dsi_context[i].dsi_params)); + } else { + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + /* disable mipi clock */ + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, RG_DSI0_MPPLL_PLL_EN, + 0); + mdelay(1); + MIPITX_OUTREGBIT(MIPITX_DSI_TOP_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_TOP_CON, + RG_DSI_PAD_TIE_LOW_EN, 1); + + + MIPITX_OUTREGBIT(MIPITX_DSI_CLOCK_LANE_REG, + DSI_PHY_REG[i]->MIPITX_DSI_CLOCK_LANE, + RG_DSI_LNTC_LDOOUT_EN, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE0, + RG_DSI_LNT0_LDOOUT_EN, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE1_REG, + DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE1, + RG_DSI_LNT1_LDOOUT_EN, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE2_REG, + DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE2, + RG_DSI_LNT2_LDOOUT_EN, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_DATA_LANE3_REG, + DSI_PHY_REG[i]->MIPITX_DSI_DATA_LANE3, + RG_DSI_LNT3_LDOOUT_EN, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_PWR_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_PWR, + DA_DSI_MPPLL_SDM_ISO_EN, 1); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_PWR_REG, DSI_PHY_REG[i]->MIPITX_DSI_PLL_PWR, + DA_DSI_MPPLL_SDM_PWR_ON, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_TOP_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_TOP_CON, + RG_DSI_LNT_HS_BIAS_EN, 0); + + MIPITX_OUTREGBIT(MIPITX_DSI_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_CON, + RG_DSI_CKG_LDOOUT_EN, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_CON, + RG_DSI_LDOCORE_EN, 0); + + MIPITX_OUTREGBIT(MIPITX_DSI_BG_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_BG_CON, + RG_DSI_BG_CKEN, 0); + MIPITX_OUTREGBIT(MIPITX_DSI_BG_CON_REG, DSI_PHY_REG[i]->MIPITX_DSI_BG_CON, + RG_DSI_BG_CORE_EN, 0); + + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, RG_DSI0_MPPLL_PREDIV, + 0); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, RG_DSI0_MPPLL_TXDIV0, + 0); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, RG_DSI0_MPPLL_TXDIV1, + 0); + MIPITX_OUTREGBIT(MIPITX_DSI_PLL_CON0_REG, + DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON0, RG_DSI0_MPPLL_POSDIV, + 0); + + + MIPITX_OUTREG32(&DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON1, 0x00000000); + MIPITX_OUTREG32(&DSI_PHY_REG[i]->MIPITX_DSI_PLL_CON2, 0x50000000); + mdelay(1); + } + } +} + +DSI_STATUS DSI_EnableClk(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ +#if 0 + int i = 0; + + DISPFUNC(); + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) + DSI_OUTREGBIT(cmdq, DSI_COM_CTRL_REG, DSI_REG[i]->DSI_COM_CTRL, DSI_EN, 1); +#endif + return DSI_STATUS_OK; +} + +DSI_STATUS DSI_DisableClk(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ +#if 0 + int i; + + DISPFUNC(); + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) + DSI_OUTREGBIT(cmdq, DSI_COM_CTRL_REG, DSI_REG[i]->DSI_COM_CTRL, DSI_EN, 0); +#endif + return DSI_STATUS_OK; +} + +DSI_STATUS DSI_Start(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + if (module == DISP_MODULE_DSI0) { + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[0]->DSI_START, DSI_START, 0); + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[0]->DSI_START, DSI_START, 1); + } + + return DSI_STATUS_OK; +} + +void DSI_Set_VM_CMD(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + + int i = 0; + + if (module != DISP_MODULE_DSIDUAL) { + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_VM_CMD_CON_REG, DSI_REG[i]->DSI_VM_CMD_CON, + TS_VFP_EN, 1); + DSI_OUTREGBIT(cmdq, DSI_VM_CMD_CON_REG, DSI_REG[i]->DSI_VM_CMD_CON, + VM_CMD_EN, 1); + DISPMSG("DSI_Set_VM_CMD"); + } + } else { + DSI_OUTREGBIT(cmdq, DSI_VM_CMD_CON_REG, DSI_REG[i]->DSI_VM_CMD_CON, TS_VFP_EN, 1); + DSI_OUTREGBIT(cmdq, DSI_VM_CMD_CON_REG, DSI_REG[i]->DSI_VM_CMD_CON, VM_CMD_EN, 1); + } +} + +DSI_STATUS DSI_EnableVM_CMD(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + int i = 0; + + if (cmdq) + DSI_MASKREG32(cmdq, &DSI_REG[0]->DSI_INTSTA, 0x00000020, 0); + else + wait_vm_cmd_done = false; + + if (module != DISP_MODULE_DSIDUAL) { + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[i]->DSI_START, VM_CMD_START, 0); + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[i]->DSI_START, VM_CMD_START, 1); + } + } else { + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[0]->DSI_START, VM_CMD_START, 0); + DSI_OUTREGBIT(cmdq, DSI_START_REG, DSI_REG[0]->DSI_START, VM_CMD_START, 1); + } + if (cmdq) + DSI_POLLREG32(cmdq, &DSI_REG[0]->DSI_INTSTA, 0x00000020, 1); + else + wait_event_interruptible(_dsi_wait_vm_cmd_done_queue[0], wait_vm_cmd_done); + + return DSI_STATUS_OK; +} + +unsigned int DSI_esd_check_times(LCM_DSI_PARAMS *dsi_params) +{ + int i = 0; + static unsigned int esd_check_times; + + if (esd_check_times) + return esd_check_times; + esd_check_times = 0; + for (i = 0; i < ESD_CHECK_NUM; i++) { + if (dsi_params->lcm_esd_check_table[i].cmd == 0) + break; + esd_check_times++; + } + DISPMSG("1.ESD times %d\n", esd_check_times); + return esd_check_times; +} + +int DSI_read_cmp(unsigned int index, DSI_RX_DATA_REG *read_data, + unsigned char *para_list, unsigned int count) +{ + int ret = 0; + int i = 0; + unsigned char packet_type; + uint32_t recv_data_cnt; + LCM_DSI_PARAMS *dsi_params = NULL; + unsigned char buffer[20]; + + dsi_params = &_dsi_context[0].dsi_params; + packet_type = read_data[0].byte0; + DISPDBG("DSI read packet_type is 0x%x\n", packet_type); + + /* 0x02: acknowledge & error report */ + /* 0x11: generic short read response(1 byte return) */ + /* 0x12: generic short read response(2 byte return) */ + /* 0x1a: generic long read response */ + /* 0x1c: dcs long read response */ + /* 0x21: dcs short read response(1 byte return) */ + /* 0x22: dcs short read response(2 byte return) */ + if (packet_type == 0x1A || packet_type == 0x1C) { + recv_data_cnt = read_data[0].byte1 + read_data[0].byte2 * 16; + DISPDBG("packet_type=0x%x,recv_data_cnt = %d\n", + packet_type, recv_data_cnt); + if (recv_data_cnt > count) + recv_data_cnt = count; + if (recv_data_cnt <= 4) { + memcpy((void *)buffer, (void *)&read_data[1], recv_data_cnt); + } else if (recv_data_cnt <= 8) { + memcpy((void *)buffer, (void *)&read_data[1], 4); + memcpy((void *)(buffer + 4), (void *)&read_data[2], + recv_data_cnt - 4); + } else { + memcpy((void *)buffer, (void *)&read_data[1], 4); + memcpy((void *)(buffer + 4), (void *)&read_data[2], 4); + memcpy((void *)(buffer + 8), (void *)&read_data[3], + recv_data_cnt - 8); + } + for (i = 0; i < recv_data_cnt; i++) { + DISPDBG("buffer[%d]=0x%x\n", i, buffer[i]); + if (buffer[i] != dsi_params->lcm_esd_check_table[index].para_list[i]) { + ret = 1; + DISPMSG("[ESD]CMP index %d return value 0x%x,para_list[%d]=0x%x\n", index, + buffer[i], i, dsi_params->lcm_esd_check_table[index].para_list[i]); + break; + } + } + } else if (packet_type == 0x11 || packet_type == 0x12 || + packet_type == 0x21 || packet_type == 0x22) { + if (packet_type == 0x11 || packet_type == 0x21) + recv_data_cnt = 1; + else + recv_data_cnt = 2; + if (recv_data_cnt > count) + recv_data_cnt = count; + memcpy((void *)buffer, (void *)&read_data[0].byte1, + recv_data_cnt); + DISPDBG("packet_type=0x%x,recv_data_cnt = %d\n", packet_type, recv_data_cnt); + for (i = 0; i < recv_data_cnt; i++) { + DISPDBG("buffer[%d]=0x%x\n", i, buffer[i]); + if (buffer[i] != dsi_params->lcm_esd_check_table[index].para_list[i]) { + ret = 1; + DISPMSG("[ESD]CMP index %d return value 0x%x,para_list[%d]=0x%x\n", index, + buffer[i], i, dsi_params->lcm_esd_check_table[index].para_list[i]); + break; + } + } + } else if (packet_type == 0x02) { + DISPMSG("read return type is 0x02, not support re-read\n"); + ret = 1; + } else { + DISPMSG("read return type is non-recognite, type = 0x%x\n", + packet_type); + ret = 1; + } + return ret; +} +/* / return value: the data length we got */ +uint32_t DSI_dcs_read_lcm_reg_v2(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, uint8_t cmd, + uint8_t *buffer, uint8_t buffer_size) +{ + int d = 0; + uint32_t max_try_count = 5; + uint32_t recv_data_cnt; + unsigned char packet_type; + DSI_RX_DATA_REG read_data0; + DSI_RX_DATA_REG read_data1; + DSI_RX_DATA_REG read_data2; + DSI_RX_DATA_REG read_data3; + DSI_T0_INS t0; + DSI_T0_INS t1; + static const long WAIT_TIMEOUT = 2 * HZ; /* 2 sec */ + long ret; + int timeout = 0; + + for (d = DSI_MODULE_BEGIN(module); d <= DSI_MODULE_END(module); d++) { + if (DSI_REG[d]->DSI_MODE_CTRL.MODE) { + /* only support cmd mode read */ + DISPERR("DSI Read Fail: DSI Mode is %d\n", + DSI_REG[d]->DSI_MODE_CTRL.MODE); + return 0; + } + + if (buffer == NULL || buffer_size == 0) { + /* illegal parameters */ + DISPERR("DSI Read Fail: buffer=%p and buffer_size=%d\n", buffer, + (unsigned int)buffer_size); + return 0; + } + + do { + if (max_try_count == 0) { + DISPERR("DSI Read Fail: try 5 times\n"); + return 0; + } + + max_try_count--; + recv_data_cnt = 0; + /* read_timeout_ms = 20; */ + + /* 1. wait dsi not busy => can't read if dsi busy */ + DSI_WaitForNotBusy(module, cmdq); + + /* 2. Check rd_rdy & cmd_done irq */ + if (DSI_REG[d]->DSI_INTEN.RD_RDY == 0) { + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, DSI_REG[d]->DSI_INTEN, + RD_RDY, 1); + + } + if (DSI_REG[d]->DSI_INTEN.CMD_DONE == 0) { + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, DSI_REG[d]->DSI_INTEN, + CMD_DONE, 1); + } + if (DSI_REG[d]->DSI_INTSTA.RD_RDY != 0 + || DSI_REG[d]->DSI_INTSTA.CMD_DONE != 0) { + /* dump cmdq & rxdata */ + { + unsigned int i; + + DISPMSG("Last DSI Read Why not clear irq???\n"); + DISPMSG("DSI_CMDQ_SIZE : %d\n", + AS_UINT32(&DSI_REG[d]->DSI_CMDQ_SIZE)); + for (i = 0; i < DSI_REG[d]->DSI_CMDQ_SIZE.CMDQ_SIZE; i++) { + DISPMSG("DSI_CMDQ_DATA%d : 0x%08x\n", i, + AS_UINT32(&DSI_CMDQ_REG[d]->data[i])); + } + DISPMSG("DSI_RX_DATA0 : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_RX_DATA0)); + DISPMSG("DSI_RX_DATA1 : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_RX_DATA1)); + DISPMSG("DSI_RX_DATA2 : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_RX_DATA2)); + DISPMSG("DSI_RX_DATA3 : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_RX_DATA3)); + } + /* clear irq */ + DSI_OUTREGBIT(cmdq, DSI_INT_STATUS_REG, DSI_REG[d]->DSI_INTSTA, + RD_RDY, 0); + DSI_OUTREGBIT(cmdq, DSI_INT_STATUS_REG, DSI_REG[d]->DSI_INTSTA, + CMD_DONE, 0); + } + /* 3. Send cmd */ + t0.CONFG = 0x04; /* /BTA */ + /* / 0xB0 is used to distinguish DCS cmd or Gerneric cmd, is that Right??? */ + t0.Data_ID = + (cmd < + 0xB0) ? DSI_DCS_READ_PACKET_ID : DSI_GERNERIC_READ_LONG_PACKET_ID; + t0.Data0 = cmd; + t0.Data1 = 0; + /* set max return size */ + t1.CONFG = 0x00; + t1.Data_ID = 0x37; + t1.Data0 = buffer_size <= 10 ? buffer_size : 10; + t1.Data1 = 0; + + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[d]->data[0], AS_UINT32(&t1)); + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[d]->data[1], AS_UINT32(&t0)); + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_CMDQ_SIZE, 2); + + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_START, 0); + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_START, 1); + + /* / the following code is to */ + /* / 1: wait read ready */ + /* / 2: ack read ready */ + /* / 3: wait for CMDQ_DONE(interrupt handler do this op) */ + /* / 4: read data */ + ret = + wait_event_interruptible_timeout(_dsi_dcs_read_wait_queue[d], + waitRDDone, WAIT_TIMEOUT); + waitRDDone = false; + if (ret > 0) { + do { + timeout++; + udelay(1); + DSI_OUTREGBIT(cmdq, DSI_RACK_REG, DSI_REG[d]->DSI_RACK, + DSI_RACK, 1); + } while (DSI_REG[d]->DSI_INTSTA.BUSY && (timeout < 1000)); + + if (timeout == 1000) { + /* wait cmd done timeout */ + DISPERR("DSI Read Fail: dsi wait cmd done timeout\n"); + DSI_DumpRegisters(module, 2); + + /* /do necessary reset here */ + DSI_OUTREGBIT(cmdq, DSI_RACK_REG, DSI_REG[d]->DSI_RACK, + DSI_RACK, 1); + DSI_Reset(module, NULL); + + /* clear rd rdy interrupt */ + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, + DSI_REG[d]->DSI_INTSTA, RD_RDY, 0); + return 0; + } + } else if (ret == 0) { + /* wait read ready timeout */ + DISPERR("DSI Read Fail: dsi wait read ready timeout\n"); + DSI_DumpRegisters(module, 2); + + /* /do necessary reset here */ + DSI_OUTREGBIT(cmdq, DSI_RACK_REG, DSI_REG[d]->DSI_RACK, DSI_RACK, + 1); + DSI_Reset(module, NULL); + return 0; + } else if (ret < 0) { + /* wake up by other interrupt, need try again??? */ + DISPERR("DSI Read Fail: dsi wait read ready wake up by other interrupt\n"); + /* /do necessary reset here */ + DSI_OUTREGBIT(cmdq, DSI_RACK_REG, DSI_REG[d]->DSI_RACK, DSI_RACK, + 1); + DSI_Reset(module, NULL); + return 0; + } + + + /* clear interrupt */ + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, DSI_REG[d]->DSI_INTSTA, RD_RDY, 0); + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, DSI_REG[d]->DSI_INTSTA, CMD_DONE, + 0); + + /* read data */ + DSI_OUTREG32(cmdq, &read_data0, AS_UINT32(&DSI_REG[d]->DSI_RX_DATA0)); + DSI_OUTREG32(cmdq, &read_data1, AS_UINT32(&DSI_REG[d]->DSI_RX_DATA1)); + DSI_OUTREG32(cmdq, &read_data2, AS_UINT32(&DSI_REG[d]->DSI_RX_DATA2)); + DSI_OUTREG32(cmdq, &read_data3, AS_UINT32(&DSI_REG[d]->DSI_RX_DATA3)); + + + { + unsigned int i; + + DISPMSG("DSI read begin i = %d --------------------\n", + 5 - max_try_count); + DISPMSG("DSI_RX_STA : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_TRIG_STA)); + DISPMSG("DSI_CMDQ_SIZE : %d\n", + AS_UINT32(&DSI_REG[d]->DSI_CMDQ_SIZE)); + for (i = 0; i < DSI_REG[d]->DSI_CMDQ_SIZE.CMDQ_SIZE; i++) { + DISPMSG("DSI_CMDQ_DATA%d : 0x%08x\n", i, + AS_UINT32(&DSI_CMDQ_REG[d]->data[i])); + } + DISPMSG("DSI_RX_DATA0 : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_RX_DATA0)); + DISPMSG("DSI_RX_DATA1 : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_RX_DATA1)); + DISPMSG("DSI_RX_DATA2 : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_RX_DATA2)); + DISPMSG("DSI_RX_DATA3 : 0x%08x\n", + AS_UINT32(&DSI_REG[d]->DSI_RX_DATA3)); + DISPMSG("DSI read end ----------------------------\n"); + } + + packet_type = read_data0.byte0; + + DISPMSG("DSI read packet_type is 0x%x\n", packet_type); + + /* 0x02: acknowledge & error report */ + /* 0x11: generic short read response(1 byte return) */ + /* 0x12: generic short read response(2 byte return) */ + /* 0x1a: generic long read response */ + /* 0x1c: dcs long read response */ + /* 0x21: dcs short read response(1 byte return) */ + /* 0x22: dcs short read response(2 byte return) */ + if (packet_type == 0x1A || packet_type == 0x1C) { + recv_data_cnt = read_data0.byte1 + read_data0.byte2 * 16; + if (recv_data_cnt > 10) { + DISPMSG + ("DSI read long packet data exceeds 4 bytes return size: %d\n", + recv_data_cnt); + recv_data_cnt = 10; + } + + if (recv_data_cnt > buffer_size) { + DISPMSG + ("DSI read long packet data exceeds buffer size return size %d\n", + recv_data_cnt); + recv_data_cnt = buffer_size; + } + DISPMSG("DSI read long packet size: %d\n", recv_data_cnt); + + if (recv_data_cnt <= 4) { + memcpy((void *)buffer, (void *)&read_data1, recv_data_cnt); + } else if (recv_data_cnt <= 8) { + memcpy((void *)buffer, (void *)&read_data1, 4); + memcpy((void *)((uint8_t *) buffer + 4), (void *)&read_data2, + recv_data_cnt - 4); + } else { + memcpy((void *)buffer, (void *)&read_data1, 4); + memcpy((void *)((uint8_t *) buffer + 4), (void *)&read_data2, 4); + memcpy((void *)((uint8_t *) buffer + 8), (void *)&read_data3, + recv_data_cnt - 8); + } + } else if (packet_type == 0x11 || packet_type == 0x12 || + packet_type == 0x21 || packet_type == 0x22) { + if (packet_type == 0x11 || packet_type == 0x21) + recv_data_cnt = 1; + else + recv_data_cnt = 2; + if (recv_data_cnt > buffer_size) { + DISPMSG + ("DSI read short packet data exceeds buffer size: %d\n", + buffer_size); + recv_data_cnt = buffer_size; + memcpy((void *)buffer, (void *)&read_data0.byte1, + recv_data_cnt); + } else { + memcpy((void *)buffer, (void *)&read_data0.byte1, + recv_data_cnt); + } + + } else if (packet_type == 0x02) { + DISPMSG("read return type is 0x02, re-read\n"); + } else { + DISPMSG("read return type is non-recognite, type = 0x%x\n", + packet_type); + return 0; + } + } while (packet_type == 0x02); + /* / here: we may receive a ACK packet which packet type is 0x02 (incdicates some error happened) */ + /* / therefore we try re-read again until no ACK packet */ + /* / But: if it is a good way to keep re-trying ??? */ + } + + return recv_data_cnt; +} + +void DSI_set_cmdq_V2(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, unsigned cmd, unsigned char count, + unsigned char *para_list, unsigned char force_update) +{ + uint32_t i = 0; + int d = 0; + unsigned long goto_addr, mask_para, set_para; + DSI_T0_INS t0; + DSI_T2_INS t2; + + t2.pdata = NULL; + /* DISPFUNC(); */ + for (d = DSI_MODULE_BEGIN(module); d <= DSI_MODULE_END(module); d++) { + if (0 != DSI_REG[d]->DSI_MODE_CTRL.MODE) { /* not in cmd mode */ + DSI_VM_CMD_CON_REG vm_cmdq; + + memset(&vm_cmdq, 0, sizeof(DSI_VM_CMD_CON_REG)); + DSI_READREG32(PDSI_VM_CMD_CON_REG, &vm_cmdq, &DSI_REG[d]->DSI_VM_CMD_CON); + if (cmd < 0xB0) { + if (count > 1) { + vm_cmdq.LONG_PKT = 1; + vm_cmdq.CM_DATA_ID = DSI_DCS_LONG_PACKET_ID; + vm_cmdq.CM_DATA_0 = count + 1; + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_VM_CMD_CON, + AS_UINT32(&vm_cmdq)); + + goto_addr = + (unsigned long)(&DSI_VM_CMD_REG[d]->data[0].byte0); + mask_para = (0xFF << ((goto_addr & 0x3) * 8)); + set_para = (cmd << ((goto_addr & 0x3) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~0x3), mask_para, + set_para); + + for (i = 0; i < count; i++) { + goto_addr = + (unsigned long)(&DSI_VM_CMD_REG[d]->data[0]. + byte1) + i; + mask_para = (0xFF << ((goto_addr & 0x3) * 8)); + set_para = + (para_list[i] << ((goto_addr & 0x3) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~0x3), mask_para, + set_para); + } + } else { + vm_cmdq.LONG_PKT = 0; + vm_cmdq.CM_DATA_0 = cmd; + if (count) { + vm_cmdq.CM_DATA_ID = DSI_DCS_SHORT_PACKET_ID_1; + vm_cmdq.CM_DATA_1 = para_list[0]; + } else { + vm_cmdq.CM_DATA_ID = DSI_DCS_SHORT_PACKET_ID_0; + vm_cmdq.CM_DATA_1 = 0; + } + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_VM_CMD_CON, + AS_UINT32(&vm_cmdq)); + } + } else { + if (count > 1) { + vm_cmdq.LONG_PKT = 1; + vm_cmdq.CM_DATA_ID = DSI_GERNERIC_LONG_PACKET_ID; + vm_cmdq.CM_DATA_0 = count + 1; + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_VM_CMD_CON, + AS_UINT32(&vm_cmdq)); + + goto_addr = + (unsigned long)(&DSI_VM_CMD_REG[d]->data[0].byte0); + mask_para = (0xFF << ((goto_addr & 0x3) * 8)); + set_para = (cmd << ((goto_addr & 0x3) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~0x3), mask_para, + set_para); + + for (i = 0; i < count; i++) { + goto_addr = + (unsigned long)(&DSI_VM_CMD_REG[d]->data[0]. + byte1) + i; + mask_para = (0xFF << ((goto_addr & 0x3) * 8)); + set_para = + (para_list[i] << ((goto_addr & 0x3) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~0x3), mask_para, + set_para); + } + } else { + vm_cmdq.LONG_PKT = 0; + vm_cmdq.CM_DATA_0 = cmd; + if (count) { + vm_cmdq.CM_DATA_ID = DSI_GERNERIC_SHORT_PACKET_ID_2; + vm_cmdq.CM_DATA_1 = para_list[0]; + } else { + vm_cmdq.CM_DATA_ID = DSI_GERNERIC_SHORT_PACKET_ID_1; + vm_cmdq.CM_DATA_1 = 0; + } + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_VM_CMD_CON, + AS_UINT32(&vm_cmdq)); + } + } + /* start DSI VM CMDQ */ + if (force_update) + DSI_EnableVM_CMD(module, cmdq); + } else { + DSI_WaitForNotBusy(module, cmdq); + + if (cmd < 0xB0) { + if (count > 1) { + /*DSI_CMDQ cmd_data;*/ + + t2.CONFG = 2; + t2.Data_ID = DSI_DCS_LONG_PACKET_ID; + t2.WC16 = count + 1; + + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[d]->data[0], + AS_UINT32(&t2)); + + goto_addr = + (unsigned long)(&DSI_CMDQ_REG[d]->data[1].byte0); + mask_para = (0xFFu << ((goto_addr & 0x3u) * 8)); + set_para = (cmd << ((goto_addr & 0x3u) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~((unsigned long)0x3u)), + mask_para, set_para); + + for (i = 0; i < count; i++) { + goto_addr = + (unsigned long)(&DSI_CMDQ_REG[d]->data[1]. + byte1) + i; + mask_para = (0xFFu << ((goto_addr & 0x3u) * 8)); + set_para = + (para_list[i] << ((goto_addr & 0x3u) * 8)); + DSI_MASKREG32(cmdq, + goto_addr & (~((unsigned long)0x3u)), + mask_para, set_para); + } + + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_CMDQ_SIZE, + 2 + (count) / 4); + } else { + t0.CONFG = 0; + t0.Data0 = cmd; + if (count) { + t0.Data_ID = DSI_DCS_SHORT_PACKET_ID_1; + t0.Data1 = para_list[0]; + } else { + t0.Data_ID = DSI_DCS_SHORT_PACKET_ID_0; + t0.Data1 = 0; + } + + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[d]->data[0], + AS_UINT32(&t0)); + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_CMDQ_SIZE, 1); + } + } else { + if (count > 1) { + t2.CONFG = 2; + t2.Data_ID = DSI_GERNERIC_LONG_PACKET_ID; + t2.WC16 = count + 1; + + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[d]->data[0], + AS_UINT32(&t2)); + + goto_addr = + (unsigned long)(&DSI_CMDQ_REG[d]->data[1].byte0); + mask_para = (0xFFu << ((goto_addr & 0x3u) * 8)); + set_para = (cmd << ((goto_addr & 0x3u) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~((unsigned long)0x3u)), + mask_para, set_para); + + for (i = 0; i < count; i++) { + goto_addr = + (unsigned long)(&DSI_CMDQ_REG[d]->data[1]. + byte1) + i; + mask_para = (0xFFu << ((goto_addr & 0x3u) * 8)); + set_para = + (para_list[i] << ((goto_addr & 0x3u) * 8)); + DSI_MASKREG32(cmdq, + goto_addr & (~((unsigned long)0x3u)), + mask_para, set_para); + } + + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_CMDQ_SIZE, + 2 + (count) / 4); + + } else { + t0.CONFG = 0; + t0.Data0 = cmd; + if (count) { + t0.Data_ID = DSI_GERNERIC_SHORT_PACKET_ID_2; + t0.Data1 = para_list[0]; + } else { + t0.Data_ID = DSI_GERNERIC_SHORT_PACKET_ID_1; + t0.Data1 = 0; + } + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[d]->data[0], + AS_UINT32(&t0)); + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_CMDQ_SIZE, 1); + } + } + if (force_update) { + DSI_Start(module, cmdq); + DSI_WaitForNotBusy(module, cmdq); + } + } + } +} + + +void DSI_set_cmdq_V3(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, LCM_setting_table_V3 *para_tbl, + unsigned int size, unsigned char force_update) +{ + + uint32_t i; + /* UINT32 layer, layer_state, lane_num; */ + unsigned long goto_addr, mask_para, set_para; + /* UINT32 fbPhysAddr, fbVirAddr; */ + DSI_T0_INS t0; + /* DSI_T1_INS t1; */ + DSI_T2_INS t2; + + uint32_t index = 0; + + unsigned char data_id, cmd, count; + unsigned char *para_list; + + uint32_t d; + + memset(&t2, 0, sizeof(t2)); + + for (d = DSI_MODULE_BEGIN(module); d <= DSI_MODULE_END(module); d++) { + do { + data_id = para_tbl[index].id; + cmd = para_tbl[index].cmd; + count = para_tbl[index].count; + para_list = para_tbl[index].para_list; + + if (data_id == REGFLAG_ESCAPE_ID && cmd == REGFLAG_DELAY_MS_V3) { + udelay(1000 * count); + DISPMSG("DISP/DSI " "DSI_set_cmdq_V3[%d]. Delay %d (ms)\n", index, + count); + + continue; + } + if (0 != DSI_REG[d]->DSI_MODE_CTRL.MODE) { /* not in cmd mode */ + DSI_VM_CMD_CON_REG vm_cmdq; + + OUTREG32(&vm_cmdq, AS_UINT32(&DSI_REG[d]->DSI_VM_CMD_CON)); + DISPMSG("set cmdq in VDO mode\n"); + if (count > 1) { + vm_cmdq.LONG_PKT = 1; + vm_cmdq.CM_DATA_ID = data_id; + vm_cmdq.CM_DATA_0 = count + 1; + OUTREG32(&DSI_REG[d]->DSI_VM_CMD_CON, AS_UINT32(&vm_cmdq)); + + goto_addr = + (unsigned long)(&DSI_VM_CMD_REG[d]->data[0].byte0); + mask_para = (0xFF << ((goto_addr & 0x3) * 8)); + set_para = (cmd << ((goto_addr & 0x3) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~0x3), mask_para, set_para); + + for (i = 0; i < count; i++) { + goto_addr = + (unsigned long)(&DSI_VM_CMD_REG[d]->data[0]. + byte1) + i; + mask_para = (0xFF << ((goto_addr & 0x3) * 8)); + set_para = + (para_list[i] << ((goto_addr & 0x3) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~0x3), mask_para, set_para); + } + } else { + vm_cmdq.LONG_PKT = 0; + vm_cmdq.CM_DATA_0 = cmd; + if (count) { + vm_cmdq.CM_DATA_ID = data_id; + vm_cmdq.CM_DATA_1 = para_list[0]; + } else { + vm_cmdq.CM_DATA_ID = data_id; + vm_cmdq.CM_DATA_1 = 0; + } + OUTREG32(&DSI_REG[d]->DSI_VM_CMD_CON, AS_UINT32(&vm_cmdq)); + } + /* start DSI VM CMDQ */ + if (force_update) + DSI_EnableVM_CMD(module, cmdq); + } else { + DSI_WaitForNotBusy(module, cmdq); + + OUTREG32(&DSI_CMDQ_REG[d]->data[0], 0); + + if (count > 1) { + t2.CONFG = 2; + t2.Data_ID = data_id; + t2.WC16 = count + 1; + + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[d]->data[0].byte0, + AS_UINT32(&t2)); + + goto_addr = + (unsigned long)(&DSI_CMDQ_REG[d]->data[1].byte0); + mask_para = (0xFFu << ((goto_addr & 0x3u) * 8)); + set_para = (cmd << ((goto_addr & 0x3u) * 8)); + DSI_MASKREG32(cmdq, goto_addr & (~((unsigned long)0x3u)), + mask_para, set_para); + + for (i = 0; i < count; i++) { + goto_addr = + (unsigned long)(&DSI_CMDQ_REG[d]->data[1]. + byte1) + i; + mask_para = (0xFFu << ((goto_addr & 0x3u) * 8)); + set_para = + (para_list[i] << ((goto_addr & 0x3u) * 8)); + DSI_MASKREG32(cmdq, + goto_addr & (~((unsigned long)0x3u)), + mask_para, set_para); + } + + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_CMDQ_SIZE, + 2 + (count) / 4); + } else { + t0.CONFG = 0; + t0.Data0 = cmd; + if (count) { + t0.Data_ID = data_id; + t0.Data1 = para_list[0]; + } else { + t0.Data_ID = data_id; + t0.Data1 = 0; + } + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[d]->data[0], + AS_UINT32(&t0)); + DSI_OUTREG32(cmdq, &DSI_REG[d]->DSI_CMDQ_SIZE, 1); + } + + if (force_update) { + DSI_Start(module, cmdq); + DSI_WaitForNotBusy(module, cmdq); + } + } + } while (++index < size); + } + +} + +void DSI_set_cmdq(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, unsigned int *pdata, + unsigned int queue_size, unsigned char force_update) +{ + /* DISPFUNC(); */ + + int j = 0; + int i = 0; + + /* DISPMSG("DSI_set_cmdq, module=%s, cmdq=0x%08x\n", ddp_get_module_name(module), cmdq); */ + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (0 != DSI_REG[i]->DSI_MODE_CTRL.MODE) { +#if 0 + /* not in cmd mode */ + DSI_VM_CMD_CON_REG vm_cmdq; + + OUTREG32(&vm_cmdq, AS_UINT32(&DSI_REG[i]->DSI_VM_CMD_CON)); + DISPMSG("set cmdq in VDO mode\n"); + if (queue_size > 1) { /* long packet */ + vm_cmdq.LONG_PKT = 1; + vm_cmdq.CM_DATA_ID = ((pdata[0] >> 8) & 0xFF); + vm_cmdq.CM_DATA_0 = ((pdata[0] >> 16) & 0xFF); + vm_cmdq.CM_DATA_1 = 0; + OUTREG32(&DSI_REG[i]->DSI_VM_CMD_CON, AS_UINT32(&vm_cmdq)); + for (j = 0; j < queue_size - 1; j++) { + OUTREG32(&DSI_VM_CMD_REG->data[j], + AS_UINT32((pdata + j + 1))); + } + } else { + vm_cmdq.LONG_PKT = 0; + vm_cmdq.CM_DATA_ID = ((pdata[0] >> 8) & 0xFF); + vm_cmdq.CM_DATA_0 = ((pdata[0] >> 16) & 0xFF); + vm_cmdq.CM_DATA_1 = ((pdata[0] >> 24) & 0xFF); + OUTREG32(&DSI_REG->DSI_VM_CMD_CON, AS_UINT32(&vm_cmdq)); + } + /* start DSI VM CMDQ */ + if (force_update) { + MMProfileLogEx(MTKFB_MMP_Events.DSICmd, MMProfileFlagStart, + *(unsigned int *)(&DSI_VM_CMD_REG->data[0]), + *(unsigned int *)(&DSI_VM_CMD_REG->data[1])); + DSI_EnableVM_CMD(); + + /* must wait VM CMD done? */ + MMProfileLogEx(MTKFB_MMP_Events.DSICmd, MMProfileFlagEnd, + *(unsigned int *)(&DSI_VM_CMD_REG->data[2]), + *(unsigned int *)(&DSI_VM_CMD_REG->data[3])); + } +#endif + } else { + ASSERT(queue_size <= 32); + DSI_WaitForNotBusy(module, cmdq); +#ifdef ENABLE_DSI_ERROR_REPORT + if ((pdata[0] & 1)) { + memcpy(_dsi_cmd_queue, pdata, queue_size * 4); + _dsi_cmd_queue[queue_size++] = 0x4; + pdata = (unsigned int *)_dsi_cmd_queue; + } else { + pdata[0] |= 4; + } +#endif + for (j = 0; j < queue_size; j++) { + DSI_OUTREG32(cmdq, &DSI_CMDQ_REG[i]->data[j], + AS_UINT32((pdata + j))); + } + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_CMDQ_SIZE, queue_size); + + if (force_update) { + DSI_Start(module, cmdq); + DSI_WaitForNotBusy(module, cmdq); + } + } + } +} + +void _copy_dsi_params(LCM_DSI_PARAMS *src, LCM_DSI_PARAMS *dst) +{ + memcpy((LCM_DSI_PARAMS *) dst, (LCM_DSI_PARAMS *) src, sizeof(LCM_DSI_PARAMS)); +} + +int DSI_Send_ROI(DISP_MODULE_ENUM module, void *handle, unsigned int x, unsigned int y, + unsigned int width, unsigned int height) +{ + unsigned int x0 = x; + unsigned int y0 = y; + unsigned int x1 = x0 + width - 1; + unsigned int y1 = y0 + height - 1; + + unsigned char x0_MSB = ((x0 >> 8) & 0xFF); + unsigned char x0_LSB = (x0 & 0xFF); + unsigned char x1_MSB = ((x1 >> 8) & 0xFF); + unsigned char x1_LSB = (x1 & 0xFF); + unsigned char y0_MSB = ((y0 >> 8) & 0xFF); + unsigned char y0_LSB = (y0 & 0xFF); + unsigned char y1_MSB = ((y1 >> 8) & 0xFF); + unsigned char y1_LSB = (y1 & 0xFF); + + unsigned int data_array[16]; + + data_array[0] = 0x00053902; + data_array[1] = (x1_MSB << 24) | (x0_LSB << 16) | (x0_MSB << 8) | 0x2a; + data_array[2] = (x1_LSB); + DSI_set_cmdq(module, handle, data_array, 3, 1); + data_array[0] = 0x00053902; + data_array[1] = (y1_MSB << 24) | (y0_LSB << 16) | (y0_MSB << 8) | 0x2b; + data_array[2] = (y1_LSB); + DSI_set_cmdq(module, handle, data_array, 3, 1); + DISPDBG("DSI_Send_ROI Done!\n"); + + /* data_array[0]= 0x002c3909; */ + /* DSI_set_cmdq(module, handle, data_array, 1, 0); */ + return 0; +} + + + +static void lcm_set_reset_pin(uint32_t value) +{ +#if 1 + DSI_OUTREG32(NULL, DISPSYS_CONFIG_BASE + 0x150, value); +#else +#if !defined(CONFIG_MTK_LEGACY) + if (value) + disp_dts_gpio_select_state(DTS_GPIO_STATE_LCM_RST_OUT1); + else + disp_dts_gpio_select_state(DTS_GPIO_STATE_LCM_RST_OUT0); +#endif +#endif +} + +static void lcm_udelay(uint32_t us) +{ + udelay(us); +} + +static void lcm_mdelay(uint32_t ms) +{ + if (ms < 10) + udelay(ms * 1000); + else + msleep(ms); +} + +void DSI_set_cmdq_V2_DSI0(void *cmdq, unsigned cmd, unsigned char count, unsigned char *para_list, + unsigned char force_update) +{ + /*cmdqRecHandle cmdq_hd = (cmdqRecHandle) cmdq;*/ + DSI_set_cmdq_V2(DISP_MODULE_DSI0, cmdq, cmd, count, para_list, force_update); +} + +void DSI_set_cmdq_V2_DSI1(void *cmdq, unsigned cmd, unsigned char count, unsigned char *para_list, + unsigned char force_update) +{ + /*cmdqRecHandle cmdq_hd = (cmdqRecHandle) cmdq;*/ + DSI_set_cmdq_V2(DISP_MODULE_DSI1, cmdq, cmd, count, para_list, force_update); +} + +void DSI_set_cmdq_V2_DSIDual(void *cmdq, unsigned cmd, unsigned char count, + unsigned char *para_list, unsigned char force_update) +{ + /*cmdqRecHandle cmdq_hd = (cmdqRecHandle) cmdq;*/ + DSI_set_cmdq_V2(DISP_MODULE_DSIDUAL, cmdq, cmd, count, para_list, force_update); +} + +void DSI_set_cmdq_V2_Wrapper_DSI0(unsigned cmd, unsigned char count, unsigned char *para_list, + unsigned char force_update) +{ + DSI_set_cmdq_V2(DISP_MODULE_DSI0, NULL, cmd, count, para_list, force_update); +} + +void DSI_set_cmdq_V2_Wrapper_DSI1(unsigned cmd, unsigned char count, unsigned char *para_list, + unsigned char force_update) +{ + DSI_set_cmdq_V2(DISP_MODULE_DSI1, NULL, cmd, count, para_list, force_update); +} + +void DSI_set_cmdq_V2_Wrapper_DSIDual(unsigned cmd, unsigned char count, unsigned char *para_list, + unsigned char force_update) +{ + DSI_set_cmdq_V2(DISP_MODULE_DSIDUAL, NULL, cmd, count, para_list, force_update); +} + +void DSI_set_cmdq_V3_Wrapper_DSI0(LCM_setting_table_V3 *para_tbl, unsigned int size, + unsigned char force_update) +{ + DSI_set_cmdq_V3(DISP_MODULE_DSI0, NULL, para_tbl, size, force_update); +} + +void DSI_set_cmdq_V3_Wrapper_DSI1(LCM_setting_table_V3 *para_tbl, unsigned int size, + unsigned char force_update) +{ + DSI_set_cmdq_V3(DISP_MODULE_DSI1, NULL, para_tbl, size, force_update); +} + +void DSI_set_cmdq_V3_Wrapper_DSIDual(LCM_setting_table_V3 *para_tbl, unsigned int size, + unsigned char force_update) +{ + DSI_set_cmdq_V3(DISP_MODULE_DSIDUAL, NULL, para_tbl, size, force_update); +} + +void DSI_set_cmdq_wrapper_DSI0(unsigned int *pdata, unsigned int queue_size, + unsigned char force_update) +{ + DSI_set_cmdq(DISP_MODULE_DSI0, NULL, pdata, queue_size, force_update); +} + +void DSI_set_cmdq_wrapper_DSI1(unsigned int *pdata, unsigned int queue_size, + unsigned char force_update) +{ + DSI_set_cmdq(DISP_MODULE_DSI1, NULL, pdata, queue_size, force_update); +} + +void DSI_set_cmdq_wrapper_DSIDual(unsigned int *pdata, unsigned int queue_size, + unsigned char force_update) +{ + DSI_set_cmdq(DISP_MODULE_DSIDUAL, NULL, pdata, queue_size, force_update); +} + +unsigned int DSI_dcs_read_lcm_reg_v2_wrapper_DSI0(uint8_t cmd, uint8_t *buffer, uint8_t buffer_size) +{ + return DSI_dcs_read_lcm_reg_v2(DISP_MODULE_DSI0, NULL, cmd, buffer, buffer_size); +} + +unsigned int DSI_dcs_read_lcm_reg_v2_wrapper_DSI1(uint8_t cmd, uint8_t *buffer, uint8_t buffer_size) +{ + return DSI_dcs_read_lcm_reg_v2(DISP_MODULE_DSI1, NULL, cmd, buffer, buffer_size); +} + +unsigned int DSI_dcs_read_lcm_reg_v2_wrapper_DSIDUAL(uint8_t cmd, uint8_t *buffer, uint8_t buffer_size) +{ + return DSI_dcs_read_lcm_reg_v2(DISP_MODULE_DSIDUAL, NULL, cmd, buffer, buffer_size); +} + +long lcd_enp_bias_setting(unsigned int value) +{ + long ret = 0; + +#if !defined(CONFIG_MTK_LEGACY) + if (value) + ret = disp_dts_gpio_select_state(DTS_GPIO_STATE_LCD_BIAS_ENP); + else + ret = disp_dts_gpio_select_state(DTS_GPIO_STATE_LCD_BIAS_ENN); +#endif + return ret; +} +int ddp_dsi_set_lcm_utils(DISP_MODULE_ENUM module, LCM_DRIVER *lcm_drv) +{ + LCM_UTIL_FUNCS *utils = NULL; + + if (lcm_drv == NULL) { + DISPERR("lcm_drv is null\n"); + return -1; + } + + if (module == DISP_MODULE_DSI0) { + utils = (LCM_UTIL_FUNCS *)&lcm_utils_dsi0; + } else { + DISPERR("wrong module: %d\n", module); + return -1; + } + + utils->set_reset_pin = lcm_set_reset_pin; + utils->udelay = lcm_udelay; + utils->mdelay = lcm_mdelay; + if (module == DISP_MODULE_DSI0) { + utils->dsi_set_cmdq = DSI_set_cmdq_wrapper_DSI0; + utils->dsi_set_cmdq_V2 = DSI_set_cmdq_V2_Wrapper_DSI0; + utils->dsi_set_cmdq_V3 = DSI_set_cmdq_V3_Wrapper_DSI0; + utils->dsi_dcs_read_lcm_reg_v2 = DSI_dcs_read_lcm_reg_v2_wrapper_DSI0; + utils->dsi_set_cmdq_V22 = DSI_set_cmdq_V2_DSI0; + } +#ifndef CONFIG_FPGA_EARLY_PORTING +#ifdef CONFIG_MTK_LEGACY + utils->set_gpio_out = mt_set_gpio_out; + utils->set_gpio_mode = mt_set_gpio_mode; + utils->set_gpio_dir = mt_set_gpio_dir; + utils->set_gpio_pull_enable = (int (*)(unsigned int, unsigned char))mt_set_gpio_pull_enable; +#else + utils->set_gpio_lcd_enp_bias = lcd_enp_bias_setting; +#endif +#endif + + lcm_drv->set_util_funcs(utils); + + return 0; +} + +void DSI_ChangeClk(DISP_MODULE_ENUM module, uint32_t clk) +{ + int i = 0; + + if (clk > 1250 || clk < 50) + return; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + LCM_DSI_PARAMS *dsi_params = &_dsi_context[i].dsi_params; + + dsi_params->PLL_CLOCK = clk; + DSI_WaitForNotBusy(module, NULL); + DSI_PHY_clk_setting(module, NULL, dsi_params); + DSI_PHY_TIMCONFIG(module, NULL, dsi_params); + } +} + +int ddp_dsi_init(DISP_MODULE_ENUM module, void *cmdq) +{ + DSI_STATUS ret = DSI_STATUS_OK; + int i = 0; + + DISPFUNC(); + /* DSI_OUTREG32(cmdq, 0xf0000048, 0x80000000); */ + /* DSI_OUTREG32(cmdq, MMSYS_CONFIG_BASE+0x108, 0xffffffff); */ + /* DSI_OUTREG32(cmdq, MMSYS_CONFIG_BASE+0x118, 0xffffffff); */ + /* DSI_OUTREG32(MMSYS_CONFIG_BASE+0xC08, 0xffffffff); */ +#ifdef ENABLE_CLK_MGR +#ifndef CONFIG_MTK_CLKMGR + ddp_parse_apmixed_base(); +#endif +#endif + DSI_REG[0] = (DSI_REGS *) DISPSYS_DSI0_BASE; + DSI_PHY_REG[0] = (DSI_PHY_REGS *) MIPITX_BASE; + DSI_CMDQ_REG[0] = (DSI_CMDQ_REGS *) (DISPSYS_DSI0_BASE + 0x200); + DSI_REG[1] = (DSI_REGS *) DISPSYS_DSI0_BASE; + DSI_PHY_REG[1] = (DSI_PHY_REGS *) MIPITX_BASE; + DSI_CMDQ_REG[1] = (DSI_CMDQ_REGS *) (DISPSYS_DSI0_BASE + 0x200); + DSI_VM_CMD_REG[0] = (DSI_VM_CMDQ_REGS *) (DISPSYS_DSI0_BASE + 0x134); + DSI_VM_CMD_REG[1] = (DSI_VM_CMDQ_REGS *) (DISPSYS_DSI0_BASE + 0x134); + memset(&_dsi_context, 0, sizeof(_dsi_context)); + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + init_waitqueue_head(&_dsi_cmd_done_wait_queue[i]); + init_waitqueue_head(&_dsi_dcs_read_wait_queue[i]); + init_waitqueue_head(&_dsi_wait_bta_te[i]); + init_waitqueue_head(&_dsi_wait_ext_te[i]); + init_waitqueue_head(&_dsi_wait_vm_done_queue[i]); + init_waitqueue_head(&_dsi_wait_vm_cmd_done_queue[i]); + init_waitqueue_head(&_dsi_wait_sleep_out_done_queue[i]); + DISPMSG("dsi%d initializing\n", i); + } + + disp_register_module_irq_callback(DISP_MODULE_DSI0, _DSI_INTERNAL_IRQ_Handler); + +#ifndef CONFIG_FPGA_EARLY_PORTING + if (MIPITX_IsEnabled(module, cmdq)) { + s_isDsiPowerOn = true; +#ifdef ENABLE_CLK_MGR +#ifdef CONFIG_MTK_CLKMGR + set_mipi26m(1); +#else + ddp_set_mipi26m(1); +#endif + if (module == DISP_MODULE_DSI0) { +#ifdef CONFIG_MTK_CLKMGR + ret += enable_clock(MT_CG_DISP1_DSI_ENGINE, "DSI"); + ret += enable_clock(MT_CG_DISP1_DSI_DIGITAL, "DSI"); +#else + ret += ddp_clk_enable(DISP1_DSI_ENGINE); + ret += ddp_clk_enable(DISP1_DSI_DIGITAL); +#endif + if (ret > 0) + DISPMSG("DSI0 power manager API return false\n"); + } +#endif + DSI_OUTREGBIT(NULL, DSI_INT_ENABLE_REG, DSI_REG[0]->DSI_INTEN, CMD_DONE, 1); + DSI_OUTREGBIT(NULL, DSI_INT_ENABLE_REG, DSI_REG[0]->DSI_INTEN, RD_RDY, 1); + DSI_OUTREGBIT(NULL, DSI_INT_ENABLE_REG, DSI_REG[0]->DSI_INTEN, VM_DONE, 1); + /* enable te_rdy when need, not here (both cmd mode & vdo mode) */ + /* DSI_OUTREGBIT(NULL, DSI_INT_ENABLE_REG,DSI_REG[0]->DSI_INTEN,TE_RDY,1); */ + DSI_OUTREGBIT(NULL, DSI_INT_ENABLE_REG, DSI_REG[0]->DSI_INTEN, VM_CMD_DONE, 1); + DSI_OUTREGBIT(NULL, DSI_INT_ENABLE_REG, DSI_REG[0]->DSI_INTEN, SLEEPOUT_DONE, 1); + /* DSI_OUTREGBIT(NULL, DSI_INT_ENABLE_REG,DSI_REG[0]->DSI_INTEN,FRAME_DONE_INT_EN,0); */ + DSI_BackupRegisters(module, NULL); + clock_lane = (INREG32(MIPI_TX_REG_BASE + 0x4));/*MIPITX_DSI_CLOCK_LANE*/ + data_lane3 = (INREG32(MIPI_TX_REG_BASE + 0x14));/*MIPITX_DSI_DATA_LANE3*/ + data_lane2 = (INREG32(MIPI_TX_REG_BASE + 0x10));/*MIPITX_DSI_DATA_LANE2*/ + data_lane1 = (INREG32(MIPI_TX_REG_BASE + 0xc));/*MIPITX_DSI_DATA_LANE1*/ + data_lane0 = (INREG32(MIPI_TX_REG_BASE + 0x8));/*MIPITX_DSI_DATA_LANE0*/ + DISPMSG("clk=0x%x,lan3=0x%x,lan2=0x%x,lan1=0x%x,lan0=0x%x\n", + clock_lane, data_lane3, data_lane2, data_lane1, data_lane0); + } +#endif + + return DSI_STATUS_OK; +} + +int ddp_dsi_deinit(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + return 0; +} + +void _dump_dsi_params(LCM_DSI_PARAMS *dsi_config) +{ + + if (dsi_config) { + switch (dsi_config->mode) { + case CMD_MODE: + DISPDBG("[DDPDSI] DSI Mode: CMD_MODE\n"); + break; + case SYNC_PULSE_VDO_MODE: + DISPDBG("[DDPDSI] DSI Mode: SYNC_PULSE_VDO_MODE\n"); + break; + case SYNC_EVENT_VDO_MODE: + DISPDBG("[DDPDSI] DSI Mode: SYNC_EVENT_VDO_MODE\n"); + break; + case BURST_VDO_MODE: + DISPDBG("[DDPDSI] DSI Mode: BURST_VDO_MODE\n"); + break; + default: + DISPMSG("[DDPDSI] DSI Mode: Unknown\n"); + break; + } + + DISPDBG + ("[DDPDSI] vact: %d, vbp: %d, vfp: %d, vact_line: %d, hact: %d, hbp: %d, hfp: %d, hblank: %d\n", + dsi_config->vertical_sync_active, dsi_config->vertical_backporch, + dsi_config->vertical_frontporch, dsi_config->vertical_active_line, + dsi_config->horizontal_sync_active, dsi_config->horizontal_backporch, + dsi_config->horizontal_frontporch, dsi_config->horizontal_blanking_pixel); + DISPDBG + ("[DDPDSI] pll_select: %d, pll_div1: %d, pll_div2: %d, fbk_div: %d,fbk_sel: %d, rg_bir: %d\n", + dsi_config->pll_select, dsi_config->pll_div1, dsi_config->pll_div2, + dsi_config->fbk_div, dsi_config->fbk_sel, dsi_config->rg_bir); + DISPDBG("[DDPDSI] rg_bic: %d, rg_bp: %d, PLL_CLOCK: %d, dsi_clock: %d, ssc_range: %d\n", + dsi_config->rg_bic, dsi_config->rg_bp, dsi_config->PLL_CLOCK, + dsi_config->dsi_clock, dsi_config->ssc_range); + + DISPDBG("[DDPDSI] ssc_disable: %d, compatibility_for_nvk: %d, cont_clock: %d\n", + dsi_config->ssc_disable, dsi_config->compatibility_for_nvk, dsi_config->cont_clock); + + DISPDBG + ("[DDPDSI] lcm_ext_te_enable: %d, noncont_clock: %d, noncont_clock_period: %d\n", + dsi_config->lcm_ext_te_enable, dsi_config->noncont_clock, + dsi_config->noncont_clock_period); + } +} + +static void DSI_PHY_CLK_LP_PerLine_config(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, + LCM_DSI_PARAMS *dsi_params) +{ + int i; + DSI_PHY_TIMCON0_REG timcon0; /* LPX */ + DSI_PHY_TIMCON2_REG timcon2; /* CLK_HS_TRAIL, CLK_HS_ZERO */ + DSI_PHY_TIMCON3_REG timcon3; /* CLK_HS_EXIT, CLK_HS_POST, CLK_HS_PREP */ + DSI_HSA_WC_REG hsa; + DSI_HBP_WC_REG hbp; + DSI_HFP_WC_REG hfp, new_hfp; + DSI_BLLP_WC_REG bllp; + DSI_PSCTRL_REG ps; + uint32_t hstx_ckl_wc, new_hstx_ckl_wc; + uint32_t v_a, v_b, v_c, lane_num; + LCM_DSI_MODE_CON dsi_mode; + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + lane_num = dsi_params->LANE_NUM; + dsi_mode = dsi_params->mode; + + if (dsi_mode == CMD_MODE) + continue; + /* vdo mode */ + DSI_OUTREG32(cmdq, &hsa, AS_UINT32(&DSI_REG[i]->DSI_HSA_WC)); + DSI_OUTREG32(cmdq, &hbp, AS_UINT32(&DSI_REG[i]->DSI_HBP_WC)); + DSI_OUTREG32(cmdq, &hfp, AS_UINT32(&DSI_REG[i]->DSI_HFP_WC)); + DSI_OUTREG32(cmdq, &bllp, AS_UINT32(&DSI_REG[i]->DSI_BLLP_WC)); + DSI_OUTREG32(cmdq, &ps, AS_UINT32(&DSI_REG[i]->DSI_PSCTRL)); + DSI_OUTREG32(cmdq, &hstx_ckl_wc, AS_UINT32(&DSI_REG[i]->DSI_HSTX_CKL_WC)); + DSI_OUTREG32(cmdq, &timcon0, AS_UINT32(&DSI_REG[i]->DSI_PHY_TIMECON0)); + DSI_OUTREG32(cmdq, &timcon2, AS_UINT32(&DSI_REG[i]->DSI_PHY_TIMECON2)); + DSI_OUTREG32(cmdq, &timcon3, AS_UINT32(&DSI_REG[i]->DSI_PHY_TIMECON3)); + + /* 1. sync_pulse_mode */ + /* Total WC(A) = HSA_WC + HBP_WC + HFP_WC + PS_WC + 32 */ + /* CLK init WC(B) = (CLK_HS_EXIT + LPX + CLK_HS_PREP + CLK_HS_ZERO)*lane_num */ + /* CLK end WC(C) = (CLK_HS_POST + CLK_HS_TRAIL)*lane_num */ + /* HSTX_CKLP_WC = A - B */ + /* Limitation: B + C < HFP_WC */ + if (dsi_mode == SYNC_PULSE_VDO_MODE) { + v_a = hsa.HSA_WC + hbp.HBP_WC + hfp.HFP_WC + ps.DSI_PS_WC + 32; + v_b = + (timcon3.CLK_HS_EXIT + timcon0.LPX + timcon3.CLK_HS_PRPR + + timcon2.CLK_ZERO) * lane_num; + v_c = (timcon3.CLK_HS_POST + timcon2.CLK_TRAIL) * lane_num; + + DISPMSG("===>v_a-v_b=0x%x,HSTX_CKLP_WC=0x%x\n", (v_a - v_b), hstx_ckl_wc); +/* DISPMSG("===>v_b+v_c=0x%x,HFP_WC=0x%x\n",(v_b+v_c),hfp); */ + DISPMSG("===>Will Reconfig in order to fulfill LP clock lane per line\n"); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HFP_WC, (v_b + v_c + DIFF_CLK_LANE_LP)); + DSI_OUTREG32(cmdq, &new_hfp, AS_UINT32(&DSI_REG[i]->DSI_HFP_WC)); + v_a = hsa.HSA_WC + hbp.HBP_WC + new_hfp.HFP_WC + ps.DSI_PS_WC + 32; + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HSTX_CKL_WC, (v_a - v_b)); + DSI_OUTREG32(cmdq, &new_hstx_ckl_wc, + AS_UINT32(&DSI_REG[i]->DSI_HSTX_CKL_WC)); + DISPMSG("===>new HSTX_CKL_WC=0x%x, HFP_WC=0x%x\n", new_hstx_ckl_wc, + new_hfp.HFP_WC); + } + /* 2. sync_event_mode */ + /* Total WC(A) = HBP_WC + HFP_WC + PS_WC + 26 */ + /* CLK init WC(B) = (CLK_HS_EXIT + LPX + CLK_HS_PREP + CLK_HS_ZERO)*lane_num */ + /* CLK end WC(C) = (CLK_HS_POST + CLK_HS_TRAIL)*lane_num */ + /* HSTX_CKLP_WC = A - B */ + /* Limitation: B + C < HFP_WC */ + else if (dsi_mode == SYNC_EVENT_VDO_MODE) { + v_a = hbp.HBP_WC + hfp.HFP_WC + ps.DSI_PS_WC + 26; + v_b = + (timcon3.CLK_HS_EXIT + timcon0.LPX + timcon3.CLK_HS_PRPR + + timcon2.CLK_ZERO) * lane_num; + v_c = (timcon3.CLK_HS_POST + timcon2.CLK_TRAIL) * lane_num; + + DISPMSG("===>v_a-v_b=0x%x,HSTX_CKLP_WC=0x%x\n", (v_a - v_b), hstx_ckl_wc); +/* DISPMSG("===>v_b+v_c=0x%x,HFP_WC=0x%x\n",(v_b+v_c),hfp); */ + DISPMSG("===>Will Reconfig in order to fulfill LP clock lane per line\n"); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HFP_WC, (v_b + v_c + DIFF_CLK_LANE_LP)); + DSI_OUTREG32(cmdq, &new_hfp, AS_UINT32(&DSI_REG[i]->DSI_HFP_WC)); + v_a = hbp.HBP_WC + new_hfp.HFP_WC + ps.DSI_PS_WC + 26; + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HSTX_CKL_WC, (v_a - v_b)); + DSI_OUTREG32(cmdq, &new_hstx_ckl_wc, + AS_UINT32(&DSI_REG[i]->DSI_HSTX_CKL_WC)); + DISPMSG("===>new HSTX_CKL_WC=0x%x, HFP_WC=0x%x\n", new_hstx_ckl_wc, + new_hfp.HFP_WC); + + } + /* 3. burst_mode */ + /* Total WC(A) = HBP_WC + HFP_WC + PS_WC + BLLP_WC + 32 */ + /* CLK init WC(B) = (CLK_HS_EXIT + LPX + CLK_HS_PREP + CLK_HS_ZERO)*lane_num */ + /* CLK end WC(C) = (CLK_HS_POST + CLK_HS_TRAIL)*lane_num */ + /* HSTX_CKLP_WC = A - B */ + /* Limitation: B + C < HFP_WC */ + else if (dsi_mode == BURST_VDO_MODE) { + v_a = hbp.HBP_WC + hfp.HFP_WC + ps.DSI_PS_WC + bllp.BLLP_WC + 32; + v_b = + (timcon3.CLK_HS_EXIT + timcon0.LPX + timcon3.CLK_HS_PRPR + + timcon2.CLK_ZERO) * lane_num; + v_c = (timcon3.CLK_HS_POST + timcon2.CLK_TRAIL) * lane_num; + + DISPMSG("===>v_a-v_b=0x%x,HSTX_CKLP_WC=0x%x\n", (v_a - v_b), hstx_ckl_wc); + /* DISPMSG("===>v_b+v_c=0x%x,HFP_WC=0x%x\n",(v_b+v_c),hfp); */ + DISPMSG("===>Will Reconfig in order to fulfill LP clock lane per line\n"); + + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HFP_WC, (v_b + v_c + DIFF_CLK_LANE_LP)); + DSI_OUTREG32(cmdq, &new_hfp, AS_UINT32(&DSI_REG[i]->DSI_HFP_WC)); + v_a = hbp.HBP_WC + new_hfp.HFP_WC + ps.DSI_PS_WC + bllp.BLLP_WC + 32; + DSI_OUTREG32(cmdq, &DSI_REG[i]->DSI_HSTX_CKL_WC, (v_a - v_b)); + DSI_OUTREG32(cmdq, &new_hstx_ckl_wc, + AS_UINT32(&DSI_REG[i]->DSI_HSTX_CKL_WC)); + DISPMSG("===>new HSTX_CKL_WC=0x%x, HFP_WC=0x%x\n", new_hstx_ckl_wc, + new_hfp.HFP_WC); + } + } + +} + +int ddp_dsi_config(DISP_MODULE_ENUM module, disp_ddp_path_config *config, void *cmdq) +{ + int i = 0; + LCM_DSI_PARAMS *dsi_config = &(config->dispif_config.dsi); + + if (!config->dst_dirty) { + if (atomic_read(&PMaster_enable) == 0) + return 0; + } + DISPFUNC(); + DISPDBG("===>run here 00 Pmaster: clk:%d\n", _dsi_context[0].dsi_params.PLL_CLOCK); + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + _copy_dsi_params(dsi_config, &(_dsi_context[i].dsi_params)); + _dsi_context[i].lcm_width = config->dst_w; + _dsi_context[i].lcm_height = config->dst_h; + _dump_dsi_params(&(_dsi_context[i].dsi_params)); + if (dsi_config->mode != CMD_MODE) { + /* not enable TE in vdo mode */ + if (dsi_config->eint_disable == 1) { + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, DSI_REG[i]->DSI_INTEN, + TE_RDY, 1); + DISPDBG("DSI VDO Mode TEINT On\n"); + } else { + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, DSI_REG[i]->DSI_INTEN, + TE_RDY, 0); + } + } else { + /*enable TE in cmd mode */ + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, DSI_REG[i]->DSI_INTEN, TE_RDY, 1); + } + } + DISPDBG("===>01Pmaster: clk:%d\n", _dsi_context[0].dsi_params.PLL_CLOCK); + if (dsi_config->mode != CMD_MODE) + dsi_currect_mode = 1; +#ifndef CONFIG_FPGA_EARLY_PORTING + if ((MIPITX_IsEnabled(module, cmdq)) && (atomic_read(&PMaster_enable) == 0)) { + DISPDBG("mipitx is already init\n"); + if (dsi_force_config) + goto force_config; + else + goto done; + } else +#endif + { + DISPMSG("MIPITX is not inited, will config mipitx clock now\n"); + DISPMSG("===>Pmaster:CLK SETTING??==> clk:%d\n", + _dsi_context[0].dsi_params.PLL_CLOCK); + DSI_PHY_clk_setting(module, NULL, dsi_config); + } + +force_config: + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + if (dsi_config->mode == CMD_MODE + || ((dsi_config->switch_mode_enable == 1) + && (dsi_config->switch_mode == CMD_MODE)) + || (dsi_config->mode != CMD_MODE && dsi_config->eint_disable)) + DSI_OUTREGBIT(cmdq, DSI_INT_ENABLE_REG, DSI_REG[i]->DSI_INTEN, TE_RDY, 1); + } + /* DSI_Reset(module, cmdq_handle); */ + DSI_TXRX_Control(module, cmdq, dsi_config); + DSI_PS_Control(module, cmdq, dsi_config, config->dst_w, config->dst_h); + DSI_PHY_TIMCONFIG(module, cmdq, dsi_config); + + if (dsi_config->mode != CMD_MODE + || ((dsi_config->switch_mode_enable == 1) && (dsi_config->switch_mode != CMD_MODE))) { + DSI_Config_VDO_Timing(module, cmdq, dsi_config); + DSI_Set_VM_CMD(module, cmdq); + } + /* Enable clk low power per Line ; */ + if (dsi_config->clk_lp_per_line_enable) + DSI_PHY_CLK_LP_PerLine_config(module, cmdq, dsi_config); + + +done: + + return 0; +} + +int ddp_dsi_start(DISP_MODULE_ENUM module, void *cmdq) +{ + + int i = 0; + int g_lcm_x = disp_helper_get_option(DISP_OPT_FAKE_LCM_X); + int g_lcm_y = disp_helper_get_option(DISP_OPT_FAKE_LCM_Y); + + DISPFUNC(); + if (module == DISP_MODULE_DSI0) { + DSI_Send_ROI(module, cmdq, g_lcm_x, g_lcm_y, _dsi_context[i].lcm_width, + _dsi_context[i].lcm_height); + DSI_SetMode(module, cmdq, _dsi_context[i].dsi_params.mode); + DSI_clk_HS_mode(module, cmdq, true); + } + + return 0; +} + +int ddp_dsi_stop(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + int i = 0; + unsigned int tmp = 0; + + DISPFUNC(); + /* ths caller should call wait_event_or_idle for frame stop event then. */ + /* DSI_SetMode(module, cmdq_handle, CMD_MODE); */ + + if (_dsi_is_video_mode(module)) { + DISPMSG("dsi is video mode\n"); + DSI_SetMode(module, cmdq_handle, CMD_MODE); + + i = DSI_MODULE_BEGIN(module); + while (1) { + tmp = INREG32(&DSI_REG[i]->DSI_INTSTA); + if (!(tmp & 0x80000000)) + break; + } + + i = DSI_MODULE_END(module); + while (1) { + DISPMSG("dsi%d is busy\n", i); + tmp = INREG32(&DSI_REG[i]->DSI_INTSTA); + if (!(tmp & 0x80000000)) + break; + } + + } else { + DISPMSG("dsi is cmd mode\n"); + /* TODO: modify this with wait event */ + DSI_WaitForNotBusy(module, cmdq_handle); + } + DSI_clk_HS_mode(module, cmdq_handle, false); + return 0; +} + +/*TUI will use the api*/ +int dsi_enable_irq(DISP_MODULE_ENUM module, void *handle, unsigned int enable) +{ + if (module == DISP_MODULE_DSI0) + DSI_OUTREGBIT(handle, DSI_INT_ENABLE_REG, DSI_REG[0]->DSI_INTEN, FRAME_DONE_INT_EN, enable); + + return 0; +} + + +int ddp_dsi_switch_lcm_mode(DISP_MODULE_ENUM module, void *params) +{ + int i = 0; + LCM_DSI_MODE_SWITCH_CMD lcm_cmd = *((LCM_DSI_MODE_SWITCH_CMD *) (params)); + int mode = (int)(lcm_cmd.mode); + + if (dsi_currect_mode == mode) { + DISPMSG + ("[ddp_dsi_switch_mode] not need switch mode, current mode = %d, switch to %d\n", + dsi_currect_mode, mode); + return 0; + } + if (lcm_cmd.cmd_if == (unsigned int)LCM_INTERFACE_DSI0) + i = 0; + else if (lcm_cmd.cmd_if == (unsigned int)LCM_INTERFACE_DSI1) + i = 1; + else { + DISPMSG("dsi switch not support this cmd IF:%d\n", lcm_cmd.cmd_if); + return -1; + } + + if (mode == 0) { /* V2C */ + DSI_OUTREG32(NULL, (unsigned long)(DSI_REG[i]) + 0x130, + 0x00001521 | (lcm_cmd.addr << 16) | (lcm_cmd.val[0] << 24)); /* RM = 1 */ + DSI_OUTREGBIT(NULL, DSI_START_REG, DSI_REG[i]->DSI_START, VM_CMD_START, 0); + DSI_OUTREGBIT(NULL, DSI_START_REG, DSI_REG[i]->DSI_START, VM_CMD_START, 1); + wait_vm_cmd_done = false; + wait_event_interruptible(_dsi_wait_vm_cmd_done_queue[i], wait_vm_cmd_done); + } + return 0; +} + +int ddp_dsi_switch_mode(DISP_MODULE_ENUM module, void *cmdq_handle, void *params) +{ + int i = 0; + LCM_DSI_MODE_SWITCH_CMD lcm_cmd = *((LCM_DSI_MODE_SWITCH_CMD *) (params)); + int mode = (int)(lcm_cmd.mode); + + if (dsi_currect_mode == mode) { + DISPMSG + ("[ddp_dsi_switch_mode] not need switch mode, current mode = %d, switch to %d\n", + dsi_currect_mode, mode); + return 0; + } + if (lcm_cmd.cmd_if == (unsigned int)LCM_INTERFACE_DSI0) + i = 0; + else if (lcm_cmd.cmd_if == (unsigned int)LCM_INTERFACE_DSI1) + i = 1; + else { + DISPMSG("dsi switch not support this cmd IF:%d\n", lcm_cmd.cmd_if); + return -1; + } + + if (mode == 0) { /* V2C */ + + DSI_SetSwitchMode(module, cmdq_handle, 0); /* */ + DSI_OUTREG32(cmdq_handle, (unsigned long)(DSI_REG[i]) + 0x130, + 0x00001539 | (lcm_cmd.addr << 16) | (lcm_cmd.val[1] << 24)); /* DM = 0 */ + DSI_OUTREGBIT(cmdq_handle, DSI_START_REG, DSI_REG[i]->DSI_START, VM_CMD_START, 0); + DSI_OUTREGBIT(cmdq_handle, DSI_START_REG, DSI_REG[i]->DSI_START, VM_CMD_START, 1); + DSI_MASKREG32(cmdq_handle, 0xF4020028, 0x1, 0x1); /* reset mutex for V2C */ + DSI_MASKREG32(cmdq_handle, 0xF4020028, 0x1, 0x0); /* */ + DSI_MASKREG32(cmdq_handle, 0xF4020030, 0x1, 0x0); /* mutext to cmd mode */ + cmdqRecFlush(cmdq_handle); + cmdqRecReset(cmdq_handle); + cmdqRecWaitNoClear(cmdq_handle, CMDQ_SYNC_TOKEN_STREAM_EOF); + DSI_SetMode(module, NULL, 0); + } else { /* C2V */ + + DSI_SetMode(module, cmdq_handle, mode); + DSI_SetSwitchMode(module, cmdq_handle, 1); /* EXT TE could not use C2V */ + DSI_MASKREG32(cmdq_handle, 0xF4020030, 0x1, 0x1); /* mutext to video mode */ + DSI_OUTREG32(cmdq_handle, (unsigned long)(DSI_REG[i]) + 0x200 + 0, + 0x00001500 | (lcm_cmd.addr << 16) | (lcm_cmd.val[0] << 24)); + DSI_OUTREG32(cmdq_handle, (unsigned long)(DSI_REG[i]) + 0x200 + 4, 0x00000020); + DSI_OUTREG32(cmdq_handle, (unsigned long)(DSI_REG[i]) + 0x60, 2); + DSI_Start(module, cmdq_handle); /* ???????????????????????????????? */ + DSI_MASKREG32(NULL, 0xF4020020, 0x1, 0x1); /* release mutex for video mode */ + cmdqRecFlush(cmdq_handle); + cmdqRecReset(cmdq_handle); + cmdqRecWaitNoClear(cmdq_handle, CMDQ_SYNC_TOKEN_STREAM_EOF); + } + dsi_currect_mode = mode; + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) + _dsi_context[i].dsi_params.mode = mode; + return 0; +} + +int ddp_dsi_clk_on(DISP_MODULE_ENUM module, void *cmdq_handle, unsigned int level) +{ + int ret = 0; + return ret; +} + +int ddp_dsi_clk_off(DISP_MODULE_ENUM module, void *cmdq_handle, unsigned int level) +{ + int ret = 0; + + return ret; +} + +int ddp_dsi_ioctl(DISP_MODULE_ENUM module, void *cmdq_handle, DDP_IOCTL_NAME ioctl_cmd, + void *params) +{ + int ret = 0; + /* DISPFUNC(); */ + DDP_IOCTL_NAME ioctl = (DDP_IOCTL_NAME) ioctl_cmd; + /* DISPMSG("[ddp_dsi_ioctl] index = %d\n", ioctl); */ + switch (ioctl) { + case DDP_STOP_VIDEO_MODE: + { + /* ths caller should call wait_event_or_idle for frame stop event then. */ + DSI_SetMode(module, cmdq_handle, CMD_MODE); + /* TODO: modify this with wait event */ + + if (0 != DSI_WaitVMDone(module)) + ret = -1; + if (module == DISP_MODULE_DSIDUAL) { + DSI_OUTREGBIT(cmdq_handle, DSI_COM_CTRL_REG, + DSI_REG[0]->DSI_COM_CTRL, DSI_DUAL_EN, 0); + DSI_OUTREGBIT(cmdq_handle, DSI_COM_CTRL_REG, + DSI_REG[1]->DSI_COM_CTRL, DSI_DUAL_EN, 0); + DSI_OUTREGBIT(cmdq_handle, DSI_START_REG, DSI_REG[0]->DSI_START, + DSI_START, 0); + DSI_OUTREGBIT(cmdq_handle, DSI_START_REG, DSI_REG[1]->DSI_START, + DSI_START, 0); + } + break; + } + + case DDP_SWITCH_DSI_MODE: + { + ret = ddp_dsi_switch_mode(module, cmdq_handle, params); + break; + } + case DDP_SWITCH_LCM_MODE: + { + ret = ddp_dsi_switch_lcm_mode(module, params); + break; + } + case DDP_BACK_LIGHT: + { + unsigned int cmd = 0x51; + unsigned int count = 1; + unsigned int *p = (unsigned int *)params; + unsigned int level = p[0]; + + DISPMSG("[ddp_dsi_ioctl] level = %d\n", level); + DSI_set_cmdq_V2(module, cmdq_handle, cmd, count, ((unsigned char *)&level), 1); + break; + } + case DDP_DSI_IDLE_CLK_CLOSED: + break; + case DDP_DSI_IDLE_CLK_OPEN: + break; + case DDP_DSI_PORCH_CHANGE: + { + unsigned int *p = (unsigned int *)params; + unsigned int vfp = p[0]; + + ddp_dsi_porch_setting(module, + cmdq_handle, DSI_VFP , vfp); + break; + } + case DDP_PHY_CLK_CHANGE: + { + LCM_DSI_PARAMS *dsi_params = &_dsi_context[0].dsi_params; + unsigned int *p = (unsigned int *)params; + + dsi_params->PLL_CLOCK = *p; + /*DSI_WaitForNotBusy(module, cmdq_handle);*/ + DSI_PHY_clk_change(module, cmdq_handle, dsi_params); + DSI_PHY_TIMCONFIG(module, cmdq_handle, dsi_params); + break; + } + default: + break; + } + return ret; +} + +int ddp_dsi_trigger(DISP_MODULE_ENUM module, void *cmdq) +{ + int i = 0; + unsigned int data_array[16]; + + if (_dsi_context[i].dsi_params.mode == CMD_MODE) { + data_array[0] = 0x002c3909; + DSI_set_cmdq(module, cmdq, data_array, 1, 0); + } + DSI_Start(module, cmdq); + + return 0; +} + +int ddp_dsi_reset(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + DSI_Reset(module, cmdq_handle); + + return 0; +} + + +int ddp_dsi_power_on(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + + int ret = 0; + + DISPFUNC(); + + /* DSI_DumpRegisters(module,1); */ + if (!s_isDsiPowerOn) { +#ifdef ENABLE_CLK_MGR +#ifdef CONFIG_MTK_CLKMGR + set_mipi26m(1); +#else + ddp_set_mipi26m(1); +#endif + if (is_ipoh_bootup) { + if (module == DISP_MODULE_DSI0 || module == DISP_MODULE_DSIDUAL) { +#ifdef CONFIG_MTK_CLKMGR + ret += enable_clock(MT_CG_DISP1_DSI_ENGINE, "DSI"); + ret += enable_clock(MT_CG_DISP1_DSI_DIGITAL, "DSI"); +#else + ret += ddp_clk_enable(DISP1_DSI_ENGINE); + ret += ddp_clk_enable(DISP1_DSI_DIGITAL); +#endif + if (ret > 0) + pr_warn("DISP/DSI " "DSI power manager API return FALSE\n"); + } + s_isDsiPowerOn = true; + DISPMSG("ipoh dsi power on return\n"); + return DSI_STATUS_OK; + } + DSI_PHY_clk_switch(module, NULL, true); + if (module == DISP_MODULE_DSI0 || module == DISP_MODULE_DSIDUAL) { +#ifdef CONFIG_MTK_CLKMGR + ret += enable_clock(MT_CG_DISP1_DSI_ENGINE, "DSI"); + ret += enable_clock(MT_CG_DISP1_DSI_DIGITAL, "DSI"); +#else + ret += ddp_clk_enable(DISP1_DSI_ENGINE); + ret += ddp_clk_enable(DISP1_DSI_DIGITAL); +#endif + if (ret > 0) + DISPMSG("DSI power manager API return false\n"); + } + /* restore dsi register */ + DSI_RestoreRegisters(module, NULL); + + /* enable sleep-out mode */ + DSI_SleepOut(module, NULL); + + /* restore lane_num */ + { + DSI_REGS *regs = NULL; + + regs = &(_dsi_context[0].regBackup); + DSI_OUTREG32(NULL, &DSI_REG[0]->DSI_TXRX_CTRL, + AS_UINT32(®s->DSI_TXRX_CTRL)); + } + /* enter wakeup */ + DSI_Wakeup(module, NULL); + + /* enable clock */ + DSI_EnableClk(module, NULL); + + DSI_Reset(module, NULL); +#endif + s_isDsiPowerOn = true; + } + /* DSI_DumpRegisters(module,1); */ + return DSI_STATUS_OK; +} + + +int ddp_dsi_power_off(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + int i = 0; + int ret = 0; + unsigned int value = 0; + + DISPFUNC(); + /* DSI_DumpRegisters(module,1); */ + + if (s_isDsiPowerOn) { + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + /*disable TE when power off */ + DSI_OUTREGBIT(NULL, DSI_INT_ENABLE_REG, DSI_REG[i]->DSI_INTEN, TE_RDY, 0); + } + DSI_BackupRegisters(module, NULL); +#ifdef ENABLE_CLK_MGR + /* disable HS mode */ + DSI_clk_HS_mode(module, NULL, false); + /* enter ULPS mode */ + DSI_lane0_ULP_mode(module, NULL, 1); + DSI_clk_ULP_mode(module, NULL, 1); + /* make sure enter ulps mode */ + while (1) { + mdelay(1); + value = INREG32(&DSI_REG[0]->DSI_STATE_DBG1); + value = value >> 24; + if (value == 0x20) + break; + DISPMSG("dsi not in ulps mode, try again...\n"); + } + /* clear lane_num when enter ulps */ + DSI_OUTREGBIT(NULL, DSI_TXRX_CTRL_REG, DSI_REG[0]->DSI_TXRX_CTRL, LANE_NUM, 0); + /* disable clock */ + DSI_DisableClk(module, NULL); + + if (module == DISP_MODULE_DSI0 || module == DISP_MODULE_DSIDUAL) { +#ifdef CONFIG_MTK_CLKMGR + ret += disable_clock(MT_CG_DISP1_DSI_ENGINE, "DSI"); + ret += disable_clock(MT_CG_DISP1_DSI_DIGITAL, "DSI"); +#else + ddp_clk_disable(DISP1_DSI_ENGINE); + ddp_clk_disable(DISP1_DSI_DIGITAL); +#endif + if (ret > 0) + DISPMSG("DSI power manager API return false\n"); + } + /* disable mipi pll */ + DSI_PHY_clk_switch(module, NULL, false); +#ifdef CONFIG_MTK_CLKMGR + set_mipi26m(0); +#else + ddp_set_mipi26m(0); +#endif + +#endif + s_isDsiPowerOn = false; + } + /* DSI_DumpRegisters(module,1); */ + return DSI_STATUS_OK; +} + + +int ddp_dsi_is_busy(DISP_MODULE_ENUM module) +{ + int i = 0; + int busy = 0; + DSI_INT_STATUS_REG status; + /* DISPFUNC(); */ + + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + status = DSI_REG[i]->DSI_INTSTA; + + if (status.BUSY) + busy++; + } + + DISPDBG("%s is %s\n", ddp_get_module_name(module), busy ? "busy" : "idle"); + return busy; +} + +int ddp_dsi_is_idle(DISP_MODULE_ENUM module) +{ + return !ddp_dsi_is_busy(module); +} + +static const char *dsi_mode_spy(LCM_DSI_MODE_CON mode) +{ + switch (mode) { + case CMD_MODE: + return "CMD_MODE"; + case SYNC_PULSE_VDO_MODE: + return "SYNC_PULSE_VDO_MODE"; + case SYNC_EVENT_VDO_MODE: + return "SYNC_EVENT_VDO_MODE"; + case BURST_VDO_MODE: + return "BURST_VDO_MODE"; + default: + return "unknown"; + } +} + +void dsi_analysis(DISP_MODULE_ENUM module) +{ + int i = 0; + + DISPDMP("==DISP DSI ANALYSIS==\n"); + for (i = DSI_MODULE_BEGIN(module); i <= DSI_MODULE_END(module); i++) { + DISPDMP("MIPITX Clock: %d\n", dsi_phy_get_clk(module)); + DISPDMP + ("DSI%d Start:%x, Busy:%d, DSI_DUAL_EN:%d, MODE:%s, High Speed:%d, FSM State:%s\n", + i, DSI_REG[i]->DSI_START.DSI_START, DSI_REG[i]->DSI_INTSTA.BUSY, + DSI_REG[i]->DSI_COM_CTRL.DSI_DUAL_EN, + dsi_mode_spy(DSI_REG[i]->DSI_MODE_CTRL.MODE), + DSI_REG[i]->DSI_PHY_LCCON.LC_HS_TX_EN, + _dsi_cmd_mode_parse_state(DSI_REG[i]->DSI_STATE_DBG6.CMTRL_STATE)); + + DISPDMP + ("DSI%d IRQ,RD_RDY:%d, CMD_DONE:%d, SLEEPOUT_DONE:%d, TE_RDY:%d, VM_CMD_DONE:%d, VM_DONE:%d\n", + i, DSI_REG[i]->DSI_INTSTA.RD_RDY, DSI_REG[i]->DSI_INTSTA.CMD_DONE, + DSI_REG[i]->DSI_INTSTA.SLEEPOUT_DONE, DSI_REG[i]->DSI_INTSTA.TE_RDY, + DSI_REG[i]->DSI_INTSTA.VM_CMD_DONE, DSI_REG[i]->DSI_INTSTA.VM_DONE); + + DISPDMP("DSI%d Lane Num:%d, Ext_TE_EN:%d, Ext_TE_Edge:%d, HSTX_CKLP_EN:%d\n", i, + DSI_REG[i]->DSI_TXRX_CTRL.LANE_NUM, + DSI_REG[i]->DSI_TXRX_CTRL.EXT_TE_EN, + DSI_REG[i]->DSI_TXRX_CTRL.EXT_TE_EDGE, + DSI_REG[i]->DSI_TXRX_CTRL.HSTX_CKLP_EN); + + DISPDMP("DSI%d LFR En:%d, LFR MODE:%d, LFR TYPE:%d, LFR SKIP NUMBER:%d\n", i, + DSI_REG[i]->DSI_LFR_CON.LFR_EN, + DSI_REG[i]->DSI_LFR_CON.LFR_MODE, + DSI_REG[i]->DSI_LFR_CON.LFR_TYPE, DSI_REG[i]->DSI_LFR_CON.LFR_SKIP_NUM); + } +} + +int ddp_dsi_dump(DISP_MODULE_ENUM module, int level) +{ + if (!s_isDsiPowerOn) { + DISPMSG("sleep dump is invalid\n"); + return 0; + } + + dsi_analysis(module); + DSI_DumpRegisters(module, level); + + return 0; +} + +int ddp_dsi_build_cmdq(DISP_MODULE_ENUM module, void *cmdq_trigger_handle, CMDQ_STATE state) +{ + int ret = 0; + int i = 0; + int dsi_i = 0; + LCM_DSI_PARAMS *dsi_params = NULL; + DSI_T0_INS t0; + DSI_T0_INS t1; + DSI_RX_DATA_REG read_data[4]; + + static cmdqBackupSlotHandle hSlot[4] = {0, 0, 0, 0}; + + if (DISP_MODULE_DSIDUAL == module) + dsi_i = 0; + else + dsi_i = DSI_MODULE_to_ID(module); + dsi_params = &_dsi_context[dsi_i].dsi_params; + + if (cmdq_trigger_handle == NULL) { + DISPERR("cmdq_trigger_handle is NULL\n"); + return -1; + } + + if (state == CMDQ_WAIT_LCM_TE) { + /* need waiting te */ + if (module == DISP_MODULE_DSI0) { + if (dsi0_te_enable == 0) + return 0; + + if (disp_helper_get_option(DISP_OPT_USE_CMDQ)) { + ret = + cmdqRecClearEventToken(cmdq_trigger_handle, CMDQ_EVENT_DSI_TE); + ret = cmdqRecWait(cmdq_trigger_handle, CMDQ_EVENT_DSI_TE); + } + } else { + DISPERR("wrong module: %s\n", ddp_get_module_name(module)); + return -1; + } + } else if (state == CMDQ_CHECK_IDLE_AFTER_STREAM_EOF) { + /* need waiting te */ + if (module == DISP_MODULE_DSI0) + DSI_POLLREG32(cmdq_trigger_handle, &DSI_REG[dsi_i]->DSI_INTSTA, 0x80000000, + 0); + else { + DISPERR("wrong module: %s\n", ddp_get_module_name(module)); + return -1; + } + } else if (state == CMDQ_ESD_CHECK_READ) { + /* enable dsi interrupt: RD_RDY/CMD_DONE (need do this here?) */ + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_INT_ENABLE_REG, DSI_REG[dsi_i]->DSI_INTEN, + RD_RDY, 1); + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_INT_ENABLE_REG, DSI_REG[dsi_i]->DSI_INTEN, + CMD_DONE, 1); + + for (i = 0; i < ESD_CHECK_NUM; i++) { + if (dsi_params->lcm_esd_check_table[i].cmd == 0) + break; + /* 0. send read lcm command(short packet) */ + t0.CONFG = 0x04;/* BTA */ + t0.Data0 = dsi_params->lcm_esd_check_table[i].cmd; + /* / 0xB0 is used to distinguish DCS cmd or Gerneric cmd, is that Right??? */ + t0.Data_ID = + (t0.Data0 < + 0xB0) ? DSI_DCS_READ_PACKET_ID : DSI_GERNERIC_READ_LONG_PACKET_ID; + t0.Data1 = 0; + + t1.CONFG = 0x00; + t1.Data0 = dsi_params->lcm_esd_check_table[i].count; + t1.Data1 = 0x00; + t1.Data_ID = 0x37; + /* write DSI CMDQ */ + DSI_OUTREG32(cmdq_trigger_handle, &DSI_CMDQ_REG[dsi_i]->data[0], + AS_UINT32(&t1)); + DSI_OUTREG32(cmdq_trigger_handle, &DSI_CMDQ_REG[dsi_i]->data[1], + AS_UINT32(&t0)); + DSI_OUTREG32(cmdq_trigger_handle, &DSI_REG[dsi_i]->DSI_CMDQ_SIZE, 2); + + /* start DSI */ + DSI_OUTREG32(cmdq_trigger_handle, &DSI_REG[dsi_i]->DSI_START, 0); + DSI_OUTREG32(cmdq_trigger_handle, &DSI_REG[dsi_i]->DSI_START, 1); + + /* 1. wait DSI RD_RDY(must clear, in case of cpu RD_RDY interrupt handler) */ + if (dsi_i == 0) { + DSI_POLLREG32(cmdq_trigger_handle, &DSI_REG[dsi_i]->DSI_INTSTA, + 0x00000001, 0x1); + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_INT_STATUS_REG, + DSI_REG[dsi_i]->DSI_INTSTA, RD_RDY, 0x00000000); + } + /* 2. save RX data */ + if (hSlot[0] && hSlot[1] && hSlot[2] && hSlot[3]) { + DSI_BACKUPREG32(cmdq_trigger_handle, hSlot[0], i, + &DSI_REG[0]->DSI_RX_DATA0); + DSI_BACKUPREG32(cmdq_trigger_handle, hSlot[1], i, + &DSI_REG[0]->DSI_RX_DATA1); + DSI_BACKUPREG32(cmdq_trigger_handle, hSlot[2], i, + &DSI_REG[0]->DSI_RX_DATA2); + DSI_BACKUPREG32(cmdq_trigger_handle, hSlot[3], i, + &DSI_REG[0]->DSI_RX_DATA3); + } + /* 3. write RX_RACK */ + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_RACK_REG, DSI_REG[dsi_i]->DSI_RACK, + DSI_RACK, 1); + /* 4. polling not busy(no need clear) */ + if (dsi_i == 0) + DSI_POLLREG32(cmdq_trigger_handle, &DSI_REG[dsi_i]->DSI_INTSTA, + 0x80000000, 0); + /* loop: 0~4 */ + } + /* DSI_OUTREGBIT(cmdq_trigger_handle, DSI_INT_ENABLE_REG,DSI_REG[dsi_i]->DSI_INTEN,RD_RDY,0); */ + } else if (state == CMDQ_ESD_CHECK_CMP) { + + DISPMSG("[DSI]enter cmp\n"); + /* cmp just once and only 1 return value */ + for (i = 0; i < ESD_CHECK_NUM; i++) { + if (dsi_params->lcm_esd_check_table[i].cmd == 0) + break; + DISPMSG("[DSI]enter cmp i=%d\n", i); + + /* read data */ + if (hSlot[0] && hSlot[1] && hSlot[2] && hSlot[3]) { + /* read from slot */ + cmdqBackupReadSlot(hSlot[0], i, ((uint32_t *) &read_data[0])); + cmdqBackupReadSlot(hSlot[1], i, ((uint32_t *) &read_data[1])); + cmdqBackupReadSlot(hSlot[2], i, ((uint32_t *) &read_data[2])); + cmdqBackupReadSlot(hSlot[3], i, ((uint32_t *) &read_data[3])); + } else { + /* read from dsi , support only one cmd read */ + if (i == 0) { + DSI_OUTREG32(NULL, &read_data[0], + AS_UINT32(&DSI_REG[dsi_i]->DSI_RX_DATA0)); + DSI_OUTREG32(NULL, &read_data[1], + AS_UINT32(&DSI_REG[dsi_i]->DSI_RX_DATA0)); + DSI_OUTREG32(NULL, &read_data[2], + AS_UINT32(&DSI_REG[dsi_i]->DSI_RX_DATA0)); + DSI_OUTREG32(NULL, &read_data[3], + AS_UINT32(&DSI_REG[dsi_i]->DSI_RX_DATA0)); + } + } + + DISPDBG("[DSI]enter cmp read_data0 byte0=0x%x byte1=0x%x byte2=0x%x byte3=0x%x\n", + read_data[0].byte0, read_data[0].byte1, read_data[0].byte2, + read_data[0].byte3); + DISPDBG("[DSI]enter cmp read_data0=0x%x,read_data1=0x%x\n", AS_UINT32(&read_data[0]), + AS_UINT32(&read_data[1])); + DISPDBG("[DSI]enter cmp read_data2=0x%x,read_data3=0x%x\n", AS_UINT32(&read_data[2]), + AS_UINT32(&read_data[3])); + DISPDBG("[DSI]enter cmp check_table cmd=0x%x,count=0x%x,para_list[0]=0x%x,para_list[1]=0x%x\n", + dsi_params->lcm_esd_check_table[i].cmd, + dsi_params->lcm_esd_check_table[i].count, + dsi_params->lcm_esd_check_table[i].para_list[0], + dsi_params->lcm_esd_check_table[i].para_list[1]); + DISPDBG("[DSI]enter cmp DSI+0x200=0x%x\n", + AS_UINT32(DDP_REG_BASE_DSI0 + 0x200)); + DISPDBG("[DSI]enter cmp DSI+0x204=0x%x\n", + AS_UINT32(DDP_REG_BASE_DSI0 + 0x204)); + DISPDBG("[DSI]enter cmp DSI+0x60=0x%x\n", + AS_UINT32(DDP_REG_BASE_DSI0 + 0x60)); + DISPDBG("[DSI]enter cmp DSI+0x74=0x%x\n", + AS_UINT32(DDP_REG_BASE_DSI0 + 0x74)); + DISPDBG("[DSI]enter cmp DSI+0x88=0x%x\n", + AS_UINT32(DDP_REG_BASE_DSI0 + 0x88)); + DISPDBG("[DSI]enter cmp DSI+0x0c=0x%x\n", + AS_UINT32(DDP_REG_BASE_DSI0 + 0x0c)); + + ret = DSI_read_cmp(i, read_data, dsi_params->lcm_esd_check_table[i].para_list, + dsi_params->lcm_esd_check_table[i].count); + if (ret) + break; + } + } else if (state == CMDQ_ESD_ALLC_SLOT) { + /* create 3 slot */ + unsigned int n = 0; + + n = DSI_esd_check_times(dsi_params); + cmdqBackupAllocateSlot(&hSlot[0], n); + cmdqBackupAllocateSlot(&hSlot[1], n); + cmdqBackupAllocateSlot(&hSlot[2], n); + cmdqBackupAllocateSlot(&hSlot[3], n); + } else if (state == CMDQ_ESD_FREE_SLOT) { + unsigned int h = 0; + + for (h = 0; h < 4; h++) + if (hSlot[h]) { + cmdqBackupFreeSlot(hSlot[h]); + hSlot[h] = 0; + } + } else if (state == CMDQ_STOP_VDO_MODE) { + /* use cmdq to stop dsi vdo mode */ + /* 0. set dsi cmd mode */ + DSI_SetMode(module, cmdq_trigger_handle, CMD_MODE); + /* 1. polling dsi not busy */ + i = DSI_MODULE_BEGIN(module); + if (i == 0) { + /* polling dsi busy */ + DSI_POLLREG32(cmdq_trigger_handle, &DSI_REG[i]->DSI_INTSTA, 0x80000000, 0); +#if 0 + i = DSI_MODULE_END(module); + if (i == 1) /* DUAL */ + DSI_POLLREG32(cmdq_trigger_handle, &DSI_REG[i]->DSI_INTSTA, + 0x80000000, 0); +#endif + } + /* 2.dual dsi need do reset DSI_DUAL_EN/DSI_START */ + if (module == DISP_MODULE_DSIDUAL) { + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_COM_CTRL_REG, + DSI_REG[0]->DSI_COM_CTRL, DSI_DUAL_EN, 0); + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_COM_CTRL_REG, + DSI_REG[1]->DSI_COM_CTRL, DSI_DUAL_EN, 0); + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_START_REG, DSI_REG[0]->DSI_START, + DSI_START, 0); + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_START_REG, DSI_REG[1]->DSI_START, + DSI_START, 0); + } + /* 3.disable HS */ + /* DSI_clk_HS_mode(module, cmdq_trigger_handle, FALSE); */ + + } else if (state == CMDQ_START_VDO_MODE) { + + /* 0. dual dsi set DSI_START/DSI_DUAL_EN */ + if (module == DISP_MODULE_DSIDUAL) { + /* must set DSI_START to 0 before set dsi_dual_en, don't know why.2014.02.15 */ + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_START_REG, DSI_REG[0]->DSI_START, + DSI_START, 0); + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_START_REG, DSI_REG[1]->DSI_START, + DSI_START, 0); + + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_COM_CTRL_REG, + DSI_REG[0]->DSI_COM_CTRL, DSI_DUAL_EN, 1); + DSI_OUTREGBIT(cmdq_trigger_handle, DSI_COM_CTRL_REG, + DSI_REG[1]->DSI_COM_CTRL, DSI_DUAL_EN, 1); + + } + /* 1. set dsi vdo mode */ + DSI_SetMode(module, cmdq_trigger_handle, dsi_params->mode); + + /* 2. enable HS */ + /* DSI_clk_HS_mode(module, cmdq_trigger_handle, TRUE); */ + + /* 3. enable mutex */ + /* ddp_mutex_enable(mutex_id_for_latest_trigger,0,cmdq_trigger_handle); */ + + /* 4. start dsi */ + /* DSI_Start(module, cmdq_trigger_handle); */ + + } else if (state == CMDQ_DSI_RESET) { + DISPMSG("CMDQ Timeout, Reset DSI\n"); + DSI_DumpRegisters(module, 1); + DSI_Reset(module, NULL); + } else if (state == CMDQ_DSI_LFR_MODE) { + if (dsi_params->lfr_mode == 2 || dsi_params->lfr_mode == 3) + DSI_LFR_UPDATE(module, cmdq_trigger_handle); + } + + return ret; +} + +void *get_dsi_params_handle(uint32_t dsi_idx) +{ + if (dsi_idx != PM_DSI1) + return (void *)(&_dsi_context[0].dsi_params); + else + return (void *)(&_dsi_context[1].dsi_params); +} + +int32_t DSI_ssc_enable(uint32_t dsi_index, uint32_t en) +{ + uint32_t disable = en ? 0 : 1; + + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[0]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_EN, en); + _dsi_context[0].dsi_params.ssc_disable = disable; + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[1]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_EN, en); + _dsi_context[1].dsi_params.ssc_disable = disable; + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[0]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_EN, en); + DSI_OUTREGBIT(NULL, MIPITX_DSI_PLL_CON1_REG, DSI_PHY_REG[1]->MIPITX_DSI_PLL_CON1, + RG_DSI0_MPPLL_SDM_SSC_EN, en); + _dsi_context[0].dsi_params.ssc_disable = _dsi_context[1].dsi_params.ssc_disable = + disable; + } + return 0; +} + +DDP_MODULE_DRIVER ddp_driver_dsi0 = { + .module = DISP_MODULE_DSI0, + .init = ddp_dsi_init, + .deinit = ddp_dsi_deinit, + .config = ddp_dsi_config, + .build_cmdq = ddp_dsi_build_cmdq, + .trigger = ddp_dsi_trigger, + .start = ddp_dsi_start, + .stop = ddp_dsi_stop, + .reset = ddp_dsi_reset, + .power_on = ddp_dsi_power_on, + .power_off = ddp_dsi_power_off, + .is_idle = ddp_dsi_is_idle, + .is_busy = ddp_dsi_is_busy, + .dump_info = ddp_dsi_dump, + .set_lcm_utils = ddp_dsi_set_lcm_utils, + .ioctl = ddp_dsi_ioctl +}; + +const LCM_UTIL_FUNCS PM_lcm_utils_dsi0 = { + .set_reset_pin = lcm_set_reset_pin, + .udelay = lcm_udelay, + .mdelay = lcm_mdelay, + .dsi_set_cmdq = DSI_set_cmdq_wrapper_DSI0, + .dsi_set_cmdq_V2 = DSI_set_cmdq_V2_Wrapper_DSI0 +}; + + +/* /////////////////////// Panel Master ////////////////////////////////// */ +uint32_t PanelMaster_get_TE_status(uint32_t dsi_idx) +{ + if (dsi_idx == 0) + return dsi0_te_enable ? 1 : 0; + /* else */ + /* return dsi1_te_enable ? 1:0 ; */ + return 1; +} + +uint32_t PanelMaster_get_CC(uint32_t dsi_idx) +{ + DSI_TXRX_CTRL_REG tmp_reg; + + DSI_READREG32(PDSI_TXRX_CTRL_REG, &tmp_reg, &DSI_REG[dsi_idx]->DSI_TXRX_CTRL); + return tmp_reg.HSTX_CKLP_EN ? 1 : 0; +} + +void PanelMaster_set_CC(uint32_t dsi_index, uint32_t enable) +{ + DISPMSG("set_cc :%d\n", enable); + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_TXRX_CTRL_REG, DSI_REG[0]->DSI_TXRX_CTRL, HSTX_CKLP_EN, + enable); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_TXRX_CTRL_REG, DSI_REG[1]->DSI_TXRX_CTRL, HSTX_CKLP_EN, + enable); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_TXRX_CTRL_REG, DSI_REG[0]->DSI_TXRX_CTRL, HSTX_CKLP_EN, + enable); + DSI_OUTREGBIT(NULL, DSI_TXRX_CTRL_REG, DSI_REG[1]->DSI_TXRX_CTRL, HSTX_CKLP_EN, + enable); + } +} + +void PanelMaster_DSI_set_timing(uint32_t dsi_index, MIPI_TIMING timing) +{ + uint32_t hbp_byte; + LCM_DSI_PARAMS *dsi_params; + int fbconfig_dsiTmpBufBpp = 0; + + if (_dsi_context[dsi_index].dsi_params.data_format.format == LCM_DSI_FORMAT_RGB565) + fbconfig_dsiTmpBufBpp = 2; + else + fbconfig_dsiTmpBufBpp = 3; + dsi_params = get_dsi_params_handle(dsi_index); + switch (timing.type) { + case LPX: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[0]->DSI_PHY_TIMECON0, LPX, + timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[1]->DSI_PHY_TIMECON0, LPX, + timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[0]->DSI_PHY_TIMECON0, LPX, + timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[1]->DSI_PHY_TIMECON0, LPX, + timing.value); + } + break; + case HS_PRPR: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[0]->DSI_PHY_TIMECON0, + HS_PRPR, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[1]->DSI_PHY_TIMECON0, + HS_PRPR, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[0]->DSI_PHY_TIMECON0, + HS_PRPR, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[1]->DSI_PHY_TIMECON0, + HS_PRPR, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON0_REG,DSI_REG->DSI_PHY_TIMECON0,HS_PRPR,timing.value); */ + break; + case HS_ZERO: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[0]->DSI_PHY_TIMECON0, + HS_ZERO, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[1]->DSI_PHY_TIMECON0, + HS_ZERO, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[0]->DSI_PHY_TIMECON0, + HS_ZERO, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[1]->DSI_PHY_TIMECON0, + HS_ZERO, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON0_REG,DSI_REG->DSI_PHY_TIMECON0,HS_ZERO,timing.value); */ + break; + case HS_TRAIL: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[0]->DSI_PHY_TIMECON0, + HS_TRAIL, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[1]->DSI_PHY_TIMECON0, + HS_TRAIL, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[0]->DSI_PHY_TIMECON0, + HS_TRAIL, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON0_REG, DSI_REG[1]->DSI_PHY_TIMECON0, + HS_TRAIL, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON0_REG,DSI_REG->DSI_PHY_TIMECON0,HS_TRAIL,timing.value); */ + break; + case TA_GO: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[0]->DSI_PHY_TIMECON1, + TA_GO, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[1]->DSI_PHY_TIMECON1, + TA_GO, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[0]->DSI_PHY_TIMECON1, + TA_GO, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[1]->DSI_PHY_TIMECON1, + TA_GO, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON1_REG,DSI_REG->DSI_PHY_TIMECON1,TA_GO,timing.value); */ + break; + case TA_SURE: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[0]->DSI_PHY_TIMECON1, + TA_SURE, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[1]->DSI_PHY_TIMECON1, + TA_SURE, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[0]->DSI_PHY_TIMECON1, + TA_SURE, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[1]->DSI_PHY_TIMECON1, + TA_SURE, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON1_REG,DSI_REG->DSI_PHY_TIMECON1,TA_SURE,timing.value); */ + break; + case TA_GET: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[0]->DSI_PHY_TIMECON1, + TA_GET, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[1]->DSI_PHY_TIMECON1, + TA_GET, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[0]->DSI_PHY_TIMECON1, + TA_GET, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[1]->DSI_PHY_TIMECON1, + TA_GET, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON1_REG,DSI_REG->DSI_PHY_TIMECON1,TA_GET,timing.value); */ + break; + case DA_HS_EXIT: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[0]->DSI_PHY_TIMECON1, + DA_HS_EXIT, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[1]->DSI_PHY_TIMECON1, + DA_HS_EXIT, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[0]->DSI_PHY_TIMECON1, + DA_HS_EXIT, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON1_REG, DSI_REG[1]->DSI_PHY_TIMECON1, + DA_HS_EXIT, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON1_REG,DSI_REG->DSI_PHY_TIMECON1,DA_HS_EXIT,timing.value); */ + break; + case CONT_DET: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[0]->DSI_PHY_TIMECON2, + CONT_DET, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[1]->DSI_PHY_TIMECON2, + CONT_DET, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[0]->DSI_PHY_TIMECON2, + CONT_DET, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[1]->DSI_PHY_TIMECON2, + CONT_DET, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON2_REG,DSI_REG->DSI_PHY_TIMECON2,CONT_DET,timing.value); */ + break; + case CLK_ZERO: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[0]->DSI_PHY_TIMECON2, + CLK_ZERO, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[1]->DSI_PHY_TIMECON2, + CLK_ZERO, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[0]->DSI_PHY_TIMECON2, + CLK_ZERO, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[1]->DSI_PHY_TIMECON2, + CLK_ZERO, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON2_REG,DSI_REG->DSI_PHY_TIMECON2,CLK_ZERO,timing.value); */ + break; + case CLK_TRAIL: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[0]->DSI_PHY_TIMECON2, + CLK_TRAIL, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[1]->DSI_PHY_TIMECON2, + CLK_TRAIL, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[0]->DSI_PHY_TIMECON2, + CLK_TRAIL, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON2_REG, DSI_REG[1]->DSI_PHY_TIMECON2, + CLK_TRAIL, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON2_REG,DSI_REG->DSI_PHY_TIMECON2,CLK_TRAIL,timing.value); */ + break; + case CLK_HS_PRPR: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[0]->DSI_PHY_TIMECON3, + CLK_HS_PRPR, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[1]->DSI_PHY_TIMECON3, + CLK_HS_PRPR, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[0]->DSI_PHY_TIMECON3, + CLK_HS_PRPR, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[1]->DSI_PHY_TIMECON3, + CLK_HS_PRPR, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON3_REG,DSI_REG->DSI_PHY_TIMECON3,CLK_HS_PRPR,timing.value); */ + break; + case CLK_HS_POST: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[0]->DSI_PHY_TIMECON3, + CLK_HS_POST, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[1]->DSI_PHY_TIMECON3, + CLK_HS_POST, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[0]->DSI_PHY_TIMECON3, + CLK_HS_POST, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[1]->DSI_PHY_TIMECON3, + CLK_HS_POST, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON3_REG,DSI_REG->DSI_PHY_TIMECON3,CLK_HS_POST,timing.value); */ + break; + case CLK_HS_EXIT: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[0]->DSI_PHY_TIMECON3, + CLK_HS_EXIT, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[1]->DSI_PHY_TIMECON3, + CLK_HS_EXIT, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[0]->DSI_PHY_TIMECON3, + CLK_HS_EXIT, timing.value); + DSI_OUTREGBIT(NULL, DSI_PHY_TIMCON3_REG, DSI_REG[1]->DSI_PHY_TIMECON3, + CLK_HS_EXIT, timing.value); + } + /* OUTREGBIT(DSI_PHY_TIMCON3_REG,DSI_REG->DSI_PHY_TIMECON3,CLK_HS_EXIT,timing.value); */ + break; + case HPW: + if (!(dsi_params->mode == SYNC_EVENT_VDO_MODE || dsi_params->mode == BURST_VDO_MODE)) + timing.value = (timing.value * fbconfig_dsiTmpBufBpp - 10); + timing.value = ALIGN_TO((timing.value), 4); + if (dsi_index == PM_DSI0) { + DSI_OUTREG32(NULL, &DSI_REG[0]->DSI_HSA_WC, timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREG32(NULL, &DSI_REG[1]->DSI_HSA_WC, timing.value); + } else if (dsi_index == PM_DSI_DUAL) { + DSI_OUTREG32(NULL, &DSI_REG[0]->DSI_HSA_WC, timing.value); + DSI_OUTREG32(NULL, &DSI_REG[1]->DSI_HSA_WC, timing.value); + } + break; + case HFP: + timing.value = timing.value * fbconfig_dsiTmpBufBpp - 12; + timing.value = ALIGN_TO(timing.value, 4); + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_HFP_WC_REG, DSI_REG[0]->DSI_HFP_WC, HFP_WC, + timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_HFP_WC_REG, DSI_REG[1]->DSI_HFP_WC, HFP_WC, + timing.value); + } else { + DSI_OUTREGBIT(NULL, DSI_HFP_WC_REG, DSI_REG[0]->DSI_HFP_WC, HFP_WC, + timing.value); + DSI_OUTREGBIT(NULL, DSI_HFP_WC_REG, DSI_REG[1]->DSI_HFP_WC, HFP_WC, + timing.value); + } + break; + case HBP: + if (dsi_params->mode == SYNC_EVENT_VDO_MODE || dsi_params->mode == BURST_VDO_MODE) { + hbp_byte = + ((timing.value + + dsi_params->horizontal_sync_active) * fbconfig_dsiTmpBufBpp - 10); + } else { + /* hsa_byte = (dsi_params->horizontal_sync_active * fbconfig_dsiTmpBufBpp - 10); */ + hbp_byte = timing.value * fbconfig_dsiTmpBufBpp - 10; + } + if (dsi_index == PM_DSI0) { + DSI_OUTREG32(NULL, &DSI_REG[0]->DSI_HBP_WC, ALIGN_TO((hbp_byte), 4)); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREG32(NULL, &DSI_REG[1]->DSI_HBP_WC, ALIGN_TO((hbp_byte), 4)); + } else { + DSI_OUTREG32(NULL, &DSI_REG[0]->DSI_HBP_WC, ALIGN_TO((hbp_byte), 4)); + DSI_OUTREG32(NULL, &DSI_REG[1]->DSI_HBP_WC, ALIGN_TO((hbp_byte), 4)); + } + + break; + case VPW: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_VACT_NL_REG, DSI_REG[0]->DSI_VACT_NL, VACT_NL, + timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_VACT_NL_REG, DSI_REG[1]->DSI_VACT_NL, VACT_NL, + timing.value); + } else { + DSI_OUTREGBIT(NULL, DSI_VACT_NL_REG, DSI_REG[0]->DSI_VACT_NL, VACT_NL, + timing.value); + DSI_OUTREGBIT(NULL, DSI_VACT_NL_REG, DSI_REG[1]->DSI_VACT_NL, VACT_NL, + timing.value); + } + /* OUTREG32(&DSI_REG->DSI_VACT_NL,timing.value); */ + break; + case VFP: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_VFP_NL_REG, DSI_REG[0]->DSI_VFP_NL, VFP_NL, + timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_VFP_NL_REG, DSI_REG[1]->DSI_VFP_NL, VFP_NL, + timing.value); + } else { + DSI_OUTREGBIT(NULL, DSI_VFP_NL_REG, DSI_REG[0]->DSI_VFP_NL, VFP_NL, + timing.value); + DSI_OUTREGBIT(NULL, DSI_VFP_NL_REG, DSI_REG[1]->DSI_VFP_NL, VFP_NL, + timing.value); + } + /* OUTREG32(&DSI_REG->DSI_VFP_NL, timing.value); */ + break; + case VBP: + if (dsi_index == PM_DSI0) { + DSI_OUTREGBIT(NULL, DSI_VBP_NL_REG, DSI_REG[0]->DSI_VBP_NL, VBP_NL, + timing.value); + } else if (dsi_index == PM_DSI1) { + DSI_OUTREGBIT(NULL, DSI_VBP_NL_REG, DSI_REG[1]->DSI_VBP_NL, VBP_NL, + timing.value); + } else { + DSI_OUTREGBIT(NULL, DSI_VBP_NL_REG, DSI_REG[0]->DSI_VBP_NL, VBP_NL, + timing.value); + DSI_OUTREGBIT(NULL, DSI_VBP_NL_REG, DSI_REG[1]->DSI_VBP_NL, VBP_NL, + timing.value); + } + /* OUTREG32(&DSI_REG->DSI_VBP_NL, timing.value); */ + break; + case SSC_EN: + DSI_ssc_enable(dsi_index, timing.value); + break; + default: + DISPMSG("fbconfig dsi set timing :no such type!!\n"); + break; + } +} + +uint32_t PanelMaster_get_dsi_timing(uint32_t dsi_index, MIPI_SETTING_TYPE type) +{ + uint32_t dsi_val; + PDSI_REGS dsi_reg; + int fbconfig_dsiTmpBufBpp = 0; + + if (_dsi_context[dsi_index].dsi_params.data_format.format == LCM_DSI_FORMAT_RGB565) + fbconfig_dsiTmpBufBpp = 2; + else + fbconfig_dsiTmpBufBpp = 3; + if ((dsi_index == PM_DSI0) || (dsi_index == PM_DSI_DUAL)) + dsi_reg = DSI_REG[0]; + else + dsi_reg = DSI_REG[1]; + switch (type) { + case LPX: + dsi_val = dsi_reg->DSI_PHY_TIMECON0.LPX; + return dsi_val; + case HS_PRPR: + dsi_val = dsi_reg->DSI_PHY_TIMECON0.HS_PRPR; + return dsi_val; + case HS_ZERO: + dsi_val = dsi_reg->DSI_PHY_TIMECON0.HS_ZERO; + return dsi_val; + case HS_TRAIL: + dsi_val = dsi_reg->DSI_PHY_TIMECON0.HS_TRAIL; + return dsi_val; + case TA_GO: + dsi_val = dsi_reg->DSI_PHY_TIMECON1.TA_GO; + return dsi_val; + case TA_SURE: + dsi_val = dsi_reg->DSI_PHY_TIMECON1.TA_SURE; + return dsi_val; + case TA_GET: + dsi_val = dsi_reg->DSI_PHY_TIMECON1.TA_GET; + return dsi_val; + case DA_HS_EXIT: + dsi_val = dsi_reg->DSI_PHY_TIMECON1.DA_HS_EXIT; + return dsi_val; + case CONT_DET: + dsi_val = dsi_reg->DSI_PHY_TIMECON2.CONT_DET; + return dsi_val; + case CLK_ZERO: + dsi_val = dsi_reg->DSI_PHY_TIMECON2.CLK_ZERO; + return dsi_val; + case CLK_TRAIL: + dsi_val = dsi_reg->DSI_PHY_TIMECON2.CLK_TRAIL; + return dsi_val; + case CLK_HS_PRPR: + dsi_val = dsi_reg->DSI_PHY_TIMECON3.CLK_HS_PRPR; + return dsi_val; + case CLK_HS_POST: + dsi_val = dsi_reg->DSI_PHY_TIMECON3.CLK_HS_POST; + return dsi_val; + case CLK_HS_EXIT: + dsi_val = dsi_reg->DSI_PHY_TIMECON3.CLK_HS_EXIT; + return dsi_val; + case HPW: + { + DSI_HSA_WC_REG tmp_reg; + + DSI_READREG32(PDSI_HSA_WC_REG, &tmp_reg, &dsi_reg->DSI_HSA_WC); + dsi_val = (tmp_reg.HSA_WC + 10) / fbconfig_dsiTmpBufBpp; + return dsi_val; + } + case HFP: + { + DSI_HFP_WC_REG tmp_hfp; + + DSI_READREG32(PDSI_HFP_WC_REG, &tmp_hfp, &dsi_reg->DSI_HFP_WC); + dsi_val = ((tmp_hfp.HFP_WC + 12) / fbconfig_dsiTmpBufBpp); + return dsi_val; + } + case HBP: + { + DSI_HBP_WC_REG tmp_hbp; + LCM_DSI_PARAMS *dsi_params; + + dsi_params = get_dsi_params_handle(dsi_index); + OUTREG32(&tmp_hbp, AS_UINT32(&dsi_reg->DSI_HBP_WC)); + if (dsi_params->mode == SYNC_EVENT_VDO_MODE + || dsi_params->mode == BURST_VDO_MODE) + return ((tmp_hbp.HBP_WC + 10) / fbconfig_dsiTmpBufBpp - + dsi_params->horizontal_sync_active); + else + return (tmp_hbp.HBP_WC + 10) / fbconfig_dsiTmpBufBpp; + } + case VPW: + { + DSI_VACT_NL_REG tmp_vpw; + + DSI_READREG32(PDSI_VACT_NL_REG, &tmp_vpw, &dsi_reg->DSI_VACT_NL); + dsi_val = tmp_vpw.VACT_NL; + return dsi_val; + } + case VFP: + { + DSI_VFP_NL_REG tmp_vfp; + + DSI_READREG32(PDSI_VFP_NL_REG, &tmp_vfp, &dsi_reg->DSI_VFP_NL); + dsi_val = tmp_vfp.VFP_NL; + return dsi_val; + } + case VBP: + { + DSI_VBP_NL_REG tmp_vbp; + + DSI_READREG32(PDSI_VBP_NL_REG, &tmp_vbp, &dsi_reg->DSI_VBP_NL); + dsi_val = tmp_vbp.VBP_NL; + return dsi_val; + } + case SSC_EN: + { + if (_dsi_context[dsi_index].dsi_params.ssc_disable) + dsi_val = 0; + else + dsi_val = 1; + return dsi_val; + } + default: + DISPMSG("fbconfig dsi set timing :no such type!!\n"); + } + dsi_val = 0; + return dsi_val; +} + +unsigned int PanelMaster_set_PM_enable(unsigned int value) +{ + atomic_set(&PMaster_enable, value); + return 0; +} + +/* ///////////////////////////////No DSI Driver //////////////////////////////////////////////// */ +int DSI_set_roi(int x, int y) +{ + DISPMSG("[DSI](x0,y0,x1,y1)=(%d,%d,%d,%d)\n", x, y, _dsi_context[0].lcm_width, + _dsi_context[0].lcm_height); + return DSI_Send_ROI(DISP_MODULE_DSI0, NULL, x, y, _dsi_context[0].lcm_width - x, + _dsi_context[0].lcm_height - y); +} + +int DSI_check_roi(void) +{ + int ret = 0; + unsigned char read_buf[4] = { 1, 1, 1, 1 }; + unsigned int data_array[16]; + int count; + int x0; + int y0; + + data_array[0] = 0x00043700; /* read id return two byte,version and id */ + DSI_set_cmdq(DISP_MODULE_DSI0, NULL, data_array, 1, 1); + + msleep(20); + + count = DSI_dcs_read_lcm_reg_v2(DISP_MODULE_DSI0, NULL, 0x2a, read_buf, 4); + + msleep(20); + x0 = (read_buf[0] << 8) | read_buf[1]; + + DISPMSG("x0=%d count=%d,read_buf[0]=%d,read_buf[1]=%d,read_buf[2]=%d,read_buf[3]=%d\n", x0, + count, read_buf[0], read_buf[1], read_buf[2], read_buf[3]); + if ((count == 0) || (x0 != 0)) { + DISPMSG("[DSI]x count %d read_buf[0]=%d,read_buf[1]=%d,read_buf[2]=%d,read_buf[3]=%d\n", + count, read_buf[0], read_buf[1], read_buf[2], read_buf[3]); + return -1; + } + msleep(20); + count = DSI_dcs_read_lcm_reg_v2(DISP_MODULE_DSI0, NULL, 0x2b, read_buf, 4); + y0 = (read_buf[0] << 8) | read_buf[1]; + + DISPMSG("y0=%d count %d,read_buf[0]=%d,read_buf[1]=%d,read_buf[2]=%d,read_buf[3]=%d\n", y0, + count, read_buf[0], read_buf[1], read_buf[2], read_buf[3]); + if ((count == 0) || (y0 != 0)) { + DISPMSG("[DSI]y count %d read_buf[0]=%d,read_buf[1]=%d,read_buf[2]=%d,read_buf[3]=%d\n", + count, read_buf[0], read_buf[1], read_buf[2], read_buf[3]); + return -1; + } + return ret; +} + +void DSI_ForceConfig(int forceconfig) +{ + dsi_force_config = forceconfig; + /*cv switch by resume*/ + if (disp_helper_get_option(DISP_OPT_CV_BYSUSPEND)) { + if (lcm_mode_status != 0) { + if (0 == _dsi_context[0].dsi_params.PLL_CK_CMD) + _dsi_context[0].dsi_params.PLL_CK_CMD = _dsi_context[0].dsi_params.PLL_CLOCK; + if (0 == _dsi_context[0].dsi_params.PLL_CK_VDO) + _dsi_context[0].dsi_params.PLL_CK_VDO = _dsi_context[0].dsi_params.PLL_CLOCK; + if (CMD_MODE == lcm_dsi_mode) + _dsi_context[0].dsi_params.PLL_CLOCK = _dsi_context[0].dsi_params.PLL_CK_CMD; + else if (SYNC_PULSE_VDO_MODE == lcm_dsi_mode || + SYNC_EVENT_VDO_MODE == lcm_dsi_mode || + BURST_VDO_MODE == lcm_dsi_mode) + _dsi_context[0].dsi_params.PLL_CLOCK = _dsi_context[0].dsi_params.PLL_CK_VDO; + } + } +} diff --git a/drivers/misc/mediatek/video/mt6755/ddp_dsi.h b/drivers/misc/mediatek/video/mt6755/ddp_dsi.h new file mode 100644 index 0000000000000000000000000000000000000000..1b039810ef8d4fbfc3d46a6b82db70029936fdbe --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_dsi.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DSI_DRV_H__ +#define __DSI_DRV_H__ + + +#include + +#include "lcm_drv.h" +#include "ddp_hal.h" +#include "fbconfig_kdebug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* --------------------------------------------------------------------------- */ + +#define DSI_CHECK_RET(expr) \ + do { \ + DSI_STATUS ret = (expr); \ + ASSERT(DSI_STATUS_OK == ret); \ + } while (0) + +/* --------------------------------------------------------------------------- */ + +#define DSI_DCS_SHORT_PACKET_ID_0 0x05 +#define DSI_DCS_SHORT_PACKET_ID_1 0x15 +#define DSI_DCS_LONG_PACKET_ID 0x39 +#define DSI_DCS_READ_PACKET_ID 0x06 + +#define DSI_GERNERIC_SHORT_PACKET_ID_1 0x13 +#define DSI_GERNERIC_SHORT_PACKET_ID_2 0x23 +#define DSI_GERNERIC_LONG_PACKET_ID 0x29 +#define DSI_GERNERIC_READ_LONG_PACKET_ID 0x14 + + +#define DSI_WMEM_CONTI (0x3C) +#define DSI_RMEM_CONTI (0x3E) + +/* ESD recovery method for video mode LCM */ +#define METHOD_NONCONTINUOUS_CLK (0x1) +#define METHOD_BUS_TURN_AROUND (0x2) + +/* State of DSI engine */ +#define DSI_VDO_VSA_VS_STATE (0x008) +#define DSI_VDO_VSA_HS_STATE (0x010) +#define DSI_VDO_VSA_VE_STATE (0x020) +#define DSI_VDO_VBP_STATE (0x040) +#define DSI_VDO_VACT_STATE (0x080) +#define DSI_VDO_VFP_STATE (0x100) + +/* --------------------------------------------------------------------------- */ + + typedef enum { + DSI_STATUS_OK = 0, + + DSI_STATUS_ERROR, + } DSI_STATUS; + + + typedef enum { + SHORT_PACKET_RW = 0, + FB_WRITE = 1, + LONG_PACKET_W = 2, + FB_READ = 3, + } DSI_INS_TYPE; + + + typedef enum { + DISABLE_BTA = 0, + ENABLE_BTA = 1, + } DSI_CMDQ_BTA; + + + typedef enum { + LOW_POWER = 0, + HIGH_SPEED = 1, + } DSI_CMDQ_HS; + + + typedef enum { + CL_8BITS = 0, + CL_16BITS = 1, + } DSI_CMDQ_CL; + + + typedef enum { + DISABLE_TE = 0, + ENABLE_TE = 1, + } DSI_CMDQ_TE; + + + typedef enum { + DISABLE_RPT = 0, + ENABLE_RPT = 1, + } DSI_CMDQ_RPT; + + + typedef struct { + unsigned type:2; + unsigned BTA:1; + unsigned HS:1; + unsigned CL:1; + unsigned TE:1; + unsigned Rsv:1; + unsigned RPT:1; + } DSI_CMDQ_CONFG, *PDSI_CMDQ_CONFIG; + + + typedef struct { + unsigned CONFG:8; + unsigned Data_ID:8; + unsigned Data0:8; + unsigned Data1:8; + } DSI_T0_INS, *PDSI_T0_INS; + + typedef struct { + unsigned CONFG:8; + unsigned Data_ID:8; + unsigned mem_start0:8; + unsigned mem_start1:8; + } DSI_T1_INS, *PDSI_T1_INS; + + typedef struct { + unsigned CONFG:8; + unsigned Data_ID:8; + unsigned WC16:16; + unsigned int *pdata; + } DSI_T2_INS, *PDSI_T2_INS; + + typedef struct { + unsigned CONFG:8; + unsigned Data_ID:8; + unsigned mem_start0:8; + unsigned mem_start1:8; + } DSI_T3_INS, *PDSI_T3_INS; + + typedef struct { + uint8_t TXDIV0; + uint8_t TXDIV1; + uint32_t SDM_PCW; + uint8_t SSC_PH_INIT; + uint16_t SSC_PRD; + uint16_t SSC_DELTA1; + uint16_t SSC_DELTA; + } DSI_PLL_CONFIG; + + typedef enum { + DSI_INTERFACE_0 = 0, + DSI_INTERFACE_1, + DSI_INTERFACE_DUAL, + DSI_INTERFACE_NUM, + } DSI_INTERFACE_ID; + + typedef enum { + DSI_VFP = 0, + DSI_VSA, + DSI_VBP, + DSI_VACT, + DSI_HFP, + DSI_HSA, + DSI_HBP, + DSI_BLLP, + DSI_PORCH_NUM, + } DSI_PORCH_TYPE; + + extern const LCM_UTIL_FUNCS PM_lcm_utils_dsi0; + /* defined in mtkfb.c */ + extern bool is_ipoh_bootup; + + + void DSI_ChangeClk(DISP_MODULE_ENUM module, uint32_t clk); + int32_t DSI_ssc_enable(uint32_t dsi_idx, uint32_t en); + uint32_t PanelMaster_get_CC(uint32_t dsi_idx); + void PanelMaster_set_CC(uint32_t dsi_index, uint32_t enable); + uint32_t PanelMaster_get_dsi_timing(uint32_t dsi_index, MIPI_SETTING_TYPE type); + uint32_t PanelMaster_get_TE_status(uint32_t dsi_idx); + void PanelMaster_DSI_set_timing(uint32_t dsi_index, MIPI_TIMING timing); + unsigned int PanelMaster_set_PM_enable(unsigned int value); + uint32_t DSI_dcs_read_lcm_reg_v2(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, uint8_t cmd, + uint8_t *buffer, uint8_t buffer_size); + void *get_dsi_params_handle(uint32_t dsi_idx); + void dsi_analysis(DISP_MODULE_ENUM module); + void DSI_LFR_UPDATE(DISP_MODULE_ENUM module, cmdqRecHandle cmdq); + void DSI_Set_LFR(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, unsigned int mode, + unsigned int type, unsigned int enable, unsigned int skip_num); + DSI_STATUS DSI_BIST_Pattern_Test(DISP_MODULE_ENUM module, cmdqRecHandle cmdq, bool enable, unsigned int color); + int ddp_dsi_start(DISP_MODULE_ENUM module, void *cmdq); + DSI_STATUS DSI_DumpRegisters(DISP_MODULE_ENUM module, int level); + void DSI_ForceConfig(int forceconfig); + int DSI_set_roi(int x, int y); + int DSI_check_roi(void); + int dsi_enable_irq(DISP_MODULE_ENUM module, void *handle, unsigned int enable); + +#ifdef __cplusplus +} +#endif +#endif /* __DPI_DRV_H__ */ diff --git a/drivers/misc/mediatek/video/mt6755/ddp_dump.c b/drivers/misc/mediatek/video/mt6755/ddp_dump.c new file mode 100644 index 0000000000000000000000000000000000000000..8e9554a23007e4aead62ae9d2253b96d2af07276 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_dump.c @@ -0,0 +1,989 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "dump" +#include "ddp_reg.h" +#include "disp_log.h" +#include "ddp_dump.h" +#include "ddp_ovl.h" +#include "ddp_wdma.h" +#include "ddp_rdma.h" +#include "ddp_dsi.h" +#include + +static char *ddp_signal_0(int bit) +{ + switch (bit) { + case 31: + return "dpi0_sel_to_dpi0"; + case 30: + return "dis0_sel_to_dsi0"; + case 29: + return "rdma1_sout1_to_dpi0_sin2"; + case 28: + return "rdma1_sout0_to_dsi0_sin2"; + case 27: + return "rdma1_to_rdma1_sout"; + /* case 26: return "bit26-unused"; */ + case 25: + return "ovl1_mout1_to_wdma1"; + case 24: + return "ovl1_mout0_to_rdma1"; + case 23: + return "ovl1_to_ovl1_mout"; + case 22: + return "wdma0_sel_to_wdma0"; + case 21: + return "ufoe_mout2_to_wdma0_sin2"; + case 20: + return "ufoe_mout1_to_dpi0_sin0"; + case 19: + return "ufoe_mout0_to_dsi0_sin0"; + case 18: + return "ufoe_to_ufoe_mout"; + case 17: + return "ufoe_sel_to_ufoe"; + case 16: + return "rdma0_sout3_to_dpi0_sin1"; + case 15: + return "rdma0_sout2_to_dsi0_sin1"; + case 14: + return "rdma0_sout1_to_color_sin0"; + case 13: + return "rdma0_sout0_to_ufoe_sin0"; + case 12: + return "rdma0_to_rdma0_sout"; + case 11: + return "dither_mout2_to_wdma0_sin1"; + case 10: + return "dither_mout1_to_ufoe_sin1"; + case 9: + return "dither_mout0_to_rdma0"; + case 8: + return "dither_to_dither_mout"; + /* case 7: return "bit7-unused"; */ + case 6: + return "aal_to_gamma"; + case 5: + return "ccorr_to_aal"; + case 4: + return "color_to_ccorr"; + case 3: + return "color_sel_to_color"; + case 2: + return "ovl0_mout1_to_wdma0_sin0"; + case 1: + return "ovl0_mout0_to_color_sin1"; + /* case 0: return "bit0-unused"; */ + default: + return NULL; + } +} + +static char *ddp_signal_1(int bit) +{ + switch (bit) { + case 15: + return "ovl0_sel_to_ovl0_mout"; + case 14: + return "ovl1_mout2_to_ovl0_sel"; + case 13: + return "ovl1_sout1_to_ovl0_sel"; + case 12: + return "ovl1_sout0_to_ovl1_4L"; + case 11: + return "ovl1_2L_to_ovl1_sout"; + case 10: + return "ovl0_sout1_to_ovl1_2L"; + case 9: + return "ovl0_sout0_to_ovl0_sel"; + case 8: + return "ovl0_to_ovl0_sout"; + default: + return NULL; + } +} + +static char *ddp_greq_name(int bit) +{ + switch (bit) { + case 10: + return "mdp_wrot"; + case 9: + return "mdp_wdma"; + case 8: + return "mdp_rdma"; + case 7: + return "ovl1_2L"; + case 6: + return "ovl0_2L"; + case 5: + return "wdma1"; + case 4: + return "rdma1"; + case 3: + return "ovl1"; + case 2: + return "wdma0"; + case 1: + return "rdma0"; + case 0: + return "ovl0"; + default: + return NULL; + } +} + +static char *ddp_get_mutex_module_name(unsigned int bit) +{ + switch (bit) { + case 7: + return "ovl0"; + case 8: + return "ovl1"; + case 9: + return "rdma0"; + case 10: + return "rdma1"; + case 11: + return "wdma0"; + case 12: + return "color0"; + case 13: + return "ccorr"; + case 14: + return "aal"; + case 15: + return "gamma"; + case 16: + return "dither"; + case 17: + return "wdma1"; + case 18: + return "pwm0"; + case 19: + return "ovl0_2l"; + case 20: + return "ovl1_2l"; + default: + return "mutex-unknown"; + } +} + +char *ddp_get_fmt_name(DISP_MODULE_ENUM module, unsigned int fmt) +{ + if (module == DISP_MODULE_WDMA0) { + switch (fmt) { + case 0: + return "rgb565"; + case 1: + return "rgb888"; + case 2: + return "rgba8888"; + case 3: + return "argb8888"; + case 4: + return "uyvy"; + case 5: + return "yuy2"; + case 7: + return "y-only"; + case 8: + return "iyuv"; + case 12: + return "nv12"; + default: + DISPDMP("ddp_get_fmt_name, unknown fmt=%d, module=%d\n", fmt, module); + return "unknown"; + } + } else if (module == DISP_MODULE_OVL0) { + switch (fmt) { + case 0: + return "rgb565"; + case 1: + return "rgb888"; + case 2: + return "rgba8888"; + case 3: + return "argb8888"; + case 4: + return "uyvy"; + case 5: + return "yuyv"; + default: + DISPDMP("ddp_get_fmt_name, unknown fmt=%d, module=%d\n", fmt, module); + return "unknown"; + } + } else if (module == DISP_MODULE_RDMA0 || module == DISP_MODULE_RDMA1 || module == DISP_MODULE_RDMA2) { + switch (fmt) { + case 0: + return "rgb565"; + case 1: + return "rgb888"; + case 2: + return "rgba8888"; + case 3: + return "argb8888"; + case 4: + return "uyvy"; + case 5: + return "yuyv"; + default: + DISPDMP("ddp_get_fmt_name, unknown fmt=%d, module=%d\n", fmt, module); + return "unknown"; + } + } else { + DISPDMP("ddp_get_fmt_name, unknown module=%d\n", module); + } + + return "unknown"; +} + +static char *ddp_clock_0(int bit) +{ + switch (bit) { + case 0: + return "smi_common, "; + case 1: + return "smi_larb0, "; + case 10: + return "ovl0, "; + case 11: + return "ovl1, "; + case 12: + return "rdma0, "; + case 13: + return "rdma1, "; + case 14: + return "wdma0, "; + case 15: + return "color, "; + case 16: + return "ccorr, "; + case 17: + return "aal, "; + case 18: + return "gamma, "; + case 19: + return "dither, "; + case 21: + return "ufoe_mout, "; + case 22: + return "wdma1, "; + case 23: + return "ovl0_2L, "; + case 24: + return "ovl1_2L, "; + case 25: + return "ovl0_mout, "; + default: + return NULL; + } +} + +static char *ddp_clock_1(int bit) +{ + switch (bit) { + case 0: + return "dsi_engine, "; + case 1: + return "dsi_digital, "; + case 2: + return "dpi_pixel, "; + case 3: + return "dpi_engine, "; + default: + return NULL; + } +} + +static void mutex_dump_reg(void) +{ + DISPDMP("== START: DISP MUTEX REGS ==\n"); + DISPDMP("(0x000)M_INTEN =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX_INTEN)); + DISPDMP("(0x004)M_INTSTA =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX_INTSTA)); + DISPDMP("(0x020)M0_EN =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX0_EN)); + DISPDMP("(0x028)M0_RST =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX0_RST)); + DISPDMP("(0x02c)M0_MOD =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX0_MOD)); + DISPDMP("(0x030)M0_SOF =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX0_SOF)); + DISPDMP("(0x040)M1_EN =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX1_EN)); + DISPDMP("(0x048)M1_RST =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX1_RST)); + DISPDMP("(0x04c)M1_MOD =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX1_MOD)); + DISPDMP("(0x050)M1_SOF =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX1_SOF)); + DISPDMP("(0x060)M2_EN =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX2_EN)); + DISPDMP("(0x068)M2_RST =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX2_RST)); + DISPDMP("(0x06c)M2_MOD =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX2_MOD)); + DISPDMP("(0x070)M2_SOF =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX2_SOF)); + DISPDMP("(0x080)M3_EN =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX3_EN)); + DISPDMP("(0x088)M3_RST =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX3_RST)); + DISPDMP("(0x08c)M3_MOD =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX3_MOD)); + DISPDMP("(0x090)M3_SOF =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX3_SOF)); + DISPDMP("(0x0a0)M4_EN =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX4_EN)); + DISPDMP("(0x0a8)M4_RST =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX4_RST)); + DISPDMP("(0x0ac)M4_MOD =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX4_MOD)); + DISPDMP("(0x0b0)M4_SOF =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX4_SOF)); + DISPDMP("(0x0c0)M5_EN =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX5_EN)); + DISPDMP("(0x0c8)M5_RST =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX5_RST)); + DISPDMP("(0x0cc)M5_MOD =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX5_MOD)); + DISPDMP("(0x0d0)M5_SOF =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MUTEX5_SOF)); + DISPDMP("(0x200)DEBUG_OUT_SEL =0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_DEBUG_OUT_SEL)); + DISPDMP("-- END: DISP MUTEX REGS --\n"); +} + + +static void mutex_dump_analysis(void) +{ + int i = 0; + int j = 0; + char *mutex_module; + char *p = NULL; + int len = 0; + unsigned int val; + unsigned int regval; + + mutex_module = kzalloc(512, GFP_ATOMIC); + if (!mutex_module) { + DISPDMP("%s fail because of no memory\n", __func__); + return; + } + + DISPDMP("==DISP Mutex Analysis==\n"); + for (i = 0; i < 5; i++) { + p = mutex_module; + len = 0; + if (DISP_REG_GET(DISP_REG_CONFIG_MUTEX_MOD(i)) == 0) + continue; + + val = DISP_REG_GET(DISP_REG_CONFIG_MUTEX_SOF(i)); + len = sprintf(p, "MUTEX%d :SOF=%s,EOF=%s,WAIT=%d,module=(", i, + ddp_get_mutex_sof_name(REG_FLD_VAL_GET(SOF_FLD_MUTEX0_SOF, val)), + ddp_get_mutex_sof_name(REG_FLD_VAL_GET(SOF_FLD_MUTEX0_EOF, val)), + REG_FLD_VAL_GET(SOF_FLD_MUTEX0_EOF_WAIT, val)); + + p += len; + regval = DISP_REG_GET(DISP_REG_CONFIG_MUTEX_MOD(i)); + + for (j = 0; j < 32; j++) { + if ((regval & (1 << j))) { + len = sprintf(p, "%s,", ddp_get_mutex_module_name(j)); + p += len; + } + } + DISPDMP("%s)\n", mutex_module); + } + kfree(mutex_module); +} + +static void mmsys_config_dump_reg(void) +{ + DISPDMP("== START: DISP MMSYS_CONFIG REGS ==\n"); + DISPDMP("MMSYS:0x000=0x%08x,0x004=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_INTEN), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_INTSTA)); + DISPDMP("MMSYS:0x030=0x%08x,0x034=0x%08x,0x038=0x%08x,0x03C=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_DISP_OVL0_MOUT_EN), + DISP_REG_GET(DISP_REG_CONFIG_DISP_OVL1_MOUT_EN), + DISP_REG_GET(DISP_REG_CONFIG_DISP_DITHER_MOUT_EN), + DISP_REG_GET(DISP_REG_CONFIG_DISP_UFOE_MOUT_EN)); + DISPDMP("MMSYS:0x040=0x%08x,0x058=0x%08x,0x05C=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_MOUT_RST), + DISP_REG_GET(DISP_REG_CONFIG_DISP_COLOR0_SEL_IN), + DISP_REG_GET(DISP_REG_CONFIG_DISP_WDMA0_SEL_IN)); + DISPDMP("MMSYS:0x060=0x%08x,0x064=0x%08x,0x068=0x%08x,0x06C=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_DISP_UFOE_SEL_IN), + DISP_REG_GET(DISP_REG_CONFIG_DSI0_SEL_IN), + DISP_REG_GET(DISP_REG_CONFIG_DPI0_SEL_IN), + DISP_REG_GET(DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN)); + DISPDMP("MMSYS:0x070=0x%08x,0x074=0x%08x,0x078=0x%08x,0x07C=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN), + DISP_REG_GET(DISP_REG_CONFIG_DISP_OVL0_SOUT_SEL_IN), + DISP_REG_GET(DISP_REG_CONFIG_DISP_OVL0_SEL_IN), + DISP_REG_GET(DISP_REG_CONFIG_DISP_OVL1_SOUT_SEL_IN)); + DISPDMP("MMSYS:0x0F0=0x%08x,0x100=0x%08x,0x110=0x%08x,0x120=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_MISC), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON1), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_HW_DCM_DIS0)); + DISPDMP("MMSYS:0x130=0x%08x,0x140=0x%08x,0x144=0x%08x,0x150=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_HW_DCM_DIS1), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_SW0_RST_B), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_SW1_RST_B), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_LCM_RST_B)); + DISPDMP("MMSYS:0x880=0x%08x,0x890=0x%08x,0x894=0x%08x,0x898=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_DEBUG_OUT_SEL), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_DUMMY0), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_DUMMY1), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_DUMMY2)); + DISPDMP("MMSYS:0x89c=0x%08x,0x8a0=0x%08x,0x8a4=0x%08x,0x8a8=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_DUMMY3), + DISP_REG_GET(DISP_REG_CONFIG_DISP_DL_VALID_0), + DISP_REG_GET(DISP_REG_CONFIG_DISP_DL_VALID_1), + DISP_REG_GET(DISP_REG_CONFIG_DISP_DL_READY_0)); + DISPDMP("MMSYS:0x8ac=0x%08x\n", + DISP_REG_GET(DISP_REG_CONFIG_DISP_DL_READY_1)); + DISPDMP("-- END: DISP MMSYS_CONFIG REGS --\n"); +} + +/* ------ clock: +Before power on mmsys: +CLK_CFG_0_CLR (address is 0x10000048) = 0x80000000 (bit 31). +Before using DISP_PWM0 or DISP_PWM1: +CLK_CFG_1_CLR(address is 0x10000058)=0x80 (bit 7). +Before using DPI pixel clock: +CLK_CFG_6_CLR(address is 0x100000A8)=0x80 (bit 7). + +Only need to enable the corresponding bits of MMSYS_CG_CON0 and MMSYS_CG_CON1 for the modules: +smi_common, larb0, mdp_crop, fake_eng, mutex_32k, pwm0, pwm1, dsi0, dsi1, dpi. +Other bits could keep 1. Suggest to keep smi_common and larb0 always clock on. + +--------valid & ready +example: +ovl0 -> ovl0_mout_ready=1 means engines after ovl_mout are ready for receiving data + ovl0_mout_ready=0 means ovl0_mout can not receive data, maybe ovl0_mout or after engines config error +ovl0 -> ovl0_mout_valid=1 means engines before ovl0_mout is OK, + ovl0_mout_valid=0 means ovl can not transfer data to ovl0_mout, means ovl0 or before engines are not ready. +*/ + +static void mmsys_config_dump_analysis(void) +{ + unsigned int i = 0; + unsigned int reg = 0; + char *clock_on; + char *pos = NULL; + char *name; + + unsigned int valid0 = DISP_REG_GET(DISP_REG_CONFIG_DISP_DL_VALID_0); + unsigned int valid1 = DISP_REG_GET(DISP_REG_CONFIG_DISP_DL_VALID_1); + unsigned int ready0 = DISP_REG_GET(DISP_REG_CONFIG_DISP_DL_READY_0); + unsigned int ready1 = DISP_REG_GET(DISP_REG_CONFIG_DISP_DL_READY_1); + unsigned int greq = DISP_REG_GET(DISP_REG_CONFIG_SMI_LARB0_GREQ); + + DISPDMP("==DISP MMSYS_CONFIG ANALYSIS==\n"); + DISPDMP("mmsys clock=0x%x, CG_CON0=0x%x, CG_CON1=0x%x\n", + DISP_REG_GET(DISP_REG_CLK_CFG_0_MM_CLK), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0), + DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON1)); + if ((DISP_REG_GET(DISP_REG_CLK_CFG_0_MM_CLK) >> 31) & 0x1) + DISPERR("mmsys clock abnormal!!\n"); + +#define CLOCK_ON_SIZE 512 + clock_on = kzalloc(CLOCK_ON_SIZE, GFP_ATOMIC); + if (!clock_on) + return; + + reg = DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0); + for (i = 0; i < 32; i++) { + if ((reg & (1 << i)) == 0) { + name = ddp_clock_0(i); + if (name) + strncat(clock_on, name, CLOCK_ON_SIZE); + } + } + + reg = DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON1); + for (i = 0; i < 32; i++) { + if ((reg & (1 << i)) == 0) { + name = ddp_clock_1(i); + if (name) + strncat(clock_on, name, CLOCK_ON_SIZE); + } + } + DISPDMP("clock on modules:%s\n", clock_on); + + DISPDMP("valid0=0x%x, valid1=0x%x, ready0=0x%x, ready1=0x%x, greq=0x%x\n", + valid0, valid1, ready0, ready1, greq); + for (i = 0; i < 32; i++) { + name = ddp_signal_0(i); + if (!name) + continue; + + pos = clock_on; + pos += sprintf(pos, "%25s: ", name); + + if ((valid0 & (1 << i))) + pos += sprintf(pos, "%10s,", "valid"); + else + pos += sprintf(pos, "%10s,", "not valid"); + + if ((ready0 & (1 << i))) + pos += sprintf(pos, "%10s", "ready"); + else + pos += sprintf(pos, "%10s", "not ready"); + + DISPDMP("%s\n", clock_on); + } + + for (i = 0; i < 32; i++) { + name = ddp_signal_1(i); + if (!name) + continue; + + pos = clock_on; + pos += sprintf(pos, "%25s: ", name); + + if ((valid1 & (1 << i))) + pos += sprintf(pos, "%10s,", "valid"); + else + pos += sprintf(pos, "%10s,", "not valid"); + + if ((ready1 & (1 << i))) + pos += sprintf(pos, "%10s", "ready"); + else + pos += sprintf(pos, "%10s", "not ready"); + + DISPDMP("%s\n", clock_on); + } + + /* greq: 1 means SMI dose not grant, maybe SMI hang */ + if (greq) + DISPMSG("smi greq not grant module: (greq: 1 means SMI dose not grant, maybe SMI hang)"); + + clock_on[0] = '\0'; + for (i = 0; i < 32; i++) { + if (greq & (1 << i)) { + name = ddp_greq_name(i); + if (!name) + continue; + strncat(clock_on, name, CLOCK_ON_SIZE); + } + } + DISPDMP("%s\n", clock_on); + + kfree(clock_on); + +} + +static void gamma_dump_reg(void) +{ + DISPDMP("== START: DISP GAMMA REGS ==\n"); + DISPDMP("(0x000)GA_EN =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_EN)); + DISPDMP("(0x004)GA_RESET =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_RESET)); + DISPDMP("(0x008)GA_INTEN =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_INTEN)); + DISPDMP("(0x00c)GA_INTSTA =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_INTSTA)); + DISPDMP("(0x010)GA_STATUS =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_STATUS)); + DISPDMP("(0x020)GA_CFG =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_CFG)); + DISPDMP("(0x024)GA_IN_COUNT =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_INPUT_COUNT)); + DISPDMP("(0x028)GA_OUT_COUNT =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_OUTPUT_COUNT)); + DISPDMP("(0x02c)GA_CHKSUM =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_CHKSUM)); + DISPDMP("(0x030)GA_SIZE =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_SIZE)); + DISPDMP("(0x0c0)GA_DUMMY_REG =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_DUMMY_REG)); + DISPDMP("(0x800)GA_LUT =0x%x\n", DISP_REG_GET(DISP_REG_GAMMA_LUT)); + DISPDMP("-- END: DISP GAMMA REGS --\n"); +} + +static void gamma_dump_analysis(void) +{ + DISPDMP("==DISP GAMMA ANALYSIS==\n"); + DISPDMP("gamma: en=%d, w=%d, h=%d, in_p_cnt=%d, in_l_cnt=%d, out_p_cnt=%d, out_l_cnt=%d\n", + DISP_REG_GET(DISP_REG_GAMMA_EN), + (DISP_REG_GET(DISP_REG_GAMMA_SIZE) >> 16) & 0x1fff, + DISP_REG_GET(DISP_REG_GAMMA_SIZE) & 0x1fff, + DISP_REG_GET(DISP_REG_GAMMA_INPUT_COUNT) & 0x1fff, + (DISP_REG_GET(DISP_REG_GAMMA_INPUT_COUNT) >> 16) & 0x1fff, + DISP_REG_GET(DISP_REG_GAMMA_OUTPUT_COUNT) & 0x1fff, + (DISP_REG_GET(DISP_REG_GAMMA_OUTPUT_COUNT) >> 16) & 0x1fff); +} + +static void merge_dump_reg(void) +{ + DISPDMP("== START: DISP MERGE REGS ==\n"); + DISPDMP("(0x000)MERGE_EN =0x%x\n", DISP_REG_GET(DISP_REG_MERGE_ENABLE)); + DISPDMP("(0x004)MERGE_SW_RESET =0x%x\n", DISP_REG_GET(DISP_REG_MERGE_SW_RESET)); + DISPDMP("(0x008)MERGE_DEBUG =0x%x\n", DISP_REG_GET(DISP_REG_MERGE_DEBUG)); + DISPDMP("-- END: DISP MERGE REGS --\n"); +} + +static void merge_dump_analysis(void) +{ + DISPDMP("==DISP MERGE ANALYSIS==\n"); + DISPDMP("merge: en=%d, debug=0x%x\n", DISP_REG_GET(DISP_REG_MERGE_ENABLE), + DISP_REG_GET(DISP_REG_MERGE_DEBUG)); +} + +static void split_dump_reg(DISP_MODULE_ENUM module) +{ + DISPDMP("error: disp_split dose not exist! module=%d\n", module); +} + +static void split_dump_analysis(DISP_MODULE_ENUM module) +{ + DISPDMP("error: disp_split dose not exist! module=%d\n", module); +} + +static void color_dump_reg(DISP_MODULE_ENUM module) +{ + int index = 0; + + if (DISP_MODULE_COLOR0 == module) { + index = 0; + } else if (DISP_MODULE_COLOR1 == module) { + DISPDMP("error: DISP COLOR%d dose not exist!\n", index); + return; + } + DISPDMP("== START: DISP COLOR%d REGS ==\n", index); + DISPDMP("(0x400)COLOR_CFG_MAIN =0x%x\n", DISP_REG_GET(DISP_COLOR_CFG_MAIN)); + DISPDMP("(0x404)COLOR_PXL_CNT_MAIN =0x%x\n", DISP_REG_GET(DISP_COLOR_PXL_CNT_MAIN)); + DISPDMP("(0x408)COLOR_LINE_CNT_MAIN =0x%x\n", DISP_REG_GET(DISP_COLOR_LINE_CNT_MAIN)); + DISPDMP("(0xc00)COLOR_START =0x%x\n", DISP_REG_GET(DISP_COLOR_START)); + DISPDMP("(0xc28)DISP_COLOR_CK_ON =0x%x\n", DISP_REG_GET(DISP_COLOR_CK_ON)); + DISPDMP("(0xc50)COLOR_INTER_IP_W =0x%x\n", DISP_REG_GET(DISP_COLOR_INTERNAL_IP_WIDTH)); + DISPDMP("(0xc54)COLOR_INTER_IP_H =0x%x\n", DISP_REG_GET(DISP_COLOR_INTERNAL_IP_HEIGHT)); + DISPDMP("-- END: DISP COLOR%d REGS --\n", index); +} + +static void color_dump_analysis(DISP_MODULE_ENUM module) +{ + int index = 0; + + if (DISP_MODULE_COLOR0 == module) { + index = 0; + } else if (DISP_MODULE_COLOR1 == module) { + DISPDMP("error: DISP COLOR%d dose not exist!\n", index); + return; + } + DISPDMP("==DISP COLOR%d ANALYSIS==\n", index); + DISPDMP("color%d: bypass=%d, w=%d, h=%d, pixel_cnt=%d, line_cnt=%d,\n", + index, + (DISP_REG_GET(DISP_COLOR_CFG_MAIN) >> 7) & 0x1, + DISP_REG_GET(DISP_COLOR_INTERNAL_IP_WIDTH), + DISP_REG_GET(DISP_COLOR_INTERNAL_IP_HEIGHT), + DISP_REG_GET(DISP_COLOR_PXL_CNT_MAIN) & 0xffff, + (DISP_REG_GET(DISP_COLOR_LINE_CNT_MAIN) >> 16) & 0x1fff); + +} + +static void aal_dump_reg(void) +{ + DISPDMP("== START: DISP AAL REGS ==\n"); + DISPDMP("(0x000)AAL_EN =0x%x\n", DISP_REG_GET(DISP_AAL_EN)); + DISPDMP("(0x008)AAL_INTEN =0x%x\n", DISP_REG_GET(DISP_AAL_INTEN)); + DISPDMP("(0x00c)AAL_INTSTA =0x%x\n", DISP_REG_GET(DISP_AAL_INTSTA)); + DISPDMP("(0x020)AAL_CFG =0x%x\n", DISP_REG_GET(DISP_AAL_CFG)); + DISPDMP("(0x024)AAL_IN_CNT =0x%x\n", DISP_REG_GET(DISP_AAL_IN_CNT)); + DISPDMP("(0x028)AAL_OUT_CNT =0x%x\n", DISP_REG_GET(DISP_AAL_OUT_CNT)); + DISPDMP("(0x030)AAL_SIZE =0x%x\n", DISP_REG_GET(DISP_AAL_SIZE)); + DISPDMP("(0x20c)AAL_CABC_00 =0x%x\n", DISP_REG_GET(DISP_AAL_CABC_00)); + DISPDMP("(0x214)AAL_CABC_02 =0x%x\n", DISP_REG_GET(DISP_AAL_CABC_02)); + DISPDMP("(0x20c)AAL_STATUS_00 =0x%x\n", DISP_REG_GET(DISP_AAL_STATUS_00)); + DISPDMP("(0x210)AAL_STATUS_01 =0x%x\n", DISP_REG_GET(DISP_AAL_STATUS_00 + 0x4)); + DISPDMP("(0x2a0)AAL_STATUS_31 =0x%x\n", DISP_REG_GET(DISP_AAL_STATUS_32 - 0x4)); + DISPDMP("(0x2a4)AAL_STATUS_32 =0x%x\n", DISP_REG_GET(DISP_AAL_STATUS_32)); + DISPDMP("(0x3b0)AAL_DRE_MAPPING_00 =0x%x\n", DISP_REG_GET(DISP_AAL_DRE_MAPPING_00)); + DISPDMP("-- END: DISP AAL REGS --\n"); +} + +static void aal_dump_analysis(void) +{ + DISPDMP("==DISP AAL ANALYSIS==\n"); + DISPDMP("aal: bypass=%d, relay=%d, en=%d, w=%d, h=%d, in(%d,%d),out(%d,%d)\n", + DISP_REG_GET(DISP_AAL_EN) == 0x0, + DISP_REG_GET(DISP_AAL_CFG) & 0x01, + DISP_REG_GET(DISP_AAL_EN), + (DISP_REG_GET(DISP_AAL_SIZE) >> 16) & 0x1fff, + DISP_REG_GET(DISP_AAL_SIZE) & 0x1fff, + DISP_REG_GET(DISP_AAL_IN_CNT) & 0x1fff, + (DISP_REG_GET(DISP_AAL_IN_CNT) >> 16) & 0x1fff, + DISP_REG_GET(DISP_AAL_OUT_CNT) & 0x1fff, + (DISP_REG_GET(DISP_AAL_OUT_CNT) >> 16) & 0x1fff); +} + +static void pwm_dump_reg(DISP_MODULE_ENUM module) +{ + int index = 0; + unsigned long reg_base = 0; + + if (module == DISP_MODULE_PWM0) { + index = 0; + reg_base = DISPSYS_PWM0_BASE; + } else { + index = 1; + reg_base = DISPSYS_PWM1_BASE; + } + DISPDMP("== START: DISP PWM%d REGS ==\n", index); + DISPDMP("(0x000)PWM_EN =0x%x\n", DISP_REG_GET(reg_base + DISP_PWM_EN_OFF)); + DISPDMP("(0x008)PWM_CON_0 =0x%x\n", DISP_REG_GET(reg_base + DISP_PWM_CON_0_OFF)); + DISPDMP("(0x010)PWM_CON_1 =0x%x\n", DISP_REG_GET(reg_base + DISP_PWM_CON_1_OFF)); + DISPDMP("(0x028)PWM_DEBUG =0x%x\n", DISP_REG_GET(reg_base + 0x28)); + DISPDMP("-- END: DISP PWM%d REGS --\n", index); +} + +static void pwm_dump_analysis(DISP_MODULE_ENUM module) +{ + int index = 0; + unsigned int reg_base = 0; + + if (module == DISP_MODULE_PWM0) { + index = 0; + reg_base = DISPSYS_PWM0_BASE; + } else { + index = 1; + reg_base = DISPSYS_PWM1_BASE; + } + DISPDMP("==DISP PWM%d ANALYSIS==\n", index); + DISPDMP("pwm clock=%d\n", (DISP_REG_GET(DISP_REG_CLK_CFG_1_CLR) >> 7) & 0x1); + +} + +static void od_dump_reg(void) +{ + DISPDMP("== START: DISP OD REGS ==\n"); + DISPDMP("(00)EN =0x%x\n", DISP_REG_GET(DISP_REG_OD_EN)); + DISPDMP("(04)RESET =0x%x\n", DISP_REG_GET(DISP_REG_OD_RESET)); + DISPDMP("(08)INTEN =0x%x\n", DISP_REG_GET(DISP_REG_OD_INTEN)); + DISPDMP("(0C)INTSTA =0x%x\n", DISP_REG_GET(DISP_REG_OD_INTSTA)); + DISPDMP("(10)STATUS =0x%x\n", DISP_REG_GET(DISP_REG_OD_STATUS)); + DISPDMP("(20)CFG =0x%x\n", DISP_REG_GET(DISP_REG_OD_CFG)); + DISPDMP("(24)INPUT_COUNT =0x%x\n", DISP_REG_GET(DISP_REG_OD_INPUT_COUNT)); + DISPDMP("(28)OUTPUT_COUNT =0x%x\n", DISP_REG_GET(DISP_REG_OD_OUTPUT_COUNT)); + DISPDMP("(2C)CHKSUM =0x%x\n", DISP_REG_GET(DISP_REG_OD_CHKSUM)); + DISPDMP("(30)SIZE =0x%x\n", DISP_REG_GET(DISP_REG_OD_SIZE)); + DISPDMP("(40)HSYNC_WIDTH =0x%x\n", DISP_REG_GET(DISP_REG_OD_HSYNC_WIDTH)); + DISPDMP("(44)VSYNC_WIDTH =0x%x\n", DISP_REG_GET(DISP_REG_OD_VSYNC_WIDTH)); + DISPDMP("(48)MISC =0x%x\n", DISP_REG_GET(DISP_REG_OD_MISC)); + DISPDMP("(C0)DUMMY_REG =0x%x\n", DISP_REG_GET(DISP_REG_OD_DUMMY_REG)); + DISPDMP("-- END: DISP OD REGS --\n"); +} + +static void od_dump_analysis(void) +{ + DISPDMP("==DISP OD ANALYSIS==\n"); + DISPDMP("od: w=%d, h=%d, bypass=%d\n", + (DISP_REG_GET(DISP_REG_OD_SIZE) >> 16) & 0xffff, + DISP_REG_GET(DISP_REG_OD_SIZE) & 0xffff, DISP_REG_GET(DISP_REG_OD_CFG) & 0x1); + +} + +static void ccorr_dump_reg(void) +{ + DISPDMP("== START: DISP CCORR REGS ==\n"); + DISPDMP("(00)EN =0x%x\n", DISP_REG_GET(DISP_REG_CCORR_EN)); + DISPDMP("(20)CFG =0x%x\n", DISP_REG_GET(DISP_REG_CCORR_CFG)); + DISPDMP("(24)IN_CNT =0x%x\n", DISP_REG_GET(DISP_REG_CCORR_IN_CNT)); + DISPDMP("(28)OUT_CNT =0x%x\n", DISP_REG_GET(DISP_REG_CCORR_OUT_CNT)); + DISPDMP("(30)SIZE =0x%x\n", DISP_REG_GET(DISP_REG_CCORR_SIZE)); + DISPDMP("-- END: DISP CCORR REGS --\n"); +} + +static void ccorr_dump_analyze(void) +{ + DISPDMP("ccorr: en=%d, config=%d, w=%d, h=%d, in_p_cnt=%d, in_l_cnt=%d, out_p_cnt=%d, out_l_cnt=%d\n", + DISP_REG_GET(DISP_REG_CCORR_EN), DISP_REG_GET(DISP_REG_CCORR_CFG), + (DISP_REG_GET(DISP_REG_CCORR_SIZE) >> 16) & 0x1fff, + DISP_REG_GET(DISP_REG_CCORR_SIZE) & 0x1fff, + DISP_REG_GET(DISP_REG_CCORR_IN_CNT) & 0x1fff, + (DISP_REG_GET(DISP_REG_CCORR_IN_CNT) >> 16) & 0x1fff, + DISP_REG_GET(DISP_REG_CCORR_IN_CNT) & 0x1fff, + (DISP_REG_GET(DISP_REG_CCORR_IN_CNT) >> 16) & 0x1fff); +} + +static void dither_dump_reg(void) +{ + DISPDMP("== START: DISP DITHER REGS ==\n"); + DISPDMP("(00)EN =0x%x\n", DISP_REG_GET(DISP_REG_DITHER_EN)); + DISPDMP("(20)CFG =0x%x\n", DISP_REG_GET(DISP_REG_DITHER_CFG)); + DISPDMP("(24)IN_CNT =0x%x\n", DISP_REG_GET(DISP_REG_DITHER_IN_CNT)); + DISPDMP("(28)OUT_CNT =0x%x\n", DISP_REG_GET(DISP_REG_DITHER_IN_CNT)); + DISPDMP("(30)SIZE =0x%x\n", DISP_REG_GET(DISP_REG_DITHER_SIZE)); + DISPDMP("-- END: DISP DITHER REGS --\n"); +} + +static void dither_dump_analyze(void) +{ + DISPDMP + ("dither: en=%d, config=%d, w=%d, h=%d, in_p_cnt=%d, in_l_cnt=%d, out_p_cnt=%d, out_l_cnt=%d\n", + DISP_REG_GET(DISPSYS_DITHER_BASE + 0x000), DISP_REG_GET(DISPSYS_DITHER_BASE + 0x020), + (DISP_REG_GET(DISP_REG_DITHER_SIZE) >> 16) & 0x1fff, + DISP_REG_GET(DISP_REG_DITHER_SIZE) & 0x1fff, + DISP_REG_GET(DISP_REG_DITHER_IN_CNT) & 0x1fff, + (DISP_REG_GET(DISP_REG_DITHER_IN_CNT) >> 16) & 0x1fff, + DISP_REG_GET(DISP_REG_DITHER_OUT_CNT) & 0x1fff, + (DISP_REG_GET(DISP_REG_DITHER_OUT_CNT) >> 16) & 0x1fff); +} +static void dsi_dump_reg(DISP_MODULE_ENUM module) +{ + int i = 0; + + if (DISP_MODULE_DSI0) { + DISPDMP("== START: DISP DSI0 REGS ==\n"); + for (i = 0; i < 25 * 16; i += 16) { + DISPDMP("DSI0: 0x%04x=0x%08x,0x%04x=0x%08x,0x%04x=0x%08x,0x%04x=0x%08x\n", + i, INREG32(DISPSYS_DSI0_BASE + i), + i + 0x4, INREG32(DISPSYS_DSI0_BASE + i + 0x4), + i + 0x8, INREG32(DISPSYS_DSI0_BASE + i + 0x8), + i + 0xc, INREG32(DISPSYS_DSI0_BASE + i + 0xc)); + } + DISPDMP("DSI0 CMDQ+0x200 : 0x%08x 0x%08x 0x%08x 0x%08x\n", + INREG32(DISPSYS_DSI0_BASE + 0x200), INREG32(DISPSYS_DSI0_BASE + 0x200 + 0x4), + INREG32(DISPSYS_DSI0_BASE + 0x200 + 0x8), + INREG32(DISPSYS_DSI0_BASE + 0x200 + 0xc)); + DISPDMP("-- END: DISP DSI0 REGS --\n"); + } +} + +static void dpi_dump_reg(void) +{ + int i; + + DISPDMP("---------- Start dump DPI registers ----------\n"); + + for (i = 0; i <= 0x40; i += 4) + DISPDMP("DPI+%04x : 0x%08x\n", i, INREG32(DISPSYS_DPI_BASE + i)); + + for (i = 0x68; i <= 0x7C; i += 4) + DISPDMP("DPI+%04x : 0x%08x\n", i, INREG32(DISPSYS_DPI_BASE + i)); + + DISPDMP("DPI+Color Bar : 0x%04x : 0x%08x\n", 0xF00, INREG32(DISPSYS_DPI_BASE + 0xF00)); + DISPDMP("DPI MMSYS_CG_CON0: 0x%08x\n", INREG32(DISP_REG_CONFIG_MMSYS_CG_CON0)); + DISPDMP("DPI MMSYS_CG_CON1: 0x%08x\n", INREG32(DISP_REG_CONFIG_MMSYS_CG_CON1)); +} + +static void dpi_dump_analysis(void) +{ + DISPDMP("==DISP DPI ANALYSIS==\n"); + DISPDMP("DPI clock=0x%x\n", DISP_REG_GET(DISP_REG_CLK_CFG_6_DPI)); + DISPDMP("DPI clock_clear=%d\n", (DISP_REG_GET(DISP_REG_CLK_CFG_6_CLR) >> 7) & 0x1); +} + +int ddp_dump_reg(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_WDMA0: + wdma_dump_reg(module); + break; + case DISP_MODULE_RDMA0: + case DISP_MODULE_RDMA1: + case DISP_MODULE_RDMA2: + rdma_dump_reg(module); + break; + case DISP_MODULE_OVL0: + case DISP_MODULE_OVL1: + case DISP_MODULE_OVL0_2L: + case DISP_MODULE_OVL1_2L: + ovl_dump_reg(module); + break; + case DISP_MODULE_GAMMA: + gamma_dump_reg(); + break; + case DISP_MODULE_CONFIG: + mmsys_config_dump_reg(); + break; + case DISP_MODULE_MUTEX: + mutex_dump_reg(); + break; + case DISP_MODULE_MERGE: + merge_dump_reg(); + break; + case DISP_MODULE_SPLIT0: + case DISP_MODULE_SPLIT1: + split_dump_reg(module); + break; + case DISP_MODULE_COLOR0: + case DISP_MODULE_COLOR1: + color_dump_reg(module); + break; + case DISP_MODULE_AAL: + aal_dump_reg(); + break; + case DISP_MODULE_PWM0: + case DISP_MODULE_PWM1: + pwm_dump_reg(module); + break; + case DISP_MODULE_OD: + od_dump_reg(); + break; + case DISP_MODULE_DSI0: + case DISP_MODULE_DSI1: + dsi_dump_reg(module); + break; + case DISP_MODULE_DPI: + dpi_dump_reg(); + break; + case DISP_MODULE_CCORR: + ccorr_dump_reg(); + break; + case DISP_MODULE_DITHER: + dither_dump_reg(); + break; + default: + DISPDMP("no dump_reg for module %s(%d)\n", ddp_get_module_name(module), module); + } + return 0; +} + +int ddp_dump_analysis(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_WDMA0: + wdma_dump_analysis(module); + break; + case DISP_MODULE_RDMA0: + case DISP_MODULE_RDMA1: + case DISP_MODULE_RDMA2: + rdma_dump_analysis(module); + break; + case DISP_MODULE_OVL0: + case DISP_MODULE_OVL1: + case DISP_MODULE_OVL0_2L: + case DISP_MODULE_OVL1_2L: + ovl_dump_analysis(module); + break; + case DISP_MODULE_GAMMA: + gamma_dump_analysis(); + break; + case DISP_MODULE_CONFIG: + mmsys_config_dump_analysis(); + break; + case DISP_MODULE_MUTEX: + mutex_dump_analysis(); + break; + case DISP_MODULE_MERGE: + merge_dump_analysis(); + break; + case DISP_MODULE_SPLIT0: + case DISP_MODULE_SPLIT1: + split_dump_analysis(module); + break; + case DISP_MODULE_COLOR0: + case DISP_MODULE_COLOR1: + color_dump_analysis(module); + break; + case DISP_MODULE_AAL: + aal_dump_analysis(); + break; + case DISP_MODULE_OD: + od_dump_analysis(); + break; + case DISP_MODULE_PWM0: + case DISP_MODULE_PWM1: + pwm_dump_analysis(module); + break; + case DISP_MODULE_DSI0: + case DISP_MODULE_DSI1: + case DISP_MODULE_DSIDUAL: + dsi_analysis(module); + break; + case DISP_MODULE_DPI: + dpi_dump_analysis(); + break; + case DISP_MODULE_CCORR: + ccorr_dump_analyze(); + break; + case DISP_MODULE_DITHER: + dither_dump_analyze(); + break; + default: + DISPDMP("no dump_analysis for module %s(%d)\n", ddp_get_module_name(module), + module); + } + return 0; +} diff --git a/drivers/misc/mediatek/video/mt6755/ddp_dump.h b/drivers/misc/mediatek/video/mt6755/ddp_dump.h new file mode 100644 index 0000000000000000000000000000000000000000..310320c5260583979aa41200c4b60bab145d7e99 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_dump.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _DDP_DUMP_H_ +#define _DDP_DUMP_H_ + +#include "ddp_info.h" +#include "ddp_path.h" + +typedef enum { + DDP_SIGNAL_DPI0_SEL__DPI0 = 31, + DDP_SIGNAL_DIS0_SEL__DSI0 = 30, + DDP_SIGNAL_RDMA1_SOUT1__DPI0_SIN2 = 29, + DDP_SIGNAL_RDMA1_SOUT0__DSI0_SIN2 = 28, + DDP_SIGNAL_RDMA1__RDMA1_SOUT = 27, + DDP_SIGNAL_OVL1_MOUT2__OVL0 = 26, + DDP_SIGNAL_OVL1_MOUT1__WDMA1 = 25, + DDP_SIGNAL_OVL1_MOUT0__RDMA1 = 24, + DDP_SIGNAL_OVL1__OVL1_MOUT = 23, + DDP_SIGNAL_WDMA0_SEL__WDMA0 = 22, + DDP_SIGNAL_UFOE_MOUT2__WDMA0_SIN2 = 21, + DDP_SIGNAL_UFOE_MOUT1__DPI0_SIN0 = 20, + DDP_SIGNAL_UFOE_MOUT0__DSI0_SIN0 = 19, + DDP_SIGNAL_UFOE__UFOE_MOUT = 18, + DDP_SIGNAL_UFOE_SEL__UFOE = 17, + DDP_SIGNAL_RDMA0_SOUT3__DPI0_SIN1 = 16, + DDP_SIGNAL_RDMA0_SOUT2__DSI0_SIN1 = 15, + DDP_SIGNAL_RDMA0_SOUT1__COLOR_SIN0 = 14, + DDP_SIGNAL_RDMA0_SOUT0__UFOE_SIN0 = 13, + DDP_SIGNAL_RDMA0__RDMA0_SOUT = 12, + DDP_SIGNAL_DITHER_MOUT2__WDMA0_SIN1 = 11, + DDP_SIGNAL_DITHER_MOUT1__UFOE_SIN1 = 10, + DDP_SIGNAL_DITHER_MOUT0__RDMA0 = 9, + DDP_SIGNAL_DITHER__DITHER_MOUT = 8, + DDP_SIGNAL_GAMMA__DITHER = 7, + DDP_SIGNAL_AAL__GAMMA = 6, + DDP_SIGNAL_CCORR__AAL = 5, + DDP_SIGNAL_COLOR__CCORR = 4, + DDP_SIGNAL_COLOR_SEL__COLOR = 3, + DDP_SIGNAL_OVL0_MOUT1__WDMA0_SIN0 = 2, + DDP_SIGNAL_OVL0_MOUT0__COLOR_SIN1 = 1, + DDP_SIGNAL_OVL0__OVL0_MOUT = 0, +} DISP_ENGINE_SIGNAL0; + +char *ddp_get_fmt_name(DISP_MODULE_ENUM module, unsigned int fmt); +int ddp_dump_analysis(DISP_MODULE_ENUM module); +int ddp_dump_reg(DISP_MODULE_ENUM module); +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_hal.h b/drivers/misc/mediatek/video/mt6755/ddp_hal.h new file mode 100644 index 0000000000000000000000000000000000000000..7671bf68a73f724fff586ced5c9f66ff91624305 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_hal.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _H_DDP_HAL_ +#define _H_DDP_HAL_ + +/* DISP Mutex */ +#define DISP_MUTEX_TOTAL (10) +#define DISP_MUTEX_DDP_FIRST (0) +#define DISP_MUTEX_DDP_LAST (3) /* modify from 4 to 3, cause 4 is used for OVL0/OVL1 SW trigger */ +#define DISP_MUTEX_DDP_COUNT (4) +#define DISP_MUTEX_MDP_FIRST (5) +#define DISP_MUTEX_MDP_COUNT (5) + +/* DISP MODULE */ +typedef enum { + DISP_MODULE_OVL0 = 0, + DISP_MODULE_OVL1, + DISP_MODULE_OVL0_2L, + DISP_MODULE_OVL1_2L, + + DISP_MODULE_RDMA0, + DISP_MODULE_RDMA1, + DISP_MODULE_WDMA0, + DISP_MODULE_COLOR0, + DISP_MODULE_CCORR, + DISP_MODULE_AAL, + DISP_MODULE_GAMMA, /*10 */ + DISP_MODULE_DITHER, + DISP_MODULE_UFOE, /*not a real engine, only for path connection */ + DISP_MODULE_PWM0, + DISP_MODULE_WDMA1, + DISP_MODULE_DSI0, + DISP_MODULE_DPI, + DISP_MODULE_SMI, + DISP_MODULE_CONFIG, + DISP_MODULE_CMDQ, + DISP_MODULE_MUTEX, /*20 */ + + DISP_MODULE_COLOR1, + DISP_MODULE_RDMA2, + DISP_MODULE_PWM1, + DISP_MODULE_OD, + DISP_MODULE_MERGE, + DISP_MODULE_SPLIT0, + DISP_MODULE_SPLIT1, + DISP_MODULE_DSI1, + DISP_MODULE_DSIDUAL, + + DISP_MODULE_SMI_LARB0, /*30 */ + DISP_MODULE_SMI_COMMON, + DISP_MODULE_OVL0_VIRTUAL, /*not a real engine, only for path connection, OVL0_sel->OVL0_virtual->OVL0_MOUT */ + DISP_MODULE_MIPI, + + DISP_MODULE_UNKNOWN, /* 20 */ + DISP_MODULE_NUM +} DISP_MODULE_ENUM; + +enum dst_module_type { + DST_MOD_REAL_TIME, + DST_MOD_WDMA, +}; + +static inline int check_ddp_module(DISP_MODULE_ENUM module) +{ + return module < DISP_MODULE_UNKNOWN; +} + +typedef enum { + DISP_REG_CONFIG, + DISP_REG_OVL0, + DISP_REG_OVL1, + DISP_REG_RDMA0, + DISP_REG_RDMA1, + DISP_REG_WDMA0, + DISP_REG_COLOR, + DISP_REG_CCORR, + DISP_REG_AAL, + DISP_REG_GAMMA, + DISP_REG_DITHER, + DISP_REG_DSI0, + DISP_REG_DPI0, + DISP_REG_PWM, + DISP_REG_MUTEX, + DISP_REG_SMI_LARB0, + DISP_REG_SMI_COMMON, + DISP_REG_WDMA1, + DISP_REG_OVL0_2L, + DISP_REG_OVL1_2L, + DISP_REG_MIPI, + DISP_REG_NUM +} DISP_REG_ENUM; + +enum OVL_LAYER_SOURCE { + OVL_LAYER_SOURCE_MEM = 0, + OVL_LAYER_SOURCE_RESERVED = 1, + OVL_LAYER_SOURCE_SCL = 2, + OVL_LAYER_SOURCE_PQ = 3, +}; + +enum OVL_LAYER_SECURE_MODE { + OVL_LAYER_NORMAL_BUFFER = 0, + OVL_LAYER_SECURE_BUFFER = 1, + OVL_LAYER_PROTECTED_BUFFER = 2 +}; + +typedef enum { + CMDQ_DISABLE = 0, + CMDQ_ENABLE +} CMDQ_SWITCH; + +typedef enum { + CMDQ_WAIT_LCM_TE, + CMDQ_BEFORE_STREAM_SOF, + CMDQ_WAIT_STREAM_EOF_EVENT, + CMDQ_CHECK_IDLE_AFTER_STREAM_EOF, + CMDQ_AFTER_STREAM_EOF, + CMDQ_ESD_CHECK_READ, + CMDQ_ESD_CHECK_CMP, + CMDQ_ESD_ALLC_SLOT, + CMDQ_ESD_FREE_SLOT, + CMDQ_STOP_VDO_MODE, + CMDQ_START_VDO_MODE, + CMDQ_DSI_RESET, + CMDQ_AFTER_STREAM_SOF, + CMDQ_DSI_LFR_MODE, +} CMDQ_STATE; + +typedef enum { + DDP_IRQ_LEVEL_ALL = 0, + DDP_IRQ_LEVEL_NONE, + DDP_IRQ_LEVEL_ERROR +} DDP_IRQ_LEVEL; + + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_info.c b/drivers/misc/mediatek/video/mt6755/ddp_info.c new file mode 100644 index 0000000000000000000000000000000000000000..7925f6141d3560f8691cbe0e389dc31548ff9850 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_info.c @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "INFO" +#include"ddp_info.h" +#include"disp_debug.h" +#include "mtkfb_debug.h" +#include "disp_log.h" + +char *ddp_get_module_name(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_AAL: + return "aal "; + case DISP_MODULE_COLOR0: + return "color0 "; + case DISP_MODULE_COLOR1: + return "color1 "; + case DISP_MODULE_RDMA0: + return "rdma0 "; + case DISP_MODULE_RDMA1: + return "rdma1 "; + case DISP_MODULE_RDMA2: + return "rdma2 "; + case DISP_MODULE_WDMA0: + return "wdma0 "; + case DISP_MODULE_OVL0: + return "ovl0 "; + case DISP_MODULE_OVL1: + return "ovl1 "; + case DISP_MODULE_WDMA1: + return "wdma1 "; + case DISP_MODULE_OVL0_2L: + return "ovl0_2l "; + case DISP_MODULE_OVL1_2L: + return "ovl1_2l "; + case DISP_MODULE_GAMMA: + return "gamma "; + case DISP_MODULE_PWM0: + return "pwm0 "; + case DISP_MODULE_PWM1: + return "pwm1 "; + case DISP_MODULE_OD: + return "od "; + case DISP_MODULE_MERGE: + return "merge "; + case DISP_MODULE_SPLIT0: + return "split0 "; + case DISP_MODULE_SPLIT1: + return "split1 "; + case DISP_MODULE_DSI0: + return "dsi0 "; + case DISP_MODULE_DSI1: + return "dsi1 "; + case DISP_MODULE_DSIDUAL: + return "dsidual "; + case DISP_MODULE_DPI: + return "dpi "; + case DISP_MODULE_SMI: + return "smi "; + case DISP_MODULE_CONFIG: + return "config "; + case DISP_MODULE_CMDQ: + return "cmdq "; + case DISP_MODULE_MUTEX: + return "mutex "; + case DISP_MODULE_CCORR: + return "ccorr"; + case DISP_MODULE_DITHER: + return "dither"; + case DISP_MODULE_SMI_LARB0: + return "smi_larb0"; + case DISP_MODULE_SMI_COMMON: + return "smi_common"; + case DISP_MODULE_UFOE: + return "ufoe "; + case DISP_MODULE_OVL0_VIRTUAL: + return "ovl0_virtual"; + case DISP_MODULE_MIPI: + return "mipi"; + + default: + DISPMSG("invalid module id=%d", module); + return "unknown"; + } +} + +DISP_MODULE_ENUM ddp_get_reg_module(DISP_REG_ENUM reg_module) +{ + switch (reg_module) { + case DISP_REG_CONFIG: + return DISP_MODULE_CONFIG; + case DISP_REG_OVL0: + return DISP_MODULE_OVL0; + case DISP_REG_OVL1: + return DISP_MODULE_OVL1; + case DISP_REG_RDMA0: + return DISP_MODULE_RDMA0; + case DISP_REG_RDMA1: + return DISP_MODULE_RDMA1; + case DISP_REG_WDMA0: + return DISP_MODULE_WDMA0; + case DISP_REG_COLOR: + return DISP_MODULE_COLOR0; + case DISP_REG_CCORR: + return DISP_MODULE_CCORR; + case DISP_REG_AAL: + return DISP_MODULE_AAL; + case DISP_REG_GAMMA: + return DISP_MODULE_GAMMA; + case DISP_REG_DITHER: + return DISP_MODULE_DITHER; + case DISP_REG_DSI0: + return DISP_MODULE_DSI0; + case DISP_REG_DPI0: + return DISP_MODULE_DPI; + case DISP_REG_PWM: + return DISP_MODULE_PWM0; + case DISP_REG_MUTEX: + return DISP_MODULE_MUTEX; + case DISP_REG_SMI_LARB0: + return DISP_MODULE_SMI_LARB0; + case DISP_REG_SMI_COMMON: + return DISP_MODULE_SMI_COMMON; + case DISP_REG_WDMA1: + return DISP_MODULE_WDMA1; + case DISP_REG_OVL0_2L: + return DISP_MODULE_OVL0_2L; + case DISP_REG_OVL1_2L: + return DISP_MODULE_OVL1_2L; + case DISP_REG_MIPI: + return DISP_MODULE_MIPI; + default: + DISPERR("%s: invalid reg module id=%d", __func__, reg_module); + BUG(); + } +} + +char *ddp_get_reg_module_name(DISP_REG_ENUM reg_module) +{ + return ddp_get_module_name(ddp_get_reg_module(reg_module)); +} + +int ddp_get_module_max_irq_bit(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_AAL: + return 1; + case DISP_MODULE_COLOR0: + return 2; + case DISP_MODULE_COLOR1: + return 2; + case DISP_MODULE_RDMA0: + return 5; + case DISP_MODULE_RDMA1: + return 5; + case DISP_MODULE_RDMA2: + return 5; + case DISP_MODULE_WDMA0: + return 1; + case DISP_MODULE_OVL0: + return 3; + case DISP_MODULE_OVL1: + return 3; + case DISP_MODULE_WDMA1: + return 1; + case DISP_MODULE_OVL0_2L: + return 3; + case DISP_MODULE_OVL1_2L: + return 3; + case DISP_MODULE_GAMMA: + return 0; + case DISP_MODULE_PWM0: + return 0; + case DISP_MODULE_PWM1: + return 0; + case DISP_MODULE_OD: + return 0; + case DISP_MODULE_MERGE: + return 0; + case DISP_MODULE_SPLIT0: + return 0; + case DISP_MODULE_SPLIT1: + return 0; + case DISP_MODULE_DSI0: + return 6; + case DISP_MODULE_DSI1: + return 6; + case DISP_MODULE_DSIDUAL: + return 6; + case DISP_MODULE_DPI: + return 2; + case DISP_MODULE_SMI: + return 0; + case DISP_MODULE_CONFIG: + return 0; + case DISP_MODULE_CMDQ: + return 0; + case DISP_MODULE_MUTEX: + return 14; + case DISP_MODULE_CCORR: + return 0; + case DISP_MODULE_DITHER: + return 0; + default: + DISPMSG("invalid module id=%d", module); + } + return 0; +} + +unsigned int ddp_module_to_idx(int module) +{ + unsigned int id = 0; + + switch (module) { + case DISP_MODULE_AAL: + case DISP_MODULE_COLOR0: + case DISP_MODULE_RDMA0: + case DISP_MODULE_WDMA0: + case DISP_MODULE_OVL0: + case DISP_MODULE_GAMMA: + case DISP_MODULE_PWM0: + case DISP_MODULE_OD: + case DISP_MODULE_SPLIT0: + case DISP_MODULE_DSI0: + case DISP_MODULE_DPI: + case DISP_MODULE_DITHER: + case DISP_MODULE_CCORR: + id = 0; + break; + + case DISP_MODULE_COLOR1: + case DISP_MODULE_RDMA1: + case DISP_MODULE_PWM1: + case DISP_MODULE_SPLIT1: + case DISP_MODULE_DSI1: + case DISP_MODULE_OVL1: + case DISP_MODULE_WDMA1: + id = 1; + break; + case DISP_MODULE_RDMA2: + case DISP_MODULE_DSIDUAL: + id = 2; + break; + default: + DISPERR("ddp_module_to_idx, module=0x%x\n", module); + } + + return id; +} + + + +DDP_MODULE_DRIVER *ddp_modules_driver[DISP_MODULE_NUM] = { + &ddp_driver_ovl, /* DISP_MODULE_OVL0 = 0, */ + &ddp_driver_ovl, /* DISP_MODULE_OVL1 , */ + &ddp_driver_ovl, /* DISP_MODULE_OVL0_2L , */ + &ddp_driver_ovl, /* DISP_MODULE_OVL1_2L , */ + + &ddp_driver_rdma, /* DISP_MODULE_RDMA0 , */ + &ddp_driver_rdma, /* DISP_MODULE_RDMA1 , */ + &ddp_driver_wdma, /* DISP_MODULE_WDMA0 , */ + &ddp_driver_color, /* DISP_MODULE_COLOR0, */ + &ddp_driver_ccorr, /* DISP_MODULE_CCORR , */ + &ddp_driver_aal, /* DISP_MODULE_AAL , */ + &ddp_driver_gamma, /* DISP_MODULE_GAMMA , */ + &ddp_driver_dither, /* DISP_MODULE_DITHER, */ + 0, /* DISP_MODULE_UFOE , //10 */ + &ddp_driver_pwm, /* DISP_MODULE_PWM0 , */ + &ddp_driver_wdma, /* DISP_MODULE_WDMA1 , */ + &ddp_driver_dsi0, /* DISP_MODULE_DSI0 , */ + &ddp_driver_dpi, /* DISP_MODULE_DPI , */ + 0, /* DISP_MODULE_SMI, */ + 0, /* DISP_MODULE_CONFIG, */ + 0, /* DISP_MODULE_CMDQ, */ + 0, /* DISP_MODULE_MUTEX, */ + + 0, /* DISP_MODULE_COLOR1, */ + 0, /* DISP_MODULE_RDMA2, */ + 0, /* DISP_MODULE_PWM1, */ + 0, /* DISP_MODULE_OD, */ + 0, /* DISP_MODULE_MERGE, */ + 0, /* DISP_MODULE_SPLIT0, */ + 0, /* DISP_MODULE_SPLIT1, */ + 0, /* DISP_MODULE_DSI1, */ + 0, /* DISP_MODULE_DSIDUAL, */ + + 0, /* DISP_MODULE_SMI_LARB0 , */ + 0, /* DISP_MODULE_SMI_COMMON, */ + 0, /* DISP_MODULE_UNKNOWN, //20 */ +}; diff --git a/drivers/misc/mediatek/video/mt6755/ddp_info.h b/drivers/misc/mediatek/video/mt6755/ddp_info.h new file mode 100644 index 0000000000000000000000000000000000000000..d3168adcf3ef526b6a3a09ab55b1b2d1ed38c8de --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_info.h @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _H_DDP_INFO +#define _H_DDP_INFO +#include +#include +#include "ddp_hal.h" +#include "lcm_drv.h" +#include "disp_event.h" +#include "ddp_ovl.h" +#include + +#define _UFMT_ID_SHIFT 0 +#define _UFMT_ID_WIDTH 8 +#define _UFMT_RGBSWAP_SHIFT (_UFMT_ID_SHIFT+_UFMT_ID_WIDTH) +#define _UFMT_RGBSWAP_WIDTH 1 +#define _UFMT_BYTESWAP_SHIFT (_UFMT_RGBSWAP_SHIFT+_UFMT_RGBSWAP_WIDTH) +#define _UFMT_BYTESWAP_WIDTH 1 +#define _UFMT_FORMAT_SHIFT (_UFMT_BYTESWAP_SHIFT+_UFMT_BYTESWAP_WIDTH) +#define _UFMT_FORMAT_WIDTH 5 +#define _UFMT_VDO_SHIFT (_UFMT_FORMAT_SHIFT+_UFMT_FORMAT_WIDTH) +#define _UFMT_VDO_WIDTH 1 +#define _UFMT_BLOCK_SHIT (_UFMT_VDO_SHIFT+_UFMT_VDO_WIDTH) +#define _UFMT_BLOCK_WIDTH 1 +#define _UFMT_bpp_SHIFT (_UFMT_BLOCK_SHIT+_UFMT_BLOCK_WIDTH) +#define _UFMT_bpp_WIDTH 6 +#define _UFMT_RGB_SHIFT (_UFMT_bpp_SHIFT+_UFMT_bpp_WIDTH) +#define _UFMT_RGB_WIDTH 1 + + +#define _MASK_SHIFT(val, width, shift) (((val)>>(shift)) & ((1<<(width))-1)) + +#define MAKE_UNIFIED_COLOR_FMT(rgb, bpp, block, vdo, format, byteswap, rgbswap, id) \ + ( \ + ((rgb) << _UFMT_RGB_SHIFT) | \ + ((bpp) << _UFMT_bpp_SHIFT) | \ + ((block) << _UFMT_BLOCK_SHIT) | \ + ((vdo) << _UFMT_VDO_SHIFT) | \ + ((format) << _UFMT_FORMAT_SHIFT) | \ + ((byteswap) << _UFMT_BYTESWAP_SHIFT) | \ + ((rgbswap) << _UFMT_RGBSWAP_SHIFT) | \ + ((id) << _UFMT_ID_SHIFT)) + +#define UFMT_GET_RGB(fmt) _MASK_SHIFT(fmt, _UFMT_RGB_WIDTH, _UFMT_RGB_SHIFT) +#define UFMT_GET_bpp(fmt) _MASK_SHIFT(fmt, _UFMT_bpp_WIDTH, _UFMT_bpp_SHIFT) +#define UFMT_GET_BLOCK(fmt) _MASK_SHIFT(fmt, _UFMT_BLOCK_WIDTH, _UFMT_BLOCK_SHIT) +#define UFMT_GET_VDO(fmt) _MASK_SHIFT(fmt, _UFMT_VDO_WIDTH, _UFMT_VDO_SHIFT) +#define UFMT_GET_FORMAT(fmt) _MASK_SHIFT(fmt, _UFMT_FORMAT_WIDTH, _UFMT_FORMAT_SHIFT) +#define UFMT_GET_BYTESWAP(fmt) _MASK_SHIFT(fmt, _UFMT_BYTESWAP_WIDTH, _UFMT_BYTESWAP_SHIFT) +#define UFMT_GET_RGBSWAP(fmt) _MASK_SHIFT(fmt, _UFMT_RGBSWAP_WIDTH, _UFMT_RGBSWAP_SHIFT) +#define UFMT_GET_ID(fmt) _MASK_SHIFT(fmt, _UFMT_ID_WIDTH, _UFMT_ID_SHIFT) +#define UFMT_GET_Bpp(fmt) (UFMT_GET_bpp(fmt)/8) + +unsigned int ufmt_get_rgb(unsigned int fmt); +unsigned int ufmt_get_bpp(unsigned int fmt); +unsigned int ufmt_get_block(unsigned int fmt); +unsigned int ufmt_get_vdo(unsigned int fmt); +unsigned int ufmt_get_format(unsigned int fmt); +unsigned int ufmt_get_byteswap(unsigned int fmt); +unsigned int ufmt_get_rgbswap(unsigned int fmt); +unsigned int ufmt_get_id(unsigned int fmt); +unsigned int ufmt_get_Bpp(unsigned int fmt); +unsigned int ufmt_is_old_fmt(unsigned int fmt); + + +enum UNIFIED_COLOR_FMT { + UFMT_UNKNOWN = 0, + UFMT_Y8 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 7, 0, 0, 1), + UFMT_RGBA4444 = MAKE_UNIFIED_COLOR_FMT(1, 16, 0, 0, 0, 0, 0, 2), + UFMT_RGBA5551 = MAKE_UNIFIED_COLOR_FMT(1, 16, 0, 0, 0, 0, 0, 3), + UFMT_RGB565 = MAKE_UNIFIED_COLOR_FMT(1, 16, 0, 0, 0, 0, 0, 4), + UFMT_BGR565 = MAKE_UNIFIED_COLOR_FMT(1, 16, 0, 0, 0, 1, 0, 5), + UFMT_RGB888 = MAKE_UNIFIED_COLOR_FMT(1, 24, 0, 0, 1, 1, 0, 6), + UFMT_BGR888 = MAKE_UNIFIED_COLOR_FMT(1, 24, 0, 0, 1, 0, 0, 7), + UFMT_RGBA8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 2, 1, 0, 8), + UFMT_BGRA8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 2, 0, 0, 9), + UFMT_ARGB8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 3, 1, 0, 10), + UFMT_ABGR8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 3, 0, 0, 11), + UFMT_RGBX8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 0, 0, 0, 12), + UFMT_BGRX8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 0, 0, 0, 13), + UFMT_XRGB8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 0, 0, 0, 14), + UFMT_XBGR8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 0, 0, 0, 15), + UFMT_AYUV = MAKE_UNIFIED_COLOR_FMT(0, 0, 0, 0, 0, 0, 0, 16), + UFMT_YUV = MAKE_UNIFIED_COLOR_FMT(0, 0, 0, 0, 0, 0, 0, 17), + UFMT_UYVY = MAKE_UNIFIED_COLOR_FMT(0, 16, 0, 0, 4, 0, 0, 18), + UFMT_VYUY = MAKE_UNIFIED_COLOR_FMT(0, 16, 0, 0, 4, 1, 0, 19), + UFMT_YUYV = MAKE_UNIFIED_COLOR_FMT(0, 16, 0, 0, 5, 0, 0, 20), + UFMT_YVYU = MAKE_UNIFIED_COLOR_FMT(0, 16, 0, 0, 5, 1, 0, 21), + UFMT_UYVY_BLK = MAKE_UNIFIED_COLOR_FMT(0, 16, 1, 0, 4, 0, 0, 22), + UFMT_VYUY_BLK = MAKE_UNIFIED_COLOR_FMT(0, 16, 1, 0, 4, 1, 0, 23), + UFMT_YUY2_BLK = MAKE_UNIFIED_COLOR_FMT(0, 16, 1, 0, 5, 0, 0, 24), + UFMT_YVYU_BLK = MAKE_UNIFIED_COLOR_FMT(0, 16, 1, 0, 5, 1, 0, 25), + UFMT_YV12 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 8, 1, 0, 26), + UFMT_I420 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 8, 0, 0, 27), + UFMT_YV16 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 9, 1, 0, 28), + UFMT_I422 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 9, 0, 0, 29), + UFMT_YV24 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 10, 1, 0, 30), + UFMT_I444 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 10, 0, 0, 31), + UFMT_NV12 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 12, 0, 0, 32), + UFMT_NV21 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 12, 1, 0, 33), + UFMT_NV12_BLK = MAKE_UNIFIED_COLOR_FMT(0, 8, 1, 0, 12, 0, 0, 34), + UFMT_NV21_BLK = MAKE_UNIFIED_COLOR_FMT(0, 8, 1, 0, 12, 1, 0, 35), + UFMT_NV12_BLK_FLD = MAKE_UNIFIED_COLOR_FMT(0, 8, 1, 1, 12, 0, 0, 36), + UFMT_NV21_BLK_FLD = MAKE_UNIFIED_COLOR_FMT(0, 8, 1, 1, 12, 1, 0, 37), + UFMT_NV16 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 13, 0, 0, 38), + UFMT_NV61 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 13, 1, 0, 39), + UFMT_NV24 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 14, 0, 0, 40), + UFMT_NV42 = MAKE_UNIFIED_COLOR_FMT(0, 8, 0, 0, 14, 1, 0, 41), + UFMT_PARGB8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 3, 1, 0, 42), + UFMT_PABGR8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 3, 1, 1, 43), + UFMT_PRGBA8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 3, 0, 1, 44), + UFMT_PBGRA8888 = MAKE_UNIFIED_COLOR_FMT(1, 32, 0, 0, 3, 0, 0, 45), +}; +char *unified_color_fmt_name(enum UNIFIED_COLOR_FMT fmt); +enum UNIFIED_COLOR_FMT display_fmt_reg_to_unified_fmt(int fmt_reg_val, int byteswap, + int rgbswap); +int is_unified_color_fmt_supported(enum UNIFIED_COLOR_FMT ufmt); +enum UNIFIED_COLOR_FMT disp_fmt_to_unified_fmt(DISP_FORMAT src_fmt); +int ufmt_disable_X_channel(enum UNIFIED_COLOR_FMT src_fmt, enum UNIFIED_COLOR_FMT *dst_fmt, + int *const_bld); +int ufmt_disable_P(enum UNIFIED_COLOR_FMT src_fmt, enum UNIFIED_COLOR_FMT *dst_fmt); + + +typedef struct _OVL_CONFIG_STRUCT { + /* unsigned int ovl_index; */ + unsigned int layer; + unsigned int layer_en; + enum OVL_LAYER_SOURCE source; + enum UNIFIED_COLOR_FMT fmt; + unsigned long addr; + unsigned long vaddr; + unsigned int src_x; + unsigned int src_y; + unsigned int src_w; + unsigned int src_h; + unsigned int src_pitch; + unsigned int dst_x; + unsigned int dst_y; + unsigned int dst_w; + unsigned int dst_h; + unsigned int keyEn; + unsigned int key; + unsigned int aen; + unsigned char alpha; + + unsigned int sur_aen; + unsigned int src_alpha; + unsigned int dst_alpha; + + unsigned int isTdshp; + unsigned int isDirty; + + unsigned int buff_idx; + unsigned int identity; + unsigned int connected_type; + DISP_BUFFER_TYPE security; + unsigned int yuv_range; + int is_configured; /* is this layer configured to OVL HW, for multiply OVL sync */ + int const_bld; +} OVL_CONFIG_STRUCT; + +typedef struct _OVL_BASIC_STRUCT { + unsigned int layer; + unsigned int layer_en; + enum UNIFIED_COLOR_FMT fmt; + unsigned long addr; + unsigned int src_w; + unsigned int src_h; + unsigned int src_pitch; + unsigned int bpp; + unsigned int gpu_mode; + unsigned int adobe_mode; + unsigned int ovl_gamma_out; + unsigned int alpha; +} OVL_BASIC_STRUCT; + +typedef struct _RDMA_BASIC_STRUCT { + unsigned long addr; + unsigned int src_w; + unsigned int src_h; + unsigned int bpp; +} RDMA_BASIC_STRUCT; + +struct rdma_bg_ctrl_t { + unsigned int left; + unsigned int right; + unsigned int top; + unsigned int bottom; +}; + +typedef struct _RDMA_CONFIG_STRUCT { + unsigned idx; /* instance index */ + enum UNIFIED_COLOR_FMT inputFormat; + unsigned long address; + unsigned pitch; + unsigned width; + unsigned height; + unsigned dst_w; + unsigned dst_h; + unsigned dst_x; + unsigned dst_y; + DISP_BUFFER_TYPE security; + unsigned int yuv_range; + struct rdma_bg_ctrl_t bg_ctrl; +} RDMA_CONFIG_STRUCT; + +typedef struct _WDMA_CONFIG_STRUCT { + unsigned srcWidth; + unsigned srcHeight; /* input */ + unsigned clipX; + unsigned clipY; + unsigned clipWidth; + unsigned clipHeight; /* clip */ + enum UNIFIED_COLOR_FMT outputFormat; + unsigned long dstAddress; + unsigned dstPitch; /* output */ + unsigned int useSpecifiedAlpha; + unsigned char alpha; + DISP_BUFFER_TYPE security; +} WDMA_CONFIG_STRUCT; + +typedef struct { + unsigned int fifo_mode; + unsigned int is_wrot_sram; + unsigned int mmsys_clk; + unsigned int hrt_num; + unsigned int ext_hrt_num; + unsigned int is_display_idle; + unsigned int is_dc; + unsigned int hrt_magicnum; /* by resolution */ + unsigned int ext_hrt_magicnum; /* by resolution */ + unsigned int dst_width; + unsigned int dst_height; + unsigned int ext_dst_width; + unsigned int ext_dst_height; + unsigned int fps; + unsigned int is_one_layer; + unsigned int rdma_width; + unsigned int rdma_height; +} golden_setting_context; + +typedef struct { + struct task_struct *primary_display_idlemgr_task; + wait_queue_head_t idlemgr_wait_queue; + unsigned long long idlemgr_last_kick_time; + unsigned int enterulps; + int session_mode_before_enter_idle; + int is_primary_idle; + +} disp_idlemgr_context; + +typedef struct { + /* for ovl */ + bool ovl_dirty; + bool rdma_dirty; + bool wdma_dirty; + bool dst_dirty; + int ovl_layer_dirty; /*each bit represent one layer */ + int ovl_layer_scanned; /*each bit reprsent one layer, used for ovl engines */ + int overlap_layer_num; + OVL_CONFIG_STRUCT ovl_config[TOTAL_OVL_LAYER_NUM]; + RDMA_CONFIG_STRUCT rdma_config; + WDMA_CONFIG_STRUCT wdma_config; + LCM_PARAMS dispif_config; + unsigned int lcm_bpp; + unsigned int dst_w; + unsigned int dst_h; + unsigned int fps; + golden_setting_context *p_golden_setting_context; + void *path_handle; +} disp_ddp_path_config; + +/* dpmgr_ioctl cmd definition */ +typedef enum { +/* DSI operation */ + DDP_SWITCH_DSI_MODE = 0, + DDP_STOP_VIDEO_MODE = 1, + DDP_BACK_LIGHT = 2, + DDP_SWITCH_LCM_MODE = 3, + DDP_DPI_FACTORY_TEST = 4, + DDP_DSI_IDLE_CLK_CLOSED = 5, + DDP_DSI_IDLE_CLK_OPEN = 6, + DDP_DSI_PORCH_CHANGE = 7, + DDP_PHY_CLK_CHANGE = 8, + DDP_ENTER_ULPS = 9, + DDP_EXIT_ULPS = 10, + DDP_RDMA_GOLDEN_SETTING = 11, + DDP_OVL_GOLDEN_SETTING, +} DDP_IOCTL_NAME; + +struct ddp_io_golden_setting_arg { + enum dst_module_type dst_mod_type; + int is_decouple_mode; + unsigned int dst_w; + unsigned int dst_h; +}; + +typedef int (*ddp_module_notify) (DISP_MODULE_ENUM, DISP_PATH_EVENT); + +typedef struct { + DISP_MODULE_ENUM module; + int (*init)(DISP_MODULE_ENUM module, void *handle); + int (*deinit)(DISP_MODULE_ENUM module, void *handle); + int (*config)(DISP_MODULE_ENUM module, disp_ddp_path_config *config, void *handle); + int (*start)(DISP_MODULE_ENUM module, void *handle); + int (*trigger)(DISP_MODULE_ENUM module, void *handle); + int (*stop)(DISP_MODULE_ENUM module, void *handle); + int (*reset)(DISP_MODULE_ENUM module, void *handle); + int (*power_on)(DISP_MODULE_ENUM module, void *handle); + int (*power_off)(DISP_MODULE_ENUM module, void *handle); + int (*suspend)(DISP_MODULE_ENUM module, void *handle); + int (*resume)(DISP_MODULE_ENUM module, void *handle); + int (*is_idle)(DISP_MODULE_ENUM module); + int (*is_busy)(DISP_MODULE_ENUM module); + int (*dump_info)(DISP_MODULE_ENUM module, int level); + int (*bypass)(DISP_MODULE_ENUM module, int bypass); + int (*build_cmdq)(DISP_MODULE_ENUM module, void *cmdq_handle, CMDQ_STATE state); + int (*set_lcm_utils)(DISP_MODULE_ENUM module, LCM_DRIVER *lcm_drv); + int (*set_listener)(DISP_MODULE_ENUM module, ddp_module_notify notify); + int (*cmd)(DISP_MODULE_ENUM module, int msg, unsigned long arg, void *handle); + int (*ioctl)(DISP_MODULE_ENUM module, void *handle, DDP_IOCTL_NAME ioctl_cmd, + void *params); + int (*enable_irq)(DISP_MODULE_ENUM module, void *handle, DDP_IRQ_LEVEL irq_level); + int (*connect)(DISP_MODULE_ENUM module, DISP_MODULE_ENUM prev, DISP_MODULE_ENUM next, + int connect, void *handle); + +} DDP_MODULE_DRIVER; + +char *ddp_get_module_name(DISP_MODULE_ENUM module); +char *ddp_get_reg_module_name(DISP_REG_ENUM reg_module); +int ddp_get_module_max_irq_bit(DISP_MODULE_ENUM module); +DISP_MODULE_ENUM ddp_get_reg_module(DISP_REG_ENUM reg_module); + + +/* dsi */ +extern DDP_MODULE_DRIVER ddp_driver_dsi0; +/* extern DDP_MODULE_DRIVER ddp_driver_dsi1; */ +/* extern DDP_MODULE_DRIVER ddp_driver_dsidual; */ +/* dpi */ +extern DDP_MODULE_DRIVER ddp_driver_dpi; + +/* ovl */ +extern DDP_MODULE_DRIVER ddp_driver_ovl; +/* rdma */ +extern DDP_MODULE_DRIVER ddp_driver_rdma; +/* wdma */ +extern DDP_MODULE_DRIVER ddp_driver_wdma; +/* color */ +extern DDP_MODULE_DRIVER ddp_driver_color; +/* aal */ +extern DDP_MODULE_DRIVER ddp_driver_aal; +/* od */ +/* extern DDP_MODULE_DRIVER ddp_driver_od; */ +/* gamma */ +extern DDP_MODULE_DRIVER ddp_driver_gamma; +/* dither */ +extern DDP_MODULE_DRIVER ddp_driver_dither; +/* ccorr */ +extern DDP_MODULE_DRIVER ddp_driver_ccorr; +/* split */ +/* extern DDP_MODULE_DRIVER ddp_driver_split; */ + +/* pwm */ +extern DDP_MODULE_DRIVER ddp_driver_pwm; +/* ufoe */ +/* extern DDP_MODULE_DRIVER ddp_driver_ufoe; */ + +extern DDP_MODULE_DRIVER *ddp_modules_driver[DISP_MODULE_NUM]; + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_irq.c b/drivers/misc/mediatek/video/mt6755/ddp_irq.c new file mode 100644 index 0000000000000000000000000000000000000000..a4a47b5a23fe8d25e3dec68ec7521a338d344549 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_irq.c @@ -0,0 +1,496 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#define LOG_TAG "IRQ" + +#include "disp_log.h" +#include "disp_debug.h" +#include "mtkfb_debug.h" + +#include +#include +#include +#include +#include + +#include "ddp_reg.h" +#include "ddp_irq.h" +#include "ddp_aal.h" +#include "ddp_drv.h" +#include "disp_helper.h" + +/* IRQ log print kthread */ +static struct task_struct *disp_irq_log_task; +static wait_queue_head_t disp_irq_log_wq; +static int disp_irq_log_module; + +static int irq_init; + +static unsigned int cnt_rdma_underflow[2]; +static unsigned int cnt_rdma_abnormal[2]; +static unsigned int cnt_ovl_underflow[OVL_NUM]; +static unsigned int cnt_wdma_underflow[2]; + +unsigned long long rdma_start_time[2] = { 0 }; +unsigned long long rdma_end_time[2] = { 0 }; + +unsigned int mmsys_debug[4] = {0}; +unsigned int mmsys_enable = 4; + + + +#define DISP_MAX_IRQ_CALLBACK 10 + +static DDP_IRQ_CALLBACK irq_module_callback_table[DISP_MODULE_NUM][DISP_MAX_IRQ_CALLBACK]; +static DDP_IRQ_CALLBACK irq_callback_table[DISP_MAX_IRQ_CALLBACK]; + +/* dsi read by cpu should keep esd_check_bycmdq = 0. */ +/* dsi read by cmdq should keep esd_check_bycmdq = 1. */ +atomic_t ESDCheck_byCPU = ATOMIC_INIT(0); + +void disp_irq_esd_cust_bycmdq(int enable) +{ + atomic_set(&ESDCheck_byCPU, enable ? 0 : 1); +} + +int disp_irq_esd_cust_get(void) +{ + return atomic_read(&ESDCheck_byCPU); +} + +int disp_register_irq_callback(DDP_IRQ_CALLBACK cb) +{ + int i = 0; + + for (i = 0; i < DISP_MAX_IRQ_CALLBACK; i++) { + if (irq_callback_table[i] == cb) + break; + } + if (i < DISP_MAX_IRQ_CALLBACK) + return 0; + + for (i = 0; i < DISP_MAX_IRQ_CALLBACK; i++) { + if (irq_callback_table[i] == NULL) + break; + } + if (i == DISP_MAX_IRQ_CALLBACK) { + DISPERR("not enough irq callback entries for module\n"); + return -1; + } + DISPMSG("register callback on %d\n", i); + irq_callback_table[i] = cb; + return 0; +} + +int disp_unregister_irq_callback(DDP_IRQ_CALLBACK cb) +{ + int i; + + for (i = 0; i < DISP_MAX_IRQ_CALLBACK; i++) { + if (irq_callback_table[i] == cb) { + irq_callback_table[i] = NULL; + break; + } + } + if (i == DISP_MAX_IRQ_CALLBACK) { + DISPERR("Try to unregister callback function %p which was not registered\n", cb); + return -1; + } + return 0; +} + +int disp_register_module_irq_callback(DISP_MODULE_ENUM module, DDP_IRQ_CALLBACK cb) +{ + int i; + + if (module >= DISP_MODULE_NUM) { + DISPERR("Register IRQ with invalid module ID. module=%d\n", module); + return -1; + } + if (cb == NULL) { + DISPERR("Register IRQ with invalid cb.\n"); + return -1; + } + for (i = 0; i < DISP_MAX_IRQ_CALLBACK; i++) { + if (irq_module_callback_table[module][i] == cb) + break; + } + if (i < DISP_MAX_IRQ_CALLBACK) + return 0; + + for (i = 0; i < DISP_MAX_IRQ_CALLBACK; i++) { + if (irq_module_callback_table[module][i] == NULL) + break; + } + if (i == DISP_MAX_IRQ_CALLBACK) { + DISPERR("No enough callback entries for module %d.\n", module); + return -1; + } + irq_module_callback_table[module][i] = cb; + return 0; +} + +int disp_unregister_module_irq_callback(DISP_MODULE_ENUM module, DDP_IRQ_CALLBACK cb) +{ + int i; + + for (i = 0; i < DISP_MAX_IRQ_CALLBACK; i++) { + if (irq_module_callback_table[module][i] == cb) { + irq_module_callback_table[module][i] = NULL; + break; + } + } + if (i == DISP_MAX_IRQ_CALLBACK) { + DISPERR + ("Try to unregister callback function with was not registered. module=%d cb=%p\n", + module, cb); + return -1; + } + return 0; +} + +void disp_invoke_irq_callbacks(DISP_MODULE_ENUM module, unsigned int param) +{ + int i; + + for (i = 0; i < DISP_MAX_IRQ_CALLBACK; i++) { + + if (irq_callback_table[i]) { + /* DISPERR("Invoke callback function. module=%d param=0x%X\n", module, param); */ + irq_callback_table[i] (module, param); + } + + if (irq_module_callback_table[module][i]) { + /* DISPERR("Invoke module callback function. module=%d param=0x%X\n", module, param); */ + irq_module_callback_table[module][i] (module, param); + } + } +} + +static DISP_MODULE_ENUM disp_irq_module(unsigned int irq) +{ + DISP_REG_ENUM reg_module; + + for (reg_module = 0; reg_module < DISP_REG_NUM; reg_module++) { + if (irq == dispsys_irq[reg_module]) + return ddp_get_reg_module(reg_module); + } + DISPERR("cannot find module for irq %d\n", irq); + BUG(); + return DISP_MODULE_UNKNOWN; +} + +/* /TODO: move each irq to module driver */ +unsigned int rdma_start_irq_cnt[2] = { 0, 0 }; +unsigned int rdma_done_irq_cnt[2] = { 0, 0 }; +unsigned int rdma_underflow_irq_cnt[2] = { 0, 0 }; +unsigned int rdma_targetline_irq_cnt[2] = { 0, 0 }; + +irqreturn_t disp_irq_handler(int irq, void *dev_id) +{ + DISP_MODULE_ENUM module = DISP_MODULE_UNKNOWN; + unsigned int reg_val = 0; + unsigned int index = 0; + unsigned int mutexID = 0; + unsigned int reg_temp_val = 0; + unsigned int tmp_mmsys_debug[4] = {0}; + + DISPIRQ("disp_irq_handler, irq=%d, module=%s\n", + irq, ddp_get_module_name(disp_irq_module(irq))); + + if (irq == dispsys_irq[DISP_REG_DSI0]) { + module = DISP_MODULE_DSI0; + reg_val = (DISP_REG_GET(dsi_reg_va + 0xC) & 0xff); + reg_temp_val = reg_val; + /* rd_rdy don't clear and wait for ESD & Read LCM will clear the bit. */ + if (disp_irq_esd_cust_get() == 0) + reg_temp_val = reg_val&0xfffe; + DISP_CPU_REG_SET(dsi_reg_va + 0xC, ~reg_temp_val); + } else if (irq == dispsys_irq[DISP_REG_OVL0] || + irq == dispsys_irq[DISP_REG_OVL1] || + irq == dispsys_irq[DISP_REG_OVL0_2L] || irq == dispsys_irq[DISP_REG_OVL1_2L] + ) { + module = disp_irq_module(irq); + index = ovl_to_index(module); + reg_val = DISP_REG_GET(DISP_REG_OVL_INTSTA + ovl_base_addr(module)); + if (reg_val & (1 << 0)) + DISPIRQ("IRQ: %s reg commit!\n", ddp_get_module_name(module)); + + if (reg_val & (1 << 1)) + DISPIRQ("IRQ: %s frame done!\n", ddp_get_module_name(module)); + + if (reg_val & (1 << 2)) + DISPERR("IRQ: %s frame underflow! cnt=%d\n", ddp_get_module_name(module), + cnt_ovl_underflow[index]++); + + if (reg_val & (1 << 3)) + DISPIRQ("IRQ: %s sw reset done\n", ddp_get_module_name(module)); + + if (reg_val & (1 << 4)) + DISPERR("IRQ: %s hw reset done\n", ddp_get_module_name(module)); + + if (reg_val & (1 << 5)) + DISPERR("IRQ: %s-L0 not complete until EOF!\n", + ddp_get_module_name(module)); + + if (reg_val & (1 << 6)) + DISPERR("IRQ: %s-L1 not complete until EOF!\n", + ddp_get_module_name(module)); + + if (reg_val & (1 << 7)) + DISPERR("IRQ: %s-L2 not complete until EOF!\n", + ddp_get_module_name(module)); + + if (reg_val & (1 << 8)) + DISPERR("IRQ: %s-L3 not complete until EOF!\n", + ddp_get_module_name(module)); +#if 0 + /* we don't care ovl underflow, it's not error */ + if (reg_val & (1 << 9)) + DISPERR("IRQ: %s-L0 fifo underflow!\n", ddp_get_module_name(module)); + + + if (reg_val & (1 << 10)) + DISPERR("IRQ: %s-L1 fifo underflow!\n", ddp_get_module_name(module)); + + if (reg_val & (1 << 11)) + DISPERR("IRQ: %s-L2 fifo underflow!\n", ddp_get_module_name(module)); + + if (reg_val & (1 << 12)) + DISPERR("IRQ: %s-L3 fifo underflow!\n", ddp_get_module_name(module)); +#endif + if (reg_val & (1 << 13)) + DISPERR("IRQ: %s abnormal SOF!\n", ddp_get_module_name(module)); + + DISP_CPU_REG_SET(DISP_REG_OVL_INTSTA + ovl_base_addr(module), ~reg_val); + MMProfileLogEx(ddp_mmp_get_events()->OVL_IRQ[index], MMProfileFlagPulse, reg_val, + 0); + if (reg_val & 0x1e0) + MMProfileLogEx(ddp_mmp_get_events()->ddp_abnormal_irq, MMProfileFlagPulse, + (index << 16) | reg_val, module); + + } else if (irq == dispsys_irq[DISP_REG_WDMA0] || irq == dispsys_irq[DISP_REG_WDMA1]) { + index = (irq == dispsys_irq[DISP_REG_WDMA0]) ? 0 : 1; + module = + (irq == dispsys_irq[DISP_REG_WDMA0]) ? DISP_MODULE_WDMA0 : DISP_MODULE_WDMA1; + reg_val = DISP_REG_GET(DISP_REG_WDMA_INTSTA + index * DISP_WDMA_INDEX_OFFSET); + if (reg_val & (1 << 0)) + DISPIRQ("IRQ: WDMA%d frame done!\n", index); + + if (reg_val & (1 << 1)) { + DISPERR("IRQ: WDMA%d underrun! cnt=%d\n", index, + cnt_wdma_underflow[index]++); + disp_irq_log_module |= 1 << module; + } + /* clear intr */ + DISP_CPU_REG_SET(DISP_REG_WDMA_INTSTA + index * DISP_WDMA_INDEX_OFFSET, ~reg_val); + MMProfileLogEx(ddp_mmp_get_events()->WDMA_IRQ[index], MMProfileFlagPulse, reg_val, + DISP_REG_GET(DISP_REG_WDMA_CLIP_SIZE)); + if (reg_val & 0x2) + MMProfileLogEx(ddp_mmp_get_events()->ddp_abnormal_irq, MMProfileFlagPulse, + (cnt_wdma_underflow[index] << 24) | (index << 16) | reg_val, + module); + + } else if (irq == dispsys_irq[DISP_REG_RDMA0] || irq == dispsys_irq[DISP_REG_RDMA1]) { + if (dispsys_irq[DISP_REG_RDMA0] == irq) { + index = 0; + module = DISP_MODULE_RDMA0; + } else if (dispsys_irq[DISP_REG_RDMA1] == irq) { + index = 1; + module = DISP_MODULE_RDMA1; + } + + reg_val = DISP_REG_GET(DISP_REG_RDMA_INT_STATUS + index * DISP_RDMA_INDEX_OFFSET); + if (reg_val & (1 << 0)) + DISPIRQ("IRQ: RDMA%d reg update done!\n", index); + + if (reg_val & (1 << 2)) { + MMProfileLogEx(ddp_mmp_get_events()->SCREEN_UPDATE[index], MMProfileFlagEnd, + reg_val, 0); + rdma_end_time[index] = sched_clock(); + tmp_mmsys_debug[2] = DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0); + tmp_mmsys_debug[3] = DISP_REG_GET(DISP_REG_CONFIG_MMSYS_SW0_RST_B); + + if ((tmp_mmsys_debug[2] != mmsys_debug[2]) + || (tmp_mmsys_debug[3] != mmsys_debug[3])) { + mmsys_debug[2] = tmp_mmsys_debug[2]; + mmsys_debug[3] = tmp_mmsys_debug[3]; + if (mmsys_enable > 0) { + DISPMSG("cg_e = %x, rst_e = %x", mmsys_debug[2], mmsys_debug[3]); + mmsys_enable--; + } + } + DISPIRQ("IRQ: RDMA%d frame done!\n", index); + rdma_done_irq_cnt[index]++; + } + if (reg_val & (1 << 1)) { + MMProfileLogEx(ddp_mmp_get_events()->SCREEN_UPDATE[index], + MMProfileFlagStart, reg_val, 0); + rdma_start_time[index] = sched_clock(); + tmp_mmsys_debug[0] = DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0); + tmp_mmsys_debug[1] = DISP_REG_GET(DISP_REG_CONFIG_MMSYS_SW0_RST_B); + + if ((tmp_mmsys_debug[0] != mmsys_debug[0]) + || (tmp_mmsys_debug[1] != mmsys_debug[1])) { + mmsys_debug[0] = tmp_mmsys_debug[0]; + mmsys_debug[1] = tmp_mmsys_debug[1]; + if (mmsys_enable > 0) { + DISPMSG("cg_s = %x, rst_s = %x", mmsys_debug[0], mmsys_debug[1]); + mmsys_enable--; + } + } + DISPIRQ("IRQ: RDMA%d frame start!\n", index); + rdma_start_irq_cnt[index]++; + } + if (reg_val & (1 << 3)) { + MMProfileLogEx(ddp_mmp_get_events()->SCREEN_UPDATE[index], MMProfileFlagPulse, + reg_val, 0); + + DISPERR("IRQ: RDMA%d abnormal! cnt=%d\n", index, cnt_rdma_abnormal[index]++); + disp_irq_log_module |= 1 << module; + + } + if (reg_val & (1 << 4)) { + + MMProfileLogEx(ddp_mmp_get_events()->SCREEN_UPDATE[index], MMProfileFlagPulse, + reg_val, 1); + + DISPMSG("rdma%d, pix(%d,%d,%d,%d)\n", + index, + DISP_REG_GET(DISP_REG_RDMA_IN_P_CNT + + DISP_RDMA_INDEX_OFFSET * index), + DISP_REG_GET(DISP_REG_RDMA_IN_LINE_CNT + + DISP_RDMA_INDEX_OFFSET * index), + DISP_REG_GET(DISP_REG_RDMA_OUT_P_CNT + + DISP_RDMA_INDEX_OFFSET * index), + DISP_REG_GET(DISP_REG_RDMA_OUT_LINE_CNT + + DISP_RDMA_INDEX_OFFSET * index)); + DISPERR("IRQ: RDMA%d underflow! cnt=%d\n", index, cnt_rdma_underflow[index]++); + DISPERR("(0x030)R_M_GMC_SET0 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_GMC_SETTING_0 + DISP_RDMA_INDEX_OFFSET * index)); + if (disp_helper_get_option(DISP_OPT_RDMA_UNDERFLOW_AEE)) + DISPAEE("RDMA%d underflow!cnt=%d\n", index, cnt_rdma_underflow[index]++); + disp_irq_log_module |= 1 << module; + rdma_underflow_irq_cnt[index]++; + } + if (reg_val & (1 << 5)) { + DISPIRQ("IRQ: RDMA%d target line!\n", index); + rdma_targetline_irq_cnt[index]++; + } + /* clear intr */ + DISP_CPU_REG_SET(DISP_REG_RDMA_INT_STATUS + index * DISP_RDMA_INDEX_OFFSET, ~reg_val); + MMProfileLogEx(ddp_mmp_get_events()->RDMA_IRQ[index], MMProfileFlagPulse, reg_val, 0); + if (reg_val & 0x18) + MMProfileLogEx(ddp_mmp_get_events()->ddp_abnormal_irq, MMProfileFlagPulse, + (rdma_underflow_irq_cnt[index] << 24) | (index << 16) | reg_val, module); + + } else if (irq == dispsys_irq[DISP_REG_COLOR]) { + DISPERR("color irq happens!! %d\n", irq); + } else if (irq == dispsys_irq[DISP_REG_MUTEX]) { + /* mutex0: perimary disp */ + /* mutex1: sub disp */ + /* mutex2: aal */ + module = DISP_MODULE_MUTEX; + reg_val = DISP_REG_GET(DISP_REG_CONFIG_MUTEX_INTSTA) & 0x7C1F; + for (mutexID = 0; mutexID < 5; mutexID++) { + if (reg_val & (0x1 << mutexID)) { + DISPIRQ("IRQ: mutex%d sof!\n", mutexID); + MMProfileLogEx(ddp_mmp_get_events()->MUTEX_IRQ[mutexID], + MMProfileFlagPulse, reg_val, 0); + } + if (reg_val & (0x1 << (mutexID + DISP_MUTEX_TOTAL))) { + DISPIRQ("IRQ: mutex%d eof!\n", mutexID); + MMProfileLogEx(ddp_mmp_get_events()->MUTEX_IRQ[mutexID], + MMProfileFlagPulse, reg_val, 1); + } + } + DISP_CPU_REG_SET(DISP_REG_CONFIG_MUTEX_INTSTA, ~reg_val); + } else if (irq == dispsys_irq[DISP_REG_AAL]) { + module = DISP_MODULE_AAL; + reg_val = DISP_REG_GET(DISP_AAL_INTSTA); + disp_aal_on_end_of_frame(); + } else if (irq == dispsys_irq[DISP_REG_CONFIG]) { /* MMSYS error intr */ + reg_val = DISP_REG_GET(DISP_REG_CONFIG_MMSYS_INTSTA) & 0x7; + if (reg_val & (1 << 0)) + DISPERR("MMSYS to MFG APB TX Error, MMSYS clock off but MFG clock on!\n"); + + if (reg_val & (1 << 1)) + DISPERR("MMSYS to MJC APB TX Error, MMSYS clock off but MJC clock on!\n"); + + if (reg_val & (1 << 2)) + DISPERR("PWM APB TX Error!\n"); + + DISP_CPU_REG_SET(DISP_REG_CONFIG_MMSYS_INTSTA, ~reg_val); + } else if (irq == dispsys_irq[DISP_REG_DPI0]) { + module = DISP_MODULE_DPI; + reg_val = DISP_REG_GET(DISP_REG_DPI_INSTA) & 0x7; + DISP_CPU_REG_SET(DISP_REG_DPI_INSTA, 0); + } else { + module = DISP_MODULE_UNKNOWN; + reg_val = 0; + DISPERR("invalid irq=%d\n ", irq); + } + + disp_invoke_irq_callbacks(module, reg_val); + if (disp_irq_log_module != 0) + wake_up_interruptible(&disp_irq_log_wq); + + MMProfileLogEx(ddp_mmp_get_events()->DDP_IRQ, MMProfileFlagEnd, irq, reg_val); + return IRQ_HANDLED; +} + + +static int disp_irq_log_kthread_func(void *data) +{ + unsigned int i = 0; + + while (1) { + wait_event_interruptible(disp_irq_log_wq, disp_irq_log_module); + DISPMSG("disp_irq_log_kthread_func dump intr register: disp_irq_log_module=%d\n", + disp_irq_log_module); + for (i = 0; i < DISP_MODULE_NUM; i++) { + if ((disp_irq_log_module & (1 << i)) != 0) + ddp_dump_reg(i); + + } + disp_irq_log_module = 0; + } + return 0; +} + +void disp_register_dev_irq(unsigned int irq_num, char *device_name) +{ + if (request_irq(irq_num, (irq_handler_t) disp_irq_handler, + IRQF_TRIGGER_LOW, device_name, NULL)) + DISPERR("ddp register irq %u failed on device %s\n", irq_num, device_name); + +} + +int disp_init_irq(void) +{ + if (irq_init) + return 0; + + irq_init = 1; + DISPMSG("disp_init_irq\n"); + + /* create irq log thread */ + init_waitqueue_head(&disp_irq_log_wq); + disp_irq_log_task = kthread_create(disp_irq_log_kthread_func, NULL, "ddp_irq_log_kthread"); + if (IS_ERR(disp_irq_log_task)) + DISPERR(" can not create disp_irq_log_task kthread\n"); + + /* wake_up_process(disp_irq_log_task); */ + return 0; +} diff --git a/drivers/misc/mediatek/video/mt6755/ddp_irq.h b/drivers/misc/mediatek/video/mt6755/ddp_irq.h new file mode 100644 index 0000000000000000000000000000000000000000..fd7f170b51229089bd386590cb590526dc159cf7 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_irq.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _H_DDP_IRQ_H +#define _H_DDP_IRQ_H + +#include "ddp_info.h" +#include + +extern atomic_t ESDCheck_byCPU; + +typedef void (*DDP_IRQ_CALLBACK)(DISP_MODULE_ENUM module, unsigned int reg_value); + +int disp_register_module_irq_callback(DISP_MODULE_ENUM module, DDP_IRQ_CALLBACK cb); +int disp_unregister_module_irq_callback(DISP_MODULE_ENUM module, DDP_IRQ_CALLBACK cb); + +int disp_register_irq_callback(DDP_IRQ_CALLBACK cb); +int disp_unregister_irq_callback(DDP_IRQ_CALLBACK cb); + +void disp_register_irq(unsigned int irq_num, char *device_name); +int disp_init_irq(void); +irqreturn_t disp_irq_handler(int irq, void *dev_id); + +int disp_irq_esd_cust_get(void); +void disp_irq_esd_cust_bycmdq(int enable); +#endif + diff --git a/drivers/misc/mediatek/video/mt6755/ddp_manager.c b/drivers/misc/mediatek/video/mt6755/ddp_manager.c new file mode 100644 index 0000000000000000000000000000000000000000..07aafbd6a0d8add3bc01a5d0480c2ff411870f17 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_manager.c @@ -0,0 +1,1859 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "ddp_manager" + +#include +#include +#include + +#include "disp_helper.h" +#include "lcm_drv.h" +#include "ddp_reg.h" +#include "ddp_path.h" +#include "ddp_irq.h" +#include "ddp_drv.h" +#include "disp_debug.h" +#include "mtkfb_debug.h" +#include "ddp_manager.h" +#include "ddp_rdma.h" +#include "ddp_ovl.h" + +#include "disp_log.h" +/* #pragma GCC optimize("O0") */ + +static int ddp_manager_init; +#define DDP_MAX_MANAGER_HANDLE (DISP_MUTEX_DDP_COUNT+DISP_MUTEX_DDP_FIRST) + +typedef struct { + volatile unsigned int init; + DISP_PATH_EVENT event; + wait_queue_head_t wq; + + volatile unsigned long long data; +} DPMGR_WQ_HANDLE; + +typedef struct { + DDP_IRQ_BIT irq_bit; +} DDP_IRQ_EVENT_MAPPING; + +typedef struct { + cmdqRecHandle cmdqhandle; + int hwmutexid; + int power_sate; + DDP_MODE mode; + struct mutex mutex_lock; + DDP_IRQ_EVENT_MAPPING irq_event_map[DISP_PATH_EVENT_NUM]; + DPMGR_WQ_HANDLE wq_list[DISP_PATH_EVENT_NUM]; + DDP_SCENARIO_ENUM scenario; + DISP_MODULE_ENUM mem_module; + disp_ddp_path_config last_config; +} ddp_path_handle_t, *ddp_path_handle; + +typedef struct { + int handle_cnt; + int mutex_idx; + int power_sate; + struct mutex mutex_lock; + int module_usage_table[DISP_MODULE_NUM]; + ddp_path_handle module_path_table[DISP_MODULE_NUM]; + ddp_path_handle handle_pool[DDP_MAX_MANAGER_HANDLE]; +} DDP_MANAGER_CONTEXT; + +#define DEFAULT_IRQ_EVENT_SCENARIO (4) +static DDP_IRQ_EVENT_MAPPING ddp_irq_event_list[DEFAULT_IRQ_EVENT_SCENARIO][DISP_PATH_EVENT_NUM] = { + { /* ovl0 path */ + {DDP_IRQ_RDMA0_DONE}, /*FRAME_DONE */ + {DDP_IRQ_RDMA0_START}, /*FRAME_START */ + {DDP_IRQ_RDMA0_REG_UPDATE}, /*FRAME_REG_UPDATE */ + {DDP_IRQ_RDMA0_TARGET_LINE}, /*FRAME_TARGET_LINE */ + {DDP_IRQ_WDMA0_FRAME_COMPLETE}, /*FRAME_COMPLETE */ + {DDP_IRQ_RDMA0_TARGET_LINE}, /*FRAME_STOP */ + {DDP_IRQ_RDMA0_REG_UPDATE}, /*IF_CMD_DONE */ + {DDP_IRQ_DSI0_EXT_TE}, /*IF_VSYNC */ + {DDP_IRQ_UNKNOWN}, /*TRIGER*/ {DDP_IRQ_AAL_OUT_END_FRAME}, /*AAL_OUT_END_EVENT */ + }, + { /* ovl1 path */ + {DDP_IRQ_RDMA1_DONE}, /*FRAME_DONE */ + {DDP_IRQ_RDMA1_START}, /*FRAME_START */ + {DDP_IRQ_RDMA1_REG_UPDATE}, /*FRAME_REG_UPDATE */ + {DDP_IRQ_RDMA1_TARGET_LINE}, /*FRAME_TARGET_LINE */ + {DDP_IRQ_WDMA1_FRAME_COMPLETE}, /*FRAME_COMPLETE */ + {DDP_IRQ_RDMA1_TARGET_LINE}, /*FRAME_STOP */ + {DDP_IRQ_RDMA1_REG_UPDATE}, /*IF_CMD_DONE */ + {DDP_IRQ_RDMA1_TARGET_LINE}, /*IF_VSYNC */ + {DDP_IRQ_UNKNOWN}, /*TRIGER*/ {DDP_IRQ_UNKNOWN}, /*AAL_OUT_END_EVENT */ + }, + { /* rdma path */ + {DDP_IRQ_RDMA2_DONE}, /*FRAME_DONE */ + {DDP_IRQ_RDMA2_START}, /*FRAME_START */ + {DDP_IRQ_RDMA2_REG_UPDATE}, /*FRAME_REG_UPDATE */ + {DDP_IRQ_RDMA2_TARGET_LINE}, /*FRAME_TARGET_LINE */ + {DDP_IRQ_UNKNOWN}, /*FRAME_COMPLETE */ + {DDP_IRQ_RDMA2_TARGET_LINE}, /*FRAME_STOP */ + {DDP_IRQ_RDMA2_REG_UPDATE}, /*IF_CMD_DONE */ + {DDP_IRQ_RDMA2_TARGET_LINE}, /*IF_VSYNC */ + {DDP_IRQ_UNKNOWN}, /*TRIGER*/ {DDP_IRQ_UNKNOWN}, /*AAL_OUT_END_EVENT */ + }, + { /* ovl0 path */ + {DDP_IRQ_RDMA0_DONE}, /*FRAME_DONE */ + {DDP_IRQ_MUTEX1_SOF}, /*FRAME_START */ + {DDP_IRQ_RDMA0_REG_UPDATE}, /*FRAME_REG_UPDATE */ + {DDP_IRQ_RDMA0_TARGET_LINE}, /*FRAME_TARGET_LINE */ + {DDP_IRQ_WDMA0_FRAME_COMPLETE}, /*FRAME_COMPLETE */ + {DDP_IRQ_RDMA0_TARGET_LINE}, /*FRAME_STOP */ + {DDP_IRQ_RDMA0_REG_UPDATE}, /*IF_CMD_DONE */ + {DDP_IRQ_DSI0_EXT_TE}, /*IF_VSYNC */ + {DDP_IRQ_UNKNOWN}, /*TRIGER*/ {DDP_IRQ_AAL_OUT_END_FRAME}, /*AAL_OUT_END_EVENT */ + } +}; + +static char *path_event_name(DISP_PATH_EVENT event) +{ + switch (event) { + case DISP_PATH_EVENT_FRAME_START: + return "FRAME_START"; + case DISP_PATH_EVENT_FRAME_DONE: + return "FRAME_DONE"; + case DISP_PATH_EVENT_FRAME_REG_UPDATE: + return "REG_UPDATE"; + case DISP_PATH_EVENT_FRAME_TARGET_LINE: + return "TARGET_LINE"; + case DISP_PATH_EVENT_FRAME_COMPLETE: + return "FRAME COMPLETE"; + case DISP_PATH_EVENT_FRAME_STOP: + return "FRAME_STOP"; + case DISP_PATH_EVENT_IF_CMD_DONE: + return "FRAME_STOP"; + case DISP_PATH_EVENT_IF_VSYNC: + return "VSYNC"; + case DISP_PATH_EVENT_TRIGGER: + return "TRIGGER"; + case DISP_PATH_EVENT_DELAYED_TRIGGER_33ms: + return "DELAY_TRIG"; + default: + return "unknown event"; + } + return "unknown event"; +} + +static DDP_MANAGER_CONTEXT *_get_context(void) +{ + static int is_context_inited; + static DDP_MANAGER_CONTEXT context; + + if (!is_context_inited) { + memset((void *)&context, 0, sizeof(DDP_MANAGER_CONTEXT)); + context.mutex_idx = (1 << DISP_MUTEX_DDP_COUNT) - 1; + mutex_init(&context.mutex_lock); + is_context_inited = 1; + } + return &context; +} + +static int path_top_clock_off(void) +{ + int i = 0; + DDP_MANAGER_CONTEXT *context = _get_context(); + + if (context->power_sate) { + for (i = 0; i < DDP_MAX_MANAGER_HANDLE; i++) { + if (context->handle_pool[i] != NULL + && context->handle_pool[i]->power_sate != 0) + return 0; + + } + context->power_sate = 0; + ddp_path_top_clock_off(); + } + return 0; +} + +static int path_top_clock_on(void) +{ + DDP_MANAGER_CONTEXT *context = _get_context(); + + if (!context->power_sate) { + context->power_sate = 1; + ddp_path_top_clock_on(); + } + return 0; +} + +static int module_power_off(DISP_MODULE_ENUM module) +{ + if (module == DISP_MODULE_DSI0) + return 0; + + if (ddp_modules_driver[module] != 0) { + if (ddp_modules_driver[module]->power_off != 0) { + DISPDBG("%s power off\n", ddp_get_module_name(module)); + ddp_modules_driver[module]->power_off(module, NULL); /* now just 0; */ + } + } + return 0; +} + +static int module_power_on(DISP_MODULE_ENUM module) +{ + if (module == DISP_MODULE_DSI0) + return 0; + + if (ddp_modules_driver[module] != 0) { + if (ddp_modules_driver[module]->power_on != 0) { + DISPDBG("%s power on\n", ddp_get_module_name(module)); + ddp_modules_driver[module]->power_on(module, NULL); /* now just 0; */ + } + } + return 0; +} + +static ddp_path_handle find_handle_by_module(DISP_MODULE_ENUM module) +{ + return _get_context()->module_path_table[module]; +} + +int dpmgr_module_notify(DISP_MODULE_ENUM module, DISP_PATH_EVENT event) +{ + ddp_path_handle handle = find_handle_by_module(module); + + MMProfileLogEx(ddp_mmp_get_events()->primary_display_aalod_trigger, MMProfileFlagPulse, + module, event); + return dpmgr_signal_event(handle, event); + return 0; +} + +static int assign_default_irqs_table(DDP_SCENARIO_ENUM scenario, DDP_IRQ_EVENT_MAPPING *irq_events) +{ + int idx = 0; + + switch (scenario) { + case DDP_SCENARIO_PRIMARY_DISP: + case DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP: + case DDP_SCENARIO_PRIMARY_RDMA0_DISP: + case DDP_SCENARIO_PRIMARY_BYPASS_RDMA: + case DDP_SCENARIO_PRIMARY_DITHER_MEMOUT: + case DDP_SCENARIO_PRIMARY_UFOE_MEMOUT: + case DDP_SCENARIO_PRIMARY_ALL: + case DDP_SCENARIO_DITHER_1TO2: + case DDP_SCENARIO_UFOE_1TO2: + idx = 0; + break; + case DDP_SCENARIO_SUB_DISP: + case DDP_SCENARIO_SUB_RDMA1_DISP: + case DDP_SCENARIO_SUB_OVL_MEMOUT: + case DDP_SCENARIO_SUB_ALL: + idx = 1; + break; + case DDP_SCENARIO_PRIMARY_OVL_MEMOUT: + idx = 3; + break; + default: + DISPERR("unknown scenario %d\n", scenario); + } + memcpy(irq_events, ddp_irq_event_list[idx], sizeof(ddp_irq_event_list[idx])); + return 0; +} + +static int acquire_mutex(DDP_SCENARIO_ENUM scenario) +{ +/* /: primay use mutex 0 */ + int mutex_id = 0; + DDP_MANAGER_CONTEXT *content = _get_context(); + int mutex_idx_free = content->mutex_idx; + + ASSERT(scenario >= 0 && scenario < DDP_SCENARIO_MAX); + while (mutex_idx_free) { + if (mutex_idx_free & 0x1) { + content->mutex_idx &= (~(0x1 << mutex_id)); + mutex_id += DISP_MUTEX_DDP_FIRST; + break; + } + mutex_idx_free >>= 1; + ++mutex_id; + } + ASSERT(mutex_id < (DISP_MUTEX_DDP_FIRST + DISP_MUTEX_DDP_COUNT)); + DISPDBG("scenario %s acquire mutex %d , left mutex 0x%x!\n", + ddp_get_scenario_name(scenario), mutex_id, content->mutex_idx); + return mutex_id; +} + +static int release_mutex(int mutex_idx) +{ + DDP_MANAGER_CONTEXT *content = _get_context(); + + ASSERT(mutex_idx < (DISP_MUTEX_DDP_FIRST + DISP_MUTEX_DDP_COUNT)); + content->mutex_idx |= 1 << (mutex_idx - DISP_MUTEX_DDP_FIRST); + DISPDBG("release mutex %d , left mutex 0x%x!\n", mutex_idx, content->mutex_idx); + return 0; +} + +int dpmgr_path_set_video_mode(disp_path_handle dp_handle, int is_vdo_mode) +{ + ddp_path_handle handle = NULL; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + handle->mode = is_vdo_mode ? DDP_VIDEO_MODE : DDP_CMD_MODE; + DISPDBG("set scenario %s mode: %s\n", ddp_get_scenario_name(handle->scenario), + is_vdo_mode ? "Video_Mode" : "Cmd_Mode"); + return 0; +} + +disp_path_handle dpmgr_create_path(DDP_SCENARIO_ENUM scenario, cmdqRecHandle cmdq_handle) +{ + int i = 0; + int module_name; + ddp_path_handle path_handle = NULL; + int *modules = ddp_get_scenario_list(scenario); + int module_num = ddp_get_module_num(scenario); + DDP_MANAGER_CONTEXT *content = _get_context(); + + path_handle = kzalloc(sizeof(ddp_path_handle_t), GFP_KERNEL); + if (NULL != path_handle) { + path_handle->cmdqhandle = cmdq_handle; + path_handle->scenario = scenario; + path_handle->hwmutexid = acquire_mutex(scenario); + path_handle->last_config.path_handle = path_handle; + assign_default_irqs_table(scenario, path_handle->irq_event_map); + DISPDBG("create handle %p on scenario %s\n", path_handle, + ddp_get_scenario_name(scenario)); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + DISPDBG(" scenario %s include module %s\n", + ddp_get_scenario_name(scenario), + ddp_get_module_name(module_name)); + content->module_usage_table[module_name]++; + content->module_path_table[module_name] = path_handle; + } + content->handle_cnt++; + content->handle_pool[path_handle->hwmutexid] = path_handle; + } else { + DISPERR("Fail to create handle on scenario %s\n", + ddp_get_scenario_name(scenario)); + } + return path_handle; +} + +int dpmgr_get_scenario(disp_path_handle dp_handle) +{ + ddp_path_handle handle; + + handle = (ddp_path_handle) dp_handle; + return handle->scenario; +} + +static int _dpmgr_path_connect(DDP_SCENARIO_ENUM scenario, void *handle) +{ + int i = 0, module; + int *modules = ddp_get_scenario_list(scenario); + int module_num = ddp_get_module_num(scenario); + + ddp_connect_path(scenario, handle); + + for (i = 0; i < module_num; i++) { + module = modules[i]; + if (ddp_modules_driver[module] && ddp_modules_driver[module]->connect) { + int prev = i == 0 ? DISP_MODULE_UNKNOWN : modules[i - 1]; + int next = i == module_num - 1 ? DISP_MODULE_UNKNOWN : modules[i + 1]; + + ddp_modules_driver[module]->connect(module, prev, next, 1, handle); + } + } + + return 0; +} + +static int _dpmgr_path_disconnect(DDP_SCENARIO_ENUM scenario, void *handle) +{ + int i = 0, module; + int *modules = ddp_get_scenario_list(scenario); + int module_num = ddp_get_module_num(scenario); + + ddp_disconnect_path(scenario, handle); + + for (i = 0; i < module_num; i++) { + module = modules[i]; + if (ddp_modules_driver[module] && ddp_modules_driver[module]->connect) { + int prev = i == 0 ? DISP_MODULE_UNKNOWN : modules[i - 1]; + int next = i == module_num - 1 ? DISP_MODULE_UNKNOWN : modules[i + 1]; + + ddp_modules_driver[module]->connect(module, prev, next, 1, handle); + } + } + + return 0; +} + + +int dpmgr_modify_path_power_on_new_modules(disp_path_handle dp_handle, + DDP_SCENARIO_ENUM new_scenario, int sw_only) +{ + int i = 0; + int module_name = 0; + DDP_MANAGER_CONTEXT *content = _get_context(); + ddp_path_handle handle; + int *new_modules; + int new_module_num; + + handle = (ddp_path_handle) dp_handle; + new_modules = ddp_get_scenario_list(new_scenario); + new_module_num = ddp_get_module_num(new_scenario); + + for (i = 0; i < new_module_num; i++) { + module_name = new_modules[i]; + if (content->module_usage_table[module_name] == 0) { /* new module 's count =0 */ + content->module_usage_table[module_name]++; + content->module_path_table[module_name] = handle; + if (!sw_only) + module_power_on(module_name); + } + } + return 0; + +} + +/* NOTES: modify path should call API like this : + old_scenario = dpmgr_get_scenario(handle); + dpmgr_modify_path_power_on_new_modules(); + dpmgr_modify_path(); + after cmdq handle exec done: + dpmgr_modify_path_power_off_old_modules(); +*/ +int dpmgr_modify_path(disp_path_handle dp_handle, DDP_SCENARIO_ENUM new_scenario, + cmdqRecHandle cmdq_handle, DDP_MODE mode, int sw_only) +{ + ddp_path_handle handle; + DDP_SCENARIO_ENUM old_scenario; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + old_scenario = handle->scenario; + handle->cmdqhandle = cmdq_handle; + handle->scenario = new_scenario; + DISPMSG("modify handle %p from %s to %s\n", handle, ddp_get_scenario_name(old_scenario), + ddp_get_scenario_name(new_scenario)); + + if (!sw_only) { + /* mutex set will clear old settings */ + ddp_mutex_set(handle->hwmutexid, new_scenario, mode, cmdq_handle); + + ddp_mutex_Interrupt_enable(handle->hwmutexid, cmdq_handle); + /* disconnect old path first */ + _dpmgr_path_disconnect(old_scenario, cmdq_handle); + + /* connect new path */ + _dpmgr_path_connect(new_scenario, cmdq_handle); + + } + return 0; +} + +int dpmgr_modify_path_power_off_old_modules(DDP_SCENARIO_ENUM old_scenario, + DDP_SCENARIO_ENUM new_scenario, int sw_only) +{ + int i = 0; + int module_name = 0; + + DDP_MANAGER_CONTEXT *content = _get_context(); + + int *old_modules = ddp_get_scenario_list(old_scenario); + int old_module_num = ddp_get_module_num(old_scenario); + + for (i = 0; i < old_module_num; i++) { + module_name = old_modules[i]; + if (!ddp_is_module_in_scenario(new_scenario, module_name)) { + content->module_usage_table[module_name]--; + content->module_path_table[module_name] = NULL; + if (!sw_only) + module_power_off(module_name); + } + } + + return 0; +} + + +int dpmgr_destroy_path_handle(disp_path_handle dp_handle) +{ + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + DDP_MANAGER_CONTEXT *content; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + + if (handle != NULL) { + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + content = _get_context(); + + DISPDBG("destroy path handle %p on scenario %s\n", handle, + ddp_get_scenario_name(handle->scenario)); + + release_mutex(handle->hwmutexid); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + content->module_usage_table[module_name]--; + content->module_path_table[module_name] = NULL; + } + content->handle_cnt--; + ASSERT(content->handle_cnt >= 0); + content->handle_pool[handle->hwmutexid] = NULL; + kfree(handle); + } + return 0; +} + +int dpmgr_destroy_path(disp_path_handle dp_handle, cmdqRecHandle cmdq_handle) +{ + + ddp_path_handle handle; + + handle = (ddp_path_handle) dp_handle; + + if (handle) + _dpmgr_path_disconnect(handle->scenario, cmdq_handle); + + dpmgr_destroy_path_handle(dp_handle); + return 0; +} + +int dpmgr_path_memout_clock(disp_path_handle dp_handle, int clock_switch) +{ +#if 0 + ASSERT(dp_handle != NULL); + ddp_path_handle handle; + + handle = (ddp_path_handle) dp_handle; + handle->mem_module = + ddp_is_scenario_on_primary(handle->scenario) ? DISP_MODULE_WDMA0 : DISP_MODULE_WDMA1; + if (handle->mem_module == DISP_MODULE_WDMA0 || handle->mem_module == DISP_MODULE_WDMA1) { + if (ddp_modules_driver[handle->mem_module] != 0) { + if (clock_switch) { + if (ddp_modules_driver[handle->mem_module]->power_on != 0) + ddp_modules_driver[handle->mem_module]->power_on(handle-> + mem_module, + NULL); + + } else { + if (ddp_modules_driver[handle->mem_module]->power_off != 0) + ddp_modules_driver[handle->mem_module]->power_off(handle-> + mem_module, + NULL); + + handle->mem_module = DISP_MODULE_UNKNOWN; + } + } + return 0; + } + return -1; +#endif + return 0; +} + +int dpmgr_path_add_memout(disp_path_handle dp_handle, DISP_MODULE_ENUM engine, void *cmdq_handle) +{ + + ddp_path_handle handle; + DISP_MODULE_ENUM wdma; + DDP_MANAGER_CONTEXT *context; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + ASSERT(handle->scenario == DDP_SCENARIO_PRIMARY_DISP + || handle->scenario == DDP_SCENARIO_SUB_DISP + || handle->scenario == DDP_SCENARIO_PRIMARY_OVL_MEMOUT); + wdma = + ddp_is_scenario_on_primary(handle->scenario) ? DISP_MODULE_WDMA0 : DISP_MODULE_WDMA1; + + if (ddp_is_module_in_scenario(handle->scenario, wdma) == 1) { + DISPERR("dpmgr_path_add_memout error, wdma is already in scenario=%s\n", + ddp_get_scenario_name(handle->scenario)); + return -1; + } + /* update contxt */ + context = _get_context(); + + context->module_usage_table[wdma]++; + context->module_path_table[wdma] = handle; + if (engine == DISP_MODULE_OVL0) { + handle->scenario = DDP_SCENARIO_PRIMARY_ALL; + } else if (engine == DISP_MODULE_OVL1) { + handle->scenario = DDP_SCENARIO_SUB_ALL; + } else if (engine == DISP_MODULE_DITHER) { + handle->scenario = DDP_SCENARIO_DITHER_1TO2; + } else if (engine == DISP_MODULE_UFOE) { + handle->scenario = DDP_SCENARIO_UFOE_1TO2; + } else { + pr_err("%s error: engine=%d\n", __func__, engine); + BUG(); + } + /* update connected */ + _dpmgr_path_connect(handle->scenario, cmdq_handle); + ddp_mutex_set(handle->hwmutexid, handle->scenario, handle->mode, cmdq_handle); + + /* wdma just need start. */ + if (ddp_modules_driver[wdma] != 0) { + if (ddp_modules_driver[wdma]->init != 0) + ddp_modules_driver[wdma]->init(wdma, cmdq_handle); + + if (ddp_modules_driver[wdma]->start != 0) + ddp_modules_driver[wdma]->start(wdma, cmdq_handle); + + } + return 0; +} + +int dpmgr_path_remove_memout(disp_path_handle dp_handle, void *cmdq_handle) +{ + + DDP_SCENARIO_ENUM dis_scn, new_scn; + ddp_path_handle handle; + DISP_MODULE_ENUM wdma; + DDP_MANAGER_CONTEXT *context; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + ASSERT(handle->scenario == DDP_SCENARIO_PRIMARY_DISP + || handle->scenario == DDP_SCENARIO_PRIMARY_ALL + || handle->scenario == DDP_SCENARIO_DITHER_1TO2 + || handle->scenario == DDP_SCENARIO_UFOE_1TO2 + || handle->scenario == DDP_SCENARIO_SUB_DISP + || handle->scenario == DDP_SCENARIO_SUB_ALL); + wdma = + ddp_is_scenario_on_primary(handle->scenario) ? DISP_MODULE_WDMA0 : DISP_MODULE_WDMA1; + + if (ddp_is_module_in_scenario(handle->scenario, wdma) == 0) { + DISPERR("dpmgr_path_remove_memout error, wdma is not in scenario=%s\n", + ddp_get_scenario_name(handle->scenario)); + return -1; + } + /* update contxt */ + context = _get_context(); + + context->module_usage_table[wdma]--; + context->module_path_table[wdma] = 0; + /* wdma just need stop */ + if (ddp_modules_driver[wdma] != 0) { + if (ddp_modules_driver[wdma]->stop != 0) + ddp_modules_driver[wdma]->stop(wdma, cmdq_handle); + + if (ddp_modules_driver[wdma]->deinit != 0) + ddp_modules_driver[wdma]->deinit(wdma, cmdq_handle); + + } + if (handle->scenario == DDP_SCENARIO_PRIMARY_ALL) { + dis_scn = DDP_SCENARIO_PRIMARY_OVL_MEMOUT; + new_scn = DDP_SCENARIO_PRIMARY_DISP; + } else if (handle->scenario == DDP_SCENARIO_DITHER_1TO2) { + dis_scn = DDP_SCENARIO_PRIMARY_DITHER_MEMOUT; + new_scn = DDP_SCENARIO_PRIMARY_DISP; + } else if (handle->scenario == DDP_SCENARIO_UFOE_1TO2) { + dis_scn = DDP_SCENARIO_PRIMARY_UFOE_MEMOUT; + new_scn = DDP_SCENARIO_PRIMARY_DISP; + + } else if (handle->scenario == DDP_SCENARIO_SUB_ALL) { + dis_scn = DDP_SCENARIO_SUB_OVL_MEMOUT; + new_scn = DDP_SCENARIO_SUB_DISP; + } else { + pr_err("%s: error scenario =%d\n", __func__, handle->scenario); + BUG(); + } + _dpmgr_path_disconnect(dis_scn, cmdq_handle); + handle->scenario = new_scn; + /* update connected */ + _dpmgr_path_connect(handle->scenario, cmdq_handle); + ddp_mutex_set(handle->hwmutexid, handle->scenario, handle->mode, cmdq_handle); + + return 0; +} + +int dpmgr_insert_ovl1_sub(disp_path_handle dp_handle, void *cmdq_handle) +{ + int ret = 0; + ddp_path_handle handle; + DDP_MANAGER_CONTEXT *context; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle)dp_handle; + if ((handle->scenario != DDP_SCENARIO_SUB_RDMA1_DISP) && (handle->scenario != DDP_SCENARIO_SUB_DISP)) { + DISPERR("dpmgr_insert_ovl1_sub error, handle->scenario=%s\n", + ddp_get_scenario_name(handle->scenario)); + return -1; + } + + if (ddp_is_module_in_scenario(handle->scenario, DISP_MODULE_OVL1) == 1) { + DISPMSG("dpmgr_insert_ovl1_sub, OVL1 already in the path\n"); + return -1; + } + + DISPDBG("dpmgr_insert_ovl1_sub\n"); + /* update contxt*/ + context = _get_context(); + context->module_usage_table[DISP_MODULE_OVL1]++; + context->module_path_table[DISP_MODULE_OVL1] = handle; + + /* update connected*/ + ddp_connect_path(DDP_SCENARIO_SUB_DISP, cmdq_handle); + ret = ddp_mutex_set(handle->hwmutexid, DDP_SCENARIO_SUB_DISP, handle->mode, cmdq_handle); + + handle->scenario = DDP_SCENARIO_SUB_DISP; + + /*ovl1 just need start.*/ + if (ddp_modules_driver[DISP_MODULE_OVL1] != 0) { + if (ddp_modules_driver[DISP_MODULE_OVL1]->init != 0) + ddp_modules_driver[DISP_MODULE_OVL1]->init(DISP_MODULE_OVL1, cmdq_handle); + + if (ddp_modules_driver[DISP_MODULE_OVL1]->start != 0) + ddp_modules_driver[DISP_MODULE_OVL1]->start(DISP_MODULE_OVL1, cmdq_handle); + } + + return ret; +} + +int dpmgr_remove_ovl1_sub(disp_path_handle dp_handle, void *cmdq_handle) +{ + int ret = 0; + ddp_path_handle handle; + DDP_MANAGER_CONTEXT *context; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle)dp_handle; + if ((handle->scenario != DDP_SCENARIO_SUB_RDMA1_DISP) && (handle->scenario != DDP_SCENARIO_SUB_DISP)) { + DISPERR("dpmgr_remove_ovl1_sub error, handle->scenario=%s\n", ddp_get_scenario_name(handle->scenario)); + return -1; + } + + if (ddp_is_module_in_scenario(handle->scenario, DISP_MODULE_OVL1) == 0) { + DISPMSG("dpmgr_remove_ovl1_sub, OVL1 already not in the path\n"); + return -1; + } + + DISPDBG("dpmgr_remove_ovl1_sub\n"); + /* update contxt */ + context = _get_context(); + context->module_usage_table[DISP_MODULE_OVL1]--; + context->module_path_table[DISP_MODULE_OVL1] = 0; + + ddp_disconnect_path(handle->scenario, cmdq_handle); + ddp_connect_path(DDP_SCENARIO_SUB_RDMA1_DISP, cmdq_handle); + ret = ddp_mutex_set(handle->hwmutexid, DDP_SCENARIO_SUB_RDMA1_DISP, handle->mode, cmdq_handle); + + handle->scenario = DDP_SCENARIO_SUB_RDMA1_DISP; + + /*ovl1 just need stop */ + if (ddp_modules_driver[DISP_MODULE_OVL1] != 0) { + if (ddp_modules_driver[DISP_MODULE_OVL1]->stop != 0) + ddp_modules_driver[DISP_MODULE_OVL1]->stop(DISP_MODULE_OVL1, cmdq_handle); + + if (ddp_modules_driver[DISP_MODULE_OVL1]->deinit != 0) + ddp_modules_driver[DISP_MODULE_OVL1]->deinit(DISP_MODULE_OVL1, cmdq_handle); + } + + return ret; +} + +int dpmgr_path_set_dst_module(disp_path_handle dp_handle, DISP_MODULE_ENUM dst_module) +{ + ddp_path_handle handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + ASSERT((handle->scenario >= 0 && handle->scenario < DDP_SCENARIO_MAX)); + DISPDBG("set dst module on scenario %s, module %s\n", + ddp_get_scenario_name(handle->scenario), ddp_get_module_name(dst_module)); + return ddp_set_dst_module(handle->scenario, dst_module); +} + +int dpmgr_path_get_mutex(disp_path_handle dp_handle) +{ + ddp_path_handle handle = NULL; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + return handle->hwmutexid; +} + +DISP_MODULE_ENUM dpmgr_path_get_dst_module(disp_path_handle dp_handle) +{ + ddp_path_handle handle; + DISP_MODULE_ENUM dst_module; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + ASSERT((handle->scenario >= 0 && handle->scenario < DDP_SCENARIO_MAX)); + dst_module = ddp_get_dst_module(handle->scenario); + + DISPDBG("get dst module on scenario %s, module %s\n", + ddp_get_scenario_name(handle->scenario), ddp_get_module_name(dst_module)); + return dst_module; +} + +enum dst_module_type dpmgr_path_get_dst_module_type(disp_path_handle dp_handle) +{ + DISP_MODULE_ENUM dst_module; + + dst_module = dpmgr_path_get_dst_module(dp_handle); + if (dst_module == DISP_MODULE_WDMA0 || dst_module == DISP_MODULE_WDMA1) + return DST_MOD_WDMA; + else + return DST_MOD_REAL_TIME; +} + + +int dpmgr_path_connect(disp_path_handle dp_handle, int encmdq) +{ + ddp_path_handle handle; + cmdqRecHandle cmdqHandle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + + _dpmgr_path_connect(handle->scenario, cmdqHandle); + + ddp_mutex_set(handle->hwmutexid, handle->scenario, handle->mode, cmdqHandle); + ddp_mutex_Interrupt_enable(handle->hwmutexid, cmdqHandle); + return 0; +} + +int dpmgr_path_disconnect(disp_path_handle dp_handle, int encmdq) +{ + ddp_path_handle handle; + cmdqRecHandle cmdqHandle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + + DISPDBG("dpmgr_path_disconnect on scenario %s\n", + ddp_get_scenario_name(handle->scenario)); + ddp_mutex_clear(handle->hwmutexid, cmdqHandle); + ddp_mutex_Interrupt_disable(handle->hwmutexid, cmdqHandle); + _dpmgr_path_disconnect(handle->scenario, cmdqHandle); + return 0; +} + +int dpmgr_path_init(disp_path_handle dp_handle, int encmdq) +{ + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + cmdqRecHandle cmdqHandle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + + DISPDBG("path init on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + /* open top clock */ + path_top_clock_on(); + /* seting mutex */ + ddp_mutex_set(handle->hwmutexid, handle->scenario, handle->mode, cmdqHandle); + ddp_mutex_Interrupt_enable(handle->hwmutexid, cmdqHandle); + /* connect path; */ + _dpmgr_path_connect(handle->scenario, cmdqHandle); + + /* each module init */ + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->init != 0) { + DISPDBG("scenario %s init module %s\n", + ddp_get_scenario_name(handle->scenario), + ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->init(module_name, cmdqHandle); + } + if (ddp_modules_driver[module_name]->set_listener != 0) + ddp_modules_driver[module_name]->set_listener(module_name, + dpmgr_module_notify); + + } + } + /* after init this path will power on; */ + handle->power_sate = 1; + return 0; +} + +int dpmgr_path_deinit(disp_path_handle dp_handle, int encmdq) +{ + int i = 0; + int module_name; + int *modules; + int module_num; + cmdqRecHandle cmdqHandle; + ddp_path_handle handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + + DISPDBG("path deinit on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + ddp_mutex_Interrupt_disable(handle->hwmutexid, cmdqHandle); + ddp_mutex_clear(handle->hwmutexid, cmdqHandle); + _dpmgr_path_disconnect(handle->scenario, cmdqHandle); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->deinit != 0) { + DISPDBG("scenario %s deinit module %s\n", + ddp_get_scenario_name(handle->scenario), + ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->deinit(module_name, cmdqHandle); + } + if (ddp_modules_driver[module_name]->set_listener != 0) + ddp_modules_driver[module_name]->set_listener(module_name, NULL); + + } + } + handle->power_sate = 0; + /* close top clock when last path init */ + path_top_clock_off(); + return 0; +} + +int dpmgr_path_start(disp_path_handle dp_handle, int encmdq) +{ + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + cmdqRecHandle cmdqHandle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + + DISPMSG("path start on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->start != 0) { + DISPDBG("scenario %s start module %s\n", + ddp_get_scenario_name(handle->scenario), + ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->start(module_name, cmdqHandle); + } + } + } + return 0; +} + +int dpmgr_path_stop(disp_path_handle dp_handle, int encmdq) +{ + + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + cmdqRecHandle cmdqHandle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + + DISPMSG("path stop on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + for (i = module_num - 1; i >= 0; i--) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->stop != 0) { + DISPDBG("scenario %s stop module %s\n", + ddp_get_scenario_name(handle->scenario), + ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->stop(module_name, cmdqHandle); + } + } + } + return 0; +} + +int dpmgr_path_ioctl(disp_path_handle dp_handle, void *cmdq_handle, DDP_IOCTL_NAME ioctl_cmd, + void *params) +{ + int i = 0; + int ret = 0; + int module_name; + int *modules; + int module_num; + ddp_path_handle handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPDBG("path IOCTL on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + for (i = module_num - 1; i >= 0; i--) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->ioctl != 0) { + ret += + ddp_modules_driver[module_name]->ioctl(module_name, cmdq_handle, + ioctl_cmd, params); + } + } + } + return ret; +} + +int dpmgr_path_enable_irq(disp_path_handle dp_handle, void *cmdq_handle, DDP_IRQ_LEVEL irq_level) +{ + int i = 0; + int ret = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPDBG("path enable irq on scenario %s, level %d\n", + ddp_get_scenario_name(handle->scenario), irq_level); + + if (irq_level != DDP_IRQ_LEVEL_ALL) + ddp_mutex_Interrupt_disable(handle->hwmutexid, cmdq_handle); + else + ddp_mutex_Interrupt_enable(handle->hwmutexid, cmdq_handle); + + + for (i = module_num - 1; i >= 0; i--) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] && ddp_modules_driver[module_name]->enable_irq) { + DISPDBG("scenario %s, module %s enable irq level %d\n", + ddp_get_scenario_name(handle->scenario), + ddp_get_module_name(module_name), irq_level); + ret += + ddp_modules_driver[module_name]->enable_irq(module_name, cmdq_handle, + irq_level); + } + } + return ret; +} + +int dpmgr_path_reset(disp_path_handle dp_handle, int encmdq) +{ + int i = 0; + int ret = 0; + int error = 0; + int module_name; + int *modules; + int module_num; + ddp_path_handle handle; + cmdqRecHandle cmdqHandle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + + DISPMSG("path reset on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + /* first reset mutex */ + ddp_mutex_reset(handle->hwmutexid, cmdqHandle); + + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->reset != 0) { + DISPDBG("scenario %s reset module %s\n", + ddp_get_scenario_name(handle->scenario), + ddp_get_module_name(module_name)); + ret = + ddp_modules_driver[module_name]->reset(module_name, cmdqHandle); + if (ret != 0) + error++; + + } + } + } + return error > 0 ? -1 : 0; +} + +static unsigned int dpmgr_is_PQ(DISP_MODULE_ENUM module) +{ + unsigned int isPQ = 0; + + switch (module) { + case DISP_MODULE_COLOR0: + case DISP_MODULE_CCORR: + case DISP_MODULE_AAL: + case DISP_MODULE_GAMMA: + case DISP_MODULE_DITHER: + /* case DISP_MODULE_PWM0 : */ + isPQ = 1; + break; + default: + isPQ = 0; + } + + return isPQ; +} + +int dpmgr_path_config(disp_path_handle dp_handle, disp_ddp_path_config *config, void *cmdq_handle) +{ + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPDBG("path config ovl %d, rdma %d, wdma %d, dst %d on handle %p scenario %s\n", + config->ovl_dirty, + config->rdma_dirty, + config->wdma_dirty, + config->dst_dirty, handle, ddp_get_scenario_name(handle->scenario)); + memcpy(&handle->last_config, config, sizeof(disp_ddp_path_config)); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->config != 0) { + DISPDBG("scenario %s config module %s\n", + ddp_get_scenario_name(handle->scenario), + ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->config(module_name, config, + cmdq_handle); + } + + if (disp_helper_get_option(DISP_OPT_BYPASS_PQ) + && dpmgr_is_PQ(module_name) == 1) { + if (ddp_modules_driver[module_name]->bypass != NULL) + ddp_modules_driver[module_name]->bypass(module_name, 1); + } + + } + } + return 0; +} + +disp_ddp_path_config *dpmgr_path_get_last_config_notclear(disp_path_handle dp_handle) +{ + ddp_path_handle handle = (ddp_path_handle) dp_handle; + + ASSERT(dp_handle != NULL); + return &handle->last_config; +} + +disp_ddp_path_config *dpmgr_path_get_last_config(disp_path_handle dp_handle) +{ + ddp_path_handle handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + handle->last_config.ovl_dirty = 0; + handle->last_config.rdma_dirty = 0; + handle->last_config.wdma_dirty = 0; + handle->last_config.dst_dirty = 0; + handle->last_config.ovl_layer_dirty = 0; + handle->last_config.ovl_layer_scanned = 0; + return &handle->last_config; +} + +void dpmgr_get_input_address(disp_path_handle dp_handle, unsigned long *addr) +{ + ddp_path_handle handle; + int *modules; + + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + + if (modules[0] == DISP_MODULE_OVL0 || modules[0] == DISP_MODULE_OVL1) + ovl_get_address(modules[0], addr); + else if (modules[0] == DISP_MODULE_RDMA0 || modules[0] == DISP_MODULE_RDMA1 + || modules[0] == DISP_MODULE_RDMA2) + rdma_get_address(modules[0], addr); +} + +int dpmgr_path_build_cmdq(disp_path_handle dp_handle, void *trigger_loop_handle, CMDQ_STATE state, + int reverse) +{ + int ret = 0; + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + if (reverse) { + for (i = module_num - 1; i >= 0; i--) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] + && ddp_modules_driver[module_name]->build_cmdq) { + ret = + ddp_modules_driver[module_name]->build_cmdq(module_name, + trigger_loop_handle, + state); + } + } + } else { + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] + && ddp_modules_driver[module_name]->build_cmdq) { + ret = + ddp_modules_driver[module_name]->build_cmdq(module_name, + trigger_loop_handle, + state); + } + } + } + return ret; +} + +int dpmgr_path_trigger(disp_path_handle dp_handle, void *trigger_loop_handle, int encmdq) +{ + ddp_path_handle handle; + int *modules; + int module_num; + int i; + int module_name; + cmdqRecHandle cmdqHandle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + DISPDBG("dpmgr_path_trigger on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + ddp_mutex_enable(handle->hwmutexid, handle->scenario, trigger_loop_handle); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->trigger != 0) { + DISPDBG("%s trigger\n", ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->trigger(module_name, + trigger_loop_handle); + } + } + } + return 0; +} + +int dpmgr_path_flush(disp_path_handle dp_handle, int encmdq) +{ + ddp_path_handle handle; + cmdqRecHandle cmdqHandle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + cmdqHandle = encmdq ? handle->cmdqhandle : NULL; + DISPDBG("path flush on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + return ddp_mutex_enable(handle->hwmutexid, handle->scenario, cmdqHandle); +} + +int dpmgr_path_power_off(disp_path_handle dp_handle, CMDQ_SWITCH encmdq) +{ + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPMSG("path power off on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] && ddp_modules_driver[module_name]->power_off) { + DISPDBG(" %s power off\n", ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->power_off(module_name, + encmdq ? handle->cmdqhandle : + NULL); + } + } + handle->power_sate = 0; + path_top_clock_off(); + return 0; +} + +int dpmgr_path_power_on(disp_path_handle dp_handle, CMDQ_SWITCH encmdq) +{ + int i = 0; + int module_name; + int *modules; + int module_num; + ddp_path_handle handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPMSG("path power on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + path_top_clock_on(); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] && ddp_modules_driver[module_name]->power_on) { + DISPDBG("%s power on\n", ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->power_on(module_name, + encmdq ? handle->cmdqhandle : + NULL); + } + } + /* modules on this path will resume power on; */ + handle->power_sate = 1; + return 0; +} + +int dpmgr_path_power_off_bypass_pwm(disp_path_handle dp_handle, CMDQ_SWITCH encmdq) +{ + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPMSG("path power off on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] && ddp_modules_driver[module_name]->power_off) { + if (module_name == DISP_MODULE_PWM0) + DISPMSG(" %s power off -- bypass\n", ddp_get_module_name(module_name)); + else { + DISPDBG(" %s power off\n", ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->power_off(module_name, + encmdq ? handle->cmdqhandle : + NULL); + } + } + } + handle->power_sate = 0; + path_top_clock_off(); + return 0; +} + +int dpmgr_path_power_on_bypass_pwm(disp_path_handle dp_handle, CMDQ_SWITCH encmdq) +{ + int i = 0; + int module_name; + int *modules; + int module_num; + ddp_path_handle handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPMSG("path power on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + path_top_clock_on(); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] && ddp_modules_driver[module_name]->power_on) { + if (module_name == DISP_MODULE_PWM0) + DISPMSG(" %s power on -- bypass\n", ddp_get_module_name(module_name)); + else { + DISPDBG("%s power on\n", ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->power_on(module_name, + encmdq ? handle->cmdqhandle : + NULL); + } + } + } + /* modules on this path will resume power on; */ + handle->power_sate = 1; + return 0; +} +static int is_module_in_path(DISP_MODULE_ENUM module, ddp_path_handle handle) +{ + DDP_MANAGER_CONTEXT *context = _get_context(); + + ASSERT(module < DISP_MODULE_UNKNOWN); + if (context->module_path_table[module] == handle) + return 1; + + return 0; +} + +int dpmgr_path_user_cmd(disp_path_handle dp_handle, int msg, unsigned long arg, void *cmdqhandle) +{ + int ret = -1; + DISP_MODULE_ENUM dst = DISP_MODULE_UNKNOWN; + ddp_path_handle handle = NULL; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + /* DISPDBG("dpmgr_path_user_cmd msg 0x%08x\n",msg); */ + switch (msg) { + case DISP_IOCTL_AAL_EVENTCTL: + case DISP_IOCTL_AAL_GET_HIST: + case DISP_IOCTL_AAL_INIT_REG: + case DISP_IOCTL_AAL_SET_PARAM: + /* TODO: just for verify rootcause, will be removed soon */ +#ifndef CONFIG_FOR_SOURCE_PQ + if (is_module_in_path(DISP_MODULE_AAL, handle)) { + if (ddp_modules_driver[DISP_MODULE_AAL]->cmd != NULL) + ret = + ddp_modules_driver[DISP_MODULE_AAL]->cmd(DISP_MODULE_AAL, msg, + arg, cmdqhandle); + + } +#endif + break; + case DISP_IOCTL_SET_GAMMALUT: + if (ddp_modules_driver[DISP_MODULE_GAMMA]->cmd != NULL) + ret = + ddp_modules_driver[DISP_MODULE_GAMMA]->cmd(DISP_MODULE_GAMMA, msg, arg, + cmdqhandle); + break; + case DISP_IOCTL_SET_CCORR: + if (ddp_modules_driver[DISP_MODULE_CCORR]->cmd != NULL) + ret = + ddp_modules_driver[DISP_MODULE_CCORR]->cmd(DISP_MODULE_CCORR, msg, arg, + cmdqhandle); + break; + + case DISP_IOCTL_SET_PQPARAM: + case DISP_IOCTL_GET_PQPARAM: + case DISP_IOCTL_SET_PQINDEX: + case DISP_IOCTL_GET_PQINDEX: + case DISP_IOCTL_SET_COLOR_REG: + case DISP_IOCTL_SET_TDSHPINDEX: + case DISP_IOCTL_GET_TDSHPINDEX: + case DISP_IOCTL_SET_PQ_CAM_PARAM: + case DISP_IOCTL_GET_PQ_CAM_PARAM: + case DISP_IOCTL_SET_PQ_GAL_PARAM: + case DISP_IOCTL_GET_PQ_GAL_PARAM: + case DISP_IOCTL_PQ_SET_BYPASS_COLOR: + case DISP_IOCTL_PQ_SET_WINDOW: + case DISP_IOCTL_WRITE_REG: + case DISP_IOCTL_READ_REG: + case DISP_IOCTL_MUTEX_CONTROL: + case DISP_IOCTL_PQ_GET_TDSHP_FLAG: + case DISP_IOCTL_PQ_SET_TDSHP_FLAG: + case DISP_IOCTL_PQ_GET_DC_PARAM: + case DISP_IOCTL_PQ_SET_DC_PARAM: + case DISP_IOCTL_PQ_GET_DS_PARAM: + case DISP_IOCTL_PQ_GET_MDP_COLOR_CAP: + case DISP_IOCTL_PQ_GET_MDP_TDSHP_REG: + case DISP_IOCTL_WRITE_SW_REG: + case DISP_IOCTL_READ_SW_REG: + if (is_module_in_path(DISP_MODULE_COLOR0, handle)) + dst = DISP_MODULE_COLOR0; + else if (is_module_in_path(DISP_MODULE_COLOR1, handle)) + dst = DISP_MODULE_COLOR1; + else + DISPDBG("dpmgr_path_user_cmd color is not on this path\n"); + + if (dst != DISP_MODULE_UNKNOWN) { + + if (ddp_modules_driver[dst]->cmd != NULL) + ret = ddp_modules_driver[dst]->cmd(dst, msg, arg, cmdqhandle); + + } + break; + default: + DISPDBG("dpmgr_path_user_cmd io not supported\n"); + break; + } + return ret; +} + +int dpmgr_path_set_parameter(disp_path_handle dp_handle, int io_evnet, void *data) +{ + return 0; +} + +int dpmgr_path_get_parameter(disp_path_handle dp_handle, int io_evnet, void *data) +{ + return 0; +} + +int dpmgr_path_is_idle(disp_path_handle dp_handle) +{ + ASSERT(dp_handle != NULL); + return !dpmgr_path_is_busy(dp_handle); +} + +int dpmgr_path_is_busy(disp_path_handle dp_handle) +{ + int i = 0; + int module_name; + ddp_path_handle handle; + int *modules; + int module_num; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPDBG("path check busy on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + for (i = module_num - 1; i >= 0; i--) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->is_busy != 0) { + if (ddp_modules_driver[module_name]->is_busy(module_name)) { + DISPDBG("%s is busy\n", + ddp_get_module_name(module_name)); + return 1; + } + } + } + } + return 0; +} + +int dpmgr_set_lcm_utils(disp_path_handle dp_handle, void *lcm_drv) +{ + int i = 0; + int module_name; + int *modules; + int module_num; + ddp_path_handle handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPDBG("path set lcm drv handle %p\n", handle); + for (i = 0; i < module_num; i++) { + module_name = modules[i]; + if (ddp_modules_driver[module_name] != 0) { + if ((ddp_modules_driver[module_name]->set_lcm_utils != 0) && lcm_drv) { + DISPDBG("%s set lcm utils\n", ddp_get_module_name(module_name)); + ddp_modules_driver[module_name]->set_lcm_utils(module_name, + lcm_drv); + } + } + } + return 0; +} + +int dpmgr_enable_event(disp_path_handle dp_handle, DISP_PATH_EVENT event) +{ + ddp_path_handle handle; + DPMGR_WQ_HANDLE *wq_handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + wq_handle = &handle->wq_list[event]; + + DISPDBG("enable event %s on scenario %s, irtbit 0x%x\n", + path_event_name(event), + ddp_get_scenario_name(handle->scenario), handle->irq_event_map[event].irq_bit); + if (!wq_handle->init) { + init_waitqueue_head(&(wq_handle->wq)); + wq_handle->init = 1; + wq_handle->data = 0; + wq_handle->event = event; + } + return 0; +} + +int dpmgr_map_event_to_irq(disp_path_handle dp_handle, DISP_PATH_EVENT event, DDP_IRQ_BIT irq_bit) +{ + ddp_path_handle handle; + DDP_IRQ_EVENT_MAPPING *irq_table; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + irq_table = handle->irq_event_map; + + if (event < DISP_PATH_EVENT_NUM) { + DISPDBG("map event %s to irq 0x%x on scenario %s\n", path_event_name(event), + irq_bit, ddp_get_scenario_name(handle->scenario)); + irq_table[event].irq_bit = irq_bit; + return 0; + } + DISPERR("fail to map event %s to irq 0x%x on scenario %s\n", path_event_name(event), + irq_bit, ddp_get_scenario_name(handle->scenario)); + return -1; +} + +int dpmgr_disable_event(disp_path_handle dp_handle, DISP_PATH_EVENT event) +{ + ddp_path_handle handle; + DPMGR_WQ_HANDLE *wq_handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + + DISPDBG("disable event %s on scenario %s\n", path_event_name(event), + ddp_get_scenario_name(handle->scenario)); + wq_handle = &handle->wq_list[event]; + + wq_handle->init = 0; + wq_handle->data = 0; + return 0; +} + +int dpmgr_check_status(disp_path_handle dp_handle) +{ + int i = 0; + int *modules; + int module_num; + ddp_path_handle handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + modules = ddp_get_scenario_list(handle->scenario); + module_num = ddp_get_module_num(handle->scenario); + + DISPDMP("check status on scenario %s\n", ddp_get_scenario_name(handle->scenario)); + ddp_dump_analysis(DISP_MODULE_CONFIG); + ddp_check_path(handle->scenario); + ddp_check_mutex(handle->hwmutexid, handle->scenario, handle->mode); + + /* dump path */ + { + DISPDMP("path:"); + for (i = 0; i < module_num; i++) + DISPDMP("%s-", ddp_get_module_name(modules[i])); + + DISPDMP("\n"); + } + ddp_dump_analysis(DISP_MODULE_MUTEX); + + for (i = 0; i < module_num; i++) + ddp_dump_analysis(modules[i]); + + for (i = 0; i < module_num; i++) + ddp_dump_reg(modules[i]); + + + ddp_dump_reg(DISP_MODULE_CONFIG); + ddp_dump_reg(DISP_MODULE_MUTEX); + + return 0; +} + +void dpmgr_debug_path_status(int mutex_id) +{ + int i = 0; + DDP_MANAGER_CONTEXT *content = _get_context(); + disp_path_handle handle = NULL; + + if (mutex_id >= DISP_MUTEX_DDP_FIRST + && mutex_id < (DISP_MUTEX_DDP_FIRST + DISP_MUTEX_DDP_COUNT)) { + handle = (disp_path_handle) content->handle_pool[mutex_id]; + if (handle) + dpmgr_check_status(handle); + + } else { + for (i = DISP_MUTEX_DDP_FIRST; i < (DISP_MUTEX_DDP_FIRST + DISP_MUTEX_DDP_COUNT); + i++) { + handle = (disp_path_handle) content->handle_pool[i]; + if (handle) + dpmgr_check_status(handle); + + } + } +} + + +int dpmgr_wait_event_timeout(disp_path_handle dp_handle, DISP_PATH_EVENT event, int timeout) +{ + int ret = -1; + ddp_path_handle handle; + DPMGR_WQ_HANDLE *wq_handle; + unsigned long long cur_time; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + wq_handle = &handle->wq_list[event]; + + if (wq_handle->init) { + DISPDBG("wait event %s on scenario %s\n", path_event_name(event), + ddp_get_scenario_name(handle->scenario)); + cur_time = ktime_to_ns(ktime_get());/*sched_clock();*/ + + ret = + wait_event_interruptible_timeout(wq_handle->wq, cur_time < wq_handle->data, + timeout); + if (ret == 0) { + DISPERR("wait %s timeout on scenario %s\n", path_event_name(event), + ddp_get_scenario_name(handle->scenario)); + /* dpmgr_check_status(dp_handle); */ + } else if (ret < 0) { + DISPERR("wait %s interrupt by other timeleft %d on scenario %s\n", + path_event_name(event), ret, + ddp_get_scenario_name(handle->scenario)); + } else { + DISPDBG("received event %s timeleft %d on scenario %s\n", + path_event_name(event), ret, + ddp_get_scenario_name(handle->scenario)); + } + return ret; + } + DISPERR("wait event %s not initialized on scenario %s\n", path_event_name(event), + ddp_get_scenario_name(handle->scenario)); + return ret; +} + +int _dpmgr_wait_event(disp_path_handle dp_handle, DISP_PATH_EVENT event, unsigned long long *event_ts) +{ + int ret = -1; + ddp_path_handle handle; + DPMGR_WQ_HANDLE *wq_handle; + unsigned long long cur_time; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + wq_handle = &handle->wq_list[event]; + + if (!wq_handle->init) { + DISPERR("wait event %s not initialized on scenario %s\n", path_event_name(event), + ddp_get_scenario_name(handle->scenario)); + return -2; + } + + DISPDBG("wait event %s on scenario %s\n", path_event_name(event), + ddp_get_scenario_name(handle->scenario)); + + cur_time = ktime_to_ns(ktime_get());/*sched_clock();*/ + ret = wait_event_interruptible(wq_handle->wq, cur_time < wq_handle->data); + if (ret < 0) { + DISPERR("wait %s interrupt by other ret %d on scenario %s\n", + path_event_name(event), ret, + ddp_get_scenario_name(handle->scenario)); + } else { + DISPDBG("received event %s ret %d on scenario %s\n", + path_event_name(event), ret, + ddp_get_scenario_name(handle->scenario)); + } + if (event_ts) + *event_ts = wq_handle->data; + + return ret; +} + +int dpmgr_wait_event(disp_path_handle dp_handle, DISP_PATH_EVENT event) +{ + return _dpmgr_wait_event(dp_handle, event, NULL); +} + +int dpmgr_wait_event_ts(disp_path_handle dp_handle, DISP_PATH_EVENT event, unsigned long long *event_ts) +{ + return _dpmgr_wait_event(dp_handle, event, event_ts); +} + +int dpmgr_signal_event(disp_path_handle dp_handle, DISP_PATH_EVENT event) +{ + ddp_path_handle handle; + DPMGR_WQ_HANDLE *wq_handle; + + ASSERT(dp_handle != NULL); + handle = (ddp_path_handle) dp_handle; + wq_handle = &handle->wq_list[event]; + + if (handle->wq_list[event].init) { + wq_handle->data = ktime_to_ns(ktime_get());/*sched_clock();*/ + DISPDBG("wake up evnet %s on scenario %s\n", path_event_name(event), + ddp_get_scenario_name(handle->scenario)); + wake_up_interruptible(&(handle->wq_list[event].wq)); + } + return 0; +} + +static void dpmgr_irq_handler(DISP_MODULE_ENUM module, unsigned int regvalue) +{ + int i = 0; + int j = 0; + int irq_bits_num = 0; + int irq_bit = 0; + ddp_path_handle handle = NULL; + + handle = find_handle_by_module(module); + if (handle == NULL) + return; + + irq_bits_num = ddp_get_module_max_irq_bit(module); + for (i = 0; i <= irq_bits_num; i++) { + if (regvalue & (0x1 << i)) { + irq_bit = MAKE_DDP_IRQ_BIT(module, i); + dprec_stub_irq(irq_bit); + for (j = 0; j < DISP_PATH_EVENT_NUM; j++) { + if (handle->wq_list[j].init + && irq_bit == handle->irq_event_map[j].irq_bit) { + dprec_stub_event(j); + handle->wq_list[j].data = ktime_to_ns(ktime_get());/*sched_clock();*/ + DISPIRQ("irq signal event %s on cycle %llu on scenario %s\n", + path_event_name(j), handle->wq_list[j].data, + ddp_get_scenario_name(handle->scenario)); + wake_up_interruptible(&(handle->wq_list[j].wq)); + } + } + } + } +} + +int dpmgr_init(void) +{ + DISPMSG("ddp manager init\n"); + if (ddp_manager_init) + return 0; + ddp_manager_init = 1; + /* ddp_debug_init(); */ + disp_init_irq(); + disp_register_irq_callback(dpmgr_irq_handler); + return 0; +} + +int dpmgr_factory_mode_test(int module_name, void *cmdqhandle, void *config) +{ + if (ddp_modules_driver[module_name] != 0) { + if (ddp_modules_driver[module_name]->ioctl != 0) { + DISPMSG(" %s factory_mode_test\n", ddp_get_module_name(DISP_MODULE_DPI)); + ddp_modules_driver[DISP_MODULE_DPI]->ioctl(module_name, cmdqhandle, + DDP_DPI_FACTORY_TEST, config); + } + } + + return 0; +} + +int dpmgr_wait_ovl_available(int ovl_num) +{ + int ret = 1; + + return ret; +} diff --git a/drivers/misc/mediatek/video/mt6755/ddp_manager.h b/drivers/misc/mediatek/video/mt6755/ddp_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..1f88f10ac66f4298c02425e1eead54d4919ecadb --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_manager.h @@ -0,0 +1,426 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DDP_PATH_MANAGER_H__ +#define __DDP_PATH_MANAGER_H__ + +#include +#include "ddp_info.h" +#include "disp_event.h" +#include "ddp_path.h" + +#include "cmdq_record.h" + +#define MAKE_DDP_IRQ_BIT(module, shift) ((module<<24)|(0x1<> 24) +#define IRQBIT_BIT(irqbit) (irqbit & 0xffffff) + +/* IRQ and module are combined to consist DDP IRQ */ +typedef enum { + DDP_IRQ_OVL0_FRAME_COMPLETE = MAKE_DDP_IRQ_BIT(DISP_MODULE_OVL0, 1), + DDP_IRQ_AAL_OUT_END_FRAME = MAKE_DDP_IRQ_BIT(DISP_MODULE_AAL, 1), + + DDP_IRQ_RDMA0_REG_UPDATE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA0, 0), + DDP_IRQ_RDMA0_START = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA0, 1), + DDP_IRQ_RDMA0_DONE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA0, 2), + DDP_IRQ_RDMA0_UNDERFLOW = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA0, 3), + DDP_IRQ_RDMA0_TARGET_LINE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA0, 4), + + DDP_IRQ_RDMA1_REG_UPDATE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA1, 0), + DDP_IRQ_RDMA1_START = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA1, 1), + DDP_IRQ_RDMA1_DONE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA1, 2), + DDP_IRQ_RDMA1_UNDERFLOW = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA1, 3), + DDP_IRQ_RDMA1_TARGET_LINE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA1, 4), + + DDP_IRQ_RDMA2_REG_UPDATE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA2, 0), + DDP_IRQ_RDMA2_START = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA2, 1), + DDP_IRQ_RDMA2_DONE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA2, 2), + DDP_IRQ_RDMA2_UNDERFLOW = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA2, 3), + DDP_IRQ_RDMA2_TARGET_LINE = MAKE_DDP_IRQ_BIT(DISP_MODULE_RDMA2, 4), + + DDP_IRQ_WDMA0_FRAME_COMPLETE = MAKE_DDP_IRQ_BIT(DISP_MODULE_WDMA0, 0), + + DDP_IRQ_WDMA1_FRAME_COMPLETE = MAKE_DDP_IRQ_BIT(DISP_MODULE_WDMA1, 0), + + DDP_IRQ_DSI0_EXT_TE = MAKE_DDP_IRQ_BIT(DISP_MODULE_DSI0, 2), + DDP_IRQ_DSI0_CMD_DONE = MAKE_DDP_IRQ_BIT(DISP_MODULE_DSI0, 1), + DDP_IRQ_DSI0_FRAME_DONE = MAKE_DDP_IRQ_BIT(DISP_MODULE_DSI0, 4), + + DDP_IRQ_MUTEX0_SOF = MAKE_DDP_IRQ_BIT(DISP_MODULE_MUTEX, 0), + DDP_IRQ_MUTEX1_SOF = MAKE_DDP_IRQ_BIT(DISP_MODULE_MUTEX, 1), + + DDP_IRQ_DPI_VSYNC = MAKE_DDP_IRQ_BIT(DISP_MODULE_DPI, 0), + DDP_IRQ_DPI_VDE = MAKE_DDP_IRQ_BIT(DISP_MODULE_DPI, 1), + + DDP_IRQ_UNKNOWN = MAKE_DDP_IRQ_BIT(DISP_MODULE_UNKNOWN, 0), + +} DDP_IRQ_BIT; + +/* path handle */ +typedef void *disp_path_handle; + +/* Init ddp manager, now only register irq handler to ddp_irq.c + * return 0 if ok or -1 if fail. +*/ +int dpmgr_init(void); + +/* create disp path handle , it will assign mutex to this handle, and cache this handle + * to modules in scenario, and will assign default irq event to this handle. + * return NULL if fail to create handle. + * scenario: used to demininate path, and ddp manager will do operations + * according to current scenario. + * cmdq_handle : will save current config cmdqhandle, and if cmdq is enable , will + use cmdq to write regitsers. +*/ +disp_path_handle dpmgr_create_path(DDP_SCENARIO_ENUM scenario, cmdqRecHandle cmdq_handle); + + +int dpmgr_get_scenario(disp_path_handle dp_handle); + +/* NOTES: modify path should call API like this : + old_scenario = dpmgr_get_scenario(handle); + dpmgr_modify_path_power_on_new_modules(); + dpmgr_modify_path(); + after cmdq handle exec done: + dpmgr_modify_path_power_off_old_modules(); +*/ +int dpmgr_modify_path_power_on_new_modules(disp_path_handle dp_handle, + DDP_SCENARIO_ENUM new_scenario, int sw_only); +int dpmgr_modify_path(disp_path_handle dp_handle, DDP_SCENARIO_ENUM new_scenario, + cmdqRecHandle cmdq_handle, DDP_MODE isvdomode, int sw_only); +int dpmgr_modify_path_power_off_old_modules(DDP_SCENARIO_ENUM old_scenario, + DDP_SCENARIO_ENUM new_scenario, int sw_only); + +/* destroy path, it will release mutex to pool, and disconnect path, + * clear mapping between handle and modules. + * return 0; +*/ +int dpmgr_destroy_path(disp_path_handle dp_handle, cmdqRecHandle cmdq_handle); + +/* only destroy handle, don't disconnect path */ +int dpmgr_destroy_path_handle(disp_path_handle dp_handle); + + +/* add dump to path, for primary path , support OVL0, UFOE and OD. + * for sub path ,support OVL1. + * return 0 if success or -1 if fail. + * dp_handle: disp path handle. +*/ + +int dpmgr_path_memout_clock(disp_path_handle dp_handle, int clock_switch); + +int dpmgr_path_add_memout(disp_path_handle dp_handle, DISP_MODULE_ENUM engine, void *cmdq_handle); + +/* remove dump to path. should match between add dump and remove dump. + * return 0 if success or -1 if fail. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_remove_memout(disp_path_handle dp_handle, void *cmdq_handle); + + +/* query current path mutex. + * return mutex. + * dp_handle: disp path handle. +*/ +int dpmgr_path_get_mutex(disp_path_handle dp_handle); + + +/* query current dst module. + * return module enum. + * dp_handle: disp path handle. +*/ +DISP_MODULE_ENUM dpmgr_path_get_dst_module(disp_path_handle dp_handle); +enum dst_module_type dpmgr_path_get_dst_module_type(disp_path_handle dp_handle); + + +/* set dst module, the default dst module maybe not right, so set real dst module on this path. + * return 0. + * dp_handle: disp path handle. + * dst_module(one of bellow): + * DISP_MODULE_DSI0 + * DISP_MODULE_DSI1 + * DISP_MODULE_DSIDUAL(DISP_MODULE_DSI0+DISP_MODULE_DSI1) +* DISP_MODULE_DPI +*/ +int dpmgr_path_set_dst_module(disp_path_handle dp_handle, DISP_MODULE_ENUM dst_module); + +/* set mode type(sof source): cmd or video mode. + * return 0. + * dp_handle: disp path handle. + * is_vdo_mode: 0 is cmd mode, 1 is video mode. +*/ +int dpmgr_path_set_video_mode(disp_path_handle dp_handle, int is_vdo_mode); + +/* init path , it will set mutex according to modules on this path and sof sorce. + * and it will connect path , then initialize modules on this path. + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_init(disp_path_handle dp_handle, int encmdq); + + +/*connect path , it will set mutex according to modules on this path and sof sorce. + * and it will connect path , then initialize modules on this path. + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_connect(disp_path_handle dp_handle, int encmdq); + +/*connect path , it will set mutex according to modules on this path and sof sorce. + * and it will connect path , then initialize modules on this path. + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_disconnect(disp_path_handle dp_handle, int encmdq); + + +/* deinit path , it will clear mutex and dissconnect path. + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_deinit(disp_path_handle dp_handle, int encmdq); + + +/* start path , it will start this path by calling each drviers start function. + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_start(disp_path_handle dp_handle, int encmdq); + + +/* start path , it will stop this path by calling each drviers stop function. + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_stop(disp_path_handle dp_handle, int encmdq); + + +/* reset path , it will reset this path by calling each drviers reset function. + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_reset(disp_path_handle dp_handle, int encmdq); + + +/* config data , it will config input or output data of this path. + * now config contains three parts: + * 1. dst dirty .it means dst with & dst hight need be updated. + * 2. ovl dirty. it means ovl config need be updated. + * 3. rdma dirty. it means rdma need be updated. + * 4. wdma dirty. it means wdam need be updated. + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_config(disp_path_handle dp_handle, disp_ddp_path_config *config, void *cmdq_handle); + + +/* path flush, this will enable mutex + * return 0. + * dp_handle: disp path handle. + * encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_flush(disp_path_handle dp_handle, int encmdq); + + +/* this will dump modules info on this path. + * return 0. + * dp_handle: disp path handle. +*/ +int dpmgr_check_status(disp_path_handle dp_handle); + + +/* this will dump modules info on mutex path. + * return 0. + * mutex_id: mutex idex[0-4], if not in this range, will dump all. +*/ +void dpmgr_debug_path_status(int mutex_id); + +void dpmgr_get_input_address(disp_path_handle dp_handle, unsigned long *addr); + + +/* this will deal with cmdq message: + * return 0. + * dp_handle: disp path handle. + * trigger_loop_handle: triger thread. + * state : + CMDQ_BEFORE_STREAM_SOF // before sof. + CMDQ_WAIT_STREAM_EOF_EVENT // wait sof + CMDQ_CHECK_IDLE_AFTER_STREAM_EOF // check sof + CMDQ_AFTER_STREAM_EOF // after sof +*/ +int dpmgr_path_build_cmdq(disp_path_handle dp_handle, void *trigger_loop_handle, CMDQ_STATE state, + int reverse); + + +/* this will trigger this path. it will trigger each module and enable mutex. + * return 0. + * dp_handle: disp path handle. + * trigger_loop_handle : trigger thread. +*/ +int dpmgr_path_trigger(disp_path_handle dp_handle, void *trigger_loop_handle, int encmdq); + + +/* set signal to event. this if not irq signal, but user send event + * return 0. + * dp_handle: disp path handle. + * event: path event. +*/ +int dpmgr_signal_event(disp_path_handle dp_handle, DISP_PATH_EVENT event); + + +/* enable init will initialize wakequeue. + * return 0. + * dp_handle: disp path handle. + * event: path event. +*/ +int dpmgr_enable_event(disp_path_handle dp_handle, DISP_PATH_EVENT event); + + +/* disable event, related irq will not be received. + * return 0. + * dp_handle: disp path handle. + * event: path event. +*/ +int dpmgr_disable_event(disp_path_handle dp_handle, DISP_PATH_EVENT event); + +/* map event to irq can change mappling between path event and irq . + * return 0. + * dp_handle: disp path handle. + * event: path event. + * irq_bit +*/ +int dpmgr_map_event_to_irq(disp_path_handle dp_handle, DISP_PATH_EVENT event, DDP_IRQ_BIT irq_bit); + + +/* wait event, timeout (ms). + * return + * < 0, error. + * 0 timeout + * > 0 no timeout + * event : disp event. + * timeout :(ms). +*/ +int dpmgr_wait_event_timeout(disp_path_handle dp_handle, DISP_PATH_EVENT event, int timeout); + + +/* wait event + * return : + * 0 , wait succesfull. + * <0, wait error. + * event : disp event. + * timeout :(ms). +*/ +int dpmgr_wait_event(disp_path_handle dp_handle, DISP_PATH_EVENT event); +int dpmgr_wait_event_ts(disp_path_handle dp_handle, DISP_PATH_EVENT event, unsigned long long *event_ts); + + +/* power on, turn on each modules clk. + * return 0. +* dp_handle: disp path handle. +* encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_power_on(disp_path_handle dp_handle, CMDQ_SWITCH encmdq); +int dpmgr_path_power_on_bypass_pwm(disp_path_handle dp_handle, CMDQ_SWITCH encmdq); + +/* power 0ff, turn off each modules clk, if all hande are closed. top clock will be off. + * return 0. +* dp_handle: disp path handle. +* encmdq: 1 use command queue, 0 not. +*/ +int dpmgr_path_power_off(disp_path_handle dp_handle, CMDQ_SWITCH encmdq); +int dpmgr_path_power_off_bypass_pwm(disp_path_handle dp_handle, CMDQ_SWITCH encmdq); + +/* set lcm utils. now only dis/dpi used. + * return 0. +* dp_handle: disp path handle. +* lcm_drv: lcm driver +*/ +int dpmgr_set_lcm_utils(disp_path_handle dp_handle, void *lcm_drv); + + +/* check if this path is busy. it wil check each module on this path. + * return 0. +* dp_handle: disp path handle. +*/ +int dpmgr_path_is_busy(disp_path_handle dp_handle); + + +/* check if this path is idle. it wil check each module on this path. + * return 0 if idle. +* dp_handle: disp path handle. +*/ +int dpmgr_path_is_idle(disp_path_handle dp_handle); + +/* add parameter to this path. + * return 0. + * dp_handle: disp path handle. + * io_evnet: not defined. + * data : data. +*/ +int dpmgr_path_user_cmd(disp_path_handle dp_handle, int msg, unsigned long arg, void *cmdqhandle); + + +int dpmgr_path_set_parameter(disp_path_handle dp_handle, int io_evnet, void *data); + + +/* get parameter of this path. + * return 0. + * dp_handle: disp path handle. + * io_evnet: not defined. + * data : data. +*/ +int dpmgr_path_get_parameter(disp_path_handle dp_handle, int io_evnet, void *data); + +/* dpmgr_ioctl , it will call ioctl of ddp modules ioctl() to do some special config or setting. + * return 0. + * dp_handle: disp path handle. + * cmdq_handle: cmdq handle + * ioctl_cmd: ioctl cmd + * params: ioctl parameters +*/ +int dpmgr_path_ioctl(disp_path_handle dp_handle, void *cmdq_handle, DDP_IOCTL_NAME ioctl_cmd, + void *params); + +int dpmgr_path_enable_irq(disp_path_handle dp_handle, void *cmdq_handle, DDP_IRQ_LEVEL irq_level); +/* get last config parameter of path + * return pointer to last config + * dp_handle: disp path handle. +*/ +disp_ddp_path_config *dpmgr_path_get_last_config(disp_path_handle dp_handle); +disp_ddp_path_config *dpmgr_path_get_last_config_notclear(disp_path_handle dp_handle); + +void dpmgr_get_input_buffer(disp_path_handle dp_handle, unsigned long *addr); +int dpmgr_module_notify(DISP_MODULE_ENUM module, DISP_PATH_EVENT event); + +int dpmgr_insert_ovl1_sub(disp_path_handle dp_handle, void *cmdq_handle); +int dpmgr_remove_ovl1_sub(disp_path_handle dp_handle, void *cmdq_handle); + +/* factory mode test + * return 0 + * module_name: module name. + * encmdq: 1 use command queue, 0 not. + * config: +*/ +int dpmgr_factory_mode_test(int module_name, void *cmdqhandle, void *config); + +int dpmgr_wait_ovl_available(int ovl_num); +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_matrix_para.h b/drivers/misc/mediatek/video/mt6755/ddp_matrix_para.h new file mode 100644 index 0000000000000000000000000000000000000000..b00c1567d92348dd6b6d492d95fe8b63b557e094 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_matrix_para.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _DDP_MATRIX_PARA_H_ +#define _DDP_MATRIX_PARA_H_ + + +#define TABLE_NO 10 + +#define YUV2RGB_601_16_16 0 +#define YUV2RGB_601_16_0 1 +#define YUV2RGB_601_0_0 2 +#define YUV2RGB_709_16_16 3 +#define YUV2RGB_709_16_0 4 +#define YUV2RGB_709_0_0 5 +#define RGB2YUV_601 6 +#define RGB2YUV_601_XVYCC 7 +#define RGB2YUV_709 8 +#define RGB2YUV_709_XVYCC 9 + +static const short int coef_rdma_601_r2y[5][3] = { + {263, 516, 100}, + {-152, -298, 450}, + {450, -377, -73}, + {0, 0, 0}, + {0, 128, 128} +}; + +static const short int coef_rdma_709_r2y[5][3] = { + {187, 629, 63}, + {-103, -347, 450}, + {450, -409, -41}, + {0, 0, 0}, + {16, 128, 128} +}; + +static const short int coef_rdma_601_y2r[5][3] = { + {1193, 0, 1633}, + {1193, -400, -832}, + {1193, 2065, 0}, + {-16, -128, -128}, + {0, 0, 0} +}; + +static const short int coef_rdma_709_y2r[5][3] = { + {1193, 0, 1934}, + {1193, -217, -545}, + {1193, 2163, -1}, + {-16, -128, -128}, + {0, 0, 0} +}; + + +static const short int coef[10][5][3] = { + /* ----------------------------------------- */ + /* YUV to RGB SD */ + /* ----------------------------------------- */ + /* yuv2rgb_601_16_16, y=16~235, uv=16~240, rgb=16~235 */ + {{0x0400, 0x0000, 0x057c}, /* 1, 0 , 1.371 13bit: sign+2.10 */ + {0x0400, 0x1ea8, 0x1d35}, /* 1, -0.336, -0.698 13bit: sign+2.10 */ + {0x0400, 0x06ee, 0x0000}, /* 1, 1.732, 0 13bit: sign+2.10 */ + {0, 0x180, 0x180}, /* 0, -128 , -128 9bit: sign+8.0 */ + {0, 0, 0} }, + /* yuv2rgb_601_16_0, y=16~235, uv=16~240, rgb=0~255 */ + {{0x04a7, 0x0000, 0x0662}, /* 1.164, 0 , 1.596 13bit: sign+2.10 */ + {0x04a7, 0x1e70, 0x1cc0}, /* 1.164, -0.391 , -0.813 13bit: sign+2.10 */ + {0x04a7, 0x0812, 0x0000}, /* 1.164, 2.018 , 0 13bit: sign+2.10 */ + {0x1f0, 0x180, 0x180}, /* -16, -128 , -128 9bit: sign+8.0 */ + {0, 0, 0} }, + /* yuv2rgb_601_0_0, yuv=0~255, rgb=0~255 */ + {{0x0400, 0x0000, 0x059b}, /* 1, 0 , 1.402 13bit: sign+2.10 */ + {0x0400, 0x1ea0, 0x1d25}, /* 1, -0.3341, -0.7141 13bit: sign+2.10 */ + {0x0400, 0x0716, 0x0000}, /* 1, 1.772 , 0 13bit: sign+2.10 */ + {0, 0x180, 0x180}, /* 0, -128 , -128 9bit: sign+8.0 */ + {0, 0, 0} }, + /* ----------------------------------------- */ + /* YUV to RGB HD */ + /* ----------------------------------------- */ + /* yuv2rgb_709_16_16, y=16~235, uv=16~240, rgb=16~235 */ + {{0x0400, 0x0000, 0x0628}, /* 1, 0 , 1.54 13bit: sign+2.10 */ + {0x0400, 0x1f45, 0x1e2a}, /* 1, -0.183, -0.459 13bit: sign+2.10 */ + {0x0400, 0x0743, 0x0000}, /* 1, 1.816, 0 13bit: sign+2.10 */ + {0, 0x180, 0x180}, /* 0, -128 , -128 9bit: sign+8.0 */ + {0, 0, 0} }, + /* yuv2rgb_709_16_0, y=16~235, uv=16~240, rgb=0~255 */ + {{0x04a7, 0x0000, 0x072c}, /* 1.164, 0 , 1.793 13bit: sign+2.10 */ + {0x04a7, 0x1f26, 0x1dde}, /* 1.164, -0.213 , -0.534 13bit: sign+2.10 */ + {0x04a7, 0x0875, 0x0000}, /* 1.164, 2.115 , 0 13bit: sign+2.10 */ + {0x1f0, 0x180, 0x180}, /* -16, -128 , -128 9bit: sign+8.0 */ + {0, 0, 0} }, + /* yuv2rgb_709_0_0, yuv=0~255, rgb=0~255 */ + {{0x0400, 0x0000, 0x064d}, /* 1, 0 , 1.5748 13bit: sign+2.10 */ + {0x0400, 0x1f40, 0x1e21}, /* 1, -0.1873, -0.4681 13bit: sign+2.10 */ + {0x0400, 0x076c, 0x0000}, /* 1, 1.8556, 0 13bit: sign+2.10 */ + {0, 0x180, 0x180}, /* 0, -128 , -128 9bit: sign+8.0 */ + {0, 0, 0} }, + /* ----------------------------------------- */ + /* RGB to YUV SD */ + /* ----------------------------------------- */ + /* rgb2yuv_601, rgb=0~255, y=16~235, uv=16~240 */ + {{0x0107, 0x0204, 0x0064}, /* 0.257 , 0.504 , 0.098 13bit: sign+2.10 */ + {0x1f68, 0x1ed6, 0x01c2}, /* -0.148 , -0.291 , 0.439 13bit: sign+2.10 */ + {0x01c2, 0x1e87, 0x1fb7}, /* 0.439 , -0.368 , -0.071 13bit: sign+2.10 */ + {0, 0, 0}, + {0x010, 0x080, 0x080} }, /* 16 , 128 , 128 9bit: sign+8.0 */ + /* rgb2yuv_601_xvycc, rgb=0~255, yuv=0~255 */ + {{0x0132, 0x0259, 0x0075}, /* 0.299 , 0.587 , 0.114 13bit: sign+2.10 */ + {0x1f53, 0x1ead, 0x0200}, /* -0.1687, -0.3313, 0.5 13bit: sign+2.10 */ + {0x0200, 0x1e53, 0x1fad}, /* 0.5 , -0.4187, -0.0813 13bit: sign+2.10 */ + {0, 0, 0}, + {0x010, 0x080, 0x080} }, /* 16 , 128 , 128 9bit: sign+8.0 */ + /* ----------------------------------------- */ + /* RGB to YUV SD */ + /* ----------------------------------------- */ + /* rgb2yuv_709, rgb=0~255, y=16~235, uv=16~240 */ + {{0x00bb, 0x0275, 0x003f}, /* 0.183 , 0.614 , 0.062 13bit: sign+2.10 */ + {0x1f98, 0x1ea6, 0x01c2}, /* -0.101 , -0.338 , 0.439 13bit: sign+2.10 */ + {0x01c2, 0x1e67, 0x1fd7}, /* 0.439 , -0.399 , -0.04 13bit: sign+2.10 */ + {0, 0, 0}, + {0x010, 0x080, 0x080} }, /* 16 , 128 , 128 9bit: sign+8.0 */ + /* rgb2yuv_709_xvycc, rgb=0~255, yuv=0~255 */ + {{0x00da, 0x02dc, 0x004a}, /* 0.2126, 0.7152, 0.0722 13bit: sign+2.10 */ + {0x1f8b, 0x1e75, 0x0200}, /* -0.1146, -0.3854, 0.5 13bit: sign+2.10 */ + {0x0200, 0x1e2f, 0x1fd1}, /* 0.5 , -0.4542, -0.0458 13bit: sign+2.10 */ + {0, 0, 0}, + {0x010, 0x080, 0x080} } /* 16 , 128 , 128 9bit: sign+8.0 */ +}; + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_met.c b/drivers/misc/mediatek/video/mt6755/ddp_met.c new file mode 100644 index 0000000000000000000000000000000000000000..660584aa103ee7c96b3e0c66725ec9cf86fd1a6b --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_met.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "MET" + +#include "disp_log.h" + +#include +#include "ddp_irq.h" +#include "ddp_reg.h" +#include "ddp_met.h" +#include "ddp_path.h" +#include "ddp_ovl.h" +#include "ddp_rdma.h" +#include "DpDataType.h" + +#define DDP_IRQ_EER_ID (0xFFFF0000) +#define DDP_IRQ_FPS_ID (DDP_IRQ_EER_ID + 1) +#define DDP_IRQ_LAYER_FPS_ID (DDP_IRQ_EER_ID + 2) +#define DDP_IRQ_LAYER_SIZE_ID (DDP_IRQ_EER_ID + 3) +#define DDP_IRQ_LAYER_FORMAT_ID (DDP_IRQ_EER_ID + 4) + +#define MAX_PATH_NUM (3) +#define RDMA_NUM (2) +#define MAX_OVL_LAYERS (4) +#define OVL_LAYER_NUM_PER_OVL (4) + + +unsigned int met_tag_on = 0; +#if 0 +static const char *const parse_color_format(DpColorFormat fmt) +{ + switch (fmt) { + case eBGR565: + return "eBGR565"; + case eRGB565: + return "eRGB565"; + case eRGB888: + return "eRGB888"; + case eBGR888: + return "eBGR888"; + case eRGBA8888: + return "eRGBA8888"; + case eBGRA8888: + return "eBGRA8888"; + case eARGB8888: + return "eARGB8888"; + case eABGR8888: + return "eABGR8888"; + case eVYUY: + return "eVYUY"; + case eUYVY: + return "eUYVY"; + case eYVYU: + return "eYVYU"; + case eYUY2: + return "eYUY2"; + default: + return "DEFAULT"; + } +} +#endif + +/** + * check if it's decouple mode + * + * mutex_id | decouple | direct-link + * ------------------------------------- + * OVL_Path | 1 | 0 + * RDMA_Path | 0 | X + * + */ +int dpp_disp_is_decouple(void) +{ + if (ddp_is_moudule_in_mutex(0, DISP_MODULE_OVL0) || + ddp_is_moudule_in_mutex(0, DISP_MODULE_OVL0_2L)) + return 0; + else + return 1; +} + +/** + * Represent to LCM display refresh rate + * Primary Display: map to RDMA0 sof/eof ISR, for all display mode + * External Display: map to RDMA1 sof/eof ISR, for all display mode + * NOTICE: + * for WFD, nothing we can do here + */ +static void ddp_disp_refresh_tag_start(unsigned int index) +{ + static unsigned long sBufAddr[RDMA_NUM]; + + static RDMA_BASIC_STRUCT rdmaInfo; + + char tag_name[30] = { '\0' }; + + if (dpp_disp_is_decouple() == 1) { + + rdma_get_info(index, &rdmaInfo); + if (rdmaInfo.addr == 0 || (rdmaInfo.addr != 0 && sBufAddr[index] != rdmaInfo.addr)) { + sBufAddr[index] = rdmaInfo.addr; + sprintf(tag_name, index ? "ExtDispRefresh" : "PrimDispRefresh"); + met_tag_oneshot(DDP_IRQ_FPS_ID, tag_name, 1); + } + + } else { + static OVL_BASIC_STRUCT old_ovlInfo[OVL_NUM*OVL_LAYER_NUM_PER_OVL]; + static OVL_BASIC_STRUCT ovlInfo[OVL_NUM*OVL_LAYER_NUM_PER_OVL]; + int ovl_index; + int b_layer_changed; + int i, j; + + b_layer_changed = 0; + + /*Traversal layers and get layer info*/ + memset(ovlInfo, 0, sizeof(ovlInfo));/*essential for structure comparision*/ + + for (i = 0; i < OVL_NUM; i++) { + + ovl_get_info(i, &(ovlInfo[i*OVL_LAYER_NUM_PER_OVL])); + + for (j = 0; j < OVL_LAYER_NUM_PER_OVL; j++) { + ovl_index = (i * OVL_LAYER_NUM_PER_OVL) + j; + + if (memcmp(&(ovlInfo[ovl_index]), &(old_ovlInfo[ovl_index]), + sizeof(OVL_BASIC_STRUCT)) == 0) + continue; + + if (ovlInfo[ovl_index].layer_en) + b_layer_changed = 1; + } + + /*store old value*/ + memcpy(&(old_ovlInfo[i*OVL_LAYER_NUM_PER_OVL]), + &(ovlInfo[i*OVL_LAYER_NUM_PER_OVL]), + OVL_LAYER_NUM_PER_OVL*sizeof(OVL_BASIC_STRUCT)); + + } + + if (b_layer_changed) { + sprintf(tag_name, index ? "ExtDispRefresh" : "PrimDispRefresh"); + met_tag_oneshot(DDP_IRQ_FPS_ID, tag_name, 1); + } + + } +} + +static void ddp_disp_refresh_tag_end(unsigned int index) +{ + char tag_name[30] = { '\0' }; + + sprintf(tag_name, index ? "ExtDispRefresh" : "PrimDispRefresh"); + met_tag_oneshot(DDP_IRQ_FPS_ID, tag_name, 0); +} + +/** + * Represent to OVL0/0VL1 each layer's refresh rate + */ +static void ddp_inout_info_tag(unsigned int index) +{ +#if 0 + static unsigned long sLayerBufAddr[OVL_NUM][OVL_LAYER_NUM_PER_OVL]; + static unsigned int sLayerBufFmt[OVL_NUM][OVL_LAYER_NUM_PER_OVL]; + static unsigned int sLayerBufWidth[OVL_NUM][OVL_LAYER_NUM_PER_OVL]; + static unsigned int sLayerBufHeight[OVL_NUM][OVL_LAYER_NUM_PER_OVL]; + + OVL_BASIC_STRUCT ovlInfo[OVL_NUM*OVL_LAYER_NUM_PER_OVL]; + unsigned int flag, i, idx, enLayerCnt, layerCnt; + unsigned int width, height, bpp, fmt; + char *fmtStr; + char tag_name[30] = { '\0' }; + uint32_t layer_change_bits = 0; + uint32_t layer_enable_bits = 0; + + memset((void *)ovlInfo, 0, sizeof(ovlInfo)); + ovl_get_info(index, ovlInfo); + + /* Any layer enable bit changes , new frame refreshes */ + enLayerCnt = 0; + if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) + layerCnt = OVL_LAYER_NUM; + else + layerCnt = OVL_LAYER_NUM_PER_OVL; + + for (i = 0; i < layerCnt; i++) { + if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) + index = 1 - i / OVL_LAYER_NUM_PER_OVL; + + idx = i % OVL_LAYER_NUM_PER_OVL; + + fmtStr = parse_color_format(ovlInfo[i].fmt); + + if (ovlInfo[i].layer_en) { + enLayerCnt++; + layer_enable_bits |= (1 << i); + if (sLayerBufAddr[index][idx] != ovlInfo[i].addr) { + sLayerBufAddr[index][idx] = ovlInfo[i].addr; + sprintf(tag_name, "OVL%dL%d_InFps", index, idx); + met_tag_oneshot(DDP_IRQ_LAYER_FPS_ID, tag_name, i+1); + layer_change_bits |= 1 << i; + } +#if 0 + if (sLayerBufFmt[index][idx] != ovlInfo[i].fmt) { + sLayerBufFmt[index][idx] = ovlInfo[i].fmt; + sprintf(tag_name, "OVL%dL%d_Fmt_%s", index, idx, fmtStr); + met_tag_oneshot(DDP_IRQ_LAYER_FORMAT_ID, tag_name, i+1); + layer_change_bits |= 1 << i; + } + if (sLayerBufWidth[index][idx] != ovlInfo[i].src_w) { + sLayerBufWidth[index][idx] = ovlInfo[i].src_w; + sprintf(tag_name, "OVL%dL%d_Width", index, idx); + met_tag_oneshot(DDP_IRQ_LAYER_SIZE_ID, tag_name, ovlInfo[i].src_w); + layer_change_bits |= 1 << i; + } + if (sLayerBufHeight[index][idx] != ovlInfo[i].src_h) { + sLayerBufHeight[index][idx] = ovlInfo[i].src_h; + sprintf(tag_name, "OVL%dL%d_Height", index, idx); + met_tag_oneshot(DDP_IRQ_LAYER_SIZE_ID, tag_name, ovlInfo[i].src_h); + layer_change_bits |= 1 << i; + } +#endif + } else { + sLayerBufAddr[index][idx] = 0; + sLayerBufFmt[index][idx] = 0; + sLayerBufWidth[index][idx] = 0; + sLayerBufHeight[index][idx] = 0; + } + + if ((i == (OVL_LAYER_NUM_PER_OVL - 1)) || (i == (OVL_LAYER_NUM - 1))) { + if (enLayerCnt) { + enLayerCnt = 0; + sprintf(tag_name, "OVL%d_OutFps", index); + met_tag_oneshot(DDP_IRQ_LAYER_FPS_ID, tag_name, index); + } + } + } + + + /*CLS:met mmsys profile*/ + { + int i; + + for (i = 0; i < OVL_LAYER_NUM; i++) { + if (layer_change_bits & (1 << i)) { + MET_UDTL_GET_PROP(OVL_LAYER_Props).layer = i; + MET_UDTL_GET_PROP(OVL_LAYER_Props).layer_en = layer_enable_bits; + MET_UDTL_GET_PROP(OVL_LAYER_Props).fmt = ovlInfo[i].fmt; + MET_UDTL_GET_PROP(OVL_LAYER_Props).addr = ovlInfo[i].addr; + MET_UDTL_GET_PROP(OVL_LAYER_Props).src_w = ovlInfo[i].src_w; + MET_UDTL_GET_PROP(OVL_LAYER_Props).src_h = ovlInfo[i].src_h; + MET_UDTL_GET_PROP(OVL_LAYER_Props).src_pitch = ovlInfo[i].src_pitch; + MET_UDTL_GET_PROP(OVL_LAYER_Props).bpp = ovlInfo[i].bpp; + + MET_UDTL_TRACELINE_PROP(MMSYS, OVL_LAYERS__LAYER, OVL_LAYER_Props); + } + } + } + + +#endif + +} + +static void ddp_err_irq_met_tag(const char *name) +{ + met_tag_oneshot(DDP_IRQ_EER_ID, name, 0); +} + +static void met_irq_handler(DISP_MODULE_ENUM module, unsigned int reg_val) +{ + int index = 0; + char tag_name[30] = { '\0' }; + int mutexID; + /* DISPERR("met_irq_handler() module=%d, val=0x%x\n", module, reg_val); */ + switch (module) { + case DISP_MODULE_RDMA0: + case DISP_MODULE_RDMA1: + index = module - DISP_MODULE_RDMA0; + if (reg_val & (1 << 2)) + ddp_disp_refresh_tag_end(index);/*Always process eof prior to sof*/ + + if (reg_val & (1 << 1)) + ddp_disp_refresh_tag_start(index); + + if (reg_val & (1 << 4)) { + sprintf(tag_name, "rdma%d_underflow", index); + ddp_err_irq_met_tag(tag_name); + } + if (reg_val & (1 << 3)) { + sprintf(tag_name, "rdma%d_abnormal", index); + ddp_err_irq_met_tag(tag_name); + } + break; + + case DISP_MODULE_OVL0: + case DISP_MODULE_OVL1: + index = module - DISP_MODULE_OVL0; + if (reg_val & (1 << 1)) {/*EOF*/ + ddp_inout_info_tag(index); + if (met_mmsys_event_disp_ovl_eof) + met_mmsys_event_disp_ovl_eof(index); + } + + break; + + case DISP_MODULE_MUTEX: + /*reg_val is DISP_REG_GET(DISP_REG_CONFIG_MUTEX_INTSTA) & 0x7C1F; */ + for (mutexID = DISP_MUTEX_DDP_FIRST; mutexID <= DISP_MUTEX_DDP_LAST; mutexID++) { + if (reg_val & (0x1<layer, + pLayer->layer_en); + else if (session == 2) + MMProfileLogEx(DDP_MMP_Events.Extd_layer_dump_parent, MMProfileFlagStart, + pLayer->layer, pLayer->layer_en); + + if (pLayer->layer_en) { + Bitmap.data1 = pLayer->vaddr; + Bitmap.width = pLayer->dst_w; + Bitmap.height = pLayer->dst_h; + switch (pLayer->fmt) { + case UFMT_RGB565: + case UFMT_BGR565: + Bitmap.format = MMProfileBitmapRGB565; + Bitmap.bpp = 16; + break; + case UFMT_RGB888: + Bitmap.format = MMProfileBitmapRGB888; + Bitmap.bpp = 24; + break; + case UFMT_BGRA8888: + Bitmap.format = MMProfileBitmapBGRA8888; + Bitmap.bpp = 32; + break; + case UFMT_BGR888: + Bitmap.format = MMProfileBitmapBGR888; + Bitmap.bpp = 24; + break; + case UFMT_RGBA8888: + Bitmap.format = MMProfileBitmapRGBA8888; + Bitmap.bpp = 32; + break; + case UFMT_ABGR8888: + case UFMT_ARGB8888: + Bitmap.format = MMProfileBitmapRGBA8888; + Bitmap.bpp = 32; + break; + case UFMT_PARGB8888: + case UFMT_PABGR8888: + Bitmap.format = MMProfileBitmapRGBA8888; + Bitmap.bpp = 32; + break; + case UFMT_PRGBA8888: + case UFMT_PBGRA8888: + Bitmap.format = MMProfileBitmapBGRA8888; + Bitmap.bpp = 32; + break; + default: + DISPERR("ddp_mmp_ovl_layer(), unknown fmt=0x%x,dump raw\n", pLayer->fmt); + raw = 1; + } + if (!raw) { + Bitmap.start_pos = 0; + Bitmap.pitch = pLayer->src_pitch; + Bitmap.data_size = Bitmap.pitch * Bitmap.height; + Bitmap.down_sample_x = down_sample_x; + Bitmap.down_sample_y = down_sample_y; + if (m4u_mva_map_kernel + (pLayer->addr, Bitmap.data_size, (unsigned long *)&Bitmap.pData, + &Bitmap.data_size) == 0) { + if (session == 1) + MMProfileLogMetaBitmap(DDP_MMP_Events. + layer_dump[pLayer->layer], + MMProfileFlagPulse, &Bitmap); + else if (session == 2) + MMProfileLogMetaBitmap(DDP_MMP_Events. + ovl1layer_dump[pLayer->layer], + MMProfileFlagPulse, &Bitmap); + m4u_mva_unmap_kernel(pLayer->addr, Bitmap.data_size, + (unsigned long)Bitmap.pData); + } else { + DISPERR("ddp_mmp_ovl_layer(),fail to dump rgb(0x%x)\n", pLayer->fmt); + } + } else { + meta.data_type = MMProfileMetaRaw; + meta.size = pLayer->src_pitch * pLayer->src_h; + if (m4u_mva_map_kernel + (pLayer->addr, meta.size, (unsigned long *)&meta.pData, + &meta.size) == 0) { + if (session == 1) + MMProfileLogMeta(DDP_MMP_Events.layer_dump[pLayer->layer], + MMProfileFlagPulse, &meta); + else if (session == 2) + MMProfileLogMeta(DDP_MMP_Events. + ovl1layer_dump[pLayer->layer], + MMProfileFlagPulse, &meta); + m4u_mva_unmap_kernel(pLayer->addr, meta.size, + (unsigned long)meta.pData); + } else { + DISPERR("ddp_mmp_ovl_layer(),fail to dump raw(0x%x)\n", pLayer->fmt); + } + } + } + + if (session == 1) + MMProfileLogEx(DDP_MMP_Events.layer_dump_parent, MMProfileFlagEnd, pLayer->fmt, + pLayer->addr); + else if (session == 2) + MMProfileLogEx(DDP_MMP_Events.Extd_layer_dump_parent, MMProfileFlagEnd, pLayer->fmt, + pLayer->addr); + +} + +void ddp_mmp_wdma_layer(WDMA_CONFIG_STRUCT *wdma_layer, unsigned int wdma_num, + unsigned int down_sample_x, unsigned int down_sample_y) +{ + MMP_MetaDataBitmap_t Bitmap; + MMP_MetaData_t meta; + int raw = 0; + + if (wdma_num > 1) { + DISPERR("dprec_mmp_dump_wdma_layer is error %d\n", wdma_num); + return; + } + + Bitmap.data1 = wdma_layer->dstAddress; + Bitmap.width = wdma_layer->srcWidth; + Bitmap.height = wdma_layer->srcHeight; + switch (wdma_layer->outputFormat) { + case UFMT_RGB565: + case UFMT_BGR565: + Bitmap.format = MMProfileBitmapRGB565; + Bitmap.bpp = 16; + break; + case UFMT_RGB888: + Bitmap.format = MMProfileBitmapRGB888; + Bitmap.bpp = 24; + break; + case UFMT_BGRA8888: + Bitmap.format = MMProfileBitmapBGRA8888; + Bitmap.bpp = 32; + break; + case UFMT_BGR888: + Bitmap.format = MMProfileBitmapBGR888; + Bitmap.bpp = 24; + break; + case UFMT_RGBA8888: + Bitmap.format = MMProfileBitmapRGBA8888; + Bitmap.bpp = 32; + break; + case UFMT_ABGR8888: + case UFMT_ARGB8888: + Bitmap.format = MMProfileBitmapRGBA8888; + Bitmap.bpp = 32; + break; + case UFMT_YUYV: + case UFMT_YVYU: + /* use rgb888 to cheet MMP, haha! */ + Bitmap.format = MMProfileBitmapRGB888; + Bitmap.bpp = 16; + Bitmap.data2 = wdma_layer->outputFormat; + break; + default: + DISPERR("dprec_mmp_dump_wdma_layer(), unknown fmt=%d, dump raw\n", + wdma_layer->outputFormat); + raw = 1; + } + if (!raw) { + Bitmap.start_pos = 0; + Bitmap.pitch = wdma_layer->dstPitch; + Bitmap.data_size = Bitmap.pitch * Bitmap.height; + Bitmap.down_sample_x = down_sample_x; + Bitmap.down_sample_y = down_sample_y; + if (m4u_mva_map_kernel + (wdma_layer->dstAddress, Bitmap.data_size, (unsigned long *)&Bitmap.pData, + &Bitmap.data_size) == 0) { + MMProfileLogMetaBitmap(DDP_MMP_Events.wdma_dump[wdma_num], + MMProfileFlagPulse, &Bitmap); + m4u_mva_unmap_kernel(wdma_layer->dstAddress, Bitmap.data_size, + (unsigned long)Bitmap.pData); + } else { + DISPERR("dprec_mmp_dump_wdma_layer(),fail to dump rgb(0x%x)\n", + wdma_layer->outputFormat); + } + } else { + meta.data_type = MMProfileMetaRaw; + meta.size = wdma_layer->dstPitch * wdma_layer->srcHeight; + if (m4u_mva_map_kernel + (wdma_layer->dstAddress, meta.size, (unsigned long *)&meta.pData, + &meta.size) == 0) { + MMProfileLogMeta(DDP_MMP_Events.wdma_dump[wdma_num], MMProfileFlagPulse, + &meta); + } else { + DISPERR("dprec_mmp_dump_wdma_layer(),fail to dump raw(0x%x)\n", + wdma_layer->outputFormat); + } + } + + +} + +void ddp_mmp_rdma_layer(RDMA_CONFIG_STRUCT *rdma_layer, unsigned int rdma_num, + unsigned int down_sample_x, unsigned int down_sample_y) +{ + MMP_MetaDataBitmap_t Bitmap; + MMP_MetaData_t meta; + int raw = 0; + + if (rdma_num > 1) { + DISPERR("dump_rdma_layer is error %d\n", rdma_num); + return; + } + + Bitmap.data1 = rdma_layer->address; + Bitmap.width = rdma_layer->width; + Bitmap.height = rdma_layer->height; + switch (rdma_layer->inputFormat) { + case UFMT_RGB565: + case UFMT_BGR565: + Bitmap.format = MMProfileBitmapRGB565; + Bitmap.bpp = 16; + break; + case UFMT_RGB888: + Bitmap.format = MMProfileBitmapRGB888; + Bitmap.bpp = 24; + break; + case UFMT_BGRA8888: + Bitmap.format = MMProfileBitmapBGRA8888; + Bitmap.bpp = 32; + break; + case UFMT_BGR888: + Bitmap.format = MMProfileBitmapBGR888; + Bitmap.bpp = 24; + break; + case UFMT_RGBA8888: + Bitmap.format = MMProfileBitmapRGBA8888; + Bitmap.bpp = 32; + break; + case UFMT_ABGR8888: + case UFMT_ARGB8888: + Bitmap.format = MMProfileBitmapRGBA8888; + Bitmap.bpp = 32; + break; + case UFMT_YUYV: + case UFMT_YVYU: + /* use rgb888 to cheet MMP, haha! */ + Bitmap.format = MMProfileBitmapRGB888; + Bitmap.bpp = 16; + Bitmap.data2 = rdma_layer->inputFormat; + break; + default: + DISPERR("dump_rdma_layer(), unknown fmt=%d, dump raw\n", rdma_layer->inputFormat); + raw = 1; + } + if (!raw) { + Bitmap.start_pos = 0; + Bitmap.pitch = rdma_layer->pitch; + Bitmap.data_size = Bitmap.pitch * Bitmap.height; + Bitmap.down_sample_x = down_sample_x; + Bitmap.down_sample_y = down_sample_y; + if (m4u_mva_map_kernel + (rdma_layer->address, Bitmap.data_size, (unsigned long int *)&Bitmap.pData, + &Bitmap.data_size) == 0) { + MMProfileLogMetaBitmap(DDP_MMP_Events.rdma_dump[rdma_num], + MMProfileFlagPulse, &Bitmap); + m4u_mva_unmap_kernel(rdma_layer->address, Bitmap.data_size, + (unsigned long)Bitmap.pData); + } else { + DISPERR("dump_rdma_layer(),fail to dump rgb(0x%x)\n", + rdma_layer->inputFormat); + } + } else { + meta.data_type = MMProfileMetaRaw; + meta.size = rdma_layer->pitch * rdma_layer->height; + if (m4u_mva_map_kernel + (rdma_layer->address, meta.size, (unsigned long int *)&meta.pData, + &meta.size) == 0) { + MMProfileLogMeta(DDP_MMP_Events.rdma_dump[rdma_num], MMProfileFlagPulse, + &meta); + m4u_mva_unmap_kernel(rdma_layer->address, meta.size, + (unsigned long)meta.pData); + } else { + DISPERR("dprec_mmp_dump_rdma_layer(),fail to dump raw(0x%x)\n", + rdma_layer->inputFormat); + } + } + +} + + +DDP_MMP_Events_t *ddp_mmp_get_events(void) +{ + return &DDP_MMP_Events; +} + +void ddp_mmp_init(void) +{ +#ifdef DEFAULT_MMP_ENABLE + DISPMSG("ddp_mmp_init\n"); + MMProfileEnable(1); + init_ddp_mmp_events(); + MMProfileStart(1); +#endif +} diff --git a/drivers/misc/mediatek/video/mt6755/ddp_mmp.h b/drivers/misc/mediatek/video/mt6755/ddp_mmp.h new file mode 100644 index 0000000000000000000000000000000000000000..7e47ffddac8e1c3bbaeab3e62ee1d244d3c8a880 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_mmp.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __H_DDP_MMP__ +#define __H_DDP_MMP__ + +#include "mmprofile.h" +#include "ddp_info.h" +#include "disp_session.h" +typedef struct { + MMP_Event DDP; + MMP_Event layerParent; + MMP_Event layer[4]; + MMP_Event ovl1_layer[4]; + MMP_Event layer_dump_parent; + MMP_Event layer_dump[4]; + MMP_Event ovl1layer_dump[4]; + MMP_Event wdma_dump[2]; + MMP_Event rdma_dump[2]; + MMP_Event DDP_IRQ; + MMP_Event OVL_IRQ_Parent; + MMP_Event OVL_IRQ[OVL_NUM]; + MMP_Event WDMA_IRQ_Parent; + MMP_Event WDMA_IRQ[2]; + MMP_Event RDMA_IRQ_Parent; + MMP_Event RDMA_IRQ[3]; + MMP_Event SCREEN_UPDATE[3]; + MMP_Event DSI_IRQ_Parent; + MMP_Event DSI_IRQ[2]; + MMP_Event MutexParent; + MMP_Event MUTEX_IRQ[5]; + MMP_Event primary_Parent; + MMP_Event primary_trigger; + MMP_Event primary_suspend; + MMP_Event primary_resume; + MMP_Event primary_config; + MMP_Event primary_rdma_config; + MMP_Event primary_wdma_config; + MMP_Event primary_set_dirty; + MMP_Event primary_cmdq_flush; + MMP_Event primary_cmdq_done; + MMP_Event primary_display_cmd; + MMP_Event primary_cache_sync; + MMP_Event primary_display_aalod_trigger; + MMP_Event primary_wakeup; + MMP_Event primary_switch_mode; + MMP_Event primary_mode[DISP_SESSION_MODE_NUM]; + MMP_Event primary_seq_info; + MMP_Event primary_seq_insert; + MMP_Event primary_seq_config; + MMP_Event primary_seq_trigger; + MMP_Event primary_seq_rdma_irq; + MMP_Event primary_seq_release; + MMP_Event primary_ovl_fence_release; + MMP_Event primary_wdma_fence_release; + MMP_Event present_fence_release; + MMP_Event present_fence_get; + MMP_Event present_fence_set; + MMP_Event idlemgr; + MMP_Event sec; + MMP_Event tui; + MMP_Event fps_set; + MMP_Event fps_get; + MMP_Event primary_error; + MMP_Event ovl_trigger; + MMP_Event interface_trigger; + MMP_Event Extd_Parent; + MMP_Event Extd_layerParent; + MMP_Event Extd_layer[4]; + MMP_Event Extd_layer_dump_parent; + MMP_Event Extd_State; + MMP_Event Extd_DevInfo; + MMP_Event Extd_ErrorInfo; + MMP_Event Extd_Mutex; + MMP_Event Extd_ImgDump; + MMP_Event Extd_IrqStatus; + MMP_Event Extd_UsedBuff; + MMP_Event Extd_trigger; + MMP_Event Extd_config; + MMP_Event Extd_set_dirty; + MMP_Event Extd_cmdq_flush; + MMP_Event Extd_cmdq_done; + MMP_Event dprec_cpu_write_reg; + MMP_Event primary_sw_mutex; + MMP_Event primary_set_bl; + MMP_Event ESD_Parent; + MMP_Event esd_check_t; + MMP_Event esd_recovery_t; + MMP_Event esd_extte; + MMP_Event esd_rdlcm; + MMP_Event esd_vdo_eint; + MMP_Event session_Parent; + MMP_Event session_prepare; + MMP_Event session_set_input; + MMP_Event session_trigger; + MMP_Event session_find_idx; + MMP_Event session_release; + MMP_Event session_wait_vsync; + MMP_Event MonitorParent; + MMP_Event rdma_underflow; + MMP_Event trigger_delay; + MMP_Event release_delay; + MMP_Event vsync_count; + MMP_Event dal_printf; + MMP_Event dal_clean; + MMP_Event tmp_debug; + MMP_Event cg_mode; + MMP_Event power_down_mode; + MMP_Event sodi_disable; + MMP_Event sodi_enable; + MMP_Event ovl_enable; + MMP_Event ovl_disable; + MMP_Event cascade_enable; + MMP_Event cascade_disable; + MMP_Event ddp_abnormal_irq; + MMP_Event ovl1_status; + MMP_Event dpmgr_wait_event_timeout; + MMP_Event cmdq_rebuild; + MMP_Event LFR_NUM; + MMP_Event dsi_te; + MMP_Event dsi_frame_done; + MMP_Event dsi_lfr_switch; + MMP_Event Dsi_Update; + MMP_Event primary_set_cmd; +} DDP_MMP_Events_t; + +DDP_MMP_Events_t *ddp_mmp_get_events(void); +void init_ddp_mmp_events(void); +void ddp_mmp_init(void); +void ddp_mmp_ovl_layer(OVL_CONFIG_STRUCT *pLayer, unsigned int down_sample_x, + unsigned int down_sample_y, + unsigned int session /*1:primary, 2:external, 3:memory */); +void ddp_mmp_wdma_layer(WDMA_CONFIG_STRUCT *wdma_layer, unsigned int wdma_num, + unsigned int down_sample_x, unsigned int down_sample_y); +void ddp_mmp_rdma_layer(RDMA_CONFIG_STRUCT *rdma_layer, unsigned int rdma_num, + unsigned int down_sample_x, unsigned int down_sample_y); + +/*defined in mmp driver, should remove it */ +extern void MMProfileEnable(int enable); +void MMProfileStart(int start); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_ovl.c b/drivers/misc/mediatek/video/mt6755/ddp_ovl.c new file mode 100644 index 0000000000000000000000000000000000000000..e4e5cd2e2f692ecf9af410eea2013f8466de353a --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_ovl.c @@ -0,0 +1,1254 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "OVL" +#include "disp_log.h" +#include "disp_debug.h" +#include "mtkfb_debug.h" +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include "ddp_clkmgr.h" +#endif +#include "m4u.h" +#include +#include "ddp_info.h" +#include "ddp_hal.h" +#include "ddp_reg.h" +#include "ddp_ovl.h" +#include "primary_display.h" + +#define OVL_REG_BACK_MAX (40) +#define OVL_LAYER_OFFSET (0x20) +#define OVL_RDMA_DEBUG_OFFSET (0x4) + +enum OVL_COLOR_SPACE { + OVL_COLOR_SPACE_RGB = 0, + OVL_COLOR_SPACE_YUV, +}; + +struct OVL_REG { + unsigned long address; + unsigned int value; +}; + +static DISP_MODULE_ENUM ovl_index_module[OVL_NUM] = { + DISP_MODULE_OVL0, DISP_MODULE_OVL1, DISP_MODULE_OVL0_2L, DISP_MODULE_OVL1_2L +}; + +static unsigned int reg_back_cnt[OVL_NUM]; +static struct OVL_REG reg_back[OVL_NUM][OVL_REG_BACK_MAX]; +static unsigned int gOVLBackground = 0xFF000000; + +static inline int is_module_ovl(DISP_MODULE_ENUM module) +{ + if (module == DISP_MODULE_OVL0 || + module == DISP_MODULE_OVL1 || + module == DISP_MODULE_OVL0_2L || module == DISP_MODULE_OVL1_2L) + return 1; + else + return 0; +} + +unsigned long ovl_base_addr(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_OVL0: + return DDP_REG_BASE_DISP_OVL0; + case DISP_MODULE_OVL1: + return DDP_REG_BASE_DISP_OVL1; + case DISP_MODULE_OVL0_2L: + return DDP_REG_BASE_DISP_OVL0_2L; + case DISP_MODULE_OVL1_2L: + return DDP_REG_BASE_DISP_OVL1_2L; + default: + DISPERR("invalid ovl module=%d\n", module); + BUG(); + } + return 0; +} + +static inline unsigned long ovl_layer_num(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_OVL0: + return 4; + case DISP_MODULE_OVL1: + return 4; + case DISP_MODULE_OVL0_2L: + return 2; + case DISP_MODULE_OVL1_2L: + return 2; + default: + DISPERR("invalid ovl module=%d\n", module); + BUG(); + } + return 0; +} + +static inline unsigned long ovl_to_m4u_port(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_OVL0: + return M4U_PORT_DISP_OVL0; + case DISP_MODULE_OVL1: + return M4U_PORT_DISP_OVL1; + case DISP_MODULE_OVL0_2L: + return M4U_PORT_DISP_2L_OVL0; + case DISP_MODULE_OVL1_2L: + return M4U_PORT_DISP_2L_OVL1; + default: + DISPERR("invalid ovl module=%d\n", module); + BUG(); + } + return 0; +} + +CMDQ_EVENT_ENUM ovl_to_cmdq_event_nonsec_end(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_OVL0: + return CMDQ_SYNC_DISP_OVL0_2NONSEC_END; + case DISP_MODULE_OVL1: + return CMDQ_SYNC_DISP_OVL1_2NONSEC_END; + case DISP_MODULE_OVL0_2L: + return CMDQ_SYNC_DISP_2LOVL0_2NONSEC_END; + case DISP_MODULE_OVL1_2L: + return CMDQ_SYNC_DISP_2LOVL1_2NONSEC_END; + default: + DISPERR("invalid ovl module=%d\n", module); + BUG(); + } + return 0; + +} + +static inline unsigned long ovl_to_cmdq_engine(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_OVL0: + return CMDQ_ENG_DISP_OVL0; + case DISP_MODULE_OVL1: + return CMDQ_ENG_DISP_OVL1; + case DISP_MODULE_OVL0_2L: + return CMDQ_ENG_DISP_2L_OVL0; + case DISP_MODULE_OVL1_2L: + return CMDQ_ENG_DISP_2L_OVL1; + default: + DISPERR("invalid ovl module=%d\n", module); + BUG(); + } + return 0; +} + +unsigned long ovl_to_index(DISP_MODULE_ENUM module) +{ + int i; + + for (i = 0; i < OVL_NUM; i++) { + if (ovl_index_module[i] == module) + return i; + } + DISPERR("invalid ovl module=%d\n", module); + BUG(); + return 0; +} + +static inline DISP_MODULE_ENUM ovl_index_to_module(int index) +{ + if (index >= OVL_NUM) { + DISPERR("invalid ovl index=%d\n", index); + BUG(); + } + return ovl_index_module[index]; +} + +int ovl_start(DISP_MODULE_ENUM module, void *handle) +{ + unsigned long ovl_base = ovl_base_addr(module); + + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_EN, 0x01); + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_INTEN, + 0x1E | REG_FLD_VAL(INTEN_FLD_ABNORMAL_SOF, 1)); + DISP_REG_SET_FIELD(handle, DATAPATH_CON_FLD_LAYER_SMI_ID_EN, + ovl_base + DISP_REG_OVL_DATAPATH_CON, 0x1); + return 0; +} + +int ovl_stop(DISP_MODULE_ENUM module, void *handle) +{ + unsigned long ovl_base = ovl_base_addr(module); + + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_INTEN, 0x00); + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_EN, 0x00); + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_INTSTA, 0x00); + + return 0; +} + +int ovl_is_idle(DISP_MODULE_ENUM module) +{ + unsigned long ovl_base = ovl_base_addr(module); + + if (((DISP_REG_GET(ovl_base + DISP_REG_OVL_FLOW_CTRL_DBG) & 0x3ff) != 0x1) && + ((DISP_REG_GET(ovl_base + DISP_REG_OVL_FLOW_CTRL_DBG) & 0x3ff) != 0x2)) + return 0; + else + return 1; + +} + +int ovl_reset(DISP_MODULE_ENUM module, void *handle) +{ +#define OVL_IDLE (0x3) + int ret = 0; + unsigned int delay_cnt = 0; + unsigned long ovl_base = ovl_base_addr(module); + + DISP_CPU_REG_SET(ovl_base + DISP_REG_OVL_RST, 0x1); + DISP_CPU_REG_SET(ovl_base + DISP_REG_OVL_RST, 0x0); + /*only wait if not cmdq */ + if (handle == NULL) { + while (!(DISP_REG_GET(ovl_base + DISP_REG_OVL_FLOW_CTRL_DBG) & OVL_IDLE)) { + delay_cnt++; + udelay(10); + if (delay_cnt > 2000) { + DISPERR("%s reset timeout!\n", ddp_get_module_name(module)); + ret = -1; + break; + } + } + } + return ret; +} + +int ovl_roi(DISP_MODULE_ENUM module, + unsigned int bg_w, unsigned int bg_h, unsigned int bg_color, void *handle) +{ + unsigned long ovl_base = ovl_base_addr(module); + + if ((bg_w > OVL_MAX_WIDTH) || (bg_h > OVL_MAX_HEIGHT)) { + DISPERR("ovl_roi,exceed OVL max size, w=%d, h=%d\n", bg_w, bg_h); + ASSERT(0); + } + + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_ROI_SIZE, bg_h << 16 | bg_w); + + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_ROI_BGCLR, bg_color); + + return 0; +} + +int ovl_layer_switch(DISP_MODULE_ENUM module, unsigned layer, unsigned int en, void *handle) +{ + unsigned long ovl_base = ovl_base_addr(module); + + ASSERT(layer <= 3); + switch (layer) { + case 0: + DISP_REG_SET_FIELD(handle, SRC_CON_FLD_L0_EN, ovl_base + DISP_REG_OVL_SRC_CON, en); + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_RDMA0_CTRL, en); + break; + case 1: + DISP_REG_SET_FIELD(handle, SRC_CON_FLD_L1_EN, ovl_base + DISP_REG_OVL_SRC_CON, en); + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_RDMA1_CTRL, en); + break; + case 2: + DISP_REG_SET_FIELD(handle, SRC_CON_FLD_L2_EN, ovl_base + DISP_REG_OVL_SRC_CON, en); + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_RDMA2_CTRL, en); + break; + case 3: + DISP_REG_SET_FIELD(handle, SRC_CON_FLD_L3_EN, ovl_base + DISP_REG_OVL_SRC_CON, en); + DISP_REG_SET(handle, ovl_base + DISP_REG_OVL_RDMA3_CTRL, en); + break; + default: + DISPERR("invalid layer=%d\n", layer); + ASSERT(0); + } + + return 0; +} + +static int ovl_layer_config(DISP_MODULE_ENUM module, + unsigned int layer, + unsigned int is_engine_sec, + const OVL_CONFIG_STRUCT * const cfg, + void *handle) +{ + unsigned int value = 0; + unsigned int Bpp, input_swap, input_fmt; + unsigned int rgb_swap = 0; + int is_rgb; + int color_matrix = 0x4; + int rotate = 0; + unsigned long ovl_base = ovl_base_addr(module); + unsigned long layer_offset = ovl_base + layer * OVL_LAYER_OFFSET; + unsigned int offset = 0; + enum UNIFIED_COLOR_FMT format = cfg->fmt; + unsigned int src_x = cfg->src_x; + unsigned int dst_w = cfg->dst_w; + + if (cfg->dst_w > OVL_MAX_WIDTH) + BUG(); + if (cfg->dst_h > OVL_MAX_HEIGHT) + BUG(); + if (layer > 3) + BUG(); + + if (!cfg->addr && cfg->source == OVL_LAYER_SOURCE_MEM) { + DISPERR("source from memory, but addr is 0!\n"); + BUG(); + } + +#ifdef CONFIG_MTK_LCM_PHYSICAL_ROTATION_HW + if (module != DISP_MODULE_OVL1) + rotate = 1; +#endif + + /* check dim layer fmt */ + if (cfg->source == OVL_LAYER_SOURCE_RESERVED) { + if (cfg->aen == 0) + DISPERR("dim layer%d ahpha enable should be 1!\n", layer); + format = UFMT_RGB888; + } + Bpp = ufmt_get_Bpp(format); + input_swap = ufmt_get_byteswap(format); + input_fmt = ufmt_get_format(format); + is_rgb = ufmt_get_rgb(format); + + if (format == UFMT_UYVY || format == UFMT_VYUY || + format == UFMT_YUYV || format == UFMT_YVYU) { + unsigned int regval = 0; + + if (src_x % 2) { + src_x -= 1; /* make src_x to even */ + dst_w += 1; + regval |= REG_FLD_VAL(OVL_L_CLIP_FLD_LEFT, 1); + } + + if ((src_x + dst_w) % 2) { + dst_w += 1; /* make right boundary even */ + regval |= REG_FLD_VAL(OVL_L_CLIP_FLD_RIGHT, 1); + } + DISP_REG_SET(handle, DISP_REG_OVL_L0_CLIP + layer_offset, regval); + } + + switch (cfg->yuv_range) { + case 0: + color_matrix = 4; + break; /* BT601_full */ + case 1: + color_matrix = 6; + break; /* BT601 */ + case 2: + color_matrix = 7; + break; /* BT709 */ + default: + DISPERR("un-recognized yuv_range=%d!\n", cfg->yuv_range); + color_matrix = 4; + } + + + DISP_REG_SET(handle, DISP_REG_OVL_RDMA0_CTRL + layer_offset, 0x1); + + value = (REG_FLD_VAL((L_CON_FLD_LARC), (cfg->source)) | + REG_FLD_VAL((L_CON_FLD_CFMT), (input_fmt)) | + REG_FLD_VAL((L_CON_FLD_AEN), (cfg->aen)) | + REG_FLD_VAL((L_CON_FLD_APHA), (cfg->alpha)) | + REG_FLD_VAL((L_CON_FLD_SKEN), (cfg->keyEn)) | + REG_FLD_VAL((L_CON_FLD_BTSW), (input_swap))); + if (ufmt_is_old_fmt(format)) { + if (format == UFMT_PARGB8888 || format == UFMT_PABGR8888 || + format == UFMT_PRGBA8888 || format == UFMT_PBGRA8888) { + rgb_swap = ufmt_get_rgbswap(format); + value |= REG_FLD_VAL((L_CON_FLD_RGB_SWAP), (rgb_swap)); + } + value |= REG_FLD_VAL((L_CON_FLD_CLRFMT_MAN), (1)); + } + if (!is_rgb) + value = value | REG_FLD_VAL((L_CON_FLD_MTX), (color_matrix)); + + if (rotate) + value |= REG_FLD_VAL((L_CON_FLD_VIRTICAL_FLIP), (1)) | REG_FLD_VAL((L_CON_FLD_HORI_FLIP), (1)); + + DISP_REG_SET(handle, DISP_REG_OVL_L0_CON + layer_offset, value); + + DISP_REG_SET(handle, DISP_REG_OVL_L0_CLR + ovl_base + layer * 4, 0xff000000); + + DISP_REG_SET(handle, DISP_REG_OVL_L0_SRC_SIZE + layer_offset, cfg->dst_h << 16 | dst_w); + + if (rotate) { + unsigned int bg_h, bg_w; + + bg_h = DISP_REG_GET(ovl_base + DISP_REG_OVL_ROI_SIZE); + bg_w = bg_h & 0xFFFF; + bg_h = bg_h >> 16; + DISP_REG_SET(handle, DISP_REG_OVL_L0_OFFSET + layer_offset, + ((bg_h - cfg->dst_h - cfg->dst_y) << 16) | (bg_w - dst_w - cfg->dst_x)); + DISP_REG_SET(handle, DISP_REG_OVL_L0_ADDR + layer_offset, + cfg->addr + cfg->src_pitch * (cfg->dst_h + cfg->src_y - 1) + (src_x + dst_w) * Bpp - 1); + offset = (src_x + dst_w) * Bpp + (cfg->src_y + cfg->dst_h - 1) * cfg->src_pitch - 1; + } else { + DISP_REG_SET(handle, DISP_REG_OVL_L0_OFFSET + layer_offset, (cfg->dst_y << 16) | cfg->dst_x); + DISP_REG_SET(handle, DISP_REG_OVL_L0_ADDR + layer_offset, + cfg->addr + src_x * Bpp + cfg->src_y * cfg->src_pitch); + offset = src_x * Bpp + cfg->src_y * cfg->src_pitch; + } + + if (!is_engine_sec) { + DISP_REG_SET(handle, DISP_REG_OVL_L0_ADDR + layer_offset, cfg->addr + offset); + } else { + unsigned int size; + int m4u_port; + + size = (cfg->dst_h - 1) * cfg->src_pitch + dst_w * Bpp; + m4u_port = ovl_to_m4u_port(module); + if (cfg->security != DISP_SECURE_BUFFER) { + /* ovl is sec but this layer is non-sec */ + /* we need to tell cmdq to help map non-sec mva to sec mva */ + cmdqRecWriteSecure(handle, + disp_addr_convert(DISP_REG_OVL_L0_ADDR + layer_offset), + CMDQ_SAM_NMVA_2_MVA, cfg->addr + offset, 0, size, m4u_port); + + } else { + /* for sec layer, addr variable stores sec handle */ + /* we need to pass this handle and offset to cmdq driver */ + /* cmdq sec driver will help to convert handle to correct address */ + cmdqRecWriteSecure(handle, + disp_addr_convert(DISP_REG_OVL_L0_ADDR + layer_offset), + CMDQ_SAM_H_2_MVA, cfg->addr, offset, size, m4u_port); + } + } + DISP_REG_SET(handle, DISP_REG_OVL_L0_SRCKEY + layer_offset, cfg->key); + + value = (((cfg->sur_aen & 0x1) << 15) | + ((cfg->dst_alpha & 0x3) << 6) | ((cfg->dst_alpha & 0x3) << 4) | + ((cfg->src_alpha & 0x3) << 2) | (cfg->src_alpha & 0x3)); + + value = (REG_FLD_VAL((L_PITCH_FLD_SUR_ALFA), (value)) | + REG_FLD_VAL((L_PITCH_FLD_LSP), (cfg->src_pitch))); + + if (cfg->const_bld) + value = value | REG_FLD_VAL((L_PITCH_FLD_CONST_BLD), (1)); + DISP_REG_SET(handle, DISP_REG_OVL_L0_PITCH + layer_offset, value); + + return 0; +} + +static void ovl_store_regs(DISP_MODULE_ENUM module) +{ + int i = 0; + unsigned long ovl_base = ovl_base_addr(module); + int idx = ovl_to_index(module); + static unsigned long regs[3]; + + regs[0] = DISP_REG_OVL_ROI_SIZE + ovl_base; + regs[1] = DISP_REG_OVL_ROI_BGCLR + ovl_base; + regs[2] = DISP_REG_OVL_DATAPATH_CON + ovl_base; + + + reg_back_cnt[idx] = sizeof(regs) / sizeof(unsigned long); + ASSERT(reg_back_cnt[idx] <= OVL_REG_BACK_MAX); + + + for (i = 0; i < reg_back_cnt[idx]; i++) { + reg_back[idx][i].address = regs[i]; + reg_back[idx][i].value = DISP_REG_GET(regs[i]); + } + DISPMSG("store %d cnt registers on ovl %d\n", reg_back_cnt[idx], idx); + +} + +static void ovl_restore_regs(DISP_MODULE_ENUM module, void *handle) +{ + int idx = ovl_to_index(module); + int i = reg_back_cnt[idx]; + + while (i > 0) { + i--; + DISP_REG_SET(handle, reg_back[idx][i].address, reg_back[idx][i].value); + } + DISPMSG("restore %d cnt registers on ovl %d\n", reg_back_cnt[idx], idx); + reg_back_cnt[idx] = 0; +} + +int ovl_clock_on(DISP_MODULE_ENUM module, void *handle) +{ + unsigned long ovl_base = ovl_base_addr(module); + + DISPDBG("%s clock_on\n", ddp_get_module_name(module)); + /* do not set CG */ +/* +#ifdef ENABLE_CLK_MGR + + switch (module) { + case DISP_MODULE_OVL0: +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_DISP0_DISP_OVL0, ddp_get_module_name(module)); +#else + ddp_clk_enable(DISP0_DISP_OVL0); +#endif + break; + case DISP_MODULE_OVL1: +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_DISP0_DISP_OVL1, ddp_get_module_name(module)); +#else + ddp_clk_enable(DISP0_DISP_OVL1); +#endif + break; + case DISP_MODULE_OVL0_2L: +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_DISP0_DISP_OVL0_2L, ddp_get_module_name(module)); +#else + ddp_clk_enable(DISP0_DISP_2L_OVL0); +#endif + break; + case DISP_MODULE_OVL1_2L: +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_DISP0_DISP_OVL1_2L, ddp_get_module_name(module)); +#else + ddp_clk_enable(DISP0_DISP_2L_OVL1); +#endif + break; + default: + DISPERR("invalid ovl module=%d\n", module); + BUG(); + } + +#endif +*/ + /* DCM Setting -- Enable DCM */ + /* DISP_REG_SET(NULL, ovl_base + DISP_REG_OVL_FUNC_DCM0, 0x10); */ + DISP_REG_SET(NULL, ovl_base + DISP_REG_OVL_FUNC_DCM1, 0x10); + + return 0; +} + +int ovl_clock_off(DISP_MODULE_ENUM module, void *handle) +{ + DISPDBG("%s clock_off\n", ddp_get_module_name(module)); + /* do not set CG */ +/* +#ifdef ENABLE_CLK_MGR + switch (module) { + case DISP_MODULE_OVL0: +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_DISP0_DISP_OVL0, ddp_get_module_name(module)); +#else + ddp_clk_disable(DISP0_DISP_OVL0); +#endif + break; + case DISP_MODULE_OVL1: +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_DISP0_DISP_OVL1, ddp_get_module_name(module)); +#else + ddp_clk_disable(DISP0_DISP_OVL1); +#endif + break; + case DISP_MODULE_OVL0_2L: +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_DISP0_DISP_OVL0_2L, ddp_get_module_name(module)); +#else + ddp_clk_disable(DISP0_DISP_2L_OVL0); +#endif + break; + case DISP_MODULE_OVL1_2L: +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_DISP0_DISP_OVL1_2L, ddp_get_module_name(module)); +#else + ddp_clk_disable(DISP0_DISP_2L_OVL1); +#endif + break; + default: + DISPERR("invalid ovl module=%d\n", module); + BUG(); + } +#endif +*/ + return 0; +} + +int ovl_resume(DISP_MODULE_ENUM module, void *handle) +{ + ovl_clock_on(module, handle); + ovl_restore_regs(module, handle); + return 0; +} + +int ovl_suspend(DISP_MODULE_ENUM module, void *handle) +{ + DISPMSG("%s suspend\n", ddp_get_module_name(module)); + ovl_store_regs(module); + ovl_clock_off(module, handle); + return 0; +} + +int ovl_init(DISP_MODULE_ENUM module, void *handle) +{ + return ovl_clock_on(module, handle); +} + +int ovl_deinit(DISP_MODULE_ENUM module, void *handle) +{ + return ovl_clock_off(module, handle); +} + +int ovl_connect(DISP_MODULE_ENUM module, DISP_MODULE_ENUM prev, + DISP_MODULE_ENUM next, int connect, void *handle) +{ + unsigned long ovl_base = ovl_base_addr(module); + + if (connect && is_module_ovl(prev)) + DISP_REG_SET_FIELD(handle, DATAPATH_CON_FLD_BGCLR_IN_SEL, + ovl_base + DISP_REG_OVL_DATAPATH_CON, 1); + else + DISP_REG_SET_FIELD(handle, DATAPATH_CON_FLD_BGCLR_IN_SEL, + ovl_base + DISP_REG_OVL_DATAPATH_CON, 0); + return 0; +} + +unsigned int ddp_ovl_get_cur_addr(bool rdma_mode, int layerid) +{ + /*just workaround, should remove this func */ + unsigned long ovl_base = ovl_base_addr(DISP_MODULE_OVL0_2L); + + if (rdma_mode) + return DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR); + if (DISP_REG_GET(DISP_REG_OVL_RDMA0_CTRL + layerid * 0x20 + ovl_base) & 0x1) + return DISP_REG_GET(DISP_REG_OVL_L0_ADDR + layerid * 0x20 + ovl_base); + return 0; +} + +void ovl_get_address(DISP_MODULE_ENUM module, unsigned long *add) +{ + int i = 0; + unsigned long ovl_base = ovl_base_addr(module); + unsigned long layer_off = 0; + unsigned int src_on = DISP_REG_GET(DISP_REG_OVL_SRC_CON + ovl_base); + + for (i = 0; i < 4; i++) { + layer_off = i * OVL_LAYER_OFFSET + ovl_base; + if (src_on & (0x1 << i)) + add[i] = DISP_REG_GET(layer_off + DISP_REG_OVL_L0_ADDR); + else + add[i] = 0; + } +} + +void ovl_get_info(DISP_MODULE_ENUM module, void *data) +{ + int i = 0; + OVL_BASIC_STRUCT *pdata = data; + unsigned long ovl_base = ovl_base_addr(module); + unsigned long layer_off = 0; + unsigned int src_on = DISP_REG_GET(DISP_REG_OVL_SRC_CON + ovl_base); + OVL_BASIC_STRUCT *p = NULL; + + for (i = 0; i < ovl_layer_num(module); i++) { + layer_off = i * OVL_LAYER_OFFSET + ovl_base; + p = &pdata[i]; + p->layer = i; + p->layer_en = src_on & (0x1 << i); + if (p->layer_en) { + p->fmt = display_fmt_reg_to_unified_fmt(DISP_REG_GET_FIELD(L_CON_FLD_CFMT, + layer_off + + DISP_REG_OVL_L0_CON), + DISP_REG_GET_FIELD(L_CON_FLD_BTSW, + layer_off + + DISP_REG_OVL_L0_CON), + DISP_REG_GET_FIELD(L_CON_FLD_RGB_SWAP, + layer_off + + DISP_REG_OVL_L0_CON)); + p->addr = DISP_REG_GET(layer_off + DISP_REG_OVL_L0_ADDR); + p->src_w = DISP_REG_GET(layer_off + DISP_REG_OVL_L0_SRC_SIZE) & 0xfff; + p->src_h = + (DISP_REG_GET(layer_off + DISP_REG_OVL_L0_SRC_SIZE) >> 16) & 0xfff; + p->src_pitch = DISP_REG_GET(layer_off + DISP_REG_OVL_L0_PITCH) & 0xffff; + p->bpp = UFMT_GET_bpp(p->fmt) / 8; + p->gpu_mode = (DISP_REG_GET(layer_off + DISP_REG_OVL_DATAPATH_CON) & (0x1<<(8+i)))?1:0; + p->adobe_mode = (DISP_REG_GET(layer_off + DISP_REG_OVL_DATAPATH_CON) & (0x1<<12))?1:0; + p->ovl_gamma_out = (DISP_REG_GET(layer_off + DISP_REG_OVL_DATAPATH_CON) & (0x1<<15))?1:0; + p->alpha = (DISP_REG_GET(layer_off + DISP_REG_OVL_L0_CON + (i*0x20)) & (0x1<<8))?1:0; + } + DISPDBG("ovl_get_info:layer%d,en %d,w %d,h %d,bpp %d,addr %lu\n", + i, p->layer_en, p->src_w, p->src_h, p->bpp, p->addr); + } +} + +static int ovl_check_input_param(OVL_CONFIG_STRUCT *config) +{ + if ((config->addr == 0 && config->source == 0) || config->dst_w == 0 || config->dst_h == 0) { + DISPERR("ovl parameter invalidate, addr=%lu, w=%d, h=%d\n", + config->addr, config->dst_w, config->dst_h); + ASSERT(0); + return -1; + } + + return 0; +} + +/* use noinline to reduce stack size */ +static noinline void print_layer_config_args(int module, int local_layer, OVL_CONFIG_STRUCT *ovl_cfg) +{ + DISPDBG("%s, layer=%d(%d), source=%s, off(x=%d, y=%d), dst(%d, %d, %d, %d),pitch=%d,", + ddp_get_module_name(module), local_layer, ovl_cfg->layer, + (ovl_cfg->source == 0) ? "memory" : "dim", ovl_cfg->src_x, ovl_cfg->src_y, + ovl_cfg->dst_x, ovl_cfg->dst_y, ovl_cfg->dst_w, ovl_cfg->dst_h, ovl_cfg->src_pitch); + DISPDBG("fmt=%s, addr=%lx, keyEn=%d, key=%d, aen=%d, alpha=%d,", + unified_color_fmt_name(ovl_cfg->fmt), ovl_cfg->addr, + ovl_cfg->keyEn, ovl_cfg->key, ovl_cfg->aen, ovl_cfg->alpha); + DISPDBG("sur_aen=%d,sur_alpha=0x%x,yuv_range=%d,sec=%d,const_bld=%d\n", + ovl_cfg->sur_aen, (ovl_cfg->dst_alpha << 2) | ovl_cfg->src_alpha, + ovl_cfg->yuv_range, ovl_cfg->security, ovl_cfg->const_bld); +} + +static int ovl_is_sec[OVL_NUM]; +static int setup_ovl_sec(DISP_MODULE_ENUM module, void *handle, int is_engine_sec) +{ + int i = 0; + int ovl_idx = ovl_to_index(module); + CMDQ_ENG_ENUM cmdq_engine; + /*CMDQ_EVENT_ENUM cmdq_event_nonsec_end;*/ + cmdq_engine = ovl_to_cmdq_engine(module); + /*cmdq_event_nonsec_end = ovl_to_cmdq_event_nonsec_end(module);*/ + + if (is_engine_sec) { + + cmdqRecSetSecure(handle, 1); + /* set engine as sec */ + cmdqRecSecureEnablePortSecurity(handle, (1LL << cmdq_engine)); + /* cmdqRecSecureEnableDAPC(handle, (1LL << cmdq_engine)); */ + if (ovl_is_sec[ovl_idx] == 0) + DISPMSG("[SVP] switch ovl%d to sec\n", ovl_idx); + ovl_is_sec[ovl_idx] = 1; + } else { + if (ovl_is_sec[ovl_idx] == 1) { + /* ovl is in sec stat, we need to switch it to nonsec */ + cmdqRecHandle nonsec_switch_handle; + int ret; + + ret = + cmdqRecCreate(CMDQ_SCENARIO_DISP_PRIMARY_DISABLE_SECURE_PATH, + &(nonsec_switch_handle)); + if (ret) + DISPAEE("[SVP]fail to create disable handle %s ret=%d\n", + __func__, ret); + + cmdqRecReset(nonsec_switch_handle); + /*_cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle);*/ + + if (module != DISP_MODULE_OVL1) { + /*Primary Mode*/ + if (primary_display_is_decouple_mode()) + cmdqRecWaitNoClear(nonsec_switch_handle, CMDQ_EVENT_DISP_WDMA0_EOF); + else + _cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle); + } else { + /*External Mode*/ + /*_cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle);*/ + cmdqRecWaitNoClear(nonsec_switch_handle, CMDQ_SYNC_DISP_EXT_STREAM_EOF); + } + cmdqRecSetSecure(nonsec_switch_handle, 1); + + /* we should disable ovl before new (nonsec) setting take effect + * or translation fault may happen, + * if we switch ovl to nonsec BUT its setting is still sec */ + for (i = 0; i < ovl_layer_num(module); i++) + ovl_layer_switch(module, i, 0, nonsec_switch_handle); + /*in fact, dapc/port_sec will be disabled by cmdq */ + cmdqRecSecureEnablePortSecurity(nonsec_switch_handle, (1LL << cmdq_engine)); + /* cmdqRecSecureEnableDAPC(handle, (1LL << cmdq_engine)); */ + /*cmdqRecSetEventToken(nonsec_switch_handle, cmdq_event_nonsec_end);*/ + /*cmdqRecFlushAsync(nonsec_switch_handle);*/ + cmdqRecFlush(nonsec_switch_handle); + cmdqRecDestroy(nonsec_switch_handle); + /*cmdqRecWait(handle, cmdq_event_nonsec_end);*/ + DISPMSG("[SVP] switch ovl%d to nonsec\n", ovl_idx); + } + ovl_is_sec[ovl_idx] = 0; + } + + return 0; +} + +static int ovl_config_l(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle) +{ + int enabled_layers = 0; + int has_sec_layer = 0; + int local_layer, global_layer, layer_id; + + if (pConfig->dst_dirty) + ovl_roi(module, pConfig->dst_w, pConfig->dst_h, gOVLBackground, handle); + + if (!pConfig->ovl_dirty) + return 0; + + for (global_layer = 0; global_layer < TOTAL_OVL_LAYER_NUM; global_layer++) { + if (!(pConfig->ovl_layer_scanned & (1 << global_layer))) + break; + } + if (global_layer > TOTAL_OVL_LAYER_NUM - ovl_layer_num(module)) { + DISPERR("%s: %s scan error, layer_scanned=%u\n", __func__, + ddp_get_module_name(module), pConfig->ovl_layer_scanned); + BUG(); + } + + /* check if the ovl module has sec layer */ + for (layer_id = global_layer; layer_id < (global_layer + ovl_layer_num(module)); layer_id++) { + if (pConfig->ovl_config[layer_id].layer_en && + (pConfig->ovl_config[layer_id].security == DISP_SECURE_BUFFER)) + has_sec_layer = 1; + } + + setup_ovl_sec(module, handle, has_sec_layer); + + for (local_layer = 0; local_layer < ovl_layer_num(module); local_layer++, global_layer++) { + + OVL_CONFIG_STRUCT *ovl_cfg = &pConfig->ovl_config[global_layer]; + + pConfig->ovl_layer_scanned |= (1 << global_layer); + + if (ovl_cfg->layer_en == 0) + continue; + if (ovl_check_input_param(ovl_cfg)) + continue; + print_layer_config_args(module, local_layer, ovl_cfg); + ovl_layer_config(module, local_layer, has_sec_layer, ovl_cfg, handle); + + enabled_layers |= 1 << local_layer; + + } + + DISP_REG_SET(handle, ovl_base_addr(module) + DISP_REG_OVL_SRC_CON, enabled_layers); + + return 0; +} + +int ovl_build_cmdq(DISP_MODULE_ENUM module, void *cmdq_trigger_handle, CMDQ_STATE state) +{ + int ret = 0; + /*int reg_pa = DISP_REG_OVL_FLOW_CTRL_DBG & 0x1fffffff;*/ + if (cmdq_trigger_handle == NULL) { + DISPERR("cmdq_trigger_handle is NULL\n"); + return -1; + } + + if (state == CMDQ_CHECK_IDLE_AFTER_STREAM_EOF) { + if (module == DISP_MODULE_OVL0) { + ret = cmdqRecPoll(cmdq_trigger_handle, 0x14007240, 2, 0x3f); + } else { + DISPERR("wrong module: %s\n", ddp_get_module_name(module)); + return -1; + } + } + + return 0; +} + + +/***************** ovl debug info ************/ + +void ovl_dump_reg(DISP_MODULE_ENUM module) +{ + unsigned long offset = ovl_base_addr(module); + unsigned int src_on = DISP_REG_GET(DISP_REG_OVL_SRC_CON + offset); + + DISPDMP("== START: DISP %s REGS ==\n", ddp_get_module_name(module)); + DISPDMP("OVL:0x000=0x%08x,0x004=0x%08x,0x008=0x%08x,0x00c=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_STA + offset), + DISP_REG_GET(DISP_REG_OVL_INTEN + offset), + DISP_REG_GET(DISP_REG_OVL_INTSTA + offset), DISP_REG_GET(DISP_REG_OVL_EN + offset)); + DISPDMP("OVL:0x010=0x%08x,0x014=0x%08x,0x020=0x%08x,0x024=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_TRIG + offset), + DISP_REG_GET(DISP_REG_OVL_RST + offset), + DISP_REG_GET(DISP_REG_OVL_ROI_SIZE + offset), + DISP_REG_GET(DISP_REG_OVL_DATAPATH_CON + offset)); + DISPDMP("OVL:0x028=0x%08x,0x02c=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_ROI_BGCLR + offset), + DISP_REG_GET(DISP_REG_OVL_SRC_CON + offset)); + + if (src_on & 0x1) { + DISPDMP("OVL:0x030=0x%08x,0x034=0x%08x,0x038=0x%08x,0x03c=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_L0_CON + offset), + DISP_REG_GET(DISP_REG_OVL_L0_SRCKEY + offset), + DISP_REG_GET(DISP_REG_OVL_L0_SRC_SIZE + offset), + DISP_REG_GET(DISP_REG_OVL_L0_OFFSET + offset)); + + DISPDMP("OVL:0xf40=0x%08x,0x044=0x%08x,0x0c0=0x%08x,0x0c8=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_L0_ADDR + offset), + DISP_REG_GET(DISP_REG_OVL_L0_PITCH + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA0_CTRL + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA0_MEM_GMC_SETTING + offset)); + + DISPDMP("OVL:0x0d0=0x%08x,0x1e0=0x%08x,0x24c=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_RDMA0_FIFO_CTRL + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA0_MEM_GMC_S2 + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA0_DBG + offset)); + } + if (src_on & 0x2) { + DISPDMP("OVL:0x050=0x%08x,0x054=0x%08x,0x058=0x%08x,0x05c=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_L1_CON + offset), + DISP_REG_GET(DISP_REG_OVL_L1_SRCKEY + offset), + DISP_REG_GET(DISP_REG_OVL_L1_SRC_SIZE + offset), + DISP_REG_GET(DISP_REG_OVL_L1_OFFSET + offset)); + + DISPDMP("OVL:0xf60=0x%08x,0x064=0x%08x,0x0e0=0x%08x,0x0e8=0x%08x,0x0f0=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_L1_ADDR + offset), + DISP_REG_GET(DISP_REG_OVL_L1_PITCH + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA1_CTRL + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA1_MEM_GMC_SETTING + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA1_FIFO_CTRL + offset)); + + DISPDMP("OVL:0x1e4=0x%08x,0x250=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_RDMA1_MEM_GMC_S2 + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA1_DBG + offset)); + } + if (src_on & 0x4) { + DISPDMP("OVL:0x070=0x%08x,0x074=0x%08x,0x078=0x%08x,0x07c=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_L2_CON + offset), + DISP_REG_GET(DISP_REG_OVL_L2_SRCKEY + offset), + DISP_REG_GET(DISP_REG_OVL_L2_SRC_SIZE + offset), + DISP_REG_GET(DISP_REG_OVL_L2_OFFSET + offset)); + + DISPDMP("OVL:0xf80=0x%08x,0x084=0x%08x,0x100=0x%08x,0x110=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_L2_ADDR + offset), + DISP_REG_GET(DISP_REG_OVL_L2_PITCH + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA2_CTRL + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA2_FIFO_CTRL + offset)); + + DISPDMP("OVL:0x1e8=0x%08x,0x254=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_RDMA2_MEM_GMC_S2 + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA2_DBG + offset)); + } + if (src_on & 0x8) { + DISPDMP("OVL:0x090=0x%08x,0x094=0x%08x,0x098=0x%08x,0x09c=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_L3_CON + offset), + DISP_REG_GET(DISP_REG_OVL_L3_SRCKEY + offset), + DISP_REG_GET(DISP_REG_OVL_L3_SRC_SIZE + offset), + DISP_REG_GET(DISP_REG_OVL_L3_OFFSET + offset)); + + DISPDMP("OVL:0xfa0=0x%08x,0x0a4=0x%08x,0x120=0x%08x,0x130=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_L3_ADDR + offset), + DISP_REG_GET(DISP_REG_OVL_L3_PITCH + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA3_CTRL + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA3_FIFO_CTRL + offset)); + + DISPDMP("OVL:0x1ec=0x%08x,0x258=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_RDMA3_MEM_GMC_S2 + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA3_DBG + offset)); + } + DISPDMP("OVL:0x1d4=0x%08x,0x1f8=0x%08x,0x1fc=0x%08x,0x200=0x%08x,0x20c=0x%08x\n" + "0x210=0x%08x,0x214=0x%08x,0x218=0x%08x,0x21c=0x%08x\n" + "0x230=0x%08x,0x234=0x%08x,0x240=0x%08x,0x244=0x%08x,0x2A0=0x%08x,0x2A4=0x%08x\n", + DISP_REG_GET(DISP_REG_OVL_DEBUG_MON_SEL + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA_GREQ_NUM + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA_GREQ_URG_NUM + offset), + DISP_REG_GET(DISP_REG_OVL_DUMMY_REG + offset), + DISP_REG_GET(DISP_REG_OVL_RDMA_ULTRA_SRC + offset), + + DISP_REG_GET(DISP_REG_OVL_RDMAn_BUF_LOW(0) + offset), + DISP_REG_GET(DISP_REG_OVL_RDMAn_BUF_LOW(1) + offset), + DISP_REG_GET(DISP_REG_OVL_RDMAn_BUF_LOW(2) + offset), + DISP_REG_GET(DISP_REG_OVL_RDMAn_BUF_LOW(3) + offset), + + DISP_REG_GET(DISP_REG_OVL_SMI_DBG + offset), + DISP_REG_GET(DISP_REG_OVL_GREQ_LAYER_CNT + offset), + DISP_REG_GET(DISP_REG_OVL_FLOW_CTRL_DBG + offset), + DISP_REG_GET(DISP_REG_OVL_ADDCON_DBG + offset), + DISP_REG_GET(DISP_REG_OVL_FUNC_DCM0 + offset), + DISP_REG_GET(DISP_REG_OVL_FUNC_DCM1 + offset)); + DISPDMP("-- END: DISP %s REGS --\n", ddp_get_module_name(module)); +} + +static void ovl_printf_status(unsigned int status) +{ + DISPDMP("=OVL_FLOW_CONTROL_DEBUG=:\n"); + DISPDMP("addcon_idle:%d,blend_idle:%d,out_valid:%d,out_ready:%d,out_idle:%d\n", + (status >> 10) & (0x1), + (status >> 11) & (0x1), + (status >> 12) & (0x1), (status >> 13) & (0x1), (status >> 15) & (0x1) + ); + DISPDMP("rdma3_idle:%d,rdma2_idle:%d,rdma1_idle:%d, rdma0_idle:%d,rst:%d\n", + (status >> 16) & (0x1), + (status >> 17) & (0x1), + (status >> 18) & (0x1), (status >> 19) & (0x1), (status >> 20) & (0x1) + ); + DISPDMP("trig:%d,frame_hwrst_done:%d,frame_swrst_done:%d,frame_underrun:%d,frame_done:%d\n", + (status >> 21) & (0x1), + (status >> 23) & (0x1), + (status >> 24) & (0x1), (status >> 25) & (0x1), (status >> 26) & (0x1) + ); + DISPDMP("ovl_running:%d,ovl_start:%d,ovl_clr:%d,reg_update:%d,ovl_upd_reg:%d\n", + (status >> 27) & (0x1), + (status >> 28) & (0x1), + (status >> 29) & (0x1), (status >> 30) & (0x1), (status >> 31) & (0x1) + ); + + DISPDMP("ovl_fms_state:\n"); + switch (status & 0x3ff) { + case 0x1: + DISPDMP("idle\n"); + break; + case 0x2: + DISPDMP("wait_SOF\n"); + break; + case 0x4: + DISPDMP("prepare\n"); + break; + case 0x8: + DISPDMP("reg_update\n"); + break; + case 0x10: + DISPDMP("eng_clr(internal reset)\n"); + break; + case 0x20: + DISPDMP("eng_act(processing)\n"); + break; + case 0x40: + DISPDMP("h_wait_w_rst\n"); + break; + case 0x80: + DISPDMP("s_wait_w_rst\n"); + break; + case 0x100: + DISPDMP("h_w_rst\n"); + break; + case 0x200: + DISPDMP("s_w_rst\n"); + break; + default: + DISPDMP("ovl_fsm_unknown\n"); + break; + } + +} + +static void ovl_print_ovl_rdma_status(unsigned int status) +{ + DISPDMP("wram_rst_cs:0x%x,layer_greq:0x%x,out_data:0x%x,", + status & 0x7, (status >> 3) & 0x1, (status >> 4) & 0xffffff); + DISPDMP("out_ready:0x%x,out_valid:0x%x,smi_busy:0x%x,smi_greq:0x%x\n", + (status >> 28) & 0x1, (status >> 29) & 0x1, (status >> 30) & 0x1, + (status >> 31) & 0x1); +} + +static void ovl_dump_layer_info(int layer, unsigned long layer_offset) +{ + enum UNIFIED_COLOR_FMT fmt; + + fmt = + display_fmt_reg_to_unified_fmt(DISP_REG_GET_FIELD + (L_CON_FLD_CFMT, DISP_REG_OVL_L0_CON + layer_offset), + DISP_REG_GET_FIELD(L_CON_FLD_BTSW, + DISP_REG_OVL_L0_CON + layer_offset), + DISP_REG_GET_FIELD(L_CON_FLD_RGB_SWAP, + DISP_REG_OVL_L0_CON + layer_offset)); + + DISPDMP("layer%d: w=%d,h=%d,off(x=%d,y=%d),pitch=%d,addr=0x%x,fmt=%s,source=%s,aen=%d,alpha=%d\n", + layer, DISP_REG_GET(layer_offset + DISP_REG_OVL_L0_SRC_SIZE) & 0xfff, + (DISP_REG_GET(layer_offset + DISP_REG_OVL_L0_SRC_SIZE) >> 16) & 0xfff, + DISP_REG_GET(layer_offset + DISP_REG_OVL_L0_OFFSET) & 0xfff, + (DISP_REG_GET(layer_offset + DISP_REG_OVL_L0_OFFSET) >> 16) & 0xfff, + DISP_REG_GET(layer_offset + DISP_REG_OVL_L0_PITCH) & 0xffff, + DISP_REG_GET(layer_offset + DISP_REG_OVL_L0_ADDR), unified_color_fmt_name(fmt), + (DISP_REG_GET_FIELD(L_CON_FLD_LARC, DISP_REG_OVL_L0_CON + layer_offset) == + 0) ? "memory" : "constant_color", DISP_REG_GET_FIELD(L_CON_FLD_AEN, + DISP_REG_OVL_L0_CON + + layer_offset), + DISP_REG_GET_FIELD(L_CON_FLD_APHA, DISP_REG_OVL_L0_CON + layer_offset) + ); +} + +void ovl_dump_analysis(DISP_MODULE_ENUM module) +{ + int i = 0; + unsigned long layer_offset = 0; + unsigned long rdma_offset = 0; + unsigned long offset = ovl_base_addr(module); + unsigned int src_on = DISP_REG_GET(DISP_REG_OVL_SRC_CON + offset); + unsigned int rdma_ctrl; + + DISPDMP("==DISP %s ANALYSIS==\n", ddp_get_module_name(module)); + DISPDMP("ovl_en=%d,layer_enable(%d,%d,%d,%d),bg(w=%d, h=%d),", + DISP_REG_GET(DISP_REG_OVL_EN + offset), + DISP_REG_GET(DISP_REG_OVL_SRC_CON + offset) & 0x1, + (DISP_REG_GET(DISP_REG_OVL_SRC_CON + offset) >> 1) & 0x1, + (DISP_REG_GET(DISP_REG_OVL_SRC_CON + offset) >> 2) & 0x1, + (DISP_REG_GET(DISP_REG_OVL_SRC_CON + offset) >> 3) & 0x1, + DISP_REG_GET(DISP_REG_OVL_ROI_SIZE + offset) & 0xfff, + (DISP_REG_GET(DISP_REG_OVL_ROI_SIZE + offset) >> 16) & 0xfff); + DISPDMP("cur_pos(x=%d,y=%d),layer_hit(%d,%d,%d,%d),bg_mode=%s,sta=0x%x\n", + DISP_REG_GET_FIELD(ADDCON_DBG_FLD_ROI_X, DISP_REG_OVL_ADDCON_DBG + offset), + DISP_REG_GET_FIELD(ADDCON_DBG_FLD_ROI_Y, DISP_REG_OVL_ADDCON_DBG + offset), + DISP_REG_GET_FIELD(ADDCON_DBG_FLD_L0_WIN_HIT, DISP_REG_OVL_ADDCON_DBG + offset), + DISP_REG_GET_FIELD(ADDCON_DBG_FLD_L1_WIN_HIT, DISP_REG_OVL_ADDCON_DBG + offset), + DISP_REG_GET_FIELD(ADDCON_DBG_FLD_L2_WIN_HIT, DISP_REG_OVL_ADDCON_DBG + offset), + DISP_REG_GET_FIELD(ADDCON_DBG_FLD_L3_WIN_HIT, DISP_REG_OVL_ADDCON_DBG + offset), + DISP_REG_GET_FIELD(DATAPATH_CON_FLD_BGCLR_IN_SEL, + DISP_REG_OVL_DATAPATH_CON + offset) ? "directlink" : "const", + DISP_REG_GET(DISP_REG_OVL_STA + offset) + ); + for (i = 0; i < 4; i++) { + layer_offset = i * OVL_LAYER_OFFSET + offset; + rdma_offset = i * OVL_RDMA_DEBUG_OFFSET + offset; + if (src_on & (0x1 << i)) + ovl_dump_layer_info(i, layer_offset); + else + DISPDMP("layer%d: disabled\n", i); + + rdma_ctrl = DISP_REG_GET(layer_offset + DISP_REG_OVL_RDMA0_CTRL); + + DISPDMP("ovl rdma%d status:(en=%d, fifo_used %d, GMC=0x%x)\n", i, + REG_FLD_VAL_GET(RDMA0_CTRL_FLD_RDMA_EN, rdma_ctrl), + REG_FLD_VAL_GET(RDMA0_CTRL_FLD_RMDA_FIFO_USED_SZ, rdma_ctrl), + DISP_REG_GET(layer_offset + DISP_REG_OVL_RDMA0_MEM_GMC_SETTING)); + ovl_print_ovl_rdma_status(DISP_REG_GET(DISP_REG_OVL_RDMA0_DBG + rdma_offset)); + } + ovl_printf_status(DISP_REG_GET(DISP_REG_OVL_FLOW_CTRL_DBG + offset)); +} + +int ovl_dump(DISP_MODULE_ENUM module, int level) +{ + ovl_dump_analysis(module); + ovl_dump_reg(module); + + return 0; +} + +static int ovl_golden_setting(DISP_MODULE_ENUM module, enum dst_module_type dst_mod_type, void *cmdq) +{ + unsigned long ovl_base = ovl_base_addr(module); + unsigned int regval; + int i, layer_num; + + layer_num = ovl_layer_num(module); + + /* DISP_REG_OVL_RDMA0_MEM_GMC_SETTING */ + regval = REG_FLD_VAL(FLD_OVL_RDMA_MEM_GMC_ULTRA_THRESHOLD, 0xff); + if (dst_mod_type == DST_MOD_REAL_TIME) + regval |= REG_FLD_VAL(FLD_OVL_RDMA_MEM_GMC_PRE_ULTRA_THRESHOLD, 0xff); + else + regval |= REG_FLD_VAL(FLD_OVL_RDMA_MEM_GMC_PRE_ULTRA_THRESHOLD, /*0x78*/ 0xff); + + for (i = 0; i < layer_num; i++) { + unsigned long layer_offset = i * OVL_LAYER_OFFSET + ovl_base; + + DISP_REG_SET(cmdq, layer_offset + DISP_REG_OVL_RDMA0_MEM_GMC_SETTING, regval); + } + + /* DISP_REG_OVL_RDMA0_FIFO_CTRL */ + regval = REG_FLD_VAL(FLD_OVL_RDMA_FIFO_SIZE, 144); + for (i = 0; i < layer_num; i++) { + unsigned long layer_offset = i * OVL_LAYER_OFFSET + ovl_base; + + DISP_REG_SET(cmdq, layer_offset + DISP_REG_OVL_RDMA0_FIFO_CTRL, regval); + } + + /* DISP_REG_OVL_RDMA_GREQ_NUM */ + regval = REG_FLD_VAL(FLD_OVL_RDMA_GREQ_LAYER0_GREQ_NUM, 5); + if (layer_num > 1) + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_LAYER1_GREQ_NUM, 5); + if (layer_num > 2) + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_LAYER2_GREQ_NUM, 5); + if (layer_num > 3) + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_LAYER3_GREQ_NUM, 5); + + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_OSTD_GREQ_NUM, 0xff); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_GREQ_DIS_CNT, 0); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_IOBUF_FLUSH_PREULTRA, 1); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_IOBUF_FLUSH_ULTRA, 0); + DISP_REG_SET(cmdq, ovl_base + DISP_REG_OVL_RDMA_GREQ_NUM, regval); + + /* DISP_REG_OVL_RDMA_GREQ_URG_NUM */ + regval = REG_FLD_VAL(FLD_OVL_RDMA_GREQ_LAYER0_GREQ_URG_NUM, 5); + if (layer_num > 0) + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_LAYER1_GREQ_URG_NUM, 5); + if (layer_num > 1) + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_LAYER2_GREQ_URG_NUM, 5); + if (layer_num > 2) + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_LAYER3_GREQ_URG_NUM, 5); + + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_ARG_GREQ_URG_TH, 0); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_GREQ_ARG_URG_BIAS, 0); + DISP_REG_SET(cmdq, ovl_base + DISP_REG_OVL_RDMA_GREQ_URG_NUM, regval); + + /* DISP_REG_OVL_RDMA_ULTRA_SRC */ + regval = REG_FLD_VAL(FLD_OVL_RDMA_PREULTRA_BUF_SRC, 0); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_PREULTRA_SMI_SRC, 0); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_PREULTRA_RDMA_SRC, 1); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_ULTRA_BUF_SRC, 0); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_ULTRA_SMI_SRC, 0); + if (dst_mod_type == DST_MOD_REAL_TIME) { + regval |= REG_FLD_VAL(FLD_OVL_RDMA_ULTRA_ROI_END_SRC, 0); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_PREULTRA_ROI_END_SRC, 0); + + } else { + regval |= REG_FLD_VAL(FLD_OVL_RDMA_ULTRA_ROI_END_SRC, 2); + regval |= REG_FLD_VAL(FLD_OVL_RDMA_PREULTRA_ROI_END_SRC, 1); + + } + regval |= REG_FLD_VAL(FLD_OVL_RDMA_ULTRA_RDMA_SRC, 2); + + DISP_REG_SET(cmdq, ovl_base + DISP_REG_OVL_RDMA_ULTRA_SRC, regval); + + /* DISP_REG_OVL_RDMAn_BUF_LOW */ + regval = REG_FLD_VAL(FLD_OVL_RDMA_BUF_LOW_ULTRA_TH, 0); + if (dst_mod_type == DST_MOD_REAL_TIME) + regval |= REG_FLD_VAL(FLD_OVL_RDMA_BUF_LOW_PREULTRA_TH, 0); + else + regval |= REG_FLD_VAL(FLD_OVL_RDMA_BUF_LOW_PREULTRA_TH, /*0x30*/ 0x0); + + for (i = 0; i < layer_num; i++) + DISP_REG_SET(cmdq, ovl_base + DISP_REG_OVL_RDMAn_BUF_LOW(i), regval); + + /* DISP_REG_OVL_FUNC_DCM1 -- no need anymore, because we set it @ovl_clock_on()*/ + /* DISP_REG_SET(cmdq, ovl_base + DISP_REG_OVL_FUNC_DCM1, 0x10); */ + + return 0; +} + +static int ovl_ioctl(DISP_MODULE_ENUM module, void *handle, DDP_IOCTL_NAME ioctl_cmd, void *params) +{ + int ret = 0; + + if (ioctl_cmd == DDP_OVL_GOLDEN_SETTING) { + struct ddp_io_golden_setting_arg *gset_arg = params; + + ovl_golden_setting(module, gset_arg->dst_mod_type, handle); + } + + return ret; +} + +/***************** driver************/ +DDP_MODULE_DRIVER ddp_driver_ovl = { + .init = ovl_init, + .deinit = ovl_deinit, + .config = ovl_config_l, + .start = ovl_start, + .trigger = NULL, + .stop = ovl_stop, + .reset = ovl_reset, + .power_on = ovl_clock_on, + .power_off = ovl_clock_off, + .suspend = ovl_suspend, + .resume = ovl_resume, + .is_idle = NULL, + .is_busy = NULL, + .dump_info = ovl_dump, + .bypass = NULL, + .build_cmdq = NULL, + .set_lcm_utils = NULL, + .ioctl = ovl_ioctl, + .connect = ovl_connect, +}; diff --git a/drivers/misc/mediatek/video/mt6755/ddp_ovl.h b/drivers/misc/mediatek/video/mt6755/ddp_ovl.h new file mode 100644 index 0000000000000000000000000000000000000000..72cdf2f9bb185cc50a76566a74c03a302ea966c5 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_ovl.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _DDP_OVL_H_ +#define _DDP_OVL_H_ + +#include "ddp_hal.h" +#include "ddp_info.h" + +#define OVL_MAX_WIDTH (4095) +#define OVL_MAX_HEIGHT (4095) + +#define TOTAL_OVL_LAYER_NUM (12) +#define OVL_NUM (4) +#define PRIMARY_THREE_OVL_CASCADE + +/* start overlay module */ +int ovl_start(DISP_MODULE_ENUM module, void *handle); + +/* stop overlay module */ +int ovl_stop(DISP_MODULE_ENUM module, void *handle); + +/* reset overlay module */ +int ovl_reset(DISP_MODULE_ENUM module, void *handle); + +/* set region of interest */ +int ovl_roi(DISP_MODULE_ENUM module, unsigned int bgW, unsigned int bgH, + unsigned int bgColor, + void *handle); + +/* switch layer on/off */ +int ovl_layer_switch(DISP_MODULE_ENUM module, unsigned layer, unsigned int en, void *handle); +/* get ovl input address */ +void ovl_get_address(DISP_MODULE_ENUM module, unsigned long *add); + +int ovl_3d_config(DISP_MODULE_ENUM module, + unsigned int layer_id, + unsigned int en_3d, unsigned int landscape, unsigned int r_first, void *handle); + +void ovl_dump_analysis(DISP_MODULE_ENUM module); +void ovl_dump_reg(DISP_MODULE_ENUM module); +unsigned long ovl_base_addr(DISP_MODULE_ENUM module); +unsigned long ovl_to_index(DISP_MODULE_ENUM module); + +void ovl_get_info(DISP_MODULE_ENUM module, void *data); +unsigned int ddp_ovl_get_cur_addr(bool rdma_mode, int layerid); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_path.c b/drivers/misc/mediatek/video/mt6755/ddp_path.c new file mode 100644 index 0000000000000000000000000000000000000000..0253c33266a5011afd58d89e4da4b3b328fdd7ea --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_path.c @@ -0,0 +1,1232 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#define LOG_TAG "ddp_path" +#include "disp_log.h" + +#include +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include "ddp_clkmgr.h" +#endif +#include "ddp_reg.h" + +#include "disp_debug.h" +#include "mtkfb_debug.h" +#include "ddp_path.h" +#include "primary_display.h" +#include "ddp_hal.h" +#include "disp_helper.h" +#include "ddp_path.h" + +#include "m4u.h" + +#pragma GCC optimize("O0") + +typedef struct module_map_s { + DISP_MODULE_ENUM module; + int bit; +} module_map_t; + +typedef struct { + int m; + int v; +} m_to_b; + +typedef struct mout_s { + int id; + m_to_b out_id_bit_map[5]; + + volatile unsigned long *reg; + unsigned int reg_val; +} mout_t; + +typedef struct selection_s { + int id; + int id_bit_map[5]; + + volatile unsigned long *reg; + unsigned int reg_val; +} sel_t; + +#define DDP_ENING_NUM (15) + +#define DDP_MOUT_NUM 4 +#define DDP_SEL_OUT_NUM 4 +#define DDP_SEL_IN_NUM 6 +#define DDP_MUTEX_MAX 5 + +unsigned int module_list_scenario[DDP_SCENARIO_MAX][DDP_ENING_NUM] = { + /*PRIMARY_DISP */ + { + DISP_MODULE_OVL0_2L, DISP_MODULE_OVL0, DISP_MODULE_OVL1_2L, DISP_MODULE_OVL0_VIRTUAL, + DISP_MODULE_COLOR0, DISP_MODULE_CCORR, DISP_MODULE_AAL, DISP_MODULE_GAMMA, + DISP_MODULE_DITHER, + DISP_MODULE_RDMA0, DISP_MODULE_UFOE, DISP_MODULE_PWM0, DISP_MODULE_DSI0, -1, -1}, + + /*PRIMARY_RDMA0_COLOR0_DISP */ + { + DISP_MODULE_RDMA0, DISP_MODULE_COLOR0, DISP_MODULE_CCORR, DISP_MODULE_AAL, + DISP_MODULE_GAMMA, DISP_MODULE_DITHER, DISP_MODULE_UFOE, DISP_MODULE_PWM0, + DISP_MODULE_DSI0, -1, -1, -1, -1, -1, -1}, + + /*PRIMARY_RDMA0_DISP */ + { + DISP_MODULE_RDMA0, DISP_MODULE_PWM0, DISP_MODULE_DSI0, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + + /*PRIMARY_BYPASS_RDMA */ + { + DISP_MODULE_OVL0_2L, DISP_MODULE_OVL0, DISP_MODULE_OVL1_2L, DISP_MODULE_OVL0_VIRTUAL, + DISP_MODULE_COLOR0, DISP_MODULE_CCORR, DISP_MODULE_AAL, DISP_MODULE_GAMMA, + DISP_MODULE_DITHER, + DISP_MODULE_UFOE, DISP_MODULE_PWM0, DISP_MODULE_DSI0, -1, -1}, + + /*PRIMARY_OVL_MEMOUT */ + { + DISP_MODULE_OVL0_2L, DISP_MODULE_OVL0, DISP_MODULE_OVL1_2L, DISP_MODULE_OVL0_VIRTUAL, + DISP_MODULE_WDMA0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + + /*PRIMARY_DITHER_MEMOUT */ + { + DISP_MODULE_OVL0_2L, DISP_MODULE_OVL0, DISP_MODULE_OVL1_2L, DISP_MODULE_OVL0_VIRTUAL, + DISP_MODULE_COLOR0, DISP_MODULE_CCORR, DISP_MODULE_AAL, DISP_MODULE_GAMMA, + DISP_MODULE_DITHER, DISP_MODULE_WDMA0, -1, -1, -1, -1, -1}, + /*PRIMARY_UFOE_MEMOUT */ + { + DISP_MODULE_OVL0_2L, DISP_MODULE_OVL0, DISP_MODULE_OVL1_2L, DISP_MODULE_OVL0_VIRTUAL, + DISP_MODULE_COLOR0, DISP_MODULE_CCORR, DISP_MODULE_AAL, DISP_MODULE_GAMMA, + DISP_MODULE_DITHER, DISP_MODULE_RDMA0, DISP_MODULE_UFOE, DISP_MODULE_WDMA0, -1, -1, -1}, + /*SUB_DISP */ + { + DISP_MODULE_OVL1, DISP_MODULE_RDMA1, DISP_MODULE_DPI, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1}, + /*SUB_RDMA1_DISP */ + { + DISP_MODULE_RDMA1, DISP_MODULE_DPI, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + /*SUB_OVL_MEMOUT */ + { + DISP_MODULE_OVL1, DISP_MODULE_WDMA1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + /*PRIMARY_DISP ALL*/ + { + DISP_MODULE_OVL0_2L, DISP_MODULE_OVL0, DISP_MODULE_OVL1_2L, DISP_MODULE_OVL0_VIRTUAL, DISP_MODULE_WDMA0, + DISP_MODULE_COLOR0, DISP_MODULE_CCORR, DISP_MODULE_AAL, DISP_MODULE_GAMMA, DISP_MODULE_DITHER, + DISP_MODULE_RDMA0, DISP_MODULE_UFOE, DISP_MODULE_PWM0, DISP_MODULE_DSI0, -1}, + /*SUB_ALL */ + { + DISP_MODULE_OVL1, DISP_MODULE_WDMA1, DISP_MODULE_RDMA1, DISP_MODULE_DPI, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1}, + /*DDP_SCENARIO_DITHER_1TO2*/ + { + DISP_MODULE_OVL0_2L, DISP_MODULE_OVL0, DISP_MODULE_OVL1_2L, DISP_MODULE_OVL0_VIRTUAL, + DISP_MODULE_COLOR0, DISP_MODULE_CCORR, DISP_MODULE_AAL, DISP_MODULE_GAMMA, DISP_MODULE_DITHER, + DISP_MODULE_WDMA0, DISP_MODULE_RDMA0, DISP_MODULE_UFOE, DISP_MODULE_PWM0, DISP_MODULE_DSI0, -1}, + /*DDP_SCENARIO_UFOE_1TO2*/ + { + DISP_MODULE_OVL0_2L, DISP_MODULE_OVL0, DISP_MODULE_OVL1_2L, DISP_MODULE_OVL0_VIRTUAL, + DISP_MODULE_COLOR0, DISP_MODULE_CCORR, DISP_MODULE_AAL, DISP_MODULE_GAMMA, DISP_MODULE_DITHER, + DISP_MODULE_RDMA0, DISP_MODULE_UFOE, DISP_MODULE_WDMA0, DISP_MODULE_PWM0, DISP_MODULE_DSI0, -1}, +}; + +/* 1st para is mout's input, 2nd para is mout's output */ +static mout_t mout_map[DDP_MOUT_NUM] = { + /* OVL_MOUT */ + {DISP_MODULE_OVL0_VIRTUAL, + {{DISP_MODULE_COLOR0, 1 << 0}, {DISP_MODULE_WDMA0, 1 << 1}, {-1, 0} }, 0, 0}, + {DISP_MODULE_OVL1, + {{DISP_MODULE_RDMA1, 1 << 0}, {DISP_MODULE_WDMA1, 1 << 1}, + {DISP_MODULE_OVL0_VIRTUAL, 1 << 2}, {-1, 0} }, 0, 0}, + /* DITHER0_MOUT */ + {DISP_MODULE_DITHER, + {{DISP_MODULE_RDMA0, 1 << 0}, {DISP_MODULE_UFOE, 1 << 1}, {DISP_MODULE_WDMA0, 1 << 2}, + {-1, 0} }, 0, 0}, + /* UFOE_MOUT */ + {DISP_MODULE_UFOE, + {{DISP_MODULE_DSI0, 1 << 0}, {DISP_MODULE_DPI, 1 << 1}, {DISP_MODULE_WDMA0, 1 << 2}, + {-1, 0} }, 0, 0}, +}; + +static sel_t sel_out_map[DDP_SEL_OUT_NUM] = { + /* OVL0_SOUT */ + {DISP_MODULE_OVL0, {DISP_MODULE_OVL0_VIRTUAL, DISP_MODULE_OVL1_2L, -1}, 0, 0}, + /* OVL1_SOUT */ + {DISP_MODULE_OVL1_2L, {DISP_MODULE_OVL1, DISP_MODULE_OVL0_VIRTUAL, -1}, 0, 0}, + /* RDMA_SOUT */ + {DISP_MODULE_RDMA0, + {DISP_MODULE_UFOE, DISP_MODULE_COLOR0, DISP_MODULE_DSI0, DISP_MODULE_DPI, -1}, 0, 0}, + {DISP_MODULE_RDMA1, {DISP_MODULE_DSI0, DISP_MODULE_DPI, -1}, 0, 0}, +}; + +/* 1st para is sout's output, 2nd para is sout's input */ +static sel_t sel_in_map[DDP_SEL_IN_NUM] = { + /* OVL0_SEL */ + {DISP_MODULE_OVL0_VIRTUAL, {DISP_MODULE_OVL0, DISP_MODULE_OVL1, DISP_MODULE_OVL1_2L, -1}, 0, + 0}, + + /* COLOR_SEL */ + {DISP_MODULE_COLOR0, {DISP_MODULE_RDMA0, DISP_MODULE_OVL0_VIRTUAL, -1}, 0, 0}, + + /* UFOE_SEL */ + {DISP_MODULE_UFOE, {DISP_MODULE_RDMA0, DISP_MODULE_DITHER, -1}, 0, 0}, + + /* DSI0_SEL */ + {DISP_MODULE_DSI0, {DISP_MODULE_UFOE, DISP_MODULE_RDMA0, DISP_MODULE_RDMA1, -1}, 0, 0}, + + /* DPI0_SEL */ + {DISP_MODULE_DPI, {DISP_MODULE_UFOE, DISP_MODULE_RDMA0, DISP_MODULE_RDMA1, -1}, 0, 0}, + + /* WDMA_SEL */ + {DISP_MODULE_WDMA0, {DISP_MODULE_OVL0_VIRTUAL, DISP_MODULE_DITHER, DISP_MODULE_UFOE, -1}, 0, 0}, +}; + + +int ddp_path_init(void) +{ + /* mout */ + mout_map[0].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_OVL0_MOUT_EN; + mout_map[1].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_OVL1_MOUT_EN; + mout_map[2].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_DITHER_MOUT_EN; + mout_map[3].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_UFOE_MOUT_EN; + /* sel_out */ + sel_out_map[0].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_OVL0_SOUT_SEL_IN; + sel_out_map[1].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_OVL1_SOUT_SEL_IN; + sel_out_map[2].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN; + sel_out_map[3].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN; + /* sel_in */ + sel_in_map[0].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_OVL0_SEL_IN; /* OVL_SEL */ + sel_in_map[1].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_COLOR0_SEL_IN; /* COLOR_SEL */ + sel_in_map[2].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_UFOE_SEL_IN; /* UFOE_SEL */ + sel_in_map[3].reg = (volatile unsigned long *)DISP_REG_CONFIG_DSI0_SEL_IN; /* DSI0_SEL */ + sel_in_map[4].reg = (volatile unsigned long *)DISP_REG_CONFIG_DPI0_SEL_IN; /* DPI0_SEL */ + sel_in_map[5].reg = (volatile unsigned long *)DISP_REG_CONFIG_DISP_WDMA0_SEL_IN; /* WDMA_SEL */ + return 0; +} + +static module_map_t module_mutex_map[DISP_MODULE_NUM] = { + {DISP_MODULE_OVL0, 7}, + {DISP_MODULE_OVL1, 8}, + {DISP_MODULE_OVL0_2L, 19}, + {DISP_MODULE_OVL1_2L, 20}, + {DISP_MODULE_RDMA0, 9}, + {DISP_MODULE_RDMA1, 10}, + {DISP_MODULE_WDMA0, 11}, + {DISP_MODULE_COLOR0, 12}, + {DISP_MODULE_CCORR, 13}, + {DISP_MODULE_AAL, 14}, + {DISP_MODULE_GAMMA, 15}, + {DISP_MODULE_DITHER, 16}, + {DISP_MODULE_UFOE, -1}, + {DISP_MODULE_PWM0, 18}, + {DISP_MODULE_WDMA1, 17}, + {DISP_MODULE_DSI0, -1}, + {DISP_MODULE_DPI, -1}, + {DISP_MODULE_SMI, -1}, + {DISP_MODULE_CONFIG, -1}, + {DISP_MODULE_CMDQ, -1}, + {DISP_MODULE_MUTEX, -1}, + {DISP_MODULE_COLOR1, -1}, + {DISP_MODULE_RDMA2, -1}, + {DISP_MODULE_PWM1, -1}, + {DISP_MODULE_OD, -1}, + {DISP_MODULE_MERGE, -1}, + {DISP_MODULE_SPLIT0, -1}, + {DISP_MODULE_SPLIT1, -1}, + {DISP_MODULE_DSI1, -1}, + {DISP_MODULE_DSIDUAL, -1}, + {DISP_MODULE_SMI_LARB0, -1}, + {DISP_MODULE_SMI_COMMON, -1}, + {DISP_MODULE_OVL0_VIRTUAL, -1}, + {DISP_MODULE_UNKNOWN, -1}, +}; + +/* module can be connect if 1 */ +static module_map_t module_can_connect[DISP_MODULE_NUM] = { + {DISP_MODULE_OVL0, 1}, + {DISP_MODULE_OVL1, 1}, + {DISP_MODULE_OVL0_2L, 0}, + {DISP_MODULE_OVL1_2L, 1}, + {DISP_MODULE_RDMA0, 1}, + {DISP_MODULE_RDMA1, 1}, + {DISP_MODULE_WDMA0, 1}, + {DISP_MODULE_COLOR0, 1}, + {DISP_MODULE_CCORR, 1}, + {DISP_MODULE_AAL, 1}, + {DISP_MODULE_GAMMA, 1}, + {DISP_MODULE_DITHER, 1}, + {DISP_MODULE_UFOE, 1}, + {DISP_MODULE_PWM0, 0}, + {DISP_MODULE_WDMA1, 1}, + {DISP_MODULE_DSI0, 1}, + {DISP_MODULE_DPI, 1}, + {DISP_MODULE_SMI, 0}, + {DISP_MODULE_CONFIG, 0}, + {DISP_MODULE_CMDQ, 0}, + {DISP_MODULE_MUTEX, 0}, + {DISP_MODULE_COLOR1, 0}, + {DISP_MODULE_RDMA2, 0}, + {DISP_MODULE_PWM1, 0}, + {DISP_MODULE_OD, 0}, + {DISP_MODULE_MERGE, 0}, + {DISP_MODULE_SPLIT0, 0}, + {DISP_MODULE_SPLIT1, 0}, + {DISP_MODULE_DSI1, 0}, + {DISP_MODULE_DSIDUAL, 0}, + {DISP_MODULE_SMI_LARB0, 0}, + {DISP_MODULE_SMI_COMMON, 0}, + {DISP_MODULE_OVL0_VIRTUAL, 1}, + {DISP_MODULE_UNKNOWN, 0}, +}; + + + +char *ddp_get_scenario_name(DDP_SCENARIO_ENUM scenario) +{ + switch (scenario) { + case DDP_SCENARIO_PRIMARY_DISP: + return "primary_disp"; + case DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP: + return "primary_rdma0_color0_disp"; + case DDP_SCENARIO_PRIMARY_RDMA0_DISP: + return "primary_rdma0_disp"; + case DDP_SCENARIO_PRIMARY_BYPASS_RDMA: + return "primary_bypass_rdma"; + case DDP_SCENARIO_PRIMARY_OVL_MEMOUT: + return "primary_ovl_memout"; + case DDP_SCENARIO_PRIMARY_DITHER_MEMOUT: + return "primary_dither_memout"; + case DDP_SCENARIO_PRIMARY_UFOE_MEMOUT: + return "primary_ufoe_memout"; + case DDP_SCENARIO_SUB_DISP: + return "sub_disp"; + case DDP_SCENARIO_SUB_RDMA1_DISP: + return "sub_rdma1_disp"; + case DDP_SCENARIO_SUB_OVL_MEMOUT: + return "sub_ovl_memout"; + case DDP_SCENARIO_PRIMARY_ALL: + return "primary_all"; + case DDP_SCENARIO_SUB_ALL: + return "sub_all"; + case DDP_SCENARIO_DITHER_1TO2: + return "dither_1to2"; + case DDP_SCENARIO_UFOE_1TO2: + return "ufoe_1to2"; + default: + DISPMSG("invalid scenario id=%d\n", scenario); + return "unknown"; + } +} + +int ddp_is_scenario_on_primary(DDP_SCENARIO_ENUM scenario) +{ + int on_primary = 0; + + switch (scenario) { + case DDP_SCENARIO_PRIMARY_DISP: + case DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP: + case DDP_SCENARIO_PRIMARY_RDMA0_DISP: + case DDP_SCENARIO_PRIMARY_BYPASS_RDMA: + case DDP_SCENARIO_PRIMARY_OVL_MEMOUT: + case DDP_SCENARIO_PRIMARY_DITHER_MEMOUT: + case DDP_SCENARIO_PRIMARY_UFOE_MEMOUT: + case DDP_SCENARIO_PRIMARY_ALL: + case DDP_SCENARIO_DITHER_1TO2: + case DDP_SCENARIO_UFOE_1TO2: + on_primary = 1; + break; + case DDP_SCENARIO_SUB_DISP: + case DDP_SCENARIO_SUB_RDMA1_DISP: + case DDP_SCENARIO_SUB_OVL_MEMOUT: + case DDP_SCENARIO_SUB_ALL: + on_primary = 0; + break; + default: + DISPMSG("invalid scenario id=%d\n", scenario); + } + + return on_primary; + +} + +char *ddp_get_mutex_sof_name(unsigned int regval) +{ + if (regval == SOF_VAL_MUTEX0_SOF_SINGLE_MODE) + return "single"; + else if (regval == SOF_VAL_MUTEX0_SOF_FROM_DSI0) + return "dsi0"; + else if (regval == SOF_VAL_MUTEX0_SOF_FROM_DPI) + return "dpi"; + DISPDMP("%s, unknown reg=%d\n", __func__, regval); + return "unknown"; +} + +char *ddp_get_mode_name(DDP_MODE ddp_mode) +{ + switch (ddp_mode) { + case DDP_VIDEO_MODE: + return "vido_mode"; + case DDP_CMD_MODE: + return "cmd_mode"; + default: + DISPMSG("invalid ddp mode =%d\n", ddp_mode); + return "unknown"; + } +} + +static int ddp_get_module_num_l(int *module_list) +{ + unsigned int num = 0; + + while (*(module_list + num) != -1) { + num++; + + if (num == DDP_ENING_NUM) + break; + } + return num; +} + +/* config mout/msel to creat a compelte path */ +static void ddp_connect_path_l(int *module_list, void *handle) +{ + unsigned int i, j, k; + int step = 0; + unsigned int mout = 0; + unsigned int reg_mout = 0; + unsigned int mout_idx = 0; + unsigned int module_num = ddp_get_module_num_l(module_list); + + DISPDBG("connect_path: %s to %s\n", ddp_get_module_name(module_list[0]), + ddp_get_module_name(module_list[module_num - 1])); + /* connect mout */ + for (i = 0; i < module_num - 1; i++) { + for (j = 0; j < DDP_MOUT_NUM; j++) { + if (module_list[i] == mout_map[j].id) { + /* find next module which can be connected */ + step = i + 1; + while (module_can_connect[module_list[step]].bit == 0 + && step < module_num) { + step++; + } + ASSERT(step < module_num); + mout = mout_map[j].reg_val; + for (k = 0; k < 5; k++) { + if (mout_map[j].out_id_bit_map[k].m == -1) + break; + if (mout_map[j].out_id_bit_map[k].m == module_list[step]) { + mout |= mout_map[j].out_id_bit_map[k].v; + reg_mout |= mout; + mout_idx = j; + DISPDBG("connect mout %s to %s value 0x%x\n", + ddp_get_module_name(module_list[i]), + ddp_get_module_name(module_list[step]), + reg_mout); + break; + } + } + mout_map[j].reg_val = mout; + mout = 0; + } + } + if (reg_mout) { + DISP_REG_SET(handle, mout_map[mout_idx].reg, reg_mout); + reg_mout = 0; + mout_idx = 0; + } + + } + /* connect out select */ + for (i = 0; i < module_num - 1; i++) { + for (j = 0; j < DDP_SEL_OUT_NUM; j++) { + if (module_list[i] == sel_out_map[j].id) { + step = i + 1; + /* find next module which can be connected */ + while (module_can_connect[module_list[step]].bit == 0 + && step < module_num) { + step++; + } + ASSERT(step < module_num); + for (k = 0; k < 4; k++) { + if (sel_out_map[j].id_bit_map[k] == -1) + break; + if (sel_out_map[j].id_bit_map[k] == module_list[step]) { + DISPDBG("connect out_s %s to %s, bits=0x%x\n", + ddp_get_module_name(module_list[i]), + ddp_get_module_name(module_list[step]), k); + DISP_REG_SET(handle, sel_out_map[j].reg, + (uint16_t) k); + break; + } + } + } + } + } + /* connect input select */ + for (i = 1; i < module_num; i++) { + for (j = 0; j < DDP_SEL_IN_NUM; j++) { + if (module_list[i] == sel_in_map[j].id) { + int found = 0; + + step = i - 1; + /* find next module which can be connected */ + while (module_can_connect[module_list[step]].bit == 0 && step > 0) + step--; + + ASSERT(step >= 0); + for (k = 0; k < 4; k++) { + if (sel_in_map[j].id_bit_map[k] == -1) + break; + if (sel_in_map[j].id_bit_map[k] == module_list[step]) { + DISPDBG("connect in_s %s to %s, bits=0x%x\n", + ddp_get_module_name(module_list[step]), + ddp_get_module_name(module_list[i]), k); + DISP_REG_SET(handle, sel_in_map[j].reg, + (uint16_t) k); + found = 1; + break; + } + } + if (!found) + pr_err("%s error: %s sel_in not set\n", __func__, + ddp_get_module_name(module_list[i])); + } + } + } +} + +static void ddp_check_path_l(int *module_list) +{ + unsigned int i, j, k; + int step = 0; + int valid = 0; + unsigned int mout; + unsigned int path_error = 0; + unsigned int module_num = ddp_get_module_num_l(module_list); + + DISPDMP("check_path: %s to %s\n", ddp_get_module_name(module_list[0]) + , ddp_get_module_name(module_list[module_num - 1])); + /* check mout */ + for (i = 0; i < module_num - 1; i++) { + for (j = 0; j < DDP_MOUT_NUM; j++) { + if (module_list[i] == mout_map[j].id) { + mout = 0; + /* find next module which can be connected */ + step = i + 1; + while (module_can_connect[module_list[step]].bit == 0 + && step < module_num) { + step++; + } + ASSERT(step < module_num); + for (k = 0; k < 5; k++) { + if (mout_map[j].out_id_bit_map[k].m == -1) + break; + if (mout_map[j].out_id_bit_map[k].m == module_list[step]) { + mout |= mout_map[j].out_id_bit_map[k].v; + valid = 1; + break; + } + } + if (valid) { + valid = 0; + if ((DISP_REG_GET(mout_map[j].reg) & mout) == 0) { + path_error += 1; + DISPDMP("error:%s mout, expect=0x%x, real=0x%x\n", + ddp_get_module_name(module_list[i]), + mout, DISP_REG_GET(mout_map[j].reg)); + } else if (DISP_REG_GET(mout_map[j].reg) != mout) { + DISPDMP + ("warning: %s mout expect=0x%x, real=0x%x\n", + ddp_get_module_name(module_list[i]), mout, + DISP_REG_GET(mout_map[j].reg)); + } + } + break; + } + } + } + /* check out select */ + for (i = 0; i < module_num - 1; i++) { + for (j = 0; j < DDP_SEL_OUT_NUM; j++) { + if (module_list[i] != sel_out_map[j].id) + continue; + /* find next module which can be connected */ + step = i + 1; + while (module_can_connect[module_list[step]].bit == 0 + && step < module_num) { + step++; + } + ASSERT(step < module_num); + for (k = 0; k < 4; k++) { + if (sel_out_map[j].id_bit_map[k] == -1) + break; + if (sel_out_map[j].id_bit_map[k] == module_list[step]) { + if (DISP_REG_GET(sel_out_map[j].reg) != k) { + path_error += 1; + DISPDMP + ("error:out_s %s not connect to %s, expect=0x%x, real=0x%x\n", + ddp_get_module_name(module_list[i]), + ddp_get_module_name(module_list[step]), + k, DISP_REG_GET(sel_out_map[j].reg)); + } + break; + } + } + } + } + /* check input select */ + for (i = 1; i < module_num; i++) { + for (j = 0; j < DDP_SEL_IN_NUM; j++) { + if (module_list[i] != sel_in_map[j].id) + continue; + /* find next module which can be connected */ + step = i - 1; + while (module_can_connect[module_list[step]].bit == 0 && step > 0) + step--; + ASSERT(step >= 0); + for (k = 0; k < 4; k++) { + if (sel_in_map[j].id_bit_map[k] == -1) + break; + if (sel_in_map[j].id_bit_map[k] == module_list[step]) { + if (DISP_REG_GET(sel_in_map[j].reg) != k) { + path_error += 1; + DISPDMP("error:in_s %s not conn to %s,expect0x%x,real0x%x\n", + ddp_get_module_name(module_list[step]), + ddp_get_module_name(module_list[i]), k, + DISP_REG_GET(sel_in_map[j].reg)); + } + break; + } + } + } + } + if (path_error == 0) { + DISPDMP("path: %s to %s is connected\n", ddp_get_module_name(module_list[0]), + ddp_get_module_name(module_list[module_num - 1])); + } else { + DISPDMP("path: %s to %s not connected!!!\n", ddp_get_module_name(module_list[0]), + ddp_get_module_name(module_list[module_num - 1])); + } +} + +static void ddp_disconnect_path_l(int *module_list, void *handle) +{ + unsigned int i, j, k; + int step = 0; + unsigned int mout = 0; + unsigned int reg_mout = 0; + unsigned int mout_idx = 0; + unsigned int module_num = ddp_get_module_num_l(module_list); + + DISPDBG("disconnect_path: %s to %s\n", ddp_get_module_name(module_list[0]), + ddp_get_module_name(module_list[module_num - 1])); + for (i = 0; i < module_num - 1; i++) { + for (j = 0; j < DDP_MOUT_NUM; j++) { + if (module_list[i] == mout_map[j].id) { + /* find next module which can be connected */ + step = i + 1; + while (module_can_connect[module_list[step]].bit == 0 + && step < module_num) { + step++; + } + ASSERT(step < module_num); + for (k = 0; k < 5; k++) { + if (mout_map[j].out_id_bit_map[k].m == -1) + break; + if (mout_map[j].out_id_bit_map[k].m == module_list[step]) { + mout |= mout_map[j].out_id_bit_map[k].v; + reg_mout |= mout; + mout_idx = j; + DISPDBG("disconnect mout %s to %s\n", + ddp_get_module_name(module_list[i]), + ddp_get_module_name(module_list[step])); + break; + } + } + /* update mout_value */ + mout_map[j].reg_val &= ~mout; + mout = 0; + } + } + if (reg_mout) { + DISP_REG_SET(handle, mout_map[mout_idx].reg, mout_map[mout_idx].reg_val); + reg_mout = 0; + mout_idx = 0; + } + } +} + +static int ddp_get_mutex_src(DISP_MODULE_ENUM dest_module, DDP_MODE ddp_mode, + unsigned int *SOF_src, unsigned int *EOF_src) +{ + unsigned int src_from_dst_module = 0; + + if (dest_module == DISP_MODULE_WDMA0 || dest_module == DISP_MODULE_WDMA1) { + + if (ddp_mode == DDP_VIDEO_MODE) + DISPDBG("%s: dst_mode=%s, but is video mode !!\n", __func__, + ddp_get_module_name(dest_module)); + + *SOF_src = *EOF_src = SOF_VAL_MUTEX0_SOF_SINGLE_MODE; + return 0; + } + + if (dest_module == DISP_MODULE_DSI0) { + src_from_dst_module = SOF_VAL_MUTEX0_SOF_FROM_DSI0; + } else if (dest_module == DISP_MODULE_DPI) { + src_from_dst_module = SOF_VAL_MUTEX0_SOF_FROM_DPI; + } else { + DISPERR("get mutex sof, invalid param dst module = %s(%d), dis mode %s\n", + ddp_get_module_name(dest_module), dest_module, ddp_get_mode_name(ddp_mode)); + BUG(); + } + + if (ddp_mode == DDP_CMD_MODE) { + *SOF_src = SOF_VAL_MUTEX0_SOF_SINGLE_MODE; + if (disp_helper_get_option(DISP_OPT_MUTEX_EOF_EN_FOR_CMD_MODE)) + *EOF_src = src_from_dst_module; + else + *EOF_src = SOF_VAL_MUTEX0_EOF_SINGLE_MODE; + + } else { + *SOF_src = *EOF_src = src_from_dst_module; + } + + return 0; +} + +/* id: mutex ID, 0~5 */ +static int ddp_mutex_set_l(int mutex_id, int *module_list, DDP_MODE ddp_mode, void *handle) +{ + int i = 0; + unsigned int value = 0; + unsigned int sof_val; + unsigned int sof_src, eof_src; + int module_num = ddp_get_module_num_l(module_list); + + ddp_get_mutex_src(module_list[module_num - 1], ddp_mode, &sof_src, &eof_src); + if (mutex_id < DISP_MUTEX_DDP_FIRST || mutex_id > DISP_MUTEX_DDP_LAST) { + DISPERR("exceed mutex max (0 ~ %d)\n", DISP_MUTEX_DDP_LAST); + return -1; + } + for (i = 0; i < module_num; i++) { + if (module_mutex_map[module_list[i]].bit != -1) { + DISPDBG("module %s added to mutex %d\n", ddp_get_module_name(module_list[i]), + mutex_id); + value |= (1 << module_mutex_map[module_list[i]].bit); + } else { + DISPDBG("module %s not added to mutex %d\n", + ddp_get_module_name(module_list[i]), mutex_id); + } + } + DISP_REG_SET(handle, DISP_REG_CONFIG_MUTEX_MOD(mutex_id), value); + + sof_val = REG_FLD_VAL(SOF_FLD_MUTEX0_SOF, sof_src); + sof_val |= REG_FLD_VAL(SOF_FLD_MUTEX0_EOF, eof_src); + DISP_REG_SET(handle, DISP_REG_CONFIG_MUTEX_SOF(mutex_id), sof_val); + + DISPDBG("mutex %d value=0x%x, sof=%s, eof=%s\n", mutex_id, + value, ddp_get_mutex_sof_name(sof_src), ddp_get_mutex_sof_name(eof_src)); + return 0; +} + +static void ddp_check_mutex_l(int mutex_id, int *module_list, DDP_MODE ddp_mode) +{ + int i = 0; + uint32_t real_value = 0; + uint32_t expect_value = 0; + unsigned int real_sof, real_eof, val; + unsigned int expect_sof, expect_eof; + int module_num = ddp_get_module_num_l(module_list); + + if (mutex_id < DISP_MUTEX_DDP_FIRST || mutex_id > DISP_MUTEX_DDP_LAST) { + DISPDMP("error:check mutex fail:exceed mutex max (0 ~ %d)\n", DISP_MUTEX_DDP_LAST); + return; + } + real_value = DISP_REG_GET(DISP_REG_CONFIG_MUTEX_MOD(mutex_id)); + for (i = 0; i < module_num; i++) { + if (module_mutex_map[module_list[i]].bit != -1) + expect_value |= (1 << module_mutex_map[module_list[i]].bit); + } + if (expect_value != real_value) + DISPDMP("error:mutex %d error: expect 0x%x, real 0x%x\n", mutex_id, expect_value, + real_value); + + val = DISP_REG_GET(DISP_REG_CONFIG_MUTEX_SOF(mutex_id)); + real_sof = REG_FLD_VAL_GET(SOF_FLD_MUTEX0_SOF, val); + real_eof = REG_FLD_VAL_GET(SOF_FLD_MUTEX0_EOF, val); + ddp_get_mutex_src(module_list[module_num - 1], ddp_mode, &expect_sof, &expect_eof); + if (expect_sof != real_sof) + DISPDMP("error:mutex %d sof error: expect %s, real %s\n", mutex_id, + ddp_get_mutex_sof_name(expect_sof), ddp_get_mutex_sof_name(real_sof)); + if (expect_eof != real_eof) + DISPDMP("error:mutex %d eof error: expect %s, real %s\n", mutex_id, + ddp_get_mutex_sof_name(expect_eof), ddp_get_mutex_sof_name(real_eof)); + +} + +static int ddp_mutex_enable_l(int mutex_idx, void *handle) +{ + DISPDBG("mutex %d enable\n", mutex_idx); + DISP_REG_SET(handle, DISP_REG_CONFIG_MUTEX_EN(mutex_idx), 1); + return 0; +} + +int ddp_get_module_num(DDP_SCENARIO_ENUM scenario) +{ + return ddp_get_module_num_l(module_list_scenario[scenario]); +} + +static void ddp_print_scenario(DDP_SCENARIO_ENUM scenario) +{ + int i = 0; + char path[256] = { '\0' }; + int num = ddp_get_module_num(scenario); + + for (i = 0; i < num; i++) { + ASSERT(strlen(path) + strlen(ddp_get_module_name(module_list_scenario[scenario][i])) < 256); + strncat(path, ddp_get_module_name(module_list_scenario[scenario][i]), sizeof(path)); + } + + DISPMSG("scenario %s have modules: %s\n", ddp_get_scenario_name(scenario), path); +} + +static int ddp_find_module_index(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM module) +{ + int i = 0; + + for (i = 0; i < DDP_ENING_NUM; i++) { + if (module_list_scenario[ddp_scenario][i] == module) + return i; + + } + DISPDBG("find module: can not find module %s on scenario %s\n", ddp_get_module_name(module), + ddp_get_scenario_name(ddp_scenario)); + return -1; +} + +/* set display interface when kernel init */ +int ddp_set_dst_module(DDP_SCENARIO_ENUM scenario, DISP_MODULE_ENUM dst_module) +{ + int i = 0; + + DISPMSG("ddp_set_dst_module, scenario=%s, dst_module=%s\n", + ddp_get_scenario_name(scenario), ddp_get_module_name(dst_module)); + if (ddp_find_module_index(scenario, dst_module) > 0) { + DISPDBG("%s is already on path\n", ddp_get_module_name(dst_module)); + return 0; + } + i = ddp_get_module_num_l(module_list_scenario[scenario]) - 1; + ASSERT(i >= 0); + if (dst_module == DISP_MODULE_DSIDUAL) { + if (i < (DDP_ENING_NUM - 1)) { + module_list_scenario[scenario][i++] = DISP_MODULE_SPLIT1; + } else { + DISPERR("set dst module over up bound\n"); + return -1; + } + } else { + if (ddp_get_dst_module(scenario) == DISP_MODULE_DSIDUAL) { + if (i >= 1) { + module_list_scenario[scenario][i--] = -1; + } else { + DISPERR("set dst module over low bound\n"); + return -1; + } + } + } + module_list_scenario[scenario][i] = dst_module; + if (scenario == DDP_SCENARIO_PRIMARY_ALL) + ddp_set_dst_module(DDP_SCENARIO_PRIMARY_DISP, dst_module); + else if (scenario == DDP_SCENARIO_SUB_ALL) + ddp_set_dst_module(DDP_SCENARIO_SUB_RDMA1_DISP, dst_module); + else if (scenario == DDP_SCENARIO_DITHER_1TO2) + ddp_set_dst_module(DDP_SCENARIO_PRIMARY_DISP, dst_module); + else if (scenario == DDP_SCENARIO_UFOE_1TO2) + ddp_set_dst_module(DDP_SCENARIO_PRIMARY_DISP, dst_module); + + ddp_print_scenario(scenario); + return 0; +} + +DISP_MODULE_ENUM ddp_get_dst_module(DDP_SCENARIO_ENUM ddp_scenario) +{ + DISP_MODULE_ENUM module_name = DISP_MODULE_UNKNOWN; + int module_num = ddp_get_module_num_l(module_list_scenario[ddp_scenario]) - 1; + + if (module_num >= 0) + module_name = module_list_scenario[ddp_scenario][module_num]; + + DISPDBG("ddp_get_dst_module, scneario=%s, dst_module=%s\n", + ddp_get_scenario_name(ddp_scenario), ddp_get_module_name(module_name)); + + return module_name; +} + +int *ddp_get_scenario_list(DDP_SCENARIO_ENUM ddp_scenario) +{ + return module_list_scenario[ddp_scenario]; +} + +int ddp_is_module_in_scenario(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM module) +{ + int i = 0; + + for (i = 0; i < DDP_ENING_NUM; i++) { + if (module_list_scenario[ddp_scenario][i] == module) + return 1; + + } + return 0; +} + +int ddp_insert_module(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM place, + DISP_MODULE_ENUM module) +{ + int i = DDP_ENING_NUM - 1; + int idx = ddp_find_module_index(ddp_scenario, place); + + if (idx < 0) { + DISPERR("error: ddp_insert_module , place=%s is not in scenario %s!\n", + ddp_get_module_name(place), ddp_get_scenario_name(ddp_scenario)); + return -1; + } + + for (i = 0; i < DDP_ENING_NUM; i++) { + if (module_list_scenario[ddp_scenario][i] == module) { + DISPERR("error: ddp_insert_module , module=%s is already in scenario %s!\n", + ddp_get_module_name(module), ddp_get_scenario_name(ddp_scenario)); + return -1; + } + } + + /* should have empty room for insert */ + ASSERT(module_list_scenario[ddp_scenario][DDP_ENING_NUM - 1] == -1); + + for (i = DDP_ENING_NUM - 2; i >= idx; i--) + module_list_scenario[ddp_scenario][i + 1] = module_list_scenario[ddp_scenario][i]; + module_list_scenario[ddp_scenario][idx] = module; + + { + int *modules = ddp_get_scenario_list(ddp_scenario); + int module_num = ddp_get_module_num(ddp_scenario); + + DISPMSG("after insert module, module list is:\n"); + for (i = 0; i < module_num; i++) + DISPMSG("%s-", ddp_get_module_name(modules[i])); + } + + return 0; +} + +int ddp_remove_module(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM module) +{ + int i = 0; + int idx = ddp_find_module_index(ddp_scenario, module); + + if (idx < 0) { + DISPERR("ddp_remove_module, can not find module %s in scenario %s\n", + ddp_get_module_name(module), ddp_get_scenario_name(ddp_scenario)); + return -1; + } + + for (i = idx; i < DDP_ENING_NUM - 1; i++) + module_list_scenario[ddp_scenario][i] = module_list_scenario[ddp_scenario][i + 1]; + module_list_scenario[ddp_scenario][DDP_ENING_NUM - 1] = -1; + + { + int *modules = ddp_get_scenario_list(ddp_scenario); + int module_num = ddp_get_module_num(ddp_scenario); + + DISPMSG("after remove module, module list is:\n"); + for (i = 0; i < module_num; i++) + DISPMSG("%s-", ddp_get_module_name(modules[i])); + } + return 0; +} + +void ddp_connect_path(DDP_SCENARIO_ENUM scenario, void *handle) +{ + DISPDBG("path connect on scenario %s\n", ddp_get_scenario_name(scenario)); + if (scenario == DDP_SCENARIO_PRIMARY_ALL) { + ddp_connect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP], handle); + ddp_connect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_OVL_MEMOUT], handle); + } else if (scenario == DDP_SCENARIO_SUB_ALL) { + ddp_connect_path_l(module_list_scenario[DDP_SCENARIO_SUB_DISP], handle); + ddp_connect_path_l(module_list_scenario[DDP_SCENARIO_SUB_OVL_MEMOUT], handle); + } else if (scenario == DDP_SCENARIO_DITHER_1TO2) { + ddp_connect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP], handle); + ddp_connect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DITHER_MEMOUT], handle); + } else if (scenario == DDP_SCENARIO_UFOE_1TO2) { + ddp_connect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP], handle); + ddp_connect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_UFOE_MEMOUT], handle); + } else { + ddp_connect_path_l(module_list_scenario[scenario], handle); + } +} + +void ddp_disconnect_path(DDP_SCENARIO_ENUM scenario, void *handle) +{ + DISPDBG("path disconnect on scenario %s\n", ddp_get_scenario_name(scenario)); + + if (scenario == DDP_SCENARIO_PRIMARY_ALL) { + ddp_disconnect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP], handle); + ddp_disconnect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_OVL_MEMOUT], handle); + } else if (scenario == DDP_SCENARIO_SUB_ALL) { + ddp_disconnect_path_l(module_list_scenario[DDP_SCENARIO_SUB_DISP], handle); + ddp_disconnect_path_l(module_list_scenario[DDP_SCENARIO_SUB_OVL_MEMOUT], handle); + } else if (scenario == DDP_SCENARIO_DITHER_1TO2) { + ddp_disconnect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP], handle); + ddp_disconnect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DITHER_MEMOUT], handle); + } else if (scenario == DDP_SCENARIO_UFOE_1TO2) { + ddp_disconnect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP], handle); + ddp_disconnect_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_UFOE_MEMOUT], handle); + } else { + ddp_disconnect_path_l(module_list_scenario[scenario], handle); + } +} + +void ddp_check_path(DDP_SCENARIO_ENUM scenario) +{ + DISPDBG("path check path on scenario %s\n", ddp_get_scenario_name(scenario)); + + if (scenario == DDP_SCENARIO_PRIMARY_ALL) { + ddp_check_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP]); + ddp_check_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_OVL_MEMOUT]); + } else if (scenario == DDP_SCENARIO_SUB_ALL) { + ddp_check_path_l(module_list_scenario[DDP_SCENARIO_SUB_DISP]); + ddp_check_path_l(module_list_scenario[DDP_SCENARIO_SUB_OVL_MEMOUT]); + } else if (scenario == DDP_SCENARIO_DITHER_1TO2) { + ddp_check_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP]); + ddp_check_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DITHER_MEMOUT]); + } else if (scenario == DDP_SCENARIO_UFOE_1TO2) { + ddp_check_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_DISP]); + ddp_check_path_l(module_list_scenario[DDP_SCENARIO_PRIMARY_UFOE_MEMOUT]); + } else { + ddp_check_path_l(module_list_scenario[scenario]); + } +} + +void ddp_check_mutex(int mutex_id, DDP_SCENARIO_ENUM scenario, DDP_MODE mode) +{ + DISPDBG("check mutex %d on scenario %s\n", mutex_id, ddp_get_scenario_name(scenario)); + ddp_check_mutex_l(mutex_id, module_list_scenario[scenario], mode); +} + +int ddp_mutex_set(int mutex_id, DDP_SCENARIO_ENUM scenario, DDP_MODE mode, void *handle) +{ + if (scenario < DDP_SCENARIO_MAX) + return ddp_mutex_set_l(mutex_id, module_list_scenario[scenario], mode, handle); + DISPERR("Invalid scenario %d when setting mutex\n", scenario); + return -1; +} + +int ddp_mutex_Interrupt_enable(int mutex_id, void *handle) +{ + + DISPDBG("mutex %d interrupt enable\n", mutex_id); + DISP_REG_MASK(handle, DISP_REG_CONFIG_MUTEX_INTEN, 0x1 << mutex_id, 0x1 << mutex_id); + DISP_REG_MASK(handle, DISP_REG_CONFIG_MUTEX_INTEN, 1 << (mutex_id + DISP_MUTEX_TOTAL), + 0x1 << (mutex_id + DISP_MUTEX_TOTAL)); + return 0; +} + +int ddp_mutex_Interrupt_disable(int mutex_id, void *handle) +{ + DISPDBG("mutex %d interrupt disenable\n", mutex_id); + DISP_REG_MASK(handle, DISP_REG_CONFIG_MUTEX_INTEN, 0, 0x1 << mutex_id); + DISP_REG_MASK(handle, DISP_REG_CONFIG_MUTEX_INTEN, 0, 0x1 << (mutex_id + DISP_MUTEX_TOTAL)); + return 0; +} + +int ddp_mutex_reset(int mutex_id, void *handle) +{ + DISPDBG("mutex %d reset\n", mutex_id); + DISP_REG_SET(handle, DISP_REG_CONFIG_MUTEX_RST(mutex_id), 1); + DISP_REG_SET(handle, DISP_REG_CONFIG_MUTEX_RST(mutex_id), 0); + + return 0; +} + +int ddp_is_moudule_in_mutex(int mutex_id, DISP_MODULE_ENUM module) +{ + int ret = 0; + uint32_t real_value = 0; + + if (mutex_id < DISP_MUTEX_DDP_FIRST || mutex_id > DISP_MUTEX_DDP_LAST) { + DISPDMP("error:check_moudule_in_mute fail:exceed mutex max (0 ~ %d)\n", + DISP_MUTEX_DDP_LAST); + return ret; + } + real_value = DISP_REG_GET(DISP_REG_CONFIG_MUTEX_MOD(mutex_id)); + if (1 == ((real_value >> module_mutex_map[module].bit) & 0x01)) + ret = 1; + + return ret; +} + + +int ddp_mutex_add_module(int mutex_id, DISP_MODULE_ENUM module, void *handle) +{ + int value = 0; + + if (module < DISP_MODULE_UNKNOWN) { + if (module_mutex_map[module].bit != -1) { + DISPDBG("module %s added to mutex %d\n", ddp_get_module_name(module), + mutex_id); + value |= (1 << module_mutex_map[module].bit); + DISP_REG_MASK(handle, DISP_REG_CONFIG_MUTEX_MOD(mutex_id), value, value); + } + } + return 0; +} + +int ddp_mutex_remove_module(int mutex_id, DISP_MODULE_ENUM module, void *handle) +{ + int value = 0; + + if (module < DISP_MODULE_UNKNOWN) { + if (module_mutex_map[module].bit != -1) { + DISPDBG("module %s added to mutex %d\n", ddp_get_module_name(module), + mutex_id); + value |= (1 << module_mutex_map[module].bit); + DISP_REG_MASK(handle, DISP_REG_CONFIG_MUTEX_MOD(mutex_id), 0, value); + } + + } + return 0; +} + +int ddp_mutex_clear(int mutex_id, void *handle) +{ + DISPDBG("mutex %d clear\n", mutex_id); + DISP_REG_SET(handle, DISP_REG_CONFIG_MUTEX_MOD(mutex_id), 0); + DISP_REG_SET(handle, DISP_REG_CONFIG_MUTEX_SOF(mutex_id), 0); + + /*reset mutex */ + ddp_mutex_reset(mutex_id, handle); + return 0; +} + +int ddp_mutex_enable(int mutex_id, DDP_SCENARIO_ENUM scenario, void *handle) +{ + return ddp_mutex_enable_l(mutex_id, handle); +} + +int ddp_mutex_disenable(int mutex_id, DDP_SCENARIO_ENUM scenario, void *handle) +{ + DISPDBG("mutex %d disable\n", mutex_id); + DISP_REG_SET(handle, DISP_REG_CONFIG_MUTEX_EN(mutex_id), 0); + return 0; +} + +int ddp_mutex_set_sof_wait(int mutex_id, cmdqRecHandle handle, int wait) +{ + if (mutex_id < DISP_MUTEX_DDP_FIRST || mutex_id > DISP_MUTEX_DDP_LAST) { + DISPERR("exceed mutex max (0 ~ %d)\n", DISP_MUTEX_DDP_LAST); + return -1; + } + + DISP_REG_SET_FIELD(handle, SOF_FLD_MUTEX0_SOF_WAIT, DISP_REG_CONFIG_MUTEX_SOF(mutex_id), wait); + return 0; +} + + +int ddp_check_engine_status(int mutexID) +{ + /* check engines' clock bit & enable bit & status bit before unlock mutex */ + /* should not needed, in comdq do? */ + int result = 0; + + return result; +} + +int ddp_path_top_clock_on(void) +{ + static int need_enable; + +#ifdef ENABLE_CLK_MGR + DISPMSG("ddp path top clock on %d\n", need_enable); +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_DISP0_SMI_COMMON, "DDP_SMI"); + enable_clock(MT_CG_DISP0_SMI_LARB0, "DDP_LARB0"); +#else + if (need_enable) { + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) + ddp_clk_prepare_enable(MM_VENCPLL); + ddp_clk_prepare_enable(DISP_MTCMOS_CLK); + ddp_clk_prepare_enable(DISP0_SMI_COMMON); + ddp_clk_prepare_enable(DISP0_SMI_LARB0); + } else { + need_enable = 1; + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) + ddp_clk_prepare_enable(MM_VENCPLL); + } +#endif + /* enable_clock(MT_CG_DISP0_MUTEX_32K , "DDP_MUTEX"); */ + DISPMSG("ddp CG:%x\n", DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0)); +#endif + return 0; +} + +int ddp_path_top_clock_off(void) +{ +#ifdef ENABLE_CLK_MGR +#ifdef CONFIG_MTK_CLKMGR + DISPMSG("ddp path top clock off\n"); + if (clk_is_force_on(MT_CG_DISP0_SMI_LARB0) || clk_is_force_on(MT_CG_DISP0_SMI_COMMON)) { + DISPMSG("clear SMI_LARB0 & SMI_COMMON forced on\n"); + clk_clr_force_on(MT_CG_DISP0_SMI_LARB0); + clk_clr_force_on(MT_CG_DISP0_SMI_COMMON); + } + /* disable_clock(MT_CG_DISP0_MUTEX_32K , "DDP_MUTEX"); */ + disable_clock(MT_CG_DISP0_SMI_LARB0, "DDP_LARB0"); + disable_clock(MT_CG_DISP0_SMI_COMMON, "DDP_SMI"); +#else + ddp_clk_disable_unprepare(DISP0_SMI_LARB0); + ddp_clk_disable_unprepare(DISP0_SMI_COMMON); + ddp_clk_disable_unprepare(DISP_MTCMOS_CLK); + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) + ddp_clk_disable_unprepare(MM_VENCPLL); + +#endif +#endif + return 0; +} + +int disp_get_dst_module(DDP_SCENARIO_ENUM scenario) +{ + return ddp_get_dst_module(scenario); +} + +int ddp_convert_ovl_input_to_rdma(RDMA_CONFIG_STRUCT *rdma_cfg, OVL_CONFIG_STRUCT *ovl_cfg, + int dst_w, int dst_h) +{ + unsigned int Bpp = ufmt_get_Bpp(ovl_cfg->fmt); + unsigned int offset; + + rdma_cfg->dst_y = ovl_cfg->dst_y; + rdma_cfg->dst_x = ovl_cfg->dst_x; + rdma_cfg->dst_h = dst_h; + rdma_cfg->dst_w = dst_w; + rdma_cfg->inputFormat = ovl_cfg->fmt; + offset = ovl_cfg->src_x * Bpp + ovl_cfg->src_y * ovl_cfg->src_pitch; + rdma_cfg->address = ovl_cfg->addr + offset; + rdma_cfg->pitch = ovl_cfg->src_pitch; + rdma_cfg->width = ovl_cfg->dst_w; + rdma_cfg->height = ovl_cfg->dst_h; + rdma_cfg->security = ovl_cfg->security; + rdma_cfg->yuv_range = ovl_cfg->yuv_range; + return 0; +} + + diff --git a/drivers/misc/mediatek/video/mt6755/ddp_path.h b/drivers/misc/mediatek/video/mt6755/ddp_path.h new file mode 100644 index 0000000000000000000000000000000000000000..e459ce53dd5820d1e27fb59a5895dbfa68b6ebf6 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_path.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DDP_PATH_H__ +#define __DDP_PATH_H__ + +#include "ddp_info.h" +#include "cmdq_record.h" + +typedef enum { + DDP_VIDEO_MODE = 0, + DDP_CMD_MODE, +} DDP_MODE; + +typedef enum { + DDP_SCENARIO_PRIMARY_DISP = 0, + DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP, + DDP_SCENARIO_PRIMARY_RDMA0_DISP, + DDP_SCENARIO_PRIMARY_BYPASS_RDMA, + DDP_SCENARIO_PRIMARY_OVL_MEMOUT, + DDP_SCENARIO_PRIMARY_DITHER_MEMOUT, + DDP_SCENARIO_PRIMARY_UFOE_MEMOUT, + DDP_SCENARIO_SUB_DISP, + DDP_SCENARIO_SUB_RDMA1_DISP, + DDP_SCENARIO_SUB_OVL_MEMOUT, + DDP_SCENARIO_PRIMARY_ALL, + DDP_SCENARIO_SUB_ALL, + DDP_SCENARIO_DITHER_1TO2, + DDP_SCENARIO_UFOE_1TO2, + DDP_SCENARIO_MAX +} DDP_SCENARIO_ENUM; + +void ddp_connect_path(DDP_SCENARIO_ENUM scenario, void *handle); +void ddp_disconnect_path(DDP_SCENARIO_ENUM scenario, void *handle); +int ddp_get_module_num(DDP_SCENARIO_ENUM scenario); + +void ddp_check_path(DDP_SCENARIO_ENUM scenario); +int ddp_mutex_set(int mutex_id, DDP_SCENARIO_ENUM scenario, DDP_MODE mode, void *handle); +int ddp_mutex_clear(int mutex_id, void *handle); +int ddp_mutex_enable(int mutex_id, DDP_SCENARIO_ENUM scenario, void *handle); +int ddp_mutex_disable(int mutex_id, DDP_SCENARIO_ENUM scenario, void *handle); +void ddp_check_mutex(int mutex_id, DDP_SCENARIO_ENUM scenario, DDP_MODE mode); +int ddp_mutex_reset(int mutex_id, void *handle); +int ddp_mutex_set_sof_wait(int mutex_id, cmdqRecHandle handle, int wait); + +int ddp_is_moudule_in_mutex(int mutex_id, DISP_MODULE_ENUM module); + +int ddp_mutex_add_module(int mutex_id, DISP_MODULE_ENUM module, void *handle); + +int ddp_mutex_remove_module(int mutex_id, DISP_MODULE_ENUM module, void *handle); + +int ddp_mutex_Interrupt_enable(int mutex_id, void *handle); + +int ddp_mutex_Interrupt_disable(int mutex_id, void *handle); + + +DISP_MODULE_ENUM ddp_get_dst_module(DDP_SCENARIO_ENUM scenario); +int ddp_set_dst_module(DDP_SCENARIO_ENUM scenario, DISP_MODULE_ENUM dst_module); + +int *ddp_get_scenario_list(DDP_SCENARIO_ENUM ddp_scenario); + +int ddp_insert_module(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM place, + DISP_MODULE_ENUM module); +int ddp_remove_module(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM module); + +int ddp_is_scenario_on_primary(DDP_SCENARIO_ENUM scenario); + +char *ddp_get_scenario_name(DDP_SCENARIO_ENUM scenario); + +int ddp_path_top_clock_off(void); +int ddp_path_top_clock_on(void); + +/* should remove */ +int ddp_insert_config_allow_rec(void *handle); +int ddp_insert_config_dirty_rec(void *handle); + +int disp_get_dst_module(DDP_SCENARIO_ENUM scenario); +int ddp_is_module_in_scenario(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM module); +char *ddp_get_mutex_sof_name(unsigned int regval); +int ddp_path_init(void); +int ddp_convert_ovl_input_to_rdma(RDMA_CONFIG_STRUCT *rdma_cfg, OVL_CONFIG_STRUCT *ovl_cfg, + int dst_w, int dst_h); +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_pwm_mux.c b/drivers/misc/mediatek/video/mt6755/ddp_pwm_mux.c new file mode 100644 index 0000000000000000000000000000000000000000..bc95a9ee5a776586678fbc18ebd9dcee709d3ebb --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_pwm_mux.c @@ -0,0 +1,263 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#include +#include +#include +#include +#include "ddp_clkmgr.h" +#include +#include +#include +#include "ddp_reg.h" + +#define PWM_MSG(fmt, arg...) pr_debug("[PWM] " fmt "\n", ##arg) +#define PWM_ERR(fmt, arg...) pr_err("[PWM] " fmt "\n", ##arg) +/* #define HARD_CODE_CONFIG */ +/***************************************************************************** + * + * variable for get clock node fromdts + * +*****************************************************************************/ +static void __iomem *disp_pmw_mux_base; + +#ifndef MUX_DISPPWM_ADDR /* disp pwm source clock select register address */ +#define MUX_DISPPWM_ADDR (disp_pmw_mux_base + 0xB0) +#endif +#ifdef HARD_CODE_CONFIG +#ifndef MUX_UPDATE_ADDR /* disp pwm source clock update register address */ +#define MUX_UPDATE_ADDR (disp_pmw_mux_base + 0x4) +#endif +#endif + +/* clock hard code access API */ +#define DRV_Reg32(addr) INREG32(addr) +#define clk_readl(addr) DRV_Reg32(addr) +#define clk_writel(addr, val) mt_reg_sync_writel(val, addr) + +/***************************************************************************** + * + * disp pwm source clock select mux api + * +*****************************************************************************/ +static eDDP_CLK_ID disp_pwm_get_clkid(unsigned int clk_req) +{ + eDDP_CLK_ID clkid = -1; + + switch (clk_req) { + case 0: + clkid = ULPOSC_D8; /* ULPOSC 26M */ + break; + case 1: + clkid = ULPOSC_D2; /* ULPOSC 104M */ + break; + case 2: + clkid = UNIVPLL2_D4; /* PLL 104M */ + break; + default: + clkid = -1; + break; + } + + return clkid; +} + +/***************************************************************************** + * + * get disp pwm source mux node + * +*****************************************************************************/ +#define DTSI_TOPCKGEN "mediatek,topckgen" +static int disp_pwm_get_muxbase(void) +{ + int ret = 0; + struct device_node *node; + + if (disp_pmw_mux_base != NULL) + return 0; + + node = of_find_compatible_node(NULL, NULL, DTSI_TOPCKGEN); + if (!node) { + PWM_ERR("DISP find TOPCKGEN node failed\n"); + return -1; + } + disp_pmw_mux_base = of_iomap(node, 0); + if (!disp_pmw_mux_base) { + PWM_ERR("DISP TOPCKGEN base failed\n"); + return -1; + } + + return ret; +} + +static unsigned int disp_pwm_get_pwmmux(void) +{ + unsigned int regsrc = 0; + + if (MUX_DISPPWM_ADDR != NULL) + regsrc = clk_readl(MUX_DISPPWM_ADDR); + else + PWM_ERR("mux addr illegal"); + + return regsrc; +} + +/***************************************************************************** + * + * disp pwm source clock select mux api + * +*****************************************************************************/ +int disp_pwm_set_pwmmux(unsigned int clk_req) +{ + unsigned int regsrc; + int ret = 0; + eDDP_CLK_ID clkid = -1; + + clkid = disp_pwm_get_clkid(clk_req); + ret = disp_pwm_get_muxbase(); + regsrc = disp_pwm_get_pwmmux(); + + if (clkid != -1) { + ddp_clk_enable(MUX_PWM); + ddp_clk_set_parent(MUX_PWM, clkid); + ddp_clk_disable(MUX_PWM); + } + + PWM_MSG("clk_req=%d clkid=%d, PWM_MUX %x->%x", + clk_req, clkid, regsrc, disp_pwm_get_pwmmux()); + + return 0; +} + +static void __iomem *disp_pmw_osc_base; + +#ifndef OSC_ULPOSC_ADDR /* rosc control register address */ +#define OSC_ULPOSC_ADDR (disp_pmw_osc_base + 0x458) +#endif + +/***************************************************************************** + * + * get disp pwm source osc + * +*****************************************************************************/ +static int get_ulposc_base(void) +{ + int ret = 0; + struct device_node *node; + + if (disp_pmw_osc_base != NULL) + return 0; + + node = of_find_compatible_node(NULL, NULL, "mediatek,sleep"); + if (!node) { + PWM_ERR("DISP find SLEEP node failed\n"); + return -1; + } + disp_pmw_osc_base = of_iomap(node, 0); + if (!disp_pmw_osc_base) { + PWM_ERR("DISP find SLEEP base failed\n"); + return -1; + } + + return ret; +} + +static int get_ulposc_status(void) +{ + unsigned int regosc; + int ret = -1; + + if (get_ulposc_base() == -1) { + PWM_ERR("get ULPOSC status fail"); + return ret; + } + + regosc = clk_readl(OSC_ULPOSC_ADDR); + if ((regosc & 0x5) != 0x5) { + PWM_MSG("ULPOSC is off (%x)", regosc); + ret = 0; + } else { + PWM_MSG("ULPOSC is on (%x)", regosc); + ret = 1; + } + + return ret; +} + +/***************************************************************************** + * + * hardcode turn on/off ROSC api + * +*****************************************************************************/ +static int ulposc_enable(eDDP_CLK_ID clkid) +{ + int ret = 0; + + ret = ddp_clk_prepare_enable(clkid); + get_ulposc_status(); + + return ret; +} + +static int ulposc_disable(eDDP_CLK_ID clkid) +{ + int ret = 0; + + ret = ddp_clk_disable_unprepare(clkid); + get_ulposc_status(); + + return ret; +} + +/***************************************************************************** + * + * disp pwm clock source power on /power off api + * +*****************************************************************************/ +int disp_pwm_clksource_enable(int clk_req) +{ + int ret = 0; + eDDP_CLK_ID clkid = -1; + + clkid = disp_pwm_get_clkid(clk_req); + + switch (clkid) { + case ULPOSC_D2: + case ULPOSC_D8: + ulposc_enable(clkid); + break; + default: + break; + } + + return ret; +} + +int disp_pwm_clksource_disable(int clk_req) +{ + int ret = 0; + eDDP_CLK_ID clkid = -1; + + clkid = disp_pwm_get_clkid(clk_req); + + switch (clkid) { + case ULPOSC_D2: + case ULPOSC_D8: + ulposc_disable(clkid); + break; + default: + break; + } + + return ret; +} + diff --git a/drivers/misc/mediatek/video/mt6755/ddp_rdma.c b/drivers/misc/mediatek/video/mt6755/ddp_rdma.c new file mode 100644 index 0000000000000000000000000000000000000000..3d275c2be0111fa371e063b0e5f40dd28b3bd817 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_rdma.c @@ -0,0 +1,1143 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#define LOG_TAG "RDMA" +#include "disp_log.h" +#include "disp_debug.h" +#include "mtkfb_debug.h" +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include "ddp_clkmgr.h" +#endif +#include +#include "ddp_info.h" +#include "ddp_reg.h" +#include "ddp_matrix_para.h" +#include "ddp_rdma.h" +#include "ddp_dump.h" +#include "lcm_drv.h" +#include "primary_display.h" +#include "m4u.h" +#include "mt_spm_reg.h" +/* #include "pcm_def.h" */ +#include "mt_spm.h" +#include "mt_smi.h" +/* #include "mmdvfs_mgr.h" */ +#include "disp_lowpower.h" + +#define MMSYS_CLK_LOW (0) +#define MMSYS_CLK_HIGH (1) +#define MMSYS_CLK_MEDIUM (2) +#define PRI_DISPLAY_MAX_HEIGHT (1920) +#define PRI_DISPLAY_MAX_WIDTH (1080) +#define EXT_DISPLAY_MAX_HEIGHT (1080) +#define EXT_DISPLAY_MAX_WIDTH (1920) + + +static unsigned int rdma_fps[RDMA_INSTANCES] = { 60, 60 }; +static golden_setting_context *rdma_golden_setting; +static unsigned int rdma_index(DISP_MODULE_ENUM module) +{ + int idx = 0; + + switch (module) { + case DISP_MODULE_RDMA0: + idx = 0; + break; + case DISP_MODULE_RDMA1: + idx = 1; + break; + default: + DISPERR("invalid rdma module=%d\n", module); /* invalid module */ + ASSERT(0); + } + return idx; +} + +static inline unsigned long rdma_to_cmdq_engine(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_RDMA0: + return CMDQ_ENG_DISP_RDMA0; + case DISP_MODULE_RDMA1: + return CMDQ_ENG_DISP_RDMA1; + default: + DISPERR("invalid rdma module=%d\n", module); + BUG(); + } + return 0; +} + +static inline unsigned long rdma_to_cmdq_event_nonsec_end(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_RDMA0: + return CMDQ_SYNC_DISP_RDMA0_2NONSEC_END; + case DISP_MODULE_RDMA1: + return CMDQ_SYNC_DISP_RDMA1_2NONSEC_END; + default: + DISPERR("invalid rdma module=%d\n", module); + BUG(); + } + + return 0; +} + +int rdma_enable_irq(DISP_MODULE_ENUM module, void *handle, DDP_IRQ_LEVEL irq_level) +{ + unsigned int idx = rdma_index(module); + + ASSERT(idx <= RDMA_INSTANCES); + switch (irq_level) { + case DDP_IRQ_LEVEL_ALL: + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x1E); + break; + case DDP_IRQ_LEVEL_ERROR: + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x18); + break; + case DDP_IRQ_LEVEL_NONE: + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x0); + break; + default: + break; + } + + return 0; +} + +int rdma_start(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int idx = rdma_index(module); + unsigned int regval; + + ASSERT(idx <= RDMA_INSTANCES); + regval = REG_FLD_VAL(INT_STATUS_FLD_REG_UPDATE_INT_FLAG, 0) | + REG_FLD_VAL(INT_STATUS_FLD_FRAME_START_INT_FLAG, 1) | + REG_FLD_VAL(INT_STATUS_FLD_FRAME_END_INT_FLAG, 1) | + REG_FLD_VAL(INT_STATUS_FLD_EOF_ABNORMAL_INT_FLAG, 1) | + REG_FLD_VAL(INT_STATUS_FLD_FIFO_UNDERFLOW_INT_FLAG, 1) | + REG_FLD_VAL(INT_STATUS_FLD_TARGET_LINE_INT_FLAG, 0) | + REG_FLD_VAL(INT_STATUS_FLD_FIFO_EMPTY_INT_FLAG, 0); + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, regval); + DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_ENGINE_EN, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 1); + + return 0; +} + +int rdma_stop(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int idx = rdma_index(module); + + ASSERT(idx <= RDMA_INSTANCES); + DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_ENGINE_EN, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 0); + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0); + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_STATUS, 0); + return 0; +} + +int rdma_reset(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int delay_cnt = 0; + int ret = 0; + unsigned int idx = rdma_index(module); + + ASSERT(idx <= RDMA_INSTANCES); + + DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_SOFT_RESET, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 1); + while ((DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON) & 0x700) == + 0x100) { + delay_cnt++; + udelay(10); + if (delay_cnt > 10000) { + ret = -1; + DISPERR("rdma%d_reset timeout, stage 1! DISP_REG_RDMA_GLOBAL_CON=0x%x\n", + idx, + DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + + DISP_REG_RDMA_GLOBAL_CON)); + break; + } + } + DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_SOFT_RESET, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 0); + delay_cnt = 0; + while ((DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON) & 0x700) != + 0x100) { + delay_cnt++; + udelay(10); + if (delay_cnt > 10000) { + ret = -1; + DISPERR("rdma%d_reset timeout, stage 2! DISP_REG_RDMA_GLOBAL_CON=0x%x\n", + idx, + DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + + DISP_REG_RDMA_GLOBAL_CON)); + break; + } + } + return ret; +} +#if 0 +/* set ultra registers */ +void rdma_set_ultra(unsigned int idx, unsigned int width, unsigned int height, unsigned int bpp, + unsigned int frame_rate, void *handle) +{ + /* constant */ + static const unsigned int blank_overhead = 115; /* it is 1.15, need to divide 100 later */ + static const unsigned int rdma_fifo_width = 16; /* in unit of byte */ + static const unsigned int ultra_low_time = 6; /* in unit of us */ + static const unsigned int pre_ultra_low_time = 8; /* in unit of us */ + static const unsigned int pre_ultra_high_time = 9; /* in unit of us */ + static const unsigned int fifo_size = 512; + static const unsigned int fifo_valid_line_ratio = 125; /* valid size 1/8 line; */ + static const unsigned int fifo_min_size = 32; + /* working variables */ + unsigned int consume_levels_per_sec; + unsigned int ultra_low_level; + unsigned int pre_ultra_low_level; + unsigned int pre_ultra_high_level; + unsigned int ultra_high_ofs; + unsigned int pre_ultra_low_ofs; + unsigned int pre_ultra_high_ofs; + unsigned int fifo_valid_size = 16; + + /* compute fifo valid size */ + + fifo_valid_size = (width * bpp * fifo_valid_line_ratio) / (rdma_fifo_width * 1000); + fifo_valid_size = fifo_valid_size > fifo_min_size ? fifo_valid_size : fifo_min_size; + /* change calculation order to prevent overflow of unsigned int */ + consume_levels_per_sec = (width * height * frame_rate * bpp / rdma_fifo_width / 100) * blank_overhead; + + /* /1000000 for ultra_low_time in unit of us */ + ultra_low_level = (unsigned int)(ultra_low_time * consume_levels_per_sec / 1000000); + pre_ultra_low_level = (unsigned int)(pre_ultra_low_time * consume_levels_per_sec / 1000000); + pre_ultra_high_level = + (unsigned int)(pre_ultra_high_time * consume_levels_per_sec / 1000000); + + pre_ultra_low_ofs = pre_ultra_low_level - ultra_low_level; + ultra_high_ofs = 1; + pre_ultra_high_ofs = pre_ultra_high_level - pre_ultra_low_level; + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0, + ultra_low_level | (pre_ultra_low_ofs << 8) | (ultra_high_ofs << 16) | + (pre_ultra_high_ofs << 24)); + + DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_OUTPUT_VALID_FIFO_THRESHOLD, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, fifo_valid_size); + + if (idx == 1) { + DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_FIFO_PSEUDO_SIZE, + DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, 256); + } + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_1, 0x60); + DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_FIFO_UNDERFLOW_EN, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, 1); + + DISPDBG("FIFO_VALID_Size = 0x%03x = %d\n", fifo_valid_size, fifo_valid_size); + DISPDBG("ultra_low_level = 0x%03x = %d\n", ultra_low_level, ultra_low_level); + DISPDBG("pre_ultra_low_level = 0x%03x = %d\n", pre_ultra_low_level, pre_ultra_low_level); + DISPDBG("pre_ultra_high_level = 0x%03x = %d\n", pre_ultra_high_level, pre_ultra_high_level); + DISPDBG("ultra_high_ofs = 0x%03x = %d\n", ultra_high_ofs, ultra_high_ofs); + DISPDBG("pre_ultra_low_ofs = 0x%03x = %d\n", pre_ultra_low_ofs, pre_ultra_low_ofs); + DISPDBG("pre_ultra_high_ofs = 0x%03x = %d\n", pre_ultra_high_ofs, pre_ultra_high_ofs); +} +#endif +/* set ultra registers */ +void rdma_set_ultra_l(unsigned int idx, unsigned int bpp, void *handle, golden_setting_context *p_golden_setting) +{ + + /* rdma golden setting variables */ + unsigned int mmsysclk = 286; + unsigned int is_wrot_sram = 0; + unsigned int fifo_mode = 1; + + unsigned int ultra_low_us = 4; + unsigned int ultra_high_us = 6; + unsigned int preultra_low_us = ultra_high_us; + unsigned int preultra_high_us = 7; + + unsigned long long fill_rate = 0; + unsigned long long consume_rate = 0; + + unsigned int fifo_valid_size = 512; + + /* working variables */ + unsigned int ultra_low; + unsigned int preultra_low; + unsigned int preultra_high; + unsigned int ultra_high; + + unsigned int issue_req_threshold; + unsigned int output_valid_fifo_threshold; + + unsigned int sodi_threshold_high; + unsigned int sodi_threshold_low; + unsigned int dvfs_threshold_high; + unsigned int dvfs_threshold_low; + + golden_setting_context temp_golden_setting; + unsigned int frame_rate; + long long temp; + long long temp_for_div; + + if (p_golden_setting == NULL) { + DISPDMP("[disp_lowpower]p_golden_setting is NULL\n"); + + /* default setting */ + temp_golden_setting.fps = 60; + temp_golden_setting.is_dc = 0; + temp_golden_setting.is_display_idle = 0; + temp_golden_setting.is_wrot_sram = 0; + temp_golden_setting.mmsys_clk = MMSYS_CLK_MEDIUM;/* 286: defalut ; 182: low ; 364: high */ + + /* primary_display */ + temp_golden_setting.dst_width = 1080; + temp_golden_setting.dst_height = 1920; + temp_golden_setting.rdma_width = 1080; + temp_golden_setting.rdma_height = 1920; + temp_golden_setting.hrt_magicnum = 2; + + /* set hrtnum max */ + temp_golden_setting.hrt_num = temp_golden_setting.hrt_magicnum + 1; + + /* fifo mode : 0/1/2 */ + if (temp_golden_setting.is_display_idle) + temp_golden_setting.fifo_mode = 0; + else if (temp_golden_setting.hrt_num > temp_golden_setting.hrt_magicnum) + temp_golden_setting.fifo_mode = 2; + else + temp_golden_setting.fifo_mode = 1; + + /* ext_display */ + temp_golden_setting.ext_dst_width = temp_golden_setting.dst_width; + temp_golden_setting.ext_dst_height = temp_golden_setting.dst_height; + temp_golden_setting.ext_hrt_magicnum = temp_golden_setting.hrt_magicnum; + temp_golden_setting.ext_hrt_num = temp_golden_setting.hrt_num; + + rdma_golden_setting = &temp_golden_setting; + } else + rdma_golden_setting = p_golden_setting; + + if (0 == idx) { + if (rdma_golden_setting->dst_height > PRI_DISPLAY_MAX_HEIGHT) + DISPERR("Pri dst_height = %u beyond support\n", rdma_golden_setting->dst_height); + + if (rdma_golden_setting->dst_width > PRI_DISPLAY_MAX_WIDTH) + DISPERR("Pri dst_width = %u beyond support\n", rdma_golden_setting->dst_width); + } else if (1 == idx) { + /*usually, width is bigger than height in ext_display*/ + if (rdma_golden_setting->ext_dst_height < rdma_golden_setting->ext_dst_width) { + if (rdma_golden_setting->ext_dst_height > EXT_DISPLAY_MAX_HEIGHT) + DISPERR("Ext dst_height=%u beyond support\n", rdma_golden_setting->ext_dst_height); + + if (rdma_golden_setting->ext_dst_width > EXT_DISPLAY_MAX_WIDTH) + DISPERR("Ext dst_width = %u beyond support\n", rdma_golden_setting->ext_dst_height); + } else { + if (rdma_golden_setting->ext_dst_height > EXT_DISPLAY_MAX_WIDTH) + DISPERR("Ext dst_height=%u beyond support\n", rdma_golden_setting->ext_dst_height); + + if (rdma_golden_setting->ext_dst_width > EXT_DISPLAY_MAX_HEIGHT) + DISPERR("Ext st_width = %u beyond support\n", rdma_golden_setting->ext_dst_height); + } + } + + frame_rate = rdma_golden_setting->fps; + if (idx == 1) { + /* hardcode bpp & frame_rate for rdma1 */ + bpp = 24; + frame_rate = 60; + } + + /* get fifo parameters */ + switch (rdma_golden_setting->mmsys_clk) { + case MMSYS_CLK_LOW: + mmsysclk = 182; + break; + case MMSYS_CLK_MEDIUM: + mmsysclk = 286; + break; + case MMSYS_CLK_HIGH: + mmsysclk = 364; + break; + } + + is_wrot_sram = rdma_golden_setting->is_wrot_sram; + fifo_mode = rdma_golden_setting->fifo_mode; + + if (idx == 0) { + if (fifo_mode == 0) { +#if 0 + ultra_low_us = 1; + ultra_high_us = 3; + preultra_low_us = ultra_high_us; + preultra_high_us = 4; +#else + ultra_low_us = 4; + ultra_high_us = 6; + preultra_low_us = ultra_high_us; + preultra_high_us = 7; +#endif + } else if (fifo_mode == 1) { + ultra_low_us = 4; + ultra_high_us = 6; + preultra_low_us = ultra_high_us; + preultra_high_us = 7; + } else { + ultra_low_us = 8; + ultra_high_us = 12; + preultra_low_us = ultra_high_us; + preultra_high_us = 15; + } + } else { + if (rdma_golden_setting->ext_dst_width == 1920 && rdma_golden_setting->ext_dst_height == 1080) { + ultra_low_us = 4; + ultra_high_us = 6; + preultra_low_us = ultra_high_us; + preultra_high_us = 7; + } else if ((rdma_golden_setting->ext_dst_width == 1280 && rdma_golden_setting->ext_dst_height == 720) + || (rdma_golden_setting->ext_dst_width == 720 && rdma_golden_setting->ext_dst_height == 480)) { + if (rdma_golden_setting->ext_hrt_num > rdma_golden_setting->hrt_magicnum) { + ultra_low_us = 8; + ultra_high_us = 12; + preultra_low_us = ultra_high_us; + preultra_high_us = 15; + } else { + ultra_low_us = 4; + ultra_high_us = 6; + preultra_low_us = ultra_high_us; + preultra_high_us = 7; + } + } else { + ultra_low_us = 8; + ultra_high_us = 12; + preultra_low_us = ultra_high_us; + preultra_high_us = 15; + } + + + } + + if (rdma_golden_setting->is_dc) + fill_rate = 960*mmsysclk; /* FIFO depth / us */ + else + fill_rate = 960*mmsysclk*3/16; /* FIFO depth / us */ + + if (idx == 0) { + consume_rate = (unsigned long long)rdma_golden_setting->dst_width* + rdma_golden_setting->dst_height*frame_rate*bpp; + do_div(consume_rate, 8*1000); + } else { + consume_rate = rdma_golden_setting->ext_dst_width + *rdma_golden_setting->ext_dst_height*frame_rate*bpp; + do_div(consume_rate, 8*1000); + } + consume_rate = 1200*consume_rate; + do_div(consume_rate, 16*1000); + + preultra_low = preultra_low_us * consume_rate; + if (preultra_low%1000) + preultra_low = preultra_low / 1000 + 1; + else + preultra_low = preultra_low / 1000; + + + preultra_high = preultra_high_us * consume_rate; + if (preultra_high%1000) + preultra_high = preultra_high / 1000 + 1; + else + preultra_high = preultra_high / 1000; + + + ultra_low = ultra_low_us * consume_rate; + if (ultra_low%1000) + ultra_low = ultra_low / 1000 + 1; + else + ultra_low = ultra_low / 1000; + + ultra_high = preultra_low; + if (idx == 0) { + /* only rdma0 can share sram */ + if (is_wrot_sram) + fifo_valid_size = 2048; + else + fifo_valid_size = 512; + } else + fifo_valid_size = 256; + + + issue_req_threshold = (fifo_valid_size - preultra_low) < 255 ? (fifo_valid_size - preultra_low) : 255; + temp = rdma_golden_setting->rdma_width * rdma_golden_setting->rdma_height * bpp; + do_div(temp, 16*8); + temp--; + + output_valid_fifo_threshold = preultra_low < temp ? preultra_low : temp; + + temp_for_div = 1200 * (fill_rate - consume_rate); + do_div(temp_for_div, 1000000); + temp = fifo_valid_size - temp_for_div; + if (temp < 0) + sodi_threshold_high = preultra_high; + else + sodi_threshold_high = preultra_high > temp ? preultra_high : temp; + + sodi_threshold_low = (ultra_low_us*10 + 4) * consume_rate; + sodi_threshold_low = sodi_threshold_low / 10; + + if (sodi_threshold_low % 1000) + sodi_threshold_low = sodi_threshold_low/1000 + 1; + else + sodi_threshold_low = sodi_threshold_low/1000; + + + dvfs_threshold_low = preultra_low; + dvfs_threshold_high = preultra_low+1; + + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0, + preultra_low | (preultra_high << 16)); + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_1, + ultra_low | (ultra_high << 16)); + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_2, + issue_req_threshold); + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, + output_valid_fifo_threshold | (fifo_valid_size << 16)); + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_THRESHOLD_FOR_SODI, + sodi_threshold_low | (sodi_threshold_high << 16)); + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_THRESHOLD_FOR_DVFS, + dvfs_threshold_low | (dvfs_threshold_high << 16)); + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SRAM_SEL, + is_wrot_sram); + + DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_FIFO_UNDERFLOW_EN, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, 1); +/* + if (idx == 0) + rdma_dump_golden_setting_context(DISP_MODULE_RDMA0); + else + rdma_dump_golden_setting_context(DISP_MODULE_RDMA1); +*/ + if (rdma_golden_setting->dst_width == 0 || rdma_golden_setting->dst_height == 0 + || bpp == 0 || frame_rate == 0) { + DISPDMP("==RDMA Golden Setting Value=============\n"); + + DISPDMP("width = %d\n", rdma_golden_setting->dst_width); + DISPDMP("height = %d\n", rdma_golden_setting->dst_height); + DISPDMP("bpp = %d\n", bpp); + DISPDMP("frame_rate = %d\n", frame_rate); + + DISPDMP("fill_rate = %lld\n", fill_rate); + DISPDMP("consume_rate = %lld\n", consume_rate); + DISPDMP("ultra_low_us = %d\n", ultra_low_us); + DISPDMP("ultra_high_us = %d\n", ultra_high_us); + DISPDMP("preultra_high_us= %d\n", preultra_high_us); + + DISPDMP("preultra_low = %d\n", preultra_low); + DISPDMP("preultra_high = %d\n", preultra_high); + DISPDMP("ultra_low = %d\n", ultra_low); + DISPDMP("issue_req_threshold = %d\n", issue_req_threshold); + DISPDMP("output_valid_fifo_threshold = %d\n", output_valid_fifo_threshold); + DISPDMP("sodi_threshold_low = %d\n", sodi_threshold_low); + DISPDMP("sodi_threshold_high = %d\n", sodi_threshold_high); + DISPDMP("dvfs_threshold_low = %d\n", dvfs_threshold_low); + DISPDMP("dvfs_threshold_high = %d\n", dvfs_threshold_high); + } + +} + +static int rdma_config(DISP_MODULE_ENUM module, + enum RDMA_MODE mode, + unsigned long address, + enum UNIFIED_COLOR_FMT inFormat, + unsigned pitch, + unsigned width, + unsigned height, + unsigned ufoe_enable, + DISP_BUFFER_TYPE sec, + unsigned int yuv_range, struct rdma_bg_ctrl_t *bg_ctrl, void *handle, + golden_setting_context *p_golden_setting, unsigned int bpp) +{ + + unsigned int output_is_yuv = 0; + unsigned int input_is_yuv = !UFMT_GET_RGB(inFormat); + unsigned int input_swap = UFMT_GET_BYTESWAP(inFormat); + unsigned int input_format_reg = UFMT_GET_FORMAT(inFormat); + unsigned int idx = rdma_index(module); + unsigned int color_matrix; + unsigned int regval; + + DISPDBG("RDMAConfig idx %d, mode %d, address 0x%lx, inputformat %s, pitch %u, width %u, height %u,sec%d\n", + idx, mode, address, unified_color_fmt_name(inFormat), pitch, width, height, sec); + ASSERT(idx <= RDMA_INSTANCES); + if ((width > RDMA_MAX_WIDTH) || (height > RDMA_MAX_HEIGHT)) + DISPERR("RDMA input overflow, w=%d, h=%d, max_w=%d, max_h=%d\n", width, height, + RDMA_MAX_WIDTH, RDMA_MAX_HEIGHT); + + if (input_is_yuv == 1 && output_is_yuv == 0) { + switch (yuv_range) { + case 0: + color_matrix = 4; + break; /* BT601_full */ + case 1: + color_matrix = 6; + break; /* BT601 */ + case 2: + color_matrix = 7; + break; /* BT709 */ + default: + DISPERR("%s,un-recognized yuv_range=%d!\n", __func__, yuv_range); + color_matrix = 4; + } + + DISP_REG_SET_FIELD(handle, SIZE_CON_0_FLD_MATRIX_ENABLE, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, 1); + DISP_REG_SET_FIELD(handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, + color_matrix); + } else if (input_is_yuv == 0 && output_is_yuv == 1) { + color_matrix = 0x2; /* 0x0010, RGB_TO_BT601 */ + DISP_REG_SET_FIELD(handle, SIZE_CON_0_FLD_MATRIX_ENABLE, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, 1); + DISP_REG_SET_FIELD(handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, + color_matrix); + } else { + DISP_REG_SET_FIELD(handle, SIZE_CON_0_FLD_MATRIX_ENABLE, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, 0); + DISP_REG_SET_FIELD(handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, 0); + } + + DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_MODE_SEL, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, mode); + /* FORMAT & SWAP only works when RDMA memory mode, set both to 0 when RDMA direct link mode. */ + DISP_REG_SET_FIELD(handle, MEM_CON_FLD_MEM_MODE_INPUT_FORMAT, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_CON, + ((mode == RDMA_MODE_DIRECT_LINK) ? 0 : input_format_reg & 0xf)); + DISP_REG_SET_FIELD(handle, MEM_CON_FLD_MEM_MODE_INPUT_SWAP, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_CON, + ((mode == RDMA_MODE_DIRECT_LINK) ? 0 : input_swap)); + + if (sec != DISP_SECURE_BUFFER) { + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_START_ADDR, + address); + } else { + int m4u_port; + unsigned int size = pitch * height; + + m4u_port = idx == 0 ? M4U_PORT_DISP_RDMA0 : M4U_PORT_DISP_RDMA1; + /* for sec layer, addr variable stores sec handle */ + /* we need to pass this handle and offset to cmdq driver */ + /* cmdq sec driver will help to convert handle to correct address */ + cmdqRecWriteSecure(handle, + disp_addr_convert(idx * DISP_RDMA_INDEX_OFFSET + + DISP_REG_RDMA_MEM_START_ADDR), + CMDQ_SAM_H_2_MVA, address, 0, size, m4u_port); + } + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_SRC_PITCH, pitch); + /* DISP_REG_SET(handle,idx*DISP_RDMA_INDEX_OFFSET+ DISP_REG_RDMA_INT_ENABLE, 0x3F); */ + DISP_REG_SET_FIELD(handle, SIZE_CON_0_FLD_OUTPUT_FRAME_WIDTH, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, width); + DISP_REG_SET_FIELD(handle, SIZE_CON_1_FLD_OUTPUT_FRAME_HEIGHT, + idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_1, height); + + /* rdma bg control */ + regval = REG_FLD_VAL(RDMA_BG_CON_0_LEFT, bg_ctrl->left); + regval |= REG_FLD_VAL(RDMA_BG_CON_0_RIGHT, bg_ctrl->right); + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_BG_CON_0, regval); + + regval = REG_FLD_VAL(RDMA_BG_CON_1_TOP, bg_ctrl->top); + regval |= REG_FLD_VAL(RDMA_BG_CON_1_BOTTOM, bg_ctrl->bottom); + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_BG_CON_1, regval); + + set_rdma_width_height(width, height); + rdma_set_ultra_l(idx, bpp, handle, p_golden_setting); + + return 0; +} + +void rdma_set_target_line(DISP_MODULE_ENUM module, unsigned int line, void *handle) +{ + unsigned int idx = rdma_index(module); + + DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_TARGET_LINE, line); +} + +static int rdma_clock_on(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int idx; + + idx = rdma_index(module); + /* do not set CG */ +/* +#ifdef ENABLE_CLK_MGR +#ifdef CONFIG_MTK_CLKMGR + if (idx == 0) + enable_clock(MT_CG_DISP0_DISP_RDMA0, "RDMA0"); + else + enable_clock(MT_CG_DISP0_DISP_RDMA1, "RDMA1"); +#else + if (idx == 0) + ddp_clk_enable(DISP0_DISP_RDMA0); + else + ddp_clk_enable(DISP0_DISP_RDMA1); +#endif +#endif +*/ + DISPDBG("rdma_%d_clock_on CG 0x%x\n", idx, DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0)); + return 0; +} + +static int rdma_clock_off(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int idx; + + idx = rdma_index(module); + /* do not set CG */ +/* +#ifdef ENABLE_CLK_MGR +#ifdef CONFIG_MTK_CLKMGR + if (idx == 0) + disable_clock(MT_CG_DISP0_DISP_RDMA0, "RDMA0"); + else + disable_clock(MT_CG_DISP0_DISP_RDMA1, "RDMA1"); +#else + if (idx == 0) + ddp_clk_disable(DISP0_DISP_RDMA0); + else + ddp_clk_disable(DISP0_DISP_RDMA1); + +#endif +#endif +*/ + DISPDBG("rdma_%d_clock_off CG 0x%x\n", idx, DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0)); + return 0; +} + +static int rdma_init(DISP_MODULE_ENUM module, void *handle) +{ + return rdma_clock_on(module, handle); +} + +static int rdma_deinit(DISP_MODULE_ENUM module, void *handle) +{ + return rdma_clock_off(module, handle); +} + +void rdma_dump_golden_setting_context(DISP_MODULE_ENUM module) +{ + if (rdma_golden_setting) { + DISPDMP("==RDMA Golden Setting Context=============\n"); + DISPDMP("fifo_mode = %d\n", rdma_golden_setting->fifo_mode); + DISPDMP("hrt_num = %d\n", rdma_golden_setting->hrt_num); + DISPDMP("is_display_idle = %d\n", rdma_golden_setting->is_display_idle); + DISPDMP("is_wrot_sram = %d\n", rdma_golden_setting->is_wrot_sram); + DISPDMP("is_dc = %d\n", rdma_golden_setting->is_dc); + DISPDMP("mmsys_clk = %d\n", rdma_golden_setting->mmsys_clk); + DISPDMP("fps = %d\n", rdma_golden_setting->fps); + DISPDMP("is_one_layer = %d\n", rdma_golden_setting->is_one_layer); + DISPDMP("rdma_width = %d\n", rdma_golden_setting->rdma_width); + DISPDMP("rdma_height = %d\n", rdma_golden_setting->rdma_height); + } +} + +void rdma_dump_reg(DISP_MODULE_ENUM module) +{ + unsigned int idx = rdma_index(module); + + DISPDMP("== START: DISP RDMA%d REGS ==\n", idx); + DISPDMP("(0x000)R_INTEN =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_INT_ENABLE + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x004)R_INTS =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_INT_STATUS + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x010)R_CON =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_GLOBAL_CON + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x014)R_SIZE0 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x018)R_SIZE1 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x01c)R_TAR_LINE =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_TARGET_LINE + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x024)R_M_CON =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0xf00)R_M_S_ADDR =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x02c)R_M_SRC_PITCH =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_SRC_PITCH + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x030)R_M_GMC_SET0 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_GMC_SETTING_0 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x034)R_M_GMC_SET1 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_GMC_SETTING_1 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x038)R_M_SLOW_CON =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_SLOW_CON + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x03c)R_M_GMC_SET2 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_GMC_SETTING_2 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x040)R_FIFO_CON =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_FIFO_CON + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x044)R_FIFO_LOG =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_FIFO_LOG + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x078)R_PRE_ADD0 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_0 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x07c)R_PRE_ADD1 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_1 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x080)R_PRE_ADD2 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_2 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x084)R_POST_ADD0 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_POST_ADD_0 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x088)R_POST_ADD1 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_POST_ADD_1 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x08c)R_POST_ADD2 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_POST_ADD_2 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x090)R_DUMMY =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_DUMMY + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x094)R_OUT_SEL =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_DEBUG_OUT_SEL + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x094)R_M_START =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0a0)R_BG_CON_0 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_BG_CON_0 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0a4)R_BG_CON_1 =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_BG_CON_1 + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0a8)R_FOR_SODI =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_THRESHOLD_FOR_SODI + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0ac)R_FOR_DVFS =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_THRESHOLD_FOR_DVFS + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0b0)R_FOR_SRAM =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_SRAM_SEL + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0b4)DISP_RDMA_STALL_CG_CON =0x%x\n", + DISP_REG_GET(DISP_RDMA_STALL_CG_CON + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0f0)R_IN_PXL_CNT =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_IN_P_CNT + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0f4)R_IN_LINE_CNT =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_IN_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0f8)R_OUT_PXL_CNT =0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_OUT_P_CNT + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("(0x0fc)R_OUT_LINE_CNT=0x%x\n", + DISP_REG_GET(DISP_REG_RDMA_OUT_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx)); + DISPDMP("-- END: DISP RDMA%d REGS --\n", idx); +} + +void rdma_dump_analysis(DISP_MODULE_ENUM module) +{ + unsigned int idx = rdma_index(module); + unsigned int global_ctrl = + DISP_REG_GET(DISP_REG_RDMA_GLOBAL_CON + DISP_RDMA_INDEX_OFFSET * idx); + unsigned int bg0 = DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_BG_CON_0); + unsigned int bg1 = DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_BG_CON_1); + + DISPDMP("==DISP RDMA%d ANALYSIS==\n", idx); + DISPDMP("rdma%d: en=%d,memory_mode=%d,smi_busy=%d,w=%d,h=%d,pitch=%d,addr=0x%x,fmt=%s,fifo_min=%d,\n" + "in_p=%d,in_l=%d,out_p=%d,out_l=%d,bg(t%d,b%d,l%d,r%d),start=%lld ns,end=%lld ns\n", + idx, REG_FLD_VAL_GET(GLOBAL_CON_FLD_ENGINE_EN, global_ctrl), + REG_FLD_VAL_GET(GLOBAL_CON_FLD_MODE_SEL, global_ctrl), + REG_FLD_VAL_GET(GLOBAL_CON_FLD_SMI_BUSY, global_ctrl), + DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfff, + DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfffff, + DISP_REG_GET(DISP_REG_RDMA_MEM_SRC_PITCH + DISP_RDMA_INDEX_OFFSET * idx), + DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx), + unified_color_fmt_name(display_fmt_reg_to_unified_fmt + ((DISP_REG_GET + (DISP_REG_RDMA_MEM_CON + + DISP_RDMA_INDEX_OFFSET * idx) >> 4) & 0xf, + (DISP_REG_GET + (DISP_REG_RDMA_MEM_CON + + DISP_RDMA_INDEX_OFFSET * idx) >> 8) & 0x1, 0)), + DISP_REG_GET(DISP_REG_RDMA_FIFO_LOG + DISP_RDMA_INDEX_OFFSET * idx), + DISP_REG_GET(DISP_REG_RDMA_IN_P_CNT + DISP_RDMA_INDEX_OFFSET * idx), + DISP_REG_GET(DISP_REG_RDMA_IN_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx), + DISP_REG_GET(DISP_REG_RDMA_OUT_P_CNT + DISP_RDMA_INDEX_OFFSET * idx), + DISP_REG_GET(DISP_REG_RDMA_OUT_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx), + REG_FLD_VAL_GET(RDMA_BG_CON_1_TOP, bg1), + REG_FLD_VAL_GET(RDMA_BG_CON_1_BOTTOM, bg1), + REG_FLD_VAL_GET(RDMA_BG_CON_0_LEFT, bg0), + REG_FLD_VAL_GET(RDMA_BG_CON_0_RIGHT, bg0), + rdma_start_time[idx], rdma_end_time[idx] + ); + DISPDMP("irq cnt: start=%d, end=%d, underflow=%d, targetline=%d\n", + rdma_start_irq_cnt[idx], rdma_done_irq_cnt[idx], rdma_underflow_irq_cnt[idx], + rdma_targetline_irq_cnt[idx]); + + rdma_dump_golden_setting_context(module); + +} + +static int rdma_dump(DISP_MODULE_ENUM module, int level) +{ + rdma_dump_analysis(module); + rdma_dump_reg(module); + + return 0; +} + +void rdma_get_address(DISP_MODULE_ENUM module, unsigned long *addr) +{ + unsigned int idx = rdma_index(module); + *addr = DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx); + +} + +void rdma_get_info(int idx, RDMA_BASIC_STRUCT *info) +{ + RDMA_BASIC_STRUCT *p = info; + + p->addr = DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx); + p->src_w = DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfff; + p->src_h = DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfffff, + p->bpp = UFMT_GET_bpp(display_fmt_reg_to_unified_fmt((DISP_REG_GET + (DISP_REG_RDMA_MEM_CON + + DISP_RDMA_INDEX_OFFSET * + idx) >> 4) & 0xf, + (DISP_REG_GET + (DISP_REG_RDMA_MEM_CON + + DISP_RDMA_INDEX_OFFSET * + idx) >> 8) & 0x1, 0)) / 8; + + +} + +static inline enum RDMA_MODE get_rdma_mode(DISP_MODULE_ENUM module) +{ + unsigned int idx = rdma_index(module); + + return DISP_REG_GET_FIELD(GLOBAL_CON_FLD_MODE_SEL, (DISP_RDMA_INDEX_OFFSET * idx) + DISP_REG_RDMA_GLOBAL_CON); +} + +static inline enum RDMA_MODE rdma_config_mode(unsigned long address) +{ + return address ? RDMA_MODE_MEMORY : RDMA_MODE_DIRECT_LINK; +} + +static int do_rdma_config_l(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle) +{ + RDMA_CONFIG_STRUCT *r_config = &pConfig->rdma_config; + enum RDMA_MODE mode = rdma_config_mode(r_config->address); + LCM_PARAMS *lcm_param = &(pConfig->dispif_config); + unsigned int width = pConfig->dst_dirty ? pConfig->dst_w : r_config->width; + unsigned int height = pConfig->dst_dirty ? pConfig->dst_h : r_config->height; + golden_setting_context *p_golden_setting = pConfig->p_golden_setting_context; + enum UNIFIED_COLOR_FMT inFormat = r_config->inputFormat; + + if (pConfig->fps) + rdma_fps[rdma_index(module)] = pConfig->fps / 100; + + if (mode == RDMA_MODE_DIRECT_LINK && r_config->security != DISP_NORMAL_BUFFER) + DISPERR("%s: rdma directlink BUT is sec ??!!\n", __func__); + + if (mode == RDMA_MODE_DIRECT_LINK) { + pConfig->rdma_config.bg_ctrl.top = 0; + pConfig->rdma_config.bg_ctrl.bottom = 0; + pConfig->rdma_config.bg_ctrl.left = 0; + pConfig->rdma_config.bg_ctrl.right = 0; + } else if (mode == RDMA_MODE_MEMORY) { + pConfig->rdma_config.bg_ctrl.top = r_config->dst_y; + pConfig->rdma_config.bg_ctrl.bottom = r_config->dst_h - + r_config->dst_y - height; + pConfig->rdma_config.bg_ctrl.left = r_config->dst_x; + pConfig->rdma_config.bg_ctrl.right = r_config->dst_w - + r_config->dst_x - width; + } + DISPDBG("top=%d,bottom=%d,left=%d,right=%d\n", + pConfig->rdma_config.bg_ctrl.top, pConfig->rdma_config.bg_ctrl.bottom, + pConfig->rdma_config.bg_ctrl.left, pConfig->rdma_config.bg_ctrl.right); + DISPDBG("r.dst_x=%d,r.dst_y=%d,r.dst_w=%d,r.dst_h=%d,width=%d,height=%d\n", + r_config->dst_x, r_config->dst_y, r_config->dst_w, + r_config->dst_h, width, height); + /*PARGB,etc need convert ARGB,etc*/ + ufmt_disable_P(r_config->inputFormat, &inFormat); + rdma_config(module, + mode, + (mode == RDMA_MODE_DIRECT_LINK) ? 0 : r_config->address, + (mode == RDMA_MODE_DIRECT_LINK) ? UFMT_RGB888 : inFormat, + (mode == RDMA_MODE_DIRECT_LINK) ? 0 : r_config->pitch, + width, + height, + lcm_param->dsi.ufoe_enable, + r_config->security, r_config->yuv_range, &(r_config->bg_ctrl), handle, + p_golden_setting, pConfig->lcm_bpp); + + return 0; +} + +static int setup_rdma_sec(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle) +{ + static int rdma_is_sec[2]; + CMDQ_ENG_ENUM cmdq_engine; + /*CMDQ_EVENT_ENUM cmdq_event_nonsec_end;*/ + int rdma_idx = rdma_index(module); + DISP_BUFFER_TYPE security = pConfig->rdma_config.security; + enum RDMA_MODE mode = rdma_config_mode(pConfig->rdma_config.address); + + /*cmdq_engine = rdma_idx == 0 ? CMDQ_ENG_DISP_RDMA0 : CMDQ_ENG_DISP_RDMA1;*/ + cmdq_engine = rdma_to_cmdq_engine(module); + /*cmdq_event_nonsec_end = rdma_to_cmdq_event_nonsec_end(module);*/ + + if (!handle) { + DISPDBG("[SVP] bypass rdma sec setting sec=%d,handle=NULL\n", security); + return 0; + } + /* sec setting make sence only in memory mode ! */ + if (mode == RDMA_MODE_MEMORY) { + if (security == DISP_SECURE_BUFFER) { + cmdqRecSetSecure(handle, 1); + /* set engine as sec */ + cmdqRecSecureEnablePortSecurity(handle, (1LL << cmdq_engine)); + /* cmdqRecSecureEnableDAPC(handle, (1LL << cmdq_engine)); */ + + if (rdma_is_sec[rdma_idx] == 0) { + DISPMSG("[SVP] switch rdma%d to sec\n", rdma_idx); + mdelay(3); + } + rdma_is_sec[rdma_idx] = 1; + } else { + if (rdma_is_sec[rdma_idx]) { + /* rdma is in sec stat, we need to switch it to nonsec */ + cmdqRecHandle nonsec_switch_handle; + + int ret; + + ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_PRIMARY_DISABLE_SECURE_PATH, + &(nonsec_switch_handle)); + if (ret) + DISPAEE("[SVP]fail to create disable handle %s ret=%d\n", + __func__, ret); + + cmdqRecReset(nonsec_switch_handle); + _cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle); + cmdqRecSetSecure(nonsec_switch_handle, 1); + + /*ugly work around by kzhang !!. will remove when cmdq delete disable scenario. + * To avoid translation fault like ovl (see notes in ovl.c)*/ + if (get_rdma_mode(module) == RDMA_MODE_MEMORY) + do_rdma_config_l(module, pConfig, nonsec_switch_handle); + /*in fact, dapc/port_sec will be disabled by cmdq */ + cmdqRecSecureEnablePortSecurity(nonsec_switch_handle, + (1LL << cmdq_engine)); + /* cmdqRecSecureEnableDAPC(nonsec_switch_handle, (1LL << cmdq_engine)); */ + /*cmdqRecSetEventToken(nonsec_switch_handle, cmdq_event_nonsec_end);*/ + /*cmdqRecFlushAsync(nonsec_switch_handle);*/ + cmdqRecFlush(nonsec_switch_handle); + cmdqRecDestroy(nonsec_switch_handle); + /*cmdqRecWait(handle, cmdq_event_nonsec_end);*/ + DISPMSG("[SVP] switch rdma%d to nonsec done\n", rdma_idx); + } + rdma_is_sec[rdma_idx] = 0; + } + } + return 0; +} + + +static int rdma_config_l(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle) +{ + if (pConfig->dst_dirty || pConfig->rdma_dirty) { + + setup_rdma_sec(module, pConfig, handle); + + do_rdma_config_l(module, pConfig, handle); + } + return 0; +} + +void rdma_enable_color_transform(DISP_MODULE_ENUM module) +{ + unsigned int idx = rdma_index(module); + uint32_t value = DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx); + + value = value | REG_FLD_VAL((SIZE_CON_0_FLD_MATRIX_EXT_MTX_EN), 1) | + REG_FLD_VAL((SIZE_CON_0_FLD_MATRIX_ENABLE), 1); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, value); +} + +void rdma_disable_color_transform(DISP_MODULE_ENUM module) +{ + unsigned int idx = rdma_index(module); + uint32_t value = DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx); + + value = value | REG_FLD_VAL((SIZE_CON_0_FLD_MATRIX_EXT_MTX_EN), 0) | + REG_FLD_VAL((SIZE_CON_0_FLD_MATRIX_ENABLE), 0); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, value); +} + +void rdma_set_color_matrix(DISP_MODULE_ENUM module, + rdma_color_matrix *matrix, rdma_color_pre *pre, rdma_color_post *post) +{ + unsigned int idx = rdma_index(module); + + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C00, matrix->C00); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C01, matrix->C01); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C02, matrix->C02); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C10, matrix->C10); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C11, matrix->C11); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C12, matrix->C12); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C20, matrix->C20); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C21, matrix->C21); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_C22, matrix->C22); + + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_PRE_ADD_0, pre->ADD0); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_PRE_ADD_1, pre->ADD1); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_PRE_ADD_2, pre->ADD2); + + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_POST_ADD_0, post->ADD0); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_POST_ADD_1, post->ADD1); + DISP_REG_SET(NULL, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_POST_ADD_2, post->ADD2); +} + +int rdma_ioctl(DISP_MODULE_ENUM module, void *cmdq_handle, DDP_IOCTL_NAME ioctl_cmd, void *params) +{ + int ret = 0; + DDP_IOCTL_NAME ioctl = (DDP_IOCTL_NAME) ioctl_cmd; + unsigned int idx = rdma_index(module); + disp_ddp_path_config *pConfig = NULL; + golden_setting_context *p_golden_setting = NULL; + + switch (ioctl) { + case DDP_RDMA_GOLDEN_SETTING: + pConfig = (disp_ddp_path_config *)params; + p_golden_setting = pConfig->p_golden_setting_context; + rdma_set_ultra_l(idx, pConfig->lcm_bpp, cmdq_handle, p_golden_setting); + break; + default: + break; + } + + return ret; +} + +DDP_MODULE_DRIVER ddp_driver_rdma = { + .init = rdma_init, + .deinit = rdma_deinit, + .config = rdma_config_l, + .start = rdma_start, + .trigger = NULL, + .stop = rdma_stop, + .reset = rdma_reset, + .power_on = rdma_clock_on, + .power_off = rdma_clock_off, + .is_idle = NULL, + .is_busy = NULL, + .dump_info = rdma_dump, + .bypass = NULL, + .build_cmdq = NULL, + .set_lcm_utils = NULL, + .enable_irq = rdma_enable_irq, + .ioctl = rdma_ioctl, +}; diff --git a/drivers/misc/mediatek/video/mt6755/ddp_rdma.h b/drivers/misc/mediatek/video/mt6755/ddp_rdma.h new file mode 100644 index 0000000000000000000000000000000000000000..1f6c9259f4c4b25f13e870969af7d5237a42efed --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_rdma.h @@ -0,0 +1,86 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#ifndef _DDP_RDMA_API_H_ +#define _DDP_RDMA_API_H_ +#include "ddp_info.h" + +#define RDMA_INSTANCES 2 +#define RDMA_MAX_WIDTH 4095 +#define RDMA_MAX_HEIGHT 4095 + +enum RDMA_OUTPUT_FORMAT { + RDMA_OUTPUT_FORMAT_ARGB = 0, + RDMA_OUTPUT_FORMAT_YUV444 = 1, +}; + +enum RDMA_MODE { + RDMA_MODE_DIRECT_LINK = 0, + RDMA_MODE_MEMORY = 1, +}; + +typedef struct _rdma_color_matrix { + uint32_t C00; + uint32_t C01; + uint32_t C02; + uint32_t C10; + uint32_t C11; + uint32_t C12; + uint32_t C20; + uint32_t C21; + uint32_t C22; +} rdma_color_matrix; + +typedef struct _rdma_color_pre { + uint32_t ADD0; + uint32_t ADD1; + uint32_t ADD2; +} rdma_color_pre; + +typedef struct _rdma_color_post { + uint32_t ADD0; + uint32_t ADD1; + uint32_t ADD2; +} rdma_color_post; + + +/* start module */ +int rdma_start(DISP_MODULE_ENUM module, void *handle); + +/* stop module */ +int rdma_stop(DISP_MODULE_ENUM module, void *handle); + +/* reset module */ +int rdma_reset(DISP_MODULE_ENUM module, void *handle); + +void rdma_set_target_line(DISP_MODULE_ENUM module, unsigned int line, void *handle); + +void rdma_get_address(DISP_MODULE_ENUM module, unsigned long *data); +void rdma_dump_reg(DISP_MODULE_ENUM module); +void rdma_dump_analysis(DISP_MODULE_ENUM module); +void rdma_dump_golden_setting_context(DISP_MODULE_ENUM module); +void rdma_get_info(int idx, RDMA_BASIC_STRUCT *info); + +void rdma_enable_color_transform(DISP_MODULE_ENUM module); +void rdma_disable_color_transform(DISP_MODULE_ENUM module); +void rdma_set_color_matrix(DISP_MODULE_ENUM module, + rdma_color_matrix *matrix, + rdma_color_pre *pre, rdma_color_post *post); + +extern unsigned long long rdma_start_time[2]; +extern unsigned long long rdma_end_time[2]; +extern unsigned int rdma_start_irq_cnt[2]; +extern unsigned int rdma_done_irq_cnt[2]; +extern unsigned int rdma_underflow_irq_cnt[2]; +extern unsigned int rdma_targetline_irq_cnt[2]; + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/ddp_reg.h b/drivers/misc/mediatek/video/mt6755/ddp_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..0043c45880c8648871babcf34df69cdf0479f602 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_reg.h @@ -0,0 +1,2547 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _DDP_REG_H_ +#define _DDP_REG_H_ +#include +/*#include */ +/* #include */ +#include +#include "disp_recorder.h" +#include "cmdq_record.h" +#include "cmdq_core.h" +#include "ddp_hal.h" + +/* //////////////////////////////////// macro /////////////////////////////////////////// */ + +#define ENABLE_CLK_MGR + +/* field definition */ +/* ------------------------------------------------------------- */ +/* MIPITX */ +typedef struct { + unsigned RG_DSI_LDOCORE_EN:1; + unsigned RG_DSI_CKG_LDOOUT_EN:1; + unsigned RG_DSI_BCLK_SEL:2; + unsigned RG_DSI_LD_IDX_SEL:3; + unsigned rsv_7:1; + unsigned RG_DSI_PHYCLK_SEL:2; + unsigned RG_DSI_DSICLK_FREQ_SEL:1; + unsigned RG_DSI_LPTX_CLMP_EN:1; + unsigned rsv_12:20; +} MIPITX_DSI_CON_REG, *PMIPITX_DSI_CON_REG; + +typedef struct { + unsigned RG_DSI_LNTC_LDOOUT_EN:1; + unsigned RG_DSI_LNTC_LOOPBACK_EN:1; + unsigned RG_DSI_LNTC_LPTX_IPLUS1:1; + unsigned RG_DSI_LNTC_LPTX_IPLUS2:1; + unsigned RG_DSI_LNTC_LPTX_IMINUS:1; + unsigned RG_DSI_LNTC_LPCD_IPLUS:1; + unsigned RG_DSI_LNTC_LPCD_IMINUS:1; + unsigned rsv_7:1; + unsigned RG_DSI_LNTC_RT_CODE:4; + unsigned rsv_12:20; +} MIPITX_DSI_CLOCK_LANE_REG, *PMIPITX_DSI_CLOCK_LANE_REG; + +typedef struct { + unsigned RG_DSI_LNT0_LDOOUT_EN:1; + unsigned RG_DSI_LNT0_CKLANE_EN:1; + unsigned RG_DSI_LNT0_LPTX_IPLUS1:1; + unsigned RG_DSI_LNT0_LPTX_IPLUS2:1; + unsigned RG_DSI_LNT0_LPTX_IMINUS:1; + unsigned RG_DSI_LNT0_LPCD_IPLUS:1; + unsigned RG_DSI_LNT0_LPCD_IMINUS:1; + unsigned rsv_7:1; + unsigned RG_DSI_LNT0_RT_CODE:4; + unsigned rsv_11:20; +} MIPITX_DSI_DATA_LANE0_REG, *PMIPITX_DSI_DATA_LANE0_REG; + + +typedef struct { + unsigned RG_DSI_LNT1_LDOOUT_EN:1; + unsigned RG_DSI_LNT1_CKLANE_EN:1; + unsigned RG_DSI_LNT1_LPTX_IPLUS1:1; + unsigned RG_DSI_LNT1_LPTX_IPLUS2:1; + unsigned RG_DSI_LNT1_LPTX_IMINUS:1; + unsigned RG_DSI_LNT1_LPCD_IPLUS:1; + unsigned RG_DSI_LNT1_LPCD_IMINUS:1; + unsigned rsv_7:1; + unsigned RG_DSI_LNT1_RT_CODE:4; + unsigned rsv_11:20; +} MIPITX_DSI_DATA_LANE1_REG, *PMIPITX_DSI_DATA_LANE1_REG; + + +typedef struct { + unsigned RG_DSI_LNT2_LDOOUT_EN:1; + unsigned RG_DSI_LNT2_LOOPBACK_EN:1; + unsigned RG_DSI_LNT2_LPTX_IPLUS1:1; + unsigned RG_DSI_LNT2_LPTX_IPLUS2:1; + unsigned RG_DSI_LNT2_LPTX_IMINUS:1; + unsigned RG_DSI_LNT2_LPCD_IPLUS:1; + unsigned RG_DSI_LNT2_LPCD_IMINUS:1; + unsigned rsv_7:1; + unsigned RG_DSI_LNT2_RT_CODE:4; + unsigned rsv_11:20; +} MIPITX_DSI_DATA_LANE2_REG, *PMIPITX_DSI_DATA_LANE2_REG; + +typedef struct { + unsigned RG_DSI_LNT3_LDOOUT_EN:1; + unsigned RG_DSI_LNT3_LOOPBACK_EN:1; + unsigned RG_DSI_LNT3_LPTX_IPLUS1:1; + unsigned RG_DSI_LNT3_LPTX_IPLUS2:1; + unsigned RG_DSI_LNT3_LPTX_IMINUS:1; + unsigned RG_DSI_LNT3_LPCD_IPLUS:1; + unsigned RG_DSI_LNT3_LPCD_IMINUS:1; + unsigned rsv_7:1; + unsigned RG_DSI_LNT3_RT_CODE:4; + unsigned rsv_11:20; +} MIPITX_DSI_DATA_LANE3_REG, *PMIPITX_DSI_DATA_LANE3_REG; + +typedef struct { + unsigned RG_DSI_LNT_INTR_EN:1; + unsigned RG_DSI_LNT_HS_BIAS_EN:1; + unsigned RG_DSI_LNT_IMP_CAL_EN:1; + unsigned RG_DSI_LNT_TESTMODE_EN:1; + unsigned RG_DSI_LNT_IMP_CAL_CODE:4; + unsigned RG_DSI_LNT_AIO_SEL:3; + unsigned RG_DSI_PAD_TIE_LOW_EN:1; + unsigned rsv_12:1; + unsigned RG_DSI_PRESERVE:3; + unsigned rsv_16:16; +} MIPITX_DSI_TOP_CON_REG, *PMIPITX_DSI_TOP_CON_REG; + + +typedef struct { + unsigned RG_DSI_BG_CORE_EN:1; + unsigned RG_DSI_BG_CKEN:1; + unsigned RG_DSI_BG_DIV:2; + unsigned RG_DSI_BG_FAST_CHARGE:1; + unsigned RG_DSI_V12_SEL:3; + unsigned RG_DSI_V10_SEL:3; + unsigned RG_DSI_V072_SEL:3; + unsigned RG_DSI_V04_SEL:3; + unsigned RG_DSI_V032_SEL:3; + unsigned RG_DSI_V02_SEL:3; + unsigned rsv_23:1; + unsigned RG_DSI_BG_R1_TRIM:4; + unsigned RG_DSI_BG_R2_TRIM:4; +} MIPITX_DSI_BG_CON_REG, *PMIPITX_DSI_BG_CON_REG; + + +typedef struct { + unsigned RG_DSI0_MPPLL_PLL_EN:1; + unsigned RG_DSI0_MPPLL_PREDIV:2; + unsigned RG_DSI0_MPPLL_TXDIV0:2; + unsigned RG_DSI0_MPPLL_TXDIV1:2; + unsigned RG_DSI0_MPPLL_POSDIV:3; + unsigned RG_DSI0_MPPLL_MONVC_EN:1; + unsigned RG_DSI0_MPPLL_MONREF_EN:1; + unsigned RG_DSI0_MPPLL_VDO_EN:1; + unsigned rsv_13:19; +} MIPITX_DSI_PLL_CON0_REG, *PMIPITX_DSI_PLL_CON0_REG; + + +typedef struct { + unsigned RG_DSI0_MPPLL_SDM_FRA_EN:1; + unsigned RG_DSI0_MPPLL_SDM_SSC_PH_INIT:1; + unsigned RG_DSI0_MPPLL_SDM_SSC_EN:1; + unsigned rsv_3:13; + unsigned RG_DSI0_MPPLL_SDM_SSC_PRD:16; +} MIPITX_DSI_PLL_CON1_REG, *PMIPITX_DSI_PLL_CON1_REG; + +typedef struct { + unsigned RG_DSI0_MPPLL_SDM_PCW_0_7:8; + unsigned RG_DSI0_MPPLL_SDM_PCW_8_15:8; + unsigned RG_DSI0_MPPLL_SDM_PCW_16_23:8; + unsigned RG_DSI0_MPPLL_SDM_PCW_H:7; + unsigned rsv_31:1; +} MIPITX_DSI_PLL_CON2_REG, *PMIPITX_DSI_PLL_CON2_REG; + + +typedef struct { + unsigned RG_DSI0_MPPLL_SDM_SSC_DELTA1:16; + unsigned RG_DSI0_MPPLL_SDM_SSC_DELTA:16; +} MIPITX_DSI_PLL_CON3_REG, *PMIPITX_DSI_PLL_CON3_REG; + + +typedef struct { + unsigned RG_DSI0_MPPLL_SDM_PCW_CHG:1; + unsigned rsv_1:31; +} MIPITX_DSI_PLL_CHG_REG, *PMIPITX_DSI_PLL_CHG_REG; + + +typedef struct { + unsigned RG_MPPLL_TST_EN:1; + unsigned RG_MPPLL_TSTCK_EN:1; + unsigned RG_MPPLL_TSTSEL:2; + unsigned RG_MPPLL_S2QDIV:2; + unsigned RG_MPPLL_PLLOUT_EN:1; + unsigned RG_MPPLL_PRESERVE:5; + unsigned rsv_12:20; +} MIPITX_DSI_PLL_TOP_REG, *PMIPITX_DSI_PLL_TOP_REG; + + +typedef struct { + unsigned DA_DSI_MPPLL_SDM_PWR_ON:1; + unsigned DA_DSI_MPPLL_SDM_ISO_EN:1; + unsigned rsv_2:6; + unsigned AD_DSI0_MPPLL_SDM_PWR_ACK:1; + unsigned rsv_9:23; +} MIPITX_DSI_PLL_PWR_REG, *PMIPITX_DSI_PLL_PWR_REG; + + +typedef struct { + unsigned RGS_DSI_LNT_IMP_CAL_OUTPUT:1; + unsigned rsv_1:31; +} MIPITX_DSI_RGS_REG, *PMIPITX_DSI_RGS_REG; + + +typedef struct { + unsigned RG_DSI0_GPI0_EN:1; + unsigned RG_DSI0_GPI1_EN:1; + unsigned RG_DSI0_GPI2_EN:1; + unsigned RG_DSI0_GPI3_EN:1; + unsigned RG_DSI0_GPI4_EN:1; + unsigned RG_DSI0_GPI5_EN:1; + unsigned RG_DSI0_GPI6_EN:1; + unsigned RG_DSI0_GPI7_EN:1; + unsigned RG_DSI0_GPI8_EN:1; + unsigned RG_DSI0_GPI9_EN:1; + unsigned RG_DSI0_GPI_SMT_EN:1; + unsigned RG_DSI0_GPI_DRIVE_EN:1; + unsigned rsv_12:20; +} MIPITX_DSI_GPI_EN_REG, *PMIPITX_DSI_GPI_EN_REG; + +typedef struct { + unsigned RG_DSI0_GPI0_PD:1; + unsigned RG_DSI0_GPI1_PD:1; + unsigned RG_DSI0_GPI2_PD:1; + unsigned RG_DSI0_GPI3_PD:1; + unsigned RG_DSI0_GPI4_PD:1; + unsigned RG_DSI0_GPI5_PD:1; + unsigned RG_DSI0_GPI6_PD:1; + unsigned RG_DSI0_GPI7_PD:1; + unsigned RG_DSI0_GPI8_PD:1; + unsigned RG_DSI0_GPI9_PD:1; + unsigned rsv_10:6; + unsigned RG_DSI0_GPI0_PU:1; + unsigned RG_DSI0_GPI1_PU:1; + unsigned RG_DSI0_GPI2_PU:1; + unsigned RG_DSI0_GPI3_PU:1; + unsigned RG_DSI0_GPI4_PU:1; + unsigned RG_DSI0_GPI5_PU:1; + unsigned RG_DSI0_GPI6_PU:1; + unsigned RG_DSI0_GPI7_PU:1; + unsigned RG_DSI0_GPI8_PU:1; + unsigned RG_DSI0_GPI9_PU:1; + unsigned rsv_26:6; +} MIPITX_DSI_GPI_PULL_REG, *PMIPITX_DSI_GPI_PULL_REG; + + +typedef struct { + unsigned MIPI_TX_PHY0_SEL:3; + unsigned rsv_3:1; + unsigned MIPI_TX_PHY1_SEL:3; + unsigned rsv_7:1; + unsigned MIPI_TX_PHY2_SEL:3; + unsigned rsv_11:1; + unsigned MIPI_TX_PHY3_SEL:3; + unsigned rsv_15:1; + unsigned MIPI_TX_PHYC_SEL:3; + unsigned rsv_19:1; + unsigned MIPI_TX_LPRX_SEL:3; + unsigned rsv_23:9; +} MIPITX_DSI_PHY_SEL_REG, *PMIPITX_DSI_PHY_SEL_REG; + + +typedef struct { + unsigned SW_CTRL_EN:1; + unsigned rsv_1:31; +} MIPITX_DSI_SW_CTRL_REG, *PMIPITX_DSI_SW_CTRL_REG; + + +typedef struct { + unsigned SW_LNTC_LPTX_PRE_OE:1; + unsigned SW_LNTC_LPTX_OE:1; + unsigned SW_LNTC_LPTX_DP:1; + unsigned SW_LNTC_LPTX_DN:1; + unsigned SW_LNTC_HSTX_PRE_OE:1; + unsigned SW_LNTC_HSTX_OE:1; + unsigned SW_LNTC_HSTX_RDY:1; + unsigned SW_LNTC_LPRX_EN:1; + unsigned SW_LNTC_HSTX_DATA:8; + unsigned rsv_16:16; +} MIPITX_DSI_SW_CTRL_CON0_REG, *PMIPITX_DSI_SW_CTRL_CON0_REG; + + +typedef struct { + unsigned SW_LNT0_LPTX_PRE_OE:1; + unsigned SW_LNT0_LPTX_OE:1; + unsigned SW_LNT0_LPTX_DP:1; + unsigned SW_LNT0_LPTX_DN:1; + unsigned SW_LNT0_HSTX_PRE_OE:1; + unsigned SW_LNT0_HSTX_OE:1; + unsigned SW_LNT0_HSTX_RDY:1; + unsigned SW_LNT0_LPRX_EN:1; + unsigned SW_LNT1_LPTX_PRE_OE:1; + unsigned SW_LNT1_LPTX_OE:1; + unsigned SW_LNT1_LPTX_DP:1; + unsigned SW_LNT1_LPTX_DN:1; + unsigned SW_LNT1_HSTX_PRE_OE:1; + unsigned SW_LNT1_HSTX_OE:1; + unsigned SW_LNT1_HSTX_RDY:1; + unsigned SW_LNT1_LPRX_EN:1; + unsigned SW_LNT2_LPTX_PRE_OE:1; + unsigned SW_LNT2_LPTX_OE:1; + unsigned SW_LNT2_LPTX_DP:1; + unsigned SW_LNT2_LPTX_DN:1; + unsigned SW_LNT2_HSTX_PRE_OE:1; + unsigned SW_LNT2_HSTX_OE:1; + unsigned SW_LNT2_HSTX_RDY:1; + unsigned SW_LNT2_LPRX_EN:1; + unsigned SW_LNT3_LPTX_PRE_OE:1; + unsigned SW_LNT3_LPTX_OE:1; + unsigned SW_LNT3_LPTX_DP:1; + unsigned SW_LNT3_LPTX_DN:1; + unsigned SW_LNT3_HSTX_PRE_OE:1; + unsigned SW_LNT3_HSTX_OE:1; + unsigned SW_LNT3_HSTX_RDY:1; + unsigned SW_LNT3_LPRX_EN:1; +} MIPITX_DSI_SW_CTRL_CON1_REG, *PMIPITX_DSI_SW_CTRL_CON1_REG; + +typedef struct { + unsigned SW_LNT_HSTX_DATA:8; + unsigned rsv_8:24; +} MIPITX_DSI_SW_CTRL_CON2_REG, *PMIPITX_DSI_SW_CTRL_CON2_REG; + +typedef struct { + unsigned MIPI_TX_DBG_SEL:4; + unsigned MIPI_TX_DBG_OUT_EN:1; + unsigned MIPI_TX_GPIO_MODE_EN:1; + unsigned MIPI_TX_APB_ASYNC_CNT_EN:1; + unsigned rsv_7:25; +} MIPITX_DSI_DBG_CON_REG, *PMIPITX_DSI_DBG_CON_REG; + +typedef struct { + unsigned MIPI_TX_APB_ASYNC_ERR:1; + unsigned MIPI_TX_APB_ASYNC_ERR_ADDR:10; + unsigned rsv_11:21; +} MIPITX_DSI_APB_ASYNC_STA_REG, *PMIPITX_DSI_APB_ASYNC_STA_REG; + + +/* field definition */ +/* ------------------------------------------------------------- */ +/* DSI */ + +typedef struct { + unsigned DSI_START:1; + unsigned rsv_1:1; + unsigned SLEEPOUT_START:1; + unsigned rsv_3:1; + unsigned SKEWCAL_START:1; + unsigned rsv_5:11; + unsigned VM_CMD_START:1; + unsigned rsv_17:15; +} DSI_START_REG, *PDSI_START_REG; + + +typedef struct { + unsigned rsv_0:1; + unsigned BUF_UNDERRUN:1; + unsigned rsv_2:2; + unsigned ESC_ENTRY_ERR:1; + unsigned ESC_SYNC_ERR:1; + unsigned CTRL_ERR:1; + unsigned CONTENT_ERR:1; + unsigned rsv_8:24; +} DSI_STATUS_REG, *PDSI_STATUS_REG; + + +typedef struct { + unsigned RD_RDY:1; + unsigned CMD_DONE:1; + unsigned TE_RDY:1; + unsigned VM_DONE:1; + unsigned FRAME_DONE_INT_EN:1; + unsigned VM_CMD_DONE:1; + unsigned SLEEPOUT_DONE:1; + unsigned TE_TIMEOUT_INT_EN:1; + unsigned VM_VBP_STR_INT_EN:1; + unsigned VM_VACT_STR_INT_EN:1; + unsigned VM_VFP_STR_INT_EN:1; + unsigned SKEWCAL_DONE_INT_EN:1; + unsigned rsv_12:20; +} DSI_INT_ENABLE_REG, *PDSI_INT_ENABLE_REG; + + +typedef struct { + unsigned RD_RDY:1; + unsigned CMD_DONE:1; + unsigned TE_RDY:1; + unsigned VM_DONE:1; + unsigned FRAME_DONE_INT_EN:1; + unsigned VM_CMD_DONE:1; + unsigned SLEEPOUT_DONE:1; + unsigned TE_TIMEOUT_INT_EN:1; + unsigned VM_VBP_STR_INT_EN:1; + unsigned VM_VACT_STR_INT_EN:1; + unsigned VM_VFP_STR_INT_EN:1; + unsigned SKEWCAL_DONE_INT_EN:1; + unsigned rsv_12:19; + unsigned BUSY:1; +} DSI_INT_STATUS_REG, *PDSI_INT_STATUS_REG; + + +typedef struct { + unsigned DSI_RESET:1; + unsigned rsv_1:1; + unsigned DPHY_RESET:1; + unsigned rsv_3:1; + unsigned DSI_DUAL_EN:1; + unsigned rsv_5:27; +} DSI_COM_CTRL_REG, *PDSI_COM_CTRL_REG; + + +typedef enum { + DSI_CMD_MODE = 0, + DSI_SYNC_PULSE_VDO_MODE = 1, + DSI_SYNC_EVENT_VDO_MODE = 2, + DSI_BURST_VDO_MODE = 3 +} DSI_MODE_CTRL; + + +typedef struct { + unsigned MODE:2; + unsigned rsv_2:14; + unsigned FRM_MODE:1; + unsigned MIX_MODE:1; + unsigned V2C_SWITCH_ON:1; + unsigned C2V_SWITCH_ON:1; + unsigned SLEEP_MODE:1; + unsigned rsv_21:11; +} DSI_MODE_CTRL_REG, *PDSI_MODE_CTRL_REG; + + +typedef enum { + ONE_LANE = 1, + TWO_LANE = 2, + THREE_LANE = 3, + FOUR_LANE = 4 +} DSI_LANE_NUM; + + +typedef struct { + unsigned VC_NUM:2; + unsigned LANE_NUM:4; + unsigned DIS_EOT:1; + unsigned BLLP_EN:1; + unsigned TE_FREERUN:1; + unsigned EXT_TE_EN:1; + unsigned EXT_TE_EDGE:1; + unsigned TE_AUTO_SYNC:1; + unsigned MAX_RTN_SIZE:4; + unsigned HSTX_CKLP_EN:1; + unsigned TYPE1_BTA_SEL:1; + unsigned TE_WITH_CMD_EN:1; + unsigned TE_TIMEOUT_CHK_EN:1; + unsigned EXT_TE_TIME_VM:4; + unsigned rsv_24:8; +} DSI_TXRX_CTRL_REG, *PDSI_TXRX_CTRL_REG; + + +typedef enum { + PACKED_PS_16BIT_RGB565 = 0, + LOOSELY_PS_18BIT_RGB666 = 1, + PACKED_PS_24BIT_RGB888 = 2, + PACKED_PS_18BIT_RGB666 = 3 +} DSI_PS_TYPE; + + +typedef struct { + unsigned DSI_PS_WC:14; + unsigned rsv_14:2; + unsigned DSI_PS_SEL:2; + unsigned rsv_18:6; + unsigned RGB_SWAP:1; + unsigned BYTE_SWAP:1; + unsigned rsv_26:6; +} DSI_PSCTRL_REG, *PDSI_PSCTRL_REG; + + +typedef struct { + unsigned VSA_NL:12; + unsigned rsv_12:20; +} DSI_VSA_NL_REG, *PDSI_VSA_NL_REG; + + +typedef struct { + unsigned VBP_NL:12; + unsigned rsv_12:20; +} DSI_VBP_NL_REG, *PDSI_VBP_NL_REG; + + +typedef struct { + unsigned VFP_NL:12; + unsigned rsv_12:20; +} DSI_VFP_NL_REG, *PDSI_VFP_NL_REG; + + +typedef struct { + unsigned VACT_NL:12; + unsigned rsv_12:20; +} DSI_VACT_NL_REG, *PDSI_VACT_NL_REG; + +typedef struct { + unsigned LFR_MODE:2; + unsigned LFR_TYPE:2; + unsigned LFR_EN:1; + unsigned LFR_UPDATE:1; + unsigned LFR_VSE_DIS:1; + unsigned rsv_7:1; + unsigned LFR_SKIP_NUM:6; + unsigned rsv_14:18; +} DSI_LFR_CON_REG, *PDSI_LFR_CON_REG; + + +typedef struct { + unsigned LFR_SKIP_CNT:6; + unsigned rsv_6:2; + unsigned LFR_SKIP_STA:1; + unsigned rsv_9:23; +} DSI_LFR_STA_REG, *PDSI_LFR_STA_REG; + + +typedef struct { + unsigned HSA_WC:12; + unsigned rsv_12:20; +} DSI_HSA_WC_REG, *PDSI_HSA_WC_REG; + + +typedef struct { + unsigned HBP_WC:12; + unsigned rsv_12:20; +} DSI_HBP_WC_REG, *PDSI_HBP_WC_REG; + + +typedef struct { + unsigned HFP_WC:12; + unsigned rsv_12:20; +} DSI_HFP_WC_REG, *PDSI_HFP_WC_REG; + +typedef struct { + unsigned BLLP_WC:12; + unsigned rsv_12:20; +} DSI_BLLP_WC_REG, *PDSI_BLLP_WC_REG; + +typedef struct { + unsigned CMDQ_SIZE:8; + unsigned rsv_8:24; +} DSI_CMDQ_CTRL_REG, *PDSI_CMDQ_CTRL_REG; +typedef struct { + unsigned rsv_0:2; + unsigned HSTX_CKLP_WC:14; + unsigned HSTX_CKLP_WC_AUTO:1; + unsigned rsv_17:15; +} DSI_HSTX_CKLP_REG, *PDSI_HSTX_CKLP_REG; + +typedef struct { + unsigned HSTX_CKLP_WC_AUTO_RESULT:16; + unsigned rsv_16:16; +} DSI_HSTX_CKLP_WC_AUTO_RESULT_REG, *PDSI_HSTX_CKLP_WC_AUTO_RESULT_REG; + +typedef struct { + unsigned char byte0; + unsigned char byte1; + unsigned char byte2; + unsigned char byte3; +} DSI_RX_DATA_REG, *PDSI_RX_DATA_REG; + + +typedef struct { + unsigned DSI_RACK:1; + unsigned DSI_RACK_BYPASS:1; + unsigned rsv2:30; +} DSI_RACK_REG, *PDSI_RACK_REG; + + +typedef struct { + unsigned TRIG0:1; /* remote rst */ + unsigned TRIG1:1; /* TE */ + unsigned TRIG2:1; /* ack */ + unsigned TRIG3:1; /* rsv */ + unsigned RX_ULPS:1; + unsigned DIRECTION:1; + unsigned RX_LPDT:1; + unsigned rsv7:1; + unsigned RX_POINTER:4; + unsigned rsv12:20; +} DSI_TRIG_STA_REG, *PDSI_TRIG_STA_REG; + + +typedef struct { + unsigned RWMEM_CONTI:16; + unsigned rsv16:16; +} DSI_MEM_CONTI_REG, *PDSI_MEM_CONTI_REG; + + +typedef struct { + unsigned FRM_BC:21; + unsigned rsv21:11; +} DSI_FRM_BC_REG, *PDSI_FRM_BC_REG; + +typedef struct { + unsigned _3D_MODE:2; + unsigned _3D_FMT:2; + unsigned _3D_VSYNC:1; + unsigned _3D_LR:1; + unsigned _3D_EN:1; + unsigned rsv08:25; +} DSI_3D_CON_REG, *PDSI_3D_CON_REG; + +typedef struct { + unsigned UPLS_WAKEUP_PRD:16; + unsigned SKEWCALL_PRD:16; +} DSI_TIME_CON0_REG, *PDSI_TIME_CON0_REG; + +typedef struct { + unsigned TE_WAKEUP_PRD:16; + unsigned PREFETCH_TIME:15; + unsigned PREFETCH_EN:1; +} DSI_TIME_CON1_REG, *PDSI_TIME_CON1_REG; + + +typedef struct { + unsigned LC_HSTX_CK_PAT:32; +} DSI_PHY_LCPAT_REG, *PDSI_PHY_LCPAT_REG; + +typedef struct { + unsigned LC_HS_TX_EN:1; + unsigned LC_ULPM_EN:1; + unsigned LC_WAKEUP_EN:1; + unsigned rsv3:29; +} DSI_PHY_LCCON_REG, *PDSI_PHY_LCCON_REG; + + +typedef struct { + unsigned L0_RM_TRIG_EN:1; + unsigned L0_ULPM_EN:1; + unsigned L0_WAKEUP_EN:1; + unsigned Lx_ULPM_AS_L0:1; + unsigned L0_RX_FILTER_EN:1; + unsigned rsv3:27; +} DSI_PHY_LD0CON_REG, *PDSI_PHY_LD0CON_REG; + + +typedef struct { + unsigned HS_SYNC_CODE:8; + unsigned HS_SYNC_CODE2:8; + unsigned HS_SKEWCAL_PAT:8; + unsigned HS_DB_SYNC_EN:1; + unsigned rsv25:7; +} DSI_PHY_SYNCON_REG, *PDSI_PHY_SYNCON_REG; + + +typedef struct { + unsigned char LPX; + unsigned char HS_PRPR; + unsigned char HS_ZERO; + unsigned char HS_TRAIL; +} DSI_PHY_TIMCON0_REG, *PDSI_PHY_TIMCON0_REG; + + +typedef struct { + unsigned char TA_GO; + unsigned char TA_SURE; + unsigned char TA_GET; + unsigned char DA_HS_EXIT; +} DSI_PHY_TIMCON1_REG, *PDSI_PHY_TIMCON1_REG; + + +typedef struct { + unsigned char CONT_DET; + unsigned char DA_HS_SYNC; + unsigned char CLK_ZERO; + unsigned char CLK_TRAIL; +} DSI_PHY_TIMCON2_REG, *PDSI_PHY_TIMCON2_REG; + + +typedef struct { + unsigned char CLK_HS_PRPR; + unsigned char CLK_HS_POST; + unsigned char CLK_HS_EXIT; + unsigned rsv24:8; +} DSI_PHY_TIMCON3_REG, *PDSI_PHY_TIMCON3_REG; + + +typedef struct { + unsigned ULPS_WAKEUP:20; + unsigned rsv20:12; +} DSI_PHY_TIMCON4_REG, *PDSI_PHY_TIMCON4_REG; + +typedef struct { + unsigned VM_CMD_EN:1; + unsigned LONG_PKT:1; + unsigned TIME_SEL:1; + unsigned TS_VSA_EN:1; + unsigned TS_VBP_EN:1; + unsigned TS_VFP_EN:1; + unsigned rsv6:2; + unsigned CM_DATA_ID:8; + unsigned CM_DATA_0:8; + unsigned CM_DATA_1:8; +} DSI_VM_CMD_CON_REG, *PDSI_VM_CMD_CON_REG; + + +typedef struct { + DSI_PHY_TIMCON0_REG CTRL0; + DSI_PHY_TIMCON1_REG CTRL1; + DSI_PHY_TIMCON2_REG CTRL2; + DSI_PHY_TIMCON3_REG CTRL3; +} DSI_PHY_TIMCON_REG, *PDSI_PHY_TIMCON_REG; + + +typedef struct { + unsigned PKT_CHECK_SUM:16; + unsigned ACC_CHECK_SUM:16; +} DSI_CKSM_OUT_REG, *PDSI_CKSM_OUT_REG; + + +typedef struct { + unsigned DPHY_CTL_STATE_C:9; + unsigned rsv9:7; + unsigned DPHY_HS_TX_STATE_C:5; + unsigned rsv21:11; +} DSI_STATE_DBG0_REG, *PDSI_STATE_DBG0_REG; + + +typedef struct { + unsigned CTL_STATE_C:15; + unsigned rsv15:1; + unsigned HS_TX_STATE_0:5; + unsigned rsv21:3; + unsigned ESC_STATE_0:8; +} DSI_STATE_DBG1_REG, *PDSI_STATE_DBG1_REG; + + +typedef struct { + unsigned RX_ESC_STATE:10; + unsigned rsv10:6; + unsigned TA_T2R_STATE:5; + unsigned rsv21:3; + unsigned TA_R2T_STATE:5; + unsigned rsv29:3; +} DSI_STATE_DBG2_REG, *PDSI_STATE_DBG2_REG; + + +typedef struct { + unsigned CTL_STATE_1:5; + unsigned rsv5:3; + unsigned HS_TX_STATE_1:5; + unsigned rsv13:3; + unsigned CTL_STATE_2:5; + unsigned rsv21:3; + unsigned HS_TX_STATE_2:5; + unsigned rsv29:3; +} DSI_STATE_DBG3_REG, *PDSI_STATE_DBG3_REG; + + +typedef struct { + unsigned CTL_STATE_3:5; + unsigned rsv5:3; + unsigned HS_TX_STATE_3:5; + unsigned rsv13:19; +} DSI_STATE_DBG4_REG, *PDSI_STATE_DBG4_REG; + + +typedef struct { + unsigned TIMER_COUNTER:16; + unsigned TIMER_BUSY:1; + unsigned rsv17:11; + unsigned WAKEUP_STATE:4; +} DSI_STATE_DBG5_REG, *PDSI_STATE_DBG5_REG; + + +typedef struct { + unsigned CMTRL_STATE:14; + unsigned rsv14:2; + unsigned CMDQ_STATE:8; + unsigned rsv24:8; +} DSI_STATE_DBG6_REG, *PDSI_STATE_DBG6_REG; + + +typedef struct { + unsigned VMCTL_STATE:11; + unsigned rsv11:1; + unsigned VFP_PERIOD:1; + unsigned VACT_PERIOD:1; + unsigned VBP_PERIOD:1; + unsigned VSA_PERIOD:1; + unsigned rsv16:16; +} DSI_STATE_DBG7_REG, *PDSI_STATE_DBG7_REG; + + +typedef struct { + unsigned WORD_COUNTER:14; + unsigned rsv14:18; +} DSI_STATE_DBG8_REG, *PDSI_STATE_DBG8_REG; + + +typedef struct { + unsigned LINE_COUNTER:22; + unsigned rsv22:10; +} DSI_STATE_DBG9_REG, *PDSI_STATE_DBG9_REG; + + +typedef struct { + unsigned DEBUG_OUT_SEL:5; + unsigned rsv5:3; + unsigned CHKSUM_REC_EN:1; + unsigned rsv9:23; +} DSI_DEBUG_SEL_REG, *PDSI_DEBUG_SEL_REG; + + +typedef struct { + unsigned BIST_MODE:1; + unsigned BIST_ENABLE:1; + unsigned BIST_FIX_PATTERN:1; + unsigned BIST_SPC_PATTERN:1; + unsigned BIST_HS_FREE:1; + unsigned rsv_05:1; + unsigned SELF_PAT_MODE:1; + unsigned rsv_07:1; + unsigned BIST_LANE_NUM:4; + unsigned rsv12:4; + unsigned BIST_TIMING:8; + unsigned rsv24:8; +} DSI_BIST_CON_REG, *PDSI_BIST_CON_REG; + + + +typedef struct { + DSI_START_REG DSI_START; /* 0000 */ + DSI_STATUS_REG DSI_STA; /* 0004 */ + DSI_INT_ENABLE_REG DSI_INTEN; /* 0008 */ + DSI_INT_STATUS_REG DSI_INTSTA; /* 000C */ + DSI_COM_CTRL_REG DSI_COM_CTRL; /* 0010 */ + DSI_MODE_CTRL_REG DSI_MODE_CTRL; /* 0014 */ + DSI_TXRX_CTRL_REG DSI_TXRX_CTRL; /* 0018 */ + DSI_PSCTRL_REG DSI_PSCTRL; /* 001C */ + DSI_VSA_NL_REG DSI_VSA_NL; /* 0020 */ + DSI_VBP_NL_REG DSI_VBP_NL; /* 0024 */ + DSI_VFP_NL_REG DSI_VFP_NL; /* 0028 */ + DSI_VACT_NL_REG DSI_VACT_NL; /* 002C */ + DSI_LFR_CON_REG DSI_LFR_CON; /* 0030 */ + DSI_LFR_STA_REG DSI_LFR_STA; /* 0034 */ + uint32_t rsv_38[6]; /* 0038..004C */ + DSI_HSA_WC_REG DSI_HSA_WC; /* 0050 */ + DSI_HBP_WC_REG DSI_HBP_WC; /* 0054 */ + DSI_HFP_WC_REG DSI_HFP_WC; /* 0058 */ + DSI_BLLP_WC_REG DSI_BLLP_WC; /* 005C */ + DSI_CMDQ_CTRL_REG DSI_CMDQ_SIZE; /* 0060 */ + DSI_HSTX_CKLP_REG DSI_HSTX_CKL_WC; /* 0064 */ + DSI_HSTX_CKLP_WC_AUTO_RESULT_REG DSI_HSTX_CKL_WC_AUTO_RESULT; /* 0068 */ + uint32_t rsv_006C[2]; /* 006c..0070 */ + DSI_RX_DATA_REG DSI_RX_DATA0; /* 0074 */ + DSI_RX_DATA_REG DSI_RX_DATA1; /* 0078 */ + DSI_RX_DATA_REG DSI_RX_DATA2; /* 007c */ + DSI_RX_DATA_REG DSI_RX_DATA3; /* 0080 */ + DSI_RACK_REG DSI_RACK; /* 0084 */ + DSI_TRIG_STA_REG DSI_TRIG_STA; /* 0088 */ + uint32_t rsv_008C; /* 008C */ + DSI_MEM_CONTI_REG DSI_MEM_CONTI; /* 0090 */ + DSI_FRM_BC_REG DSI_FRM_BC; /* 0094 */ + DSI_3D_CON_REG DSI_3D_CON; /* 0098 */ + uint32_t rsv_009C; /* 009c */ + DSI_TIME_CON0_REG DSI_TIME_CON0; /* 00A0 */ + DSI_TIME_CON1_REG DSI_TIME_CON1; /* 00A4 */ + + uint32_t rsv_00A8[22]; /* 0A8..0FC */ + uint32_t DSI_PHY_PCPAT; /* 00100 */ + + DSI_PHY_LCCON_REG DSI_PHY_LCCON; /* 0104 */ + DSI_PHY_LD0CON_REG DSI_PHY_LD0CON; /* 0108 */ + DSI_PHY_SYNCON_REG DSI_PHY_SYNCON; /* 010C */ + DSI_PHY_TIMCON0_REG DSI_PHY_TIMECON0; /* 0110 */ + DSI_PHY_TIMCON1_REG DSI_PHY_TIMECON1; /* 0114 */ + DSI_PHY_TIMCON2_REG DSI_PHY_TIMECON2; /* 0118 */ + DSI_PHY_TIMCON3_REG DSI_PHY_TIMECON3; /* 011C */ + uint32_t rsv_0120[4]; /* 0120..012c */ + DSI_VM_CMD_CON_REG DSI_VM_CMD_CON; /* 0130 */ + uint32_t DSI_VM_CMD_DATA0; /* 0134 */ + uint32_t DSI_VM_CMD_DATA4; /* 0138 */ + uint32_t DSI_VM_CMD_DATA8; /* 013C */ + uint32_t DSI_VM_CMD_DATAC; /* 0140 */ + DSI_CKSM_OUT_REG DSI_CKSM_OUT; /* 0144 */ + DSI_STATE_DBG0_REG DSI_STATE_DBG0; /* 0148 */ + DSI_STATE_DBG1_REG DSI_STATE_DBG1; /* 014C */ + DSI_STATE_DBG2_REG DSI_STATE_DBG2; /* 0150 */ + DSI_STATE_DBG3_REG DSI_STATE_DBG3; /* 0154 */ + DSI_STATE_DBG4_REG DSI_STATE_DBG4; /* 0158 */ + DSI_STATE_DBG5_REG DSI_STATE_DBG5; /* 015C */ + DSI_STATE_DBG6_REG DSI_STATE_DBG6; /* 0160 */ + DSI_STATE_DBG7_REG DSI_STATE_DBG7; /* 0164 */ + DSI_STATE_DBG8_REG DSI_STATE_DBG8; /* 0168 */ + DSI_STATE_DBG9_REG DSI_STATE_DBG9; /* 016C */ + DSI_DEBUG_SEL_REG DSI_DEBUG_SEL; /* 0170 */ + uint32_t rsv174; /* 0174 */ + uint32_t DSI_BIST_PATTERN; /* 0178 */ + DSI_BIST_CON_REG DSI_BIST_CON; /* 017C */ + uint32_t DSI_VM_CMD_DATA10; /* 00180 */ + uint32_t DSI_VM_CMD_DATA14; /* 00184 */ + uint32_t DSI_VM_CMD_DATA18; /* 00188 */ + uint32_t DSI_VM_CMD_DATA1C; /* 0018C */ +} volatile DSI_REGS, *PDSI_REGS; + +/* 0~1 TYPE ,2 BTA,3 HS, 4 CL,5 TE,6~7 RESV, 8~15 DATA_ID,16~23 DATA_0,24~31 DATA_1 */ +typedef struct { + unsigned char byte0; + unsigned char byte1; + unsigned char byte2; + unsigned char byte3; +} DSI_CMDQ, *PDSI_CMDQ; + +typedef struct { + DSI_CMDQ data[128]; +} DSI_CMDQ_REGS, *PDSI_CMDQ_REGS; + +typedef struct { + unsigned char byte0; + unsigned char byte1; + unsigned char byte2; + unsigned char byte3; +} DSI_VM_CMDQ, *PDSI_VM_CMDQ; + +typedef struct { + DSI_VM_CMDQ data[4]; +} DSI_VM_CMDQ_REGS, *PDSI_VM_CMDQ_REGS; + +typedef struct { + MIPITX_DSI_CON_REG MIPITX_DSI_CON; /* 0000 */ + MIPITX_DSI_CLOCK_LANE_REG MIPITX_DSI_CLOCK_LANE; /* 0004 */ + MIPITX_DSI_DATA_LANE0_REG MIPITX_DSI_DATA_LANE0; /* 0008 */ + MIPITX_DSI_DATA_LANE1_REG MIPITX_DSI_DATA_LANE1; /* 000C */ + MIPITX_DSI_DATA_LANE2_REG MIPITX_DSI_DATA_LANE2; /* 0010 */ + MIPITX_DSI_DATA_LANE3_REG MIPITX_DSI_DATA_LANE3; /* 0014 */ + uint32_t rsv_18[10]; /* 0018..003C */ + + MIPITX_DSI_TOP_CON_REG MIPITX_DSI_TOP_CON; /* 0040 */ + MIPITX_DSI_BG_CON_REG MIPITX_DSI_BG_CON; /* 0044 */ + uint32_t rsv_48[2]; /* 0048..004C */ + MIPITX_DSI_PLL_CON0_REG MIPITX_DSI_PLL_CON0; /* 0050 */ + MIPITX_DSI_PLL_CON1_REG MIPITX_DSI_PLL_CON1; /* 0054 */ + MIPITX_DSI_PLL_CON2_REG MIPITX_DSI_PLL_CON2; /* 0058 */ + MIPITX_DSI_PLL_CON3_REG MIPITX_DSI_PLL_CON3; /* 005C */ + MIPITX_DSI_PLL_CHG_REG MIPITX_DSI_PLL_CHG; /* 0060 */ + MIPITX_DSI_PLL_TOP_REG MIPITX_DSI_PLL_TOP; /* 0064 */ + MIPITX_DSI_PLL_PWR_REG MIPITX_DSI_PLL_PWR; /* 0068 */ + uint32_t rsv_6C; /* 006C */ + MIPITX_DSI_RGS_REG MIPITX_DSI_RGS; /* 0070 */ + MIPITX_DSI_GPI_EN_REG MIPITX_DSI_GPI_EN; /* 0074 */ + MIPITX_DSI_GPI_PULL_REG MIPITX_DSI_GPI_PULL; /* 0078 */ + MIPITX_DSI_PHY_SEL_REG MIPITX_DSI_PHY_SEL; /* 007C */ + + MIPITX_DSI_SW_CTRL_REG MIPITX_DSI_SW_CTRL_EN; /* 0080 */ + MIPITX_DSI_SW_CTRL_CON0_REG MIPITX_DSI_SW_CTRL_CON0; /* 0084 */ + MIPITX_DSI_SW_CTRL_CON1_REG MIPITX_DSI_SW_CTRL_CON1; /* 0088 */ + MIPITX_DSI_SW_CTRL_CON2_REG MIPITX_DSI_SW_CTRL_CON2; /* 008C */ + MIPITX_DSI_DBG_CON_REG MIPITX_DSI_DBG_CON; /* 0090 */ + uint32_t MIPITX_DSI_DBG_OUT; /* 0084 */ + MIPITX_DSI_APB_ASYNC_STA_REG MIPITX_DSI_APB_ASYNC_STA; /* 0098 */ + +} volatile DSI_PHY_REGS, *PDSI_PHY_REGS; + +/* +#ifndef BUILD_LK + +STATIC_ASSERT(0x0050 == offsetof(DSI_PHY_REGS, MIPITX_DSI_PLL_CON0)); +STATIC_ASSERT(0x0070 == offsetof(DSI_PHY_REGS, MIPITX_DSI_RGS)); +STATIC_ASSERT(0x0080 == offsetof(DSI_PHY_REGS, MIPITX_DSI_SW_CTRL_EN)); +STATIC_ASSERT(0x0090 == offsetof(DSI_PHY_REGS, MIPITX_DSI_DBG_CON)); + +STATIC_ASSERT(0x002C == offsetof(DSI_REGS, DSI_VACT_NL)); +STATIC_ASSERT(0x0104 == offsetof(DSI_REGS, DSI_PHY_LCCON)); +STATIC_ASSERT(0x011C == offsetof(DSI_REGS, DSI_PHY_TIMECON3)); +STATIC_ASSERT(0x017C == offsetof(DSI_REGS, DSI_BIST_CON)); +STATIC_ASSERT(0x0100 == offsetof(DSI_REGS, DSI_PHY_PCPAT)); + +STATIC_ASSERT((uint32_t)0x0098 == offsetof(DSI_REGS, DSI_3D_CON)); +#endif +*/ +/* mipi and dsi's extern variable */ +extern volatile unsigned long dispsys_reg[DISP_REG_NUM]; +extern unsigned long ddp_reg_pa_base[DISP_REG_NUM]; +extern volatile unsigned long mipi_tx_reg; +extern volatile unsigned long dsi_reg_va; + +/* DTS will assign reigister address dynamically, so can not define to 0x1000 */ +/* #define DISP_INDEX_OFFSET 0x1000 */ + +#define DISP_RDMA_INDEX_OFFSET (dispsys_reg[DISP_REG_RDMA1] - dispsys_reg[DISP_REG_RDMA0]) +#define DISP_WDMA_INDEX_OFFSET (dispsys_reg[DISP_REG_WDMA1] - dispsys_reg[DISP_REG_WDMA0]) + +#define DDP_REG_BASE_MMSYS_CONFIG dispsys_reg[DISP_REG_CONFIG] +#define DDP_REG_BASE_DISP_OVL0 dispsys_reg[DISP_REG_OVL0] +#define DDP_REG_BASE_DISP_OVL1 dispsys_reg[DISP_REG_OVL1] +#define DDP_REG_BASE_DISP_RDMA0 dispsys_reg[DISP_REG_RDMA0] +#define DDP_REG_BASE_DISP_RDMA1 dispsys_reg[DISP_REG_RDMA1] +#define DDP_REG_BASE_DISP_WDMA0 dispsys_reg[DISP_REG_WDMA0] +#define DDP_REG_BASE_DISP_WDMA1 dispsys_reg[DISP_REG_WDMA1] +#define DDP_REG_BASE_DISP_COLOR0 dispsys_reg[DISP_REG_COLOR] +#define DDP_REG_BASE_DISP_COLOR1 0 +#define DDP_REG_BASE_DISP_AAL dispsys_reg[DISP_REG_AAL] +#define DDP_REG_BASE_DISP_GAMMA dispsys_reg[DISP_REG_GAMMA] +#define DDP_REG_BASE_DISP_MERGE 0 +#define DDP_REG_BASE_DISP_SPLIT0 0 +#define DDP_REG_BASE_DISP_SPLIT1 0 +#define DDP_REG_BASE_DISP_UFOE 0 +#define DDP_REG_BASE_DSI0 dispsys_reg[DISP_REG_DSI0] +#define DDP_REG_BASE_DSI1 0 +#define DDP_REG_BASE_DPI dispsys_reg[DISP_REG_DPI0] +#define DDP_REG_BASE_DISP_PWM0 dispsys_reg[DISP_REG_PWM] +#define DDP_REG_BASE_DISP_PWM1 0 +#define DDP_REG_BASE_MM_MUTEX dispsys_reg[DISP_REG_MUTEX] +#define DDP_REG_BASE_SMI_LARB0 dispsys_reg[DISP_REG_SMI_LARB0] +#define DDP_REG_BASE_SMI_COMMON dispsys_reg[DISP_REG_SMI_COMMON] +#define DDP_REG_BASE_DISP_OD 0 +#define DDP_REG_BASE_DISP_CCORR dispsys_reg[DISP_REG_CCORR] +#define DDP_REG_BASE_DISP_DITHER dispsys_reg[DISP_REG_DITHER] +#define DDP_REG_BASE_DISP_OVL0_2L dispsys_reg[DISP_REG_OVL0_2L] +#define DDP_REG_BASE_DISP_OVL1_2L dispsys_reg[DISP_REG_OVL1_2L] + +#define MIPI_TX_REG_BASE (mipi_tx_reg) + +#define DISPSYS_REG_ADDR_MIN (DISPSYS_CONFIG_BASE) +#define DISPSYS_REG_ADDR_MAX (DDP_REG_BASE_DISP_OVL1_2L) + +#define DISPSYS_CONFIG_BASE DDP_REG_BASE_MMSYS_CONFIG +#define DISPSYS_OVL0_BASE DDP_REG_BASE_DISP_OVL0 +#define DISPSYS_OVL1_BASE DDP_REG_BASE_DISP_OVL1 +#define DISPSYS_RDMA0_BASE DDP_REG_BASE_DISP_RDMA0 +#define DISPSYS_RDMA1_BASE DDP_REG_BASE_DISP_RDMA1 +#define DISPSYS_WDMA0_BASE DDP_REG_BASE_DISP_WDMA0 +#define DISPSYS_WDMA1_BASE DDP_REG_BASE_DISP_WDMA1 +#define DISPSYS_COLOR0_BASE DDP_REG_BASE_DISP_COLOR0 +#define DISPSYS_COLOR1_BASE DDP_REG_BASE_DISP_COLOR1 +#define DISPSYS_AAL_BASE DDP_REG_BASE_DISP_AAL +#define DISPSYS_GAMMA_BASE DDP_REG_BASE_DISP_GAMMA +#define DISPSYS_MERGE_BASE DDP_REG_BASE_DISP_MERGE +#define DISPSYS_SPLIT0_BASE DDP_REG_BASE_DISP_SPLIT0 +#define DISPSYS_SPLIT1_BASE DDP_REG_BASE_DISP_SPLIT1 +#define DISPSYS_UFOE_BASE DDP_REG_BASE_DISP_UFOE +#define DISPSYS_DSI0_BASE DDP_REG_BASE_DSI0 +#define DISPSYS_DITHER_BASE DDP_REG_BASE_DISP_DITHER +#define DISPSYS_DSI1_BASE DDP_REG_BASE_DSI1 +#define DISPSYS_DPI_BASE DDP_REG_BASE_DPI +#define DISPSYS_PWM0_BASE DDP_REG_BASE_DISP_PWM0 +#define DISPSYS_PWM1_BASE DDP_REG_BASE_DISP_PWM1 +#define DISPSYS_MUTEX_BASE DDP_REG_BASE_MM_MUTEX +#define DISPSYS_SMI_LARB0_BASE DDP_REG_BASE_SMI_LARB0 +#define DISPSYS_SMI_COMMON_BASE DDP_REG_BASE_SMI_COMMON +#define DISPSYS_OD_BASE DDP_REG_BASE_DISP_OD +#define DISPSYS_CCORR_BASE DDP_REG_BASE_DISP_CCORR + + +#define MIPITX_BASE MIPI_TX_REG_BASE + +#ifdef INREG32 +#undef INREG32 +#define INREG32(x) (__raw_readl((volatile unsigned long*)(x))) +#endif + +/* --------------------------------------------------------------------------- */ +/* Register Field Access */ +/* --------------------------------------------------------------------------- */ + +#define READ_REGISTER_UINT32(reg) (*(volatile uint32_t *const)(reg)) +#define INREG32(x) READ_REGISTER_UINT32((uint32_t *)((void *)(x))) +#define DRV_Reg32(addr) INREG32(addr) +#define WRITE_REGISTER_UINT32(reg, val) ((*(volatile uint32_t *const)(reg)) = (val)) +#define OUTREG32(x, y) WRITE_REGISTER_UINT32((uint32_t *)((void *)(x)), (uint32_t)(y)) +#define AS_UINT32(x) (*(uint32_t *)((void *)x)) + +#define REG_FLD(width, shift) \ + ((unsigned int)((((width) & 0xFF) << 16) | ((shift) & 0xFF))) + +#define REG_FLD_MSB_LSB(msb, lsb) REG_FLD((msb) - (lsb) + 1, (lsb)) + +#define REG_FLD_WIDTH(field) \ + ((unsigned int)(((field) >> 16) & 0xFF)) + +#define REG_FLD_SHIFT(field) \ + ((unsigned int)((field) & 0xFF)) + +#define REG_FLD_MASK(field) \ + ((unsigned int)((1ULL << REG_FLD_WIDTH(field)) - 1) << REG_FLD_SHIFT(field)) + +#define REG_FLD_VAL(field, val) \ + (((val) << REG_FLD_SHIFT(field)) & REG_FLD_MASK(field)) + +#define REG_FLD_VAL_GET(field, regval) \ + (((regval) & REG_FLD_MASK(field)) >> REG_FLD_SHIFT(field)) + + +#define DISP_REG_GET(reg32) __raw_readl((volatile unsigned int*)(reg32)) +#define DISP_REG_GET_FIELD(field, reg32) \ + REG_FLD_VAL_GET(field, __raw_readl((volatile unsigned int*)(reg32))) + +/* polling register until masked bit is 1 */ +#define DDP_REG_POLLING(reg32, mask) \ + do { \ + while (!((DISP_REG_GET(reg32))&mask))\ + ; \ + } while (0) + +/* Polling register until masked bit is 0 */ +#define DDP_REG_POLLING_NEG(reg32, mask) \ + do { \ + while ((DISP_REG_GET(reg32))&mask)\ + ; \ + } while (0) + +#define DISP_CPU_REG_SET(reg32, val) \ + do {\ + if (0) \ + dprec_reg_op(NULL, reg32, val, 0x00000000);\ + mt_reg_sync_writel(val, (volatile unsigned long*)(reg32));\ + } while (0) +#define DISP_CPU_REG_SET_FIELD(field, reg32, val) \ + do { \ + if (0)\ + dprec_reg_op(NULL, (unsigned long)(reg32), val< +#endif +#include + +#include "ddp_info.h" +#include "ddp_hal.h" +#include "ddp_reg.h" + +static bool ufoe_enable; + +static void ufoe_dump(void) +{ + DISPDMP("==DISP UFOE REGS==\n"); + DISPDMP("(0x000)UFOE_START =0x%x\n", DISP_REG_GET(DISP_REG_UFO_START)); + DISPDMP("(0x000)UFOE_CFG0 =0x%x\n", DISP_REG_GET(DISP_REG_UFO_CFG_0B)); + DISPDMP("(0x000)UFOE_CFG1 =0x%x\n", DISP_REG_GET(DISP_REG_UFO_CFG_1B)); + DISPDMP("(0x000)UFOE_WIDTH =0x%x\n", DISP_REG_GET(DISP_REG_UFO_FRAME_WIDTH)); + DISPDMP("(0x000)UFOE_HEIGHT =0x%x\n", DISP_REG_GET(DISP_REG_UFO_FRAME_HEIGHT)); + DISPDMP("(0x000)UFOE_PAD =0x%x\n", DISP_REG_GET(DISP_REG_UFO_CR0P6_PAD)); +} + +static int ufoe_init(DISP_MODULE_ENUM module, void *handle) +{ +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_DISP0_DISP_UFOE, "ufoe"); +#endif + DISPMSG("ufoe_clock on CG 0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0)); + return 0; +} + +static int ufoe_deinit(DISP_MODULE_ENUM module, void *handle) +{ +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_DISP0_DISP_UFOE, "ufoe"); +#endif + DISPMSG("ufoe_clock off CG 0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0)); + return 0; +} + +int ufoe_start(DISP_MODULE_ENUM module, cmdqRecHandle cmdq) +{ + if (ufoe_enable) + DISP_REG_SET_FIELD(cmdq, START_FLD_DISP_UFO_START, DISP_REG_UFO_START, 1); + + DISPMSG("ufoe_start, ufoe_start:0x%x\n", DISP_REG_GET(DISP_REG_UFO_START)); + return 0; +} + + +int ufoe_stop(DISP_MODULE_ENUM module, void *cmdq_handle) +{ + DISP_REG_SET_FIELD(cmdq_handle, START_FLD_DISP_UFO_START, DISP_REG_UFO_START, 0); + DISPMSG("ufoe_stop, ufoe_start:0x%x\n", DISP_REG_GET(DISP_REG_UFO_START)); + return 0; +} + +static int ufoe_config(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle) +{ + LCM_PARAMS *disp_if_config = &(pConfig->dispif_config); + LCM_DSI_PARAMS *lcm_config = &(disp_if_config->dsi); + + if (lcm_config->ufoe_enable) { + ufoe_enable = true; + DISP_REG_SET_FIELD(handle, START_FLD_DISP_UFO_BYPASS, DISP_REG_UFO_START, 0); + /* DISP_REG_SET_FIELD(handle, START_FLD_DISP_UFO_START, DISP_REG_UFO_START, 1); */ + if (lcm_config->ufoe_params.lr_mode_en == 1) { + DISP_REG_SET_FIELD(handle, START_FLD_DISP_UFO_LR_EN, DISP_REG_UFO_START, 1); + } else { + DISP_REG_SET_FIELD(handle, START_FLD_DISP_UFO_LR_EN, DISP_REG_UFO_START, 0); + if (lcm_config->ufoe_params.compress_ratio == 3) { + unsigned int internal_width = + disp_if_config->width + disp_if_config->width % 4; + DISP_REG_SET_FIELD(handle, CFG_0B_FLD_DISP_UFO_CFG_COM_RATIO, + DISP_REG_UFO_CFG_0B, 1); + if (internal_width % 6 != 0) { + DISP_REG_SET_FIELD(handle, + CR0P6_PAD_FLD_DISP_UFO_STR_PAD_NUM, + DISP_REG_UFO_CR0P6_PAD, + (internal_width / 6 + 1) * 6 - + internal_width); + } + } else + DISP_REG_SET_FIELD(handle, CFG_0B_FLD_DISP_UFO_CFG_COM_RATIO, + DISP_REG_UFO_CFG_0B, 0); + + if (lcm_config->ufoe_params.vlc_disable) { + DISP_REG_SET_FIELD(handle, CFG_0B_FLD_DISP_UFO_CFG_VLC_EN, + DISP_REG_UFO_CFG_0B, 0); + DISP_REG_SET(handle, DISP_REG_UFO_CFG_1B, 0x1); + } else { + DISP_REG_SET_FIELD(handle, CFG_0B_FLD_DISP_UFO_CFG_VLC_EN, + DISP_REG_UFO_CFG_0B, 1); + DISP_REG_SET(handle, DISP_REG_UFO_CFG_1B, + (lcm_config->ufoe_params.vlc_config == + 0) ? 5 : lcm_config->ufoe_params.vlc_config); + } + } + DISP_REG_SET(handle, DISP_REG_UFO_FRAME_WIDTH, disp_if_config->width); + DISP_REG_SET(handle, DISP_REG_UFO_FRAME_HEIGHT, disp_if_config->height); + } +/* ufoe_dump(); */ + return 0; + +} + +static int ufoe_clock_on(DISP_MODULE_ENUM module, void *handle) +{ +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_DISP0_DISP_UFOE, "ufoe"); +#endif + DISPMSG("ufoe_clock on CG 0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0)); + return 0; +} + +static int ufoe_clock_off(DISP_MODULE_ENUM module, void *handle) +{ +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_DISP0_DISP_UFOE, "ufoe"); +#endif + DISPMSG("ufoe_clock off CG 0x%x\n", DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0)); + return 0; +} + +static int ufoe_reset(DISP_MODULE_ENUM module, void *handle) +{ + DISP_REG_SET_FIELD(handle, START_FLD_DISP_UFO_SW_RST_ENGINE, DISP_REG_UFO_START, 1); + DISP_REG_SET_FIELD(handle, START_FLD_DISP_UFO_SW_RST_ENGINE, DISP_REG_UFO_START, 0); + DISPMSG("ufoe reset done\n"); + return 0; +} + +/* ufoe */ +DDP_MODULE_DRIVER ddp_driver_ufoe = { + .init = ufoe_init, + .deinit = ufoe_deinit, + .config = ufoe_config, + .start = ufoe_start, + .trigger = NULL, + .stop = ufoe_stop, + .reset = ufoe_reset, + .power_on = ufoe_clock_on, + .power_off = ufoe_clock_off, + .is_idle = NULL, + .is_busy = NULL, + .dump_info = ufoe_dump, + .bypass = NULL, + .build_cmdq = NULL, + .set_lcm_utils = NULL, +}; diff --git a/drivers/misc/mediatek/video/mt6755/ddp_wdma.c b/drivers/misc/mediatek/video/mt6755/ddp_wdma.c new file mode 100644 index 0000000000000000000000000000000000000000..15b48aad7994b88c2f4b059799ae0871a1f58494 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_wdma.c @@ -0,0 +1,698 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#define LOG_TAG "WDMA" +#include "disp_log.h" +#include "disp_debug.h" +#include "mtkfb_debug.h" +#ifdef CONFIG_MTK_CLKMGR +#include +#else +#include "ddp_clkmgr.h" +#endif +#include +#include "ddp_reg.h" +#include "ddp_matrix_para.h" +#include "ddp_info.h" +#include "ddp_wdma.h" +#include "primary_display.h" +#include "m4u.h" + +#define ALIGN_TO(x, n) \ + (((x) + ((n) - 1)) & ~((n) - 1)) + +static char *wdma_get_status(unsigned int status) +{ + switch (status) { + case 0x1: + return "idle"; + case 0x2: + return "clear"; + case 0x4: + return "prepare"; + case 0x8: + return "prepare"; + case 0x10: + return "data_running"; + case 0x20: + return "eof_wait"; + case 0x40: + return "soft_reset_wait"; + case 0x80: + return "eof_done"; + case 0x100: + return "soft_reset_done"; + case 0x200: + return "frame_complete"; + } + return "unknown"; + +} + +static unsigned int wdma_index(DISP_MODULE_ENUM module) +{ + int idx = 0; + + switch (module) { + case DISP_MODULE_WDMA0: + idx = 0; + break; + case DISP_MODULE_WDMA1: + idx = 1; + break; + default: + DISPERR("[DDP] error: invalid wdma module=%d\n", module); /* invalid module */ + ASSERT(0); + } + return idx; +} + +static inline unsigned long wdma_to_cmdq_engine(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_WDMA0: + return CMDQ_ENG_DISP_WDMA0; + case DISP_MODULE_WDMA1: + return CMDQ_ENG_DISP_WDMA1; + default: + DISPERR("invalid rdma module=%d\n", module); + BUG(); + } + return 0; +} + +static inline unsigned long wdma_to_cmdq_event_nonsec_end(DISP_MODULE_ENUM module) +{ + switch (module) { + case DISP_MODULE_WDMA0: + return CMDQ_SYNC_DISP_WDMA0_2NONSEC_END; + case DISP_MODULE_WDMA1: + return CMDQ_SYNC_DISP_WDMA1_2NONSEC_END; + default: + DISPERR("invalid rdma module=%d\n", module); + BUG(); + } + + return 0; +} + +static int wdma_start(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int idx = wdma_index(module); + + DISP_REG_SET(handle, idx * DISP_WDMA_INDEX_OFFSET + DISP_REG_WDMA_INTEN, 0x03); + DISP_REG_SET(handle, idx * DISP_WDMA_INDEX_OFFSET + DISP_REG_WDMA_EN, 0x01); + + return 0; +} + +static int wdma_stop(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int idx = wdma_index(module); + + DISP_REG_SET(handle, idx * DISP_WDMA_INDEX_OFFSET + DISP_REG_WDMA_INTEN, 0x00); + DISP_REG_SET(handle, idx * DISP_WDMA_INDEX_OFFSET + DISP_REG_WDMA_EN, 0x00); + DISP_REG_SET(handle, idx * DISP_WDMA_INDEX_OFFSET + DISP_REG_WDMA_INTSTA, 0x00); + + return 0; +} + +static int wdma_reset(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int delay_cnt = 0; + unsigned int idx = wdma_index(module); + + DISP_REG_SET(handle, idx * DISP_WDMA_INDEX_OFFSET + DISP_REG_WDMA_RST, 0x01); /* trigger soft reset */ + if (!handle) { + while ((DISP_REG_GET(idx * DISP_WDMA_INDEX_OFFSET + DISP_REG_WDMA_FLOW_CTRL_DBG) & + 0x1) == 0) { + delay_cnt++; + udelay(10); + if (delay_cnt > 2000) { + DISPERR("wdma%d reset timeout!\n", idx); + break; + } + } + } else { + /* add comdq polling */ + } + DISP_REG_SET(handle, idx * DISP_WDMA_INDEX_OFFSET + DISP_REG_WDMA_RST, 0x0); /* trigger soft reset */ + + return 0; +} + +static int wdma_config_yuv420(DISP_MODULE_ENUM module, + enum UNIFIED_COLOR_FMT fmt, + unsigned int dstPitch, + unsigned int Height, + unsigned long dstAddress, DISP_BUFFER_TYPE sec, void *handle) +{ + unsigned int idx = wdma_index(module); + unsigned int idx_offst = idx * DISP_WDMA_INDEX_OFFSET; + unsigned int u_off = 0; + unsigned int v_off = 0; + unsigned int u_stride = 0; + unsigned int y_size = 0; + unsigned int u_size = 0; + unsigned int stride = dstPitch; + int has_v = 1; + + if (fmt != UFMT_YV12 && fmt != UFMT_I420 && fmt != UFMT_NV12 && fmt != UFMT_NV21) + return 0; + + if (fmt == UFMT_YV12) { + y_size = stride * Height; + u_stride = ALIGN_TO(stride / 2, 16); + u_size = u_stride * Height / 2; + u_off = y_size; + v_off = y_size + u_size; + } else if (fmt == UFMT_I420) { + y_size = stride * Height; + u_stride = ALIGN_TO(stride / 2, 16); + u_size = u_stride * Height / 2; + v_off = y_size; + u_off = y_size + u_size; + } else if (fmt == UFMT_NV12 || fmt == UFMT_NV21) { + y_size = stride * Height; + u_stride = stride / 2; + u_size = u_stride * Height / 2; + u_off = y_size; + has_v = 0; + } + + if (sec != DISP_SECURE_BUFFER) { + DISP_REG_SET(handle, idx_offst + DISP_REG_WDMA_DST_ADDR1, dstAddress + u_off); + if (has_v) + DISP_REG_SET(handle, idx_offst + DISP_REG_WDMA_DST_ADDR2, + dstAddress + v_off); + } else { + int m4u_port; + + m4u_port = idx == 0 ? M4U_PORT_DISP_WDMA0 : M4U_PORT_DISP_WDMA1; + + cmdqRecWriteSecure(handle, disp_addr_convert(idx_offst + DISP_REG_WDMA_DST_ADDR1), + CMDQ_SAM_H_2_MVA, dstAddress, u_off, u_size, m4u_port); + if (has_v) + cmdqRecWriteSecure(handle, + disp_addr_convert(idx_offst + DISP_REG_WDMA_DST_ADDR2), + CMDQ_SAM_H_2_MVA, dstAddress, v_off, u_size, m4u_port); + } + DISP_REG_SET_FIELD(handle, DST_W_IN_BYTE_FLD_DST_W_IN_BYTE, + idx_offst + DISP_REG_WDMA_DST_UV_PITCH, u_stride); + return 0; +} + +static int wdma_config(DISP_MODULE_ENUM module, + unsigned srcWidth, + unsigned srcHeight, + unsigned clipX, + unsigned clipY, + unsigned clipWidth, + unsigned clipHeight, + enum UNIFIED_COLOR_FMT out_format, + unsigned long dstAddress, + unsigned dstPitch, + unsigned int useSpecifiedAlpha, + unsigned char alpha, DISP_BUFFER_TYPE sec, void *handle) +{ + unsigned int idx = wdma_index(module); + unsigned int output_swap = ufmt_get_byteswap(out_format); + unsigned int is_rgb = ufmt_get_rgb(out_format); + unsigned int out_fmt_reg = ufmt_get_format(out_format); + int color_matrix = 0x2; /* 0010 RGB_TO_BT601 */ + unsigned int idx_offst = idx * DISP_WDMA_INDEX_OFFSET; + size_t size = dstPitch * clipHeight; + + DISPDBG("%s,src(w%d,h%d),clip(x%d,y%d,w%d,h%d),fmt=%s,addr=0x%lx,pitch=%d,s_alfa=%d,alpa=%d,hnd=0x%p,sec%d\n", + ddp_get_module_name(module), srcWidth, srcHeight, clipX, clipY, clipWidth, clipHeight, + unified_color_fmt_name(out_format), dstAddress, dstPitch, useSpecifiedAlpha, alpha, + handle, sec); + + /* should use OVL alpha instead of sw config */ + DISP_REG_SET(handle, idx_offst + DISP_REG_WDMA_SRC_SIZE, srcHeight << 16 | srcWidth); + DISP_REG_SET(handle, idx_offst + DISP_REG_WDMA_CLIP_COORD, clipY << 16 | clipX); + DISP_REG_SET(handle, idx_offst + DISP_REG_WDMA_CLIP_SIZE, clipHeight << 16 | clipWidth); + DISP_REG_SET_FIELD(handle, CFG_FLD_OUT_FORMAT, idx_offst + DISP_REG_WDMA_CFG, out_fmt_reg); + + if (!is_rgb) { + /* set DNSP for UYVY and YUV_3P format for better quality */ + wdma_config_yuv420(module, out_format, dstPitch, clipHeight, dstAddress, sec, + handle); + /*user internal matrix */ + DISP_REG_SET_FIELD(handle, CFG_FLD_EXT_MTX_EN, idx_offst + DISP_REG_WDMA_CFG, 0); + DISP_REG_SET_FIELD(handle, CFG_FLD_CT_EN, idx_offst + DISP_REG_WDMA_CFG, 1); + DISP_REG_SET_FIELD(handle, CFG_FLD_INT_MTX_SEL, idx_offst + DISP_REG_WDMA_CFG, + color_matrix); + } else { + DISP_REG_SET_FIELD(handle, CFG_FLD_EXT_MTX_EN, idx_offst + DISP_REG_WDMA_CFG, 0); + DISP_REG_SET_FIELD(handle, CFG_FLD_CT_EN, idx_offst + DISP_REG_WDMA_CFG, 0); + } + DISP_REG_SET_FIELD(handle, CFG_FLD_SWAP, idx_offst + DISP_REG_WDMA_CFG, output_swap); + if (sec != DISP_SECURE_BUFFER) { + DISP_REG_SET(handle, idx_offst + DISP_REG_WDMA_DST_ADDR0, dstAddress); + } else { + int m4u_port; + + m4u_port = idx == 0 ? M4U_PORT_DISP_WDMA0 : M4U_PORT_DISP_WDMA1; + + /* for sec layer, addr variable stores sec handle */ + /* we need to pass this handle and offset to cmdq driver */ + /* cmdq sec driver will help to convert handle to correct address */ + cmdqRecWriteSecure(handle, disp_addr_convert(idx_offst + DISP_REG_WDMA_DST_ADDR0), + CMDQ_SAM_H_2_MVA, dstAddress, 0, size, m4u_port); + } + DISP_REG_SET(handle, idx_offst + DISP_REG_WDMA_DST_W_IN_BYTE, dstPitch); + DISP_REG_SET_FIELD(handle, ALPHA_FLD_A_SEL, idx_offst + DISP_REG_WDMA_ALPHA, + useSpecifiedAlpha); + DISP_REG_SET_FIELD(handle, ALPHA_FLD_A_VALUE, idx_offst + DISP_REG_WDMA_ALPHA, alpha); + + return 0; +} + +static int wdma_clock_on(DISP_MODULE_ENUM module, void *handle) +{ + /* DISPMSG("wmda%d_clock_on\n",idx); */ + /* do not set CG */ +/* +#ifdef ENABLE_CLK_MGR +#ifdef CONFIG_MTK_CLKMGR + if (idx == 0) + enable_clock(MT_CG_DISP0_DISP_WDMA0, "WDMA0"); + else + enable_clock(MT_CG_DISP0_DISP_WDMA1, "WDMA1"); +#else + if (idx == 0) + ddp_clk_enable(DISP0_DISP_WDMA0); + else + ddp_clk_enable(DISP0_DISP_WDMA1); +#endif +#endif +*/ + /* DCM Setting -- Enable DCM */ + DISP_REG_MASK(NULL, DISP_REG_WDMA_EN, 0x80000000, 0x80000000); + return 0; +} + +static int wdma_clock_off(DISP_MODULE_ENUM module, void *handle) +{ + /* DISPMSG("wdma%d_clock_off\n",idx); */ + /* do not set CG */ +/* +#ifdef ENABLE_CLK_MGR +#ifdef CONFIG_MTK_CLKMGR + if (idx == 0) + disable_clock(MT_CG_DISP0_DISP_WDMA0, "WDMA0"); + else + disable_clock(MT_CG_DISP0_DISP_WDMA1, "WDMA1"); +#else + if (idx == 0) + ddp_clk_disable(DISP0_DISP_WDMA0); + else + ddp_clk_disable(DISP0_DISP_WDMA1); +#endif + +#endif +*/ + return 0; +} + +void wdma_dump_analysis(DISP_MODULE_ENUM module) +{ + unsigned int index = wdma_index(module); + unsigned int idx_offst = index * DISP_WDMA_INDEX_OFFSET; + + DISPDMP("==DISP WDMA%d ANALYSIS==\n", index); + DISPDMP("wdma%d:en=%d,w=%d,h=%d,clip=(%d,%d,%d,%d),pitch=(W=%d,UV=%d),addr=(0x%x,0x%x,0x%x),fmt=%s\n", + index, DISP_REG_GET(DISP_REG_WDMA_EN + idx_offst), + DISP_REG_GET(DISP_REG_WDMA_SRC_SIZE + idx_offst) & 0x3fff, + (DISP_REG_GET(DISP_REG_WDMA_SRC_SIZE + idx_offst) >> 16) & 0x3fff, + DISP_REG_GET(DISP_REG_WDMA_CLIP_COORD + idx_offst) & 0x3fff, + (DISP_REG_GET(DISP_REG_WDMA_CLIP_COORD + idx_offst) >> 16) & 0x3fff, + DISP_REG_GET(DISP_REG_WDMA_CLIP_SIZE + idx_offst) & 0x3fff, + (DISP_REG_GET(DISP_REG_WDMA_CLIP_SIZE + idx_offst) >> 16) & 0x3fff, + DISP_REG_GET(DISP_REG_WDMA_DST_W_IN_BYTE + idx_offst), + DISP_REG_GET(DISP_REG_WDMA_DST_UV_PITCH + idx_offst), + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR0 + idx_offst), + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR1 + idx_offst), + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR2 + idx_offst), + unified_color_fmt_name(display_fmt_reg_to_unified_fmt + ((DISP_REG_GET(DISP_REG_WDMA_CFG + idx_offst) >> 4) & 0xf, + (DISP_REG_GET(DISP_REG_WDMA_CFG + idx_offst) >> 11) & 0x1, 0)) + ); + DISPDMP("wdma%d:status=%s,in_req=%d(prev sent data),in_ack=%d(ask data to prev),exec=%d,in_pix=(L:%d,P:%d)\n", + index, + wdma_get_status(DISP_REG_GET_FIELD + (FLOW_CTRL_DBG_FLD_WDMA_STA_FLOW_CTRL, + DISP_REG_WDMA_FLOW_CTRL_DBG + idx_offst)), + DISP_REG_GET_FIELD(EXEC_DBG_FLD_WDMA_IN_REQ, + DISP_REG_WDMA_FLOW_CTRL_DBG + idx_offst), + DISP_REG_GET_FIELD(EXEC_DBG_FLD_WDMA_IN_ACK, + DISP_REG_WDMA_FLOW_CTRL_DBG + idx_offst), + DISP_REG_GET(DISP_REG_WDMA_EXEC_DBG + idx_offst) & 0x1f, + (DISP_REG_GET(DISP_REG_WDMA_CT_DBG + idx_offst) >> 16) & 0xffff, + DISP_REG_GET(DISP_REG_WDMA_CT_DBG + idx_offst) & 0xffff); + +} + +void wdma_dump_reg(DISP_MODULE_ENUM module) +{ + unsigned int idx = wdma_index(module); + unsigned int off_sft = idx * DISP_WDMA_INDEX_OFFSET; + + DISPDMP("== START: DISP WDMA%d REGS ==\n", idx); + DISPDMP("WDMA:0x000=0x%08x,0x004=0x%08x,0x008=0x%08x,0x00c=0x%08x\n", + DISP_REG_GET(DISP_REG_WDMA_INTEN + off_sft), + DISP_REG_GET(DISP_REG_WDMA_INTSTA + off_sft), + DISP_REG_GET(DISP_REG_WDMA_EN + off_sft), + DISP_REG_GET(DISP_REG_WDMA_RST + off_sft)); + + DISPDMP("WDMA:0x010=0x%08x,0x014=0x%08x,0x018=0x%08x,0x01c=0x%08x\n", + DISP_REG_GET(DISP_REG_WDMA_SMI_CON + off_sft), + DISP_REG_GET(DISP_REG_WDMA_CFG + off_sft), + DISP_REG_GET(DISP_REG_WDMA_SRC_SIZE + off_sft), + DISP_REG_GET(DISP_REG_WDMA_CLIP_SIZE + off_sft)); + + DISPDMP("WDMA:0x020=0x%08x,0x028=0x%08x,0x02c=0x%08x,0x038=0x%08x\n", + DISP_REG_GET(DISP_REG_WDMA_CLIP_COORD + off_sft), + DISP_REG_GET(DISP_REG_WDMA_DST_W_IN_BYTE + off_sft), + DISP_REG_GET(DISP_REG_WDMA_ALPHA + off_sft), + DISP_REG_GET(DISP_REG_WDMA_BUF_CON1 + off_sft)); + + DISPDMP("WDMA:0x03c=0x%08x,0x058=0x%08x,0x05c=0x%08x,0x060=0x%08x\n", + DISP_REG_GET(DISP_REG_WDMA_BUF_CON2 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_PRE_ADD0 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_PRE_ADD2 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_POST_ADD0 + off_sft)); + + DISPDMP("WDMA:0x064=0x%08x,0x078=0x%08x,0x080=0x%08x,0x084=0x%08x\n", + DISP_REG_GET(DISP_REG_WDMA_POST_ADD2 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_DST_UV_PITCH + off_sft), + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR_OFFSET0 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR_OFFSET1 + off_sft)); + + DISPDMP("WDMA:0x088=0x%08x,0x0a0=0x%08x,0x0a4=0x%08x,0x0a8=0x%08x\n", + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR_OFFSET2 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_FLOW_CTRL_DBG + off_sft), + DISP_REG_GET(DISP_REG_WDMA_EXEC_DBG + off_sft), + DISP_REG_GET(DISP_REG_WDMA_CT_DBG + off_sft)); + + DISPDMP("WDMA:0x0ac=0x%08x,0xf00=0x%08x,0xf04=0x%08x,0xf08=0x%08x,\n", + DISP_REG_GET(DISP_REG_WDMA_DEBUG + off_sft), + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR0 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR1 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_DST_ADDR2 + off_sft)); + +#ifdef __ENABLE_WDMA_PROC_TRACK__ + DISPDMP("WDMA:0x090=0x%08x,0x094=0x%08x,0x098=0x%08x\n", + DISP_REG_GET(DISP_REG_WDMA_PROC_TRACK_CON_0 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_PROC_TRACK_CON_1 + off_sft), + DISP_REG_GET(DISP_REG_WDMA_PROC_TRACK_CON_2 + off_sft)); + + void *emi_va = ioremap_nocache(0x10203000, 0x1000); + + DISPDMP("0x10203018 = 0x%08x\n", *(unsigned int *)(emi_va+0x18)); + iounmap(emi_va); +#endif + DISPDMP("-- END: DISP WDMA%d REGS --\n", idx); + +} + +static int wdma_dump(DISP_MODULE_ENUM module, int level) +{ + wdma_dump_analysis(module); + wdma_dump_reg(module); + + return 0; +} + +static int wdma_golden_setting(DISP_MODULE_ENUM module, enum dst_module_type dst_mod_type, + unsigned int width, unsigned int height, void *cmdq) +{ + unsigned int regval; + int wdma_idx = wdma_index(module); + unsigned long idx_offset = wdma_idx * DISP_WDMA_INDEX_OFFSET; + unsigned long res = width * height; + unsigned long res_HD = 720 * 1280; + /* DISP_REG_WDMA_BUF_CON1 */ + regval = 0; + if (dst_mod_type == DST_MOD_REAL_TIME) { + regval |= REG_FLD_VAL(BUF_CON1_FLD_ULTRA_ENABLE, 1); + regval |= REG_FLD_VAL(BUF_CON1_FLD_PRE_ULTRA_ENABLE, 1); + } else { + regval |= REG_FLD_VAL(BUF_CON1_FLD_ULTRA_ENABLE, 0); + regval |= REG_FLD_VAL(BUF_CON1_FLD_PRE_ULTRA_ENABLE, 0); + } + + if (dst_mod_type == DST_MOD_REAL_TIME) + regval |= REG_FLD_VAL(BUF_CON1_FLD_FRAME_END_ULTRA, 1); + else + regval |= REG_FLD_VAL(BUF_CON1_FLD_FRAME_END_ULTRA, 0); + + regval |= REG_FLD_VAL(BUF_CON1_FLD_ISSUE_REQ_TH, 64); + regval |= REG_FLD_VAL(BUF_CON1_FLD_FIFO_PSEUDO_SIZE, 256); + + DISP_REG_SET(cmdq, idx_offset + DISP_REG_WDMA_BUF_CON1, regval); + + /* DISP_REG_WDMA_BUF_CON2 */ + regval = 0; + if (res > res_HD) + regval |= REG_FLD_VAL(BUF_CON2_FLD_ULTRA_TH_HIGH_OFS, 45); + else + regval |= REG_FLD_VAL(BUF_CON2_FLD_ULTRA_TH_HIGH_OFS, 20); + + regval |= REG_FLD_VAL(BUF_CON2_FLD_PRE_ULTRA_TH_HIGH_OFS, 1); + + if (res > res_HD) + regval |= REG_FLD_VAL(BUF_CON2_FLD_ULTRA_TH_LOW_OFS, 24); + else + regval |= REG_FLD_VAL(BUF_CON2_FLD_ULTRA_TH_LOW_OFS, 10); + + if (res > res_HD) + regval |= REG_FLD_VAL(BUF_CON2_FLD_PRE_ULTRA_TH_LOW, 93); + else + regval |= REG_FLD_VAL(BUF_CON2_FLD_PRE_ULTRA_TH_LOW, 184); + + DISP_REG_SET(cmdq, idx_offset + DISP_REG_WDMA_BUF_CON2, regval); + +#ifdef __ENABLE_WDMA_PROC_TRACK__ + /* WDMA proc track */ + regval = 0; + if (dst_mod_type == DST_MOD_REAL_TIME) { + DISP_REG_SET(cmdq, idx_offset + DISP_REG_WDMA_PROC_TRACK_CON_0, 0); + DISP_REG_SET(cmdq, idx_offset + DISP_REG_WDMA_PROC_TRACK_CON_1, 0); + DISP_REG_SET(cmdq, idx_offset + DISP_REG_WDMA_PROC_TRACK_CON_2, 0); + cmdqRecWrite(cmdq, 0x10203018, 0, 0xffff0000); + } else { + regval |= REG_FLD_VAL(FLD_WDMA_PROC_TRACK_CON0_IGNORE_INIT_LEGECY, 1); + regval |= REG_FLD_VAL(FLD_WDMA_PROC_TRACK_CON0_STOP_GREQ_EN, 1); + regval |= REG_FLD_VAL(FLD_WDMA_PROC_TRACK_CON0_PREULTRA_EN, 1); + regval |= REG_FLD_VAL(FLD_WDMA_PROC_TRACK_CON0_TRACK_WND, 256); + + DISP_REG_SET(cmdq, idx_offset + DISP_REG_WDMA_PROC_TRACK_CON_0, regval); + DISP_REG_SET(cmdq, idx_offset + DISP_REG_WDMA_PROC_TRACK_CON_1, 0x8000); + DISP_REG_SET(cmdq, idx_offset + DISP_REG_WDMA_PROC_TRACK_CON_2, 3*0x8000); + cmdqRecWrite(cmdq, 0x10203018, 0xffff0000, 0xffff0000); + } +#endif + return 0; +} + + +static int wdma_check_input_param(WDMA_CONFIG_STRUCT *config) +{ + if (!is_unified_color_fmt_supported(config->outputFormat)) { + DISPERR("wdma parameter invalidate outfmt %s:0x%x\n", + unified_color_fmt_name(config->outputFormat), config->outputFormat); + return -1; + } + + if (config->dstAddress == 0 || config->srcWidth == 0 || config->srcHeight == 0) { + DISPERR("wdma parameter invalidate, addr=0x%lx, w=%d, h=%d\n", + config->dstAddress, config->srcWidth, config->srcHeight); + return -1; + } + return 0; +} + +static int wdma_is_sec[2]; + +static inline int wdma_switch_to_sec(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int wdma_idx = wdma_index(module); + /*int *wdma_is_sec = svp_pgc->module_sec.wdma_sec;*/ + CMDQ_ENG_ENUM cmdq_engine; + CMDQ_EVENT_ENUM cmdq_event; + + cmdq_engine = wdma_to_cmdq_engine(module); + cmdq_event = wdma_idx == 0 ? CMDQ_EVENT_DISP_WDMA0_EOF : CMDQ_EVENT_DISP_WDMA1_EOF; + + cmdqRecSetSecure(handle, 1); + /* set engine as sec */ + cmdqRecSecureEnablePortSecurity(handle, (1LL << cmdq_engine)); + cmdqRecSecureEnableDAPC(handle, (1LL << cmdq_engine)); + if (wdma_is_sec[wdma_idx] == 0) { + DISPMSG("[SVP] switch wdma%d to sec\n", wdma_idx); + /*MMProfileLogEx(ddp_mmp_get_events()->svp_module[module], + MMProfileFlagStart, 0, 0);*/ + /*MMProfileLogEx(ddp_mmp_get_events()->svp_module[module], + MMProfileFlagPulse, wdma_idx, 1);*/ + } + wdma_is_sec[wdma_idx] = 1; + + return 0; +} + +static inline int wdma_switch_to_nonsec(DISP_MODULE_ENUM module, void *handle) +{ + unsigned int wdma_idx = wdma_index(module); + /*int *wdma_is_sec = svp_pgc->module_sec.wdma_sec;*/ + + CMDQ_ENG_ENUM cmdq_engine; + CMDQ_EVENT_ENUM cmdq_event; + CMDQ_EVENT_ENUM cmdq_event_nonsec_end; + + cmdq_engine = wdma_to_cmdq_engine(module); + cmdq_event = wdma_idx == 0 ? CMDQ_EVENT_DISP_WDMA0_EOF : CMDQ_EVENT_DISP_WDMA1_EOF; + cmdq_event_nonsec_end = wdma_to_cmdq_event_nonsec_end(module); + + if (wdma_is_sec[wdma_idx] == 1) { + /* wdma is in sec stat, we need to switch it to nonsec */ + cmdqRecHandle nonsec_switch_handle; + int ret; + + ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_PRIMARY_DISABLE_SECURE_PATH, + &(nonsec_switch_handle)); + if (ret) + DISPAEE("[SVP]fail to create disable handle %s ret=%d\n", + __func__, ret); + + cmdqRecReset(nonsec_switch_handle); + + if (wdma_idx == 0) { + /*Primary Mode*/ + if (primary_display_is_decouple_mode()) + cmdqRecWaitNoClear(nonsec_switch_handle, cmdq_event); + else + _cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle); + } else { + /*External Mode*/ + /*ovl1->wdma1*/ + /*_cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle);*/ + cmdqRecWaitNoClear(nonsec_switch_handle, CMDQ_SYNC_DISP_EXT_STREAM_EOF); + } + + /*_cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle);*/ + cmdqRecSetSecure(nonsec_switch_handle, 1); + + /*in fact, dapc/port_sec will be disabled by cmdq */ + cmdqRecSecureEnablePortSecurity(nonsec_switch_handle, (1LL << cmdq_engine)); + cmdqRecSecureEnableDAPC(nonsec_switch_handle, (1LL << cmdq_engine)); + if (handle != NULL) { + /*Async Flush method*/ + cmdqRecSetEventToken(nonsec_switch_handle, cmdq_event_nonsec_end); + cmdqRecFlushAsync(nonsec_switch_handle); + cmdqRecWait(handle, cmdq_event_nonsec_end); + } else { + /*Sync Flush method*/ + cmdqRecFlush(nonsec_switch_handle); + } + cmdqRecDestroy(nonsec_switch_handle); + DISPMSG("[SVP] switch wdma%d to nonsec\n", wdma_idx); + /*MMProfileLogEx(ddp_mmp_get_events()->svp_module[module], + MMProfileFlagEnd, 0, 0);*/ + /*MMProfileLogEx(ddp_mmp_get_events()->svp_module[module], + MMProfileFlagPulse, wdma_idx, 0);*/ + } + wdma_is_sec[wdma_idx] = 0; + + return 0; +} + +static int setup_wdma_sec(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle) +{ + int ret; + int is_engine_sec = 0; + + if (pConfig->wdma_config.security == DISP_SECURE_BUFFER) + is_engine_sec = 1; + + if (!handle) { + DISPDBG("[SVP] bypass wdma sec setting sec=%d,handle=NULL\n", is_engine_sec); + return 0; + } + + if (is_engine_sec == 1) + ret = wdma_switch_to_sec(module, handle); + else + ret = wdma_switch_to_nonsec(module, NULL); + if (ret) + DISPAEE("[SVP]fail to setup_ovl_sec: %s ret=%d\n", + __func__, ret); + + return is_engine_sec; +} + +static int wdma_config_l(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle) +{ + + WDMA_CONFIG_STRUCT *config = &pConfig->wdma_config; + + if (!pConfig->wdma_dirty) + return 0; + + setup_wdma_sec(module, pConfig, handle); + + if (wdma_check_input_param(config) == 0) { + enum dst_module_type dst_mod_type; + + wdma_config(module, + config->srcWidth, + config->srcHeight, + config->clipX, + config->clipY, + config->clipWidth, + config->clipHeight, + config->outputFormat, + config->dstAddress, + config->dstPitch, + config->useSpecifiedAlpha, config->alpha, config->security, handle); + + dst_mod_type = dpmgr_path_get_dst_module_type(pConfig->path_handle); + wdma_golden_setting(module, dst_mod_type, config->srcWidth, config->srcHeight, handle); + } + return 0; +} + +unsigned int ddp_wdma_get_cur_addr(void) +{ + return INREG32(DISP_REG_WDMA_DST_ADDR0); +} + +DDP_MODULE_DRIVER ddp_driver_wdma = { + .module = DISP_MODULE_WDMA0, + .init = wdma_clock_on, + .deinit = wdma_clock_off, + .config = wdma_config_l, + .start = wdma_start, + .trigger = NULL, + .stop = wdma_stop, + .reset = wdma_reset, + .power_on = wdma_clock_on, + .power_off = wdma_clock_off, + .is_idle = NULL, + .is_busy = NULL, + .dump_info = wdma_dump, + .bypass = NULL, + .build_cmdq = NULL, + .set_lcm_utils = NULL, +}; diff --git a/drivers/misc/mediatek/video/mt6755/ddp_wdma.h b/drivers/misc/mediatek/video/mt6755/ddp_wdma.h new file mode 100644 index 0000000000000000000000000000000000000000..b6bfbdc8705ba1e4e4c7e83c9f1822aede5bddec --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/ddp_wdma.h @@ -0,0 +1,31 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#ifndef _DDP_WDMA_API_H_ +#define _DDP_WDMA_API_H_ + +#include "ddp_hal.h" +#include "ddp_info.h" + +#define WDMA_INSTANCES 2 +#define WDMA_MAX_WIDTH 1920 +#define WDMA_MAX_HEIGHT 1080 + +enum WDMA_INPUT_FORMAT { + WDMA_INPUT_FORMAT_ARGB = 0x00, /* from overlay */ + WDMA_INPUT_FORMAT_YUV444 = 0x01, /* from direct link */ +}; + +void wdma_dump_analysis(DISP_MODULE_ENUM module); +void wdma_dump_reg(DISP_MODULE_ENUM module); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/disp_assert_layer.c b/drivers/misc/mediatek/video/mt6755/disp_assert_layer.c new file mode 100644 index 0000000000000000000000000000000000000000..1eba1e8ff1fa06605bdcff7853f754d617a911a7 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_assert_layer.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include "primary_display.h" +#include "ddp_hal.h" +#include "disp_log.h" +#include "disp_assert_layer.h" +#include +#include +#include "ddp_mmp.h" +#include "disp_drv_platform.h" +#include "disp_session.h" +#include +#include +#include +#include +#include + +/* /common part */ +#define DAL_BPP (2) +#define DAL_WIDTH (DISP_GetScreenWidth()) +#define DAL_HEIGHT (DISP_GetScreenHeight()) + +#ifdef CONFIG_MTK_FB_SUPPORT_ASSERTION_LAYER +/* #if defined(CONFIG_MTK_FB_SUPPORT_ASSERTION_LAYER) */ + +#include "mtkfb_console.h" + +/* --------------------------------------------------------------------------- */ +#define DAL_FORMAT (DISP_FORMAT_RGB565) +#define DAL_BG_COLOR (dal_bg_color) +#define DAL_FG_COLOR (dal_fg_color) + +#define RGB888_To_RGB565(x) ((((x) & 0xF80000) >> 8) | \ + (((x) & 0x00FC00) >> 5) | \ + (((x) & 0x0000F8) >> 3)) + +#define MAKE_TWO_RGB565_COLOR(high, low) (((low) << 16) | (high)) + +DEFINE_SEMAPHORE(dal_sem); +inline DAL_STATUS DAL_LOCK(void) +{ + if (down_interruptible(&dal_sem)) { + DISPMSG("Can't get semaphore in %s()\n", + __func__); + return DAL_STATUS_LOCK_FAIL; + } + return DAL_STATUS_OK; +} + +#define DAL_UNLOCK() up(&dal_sem) + + +inline MFC_STATUS DAL_CHECK_MFC_RET(MFC_STATUS expr) +{ + MFC_STATUS ret = expr; + + if (MFC_STATUS_OK != ret) { + DISPMSG("Warning: call MFC_XXX function failed in %s(), line: %d, ret: %x\n", + __func__, __LINE__, ret); + return ret; + } + return MFC_STATUS_OK; +} + + +inline DISP_STATUS DAL_CHECK_DISP_RET(DISP_STATUS expr) +{ + DISP_STATUS ret = (expr); + + if (DISP_STATUS_OK != ret) { + DISPMSG("Warning: call DISP_XXX function failed in %s(), line: %d, ret: %x\n", + __func__, __LINE__, ret); + return ret; + } + return DISP_STATUS_OK; +} + +#define DAL_LOG(fmt, arg...) \ + DISPMSG(fmt, ##arg) +/* --------------------------------------------------------------------------- */ + +static MFC_HANDLE mfc_handle; +static void *dal_fb_addr; +static unsigned long dal_fb_pa; + +/*static BOOL dal_enable_when_resume = FALSE;*/ +static bool dal_disable_when_resume; +static unsigned int dal_fg_color = RGB888_To_RGB565(DAL_COLOR_WHITE); +static unsigned int dal_bg_color = RGB888_To_RGB565(DAL_COLOR_RED); +static char dal_print_buffer[1024]; + +bool dal_shown = false; +unsigned int isAEEEnabled = 0; + +/* --------------------------------------------------------------------------- */ + + +uint32_t DAL_GetLayerSize(void) +{ + /* avoid lcdc read buffersize+1 issue */ + return DAL_WIDTH * DAL_HEIGHT * DAL_BPP + 4096; +} +/* +static DAL_STATUS DAL_SetRedScreen(uint32_t *addr) +{ + uint32_t i; + const uint32_t BG_COLOR = MAKE_TWO_RGB565_COLOR(DAL_BG_COLOR, DAL_BG_COLOR); + + for (i = 0; i < DAL_GetLayerSize() / sizeof(uint32_t); ++i) + *addr++ = BG_COLOR; + return DAL_STATUS_OK; +} +*/ +DAL_STATUS DAL_SetScreenColor(DAL_COLOR color) +{ + uint32_t i; + uint32_t size; + uint32_t BG_COLOR; + MFC_CONTEXT *ctxt = NULL; + uint32_t offset; + unsigned int *addr; + + color = RGB888_To_RGB565(color); + BG_COLOR = MAKE_TWO_RGB565_COLOR(color, color); + + ctxt = (MFC_CONTEXT *) mfc_handle; + if (!ctxt) + return DAL_STATUS_FATAL_ERROR; + if (ctxt->screen_color == color) + return DAL_STATUS_OK; + offset = MFC_Get_Cursor_Offset(mfc_handle); + addr = (unsigned int *)(ctxt->fb_addr + offset); + + size = DAL_GetLayerSize() - offset; + for (i = 0; i < size / sizeof(uint32_t); ++i) + *addr++ = BG_COLOR; + ctxt->screen_color = color; + + return DAL_STATUS_OK; +} +EXPORT_SYMBOL(DAL_SetScreenColor); + +DAL_STATUS DAL_Init(unsigned long layerVA, unsigned long layerPA) +{ + pr_debug("%s, layerVA=0x%lx, layerPA=0x%lx\n", __func__, layerVA, layerPA); + + dal_fb_addr = (void *)layerVA; + dal_fb_pa = layerPA; + DAL_CHECK_MFC_RET(MFC_Open(&mfc_handle, dal_fb_addr, + DAL_WIDTH, DAL_HEIGHT, DAL_BPP, DAL_FG_COLOR, DAL_BG_COLOR)); + /* DAL_Clean(); */ + DAL_SetScreenColor(DAL_COLOR_RED); + + return DAL_STATUS_OK; +} + +DAL_STATUS DAL_SetColor(unsigned int fgColor, unsigned int bgColor) +{ + if (NULL == mfc_handle) + return DAL_STATUS_NOT_READY; + + DAL_LOCK(); + dal_fg_color = RGB888_To_RGB565(fgColor); + dal_bg_color = RGB888_To_RGB565(bgColor); + DAL_CHECK_MFC_RET(MFC_SetColor(mfc_handle, dal_fg_color, dal_bg_color)); + DAL_UNLOCK(); + + return DAL_STATUS_OK; +} +EXPORT_SYMBOL(DAL_SetColor); + +DAL_STATUS DAL_Dynamic_Change_FB_Layer(unsigned int isAEEEnabled) +{ + return DAL_STATUS_OK; +} +static int show_dal_layer(int enable) +{ + disp_session_input_config *session_input; + disp_input_config *input; + int ret; + + session_input = kzalloc(sizeof(*session_input), GFP_KERNEL); + if (!session_input) + return -ENOMEM; + + session_input->setter = SESSION_USER_AEE; + session_input->config_layer_num = 1; + input = &session_input->config[0]; + + input->src_phy_addr = (void *)dal_fb_pa; + input->layer_id = primary_display_get_option("ASSERT_LAYER"); + input->layer_enable = enable; + input->src_offset_x = 0; + input->src_offset_y = 0; + input->src_width = DAL_WIDTH; + input->src_height = DAL_HEIGHT; + input->tgt_offset_x = 0; + input->tgt_offset_y = 0; + input->tgt_width = DAL_WIDTH; + input->tgt_height = DAL_HEIGHT; + input->alpha = 0x80; + input->alpha_enable = 1; + input->next_buff_idx = -1; + input->src_pitch = DAL_WIDTH; + input->src_fmt = DAL_FORMAT; + input->next_buff_idx = -1; + + ret = primary_display_config_input_multiple(session_input); + kfree(session_input); + return ret; +} + + +DAL_STATUS DAL_Clean(void) +{ + /* const uint32_t BG_COLOR = MAKE_TWO_RGB565_COLOR(DAL_BG_COLOR, DAL_BG_COLOR); */ + DAL_STATUS ret = DAL_STATUS_OK; + + static int dal_clean_cnt; + MFC_CONTEXT *ctxt = (MFC_CONTEXT *) mfc_handle; + + pr_err("[MTKFB_DAL] DAL_Clean\n"); + if (NULL == mfc_handle) + return DAL_STATUS_NOT_READY; + + + MMProfileLogEx(ddp_mmp_get_events()->dal_clean, MMProfileFlagStart, 0, 0); + DAL_LOCK(); + if (MFC_STATUS_OK != MFC_ResetCursor(mfc_handle)) { + pr_err("mfc_handle = %p\n", mfc_handle); + goto End; + } + ctxt->screen_color = 0; + DAL_SetScreenColor(DAL_COLOR_RED); + + + /* TODO: if dal_shown=false, and 3D enabled, mtkfb may disable UI layer, please modify 3D driver */ + if (isAEEEnabled == 1) { + show_dal_layer(0); + /* DAL disable, switch UI layer to default layer 3 */ + pr_err("[DDP]* isAEEEnabled from 1 to 0, %d\n", dal_clean_cnt++); + isAEEEnabled = 0; + DAL_Dynamic_Change_FB_Layer(isAEEEnabled); /* restore UI layer to DEFAULT_UI_LAYER */ + primary_display_trigger(0, NULL, 0); + } + + dal_shown = false; + dal_disable_when_resume = false; + + /*primary_display_trigger(0, NULL, 0);*/ + + +End: + DAL_UNLOCK(); + MMProfileLogEx(ddp_mmp_get_events()->dal_clean, MMProfileFlagEnd, 0, 0); + return ret; +} +EXPORT_SYMBOL(DAL_Clean); + +int is_DAL_Enabled(void) +{ + int ret = 0; + + ret = isAEEEnabled; + return ret; +} + +DAL_STATUS DAL_Printf(const char *fmt, ...) +{ + va_list args; + uint i; + DAL_STATUS ret = DAL_STATUS_OK; + + + /* printk("[MTKFB_DAL] DAL_Printf mfc_handle=0x%08X, fmt=0x%08X\n", mfc_handle, fmt); */ + + DISPFUNC(); + + if (NULL == mfc_handle) + return DAL_STATUS_NOT_READY; + + if (NULL == fmt) + return DAL_STATUS_INVALID_ARGUMENT; + + MMProfileLogEx(ddp_mmp_get_events()->dal_printf, MMProfileFlagStart, 0, 0); + DAL_LOCK(); +#if 0 + if (isAEEEnabled == 0) { + pr_err("[DDP] isAEEEnabled from 0 to 1, ASSERT_LAYER=%d, dal_fb_pa %lx\n", + primary_display_get_option("ASSERT_LAYER"), dal_fb_pa); + + isAEEEnabled = 1; + DAL_Dynamic_Change_FB_Layer(isAEEEnabled); /* default_ui_ layer coniig to changed_ui_layer */ + + DAL_CHECK_MFC_RET(MFC_Open(&mfc_handle, dal_fb_addr, + DAL_WIDTH, DAL_HEIGHT, DAL_BPP, + DAL_FG_COLOR, DAL_BG_COLOR)); + show_dal_layer(1); + } +#else + { + pr_err("[DDP] isAEEEnabled %d ASSERT_LAYER=%d, dal_fb_pa %lx\n", + isAEEEnabled, primary_display_get_option("ASSERT_LAYER"), dal_fb_pa); + + if (isAEEEnabled == 0) { + isAEEEnabled = 1; + DAL_Dynamic_Change_FB_Layer(isAEEEnabled); + } + show_dal_layer(1); + } +#endif + va_start(args, fmt); + i = vsprintf(dal_print_buffer, fmt, args); + BUG_ON(i >= ARRAY_SIZE(dal_print_buffer)); + va_end(args); + DAL_CHECK_MFC_RET(MFC_Print(mfc_handle, dal_print_buffer)); + + flush_cache_all(); + + + if (!dal_shown) + dal_shown = true; + + ret = primary_display_trigger(0, NULL, 0); + + + DAL_UNLOCK(); + + MMProfileLogEx(ddp_mmp_get_events()->dal_printf, MMProfileFlagEnd, 0, 0); + + return ret; +} +EXPORT_SYMBOL(DAL_Printf); + + +DAL_STATUS DAL_OnDispPowerOn(void) +{ + return DAL_STATUS_OK; +} + +/* ########################################################################## */ +/* !CONFIG_MTK_FB_SUPPORT_ASSERTION_LAYER */ +/* ########################################################################## */ +#else +unsigned int isAEEEnabled = 0; + +uint32_t DAL_GetLayerSize(void) +{ + /* xuecheng, avoid lcdc read buffersize+1 issue */ + return DAL_WIDTH * DAL_HEIGHT * DAL_BPP + 4096; +} + +DAL_STATUS DAL_Init(unsigned long layerVA, unsigned long layerPA) +{ + NOT_REFERENCED(layerVA); + NOT_REFERENCED(layerPA); + + return DAL_STATUS_OK; +} + +DAL_STATUS DAL_SetColor(unsigned int fgColor, unsigned int bgColor) +{ + NOT_REFERENCED(fgColor); + NOT_REFERENCED(bgColor); + + return DAL_STATUS_OK; +} +EXPORT_SYMBOL(DAL_SetColor); + +DAL_STATUS DAL_Clean(void) +{ + pr_err("[MTKFB_DAL] DAL_Clean is not implemented\n"); + return DAL_STATUS_OK; +} +EXPORT_SYMBOL(DAL_Clean); + +DAL_STATUS DAL_Printf(const char *fmt, ...) +{ + NOT_REFERENCED(fmt); + pr_err("[MTKFB_DAL] DAL_Printf is not implemented\n"); + return DAL_STATUS_OK; +} +EXPORT_SYMBOL(DAL_Printf); + +DAL_STATUS DAL_OnDispPowerOn(void) +{ + return DAL_STATUS_OK; +} + +DAL_STATUS DAL_SetScreenColor(DAL_COLOR color) +{ + return DAL_STATUS_OK; +} +EXPORT_SYMBOL(DAL_SetScreenColor); + +int is_DAL_Enabled(void) +{ + return 0; +} + +#endif /* CONFIG_MTK_FB_SUPPORT_ASSERTION_LAYER */ diff --git a/drivers/misc/mediatek/video/mt6755/disp_assert_layer.h b/drivers/misc/mediatek/video/mt6755/disp_assert_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..c86cdfb1d8387d3604f27625931a220cc4b374cb --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_assert_layer.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DISP_ASSERT_LAYER_H__ +#define __DISP_ASSERT_LAYER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + typedef enum { + DAL_STATUS_OK = 0, + + DAL_STATUS_NOT_READY = -1, + DAL_STATUS_INVALID_ARGUMENT = -2, + DAL_STATUS_LOCK_FAIL = -3, + DAL_STATUS_LCD_IN_SUSPEND = -4, + DAL_STATUS_FATAL_ERROR = -10, + } DAL_STATUS; + + + typedef enum { + DAL_COLOR_BLACK = 0x000000, + DAL_COLOR_WHITE = 0xFFFFFF, + DAL_COLOR_RED = 0xFF0000, + DAL_COLOR_GREEN = 0x00FF00, + DAL_COLOR_BLUE = 0x0000FF, + DAL_COLOR_TURQUOISE = (DAL_COLOR_GREEN | DAL_COLOR_BLUE), + DAL_COLOR_YELLOW = (DAL_COLOR_RED | DAL_COLOR_GREEN), + DAL_COLOR_PINK = (DAL_COLOR_RED | DAL_COLOR_BLUE), + } DAL_COLOR; + + +/* Display Assertion Layer API */ + + unsigned int DAL_GetLayerSize(void); + DAL_STATUS DAL_SetScreenColor(DAL_COLOR color); + DAL_STATUS DAL_Init(unsigned long layerVA, unsigned long layerPA); + DAL_STATUS DAL_SetColor(unsigned int fgColor, unsigned int bgColor); + DAL_STATUS DAL_Clean(void); + DAL_STATUS DAL_Printf(const char *fmt, ...); + DAL_STATUS DAL_OnDispPowerOn(void); + DAL_STATUS DAL_LowMemoryOn(void); + DAL_STATUS DAL_LowMemoryOff(void); + int is_DAL_Enabled(void); + +#ifdef __cplusplus +} +#endif +#endif /* __DISP_ASSERT_LAYER_H__ */ diff --git a/drivers/misc/mediatek/video/mt6755/disp_debug.c b/drivers/misc/mediatek/video/mt6755/disp_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..61557c4daa0b8196600da985b976b114a09b0b83 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_debug.c @@ -0,0 +1,981 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MTK_LEGACY +#include +#include +#else +#include "disp_dts_gpio.h" +#endif + +#include "m4u.h" +#include "cmdq_def.h" +#include "cmdq_record.h" +#include "cmdq_reg.h" +#include "cmdq_core.h" + +#include "lcm_drv.h" +#include "ddp_path.h" +#include "ddp_reg.h" +#include "ddp_drv.h" +#include "ddp_wdma.h" +#include "ddp_hal.h" +#include "ddp_aal.h" +#include "ddp_pwm.h" +#include "ddp_dither.h" +#include "ddp_info.h" +#include "ddp_dsi.h" +#include "ddp_rdma.h" +#include "ddp_manager.h" +#include "ddp_met.h" +#include "disp_log.h" +#include "disp_debug.h" +#include "disp_helper.h" +#include "disp_drv_ddp.h" +#include "disp_recorder.h" +#include "disp_session.h" +#include "disp_lowpower.h" +#include "disp_recovery.h" +#include "disp_assert_layer.h" +#include "mtkfb.h" +#include "mtkfb_fence.h" +#include "mtkfb_debug.h" +#include "primary_display.h" + +#pragma GCC optimize("O0") + +/* --------------------------------------------------------------------------- */ +/* Global variable declarations */ +/* --------------------------------------------------------------------------- */ +char DDP_STR_HELP[] = + "USAGE:\n" + " echo [ACTION]>/d/dispsys\n" + "ACTION:\n" + " regr:addr\n :regr:0xf400c000\n" + " regw:addr,value :regw:0xf400c000,0x1\n" + " dbg_log:0|1|2 :0 off, 1 dbg, 2 all\n" + " irq_log:0|1 :0 off, !0 on\n" + " met_on:[0|1],[0|1],[0|1] :fist[0|1]on|off,other [0|1]direct|decouple\n" + " backlight:level\n" + " dump_aal:arg\n" + " mmp\n" + " dump_reg:moduleID\n" + " dump_path:mutexID\n" + " dpfd_ut1:channel\n"; + +char MTKFB_STR_HELP[] = + "\n" + "USAGE\n" + " echo [ACTION]... > /d/mtkfb\n" + "\n" + "ACTION\n" + " mtkfblog:[on|off]\n" + " enable/disable [MTKFB] log\n" + "\n" + " displog:[on|off]\n" + " enable/disable [DISP] log\n" + "\n" + " mtkfb_vsynclog:[on|off]\n" + " enable/disable [VSYNC] log\n" + "\n" + " log:[on|off]\n" + " enable/disable above all log\n" + "\n" + " fps:[on|off]\n" + " enable fps and lcd update time log\n" + "\n" + " tl:[on|off]\n" + " enable touch latency log\n" + "\n" + " layer\n" + " dump lcd layer information\n" + "\n" + " suspend\n" + " enter suspend mode\n" + "\n" + " resume\n" + " leave suspend mode\n" + "\n" + " lcm:[on|off|init]\n" + " power on/off lcm\n" + "\n" + " cabc:[ui|mov|still]\n" + " cabc mode, UI/Moving picture/Still picture\n" + "\n" + " lcd:[on|off]\n" + " power on/off display engine\n" + "\n" + " te:[on|off]\n" + " turn on/off tearing-free control\n" + "\n" + " tv:[on|off]\n" + " turn on/off tv-out\n" + "\n" + " tvsys:[ntsc|pal]\n" + " switch tv system\n" + "\n" + " reg:[lcd|dpi|dsi|tvc|tve]\n" + " dump hw register values\n" + "\n" + " regw:addr=val\n" + " write hw register\n" + "\n" + " regr:addr\n" + " read hw register\n" + "\n" + " cpfbonly:[on|off]\n" + " capture UI layer only on/off\n" + "\n" + " esd:[on|off]\n" + " esd kthread on/off\n" + " HQA:[NormalToFactory|FactoryToNormal]\n" + " for HQA requirement\n" + "\n" + " mmp\n" + " Register MMProfile events\n" + "\n" + " dump_fb:[on|off[,down_sample_x[,down_sample_y,[delay]]]]\n" + " Start/end to capture framebuffer every delay(ms)\n" + "\n" + " dump_ovl:[on|off[,down_sample_x[,down_sample_y]]]\n" + " Start to capture OVL only once\n" + "\n" + " dump_layer:[on|off[,down_sample_x[,down_sample_y]][,layer(0:L0,1:L1,2:L2,3:L3,4:L0-3)]\n" + " Start/end to capture current enabled OVL layer every frame\n"; + +/* --------------------------------------------------------------------------- */ +/* Local variable declarations */ +/* --------------------------------------------------------------------------- */ +static struct dentry *lowpowermode_debugfs; +static struct dentry *kickdump_debugfs; +static int low_power_cust_mode = LP_CUST_DISABLE; +static unsigned int vfp_backup; +static char LP_CUST_STR_HELP[] = + "USAGE:\n" + " echo [ACTION]>/d/disp/lowpowermode\n" + "ACTION:\n" + " low_power_mode:Mode\n" + " Mode:0(LP_CUST_DISABLE)|1(LOW_POWER_MODE)|2(JUST_MAKE_MODE)|3(PERFORMANC_MODE)\n"; + +/* --------------------------------------------------------------------------- */ +/* DDP and MTKFB Command Processor */ +/* --------------------------------------------------------------------------- */ +void ddp_process_dbg_opt(const char *opt) +{ + int ret = 0; + char *buf = dbg_buf + strlen(dbg_buf); + + if (0 == strncmp(opt, "regr:", 5)) { + char *p = (char *)opt + 5; + unsigned long addr = 0; + + ret = kstrtoul(p, 16, &addr); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + if (is_reg_addr_valid(1, addr) == 1) { + unsigned int regVal = DISP_REG_GET(addr); + + DISPMSG("regr: 0x%lx = 0x%08X\n", addr, regVal); + sprintf(buf, "regr: 0x%lx = 0x%08X\n", addr, regVal); + } else { + sprintf(buf, "regr, invalid address 0x%lx\n", addr); + goto Error; + } + } else if (0 == strncmp(opt, "lfr_update", 3)) { + DSI_LFR_UPDATE(DISP_MODULE_DSI0, NULL); + } else if (0 == strncmp(opt, "regw:", 5)) { + unsigned long addr; + unsigned int val; + + ret = sscanf(opt, "regw:0x%lx,0x%x\n", &addr, &val); + if (ret != 2) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + if (is_reg_addr_valid(1, addr) == 1) { + unsigned int regVal; + + DISP_CPU_REG_SET(addr, val); + regVal = DISP_REG_GET(addr); + DISPMSG("regw: 0x%lx, 0x%08X = 0x%08X\n", addr, val, regVal); + sprintf(buf, "regw: 0x%lx, 0x%08X = 0x%08X\n", addr, val, regVal); + } else { + sprintf(buf, "regw, invalid address 0x%lx\n", addr); + goto Error; + } + } else if (0 == strncmp(opt, "dbg_log:", 8)) { + char *p = (char *)opt + 8; + unsigned int enable; + + ret = kstrtouint(p, 0, &enable); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + if (enable) { + dbg_log_level = 1; + g_fencelog = 1; + g_loglevel = 5; + } else { + dbg_log_level = 0; + g_fencelog = 0; + g_loglevel = 3; + } + + sprintf(buf, "dbg_log: %d\n", dbg_log_level); + } else if (0 == strncmp(opt, "irq_log:", 8)) { + char *p = (char *)opt + 8; + unsigned int enable; + + ret = kstrtouint(p, 0, &enable); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + if (enable) { + irq_log_level = 1; + g_loglevel = 6; + } else { + irq_log_level = 0; + g_loglevel = 3; + } + + sprintf(buf, "irq_log: %d\n", irq_log_level); + } else if (0 == strncmp(opt, "met_on:", 7)) { + int met_on, rdma0_mode, rdma1_mode; + + ret = sscanf(opt, "met_on:%d,%d,%d\n", &met_on, &rdma0_mode, &rdma1_mode); + if (ret != 3) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + ddp_init_met_tag(met_on, rdma0_mode, rdma1_mode); + DISPMSG("process_dbg_opt, met_on=%d,rdma0_mode %d, rdma1 %d\n", met_on, rdma0_mode, + rdma1_mode); + sprintf(buf, "met_on:%d,rdma0_mode:%d,rdma1_mode:%d\n", met_on, rdma0_mode, + rdma1_mode); + } else if (0 == strncmp(opt, "backlight:", 10)) { + char *p = (char *)opt + 10; + unsigned int level; + + ret = kstrtouint(p, 0, &level); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + if (level) { + /*disp_bls_set_backlight(level);*/ + sprintf(buf, "backlight: %d\n", level); + } else { + goto Error; + } + } else if (0 == strncmp(opt, "pwm0:", 5) || 0 == strncmp(opt, "pwm1:", 5)) { + char *p = (char *)opt + 5; + unsigned int level; + + ret = kstrtouint(p, 0, &level); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + if (level) { + disp_pwm_id_t pwm_id = DISP_PWM0; + + if (opt[3] == '1') + pwm_id = DISP_PWM1; + + /*disp_pwm_set_backlight(pwm_id, level);*/ + sprintf(buf, "PWM 0x%x : %d\n", pwm_id, level); + } else { + goto Error; + } + } else if (0 == strncmp(opt, "rdma_color:", 11)) { + unsigned int red, green, blue; + + rdma_color_matrix matrix; + rdma_color_pre pre = { 0 }; + rdma_color_post post = { 255, 0, 0 }; + + memset(&matrix, 0, sizeof(matrix)); + + ret = sscanf(opt, "rdma_color:%d,%d,%d\n", &red, &green, &blue); + if (ret != 3) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + post.ADD0 = red; + post.ADD1 = green; + post.ADD2 = blue; + rdma_set_color_matrix(DISP_MODULE_RDMA0, &matrix, &pre, &post); + rdma_enable_color_transform(DISP_MODULE_RDMA0); + } else if (0 == strncmp(opt, "rdma_color:off", 14)) { + rdma_disable_color_transform(DISP_MODULE_RDMA0); + } else if (0 == strncmp(opt, "aal_dbg:", 8)) { + char *p = (char *)opt + 8; + + ret = kstrtouint(p, 0, &aal_dbg_en); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + sprintf(buf, "aal_dbg_en = 0x%x\n", aal_dbg_en); + } else if (0 == strncmp(opt, "aal_test:", 9)) { + aal_test(opt + 9, buf); + } else if (0 == strncmp(opt, "pwm_test:", 9)) { + disp_pwm_test(opt + 9, buf); + } else if (0 == strncmp(opt, "dither_test:", 12)) { + dither_test(opt + 12, buf); + } else if (0 == strncmp(opt, "corr_dbg:", 9)) { + int i; + + i = 0; + } else if (0 == strncmp(opt, "dump_reg:", 9)) { + char *p = (char *)opt + 9; + unsigned int module; + + ret = kstrtouint(p, 0, &module); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + DISPMSG("process_dbg_opt, module=%d\n", module); + if (module < DISP_MODULE_NUM) { + ddp_dump_reg(module); + sprintf(buf, "dump_reg: %d\n", module); + } else { + DISPMSG("process_dbg_opt2, module=%d\n", module); + goto Error; + } + } else if (0 == strncmp(opt, "dump_path:", 10)) { + char *p = (char *)opt + 10; + unsigned int mutex_idx; + + ret = kstrtouint(p, 0, &mutex_idx); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + DISPMSG("process_dbg_opt, path mutex=%d\n", mutex_idx); + dpmgr_debug_path_status(mutex_idx); + sprintf(buf, "dump_path: %d\n", mutex_idx); + + } else if (0 == strncmp(opt, "get_module_addr", 15)) { + unsigned int i = 0; + char *buf_temp = buf; + + for (i = 0; i < DISP_REG_NUM; i++) { + DISPDMP("i=%d, module=%s, va=0x%lx, pa=0x%lx, irq(%d)\n", + i, ddp_get_reg_module_name(i), dispsys_reg[i], + ddp_reg_pa_base[i], dispsys_irq[i]); + snprintf(buf_temp, 100, + "i=%d, module=%s, va=0x%lx, pa=0x%lx, irq(%d)\n", i, + ddp_get_reg_module_name(i), dispsys_reg[i], + ddp_reg_pa_base[i], dispsys_irq[i]); + buf_temp += strlen(buf_temp); + } + + } else if (0 == strncmp(opt, "debug:", 6)) { + char *p = (char *)opt + 6; + unsigned int enable; + + ret = kstrtouint(p, 0, &enable); + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + if (enable == 1) { + DISPMSG("[DDP] debug=1, trigger AEE\n"); + /* aee_kernel_exception("DDP-TEST-ASSERT", "[DDP] DDP-TEST-ASSERT"); */ + } else if (enable == 2) { + ddp_mem_test(); + } else if (enable == 3) { + ddp_lcd_test(); + } else if (enable == 4) { + /* DISPAEE("test 4"); */ + } else if (enable == 12) { + if (gUltraEnable == 0) + gUltraEnable = 1; + else + gUltraEnable = 0; + sprintf(buf, "gUltraEnable: %d\n", gUltraEnable); + } + } else if (0 == strncmp(opt, "mmp", 3)) { + init_ddp_mmp_events(); + } else if (0 == strncmp(opt, "low_power_mode:", 15)) { + char *p = (char *)opt + 15; + unsigned int mode; + + ret = kstrtouint(p, 0, &mode); + + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + low_power_cust_mode = mode; + + } else { + dbg_buf[0] = '\0'; + goto Error; + } + + return; + +Error: + DISPERR("parse command error!\n%s\n\n%s", opt, DDP_STR_HELP); +} + +void mtkfb_process_dbg_opt(const char *opt) +{ + int ret; + + if (0 == strncmp(opt, "helper", 6)) { + /*ex: echo helper:DISP_OPT_BYPASS_OVL,0 > /d/mtkfb */ + char option[100] = ""; + char *tmp; + int value, i; + + tmp = (char *)opt + 7; + for (i = 0; i < 100; i++) { + if (tmp[i] != ',' && tmp[i] != ' ') + option[i] = tmp[i]; + else + break; + } + tmp += i + 1; + ret = sscanf(tmp, "%d\n", &value); + if (ret != 1) { + pr_err("error to parse cmd %s: %s %s ret=%d\n", opt, option, tmp, ret); + return; + } + + DISPMSG("will set option %s to %d\n", option, value); + disp_helper_set_option_by_name(option, value); + } else if (0 == strncmp(opt, "switch_mode:", 12)) { + int session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0); + int sess_mode; + + ret = sscanf(opt, "switch_mode:%d\n", &sess_mode); + if (ret != 1) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + primary_display_switch_mode(sess_mode, session_id, 1); + } else if (0 == strncmp(opt, "dsi_mode:cmd", 12)) { + lcm_mode_status = 1; + DISPMSG("switch cmd\n"); + } else if (0 == strncmp(opt, "dsi_mode:vdo", 12)) { + DISPMSG("switch vdo\n"); + lcm_mode_status = 2; + } else if (0 == strncmp(opt, "clk_change:", 11)) { + char *p = (char *)opt + 11; + unsigned int clk = 0; + + ret = kstrtouint(p, 0, &clk); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + DISPMSG("clk_change:%d\n", clk); + primary_display_mipi_clk_change(clk); + } else if (0 == strncmp(opt, "freeze:", 7)) { + if (0 == strncmp(opt + 7, "on", 2)) + display_freeze_mode(1, 1); + else if (0 == strncmp(opt + 7, "off", 3)) + display_freeze_mode(0, 1); + } else if (0 == strncmp(opt, "dsipattern", 10)) { + char *p = (char *)opt + 11; + unsigned int pattern; + + ret = kstrtouint(p, 0, &pattern); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + if (pattern) { + DSI_BIST_Pattern_Test(DISP_MODULE_DSI0, NULL, true, pattern); + DISPMSG("enable dsi pattern: 0x%08x\n", pattern); + } else { + primary_display_manual_lock(); + DSI_BIST_Pattern_Test(DISP_MODULE_DSI0, NULL, false, 0); + primary_display_manual_unlock(); + return; + } + } else if (0 == strncmp(opt, "bypass_blank:", 13)) { + char *p = (char *)opt + 13; + unsigned int blank; + + ret = kstrtouint(p, 0, &blank); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + if (blank) + bypass_blank = 1; + else + bypass_blank = 0; + + } else if (0 == strncmp(opt, "force_fps:", 9)) { + unsigned int keep; + unsigned int skip; + + ret = sscanf(opt, "force_fps:%d,%d\n", &keep, &skip); + if (ret != 2) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + DISPMSG("force set fps, keep %d, skip %d\n", keep, skip); + primary_display_force_set_fps(keep, skip); + } else if (0 == strncmp(opt, "AAL_trigger", 11)) { + int i = 0; + disp_session_vsync_config vsync_config; + + for (i = 0; i < 1200; i++) { + primary_display_wait_for_vsync(&vsync_config); + dpmgr_module_notify(DISP_MODULE_AAL, DISP_PATH_EVENT_TRIGGER); + } + } else if (0 == strncmp(opt, "diagnose", 8)) { + primary_display_diagnose(); + return; + } else if (0 == strncmp(opt, "_efuse_test", 11)) { + primary_display_check_test(); + } else if (0 == strncmp(opt, "dprec_reset", 11)) { + dprec_logger_reset_all(); + return; + } else if (0 == strncmp(opt, "suspend", 7)) { + primary_display_suspend(); + return; + } else if (0 == strncmp(opt, "resume", 6)) { + primary_display_resume(); + } else if (0 == strncmp(opt, "ata", 3)) { + mtkfb_fm_auto_test(); + return; + } else if (0 == strncmp(opt, "dalprintf", 9)) { + DAL_Printf("display aee layer test\n"); + } else if (0 == strncmp(opt, "dalclean", 8)) { + DAL_Clean(); + } else if (0 == strncmp(opt, "daltest", 7)) { + int i = 1000; + + while (i--) { + DAL_Printf("display aee layer test\n"); + msleep(20); + DAL_Clean(); + msleep(20); + } + } else if (0 == strncmp(opt, "lfr_setting:", 12)) { + unsigned int enable; + unsigned int mode; + unsigned int type = 0; + unsigned int skip_num = 1; + + ret = sscanf(opt, "lfr_setting:%d,%d\n", &enable, &mode); + if (ret != 2) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + DISPMSG("--------------enable/disable lfr--------------\n"); + if (enable) { + DISPMSG("lfr enable %d mode =%d\n", enable, mode); + enable = 1; + DSI_Set_LFR(DISP_MODULE_DSI0, NULL, mode, type, enable, skip_num); + } else { + DISPMSG("lfr disable %d mode=%d\n", enable, mode); + enable = 0; + DSI_Set_LFR(DISP_MODULE_DSI0, NULL, mode, type, enable, skip_num); + } + } else if (0 == strncmp(opt, "vsync_switch:", 13)) { + char *p = (char *)opt + 13; + unsigned int method = 0; + + ret = kstrtouint(p, 0, &method); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + primary_display_vsync_switch(method); + + } else if (0 == strncmp(opt, "dsi0_clk:", 9)) { + char *p = (char *)opt + 9; + uint32_t clk; + + ret = kstrtouint(p, 0, &clk); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + } else if (0 == strncmp(opt, "detect_recovery", 15)) { + DISPMSG("primary_display_signal_recovery\n"); + primary_display_signal_recovery(); + } else if (0 == strncmp(opt, "dst_switch:", 11)) { + char *p = (char *)opt + 11; + uint32_t mode; + + ret = kstrtouint(p, 0, &mode); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + primary_display_switch_dst_mode(mode % 2); + return; + } else if (0 == strncmp(opt, "cmmva_dprec", 11)) { + dprec_handle_option(0x7); + } else if (0 == strncmp(opt, "cmmpa_dprec", 11)) { + dprec_handle_option(0x3); + } else if (0 == strncmp(opt, "dprec", 5)) { + char *p = (char *)opt + 6; + unsigned int option; + + ret = kstrtouint(p, 0, &option); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + dprec_handle_option(option); + } else if (0 == strncmp(opt, "maxlayer", 8)) { + char *p = (char *)opt + 9; + unsigned int maxlayer; + + ret = kstrtouint(p, 0, &maxlayer); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + if (maxlayer) + primary_display_set_max_layer(maxlayer); + else + DISPERR("can't set max layer to 0\n"); + } else if (0 == strncmp(opt, "primary_reset", 13)) { + primary_display_reset(); + } else if (0 == strncmp(opt, "esd_check", 9)) { + char *p = (char *)opt + 10; + unsigned int enable; + + ret = kstrtouint(p, 0, &enable); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + primary_display_esd_check_enable(enable); + } else if (0 == strncmp(opt, "esd_recovery", 12)) { + primary_display_esd_recovery(); + } else if (0 == strncmp(opt, "lcm0_reset", 10)) { + DISPMSG("lcm0_reset\n"); +#if 1 + DISP_CPU_REG_SET(DISPSYS_CONFIG_BASE + 0x150, 1); + msleep(20); + DISP_CPU_REG_SET(DISPSYS_CONFIG_BASE + 0x150, 0); + msleep(20); + DISP_CPU_REG_SET(DISPSYS_CONFIG_BASE + 0x150, 1); +#else +#ifdef CONFIG_MTK_LEGACY + mt_set_gpio_mode(GPIO158 | 0x80000000, GPIO_MODE_00); + mt_set_gpio_dir(GPIO158 | 0x80000000, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO158 | 0x80000000, GPIO_OUT_ONE); + msleep(20); + mt_set_gpio_out(GPIO158 | 0x80000000, GPIO_OUT_ZERO); + msleep(20); + mt_set_gpio_out(GPIO158 | 0x80000000, GPIO_OUT_ONE); +#else + ret = disp_dts_gpio_select_state(DTS_GPIO_STATE_LCM_RST_OUT1); + msleep(20); + ret |= disp_dts_gpio_select_state(DTS_GPIO_STATE_LCM_RST_OUT0); + msleep(20); + ret |= disp_dts_gpio_select_state(DTS_GPIO_STATE_LCM_RST_OUT1); +#endif +#endif + } else if (0 == strncmp(opt, "lcm0_reset0", 11)) { + DISP_CPU_REG_SET(DDP_REG_BASE_MMSYS_CONFIG + 0x150, 0); + } else if (0 == strncmp(opt, "lcm0_reset1", 11)) { + DISP_CPU_REG_SET(DDP_REG_BASE_MMSYS_CONFIG + 0x150, 1); + } else if (0 == strncmp(opt, "dump_layer:", 11)) { + if (0 == strncmp(opt + 11, "on", 2)) { + ret = sscanf(opt, "dump_layer:on,%d,%d,%d\n", + &gCapturePriLayerDownX, &gCapturePriLayerDownY, &gCapturePriLayerNum); + if (ret != 3) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + gCapturePriLayerEnable = 1; + gCaptureWdmaLayerEnable = 0; + if (gCapturePriLayerDownX == 0) + gCapturePriLayerDownX = 20; + if (gCapturePriLayerDownY == 0) + gCapturePriLayerDownY = 20; + DISPMSG("dump_layer En %d DownX %d DownY %d,Num %d", gCapturePriLayerEnable, + gCapturePriLayerDownX, gCapturePriLayerDownY, gCapturePriLayerNum); + + } else if (0 == strncmp(opt + 11, "off", 3)) { + gCapturePriLayerEnable = 0; + gCaptureWdmaLayerEnable = 0; + gCapturePriLayerNum = TOTAL_OVL_LAYER_NUM; + DISPMSG("dump_layer En %d\n", gCapturePriLayerEnable); + } + + } else if (0 == strncmp(opt, "dump_wdma_layer:", 16)) { + if (0 == strncmp(opt + 16, "on", 2)) { + ret = sscanf(opt, "dump_wdma_layer:on,%d,%d\n", + &gCapturePriLayerDownX, &gCapturePriLayerDownY); + if (ret != 2) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + gCaptureWdmaLayerEnable = 1; + if (gCapturePriLayerDownX == 0) + gCapturePriLayerDownX = 20; + if (gCapturePriLayerDownY == 0) + gCapturePriLayerDownY = 20; + DISPMSG("dump_wdma_layer En %d DownX %d DownY %d", gCaptureWdmaLayerEnable, + gCapturePriLayerDownX, gCapturePriLayerDownY); + + } else if (0 == strncmp(opt + 16, "off", 3)) { + gCaptureWdmaLayerEnable = 0; + DISPMSG("dump_layer En %d\n", gCaptureWdmaLayerEnable); + } + } else if (0 == strncmp(opt, "dump_rdma_layer:", 16)) { + if (0 == strncmp(opt + 16, "on", 2)) { + ret = sscanf(opt, "dump_rdma_layer:on,%d,%d\n", + &gCapturePriLayerDownX, &gCapturePriLayerDownY); + if (ret != 2) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + gCaptureRdmaLayerEnable = 1; + if (gCapturePriLayerDownX == 0) + gCapturePriLayerDownX = 20; + if (gCapturePriLayerDownY == 0) + gCapturePriLayerDownY = 20; + DISPMSG("dump_wdma_layer En %d DownX %d DownY %d", gCaptureRdmaLayerEnable, + gCapturePriLayerDownX, gCapturePriLayerDownY); + + } else if (0 == strncmp(opt + 16, "off", 3)) { + gCaptureRdmaLayerEnable = 0; + DISPMSG("dump_layer En %d\n", gCaptureRdmaLayerEnable); + } + } else if (0 == strncmp(opt, "enable_idlemgr:", 15)) { + char *p = (char *)opt + 15; + uint32_t flg; + + ret = kstrtouint(p, 0, &flg); + if (ret) { + pr_err("error to parse cmd %s\n", opt); + return; + } + enable_idlemgr(flg); + } + + if (0 == strncmp(opt, "primary_basic_test:", 19)) { + int layer_num, w, h, fmt, frame_num, vsync; + + ret = sscanf(opt, "primary_basic_test:%d,%d,%d,%d,%d,%d\n", + &layer_num, &w, &h, &fmt, &frame_num, &vsync); + if (ret != 6) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + if (fmt == 0) + fmt = DISP_FORMAT_RGBA8888; + else if (fmt == 1) + fmt = DISP_FORMAT_RGB888; + else if (fmt == 2) + fmt = DISP_FORMAT_RGB565; + + /*primary_display_basic_test(layer_num, w, h, fmt, frame_num, vsync);*/ + } + + if (0 == strncmp(opt, "pan_disp_test:", 13)) { + int frame_num; + int bpp; + + ret = sscanf(opt, "pan_disp_test:%d,%d\n", &frame_num, &bpp); + if (ret != 2) { + pr_err("error to parse cmd %s\n", opt); + return; + } + + pan_display_test(frame_num, bpp); + } + +} + +/* --------------------------------------------------------------------------- */ +/* Local debugfs Command Processor */ +/* --------------------------------------------------------------------------- */ +int get_lp_cust_mode(void) +{ + return low_power_cust_mode; +} +void backup_vfp_for_lp_cust(unsigned int vfp) +{ + vfp_backup = vfp; +} +unsigned int get_backup_vfp(void) +{ + return vfp_backup; +} + +static char cmd_buf[512]; + +static void lp_cust_process_dbg_opt(const char *opt) +{ + int ret = 0; + char *buf = cmd_buf + strlen(cmd_buf); + + if (0 == strncmp(opt, "low_power_mode:", 15)) { + char *p = (char *)opt + 15; + unsigned int mode; + + ret = kstrtouint(p, 0, &mode); + + if (ret) { + snprintf(buf, 50, "error to parse cmd %s\n", opt); + return; + } + + low_power_cust_mode = mode; + + } else { + cmd_buf[0] = '\0'; + goto Error; + } + + return; + +Error: + DISPERR("parse command error!\n%s\n\n%s", opt, LP_CUST_STR_HELP); +} + +static void lp_cust_process_dbg_cmd(char *cmd) +{ + char *tok; + + DISPMSG("cmd: %s\n", cmd); + memset(cmd_buf, 0, sizeof(cmd_buf)); + while ((tok = strsep(&cmd, " ")) != NULL) + lp_cust_process_dbg_opt(tok); +} + +static ssize_t lp_cust_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) +{ + const int debug_bufmax = sizeof(cmd_buf) - 1; + size_t ret; + + ret = count; + + if (count > debug_bufmax) + count = debug_bufmax; + + if (copy_from_user(&cmd_buf, ubuf, count)) + return -EFAULT; + + cmd_buf[count] = 0; + + lp_cust_process_dbg_cmd(cmd_buf); + + return ret; +} + +static ssize_t lp_cust_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) +{ + char *mode0 = "low power mode(1)\n"; + char *mode1 = "just make mode(2)\n"; + char *mode2 = "performance mode(3)\n"; + char *mode4 = "unknown mode(n)\n"; + + switch (low_power_cust_mode) { + case LOW_POWER_MODE: + return simple_read_from_buffer(ubuf, count, ppos, mode0, strlen(mode0)); + case JUST_MAKE_MODE: + return simple_read_from_buffer(ubuf, count, ppos, mode1, strlen(mode1)); + case PERFORMANC_MODE: + return simple_read_from_buffer(ubuf, count, ppos, mode2, strlen(mode2)); + default: + return simple_read_from_buffer(ubuf, count, ppos, mode4, strlen(mode4)); + } + +} + +static int lp_cust_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static const struct file_operations low_power_cust_fops = { + .read = lp_cust_read, + .write = lp_cust_write, + .open = lp_cust_open, +}; + +static ssize_t kick_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) +{ + return simple_read_from_buffer(ubuf, count, ppos, get_kick_dump(), get_kick_dump_size()); +} + +static const struct file_operations kickidle_fops = { + .read = kick_read, +}; + +void sub_debug_init(void) +{ + lowpowermode_debugfs = debugfs_create_file("lowpowermode", + S_IFREG | S_IRUGO, disp_debugDir, NULL, &low_power_cust_fops); + if (!lowpowermode_debugfs) + DISPERR("create debug file disp/lowpowermode fail!\n"); + + kickdump_debugfs = debugfs_create_file("kickdump", + S_IFREG | S_IRUGO, disp_debugDir, NULL, &kickidle_fops); + if (!kickdump_debugfs) + DISPERR("create debug file disp/kickdump fail!\n"); +} + +void sub_debug_deinit(void) +{ + debugfs_remove(lowpowermode_debugfs); + debugfs_remove(kickdump_debugfs); +} + diff --git a/drivers/misc/mediatek/video/mt6755/disp_debug.h b/drivers/misc/mediatek/video/mt6755/disp_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..fbd0493cdde6080ea339646e1eba8fec39fa148b --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_debug.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DISP_DEBUG_H__ +#define __DISP_DEBUG_H__ + +#include +#include "ddp_mmp.h" +#include "ddp_dump.h" +#include "disp_log.h" +#include "mmprofile.h" + +#define LP_CUST_DISABLE (0) +#define LOW_POWER_MODE (1) +#define JUST_MAKE_MODE (2) +#define PERFORMANC_MODE (3) + +#define dprec_string_max_length 512 +#define dprec_dump_max_length (1024 * 16 * 4) +#define LOGGER_BUFFER_SIZE (16 * 1024) +#define ERROR_BUFFER_COUNT 2 +#define FENCE_BUFFER_COUNT 22 +#define DEBUG_BUFFER_COUNT 4 +#define DUMP_BUFFER_COUNT 2 +#define STATUS_BUFFER_COUNT 1 +#define DPREC_ERROR_LOG_BUFFER_LENGTH \ + (1024 * 16 + LOGGER_BUFFER_SIZE * \ + (ERROR_BUFFER_COUNT + FENCE_BUFFER_COUNT + DEBUG_BUFFER_COUNT + DUMP_BUFFER_COUNT + STATUS_BUFFER_COUNT)) + +extern char DDP_STR_HELP[]; +extern char MTKFB_STR_HELP[]; + +void ddp_process_dbg_opt(const char *opt); +void mtkfb_process_dbg_opt(const char *opt); +int get_lp_cust_mode(void); +unsigned int get_backup_vfp(void); +void backup_vfp_for_lp_cust(unsigned int vfp); +void sub_debug_init(void); +void sub_debug_deinit(void); + +#endif /* __DISP_DEBUG_H__ */ diff --git a/drivers/misc/mediatek/video/mt6755/disp_drv_ddp.h b/drivers/misc/mediatek/video/mt6755/disp_drv_ddp.h new file mode 100644 index 0000000000000000000000000000000000000000..8f322d80438f869155ffc38ba0d29cf74d107c60 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_drv_ddp.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +/* Only for DDP driver. */ +#ifndef __DISP_DRV_DDP_H__ +#define __DISP_DRV_DDP_H__ +/*#include */ + +typedef int (*DISP_EXTRA_CHECKUPDATE_PTR)(int); +typedef int (*DISP_EXTRA_CONFIG_PTR)(int); +int DISP_RegisterExTriggerSource(DISP_EXTRA_CHECKUPDATE_PTR pCheckUpdateFunc , DISP_EXTRA_CONFIG_PTR pConfFunc); +void DISP_UnRegisterExTriggerSource(int u4ID); +void GetUpdateMutex(void); +void ReleaseUpdateMutex(void); +bool DISP_IsVideoMode(void); +unsigned long DISP_GetLCMIndex(void); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/disp_drv_platform.h b/drivers/misc/mediatek/video/mt6755/disp_drv_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..ef75e3ce8a7658b6d9200a9822813770fed85bfb --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_drv_platform.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DISP_DRV_PLATFORM_H__ +#define __DISP_DRV_PLATFORM_H__ + +#include +#include "m4u.h" +/*#include */ +#ifdef CONFIG_MTK_CLKMGR +#include +#endif + +#include +/*#include */ +#include "disp_assert_layer.h" + +#include "ddp_hal.h" +#include "ddp_drv.h" +#include "ddp_path.h" +#include "ddp_rdma.h" + +/* #include */ +/* #include */ + +#define ALIGN_TO(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) + +#define MTK_FB_ALIGNMENT 32 /*Hardware 3D */ +/*#define MTK_FB_ALIGNMENT 1 // SW 3D */ +#define MTK_FB_ION_SUPPORT +#define VIDEO_LAYER_COUNT (3) +/* #define HW_OVERLAY_COUNT (4) */ + +#define PRIMARY_SESSION_INPUT_LAYER_COUNT (8) +#define EXTERNAL_SESSION_INPUT_LAYER_COUNT (4) +#define MEMORY_SESSION_INPUT_LAYER_COUNT (4) +#define DISP_SESSION_OVL_TIMELINE_ID(x) (x) + +/* Display HW Capabilities */ +#define DISP_HW_MODE_CAP DISP_OUTPUT_CAP_SWITCHABLE +#define DISP_HW_PASS_MODE DISP_OUTPUT_CAP_SINGLE_PASS +#define DISP_HW_MAX_LAYER 4 + +typedef enum { + DISP_SESSION_OUTPUT_TIMELINE_ID = PRIMARY_SESSION_INPUT_LAYER_COUNT, + DISP_SESSION_PRESENT_TIMELINE_ID, + DISP_SESSION_OUTPUT_INTERFACE_TIMELINE_ID, + DISP_SESSION_TIMELINE_COUNT, +} DISP_SESSION_ENUM; + +#define MAX_SESSION_COUNT 5 + +/* macros for display path hardware */ +#define DISP_HW_HRT_LYAERS_FOR_LOW_POWER 4 +#define DISP_HW_HRT_LYAERS_FOR_HI_PERF 6 +#define DISP_HW_HRT_720P_LYAERS_FOR_HI_PERF 6 + +#define DISP_HW_HRT_PERF_FOR_LCM_BIG 4 +#define DISP_HW_HRT_PERF_FOR_LCM_BIG_MAX 6 +#define DISP_HW_HRT_PERF_FOR_LCM_SMALL 6 +#define DISP_HW_HRT_PERF_LCM_AREA_THRESHOLD (1280 * 800) + +/*schedule priority*/ +#define RTPM_PRIO_SCRN_UPDATE 94 /*0x5e*/ +#define RTPM_PRIO_FB_THREAD 87 /*0x57*/ +#define FBCONFIG_SHOULD_KICK_IDLEMGR + +/* Other platform-dependent features */ +#define DISP_PATH_DELAYED_TRIGGER_33ms_SUPPORT + +#endif /* __DISP_DRV_PLATFORM_H__ */ diff --git a/drivers/misc/mediatek/video/mt6755/disp_dts_gpio.c b/drivers/misc/mediatek/video/mt6755/disp_dts_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..109357711f7e27db3ba6a23a0fb5247aabf732a8 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_dts_gpio.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "disp_dts_gpio.h" +#include +#include "disp_helper.h" +#include + +static struct pinctrl *this_pctrl; /* static pinctrl instance */ + +/* DTS state mapping name */ +static const char *this_state_name[DTS_GPIO_STATE_MAX] = { + "mode_te_gpio", + "mode_te_te", + "lcm_rst_out0_gpio", + "lcm_rst_out1_gpio", + "lcd_bias_enp0_gpio", + "lcd_bias_enp1_gpio" +}; + +/* pinctrl implementation */ +static long _set_state(const char *name) +{ + long ret = 0; + struct pinctrl_state *pState = 0; + + BUG_ON(!this_pctrl); + + pState = pinctrl_lookup_state(this_pctrl, name); + if (IS_ERR(pState)) { + pr_err("set state '%s' failed\n", name); + ret = PTR_ERR(pState); + goto exit; + } + + /* select state! */ + pinctrl_select_state(this_pctrl, pState); + +exit: + return ret; /* Good! */ +} + +long disp_dts_gpio_init(struct platform_device *pdev) +{ + long ret = 0; + struct pinctrl *pctrl; + + /* retrieve */ + pctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(pctrl)) { + dev_err(&pdev->dev, "Cannot find disp pinctrl!"); + ret = PTR_ERR(pctrl); + goto exit; + } + + this_pctrl = pctrl; + +exit: + return ret; +} + +long disp_dts_gpio_select_state(DTS_GPIO_STATE s) +{ + BUG_ON(!((unsigned int)(s) < (unsigned int)(DTS_GPIO_STATE_MAX))); + return _set_state(this_state_name[s]); +} + diff --git a/drivers/misc/mediatek/video/mt6755/disp_dts_gpio.h b/drivers/misc/mediatek/video/mt6755/disp_dts_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..b48281a1dde9f62486dcec26cb2920ba2e6bc3d5 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_dts_gpio.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DISP_DTS_GPIO_H__ +#define __DISP_DTS_GPIO_H__ + +/* + * This module helps you to set GPIO pin according to linux device tree (DTS). To + * use this module, you MUST init this module once before any operation. + */ + +#include /* struct platform_device */ + +/* DTS state */ +typedef enum tagDTS_GPIO_STATE { + DTS_GPIO_STATE_TE_MODE_GPIO = 0, /* mode_te_gpio */ + DTS_GPIO_STATE_TE_MODE_TE, /* mode_te_te */ + DTS_GPIO_STATE_LCM_RST_OUT0, + DTS_GPIO_STATE_LCM_RST_OUT1, + DTS_GPIO_STATE_LCD_BIAS_ENN, + DTS_GPIO_STATE_LCD_BIAS_ENP, + DTS_GPIO_STATE_MAX, /* for array size */ +} DTS_GPIO_STATE; + +/* this function MUST be called in mtkfb_probe. + * @param *pdev - reference of struct platform_device which contains pinctrl + * state information of GPIO + * @return - 0 for OK, otherwise returns PTR_ERR(pdev). + */ +long disp_dts_gpio_init(struct platform_device *pdev); + +/* set gpio according sepcified DTS state. + * @notice - to call this function, you MUST init this module first. + * If not, we will trigger BUG_ON(0). + * @param s - state which describes GPIO statement. + * @return - 0 for OK, otherwise returns PTR_ERR(pdev). + */ +long disp_dts_gpio_select_state(DTS_GPIO_STATE s); + +/* repo of initialization */ +#ifdef CONFIG_MTK_LEGACY +#define disp_dts_gpio_init_repo(x) (0) +#else +#define disp_dts_gpio_init_repo(x) (disp_dts_gpio_init(x)) +#endif + +#endif/*__DISP_DTS_GPIO_H__ */ diff --git a/drivers/misc/mediatek/video/mt6755/disp_event.h b/drivers/misc/mediatek/video/mt6755/disp_event.h new file mode 100644 index 0000000000000000000000000000000000000000..d6257f23ea7744b1e33d0abd56bb50cddb670010 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_event.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __DISP_EVENT_H__ +#define __DISP_EVENT_H__ + +typedef enum{ + DISP_PATH_EVENT_FRAME_DONE = 0, + DISP_PATH_EVENT_FRAME_START, + DISP_PATH_EVENT_FRAME_REG_UPDATE, + DISP_PATH_EVENT_FRAME_TARGET_LINE, + DISP_PATH_EVENT_FRAME_COMPLETE, + DISP_PATH_EVENT_FRAME_STOP, + DISP_PATH_EVENT_IF_CMD_DONE, + DISP_PATH_EVENT_IF_VSYNC, + DISP_PATH_EVENT_TRIGGER, + DISP_PATH_EVENT_AAL_OUT_END_FRAME, + DISP_PATH_EVENT_DELAYED_TRIGGER_33ms, + DISP_PATH_EVENT_NUM, + DISP_PATH_EVENT_NONE = 0xff, +} DISP_PATH_EVENT; + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/disp_helper.c b/drivers/misc/mediatek/video/mt6755/disp_helper.c new file mode 100644 index 0000000000000000000000000000000000000000..5d9bce4f915e9c67b7d60910bfd5911e2e0baf50 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_helper.c @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt-plat/mt_chip.h" +#include "disp_log.h" +#include "primary_display.h" + +#include "mt-plat/mt_boot.h" +#include "disp_helper.h" +#include "disp_drv_platform.h" +#include "primary_display.h" + +/* use this magic_code to detect memory corruption */ +#define MAGIC_CODE 0xDEADAAA0U + +/* CONFIG_MTK_FPGA is used in linux kernel for early porting. */ +/* if the macro name changed, please modify the code here too. */ +#ifdef CONFIG_MTK_FPGA +static unsigned int disp_global_stage = MAGIC_CODE | DISP_HELPER_STAGE_EARLY_PORTING; +#else +/* please change this to DISP_HELPER_STAGE_NORMAL after bring up done */ +/*static unsigned int disp_global_stage = MAGIC_CODE | DISP_HELPER_STAGE_BRING_UP;*/ +static unsigned int disp_global_stage = MAGIC_CODE | DISP_HELPER_STAGE_NORMAL; +#endif + +static int _is_early_porting_stage(void) +{ + return (disp_global_stage & (~MAGIC_CODE)) == DISP_HELPER_STAGE_EARLY_PORTING; +} + +static int _is_bringup_stage(void) +{ + return (disp_global_stage & (~MAGIC_CODE)) == DISP_HELPER_STAGE_BRING_UP; +} + +static int _is_normal_stage(void) +{ + return (disp_global_stage & (~MAGIC_CODE)) == DISP_HELPER_STAGE_NORMAL; +} + +#if 0 +static int _disp_helper_option_value[DISP_OPT_NUM] = { 0 }; + + +const char *disp_helper_option_string[DISP_OPT_NUM] = { + "DISP_OPT_USE_CMDQ", + "DISP_OPT_USE_M4U", + "DISP_OPT_MIPITX_ON_CHIP", + "DISP_OPT_USE_DEVICE_TREE", + "DISP_OPT_FAKE_LCM_X", + "DISP_OPT_FAKE_LCM_Y", + "DISP_OPT_FAKE_LCM_WIDTH", + "DISP_OPT_FAKE_LCM_HEIGHT", + "DISP_OPT_OVL_WARM_RESET", + "DISP_OPT_DYNAMIC_SWITCH_UNDERFLOW_EN", + /* Begin: lowpower option*/ + "DISP_OPT_SODI_SUPPORT", + "DISP_OPT_IDLE_MGR", + "DISP_OPT_IDLEMGR_SWTCH_DECOUPLE", + "DISP_OPT_IDLEMGR_ENTER_ULPS", + "DISP_OPT_SHARE_SRAM", + "DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK", + "DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING", + "DISP_OPT_IDLEMGR_DISABLE_ROUTINE_IRQ", + "DISP_OPT_MET_LOG", /* for met */ + /* End: lowpower option */ + "DISP_OPT_DECOUPLE_MODE_USE_RGB565", + "DISP_OPT_NO_LCM_FOR_LOW_POWER_MEASUREMENT", + "DISP_OPT_NO_LK", + "DISP_OPT_BYPASS_PQ", + "DISP_OPT_ESD_CHECK_RECOVERY", + "DISP_OPT_ESD_CHECK_SWITCH", + "DISP_OPT_PRESENT_FENCE", + "DISP_OPT_PERFORMANCE_DEBUG", + "DISP_OPT_SWITCH_DST_MODE", + "DISP_OPT_MUTEX_EOF_EN_FOR_CMD_MODE", + "DISP_OPT_SCREEN_CAP_FROM_DITHER", + "DISP_OPT_BYPASS_OVL", + "DISP_OPT_FPS_CALC_WND", + "DISP_OPT_SMART_OVL", + "DISP_OPT_DYNAMIC_DEBUG", + "DISP_OPT_SHOW_VISUAL_DEBUG_INFO", + "DISP_OPT_RDMA_UNDERFLOW_AEE", + "DISP_OPT_GMO_OPTIMIZE", + "DISP_OPT_CV_BYSUSPEND", +}; +#endif + +#define OPT_COUNT 40 +const int help_info_cnt = OPT_COUNT; + +struct disp_help_info help_info[OPT_COUNT] = { + { DISP_OPT_USE_CMDQ, 1, "DISP_OPT_USE_CMDQ" }, + { DISP_OPT_USE_M4U, 1, "DISP_OPT_USE_M4U" }, + { DISP_OPT_MIPITX_ON_CHIP, 0, "DISP_OPT_MIPITX_ON_CHIP" }, + { DISP_OPT_USE_DEVICE_TREE, 0, "DISP_OPT_USE_DEVICE_TREE" }, + { DISP_OPT_FAKE_LCM_X, 0, "DISP_OPT_FAKE_LCM_X" }, + { DISP_OPT_FAKE_LCM_Y, 0, "DISP_OPT_FAKE_LCM_Y" }, + { DISP_OPT_FAKE_LCM_WIDTH, 0, "DISP_OPT_FAKE_LCM_WIDTH" }, + { DISP_OPT_FAKE_LCM_HEIGHT, 0, "DISP_OPT_FAKE_LCM_HEIGHT" }, + { DISP_OPT_OVL_WARM_RESET, 0, "DISP_OPT_OVL_WARM_RESET" }, + { DISP_OPT_DYNAMIC_SWITCH_UNDERFLOW_EN, 0, "DISP_OPT_DYNAMIC_SWITCH_UNDERFLOW_EN" }, + { DISP_OPT_SODI_SUPPORT, 1, "DISP_OPT_SODI_SUPPORT" }, + { DISP_OPT_IDLE_MGR, 1, "DISP_OPT_IDLE_MGR" }, + { DISP_OPT_IDLEMGR_SWTCH_DECOUPLE, 1, "DISP_OPT_IDLEMGR_SWTCH_DECOUPLE" }, + { DISP_OPT_IDLEMGR_ENTER_ULPS, 1, "DISP_OPT_IDLEMGR_ENTER_ULPS" }, + { DISP_OPT_SHARE_SRAM, 1, "DISP_OPT_SHARE_SRAM" }, + { DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK, 0, "DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK" }, + { DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING, 1, "DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING" }, + { DISP_OPT_IDLEMGR_DISABLE_ROUTINE_IRQ, 1, "DISP_OPT_IDLEMGR_DISABLE_ROUTINE_IRQ" }, + { DISP_OPT_MET_LOG, 1, "DISP_OPT_MET_LOG" }, + { DISP_OPT_DECOUPLE_MODE_USE_RGB565, 0, "DISP_OPT_DECOUPLE_MODE_USE_RGB565" }, + { DISP_OPT_NO_LCM_FOR_LOW_POWER_MEASUREMENT, 0, "DISP_OPT_NO_LCM_FOR_LOW_POWER_MEASUREMENT" }, + { DISP_OPT_NO_LK, 0, "DISP_OPT_NO_LK" }, + { DISP_OPT_BYPASS_PQ, 0, "DISP_OPT_BYPASS_PQ" }, + { DISP_OPT_ESD_CHECK_RECOVERY, 1, "DISP_OPT_ESD_CHECK_RECOVERY" }, + { DISP_OPT_ESD_CHECK_SWITCH, 1, "DISP_OPT_ESD_CHECK_SWITCH" }, + { DISP_OPT_PRESENT_FENCE, 1, "DISP_OPT_PRESENT_FENCE" }, + { DISP_OPT_PERFORMANCE_DEBUG, 0, "DISP_OPT_PERFORMANCE_DEBUG" }, + { DISP_OPT_SWITCH_DST_MODE, 0, "DISP_OPT_SWITCH_DST_MODE" }, + { DISP_OPT_MUTEX_EOF_EN_FOR_CMD_MODE, 1, "DISP_OPT_MUTEX_EOF_EN_FOR_CMD_MODE" }, + { DISP_OPT_SCREEN_CAP_FROM_DITHER, 0, "DISP_OPT_SCREEN_CAP_FROM_DITHER" }, + { DISP_OPT_BYPASS_OVL, 1, "DISP_OPT_BYPASS_OVL" }, + { DISP_OPT_FPS_CALC_WND, 10, "DISP_OPT_FPS_CALC_WND" }, + { DISP_OPT_SMART_OVL, 1, "DISP_OPT_SMART_OVL" }, + { DISP_OPT_DYNAMIC_DEBUG, 0, "DISP_OPT_DYNAMIC_DEBUG" }, + { DISP_OPT_SHOW_VISUAL_DEBUG_INFO, 0, "DISP_OPT_SHOW_VISUAL_DEBUG_INFO" }, + { DISP_OPT_RDMA_UNDERFLOW_AEE, 0, "DISP_OPT_RDMA_UNDERFLOW_AEE" }, + { DISP_OPT_GMO_OPTIMIZE, 0, "DISP_OPT_GMO_OPTIMIZE" }, + { DISP_OPT_CV_BYSUSPEND, 1, "DISP_OPT_CV_BYSUSPEND" }, + { DISP_OPT_DETECT_RECOVERY, 0, "DISP_OPT_DETECT_RECOVERY" }, + { DISP_OPT_DELAYED_TRIGGER, 1, "DISP_OPT_DELAYED_TRIGGER" }, +}; + +static int option_to_index(DISP_HELPER_OPT option) +{ + int index = -1; + int i = 0; + + for (i = 0; i < help_info_cnt; i++) { + if (option == help_info[i].opt_enum) { + index = i; + break; + } + } + return index; +} + +const char *disp_helper_option_spy(DISP_HELPER_OPT option) +{ + int index = -1; + + index = option_to_index(option); + if (index < 0) + return "unknown option!!"; + return help_info[index].opt_string; +} + +DISP_HELPER_OPT disp_helper_name_to_opt(const char *name) +{ + DISP_HELPER_OPT opt = -1; + int i = 0; + + for (i = 0; i < help_info_cnt; i++) { + const char *opt_name = help_info[i].opt_string; + + if (strncmp(name, opt_name, strlen(opt_name)) == 0) { + opt = help_info[i].opt_enum; + break; + } + } + if (opt == -1) + pr_err("%s: unknown name: %s\n", __func__, name); + return opt; +} + +int disp_helper_set_option(DISP_HELPER_OPT option, int value) +{ + int index = -1; + int ret = 0; + + if (option == DISP_OPT_FPS_CALC_WND) { + /*ret = primary_fps_ctx_set_wnd_sz(value);*/ + if (ret) { + DISPERR("%s error to set fps_wnd_sz to %d\n", __func__, value); + return ret; + } + } + + index = option_to_index(option); + if (index >= 0) { + DISPMSG("Set Option %d(%s) from (%d) to (%d)\n", option, + help_info[index].opt_string, help_info[index].opt_value, value); + help_info[index].opt_value = value; + DISPMSG("After set (%s) is (%d)\n", help_info[index].opt_string, + help_info[index].opt_value); + ret = 0; + } else { + DISPERR("Wrong option: %d\n", option); + ret = -1; + } + return ret; +} + +int disp_helper_set_option_by_name(const char *name, int value) +{ + DISP_HELPER_OPT opt; + + opt = disp_helper_name_to_opt(name); + if (opt < 0) + return -1; + + return disp_helper_set_option(opt, value); +} + +int disp_helper_get_option(DISP_HELPER_OPT option) +{ + int index = -1; + int ret = 0; + + index = option_to_index(option); + if (index < 0) { + DISPERR("%s: option invalid %d\n", __func__, option); + BUG(); + } + + switch (option) { + case DISP_OPT_USE_CMDQ: + case DISP_OPT_SHOW_VISUAL_DEBUG_INFO: + { + return help_info[index].opt_value; + } + case DISP_OPT_USE_M4U: + { + return help_info[index].opt_value; + } + case DISP_OPT_MIPITX_ON_CHIP: + { + if (_is_normal_stage()) + return 1; + else if (_is_bringup_stage()) + return 1; + else if (_is_early_porting_stage()) + return 0; + + BUG_ON(1); + return 0; + } + case DISP_OPT_FAKE_LCM_X: + { + int x = 0; +#ifdef CONFIG_CUSTOM_LCM_X + ret = kstrtoint(CONFIG_CUSTOM_LCM_X, 0, &x); + if (ret) { + pr_err("%s error to parse x: %s\n", __func__, CONFIG_CUSTOM_LCM_X); + x = 0; + } +#endif + return x; + } + case DISP_OPT_FAKE_LCM_Y: + { + int y = 0; +#ifdef CONFIG_CUSTOM_LCM_Y + ret = kstrtoint(CONFIG_CUSTOM_LCM_Y, 0, &y); + if (ret) { + pr_err("%s error to parse x: %s\n", __func__, CONFIG_CUSTOM_LCM_Y); + y = 0; + } + +#endif + return y; + } + case DISP_OPT_FAKE_LCM_WIDTH: + { + int w = primary_display_get_virtual_width(); + + if (w == 0) + w = DISP_GetScreenWidth(); + return w; + } + case DISP_OPT_FAKE_LCM_HEIGHT: + { + int h = primary_display_get_virtual_height(); + + if (h == 0) + h = DISP_GetScreenHeight(); + return h; + } + case DISP_OPT_OVL_WARM_RESET: + { + return 0; + } + case DISP_OPT_NO_LK: + { + if (_is_normal_stage()) + return 0; + else if (_is_bringup_stage()) + return 0; + return 1; + } + case DISP_OPT_PERFORMANCE_DEBUG: + { + if (_is_normal_stage()) + return 0; + else if (_is_bringup_stage()) + return 0; + else if (_is_early_porting_stage()) + return 0; + BUG_ON(1); + } + case DISP_OPT_SWITCH_DST_MODE: + { + if (_is_normal_stage()) + return 0; + else if (_is_bringup_stage()) + return 0; + else if (_is_early_porting_stage()) + return 0; + BUG_ON(1); + } + default: + { + return help_info[index].opt_value; + } + } + + return ret; +} + +DISP_HELPER_STAGE disp_helper_get_stage(void) +{ + return disp_global_stage & (~MAGIC_CODE); +} + +const char *disp_helper_stage_spy(void) +{ + if (disp_helper_get_stage() == DISP_HELPER_STAGE_EARLY_PORTING) + return "EARLY_PORTING"; + else if (disp_helper_get_stage() == DISP_HELPER_STAGE_BRING_UP) + return "BRINGUP"; + else if (disp_helper_get_stage() == DISP_HELPER_STAGE_NORMAL) + return "NORMAL"; + return NULL; +} + +void disp_helper_option_init(void) +{ + disp_helper_set_option(DISP_OPT_USE_CMDQ, 1); + disp_helper_set_option(DISP_OPT_USE_M4U, 1); + + /* test solution for 6795 rdma underflow caused by ufoe LR mode(ufoe fifo is larger than rdma) */ + disp_helper_set_option(DISP_OPT_DYNAMIC_SWITCH_UNDERFLOW_EN, 0); + + /* warm reset ovl before each trigger for cmd mode */ + disp_helper_set_option(DISP_OPT_OVL_WARM_RESET, 0); + + /* ===================Begin: lowpower option setting==================== */ + disp_helper_set_option(DISP_OPT_SODI_SUPPORT, 1); + disp_helper_set_option(DISP_OPT_IDLE_MGR, 1); + + /* 1. vdo mode + screen idle(need idlemgr) */ + disp_helper_set_option(DISP_OPT_IDLEMGR_SWTCH_DECOUPLE, 1); + disp_helper_set_option(DISP_OPT_SHARE_SRAM, 1); + disp_helper_set_option(DISP_OPT_IDLEMGR_DISABLE_ROUTINE_IRQ, 1); + + /* 2. cmd mode + screen idle(need idlemgr) */ + disp_helper_set_option(DISP_OPT_IDLEMGR_ENTER_ULPS, 1); + + /* 3. cmd mode + vdo mode */ + disp_helper_set_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK, 0); + disp_helper_set_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING, 1); + + + disp_helper_set_option(DISP_OPT_MET_LOG, 1); + /* ===================End: lowpower option setting==================== */ + + disp_helper_set_option(DISP_OPT_PRESENT_FENCE, 1); + + /* use fake vsync timer for low power measurement */ + disp_helper_set_option(DISP_OPT_NO_LCM_FOR_LOW_POWER_MEASUREMENT, 0); + + /* use RGB565 format for decouple mode intermediate buffer */ + disp_helper_set_option(DISP_OPT_DECOUPLE_MODE_USE_RGB565, 0); + + disp_helper_set_option(DISP_OPT_BYPASS_PQ, 0); + disp_helper_set_option(DISP_OPT_MUTEX_EOF_EN_FOR_CMD_MODE, 1); + disp_helper_set_option(DISP_OPT_ESD_CHECK_RECOVERY, 1); + disp_helper_set_option(DISP_OPT_ESD_CHECK_SWITCH, 1); + + disp_helper_set_option(DISP_OPT_BYPASS_OVL, 1); + disp_helper_set_option(DISP_OPT_FPS_CALC_WND, 10); + disp_helper_set_option(DISP_OPT_SMART_OVL, 1); + disp_helper_set_option(DISP_OPT_GMO_OPTIMIZE, 0); + disp_helper_set_option(DISP_OPT_CV_BYSUSPEND, 1); + disp_helper_set_option(DISP_OPT_DYNAMIC_DEBUG, 0); + disp_helper_set_option(DISP_OPT_DELAYED_TRIGGER, 1); + /*Detect Hang thread Option*/ + disp_helper_set_option(DISP_OPT_DETECT_RECOVERY, 0); +} + +int disp_helper_get_option_list(char *stringbuf, int buf_len) +{ + int len = 0; + int i = 0; + + for (i = 0; i < help_info_cnt; i++) { + len += + scnprintf(stringbuf + len, buf_len - len, "Option: [%d][%s] Value: [%d]\n", i, + help_info[i].opt_string, help_info[i].opt_value); + } + + return len; +} diff --git a/drivers/misc/mediatek/video/mt6755/disp_helper.h b/drivers/misc/mediatek/video/mt6755/disp_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..e37f94b8e13ba4a998173107a87ff053c91b5c8b --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_helper.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "disp_helper_option.h" diff --git a/drivers/misc/mediatek/video/mt6755/disp_lcm.c b/drivers/misc/mediatek/video/mt6755/disp_lcm.c new file mode 100644 index 0000000000000000000000000000000000000000..f7bf5ccf6178b477072cf149388bc8693a7a0752 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_lcm.c @@ -0,0 +1,590 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include "disp_log.h" +#include "lcm_drv.h" +#include "disp_drv_platform.h" +#include "ddp_manager.h" +#include "disp_lcm.h" + +/* This macro and arrya is designed for multiple LCM support */ +/* for multiple LCM, we should assign I/F Port id in lcm driver, such as DPI0, DSI0/1 */ + +int _lcm_count(void) +{ + return lcm_count; +} + +int _is_lcm_inited(disp_lcm_handle *plcm) +{ + if (plcm) { + if (plcm->params && plcm->drv) + return 1; + + DISPERR("WARNING,params|drv is null!\n"); + return 0; + } + + DISPERR("WARNING, invalid lcm handle: %p\n", plcm); + return 0; +} +LCM_PARAMS *_get_lcm_params_by_handle(disp_lcm_handle *plcm) +{ + if (plcm) + return plcm->params; + DISPERR("WARNING, invalid lcm handle:%p\n", plcm); + return NULL; +} + +LCM_DRIVER *_get_lcm_driver_by_handle(disp_lcm_handle *plcm) +{ + if (plcm) + return plcm->drv; + DISPERR("WARNING, invalid lcm handle:%p\n", plcm); + return NULL; +} + +void _dump_lcm_info(disp_lcm_handle *plcm) +{ + LCM_DRIVER *l = NULL; + LCM_PARAMS *p = NULL; + + if (plcm == NULL) { + DISPERR("plcm is null\n"); + return; + } + + l = plcm->drv; + p = plcm->params; + + if (!l || !p) + return; + + DISPMSG("[LCM], name: %s\n", l->name); + DISPMSG("[LCM] resolution: %d x %d\n", p->width, p->height); + DISPMSG("[LCM] physical size: %d x %d\n", p->physical_width, p->physical_height); + DISPMSG("[LCM] physical size: %d x %d\n", p->physical_width, p->physical_height); + + switch (p->lcm_if) { + case LCM_INTERFACE_DSI0: + DISPMSG("[LCM] interface: DSI0\n"); + break; + case LCM_INTERFACE_DSI1: + DISPMSG("[LCM] interface: DSI1\n"); + break; + case LCM_INTERFACE_DPI0: + DISPMSG("[LCM] interface: DPI0\n"); + break; + case LCM_INTERFACE_DPI1: + DISPMSG("[LCM] interface: DPI1\n"); + break; + case LCM_INTERFACE_DBI0: + DISPMSG("[LCM] interface: DBI0\n"); + break; + default: + DISPMSG("[LCM] interface: unknown\n"); + break; + } + + switch (p->type) { + case LCM_TYPE_DBI: + DISPMSG("[LCM] Type: DBI\n"); + break; + case LCM_TYPE_DSI: + DISPMSG("[LCM] Type: DSI\n"); + + break; + case LCM_TYPE_DPI: + DISPMSG("[LCM] Type: DPI\n"); + break; + default: + DISPMSG("[LCM] TYPE: unknown\n"); + break; + } + + if (p->type == LCM_TYPE_DSI) { + switch (p->dsi.mode) { + case CMD_MODE: + DISPMSG("[LCM] DSI Mode: CMD_MODE\n"); + break; + case SYNC_PULSE_VDO_MODE: + DISPMSG("[LCM] DSI Mode: SYNC_PULSE_VDO_MODE\n"); + break; + case SYNC_EVENT_VDO_MODE: + DISPMSG("[LCM] DSI Mode: SYNC_EVENT_VDO_MODE\n"); + break; + case BURST_VDO_MODE: + DISPMSG("[LCM] DSI Mode: BURST_VDO_MODE\n"); + break; + default: + DISPMSG("[LCM] DSI Mode: Unknown\n"); + break; + } + } + + if (p->type == LCM_TYPE_DSI) { + DISPMSG("[LCM] LANE_NUM: %d,data_format\n", (int)p->dsi.LANE_NUM); + DISPMSG("[LCM] vact: %u, vbp: %u, vfp: %u, vact_line: %u, hact: %u, hbp: %u, hfp: %u, hblank: %u\n", + p->dsi.vertical_sync_active, p->dsi.vertical_backporch, + p->dsi.vertical_frontporch, p->dsi.vertical_active_line, + p->dsi.horizontal_sync_active, p->dsi.horizontal_backporch, + p->dsi.horizontal_frontporch, p->dsi.horizontal_blanking_pixel); + DISPMSG("[LCM] pll_select: %d, pll_div1: %d, pll_div2: %d, fbk_div: %d,fbk_sel: %d, rg_bir: %d\n", + p->dsi.pll_select, p->dsi.pll_div1, p->dsi.pll_div2, p->dsi.fbk_div, + p->dsi.fbk_sel, p->dsi.rg_bir); + DISPMSG("[LCM] rg_bic: %d, rg_bp: %d,PLL_CLOCK: %d, dsi_clock: %d, ssc_range: %d,ssc_disable: %d", + p->dsi.rg_bic, p->dsi.rg_bp, p->dsi.PLL_CLOCK, p->dsi.dsi_clock, + p->dsi.ssc_range, p->dsi.ssc_disable); + DISPMSG("[LCM]compatibility_for_nvk: %d, cont_clock: %d\n", + p->dsi.compatibility_for_nvk, + p->dsi.cont_clock); + DISPMSG("[LCM] lcm_ext_te_enable: %d, noncont_clock: %d, noncont_clock_period: %d\n", + p->dsi.lcm_ext_te_enable, p->dsi.noncont_clock, + p->dsi.noncont_clock_period); + } +} + +disp_lcm_handle *disp_lcm_probe(char *plcm_name, LCM_INTERFACE_ID lcm_id, int is_lcm_inited) +{ + + int lcmindex = 0; + bool isLCMFound = false; + bool isLCMInited = false; + int i; + LCM_DRIVER *lcm_drv = NULL; + LCM_PARAMS *lcm_param = NULL; + disp_lcm_handle *plcm = NULL; + + DISPMSG("plcm_name=%s is_lcm_inited %d\n", plcm_name, is_lcm_inited); + if (_lcm_count() == 0) { + DISPERR("no lcm driver defined in linux kernel driver\n"); + return NULL; + } else if (_lcm_count() == 1) { + if (plcm_name == NULL) { + lcm_drv = lcm_driver_list[0]; + + isLCMFound = true; + isLCMInited = false; + DISPMSG("LCM Name NULL\n"); + } else { + lcm_drv = lcm_driver_list[0]; + if (strcmp(lcm_drv->name, plcm_name)) { + DISPERR + ("FATAL ERROR!!!LCM Driver defined in kernel(%s) is different with LK(%s)\n", + lcm_drv->name, plcm_name); + return NULL; + } + + isLCMInited = true; + isLCMFound = true; + } + + if (!is_lcm_inited) { + isLCMFound = true; + isLCMInited = false; + DISPMSG("LCM not init\n"); + } + + lcmindex = 0; + } else { + if (plcm_name == NULL) { + /* TODO: we need to detect all the lcm driver */ + } else { + + for (i = 0; i < _lcm_count(); i++) { + lcm_drv = lcm_driver_list[i]; + if (!strcmp(lcm_drv->name, plcm_name)) { + isLCMFound = true; + isLCMInited = true; + lcmindex = i; + break; + } + } + if (!isLCMFound) { + DISPERR + ("FATAL ERROR: can't found lcm driver:%s in linux kernel driver\n", + plcm_name); + } else if (!is_lcm_inited) { + isLCMInited = false; + DISPMSG("LCM not init\n"); + } + } + /* TODO: */ + } + + if (isLCMFound == false) { + DISPERR("FATAL ERROR!!!No LCM Driver defined\n"); + return NULL; + } + + plcm = kzalloc(sizeof(uint8_t *) * sizeof(disp_lcm_handle), GFP_KERNEL); + lcm_param = kzalloc(sizeof(uint8_t *) * sizeof(LCM_PARAMS), GFP_KERNEL); + if (plcm && lcm_param) { + plcm->params = lcm_param; + plcm->drv = lcm_drv; + plcm->is_inited = isLCMInited; + plcm->index = lcmindex; + } else { + DISPERR("FATAL ERROR!!!kzalloc plcm and plcm->params failed\n"); + goto FAIL; + } + + plcm->drv->get_params(plcm->params); + plcm->lcm_if_id = plcm->params->lcm_if; + + /* below code is for lcm driver forward compatible */ + if (plcm->params->type == LCM_TYPE_DSI + && plcm->params->lcm_if == LCM_INTERFACE_NOTDEFINED) + plcm->lcm_if_id = LCM_INTERFACE_DSI0; + if (plcm->params->type == LCM_TYPE_DPI + && plcm->params->lcm_if == LCM_INTERFACE_NOTDEFINED) + plcm->lcm_if_id = LCM_INTERFACE_DPI0; + if (plcm->params->type == LCM_TYPE_DBI + && plcm->params->lcm_if == LCM_INTERFACE_NOTDEFINED) + plcm->lcm_if_id = LCM_INTERFACE_DBI0; + + if ((lcm_id == LCM_INTERFACE_NOTDEFINED) || lcm_id == plcm->lcm_if_id) { + plcm->lcm_original_width = plcm->params->width; + plcm->lcm_original_height = plcm->params->height; + _dump_lcm_info(plcm); + return plcm; + } + DISPERR("the specific LCM Interface [%d] didn't define any lcm driver\n", + lcm_id); + +FAIL: + + kfree(plcm); + kfree(lcm_param); + return NULL; +} + +int disp_lcm_init(disp_lcm_handle *plcm, int force) +{ + LCM_DRIVER *lcm_drv = NULL; + + + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + + if (lcm_drv->init_power) { + if (!disp_lcm_is_inited(plcm) || force) { + pr_debug("lcm init power()\n"); + lcm_drv->init_power(); + } + } + + if (lcm_drv->init) { + if (!disp_lcm_is_inited(plcm) || force) { + pr_debug("lcm init()\n"); + lcm_drv->init(); + } + } else { + DISPERR("FATAL ERROR, lcm_drv->init is null\n"); + return -1; + } +#if 0 + if (LCM_TYPE_DSI == plcm->params->type) { + int ret = 0; + char buffer = 0; + + ret = DSI_dcs_read_lcm_reg_v2(DISP_MODULE_DSI0, NULL, 0x0A, &buffer, 1); + if (ret == 0) + pr_debug("lcm is not connected\n"); + else + pr_debug("lcm is connected\n"); + + } +#endif + /* ddp_dsi_start(DISP_MODULE_DSI0, NULL); */ + /* DSI_BIST_Pattern_Test(DISP_MODULE_DSI0,NULL,true, 0x00ffff00); */ + return 0; + } + DISPERR("plcm is null\n"); + return -1; +} + +LCM_PARAMS *disp_lcm_get_params(disp_lcm_handle *plcm) +{ + /* DISPFUNC(); */ + + if (_is_lcm_inited(plcm)) + return plcm->params; + return NULL; +} + +LCM_INTERFACE_ID disp_lcm_get_interface_id(disp_lcm_handle *plcm) +{ + DISPFUNC(); + + if (_is_lcm_inited(plcm)) + return plcm->lcm_if_id; + + return LCM_INTERFACE_NOTDEFINED; +} + +int disp_lcm_update(disp_lcm_handle *plcm, int x, int y, int w, int h, int force) +{ + LCM_DRIVER *lcm_drv = NULL; + int ret = 0; + + DISPFUNC(); + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + if (lcm_drv->update) { + lcm_drv->update(x, y, w, h); + } else { + if (!disp_lcm_is_video_mode(plcm)) + DISPERR("FATAL ERROR, lcm is cmd mode lcm_drv->update is null\n"); + ret = -1; + } + } else { + DISPERR("lcm_drv is null\n"); + ret = -1; + } + return ret; +} + +/* return 1: esd check fail */ +/* return 0: esd check pass */ +int disp_lcm_esd_check(disp_lcm_handle *plcm) +{ + LCM_DRIVER *lcm_drv = NULL; + int ret = 0; + + DISPFUNC(); + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + if (lcm_drv->esd_check) { + ret = lcm_drv->esd_check(); + } else { + DISPERR("FATAL ERROR, lcm_drv->esd_check is null\n"); + ret = 0; + } + } else { + DISPERR("lcm_drv is null\n"); + ret = 0; + } + return ret; +} + + + +int disp_lcm_esd_recover(disp_lcm_handle *plcm) +{ + LCM_DRIVER *lcm_drv = NULL; + int ret = 0; + + DISPFUNC(); + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + if (lcm_drv->esd_recover) { + lcm_drv->esd_recover(); + } else { + DISPERR("FATAL ERROR, lcm_drv->esd_check is null\n"); + ret = -1; + } + } else { + DISPERR("lcm_drv is null\n"); + ret = -1; + } + return ret; +} + +int disp_lcm_suspend(disp_lcm_handle *plcm) +{ + LCM_DRIVER *lcm_drv = NULL; + int ret = 0; + + DISPFUNC(); + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + if (lcm_drv->suspend) { + lcm_drv->suspend(); + } else { + DISPERR("FATAL ERROR, lcm_drv->suspend is null\n"); + ret = -1; + } + if (lcm_drv->suspend_power) + lcm_drv->suspend_power(); + } else { + DISPERR("lcm_drv is null\n"); + ret = -1; + } + return ret; +} + +int disp_lcm_resume(disp_lcm_handle *plcm) +{ + LCM_DRIVER *lcm_drv = NULL; + int ret = 0; + + DISPFUNC(); + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + if (lcm_drv->resume_power) + lcm_drv->resume_power(); + if (lcm_drv->resume) { + lcm_drv->resume(); + } else { + DISPERR("FATAL ERROR, lcm_drv->resume is null\n"); + ret = -1; + } + } else { + DISPERR("lcm_drv is null\n"); + ret = -1; + } + return ret; +} + +int disp_lcm_set_backlight(disp_lcm_handle *plcm, void *handle, int level) +{ + LCM_DRIVER *lcm_drv = NULL; + int ret = 0; + + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + if (lcm_drv->set_backlight_cmdq) { + lcm_drv->set_backlight_cmdq(handle, level); + } else { + DISPERR("FATAL ERROR, lcm_drv->set_backlight is null\n"); + ret = -1; + } + } else { + DISPERR("lcm_drv is null\n"); + ret = -1; + } + return ret; +} + +int disp_lcm_ioctl(disp_lcm_handle *plcm, LCM_IOCTL ioctl, unsigned int arg) +{ + return 0; +} + +int disp_lcm_is_inited(disp_lcm_handle *plcm) +{ + if (_is_lcm_inited(plcm)) + return plcm->is_inited; + else + return 0; +} + +unsigned int disp_lcm_ATA(disp_lcm_handle *plcm) +{ + unsigned int ret = 0; + LCM_DRIVER *lcm_drv = NULL; + + DISPFUNC(); + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + if (lcm_drv->ata_check) { + + ret = lcm_drv->ata_check(NULL); + } else { + DISPERR("FATAL ERROR, lcm_drv->ata_check is null\n"); + ret = 0; + } + } else { + DISPERR("lcm_drv is null\n"); + ret = 0; + } + return ret; +} + +void *disp_lcm_switch_mode(disp_lcm_handle *plcm, int mode) +{ + LCM_DRIVER *lcm_drv = NULL; + LCM_DSI_MODE_SWITCH_CMD *lcm_cmd = NULL; + + if (_is_lcm_inited(plcm)) { + if (plcm->params->dsi.switch_mode_enable == 0) { + DISPERR(" ERROR, Not enable switch in lcm_get_params function\n"); + return NULL; + } + lcm_drv = plcm->drv; + if (lcm_drv->switch_mode) { + lcm_cmd = (LCM_DSI_MODE_SWITCH_CMD *) lcm_drv->switch_mode(mode); + lcm_cmd->cmd_if = (unsigned int)(plcm->params->lcm_cmd_if); + } else { + DISPERR("FATAL ERROR, lcm_drv->switch_mode is null\n"); + return NULL; + } + return (void *)(lcm_cmd); + } + DISPERR("lcm_drv is null\n"); + return NULL; +} + +int disp_lcm_is_video_mode(disp_lcm_handle *plcm) +{ + LCM_PARAMS *lcm_param = NULL; + + if (_is_lcm_inited(plcm)) + lcm_param = plcm->params; + else + BUG(); + + switch (lcm_param->type) { + case LCM_TYPE_DBI: + return false; + case LCM_TYPE_DSI: + break; + case LCM_TYPE_DPI: + return true; + default: + DISPMSG("[LCM] TYPE: unknown\n"); + break; + } + + if (lcm_param->type == LCM_TYPE_DSI) { + switch (lcm_param->dsi.mode) { + case CMD_MODE: + return false; + case SYNC_PULSE_VDO_MODE: + case SYNC_EVENT_VDO_MODE: + case BURST_VDO_MODE: + return true; + default: + DISPMSG("[LCM] DSI Mode: Unknown\n"); + break; + } + } + + BUG(); + return 0; +} + +int disp_lcm_set_lcm_cmd(disp_lcm_handle *plcm, void *cmdq_handle, unsigned int *lcm_cmd, + unsigned int *lcm_count, unsigned int *lcm_value) +{ + int ret = 0; + + LCM_DRIVER *lcm_drv = NULL; + + if (_is_lcm_inited(plcm)) { + lcm_drv = plcm->drv; + if (lcm_drv->set_lcm_cmd) { + lcm_drv->set_lcm_cmd(cmdq_handle, lcm_cmd, lcm_count, lcm_value); + } else { + DISPERR("FATAL ERROR, lcm_drv->set_lcm_cmd is null\n"); + ret = -1; + } + } else { + DISPERR("lcm_drv is null\n"); + ret = -1; + } + return ret; +} diff --git a/drivers/misc/mediatek/video/mt6755/disp_lcm.h b/drivers/misc/mediatek/video/mt6755/disp_lcm.h new file mode 100644 index 0000000000000000000000000000000000000000..23f2139d14a13a1a71a75c667e4f53bdd1b31af8 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_lcm.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _DISP_LCM_H_ +#define _DISP_LCM_H_ +#include "lcm_drv.h" + +#define MAX_LCM_NUMBER 2 + +typedef struct { + LCM_PARAMS *params; + LCM_DRIVER *drv; + LCM_INTERFACE_ID lcm_if_id; + int module; + int is_inited; + unsigned int lcm_original_width; + unsigned int lcm_original_height; + int index; +} disp_lcm_handle, *pdisp_lcm_handle; + + +/* these 2 variables are defined in mt65xx_lcm_list.c */ +extern LCM_DRIVER *lcm_driver_list[]; +extern unsigned int lcm_count; + + +disp_lcm_handle *disp_lcm_probe(char *plcm_name, LCM_INTERFACE_ID lcm_id, int is_lcm_inited); +int disp_lcm_init(disp_lcm_handle *plcm, int force); +LCM_PARAMS *disp_lcm_get_params(disp_lcm_handle *plcm); +LCM_INTERFACE_ID disp_lcm_get_interface_id(disp_lcm_handle *plcm); +int disp_lcm_update(disp_lcm_handle *plcm, int x, int y, int w, int h, int force); +int disp_lcm_esd_check(disp_lcm_handle *plcm); +int disp_lcm_esd_recover(disp_lcm_handle *plcm); +int disp_lcm_suspend(disp_lcm_handle *plcm); +int disp_lcm_resume(disp_lcm_handle *plcm); +int disp_lcm_set_backlight(disp_lcm_handle *plcm, void *handle, int level); +int disp_lcm_read_fb(disp_lcm_handle *plcm); +int disp_lcm_ioctl(disp_lcm_handle *plcm, LCM_IOCTL ioctl, unsigned int arg); +int disp_lcm_is_video_mode(disp_lcm_handle *plcm); +int disp_lcm_is_inited(disp_lcm_handle *plcm); +unsigned int disp_lcm_ATA(disp_lcm_handle *plcm); +void *disp_lcm_switch_mode(disp_lcm_handle *plcm, int mode); +int disp_lcm_set_lcm_cmd(disp_lcm_handle *plcm, void *cmdq_handle, unsigned int *lcm_cmd, + unsigned int *lcm_count, unsigned int *lcm_value); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/disp_lowpower.c b/drivers/misc/mediatek/video/mt6755/disp_lowpower.c new file mode 100644 index 0000000000000000000000000000000000000000..a5a951f2c35f4cc22208cd0dfee25055add744d6 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_lowpower.c @@ -0,0 +1,1123 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtk_ion.h" +#include "ion_drv.h" +#include "mt_idle.h" +#include "mt_spm_reg.h" +#include "mt_boot_common.h" +/* #include "pcm_def.h" */ +#include "mt_spm_idle.h" +#include "mt_smi.h" +#include "m4u.h" + +#include "disp_drv_platform.h" +#include "disp_debug.h" +#include "disp_debug.h" +#include "disp_log.h" +#include "disp_lcm.h" +#include "disp_utils.h" +#include "disp_session.h" +#include "primary_display.h" +#include "disp_helper.h" +#include "cmdq_def.h" +#include "cmdq_record.h" +#include "cmdq_reg.h" +#include "cmdq_core.h" +#include "ddp_manager.h" +#include "disp_lcm.h" +#include "ddp_clkmgr.h" +#include "mt_smi.h" +/* #include "mmdvfs_mgr.h" */ +#include "disp_lowpower.h" +/* device tree */ +#include +#include +#include +#include +#define idlemgr_pgc _get_idlemgr_context() +#define golden_setting_pgc _get_golden_setting_context() +#define kick_dump_max_length (1024 * 16 * 4) +static unsigned char kick_string_buffer_analysize[kick_dump_max_length] = { 0 }; +static unsigned int kick_buf_length; +static atomic_t idlemgr_task_wakeup = ATOMIC_INIT(1); + +#define MMSYS_CLK_LOW (0) +#define MMSYS_CLK_HIGH (1) +#define MMSYS_CLK_MEDIUM (2) + +/* Local API */ +/*********************************************************************************************************************/ +static int _primary_path_idlemgr_monitor_thread(void *data); + +static disp_idlemgr_context *_get_idlemgr_context(void) +{ + static int is_inited; + static disp_idlemgr_context g_idlemgr_context; + + if (!is_inited) { + init_waitqueue_head(&(g_idlemgr_context.idlemgr_wait_queue)); + g_idlemgr_context.session_mode_before_enter_idle = DISP_INVALID_SESSION_MODE; + g_idlemgr_context.is_primary_idle = 0; + g_idlemgr_context.enterulps = 0; + g_idlemgr_context.idlemgr_last_kick_time = ~(0ULL); + g_idlemgr_context.primary_display_idlemgr_task + = kthread_create(_primary_path_idlemgr_monitor_thread, NULL, "disp_idlemgr"); + + /* wakeup process when idlemgr init */ + /* wake_up_process(g_idlemgr_context.primary_display_idlemgr_task); */ + + is_inited = 1; + } + + return &g_idlemgr_context; +} + +int primary_display_idlemgr_init(void) +{ + wake_up_process(idlemgr_pgc->primary_display_idlemgr_task); + return 0; +} + +static golden_setting_context *_get_golden_setting_context(void) +{ + static int is_inited; + static golden_setting_context g_golden_setting_context; + + if (!is_inited) { + /* default setting */ + g_golden_setting_context.is_one_layer = 0; + g_golden_setting_context.fps = 60; + g_golden_setting_context.is_dc = 0; + g_golden_setting_context.is_display_idle = 0; + g_golden_setting_context.is_wrot_sram = 0; + g_golden_setting_context.mmsys_clk = MMSYS_CLK_MEDIUM; /* 286: defalut ; 182: low ; 364: high */ + + /* primary_display */ + g_golden_setting_context.dst_width = primary_get_lcm()->params->width; + g_golden_setting_context.dst_height = primary_get_lcm()->params->height; + g_golden_setting_context.rdma_width = g_golden_setting_context.dst_width; + g_golden_setting_context.rdma_height = g_golden_setting_context.dst_height; + if (g_golden_setting_context.dst_width == 1080 + && g_golden_setting_context.dst_height == 1920) + g_golden_setting_context.hrt_magicnum = 2; + else if (g_golden_setting_context.dst_width == 720 + && g_golden_setting_context.dst_height == 1280) + g_golden_setting_context.hrt_magicnum = 4; + + /* set hrtnum max */ + g_golden_setting_context.hrt_num = g_golden_setting_context.hrt_magicnum + 1; + + /* fifo mode : 0/1/2 */ + if (g_golden_setting_context.is_display_idle) + g_golden_setting_context.fifo_mode = 0; + else if (g_golden_setting_context.hrt_num > g_golden_setting_context.hrt_magicnum) + g_golden_setting_context.fifo_mode = 2; + else + g_golden_setting_context.fifo_mode = 1; + /* ext_display */ + g_golden_setting_context.ext_dst_width = g_golden_setting_context.dst_width; + g_golden_setting_context.ext_dst_height = g_golden_setting_context.dst_height; + g_golden_setting_context.ext_hrt_magicnum = g_golden_setting_context.hrt_magicnum; + g_golden_setting_context.ext_hrt_num = g_golden_setting_context.hrt_num; + + is_inited = 1; + } + + return &g_golden_setting_context; +} + +static void set_fps(unsigned int fps) +{ + golden_setting_pgc->fps = fps; +} + +static void set_is_display_idle(unsigned int is_displayidle) +{ + + if (golden_setting_pgc->is_display_idle != is_displayidle) { + golden_setting_pgc->is_display_idle = is_displayidle; + + if (is_displayidle) + golden_setting_pgc->fifo_mode = 0; + else if (golden_setting_pgc->hrt_num <= golden_setting_pgc->hrt_magicnum) + golden_setting_pgc->fifo_mode = 1; + else + golden_setting_pgc->fifo_mode = 2; + /* notify to mmsys mgr */ + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) { + if (is_displayidle) + ;/*mmdvfs_notify_mmclk_switch_request(MMDVFS_EVENT_UI_IDLE_ENTER);*/ + else + ;/*mmdvfs_notify_mmclk_switch_request(MMDVFS_EVENT_UI_IDLE_EXIT);*/ + } + } + +} + +#if 0 +static unsigned int get_hrtnum(void) +{ + return golden_setting_pgc->hrt_num; +} +#endif + +static void set_share_sram(unsigned int is_share_sram) +{ + if (golden_setting_pgc->is_wrot_sram != is_share_sram) + golden_setting_pgc->is_wrot_sram = is_share_sram; +} + +static unsigned int use_wrot_sram(void) +{ + return golden_setting_pgc->is_wrot_sram; +} + +static void set_mmsys_clk(unsigned int clk) +{ + if (golden_setting_pgc->mmsys_clk != clk) + golden_setting_pgc->mmsys_clk = clk; +} + +static unsigned int get_mmsys_clk(void) +{ + return golden_setting_pgc->mmsys_clk; +} + + +static int primary_display_set_idle_stat(int is_idle) +{ + int old_stat = idlemgr_pgc->is_primary_idle; + + idlemgr_pgc->is_primary_idle = is_idle; + return old_stat; +} + +/* Need blocking for stop trigger loop */ +int _blocking_flush(void) +{ + int ret = 0; + cmdqRecHandle handle = NULL; + + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + if (ret) { + DISPERR("%s:%d, create cmdq handle fail!ret=%d\n", __func__, __LINE__, ret); + return -1; + } + cmdqRecReset(handle); + if (primary_display_is_decouple_mode()) + cmdqRecWaitNoClear(handle, CMDQ_EVENT_DISP_WDMA0_EOF); + _cmdq_insert_wait_frame_done_token_mira(handle); + + cmdqRecFlush(handle); + cmdqRecDestroy(handle); + return ret; +} +int primary_display_dsi_vfp_change(int state) +{ + int ret = 0; + cmdqRecHandle handle = NULL; + + cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + cmdqRecReset(handle); + + /* wait rdma0_sof: only used for video mode & trigger loop need wait and clear rdma0 sof */ + cmdqRecWaitNoClear(handle, CMDQ_EVENT_DISP_RDMA0_SOF); + + if (state == 1) { + /* need calculate fps by vdo mode params */ + /* set_fps(55); */ + dpmgr_path_ioctl(primary_get_dpmgr_handle(), handle, + DDP_DSI_PORCH_CHANGE, + &primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power); + } else if (state == 0) { + + set_fps(primary_display_get_fps_nolock()/100); + dpmgr_path_ioctl(primary_get_dpmgr_handle(), handle, + DDP_DSI_PORCH_CHANGE, + &primary_get_lcm()->params->dsi.vertical_frontporch); + } + cmdqRecFlushAsync(handle); + cmdqRecDestroy(handle); + return ret; +} + +void _idle_set_golden_setting(void) +{ + cmdqRecHandle handle; + disp_ddp_path_config *pconfig = dpmgr_path_get_last_config_notclear(primary_get_dpmgr_handle()); + + /* no need lock */ + /* 1.create and reset cmdq */ + cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + + cmdqRecReset(handle); + + /* 2.wait mutex0_stream_eof: only used for video mode */ + cmdqRecWaitNoClear(handle, CMDQ_EVENT_MUTEX0_STREAM_EOF); + + + /* 3.golden setting */ + dpmgr_path_ioctl(primary_get_dpmgr_handle(), handle, DDP_RDMA_GOLDEN_SETTING, pconfig); + + /* 4.flush */ + cmdqRecFlushAsync(handle); + cmdqRecDestroy(handle); + + +} + +/* Share wrot sram for vdo mode increase enter sodi ratio */ +void _acquire_wrot_resource_nolock(CMDQ_EVENT_ENUM resourceEvent) +{ + cmdqRecHandle handle; + + int32_t acquireResult; + disp_ddp_path_config *pconfig = dpmgr_path_get_last_config_notclear(primary_get_dpmgr_handle()); + + DISPMSG("[disp_lowpower]%s\n", __func__); + if (use_wrot_sram()) + return; + + if (is_mipi_enterulps()) + return; + + /* 1.create and reset cmdq */ + cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + + cmdqRecReset(handle); + + /* 2. wait sof */ + _cmdq_insert_wait_frame_done_token_mira(handle); + + /* 3.try to share wrot sram */ + acquireResult = cmdqRecWriteForResource(handle, resourceEvent, + 0x1400A000+0xb0, 1, ~0); + if (acquireResult < 0) { + /* acquire resource fail */ + DISPERR("acquire resource fail\n"); + + cmdqRecDestroy(handle); + return; + + } else { + /* acquire resource success */ + /* cmdqRecClearEventToken(handle, resourceEvent); //???cmdq do it */ + + /* set rdma golden setting parameters*/ + set_share_sram(1); + + /* add instr for modification rdma fifo regs */ + /* dpmgr_handle can cover both dc & dl */ + if (disp_helper_get_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING)) + dpmgr_path_ioctl(primary_get_dpmgr_handle(), handle, DDP_RDMA_GOLDEN_SETTING, pconfig); + + } + + cmdqRecFlushAsync(handle); + cmdqRecDestroy(handle); + + +} + +static int32_t _acquire_wrot_resource(CMDQ_EVENT_ENUM resourceEvent) +{ + primary_display_manual_lock(); + _acquire_wrot_resource_nolock(resourceEvent); + primary_display_manual_unlock(); + return 0; +} + + +void _release_wrot_resource_nolock(CMDQ_EVENT_ENUM resourceEvent) +{ + cmdqRecHandle handle; + disp_ddp_path_config *pconfig = dpmgr_path_get_last_config_notclear(primary_get_dpmgr_handle()); + + DISPMSG("[disp_lowpower]%s\n", __func__); + if (use_wrot_sram() == 0) + return; + + /* 1.create and reset cmdq */ + cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + + cmdqRecReset(handle); + + /* 2.wait sof */ + _cmdq_insert_wait_frame_done_token_mira(handle); + + /* 3.release share sram */ + cmdqRecWrite(handle, 0x1400A000+0xb0, 0, ~0); /* why need ??? */ + cmdqRecReleaseResource(handle, resourceEvent); + + /* set rdma golden setting parameters*/ + set_share_sram(0); + + /* 4.add instr for modification rdma fifo regs */ + /* rdma: dpmgr_handle can cover both dc & dl */ + if (disp_helper_get_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING)) + dpmgr_path_ioctl(primary_get_dpmgr_handle(), handle, DDP_RDMA_GOLDEN_SETTING, pconfig); + + cmdqRecFlushAsync(handle); + cmdqRecDestroy(handle); + + +} + +static int32_t _release_wrot_resource(CMDQ_EVENT_ENUM resourceEvent) +{ + /* need lock */ + primary_display_manual_lock(); + _release_wrot_resource_nolock(resourceEvent); + primary_display_manual_unlock(); + + return 0; +} + +int _switch_mmsys_clk_callback(unsigned int need_disable_pll) +{ + /* disable vencpll */ + if (need_disable_pll == MM_VENCPLL) { + ddp_clk_set_parent(MUX_MM, SYSPLL2_D2); + ddp_clk_disable_unprepare(MUX_MM); + ddp_clk_disable_unprepare(MM_VENCPLL); + } else if (need_disable_pll == SYSPLL2_D2) { + ddp_clk_set_parent(MUX_MM, MM_VENCPLL); + ddp_clk_disable_unprepare(MUX_MM); + ddp_clk_disable_unprepare(SYSPLL2_D2); + } + return 0; +} +int _switch_mmsys_clk(int mmsys_clk_old, int mmsys_clk_new) +{ + int ret = 0; + cmdqRecHandle handle; + unsigned int need_disable_pll = 0; + disp_ddp_path_config *pconfig = dpmgr_path_get_last_config_notclear(primary_get_dpmgr_handle()); + + DISPMSG("[disp_lowpower]%s\n", __func__); + if (mmsys_clk_new == get_mmsys_clk()) + return ret; + + if (primary_get_state() != DISP_ALIVE || is_mipi_enterulps()) { + DISPMSG("[disp_lowpower]_switch_mmsys_clk when display suspend old = %d & new = %d.\n", + mmsys_clk_old, mmsys_clk_new); + return ret; + } + /* 1.create and reset cmdq */ + cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + + cmdqRecReset(handle); + + if (mmsys_clk_old == MMSYS_CLK_MEDIUM && mmsys_clk_new == MMSYS_CLK_LOW) { + /* 2.wait sof */ + _cmdq_insert_wait_frame_done_token_mira(handle); + + ddp_clk_prepare_enable(MUX_MM); + ddp_clk_prepare_enable(SYSPLL2_D2); + cmdqRecWrite(handle, 0x10000048, 0x07000000, 0x07000000); /* clear */ + cmdqRecWrite(handle, 0x10000044, 0x04000000, 0x04000000); /* set syspll2_d2 */ + cmdqRecWrite(handle, 0x10000004, 8, 8); /* update */ + + /* set rdma golden setting parameters */ + set_mmsys_clk(MMSYS_CLK_LOW); + need_disable_pll = MM_VENCPLL; + + } else if (mmsys_clk_old == MMSYS_CLK_LOW && mmsys_clk_new == MMSYS_CLK_MEDIUM) { + /* 2.wait sof */ + _cmdq_insert_wait_frame_done_token_mira(handle); + + /* enable vencpll */ + ddp_clk_prepare_enable(MUX_MM); + ddp_clk_prepare_enable(MM_VENCPLL); + cmdqRecWrite(handle, 0x10000048, 0x07000000, 0x07000000); /* clear */ + cmdqRecWrite(handle, 0x10000044, 0x02000000, 0x02000000); /* set vencpll */ + cmdqRecWrite(handle, 0x10000004, 8, 8); /* update */ + + /* set rdma golden setting parameters */ + set_mmsys_clk(MMSYS_CLK_MEDIUM); + need_disable_pll = SYSPLL2_D2; + + } else if (mmsys_clk_old == MMSYS_CLK_MEDIUM && mmsys_clk_new == MMSYS_CLK_HIGH) { + /* 2.wait sof */ + _cmdq_insert_wait_frame_done_token_mira(handle); + /* 286 => 364 */ + /* set rdma golden setting parameters */ + set_mmsys_clk(MMSYS_CLK_HIGH); + + } else if (mmsys_clk_old == MMSYS_CLK_HIGH && mmsys_clk_new == MMSYS_CLK_MEDIUM) { + /* 2.wait sof */ + _cmdq_insert_wait_frame_done_token_mira(handle); + /* 364 => 286 */ + /* set rdma golden setting parameters */ + set_mmsys_clk(MMSYS_CLK_MEDIUM); + } else + goto cmdq_d; + + + /* 4.add instr for modification rdma fifo regs */ + /* rdma: dpmgr_handle can cover both dc & dl */ + if (disp_helper_get_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING)) + dpmgr_path_ioctl(primary_get_dpmgr_handle(), handle, DDP_RDMA_GOLDEN_SETTING, pconfig); + + + cmdqRecFlush(handle); + +cmdq_d: + cmdqRecDestroy(handle); + + _switch_mmsys_clk_callback(need_disable_pll); + return get_mmsys_clk(); + +} +int primary_display_switch_mmsys_clk(int mmsys_clk_old, int mmsys_clk_new) +{ + /* need lock */ + DISPMSG("[disp_lowpower]%s\n", __func__); + primary_display_manual_lock(); + _switch_mmsys_clk(mmsys_clk_old, mmsys_clk_new); + primary_display_manual_unlock(); + return 0; +} +void _primary_display_disable_mmsys_clk(void) +{ + if (primary_get_sess_mode() == DISP_SESSION_RDMA_MODE) { + /* switch back to DL mode before suspend */ + do_primary_display_switch_mode(DISP_SESSION_DIRECT_LINK_MODE, + primary_get_sess_id(), 0, NULL, 1); + } + if (primary_get_sess_mode() != DISP_SESSION_DIRECT_LINK_MODE) + return; + + /* blocking flush before stop trigger loop */ + _blocking_flush(); + /* no need lock now */ + if (disp_helper_get_option(DISP_OPT_USE_CMDQ)) { + DISPDBG("[LP]1.display cmdq trigger loop stop[begin]\n"); + _cmdq_stop_trigger_loop(); + DISPDBG("[LP]1.display cmdq trigger loop stop[end]\n"); + } + + DISPDBG("[LP]2.primary display path stop[begin]\n"); + dpmgr_path_stop(primary_get_dpmgr_handle(), CMDQ_DISABLE); + DISPDBG("[LP]2.primary display path stop[end]\n"); + + if (dpmgr_path_is_busy(primary_get_dpmgr_handle())) { + DISPERR("[LP]2.stop display path failed, still busy\n"); + dpmgr_path_reset(primary_get_dpmgr_handle(), CMDQ_DISABLE); + /* even path is busy(stop fail), we still need to continue power off other module/devices */ + } + + /* can not release fence here */ + DISPDBG("[LP]3.dpmanager path power off[begin]\n"); + dpmgr_path_power_off_bypass_pwm(primary_get_dpmgr_handle(), CMDQ_DISABLE); + + if (primary_display_is_decouple_mode()) { + DISPMSG("[LP]3.1 dpmanager path power off: ovl2men [begin]\n"); + if (primary_get_ovl2mem_handle()) + dpmgr_path_power_off(primary_get_ovl2mem_handle(), CMDQ_DISABLE); + else + DISPERR("display is decouple mode, but ovl2mem_path_handle is null\n"); + + DISPMSG("[LP]3.1 dpmanager path power off: ovl2men [end]\n"); + } + DISPMSG("[LP]3.dpmanager path power off[end]\n"); + if (disp_helper_get_option(DISP_OPT_MET_LOG)) + set_enterulps(1); + + + +} + +void _primary_display_enable_mmsys_clk(void) +{ + disp_ddp_path_config *data_config; + struct ddp_io_golden_setting_arg gset_arg; + + if (primary_get_sess_mode() != DISP_SESSION_DIRECT_LINK_MODE) + return; + /* do something */ + DISPDBG("[LP]1.dpmanager path power on[begin]\n"); + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(primary_get_dpmgr_handle()); + if (primary_display_is_decouple_mode()) { + if (primary_get_ovl2mem_handle() == NULL) { + DISPERR("display is decouple mode, but ovl2mem_path_handle is null\n"); + return; + } + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(primary_get_ovl2mem_handle()); + gset_arg.is_decouple_mode = 1; + DISPDBG("[LP]1.1 dpmanager path power on: ovl2men [begin]\n"); + dpmgr_path_power_on(primary_get_ovl2mem_handle(), CMDQ_DISABLE); + DISPDBG("[LP]1.1 dpmanager path power on: ovl2men [end]\n"); + } + + dpmgr_path_power_on_bypass_pwm(primary_get_dpmgr_handle(), CMDQ_DISABLE); + DISPDBG("[LP]1.dpmanager path power on[end]\n"); + if (disp_helper_get_option(DISP_OPT_MET_LOG)) + set_enterulps(0); + + DISPDBG("[LP]2.dpmanager path config[begin]\n"); + + /* disconnect primary path first * + * because MMsys config register may not power off during early suspend + * BUT session mode may change in primary_display_switch_mode() */ + ddp_disconnect_path(DDP_SCENARIO_PRIMARY_ALL, NULL); + ddp_disconnect_path(DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP, NULL); + + dpmgr_path_connect(primary_get_dpmgr_handle(), CMDQ_DISABLE); + if (primary_display_is_decouple_mode()) + dpmgr_path_connect(primary_get_ovl2mem_handle(), CMDQ_DISABLE); + + data_config = dpmgr_path_get_last_config(primary_get_dpmgr_handle()); + + data_config->dst_dirty = 1; + data_config->ovl_dirty = 1; + data_config->rdma_dirty = 1; + dpmgr_path_config(primary_get_dpmgr_handle(), data_config, NULL); + + if (primary_display_is_decouple_mode()) { + + data_config = dpmgr_path_get_last_config(primary_get_dpmgr_handle()); + data_config->rdma_dirty = 1; + dpmgr_path_config(primary_get_dpmgr_handle(), data_config, NULL); + + data_config = dpmgr_path_get_last_config(primary_get_ovl2mem_handle()); + data_config->dst_dirty = 1; + dpmgr_path_config(primary_get_ovl2mem_handle(), data_config, NULL); + dpmgr_path_ioctl(primary_get_ovl2mem_handle(), NULL, DDP_OVL_GOLDEN_SETTING, &gset_arg); + } else { + dpmgr_path_ioctl(primary_get_dpmgr_handle(), NULL, DDP_OVL_GOLDEN_SETTING, &gset_arg); + } + + DISPMSG("[LP]2.dpmanager path config[end]\n"); + + DISPDBG("[LP]3.dpmgr path start[begin]\n"); + dpmgr_path_start(primary_get_dpmgr_handle(), CMDQ_DISABLE); + + if (primary_display_is_decouple_mode()) + dpmgr_path_start(primary_get_ovl2mem_handle(), CMDQ_DISABLE); + + DISPDBG("[LP]3.dpmgr path start[end]\n"); + if (dpmgr_path_is_busy(primary_get_dpmgr_handle())) + DISPERR("[LP]3.Fatal error, we didn't trigger display path but it's already busy\n"); + + + if (disp_helper_get_option(DISP_OPT_USE_CMDQ)) { + DISPDBG("[LP]4.start cmdq[begin]\n"); + _cmdq_start_trigger_loop(); + DISPDBG("[LP]4.start cmdq[end]\n"); + } + + /* (in suspend) when we stop trigger loop + * if no other thread is running, cmdq may disable its clock + * all cmdq event will be cleared after suspend */ + cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_EOF); +} + +/* Share wrot sram end */ +void _vdo_mode_enter_idle(void) +{ + int ret = 0; + + DISPMSG("[disp_lowpower]%s\n", __func__); + + /* backup for DL <-> DC */ + idlemgr_pgc->session_mode_before_enter_idle = primary_get_sess_mode(); + + /* DL -> DC*/ + if (!primary_is_sec() && + primary_get_sess_mode() == DISP_SESSION_DIRECT_LINK_MODE && + (disp_helper_get_option(DISP_OPT_IDLEMGR_SWTCH_DECOUPLE) || + disp_helper_get_option(DISP_OPT_SMART_OVL))) { + if (disp_helper_get_option(DISP_OPT_GMO_OPTIMIZE)) + ret = pd_allocate_dc_buffer(); + /* smart_ovl_try_switch_mode_nolock(); */ + /* switch to decouple mode */ + if (!ret) { + do_primary_display_switch_mode(DISP_SESSION_DECOUPLE_MODE, primary_get_sess_id(), 0, NULL, 0); + set_is_dc(1); + } else + DISPMSG("pd_allocate_dc_buffer fail\n"); + /* merge setting when the last one */ + /* + if (disp_helper_get_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING)) + _idle_set_golden_setting(); + */ + } + + /* Disable irq & increase vfp */ + if (!primary_is_sec()) { + if (disp_helper_get_option(DISP_OPT_IDLEMGR_DISABLE_ROUTINE_IRQ)) { + /* disable routine irq before switch to decouple mode, otherwise we need to disable two paths */ + dpmgr_path_enable_irq(primary_get_dpmgr_handle(), NULL, DDP_IRQ_LEVEL_ERROR); + } + + if (get_lp_cust_mode() > LP_CUST_DISABLE && get_lp_cust_mode() < PERFORMANC_MODE + 1) { + switch (get_lp_cust_mode()) { + case LOW_POWER_MODE: /* 50 */ + primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power = 400; + set_fps(50); + primary_display_dsi_vfp_change(1); + break; + case JUST_MAKE_MODE: /* 55 */ + primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power = 200; + set_fps(55); + primary_display_dsi_vfp_change(1); + break; + case PERFORMANC_MODE: /* 60 */ + primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power = 0; + set_fps(primary_display_get_fps_nolock()/100); + primary_display_dsi_vfp_change(0); + break; + } + } else { + if (get_backup_vfp() != primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power) + primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power = get_backup_vfp(); + + if (primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power) { + set_fps(50); + primary_display_dsi_vfp_change(1); + } + } + + } + + /* DC homeidle share wrot sram */ + /* + if (disp_helper_get_option(DISP_OPT_SHARE_SRAM) + && (primary_get_sess_mode() == DISP_SESSION_DECOUPLE_MODE + || primary_get_sess_mode() == DISP_SESSION_RDMA_MODE)) + enter_share_sram(CMDQ_SYNC_RESOURCE_WROT0); + */ + + /* set golden setting , merge fps/dc */ + set_is_display_idle(1); + if (disp_helper_get_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING)) + _idle_set_golden_setting(); + +#if 0 + /* Enable sodi - need wait golden setting done ??? */ + if (disp_helper_get_option(DISP_OPT_SODI_SUPPORT)) { + /* set power down mode forbidden */ + spm_sodi_mempll_pwr_mode(1); + spm_enable_sodi(1); + } +#endif +} + +void _vdo_mode_leave_idle(void) +{ + DISPMSG("[disp_lowpower]%s\n", __func__); + +#if 0 + /* Disable sodi */ + if (disp_helper_get_option(DISP_OPT_SODI_SUPPORT)) + spm_enable_sodi(0); +#endif + + /* set golden setting */ + set_is_display_idle(0); + if (disp_helper_get_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING)) + _idle_set_golden_setting(); + + /* DC homeidle share wrot sram */ + /* + if (disp_helper_get_option(DISP_OPT_SHARE_SRAM) + && (primary_get_sess_mode() == DISP_SESSION_DECOUPLE_MODE + || primary_get_sess_mode() == DISP_SESSION_RDMA_MODE)) + leave_share_sram(CMDQ_SYNC_RESOURCE_WROT0); + */ + + /* Enable irq & restore vfp */ + if (!primary_is_sec()) { + + if (primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power) { + primary_display_dsi_vfp_change(0); + if (disp_helper_get_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING)) + _idle_set_golden_setting(); + } + if (disp_helper_get_option(DISP_OPT_IDLEMGR_DISABLE_ROUTINE_IRQ)) { + /* enable routine irq after switch to directlink mode, otherwise we need to disable two paths */ + dpmgr_path_enable_irq(primary_get_dpmgr_handle(), NULL, DDP_IRQ_LEVEL_ALL); + } + } + + /* DC -> DL */ + if (disp_helper_get_option(DISP_OPT_IDLEMGR_SWTCH_DECOUPLE) && + !disp_helper_get_option(DISP_OPT_SMART_OVL)) { + /* switch to the mode before idle */ + do_primary_display_switch_mode(idlemgr_pgc->session_mode_before_enter_idle, + primary_get_sess_id(), 0, NULL, 0); + + set_is_dc(0); + if (disp_helper_get_option(DISP_OPT_DYNAMIC_RDMA_GOLDEN_SETTING)) + _idle_set_golden_setting(); + } + +} +void _cmd_mode_enter_idle(void) +{ + DISPMSG("[disp_lowpower]%s\n", __func__); + + /* need leave share sram for disable mmsys clk */ + if (disp_helper_get_option(DISP_OPT_SHARE_SRAM)) + leave_share_sram(CMDQ_SYNC_RESOURCE_WROT0); + + /* please keep last */ + if (disp_helper_get_option(DISP_OPT_IDLEMGR_ENTER_ULPS)) { + /* switch to vencpll before disable mmsys clk */ + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) + ;/*mmdvfs_notify_mmclk_switch_request(MMDVFS_EVENT_OVL_SINGLE_LAYER_EXIT);*/ + /* need delay to make sure done??? */ + _primary_display_disable_mmsys_clk(); + /* Enable SODI3 after mmsys is disabled */ + spm_enable_sodi3(1); + } + + +} +void _cmd_mode_leave_idle(void) +{ + DISPMSG("[disp_lowpower]%s\n", __func__); + + if (disp_helper_get_option(DISP_OPT_IDLEMGR_ENTER_ULPS)) { + /* Disable SODI3 before mmsys is enabled */ + spm_enable_sodi3(0); + _primary_display_enable_mmsys_clk(); + } + + + if (disp_helper_get_option(DISP_OPT_SHARE_SRAM)) + enter_share_sram(CMDQ_SYNC_RESOURCE_WROT0); +} +void primary_display_idlemgr_enter_idle_nolock(void) +{ + if (primary_display_is_video_mode()) + _vdo_mode_enter_idle(); + else + _cmd_mode_enter_idle(); +} + +void primary_display_idlemgr_leave_idle_nolock(void) +{ + + if (primary_display_is_video_mode()) + _vdo_mode_leave_idle(); + else + _cmd_mode_leave_idle(); +} + +static int _primary_path_idlemgr_monitor_thread(void *data) +{ + int ret = 0; + + msleep(16000); + while (1) { + msleep(100); /* 100ms */ + ret = wait_event_interruptible(idlemgr_pgc->idlemgr_wait_queue, atomic_read(&idlemgr_task_wakeup)); + + primary_display_manual_lock(); + + if (primary_get_state() != DISP_ALIVE) { + primary_display_manual_unlock(); + primary_display_wait_state(DISP_ALIVE, MAX_SCHEDULE_TIMEOUT); + continue; + } + + if (primary_display_is_idle()) { + primary_display_manual_unlock(); + continue; + } + + if (((local_clock() - idlemgr_pgc->idlemgr_last_kick_time) / 1000) < 500 * 1000) { + /* kicked in 500ms, it's not idle */ + primary_display_manual_unlock(); + continue; + } + MMProfileLogEx(ddp_mmp_get_events()->idlemgr, MMProfileFlagStart, 0, 0); + DISPDBG("[disp_lowpower]primary enter idle state\n"); + + /* enter idle state */ + dprec_logger_start(DPREC_LOGGER_IDLEMGR, 0, 0); + primary_display_idlemgr_enter_idle_nolock(); + primary_display_set_idle_stat(1); + + primary_display_manual_unlock(); + + wait_event_interruptible(idlemgr_pgc->idlemgr_wait_queue, !primary_display_is_idle()); + + if (kthread_should_stop()) + break; + } + + return 0; +} + +void kick_logger_dump(char *string) +{ + if (kick_buf_length + strlen(string) >= kick_dump_max_length) + kick_logger_dump_reset(); + + kick_buf_length += scnprintf(kick_string_buffer_analysize + kick_buf_length, + kick_dump_max_length - kick_buf_length, string); + + +} + +void kick_logger_dump_reset(void) +{ + kick_buf_length = 0; + memset(kick_string_buffer_analysize, 0, sizeof(kick_string_buffer_analysize)); + +} + +char *get_kick_dump(void) +{ + return kick_string_buffer_analysize; +} + +unsigned int get_kick_dump_size(void) +{ + return kick_buf_length; +} + +/* API */ +/*********************************************************************************************************************/ +golden_setting_context *get_golden_setting_pgc(void) +{ + return golden_setting_pgc; +} + +/* for met - begin */ +unsigned int is_mipi_enterulps(void) +{ + return idlemgr_pgc->enterulps; +} + +unsigned int get_mipi_clk(void) +{ + + if (disp_helper_get_option(DISP_OPT_MET_LOG)) { + if (is_mipi_enterulps()) + return 0; + else + return dsi_phy_get_clk(DISP_MODULE_NUM); + } else { + return 0; + } +} +void primary_display_sodi_enable(int flag) +{ + spm_enable_sodi(flag); +} +/* for met - end */ +void primary_display_sodi_rule_init(void) +{ + /* enable sodi when display driver is ready */ + if (primary_display_is_video_mode()) { + /* set power down mode forbidden */ + spm_sodi_mempll_pwr_mode(1); + spm_enable_sodi(1); + } else + primary_display_sodi_enable(1); + +} + +int primary_display_lowpower_init(void) +{ + set_fps(primary_display_get_fps_nolock()/100); + backup_vfp_for_lp_cust(primary_get_lcm()->params->dsi.vertical_frontporch_for_low_power); + /* init idlemgr */ + if (disp_helper_get_option(DISP_OPT_IDLE_MGR) && get_boot_mode() == NORMAL_BOOT) + primary_display_idlemgr_init(); + + + if (disp_helper_get_option(DISP_OPT_SODI_SUPPORT)) + primary_display_sodi_rule_init(); + + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) + /* callback with lock or without lock ??? */ + ;/*register_mmclk_switch_cb(primary_display_switch_mmsys_clk, _switch_mmsys_clk);*/ + + /* cmd mode always enable share sram */ + if (disp_helper_get_option(DISP_OPT_SHARE_SRAM)) + enter_share_sram(CMDQ_SYNC_RESOURCE_WROT0); + return 0; + +} + + +int primary_display_is_idle(void) +{ + return idlemgr_pgc->is_primary_idle; +} + +void primary_display_idlemgr_kick(const char *source, int need_lock) +{ + char log[128] = ""; + + MMProfileLogEx(ddp_mmp_get_events()->idlemgr, MMProfileFlagPulse, 1, 0); + snprintf(log, sizeof(log), "[kick]%s kick at %lld\n", source, sched_clock()); + kick_logger_dump(log); + + /* get primary lock to protect idlemgr_last_kick_time and primary_display_is_idle() */ + if (need_lock) + primary_display_manual_lock(); + + /* update kick timestamp */ + idlemgr_pgc->idlemgr_last_kick_time = sched_clock(); + + if (primary_display_is_idle()) { + primary_display_idlemgr_leave_idle_nolock(); + primary_display_set_idle_stat(0); + dprec_logger_done(DPREC_LOGGER_IDLEMGR, 0, 0); + + MMProfileLogEx(ddp_mmp_get_events()->idlemgr, MMProfileFlagEnd, 0, 0); + /* wake up idlemgr process to monitor next idle stat */ + wake_up_interruptible(&(idlemgr_pgc->idlemgr_wait_queue)); + } + + if (need_lock) + primary_display_manual_unlock(); +} + +#if 0 /* move to mt_spm_sodi_cmdq.c */ +void exit_pd_by_cmdq(cmdqRecHandle handler) +{ + /* Enable SPM CG Mode(Force 30+ times to ensure write success, need find root cause and fix later) */ + cmdqRecWrite(handler, 0x100062B0, 0x2, ~0); + /* Polling EMI Status to ensure EMI is enabled */ + cmdqRecPoll(handler, 0x1000611C, 0x10000, 0x10000); +} + +void enter_pd_by_cmdq(cmdqRecHandle handler) +{ + cmdqRecWrite(handler, 0x100062B0, 0x0, 0x2); +} +#endif + +void enter_share_sram(CMDQ_EVENT_ENUM resourceEvent) +{ + /* 1. register call back first */ + cmdqCoreSetResourceCallback(CMDQ_SYNC_RESOURCE_WROT0, + _acquire_wrot_resource, _release_wrot_resource); + + /* 2. try to allocate sram at the fisrt time */ + _acquire_wrot_resource_nolock(CMDQ_SYNC_RESOURCE_WROT0); +} + +void leave_share_sram(CMDQ_EVENT_ENUM resourceEvent) +{ + /* 1. unregister call back */ + cmdqCoreSetResourceCallback(CMDQ_SYNC_RESOURCE_WROT0, NULL, NULL); + + /* 2. try to release share sram */ + _release_wrot_resource_nolock(CMDQ_SYNC_RESOURCE_WROT0); +} + + +void set_hrtnum(unsigned int new_hrtnum) +{ + if (golden_setting_pgc->hrt_num != new_hrtnum) { + if ((golden_setting_pgc->hrt_num > golden_setting_pgc->hrt_magicnum + && new_hrtnum <= golden_setting_pgc->hrt_magicnum) + || (golden_setting_pgc->hrt_num <= golden_setting_pgc->hrt_magicnum + && new_hrtnum > golden_setting_pgc->hrt_magicnum)) { + /* should not on screenidle when set hrtnum */ + if (new_hrtnum > golden_setting_pgc->hrt_magicnum) + golden_setting_pgc->fifo_mode = 2; + else + golden_setting_pgc->fifo_mode = 1; + + } + golden_setting_pgc->hrt_num = new_hrtnum; + } +} + +/* set enterulps flag after power on & power off */ +void set_enterulps(unsigned flag) +{ + idlemgr_pgc->enterulps = flag; +} + +void set_is_dc(unsigned int is_dc) +{ + if (golden_setting_pgc->is_dc != is_dc) + golden_setting_pgc->is_dc = is_dc; + +} + +/* return 0: no change / return 1: change */ +unsigned int set_one_layer(unsigned int is_onelayer) +{ + if (golden_setting_pgc->is_one_layer == is_onelayer) + return 0; + + golden_setting_pgc->is_one_layer = is_onelayer; + + return 1; +} +void set_rdma_width_height(unsigned int width, unsigned height) +{ + golden_setting_pgc->rdma_width = width; + golden_setting_pgc->rdma_height = height; +} + +void enable_idlemgr(unsigned int flag) +{ + if (flag) { + DISPMSG("[disp_lowpower]enabel idlemgr\n"); + atomic_set(&idlemgr_task_wakeup, 1); + wake_up_interruptible(&(idlemgr_pgc->idlemgr_wait_queue)); + } else { + DISPMSG("[disp_lowpower]disable idlemgr\n"); + atomic_set(&idlemgr_task_wakeup, 0); + primary_display_idlemgr_kick((char *)__func__, 1); + } +} +unsigned int get_idlemgr_flag(void) +{ + unsigned int idlemgr_flag; + + idlemgr_flag = atomic_read(&idlemgr_task_wakeup); + return idlemgr_flag; +} + +unsigned int set_idlemgr(unsigned int flag, int need_lock) +{ + unsigned int old_flag = atomic_read(&idlemgr_task_wakeup); + + if (flag) { + DISPMSG("[disp_lowpower]enable idlemgr\n"); + atomic_set(&idlemgr_task_wakeup, 1); + wake_up_interruptible(&(idlemgr_pgc->idlemgr_wait_queue)); + } else { + DISPMSG("[disp_lowpower]disable idlemgr\n"); + atomic_set(&idlemgr_task_wakeup, 0); + primary_display_idlemgr_kick((char *)__func__, need_lock); + } + return old_flag; +} diff --git a/drivers/misc/mediatek/video/mt6755/disp_lowpower.h b/drivers/misc/mediatek/video/mt6755/disp_lowpower.h new file mode 100644 index 0000000000000000000000000000000000000000..99d544fefb594bb7691ddd10b9320931779ec66a --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_lowpower.h @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#ifndef _DISP_LOWPOWER_H_ +#define _DISP_LOWPOWER_H_ + +unsigned int dsi_phy_get_clk(DISP_MODULE_ENUM module); +void primary_display_idlemgr_enter_idle_nolock(void); + + +golden_setting_context *get_golden_setting_pgc(void); +int primary_display_lowpower_init(void); +void primary_display_sodi_rule_init(void); +void kick_logger_dump(char *string); +void kick_logger_dump_reset(void); +char *get_kick_dump(void); +unsigned int get_kick_dump_size(void); +/* +return 0: display is not idle trigger now +return 1: display is idle +*/ +int primary_display_is_idle(void); +void primary_display_idlemgr_kick(const char *source, int need_lock); +void exit_pd_by_cmdq(cmdqRecHandle handler); +void enter_pd_by_cmdq(cmdqRecHandle handler); +void enter_share_sram(CMDQ_EVENT_ENUM resourceEvent); +void leave_share_sram(CMDQ_EVENT_ENUM resourceEvent); +void set_hrtnum(unsigned int new_hrtnum); +void set_enterulps(unsigned flag); +void set_is_dc(unsigned int is_dc); +unsigned int set_one_layer(unsigned int is_onelayer); +void set_rdma_width_height(unsigned int width, unsigned height); +void enable_idlemgr(unsigned int flag); +unsigned int get_idlemgr_flag(void); +unsigned int set_idlemgr(unsigned int flag, int need_lock); +int _blocking_flush(void); +void primary_display_sodi_enable(int flag); +/**************************************** for met******************************************* */ +/* +return 0: not enter ultra lowpower state which means mipi pll enable +return 1: enter ultra lowpower state whicn means mipi pll disable +*/ +unsigned int is_mipi_enterulps(void); + +/* +read dsi regs to calculate clk +*/ +unsigned int get_mipi_clk(void); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/disp_recovery.c b/drivers/misc/mediatek/video/mt6755/disp_recovery.c new file mode 100644 index 0000000000000000000000000000000000000000..0a89b67a7dceaf1099d81b0396ac7943c4ff4d9c --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_recovery.c @@ -0,0 +1,800 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtk_ion.h" +#include "ion_drv.h" +#include +#include "mt_idle.h" +#include "mt_spm_reg.h" +/* #include "pcm_def.h" */ +#include "mt_spm_idle.h" +#include "mt_smi.h" +#include "m4u.h" + +#include "disp_drv_platform.h" +#include "disp_debug.h" +#include "disp_debug.h" +#include "disp_lcm.h" +#include "disp_utils.h" +#include "disp_session.h" +#include "primary_display.h" +#include "disp_helper.h" +#include "cmdq_def.h" +#include "cmdq_record.h" +#include "cmdq_reg.h" +#include "cmdq_core.h" +#include "ddp_manager.h" +#include "disp_lcm.h" +#include "ddp_clkmgr.h" +#include "mt_smi.h" +/* #include "mmdvfs_mgr.h" */ +#include "disp_log.h" +#include "disp_lowpower.h" +/* device tree */ +#include +#include +#include +#include +/*#include "mach/eint.h"*/ +#if defined(CONFIG_MTK_LEGACY) +#include +#include +#include +#else +#include "disp_dts_gpio.h" +#endif + +#include "disp_recovery.h" + +static struct task_struct *primary_display_check_task; /* For abnormal check */ +static wait_queue_head_t _check_task_wq; /* used for blocking check task */ +static atomic_t _check_task_wakeup = ATOMIC_INIT(0); /* For Check Task */ + +static wait_queue_head_t esd_ext_te_wq; /* For EXT TE EINT Check */ +static atomic_t esd_ext_te_event = ATOMIC_INIT(0); /* For EXT TE EINT Check */ +static unsigned int esd_check_mode; +static unsigned int esd_check_enable; +static unsigned int esd_init; + +unsigned int get_esd_check_mode(void) +{ + return esd_check_mode; +} + +void set_esd_check_mode(unsigned int mode) +{ + esd_check_mode = mode; +} + +unsigned int _can_switch_check_mode(void) +{ + int ret = 0; + + if (primary_get_lcm()->params->dsi.customization_esd_check_enable == 0 + && primary_get_lcm()->params->dsi.lcm_esd_check_table[0].cmd != 0) + ret = 1; + return ret; +} + +bool _can_do_read_reg(void) +{ + bool ret = false; + + if (primary_display_is_video_mode()) + ret = true; + else if (!disp_helper_get_option(DISP_OPT_IDLE_MGR)) + ret = true; + if (primary_get_lcm()->params->dsi.lcm_esd_check_table[0].cmd == 0) + ret = false; + + return ret; +} + +static unsigned int _need_do_esd_check(void) +{ + int ret = 0; +#ifdef CONFIG_OF + if ((primary_get_lcm()->params->dsi.esd_check_enable == 1) && (islcmconnected == 1)) + ret = 1; + +#else + if (primary_get_lcm()->params->dsi.esd_check_enable == 1) + ret = 1; + +#endif + return ret; +} + +/* For Cmd Mode Read LCM Check */ +/* Config cmdq_handle_config_esd */ +int _esd_check_config_handle_cmd(cmdqRecHandle handle) +{ + int ret = 0; /* 0:success */ + + /* 1.reset */ + cmdqRecReset(handle); + + primary_display_manual_lock(); + + /* 2.write first instruction */ + /* cmd mode: wait CMDQ_SYNC_TOKEN_STREAM_EOF(wait trigger thread done) */ + cmdqRecWaitNoClear(handle, CMDQ_SYNC_TOKEN_STREAM_EOF); + + /* 3.clear CMDQ_SYNC_TOKEN_ESD_EOF(trigger thread need wait this sync token) */ + cmdqRecClearEventToken(handle, CMDQ_SYNC_TOKEN_ESD_EOF); + + /* 4.write instruction(read from lcm) */ + dpmgr_path_build_cmdq(primary_get_dpmgr_handle(), handle, + CMDQ_ESD_CHECK_READ, 0); + + /* 5.set CMDQ_SYNC_TOKE_ESD_EOF(trigger thread can work now) */ + cmdqRecSetEventToken(handle, CMDQ_SYNC_TOKEN_ESD_EOF); + + primary_display_manual_unlock(); + + /* 6.flush instruction */ + dprec_logger_start(DPREC_LOGGER_ESD_CMDQ, 0, 0); + ret = cmdqRecFlush(handle); + dprec_logger_done(DPREC_LOGGER_ESD_CMDQ, 0, 0); + + + DISPMSG("[ESD]_esd_check_config_handle_cmd ret=%d\n", ret); + + + if (ret) + ret = 1; + return ret; +} + +/* For Vdo Mode Read LCM Check */ +/* Config cmdq_handle_config_esd */ +int _esd_check_config_handle_vdo(cmdqRecHandle handle) +{ + int ret = 0; /* 0:success , 1:fail */ + + /* 1.reset */ + cmdqRecReset(handle); + + primary_display_manual_lock(); + /* 2.stop dsi vdo mode */ + dpmgr_path_build_cmdq(primary_get_dpmgr_handle(), handle, CMDQ_STOP_VDO_MODE, + 0); + + /* 3.write instruction(read from lcm) */ + dpmgr_path_build_cmdq(primary_get_dpmgr_handle(), handle, CMDQ_ESD_CHECK_READ, + 0); + + /* 4.start dsi vdo mode */ + dpmgr_path_build_cmdq(primary_get_dpmgr_handle(), handle, CMDQ_START_VDO_MODE, + 0); + cmdqRecClearEventToken(handle, CMDQ_EVENT_MUTEX0_STREAM_EOF); + cmdqRecClearEventToken(handle, CMDQ_EVENT_DISP_RDMA0_EOF); + /* 5. trigger path */ + dpmgr_path_trigger(primary_get_dpmgr_handle(), handle, CMDQ_ENABLE); + /* mutex sof wait*/ + ddp_mutex_set_sof_wait(dpmgr_path_get_mutex(primary_get_dpmgr_handle()), + handle, 0); + + primary_display_manual_unlock(); + + /* 6.flush instruction */ + dprec_logger_start(DPREC_LOGGER_ESD_CMDQ, 0, 0); + ret = cmdqRecFlush(handle); + dprec_logger_done(DPREC_LOGGER_ESD_CMDQ, 0, 0); + + DISPMSG("[ESD]_esd_check_config_handle_vdo ret=%d\n", ret); + + + if (ret) + ret = 1; + return ret; +} + +/* For EXT TE EINT Check */ +static irqreturn_t _esd_check_ext_te_irq_handler(int irq, void *data) +{ + MMProfileLogEx(ddp_mmp_get_events()->esd_vdo_eint, MMProfileFlagPulse, 0, 0); + atomic_set(&esd_ext_te_event, 1); + wake_up_interruptible(&esd_ext_te_wq); + return IRQ_HANDLED; +} + +#if defined(CONFIG_MTK_LEGACY) +int primary_display_switch_esd_mode(int mode) +{ + int ret = 0; + int gpio_mode = 0; + struct device_node *node; + int irq; + u32 ints[2] = { 0, 0 }; + +#ifndef GPIO_DSI_TE_PIN + return ret; +#endif + + gpio_mode = mt_get_gpio_mode(GPIO_DSI_TE_PIN); + + /* switch to eint mode */ + if (mode == GPIO_EINT_MODE) { + /* 1. set mode0 */ + /* keep dsi te mode */ + /* mt_set_gpio_mode(GPIO_DSI_TE_PIN, GPIO_DSI_TE_PIN_M_GPIO); */ + + /* 2.register irq handler */ + node = of_find_compatible_node(NULL, NULL, "mediatek, DSI_TE-eint"); + if (node) { + of_property_read_u32_array(node, + "debounce", + ints, + ARRAY_SIZE(ints)); + mt_gpio_set_debounce(ints[0], ints[1]); + irq = irq_of_parse_and_map(node, 0); + if (primary_get_lcm()->params->dsi.ext_te_edge == LCM_POLARITY_FALLING) { + if (request_irq(irq, _esd_check_ext_te_irq_handler, + IRQF_TRIGGER_FALLING, "DSI_TE-eint", NULL)) + /*IRQF_TRIGGER_NONE*/ + DISPERR("[ESD]EINT IRQ LINE NOT AVAILABLE!!\n"); + } else { + if (request_irq(irq, _esd_check_ext_te_irq_handler, + IRQF_TRIGGER_RISING, "DSI_TE-eint", NULL)) + /*IRQF_TRIGGER_NONE*/ + DISPERR("[ESD]EINT IRQ LINE NOT AVAILABLE!!\n"); + } + } else + DISPERR("[ESD][%s] can't find DSI_TE eint compatible node\n", __func__); + + } + + if (mode == GPIO_DSI_MODE) { + + /* 1. unregister irq handler */ + node = of_find_compatible_node(NULL, NULL, "mediatek, DSI_TE-eint"); + if (node) { + irq = irq_of_parse_and_map(node, 0); + free_irq(irq, NULL); + } else + DISPERR("[ESD][%s] can't find DSI_TE eint compatible node\n", __func__); + + /* 2. set dsi te mode */ + /* mt_set_gpio_mode(GPIO_DSI_TE_PIN, GPIO_DSI_TE_PIN_M_DSI_TE); */ + + } + + return ret; +} +#else +int primary_display_switch_esd_mode(int mode) +{ + int ret = 0; + /* int gpio_mode = 0; */ + struct device_node *node; + int irq; + u32 ints[2] = { 0, 0 }; + + if (mode == GPIO_EINT_MODE) { + + /* 1. set mode0 */ + /* disp_dts_gpio_select_state(DTS_GPIO_STATE_TE_MODE_GPIO); */ + + /* 2.register irq handler */ + node = of_find_compatible_node(NULL, NULL, "mediatek, DSI_TE-eint"); + if (node) { + of_property_read_u32_array(node, + "debounce", + ints, + ARRAY_SIZE(ints)); + /* mt_gpio_set_debounce(ints[0], ints[1]); */ + irq = irq_of_parse_and_map(node, 0); + if (primary_get_lcm()->params->dsi.ext_te_edge == LCM_POLARITY_FALLING) { + if (request_irq(irq, _esd_check_ext_te_irq_handler, + IRQF_TRIGGER_FALLING, "DSI_TE-eint", NULL)) + /*IRQF_TRIGGER_NONE*/ + DISPERR("[ESD]EINT IRQ LINE NOT AVAILABLE!!\n"); + } else { + if (request_irq(irq, _esd_check_ext_te_irq_handler, + IRQF_TRIGGER_RISING, "DSI_TE-eint", NULL)) + /*IRQF_TRIGGER_NONE*/ + DISPERR("[ESD]EINT IRQ LINE NOT AVAILABLE!!\n"); + } + + } else + DISPERR("[ESD][%s] can't find DSI_TE eint compatible node\n", __func__); + + + + } else if (mode == GPIO_DSI_MODE) { + /* 1. unregister irq handler */ + node = of_find_compatible_node(NULL, NULL, "mediatek, DSI_TE-eint"); + + if (node) { + irq = irq_of_parse_and_map(node, 0); + free_irq(irq, NULL); + } else + DISPERR("[ESD][%s] can't find DSI_TE eint compatible node\n", __func__); + + /* disp_dts_gpio_select_state(DTS_GPIO_STATE_TE_MODE_TE); */ + + + } + + return ret; +} +#endif + +int do_esd_check_eint(void) +{ + int ret = 0; + + if (wait_event_interruptible_timeout(esd_ext_te_wq, + atomic_read(&esd_ext_te_event), HZ / 2) > 0) + ret = 0; /* esd check pass */ + else + ret = 1; /* esd check fail */ + + atomic_set(&esd_ext_te_event, 0); + + return ret; +} + +int do_esd_check_dsi_te(void) +{ + int ret = 0; + + if (dpmgr_wait_event_timeout(primary_get_dpmgr_handle(), DISP_PATH_EVENT_IF_VSYNC, HZ / 2) > 0) + ret = 0; /* esd check pass */ + else + ret = 1; /* esd check fail */ + + return ret; +} + +int do_esd_check_read(void) +{ + int ret = 0; + cmdqRecHandle handle; + + /* 0.create esd check cmdq */ + cmdqRecCreate(CMDQ_SCENARIO_DISP_ESD_CHECK, &handle); + + primary_display_manual_lock(); + dpmgr_path_build_cmdq(primary_get_dpmgr_handle(), handle, CMDQ_ESD_ALLC_SLOT, 0); + primary_display_manual_unlock(); + + DISPMSG("[ESD]ESD config thread=%p\n", handle); + + /* 1.use cmdq to read from lcm */ + if (primary_display_is_video_mode()) + ret = _esd_check_config_handle_vdo(handle); + else + ret = _esd_check_config_handle_cmd(handle); + + primary_display_manual_lock(); + + if (ret == 1) { /* cmdq fail */ + if (need_wait_esd_eof()) { + /* Need set esd check eof synctoken to let trigger loop go. */ + cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_ESD_EOF); + } + /* do dsi reset */ + dpmgr_path_build_cmdq(primary_get_dpmgr_handle(), handle, + CMDQ_DSI_RESET, 0); + goto destroy_cmdq; + } + + DISPMSG("[ESD]ESD config thread done~\n"); + + /* 2.check data(*cpu check now) */ + ret = dpmgr_path_build_cmdq(primary_get_dpmgr_handle(), handle, + CMDQ_ESD_CHECK_CMP, 0); + if (ret) + ret = 1; /* esd check fail */ + + +destroy_cmdq: + dpmgr_path_build_cmdq(primary_get_dpmgr_handle(), handle, + CMDQ_ESD_FREE_SLOT, 0); + primary_display_manual_unlock(); + + /* 3.destroy esd config thread */ + cmdqRecDestroy(handle); + + return ret; +} +/* ESD CHECK FUNCTION */ +/* return 1: esd check fail */ +/* return 0: esd check pass */ +int primary_display_esd_check(void) +{ + int ret = 0; + unsigned int mode; + + dprec_logger_start(DPREC_LOGGER_ESD_CHECK, 0, 0); + MMProfileLogEx(ddp_mmp_get_events()->esd_check_t, MMProfileFlagStart, 0, 0); + DISPMSG("[ESD]ESD check begin\n"); + + primary_display_manual_lock(); + if (primary_get_state() == DISP_SLEPT) { + MMProfileLogEx(ddp_mmp_get_events()->esd_check_t, MMProfileFlagPulse, 1, 0); + DISPMSG("[ESD]primary display path is slept?? -- skip esd check\n"); + primary_display_manual_unlock(); + goto done; + } + primary_display_manual_unlock(); + + /* Esd Check : EXT TE */ + if (primary_get_lcm()->params->dsi.customization_esd_check_enable == 0) { + /* use te for esd check */ + MMProfileLogEx(ddp_mmp_get_events()->esd_extte, MMProfileFlagStart, 0, 0); + + mode = get_esd_check_mode(); + if (GPIO_EINT_MODE == mode) { + DISPMSG("[ESD]ESD check eint\n"); + MMProfileLogEx(ddp_mmp_get_events()->esd_extte, MMProfileFlagPulse, + primary_display_is_video_mode(), mode); + primary_display_switch_esd_mode(mode); + ret = do_esd_check_eint(); + mode = GPIO_DSI_MODE; /* used for mode switch */ + primary_display_switch_esd_mode(mode); + } else if (GPIO_DSI_MODE == mode) { + MMProfileLogEx(ddp_mmp_get_events()->esd_extte, MMProfileFlagPulse, + primary_display_is_video_mode(), mode); +#if 0 + /* use eint do esd check instead of dsi te irq for lowpower */ + ret = do_esd_check_dsi_te(); +#else + DISPMSG("[ESD]ESD check read\n"); + if (_can_do_read_reg()) + ret = do_esd_check_read(); +#endif + mode = GPIO_EINT_MODE; /* used for mode switch */ + } + if (disp_helper_get_option(DISP_OPT_ESD_CHECK_SWITCH)) + if (primary_display_is_video_mode()) { + /* try eint & read switch on vdo mode */ + if (_can_switch_check_mode()) + set_esd_check_mode(mode); + } + + MMProfileLogEx(ddp_mmp_get_events()->esd_extte, MMProfileFlagEnd, 0, ret); + + goto done; + } + + /* Esd Check : Read from lcm */ + MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagStart, 0, + primary_display_cmdq_enabled()); + + if (primary_display_cmdq_enabled() == 0) { + DISPMSG("[ESD]not support cpu read do esd check\n"); + MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagEnd, 0, ret); + goto done; + } + + MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, 0, + primary_display_is_video_mode()); + + /* only cmd mode read & with disable mmsys clk will kick */ + if (disp_helper_get_option(DISP_OPT_IDLEMGR_ENTER_ULPS) && !primary_display_is_video_mode()) + primary_display_idlemgr_kick((char *)__func__, 1); + ret = do_esd_check_read(); + + + MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagEnd, 0, ret); + +done: + DISPMSG("[ESD]ESD check end, ret = %d\n", ret); + MMProfileLogEx(ddp_mmp_get_events()->esd_check_t, MMProfileFlagEnd, 0, ret); + dprec_logger_done(DPREC_LOGGER_ESD_CHECK, 0, 0); + return ret; + +} + + +static int primary_display_check_recovery_worker_kthread(void *data) +{ + struct sched_param param = {.sched_priority = RTPM_PRIO_FB_THREAD }; + int ret = 0; + int i = 0; + int esd_try_cnt = 5; /* 20; */ + int recovery_done = 0; + + DISPFUNC(); + sched_setscheduler(current, SCHED_RR, ¶m); + + while (1) { + msleep(2000);/*2s*/ + mmsys_enable = 4; + ret = wait_event_interruptible(_check_task_wq, atomic_read(&_check_task_wakeup)); + if (ret < 0) { + DISPMSG("[disp_check]check thread waked up accidently\n"); + continue; + } + + _primary_path_switch_dst_lock(); + + /* 1. esd check & recovery */ + if (esd_check_enable) { + + i = 0;/*repeat*/ + do { + ret = primary_display_esd_check(); + + if (ret == 1) { + DISPERR("[ESD]esd check fail, will do esd recovery. try=%d\n", i); + primary_display_esd_recovery(); + recovery_done = 1; + } else + break; + + } while (++i < esd_try_cnt); + + if (ret == 1) { + DISPERR("[ESD]after esd recovery %d times, still fail, disable esd check\n", + esd_try_cnt); + primary_display_esd_check_enable(0); + } else if (recovery_done == 1) { + DISPMSG("[ESD]esd recovery success\n"); + recovery_done = 0; + } + } + + _primary_path_switch_dst_unlock(); + + /* 2. other check & recovery */ + + if (kthread_should_stop()) + break; + } + return 0; +} + + +/* ESD RECOVERY */ +int primary_display_esd_recovery(void) +{ + DISP_STATUS ret = DISP_STATUS_OK; + LCM_PARAMS *lcm_param = NULL; + + DISPFUNC(); + dprec_logger_start(DPREC_LOGGER_ESD_RECOVERY, 0, 0); + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagStart, 0, 0); + DISPMSG("[ESD]ESD recovery begin\n"); + primary_display_manual_lock(); + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, + primary_display_is_video_mode(), 1); + + + lcm_param = disp_lcm_get_params(primary_get_lcm()); + if (primary_get_state() == DISP_SLEPT) { + DISPMSG("[ESD]esd recovery but primary display path is slept??\n"); + goto done; + } + primary_display_idlemgr_kick((char *)__func__, 0); + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 2); + + /* blocking flush before stop trigger loop */ + _blocking_flush(); + + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 3); + + DISPDBG("[ESD]display cmdq trigger loop stop[begin]\n"); + _cmdq_stop_trigger_loop(); + DISPMSG("[ESD]display cmdq trigger loop stop[end]\n"); + + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 4); + + DISPDBG("[ESD]stop dpmgr path[begin]\n"); + dpmgr_path_stop(primary_get_dpmgr_handle(), CMDQ_DISABLE); + if (primary_display_is_decouple_mode()) + dpmgr_path_stop(primary_get_ovl2mem_handle(), CMDQ_DISABLE); + DISPMSG("[ESD]stop dpmgr path[end]\n"); + + if (dpmgr_path_is_busy(primary_get_dpmgr_handle())) { + DISPMSG("[ESD]primary display path is busy after stop\n"); + dpmgr_wait_event_timeout(primary_get_dpmgr_handle(), DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + DISPMSG("[ESD]wait frame done ret:%d\n", ret); + } + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 5); + + DISPDBG("[ESD]reset display path[begin]\n"); + dpmgr_path_reset(primary_get_dpmgr_handle(), CMDQ_DISABLE); + if (primary_display_is_decouple_mode()) + dpmgr_path_reset(primary_get_ovl2mem_handle(), CMDQ_DISABLE); + DISPMSG("[ESD]reset display path[end]\n"); + + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 6); + { + LCM_PARAMS *lcm_param; + disp_ddp_path_config *data_config; + struct ddp_io_golden_setting_arg gset_arg; + + ddp_disconnect_path(DDP_SCENARIO_PRIMARY_ALL, NULL); + ddp_disconnect_path(DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP, NULL); + DISPMSG("cmd/video mode=%d\n", primary_display_is_video_mode()); + dpmgr_path_set_video_mode(primary_get_dpmgr_handle(), primary_display_is_video_mode()); + + dpmgr_path_connect(primary_get_dpmgr_handle(), CMDQ_DISABLE); + if (primary_display_is_decouple_mode()) { + if (primary_get_ovl2mem_handle()) + dpmgr_path_connect(primary_get_ovl2mem_handle(), CMDQ_DISABLE); + else + DISPERR("in decouple_mode but no ovl2mem_path_handle\n"); + } + + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 2); + lcm_param = disp_lcm_get_params(primary_get_lcm()); + + data_config = dpmgr_path_get_last_config(primary_get_dpmgr_handle()); + memcpy(&(data_config->dispif_config), lcm_param, sizeof(LCM_PARAMS)); + + data_config->dst_w = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + data_config->dst_h = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + if (lcm_param->type == LCM_TYPE_DSI) { + if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB888) + data_config->lcm_bpp = 24; + else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB565) + data_config->lcm_bpp = 16; + else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB666) + data_config->lcm_bpp = 18; + } else if (lcm_param->type == LCM_TYPE_DPI) { + if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB888) + data_config->lcm_bpp = 24; + else if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB565) + data_config->lcm_bpp = 16; + if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB666) + data_config->lcm_bpp = 18; + } + + data_config->fps = primary_display_get_fps_nolock(); + data_config->dst_dirty = 1; + + data_config->ovl_dirty = 1; + + ret = dpmgr_path_config(primary_get_dpmgr_handle(), data_config, NULL); + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 2, 2); + data_config->dst_dirty = 0; + + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(primary_get_dpmgr_handle()); + gset_arg.is_decouple_mode = primary_display_is_decouple_mode(); + dpmgr_path_ioctl(primary_get_dpmgr_handle(), NULL, DDP_OVL_GOLDEN_SETTING, &gset_arg); + + } + DISPDBG("[POWER]lcm suspend[begin]\n"); + disp_lcm_suspend(primary_get_lcm()); + DISPMSG("[POWER]lcm suspend[end]\n"); + DISPDBG("[ESD]lcm force init[begin]\n"); + disp_lcm_init(primary_get_lcm(), 1); + DISPMSG("[ESD]lcm force init[end]\n"); + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 8); + + DISPDBG("[ESD]start dpmgr path[begin]\n"); + dpmgr_path_start(primary_get_dpmgr_handle(), CMDQ_DISABLE); + if (primary_display_is_decouple_mode()) + dpmgr_path_start(primary_get_ovl2mem_handle(), CMDQ_DISABLE); + DISPMSG("[ESD]start dpmgr path[end]\n"); + if (dpmgr_path_is_busy(primary_get_dpmgr_handle())) { + DISPERR("[ESD]Fatal error, we didn't trigger display path but it's already busy\n"); + ret = -1; + /* goto done; */ + } + + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 9); + DISPDBG("[ESD]start cmdq trigger loop[begin]\n"); + _cmdq_start_trigger_loop(); + DISPMSG("[ESD]start cmdq trigger loop[end]\n"); + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 10); + if (primary_display_is_video_mode()) { + /* for video mode, we need to force trigger here */ + /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */ + dpmgr_path_trigger(primary_get_dpmgr_handle(), NULL, CMDQ_DISABLE); + } + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 11); + + /* (in suspend) when we stop trigger loop + * if no other thread is running, cmdq may disable its clock + * all cmdq event will be cleared after suspend */ + cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_EOF); + + /* set dirty to trigger one frame -- cmd mode */ + if (!primary_display_is_video_mode()) { + cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + mdelay(40); + } +done: + primary_display_manual_unlock(); + DISPMSG("[ESD]ESD recovery end\n"); + MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagEnd, 0, 0); + dprec_logger_done(DPREC_LOGGER_ESD_RECOVERY, 0, 0); + return ret; +} + + + + +void primary_display_check_recovery_init(void) +{ + if (!esd_init) { + /* primary display check thread init */ + primary_display_check_task = + kthread_create(primary_display_check_recovery_worker_kthread, NULL, + "disp_check"); + init_waitqueue_head(&_check_task_wq); + + esd_init = 1; + if (disp_helper_get_option(DISP_OPT_ESD_CHECK_RECOVERY)) + wake_up_process(primary_display_check_task); + init_waitqueue_head(&esd_ext_te_wq); + } + if (disp_helper_get_option(DISP_OPT_ESD_CHECK_RECOVERY)) { + if (_need_do_esd_check()) { + /* esd check init */ + set_esd_check_mode(GPIO_EINT_MODE); + primary_display_esd_check_enable(1); + } else { + atomic_set(&_check_task_wakeup, 1); + wake_up_interruptible(&_check_task_wq); + } + } +} + +void primary_display_esd_check_enable(int enable) +{ + if (_need_do_esd_check()) { + + if (enable) { + esd_check_enable = 1; + DISPMSG("[ESD]enable esd check\n"); + atomic_set(&_check_task_wakeup, 1); + wake_up_interruptible(&_check_task_wq); + } else { + esd_check_enable = 0; + DISPMSG("[ESD]disable esd check\n"); + + } + } else + DISPMSG("[ESD]do not support esd check\n"); + +} + +unsigned int need_wait_esd_eof(void) +{ + int ret = 1; + + /* 1.esd check disable */ + /* 2.vdo mode */ + /* 3.cmd mode te */ + if (_need_do_esd_check() == 0) + ret = 0; + + if (primary_display_is_video_mode()) + ret = 0; + + if (primary_get_lcm()->params->dsi.customization_esd_check_enable == 0) + ret = 0; + + return ret; +} + diff --git a/drivers/misc/mediatek/video/mt6755/disp_recovery.h b/drivers/misc/mediatek/video/mt6755/disp_recovery.h new file mode 100644 index 0000000000000000000000000000000000000000..d11e65acd5078482a3216ab068a8e4e8e37a6373 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_recovery.h @@ -0,0 +1,29 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ +#ifndef _DISP_RECOVERY_H_ +#define _DISP_RECOVERY_H_ + +#define GPIO_EINT_MODE 0 +#define GPIO_DSI_MODE 1 + + + +/* defined in mtkfb.c should move to mtkfb.h*/ +extern unsigned int islcmconnected; +extern unsigned int mmsys_enable; + +void primary_display_check_recovery_init(void); +void primary_display_esd_check_enable(int enable); +unsigned int need_wait_esd_eof(void); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/disp_utils.c b/drivers/misc/mediatek/video/mt6755/disp_utils.c new file mode 100644 index 0000000000000000000000000000000000000000..122da47f9fac6d90f38de2074dd5d01a7086bfc6 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_utils.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include "m4u.h" +#include +#include +#include "disp_log.h" +#include "disp_utils.h" + +int disp_sw_mutex_lock(struct mutex *m) +{ + mutex_lock(m); + return 0; +} + +int disp_mutex_trylock(struct mutex *m) +{ + int ret = 0; + + ret = mutex_trylock(m); + return ret; +} + + +int disp_sw_mutex_unlock(struct mutex *m) +{ + mutex_unlock(m); + return 0; +} + +int disp_msleep(unsigned int ms) +{ + msleep(ms); + return 0; +} + +long int disp_get_time_us(void) +{ + struct timeval t; + + do_gettimeofday(&t); + return (t.tv_sec & 0xFFF) * 1000000 + t.tv_usec; +} + +unsigned int disp_allocate_mva(unsigned int pa, unsigned int size, M4U_PORT_ID port) +{ + int ret = 0; + unsigned int mva = 0; + m4u_client_t *client = NULL; + struct sg_table *sg_table = kzalloc(sizeof(struct sg_table), GFP_ATOMIC); + + sg_alloc_table(sg_table, 1, GFP_KERNEL); + + sg_dma_address(sg_table->sgl) = pa; + sg_dma_len(sg_table->sgl) = size; + client = m4u_create_client(); + if (IS_ERR_OR_NULL(client)) + DISPERR("create client fail!\n"); + + mva = pa; + ret = + m4u_alloc_mva(client, port, 0, sg_table, size, M4U_PROT_READ | M4U_PROT_WRITE, + M4U_FLAGS_FIX_MVA, &mva); + /* m4u_alloc_mva(M4U_PORT_DISP_OVL0, pa_start, (pa_end - pa_start + 1), 0, 0, mva); */ + if (ret) + DISPERR("m4u_alloc_mva returns fail: %d\n", ret); + DISPMSG("[DISPHAL] FB MVA is 0x%08X PA is 0x%08X\n", mva, pa); + + return mva; +} diff --git a/drivers/misc/mediatek/video/mt6755/disp_utils.h b/drivers/misc/mediatek/video/mt6755/disp_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..cb79b72cc82db80df7d2431eaf1661ea8d76fded --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/disp_utils.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __H_DISP_UTILS__ +#define __H_DISP_UTILS__ + +#include + +#define __my_wait_event_interruptible_timeout(wq, ret) \ +do { \ + DEFINE_WAIT(__wait); \ + prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + finish_wait(&wq, &__wait); \ +} while (0) + +int disp_sw_mutex_lock(struct mutex *m); +int disp_mutex_trylock(struct mutex *m); +int disp_sw_mutex_unlock(struct mutex *m); +int disp_msleep(unsigned int ms); +long int disp_get_time_us(void); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/mtk_disp_mgr.c b/drivers/misc/mediatek/video/mt6755/mtk_disp_mgr.c new file mode 100644 index 0000000000000000000000000000000000000000..9c8ebee5e6baee30ac846a8f84a488636f1311ae --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtk_disp_mgr.c @@ -0,0 +1,1895 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +/*#include */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m4u.h" + +#include "mtk_sync.h" +#include "disp_debug.h" +#include "disp_log.h" +#include "disp_lcm.h" +#include "disp_utils.h" +#include "mtkfb_console.h" +#include "ddp_hal.h" +#include "ddp_dump.h" +#include "ddp_path.h" +#include "ddp_drv.h" +#include "ddp_info.h" +#include "primary_display.h" +#include "cmdq_def.h" +#include "cmdq_record.h" +#include "cmdq_reg.h" +#include "cmdq_core.h" +#include "ddp_manager.h" +#include "disp_drv_platform.h" +#include "disp_recorder.h" +#include "mtk_disp_mgr.h" +#include "disp_session.h" +#include "mtk_ovl.h" +#include "ddp_mmp.h" +#include "mtkfb_fence.h" +#include "extd_multi_control.h" +#include "m4u.h" + +#include "compat_mtk_disp_mgr.h" + + +#define DDP_OUTPUT_LAYID 4 + +static unsigned int session_config[MAX_SESSION_COUNT]; +static DEFINE_MUTEX(disp_session_lock); + +static dev_t mtk_disp_mgr_devno; +static struct cdev *mtk_disp_mgr_cdev; +static struct class *mtk_disp_mgr_class; + +static int mtk_disp_mgr_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t mtk_disp_mgr_read(struct file *file, char __user *data, size_t len, loff_t *ppos) +{ + return 0; +} + +static int mtk_disp_mgr_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static int mtk_disp_mgr_flush(struct file *a_pstFile, fl_owner_t a_id) +{ + return 0; +} + +static int mtk_disp_mgr_mmap(struct file *file, struct vm_area_struct *vma) +{ + static const unsigned long addr_min = 0x14000000; + static const unsigned long addr_max = 0x14025000; + static const unsigned long size = addr_max - addr_min; + const unsigned long require_size = vma->vm_end - vma->vm_start; + unsigned long pa_start = vma->vm_pgoff << PAGE_SHIFT; + unsigned long pa_end = pa_start + require_size; + + DISPDBG("mmap size %ld, vmpg0ff 0x%lx, pastart 0x%lx, paend 0x%lx\n", + require_size, vma->vm_pgoff, pa_start, pa_end); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (require_size > size || (pa_start < addr_min || pa_end > addr_max)) { + DISPERR("mmap size range over flow!!\n"); + return -EAGAIN; + } + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, (vma->vm_end - vma->vm_start), vma->vm_page_prot)) { + DISPERR("display mmap failed!!\n"); + return -EAGAIN; + } + + return 0; +} + +int _session_inited(disp_session_config config) +{ +#if 0 + int i, idx = -1; + + for (i = 0; i < MAX_SESSION_COUNT; i++) { + if (session_config[i] == 0 && idx == -1) + idx = i; + + + if (session_config[i] == session) { + ret = DCP_STATUS_ALREADY_EXIST; + DISPMSG("session(0x%x) already exists\n", session); + break; + } + } +#endif + return 0; +} + +int disp_create_session(disp_session_config *config) +{ + int ret = 0; + int is_session_inited = 0; + unsigned int session = MAKE_DISP_SESSION(config->type, config->device_id); + int i, idx = -1; + /* 1.To check if this session exists already */ + mutex_lock(&disp_session_lock); + for (i = 0; i < MAX_SESSION_COUNT; i++) { + if (session_config[i] == session) { + is_session_inited = 1; + idx = i; + DISPMSG("create session is exited:0x%x\n", session); + break; + } + } + + if (is_session_inited == 1) { + config->session_id = session; + goto done; + } + + for (i = 0; i < MAX_SESSION_COUNT; i++) { + if (session_config[i] == 0 && idx == -1) { + idx = i; + break; + } + } + /* 1.To check if support this session (mode,type,dev) */ + /* 2. Create this session */ + if (idx != -1) { + config->session_id = session; + session_config[idx] = session; + DISPMSG("New session(0x%x)\n", session); + } else { + DISPERR("Invalid session creation request\n"); + ret = -1; + } +done: + mutex_unlock(&disp_session_lock); + + return ret; +} + +static int release_session_buffer(unsigned int session) +{ + int i = 0; + + mutex_lock(&disp_session_lock); + + for (i = 0; i < MAX_SESSION_COUNT; i++) { + if (session_config[i] == session) + break; + } + + if (i == MAX_SESSION_COUNT) { + DISPERR("%s: no session %u found!\n", __func__, session); + mutex_unlock(&disp_session_lock); + return -1; + } + + mtkfb_release_session_fence(session); + + mutex_unlock(&disp_session_lock); + return 0; +} + + +int disp_destroy_session(disp_session_config *config) +{ + int ret = -1; + unsigned int session = config->session_id; + int i; + + DISPMSG("disp_destroy_session, 0x%x", config->session_id); + + /* 1.To check if this session exists already, and remove it */ + mutex_lock(&disp_session_lock); + for (i = 0; i < MAX_SESSION_COUNT; i++) { + if (session_config[i] == session) { + session_config[i] = 0; + ret = 0; + break; + } + } + + mutex_unlock(&disp_session_lock); + + if (DISP_SESSION_TYPE(config->session_id) != DISP_SESSION_PRIMARY) + external_display_switch_mode(config->mode, session_config, config->session_id); + + if (DISP_SESSION_TYPE(config->session_id) != DISP_SESSION_PRIMARY) + release_session_buffer(config->session_id); + + /* 2. Destroy this session */ + if (ret == 0) + DISPMSG("Destroy session(0x%x)\n", session); + else + DISPERR("session(0x%x) does not exists\n", session); + + + return ret; +} + + +int _ioctl_create_session(unsigned long arg) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + disp_session_config config; + + if (copy_from_user(&config, argp, sizeof(config))) { + DISPERR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + if (disp_create_session(&config) != 0) + ret = -EFAULT; + + + if (copy_to_user(argp, &config, sizeof(config))) { + DISPERR("[FB]: copy_to_user failed! line:%d\n", __LINE__); + ret = -EFAULT; + } + + return ret; +} + +int _ioctl_destroy_session(unsigned long arg) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + disp_session_config config; + + if (copy_from_user(&config, argp, sizeof(config))) { + DISPERR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + if (disp_destroy_session(&config) != 0) + ret = -EFAULT; + + + return ret; +} + + +char *disp_session_mode_spy(unsigned int session_id) +{ + switch (DISP_SESSION_TYPE(session_id)) { + case DISP_SESSION_PRIMARY: + return "P"; + case DISP_SESSION_EXTERNAL: + return "E"; + case DISP_SESSION_MEMORY: + return "M"; + default: + return "Unknown"; + } +} +static int __trigger_display(disp_session_config *config) +{ + int ret = 0; + + unsigned int session_id = 0; + + disp_session_sync_info *session_info; + + session_id = config->session_id; + session_info = disp_get_session_sync_info_for_debug(session_id); + if (session_info) { + unsigned int proc_name = (current->comm[0] << 24) | + (current->comm[1] << 16) | (current->comm[2] << 8) | (current->comm[3] << 0); + dprec_start(&session_info->event_trigger, proc_name, 0); + } + + if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_PRIMARY) { + DISPPR_FENCE("T+/%s%d/%d\n", disp_session_mode_spy(session_id), + DISP_SESSION_DEV(session_id), config->present_fence_idx); + } else { + DISPPR_FENCE("T+/%s%d\n", disp_session_mode_spy(session_id), + DISP_SESSION_DEV(session_id)); + } + + if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_PRIMARY) { + pr_err("%s: legecy API are not supported!\n", __func__); + BUG(); + } else if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_EXTERNAL) { + mutex_lock(&disp_session_lock); + ret = external_display_trigger(config->tigger_mode, session_id); + mutex_unlock(&disp_session_lock); + } else if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_MEMORY) { + ovl2mem_trigger(1, NULL, 0); + } else { + DISPERR("session type is wrong:0x%08x\n", session_id); + ret = -1; + } + + if (session_info) + dprec_done(&session_info->event_trigger, 0, 0); + + + return ret; +} + +int _ioctl_trigger_session(unsigned long arg) +{ + void __user *argp = (void __user *)arg; + disp_session_config config; + + if (copy_from_user(&config, argp, sizeof(config))) { + DISPERR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + return __trigger_display(&config); +} + + +int _ioctl_prepare_present_fence(unsigned long arg) +{ + int ret = 0; + + void __user *argp = (void __user *)arg; + struct fence_data data; + disp_present_fence preset_fence_struct; + static unsigned int fence_idx; + disp_sync_info *layer_info = NULL; + int timeline_id = disp_sync_get_present_timeline_id(); + + if (copy_from_user(&preset_fence_struct, (void __user *)arg, sizeof(disp_present_fence))) { + pr_err("[FB Driver]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + if (DISP_SESSION_TYPE(preset_fence_struct.session_id) != DISP_SESSION_PRIMARY) { + DISPERR("non-primary ask for present fence! session=0x%x\n", + preset_fence_struct.session_id); + data.fence = MTK_FB_INVALID_FENCE_FD; + data.value = 0; + } else { + layer_info = _get_sync_info(preset_fence_struct.session_id, timeline_id); + if (layer_info == NULL) { + DISPERR("layer_info is null\n"); + ret = -EFAULT; + return ret; + } + /* create fence */ + data.fence = MTK_FB_INVALID_FENCE_FD; + data.value = ++fence_idx; + ret = fence_create(layer_info->timeline, &data); + if (ret != 0) { + DISPPR_ERROR("%s%d,layer%d create Fence Object failed!\n", + disp_session_mode_spy(preset_fence_struct.session_id), + DISP_SESSION_DEV(preset_fence_struct.session_id), timeline_id); + ret = -EFAULT; + } + } + + preset_fence_struct.present_fence_fd = data.fence; + preset_fence_struct.present_fence_index = data.value; + if (copy_to_user(argp, &preset_fence_struct, sizeof(preset_fence_struct))) { + pr_err("[FB Driver]: copy_to_user failed! line:%d\n", __LINE__); + ret = -EFAULT; + } + MMProfileLogEx(ddp_mmp_get_events()->present_fence_get, MMProfileFlagPulse, + preset_fence_struct.present_fence_fd, + preset_fence_struct.present_fence_index); + DISPPR_FENCE("P+/%s%d/L%d/id%d/fd%d\n", + disp_session_mode_spy(preset_fence_struct.session_id), + DISP_SESSION_DEV(preset_fence_struct.session_id), timeline_id, + preset_fence_struct.present_fence_index, preset_fence_struct.present_fence_fd); + + return ret; +} + +int _ioctl_prepare_buffer(unsigned long arg, ePREPARE_FENCE_TYPE type) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + disp_buffer_info info; + struct mtkfb_fence_buf_info *buf, *buf2; + + if (copy_from_user(&info, (void __user *)arg, sizeof(info))) { + pr_err("[FB Driver]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + if (type == PREPARE_INPUT_FENCE) + /* do nothing */; + else if (type == PREPARE_PRESENT_FENCE) + info.layer_id = disp_sync_get_present_timeline_id(); + else if (type == PREPARE_OUTPUT_FENCE) + info.layer_id = disp_sync_get_output_timeline_id(); + else + DISPPR_ERROR("type is wrong: %d\n", type); + + + if (info.layer_en) { + buf = disp_sync_prepare_buf(&info); + if (buf != NULL) { + info.fence_fd = buf->fence; + info.index = buf->idx; + } else { + DISPPR_ERROR("P+ FAIL /%s%d/l%d/e%d/ion%d/c%d/id%d/ffd%d\n", + disp_session_mode_spy(info.session_id), + DISP_SESSION_DEV(info.session_id), info.layer_id, + info.layer_en, info.ion_fd, info.cache_sync, info.index, + info.fence_fd); + info.fence_fd = MTK_FB_INVALID_FENCE_FD; /* invalid fd */ + info.index = 0; + } + + if (type == PREPARE_OUTPUT_FENCE) { + if (primary_display_is_decouple_mode() && primary_display_is_mirror_mode()) { + /*create second fence for wdma when decouple mirror mode */ + info.layer_id = disp_sync_get_output_interface_timeline_id(); + buf2 = disp_sync_prepare_buf(&info); + if (buf2 != NULL) { + info.interface_fence_fd = buf2->fence; + info.interface_index = buf2->idx; + } else { + DISPPR_ERROR("P+ FAIL /%s%d/l%d/e%d/ion%d/c%d/id%d/ffd%d\n", + disp_session_mode_spy(info.session_id), + DISP_SESSION_DEV(info.session_id), + info.layer_id, info.layer_en, info.ion_fd, + info.cache_sync, info.index, info.fence_fd); + info.interface_fence_fd = MTK_FB_INVALID_FENCE_FD; /* invalid fd */ + info.interface_index = 0; + } + } else { + info.interface_fence_fd = MTK_FB_INVALID_FENCE_FD; /* invalid fd */ + info.interface_index = 0; + } + } + } else { + DISPPR_ERROR("P+ FAIL /%s%d/l%d/e%d/ion%d/c%d/id%d/ffd%d\n", + disp_session_mode_spy(info.session_id), + DISP_SESSION_DEV(info.session_id), info.layer_id, info.layer_en, + info.ion_fd, info.cache_sync, info.index, info.fence_fd); + info.fence_fd = MTK_FB_INVALID_FENCE_FD; /* invalid fd */ + info.index = 0; + } + if (copy_to_user(argp, &info, sizeof(info))) { + pr_err("[FB Driver]: copy_to_user failed! line:%d\n", __LINE__); + ret = -EFAULT; + } + return ret; +} + +int _ioctl_screen_freeze(unsigned long arg) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + unsigned int enable; + int need_lock = 1; + + if (copy_from_user(&enable, argp, sizeof(unsigned int))) { + DISPMSG("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + ret = display_freeze_mode(enable, need_lock); + + return ret; +} + +const char *_disp_format_spy(DISP_FORMAT format) +{ + switch (format) { + case DISP_FORMAT_RGB565: + return "RGB565"; + case DISP_FORMAT_RGB888: + return "RGB888"; + case DISP_FORMAT_BGR888: + return "BGR888"; + case DISP_FORMAT_ARGB8888: + return "ARGB8888"; + case DISP_FORMAT_ABGR8888: + return "ABGR8888"; + case DISP_FORMAT_RGBA8888: + return "RGBA8888"; + case DISP_FORMAT_BGRA8888: + return "BGRA8888"; + case DISP_FORMAT_YUV422: + return "YUV422"; + case DISP_FORMAT_XRGB8888: + return "XRGB8888"; + case DISP_FORMAT_XBGR8888: + return "XBGR8888"; + case DISP_FORMAT_RGBX8888: + return "RGBX8888"; + case DISP_FORMAT_BGRX8888: + return "BGRX8888"; + case DISP_FORMAT_UYVY: + return "UYVY"; + case DISP_FORMAT_YUV420_P: + return "YUV420_P"; + case DISP_FORMAT_YV12: + return "YV12"; + case DISP_FORMAT_PABGR8888: + return "PABGR"; + case DISP_FORMAT_PARGB8888: + return "PARGB"; + case DISP_FORMAT_PBGRA8888: + return "PBGRA"; + case DISP_FORMAT_PRGBA8888: + return "PRGBA"; + default: + return "unknown"; + } +} + +#if 0 +static int _sync_convert_fb_layer_to_disp_input(unsigned int session_id, disp_input_config *src, + primary_disp_input_config *dst, + unsigned int dst_mva) +{ + unsigned int layerpitch = 0; + + dst->layer = src->layer_id; + + if (!src->layer_enable) { + dst->layer_en = 0; + dst->isDirty = true; + return 0; + } + + dst->fmt = disp_fmt_to_unified_fmt(src->src_fmt); + layerpitch = UFMT_GET_bpp(dst->fmt) / 8; + + dst->buffer_source = src->buffer_source; + + dst->vaddr = (unsigned long)src->src_base_addr; + dst->security = src->security; + if (src->src_phy_addr != NULL) + dst->addr = (unsigned long)src->src_phy_addr; + else + dst->addr = dst_mva; + + dst->isTdshp = src->isTdshp; + dst->buff_idx = src->next_buff_idx; + dst->identity = src->identity; + dst->connected_type = src->connected_type; + + /* set Alpha blending */ + dst->aen = src->alpha_enable; + dst->alpha = src->alpha; + dst->sur_aen = src->sur_aen; + dst->src_alpha = src->src_alpha; + dst->dst_alpha = src->dst_alpha; +#if 1 + if (DISP_FORMAT_ARGB8888 == src->src_fmt || DISP_FORMAT_ABGR8888 == src->src_fmt + || DISP_FORMAT_RGBA8888 == src->src_fmt || DISP_FORMAT_BGRA8888 == src->src_fmt) { + dst->aen = true; + } +#endif + + /* set src width, src height */ + dst->src_x = src->src_offset_x; + dst->src_y = src->src_offset_y; + dst->src_w = src->src_width; + dst->src_h = src->src_height; + dst->dst_x = src->tgt_offset_x; + dst->dst_y = src->tgt_offset_y; + dst->dst_w = src->tgt_width; + dst->dst_h = src->tgt_height; + if (dst->dst_w > dst->src_w) + dst->dst_w = dst->src_w; + if (dst->dst_h > dst->src_h) + dst->dst_h = dst->src_h; + + dst->src_pitch = src->src_pitch * layerpitch; + + /* set color key */ + dst->key = src->src_color_key; + dst->keyEn = src->src_use_color_key; + + /* data transferring is triggerred in MTKFB_TRIG_OVERLAY_OUT */ + dst->layer_en = src->layer_enable; + dst->isDirty = true; + dst->yuv_range = src->yuv_range; + dst->buffer_source = src->buffer_source; + + return 0; +} +#endif +static int set_memory_buffer(disp_session_input_config *input) +{ + int i = 0; + int layer_id = 0; + unsigned int dst_size = 0; + unsigned long dst_mva = 0; + unsigned int session_id = 0; + disp_session_sync_info *session_info; + + + session_id = input->session_id; + session_info = disp_get_session_sync_info_for_debug(session_id); + + for (i = 0; i < input->config_layer_num; i++) { + dst_mva = 0; + layer_id = input->config[i].layer_id; + if (input->config[i].layer_enable) { + if (input->config[i].buffer_source == DISP_BUFFER_ALPHA) { + DISPPR_FENCE("ML %d is dim layer,fence %d\n", + input->config[i].layer_id, + input->config[i].next_buff_idx); + input->config[i].src_offset_x = 0; + input->config[i].src_offset_y = 0; + input->config[i].sur_aen = 0; + input->config[i].src_fmt = DISP_FORMAT_RGB888; + input->config[i].src_pitch = input->config[i].src_width; + input->config[i].src_phy_addr = 0; + input->config[i].next_buff_idx = 0; + /* force dim layer as non-sec */ + input->config[i].security = DISP_NORMAL_BUFFER; + } + if (input->config[i].src_phy_addr) { + dst_mva = (unsigned long)input->config[i].src_phy_addr; + } else { + disp_sync_query_buf_info(session_id, layer_id, input->config[i].next_buff_idx, + (unsigned long *)(&dst_mva), &dst_size); + input->config[i].src_phy_addr = (void *)dst_mva; + } + + if (dst_mva == 0) + input->config[i].layer_enable = 0; + + + DISPPR_FENCE + ("S+/ML%d/e%d/id%d/%dx%d(%d,%d)(%d,%d)/%s/%d/0x%p/mva0x%lx/t%d/sec%d\n", + input->config[i].layer_id, input->config[i].layer_enable, + input->config[i].next_buff_idx, input->config[i].src_width, + input->config[i].src_height, input->config[i].src_offset_x, + input->config[i].src_offset_y, input->config[i].tgt_offset_x, + input->config[i].tgt_offset_y, + _disp_format_spy(input->config[i].src_fmt), input->config[i].src_pitch, + input->config[i].src_phy_addr, dst_mva, get_ovl2mem_ticket(), + input->config[i].security); + } else { + DISPPR_FENCE("S+/ML%d/e%d/id%d\n", input->config[i].layer_id, + input->config[i].layer_enable, input->config[i].next_buff_idx); + } + + /* disp_sync_put_cached_layer_info(session_id, layer_id, &input->config[i], get_ovl2mem_ticket()); */ + mtkfb_update_buf_ticket(session_id, layer_id, input->config[i].next_buff_idx, + get_ovl2mem_ticket()); + + if (input->config[i].layer_enable) { + mtkfb_update_buf_info(input->session_id, input->config[i].layer_id, + input->config[i].next_buff_idx, 0, + input->config[i].frm_sequence); + } + if (session_info) { + dprec_submit(&session_info->event_setinput, input->config[i].next_buff_idx, + (input->config_layer_num << 28) | (input-> + config[i].layer_id << 24) | + (input->config[i].src_fmt << 12) | input->config[i]. + layer_enable); + } + } + + ovl2mem_input_config(input); + + return 0; + +} + +static int set_external_buffer(disp_session_input_config *input) +{ + int i = 0; + int ret = 0; + int layer_id = 0; + unsigned int dst_size = 0; + unsigned long dst_mva = 0; + unsigned int session_id = 0; + unsigned int mva_offset = 0; + disp_session_sync_info *session_info; + + session_id = input->session_id; + session_info = disp_get_session_sync_info_for_debug(session_id); + + for (i = 0; i < input->config_layer_num; ++i) { + dst_mva = 0; + layer_id = input->config[i].layer_id; + if (input->config[i].layer_enable) { + if (input->config[i].buffer_source == DISP_BUFFER_ALPHA) { + DISPPR_FENCE("EL %d is dim layer,fence %d\n", + input->config[i].layer_id, + input->config[i].next_buff_idx); + input->config[i].src_offset_x = 0; + input->config[i].src_offset_y = 0; + input->config[i].sur_aen = 0; + input->config[i].src_fmt = DISP_FORMAT_RGB888; + input->config[i].src_pitch = input->config[i].src_width; + input->config[i].src_phy_addr = (void *)get_dim_layer_mva_addr(); + input->config[i].next_buff_idx = 0; + /* force dim layer as non-sec */ + input->config[i].security = DISP_NORMAL_BUFFER; + } + if (input->config[i].src_phy_addr) { + dst_mva = (unsigned long)input->config[i].src_phy_addr; + } else { + disp_sync_query_buf_info(session_id, layer_id, + (unsigned int)input->config[i].next_buff_idx, + (unsigned long *)&dst_mva, &dst_size); + input->config[i].src_phy_addr = (void *)dst_mva; + } + + if (dst_mva == 0) + input->config[i].layer_enable = 0; + + + DISPPR_FENCE + ("S+/EL%d/e%d/id%d/%dx%d(%d,%d)(%d,%d)/%s/%d/0x%p/mva0x%08lx\n", + input->config[i].layer_id, input->config[i].layer_enable, + input->config[i].next_buff_idx, input->config[i].src_width, + input->config[i].src_height, input->config[i].src_offset_x, + input->config[i].src_offset_y, input->config[i].tgt_offset_x, + input->config[i].tgt_offset_y, + _disp_format_spy(input->config[i].src_fmt), input->config[i].src_pitch, + input->config[i].src_phy_addr, dst_mva); + } else { + DISPPR_FENCE("S+/EL%d/e%d/id%d\n", input->config[i].layer_id, + input->config[i].layer_enable, input->config[i].next_buff_idx); + } + + disp_sync_put_cached_layer_info(session_id, layer_id, &input->config[i], dst_mva); + + if (input->config[i].layer_enable) { + /*which is calculated by pitch and ROI. */ + unsigned int Bpp, x, y, pitch; + + x = input->config[i].src_offset_x; + y = input->config[i].src_offset_y; + pitch = input->config[i].src_pitch; + Bpp = UFMT_GET_bpp(disp_fmt_to_unified_fmt(input->config[i].src_fmt)) / 8; + mva_offset = (x + y * pitch) * Bpp; + mtkfb_update_buf_info(input->session_id, input->config[i].layer_id, + input->config[i].next_buff_idx, mva_offset, + input->config[i].frm_sequence); +#ifdef CONFIG_MTK_HDMI_3D_SUPPORT + mtkfb_update_buf_info_new(input->session_id, mva_offset, + (disp_input_config *) input->config); +#endif + } + + if (session_info) { + dprec_submit(&session_info->event_setinput, input->config[i].next_buff_idx, + (input->config_layer_num << 28) | (input->config[i].layer_id << 24) + | (input->config[i].src_fmt << 12) | input->config[i].layer_enable); + } + } + + ret = external_display_config_input(input, input->config[0].next_buff_idx, session_id); + + if (ret == -2) { + for (i = 0; i < input->config_layer_num; i++) + mtkfb_release_layer_fence(input->session_id, i); + } + + + return 0; +} + +static int input_config_preprocess(struct disp_frame_cfg_t *cfg) +{ + int i = 0; + int layer_id = 0; + unsigned int dst_size = 0; + unsigned long dst_mva = 0; + unsigned int session_id = 0; + unsigned int mva_offset = 0; + disp_session_sync_info *session_info; + + session_id = cfg->session_id; + session_info = disp_get_session_sync_info_for_debug(session_id); + + if (cfg->input_layer_num == 0 + || cfg->input_layer_num > primary_display_get_max_layer()) { + DISPERR("set_primary_buffer, config_layer_num invalid = %d!\n", + cfg->input_layer_num); + return 0; + } + + for (i = 0; i < cfg->input_layer_num; i++) { + dst_mva = 0; + layer_id = cfg->input_cfg[i].layer_id; + if (layer_id >= primary_display_get_max_layer()) { + DISPERR("set_primary_buffer, invalid layer_id = %d!\n", layer_id); + continue; + } + + if (cfg->input_cfg[i].layer_enable) { + unsigned int Bpp, x, y, pitch; + + if (cfg->input_cfg[i].buffer_source == DISP_BUFFER_ALPHA) { + DISPPR_FENCE("PL %d is dim layer,fence %d\n", + cfg->input_cfg[i].layer_id, + cfg->input_cfg[i].next_buff_idx); + + cfg->input_cfg[i].src_offset_x = 0; + cfg->input_cfg[i].src_offset_y = 0; + cfg->input_cfg[i].sur_aen = 0; + cfg->input_cfg[i].src_fmt = DISP_FORMAT_RGB888; + cfg->input_cfg[i].src_pitch = cfg->input_cfg[i].src_width; + cfg->input_cfg[i].src_phy_addr = (void *)get_dim_layer_mva_addr(); + cfg->input_cfg[i].next_buff_idx = 0; + /* force dim layer as non-sec */ + cfg->input_cfg[i].security = DISP_NORMAL_BUFFER; + } + if (cfg->input_cfg[i].src_phy_addr) { + dst_mva = (unsigned long)cfg->input_cfg[i].src_phy_addr; + } else { + disp_sync_query_buf_info(session_id, layer_id, + (unsigned int)cfg->input_cfg[i].next_buff_idx, &dst_mva, &dst_size); + } + + cfg->input_cfg[i].src_phy_addr = (void *)dst_mva; + + if (dst_mva == 0) { + DISPPR_ERROR("disable layer %d because of no valid mva\n", + cfg->input_cfg[i].layer_id); + DISPERR("S+/PL%d/e%d/id%d/%dx%d(%d,%d)(%d,%d)/%s/%d/0x%p/mva0x%08lx/sec%d/s%d\n", + cfg->input_cfg[i].layer_id, cfg->input_cfg[i].layer_enable, + cfg->input_cfg[i].next_buff_idx, cfg->input_cfg[i].src_width, + cfg->input_cfg[i].src_height, cfg->input_cfg[i].src_offset_x, + cfg->input_cfg[i].src_offset_y, cfg->input_cfg[i].tgt_offset_x, + cfg->input_cfg[i].tgt_offset_y, + _disp_format_spy(cfg->input_cfg[i].src_fmt), cfg->input_cfg[i].src_pitch, + cfg->input_cfg[i].src_phy_addr, dst_mva, cfg->input_cfg[i].security, + cfg->input_cfg[i].buffer_source); + /*disp_aee_print("no valid mva\n");*/ + cfg->input_cfg[i].layer_enable = 0; + } + /* OVL addr is not the start address of buffer, which is calculated by pitch and ROI. */ + x = cfg->input_cfg[i].src_offset_x; + y = cfg->input_cfg[i].src_offset_y; + pitch = cfg->input_cfg[i].src_pitch; + Bpp = UFMT_GET_bpp(disp_fmt_to_unified_fmt(cfg->input_cfg[i].src_fmt)) / 8; + + mva_offset = (x + y * pitch) * Bpp; + mtkfb_update_buf_info(cfg->session_id, cfg->input_cfg[i].layer_id, + cfg->input_cfg[i].next_buff_idx, mva_offset, + cfg->input_cfg[i].frm_sequence); + + DISPPR_FENCE("S+/PL%d/e%d/id%d/%dx%d(%d,%d)(%d,%d)/%s/%d/0x%p/mva0x%08lx/sec%d\n", + cfg->input_cfg[i].layer_id, cfg->input_cfg[i].layer_enable, + cfg->input_cfg[i].next_buff_idx, cfg->input_cfg[i].src_width, + cfg->input_cfg[i].src_height, cfg->input_cfg[i].src_offset_x, + cfg->input_cfg[i].src_offset_y, cfg->input_cfg[i].tgt_offset_x, + cfg->input_cfg[i].tgt_offset_y, + _disp_format_spy(cfg->input_cfg[i].src_fmt), cfg->input_cfg[i].src_pitch, + cfg->input_cfg[i].src_phy_addr, dst_mva, cfg->input_cfg[i].security); + } else { + DISPPR_FENCE("S+/PL%d/e%d/id%d\n", cfg->input_cfg[i].layer_id, + cfg->input_cfg[i].layer_enable, cfg->input_cfg[i].next_buff_idx); + } + + disp_sync_put_cached_layer_info(session_id, layer_id, &cfg->input_cfg[i], dst_mva); + + if (session_info) + dprec_submit(&session_info->event_setinput, cfg->input_cfg[i].next_buff_idx, dst_mva); + } + return 0; +} + +static int __set_input(disp_session_input_config *session_input, int overlap_layer_num) +{ + int ret = 0; + unsigned int session_id = 0; + disp_session_sync_info *session_info; + + session_input->setter = SESSION_USER_HWC; + session_id = session_input->session_id; + + session_info = disp_get_session_sync_info_for_debug(session_id); + + if (session_info) + dprec_start(&session_info->event_setinput, overlap_layer_num, session_input->config_layer_num); + + + DISPPR_FENCE("S+/%s%d/count%d\n", disp_session_mode_spy(session_id), + DISP_SESSION_DEV(session_id), session_input->config_layer_num); + + if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_PRIMARY) { + pr_err("%s: legecy API are not supported!\n", __func__); + BUG(); + } else if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_EXTERNAL) { + ret = set_external_buffer(session_input); + } else if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_MEMORY) { + ret = set_memory_buffer(session_input); + } else { + DISPERR("session type is wrong:0x%08x\n", session_id); + return -1; + } + + if (session_info) + dprec_done(&session_info->event_setinput, 0, session_input->config_layer_num); + + + return ret; + +} + +int _ioctl_set_input_buffer(unsigned long arg) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + disp_session_input_config *session_input; + + session_input = kmalloc(sizeof(*session_input), GFP_KERNEL); + + if (!session_input) + return -ENOMEM; + + if (copy_from_user(session_input, argp, sizeof(*session_input))) { + DISPERR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + kfree(session_input); + return -EFAULT; + } + ret = __set_input(session_input, 4); + kfree(session_input); + return ret; +} + +static int _sync_convert_fb_layer_to_disp_output(unsigned int session_id, disp_output_config *src, + disp_mem_output_config *dst, unsigned int dst_mva) +{ + dst->fmt = disp_fmt_to_unified_fmt(src->fmt); + + dst->vaddr = (unsigned long)src->va; + dst->security = src->security; + dst->w = src->width; + dst->h = src->height; + +/* set_overlay will not use fence+ion handle */ +#if defined(MTK_FB_ION_SUPPORT) + if (src->pa != NULL) + dst->addr = (unsigned long)src->pa; + else + dst->addr = dst_mva; + +#else + dst->addr = (unsigned long)src->pa; +#endif + + dst->buff_idx = src->buff_idx; + dst->interface_idx = src->interface_idx; + + dst->x = src->x; + dst->y = src->y; + dst->pitch = src->pitch * UFMT_GET_Bpp(dst->fmt); + return 0; +} + +static int output_config_preprocess(struct disp_frame_cfg_t *cfg) +{ + unsigned int session_id = 0; + unsigned long dst_mva = 0; + disp_session_sync_info *session_info; + + session_id = cfg->session_id; + session_info = disp_get_session_sync_info_for_debug(session_id); + + if (cfg->output_cfg.pa) { + dst_mva = (unsigned long)cfg->output_cfg.pa; + } else { + dst_mva = mtkfb_query_buf_mva(session_id, disp_sync_get_output_timeline_id(), + cfg->output_cfg.buff_idx); + } + cfg->output_cfg.pa = (void *)dst_mva; + + if (!dst_mva) { + DISPERR("%s output mva=0!!, skip it\n", __func__); + cfg->output_en = 0; + goto out; + } + + /* must be mirror mode */ + if (primary_display_is_decouple_mode()) { + disp_sync_put_cached_layer_info_v2(session_id, + disp_sync_get_output_interface_timeline_id(), + cfg->output_cfg.interface_idx, 1, dst_mva); + + disp_sync_put_cached_layer_info_v2(session_id, + disp_sync_get_output_timeline_id(), + cfg->output_cfg.buff_idx, 1, dst_mva); + } + + DISPPR_FENCE("S+O/%s%d/L%d(id%d)/L%d(id%d)/%dx%d(%d,%d)/%s/%d/0x%08x/mva0x%08lx/sec%d\n", + disp_session_mode_spy(session_id), DISP_SESSION_DEV(session_id), + disp_sync_get_output_timeline_id(), cfg->output_cfg.buff_idx, + disp_sync_get_output_interface_timeline_id(), + cfg->output_cfg.interface_idx, cfg->output_cfg.width, + cfg->output_cfg.height, cfg->output_cfg.x, cfg->output_cfg.y, + _disp_format_spy(cfg->output_cfg.fmt), cfg->output_cfg.pitch, + cfg->output_cfg.pitchUV, dst_mva, cfg->output_cfg.security); + + mtkfb_update_buf_info(cfg->session_id, + disp_sync_get_output_interface_timeline_id(), + cfg->output_cfg.buff_idx, 0, + cfg->output_cfg.frm_sequence); + + if (session_info) { + dprec_submit(&session_info->event_setoutput, cfg->output_cfg.buff_idx, + dst_mva); + } + DISPDBG("_ioctl_set_output_buffer done idx 0x%x, mva %lx, fmt %x, w %x, h %x (%x %x), p %x\n", + cfg->output_cfg.buff_idx, dst_mva, cfg->output_cfg.fmt, + cfg->output_cfg.width, cfg->output_cfg.height, + cfg->output_cfg.x, cfg->output_cfg.y, cfg->output_cfg.pitch); +out: + return 0; +} + +static int __set_output(disp_session_output_config *session_output) +{ + unsigned int session_id = 0; + unsigned long dst_mva = 0; + disp_session_sync_info *session_info; + + session_id = session_output->session_id; + session_info = disp_get_session_sync_info_for_debug(session_id); + + if (session_info) + dprec_start(&session_info->event_setoutput, session_output->config.buff_idx, 0); + + if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_PRIMARY) { + pr_err("%s: legecy API are not supported!\n", __func__); + BUG(); + } else if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_MEMORY) { + disp_mem_output_config primary_output; + + memset((void *)&primary_output, 0, sizeof(primary_output)); + if (session_output->config.pa) { + dst_mva = (unsigned long)session_output->config.pa; + } else { + dst_mva = + mtkfb_query_buf_mva(session_id, disp_sync_get_output_timeline_id(), + (unsigned int)session_output->config.buff_idx); + } + + mtkfb_update_buf_ticket(session_id, disp_sync_get_output_timeline_id(), + session_output->config.buff_idx, get_ovl2mem_ticket()); + _sync_convert_fb_layer_to_disp_output(session_output->session_id, + &(session_output->config), &primary_output, + dst_mva); + primary_output.dirty = 1; + + DISPPR_FENCE("S+/%s%d/L%d/id%d/%dx%d(%d,%d)/%s/%d/%d/0x%p/mva0x%lx/t%d/sec%d(%d)\n", + disp_session_mode_spy(session_id), DISP_SESSION_DEV(session_id), + disp_sync_get_output_timeline_id(), + session_output->config.buff_idx, + session_output->config.width, + session_output->config.height, + session_output->config.x, + session_output->config.y, + _disp_format_spy(session_output->config.fmt), + session_output->config.pitch, + session_output->config.pitchUV, + session_output->config.pa, + dst_mva, get_ovl2mem_ticket(), + session_output->config.security, primary_output.security); + + if (dst_mva) + ovl2mem_output_config(&primary_output); + else + DISPERR("error buffer idx 0x%x\n", session_output->config.buff_idx); + + mtkfb_update_buf_info(session_output->session_id, disp_sync_get_output_timeline_id(), + session_output->config.buff_idx, 0, + session_output->config.frm_sequence); + + if (session_info) + dprec_submit(&session_info->event_setoutput, session_output->config.buff_idx, dst_mva); + + DISPDBG("_ioctl_set_output_buffer done idx 0x%x, mva %lx, fmt %x, w %x, h %x, p %x\n", + session_output->config.buff_idx, dst_mva, session_output->config.fmt, + session_output->config.width, session_output->config.height, + session_output->config.pitch); + } + + + if (session_info) + dprec_done(&session_info->event_setoutput, session_output->config.buff_idx, 0); + + return 0; +} + +int _ioctl_set_output_buffer(unsigned long arg) +{ + void __user *argp = (void __user *)arg; + disp_session_output_config session_output; + + if (copy_from_user(&session_output, argp, sizeof(session_output))) { + DISPERR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + return __set_output(&session_output); +} + + +static int __frame_config_set_input(struct disp_frame_cfg_t *frame_cfg) +{ + int ret; + disp_session_input_config *session_input; + + session_input = kmalloc(sizeof(*session_input), GFP_KERNEL); + if (!session_input) + return -ENOMEM; + + session_input->setter = SESSION_USER_HWC; + session_input->session_id = frame_cfg->session_id; + session_input->config_layer_num = frame_cfg->input_layer_num; + memcpy(session_input->config, frame_cfg->input_cfg, sizeof(frame_cfg->input_cfg)); + + ret = __set_input(session_input, frame_cfg->overlap_layer_num); + kfree(session_input); + return ret; +} + +static int __frame_config_set_output(struct disp_frame_cfg_t *frame_cfg) +{ + disp_session_output_config session_output; + + if (!frame_cfg->output_en) + return 0; + + session_output.session_id = frame_cfg->session_id; + memcpy(&session_output.config, &frame_cfg->output_cfg, sizeof(frame_cfg->output_cfg)); + + return __set_output(&session_output); +} + +static int __frame_config_trigger(struct disp_frame_cfg_t *frame_cfg) +{ + disp_session_config config; + + config.session_id = frame_cfg->session_id; + config.need_merge = 0; + config.present_fence_idx = frame_cfg->present_fence_idx; + config.tigger_mode = frame_cfg->tigger_mode; + + return __trigger_display(&config); +} + +int _ioctl_frame_config(unsigned long arg) +{ + struct disp_frame_cfg_t *frame_cfg = kzalloc(sizeof(struct disp_frame_cfg_t), GFP_KERNEL); + + if (frame_cfg == NULL) + return -EFAULT; + + if (copy_from_user(frame_cfg, (void __user *)arg, sizeof(*frame_cfg))) { + pr_err("[FB Driver]: copy_from_user failed! line:%d\n", __LINE__); + kfree(frame_cfg); + return -EFAULT; + } + + frame_cfg->setter = SESSION_USER_HWC; + + if (DISP_SESSION_TYPE(frame_cfg->session_id) == DISP_SESSION_PRIMARY) { + input_config_preprocess(frame_cfg); + if (frame_cfg->output_en) + output_config_preprocess(frame_cfg); + primary_display_frame_cfg(frame_cfg); + } else { + /* set input */ + __frame_config_set_input(frame_cfg); + /* set output */ + __frame_config_set_output(frame_cfg); + /* trigger */ + __frame_config_trigger(frame_cfg); + } + + kfree(frame_cfg); + + return 0; +} + +int disp_mgr_get_session_info(disp_session_info *info) +{ + unsigned int session_id = 0; + + session_id = info->session_id; + + if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_PRIMARY) { + primary_display_get_info(info); + } else if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_EXTERNAL) { + external_display_get_info(info, session_id); + } else if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_MEMORY) { + ovl2mem_get_info(info); + } else { + DISPERR("session type is wrong:0x%08x\n", session_id); + return -1; + } + + return 0; +} + + +int _ioctl_get_info(unsigned long arg) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + disp_session_info info; + + if (copy_from_user(&info, argp, sizeof(info))) { + DISPERR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + ret = disp_mgr_get_session_info(&info); + + if (copy_to_user(argp, &info, sizeof(info))) { + DISPERR("[FB]: copy_to_user failed! line:%d\n", __LINE__); + ret = -EFAULT; + } + + return ret; +} + +int _ioctl_get_is_driver_suspend(unsigned long arg) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + unsigned int is_suspend = 0; + + is_suspend = primary_display_is_sleepd(); + DISPDBG("ioctl_get_is_driver_suspend, is_suspend=%d\n", is_suspend); + if (copy_to_user(argp, &is_suspend, sizeof(int))) { + DISPERR("[FB]: copy_to_user failed! line:%d\n", __LINE__); + ret = -EFAULT; + } + + return ret; +} + +int _ioctl_get_display_caps(unsigned long arg) +{ + int ret = 0; + disp_caps_info caps_info; + void __user *argp = (void __user *)arg; + + if (copy_from_user(&caps_info, argp, sizeof(caps_info))) { + DISPERR("[FB]: copy_to_user failed! line:%d\n", __LINE__); + ret = -EFAULT; + } + memset(&caps_info, 0, sizeof(caps_info)); +#ifdef DISP_HW_MODE_CAP + caps_info.output_mode = DISP_HW_MODE_CAP; +#else + caps_info.output_mode = DISP_OUTPUT_CAP_DIRECT_LINK; +#endif + +#ifdef DISP_HW_PASS_MODE + caps_info.output_pass = DISP_HW_PASS_MODE; +#else + caps_info.output_pass = DISP_OUTPUT_CAP_SINGLE_PASS; +#endif + +#ifdef DISP_HW_MAX_LAYER + caps_info.max_layer_num = DISP_HW_MAX_LAYER; +#else + caps_info.max_layer_num = 4; +#endif + caps_info.is_support_frame_cfg_ioctl = 1; + +#ifdef CONFIG_MTK_LCM_PHYSICAL_ROTATION_HW + caps_info.is_output_rotated = 1; +#endif + + DISPDBG("%s mode:%d, pass:%d, max_layer_num:%d\n", + __func__, caps_info.output_mode, caps_info.output_pass, caps_info.max_layer_num); + + if (copy_to_user(argp, &caps_info, sizeof(caps_info))) { + DISPERR("[FB]: copy_to_user failed! line:%d\n", __LINE__); + ret = -EFAULT; + } + + return ret; +} + +int _ioctl_wait_vsync(unsigned long arg) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + disp_session_vsync_config vsync_config; + disp_session_sync_info *session_info; + + if (copy_from_user(&vsync_config, argp, sizeof(vsync_config))) { + DISPPR_ERROR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + session_info = + disp_get_session_sync_info_for_debug(vsync_config.session_id); + if (session_info) + dprec_start(&session_info->event_waitvsync, 0, 0); + + if (DISP_SESSION_TYPE(vsync_config.session_id) == DISP_SESSION_EXTERNAL) + ret = external_display_wait_for_vsync(&vsync_config, vsync_config.session_id); + else + ret = primary_display_wait_for_vsync(&vsync_config); + + if (session_info) + dprec_done(&session_info->event_waitvsync, 0, 0); + + if (copy_to_user(argp, &vsync_config, sizeof(vsync_config))) { + DISPPR_ERROR("[FB]: copy_to_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + return ret; +} + +int _ioctl_set_vsync(unsigned long arg) +{ + int ret = 0; + void __user *argp = (void __user *)arg; + unsigned int fps = 0; + + if (copy_from_user(&fps, argp, sizeof(unsigned int))) { + DISPERR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + ret = primary_display_force_set_vsync_fps(fps); + return ret; +} + +int set_session_mode(disp_session_config *config_info, int force) +{ + int ret = 0; + + if (DISP_SESSION_TYPE(config_info->session_id) == DISP_SESSION_PRIMARY) + ret = primary_display_switch_mode(config_info->mode, config_info->session_id, 0); + else + DISPERR("[FB]: session(0x%x) swith mode(%d) fail\n", config_info->session_id, config_info->mode); + + external_display_switch_mode(config_info->mode, session_config, config_info->session_id); + + return ret; +} + +int _ioctl_set_session_mode(unsigned long arg) +{ + void __user *argp = (void __user *)arg; + disp_session_config config_info; + + if (copy_from_user(&config_info, argp, sizeof(disp_session_config))) { + DISPERR("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + return set_session_mode(&config_info, 0); +} + +const char *_session_ioctl_spy(unsigned int cmd) +{ + switch (cmd) { + case DISP_IOCTL_CREATE_SESSION: + { + return "DISP_IOCTL_CREATE_SESSION"; + } + case DISP_IOCTL_DESTROY_SESSION: + { + return "DISP_IOCTL_DESTROY_SESSION"; + } + case DISP_IOCTL_TRIGGER_SESSION: + { + return "DISP_IOCTL_TRIGGER_SESSION"; + } + case DISP_IOCTL_SET_INPUT_BUFFER: + { + return "DISP_IOCTL_SET_INPUT_BUFFER"; + } + case DISP_IOCTL_PREPARE_INPUT_BUFFER: + { + return "DISP_IOCTL_PREPARE_INPUT_BUFFER"; + } + case DISP_IOCTL_WAIT_FOR_VSYNC: + { + return "DISP_IOCL_WAIT_FOR_VSYNC"; + } + case DISP_IOCTL_GET_SESSION_INFO: + return "DISP_IOCTL_GET_SESSION_INFO"; + case DISP_IOCTL_AAL_EVENTCTL: + return "DISP_IOCTL_AAL_EVENTCTL"; + case DISP_IOCTL_AAL_GET_HIST: + return "DISP_IOCTL_AAL_GET_HIST"; + case DISP_IOCTL_AAL_INIT_REG: + return "DISP_IOCTL_AAL_INIT_REG"; + case DISP_IOCTL_AAL_SET_PARAM: + return "DISP_IOCTL_AAL_SET_PARAM"; + case DISP_IOCTL_SET_GAMMALUT: + return "DISP_IOCTL_SET_GAMMALUT"; + case DISP_IOCTL_SET_CCORR: + return "DISP_IOCTL_SET_CCORR"; + case DISP_IOCTL_SET_PQPARAM: + return "DISP_IOCTL_SET_PQPARAM"; + case DISP_IOCTL_GET_PQPARAM: + return "DISP_IOCTL_GET_PQPARAM"; + case DISP_IOCTL_GET_PQINDEX: + return "DISP_IOCTL_GET_PQINDEX"; + case DISP_IOCTL_SET_PQINDEX: + return "DISP_IOCTL_SET_PQINDEX"; + case DISP_IOCTL_SET_COLOR_REG: + return "DISP_IOCTL_SET_COLOR_REG"; + case DISP_IOCTL_SET_TDSHPINDEX: + return "DISP_IOCTL_SET_TDSHPINDEX"; + case DISP_IOCTL_GET_TDSHPINDEX: + return "DISP_IOCTL_GET_TDSHPINDEX"; + case DISP_IOCTL_SET_PQ_CAM_PARAM: + return "DISP_IOCTL_SET_PQ_CAM_PARAM"; + case DISP_IOCTL_GET_PQ_CAM_PARAM: + return "DISP_IOCTL_GET_PQ_CAM_PARAM"; + case DISP_IOCTL_SET_PQ_GAL_PARAM: + return "DISP_IOCTL_SET_PQ_GAL_PARAM"; + case DISP_IOCTL_GET_PQ_GAL_PARAM: + return "DISP_IOCTL_GET_PQ_GAL_PARAM"; + case DISP_IOCTL_OD_CTL: + return "DISP_IOCTL_OD_CTL"; + case DISP_IOCTL_GET_DISPLAY_CAPS: + return "DISP_IOCTL_GET_DISPLAY_CAPS"; + default: + { + return "unknown"; + } + } +} + +long mtk_disp_mgr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = -1; + + /* DISPMSG("mtk_disp_mgr_ioctl, cmd=%s, arg=0x%08x\n", _session_ioctl_spy(cmd), arg); */ + + switch (cmd) { + case DISP_IOCTL_CREATE_SESSION: + { + return _ioctl_create_session(arg); + } + case DISP_IOCTL_DESTROY_SESSION: + { + return _ioctl_destroy_session(arg); + } + case DISP_IOCTL_TRIGGER_SESSION: + { + return _ioctl_trigger_session(arg); + } + case DISP_IOCTL_GET_PRESENT_FENCE: + { + /* return _ioctl_prepare_buffer(arg, PREPARE_PRESENT_FENCE); */ + return _ioctl_prepare_present_fence(arg); + } + case DISP_IOCTL_PREPARE_INPUT_BUFFER: + { + return _ioctl_prepare_buffer(arg, PREPARE_INPUT_FENCE); + } + case DISP_IOCTL_SET_INPUT_BUFFER: + { + return _ioctl_set_input_buffer(arg); + } + case DISP_IOCTL_WAIT_FOR_VSYNC: + { + return _ioctl_wait_vsync(arg); + } + case DISP_IOCTL_GET_SESSION_INFO: + { + return _ioctl_get_info(arg); + } + case DISP_IOCTL_GET_DISPLAY_CAPS: + { + return _ioctl_get_display_caps(arg); + } + case DISP_IOCTL_SET_VSYNC_FPS: + { + return _ioctl_set_vsync(arg); + } + case DISP_IOCTL_SET_SESSION_MODE: + { + return _ioctl_set_session_mode(arg); + } + case DISP_IOCTL_PREPARE_OUTPUT_BUFFER: + { + return _ioctl_prepare_buffer(arg, PREPARE_OUTPUT_FENCE); + } + case DISP_IOCTL_SET_OUTPUT_BUFFER: + { + return _ioctl_set_output_buffer(arg); + } + case DISP_IOCTL_FRAME_CONFIG: + return _ioctl_frame_config(arg); + case DISP_IOCTL_GET_LCMINDEX: + { + return primary_display_get_lcm_index(); + } + case DISP_IOCTL_SCREEN_FREEZE: + { + return _ioctl_screen_freeze(arg); + } + case DISP_IOCTL_AAL_EVENTCTL: + case DISP_IOCTL_AAL_GET_HIST: + case DISP_IOCTL_AAL_INIT_REG: + case DISP_IOCTL_AAL_SET_PARAM: + case DISP_IOCTL_SET_GAMMALUT: + case DISP_IOCTL_SET_CCORR: + case DISP_IOCTL_SET_PQPARAM: + case DISP_IOCTL_GET_PQPARAM: + case DISP_IOCTL_SET_PQINDEX: + case DISP_IOCTL_GET_PQINDEX: + case DISP_IOCTL_SET_COLOR_REG: + case DISP_IOCTL_SET_TDSHPINDEX: + case DISP_IOCTL_GET_TDSHPINDEX: + case DISP_IOCTL_SET_PQ_CAM_PARAM: + case DISP_IOCTL_GET_PQ_CAM_PARAM: + case DISP_IOCTL_SET_PQ_GAL_PARAM: + case DISP_IOCTL_GET_PQ_GAL_PARAM: + case DISP_IOCTL_PQ_SET_BYPASS_COLOR: + case DISP_IOCTL_PQ_SET_WINDOW: + case DISP_IOCTL_OD_CTL: + case DISP_IOCTL_WRITE_REG: + case DISP_IOCTL_READ_REG: + case DISP_IOCTL_MUTEX_CONTROL: + case DISP_IOCTL_PQ_GET_TDSHP_FLAG: + case DISP_IOCTL_PQ_SET_TDSHP_FLAG: + case DISP_IOCTL_PQ_GET_DC_PARAM: +/* case DISP_IOCTL_PQ_GET_DS_PARAM: */ + case DISP_IOCTL_PQ_SET_DC_PARAM: + case DISP_IOCTL_PQ_GET_DS_PARAM: + case DISP_IOCTL_PQ_GET_MDP_COLOR_CAP: + case DISP_IOCTL_PQ_GET_MDP_TDSHP_REG: + case DISP_IOCTL_WRITE_SW_REG: + case DISP_IOCTL_READ_SW_REG: + { + ret = primary_display_user_cmd(cmd, arg); + break; + } + default: + { + DISPERR("[session]ioctl not supported, 0x%08x\n", cmd); + } + } + + return ret; +} + +#ifdef CONFIG_COMPAT +const char *_session_compat_ioctl_spy(unsigned int cmd) +{ + switch (cmd) { + case COMPAT_DISP_IOCTL_CREATE_SESSION: + { + return "DISP_IOCTL_CREATE_SESSION"; + } + case COMPAT_DISP_IOCTL_DESTROY_SESSION: + { + return "DISP_IOCTL_DESTROY_SESSION"; + } + case COMPAT_DISP_IOCTL_TRIGGER_SESSION: + { + return "DISP_IOCTL_TRIGGER_SESSION"; + } + case COMPAT_DISP_IOCTL_SET_INPUT_BUFFER: + { + return "DISP_IOCTL_SET_INPUT_BUFFER"; + } + case COMPAT_DISP_IOCTL_PREPARE_INPUT_BUFFER: + { + return "DISP_IOCTL_PREPARE_INPUT_BUFFER"; + } + case COMPAT_DISP_IOCTL_WAIT_FOR_VSYNC: + { + return "DISP_IOCL_WAIT_FOR_VSYNC"; + } + case COMPAT_DISP_IOCTL_GET_SESSION_INFO: + { + return "DISP_IOCTL_GET_SESSION_INFO"; + } + case COMPAT_DISP_IOCTL_PREPARE_OUTPUT_BUFFER: + { + return "DISP_IOCTL_PREPARE_OUTPUT_BUFFER"; + } + case COMPAT_DISP_IOCTL_SET_OUTPUT_BUFFER: + { + return "DISP_IOCTL_SET_OUTPUT_BUFFER"; + } + case COMPAT_DISP_IOCTL_SET_SESSION_MODE: + { + return "DISP_IOCTL_SET_SESSION_MODE"; + } + default: + { + return "unknown"; + } + } +} + +static long mtk_disp_mgr_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret = -ENOIOCTLCMD; + /*DISPMSG("mtk_disp_mgr_compat_ioctl, cmd=%s, arg=0x%08lx\n", _session_compat_ioctl_spy(cmd), arg);*/ + switch (cmd) { + case COMPAT_DISP_IOCTL_CREATE_SESSION: + { + return _compat_ioctl_create_session(file, arg); + } + case COMPAT_DISP_IOCTL_DESTROY_SESSION: + { + return _compat_ioctl_destroy_session(file, arg); + } + case COMPAT_DISP_IOCTL_TRIGGER_SESSION: + { + return _compat_ioctl_trigger_session(file, arg); + } + case COMPAT_DISP_IOCTL_GET_PRESENT_FENCE: + { + return _compat_ioctl_prepare_present_fence(file, arg); + } + case COMPAT_DISP_IOCTL_PREPARE_INPUT_BUFFER: + { + return _compat_ioctl_prepare_buffer(file, arg, PREPARE_INPUT_FENCE); + } + case COMPAT_DISP_IOCTL_SET_INPUT_BUFFER: + { + return _compat_ioctl_set_input_buffer(file, arg); + } + case COMPAT_DISP_IOCTL_FRAME_CONFIG: + { + return _compat_ioctl_frame_config(file, arg); + } + case COMPAT_DISP_IOCTL_WAIT_FOR_VSYNC: + { + return _compat_ioctl_wait_vsync(file, arg); + } + case COMPAT_DISP_IOCTL_GET_SESSION_INFO: + { + return _compat_ioctl_get_info(file, arg); + } + case COMPAT_DISP_IOCTL_GET_DISPLAY_CAPS: + { + return _compat_ioctl_get_display_caps(file, arg); + } + case COMPAT_DISP_IOCTL_SET_VSYNC_FPS: + { + return _compat_ioctl_set_vsync(file, arg); + } + case COMPAT_DISP_IOCTL_SET_SESSION_MODE: + { + return _compat_ioctl_set_session_mode(file, arg); + } + case COMPAT_DISP_IOCTL_PREPARE_OUTPUT_BUFFER: + { + return _compat_ioctl_prepare_buffer(file, arg, PREPARE_OUTPUT_FENCE); + } + case COMPAT_DISP_IOCTL_SET_OUTPUT_BUFFER: + { + return _compat_ioctl_set_output_buffer(file, arg); + } + case COMPAT_DISP_IOCTL_SCREEN_FREEZE: + { + return _compat_ioctl_screen_freeze(file, arg); + } + case DISP_IOCTL_AAL_GET_HIST: + case DISP_IOCTL_AAL_EVENTCTL: + case DISP_IOCTL_AAL_INIT_REG: + case DISP_IOCTL_AAL_SET_PARAM: + { + void __user *data32; + + data32 = compat_ptr(arg); + ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)data32); + return ret; + } + case DISP_IOCTL_SET_GAMMALUT: + case DISP_IOCTL_SET_CCORR: + case DISP_IOCTL_SET_PQPARAM: + case DISP_IOCTL_GET_PQPARAM: + case DISP_IOCTL_SET_PQINDEX: + case DISP_IOCTL_GET_PQINDEX: + case DISP_IOCTL_SET_COLOR_REG: + case DISP_IOCTL_SET_TDSHPINDEX: + case DISP_IOCTL_GET_TDSHPINDEX: + case DISP_IOCTL_SET_PQ_CAM_PARAM: + case DISP_IOCTL_GET_PQ_CAM_PARAM: + case DISP_IOCTL_SET_PQ_GAL_PARAM: + case DISP_IOCTL_GET_PQ_GAL_PARAM: + case DISP_IOCTL_PQ_SET_BYPASS_COLOR: + case DISP_IOCTL_PQ_SET_WINDOW: + case DISP_IOCTL_OD_CTL: + case DISP_IOCTL_WRITE_REG: + case DISP_IOCTL_READ_REG: + case DISP_IOCTL_MUTEX_CONTROL: + case DISP_IOCTL_PQ_GET_TDSHP_FLAG: + case DISP_IOCTL_PQ_SET_TDSHP_FLAG: + case DISP_IOCTL_PQ_GET_DC_PARAM: + case DISP_IOCTL_PQ_GET_DS_PARAM: + case DISP_IOCTL_PQ_SET_DC_PARAM: + case DISP_IOCTL_PQ_GET_MDP_COLOR_CAP: + case DISP_IOCTL_PQ_GET_MDP_TDSHP_REG: + case DISP_IOCTL_WRITE_SW_REG: + case DISP_IOCTL_READ_SW_REG: + { + ret = primary_display_user_cmd(cmd, arg); + break; + } + default: + { + DISPERR("[%s]ioctl not supported, 0x%08x\n", __func__, cmd); + return -ENOIOCTLCMD; + } + } + + return ret; +} +#endif + +static const struct file_operations mtk_disp_mgr_fops = { + .owner = THIS_MODULE, + .mmap = mtk_disp_mgr_mmap, + .unlocked_ioctl = mtk_disp_mgr_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = mtk_disp_mgr_compat_ioctl, +#endif + + .open = mtk_disp_mgr_open, + .release = mtk_disp_mgr_release, + .flush = mtk_disp_mgr_flush, + .read = mtk_disp_mgr_read, +}; + +static int mtk_disp_mgr_probe(struct platform_device *pdev) +{ + int err = 0; + struct class_device; + struct class_device *class_dev = NULL; + + pr_debug("mtk_disp_mgr_probe called!\n"); + + if (alloc_chrdev_region(&mtk_disp_mgr_devno, 0, 1, DISP_SESSION_DEVICE)) + return -EFAULT; + + + mtk_disp_mgr_cdev = cdev_alloc(); + mtk_disp_mgr_cdev->owner = THIS_MODULE; + mtk_disp_mgr_cdev->ops = &mtk_disp_mgr_fops; + + err = cdev_add(mtk_disp_mgr_cdev, mtk_disp_mgr_devno, 1); + if (err) + DISPERR("[FB]: add cdev fail!\n"); + + mtk_disp_mgr_class = class_create(THIS_MODULE, DISP_SESSION_DEVICE); + class_dev = + (struct class_device *)device_create(mtk_disp_mgr_class, NULL, mtk_disp_mgr_devno, NULL, + DISP_SESSION_DEVICE); + disp_sync_init(); + external_display_control_init(); + + return 0; +} + +static int mtk_disp_mgr_remove(struct platform_device *pdev) +{ + return 0; +} + +static void mtk_disp_mgr_shutdown(struct platform_device *pdev) +{ +} + +static int mtk_disp_mgr_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + return 0; +} + +static int mtk_disp_mgr_resume(struct platform_device *pdev) +{ + return 0; +} + + +static struct platform_driver mtk_disp_mgr_driver = { + .probe = mtk_disp_mgr_probe, + .remove = mtk_disp_mgr_remove, + .shutdown = mtk_disp_mgr_shutdown, + .suspend = mtk_disp_mgr_suspend, + .resume = mtk_disp_mgr_resume, + .driver = { + .name = DISP_SESSION_DEVICE, + }, +}; + +static void mtk_disp_mgr_device_release(struct device *dev) +{ + +} + +static u64 mtk_disp_mgr_dmamask = ~(u32) 0; + +static struct platform_device mtk_disp_mgr_device = { + .name = DISP_SESSION_DEVICE, + .id = 0, + .dev = { + .release = mtk_disp_mgr_device_release, + .dma_mask = &mtk_disp_mgr_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = 0, +}; + +static int __init mtk_disp_mgr_init(void) +{ + pr_debug("mtk_disp_mgr_init\n"); + if (platform_device_register(&mtk_disp_mgr_device)) + return -ENODEV; + + + if (platform_driver_register(&mtk_disp_mgr_driver)) { + platform_device_unregister(&mtk_disp_mgr_device); + return -ENODEV; + } + + + return 0; +} + +static void __exit mtk_disp_mgr_exit(void) +{ + cdev_del(mtk_disp_mgr_cdev); + unregister_chrdev_region(mtk_disp_mgr_devno, 1); + + platform_driver_unregister(&mtk_disp_mgr_driver); + platform_device_unregister(&mtk_disp_mgr_device); + + device_destroy(mtk_disp_mgr_class, mtk_disp_mgr_devno); + class_destroy(mtk_disp_mgr_class); +} +module_init(mtk_disp_mgr_init); +module_exit(mtk_disp_mgr_exit); + +MODULE_DESCRIPTION("MediaTek Display Manager"); diff --git a/drivers/misc/mediatek/video/mt6755/mtk_disp_mgr.h b/drivers/misc/mediatek/video/mt6755/mtk_disp_mgr.h new file mode 100644 index 0000000000000000000000000000000000000000..df107533059c61059c0dccd586804b94580f86c3 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtk_disp_mgr.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __H_MTK_DISP_MGR__ +#define __H_MTK_DISP_MGR__ +#include "disp_session.h" + +typedef enum { + PREPARE_INPUT_FENCE, + PREPARE_OUTPUT_FENCE, + PREPARE_PRESENT_FENCE +} ePREPARE_FENCE_TYPE; + +long mtk_disp_mgr_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +int disp_create_session(disp_session_config *config); +int disp_destroy_session(disp_session_config *config); +int set_session_mode(disp_session_config *config_info, int force); +char *disp_session_mode_spy(unsigned int session_id); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/mtk_mira.c b/drivers/misc/mediatek/video/mt6755/mtk_mira.c new file mode 100644 index 0000000000000000000000000000000000000000..bfb14abaa51c9132581c5d812169dacc2e5321ad --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtk_mira.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define LOG_TAG "mtk_mira" + +#include "disp_log.h" + +#include +#include +#include +#include + +#include "mtk_mira.h" +#include "mtk_disp_mgr.h" + + +#define DISP_DEVNAME "mtk_mira" + +static struct proc_dir_entry *proc_entry; + +static long disp_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return mtk_disp_mgr_ioctl(file, cmd, arg); +} + +#ifdef CONFIG_COMPAT +static long disp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + + return mtk_disp_mgr_ioctl(file, cmd, arg); +} +#endif + +static int disp_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t disp_read(struct file *file, char __user *data, size_t len, loff_t *ppos) +{ + return 0; +} + +static int disp_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static int disp_flush(struct file *file, fl_owner_t a_id) +{ + return 0; +} + +/* remap register to user space */ +static int disp_mmap(struct file *file, struct vm_area_struct *a_pstVMArea) +{ + return 0; +} + +/* Kernel interface */ +static const struct file_operations disp_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = disp_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = disp_compat_ioctl, +#endif + .open = disp_open, + .release = disp_release, + .flush = disp_flush, + .read = disp_read, + .mmap = disp_mmap +}; + +static int __init disp_init(void) +{ + int ret = 0; + + DISPMSG("Register the disp driver\n"); + proc_entry = proc_create(DISP_DEVNAME, 0644, NULL, &disp_fops); + if (proc_entry == NULL) + ret = -ENOMEM; + return ret; +} + +static void __exit disp_exit(void) +{ + remove_proc_entry(DISP_DEVNAME, proc_entry); + DISPMSG("Done\n"); +} +module_init(disp_init); +module_exit(disp_exit); +MODULE_AUTHOR("Tzu-Meng, Chung "); +MODULE_DESCRIPTION("Display subsystem Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/video/mt6755/mtk_mira.h b/drivers/misc/mediatek/video/mt6755/mtk_mira.h new file mode 100644 index 0000000000000000000000000000000000000000..d64c721fd050b713863710386f5b3403b700d841 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtk_mira.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#ifndef __MTK_MIRA_H__ +#define __MTK_MIRA_H__ + +#include "ddp_drv.h" +#endif diff --git a/drivers/misc/mediatek/video/mt6755/mtk_ovl.c b/drivers/misc/mediatek/video/mt6755/mtk_ovl.c new file mode 100644 index 0000000000000000000000000000000000000000..4c91bcff604e2a545820b26fac1053d096c7a151 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtk_ovl.c @@ -0,0 +1,565 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include "disp_debug.h" +#include "mtkfb_debug.h" +#include "disp_log.h" +#include "disp_utils.h" + +#include "ddp_dump.h" +#include "ddp_path.h" +#include "ddp_drv.h" + +#include "disp_session.h" +#include "primary_display.h" + +#include "m4u.h" +#include "cmdq_def.h" +#include "cmdq_record.h" +#include "cmdq_reg.h" +#include "cmdq_core.h" + +#include "ddp_manager.h" +#include "disp_drv_platform.h" +#include "disp_recorder.h" +#include "ddp_mmp.h" +#include "mtk_ovl.h" + +#include "mtkfb_fence.h" + +#include + +static int ovl2mem_layer_num; +int ovl2mem_use_m4u = 1; +int ovl2mem_use_cmdq = CMDQ_ENABLE; + +typedef struct { + int state; + unsigned int session; + unsigned int lcm_fps; + int max_layer; + int need_trigger_path; + struct mutex lock; + cmdqRecHandle cmdq_handle_config; + cmdqRecHandle cmdq_handle_trigger; + disp_path_handle dpmgr_handle; + const char *mutex_locker; +} ovl2mem_path_context; + +atomic_t g_trigger_ticket = ATOMIC_INIT(1); +atomic_t g_release_ticket = ATOMIC_INIT(1); + + +#define pgc _get_context() + +static ovl2mem_path_context *_get_context(void) +{ + static int is_context_inited; + static ovl2mem_path_context g_context; + + if (!is_context_inited) { + memset((void *)&g_context, 0, sizeof(ovl2mem_path_context)); + is_context_inited = 1; + } + + return &g_context; +} + +CMDQ_SWITCH ovl2mem_cmdq_enabled(void) +{ + return ovl2mem_use_cmdq; +} +/* +static unsigned int cmdqDdpClockOn(uint64_t engineFlag) +{ + return 0; +} + +static unsigned int cmdqDdpResetEng(uint64_t engineFlag) +{ + return 0; +} + +static unsigned int cmdqDdpClockOff(uint64_t engineFlag) +{ + return 0; +} + +static unsigned int cmdqDdpDumpInfo(uint64_t engineFlag, char *pOutBuf, unsigned int bufSize) +{ + DISPMSG("ovl2mem cmdq timeout:%llu\n", engineFlag); + if (pgc->dpmgr_handle) + dpmgr_check_status(pgc->dpmgr_handle); + + return 0; +} +*/ +static void _ovl2mem_path_lock(const char *caller) +{ + dprec_logger_start(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0); + disp_sw_mutex_lock(&(pgc->lock)); + pgc->mutex_locker = caller; +} + +static void _ovl2mem_path_unlock(const char *caller) +{ + pgc->mutex_locker = NULL; + disp_sw_mutex_unlock(&(pgc->lock)); + dprec_logger_done(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0); +} + +void ovl2mem_setlayernum(int layer_num) +{ + ovl2mem_layer_num = layer_num; +} + +int ovl2mem_get_info(void *info) +{ + /* /DISPFUNC(); */ + disp_session_info *dispif_info = (disp_session_info *) info; + + memset((void *)dispif_info, 0, sizeof(disp_session_info)); + + /* FIXME, for decouple mode, should dynamic return 4 or 8, please refer to primary_display_get_info() */ + dispif_info->maxLayerNum = ovl2mem_layer_num; + dispif_info->displayType = DISP_IF_TYPE_DPI; + dispif_info->displayMode = DISP_IF_MODE_VIDEO; + dispif_info->isHwVsyncAvailable = 1; + dispif_info->displayFormat = DISP_IF_FORMAT_RGB888; + + dispif_info->displayWidth = primary_display_get_width(); + dispif_info->displayHeight = primary_display_get_height(); + + dispif_info->vsyncFPS = pgc->lcm_fps; + + if (dispif_info->displayWidth * dispif_info->displayHeight <= 240 * 432) + dispif_info->physicalHeight = dispif_info->physicalWidth = 0; + else if (dispif_info->displayWidth * dispif_info->displayHeight <= 320 * 480) + dispif_info->physicalHeight = dispif_info->physicalWidth = 0; + else if (dispif_info->displayWidth * dispif_info->displayHeight <= 480 * 854) + dispif_info->physicalHeight = dispif_info->physicalWidth = 0; + else + dispif_info->physicalHeight = dispif_info->physicalWidth = 0; + + dispif_info->isConnected = 1; + + return 0; +} + + +static int _convert_disp_input_to_ovl(OVL_CONFIG_STRUCT *dst, disp_input_config *src) +{ + int ret = 0; + int force_disable_alpha = 0; + enum UNIFIED_COLOR_FMT tmp_fmt; + unsigned int Bpp = 0; + + if (!src || !dst) { + DISPERR("%s src(0x%p) or dst(0x%p) is null\n", __func__, src, dst); + return -1; + } + + dst->layer = src->layer_id; + dst->isDirty = 1; + dst->buff_idx = src->next_buff_idx; + dst->layer_en = src->layer_enable; + + /* if layer is disable, we just needs config above params. */ + if (!src->layer_enable) + return 0; + + tmp_fmt = disp_fmt_to_unified_fmt(src->src_fmt); + /* display don't support X channel, like XRGB8888 + * we need to enable const_bld*/ + ufmt_disable_X_channel(tmp_fmt, &dst->fmt, &dst->const_bld); +#if 0 + if (tmp_fmt != dst->fmt) + force_disable_alpha = 1; +#endif + Bpp = UFMT_GET_Bpp(dst->fmt); + + dst->addr = (unsigned long)src->src_phy_addr; + dst->vaddr = (unsigned long)src->src_base_addr; + dst->src_x = src->src_offset_x; + dst->src_y = src->src_offset_y; + dst->src_w = src->src_width; + dst->src_h = src->src_height; + dst->src_pitch = src->src_pitch * Bpp; + dst->dst_x = src->tgt_offset_x; + dst->dst_y = src->tgt_offset_y; + + /* dst W/H should <= src W/H */ + dst->dst_w = min(src->src_width, src->tgt_width); + dst->dst_h = min(src->src_height, src->tgt_height); + + dst->keyEn = src->src_use_color_key; + dst->key = src->src_color_key; + + dst->aen = force_disable_alpha ? 0 : src->alpha_enable; + dst->sur_aen = force_disable_alpha ? 0 : src->sur_aen; + + dst->alpha = src->alpha; + dst->src_alpha = src->src_alpha; + dst->dst_alpha = src->dst_alpha; + + dst->identity = src->identity; + dst->connected_type = src->connected_type; + dst->security = src->security; + dst->yuv_range = src->yuv_range; + + if (src->buffer_source == DISP_BUFFER_ALPHA) { + dst->source = OVL_LAYER_SOURCE_RESERVED; /* dim layer, constant alpha */ + } else if (src->buffer_source == DISP_BUFFER_ION || src->buffer_source == DISP_BUFFER_MVA) { + dst->source = OVL_LAYER_SOURCE_MEM; /* from memory */ + } else { + DISPERR("unknown source = %d", src->buffer_source); + dst->source = OVL_LAYER_SOURCE_MEM; + } + + return ret; +} + +static int ovl2mem_callback(unsigned int userdata) +{ + int fence_idx = 0; + int layid = 0; + + DISPMSG("ovl2mem_callback(%x), current tick=%d, release tick: %d\n", pgc->session, + get_ovl2mem_ticket(), userdata); + for (layid = 0; layid < (MEMORY_SESSION_INPUT_LAYER_COUNT); layid++) { + fence_idx = mtkfb_query_idx_by_ticket(pgc->session, layid, userdata); + if (fence_idx >= 0) + mtkfb_release_fence(pgc->session, layid, fence_idx); + } + + layid = disp_sync_get_output_timeline_id(); + fence_idx = mtkfb_query_idx_by_ticket(pgc->session, layid, userdata); + if (fence_idx >= 0) { + disp_ddp_path_config *data_config = + dpmgr_path_get_last_config(pgc->dpmgr_handle); + if (data_config) { + WDMA_CONFIG_STRUCT wdma_layer; + + wdma_layer.dstAddress = + mtkfb_query_buf_mva(pgc->session, layid, fence_idx); + wdma_layer.outputFormat = data_config->wdma_config.outputFormat; + wdma_layer.srcWidth = data_config->wdma_config.srcWidth; + wdma_layer.srcHeight = data_config->wdma_config.srcHeight; + wdma_layer.dstPitch = data_config->wdma_config.dstPitch; + + dprec_mmp_dump_wdma_layer(&wdma_layer, 1); + } + mtkfb_release_fence(pgc->session, layid, fence_idx); + } + + atomic_set(&g_release_ticket, userdata); + + return 0; +} + +int get_ovl2mem_ticket(void) +{ + return atomic_read(&g_trigger_ticket); + +} + +int ovl2mem_init(unsigned int session) +{ + int ret = -1; + M4U_PORT_STRUCT sPort; + + DISPMSG("ovl2mem_init\n"); + dpmgr_init(); + mutex_init(&(pgc->lock)); + + _ovl2mem_path_lock(__func__); + + if (pgc->state > 0) + goto Exit; + + ret = cmdqRecCreate(CMDQ_SCENARIO_SUB_DISP, &(pgc->cmdq_handle_config)); + if (ret) { + DISPERR("cmdqRecCreate FAIL, ret=%d\n", ret); + goto Exit; + } else { + DISPDBG("cmdqRecCreate SUCCESS, cmdq_handle=%p\n", pgc->cmdq_handle_config); + } + + pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_SUB_OVL_MEMOUT, pgc->cmdq_handle_config); + + if (pgc->dpmgr_handle) { + DISPDBG("dpmgr create path SUCCESS(%p)\n", pgc->dpmgr_handle); + } else { + DISPERR("dpmgr create path FAIL\n"); + goto Exit; + } + + sPort.ePortID = M4U_PORT_DISP_OVL1; + sPort.Virtuality = ovl2mem_use_m4u; + sPort.Security = 0; + sPort.Distance = 1; + sPort.Direction = 0; + ret = m4u_config_port(&sPort); + sPort.ePortID = M4U_PORT_DISP_WDMA1; + sPort.Virtuality = ovl2mem_use_m4u; + sPort.Security = 0; + sPort.Distance = 1; + sPort.Direction = 0; + ret = m4u_config_port(&sPort); + if (ret == 0) { + DISPDBG("config M4U Port %s to %s SUCCESS\n", + ddp_get_module_name(DISP_MODULE_OVL1), + ovl2mem_use_m4u ? "virtual" : "physical"); + } else { + DISPERR("config M4U Port %s to %s FAIL(ret=%d)\n", + ddp_get_module_name(DISP_MODULE_OVL1), + ovl2mem_use_m4u ? "virtual" : "physical", ret); + goto Exit; + } + + dpmgr_path_set_video_mode(pgc->dpmgr_handle, ovl2mem_cmdq_enabled()); + + dpmgr_path_init(pgc->dpmgr_handle, CMDQ_DISABLE); + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + /* dpmgr_path_set_dst_module(pgc->dpmgr_handle,DISP_MODULE_ENUM dst_module) */ + + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_COMPLETE); + + pgc->max_layer = 4; + pgc->state = 1; + pgc->session = session; + atomic_set(&g_trigger_ticket, 1); + atomic_set(&g_release_ticket, 1); + +Exit: + _ovl2mem_path_unlock(__func__); + + DISPMSG("ovl2mem_init done\n"); + + return ret; +} + + +int ovl2mem_input_config(disp_session_input_config *input) +{ + int ret = -1; + int i = 0; + int config_layer_id = 0; + disp_ddp_path_config *data_config; + + DISPFUNC(); + _ovl2mem_path_lock(__func__); + + if (pgc->state == 0) { + DISPERR("ovl2mem is already slept\n"); + _ovl2mem_path_unlock(__func__); + return 0; + } + + /* all dirty should be cleared in dpmgr_path_get_last_config() */ + data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle); + data_config->dst_dirty = 0; + data_config->ovl_dirty = 0; + data_config->rdma_dirty = 0; + + /* hope we can use only 1 input struct for input config, just set layer number */ + for (i = 0; i < input->config_layer_num; i++) { + dprec_logger_start(DPREC_LOGGER_PRIMARY_CONFIG, + input->config[i].layer_id | (input->config[i].layer_enable << 16), + 0/*input->config[i].src_phy_addr*/); + + config_layer_id = input->config[i].layer_id; + _convert_disp_input_to_ovl(&(data_config->ovl_config[config_layer_id]), &(input->config[i])); + dprec_mmp_dump_ovl_layer(&(data_config->ovl_config[config_layer_id]), config_layer_id, 3); + + data_config->ovl_dirty = 1; + dprec_logger_done(DPREC_LOGGER_PRIMARY_CONFIG, input->config[i].src_offset_x, + input->config[i].src_offset_y); + } + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_COMPLETE, HZ / 5); + + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, pgc->cmdq_handle_config); + + _ovl2mem_path_unlock(__func__); + + return ret; +} + +int ovl2mem_output_config(disp_mem_output_config *out) +{ + int ret = -1; + disp_ddp_path_config *data_config; + + /* /DISPFUNC(); */ + + _ovl2mem_path_lock(__func__); + + /* all dirty should be cleared in dpmgr_path_get_last_config() */ + data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle); + data_config->dst_dirty = 1; + data_config->dst_h = out->h; + data_config->dst_w = out->w; + data_config->ovl_dirty = 0; + data_config->rdma_dirty = 0; + data_config->wdma_dirty = 1; + data_config->wdma_config.dstAddress = out->addr; + data_config->wdma_config.srcHeight = out->h; + data_config->wdma_config.srcWidth = out->w; + data_config->wdma_config.clipX = out->x; + data_config->wdma_config.clipY = out->y; + data_config->wdma_config.clipHeight = out->h; + data_config->wdma_config.clipWidth = out->w; + data_config->wdma_config.outputFormat = out->fmt; + data_config->wdma_config.dstPitch = out->pitch; + data_config->wdma_config.useSpecifiedAlpha = 1; + data_config->wdma_config.alpha = 0xFF; + data_config->wdma_config.security = out->security; + + if (pgc->state == 0) { + DISPERR("ovl2mem is already slept\n"); + _ovl2mem_path_unlock(__func__); + return 0; + } + + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 5); + + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, pgc->cmdq_handle_config); + + pgc->need_trigger_path = 1; + + _ovl2mem_path_unlock(__func__); + + return ret; +} + + +int ovl2mem_trigger(int blocking, void *callback, unsigned int userdata) +{ + int ret = -1; + int fence_idx = 0; + int layid = 0; + + DISPFUNC(); + if (pgc->need_trigger_path == 0) { + DISPMSG("ovl2mem_trigger do not trigger\n"); + if ((atomic_read(&g_trigger_ticket) - atomic_read(&g_release_ticket)) == 1) { + DISPERR("ovl2mem_trigger(%x), configue input,but does not config output!!\n", pgc->session); + for (layid = 0; layid < (MEMORY_SESSION_INPUT_LAYER_COUNT + 1); layid++) { + fence_idx = mtkfb_query_idx_by_ticket(pgc->session, layid, + atomic_read(&g_trigger_ticket)); + if (fence_idx >= 0) + mtkfb_release_fence(pgc->session, layid, fence_idx); + } + } + return ret; + } + _ovl2mem_path_lock(__func__); + cmdqRecClearEventToken(pgc->cmdq_handle_config, CMDQ_SYNC_DISP_EXT_STREAM_EOF); + dpmgr_path_start(pgc->dpmgr_handle, ovl2mem_cmdq_enabled()); + dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_config, ovl2mem_cmdq_enabled()); + + cmdqRecWait(pgc->cmdq_handle_config, CMDQ_EVENT_DISP_WDMA1_EOF); + cmdqRecSetEventToken(pgc->cmdq_handle_config, CMDQ_SYNC_DISP_EXT_STREAM_EOF); + dpmgr_path_stop(pgc->dpmgr_handle, ovl2mem_cmdq_enabled()); + + /* /cmdqRecDumpCommand(pgc->cmdq_handle_config); */ + + cmdqRecFlushAsyncCallback(pgc->cmdq_handle_config, (CmdqAsyncFlushCB)ovl2mem_callback, + atomic_read(&g_trigger_ticket)); + + cmdqRecReset(pgc->cmdq_handle_config); + + pgc->need_trigger_path = 0; + atomic_add(1, &g_trigger_ticket); + + _ovl2mem_path_unlock(__func__); + + return ret; +} + +void ovl2mem_wait_done(void) +{ + int loop_cnt = 0; + + if ((atomic_read(&g_trigger_ticket) - atomic_read(&g_release_ticket)) <= 1) + return; + + DISPFUNC(); + + while ((atomic_read(&g_trigger_ticket) - atomic_read(&g_release_ticket)) > 1) { + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_COMPLETE, + HZ / 30); + + if (loop_cnt > 5) + break; + + + loop_cnt++; + } + + DISPMSG("ovl2mem_wait_done loop %d, trigger tick:%d, release tick:%d\n", loop_cnt, + atomic_read(&g_trigger_ticket), atomic_read(&g_release_ticket)); + +} + +int ovl2mem_deinit(void) +{ + int ret = -1; + int loop_cnt = 0; + + DISPFUNC(); + _ovl2mem_path_lock(__func__); + + if (pgc->state == 0) + goto Exit; + + /* ovl2mem_wait_done(); */ + ovl2mem_layer_num = 0; + while (((atomic_read(&g_trigger_ticket) - atomic_read(&g_release_ticket)) != 1) && (loop_cnt < 10)) { + msleep(20); + /* wait the last configuration done */ + loop_cnt++; + } + + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + dpmgr_path_deinit(pgc->dpmgr_handle, CMDQ_DISABLE); + dpmgr_destroy_path(pgc->dpmgr_handle, NULL); + + cmdqRecDestroy(pgc->cmdq_handle_config); + + pgc->dpmgr_handle = NULL; + pgc->cmdq_handle_config = NULL; + pgc->state = 0; + pgc->need_trigger_path = 0; + atomic_set(&g_trigger_ticket, 1); + atomic_set(&g_release_ticket, 1); + +Exit: + _ovl2mem_path_unlock(__func__); + + DISPMSG("ovl2mem_deinit done\n"); + return ret; +} diff --git a/drivers/misc/mediatek/video/mt6755/mtk_ovl.h b/drivers/misc/mediatek/video/mt6755/mtk_ovl.h new file mode 100644 index 0000000000000000000000000000000000000000..42bc3f07ef8f70a7e37154d261e43db5f8dfa1c8 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtk_ovl.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#ifndef __MTK_OVL_H__ +#define __MTK_OVL_H__ +#include "primary_display.h" +void ovl2mem_setlayernum(int layer_num); +int ovl2mem_get_info(void *info); +int get_ovl2mem_ticket(void); +int ovl2mem_init(unsigned int session); +int ovl2mem_input_config(disp_session_input_config *input); +int ovl2mem_output_config(disp_mem_output_config *out); +int ovl2mem_trigger(int blocking, void *callback, unsigned int userdata); +void ovl2mem_wait_done(void); +int ovl2mem_deinit(void); + +#endif diff --git a/drivers/misc/mediatek/video/mt6755/mtkfb.c b/drivers/misc/mediatek/video/mt6755/mtkfb.c new file mode 100644 index 0000000000000000000000000000000000000000..70b574ffefd466385224d5fd2f403bdd6877a385 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtkfb.c @@ -0,0 +1,2880 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "disp_assert_layer.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +#include "ion_drv.h" +#include +/* #include */ +#include +#include +#include +#include +#include "disp_debug.h" +#include "ddp_hal.h" +#include "disp_log.h" +#include "disp_lcm.h" +#include "mtkfb.h" +#include "mtkfb_console.h" +#include "mtkfb_fence.h" +#include "mtkfb_debug.h" +#include "mtkfb_info.h" +#include "ddp_ovl.h" +#include "disp_drv_platform.h" +#include "primary_display.h" +#include "ddp_dump.h" +#include "disp_recorder.h" +#include "fbconfig_kdebug.h" +#include "mtk_ovl.h" +#include "mt_boot.h" +#include "disp_helper.h" +#include "disp_dts_gpio.h" +#include "disp_recovery.h" +#include "ddp_clkmgr.h" + +/* static variable */ +static u32 MTK_FB_XRES; +static u32 MTK_FB_YRES; +static u32 MTK_FB_BPP; +static u32 MTK_FB_PAGES; +static u32 fb_xres_update; +static u32 fb_yres_update; +static size_t mtkfb_log_on = true; + +static int sem_flipping_cnt = 1; +static int sem_early_suspend_cnt = 1; +static int vsync_cnt; +static const struct timeval FRAME_INTERVAL = { 0, 30000 }; /* 33ms */ + +static bool no_update; +static disp_session_input_config session_input; + +/* macro definiton */ +#define ALIGN_TO(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) +#define MTK_FB_XRESV (ALIGN_TO(MTK_FB_XRES, MTK_FB_ALIGNMENT)) +#define MTK_FB_YRESV (MTK_FB_YRES * MTK_FB_PAGES) /* For page flipping */ +#define MTK_FB_BYPP ((MTK_FB_BPP + 7) >> 3) +#define MTK_FB_LINE (ALIGN_TO(MTK_FB_XRES, MTK_FB_ALIGNMENT) * MTK_FB_BYPP) +#define MTK_FB_SIZE (MTK_FB_LINE * MTK_FB_YRES) +#define MTK_FB_SIZEV (MTK_FB_LINE * MTK_FB_YRES * MTK_FB_PAGES) +#define ASSERT_LAYER (DDP_OVL_LAYER_MUN-1) +#define DISP_DEFAULT_UI_LAYER_ID (DDP_OVL_LAYER_MUN-1) +#define DISP_CHANGED_UI_LAYER_ID (DDP_OVL_LAYER_MUN-2) + +#define CHECK_RET(expr) \ +do { \ + int ret = (expr); \ + ASSERT(0 == ret); \ +} while (0) + +#define MTKFB_LOG(fmt, arg...) \ + do { \ + if (mtkfb_log_on) \ + DISPMSG(fmt, ##arg); \ + } while (0) +/* always show this debug info while the global debug log is off */ +#define MTKFB_LOG_DBG(fmt, arg...) \ + do { \ + if (!mtkfb_log_on) \ + DISPMSG(fmt, ##arg); \ + } while (0) + +#define MTKFB_FUNC() \ + do { \ + if (mtkfb_log_on) \ + DISPMSG("[Func]%s\n", __func__); \ + } while (0) + +#define PRNERR(fmt, args...) DISPMSG(fmt, ## args) + +/* --------------------------------------------------------------------------- */ +/* local variables */ +/* --------------------------------------------------------------------------- */ +struct notifier_block pm_nb; +unsigned int EnableVSyncLog = 0; +unsigned long fb_pa = 0; +atomic_t has_pending_update = ATOMIC_INIT(0); +struct fb_overlay_layer video_layerInfo; +uint32_t dbr_backup = 0; +uint32_t dbg_backup = 0; +uint32_t dbb_backup = 0; +bool fblayer_dither_needed = false; +bool is_ipoh_bootup = false; +struct fb_info *mtkfb_fbi; +struct fb_overlay_layer fb_layer_context; +mtk_dispif_info_t dispif_info[MTKFB_MAX_DISPLAY_COUNT]; +unsigned int FB_LAYER = 2; +bool is_early_suspended = false; +atomic_t OverlaySettingDirtyFlag = ATOMIC_INIT(0); +atomic_t OverlaySettingApplied = ATOMIC_INIT(0); +unsigned int PanDispSettingPending = 0; +unsigned int PanDispSettingDirty = 0; +unsigned int PanDispSettingApplied = 0; +unsigned int need_esd_check = 0; +unsigned int lcd_fps = 6000; +wait_queue_head_t screen_update_wq; +char mtkfb_lcm_name[256] = { 0 }; + + +DEFINE_SEMAPHORE(sem_flipping); +DEFINE_SEMAPHORE(sem_early_suspend); +DEFINE_SEMAPHORE(sem_overlay_buffer); + +/* --------------------------------------------------------------------------- */ +/* local function declarations */ +/* --------------------------------------------------------------------------- */ +static int mtkfb_set_par(struct fb_info *fbi); +static int init_framebuffer(struct fb_info *info); +static int mtkfb_get_overlay_layer_info(struct fb_overlay_layer_info *layerInfo); + +#ifdef CONFIG_OF +static int _parse_tag_videolfb(void); +#endif + +void mtkfb_log_enable(int enable) +{ + mtkfb_log_on = enable; + MTKFB_LOG("mtkfb log %s\n", enable ? "enabled" : "disabled"); +} + +/* + * --------------------------------------------------------------------------- + * fbdev framework callbacks and the ioctl interface + * --------------------------------------------------------------------------- + */ +/* Called each time the mtkfb device is opened */ +static int mtkfb_open(struct fb_info *info, int user) +{ + DISPFUNC(); + MSG_FUNC_ENTER(); + MSG_FUNC_LEAVE(); + return 0; +} + +/* Called when the mtkfb device is closed. We make sure that any pending + * gfx DMA operations are ended, before we return. */ +static int mtkfb_release(struct fb_info *info, int user) +{ + + DISPFUNC(); + + MSG_FUNC_ENTER(); + MSG_FUNC_LEAVE(); + return 0; +} + +/* Store a single color palette entry into a pseudo palette or the hardware + * palette if one is available. For now we support only 16bpp and thus store + * the entry only to the pseudo palette. + */ +static int mtkfb_setcolreg(u_int regno, u_int red, u_int green, + u_int blue, u_int transp, struct fb_info *info) +{ + int r = 0; + unsigned bpp, m; + + + MSG_FUNC_ENTER(); + + bpp = info->var.bits_per_pixel; + m = 1 << bpp; + if (regno >= m) { + r = -EINVAL; + goto exit; + } + + switch (bpp) { + case 16: + /* RGB 565 */ + ((u32 *) (info->pseudo_palette))[regno] = + ((red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11)); + break; + case 32: + /* ARGB8888 */ + ((u32 *) (info->pseudo_palette))[regno] = + (0xff000000) | + ((red & 0xFF00) << 8) | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); + break; + + /* TODO: RGB888, BGR888, ABGR8888 */ + + default: + ASSERT(0); + } + +exit: + MSG_FUNC_LEAVE(); + return r; +} + +static void mtkfb_blank_resume(void) +{ + int ret; + + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) + return; + + DISPMSG("[FB Driver] enter blank_resume\n"); + + ret = primary_display_resume(); + + if (ret) { + DISPERR("primary display resume failed\n"); + return; + } + + DISPMSG("[FB Driver] leave blank_resume\n"); + +} + +static void mtkfb_blank_suspend(void) +{ + int ret = 0; + + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) + return; + + DISPMSG("[FB Driver] enter blank_suspend\n"); + + msleep(30); + + ret = primary_display_suspend(); + + if (ret < 0) { + DISPERR("primary display suspend failed\n"); + return; + } + + DISPMSG("[FB Driver] leave blank_suspend\n"); +} + +#if defined(CONFIG_PM_AUTOSLEEP) +static int mtkfb_blank(int blank_mode, struct fb_info *info) +{ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + if (bypass_blank) { + DISPERR("FB_BLANK_UNBLANK bypass_blank %d\n", bypass_blank); + break; + } + mtkfb_blank_resume(); + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + break; + case FB_BLANK_POWERDOWN: + if (bypass_blank) { + DISPERR("FB_BLANK_POWERDOWN bypass_blank %d\n", bypass_blank); + break; + } + mtkfb_blank_suspend(); + break; + default: + return -EINVAL; + } + + return 0; +} +#endif + +int mtkfb_set_backlight_level(unsigned int level) +{ + MTKFB_FUNC(); + DISPDBG("mtkfb_set_backlight_level:%d Start\n", level); + primary_display_setbacklight(level); + DISPDBG("mtkfb_set_backlight_level End\n"); + return 0; +} +EXPORT_SYMBOL(mtkfb_set_backlight_level); + +int mtkfb_set_backlight_mode(unsigned int mode) +{ + MTKFB_FUNC(); + if (down_interruptible(&sem_flipping)) { + DISPERR("[FB Driver] can't get semaphore:%d\n", __LINE__); + return -ERESTARTSYS; + } + sem_flipping_cnt--; + if (down_interruptible(&sem_early_suspend)) { + DISPERR("[FB Driver] can't get semaphore:%d\n", __LINE__); + sem_flipping_cnt++; + up(&sem_flipping); + return -ERESTARTSYS; + } + + sem_early_suspend_cnt--; + if (primary_display_is_sleepd()) + goto End; + + /* DISP_SetBacklight_mode(mode); */ +End: + sem_flipping_cnt++; + sem_early_suspend_cnt++; + up(&sem_early_suspend); + up(&sem_flipping); + return 0; +} +EXPORT_SYMBOL(mtkfb_set_backlight_mode); + +int mtkfb_set_backlight_pwm(int div) +{ + MTKFB_FUNC(); + if (down_interruptible(&sem_flipping)) { + DISPERR("[FB Driver] can't get semaphore:%d\n", __LINE__); + return -ERESTARTSYS; + } + sem_flipping_cnt--; + if (down_interruptible(&sem_early_suspend)) { + DISPERR("[FB Driver] can't get semaphore:%d\n", __LINE__); + sem_flipping_cnt++; + up(&sem_flipping); + return -ERESTARTSYS; + } + sem_early_suspend_cnt--; + if (primary_display_is_sleepd()) + goto End; + /* DISP_SetPWM(div); */ +End: + sem_flipping_cnt++; + sem_early_suspend_cnt++; + up(&sem_early_suspend); + up(&sem_flipping); + return 0; +} +EXPORT_SYMBOL(mtkfb_set_backlight_pwm); + +int mtkfb_get_backlight_pwm(int div, unsigned int *freq) +{ + /* DISP_GetPWM(div, freq); */ + return 0; +} +EXPORT_SYMBOL(mtkfb_get_backlight_pwm); + +void mtkfb_waitVsync(void) +{ + if (primary_display_is_sleepd()) { + DISPMSG("[MTKFB_VSYNC]:mtkfb has suspend, return directly\n"); + msleep(20); + return; + } + vsync_cnt++; +#ifdef CONFIG_MTK_FPGA + msleep(20); +#else + primary_display_wait_for_vsync(NULL); +#endif + vsync_cnt--; +} +EXPORT_SYMBOL(mtkfb_waitVsync); + +static int _convert_fb_layer_to_disp_input(struct fb_overlay_layer *src, disp_input_config *dst) +{ + + dst->layer_id = src->layer_id; + + if (!src->layer_enable) { + dst->layer_enable = 0; + return 0; + } + + switch (src->src_fmt) { + case MTK_FB_FORMAT_YUV422: + dst->src_fmt = DISP_FORMAT_YUV422; + break; + + case MTK_FB_FORMAT_RGB565: + dst->src_fmt = DISP_FORMAT_RGB565; + break; + + case MTK_FB_FORMAT_RGB888: + dst->src_fmt = DISP_FORMAT_RGB888; + break; + + case MTK_FB_FORMAT_BGR888: + dst->src_fmt = DISP_FORMAT_BGR888; + break; + + case MTK_FB_FORMAT_ARGB8888: + dst->src_fmt = DISP_FORMAT_ARGB8888; + break; + + case MTK_FB_FORMAT_ABGR8888: + dst->src_fmt = DISP_FORMAT_ABGR8888; + break; + + case MTK_FB_FORMAT_XRGB8888: + dst->src_fmt = DISP_FORMAT_XRGB8888; + break; + + case MTK_FB_FORMAT_XBGR8888: + dst->src_fmt = DISP_FORMAT_XBGR8888; + break; + + case MTK_FB_FORMAT_UYVY: + dst->src_fmt = DISP_FORMAT_UYVY; + break; + case MTK_FB_FORMAT_RGBA8888: + dst->src_fmt = DISP_FORMAT_RGBA8888; + break; + + case MTK_FB_FORMAT_BGRA8888: + dst->src_fmt = DISP_FORMAT_BGRA8888; + break; + + default: + DISPERR("Invalid color format: 0x%x\n", src->src_fmt); + return -1; + } + + dst->src_base_addr = src->src_base_addr; + dst->security = src->security; + dst->src_phy_addr = src->src_phy_addr; + DISPDBG("_convert_fb_layer_to_disp_input, dst->addr=0x%p\n", dst->src_phy_addr); + + dst->isTdshp = src->isTdshp; + dst->next_buff_idx = src->next_buff_idx; + dst->identity = src->identity; + dst->connected_type = src->connected_type; + + /* set Alpha blending */ + dst->alpha = src->alpha; + if (MTK_FB_FORMAT_ARGB8888 == src->src_fmt || MTK_FB_FORMAT_ABGR8888 == src->src_fmt) + dst->alpha_enable = true; + else + dst->alpha_enable = false; + + + /* set src width, src height */ + dst->src_offset_x = src->src_offset_x; + dst->src_offset_y = src->src_offset_y; + dst->src_width = src->src_width; + dst->src_height = src->src_height; + dst->tgt_offset_x = src->tgt_offset_x; + dst->tgt_offset_y = src->tgt_offset_y; + dst->tgt_width = src->tgt_width; + dst->tgt_height = src->tgt_height; + if (dst->tgt_width > dst->src_width) + dst->tgt_width = dst->src_width; + if (dst->tgt_height > dst->src_height) + dst->tgt_height = dst->src_height; + + dst->src_pitch = src->src_pitch; + + /* set color key */ + dst->src_color_key = src->src_color_key; + dst->src_use_color_key = src->src_use_color_key; + + /* data transferring is triggerred in MTKFB_TRIG_OVERLAY_OUT */ + dst->layer_enable = src->layer_enable; + +#if 1 + DISPDBG("%s:id=%u,en=%u,next_idx=%u,vaddr=%p,pa=%p,srcfmt=%u,dstfmt=%u,pitch=%u,x=%u,y=%u,w=%u,h=%u\n", + __func__, dst->layer_id, dst->layer_enable, dst->next_buff_idx, dst->src_base_addr, + dst->src_phy_addr, src->src_fmt, dst->src_fmt, dst->src_pitch, dst->src_offset_x, + dst->src_offset_y, dst->src_width, dst->src_height); + DISPDBG("%s:target xoff=%u, target yoff=%u, target w=%u, target h=%u, aen=%u\n", + __func__, dst->tgt_offset_x, dst->tgt_offset_y, dst->tgt_width, dst->tgt_height, + dst->alpha_enable); +#endif + return 0; +} +#if 0 +static int _overlay_info_convert(struct fb_overlay_layer *src, OVL_CONFIG_STRUCT *dst) +{ + unsigned int layerpitch = 0; + unsigned int layerbpp = 0; + + dst->layer = src->layer_id; + + if (!src->layer_enable) { + dst->layer_en = 0; + dst->isDirty = true; + return 0; + } + + switch (src->src_fmt) { + case MTK_FB_FORMAT_YUV422: + dst->fmt = UFMT_YUYV; + layerpitch = 2; + layerbpp = 16; + break; + + case MTK_FB_FORMAT_RGB565: + dst->fmt = UFMT_RGB565; + layerpitch = 2; + layerbpp = 16; + break; + + case MTK_FB_FORMAT_RGB888: + dst->fmt = UFMT_RGB888; + layerpitch = 3; + layerbpp = 24; + break; + + case MTK_FB_FORMAT_BGR888: + dst->fmt = UFMT_BGR888; + layerpitch = 3; + layerbpp = 24; + break; + + case MTK_FB_FORMAT_ARGB8888: + dst->fmt = UFMT_ARGB8888; + layerpitch = 4; + layerbpp = 32; + break; + + case MTK_FB_FORMAT_ABGR8888: + /* dst->fmt = eABGR8888; */ + dst->fmt = UFMT_ABGR8888; + layerpitch = 4; + layerbpp = 32; + break; + case MTK_FB_FORMAT_XRGB8888: + dst->fmt = UFMT_XRGB8888; + layerpitch = 4; + layerbpp = 32; + break; + + case MTK_FB_FORMAT_XBGR8888: + dst->fmt = UFMT_XBGR8888; + layerpitch = 4; + layerbpp = 32; + break; + + case MTK_FB_FORMAT_UYVY: + dst->fmt = UFMT_UYVY; + layerpitch = 2; + layerbpp = 16; + break; + + default: + DISPERR("Invalid color format: 0x%x\n", src->src_fmt); + return -1; + } + + dst->vaddr = (unsigned long)src->src_base_addr; + dst->security = src->security; +/* set overlay will not use fence+ion handle */ +#if 0 +/* #if defined (MTK_FB_ION_SUPPORT) */ + if (src->src_phy_addr != NULL) + dst->addr = (unsigned int)src->src_phy_addr; + else + dst->addr = mtkfb_query_buf_mva(src->layer_id, (unsigned int)src->next_buff_idx); + +#else + dst->addr = (unsigned long)src->src_phy_addr; +#endif + dst->isTdshp = src->isTdshp; + dst->buff_idx = src->next_buff_idx; + dst->identity = src->identity; + dst->connected_type = src->connected_type; + + /* set Alpha blending */ + dst->alpha = src->alpha; + if (MTK_FB_FORMAT_ARGB8888 == src->src_fmt || MTK_FB_FORMAT_ABGR8888 == src->src_fmt) + dst->aen = TRUE; + else + dst->aen = FALSE; + + + /* set src width, src height */ + dst->src_x = src->src_offset_x; + dst->src_y = src->src_offset_y; + dst->src_w = src->src_width; + dst->src_h = src->src_height; + dst->dst_x = src->tgt_offset_x; + dst->dst_y = src->tgt_offset_y; + dst->dst_w = src->tgt_width; + dst->dst_h = src->tgt_height; + if (dst->dst_w > dst->src_w) + dst->dst_w = dst->src_w; + if (dst->dst_h > dst->src_h) + dst->dst_h = dst->src_h; + + dst->src_pitch = src->src_pitch * layerpitch; + /* set color key */ + dst->key = src->src_color_key; + dst->keyEn = src->src_use_color_key; + /* data transferring is triggerred in MTKFB_TRIG_OVERLAY_OUT */ + dst->layer_en = src->layer_enable; + dst->isDirty = true; + +#if 1 + DISPMSG("%s:id=%u,en=%u,next_idx=%u,vaddr=0x%lx,paddr=0x%lx,fmt=%u,pitch=%u,xoff=%u,yoff=%u,w=%u,h=%u\n", + __func__, dst->layer, dst->layer_en, dst->buff_idx, dst->addr, dst->vaddr, dst->fmt, + dst->src_pitch, dst->src_x, dst->src_y, dst->src_w, dst->src_h); + DISPMSG("%s:target xoff=%u, target yoff=%u, target w=%u, target h=%u, aen=%u\n", + __func__, dst->dst_x, dst->dst_y, dst->dst_w, dst->dst_h, dst->aen); +#endif + + return 0; +} +#endif +static int mtkfb_pan_display_impl(struct fb_var_screeninfo *var, struct fb_info *info) +{ + uint32_t offset = 0; + uint32_t paStart = 0; + char *vaStart = NULL, *vaEnd = NULL; + int ret = 0; + unsigned int src_pitch = 0; + disp_session_input_config *session_input; + disp_input_config *input; + + /* DISPFUNC(); */ + + if (no_update) { + DISPMSG("the first time of mtkfb_pan_display_impl will be ignored\n"); + return ret; + } + + DISPDBG("pan_display: offset(%u,%u), res(%u,%u), resv(%u,%u)\n", + var->xoffset, var->yoffset, info->var.xres, info->var.yres, + info->var.xres_virtual, info->var.yres_virtual); + + info->var.yoffset = var->yoffset; + offset = var->yoffset * info->fix.line_length; + paStart = fb_pa + offset; + vaStart = info->screen_base + offset; + vaEnd = vaStart + info->var.yres * info->fix.line_length; + + session_input = kzalloc(sizeof(*session_input), GFP_KERNEL); + if (!session_input) + BUG(); + + /* pan display use layer 0 */ + input = &session_input->config[0]; + input->layer_id = 0; + input->src_phy_addr = (void *)((unsigned long)paStart); + input->src_base_addr = (void *)((unsigned long)vaStart); + input->layer_id = primary_display_get_option("FB_LAYER"); + input->layer_enable = 1; + input->src_offset_x = 0; + input->src_offset_y = 0; + input->src_width = var->xres; + input->src_height = var->yres; + input->tgt_offset_x = 0; + input->tgt_offset_y = 0; + input->tgt_width = var->xres; + input->tgt_height = var->yres; + + switch (var->bits_per_pixel) { + case 16: + input->src_fmt = DISP_FORMAT_RGB565; + break; + case 24: + input->src_fmt = DISP_FORMAT_RGB888; + break; + case 32: + input->src_fmt = + (0 == var->blue.offset) ? DISP_FORMAT_BGRA8888 : DISP_FORMAT_RGBX8888; + + break; + default: + DISPERR("Invalid color format bpp: 0x%d\n", var->bits_per_pixel); + kfree(session_input); + return -1; + } + input->alpha_enable = false; + + input->alpha = 0xFF; + input->next_buff_idx = -1; + src_pitch = ALIGN_TO(var->xres, MTK_FB_ALIGNMENT); + input->src_pitch = src_pitch; + + session_input->config_layer_num++; + + if (!is_DAL_Enabled()) { + /* disable font layer(layer3) drawed in lk */ + session_input->config[1].layer_id = primary_display_get_option("ASSERT_LAYER"); + session_input->config[1].next_buff_idx = -1; + session_input->config[1].layer_enable = 0; + session_input->config_layer_num++; + } + ret = primary_display_config_input_multiple(session_input); + ret = primary_display_trigger(true, NULL, 0); + + kfree(session_input); + + return ret; +} + + +/* Set fb_info.fix fields and also updates fbdev. + * When calling this fb_info.var must be set up already. + */ +static void set_fb_fix(struct mtkfb_device *fbdev) +{ + struct fb_info *fbi = fbdev->fb_info; + struct fb_fix_screeninfo *fix = &fbi->fix; + struct fb_var_screeninfo *var = &fbi->var; + struct fb_ops *fbops = fbi->fbops; + + strncpy(fix->id, MTKFB_DRIVER, sizeof(fix->id)); + fix->type = FB_TYPE_PACKED_PIXELS; + + switch (var->bits_per_pixel) { + case 16: + case 24: + case 32: + fix->visual = FB_VISUAL_TRUECOLOR; + break; + case 1: + case 2: + case 4: + case 8: + fix->visual = FB_VISUAL_PSEUDOCOLOR; + break; + default: + ASSERT(0); + } + + fix->accel = FB_ACCEL_NONE; + fix->line_length = ALIGN_TO(var->xres_virtual, MTK_FB_ALIGNMENT) * var->bits_per_pixel / 8; + fix->smem_len = fbdev->fb_size_in_byte; + fix->smem_start = fbdev->fb_pa_base; + + fix->xpanstep = 0; + fix->ypanstep = 1; + + fbops->fb_fillrect = cfb_fillrect; + fbops->fb_copyarea = cfb_copyarea; + fbops->fb_imageblit = cfb_imageblit; +} + + +/* Check values in var, try to adjust them in case of out of bound values if + * possible, or return error. + */ +static int mtkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) +{ + unsigned int bpp; + unsigned long max_frame_size; + unsigned long line_size; + + struct mtkfb_device *fbdev = (struct mtkfb_device *)fbi->par; + + /* DISPFUNC(); */ + + DISPDBG("mtkfb_check_var,xres=%u,yres=%u,x_virt=%u,y_virt=%u,xoffset=%u,yoffset=%u,bits_per_pixel=%u)\n", + var->xres, var->yres, var->xres_virtual, var->yres_virtual, + var->xoffset, var->yoffset, var->bits_per_pixel); + + bpp = var->bits_per_pixel; + + if (bpp != 16 && bpp != 24 && bpp != 32) { + MTKFB_LOG("[%s]unsupported bpp: %d", __func__, bpp); + return -1; + } + + switch (var->rotate) { + case 0: + case 180: + var->xres = MTK_FB_XRES; + var->yres = MTK_FB_YRES; + break; + case 90: + case 270: + var->xres = MTK_FB_YRES; + var->yres = MTK_FB_XRES; + break; + default: + return -1; + } + + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + max_frame_size = fbdev->fb_size_in_byte; + DISPDBG("fbdev->fb_size_in_byte=0x%08lx\n", fbdev->fb_size_in_byte); + line_size = var->xres_virtual * bpp / 8; + + if (line_size * var->yres_virtual > max_frame_size) { + /* Try to keep yres_virtual first */ + line_size = max_frame_size / var->yres_virtual; + var->xres_virtual = line_size * 8 / bpp; + if (var->xres_virtual < var->xres) { + /* Still doesn't fit. Shrink yres_virtual too */ + var->xres_virtual = var->xres; + line_size = var->xres * bpp / 8; + var->yres_virtual = max_frame_size / line_size; + } + } + DISPDBG("mtkfb_check_var,xres=%u,yres=%u,x_virt=%u,y_virl=%u,xoffset=%u,yoffset=%u,bits_per_pixel=%u)\n", + var->xres, var->yres, var->xres_virtual, var->yres_virtual, + var->xoffset, var->yoffset, var->bits_per_pixel); + if (var->xres + var->xoffset > var->xres_virtual) + var->xoffset = var->xres_virtual - var->xres; + if (var->yres + var->yoffset > var->yres_virtual) + var->yoffset = var->yres_virtual - var->yres; + + DISPDBG("mtkfb_check_var,xres=%u,yres=%u,x_virt=%u,y_virt=%u,xoffset=%u,yoffset=%u,bits_per_pixel=%u)\n", + var->xres, var->yres, var->xres_virtual, var->yres_virtual, + var->xoffset, var->yoffset, var->bits_per_pixel); + + if (16 == bpp) { + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + } else if (24 == bpp) { + var->red.length = var->green.length = var->blue.length = 8; + var->transp.length = 0; + + /* Check if format is RGB565 or BGR565 */ + + ASSERT(8 == var->green.offset); + ASSERT(16 == var->red.offset + var->blue.offset); + ASSERT(16 == var->red.offset || 0 == var->red.offset); + } else if (32 == bpp) { + var->red.length = var->green.length = var->blue.length = var->transp.length = 8; + + /* Check if format is ARGB565 or ABGR565 */ + + ASSERT(8 == var->green.offset && 24 == var->transp.offset); + ASSERT(16 == var->red.offset + var->blue.offset); + ASSERT(16 == var->red.offset || 0 == var->red.offset); + } + + var->red.msb_right = var->green.msb_right = var->blue.msb_right = var->transp.msb_right = 0; + + if (var->activate & FB_ACTIVATE_NO_UPDATE) + no_update = true; + else + no_update = false; + + + var->activate = FB_ACTIVATE_NOW; + + var->height = UINT_MAX; + var->width = UINT_MAX; + var->grayscale = 0; + var->nonstd = 0; + + var->pixclock = UINT_MAX; + var->left_margin = UINT_MAX; + var->right_margin = UINT_MAX; + var->upper_margin = UINT_MAX; + var->lower_margin = UINT_MAX; + var->hsync_len = UINT_MAX; + var->vsync_len = UINT_MAX; + + var->vmode = FB_VMODE_NONINTERLACED; + var->sync = 0; + + MSG_FUNC_LEAVE(); + return 0; +} + + + +/* Switch to a new mode. The parameters for it has been check already by + * mtkfb_check_var. + */ +static int mtkfb_set_par(struct fb_info *fbi) +{ + struct fb_var_screeninfo *var = &fbi->var; + struct mtkfb_device *fbdev = (struct mtkfb_device *)fbi->par; + struct fb_overlay_layer fb_layer; + u32 bpp = var->bits_per_pixel; + disp_session_input_config *session_input; + disp_input_config *input; + + /* DISPFUNC(); */ + memset(&fb_layer, 0, sizeof(struct fb_overlay_layer)); + switch (bpp) { + case 16: + fb_layer.src_fmt = MTK_FB_FORMAT_RGB565; + fb_layer.src_use_color_key = 1; + fb_layer.src_color_key = 0xFF000000; + break; + + case 24: + fb_layer.src_use_color_key = 1; + fb_layer.src_fmt = (0 == var->blue.offset) ? + MTK_FB_FORMAT_RGB888 : MTK_FB_FORMAT_BGR888; + fb_layer.src_color_key = 0xFF000000; + break; + + case 32: + fb_layer.src_use_color_key = 0; + DISPDBG("set_par,var->blue.offset=%d\n", var->blue.offset); + fb_layer.src_fmt = (0 == var->blue.offset) ? + MTK_FB_FORMAT_RGBA8888 : MTK_FB_FORMAT_BGRA8888; + fb_layer.src_color_key = 0; + break; + + default: + fb_layer.src_fmt = MTK_FB_FORMAT_UNKNOWN; + DISPERR("[%s]unsupported bpp: %d", __func__, bpp); + return -1; + } + + + set_fb_fix(fbdev); + + fb_layer.layer_id = primary_display_get_option("FB_LAYER"); + fb_layer.layer_enable = 1; + fb_layer.src_base_addr = + (void *)((unsigned long)fbdev->fb_va_base + var->yoffset * fbi->fix.line_length); + DISPDBG("fb_pa=0x%08lx, var->yoffset=0x%08x,fbi->fix.line_length=0x%08x\n", fb_pa, + var->yoffset, fbi->fix.line_length); + fb_layer.src_phy_addr = (void *)(fb_pa + var->yoffset * fbi->fix.line_length); + fb_layer.src_direct_link = 0; + fb_layer.src_offset_x = fb_layer.src_offset_y = 0; + fb_layer.src_pitch = ALIGN_TO(var->xres, MTK_FB_ALIGNMENT); + fb_layer.src_width = fb_layer.tgt_width = var->xres; + fb_layer.src_height = fb_layer.tgt_height = var->yres; + fb_layer.tgt_offset_x = fb_layer.tgt_offset_y = 0; + fb_layer.alpha = 0xff; + /* fb_layer.src_color_key = 0; */ + fb_layer.layer_rotation = MTK_FB_ORIENTATION_0; + fb_layer.layer_type = LAYER_2D; + DISPDBG("mtkfb_set_par, fb_layer.src_fmt=%x\n", fb_layer.src_fmt); + + session_input = kzalloc(sizeof(*session_input), GFP_KERNEL); + if (!session_input) + goto out; + + session_input->config_layer_num = 0; + + if (!is_DAL_Enabled()) { + DISPDBG("AEE is not enabled, will disable layer 3\n"); + input = &session_input->config[session_input->config_layer_num++]; + input->layer_id = primary_display_get_option("ASSERT_LAYER"); + input->layer_enable = 0; + } else { + DISPDBG("AEE is enabled, should not disable layer 3\n"); + } + + input = &session_input->config[session_input->config_layer_num++]; + _convert_fb_layer_to_disp_input(&fb_layer, input); + primary_display_config_input_multiple(session_input); + kfree(session_input); + +out: + /* backup fb_layer information. */ + memcpy(&fb_layer_context, &fb_layer, sizeof(fb_layer)); + + MSG_FUNC_LEAVE(); + return 0; +} + + +static int mtkfb_soft_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + + return 0; +} + +static int mtkfb_get_overlay_layer_info(struct fb_overlay_layer_info *layerInfo) +{ + return 0; +} + +void mtkfb_dump_layer_info(void) +{ +} + + +uint32_t color = 0; +unsigned int mtkfb_fm_auto_test(void) +{ + unsigned int result = 0; + unsigned int i = 0; + unsigned long fbVirAddr; + uint32_t fbsize; + int r = 0; + unsigned int *fb_buffer; + struct mtkfb_device *fbdev = (struct mtkfb_device *)mtkfb_fbi->par; + struct fb_var_screeninfo var; + + fbVirAddr = (unsigned long)fbdev->fb_va_base; + fb_buffer = (unsigned int *)fbVirAddr; + memcpy(&var, &(mtkfb_fbi->var), sizeof(var)); + var.activate = FB_ACTIVATE_NOW; + var.bits_per_pixel = 32; + var.transp.offset = 24; + var.transp.length = 8; + var.red.offset = 16; + var.red.length = 8; + var.green.offset = 8; + var.green.length = 8; + var.blue.offset = 0; + var.blue.length = 8; + + r = mtkfb_check_var(&var, mtkfb_fbi); + if (r != 0) + PRNERR("failed to mtkfb_check_var\n"); + + mtkfb_fbi->var = var; + +#if 0 + r = mtkfb_set_par(mtkfb_fbi); + + if (r != 0) + PRNERR("failed to mtkfb_set_par\n"); +#endif + if (color == 0) + color = 0xFF00FF00; + fbsize = + ALIGN_TO(DISP_GetScreenWidth(), + MTK_FB_ALIGNMENT) * DISP_GetScreenHeight() * MTK_FB_PAGES; + for (i = 0; i < fbsize; i++) + *fb_buffer++ = color; +#if 0 + if (!primary_display_is_video_mode()) + primary_display_trigger(1, NULL, 0); +#endif + mtkfb_pan_display_impl(&mtkfb_fbi->var, mtkfb_fbi); + msleep(100); + + result = primary_display_lcm_ATA(); + + if (result == 0) + DISPERR("ATA LCM failed\n"); + else + DISPMSG("ATA LCM passed\n"); + + + return result; +} + + + +static int mtkfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + DISP_STATUS ret = 0; + int r = 0; + + /* DISPFUNC(); */ + /* / M: dump debug mmprofile log info */ + DISPDBG("mtkfb_ioctl, info=%p, cmd nr=0x%08x, cmd size=0x%08x\n", info, + (unsigned int)_IOC_NR(cmd), (unsigned int)_IOC_SIZE(cmd)); + + switch (cmd) { + + case MTKFB_GET_FRAMEBUFFER_MVA: + return copy_to_user(argp, &fb_pa, sizeof(fb_pa)) ? -EFAULT : 0; + /* remain this for engineer mode dfo multiple resolution */ + + case MTKFB_GET_DISPLAY_IF_INFORMATION: + { + int displayid = 0; + + if (copy_from_user(&displayid, (void __user *)arg, sizeof(displayid))) { + MTKFB_LOG("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + + if (displayid > MTKFB_MAX_DISPLAY_COUNT || displayid < 0) { + DISPERR("[FB]: invalid display id:%d\n", displayid); + return -EFAULT; + } + + if (displayid == 0) { + dispif_info[displayid].displayWidth = primary_display_get_width(); + dispif_info[displayid].displayHeight = primary_display_get_height(); + + dispif_info[displayid].lcmOriginalWidth = + primary_display_get_original_width(); + dispif_info[displayid].lcmOriginalHeight = + primary_display_get_original_height(); + dispif_info[displayid].displayMode = + primary_display_is_video_mode() ? 0 : 1; + } else { + DISPERR("information for displayid: %d is not available now\n", + displayid); + } + + if (copy_to_user((void __user *)arg, &(dispif_info[displayid]), sizeof(mtk_dispif_info_t))) { + MTKFB_LOG("[FB]: copy_to_user failed! line:%d\n", __LINE__); + r = -EFAULT; + } + + return r; + } + + case MTKFB_POWEROFF: + { + MTKFB_FUNC(); + if (primary_display_is_sleepd()) { + DISPMSG("[FB Driver] is still in MTKFB_POWEROFF!!!\n"); + return r; + } + + DISPMSG("[FB Driver] enter MTKFB_POWEROFF\n"); + ret = primary_display_suspend(); + if (ret < 0) + DISPERR("primary display suspend failed\n"); + DISPMSG("[FB Driver] leave MTKFB_POWEROFF\n"); + + is_early_suspended = true; /* no care */ + return r; + } + + case MTKFB_POWERON: + { + MTKFB_FUNC(); + if (primary_display_is_alive()) { + DISPMSG("[FB Driver] is still in MTKFB_POWERON!!!\n"); + return r; + } + DISPMSG("[FB Driver] enter MTKFB_POWERON\n"); + primary_display_resume(); + DISPMSG("[FB Driver] leave MTKFB_POWERON\n"); + is_early_suspended = false; /* no care */ + return r; + } + case MTKFB_GET_POWERSTATE: + { + int power_state; + + if (primary_display_is_sleepd()) + power_state = 0; + else + power_state = 1; + + if (copy_to_user(argp, &power_state, sizeof(power_state))) { + pr_err("MTKFB_GET_POWERSTATE failed\n"); + return -EFAULT; + } + + return 0; + } + + case MTKFB_CONFIG_IMMEDIATE_UPDATE: + { + MTKFB_LOG("[%s] MTKFB_CONFIG_IMMEDIATE_UPDATE, enable = %lu\n", __func__, + arg); + if (down_interruptible(&sem_early_suspend)) { + MTKFB_LOG("[mtkfb_ioctl] can't get semaphore:%d\n", __LINE__); + return -ERESTARTSYS; + } + sem_early_suspend_cnt--; + /* DISP_WaitForLCDNotBusy(); */ + /* ret = DISP_ConfigImmediateUpdate((BOOL)arg); */ + /* sem_early_suspend_cnt++; */ + up(&sem_early_suspend); + return r; + } + + case MTKFB_CAPTURE_FRAMEBUFFER: + { + unsigned long dst_pbuf = 0; + unsigned long *src_pbuf = NULL; + unsigned int pixel_bpp = info->var.bits_per_pixel / 8; + unsigned int fbsize = DISP_GetScreenHeight() * DISP_GetScreenWidth() * pixel_bpp; + + if (copy_from_user(&dst_pbuf, (void __user *)arg, sizeof(dst_pbuf))) { + MTKFB_LOG("[FB]: copy_from_user failed! line:%d\n", __LINE__); + r = -EFAULT; + } else { + src_pbuf = vmalloc(fbsize); + if (!src_pbuf) { + MTKFB_LOG("[FB]: vmalloc capture src_pbuf failed! line:%d\n", __LINE__); + r = -EFAULT; + } else { + dprec_logger_start(DPREC_LOGGER_WDMA_DUMP, 0, 0); + primary_display_capture_framebuffer_ovl((unsigned long)src_pbuf, UFMT_BGRA8888); + dprec_logger_done(DPREC_LOGGER_WDMA_DUMP, 0, 0); + if (copy_to_user((unsigned long *)dst_pbuf, src_pbuf, fbsize)) { + MTKFB_LOG("[FB]: copy_to_user failed! line:%d\n", __LINE__); + r = -EFAULT; + } + } + vfree(src_pbuf); + } + + return r; + } + + case MTKFB_SLT_AUTO_CAPTURE: + { + struct fb_slt_catpure capConfig; + char *dst_buffer; + unsigned int fb_size; + + if (copy_from_user(&capConfig, (void __user *)arg, sizeof(capConfig))) { + MTKFB_LOG("[FB]: copy_from_user failed! line:%d\n", __LINE__); + r = -EFAULT; + } else { + unsigned int format; + + switch (capConfig.format) { + case MTK_FB_FORMAT_RGB888: + format = UFMT_RGB888; + break; + case MTK_FB_FORMAT_BGR888: + format = UFMT_BGR888; + break; + case MTK_FB_FORMAT_ARGB8888: + format = UFMT_ARGB8888; + break; + case MTK_FB_FORMAT_RGB565: + format = UFMT_RGB565; + break; + case MTK_FB_FORMAT_UYVY: + format = UFMT_UYVY; + break; + case MTK_FB_FORMAT_ABGR8888: + default: + format = UFMT_ABGR8888; + break; + } + + dst_buffer = (char *)capConfig.outputBuffer; + fb_size = DISP_GetScreenWidth() * DISP_GetScreenHeight() * 4; + if (!capConfig.outputBuffer) { + MTKFB_LOG("[FB]: vmalloc capture outputBuffer failed! line:%d\n", + __LINE__); + r = -EFAULT; + } else { + capConfig.outputBuffer = vmalloc(fb_size); + primary_display_capture_framebuffer_ovl((unsigned long) + capConfig.outputBuffer, + format); + if (copy_to_user(dst_buffer, (char *)capConfig.outputBuffer, fb_size)) { + MTKFB_LOG("[FB]: copy_to_user failed!line:%d\n", __LINE__); + r = -EFAULT; + } + vfree((char *)capConfig.outputBuffer); + } + } + + return r; + } + case MTKFB_GET_OVERLAY_LAYER_INFO: + { + struct fb_overlay_layer_info layerInfo; + + MTKFB_LOG(" mtkfb_ioctl():MTKFB_GET_OVERLAY_LAYER_INFO\n"); + + if (copy_from_user(&layerInfo, (void __user *)arg, sizeof(layerInfo))) { + MTKFB_LOG("[FB]: copy_from_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + if (mtkfb_get_overlay_layer_info(&layerInfo) < 0) { + MTKFB_LOG("[FB]: Failed to get overlay layer info\n"); + return -EFAULT; + } + if (copy_to_user((void __user *)arg, &layerInfo, sizeof(layerInfo))) { + MTKFB_LOG("[FB]: copy_to_user failed! line:%d\n", __LINE__); + r = -EFAULT; + } + return r; + } + case MTKFB_SET_OVERLAY_LAYER: + { /* no function */ + struct fb_overlay_layer *layerInfo; + disp_input_config *input; + + layerInfo = kmalloc(sizeof(*layerInfo), GFP_KERNEL); + if (!layerInfo) + return -ENOMEM; + + if (copy_from_user(layerInfo, (void __user *)arg, sizeof(*layerInfo))) { + MTKFB_LOG("[FB]: copy_from_user failed! line:%d\n", __LINE__); + r = -EFAULT; + } else { + /* in early suspend mode ,will not update buffer index, info SF by return value */ + if (primary_display_is_sleepd()) { + DISPMSG + ("[FB] error, set overlay in early suspend ,skip!\n"); + kfree(layerInfo); + return MTKFB_ERROR_IS_EARLY_SUSPEND; + } + memset((void *)&session_input, 0, sizeof(session_input)); + if (layerInfo->layer_id >= TOTAL_OVL_LAYER_NUM) { + DISPAEE("MTKFB_SET_OVERLAY_LAYER ,layer_id invalid=%d\n", + layerInfo->layer_id); + } else { + input = &session_input.config[session_input.config_layer_num++]; + _convert_fb_layer_to_disp_input(layerInfo, input); + } + primary_display_config_input_multiple(&session_input); + primary_display_trigger(1, NULL, 0); + } + kfree(layerInfo); + + return r; + } + + case MTKFB_ERROR_INDEX_UPDATE_TIMEOUT: + { + DISPMSG("[DDP] mtkfb_ioctl():MTKFB_ERROR_INDEX_UPDATE_TIMEOUT\n"); + /* call info dump function here */ + /* mtkfb_dump_layer_info(); */ + return r; + } + + case MTKFB_ERROR_INDEX_UPDATE_TIMEOUT_AEE: + { + DISPMSG("[DDP] mtkfb_ioctl():MTKFB_ERROR_INDEX_UPDATE_TIMEOUT\n"); + /* call info dump function here */ + /* mtkfb_dump_layer_info(); */ + return r; + } + + case MTKFB_SET_VIDEO_LAYERS: + { + struct mmp_fb_overlay_layers { + struct fb_overlay_layer Layer0; + struct fb_overlay_layer Layer1; + struct fb_overlay_layer Layer2; + struct fb_overlay_layer Layer3; + }; + + struct fb_overlay_layer *layerInfo; + int layerInfo_size = sizeof(struct fb_overlay_layer) * VIDEO_LAYER_COUNT; + + MTKFB_LOG(" mtkfb_ioctl():MTKFB_SET_VIDEO_LAYERS\n"); + + layerInfo = kmalloc(layerInfo_size, GFP_KERNEL); + if (!layerInfo) + return -ENOMEM; + + + + if (copy_from_user(layerInfo, (void __user *)arg, layerInfo_size)) { + MTKFB_LOG("[FB]: copy_from_user failed! line:%d\n", __LINE__); + r = -EFAULT; + } else { + int32_t i; + disp_input_config *input; + + memset((void *)&session_input, 0, sizeof(session_input)); + + for (i = 0; i < VIDEO_LAYER_COUNT; ++i) { + if (layerInfo[i].layer_id >= TOTAL_OVL_LAYER_NUM) { + DISPAEE("MTKFB_SET_VIDEO_LAYERS, layer_id invalid=%d\n", + layerInfo[i].layer_id); + continue; + } + + input = + &session_input.config[session_input.config_layer_num++]; + _convert_fb_layer_to_disp_input(&layerInfo[i], input); + + } + primary_display_config_input_multiple(&session_input); + primary_display_trigger(1, NULL, 0); + } + kfree(layerInfo); + return r; + } + + case MTKFB_TRIG_OVERLAY_OUT: + { + MTKFB_LOG(" mtkfb_ioctl():MTKFB_TRIG_OVERLAY_OUT\n"); + primary_display_trigger(1, NULL, 0); + return 0; + } + + case MTKFB_META_RESTORE_SCREEN: + { + struct fb_var_screeninfo var; + + if (copy_from_user(&var, argp, sizeof(var))) + return -EFAULT; + + info->var.yoffset = var.yoffset; + init_framebuffer(info); + + return mtkfb_pan_display_impl(&var, info); + } + + + case MTKFB_GET_DEFAULT_UPDATESPEED: + { + unsigned int speed; + + MTKFB_LOG("[MTKFB] get default update speed\n"); + /* DISP_Get_Default_UpdateSpeed(&speed); */ + + DISPMSG("[MTKFB EM]MTKFB_GET_DEFAULT_UPDATESPEED is %d\n", speed); + return copy_to_user(argp, &speed, sizeof(speed)) ? -EFAULT : 0; + } + + case MTKFB_GET_CURR_UPDATESPEED: + { + unsigned int speed; + + MTKFB_LOG("[MTKFB] get current update speed\n"); + /* DISP_Get_Current_UpdateSpeed(&speed); */ + + DISPMSG("[MTKFB EM]MTKFB_GET_CURR_UPDATESPEED is %d\n", speed); + return copy_to_user(argp, &speed, sizeof(speed)) ? -EFAULT : 0; + } + + case MTKFB_CHANGE_UPDATESPEED: + { + unsigned int speed; + + MTKFB_LOG("[MTKFB] change update speed\n"); + + if (copy_from_user(&speed, (void __user *)arg, sizeof(speed))) { + MTKFB_LOG("[FB]: copy_from_user failed! line:%d\n", __LINE__); + r = -EFAULT; + } else { + /* DISP_Change_Update(speed); */ + + DISPMSG("[MTKFB EM]MTKFB_CHANGE_UPDATESPEED is %d\n", speed); + + } + return r; + } + + case MTKFB_AEE_LAYER_EXIST: + { + int dal_en = is_DAL_Enabled(); + + /* DISPMSG("[MTKFB] isAEEEnabled=%d\n", isAEEEnabled); */ + return copy_to_user(argp, &dal_en, sizeof(dal_en)) ? -EFAULT : 0; + } + case MTKFB_LOCK_FRONT_BUFFER: + return 0; + case MTKFB_UNLOCK_FRONT_BUFFER: + return 0; + + case MTKFB_FACTORY_AUTO_TEST: + { + unsigned int result = 0; + + DISPMSG("factory mode: lcm auto test\n"); + result = mtkfb_fm_auto_test(); + return copy_to_user(argp, &result, sizeof(result)) ? -EFAULT : 0; + } + case MTKFB_META_SHOW_BOOTLOGO: + { + struct mtkfb_device *fbdev; + int i; + + disp_input_config *input; + + DISPMSG("MTKFB_META_SHOW_BOOTLOGO\n"); + memset((void *)&session_input, 0, sizeof(session_input)); + fbdev = (struct mtkfb_device *)mtkfb_fbi->par; + for (i = 0; i < 2; i++) { + + input = &session_input.config[session_input.config_layer_num++]; + + input->layer_enable = 1; + input->src_fmt = DISP_FORMAT_RGBA8888; + input->src_offset_x = 0; + input->src_offset_y = 0; + input->src_width = MTK_FB_XRES; + input->src_height = MTK_FB_YRES; + input->tgt_offset_x = 0; + input->tgt_offset_y = 0; + input->tgt_width = MTK_FB_XRES; + input->tgt_height = MTK_FB_YRES; + + input->src_pitch = ALIGN_TO(MTK_FB_XRES, MTK_FB_ALIGNMENT) * 4; + input->alpha_enable = 1; + input->alpha = 0xff; + input->next_buff_idx = -1; + } + + input = &session_input.config[0]; + input->layer_id = 0; + input->src_phy_addr = (void *)((unsigned long)fbdev->fb_pa_base); + + input = &session_input.config[1]; + input->layer_id = 3; + input->src_phy_addr = + (void *)((unsigned long)(fbdev->fb_pa_base + + (ALIGN_TO(MTK_FB_XRES, MTK_FB_ALIGNMENT) * + ALIGN_TO(MTK_FB_YRES, MTK_FB_ALIGNMENT) * 4))); + + primary_display_config_input_multiple(&session_input); + primary_display_trigger(1, NULL, 0); + + return 0; + } + + default: + pr_err("mtkfb_ioctl Not support, info=0x%p, cmd=0x%08x, arg=0x%08lx\n", info, + (unsigned int)cmd, arg); + return -EINVAL; + } +} + +#ifdef CONFIG_COMPAT + +static void compat_convert(struct compat_fb_overlay_layer *compat_info, + struct fb_overlay_layer *info) +{ + info->layer_id = compat_info->layer_id; + info->layer_enable = compat_info->layer_enable; + info->src_base_addr = (void *)((unsigned long)compat_info->src_base_addr); + info->src_phy_addr = (void *)((unsigned long)compat_info->src_phy_addr); + info->src_direct_link = compat_info->src_direct_link; + info->src_fmt = compat_info->src_fmt; + info->src_use_color_key = compat_info->src_use_color_key; + info->src_color_key = compat_info->src_color_key; + info->src_pitch = compat_info->src_pitch; + info->src_offset_x = compat_info->src_offset_x; + info->src_offset_y = compat_info->src_offset_y; + info->src_width = compat_info->src_width; + info->src_height = compat_info->src_height; + info->tgt_offset_x = compat_info->tgt_offset_x; + info->tgt_offset_y = compat_info->tgt_offset_y; + info->tgt_width = compat_info->tgt_width; + info->tgt_height = compat_info->tgt_height; + info->layer_rotation = compat_info->layer_rotation; + info->layer_type = compat_info->layer_type; + info->video_rotation = compat_info->video_rotation; + + info->isTdshp = compat_info->isTdshp; + info->next_buff_idx = compat_info->next_buff_idx; + info->identity = compat_info->identity; + info->connected_type = compat_info->connected_type; + + info->security = compat_info->security; + info->alpha_enable = compat_info->alpha_enable; + info->alpha = compat_info->alpha; + info->fence_fd = compat_info->fence_fd; + info->ion_fd = compat_info->ion_fd; +} + + +static int mtkfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +{ + struct fb_overlay_layer layerInfo; + long ret = 0; + + pr_debug("[FB Driver] mtkfb_compat_ioctl, cmd=0x%08x, cmd nr=0x%08x, cmd size=0x%08x\n", cmd, + (unsigned int)_IOC_NR(cmd), (unsigned int)_IOC_SIZE(cmd)); + + switch (cmd) { + case COMPAT_MTKFB_GET_FRAMEBUFFER_MVA: + { + compat_uint_t __user *data32; + __u32 data; + + data32 = compat_ptr(arg); + data = (__u32) fb_pa; + if (put_user(data, data32)) { + pr_err("MTKFB_FRAMEBUFFER_MVA failed\n"); + ret = -EFAULT; + } + pr_debug("MTKFB_FRAMEBUFFER_MVA success 0x%lx\n", fb_pa); + return ret; + } + case COMPAT_MTKFB_GET_DISPLAY_IF_INFORMATION: + { + compat_uint_t __user *data32; + compat_uint_t displayid = 0; + compat_mtk_dispif_info_t compat_dispif_info; + + memset(&compat_dispif_info, 0, sizeof(compat_mtk_dispif_info_t)); + data32 = compat_ptr(arg); + + if (get_user(displayid, data32)) { + pr_err("COMPAT_MTKFB_GET_DISPLAY_IF_INFORMATION failed\n"); + return -EFAULT; + } + if (displayid > MTKFB_MAX_DISPLAY_COUNT) { + pr_err("[FB]: invalid display id:%d\n", displayid); + return -EFAULT; + } + if (displayid == 0) { + dispif_info[displayid].displayWidth = primary_display_get_width(); + dispif_info[displayid].displayHeight = primary_display_get_height(); + + dispif_info[displayid].lcmOriginalWidth = + primary_display_get_original_width(); + dispif_info[displayid].lcmOriginalHeight = + primary_display_get_original_height(); + dispif_info[displayid].displayMode = + primary_display_is_video_mode() ? 0 : 1; + } else { + DISPERR("information for displayid: %d is not available now\n", + displayid); + return -EFAULT; + } + compat_dispif_info.displayWidth = + dispif_info[displayid].displayWidth; + compat_dispif_info.displayHeight = + dispif_info[displayid].displayHeight; + compat_dispif_info.lcmOriginalWidth = + dispif_info[displayid].lcmOriginalWidth; + compat_dispif_info.lcmOriginalHeight = + dispif_info[displayid].lcmOriginalHeight; + compat_dispif_info.displayMode = + dispif_info[displayid].displayMode; + if (copy_to_user((void __user *)arg, + &(compat_dispif_info), sizeof(compat_mtk_dispif_info_t))) { + pr_err("[FB]: copy_to_user failed! line:%d\n", __LINE__); + return -EFAULT; + } + break; + } + case COMPAT_MTKFB_POWEROFF: + { + ret = mtkfb_ioctl(info, MTKFB_POWEROFF, arg); + break; + } + + case COMPAT_MTKFB_POWERON: + { + ret = mtkfb_ioctl(info, MTKFB_POWERON, arg); + break; + } + case COMPAT_MTKFB_GET_POWERSTATE: + { + compat_uint_t __user *data32; + int power_state = 0; + + data32 = compat_ptr(arg); + if (primary_display_is_sleepd()) + power_state = 0; + else + power_state = 1; + if (put_user(power_state, data32)) { + pr_err("MTKFB_GET_POWERSTATE failed\n"); + ret = -EFAULT; + } + pr_debug("MTKFB_GET_POWERSTATE success %d\n", power_state); + break; + } + case COMPAT_MTKFB_CAPTURE_FRAMEBUFFER: + { + compat_ulong_t __user *data32; + unsigned long *pbuf; + compat_ulong_t l; + + data32 = compat_ptr(arg); + pbuf = compat_alloc_user_space(sizeof(unsigned long)); + ret = get_user(l, data32); + ret |= put_user(l, pbuf); + primary_display_capture_framebuffer_ovl(*pbuf, UFMT_BGRA8888); + break; + } + case COMPAT_MTKFB_TRIG_OVERLAY_OUT: + { + arg = (unsigned long)compat_ptr(arg); + ret = mtkfb_ioctl(info, MTKFB_TRIG_OVERLAY_OUT, arg); + break; + } + case COMPAT_MTKFB_META_RESTORE_SCREEN: + { + arg = (unsigned long)compat_ptr(arg); + ret = mtkfb_ioctl(info, MTKFB_META_RESTORE_SCREEN, arg); + break; + } + + case COMPAT_MTKFB_SET_OVERLAY_LAYER: + { + struct compat_fb_overlay_layer *compat_layerInfo; + disp_input_config *input; + + compat_layerInfo = kmalloc(sizeof(*compat_layerInfo), GFP_KERNEL); + + if (!compat_layerInfo) + return -ENOMEM; + + MTKFB_LOG(" mtkfb_compat_ioctl():MTKFB_SET_OVERLAY_LAYER\n"); + + arg = (unsigned long)compat_ptr(arg); + if (copy_from_user(compat_layerInfo, (void __user *)arg, sizeof(*compat_layerInfo))) { + MTKFB_LOG("[FB Driver]: copy_from_user failed! line:%d\n", + __LINE__); + ret = -EFAULT; + } else { + + compat_convert(compat_layerInfo, &layerInfo); + + /* in early suspend mode ,will not update buffer index, info SF by return value */ + if (primary_display_is_sleepd()) { + pr_debug("[FB Driver] error, set overlay in early suspend ,skip!\n"); + kfree(compat_layerInfo); + return MTKFB_ERROR_IS_EARLY_SUSPEND; + } + memset((void *)&session_input, 0, sizeof(session_input)); + if (layerInfo.layer_id >= TOTAL_OVL_LAYER_NUM) { + DISPAEE("COMPAT_MTKFB_SET_OVERLAY_LAYER, layer_id invalid:%d\n", + layerInfo.layer_id); + } else { + input = &session_input.config[session_input.config_layer_num++]; + _convert_fb_layer_to_disp_input(&layerInfo, input); + } + primary_display_config_input_multiple(&session_input); + /* primary_display_trigger(1, NULL, 0); */ + } + kfree(compat_layerInfo); + } + break; + + case COMPAT_MTKFB_SET_VIDEO_LAYERS: + { + struct compat_fb_overlay_layer *compat_layerInfo; + int compat_layerInfo_size = sizeof(struct compat_fb_overlay_layer) * VIDEO_LAYER_COUNT; + + compat_layerInfo = kmalloc(compat_layerInfo_size, GFP_KERNEL); + if (!compat_layerInfo) + return -ENOMEM; + + MTKFB_LOG(" mtkfb_compat_ioctl():MTKFB_SET_VIDEO_LAYERS\n"); + + if (copy_from_user(compat_layerInfo, (void __user *)arg, compat_layerInfo_size)) { + MTKFB_LOG("[FB Driver]: copy_from_user failed! line:%d\n", __LINE__); + ret = -EFAULT; + } else { + int32_t i; + /* mutex_lock(&OverlaySettingMutex); */ + disp_input_config *input; + + memset((void *)&session_input, 0, sizeof(session_input)); + + for (i = 0; i < VIDEO_LAYER_COUNT; ++i) { + compat_convert(&compat_layerInfo[i], &layerInfo); + if (layerInfo.layer_id >= TOTAL_OVL_LAYER_NUM) { + DISPAEE("COMPAT_MTKFB_SET_VIDEO_LAYERS, layer_id invalid=%d\n", + layerInfo.layer_id); + continue; + } + input = + &session_input.config[session_input.config_layer_num++]; + _convert_fb_layer_to_disp_input(&layerInfo, input); + } + /* is_ipoh_bootup = false; */ + /* atomic_set(&OverlaySettingDirtyFlag, 1); */ + /* atomic_set(&OverlaySettingApplied, 0); */ + /* mutex_unlock(&OverlaySettingMutex); */ + /* MMProfileLogStructure(MTKFB_MMP_Events.SetOverlayLayers, MMProfileFlagEnd, + layerInfo, struct mmp_fb_overlay_layers); */ + primary_display_config_input_multiple(&session_input); + /* primary_display_trigger(1, NULL, 0); */ + } + kfree(compat_layerInfo); + } + break; + case COMPAT_MTKFB_AEE_LAYER_EXIST: + { + int dal_en = is_DAL_Enabled(); + compat_ulong_t __user *data32; + + data32 = compat_ptr(arg); + if (put_user(dal_en, data32)) { + pr_err("MTKFB_GET_POWERSTATE failed\n"); + ret = -EFAULT; + } + break; + } + case COMPAT_MTKFB_FACTORY_AUTO_TEST: + { + compat_ulong_t __user *data32; + unsigned long result = 0; + + result = mtkfb_fm_auto_test(); + DISPMSG("factory mode: lcm auto test\n"); + data32 = compat_ptr(arg); + if (put_user(result, data32)) { + pr_err("MTKFB_GET_POWERSTATE failed\n"); + ret = -EFAULT; + } + break; + /*return copy_to_user(argp, &result, sizeof(result)) ? -EFAULT : 0;*/ + } + case COMPAT_MTKFB_META_SHOW_BOOTLOGO: + { + arg = (unsigned long)compat_ptr(arg); + ret = mtkfb_ioctl(info, MTKFB_META_SHOW_BOOTLOGO, arg); + break; + } + default: + /* NOTHING DIFFERENCE with standard ioctl calling */ + arg = (unsigned long)compat_ptr(arg); + ret = mtkfb_ioctl(info, cmd, arg); + break; + } + + return ret; +} +#endif + +static int mtkfb_pan_display_proxy(struct fb_var_screeninfo *var, struct fb_info *info) +{ +#ifdef CONFIG_MTPROF_APPLAUNCH /* eng enable, user disable */ + LOG_PRINT(ANDROID_LOG_INFO, "AppLaunch", "mtkfb_pan_display_proxy.\n"); +#endif + return mtkfb_pan_display_impl(var, info); +} + +/* Callback table for the frame buffer framework. Some of these pointers + * will be changed according to the current setting of fb_info->accel_flags. + */ +static struct fb_ops mtkfb_ops = { + .owner = THIS_MODULE, + .fb_open = mtkfb_open, + .fb_release = mtkfb_release, + .fb_setcolreg = mtkfb_setcolreg, + .fb_pan_display = mtkfb_pan_display_proxy, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_cursor = mtkfb_soft_cursor, + .fb_check_var = mtkfb_check_var, + .fb_set_par = mtkfb_set_par, + .fb_ioctl = mtkfb_ioctl, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = mtkfb_compat_ioctl, +#endif +#if defined(CONFIG_PM_AUTOSLEEP) + .fb_blank = mtkfb_blank, +#endif +}; + +/* + * --------------------------------------------------------------------------- + * Sysfs interface + * --------------------------------------------------------------------------- + */ + +static int mtkfb_register_sysfs(struct mtkfb_device *fbdev) +{ + + return 0; +} + +static void mtkfb_unregister_sysfs(struct mtkfb_device *fbdev) +{ +} + +/* + * --------------------------------------------------------------------------- + * LDM callbacks + * --------------------------------------------------------------------------- + */ +/* Initialize system fb_info object and set the default video mode. + * The frame buffer memory already allocated by lcddma_init + */ +static int mtkfb_fbinfo_init(struct fb_info *info) +{ + struct mtkfb_device *fbdev = (struct mtkfb_device *)info->par; + struct fb_var_screeninfo var; + int r = 0; + + DISPFUNC(); + + BUG_ON(!fbdev->fb_va_base); + info->fbops = &mtkfb_ops; + info->flags = FBINFO_FLAG_DEFAULT; + info->screen_base = (char *)fbdev->fb_va_base; + info->screen_size = fbdev->fb_size_in_byte; + info->pseudo_palette = fbdev->pseudo_palette; + + r = fb_alloc_cmap(&info->cmap, 32, 0); + if (r != 0) + DISPERR("unable to allocate color map memory\n"); + + /* setup the initial video mode (RGB565) */ + + memset(&var, 0, sizeof(var)); + + var.xres = MTK_FB_XRES; + var.yres = MTK_FB_YRES; + var.xres_virtual = MTK_FB_XRESV; + var.yres_virtual = MTK_FB_YRESV; + pr_debug("mtkfb_fbinfo_init var.xres=%d,var.yres=%d,var.xres_virtual=%d,var.yres_virtual=%d\n", + var.xres, var.yres, var.xres_virtual, var.yres_virtual); + /* use 32 bit framebuffer as default */ + var.bits_per_pixel = 32; + + var.transp.offset = 24; + var.red.length = 8; +#if 0 + var.red.offset = 16; + var.red.length = 8; + var.green.offset = 8; + var.green.length = 8; + var.blue.offset = 0; + var.blue.length = 8; +#else + var.red.offset = 0; + var.red.length = 8; + var.green.offset = 8; + var.green.length = 8; + var.blue.offset = 16; + var.blue.length = 8; +#endif + + var.width = DISP_GetActiveWidth(); + var.height = DISP_GetActiveHeight(); + + var.activate = FB_ACTIVATE_NOW; + + r = mtkfb_check_var(&var, info); + if (r != 0) + DISPERR("failed to mtkfb_check_var\n"); + + info->var = var; + + r = mtkfb_set_par(info); + if (r != 0) + DISPERR("failed to mtkfb_set_par\n"); + + MSG_FUNC_LEAVE(); + return r; +} + +/* Release the fb_info object */ +static void mtkfb_fbinfo_cleanup(struct mtkfb_device *fbdev) +{ + MSG_FUNC_ENTER(); + + fb_dealloc_cmap(&fbdev->fb_info->cmap); + + MSG_FUNC_LEAVE(); +} +/* fast memset for hw test tool */ +void DISP_memset_io(volatile void __iomem *dst, int c, size_t count) +{ + u32 qc = (u8)c; + + qc |= qc << 8; + qc |= qc << 16; + + while (count && !IS_ALIGNED((unsigned long)dst, 8)) { + __raw_writeb(c, dst); + dst++; + count--; + } + while (count >= 4) { + __raw_writel(qc, dst); + dst += 4; + count -= 4; + } + + while (count) { + __raw_writeb(c, dst); + dst++; + count--; + } +} +/* Init frame buffer content as 3 R/G/B color bars for debug */ +static int init_framebuffer(struct fb_info *info) +{ + unsigned int size; + + void *buffer = info->screen_base + info->var.yoffset * info->fix.line_length; + + /* clean whole frame buffer as black */ + /*memset_io(buffer, 0, info->screen_size);*/ + + size = info->var.xres_virtual * info->var.yres * info->var.bits_per_pixel/8; + DISP_memset_io(buffer, 0, size); + return 0; +} + + +/* Free driver resources. Can be called to rollback an aborted initialization + * sequence. + */ +static void mtkfb_free_resources(struct mtkfb_device *fbdev, int state) +{ + int r = 0; + + switch (state) { + case MTKFB_ACTIVE: + r = unregister_framebuffer(fbdev->fb_info); + ASSERT(0 == r); + /* lint -fallthrough */ + case 5: + mtkfb_unregister_sysfs(fbdev); + /* lint -fallthrough */ + case 4: + mtkfb_fbinfo_cleanup(fbdev); + /* lint -fallthrough */ + case 3: + /* DISP_CHECK_RET(DISP_Deinit()); */ + /* lint -fallthrough */ + case 2: +#ifndef CONFIG_MTK_FPGA + dma_free_coherent(0, fbdev->fb_size_in_byte, fbdev->fb_va_base, fbdev->fb_pa_base); +#endif + /* lint -fallthrough */ + case 1: + dev_set_drvdata(fbdev->dev, NULL); + framebuffer_release(fbdev->fb_info); + /* lint -fallthrough */ + case 0: + /* nothing to free */ + break; + default: + BUG(); + } +} + +void disp_get_fb_address(unsigned long *fbVirAddr, unsigned long *fbPhysAddr) +{ + struct mtkfb_device *fbdev = (struct mtkfb_device *)mtkfb_fbi->par; + + *fbVirAddr = + (unsigned long)fbdev->fb_va_base + mtkfb_fbi->var.yoffset * mtkfb_fbi->fix.line_length; + *fbPhysAddr = + (unsigned long)fbdev->fb_pa_base + mtkfb_fbi->var.yoffset * mtkfb_fbi->fix.line_length; +} + +#if 0 +static int mtkfb_fbinfo_modify(struct fb_info *info) +{ + struct fb_var_screeninfo var; + int r = 0; + + memcpy(&var, &(info->var), sizeof(var)); + var.activate = FB_ACTIVATE_NOW; + var.bits_per_pixel = 32; + var.transp.offset = 24; + var.transp.length = 8; + var.red.offset = 16; + var.red.length = 8; + var.green.offset = 8; + var.green.length = 8; + var.blue.offset = 0; + var.blue.length = 8; + var.yoffset = var.yres; + + r = mtkfb_check_var(&var, info); + if (r != 0) + PRNERR("failed to mtkfb_check_var\n"); + + info->var = var; + + r = mtkfb_set_par(info); + if (r != 0) + PRNERR("failed to mtkfb_set_par\n"); + + return r; +} +#endif +#if 0 +static void _mtkfb_draw_point(unsigned int addr, unsigned int x, unsigned int y, unsigned int color) +{ + +} +#endif +static void _mtkfb_draw_block(unsigned long addr, unsigned int x, unsigned int y, unsigned int w, + unsigned int h, unsigned int color) +{ + int i = 0; + int j = 0; + unsigned long start_addr; + + start_addr = addr + MTK_FB_XRESV * 4 * y + x * 4; + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) + mt_reg_sync_writel(color, (start_addr + i * 4 + j * MTK_FB_XRESV * 4)); + } +} + +char *mtkfb_find_lcm_driver(void) +{ + _parse_tag_videolfb(); + DISPMSG("%s, %s\n", __func__, mtkfb_lcm_name); +/* Vanzo:maxiaojun on: Mon, 26 Aug 2013 17:04:18 +0800 + * board device name support. + */ +#ifdef VANZO_DEVICE_NAME_SUPPORT + { + extern void v_set_dev_name(int id, char *name); + v_set_dev_name(1, mtkfb_lcm_name); + } +#endif +// End of Vanzo:maxiaojun + + return mtkfb_lcm_name; +} + + +static int _mtkfb_internal_test(unsigned long va, unsigned int w, unsigned int h) +{ + /* this is for debug, used in bring up day */ + unsigned int i = 0; + unsigned int color = 0; + int _internal_test_block_size = 120; + + for (i = 0; i < w * h / _internal_test_block_size / _internal_test_block_size; i++) { + color = (i & 0x1) * 0xff; + /* color += ((i&0x2)>>1)*0xff00; */ + /* color += ((i&0x4)>>2)*0xff0000; */ + color += 0xff000000U; + _mtkfb_draw_block(va, + i % (w / _internal_test_block_size) * _internal_test_block_size, + i / (w / _internal_test_block_size) * _internal_test_block_size, + _internal_test_block_size, _internal_test_block_size, color); + } + /* unsigned long ttt = get_current_time_us(); */ + /* for(i=0;i<1000;i++) */ + + primary_display_trigger(1, NULL, 0); + + /* ttt = get_current_time_us()-ttt; */ + /*return 0;*/ + + _internal_test_block_size = 20; + for (i = 0; i < w * h / _internal_test_block_size / _internal_test_block_size; i++) { + color = (i & 0x1) * 0xff; + color += ((i & 0x2) >> 1) * 0xff00; + color += ((i & 0x4) >> 2) * 0xff0000; + color += 0xff000000U; + _mtkfb_draw_block(va, + i % (w / _internal_test_block_size) * _internal_test_block_size, + i / (w / _internal_test_block_size) * _internal_test_block_size, + _internal_test_block_size, _internal_test_block_size, color); + } + primary_display_trigger(1, NULL, 0); + _internal_test_block_size = 30; + for (i = 0; i < w * h / _internal_test_block_size / _internal_test_block_size; i++) { + color = (i & 0x1) * 0xff; + color += ((i & 0x2) >> 1) * 0xff00; + color += ((i & 0x4) >> 2) * 0xff0000; + color += 0xff000000U; + _mtkfb_draw_block(va, + i % (w / _internal_test_block_size) * _internal_test_block_size, + i / (w / _internal_test_block_size) * _internal_test_block_size, + _internal_test_block_size, _internal_test_block_size, color); + } + primary_display_trigger(1, NULL, 0); + + return 0; +} + + +#ifdef CONFIG_OF +struct tag_videolfb { + u64 fb_base; + u32 islcmfound; + u32 fps; + u32 vram; + char lcmname[1]; /* this is the minimum size */ +}; +unsigned int islcmconnected = 0; +unsigned int is_lcm_inited = 0; +unsigned int vramsize = 0; +phys_addr_t fb_base = 0; +static int is_videofb_parse_done; +static int fb_early_init_dt_get_chosen(unsigned long node, const char *uname, int depth, + void *p_ret_node) +{ + if (depth != 1 || (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; + + *(unsigned long *)p_ret_node = node; + return 1; +} + +int __parse_tag_videolfb_extra(unsigned long node) +{ + uint32_t *prop; + int size = 0; + u32 fb_base_h, fb_base_l; + + prop = (uint32_t *)of_get_flat_dt_prop(node, "atag,videolfb-fb_base_h", NULL); + if (!prop) + return -1; + fb_base_h = of_read_number(prop, 1); + + prop = (uint32_t *)of_get_flat_dt_prop(node, "atag,videolfb-fb_base_l", NULL); + if (!prop) + return -1; + fb_base_l = of_read_number(prop, 1); + + fb_base = ((u64) fb_base_h << 32) | (u64) fb_base_l; + + prop = (uint32_t *)of_get_flat_dt_prop(node, "atag,videolfb-islcmfound", NULL); + if (!prop) + return -1; + islcmconnected = of_read_number(prop, 1); + + prop = (uint32_t *)of_get_flat_dt_prop(node, "atag,videolfb-islcm_inited", NULL); + if (!prop) + is_lcm_inited = 1; + else + is_lcm_inited = of_read_number(prop, 1); + + prop = (uint32_t *)of_get_flat_dt_prop(node, "atag,videolfb-fps", NULL); + if (!prop) + return -1; + lcd_fps = of_read_number(prop, 1); + if (0 == lcd_fps) + lcd_fps = 6000; + + prop = (uint32_t *)of_get_flat_dt_prop(node, "atag,videolfb-vramSize", NULL); + if (!prop) + return -1; + vramsize = of_read_number(prop, 1); + + prop = (uint32_t *)of_get_flat_dt_prop(node, "atag,videolfb-fb_base_l", NULL); + if (!prop) + return -1; + fb_base_l = of_read_number(prop, 1); + + prop = (uint32_t *)of_get_flat_dt_prop(node, "atag,videolfb-lcmname", &size); + if (!prop) + return -1; + if (size >= sizeof(mtkfb_lcm_name)) { + DISPMSG("%s: error to get lcmname size=%d\n", __func__, size); + return -1; + } + memset((void *)mtkfb_lcm_name, 0, sizeof(mtkfb_lcm_name)); + strncpy((char *)mtkfb_lcm_name, (char *)prop, sizeof(mtkfb_lcm_name)); + mtkfb_lcm_name[size] = '\0'; + pr_debug("__parse_tag_videolfb_extra done\n"); + return 0; +} + +int __parse_tag_videolfb(unsigned long node) +{ + struct tag_videolfb *videolfb_tag = NULL; + + videolfb_tag = (struct tag_videolfb *)of_get_flat_dt_prop(node, "atag,videolfb", NULL); + if (videolfb_tag) { + memset((void *)mtkfb_lcm_name, 0, sizeof(mtkfb_lcm_name)); + strcpy((char *)mtkfb_lcm_name, videolfb_tag->lcmname); + mtkfb_lcm_name[strlen(videolfb_tag->lcmname)] = '\0'; + + lcd_fps = videolfb_tag->fps; + if (0 == lcd_fps) + lcd_fps = 6000; + + islcmconnected = videolfb_tag->islcmfound; + vramsize = videolfb_tag->vram; + fb_base = videolfb_tag->fb_base; + is_lcm_inited = 1; + return 0; + } + DISPMSG("[DT][videolfb] videolfb_tag not found\n"); + return -1; +} + + +static int _parse_tag_videolfb(void) +{ + int ret; + unsigned long node = 0; + + DISPMSG("[DT][videolfb]isvideofb_parse_done = %d\n", is_videofb_parse_done); + + if (is_videofb_parse_done) + return 0; + + ret = of_scan_flat_dt(fb_early_init_dt_get_chosen, &node); + if (node) { + ret = __parse_tag_videolfb(node); + if (!ret) + goto found; + ret = __parse_tag_videolfb_extra(node); + if (!ret) + goto found; + } else { + DISPMSG("[DT][videolfb] of_chosen not found\n"); + } + return -1; + +found: + is_videofb_parse_done = 1; + DISPMSG("[DT][videolfb] islcmfound = %d\n", islcmconnected); + DISPMSG("[DT][videolfb] is_lcm_inited = %d\n", is_lcm_inited); + DISPMSG("[DT][videolfb] fps = %d\n", lcd_fps); + DISPMSG("[DT][videolfb] fb_base = 0x%pa\n", &fb_base); + DISPMSG("[DT][videolfb] vram = %d\n", vramsize); + DISPMSG("[DT][videolfb] lcmname = %s\n", mtkfb_lcm_name); + return 0; +} + +phys_addr_t mtkfb_get_fb_base(void) +{ + _parse_tag_videolfb(); + return fb_base; +} +EXPORT_SYMBOL(mtkfb_get_fb_base); + +size_t mtkfb_get_fb_size(void) +{ + _parse_tag_videolfb(); + return vramsize; +} +EXPORT_SYMBOL(mtkfb_get_fb_size); +#endif + +/* used when early porting, test pan display*/ +int pan_display_test(int frame_num, int bpp) +{ + int i, j; + int Bpp = bpp / 8; + unsigned char *fb_va; + unsigned long fb_pa; + unsigned int fb_size; + int w, h, fb_h; + int yoffset_max; + int yoffset; + + mtkfb_fbi->var.yoffset = 0; + disp_get_fb_address((unsigned long *)&fb_va, &fb_pa); + fb_size = mtkfb_fbi->fix.smem_len; + w = mtkfb_fbi->var.xres; + h = mtkfb_fbi->var.yres; + fb_h = fb_size / (w * Bpp) - 10; + + DISPMSG("%s: frame_num=%d,bpp=%d, w=%d,h=%d,fb_h=%d\n", + __func__, frame_num, bpp, w, h, fb_h); + + for (i = 0; i < fb_h; i++) + for (j = 0; j < w; j++) { + int x = (i * w + j) * Bpp; + + fb_va[x++] = (i + j) % 256; + fb_va[x++] = (i + j) % 256; + fb_va[x++] = (i + j) % 256; + if (Bpp == 4) + fb_va[x++] = 255; + } + + mtkfb_fbi->var.bits_per_pixel = bpp; + + yoffset_max = fb_h - h; + yoffset = 0; + + for (i = 0; i < frame_num; i++, yoffset += 10) { + + if (yoffset >= yoffset_max) + yoffset = 0; + + mtkfb_fbi->var.xoffset = 0; + mtkfb_fbi->var.yoffset = yoffset; + mtkfb_pan_display_impl(&mtkfb_fbi->var, mtkfb_fbi); + } + + return 0; +} + +/* #define FPGA_DEBUG_PAN */ +#ifdef FPGA_DEBUG_PAN +static struct task_struct *test_task; +static int update_test_kthread(void *data) +{ + /* struct sched_param param = { .sched_priority = RTPM_PRIO_SCRN_UPDATE }; */ + /* sched_setscheduler(current, SCHED_RR, ¶m); */ + unsigned int i = 0, j = 0; + unsigned long fb_va; + unsigned long fb_pa; + unsigned int *fb_start; + unsigned int fbsize = primary_display_get_height() * primary_display_get_width(); + + mtkfb_fbi->var.yoffset = 0; + disp_get_fb_address(&fb_va, &fb_pa); + + for (;;) { + + if (kthread_should_stop()) + break; + msleep(1000); /* 2s */ + pr_debug("update test thread work,offset = %d\n", i); + + mtkfb_fbi->var.yoffset = 0; + disp_get_fb_address(&fb_va, &fb_pa); + fb_start = (unsigned int *)fb_va; + for (j = 0; j < fbsize; j++) { + *fb_start = (0x55) << ((i % 4) * 8); + fb_start++; + } + mtkfb_pan_display_impl(&mtkfb_fbi->var, mtkfb_fbi); + i++; + } + + pr_debug("exit update_test_kthread()\n"); + return 0; +} +#endif + +static int mtkfb_probe(struct device *dev) +{ + struct mtkfb_device *fbdev = NULL; + struct fb_info *fbi; + struct platform_device *pdev; + int init_state; + int r = 0; + long dts_gpio_state = 0; + + pr_debug("mtkfb_probe\n"); + + _parse_tag_videolfb(); + + init_state = 0; + pdev = to_platform_device(dev); + /* repo call DTS gpio module, if not necessary, invoke nothing */ + dts_gpio_state = disp_dts_gpio_init_repo(pdev); + if (dts_gpio_state != 0) + dev_err(&pdev->dev, "retrieve GPIO DTS failed."); + + fbi = framebuffer_alloc(sizeof(struct mtkfb_device), dev); + if (!fbi) { + DISPERR("unable to allocate memory for device info\n"); + r = -ENOMEM; + goto cleanup; + } + mtkfb_fbi = fbi; + + fbdev = (struct mtkfb_device *)fbi->par; + fbdev->fb_info = fbi; + fbdev->dev = dev; + dev_set_drvdata(dev, fbdev); + + DISPMSG("mtkfb_probe: fb_pa = 0x%pa\n", &fb_base); + + disp_hal_allocate_framebuffer(fb_base, (fb_base + vramsize - 1), + (unsigned long *)&fbdev->fb_va_base, &fb_pa); + fbdev->fb_pa_base = fb_base; + + primary_display_set_frame_buffer_address((unsigned long)fbdev->fb_va_base, fb_pa); + primary_display_init(mtkfb_find_lcm_driver(), lcd_fps, is_lcm_inited); + + init_state++; /* 1 */ + MTK_FB_XRES = DISP_GetScreenWidth(); + MTK_FB_YRES = DISP_GetScreenHeight(); + fb_xres_update = MTK_FB_XRES; + fb_yres_update = MTK_FB_YRES; + + MTK_FB_BPP = DISP_GetScreenBpp(); + MTK_FB_PAGES = DISP_GetPages(); + DISPMSG + ("MTK_FB_XRES=%d, MTKFB_YRES=%d, MTKFB_BPP=%d, MTK_FB_PAGES=%d, MTKFB_LINE=%d, MTKFB_SIZEV=%d\n", + MTK_FB_XRES, MTK_FB_YRES, MTK_FB_BPP, MTK_FB_PAGES, MTK_FB_LINE, MTK_FB_SIZEV); + fbdev->fb_size_in_byte = MTK_FB_SIZEV; + + /* Allocate and initialize video frame buffer */ + DISPMSG("[FB Driver] fbdev->fb_pa_base = 0x%pa, fbdev->fb_va_base = 0x%p\n", + &(fbdev->fb_pa_base), fbdev->fb_va_base); + + if (!fbdev->fb_va_base) { + DISPERR("unable to allocate memory for frame buffer\n"); + r = -ENOMEM; + goto cleanup; + } + init_state++; /* 2 */ + + r = mtkfb_fbinfo_init(fbi); + if (r) { + DISPERR("mtkfb_fbinfo_init fail, r = %d\n", r); + goto cleanup; + } + init_state++; /* 4 */ + DISPMSG("\nmtkfb_fbinfo_init done\n"); + + if (disp_helper_get_stage() == DISP_HELPER_STAGE_NORMAL) { + /* dal_init should after mtkfb_fbinfo_init, otherwise layer 3 will show dal background color */ + DAL_STATUS ret; + unsigned long fbVA = (unsigned long)fbdev->fb_va_base; + unsigned long fbPA = fb_pa; + /* / DAL init here */ + fbVA += DISP_GetFBRamSize(); + fbPA += DISP_GetFBRamSize(); + ret = DAL_Init(fbVA, fbPA); + } + + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) + _mtkfb_internal_test((unsigned long)fbdev->fb_va_base, MTK_FB_XRES, MTK_FB_YRES); + + + r = mtkfb_register_sysfs(fbdev); + if (r) { + DISPERR("mtkfb_register_sysfs fail, r = %d\n", r); + goto cleanup; + } + init_state++; /* 5 */ + + r = register_framebuffer(fbi); + if (r != 0) { + DISPERR("register_framebuffer failed\n"); + goto cleanup; + } +#ifdef FPGA_DEBUG_PAN + test_task = kthread_create(update_test_kthread, NULL, "update_test_kthread"); + wake_up_process(test_task); +#endif + + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) + primary_display_diagnose(); + + + /*this function will get fb_heap base address to ion for management frame buffer */ + ion_drv_create_FB_heap(mtkfb_get_fb_base(), mtkfb_get_fb_size()); + + fbdev->state = MTKFB_ACTIVE; + + MSG_FUNC_LEAVE(); + return 0; + +cleanup: + mtkfb_free_resources(fbdev, init_state); + + pr_debug("mtkfb_probe end\n"); + return r; +} + +/* Called when the device is being detached from the driver */ +static int mtkfb_remove(struct device *dev) +{ + struct mtkfb_device *fbdev = dev_get_drvdata(dev); + enum mtkfb_state saved_state = fbdev->state; + + MSG_FUNC_ENTER(); + /* FIXME: wait till completion of pending events */ + + fbdev->state = MTKFB_DISABLED; + mtkfb_free_resources(fbdev, saved_state); + + MSG_FUNC_LEAVE(); + return 0; +} + +/* PM suspend */ +static int mtkfb_suspend(struct device *pdev, pm_message_t mesg) +{ + MSG_FUNC_ENTER(); + MTKFB_LOG("[FB Driver] mtkfb_suspend(): 0x%x\n", mesg.event); +/* ovl2mem_wait_done();*/ + + MSG_FUNC_LEAVE(); + return 0; +} + +bool mtkfb_is_suspend(void) +{ + return primary_display_is_sleepd(); +} +EXPORT_SYMBOL(mtkfb_is_suspend); + +int mtkfb_ipoh_restore(struct notifier_block *nb, unsigned long val, void *ign) +{ + switch (val) { + case PM_HIBERNATION_PREPARE: + DISPMSG("[FB Driver] mtkfb_ipoh_restore PM_HIBERNATION_PREPARE\n"); + return NOTIFY_DONE; + case PM_RESTORE_PREPARE: + primary_display_ipoh_restore(); + DISPMSG("[FB Driver] mtkfb_ipoh_restore PM_RESTORE_PREPARE\n"); + return NOTIFY_DONE; + case PM_POST_HIBERNATION: + DISPMSG("[FB Driver] mtkfb_ipoh_restore PM_POST_HIBERNATION\n"); + return NOTIFY_DONE; + } + return NOTIFY_OK; +} + +int mtkfb_ipo_init(void) +{ + pm_nb.notifier_call = mtkfb_ipoh_restore; + pm_nb.priority = 0; + register_pm_notifier(&pm_nb); + return 0; +} + +static void mtkfb_shutdown(struct device *pdev) +{ + MTKFB_LOG("[FB Driver] mtkfb_shutdown()\n"); + /* mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, LED_OFF); */ + if (!lcd_fps) + msleep(30); + else + msleep(2 * 100000 / lcd_fps); /* Delay 2 frames. */ + + if (primary_display_is_sleepd()) { + MTKFB_LOG("mtkfb has been power off\n"); + return; + } + primary_display_suspend(); + MTKFB_LOG("[FB Driver] leave mtkfb_shutdown\n"); +} + +void mtkfb_clear_lcm(void) +{ +} +/* +#ifdef CONFIG_HAS_EARLYSUSPEND +static void mtkfb_early_suspend(struct early_suspend *h) +{ + int ret = 0; + + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) + return; + + DISPMSG("[FB Driver] enter early_suspend\n"); + + + msleep(30); + + ret = primary_display_suspend(); + + if (ret < 0) { + DISPERR("primary display suspend failed\n"); + return; + } + + DISPMSG("[FB Driver] leave early_suspend\n"); + + return; +} +#endif +*/ +/* PM resume */ +static int mtkfb_resume(struct device *pdev) +{ + MSG_FUNC_ENTER(); + MTKFB_LOG("[FB Driver] mtkfb_resume()\n"); + MSG_FUNC_LEAVE(); + return 0; +} +/* +#ifdef CONFIG_HAS_EARLYSUSPEND +static void mtkfb_late_resume(struct early_suspend *h) +{ + int ret = 0; + + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) + return; + + DISPMSG("[FB Driver] enter late_resume\n"); + + ret = primary_display_resume(); + + if (ret) { + DISPERR("primary display resume failed\n"); + return; + } + + DISPMSG("[FB Driver] leave late_resume\n"); + +#endif +*/ +/*---------------------------------------------------------------------------*/ +#ifdef CONFIG_PM +/*---------------------------------------------------------------------------*/ +int mtkfb_pm_suspend(struct device *device) +{ + /* pr_debug("calling %s()\n", __func__); */ + + struct platform_device *pdev = to_platform_device(device); + + BUG_ON(pdev == NULL); + + return mtkfb_suspend((struct device *)pdev, PMSG_SUSPEND); +} + +int mtkfb_pm_resume(struct device *device) +{ + /* pr_debug("calling %s()\n", __func__); */ + + struct platform_device *pdev = to_platform_device(device); + + BUG_ON(pdev == NULL); + + return mtkfb_resume((struct device *)pdev); +} + +int mtkfb_pm_freeze(struct device *device) +{ + primary_display_esd_check_enable(0); + return 0; +} + +int mtkfb_pm_restore_noirq(struct device *device) +{ + /* disphal_pm_restore_noirq(device); */ + DISPMSG("%s: %d\n", __func__, __LINE__); + is_ipoh_bootup = true; +#if 0 + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) + ddp_clk_prepare_enable(MM_VENCPLL); + ddp_clk_prepare_enable(DISP_MTCMOS_CLK); + ddp_clk_prepare_enable(DISP0_SMI_COMMON); + ddp_clk_prepare_enable(DISP0_SMI_LARB0); +#else + dpmgr_path_power_on(primary_get_dpmgr_handle(), CMDQ_DISABLE); +#endif + DISPMSG("%s: %d\n", __func__, __LINE__); + return 0; + +} + +/*---------------------------------------------------------------------------*/ +#else /*CONFIG_PM */ +/*---------------------------------------------------------------------------*/ +#define mtkfb_pm_suspend NULL +#define mtkfb_pm_resume NULL +#define mtkfb_pm_restore_noirq NULL +#define mtkfb_pm_freeze NULL +/*---------------------------------------------------------------------------*/ +#endif /*CONFIG_PM */ +/*---------------------------------------------------------------------------*/ +static const struct of_device_id mtkfb_of_ids[] = { + {.compatible = "mediatek,MTKFB",}, + {} +}; + +static const struct dev_pm_ops mtkfb_pm_ops = { + .suspend = mtkfb_pm_suspend, + .resume = mtkfb_pm_resume, + .freeze = mtkfb_pm_freeze, + .thaw = mtkfb_pm_resume, + .poweroff = mtkfb_pm_suspend, + .restore = mtkfb_pm_resume, + .restore_noirq = mtkfb_pm_restore_noirq, +}; + +static struct platform_driver mtkfb_driver = { + .driver = { + .name = MTKFB_DRIVER, +#ifdef CONFIG_PM + .pm = &mtkfb_pm_ops, +#endif + .bus = &platform_bus_type, + .probe = mtkfb_probe, + .remove = mtkfb_remove, + .suspend = mtkfb_suspend, + .resume = mtkfb_resume, + .shutdown = mtkfb_shutdown, + .of_match_table = mtkfb_of_ids, + }, +}; + +#if 0 +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct early_suspend mtkfb_early_suspend_handler = { + .level = EARLY_SUSPEND_LEVEL_DISABLE_FB, + .suspend = mtkfb_early_suspend, + .resume = mtkfb_late_resume, +}; +#endif +#endif + + +int mtkfb_get_debug_state(char *stringbuf, int buf_len) +{ + int len = 0; + struct mtkfb_device *fbdev = (struct mtkfb_device *)mtkfb_fbi->par; + + unsigned long va = (unsigned long)fbdev->fb_va_base; + unsigned long mva = (unsigned long)fbdev->fb_pa_base; + unsigned long pa = fbdev->fb_pa_base; + unsigned int resv_size = vramsize; + + len += + scnprintf(stringbuf + len, buf_len - len, + "|--------------------------------------------------------------------------------------|\n"); + len += scnprintf(stringbuf + len, buf_len - len, "********MTKFB Driver General Information********\n"); + len += + scnprintf(stringbuf + len, buf_len - len, + "|Framebuffer VA:0x%lx, PA:0x%lx, MVA:0x%lx, Reserved Size:0x%08x|%d\n", va, + pa, mva, resv_size, resv_size); + len += + scnprintf(stringbuf + len, buf_len - len, "|xoffset=%d, yoffset=%d\n", + mtkfb_fbi->var.xoffset, mtkfb_fbi->var.yoffset); + len += + scnprintf(stringbuf + len, buf_len - len, "|framebuffer line alignment(for gpu)=%d\n", + MTK_FB_ALIGNMENT); + len += + scnprintf(stringbuf + len, buf_len - len, + "|xres=%d, yres=%d,bpp=%d,pages=%d,linebytes=%d,total size=%d\n", MTK_FB_XRES, + MTK_FB_YRES, MTK_FB_BPP, MTK_FB_PAGES, MTK_FB_LINE, MTK_FB_SIZEV); + /* use extern in case DAL_LOCK is hold, then can't get any debug info */ + len += + scnprintf(stringbuf + len, buf_len - len, "|AEE Layer is %s\n", + is_DAL_Enabled() ? "enabled" : "disabled"); + + return len; +} + + +/* Register both the driver and the device */ +int __init mtkfb_init(void) +{ + int r = 0; + + MSG_FUNC_ENTER(); + DISPMSG("mtkfb_init Enter\n"); + if (platform_driver_register(&mtkfb_driver)) { + PRNERR("failed to register mtkfb driver\n"); + r = -ENODEV; + goto exit; + } +#if 0 +#ifdef CONFIG_HAS_EARLYSUSPEND + register_early_suspend(&mtkfb_early_suspend_handler); +#endif +#endif + PanelMaster_Init(); + DBG_Init(); + mtkfb_ipo_init(); +exit: + MSG_FUNC_LEAVE(); + DISPMSG("mtkfb_init LEAVE\n"); + return r; +} + + +static void __exit mtkfb_cleanup(void) +{ + MSG_FUNC_ENTER(); + + platform_driver_unregister(&mtkfb_driver); +#if 0 +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&mtkfb_early_suspend_handler); +#endif +#endif + /*PanelMaster_Deinit();*/ + DBG_Deinit(); + + MSG_FUNC_LEAVE(); +} + + +module_init(mtkfb_init); +module_exit(mtkfb_cleanup); + +MODULE_DESCRIPTION("MEDIATEK framebuffer driver"); +MODULE_AUTHOR("Xuecheng Zhang "); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/video/mt6755/mtkfb_console.c b/drivers/misc/mediatek/video/mt6755/mtkfb_console.c new file mode 100644 index 0000000000000000000000000000000000000000..19814a4011f6620fdfadc200964d23e708f20229 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtkfb_console.c @@ -0,0 +1,559 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include + +#include +#include +#include "mtkfb_console.h" +#include "ddp_hal.h" + +/* --------------------------------------------------------------------------- */ + +#define MFC_WIDTH (ctxt->fb_width) +#define MFC_HEIGHT (ctxt->fb_height) +#define MFC_BPP (ctxt->fb_bpp) +#define MFC_PITCH (ctxt->fb_pitch) +/* #define MFC_PITCH (MFC_WIDTH * MFC_BPP) */ + +#define MFC_FG_COLOR (ctxt->fg_color) +#define MFC_BG_COLOR (ctxt->bg_color) + +#define MFC_FONT font_vga_8x16 +#define MFC_FONT_WIDTH (MFC_FONT.width) +#define MFC_FONT_HEIGHT (MFC_FONT.height) +#define MFC_FONT_DATA (MFC_FONT.data) + +#define MFC_ROW_SIZE (MFC_FONT_HEIGHT * MFC_PITCH) +#define MFC_ROW_FIRST ((uint8_t *)(ctxt->fb_addr)) +#define MFC_ROW_SECOND (MFC_ROW_FIRST + MFC_ROW_SIZE) +#define MFC_ROW_LAST (MFC_ROW_FIRST + MFC_SIZE - MFC_ROW_SIZE) +#define MFC_SIZE (MFC_ROW_SIZE * ctxt->rows) +#define MFC_SCROLL_SIZE (MFC_SIZE - MFC_ROW_SIZE) + +#define MAKE_TWO_RGB565_COLOR(high, low) (((low) << 16) | (high)) + +inline MFC_STATUS MFC_LOCK(MFC_CONTEXT *ctxt) +{ + if (down_interruptible(&ctxt->sem)) { + pr_err("[MFC] ERROR: Can't get semaphore in %s()\n", + __func__); + BUG_ON(1); + return MFC_STATUS_LOCK_FAIL; + } + return MFC_STATUS_OK; +} + +inline void MFC_UNLOCK(MFC_CONTEXT *ctxt) +{ + up(&ctxt->sem); +} + +/* --------------------------------------------------------------------------- */ +uint32_t MFC_Get_Cursor_Offset(MFC_HANDLE handle) +{ + MFC_CONTEXT *ctxt = (MFC_CONTEXT *) handle; + + uint32_t offset = + ctxt->cursor_col * MFC_FONT_WIDTH * MFC_BPP + + ctxt->cursor_row * MFC_FONT_HEIGHT * MFC_PITCH; + + return offset; +} + +static void _MFC_DrawChar(MFC_CONTEXT *ctxt, uint32_t x, uint32_t y, char c) +{ + uint8_t ch = *((uint8_t *)&c); + const uint8_t *cdat; + uint8_t *dest; + int32_t rows, cols, offset; + + int font_draw_table16[4]; + + BUG_ON(!(x <= (MFC_WIDTH - MFC_FONT_WIDTH))); + BUG_ON(!(y <= (MFC_HEIGHT - MFC_FONT_HEIGHT))); + + offset = y * MFC_PITCH + x * MFC_BPP; + dest = (MFC_ROW_FIRST + offset); + + switch (MFC_BPP) { + /* RGB 565 */ + case 2: + font_draw_table16[0] = MAKE_TWO_RGB565_COLOR(MFC_BG_COLOR, MFC_BG_COLOR); + font_draw_table16[1] = MAKE_TWO_RGB565_COLOR(MFC_BG_COLOR, MFC_FG_COLOR); + font_draw_table16[2] = MAKE_TWO_RGB565_COLOR(MFC_FG_COLOR, MFC_BG_COLOR); + font_draw_table16[3] = MAKE_TWO_RGB565_COLOR(MFC_FG_COLOR, MFC_FG_COLOR); + + cdat = (const uint8_t *)MFC_FONT_DATA + ch * MFC_FONT_HEIGHT; + + for (rows = MFC_FONT_HEIGHT; rows--; dest += MFC_PITCH) { + uint8_t bits = *cdat++; + + ((uint32_t *) dest)[0] = font_draw_table16[bits >> 6]; + ((uint32_t *) dest)[1] = font_draw_table16[bits >> 4 & 3]; + ((uint32_t *) dest)[2] = font_draw_table16[bits >> 2 & 3]; + ((uint32_t *) dest)[3] = font_draw_table16[bits & 3]; + } + break; + /* RGB 888 */ + case 3: + cdat = (const uint8_t *)MFC_FONT_DATA + ch * MFC_FONT_HEIGHT; + for (rows = MFC_FONT_HEIGHT; rows--; dest += MFC_PITCH) { + uint8_t bits = *cdat++; + uint8_t *tmp = dest; + + for (cols = 0; cols < 8; ++cols) { + uint32_t color = ((bits >> (7 - cols)) & 0x1) ? MFC_FG_COLOR : MFC_BG_COLOR; + ((uint8_t *)tmp)[0] = color & 0xff; + ((uint8_t *)tmp)[1] = (color >> 8) & 0xff; + ((uint8_t *)tmp)[2] = (color >> 16) & 0xff; + tmp += 3; + } + } + break; + /* ARGB 8888 */ + case 4: + cdat = (const uint8_t *)MFC_FONT_DATA + ch * MFC_FONT_HEIGHT; + for (rows = MFC_FONT_HEIGHT; rows--; dest += MFC_PITCH) { + uint8_t bits = *cdat++; + uint8_t *tmp = dest; + + for (cols = 0; cols < 8; ++cols) { + uint32_t color = ((bits >> (7 - cols)) & 0x1) ? MFC_FG_COLOR : MFC_BG_COLOR; + ((uint8_t *)tmp)[1] = color & 0xff; + ((uint8_t *)tmp)[2] = (color >> 8) & 0xff; + ((uint8_t *)tmp)[3] = (color >> 16) & 0xff; + ((uint8_t *)tmp)[0] = (color >> 16) & 0xff; + tmp += 4; + } + } + break; + default: + BUG_ON(1); + } +} + + +static void _MFC_ScrollUp(MFC_CONTEXT *ctxt) +{ + const uint32_t BG_COLOR = MAKE_TWO_RGB565_COLOR(MFC_BG_COLOR, MFC_BG_COLOR); + + uint32_t *ptr = (uint32_t *) MFC_ROW_LAST; + int i = MFC_ROW_SIZE / sizeof(uint32_t); + + memcpy(MFC_ROW_FIRST, MFC_ROW_SECOND, MFC_SCROLL_SIZE); + + while (--i >= 0) + *ptr++ = BG_COLOR; +} + + +static void _MFC_Newline(MFC_CONTEXT *ctxt) +{ + /* /Bin:add for filling the color for the blank of this column */ + while (ctxt->cursor_col < ctxt->cols) { + _MFC_DrawChar(ctxt, + ctxt->cursor_col * MFC_FONT_WIDTH, + ctxt->cursor_row * MFC_FONT_HEIGHT, ' '); + + ++ctxt->cursor_col; + } + ++ctxt->cursor_row; + ctxt->cursor_col = 0; + + /* Check if we need to scroll the terminal */ + if (ctxt->cursor_row >= ctxt->rows) { + /* Scroll everything up */ + _MFC_ScrollUp(ctxt); + + /* Decrement row number */ + --ctxt->cursor_row; + } +} + + +#define CHECK_NEWLINE() \ +do { \ + if (ctxt->cursor_col >= ctxt->cols) \ + _MFC_Newline(ctxt); \ +} while (0) + +static void _MFC_Putc(MFC_CONTEXT *ctxt, const char c) +{ + CHECK_NEWLINE(); + + switch (c) { + case '\n': /* next line */ + _MFC_Newline(ctxt); + break; + + case '\r': /* carriage return */ + ctxt->cursor_col = 0; + break; + + case '\t': /* tab 8 */ + ctxt->cursor_col += 8; + ctxt->cursor_col &= ~0x0007; + CHECK_NEWLINE(); + break; + + default: /* draw the char */ + _MFC_DrawChar(ctxt, + ctxt->cursor_col * MFC_FONT_WIDTH, + ctxt->cursor_row * MFC_FONT_HEIGHT, c); + ++ctxt->cursor_col; + CHECK_NEWLINE(); + } +} + +/* --------------------------------------------------------------------------- */ + +MFC_STATUS MFC_Open(MFC_HANDLE *handle, + void *fb_addr, + unsigned int fb_width, + unsigned int fb_height, + unsigned int fb_bpp, unsigned int fg_color, unsigned int bg_color) +{ + MFC_CONTEXT *ctxt = NULL; + + if (NULL == handle || NULL == fb_addr) + return MFC_STATUS_INVALID_ARGUMENT; + + /* if (fb_bpp != 2) */ + /* return MFC_STATUS_NOT_IMPLEMENTED; */ + + ctxt = kzalloc(sizeof(MFC_CONTEXT), GFP_KERNEL); + if (!ctxt) + return MFC_STATUS_OUT_OF_MEMORY; + +/* init_MUTEX(&ctxt->sem); */ + sema_init(&ctxt->sem, 1); + ctxt->fb_addr = fb_addr; + ctxt->fb_width = fb_width; + ctxt->fb_height = fb_height; + ctxt->fb_bpp = fb_bpp; + ctxt->fg_color = fg_color; + ctxt->bg_color = bg_color; + ctxt->rows = fb_height / MFC_FONT_HEIGHT; + ctxt->cols = fb_width / MFC_FONT_WIDTH; + ctxt->font_width = MFC_FONT_WIDTH; + ctxt->font_height = MFC_FONT_HEIGHT; + ctxt->fb_pitch = fb_width * fb_bpp; + + *handle = ctxt; + + return MFC_STATUS_OK; +} + +MFC_STATUS MFC_Open_Ex(MFC_HANDLE *handle, + void *fb_addr, + unsigned int fb_width, + unsigned int fb_height, + unsigned int fb_pitch, + unsigned int fb_bpp, unsigned int fg_color, unsigned int bg_color) +{ + + MFC_CONTEXT *ctxt = NULL; + + if (NULL == handle || NULL == fb_addr) + return MFC_STATUS_INVALID_ARGUMENT; + + if (fb_bpp != 2) + return MFC_STATUS_NOT_IMPLEMENTED; /* only support RGB565 */ + + ctxt = kzalloc(sizeof(MFC_CONTEXT), GFP_KERNEL); + if (!ctxt) + return MFC_STATUS_OUT_OF_MEMORY; + +/* init_MUTEX(&ctxt->sem); */ + sema_init(&ctxt->sem, 1); + ctxt->fb_addr = fb_addr; + ctxt->fb_width = fb_pitch; + ctxt->fb_height = fb_height; + ctxt->fb_bpp = fb_bpp; + ctxt->fg_color = fg_color; + ctxt->bg_color = bg_color; + ctxt->rows = fb_height / MFC_FONT_HEIGHT; + ctxt->cols = fb_width / MFC_FONT_WIDTH; + ctxt->font_width = MFC_FONT_WIDTH; + ctxt->font_height = MFC_FONT_HEIGHT; + ctxt->fb_pitch = fb_pitch * fb_bpp; + + *handle = ctxt; + + return MFC_STATUS_OK; + +} + +MFC_STATUS MFC_Open_Ex_v2(MFC_HANDLE *handle, + void *fb_addr, + unsigned int fb_width, + unsigned int fb_height, + unsigned int fb_pitch_in_bytes, + unsigned int fb_bpp, unsigned int fg_color, unsigned int bg_color) +{ + + MFC_CONTEXT *ctxt = NULL; + + if (NULL == handle || NULL == fb_addr) + return MFC_STATUS_INVALID_ARGUMENT; + + ctxt = kzalloc(sizeof(MFC_CONTEXT), GFP_KERNEL); + if (!ctxt) + return MFC_STATUS_OUT_OF_MEMORY; + +/* init_MUTEX(&ctxt->sem); */ + sema_init(&ctxt->sem, 1); + ctxt->fb_addr = fb_addr; + ctxt->fb_width = fb_pitch_in_bytes; + ctxt->fb_height = fb_height; + ctxt->fb_bpp = fb_bpp; + ctxt->fg_color = fg_color; + ctxt->bg_color = bg_color; + ctxt->rows = fb_height / MFC_FONT_HEIGHT; + ctxt->cols = fb_width / MFC_FONT_WIDTH; + ctxt->font_width = MFC_FONT_WIDTH; + ctxt->font_height = MFC_FONT_HEIGHT; + ctxt->fb_pitch = fb_pitch_in_bytes; + + *handle = ctxt; + + return MFC_STATUS_OK; +} + +MFC_STATUS MFC_Close(MFC_HANDLE handle) +{ + if (!handle) + return MFC_STATUS_INVALID_ARGUMENT; + + kfree(handle); + + return MFC_STATUS_OK; +} + + +MFC_STATUS MFC_SetColor(MFC_HANDLE handle, unsigned int fg_color, unsigned int bg_color) +{ + MFC_CONTEXT *ctxt = (MFC_CONTEXT *) handle; + + if (!ctxt) + return MFC_STATUS_INVALID_ARGUMENT; + + MFC_LOCK(ctxt); + ctxt->fg_color = fg_color; + ctxt->bg_color = bg_color; + MFC_UNLOCK(ctxt); + + return MFC_STATUS_OK; +} + + +MFC_STATUS MFC_ResetCursor(MFC_HANDLE handle) +{ + MFC_CONTEXT *ctxt = (MFC_CONTEXT *) handle; + + if (!ctxt) + return MFC_STATUS_INVALID_ARGUMENT; + + MFC_LOCK(ctxt); + ctxt->cursor_row = ctxt->cursor_col = 0; + MFC_UNLOCK(ctxt); + + return MFC_STATUS_OK; +} + + +MFC_STATUS MFC_Print(MFC_HANDLE handle, const char *str) +{ + MFC_CONTEXT *ctxt = (MFC_CONTEXT *) handle; + int count = 0; + + if (!ctxt || !str) + return MFC_STATUS_INVALID_ARGUMENT; + + MFC_LOCK(ctxt); + + count = strlen(str); + + while (count--) + _MFC_Putc(ctxt, *str++); + + MFC_UNLOCK(ctxt); + + return MFC_STATUS_OK; +} + +MFC_STATUS MFC_SetMem(MFC_HANDLE handle, const char *str, uint32_t color) +{ + MFC_CONTEXT *ctxt = (MFC_CONTEXT *) handle; + int count = 0; + int i, j; + uint32_t *ptr; + + if (!ctxt || !str) + return MFC_STATUS_INVALID_ARGUMENT; + + MFC_LOCK(ctxt); + + count = strlen(str); + count = count * MFC_FONT_WIDTH; + + for (j = 0; j < MFC_FONT_HEIGHT; j++) { + ptr = (uint32_t *) (ctxt->fb_addr + (j + 1) * MFC_PITCH - count * ctxt->fb_bpp); + for (i = 0; i < count * ctxt->fb_bpp / sizeof(uint32_t); i++) + *ptr++ = color; + } + + MFC_UNLOCK(ctxt); + + return MFC_STATUS_OK; +} + +MFC_STATUS MFC_LowMemory_Printf(MFC_HANDLE handle, const char *str, uint32_t fg_color, + uint32_t bg_color) +{ + MFC_CONTEXT *ctxt = (MFC_CONTEXT *) handle; + int count = 0; + unsigned int col, row, fg_color_mfc, bg_color_mfc; + + if (!ctxt || !str) + return MFC_STATUS_INVALID_ARGUMENT; + + MFC_LOCK(ctxt); + + count = strlen(str); +/* //store cursor_col and row for printf low memory char temply */ + row = ctxt->cursor_row; + col = ctxt->cursor_col; + ctxt->cursor_row = 0; + ctxt->cursor_col = ctxt->cols - count; + fg_color_mfc = ctxt->fg_color; + bg_color_mfc = ctxt->bg_color; + +/* ///////// */ + ctxt->fg_color = fg_color; + ctxt->bg_color = bg_color; + while (count--) + _MFC_Putc(ctxt, *str++); + +/* //restore cursor_col and row for printf low memory char temply */ + ctxt->cursor_row = row; + ctxt->cursor_col = col; + ctxt->fg_color = fg_color_mfc; + ctxt->bg_color = bg_color_mfc; +/* ///////// */ + + + MFC_UNLOCK(ctxt); + + return MFC_STATUS_OK; +} + +/* screen logger. */ +static screen_logger logger_head; +static int screen_logger_inited; +void screen_logger_init(void) +{ + if (0 == screen_logger_inited) { + INIT_LIST_HEAD(&logger_head.list); + screen_logger_inited = 1; + } +} + +void screen_logger_add_message(char *obj, message_mode mode, char *message) +{ + screen_logger *p; + int add_new = 1; + char *tmp1, *tmp2; + unsigned int len = 0; + + screen_logger_init(); + list_for_each_entry(p, &logger_head.list, list) { + if (strcmp(p->obj, obj) == 0) { + switch (mode) { + case MESSAGE_REPLACE: + tmp1 = p->message; + tmp2 = kstrdup(message, GFP_KERNEL); + p->message = tmp2; + kfree(tmp1); + break; + case MESSAGE_APPEND: + len = strlen(p->message) + strlen(message); + tmp1 = kmalloc(sizeof(char) * (len + 1), GFP_KERNEL); + strcpy(tmp1, p->message); + strcat(tmp1, message); + tmp2 = p->message; + p->message = tmp1; + kfree(tmp2); + break; + default: + break; + } + add_new = 0; + } + } + if (1 == add_new) { + screen_logger *logger = kmalloc(sizeof(screen_logger), GFP_KERNEL); + + logger->obj = kstrdup(obj, GFP_KERNEL); + logger->message = kstrdup(message, GFP_KERNEL); + list_add_tail(&logger->list, &logger_head.list); + } +} + +void screen_logger_remove_message(char *obj) +{ + screen_logger *p; + + list_for_each_entry(p, &logger_head.list, list) { + if (0 == strcmp(p->obj, obj)) { + kfree(p->obj); + kfree(p->message); + /* memory leak. TODO: delete completely. */ + list_del(&p->list); + kfree(p); + break; + } + } + p = NULL; +} + +void screen_logger_print(MFC_HANDLE handle) +{ + screen_logger *p; + + list_for_each_entry(p, &logger_head.list, list) { + MFC_Print(handle, p->message); + } +} + +void screen_logger_empty(void) +{ + screen_logger *p = list_entry(logger_head.list.prev, typeof(*p), list); + + while (p != &logger_head) { + screen_logger_remove_message(p->obj); + p = list_entry(logger_head.list.prev, typeof(*p), list); + } +} + +void screen_logger_test_case(MFC_HANDLE handle) +{ + screen_logger_add_message("message1", MESSAGE_REPLACE, "print message1\n"); + screen_logger_add_message("message1", MESSAGE_REPLACE, "print message2\n"); + screen_logger_print(handle); + screen_logger_empty(); +} diff --git a/drivers/misc/mediatek/video/mt6755/mtkfb_console.h b/drivers/misc/mediatek/video/mt6755/mtkfb_console.h new file mode 100644 index 0000000000000000000000000000000000000000..0836d709a61976882723d093a9000f24795816d2 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtkfb_console.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MTK_FB_CONSOLE_H__ +#define __MTK_FB_CONSOLE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define MFC_CHECK_RET(expr) \ +do { \ + MFC_STATUS ret = (expr); \ + ASSERT(MFC_STATUS_OK == ret); \ +} while (0) + + + typedef enum { + MFC_STATUS_OK = 0, + + MFC_STATUS_INVALID_ARGUMENT = -1, + MFC_STATUS_NOT_IMPLEMENTED = -2, + MFC_STATUS_OUT_OF_MEMORY = -3, + MFC_STATUS_LOCK_FAIL = -4, + MFC_STATUS_FATAL_ERROR = -5, + } MFC_STATUS; + + + typedef void *MFC_HANDLE; + +/* --------------------------------------------------------------------------- */ + + typedef struct { + struct semaphore sem; + + uint8_t *fb_addr; + uint32_t fb_width; + uint32_t fb_height; + uint32_t fb_bpp; + uint32_t fb_pitch; + uint32_t fg_color; + uint32_t bg_color; + uint32_t screen_color; + uint32_t rows; + uint32_t cols; + uint32_t cursor_row; + uint32_t cursor_col; + uint32_t font_width; + uint32_t font_height; + } MFC_CONTEXT; + +/* MTK Framebuffer Console API */ + + MFC_STATUS MFC_Open(MFC_HANDLE *handle, + void *fb_addr, + unsigned int fb_width, + unsigned int fb_height, + unsigned int fb_bpp, unsigned int fg_color, unsigned int bg_color); + + MFC_STATUS MFC_Open_Ex(MFC_HANDLE *handle, + void *fb_addr, + unsigned int fb_width, + unsigned int fb_height, + unsigned int fb_pitch, + unsigned int fb_bpp, unsigned int fg_color, unsigned int bg_color); + + MFC_STATUS MFC_Open_Ex_v2(MFC_HANDLE *handle, + void *fb_addr, + unsigned int fb_width, + unsigned int fb_height, + unsigned int fb_pitch_in_bytes, + unsigned int fb_bpp, unsigned int fg_color, unsigned int bg_color); + + MFC_STATUS MFC_Close(MFC_HANDLE handle); + + MFC_STATUS MFC_SetColor(MFC_HANDLE handle, unsigned int fg_color, unsigned int bg_color); + + MFC_STATUS MFC_ResetCursor(MFC_HANDLE handle); + + MFC_STATUS MFC_Print(MFC_HANDLE handle, const char *str); + + MFC_STATUS MFC_LowMemory_Printf(MFC_HANDLE handle, const char *str, uint32_t fg_color, + uint32_t bg_color); + + MFC_STATUS MFC_SetMem(MFC_HANDLE handle, const char *str, uint32_t color); + uint32_t MFC_Get_Cursor_Offset(MFC_HANDLE handle); + + /* screen logger */ + typedef struct _screen_logger { + struct list_head list; + char *obj; + char *message; + } screen_logger; + + typedef enum _message_mode { + MESSAGE_REPLACE = 0, + MESSAGE_APPEND = 1 + } message_mode; + + void screen_logger_init(void); + void screen_logger_add_message(char *obj, message_mode mode, char *message); + void screen_logger_remove_message(char *obj); + void screen_logger_print(MFC_HANDLE handle); + void screen_logger_empty(void); + void screen_logger_test_case(MFC_HANDLE handle); +#ifdef __cplusplus +} +#endif +#endif /* __MTK_FB_CONSOLE_H__ */ diff --git a/drivers/misc/mediatek/video/mt6755/mtkfb_dummy.c b/drivers/misc/mediatek/video/mt6755/mtkfb_dummy.c new file mode 100644 index 0000000000000000000000000000000000000000..52f2bdbe7f881d09eb6c6de254d4283f22915d07 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtkfb_dummy.c @@ -0,0 +1,966 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "disp_assert_layer.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ion_drv.h" +#include +#include +#include +#include "mtkfb.h" +#include "mtkfb_info.h" + +#define DISPMSG pr_debug +#define ALIGN_TO(x, n) \ + (((x) + ((n) - 1)) & ~((n) - 1)) + +#define SCREEN_WIDHT (1080) +#define SCREEN_HEIGHT (1920) + +#define MTK_FB_ALIGNMENT 32 + +static u32 MTK_FB_XRES; +static u32 MTK_FB_YRES; +static u32 MTK_FB_BPP; +static u32 MTK_FB_PAGES; +static u32 fb_xres_update; +static u32 fb_yres_update; +static unsigned long size; +#define MTK_FB_XRESV (ALIGN_TO(MTK_FB_XRES, MTK_FB_ALIGNMENT)) +#define MTK_FB_YRESV (ALIGN_TO(MTK_FB_YRES, MTK_FB_ALIGNMENT) * MTK_FB_PAGES) /* For page flipping */ +#define MTK_FB_BYPP ((MTK_FB_BPP + 7) >> 3) +#define MTK_FB_LINE (ALIGN_TO(MTK_FB_XRES, MTK_FB_ALIGNMENT) * MTK_FB_BYPP) +#define MTK_FB_SIZE (MTK_FB_LINE * ALIGN_TO(MTK_FB_YRES, MTK_FB_ALIGNMENT)) + +#define MTK_FB_SIZEV (MTK_FB_LINE * ALIGN_TO(MTK_FB_YRES, MTK_FB_ALIGNMENT) * MTK_FB_PAGES) + + +/* --------------------------------------------------------------------------- */ +/* local variables */ +/* --------------------------------------------------------------------------- */ + +unsigned long fb_pa = 0; +struct fb_info *mtkfb_fbi; +unsigned int lcd_fps = 6000; +char mtkfb_lcm_name[256] = { 0 }; + +bool is_ipoh_bootup = false; +BOOL is_early_suspended = FALSE; + + +/* --------------------------------------------------------------------------- */ +/* local function declarations */ +/* --------------------------------------------------------------------------- */ + +#ifdef CONFIG_OF +static int _parse_tag_videolfb(void); +#endif + + +int mtkfb_get_debug_state(char *stringbuf, int buf_len) +{ + return 0; +} + +unsigned int mtkfb_fm_auto_test(void) +{ + return 0; +} + + +/* Init frame buffer content as 3 R/G/B color bars for debug */ +static int init_framebuffer(struct fb_info *info) +{ + void *buffer = info->screen_base + info->var.yoffset * info->fix.line_length; + + /* clean whole frame buffer as black */ + memset(buffer, 0, info->screen_size); + + return 0; +} + +unsigned int DISP_GetVRamSizeBoot(void) +{ + return 0x01800000; +} + +/* + * --------------------------------------------------------------------------- + * fbdev framework callbacks and the ioctl interface + * --------------------------------------------------------------------------- + */ +/* Called each time the mtkfb device is opened */ +static int mtkfb_open(struct fb_info *info, int user) +{ + return 0; +} + +/* Called when the mtkfb device is closed. We make sure that any pending + * gfx DMA operations are ended, before we return. */ +static int mtkfb_release(struct fb_info *info, int user) +{ + return 0; +} + +/* Store a single color palette entry into a pseudo palette or the hardware + * palette if one is available. For now we support only 16bpp and thus store + * the entry only to the pseudo palette. + */ +static int mtkfb_setcolreg(u_int regno, u_int red, u_int green, + u_int blue, u_int transp, struct fb_info *info) +{ + int r = 0; + unsigned bpp, m; + + NOT_REFERENCED(transp); + bpp = info->var.bits_per_pixel; + m = 1 << bpp; + if (regno >= m) { + r = -EINVAL; + goto exit; + } + + switch (bpp) { + case 16: + /* RGB 565 */ + ((u32 *) (info->pseudo_palette))[regno] = + ((red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11)); + break; + case 32: + /* ARGB8888 */ + ((u32 *) (info->pseudo_palette))[regno] = + (0xff000000) | + ((red & 0xFF00) << 8) | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); + break; + + /* TODO: RGB888, BGR888, ABGR8888 */ + + default: + ASSERT(0); + } + +exit: + return r; +} + + +/* Set fb_info.fix fields and also updates fbdev. + * When calling this fb_info.var must be set up already. + */ +static void set_fb_fix(struct mtkfb_device *fbdev) +{ + struct fb_info *fbi = fbdev->fb_info; + struct fb_fix_screeninfo *fix = &fbi->fix; + struct fb_var_screeninfo *var = &fbi->var; + struct fb_ops *fbops = fbi->fbops; + + strncpy(fix->id, MTKFB_DRIVER, sizeof(fix->id)); + fix->type = FB_TYPE_PACKED_PIXELS; + + switch (var->bits_per_pixel) { + case 16: + case 24: + case 32: + fix->visual = FB_VISUAL_TRUECOLOR; + break; + case 1: + case 2: + case 4: + case 8: + fix->visual = FB_VISUAL_PSEUDOCOLOR; + break; + default: + ASSERT(0); + } + + fix->accel = FB_ACCEL_NONE; + fix->line_length = ALIGN_TO(var->xres_virtual, MTK_FB_ALIGNMENT) * var->bits_per_pixel / 8; + fix->smem_len = fbdev->fb_size_in_byte; + fix->smem_start = fbdev->fb_pa_base; + + fix->xpanstep = 0; + fix->ypanstep = 1; + + fbops->fb_fillrect = cfb_fillrect; + fbops->fb_copyarea = cfb_copyarea; + fbops->fb_imageblit = cfb_imageblit; +} + + +/* Switch to a new mode. The parameters for it has been check already by + * mtkfb_check_var. + */ +static int mtkfb_set_par(struct fb_info *fbi) +{ + struct fb_var_screeninfo *var = &fbi->var; + struct mtkfb_device *fbdev = (struct mtkfb_device *)fbi->par; + + set_fb_fix(fbdev); + return 0; +} + +int mtkfb_set_backlight_mode(unsigned int mode) +{ + return 0; +} + +int mtkfb_set_backlight_level(unsigned int level) +{ + return 0; +} + +static int mtkfb_pan_display_impl(struct fb_var_screeninfo *var, struct fb_info *info) +{ + + pr_debug("xoffset=%u, yoffset=%u, xres=%u, yres=%u, xresv=%u, yresv=%u\n", var->xoffset, + var->yoffset, info->var.xres, info->var.yres, info->var.xres_virtual, + info->var.yres_virtual); + info->var.yoffset = var->yoffset; + return 0; +} + + +/* Check values in var, try to adjust them in case of out of bound values if + * possible, or return error. + */ +static int mtkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) +{ + unsigned int bpp; + unsigned long max_frame_size; + unsigned long line_size; + + struct mtkfb_device *fbdev = (struct mtkfb_device *)fbi->par; + + /* DISPFUNC(); */ + + pr_debug("mtkfb_check_var,xres=%u,yres=%u,x_vir=%u,y_vir=%u,xoffset=%u,yoffset=%u,bits_per_pixel=%u)\n", + var->xres, var->yres, var->xres_virtual, var->yres_virtual, + var->xoffset, var->yoffset, var->bits_per_pixel); + + bpp = var->bits_per_pixel; + + if (bpp != 16 && bpp != 24 && bpp != 32) { + pr_debug("[%s]unsupported bpp: %d", __func__, bpp); + return -1; + } + + switch (var->rotate) { + case 0: + case 180: + var->xres = MTK_FB_XRES; + var->yres = MTK_FB_YRES; + break; + case 90: + case 270: + var->xres = MTK_FB_YRES; + var->yres = MTK_FB_XRES; + break; + default: + return -1; + } + + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + max_frame_size = fbdev->fb_size_in_byte; + pr_debug("fbdev->fb_size_in_byte=0x%08lx\n", fbdev->fb_size_in_byte); + line_size = var->xres_virtual * bpp / 8; + + if (line_size * var->yres_virtual > max_frame_size) { + /* Try to keep yres_virtual first */ + line_size = max_frame_size / var->yres_virtual; + var->xres_virtual = line_size * 8 / bpp; + if (var->xres_virtual < var->xres) { + /* Still doesn't fit. Shrink yres_virtual too */ + var->xres_virtual = var->xres; + line_size = var->xres * bpp / 8; + var->yres_virtual = max_frame_size / line_size; + } + } + pr_error("mtkfb_check_var,xres=%u,yres=%u,x_vir=%u,y_vir=%u,xoffset=%u,yoffset=%u,bits_per_pixel=%u)\n", + var->xres, var->yres, var->xres_virtual, var->yres_virtual, + var->xoffset, var->yoffset, var->bits_per_pixel); + if (var->xres + var->xoffset > var->xres_virtual) + var->xoffset = var->xres_virtual - var->xres; + if (var->yres + var->yoffset > var->yres_virtual) + var->yoffset = var->yres_virtual - var->yres; + + pr_error("mtkfb_check_var,xres=%u,yres=%u,x_vir=%u,y_vir=%u,xoffset=%u,yoffset=%u,bits_per_pixel=%u)\n", + var->xres, var->yres, var->xres_virtual, var->yres_virtual, + var->xoffset, var->yoffset, var->bits_per_pixel); + + if (16 == bpp) { + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + } else if (24 == bpp) { + var->red.length = var->green.length = var->blue.length = 8; + var->transp.length = 0; + + /* Check if format is RGB565 or BGR565 */ + + ASSERT(8 == var->green.offset); + ASSERT(16 == var->red.offset + var->blue.offset); + ASSERT(16 == var->red.offset || 0 == var->red.offset); + } else if (32 == bpp) { + var->red.length = var->green.length = var->blue.length = var->transp.length = 8; + + /* Check if format is ARGB565 or ABGR565 */ + + ASSERT(8 == var->green.offset && 24 == var->transp.offset); + ASSERT(16 == var->red.offset + var->blue.offset); + ASSERT(16 == var->red.offset || 0 == var->red.offset); + } + + var->red.msb_right = var->green.msb_right = var->blue.msb_right = var->transp.msb_right = 0; + + var->activate = FB_ACTIVATE_NOW; + + var->height = UINT_MAX; + var->width = UINT_MAX; + var->grayscale = 0; + var->nonstd = 0; + + var->pixclock = UINT_MAX; + var->left_margin = UINT_MAX; + var->right_margin = UINT_MAX; + var->upper_margin = UINT_MAX; + var->lower_margin = UINT_MAX; + var->hsync_len = UINT_MAX; + var->vsync_len = UINT_MAX; + + var->vmode = FB_VMODE_NONINTERLACED; + var->sync = 0; + + return 0; +} + + +static int mtkfb_pan_display_proxy(struct fb_var_screeninfo *var, struct fb_info *info) +{ + return mtkfb_pan_display_impl(var, info); +} + +#ifdef CONFIG_DMA_SHARED_BUFFER +static struct sg_table *mtkfb_dma_buf_map(struct dma_buf_attachment *attachment, + enum dma_data_direction dir) +{ + struct sg_table *table; + struct fb_info *info = attachment->dmabuf->priv; + struct page *page; + int err; + + table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) + return ERR_PTR(-ENOMEM); + + err = sg_alloc_table(table, 1, GFP_KERNEL); + if (err) { + kfree(table); + return ERR_PTR(err); + } + + sg_set_page(table->sgl, NULL, info->fix.smem_len, 0); + + sg_dma_address(table->sgl) = info->fix.smem_start; + debug_dma_map_sg(NULL, table->sgl, table->nents, table->nents, DMA_BIDIRECTIONAL); + + return table; +} + +static void mtkfb_dma_buf_unmap(struct dma_buf_attachment *attachment, struct sg_table *table, + enum dma_data_direction dir) +{ + debug_dma_unmap_sg(NULL, table->sgl, table->nents, DMA_BIDIRECTIONAL); + sg_free_table(table); + kfree(table); +} + +static void mtkfb_dma_buf_release(struct dma_buf *buf) +{ + /* Nop */ +} + +static void *mtkfb_dma_buf_kmap_atomic(struct dma_buf *buf, unsigned long off) +{ + /* Not supported */ + return NULL; +} + +static void *mtkfb_dma_buf_kmap(struct dma_buf *buf, unsigned long off) +{ + /* Not supported */ + return NULL; +} + +static int mtkfb_dma_buf_mmap(struct dma_buf *buf, struct vm_area_struct *vma) +{ + struct fb_info *info = (struct fb_info *)buf->priv; + + pr_error(KERN_INFO "mtkfb: mmap dma-buf: %p, start: %lu, offset: %lu, size: %lu\n", + buf, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start); + + return io_remap_pfn_range(vma, + vma->vm_start + vma->vm_pgoff, + (info->fix.smem_start + vma->vm_pgoff) >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + pgprot_writecombine(vma->vm_page_prot)); +} + +static struct dma_buf_ops mtkfb_dma_buf_ops = { + .map_dma_buf = mtkfb_dma_buf_map, + .unmap_dma_buf = mtkfb_dma_buf_unmap, + .release = mtkfb_dma_buf_release, + .kmap_atomic = mtkfb_dma_buf_kmap_atomic, + .kmap = mtkfb_dma_buf_kmap, + .mmap = mtkfb_dma_buf_mmap, +}; + +static struct dma_buf *mtkfb_dmabuf_export(struct fb_info *info) +{ + struct dma_buf *buf; + + pr_error(KERN_INFO "mtkfb: Exporting dma-buf\n"); + + + buf = dma_buf_export(info, &mtkfb_dma_buf_ops, info->fix.smem_len, O_RDWR); + + return buf; +} + +#endif + +/* Callback table for the frame buffer framework. Some of these pointers + * will be changed according to the current setting of fb_info->accel_flags. + */ +static struct fb_ops mtkfb_ops = { + .owner = THIS_MODULE, + .fb_open = mtkfb_open, + .fb_release = mtkfb_release, + .fb_setcolreg = mtkfb_setcolreg, + .fb_pan_display = mtkfb_pan_display_proxy, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_cursor = NULL, + .fb_check_var = mtkfb_check_var, + .fb_set_par = mtkfb_set_par, + .fb_ioctl = NULL, +#ifdef CONFIG_DMA_SHARED_BUFFER + .fb_dmabuf_export = mtkfb_dmabuf_export, +#endif +}; + + +/* + * --------------------------------------------------------------------------- + * LDM callbacks + * --------------------------------------------------------------------------- + */ +/* Initialize system fb_info object and set the default video mode. + * The frame buffer memory already allocated by lcddma_init + */ +static int mtkfb_fbinfo_init(struct fb_info *info) +{ + struct mtkfb_device *fbdev = (struct mtkfb_device *)info->par; + struct fb_var_screeninfo var; + int r = 0; + + BUG_ON(!fbdev->fb_va_base); + info->fbops = &mtkfb_ops; + info->flags = FBINFO_FLAG_DEFAULT; + info->screen_base = (char *)fbdev->fb_va_base; + info->screen_size = fbdev->fb_size_in_byte; + info->pseudo_palette = fbdev->pseudo_palette; + + r = fb_alloc_cmap(&info->cmap, 32, 0); + if (r != 0) + pr_error("unable to allocate color map memory\n"); + + /* setup the initial video mode (RGB565) */ + + memset(&var, 0, sizeof(var)); + + var.xres = MTK_FB_XRES; + var.yres = MTK_FB_YRES; + var.xres_virtual = MTK_FB_XRESV; + var.yres_virtual = MTK_FB_YRESV; + /* use 32 bit framebuffer as default */ + var.bits_per_pixel = 32; + + var.transp.offset = 24; + var.red.length = 8; +#if 0 + var.red.offset = 16; + var.red.length = 8; + var.green.offset = 8; + var.green.length = 8; + var.blue.offset = 0; + var.blue.length = 8; +#else + var.red.offset = 0; + var.red.length = 8; + var.green.offset = 8; + var.green.length = 8; + var.blue.offset = 16; + var.blue.length = 8; +#endif + + var.width = 0; + var.height = 0; + + var.activate = FB_ACTIVATE_NOW; + + r = mtkfb_check_var(&var, info); + if (r != 0) + pr_error("failed to mtkfb_check_var\n"); + + info->var = var; + + r = mtkfb_set_par(info); + if (r != 0) + pr_error("failed to mtkfb_set_par\n"); + return r; +} + +/* Release the fb_info object */ +static void mtkfb_fbinfo_cleanup(struct mtkfb_device *fbdev) +{ + fb_dealloc_cmap(&fbdev->fb_info->cmap); +} + +/* Free driver resources. Can be called to rollback an aborted initialization + * sequence. + */ +static void mtkfb_free_resources(struct mtkfb_device *fbdev, int state) +{ + int r = 0; + + switch (state) { + case MTKFB_ACTIVE: + r = unregister_framebuffer(fbdev->fb_info); + ASSERT(0 == r); + /* lint -fallthrough */ + case 4: + mtkfb_fbinfo_cleanup(fbdev); + /* lint -fallthrough */ + case 2: +#ifndef FPGA_EARLY_PORTING + dma_free_coherent(0, fbdev->fb_size_in_byte, fbdev->fb_va_base, fbdev->fb_pa_base); +#endif + /* lint -fallthrough */ + case 1: + dev_set_drvdata(fbdev->dev, NULL); + framebuffer_release(fbdev->fb_info); + /* lint -fallthrough */ + case 0: + /* nothing to free */ + break; + default: + BUG(); + } +} + +UINT32 DISP_GetScreenWidth(void) +{ + return SCREEN_WIDHT; +} + +UINT32 DISP_GetScreenHeight(void) +{ + return SCREEN_HEIGHT; +} + +void disp_get_fb_address(unsigned long *fbVirAddr, unsigned long *fbPhysAddr) +{ + struct mtkfb_device *fbdev = (struct mtkfb_device *)mtkfb_fbi->par; + + *fbVirAddr = + (unsigned long)fbdev->fb_va_base + mtkfb_fbi->var.yoffset * mtkfb_fbi->fix.line_length; + *fbPhysAddr = + (unsigned long)fbdev->fb_pa_base + mtkfb_fbi->var.yoffset * mtkfb_fbi->fix.line_length; +} + +static int mtkfb_fbinfo_modify(struct fb_info *info) +{ + struct fb_var_screeninfo var; + int r = 0; + + memcpy(&var, &(info->var), sizeof(var)); + var.activate = FB_ACTIVATE_NOW; + var.bits_per_pixel = 32; + var.transp.offset = 24; + var.transp.length = 8; + var.red.offset = 16; + var.red.length = 8; + var.green.offset = 8; + var.green.length = 8; + var.blue.offset = 0; + var.blue.length = 8; + var.yoffset = var.yres; + + r = mtkfb_check_var(&var, info); + if (r != 0) + pr_error("failed to mtkfb_check_var\n"); + + info->var = var; + + r = mtkfb_set_par(info); + if (r != 0) + pr_error("failed to mtkfb_set_par\n"); + + return r; +} + +unsigned int vramsize = 0; +#ifdef CONFIG_OF +struct tag_videolfb { + u64 fb_base; + u32 islcmfound; + u32 fps; + u32 vram; + char lcmname[1]; /* this is the minimum size */ +}; +unsigned int islcmconnected = 0; +phys_addr_t fb_base = 0; +static int is_videofb_parse_done; +static unsigned long video_node; + +static int fb_early_init_dt_get_chosen(unsigned long node, const char *uname, int depth, void *data) +{ + if (depth != 1 || (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; + video_node = node; + return 1; +} + +/* 0: success / 1: fail */ +static int _parse_tag_videolfb(void) +{ + unsigned long size = 0; + void *prop = NULL; + struct tag_videolfb *videolfb_tag = NULL; + + pr_error("[DT][videolfb]isvideofb_parse_done = %d\n", is_videofb_parse_done); + + if (is_videofb_parse_done) + return 0; + if (of_scan_flat_dt(fb_early_init_dt_get_chosen, NULL) > 0) { + videolfb_tag = + (struct tag_videolfb *)of_get_flat_dt_prop(video_node, "atag,videolfb", NULL); + if (videolfb_tag) { + pr_error("[DT][videolfb] find video info from lk\n"); + memset((void *)mtkfb_lcm_name, 0, sizeof(mtkfb_lcm_name)); + strcpy((char *)mtkfb_lcm_name, videolfb_tag->lcmname); + mtkfb_lcm_name[strlen(videolfb_tag->lcmname)] = '\0'; + + lcd_fps = videolfb_tag->fps; + if (0 == lcd_fps) + lcd_fps = 6000; + + islcmconnected = videolfb_tag->islcmfound; + vramsize = videolfb_tag->vram; + fb_base = videolfb_tag->fb_base; + is_videofb_parse_done = 1; + pr_error("[DT][videolfb] islcmfound = %d\n", islcmconnected); + pr_error("[DT][videolfb] fps = %d\n", lcd_fps); + pr_error("[DT][videolfb] fb_base = 0x%p\n", (void *)fb_base); + pr_error("[DT][videolfb] vram = %d\n", vramsize); + pr_error("[DT][videolfb] lcmname = %s\n", mtkfb_lcm_name); + } else { + pr_error("[DT][videolfb] find video info from dts\n"); + prop = of_get_flat_dt_prop(video_node, "atag,videolfb-fb_base", NULL); + if (!prop) { + pr_error("[DT][videolfb] fail to parse fb_base\n"); + return -1; + } + fb_base = of_read_number(prop, 1); + + prop = of_get_flat_dt_prop(video_node, "atag,videolfb-islcmfound", NULL); + if (!prop) { + pr_error("[DT][videolfb] fail to parse islcmfound\n"); + return -1; + } + islcmconnected = of_read_number(prop, 1); + + prop = of_get_flat_dt_prop(video_node, "atag,videolfb-fps", NULL); + if (!prop) { + pr_error("[DT][videolfb] fail to parse fps\n"); + return -1; + } + lcd_fps = of_read_number(prop, 1); + if (0 == lcd_fps) + lcd_fps = 6000; + + prop = of_get_flat_dt_prop(video_node, "atag,videolfb-vramSize", NULL); + if (!prop) { + pr_error("[DT][videolfb] fail to parse vramSize\n"); + return -1; + } + vramsize = of_read_number(prop, 1); + + prop = of_get_flat_dt_prop(video_node, "atag,videolfb-lcmname", &size); + if (!prop) { + pr_error("[DT][videolfb] fail to parse lcmname\n"); + return -1; + } + + if (size >= sizeof(mtkfb_lcm_name)) { + DISPMSG("%s: error to get lcmname size=%ld\n", __func__, + size); + return -1; + } + memset((void *)mtkfb_lcm_name, 0, sizeof(mtkfb_lcm_name)); + strncpy((char *)mtkfb_lcm_name, prop, sizeof(mtkfb_lcm_name)); + mtkfb_lcm_name[size] = '\0'; + + is_videofb_parse_done = 1; + + pr_error("[DT][videolfb] fb_base = %p\n", (void *)fb_base); + pr_error("[DT][videolfb] islcmfound = %d\n", islcmconnected); + pr_error("[DT][videolfb] fps = %d\n", lcd_fps); + pr_error("[DT][videolfb] vram = %d\n", vramsize); + pr_error("[DT][videolfb] lcmname = %s\n", mtkfb_lcm_name); + } + return 0; + } + pr_error("[DT][videolfb] of_chosen not found\n"); + return 1; +} + +phys_addr_t mtkfb_get_fb_base(void) +{ + _parse_tag_videolfb(); + return fb_base; +} +#endif + + +int mtkfb_allocate_framebuffer(phys_addr_t pa_start, phys_addr_t pa_end, unsigned long *va, + unsigned long *mva) +{ + int ret = 0; + *va = (unsigned long)ioremap_nocache(pa_start, pa_end - pa_start + 1); + pr_error("disphal_allocate_fb, pa=%p, va=0x%lx\n", (void *)pa_start, *va); + { + *mva = pa_start & 0xffffffffULL; + } + return 0; +} + +static int mtkfb_probe(struct device *dev) +{ + struct platform_device *pdev; + struct mtkfb_device *fbdev = NULL; + struct fb_info *fbi; + int init_state; + int r = 0; + char *p = NULL; + + pr_error("mtkfb_probe begin\n"); + +#ifdef CONFIG_OF + _parse_tag_videolfb(); +#else + pr_error("%s, no device tree ??!!\n", __func__); + BUG(); +#endif + init_state = 0; + + pdev = to_platform_device(dev); + + fbi = framebuffer_alloc(sizeof(struct mtkfb_device), dev); + if (!fbi) { + pr_error("unable to allocate memory for device info\n"); + r = -ENOMEM; + goto cleanup; + } + + fbdev = (struct mtkfb_device *)fbi->par; + fbdev->fb_info = fbi; + fbdev->dev = dev; + dev_set_drvdata(dev, fbdev); + + { + +#ifdef CONFIG_OF + pr_error("mtkfb_probe:get FB MEM REG\n"); + _parse_tag_videolfb(); + pr_error("mtkfb_probe: fb_pa = %p\n", (void *)fb_base); + + mtkfb_allocate_framebuffer(fb_base, (fb_base + vramsize - 1), + (unsigned int *)&fbdev->fb_va_base, &fb_pa); + fbdev->fb_pa_base = fb_base; +#else + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + disp_hal_allocate_framebuffer(res->start, res->end, + (unsigned int *)&fbdev->fb_va_base, &fb_pa); + fbdev->fb_pa_base = res->start; +#endif + } + + init_state++; /* 1 */ + MTK_FB_XRES = SCREEN_WIDHT; + MTK_FB_YRES = SCREEN_HEIGHT; + fb_xres_update = MTK_FB_XRES; + fb_yres_update = MTK_FB_YRES; + + MTK_FB_BPP = 32; + MTK_FB_PAGES = 3; + pr_error + ("MTK_FB_XRES=%d, MTKFB_YRES=%d, MTKFB_BPP=%d, MTK_FB_PAGES=%d, MTKFB_LINE=%d, MTKFB_SIZEV=%d\n", + MTK_FB_XRES, MTK_FB_YRES, MTK_FB_BPP, MTK_FB_PAGES, MTK_FB_LINE, MTK_FB_SIZEV); + fbdev->fb_size_in_byte = MTK_FB_SIZEV; + + /* Allocate and initialize video frame buffer */ + pr_error("[FB Driver] fbdev->fb_pa_base = %lx, fbdev->fb_va_base = %lx\n", + (unsigned long)fbdev->fb_pa_base, (unsigned long)(fbdev->fb_va_base)); + + if (!fbdev->fb_va_base) { + pr_error("unable to allocate memory for frame buffer\n"); + r = -ENOMEM; + goto cleanup; + } + init_state++; /* 2 */ + + /* Register to system */ + + r = mtkfb_fbinfo_init(fbi); + if (r) { + pr_error("mtkfb_fbinfo_init fail, r = %d\n", r); + goto cleanup; + } + init_state++; /* 4 */ + mtkfb_fbi = fbi; + init_state++; /* 5 */ + + r = register_framebuffer(fbi); + if (r != 0) { + pr_error("register_framebuffer failed\n"); + goto cleanup; + } + fbdev->state = MTKFB_ACTIVE; + pr_error("mtkfb_probe end\n"); + return 0; + +cleanup: + mtkfb_free_resources(fbdev, init_state); + + pr_error("mtkfb_probe end\n"); + return r; +} + + +/* Called when the device is being detached from the driver */ +static int mtkfb_remove(struct device *dev) +{ + struct mtkfb_device *fbdev = dev_get_drvdata(dev); + enum mtkfb_state saved_state = fbdev->state; + + fbdev->state = MTKFB_DISABLED; + mtkfb_free_resources(fbdev, saved_state); + return 0; +} + +int mtkfb_ipo_init(void) +{ + return 0; +} + +static void mtkfb_shutdown(struct device *pdev) +{ + +} + +void mtkfb_clear_lcm(void) +{ + +} + +static const struct of_device_id mtkfb_of_ids[] = { + {.compatible = "mediatek,MTKFB",}, + {} +}; + +static struct platform_driver mtkfb_driver = { + .driver = { + .name = MTKFB_DRIVER, +#ifdef CONFIG_PM + .pm = NULL, +#endif + .bus = &platform_bus_type, + .probe = mtkfb_probe, + .remove = mtkfb_remove, + .suspend = NULL, + .resume = NULL, + .shutdown = NULL, + .of_match_table = mtkfb_of_ids, + }, +}; + +/* Register both the driver and the device */ +int __init mtkfb_init(void) +{ + int r = 0; + + pr_error("mtkfb_init init"); + + if (platform_driver_register(&mtkfb_driver)) { + pr_error("failed to register mtkfb driver\n"); + r = -ENODEV; + } + return r; +} + +static void __exit mtkfb_cleanup(void) +{ + platform_driver_unregister(&mtkfb_driver); + +} + + +module_init(mtkfb_init); +module_exit(mtkfb_cleanup); + +MODULE_DESCRIPTION("MEDIATEK framebuffer driver"); +MODULE_AUTHOR("Xuecheng Zhang "); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/video/mt6755/mtkfb_vsync.c b/drivers/misc/mediatek/video/mt6755/mtkfb_vsync.c new file mode 100644 index 0000000000000000000000000000000000000000..1a41e4567aa016d0c7f1e5a0501dccd43401f496 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/mtkfb_vsync.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtkfb_vsync.h" +#include "primary_display.h" +#include "extd_info.h" + +#define VSYNC_DBG(...) pr_debug(__VA_ARGS__) + +#define VSYNC_INF(...) pr_debug(__VA_ARGS__) +#define VSYNC_WRN(...) pr_debug(__VA_ARGS__) +#define VSYNC_ERR(...) pr_debug(__VA_ARGS__) + +static size_t mtkfb_vsync_on; +#define MTKFB_VSYNC_LOG(fmt, arg...) \ +do { \ + if (mtkfb_vsync_on) \ + VSYNC_WRN(fmt, ##arg); \ +} while (0) + +#define MTKFB_VSYNC_FUNC() \ + do { \ + if (mtkfb_vsync_on) \ + VSYNC_WRN("[Func]%s\n", __func__); \ + } while (0) + +static EXTD_DRIVER *extd_driver[DEV_MAX_NUM - 1]; + +static dev_t mtkfb_vsync_devno; +static struct cdev *mtkfb_vsync_cdev; +static struct class *mtkfb_vsync_class; + +DEFINE_SEMAPHORE(mtkfb_vsync_sem); + +void mtkfb_vsync_log_enable(int enable) +{ + mtkfb_vsync_on = enable; + MTKFB_VSYNC_LOG("mtkfb_vsync log %s\n", enable ? "enabled" : "disabled"); +} + +static int mtkfb_vsync_open(struct inode *inode, struct file *file) +{ + VSYNC_DBG("driver open\n"); + return 0; +} + +static ssize_t mtkfb_vsync_read(struct file *file, char __user *data, size_t len, loff_t *ppos) +{ + VSYNC_DBG("driver read\n"); + return 0; +} + +static int mtkfb_vsync_release(struct inode *inode, struct file *file) +{ + VSYNC_DBG("driver release\n"); + VSYNC_DBG("reset overlay engine\n"); + return 0; +} + +static int mtkfb_vsync_flush(struct file *a_pstFile, fl_owner_t a_id) +{ + /* To Do : error handling here */ + return 0; +} + +static long mtkfb_vsync_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + MTKFB_VSYNC_FUNC(); + switch (cmd) { + case MTKFB_VSYNC_IOCTL: + { + MTKFB_VSYNC_LOG("[MTKFB_VSYNC]: enter MTKFB_VSYNC_IOCTL\n"); + extd_driver[DEV_MHL] = EXTD_HDMI_Driver(); + extd_driver[DEV_EINK] = EXTD_EPD_Driver(); + if (arg == MTKFB_VSYNC_SOURCE_HDMI || arg == MTKFB_VSYNC_SOURCE_EPD) { + if (down_interruptible(&mtkfb_vsync_sem)) { + pr_err("[mtkfb_vsync_ioctl] can't get semaphore,%d\n", __LINE__); + msleep(20); + return ret; + } + + if (extd_driver[arg-1]->wait_vsync) + ret = extd_driver[arg-1]->wait_vsync(); + else + ret = -EFAULT; + + up(&mtkfb_vsync_sem); + pr_debug("[MTKFB_VSYNC]: leave MTKFB_VSYNC_IOCTL, %d, ret:%d\n", __LINE__, ret); + + return ret; + } + + if (down_interruptible(&mtkfb_vsync_sem)) { + pr_err("[mtkfb_vsync_ioctl] can't get semaphore,%d\n", __LINE__); + msleep(20); + return ret; + } + primary_display_wait_for_vsync(NULL); + up(&mtkfb_vsync_sem); + MTKFB_VSYNC_LOG("[MTKFB_VSYNC]: leave MTKFB_VSYNC_IOCTL\n"); + } + break; + } + return ret; +} + + +#ifdef CONFIG_COMPAT +static long mtkfb_vsync_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret = 0; + + ret = mtkfb_vsync_unlocked_ioctl(file, cmd, arg); + return ret; +} +#endif + +static const struct file_operations mtkfb_vsync_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = mtkfb_vsync_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = mtkfb_vsync_compat_ioctl, +#endif + .open = mtkfb_vsync_open, + .release = mtkfb_vsync_release, + .flush = mtkfb_vsync_flush, + .read = mtkfb_vsync_read, +}; + +static int mtkfb_vsync_probe(struct platform_device *pdev) +{ + struct class_device; + struct class_device *class_dev = NULL; + + pr_err("\n=== MTKFB_VSYNC probe ===\n"); + + if (alloc_chrdev_region(&mtkfb_vsync_devno, 0, 1, MTKFB_VSYNC_DEVNAME)) { + VSYNC_ERR("can't get device major number...\n"); + return -EFAULT; + } + + pr_err("get device major number (%d)\n", mtkfb_vsync_devno); + + mtkfb_vsync_cdev = cdev_alloc(); + mtkfb_vsync_cdev->owner = THIS_MODULE; + mtkfb_vsync_cdev->ops = &mtkfb_vsync_fops; + + cdev_add(mtkfb_vsync_cdev, mtkfb_vsync_devno, 1); + + mtkfb_vsync_class = class_create(THIS_MODULE, MTKFB_VSYNC_DEVNAME); + class_dev = + (struct class_device *)device_create(mtkfb_vsync_class, NULL, mtkfb_vsync_devno, NULL, + MTKFB_VSYNC_DEVNAME); + + VSYNC_INF("probe is done\n"); + return 0; +} + +static int mtkfb_vsync_remove(struct platform_device *pdev) +{ + VSYNC_INF("device remove\n"); + return 0; +} + +static void mtkfb_vsync_shutdown(struct platform_device *pdev) +{ + pr_err("mtkfb_vsync device shutdown\n"); +} + +static int mtkfb_vsync_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + return 0; +} + +static int mtkfb_vsync_resume(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver mtkfb_vsync_driver = { + .probe = mtkfb_vsync_probe, + .remove = mtkfb_vsync_remove, + .shutdown = mtkfb_vsync_shutdown, + .suspend = mtkfb_vsync_suspend, + .resume = mtkfb_vsync_resume, + .driver = { + .name = MTKFB_VSYNC_DEVNAME, + }, +}; + +static void mtkfb_vsync_device_release(struct device *dev) +{ +} + +static u64 mtkfb_vsync_dmamask = ~(u32) 0; + +static struct platform_device mtkfb_vsync_device = { + .name = MTKFB_VSYNC_DEVNAME, + .id = 0, + .dev = { + .release = mtkfb_vsync_device_release, + .dma_mask = &mtkfb_vsync_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = 0, +}; + +static int __init mtkfb_vsync_init(void) +{ + VSYNC_INF("initializeing driver...\n"); + + if (platform_device_register(&mtkfb_vsync_device)) { + VSYNC_ERR("failed to register device\n"); + return -ENODEV; + } + + if (platform_driver_register(&mtkfb_vsync_driver)) { + VSYNC_ERR("failed to register driver\n"); + platform_device_unregister(&mtkfb_vsync_device); + return -ENODEV; + } + + return 0; +} + +static void __exit mtkfb_vsync_exit(void) +{ + cdev_del(mtkfb_vsync_cdev); + unregister_chrdev_region(mtkfb_vsync_devno, 1); + + platform_driver_unregister(&mtkfb_vsync_driver); + platform_device_unregister(&mtkfb_vsync_device); + + device_destroy(mtkfb_vsync_class, mtkfb_vsync_devno); + class_destroy(mtkfb_vsync_class); + + VSYNC_INF("exit driver...\n"); +} + +/* module_init(mtkfb_vsync_init); */ +/* module_exit(mtkfb_vsync_exit); */ + +MODULE_DESCRIPTION("MediaTek FB VSYNC Driver"); +MODULE_AUTHOR("Zaikuo Wang "); diff --git a/drivers/misc/mediatek/video/mt6755/primary_display.c b/drivers/misc/mediatek/video/mt6755/primary_display.c new file mode 100644 index 0000000000000000000000000000000000000000..c059ae9f95773e6d63786c77a5496fab1b322d7a --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/primary_display.c @@ -0,0 +1,6868 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtk_ion.h" +#include "ion_drv.h" +/*#include */ +/*#include */ +/*#include */ +/*#include "mach/eint.h"*/ +#if defined(CONFIG_MTK_LEGACY) +#include +#endif +#include "mt-plat/mt_smi.h" +#include "m4u.h" +#include +#include "mt_vcorefs_manager.h" + +#include "disp_drv_platform.h" +#include "disp_debug.h" +#include "disp_log.h" +#include "disp_lcm.h" +#include "disp_utils.h" +#include "mtkfb.h" +#include "ddp_hal.h" +#include "ddp_dump.h" +#include "ddp_path.h" +#include "ddp_drv.h" +#include "ddp_reg.h" +#include "disp_session.h" +#include "primary_display.h" +#include "cmdq_def.h" +#include "cmdq_record.h" +#include "cmdq_reg.h" +#include "cmdq_core.h" +#include "ddp_manager.h" +#include "mtkfb_fence.h" +#include "mtkfb_debug.h" +#include "disp_recorder.h" +#include "fbconfig_kdebug.h" +#include "ddp_mmp.h" +#include "mtk_sync.h" +#include "ddp_irq.h" +#include "disp_session.h" +#include "disp_helper.h" +#include "ddp_reg.h" +#include "mtk_disp_mgr.h" +#include "ddp_dsi.h" +#include "m4u.h" +#include "m4u_priv.h" +#include "mt_spm.h" +#include "mtkfb_console.h" +#include "mt_idle.h" +#include "mt_boot_common.h" +#if defined(CONFIG_MTK_LEGACY) +#include +/* #include */ +#else +#include "disp_dts_gpio.h" +#endif +#include "ddp_clkmgr.h" +#include "mt_smi.h" + +#include "disp_lowpower.h" +#include "disp_recovery.h" +#include "mt_spm_sodi_cmdq.h" +#include "mt_spm_reg.h" +#include "mt_spm_idle.h" + +#define FRM_UPDATE_SEQ_CACHE_NUM (DISP_INTERNAL_BUFFER_COUNT+1) + +static disp_internal_buffer_info *decouple_buffer_info[DISP_INTERNAL_BUFFER_COUNT]; +static disp_internal_buffer_info *freeze_buffer_info;/*freeze mode*/ +static disp_internal_buffer_info *gmo_decouple_buffer_info; +static RDMA_CONFIG_STRUCT decouple_rdma_config; +static WDMA_CONFIG_STRUCT decouple_wdma_config; +static disp_mem_output_config mem_config; +static unsigned int primary_session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0); +static disp_frm_seq_info frm_update_sequence[FRM_UPDATE_SEQ_CACHE_NUM]; +static unsigned int frm_update_cnt; +static unsigned int gPresentFenceIndex; +static unsigned int g_keep; +static unsigned int g_skip; +static DISP_POWER_STATE power_stat_backup; +static int session_mode_backup; +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI +static struct switch_dev disp_switch_data; +#endif +static struct hrtimer cmd_mode_update_timer; +/* static ktime_t cmd_mode_update_timer_period; */ +static int is_fake_timer_inited; + +static struct task_struct *primary_display_switch_dst_mode_task; +static struct task_struct *present_fence_release_worker_task; +static struct task_struct *primary_path_aal_task; +static struct task_struct *decouple_update_rdma_config_thread; +static struct task_struct *primary_delay_trigger_task; +static struct task_struct *decouple_trigger_thread; +static struct sg_table table; + +static int primary_display_recovery_thread(void *data); +static int decouple_mirror_update_rdma_config_thread(void *data); +static int decouple_trigger_worker_thread(void *data); + +struct task_struct *primary_display_frame_update_task = NULL; +wait_queue_head_t primary_display_frame_update_wq; +atomic_t primary_display_frame_update_event = ATOMIC_INIT(0); +DISP_PRIMARY_PATH_MODE primary_display_mode = DIRECT_LINK_MODE; +int primary_display_def_dst_mode = 0; +int primary_display_cur_dst_mode = 0; +unsigned long long last_primary_trigger_time; +bool is_switched_dst_mode = false; +int primary_trigger_cnt = 0; +atomic_t decouple_update_rdma_event = ATOMIC_INIT(0); +DECLARE_WAIT_QUEUE_HEAD(decouple_update_rdma_wq); +atomic_t decouple_trigger_event = ATOMIC_INIT(0); +DECLARE_WAIT_QUEUE_HEAD(decouple_trigger_wq); +wait_queue_head_t primary_display_present_fence_wq; +atomic_t primary_display_present_fence_update_event = ATOMIC_INIT(0); +static unsigned int _need_lfr_check(void); + +/* dvfs */ +static atomic_t dvfs_ovl_req_status = ATOMIC_INIT(OPPI_UNREQ); +static int dvfs_last_ovl_req = OPPI_UNREQ; +static atomic_t delayed_trigger_kick = ATOMIC_INIT(0); +/*detect hang and recovery*/ +static struct task_struct *primary_display_Recovery_task; +static wait_queue_head_t primary_recovery_task_wq; +static atomic_t primary_recovery_task_wakeup = ATOMIC_INIT(0); + +typedef struct { + DISP_POWER_STATE state; + unsigned int lcm_fps; + int max_layer; + int need_trigger_overlay; + int need_trigger_ovl1to2; + int need_trigger_dcMirror_out; + DISP_PRIMARY_PATH_MODE mode; + unsigned int session_id; + int session_mode; + int ovl1to2_mode; + unsigned int last_vsync_tick; + unsigned long framebuffer_mva; + unsigned long framebuffer_va; + struct mutex lock; + struct mutex capture_lock; + struct mutex switch_dst_lock; + disp_lcm_handle *plcm; + cmdqRecHandle cmdq_handle_config_esd; + cmdqRecHandle cmdq_handle_config; + disp_path_handle dpmgr_handle; + disp_path_handle ovl2mem_path_handle; + cmdqRecHandle cmdq_handle_ovl1to2_config; + cmdqRecHandle cmdq_handle_trigger; + char *mutex_locker; + int vsync_drop; + unsigned int dc_buf_id; + unsigned int dc_buf[DISP_INTERNAL_BUFFER_COUNT]; + unsigned int freeze_buf; + unsigned int force_fps_keep_count; + unsigned int force_fps_skip_count; + cmdqBackupSlotHandle cur_config_fence; + cmdqBackupSlotHandle subtractor_when_free; + cmdqBackupSlotHandle rdma_buff_info; + cmdqBackupSlotHandle ovl_status_info; + cmdqBackupSlotHandle ovl_config_time; + + int is_primary_sec; +} display_primary_path_context; + +#define pgc _get_context() + +static int smart_ovl_try_switch_mode_nolock(void); + +static display_primary_path_context *_get_context(void) +{ + static int is_context_inited; + static display_primary_path_context g_context; + + if (!is_context_inited) { + memset((void *)&g_context, 0, sizeof(display_primary_path_context)); + is_context_inited = 1; + } + + return &g_context; +} + +static void _primary_path_lock(const char *caller) +{ + dprec_logger_start(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0); + disp_sw_mutex_lock(&(pgc->lock)); + pgc->mutex_locker = (char *)caller; +} + +static void _primary_path_unlock(const char *caller) +{ + pgc->mutex_locker = NULL; + disp_sw_mutex_unlock(&(pgc->lock)); + dprec_logger_done(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0); +} + +static const char *session_mode_spy(unsigned int mode) +{ + switch (mode) { + case DISP_SESSION_DIRECT_LINK_MODE: + return "DIRECT_LINK"; + case DISP_SESSION_DIRECT_LINK_MIRROR_MODE: + return "DIRECT_LINK_MIRROR"; + case DISP_SESSION_DECOUPLE_MODE: + return "DECOUPLE"; + case DISP_SESSION_DECOUPLE_MIRROR_MODE: + return "DECOUPLE_MIRROR"; + case DISP_SESSION_RDMA_MODE: + return "RDMA_MODE"; + default: + return "UNKNOWN"; + } +} + +int primary_display_is_directlink_mode(void) +{ + DISP_MODE mode = pgc->session_mode; + + if (mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE || mode == DISP_SESSION_DIRECT_LINK_MODE) + return 1; + else + return 0; +} + +DISP_MODE primary_get_sess_mode(void) +{ + return pgc->session_mode; +} + +unsigned int primary_get_sess_id(void) +{ + return pgc->session_id; +} + +disp_lcm_handle *primary_get_lcm(void) +{ + return pgc->plcm; +} +void *primary_get_dpmgr_handle(void) +{ + return pgc->dpmgr_handle; +} + +void *primary_get_ovl2mem_handle(void) +{ + return pgc->ovl2mem_path_handle; +} +int primary_display_is_decouple_mode(void) +{ + DISP_MODE mode = pgc->session_mode; + + if (mode == DISP_SESSION_DECOUPLE_MODE || mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) + return 1; + else + return 0; +} + +int _is_mirror_mode(DISP_MODE mode) +{ + if (mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE || mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) + return 1; + else + return 0; +} +int primary_display_is_mirror_mode(void) +{ + return _is_mirror_mode(pgc->session_mode); +} + +int primary_is_sec(void) +{ + return pgc->is_primary_sec; +} + +void _primary_path_switch_dst_lock(void) +{ + mutex_lock(&(pgc->switch_dst_lock)); +} + +void _primary_path_switch_dst_unlock(void) +{ + mutex_unlock(&(pgc->switch_dst_lock)); +} + +static int _disp_primary_path_switch_dst_mode_thread(void *data) +{ + while (1) { + msleep(1000); + + if (((sched_clock() - last_primary_trigger_time) / 1000) > 500000) { /* 500ms not trigger disp */ + primary_display_switch_dst_mode(0); /* switch to cmd mode */ + is_switched_dst_mode = true; + } + if (kthread_should_stop()) + break; + } + return 0; +} + +static DECLARE_WAIT_QUEUE_HEAD(display_state_wait_queue); + +DISP_POWER_STATE primary_get_state(void) +{ + return pgc->state; +} +static DISP_POWER_STATE primary_set_state(DISP_POWER_STATE new_state) +{ + DISP_POWER_STATE old_state = pgc->state; + + pgc->state = new_state; + DISPDBG("%s %d to %d\n", __func__, old_state, new_state); + wake_up(&display_state_wait_queue); + return old_state; +} +/* use MAX_SCHEDULE_TIMEOUT to wait for ever + * NOTES: primary_path_lock should NOT be held when call this func !!!!!!!! + */ +#define __primary_display_wait_state(condition, timeout) \ +({ \ + wait_event_timeout(display_state_wait_queue, condition, timeout);\ +}) + +long primary_display_wait_state(DISP_POWER_STATE state, long timeout) +{ + long ret; + + ret = __primary_display_wait_state(primary_get_state() == state, timeout); + return ret; +} +long primary_display_wait_not_state(DISP_POWER_STATE state, long timeout) +{ + long ret; + + ret = __primary_display_wait_state(primary_get_state() != state, timeout); + return ret; +} + +int dynamic_debug_msg_print(unsigned int mva, int w, int h, int pitch_in_bytes, int bytes_per_pix) +{ + int ret = 0; + unsigned int layer_size = pitch_in_bytes * h; + unsigned int real_mva = 0; + unsigned long kva = 0; + unsigned int real_size = 0, mapped_size = 0; + unsigned int bg_color = 0, fg_color = 0; + + if (disp_helper_get_option(DISP_OPT_SHOW_VISUAL_DEBUG_INFO)) { + static MFC_HANDLE mfc_handle; + + m4u_query_mva_info(mva, layer_size, &real_mva, &real_size); + if (ret < 0) { + pr_debug("m4u_query_mva_info error\n"); + return -1; + } + ret = m4u_mva_map_kernel(real_mva, real_size, &kva, &mapped_size); + if (ret < 0) { + pr_debug("m4u_mva_map_kernel fail.\n"); + return -1; + } + if (layer_size > mapped_size) { + pr_debug("warning: layer size > mapped size\n"); + goto err1; + } + +#define RGB888_To_RGB565(x) ((((x) & 0xF80000) >> 8) | \ + (((x) & 0x00FC00) >> 5) | \ + (((x) & 0x0000F8) >> 3)) + fg_color = bytes_per_pix == 2 ? RGB888_To_RGB565(DAL_COLOR_WHITE) : DAL_COLOR_WHITE; + bg_color = bytes_per_pix == 2 ? RGB888_To_RGB565(DAL_COLOR_RED) : DAL_COLOR_RED; + ret = MFC_Open_Ex_v2(&mfc_handle, + (void *)kva, + w, + h, + pitch_in_bytes, + bytes_per_pix, + DAL_COLOR_WHITE, + DAL_COLOR_RED); + if (ret != MFC_STATUS_OK) + goto err1; + screen_logger_print(mfc_handle); + MFC_Close(mfc_handle); +err1: + m4u_mva_unmap_kernel(real_mva, real_size, kva); + } + return 0; +} + +static int primary_show_basic_debug_info(struct disp_frame_cfg_t *cfg) +{ + int i; + fpsEx fps; + char disp_tmp[20]; + int dst_layer_id = 0; + int bytes_per_pixel = 0; + + dprec_logger_get_result_value(DPREC_LOGGER_RDMA0_TRANSFER_1SECOND, &fps); + snprintf(disp_tmp, sizeof(disp_tmp), ",rdma_fps:%lld.%02lld,", fps.fps, fps.fps_low); + screen_logger_add_message("rdma_fps", MESSAGE_REPLACE, disp_tmp); + + dprec_logger_get_result_value(DPREC_LOGGER_OVL_FRAME_COMPLETE_1SECOND, &fps); + snprintf(disp_tmp, sizeof(disp_tmp), "ovl_fps:%lld.%02lld,", fps.fps, fps.fps_low); + screen_logger_add_message("ovl_fps", MESSAGE_REPLACE, disp_tmp); + + dprec_logger_get_result_value(DPREC_LOGGER_PQ_TRIGGER_1SECOND, &fps); + snprintf(disp_tmp, sizeof(disp_tmp), "PQ_trigger:%lld.%02lld,", fps.fps, fps.fps_low); + screen_logger_add_message("PQ trigger", MESSAGE_REPLACE, disp_tmp); + + snprintf(disp_tmp, sizeof(disp_tmp), primary_display_is_video_mode() ? "vdo," : "cmd,"); + screen_logger_add_message("mode", MESSAGE_REPLACE, disp_tmp); + + for (i = 0; i < cfg->input_layer_num; i++) { + if (cfg->input_cfg[i].tgt_offset_y == 0 && + cfg->input_cfg[i].layer_enable) { + dst_layer_id = dst_layer_id > cfg->input_cfg[i].layer_id ? + dst_layer_id : cfg->input_cfg[i].layer_id; + } + } + + bytes_per_pixel = cfg->input_cfg[dst_layer_id].src_fmt & 0xff; + dynamic_debug_msg_print((unsigned int)(unsigned long)cfg->input_cfg[dst_layer_id].src_phy_addr, + cfg->input_cfg[dst_layer_id].tgt_width, + cfg->input_cfg[dst_layer_id].tgt_height, + cfg->input_cfg[dst_layer_id].src_pitch * bytes_per_pixel, + bytes_per_pixel); + return 0; +} + +/* static int primary_dynamic_debug(unsigned int mva, unsigned int pitch, unsigned int w, unsigned int h, + unsigned int x_pos, unsigned int block_sz) +{ + unsigned int real_mva, real_size, map_size; + unsigned long map_va; + int ret; + + unsigned char *buf_va; + int x, y; + + if (!disp_helper_get_option(DISP_OPT_DYNAMIC_DEBUG)) + return 0; + + ret = m4u_query_mva_info(mva, 0, &real_mva, &real_size); + if (ret) { + pr_err("%s error to query mva = 0x%x\n", __func__, mva); + return -1; + } + ret = m4u_mva_map_kernel(real_mva, real_size, &map_va, &map_size); + if (ret) { + pr_err("%s error to map mva = 0x%x\n", __func__, real_mva); + return -1; + } + + buf_va = (unsigned char *)(map_va + (mva - real_mva)); + if (x_pos + block_sz > w) + block_sz = w/2; + if (block_sz > h) + block_sz = h; + + for (y = 0; y < block_sz; y++) { + for (x = 0; x < block_sz * 4; x++) + buf_va[x_pos * 4 + x + y * pitch] = 255; + } + + m4u_mva_unmap_kernel(real_mva, real_size, map_va); + + return 0; +} */ + +/*************************** fps calculate ************************/ +#if 1 +#define FPS_ARRAY_SZ 30 +struct fps_ctx_t { + unsigned long long last_trig; + unsigned int array[FPS_ARRAY_SZ]; + unsigned int total; + unsigned int wnd_sz; + unsigned int cur_wnd_sz; + struct mutex lock; + int is_inited; +} primary_fps_ctx; + +/* static struct task_struct *fps_monitor; */ +/* static int fps_monitor_thread(void *data); */ + +static int _fps_ctx_reset(struct fps_ctx_t *fps_ctx, int reserve_num) +{ + int i; + + if (reserve_num >= FPS_ARRAY_SZ) { + pr_err("%s error to reset, reserve=%d\n", __func__, reserve_num); + BUG(); + } + for (i = reserve_num; i < FPS_ARRAY_SZ; i++) + fps_ctx->array[i] = 0; + + if (reserve_num < fps_ctx->cur_wnd_sz) + fps_ctx->cur_wnd_sz = reserve_num; + + /* re-calc total */ + fps_ctx->total = 0; + for (i = 0; i < fps_ctx->cur_wnd_sz; i++) + fps_ctx->total += fps_ctx->array[i]; + + return 0; +} + +static int _fps_ctx_update(struct fps_ctx_t *fps_ctx, unsigned int fps, unsigned long long time_ns) +{ + int i; + + fps_ctx->total -= fps_ctx->array[fps_ctx->wnd_sz-1]; + + for (i = fps_ctx->wnd_sz - 1; i > 0; i--) + fps_ctx->array[i] = fps_ctx->array[i-1]; + + fps_ctx->array[0] = fps; + + fps_ctx->total += fps_ctx->array[0]; + if (fps_ctx->cur_wnd_sz < fps_ctx->wnd_sz) + fps_ctx->cur_wnd_sz++; + + fps_ctx->last_trig = time_ns; + + return 0; +} + +static int fps_ctx_init(struct fps_ctx_t *fps_ctx, int wnd_sz) +{ + if (fps_ctx->is_inited) + return 0; + + memset(fps_ctx, 0, sizeof(*fps_ctx)); + mutex_init(&fps_ctx->lock); + + if (wnd_sz > FPS_ARRAY_SZ) { + pr_err("%s error: wnd_sz = %d\n", __func__, wnd_sz); + wnd_sz = FPS_ARRAY_SZ; + } + fps_ctx->wnd_sz = wnd_sz; + + /* fps_monitor = kthread_create(fps_monitor_thread, NULL, "fps_monitor");*/ + /* wake_up_process(fps_monitor); */ + fps_ctx->is_inited = 1; + + return 0; +} + +static unsigned int _fps_ctx_calc_cur_fps(struct fps_ctx_t *fps_ctx, unsigned long long cur_ns) +{ + unsigned long long delta; + unsigned long long fps = 1000000000; + + delta = cur_ns - fps_ctx->last_trig; + do_div(fps, delta); + + if (fps > 120ULL) + fps = 120ULL; + + return (unsigned int)fps; +} + +static unsigned int _fps_ctx_get_avg_fps(struct fps_ctx_t *fps_ctx) +{ + unsigned int avg_fps; + + if (fps_ctx->cur_wnd_sz == 0) + return 0; + avg_fps = fps_ctx->total / fps_ctx->cur_wnd_sz; + return avg_fps; +} +static unsigned int _fps_ctx_get_avg_fps_ext(struct fps_ctx_t *fps_ctx, unsigned int abs_fps) +{ + unsigned int avg_fps; + + avg_fps = (fps_ctx->total + abs_fps) / (fps_ctx->cur_wnd_sz + 1); + return avg_fps; +} +#endif +#if 0 +static int _fps_ctx_check_drastic_change(struct fps_ctx_t *fps_ctx, unsigned int abs_fps) +{ + unsigned int avg_fps; + + avg_fps = _fps_ctx_get_avg_fps(fps_ctx); + + /* if long time no trigger, ex:500ms + * abs_fps=1, avg_fps may be 58 + * we should let avg_fps decline rapidly */ + if (abs_fps < avg_fps / 4 || abs_fps > avg_fps * 4) { + _fps_ctx_reset(fps_ctx, fps_ctx->cur_wnd_sz / 4); + } else if (abs_fps < avg_fps / 2 || abs_fps > avg_fps * 2) { + if (fps_ctx->cur_wnd_sz >= 2) + _fps_ctx_reset(fps_ctx, fps_ctx->cur_wnd_sz / 2); + } + + return 0; +} +#endif +static int fps_ctx_update(struct fps_ctx_t *fps_ctx) +{ + unsigned int abs_fps, avg_fps; + unsigned long long ns = sched_clock(); + + mutex_lock(&fps_ctx->lock); + abs_fps = _fps_ctx_calc_cur_fps(fps_ctx, ns); + + /* _fps_ctx_check_drastic_change(fps_ctx, abs_fps); */ + + avg_fps = _fps_ctx_get_avg_fps(fps_ctx); + + /* if long time no trigger, ex:500ms + * abs_fps=1, avg_fps may be 58 + * we should let avg_fps decline rapidly */ + + if (abs_fps < avg_fps / 2 && avg_fps > 10) + _fps_ctx_reset(fps_ctx, 0); + + + _fps_ctx_update(fps_ctx, abs_fps, ns); + + MMProfileLogEx(ddp_mmp_get_events()->fps_set, MMProfileFlagPulse, abs_fps, fps_ctx->cur_wnd_sz); + mutex_unlock(&fps_ctx->lock); + return 0; +} + +static int fps_ctx_get_fps(struct fps_ctx_t *fps_ctx, unsigned int *fps, int *stable) +{ + unsigned long long ns = sched_clock(); + + unsigned int abs_fps = 0, avg_fps = 0; + + *stable = 1; + mutex_lock(&fps_ctx->lock); + + abs_fps = _fps_ctx_calc_cur_fps(fps_ctx, ns); + avg_fps = _fps_ctx_get_avg_fps(fps_ctx); + + /* if long time no trigger, we should pull fps down */ + if (abs_fps < avg_fps/2 && avg_fps > 10) { + _fps_ctx_reset(fps_ctx, 0); + *fps = abs_fps; + *stable = 0; + goto done; + } + + if (fps_ctx->cur_wnd_sz < fps_ctx->wnd_sz/2) + *stable = 0; + + if (abs_fps < avg_fps) + *fps = _fps_ctx_get_avg_fps_ext(fps_ctx, abs_fps); + else + *fps = avg_fps; + +done: + MMProfileLogEx(ddp_mmp_get_events()->fps_get, MMProfileFlagPulse, *fps, *stable); + mutex_unlock(&fps_ctx->lock); + return 0; +} +#if 0 +static int fps_ctx_set_wnd_sz(struct fps_ctx_t *fps_ctx, unsigned int wnd_sz) +{ + int i; + + if (!fps_ctx->is_inited) + return fps_ctx_init(fps_ctx, wnd_sz); + + if (wnd_sz > FPS_ARRAY_SZ) { + pr_err("error: %s wnd_sz=%d\n", __func__, wnd_sz); + return -1; + } + mutex_lock(&fps_ctx->lock); + + fps_ctx->total = 0; + fps_ctx->wnd_sz = wnd_sz; + + for (i = 0; i < wnd_sz; i++) + fps_ctx->total += fps_ctx->array[i]; + + mutex_unlock(&fps_ctx->lock); + return 0; +} +static int fps_ctx_get_wnd_sz(struct fps_ctx_t *fps_ctx, unsigned int *cur_wnd, unsigned int *max_wnd) +{ + mutex_lock(&fps_ctx->lock); + if (cur_wnd) + *cur_wnd = fps_ctx->cur_wnd_sz; + if (max_wnd) + *max_wnd = fps_ctx->wnd_sz; + mutex_unlock(&fps_ctx->lock); + return 0; +} + +int primary_fps_ctx_set_wnd_sz(unsigned int wnd_sz) +{ + return fps_ctx_set_wnd_sz(&primary_fps_ctx, wnd_sz); +} + + +static int fps_monitor_thread(void *data) +{ + + + msleep(16000); + while (1) { + int fps, stable; + + msleep(20); + _primary_path_lock(__func__); + fps_ctx_get_fps(&primary_fps_ctx, &fps, &stable); + _primary_path_unlock(__func__); + } + + return 0; +} +#endif +/*********************** fps calculate finish *********************************/ + +/*********************** idle manager *****************************************/ +int primary_display_get_debug_state(char *stringbuf, int buf_len) +{ + int len = 0; + LCM_PARAMS *lcm_param = disp_lcm_get_params(pgc->plcm); + LCM_DRIVER *lcm_drv = pgc->plcm->drv; + + len += scnprintf(stringbuf + len, buf_len - len, + "|--------------------------------------------------------------------------------------|\n"); + len += scnprintf(stringbuf + len, buf_len - len, + "|********Primary Display Path General Information********\n"); + len += scnprintf(stringbuf + len, buf_len - len, "|Primary Display is %s\n", + dpmgr_path_is_idle(pgc->dpmgr_handle) ? "idle" : "busy"); + + if (mutex_trylock(&(pgc->lock))) { + mutex_unlock(&(pgc->lock)); + len += scnprintf(stringbuf + len, buf_len - len, + "|primary path global mutex is free\n"); + } else { + len += scnprintf(stringbuf + len, buf_len - len, + "|primary path global mutex is hold by [%s]\n", pgc->mutex_locker); + } + + if (lcm_param && lcm_drv) + len += scnprintf(stringbuf + len, buf_len - len, + "|LCM Driver=[%s]\tResolution=%dx%d,Interface:%s\n", lcm_drv->name, + lcm_param->width, lcm_param->height, + (lcm_param->type == LCM_TYPE_DSI) ? "DSI" : "Other"); + len += scnprintf(stringbuf + len, buf_len - len, + "|State=%s\tlcm_fps=%d\tmax_layer=%d\tmode:%d\tvsync_drop=%d\n", + pgc->state == DISP_ALIVE ? "Alive" : "Sleep", pgc->lcm_fps, pgc->max_layer, + pgc->mode, pgc->vsync_drop); + len += scnprintf(stringbuf + len, buf_len - len, + "|cmdq_handle_config=%p\tcmdq_handle_trigger=%p\tdpmgr_handle=%p\tovl2mem_path_handle=%p\n", + pgc->cmdq_handle_config, pgc->cmdq_handle_trigger, pgc->dpmgr_handle, + pgc->ovl2mem_path_handle); + len += scnprintf(stringbuf + len, buf_len - len, + "|PathMode:%s\n", session_mode_spy(pgc->session_mode)); + len += scnprintf(stringbuf + len, buf_len - len, "|Current display driver status=%s + %s\n", + primary_display_is_video_mode() ? "video mode" : "cmd mode", + primary_display_cmdq_enabled() ? "CMDQ Enabled" : "CMDQ Disabled"); + + return len; +} + +static DISP_MODULE_ENUM _get_dst_module_by_lcm(disp_lcm_handle *plcm) +{ + DISP_MODULE_ENUM ret = DISP_MODULE_UNKNOWN; + + if (plcm == NULL) { + DISPERR("plcm is null\n"); + return ret; + } + + if (plcm->params->type == LCM_TYPE_DSI) { + if (plcm->lcm_if_id == LCM_INTERFACE_DSI0) + ret = DISP_MODULE_DSI0; + else if (plcm->lcm_if_id == LCM_INTERFACE_DSI1) + ret = DISP_MODULE_DSI1; + else if (plcm->lcm_if_id == LCM_INTERFACE_DSI_DUAL) + ret = DISP_MODULE_DSIDUAL; + else + ret = DISP_MODULE_DSI0; + } else if (plcm->params->type == LCM_TYPE_DPI) { + ret = DISP_MODULE_DPI; + } else { + DISPERR("can't find primary path dst module\n"); + ret = DISP_MODULE_UNKNOWN; + } + return ret; +} + + +/*************************************************************** +***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU +*** 1.wait idle: N N Y Y +*** 2.lcm update: N Y N Y +*** 3.path start: idle->Y Y idle->Y Y +*** 4.path trigger: idle->Y Y idle->Y Y +*** 5.mutex enable: N N idle->Y Y +*** 6.set cmdq dirty: N Y N N +*** 7.flush cmdq: Y Y N N +****************************************************************/ + +int _should_wait_path_idle(void) +{ + /***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU + *** 1.wait idle: N N Y Y */ + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) + return 0; + else + return 0; + + } else { + if (primary_display_is_video_mode()) + return dpmgr_path_is_busy(pgc->dpmgr_handle); + else + return dpmgr_path_is_busy(pgc->dpmgr_handle); + + } +} + +int _should_update_lcm(void) +{ + int ret = 0; +/***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU +*** 2.lcm update: N Y N Y **/ + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) + ret = 0; + else { + /* lcm_update can't use cmdq now */ + ret = 0; + } + } else { + if (primary_display_is_video_mode()) + ret = 0; + else + ret = 1; + } + return ret; +} + +int _should_start_path(void) +{ +/***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU +*** 3.path start: idle->Y Y idle->Y Y ***/ + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) { + return 0; + /* return dpmgr_path_is_idle(pgc->dpmgr_handle); */ + } else { + return 0; + } + } else { + if (primary_display_is_video_mode()) + return dpmgr_path_is_idle(pgc->dpmgr_handle); + else + return 1; + + } +} + +int _should_trigger_path(void) +{ +/***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU +*** 4.path trigger: idle->Y Y idle->Y Y +*** 5.mutex enable: N N idle->Y Y ***/ + + /* this is not a perfect design, we can't decide path trigger(ovl/rdma/dsi..) separately with mutex enable */ + /* but it's lucky because path trigger and mutex enable is the same w/o cmdq, and it's correct w/ CMDQ(Y+N). */ + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) { + return 0; + /* return dpmgr_path_is_idle(pgc->dpmgr_handle); */ + } else { + return 0; + } + } else { + if (primary_display_is_video_mode()) + return dpmgr_path_is_idle(pgc->dpmgr_handle); + else + return 1; + + } +} + +int _should_set_cmdq_dirty(void) +{ +/***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU +*** 6.set cmdq dirty: N Y N N ***/ + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) + return 0; + else + return 1; + + } else { + if (primary_display_is_video_mode()) + return 0; + else + return 0; + + } +} + +int _should_flush_cmdq_config_handle(void) +{ +/***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU +*** 7.flush cmdq: Y Y N N ***/ + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) + return 1; + else + return 1; + + } else { + if (primary_display_is_video_mode()) + return 0; + else + return 0; + + } +} + +int _should_reset_cmdq_config_handle(void) +{ + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) + return 1; + else + return 1; + + } else { + if (primary_display_is_video_mode()) + return 0; + else + return 0; + + } +} + +int _should_insert_wait_frame_done_token(void) +{ +/***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU +*** 7.flush cmdq: Y Y N N */ + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) + return 1; + else + return 1; + + } else { + if (primary_display_is_video_mode()) + return 0; + else + return 0; + + } +} + +int _should_trigger_interface(void) +{ + if (pgc->mode == DECOUPLE_MODE) + return 0; + else + return 1; + +} + +int _should_config_ovl_input(void) +{ + /* should extend this when display path dynamic switch is ready */ + if (pgc->mode == SINGLE_LAYER_MODE || pgc->mode == DEBUG_RDMA1_DSI0_MODE) + return 0; + else + return 1; + +} + +static long int get_current_time_us(void) +{ + struct timeval t; + + do_gettimeofday(&t); + return (t.tv_sec & 0xFFF) * 1000000 + t.tv_usec; +} + + +static enum hrtimer_restart _DISP_CmdModeTimer_handler(struct hrtimer *timer) +{ + DISPMSG("fake timer, wake up\n"); + dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); +#if 0 + if ((get_current_time_us() - pgc->last_vsync_tick) > 16666) { + dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + pgc->last_vsync_tick = get_current_time_us(); + } +#endif + hrtimer_forward_now(timer, ns_to_ktime(16666666)); + return HRTIMER_RESTART; +} + +int _init_vsync_fake_monitor(int fps) +{ + if (is_fake_timer_inited) + return 0; + + is_fake_timer_inited = 1; + + if (fps == 0) + fps = 6000; + + + hrtimer_init(&cmd_mode_update_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + cmd_mode_update_timer.function = _DISP_CmdModeTimer_handler; + hrtimer_start(&cmd_mode_update_timer, ns_to_ktime(16666666), HRTIMER_MODE_REL); + + return 0; +} + +static int _build_path_decouple(void) +{ + return 0; +} + +static int _build_path_single_layer(void) +{ + return 0; +} + +static int _build_path_debug_rdma1_dsi0(void) +{ + int ret = 0; + + DISP_MODULE_ENUM dst_module = 0; + + pgc->mode = DEBUG_RDMA1_DSI0_MODE; + + pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_SUB_RDMA1_DISP, pgc->cmdq_handle_config); + if (pgc->dpmgr_handle) { + DISPDBG("dpmgr create path SUCCESS(%p)\n", pgc->dpmgr_handle); + } else { + DISPERR("dpmgr create path FAIL\n"); + return -1; + } + + dst_module = _get_dst_module_by_lcm(pgc->plcm); + dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module); + + if (disp_helper_get_option(DISP_OPT_USE_M4U)) { + M4U_PORT_STRUCT sPort; + + sPort.ePortID = M4U_PORT_DISP_RDMA1; + sPort.Virtuality = disp_helper_get_option(DISP_OPT_USE_M4U); + sPort.Security = 0; + sPort.Distance = 1; + sPort.Direction = 0; + ret = m4u_config_port(&sPort); + if (ret == 0) { + DISPDBG("config M4U Port %s to %s SUCCESS\n", + ddp_get_module_name(DISP_MODULE_RDMA1), + disp_helper_get_option(DISP_OPT_USE_M4U) ? "virtual" : + "physical"); + } else { + DISPERR("config M4U Port %s to %s FAIL(ret=%d)\n", + ddp_get_module_name(DISP_MODULE_RDMA1), + disp_helper_get_option(DISP_OPT_USE_M4U) ? "virtual" : + "physical", ret); + return -1; + } + } + + dpmgr_set_lcm_utils(pgc->dpmgr_handle, pgc->plcm->drv); + + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); + + return ret; +} + +static void _cmdq_build_trigger_loop(void) +{ + int ret = 0; + + if (pgc->cmdq_handle_trigger == NULL) { + cmdqRecCreate(CMDQ_SCENARIO_TRIGGER_LOOP, &(pgc->cmdq_handle_trigger)); + DISPMSG("primary path trigger thread cmd handle=%p\n", pgc->cmdq_handle_trigger); + } + cmdqRecReset(pgc->cmdq_handle_trigger); + + if (primary_display_is_video_mode()) { + /* if (_need_lfr_check()) */ + /* ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_DSI0_EOF); */ + + ddp_mutex_set_sof_wait(dpmgr_path_get_mutex(pgc->dpmgr_handle), pgc->cmdq_handle_trigger, 0); + + cmdqRecWaitNoClear(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_EOF); + cmdqRecWaitNoClear(pgc->cmdq_handle_trigger, CMDQ_EVENT_MUTEX0_STREAM_EOF); + cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_EOF); + cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_EVENT_MUTEX0_STREAM_EOF); + + /* wait and clear rdma0_sof for vfp change */ + cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_SOF); + + /* for some module(like COLOR) to read hw register to GPR after frame done */ + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, + CMDQ_AFTER_STREAM_EOF, 0); + } else { + /* DSI command mode doesn't have mutex_stream_eof, need use CMDQ token instead */ + ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + + if (need_wait_esd_eof()) { + /* Wait esd config thread done. */ + ret = cmdqRecWaitNoClear(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_ESD_EOF); + } + /* ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_MDP_DSI0_TE_SOF); */ + /* for operations before frame transfer, such as waiting for DSI TE */ +#ifndef CONFIG_MTK_FPGA /* fpga has no TE signal */ + if (islcmconnected) + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_WAIT_LCM_TE, 0); +#endif + ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CABC_EOF); + /* cleat frame done token, now the config thread will not allowed to config registers. */ + /* remember that config thread's priority is higher than trigger thread, + * so all the config queued before will be applied then STREAM_EOF token be cleared */ + /* this is what CMDQ did as "Merge" */ + ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF); + + ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + + /* clear rdma EOF token before wait */ + ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_EOF); + + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_BEFORE_STREAM_SOF, 0); + + + if (disp_helper_get_option(DISP_OPT_SODI_SUPPORT)) + exit_pd_by_cmdq(pgc->cmdq_handle_trigger); + + /* enable mutex, only cmd mode need this */ + /* this is what CMDQ did as "Trigger" */ + dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_ENABLE); + + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, + CMDQ_AFTER_STREAM_SOF, 1); + + /* waiting for frame done, because we can't use mutex stream eof here, + * so need to let dpmanager help to decide which event to wait */ + /* most time we wait rdmax frame done event. */ + ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_EOF); + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, + CMDQ_WAIT_STREAM_EOF_EVENT, 0); + + /* dsi is not idle rightly after rdma frame done, + * so we need to polling about 1us for dsi returns to idle */ + /* do not polling dsi idle directly which will decrease CMDQ performance */ + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, + CMDQ_CHECK_IDLE_AFTER_STREAM_EOF, 0); + + /* for some module(like COLOR) to read hw register to GPR after frame done */ + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, + CMDQ_AFTER_STREAM_EOF, 0); + + if (disp_helper_get_option(DISP_OPT_SODI_SUPPORT)) + enter_pd_by_cmdq(pgc->cmdq_handle_trigger); + + /* polling DSI idle */ + /* ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x1401b00c, 0, 0x80000000); */ + /* polling wdma frame done */ + /* ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x140060A0, 1, 0x1); */ + + /* now frame done, config thread is allowed to config register now */ + ret = cmdqRecSetEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF); + ret = cmdqRecSetEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CABC_EOF); + /* RUN forever!!!! */ + BUG_ON(ret < 0); + } + + /* dump trigger loop instructions to check whether dpmgr_path_build_cmdq works correctly */ + DISPMSG("primary display BUILD cmdq trigger loop finished\n"); + + return; + +} + +void disp_spm_enter_cg_mode(void) +{ + MMProfileLogEx(ddp_mmp_get_events()->cg_mode, MMProfileFlagPulse, 0, 0); +} + +void disp_spm_enter_power_down_mode(void) +{ + MMProfileLogEx(ddp_mmp_get_events()->power_down_mode, MMProfileFlagPulse, 0, 0); +} + +#if 0 +static void _cmdq_build_monitor_loop(void) +{ + int ret = 0; + cmdqRecHandle g_cmdq_handle_monitor; + + cmdqRecCreate(CMDQ_SCENARIO_DISP_SCREEN_CAPTURE, &(g_cmdq_handle_monitor)); + DISPMSG("primary path monitor thread cmd handle=%p\n", g_cmdq_handle_monitor); + + cmdqRecReset(g_cmdq_handle_monitor); + + /* wait and clear stream_done, HW will assert mutex enable automatically in frame done reset. */ + /* todo: should let dpmanager to decide wait which mutex's eof. */ + ret = cmdqRecWait(g_cmdq_handle_monitor, CMDQ_EVENT_DISP_RDMA0_UNDERRUN); + + cmdqRecReadToDataRegister(g_cmdq_handle_monitor, 0x10006b0c, + CMDQ_DATA_REG_2D_SHARPNESS_1_DST); + cmdqRecWriteFromDataRegister(g_cmdq_handle_monitor, CMDQ_DATA_REG_2D_SHARPNESS_1_DST, + 0x1401b280); + + cmdqRecReadToDataRegister(g_cmdq_handle_monitor, 0x10006b08, + CMDQ_DATA_REG_2D_SHARPNESS_1_DST); + cmdqRecWriteFromDataRegister(g_cmdq_handle_monitor, CMDQ_DATA_REG_2D_SHARPNESS_1_DST, + 0x1401b284); + + cmdqRecReadToDataRegister(g_cmdq_handle_monitor, 0x10006b04, + CMDQ_DATA_REG_2D_SHARPNESS_1_DST); + cmdqRecWriteFromDataRegister(g_cmdq_handle_monitor, CMDQ_DATA_REG_2D_SHARPNESS_1_DST, + 0x1401b288); + + cmdqRecReadToDataRegister(g_cmdq_handle_monitor, 0x1401b16c, + CMDQ_DATA_REG_2D_SHARPNESS_1_DST); + cmdqRecWriteFromDataRegister(g_cmdq_handle_monitor, CMDQ_DATA_REG_2D_SHARPNESS_1_DST, + 0x1401b28C); + + ret = cmdqRecStartLoop(g_cmdq_handle_monitor); +} +#endif +void _cmdq_start_trigger_loop(void) +{ + int ret = 0; + /*cmdqRecDumpCommand(pgc->cmdq_handle_trigger);*/ + /* this should be called only once because trigger loop will nevet stop */ + ret = cmdqRecStartLoop(pgc->cmdq_handle_trigger); + if (!primary_display_is_video_mode()) { + if (need_wait_esd_eof()) { + /* Need set esd check eof synctoken to let trigger loop go. */ + cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_ESD_EOF); + } + /* need to set STREAM_EOF for the first time, otherwise we will stuck in dead loop */ + cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_STREAM_EOF); + cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_CABC_EOF); + cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_EOF); + /*dprec_event_op(DPREC_EVENT_CMDQ_SET_EVENT_ALLOW);*/ + } + + DISPMSG("primary display START cmdq trigger loop finished\n"); + +} + +void _cmdq_stop_trigger_loop(void) +{ + int ret = 0; + /* this should be called only once because trigger loop will nevet stop */ + ret = cmdqRecStopLoop(pgc->cmdq_handle_trigger); + DISPMSG("primary display STOP cmdq trigger loop finished\n"); +} + +static void _cmdq_set_config_handle_dirty(void) +{ + if (!primary_display_is_video_mode()) { + dprec_logger_start(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 0); + /* only command mode need to set dirty */ + cmdqRecSetEventToken(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + /*dprec_event_op(DPREC_EVENT_CMDQ_SET_DIRTY);*/ + dprec_logger_done(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 0); + } +} + +static void _cmdq_handle_clear_dirty(cmdqRecHandle cmdq_handle) +{ + if (!primary_display_is_video_mode()) { + dprec_logger_trigger(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 1); + cmdqRecClearEventToken(cmdq_handle, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + } +} + +static void _cmdq_set_config_handle_dirty_mira(void *handle) +{ + if (!primary_display_is_video_mode()) { + dprec_logger_start(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 0); + /* only command mode need to set dirty */ + cmdqRecSetEventToken(handle, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + /*dprec_event_op(DPREC_EVENT_CMDQ_SET_DIRTY);*/ + dprec_logger_done(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 0); + } +} + +static void _cmdq_reset_config_handle(void) +{ + cmdqRecReset(pgc->cmdq_handle_config); + /*dprec_event_op(DPREC_EVENT_CMDQ_RESET);*/ +} + +static void _cmdq_flush_config_handle(int blocking, CmdqAsyncFlushCB callback, unsigned int userdata) +{ + dprec_logger_start(DPREC_LOGGER_PRIMARY_CMDQ_FLUSH, blocking, + (unsigned int)(unsigned long)callback); + if (blocking) { + cmdqRecFlush(pgc->cmdq_handle_config); + } else { + if (callback) + cmdqRecFlushAsyncCallback(pgc->cmdq_handle_config, + callback, userdata); + else + cmdqRecFlushAsync(pgc->cmdq_handle_config); + } + + /*dprec_event_op(DPREC_EVENT_CMDQ_FLUSH);*/ + dprec_logger_done(DPREC_LOGGER_PRIMARY_CMDQ_FLUSH, userdata, 0); + + if (dprec_option_enabled()) + cmdqRecDumpCommand(pgc->cmdq_handle_config); + +} + +static void _cmdq_flush_config_handle_mira(void *handle, int blocking) +{ + dprec_logger_start(DPREC_LOGGER_PRIMARY_CMDQ_FLUSH, 0, 0); + if (blocking) + cmdqRecFlush(handle); + else + cmdqRecFlushAsync(handle); + + /*dprec_event_op(DPREC_EVENT_CMDQ_FLUSH);*/ + dprec_logger_done(DPREC_LOGGER_PRIMARY_CMDQ_FLUSH, 0, 0); +} + +void _cmdq_insert_wait_primary_path_frame_done(void *handle) +{ + if (primary_display_is_video_mode()) + cmdqRecWaitNoClear(handle, CMDQ_EVENT_MUTEX0_STREAM_EOF); + else + cmdqRecWaitNoClear(handle, CMDQ_SYNC_TOKEN_STREAM_EOF); +} + +void _cmdq_insert_wait_frame_done_token_mira(void *handle) +{ + if (primary_display_is_video_mode()) { + cmdqRecWaitNoClear(handle, CMDQ_EVENT_DISP_RDMA0_EOF); + cmdqRecWaitNoClear(handle, CMDQ_EVENT_MUTEX0_STREAM_EOF); + ddp_mutex_set_sof_wait(dpmgr_path_get_mutex(pgc->dpmgr_handle), handle, 0); + } else { + cmdqRecWaitNoClear(handle, CMDQ_SYNC_TOKEN_STREAM_EOF); + } + + /*dprec_event_op(DPREC_EVENT_CMDQ_WAIT_STREAM_EOF);*/ +} + +static void update_frm_seq_info(unsigned int addr, unsigned int addr_offset, unsigned int seq, + DISP_FRM_SEQ_STATE state) +{ + int i = 0; + + if (FRM_CONFIG == state) { + frm_update_sequence[frm_update_cnt].state = state; + frm_update_sequence[frm_update_cnt].mva = addr; + frm_update_sequence[frm_update_cnt].max_offset = addr_offset; + if (seq > 0) + frm_update_sequence[frm_update_cnt].seq = seq; + MMProfileLogEx(ddp_mmp_get_events()->primary_seq_config, MMProfileFlagPulse, addr, + seq); + + } else if (FRM_TRIGGER == state) { + frm_update_sequence[frm_update_cnt].state = FRM_TRIGGER; + MMProfileLogEx(ddp_mmp_get_events()->primary_seq_trigger, MMProfileFlagPulse, + frm_update_cnt, frm_update_sequence[frm_update_cnt].seq); + + dprec_logger_frame_seq_begin(pgc->session_id, + frm_update_sequence[frm_update_cnt].seq); + + frm_update_cnt++; + frm_update_cnt %= FRM_UPDATE_SEQ_CACHE_NUM; + + + } else if (FRM_START == state) { + for (i = 0; i < FRM_UPDATE_SEQ_CACHE_NUM; i++) { + if ((abs(addr - frm_update_sequence[i].mva) <= frm_update_sequence[i].max_offset) + && (frm_update_sequence[i].state == FRM_TRIGGER)) { + MMProfileLogEx(ddp_mmp_get_events()->primary_seq_rdma_irq, + MMProfileFlagPulse, frm_update_sequence[i].mva, + frm_update_sequence[i].seq); + frm_update_sequence[i].state = FRM_START; + dprec_logger_frame_seq_end(pgc->session_id, + frm_update_sequence[i].seq); + dprec_logger_frame_seq_begin(0, frm_update_sequence[i].seq); + /* /break; */ + } + } + } else if (FRM_END == state) { + for (i = 0; i < FRM_UPDATE_SEQ_CACHE_NUM; i++) { + if (FRM_START == frm_update_sequence[i].state) { + frm_update_sequence[i].state = FRM_END; + dprec_logger_frame_seq_end(0, frm_update_sequence[i].seq); + MMProfileLogEx(ddp_mmp_get_events()->primary_seq_release, + MMProfileFlagPulse, frm_update_sequence[i].mva, + frm_update_sequence[i].seq); + + } + } + } + +} + +static int _config_wdma_output(WDMA_CONFIG_STRUCT *wdma_config, + disp_path_handle disp_handle, cmdqRecHandle cmdq_handle) +{ + disp_ddp_path_config *pconfig = dpmgr_path_get_last_config(disp_handle); + + pconfig->wdma_config = *wdma_config; + pconfig->wdma_dirty = 1; + dpmgr_path_config(disp_handle, pconfig, cmdq_handle); + return 0; +} + +static int _config_rdma_input_data(RDMA_CONFIG_STRUCT *rdma_config, + disp_path_handle disp_handle, cmdqRecHandle cmdq_handle) +{ + disp_ddp_path_config *pconfig = dpmgr_path_get_last_config(disp_handle); + + pconfig->rdma_config = *rdma_config; + pconfig->rdma_dirty = 1; + dpmgr_path_config(disp_handle, pconfig, cmdq_handle); + return 0; +} + +static void directlink_path_add_memory(WDMA_CONFIG_STRUCT *p_wdma, DISP_MODULE_ENUM after_engine) +{ + int ret = 0; + cmdqRecHandle cmdq_handle = NULL; + cmdqRecHandle cmdq_wait_handle = NULL; + disp_ddp_path_config *pconfig = NULL; + + /*create config thread */ + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle); + if (ret != 0) { + DISPERR("dl_to_dc capture:Fail to create cmdq handle\n"); + ret = -1; + goto out; + } + cmdqRecReset(cmdq_handle); + + /*create wait thread */ + ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_SCREEN_CAPTURE, &cmdq_wait_handle); + if (ret != 0) { + DISPERR("dl_to_dc capture:Fail to create cmdq wait handle\n"); + ret = -1; + goto out; + } + cmdqRecReset(cmdq_wait_handle); + + /*configure config thread */ + _cmdq_insert_wait_frame_done_token_mira(cmdq_handle); + + dpmgr_path_add_memout(pgc->dpmgr_handle, after_engine, cmdq_handle); + + pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle); + pconfig->wdma_config = *p_wdma; + + if (disp_helper_get_option(DISP_OPT_DECOUPLE_MODE_USE_RGB565)) { + pconfig->wdma_config.outputFormat = UFMT_RGB565; + pconfig->wdma_config.dstPitch = pconfig->wdma_config.srcWidth * 2; + } + + pconfig->wdma_dirty = 1; + ret = dpmgr_path_config(pgc->dpmgr_handle, pconfig, cmdq_handle); + + _cmdq_set_config_handle_dirty_mira(cmdq_handle); + _cmdq_flush_config_handle_mira(cmdq_handle, 0); + DISPDBG("dl_to_dc capture:Flush add memout mva(0x%lx)\n", p_wdma->dstAddress); + + /*wait wdma0 sof */ + cmdqRecWait(cmdq_wait_handle, CMDQ_EVENT_DISP_WDMA0_SOF); + cmdqRecFlush(cmdq_wait_handle); + DISPMSG("dl_to_dc capture:Flush wait wdma sof\n"); +out: + cmdqRecDestroy(cmdq_handle); + cmdqRecDestroy(cmdq_wait_handle); +} + + +void disp_enable_emi_force_on(unsigned int enable, void *cmdq_handle) +{ +} + +static unsigned int _get_switch_dc_buffer(void) +{ + if (pgc->freeze_buf) + return pgc->freeze_buf; + + return pgc->dc_buf[pgc->dc_buf_id]; +} +static int _DL_switch_to_DC_fast(void) +{ + int ret = 0; + DDP_SCENARIO_ENUM old_scenario, new_scenario; + RDMA_CONFIG_STRUCT rdma_config = decouple_rdma_config; + WDMA_CONFIG_STRUCT wdma_config = decouple_wdma_config; + + disp_ddp_path_config *data_config_dl = NULL; + disp_ddp_path_config *data_config_dc = NULL; + unsigned int mva = 0; /* mva for 1. ovl->wdma and 2.Rdma->dsi , */ + struct ddp_io_golden_setting_arg gset_arg; + + mva = _get_switch_dc_buffer(); + wdma_config.dstAddress = mva; + wdma_config.security = DISP_NORMAL_BUFFER; + + /* 1.save a temp frame to intermediate buffer */ + directlink_path_add_memory(&wdma_config, DISP_MODULE_OVL0); + + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 1, 0); + + /* 2.reset primary handle */ + _cmdq_reset_config_handle(); + _cmdq_handle_clear_dirty(pgc->cmdq_handle_config); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + /* 3.modify interface path handle to new scenario(rdma->dsi) */ + old_scenario = dpmgr_get_scenario(pgc->dpmgr_handle); + new_scenario = DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP; + + dpmgr_modify_path_power_on_new_modules(pgc->dpmgr_handle, new_scenario, 0); + + dpmgr_modify_path(pgc->dpmgr_handle, new_scenario, pgc->cmdq_handle_config, + primary_display_is_video_mode() ? DDP_VIDEO_MODE : DDP_CMD_MODE, 0); + + + /* 4.config rdma from directlink mode to memory mode */ + rdma_config.address = mva; + rdma_config.security = DISP_NORMAL_BUFFER; + + data_config_dl = dpmgr_path_get_last_config(pgc->dpmgr_handle); + data_config_dl->rdma_config = rdma_config; + data_config_dl->rdma_config.dst_x = 0; + data_config_dl->rdma_config.dst_y = 0; + data_config_dl->rdma_config.dst_h = data_config_dl->dst_h; + data_config_dl->rdma_config.dst_w = data_config_dl->dst_w; + data_config_dl->rdma_dirty = 1; + + /* no need ioctl because of rdma_dirty */ + set_is_dc(1); + + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config_dl, pgc->cmdq_handle_config); + + screen_logger_add_message("sess_mode", MESSAGE_REPLACE, (char *)session_mode_spy(DISP_SESSION_DECOUPLE_MODE)); + dynamic_debug_msg_print(mva, rdma_config.width, rdma_config.height, rdma_config.pitch, + UFMT_GET_Bpp(rdma_config.inputFormat)); + + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(pgc->dpmgr_handle); + gset_arg.is_decouple_mode = 1; + dpmgr_path_ioctl(pgc->dpmgr_handle, pgc->cmdq_handle_config, DDP_OVL_GOLDEN_SETTING, &gset_arg); + + /* screen_logger_add_message("sess_mode", MESSAGE_REPLACE, session_mode_spy(DISP_SESSION_DECOUPLE_MODE)); */ + /* dynamic_debug_msg_print(mva, rdma_config.width, rdma_config.height, rdma_config.pitch, */ + /* ovl_get_Bpp_from_dpColorFmt(rdma_config.inputFormat)); */ + + /* 5. backup rdma address to slots */ + cmdqRecBackupUpdateSlot(pgc->cmdq_handle_config, pgc->rdma_buff_info, 0, rdma_config.address); + cmdqRecBackupUpdateSlot(pgc->cmdq_handle_config, pgc->rdma_buff_info, 1, rdma_config.pitch); + cmdqRecBackupUpdateSlot(pgc->cmdq_handle_config, pgc->rdma_buff_info, 2, rdma_config.inputFormat); + + + /* 6 .flush to cmdq */ + _cmdq_set_config_handle_dirty(); + _cmdq_flush_config_handle(1, NULL, 0); + + dpmgr_modify_path_power_off_old_modules(old_scenario, new_scenario, 0); + + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 2, 0); + + /* ddp_mmp_rdma_layer(&rdma_config, 0, 20, 20); */ + + /* 7.reset cmdq */ + _cmdq_reset_config_handle(); + _cmdq_handle_clear_dirty(pgc->cmdq_handle_config); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + /* 9. create ovl2mem path handle */ + cmdqRecReset(pgc->cmdq_handle_ovl1to2_config); + pgc->ovl2mem_path_handle = + dpmgr_create_path(DDP_SCENARIO_PRIMARY_OVL_MEMOUT, pgc->cmdq_handle_ovl1to2_config); + + if (pgc->ovl2mem_path_handle) { + DISPDBG("dpmgr create ovl memout path SUCCESS(%p)\n", pgc->ovl2mem_path_handle); + } else { + DISPERR("dpmgr create path FAIL\n"); + return -1; + } + + dpmgr_path_set_video_mode(pgc->ovl2mem_path_handle, 0); + dpmgr_path_init(pgc->ovl2mem_path_handle, CMDQ_ENABLE); + + data_config_dc = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle); + data_config_dc->dst_w = rdma_config.width; + data_config_dc->dst_h = rdma_config.height; + data_config_dc->dst_dirty = 1; + + /* move ovl config info from dl to dc */ + memcpy(data_config_dc->ovl_config, data_config_dl->ovl_config, + sizeof(data_config_dl->ovl_config)); + + ret = dpmgr_path_config(pgc->ovl2mem_path_handle, data_config_dc, + pgc->cmdq_handle_ovl1to2_config); + + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(pgc->ovl2mem_path_handle); + gset_arg.is_decouple_mode = 1; + dpmgr_path_ioctl(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config, DDP_OVL_GOLDEN_SETTING, &gset_arg); + + ret = dpmgr_path_start(pgc->ovl2mem_path_handle, CMDQ_ENABLE); + + /* cmdqRecDumpCommand(pgc->cmdq_handle_ovl1to2_config); */ + /*cmdqRecClearEventToken(pgc->cmdq_handle_ovl1to2_config, CMDQ_EVENT_DISP_WDMA0_EOF);*/ + _cmdq_flush_config_handle_mira(pgc->cmdq_handle_ovl1to2_config, 0); + cmdqRecReset(pgc->cmdq_handle_ovl1to2_config); + cmdqRecWait(pgc->cmdq_handle_ovl1to2_config, CMDQ_EVENT_DISP_WDMA0_EOF); + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 3, 0); + + /* 11..enable event for new path */ +/* dpmgr_enable_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_COMPLETE); */ +/* dpmgr_map_event_to_irq(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_START, DDP_IRQ_WDMA0_FRAME_COMPLETE); */ +/* dpmgr_enable_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_START); */ + + if (primary_display_is_video_mode()) { + if (_need_lfr_check()) { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_DSI0_FRAME_DONE); + } else { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_RDMA0_DONE); + } + } + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + /* dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); */ + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START); + + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 4, 0); + + return ret; +} + +static int DL_switch_to_DC_fast(int sw_only) +{ + int ret = 0; + + if (!sw_only) + ret = _DL_switch_to_DC_fast(); + else + ret = -1; /*not support yet */ + + return ret; +} + +static int modify_path_power_off_callback(unsigned long userdata) +{ + DDP_SCENARIO_ENUM old_scenario, new_scenario; + int layer; + + old_scenario = userdata >> 16; + new_scenario = userdata & ((1 << 16) - 1); + dpmgr_modify_path_power_off_old_modules(old_scenario, new_scenario, 0); + + /* release output buffer */ + layer = disp_sync_get_output_interface_timeline_id(); + mtkfb_release_layer_fence(primary_session_id, layer); + return 0; +} + +static int _DC_switch_to_DL_fast(void) +{ + int ret = 0; + int layer = 0; + disp_ddp_path_config *data_config_dl = NULL; + disp_ddp_path_config *data_config_dc = NULL; + DDP_SCENARIO_ENUM old_scenario, new_scenario; + struct ddp_io_golden_setting_arg gset_arg; + + /* 3.destroy ovl->mem path. */ + data_config_dc = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle); + data_config_dl = dpmgr_path_get_last_config(pgc->dpmgr_handle); + + /*copy ovl config from DC handle to DL handle */; + memcpy(data_config_dl->ovl_config, data_config_dc->ovl_config, sizeof(data_config_dl->ovl_config)); + + dpmgr_path_deinit(pgc->ovl2mem_path_handle, + (int)(unsigned long)pgc->cmdq_handle_ovl1to2_config); + dpmgr_destroy_path(pgc->ovl2mem_path_handle, + pgc->cmdq_handle_ovl1to2_config); + /*clear sof token for next dl to dc */ + cmdqRecClearEventToken(pgc->cmdq_handle_ovl1to2_config, CMDQ_EVENT_DISP_WDMA0_SOF); + + _cmdq_flush_config_handle_mira(pgc->cmdq_handle_ovl1to2_config, 1); + cmdqRecReset(pgc->cmdq_handle_ovl1to2_config); + pgc->ovl2mem_path_handle = NULL; + + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 1, 1); + + /* release output buffer */ + layer = disp_sync_get_output_timeline_id(); + mtkfb_release_layer_fence(primary_session_id, layer); + + /* 4.modify interface path handle to new scenario(rdma->dsi) */ + _cmdq_reset_config_handle(); + _cmdq_handle_clear_dirty(pgc->cmdq_handle_config); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + old_scenario = dpmgr_get_scenario(pgc->dpmgr_handle); + new_scenario = DDP_SCENARIO_PRIMARY_DISP; + + dpmgr_modify_path_power_on_new_modules(pgc->dpmgr_handle, new_scenario, 0); + + dpmgr_modify_path(pgc->dpmgr_handle, new_scenario, pgc->cmdq_handle_config, + primary_display_is_video_mode() ? DDP_VIDEO_MODE : DDP_CMD_MODE, 0); + + /* 5.config rdma from memory mode to directlink mode */ + data_config_dl->rdma_config = decouple_rdma_config; + data_config_dl->rdma_config.address = 0; + data_config_dl->rdma_config.pitch = 0; + data_config_dl->rdma_config.security = DISP_NORMAL_BUFFER; + data_config_dl->rdma_dirty = 1; + data_config_dl->dst_dirty = 1; + + /* no need ioctl because of rdma_dirty */ + set_is_dc(0); + + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config_dl, pgc->cmdq_handle_config); + + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(pgc->dpmgr_handle); + gset_arg.is_decouple_mode = 0; + dpmgr_path_ioctl(pgc->dpmgr_handle, pgc->cmdq_handle_config, DDP_OVL_GOLDEN_SETTING, &gset_arg); + + cmdqRecBackupUpdateSlot(pgc->cmdq_handle_config, pgc->rdma_buff_info, 0, 0); + + /* cmdqRecDumpCommand(pgc->cmdq_handle_config); */ + _cmdq_set_config_handle_dirty(); + /*if blocking flush won't cause UX issue, we should simplify this code: remove callback * + *else we should move disable_sodi to callback, and change to nonblocking flush */ + if (disp_helper_get_option(DISP_OPT_GMO_OPTIMIZE)) { + _cmdq_flush_config_handle(1, modify_path_power_off_callback, (old_scenario << 16) | new_scenario); + modify_path_power_off_callback((old_scenario << 16) | new_scenario); + pd_release_dc_buffer(); + } else { + _cmdq_flush_config_handle(0, modify_path_power_off_callback, (old_scenario << 16) | new_scenario); + /* modify_path_power_off_callback((old_scenario << 16) | new_scenario); */ + } + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 2, 1); + + _cmdq_reset_config_handle(); + _cmdq_handle_clear_dirty(pgc->cmdq_handle_config); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + /* 9.enable event for new path */ + if (primary_display_is_video_mode()) { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_RDMA0_DONE); + } + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START); + + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 3, 1); + + return ret; +} + +static int _DC_switch_to_DL_sw_only(void) +{ + int ret = 0; + int layer = 0; + disp_ddp_path_config *data_config_dc = NULL; + disp_ddp_path_config *data_config_dl = NULL; + DDP_SCENARIO_ENUM old_scenario, new_scenario; + + /* 3.destroy ovl->mem path. */ + data_config_dc = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle); + data_config_dl = dpmgr_path_get_last_config(pgc->dpmgr_handle); + + dpmgr_destroy_path_handle(pgc->ovl2mem_path_handle); + + cmdqRecReset(pgc->cmdq_handle_ovl1to2_config); + pgc->ovl2mem_path_handle = NULL; + + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 1, 1); + + /* release output buffer */ + layer = disp_sync_get_output_timeline_id(); + mtkfb_release_layer_fence(primary_session_id, layer); + + /* 4.modify interface path handle to new scenario(rdma->dsi) */ + _cmdq_reset_config_handle(); + _cmdq_handle_clear_dirty(pgc->cmdq_handle_config); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + old_scenario = dpmgr_get_scenario(pgc->dpmgr_handle); + new_scenario = DDP_SCENARIO_PRIMARY_DISP; + dpmgr_modify_path_power_on_new_modules(pgc->dpmgr_handle, new_scenario, 1); + dpmgr_modify_path(pgc->dpmgr_handle, new_scenario, pgc->cmdq_handle_config, + primary_display_is_video_mode() ? DDP_VIDEO_MODE : DDP_CMD_MODE, 1); + dpmgr_modify_path_power_off_old_modules(old_scenario, new_scenario, 1); + + /* 5.config rdma from memory mode to directlink mode */ + data_config_dl->rdma_config = decouple_rdma_config; + data_config_dl->rdma_config.address = 0; + data_config_dl->rdma_config.pitch = 0; + data_config_dl->rdma_config.security = DISP_NORMAL_BUFFER; + /* no need ioctl because of rdma_dirty */ + set_is_dc(0); + + if (disp_helper_get_option(DISP_OPT_GMO_OPTIMIZE)) + pd_release_dc_buffer(); + + /* release output buffer */ + layer = disp_sync_get_output_interface_timeline_id(); + mtkfb_release_layer_fence(primary_session_id, layer); + + _cmdq_reset_config_handle(); + _cmdq_handle_clear_dirty(pgc->cmdq_handle_config); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + /* 9.enable event for new path */ + if (primary_display_is_video_mode()) { + if (_need_lfr_check()) { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_DSI0_FRAME_DONE); + } else { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_RDMA0_DONE); + } + } + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START); + + if (!primary_display_is_video_mode()) + _cmdq_build_trigger_loop(); + + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, 3, 1); + + return ret; +} + +static int DC_switch_to_DL_fast(int sw_only) +{ + int ret = 0; + + if (!sw_only) + ret = _DC_switch_to_DL_fast(); + else + ret = _DC_switch_to_DL_sw_only(); + + return ret; +} + +static int DL_switch_to_rdma_mode(cmdqRecHandle handle, int block) +{ + int ret; + DDP_SCENARIO_ENUM old_scenario, new_scenario; + int need_flush = 0; + struct ddp_io_golden_setting_arg gset_arg; + + if (!handle) { + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + if (ret) { + DISPERR("%s:%d, create cmdq handle fail!ret=%d\n", __func__, __LINE__, ret); + return -1; + } + _cmdq_insert_wait_frame_done_token_mira(handle); + need_flush = 1; + } + + old_scenario = dpmgr_get_scenario(pgc->dpmgr_handle); + new_scenario = DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP; + dpmgr_modify_path_power_on_new_modules(pgc->dpmgr_handle, new_scenario, 0); + dpmgr_modify_path(pgc->dpmgr_handle, new_scenario, handle, + primary_display_is_video_mode() ? DDP_VIDEO_MODE : DDP_CMD_MODE, 0); + dpmgr_modify_path_power_off_old_modules(old_scenario, new_scenario, 0); + + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(pgc->dpmgr_handle); + gset_arg.is_decouple_mode = 1; + dpmgr_path_ioctl(pgc->dpmgr_handle, handle, DDP_OVL_GOLDEN_SETTING, &gset_arg); + + if (need_flush) { + if (block) + cmdqRecFlush(handle); + else + cmdqRecFlushAsync(handle); + cmdqRecDestroy(handle); + } + + return 0; +} + +static int rdma_mode_switch_to_DL(cmdqRecHandle handle, int block) +{ + int ret; + DDP_SCENARIO_ENUM old_scenario, new_scenario; + int need_flush = 0; + disp_ddp_path_config *pconfig; + struct ddp_io_golden_setting_arg gset_arg; + + if (!handle) { + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + if (ret) { + DISPERR("%s:%d, create cmdq handle fail!ret=%d\n", __func__, __LINE__, ret); + return -1; + } + _cmdq_insert_wait_frame_done_token_mira(handle); + need_flush = 1; + } + + old_scenario = dpmgr_get_scenario(pgc->dpmgr_handle); + new_scenario = DDP_SCENARIO_PRIMARY_DISP; + dpmgr_modify_path_power_on_new_modules(pgc->dpmgr_handle, new_scenario, 0); + dpmgr_modify_path(pgc->dpmgr_handle, new_scenario, handle, + primary_display_is_video_mode() ? DDP_VIDEO_MODE : DDP_CMD_MODE, 0); + dpmgr_modify_path_power_off_old_modules(old_scenario, new_scenario, 0); + + /* set rdma to DL mode */ + pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle); + pconfig->rdma_config.address = 0; + pconfig->rdma_config.pitch = 0; + pconfig->rdma_config.width = pconfig->dst_w; + pconfig->rdma_config.height = pconfig->dst_h; + pconfig->rdma_config.security = DISP_NORMAL_BUFFER; + pconfig->rdma_dirty = 1; + pconfig->dst_dirty = 1; + if (need_flush) { + /* re-config ovl because ovl is new-coming */ + pconfig->ovl_dirty = 1; + } + + /* no need ioctl because of rdma_dirty */ + set_is_dc(0); + + ret = dpmgr_path_config(pgc->dpmgr_handle, pconfig, handle); + /* clear dirty set by this func */ + pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle); + + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(pgc->dpmgr_handle); + gset_arg.is_decouple_mode = 0; + dpmgr_path_ioctl(pgc->dpmgr_handle, handle, DDP_OVL_GOLDEN_SETTING, &gset_arg); + + if (need_flush) { + if (block) + cmdqRecFlush(handle); + else + cmdqRecFlushAsync(handle); + cmdqRecDestroy(handle); + } + + return 0; +} + +static int config_display_m4u_port(void) +{ + int ret = 0; + M4U_PORT_STRUCT sPort; + char *m4u_usage = + disp_helper_get_option(DISP_OPT_USE_M4U) ? "virtual" : "physical"; + + sPort.ePortID = M4U_PORT_DISP_OVL0; + sPort.Virtuality = disp_helper_get_option(DISP_OPT_USE_M4U); + sPort.Security = 0; + sPort.Distance = 1; + sPort.Direction = 0; + ret = m4u_config_port(&sPort); + if (ret) { + DISPERR("config M4U Port %s to %s FAIL(ret=%d)\n", + ddp_get_module_name(DISP_MODULE_OVL0), m4u_usage, ret); + return -1; + } + + sPort.ePortID = M4U_PORT_DISP_2L_OVL0; + ret = m4u_config_port(&sPort); + if (ret) { + DISPERR("config M4U Port %s to %s FAIL(ret=%d)\n", + ddp_get_module_name(DISP_MODULE_OVL0_2L), m4u_usage, ret); + return -1; + } + + sPort.ePortID = M4U_PORT_DISP_2L_OVL1; + ret = m4u_config_port(&sPort); + if (ret) { + DISPERR("config M4U Port %s to %s FAIL(ret=%d)\n", + ddp_get_module_name(DISP_MODULE_OVL0_2L), m4u_usage, ret); + return -1; + } + + sPort.ePortID = M4U_PORT_DISP_RDMA0; + ret = m4u_config_port(&sPort); + if (ret) { + DISPERR("config M4U Port %s to %s FAIL(ret=%d)\n", + ddp_get_module_name(DISP_MODULE_RDMA0), m4u_usage, ret); + return -1; + } + + sPort.ePortID = M4U_PORT_DISP_WDMA0; + ret = m4u_config_port(&sPort); + if (ret) { + DISPERR("config M4U Port %s to %s FAIL(ret=%d)\n", + ddp_get_module_name(DISP_MODULE_WDMA0), m4u_usage, ret); + return -1; + } + return ret; +} + +static disp_internal_buffer_info *allocat_decouple_buffer(int size) +{ + void *buffer_va = NULL; + unsigned int buffer_mva = 0; + unsigned int mva_size = 0; + struct ion_mm_data mm_data; + struct ion_client *client = NULL; + struct ion_handle *handle = NULL; + disp_internal_buffer_info *buf_info = NULL; + + memset((void *)&mm_data, 0, sizeof(struct ion_mm_data)); + client = ion_client_create(g_ion_device, "disp_decouple"); + + buf_info = kzalloc(sizeof(disp_internal_buffer_info), GFP_KERNEL); + if (buf_info) { + handle = ion_alloc(client, size, 0, ION_HEAP_MULTIMEDIA_MASK, 0); + if (IS_ERR(handle)) { + DISPERR("Fatal Error, ion_alloc for size %d failed\n", size); + ion_free(client, handle); + ion_client_destroy(client); + kfree(buf_info); + return NULL; + } + + buffer_va = ion_map_kernel(client, handle); + if (buffer_va == NULL) { + DISPERR("ion_map_kernrl failed\n"); + ion_free(client, handle); + ion_client_destroy(client); + kfree(buf_info); + return NULL; + } + mm_data.config_buffer_param.kernel_handle = handle; + mm_data.mm_cmd = ION_MM_CONFIG_BUFFER; + if (ion_kernel_ioctl(client, ION_CMD_MULTIMEDIA, (unsigned long)&mm_data) < 0) { + DISPERR("ion_test_drv: Config buffer failed.\n"); + ion_free(client, handle); + ion_client_destroy(client); + kfree(buf_info); + return NULL; + } + + ion_phys(client, handle, (ion_phys_addr_t *) &buffer_mva, (size_t *) &mva_size); + if (buffer_mva == 0) { + DISPERR("Fatal Error, get mva failed\n"); + ion_free(client, handle); + ion_client_destroy(client); + kfree(buf_info); + return NULL; + } + buf_info->handle = handle; + buf_info->mva = buffer_mva; + buf_info->size = mva_size; + buf_info->va = buffer_va; + buf_info->client = client; + } else { + DISPERR("Fatal error, kzalloc internal buffer info failed!!\n"); + kfree(buf_info); + return NULL; + } + return buf_info; +} + +static int init_decouple_buffers(void) +{ + int i = 0; + enum UNIFIED_COLOR_FMT fmt = UFMT_RGB888; + int height = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + int width = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + int Bpp = UFMT_GET_Bpp(fmt); + int buffer_size; + + buffer_size = width * height * Bpp; + + for (i = 0; i < DISP_INTERNAL_BUFFER_COUNT; i++) { /* INTERNAL Buf 3 frames */ + decouple_buffer_info[i] = allocat_decouple_buffer(buffer_size); + if (decouple_buffer_info[i] != NULL) + pgc->dc_buf[i] = decouple_buffer_info[i]->mva; + + } + + /*initialize rdma config */ + decouple_rdma_config.height = height; + decouple_rdma_config.width = width; + decouple_rdma_config.idx = 0; + decouple_rdma_config.inputFormat = fmt; + decouple_rdma_config.pitch = width * Bpp; + decouple_rdma_config.security = DISP_NORMAL_BUFFER; + decouple_rdma_config.dst_x = 0; + decouple_rdma_config.dst_y = 0; + decouple_rdma_config.dst_w = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + decouple_rdma_config.dst_h = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + + /*initialize wdma config */ + decouple_wdma_config.srcHeight = height; + decouple_wdma_config.srcWidth = width; + decouple_wdma_config.clipX = 0; + decouple_wdma_config.clipY = 0; + decouple_wdma_config.clipHeight = height; + decouple_wdma_config.clipWidth = width; + decouple_wdma_config.outputFormat = fmt; + decouple_wdma_config.useSpecifiedAlpha = 1; + decouple_wdma_config.alpha = 0xFF; + decouple_wdma_config.dstPitch = width * Bpp; + decouple_wdma_config.security = DISP_NORMAL_BUFFER; + + return 0; + +} + +static int _allocate_dc_buffer(void) +{ + int ret = 0; + int i = 0; + enum UNIFIED_COLOR_FMT fmt = UFMT_RGB888; + int height = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + int width = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + int Bpp = UFMT_GET_Bpp(fmt); + + int buffer_size = width * height * Bpp; + + gmo_decouple_buffer_info = allocat_decouple_buffer(buffer_size); + if (gmo_decouple_buffer_info != NULL) + for (i = 0; i < DISP_INTERNAL_BUFFER_COUNT; i++) + pgc->dc_buf[i] = gmo_decouple_buffer_info->mva; + else { + DISPERR("_allocate_dc_buffer fail\n"); + return -EFAULT; + } + DISPDBG("_allocate_dc_buffer mva 0x%x\n", gmo_decouple_buffer_info->mva); + /*initialize rdma config */ + decouple_rdma_config.height = height; + decouple_rdma_config.width = width; + decouple_rdma_config.idx = 0; + decouple_rdma_config.inputFormat = fmt; + decouple_rdma_config.pitch = width * Bpp; + decouple_rdma_config.security = DISP_NORMAL_BUFFER; + decouple_rdma_config.dst_x = 0; + decouple_rdma_config.dst_y = 0; + decouple_rdma_config.dst_w = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + decouple_rdma_config.dst_h = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + + /*initialize wdma config */ + decouple_wdma_config.srcHeight = height; + decouple_wdma_config.srcWidth = width; + decouple_wdma_config.clipX = 0; + decouple_wdma_config.clipY = 0; + decouple_wdma_config.clipHeight = height; + decouple_wdma_config.clipWidth = width; + decouple_wdma_config.outputFormat = fmt; + decouple_wdma_config.useSpecifiedAlpha = 1; + decouple_wdma_config.alpha = 0xFF; + decouple_wdma_config.dstPitch = width * Bpp; + decouple_wdma_config.security = DISP_NORMAL_BUFFER; + return ret; +} + +static int _release_dc_buffer(void) +{ + int ret = 0; + int i = 0; + + if (gmo_decouple_buffer_info) { + ion_free(gmo_decouple_buffer_info->client, gmo_decouple_buffer_info->handle); + ion_client_destroy(gmo_decouple_buffer_info->client); + kfree(gmo_decouple_buffer_info); + gmo_decouple_buffer_info = NULL; + for (i = 0; i < DISP_INTERNAL_BUFFER_COUNT; i++) + pgc->dc_buf[i] = 0; + DISPDBG("_release_dc_buffer\n"); + } + + return ret; +} + +static int _allocate_freeze_buffer(void) +{ + enum UNIFIED_COLOR_FMT fmt = UFMT_RGB888; + int height = primary_display_get_height(); + int width = primary_display_get_width(); + int Bpp = UFMT_GET_Bpp(fmt); + int buffer_size = width * height * Bpp; + + freeze_buffer_info = allocat_decouple_buffer(buffer_size); + if (freeze_buffer_info != NULL) + pgc->freeze_buf = freeze_buffer_info->mva; + else + return -1; + + return 0; +} + +static int release_freeze_buffer(void) +{ + if (freeze_buffer_info) { + ion_free(freeze_buffer_info->client, freeze_buffer_info->handle); + ion_client_destroy(freeze_buffer_info->client); + kfree(freeze_buffer_info); + freeze_buffer_info = NULL; + pgc->freeze_buf = 0; + } + return 0; +} + +int pd_release_dc_buffer(void) +{ + int ret = 0; + + ret = _release_dc_buffer(); + return ret; +} + +int pd_allocate_dc_buffer(void) +{ + int ret = 0; + + ret = _allocate_dc_buffer(); + return ret; +} + +static int _build_path_direct_link(void) +{ + int ret = 0; + + + DISPFUNC(); + pgc->mode = DIRECT_LINK_MODE; + + pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_PRIMARY_DISP, pgc->cmdq_handle_config); + if (pgc->dpmgr_handle) { + DISPDBG("dpmgr create path SUCCESS(%p)\n", pgc->dpmgr_handle); + } else { + DISPERR("dpmgr create path FAIL\n"); + return -1; + } + dpmgr_set_lcm_utils(pgc->dpmgr_handle, pgc->plcm->drv); + + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START); + + return ret; +} + + +static int _convert_disp_input_to_ovl(OVL_CONFIG_STRUCT *dst, disp_input_config *src) +{ + int ret = 0; + int force_disable_alpha = 0; + enum UNIFIED_COLOR_FMT tmp_fmt; + unsigned int Bpp = 0; + + if (!src || !dst) { + DISPAEE("%s src(0x%p) or dst(0x%p) is null\n", __func__, src, dst); + return -1; + } + + dst->layer = src->layer_id; + dst->isDirty = 1; + dst->buff_idx = src->next_buff_idx; + dst->layer_en = src->layer_enable; + + /* if layer is disable, we just needs config above params. */ + if (!src->layer_enable) + return 0; + + tmp_fmt = disp_fmt_to_unified_fmt(src->src_fmt); + /* display don't support X channel, like XRGB8888 + * we need to enable const_bld*/ + ufmt_disable_X_channel(tmp_fmt, &dst->fmt, &dst->const_bld); +#if 0 + if (tmp_fmt != dst->fmt) + force_disable_alpha = 1; +#endif + Bpp = UFMT_GET_Bpp(dst->fmt); + + dst->addr = (unsigned long)src->src_phy_addr; + dst->vaddr = (unsigned long)src->src_base_addr; + dst->src_x = src->src_offset_x; + dst->src_y = src->src_offset_y; + dst->src_w = src->src_width; + dst->src_h = src->src_height; + dst->src_pitch = src->src_pitch * Bpp; + dst->dst_x = src->tgt_offset_x; + dst->dst_y = src->tgt_offset_y; + + /* dst W/H should <= src W/H */ + dst->dst_w = min(src->src_width, src->tgt_width); + dst->dst_h = min(src->src_height, src->tgt_height); + + dst->keyEn = src->src_use_color_key; + dst->key = src->src_color_key; + + dst->aen = force_disable_alpha ? 0 : src->alpha_enable; + dst->sur_aen = force_disable_alpha ? 0 : src->sur_aen; + + dst->alpha = src->alpha; + dst->src_alpha = src->src_alpha; + dst->dst_alpha = src->dst_alpha; + + dst->identity = src->identity; + dst->connected_type = src->connected_type; + dst->security = src->security; + dst->yuv_range = src->yuv_range; + + if (src->buffer_source == DISP_BUFFER_ALPHA) { + dst->source = OVL_LAYER_SOURCE_RESERVED; /* dim layer, constant alpha */ + } else if (src->buffer_source == DISP_BUFFER_ION || src->buffer_source == DISP_BUFFER_MVA) { + dst->source = OVL_LAYER_SOURCE_MEM; /* from memory */ + } else { + DISPERR("unknown source = %d", src->buffer_source); + dst->source = OVL_LAYER_SOURCE_MEM; + } + + return ret; +} +#if 0 +static int _convert_disp_input_to_rdma(RDMA_CONFIG_STRUCT *dst, + disp_session_input_config *session_input) +{ + pr_err("%s not implement yet!!!!!!!!!!!!!!!\n", __func__); + return -1; +} +#endif +int _trigger_display_interface(int blocking, void *callback, unsigned int userdata) +{ + int ret; + + if (_should_wait_path_idle()) { + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + if (ret <= 0) + primary_display_diagnose(); + } + + if (_should_update_lcm()) { + int x = disp_helper_get_option(DISP_OPT_FAKE_LCM_X); + int y = disp_helper_get_option(DISP_OPT_FAKE_LCM_Y); + int width = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + int height = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + + disp_lcm_update(pgc->plcm, x, y, width, height, 0); + } + if (_should_start_path()) + dpmgr_path_start(pgc->dpmgr_handle, primary_display_cmdq_enabled()); + + if (_should_trigger_path()) { + if (islcmconnected) + dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, primary_display_cmdq_enabled()); + } + if (_should_set_cmdq_dirty()) + _cmdq_set_config_handle_dirty(); + + if (_should_flush_cmdq_config_handle()) + _cmdq_flush_config_handle(blocking, callback, userdata); + + if (_should_reset_cmdq_config_handle()) + _cmdq_reset_config_handle(); + + /* clear cmdq dirty incase trigger loop starts here */ + if (_should_set_cmdq_dirty()) + _cmdq_handle_clear_dirty(pgc->cmdq_handle_config); + + if (_should_insert_wait_frame_done_token()) + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + if (_need_lfr_check()) + dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config, CMDQ_DSI_LFR_MODE, 0); + + return 0; +} + +int _trigger_ovl_to_memory(disp_path_handle disp_handle, + cmdqRecHandle cmdq_handle, + CmdqAsyncFlushCB callback, unsigned int data) +{ + int layer = 0; + unsigned int rdma_pitch_sec; + + MMProfileLogEx(ddp_mmp_get_events()->ovl_trigger, MMProfileFlagStart, 0, data); + + dpmgr_path_trigger(disp_handle, cmdq_handle, CMDQ_ENABLE); + + cmdqRecWaitNoClear(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_EOF); + + layer = disp_sync_get_output_timeline_id(); + cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_config_fence, layer, mem_config.buff_idx); + + layer = disp_sync_get_output_interface_timeline_id(); + cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_config_fence, layer, + mem_config.interface_idx); + + cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 0, (unsigned int)mem_config.addr); + + /*rdma pitch only use bit[15..0], we use bit[31:30] to store secure information */ + rdma_pitch_sec = mem_config.pitch | (mem_config.security << 30); + cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 1, rdma_pitch_sec); + cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 2, (unsigned int)mem_config.fmt); + + cmdqRecFlushAsyncCallback(cmdq_handle, callback, data); + cmdqRecReset(cmdq_handle); + cmdqRecWait(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_EOF); + MMProfileLogEx(ddp_mmp_get_events()->ovl_trigger, MMProfileFlagEnd, 0, data); + return 0; +} + +int _trigger_overlay_engine(void) +{ + /* maybe we need a simple merge mechanism for CPU config. */ + dpmgr_path_trigger(pgc->ovl2mem_path_handle, NULL, + disp_helper_get_option(DISP_OPT_USE_CMDQ)); + return 0; +} + + +static unsigned int _need_lfr_check(void) +{ + unsigned int ret = 0; +#ifdef CONFIG_OF + if ((pgc->plcm->params->dsi.lfr_enable == 1) && (islcmconnected == 1)) + ret = 1; + +#else + if (pgc->plcm->params->dsi.lfr_enable == 1) + ret = 1; + +#endif + return ret; +} + +static int _primary_check_trigger(void) +{ + int ret = 0; + + MMProfileLogEx(ddp_mmp_get_events()->primary_display_aalod_trigger, + MMProfileFlagStart, 0, 0); + _primary_path_lock(__func__); + if (pgc->state != DISP_ALIVE) + goto out; + if (primary_display_is_video_mode()) + goto out; + dprec_logger_trigger(DPREC_LOGGER_PQ_TRIGGER_1SECOND, 0, 0); + if (disp_helper_get_option(DISP_OPT_USE_CMDQ)) { + static cmdqRecHandle handle; + + if (!handle) + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + cmdqRecReset(handle); + primary_display_idlemgr_kick((char *)__func__, 0); + _cmdq_insert_wait_frame_done_token_mira(handle); + _cmdq_set_config_handle_dirty_mira(handle); + _cmdq_flush_config_handle_mira(handle, 0); + } else { + dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_TRIGGER); + DISPMSG("Force Trigger Display Path\n"); + primary_display_trigger(1, NULL, 0); + } +out: + MMProfileLogEx(ddp_mmp_get_events()->primary_display_aalod_trigger, + MMProfileFlagEnd, 0, 0); + _primary_path_unlock(__func__); + return 0; +} + +static int _disp_primary_path_check_trigger(void *data) +{ + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_TRIGGER); + while (1) { + dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_TRIGGER); + _primary_check_trigger(); + if (kthread_should_stop()) + break; + } + return 0; +} + +static int _disp_primary_path_check_trigger_delay_33ms(void *data) +{ + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_DELAYED_TRIGGER_33ms); + while (1) { + dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_DELAYED_TRIGGER_33ms); + atomic_set(&delayed_trigger_kick, 0); + + if (disp_helper_get_option(DISP_OPT_DELAYED_TRIGGER)) + usleep_range(32000, 33000); + if (!atomic_read(&delayed_trigger_kick)) + _primary_check_trigger(); + if (kthread_should_stop()) + break; + } + return 0; +} + + +int32_t cmdqDdpClockOn(uint64_t engineFlag) +{ + return 0; +} + +int32_t cmdqDdpClockOff(uint64_t engineFlag) +{ + return 0; +} + +int32_t cmdqDdpDumpInfo(uint64_t engineFlag, int level) +{ + DISPERR("cmdq timeout:%llu\n", engineFlag); + primary_display_diagnose(); + + if (primary_display_is_decouple_mode()) + ddp_dump_analysis(DISP_MODULE_OVL0); + + ddp_dump_analysis(DISP_MODULE_WDMA0); + + /* try to set event by CPU to avoid blocking auto test such as Monkey/MTBF */ + /* cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_STREAM_EOF); */ + /* cmdqCoreSetEvent(CMDQ_EVENT_DISP_RDMA0_EOF); */ + if (disp_helper_get_option(DISP_OPT_DETECT_RECOVERY)) { + atomic_set(&primary_recovery_task_wakeup, 1); + wake_up_interruptible(&primary_recovery_task_wq); + } + return 0; +} + +uint32_t cmdqDdpResetEng(uint64_t engineFlag) +{ + return 0; +} +#if 0 +static void _RDMA0_INTERNAL_IRQ_Handler(DISP_MODULE_ENUM module, unsigned int param) +{ + if (param & 0x2) { + /* RDMA Start */ + /*spm_sodi_mempll_pwr_mode(1);*/ + MMProfileLogEx(ddp_mmp_get_events()->sodi_disable, MMProfileFlagPulse, 0, 0); + } else if (param & 0x4) { + /* RDMA Done */ + /*spm_sodi_mempll_pwr_mode(0);*/ + MMProfileLogEx(ddp_mmp_get_events()->sodi_enable, MMProfileFlagPulse, 0, 0); + } +} + + +void primary_display_sodi_rule_init(void) +{ + /* enable sodi when display driver is ready */ + if (disp_helper_get_option(DISP_HELPER_OPTION_SODI_SUPPORT)) { + if (primary_display_is_video_mode()) + spm_enable_sodi(1); + else + spm_enable_sodi(1); + + return; + } +} +#endif +int primary_display_change_lcm_resolution(unsigned int width, unsigned int height) +{ + if (pgc->plcm) { + DISPMSG("LCM Resolution will be changed, original: %dx%d, now: %dx%d\n", + pgc->plcm->params->width, pgc->plcm->params->height, width, height); + /* align with 4 is the minimal check, to ensure we can boot up into kernel, + * and could modify dfo setting again using meta tool */ + /* otherwise we will have a panic in lk(root cause unknown). */ + if (width > pgc->plcm->params->width || height > pgc->plcm->params->height + || width == 0 || height == 0 || width % 4 || height % 4) { + DISPERR("Invalid resolution: %dx%d\n", width, height); + return -1; + } + + if (primary_display_is_video_mode()) { + DISPERR("Warning!!!Video Mode can't support multiple resolution!\n"); + return -1; + } + + pgc->plcm->params->width = width; + pgc->plcm->params->height = height; + + return 0; + } else { + return -1; + } +} + +static int _wdma_fence_release_callback(unsigned long userdata) +{ + int fence_idx, layer; + + layer = disp_sync_get_output_timeline_id(); + + cmdqBackupReadSlot(pgc->cur_config_fence, layer, &fence_idx); + mtkfb_release_fence(primary_session_id, layer, fence_idx); + MMProfileLogEx(ddp_mmp_get_events()->primary_wdma_fence_release, MMProfileFlagPulse, layer, + fence_idx); + + return 0; +} + +static int _Interface_fence_release_callback(unsigned long userdata) +{ + int layer = disp_sync_get_output_interface_timeline_id(); + + if (userdata > 0) { + mtkfb_release_fence(primary_session_id, layer, userdata); + MMProfileLogEx(ddp_mmp_get_events()->primary_wdma_fence_release, MMProfileFlagPulse, + layer, userdata); + } + + return 0; +} + +static int _decouple_update_rdma_config_nolock(void) +{ + uint32_t interface_fence = 0; + int layer = 0; + int ret = 0; + + if (primary_display_is_decouple_mode()) { + static cmdqRecHandle cmdq_handle; + unsigned int rdma_pitch_sec; + + layer = disp_sync_get_output_interface_timeline_id(); + cmdqBackupReadSlot(pgc->cur_config_fence, layer, &interface_fence); + + if (primary_get_state() != DISP_ALIVE) { + /* don't trigger rdma */ + /* release interface fence */ + _Interface_fence_release_callback(interface_fence > 1 ? interface_fence - 1 : 0); + + return -1; + } + + if (cmdq_handle == NULL) + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle); + if (ret == 0) { + RDMA_CONFIG_STRUCT tmpConfig = decouple_rdma_config; + + cmdqRecReset(cmdq_handle); + _cmdq_insert_wait_frame_done_token_mira(cmdq_handle); + cmdqBackupReadSlot(pgc->rdma_buff_info, 0, (uint32_t *)(&(tmpConfig.address))); + + /*rdma pitch only use bit[15..0], we use bit[31:30] to store secure information*/ + cmdqBackupReadSlot(pgc->rdma_buff_info, 1, &(rdma_pitch_sec)); + tmpConfig.pitch = rdma_pitch_sec & ~(3<<30); + tmpConfig.security = rdma_pitch_sec >> 30; + + cmdqBackupReadSlot(pgc->rdma_buff_info, 2, &(tmpConfig.inputFormat)); + + tmpConfig.height = primary_display_get_height(); + tmpConfig.width = primary_display_get_width(); + tmpConfig.yuv_range = DISP_YUV_BT601; + _config_rdma_input_data(&tmpConfig, pgc->dpmgr_handle, cmdq_handle); + _cmdq_set_config_handle_dirty_mira(cmdq_handle); + cmdqRecFlushAsyncCallback(cmdq_handle, _Interface_fence_release_callback, + interface_fence > 1 ? interface_fence - 1 : 0); + + dprec_mmp_dump_rdma_layer(&tmpConfig, 0); + MMProfileLogEx(ddp_mmp_get_events()->primary_rdma_config, MMProfileFlagPulse, + interface_fence, tmpConfig.address); + } else { + DISPERR("fail to create cmdq\n"); + } + } + return 0; +} + + +static int decouple_update_rdma_config(void) +{ + int ret; + + _primary_path_lock(__func__); + ret = _decouple_update_rdma_config_nolock(); + _primary_path_unlock(__func__); + return ret; +} + +static int _requestCondition(int overlap_layers) +{ + int ret = 0; + int iwidth = 0; + int ihight = 0; + + ihight = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + iwidth = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + + if (ihight * iwidth < DISP_HW_HRT_PERF_LCM_AREA_THRESHOLD) { + if (overlap_layers <= DISP_HW_HRT_PERF_FOR_LCM_SMALL) + return -1; + } else { + if (overlap_layers > DISP_HW_HRT_PERF_FOR_LCM_BIG_MAX) + DISPWRN("overlayed layer num is %d > %d\n", overlap_layers, + DISP_HW_HRT_PERF_FOR_LCM_BIG_MAX); + if (overlap_layers <= DISP_HW_HRT_PERF_FOR_LCM_BIG) + return -1; + } + + return ret; +} + +static int _request_dvfs_perf(int req) +{ + if (is_vcorefs_can_work() != 1) + return 0; + + if (atomic_read(&dvfs_ovl_req_status) != req) { + vcorefs_request_dvfs_opp(KIR_OVL, req); + atomic_set(&dvfs_ovl_req_status, req); + } + + return 0; +} + +static int _ovl_fence_release_callback(unsigned long userdata) +{ + int i = 0; + unsigned int addr = 0; + int ret = 0; + int real_overlap_layers = 0; + + MMProfileLogEx(ddp_mmp_get_events()->session_release, MMProfileFlagStart, 1, userdata); + + /* check overlap layer */ + cmdqBackupReadSlot(pgc->subtractor_when_free, i, &real_overlap_layers); + real_overlap_layers >>= 16; + + _primary_path_lock(__func__); + + if (!_requestCondition(real_overlap_layers)) { + _request_dvfs_perf(OPPI_PERF); + } else { + /* be carefull for race condition !! because callback may delay */ + /* so we need to check last request when ovl_config */ + if (dvfs_last_ovl_req == OPPI_UNREQ) + _request_dvfs_perf(OPPI_UNREQ); + } + _primary_path_unlock(__func__); + + /*check last ovl status: should be idle when config */ + if (primary_display_is_video_mode() && !primary_display_is_decouple_mode()) { + unsigned int status; + + cmdqBackupReadSlot(pgc->ovl_status_info, 0, &status); +#ifdef DEBUG_OVL_CONFIG_TIME + unsigned int time_event = 0; + unsigned int time_event1 = 0; + unsigned int time_event2 = 0; + + cmdqBackupReadSlot(pgc->ovl_config_time, 0, &time_event); + cmdqBackupReadSlot(pgc->ovl_config_time, 1, &time_event1); + cmdqBackupReadSlot(pgc->ovl_config_time, 2, &time_event2); + DISPMSG("ovl config time_event %d time_event1 %d time_event2 %d time1_diff %d time2_diff %d\n", + time_event, time_event1, time_event2, time_event1 - time_event, time_event2 - time_event1); +#endif + if ((status & 0x1) != 0) { + /* ovl is not idle !! */ + DISPERR("disp ovl status error!! stat=0x%x\n", status); + /* DISPAEE("ovl_stat 0x%x\n", status); */ + MMProfileLogEx(ddp_mmp_get_events()->primary_error, MMProfileFlagPulse, status, 0); + primary_display_diagnose(); + ret = -1; + } + } + + for (i = 0; i < PRIMARY_SESSION_INPUT_LAYER_COUNT; i++) { + int fence_idx = 0; + int subtractor = 0; + + if (i == primary_display_get_option("ASSERT_LAYER") && is_DAL_Enabled()) { + mtkfb_release_layer_fence(primary_session_id, i); + } else { + cmdqBackupReadSlot(pgc->cur_config_fence, i, &fence_idx); + cmdqBackupReadSlot(pgc->subtractor_when_free, i, &subtractor); + subtractor &= 0xFFFF; + mtkfb_release_fence(primary_session_id, i, fence_idx - subtractor); + } + MMProfileLogEx(ddp_mmp_get_events()->primary_ovl_fence_release, MMProfileFlagPulse, + i, fence_idx - subtractor); + } + + addr = ddp_ovl_get_cur_addr(!_should_config_ovl_input(), 0); + if ((primary_display_is_decouple_mode() == 0)) + update_frm_seq_info(addr, 0, 2, FRM_START); + + MMProfileLogEx(ddp_mmp_get_events()->session_release, MMProfileFlagEnd, 1, userdata); + return ret; +} + +/* #define UPDATE_RDMA_CONFIG_USING_CMDQ_CALLBACK */ +static int _ovl_wdma_fence_release_callback(unsigned long userdata) +{ + int ret = 0; + + ret = _ovl_fence_release_callback(userdata); + ret |= _wdma_fence_release_callback(userdata); + +#ifdef UPDATE_RDMA_CONFIG_USING_CMDQ_CALLBACK + ret |= decouple_update_rdma_config(); +#endif + + return ret; +} + + +#ifdef UPDATE_RDMA_CONFIG_USING_CMDQ_CALLBACK +static int decouple_mirror_update_rdma_config_thread(void *data) +{ + return 0; +} +#else +static void decouple_mirror_irq_callback(DISP_MODULE_ENUM module, unsigned int reg_value) +{ + #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT) + /* In TEE, we have to protect WDMA registers, so we can't enable WDMA interrupt */ + /* here we use ovl frame done interrupt instead */ + if ((module == DISP_MODULE_OVL0) && (primary_display_is_decouple_mode())) { + if (reg_value & 0x2) {/*OVL0 frame done*/ + atomic_set(&decouple_update_rdma_event, 1); + wake_up_interruptible(&decouple_update_rdma_wq); + } + } + +#else + if ((module == DISP_MODULE_WDMA0) && (primary_display_is_decouple_mode())) { + if (reg_value & 0x1) { /*wdma0 frame done*/ + atomic_set(&decouple_update_rdma_event, 1); + wake_up_interruptible(&decouple_update_rdma_wq); + } + } +#endif +} + +static int decouple_mirror_update_rdma_config_thread(void *data) +{ + struct sched_param param = {.sched_priority = RTPM_PRIO_SCRN_UPDATE }; + + sched_setscheduler(current, SCHED_RR, ¶m); + + disp_register_module_irq_callback(DISP_MODULE_WDMA0, decouple_mirror_irq_callback); + disp_register_module_irq_callback(DISP_MODULE_OVL0, decouple_mirror_irq_callback); + while (1) { + wait_event_interruptible(decouple_update_rdma_wq, + atomic_read(&decouple_update_rdma_event)); + atomic_set(&decouple_update_rdma_event, 0); + decouple_update_rdma_config(); + if (kthread_should_stop()) + break; + } + + return 0; +} +#endif + +static int primary_display_remove_output(CmdqAsyncFlushCB callback, unsigned int userdata) +{ + int ret = 0; + static cmdqRecHandle cmdq_handle; + static cmdqRecHandle cmdq_wait_handle; + + /*create config thread */ + if (cmdq_handle == NULL) + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle); + + if (ret == 0) { + /* capture thread wait wdma sof */ + if (cmdq_wait_handle == NULL) + ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_SCREEN_CAPTURE, &cmdq_wait_handle); + + if (ret == 0) { + cmdqRecReset(cmdq_wait_handle); + cmdqRecWait(cmdq_wait_handle, CMDQ_EVENT_DISP_WDMA0_SOF); + cmdqRecFlush(cmdq_wait_handle); + /* cmdqRecDestroy(cmdq_wait_handle); */ + } else { + DISPERR("fail to create wait handle\n"); + } + cmdqRecReset(cmdq_handle); + _cmdq_insert_wait_frame_done_token_mira(cmdq_handle); + + /* update output fence */ + cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_config_fence, + disp_sync_get_output_timeline_id(), mem_config.buff_idx); + + dpmgr_path_remove_memout(pgc->dpmgr_handle, cmdq_handle); + + cmdqRecClearEventToken(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_SOF); + _cmdq_set_config_handle_dirty_mira(cmdq_handle); + cmdqRecFlushAsyncCallback(cmdq_handle, callback, 0); + pgc->need_trigger_ovl1to2 = 0; + /* cmdqRecDestroy(cmdq_handle); */ + } else { + ret = -1; + DISPERR("fail to remove memout out\n"); + } + return ret; +} + +static void primary_display_frame_update_irq_callback(DISP_MODULE_ENUM module, unsigned int param) +{ + /* /if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE) */ + /* / return; */ + + if (module == DISP_MODULE_RDMA0) { + if (param & 0x2) { /* rdma0 frame start 0x20 */ + if (pgc->session_id > 0 && primary_display_is_decouple_mode()) + update_frm_seq_info(ddp_ovl_get_cur_addr(1, 0), 0, 1, FRM_START); + } + + if (param & 0x4) { /* rdma0 frame done */ + atomic_set(&primary_display_frame_update_event, 1); + wake_up_interruptible(&primary_display_frame_update_wq); + } + } + + if ((module == DISP_MODULE_OVL0) && (primary_display_is_decouple_mode() == 0)) { + if (param & 0x2) { /* ov0 frame done */ + atomic_set(&primary_display_frame_update_event, 1); + wake_up_interruptible(&primary_display_frame_update_wq); + } + } + +} + +static int primary_display_frame_update_kthread(void *data) +{ + struct sched_param param = {.sched_priority = RTPM_PRIO_SCRN_UPDATE }; + + sched_setscheduler(current, SCHED_RR, ¶m); + + for (;;) { + wait_event_interruptible(primary_display_frame_update_wq, + atomic_read(&primary_display_frame_update_event)); + atomic_set(&primary_display_frame_update_event, 0); + + if (pgc->session_id > 0) + update_frm_seq_info(0, 0, 0, FRM_END); + + if (kthread_should_stop()) + break; + + } + + return 0; +} + +static int _present_fence_release_worker_thread(void *data) +{ + disp_sync_info *layer_info; + static int count; + struct sched_param param = {.sched_priority = RTPM_PRIO_FB_THREAD }; + + sched_setscheduler(current, SCHED_RR, ¶m); + + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + + while (1) { + int fence_increment = 0; + int timeline_id; + + wait_event_interruptible(primary_display_present_fence_wq, + atomic_read(&primary_display_present_fence_update_event)); + atomic_set(&primary_display_present_fence_update_event, 0); + if (!islcmconnected && !primary_display_is_video_mode()) { + if ((count++%3) == 0) + DISPMSG("LCM Not Connected && CMD Mode\n"); + msleep(20); + } else { + dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + /* dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); */ + } + + timeline_id = disp_sync_get_present_timeline_id(); + + layer_info = _get_sync_info(primary_session_id, timeline_id); + if (layer_info == NULL) { + MMProfileLogEx(ddp_mmp_get_events()->present_fence_release, + MMProfileFlagPulse, -1, 0x5a5a5a5a); + continue; + } + + _primary_path_lock(__func__); + fence_increment = gPresentFenceIndex - layer_info->timeline->value; + if (fence_increment > 0) { + timeline_inc(layer_info->timeline, fence_increment); + DISPPR_FENCE("R+/%s%d/L%d/id%d\n", + disp_session_mode_spy(primary_session_id), + DISP_SESSION_DEV(primary_session_id), timeline_id, + gPresentFenceIndex); + } + MMProfileLogEx(ddp_mmp_get_events()->present_fence_release, MMProfileFlagPulse, + gPresentFenceIndex, fence_increment); + _primary_path_unlock(__func__); + } + + return 0; +} + +int primary_display_set_frame_buffer_address(unsigned long va, unsigned long mva) +{ + + DISPDBG("framebuffer va 0x%lx, mva 0x%lx\n", va, mva); + pgc->framebuffer_va = va; + pgc->framebuffer_mva = mva; + + return 0; +} + +unsigned long primary_display_get_frame_buffer_mva_address(void) +{ + return pgc->framebuffer_mva; +} + +unsigned long primary_display_get_frame_buffer_va_address(void) +{ + return pgc->framebuffer_va; +} + +int is_dim_layer(unsigned long mva) +{ + if (mva == get_dim_layer_mva_addr()) + return 1; + return 0; +} + +unsigned long get_dim_layer_mva_addr(void) +{ + static unsigned long dim_layer_mva; + + if (dim_layer_mva == 0) { + int frame_buffer_size = ALIGN_TO(DISP_GetScreenWidth(), MTK_FB_ALIGNMENT) * + DISP_GetScreenHeight() * 4; + dim_layer_mva = pgc->framebuffer_mva + (DISP_GetPages() - 1) * frame_buffer_size; + DISPMSG("init dim layer mva %lu, size %d", dim_layer_mva, frame_buffer_size); + } + return dim_layer_mva; +} + +static int init_cmdq_slots(cmdqBackupSlotHandle *pSlot, int count, int init_val) +{ + int i; + + cmdqBackupAllocateSlot(pSlot, count); + + for (i = 0; i < count; i++) + cmdqBackupWriteSlot(*pSlot, i, init_val); + + return 0; +} + +static int update_primary_intferface_module(void) +{ + /*update interface module, it may be: dsi0/dsi1/dsi_dual */ + DISP_MODULE_ENUM interface_module; + + interface_module = _get_dst_module_by_lcm(pgc->plcm); + ddp_set_dst_module(DDP_SCENARIO_PRIMARY_DISP, interface_module); + ddp_set_dst_module(DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP, interface_module); + ddp_set_dst_module(DDP_SCENARIO_PRIMARY_RDMA0_DISP, interface_module); + ddp_set_dst_module(DDP_SCENARIO_PRIMARY_BYPASS_RDMA, interface_module); + + ddp_set_dst_module(DDP_SCENARIO_PRIMARY_ALL, interface_module); + ddp_set_dst_module(DDP_SCENARIO_DITHER_1TO2, interface_module); + ddp_set_dst_module(DDP_SCENARIO_UFOE_1TO2, interface_module); + + return 0; +} + +int primary_display_init(char *lcm_name, unsigned int lcm_fps, int is_lcm_inited) +{ + DISP_STATUS ret = DISP_STATUS_OK; + DISP_MODULE_ENUM dst_module = 0; + LCM_PARAMS *lcm_param = NULL; + int use_cmdq = disp_helper_get_option(DISP_OPT_USE_CMDQ); + struct ddp_io_golden_setting_arg gset_arg; + disp_ddp_path_config *data_config = NULL; + + DISPMSG("primary_display_init begin lcm=%s, inited=%d\n", lcm_name, is_lcm_inited); + + dprec_init(); + dpmgr_init(); + + init_cmdq_slots(&(pgc->ovl_config_time), 3, 0); + init_cmdq_slots(&(pgc->cur_config_fence), DISP_SESSION_TIMELINE_COUNT, 0); + init_cmdq_slots(&(pgc->subtractor_when_free), DISP_SESSION_TIMELINE_COUNT, 0); + init_cmdq_slots(&(pgc->rdma_buff_info), 3, 0); + init_cmdq_slots(&(pgc->ovl_status_info), 4, 0); + + mutex_init(&(pgc->capture_lock)); + mutex_init(&(pgc->lock)); + mutex_init(&(pgc->switch_dst_lock)); + + fps_ctx_init(&primary_fps_ctx, disp_helper_get_option(DISP_OPT_FPS_CALC_WND)); + + _primary_path_lock(__func__); + + pgc->plcm = disp_lcm_probe(lcm_name, LCM_INTERFACE_NOTDEFINED, is_lcm_inited); + + if (pgc->plcm == NULL) { + DISPDBG("disp_lcm_probe returns null\n"); + ret = DISP_STATUS_ERROR; + goto done; + } else { + DISPMSG("disp_lcm_probe SUCCESS\n"); + } + + lcm_param = disp_lcm_get_params(pgc->plcm); + + if (lcm_param == NULL) { + DISPERR("get lcm params FAILED\n"); + ret = DISP_STATUS_ERROR; + goto done; + } + + update_primary_intferface_module(); + + if (use_cmdq) { + ret = cmdqCoreRegisterCB(CMDQ_GROUP_DISP, cmdqDdpClockOn, + cmdqDdpDumpInfo, NULL, cmdqDdpClockOff); + if (ret) { + DISPERR("cmdqCoreRegisterCB failed, ret=%d\n", ret); + ret = DISP_STATUS_ERROR; + goto done; + } + + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &(pgc->cmdq_handle_config)); + if (ret) { + DISPDBG("cmdqRecCreate FAIL, ret=%d\n", ret); + ret = DISP_STATUS_ERROR; + goto done; + } else { + DISPDBG("cmdqRecCreate SUCCESS, g_cmdq_handle=%p\n", + pgc->cmdq_handle_config); + } + /*create ovl2mem path cmdq handle */ + ret = + cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_MEMOUT, &(pgc->cmdq_handle_ovl1to2_config)); + if (ret != 0) { + DISPERR("cmdqRecCreate FAIL, ret=%d\n", ret); + ret = DISP_STATUS_ERROR; + goto done; + } + } else { + pgc->cmdq_handle_config = NULL; + pgc->cmdq_handle_ovl1to2_config = NULL; + } + + if (primary_display_mode == DIRECT_LINK_MODE) { + _build_path_direct_link(); + pgc->session_mode = DISP_SESSION_DIRECT_LINK_MODE; + DISPMSG("primary display is DIRECT LINK MODE\n"); + } else if (primary_display_mode == DECOUPLE_MODE) { + _build_path_decouple(); + pgc->session_mode = DISP_SESSION_DECOUPLE_MODE; + + DISPMSG("primary display is DECOUPLE MODE\n"); + } else if (primary_display_mode == SINGLE_LAYER_MODE) { + _build_path_single_layer(); + + DISPMSG("primary display is SINGLE LAYER MODE\n"); + } else if (primary_display_mode == DEBUG_RDMA1_DSI0_MODE) { + _build_path_debug_rdma1_dsi0(); + + DISPMSG("primary display is DEBUG RDMA1 DSI0 MODE\n"); + } else { + DISPMSG("primary display mode is WRONG\n"); + } + + if (use_cmdq && is_lcm_inited) { + /* if lcm is not inited (no LK), + * the first config should not wait frame done + * because there's no frame done for vdo mode */ + _cmdq_reset_config_handle(); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + } + + config_display_m4u_port(); + primary_display_set_max_layer(PRIMARY_SESSION_INPUT_LAYER_COUNT); + if (!disp_helper_get_option(DISP_OPT_GMO_OPTIMIZE)) + init_decouple_buffers(); + + dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode()); + DISPDBG("primary_display_init->dpmgr_path_init\n"); + dpmgr_path_init(pgc->dpmgr_handle, use_cmdq); + + /* use fake timer to generate vsync signal for cmd mode w/o LCM(originally using LCM TE Signal as VSYNC) */ + /* so we don't need to modify display driver's behavior. */ + if (disp_helper_get_option(DISP_OPT_NO_LCM_FOR_LOW_POWER_MEASUREMENT)) { + /* only for low power measurement */ + DISPWRN("WARNING!!!!!! FORCE NO LCM MODE!!!\n"); + islcmconnected = 0; + + /* no need to change video mode vsync behavior */ + if (!primary_display_is_video_mode()) { + _init_vsync_fake_monitor(lcm_fps); + + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_UNKNOWN); + } + } + + if (use_cmdq) { + _cmdq_build_trigger_loop(); + _cmdq_start_trigger_loop(); + } + + DISPMSG("primary_display_init->dpmgr_path_config\n"); + + + data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle); + memcpy(&(data_config->dispif_config), lcm_param, sizeof(LCM_PARAMS)); + data_config->dst_w = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + data_config->dst_h = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + data_config->p_golden_setting_context = get_golden_setting_pgc(); + + if (lcm_param->type == LCM_TYPE_DSI) { + if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB888) + data_config->lcm_bpp = 24; + else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB565) + data_config->lcm_bpp = 16; + else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB666) + data_config->lcm_bpp = 18; + } else if (lcm_param->type == LCM_TYPE_DPI) { + if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB888) + data_config->lcm_bpp = 24; + else if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB565) + data_config->lcm_bpp = 16; + if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB666) + data_config->lcm_bpp = 18; + } + + data_config->fps = lcm_fps; + data_config->dst_dirty = 1; + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, pgc->cmdq_handle_config); + + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(pgc->dpmgr_handle); + gset_arg.is_decouple_mode = 0; + dpmgr_path_ioctl(pgc->dpmgr_handle, pgc->cmdq_handle_config, DDP_OVL_GOLDEN_SETTING, &gset_arg); + + dpmgr_path_start(pgc->dpmgr_handle, use_cmdq); + + if (use_cmdq) { + _cmdq_flush_config_handle(0, NULL, 0); + _cmdq_reset_config_handle(); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + } + + if (is_lcm_inited) { + ret = disp_lcm_init(pgc->plcm, 0); /* no need lcm power on,because lk power on lcm */ + } else { + ret = disp_lcm_init(pgc->plcm, 1); + + if (primary_display_is_video_mode()) + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, 0); + } + + if (disp_helper_get_option(DISP_OPT_MET_LOG)) + set_enterulps(0); + + primary_display_check_recovery_init(); + + if (disp_helper_get_option(DISP_OPT_SWITCH_DST_MODE)) { + primary_display_switch_dst_mode_task = + kthread_create(_disp_primary_path_switch_dst_mode_thread, NULL, + "display_switch_dst_mode"); + wake_up_process(primary_display_switch_dst_mode_task); + } + + if (decouple_update_rdma_config_thread == NULL) { + decouple_update_rdma_config_thread = + kthread_create(decouple_mirror_update_rdma_config_thread, NULL, + "decouple_update_rdma_cfg"); + wake_up_process(decouple_update_rdma_config_thread); + } + + if (decouple_trigger_thread == NULL) { + decouple_trigger_thread = + kthread_create(decouple_trigger_worker_thread, NULL, "decouple_trigger"); + wake_up_process(decouple_trigger_thread); + } + + if (disp_helper_get_stage() == DISP_HELPER_STAGE_NORMAL) { + primary_path_aal_task = + kthread_create(_disp_primary_path_check_trigger, NULL, "display_check_aal"); + wake_up_process(primary_path_aal_task); + } + + if (disp_helper_get_stage() == DISP_HELPER_STAGE_NORMAL) { + primary_delay_trigger_task = + kthread_create(_disp_primary_path_check_trigger_delay_33ms, NULL, "disp_delay_trigger"); + wake_up_process(primary_delay_trigger_task); + } + + if (disp_helper_get_option(DISP_OPT_PRESENT_FENCE)) { + init_waitqueue_head(&primary_display_present_fence_wq); + present_fence_release_worker_task = + kthread_create(_present_fence_release_worker_thread, NULL, + "present_fence_worker"); + wake_up_process(present_fence_release_worker_task); + } + + if (disp_helper_get_option(DISP_OPT_PERFORMANCE_DEBUG)) { + if (primary_display_frame_update_task == NULL) { + init_waitqueue_head(&primary_display_frame_update_wq); + disp_register_module_irq_callback(DISP_MODULE_RDMA0, + primary_display_frame_update_irq_callback); + disp_register_module_irq_callback(DISP_MODULE_OVL0, + primary_display_frame_update_irq_callback); + primary_display_frame_update_task = + kthread_create(primary_display_frame_update_kthread, NULL, + "frame_update_worker"); + wake_up_process(primary_display_frame_update_task); + } + } + + if (primary_display_is_video_mode()) { + /* + if (disp_helper_get_option(DISP_HELPER_OPTION_IDLE_MGR)) + primary_display_idlemgr_init(); + */ + + if (disp_helper_get_option(DISP_OPT_SWITCH_DST_MODE)) { + primary_display_cur_dst_mode = 1; /* video mode */ + primary_display_def_dst_mode = 1; /* default mode is video mode */ + } + if (_need_lfr_check()) { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_DSI0_FRAME_DONE); + } else { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_RDMA0_DONE); + } + } + + if (disp_helper_get_option(DISP_OPT_DETECT_RECOVERY)) { + /*thread: path recovery */ + primary_display_Recovery_task = + kthread_create(primary_display_recovery_thread, NULL, + "display_recovery"); + init_waitqueue_head(&primary_recovery_task_wq); + /*if (disp_helper_get_option(DISP_OPT_BYPASS_OVL))*/ + wake_up_process(primary_display_Recovery_task); + } + pgc->lcm_fps = lcm_fps; + /* keep lowpower init after setting lcm_fps */ + primary_display_lowpower_init(); + + pgc->state = DISP_ALIVE; +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + disp_switch_data.name = "disp"; + disp_switch_data.index = 0; + disp_switch_data.state = DISP_ALIVE; + ret = switch_dev_register(&disp_switch_data); +#endif +/* + primary_display_sodi_rule_init(); + + if (disp_helper_get_option(DISP_HELPER_OPTION_DYNAMIC_SWITCH_MMSYSCLK)) + register_mmclk_switch_cb(primary_display_switch_mmsys_clk); +*/ + +done: + primary_display_diagnose(); + dst_module = _get_dst_module_by_lcm(pgc->plcm); + _primary_path_unlock(__func__); + return ret; +} + +int primary_display_deinit(void) +{ + _primary_path_lock(__func__); + + _cmdq_stop_trigger_loop(); + dpmgr_path_deinit(pgc->dpmgr_handle, CMDQ_DISABLE); + _primary_path_unlock(__func__); + return 0; +} + +/* register rdma done event */ +int primary_display_wait_for_idle(void) +{ + DISP_STATUS ret = DISP_STATUS_OK; + + DISPFUNC(); + + _primary_path_lock(__func__); + + + _primary_path_unlock(__func__); + return ret; +} + +int primary_display_wait_for_dump(void) +{ + return 0; +} + +int primary_display_release_fence_fake(void) +{ + unsigned int layer_en = 0; + unsigned int addr = 0; + unsigned int fence_idx = -1; + unsigned int session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0); + int i = 0; + + DISPFUNC(); + + for (i = 0; i < PRIMARY_SESSION_INPUT_LAYER_COUNT; i++) { + if (i == primary_display_get_option("ASSERT_LAYER") && is_DAL_Enabled()) { + mtkfb_release_layer_fence(session_id, 3); + } else { + disp_sync_get_cached_layer_info(session_id, i, &layer_en, + (unsigned long *)&addr, &fence_idx); + if (fence_idx == -1) { + DISPPR_ERROR("find fence for layer %d,addr 0x%08x fail, unregistered\n", i, addr); + } else if (fence_idx < 0) { + DISPPR_ERROR("find fence idx for layer %d,addr 0x%08x fail,unknown\n", i, addr); + } else { + if (layer_en) + mtkfb_release_fence(session_id, i, fence_idx - 1); + else + mtkfb_release_fence(session_id, i, fence_idx); + } + } + } + + return 0; +} + +int primary_display_wait_for_vsync(void *config) +{ + disp_session_vsync_config *c = (disp_session_vsync_config *) config; + int ret = 0, has_vsync = 1; + unsigned long long ts = 0ULL; + static int count; + /* kick idle manager here to ensure sodi is disabled when screen update begin(not 100% ensure) */ + primary_display_idlemgr_kick((char *)__func__, 1); + +#ifdef CONFIG_MTK_FPGA + if (!primary_display_is_video_mode()) + has_vsync = 0; /* fpga has no TE signal */ +#endif + + if (!islcmconnected || !has_vsync) { + if ((count++%3) == 0) + DISPMSG("use fake vsync: lcm_connect=%d, has_vsync=%d\n", + islcmconnected, has_vsync); + msleep(20); + return 0; + } + + if (pgc->force_fps_keep_count && pgc->force_fps_skip_count) { + g_keep++; + DISPMSG("vsync|keep %d\n", g_keep); + if (g_keep == pgc->force_fps_keep_count) { + g_keep = 0; + + while (g_skip != pgc->force_fps_skip_count) { + g_skip++; + DISPMSG("vsync|skip %d\n", g_skip); + ret = + dpmgr_wait_event_timeout(pgc->dpmgr_handle, + DISP_PATH_EVENT_IF_VSYNC, HZ / 10); + if (ret == -2) { + DISPPR_ERROR("vsync for primary display path not enabled yet\n"); + return -1; + } else if (ret == 0) { + primary_display_release_fence_fake(); + } + } + g_skip = 0; + } + } else { + g_keep = 0; + g_skip = 0; + } + + ret = dpmgr_wait_event_ts(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, &ts); + + if (ret == -2) { + DISPPR_ERROR("vsync for primary display path not enabled yet\n"); + goto out; + } else if (ret == 0) { + /* primary_display_release_fence_fake(); */ + } + + if (pgc->vsync_drop) { + /* ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, HZ/10); */ + ret = dpmgr_wait_event_ts(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, &ts); + } + +out: + c->vsync_ts = ts; + c->vsync_cnt++; + + return ret; +} + +unsigned int primary_display_get_ticket(void) +{ + return dprec_get_vsync_count(); +} + +int primary_suspend_release_fence(void) +{ + unsigned int session = (unsigned int)((DISP_SESSION_PRIMARY) << 16 | (0)); + unsigned int i = 0; + + for (i = 0; i < DISP_SESSION_TIMELINE_COUNT; i++) { + DISPDBG("mtkfb_release_layer_fence session=0x%x,layerid=%d\n", session, i); + mtkfb_release_layer_fence(session, i); + } + return 0; +} + +int primary_display_suspend(void) +{ + DISP_STATUS ret = DISP_STATUS_OK; + int event_ret; + + DISPMSG("primary_display_suspend begin\n"); + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagStart, 0, 0); + primary_display_idlemgr_kick((char *)__func__, 1); + + if (disp_helper_get_option(DISP_OPT_SWITCH_DST_MODE)) + primary_display_switch_dst_mode(primary_display_def_dst_mode); + + _primary_path_switch_dst_lock(); + disp_sw_mutex_lock(&(pgc->capture_lock)); + _primary_path_lock(__func__); + + while (primary_get_state() == DISP_BLANK) { + _primary_path_unlock(__func__); + DISPMSG("primary_display_suspend wait tui finish!!\n"); +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + switch_set_state(&disp_switch_data, DISP_SLEPT); +#endif + primary_display_wait_state(DISP_ALIVE, MAX_SCHEDULE_TIMEOUT); + _primary_path_lock(__func__); + DISPMSG("primary_display_suspend wait tui done stat=%d\n", primary_get_state()); + } + + display_freeze_mode(0, 0); + + if (pgc->state == DISP_SLEPT) { + DISPWRN("primary display path is already sleep, skip\n"); + goto done; + } + primary_display_idlemgr_kick((char *)__func__, 0); + + if (pgc->session_mode == DISP_SESSION_RDMA_MODE + || pgc->session_mode == DISP_SESSION_DECOUPLE_MODE) { + /* switch back to DL mode before suspend */ + do_primary_display_switch_mode(DISP_SESSION_DIRECT_LINK_MODE, + pgc->session_id, 0, NULL, 1); + } + + /* need leave share sram for suspend */ + if (disp_helper_get_option(DISP_OPT_SHARE_SRAM)) + leave_share_sram(CMDQ_SYNC_RESOURCE_WROT0); + + /* switch to vencpll before disable mmsys clk */ + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) + ;/* mmdvfs_notify_mmclk_switch_request(MMDVFS_EVENT_OVL_SINGLE_LAYER_EXIT); */ + /* blocking flush before stop trigger loop */ + _blocking_flush(); + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 1); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 1, 2); + event_ret = + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 2, 2); + DISPDBG + ("[POWER]primary display path is busy now, wait frame done, event_ret=%d\n", + event_ret); + if (event_ret <= 0) { + DISPERR("wait frame done in suspend timeout\n"); + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 3, + 2); + primary_display_diagnose(); + ret = -1; + } + } + + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 2); + + if (disp_helper_get_option(DISP_OPT_USE_CMDQ)) { + DISPDBG("[POWER]display cmdq trigger loop stop\n"); + _cmdq_stop_trigger_loop(); + } + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 3); + + DISPDBG("[POWER]primary display path stop[begin]\n"); + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + DISPMSG("[POWER]primary display path stop[end]\n"); + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 4); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 1, 4); + DISPERR("[POWER]stop display path failed, still busy\n"); + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + ret = -1; + /* even path is busy(stop fail), we still need to continue power off other module/devices */ + /* goto done; */ + } + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 5); + + DISPDBG("[POWER]lcm suspend[begin]\n"); + disp_lcm_suspend(pgc->plcm); + DISPMSG("[POWER]lcm suspend[end]\n"); + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 6); + DISPDBG("[POWER]primary display path Release Fence[begin]\n"); + primary_suspend_release_fence(); + DISPDBG("[POWER]primary display path Release Fence[end]\n"); + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 7); + + DISPDBG("[POWER]dpmanager path power off[begin]\n"); + dpmgr_path_power_off(pgc->dpmgr_handle, CMDQ_DISABLE); + if (primary_display_is_decouple_mode()) + dpmgr_path_power_off(pgc->ovl2mem_path_handle, CMDQ_DISABLE); + if (disp_helper_get_option(DISP_OPT_MET_LOG)) + set_enterulps(1); + + DISPMSG("[POWER]dpmanager path power off[end]\n"); + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 8); + +done: + primary_set_state(DISP_SLEPT); + _primary_path_unlock(__func__); + disp_sw_mutex_unlock(&(pgc->capture_lock)); + _primary_path_switch_dst_unlock(); + + aee_kernel_wdt_kick_Powkey_api("mtkfb_early_suspend", WDT_SETBY_Display); + primary_trigger_cnt = 0; + MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagEnd, 0, 0); + DISPMSG("primary_display_suspend end\n"); + return ret; +} + +int primary_display_get_lcm_index(void) +{ + int index = 0; + + DISPFUNC(); + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + index = pgc->plcm->index; + return index; +} + +int primary_display_resume(void) +{ + DISP_STATUS ret = DISP_STATUS_OK; + struct ddp_io_golden_setting_arg gset_arg; + int use_cmdq, i; + + DISPMSG("primary_display_resume begin\n"); + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagStart, 0, 0); + + _primary_path_lock(__func__); + use_cmdq = disp_helper_get_option(DISP_OPT_USE_CMDQ); + if (pgc->state == DISP_ALIVE) { + DISPMSG("primary display path is already resume, skip\n"); + goto done; + } + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 1); + + if (is_ipoh_bootup) { + DISPMSG("[primary display path] leave primary_display_resume -- IPOH\n"); + DISPMSG("ESD check start[begin]\n"); + primary_display_esd_check_enable(1); + DISPMSG("ESD check start[end]\n"); + is_ipoh_bootup = false; + DISPDBG("[POWER]start cmdq[begin]--IPOH\n"); + if (use_cmdq) + _cmdq_start_trigger_loop(); + enable_idlemgr(1); + DISPDBG("[POWER]start cmdq[end]--IPOH\n"); + goto done; + } + /* c/v switch by suspend start*/ + if (disp_helper_get_option(DISP_OPT_CV_BYSUSPEND)) { + if (lcm_mode_status != 0) { + static LCM_DSI_MODE_CON vdo_mode_type; + LCM_PARAMS *lcm_param_cv = NULL; + + lcm_param_cv = disp_lcm_get_params(pgc->plcm); + DISPMSG("lcm_mode_status=%d, lcm_param_cv->dsi.mode %d\n", + lcm_mode_status, lcm_param_cv->dsi.mode); + if (lcm_param_cv->dsi.mode != CMD_MODE) + vdo_mode_type = lcm_param_cv->dsi.mode; + if (lcm_mode_status == 1) { + lcm_dsi_mode = CMD_MODE; + spm_sodi_mempll_pwr_mode(0); + spm_enable_sodi(1); + } else if (lcm_mode_status == 2) { + if (vdo_mode_type) + lcm_dsi_mode = vdo_mode_type; + else + lcm_dsi_mode = SYNC_PULSE_VDO_MODE; + spm_sodi_mempll_pwr_mode(1); + spm_enable_sodi(1); + } else { + lcm_dsi_mode = lcm_param_cv->dsi.mode; + } + DSI_ForceConfig(1); + lcm_param_cv->dsi.mode = lcm_dsi_mode; + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, lcm_mode_status); + lcm_mode_status = 0; + if (disp_helper_get_option(DISP_OPT_CV_BYSUSPEND)) + primary_display_check_recovery_init(); + } + DISPDBG("lcm_mode_status=%d, lcm_dsi_mode=%d\n", lcm_mode_status, lcm_dsi_mode); + } + /* c/v switch by suspend end*/ + DISPDBG("dpmanager path power on[begin]\n"); + dpmgr_path_power_on(pgc->dpmgr_handle, CMDQ_DISABLE); + if (disp_helper_get_option(DISP_OPT_MET_LOG)) + set_enterulps(0); + + DISPMSG("dpmanager path power on[end]\n"); + DISPDBG("dpmanager path reset[begin]\n"); + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + DISPDBG("dpmanager path reset[end]\n"); + + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 2); + + DISPDBG("[POWER]dpmanager re-init[begin]\n"); + + { + LCM_PARAMS *lcm_param = NULL; + disp_ddp_path_config *data_config = NULL; + /* disconnect primary path first * + * because MMsys config register may not power off during early suspend + * BUT session mode may change in primary_display_switch_mode() */ + ddp_disconnect_path(DDP_SCENARIO_PRIMARY_ALL, NULL); + ddp_disconnect_path(DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP, NULL); + DISPDBG("cmd/video mode=%d\n", primary_display_is_video_mode()); + dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode()); + + dpmgr_path_connect(pgc->dpmgr_handle, CMDQ_DISABLE); + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 2); + lcm_param = disp_lcm_get_params(pgc->plcm); + + data_config = + dpmgr_path_get_last_config(pgc->dpmgr_handle); + memcpy(&(data_config->dispif_config), lcm_param, sizeof(LCM_PARAMS)); + + data_config->dst_w = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + data_config->dst_h = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + if (lcm_param->type == LCM_TYPE_DSI) { + if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB888) + data_config->lcm_bpp = 24; + else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB565) + data_config->lcm_bpp = 16; + else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB666) + data_config->lcm_bpp = 18; + } else if (lcm_param->type == LCM_TYPE_DPI) { + if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB888) + data_config->lcm_bpp = 24; + else if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB565) + data_config->lcm_bpp = 16; + if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB666) + data_config->lcm_bpp = 18; + } + + data_config->fps = pgc->lcm_fps; + data_config->dst_dirty = 1; + + /* disable all ovl layers to show black screen */ + /* note that if WFD is connected, we may miss the black setting before the last suspend */ + for (i = 0; i < ARRAY_SIZE(data_config->ovl_config); i++) { + if (is_DAL_Enabled() && + data_config->ovl_config[i].layer == primary_display_get_option("ASSERT_LAYER")) + continue; + data_config->ovl_config[i].layer_en = 0; + } + + data_config->ovl_dirty = 1; + + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, NULL); + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 2, 2); + data_config->dst_dirty = 0; + + memset(&gset_arg, 0, sizeof(gset_arg)); + gset_arg.dst_mod_type = dpmgr_path_get_dst_module_type(pgc->dpmgr_handle); + gset_arg.is_decouple_mode = primary_display_is_decouple_mode(); + dpmgr_path_ioctl(pgc->dpmgr_handle, NULL, DDP_OVL_GOLDEN_SETTING, &gset_arg); + + } + DISPMSG("[POWER]dpmanager re-init[end]\n"); + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 3); + + DISPDBG("[POWER]lcm resume[begin]\n"); + disp_lcm_resume(pgc->plcm); + DISPMSG("[POWER]lcm resume[end]\n"); + + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 4); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 4); + DISPERR("[POWER]Fatal error, we didn't start display path but it's already busy\n"); + ret = -1; + /* goto done; */ + } + + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 5); + DISPDBG("[POWER]dpmgr path start[begin]\n"); + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + + if (primary_display_is_decouple_mode()) + dpmgr_path_start(pgc->ovl2mem_path_handle, CMDQ_DISABLE); + + DISPDBG("[POWER]dpmgr path start[end]\n"); + + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 6); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 6); + DISPERR + ("[POWER]Fatal error, we didn't trigger display path but it's already busy\n"); + ret = -1; + /* goto done; */ + } + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 7); + + if (use_cmdq) { + DISPDBG("[POWER]build cmdq trigger loop[begin]\n"); + _cmdq_build_trigger_loop(); + DISPDBG("[POWER]build cmdq trigger loop[end]\n"); + } + + if (primary_display_is_video_mode()) { + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 7); + /* for video mode, we need to force trigger here */ + /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */ + if (_should_reset_cmdq_config_handle()) + _cmdq_reset_config_handle(); + if (_should_insert_wait_frame_done_token()) + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_RDMA0_DONE); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE); + } + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 8); + + if (use_cmdq) { + DISPDBG("[POWER]start cmdq[begin]\n"); + _cmdq_start_trigger_loop(); + DISPDBG("[POWER]start cmdq[end]\n"); + } + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 9); + + /* primary_display_diagnose(); */ + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 10); + + if (!primary_display_is_video_mode()) { + DISPDBG("[POWER]triggger cmdq[begin] cmd mode\n"); + if (_should_reset_cmdq_config_handle()) + _cmdq_reset_config_handle(); + if (_should_insert_wait_frame_done_token()) + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_DSI0_EXT_TE); + dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + + /*refresh black picture of ovl bg */ + _trigger_display_interface(1, NULL, 0); + DISPDBG("[POWER]triggger cmdq[end] cmd mode\n"); + mdelay(16); /* wait for one frame for pms workarround!!!! */ + } + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 11); + + /* (in suspend) when we stop trigger loop + * if no other thread is running, cmdq may disable its clock + * all cmdq event will be cleared after suspend */ + cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_EOF); + + /* reinit fake timer for debug, we can enable option then press powerkey to enable thsi feature. */ + /* use fake timer to generate vsync signal for cmd mode w/o LCM(originally using LCM TE Signal as VSYNC) */ + /* so we don't need to modify display driver's behavior. */ + if (disp_helper_get_option(DISP_OPT_NO_LCM_FOR_LOW_POWER_MEASUREMENT)) { + /* only for low power measurement */ + DISPWRN("WARNING!!!!!! FORCE NO LCM MODE!!!\n"); + islcmconnected = 0; + + /* no need to change video mode vsync behavior */ + if (!primary_display_is_video_mode()) { + _init_vsync_fake_monitor(pgc->lcm_fps); + + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_UNKNOWN); + } + } + + /* need enter share sram for resume */ + if (disp_helper_get_option(DISP_OPT_SHARE_SRAM)) + enter_share_sram(CMDQ_SYNC_RESOURCE_WROT0); + if (disp_helper_get_option(DISP_OPT_CV_BYSUSPEND)) + DSI_ForceConfig(0); +done: + primary_set_state(DISP_ALIVE); +#ifdef CONFIG_TRUSTONIC_TRUSTED_UI + switch_set_state(&disp_switch_data, DISP_ALIVE); +#endif + _primary_path_unlock(__func__); + + aee_kernel_wdt_kick_Powkey_api("mtkfb_late_resume", WDT_SETBY_Display); + MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagEnd, 0, 0); + return 0; +} + +int primary_display_ipoh_restore(void) +{ + DISPMSG("primary_display_ipoh_restore In\n"); + DISPDBG("ESD check stop[begin]\n"); + enable_idlemgr(0); + primary_display_esd_check_enable(0); + DISPMSG("ESD check stop[end]\n"); + if (NULL != pgc->cmdq_handle_trigger) { + struct TaskStruct *pTask = pgc->cmdq_handle_trigger->pRunningTask; + + if (NULL != pTask) { + DISPMSG("[Primary_display]display cmdq trigger loop stop[begin]\n"); + _cmdq_stop_trigger_loop(); + DISPMSG("[Primary_display]display cmdq trigger loop stop[end]\n"); + ddp_mutex_set_sof_wait(dpmgr_path_get_mutex(pgc->dpmgr_handle), NULL, 0); + } + } + DISPMSG("primary_display_ipoh_restore Out\n"); + return 0; +} + +int primary_display_start(void) +{ + DISP_STATUS ret = DISP_STATUS_OK; + + DISPFUNC(); + + _primary_path_lock(__func__); + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + DISPERR("Fatal error, we didn't trigger display path but it's already busy\n"); + ret = -1; + goto done; + } + +done: + _primary_path_unlock(__func__); + return ret; +} + +int primary_display_stop(void) +{ + DISP_STATUS ret = DISP_STATUS_OK; + + DISPFUNC(); + _primary_path_lock(__func__); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + + + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + DISPERR("stop display path failed, still busy\n"); + ret = -1; + goto done; + } + +done: + _primary_path_unlock(__func__); + return ret; +} + +void primary_display_update_present_fence(unsigned int fence_idx) +{ + gPresentFenceIndex = fence_idx; + atomic_set(&primary_display_present_fence_update_event, 1); + wake_up_interruptible(&primary_display_present_fence_wq); +} + +/* the function will trigger ovl->wdma */ +static int trigger_decouple_mirror(void) +{ + if (pgc->need_trigger_dcMirror_out == 0) { + /* DISPPR_ERROR("There is no output config when decouple mirror!!\n"); */ + } else { + pgc->need_trigger_dcMirror_out = 0; + + /* check if still in decouple mirror mode: * + * DC->DL switch may happen before vsync, it may free ovl2mem_handle ! */ + if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) { + _trigger_ovl_to_memory(pgc->ovl2mem_path_handle, + pgc->cmdq_handle_ovl1to2_config, + _ovl_wdma_fence_release_callback, + DISP_SESSION_DECOUPLE_MIRROR_MODE); + dprec_logger_trigger(DPREC_LOGGER_PRIMARY_TRIGGER, 0xffffffff, 0); + } else { + dprec_logger_trigger(DPREC_LOGGER_PRIMARY_TRIGGER, 0xffffffff, 0xaaaaaaaa); + } + } + return 0; +} + +static int primary_display_trigger_nolock(int blocking, void *callback, int need_merge) +{ + int ret = 0; + /* DISPFUNC(); */ + + last_primary_trigger_time = sched_clock(); + if (is_switched_dst_mode) { + primary_display_switch_dst_mode(1); /* swith to vdo mode if trigger disp */ + is_switched_dst_mode = false; + } + + primary_trigger_cnt++; + + if (pgc->state == DISP_SLEPT) { + DISPERR("%s, skip because primary dipslay is sleep\n", __func__); + goto done; + } + primary_display_idlemgr_kick((char *)__func__, 0); + + dprec_logger_start(DPREC_LOGGER_PRIMARY_TRIGGER, 0, 0); + + if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE || + pgc->session_mode == DISP_SESSION_RDMA_MODE) { + _trigger_display_interface(blocking, _ovl_fence_release_callback, + DISP_SESSION_DIRECT_LINK_MODE); + } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE) { + _trigger_display_interface(0, _ovl_fence_release_callback, + DISP_SESSION_DIRECT_LINK_MIRROR_MODE); + + if (pgc->need_trigger_ovl1to2 == 0) { + DISPPR_ERROR("There is no output config when directlink mirror!!\n"); + } else { + primary_display_remove_output(_wdma_fence_release_callback, + DISP_SESSION_DIRECT_LINK_MIRROR_MODE); + pgc->need_trigger_ovl1to2 = 0; + } + } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE) { + _trigger_ovl_to_memory(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config, + _ovl_fence_release_callback, DISP_SESSION_DECOUPLE_MODE); + } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) { + if (need_merge == 0 || primary_is_sec()) { + trigger_decouple_mirror(); + } else { + /* because only one of MM/UI thread will set output */ + /* we have to merge it up, then trigger at next vsync */ + /* see decouple_trigger_worker_thread below */ + atomic_set(&decouple_trigger_event, 1); + wake_up(&decouple_trigger_wq); + } + } + + dprec_logger_done(DPREC_LOGGER_PRIMARY_TRIGGER, 0, 0); + + smart_ovl_try_switch_mode_nolock(); + atomic_set(&delayed_trigger_kick, 1); +done: + if ((primary_trigger_cnt > 1) && aee_kernel_Powerkey_is_press()) { + aee_kernel_wdt_kick_Powkey_api("primary_display_trigger", WDT_SETBY_Display); + primary_trigger_cnt = 0; + } + + if (pgc->session_id > 0) + update_frm_seq_info(0, 0, 0, FRM_TRIGGER); + + return ret; +} + +int primary_display_trigger(int blocking, void *callback, int need_merge) +{ + int ret; + + _primary_path_lock(__func__); + ret = primary_display_trigger_nolock(blocking, callback, need_merge); + _primary_path_unlock(__func__); + return ret; +} + +/* the function will trigger dc and wake up dc thread for merge status; */ +/* decouple_trigger thread->trigger mirror->decouple_update_rdma_config_thread */ +static int decouple_trigger_worker_thread(void *data) +{ + struct sched_param param = {.sched_priority = RTPM_PRIO_SCRN_UPDATE }; + + sched_setscheduler(current, SCHED_RR, ¶m); + + while (1) { + wait_event(decouple_trigger_wq, atomic_read(&decouple_trigger_event)); + dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC); + + _primary_path_lock(__func__); + trigger_decouple_mirror(); + atomic_set(&decouple_trigger_event, 0); + wake_up(&decouple_trigger_wq); + _primary_path_unlock(__func__); + if (kthread_should_stop()) { + DISPERR("error: stop %s as demond\n", __func__); + break; + } + } + return 0; +} + +static int config_wdma_output(disp_path_handle disp_handle, + cmdqRecHandle cmdq_handle, disp_output_config *output) +{ + disp_ddp_path_config *pconfig = NULL; + + BUG_ON(output == NULL); + pconfig = dpmgr_path_get_last_config(disp_handle); + pconfig->wdma_config.dstAddress = (unsigned long)output->pa; + pconfig->wdma_config.srcHeight = disp_helper_get_option(DISP_OPT_FAKE_LCM_HEIGHT); + pconfig->wdma_config.srcWidth = disp_helper_get_option(DISP_OPT_FAKE_LCM_WIDTH); + pconfig->wdma_config.clipX = output->x; + pconfig->wdma_config.clipY = output->y; + pconfig->wdma_config.clipHeight = output->height; + pconfig->wdma_config.clipWidth = output->width; + pconfig->wdma_config.outputFormat = disp_fmt_to_unified_fmt(output->fmt); + pconfig->wdma_config.useSpecifiedAlpha = 1; + pconfig->wdma_config.alpha = 0xFF; + pconfig->wdma_config.dstPitch = output->pitch * UFMT_GET_Bpp(pconfig->wdma_config.outputFormat); + pconfig->wdma_config.security = output->security; + pconfig->wdma_dirty = 1; + + return dpmgr_path_config(disp_handle, pconfig, cmdq_handle); +} + +static int _convert_disp_output_to_memout(disp_output_config *src, disp_mem_output_config *dst) +{ + dst->fmt = disp_fmt_to_unified_fmt(src->fmt); + + dst->vaddr = (unsigned long)src->va; + dst->security = src->security; + dst->w = src->width; + dst->h = src->height; + + dst->addr = (unsigned long)src->pa; + + dst->buff_idx = src->buff_idx; + dst->interface_idx = src->interface_idx; + + dst->x = src->x; + dst->y = src->y; + dst->pitch = src->pitch * UFMT_GET_Bpp(dst->fmt); + return 0; +} + +static int primary_frame_cfg_output(struct disp_frame_cfg_t *cfg) +{ + int ret = 0; + disp_path_handle disp_handle; + cmdqRecHandle cmdq_handle = NULL; + + if (pgc->state == DISP_SLEPT) { + DISPERR("mem out is already slept or mode wrong(%d)\n", pgc->session_mode); + goto done; + } + + if (!primary_display_is_mirror_mode()) { + DISPERR("should not config output if not mirror mode!!\n"); + goto done; + } + + if (primary_display_is_decouple_mode()) { + disp_handle = pgc->ovl2mem_path_handle; + cmdq_handle = pgc->cmdq_handle_ovl1to2_config; + } else { + disp_handle = pgc->dpmgr_handle; + cmdq_handle = pgc->cmdq_handle_config; + } + + if (primary_display_is_decouple_mode()) { + pgc->need_trigger_dcMirror_out = 1; + } else { + /*direct link mirror mode should add memout first */ + dpmgr_path_add_memout(pgc->dpmgr_handle, DISP_MODULE_OVL0, cmdq_handle); + pgc->need_trigger_ovl1to2 = 1; + } + + ret = config_wdma_output(disp_handle, cmdq_handle, &cfg->output_cfg); + + if ((pgc->session_id > 0) && primary_display_is_decouple_mode()) { + update_frm_seq_info((unsigned long)cfg->output_cfg.pa, 0, + mtkfb_query_frm_seq_by_addr(pgc->session_id, 0, 0), FRM_CONFIG); + } + + _convert_disp_output_to_memout(&cfg->output_cfg, &mem_config); + + MMProfileLogEx(ddp_mmp_get_events()->primary_wdma_config, MMProfileFlagPulse, + cfg->output_cfg.buff_idx, (unsigned long)cfg->output_cfg.pa); + +done: + return ret; +} + +typedef enum { + SVP_NOMAL = 0, + SVP_IN_POINT, + SVP_SEC, + SVP_2_NOMAL, + SVP_EXIT_POINT +} SVP_STATE; +static SVP_STATE svp_state = SVP_NOMAL; +static int svp_sum; + +#ifndef OPT_BACKUP_NUM + #define OPT_BACKUP_NUM 3 +#endif + +static DISP_HELPER_OPT opt_backup_name[OPT_BACKUP_NUM] = { + DISP_OPT_SMART_OVL, + DISP_OPT_IDLEMGR_SWTCH_DECOUPLE, + DISP_OPT_BYPASS_OVL +}; +static int opt_backup_value[OPT_BACKUP_NUM]; +unsigned int idlemgr_flag_backup; + +static int disp_enter_svp(SVP_STATE state) +{ + int i; + + if (state == SVP_IN_POINT) { + + for (i = 0; i < OPT_BACKUP_NUM; i++) { + opt_backup_value[i] = disp_helper_get_option(opt_backup_name[i]); + disp_helper_set_option(opt_backup_name[i], 0); + } + + if (primary_display_is_decouple_mode() && (!primary_display_is_mirror_mode())) { + /* switch to DL */ + do_primary_display_switch_mode(DISP_SESSION_DIRECT_LINK_MODE, pgc->session_id, 0, NULL, 0); + } + idlemgr_flag_backup = set_idlemgr(0, 0); + } + + return 0; +} + +static int disp_leave_svp(SVP_STATE state) +{ + int i; + + if (state == SVP_EXIT_POINT) { + + for (i = 0; i < OPT_BACKUP_NUM; i++) + disp_helper_set_option(opt_backup_name[i], opt_backup_value[i]); + + set_idlemgr(idlemgr_flag_backup, 0); + } + return 0; +} + +static int setup_disp_sec(disp_ddp_path_config *data_config, cmdqRecHandle cmdq_handle, + int is_locked) +{ + int i, has_sec_layer = 0; + + for (i = 0; i < ARRAY_SIZE(data_config->ovl_config); i++) { + if (data_config->ovl_config[i].layer_en && (data_config->ovl_config[i].security == DISP_SECURE_BUFFER)) + has_sec_layer = 1; + } + + if (has_sec_layer != primary_is_sec()) { + MMProfileLogEx(ddp_mmp_get_events()->sec, MMProfileFlagPulse, has_sec_layer, 0); + /* sec/nonsec switch */ + + cmdqRecReset(cmdq_handle); + if (primary_display_is_decouple_mode()) + cmdqRecWait(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_EOF); + else + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + + + MMProfileLogEx(ddp_mmp_get_events()->sec, MMProfileFlagPulse, has_sec_layer, 1); + + if (has_sec_layer) { + /* switch nonsec --> sec */ + svp_state = SVP_IN_POINT; + disp_enter_svp(svp_state); + MMProfileLogEx(ddp_mmp_get_events()->sec, MMProfileFlagStart, 0, 0); + } else { + /*switch sec --> nonsec */ + svp_state = SVP_2_NOMAL; + MMProfileLogEx(ddp_mmp_get_events()->sec, MMProfileFlagEnd, 0, 0); + } + } + + if ((has_sec_layer == primary_is_sec()) && (primary_is_sec() == 0)) { + + if (svp_state == SVP_2_NOMAL) { + svp_sum++; + /*after 3 normal frame, we restore the normal environment*/ + if (svp_sum > 2) { + svp_sum = 0; + svp_state = SVP_EXIT_POINT; + disp_leave_svp(svp_state); + } + } else + svp_state = SVP_NOMAL; + + } + + if ((has_sec_layer == primary_is_sec()) && (primary_is_sec() == 1)) { + /* IN SVP now!*/ + svp_state = SVP_SEC; + } + + pgc->is_primary_sec = has_sec_layer; + return 0; +} + +static int can_bypass_ovl(disp_ddp_path_config *data_config, int *bypass_layer_id) +{ + int total_layer = 0; + int i; + unsigned int w, h; + +#ifdef CONFIG_MTK_LCM_PHYSICAL_ROTATION_HW + /* rdma don't support rotation */ + return 0; +#endif + + if (!disp_helper_get_option(DISP_OPT_BYPASS_OVL)) + return 0; + + for (i = 0; i < ARRAY_SIZE(data_config->ovl_config); i++) { + if (data_config->ovl_config[i].layer_en) { + total_layer++; + *bypass_layer_id = i; + } + } + + if (total_layer != 1) + return 0; + + /* rdma cannot process dim layer */ + if (data_config->ovl_config[*bypass_layer_id].source != OVL_LAYER_SOURCE_MEM) + return 0; + + /* now we have only 1 layer */ + /* check background (bg). + * If top_bg=0, and left bg!=0, we should not use rdma mode. + */ + if (data_config->ovl_config[*bypass_layer_id].dst_y == 0 && + data_config->ovl_config[*bypass_layer_id].dst_x != 0) + return 0; + + /* we need to check layer size, because rdma has output_valid_thres setting + * if (size < output_valid_thres) RDMA will hang !!*/ + h = data_config->ovl_config[*bypass_layer_id].dst_h; + w = data_config->ovl_config[*bypass_layer_id].dst_w; + if (w * h <= 512 * 16 / 2) + return 0; + /* RDMA must use even width */ + if (w & 0x1) + return 0; + + + return 1; +} + +static int _config_ovl_input(struct disp_frame_cfg_t *cfg, + disp_path_handle disp_handle, cmdqRecHandle cmdq_handle) +{ + int ret = 0, i = 0, layer = 0; + disp_ddp_path_config *data_config = NULL; + int max_layer_id_configed = 0; + int bypass, bypass_layer_id = 0; + int overlap_layers; + +#ifdef DEBUG_OVL_CONFIG_TIME + cmdqRecBackupRegisterToSlot(cmdq_handle, pgc->ovl_config_time, 0, 0x10008028); +#endif + /*=== create new data_config for ovl input ===*/ + data_config = dpmgr_path_get_last_config(disp_handle); + for (i = 0; i < cfg->input_layer_num; i++) { + disp_input_config *input_cfg = &cfg->input_cfg[i]; + OVL_CONFIG_STRUCT *ovl_cfg; + + layer = input_cfg->layer_id; + ovl_cfg = &(data_config->ovl_config[layer]); + if (cfg->setter != SESSION_USER_AEE) { + if (is_DAL_Enabled() && layer == primary_display_get_option("ASSERT_LAYER")) { + DISPMSG("skip AEE layer %d\n", layer); + continue; + } + } else { + DISPMSG("set AEE layer %d\n", layer); + } + _convert_disp_input_to_ovl(ovl_cfg, input_cfg); + + dprec_logger_start(DPREC_LOGGER_PRIMARY_CONFIG, + ovl_cfg->layer | (ovl_cfg->layer_en << 16), ovl_cfg->addr); + dprec_logger_done(DPREC_LOGGER_PRIMARY_CONFIG, ovl_cfg->src_x, ovl_cfg->src_y); + + dprec_mmp_dump_ovl_layer(ovl_cfg, layer, 1); + + if ((ovl_cfg->layer == 0) && (!primary_display_is_decouple_mode())) + update_frm_seq_info(ovl_cfg->addr, + ovl_cfg->src_x * 4 + + ovl_cfg->src_y * ovl_cfg->src_pitch, + mtkfb_query_frm_seq_by_addr(pgc->session_id, 0, 0), + FRM_CONFIG); + + if (max_layer_id_configed < layer) + max_layer_id_configed = layer; + + data_config->ovl_layer_dirty |= (1 << i); + } + + overlap_layers = cfg->overlap_layer_num; + data_config->overlap_layer_num = overlap_layers; + + if (!_requestCondition(overlap_layers)) { + _request_dvfs_perf(OPPI_PERF); + dvfs_last_ovl_req = OPPI_PERF; + } else { + dvfs_last_ovl_req = OPPI_UNREQ; + } + if (disp_helper_get_option(DISP_OPT_SHOW_VISUAL_DEBUG_INFO)) { + char msg[10]; + + snprintf(msg, sizeof(msg), "HRT=%d,", overlap_layers); + screen_logger_add_message("HRT", MESSAGE_REPLACE, msg); + } + + if (_should_wait_path_idle()) + dpmgr_wait_event_timeout(disp_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + + if (cmdq_handle) + setup_disp_sec(data_config, cmdq_handle, 1); + if (primary_display_is_decouple_mode()) { + disp_handle = pgc->ovl2mem_path_handle; + cmdq_handle = pgc->cmdq_handle_ovl1to2_config; + } else { + disp_handle = pgc->dpmgr_handle; + cmdq_handle = pgc->cmdq_handle_config; + } + data_config = dpmgr_path_get_last_config(disp_handle); + data_config->overlap_layer_num = overlap_layers; + + /* check bypass ovl */ + bypass = can_bypass_ovl(data_config, &bypass_layer_id); + if (bypass) { + /* switch to rdma mode */ + if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE) { + do_primary_display_switch_mode(DISP_SESSION_RDMA_MODE, pgc->session_id, 0, + cmdq_handle, 0); + } + } else { + if (pgc->session_mode == DISP_SESSION_RDMA_MODE) { + do_primary_display_switch_mode(DISP_SESSION_DIRECT_LINK_MODE, pgc->session_id, 0, + cmdq_handle, 0); + } + } + + + if (pgc->session_mode != DISP_SESSION_RDMA_MODE) { + data_config->ovl_dirty = 1; + } else { + ret = ddp_convert_ovl_input_to_rdma(&data_config->rdma_config, + &data_config->ovl_config[bypass_layer_id], + data_config->dst_w, data_config->dst_h); + data_config->rdma_dirty = 1; + + /* no need ioctl because of rdma_dirty */ + set_is_dc(1); + + dynamic_debug_msg_print(data_config->rdma_config.address, data_config->rdma_config.width, + data_config->rdma_config.height, data_config->rdma_config.pitch, + UFMT_GET_Bpp(data_config->rdma_config.inputFormat)); + + } + + if (disp_helper_get_option(DISP_OPT_DYNAMIC_SWITCH_MMSYSCLK)) { + if (bypass) { + if (set_one_layer(1)) + ; /* mmdvfs_notify_mmclk_switch_request(MMDVFS_EVENT_OVL_SINGLE_LAYER_ENTER); */ + } else { + if (set_one_layer(0)) + ; /* mmdvfs_notify_mmclk_switch_request(MMDVFS_EVENT_OVL_SINGLE_LAYER_EXIT); */ + } + } + + ret = dpmgr_path_config(disp_handle, data_config, cmdq_handle); + +#ifdef DEBUG_OVL_CONFIG_TIME + cmdqRecBackupRegisterToSlot(cmdq_handle, pgc->ovl_config_time, 1, 0x10008028); +#endif + if (!cmdq_handle) + goto done; + + /* write fence_id/enable to DRAM using cmdq + * it will be used when release fence (put these after config registers done)*/ + for (i = 0; i < cfg->input_layer_num; i++) { + unsigned int last_fence, cur_fence, sub; + disp_input_config *input_cfg = &cfg->input_cfg[i]; + + layer = input_cfg->layer_id; + + cmdqBackupReadSlot(pgc->cur_config_fence, layer, &last_fence); + cur_fence = input_cfg->next_buff_idx; + + if (cur_fence != -1 && cur_fence > last_fence) + cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_config_fence, layer, cur_fence); + + /* for dim_layer/disable_layer/no_fence_layer, just release all fences configured */ + /* for other layers, release current_fence-1 */ + if (input_cfg->buffer_source == DISP_BUFFER_ALPHA + || input_cfg->layer_enable == 0 || cur_fence == -1) + sub = 0; + else + sub = 1; + + /* store overlap layer to layer0's subtractor_when_free : bit[31:16] */ + if (layer == 0) + sub |= overlap_layers << 16; + cmdqRecBackupUpdateSlot(cmdq_handle, pgc->subtractor_when_free, layer, sub); + } + + if (primary_display_is_video_mode() && !primary_display_is_decouple_mode()) { + unsigned long ovl_base = ovl_base_addr(DISP_MODULE_OVL1_2L); + + cmdqRecBackupRegisterToSlot(cmdq_handle, pgc->ovl_status_info, + 0, disp_addr_convert(DISP_REG_OVL_STA + ovl_base)); + } + +done: +#ifdef DEBUG_OVL_CONFIG_TIME + cmdqRecBackupRegisterToSlot(cmdq_handle, pgc->ovl_config_time, 2, 0x10008028); +#endif + return ret; +} + +/* notes: primary lock should be held when call this func */ +static int primary_frame_cfg_input(struct disp_frame_cfg_t *cfg) +{ + int ret = 0; + unsigned int wdma_mva = 0; + disp_path_handle disp_handle; + cmdqRecHandle cmdq_handle; + + primary_display_idlemgr_kick((char *)__func__, 0); + + if (primary_display_is_decouple_mode()) { + disp_handle = pgc->ovl2mem_path_handle; + cmdq_handle = pgc->cmdq_handle_ovl1to2_config; + } else { + disp_handle = pgc->dpmgr_handle; + cmdq_handle = pgc->cmdq_handle_config; + } + + if (pgc->state == DISP_SLEPT) { + DISPERR("%s, skip because primary dipslay is slept\n", __func__); + + if (is_DAL_Enabled() && + cfg->setter == SESSION_USER_AEE && + cfg->input_cfg[0].layer_id == primary_display_get_option("ASSERT_LAYER")) { + disp_ddp_path_config *data_config = dpmgr_path_get_last_config(disp_handle); + int layer = cfg->input_cfg[0].layer_id; + + ret = _convert_disp_input_to_ovl(&(data_config->ovl_config[layer]), + &cfg->input_cfg[0]); + } + + goto done; + } + + fps_ctx_update(&primary_fps_ctx); + if (disp_helper_get_option(DISP_OPT_SHOW_VISUAL_DEBUG_INFO)) + primary_show_basic_debug_info(cfg); + + _config_ovl_input(cfg, disp_handle, cmdq_handle); + + if (primary_display_is_decouple_mode() && !primary_display_is_mirror_mode()) { + pgc->dc_buf_id++; + pgc->dc_buf_id %= DISP_INTERNAL_BUFFER_COUNT; + wdma_mva = pgc->dc_buf[pgc->dc_buf_id]; + decouple_wdma_config.dstAddress = wdma_mva; + _config_wdma_output(&decouple_wdma_config, pgc->ovl2mem_path_handle, + pgc->cmdq_handle_ovl1to2_config); + mem_config.addr = wdma_mva; + mem_config.buff_idx = -1; + mem_config.interface_idx = -1; + mem_config.security = DISP_NORMAL_BUFFER; + mem_config.pitch = decouple_wdma_config.dstPitch; + mem_config.fmt = decouple_wdma_config.outputFormat; + MMProfileLogEx(ddp_mmp_get_events()->primary_wdma_config, MMProfileFlagPulse, + pgc->dc_buf_id, wdma_mva); + } +done: + return ret; +} + +int primary_display_config_input_multiple(disp_session_input_config *session_input) +{ + int ret = 0; + struct disp_frame_cfg_t *frame_cfg; + + BUG_ON(sizeof(session_input->config) != sizeof(frame_cfg->input_cfg)); + + frame_cfg = kzalloc(sizeof(struct disp_frame_cfg_t), GFP_KERNEL); + if (frame_cfg == NULL) + return -ENOMEM; + + frame_cfg->session_id = session_input->session_id; + frame_cfg->setter = session_input->setter; + frame_cfg->input_layer_num = session_input->config_layer_num; + frame_cfg->overlap_layer_num = 4; + memcpy(frame_cfg->input_cfg, session_input->config, sizeof(frame_cfg->input_cfg)); + + _primary_path_lock(__func__); + + ret = primary_frame_cfg_input(frame_cfg); + + _primary_path_unlock(__func__); + + kfree(frame_cfg); + return ret; +} + +int primary_display_frame_cfg(struct disp_frame_cfg_t *cfg) +{ + int ret = 0; + disp_session_sync_info *session_info = disp_get_session_sync_info_for_debug(cfg->session_id); + dprec_logger_event *input_event, *output_event, *trigger_event; + + if (session_info) { + input_event = &session_info->event_setinput; + output_event = &session_info->event_setoutput; + trigger_event = &session_info->event_trigger; + } else { + input_event = output_event = trigger_event = NULL; + } + + _primary_path_lock(__func__); + + /* set input */ + dprec_start(input_event, cfg->overlap_layer_num, cfg->input_layer_num); + primary_frame_cfg_input(cfg); + dprec_done(input_event, 0, 0); + + if (cfg->output_en) { + dprec_start(output_event, cfg->output_cfg.buff_idx, 0); + primary_frame_cfg_output(cfg); + dprec_done(output_event, 0, 0); + } + + if (trigger_event) { + /* to debug UI thread or MM thread */ + unsigned int proc_name = (current->comm[0] << 24) | + (current->comm[1] << 16) | (current->comm[2] << 8) | (current->comm[3] << 0); + dprec_start(trigger_event, proc_name, 0); + } + + if (cfg->present_fence_idx != (unsigned int)-1) + primary_display_update_present_fence(cfg->present_fence_idx); + + primary_display_trigger_nolock(0, NULL, 0); + + dprec_done(trigger_event, 0, 0); + + _primary_path_unlock(__func__); + return ret; +} + + +int primary_display_user_cmd(unsigned int cmd, unsigned long arg) +{ + int ret = 0; + cmdqRecHandle handle = NULL; + int cmdqsize = 0; + + MMProfileLogEx(ddp_mmp_get_events()->primary_display_cmd, + MMProfileFlagStart, (unsigned long)handle, 0); + + if (disp_helper_get_option(DISP_OPT_USE_CMDQ)) { + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle); + cmdqRecReset(handle); + _cmdq_insert_wait_frame_done_token_mira(handle); + cmdqsize = cmdqRecGetInstructionCount(handle); + } + + if (cmd == DISP_IOCTL_AAL_GET_HIST) { + _primary_path_lock(__func__); + if (pgc->state == DISP_SLEPT && handle) { + cmdqRecDestroy(handle); + handle = NULL; + } + _primary_path_unlock(__func__); + + /* only cmd mode & with disable mmsys clk will kick */ + if (disp_helper_get_option(DISP_OPT_IDLEMGR_ENTER_ULPS) && + !primary_display_is_video_mode()) + primary_display_idlemgr_kick((char *)__func__, 1); + ret = dpmgr_path_user_cmd(pgc->dpmgr_handle, cmd, arg, handle); + + if (handle) { + if (cmdqRecGetInstructionCount(handle) > cmdqsize) { + _primary_path_lock(__func__); + if (pgc->state == DISP_ALIVE) { + /* do not set dirty here, just write register. */ + /* if set dirty needed, will be implemented by dpmgr_module_notify() */ + /* _cmdq_set_config_handle_dirty_mira(handle); */ + /* use non-blocking flush here to avoid primary path is locked for too long */ + _cmdq_flush_config_handle_mira(handle, 0); + } + _primary_path_unlock(__func__); + } + + cmdqRecDestroy(handle); + } + } else { + _primary_path_switch_dst_lock(); + _primary_path_lock(__func__); + if (pgc->state == DISP_SLEPT && handle) { + cmdqRecDestroy(handle); + handle = NULL; + goto user_cmd_unlock; + } + /* only cmd mode & with disable mmsys clk will kick */ + if (disp_helper_get_option(DISP_OPT_IDLEMGR_ENTER_ULPS) && + !primary_display_is_video_mode()) + primary_display_idlemgr_kick((char *)__func__, 0); + ret = dpmgr_path_user_cmd(pgc->dpmgr_handle, cmd, arg, handle); + + if (handle) { + if (cmdqRecGetInstructionCount(handle) > cmdqsize) { + if (pgc->state == DISP_ALIVE) { + /* do not set dirty here, just write register. */ + /* if set dirty needed, will be implemented by dpmgr_module_notify() */ + /* _cmdq_set_config_handle_dirty_mira(handle); */ + /* use non-blocking flush here to avoid primary path is locked for too long */ + _cmdq_flush_config_handle_mira(handle, 0); + } + } + + cmdqRecDestroy(handle); + } +user_cmd_unlock: + _primary_path_unlock(__func__); + _primary_path_switch_dst_unlock(); + + } + MMProfileLogEx(ddp_mmp_get_events()->primary_display_cmd, + MMProfileFlagEnd, (unsigned long)handle, cmdqsize); + + return ret; +} + +int do_primary_display_switch_mode(int sess_mode, unsigned int session, int need_lock, + cmdqRecHandle handle, int block) +{ + int ret = 0, sw_only = 0; + + if (need_lock) + _primary_path_lock(__func__); + + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagStart, + pgc->session_mode, sess_mode); + + if (pgc->session_mode == sess_mode) + goto done; + + + if (pgc->state == DISP_SLEPT) { + DISPERR("primary display switch from %s to %s in suspend state!!!\n", + session_mode_spy(pgc->session_mode), session_mode_spy(sess_mode)); + sw_only = 1; + } + + DISPMSG("primary display will switch from %s to %s\n", session_mode_spy(pgc->session_mode), + session_mode_spy(sess_mode)); + + if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE + && sess_mode == DISP_SESSION_DECOUPLE_MODE) { + /* dl to dc */ + DL_switch_to_DC_fast(sw_only); + } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE + && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) { + /* dc to dl */ + DC_switch_to_DL_fast(sw_only); + /* primary_display_diagnose(); */ + } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE + && sess_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE) { + /* dl to dl mirror */ + } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE + && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) { + /*dl mirror to dl */ + } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE + && sess_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) { + if (disp_helper_get_option(DISP_OPT_GMO_OPTIMIZE)) + ret = pd_allocate_dc_buffer(); + if (ret) + goto err; + /* dl to dc mirror mirror */ + DL_switch_to_DC_fast(sw_only); + } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE + && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) { + /*dc mirror to dl */ + DC_switch_to_DL_fast(sw_only); + } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE && + sess_mode == DISP_SESSION_DECOUPLE_MODE){ + /* do nothing */ + /* just switch mode */ + } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE && + sess_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE){ + /* do nothing */ + /* just switch mode */ + } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE && sess_mode == DISP_SESSION_RDMA_MODE) { + ret = DL_switch_to_rdma_mode(handle, block); + if (ret) + goto err; + } else if (pgc->session_mode == DISP_SESSION_RDMA_MODE && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) { + ret = rdma_mode_switch_to_DL(handle, block); + if (ret) + goto err; + } else if (pgc->session_mode == DISP_SESSION_RDMA_MODE && sess_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) { + /* switch to DL mode first */ + ret = rdma_mode_switch_to_DL(NULL, 0); + if (ret) + goto err; + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, pgc->session_mode, 0); + DL_switch_to_DC_fast(0); + } else if (pgc->session_mode == DISP_SESSION_RDMA_MODE && sess_mode == DISP_SESSION_DECOUPLE_MODE) { + /* switch to DL mode first */ + ret = rdma_mode_switch_to_DL(NULL, 0); + if (ret) + goto err; + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, pgc->session_mode, 0); + DL_switch_to_DC_fast(0); + } else { + DISPERR("invalid mode switch from %s to %s\n", session_mode_spy(pgc->session_mode), + session_mode_spy(sess_mode)); + BUG(); + } +done: + MMProfileLogEx(ddp_mmp_get_events()->primary_mode[pgc->session_mode], + MMProfileFlagEnd, pgc->session_mode, sess_mode); + MMProfileLogEx(ddp_mmp_get_events()->primary_mode[sess_mode], + MMProfileFlagStart, pgc->session_mode, sess_mode); + + pgc->session_mode = sess_mode; + DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode)); + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse, pgc->session_mode, sess_mode); + pgc->session_id = session; + screen_logger_add_message("sess_mode", MESSAGE_REPLACE, (char *)session_mode_spy(sess_mode)); +err: + MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagEnd, pgc->session_mode, sess_mode); + + if (need_lock) + _primary_path_unlock(__func__); + pgc->session_id = session; + return ret; +} + +int primary_display_switch_mode(int sess_mode, unsigned int session, int force) +{ + int ret = 0; + + _primary_path_lock(__func__); + if (bypass_blank && !force) { + DISPMSG("%s DISPLAY UT Return!\n", __func__); + goto done; + } + primary_display_idlemgr_kick((char *)__func__, 0); + + if (!force && primary_display_is_mirror_mode() == _is_mirror_mode(sess_mode)) { + /* HWC only needs to control mirror/not mirror + * it doesn't need to control DL/DC */ + goto done; + } + + if (pgc->session_mode == sess_mode) + goto done; + + while (primary_get_state() == DISP_BLANK) { + _primary_path_unlock(__func__); + DISPMSG("%s wait for leave TUI\n", __func__); + primary_display_wait_not_state(DISP_BLANK, MAX_SCHEDULE_TIMEOUT); + _primary_path_lock(__func__); + } + + ret = do_primary_display_switch_mode(sess_mode, session, 0, NULL, 0); + +done: + _primary_path_unlock(__func__); + + return ret; +} + +static int smart_ovl_try_switch_mode_nolock(void) +{ + unsigned int hwc_fps, lcm_fps; + unsigned long long ovl_sz, rdma_sz; + disp_path_handle disp_handle = NULL; + disp_ddp_path_config *data_config = NULL; + int i, stable; + unsigned long long DL_bw, DC_bw, bw_th; + + if (get_boot_mode() == FACTORY_BOOT) + return 0; + + if (!disp_helper_get_option(DISP_OPT_SMART_OVL)) + return 0; + + if (!primary_display_is_video_mode()) + return 0; + + if (pgc->session_mode != DISP_SESSION_DIRECT_LINK_MODE && + pgc->session_mode != DISP_SESSION_DECOUPLE_MODE) + return 0; + + if (pgc->state != DISP_ALIVE) + return 0; + + lcm_fps = pgc->lcm_fps / 100; + fps_ctx_get_fps(&primary_fps_ctx, &hwc_fps, &stable); + + /* we switch DL->DC only when fps is stable ! */ + if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE) { + if (!stable) + return 0; + } + + if (hwc_fps > lcm_fps) + hwc_fps = lcm_fps; + + if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE) + disp_handle = pgc->ovl2mem_path_handle; + else + disp_handle = pgc->dpmgr_handle; + + data_config = dpmgr_path_get_last_config(disp_handle); + + /* calc wdma/rdma data size */ + rdma_sz = data_config->dst_h * data_config->dst_w * 3; + + /* calc ovl data size */ + ovl_sz = 0; + for (i = 0; i < ARRAY_SIZE(data_config->ovl_config); i++) { + OVL_CONFIG_STRUCT *ovl_cfg = &(data_config->ovl_config[i]); + + if (ovl_cfg->layer_en) { + unsigned int Bpp = UFMT_GET_Bpp(ovl_cfg->fmt); + + ovl_sz += ovl_cfg->dst_w * ovl_cfg->dst_h * Bpp; + } + } + + /* switch criteria is: (DL) V.S. (DC): + * (ovl * lcm_fps) V.S. (ovl * hwc_fps + wdma * hwc_fps + rdma * lcm_fps) + */ + DL_bw = ovl_sz * lcm_fps; + DC_bw = (ovl_sz + rdma_sz) * hwc_fps + rdma_sz * lcm_fps; + + if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE) { + bw_th = DL_bw*4; + do_div(bw_th, 5); + if (DC_bw < bw_th) { + /* switch to DC */ + do_primary_display_switch_mode(DISP_SESSION_DECOUPLE_MODE, pgc->session_id, 0, NULL, 0); + } + } else { + bw_th = DC_bw*4; + do_div(bw_th, 5); + if (DL_bw < bw_th) { + /* switch to DL */ + do_primary_display_switch_mode(DISP_SESSION_DIRECT_LINK_MODE, pgc->session_id, 0, NULL, 0); + } + } + + return 0; +} + +int primary_display_is_alive(void) +{ + unsigned int temp = 0; + + _primary_path_lock(__func__); + + if (pgc->state == DISP_ALIVE) + temp = 1; + + + _primary_path_unlock(__func__); + + return temp; +} + +int primary_display_is_sleepd(void) +{ + unsigned int temp = 0; + + _primary_path_lock(__func__); + + if (pgc->state == DISP_SLEPT) + temp = 1; + + + _primary_path_unlock(__func__); + + return temp; +} + +int primary_display_get_width(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->params->width; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +int primary_display_get_height(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->params->height; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +int primary_display_get_virtual_width(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->params->virtual_width; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +int primary_display_get_virtual_height(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->params->virtual_height; + + DISPERR("lcm_params is null!\n"); + return 0; +} +int primary_display_get_original_width(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->lcm_original_width; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +int primary_display_get_original_height(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->lcm_original_height; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +int primary_display_get_bpp(void) +{ + return 32; +} + +void primary_display_set_max_layer(int maxlayer) +{ + pgc->max_layer = maxlayer; +} + +int primary_display_get_max_layer(void) +{ + return pgc->max_layer; +} + +int primary_display_get_info(disp_session_info *info) +{ + disp_session_info *dispif_info = (disp_session_info *) info; + LCM_PARAMS *lcm_param = disp_lcm_get_params(pgc->plcm); + + if (lcm_param == NULL) { + DISPERR("lcm_param is null\n"); + return -1; + } + + memset((void *)dispif_info, 0, sizeof(disp_session_info)); + + if (is_DAL_Enabled()) + dispif_info->maxLayerNum = pgc->max_layer - 1; + else + dispif_info->maxLayerNum = pgc->max_layer; + + dispif_info->const_layer_num = 0; + + switch (lcm_param->type) { + case LCM_TYPE_DBI: + { + dispif_info->displayType = DISP_IF_TYPE_DBI; + dispif_info->displayMode = DISP_IF_MODE_COMMAND; + dispif_info->isHwVsyncAvailable = 1; + /* DISPMSG("DISP Info: DBI, CMD Mode, HW Vsync enable\n"); */ + break; + } + case LCM_TYPE_DPI: + { + dispif_info->displayType = DISP_IF_TYPE_DPI; + dispif_info->displayMode = DISP_IF_MODE_VIDEO; + dispif_info->isHwVsyncAvailable = 1; + /* DISPMSG("DISP Info: DPI, VDO Mode, HW Vsync enable\n"); */ + break; + } + case LCM_TYPE_DSI: + { + dispif_info->displayType = DISP_IF_TYPE_DSI0; + if (lcm_param->dsi.mode == CMD_MODE) { + dispif_info->displayMode = DISP_IF_MODE_COMMAND; + dispif_info->isHwVsyncAvailable = 1; + /* DISPMSG("DISP Info: DSI, CMD Mode, HW Vsync enable\n"); */ + } else { + dispif_info->displayMode = DISP_IF_MODE_VIDEO; + dispif_info->isHwVsyncAvailable = 1; + /* DISPMSG("DISP Info: DSI, VDO Mode, HW Vsync enable\n"); */ + } + + break; + } + default: + break; + } + + + dispif_info->displayFormat = DISP_IF_FORMAT_RGB888; + + dispif_info->displayWidth = primary_display_get_width(); + dispif_info->displayHeight = primary_display_get_height(); + + dispif_info->physicalWidth = DISP_GetActiveWidth(); + dispif_info->physicalHeight = DISP_GetActiveHeight(); + dispif_info->physicalWidthUm = DISP_GetActiveWidthUm(); + dispif_info->physicalHeightUm = DISP_GetActiveHeightUm(); + + dispif_info->vsyncFPS = pgc->lcm_fps; + dispif_info->isConnected = 1; + + fps_ctx_get_fps(&primary_fps_ctx, &dispif_info->updateFPS, &dispif_info->is_updateFPS_stable); + dispif_info->updateFPS *= 100; + + return 0; +} + +uint32_t DISP_GetActiveHeightUm(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->params->physical_height_um; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +uint32_t DISP_GetActiveWidthUm(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->params->physical_width_um; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +int primary_display_get_pages(void) +{ + return 3; +} + +int primary_display_is_video_mode(void) +{ + /* TODO: we should store the video/cmd mode in runtime, because ROME will support cmd/vdo dynamic switch */ + return disp_lcm_is_video_mode(pgc->plcm); +} + +int primary_display_diagnose(void) +{ + int ret = 0; + + DISPMSG("==== %s ===>\n", __func__); + dpmgr_check_status(pgc->dpmgr_handle); + + if (primary_display_is_decouple_mode()) { + if (pgc->ovl2mem_path_handle) + dpmgr_check_status(pgc->ovl2mem_path_handle); + } + DISPMSG("==== %s ===<\n", __func__); + return ret; +} + +CMDQ_SWITCH primary_display_cmdq_enabled(void) +{ + return disp_helper_get_option(DISP_OPT_USE_CMDQ); +} + +int primary_display_manual_lock(void) +{ + _primary_path_lock(__func__); + return 0; +} + +int primary_display_manual_unlock(void) +{ + _primary_path_unlock(__func__); + return 0; +} + +void primary_display_reset(void) +{ + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); +} + +unsigned int primary_display_get_fps_nolock(void) +{ + return pgc->lcm_fps; +} +unsigned int primary_display_get_fps(void) +{ + unsigned int fps = 0; + + _primary_path_lock(__func__); + fps = pgc->lcm_fps; + _primary_path_unlock(__func__); + + return fps; +} + +int primary_display_force_set_fps(unsigned int keep, unsigned int skip) +{ + int ret = 0; + + DISPMSG("force set fps to keep %d, skip %d\n", keep, skip); + _primary_path_lock(__func__); + + pgc->force_fps_keep_count = keep; + pgc->force_fps_skip_count = skip; + + g_keep = 0; + g_skip = 0; + _primary_path_unlock(__func__); + + return ret; +} + +int primary_display_force_set_vsync_fps(unsigned int fps) +{ + int ret = 0; + + DISPMSG("force set fps to %d\n", fps); + _primary_path_lock(__func__); + + if (fps == pgc->lcm_fps) { + pgc->vsync_drop = 0; + ret = 0; + } else if (fps == 30) { + pgc->vsync_drop = 1; + ret = 0; + } else { + ret = -1; + } + + _primary_path_unlock(__func__); + + return ret; +} + +int primary_display_vsync_switch(int method) +{ + int ret = 0; + + if (method == 0) { + pr_debug("Vsync map RDMA %d\n", method); + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_RDMA0_DONE); + } else if (method == 1) { + pr_debug("Vsync map DSI TE %d\n", method); + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_DSI0_EXT_TE); + } else if (method == 2) { + pr_debug("Vsync map DSI FRAME DONE %d\n", method); + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_DSI0_FRAME_DONE); + } + + return ret; +} + +int _set_backlight_by_cmdq(unsigned int level) +{ + int ret = 0; + + cmdqRecHandle cmdq_handle_backlight = NULL; + + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 1); + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle_backlight); + DISPDBG("primary backlight, handle=%p\n", cmdq_handle_backlight); + if (ret != 0) { + DISPERR("fail to create primary cmdq handle for backlight\n"); + return -1; + } + + if (primary_display_is_video_mode()) { + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 2); + cmdqRecReset(cmdq_handle_backlight); + disp_lcm_set_backlight(pgc->plcm, cmdq_handle_backlight, level); + _cmdq_flush_config_handle_mira(cmdq_handle_backlight, 1); + DISPMSG("[BL]_set_backlight_by_cmdq ret=%d\n", ret); + } else { + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 3); + cmdqRecReset(cmdq_handle_backlight); + cmdqRecWait(cmdq_handle_backlight, CMDQ_SYNC_TOKEN_CABC_EOF); + _cmdq_handle_clear_dirty(cmdq_handle_backlight); + _cmdq_insert_wait_frame_done_token_mira(cmdq_handle_backlight); + disp_lcm_set_backlight(pgc->plcm, cmdq_handle_backlight, level); + cmdqRecSetEventToken(cmdq_handle_backlight, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + cmdqRecSetEventToken(cmdq_handle_backlight, CMDQ_SYNC_TOKEN_CABC_EOF); + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 4); + _cmdq_flush_config_handle_mira(cmdq_handle_backlight, 1); + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 6); + DISPMSG("[BL]_set_backlight_by_cmdq ret=%d\n", ret); + } + cmdqRecDestroy(cmdq_handle_backlight); + cmdq_handle_backlight = NULL; + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 5); + + return ret; +} + +int _set_backlight_by_cpu(unsigned int level) +{ + int ret = 0; + + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) { + DISPMSG("%s skip due to stage %s\n", __func__, disp_helper_stage_spy()); + return 0; + } + + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 0, 1); + if (primary_display_is_video_mode()) { + disp_lcm_set_backlight(pgc->plcm, NULL, level); + } else { + DISPMSG("[BL]display cmdq trigger loop stop[begin]\n"); + if (primary_display_cmdq_enabled()) + _cmdq_stop_trigger_loop(); + + DISPMSG("[BL]display cmdq trigger loop stop[end]\n"); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + DISPMSG("[BL]primary display path is busy\n"); + ret = + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, + HZ * 1); + DISPMSG("[BL]wait frame done ret:%d\n", ret); + } + + DISPMSG("[BL]stop dpmgr path[begin]\n"); + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + DISPMSG("[BL]stop dpmgr path[end]\n"); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + DISPMSG("[BL]primary display path is busy after stop\n"); + dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, + HZ * 1); + DISPMSG("[BL]wait frame done ret:%d\n", ret); + } + DISPMSG("[BL]reset display path[begin]\n"); + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + DISPMSG("[BL]reset display path[end]\n"); + + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 0, 2); + + disp_lcm_set_backlight(pgc->plcm, NULL, level); + + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 0, 3); + + DISPMSG("[BL]start dpmgr path[begin]\n"); + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + DISPMSG("[BL]start dpmgr path[end]\n"); + + if (primary_display_cmdq_enabled()) { + DISPMSG("[BL]start cmdq trigger loop[begin]\n"); + _cmdq_start_trigger_loop(); + } + DISPMSG("[BL]start cmdq trigger loop[end]\n"); + } + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 0, 7); + return ret; +} + +int primary_display_setbacklight(unsigned int level) +{ + int ret = 0; + static unsigned int last_level; + int need_lock = 0; + + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) { + DISPMSG("%s skip due to stage %s\n", __func__, disp_helper_stage_spy()); + return 0; + } + + if (last_level == level) + return 0; + + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagStart, 0, 0); + +#ifndef CONFIG_MTK_AAL_SUPPORT + /* backlight setting from led driver : need lock */ + need_lock = 1; +#else + /* In AAL feature on case + if backlight value not equal to zero, setting if from AAL : need not lock because + already locked at user command function (primary_display_user_cmd) + if backlight value equal to zero, setting if from led driver : need lock because + not lock applied before + */ + need_lock = aal_is_need_lock(); +#endif + if (need_lock) { + _primary_path_switch_dst_lock(); + _primary_path_lock(__func__); + } + if (pgc->state == DISP_SLEPT) { + DISPERR("Sleep State set backlight invald\n"); + } else { + primary_display_idlemgr_kick((char *)__func__, 0); + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) { + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, + MMProfileFlagPulse, 0, 7); + disp_lcm_set_backlight(pgc->plcm, NULL, level); + } else { + _set_backlight_by_cmdq(level); + } + atomic_set(&delayed_trigger_kick, 1); + } else { + _set_backlight_by_cpu(level); + } + last_level = level; + } + if (need_lock) { + _primary_path_unlock(__func__); + _primary_path_switch_dst_unlock(); + } + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagEnd, 0, 0); + return ret; +} + +int _set_lcm_cmd_by_cmdq(unsigned int *lcm_cmd, unsigned int *lcm_count, unsigned int *lcm_value) +{ + int ret = 0; + cmdqRecHandle cmdq_handle_lcm_cmd = NULL; + + MMProfileLogEx(ddp_mmp_get_events()->primary_set_cmd, MMProfileFlagPulse, 1, 1); + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle_lcm_cmd); + DISPDBG("primary set lcm cmd, handle=%p\n", cmdq_handle_lcm_cmd); + if (ret != 0) { + DISPERR("fail to create primary cmdq handle for setlcmcmd\n"); + return -1; + } + + if (primary_display_is_video_mode()) { + MMProfileLogEx(ddp_mmp_get_events()->primary_set_cmd, MMProfileFlagPulse, 1, 2); + cmdqRecReset(cmdq_handle_lcm_cmd); + disp_lcm_set_lcm_cmd(pgc->plcm, cmdq_handle_lcm_cmd, lcm_cmd, lcm_count, lcm_value); + _cmdq_flush_config_handle_mira(cmdq_handle_lcm_cmd, 1); + DISPMSG("[CMD]_set_lcm_cmd_by_cmdq ret=%d\n", ret); + } else { + MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 3); + cmdqRecReset(cmdq_handle_lcm_cmd); + _cmdq_handle_clear_dirty(cmdq_handle_lcm_cmd); + _cmdq_insert_wait_frame_done_token_mira(cmdq_handle_lcm_cmd); + + disp_lcm_set_lcm_cmd(pgc->plcm, cmdq_handle_lcm_cmd, lcm_cmd, lcm_count, lcm_value); + cmdqRecSetEventToken(cmdq_handle_lcm_cmd, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + MMProfileLogEx(ddp_mmp_get_events()->primary_set_cmd, MMProfileFlagPulse, 1, 4); + _cmdq_flush_config_handle_mira(cmdq_handle_lcm_cmd, 1); + MMProfileLogEx(ddp_mmp_get_events()->primary_set_cmd, MMProfileFlagPulse, 1, 6); + DISPMSG("[CMD]_set_lcm_cmd_by_cmdq ret=%d\n", ret); + } + cmdqRecDestroy(cmdq_handle_lcm_cmd); + cmdq_handle_lcm_cmd = NULL; + MMProfileLogEx(ddp_mmp_get_events()->primary_set_cmd, MMProfileFlagPulse, 1, 5); + return ret; + +} + +int primary_display_setlcm_cmd(unsigned int *lcm_cmd, unsigned int *lcm_count, + unsigned int *lcm_value) +{ + int ret = 0; + + DISPFUNC(); + if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL) { + DISPMSG("%s skip due to stage %s\n", __func__, disp_helper_stage_spy()); + return 0; + } + + MMProfileLogEx(ddp_mmp_get_events()->primary_set_cmd, MMProfileFlagStart, 0, 0); + + _primary_path_switch_dst_lock(); + + _primary_path_lock(__func__); + if (pgc->state == DISP_SLEPT) { + DISPMSG("Sleep State set backlight invald\n"); + } else { + if (primary_display_cmdq_enabled()) { + if (primary_display_is_video_mode()) { + MMProfileLogEx(ddp_mmp_get_events()->primary_set_cmd, + MMProfileFlagPulse, 0, 7); + _set_lcm_cmd_by_cmdq(lcm_cmd, lcm_count, lcm_value); + } else { + _set_lcm_cmd_by_cmdq(lcm_cmd, lcm_count, lcm_value); + } + } else { + /* cpu */ + } + } + _primary_path_unlock(__func__); + + _primary_path_switch_dst_lock(); + + MMProfileLogEx(ddp_mmp_get_events()->primary_set_cmd, MMProfileFlagEnd, 0, 0); + + return ret; +} + +int primary_display_mipi_clk_change(unsigned int clk_value) +{ + cmdqRecHandle cmdq_handle = NULL; + + if (pgc->state == DISP_SLEPT) { + DISPMSG("Sleep State clk change invald\n"); + return 0; + } + + _primary_path_lock(__func__); + + if (!primary_display_is_video_mode()) { + DISPMSG("clk change CMD Mode return\n"); + return 0; + } + + cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle); + cmdqRecReset(cmdq_handle); + + _cmdq_insert_wait_frame_done_token_mira(cmdq_handle); + pgc->plcm->params->dsi.PLL_CLOCK = clk_value; + + dpmgr_path_build_cmdq(pgc->dpmgr_handle, + cmdq_handle, CMDQ_STOP_VDO_MODE, 0); + + dpmgr_path_ioctl(primary_get_dpmgr_handle(), cmdq_handle, + DDP_PHY_CLK_CHANGE, + &clk_value); + + dpmgr_path_build_cmdq(pgc->dpmgr_handle, + cmdq_handle, CMDQ_START_VDO_MODE, 0); + + cmdqRecClearEventToken(cmdq_handle, CMDQ_EVENT_MUTEX0_STREAM_EOF); + cmdqRecClearEventToken(cmdq_handle, CMDQ_EVENT_DISP_RDMA0_EOF); + + dpmgr_path_trigger(pgc->dpmgr_handle, cmdq_handle, CMDQ_ENABLE); + ddp_mutex_set_sof_wait(dpmgr_path_get_mutex(pgc->dpmgr_handle), pgc->cmdq_handle_config_esd, 0); + _cmdq_flush_config_handle_mira(cmdq_handle, 1); + + cmdqRecDestroy(cmdq_handle); + cmdq_handle = NULL; + + DISPMSG("primary_display_mipi_clk_change return\n"); + + _primary_path_unlock(__func__); + + return 0; +} + +/***********************/ +/*****Legacy DISP API*****/ +/***********************/ +uint32_t DISP_GetScreenWidth(void) +{ + return primary_display_get_width(); +} + +uint32_t DISP_GetScreenHeight(void) +{ + return primary_display_get_height(); +} + +uint32_t DISP_GetActiveHeight(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->params->physical_height; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +uint32_t DISP_GetActiveWidth(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return 0; + } + + if (pgc->plcm->params) + return pgc->plcm->params->physical_width; + + DISPERR("lcm_params is null!\n"); + return 0; +} + +LCM_PARAMS *DISP_GetLcmPara(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return NULL; + } + + if (pgc->plcm->params) + return pgc->plcm->params; + else + return NULL; +} + +LCM_DRIVER *DISP_GetLcmDrv(void) +{ + if (pgc->plcm == NULL) { + DISPERR("lcm handle is null\n"); + return NULL; + } + + if (pgc->plcm->drv) + return pgc->plcm->drv; + else + return NULL; +} + +static int _screen_cap_by_cmdq(unsigned int mva, enum UNIFIED_COLOR_FMT ufmt, DISP_MODULE_ENUM after_eng) +{ + int ret = 0; + cmdqRecHandle cmdq_handle = NULL; + cmdqRecHandle cmdq_wait_handle = NULL; + disp_ddp_path_config *pconfig = NULL; + unsigned int w_xres = primary_display_get_width(); + unsigned int h_yres = primary_display_get_height(); + + /*create config thread */ + ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle); + if (ret != 0) { + DISPMSG("primary capture:Fail to create primary cmdq handle for capture\n"); + ret = -1; + goto out; + } + cmdqRecReset(cmdq_handle); + + /*create wait thread */ + ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_SCREEN_CAPTURE, &cmdq_wait_handle); + if (ret != 0) { + DISPMSG + ("primary capture:Fail to create primary cmdq wait handle for capture\n"); + ret = -1; + goto out; + } + cmdqRecReset(cmdq_wait_handle); + + dpmgr_path_memout_clock(pgc->dpmgr_handle, 1); + + _cmdq_handle_clear_dirty(cmdq_handle); + _cmdq_insert_wait_frame_done_token_mira(cmdq_handle); + + _primary_path_lock(__func__); + + primary_display_idlemgr_kick(__func__, 0); + dpmgr_path_add_memout(pgc->dpmgr_handle, after_eng, cmdq_handle); + + pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle); + pconfig->wdma_dirty = 1; + pconfig->wdma_config.dstAddress = mva; + pconfig->wdma_config.srcHeight = h_yres; + pconfig->wdma_config.srcWidth = w_xres; + pconfig->wdma_config.clipX = 0; + pconfig->wdma_config.clipY = 0; + pconfig->wdma_config.clipHeight = h_yres; + pconfig->wdma_config.clipWidth = w_xres; + pconfig->wdma_config.outputFormat = ufmt; + pconfig->wdma_config.useSpecifiedAlpha = 1; + pconfig->wdma_config.alpha = 0xFF; + pconfig->wdma_config.dstPitch = w_xres * UFMT_GET_bpp(ufmt) / 8; + ret = dpmgr_path_config(pgc->dpmgr_handle, pconfig, cmdq_handle); + pconfig->wdma_dirty = 0; + + _cmdq_set_config_handle_dirty_mira(cmdq_handle); + _cmdq_flush_config_handle_mira(cmdq_handle, 0); + DISPMSG("primary capture:Flush add memout mva(0x%x)\n", mva); + /*wait wdma0 sof */ + cmdqRecWait(cmdq_wait_handle, CMDQ_EVENT_DISP_WDMA0_SOF); + cmdqRecFlush(cmdq_wait_handle); + DISPMSG("primary capture:Flush wait wdma sof\n"); + cmdqRecReset(cmdq_handle); + _cmdq_handle_clear_dirty(cmdq_handle); + _cmdq_insert_wait_frame_done_token_mira(cmdq_handle); + + dpmgr_path_remove_memout(pgc->dpmgr_handle, cmdq_handle); + + cmdqRecClearEventToken(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_SOF); + _cmdq_set_config_handle_dirty_mira(cmdq_handle); + /* flush remove memory to cmdq */ + _cmdq_flush_config_handle_mira(cmdq_handle, 1); + DISPMSG("primary capture: Flush remove memout\n"); + + dpmgr_path_memout_clock(pgc->dpmgr_handle, 0); + _primary_path_unlock(__func__); + +out: + cmdqRecDestroy(cmdq_handle); + cmdqRecDestroy(cmdq_wait_handle); + return 0; +} + +static int _screen_cap_by_cpu(unsigned int mva, enum UNIFIED_COLOR_FMT ufmt, DISP_MODULE_ENUM after_eng) +{ + int ret = 0; + disp_ddp_path_config *pconfig = NULL; + unsigned int w_xres = primary_display_get_width(); + unsigned int h_yres = primary_display_get_height(); + + dpmgr_path_memout_clock(pgc->dpmgr_handle, 1); + + if (_should_wait_path_idle()) { + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + if (ret <= 0) + primary_display_diagnose(); + } + + _primary_path_lock(__func__); + primary_display_idlemgr_kick(__func__, 1); + + dpmgr_path_add_memout(pgc->dpmgr_handle, after_eng, NULL); + + pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle); + pconfig->wdma_dirty = 1; + pconfig->wdma_config.dstAddress = mva; + pconfig->wdma_config.srcHeight = h_yres; + pconfig->wdma_config.srcWidth = w_xres; + pconfig->wdma_config.clipX = 0; + pconfig->wdma_config.clipY = 0; + pconfig->wdma_config.clipHeight = h_yres; + pconfig->wdma_config.clipWidth = w_xres; + pconfig->wdma_config.outputFormat = ufmt; + pconfig->wdma_config.useSpecifiedAlpha = 1; + pconfig->wdma_config.alpha = 0xFF; + pconfig->wdma_config.dstPitch = w_xres * UFMT_GET_bpp(ufmt) / 8; + ret = dpmgr_path_config(pgc->dpmgr_handle, pconfig, NULL); + pconfig->wdma_dirty = 0; + + _trigger_display_interface(1, NULL, 0); + msleep(20); + if (_should_wait_path_idle()) { + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + if (ret <= 0) + primary_display_diagnose(); + } + + dpmgr_path_remove_memout(pgc->dpmgr_handle, NULL); + + dpmgr_path_memout_clock(pgc->dpmgr_handle, 0); + _primary_path_unlock(__func__); + return 0; +} + +int primary_display_capture_framebuffer_ovl(unsigned long pbuf, enum UNIFIED_COLOR_FMT ufmt) +{ + + int ret = 0; + m4u_client_t *m4uClient = NULL; + unsigned int mva = 0; + unsigned int w_xres = primary_display_get_width(); + unsigned int h_yres = primary_display_get_height(); + unsigned int pixel_byte = primary_display_get_bpp() / 8; + int tmp; + int buffer_size = h_yres * w_xres * pixel_byte; + DISP_MODULE_ENUM after_eng = DISP_MODULE_OVL0; + + DISPMSG("primary capture: begin\n"); + disp_sw_mutex_lock(&(pgc->capture_lock)); + + if (primary_display_is_sleepd()) { + memset((void *)pbuf, 0, buffer_size); + DISPMSG("primary capture: Fail black End\n"); + goto out; + } + + m4uClient = m4u_create_client(); + if (m4uClient == NULL) { + DISPERR("primary capture:Fail to alloc m4uClient\n"); + ret = -1; + goto out; + } + + ret = m4u_alloc_mva(m4uClient, M4U_PORT_DISP_WDMA0, pbuf, NULL, buffer_size, + M4U_PROT_READ | M4U_PROT_WRITE, 0, &mva); + if (ret != 0) { + DISPERR("primary capture:Fail to allocate mva\n"); + ret = -1; + goto out; + } + + ret = m4u_cache_sync(m4uClient, M4U_PORT_DISP_WDMA0, pbuf, buffer_size, mva, + M4U_CACHE_FLUSH_ALL); + if (ret != 0) { + DISPERR("primary capture:Fail to cach sync\n"); + ret = -1; + goto out; + } + tmp = disp_helper_get_option(DISP_OPT_SCREEN_CAP_FROM_DITHER); + if (tmp == 0) + after_eng = DISP_MODULE_OVL0; + else if (tmp == 1) + after_eng = DISP_MODULE_DITHER; + else if (tmp == 2) + after_eng = DISP_MODULE_UFOE; + + if (primary_display_cmdq_enabled()) + _screen_cap_by_cmdq(mva, ufmt, after_eng); + else + _screen_cap_by_cpu(mva, ufmt, after_eng); + + ret = m4u_cache_sync(m4uClient, M4U_PORT_DISP_WDMA0, pbuf, buffer_size, mva, + M4U_CACHE_INVALID_BY_RANGE); +out: + if (mva > 0) + m4u_dealloc_mva(m4uClient, M4U_PORT_DISP_WDMA0, mva); + + if (m4uClient != 0) + m4u_destroy_client(m4uClient); + + disp_sw_mutex_unlock(&(pgc->capture_lock)); + DISPMSG("primary capture: end\n"); + return ret; +} + +int primary_display_capture_framebuffer(unsigned long pbuf) +{ + unsigned int fb_layer_id = primary_display_get_option("FB_LAYER"); + unsigned int w_xres = primary_display_get_width(); + unsigned int h_yres = primary_display_get_height(); + unsigned int pixel_bpp = primary_display_get_bpp() / 8; /* bpp is either 32 or 16, can not be other value */ + unsigned int w_fb = ALIGN_TO(w_xres, MTK_FB_ALIGNMENT); + unsigned int fbsize = w_fb * h_yres * pixel_bpp; /* frame buffer size */ + unsigned long fbaddress = + dpmgr_path_get_last_config(pgc->dpmgr_handle)->ovl_config[fb_layer_id].addr; + unsigned int i; + unsigned long ttt; + void *fbv = 0; + + DISPMSG("w_res=%d, h_yres=%d, pixel_bpp=%d, w_fb=%d, fbsize=%d, fbaddress=0x%lx\n", w_xres, + h_yres, pixel_bpp, w_fb, fbsize, fbaddress); + fbv = ioremap(fbaddress, fbsize); + DISPMSG + ("w_xres = %d, h_yres = %d, w_fb = %d, pixel_bpp = %d, fbsize = %d, fbaddress = 0x%08lx\n", + w_xres, h_yres, w_fb, pixel_bpp, fbsize, fbaddress); + if (!fbv) { + DISPMSG + ("[FB Driver], Unable to allocate memory for frame buffer: address=0x%lx, size=0x%08x\n", + fbaddress, fbsize); + return -1; + } + + ttt = get_current_time_us(); + for (i = 0; i < h_yres; i++) { + memcpy((void *)(pbuf + i * w_xres * pixel_bpp), + (void *)(fbv + i * w_fb * pixel_bpp), w_xres * pixel_bpp); + } + DISPMSG("capture framebuffer cost %ld us\n", get_current_time_us() - ttt); + iounmap((void *)fbv); + return -1; +} + +static uint32_t disp_fb_bpp = 32; +static uint32_t disp_fb_pages = 3; + +uint32_t DISP_GetScreenBpp(void) +{ + return disp_fb_bpp; +} + +uint32_t DISP_GetPages(void) +{ + return disp_fb_pages; +} + +uint32_t DISP_GetFBRamSize(void) +{ + return ALIGN_TO(DISP_GetScreenWidth(), MTK_FB_ALIGNMENT) * + DISP_GetScreenHeight() * ((DISP_GetScreenBpp() + 7) >> 3) * DISP_GetPages(); +} + +uint32_t DISP_GetVRamSize(void) +{ +#if 0 + /* Use a local static variable to cache the calculated vram size */ + /* */ + static uint32_t vramSize; + + if (0 == vramSize) { + disp_drv_init_context(); + + /* /get framebuffer size */ + vramSize = DISP_GetFBRamSize(); + + /* /get DXI working buffer size */ + vramSize += disp_if_drv->get_working_buffer_size(); + + /* get assertion layer buffer size */ + vramSize += DAL_GetLayerSize(); + + /* Align vramSize to 1MB */ + /* */ + vramSize = ALIGN_TO_POW_OF_2(vramSize, 0x100000); + + DISP_LOG("DISP_GetVRamSize: %u bytes\n", vramSize); + } + + return vramSize; +#endif + return 0; +} + +uint32_t DISP_GetVRamSizeBoot(char *cmdline) +{ + unsigned int vramsize; + + vramsize = mtkfb_get_fb_size(); + BUG_ON(!vramsize); + DISPMSG("[DT]display vram size = 0x%08x|%d\n", vramsize, vramsize); + return vramsize; +} + +int disp_hal_allocate_framebuffer(phys_addr_t pa_start, phys_addr_t pa_end, unsigned long *va, + unsigned long *mva) +{ + int ret = 0; + + *va = (unsigned long)ioremap_nocache(pa_start, pa_end - pa_start + 1); + pr_debug("disphal_allocate_fb, pa_start=0x%pa, pa_end=0x%pa, va=0x%lx\n", &pa_start, + &pa_end, *va); + + if (disp_helper_get_option(DISP_OPT_USE_M4U)) { + m4u_client_t *client; + struct sg_table *sg_table = &table; + + sg_alloc_table(sg_table, 1, GFP_KERNEL); + + sg_dma_address(sg_table->sgl) = pa_start; + sg_dma_len(sg_table->sgl) = (pa_end - pa_start + 1); + client = m4u_create_client(); + if (IS_ERR_OR_NULL(client)) + DISPERR("create client fail!\n"); + + + *mva = pa_start & 0xffffffffULL; + ret = + m4u_alloc_mva(client, M4U_PORT_DISP_OVL0, 0, sg_table, (pa_end - pa_start + 1), + M4U_PROT_READ | M4U_PROT_WRITE, M4U_FLAGS_FIX_MVA, (unsigned int *)mva); + /* m4u_alloc_mva(M4U_PORT_DISP_OVL0, pa_start, (pa_end - pa_start + 1), 0, 0, mva); */ + if (ret) + DISPERR("m4u_alloc_mva returns fail: %d\n", ret); + + pr_debug("[DISPHAL] FB MVA is 0x%lx PA is 0x%pa\n", *mva, &pa_start); + + } else { + *mva = pa_start & 0xffffffffULL; + } + + return 0; +} + + +unsigned int primary_display_get_option(const char *option) +{ + if (!strcmp(option, "FB_LAYER")) + return 0; + if (!strcmp(option, "ASSERT_LAYER")) + return PRIMARY_SESSION_INPUT_LAYER_COUNT - 1; + if (!strcmp(option, "M4U_ENABLE")) + return disp_helper_get_option(DISP_OPT_USE_M4U); + BUG_ON(1); + return 0; /* avoid build warning */ +} + +int primary_display_lcm_ATA(void) +{ + DISP_STATUS ret = DISP_STATUS_OK; + + DISPFUNC(); + primary_display_esd_check_enable(0); + _primary_path_lock(__func__); + disp_irq_esd_cust_bycmdq(0); + if (pgc->state == 0) { + DISPMSG("ATA_LCM, primary display path is already sleep, skip\n"); + goto done; + } + + DISPMSG("[ATA_LCM]primary display path stop[begin]\n"); + if (primary_display_is_video_mode()) + dpmgr_path_ioctl(pgc->dpmgr_handle, NULL, DDP_STOP_VIDEO_MODE, NULL); + + DISPMSG("[ATA_LCM]primary display path stop[end]\n"); + ret = disp_lcm_ATA(pgc->plcm); + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + if (primary_display_is_video_mode()) { + /* for video mode, we need to force trigger here */ + /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */ + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE); + } +done: + disp_irq_esd_cust_bycmdq(1); + _primary_path_unlock(__func__); + primary_display_esd_check_enable(1); + return ret; +} + +static int Panel_Master_primary_display_config_dsi(const char *name, uint32_t config_value) +{ + int ret = 0; + disp_ddp_path_config *data_config; + + /* all dirty should be cleared in dpmgr_path_get_last_config() */ + data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle); + /* modify below for config dsi */ + if (!strcmp(name, "PM_CLK")) { + pr_debug("Pmaster_config_dsi: PM_CLK:%d\n", config_value); + data_config->dispif_config.dsi.PLL_CLOCK = config_value; + } else if (!strcmp(name, "PM_SSC")) { + data_config->dispif_config.dsi.ssc_range = config_value; + } + pr_debug("Pmaster_config_dsi: will Run path_config()\n"); + ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, NULL); + + return ret; +} + +int fbconfig_get_esd_check_test(uint32_t dsi_id, uint32_t cmd, uint8_t *buffer, uint32_t num) +{ + int ret = 0; + + _primary_path_lock(__func__); + if (pgc->state == DISP_SLEPT) { + DISPMSG("[ESD]primary display path is slept?? -- skip esd check\n"); + _primary_path_unlock(__func__); + goto done; + } + primary_display_esd_check_enable(0); + disp_irq_esd_cust_bycmdq(0); + /* / 1: stop path */ + _cmdq_stop_trigger_loop(); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + DISPMSG("[ESD]wait frame done ret:%d\n", ret); + + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + DISPMSG("[ESD]stop dpmgr path[end]\n"); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + DISPMSG("[ESD]wait frame done ret:%d\n", ret); + + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + ret = fbconfig_get_esd_check(dsi_id, cmd, buffer, num); + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + DISPMSG("[ESD]start dpmgr path[end]\n"); + if (primary_display_is_video_mode()) { + /* for video mode, we need to force trigger here */ + /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */ + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE); + } + _cmdq_start_trigger_loop(); + /* when we stop trigger loop + * if no other thread is running, cmdq may disable its clock + * all cmdq event will be cleared after suspend */ + cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_EOF); + DISPMSG("[ESD]start cmdq trigger loop[end]\n"); + disp_irq_esd_cust_bycmdq(1); + primary_display_esd_check_enable(1); + _primary_path_unlock(__func__); + +done: + return ret; +} + +int Panel_Master_dsi_config_entry(const char *name, void *config_value) +{ + int ret = 0; + int force_trigger_path = 0; + uint32_t *config_dsi = (uint32_t *) config_value; + LCM_PARAMS *lcm_param = NULL; + LCM_DRIVER *pLcm_drv = DISP_GetLcmDrv(); + + DISPFUNC(); + if (!strcmp(name, "DRIVER_IC_RESET") || !strcmp(name, "PM_DDIC_CONFIG")) { + primary_display_esd_check_enable(0); + msleep(2500); + } + _primary_path_lock(__func__); + + lcm_param = disp_lcm_get_params(pgc->plcm); + if (pgc->state == DISP_SLEPT) { + DISPERR("[Pmaster]Panel_Master: primary display path is slept??\n"); + goto done; + } + /* / Esd Check : Read from lcm */ + /* / the following code is to */ + /* / 0: lock path */ + /* / 1: stop path */ + /* / 2: do esd check (!!!) */ + /* / 3: start path */ + /* / 4: unlock path */ + /* / 1: stop path */ + _cmdq_stop_trigger_loop(); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + int event_ret; + + DISPMSG("[ESD]wait frame done ret:%d\n", ret); + event_ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + if (event_ret <= 0) { + DISPERR("wait frame done in suspend timeout\n"); + primary_display_diagnose(); + ret = -1; + } + } + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + DISPMSG("[ESD]stop dpmgr path[end]\n"); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + DISPMSG("[ESD]wait frame done ret:%d\n", ret); + + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + if ((!strcmp(name, "PM_CLK")) || (!strcmp(name, "PM_SSC"))) + Panel_Master_primary_display_config_dsi(name, *config_dsi); + else if (!strcmp(name, "PM_DDIC_CONFIG")) { + Panel_Master_DDIC_config(); + force_trigger_path = 1; + } else if (!strcmp(name, "DRIVER_IC_RESET")) { + if (pLcm_drv && pLcm_drv->init_power) + pLcm_drv->init_power(); + if (pLcm_drv) + pLcm_drv->init(); + else + ret = -1; + force_trigger_path = 1; + } + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + if (primary_display_is_video_mode()) { + /* for video mode, we need to force trigger here */ + /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */ + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE); + force_trigger_path = 0; + } + _cmdq_start_trigger_loop(); + + /* when we stop trigger loop + * if no other thread is running, cmdq may disable its clock + * all cmdq event will be cleared after suspend */ + cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_EOF); + + DISPMSG("[Pmaster]start cmdq trigger loop\n"); +done: + _primary_path_unlock(__func__); + + if (force_trigger_path) { + primary_display_trigger(0, NULL, 0); + DISPMSG("[Pmaster]force trigger display path\r\n"); + } + + return ret; +} + +/* +mode: 0, switch to cmd mode; 1, switch to vdo mode +*/ +int primary_display_switch_dst_mode(int mode) +{ + DISP_STATUS ret = DISP_STATUS_ERROR; + void *lcm_cmd = NULL; + + pr_debug + ("[ERROR: primary_display_switch_dst_mode]this function not enable in disp driver\n"); + + DISPFUNC(); + _primary_path_switch_dst_lock(); + disp_sw_mutex_lock(&(pgc->capture_lock)); + if (pgc->plcm->params->type != LCM_TYPE_DSI) { + pr_debug("[primary_display_switch_dst_mode] Error, only support DSI IF\n"); + goto done; + } + if (pgc->state == DISP_SLEPT) { + DISPMSG + ("[primary_display_switch_dst_mode], primary display path is already sleep, skip\n"); + goto done; + } + + if (mode == primary_display_cur_dst_mode) { + DISPMSG + ("[primary_display_switch_dst_mode]not need switch,cur_mode:%d, switch_mode:%d\n", + primary_display_cur_dst_mode, mode); + goto done; + } + lcm_cmd = disp_lcm_switch_mode(pgc->plcm, mode); + if (lcm_cmd == NULL) { + DISPMSG + ("[primary_display_switch_dst_mode]get lcm cmd fail primary_display_cur_dst_mode=%d mode=%d\n", + primary_display_cur_dst_mode, mode); + goto done; + } else { + int temp_mode = 0; + + if (0 != dpmgr_path_ioctl(pgc->dpmgr_handle, pgc->cmdq_handle_config, + DDP_SWITCH_LCM_MODE, lcm_cmd)) { + pr_err("switch lcm mode fail, return directly\n"); + goto done; + } + _primary_path_lock(__func__); + temp_mode = (int)(pgc->plcm->params->dsi.mode); + pgc->plcm->params->dsi.mode = pgc->plcm->params->dsi.switch_mode; + pgc->plcm->params->dsi.switch_mode = temp_mode; + dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode()); + if (0 != dpmgr_path_ioctl(pgc->dpmgr_handle, pgc->cmdq_handle_config, + DDP_SWITCH_DSI_MODE, lcm_cmd)) { + pr_err("switch dsi mode fail, return directly\n"); + _primary_path_unlock(__func__); + goto done; + } + } + if (disp_helper_get_option(DISP_OPT_SODI_SUPPORT)) + primary_display_sodi_rule_init(); + _cmdq_stop_trigger_loop(); + _cmdq_build_trigger_loop(); + _cmdq_start_trigger_loop(); + _cmdq_reset_config_handle(); /* must do this */ + _cmdq_handle_clear_dirty(pgc->cmdq_handle_config); + _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_config); + + primary_display_cur_dst_mode = mode; + + if (primary_display_is_video_mode()) { + if (_need_lfr_check()) { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_DSI0_FRAME_DONE); + } else { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_RDMA0_DONE); + } + } else { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_DSI0_EXT_TE); + } + _primary_path_unlock(__func__); + ret = DISP_STATUS_OK; +done: +/* dprec_handle_option(0x0); */ + disp_sw_mutex_unlock(&(pgc->capture_lock)); + _primary_path_switch_dst_unlock(); + return ret; +} + + +/***************************************************************************** + * Below code is for Efuse test in Android Load. + * include TE, ROI and Resolution. + *****************************************************************************/ +/* extern void DSI_ForceConfig(int forceconfig); */ +/* extern int DSI_set_roi(int x,int y); */ +/* extern int DSI_check_roi(void); */ + +static int width_array[] = {2560, 1440, 1920, 1280, 1200, 800, 960, 640}; +static int heigh_array[] = {1440, 2560, 1200, 800, 1920, 1280, 640, 960}; +static int array_id[] = {6, 2, 7, 4, 3, 0, 5, 1}; +LCM_PARAMS *lcm_param2 = NULL; +disp_ddp_path_config data_config2; + +int primary_display_te_test(void) +{ + int ret = 0; + int try_cnt = 3; + int time_interval = 0; + int time_interval_max = 0; + long long time_te = 0; + long long time_framedone = 0; + + DISPMSG("display_test te begin\n"); + if (primary_display_is_video_mode()) { + DISPMSG("Video Mode No TE\n"); + return ret; + } + + while (try_cnt >= 0) { + try_cnt--; + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, HZ*1); + time_te = sched_clock(); + + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE); + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*1); + time_framedone = sched_clock(); + time_interval = (int) (time_framedone - time_te); + time_interval = time_interval / 1000; + if (time_interval > time_interval_max) + time_interval_max = time_interval; + } + if (time_interval_max > 20000) + ret = 0; + else + ret = -1; + + if (ret >= 0) + DISPMSG("[display_test_result]==>Force On TE Open!(%d)\n", time_interval_max); + else + DISPMSG("[display_test_result]==>Force On TE Closed!(%d)\n", time_interval_max); + + DISPMSG("display_test te end\n"); + return ret; +} + + +int primary_display_roi_test(int x, int y) +{ + int ret = 0; + + DISPMSG("display_test roi begin\n"); + DISPMSG("display_test roi set roi %d, %d\n", x, y); + DSI_set_roi(x, y); + msleep(50); + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE); + msleep(50); + DISPMSG("display_test DSI_check_roi\n"); + ret = DSI_check_roi(); + msleep(20); + if (ret == 0) + DISPMSG("[display_test_result]==>DSI_ROI limit!\n"); + else + DISPMSG("[display_test_result]==>DSI_ROI Normal!\n"); + + DISPMSG("display_test set roi %d, %d\n", 0, 0); + + DSI_set_roi(0, 0); + + msleep(20); + DISPMSG("display_test end\n"); + return ret; +} + +int primary_display_resolution_test(void) +{ + int ret = 0; + int i = 0; + unsigned int w_backup = 0; + unsigned int h_backup = 0; + int dst_width = 0; + int dst_heigh = 0; + LCM_DSI_MODE_CON dsi_mode_backup = primary_display_is_video_mode(); + + memset((void *)&data_config2, 0, sizeof(data_config2)); + lcm_param2 = NULL; + memcpy((void *)&data_config2, + (void *)dpmgr_path_get_last_config(pgc->dpmgr_handle), + sizeof(disp_ddp_path_config)); + w_backup = data_config2.dst_w; + h_backup = data_config2.dst_h; + DISPMSG("[display_test resolution]w_backup %d h_backup %d dsi_mode_backup %d\n", + w_backup, h_backup, dsi_mode_backup); + /* for dsi config */ + DSI_ForceConfig(1); + for (i = 0; i < sizeof(width_array)/sizeof(int); i++) { + dst_width = width_array[i]; + dst_heigh = heigh_array[i]; + DISPMSG("[display_test resolution] width %d, heigh %d\n", dst_width, dst_heigh); + lcm_param2 = disp_lcm_get_params(pgc->plcm); + lcm_param2->dsi.mode = CMD_MODE; + lcm_param2->dsi.horizontal_active_pixel = dst_width; + lcm_param2->dsi.vertical_active_line = dst_heigh; + + data_config2.dispif_config.dsi.mode = CMD_MODE; + data_config2.dispif_config.dsi.horizontal_active_pixel = dst_width; + data_config2.dispif_config.dsi.vertical_active_line = dst_heigh; + + + data_config2.dst_w = dst_width; + data_config2.dst_h = dst_heigh; + + data_config2.ovl_config[0].layer = 0; + data_config2.ovl_config[0].layer_en = 0; + data_config2.ovl_config[1].layer = 1; + data_config2.ovl_config[1].layer_en = 0; + data_config2.ovl_config[2].layer = 2; + data_config2.ovl_config[2].layer_en = 0; + data_config2.ovl_config[3].layer = 3; + data_config2.ovl_config[3].layer_en = 0; + + data_config2.dst_dirty = 1; + data_config2.ovl_dirty = 1; + + dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode()); + + dpmgr_path_config(pgc->dpmgr_handle, &data_config2, CMDQ_DISABLE); + data_config2.dst_dirty = 0; + data_config2.ovl_dirty = 0; + + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + DISPERR("[display_test]==>Fatal error, we didn't trigger display path but it's already busy\n"); + + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE); + + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*1); + if (ret > 0) { + if (!dpmgr_path_is_busy(pgc->dpmgr_handle)) { + if (i == 0) + DISPMSG("[display_test resolution] display_result 0x%x unlimited!\n", + array_id[i]); + else if (i == 1) + DISPMSG("[display_test resolution] display_result 0x%x unlimited (Wdpmgr_handle, CMDQ_DISABLE); + } + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + lcm_param2 = disp_lcm_get_params(pgc->plcm); + lcm_param2->dsi.mode = dsi_mode_backup; + lcm_param2->dsi.vertical_active_line = h_backup; + lcm_param2->dsi.horizontal_active_pixel = w_backup; + data_config2.dispif_config.dsi.vertical_active_line = h_backup; + data_config2.dispif_config.dsi.horizontal_active_pixel = w_backup; + data_config2.dispif_config.dsi.mode = dsi_mode_backup; + data_config2.dst_w = w_backup; + data_config2.dst_h = h_backup; + data_config2.dst_dirty = 1; + dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode()); + dpmgr_path_connect(pgc->dpmgr_handle, CMDQ_DISABLE); + dpmgr_path_config(pgc->dpmgr_handle, &data_config2, CMDQ_DISABLE); + data_config2.dst_dirty = 0; + DSI_ForceConfig(0); + return ret; +} + +int primary_display_check_test(void) +{ + int ret = 0; + int esd_backup = 0; + + DISPMSG("[display_test]Display test[Start]\n"); + _primary_path_lock(__func__); + /* disable esd check */ + if (1) { + esd_backup = 1; + primary_display_esd_check_enable(0); + msleep(2000); + DISPMSG("[display_test]Disable esd check end\n"); + } + + /* if suspend => return */ + if (pgc->state == DISP_SLEPT) { + DISPMSG("[display_test_result]======================================\n"); + DISPMSG("[display_test_result]==>Test Fail : primary display path is slept\n"); + DISPMSG("[display_test_result]======================================\n"); + goto done; + } + + /* stop trigger loop */ + DISPMSG("[display_test]Stop trigger loop[begin]\n"); + _cmdq_stop_trigger_loop(); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + DISPMSG("[display_test]==>primary display path is busy\n"); + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*1); + if (ret <= 0) + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + + DISPMSG("[display_test]==>wait frame done ret:%d\n", ret); + } + DISPMSG("[display_test]Stop trigger loop[end]\n"); + + /* test force te */ + /* primary_display_te_test(); */ + + /* test roi */ + /* primary_display_roi_test(30, 30); */ + + /* test resolution test */ + primary_display_resolution_test(); + + DISPMSG("[display_test]start dpmgr path[begin]\n"); + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) + DISPERR("[display_test]==>Fatal error, we didn't trigger display path but it's already busy\n"); + + DISPMSG("[display_test]start dpmgr path[end]\n"); + + DISPMSG("[display_test]Start trigger loop[begin]\n"); + _cmdq_start_trigger_loop(); + DISPMSG("[display_test]Start trigger loop[end]\n"); + +done: + /* restore esd */ + if (esd_backup == 1) { + primary_display_esd_check_enable(1); + DISPMSG("[display_test]Restore esd check\n"); + } + /* unlock path */ + _primary_path_unlock(__func__); + DISPMSG("[display_test]Display test[End]\n"); + return ret; +} + +OPT_BACKUP tui_opt_backup[3] = { + {DISP_OPT_IDLEMGR_SWTCH_DECOUPLE, 0}, + {DISP_OPT_SMART_OVL, 0}, + {DISP_OPT_BYPASS_OVL, 0} +}; +void stop_smart_ovl_nolock(void) +{ + int i; + + for (i = 0; i < (sizeof(tui_opt_backup) / sizeof((tui_opt_backup)[0])); i++) { + tui_opt_backup[i].value = disp_helper_get_option(tui_opt_backup[i].option); + disp_helper_set_option(tui_opt_backup[i].option, 0); + } + /*primary_display_esd_check_enable(0);*/ +} +void restart_smart_ovl_nolock(void) +{ + int i; + + for (i = 0; i < 3; i++) + disp_helper_set_option(tui_opt_backup[i].option, tui_opt_backup[i].value); + +} + +/*Now the normal display vsync is DDP_IRQ_RDMA0_DONE in vdo mode, but when enter TUI, + *we must protect the rdma0, then, should + * switch it to the DDP_IRQ_DSI0_FRAME_DONE. + */ +int display_vsync_switch_to_dsi(unsigned int flg) +{ + if (!primary_display_is_video_mode()) + return 0; + + if (!flg) { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_RDMA0_DONE); + dsi_enable_irq(DISP_MODULE_DSI0, NULL, 0); + + } else { + dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, + DDP_IRQ_DSI0_FRAME_DONE); + dsi_enable_irq(DISP_MODULE_DSI0, NULL, 1); + } + + return 0; +} + +int display_enter_tui(void) +{ + + msleep(500); + DISPMSG("TDDP: %s\n", __func__); + + MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagStart, 0, 0); + + _primary_path_lock(__func__); + + if (primary_get_state() != DISP_ALIVE) { + DISPERR("Can't enter tui: current_stat=%d is not alive\n", primary_get_state()); + goto err0; + } + + power_stat_backup = primary_set_state(DISP_BLANK); + + primary_display_idlemgr_kick((char *)__func__, 0); + + if (primary_display_is_mirror_mode()) { + DISPERR("Can't enter tui: current_mode=%s\n", session_mode_spy(pgc->session_mode)); + goto err1; + } + + stop_smart_ovl_nolock(); + + session_mode_backup = pgc->session_mode; + + if (session_mode_backup == DISP_SESSION_RDMA_MODE) { + do_primary_display_switch_mode(DISP_SESSION_DIRECT_LINK_MODE, pgc->session_id, 0, NULL, 0); + session_mode_backup = DISP_SESSION_DIRECT_LINK_MODE; + } + + do_primary_display_switch_mode(DISP_SESSION_DECOUPLE_MODE, pgc->session_id, 0, NULL, 0); + display_vsync_switch_to_dsi(1); + + MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagPulse, 0, 1); + + _primary_path_unlock(__func__); + return 0; + +err1: + primary_set_state(power_stat_backup); + +err0: + MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagEnd, 0, 0); + _primary_path_unlock(__func__); + + return -1; +} + +int display_exit_tui(void) +{ + pr_info("[TUI-HAL] display_exit_tui() start\n"); + MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagPulse, 1, 1); + + _primary_path_lock(__func__); + primary_set_state(power_stat_backup); + + /* trigger rdma to display last normal buffer */ + _decouple_update_rdma_config_nolock(); + /*workaround: wait until this frame triggered to lcm */ + msleep(32); + do_primary_display_switch_mode(session_mode_backup, pgc->session_id, 0, NULL, 0); + /*DISP_REG_SET(NULL, DISP_REG_RDMA_INT_ENABLE, 0xffffffff);*/ + + restart_smart_ovl_nolock(); + display_vsync_switch_to_dsi(0); + _primary_path_unlock(__func__); + + MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagEnd, 0, 0); + DISPMSG("TDDP: %s\n", __func__); + pr_info("[TUI-HAL] display_exit_tui() done\n"); + return 0; + +} + +int primary_display_signal_recovery(void) +{ + DISPMSG("[Primary Recovery] signal\n"); + atomic_set(&primary_recovery_task_wakeup, 1); + wake_up_interruptible(&primary_recovery_task_wq); + return 0; +} + +static int primary_display_recovery_thread(void *data) +{ + int ret = 0; + + struct sched_param param = {.sched_priority = 87 }; + + sched_setscheduler(current, SCHED_RR, ¶m); + DISPMSG("[primary_display_recovery_thread]\n"); + while (1) { + msleep(1500); + ret = + wait_event_interruptible(primary_recovery_task_wq, + atomic_read + (&primary_recovery_task_wakeup)); + atomic_set(&primary_recovery_task_wakeup, 0); + pr_debug("[Primary Recovery] begin ret %d\n", ret); + _primary_path_lock(__func__); + if (pgc->state != DISP_SLEPT) { + primary_display_idlemgr_kick((char *)__func__, 0); + if (ret == 0) { + DISPMSG("[Primary Recovery]stop cmdq trigger loop\n"); + _cmdq_stop_trigger_loop(); + + if (dpmgr_path_is_busy(pgc->dpmgr_handle)) { + pr_debug("[ESD]primary display path is busy\n"); + ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, + DISP_PATH_EVENT_FRAME_DONE, HZ * 1); + pr_debug("[ESD]wait frame done ret:%d\n", ret); + } + + if (0 != ret) { + pr_debug("[Primary Recovery]stop path\n"); + dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE); + } + + DISPMSG("[Primary Recovery] path reset\n"); + dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); + + DISPMSG("[Primary Recovery] path start\n"); + dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE); + + DISPMSG("[Primary Recovery]start cmdq trigger loop\n"); + _cmdq_start_trigger_loop(); + + /* (in suspend) when we stop trigger loop + * if no other thread is running, cmdq may disable its clock + * all cmdq event will be cleared after suspend */ + cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_EOF); + + if (primary_display_is_video_mode()) { + /* for video mode, need to force trigger here */ + /* for cmd mode, */ + /* just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */ + dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE); + } else { + cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_CONFIG_DIRTY); + mdelay(40); + } + } + } else { + pr_debug + ("[Primary Recovery] can not recovery path in suspend\n"); + } + _primary_path_unlock(__func__); + pr_debug("[Primary Recovery] end\n"); + + if (kthread_should_stop()) + break; + } + return ret; + +} +int display_freeze_mode(int enable, int need_lock) +{ + + DISPMSG("%s, enable:%d\n", __func__, enable); + MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagStart, 0, 0); + + if (need_lock) + _primary_path_lock(__func__); + if (enable) { + if (primary_get_state() != DISP_ALIVE) { + DISPERR("Can't enter freeze mode: current_stat=%d is not alive\n", primary_get_state()); + goto end; + } + disp_helper_set_option(DISP_OPT_SMART_OVL, 0); + _allocate_freeze_buffer(); + power_stat_backup = primary_set_state(DISP_FREEZE); + if (primary_display_is_mirror_mode()) { + DISPERR("Can't enter freeze mode: current_mode=%s\n", session_mode_spy(pgc->session_mode)); + goto err1; + } + primary_display_idlemgr_kick((char *)__func__, 0); + session_mode_backup = pgc->session_mode; + if (session_mode_backup == DISP_SESSION_DECOUPLE_MODE + || session_mode_backup == DISP_SESSION_RDMA_MODE) { + do_primary_display_switch_mode(DISP_SESSION_DIRECT_LINK_MODE, + pgc->session_id, 0, NULL, 0); + session_mode_backup = DISP_SESSION_DIRECT_LINK_MODE; + } + do_primary_display_switch_mode(DISP_SESSION_DECOUPLE_MODE, + pgc->session_id, 0, NULL, 0); + } else { + if (primary_get_state() != DISP_FREEZE) + goto end; + primary_set_state(power_stat_backup); + primary_display_idlemgr_kick((char *)__func__, 0); + do_primary_display_switch_mode(session_mode_backup, pgc->session_id, + 0, NULL, 0); + release_freeze_buffer(); + disp_helper_set_option(DISP_OPT_SMART_OVL, 1); + } + if (need_lock) + _primary_path_unlock(__func__); + return 0; + +err1: + primary_set_state(power_stat_backup); + release_freeze_buffer(); +end: + if (need_lock) + _primary_path_unlock(__func__); + + return -1; +} diff --git a/drivers/misc/mediatek/video/mt6755/primary_display.h b/drivers/misc/mediatek/video/mt6755/primary_display.h new file mode 100644 index 0000000000000000000000000000000000000000..048b39da99ff8d0935145ddee64128c81b462644 --- /dev/null +++ b/drivers/misc/mediatek/video/mt6755/primary_display.h @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _PRIMARY_DISPLAY_H_ +#define _PRIMARY_DISPLAY_H_ + +#include "ddp_hal.h" +#include "ddp_manager.h" +#include +#include "disp_session.h" +#include "disp_lcm.h" +#include "disp_helper.h" +typedef enum { + DIRECT_LINK_MODE, + DECOUPLE_MODE, + SINGLE_LAYER_MODE, + DEBUG_RDMA1_DSI0_MODE +} DISP_PRIMARY_PATH_MODE; + +#define ALIGN_TO(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) + +#define ASSERT_LAYER (DDP_OVL_LAYER_MUN-1) +extern unsigned int FB_LAYER; /* default LCD layer */ +#define DISP_DEFAULT_UI_LAYER_ID (DDP_OVL_LAYER_MUN-1) +#define DISP_CHANGED_UI_LAYER_ID (DDP_OVL_LAYER_MUN-2) + +typedef struct { + unsigned int id; + unsigned int curr_en; + unsigned int next_en; + unsigned int hw_en; + int curr_idx; + int next_idx; + int hw_idx; + int curr_identity; + int next_identity; + int hw_identity; + int curr_conn_type; + int next_conn_type; + int hw_conn_type; +} DISP_LAYER_INFO; + +typedef enum { + DISP_STATUS_OK = 0, + + DISP_STATUS_NOT_IMPLEMENTED, + DISP_STATUS_ALREADY_SET, + DISP_STATUS_ERROR, +} DISP_STATUS; + + +typedef enum { + DISP_STATE_IDLE = 0, + DISP_STATE_BUSY, +} DISP_STATE; + +typedef enum { + DISP_OP_PRE = 0, + DISP_OP_NORMAL, + DISP_OP_POST, +} DISP_OP_STATE; + +typedef enum { + DISP_ALIVE = 0xf0, + DISP_SLEPT, + DISP_BLANK, + DISP_FREEZE, +} DISP_POWER_STATE; + +typedef enum { + FRM_CONFIG = 0, + FRM_TRIGGER, + FRM_START, + FRM_END +} DISP_FRM_SEQ_STATE; + +typedef enum { + DISPLAY_HAL_IOCTL_SET_CMDQ = 0xff00, + DISPLAY_HAL_IOCTL_ENABLE_CMDQ, + DISPLAY_HAL_IOCTL_DUMP, + DISPLAY_HAL_IOCTL_PATTERN, +} DISPLAY_HAL_IOCTL; + + +typedef struct { + unsigned int layer; + unsigned int layer_en; + unsigned int buffer_source; + unsigned int fmt; + unsigned long addr; + unsigned long addr_sub_u; + unsigned long addr_sub_v; + unsigned long vaddr; + unsigned int src_x; + unsigned int src_y; + unsigned int src_w; + unsigned int src_h; + unsigned int src_pitch; + unsigned int dst_x; + unsigned int dst_y; + unsigned int dst_w; + unsigned int dst_h; /* clip region */ + unsigned int keyEn; + unsigned int key; + unsigned int aen; + unsigned char alpha; + + unsigned int sur_aen; + unsigned int src_alpha; + unsigned int dst_alpha; + + + unsigned int isTdshp; + unsigned int isDirty; + + unsigned int buff_idx; + unsigned int identity; + unsigned int connected_type; + DISP_BUFFER_TYPE security; + unsigned int dirty; + unsigned int yuv_range; +} primary_disp_input_config; + +typedef struct { + enum UNIFIED_COLOR_FMT fmt; + unsigned long addr; + unsigned long addr_sub_u; + unsigned long addr_sub_v; + unsigned long vaddr; + unsigned int x; + unsigned int y; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitchUV; + + unsigned int buff_idx; + unsigned int interface_idx; + DISP_BUFFER_TYPE security; + unsigned int dirty; + int mode; +} disp_mem_output_config; + +#define DISP_INTERNAL_BUFFER_COUNT 3 + +typedef struct { + struct list_head list; + struct ion_handle *handle; + struct sync_fence *pfence; + void *va; + uint32_t fence_id; + uint32_t mva; + uint32_t size; + uint32_t output_fence_id; + uint32_t interface_fence_id; + unsigned long long timestamp; + struct ion_client *client; +} disp_internal_buffer_info; + +typedef struct { + unsigned int mva; + unsigned int max_offset; + unsigned int seq; + DISP_FRM_SEQ_STATE state; +} disp_frm_seq_info; + +typedef struct _opt_backup { + DISP_HELPER_OPT option; + int value; +} OPT_BACKUP; + +typedef int (*PRIMARY_DISPLAY_CALLBACK) (unsigned int user_data); + +int primary_display_init(char *lcm_name, unsigned int lcm_fps, int is_lcm_inited); +int primary_display_config(unsigned long pa, unsigned long mva); +int primary_display_set_frame_buffer_address(unsigned long va, unsigned long mva); +unsigned long primary_display_get_frame_buffer_mva_address(void); +unsigned long primary_display_get_frame_buffer_va_address(void); +int primary_display_suspend(void); +int primary_display_resume(void); +int primary_display_ipoh_restore(void); +int primary_display_get_width(void); +int primary_display_get_height(void); +int primary_display_get_virtual_width(void); +int primary_display_get_virtual_height(void); +int primary_display_get_bpp(void); +int primary_display_get_pages(void); +int primary_display_set_overlay_layer(primary_disp_input_config *input); +int primary_display_is_alive(void); +int primary_display_is_sleepd(void); +int primary_display_wait_for_vsync(void *config); +unsigned int primary_display_get_ticket(void); +int primary_display_user_cmd(unsigned int cmd, unsigned long arg); +int primary_display_trigger(int blocking, void *callback, int need_merge); +int primary_display_switch_mode(int sess_mode, unsigned int session, int force); +int primary_display_diagnose(void); +int primary_display_signal_recovery(void); +int primary_display_get_info(disp_session_info *info); +int primary_display_capture_framebuffer(unsigned long pbuf); +int primary_display_capture_framebuffer_ovl(unsigned long pbuf, unsigned int format); + +int primary_display_is_video_mode(void); +int primary_is_sec(void); +int do_primary_display_switch_mode(int sess_mode, unsigned int session, int need_lock, + cmdqRecHandle handle, int block); +DISP_MODE primary_get_sess_mode(void); +unsigned int primary_get_sess_id(void); +DISP_POWER_STATE primary_get_state(void); +disp_lcm_handle *primary_get_lcm(void); +void *primary_get_dpmgr_handle(void); +void _cmdq_stop_trigger_loop(void); +void _cmdq_start_trigger_loop(void); +void *primary_get_ovl2mem_handle(void); +int primary_display_is_decouple_mode(void); +int primary_display_is_mirror_mode(void); +unsigned int primary_display_get_option(const char *option); +CMDQ_SWITCH primary_display_cmdq_enabled(void); +int primary_display_switch_cmdq_cpu(CMDQ_SWITCH use_cmdq); +int primary_display_manual_lock(void); +int primary_display_manual_unlock(void); +int primary_display_start(void); +int primary_display_stop(void); +int primary_display_esd_recovery(void); +int primary_display_get_debug_state(char *stringbuf, int buf_len); +void primary_display_set_max_layer(int maxlayer); +void primary_display_reset(void); +void primary_display_esd_check_enable(int enable); +int primary_display_config_input_multiple(disp_session_input_config *session_input); +int primary_display_frame_cfg(struct disp_frame_cfg_t *cfg); +int primary_display_force_set_vsync_fps(unsigned int fps); +unsigned int primary_display_get_fps(void); +unsigned int primary_display_get_fps_nolock(void); +int primary_display_get_original_width(void); +int primary_display_get_original_height(void); +int primary_display_lcm_ATA(void); +int primary_display_setbacklight(unsigned int level); +int primary_display_pause(PRIMARY_DISPLAY_CALLBACK callback, unsigned int user_data); +int primary_display_switch_dst_mode(int mode); +int primary_display_get_lcm_index(void); +int primary_display_force_set_fps(unsigned int keep, unsigned int skip); +int primary_display_set_fps(int fps); +void primary_display_idlemgr_kick(const char *source, int need_lock); +void primary_display_update_present_fence(unsigned int fence_idx); +int primary_display_switch_esd_mode(int mode); +int primary_display_cmdq_set_reg(unsigned int addr, unsigned int val); +int primary_display_vsync_switch(int method); +int primary_display_setlcm_cmd(unsigned int *lcm_cmd, unsigned int *lcm_count, + unsigned int *lcm_value); +int primary_display_mipi_clk_change(unsigned int clk_value); + +void _cmdq_insert_wait_frame_done_token_mira(void *handle); +int primary_display_get_max_layer(void); +long primary_display_wait_state(DISP_POWER_STATE state, long timeout); +int do_primary_display_switch_mode(int sess_mode, unsigned int session, int need_lock, + cmdqRecHandle handle, int block); +int primary_display_check_test(void); +void _primary_path_switch_dst_lock(void); +void _primary_path_switch_dst_unlock(void); +int pd_release_dc_buffer(void); +int pd_allocate_dc_buffer(void); + +/* legancy */ +LCM_PARAMS *DISP_GetLcmPara(void); +LCM_DRIVER *DISP_GetLcmDrv(void); +uint32_t DISP_GetVRamSize(void); +uint32_t DISP_GetFBRamSize(void); +uint32_t DISP_GetPages(void); +uint32_t DISP_GetScreenBpp(void); +uint32_t DISP_GetScreenWidth(void); +uint32_t DISP_GetScreenHeight(void); +uint32_t DISP_GetActiveHeight(void); +uint32_t DISP_GetActiveWidth(void); +uint32_t DISP_GetActiveHeightUm(void); +uint32_t DISP_GetActiveWidthUm(void); +unsigned long get_dim_layer_mva_addr(void); +int disp_hal_allocate_framebuffer(phys_addr_t pa_start, phys_addr_t pa_end, unsigned long *va, + unsigned long *mva); +int Panel_Master_dsi_config_entry(const char *name, void *config_value); +int fbconfig_get_esd_check_test(uint32_t dsi_id, uint32_t cmd, uint8_t *buffer, uint32_t num); + + +/* defined in mtkfb.c should move to mtkfb.h*/ +extern unsigned int islcmconnected; + +size_t mtkfb_get_fb_size(void); + +int primary_fps_ctx_set_wnd_sz(unsigned int wnd_sz); + +int dynamic_debug_msg_print(unsigned int mva, int w, int h, int pitch, int bytes_per_pix); + +int display_enter_tui(void); +int display_exit_tui(void); +int display_freeze_mode(int enable, int need_lock); + +#endif diff --git a/drivers/misc/mediatek/videocodec/mt6755/Makefile b/drivers/misc/mediatek/videocodec/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ab0a790ac400de02b9662a0695b35123b8621479 --- /dev/null +++ b/drivers/misc/mediatek/videocodec/mt6755/Makefile @@ -0,0 +1,29 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +vcodec_kernel_driver-objs := \ + videocodec_kernel_driver.o \ + common/val/src/val.o \ + common/drv/src/drv_base.o + +obj-$(CONFIG_MTK_VIDEOCODEC_DRIVER) += vcodec_kernel_driver.o + + +ccflags-y += \ + -I$(srctree)/drivers/misc/mediatek/videocodec/$(MTK_PLATFORM)/common/drv/inc \ + -I$(srctree)/drivers/misc/mediatek/videocodec/include \ + -I$(srctree)/drivers/misc/mediatek/videocodec/include/kernel \ + -I$(srctree)/drivers/misc/mediatek/include/mt-plat \ + -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach \ + -I$(srctree)/drivers/misc/mediatek/m4u/$(MTK_PLATFORM) + diff --git a/drivers/misc/mediatek/videocodec/mt6755/common/drv/inc/drv_api.h b/drivers/misc/mediatek/videocodec/mt6755/common/drv/inc/drv_api.h new file mode 100644 index 0000000000000000000000000000000000000000..351808efca059d5c8d75f828fb552c26ec1010ff --- /dev/null +++ b/drivers/misc/mediatek/videocodec/mt6755/common/drv/inc/drv_api.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT6755_DRVBASE_H__ +#define __MT6755_DRVBASE_H__ + +#include "val_types_private.h" + +/* ============================================================= */ +/* For driver */ + +typedef struct { + VAL_VOID_T *pvHandle; /* HW vcodec handle */ + VAL_TIME_T rLockedTime; + VAL_DRIVER_TYPE_T eDriverType; +} VAL_VCODEC_HW_LOCK_T; + +typedef struct { + VAL_ULONG_T ulKVA; /* Kernel virtual address */ + VAL_ULONG_T ulKPA; /* Kernel physical address */ + VAL_HANDLE_T pvHandle; /* */ + VAL_UINT32_T u4VCodecThreadNum; /* Hybrid vcodec thread num */ + VAL_UINT32_T u4VCodecThreadID[VCODEC_THREAD_MAX_NUM]; /* hybrid vcodec thread ids */ + VAL_ULONG_T ulSize; +} VAL_NON_CACHE_MEMORY_LIST_T; + +/* ============================================================== */ +/* For Hybrid HW */ +#define VCODEC_MULTIPLE_INSTANCE_NUM 16 +#define VCODEC_MULTIPLE_INSTANCE_NUM_x_10 (VCODEC_MULTIPLE_INSTANCE_NUM * 10) + +/* spinlock : OalHWContextLock */ +extern VAL_VCODEC_OAL_HW_CONTEXT_T oal_hw_context[VCODEC_MULTIPLE_INSTANCE_NUM]; +/* mutex : NonCacheMemoryListLock */ +extern VAL_NON_CACHE_MEMORY_LIST_T grNonCacheMemoryList[VCODEC_MULTIPLE_INSTANCE_NUM_x_10]; + +/* For both hybrid and pure HW */ +extern VAL_VCODEC_HW_LOCK_T grVcodecDecHWLock; /* mutex : VdecHWLock */ +extern VAL_VCODEC_HW_LOCK_T grVcodecEncHWLock; /* mutex : VencHWLock */ + +extern VAL_UINT32_T gu4LockDecHWCount; /* spinlock : LockDecHWCountLock */ +extern VAL_UINT32_T gu4LockEncHWCount; /* spinlock : LockEncHWCountLock */ +extern VAL_UINT32_T gu4DecISRCount; /* spinlock : DecISRCountLock */ +extern VAL_UINT32_T gu4EncISRCount; /* spinlock : EncISRCountLock */ + +VAL_INT32_T search_HWLockSlot_ByTID(VAL_ULONG_T ulpa, VAL_UINT32_T curr_tid); +VAL_INT32_T search_HWLockSlot_ByHandle(VAL_ULONG_T ulpa, VAL_HANDLE_T handle); +VAL_VCODEC_OAL_HW_CONTEXT_T *setCurr_HWLockSlot(VAL_ULONG_T ulpa, VAL_UINT32_T tid); +VAL_VCODEC_OAL_HW_CONTEXT_T *setCurr_HWLockSlot_Thread_ID(VAL_VCODEC_THREAD_ID_T a_prVcodecThreadID, + VAL_UINT32_T *a_prIndex); +VAL_VCODEC_OAL_HW_CONTEXT_T *freeCurr_HWLockSlot(VAL_ULONG_T ulpa); +void Add_NonCacheMemoryList(VAL_ULONG_T a_ulKVA, + VAL_ULONG_T a_ulKPA, + VAL_ULONG_T a_ulSize, + VAL_UINT32_T a_u4VCodecThreadNum, VAL_UINT32_T *a_pu4VCodecThreadID); +void Free_NonCacheMemoryList(VAL_ULONG_T a_ulKVA, VAL_ULONG_T a_ulKPA); +void Force_Free_NonCacheMemoryList(VAL_UINT32_T a_u4Tid); +VAL_ULONG_T Search_NonCacheMemoryList_By_KPA(VAL_ULONG_T a_u4KPA); + +#endif diff --git a/drivers/misc/mediatek/videocodec/mt6755/common/drv/src/drv_base.c b/drivers/misc/mediatek/videocodec/mt6755/common/drv/src/drv_base.c new file mode 100644 index 0000000000000000000000000000000000000000..f01c1f7044755f9252cd9b049f47c111e1c77f52 --- /dev/null +++ b/drivers/misc/mediatek/videocodec/mt6755/common/drv/src/drv_base.c @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include "val_types_private.h" +#include "val_log.h" +#include "drv_api.h" + +/* #define VCODEC_DEBUG */ +#ifdef VCODEC_DEBUG +#undef VCODEC_DEBUG +#define VCODEC_DEBUG MODULE_MFV_LOGE +#undef MODULE_MFV_LOGD +#define MODULE_MFV_LOGD MODULE_MFV_LOGE +#else +#define VCODEC_DEBUG(...) +#undef MODULE_MFV_LOGD +#define MODULE_MFV_LOGD(...) +#endif + +/* ============================================================== */ +/* For Hybrid HW */ +/* spinlock : OalHWContextLock */ +VAL_VCODEC_OAL_HW_CONTEXT_T oal_hw_context[VCODEC_MULTIPLE_INSTANCE_NUM]; +/* mutex : NonCacheMemoryListLock */ +VAL_NON_CACHE_MEMORY_LIST_T grNonCacheMemoryList[VCODEC_MULTIPLE_INSTANCE_NUM_x_10]; + +/* For both hybrid and pure HW */ +VAL_VCODEC_HW_LOCK_T grVcodecDecHWLock; /* mutex : VdecHWLock */ +VAL_VCODEC_HW_LOCK_T grVcodecEncHWLock; /* mutex : VencHWLock */ + +VAL_UINT32_T gu4LockDecHWCount; /* spinlock : LockDecHWCountLock */ +VAL_UINT32_T gu4LockEncHWCount; /* spinlock : LockEncHWCountLock */ +VAL_UINT32_T gu4DecISRCount; /* spinlock : DecISRCountLock */ +VAL_UINT32_T gu4EncISRCount; /* spinlock : EncISRCountLock */ + + +VAL_INT32_T search_HWLockSlot_ByTID(VAL_ULONG_T ulpa, VAL_UINT32_T curr_tid) +{ + int i; + int j; + + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + if (oal_hw_context[i].u4VCodecThreadNum != VCODEC_THREAD_MAX_NUM) { + for (j = 0; j < oal_hw_context[i].u4VCodecThreadNum; j++) { + if (oal_hw_context[i].u4VCodecThreadID[j] == curr_tid) { + MODULE_MFV_LOGD("[VCODEC][search_HWLockSlot_ByTID]\n"); + MODULE_MFV_LOGD("Lookup curr HW Locker is ObjId %d in index%d\n", + curr_tid, i); + return i; + } + } + } + } + + return -1; +} + +VAL_INT32_T search_HWLockSlot_ByHandle(VAL_ULONG_T ulpa, VAL_HANDLE_T handle) +{ + VAL_INT32_T i; + + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + if (oal_hw_context[i].pvHandle == handle) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + return i; + } + } + + /* dump debug info */ + MODULE_MFV_LOGE("search_HWLockSlot_ByHandle"); + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM / 2; i++) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[%d] 0x%lx", i, oal_hw_context[i].pvHandle); + } + + return -1; +} + +VAL_VCODEC_OAL_HW_CONTEXT_T *setCurr_HWLockSlot(VAL_ULONG_T ulpa, VAL_UINT32_T tid) +{ + + int i, j; + + /* Dump current ObjId */ + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGD("[VCODEC] Dump curr slot %d ObjId 0x%lx\n", i, oal_hw_context[i].ObjId); + } + + /* check if current ObjId exist in oal_hw_context[i].ObjId */ + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + if (oal_hw_context[i].ObjId == ulpa) { + MODULE_MFV_LOGD("[VCODEC] Curr Already exist in %d Slot\n", i); + return &oal_hw_context[i]; + } + } + + /* if not exist in table, find a new free slot and put it */ + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + if (oal_hw_context[i].u4VCodecThreadNum != VCODEC_THREAD_MAX_NUM) { + for (j = 0; j < oal_hw_context[i].u4VCodecThreadNum; j++) { + if (oal_hw_context[i].u4VCodecThreadID[j] == current->pid) { + oal_hw_context[i].ObjId = ulpa; + MODULE_MFV_LOGD("[VCODEC][setCurr_HWLockSlot] setCurr %d Slot\n", + i); + return &oal_hw_context[i]; + } + } + } + } + + MODULE_MFV_LOGE("[VCODEC][ERROR] setCurr_HWLockSlot All %d Slots unavaliable\n", + VCODEC_MULTIPLE_INSTANCE_NUM); + oal_hw_context[0].u4VCodecThreadNum = VCODEC_THREAD_MAX_NUM - 1; + for (i = 0; i < oal_hw_context[0].u4VCodecThreadNum; i++) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + oal_hw_context[0].u4VCodecThreadID[i] = current->pid; + } + return &oal_hw_context[0]; +} + + +VAL_VCODEC_OAL_HW_CONTEXT_T *setCurr_HWLockSlot_Thread_ID(VAL_VCODEC_THREAD_ID_T a_prVcodecThreadID, + VAL_UINT32_T *a_prIndex) +{ + int i; + int j; + int k; + + /* Dump current tids */ + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + if (oal_hw_context[i].u4VCodecThreadNum != VCODEC_THREAD_MAX_NUM) { + for (j = 0; j < oal_hw_context[i].u4VCodecThreadNum; j++) { + MODULE_MFV_LOGD("[VCODEC][setCurr_HWLockSlot_Thread_ID]\n"); + MODULE_MFV_LOGD("Dump curr slot %d, ThreadID[%d] = %d\n", + i, j, oal_hw_context[i].u4VCodecThreadID[j]); + } + } + } + + for (i = 0; i < a_prVcodecThreadID.u4VCodecThreadNum; i++) { + MODULE_MFV_LOGD + ("[VCODEC][setCurr_HWLockSlot_Thread_ID] VCodecThreadNum = %d, VCodecThreadID = %d\n", + a_prVcodecThreadID.u4VCodecThreadNum, a_prVcodecThreadID.u4VCodecThreadID[i] + ); + } + + /* check if current tids exist in oal_hw_context[i].ObjId */ + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + if (oal_hw_context[i].u4VCodecThreadNum != VCODEC_THREAD_MAX_NUM) { + for (j = 0; j < oal_hw_context[i].u4VCodecThreadNum; j++) { + for (k = 0; k < a_prVcodecThreadID.u4VCodecThreadNum; k++) { + if (oal_hw_context[i].u4VCodecThreadID[j] == + a_prVcodecThreadID.u4VCodecThreadID[k]) { + MODULE_MFV_LOGE + ("[VCODEC][setCurr_HWLockSlot_Thread_ID]\n"); + MODULE_MFV_LOGE("Curr Already exist in %d Slot\n", i); + *a_prIndex = i; + return &oal_hw_context[i]; + } + } + } + } + } + + /* if not exist in table, find a new free slot and put it */ + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + if (oal_hw_context[i].u4VCodecThreadNum == VCODEC_THREAD_MAX_NUM) { + oal_hw_context[i].u4VCodecThreadNum = a_prVcodecThreadID.u4VCodecThreadNum; + for (j = 0; j < a_prVcodecThreadID.u4VCodecThreadNum; j++) { + oal_hw_context[i].u4VCodecThreadID[j] = + a_prVcodecThreadID.u4VCodecThreadID[j]; + MODULE_MFV_LOGD + ("[VCODEC][setCurr_HWLockSlot_Thread_ID] setCurr %d Slot, %d\n", + i, oal_hw_context[i].u4VCodecThreadID[j]); + } + *a_prIndex = i; + return &oal_hw_context[i]; + } + } + + { + MODULE_MFV_LOGE("[VCODEC][ERROR] setCurr_HWLockSlot_Thread_ID All %d Slots unavaliable\n", + VCODEC_MULTIPLE_INSTANCE_NUM); + oal_hw_context[0].u4VCodecThreadNum = a_prVcodecThreadID.u4VCodecThreadNum; + for (i = 0; i < oal_hw_context[0].u4VCodecThreadNum; i++) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + oal_hw_context[0].u4VCodecThreadID[i] = + a_prVcodecThreadID.u4VCodecThreadID[i]; + } + *a_prIndex = 0; + return &oal_hw_context[0]; + } +} + + +VAL_VCODEC_OAL_HW_CONTEXT_T *freeCurr_HWLockSlot(VAL_ULONG_T ulpa) +{ + int i; + int j; + + /* check if current ObjId exist in oal_hw_context[i].ObjId */ + + for (i = 0; i < VCODEC_MULTIPLE_INSTANCE_NUM; i++) { + if (oal_hw_context[i].ObjId == ulpa) { + oal_hw_context[i].ObjId = -1L; + for (j = 0; j < oal_hw_context[i].u4VCodecThreadNum; j++) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + oal_hw_context[i].u4VCodecThreadID[j] = -1; + } + oal_hw_context[i].u4VCodecThreadNum = VCODEC_THREAD_MAX_NUM; + oal_hw_context[i].Oal_HW_reg = (VAL_VCODEC_OAL_HW_REGISTER_T *) 0; + MODULE_MFV_LOGD("[VCODEC] freeCurr_HWLockSlot %d Slot\n", i); + return &oal_hw_context[i]; + } + } + + MODULE_MFV_LOGE("[VCODEC][ERROR] freeCurr_HWLockSlot can't find pid in HWLockSlot\n"); + return 0; +} + + +void Add_NonCacheMemoryList(VAL_ULONG_T a_ulKVA, + VAL_ULONG_T a_ulKPA, + VAL_ULONG_T a_ulSize, + VAL_UINT32_T a_u4VCodecThreadNum, VAL_UINT32_T *a_pu4VCodecThreadID) +{ + VAL_UINT32_T u4I = 0; + VAL_UINT32_T u4J = 0; + + MODULE_MFV_LOGD("[VCODEC] Add_NonCacheMemoryList +, KVA = 0x%lx, KPA = 0x%lx, Size = 0x%lx\n", + a_ulKVA, a_ulKPA, a_ulSize); + + for (u4I = 0; u4I < VCODEC_MULTIPLE_INSTANCE_NUM_x_10; u4I++) { + if ((grNonCacheMemoryList[u4I].ulKVA == -1L) + && (grNonCacheMemoryList[u4I].ulKPA == -1L)) { + MODULE_MFV_LOGD + ("[VCODEC] Add_NonCacheMemoryList index = %d, VCodecThreadNum = %d, curr_tid = %d\n", + u4I, a_u4VCodecThreadNum, current->pid); + + grNonCacheMemoryList[u4I].u4VCodecThreadNum = a_u4VCodecThreadNum; + for (u4J = 0; u4J < grNonCacheMemoryList[u4I].u4VCodecThreadNum; u4J++) { + grNonCacheMemoryList[u4I].u4VCodecThreadID[u4J] = + *(a_pu4VCodecThreadID + u4J); + MODULE_MFV_LOGD + ("[VCODEC][Add_NonCacheMemoryList] VCodecThreadNum = %d, VCodecThreadID = %d\n", + grNonCacheMemoryList[u4I].u4VCodecThreadNum, + grNonCacheMemoryList[u4I].u4VCodecThreadID[u4J]); + } + + grNonCacheMemoryList[u4I].ulKVA = a_ulKVA; + grNonCacheMemoryList[u4I].ulKPA = a_ulKPA; + grNonCacheMemoryList[u4I].ulSize = a_ulSize; + break; + } + } + + if (u4I == VCODEC_MULTIPLE_INSTANCE_NUM_x_10) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] CAN'T ADD Add_NonCacheMemoryList, List is FULL!!\n"); + } + + MODULE_MFV_LOGD("[VCODEC] Add_NonCacheMemoryList -\n"); +} + +void Free_NonCacheMemoryList(VAL_ULONG_T a_ulKVA, VAL_ULONG_T a_ulKPA) +{ + VAL_UINT32_T u4I = 0; + VAL_UINT32_T u4J = 0; + + MODULE_MFV_LOGD("[VCODEC] Free_NonCacheMemoryList +, KVA = 0x%lx, KPA = 0x%lx\n", a_ulKVA, + a_ulKPA); + + for (u4I = 0; u4I < VCODEC_MULTIPLE_INSTANCE_NUM_x_10; u4I++) { + if ((grNonCacheMemoryList[u4I].ulKVA == a_ulKVA) + && (grNonCacheMemoryList[u4I].ulKPA == a_ulKPA)) { + MODULE_MFV_LOGD("[VCODEC] Free Free_NonCacheMemoryList index = %d\n", u4I); + grNonCacheMemoryList[u4I].u4VCodecThreadNum = VCODEC_THREAD_MAX_NUM; + for (u4J = 0; u4J < VCODEC_THREAD_MAX_NUM; u4J++) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + grNonCacheMemoryList[u4I].u4VCodecThreadID[u4J] = 0xffffffff; + } + + grNonCacheMemoryList[u4I].ulKVA = -1L; + grNonCacheMemoryList[u4I].ulKPA = -1L; + grNonCacheMemoryList[u4I].ulSize = -1L; + break; + } + } + + if (u4I == VCODEC_MULTIPLE_INSTANCE_NUM_x_10) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE + ("[VCODEC][ERROR] CAN'T Free Free_NonCacheMemoryList, Address is not find!!\n"); + } + + MODULE_MFV_LOGD("[VCODEC]Free_NonCacheMemoryList -\n"); +} + + +void Force_Free_NonCacheMemoryList(VAL_UINT32_T a_u4Tid) +{ + VAL_UINT32_T u4I = 0; + VAL_UINT32_T u4J = 0; + VAL_UINT32_T u4K = 0; + + MODULE_MFV_LOGD("[VCODEC] Force_Free_NonCacheMemoryList +, curr_id = %d", a_u4Tid); + + for (u4I = 0; u4I < VCODEC_MULTIPLE_INSTANCE_NUM_x_10; u4I++) { + if (grNonCacheMemoryList[u4I].u4VCodecThreadNum != VCODEC_THREAD_MAX_NUM) { + for (u4J = 0; u4J < grNonCacheMemoryList[u4I].u4VCodecThreadNum; u4J++) { + if (grNonCacheMemoryList[u4I].u4VCodecThreadID[u4J] == a_u4Tid) { + MODULE_MFV_LOGE + ("[VCODEC][WARNING] Force_Free_NonCacheMemoryList\n"); + MODULE_MFV_LOGE + ("index = %d, tid = %d, KVA = 0x%lx, KPA = 0x%lx, Size = %lu\n", + u4I, a_u4Tid, grNonCacheMemoryList[u4I].ulKVA, + grNonCacheMemoryList[u4I].ulKPA, + grNonCacheMemoryList[u4I].ulSize); + + dma_free_coherent(0, + grNonCacheMemoryList[u4I].ulSize, + (void *)grNonCacheMemoryList[u4I].ulKVA, + (dma_addr_t) grNonCacheMemoryList[u4I]. + ulKPA); + + grNonCacheMemoryList[u4I].u4VCodecThreadNum = + VCODEC_THREAD_MAX_NUM; + for (u4K = 0; u4K < VCODEC_THREAD_MAX_NUM; u4K++) { + /* Add one line comment for avoid kernel coding style, + WARNING:BRACES: */ + grNonCacheMemoryList[u4I].u4VCodecThreadID[u4K] = + 0xffffffff; + } + grNonCacheMemoryList[u4I].ulKVA = -1L; + grNonCacheMemoryList[u4I].ulKPA = -1L; + grNonCacheMemoryList[u4I].ulSize = -1L; + break; + } + } + } + } + + MODULE_MFV_LOGD("[VCODEC] Force_Free_NonCacheMemoryList -, curr_id = %d", a_u4Tid); +} + +VAL_ULONG_T Search_NonCacheMemoryList_By_KPA(VAL_ULONG_T a_ulKPA) +{ + VAL_UINT32_T u4I = 0; + VAL_ULONG_T ulVA_Offset = 0; + + ulVA_Offset = a_ulKPA & 0x0000000000000fff; + + MODULE_MFV_LOGD("[VCODEC] Search_NonCacheMemoryList_By_KPA +, KPA = 0x%lx, ulVA_Offset = 0x%lx\n", + a_ulKPA, ulVA_Offset); + + for (u4I = 0; u4I < VCODEC_MULTIPLE_INSTANCE_NUM_x_10; u4I++) { + if (grNonCacheMemoryList[u4I].ulKPA == (a_ulKPA - ulVA_Offset)) { + MODULE_MFV_LOGD("[VCODEC] Find Search_NonCacheMemoryList_By_KPA index = %d\n", + u4I); + break; + } + } + + if (u4I == VCODEC_MULTIPLE_INSTANCE_NUM_x_10) { + MODULE_MFV_LOGE + ("[VCODEC][ERROR] CAN'T Find Search_NonCacheMemoryList_By_KPA, Address is not find!!\n"); + return grNonCacheMemoryList[0].ulKVA + ulVA_Offset; + } + + MODULE_MFV_LOGD("[VCODEC] Search_NonCacheMemoryList_By_KPA, ulVA = 0x%lx -\n", + (grNonCacheMemoryList[u4I].ulKVA + ulVA_Offset)); + + return grNonCacheMemoryList[u4I].ulKVA + ulVA_Offset; +} diff --git a/drivers/misc/mediatek/videocodec/mt6755/common/hal/src/hal.c b/drivers/misc/mediatek/videocodec/mt6755/common/hal/src/hal.c new file mode 100644 index 0000000000000000000000000000000000000000..37290503dc2d1178fb1d86a359318229a3cc8048 --- /dev/null +++ b/drivers/misc/mediatek/videocodec/mt6755/common/hal/src/hal.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "hal_api.h" + +VAL_RESULT_T eHalInit(VAL_HANDLE_T *a_phHalHandle) +{ + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eHalDeInit(VAL_HANDLE_T *a_phHalHandle) +{ + + return VAL_RESULT_NO_ERROR; +} + + +VAL_RESULT_T eHalCmdProc(VAL_HANDLE_T *a_hHalHandle, + HAL_CMD_T a_eHalCmd, VAL_VOID_T *a_pvInParam, VAL_VOID_T *a_pvOutParam) +{ + switch (a_eHalCmd) { + case HAL_CMD_SET_CMD_QUEUE: + break; + case HAL_CMD_SET_POWER: + break; + case HAL_CMD_SET_ISR: + break; + default: + return VAL_RESULT_INVALID_PARAMETER; + } + + return VAL_RESULT_NO_ERROR; +} diff --git a/drivers/misc/mediatek/videocodec/mt6755/common/val/src/val.c b/drivers/misc/mediatek/videocodec/mt6755/common/val/src/val.c new file mode 100644 index 0000000000000000000000000000000000000000..76b1057b8ea2acbdc2f9e10cfd799215fe8bee70 --- /dev/null +++ b/drivers/misc/mediatek/videocodec/mt6755/common/val/src/val.c @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 Files + *===========================================================================*/ +#include "val_types_private.h" +#include "val_api_private.h" +#include "val_log.h" +/* #include "mfv_reg.h" */ +/* #include "mfv_config.h" */ +#include +#include +#include +#include +#include +#include +#include + +#define MAX_HEAP_SIZE (0x1000000) +#ifdef _6573_FPGA +#define GMC 0xC8000000 +#else /* _6573_REAL_CHIP E1 address */ +#define GMC 0x40000000 +#endif + + + +/*============================================================================= + * Function Body + *===========================================================================*/ + +VAL_RESULT_T eVideoMemAlloc(VAL_MEMORY_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoMemFree(VAL_MEMORY_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + /* MODULE_MFV_LOGD("!!Free Mem Size:%d!!\n",a_prParam->u4MemSize); */ + + return VAL_RESULT_NO_ERROR; + +} + +/* mimic internal memory buffer, 128K bytes. */ +VAL_RESULT_T eVideoIntMemUsed(VAL_INTMEM_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + + return VAL_RESULT_NO_ERROR; +} + +/* mimic internal memory buffer, 128K bytes. */ +VAL_RESULT_T eVideoIntMemAlloc(VAL_INTMEM_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + + return VAL_RESULT_NO_ERROR; +} + +/* mimic internal memory buffer, 128K bytes. */ +VAL_RESULT_T eVideoIntMemFree(VAL_INTMEM_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + + return VAL_RESULT_NO_ERROR; +} + + + +VAL_RESULT_T eVideoCreateEvent(VAL_EVENT_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + wait_queue_head_t *pWaitQueue; + VAL_UINT8_T *pFlag; + + pWaitQueue = kmalloc(sizeof(wait_queue_head_t), GFP_ATOMIC); + pFlag = kmalloc(sizeof(VAL_UINT8_T), GFP_ATOMIC); + if (pWaitQueue != VAL_NULL) { + init_waitqueue_head(pWaitQueue); + a_prParam->pvWaitQueue = (VAL_VOID_T *) pWaitQueue; + } else { + MODULE_MFV_LOGE("[VCODEC][ERROR] Event wait Queue failed to create\n"); + } + if (pFlag != VAL_NULL) { + a_prParam->pvReserved = (VAL_VOID_T *) pFlag; + *((VAL_UINT8_T *) a_prParam->pvReserved) = VAL_FALSE; + } else { + MODULE_MFV_LOGE("[VCODEC][ERROR] Event flag failed to create\n"); + } + + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoCloseEvent(VAL_EVENT_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + wait_queue_head_t *pWaitQueue; + VAL_UINT8_T *pFlag; + + pWaitQueue = (wait_queue_head_t *) a_prParam->pvWaitQueue; + pFlag = (VAL_UINT8_T *) a_prParam->pvReserved; + + kfree(pWaitQueue); + kfree(pFlag); + + a_prParam->pvWaitQueue = VAL_NULL; + a_prParam->pvReserved = VAL_NULL; + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoWaitEvent(VAL_EVENT_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + wait_queue_head_t *pWaitQueue; + long timeout_jiff, i4Ret; + VAL_RESULT_T status; + + pWaitQueue = (wait_queue_head_t *) a_prParam->pvWaitQueue; + timeout_jiff = (a_prParam->u4TimeoutMs) * HZ / 1000; + /* MODULE_MFV_LOGD("[MFV]eVideoWaitEvent,a_prParam->u4TimeoutMs=%d, timeout = %ld\n", + a_prParam->u4TimeoutMs,timeout_jiff); */ + i4Ret = wait_event_interruptible_timeout(*pWaitQueue, + *((VAL_UINT8_T *) a_prParam-> + pvReserved) /*g_mflexvideo_interrupt_handler */ , + timeout_jiff); + if (0 == i4Ret) { + MODULE_MFV_LOGE("[VCODEC] eVideoWaitEvent timeout: %d ms", a_prParam->u4TimeoutMs); + status = VAL_RESULT_INVALID_ISR; /* timeout */ + } else if (-ERESTARTSYS == i4Ret) { + MODULE_MFV_LOGE("[VCODEC] eVideoWaitEvent wake up by ERESTARTSYS"); + status = VAL_RESULT_RESTARTSYS; + } else if (i4Ret > 0) { + status = VAL_RESULT_NO_ERROR; + } else { + MODULE_MFV_LOGE("[VCODEC] eVideoWaitEvent wake up by %ld", i4Ret); + status = VAL_RESULT_NO_ERROR; + } + *((VAL_UINT8_T *) a_prParam->pvReserved) = VAL_FALSE; + return status; +} + +VAL_RESULT_T eVideoSetEvent(VAL_EVENT_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + wait_queue_head_t *pWaitQueue; + /* MODULE_MFV_LOGD("[MFV]eVideoSetEvent\n"); */ + pWaitQueue = (wait_queue_head_t *) a_prParam->pvWaitQueue; + if (a_prParam->pvReserved != VAL_NULL) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + *((VAL_UINT8_T *) a_prParam->pvReserved) = VAL_TRUE; + } else { + MODULE_MFV_LOGE("[VCODEC][ERROR]Event flag should not be null\n"); + } + if (pWaitQueue != VAL_NULL) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + wake_up_interruptible(pWaitQueue); + } else { + MODULE_MFV_LOGE("[VCODEC][ERROR]Wait Queue should not be null\n"); + } + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoCreateMutex(VAL_MUTEX_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + struct semaphore *pLock; + + pLock = kmalloc(sizeof(struct semaphore), GFP_ATOMIC); + if (pLock != VAL_NULL) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + a_prParam->pvMutex = (VAL_VOID_T *) pLock; + } else { + MODULE_MFV_LOGE("[VCODEC][ERROR]Enable to create mutex!\n"); + } + /* init_MUTEX(pLock); */ + sema_init(pLock, 1); + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoCloseMutex(VAL_MUTEX_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + if (a_prParam->pvMutex != VAL_NULL) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + kfree(a_prParam->pvMutex); + } + a_prParam->pvMutex = VAL_NULL; + return VAL_RESULT_NO_ERROR; +} + + +VAL_RESULT_T eVideoWaitMutex(VAL_MUTEX_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + struct semaphore *pLock; + + pLock = (struct semaphore *)a_prParam->pvMutex; + down(pLock); + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoReleaseMutex(VAL_MUTEX_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + struct semaphore *pLock; + + pLock = (struct semaphore *)a_prParam->pvMutex; + up(pLock); + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoMemSet(VAL_MEMORY_T *a_prParam, + VAL_UINT32_T a_u4ParamSize, VAL_INT32_T a_u4Value, VAL_UINT32_T a_u4Size) +{ + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoMemCpy(VAL_MEMORY_T *a_prParamDst, + VAL_UINT32_T a_u4ParamDstSize, + VAL_MEMORY_T *a_prParamSrc, + VAL_UINT32_T a_u4ParamSrcSize, VAL_UINT32_T a_u4Size) +{ + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoMemCmp(VAL_MEMORY_T *a_prParamSrc1, + VAL_UINT32_T a_u4ParamSrc1Size, + VAL_MEMORY_T *a_prParamSrc2, + VAL_UINT32_T a_u4ParamSrc2Size, VAL_UINT32_T a_u4Size) +{ + return VAL_RESULT_NO_ERROR; +} + +VAL_RESULT_T eVideoGetTimeOfDay(VAL_TIME_T *a_prParam, VAL_UINT32_T a_u4ParamSize) +{ + struct timeval t1; + + do_gettimeofday(&t1); + a_prParam->u4Sec = t1.tv_sec; + a_prParam->u4uSec = t1.tv_usec; + return VAL_RESULT_NO_ERROR; +} diff --git a/drivers/misc/mediatek/videocodec/mt6755/videocodec_kernel_driver.c b/drivers/misc/mediatek/videocodec/mt6755/videocodec_kernel_driver.c new file mode 100644 index 0000000000000000000000000000000000000000..b74e9af0ed1a06f0a6e0fcb82fbaafaf45056a05 --- /dev/null +++ b/drivers/misc/mediatek/videocodec/mt6755/videocodec_kernel_driver.c @@ -0,0 +1,2532 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +#include +#include +#include +#include "mt-plat/sync_write.h" + +#ifndef CONFIG_MTK_CLKMGR +#include +#else +#include "mach/mt_clkmgr.h" +#endif + +#ifdef CONFIG_MTK_HIBERNATION +#include +#include +#endif + +#include "videocodec_kernel_driver.h" +#include "../videocodec_kernel.h" +#include +#include +#include +#include "val_types_private.h" +#include "hal_types_private.h" +#include "val_api_private.h" +#include "val_log.h" +#include "drv_api.h" + +#include +#include +#include + +#if IS_ENABLED(CONFIG_COMPAT) +#include +#include +#endif + +#define VDO_HW_WRITE(ptr, data) mt_reg_sync_writel(data, ptr) +#define VDO_HW_READ(ptr) (*((volatile unsigned int * const)(ptr))) + +#define VCODEC_DEVNAME "Vcodec" +#define VCODEC_DEV_MAJOR_NUMBER 160 /* 189 */ +/* #define VENC_USE_L2C */ + +static dev_t vcodec_devno = MKDEV(VCODEC_DEV_MAJOR_NUMBER, 0); +static struct cdev *vcodec_cdev; +static struct class *vcodec_class; +static struct device *vcodec_device; + +#ifndef CONFIG_MTK_CLKMGR +static struct clk *clk_MT_CG_DISP0_SMI_COMMON; /* MM_DISP0_SMI_COMMON */ +static struct clk *clk_MT_CG_VDEC0_VDEC; /* VDEC0_VDEC */ +static struct clk *clk_MT_CG_VDEC1_LARB; /* VDEC1_LARB */ + +static struct clk *clk_MT_CG_VENC_VENC; /* VENC_VENC */ +static struct clk *clk_MT_CG_VENC_LARB; /* VENC_LARB */ + +static struct clk *clk_MT_SCP_SYS_VDE; /* SCP_SYS_VDE */ +static struct clk *clk_MT_SCP_SYS_VEN; /* SCP_SYS_VEN */ +static struct clk *clk_MT_SCP_SYS_DIS; /* SCP_SYS_DIS */ +#endif + +static DEFINE_MUTEX(IsOpenedLock); +static DEFINE_MUTEX(PWRLock); +static DEFINE_MUTEX(VdecHWLock); +static DEFINE_MUTEX(VencHWLock); +static DEFINE_MUTEX(EncEMILock); +static DEFINE_MUTEX(L2CLock); +static DEFINE_MUTEX(DecEMILock); +static DEFINE_MUTEX(DriverOpenCountLock); +static DEFINE_MUTEX(DecHWLockEventTimeoutLock); +static DEFINE_MUTEX(EncHWLockEventTimeoutLock); + +static DEFINE_MUTEX(VdecPWRLock); +static DEFINE_MUTEX(VencPWRLock); +static DEFINE_MUTEX(LogCountLock); + +static DEFINE_SPINLOCK(DecIsrLock); +static DEFINE_SPINLOCK(EncIsrLock); +static DEFINE_SPINLOCK(LockDecHWCountLock); +static DEFINE_SPINLOCK(LockEncHWCountLock); +static DEFINE_SPINLOCK(DecISRCountLock); +static DEFINE_SPINLOCK(EncISRCountLock); + + +static VAL_EVENT_T DecHWLockEvent; /* mutex : HWLockEventTimeoutLock */ +static VAL_EVENT_T EncHWLockEvent; /* mutex : HWLockEventTimeoutLock */ +static VAL_EVENT_T DecIsrEvent; /* mutex : HWLockEventTimeoutLock */ +static VAL_EVENT_T EncIsrEvent; /* mutex : HWLockEventTimeoutLock */ +static VAL_INT32_T Driver_Open_Count; /* mutex : DriverOpenCountLock */ +static VAL_UINT32_T gu4PWRCounter; /* mutex : PWRLock */ +static VAL_UINT32_T gu4EncEMICounter; /* mutex : EncEMILock */ +static VAL_UINT32_T gu4DecEMICounter; /* mutex : DecEMILock */ +static VAL_UINT32_T gu4L2CCounter; /* mutex : L2CLock */ +static VAL_BOOL_T bIsOpened = VAL_FALSE; /* mutex : IsOpenedLock */ +static VAL_UINT32_T gu4HwVencIrqStatus; /* hardware VENC IRQ status (VP8/H264) */ + +static VAL_UINT32_T gu4VdecPWRCounter; /* mutex : VdecPWRLock */ +static VAL_UINT32_T gu4VencPWRCounter; /* mutex : VencPWRLock */ + +static VAL_UINT32_T gu4LogCountUser; /* mutex : LogCountLock */ +static VAL_UINT32_T gu4LogCount; + +static VAL_UINT32_T gLockTimeOutCount; + +static VAL_UINT32_T gu4VdecLockThreadId; + +/* #define VCODEC_DEBUG */ +#ifdef VCODEC_DEBUG +#undef VCODEC_DEBUG +#define VCODEC_DEBUG MODULE_MFV_LOGE +#undef MODULE_MFV_LOGD +#define MODULE_MFV_LOGD MODULE_MFV_LOGE +#else +#define VCODEC_DEBUG(...) +#undef MODULE_MFV_LOGD +#define MODULE_MFV_LOGD(...) +#endif + +/* VENC physical base address */ +#undef VENC_BASE +#define VENC_BASE 0x17002000 +#define VENC_REGION 0x1000 + +/* VDEC virtual base address */ +#define VDEC_BASE_PHY 0x16000000 +#define VDEC_REGION 0x29000 + +#define HW_BASE 0x7FFF000 +#define HW_REGION 0x2000 + +#define INFO_BASE 0x10000000 +#define INFO_REGION 0x1000 + +#if 0 +#define VENC_IRQ_STATUS_addr (VENC_BASE + 0x05C) +#define VENC_IRQ_ACK_addr (VENC_BASE + 0x060) +#define VENC_MP4_IRQ_ACK_addr (VENC_BASE + 0x678) +#define VENC_MP4_IRQ_STATUS_addr (VENC_BASE + 0x67C) +#define VENC_ZERO_COEF_COUNT_addr (VENC_BASE + 0x688) +#define VENC_BYTE_COUNT_addr (VENC_BASE + 0x680) +#define VENC_MP4_IRQ_ENABLE_addr (VENC_BASE + 0x668) + +#define VENC_MP4_STATUS_addr (VENC_BASE + 0x664) +#define VENC_MP4_MVQP_STATUS_addr (VENC_BASE + 0x6E4) +#endif + + +#define VENC_IRQ_STATUS_SPS 0x1 +#define VENC_IRQ_STATUS_PPS 0x2 +#define VENC_IRQ_STATUS_FRM 0x4 +#define VENC_IRQ_STATUS_DRAM 0x8 +#define VENC_IRQ_STATUS_PAUSE 0x10 +#define VENC_IRQ_STATUS_SWITCH 0x20 + +#if 0 +/* VDEC virtual base address */ +#define VDEC_MISC_BASE (VDEC_BASE + 0x0000) +#define VDEC_VLD_BASE (VDEC_BASE + 0x1000) +#endif + + +VAL_ULONG_T KVA_VENC_IRQ_ACK_ADDR, KVA_VENC_IRQ_STATUS_ADDR, KVA_VENC_BASE; +VAL_ULONG_T KVA_VDEC_MISC_BASE, KVA_VDEC_VLD_BASE, KVA_VDEC_BASE, KVA_VDEC_GCON_BASE; +VAL_UINT32_T VENC_IRQ_ID, VDEC_IRQ_ID; + +extern void __attribute__((weak)) met_mmsys_tag(const char *tag, unsigned int value); + +/* #define KS_POWER_WORKAROUND */ + +/* extern unsigned long pmem_user_v2p_video(unsigned long va); */ + +#if defined(VENC_USE_L2C) +/* extern int config_L2(int option); */ +#endif + +void *mt_venc_base_get(void) +{ + return (void *)KVA_VENC_BASE; +} +EXPORT_SYMBOL(mt_venc_base_get); + +void *mt_vdec_base_get(void) +{ + return (void *)KVA_VDEC_BASE; +} +EXPORT_SYMBOL(mt_vdec_base_get); + +void vdec_power_on(void) +{ + int ret = 0; + + mutex_lock(&VdecPWRLock); + gu4VdecPWRCounter++; + mutex_unlock(&VdecPWRLock); + ret = 0; + +#ifdef CONFIG_MTK_CLKMGR + /* Central power on */ + enable_clock(MT_CG_DISP0_SMI_COMMON, "VDEC"); + enable_clock(MT_CG_VDEC0_VDEC, "VDEC"); + enable_clock(MT_CG_VDEC1_LARB, "VDEC"); +#ifdef VDEC_USE_L2C + /* enable_clock(MT_CG_INFRA_L2C_SRAM, "VDEC"); */ +#endif +#else + ret = clk_prepare_enable(clk_MT_SCP_SYS_DIS); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][vdec_power_on] clk_MT_SCP_SYS_DIS is not enabled, ret = %d\n", ret); + } + + ret = clk_prepare_enable(clk_MT_CG_DISP0_SMI_COMMON); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][vdec_power_on] clk_MT_CG_DISP0_SMI_COMMON is not enabled, ret = %d\n", + ret); + } + + ret = clk_prepare_enable(clk_MT_SCP_SYS_VDE); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][vdec_power_on] clk_MT_SCP_SYS_VDE is not enabled, ret = %d\n", ret); + } + + ret = clk_prepare_enable(clk_MT_CG_VDEC0_VDEC); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][vdec_power_on] clk_MT_CG_VDEC0_VDEC is not enabled, ret = %d\n", ret); + } + + ret = clk_prepare_enable(clk_MT_CG_VDEC1_LARB); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][vdec_power_on] clk_MT_CG_VDEC1_LARB is not enabled, ret = %d\n", ret); + } +#endif +} + +void vdec_power_off(void) +{ + mutex_lock(&VdecPWRLock); + if (gu4VdecPWRCounter == 0) { + MODULE_MFV_LOGD("[VCODEC] gu4VdecPWRCounter = 0\n"); + } else { + gu4VdecPWRCounter--; +#ifdef CONFIG_MTK_CLKMGR + /* Central power off */ + disable_clock(MT_CG_VDEC0_VDEC, "VDEC"); + disable_clock(MT_CG_VDEC1_LARB, "VDEC"); + disable_clock(MT_CG_DISP0_SMI_COMMON, "VDEC"); +#ifdef VDEC_USE_L2C + /* disable_clock(MT_CG_INFRA_L2C_SRAM, "VDEC"); */ +#endif +#else + clk_disable_unprepare(clk_MT_CG_VDEC1_LARB); + clk_disable_unprepare(clk_MT_CG_VDEC0_VDEC); + clk_disable_unprepare(clk_MT_SCP_SYS_VDE); + clk_disable_unprepare(clk_MT_CG_DISP0_SMI_COMMON); + clk_disable_unprepare(clk_MT_SCP_SYS_DIS); +#endif + } + mutex_unlock(&VdecPWRLock); +} + +void venc_power_on(void) +{ + int ret = 0; + + mutex_lock(&VencPWRLock); + gu4VencPWRCounter++; + mutex_unlock(&VencPWRLock); + ret = 0; + + MODULE_MFV_LOGD("[VCODEC] venc_power_on +\n"); +#ifdef CONFIG_MTK_CLKMGR + enable_clock(MT_CG_DISP0_SMI_COMMON, "VENC"); + enable_clock(MT_CG_VENC_VENC, "VENC"); + enable_clock(MT_CG_VENC_LARB , "VENC"); + +#ifdef VENC_USE_L2C + enable_clock(MT_CG_INFRA_L2C_SRAM, "VENC"); +#endif +#else + ret = clk_prepare_enable(clk_MT_SCP_SYS_DIS); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][venc_power_on] clk_MT_SCP_SYS_DIS is not enabled, ret = %d\n", ret); + } + + ret = clk_prepare_enable(clk_MT_CG_DISP0_SMI_COMMON); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][venc_power_on] clk_MT_CG_DISP0_SMI_COMMON is not enabled, ret = %d\n", + ret); + } + + ret = clk_prepare_enable(clk_MT_SCP_SYS_VEN); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][venc_power_on] clk_MT_SCP_SYS_VEN is not enabled, ret = %d\n", ret); + } + + ret = clk_prepare_enable(clk_MT_CG_VENC_VENC); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][venc_power_on] clk_MT_CG_VENC_VENC is not enabled, ret = %d\n", ret); + } + + ret = clk_prepare_enable(clk_MT_CG_VENC_LARB); + if (ret) { + /* print error log & error handling */ + MODULE_MFV_LOGE("[VCODEC][ERROR][venc_power_on] clk_MT_CG_VENC_LARB is not enabled, ret = %d\n", ret); + } +#endif + + MODULE_MFV_LOGD("[VCODEC] venc_power_on -\n"); +} + +void venc_power_off(void) +{ + mutex_lock(&VencPWRLock); + if (gu4VencPWRCounter == 0) { + MODULE_MFV_LOGD("[VCODEC] gu4VencPWRCounter = 0\n"); + } else { + gu4VencPWRCounter--; + MODULE_MFV_LOGD("[VCODEC] venc_power_off +\n"); +#ifdef CONFIG_MTK_CLKMGR + disable_clock(MT_CG_VENC_VENC, "VENC"); + disable_clock(MT_CG_VENC_LARB, "VENC"); + disable_clock(MT_CG_DISP0_SMI_COMMON, "VENC"); +#ifdef VENC_USE_L2C + disable_clock(MT_CG_INFRA_L2C_SRAM, "VENC"); +#endif +#else + clk_disable_unprepare(clk_MT_CG_VENC_LARB); + clk_disable_unprepare(clk_MT_CG_VENC_VENC); + clk_disable_unprepare(clk_MT_SCP_SYS_VEN); + clk_disable_unprepare(clk_MT_CG_DISP0_SMI_COMMON); + clk_disable_unprepare(clk_MT_SCP_SYS_DIS); +#endif + MODULE_MFV_LOGD("[VCODEC] venc_power_off -\n"); + } + mutex_unlock(&VencPWRLock); +} + +void dec_isr(void) +{ + VAL_RESULT_T eValRet; + VAL_ULONG_T ulFlags, ulFlagsISR, ulFlagsLockHW; + + VAL_UINT32_T u4TempDecISRCount = 0; + VAL_UINT32_T u4TempLockDecHWCount = 0; + VAL_UINT32_T u4CgStatus = 0; + VAL_UINT32_T u4DecDoneStatus = 0; + + u4CgStatus = VDO_HW_READ(KVA_VDEC_GCON_BASE); + if ((u4CgStatus & 0x10) != 0) { + MODULE_MFV_LOGE("[VCODEC][ERROR] DEC ISR, VDEC active is not 0x0 (0x%08x)", u4CgStatus); + return; + } + + u4DecDoneStatus = VDO_HW_READ(KVA_VDEC_BASE + 0xA4); + if ((u4DecDoneStatus & (0x1 << 16)) != 0x10000) { + MODULE_MFV_LOGE("[VCODEC][ERROR] DEC ISR, Decode done status is not 0x1 (0x%08x)", u4DecDoneStatus); + return; + } + + + spin_lock_irqsave(&DecISRCountLock, ulFlagsISR); + gu4DecISRCount++; + u4TempDecISRCount = gu4DecISRCount; + spin_unlock_irqrestore(&DecISRCountLock, ulFlagsISR); + + spin_lock_irqsave(&LockDecHWCountLock, ulFlagsLockHW); + u4TempLockDecHWCount = gu4LockDecHWCount; + spin_unlock_irqrestore(&LockDecHWCountLock, ulFlagsLockHW); + + if (u4TempDecISRCount != u4TempLockDecHWCount) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + /* MODULE_MFV_LOGE("[INFO] Dec ISRCount: 0x%x, LockHWCount:0x%x\n", + u4TempDecISRCount, u4TempLockDecHWCount); */ + } + + /* Clear interrupt */ + VDO_HW_WRITE(KVA_VDEC_MISC_BASE + 41 * 4, VDO_HW_READ(KVA_VDEC_MISC_BASE + 41 * 4) | 0x11); + VDO_HW_WRITE(KVA_VDEC_MISC_BASE + 41 * 4, VDO_HW_READ(KVA_VDEC_MISC_BASE + 41 * 4) & ~0x10); + + + spin_lock_irqsave(&DecIsrLock, ulFlags); + eValRet = eVideoSetEvent(&DecIsrEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] ISR set DecIsrEvent error\n"); + } + spin_unlock_irqrestore(&DecIsrLock, ulFlags); +} + + +void enc_isr(void) +{ + VAL_RESULT_T eValRet; + VAL_ULONG_T ulFlagsISR, ulFlagsLockHW; + + + VAL_UINT32_T u4TempEncISRCount = 0; + VAL_UINT32_T u4TempLockEncHWCount = 0; + /* ---------------------- */ + + spin_lock_irqsave(&EncISRCountLock, ulFlagsISR); + gu4EncISRCount++; + u4TempEncISRCount = gu4EncISRCount; + spin_unlock_irqrestore(&EncISRCountLock, ulFlagsISR); + + spin_lock_irqsave(&LockEncHWCountLock, ulFlagsLockHW); + u4TempLockEncHWCount = gu4LockEncHWCount; + spin_unlock_irqrestore(&LockEncHWCountLock, ulFlagsLockHW); + + if (u4TempEncISRCount != u4TempLockEncHWCount) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + /* MODULE_MFV_LOGE("[INFO] Enc ISRCount: 0x%x, LockHWCount:0x%x\n", + u4TempEncISRCount, u4TempLockEncHWCount); */ + } + + if (grVcodecEncHWLock.pvHandle == 0) { + MODULE_MFV_LOGE("[VCODEC][ERROR] NO one Lock Enc HW, please check!!\n"); + + /* Clear all status */ + /* VDO_HW_WRITE(KVA_VENC_MP4_IRQ_ACK_ADDR, 1); */ + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_PAUSE); + /* VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_DRAM_VP8); */ + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_SWITCH); + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_DRAM); + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_SPS); + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_PPS); + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_FRM); + return; + } + + if (grVcodecEncHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC) { /* hardwire */ + gu4HwVencIrqStatus = VDO_HW_READ(KVA_VENC_IRQ_STATUS_ADDR); + if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_PAUSE) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_PAUSE); + } + if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_SWITCH) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_SWITCH); + } + if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_DRAM) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_DRAM); + } + if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_SPS) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_SPS); + } + if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_PPS) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_PPS); + } + if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_FRM) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_FRM); + } + } else if (grVcodecEncHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_ENC) { /* hardwire */ + MODULE_MFV_LOGE("[VCODEC][enc_isr] VAL_DRIVER_TYPE_HEVC_ENC!!\n"); + } else { + MODULE_MFV_LOGE("[VCODEC][ERROR] Invalid lock holder driver type = %d\n", + grVcodecEncHWLock.eDriverType); + } + + eValRet = eVideoSetEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] ISR set EncIsrEvent error\n"); + } +} + +static irqreturn_t video_intr_dlr(int irq, void *dev_id) +{ + if (met_mmsys_tag) + met_mmsys_tag("VDEC", grVcodecDecHWLock.eDriverType | 0x100); + + dec_isr(); + return IRQ_HANDLED; +} + +static irqreturn_t video_intr_dlr2(int irq, void *dev_id) +{ + if (met_mmsys_tag) + met_mmsys_tag("VENC", grVcodecEncHWLock.eDriverType | 0x100); + + enc_isr(); + return IRQ_HANDLED; +} + +static long vcodec_alloc_non_cache_buffer(unsigned long arg) +{ + VAL_UINT8_T *user_data_addr; + VAL_MEMORY_T rTempMem; + VAL_LONG_T ret; + + MODULE_MFV_LOGE("VCODEC_ALLOC_NON_CACHE_BUFFER + tid = %d\n", current->pid); + + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rTempMem, user_data_addr, sizeof(VAL_MEMORY_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_ALLOC_NON_CACHE_BUFFER, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + + rTempMem.u4ReservedSize /*kernel va*/ = + (VAL_ULONG_T)dma_alloc_coherent(0, rTempMem.u4MemSize, (dma_addr_t *)&rTempMem.pvMemPa, GFP_KERNEL); + if ((0 == rTempMem.u4ReservedSize) || (0 == rTempMem.pvMemPa)) { + MODULE_MFV_LOGE("[ERROR] dma_alloc_coherent fail in VCODEC_ALLOC_NON_CACHE_BUFFER\n"); + return -EFAULT; + } + + MODULE_MFV_LOGD("[VCODEC] kernel va = 0x%lx, kernel pa = 0x%lx, memory size = %lu\n", + (VAL_ULONG_T)rTempMem.u4ReservedSize, + (VAL_ULONG_T)rTempMem.pvMemPa, + (VAL_ULONG_T)rTempMem.u4MemSize); + + /* mutex_lock(&NonCacheMemoryListLock); */ + /* Add_NonCacheMemoryList(rTempMem.u4ReservedSize, (VAL_UINT32_T)rTempMem.pvMemPa, + (VAL_UINT32_T)rTempMem.u4MemSize, 0, 0); */ + /* mutex_unlock(&NonCacheMemoryListLock); */ + + ret = copy_to_user(user_data_addr, &rTempMem, sizeof(VAL_MEMORY_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_ALLOC_NON_CACHE_BUFFER, copy_to_user failed: %lu\n", ret); + return -EFAULT; + } + + MODULE_MFV_LOGE("VCODEC_ALLOC_NON_CACHE_BUFFER - tid = %d\n", current->pid); + + return 0; +} + +static long vcodec_free_non_cache_buffer(unsigned long arg) +{ + VAL_UINT8_T *user_data_addr; + VAL_MEMORY_T rTempMem; + VAL_LONG_T ret; + + MODULE_MFV_LOGE("VCODEC_FREE_NON_CACHE_BUFFER + tid = %d\n", current->pid); + + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rTempMem, user_data_addr, sizeof(VAL_MEMORY_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_FREE_NON_CACHE_BUFFER, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + + dma_free_coherent(0, rTempMem.u4MemSize, (void *)rTempMem.u4ReservedSize, + (dma_addr_t)(VAL_ULONG_T)rTempMem.pvMemPa); + + /* mutex_lock(&NonCacheMemoryListLock); */ + /* Free_NonCacheMemoryList(rTempMem.u4ReservedSize, (VAL_UINT32_T)rTempMem.pvMemPa); */ + /* mutex_unlock(&NonCacheMemoryListLock); */ + + rTempMem.u4ReservedSize = 0; + rTempMem.pvMemPa = NULL; + + ret = copy_to_user(user_data_addr, &rTempMem, sizeof(VAL_MEMORY_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_FREE_NON_CACHE_BUFFER, copy_to_user failed: %lu\n", ret); + return -EFAULT; + } + + MODULE_MFV_LOGE("VCODEC_FREE_NON_CACHE_BUFFER - tid = %d\n", current->pid); + + return 0; +} + +static long vcodec_lockhw_dec_fail(VAL_HW_LOCK_T rHWLock, VAL_UINT32_T FirstUseDecHW) +{ + MODULE_MFV_LOGE("[ERROR] VCODEC_LOCKHW, DecHWLockEvent TimeOut, CurrentTID = %d\n", current->pid); + if (FirstUseDecHW != 1) { + mutex_lock(&VdecHWLock); + if (grVcodecDecHWLock.pvHandle == 0) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW, maybe mediaserver restart before, please check!!\n"); + } else { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW, someone use HW, and check timeout value!!\n"); + } + mutex_unlock(&VdecHWLock); + } + + return 0; +} + +static long vcodec_lockhw_enc_fail(VAL_HW_LOCK_T rHWLock, VAL_UINT32_T FirstUseEncHW) +{ + MODULE_MFV_LOGE("[ERROR] VCODEC_LOCKHW EncHWLockEvent TimeOut, CurrentTID = %d\n", current->pid); + + if (FirstUseEncHW != 1) { + mutex_lock(&VencHWLock); + if (grVcodecEncHWLock.pvHandle == 0) { + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW, maybe mediaserver restart before, please check!!\n"); + } else { + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW, someone use HW, and check timeout value!! %d\n", + gLockTimeOutCount); + ++gLockTimeOutCount; + if (gLockTimeOutCount > 30) { + MODULE_MFV_LOGE("[ERROR] VCODEC_LOCKHW - ID %d fail\n", current->pid); + MODULE_MFV_LOGE("someone locked HW time out more than 30 times 0x%lx,%lx,0x%lx,type:%d\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, + pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle), + (VAL_ULONG_T)rHWLock.pvHandle, + rHWLock.eDriverType); + gLockTimeOutCount = 0; + mutex_unlock(&VencHWLock); + return -EFAULT; + } + + if (rHWLock.u4TimeoutMs == 0) { + MODULE_MFV_LOGE("[ERROR] VCODEC_LOCKHW - ID %d fail\n", current->pid); + MODULE_MFV_LOGE("someone locked HW already 0x%lx,%lx,0x%lx,type:%d\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, + pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle), + (VAL_ULONG_T)rHWLock.pvHandle, + rHWLock.eDriverType); + gLockTimeOutCount = 0; + mutex_unlock(&VencHWLock); + return -EFAULT; + } + } + mutex_unlock(&VencHWLock); + } + + return 0; +} + +static long vcodec_lockhw(unsigned long arg) +{ + VAL_UINT8_T *user_data_addr; + VAL_HW_LOCK_T rHWLock; + VAL_RESULT_T eValRet; + VAL_LONG_T ret; + VAL_BOOL_T bLockedHW = VAL_FALSE; + VAL_UINT32_T FirstUseDecHW = 0; + VAL_UINT32_T FirstUseEncHW = 0; + VAL_TIME_T rCurTime; + VAL_UINT32_T u4TimeInterval; + VAL_ULONG_T ulFlagsLockHW; + + MODULE_MFV_LOGD("VCODEC_LOCKHW + tid = %d\n", current->pid); + + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rHWLock, user_data_addr, sizeof(VAL_HW_LOCK_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_LOCKHW, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + + MODULE_MFV_LOGD("[VCODEC] LOCKHW eDriverType = %d\n", rHWLock.eDriverType); + eValRet = VAL_RESULT_INVALID_ISR; + if (rHWLock.eDriverType == VAL_DRIVER_TYPE_MP4_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_MP1_MP2_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_VC1_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_VC1_ADV_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_VP8_DEC) { + while (bLockedHW == VAL_FALSE) { + mutex_lock(&DecHWLockEventTimeoutLock); + if (DecHWLockEvent.u4TimeoutMs == 1) { + MODULE_MFV_LOGE("VCODEC_LOCKHW, First Use Dec HW!!\n"); + FirstUseDecHW = 1; + } else { + FirstUseDecHW = 0; + } + mutex_unlock(&DecHWLockEventTimeoutLock); + + if (FirstUseDecHW == 1) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + eValRet = eVideoWaitEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); + } + mutex_lock(&DecHWLockEventTimeoutLock); + if (DecHWLockEvent.u4TimeoutMs != 1000) { + DecHWLockEvent.u4TimeoutMs = 1000; + FirstUseDecHW = 1; + } else { + FirstUseDecHW = 0; + } + mutex_unlock(&DecHWLockEventTimeoutLock); + + mutex_lock(&VdecHWLock); + /* one process try to lock twice */ + if (grVcodecDecHWLock.pvHandle == + (VAL_VOID_T *)pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle)) { + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW, one decoder instance try to lock twice\n"); + MODULE_MFV_LOGE("may cause lock HW timeout!! instance = 0x%lx, CurrentTID = %d\n", + (VAL_ULONG_T)grVcodecDecHWLock.pvHandle, current->pid); + } + mutex_unlock(&VdecHWLock); + + if (FirstUseDecHW == 0) { + MODULE_MFV_LOGD("VCODEC_LOCKHW, Not first time use HW, timeout = %d\n", + DecHWLockEvent.u4TimeoutMs); + eValRet = eVideoWaitEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); + } + + if (VAL_RESULT_INVALID_ISR == eValRet) { + ret = vcodec_lockhw_dec_fail(rHWLock, FirstUseDecHW); + if (ret) { + MODULE_MFV_LOGE("[ERROR] vcodec_lockhw_dec_fail failed: %lu\n", ret); + return -EFAULT; + } + } else if (VAL_RESULT_RESTARTSYS == eValRet) { + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW, VAL_RESULT_RESTARTSYS return when HWLock!!\n"); + return -ERESTARTSYS; + } + + mutex_lock(&VdecHWLock); + if (grVcodecDecHWLock.pvHandle == 0) { /* No one holds dec hw lock now */ + gu4VdecLockThreadId = current->pid; + grVcodecDecHWLock.pvHandle = + (VAL_VOID_T *)pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle); + grVcodecDecHWLock.eDriverType = rHWLock.eDriverType; + eVideoGetTimeOfDay(&grVcodecDecHWLock.rLockedTime, sizeof(VAL_TIME_T)); + + MODULE_MFV_LOGD("VCODEC_LOCKHW, No process use dec HW, so current process can use HW\n"); + MODULE_MFV_LOGD("LockInstance = 0x%lx CurrentTID = %d, rLockedTime(s, us) = %d, %d\n", + (VAL_ULONG_T)grVcodecDecHWLock.pvHandle, + current->pid, + grVcodecDecHWLock.rLockedTime.u4Sec, grVcodecDecHWLock.rLockedTime.u4uSec); + + bLockedHW = VAL_TRUE; + if (VAL_RESULT_INVALID_ISR == eValRet && FirstUseDecHW != 1) { + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW, reset power/irq when HWLock!!\n"); +#ifndef KS_POWER_WORKAROUND + vdec_power_off(); +#endif + disable_irq(VDEC_IRQ_ID); + } +#ifndef KS_POWER_WORKAROUND + vdec_power_on(); +#endif + if (rHWLock.bSecureInst == VAL_FALSE) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + enable_irq(VDEC_IRQ_ID); + } + } else { /* Another one holding dec hw now */ + MODULE_MFV_LOGE("VCODEC_LOCKHW E\n"); + eVideoGetTimeOfDay(&rCurTime, sizeof(VAL_TIME_T)); + u4TimeInterval = (((((rCurTime.u4Sec - grVcodecDecHWLock.rLockedTime.u4Sec) * 1000000) + + rCurTime.u4uSec) - grVcodecDecHWLock.rLockedTime.u4uSec) / 1000); + + MODULE_MFV_LOGD("VCODEC_LOCKHW, someone use dec HW, and check timeout value\n"); + MODULE_MFV_LOGD("TimeInterval(ms) = %d, TimeOutValue(ms)) = %d\n", + u4TimeInterval, rHWLock.u4TimeoutMs); + MODULE_MFV_LOGD("Lock Instance = 0x%lx, Lock TID = %d, CurrentTID = %d\n", + (VAL_ULONG_T)grVcodecDecHWLock.pvHandle, + gu4VdecLockThreadId, + current->pid); + MODULE_MFV_LOGD("rLockedTime(%d s, %d us), rCurTime(%d s, %d us)\n", + grVcodecDecHWLock.rLockedTime.u4Sec, grVcodecDecHWLock.rLockedTime.u4uSec, + rCurTime.u4Sec, rCurTime.u4uSec); + + /* 2012/12/16. Cheng-Jung Never steal hardware lock */ + } + mutex_unlock(&VdecHWLock); + spin_lock_irqsave(&LockDecHWCountLock, ulFlagsLockHW); + gu4LockDecHWCount++; + spin_unlock_irqrestore(&LockDecHWCountLock, ulFlagsLockHW); + } + } else if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_ENC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_JPEG_ENC) { + while (bLockedHW == VAL_FALSE) { + /* Early break for JPEG VENC */ + if (rHWLock.u4TimeoutMs == 0) { + if (grVcodecEncHWLock.pvHandle != 0) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + break; + } + } + + /* Wait to acquire Enc HW lock */ + mutex_lock(&EncHWLockEventTimeoutLock); + if (EncHWLockEvent.u4TimeoutMs == 1) { + MODULE_MFV_LOGE("VCODEC_LOCKHW, First Use Enc HW %d!!\n", rHWLock.eDriverType); + FirstUseEncHW = 1; + } else { + FirstUseEncHW = 0; + } + mutex_unlock(&EncHWLockEventTimeoutLock); + if (FirstUseEncHW == 1) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + eValRet = eVideoWaitEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); + } + + mutex_lock(&EncHWLockEventTimeoutLock); + if (EncHWLockEvent.u4TimeoutMs == 1) { + EncHWLockEvent.u4TimeoutMs = 1000; + FirstUseEncHW = 1; + } else { + FirstUseEncHW = 0; + if (rHWLock.u4TimeoutMs == 0) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + EncHWLockEvent.u4TimeoutMs = 0; /* No wait */ + } else { + EncHWLockEvent.u4TimeoutMs = 1000; /* Wait indefinitely */ + } + } + mutex_unlock(&EncHWLockEventTimeoutLock); + + mutex_lock(&VencHWLock); + /* one process try to lock twice */ + if (grVcodecEncHWLock.pvHandle == + (VAL_VOID_T *)pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle)) { + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW, one encoder instance try to lock twice\n"); + MODULE_MFV_LOGE("may cause lock HW timeout!! instance=0x%lx, CurrentTID=%d, type:%d\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, current->pid, rHWLock.eDriverType); + } + mutex_unlock(&VencHWLock); + + if (FirstUseEncHW == 0) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + eValRet = eVideoWaitEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); + } + + if (VAL_RESULT_INVALID_ISR == eValRet) { + ret = vcodec_lockhw_enc_fail(rHWLock, FirstUseEncHW); + if (ret) { + MODULE_MFV_LOGE("[ERROR] vcodec_lockhw_enc_fail failed: %lu\n", ret); + return -EFAULT; + } + } else if (VAL_RESULT_RESTARTSYS == eValRet) { + return -ERESTARTSYS; + } + + mutex_lock(&VencHWLock); + if (grVcodecEncHWLock.pvHandle == 0) { /* No process use HW, so current process can use HW */ + if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_ENC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_JPEG_ENC) { + grVcodecEncHWLock.pvHandle = + (VAL_VOID_T *)pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle); + grVcodecEncHWLock.eDriverType = rHWLock.eDriverType; + eVideoGetTimeOfDay(&grVcodecEncHWLock.rLockedTime, sizeof(VAL_TIME_T)); + + MODULE_MFV_LOGD("VCODEC_LOCKHW, No process use HW, so current process can use HW\n"); + MODULE_MFV_LOGD("VCODEC_LOCKHW, handle = 0x%lx\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle); + MODULE_MFV_LOGD("LockInstance = 0x%lx CurrentTID = %d, rLockedTime(s, us) = %d, %d\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, + current->pid, + grVcodecEncHWLock.rLockedTime.u4Sec, + grVcodecEncHWLock.rLockedTime.u4uSec); + + bLockedHW = VAL_TRUE; + if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_ENC) { +#ifndef KS_POWER_WORKAROUND + venc_power_on(); +#endif + enable_irq(VENC_IRQ_ID); + } + } + } else { /* someone use HW, and check timeout value */ + if (rHWLock.u4TimeoutMs == 0) { + bLockedHW = VAL_FALSE; + mutex_unlock(&VencHWLock); + break; + } + + eVideoGetTimeOfDay(&rCurTime, sizeof(VAL_TIME_T)); + u4TimeInterval = (((((rCurTime.u4Sec - grVcodecEncHWLock.rLockedTime.u4Sec) * 1000000) + + rCurTime.u4uSec) - grVcodecEncHWLock.rLockedTime.u4uSec) / 1000); + + MODULE_MFV_LOGD("VCODEC_LOCKHW, someone use enc HW, and check timeout value\n"); + MODULE_MFV_LOGD("TimeInterval(ms) = %d, TimeOutValue(ms) = %d\n", + u4TimeInterval, rHWLock.u4TimeoutMs); + MODULE_MFV_LOGD("rLockedTime(s, us) = %d, %d, rCurTime(s, us) = %d, %d\n", + grVcodecEncHWLock.rLockedTime.u4Sec, grVcodecEncHWLock.rLockedTime.u4uSec, + rCurTime.u4Sec, rCurTime.u4uSec); + MODULE_MFV_LOGD("LockInstance = 0x%lx, CurrentInstance = 0x%lx, CurrentTID = %d\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, + pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle), + current->pid); + + ++gLockTimeOutCount; + if (gLockTimeOutCount > 30) { + MODULE_MFV_LOGE("[ERROR] VCODEC_LOCKHW %d fail,someone locked HW over 30 times\n", + current->pid); + MODULE_MFV_LOGE("without timeout 0x%lx,%lx,0x%lx,type:%d\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, + pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle), + (VAL_ULONG_T)rHWLock.pvHandle, + rHWLock.eDriverType); + gLockTimeOutCount = 0; + mutex_unlock(&VencHWLock); + return -EFAULT; + } + + /* 2013/04/10. Cheng-Jung Never steal hardware lock */ + } + + if (VAL_TRUE == bLockedHW) { + MODULE_MFV_LOGD("VCODEC_LOCKHW, Lock ok grVcodecEncHWLock.pvHandle = 0x%lx, va:%lx, type:%d\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, + (VAL_ULONG_T)rHWLock.pvHandle, + rHWLock.eDriverType); + gLockTimeOutCount = 0; + } + mutex_unlock(&VencHWLock); + } + + if (VAL_FALSE == bLockedHW) { + MODULE_MFV_LOGE("[ERROR] VCODEC_LOCKHW %d fail,someone locked HW already,0x%lx,%lx,0x%lx,type:%d\n", + current->pid, + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, + pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle), + (VAL_ULONG_T)rHWLock.pvHandle, + rHWLock.eDriverType); + gLockTimeOutCount = 0; + return -EFAULT; + } + + spin_lock_irqsave(&LockEncHWCountLock, ulFlagsLockHW); + gu4LockEncHWCount++; + spin_unlock_irqrestore(&LockEncHWCountLock, ulFlagsLockHW); + + MODULE_MFV_LOGD("VCODEC_LOCKHW, get locked - ObjId =%d\n", current->pid); + + MODULE_MFV_LOGD("VCODEC_LOCKHWed - tid = %d\n", current->pid); + } else { + MODULE_MFV_LOGE("[WARNING] VCODEC_LOCKHW Unknown instance\n"); + return -EFAULT; + } + + MODULE_MFV_LOGD("VCODEC_LOCKHW - tid = %d\n", current->pid); + + return 0; +} + +static long vcodec_unlockhw(unsigned long arg) +{ + VAL_UINT8_T *user_data_addr; + VAL_HW_LOCK_T rHWLock; + VAL_RESULT_T eValRet; + VAL_LONG_T ret; + + MODULE_MFV_LOGD("VCODEC_UNLOCKHW + tid = %d\n", current->pid); + + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rHWLock, user_data_addr, sizeof(VAL_HW_LOCK_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_UNLOCKHW, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + + MODULE_MFV_LOGD("VCODEC_UNLOCKHW eDriverType = %d\n", rHWLock.eDriverType); + eValRet = VAL_RESULT_INVALID_ISR; + if (rHWLock.eDriverType == VAL_DRIVER_TYPE_MP4_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_MP1_MP2_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_VC1_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_VC1_ADV_DEC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_VP8_DEC) { + mutex_lock(&VdecHWLock); + /* Current owner give up hw lock */ + if (grVcodecDecHWLock.pvHandle == (VAL_VOID_T *)pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle)) { + grVcodecDecHWLock.pvHandle = 0; + grVcodecDecHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; + if (rHWLock.bSecureInst == VAL_FALSE) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + disable_irq(VDEC_IRQ_ID); + } + /* TODO: check if turning power off is ok */ +#ifndef KS_POWER_WORKAROUND + vdec_power_off(); +#endif + } else { /* Not current owner */ + MODULE_MFV_LOGE("[ERROR] VCODEC_UNLOCKHW\n"); + MODULE_MFV_LOGE("Not owner trying to unlock dec hardware 0x%lx\n", + pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle)); + mutex_unlock(&VdecHWLock); + return -EFAULT; + } + mutex_unlock(&VdecHWLock); + eValRet = eVideoSetEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); + } else if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_ENC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_JPEG_ENC) { + mutex_lock(&VencHWLock); + /* Current owner give up hw lock */ + if (grVcodecEncHWLock.pvHandle == (VAL_VOID_T *)pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle)) { + grVcodecEncHWLock.pvHandle = 0; + grVcodecEncHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; + if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || + rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_ENC) { + disable_irq(VENC_IRQ_ID); + /* turn venc power off */ +#ifndef KS_POWER_WORKAROUND + venc_power_off(); +#endif + } + } else { /* Not current owner */ + /* [TODO] error handling */ + MODULE_MFV_LOGE("[ERROR] VCODEC_UNLOCKHW\n"); + MODULE_MFV_LOGE("Not owner trying to unlock enc hardware 0x%lx, pa:%lx, va:%lx type:%d\n", + (VAL_ULONG_T)grVcodecEncHWLock.pvHandle, + pmem_user_v2p_video((VAL_ULONG_T)rHWLock.pvHandle), + (VAL_ULONG_T)rHWLock.pvHandle, + rHWLock.eDriverType); + mutex_unlock(&VencHWLock); + return -EFAULT; + } + mutex_unlock(&VencHWLock); + eValRet = eVideoSetEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); + } else { + MODULE_MFV_LOGE("[WARNING] VCODEC_UNLOCKHW Unknown instance\n"); + return -EFAULT; + } + + MODULE_MFV_LOGD("VCODEC_UNLOCKHW - tid = %d\n", current->pid); + + return 0; +} + +static long vcodec_waitisr(unsigned long arg) +{ + VAL_UINT8_T *user_data_addr; + VAL_ISR_T val_isr; + VAL_BOOL_T bLockedHW = VAL_FALSE; + VAL_ULONG_T ulFlags; + VAL_LONG_T ret; + VAL_RESULT_T eValRet; + + MODULE_MFV_LOGD("VCODEC_WAITISR + tid = %d\n", current->pid); + + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&val_isr, user_data_addr, sizeof(VAL_ISR_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_WAITISR, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + + if (val_isr.eDriverType == VAL_DRIVER_TYPE_MP4_DEC || + val_isr.eDriverType == VAL_DRIVER_TYPE_HEVC_DEC || + val_isr.eDriverType == VAL_DRIVER_TYPE_H264_DEC || + val_isr.eDriverType == VAL_DRIVER_TYPE_MP1_MP2_DEC || + val_isr.eDriverType == VAL_DRIVER_TYPE_VC1_DEC || + val_isr.eDriverType == VAL_DRIVER_TYPE_VC1_ADV_DEC || + val_isr.eDriverType == VAL_DRIVER_TYPE_VP8_DEC) { + mutex_lock(&VdecHWLock); + if (grVcodecDecHWLock.pvHandle == (VAL_VOID_T *)pmem_user_v2p_video((VAL_ULONG_T)val_isr.pvHandle)) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + bLockedHW = VAL_TRUE; + } else { + } + mutex_unlock(&VdecHWLock); + + if (bLockedHW == VAL_FALSE) { + MODULE_MFV_LOGE("[ERROR] VCODEC_WAITISR, DO NOT have HWLock, so return fail\n"); + return -EFAULT; + } + + spin_lock_irqsave(&DecIsrLock, ulFlags); + DecIsrEvent.u4TimeoutMs = val_isr.u4TimeoutMs; + spin_unlock_irqrestore(&DecIsrLock, ulFlags); + + eValRet = eVideoWaitEvent(&DecIsrEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_INVALID_ISR == eValRet) { + return -2; + } else if (VAL_RESULT_RESTARTSYS == eValRet) { + MODULE_MFV_LOGE("[WARNING] VCODEC_WAITISR, VAL_RESULT_RESTARTSYS return when WAITISR!!\n"); + return -ERESTARTSYS; + } + } else if (val_isr.eDriverType == VAL_DRIVER_TYPE_H264_ENC || + val_isr.eDriverType == VAL_DRIVER_TYPE_HEVC_ENC) { + mutex_lock(&VencHWLock); + if (grVcodecEncHWLock.pvHandle == (VAL_VOID_T *)pmem_user_v2p_video((VAL_ULONG_T)val_isr.pvHandle)) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + bLockedHW = VAL_TRUE; + } else { + } + mutex_unlock(&VencHWLock); + + if (bLockedHW == VAL_FALSE) { + MODULE_MFV_LOGE("[ERROR] VCODEC_WAITISR, DO NOT have enc HWLock, so return fail pa:%lx, va:%lx\n", + pmem_user_v2p_video((VAL_ULONG_T)val_isr.pvHandle), + (VAL_ULONG_T)val_isr.pvHandle); + return -EFAULT; + } + + spin_lock_irqsave(&EncIsrLock, ulFlags); + EncIsrEvent.u4TimeoutMs = val_isr.u4TimeoutMs; + spin_unlock_irqrestore(&EncIsrLock, ulFlags); + + eValRet = eVideoWaitEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_INVALID_ISR == eValRet) { + return -2; + } else if (VAL_RESULT_RESTARTSYS == eValRet) { + MODULE_MFV_LOGE("[WARNING] VCODEC_WAITISR, VAL_RESULT_RESTARTSYS return when WAITISR!!\n"); + return -ERESTARTSYS; + } + + if (val_isr.u4IrqStatusNum > 0) { + val_isr.u4IrqStatus[0] = gu4HwVencIrqStatus; + ret = copy_to_user(user_data_addr, &val_isr, sizeof(VAL_ISR_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_WAITISR, copy_to_user failed: %lu\n", ret); + return -EFAULT; + } + } + } else { + MODULE_MFV_LOGE("[WARNING] VCODEC_WAITISR Unknown instance\n"); + return -EFAULT; + } + + MODULE_MFV_LOGD("VCODEC_WAITISR - tid = %d\n", current->pid); + + return 0; +} + +static long vcodec_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + VAL_LONG_T ret; + VAL_UINT8_T *user_data_addr; + VAL_VCODEC_CORE_LOADING_T rTempCoreLoading; + VAL_VCODEC_CPU_OPP_LIMIT_T rCpuOppLimit; + VAL_INT32_T temp_nr_cpu_ids; + VAL_POWER_T rPowerParam; + VAL_BOOL_T rIncLogCount; + +#if 0 + VCODEC_DRV_CMD_QUEUE_T rDrvCmdQueue; + P_VCODEC_DRV_CMD_T cmd_queue = VAL_NULL; + VAL_UINT32_T u4Size, uValue, nCount; +#endif + + switch (cmd) { + case VCODEC_SET_THREAD_ID: + { + /* MODULE_MFV_LOGE("VCODEC_SET_THREAD_ID [EMPTY] + tid = %d\n", current->pid); */ + /* MODULE_MFV_LOGE("VCODEC_SET_THREAD_ID [EMPTY] - tid = %d\n", current->pid); */ + } + break; + + case VCODEC_ALLOC_NON_CACHE_BUFFER: + { + ret = vcodec_alloc_non_cache_buffer(arg); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_ALLOC_NON_CACHE_BUFFER failed! %lu\n", ret); + return ret; + } + } + break; + + case VCODEC_FREE_NON_CACHE_BUFFER: + { + ret = vcodec_free_non_cache_buffer(arg); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_FREE_NON_CACHE_BUFFER failed! %lu\n", ret); + return ret; + } + } + break; + + case VCODEC_INC_DEC_EMI_USER: + { + MODULE_MFV_LOGD("VCODEC_INC_DEC_EMI_USER + tid = %d\n", current->pid); + + mutex_lock(&DecEMILock); + gu4DecEMICounter++; + MODULE_MFV_LOGD("[VCODEC] DEC_EMI_USER = %d\n", gu4DecEMICounter); + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_to_user(user_data_addr, &gu4DecEMICounter, sizeof(VAL_UINT32_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_INC_DEC_EMI_USER, copy_to_user failed: %lu\n", ret); + mutex_unlock(&DecEMILock); + return -EFAULT; + } + mutex_unlock(&DecEMILock); + + MODULE_MFV_LOGD("VCODEC_INC_DEC_EMI_USER - tid = %d\n", current->pid); + } + break; + + case VCODEC_DEC_DEC_EMI_USER: + { + MODULE_MFV_LOGD("VCODEC_DEC_DEC_EMI_USER + tid = %d\n", current->pid); + + mutex_lock(&DecEMILock); + gu4DecEMICounter--; + MODULE_MFV_LOGD("[VCODEC] DEC_EMI_USER = %d\n", gu4DecEMICounter); + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_to_user(user_data_addr, &gu4DecEMICounter, sizeof(VAL_UINT32_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_DEC_DEC_EMI_USER, copy_to_user failed: %lu\n", ret); + mutex_unlock(&DecEMILock); + return -EFAULT; + } + mutex_unlock(&DecEMILock); + + MODULE_MFV_LOGD("VCODEC_DEC_DEC_EMI_USER - tid = %d\n", current->pid); + } + break; + + case VCODEC_INC_ENC_EMI_USER: + { + MODULE_MFV_LOGD("VCODEC_INC_ENC_EMI_USER + tid = %d\n", current->pid); + + mutex_lock(&EncEMILock); + gu4EncEMICounter++; + MODULE_MFV_LOGE("[VCODEC] ENC_EMI_USER = %d\n", gu4EncEMICounter); + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_to_user(user_data_addr, &gu4EncEMICounter, sizeof(VAL_UINT32_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_INC_ENC_EMI_USER, copy_to_user failed: %lu\n", ret); + mutex_unlock(&EncEMILock); + return -EFAULT; + } + mutex_unlock(&EncEMILock); + + MODULE_MFV_LOGD("VCODEC_INC_ENC_EMI_USER - tid = %d\n", current->pid); + } + break; + + case VCODEC_DEC_ENC_EMI_USER: + { + MODULE_MFV_LOGD("VCODEC_DEC_ENC_EMI_USER + tid = %d\n", current->pid); + + mutex_lock(&EncEMILock); + gu4EncEMICounter--; + MODULE_MFV_LOGE("[VCODEC] ENC_EMI_USER = %d\n", gu4EncEMICounter); + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_to_user(user_data_addr, &gu4EncEMICounter, sizeof(VAL_UINT32_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_DEC_ENC_EMI_USER, copy_to_user failed: %lu\n", ret); + mutex_unlock(&EncEMILock); + return -EFAULT; + } + mutex_unlock(&EncEMILock); + + MODULE_MFV_LOGD("VCODEC_DEC_ENC_EMI_USER - tid = %d\n", current->pid); + } + break; + + case VCODEC_LOCKHW: + { + ret = vcodec_lockhw(arg); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_LOCKHW failed! %lu\n", ret); + return ret; + } + } + break; + + case VCODEC_UNLOCKHW: + { + ret = vcodec_unlockhw(arg); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_UNLOCKHW failed! %lu\n", ret); + return ret; + } + } + break; + + case VCODEC_INC_PWR_USER: + { + MODULE_MFV_LOGD("VCODEC_INC_PWR_USER + tid = %d\n", current->pid); + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rPowerParam, user_data_addr, sizeof(VAL_POWER_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_INC_PWR_USER, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + MODULE_MFV_LOGD("[VCODEC] INC_PWR_USER eDriverType = %d\n", rPowerParam.eDriverType); + mutex_lock(&L2CLock); + +#ifdef VENC_USE_L2C + if (rPowerParam.eDriverType == VAL_DRIVER_TYPE_H264_ENC) { + gu4L2CCounter++; + MODULE_MFV_LOGD("[VCODEC] INC_PWR_USER L2C counter = %d\n", gu4L2CCounter); + + if (1 == gu4L2CCounter) { + if (config_L2(0)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Switch L2C size to 512K failed\n"); + mutex_unlock(&L2CLock); + return -EFAULT; + } + MODULE_MFV_LOGE("[VCODEC] Switch L2C size to 512K successful\n"); + + } + } +#endif + mutex_unlock(&L2CLock); + MODULE_MFV_LOGD("VCODEC_INC_PWR_USER - tid = %d\n", current->pid); + } + break; + + case VCODEC_DEC_PWR_USER: + { + MODULE_MFV_LOGD("VCODEC_DEC_PWR_USER + tid = %d\n", current->pid); + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rPowerParam, user_data_addr, sizeof(VAL_POWER_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_DEC_PWR_USER, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + MODULE_MFV_LOGD("[VCODEC] DEC_PWR_USER eDriverType = %d\n", rPowerParam.eDriverType); + + mutex_lock(&L2CLock); + +#ifdef VENC_USE_L2C + if (rPowerParam.eDriverType == VAL_DRIVER_TYPE_H264_ENC) { + gu4L2CCounter--; + MODULE_MFV_LOGD("[VCODEC] DEC_PWR_USER L2C counter = %d\n", gu4L2CCounter); + + if (0 == gu4L2CCounter) { + if (config_L2(1)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Switch L2C size to 0K failed\n"); + mutex_unlock(&L2CLock); + return -EFAULT; + } + MODULE_MFV_LOGE("[VCODEC] Switch L2C size to 0K successful\n"); + } + } +#endif + mutex_unlock(&L2CLock); + MODULE_MFV_LOGD("VCODEC_DEC_PWR_USER - tid = %d\n", current->pid); + } + break; + + case VCODEC_WAITISR: + { + ret = vcodec_waitisr(arg); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_WAITISR failed! %lu\n", ret); + return ret; + } + } + break; + + case VCODEC_INITHWLOCK: + { + MODULE_MFV_LOGE("VCODEC_INITHWLOCK [EMPTY] + - tid = %d\n", current->pid); + MODULE_MFV_LOGE("VCODEC_INITHWLOCK [EMPTY] - - tid = %d\n", current->pid); + } + break; + + case VCODEC_DEINITHWLOCK: + { + MODULE_MFV_LOGE("VCODEC_DEINITHWLOCK [EMPTY] + - tid = %d\n", current->pid); + MODULE_MFV_LOGE("VCODEC_DEINITHWLOCK [EMPTY] - - tid = %d\n", current->pid); + } + break; + +#if 0 + case VCODEC_GET_CPU_LOADING_INFO: + { + VAL_UINT8_T *user_data_addr; + VAL_VCODEC_CPU_LOADING_INFO_T _temp; + + MODULE_MFV_LOGD("VCODEC_GET_CPU_LOADING_INFO +\n"); + user_data_addr = (VAL_UINT8_T *)arg; + /* TODO: */ +#if 0 /* Morris Yang 20120112 mark temporarily */ + _temp._cpu_idle_time = mt_get_cpu_idle(0); + _temp._thread_cpu_time = mt_get_thread_cputime(0); + spin_lock_irqsave(&OalHWContextLock, ulFlags); + _temp._inst_count = getCurInstanceCount(); + spin_unlock_irqrestore(&OalHWContextLock, ulFlags); + _temp._sched_clock = mt_sched_clock(); +#endif + ret = copy_to_user(user_data_addr, &_temp, sizeof(VAL_VCODEC_CPU_LOADING_INFO_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_GET_CPU_LOADING_INFO, copy_to_user failed: %lu\n", ret); + return -EFAULT; + } + + MODULE_MFV_LOGD("VCODEC_GET_CPU_LOADING_INFO -\n"); + } + break; +#endif + + case VCODEC_GET_CORE_LOADING: + { + MODULE_MFV_LOGD("VCODEC_GET_CORE_LOADING + - tid = %d\n", current->pid); + + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rTempCoreLoading, user_data_addr, sizeof(VAL_VCODEC_CORE_LOADING_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_GET_CORE_LOADING, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + if (rTempCoreLoading.CPUid < 0) { + MODULE_MFV_LOGE("[ERROR] rTempCoreLoading.CPUid < 0\n"); + return -EFAULT; + } + if (rTempCoreLoading.CPUid > num_possible_cpus()) { + MODULE_MFV_LOGE("[ERROR] rTempCoreLoading.CPUid(%d) > num_possible_cpus(%d)\n", + rTempCoreLoading.CPUid, num_possible_cpus()); + return -EFAULT; + } + rTempCoreLoading.Loading = get_cpu_load(rTempCoreLoading.CPUid); + ret = copy_to_user(user_data_addr, &rTempCoreLoading, sizeof(VAL_VCODEC_CORE_LOADING_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_GET_CORE_LOADING, copy_to_user failed: %lu\n", ret); + return -EFAULT; + } + MODULE_MFV_LOGD("VCODEC_GET_CORE_LOADING - - tid = %d\n", current->pid); + } + break; + + case VCODEC_GET_CORE_NUMBER: + { + MODULE_MFV_LOGD("VCODEC_GET_CORE_NUMBER + - tid = %d\n", current->pid); + + user_data_addr = (VAL_UINT8_T *)arg; + temp_nr_cpu_ids = nr_cpu_ids; + ret = copy_to_user(user_data_addr, &temp_nr_cpu_ids, sizeof(int)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_GET_CORE_NUMBER, copy_to_user failed: %lu\n", ret); + return -EFAULT; + } + MODULE_MFV_LOGD("VCODEC_GET_CORE_NUMBER - - tid = %d\n", current->pid); + } + break; + + case VCODEC_SET_CPU_OPP_LIMIT: + { + MODULE_MFV_LOGE("VCODEC_SET_CPU_OPP_LIMIT [EMPTY] + - tid = %d\n", current->pid); + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rCpuOppLimit, user_data_addr, sizeof(VAL_VCODEC_CPU_OPP_LIMIT_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_SET_CPU_OPP_LIMIT, copy_from_user failed: %lu\n", ret); + return -EFAULT; + } + MODULE_MFV_LOGE("+VCODEC_SET_CPU_OPP_LIMIT (%d, %d, %d), tid = %d\n", + rCpuOppLimit.limited_freq, rCpuOppLimit.limited_cpu, rCpuOppLimit.enable, current->pid); + /* TODO: Check if cpu_opp_limit is available */ + /* + ret = cpu_opp_limit(EVENT_VIDEO, rCpuOppLimit.limited_freq, + rCpuOppLimit.limited_cpu, rCpuOppLimit.enable); // 0: PASS, other: FAIL + if (ret) { + MODULE_MFV_LOGE("[VCODEC][ERROR] cpu_opp_limit failed: %lu\n", ret); + return -EFAULT; + } + */ + MODULE_MFV_LOGE("-VCODEC_SET_CPU_OPP_LIMIT tid = %d, ret = %lu\n", current->pid, ret); + MODULE_MFV_LOGE("VCODEC_SET_CPU_OPP_LIMIT [EMPTY] - - tid = %d\n", current->pid); + } + break; + + case VCODEC_MB: + { + mb(); + } + break; + + case VCODEC_SET_LOG_COUNT: + { + MODULE_MFV_LOGD("VCODEC_SET_LOG_COUNT + tid = %d\n", current->pid); + + mutex_lock(&LogCountLock); + user_data_addr = (VAL_UINT8_T *)arg; + ret = copy_from_user(&rIncLogCount, user_data_addr, sizeof(VAL_BOOL_T)); + if (ret) { + MODULE_MFV_LOGE("[ERROR] VCODEC_SET_LOG_COUNT, copy_from_user failed: %lu\n", ret); + mutex_unlock(&LogCountLock); + return -EFAULT; + } + + if (rIncLogCount == VAL_TRUE) { + if (gu4LogCountUser == 0) { + gu4LogCount = get_detect_count(); + set_detect_count(gu4LogCount + 100); + } + gu4LogCountUser++; + } else { + gu4LogCountUser--; + if (gu4LogCountUser == 0) { + set_detect_count(gu4LogCount); + gu4LogCount = 0; + } + } + mutex_unlock(&LogCountLock); + + MODULE_MFV_LOGD("VCODEC_SET_LOG_COUNT - tid = %d\n", current->pid); + } + break; + + default: + { + MODULE_MFV_LOGE("========[ERROR] vcodec_ioctl default case======== %u\n", cmd); + } + break; + + } + return 0xFF; +} + +#if IS_ENABLED(CONFIG_COMPAT) + +typedef enum { + VAL_HW_LOCK_TYPE = 0, + VAL_POWER_TYPE, + VAL_ISR_TYPE, + VAL_MEMORY_TYPE +} STRUCT_TYPE; + +typedef enum { + COPY_FROM_USER = 0, + COPY_TO_USER, +} COPY_DIRECTION; + +typedef struct COMPAT_VAL_HW_LOCK { + /* [IN] The video codec driver handle */ + compat_uptr_t pvHandle; + /* [IN] The size of video codec driver handle */ + compat_uint_t u4HandleSize; + /* [IN/OUT] The Lock discriptor */ + compat_uptr_t pvLock; + /* [IN] The timeout ms */ + compat_uint_t u4TimeoutMs; + /* [IN/OUT] The reserved parameter */ + compat_uptr_t pvReserved; + /* [IN] The size of reserved parameter structure */ + compat_uint_t u4ReservedSize; + /* [IN] The driver type */ + compat_uint_t eDriverType; + /* [IN] True if this is a secure instance // MTK_SEC_VIDEO_PATH_SUPPORT */ + char bSecureInst; +} COMPAT_VAL_HW_LOCK_T; + +typedef struct COMPAT_VAL_POWER { + /* [IN] The video codec driver handle */ + compat_uptr_t pvHandle; + /* [IN] The size of video codec driver handle */ + compat_uint_t u4HandleSize; + /* [IN] The driver type */ + compat_uint_t eDriverType; + /* [IN] Enable or not. */ + char fgEnable; + /* [IN/OUT] The reserved parameter */ + compat_uptr_t pvReserved; + /* [IN] The size of reserved parameter structure */ + compat_uint_t u4ReservedSize; + /* [OUT] The number of power user right now */ + /* VAL_UINT32_T u4L2CUser; */ +} COMPAT_VAL_POWER_T; + +typedef struct COMPAT_VAL_ISR { + /* [IN] The video codec driver handle */ + compat_uptr_t pvHandle; + /* [IN] The size of video codec driver handle */ + compat_uint_t u4HandleSize; + /* [IN] The driver type */ + compat_uint_t eDriverType; + /* [IN] The isr function */ + compat_uptr_t pvIsrFunction; + /* [IN/OUT] The reserved parameter */ + compat_uptr_t pvReserved; + /* [IN] The size of reserved parameter structure */ + compat_uint_t u4ReservedSize; + /* [IN] The timeout in ms */ + compat_uint_t u4TimeoutMs; + /* [IN] The num of return registers when HW done */ + compat_uint_t u4IrqStatusNum; + /* [IN/OUT] The value of return registers when HW done */ + compat_uint_t u4IrqStatus[IRQ_STATUS_MAX_NUM]; +} COMPAT_VAL_ISR_T; + +typedef struct COMPAT_VAL_MEMORY { + /* [IN] The allocation memory type */ + compat_uint_t eMemType; + /* [IN] The size of memory allocation */ + compat_ulong_t u4MemSize; + /* [IN/OUT] The memory virtual address */ + compat_uptr_t pvMemVa; + /* [IN/OUT] The memory physical address */ + compat_uptr_t pvMemPa; + /* [IN] The memory byte alignment setting */ + compat_uint_t eAlignment; + /* [IN/OUT] The align memory virtual address */ + compat_uptr_t pvAlignMemVa; + /* [IN/OUT] The align memory physical address */ + compat_uptr_t pvAlignMemPa; + /* [IN] The memory codec for VENC or VDEC */ + compat_uint_t eMemCodec; + compat_uint_t i4IonShareFd; + compat_uptr_t pIonBufhandle; + /* [IN/OUT] The reserved parameter */ + compat_uptr_t pvReserved; + /* [IN] The size of reserved parameter structure */ + compat_ulong_t u4ReservedSize; +} COMPAT_VAL_MEMORY_T; + +static int get_uptr_to_32(compat_uptr_t *p, void __user **uptr) +{ + void __user *p2p; + int err = get_user(p2p, uptr); + *p = ptr_to_compat(p2p); + return err; +} +static int compat_copy_struct( + STRUCT_TYPE eType, + COPY_DIRECTION eDirection, + void __user *data32, + void __user *data) +{ + compat_uint_t u; + compat_ulong_t l; + compat_uptr_t p; + char c; + int err = 0; + + switch (eType) { + case VAL_HW_LOCK_TYPE: + { + if (eDirection == COPY_FROM_USER) { + COMPAT_VAL_HW_LOCK_T __user *from32 = (COMPAT_VAL_HW_LOCK_T *)data32; + VAL_HW_LOCK_T __user *to = (VAL_HW_LOCK_T *)data; + + err = get_user(p, &(from32->pvHandle)); + err |= put_user(compat_ptr(p), &(to->pvHandle)); + err |= get_user(u, &(from32->u4HandleSize)); + err |= put_user(u, &(to->u4HandleSize)); + err |= get_user(p, &(from32->pvLock)); + err |= put_user(compat_ptr(p), &(to->pvLock)); + err |= get_user(u, &(from32->u4TimeoutMs)); + err |= put_user(u, &(to->u4TimeoutMs)); + err |= get_user(p, &(from32->pvReserved)); + err |= put_user(compat_ptr(p), &(to->pvReserved)); + err |= get_user(u, &(from32->u4ReservedSize)); + err |= put_user(u, &(to->u4ReservedSize)); + err |= get_user(u, &(from32->eDriverType)); + err |= put_user(u, &(to->eDriverType)); + err |= get_user(c, &(from32->bSecureInst)); + err |= put_user(c, &(to->bSecureInst)); + } else { + COMPAT_VAL_HW_LOCK_T __user *to32 = (COMPAT_VAL_HW_LOCK_T *)data32; + VAL_HW_LOCK_T __user *from = (VAL_HW_LOCK_T *)data; + + err = get_uptr_to_32(&p, &(from->pvHandle)); + err |= put_user(p, &(to32->pvHandle)); + err |= get_user(u, &(from->u4HandleSize)); + err |= put_user(u, &(to32->u4HandleSize)); + err |= get_uptr_to_32(&p, &(from->pvLock)); + err |= put_user(p, &(to32->pvLock)); + err |= get_user(u, &(from->u4TimeoutMs)); + err |= put_user(u, &(to32->u4TimeoutMs)); + err |= get_uptr_to_32(&p, &(from->pvReserved)); + err |= put_user(p, &(to32->pvReserved)); + err |= get_user(u, &(from->u4ReservedSize)); + err |= put_user(u, &(to32->u4ReservedSize)); + err |= get_user(u, &(from->eDriverType)); + err |= put_user(u, &(to32->eDriverType)); + err |= get_user(c, &(from->bSecureInst)); + err |= put_user(c, &(to32->bSecureInst)); + } + } + break; + case VAL_POWER_TYPE: + { + if (eDirection == COPY_FROM_USER) { + COMPAT_VAL_POWER_T __user *from32 = (COMPAT_VAL_POWER_T *)data32; + VAL_POWER_T __user *to = (VAL_POWER_T *)data; + + err = get_user(p, &(from32->pvHandle)); + err |= put_user(compat_ptr(p), &(to->pvHandle)); + err |= get_user(u, &(from32->u4HandleSize)); + err |= put_user(u, &(to->u4HandleSize)); + err |= get_user(u, &(from32->eDriverType)); + err |= put_user(u, &(to->eDriverType)); + err |= get_user(c, &(from32->fgEnable)); + err |= put_user(c, &(to->fgEnable)); + err |= get_user(p, &(from32->pvReserved)); + err |= put_user(compat_ptr(p), &(to->pvReserved)); + err |= get_user(u, &(from32->u4ReservedSize)); + err |= put_user(u, &(to->u4ReservedSize)); + } else { + COMPAT_VAL_POWER_T __user *to32 = (COMPAT_VAL_POWER_T *)data32; + VAL_POWER_T __user *from = (VAL_POWER_T *)data; + + err = get_uptr_to_32(&p, &(from->pvHandle)); + err |= put_user(p, &(to32->pvHandle)); + err |= get_user(u, &(from->u4HandleSize)); + err |= put_user(u, &(to32->u4HandleSize)); + err |= get_user(u, &(from->eDriverType)); + err |= put_user(u, &(to32->eDriverType)); + err |= get_user(c, &(from->fgEnable)); + err |= put_user(c, &(to32->fgEnable)); + err |= get_uptr_to_32(&p, &(from->pvReserved)); + err |= put_user(p, &(to32->pvReserved)); + err |= get_user(u, &(from->u4ReservedSize)); + err |= put_user(u, &(to32->u4ReservedSize)); + } + } + break; + case VAL_ISR_TYPE: + { + int i = 0; + + if (eDirection == COPY_FROM_USER) { + COMPAT_VAL_ISR_T __user *from32 = (COMPAT_VAL_ISR_T *)data32; + VAL_ISR_T __user *to = (VAL_ISR_T *)data; + + err = get_user(p, &(from32->pvHandle)); + err |= put_user(compat_ptr(p), &(to->pvHandle)); + err |= get_user(u, &(from32->u4HandleSize)); + err |= put_user(u, &(to->u4HandleSize)); + err |= get_user(u, &(from32->eDriverType)); + err |= put_user(u, &(to->eDriverType)); + err |= get_user(p, &(from32->pvIsrFunction)); + err |= put_user(compat_ptr(p), &(to->pvIsrFunction)); + err |= get_user(p, &(from32->pvReserved)); + err |= put_user(compat_ptr(p), &(to->pvReserved)); + err |= get_user(u, &(from32->u4ReservedSize)); + err |= put_user(u, &(to->u4ReservedSize)); + err |= get_user(u, &(from32->u4TimeoutMs)); + err |= put_user(u, &(to->u4TimeoutMs)); + err |= get_user(u, &(from32->u4IrqStatusNum)); + err |= put_user(u, &(to->u4IrqStatusNum)); + for (; i < IRQ_STATUS_MAX_NUM; i++) { + err |= get_user(u, &(from32->u4IrqStatus[i])); + err |= put_user(u, &(to->u4IrqStatus[i])); + } + return err; + + } else { + COMPAT_VAL_ISR_T __user *to32 = (COMPAT_VAL_ISR_T *)data32; + VAL_ISR_T __user *from = (VAL_ISR_T *)data; + + err = get_uptr_to_32(&p, &(from->pvHandle)); + err |= put_user(p, &(to32->pvHandle)); + err |= get_user(u, &(from->u4HandleSize)); + err |= put_user(u, &(to32->u4HandleSize)); + err |= get_user(u, &(from->eDriverType)); + err |= put_user(u, &(to32->eDriverType)); + err |= get_uptr_to_32(&p, &(from->pvIsrFunction)); + err |= put_user(p, &(to32->pvIsrFunction)); + err |= get_uptr_to_32(&p, &(from->pvReserved)); + err |= put_user(p, &(to32->pvReserved)); + err |= get_user(u, &(from->u4ReservedSize)); + err |= put_user(u, &(to32->u4ReservedSize)); + err |= get_user(u, &(from->u4TimeoutMs)); + err |= put_user(u, &(to32->u4TimeoutMs)); + err |= get_user(u, &(from->u4IrqStatusNum)); + err |= put_user(u, &(to32->u4IrqStatusNum)); + for (; i < IRQ_STATUS_MAX_NUM; i++) { + err |= get_user(u, &(from->u4IrqStatus[i])); + err |= put_user(u, &(to32->u4IrqStatus[i])); + } + } + } + break; + case VAL_MEMORY_TYPE: + { + if (eDirection == COPY_FROM_USER) { + COMPAT_VAL_MEMORY_T __user *from32 = (COMPAT_VAL_MEMORY_T *)data32; + VAL_MEMORY_T __user *to = (VAL_MEMORY_T *)data; + + err = get_user(u, &(from32->eMemType)); + err |= put_user(u, &(to->eMemType)); + err |= get_user(l, &(from32->u4MemSize)); + err |= put_user(l, &(to->u4MemSize)); + err |= get_user(p, &(from32->pvMemVa)); + err |= put_user(compat_ptr(p), &(to->pvMemVa)); + err |= get_user(p, &(from32->pvMemPa)); + err |= put_user(compat_ptr(p), &(to->pvMemPa)); + err |= get_user(u, &(from32->eAlignment)); + err |= put_user(u, &(to->eAlignment)); + err |= get_user(p, &(from32->pvAlignMemVa)); + err |= put_user(compat_ptr(p), &(to->pvAlignMemVa)); + err |= get_user(p, &(from32->pvAlignMemPa)); + err |= put_user(compat_ptr(p), &(to->pvAlignMemPa)); + err |= get_user(u, &(from32->eMemCodec)); + err |= put_user(u, &(to->eMemCodec)); + err |= get_user(u, &(from32->i4IonShareFd)); + err |= put_user(u, &(to->i4IonShareFd)); + err |= get_user(p, &(from32->pIonBufhandle)); + err |= put_user(compat_ptr(p), &(to->pIonBufhandle)); + err |= get_user(p, &(from32->pvReserved)); + err |= put_user(compat_ptr(p), &(to->pvReserved)); + err |= get_user(l, &(from32->u4ReservedSize)); + err |= put_user(l, &(to->u4ReservedSize)); + } else{ + COMPAT_VAL_MEMORY_T __user *to32 = (COMPAT_VAL_MEMORY_T *)data32; + + VAL_MEMORY_T __user *from = (VAL_MEMORY_T *)data; + + err = get_user(u, &(from->eMemType)); + err |= put_user(u, &(to32->eMemType)); + err |= get_user(l, &(from->u4MemSize)); + err |= put_user(l, &(to32->u4MemSize)); + err |= get_uptr_to_32(&p, &(from->pvMemVa)); + err |= put_user(p, &(to32->pvMemVa)); + err |= get_uptr_to_32(&p, &(from->pvMemPa)); + err |= put_user(p, &(to32->pvMemPa)); + err |= get_user(u, &(from->eAlignment)); + err |= put_user(u, &(to32->eAlignment)); + err |= get_uptr_to_32(&p, &(from->pvAlignMemVa)); + err |= put_user(p, &(to32->pvAlignMemVa)); + err |= get_uptr_to_32(&p, &(from->pvAlignMemPa)); + err |= put_user(p, &(to32->pvAlignMemPa)); + err |= get_user(u, &(from->eMemCodec)); + err |= put_user(u, &(to32->eMemCodec)); + err |= get_user(u, &(from->i4IonShareFd)); + err |= put_user(u, &(to32->i4IonShareFd)); + err |= get_uptr_to_32(&p, (void __user **)&(from->pIonBufhandle)); + err |= put_user(p, &(to32->pIonBufhandle)); + err |= get_uptr_to_32(&p, &(from->pvReserved)); + err |= put_user(p, &(to32->pvReserved)); + err |= get_user(l, &(from->u4ReservedSize)); + err |= put_user(l, &(to32->u4ReservedSize)); + } + } + break; + default: + break; + } + + return err; +} + + +static long vcodec_unlocked_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret = 0; + /* MODULE_MFV_LOGD("vcodec_unlocked_compat_ioctl: 0x%x\n", cmd); */ + switch (cmd) { + case VCODEC_ALLOC_NON_CACHE_BUFFER: + case VCODEC_FREE_NON_CACHE_BUFFER: + { + COMPAT_VAL_MEMORY_T __user *data32; + VAL_MEMORY_T __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(VAL_MEMORY_T)); + if (data == NULL) + return -EFAULT; + + err = compat_copy_struct(VAL_MEMORY_TYPE, COPY_FROM_USER, (void *)data32, (void *)data); + if (err) + return err; + + ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)data); + + err = compat_copy_struct(VAL_MEMORY_TYPE, COPY_TO_USER, (void *)data32, (void *)data); + + if (err) + return err; + return ret; + } + break; + case VCODEC_LOCKHW: + case VCODEC_UNLOCKHW: + { + COMPAT_VAL_HW_LOCK_T __user *data32; + VAL_HW_LOCK_T __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(VAL_HW_LOCK_T)); + if (data == NULL) + return -EFAULT; + + err = compat_copy_struct(VAL_HW_LOCK_TYPE, COPY_FROM_USER, (void *)data32, (void *)data); + if (err) + return err; + + ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)data); + + err = compat_copy_struct(VAL_HW_LOCK_TYPE, COPY_TO_USER, (void *)data32, (void *)data); + + if (err) + return err; + return ret; + } + break; + + case VCODEC_INC_PWR_USER: + case VCODEC_DEC_PWR_USER: + { + COMPAT_VAL_POWER_T __user *data32; + VAL_POWER_T __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(VAL_POWER_T)); + if (data == NULL) + return -EFAULT; + + err = compat_copy_struct(VAL_POWER_TYPE, COPY_FROM_USER, (void *)data32, (void *)data); + + if (err) + return err; + + ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)data); + + err = compat_copy_struct(VAL_POWER_TYPE, COPY_TO_USER, (void *)data32, (void *)data); + + if (err) + return err; + return ret; + } + break; + + case VCODEC_WAITISR: + { + COMPAT_VAL_ISR_T __user *data32; + VAL_ISR_T __user *data; + int err; + + data32 = compat_ptr(arg); + data = compat_alloc_user_space(sizeof(VAL_ISR_T)); + if (data == NULL) + return -EFAULT; + + err = compat_copy_struct(VAL_ISR_TYPE, COPY_FROM_USER, (void *)data32, (void *)data); + if (err) + return err; + + ret = file->f_op->unlocked_ioctl(file, VCODEC_WAITISR, (unsigned long)data); + + err = compat_copy_struct(VAL_ISR_TYPE, COPY_TO_USER, (void *)data32, (void *)data); + + if (err) + return err; + return ret; + } + break; + + default: + return vcodec_unlocked_ioctl(file, cmd, arg); + } + return 0; +} +#else +#define vcodec_unlocked_compat_ioctl NULL +#endif +static int vcodec_open(struct inode *inode, struct file *file) +{ + MODULE_MFV_LOGD("vcodec_open\n"); + + mutex_lock(&DriverOpenCountLock); + Driver_Open_Count++; + + MODULE_MFV_LOGE("vcodec_open pid = %d, Driver_Open_Count %d\n", current->pid, Driver_Open_Count); + mutex_unlock(&DriverOpenCountLock); + + + /* TODO: Check upper limit of concurrent users? */ + + return 0; +} + +static int vcodec_flush(struct file *file, fl_owner_t id) +{ + MODULE_MFV_LOGD("vcodec_flush, curr_tid =%d\n", current->pid); + MODULE_MFV_LOGE("vcodec_flush pid = %d, Driver_Open_Count %d\n", current->pid, Driver_Open_Count); + + return 0; +} + +static int vcodec_release(struct inode *inode, struct file *file) +{ + VAL_ULONG_T ulFlagsLockHW, ulFlagsISR; + + /* dump_stack(); */ + MODULE_MFV_LOGD("vcodec_release, curr_tid =%d\n", current->pid); + mutex_lock(&DriverOpenCountLock); + MODULE_MFV_LOGE("vcodec_release pid = %d, Driver_Open_Count %d\n", current->pid, Driver_Open_Count); + Driver_Open_Count--; + + if (Driver_Open_Count == 0) { + mutex_lock(&VdecHWLock); + gu4VdecLockThreadId = 0; + grVcodecDecHWLock.pvHandle = 0; + grVcodecDecHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; + grVcodecDecHWLock.rLockedTime.u4Sec = 0; + grVcodecDecHWLock.rLockedTime.u4uSec = 0; + mutex_unlock(&VdecHWLock); + + mutex_lock(&VencHWLock); + grVcodecEncHWLock.pvHandle = 0; + grVcodecEncHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; + grVcodecEncHWLock.rLockedTime.u4Sec = 0; + grVcodecEncHWLock.rLockedTime.u4uSec = 0; + mutex_unlock(&VencHWLock); + + mutex_lock(&DecEMILock); + gu4DecEMICounter = 0; + mutex_unlock(&DecEMILock); + + mutex_lock(&EncEMILock); + gu4EncEMICounter = 0; + mutex_unlock(&EncEMILock); + + mutex_lock(&PWRLock); + gu4PWRCounter = 0; + mutex_unlock(&PWRLock); + +#if defined(VENC_USE_L2C) + mutex_lock(&L2CLock); + if (gu4L2CCounter != 0) { + MODULE_MFV_LOGE("vcodec_flush pid = %d, L2 user = %d, force restore L2 settings\n", + current->pid, gu4L2CCounter); + if (config_L2(1)) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] restore L2 settings failed\n"); + } + } + gu4L2CCounter = 0; + mutex_unlock(&L2CLock); +#endif + spin_lock_irqsave(&LockDecHWCountLock, ulFlagsLockHW); + gu4LockDecHWCount = 0; + spin_unlock_irqrestore(&LockDecHWCountLock, ulFlagsLockHW); + + spin_lock_irqsave(&LockEncHWCountLock, ulFlagsLockHW); + gu4LockEncHWCount = 0; + spin_unlock_irqrestore(&LockEncHWCountLock, ulFlagsLockHW); + + spin_lock_irqsave(&DecISRCountLock, ulFlagsISR); + gu4DecISRCount = 0; + spin_unlock_irqrestore(&DecISRCountLock, ulFlagsISR); + + spin_lock_irqsave(&EncISRCountLock, ulFlagsISR); + gu4EncISRCount = 0; + spin_unlock_irqrestore(&EncISRCountLock, ulFlagsISR); + } + + mutex_unlock(&DriverOpenCountLock); + + return 0; +} + +void vcodec_vma_open(struct vm_area_struct *vma) +{ + MODULE_MFV_LOGD("vcodec VMA open, virt %lx, phys %lx\n", vma->vm_start, vma->vm_pgoff << PAGE_SHIFT); +} + +void vcodec_vma_close(struct vm_area_struct *vma) +{ + MODULE_MFV_LOGD("vcodec VMA close, virt %lx, phys %lx\n", vma->vm_start, vma->vm_pgoff << PAGE_SHIFT); +} + +static struct vm_operations_struct vcodec_remap_vm_ops = { + .open = vcodec_vma_open, + .close = vcodec_vma_close, +}; + +static int vcodec_mmap(struct file *file, struct vm_area_struct *vma) +{ +#if 1 + VAL_UINT32_T u4I = 0; + VAL_ULONG_T length; + VAL_ULONG_T pfn; + + length = vma->vm_end - vma->vm_start; + pfn = vma->vm_pgoff << PAGE_SHIFT; + + if (((length > VENC_REGION) || (pfn < VENC_BASE) || (pfn > VENC_BASE + VENC_REGION)) && + ((length > VDEC_REGION) || (pfn < VDEC_BASE_PHY) || (pfn > VDEC_BASE_PHY + VDEC_REGION)) && + ((length > HW_REGION) || (pfn < HW_BASE) || (pfn > HW_BASE + HW_REGION)) && + ((length > INFO_REGION) || (pfn < INFO_BASE) || (pfn > INFO_BASE + INFO_REGION)) + ) { + VAL_ULONG_T ulAddr, ulSize; + + for (u4I = 0; u4I < VCODEC_MULTIPLE_INSTANCE_NUM_x_10; u4I++) { + if ((grNonCacheMemoryList[u4I].ulKVA != -1L) && (grNonCacheMemoryList[u4I].ulKPA != -1L)) { + ulAddr = grNonCacheMemoryList[u4I].ulKPA; + ulSize = (grNonCacheMemoryList[u4I].ulSize + 0x1000 - 1) & ~(0x1000 - 1); + if ((length == ulSize) && (pfn == ulAddr)) { + MODULE_MFV_LOGD("[VCODEC] cache idx %d\n", u4I); + break; + } + } + } + + if (u4I == VCODEC_MULTIPLE_INSTANCE_NUM_x_10) { + MODULE_MFV_LOGE("[VCODEC][ERROR] mmap region error: Length(0x%lx), pfn(0x%lx)\n", + (VAL_ULONG_T)length, pfn); + return -EAGAIN; + } + } +#endif + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + MODULE_MFV_LOGD("[VCODEC][mmap] vma->start 0x%lx, vma->end 0x%lx, vma->pgoff 0x%lx\n", + (VAL_ULONG_T)vma->vm_start, (VAL_ULONG_T)vma->vm_end, (VAL_ULONG_T)vma->vm_pgoff); + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + return -EAGAIN; + } + + vma->vm_ops = &vcodec_remap_vm_ops; + vcodec_vma_open(vma); + + return 0; +} + +static const struct file_operations vcodec_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = vcodec_unlocked_ioctl, + .open = vcodec_open, + .flush = vcodec_flush, + .release = vcodec_release, + .mmap = vcodec_mmap, +#if IS_ENABLED(CONFIG_COMPAT) + .compat_ioctl = vcodec_unlocked_compat_ioctl, +#endif + +}; + +static int vcodec_probe(struct platform_device *dev) +{ + int ret; + + MODULE_MFV_LOGD("+vcodec_probe\n"); + + mutex_lock(&DecEMILock); + gu4DecEMICounter = 0; + mutex_unlock(&DecEMILock); + + mutex_lock(&EncEMILock); + gu4EncEMICounter = 0; + mutex_unlock(&EncEMILock); + + mutex_lock(&PWRLock); + gu4PWRCounter = 0; + mutex_unlock(&PWRLock); + + mutex_lock(&L2CLock); + gu4L2CCounter = 0; + mutex_unlock(&L2CLock); + + ret = register_chrdev_region(vcodec_devno, 1, VCODEC_DEVNAME); + if (ret) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[ERROR] Can't Get Major number for VCodec Device\n"); + } + + vcodec_cdev = cdev_alloc(); + vcodec_cdev->owner = THIS_MODULE; + vcodec_cdev->ops = &vcodec_fops; + + ret = cdev_add(vcodec_cdev, vcodec_devno, 1); + if (ret) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[ERROR] Can't add Vcodec Device\n"); + } + + vcodec_class = class_create(THIS_MODULE, VCODEC_DEVNAME); + if (IS_ERR(vcodec_class)) { + ret = PTR_ERR(vcodec_class); + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to create class, err = %d", ret); + return ret; + } + + vcodec_device = device_create(vcodec_class, NULL, vcodec_devno, NULL, VCODEC_DEVNAME); + + if (request_irq(VDEC_IRQ_ID , (irq_handler_t)video_intr_dlr, IRQF_TRIGGER_LOW, VCODEC_DEVNAME, NULL) < 0) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] error to request dec irq\n"); + } else { + MODULE_MFV_LOGD("[VCODEC] success to request dec irq: %d\n", VDEC_IRQ_ID); + } + + if (request_irq(VENC_IRQ_ID , (irq_handler_t)video_intr_dlr2, IRQF_TRIGGER_LOW, VCODEC_DEVNAME, NULL) < 0) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGD("[VCODEC][ERROR] error to request enc irq\n"); + } else { + MODULE_MFV_LOGD("[VCODEC] success to request enc irq: %d\n", VENC_IRQ_ID); + } + + disable_irq(VDEC_IRQ_ID); + disable_irq(VENC_IRQ_ID); + +#ifndef CONFIG_MTK_CLKMGR + clk_MT_CG_DISP0_SMI_COMMON = devm_clk_get(&dev->dev, "MT_CG_DISP0_SMI_COMMON"); + if (IS_ERR(clk_MT_CG_DISP0_SMI_COMMON)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to devm_clk_get MT_CG_DISP0_SMI_COMMON\n"); + return PTR_ERR(clk_MT_CG_DISP0_SMI_COMMON); + } + + clk_MT_CG_VDEC0_VDEC = devm_clk_get(&dev->dev, "MT_CG_VDEC0_VDEC"); + if (IS_ERR(clk_MT_CG_VDEC0_VDEC)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to devm_clk_get MT_CG_VDEC0_VDEC\n"); + return PTR_ERR(clk_MT_CG_VDEC0_VDEC); + } + + clk_MT_CG_VDEC1_LARB = devm_clk_get(&dev->dev, "MT_CG_VDEC1_LARB"); + if (IS_ERR(clk_MT_CG_VDEC1_LARB)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to devm_clk_get MT_CG_VDEC1_LARB\n"); + return PTR_ERR(clk_MT_CG_VDEC1_LARB); + } + + clk_MT_CG_VENC_VENC = devm_clk_get(&dev->dev, "MT_CG_VENC_VENC"); + if (IS_ERR(clk_MT_CG_VENC_VENC)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to devm_clk_get MT_CG_VENC_VENC\n"); + return PTR_ERR(clk_MT_CG_VENC_VENC); + } + + clk_MT_CG_VENC_LARB = devm_clk_get(&dev->dev, "MT_CG_VENC_LARB"); + if (IS_ERR(clk_MT_CG_VENC_LARB)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to devm_clk_get MT_CG_VENC_LARB\n"); + return PTR_ERR(clk_MT_CG_VENC_LARB); + } + + clk_MT_SCP_SYS_VDE = devm_clk_get(&dev->dev, "MT_SCP_SYS_VDE"); + if (IS_ERR(clk_MT_SCP_SYS_VDE)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to devm_clk_get MT_SCP_SYS_VDE\n"); + return PTR_ERR(clk_MT_SCP_SYS_VDE); + } + + clk_MT_SCP_SYS_VEN = devm_clk_get(&dev->dev, "MT_SCP_SYS_VEN"); + if (IS_ERR(clk_MT_SCP_SYS_VEN)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to devm_clk_get MT_SCP_SYS_VEN\n"); + return PTR_ERR(clk_MT_SCP_SYS_VEN); + } + + clk_MT_SCP_SYS_DIS = devm_clk_get(&dev->dev, "MT_SCP_SYS_DIS"); + if (IS_ERR(clk_MT_SCP_SYS_DIS)) { + MODULE_MFV_LOGE("[VCODEC][ERROR] Unable to devm_clk_get MT_SCP_SYS_DIS\n"); + return PTR_ERR(clk_MT_SCP_SYS_DIS); + } +#endif + + MODULE_MFV_LOGD("vcodec_probe Done\n"); + +#ifdef KS_POWER_WORKAROUND + vdec_power_on(); + venc_power_on(); +#endif + + return 0; +} + +static int vcodec_remove(struct platform_device *pDev) +{ + MODULE_MFV_LOGD("vcodec_remove\n"); + return 0; +} + +#ifdef CONFIG_MTK_HIBERNATION +/* extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); */ +/* extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity); */ +static int vcodec_pm_restore_noirq(struct device *device) +{ + /* vdec: IRQF_TRIGGER_LOW */ + mt_irq_set_sens(VDEC_IRQ_ID, MT_LEVEL_SENSITIVE); + mt_irq_set_polarity(VDEC_IRQ_ID, MT_POLARITY_LOW); + /* venc: IRQF_TRIGGER_LOW */ + mt_irq_set_sens(VENC_IRQ_ID, MT_LEVEL_SENSITIVE); + mt_irq_set_polarity(VENC_IRQ_ID, MT_POLARITY_LOW); + + return 0; +} +#endif + +static const struct of_device_id vcodec_of_match[] = { + { .compatible = "mediatek,mt6755-vdec_gcon", }, + {/* sentinel */} +}; + +MODULE_DEVICE_TABLE(of, vcodec_of_match); + +static struct platform_driver vcodec_driver = { + .probe = vcodec_probe, + .remove = vcodec_remove, + /* + .suspend = vcodec_suspend, + .resume = vcodec_resume, + */ + .driver = { + .name = VCODEC_DEVNAME, + .owner = THIS_MODULE, + .of_match_table = vcodec_of_match, + }, +}; + +static int __init vcodec_driver_init(void) +{ + VAL_RESULT_T eValHWLockRet; + VAL_ULONG_T ulFlags, ulFlagsLockHW, ulFlagsISR; + + MODULE_MFV_LOGD("+vcodec_driver_init !!\n"); + + mutex_lock(&DriverOpenCountLock); + Driver_Open_Count = 0; + mutex_unlock(&DriverOpenCountLock); + + mutex_lock(&LogCountLock); + gu4LogCountUser = 0; + gu4LogCount = 0; + mutex_unlock(&LogCountLock); + + { + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-venc"); + KVA_VENC_BASE = (VAL_ULONG_T)of_iomap(node, 0); + VENC_IRQ_ID = irq_of_parse_and_map(node, 0); + KVA_VENC_IRQ_STATUS_ADDR = KVA_VENC_BASE + 0x05C; + KVA_VENC_IRQ_ACK_ADDR = KVA_VENC_BASE + 0x060; + } + + { + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-vdec_full_top"); + KVA_VDEC_BASE = (VAL_ULONG_T)of_iomap(node, 0); + VDEC_IRQ_ID = irq_of_parse_and_map(node, 0); + KVA_VDEC_MISC_BASE = KVA_VDEC_BASE + 0x0000; + KVA_VDEC_VLD_BASE = KVA_VDEC_BASE + 0x1000; + } + { + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt6755-vdec_gcon"); + KVA_VDEC_GCON_BASE = (VAL_ULONG_T)of_iomap(node, 0); + + MODULE_MFV_LOGD("[VCODEC][DeviceTree] KVA_VENC_BASE(0x%lx), KVA_VDEC_BASE(0x%lx), KVA_VDEC_GCON_BASE(0x%lx)", + KVA_VENC_BASE, KVA_VDEC_BASE, KVA_VDEC_GCON_BASE); + MODULE_MFV_LOGD("[VCODEC][DeviceTree] VDEC_IRQ_ID(%d), VENC_IRQ_ID(%d)", + VDEC_IRQ_ID, VENC_IRQ_ID); + } + + /* KVA_VENC_IRQ_STATUS_ADDR = (VAL_ULONG_T)ioremap(VENC_IRQ_STATUS_addr, 4); */ + /* KVA_VENC_IRQ_ACK_ADDR = (VAL_ULONG_T)ioremap(VENC_IRQ_ACK_addr, 4); */ + + spin_lock_irqsave(&LockDecHWCountLock, ulFlagsLockHW); + gu4LockDecHWCount = 0; + spin_unlock_irqrestore(&LockDecHWCountLock, ulFlagsLockHW); + + spin_lock_irqsave(&LockEncHWCountLock, ulFlagsLockHW); + gu4LockEncHWCount = 0; + spin_unlock_irqrestore(&LockEncHWCountLock, ulFlagsLockHW); + + spin_lock_irqsave(&DecISRCountLock, ulFlagsISR); + gu4DecISRCount = 0; + spin_unlock_irqrestore(&DecISRCountLock, ulFlagsISR); + + spin_lock_irqsave(&EncISRCountLock, ulFlagsISR); + gu4EncISRCount = 0; + spin_unlock_irqrestore(&EncISRCountLock, ulFlagsISR); + + mutex_lock(&VdecPWRLock); + gu4VdecPWRCounter = 0; + mutex_unlock(&VdecPWRLock); + + mutex_lock(&VencPWRLock); + gu4VencPWRCounter = 0; + mutex_unlock(&VencPWRLock); + + mutex_lock(&IsOpenedLock); + if (VAL_FALSE == bIsOpened) { + bIsOpened = VAL_TRUE; + /* vcodec_probe(NULL); */ + } + mutex_unlock(&IsOpenedLock); + + mutex_lock(&VdecHWLock); + gu4VdecLockThreadId = 0; + grVcodecDecHWLock.pvHandle = 0; + grVcodecDecHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; + grVcodecDecHWLock.rLockedTime.u4Sec = 0; + grVcodecDecHWLock.rLockedTime.u4uSec = 0; + mutex_unlock(&VdecHWLock); + + mutex_lock(&VencHWLock); + grVcodecEncHWLock.pvHandle = 0; + grVcodecEncHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; + grVcodecEncHWLock.rLockedTime.u4Sec = 0; + grVcodecEncHWLock.rLockedTime.u4uSec = 0; + mutex_unlock(&VencHWLock); + + /* HWLockEvent part */ + mutex_lock(&DecHWLockEventTimeoutLock); + DecHWLockEvent.pvHandle = "DECHWLOCK_EVENT"; + DecHWLockEvent.u4HandleSize = sizeof("DECHWLOCK_EVENT") + 1; + DecHWLockEvent.u4TimeoutMs = 1; + mutex_unlock(&DecHWLockEventTimeoutLock); + eValHWLockRet = eVideoCreateEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValHWLockRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] create dec hwlock event error\n"); + } + + mutex_lock(&EncHWLockEventTimeoutLock); + EncHWLockEvent.pvHandle = "ENCHWLOCK_EVENT"; + EncHWLockEvent.u4HandleSize = sizeof("ENCHWLOCK_EVENT") + 1; + EncHWLockEvent.u4TimeoutMs = 1; + mutex_unlock(&EncHWLockEventTimeoutLock); + eValHWLockRet = eVideoCreateEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValHWLockRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] create enc hwlock event error\n"); + } + + /* IsrEvent part */ + spin_lock_irqsave(&DecIsrLock, ulFlags); + DecIsrEvent.pvHandle = "DECISR_EVENT"; + DecIsrEvent.u4HandleSize = sizeof("DECISR_EVENT") + 1; + DecIsrEvent.u4TimeoutMs = 1; + spin_unlock_irqrestore(&DecIsrLock, ulFlags); + eValHWLockRet = eVideoCreateEvent(&DecIsrEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValHWLockRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] create dec isr event error\n"); + } + + spin_lock_irqsave(&EncIsrLock, ulFlags); + EncIsrEvent.pvHandle = "ENCISR_EVENT"; + EncIsrEvent.u4HandleSize = sizeof("ENCISR_EVENT") + 1; + EncIsrEvent.u4TimeoutMs = 1; + spin_unlock_irqrestore(&EncIsrLock, ulFlags); + eValHWLockRet = eVideoCreateEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValHWLockRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] create enc isr event error\n"); + } + + MODULE_MFV_LOGD("vcodec_driver_init Done\n"); + +#ifdef CONFIG_MTK_HIBERNATION + register_swsusp_restore_noirq_func(ID_M_VCODEC, vcodec_pm_restore_noirq, NULL); +#endif + + return platform_driver_register(&vcodec_driver); +} + +static void __exit vcodec_driver_exit(void) +{ + VAL_RESULT_T eValHWLockRet; + + MODULE_MFV_LOGD("vcodec_driver_exit\n"); + + mutex_lock(&IsOpenedLock); + if (VAL_TRUE == bIsOpened) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + bIsOpened = VAL_FALSE; + } + mutex_unlock(&IsOpenedLock); + + cdev_del(vcodec_cdev); + unregister_chrdev_region(vcodec_devno, 1); + + /* [TODO] iounmap the following? */ +#if 0 + iounmap((void *)KVA_VENC_IRQ_STATUS_ADDR); + iounmap((void *)KVA_VENC_IRQ_ACK_ADDR); +#endif + + free_irq(VENC_IRQ_ID, NULL); + free_irq(VDEC_IRQ_ID, NULL); + + /* MT6589_HWLockEvent part */ + eValHWLockRet = eVideoCloseEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValHWLockRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] close dec hwlock event error\n"); + } + + eValHWLockRet = eVideoCloseEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValHWLockRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] close enc hwlock event error\n"); + } + + /* MT6589_IsrEvent part */ + eValHWLockRet = eVideoCloseEvent(&DecIsrEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValHWLockRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] close dec isr event error\n"); + } + + eValHWLockRet = eVideoCloseEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); + if (VAL_RESULT_NO_ERROR != eValHWLockRet) { + /* Add one line comment for avoid kernel coding style, WARNING:BRACES: */ + MODULE_MFV_LOGE("[VCODEC][ERROR] close enc isr event error\n"); + } + +#ifdef CONFIG_MTK_HIBERNATION + unregister_swsusp_restore_noirq_func(ID_M_VCODEC); +#endif + + platform_driver_unregister(&vcodec_driver); +} + +module_init(vcodec_driver_init); +module_exit(vcodec_driver_exit); +MODULE_AUTHOR("Legis, Lu "); +MODULE_DESCRIPTION("Jade Vcodec Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/videocodec/mt6755/videocodec_kernel_driver.h b/drivers/misc/mediatek/videocodec/mt6755/videocodec_kernel_driver.h new file mode 100644 index 0000000000000000000000000000000000000000..debfd4114704f8d7a56e6e3154bfc372bf02bd56 --- /dev/null +++ b/drivers/misc/mediatek/videocodec/mt6755/videocodec_kernel_driver.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __VCODEC_DRIVER_H__ +#define __VCODEC_DRIVER_H__ + +#define MFV_IOC_MAGIC 'M' + +/* below is control message */ +#define MFV_TEST_CMD _IO(MFV_IOC_MAGIC, 0x00) +#define MFV_INIT_CMD _IO(MFV_IOC_MAGIC, 0x01) +#define MFV_DEINIT_CMD _IO(MFV_IOC_MAGIC, 0x02) +#define MFV_SET_CMD_CMD _IOW(MFV_IOC_MAGIC, 0x03, unsigned int) /* P_MFV_DRV_CMD_QUEUE_T */ +#define MFV_SET_PWR_CMD _IOW(MFV_IOC_MAGIC, 0x04, unsigned int) /* HAL_POWER_T * */ +#define MFV_SET_ISR_CMD _IOW(MFV_IOC_MAGIC, 0x05, unsigned int) /* HAL_ISR_T * */ +#define MFV_ALLOC_MEM_CMD _IOW(MFV_IOC_MAGIC, 0x06, unsigned int) +#define MFV_FREE_MEM_CMD _IOW(MFV_IOC_MAGIC, 0x07, unsigned int) +#define MFV_MAKE_PMEM_TO_NONCACHED _IOW(MFV_IOC_MAGIC, 0x08, unsigned int) /* unsigned int* */ +#define MFV_ALLOC_INT_MEM_CMD _IOW(MFV_IOC_MAGIC, 0x09, unsigned int) /* VAL_INTMEM_T* */ +#define MFV_FREE_INT_MEM_CMD _IOW(MFV_IOC_MAGIC, 0x0a, unsigned int) /* VAL_INTMEM_T* */ +#define VCODEC_WAITISR _IOW(MFV_IOC_MAGIC, 0x0b, unsigned int) /* HAL_POWER_T * */ +#define VCODEC_LOCKHW _IOW(MFV_IOC_MAGIC, 0x0d, unsigned int) /* VAL_HW_LOCK_T * */ +#define VCODEC_PMEM_FLUSH _IOW(MFV_IOC_MAGIC, 0x10, unsigned int) /* HAL_POWER_T * */ +#define VCODEC_PMEM_CLEAN _IOW(MFV_IOC_MAGIC, 0x11, unsigned int) /* HAL_POWER_T * */ +#define VCODEC_INC_SYSRAM_USER _IOW(MFV_IOC_MAGIC, 0x13, unsigned int) /* VAL_UINT32_T * */ +#define VCODEC_DEC_SYSRAM_USER _IOW(MFV_IOC_MAGIC, 0x14, unsigned int) /* VAL_UINT32_T * */ +#define VCODEC_INC_ENC_EMI_USER _IOW(MFV_IOC_MAGIC, 0x15, unsigned int) /* VAL_UINT32_T * */ +#define VCODEC_DEC_ENC_EMI_USER _IOW(MFV_IOC_MAGIC, 0x16, unsigned int) /* VAL_UINT32_T * */ +#define VCODEC_INC_DEC_EMI_USER _IOW(MFV_IOC_MAGIC, 0x17, unsigned int) /* VAL_UINT32_T * */ +#define VCODEC_DEC_DEC_EMI_USER _IOW(MFV_IOC_MAGIC, 0x18, unsigned int) /* VAL_UINT32_T * */ +#define VCODEC_INITHWLOCK _IOW(MFV_IOC_MAGIC, 0x20, unsigned int) /* VAL_VCODEC_OAL_HW_REGISTER_T * */ +#define VCODEC_DEINITHWLOCK _IOW(MFV_IOC_MAGIC, 0x21, unsigned int) /* VAL_VCODEC_OAL_HW_REGISTER_T * */ +#define VCODEC_ALLOC_NON_CACHE_BUFFER _IOW(MFV_IOC_MAGIC, 0x22, unsigned int) /* VAL_MEMORY_T * */ +#define VCODEC_FREE_NON_CACHE_BUFFER _IOW(MFV_IOC_MAGIC, 0x23, unsigned int) /* VAL_MEMORY_T * */ +#define VCODEC_SET_THREAD_ID _IOW(MFV_IOC_MAGIC, 0x24, unsigned int) /* VAL_VCODEC_THREAD_ID_T * */ +#define VCODEC_SET_SYSRAM_INFO _IOW(MFV_IOC_MAGIC, 0x25, unsigned int) /* VAL_INTMEM_T * */ +#define VCODEC_GET_SYSRAM_INFO _IOW(MFV_IOC_MAGIC, 0x26, unsigned int) /* VAL_INTMEM_T * */ +#define VCODEC_INC_PWR_USER _IOW(MFV_IOC_MAGIC, 0x27, unsigned int) /* HAL_POWER_T * */ +#define VCODEC_DEC_PWR_USER _IOW(MFV_IOC_MAGIC, 0x28, unsigned int) /* HAL_POWER_T * */ +#define VCODEC_GET_CPU_LOADING_INFO _IOW(MFV_IOC_MAGIC, 0x29, unsigned int) /* VAL_VCODEC_CPU_LOADING_INFO_T * */ +#define VCODEC_GET_CORE_LOADING _IOW(MFV_IOC_MAGIC, 0x30, unsigned int) /* VAL_VCODEC_CORE_LOADING_T * */ +#define VCODEC_GET_CORE_NUMBER _IOW(MFV_IOC_MAGIC, 0x31, unsigned int) /* int * */ +#define VCODEC_SET_CPU_OPP_LIMIT _IOW(MFV_IOC_MAGIC, 0x32, unsigned int) /* VAL_VCODEC_CPU_OPP_LIMIT_T * */ +#define VCODEC_UNLOCKHW _IOW(MFV_IOC_MAGIC, 0x33, unsigned int) /* VAL_HW_LOCK_T * */ +#define VCODEC_MB _IOW(MFV_IOC_MAGIC, 0x34, unsigned int) /* VAL_UINT32_T * */ +#define VCODEC_SET_LOG_COUNT _IOW(MFV_IOC_MAGIC, 0x35, unsigned int) /* VAL_BOOL_T * */ + + +/* #define MFV_GET_CACHECTRLADDR_CMD _IOR(MFV_IOC_MAGIC, 0x06, int) */ + +#endif /* __VCODEC_DRIVER_H__ */ diff --git a/drivers/misc/mediatek/watchpoint/mt6755/Makefile b/drivers/misc/mediatek/watchpoint/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e786bafd92e9c83f4e9561f593c1d617cdaa688d --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ifeq ($(CONFIG_ARM64), y) +obj-y += aarch64/ +else +obj-y += aarch32/ +endif diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch32/Makefile b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..19019cdb275756b084666c348f9d4d952f1bbaa6 --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += hw_watchpoint_aarch32.o +obj-y += mt_dbg_aarch32.o + +ifeq ($(CONFIG_MT_ENG_BUILD),y) +CFLAGS_mt_dbg_aarch32.o := -DDEBUG +CFLAGS_hw_watchpoint_aarch32.o := -DDEBUG +endif diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch32/hw_watchpoint_aarch32.c b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/hw_watchpoint_aarch32.c new file mode 100644 index 0000000000000000000000000000000000000000..c8fd6348e9e3dda469cbf6e015fff8dbfc8182c6 --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/hw_watchpoint_aarch32.c @@ -0,0 +1,601 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include "hw_watchpoint_aarch32.h" +#include "mt_dbg_aarch32.h" +#include +#include +#include +#include +#include +#include +#include + +struct wp_trace_context_t wp_tracer; +#ifdef WATCHPOINT_TEST_SUIT +struct wp_event wp_event; +int err; +volatile int my_watch_data2; +int wp_flag; +int my_wp_handler1(phys_addr_t addr) +{ + wp_flag++; + pr_debug("[MTK WP] Access my data from an instruction at %p\n", &addr); + return 0; +} + +int my_wp_handler2(phys_addr_t addr) +{ + pr_debug("[MTK WP] In my_wp_handler2 Access my data from an instruction at %p\n", &addr); + /* trigger exception */ + return 0; +} + +void wp_test1(void) +{ + init_wp_event(&wp_event, (unsigned int)&my_watch_data2, (unsigned int)&my_watch_data2, + WP_EVENT_TYPE_ALL, my_wp_handler1); + err = add_hw_watchpoint(&wp_event); + if (err) { + pr_debug("[MTK WP] add hw watch point failed...\n"); + /* fail to add watchpoing */ + } else { + /* the memory address is under watching */ + pr_debug("[MTK WP] add hw watch point success...\n"); + + /* test del + del_hw_watchpoint(&wp_event); + */ + } + /* test watchpoint */ + my_watch_data2 = 1; +} + +void smp_specific_write(int *p) +{ + *p = 1; + pr_debug("[MTK WP] wite data in specific address ok,addr=0x%p\n", p); +} + +void wp_test2(void) +{ + int i; + int ret; + + wp_flag = 0; + pr_debug("[MTK WP] Init wp.. "); + init_wp_event(&wp_event, (unsigned int)&my_watch_data2, (unsigned int)&my_watch_data2, + WP_EVENT_TYPE_ALL, my_wp_handler1); + err = add_hw_watchpoint(&wp_event); + if (err) { + pr_debug("[MTK WP] add hw watch point failed...\n"); + /* fail to add watchpoing */ + } else { + /* the memory address is under watching */ + pr_debug("[MTK WP] add hw watch point success...\n"); + + /* test del + del_hw_watchpoint(&wp_event); + */ + } + pr_debug("[MTK WP] dump standard dbgsys setting\n"); + for (i = 1; i < num_possible_cpus(); i++) { + ret = cpu_down(i); + if (ret != 0) + pr_debug("[MTK WP] cpu %d power down failed\n", i); + + if (!cpu_online(i)) + pr_debug("[MTK WP] cpu %d already power down\n", i); + } + for (i = 0; i < num_possible_cpus(); i++) { + ret = cpu_up(i); + if (ret != 0) + pr_debug("[MTK WP] cpu %d power up failed\n", i); + + if (cpu_online(i)) + pr_debug("[MTK WP] cpu %d already power up\n", i); + + pr_debug("[MTK WP] dump dbgsys setting restored\n"); +#ifdef DBG_REG_DUMP + dump_dbgregs(i); + print_dbgregs(i); +#endif + ret = + smp_call_function_single(i, (smp_call_func_t) smp_specific_write, + (void *)&my_watch_data2, 1); + if (ret == 0) + pr_debug("[MTK WP] cpu %d, wite data in specific address ok\n", i); + else + pr_debug("[MTK WP] cpu %d, wite data in specific address failed\n", i); + } + + if (wp_flag == num_possible_cpus()) + pr_debug("[MTK WP] Watchpoint item2 verfication pass 0x%x\n", wp_flag); + else + pr_debug("[MTK WP] Watchpoint item2 verfication failed 0x%x\n", wp_flag); +} + +void wp_test3(void) +{ + int i; + int ret; + + wp_flag = 0; + for (i = 0; i < num_possible_cpus(); i++) { + ret = cpu_up(i); + if (ret != 0) + pr_debug("[MTK WP] cpu %d power up failed\n", i); + + if (cpu_online(i)) + pr_debug("[MTK WP] cpu %d already power up\n", i); + + pr_debug("[MTK WP] dump dbgsys setting restored\n"); +#ifdef DBG_REG_DUMP + dump_dbgregs(i); + print_dbgregs(i); +#endif + ret = + smp_call_function_single(i, (smp_call_func_t) smp_specific_write, + (void *)&my_watch_data2, 1); + if (ret == 0) + pr_debug("[MTK WP] cpu %d, wite data in specific address ok\n", i); + else + pr_debug("[MTK WP] cpu %d, wite data in specific address failed\n", i); + } + if (wp_flag == num_possible_cpus()) + pr_debug("[MTK WP] Watchpoint item3 verfication pass 0x%x\n", wp_flag); + else + pr_debug("[MTK WP] Watchpoint item3 verfication failed 0x%x\n", wp_flag); + +} +#endif + +void smp_read_dbgdscr_callback(void *info) +{ + unsigned long tmp; + unsigned long *val = info; + + ARM_DBG_READ(c0, c2, 2, tmp); + *val = tmp; +} + +void smp_write_dbgdscr_callback(void *info) +{ + unsigned long *val = info; + unsigned long tmp = *val; + + ARM_DBG_WRITE(c0, c2, 2, tmp); +} + +void smp_read_dbgoslsr_callback(void *info) +{ + unsigned long tmp; + unsigned long *val = info; + + ARM_DBG_READ(c1, c1, 4, tmp); + *val = tmp; +} + +void smp_write_dbgoslsr_callback(void *info) +{ + unsigned long *val = info; + unsigned long tmp = *val; + + ARM_DBG_WRITE(c1, c1, 4, tmp); +} + +void smp_read_dbgvcr_callback(void *info) +{ + unsigned long tmp; + unsigned long *val = info; + + ARM_DBG_READ(c0, c7, 0, tmp); + *val = tmp; +} + +void smp_write_dbgvcr_callback(void *info) +{ + unsigned long *val = info; + unsigned long tmp = *val; + + ARM_DBG_WRITE(c0, c7, 0, tmp); +} + + + +void smp_read_dbgsdsr_callback(void *info) +{ + unsigned long tmp; + unsigned long *val = info; + + __asm__ __volatile__("mrc p15, 0, %0, c1, c3, 1 @SDSR\n\t":"=r"(tmp)); + *val = tmp; +} + +void smp_write_dbgsdsr_callback(void *info) +{ + unsigned long *val = info; + unsigned long tmp = *val; + + __asm__ __volatile("mcr p15, 0, %0, c1, c3, 1\n\t" : : "r"(tmp)); +} + + + +static spinlock_t wp_lock; + +int register_wp_context(struct wp_trace_context_t **wp_tracer_context) +{ + *wp_tracer_context = &wp_tracer; + return 0; +} + +/* + * enable_hw_watchpoint: Enable the H/W watchpoint. + * Return error code. + */ +int enable_hw_watchpoint(void) +{ + int i; + unsigned int args; + int oslsr; + int dbglsr; + + pr_debug("[MTK WP] Hotplug disable\n"); + cpu_hotplug_disable(); + for (i = 0; i < num_possible_cpus(); i++) { + if (cpu_online(i)) { + smp_call_function_single(i, smp_read_dbgdscr_callback, &args, 1); + pr_debug("[MTK WP] cpu %d, DBGDSCR 0x%x\n", i, args); + if (args & HDBGEN) { + pr_debug + ("[MTK WP] halting debug mode enabled. Unable to access hardware resources.\n"); + return -EPERM; + } + + if (args & MDBGEN) { + /* already enabled */ + pr_debug("[MTK WP] already enabled, DBGDSCR = 0x%x\n", args); + } + cs_cpu_write(wp_tracer.debug_regs[i], DBGLAR, UNLOCK_KEY); + cs_cpu_write(wp_tracer.debug_regs[i], DBGOSLAR, ~UNLOCK_KEY); + args = args | MDBGEN; + smp_call_function_single(i, smp_write_dbgdscr_callback, &args, 1); + smp_call_function_single(i, smp_read_dbgdscr_callback, &args, 1); + smp_call_function_single(i, smp_read_dbgoslsr_callback, &oslsr, 1); + dbglsr = cs_cpu_read(wp_tracer.debug_regs[i], DBGLSR); + pr_debug("[MTK WP] cpu %d, DBGLSR 0x%x, DBGOSLSR 0x%x\n", i, dbglsr, + oslsr); + pr_debug("[MTK WP] cpu %d, DBGDSCR 0x%x. (after set dbgdscr)\n", i, args); + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip enable_hw_watchpoint\n", + i, cpu_online(i)); + } + } + pr_debug("[MTK WP] Hotplug enable\n"); + cpu_hotplug_enable(); + return 0; +} + +/* + * add_hw_watchpoint: add a watch point. + * @wp_event: pointer to the struct wp_event. + * Return error code. + */ +int add_hw_watchpoint(struct wp_event *wp_event) +{ + int ret, i, j; + unsigned long flags; + unsigned int ctl; + + if (!wp_event) + return -EINVAL; + + if (!(wp_event->handler)) + return -EINVAL; + + ret = enable_hw_watchpoint(); + if (ret) + return ret; + + ctl = DBGWCR_VAL; + if (wp_event->type == WP_EVENT_TYPE_READ) + ctl |= LSC_LDR; + else if (wp_event->type == WP_EVENT_TYPE_WRITE) + ctl |= LSC_STR; + else if (wp_event->type == WP_EVENT_TYPE_ALL) + ctl |= LSC_ALL; + else + return -EINVAL; + + spin_lock_irqsave(&wp_lock, flags); + for (i = 0; i < MAX_NR_WATCH_POINT; i++) { + if (!wp_tracer.wp_events[i].in_use) { + wp_tracer.wp_events[i].in_use = 1; + break; + } + } + spin_unlock_irqrestore(&wp_lock, flags); + + if (i == MAX_NR_WATCH_POINT) + return -EAGAIN; + + wp_tracer.wp_events[i].virt = wp_event->virt & ~3; /* enforce word-aligned */ + wp_tracer.wp_events[i].phys = wp_event->phys; /* no use currently */ + wp_tracer.wp_events[i].type = wp_event->type; + wp_tracer.wp_events[i].handler = wp_event->handler; + wp_tracer.wp_events[i].auto_disable = wp_event->auto_disable; + pr_debug("[MTK WP] Hotplug disable\n"); + cpu_hotplug_disable(); + pr_debug("[MTK WP] Add watchpoint %d at address %p\n", i, &(wp_tracer.wp_events[i].virt)); + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write(wp_tracer.debug_regs[j], DBGWVR + (i << 4), + wp_tracer.wp_events[i].virt); + cs_cpu_write(wp_tracer.debug_regs[j], DBGWCR + (i << 4), ctl); + + pr_debug("[MTK WP] cpu %d, DBGWVR%d, &0x%p=0x%x\n", j, i, + wp_tracer.debug_regs[j] + DBGWVR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], DBGWVR + (i << 4))); + + pr_debug("[MTK WP] cpu %d, DBGWCR%d, &0x%p=0x%x\n", j, i, + wp_tracer.debug_regs[j] + DBGWCR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], DBGWCR + (i << 4))); + + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip adding watchpoint\n", j, + cpu_online(j)); + } + } + pr_debug("[MTK WP] Hotplug enable\n"); + cpu_hotplug_enable(); + return 0; +} + +/* + * del_hw_watchpoint: delete a watch point. + * @wp_event: pointer to the struct wp_event. + * Return error code. + */ +int del_hw_watchpoint(struct wp_event *wp_event) +{ + unsigned long flags; + int i, j; + + if (!wp_event) + return -EINVAL; + + pr_debug("[MTK WP] Hotplug disable\n"); + cpu_hotplug_disable(); + spin_lock_irqsave(&wp_lock, flags); + for (i = 0; i < MAX_NR_WATCH_POINT; i++) { + if (wp_tracer.wp_events[i].in_use + && (wp_tracer.wp_events[i].virt == wp_event->virt)) { + wp_tracer.wp_events[i].virt = 0; + wp_tracer.wp_events[i].phys = 0; + wp_tracer.wp_events[i].type = 0; + wp_tracer.wp_events[i].handler = NULL; + wp_tracer.wp_events[i].in_use = 0; + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write(wp_tracer.debug_regs[j], DBGWCR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], + DBGWCR + (i << 4)) & (~WP_EN)); + } + } + break; + } + } + spin_unlock_irqrestore(&wp_lock, flags); + pr_debug("[MTK WP] Hotplug enable\n"); + cpu_hotplug_enable(); + if (i == MAX_NR_WATCH_POINT) + return -EINVAL; + else + return 0; +} + +int watchpoint_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) +{ + unsigned long wfar, daddr, iaddr; + int i, ret, j; +#if defined(CONFIG_ARCH_MT6595) || defined(CONFIG_ARCH_MT6752)\ + || defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || defined(CONFIG_ARCH_MT6753) + /* Notes + *v7 Debug the address of instruction that triggered the watchpoint is in DBGWFAR + *v7.1 Debug the address is in DFAR + */ + asm volatile ("MRC p15, 0, %0, c6, c0, 0\n":"=r" (wfar) : : "cc"); +#else + unsigned cluster_id = raw_smp_processor_id() / get_cluster_core_count(); + + if (cluster_id == 0) + ARM_DBG_READ(c0, c6, 0, wfar); + else if (cluster_id == 1) + ARM_DBG_READ(c0, c6, 0, wfar); +#endif + daddr = addr & ~3; + iaddr = regs->ARM_pc; + pr_debug("[MTK WP] addr = 0x%lx, DBGWFAR/DFAR = 0x%lx\n", (unsigned long)addr, wfar); + pr_debug("[MTK WP] daddr = 0x%lx, iaddr = 0x%lx\n", daddr, iaddr); + + /* update PC to avoid re-execution of the instruction under watching */ + regs->ARM_pc += thumb_mode(regs) ? 2 : 4; + + for (i = 0; i < MAX_NR_WATCH_POINT; i++) { + if (wp_tracer.wp_events[i].in_use && wp_tracer.wp_events[i].virt == (daddr)) { + pr_debug("[MTK WP] Watchpoint %d triggers.\n", i); + if (!(wp_tracer.wp_events[i].handler)) { + pr_debug("[MTK WP] No watchpoint handler. Ignore.\n"); + return 0; + } + if (wp_tracer.wp_events[i].auto_disable) { + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write(wp_tracer.debug_regs[j], + DBGWCR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], + DBGWCR + + (i << 4)) & (~WP_EN)); + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip adding watchpoint auto-disable\n", + j, cpu_online(j)); + } + } + } + ret = wp_tracer.wp_events[i].handler(iaddr); + if (wp_tracer.wp_events[i].auto_disable) { + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write(wp_tracer.debug_regs[j], + DBGWCR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], + DBGWCR + + (i << 4)) | WP_EN); + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip watchpoint auto-disable\n", + j, cpu_online(j)); + } + } + + } + return ret; + } + } + + return 0; +} + +int wp_probe(struct platform_device *pdev) +{ + int ret = 0; + int i; + + pr_debug("[MTK WP] watchpoint_probe\n"); + of_property_read_u32(pdev->dev.of_node, "num", &wp_tracer.nr_dbg); + pr_debug("[MTK WP] get %d debug interface\n", wp_tracer.nr_dbg); + wp_tracer.debug_regs = + kmalloc(sizeof(void *) * (unsigned long)wp_tracer.nr_dbg, GFP_KERNEL); + if (!wp_tracer.debug_regs) { + pr_err("[MTK WP] Failed to allocate watchpoint register array\n"); + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < wp_tracer.nr_dbg; i++) { + wp_tracer.debug_regs[i] = of_iomap(pdev->dev.of_node, i); + if (wp_tracer.debug_regs[i] == NULL) { + pr_debug("[MTK WP] debug_interface %d devicetree mapping failed\n", i); + } else { + pr_debug("[MTK WP] debug_interface %d @ vm:0x%p pm:0x%x\n", i, + wp_tracer.debug_regs[i], + IO_VIRT_TO_PHYS((unsigned int)wp_tracer.debug_regs[i])); + } + } + ARM_DBG_READ(c0, c0, 0, wp_tracer.dbgdidr); + wp_tracer.wp_nr = ((wp_tracer.dbgdidr & (0xf << 28)) >> 28); + wp_tracer.bp_nr = ((wp_tracer.dbgdidr & (0xf << 24)) >> 24); + +out: + return ret; +} + +static const struct of_device_id dbg_of_ids[] = { + {.compatible = "mediatek,mt6755-dbg_debug",}, + {} +}; + +static struct platform_driver wp_driver = { + .probe = wp_probe, + .driver = { + .name = "wp", + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .of_match_table = dbg_of_ids, + }, +}; + + + +#ifdef WATCHPOINT_TEST_SUIT +static ssize_t wp_test_suit_show(struct device_driver *driver, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "==Watchpoint test==\n" + "1. test watchpoints in online cpu\n" + "2. verified all cpu's watchpoint after hotplug\n" + "3. verified all cpu's watchpoing after suspend/resume. Not:you have to run test item 1 or 2 to init watchpoint first\n"); +} + +static ssize_t wp_test_suit_store(struct device_driver *driver, const char *buf, size_t count) +{ + char *p = (char *)buf; + unsigned long int num; + ssize_t ret; + + ret = kstrtoul(p, 10, &num); + if (ret == 0) { + switch (num) { + /* Test watchpoint Function */ + case 1: + wp_test1(); + break; + case 2: + wp_test2(); + break; + case 3: + wp_test3(); + default: + break; + } + } + return count; +} + +DRIVER_ATTR(wp_test_suit, 0664, wp_test_suit_show, wp_test_suit_store); +#endif +static int __init hw_watchpoint_init(void) +{ + int err; +#ifdef WATCHPOINT_TEST_SUIT + int ret; +#endif + spin_lock_init(&wp_lock); + err = platform_driver_register(&wp_driver); + if (err) { + pr_err("[MTK WP] watchpoint registration failed\n"); + return err; + } +#ifdef WATCHPOINT_TEST_SUIT + ret = driver_create_file(&wp_driver.driver, &driver_attr_wp_test_suit); + if (ret) + pr_err("[MTK WP] Fail to create systracker_drv sysfs files"); +#endif +#ifdef CONFIG_ARM_LPAE + hook_fault_code(0x22, watchpoint_handler, SIGTRAP, 0, "watchpoint debug exception"); +#else + hook_fault_code(0x02, watchpoint_handler, SIGTRAP, 0, "watchpoint debug exception"); +#endif + pr_debug("[MTK WP] watchpoint handler init.\n"); + + return 0; +} + +/* not export currently + EXPORT_SYMBOL(add_hw_watchpoint); + */ +arch_initcall(hw_watchpoint_init); diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch32/hw_watchpoint_aarch32.h b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/hw_watchpoint_aarch32.h new file mode 100644 index 0000000000000000000000000000000000000000..4fe7e296fdc4238e7e04b6662bfc16ed0a10eb61 --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/hw_watchpoint_aarch32.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __HW_BREAKPOINT_32_H +#define __HW_BREAKPOINT_32_H +#include +#include +#include +#include + +#define MAX_NR_WATCH_POINT 4 +struct wp_trace_context_t { + void __iomem **debug_regs; + struct wp_event wp_events[MAX_NR_WATCH_POINT]; + unsigned int wp_nr; + unsigned int bp_nr; + unsigned long dbgdidr; + unsigned int nr_dbg; +}; + + + +struct dbgreg_set { + unsigned long regs[28]; +}; +#define SDSR regs[22] +#define DBGVCR regs[21] +#define DBGWCR3 regs[20] +#define DBGWCR2 regs[19] +#define DBGWCR1 regs[18] +#define DBGWCR0 regs[17] +#define DBGWVR3 regs[16] +#define DBGWVR2 regs[15] +#define DBGWVR1 regs[14] +#define DBGWVR0 regs[13] +#define DBGBCR5 regs[12] +#define DBGBCR4 regs[11] +#define DBGBCR3 regs[10] +#define DBGBCR2 regs[9] +#define DBGBCR1 regs[8] +#define DBGBCR0 regs[7] +#define DBGBVR5 regs[6] +#define DBGBVR4 regs[5] +#define DBGBVR3 regs[4] +#define DBGBVR2 regs[3] +#define DBGBVR1 regs[2] +#define DBGBVR0 regs[1] +#define DBGDSCRext regs[0] + +#define DBGWVR 0x800 +#define DBGWCR 0x808 +#define DBGBVR 0x400 +#define DBGBCR 0x408 + +#define DBGLAR 0xFB0 +#define DBGLSR 0xFB4 +#define DBGOSLAR 0x300 +/* +#define NUM_CPU 4 // max cpu# per cluster +*/ + +#define UNLOCK_KEY 0xC5ACCE55 +#define HDBGEN (1 << 14) +#define MDBGEN (1 << 15) +#define DBGWCR_VAL 0x000001E7 +/**/ +#define WP_EN (1 << 0) +#define LSC_LDR (1 << 3) +#define LSC_STR (2 << 3) +#define LSC_ALL (3 << 3) + +/* +#define WATCHPOINT_TEST_SUIT +*/ + +#define dbg_mem_read(addr) readl(IOMEM(addr)) +#define dbg_mem_write(addr, val) mt_reg_sync_writel(val, addr) +#define dbg_reg_copy(offset, base_to, base_from) \ + dbg_mem_write((base_to) + (offset), dbg_mem_read((base_from) + (offset))) + +static inline void cs_cpu_write(void __iomem *addr_base, u32 offset, u32 wdata) +{ + /* TINFO="Write addr %h, with data %h", addr_base+offset, wdata */ + mt_reg_sync_writel(wdata, addr_base + offset); +} + +static inline u32 cs_cpu_read(const void __iomem *addr_base, u32 offset) +{ + u32 actual; + + /* TINFO="Read addr %h, with data %h", addr_base+offset, actual */ + actual = readl(addr_base + offset); + return actual; +} +void smp_read_dbgsdsr_callback(void *info); +void smp_write_dbgsdsr_callback(void *info); +void smp_read_dbgdscr_callback(void *info); +void smp_write_dbgdscr_callback(void *info); +void smp_read_dbgoslsr_callback(void *info); +void smp_write_dbgoslsr_callback(void *info); +void smp_read_dbgvcr_callback(void *info); +void smp_write_dbgvcr_callback(void *info); +int register_wp_context(struct wp_trace_context_t **wp_tracer_context); +void __iomem *get_wp_base(void); +void smp_read_dbgdscr_callback(void *info); +void smp_write_dbgdscr_callback(void *info); +void smp_read_dbgoslsr_callback(void *info); +void smp_write_dbgoslsr_callback(void *info); + +extern unsigned read_clusterid(void); + +#endif /* !__HW_BREAKPOINT_32_H */ diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch32/mt_dbg_aarch32.c b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/mt_dbg_aarch32.c new file mode 100644 index 0000000000000000000000000000000000000000..0f60689eecb73a3a11f060b44e24652b3e644d9c --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/mt_dbg_aarch32.c @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#ifdef CONFIG_SMP +#include +#endif +#include "hw_watchpoint_aarch32.h" +#include "mt_dbg_aarch32.h" + +struct dbgreg_set dbgregs[8]; + +#ifdef DBG_REG_DUMP +void dump_dbgregs(int cpuid) +{ + + struct wp_trace_context_t *wp_context; + int i; + int oslsr; + int dbglsr; + + register_wp_context(&wp_context); + cs_cpu_write(wp_context->debug_regs[cpuid], DBGLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[cpuid], DBGOSLAR, ~UNLOCK_KEY); + smp_call_function_single(cpuid, smp_read_dbgoslsr_callback, &oslsr, 1); + dbglsr = cs_cpu_read(wp_context->debug_regs[cpuid], DBGLSR); + pr_debug("[MTK WP]dump_dbgregs: cpu %d, DBGLSR 0x%x, DBGOSLSR 0x%x\n", cpuid, dbglsr, + oslsr); + + isb(); + + smp_call_function_single(cpuid, smp_read_dbgdscr_callback, &dbgregs[cpuid].DBGDSCRext, 1); + + for (i = 1; i < 1 + (wp_context->bp_nr); i++) { + dbgregs[cpuid].regs[i] = + cs_cpu_read(wp_context->debug_regs[cpuid], (DBGBVR + ((i - 1) << 4))); + } + + for (i = 7; i < 7 + (wp_context->bp_nr); i++) { + dbgregs[cpuid].regs[i] = + cs_cpu_read(wp_context->debug_regs[cpuid], (DBGBCR + ((i - 7) << 4))); + } + + for (i = 13; i < 13 + (wp_context->wp_nr); i++) { + dbgregs[cpuid].regs[i] = + cs_cpu_read(wp_context->debug_regs[cpuid], (DBGWVR + ((i - 13) << 4))); + pr_debug("[MTK WP]dump_dbgregs:DBGWVR &0x%p=0x%x\n", + wp_context->debug_regs[cpuid] + (DBGWVR + ((i - 13) << 4)), + cs_cpu_read(wp_context->debug_regs[cpuid], (DBGWVR + ((i - 13) << 4)))); + } + + for (i = 17; i < 17 + (wp_context->wp_nr); i++) { + dbgregs[cpuid].regs[i] = + cs_cpu_read(wp_context->debug_regs[cpuid], (DBGWCR + ((i - 17) << 4))); + } + + smp_call_function_single(cpuid, smp_read_dbgvcr_callback, &dbgregs[cpuid].DBGVCR, 1); + /* + smp_call_function_single(cpuid,smp_read_dbgsdsr_callback,&dbgregs[cpuid].SDSR,1); + */ + isb(); + +} + +void print_dbgregs(int cpuid) +{ + + pr_debug("[MTK WP] cpu %d, DBGDSCR 0x%lx\n", cpuid, dbgregs[cpuid].DBGDSCRext); + pr_debug("[MTK WP] cpu %d, DBGBVR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR0); + pr_debug("[MTK WP] cpu %d, DBGBVR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR1); + pr_debug("[MTK WP] cpu %d, DBGBVR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR2); + pr_debug("[MTK WP] cpu %d, DBGBVR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR3); + pr_debug("[MTK WP] cpu %d, DBGBVR4 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR4); + pr_debug("[MTK WP] cpu %d, DBGBVR5 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR5); + + pr_debug("[MTK WP] cpu %d, DBGBCR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR0); + pr_debug("[MTK WP] cpu %d, DBGBCR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR1); + pr_debug("[MTK WP] cpu %d, DBGBCR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR2); + pr_debug("[MTK WP] cpu %d, DBGBCR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR3); + pr_debug("[MTK WP] cpu %d, DBGBCR4 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR4); + pr_debug("[MTK WP] cpu %d, DBGBCR5 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR5); + + + pr_debug("[MTK WP] cpu %d, DBGWVR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR0); + pr_debug("[MTK WP] cpu %d, DBGWVR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR1); + pr_debug("[MTK WP] cpu %d, DBGWVR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR2); + pr_debug("[MTK WP] cpu %d, DBGWVR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR3); + + pr_debug("[MTK WP] cpu %d, DBGWCR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR0); + pr_debug("[MTK WP] cpu %d, DBGWCR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR1); + pr_debug("[MTK WP] cpu %d, DBGWCR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR2); + pr_debug("[MTK WP] cpu %d, DBGWCR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR3); + + pr_debug("[MTK WP] cpu %d, DBGVCR 0x%lx\n", cpuid, dbgregs[cpuid].DBGVCR); + pr_debug("[MTK WP] cpu %d, SDSR 0x%lx\n", cpuid, dbgregs[cpuid].SDSR); +} + +#endif + +unsigned int *mt_save_dbg_regs(unsigned int *p, unsigned int cpuid) +{ + struct wp_trace_context_t *wp_context; + + register_wp_context(&wp_context); + cs_cpu_write(wp_context->debug_regs[cpuid], DBGLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[cpuid], DBGOSLAR, ~UNLOCK_KEY); + if (*p == ~0x0) { + pr_err("[MTK WP]restore pointer is NULL\n"); + return 0; + } + + + isb(); + /* save register */ + __asm__ __volatile__("mrc p14, 0, r4, c0, c2, 2 @DBGDSCR_ext\n\t" + "stm %0!, {r4}\n\t" + "mrc p14, 0, r4, c0, c0, 4 @DBGBVR\n\t" + "mrc p14, 0, r5, c0, c1, 4 @DBGBVR\n\t" + "mrc p14, 0, r6, c0, c2, 4 @DBGBVR\n\t" + "mrc p14, 0, r7, c0, c3, 4 @DBGBVR\n\t" + "mrc p14, 0, r8, c0, c4, 4 @DBGBVR\n\t" + "mrc p14, 0, r9, c0, c5, 4 @DBGBVR\n\t" + "stm %0!, {r4-r9}\n\t" + "mrc p14, 0, r4, c0, c0, 5 @DBGBCR\n\t" + "mrc p14, 0, r5, c0, c1, 5 @DBGBCR\n\t" + "mrc p14, 0, r6, c0, c2, 5 @DBGBCR\n\t" + "mrc p14, 0, r7, c0, c3, 5 @DBGBCR\n\t" + "mrc p14, 0, r8, c0, c4, 5 @DBGBCR\n\t" + "mrc p14, 0, r9, c0, c5, 5 @DBGBCR\n\t" + "stm %0!, {r4-r9}\n\t" + "mrc p14, 0, r4, c0, c0, 6 @DBGWVR\n\t" + "mrc p14, 0, r5, c0, c1, 6 @DBGWVR\n\t" + "mrc p14, 0, r6, c0, c2, 6 @DBGWVR\n\t" + "mrc p14, 0, r7, c0, c3, 6 @DBGWVR\n\t" + "stm %0!, {r4-r7}\n\t" + "mrc p14, 0, r4, c0, c0, 7 @DBGWCR\n\t" + "mrc p14, 0, r5, c0, c1, 7 @DBGWCR\n\t" + "mrc p14, 0, r6, c0, c2, 7 @DBGWCR\n\t" + "mrc p14, 0, r7, c0, c3, 7 @DBGWCR\n\t" + "stm %0!, {r4-r7}\n\t" + "mrc p14, 0, r4, c0, c7, 0 @DBGVCR\n\t" "stm %0!, {r4}\n\t":"+r"(p) + : : "r4", "r5", "r6", "r7", "r8", "r9"); + isb(); + + return p; +} + +void mt_restore_dbg_regs(unsigned int *p, unsigned int cpuid) +{ + unsigned int dscr; + struct wp_trace_context_t *wp_context; + + register_wp_context(&wp_context); + /* the dbg container is invalid */ + if (*p == ~0x0) { + pr_err("[MTK WP]restore pointer is NULL\n"); + return; + } + cs_cpu_write(wp_context->debug_regs[cpuid], DBGLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[cpuid], DBGOSLAR, ~UNLOCK_KEY); + + isb(); + + + /* restore register */ + __asm__ __volatile__("ldm %0!, {r4}\n\t" + "mov %1, r4\n\t" + "mcr p14, 0, r4, c0, c2, 2 @DBGDSCR\n\t" + "ldm %0!, {r4-r9}\n\t" + "mcr p14, 0, r4, c0, c0, 4 @DBGBVR\n\t" + "mcr p14, 0, r5, c0, c1, 4 @DBGBVR\n\t" + "mcr p14, 0, r6, c0, c2, 4 @DBGBVR\n\t" + "mcr p14, 0, r7, c0, c3, 4 @DBGBVR\n\t" + "mcr p14, 0, r8, c0, c4, 4 @DBGBVR\n\t" + "mcr p14, 0, r9, c0, c5, 4 @DBGBVR\n\t" + "ldm %0!, {r4-r9}\n\t" + "mcr p14, 0, r4, c0, c0, 5 @DBGBCR\n\t" + "mcr p14, 0, r5, c0, c1, 5 @DBGBCR\n\t" + "mcr p14, 0, r6, c0, c2, 5 @DBGBCR\n\t" + "mcr p14, 0, r7, c0, c3, 5 @DBGBCR\n\t" + "mcr p14, 0, r8, c0, c4, 5 @DBGBCR\n\t" + "mcr p14, 0, r9, c0, c5, 5 @DBGBCR\n\t" + "ldm %0!, {r4-r7}\n\t" + "mcr p14, 0, r4, c0, c0, 6 @DBGWVR\n\t" + "mcr p14, 0, r5, c0, c1, 6 @DBGWVR\n\t" + "mcr p14, 0, r6, c0, c2, 6 @DBGWVR\n\t" + "mcr p14, 0, r7, c0, c3, 6 @DBGWVR\n\t" + "ldm %0!, {r4-r7}\n\t" + "mcr p14, 0, r4, c0, c0, 7 @DBGWCR\n\t" + "mcr p14, 0, r5, c0, c1, 7 @DBGWCR\n\t" + "mcr p14, 0, r6, c0, c2, 7 @DBGWCR\n\t" + "mcr p14, 0, r7, c0, c3, 7 @DBGWCR\n\t" + "ldm %0!, {r4}\n\t" + "mcr p14, 0, r4, c0, c7, 0 @DBGVCR\n\t":"+r"(p), "=r"(dscr) + : : "r4", "r5", "r6", "r7", "r8", "r9"); + /* + cs_cpu_write(wp_context->debug_regs[cpuid], DBGOSLAR ,UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[cpuid], DBGLAR ,~UNLOCK_KEY); + */ + isb(); +} + + + + + +/** to copy dbg registers from FROM to TO within the same cluster. + * DBG_BASE is the common base of 2 cores debug register space. + **/ +void mt_copy_dbg_regs(int to, int from) +{ + unsigned long base_to, base_from; + unsigned long args; + struct wp_trace_context_t *wp_context; + + register_wp_context(&wp_context); + base_to = (unsigned long)wp_context->debug_regs[to]; + base_from = (unsigned long)wp_context->debug_regs[from]; + + /* os unlock */ + cs_cpu_write(wp_context->debug_regs[to], DBGLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[to], DBGOSLAR, ~UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[from], DBGLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[from], DBGOSLAR, ~UNLOCK_KEY); + + isb(); + + smp_call_function_single(from, smp_read_dbgdscr_callback, &args, 1); + smp_call_function_single(to, smp_write_dbgdscr_callback, &args, 1); + isb(); + dbg_reg_copy(DBGBCR, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x10, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x20, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x30, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x40, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x50, base_to, base_from); + + dbg_reg_copy(DBGBVR, base_to, base_from); + dbg_reg_copy(DBGBVR + 0x10, base_to, base_from); + dbg_reg_copy(DBGBVR + 0x20, base_to, base_from); + dbg_reg_copy(DBGBVR + 0x30, base_to, base_from); + dbg_reg_copy(DBGBVR + 0x40, base_to, base_from); + dbg_reg_copy(DBGBVR + 0x50, base_to, base_from); + + + dbg_reg_copy(DBGWVR, base_to, base_from); + dbg_reg_copy(DBGWVR + 0x10, base_to, base_from); + dbg_reg_copy(DBGWVR + 0x20, base_to, base_from); + dbg_reg_copy(DBGWVR + 0x30, base_to, base_from); + + dbg_reg_copy(DBGWCR, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x10, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x20, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x30, base_to, base_from); + + smp_call_function_single(from, smp_read_dbgvcr_callback, &args, 1); + ARM_DBG_WRITE(c0, c7, 0, args); + isb(); +} + + + +#ifdef CONFIG_SMP +int __cpuinit dbgregs_hotplug_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + unsigned int this_cpu = (unsigned int)hcpu; + unsigned long args; + struct wp_trace_context_t *wp_context; + + register_wp_context(&wp_context); + cs_cpu_write(wp_context->debug_regs[this_cpu], DBGLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[this_cpu], DBGOSLAR, ~UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[0], DBGLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[0], DBGOSLAR, ~UNLOCK_KEY); + args = args & 0xf; +#ifdef DBG_REG_DUMP + pr_debug("[MTK WP] cpu %x do %s,action: 0x%lx\n", this_cpu, __func__, action); +#endif + switch (action) { + case CPU_STARTING: +#ifdef DBG_REG_DUMP + pr_debug("[MTK WP] cpu %x do %s, CPU0's _MDSCR_EL1=0x%lx, action 0x%lx\n", + this_cpu, __func__, args, action); +#endif + cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (0 << 4)); + smp_call_function_single(0, smp_read_dbgdscr_callback, &args, 1); + ARM_DBG_WRITE(c0, c2, 2, args); + ARM_DBG_WRITE(c0, c0, 6, cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (0 << 4))); + ARM_DBG_WRITE(c0, c1, 6, cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (1 << 4))); + ARM_DBG_WRITE(c0, c2, 6, cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (2 << 4))); + ARM_DBG_WRITE(c0, c3, 6, cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (3 << 4))); + + ARM_DBG_WRITE(c0, c0, 7, cs_cpu_read(wp_context->debug_regs[0], DBGWCR + (0 << 4))); + ARM_DBG_WRITE(c0, c1, 7, cs_cpu_read(wp_context->debug_regs[0], DBGWCR + (1 << 4))); + ARM_DBG_WRITE(c0, c2, 7, cs_cpu_read(wp_context->debug_regs[0], DBGWCR + (2 << 4))); + ARM_DBG_WRITE(c0, c3, 7, cs_cpu_read(wp_context->debug_regs[0], DBGWCR + (3 << 4))); + + ARM_DBG_WRITE(c0, c0, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (0 << 4))); + ARM_DBG_WRITE(c0, c1, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (1 << 4))); + ARM_DBG_WRITE(c0, c2, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (2 << 4))); + ARM_DBG_WRITE(c0, c3, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (3 << 4))); + ARM_DBG_WRITE(c0, c4, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (4 << 4))); + ARM_DBG_WRITE(c0, c5, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (5 << 4))); + + ARM_DBG_WRITE(c0, c0, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (0 << 4))); + ARM_DBG_WRITE(c0, c1, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (1 << 4))); + ARM_DBG_WRITE(c0, c2, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (2 << 4))); + ARM_DBG_WRITE(c0, c3, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (3 << 4))); + ARM_DBG_WRITE(c0, c4, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (4 << 4))); + ARM_DBG_WRITE(c0, c5, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (5 << 4))); + isb(); + smp_call_function_single(0, smp_read_dbgvcr_callback, &args, 1); + ARM_DBG_WRITE(c0, c7, 0, args); + /* + smp_call_function_single(0,smp_read_dbgsdsr_callback,&args,1); + smp_write_dbgsdsr_callback(&args); + */ + break; + + default: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block cpu_nfb __cpuinitdata = { + .notifier_call = dbgregs_hotplug_callback +}; + +static int __init regs_backup(void) +{ + + register_cpu_notifier(&cpu_nfb); + + return 0; +} + +module_init(regs_backup); +#endif diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch32/mt_dbg_aarch32.h b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/mt_dbg_aarch32.h new file mode 100644 index 0000000000000000000000000000000000000000..050804874bbebe56d0f956f9010633dec19999c8 --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch32/mt_dbg_aarch32.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_DBG_H +#define __MT_DBG_H +/* #define DBG_REG_DUMP */ +unsigned int *mt_save_dbg_regs(unsigned int *p, unsigned int cpuid); +void mt_restore_dbg_regs(unsigned int *p, unsigned int cpuid); +void mt_copy_dbg_regs(int to, int from); +#ifdef DBG_REG_DUMP +void dump_dbgregs(int cpuid); +void print_dbgregs(int cpuid); + +#endif +extern int get_cluster_core_count(void); +#endif /* !__HW_BREAKPOINT_H */ diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch64/Makefile b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d0557d05d9f236dc5c365fc15916283e7353560b --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +obj-y += hw_watchpoint_aarch64.o +obj-y += mt_dbg_aarch64.o + +ifeq ($(CONFIG_MT_ENG_BUILD),y) +CFLAGS_mt_dbg_aarch64.o := -DDEBUG +CFLAGS_hw_watchpoint_aarch64.o := -DDEBUG +endif diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch64/hw_watchpoint_aarch64.c b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/hw_watchpoint_aarch64.c new file mode 100644 index 0000000000000000000000000000000000000000..cfd46685b414e53ba1aa78887d70aa58d3627d92 --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/hw_watchpoint_aarch64.c @@ -0,0 +1,612 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include "hw_watchpoint_aarch64.h" +#include "mt_dbg_aarch64.h" +#include +#include +#include +#include +#include +#include +#include +#include + +struct wp_trace_context_t wp_tracer; +#ifdef WATCHPOINT_TEST_SUIT +struct wp_event wp_event; +int err; +volatile int my_watch_data; +int wp_flag; +int my_wp_handler1(phys_addr_t addr) +{ + wp_flag++; + pr_debug("[MTK WP] Access my data from an instruction at %p\n", &addr); + return 0; +} + +int my_wp_handler2(phys_addr_t addr) +{ + + pr_debug("[MTK WP] In my_wp_handler2 Access my data from an instruction at %p\n", &addr); + /* trigger exception */ + return 0; +} + +void wp_test1(void) +{ + int i; + + init_wp_event(&wp_event, (unsigned long)&my_watch_data, (unsigned long)&my_watch_data, + WP_EVENT_TYPE_ALL, my_wp_handler1); + err = add_hw_watchpoint(&wp_event); + if (err) + /* fail to add watchpoing */ + pr_debug("[MTK WP] add hw watch point failed...\n"); + else + /* the memory address is under watching */ + pr_debug("[MTK WP] add hw watch point success...\n"); + + for (i = 0; i < num_possible_cpus(); i++) { +#ifdef DBG_REG_DUMP + dump_dbgregs(i); + print_dbgregs(i); +#endif + } + pr_debug("start to access my_watch_data\n"); + /* test watchpoint */ + my_watch_data = 1; + +} + +void smp_specific_write(int *p) +{ + *p = 1; + pr_debug("[MTK WP] wite data in specific address ok,addr=0x%p\n", p); +} + +void wp_test2(void) +{ + int i; + int ret = 0; + + wp_flag = 0; + pr_debug("[MTK WP] Init wp.. "); + init_wp_event(&wp_event, (unsigned long)&my_watch_data, (unsigned long)&my_watch_data, + WP_EVENT_TYPE_ALL, my_wp_handler1); + err = add_hw_watchpoint(&wp_event); + if (err) { + pr_debug("[MTK WP] add hw watch point failed...\n"); + /* fail to add watchpoing */ + } else { + /* the memory address is under watching */ + pr_debug("[MTK WP] add hw watch point success...\n"); + + } + pr_debug("[MTK WP] dump standard dbgsys setting\n"); + for (i = 1; i < num_possible_cpus(); i++) { + ret = cpu_down(i); /* FIXME Walkround for build error */ + if (ret != 0) + pr_debug("[MTK WP] cpu %d power down failed\n", i); + if (!cpu_online(i)) + pr_debug("[MTK WP] cpu %d already power down\n", i); + } + for (i = 0; i < num_possible_cpus(); i++) { + ret = cpu_up(i); + if (ret != 0) + pr_debug("[MTK WP] cpu %d power up failed\n", i); + if (cpu_online(i)) + pr_debug("[MTK WP] cpu %d already power up\n", i); + + pr_debug("[MTK WP] dump dbgsys setting restored\n"); +#ifdef DBG_REG_DUMP + dump_dbgregs(i); + print_dbgregs(i); +#endif + ret = + smp_call_function_single(i, (smp_call_func_t) smp_specific_write, + (void *)&my_watch_data, 1); + if (ret == 0) + pr_debug("[MTK WP] cpu %d, wite data in specific address ok\n", i); + else + pr_debug("[MTK WP] cpu %d, wite data in specific address failed\n", i); + } + if (wp_flag == num_possible_cpus()) + pr_debug("[MTK WP] Watchpoint item2 verfication pass 0x%x\n", wp_flag); + else + pr_debug("[MTK WP] Watchpoint item2 verfication failed 0x%x\n", wp_flag); +} + +void wp_test3(void) +{ + int i; + int ret; + + wp_flag = 0; + for (i = 0; i < num_possible_cpus(); i++) { + ret = cpu_up(i); + if (ret != 0) + pr_debug("[MTK WP] cpu %d power up failed\n", i); + if (cpu_online(i)) + pr_debug("[MTK WP] cpu %d already power up\n", i); + + pr_debug("[MTK WP] dump dbgsys setting restored\n"); +#ifdef DBG_REG_DUMP + dump_dbgregs(i); + print_dbgregs(i); +#endif + ret = + smp_call_function_single(i, (smp_call_func_t) smp_specific_write, + (void *)&my_watch_data, 1); + if (ret == 0) + pr_debug("[MTK WP] cpu %d, wite data in specific address ok\n", i); + else + pr_debug("[MTK WP] cpu %d, wite data in specific address failed\n", i); + } + if (wp_flag == num_possible_cpus()) + pr_debug("[MTK WP] Watchpoint item3 verfication pass 0x%x\n", wp_flag); + else + pr_debug("[MTK WP] Watchpoint item3 verfication failed 0x%x\n", wp_flag); +} +#endif + +void smp_read_MDSCR_EL1_callback(void *info) +{ + unsigned int tmp; + unsigned int *val = info; + + asm volatile ("mrs %0, MDSCR_EL1":"=r" (tmp)); + *val = tmp; +} + +void smp_write_MDSCR_EL1_callback(void *info) +{ + unsigned int *val = info; + unsigned int tmp = *val; + + asm volatile ("msr MDSCR_EL1, %0" : : "r" (tmp)); +} + +void smp_read_OSLSR_EL1_callback(void *info) +{ + unsigned int tmp; + unsigned int *val = info; + + asm volatile ("mrs %0, OSLSR_EL1":"=r" (tmp)); + *val = tmp; +} + +static spinlock_t wp_lock; + +int register_wp_context(struct wp_trace_context_t **wp_tracer_context) +{ + *wp_tracer_context = &wp_tracer; + return 0; +} + +/* + * enable_hw_watchpoint: Enable the H/W watchpoint. + * Return error code. + */ +int enable_hw_watchpoint(void) +{ + int i; + unsigned int args; + int oslsr_el1; + int edlsr; + + pr_debug("[MTK WP] Hotplug disable\n"); + cpu_hotplug_disable(); + for (i = 0; i < num_possible_cpus(); i++) { + if (cpu_online(i)) { + cs_cpu_write(wp_tracer.debug_regs[i], EDLAR, UNLOCK_KEY); + cs_cpu_write(wp_tracer.debug_regs[i], OSLAR_EL1, ~UNLOCK_KEY); + args = cs_cpu_read(wp_tracer.debug_regs[i], EDSCR); + + pr_debug("[MTK WP] cpu %d, EDSCR &0x%lx= 0x%x\n", i, + ((vmalloc_to_pfn((void *)wp_tracer.debug_regs[i]) << 12) + EDSCR), + args); + if (args & HDE) { + pr_debug + ("[MTK WP] halting debug mode enabled. Unable to access hardware resources.\n"); + return -EPERM; + } + smp_call_function_single(i, smp_read_MDSCR_EL1_callback, &args, 1); + pr_debug("[MTK WP] cpu %d, MDSCR 0x%x\n", i, args); + if (args & MDBGEN) { + /* already enabled */ + pr_debug("[MTK WP] already enabled, MDSCR = 0x%x\n", args); + } + /* + * Since Watchpoint taken from EL1 to EL1, so we have to enable KDE. + * refer ARMv8 architecture spec section - + * D2.4.1 Enabling debug exceptions from the current Exception level + */ + args = args | MDBGEN | KDE; + smp_call_function_single(i, smp_write_MDSCR_EL1_callback, &args, 1); + smp_call_function_single(i, smp_read_MDSCR_EL1_callback, &args, 1); + smp_call_function_single(i, smp_read_OSLSR_EL1_callback, &oslsr_el1, 1); + edlsr = cs_cpu_read(wp_tracer.debug_regs[i], EDLSR); + pr_debug("[MTK WP] cpu %d, EDLSR 0x%x, OSLSR_EL1 0x%x\n", i, edlsr, + oslsr_el1); + pr_debug("[MTK WP] cpu %d, MDSCR_EL1 0x%x. (after set MDSCR_EL1)\n", i, + args); + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip enable_hw_watchpoint\n", + i, cpu_online(i)); + } + } + pr_debug("[MTK WP] Hotplug enable\n"); + cpu_hotplug_enable(); + return 0; +} + + +void reset_watchpoint(void) +{ + int j; + int i; + unsigned int args; + + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write(wp_tracer.debug_regs[j], EDLAR, UNLOCK_KEY); + cs_cpu_write(wp_tracer.debug_regs[j], OSLAR_EL1, ~UNLOCK_KEY); + args = cs_cpu_read(wp_tracer.debug_regs[j], EDSCR); + pr_debug("[MTK WP] Reset flow cpu %d, EDSCR 0x%x\n", j, args); + if (args & HDE) { + pr_debug("[MTK WP]Reset flow halting debug mode enabled. Unable to reset hardware resources.\n"); + cs_cpu_write(wp_tracer.debug_regs[j], EDLAR, ~UNLOCK_KEY); + cs_cpu_write(wp_tracer.debug_regs[j], OSLAR_EL1, UNLOCK_KEY); + return; + } + for (i = 0; i < wp_tracer.wp_nr; i++) { + cs_cpu_write_64(wp_tracer.debug_regs[j], DBGWVR + (i << 4), 0); + cs_cpu_write(wp_tracer.debug_regs[j], DBGWCR + (i << 4), 0); + pr_debug("[MTK WP] Reset flow cpu %d, DBGWVR%d, &0x%p=0x%lx\n", j, + i, wp_tracer.debug_regs[j] + DBGWVR + (i << 4), + cs_cpu_read_64(wp_tracer.debug_regs[j], + DBGWVR + (i << 4))); + pr_debug("[MTK WP] Reset flow cpu %d, DBGWCR%d, &0x%p=0x%x\n", j, + i, wp_tracer.debug_regs[j] + DBGWCR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], DBGWCR + (i << 4))); + } + for (i = 0; i < wp_tracer.bp_nr; i++) { + cs_cpu_write_64(wp_tracer.debug_regs[j], DBGBVR + (i << 4), 0); + cs_cpu_write(wp_tracer.debug_regs[j], DBGBCR + (i << 4), 0); + pr_debug("[MTK WP] Reset flow cpu %d, DBGBVR%d, &0x%p=0x%lx\n", j, + i, wp_tracer.debug_regs[j] + DBGBVR + (i << 4), + cs_cpu_read_64(wp_tracer.debug_regs[j], + DBGBVR + (i << 4))); + pr_debug("[MTK WP] Reset flow cpu %d, DBGBCR%d, &0x%p=0x%x\n", j, + i, wp_tracer.debug_regs[j] + DBGBCR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], DBGBCR + (i << 4))); + } + cs_cpu_write(wp_tracer.debug_regs[j], EDLAR, ~UNLOCK_KEY); + cs_cpu_write(wp_tracer.debug_regs[j], OSLAR_EL1, UNLOCK_KEY); + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip adding watchpoint\n", j, + cpu_online(j)); + } + } +} + + + +/* + * add_hw_watchpoint: add a watch point. + * @wp_event: pointer to the struct wp_event. + * Return error code. + */ +int add_hw_watchpoint(struct wp_event *wp_event) +{ + int ret, i, j; + unsigned long flags; + unsigned int ctl; + + if (!wp_event) + return -EINVAL; + + if (!(wp_event->handler)) + return -EINVAL; + + ret = enable_hw_watchpoint(); + if (ret) + return ret; + + ctl = DBGWCR_VAL; + if (wp_event->type == WP_EVENT_TYPE_READ) + ctl |= LSC_LDR; + else if (wp_event->type == WP_EVENT_TYPE_WRITE) + ctl |= LSC_STR; + else if (wp_event->type == WP_EVENT_TYPE_ALL) + ctl |= LSC_ALL; + else + return -EINVAL; + + spin_lock_irqsave(&wp_lock, flags); + for (i = 0; i < MAX_NR_WATCH_POINT; i++) { + if (!wp_tracer.wp_events[i].in_use) { + wp_tracer.wp_events[i].in_use = 1; + break; + } + if (wp_tracer.wp_events[i].virt == (wp_event->virt & ~3)) { + pr_err("This address have been watched in %d's watchpoint\n", i); + spin_unlock_irqrestore(&wp_lock, flags); + return -EAGAIN; + } + } + spin_unlock_irqrestore(&wp_lock, flags); + + if (i == MAX_NR_WATCH_POINT) + return -EAGAIN; + + wp_tracer.wp_events[i].virt = wp_event->virt & ~3; /* enforce word-aligned */ + wp_tracer.wp_events[i].phys = wp_event->phys; /* no use currently */ + wp_tracer.wp_events[i].type = wp_event->type; + wp_tracer.wp_events[i].handler = wp_event->handler; + wp_tracer.wp_events[i].auto_disable = wp_event->auto_disable; + pr_debug("[MTK WP] Hotplug disable\n"); + cpu_hotplug_disable(); + pr_debug("[MTK WP] Add watchpoint %d at address %p\n", i, &(wp_tracer.wp_events[i].virt)); + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write_64(wp_tracer.debug_regs[j], DBGWVR + (i << 4), + wp_tracer.wp_events[i].virt); + cs_cpu_write(wp_tracer.debug_regs[j], DBGWCR + (i << 4), ctl); + + pr_debug("[MTK WP] cpu %d, DBGWVR%d, &0x%p=0x%lx\n", j, i, + wp_tracer.debug_regs[j] + DBGWVR + (i << 4), + cs_cpu_read_64(wp_tracer.debug_regs[j], DBGWVR + (i << 4))); + + pr_debug("[MTK WP] cpu %d, DBGWCR%d, &0x%p=0x%x\n", j, i, + wp_tracer.debug_regs[j] + DBGWCR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], DBGWCR + (i << 4))); + + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip adding watchpoint\n", j, + cpu_online(j)); + } + } + pr_debug("[MTK WP] Hotplug enable\n"); + cpu_hotplug_enable(); + return 0; +} + +/* + * del_hw_watchpoint: delete a watch point. + * @wp_event: pointer to the struct wp_event. + * Return error code. + */ +int del_hw_watchpoint(struct wp_event *wp_event) +{ + unsigned long flags; + int i, j; + + if (!wp_event) + return -EINVAL; + + pr_debug("[MTK WP] Hotplug disable\n"); + cpu_hotplug_disable(); + spin_lock_irqsave(&wp_lock, flags); + for (i = 0; i < MAX_NR_WATCH_POINT; i++) { + if (wp_tracer.wp_events[i].in_use + && (wp_tracer.wp_events[i].virt == wp_event->virt)) { + wp_tracer.wp_events[i].virt = 0; + wp_tracer.wp_events[i].phys = 0; + wp_tracer.wp_events[i].type = 0; + wp_tracer.wp_events[i].handler = NULL; + wp_tracer.wp_events[i].in_use = 0; + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write(wp_tracer.debug_regs[j], DBGWCR + (i << 4), + cs_cpu_read(wp_tracer.debug_regs[j], + DBGWCR + (i << 4)) & (~WP_EN)); + cs_cpu_write(wp_tracer.debug_regs[j], EDLAR, ~UNLOCK_KEY); + cs_cpu_write(wp_tracer.debug_regs[j], OSLAR_EL1, + UNLOCK_KEY); + } + } + break; + } + } + spin_unlock_irqrestore(&wp_lock, flags); + pr_debug("[MTK WP] Hotplug enable\n"); + cpu_hotplug_enable(); + if (i == MAX_NR_WATCH_POINT) + return -EINVAL; + else + return 0; +} + +static int watchpoint_handler(unsigned long addr, unsigned int esr, struct pt_regs *regs) +{ + unsigned long wfar, daddr, iaddr; + int i, ret, j; + /* Notes + * wfar is the watched data address which is accessed . and it is from FAR_EL1 + */ + asm volatile ("mrs %0, FAR_EL1":"=r" (wfar)); + daddr = addr & ~3; + iaddr = regs->pc; /* this is the instruction address that access the data that is watching. */ + pr_debug("[MTK WP] addr = 0x%lx, DBGWFAR/DFAR = 0x%lx\n", (unsigned long)addr, wfar); + pr_debug("[MTK WP] daddr = 0x%lx, iaddr = 0x%lx\n", daddr, iaddr); + + /* update PC to avoid re-execution of the instruction under watching */ + regs->pc += compat_thumb_mode(regs) ? 2 : 8; + + for (i = 0; i < MAX_NR_WATCH_POINT; i++) { + if (wp_tracer.wp_events[i].in_use && wp_tracer.wp_events[i].virt == (daddr)) { + pr_debug("[MTK WP] Watchpoint %d triggers.\n", i); + if (!(wp_tracer.wp_events[i].handler)) { + pr_debug("[MTK WP] No watchpoint handler. Ignore.\n"); + return 0; + } + if (wp_tracer.wp_events[i].auto_disable) { + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write(wp_tracer.debug_regs[j], + DBGWCR + (i << 4), + cs_cpu_read + (wp_tracer.debug_regs[j], + DBGWCR + + (i << 4)) & (~WP_EN)); + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip adding watchpoint auto-disable\n", + j, cpu_online(j)); + } + } + } + ret = wp_tracer.wp_events[i].handler(iaddr); + if (wp_tracer.wp_events[i].auto_disable) { + for (j = 0; j < num_possible_cpus(); j++) { + if (cpu_online(j)) { + cs_cpu_write(wp_tracer.debug_regs[j], + DBGWCR + (i << 4), + cs_cpu_read + (wp_tracer.debug_regs[j], + DBGWCR + (i << 4)) | WP_EN); + } else { + pr_debug("[MTK WP] cpu %d, power down(%d) so skip watchpoint auto-disable\n", + j, cpu_online(j)); + } + } + } + return ret; + } + } + + return 0; +} + +int wp_probe(struct platform_device *pdev) +{ + int ret = 0; + int i; + + pr_debug("[MTK WP] watchpoint_probe\n"); + of_property_read_u32(pdev->dev.of_node, "num", &wp_tracer.nr_dbg); + pr_debug("[MTK WP] get %d debug interface\n", wp_tracer.nr_dbg); + wp_tracer.debug_regs = + kmalloc(sizeof(void *) * (unsigned long)wp_tracer.nr_dbg, GFP_KERNEL); + if (!wp_tracer.debug_regs) { + pr_err("[MTK WP] Failed to allocate watchpoint register array\n"); + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < wp_tracer.nr_dbg; i++) { + wp_tracer.debug_regs[i] = of_iomap(pdev->dev.of_node, i); + + if (wp_tracer.debug_regs[i] == NULL) + pr_debug("[MTK WP] debug_interface %d devicetree mapping failed\n", i); + else + pr_debug("[MTK WP] debug_interface %d @ vm:0x%p pm:0x%lx\n", i, + wp_tracer.debug_regs[i], + vmalloc_to_pfn((void *)wp_tracer.debug_regs[i]) << 12); + } + asm volatile ("mrs %0, ID_AA64DFR0_EL1":"=r" (wp_tracer.id_aaa64dfr0_el1)); + wp_tracer.wp_nr = ((wp_tracer.id_aaa64dfr0_el1 & (0xf << 20)) >> 20) + 1; + wp_tracer.bp_nr = ((wp_tracer.id_aaa64dfr0_el1 & (0xf << 12)) >> 12) + 1; + pr_debug("[MTK WP] Probe:Reset watchpoints"); + reset_watchpoint(); +out: + return ret; +} + +static const struct of_device_id dbg_of_ids[] = { + {.compatible = "mediatek,mt6755-dbg_debug",}, + {} +}; + +static struct platform_driver wp_driver = { + .probe = wp_probe, + .driver = { + .name = "wp", + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .of_match_table = dbg_of_ids, + }, +}; + + +#define WATCHPOINT_TEST_SUIT +#ifdef WATCHPOINT_TEST_SUIT +static ssize_t wp_test_suit_show(struct device_driver *driver, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "==Watchpoint test==\n" + "1. test watchpoints in online cpu\n" + "2. verified all cpu's watchpoint after hotplug\n" + "3. verified all cpu's watchpoing after suspend/resume. Not:you have to run test item 1 or 2 to init watchpoint first\n"); +} + +static ssize_t wp_test_suit_store(struct device_driver *driver, const char *buf, size_t count) +{ + char *p = (char *)buf; + unsigned long int num; + ssize_t ret; + + ret = kstrtoul(p, 10, &num); + if (ret == 0) { + switch (num) { + /* Test watchpoint Function */ + case 1: + wp_test1(); + break; + case 2: + wp_test2(); + break; + case 3: + wp_test3(); + default: + break; + } + } + return count; +} + +DRIVER_ATTR(wp_test_suit, 0664, wp_test_suit_show, wp_test_suit_store); +#endif +static int __init hw_watchpoint_init(void) +{ + int err; +#ifdef WATCHPOINT_TEST_SUIT + int ret; +#endif + spin_lock_init(&wp_lock); + err = platform_driver_register(&wp_driver); + if (err) { + pr_err("[MTK WP] watchpoint registration failed\n"); + return err; + } +#ifdef WATCHPOINT_TEST_SUIT + ret = driver_create_file(&wp_driver.driver, &driver_attr_wp_test_suit); + if (ret) + pr_err("[MTK WP] Fail to create systracker_drv sysfs files"); +#endif + hook_debug_fault_code(DBG_ESR_EVT_HWWP, watchpoint_handler, SIGTRAP, TRAP_HWBKPT, + "hw-watchpoint handler"); + pr_debug("[MTK WP] watchpoint handler init.\n"); + + return 0; +} + +/* + EXPORT_SYMBOL(add_hw_watchpoint); + */ +arch_initcall(hw_watchpoint_init); diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch64/hw_watchpoint_aarch64.h b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/hw_watchpoint_aarch64.h new file mode 100644 index 0000000000000000000000000000000000000000..a6d88b4d6100da543ac638c38a8d912d749ad84a --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/hw_watchpoint_aarch64.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __HW_BREAKPOINT_64_H +#define __HW_BREAKPOINT_64_H +#include +#include +#include +#include + +#define MAX_NR_WATCH_POINT 4 +struct wp_trace_context_t { + void __iomem **debug_regs; + struct wp_event wp_events[MAX_NR_WATCH_POINT]; + unsigned int wp_nr; + unsigned int bp_nr; + unsigned long id_aaa64dfr0_el1; + unsigned int nr_dbg; +}; + +#define WATCHPOINT_TEST_SUIT + +struct dbgreg_set { + unsigned long regs[28]; +}; +#define SDSR regs[22] +#define DBGVCR regs[21] +#define DBGWCR3 regs[20] +#define DBGWCR2 regs[19] +#define DBGWCR1 regs[18] +#define DBGWCR0 regs[17] +#define DBGWVR3 regs[16] +#define DBGWVR2 regs[15] +#define DBGWVR1 regs[14] +#define DBGWVR0 regs[13] +#define DBGBCR5 regs[12] +#define DBGBCR4 regs[11] +#define DBGBCR3 regs[10] +#define DBGBCR2 regs[9] +#define DBGBCR1 regs[8] +#define DBGBCR0 regs[7] +#define DBGBVR5 regs[6] +#define DBGBVR4 regs[5] +#define DBGBVR3 regs[4] +#define DBGBVR2 regs[3] +#define DBGBVR1 regs[2] +#define DBGBVR0 regs[1] +#define MDSCR_EL1 regs[0] + +#define DBGWVR 0x800 +#define DBGWCR 0x808 +#define DBGBVR 0x400 +#define DBGBCR 0x408 +#define EDSCR 0x088 + +#define EDLAR 0xFB0 +#define EDLSR 0xFB4 +#define OSLAR_EL1 0x300 + +#define UNLOCK_KEY 0xC5ACCE55 +#define HDE (1 << 14) +#define MDBGEN (1 << 15) +#define KDE (0x1 << 13) +#define DBGWCR_VAL 0x000001E7 + /**/ +#define WP_EN (1 << 0) +#define LSC_LDR (1 << 3) +#define LSC_STR (2 << 3) +#define LSC_ALL (3 << 3) +/* + #define WATCHPOINT_TEST_SUIT +*/ +#define ARM_DBG_READ(N, M, OP2, VAL) {\ + asm volatile("mrc p14, 0, %0, " #N "," #M ", " #OP2 : "=r" (VAL));\ +} +#define ARM_DBG_WRITE(N, M, OP2, VAL) {\ + asm volatile("mcr p14, 0, %0, " #N "," #M ", " #OP2 : : "r" (VAL));\ +} +/* This is bit [29:27] in ESR which indicate watchpoint exception occurred */ +#define DBG_ESR_EVT_HWWP 0x2 +#define dbg_mem_read(addr) readl(IOMEM(addr)) +#define dbg_mem_read_64(addr) readq(IOMEM(addr)) +#define dbg_mem_write(addr, val) mt_reg_sync_writel(val, addr) +#define dbg_reg_copy(offset, base_to, base_from) \ + dbg_mem_write((base_to) + (offset), dbg_mem_read((base_from) + (offset))) +#define dbg_mem_write_64(addr, val) mt_reg_sync_writeq(val, addr) +#define dbg_reg_copy_64(offset, base_to, base_from) \ + dbg_mem_write_64((base_to) + (offset), dbg_mem_read_64((base_from) + (offset))) +static inline void cs_cpu_write(void __iomem *addr_base, u32 offset, u32 wdata) +{ + /* TINFO="Write addr %h, with data %h", addr_base+offset, wdata */ + mt_reg_sync_writel(wdata, addr_base + offset); +} + +static inline unsigned int cs_cpu_read(const void __iomem *addr_base, u32 offset) +{ + u32 actual; + + /* TINFO="Read addr %h, with data %h", addr_base+offset, actual */ + actual = readl(addr_base + offset); + + return actual; +} + +static inline void cs_cpu_write_64(void __iomem *addr_base, u64 offset, u64 wdata) +{ + /* TINFO="Write addr %h, with data %h", addr_base+offset, wdata */ + mt_reg_sync_writeq(wdata, addr_base + offset); +} + +static inline unsigned long cs_cpu_read_64(const void __iomem *addr_base, u64 offset) +{ + u64 actual; + + /* TINFO="Read addr %h, with data %h", addr_base+offset, actual */ + actual = readq(addr_base + offset); + + return actual; +} + + +void smp_read_dbgsdsr_callback(void *info); +void smp_write_dbgsdsr_callback(void *info); +void smp_read_MDSCR_EL1_callback(void *info); +void smp_write_MDSCR_EL1_callback(void *info); +void smp_read_OSLSR_EL1_callback(void *info); +int register_wp_context(struct wp_trace_context_t **wp_tracer_context); +void __iomem *get_wp_base(void); + +extern unsigned read_clusterid(void); + +#endif /* !__HW_BREAKPOINT_64_H */ diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch64/mt_dbg_aarch64.c b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/mt_dbg_aarch64.c new file mode 100644 index 0000000000000000000000000000000000000000..82d63f9f5a4a7e5f92ca0610b8fbddc3efae516e --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/mt_dbg_aarch64.c @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#ifdef CONFIG_SMP +#include +#endif +#include "hw_watchpoint_aarch64.h" +#include "mt_dbg_aarch64.h" + +struct dbgreg_set dbgregs[8]; + +#ifdef DBG_REG_DUMP +void dump_dbgregs(int cpuid) +{ + struct wp_trace_context_t *wp_context; + int i; + + register_wp_context(&wp_context); + cs_cpu_write(wp_context->debug_regs[cpuid], EDLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[cpuid], OSLAR_EL1, ~UNLOCK_KEY); + isb(); + + smp_call_function_single(cpuid, + smp_read_MDSCR_EL1_callback, + &dbgregs[cpuid].MDSCR_EL1, + 1); + + for (i = 1; i < 1 + (wp_context->bp_nr); i++) { + dbgregs[cpuid].regs[i] = + cs_cpu_read_64(wp_context->debug_regs[cpuid], + (DBGBVR + ((i - 1) << 4))); + } + + for (i = 7; i < 7 + (wp_context->bp_nr); i++) { + dbgregs[cpuid].regs[i] = + cs_cpu_read(wp_context->debug_regs[cpuid], + (DBGBCR + ((i - 7) << 4))); + } + + for (i = 13; i < 13 + (wp_context->wp_nr); i++) { + dbgregs[cpuid].regs[i] = + cs_cpu_read_64(wp_context->debug_regs[cpuid], + (DBGWVR + ((i - 13) << 4))); + } + + for (i = 17; i < 17 + (wp_context->wp_nr); i++) { + dbgregs[cpuid].regs[i] = + cs_cpu_read(wp_context->debug_regs[cpuid], + (DBGWCR + ((i - 17) << 4))); + } + + + isb(); + +} + +void print_dbgregs(int cpuid) +{ + + pr_debug("[MTK WP] cpu %d, MDSCR_EL1 0x%lx\n", + cpuid, dbgregs[cpuid].MDSCR_EL1); + pr_debug("[MTK WP] cpu %d, DBGBVR0 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBVR0); + pr_debug("[MTK WP] cpu %d, DBGBVR1 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBVR1); + pr_debug("[MTK WP] cpu %d, DBGBVR2 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBVR2); + pr_debug("[MTK WP] cpu %d, DBGBVR3 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBVR3); + pr_debug("[MTK WP] cpu %d, DBGBVR4 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBVR4); + pr_debug("[MTK WP] cpu %d, DBGBVR5 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBVR5); + + pr_debug("[MTK WP] cpu %d, DBGBCR0 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBCR0); + pr_debug("[MTK WP] cpu %d, DBGBCR1 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBCR1); + pr_debug("[MTK WP] cpu %d, DBGBCR2 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBCR2); + pr_debug("[MTK WP] cpu %d, DBGBCR3 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBCR3); + pr_debug("[MTK WP] cpu %d, DBGBCR4 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBCR4); + pr_debug("[MTK WP] cpu %d, DBGBCR5 0x%lx\n", + cpuid, dbgregs[cpuid].DBGBCR5); + + + pr_debug("[MTK WP] cpu %d, DBGWVR0 0x%lx\n", + cpuid, dbgregs[cpuid].DBGWVR0); + pr_debug("[MTK WP] cpu %d, DBGWVR1 0x%lx\n", + cpuid, dbgregs[cpuid].DBGWVR1); + pr_debug("[MTK WP] cpu %d, DBGWVR2 0x%lx\n", + cpuid, dbgregs[cpuid].DBGWVR2); + pr_debug("[MTK WP] cpu %d, DBGWVR3 0x%lx\n", + cpuid, dbgregs[cpuid].DBGWVR3); + + pr_debug("[MTK WP] cpu %d, DBGWCR0 0x%lx\n", + cpuid, dbgregs[cpuid].DBGWCR0); + pr_debug("[MTK WP] cpu %d, DBGWCR1 0x%lx\n", + cpuid, dbgregs[cpuid].DBGWCR1); + pr_debug("[MTK WP] cpu %d, DBGWCR2 0x%lx\n", + cpuid, dbgregs[cpuid].DBGWCR2); + pr_debug("[MTK WP] cpu %d, DBGWCR3 0x%lx\n", + cpuid, dbgregs[cpuid].DBGWCR3); + + /* + pr_debug("[MTK WP] cpu %d, DBGVCR 0x%lx\n", + cpuid,dbgregs[cpuid].DBGVCR); + pr_debug("[MTK WP] cpu %d, SDSR 0x%lx\n", + cpuid,dbgregs[cpuid].SDSR); + */ + +} +#endif +#if 1 +unsigned int *mt_save_dbg_regs(unsigned int *p, unsigned int cpuid) +{ + struct wp_trace_context_t *wp_context; + + register_wp_context(&wp_context); + cs_cpu_write(wp_context->debug_regs[cpuid], EDLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[cpuid], OSLAR_EL1, ~UNLOCK_KEY); +#ifdef DBG_REG_DUMP + pr_debug("[MTK WP] %s\n", __func__); +#endif + if (*p == ~0x0) { + pr_err("[MTK WP]restore pointer is NULL\n"); + return 0; + } + + + isb(); + /* save register */ + + __asm__ __volatile__("mrs x0, MDSCR_EL1\n\t" + "str x0, [%0],#0x8\n\t" + "mrs x0, DBGBVR0_EL1\n\t" + "mrs x1, DBGBVR1_EL1\n\t" + "mrs x2, DBGBVR2_EL1\n\t" + "mrs x3, DBGBVR3_EL1\n\t" + "mrs x4, DBGBVR4_EL1\n\t" + "mrs x5, DBGBVR5_EL1\n\t" + "str x0 , [%0],#0x8\n\t" + "str x1 , [%0],#0x8\n\t" + "str x2 , [%0],#0x8\n\t" + "str x3 , [%0],#0x8\n\t" + "str x4 , [%0],#0x8\n\t" + "str x5 , [%0],#0x8\n\t" + "mrs x0, DBGBCR0_EL1\n\t" + "mrs x1, DBGBCR1_EL1\n\t" + "mrs x2, DBGBCR2_EL1\n\t" + "mrs x3, DBGBCR3_EL1\n\t" + "mrs x4, DBGBCR4_EL1\n\t" + "mrs x5, DBGBCR5_EL1\n\t" + "str x0 , [%0],#0x8\n\t" + "str x1 , [%0],#0x8\n\t" + "str x2 , [%0],#0x8\n\t" + "str x3 , [%0],#0x8\n\t" + "str x4 , [%0],#0x8\n\t" + "str x5 , [%0],#0x8\n\t" + "mrs x0, DBGWVR0_EL1\n\t" + "mrs x1, DBGWVR1_EL1\n\t" + "mrs x2, DBGWVR2_EL1\n\t" + "mrs x3, DBGWVR3_EL1\n\t" + "str x0 , [%0],#0x8\n\t" + "str x1 , [%0],#0x8\n\t" + "str x2 , [%0],#0x8\n\t" + "str x3 , [%0],#0x8\n\t" + "mrs x0, DBGWCR0_EL1\n\t" + "mrs x1, DBGWCR1_EL1\n\t" + "mrs x2, DBGWCR2_EL1\n\t" + "mrs x3, DBGWCR3_EL1\n\t" + "str x0 , [%0],#0x8\n\t" + "str x1 , [%0],#0x8\n\t" + "str x2 , [%0],#0x8\n\t" + "str x3 , [%0],#0x8\n\t":"+r"(p) + : : "x0", "x1", "x2", "x3", "x4", "x5"); + isb(); + + return p; +} + +void mt_restore_dbg_regs(unsigned int *p, unsigned int cpuid) +{ + unsigned long dscr; + struct wp_trace_context_t *wp_context; +#ifdef DBG_REG_DUMP + pr_debug("[MTK WP] %s\n", __func__); +#endif + register_wp_context(&wp_context); + /* the dbg container is invalid */ + if (*p == ~0x0) { + pr_err("[MTK WP]restore pointer is NULL\n"); + return; + } + cs_cpu_write(wp_context->debug_regs[cpuid], EDLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[cpuid], OSLAR_EL1, ~UNLOCK_KEY); + + isb(); + + + /* restore register */ +#if 1 + __asm__ __volatile__("ldr x0, [%0],#0x8\n\t" + "mov %1, x0\n\t" + "msr MDSCR_EL1,x0\n\t" + "ldr x0 , [%0],#0x8\n\t" + "ldr x1 , [%0],#0x8\n\t" + "ldr x2 , [%0],#0x8\n\t" + "ldr x3 , [%0],#0x8\n\t" + "ldr x4 , [%0],#0x8\n\t" + "ldr x5 , [%0],#0x8\n\t" + "msr DBGBVR0_EL1,x0\n\t" + "msr DBGBVR1_EL1,x1\n\t" + "msr DBGBVR2_EL1,x2\n\t" + "msr DBGBVR3_EL1,x3\n\t" + "msr DBGBVR4_EL1,x4\n\t" + "msr DBGBVR5_EL1,x5\n\t" + "ldr x0 , [%0],#0x8\n\t" + "ldr x1 , [%0],#0x8\n\t" + "ldr x2 , [%0],#0x8\n\t" + "ldr x3 , [%0],#0x8\n\t" + "ldr x4 , [%0],#0x8\n\t" + "ldr x5 , [%0],#0x8\n\t" + "msr DBGBCR0_EL1,x0\n\t" + "msr DBGBCR1_EL1,x1\n\t" + "msr DBGBCR2_EL1,x2\n\t" + "msr DBGBCR3_EL1,x3\n\t" + "msr DBGBCR4_EL1,x4\n\t" + "msr DBGBCR5_EL1,x5\n\t" + "ldr x0 , [%0],#0x8\n\t" + "ldr x1 , [%0],#0x8\n\t" + "ldr x2 , [%0],#0x8\n\t" + "ldr x3 , [%0],#0x8\n\t" + "msr DBGWVR0_EL1,x0\n\t" + "msr DBGWVR1_EL1,x1\n\t" + "msr DBGWVR2_EL1,x2\n\t" + "msr DBGWVR3_EL1,x3\n\t" + "ldr x0 , [%0],#0x8\n\t" + "ldr x1 , [%0],#0x8\n\t" + "ldr x2 , [%0],#0x8\n\t" + "ldr x3 , [%0],#0x8\n\t" + "msr DBGWCR0_EL1,x0\n\t" + "msr DBGWCR1_EL1,x1\n\t" + "msr DBGWCR2_EL1,x2\n\t" + "msr DBGWCR3_EL1,x3\n\t":"+r"(p), "=r"(dscr) + : : "x0", "x1", "x2", "x3", "x4", "x5"); +#endif + isb(); +} + + + + + +/** to copy dbg registers from FROM to TO within the same cluster. + * DBG_BASE is the common base of 2 cores debug register space. + **/ +void mt_copy_dbg_regs(int to, int from) +{ + unsigned long base_to, base_from; + unsigned long args; + struct wp_trace_context_t *wp_context; + + register_wp_context(&wp_context); + base_to = (unsigned long)wp_context->debug_regs[to]; + base_from = (unsigned long)wp_context->debug_regs[from]; + + /* os unlock */ + cs_cpu_write(wp_context->debug_regs[to], EDLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[to], OSLAR_EL1, ~UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[from], EDLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[from], OSLAR_EL1, ~UNLOCK_KEY); + + isb(); + + smp_call_function_single(from, smp_read_MDSCR_EL1_callback, &args, 1); + smp_call_function_single(to, smp_write_MDSCR_EL1_callback, &args, 1); + isb(); + dbg_reg_copy(DBGBCR, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x10, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x20, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x30, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x40, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x50, base_to, base_from); + + dbg_reg_copy_64(DBGBVR, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x10, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x20, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x30, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x40, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x50, base_to, base_from); + + + dbg_reg_copy_64(DBGWVR, base_to, base_from); + dbg_reg_copy_64(DBGWVR + 0x10, base_to, base_from); + dbg_reg_copy_64(DBGWVR + 0x20, base_to, base_from); + dbg_reg_copy_64(DBGWVR + 0x30, base_to, base_from); + + dbg_reg_copy(DBGWCR, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x10, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x20, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x30, base_to, base_from); + + isb(); +} + + + +#ifdef CONFIG_SMP +int __cpuinit dbgregs_hotplug_callback( + struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + unsigned long this_cpu = (unsigned long)hcpu; + unsigned int args = 0; + struct wp_trace_context_t *wp_context; + unsigned long base_to, base_from = 0; + int i; + + register_wp_context(&wp_context); + cs_cpu_write(wp_context->debug_regs[this_cpu], EDLAR, UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[this_cpu], OSLAR_EL1, ~UNLOCK_KEY); + /*cs_cpu_write(wp_context->debug_regs[0], EDLAR, UNLOCK_KEY);*/ + /*cs_cpu_write(wp_context->debug_regs[0], OSLAR_EL1, ~UNLOCK_KEY);*/ + for (i = 0; i < num_possible_cpus(); i++) { + if (cpu_online(i)) { + cs_cpu_write(wp_context->debug_regs[i], + EDLAR, + UNLOCK_KEY); + cs_cpu_write(wp_context->debug_regs[i], + OSLAR_EL1, + ~UNLOCK_KEY); + base_from = (unsigned long)wp_context->debug_regs[i]; + break; + } + } + base_to = (unsigned long)wp_context->debug_regs[this_cpu]; + /*base_from = (unsigned long)wp_context->debug_regs[0];*/ + action = action & 0xf; +#ifdef DBG_REG_DUMP + pr_debug("[MTK WP] cpu %lx do %s,action: 0x%lx\n", + this_cpu, __func__, action); +#endif + switch (action) { + case CPU_STARTING: + smp_call_function_single(i, + smp_read_MDSCR_EL1_callback, + &args, + 1); +#ifdef DBG_REG_DUMP + pr_debug("[MTK WP] cpu %lx do %s, CPU%lx's _MDSCR_EL1=0x%x\n", + this_cpu, + i, + __func__, + args); +#endif + asm volatile ("msr MDSCR_EL1, %0" : : "r" (args)); + isb(); + dbg_reg_copy(DBGBCR, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x10, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x20, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x30, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x40, base_to, base_from); + dbg_reg_copy(DBGBCR + 0x50, base_to, base_from); + + dbg_reg_copy_64(DBGBVR, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x10, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x20, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x30, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x40, base_to, base_from); + dbg_reg_copy_64(DBGBVR + 0x50, base_to, base_from); + + + dbg_reg_copy_64(DBGWVR, base_to, base_from); + dbg_reg_copy_64(DBGWVR + 0x10, base_to, base_from); + dbg_reg_copy_64(DBGWVR + 0x20, base_to, base_from); + dbg_reg_copy_64(DBGWVR + 0x30, base_to, base_from); + + dbg_reg_copy(DBGWCR, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x10, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x20, base_to, base_from); + dbg_reg_copy(DBGWCR + 0x30, base_to, base_from); + + isb(); + break; + + default: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block cpu_nfb __cpuinitdata = { + .notifier_call = dbgregs_hotplug_callback +}; + +static int __init regs_backup(void) +{ + + register_cpu_notifier(&cpu_nfb); + + return 0; +} + +module_init(regs_backup); +#endif +#endif diff --git a/drivers/misc/mediatek/watchpoint/mt6755/aarch64/mt_dbg_aarch64.h b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/mt_dbg_aarch64.h new file mode 100644 index 0000000000000000000000000000000000000000..70df53fe4dfacafa07f3f54e2b045a6667d34c9e --- /dev/null +++ b/drivers/misc/mediatek/watchpoint/mt6755/aarch64/mt_dbg_aarch64.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_DBG_H +#define __MT_DBG_H +/* + #define DBG_REG_DUMP +*/ +unsigned int *mt_save_dbg_regs(unsigned int *p, unsigned int cpuid); +void mt_restore_dbg_regs(unsigned int *p, unsigned int cpuid); +void mt_copy_dbg_regs(int to, int from); +#ifdef DBG_REG_DUMP +void dump_dbgregs(int cpuid); +void print_dbgregs(int cpuid); + +#endif +extern int get_cluster_core_count(void); +#endif /* !__HW_BREAKPOINT_H */ diff --git a/drivers/mmc/host/mediatek/mt6755/Makefile b/drivers/mmc/host/mediatek/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b0f98efcf05dfc232a12d8a6ee7fd88cfb47d4bb --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +#add kernel source code path as head file search path +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include +#workaround for include mmc/card/queue.h and mmc/core/core.h +ccflags-y += -I$(srctree)/drivers/mmc + +obj-$(CONFIG_MMC_MTK) += msdc.o + +msdc-y += sd.o mt_sd_misc.o +msdc-y += msdc_tune.o +msdc-y += dbg.o +msdc-y += msdc_partition.o +msdc-y += autok.o +msdc-y += autok_dvfs.o + +msdc-y += msdc_io.o +ifeq ($(CONFIG_MTK_FPGA),y) +msdc-y += msdc_fpga_io.o +endif + +ifeq ($(CONFIG_MTK_AEE_IPANIC),y) +ccflags-y += -I$(srctree)/drivers/misc/mediatek/pmic_wrap/$(MTK_PLATFORM) +msdc-y += mt_dump.o +endif + +ifeq ($(CONFIG_MTK_EMMC_SUPPORT_OTP),y) +msdc-y += emmc_otp.o +endif diff --git a/drivers/mmc/host/mediatek/mt6755/autok.c b/drivers/mmc/host/mediatek/mt6755/autok.c new file mode 100644 index 0000000000000000000000000000000000000000..ad3f82f0704a7d297b036b3a2cb6ba13aab9c613 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/autok.c @@ -0,0 +1,3667 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "autok.h" +#include +#include +#include + +#include +#include +#include +#include + +#define MSDC_FIFO_THD_1K (1024) +#define TUNE_TX_CNT (100) +/*#define TUNE_DATA_TX_ADDR (0x358000)*/ +/* Use negative value to represent address from end of device, + 33 blocks used by SGPT at end of device, + 32768 blocks used by flashinfo immediate before SGPT */ +#define TUNE_DATA_TX_ADDR (-33-32768) +#define CMDQ +#define AUTOK_LATCH_CK_EMMC_TUNE_TIMES (10) /* 5.0IP eMMC 1KB fifo ZIZE */ +#define AUTOK_LATCH_CK_SDIO_TUNE_TIMES (3) /* 4.5IP SDIO 128fifo ZIZE */ +#define AUTOK_LATCH_CK_SD_TUNE_TIMES (3) /* 4.5IP SD 128fifo ZIZE */ +#define AUTOK_CMD_TIMES (20) +#define AUTOK_TUNING_INACCURACY (3) /* scan result may find xxxxooxxx */ +#define AUTOK_MARGIN_THOLD (5) +#define AUTOK_BD_WIDTH_REF (3) + +#define AUTOK_READ 0 +#define AUTOK_WRITE 1 + +#define AUTOK_FINAL_CKGEN_SEL (0) +#define SCALE_TA_CNTR (8) +#define SCALE_CMD_RSP_TA_CNTR (8) +#define SCALE_WDAT_CRC_TA_CNTR (8) +#define SCALE_INT_DAT_LATCH_CK_SEL (8) +#define SCALE_INTERNAL_DLY_CNTR (32) +#define SCALE_PAD_DAT_DLY_CNTR (32) + +#define TUNING_INACCURACY (2) + +/* autok platform specific setting */ +#define AUTOK_CKGEN_VALUE (0) +#define AUTOK_CMD_LATCH_EN_HS400_VALUE (3) +#define AUTOK_CMD_LATCH_EN_NON_HS400_VALUE (2) +#define AUTOK_CRC_LATCH_EN_HS400_VALUE (0) +#define AUTOK_CRC_LATCH_EN_NON_HS400_VALUE (2) +#define AUTOK_LATCH_CK_VALUE (1) +#define AUTOK_CMD_TA_VALUE (0) +#define AUTOK_CRC_TA_VALUE (0) +#define AUTOK_CRC_MA_VALUE (1) +#define AUTOK_BUSY_MA_VALUE (1) + +enum TUNE_TYPE { + TUNE_CMD = 0, + TUNE_DATA, + TUNE_LATCH_CK, +}; + +#define autok_msdc_retry(expr, retry, cnt) \ + do { \ + int backup = cnt; \ + while (retry) { \ + if (!(expr)) \ + break; \ + if (cnt-- == 0) { \ + retry--; cnt = backup; \ + } \ + } \ + WARN_ON(retry == 0); \ +} while (0) + +#define autok_msdc_reset() \ + do { \ + int retry = 3, cnt = 1000; \ + MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_RST); \ + /* ensure reset operation be sequential */ \ + mb(); \ + autok_msdc_retry(MSDC_READ32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ + } while (0) + +#define msdc_rxfifocnt() \ + ((MSDC_READ32(MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) >> 0) +#define msdc_txfifocnt() \ + ((MSDC_READ32(MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16) + +#define wait_cond(cond, tmo, left) \ + do { \ + u32 t = tmo; \ + while (1) { \ + if ((cond) || (t == 0)) \ + break; \ + if (t > 0) { \ + ndelay(1); \ + t--; \ + } \ + } \ + left = t; \ + } while (0) + + +#define msdc_clear_fifo() \ + do { \ + int retry = 5, cnt = 1000; \ + MSDC_SET_BIT32(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \ + /* ensure fifo clear operation be sequential */ \ + mb(); \ + autok_msdc_retry(MSDC_READ32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, retry, cnt); \ + } while (0) + +struct AUTOK_PARAM_RANGE { + unsigned int start; + unsigned int end; +}; + +struct AUTOK_PARAM_INFO { + struct AUTOK_PARAM_RANGE range; + char *param_name; +}; + +struct BOUND_INFO { + unsigned int Bound_Start; + unsigned int Bound_End; + unsigned int Bound_width; + bool is_fullbound; +}; + +#define BD_MAX_CNT 4 /* Max Allowed Boundary Number */ +struct AUTOK_SCAN_RES { + /* Bound info record, currently only allow max to 2 bounds exist, + but in extreme case, may have 4 bounds */ + struct BOUND_INFO bd_info[BD_MAX_CNT]; + /* Bound cnt record, must be in rang [0,3] */ + unsigned int bd_cnt; + /* Full boundary cnt record */ + unsigned int fbd_cnt; +}; + +struct AUTOK_REF_INFO { + /* inf[0] - rising edge res, inf[1] - falling edge res */ + struct AUTOK_SCAN_RES scan_info[2]; + /* optimised sample edge select */ + unsigned int opt_edge_sel; + /* optimised dly cnt sel */ + unsigned int opt_dly_cnt; + /* 1clk cycle equal how many delay cell cnt, if cycle_cnt is 0, + that is cannot calc cycle_cnt by current Boundary info */ + unsigned int cycle_cnt; +}; + +unsigned int do_autok_offline_tune_tx; +unsigned int autok_debug_level = AUTOK_DBG_RES; + +const struct AUTOK_PARAM_INFO autok_param_info[] = { + {{0, 1}, "CMD_EDGE"}, + {{0, 1}, "RDATA_EDGE"}, /* async fifo mode Pad dat edge must fix to 0 */ + {{0, 1}, "RD_FIFO_EDGE"}, + {{0, 1}, "WD_FIFO_EDGE"}, + + {{0, 31}, "CMD_RD_D_DLY1"}, /* Cmd Pad Tune Data Phase */ + {{0, 1}, "CMD_RD_D_DLY1_SEL"}, + {{0, 31}, "CMD_RD_D_DLY2"}, + {{0, 1}, "CMD_RD_D_DLY2_SEL"}, + + {{0, 31}, "DAT_RD_D_DLY1"}, /* Data Pad Tune Data Phase */ + {{0, 1}, "DAT_RD_D_DLY1_SEL"}, + {{0, 31}, "DAT_RD_D_DLY2"}, + {{0, 1}, "DAT_RD_D_DLY2_SEL"}, + + {{0, 7}, "INT_DAT_LATCH_CK"}, /* Latch CK Delay for data read when clock stop */ + + {{0, 31}, "EMMC50_DS_Z_DLY1"}, /* eMMC50 Related tuning param */ + {{0, 1}, "EMMC50_DS_Z_DLY1_SEL"}, + {{0, 31}, "EMMC50_DS_Z_DLY2"}, + {{0, 1}, "EMMC50_DS_Z_DLY2_SEL"}, + {{0, 31}, "EMMC50_DS_ZDLY_DLY"}, + + /* ================================================= */ + /* Timming Related Mux & Common Setting Config */ + {{0, 1}, "READ_DATA_SMPL_SEL"}, /* all data line path share sample edge */ + {{0, 1}, "WRITE_DATA_SMPL_SEL"}, + {{0, 1}, "DATA_DLYLINE_SEL"}, /* clK tune all data Line share dly */ + {{0, 1}, "MSDC_WCRC_ASYNC_FIFO_SEL"}, /* data tune mode select */ + {{0, 1}, "MSDC_RESP_ASYNC_FIFO_SEL"}, /* data tune mode select */ + /* eMMC50 Function Mux */ + {{0, 1}, "EMMC50_WDATA_MUX_EN"}, /* write path switch to emmc45 */ + {{0, 1}, "EMMC50_CMD_MUX_EN"}, /* response path switch to emmc45 */ + {{0, 1}, "EMMC50_WDATA_EDGE"}, + /* Common Setting Config */ + {{0, 31}, "CKGEN_MSDC_DLY_SEL"}, + {{1, 7}, "CMD_RSP_TA_CNTR"}, + {{1, 7}, "WRDAT_CRCS_TA_CNTR"}, + {{0, 31}, "PAD_CLK_TXDLY"}, /* tx clk dly fix to 0 for HQA res */ +}; + +/********************************************************** +* AutoK Basic Interface Implenment * +**********************************************************/ +#if defined(SDIO_TUNE_WRITE_PATH) +static void mmc_wait_done(struct mmc_request *mrq) +{ + complete(&mrq->completion); +} + +static int autok_wait_for_req(struct msdc_host *host, struct mmc_request *mrq) +{ + int ret = E_RESULT_PASS; + struct mmc_host *mmc = host->mmc; + struct mmc_command *cmd = mrq->cmd; + struct mmc_data *data = mrq->data; + + init_completion(&mrq->completion); /* start request */ + mrq->done = mmc_wait_done; + mrq->cmd->error = 0; + mrq->cmd->mrq = mrq; + mrq->cmd->data = data; + if (data != NULL) { + mrq->data->error = 0; + mrq->data->mrq = mrq; + } + mmc->ops->request(mmc, mrq); + + wait_for_completion(&mrq->completion); /* wait for request done */ + + if (cmd->error) { /*error decode */ + AUTOK_DBGPRINT(AUTOK_DBG_TRACE, "[ERROR]cmd->error : %d\n", cmd->error); + if (cmd->error == (unsigned int)(-ETIMEDOUT)) + ret |= E_RESULT_CMD_TMO; + if (cmd->error == (unsigned int)(-EILSEQ)) + ret |= E_RESULT_RSP_CRC; + } + if ((data != NULL) && (data->error)) { + AUTOK_DBGPRINT(AUTOK_DBG_TRACE, "[ERROR]data->error : %d\n", data->error); + if (data->error == (unsigned int)(-EILSEQ)) + ret |= E_RESULT_DAT_CRC; + if (data->error == (unsigned int)(-ETIMEDOUT)) + ret |= E_RESULT_DAT_TMO; + } + /* + if (ret) + AUTOK_RAWPRINT("[ERROR]%s error code :0x%x\n", __func__, ret); + */ + + return ret; + +} + +static int autok_f0_rw_direct(struct msdc_host *host, unsigned int u4Addr, char *out, char in, + bool write) +{ + struct mmc_request mrq = { NULL }; + struct mmc_command cmd = { 0 }; + int ret = E_RESULT_PASS; + + if (u4Addr & ~0x1FFFF) + return -EINVAL; + cmd.opcode = SD_IO_RW_DIRECT; + cmd.arg = write ? 0x80000000 : 0x00000000; + cmd.arg |= 0 << 28; /* function number = 0 */ + cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; /* read after write flage */ + cmd.arg |= u4Addr << 9; + cmd.arg |= in; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; + + cmd.retries = 0; + cmd.data = NULL; + mrq.cmd = &cmd; + + ret = autok_wait_for_req(host, &mrq); + if (out) + *out = cmd.resp[0] & 0xFF; + + return ret; +} + +static int +autok_f0_rw_extended(struct msdc_host *host, unsigned int u4Addr, void *pBuf, unsigned int byte_cnt, + bool write, bool opmode, bool bkmode) +{ + struct mmc_request mrq = { NULL }; + struct mmc_command cmd = { 0 }; + struct mmc_data data = { 0 }; + struct scatterlist sg; + int ret = E_RESULT_PASS; + + if (host == NULL) { + pr_debug("[%s] [ERR]host = %p\n", __func__, host); + return -1; + } + if (pBuf == NULL) + pr_err("[%s] [ERR]host = %p, memory malloc failed!!\n", __func__, host); + + /* Setup mrq */ + mrq.cmd = &cmd; + mrq.data = &data; + + /* Setup cmd */ + cmd.opcode = SD_IO_RW_EXTENDED; + cmd.arg = 0; + cmd.arg = write ? 0x80000000 : 0x00000000; + cmd.arg |= 0 << 28; /* Function num = 0 */ + cmd.arg |= u4Addr << 9; + cmd.arg |= opmode << 26; /* 0-fix addr 1-inc addr */ + cmd.arg |= bkmode << 27; /* 0- byte 1-block */ + cmd.arg |= byte_cnt; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + cmd.data = &data; + + data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; + data.sg = &sg; + data.sg_len = 1; + + data.blksz = byte_cnt; + data.blocks = 1; + + sg_init_one(&sg, pBuf, byte_cnt); + + ret = autok_wait_for_req(host, &mrq); + + return ret; +} +#endif + +static int autok_send_tune_cmd(struct msdc_host *host, unsigned int opcode, enum TUNE_TYPE tune_type_value) +{ + void __iomem *base = host->base; + unsigned int value; + unsigned int rawcmd = 0; + unsigned int arg = 0; + unsigned int sts = 0; + unsigned int wints = 0; + unsigned int tmo = 0; + unsigned int left = 0; + unsigned int fifo_have = 0; + unsigned int fifo_1k_cnt = 0; + unsigned int i = 0; + int ret = E_RESULT_PASS; + + switch (opcode) { + case MMC_SEND_EXT_CSD: + rawcmd = (512 << 16) | (0 << 13) | (1 << 11) | (1 << 7) | (8); + arg = 0; + if (tune_type_value == TUNE_LATCH_CK) + MSDC_WRITE32(SDC_BLK_NUM, host->tune_latch_ck_cnt); + else + MSDC_WRITE32(SDC_BLK_NUM, 1); + break; + case MMC_STOP_TRANSMISSION: + rawcmd = (1 << 14) | (7 << 7) | (12); + arg = 0; + break; + case MMC_SEND_STATUS: + rawcmd = (1 << 7) | (13); + arg = (1 << 16); + break; + case MMC_READ_SINGLE_BLOCK: + left = 512; + rawcmd = (512 << 16) | (0 << 13) | (1 << 11) | (1 << 7) | (17); + arg = 0; + if (tune_type_value == TUNE_LATCH_CK) + MSDC_WRITE32(SDC_BLK_NUM, host->tune_latch_ck_cnt); + else + MSDC_WRITE32(SDC_BLK_NUM, 1); + break; + case MMC_SEND_TUNING_BLOCK: + left = 64; + rawcmd = (64 << 16) | (0 << 13) | (1 << 11) | (1 << 7) | (19); + arg = 0; + if (tune_type_value == TUNE_LATCH_CK) + MSDC_WRITE32(SDC_BLK_NUM, host->tune_latch_ck_cnt); + else + MSDC_WRITE32(SDC_BLK_NUM, 1); + break; + case MMC_SEND_TUNING_BLOCK_HS200: + left = 128; + rawcmd = (128 << 16) | (0 << 13) | (1 << 11) | (1 << 7) | (21); + arg = 0; + if (tune_type_value == TUNE_LATCH_CK) + MSDC_WRITE32(SDC_BLK_NUM, host->tune_latch_ck_cnt); + else + MSDC_WRITE32(SDC_BLK_NUM, 1); + break; + case MMC_WRITE_BLOCK: + rawcmd = (512 << 16) | (1 << 13) | (1 << 11) | (1 << 7) | (24); + if (TUNE_DATA_TX_ADDR >= 0) + arg = TUNE_DATA_TX_ADDR; + else + arg = host->mmc->card->ext_csd.sectors + + TUNE_DATA_TX_ADDR; + break; + case SD_IO_RW_DIRECT: + break; + case SD_IO_RW_EXTENDED: + break; + } + + while ((MSDC_READ32(SDC_STS) & SDC_STS_SDCBUSY)) + ; + + /* clear fifo */ + if ((tune_type_value == TUNE_CMD) || (tune_type_value == TUNE_DATA)) { + autok_msdc_reset(); + msdc_clear_fifo(); + MSDC_WRITE32(MSDC_INT, 0xffffffff); + } + + /* start command */ + MSDC_WRITE32(SDC_ARG, arg); + MSDC_WRITE32(SDC_CMD, rawcmd); + + /* wait interrupt status */ + wints = MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR; + tmo = 0x3FFFFF; + wait_cond(((sts = MSDC_READ32(MSDC_INT)) & wints), tmo, tmo); + if (tmo == 0) { + ret = E_RESULT_CMD_TMO; + goto end; + } + + MSDC_WRITE32(MSDC_INT, (sts & wints)); + if (sts == 0) { + ret = E_RESULT_CMD_TMO; + goto end; + } + + if (sts & MSDC_INT_CMDRDY) { + if (tune_type_value == TUNE_CMD) { + ret = E_RESULT_PASS; + goto end; + } + } else if (sts & MSDC_INT_RSPCRCERR) { + ret = E_RESULT_RSP_CRC; + goto end; + } else if (sts & MSDC_INT_CMDTMO) { + ret = E_RESULT_CMD_TMO; + goto end; + } + if ((tune_type_value != TUNE_LATCH_CK) && (tune_type_value != TUNE_DATA)) + goto skip_tune_latch_ck_and_tune_data; + + while ((MSDC_READ32(SDC_STS) & SDC_STS_SDCBUSY)) { + if (tune_type_value == TUNE_LATCH_CK) { + fifo_have = msdc_rxfifocnt(); + if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) || (opcode == MMC_READ_SINGLE_BLOCK) + || (opcode == MMC_SEND_EXT_CSD)) { + MSDC_SET_FIELD(MSDC_DBG_SEL, 0xffff << 0, 0x0b); + MSDC_GET_FIELD(MSDC_DBG_OUT, 0x7ff << 0, fifo_1k_cnt); + if ((fifo_1k_cnt >= MSDC_FIFO_THD_1K) && (fifo_have >= MSDC_FIFO_SZ)) { + value = MSDC_READ32(MSDC_RXDATA); + value = MSDC_READ32(MSDC_RXDATA); + value = MSDC_READ32(MSDC_RXDATA); + value = MSDC_READ32(MSDC_RXDATA); + } + } else if (opcode == MMC_SEND_TUNING_BLOCK) { + if (fifo_have >= MSDC_FIFO_SZ) { + value = MSDC_READ32(MSDC_RXDATA); + value = MSDC_READ32(MSDC_RXDATA); + value = MSDC_READ32(MSDC_RXDATA); + value = MSDC_READ32(MSDC_RXDATA); + } + } + } else if ((tune_type_value == TUNE_DATA) && (opcode == MMC_WRITE_BLOCK)) { + for (i = 0; i < 64; i++) { + MSDC_WRITE32(MSDC_TXDATA, 0x5af00fa5); + MSDC_WRITE32(MSDC_TXDATA, 0x33cc33cc); + } + + while ((MSDC_READ32(SDC_STS) & SDC_STS_SDCBUSY)) + ; + } + } + + sts = MSDC_READ32(MSDC_INT); + wints = MSDC_INT_XFER_COMPL | MSDC_INT_DATCRCERR | MSDC_INT_DATTMO; + if (sts) { + /* clear status */ + MSDC_WRITE32(MSDC_INT, (sts & wints)); + if (sts & MSDC_INT_XFER_COMPL) + ret = E_RESULT_PASS; + if (MSDC_INT_DATCRCERR & sts) + ret = E_RESULT_DAT_CRC; + if (MSDC_INT_DATTMO & sts) + ret = E_RESULT_DAT_TMO; + } + +skip_tune_latch_ck_and_tune_data: + while ((MSDC_READ32(SDC_STS) & SDC_STS_SDCBUSY)) + ; + if ((tune_type_value == TUNE_CMD) || (tune_type_value == TUNE_DATA)) + msdc_clear_fifo(); + +end: + if (opcode == MMC_STOP_TRANSMISSION) { + while ((MSDC_READ32(MSDC_PS) & 0x10000) != 0x10000) + ; + } + + return ret; +} + +#if defined(SDIO_TUNE_WRITE_PATH) +static int autok_cmd53_tune_cccr_write(struct msdc_host *host) +{ + int ret = 0; + unsigned int wDat = 0x5A; + unsigned int test_cnt = 10; + int i = 0; + + do { + i++; + + ret = autok_f0_rw_extended(host, 0xE0, &wDat, 4, 1, 0, 0); + if (ret != 0) { + AUTOK_RAWPRINT("[ERROR]CMD53(%d) Write CCCR0 Error: 0x%x\n", i, ret); + + /* abort data transfer don't care response */ + autok_f0_rw_direct(host, 0x6, NULL, 0, 1); + return ret; + } + } while (--test_cnt); + + return ret; +} +#endif + +#if 0 +static int autok_cmd53_tune_cccr_read(struct msdc_host *host) +{ + int ret = 0; + unsigned char *rDat = NULL; + unsigned int test_cnt = 10; + int i = 0; + + rDat = kmalloc(32, GFP_KERNEL); + do { + i++; + + ret = autok_f0_rw_extended(host, SDIO_CCCR_CCCR, rDat, 32, 0, 0, 0); + if (ret != 0) { + AUTOK_RAWPRINT("[ERROR]CMD53(%d) Read CCCR0 Error: 0x%x\n", i, ret); + return ret; + } + } while (--test_cnt); + kfree(rDat); + + return ret; +} +#endif + +static int autok_simple_score(char *res_str, unsigned int result) +{ + unsigned int bit = 0; + unsigned int num = 0; + unsigned int old = 0; + + if (0 == result) { + strcpy(res_str, "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"); /* maybe result is 0 */ + return 32; + } + if (0xFFFFFFFF == result) { + strcpy(res_str, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + return 0; + } + + /* calc continue zero number */ + while (bit < 32) { + if (result & (1 << bit)) { + res_str[bit] = 'X'; + bit++; + if (old < num) + old = num; + num = 0; + continue; + } + res_str[bit] = 'O'; + bit++; + num++; + } + if (num > old) + old = num; + + return old; +} + +static int autok_simple_score64(char *res_str64, u64 result64) +{ + unsigned int bit = 0; + unsigned int num = 0; + unsigned int old = 0; + + if (0 == result64) { + /* maybe result is 0 */ + strcpy(res_str64, "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"); + return 64; + } + if (0xFFFFFFFFFFFFFFFF == result64) { + strcpy(res_str64, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + return 0; + } + + /* calc continue zero number */ + while (bit < 64) { + if (result64 & ((u64) (1LL << bit))) { + res_str64[bit] = 'X'; + bit++; + if (old < num) + old = num; + num = 0; + continue; + } + res_str64[bit] = 'O'; + bit++; + num++; + } + if (num > old) + old = num; + + return old; +} + +enum { + RD_SCAN_NONE, + RD_SCAN_PAD_BOUND_S, + RD_SCAN_PAD_BOUND_E, + RD_SCAN_PAD_MARGIN, +}; + +static int autok_check_scan_res64(u64 rawdat, struct AUTOK_SCAN_RES *scan_res) +{ + unsigned int bit; + unsigned int filter = 4; + struct BOUND_INFO *pBD = (struct BOUND_INFO *)scan_res->bd_info; + unsigned int RawScanSta = RD_SCAN_NONE; + + for (bit = 0; bit < 64; bit++) { + if (rawdat & (1LL << bit)) { + switch (RawScanSta) { + case RD_SCAN_NONE: + RawScanSta = RD_SCAN_PAD_BOUND_S; + pBD->Bound_Start = 0; + pBD->Bound_width = 1; + scan_res->bd_cnt += 1; + break; + case RD_SCAN_PAD_MARGIN: + RawScanSta = RD_SCAN_PAD_BOUND_S; + pBD->Bound_Start = bit; + pBD->Bound_width = 1; + scan_res->bd_cnt += 1; + break; + case RD_SCAN_PAD_BOUND_E: + if ((filter) && ((bit - pBD->Bound_End) <= AUTOK_TUNING_INACCURACY)) { + AUTOK_DBGPRINT(AUTOK_DBG_TRACE, + "[AUTOK]WARN: Try to filter the holes on raw data \r\n"); + RawScanSta = RD_SCAN_PAD_BOUND_S; + + pBD->Bound_width += (bit - pBD->Bound_End); + pBD->Bound_End = 0; + filter--; + + /* update full bound info */ + if (pBD->is_fullbound) { + pBD->is_fullbound = 0; + scan_res->fbd_cnt -= 1; + } + } else { + /* No filter Check and Get the next boundary information */ + RawScanSta = RD_SCAN_PAD_BOUND_S; + pBD++; + pBD->Bound_Start = bit; + pBD->Bound_width = 1; + scan_res->bd_cnt += 1; + if (scan_res->bd_cnt > BD_MAX_CNT) { + AUTOK_RAWPRINT + ("[AUTOK]Error: more than %d Boundary Exist\r\n", + BD_MAX_CNT); + return -1; + } + } + break; + case RD_SCAN_PAD_BOUND_S: + pBD->Bound_width++; + break; + default: + break; + } + } else { + switch (RawScanSta) { + case RD_SCAN_NONE: + RawScanSta = RD_SCAN_PAD_MARGIN; + break; + case RD_SCAN_PAD_BOUND_S: + RawScanSta = RD_SCAN_PAD_BOUND_E; + pBD->Bound_End = bit - 1; + /* update full bound info */ + if (pBD->Bound_Start > 0) { + pBD->is_fullbound = 1; + scan_res->fbd_cnt += 1; + } + break; + case RD_SCAN_PAD_MARGIN: + case RD_SCAN_PAD_BOUND_E: + default: + break; + } + } + } + if ((pBD->Bound_End == 0) && (pBD->Bound_width != 0)) + pBD->Bound_End = pBD->Bound_Start + pBD->Bound_width - 1; + + return 0; +} + +static int autok_calc_bit_cnt(unsigned int result) +{ + unsigned int cnt = 0; + + if (result == 0) + return 0; + else if (result == 0xFFFFFFFF) + return 32; + + do { + if (result & 0x1) + cnt++; + + result = result >> 1; + } while (result); + + return cnt; +} + +static int autok_ta_sel(u32 *raw_list, u32 *pmid) +{ + unsigned int i = 0; + unsigned int raw = 0; + unsigned int r_start = 0; /* range start */ + unsigned int r_stop = 7; /* range stop */ + unsigned int score = 0; + unsigned int score_max = 0; + unsigned int score_max_id = 0; + unsigned int inaccuracy = TUNING_INACCURACY; + + for (i = 0; i <= 7; i++) { + score = autok_calc_bit_cnt(raw_list[i] ^ 0xFFFFFFFF); + if (score > score_max) { + score_max = score; + score_max_id = i; + } + } + if (score_max < 5) + return -1; + + raw = raw_list[score_max_id]; + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]The maximum offset is %d\r\n", + score_max_id); +FIND: + for (i = 0; i <= 7; i++) { + if (autok_calc_bit_cnt(raw_list[i] ^ raw) <= inaccuracy) { + r_start = i; + break; + } + } + for (i = 7; i >= 0; i--) { + if (autok_calc_bit_cnt(raw_list[i] ^ raw) <= inaccuracy) { + r_stop = i; + break; + } + } + if ((r_start + 2) <= r_stop) { + /* At least get the TA of which the margin has either left 1T and right 1T */ + *pmid = (r_start + r_stop + 1) / 2; + } else { + inaccuracy++; + if (inaccuracy < 5) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, "Enlarge the inaccuracy[%d]\r\n", inaccuracy); + goto FIND; + } + } + if (*pmid) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]Find suitable range[%d %d], TA_sel=%d\r\n", + r_start, r_stop, *pmid); + } else { + *pmid = score_max_id; + AUTOK_DBGPRINT(AUTOK_DBG_RES, "Un-expected pattern, pls check!, TA_sel=%d\r\n", + *pmid); + } + + return 0; +} + +static int autok_pad_dly_sel(struct AUTOK_REF_INFO *pInfo) +{ + struct AUTOK_SCAN_RES *pBdInfo_R = NULL; /* scan result @ rising edge */ + struct AUTOK_SCAN_RES *pBdInfo_F = NULL; /* scan result @ falling edge */ + struct BOUND_INFO *pBdPrev = NULL; /* Save the first boundary info for calc optimised dly count */ + struct BOUND_INFO *pBdNext = NULL; /* Save the second boundary info for calc optimised dly count */ + struct BOUND_INFO *pBdTmp = NULL; + unsigned int FBound_Cnt_R = 0; /* Full Boundary count */ + unsigned int Bound_Cnt_R = 0; + unsigned int Bound_Cnt_F = 0; + unsigned int cycle_cnt = 64; + int uBD_mid_prev = 0; + int uBD_mid_next = 0; + int uBD_width = 3; + int uDlySel_F = 0; + int uDlySel_R = 0; + int uMgLost_F = 0; /* for falling edge margin compress */ + int uMgLost_R = 0; /* for rising edge margin compress */ + unsigned int i; + unsigned int ret = 0; + + pBdInfo_R = &(pInfo->scan_info[0]); + pBdInfo_F = &(pInfo->scan_info[1]); + FBound_Cnt_R = pBdInfo_R->fbd_cnt; + Bound_Cnt_R = pBdInfo_R->bd_cnt; + Bound_Cnt_F = pBdInfo_F->bd_cnt; + + switch (FBound_Cnt_R) { + case 4: /* SSSS Corner may cover 2~3T */ + case 3: + AUTOK_RAWPRINT("[ATUOK]Warning: Too Many Full boundary count:%d\r\n", FBound_Cnt_R); + case 2: /* mode_1 : 2 full boudary */ + for (i = 0; i < BD_MAX_CNT; i++) { + if (pBdInfo_R->bd_info[i].is_fullbound) { + if (pBdPrev == NULL) { + pBdPrev = &(pBdInfo_R->bd_info[i]); + } else { + pBdNext = &(pBdInfo_R->bd_info[i]); + break; + } + } + } + + if (pBdPrev && pBdNext) { + uBD_mid_prev = (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + uBD_mid_next = (pBdNext->Bound_Start + pBdNext->Bound_End) / 2; + /* while in 2 full bound case, bd_width calc */ + uBD_width = (pBdPrev->Bound_width + pBdNext->Bound_width) / 2; + cycle_cnt = uBD_mid_next - uBD_mid_prev; + /* delay count sel at rising edge */ + if (uBD_mid_prev >= cycle_cnt / 2) { + uDlySel_R = uBD_mid_prev - cycle_cnt / 2; + uMgLost_R = 0; + } else if ((cycle_cnt / 2 - uBD_mid_prev) > AUTOK_MARGIN_THOLD) { + uDlySel_R = uBD_mid_prev + cycle_cnt / 2; + uMgLost_R = 0; + } else { + uDlySel_R = 0; + uMgLost_R = cycle_cnt / 2 - uBD_mid_prev; + } + /* delay count sel at falling edge */ + pBdTmp = &(pBdInfo_R->bd_info[0]); + if (pBdTmp->is_fullbound) { + /* ooooxxxooooooxxxooo */ + uDlySel_F = uBD_mid_prev; + uMgLost_F = 0; + } else { + /* xooooooxxxoooooooxxxoo */ + if (pBdTmp->Bound_End > uBD_width / 2) { + uDlySel_F = (pBdTmp->Bound_End) - (uBD_width / 2); + uMgLost_F = 0; + } else { + uDlySel_F = 0; + uMgLost_F = (uBD_width / 2) - (pBdTmp->Bound_End); + } + } + } else { + /* error can not find 2 foull boary */ + AUTOK_RAWPRINT("[AUTOK]error can not find 2 foull boudary @ Mode_1"); + return -1; + } + break; + + case 1: /* rising edge find one full boundary */ + if (Bound_Cnt_R > 1) { + /* mode_2: 1 full boundary and boundary count > 1 */ + pBdPrev = &(pBdInfo_R->bd_info[0]); + pBdNext = &(pBdInfo_R->bd_info[1]); + + if (pBdPrev->is_fullbound) + uBD_width = pBdPrev->Bound_width; + else + uBD_width = pBdNext->Bound_width; + + if ((pBdPrev->is_fullbound) || (pBdNext->is_fullbound)) { + if (pBdPrev->Bound_Start > 0) + cycle_cnt = pBdNext->Bound_Start - pBdPrev->Bound_Start; + else + cycle_cnt = pBdNext->Bound_End - pBdPrev->Bound_End; + + /* delay count sel@rising & falling edge */ + if (pBdPrev->is_fullbound) { + uBD_mid_prev = (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + uDlySel_F = uBD_mid_prev; + uMgLost_F = 0; + if (uBD_mid_prev >= cycle_cnt / 2) { + uDlySel_R = uBD_mid_prev - cycle_cnt / 2; + uMgLost_R = 0; + } else if ((cycle_cnt / 2 - uBD_mid_prev) > + AUTOK_MARGIN_THOLD) { + uDlySel_R = uBD_mid_prev + cycle_cnt / 2; + uMgLost_R = 0; + } else { + uDlySel_R = 0; + uMgLost_R = cycle_cnt / 2 - uBD_mid_prev; + } + } else { + /* first boundary not full boudary */ + uBD_mid_next = (pBdNext->Bound_Start + pBdNext->Bound_End) / 2; + uDlySel_R = uBD_mid_next - cycle_cnt / 2; + uMgLost_R = 0; + if (pBdPrev->Bound_End > uBD_width / 2) { + uDlySel_F = (pBdPrev->Bound_End) - (uBD_width / 2); + uMgLost_F = 0; + } else { + uDlySel_F = 0; + uMgLost_F = (uBD_width / 2) - (pBdPrev->Bound_End); + } + } + } else { + return -1; /* full bound must in first 2 boundary */ + } + } else if (Bound_Cnt_F > 0) { + /* mode_3: 1 full boundary and only one boundary exist @rising edge */ + pBdPrev = &(pBdInfo_R->bd_info[0]); /* this boundary is full bound */ + pBdNext = &(pBdInfo_F->bd_info[0]); + uBD_mid_prev = (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + uBD_width = pBdPrev->Bound_width; + + if (pBdNext->Bound_Start == 0) { + cycle_cnt = (pBdPrev->Bound_End - pBdNext->Bound_End) * 2; + } else if (pBdNext->Bound_End == 63) { + cycle_cnt = (pBdNext->Bound_Start - pBdPrev->Bound_Start) * 2; + } else { + uBD_mid_next = (pBdNext->Bound_Start + pBdNext->Bound_End) / 2; + + if (uBD_mid_next > uBD_mid_prev) + cycle_cnt = (uBD_mid_next - uBD_mid_prev) * 2; + else + cycle_cnt = (uBD_mid_prev - uBD_mid_next) * 2; + } + + uDlySel_F = uBD_mid_prev; + uMgLost_F = 0; + + if (uBD_mid_prev >= cycle_cnt / 2) { /* case 1 */ + uDlySel_R = uBD_mid_prev - cycle_cnt / 2; + uMgLost_R = 0; + } else if (cycle_cnt / 2 - uBD_mid_prev <= AUTOK_MARGIN_THOLD) { /* case 2 */ + uDlySel_R = 0; + uMgLost_R = cycle_cnt / 2 - uBD_mid_prev; + } else if (cycle_cnt / 2 + uBD_mid_prev <= 63) { /* case 3 */ + uDlySel_R = cycle_cnt / 2 + uBD_mid_prev; + uMgLost_R = 0; + } else if (32 - uBD_mid_prev <= AUTOK_MARGIN_THOLD) { /* case 4 */ + uDlySel_R = 0; + uMgLost_R = cycle_cnt / 2 - uBD_mid_prev; + } else { /* case 5 */ + uDlySel_R = 63; + uMgLost_R = uBD_mid_prev + cycle_cnt / 2 - 63; + } + } else { + /* mode_4: falling edge no boundary found & rising edge only one full boundary exist */ + pBdPrev = &(pBdInfo_R->bd_info[0]); /* this boundary is full bound */ + uBD_mid_prev = (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + uBD_width = pBdPrev->Bound_width; + + if (pBdPrev->Bound_End > (64 - pBdPrev->Bound_Start)) + cycle_cnt = 2 * (pBdPrev->Bound_End + 1); + else + cycle_cnt = 2 * (64 - pBdPrev->Bound_Start); + + uDlySel_R = 0xFF; + uMgLost_R = 0xFF; /* Margin enough donot care margin lost */ + uDlySel_F = uBD_mid_prev; + uMgLost_F = 0xFF; /* Margin enough donot care margin lost */ + + AUTOK_RAWPRINT("[AUTOK]Warning: 1T > %d\r\n", cycle_cnt); + } + break; + + case 0: /* rising edge cannot find full boudary */ + if (Bound_Cnt_R == 2) { + pBdPrev = &(pBdInfo_R->bd_info[0]); + pBdNext = &(pBdInfo_F->bd_info[0]); /* this boundary is full bound */ + + if (pBdNext->is_fullbound) { + /* mode_5: rising_edge 2 boundary (not full bound), falling edge 1 full boundary */ + uBD_width = pBdNext->Bound_width; + cycle_cnt = 2 * (pBdNext->Bound_End - pBdPrev->Bound_End); + uBD_mid_next = (pBdNext->Bound_Start + pBdNext->Bound_End) / 2; + uDlySel_R = uBD_mid_next; + uMgLost_R = 0; + if (pBdPrev->Bound_End >= uBD_width / 2) { + uDlySel_F = pBdPrev->Bound_End - uBD_width / 2; + uMgLost_F = 0; + } else { + uDlySel_F = 0; + uMgLost_F = uBD_width / 2 - pBdPrev->Bound_End; + } + } else { + /* for falling edge there must be one full boundary between two bounary_mid at rising + * this is a corner case, falling boundary may scan miss. + * xoooooooooooooooox or xoooooooooooooooox or xoooooooooooooooox + * oooooooooooooooooo xxoooooooooooooooo ooooooooooooooooox + */ + pInfo->cycle_cnt = pBdInfo_R->bd_info[1].Bound_End + - pBdInfo_R->bd_info[0].Bound_Start; + if (Bound_Cnt_F == 0) { + pInfo->opt_edge_sel = 1; + pInfo->opt_dly_cnt = 0; + } else { + pInfo->opt_edge_sel = 0; + pInfo->opt_dly_cnt = (pBdInfo_R->bd_info[1].Bound_End + + pBdInfo_R->bd_info[0].Bound_Start) / 2; + } + return ret; + } + } else if (Bound_Cnt_R == 1) { + if (Bound_Cnt_F > 1) { + /* when rising_edge have only one boundary (not full bound), + * falling edge should not more than 1Bound exist + * this is a corner case, rising boundary may scan miss. + * xooooooooooooooooo + * oooxooooooooxooooo + */ + pInfo->cycle_cnt = (pBdInfo_F->bd_info[1].Bound_End + + pBdInfo_F->bd_info[1].Bound_Start) / 2 + - (pBdInfo_F->bd_info[0].Bound_End + + pBdInfo_F->bd_info[0].Bound_Start) / 2; + pInfo->opt_edge_sel = 1; + pInfo->opt_dly_cnt = ((pBdInfo_F->bd_info[1].Bound_End + + pBdInfo_F->bd_info[1].Bound_Start) / 2 + + (pBdInfo_F->bd_info[0].Bound_End + + pBdInfo_F->bd_info[0].Bound_Start) / 2) / 2; + return ret; + } else if (Bound_Cnt_F == 1) { + /* mode_6: rising edge only 1 boundary (not full Bound) + & falling edge have only 1 bound too */ + pBdPrev = &(pBdInfo_R->bd_info[0]); + pBdNext = &(pBdInfo_F->bd_info[0]); + if (pBdNext->is_fullbound) { + uBD_width = pBdNext->Bound_width; + } else { + if (pBdNext->Bound_width > pBdPrev->Bound_width) + uBD_width = (pBdNext->Bound_width + 1); + else + uBD_width = (pBdPrev->Bound_width + 1); + + if (uBD_width < AUTOK_BD_WIDTH_REF) + uBD_width = AUTOK_BD_WIDTH_REF; + } /* Boundary width calc done */ + + if (pBdPrev->Bound_Start == 0) { + /* Current Desing Not Allowed */ + if (pBdNext->Bound_Start == 0) { + /* Current Desing Not Allowed + * this is a corner case, boundary may scan error. + * xooooooooooooooooo + * xooooooooooooooooo + */ + pInfo->cycle_cnt = 2 * (64 - (pBdInfo_R->bd_info[0].Bound_End + + pBdInfo_R->bd_info[0].Bound_Start) / 2); + pInfo->opt_edge_sel = 0; + pInfo->opt_dly_cnt = 31; + return ret; + } + + cycle_cnt = + (pBdNext->Bound_Start - pBdPrev->Bound_End + + uBD_width) * 2; + } else if (pBdPrev->Bound_End == 63) { + /* Current Desing Not Allowed */ + if (pBdNext->Bound_End == 63) { + /* Current Desing Not Allowed + * this is a corner case, boundary may scan error. + * ooooooooooooooooox + * ooooooooooooooooox + */ + pInfo->cycle_cnt = pBdInfo_R->bd_info[0].Bound_End + + pBdInfo_R->bd_info[0].Bound_Start; + pInfo->opt_edge_sel = 0; + pInfo->opt_dly_cnt = 31; + return ret; + } + + cycle_cnt = + (pBdPrev->Bound_Start - pBdNext->Bound_End + + uBD_width) * 2; + } /* cycle count calc done */ + + /* calc optimise delay count */ + if (pBdPrev->Bound_Start == 0) { + /* falling edge sel */ + if (pBdPrev->Bound_End >= uBD_width / 2) { + uDlySel_F = pBdPrev->Bound_End - uBD_width / 2; + uMgLost_F = 0; + } else { + uDlySel_F = 0; + uMgLost_F = uBD_width / 2 - pBdPrev->Bound_End; + } + + /* rising edge sel */ + if (pBdPrev->Bound_End - uBD_width / 2 + cycle_cnt / 2 > 63) { + uDlySel_R = 63; + uMgLost_R = + pBdPrev->Bound_End - uBD_width / 2 + + cycle_cnt / 2 - 63; + } else { + uDlySel_R = + pBdPrev->Bound_End - uBD_width / 2 + + cycle_cnt / 2; + uMgLost_R = 0; + } + } else if (pBdPrev->Bound_End == 63) { + /* falling edge sel */ + if (pBdPrev->Bound_Start + uBD_width / 2 < 63) { + uDlySel_F = pBdPrev->Bound_Start + uBD_width / 2; + uMgLost_F = 0; + } else { + uDlySel_F = 63; + uMgLost_F = + pBdPrev->Bound_Start + uBD_width / 2 - 63; + } + + /* rising edge sel */ + if (pBdPrev->Bound_Start + uBD_width / 2 - cycle_cnt / 2 < 0) { + uDlySel_R = 0; + uMgLost_R = + cycle_cnt / 2 - (pBdPrev->Bound_Start + + uBD_width / 2); + } else { + uDlySel_R = + pBdPrev->Bound_Start + uBD_width / 2 - + cycle_cnt / 2; + uMgLost_R = 0; + } + } else { + return -1; + } + } else if (Bound_Cnt_F == 0) { + /* mode_7: rising edge only one bound (not full), falling no boundary */ + cycle_cnt = 128; + pBdPrev = &(pBdInfo_R->bd_info[0]); + if (pBdPrev->Bound_Start == 0) { + uDlySel_F = 0; + uDlySel_R = 63; + } else if (pBdPrev->Bound_End == 63) { + uDlySel_F = 63; + uDlySel_R = 0xFF; + } else { + return -1; + } + uMgLost_F = 0xFF; + uMgLost_R = 0xFF; + + AUTOK_RAWPRINT("[AUTOK]Warning: 1T > %d\r\n", cycle_cnt); + } + } else if (Bound_Cnt_R == 0) { /* Rising Edge No Boundary found */ + if (Bound_Cnt_F > 1) { + /* falling edge not allowed two boundary Exist for this case + * this is a corner case,rising boundary may scan miss. + * oooooooooooooooooo + * oooxooooooooxooooo + */ + pInfo->cycle_cnt = (pBdInfo_F->bd_info[1].Bound_End + + pBdInfo_F->bd_info[1].Bound_Start) / 2 + - (pBdInfo_F->bd_info[0].Bound_End + + pBdInfo_F->bd_info[0].Bound_Start) / 2; + pInfo->opt_edge_sel = 0; + pInfo->opt_dly_cnt = (pBdInfo_F->bd_info[0].Bound_End + + pBdInfo_F->bd_info[0].Bound_Start) / 2; + return ret; + } else if (Bound_Cnt_F > 0) { + /* mode_8: falling edge have one Boundary exist */ + pBdPrev = &(pBdInfo_F->bd_info[0]); + + /* this boundary is full bound */ + if (pBdPrev->is_fullbound) { + uBD_mid_prev = + (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + + if (pBdPrev->Bound_End > (64 - pBdPrev->Bound_Start)) + cycle_cnt = 2 * (pBdPrev->Bound_End + 1); + else + cycle_cnt = 2 * (64 - pBdPrev->Bound_Start); + + uDlySel_R = uBD_mid_prev; + uMgLost_R = 0xFF; + uDlySel_F = 0xFF; + uMgLost_F = 0xFF; + } else { + cycle_cnt = 128; + + uDlySel_R = (pBdPrev->Bound_Start == 0) ? 0 : 63; + uMgLost_R = 0xFF; + uDlySel_F = 0xFF; + uMgLost_F = 0xFF; + } + + AUTOK_RAWPRINT("[AUTOK]Warning: 1T > %d\r\n", cycle_cnt); + } else { + /* falling edge no boundary exist no need tuning */ + cycle_cnt = 128; + uDlySel_F = 0; + uMgLost_F = 0xFF; + uDlySel_R = 0; + uMgLost_R = 0xFF; + AUTOK_RAWPRINT("[AUTOK]Warning: 1T > %d\r\n", cycle_cnt); + } + } else { + /* Error if bound_cnt > 3 there must be at least one full boundary exist */ + return -1; + } + break; + + default: + /* warning if boundary count > 4 (from current hw design, this case cannot happen) */ + return -1; + } + + /* Select Optimised Sample edge & delay count (the small one) */ + pInfo->cycle_cnt = cycle_cnt; + if (uDlySel_R <= uDlySel_F) { + pInfo->opt_edge_sel = 0; + pInfo->opt_dly_cnt = uDlySel_R; + } else { + pInfo->opt_edge_sel = 1; + pInfo->opt_dly_cnt = uDlySel_F; + + } + AUTOK_RAWPRINT("[AUTOK]Analysis Result: 1T = %d\r\n ", cycle_cnt); + return ret; +} + +static int +autok_pad_dly_sel_single_edge(struct AUTOK_SCAN_RES *pInfo, unsigned int cycle_cnt_ref, + unsigned int *pDlySel) +{ + struct BOUND_INFO *pBdPrev = NULL; /* Save the first boundary info for calc optimised dly count */ + struct BOUND_INFO *pBdNext = NULL; /* Save the second boundary info for calc optimised dly count */ + unsigned int Bound_Cnt = 0; + unsigned int uBD_mid_prev = 0; + int uDlySel = 0; + int uMgLost = 0; + unsigned int ret = 0; + + Bound_Cnt = pInfo->bd_cnt; + if (Bound_Cnt > 1) { + pBdPrev = &(pInfo->bd_info[0]); + pBdNext = &(pInfo->bd_info[1]); + if (!(pBdPrev->is_fullbound)) { + /* mode_1: at least 2 Bound and Boud0_Start == 0 */ + uDlySel = (pBdPrev->Bound_End + pBdNext->Bound_Start) / 2; + uMgLost = (uDlySel > 31) ? (uDlySel - 31) : 0; + uDlySel = (uDlySel > 31) ? 31 : uDlySel; + + } else { + /* mode_2: at least 2 Bound found and Bound0_Start != 0 */ + uBD_mid_prev = (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + if (uBD_mid_prev >= cycle_cnt_ref / 2) { + uDlySel = uBD_mid_prev - cycle_cnt_ref / 2; + uMgLost = 0; + } else if (cycle_cnt_ref / 2 - uBD_mid_prev < AUTOK_MARGIN_THOLD) { + uDlySel = 0; + uMgLost = cycle_cnt_ref / 2 - uBD_mid_prev; + } else { + uDlySel = (pBdPrev->Bound_End + pBdNext->Bound_Start) / 2; + if ((uDlySel > 31) && (uDlySel - 31 < AUTOK_MARGIN_THOLD)) { + uDlySel = 31; + uMgLost = uDlySel - 31; + } else { + uMgLost = 0; + } + } + } + } else if (Bound_Cnt > 0) { + /* only one bound fond */ + pBdPrev = &(pInfo->bd_info[0]); + if (pBdPrev->is_fullbound) { + /* mode_3: Bound_S != 0 */ + uBD_mid_prev = (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + if (uBD_mid_prev >= cycle_cnt_ref / 2) { + uDlySel = uBD_mid_prev - cycle_cnt_ref / 2; + uMgLost = 0; + } else if (cycle_cnt_ref / 2 - uBD_mid_prev < AUTOK_MARGIN_THOLD) { + uDlySel = 0; + uMgLost = cycle_cnt_ref / 2 - uBD_mid_prev; + } else if ((uBD_mid_prev > 31 - AUTOK_MARGIN_THOLD) + || (pBdPrev->Bound_Start >= 16)) { + uDlySel = 0; + uMgLost = cycle_cnt_ref / 2 - uBD_mid_prev; + } else if (uBD_mid_prev + cycle_cnt_ref / 2 <= 63) { + /* Left Margin not enough must need to select the right side */ + uDlySel = uBD_mid_prev + cycle_cnt_ref / 2; + uMgLost = 0; + } else { + uDlySel = 63; + uMgLost = uBD_mid_prev + cycle_cnt_ref / 2 - 63; + } + } else if (pBdPrev->Bound_Start == 0) { + /* mode_4 : Only one Boud and Boud_S = 0 (Currently 1T nearly equal 64 ) */ + + /* May not exactly by for Cycle_Cnt enough can don't care */ + uBD_mid_prev = (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + if (pBdPrev->Bound_Start + cycle_cnt_ref / 2 >= 31) { + uDlySel = 31; + uMgLost = uBD_mid_prev + cycle_cnt_ref / 2 - 31; + } else { + uDlySel = uBD_mid_prev + cycle_cnt_ref / 2; + uMgLost = 0; + } + } else { + /* mode_5: Only one Boud and Boud_E = 64 */ + + /* May not exactly by for Cycle_Cnt enough can don't care */ + uBD_mid_prev = (pBdPrev->Bound_Start + pBdPrev->Bound_End) / 2; + if (pBdPrev->Bound_Start < cycle_cnt_ref / 2) { + uDlySel = 0; + uMgLost = cycle_cnt_ref / 2 - uBD_mid_prev; + } else if (uBD_mid_prev - cycle_cnt_ref / 2 > 31) { + uDlySel = 31; + uMgLost = uBD_mid_prev - cycle_cnt_ref / 2 - 31; + } else { + uDlySel = uBD_mid_prev - cycle_cnt_ref / 2; + uMgLost = 0; + } + } + } else { /*mode_6: no bound foud */ + uDlySel = 31; + uMgLost = 0xFF; + } + *pDlySel = uDlySel; + if (uDlySel > 31) { + AUTOK_RAWPRINT + ("[AUTOK]Warning Dly Sel %d > 31 easily effected by Voltage Swing\r\n", + uDlySel); + } + + return ret; +} + +static int autok_ds_dly_sel(struct AUTOK_SCAN_RES *pInfo, unsigned int *pDlySel, u8 *param) +{ + unsigned int ret = 0; + int uDlySel = 0; + unsigned int Bound_Cnt = pInfo->bd_cnt; + + if (pInfo->fbd_cnt > 0) { + /* no more than 2 boundary exist */ + AUTOK_RAWPRINT("[AUTOK]Error: Scan DS Not allow Full boundary Occurs!\r\n"); + return -1; + } + + if (Bound_Cnt > 1) { + /* bound count == 2 */ + uDlySel = (pInfo->bd_info[0].Bound_End + pInfo->bd_info[1].Bound_Start) / 2; + } else if (Bound_Cnt > 0) { + /* bound count == 1 */ + if (pInfo->bd_info[0].Bound_Start == 0) { + if (pInfo->bd_info[0].Bound_End > 31) { + uDlySel = (pInfo->bd_info[0].Bound_End + 64) / 2; + AUTOK_RAWPRINT("[AUTOK]Warning: DS Delay not in range 0~31!\r\n"); + } else { + uDlySel = (pInfo->bd_info[0].Bound_End + 31) / 2; + } + } else + uDlySel = pInfo->bd_info[0].Bound_Start / 2; + } else { + /* bound count == 0 */ + uDlySel = 16; + } + *pDlySel = uDlySel; + + return ret; +} + +/************************************************************************* +* FUNCTION +* msdc_autok_adjust_param +* +* DESCRIPTION +* This function for auto-K, adjust msdc parameter +* +* PARAMETERS +* host: msdc host manipulator pointer +* param: enum of msdc parameter +* value: value of msdc parameter +* rw: AUTOK_READ/AUTOK_WRITE +* +* RETURN VALUES +* error code: 0 success, +* -1 parameter input error +* -2 read/write fail +* -3 else error +*************************************************************************/ +static int msdc_autok_adjust_param(struct msdc_host *host, enum AUTOK_PARAM param, u32 *value, + int rw) +{ + void __iomem *base = host->base; + u32 *reg; + u32 field = 0; + + switch (param) { + case READ_DATA_SMPL_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for READ_DATA_SMPL_SEL is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + + reg = (u32 *) MSDC_IOCON; + field = (u32) (MSDC_IOCON_R_D_SMPL_SEL); + break; + case WRITE_DATA_SMPL_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for WRITE_DATA_SMPL_SEL is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + + reg = (u32 *) MSDC_IOCON; + field = (u32) (MSDC_IOCON_W_D_SMPL_SEL); + break; + case DATA_DLYLINE_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for DATA_DLYLINE_SEL is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + + reg = (u32 *) MSDC_IOCON; + field = (u32) (MSDC_IOCON_DDLSEL); + break; + case MSDC_DAT_TUNE_SEL: /* 0-Dat tune 1-CLk tune ; */ + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for DATA_DLYLINE_SEL is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE0; + field = (u32) (MSDC_PAD_TUNE0_RXDLYSEL); + break; + case MSDC_WCRC_ASYNC_FIFO_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for DATA_DLYLINE_SEL is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PATCH_BIT2; + field = (u32) (MSDC_PB2_CFGCRCSTS); + break; + case MSDC_RESP_ASYNC_FIFO_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for DATA_DLYLINE_SEL is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PATCH_BIT2; + field = (u32) (MSDC_PB2_CFGRESP); + break; + case CMD_EDGE: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for CMD_EDGE is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_IOCON; + field = (u32) (MSDC_IOCON_RSPL); + break; + case RDATA_EDGE: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for RDATA_EDGE is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_IOCON; + field = (u32) (MSDC_IOCON_R_D_SMPL); + break; + case RD_FIFO_EDGE: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for RDATA_EDGE is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PATCH_BIT0; + field = (u32) (MSDC_PB0_RD_DAT_SEL); + break; + case WD_FIFO_EDGE: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for WDATA_EDGE is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PATCH_BIT2; + field = (u32) (MSDC_PB2_CFGCRCSTSEDGE); + break; + case CMD_RD_D_DLY1: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for CMD_RD_DLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE0; + field = (u32) (MSDC_PAD_TUNE0_CMDRDLY); + break; + case CMD_RD_D_DLY1_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for CMD_RD_DLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE0; + field = (u32) (MSDC_PAD_TUNE0_CMDRRDLYSEL); + break; + case CMD_RD_D_DLY2: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for CMD_RD_DLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE1; + field = (u32) (MSDC_PAD_TUNE1_CMDRDLY2); + break; + case CMD_RD_D_DLY2_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for CMD_RD_DLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE1; + field = (u32) (MSDC_PAD_TUNE1_CMDRRDLY2SEL); + break; + case DAT_RD_D_DLY1: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for DAT0_RD_DLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE0; + field = (u32) (MSDC_PAD_TUNE0_DATRRDLY); + break; + case DAT_RD_D_DLY1_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for CMD_RD_DLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE0; + field = (u32) (MSDC_PAD_TUNE0_DATRRDLYSEL); + break; + case DAT_RD_D_DLY2: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for DAT1_RD_DLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE1; + field = (u32) (MSDC_PAD_TUNE1_DATRRDLY2); + break; + case DAT_RD_D_DLY2_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for CMD_RD_DLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE1; + field = (u32) (MSDC_PAD_TUNE1_DATRRDLY2SEL); + break; + case INT_DAT_LATCH_CK: + if ((rw == AUTOK_WRITE) && (*value > 7)) { + pr_debug + ("[%s] Input value(%d) for INT_DAT_LATCH_CK is out of range, it should be [0~7]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PATCH_BIT0; + field = (u32) (MSDC_PB0_INT_DAT_LATCH_CK_SEL); + break; + case CKGEN_MSDC_DLY_SEL: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for CKGEN_MSDC_DLY_SEL is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PATCH_BIT0; + field = (u32) (MSDC_PB0_CKGEN_MSDC_DLY_SEL); + break; + case CMD_RSP_TA_CNTR: + if ((rw == AUTOK_WRITE) && (*value > 7)) { + pr_debug + ("[%s] Input value(%d) for CMD_RSP_TA_CNTR is out of range, it should be [0~7]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PATCH_BIT1; + field = (u32) (MSDC_PB1_CMD_RSP_TA_CNTR); + break; + case WRDAT_CRCS_TA_CNTR: + if ((rw == AUTOK_WRITE) && (*value > 7)) { + pr_debug + ("[%s] Input value(%d) for WRDAT_CRCS_TA_CNTR is out of range, it should be [0~7]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PATCH_BIT1; + field = (u32) (MSDC_PB1_WRDAT_CRCS_TA_CNTR); + break; + case PAD_CLK_TXDLY: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for PAD_CLK_TXDLY is out of range, it should be [0~31]\n", + __func__, *value); + return -1; + } + reg = (u32 *) MSDC_PAD_TUNE0; + field = (u32) (MSDC_PAD_TUNE0_CLKTXDLY); + break; + case EMMC50_WDATA_MUX_EN: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for EMMC50_WDATA_MUX_EN is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) EMMC50_CFG0; + field = (u32) (MSDC_EMMC50_CFG_CRC_STS_SEL); + break; + case EMMC50_CMD_MUX_EN: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for EMMC50_CMD_MUX_EN is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) EMMC50_CFG0; + field = (u32) (MSDC_EMMC50_CFG_CMD_RESP_SEL); + break; + case EMMC50_WDATA_EDGE: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for EMMC50_WDATA_EDGE is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) EMMC50_CFG0; + field = (u32) (MSDC_EMMC50_CFG_CRC_STS_EDGE); + break; + case EMMC50_DS_Z_DLY1: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for EMMC50_DS_Z_DLY1 is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) EMMC50_PAD_DS_TUNE; + field = (u32) (MSDC_EMMC50_PAD_DS_TUNE_DLY1); + break; + case EMMC50_DS_Z_DLY1_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for EMMC50_DS_Z_DLY1_SEL is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) EMMC50_PAD_DS_TUNE; + field = (u32) (MSDC_EMMC50_PAD_DS_TUNE_DLYSEL); + break; + case EMMC50_DS_Z_DLY2: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for EMMC50_DS_Z_DLY2 is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) EMMC50_PAD_DS_TUNE; + field = (u32) (MSDC_EMMC50_PAD_DS_TUNE_DLY2); + break; + case EMMC50_DS_Z_DLY2_SEL: + if ((rw == AUTOK_WRITE) && (*value > 1)) { + pr_debug + ("[%s] Input value(%d) for EMMC50_DS_Z_DLY1_SEL is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) EMMC50_PAD_DS_TUNE; + field = (u32) (MSDC_EMMC50_PAD_DS_TUNE_DLY2SEL); + break; + case EMMC50_DS_ZDLY_DLY: + if ((rw == AUTOK_WRITE) && (*value > 31)) { + pr_debug + ("[%s] Input value(%d) for EMMC50_DS_Z_DLY2 is out of range, it should be [0~1]\n", + __func__, *value); + return -1; + } + reg = (u32 *) EMMC50_PAD_DS_TUNE; + field = (u32) (MSDC_EMMC50_PAD_DS_TUNE_DLY3); + break; + default: + pr_debug("[%s] Value of [enum AUTOK_PARAM param] is wrong\n", __func__); + return -1; + } + + if (rw == AUTOK_READ) + MSDC_GET_FIELD(reg, field, *value); + else if (rw == AUTOK_WRITE) { + MSDC_SET_FIELD(reg, field, *value); + + if (param == CKGEN_MSDC_DLY_SEL) + mdelay(1); + } else { + pr_debug("[%s] Value of [int rw] is wrong\n", __func__); + return -1; + } + + return 0; +} + +static int autok_param_update(enum AUTOK_PARAM param_id, unsigned int result, u8 *autok_tune_res) +{ + if (param_id < TUNING_PARAM_COUNT) { + if ((result > autok_param_info[param_id].range.end) || + (result < autok_param_info[param_id].range.start)) { + AUTOK_RAWPRINT("[AUTOK]param outof range : %d not in [%d,%d]\r\n", + result, autok_param_info[param_id].range.start, + autok_param_info[param_id].range.end); + return -1; + } else { + autok_tune_res[param_id] = (u8) result; + return 0; + } + } + AUTOK_RAWPRINT("[AUTOK]param not found\r\n"); + + return -1; +} + +static int autok_param_apply(struct msdc_host *host, u8 *autok_tune_res) +{ + unsigned int i = 0; + unsigned int value = 0; + + for (i = 0; i < TUNING_PARAM_COUNT; i++) { + value = (u8) autok_tune_res[i]; + msdc_autok_adjust_param(host, i, &value, AUTOK_WRITE); + } + + return 0; +} + +static int autok_result_dump(struct msdc_host *host, u8 *autok_tune_res) +{ + AUTOK_RAWPRINT("[AUTOK]CMD [EDGE:%d DLY1:%d DLY2:%d ]\r\n", + autok_tune_res[0], autok_tune_res[4], autok_tune_res[6]); + AUTOK_RAWPRINT("[AUTOK]DAT [RDAT_EDGE:%d RD_FIFO_EDGE:%d WD_FIFO_EDGE:%d]\r\n", + autok_tune_res[1], autok_tune_res[2], autok_tune_res[3]); + AUTOK_RAWPRINT("[AUTOK]DAT [LATCH_CK:%d DLY1:%d DLY2:%d ]\r\n", + autok_tune_res[12], autok_tune_res[8], autok_tune_res[10]); + AUTOK_RAWPRINT("[AUTOK]DS [DLY1:%d DLY2:%d DLY3:%d]\r\n", + autok_tune_res[13], autok_tune_res[15], autok_tune_res[17]); + + return 0; +} + +#if AUTOK_PARAM_DUMP_ENABLE +static int autok_register_dump(struct msdc_host *host) +{ + unsigned int i = 0; + unsigned int value = 0; + + for (i = 0; i < TUNING_PARAM_COUNT; i++) { + msdc_autok_adjust_param(host, i, &value, AUTOK_READ); + AUTOK_RAWPRINT("[AUTOK]reg field %s:%d\r\n", autok_param_info[i].param_name, value); + } + + return 0; +} +#endif + +void autok_tuning_parameter_init(struct msdc_host *host, u8 *res) +{ + unsigned int ret = 0; + /* void __iomem *base = host->base; */ + + /* MSDC_SET_FIELD(MSDC_PATCH_BIT2, 7<<29, 2); */ + /* MSDC_SET_FIELD(MSDC_PATCH_BIT2, 7<<16, 4); */ + + ret = autok_param_apply(host, res); +} + +/******************************************************* +* Function: msdc_autok_adjust_paddly * +* Param : value - delay cnt from 0 to 63 * +* pad_sel - 0 for cmd pad and 1 for data pad * +*******************************************************/ +#define CMD_PAD_RDLY 0 +#define DAT_PAD_RDLY 1 +#define DS_PAD_RDLY 2 +static void msdc_autok_adjust_paddly(struct msdc_host *host, unsigned int *value, + unsigned int pad_sel) +{ + unsigned int uCfgL = 0; + unsigned int uCfgLSel = 0; + unsigned int uCfgH = 0; + unsigned int uCfgHSel = 0; + unsigned int dly_cnt = *value; + + uCfgL = (dly_cnt > 31) ? (31) : dly_cnt; + uCfgH = (dly_cnt > 31) ? (dly_cnt - 32) : 0; + + uCfgLSel = (uCfgL > 0) ? 1 : 0; + uCfgHSel = (uCfgH > 0) ? 1 : 0; + switch (pad_sel) { + case CMD_PAD_RDLY: + msdc_autok_adjust_param(host, CMD_RD_D_DLY1, &uCfgL, AUTOK_WRITE); + msdc_autok_adjust_param(host, CMD_RD_D_DLY2, &uCfgH, AUTOK_WRITE); + + msdc_autok_adjust_param(host, CMD_RD_D_DLY1_SEL, &uCfgLSel, AUTOK_WRITE); + msdc_autok_adjust_param(host, CMD_RD_D_DLY2_SEL, &uCfgHSel, AUTOK_WRITE); + break; + case DAT_PAD_RDLY: + msdc_autok_adjust_param(host, DAT_RD_D_DLY1, &uCfgL, AUTOK_WRITE); + msdc_autok_adjust_param(host, DAT_RD_D_DLY2, &uCfgH, AUTOK_WRITE); + + msdc_autok_adjust_param(host, DAT_RD_D_DLY1_SEL, &uCfgLSel, AUTOK_WRITE); + msdc_autok_adjust_param(host, DAT_RD_D_DLY2_SEL, &uCfgHSel, AUTOK_WRITE); + break; + case DS_PAD_RDLY: + msdc_autok_adjust_param(host, EMMC50_DS_Z_DLY1, &uCfgL, AUTOK_WRITE); + msdc_autok_adjust_param(host, EMMC50_DS_Z_DLY2, &uCfgH, AUTOK_WRITE); + + msdc_autok_adjust_param(host, EMMC50_DS_Z_DLY1_SEL, &uCfgLSel, AUTOK_WRITE); + msdc_autok_adjust_param(host, EMMC50_DS_Z_DLY2_SEL, &uCfgHSel, AUTOK_WRITE); + break; + } +} + +static void autok_paddly_update(unsigned int pad_sel, unsigned int dly_cnt, u8 *autok_tune_res) +{ + unsigned int uCfgL = 0; + unsigned int uCfgLSel = 0; + unsigned int uCfgH = 0; + unsigned int uCfgHSel = 0; + + uCfgL = (dly_cnt > 31) ? (31) : dly_cnt; + uCfgH = (dly_cnt > 31) ? (dly_cnt - 32) : 0; + + uCfgLSel = (uCfgL > 0) ? 1 : 0; + uCfgHSel = (uCfgH > 0) ? 1 : 0; + switch (pad_sel) { + case CMD_PAD_RDLY: + autok_param_update(CMD_RD_D_DLY1, uCfgL, autok_tune_res); + autok_param_update(CMD_RD_D_DLY2, uCfgH, autok_tune_res); + + autok_param_update(CMD_RD_D_DLY1_SEL, uCfgLSel, autok_tune_res); + autok_param_update(CMD_RD_D_DLY2_SEL, uCfgHSel, autok_tune_res); + break; + case DAT_PAD_RDLY: + autok_param_update(DAT_RD_D_DLY1, uCfgL, autok_tune_res); + autok_param_update(DAT_RD_D_DLY2, uCfgH, autok_tune_res); + + autok_param_update(DAT_RD_D_DLY1_SEL, uCfgLSel, autok_tune_res); + autok_param_update(DAT_RD_D_DLY2_SEL, uCfgHSel, autok_tune_res); + break; + case DS_PAD_RDLY: + autok_param_update(EMMC50_DS_Z_DLY1, uCfgL, autok_tune_res); + autok_param_update(EMMC50_DS_Z_DLY2, uCfgH, autok_tune_res); + + autok_param_update(EMMC50_DS_Z_DLY1_SEL, uCfgLSel, autok_tune_res); + autok_param_update(EMMC50_DS_Z_DLY2_SEL, uCfgHSel, autok_tune_res); + break; + } +} + +/******************************************************* +* Exectue tuning IF Implenment * +*******************************************************/ +static int autok_write_param(struct msdc_host *host, enum AUTOK_PARAM param, u32 value) +{ + msdc_autok_adjust_param(host, param, &value, AUTOK_WRITE); + + return 0; +} + +int autok_path_sel(struct msdc_host *host) +{ + void __iomem *base = host->base; + autok_write_param(host, READ_DATA_SMPL_SEL, 0); + autok_write_param(host, WRITE_DATA_SMPL_SEL, 0); + + /* clK tune all data Line share dly */ + autok_write_param(host, DATA_DLYLINE_SEL, 0); + + /* data tune mode select */ +#if defined(CHIP_DENALI_3_DAT_TUNE) + autok_write_param(host, MSDC_DAT_TUNE_SEL, 1); +#else + autok_write_param(host, MSDC_DAT_TUNE_SEL, 0); +#endif + autok_write_param(host, MSDC_WCRC_ASYNC_FIFO_SEL, 1); + autok_write_param(host, MSDC_RESP_ASYNC_FIFO_SEL, 0); + + /* eMMC50 Function Mux */ + /* write path switch to emmc45 */ + autok_write_param(host, EMMC50_WDATA_MUX_EN, 0); + + /* response path switch to emmc45 */ + autok_write_param(host, EMMC50_CMD_MUX_EN, 0); + autok_write_param(host, EMMC50_WDATA_EDGE, 0); + + /* Common Setting Config */ + autok_write_param(host, CKGEN_MSDC_DLY_SEL, AUTOK_CKGEN_VALUE); + autok_write_param(host, CMD_RSP_TA_CNTR, AUTOK_CMD_TA_VALUE); + autok_write_param(host, WRDAT_CRCS_TA_CNTR, AUTOK_CRC_TA_VALUE); + + MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_PB1_GET_BUSY_MA, AUTOK_BUSY_MA_VALUE); + MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_PB1_GET_CRC_MA, AUTOK_CRC_MA_VALUE); + + return 0; +} +EXPORT_SYMBOL(autok_path_sel); + +int autok_init_sdr104(struct msdc_host *host) +{ + void __iomem *base = host->base; + + /* driver may miss data tune path setting in the interim */ + autok_path_sel(host); + + /* if any specific config need modify add here */ + /* LATCH_TA_EN Config for WCRC Path non_HS400 */ + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CRCSTSENSEL, AUTOK_CRC_LATCH_EN_NON_HS400_VALUE); + /* LATCH_TA_EN Config for CMD Path non_HS400 */ + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_RESPSTENSEL, AUTOK_CMD_LATCH_EN_NON_HS400_VALUE); + + /* enable dvfs feature */ + if (host->hw->host_function == MSDC_SDIO) + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_DVFS_EN, 1); + + return 0; +} +EXPORT_SYMBOL(autok_init_sdr104); + +int autok_init_hs200(struct msdc_host *host) +{ + void __iomem *base = host->base; + + /* driver may miss data tune path setting in the interim */ + autok_path_sel(host); + + /* if any specific config need modify add here */ + /* LATCH_TA_EN Config for WCRC Path non_HS400 */ + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CRCSTSENSEL, AUTOK_CRC_LATCH_EN_NON_HS400_VALUE); + /* LATCH_TA_EN Config for CMD Path non_HS400 */ + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_RESPSTENSEL, AUTOK_CMD_LATCH_EN_NON_HS400_VALUE); + + return 0; +} +EXPORT_SYMBOL(autok_init_hs200); + +int autok_init_hs400(struct msdc_host *host) +{ + void __iomem *base = host->base; + /* driver may miss data tune path setting in the interim */ + autok_path_sel(host); + + /* if any specific config need modify add here */ + /* LATCH_TA_EN Config for WCRC Path HS400 */ + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_RESPSTENSEL, AUTOK_CMD_LATCH_EN_HS400_VALUE); + /* LATCH_TA_EN Config for CMD Path HS400 */ + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CRCSTSENSEL, AUTOK_CRC_LATCH_EN_HS400_VALUE); + /* write path switch to emmc50 */ + autok_write_param(host, EMMC50_WDATA_MUX_EN, 1); + /* Specifical for HS400 Path Sel */ + autok_write_param(host, MSDC_WCRC_ASYNC_FIFO_SEL, 0); + + return 0; +} +EXPORT_SYMBOL(autok_init_hs400); + +int execute_online_tuning_hs400(struct msdc_host *host, u8 *res) +{ + void __iomem *base = host->base; + unsigned int ret = 0; + unsigned int response; + unsigned int uCmdEdge = 0; + u64 RawData64 = 0LL; + unsigned int score = 0; + unsigned int j, k; + struct AUTOK_REF_INFO uCmdDatInfo; + struct AUTOK_SCAN_RES *pBdInfo; + char tune_result_str64[65]; + u8 p_autok_tune_res[TUNING_PARAM_COUNT]; + unsigned int opcode = MMC_SEND_STATUS; +#if HS400_DSCLK_NEED_TUNING + u32 RawData = 0; +#endif + unsigned int uDatDly = 0; + + autok_init_hs400(host); + memset((void *)p_autok_tune_res, 0, sizeof(p_autok_tune_res) / sizeof(u8)); + + /* Step1 : Tuning Cmd Path */ + autok_tuning_parameter_init(host, p_autok_tune_res); + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + + uCmdEdge = 0; + do { + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[uCmdEdge]); + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + RawData64 = 0LL; + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, CMD_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES / 2; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + RawData64 |= (u64)(1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD %d \t %d \t %s\r\n", uCmdEdge, score, + tune_result_str64); + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) + return -1; + + #if 0 + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", + uCmdEdge, pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + + for (i = 0; i < BD_MAX_CNT; i++) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[%d]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", i, + pBdInfo->bd_info[i].Bound_Start, pBdInfo->bd_info[i].Bound_End, + pBdInfo->bd_info[i].Bound_width, pBdInfo->bd_info[i].is_fullbound); + } + #endif + + uCmdEdge ^= 0x1; + } while (uCmdEdge); + + if (autok_pad_dly_sel(&uCmdDatInfo) == 0) { + autok_param_update(CMD_EDGE, uCmdDatInfo.opt_edge_sel, p_autok_tune_res); + autok_paddly_update(CMD_PAD_RDLY, uCmdDatInfo.opt_dly_cnt, p_autok_tune_res); + } else { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK][Error]=============Analysis Failed!!=======================\r\n"); + } + /* DLY3 keep default value 20 */ + p_autok_tune_res[EMMC50_DS_ZDLY_DLY] = 20; + /* Step2 : Tuning DS Clk Path-ZCLK only tune DLY1 */ +#ifdef CMDQ + opcode = MMC_SEND_EXT_CSD; +#else + opcode = MMC_READ_SINGLE_BLOCK; +#endif + autok_tuning_parameter_init(host, p_autok_tune_res); + /* check device status */ + ret = autok_send_tune_cmd(host, 13, TUNE_CMD); + if (ret == E_RESULT_PASS) { + response = MSDC_READ32(SDC_RESP0); + AUTOK_RAWPRINT("[AUTOK]current device status 0x%08x\r\n", response); + } else + AUTOK_RAWPRINT("[AUTOK]CMD error while check device status\r\n"); + /* tune data pad delay , find data pad boundary */ + for (j = 0; j < 32; j++) { + msdc_autok_adjust_paddly(host, &j, DAT_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES / 4; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + AUTOK_RAWPRINT + ("[AUTOK]Error Autok CMD Failed while tune DATA PAD Delay\r\n"); + return -1; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) + break; + else if (ret == E_RESULT_FATAL_ERR) + return -1; + } + if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + p_autok_tune_res[DAT_RD_D_DLY1] = j; + if (j) + p_autok_tune_res[DAT_RD_D_DLY1_SEL] = 1; + break; + } + } + autok_tuning_parameter_init(host, p_autok_tune_res); + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[0]); + RawData64 = 0LL; + for (j = 0; j < 32; j++) { + msdc_autok_adjust_paddly(host, &j, DS_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES / 4; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + AUTOK_RAWPRINT + ("[AUTOK]Error Autok CMD Failed while tune DS Delay\r\n"); + return -1; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + RawData64 |= 0xffffffff00000000; + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]DLY1/2 %d \t %d \t %s\r\n", uCmdEdge, score, + tune_result_str64); + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) + return -1; + + #if 0 + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", uCmdEdge, + pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + + for (i = 0; i < BD_MAX_CNT; i++) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[%d]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", i, + pBdInfo->bd_info[i].Bound_Start, pBdInfo->bd_info[i].Bound_End, + pBdInfo->bd_info[i].Bound_width, pBdInfo->bd_info[i].is_fullbound); + } + #endif + + if (autok_ds_dly_sel(pBdInfo, &uDatDly, p_autok_tune_res) == 0) { + autok_paddly_update(DS_PAD_RDLY, uDatDly, p_autok_tune_res); + } else { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK][Error]=============Analysis Failed!!=======================\r\n"); + } + +#if HS400_DSCLK_NEED_TUNING + /* Step3 : Tuning DS Clk Path-ZDLY */ + p_autok_tune_res[EMMC50_DS_Z_DLY1] = 8; + p_autok_tune_res[EMMC50_DS_Z_DLY1_SEL] = 1; + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step3.Scan DS(ZDLY) Clk Pad Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]DS_ZDLY_DLY DS_ZCLK_DLY1~2 \r\n"); + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[1]); + RawData = 0; + for (j = 0; j < 32; j++) { + msdc_autok_adjust_param(host, EMMC50_DS_ZDLY_DLY, &j, AUTOK_WRITE); + for (k = 0; k < AUTOK_CMD_TIMES / 4; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + AUTOK_RAWPRINT + ("[AUTOK]Error Autok CMD Failed while tune DS(ZDLY) Delay\r\n"); + return -1; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData |= (u64) (1 << j); + break; + } + } + } + score = autok_simple_score(tune_result_str64, RawData); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK] %d \t %d \t %s\r\n", uCmdEdge, score, + tune_result_str64); + if (autok_check_scan_res64(RawData, pBdInfo) != 0) + return -1; + + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", uCmdEdge, + pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + + for (i = 0; i < BD_MAX_CNT; i++) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[%d]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", i, + pBdInfo->bd_info[i].Bound_Start, pBdInfo->bd_info[i].Bound_End, + pBdInfo->bd_info[i].Bound_width, pBdInfo->bd_info[i].is_fullbound); + } + + if (autok_ds_dly_sel(pBdInfo, &uDatDly, p_autok_tune_res) == 0) { + autok_param_update(EMMC50_DS_ZDLY_DLY, uDatDly, p_autok_tune_res); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]================Analysis Result[HS400]================\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]Sample ZDelay Cnt Sel:%d\r\n", uDatDly); + } else { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK][Error]=============Analysis Failed!!=======================\r\n"); + } +#endif + + autok_tuning_parameter_init(host, p_autok_tune_res); + autok_result_dump(host, p_autok_tune_res); +#if AUTOK_PARAM_DUMP_ENABLE + autok_register_dump(host); +#endif + if (res != NULL) { + memcpy((void *)res, (void *)p_autok_tune_res, + sizeof(p_autok_tune_res) / sizeof(u8)); + } + + return 0; +} + +int execute_cmd_online_tuning(struct msdc_host *host, u8 *res) +{ + void __iomem *base = host->base; + unsigned int ret = 0; + unsigned int uCmdEdge = 0; + u64 RawData64 = 0LL; + unsigned int score = 0; + unsigned int i, j, k; + struct AUTOK_REF_INFO uCmdDatInfo; + struct AUTOK_SCAN_RES *pBdInfo; + char tune_result_str64[65]; + u8 p_autok_tune_res[5]; + unsigned int opcode = MMC_SEND_STATUS; + + memset((void *)p_autok_tune_res, 0, sizeof(p_autok_tune_res) / sizeof(u8)); + + /* Tuning Cmd Path */ + AUTOK_RAWPRINT("[AUTOK]Optimised CMD Pad Data Delay Sel\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD_EDGE \t CMD_RD_R_DLY1~2 \r\n"); + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + + uCmdEdge = 0; + do { + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[uCmdEdge]); + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + RawData64 = 0LL; + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, CMD_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES / 2; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + RawData64 |= (u64)(1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK] %d \t %d \t %s\r\n", uCmdEdge, score, + tune_result_str64); + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) + return -1; + + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", + uCmdEdge, pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + + for (i = 0; i < BD_MAX_CNT; i++) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[%d]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", i, + pBdInfo->bd_info[i].Bound_Start, pBdInfo->bd_info[i].Bound_End, + pBdInfo->bd_info[i].Bound_width, pBdInfo->bd_info[i].is_fullbound); + } + + uCmdEdge ^= 0x1; + } while (uCmdEdge); + + if (autok_pad_dly_sel(&uCmdDatInfo) == 0) { + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdDatInfo.opt_edge_sel, AUTOK_WRITE); + msdc_autok_adjust_paddly(host, &uCmdDatInfo.opt_dly_cnt, CMD_PAD_RDLY); + MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, p_autok_tune_res[0]); + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRDLY, p_autok_tune_res[1]); + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRRDLYSEL, p_autok_tune_res[2]); + MSDC_GET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_CMDRDLY2, p_autok_tune_res[3]); + MSDC_GET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_CMDRRDLY2SEL, p_autok_tune_res[4]); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]================Analysis Result================\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]Sample Edge Sel: %d, Delay Cnt Sel:%d\r\n", + uCmdDatInfo.opt_edge_sel, uCmdDatInfo.opt_dly_cnt); + } else { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK][Error]=============Analysis Failed!!=======================\r\n"); + } + + AUTOK_RAWPRINT("[AUTOK]param CMD_EDGE:%d\r\n", p_autok_tune_res[0]); + AUTOK_RAWPRINT("[AUTOK]param CMD_RD_D_DLY1:%d\r\n", p_autok_tune_res[1]); + AUTOK_RAWPRINT("[AUTOK]param CMD_RD_D_DLY1_SEL:%d\r\n", p_autok_tune_res[2]); + AUTOK_RAWPRINT("[AUTOK]param CMD_RD_D_DLY2:%d\r\n", p_autok_tune_res[3]); + AUTOK_RAWPRINT("[AUTOK]param CMD_RD_D_DLY2_SEL:%d\r\n", p_autok_tune_res[4]); + + if (res != NULL) { + memcpy((void *)res, (void *)p_autok_tune_res, + sizeof(p_autok_tune_res) / sizeof(u8)); + } + AUTOK_RAWPRINT("[AUTOK]CMD Online Tune Alg Complete\r\n"); + + return 0; +} + +/* online tuning for latch ck */ +int autok_execute_tuning_latch_ck(struct msdc_host *host, unsigned int opcode, + unsigned int latch_ck_initail_value) +{ + unsigned int ret = 0; + unsigned int j, k; + void __iomem *base = host->base; + unsigned int tune_time; + + MSDC_WRITE32(MSDC_INT, 0xffffffff); + switch (host->hw->host_function) { + case MSDC_EMMC: + tune_time = AUTOK_LATCH_CK_EMMC_TUNE_TIMES; + break; + case MSDC_SD: + tune_time = AUTOK_LATCH_CK_SD_TUNE_TIMES; + break; + case MSDC_SDIO: + tune_time = AUTOK_LATCH_CK_SDIO_TUNE_TIMES; + break; + default: + tune_time = AUTOK_LATCH_CK_SDIO_TUNE_TIMES; + break; + } + for (j = latch_ck_initail_value; j < 8; j += (host->hclk / host->sclk)) { + host->tune_latch_ck_cnt = 0; + msdc_clear_fifo(); + MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_INT_DAT_LATCH_CK_SEL, j); + for (k = 0; k < tune_time; k++) { + if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { + switch (k) { + case 0: + host->tune_latch_ck_cnt = 1; + break; + default: + host->tune_latch_ck_cnt = k; + break; + } + } else if (opcode == MMC_SEND_TUNING_BLOCK) { + switch (k) { + case 0: + case 1: + case 2: + host->tune_latch_ck_cnt = 1; + break; + default: + host->tune_latch_ck_cnt = k - 1; + break; + } + } else if (opcode == MMC_SEND_EXT_CSD) { + host->tune_latch_ck_cnt = k + 1; + } else + host->tune_latch_ck_cnt++; + ret = autok_send_tune_cmd(host, opcode, TUNE_LATCH_CK); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + AUTOK_RAWPRINT("[AUTOK]Error Autok CMD Failed while tune LATCH CK\r\n"); + break; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + AUTOK_RAWPRINT("[AUTOK]Error Autok tune LATCH_CK error %d\r\n", j); + break; + } + } + if (ret == 0) { + MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_INT_DAT_LATCH_CK_SEL, j); + break; + } + } + host->tune_latch_ck_cnt = 0; + return j; +} + +/* online tuning for eMMC4.5(hs200) */ +int execute_online_tuning_hs200(struct msdc_host *host, u8 *res) +{ + unsigned int ret = 0; + unsigned int uCmdEdge = 0; + u64 RawData64 = 0LL; + unsigned int score = 0; + unsigned int j, k, cycle_value; + struct AUTOK_REF_INFO uCmdDatInfo; + struct AUTOK_SCAN_RES *pBdInfo; + char tune_result_str64[65]; + u8 p_autok_tune_res[TUNING_PARAM_COUNT]; + unsigned int opcode = MMC_SEND_STATUS; + unsigned int uDatDly = 0; + + autok_init_hs200(host); + memset((void *)p_autok_tune_res, 0, sizeof(p_autok_tune_res) / sizeof(u8)); + p_autok_tune_res[INT_DAT_LATCH_CK] = 1; + + /* Step1 : Tuning Cmd Path */ + autok_tuning_parameter_init(host, p_autok_tune_res); + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + + uCmdEdge = 0; + do { + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[uCmdEdge]); + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + RawData64 = 0LL; + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, CMD_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD %d \t %d \t %s\r\n", uCmdEdge, score, + tune_result_str64); + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) { + host->autok_error = -1; + return -1; + } + + #if 0 + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", + uCmdEdge, pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + + for (i = 0; i < BD_MAX_CNT; i++) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[%d]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", i, + pBdInfo->bd_info[i].Bound_Start, pBdInfo->bd_info[i].Bound_End, + pBdInfo->bd_info[i].Bound_width, pBdInfo->bd_info[i].is_fullbound); + } + #endif + + uCmdEdge ^= 0x1; + } while (uCmdEdge); + + if (autok_pad_dly_sel(&uCmdDatInfo) == 0) { + autok_param_update(CMD_EDGE, uCmdDatInfo.opt_edge_sel, p_autok_tune_res); + autok_paddly_update(CMD_PAD_RDLY, uCmdDatInfo.opt_dly_cnt, p_autok_tune_res); + } else { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK][Error]=============Analysis Failed!!=======================\r\n"); + } + cycle_value = uCmdDatInfo.cycle_cnt; + + /* Step2 Tuning Data Path (Only Rising Edge Used) */ + autok_tuning_parameter_init(host, p_autok_tune_res); + opcode = MMC_SEND_TUNING_BLOCK_HS200; + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[0]); + RawData64 = 0LL; + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, DAT_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES / 2; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + AUTOK_RAWPRINT("[AUTOK]Error Autok CMD Failed while tune Read\r\n"); + return -1; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]DAT %d \t %d \t %s\r\n", 0, score, + tune_result_str64); + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) { + return -1; + }; + #if 0 + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", 0, + pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + + for (i = 0; i < BD_MAX_CNT; i++) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[%d]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", i, + pBdInfo->bd_info[i].Bound_Start, pBdInfo->bd_info[i].Bound_End, + pBdInfo->bd_info[i].Bound_width, pBdInfo->bd_info[i].is_fullbound); + } + #endif + + if (autok_pad_dly_sel_single_edge(pBdInfo, cycle_value, &uDatDly) == 0) + autok_paddly_update(DAT_PAD_RDLY, uDatDly, p_autok_tune_res); + + autok_tuning_parameter_init(host, p_autok_tune_res); + + /* Step3 : Tuning LATCH CK */ + opcode = MMC_SEND_TUNING_BLOCK_HS200; + p_autok_tune_res[INT_DAT_LATCH_CK] = autok_execute_tuning_latch_ck(host, opcode, + p_autok_tune_res[INT_DAT_LATCH_CK]); + + autok_result_dump(host, p_autok_tune_res); + +#if AUTOK_PARAM_DUMP_ENABLE + autok_register_dump(host); +#endif + if (res != NULL) { + memcpy((void *)res, (void *)p_autok_tune_res, + sizeof(p_autok_tune_res) / sizeof(u8)); + } + + return 0; +} + +/* online tuning for SDIO/SD */ +int execute_online_tuning(struct msdc_host *host, u8 *res) +{ + unsigned int ret = 0; + unsigned int uCmdEdge = 0; + unsigned int uDatEdge = 0; + u64 RawData64 = 0LL; + unsigned int score = 0; + unsigned int j, k; + unsigned int opcode = MMC_SEND_TUNING_BLOCK; + struct AUTOK_REF_INFO uCmdDatInfo; + struct AUTOK_SCAN_RES *pBdInfo; + char tune_result_str64[65]; + u8 p_autok_tune_res[TUNING_PARAM_COUNT]; + + autok_init_sdr104(host); + memset((void *)p_autok_tune_res, 0, sizeof(p_autok_tune_res) / sizeof(u8)); + + /* Step1 : Tuning Cmd Path */ + autok_tuning_parameter_init(host, p_autok_tune_res); + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + + uCmdEdge = 0; + do { + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[uCmdEdge]); + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + RawData64 = 0LL; + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, CMD_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES / 2; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD %d \t %d \t %s\r\n", uCmdEdge, score, + tune_result_str64); + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) { + host->autok_error = -1; + return -1; + } + #if 0 + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", + uCmdEdge, pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + + for (i = 0; i < BD_MAX_CNT; i++) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[%d]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", i, + pBdInfo->bd_info[i].Bound_Start, pBdInfo->bd_info[i].Bound_End, + pBdInfo->bd_info[i].Bound_width, pBdInfo->bd_info[i].is_fullbound); + } + #endif + + uCmdEdge ^= 0x1; + } while (uCmdEdge); + + if (autok_pad_dly_sel(&uCmdDatInfo) == 0) { + autok_param_update(CMD_EDGE, uCmdDatInfo.opt_edge_sel, p_autok_tune_res); + autok_paddly_update(CMD_PAD_RDLY, uCmdDatInfo.opt_dly_cnt, p_autok_tune_res); + } else { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK][Error]=============Analysis Failed!!=======================\r\n"); + } + + /* Step2 : Tuning Data Path */ + autok_tuning_parameter_init(host, p_autok_tune_res); + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + + uDatEdge = 0; + do { + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[uDatEdge]); + msdc_autok_adjust_param(host, RD_FIFO_EDGE, &uDatEdge, AUTOK_WRITE); + RawData64 = 0LL; + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, DAT_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES / 2; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + AUTOK_RAWPRINT + ("[AUTOK]Error Autok CMD Failed while tune Read\r\n"); + host->autok_error = -1; + return -1; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]DAT %d \t %d \t %s\r\n", uDatEdge, score, + tune_result_str64); + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) { + host->autok_error = -1; + return -1; + } + #if 0 + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", + uDatEdge, pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + + for (i = 0; i < BD_MAX_CNT; i++) { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[%d]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", i, + pBdInfo->bd_info[i].Bound_Start, pBdInfo->bd_info[i].Bound_End, + pBdInfo->bd_info[i].Bound_width, pBdInfo->bd_info[i].is_fullbound); + } + #endif + + uDatEdge ^= 0x1; + } while (uDatEdge); + + if (autok_pad_dly_sel(&uCmdDatInfo) == 0) { + autok_param_update(RD_FIFO_EDGE, uCmdDatInfo.opt_edge_sel, p_autok_tune_res); + autok_paddly_update(DAT_PAD_RDLY, uCmdDatInfo.opt_dly_cnt, p_autok_tune_res); + autok_param_update(WD_FIFO_EDGE, uCmdDatInfo.opt_edge_sel, p_autok_tune_res); + } else { + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK][Error]=============Analysis Failed!!=======================\r\n"); + } + + autok_tuning_parameter_init(host, p_autok_tune_res); + + /* Step3 : Tuning LATCH CK */ + p_autok_tune_res[INT_DAT_LATCH_CK] = autok_execute_tuning_latch_ck(host, opcode, + p_autok_tune_res[INT_DAT_LATCH_CK]); + + autok_result_dump(host, p_autok_tune_res); +#if AUTOK_PARAM_DUMP_ENABLE + autok_register_dump(host); +#endif + if (res != NULL) { + memcpy((void *)res, (void *)p_autok_tune_res, + sizeof(p_autok_tune_res) / sizeof(u8)); + } + host->autok_error = 0; + + return 0; +} + +int execute_online_tuning_stress(struct msdc_host *host) +{ + unsigned int ret = 0; + unsigned int uCmdEdge = 0; + unsigned int uDatEdge = 0; + u64 RawData64 = 0LL; + unsigned int score = 0; + unsigned int i, j, k; + struct AUTOK_REF_INFO uCmdDatInfo; + struct AUTOK_SCAN_RES *pBdInfo; + char tune_result_str64[65]; + u8 p_autok_tune_res[TUNING_PARAM_COUNT]; + + autok_init_sdr104(host); + memset((void *)p_autok_tune_res, 0, sizeof(p_autok_tune_res) / sizeof(u8)); + + /* Step1. CMD Path Optimised Delay Count */ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step1.Optimised CMD Pad Data Delay Sel\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD_EDGE \t CMD_RD_R_DLY1~2 \r\n"); + for (i = 0; i < 32; i++) { + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + uCmdEdge = 0; + do { + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[uCmdEdge]); + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + RawData64 = 0LL; + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, CMD_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, MMC_SEND_TUNING_BLOCK, TUNE_CMD); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK][%d] %d \t %d \t %s\r\n", i, uCmdEdge, + score, tune_result_str64); + /*get Boundary info */ + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) { + return -1; + }; + + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", + uCmdEdge, pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[0]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", + pBdInfo->bd_info[0].Bound_Start, + pBdInfo->bd_info[0].Bound_End, + pBdInfo->bd_info[0].Bound_width, + pBdInfo->bd_info[0].is_fullbound); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[1]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", + pBdInfo->bd_info[1].Bound_Start, + pBdInfo->bd_info[1].Bound_End, + pBdInfo->bd_info[1].Bound_width, + pBdInfo->bd_info[1].is_fullbound); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[2]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", + pBdInfo->bd_info[2].Bound_Start, + pBdInfo->bd_info[2].Bound_End, + pBdInfo->bd_info[2].Bound_width, + pBdInfo->bd_info[2].is_fullbound); + + uCmdEdge ^= 0x1; + } while (uCmdEdge); + + autok_pad_dly_sel(&uCmdDatInfo); + + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]================Analysis Result[SD(IO)]===============\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]Sample Edge Sel: %d, Delay Cnt Sel:%d\r\n", + uCmdDatInfo.opt_edge_sel, uCmdDatInfo.opt_dly_cnt); + } + + /* Step2. DATA Path Optimised Delay Count */ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step2.Optimised CMD Pad Data Delay Sel\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD_EDGE \t CMD_RD_R_DLY1~2 \r\n"); + uCmdEdge = 0; + for (i = 0; i < 32; i++) { + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + memset(&uCmdDatInfo, 0, sizeof(struct AUTOK_REF_INFO)); + uDatEdge = 0; + do { + pBdInfo = (struct AUTOK_SCAN_RES *)&(uCmdDatInfo.scan_info[uDatEdge]); + msdc_autok_adjust_param(host, RD_FIFO_EDGE, &uDatEdge, AUTOK_WRITE); + RawData64 = 0LL; + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, DAT_PAD_RDLY); +rd_retry: + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, MMC_SEND_TUNING_BLOCK, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + uCmdEdge ^= 0x1; + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, + AUTOK_WRITE); + goto rd_retry; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK][%d] %d \t %d \t %s\r\n", i, uDatEdge, + score, tune_result_str64); + /*get Boundary info */ + if (autok_check_scan_res64(RawData64, pBdInfo) != 0) { + return -1; + }; + + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]Edge:%d \t BoundaryCnt:%d \t FullBoundaryCnt:%d \t\r\n", + uDatEdge, pBdInfo->bd_cnt, pBdInfo->fbd_cnt); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[0]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", + pBdInfo->bd_info[0].Bound_Start, + pBdInfo->bd_info[0].Bound_End, + pBdInfo->bd_info[0].Bound_width, + pBdInfo->bd_info[0].is_fullbound); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[1]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", + pBdInfo->bd_info[1].Bound_Start, + pBdInfo->bd_info[1].Bound_End, + pBdInfo->bd_info[1].Bound_width, + pBdInfo->bd_info[1].is_fullbound); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]BoundInf[2]: S:%d \t E:%d \t W:%d \t FullBound:%d\r\n", + pBdInfo->bd_info[2].Bound_Start, + pBdInfo->bd_info[2].Bound_End, + pBdInfo->bd_info[2].Bound_width, + pBdInfo->bd_info[2].is_fullbound); + + uDatEdge ^= 0x1; + } while (uDatEdge); + + autok_pad_dly_sel(&uCmdDatInfo); + + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]================Analysis Result[SD(IO)]===============\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]Sample Edge Sel: %d, Delay Cnt Sel:%d\r\n", + uCmdDatInfo.opt_edge_sel, uCmdDatInfo.opt_dly_cnt); + } + + i = 0; + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + + AUTOK_RAWPRINT("[AUTOK]Online Tune Alg Complete\r\n"); + + return 0; +} + +/******************************************************************** +* Offline tune for SDIO/eMMC/SD * +* Common Interface * +********************************************************************/ +int execute_offline_tuning_hs400(struct msdc_host *host) +{ + unsigned int ret = 0; + + unsigned int i, j, k; + unsigned int uCkgenSel = 0; + unsigned int uCmdEdge = 0; + unsigned int res_cmd_ta = 1; + + u64 RawData64 = 0LL; + unsigned int score = 0; + char tune_result_str32[33]; + char tune_result_str64[65]; + u32 g_ta_raw[SCALE_TA_CNTR]; + u32 g_ta_score[SCALE_TA_CNTR]; + u8 p_autok_tune_res[TUNING_PARAM_COUNT]; + + unsigned int opcode = MMC_READ_SINGLE_BLOCK; + + autok_init_hs400(host); + memset((void *)p_autok_tune_res, 0, sizeof(p_autok_tune_res) / sizeof(u8)); + p_autok_tune_res[EMMC50_DS_Z_DLY1] = 7; + p_autok_tune_res[EMMC50_DS_Z_DLY1_SEL] = 1; + p_autok_tune_res[EMMC50_DS_ZDLY_DLY] = 24; + + + /************************************************************ + * * + * Step 1 : Caculate CMD_RSP_TA * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step1.Scan CMD_RSP_TA Base on Cmd Pad Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD_EDGE \t CMD_RSP_TA_CNTR \t PAD_CMD_D_DLY \r\n"); + + uCmdEdge = 0; + do { + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + for (i = 0; i < 8; i++) { + g_ta_raw[i] = 0; + msdc_autok_adjust_param(host, CMD_RSP_TA_CNTR, &i, AUTOK_WRITE); + for (j = 0; j < 32; j++) { + msdc_autok_adjust_param(host, CMD_RD_D_DLY1, &j, AUTOK_WRITE); + + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + g_ta_raw[i] |= (1 << j); + break; + } + } + } + g_ta_score[i] = autok_simple_score(tune_result_str32, g_ta_raw[i]); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]%d \t %d\t %d \t %s\r\n", uCmdEdge, i, + g_ta_score[i], tune_result_str32); + } + + if (autok_ta_sel(g_ta_raw, &res_cmd_ta) == 0) { + /* autok_param_update(CMD_RSP_TA_CNTR, res_cmd_ta, p_autok_tune_res); */ + msdc_autok_adjust_param(host, CMD_RSP_TA_CNTR, &res_cmd_ta, AUTOK_WRITE); + AUTOK_RAWPRINT("[AUTOK]CMD_TA Sel:%d\r\n", res_cmd_ta); + break; + } else { + AUTOK_RAWPRINT + ("[AUTOK]Internal Boundary Occours,need switch cmd edge for rescan!\r\n"); + uCmdEdge ^= 1; /* TA select Fail need switch cmd edge for rescan */ + } + } while (uCmdEdge); + + /************************************************************ + * * + * Step 2 : Scan CMD Pad Delay Base on CMD_EDGE & CKGEN * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step2.Scan CMD Pad Data Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD_EDGE \t CKGEN \t CMD_RD_R_DLY1~2 \r\n"); + uCmdEdge = 0; + + do { + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + + for (i = 0; i < 32; i++) { + RawData64 = 0LL; + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, CMD_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]%d \t %d \t %d \t %s\r\n", + /*(u32)((RawData64>>32)&0xFFFFFFFF),(u32)(RawData64&0xFFFFFFFF), */ + uCmdEdge, i, score, tune_result_str64); + } + + uCmdEdge ^= 0x1; + } while (uCmdEdge); + + uCkgenSel = 0; + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &uCkgenSel, AUTOK_WRITE); + /************************************************************ + * * + * Step 3 : Scan Dat Pad Delay Base on Data_EDGE & CKGEN * + * * + ************************************************************/ + opcode = MMC_SEND_TUNING_BLOCK_HS200; + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step3.Scan DS Clk Pad Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]DS_ZDLY_DLY DS_ZCLK_DLY1~2 \r\n"); + for (i = 0; i < 32; i++) { + msdc_autok_adjust_param(host, EMMC50_DS_ZDLY_DLY, &i, AUTOK_WRITE); + uCmdEdge = 0; + RawData64 = 0LL; + + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, DS_PAD_RDLY); +rd_retry0: + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + uCmdEdge ^= 0x1; + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, + AUTOK_WRITE); + goto rd_retry0; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK][%d] %d \t %d \t %s\r\n", i, uCmdEdge, score, + tune_result_str64); + } + + /* CMD 17 Single block read */ + opcode = MMC_READ_SINGLE_BLOCK; + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step3.Scan DS Clk Pad Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]DS_ZDLY_DLY DS_ZCLK_DLY1~2 \r\n"); + + for (i = 0; i < 32; i++) { + msdc_autok_adjust_param(host, EMMC50_DS_ZDLY_DLY, &i, AUTOK_WRITE); + uCmdEdge = 0; + RawData64 = 0LL; + + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, DS_PAD_RDLY); +rd_retry1: + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + uCmdEdge ^= 0x1; + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, + AUTOK_WRITE); + goto rd_retry1; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK][%d] %d \t %d \t %s\r\n", i, uCmdEdge, score, + tune_result_str64); + } + + autok_tuning_parameter_init(host, p_autok_tune_res); + + return ret; +} + +int execute_offline_tuning(struct msdc_host *host) +{ + /* AUTOK_CODE_RELEASE */ + unsigned int ret = 0; + unsigned int i, j, k; + unsigned int uCkgenSel = 0; + unsigned int uCmdEdge = 0; + unsigned int uDatEdge = 0; + unsigned int res_cmd_ta = 1; +#if defined(SDIO_TUNE_WRITE_PATH) + unsigned int uWCrcEdge = 0; + unsigned int res_wcrc_ta = 1; +#endif + + u64 RawData64 = 0LL; + unsigned int score = 0; + char tune_result_str32[33]; + char tune_result_str64[65]; + u32 g_ta_raw[SCALE_TA_CNTR]; + u32 g_ta_score[SCALE_TA_CNTR]; + u8 p_autok_tune_res[TUNING_PARAM_COUNT]; + unsigned int opcode = MMC_SEND_TUNING_BLOCK; + + memset((void *)p_autok_tune_res, 0, sizeof(p_autok_tune_res) / sizeof(u8)); + if (host->hw->host_function == MSDC_SDIO) { + opcode = MMC_SEND_TUNING_BLOCK; + autok_init_sdr104(host); + } else if (host->hw->host_function == MSDC_EMMC) { + opcode = MMC_SEND_TUNING_BLOCK_HS200; + autok_init_hs200(host); + } + + /************************************************************ + * * + * Step 1 : Caculate CMD_RSP_TA * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step1.Scan CMD_RSP_TA Base on Cmd Pad Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD_EDGE \t CMD_RSP_TA_CNTR \t PAD_CMD_D_DLY \r\n"); + + uCmdEdge = 0; + do { + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + for (i = 0; i < 8; i++) { + g_ta_raw[i] = 0; + msdc_autok_adjust_param(host, CMD_RSP_TA_CNTR, &i, AUTOK_WRITE); + for (j = 0; j < 32; j++) { + msdc_autok_adjust_param(host, CMD_RD_D_DLY1, &j, AUTOK_WRITE); + + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + g_ta_raw[i] |= (1 << j); + break; + } + } + } + g_ta_score[i] = autok_simple_score(tune_result_str32, g_ta_raw[i]); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]%d \t %d\t %d \t %s\r\n", uCmdEdge, i, + g_ta_score[i], tune_result_str32); + } + + if (autok_ta_sel(g_ta_raw, &res_cmd_ta) == 0) { + msdc_autok_adjust_param(host, CMD_RSP_TA_CNTR, &res_cmd_ta, AUTOK_WRITE); + AUTOK_RAWPRINT("[AUTOK]CMD_TA Sel:%d\r\n", res_cmd_ta); + break; + } else { + AUTOK_RAWPRINT + ("[AUTOK]Internal Boundary Occours,need switch cmd edge for rescan!\r\n"); + uCmdEdge ^= 1; /* TA select Fail need switch cmd edge for rescan */ + } + } while (uCmdEdge); + + /************************************************************ + * * + * Step 2 : Scan CMD Pad Delay Base on CMD_EDGE & CKGEN * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step2.Scan CMD Pad Data Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD_EDGE \t CKGEN \t CMD_RD_R_DLY1~2 \r\n"); + uCmdEdge = 0; + + do { + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + + for (i = 0; i < 32; i++) { + RawData64 = 0LL; + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, CMD_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + RawData64 |= (u64)(1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]%d \t %d \t %d \t %s\r\n", + /*(u32)((RawData64>>32)&0xFFFFFFFF),(u32)(RawData64&0xFFFFFFFF), */ + uCmdEdge, i, score, tune_result_str64); + } + + uCmdEdge ^= 0x1; + } while (uCmdEdge); + + + /************************************************************ + * * + * Step 3 : Scan Dat Pad Delay Base on Data_EDGE & CKGEN * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step3.Scan Dat Pad Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]CMD_EDGE \t DAT_EDGE \t CKGEN \t DAT_RD_R_DLY1~2 \r\n"); + uCmdEdge = 0; + + do { + msdc_autok_adjust_param(host, RD_FIFO_EDGE, &uDatEdge, AUTOK_WRITE); + for (i = 0; i < 32; i++) { + RawData64 = 0LL; + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, DAT_PAD_RDLY); +rd_retry: + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + uCmdEdge ^= 0x1; + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, + AUTOK_WRITE); + goto rd_retry; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK][%d] \t %d \t %d \t %d \t %s\r\n", + uCmdEdge, uDatEdge, i, score, tune_result_str64); + } + + uDatEdge ^= 0x1; + } while (uDatEdge); + +#if defined(SDIO_TUNE_WRITE_PATH) + /************************************************************ + * * + * Step 4: Scan Write Pad Delay Base on WCRC_EDGE & CKGEN * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step4.Scan Data Pad Delay on Write Path\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]CMD_EDGE \t WCRC_EDGE \t CKGEN \t DAT_RD_R_DLY1~2 \r\n"); + uCmdEdge = 0; + + do { + msdc_autok_adjust_param(host, WD_FIFO_EDGE, &uWCrcEdge, AUTOK_WRITE); + for (i = 0; i < 32; i++) { + RawData64 = 0LL; + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, DAT_PAD_RDLY); +wd_retry: + for (k = 0; k < 2; k++) { + ret = autok_cmd53_tune_cccr_write(host); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + uCmdEdge ^= 0x1; + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, + AUTOK_WRITE); + goto wd_retry; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK][%d] \t %d \t %d \t %d \t %s\r\n", + uCmdEdge, uWCrcEdge, i, score, tune_result_str64); + } + + uWCrcEdge ^= 0x1; + } while (uWCrcEdge); + + uCkgenSel = 0; + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &uCkgenSel, AUTOK_WRITE); + /************************************************************ + * * + * Step 5 : Scan Write TA Base on Pad Delay * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step5.Scan WCRC_TA Base on Data Pad Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]WCRC_EDGE \t WRDAT_CRCS_TA_CNTR \t DAT_RD_R_DLY1~2 \r\n"); + uCmdEdge = 0; + uWCrcEdge = 0; + + do { + msdc_autok_adjust_param(host, WD_FIFO_EDGE, &uWCrcEdge, AUTOK_WRITE); + for (i = 0; i < 8; i++) { + g_ta_raw[i] = 0; + msdc_autok_adjust_param(host, WRDAT_CRCS_TA_CNTR, &i, AUTOK_WRITE); + for (j = 0; j < 32; j++) { + msdc_autok_adjust_paddly(host, &j, DAT_PAD_RDLY); + + +retry: + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_cmd53_tune_cccr_write(host); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + uCmdEdge ^= 0x1; + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, + AUTOK_WRITE); + goto retry; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + g_ta_raw[i] |= (1 << j); + break; + } + } + } + g_ta_score[i] = autok_simple_score(tune_result_str32, g_ta_raw[i]); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK][%d] \t %d \t %d\t %d \t %s\r\n", + uCmdEdge, uWCrcEdge, i, g_ta_score[i], tune_result_str32); + } + + if (autok_ta_sel(g_ta_raw, &res_wcrc_ta) == 0) { + msdc_autok_adjust_param(host, WRDAT_CRCS_TA_CNTR, &res_wcrc_ta, AUTOK_WRITE); + AUTOK_RAWPRINT("[AUTOK]CMD_TA Sel:%d\r\n", res_wcrc_ta); + break; + } else { + AUTOK_RAWPRINT + ("[AUTOK]Internal Boundary Occours,need switch cmd edge for rescan!\r\n"); + uWCrcEdge ^= 1; /* TA select Fail need switch cmd edge for rescan */ + } + } while (uWCrcEdge); +#endif + /* Debug Info for reference */ + /************************************************************ + * * + * Step [1] : Scan CMD Pad Delay Base on CMD_EDGE & CKGEN * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step[1].Scan CMD Pad Data Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]CMD_EDGE \t CKGEN \t CMD_RD_R_DLY1~2 \r\n"); + uCmdEdge = 0; + + for (i = 0; i < 32; i++) { + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + + do { + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, AUTOK_WRITE); + RawData64 = 0LL; + + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, CMD_PAD_RDLY); + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_CMD); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK]%d \t %d \t %d \t %s\r\n", + /*(u32)((RawData64>>32)&0xFFFFFFFF),(u32)(RawData64&0xFFFFFFFF), */ + uCmdEdge, i, score, tune_result_str64); + uCmdEdge ^= 0x1; + + } while (uCmdEdge); + } + + /************************************************************ + * * + * Step [2] : Scan Dat Pad Delay Base on Data_EDGE & CKGEN * + * * + ************************************************************/ + autok_tuning_parameter_init(host, p_autok_tune_res); + AUTOK_RAWPRINT("[AUTOK]Step[2].Scan Dat Pad Delay\r\n"); + AUTOK_DBGPRINT(AUTOK_DBG_RES, + "[AUTOK]CMD_EDGE \t DAT_EDGE \t CKGEN \t DAT_RD_R_DLY1~2 \r\n"); + uCmdEdge = 0; + uDatEdge = 0; + for (i = 0; i < 32; i++) { + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &i, AUTOK_WRITE); + + do { + msdc_autok_adjust_param(host, RD_FIFO_EDGE, &uDatEdge, AUTOK_WRITE); + RawData64 = 0LL; + + for (j = 0; j < 64; j++) { + msdc_autok_adjust_paddly(host, &j, DAT_PAD_RDLY); +rd_retry1: + for (k = 0; k < AUTOK_CMD_TIMES; k++) { + ret = autok_send_tune_cmd(host, opcode, TUNE_DATA); + if ((ret & (E_RESULT_CMD_TMO | E_RESULT_RSP_CRC)) != 0) { + uCmdEdge ^= 0x1; + msdc_autok_adjust_param(host, CMD_EDGE, &uCmdEdge, + AUTOK_WRITE); + goto rd_retry1; + } else if ((ret & (E_RESULT_DAT_CRC | E_RESULT_DAT_TMO)) != 0) { + RawData64 |= (u64) (1LL << j); + break; + } + } + } + score = autok_simple_score64(tune_result_str64, RawData64); + AUTOK_DBGPRINT(AUTOK_DBG_RES, "[AUTOK][%d] \t %d \t %d \t %d \t %s\r\n", + uCmdEdge, uDatEdge, i, score, tune_result_str64); + + uDatEdge ^= 0x1; + } while (uDatEdge); + + } + + uCkgenSel = 0; + msdc_autok_adjust_param(host, CKGEN_MSDC_DLY_SEL, &uCkgenSel, AUTOK_WRITE); + + AUTOK_RAWPRINT("[AUTOK]Offline Tune Alg Complete\r\n"); + + return 0; +} + +#if AUTOK_OFFLINE_TUNE_TX_ENABLE +int autok_offline_tuning_TX(struct msdc_host *host) +{ + int ret = 0; + void __iomem *base = host->base; + unsigned int response; + unsigned int tune_tx_value; + unsigned char tune_cnt; + unsigned char i; + unsigned char tune_crc_cnt[32]; + unsigned char tune_pass_cnt[32]; + unsigned char tune_tmo_cnt[32]; + char tune_result[33]; + unsigned int cmd_tx; + unsigned int dat0_tx; + unsigned int dat1_tx; + unsigned int dat2_tx; + unsigned int dat3_tx; + unsigned int dat4_tx; + unsigned int dat5_tx; + unsigned int dat6_tx; + unsigned int dat7_tx; + + AUTOK_RAWPRINT("[AUTOK][tune cmd TX]=========start========\r\n"); + /* store tx setting */ + MSDC_GET_FIELD(EMMC50_PAD_CMD_TUNE, MSDC_EMMC50_PAD_CMD_TUNE_TXDLY, cmd_tx); + MSDC_GET_FIELD(EMMC50_PAD_DAT01_TUNE, MSDC_EMMC50_PAD_DAT0_TXDLY, dat0_tx); + MSDC_GET_FIELD(EMMC50_PAD_DAT01_TUNE, MSDC_EMMC50_PAD_DAT1_TXDLY, dat1_tx); + MSDC_GET_FIELD(EMMC50_PAD_DAT23_TUNE, MSDC_EMMC50_PAD_DAT2_TXDLY, dat2_tx); + MSDC_GET_FIELD(EMMC50_PAD_DAT23_TUNE, MSDC_EMMC50_PAD_DAT3_TXDLY, dat3_tx); + MSDC_GET_FIELD(EMMC50_PAD_DAT45_TUNE, MSDC_EMMC50_PAD_DAT4_TXDLY, dat4_tx); + MSDC_GET_FIELD(EMMC50_PAD_DAT45_TUNE, MSDC_EMMC50_PAD_DAT5_TXDLY, dat5_tx); + MSDC_GET_FIELD(EMMC50_PAD_DAT67_TUNE, MSDC_EMMC50_PAD_DAT6_TXDLY, dat6_tx); + MSDC_GET_FIELD(EMMC50_PAD_DAT67_TUNE, MSDC_EMMC50_PAD_DAT7_TXDLY, dat7_tx); + + /* Step1 : Tuning Cmd TX */ + for (tune_tx_value = 0; tune_tx_value < 32; tune_tx_value++) { + tune_tmo_cnt[tune_tx_value] = 0; + tune_crc_cnt[tune_tx_value] = 0; + tune_pass_cnt[tune_tx_value] = 0; + MSDC_SET_FIELD(EMMC50_PAD_CMD_TUNE, MSDC_EMMC50_PAD_CMD_TUNE_TXDLY, tune_tx_value); + for (tune_cnt = 0; tune_cnt < TUNE_TX_CNT; tune_cnt++) { + ret = autok_send_tune_cmd(host, MMC_SEND_STATUS, TUNE_CMD); + if ((ret & E_RESULT_CMD_TMO) != 0) + tune_tmo_cnt[tune_tx_value]++; + else if ((ret&(E_RESULT_RSP_CRC)) != 0) + tune_crc_cnt[tune_tx_value]++; + else if ((ret & (E_RESULT_PASS)) == 0) + tune_pass_cnt[tune_tx_value]++; + } + + /* AUTOK_RAWPRINT("[AUTOK]tune_cmd_TX cmd_tx_value = %d tmo_cnt = %d crc_cnt = %d pass_cnt = %d\n", + tune_tx_value, tune_tmo_cnt[tune_tx_value],tune_crc_cnt[tune_tx_value], + tune_pass_cnt[tune_tx_value]); */ + } + + /* print result */ + for (i = 0; i < 32; i++) { + if ((tune_tmo_cnt[i] != 0) || (tune_crc_cnt[i] != 0)) + tune_result[i] = 'X'; + else if (tune_pass_cnt[i] == TUNE_TX_CNT) + tune_result[i] = 'O'; + } + tune_result[32] = '\0'; + AUTOK_RAWPRINT("[AUTOK]tune_cmd_TX 0 - 31 %s\r\n", tune_result); + AUTOK_RAWPRINT("[AUTOK][tune cmd TX]=========end========\r\n"); + + /* restore cmd tx setting */ + MSDC_SET_FIELD(EMMC50_PAD_CMD_TUNE, MSDC_EMMC50_PAD_CMD_TUNE_TXDLY, cmd_tx); + AUTOK_RAWPRINT("[AUTOK][tune data TX]=========start========\r\n"); + + /* Step2 : Tuning Data TX */ + for (tune_tx_value = 0; tune_tx_value < 32; tune_tx_value++) { + tune_tmo_cnt[tune_tx_value] = 0; + tune_crc_cnt[tune_tx_value] = 0; + tune_pass_cnt[tune_tx_value] = 0; + MSDC_SET_FIELD(EMMC50_PAD_DAT01_TUNE, MSDC_EMMC50_PAD_DAT0_TXDLY, tune_tx_value); + MSDC_SET_FIELD(EMMC50_PAD_DAT01_TUNE, MSDC_EMMC50_PAD_DAT1_TXDLY, tune_tx_value); + MSDC_SET_FIELD(EMMC50_PAD_DAT23_TUNE, MSDC_EMMC50_PAD_DAT2_TXDLY, tune_tx_value); + MSDC_SET_FIELD(EMMC50_PAD_DAT23_TUNE, MSDC_EMMC50_PAD_DAT3_TXDLY, tune_tx_value); + MSDC_SET_FIELD(EMMC50_PAD_DAT45_TUNE, MSDC_EMMC50_PAD_DAT4_TXDLY, tune_tx_value); + MSDC_SET_FIELD(EMMC50_PAD_DAT45_TUNE, MSDC_EMMC50_PAD_DAT5_TXDLY, tune_tx_value); + MSDC_SET_FIELD(EMMC50_PAD_DAT67_TUNE, MSDC_EMMC50_PAD_DAT6_TXDLY, tune_tx_value); + MSDC_SET_FIELD(EMMC50_PAD_DAT67_TUNE, MSDC_EMMC50_PAD_DAT7_TXDLY, tune_tx_value); + + for (tune_cnt = 0; tune_cnt < TUNE_TX_CNT; tune_cnt++) { + /* check device status */ + response = 0; + while (((response >> 9) & 0xF) != 4) { + ret = autok_send_tune_cmd(host, MMC_SEND_STATUS, TUNE_CMD); + if ((ret & (E_RESULT_RSP_CRC | E_RESULT_CMD_TMO)) != 0) { + AUTOK_RAWPRINT("[AUTOK]------while tune data TX cmd13 occur error------\r\n"); + AUTOK_RAWPRINT("[AUTOK]------tune data TX fail------\r\n"); + goto end; + } + response = MSDC_READ32(SDC_RESP0); + if ((((response >> 9) & 0xF) == 5) || (((response >> 9) & 0xF) == 6)) + ret = autok_send_tune_cmd(host, MMC_STOP_TRANSMISSION, TUNE_CMD); + } + + /* send cmd24 write one block data */ + ret = autok_send_tune_cmd(host, MMC_WRITE_BLOCK, TUNE_DATA); + response = MSDC_READ32(SDC_RESP0); + if ((ret & (E_RESULT_RSP_CRC | E_RESULT_CMD_TMO)) != 0) { + AUTOK_RAWPRINT("[AUTOK]------while tune data TX cmd%d occur error------\n", + MMC_WRITE_BLOCK); + AUTOK_RAWPRINT("[AUTOK]------tune data TX fail------\n"); + goto end; + } + if ((ret & E_RESULT_DAT_TMO) != 0) + tune_tmo_cnt[tune_tx_value]++; + else if ((ret & (E_RESULT_DAT_CRC)) != 0) + tune_crc_cnt[tune_tx_value]++; + else if ((ret & (E_RESULT_PASS)) == 0) + tune_pass_cnt[tune_tx_value]++; + } + + /* AUTOK_RAWPRINT("[AUTOK]tune_data_TX data_tx_value = %d tmo_cnt = %d crc_cnt = %d pass_cnt = %d\n", + tune_tx_value, tune_tmo_cnt[tune_tx_value],tune_crc_cnt[tune_tx_value], + tune_pass_cnt[tune_tx_value]); */ + } + + /* print result */ + for (i = 0; i < 32; i++) { + if ((tune_tmo_cnt[i] != 0) || (tune_crc_cnt[i] != 0)) + tune_result[i] = 'X'; + else if (tune_pass_cnt[i] == TUNE_TX_CNT) + tune_result[i] = 'O'; + } + tune_result[32] = '\0'; + AUTOK_RAWPRINT("[AUTOK]tune_data_TX 0 - 31 %s\r\n", tune_result); + + /* restore data tx setting */ + MSDC_SET_FIELD(EMMC50_PAD_DAT01_TUNE, MSDC_EMMC50_PAD_DAT0_TXDLY, dat0_tx); + MSDC_SET_FIELD(EMMC50_PAD_DAT01_TUNE, MSDC_EMMC50_PAD_DAT1_TXDLY, dat1_tx); + MSDC_SET_FIELD(EMMC50_PAD_DAT23_TUNE, MSDC_EMMC50_PAD_DAT2_TXDLY, dat2_tx); + MSDC_SET_FIELD(EMMC50_PAD_DAT23_TUNE, MSDC_EMMC50_PAD_DAT3_TXDLY, dat3_tx); + MSDC_SET_FIELD(EMMC50_PAD_DAT45_TUNE, MSDC_EMMC50_PAD_DAT4_TXDLY, dat4_tx); + MSDC_SET_FIELD(EMMC50_PAD_DAT45_TUNE, MSDC_EMMC50_PAD_DAT5_TXDLY, dat5_tx); + MSDC_SET_FIELD(EMMC50_PAD_DAT67_TUNE, MSDC_EMMC50_PAD_DAT6_TXDLY, dat6_tx); + MSDC_SET_FIELD(EMMC50_PAD_DAT67_TUNE, MSDC_EMMC50_PAD_DAT7_TXDLY, dat7_tx); + + AUTOK_RAWPRINT("[AUTOK][tune data TX]=========end========\r\n"); + +end: + return ret; +} +#endif + +int autok_execute_tuning(struct msdc_host *host, u8 *res) +{ + int ret = 0; + struct timeval tm_s, tm_e; + unsigned int tm_val = 0; + unsigned int clk_pwdn = 0; + unsigned int int_en = 0; + void __iomem *base = host->base; + + do_gettimeofday(&tm_s); + + int_en = MSDC_READ32(MSDC_INTEN); + MSDC_WRITE32(MSDC_INTEN, 0); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, 1); + +#if AUTOK_OFFLINE_TUNE_ENABLE + if (execute_offline_tuning(host) != 0) + AUTOK_RAWPRINT("[AUTOK] ========Error: Autok OFFLINE Failed========"); +#endif + if (execute_online_tuning(host, res) != 0) + AUTOK_RAWPRINT("[AUTOK] ========Error: Autok Failed========"); + + autok_msdc_reset(); + msdc_clear_fifo(); + MSDC_WRITE32(MSDC_INT, 0xffffffff); + MSDC_WRITE32(MSDC_INTEN, int_en); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + + do_gettimeofday(&tm_e); + tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000 + (tm_e.tv_usec - tm_s.tv_usec) / 1000; + AUTOK_RAWPRINT("[AUTOK]=========Time Cost:%d ms========\r\n", tm_val); + + return ret; +} +EXPORT_SYMBOL(autok_execute_tuning); + +int hs400_execute_tuning(struct msdc_host *host, u8 *res) +{ + int ret = 0; + struct timeval tm_s, tm_e; + unsigned int tm_val = 0; + unsigned int clk_pwdn = 0; + unsigned int int_en = 0; + void __iomem *base = host->base; + + do_gettimeofday(&tm_s); + int_en = MSDC_READ32(MSDC_INTEN); + MSDC_WRITE32(MSDC_INTEN, 0); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, 1); + +#if HS400_OFFLINE_TUNE_ENABLE + if (execute_offline_tuning_hs400(host) != 0) + AUTOK_RAWPRINT("[AUTOK] ========Error: Autok HS400 OFFLINE Failed========"); +#endif + if (execute_online_tuning_hs400(host, res) != 0) + AUTOK_RAWPRINT("[AUTOK] ========Error: Autok HS400 Failed========"); +#if AUTOK_OFFLINE_TUNE_TX_ENABLE + if (do_autok_offline_tune_tx) + autok_offline_tuning_TX(host); +#endif + + autok_msdc_reset(); + msdc_clear_fifo(); + MSDC_WRITE32(MSDC_INT, 0xffffffff); + MSDC_WRITE32(MSDC_INTEN, int_en); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + + do_gettimeofday(&tm_e); + tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000 + (tm_e.tv_usec - tm_s.tv_usec) / 1000; + AUTOK_RAWPRINT("[AUTOK][HS400]=========Time Cost:%d ms========\r\n", tm_val); + + return ret; +} +EXPORT_SYMBOL(hs400_execute_tuning); + +int hs400_execute_tuning_cmd(struct msdc_host *host, u8 *res) +{ + int ret = 0; + struct timeval tm_s, tm_e; + unsigned int tm_val = 0; + unsigned int clk_pwdn = 0; + unsigned int int_en = 0; + void __iomem *base = host->base; + + do_gettimeofday(&tm_s); + int_en = MSDC_READ32(MSDC_INTEN); + MSDC_WRITE32(MSDC_INTEN, 0); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, 1); + + autok_init_hs400(host); + if (execute_cmd_online_tuning(host, res) != 0) + AUTOK_RAWPRINT("[AUTOK only for cmd] ========Error: Autok HS400 Failed========"); + + autok_msdc_reset(); + msdc_clear_fifo(); + MSDC_WRITE32(MSDC_INT, 0xffffffff); + MSDC_WRITE32(MSDC_INTEN, int_en); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + + do_gettimeofday(&tm_e); + tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000 + (tm_e.tv_usec - tm_s.tv_usec) / 1000; + AUTOK_RAWPRINT("[AUTOK][HS400 only for cmd]=========Time Cost:%d ms========\r\n", tm_val); + + return ret; +} +EXPORT_SYMBOL(hs400_execute_tuning_cmd); + +int hs200_execute_tuning(struct msdc_host *host, u8 *res) +{ + int ret = 0; + struct timeval tm_s, tm_e; + unsigned int tm_val = 0; + unsigned int clk_pwdn = 0; + unsigned int int_en = 0; + void __iomem *base = host->base; + + do_gettimeofday(&tm_s); + int_en = MSDC_READ32(MSDC_INTEN); + MSDC_WRITE32(MSDC_INTEN, 0); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, 1); + +#if HS200_OFFLINE_TUNE_ENABLE + if (execute_offline_tuning(host) != 0) + AUTOK_RAWPRINT("[AUTOK] ========Error: Autok OFFLINE HS200 Failed========"); +#endif + MSDC_WRITE32(MSDC_INT, 0xffffffff); + if (execute_online_tuning_hs200(host, res) != 0) + AUTOK_RAWPRINT("[AUTOK] ========Error: Autok HS200 Failed========"); + + /*autok_msdc_reset();*/ + /*msdc_clear_fifo();*/ + /*MSDC_WRITE32(MSDC_INT, 0xffffffff);*/ + MSDC_WRITE32(MSDC_INTEN, int_en); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + + do_gettimeofday(&tm_e); + tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000 + (tm_e.tv_usec - tm_s.tv_usec) / 1000; + AUTOK_RAWPRINT("[AUTOK][HS200]=========Time Cost:%d ms========\r\n", tm_val); + + return ret; +} +EXPORT_SYMBOL(hs200_execute_tuning); + +int hs200_execute_tuning_cmd(struct msdc_host *host, u8 *res) +{ + int ret = 0; + struct timeval tm_s, tm_e; + unsigned int tm_val = 0; + unsigned int clk_pwdn = 0; + unsigned int int_en = 0; + void __iomem *base = host->base; + + do_gettimeofday(&tm_s); + int_en = MSDC_READ32(MSDC_INTEN); + MSDC_WRITE32(MSDC_INTEN, 0); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, 1); + + autok_init_hs200(host); + if (execute_cmd_online_tuning(host, res) != 0) + AUTOK_RAWPRINT("[AUTOK only for cmd] ========Error: Autok HS200 Failed========"); + + /*autok_msdc_reset();*/ + /*msdc_clear_fifo();*/ + /*MSDC_WRITE32(MSDC_INT, 0xffffffff);*/ + MSDC_WRITE32(MSDC_INTEN, int_en); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKPDN, clk_pwdn); + + do_gettimeofday(&tm_e); + tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000 + (tm_e.tv_usec - tm_s.tv_usec) / 1000; + AUTOK_RAWPRINT("[AUTOK][HS200 only for cmd]=========Time Cost:%d ms========\r\n", tm_val); + + return ret; +} +EXPORT_SYMBOL(hs200_execute_tuning_cmd); + diff --git a/drivers/mmc/host/mediatek/mt6755/autok.h b/drivers/mmc/host/mediatek/mt6755/autok.h new file mode 100644 index 0000000000000000000000000000000000000000..ac675266e5d5f1c293eca97865a0a86a9878ee36 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/autok.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _AUTOK_H_ +#define _AUTOK_H_ + +#include +#include +#include +#include +#include "mt_sd.h" + +#define E_RESULT_PASS (0) +#define E_RESULT_CMD_TMO (1<<0) +#define E_RESULT_RSP_CRC (1<<1) +#define E_RESULT_DAT_CRC (1<<2) +#define E_RESULT_DAT_TMO (1<<3) +#define E_RESULT_W_CRC (1<<4) +#define E_RESULT_ERR (1<<5) +#define E_RESULT_START (1<<6) +#define E_RESULT_PW_SMALL (1<<7) +#define E_RESULT_KEEP_OLD (1<<8) +#define E_RESULT_CMP_ERR (1<<9) +#define E_RESULT_FATAL_ERR (1<<10) + +#define E_RESULT_MAX + +#ifndef NULL +#define NULL 0 +#endif +#ifndef TRUE +#define TRUE (0 == 0) +#endif +#ifndef FALSE +#define FALSE (0 != 0) +#endif + +#define AUTOK_DBG_OFF 0 +#define AUTOK_DBG_ERROR 1 +#define AUTOK_DBG_RES 2 +#define AUTOK_DBG_WARN 3 +#define AUTOK_DBG_TRACE 4 +#define AUTOK_DBG_LOUD 5 + +extern unsigned int do_autok_offline_tune_tx; +extern unsigned int autok_debug_level; + +#define AUTOK_DBGPRINT(_level, _fmt ...) \ +({ \ + if (autok_debug_level >= _level) { \ + pr_err(_fmt); \ + } \ +}) + +#define AUTOK_RAWPRINT(_fmt ...) \ +({ \ + pr_err(_fmt); \ +}) + +enum AUTOK_PARAM { + /* command response sample selection (MSDC_SMPL_RISING, MSDC_SMPL_FALLING) */ + CMD_EDGE, + + /* read data sample selection (MSDC_SMPL_RISING, MSDC_SMPL_FALLING) */ + RDATA_EDGE, + + /* read data async fifo out edge select */ + RD_FIFO_EDGE, + + /* write data crc status async fifo out edge select */ + WD_FIFO_EDGE, + + /* [Data Tune]CMD Pad RX Delay Line1 Control. This register is used to + fine-tune CMD pad macro respose latch timing. Total 32 stages[Data Tune] */ + CMD_RD_D_DLY1, + + /* [Data Tune]CMD Pad RX Delay Line1 Sel-> delay cell1 enable */ + CMD_RD_D_DLY1_SEL, + + /* [Data Tune]CMD Pad RX Delay Line2 Control. This register is used to + fine-tune CMD pad macro respose latch timing. Total 32 stages[Data Tune] */ + CMD_RD_D_DLY2, + + /* [Data Tune]CMD Pad RX Delay Line1 Sel-> delay cell2 enable */ + CMD_RD_D_DLY2_SEL, + + /* [Data Tune]DAT Pad RX Delay Line1 Control (for MSDC RD), Total 32 stages [Data Tune] */ + DAT_RD_D_DLY1, + + /* [Data Tune]DAT Pad RX Delay Line1 Sel-> delay cell1 enable */ + DAT_RD_D_DLY1_SEL, + + /* [Data Tune]DAT Pad RX Delay Line2 Control (for MSDC RD), Total 32 stages [Data Tune] */ + DAT_RD_D_DLY2, + + /* [Data Tune]DAT Pad RX Delay Line2 Sel-> delay cell2 enable */ + DAT_RD_D_DLY2_SEL, + + /* Internal MSDC clock phase selection. Total 8 stages, each stage can delay 1 clock period of msdc_src_ck */ + INT_DAT_LATCH_CK, + + /* DS Pad Z clk delay count, range: 0~63, Z dly1(0~31)+Z dly2(0~31) */ + EMMC50_DS_Z_DLY1, + + /* DS Pad Z clk del sel: [dly2_sel:dly1_sel] + -> [0,1]: dly1 enable [1,2]:dl2 & dly1 enable ,else :no dly enable, */ + EMMC50_DS_Z_DLY1_SEL, + + /* DS Pad Z clk delay count, range: 0~63, Z dly1(0~31)+Z dly2(0~31) */ + EMMC50_DS_Z_DLY2, + + /* DS Pad Z clk del sel: [dly2_sel:dly1_sel] + -> [0,1]: dly1 enable [1,2]:dl2 & dly1 enable ,else :no dly enable, */ + EMMC50_DS_Z_DLY2_SEL, + + /* DS Pad Z_DLY clk delay count, range: 0~31 */ + EMMC50_DS_ZDLY_DLY, + TUNING_PARAM_COUNT, + + /* Data line rising/falling latch fine tune selection in read transaction. + 1'b0: All data line share one value indicated by MSDC_IOCON.R_D_SMPL. + 1'b1: Each data line has its own selection value indicated by Data line (x): MSDC_IOCON.R_D(x)_SMPL */ + READ_DATA_SMPL_SEL, + + /* Data line rising/falling latch fine tune selection in write transaction. + 1'b0: All data line share one value indicated by MSDC_IOCON.W_D_SMPL. + 1'b1: Each data line has its own selection value indicated by Data line (x): MSDC_IOCON.W_D(x)_SMPL */ + WRITE_DATA_SMPL_SEL, + + /* Data line delay line fine tune selection. 1'b0: All data line share one delay + selection value indicated by PAD_TUNE.PAD_DAT_RD_RXDLY. 1'b1: Each data line has its + own delay selection value indicated by Data line (x): DAT_RD_DLY(x).DAT0_RD_DLY */ + DATA_DLYLINE_SEL, + + /* [Data Tune]CMD & DATA Pin tune Data Selection[Data Tune Sel] */ + MSDC_DAT_TUNE_SEL, + + /* [Async_FIFO Mode Sel For Write Path] */ + MSDC_WCRC_ASYNC_FIFO_SEL, + + /* [Async_FIFO Mode Sel For CMD Path] */ + MSDC_RESP_ASYNC_FIFO_SEL, + + /* Write Path Mux for emmc50 function & emmc45 function , Only emmc50 design valid,[1-eMMC50, 0-eMMC45] */ + EMMC50_WDATA_MUX_EN, + + /* CMD Path Mux for emmc50 function & emmc45 function , Only emmc50 design valid,[1-eMMC50, 0-eMMC45] */ + EMMC50_CMD_MUX_EN, + + /* write data crc status async fifo output edge select */ + EMMC50_WDATA_EDGE, + + /* CKBUF in CKGEN Delay Selection. Total 32 stages */ + CKGEN_MSDC_DLY_SEL, + + /* CMD response turn around period. The turn around cycle = CMD_RSP_TA_CNTR + 2, + Only for USH104 mode, this register should be set to 0 in non-UHS104 mode */ + CMD_RSP_TA_CNTR, + + /* Write data and CRC status turn around period. The turn around cycle = WRDAT_CRCS_TA_CNTR + 2, + Only for USH104 mode, this register should be set to 0 in non-UHS104 mode */ + WRDAT_CRCS_TA_CNTR, + + /* CLK Pad TX Delay Control. This register is used to add delay to CLK phase. Total 32 stages */ + PAD_CLK_TXDLY, + TOTAL_PARAM_COUNT +}; + +/********************************************************** +* Feature Control Defination * +**********************************************************/ +#define AUTOK_OFFLINE_TUNE_TX_ENABLE 1 +#define AUTOK_OFFLINE_TUNE_ENABLE 0 +#define HS400_OFFLINE_TUNE_ENABLE 0 +#define HS200_OFFLINE_TUNE_ENABLE 0 +#define HS400_DSCLK_NEED_TUNING 0 +#define AUTOK_PARAM_DUMP_ENABLE 0 +/* #define CHIP_DENALI_3_DAT_TUNE */ +/* #define SDIO_TUNE_WRITE_PATH */ + + + +/********************************************************** +* Function Declaration * +**********************************************************/ +extern int autok_path_sel(struct msdc_host *host); +extern int autok_init_sdr104(struct msdc_host *host); +extern int autok_init_hs200(struct msdc_host *host); +extern int autok_init_hs400(struct msdc_host *host); +extern void autok_tuning_parameter_init(struct msdc_host *host, u8 *res); +extern int autok_execute_tuning(struct msdc_host *host, u8 *res); +extern int hs200_execute_tuning(struct msdc_host *host, u8 *res); +extern int hs200_execute_tuning_cmd(struct msdc_host *host, u8 *res); +extern int hs400_execute_tuning(struct msdc_host *host, u8 *res); +extern int hs400_execute_tuning_cmd(struct msdc_host *host, u8 *res); + + +extern unsigned int do_autok_offline_tune_tx; + +#endif /* _AUTOK_H_ */ + diff --git a/drivers/mmc/host/mediatek/mt6755/autok_dvfs.c b/drivers/mmc/host/mediatek/mt6755/autok_dvfs.c new file mode 100644 index 0000000000000000000000000000000000000000..9f79757d6276c712ebca95ed48bba477d5181fe8 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/autok_dvfs.c @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include + +#include "autok_dvfs.h" + +#define SDIO_AUTOK_HIGH_RES_PATH "/data/sdio_autok_high" /* E1 only use high */ +#define SDIO_AUTOK_LOW_RES_PATH "/data/sdio_autok_low" /* E2 use low and high with DFFS */ + +#define SDIO_AUTOK_DIFF_MARGIN 3 + +u8 sdio_autok_res[2][TUNING_PARAM_COUNT]; +u8 emmc_autok_res[2][TUNING_PARAM_COUNT]; +u8 sd_autok_res[2][TUNING_PARAM_COUNT]; +int sdio_ver = 0; + +static struct file *msdc_file_open(const char *path, int flags, int rights) +{ + struct file *filp = NULL; + mm_segment_t oldfs; + int err = 0; + + oldfs = get_fs(); + set_fs(get_ds()); + filp = filp_open(path, flags, rights); + set_fs(oldfs); + + if (IS_ERR(filp)) { + err = PTR_ERR(filp); + return NULL; + } + + return filp; +} + +static int msdc_file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) +{ + mm_segment_t oldfs; + int ret; + + oldfs = get_fs(); + set_fs(get_ds()); + + ret = vfs_read(file, data, size, &offset); + + set_fs(oldfs); + + return ret; +} + +static int msdc_file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) +{ + mm_segment_t oldfs; + int ret; + + oldfs = get_fs(); + set_fs(get_ds()); + + ret = vfs_write(file, data, size, &offset); + + set_fs(oldfs); + + return ret; +} + +int sdio_autok_res_apply(struct msdc_host *host, int vcore) +{ + struct file *filp = NULL; + size_t size; + u8 *res; + int ret = -1; + int i; + + if (vcore <= AUTOK_VCORE_LOW) { + res = sdio_autok_res[AUTOK_VCORE_LOW]; + filp = msdc_file_open(SDIO_AUTOK_LOW_RES_PATH, O_RDONLY, 0644); + } else { + res = sdio_autok_res[AUTOK_VCORE_HIGH]; + filp = msdc_file_open(SDIO_AUTOK_HIGH_RES_PATH, O_RDONLY, 0644); + } + + if (filp == NULL) { + pr_err("autok result open fail\n"); + return ret; + } + + size = msdc_file_read(filp, 0, res, TUNING_PARAM_COUNT); + if (size == TUNING_PARAM_COUNT) { + autok_tuning_parameter_init(host, res); + + for (i = 1; i < TUNING_PARAM_COUNT; i++) + pr_err("autok result exist!, result[%d] = %d\n", i, res[i]); + ret = 0; + } + + filp_close(filp, NULL); + + return ret; +} + +int sdio_autok_res_save(struct msdc_host *host, int vcore, u8 *res) +{ + struct file *filp = NULL; + size_t size; + int ret = -1; + + if (res == NULL) + return ret; + + if (vcore <= AUTOK_VCORE_LOW) { + memcpy((void *)sdio_autok_res[AUTOK_VCORE_LOW], (const void *)res, TUNING_PARAM_COUNT); + filp = msdc_file_open(SDIO_AUTOK_LOW_RES_PATH, O_CREAT | O_WRONLY, 0644); + } else { + memcpy((void *)sdio_autok_res[AUTOK_VCORE_HIGH], (const void *)res, TUNING_PARAM_COUNT); + filp = msdc_file_open(SDIO_AUTOK_HIGH_RES_PATH, O_CREAT | O_WRONLY, 0644); + } + + if (filp == NULL) { + pr_err("autok result open fail\n"); + return ret; + } + + size = msdc_file_write(filp, 0, res, TUNING_PARAM_COUNT); + if (size == TUNING_PARAM_COUNT) + ret = 0; + vfs_fsync(filp, 0); + + filp_close(filp, NULL); + + return ret; +} + +int autok_res_check(u8 *res_h, u8 *res_l) +{ + int ret = 0; + int i; + + for (i = 0; i < TUNING_PARAM_COUNT; i++) { + if ((i == CMD_RD_D_DLY1) || (i == DAT_RD_D_DLY1)) { + if ((res_h[i] > res_l[i]) && (res_h[i] - res_l[i] > SDIO_AUTOK_DIFF_MARGIN)) + ret = -1; + if ((res_l[i] > res_h[i]) && (res_l[i] - res_h[i] > SDIO_AUTOK_DIFF_MARGIN)) + ret = -1; + } else if ((i == CMD_RD_D_DLY1_SEL) || (i == DAT_RD_D_DLY1_SEL)) { + /* this is cover by previous check, + just by pass if 0 and 1 in cmd/dat delay */ + } else { + if (res_h[i] != res_l[i]) + ret = -1; + } + } + pr_err("autok_res_check %d!\n", ret); + + return ret; +} + +int sdio_version(struct msdc_host *host) +{ + void __iomem *base = host->base; + u32 div = 0; + + if ((host->id == 2) && (sdio_ver == 0)) { + /* enable dvfs feature */ + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_DVFS_EN, 1); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_DVFS_EN, div); + + if (div == 0) + sdio_ver = 1; + else + sdio_ver = 2; + + pr_err("SDIO E%d!\n", sdio_ver); + } + + return sdio_ver; +} + +void sdio_unreq_vcore(struct work_struct *work) +{ + if (vcorefs_request_dvfs_opp(KIR_SDIO, OPPI_UNREQ) == 0) + pr_debug("unrequest vcore pass\n"); + else + pr_err("unrequest vcore fail\n"); +} + +void sdio_set_vcore_performance(struct msdc_host *host, u32 enable) +{ + if (enable) { + if (cancel_delayed_work_sync(&(host->set_vcore_workq)) == 0) { + /* true if dwork was pending, false otherwise */ + pr_debug("** cancel @ FALSE\n"); + if (vcorefs_request_dvfs_opp(KIR_SDIO, OPPI_PERF) == 0) { + pr_debug("msdc%d -> request vcore pass\n", + host->id); + } else { + pr_err("msdc%d -> request vcore fail\n", + host->id); + } + } + } else { + schedule_delayed_work(&(host->set_vcore_workq), SDIO_DVFS_TIMEOUT); + } +} + +void sdio_set_vcorefs_sram(int vcore, int done, struct msdc_host *host) +{ + void __iomem *base = host->base; + + if (vcore >= AUTOK_VCORE_HIGH) { + vcorefs_set_sram_data(1, MSDC_READ32(MSDC_IOCON)); + vcorefs_set_sram_data(2, MSDC_READ32(MSDC_PATCH_BIT0)); + vcorefs_set_sram_data(3, MSDC_READ32(MSDC_PATCH_BIT1)); + vcorefs_set_sram_data(4, MSDC_READ32(MSDC_PATCH_BIT2)); + vcorefs_set_sram_data(5, MSDC_READ32(MSDC_PAD_TUNE0)); + vcorefs_set_sram_data(6, MSDC_READ32(MSDC_PAD_TUNE1)); + vcorefs_set_sram_data(7, MSDC_READ32(MSDC_DAT_RDDLY0)); + vcorefs_set_sram_data(8, MSDC_READ32(MSDC_DAT_RDDLY1)); + vcorefs_set_sram_data(9, MSDC_READ32(MSDC_DAT_RDDLY2)); + vcorefs_set_sram_data(10, MSDC_READ32(MSDC_DAT_RDDLY3)); + } else { + vcorefs_set_sram_data(11, MSDC_READ32(MSDC_IOCON)); + vcorefs_set_sram_data(12, MSDC_READ32(MSDC_PATCH_BIT0)); + vcorefs_set_sram_data(13, MSDC_READ32(MSDC_PATCH_BIT1)); + vcorefs_set_sram_data(14, MSDC_READ32(MSDC_PATCH_BIT2)); + vcorefs_set_sram_data(15, MSDC_READ32(MSDC_PAD_TUNE0)); + vcorefs_set_sram_data(16, MSDC_READ32(MSDC_PAD_TUNE1)); + vcorefs_set_sram_data(17, MSDC_READ32(MSDC_DAT_RDDLY0)); + vcorefs_set_sram_data(18, MSDC_READ32(MSDC_DAT_RDDLY1)); + vcorefs_set_sram_data(19, MSDC_READ32(MSDC_DAT_RDDLY2)); + vcorefs_set_sram_data(20, MSDC_READ32(MSDC_DAT_RDDLY3)); + } + + /* SPM see 0x0x55AA55AA then SDIO para apply for HPM/LPM transisiton */ + if (done) + vcorefs_set_sram_data(0, 0x55AA55AA); +} + +/* For backward compatible, remove later */ +int wait_sdio_autok_ready(void *data) +{ + return 0; +} +EXPORT_SYMBOL(wait_sdio_autok_ready); + + +void sdio_autok_wait_dvfs_ready(void) +{ + int dvfs; + + dvfs = is_vcorefs_can_work(); + + /* DVFS not ready, just wait */ + while (dvfs == 0) { + pr_err("DVFS not ready\n"); + msleep(100); + dvfs = is_vcorefs_can_work(); + } + + if (dvfs == -1) + pr_err("DVFS feature not enable\n"); + + if (dvfs == 1) + pr_err("DVFS ready\n"); +} + +int emmc_autok(void) +{ + struct msdc_host *host = mtk_msdc_host[0]; + struct mmc_host *mmc = host->mmc; + + if (mmc == NULL) { + pr_err("eMMC device not ready\n"); + return -1; + } + + pr_err("emmc autok\n"); + +#if 0 /* Wait Light confirm */ + mmc_claim_host(mmc); + + /* Performance mode, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_EMMC, OPPI_PERF) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n"); + + if (mmc->ios.timing == MMC_TIMING_MMC_HS200) { + pr_err("[AUTOK]eMMC HS200 Tune\r\n"); + hs200_execute_tuning(host, emmc_autok_res[AUTOK_VCORE_HIGH]); + } else if (mmc->ios.timing == MMC_TIMING_MMC_HS400) { + pr_err("[AUTOK]eMMC HS400 Tune\r\n"); + hs400_execute_tuning(host, emmc_autok_res[AUTOK_VCORE_HIGH]); + } + + /* Low power mode, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_EMMC, OPPI_LOW_PWR) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n"); + + if (mmc->ios.timing == MMC_TIMING_MMC_HS200) { + pr_err("[AUTOK]eMMC HS200 Tune\r\n"); + hs200_execute_tuning(host, emmc_autok_res[AUTOK_VCORE_LOW]); + } else if (mmc->ios.timing == MMC_TIMING_MMC_HS400) { + pr_err("[AUTOK]eMMC HS400 Tune\r\n"); + hs400_execute_tuning(host, emmc_autok_res[AUTOK_VCORE_LOW]); + } + + /* Un-request, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_EMMC, OPPI_UNREQ) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_UNREQ fail!\n"); + + mmc_release_host(mmc); +#endif + + return 0; +} +EXPORT_SYMBOL(emmc_autok); + +int sd_autok(void) +{ + struct msdc_host *host = mtk_msdc_host[1]; + struct mmc_host *mmc; + + if (host == NULL) { + pr_err("SD card not ready\n"); + return -1; + } + + mmc = host->mmc; + + pr_err("sd autok\n"); + +#if 0 /* Wait Cool confirm */ + mmc_claim_host(mmc); + + /* Performance mode, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_SD, OPPI_PERF) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n"); + autok_execute_tuning(host, sd_autok_res[AUTOK_VCORE_HIGH]); + + /* Low power mode, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_SD, OPPI_LOW_PWR) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n"); + autok_execute_tuning(host, sd_autok_res[AUTOK_VCORE_LOW]); + + /* Un-request, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_SD, OPPI_UNREQ) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_UNREQ fail!\n"); + + mmc_release_host(mmc); +#endif + + return 0; +} +EXPORT_SYMBOL(sd_autok); + +int sdio_autok(void) +{ + struct msdc_host *host = mtk_msdc_host[2]; + + if ((host == NULL) || (host->hw == NULL)) + return -1; + + if (host->hw->host_function != MSDC_SDIO) + return -1; + + pr_err("sdio autok\n"); + + /* DVFS need wait device ready and excute autok here */ + if (!wait_for_completion_timeout(&host->autok_done, 10 * HZ)) { + pr_err("SDIO wait device autok ready timeout"); + return -1; + } + + pr_err("sdio autok done!"); + + return 0; +} +EXPORT_SYMBOL(sdio_autok); + + + diff --git a/drivers/mmc/host/mediatek/mt6755/autok_dvfs.h b/drivers/mmc/host/mediatek/mt6755/autok_dvfs.h new file mode 100644 index 0000000000000000000000000000000000000000..3ca8a949936386c366170380a4fdbf119ee85a56 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/autok_dvfs.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _AUTOK_DVFS_H_ +#define _AUTOK_DVFS_H_ + +#include +#include "autok.h" + +#define SDIO_DVFS_TIMEOUT (HZ/100 * 5) /* 10ms x5 */ +#define SDIO_FIX_VCORE_CONDITIONAL + +enum AUTOK_VCORE { + AUTOK_VCORE_LOW = 0, + AUTOK_VCORE_HIGH, + AUTOK_VCORE_NUM +}; + +/********************************************************** +* Variable Declaration * +**********************************************************/ +extern u8 sdio_autok_res[2][TUNING_PARAM_COUNT]; +extern u8 emmc_autok_res[2][TUNING_PARAM_COUNT]; +extern u8 sd_autok_res[2][TUNING_PARAM_COUNT]; + +/********************************************************** +* Function Declaration * +**********************************************************/ +extern int sdio_autok_res_apply(struct msdc_host *host, int vcore); +extern int sdio_autok_res_save(struct msdc_host *host, int vcore, u8 *res); +extern void sdio_autok_wait_dvfs_ready(void); + +extern int autok_res_check(u8 *res_h, u8 *res_l); +extern int sdio_version(struct msdc_host *host); +extern void sdio_unreq_vcore(struct work_struct *work); +extern void sdio_set_vcore_performance(struct msdc_host *host, u32 enable); +void sdio_set_vcorefs_sram(int vcore, int done, struct msdc_host *host); + +#endif /* _AUTOK_DVFS_H_ */ + diff --git a/drivers/mmc/host/mediatek/mt6755/dbg.c b/drivers/mmc/host/mediatek/mt6755/dbg.c new file mode 100644 index 0000000000000000000000000000000000000000..70ca892cddd264d8526e6d00a79a1d21a11285a0 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/dbg.c @@ -0,0 +1,2615 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef FPGA_PLATFORM +#include +#endif +#ifdef MTK_MSDC_BRINGUP_DEBUG +#include +#endif + +#include "mt_sd.h" +#include +#include "dbg.h" +#include "autok_dvfs.h" + +/*#define CONFIG_MTK_EMMC_CQ_MET_USR_DEF*/ + +#ifdef CONFIG_MT_ENG_BUILD +/*#define MTK_EMMC_CQ_DEBUG*/ +/*#define CONFIG_MTK_EMMC_CQ_MET_USR_DEF*/ +#endif + + +#ifdef CONFIG_MTK_EMMC_CQ_MET_USR_DEF +#include +static unsigned int dbg_cq_state[32]; +#ifdef CONFIG_MTK_EMMC_CQ_MET_TAG +#define TASK_STR_ALL 32 +static char *task_str[] = { + "task_0", + "task_1", + "task_2", + "task_3", + "task_4", + "task_5", + "task_6", + "task_7", + "task_8", + "task_9", + "task_10", + "task_11", + "task_12", + "task_13", + "task_14", + "task_15", + "task_16", + "task_17", + "task_18", + "task_19", + "task_20", + "task_21", + "task_22", + "task_23", + "task_24", + "task_25", + "task_26", + "task_27", + "task_28", + "task_29", + "task_30", + "task_31", + "all", +}; + +#define TASK_STAGE_DAT 10 +static char *task_stage_str[] = { + "_0", + "_1", + "_2", + "_3", + "_4", + "_5", + "_6", + "_7", + "_8", + "_9", + "next_dat", +}; +#endif +#endif + +#ifdef MTK_IO_PERFORMANCE_DEBUG +unsigned int g_mtk_mmc_perf_dbg = 0; +unsigned int g_mtk_mmc_dbg_range = 0; +unsigned int g_dbg_range_start = 0; +unsigned int g_dbg_range_end = 0; +unsigned int g_mtk_mmc_dbg_flag = 0; +unsigned int g_dbg_req_count = 0; +unsigned int g_dbg_raw_count = 0; +unsigned int g_dbg_write_count = 0; +unsigned int g_dbg_raw_count_old = 0; +unsigned int g_mtk_mmc_clear = 0; +int g_check_read_write = 0; +int g_i = 0; +unsigned long long g_req_buf[4000][30] = { {0} }; +unsigned long long g_req_write_buf[4000][30] = { {0} }; +unsigned long long g_req_write_count[4000] = { 0 }; + +unsigned long long g_mmcqd_buf[400][300] = { {0} }; + +char *g_time_mark[] = { + "--start fetch request", + "--end fetch request", + "--start dma map this request", + "--end dma map this request", + "--start request", + "--DMA start", + "--DMA transfer done", + "--start dma unmap request", + "--end dma unmap request", + "--end of request", +}; + +char *g_time_mark_vfs_write[] = { + "--in vfs_write", + "--before generic_segment_checks", + "--after generic_segment_checks", + "--after vfs_check_frozen", + "--after generic_write_checks", + "--after file_remove_suid", + "--after file_update_time", + "--after generic_file_direct_write", + "--after generic_file_buffered_write", + "--after filemap_write_and_wait_range", + "--after invalidate_mapping_pages", + "--after 2nd generic_file_buffered_write", + "--before generic_write_sync", + "--after generic_write_sync", + "--out vfs_write" +}; +#endif + +/* for get transfer time with each trunk size, default not open */ +#ifdef MTK_MMC_PERFORMANCE_TEST +unsigned int g_mtk_mmc_perf_test = 0; +#endif + +/* for a type command, e.g. CMD53, 2 blocks */ +struct cmd_profile { + u32 max_tc; /* Max tick count */ + u32 min_tc; + u32 tot_tc; /* total tick count */ + u32 tot_bytes; + u32 count; /* the counts of the command */ +}; + +/* dump when total_tc and total_bytes */ +struct sdio_profile { + u32 total_tc; /* total tick count of CMD52 and CMD53 */ + u32 total_tx_bytes; /* total bytes of CMD53 Tx */ + u32 total_rx_bytes; /* total bytes of CMD53 Rx */ + + /*CMD52 */ + struct cmd_profile cmd52_tx; + struct cmd_profile cmd52_rx; + + /*CMD53 in byte unit */ + struct cmd_profile cmd53_tx_byte[512]; + struct cmd_profile cmd53_rx_byte[512]; + + /*CMD53 in block unit */ + struct cmd_profile cmd53_tx_blk[100]; + struct cmd_profile cmd53_rx_blk[100]; +}; + +static char cmd_buf[256]; + +/* for driver profile */ +#define TICKS_ONE_MS (13000) +u32 gpt_enable = 0; +u32 sdio_pro_enable = 0; /* make sure gpt is enabled */ +static unsigned long long sdio_pro_time = 30; /* no more than 30s */ +static unsigned long long sdio_profiling_start; +struct sdio_profile sdio_perfomance = { 0 }; + +/*#define MTK_MSDC_ERROR_TUNE_DEBUG*/ + +#ifdef MSDC_DMA_ADDR_DEBUG +struct dma_addr msdc_latest_dma_address[MAX_BD_PER_GPD]; + +static struct dma_addr *msdc_get_dma_address(int host_id) +{ + struct bd_t *bd; + int i = 0; + int mode = -1; + struct msdc_host *host; + void __iomem *base; + + if (host_id < 0 || host_id >= HOST_MAX_NUM) { + pr_err("[%s] invalid host_id %d\n", __func__, host_id); + return NULL; + } + + if (!mtk_msdc_host[host_id]) { + pr_err("[%s] msdc%d does not exist\n", __func__, host_id); + return NULL; + } + + host = mtk_msdc_host[host_id]; + base = host->base; + /* spin_lock(&host->lock); */ + MSDC_GET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, mode); + if (mode == 1) { + pr_crit("Desc.DMA\n"); + bd = host->dma.bd; + i = 0; + while (i < MAX_BD_PER_GPD) { + msdc_latest_dma_address[i].start_address = + (u32) bd[i].ptr; + msdc_latest_dma_address[i].size = bd[i].buflen; + msdc_latest_dma_address[i].end = bd[i].eol; + if (i > 0) + msdc_latest_dma_address[i - 1].next = + &msdc_latest_dma_address[i]; + + if (bd[i].eol) + break; + i++; + } + } else if (mode == 0) { + pr_crit("Basic DMA\n"); + msdc_latest_dma_address[0].start_address = + MSDC_READ32(MSDC_DMA_SA); + msdc_latest_dma_address[0].size = MSDC_READ32(MSDC_DMA_LEN); + msdc_latest_dma_address[0].end = 1; + } + /* spin_unlock(&host->lock); */ + + return msdc_latest_dma_address; + +} + +static void msdc_init_dma_latest_address(void) +{ + struct dma_addr *ptr, *prev; + int bdlen = MAX_BD_PER_GPD; + + memset(msdc_latest_dma_address, 0, sizeof(struct dma_addr) * bdlen); + ptr = msdc_latest_dma_address + bdlen - 1; + while (ptr != msdc_latest_dma_address) { + prev = ptr - 1; + prev->next = (void *)(msdc_latest_dma_address + + (ptr - msdc_latest_dma_address)); + ptr = prev; + } + +} +#endif + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT +#ifdef MTK_EMMC_CQ_DEBUG +#define dbg_max_cnt (500) +struct dbg_run_host_log { + unsigned long long time_sec; + unsigned long long time_usec; + int type; + int cmd; + int arg; +}; +static struct dbg_run_host_log dbg_run_host_log_dat[dbg_max_cnt]; +static int dbg_host_cnt; +static int is_lock_init; +static spinlock_t cmd_dump_lock; + +static unsigned int printk_cpu_test = UINT_MAX; +struct timeval cur_tv; + +void dbg_add_host_log(struct mmc_host *mmc, int type, int cmd, int arg) +{ + unsigned long long t; + unsigned long long nanosec_rem; + unsigned long flags; + + if (!is_lock_init) { + spin_lock_init(&cmd_dump_lock); + is_lock_init = 1; + } + + spin_lock_irqsave(&cmd_dump_lock, flags); + t = cpu_clock(printk_cpu_test); + nanosec_rem = do_div(t, 1000000000)/1000; + do_gettimeofday(&cur_tv); + dbg_run_host_log_dat[dbg_host_cnt].time_sec = t; + dbg_run_host_log_dat[dbg_host_cnt].time_usec = nanosec_rem; + dbg_run_host_log_dat[dbg_host_cnt].type = type; + dbg_run_host_log_dat[dbg_host_cnt].cmd = cmd; + dbg_run_host_log_dat[dbg_host_cnt].arg = arg; + dbg_host_cnt++; + if (dbg_host_cnt >= dbg_max_cnt) + dbg_host_cnt = 0; + spin_unlock_irqrestore(&cmd_dump_lock, flags); +} + +void mmc_cmd_dump(struct mmc_host *mmc) +{ + int i; + int tag = -1; + unsigned long flags; + struct msdc_host *host; + + if (!mmc || !mmc->card) + return; + + host = mmc_priv(mmc); + + if (!is_lock_init) { + spin_lock_init(&cmd_dump_lock); + is_lock_init = 1; + } + + pr_err("-------------------------------------------------------------------------------\n"); + spin_lock_irqsave(&cmd_dump_lock, flags); + for (i = dbg_host_cnt; i < dbg_max_cnt; i++) { + if (dbg_run_host_log_dat[i].cmd == 44 + && (dbg_run_host_log_dat[i].type == 0)) { + tag = (dbg_run_host_log_dat[i].arg >> 16) & 0xf; + pr_err("%d [%5llu.%06llu]%2d %2d 0x%08x tag=%d type=%s %s %s\n", i, + dbg_run_host_log_dat[i].time_sec, + dbg_run_host_log_dat[i].time_usec, + dbg_run_host_log_dat[i].type, + dbg_run_host_log_dat[i].cmd, + dbg_run_host_log_dat[i].arg, tag, + ((dbg_run_host_log_dat[i].arg >> 30) & 0x1) ? "read" : "write", + !((dbg_run_host_log_dat[i].arg >> 30) & 0x1) && + ((dbg_run_host_log_dat[i].arg >> 31) & 0x1) ? "rel" : NULL, + !((dbg_run_host_log_dat[i].arg >> 30) & 0x1) && + ((dbg_run_host_log_dat[i].arg >> 24) & 0x1) ? "fprg" : NULL + ); + } else if ((dbg_run_host_log_dat[i].cmd == 46 + || dbg_run_host_log_dat[i].cmd == 47) + && !dbg_run_host_log_dat[i].type) { + tag = (dbg_run_host_log_dat[i].arg >> 16) & 0xf; + pr_err("%d [%5llu.%06llu]%2d %2d 0x%08x tag=%d\n", i, + dbg_run_host_log_dat[i].time_sec, + dbg_run_host_log_dat[i].time_usec, + dbg_run_host_log_dat[i].type, + dbg_run_host_log_dat[i].cmd, + dbg_run_host_log_dat[i].arg, tag); + } else + pr_err("%d [%5llu.%06llu]%2d %2d 0x%08x\n", i, + dbg_run_host_log_dat[i].time_sec, + dbg_run_host_log_dat[i].time_usec, + dbg_run_host_log_dat[i].type, + dbg_run_host_log_dat[i].cmd, + dbg_run_host_log_dat[i].arg); + } + + for (i = 0; i < dbg_host_cnt; i++) { + if (dbg_run_host_log_dat[i].cmd == 44 + && !dbg_run_host_log_dat[i].type) { + tag = (dbg_run_host_log_dat[i].arg >> 16) & 0xf; + pr_err("%d [%5llu.%06llu]%2d %2d 0x%08x tag=%d type=%s %s %s\n", i, + dbg_run_host_log_dat[i].time_sec, + dbg_run_host_log_dat[i].time_usec, + dbg_run_host_log_dat[i].type, + dbg_run_host_log_dat[i].cmd, + dbg_run_host_log_dat[i].arg, tag, + ((dbg_run_host_log_dat[i].arg >> 30) & 0x1) ? "read" : "write", + !((dbg_run_host_log_dat[i].arg >> 30) & 0x1) && + ((dbg_run_host_log_dat[i].arg >> 31) & 0x1) ? "rel" : NULL, + !((dbg_run_host_log_dat[i].arg >> 30) & 0x1) && + ((dbg_run_host_log_dat[i].arg >> 24) & 0x1) ? "fprg" : NULL + ); + } else if ((dbg_run_host_log_dat[i].cmd == 46 + || dbg_run_host_log_dat[i].cmd == 47) + && !dbg_run_host_log_dat[i].type) { + tag = (dbg_run_host_log_dat[i].arg >> 16) & 0xf; + pr_err("%d [%5llu.%06llu]%2d %2d 0x%08x tag=%d\n", i, + dbg_run_host_log_dat[i].time_sec, + dbg_run_host_log_dat[i].time_usec, + dbg_run_host_log_dat[i].type, + dbg_run_host_log_dat[i].cmd, + dbg_run_host_log_dat[i].arg, tag); + } else + pr_err("%d [%5llu.%06llu]%2d %2d 0x%08x\n", i, + dbg_run_host_log_dat[i].time_sec, + dbg_run_host_log_dat[i].time_usec, + dbg_run_host_log_dat[i].type, + dbg_run_host_log_dat[i].cmd, + dbg_run_host_log_dat[i].arg); + } + spin_unlock_irqrestore(&cmd_dump_lock, flags); + msdc_cmdq_status_print(host); +} +#else +void dbg_add_host_log(struct mmc_host *mmc, int type, int cmd, int arg) +{ +} + +void mmc_cmd_dump(struct mmc_host *mmc) +{ +} +#endif + +#ifdef CONFIG_MTK_EMMC_CQ_MET_USR_DEF +void emmc_cq_state(void) +{ + MET_PRINTK("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d" + , dbg_cq_state[0], dbg_cq_state[1] + , dbg_cq_state[2], dbg_cq_state[3] + , dbg_cq_state[4], dbg_cq_state[5] + , dbg_cq_state[6], dbg_cq_state[7] + , dbg_cq_state[8], dbg_cq_state[9] + , dbg_cq_state[10], dbg_cq_state[11] + , dbg_cq_state[12], dbg_cq_state[13] + , dbg_cq_state[14], dbg_cq_state[15] + , dbg_cq_state[16], dbg_cq_state[17] + , dbg_cq_state[18], dbg_cq_state[19] + , dbg_cq_state[20], dbg_cq_state[21] + , dbg_cq_state[22], dbg_cq_state[23] + , dbg_cq_state[24], dbg_cq_state[25] + , dbg_cq_state[26], dbg_cq_state[27] + , dbg_cq_state[28], dbg_cq_state[29] + , dbg_cq_state[30], dbg_cq_state[31]); +} + +void emmc_cq_state_log(struct mmc_host *mmc, unsigned int idx, + unsigned int val) +{ + dbg_cq_state[idx] = val; + emmc_cq_state(); +} + +void emmc_cq_state_pr(struct mmc_host *mmc, unsigned int idx, + unsigned int val) +{ + dbg_cq_state[idx] = val; +} +#else +void emmc_cq_state_log(struct mmc_host *mmc, unsigned int idx, + unsigned int val) +{ +} + +void emmc_cq_state_pr(struct mmc_host *mmc, unsigned int idx, + unsigned int val) +{ +} +#endif +#endif + +void msdc_cmdq_status_print(struct msdc_host *host) +{ +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + struct mmc_host *mmc = host->mmc; + + if (!mmc || !mmc->card) + return; + + pr_err("===============================\n"); + pr_err("cmdq support : %s\n", + mmc->card->ext_csd.cmdq_support ? "yes":"no"); + pr_err("cmdq mode : %s\n", + mmc->card->ext_csd.cmdq_mode_en ? "enable" : "disable"); + pr_err("cmdq depth : %d\n", + mmc->card->ext_csd.cmdq_depth); + pr_err("===============================\n"); + pr_err("areq_cnt : %d\n", + atomic_read(&mmc->areq_cnt)); + pr_err("task_id_index: %08lx\n", + mmc->task_id_index); + pr_err("cq_wait_rdy : %d\n", + atomic_read(&mmc->cq_wait_rdy)); + pr_err("cq_rdy_cnt : %d\n", + atomic_read(&mmc->cq_rdy_cnt)); + pr_err("cq_tuning_now: %d\n", + atomic_read(&mmc->cq_tuning_now)); + +#else + pr_err("driver not supported\n"); +#endif +} + +void msdc_cmdq_func(struct msdc_host *host, const int num) +{ +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + void __iomem *base; + int a, b; +#endif + + if (!host || !host->mmc || !host->mmc->card) + return; + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + base = host->base; +#endif + + switch (num) { + case 0: + msdc_cmdq_status_print(host); + break; +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + case 1: + pr_err("force enable cmdq\n"); + host->mmc->card->ext_csd.cmdq_support = 1; + host->mmc->cmdq_support_changed = 1; + break; + case 2: + mmc_cmd_dump(host->mmc); + break; + case 3: + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRDLY, a); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRDLY, a+1); + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRDLY, b); + pr_err("force MSDC_PAD_TUNE0_CMDRDLY %d -> %d\n", a, b); + break; + case 4: + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY1, a); + MSDC_SET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY1, a+1); + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY1, b); + pr_err("force MSDC_EMMC50_PAD_DS_TUNE_DLY1 %d -> %d\n", a, b); + break; + case 5: + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY2, a); + MSDC_SET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY2, a+1); + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY2, b); + pr_err("force MSDC_EMMC50_PAD_DS_TUNE_DLY2 %d -> %d\n", a, b); + break; + case 6: + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY3, a); + MSDC_SET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY3, a+1); + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY3, b); + pr_err("force MSDC_EMMC50_PAD_DS_TUNE_DLY3 %d -> %d\n", a, b); + break; +#endif + default: + pr_err("unknown function id %d\n", num); + break; + } +} + +/* Clone from core/mmc.c since it is static in mmc.c */ +static void msdc_select_card_type(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + u8 card_type = card->ext_csd.raw_card_type; + u32 caps = host->caps, caps2 = host->caps2; + unsigned int hs_max_dtr = 0, hs200_max_dtr = 0; + unsigned int avail_type = 0; + + if (caps & MMC_CAP_MMC_HIGHSPEED && + card_type & EXT_CSD_CARD_TYPE_HS_26) { + hs_max_dtr = MMC_HIGH_26_MAX_DTR; + avail_type |= EXT_CSD_CARD_TYPE_HS_26; + } + + if (caps & MMC_CAP_MMC_HIGHSPEED && + card_type & EXT_CSD_CARD_TYPE_HS_52) { + hs_max_dtr = MMC_HIGH_52_MAX_DTR; + avail_type |= EXT_CSD_CARD_TYPE_HS_52; + } + + if (caps & MMC_CAP_1_8V_DDR && + card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) { + hs_max_dtr = MMC_HIGH_DDR_MAX_DTR; + avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V; + } + + if (caps & MMC_CAP_1_2V_DDR && + card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) { + hs_max_dtr = MMC_HIGH_DDR_MAX_DTR; + avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V; + } + + if (caps2 & MMC_CAP2_HS200_1_8V_SDR && + card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) { + hs200_max_dtr = MMC_HS200_MAX_DTR; + avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V; + } + + if (caps2 & MMC_CAP2_HS200_1_2V_SDR && + card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) { + hs200_max_dtr = MMC_HS200_MAX_DTR; + avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V; + } + + if (caps2 & MMC_CAP2_HS400_1_8V && + card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) { + hs200_max_dtr = MMC_HS200_MAX_DTR; + avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V; + } + + if (caps2 & MMC_CAP2_HS400_1_2V && + card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) { + hs200_max_dtr = MMC_HS200_MAX_DTR; + avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V; + } + + card->ext_csd.hs_max_dtr = hs_max_dtr; + card->ext_csd.hs200_max_dtr = hs200_max_dtr; + card->mmc_avail_type = avail_type; +} + +void msdc_get_host_mode_speed(struct mmc_host *mmc) +{ + pr_err("[SD_Debug]msdc[%d] supports:\n", mmc->index); + + if (mmc->caps & MMC_CAP_MMC_HIGHSPEED) + pr_err("[SD_Debug] MMC_TIMING_MMC_HS\n"); + if (mmc->caps & MMC_CAP_SD_HIGHSPEED) + pr_err("[SD_Debug] MMC_TIMING_SD_HS\n"); + if (mmc->caps & MMC_CAP_UHS_SDR12) + pr_err("[SD_Debug] MMC_CAP_UHS_SDR12\n"); + if (mmc->caps & MMC_CAP_UHS_SDR25) + pr_err("[SD_Debug] MMC_CAP_UHS_SDR25\n"); + if (mmc->caps & MMC_CAP_UHS_SDR104) + pr_err("[SD_Debug] MMC_CAP_UHS_SDR104\n"); + if (mmc->caps & MMC_CAP_UHS_DDR50) + pr_err("[SD_Debug] MMC_CAP_UHS_DDR50\n"); + if (mmc->caps & MMC_CAP_1_8V_DDR) + pr_err("[SD_Debug] MMC_CAP_MMC_DDR52\n"); + if (mmc->caps2 & MMC_CAP2_HS200_1_8V_SDR) + pr_err("[SD_Debug] MMC_TIMING_MMC_HS200\n"); + if (mmc->caps2 & MMC_CAP2_HS400_1_8V) + pr_err("[SD_Debug] MMC_TIMING_MMC_HS400\n"); + + pr_err("[SD_Debug] Command queue feature is disable\n"); + +} + +void msdc_set_host_mode_speed(struct mmc_host *mmc, int spd_mode, int cmdq) +{ + struct msdc_host *host = mmc_priv(mmc); + + /* Clear HS400, HS200 timing */ + mmc->caps2 &= + ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR); + /* Clear other timing */ + mmc->caps &= ~(MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | + MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR); + switch (spd_mode) { + case MMC_TIMING_LEGACY: + break; + case MMC_TIMING_MMC_HS: + mmc->caps |= MMC_CAP_MMC_HIGHSPEED; + break; + case MMC_TIMING_SD_HS: + mmc->caps |= MMC_CAP_SD_HIGHSPEED; + break; + case MMC_TIMING_UHS_SDR12: + mmc->caps |= MMC_CAP_UHS_SDR12; + break; + case MMC_TIMING_UHS_SDR25: + mmc->caps |= MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR12; + break; + case MMC_TIMING_UHS_SDR50: + mmc->caps |= MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR12; + break; + case MMC_TIMING_UHS_SDR104: + mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50 | + MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR12; + break; + case MMC_TIMING_UHS_DDR50: + mmc->caps |= MMC_CAP_UHS_DDR50 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR12; + break; + case MMC_TIMING_MMC_DDR52: + mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_MMC_HIGHSPEED; + break; + case MMC_TIMING_MMC_HS200: + mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR; + mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_MMC_HIGHSPEED; + break; + case MMC_TIMING_MMC_HS400: + mmc->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR; + mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_MMC_HIGHSPEED; + break; + default: + pr_err("[SD_Debug]invalid speed mode:%d\n", + spd_mode); + break; + } + + msdc_get_host_mode_speed(mmc); + +#if 0 + if (cmdq) + pr_err("[SD_Debug] enable command queue feature\n"); + else + pr_err("[SD_Debug] disable command queue feature\n"); +#endif + + if (!mmc->card || mmc_card_sd(mmc->card)) + return; + + /* For suppressing msdc_dump_info() caused by + cmd13 do in mmc_reset()@mmc.c */ + msdc_select_card_type(mmc); + g_emmc_mode_switch = 1; + + mmc_claim_host(mmc); + + if (mmc->card->ext_csd.cache_ctrl) { + mmc_flush_cache(mmc->card); + msdc_cache_ctrl(host, 0, NULL); + } + + /* Since only mmc_hw_reset() is public, + so use mmc_hw_reset() to reinit card */ + mmc->caps |= MMC_CAP_HW_RESET; + + /* Must set mmc_host ios.time = MMC_TIMING_LEGACY, + * or clock will not be setted to 400K before mmc_init_card + * CMD1 will timeout + */ + mmc->ios.timing = MMC_TIMING_LEGACY; + + if (mmc_hw_reset(mmc)) + pr_err("[SD_Debug] Reinit card failed, Can not switch speed mode\n"); + + g_emmc_mode_switch = 0; + + mmc->caps &= ~MMC_CAP_HW_RESET; + + mmc_release_host(mmc); +} + +static void msdc_set_field(void __iomem *address, unsigned int start_bit, + unsigned int len, unsigned int value) +{ + unsigned long field; + + if (start_bit > 31 || start_bit < 0 || len > 31 || len <= 0 + || (start_bit + len > 31)) { + pr_err("[SD_Debug]invalid reg field range or length\n"); + } else { + field = ((1 << len) - 1) << start_bit; + value &= (1 << len) - 1; + pr_err("[SD_Debug]Original:0x%p (0x%x)\n", + address, MSDC_READ32(address)); + MSDC_SET_FIELD(address, field, value); + pr_err("[SD_Debug]Modified:0x%p (0x%x)\n", + address, MSDC_READ32(address)); + } +} + +static void msdc_get_field(void __iomem *address, unsigned int start_bit, + unsigned int len, unsigned int value) +{ + unsigned long field; + if (start_bit > 31 || start_bit < 0 || len > 31 || len <= 0 + || (start_bit + len > 31)) { + pr_err("[SD_Debug]invalid reg field range or length\n"); + } else { + field = ((1 << len) - 1) << start_bit; + MSDC_GET_FIELD(address, field, value); + pr_err("[SD_Debug]Reg:0x%p start_bit(%d)len(%d)(0x%x)\n", + address, start_bit, len, value); + } +} + +static void msdc_init_gpt(void) +{ +#if 0 + GPT_CONFIG config; + + config.num = GPT6; + config.mode = GPT_FREE_RUN; + config.clkSrc = GPT_CLK_SRC_SYS; + config.clkDiv = GPT_CLK_DIV_1; /* 13MHz GPT6 */ + + if (GPT_Config(config) == FALSE) + return; + + GPT_Start(GPT6); +#endif +} + +u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32) +{ + u32 ret = 0; + + if (new_H32 == old_H32) { + ret = new_L32 - old_L32; + } else if (new_H32 == (old_H32 + 1)) { + if (new_L32 > old_L32) { + pr_debug("msdc old_L<0x%x> new_L<0x%x>\n", + old_L32, new_L32); + } + ret = (0xffffffff - old_L32); + ret += new_L32; + } else { + pr_debug("msdc old_H<0x%x> new_H<0x%x>\n", + old_H32, new_H32); + } + + return ret; +} + +void msdc_sdio_profile(struct sdio_profile *result) +{ + struct cmd_profile *cmd; + u32 i; + + pr_debug("sdio === performance dump ===\n"); + pr_debug("sdio === total execute tick<%d> time<%dms> Tx<%dB> Rx<%dB>\n", + result->total_tc, result->total_tc / TICKS_ONE_MS, + result->total_tx_bytes, result->total_rx_bytes); + + /* CMD52 Dump */ + cmd = &result->cmd52_rx; + pr_debug("sdio === CMD52 Rx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", + cmd->count, cmd->tot_tc, + cmd->max_tc, cmd->min_tc, cmd->tot_tc / cmd->count); + cmd = &result->cmd52_tx; + pr_debug("sdio === CMD52 Tx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", + cmd->count, cmd->tot_tc, + cmd->max_tc, cmd->min_tc, cmd->tot_tc / cmd->count); + + /* CMD53 Rx bytes + block mode */ + for (i = 0; i < 512; i++) { + cmd = &result->cmd53_rx_byte[i]; + if (cmd->count == 0) + continue; + pr_debug("sdio<%6d><%3dB>_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", + cmd->count, i, cmd->tot_tc, cmd->max_tc, cmd->min_tc, + cmd->tot_tc / cmd->count, cmd->tot_bytes, + (cmd->tot_bytes / 10) * 13 / (cmd->tot_tc / 10)); + } + for (i = 0; i < 100; i++) { + cmd = &result->cmd53_rx_blk[i]; + if (cmd->count == 0) + continue; + pr_debug("sdio<%6d><%3d>B_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", + cmd->count, i, cmd->tot_tc, cmd->max_tc, cmd->min_tc, + cmd->tot_tc / cmd->count, cmd->tot_bytes, + (cmd->tot_bytes / 10) * 13 / (cmd->tot_tc / 10)); + } + + /* CMD53 Tx bytes + block mode */ + for (i = 0; i < 512; i++) { + cmd = &result->cmd53_tx_byte[i]; + if (cmd->count == 0) + continue; + pr_debug("sdio<%6d><%3dB>_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", + cmd->count, i, cmd->tot_tc, cmd->max_tc, cmd->min_tc, + cmd->tot_tc / cmd->count, cmd->tot_bytes, + (cmd->tot_bytes / 10) * 13 / (cmd->tot_tc / 10)); + } + for (i = 0; i < 100; i++) { + cmd = &result->cmd53_tx_blk[i]; + if (cmd->count == 0) + continue; + pr_debug("sdio<%6d><%3d>B_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", + cmd->count, i, cmd->tot_tc, cmd->max_tc, cmd->min_tc, + cmd->tot_tc / cmd->count, cmd->tot_bytes, + (cmd->tot_bytes / 10) * 13 / (cmd->tot_tc / 10)); + } + + pr_debug("sdio === performance dump done ===\n"); +} + +/* ========= sdio command table =========== */ +void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks) +{ + struct sdio_profile *result = &sdio_perfomance; + struct cmd_profile *cmd; + u32 block; + long long endtime; + + if (sdio_pro_enable == 0) + return; + + if (opcode == 52) { + cmd = bRx ? &result->cmd52_rx : &result->cmd52_tx; + } else if (opcode == 53) { + if (sizes < 512) { + cmd = bRx ? &result->cmd53_rx_byte[sizes] : + &result->cmd53_tx_byte[sizes]; + } else { + block = sizes / 512; + if (block >= 99) { + pr_err("cmd53 error blocks\n"); + while (1) + ; + } + cmd = bRx ? &result->cmd53_rx_blk[block] : + &result->cmd53_tx_blk[block]; + } + } else { + return; + } + + /* update the members */ + if (ticks > cmd->max_tc) + cmd->max_tc = ticks; + + if (cmd->min_tc == 0 || ticks < cmd->min_tc) + cmd->min_tc = ticks; + + cmd->tot_tc += ticks; + cmd->tot_bytes += sizes; + cmd->count++; + + if (bRx) + result->total_rx_bytes += sizes; + else + result->total_tx_bytes += sizes; + + result->total_tc += ticks; +#if 0 + /* dump when total_tc > 30s */ + if (result->total_tc >= sdio_pro_time * TICKS_ONE_MS * 1000) { + msdc_sdio_profile(result); + memset(result, 0, sizeof(struct sdio_profile)); + } +#endif + + endtime = sched_clock(); + if ((endtime - sdio_profiling_start) >= + sdio_pro_time * 1000000000) { + msdc_sdio_profile(result); + memset(result, 0, sizeof(struct sdio_profile)); + sdio_profiling_start = endtime; + } + + +} + +#define COMPARE_ADDRESS_MMC 0x402000 +#define COMPARE_ADDRESS_SD 0x2000 +#define COMPARE_ADDRESS_SDIO 0x0 +#define COMPARE_ADDRESS_SD_COMBO 0x2000 + +#define MSDC_MULTI_BUF_LEN (4*4*1024) /*16KB write/read/compare*/ + +static DEFINE_MUTEX(sd_lock); +static DEFINE_MUTEX(emmc_lock); + +u8 read_write_state = 0; /* 0:stop, 1:read, 2:write */ + +static u8 wData_emmc[16] = { + 0x67, 0x45, 0x23, 0x01, + 0xef, 0xcd, 0xab, 0x89, + 0xce, 0x8a, 0x46, 0x02, + 0xde, 0x9b, 0x57, 0x13 +}; + +static u8 wData_sd[200] = { + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, /*worst1*/ + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, + + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, /*worst2*/ + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, /*worst3*/ + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, /*worst4*/ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + + 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, /*worst5*/ + 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, + 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x40, 0x40, + 0x04, 0xfb, 0x04, 0x04, 0x04, 0xfb, 0xfb, 0xfb, + 0x04, 0xfb, 0xfb, 0xfb, 0x02, 0x02, 0x02, 0xfd, + 0x02, 0x02, 0x02, 0xfd, 0xfd, 0xfd, 0x02, 0xfd, + 0xfd, 0xfd, 0x01, 0x01, 0x01, 0xfe, 0x01, 0x01, + 0x01, 0xfe, 0xfe, 0xfe, 0x01, 0xfe, 0xfe, 0xfe, + 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, + 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x40, 0x40, + 0x40, 0x40, 0x80, 0x7f, 0x7f, 0x7f, 0x40, 0x40, + 0x20, 0xdf, 0x20, 0x20, 0x20, 0xdf, 0xdf, 0xdf, + 0x10, 0x10, 0x10, 0xef, 0xef, 0x10, 0xef, 0xef, +}; + +/* + * @read, bit0: 1:read/0:write; bit1: 0:compare/1:not compare +*/ +static int multi_rw_compare_core(int host_num, int read, uint address, + uint type) +{ + struct scatterlist msdc_sg; + struct mmc_data msdc_data; + struct mmc_command msdc_cmd; + struct mmc_command msdc_stop; + + u32 *multi_rwbuf = NULL; + u8 *wPtr = NULL, *rPtr = NULL; + + struct mmc_request msdc_mrq; + struct msdc_host *host_ctl; + struct mmc_host *mmc; + int result = 0, forIndex = 0; + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + int is_cmdq_en; + int ret; +#endif + + u8 wData_len; + u8 *wData; + + if (host_num >= HOST_MAX_NUM || host_num < 0) { + pr_err("[%s]invalid host id: %d\n", __func__, host_num); + return -1; + } + + host_ctl = mtk_msdc_host[host_num]; + + + if (!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card) { + pr_err(" No card initialized in host[%d]\n", host_num); + result = -1; + return result; + } + + if (type == MMC_TYPE_MMC) { + wData = wData_emmc; + wData_len = 16; + } else if (type == MMC_TYPE_SD) { + wData = wData_sd; + wData_len = 200; + } else + return -1; + + /*allock memory for test buf*/ + multi_rwbuf = kzalloc((MSDC_MULTI_BUF_LEN), GFP_KERNEL); + if (multi_rwbuf == NULL) { + result = -1; + return result; + } + rPtr = wPtr = (u8 *)multi_rwbuf; + + if (!is_card_present(host_ctl)) { + pr_err(" [%s]: card is removed!\n", __func__); + result = -1; + goto free; + } + + mmc = host_ctl->mmc; + + mmc_claim_host(mmc); + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + is_cmdq_en = false; + if (host_num == 0 && host_ctl->mmc->card->ext_csd.cmdq_mode_en) { + /* cmdq enabled, turn it off first */ + pr_debug("[MSDC_DBG] cmdq enabled, turn it off\n"); + ret = mmc_blk_cmdq_switch(host_ctl->mmc->card, 0); + if (ret) { + pr_debug("[MSDC_DBG] turn off cmdq en failed\n"); + mmc_release_host(host_ctl->mmc); + result = -1; + goto free; + } else + is_cmdq_en = true; + } +#endif + +#ifdef CONFIG_MTK_EMMC_SUPPORT + if (host_ctl->hw->host_function == MSDC_EMMC) + msdc_switch_part(host_ctl, 0); +#endif + + memset(&msdc_data, 0, sizeof(struct mmc_data)); + memset(&msdc_mrq, 0, sizeof(struct mmc_request)); + memset(&msdc_cmd, 0, sizeof(struct mmc_command)); + memset(&msdc_stop, 0, sizeof(struct mmc_command)); + + msdc_mrq.cmd = &msdc_cmd; + msdc_mrq.data = &msdc_data; + msdc_data.blocks = MSDC_MULTI_BUF_LEN / 512; + + if (read) { + /* init read command */ + msdc_data.flags = MMC_DATA_READ; + msdc_cmd.opcode = MMC_READ_MULTIPLE_BLOCK; + } else { + /* init write command */ + msdc_data.flags = MMC_DATA_WRITE; + msdc_cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; + /* init write buffer */ + for (forIndex = 0; forIndex < MSDC_MULTI_BUF_LEN; forIndex++) + *(wPtr + forIndex) = wData[forIndex % wData_len]; + } + + msdc_cmd.arg = address; + msdc_stop.opcode = MMC_STOP_TRANSMISSION; + msdc_stop.arg = 0; + msdc_stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + msdc_data.stop = &msdc_stop; + + if (!mmc_card_blockaddr(host_ctl->mmc->card)) { + /* pr_err("this device use byte address!!\n"); */ + msdc_cmd.arg <<= 9; + } + msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + + msdc_data.blksz = 512; + msdc_data.sg = &msdc_sg; + msdc_data.sg_len = 1; + + sg_init_one(&msdc_sg, multi_rwbuf, MSDC_MULTI_BUF_LEN); + + mmc_set_data_timeout(&msdc_data, mmc->card); + mmc_wait_for_req(mmc, &msdc_mrq); + /* compare */ + if (!read) + goto skip_check; + + for (forIndex = 0; forIndex < MSDC_MULTI_BUF_LEN; forIndex++) { + /* + pr_err("index[%d]\tW_buffer[0x%x]\tR_buffer[0x%x]\t\n", + forIndex, wData[forIndex%wData_len], rPtr[forIndex]); + */ + if (rPtr[forIndex] != wData[forIndex % wData_len]) { + pr_err("index[%d]\tW_buffer[0x%x]\tR_buffer[0x%x]\tfailed\n", + forIndex, wData[forIndex % wData_len], + rPtr[forIndex]); + result = -1; + } + } + +skip_check: +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (is_cmdq_en) { + pr_debug("[MSDC_DBG] turn on cmdq\n"); + ret = mmc_blk_cmdq_switch(host_ctl->mmc->card, 1); + if (ret) + pr_debug("[MSDC_DBG] turn on cmdq en failed\n"); + else + is_cmdq_en = false; + } +#endif + mmc_release_host(host_ctl->mmc); + + if (msdc_cmd.error) + result = msdc_cmd.error; + + if (msdc_data.error) + result = msdc_data.error; + else + result = 0; + +free: + kfree(multi_rwbuf); + + return result; +} + +int multi_rw_compare(int host_num, uint address, int count, uint type) +{ + int i = 0, j = 0; + int error = 0; + struct mutex *rw_mutex; + + if (type == MMC_TYPE_SD) + rw_mutex = &sd_lock; + else if (type == MMC_TYPE_MMC) + rw_mutex = &emmc_lock; + else + return 0; + + for (i = 0; i < count; i++) { + /* pr_err("== cpu[%d] pid[%d]: start %d time compare ==\n", + task_cpu(current), current->pid, i); */ + + mutex_lock(rw_mutex); + /* write */ + error = multi_rw_compare_core(host_num, 0, address, type); + if (error) { + pr_err("[%s]: failed to write data, error=%d\n", + __func__, error); + mutex_unlock(rw_mutex); + break; + } + + /* read */ + for (j = 0; j < 1; j++) { + error = multi_rw_compare_core(host_num, 1, address, + type); + if (error) { + pr_err("[%s]: failed to read data, error=%d\n", + __func__, error); + break; + } + } + pr_err("== cpu[%d] pid[%d]: %s %d time compare ==\n", + task_cpu(current), current->pid, + (error ? "FAILED" : "FINISH"), i); + + mutex_unlock(rw_mutex); + } + + if (i == count) + pr_err("pid[%d]: success to compare data for %d times\n", + current->pid, count); + + return error; +} + +#define MAX_THREAD_NUM_FOR_SMP 20 + +/* make the test can run on 4GB card */ +static uint smp_address_on_sd[MAX_THREAD_NUM_FOR_SMP] = { + 0x2000, + 0x80000, + 0x100000, + 0x180000, + 0x200000, /* 1GB */ + 0x202000, + 0x280000, + 0x300000, + 0x380000, + 0x400000, /* 2GB */ + 0x402000, + 0x480000, + 0x500000, + 0x580000, + 0x600000, + 0x602000, /* 3GB */ + 0x660000, /* real total size of 4GB sd card is < 4GB */ + 0x680000, + 0x6a0000, + 0x6b0000, +}; + +/* cause the system run on the emmc storage, + * so do not to access the first 2GB region */ +static uint smp_address_on_mmc[MAX_THREAD_NUM_FOR_SMP] = { + 0x402000, + 0x410000, + 0x520000, + 0x530000, + 0x640000, + 0x452000, + 0x460000, + 0x470000, + 0x480000, + 0x490000, + 0x4a2000, + 0x4b0000, + 0x5c0000, + 0x5d0000, + 0x6e0000, + 0x602000, + 0x660000, /* real total size of 4GB sd card is < 4GB */ + 0x680000, + 0x6a0000, + 0x6b0000, +}; + +struct write_read_data { + int host_id; /* target host you want to do SMP test on. */ + uint start_address; /* Address of memcard you want to write/read */ + int count; /* times you want to do read after write */ +}; + +static struct write_read_data wr_data[HOST_MAX_NUM][MAX_THREAD_NUM_FOR_SMP]; +/* + * 2012-03-25 + * the SMP thread function + * do read after write the memory card, and bit by bit comparison + */ + +struct task_struct *rw_thread = NULL; + +static int write_read_thread(void *ptr) +{ + struct write_read_data *data = (struct write_read_data *)ptr; + + if (1 == data->host_id) { + pr_err("sd thread\n"); + multi_rw_compare(data->host_id, data->start_address, + data->count, MMC_TYPE_SD); + } else if (0 == data->host_id) { + pr_err("emmc thread\n"); + multi_rw_compare(data->host_id, data->start_address, + data->count, MMC_TYPE_MMC); + } + return 0; +} + +/* + * 2012-03-25 + * function: do SMP test on all MSDC hosts + * thread_num: number of thread to be triggerred on this host. + * count: times you want to do read after writein each thread. + * multi_address: whether do read/write the same/different address of + * the memory card in each thread. + */ +static int smp_test_on_hosts(int thread_num, int host_id, int count, + int multi_address) +{ + int i = 0, j = 0; + int id_start, id_end; + int ret = 0; + uint start_address, type; + char thread_name[128]; + struct msdc_host *host_ctl; + + pr_err("=======================[%s] start ===========================\n\n", + __func__); + pr_err(" each host run %d thread, each thread run %d RW comparison\n", + thread_num, count); + if (thread_num > MAX_THREAD_NUM_FOR_SMP) { + pr_err(" too much thread for SMP test, thread_num=%d\n", + thread_num); + ret = -1; + goto out; + } + if (host_id > HOST_MAX_NUM || host_id < 0) { + pr_err(" Invalid host id %d\n", host_id); + ret = -1; + goto out; + } + if (host_id == HOST_MAX_NUM) { + id_start = 0; + id_end = HOST_MAX_NUM; + } else { + id_start = host_id; + id_end = host_id+1; + } + + + for (i = id_start; i < id_end; i++) { + host_ctl = mtk_msdc_host[i]; + if (!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card) { + pr_err(" MSDC[%d], no card is initialized\n", i); + continue; + } + type = host_ctl->mmc->card->type; + if (type == MMC_TYPE_MMC) { + if (!multi_address) + start_address = COMPARE_ADDRESS_MMC; + else + start_address = smp_address_on_mmc[i]; + } else if (type == MMC_TYPE_SD) { + if (!multi_address) + start_address = COMPARE_ADDRESS_MMC; + else + start_address = smp_address_on_sd[i]; + } else if (type == MMC_TYPE_SDIO) { + pr_err(" MSDC[%d], SDIO:\n", i); + pr_err(" please manually run wifi application instead of write/read SDIO card\n"); + continue; + } else { + pr_err(" MSDC[%d], unkwonn card type\n ", i); + continue; + } + for (j = 0; j < thread_num; j++) { + wr_data[i][j].host_id = i; + wr_data[i][j].count = count; + wr_data[i][j].start_address = start_address; + sprintf(thread_name, "msdc_H%d_T%d", i, j); + kthread_run(write_read_thread, &wr_data[i][j], + thread_name); + pr_err(" start thread: %s, at address: 0x%x\n", + thread_name, wr_data[i][j].start_address); + } + } + out: + pr_err("=======================[%s] end ===========================\n\n", + __func__); + return ret; +} + +static int msdc_help_proc_show(struct seq_file *m, void *v) +{ + seq_puts(m, "\n===============[msdc_help]================\n"); + + seq_printf(m, "\n LOG control: echo %x [host_id] [debug_zone] > msdc_debug\n", + SD_TOOL_ZONE); + seq_printf(m, " [debug_zone] DMA:0x%x, CMD:0x%x, RSP:0x%x, INT:0x%x, CFG:0x%x, FUC:0x%x,\n", + DBG_EVT_DMA, DBG_EVT_CMD, DBG_EVT_RSP, DBG_EVT_INT, DBG_EVT_CFG, + DBG_EVT_FUC); + seq_printf(m, " OPS:0x%x, FIO:0x%x, WRN:0x%x, PWR:0x%x, CLK:0x%x, RW:0x%x, NRW:0x%x, CHE:0x%x\n", + DBG_EVT_OPS, DBG_EVT_FIO, DBG_EVT_WRN, DBG_EVT_PWR, DBG_EVT_CLK, + DBG_EVT_RW, DBG_EVT_NRW, DBG_EVT_CHE); + seq_puts(m, "\n DMA mode:\n"); + seq_printf(m, " *set DMA mode: echo %x 0 [host_id] [dma_mode] [dma_size] > msdc_debug\n", + SD_TOOL_DMA_SIZE); + seq_printf(m, " *get DMA mode: echo %x 1 [host_id] > msdc_debug\n", + SD_TOOL_DMA_SIZE); + seq_puts(m, " [dma_mode] 0:PIO, 1:DMA, 2:SIZE_DEP\n"); + seq_puts(m, " [dma_size] valid for SIZE_DEP mode, the min size can trigger the DMA mode\n"); + seq_printf(m, "\n SDIO profile: echo %x [enable] [time] > msdc_debug\n", + SD_TOOL_SDIO_PROFILE); + seq_puts(m, "\n CLOCK control:\n"); + seq_printf(m, " *set clk src: echo %x 0 [host_id] [clk_src] > msdc_debug\n", + SD_TOOL_CLK_SRC_SELECT); + seq_printf(m, " *get clk src: echo %x 1 [host_id] > msdc_debug\n", + SD_TOOL_CLK_SRC_SELECT); + seq_puts(m, " [clk_src] msdc0: 0:26M, 1:800M, 2:400M, 3:200M, 4:182M, 5:136M, 6:156M, 7:48M, 8:91M\n"); + seq_puts(m, " [clk_src] msdc1/2/3: 0:26M, 1:208M, 2:200M, 3:182M, 4:182M, 5:136M, 6:156M, 7:48M, 8:91M\n"); + seq_puts(m, "\n REGISTER control:\n"); + seq_printf(m, " write register: echo %x 0 [host_id] [register_offset] [value] > msdc_debug\n", + SD_TOOL_REG_ACCESS); + seq_printf(m, " read register: echo %x 1 [host_id] [register_offset] > msdc_debug\n", + SD_TOOL_REG_ACCESS); + seq_printf(m, " write mask: echo %x 2 [host_id] [register_offset] [start_bit] [len] [value] > msdc_debug\n", + SD_TOOL_REG_ACCESS); + seq_printf(m, " read mask: echo %x 3 [host_id] [register_offset] [start_bit] [len] > msdc_debug\n", + SD_TOOL_REG_ACCESS); + seq_printf(m, " dump all: echo %x 4 [host_id] > msdc_debug\n", + SD_TOOL_REG_ACCESS); + seq_puts(m, "\n DRVING control:\n"); + seq_printf(m, " set driving: echo %x [host_id] [clk_drv] [cmd_drv] [dat_drv] [rst_drv] [ds_drv] [voltage] > msdc_debug\n", + SD_TOOL_SET_DRIVING); + seq_puts(m, " [voltage] 1: 18v, 0: 33v\n"); + seq_printf(m, " get driving: echo %x 0 [host_id] > msdc_debug\n", + SD_TOOL_SET_DRIVING); + seq_puts(m, "\n DESENSE control:\n"); + seq_printf(m, " write register: echo %x 0 [value] > msdc_debug\n", + SD_TOOL_DESENSE); + seq_printf(m, " read register: echo %x 1 > msdc_debug\n", + SD_TOOL_DESENSE); + seq_printf(m, " write mask: echo %x 2 [start_bit] [len] [value] > msdc_debug\n", + SD_TOOL_DESENSE); + seq_printf(m, " read mask: echo %x 3 [start_bit] [len] > msdc_debug\n", + SD_TOOL_DESENSE); + seq_printf(m, "\n RW_COMPARE test: echo %x [host_id] [compare_count] > msdc_debug\n", + RW_BIT_BY_BIT_COMPARE); + seq_puts(m, " [compare_count] how many time you want to \"write=>read=>compare\"\n"); + seq_printf(m, "\n SMP_ON_ONE_HOST test: echo %x [host_id] [thread_num] [compare_count] [multi_address] > msdc_debug\n", + SMP_TEST_ON_ONE_HOST); + seq_puts(m, " [thread_num] how many R/W comparision thread you want to run at host_id\n"); + seq_puts(m, " [compare_count] how many time you want to \"write=>read=>compare\" in each thread\n"); + seq_puts(m, " [multi_address] whether read/write different address in each thread, 0:No, 1:Yes\n"); + seq_printf(m, "\n SMP_ON_ALL_HOST test: echo %x [thread_num] [compare_count] [multi_address] > msdc_debug\n", + SMP_TEST_ON_ALL_HOST); + seq_puts(m, " [thread_num] how many R/W comparision thread you want to run at each host\n"); + seq_puts(m, " [compare_count] how many time you want to \"write=>read=>compare\" in each thread\n"); + seq_puts(m, " [multi_address] whether read/write different address in each thread, 0:No, 1:Yes\n"); + seq_puts(m, "\n SPEED_MODE control:\n"); + seq_printf(m, " set speed mode: echo %x 1 [host_id] [speed_mode] [cmdq]> msdc_debug\n", + SD_TOOL_MSDC_HOST_MODE); + seq_printf(m, " get speed mode: echo %x 0 [host_id]\n", + SD_TOOL_MSDC_HOST_MODE); + seq_puts(m, " [speed_mode] 0: MMC_TIMING_LEGACY 1: MMC_TIMING_MMC_HS 2: MMC_TIMING_SD_HS 3: MMC_TIMING_UHS_SDR12\n" + " 4: MMC_TIMING_UHS_SDR25 5: MMC_TIMING_UHS_SDR50 6: MMC_TIMING_UHS_SDR104 7: MMC_TIMING_UHS_DDR50\n" + " 8: MMC_TIMING_MMC_DDR52 9: MMC_TIMING_MMC_HS200 A: MMC_TIMING_MMC_HS400\n" + " [cmdq] 0: disable cmdq feature\n" + " 1: enable cmdq feature\n"); + seq_printf(m, "\n DMA viloation: echo %x [host_id] [ops]> msdc_debug\n", + SD_TOOL_DMA_STATUS); + seq_puts(m, " [ops] 0:get latest dma address, 1:start violation test\n"); + seq_printf(m, "\n SET Slew Rate: echo %x [host_id] [clk] [cmd] [dat] [rst] [ds]> msdc_debug\n", + SD_TOOL_ENABLE_SLEW_RATE); + seq_puts(m, "\n TD/RD SEL:\n"); + seq_printf(m, " set rdsel: echo %x [host_id] 0 [value] > msdc_debug\n", + SD_TOOL_SET_RDTDSEL); + seq_printf(m, " set tdsel: echo %x [host_id] 1 [value] > msdc_debug\n", + SD_TOOL_SET_RDTDSEL); + seq_printf(m, " get tdsel/rdsel: echo %x [host_id] 2 > msdc_debug\n", + SD_TOOL_SET_RDTDSEL); + seq_puts(m, " [value] rdsel: 0x0<<4 ~ 0x3f<<4, tdsel: 0x0~0xf\n"); + seq_printf(m, "\n EMMC/SD RW test: echo %x [host_id] [mode] > msdc_debug\n", + MSDC_READ_WRITE); + seq_puts(m, " [mode] mode 0:stop, 1:read, 2:write\n"); + seq_printf(m, "\n Error tune debug: echo %x [host_id] [cmd_id] [arg] [error_type] [count] > msdc_debug\n", + MMC_ERROR_TUNE); + seq_puts(m, " [cmd_id] 0: CMD0, 1: CMD1, 2: CMD2......\n"); + seq_puts(m, " [arg] for CMD6, arg means ext_csd index......\n"); + seq_puts(m, " [error] 0: disable error tune debug, 1: cmd timeout, 2: cmd crc, 4: dat timeout, 8: dat crc, 16: acmd timeout, 32: acmd crc\n"); + seq_puts(m, " [count] error count\n"); + seq_printf(m, "\n eMMC Cache Control: echo %x [host_id] [action_id] > /proc/msdc_debug\n", + MMC_EDC_EMMC_CACHE); + seq_puts(m, " [action_id] 0:Disable cache 1:Enable cache 2:check cache status\n"); + seq_printf(m, "\n eMMC Dump GPD/BD: echo %x [host_id] > /proc/msdc_debug\n", + MMC_DUMP_GPD); + seq_puts(m, " [type] 0:tune cmd 1:tune read 2:tune write 3:tune HS400\n"); + seq_puts(m, " [start_voltage] ?mV\n"); + seq_puts(m, " [end_voltage] ?mV, we try ETT from higher voltage to lower voltage\n"); + seq_printf(m, "\n CRC Stress Test: echo %x [action_id]> /proc/msdc_debug\n", + MMC_CRC_STRESS); + seq_puts(m, " [action_id] 0:disable 1:enable\n"); + seq_printf(m, "\n Enable AXI Modules: echo %x [action_id][module_id]> /proc/msdc_debug\n", + ENABLE_AXI_MODULE); + seq_puts(m, " [action_id] 0:disable 1:enable\n"); + + seq_printf(m, "\n SDIO AutoK Result : echo %x [host_id][vcore][rw]> /proc/msdc_debug\n", + SDIO_AUTOK_RESULT); + seq_puts(m, " [host_id] 2:sdio\n"); + seq_puts(m, " [vcore] 0:low 1:high\n"); + seq_puts(m, " [rw] 0:read 1:write\n"); + + seq_puts(m, "\n NOTE: All input data is Hex number!\n"); + + seq_puts(m, "\n=============================================\n\n"); + + return 0; +} + +/* FIX ME: check if this function can be removed*/ +void msdc_hw_parameter_debug(struct msdc_hw *hw, struct seq_file *m, void *v) +{ + int i; + seq_printf(m, "hw->clk_src = %x\n", hw->clk_src); + seq_printf(m, "hw->cmd_edge = %x\n", hw->cmd_edge); + seq_printf(m, "hw->rdata_edge = %x\n", hw->rdata_edge); + seq_printf(m, "hw->wdata_edge = %x\n", hw->wdata_edge); + seq_printf(m, "hw->clk_drv = %x\n", hw->clk_drv); + seq_printf(m, "hw->cmd_drv = %x\n", hw->cmd_drv); + seq_printf(m, "hw->dat_drv = %x\n", hw->dat_drv); + seq_printf(m, "hw->rst_drv = %x\n", hw->rst_drv); + seq_printf(m, "hw->ds_drv = %x\n", hw->ds_drv); + seq_printf(m, "hw->flags = %x\n", (unsigned int)hw->flags); + + for (i = 0; i < 8; i++) + seq_printf(m, "hw->dat%drddly = %x\n", i, hw->datrddly[i]); + + seq_printf(m, "hw->datwrddly = %x\n", hw->datwrddly); + seq_printf(m, "hw->cmdrrddly = %x\n", hw->cmdrrddly); + seq_printf(m, "hw->cmdrddly = %x\n", hw->cmdrddly); + seq_printf(m, "hw->host_function = %x\n", (u32)hw->host_function); + seq_printf(m, "hw->boot = %x\n", hw->boot); +} +/* ========== driver proc interface =========== */ +static int msdc_debug_proc_show(struct seq_file *m, void *v) +{ + + seq_puts(m, "\n=========================================\n"); + + seq_puts(m, "Index<0> + Id + Zone\n"); + seq_puts(m, "-> PWR<9> WRN<8> | FIO<7> OPS<6> FUN<5> CFG<4> | INT<3> RSP<2> CMD<1> DMA<0>\n"); + seq_puts(m, "-> echo 0 3 0x3ff >msdc_bebug -> host[3] debug zone set to 0x3ff\n"); + seq_printf(m, "-> MSDC[0] Zone: 0x%.8x\n", sd_debug_zone[0]); + seq_printf(m, "-> MSDC[1] Zone: 0x%.8x\n", sd_debug_zone[1]); + + seq_printf(m, "-> MSDC[2] Zone: 0x%.8x\n", sd_debug_zone[2]); + seq_printf(m, "-> MSDC[3] Zone: 0x%.8x\n", sd_debug_zone[3]); + + seq_puts(m, "Index<1> + ID:4|Mode:4 + DMA_SIZE\n"); + seq_puts(m, "-> 0)PIO 1)DMA 2)SIZE\n"); + seq_puts(m, "-> echo 1 22 0x200 >msdc_bebug -> host[2] size mode, dma when >= 512\n"); + seq_printf(m, "-> MSDC[0] mode<%d> size<%d>\n", + drv_mode[0], dma_size[0]); + seq_printf(m, "-> MSDC[1] mode<%d> size<%d>\n", + drv_mode[1], dma_size[1]); + + seq_printf(m, "-> MSDC[2] mode<%d> size<%d>\n", + drv_mode[2], dma_size[2]); + seq_printf(m, "-> MSDC[3] mode<%d> size<%d>\n", + drv_mode[3], dma_size[3]); + + seq_puts(m, "Index<3> + SDIO_PROFILE + TIME\n"); + seq_puts(m, "-> echo 3 1 0x1E > msdc_bebug -> enable sdio_profile, 30s\n"); + seq_printf(m, "-> SDIO_PROFILE<%d> TIME<%llu s>\n", + sdio_pro_enable, sdio_pro_time); + seq_printf(m, "-> Clokc SRC of Host[0]<%d>\n", msdc_clock_src[0]); + seq_printf(m, "-> Clokc SRC of Host[1]<%d>\n", msdc_clock_src[1]); + seq_printf(m, "-> Clokc SRC of Host[2]<%d>\n", msdc_clock_src[2]); + seq_printf(m, "-> Clokc SRC of Host[3]<%d>\n", msdc_clock_src[3]); + seq_puts(m, "=========================================\n\n"); + + /* FIX ME: check if the following 4 lines can be removed*/ + seq_puts(m, "Index<4> msdc0 hw parameter:\n"); + msdc_hw_parameter_debug(mtk_msdc_host[0]->hw, m, v); + seq_puts(m, "Index<5> msdc1 hw parameter:\n"); + msdc_hw_parameter_debug(mtk_msdc_host[1]->hw, m, v); + + return 0; +} + +/* + *data: bit0~4:id, bit4~7: mode +*/ +static int rwThread(void *data) +{ + int error, i = 0; + ulong p = (ulong) data; + int id = p & 0x3; + int mode = (p >> 4) & 0x3; + int read; + uint type, address; + + pr_err("[****SD_rwThread****]id=%d, mode=%d\n", id, mode); + + if (mode == 1) + read = 1; + else if (mode == 2) + read = 0; + else + return -1; + + while (read_write_state != 0) { + if (read_write_state == 1) + p = 0x3; + else if (read_write_state == 2) + p = 0; + + if (id == 0) { + type = MMC_TYPE_MMC; + address = COMPARE_ADDRESS_MMC; + } else if (id < HOST_MAX_NUM) { + type = MMC_TYPE_SD; + address = COMPARE_ADDRESS_SD; + } + + error = multi_rw_compare_core(id, read, address, type); + if (error) { + pr_err("[%s]: failed data id0, error=%d\n", + __func__, error); + break; + } + + i++; + if (i == 10000) { + pr_err("[***rwThread %s***]", + read_write_state == 1 ? "read" : "write"); + i = 0; + } + } + pr_err("[SD_Debug]rwThread exit\n"); + return 0; +} + +void msdc_dump_gpd_bd(int id) +{ + struct msdc_host *host; + int i = 0; + struct gpd_t *gpd; + struct bd_t *bd; + + if (id < 0 || id >= HOST_MAX_NUM) { + pr_err("[%s]: invalid host id: %d\n", __func__, id); + return; + } + + host = mtk_msdc_host[id]; + if (host == NULL) { + pr_err("[%s]: host0 or host0->dma is NULL\n", __func__); + return; + } + gpd = host->dma.gpd; + bd = host->dma.bd; + + pr_err("================MSDC GPD INFO ==================\n"); + if (gpd == NULL) { + pr_err("GPD is NULL\n"); + } else { + pr_err("gpd addr:0x%lx\n", (ulong)(host->dma.gpd_addr)); + pr_err("hwo:0x%x, bdp:0x%x, rsv0:0x%x, chksum:0x%x,intr:0x%x,rsv1:0x%x,nexth4:0x%x,ptrh4:0x%x\n", + gpd->hwo, gpd->bdp, gpd->rsv0, gpd->chksum, + gpd->intr, gpd->rsv1, (unsigned int)gpd->nexth4, + (unsigned int)gpd->ptrh4); + pr_err("next:0x%x, ptr:0x%x, buflen:0x%x, extlen:0x%x, arg:0x%x,blknum:0x%x,cmd:0x%x\n", + (unsigned int)gpd->next, (unsigned int)gpd->ptr, + gpd->buflen, gpd->extlen, gpd->arg, gpd->blknum, + gpd->cmd); + } + pr_err("================MSDC BD INFO ===================\n"); + if (bd == NULL) { + pr_err("BD is NULL\n"); + } else { + pr_err("bd addr:0x%lx\n", (ulong)(host->dma.bd_addr)); + for (i = 0; i < host->dma.sglen; i++) { + pr_err("the %d BD\n", i); + pr_err(" eol:0x%x, rsv0:0x%x, chksum:0x%x, rsv1:0x%x,blkpad:0x%x,dwpad:0x%x,rsv2:0x%x\n", + bd->eol, bd->rsv0, bd->chksum, bd->rsv1, + bd->blkpad, bd->dwpad, bd->rsv2); + pr_err(" nexth4:0x%x, ptrh4:0x%x, next:0x%x, ptr:0x%x, buflen:0x%x, rsv3:0x%x\n", + (unsigned int)bd->nexth4, + (unsigned int)bd->ptrh4, (unsigned int)bd->next, + (unsigned int)bd->ptr, bd->buflen, bd->rsv3); + } + } +} + +#ifdef MTK_MSDC_USE_CACHE +static int msdc_check_emmc_cache_status(struct msdc_host *host) +{ + struct mmc_card *card; + + BUG_ON(!host || !host->mmc || !host->mmc->card); + + card = host->mmc->card; + if (!mmc_card_mmc(card)) { + pr_err("host:%d is not a eMMC card\n", host->id); + return -2; + } + + if (0 == card->ext_csd.cache_size) { + pr_err("card don't support cache feature\n"); + return -1; + } + + pr_err("msdc%d: Current eMMC Cache status: %s, Cache size:%dKB\n", + host->id, + card->ext_csd.cache_ctrl ? "Enable" : "Disable", + card->ext_csd.cache_size/8); + + return card->ext_csd.cache_ctrl; +} + +static int msdc_enable_emmc_cache(struct msdc_host *host, int enable) +{ + int err; + u8 c_ctrl; + struct mmc_card *card; + + err = msdc_check_emmc_cache_status(host); + + if (err < 0) + goto exit; + + card = host->mmc->card; + + mmc_get_card(card); + + c_ctrl = card->ext_csd.cache_ctrl; + + if (c_ctrl == enable) + pr_err("msdc%d:cache has already been %s state,\n", + host->id, enable ? "enable" : "disable"); + else { + err = msdc_cache_ctrl(host, enable, NULL); + if (err) + pr_err("msdc%d: Cache is supported, but %s failed\n", + host->id, enable ? "enable" : "disable"); + else + pr_err("msdc%d: %s cache successfully\n", + host->id, enable ? "enable" : "disable"); + } + mmc_put_card(card); + + return 0; +exit: + return -1; +} +#endif + +#ifdef MTK_MSDC_ERROR_TUNE_DEBUG +#define MTK_MSDC_ERROR_NONE (0) +#define MTK_MSDC_ERROR_CMD_TMO (0x1) +#define MTK_MSDC_ERROR_CMD_CRC (0x1 << 1) +#define MTK_MSDC_ERROR_DAT_TMO (0x1 << 2) +#define MTK_MSDC_ERROR_DAT_CRC (0x1 << 3) +#define MTK_MSDC_ERROR_ACMD_TMO (0x1 << 4) +#define MTK_MSDC_ERROR_ACMD_CRC (0x1 << 5) +unsigned int g_err_tune_dbg_count = 0; +unsigned int g_err_tune_dbg_host = 0; +unsigned int g_err_tune_dbg_cmd = 0; +unsigned int g_err_tune_dbg_arg = 0; +unsigned int g_err_tune_dbg_error = MTK_MSDC_ERROR_NONE; + +static void msdc_error_tune_debug_print(int p1, int p2, int p3, int p4, int p5) +{ + g_err_tune_dbg_host = p1; + g_err_tune_dbg_cmd = p2; + g_err_tune_dbg_arg = p3; + g_err_tune_dbg_error = p4; + g_err_tune_dbg_count = p5; + if (g_err_tune_dbg_count && + (g_err_tune_dbg_error != MTK_MSDC_ERROR_NONE)) { + pr_err("===================MSDC error debug start =======================\n"); + pr_err("host:%d, cmd=%d, arg=%d, error=%d, count=%d\n", + g_err_tune_dbg_host, g_err_tune_dbg_cmd, + g_err_tune_dbg_arg, g_err_tune_dbg_error, + g_err_tune_dbg_count); + } else { + g_err_tune_dbg_host = 0; + g_err_tune_dbg_cmd = 0; + g_err_tune_dbg_arg = 0; + g_err_tune_dbg_error = MTK_MSDC_ERROR_NONE; + g_err_tune_dbg_count = 0; + pr_err("host:%d, cmd=%d, arg=%d, error=%d, count=%d\n", + g_err_tune_dbg_host, g_err_tune_dbg_cmd, + g_err_tune_dbg_arg, g_err_tune_dbg_error, + g_err_tune_dbg_count); + pr_err("=====================MSDC error debug end =======================\n"); + } +} + +void msdc_error_tune_debug1(struct msdc_host *host, struct mmc_command *cmd, + struct mmc_command *sbc, u32 *intsts) +{ + u32 opcode = cmd->opcode; + + if (!g_err_tune_dbg_error || + (g_err_tune_dbg_count <= 0) || + (g_err_tune_dbg_host != host->id)) + return; + + if (g_err_tune_dbg_cmd == opcode) { + if ((opcode != MMC_SWITCH) + || ((opcode == MMC_SWITCH) && + (g_err_tune_dbg_arg == ((cmd->arg >> 16) & 0xff)))) { + if (g_err_tune_dbg_error & MTK_MSDC_ERROR_CMD_TMO) { + *intsts = MSDC_INT_CMDTMO; + g_err_tune_dbg_count--; + } else if (g_err_tune_dbg_error + & MTK_MSDC_ERROR_CMD_CRC) { + *intsts = MSDC_INT_RSPCRCERR; + g_err_tune_dbg_count--; + } + pr_err("[%s]: got the error cmd:%d, arg=%d, dbg error=%d, cmd->error=%d, count=%d\n", + __func__, g_err_tune_dbg_cmd, + g_err_tune_dbg_arg, g_err_tune_dbg_error, + cmd->error, g_err_tune_dbg_count); + } + } + +#ifdef MTK_MSDC_USE_CMD23 + if ((g_err_tune_dbg_cmd == MMC_SET_BLOCK_COUNT) && + sbc && + (host->autocmd & MSDC_AUTOCMD23)) { + if (g_err_tune_dbg_error & MTK_MSDC_ERROR_ACMD_TMO) { + *intsts = MSDC_INT_ACMDTMO; + } else if (g_err_tune_dbg_error + & MTK_MSDC_ERROR_ACMD_CRC) { + *intsts = MSDC_INT_ACMDCRCERR; + } else { + return; + } + pr_err("[%s]: got the error cmd:%d, dbg error=%d, sbc->error=%d, count=%d\n", + __func__, g_err_tune_dbg_cmd, g_err_tune_dbg_error, + sbc->error, g_err_tune_dbg_count); + } +#endif + +} + +void msdc_error_tune_debug2(struct msdc_host *host, struct mmc_command *stop, + u32 *intsts) +{ + void __iomem *base = host->base; + + if (!g_err_tune_dbg_error || + (g_err_tune_dbg_count <= 0) || + (g_err_tune_dbg_host != host->id)) + return; + + if (g_err_tune_dbg_cmd == (MSDC_READ32(SDC_CMD) & 0x3f)) { + if (g_err_tune_dbg_error & MTK_MSDC_ERROR_DAT_TMO) { + *intsts = MSDC_INT_DATTMO; + g_err_tune_dbg_count--; + } else if (g_err_tune_dbg_error & MTK_MSDC_ERROR_DAT_CRC) { + *intsts = MSDC_INT_DATCRCERR; + g_err_tune_dbg_count--; + } + pr_err("[%s]: got the error cmd:%d, dbg error 0x%x, data->error=%d, count=%d\n", + __func__, g_err_tune_dbg_cmd, g_err_tune_dbg_error, + host->data->error, g_err_tune_dbg_count); + } + if ((g_err_tune_dbg_cmd == MMC_STOP_TRANSMISSION) && + stop && + (host->autocmd & MSDC_AUTOCMD12)) { + if (g_err_tune_dbg_error & MTK_MSDC_ERROR_ACMD_TMO) { + *intsts = MSDC_INT_ACMDTMO; + g_err_tune_dbg_count--; + } else if (g_err_tune_dbg_error & MTK_MSDC_ERROR_ACMD_CRC) { + *intsts = MSDC_INT_ACMDCRCERR; + g_err_tune_dbg_count--; + } + pr_err("[%s]: got the error cmd:%d, dbg error 0x%x, stop->error=%d, host->error=%d, count=%d\n", + __func__, g_err_tune_dbg_cmd, g_err_tune_dbg_error, + stop->error, host->error, g_err_tune_dbg_count); + } +} + +void msdc_error_tune_debug3(struct msdc_host *host, struct mmc_command *cmd, + u32 *intsts) +{ + if (!g_err_tune_dbg_error || + (g_err_tune_dbg_count <= 0) || + (g_err_tune_dbg_host != host->id)) + return; + + if (g_err_tune_dbg_cmd != cmd->opcode) + return; + + if ((g_err_tune_dbg_cmd != MMC_SWITCH) + || ((g_err_tune_dbg_cmd == MMC_SWITCH) && + (g_err_tune_dbg_arg == ((cmd->arg >> 16) & 0xff)))) { + if (g_err_tune_dbg_error & MTK_MSDC_ERROR_CMD_TMO) { + *intsts = MSDC_INT_CMDTMO; + g_err_tune_dbg_count--; + } else if (g_err_tune_dbg_error & MTK_MSDC_ERROR_CMD_CRC) { + *intsts = MSDC_INT_RSPCRCERR; + g_err_tune_dbg_count--; + } + pr_err("[%s]: got the error cmd:%d, arg=%d, dbg error=%d, cmd->error=%d, count=%d\n", + __func__, g_err_tune_dbg_cmd, g_err_tune_dbg_arg, + g_err_tune_dbg_error, cmd->error, g_err_tune_dbg_count); + } +} +#endif /*ifdef MTK_MSDC_ERROR_TUNE_DEBUG*/ + +static ssize_t msdc_debug_proc_write(struct file *file, const char *buf, + size_t count, loff_t *data) +{ + int ret = 0; + int cmd, p1, p2, p3, p4, p5, p6, p7 = 0; + int id, zone, vcore; + int mode, size; + int thread_num, compare_count, multi_address; + void __iomem *base = NULL; + ulong data_for_wr; + unsigned int offset = 0; + unsigned int reg_value; + int spd_mode = MMC_TIMING_LEGACY; + struct msdc_host *host = NULL; +#ifdef MSDC_DMA_ADDR_DEBUG + struct dma_addr *dma_address, *p_dma_address; +#endif + int dma_status; + int sscanf_num; + u8 *res; + + p1 = p2 = p3 = p4 = p5 = p6 = p7 = -1; + + if (count == 0) + return -1; + if (count > 255) + count = 255; + ret = copy_from_user(cmd_buf, buf, count); + if (ret < 0) + return -1; + + cmd_buf[count] = '\0'; + pr_err("[SD_Debug]msdc Write %s\n", cmd_buf); + + sscanf_num = sscanf(cmd_buf, "%x %x %x %x %x %x %x %x", &cmd, &p1, &p2, + &p3, &p4, &p5, &p6, &p7); + if (sscanf_num < 1) + return count; + + if (cmd == SD_TOOL_ZONE) { + id = p1; + zone = p2; /* zone &= 0x3ff; */ + pr_err("[SD_Debug]msdc host_<%d> zone<0x%.8x>\n", id, zone); + if (id > HOST_MAX_NUM || id < 0) + goto invalid_host_id; + if (id == HOST_MAX_NUM) { + sd_debug_zone[0] = sd_debug_zone[1] = zone; + sd_debug_zone[2] = zone; + sd_debug_zone[3] = zone; + } else { + sd_debug_zone[id] = zone; + } + } else if (cmd == SD_TOOL_DMA_SIZE) { + id = p2; + mode = p3; + size = p4; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + if (p1 == 0) { + drv_mode[id] = mode; + dma_size[id] = size; + } else { + pr_err("-> MSDC[%d] mode<%d> size<%d>\n", + id, drv_mode[id], dma_size[id]); + } + } else if (cmd == SD_TOOL_CLK_SRC_SELECT) { + id = p2; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + if (p1 == 0) { + if (p3 >= 0 && p3 < CLK_SRC_MAX_NUM) { + msdc_clock_src[id] = p3; + pr_err("[SD_Debug]msdc%d's clk source changed to %d\n", + id, msdc_clock_src[id]); + pr_err("[SD_Debug]to enable the above settings, suspend and resume the phone again\n"); + } else { + pr_err("[SD_Debug] invalid clock src id:%d, check /proc/msdc_help\n", + p3); + } + } else if (p1 == 1) { + pr_err("[SD_Debug]msdc%d's pll source is %d\n", + id, msdc_clock_src[id]); + } + } else if (cmd == SD_TOOL_REG_ACCESS) { + id = p2; + offset = (unsigned int)p3; + + if (id >= HOST_MAX_NUM || id < 0 || mtk_msdc_host[id] == NULL) + goto invalid_host_id; + + host = mtk_msdc_host[id]; + base = host->base; + if ((offset == 0x18 || offset == 0x1C) && p1 != 4) { + pr_err("[SD_Debug]Err: Accessing TXDATA and RXDATA is forbidden\n"); + return count; + } + + (void)msdc_clk_enable(host); + + if (p1 == 0) { + reg_value = p4; + pr_err("[SD_Debug][MSDC Reg]Original:0x%p+0x%x (0x%x)\n", + base, offset, MSDC_READ32(base + offset)); + MSDC_WRITE32(base + offset, reg_value); + pr_err("[SD_Debug][MSDC Reg]Modified:0x%p+0x%x (0x%x)\n", + base, offset, MSDC_READ32(base + offset)); + } else if (p1 == 1) { + pr_err("[SD_Debug][MSDC Reg]Reg:0x%p+0x%x (0x%x)\n", + base, offset, MSDC_READ32(base + offset)); + } else if (p1 == 2) { + msdc_set_field(base + offset, p4, p5, p6); + } else if (p1 == 3) { + msdc_get_field(base + offset, p4, p5, p6); + } else if (p1 == 4) { + msdc_dump_info(host->id); + } else if (p1 == 5) { + msdc_dump_info(host->id); + } + + msdc_clk_disable(host); + } else if (cmd == SD_TOOL_SET_DRIVING) { + id = p1; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + host = mtk_msdc_host[id]; + if ((unsigned char)p2 > 7 || (unsigned char)p3 > 7 || + (unsigned char)p4 > 7 || (unsigned char)p5 > 7 || + (unsigned char)p6 > 7) { + pr_err("[SD_Debug]Some drving value was invalid(invalid:0~7)\n"); + } else { + if (id == 0) + p7 = 0; + if (p7 == 0) { + host->hw->clk_drv = (unsigned char)p2; + host->hw->cmd_drv = (unsigned char)p3; + host->hw->dat_drv = (unsigned char)p4; + host->hw->rst_drv = (unsigned char)p5; + host->hw->ds_drv = (unsigned char)p6; + msdc_set_driving(host, host->hw, 0); + } else if (p7 == 1) { + host->hw->clk_drv_sd_18 = (unsigned char)p2; + host->hw->cmd_drv_sd_18 = (unsigned char)p3; + host->hw->dat_drv_sd_18 = (unsigned char)p4; + msdc_set_driving(host, host->hw, 1); + } + pr_err("[SD_Debug]clk_drv=%d, cmd_drv=%d, dat_drv=%d, rst_drv=%d, ds_drv=%d\n", + p2, p3, p4, p5, p6); + } + } else if (cmd == SD_TOOL_ENABLE_SLEW_RATE) { + id = p1; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + host = mtk_msdc_host[id]; + if ((unsigned char)p2 > 1 || (unsigned char)p3 > 1 + || (unsigned char)p4 > 1 || (unsigned char)p5 > 1 + || (unsigned char)p6 > 1) { + pr_err("[SD_Debug]Some sr value was invalid(correct:0(disable),1(enable))\n"); + } else { + msdc_set_sr(host, p2, p3, p4, p5, p6); + pr_err("[SD_Debug]msdc%d, clk_sr=%d, cmd_sr=%d, dat_sr=%d, rst_sr=%d, ds_sr=%d\n", + id, p2, p3, p4, p5, p6); + } + } else if (cmd == SD_TOOL_SET_RDTDSEL) { + id = p1; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + host = mtk_msdc_host[id]; + if ((p2 < 0) || (p2 > 2)) { + pr_err("[SD_Debug]invalid option ( set rd:0, set td:1, get td/rd: 2)\n"); + } else if ((p2 == 0 && (unsigned char)p3 > 0x3F) + || (p2 == 1 && (unsigned char)p3 > 0xF)) { + pr_err("[SD_Debug]Some rd/td value was invalid (rd mask:(0x3F << 4),td mask:(0xF << 0))\n"); + } else { + if (p2 == 0) { + msdc_set_rdsel(host, MSDC_TDRDSEL_CUST, p3); + pr_err("[SD_Debug]msdc%d, set rd=%d\n", + id, p3); + } else if (p2 == 1) { /* set td:1 */ + msdc_set_tdsel(host, MSDC_TDRDSEL_CUST, p3); + pr_err("[SD_Debug]msdc%d, set td=%d\n", + id, p3); + } else if (p2 == 2) { /* get td/rd:2 */ + msdc_get_rdsel(host, &p3); /* get rd */ + msdc_get_tdsel(host, &p4); /* get td */ + pr_err("[SD_Debug]msdc%d, rd : 0x%x, td : 0x%x\n", + id, p3, p4); + } + } + } else if (cmd == SD_TOOL_ENABLE_SMT) { + id = p1; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + host = mtk_msdc_host[id]; + msdc_set_smt(host, p2); + pr_err("[SD_Debug]smt=%d\n", p2); + } else if (cmd == RW_BIT_BY_BIT_COMPARE) { + id = p1; + compare_count = p2; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + if (compare_count < 0) { + pr_err("[SD_Debug]: bad compare count: %d\n", + compare_count); + return count; + } + + if (id == 0) { /* for msdc0 */ +#ifdef CONFIG_MTK_EMMC_SUPPORT + multi_rw_compare(0, COMPARE_ADDRESS_MMC, + compare_count, MMC_TYPE_MMC); + /* test the address 0 of eMMC */ +#else + multi_rw_compare(0, COMPARE_ADDRESS_SD, + compare_count, MMC_TYPE_SD); + /* test a larger address of SD card */ +#endif + } else { + multi_rw_compare(id, COMPARE_ADDRESS_SD, + compare_count, MMC_TYPE_SD); + } + } else if (cmd == MSDC_READ_WRITE) { + id = p1; + mode = p2; /* 0:stop, 1:read, 2:write */ + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + if (mode > 2 || mode < 0) { + pr_err("[SD_Debug]: bad mode: %d\n", mode); + return count; + } + if (mode == read_write_state) { + pr_err("[SD_Debug]: same operation mode=%d\n", + read_write_state); + return count; + } + if (mode == 1 && read_write_state == 2) { + pr_err("[SD_Debug]: cannot read in write state, please stop first\n"); + return count; + } + if (mode == 2 && read_write_state == 1) { + pr_err("[SD_Debug]: cannot write in read state, please stop first\n"); + return count; + } + read_write_state = mode; + + pr_err("[SD_Debug]: host id: %d, mode: %d.\n", id, mode); + if ((mode == 0) && (rw_thread)) { + kthread_stop(rw_thread); + pr_err("[SD_Debug]: stop read/write thread\n"); + } else { + pr_err("[SD_Debug]: start read/write thread\n"); + data_for_wr = (id & 0x3) | ((mode & 0x3) << 4); + rw_thread = kthread_create(rwThread, + (void *)data_for_wr, "msdc_rw_thread"); + wake_up_process(rw_thread); + } + } else if (cmd == SD_TOOL_MSDC_HOST_MODE) { + int cmdq; + id = p2; + host = mtk_msdc_host[id]; + spd_mode = p3; + cmdq = p4; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + if (p1 == 0) + /*msdc_get_host_mode_speed(m, host->mmc);*/ + msdc_get_host_mode_speed(host->mmc); + else + msdc_set_host_mode_speed(host->mmc, spd_mode, cmdq); + + } else if (cmd == SD_TOOL_DMA_STATUS) { + id = p1; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + if (p2 == 0) { + static char const * const str[] = { + "No data transaction or the device is not present until now\n", + "DMA mode is disabled Now\n", + "Write from SD to DRAM in DMA mode\n", + "Write from DRAM to SD in DMA mode\n" + }; + dma_status = msdc_get_dma_status(id); + pr_err(">>>> msdc%d: dma_status=%d, ", id, dma_status); + pr_err("%s", str[dma_status+1]); + if (dma_status == -1) + goto out; +#ifdef MSDC_DMA_ADDR_DEBUG + dma_address = msdc_get_dma_address(id); + if (dma_address) { + pr_err(">>>> msdc%d:\n", id); + p_dma_address = dma_address; + while (p_dma_address) { + pr_err(">>>> addr=0x%x, size=%d\n", + p_dma_address->start_address, + p_dma_address->size); + if (p_dma_address->end) + break; + p_dma_address = p_dma_address->next; + } + } else { + pr_err(">>>> msdc%d: BD count=0\n", id); + } +#else + pr_err("please enable MSDC_DMA_ADDR_DEBUG at mt_sd.h if you want dump dma address\n"); +#endif + } else if (p2 == 1) { + pr_err(">>>> msdc%d: start dma violation test\n", id); + g_dma_debug[id] = 1; + multi_rw_compare(id, COMPARE_ADDRESS_SD, 3, + MMC_TYPE_SD); + } + } + +#ifdef MTK_MSDC_USE_CACHE + else if (cmd == MMC_EDC_EMMC_CACHE) { + pr_err("==== MSDC Cache Feature Test ====\n"); + id = p1; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + + host = mtk_msdc_host[id]; + switch (p2) { + case 0: + msdc_enable_emmc_cache(host, 0); + break; + case 1: + msdc_enable_emmc_cache(host, 1); + break; + case 2: + msdc_check_emmc_cache_status(host); + break; + default: + pr_err("ERROR:3rd parameter is wrong, please see the msdc_help\n"); + break; + } + } +#endif + else if (cmd == MMC_DUMP_GPD) { + pr_err("==== MSDC DUMP GPD/BD ====\n"); + id = p1; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + else + msdc_dump_gpd_bd(id); + } else if (cmd == SD_TOOL_SDIO_PROFILE) { + if (p1 == 1) { /* enable profile */ + if (gpt_enable == 0) { + msdc_init_gpt(); + gpt_enable = 1; + } + sdio_pro_enable = 1; + if (p2 == 0) + p2 = 1; + if (p2 >= 30) + p2 = 30; + sdio_pro_time = p2; + } else if (p1 == 0) { + /* todo */ + sdio_pro_enable = 0; + } + } else if (cmd == SMP_TEST_ON_ONE_HOST) { + id = p1; + thread_num = p2; + compare_count = p3; + multi_address = p4; + smp_test_on_hosts(thread_num, id, compare_count, multi_address); + } else if (cmd == SMP_TEST_ON_ALL_HOST) { + thread_num = p1; + compare_count = p2; + multi_address = p3; + smp_test_on_hosts(thread_num, HOST_MAX_NUM, compare_count, + multi_address); + } else if (cmd == MMC_REGISTER_READ) { + pr_err("p1 = 0x%x\n", p1); + pr_err("regiser: 0x%x = 0x%x\n", p1, MSDC_READ32((ulong) p1)); + } +#ifdef MTK_IO_PERFORMANCE_DEBUG + else if (cmd == MMC_PERF_DEBUG) { + /* 1 enable; 0 disable */ + g_mtk_mmc_perf_dbg = p1; + g_mtk_mmc_dbg_range = p2; + + if (2 == g_mtk_mmc_dbg_range) { + g_dbg_range_start = p3; + g_dbg_range_end = p3 + p4; + g_check_read_write = p5; + } + pr_err("g_mtk_mmc_perf_dbg = 0x%x, g_mtk_mmc_dbg_range = 0x%x, start = 0x%x, end = 0x%x\n", + g_mtk_mmc_perf_dbg, g_mtk_mmc_dbg_range, + g_dbg_range_start, g_dbg_range_end); + } else if (cmd == MMC_PERF_DEBUG_PRINT) { + int i, j, k, num = 0; + + if (p1 == 0) { + g_mtk_mmc_clear = 0; + return count; + } + pr_err("msdc g_dbg_req_count<%d>\n", g_dbg_req_count); + for (i = 1; i <= g_dbg_req_count; i++) { + pr_err("analysis: %s 0x%x %d block, PGh %d\n", + (g_check_read_write == 18 ? "read" : "write"), + (unsigned int)g_mmcqd_buf[i][298], + (unsigned int)g_mmcqd_buf[i][299], + (unsigned int)(g_mmcqd_buf[i][297] * 2)); + if (g_check_read_write == 18) { + for (j = 1; j <= g_mmcqd_buf[i][296] * 2; + j++) { + pr_err("page %d:\n", num+1); + for (k = 0; k < 5; k++) { + pr_err("%d %llu\n", + k, g_req_buf[num][k]); + } + num += 1; + } + } + pr_err("----------------------------------\n"); + for (j = 0; j < sizeof(g_time_mark)/sizeof(char *); + j++) { + pr_err("%d. %llu %s\n", j, g_mmcqd_buf[i][j], + g_time_mark[j]); + } + pr_err("==================================\n"); + } + if (g_check_read_write == 25) { + pr_err("msdc g_dbg_write_count<%d>\n", + g_dbg_write_count); + for (i = 1; i <= g_dbg_write_count; i++) { + pr_err("**********************************\n"); + pr_err("write count: %llu\n", + g_req_write_count[i]); + for (j = 0; j < sizeof(g_time_mark_vfs_write)/ + sizeof(char *); j++) { + pr_err("%d. %llu %s\n", j, + g_req_write_buf[i][j], + g_time_mark_vfs_write[j]); + } + } + pr_err("**********************************\n"); + } + g_mtk_mmc_clear = 0; + } +#endif + +#ifdef MTK_MMC_PERFORMANCE_TEST + else if (cmd == MMC_PERF_TEST) { + /* 1 enable; 0 disable */ + g_mtk_mmc_perf_test = p1; + } +#endif + +#ifdef MTK_MSDC_ERROR_TUNE_DEBUG + else if (cmd == MMC_ERROR_TUNE) + msdc_error_tune_debug_print(p1, p2, p3, p4, p5); +#endif + + else if (cmd == ENABLE_AXI_MODULE) { + char *enable_str = (p1 ? "enable" : "disable"); + + pr_err("==== %s AXI MODULE ====\n", enable_str); + if (p2 == 0 || p2 == 5) { + pr_err("%s %s transaction on AXI bus\n", + enable_str, "NFI"); + /* NFI_SW_RST */ + MSDC_SET_FIELD(pericfg_reg_base, (0x1 << 14), + (p1 ? 0x0 : 0x1)); + } + if (p2 == 1 || p2 == 5) { + pr_err("%s %s transaction on AXI bus\n", + enable_str, "SD"); + /* MSDC1_SW_RST */ + MSDC_SET_FIELD(pericfg_reg_base, (0x1 << 20), + (p1 ? 0x0 : 0x1)); + } + if (p2 == 2 || p2 == 5) { + pr_err("%s %s transaction on AXI bus\n", + enable_str, "USB"); + /* USB_SW_RST */ + MSDC_SET_FIELD(pericfg_reg_base, (0x1 << 28), + (p1 ? 0x0 : 0x1)); + } + if (p2 == 3 || p2 == 5) { + pr_err("%s %s transaction on AXI bus\n", + enable_str, "PERI"); + /* PERI_AXI */ + MSDC_SET_FIELD(pericfg_reg_base + 0x210, (0x3 << 8), + (p1 ? 0x3 : 0x2)); + } + if (p2 == 4 || p2 == 5) { + pr_err("%s %s transaction on AXI bus\n", + enable_str, "AUDIO"); + /* AUDIO_RST */ + MSDC_SET_FIELD(infracfg_ao_reg_base + 0x40, (0x1 << 5), + (p1 ? 0x0 : 0x1)); + } + pr_err("disable AXI modules, reg[0x10003000]=0x%x, reg[0x10003210]=0x%x, reg[0x10001040]=0x%x\n", + MSDC_READ32(pericfg_reg_base), + MSDC_READ32(pericfg_reg_base + 0x210), + MSDC_READ32(infracfg_ao_reg_base + 0x40)); + } else if (cmd == SDIO_AUTOK_RESULT) { + id = p1; + vcore = p2; + mode = p3; + host = mtk_msdc_host[id]; + base = host->base; + pr_err("[****AutoK test****]msdc host_id<%d> vcore<%d> mode<%d>\n", id, vcore, mode); + + vcore = (vcore <= 0) ? AUTOK_VCORE_LOW : AUTOK_VCORE_HIGH; + res = sdio_autok_res[vcore]; + + if (mode == 0) { + if (sdio_autok_res_apply(host, vcore) != 0) + pr_err("sdio autok result not exist!\n"); + } else if (mode == 1) { + sdio_autok_res_save(host, vcore, res); + } else if (mode == 2) { + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_IOCON, MSDC_READ32(MSDC_IOCON)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_PATCH_BIT0, MSDC_READ32(MSDC_PATCH_BIT0)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_PATCH_BIT1, MSDC_READ32(MSDC_PATCH_BIT1)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_PATCH_BIT2, MSDC_READ32(MSDC_PATCH_BIT2)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_PAD_TUNE0, MSDC_READ32(MSDC_PAD_TUNE0)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_PAD_TUNE1, MSDC_READ32(MSDC_PAD_TUNE1)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_DAT_RDDLY0, MSDC_READ32(MSDC_DAT_RDDLY0)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_DAT_RDDLY1, MSDC_READ32(MSDC_DAT_RDDLY1)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_DAT_RDDLY2, MSDC_READ32(MSDC_DAT_RDDLY2)); + pr_err("%d R[%x]=0x%.8x\n", id, OFFSET_MSDC_DAT_RDDLY3, MSDC_READ32(MSDC_DAT_RDDLY3)); + } + } else if (cmd == MMC_CMDQ_STATUS) { + pr_err("==== eMMC CMDQ Feature ====\n"); + id = p1; + if (id >= HOST_MAX_NUM || id < 0) + goto invalid_host_id; + host = mtk_msdc_host[id]; + msdc_cmdq_func(host, p2); + } else if (cmd == DO_AUTOK_OFFLINE_TUNE_TX) { + host = mtk_msdc_host[p1]; /*p1 = id */ + mmc_claim_host(host->mmc); + do_autok_offline_tune_tx = 1; + host->mmc->ops->execute_tuning(host->mmc, + MMC_SEND_TUNING_BLOCK_HS200); + do_autok_offline_tune_tx = 0; + mmc_release_host(host->mmc); + } + +out: + return count; + +invalid_host_id: + pr_err("[SD_Debug]invalid host id: %d\n", id); + return count; +} + +static int msdc_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, msdc_debug_proc_show, inode->i_private); +} + +static const struct file_operations msdc_proc_fops = { + .open = msdc_proc_open, + .write = msdc_debug_proc_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int msdc_help_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, msdc_help_proc_show, inode->i_private); +} +static const struct file_operations msdc_help_fops = { + .open = msdc_help_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +#ifdef MSDC_HQA +u32 sdio_vio18_flag, sdio_vcore1_flag, sdio_vcore2_flag; +u32 vio18_reg, vcore1_reg, vcore2_reg; + +static ssize_t msdc_voltage_proc_write(struct file *file, + const char __user *buf, size_t count, loff_t *data) +{ + int ret; + int sscanf_num; + + ret = copy_from_user(cmd_buf, buf, count); + if (ret < 0) + return -1; + + cmd_buf[count] = '\0'; + pr_err("[SD_Debug]msdc Write %s\n", cmd_buf); + + sscanf_num = sscanf(cmd_buf, "%d %d %d", &sdio_vio18_flag, + &sdio_vcore1_flag, &sdio_vcore2_flag); + + if (sscanf_num < 3) + return -1; + + if (sdio_vio18_flag >= 1730 && sdio_vio18_flag <= 1880) { + /*0.01V per step*/ + if (sdio_vio18_flag > 1800) + vio18_reg = 8-(sdio_vio18_flag-1800)/10; + else + vio18_reg = (1800-sdio_vio18_flag)/10; + pmic_config_interface(REG_VIO18_CAL, vio18_reg, + VIO18_CAL_MASK, VIO18_CAL_SHIFT); + } + + /*Vcore2 is VCORE_AO*/ + if (sdio_vcore2_flag > 900 && sdio_vcore2_flag < 1200) { + /*0.00625V per step*/ + /*Originally divied by 12.5, to avoid floating-point division, + amplify numerator and denominator by 4*/ + vcore2_reg = ((sdio_vcore2_flag-600)<<2)/25; + pmic_config_interface(REG_VCORE_VOSEL_SW, vcore2_reg, + VCORE_VOSEL_SW_MASK, VCORE_VOSEL_SW_SHIFT); + pmic_config_interface(REG_VCORE_VOSEL_HW, vcore2_reg, + VCORE_VOSEL_HW_MASK, VCORE_VOSEL_HW_SHIFT); + } + + return count; +} + +static int msdc_voltage_flag_proc_read_show(struct seq_file *m, void *data) +{ + seq_printf(m, "vio18: 0x%d 0x%X\n", sdio_vio18_flag, vio18_reg); + seq_printf(m, "vcore1: 0x%d 0x%X\n", sdio_vcore1_flag, vcore1_reg); + seq_printf(m, "vcore2: 0x%d 0x%X\n", sdio_vcore2_flag, vcore2_reg); + return 0; +} + +static int msdc_voltage_flag_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, msdc_voltage_flag_proc_read_show, + inode->i_private); +} + +static const struct file_operations msdc_voltage_flag_fops = { + .open = msdc_voltage_flag_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = msdc_voltage_proc_write, +}; +#endif + +#ifndef USER_BUILD_KERNEL +#define PROC_PERM 0660 +#else +#define PROC_PERM 0440 +#endif + +int msdc_debug_proc_init(void) +{ + struct proc_dir_entry *prEntry; + kuid_t uid; + kgid_t gid; +#ifdef MSDC_HQA + struct proc_dir_entry *voltage_flag; +#endif + uid = make_kuid(&init_user_ns, 0); + gid = make_kgid(&init_user_ns, 1001); + + prEntry = proc_create("msdc_debug", PROC_PERM, NULL, &msdc_proc_fops); + + if (prEntry) { + pr_err("[%s]: create /proc/msdc_debug\n", __func__); + proc_set_user(prEntry, uid, gid); + } else { + pr_err("[%s]: failed to create /proc/msdc_debug\n", __func__); + } + + prEntry = proc_create("msdc_help", PROC_PERM, NULL, &msdc_help_fops); + + if (prEntry) + pr_err("[%s]: create /proc/msdc_help\n", __func__); + else + pr_err("[%s]: failed to create /proc/msdc_help\n", __func__); + +#ifdef MSDC_HQA + voltage_flag = proc_create("msdc_voltage_flag", PROC_PERM, NULL, + &msdc_voltage_flag_fops); + + if (voltage_flag) { + proc_set_user(voltage_flag, uid, gid); + pr_err("[%s]: successfully create /proc/msdc_voltage_flag\n", + __func__); + } else { + pr_err("[%s]: failed to create /proc/msdc_voltage_flag\n", + __func__); + } +#endif + +#ifdef MSDC_DMA_ADDR_DEBUG + msdc_init_dma_latest_address(); +#endif + return 0; +} +EXPORT_SYMBOL_GPL(msdc_debug_proc_init); + diff --git a/drivers/mmc/host/mediatek/mt6755/dbg.h b/drivers/mmc/host/mediatek/mt6755/dbg.h new file mode 100644 index 0000000000000000000000000000000000000000..e56bd76590e0be664f201c8a5919e86006c3f9bc --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/dbg.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __MT_MSDC_DEUBG__ +#define __MT_MSDC_DEUBG__ +#include "mt_sd.h" + +#include "msdc_tune.h" + +#define MTK_MSDC_ERROR_TUNE_DEBUG + +/* Debug message event */ +#define DBG_EVT_NONE (0) /* No event */ +#define DBG_EVT_DMA (1 << 0) /* DMA related event */ +#define DBG_EVT_CMD (1 << 1) /* MSDC CMD related event */ +#define DBG_EVT_RSP (1 << 2) /* MSDC CMD RSP related event */ +#define DBG_EVT_INT (1 << 3) /* MSDC INT event */ +#define DBG_EVT_CFG (1 << 4) /* MSDC CFG event */ +#define DBG_EVT_FUC (1 << 5) /* Function event */ +#define DBG_EVT_OPS (1 << 6) /* Read/Write operation event */ +#define DBG_EVT_FIO (1 << 7) /* FIFO operation event */ +#define DBG_EVT_WRN (1 << 8) /* Warning event */ +#define DBG_EVT_PWR (1 << 9) /* Power event */ +#define DBG_EVT_CLK (1 << 10) /* Trace clock gate/ungate operation */ +#define DBG_EVT_CHE (1 << 11) /* eMMC cache feature operation */ +/* ==================================================== */ +#define DBG_EVT_RW (1 << 12) /* Trace the Read/Write Command */ +#define DBG_EVT_NRW (1 << 13) /* Trace other Command */ +#define DBG_EVT_ALL (0xffffffff) + +#define DBG_EVT_MASK (DBG_EVT_ALL) + +#define TAG "msdc" +#define N_MSG(evt, fmt, args...) \ +do { \ + if ((DBG_EVT_##evt) & sd_debug_zone[host->id]) { \ + pr_err(TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ + host->id, ##args , __func__, __LINE__, \ + current->comm, current->pid); \ + } \ +} while (0) + +#if 1 +#define ERR_MSG(fmt, args...) \ + pr_err(TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ + host->id, ##args , __func__, __LINE__, current->comm, \ + current->pid) + +#else +#define MAX_PRINT_PERIOD (500000000) /* 500ms */ +#define MAX_PRINT_NUMS_OVER_PERIOD (50) +#define ERR_MSG(fmt, args...) \ +do { \ + if (print_nums == 0) { \ + print_nums++; \ + msdc_print_start_time = sched_clock(); \ + pr_err(TAG"MSDC", TAG"%d -> "fmt" <- %s() : L<%d> " \ + "PID<%s><0x%x>\n", \ + host->id, ##args , __func__, __LINE__, \ + current->comm, current->pid); \ + } else { \ + msdc_print_end_time = sched_clock(); \ + if ((msdc_print_end_time - msdc_print_start_time) >= \ + MAX_PRINT_PERIOD) { \ + pr_err(TAG"MSDC", TAG"%d -> "fmt" <- %s() : L<%d> " \ + "PID<%s><0x%x>\n", \ + host->id, ##args , __func__, __LINE__, \ + current->comm, current->pid); \ + print_nums = 0; \ + } \ + if (print_nums <= MAX_PRINT_NUMS_OVER_PERIOD) { \ + pr_err(TAG"MSDC", TAG"%d -> "fmt" <- %s() : " \ + "L<%d> PID<%s><0x%x>\n", \ + host->id, ##args , __func__, \ + __LINE__, current->comm, current->pid); \ + print_nums++; \ + } \ + } \ +} while (0) +#endif + +#define INIT_MSG(fmt, args...) \ + pr_err(TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ + host->id, ##args , __func__, __LINE__, current->comm, \ + current->pid) + +#define SIMPLE_INIT_MSG(fmt, args...) \ + pr_err("%d:"fmt"\n", id, ##args) + +#define INFO_MSG(fmt, args...) \ + pr_debug(TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ + host->id, ##args , __func__, __LINE__, current->comm, \ + current->pid) + +#if 0 +/* PID in ISR in not corrent */ +#define IRQ_MSG(fmt, args...) \ + pr_err(TAG"%d -> "fmt" <- %s() : L<%d>\n", \ + host->id, ##args , __func__, __LINE__) +#else +#define IRQ_MSG(fmt, args...) +#endif + +void msdc_dump_gpd_bd(int id); +int msdc_debug_proc_init(void); +void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks); +void msdc_set_host_mode_speed(struct mmc_host *mmc, int spd_mode, int cmdq); +u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32); + +void msdc_error_tune_debug1(struct msdc_host *host, struct mmc_command *cmd, + struct mmc_command *sbc, u32 *intsts); +void msdc_error_tune_debug2(struct msdc_host *host, struct mmc_command *stop, + u32 *intsts); +void msdc_error_tune_debug3(struct msdc_host *host, struct mmc_command *cmd, + u32 *intsts); +int multi_rw_compare(int host_num, uint address, int count, uint type); +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT +void dbg_add_host_log(struct mmc_host *mmc, int type, int cmd, int arg); +void mmc_cmd_dump(struct mmc_host *mmc); +#endif +void msdc_cmdq_status_print(struct msdc_host *host); +#endif diff --git a/drivers/mmc/host/mediatek/mt6755/emmc_otp.c b/drivers/mmc/host/mediatek/mt6755/emmc_otp.c new file mode 100644 index 0000000000000000000000000000000000000000..d1b67a8bde40de28dbf584eacc0f379e6705ddd0 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/emmc_otp.c @@ -0,0 +1,856 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_COMPAT +#include +#endif + +#include "mt_sd.h" +#include "dbg.h" + +#define OTP_MAGIC_NUM 0x4E3AF28B + +struct emmc_otp_config { + u32 (*read)(u32 blkno, void *BufferPtr); + u32 (*write)(u32 blkno, void *BufferPtr); + u32 (*query_length)(u32 *Length); +}; + +struct otp_ctl { + unsigned int QLength; + unsigned int Offset; + unsigned int Length; + char *BufferPtr; + unsigned int status; +}; + +#ifdef CONFIG_COMPAT +struct compat_otp_ctl { + compat_uint_t QLength; + compat_uint_t Offset; + compat_uint_t Length; + compat_uptr_t BufferPtr; + unsigned int status; +}; +#endif + +#define EMMC_OTP_START_ADDRESS (0xc0000000) /* just for debug */ + +#define EMMC_HOST_NUM 0 +#define EMMC_OTP_MAGIC 'k' + +/* EMMC OTP IO control number */ +#define EMMC_OTP_GET_LENGTH _IOW(EMMC_OTP_MAGIC, 1, int) +#define EMMC_OTP_READ _IOW(EMMC_OTP_MAGIC, 2, int) +#define EMMC_OTP_WRITE _IOW(EMMC_OTP_MAGIC, 3, int) + +#ifdef CONFIG_COMPAT +#define COMPAT_EMMC_OTP_GET_LENGTH _IOW(EMMC_OTP_MAGIC, 1, compat_int_t) +#define COMPAT_EMMC_OTP_READ _IOW(EMMC_OTP_MAGIC, 2, compat_int_t) +#define COMPAT_EMMC_OTP_WRITE _IOW(EMMC_OTP_MAGIC, 3, compat_int_t) +#endif + +#define FS_EMMC_OTP_READ 0 +#define FS_EMMC_OTP_WRITE 1 + +/* EMMC OTP Error codes */ +#define OTP_SUCCESS 0 +#define OTP_ERROR_OVERSCOPE -1 +#define OTP_ERROR_TIMEOUT -2 +#define OTP_ERROR_BUSY -3 +#define OTP_ERROR_NOMEM -4 +#define OTP_ERROR_RESET -5 + +#include +#define DRV_NAME_MISC "otp" +#define PROCNAME "driver/otp" + +#define EMMC_OTP_DEBUG 1 + +/* static spinlock_t g_emmc_otp_lock; */ +static struct emmc_otp_config g_emmc_otp_func; +static unsigned int sg_wp_size; /* byte unit */ +static unsigned int g_otp_user_ccci = 2 * 1024 * 1024; + +struct msdc_host *emmc_otp_get_host(void) +{ + return mtk_msdc_host[EMMC_HOST_NUM]; +} + + +/****************************************************************************** + * EMMC OTP operations + * ***************************************************************************/ +unsigned int emmc_get_wp_size(void) +{ + unsigned char l_ext_csd[512]; + struct msdc_host *host_ctl; + u32 *csd = NULL; + u32 write_prot_grpsz = 0; + + if (0 == sg_wp_size) { + /* not to change ERASE_GRP_DEF after card initialized */ + host_ctl = emmc_otp_get_host(); + + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + + pr_debug("[%s:%d]mmc_host is : 0x%p\n", + __func__, __LINE__, host_ctl->mmc); + /* pr_debug("[%s:%d]claim host done! claim_status = %d, " + "claim_cnt = %d, claimer = 0x%x, current = 0x%x\n", + __func__, __LINE__, host_ctl->mmc->claimed, + host_ctl->mmc->claim_cnt, host_ctl->mmc->claimer, + current); */ + + mmc_claim_host(host_ctl->mmc); + + /* pr_debug("[%s:%d]claim host done! claim_status = %d, " + "claim_cnt = %d, claimer = 0x%x, current = 0x%x\n", + __func__, __LINE__, host_ctl->mmc->claimed, + host_ctl->mmc->claim_cnt, host_ctl->mmc->claimer, + current); */ + + /* + * As the ext_csd is large and mostly unused, raw ext_csd is + * not stored in mmc_card, so get it again. + */ + mmc_send_ext_csd(host_ctl->mmc->card, l_ext_csd); + +#if EMMC_OTP_DEBUG + { + int i; + + for (i = 0; i < 512; i++) { + pr_debug("%x", l_ext_csd[i]); + if (0 == ((i + 1) % 16)) + pr_debug("\n"); + } + } +#endif + + mmc_release_host(host_ctl->mmc); + + csd = host_ctl->mmc->card->raw_csd; + write_prot_grpsz = UNSTUFF_BITS(csd, 32, 5); + pr_err("otp: write_prot_grpsz is %d\n", write_prot_grpsz); + /* otp length equal to one write protect group size */ + if (l_ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x1) { + /* use high-capacity erase uint size, hc erase timeout, + hc wp size, store in EXT_CSD */ + sg_wp_size = (512 * 1024 * + l_ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * + l_ext_csd[EXT_CSD_HC_WP_GRP_SIZE]); + pr_err("otp: hc unit sg_wp_size %d\n", sg_wp_size); + } else { + /* use old erase group size and + write protect group size, store in CSD */ + sg_wp_size = (512 * host_ctl->mmc->card->erase_size) * + (write_prot_grpsz + 1); + pr_err("otp: non-hc unit sg_wp_size %d\n", sg_wp_size); + } + } + + return sg_wp_size; +} + +/* need subtract emmc reserved region for combo feature */ +unsigned int emmc_otp_start(void) +{ + unsigned int l_addr; + struct msdc_host *host_ctl; + struct hd_struct *lp_hd_struct = NULL; + + if (0 == sg_wp_size) + emmc_get_wp_size(); + + host_ctl = emmc_otp_get_host(); + + BUG_ON(!host_ctl); + BUG_ON(!host_ctl->mmc); + BUG_ON(!host_ctl->mmc->card); + + lp_hd_struct = get_part("otp"); + if (NULL == lp_hd_struct) { + pr_debug("not find otp in scatter file error!\n"); + put_part(lp_hd_struct); + return -EFAULT; + } + + l_addr = lp_hd_struct->start_sect; /* block unit */ + + /* find wp group start address in 43MB reserved region */ + if (l_addr % (sg_wp_size >> 9)) + l_addr += ((sg_wp_size >> 9) - l_addr % (sg_wp_size >> 9)); + + if (NULL != lp_hd_struct) + put_part(lp_hd_struct); + + pr_debug("find OTP start address is 0x%x\n", l_addr); + + return l_addr; +} + +unsigned int emmc_otp_query_length(unsigned int *QLength) +{ + /* otp length equal to one write protect group size */ + *QLength = emmc_get_wp_size() - g_otp_user_ccci; + + return 0; +} + +unsigned int emmc_otp_read(unsigned int blk_offset, void *BufferPtr) +{ + unsigned char *l_rcv_buf = (unsigned char *)BufferPtr; + unsigned int l_addr; + unsigned int l_otp_size; + unsigned int l_ret; + struct scatterlist msdc_sg; + struct mmc_data msdc_data; + struct mmc_command msdc_cmd; + struct mmc_request msdc_mrq; + struct msdc_host *host_ctl; +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + int is_cmdq_en; + int ret; +#endif + + /* check parameter */ + l_addr = emmc_otp_start(); + l_otp_size = emmc_get_wp_size(); + if (blk_offset > (l_otp_size >> 9)) + return OTP_ERROR_OVERSCOPE; + + l_addr += blk_offset; + + host_ctl = emmc_otp_get_host(); + + BUG_ON(!host_ctl); + BUG_ON(!host_ctl->mmc); + + pr_debug("[%s:%d]mmc_host is : 0x%p\n", __func__, __LINE__, + host_ctl->mmc); + mmc_claim_host(host_ctl->mmc); + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + is_cmdq_en = false; + if (host_ctl->mmc->card->ext_csd.cmdq_mode_en) { + /* cmdq enabled, turn it off first */ + pr_debug("EMMC_OTP: cmdq enabled, turn it off\n"); + is_cmdq_en = true; + ret = mmc_blk_cmdq_switch(host_ctl->mmc->card, 0); + if (ret) { + pr_debug("EMMC_OTP turn off cmdq en failed\n"); + mmc_release_host(host_ctl->mmc); + return ret; + } + } +#endif + /* make sure access user data area */ + msdc_switch_part(host_ctl, 0); + +#if EMMC_OTP_DEBUG + pr_debug("EMMC_OTP: start MSDC_SINGLE_READ_WRITE!\n"); +#endif + + memset(&msdc_data, 0, sizeof(struct mmc_data)); + memset(&msdc_mrq, 0, sizeof(struct mmc_request)); + memset(&msdc_cmd, 0, sizeof(struct mmc_command)); + + msdc_mrq.cmd = &msdc_cmd; + msdc_mrq.data = &msdc_data; + + msdc_data.flags = MMC_DATA_READ; + msdc_cmd.opcode = MMC_READ_SINGLE_BLOCK; + msdc_data.blocks = 1; /* one block Request */ + + memset(l_rcv_buf, 0, 512); + + msdc_cmd.arg = l_addr; + + BUG_ON(!host_ctl->mmc->card); + if (!mmc_card_blockaddr(host_ctl->mmc->card)) { + pr_debug("the device is used byte address!\n"); + msdc_cmd.arg <<= 9; + } + + msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + + msdc_data.stop = NULL; + msdc_data.blksz = 512; + msdc_data.sg = &msdc_sg; + msdc_data.sg_len = 1; + + sg_init_one(&msdc_sg, l_rcv_buf, 512); + mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card); + + mmc_wait_for_req(host_ctl->mmc, &msdc_mrq); + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (is_cmdq_en) { + pr_debug("EMMC_OTP turn on cmdq\n"); + ret = mmc_blk_cmdq_switch(host_ctl->mmc->card, 1); + if (ret) { + pr_debug("EMMC_OTP turn on cmdq en failed\n"); + mmc_release_host(host_ctl->mmc); + return ret; + } + } +#endif + mmc_release_host(host_ctl->mmc); + + if (msdc_cmd.error) + l_ret = msdc_cmd.error; + + if (msdc_data.error) + l_ret = msdc_data.error; + else + l_ret = OTP_SUCCESS; + + return l_ret; +} + +unsigned int emmc_otp_write(unsigned int blk_offset, void *BufferPtr) +{ + unsigned char *l_send_buf = (unsigned char *)BufferPtr; + unsigned int l_ret; + unsigned int l_addr; + unsigned int l_otp_size; + struct scatterlist msdc_sg; + struct mmc_data msdc_data; + struct mmc_command msdc_cmd; + struct mmc_request msdc_mrq; + struct msdc_host *host_ctl; +#ifdef MTK_MSDC_USE_CACHE + struct mmc_command msdc_sbc; +#endif +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + int is_cmdq_en; + int ret; +#endif + + /* check parameter */ + l_addr = emmc_otp_start(); + l_otp_size = emmc_get_wp_size(); + if (blk_offset > (l_otp_size >> 9)) + return OTP_ERROR_OVERSCOPE; + + l_addr += blk_offset; + + host_ctl = emmc_otp_get_host(); + + BUG_ON(!host_ctl); + BUG_ON(!host_ctl->mmc); + + mmc_claim_host(host_ctl->mmc); + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + is_cmdq_en = false; + if (host_ctl->mmc->card->ext_csd.cmdq_mode_en) { + /* cmdq enabled, turn it off first */ + pr_debug("EMMC_OTP: cmdq enabled, turn it off\n"); + is_cmdq_en = true; + ret = mmc_blk_cmdq_switch(host_ctl->mmc->card, 0); + if (ret) { + pr_debug("EMMC_OTP: turn off cmdq en failed\n"); + mmc_release_host(host_ctl->mmc); + return ret; + } + } +#endif + /* make sure access user data area */ + msdc_switch_part(host_ctl, 0); + +#if EMMC_OTP_DEBUG + pr_debug("EMMC_OTP: start MSDC_SINGLE_READ_WRITE!\n"); +#endif + + memset(&msdc_data, 0, sizeof(struct mmc_data)); + memset(&msdc_mrq, 0, sizeof(struct mmc_request)); + memset(&msdc_cmd, 0, sizeof(struct mmc_command)); +#ifdef MTK_MSDC_USE_CACHE + memset(&msdc_sbc, 0, sizeof(struct mmc_command)); +#endif + + msdc_mrq.cmd = &msdc_cmd; + msdc_mrq.data = &msdc_data; + + msdc_data.flags = MMC_DATA_WRITE; +#ifdef MTK_MSDC_USE_CACHE + if (mmc_card_mmc(host_ctl->mmc->card) + && (host_ctl->mmc->card->ext_csd.cache_ctrl & 0x1)) { + msdc_cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; + msdc_mrq.sbc = &msdc_sbc; + msdc_mrq.sbc->opcode = MMC_SET_BLOCK_COUNT; + msdc_mrq.sbc->arg = msdc_data.blocks | (1 << 31); + msdc_mrq.sbc->flags = MMC_RSP_R1 | MMC_CMD_AC; + } else { + msdc_cmd.opcode = MMC_WRITE_BLOCK; + } +#else + msdc_cmd.opcode = MMC_WRITE_BLOCK; +#endif + msdc_data.blocks = 1; + + msdc_cmd.arg = l_addr; + + BUG_ON(!host_ctl->mmc->card); + if (!mmc_card_blockaddr(host_ctl->mmc->card)) { + pr_debug("the device is used byte address!\n"); + msdc_cmd.arg <<= 9; + } + + msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + + msdc_data.stop = NULL; + msdc_data.blksz = 512; + msdc_data.sg = &msdc_sg; + msdc_data.sg_len = 1; + + sg_init_one(&msdc_sg, l_send_buf, 512); + mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card); + + mmc_wait_for_req(host_ctl->mmc, &msdc_mrq); + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (is_cmdq_en) { + pr_debug("EMMC_OTP turn on cmdq\n"); + ret = mmc_blk_cmdq_switch(host_ctl->mmc->card, 1); + if (ret) { + pr_debug("EMMC_OTP turn on cmdq en failed\n"); + mmc_release_host(host_ctl->mmc); + return ret; + } + } +#endif + mmc_release_host(host_ctl->mmc); + + if (msdc_cmd.error) + l_ret = msdc_cmd.error; + + if (msdc_data.error) + l_ret = msdc_data.error; + else + l_ret = OTP_SUCCESS; + + return l_ret; +} + +static int mt_otp_open(struct inode *inode, struct file *filp) +{ + pr_debug("[%s]:(MAJOR)%d:(MINOR)%d\n", + __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev)); + filp->private_data = (int *)OTP_MAGIC_NUM; + return 0; +} + +static int mt_otp_release(struct inode *inode, struct file *filp) +{ + pr_debug("[%s]:(MAJOR)%d:(MINOR)%d\n", + __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev)); + return 0; +} + +static int mt_otp_access(unsigned int access_type, unsigned int offset, + void *buff_ptr, unsigned int length, unsigned int *status) +{ + unsigned int ret = 0; + char *BufAddr = (char *)buff_ptr; + unsigned int blkno, AccessLength = 0; + unsigned int l_block_size = 512; + int Status = 0; + + char *p_D_Buff; + /* char S_Buff[64]; */ + + p_D_Buff = kmalloc(l_block_size, GFP_KERNEL); + if (!p_D_Buff) { + ret = -ENOMEM; + *status = OTP_ERROR_NOMEM; + goto exit; + } + + pr_debug("[%s]: %s (0x%x) length:(%d bytes) !\n", + __func__, access_type ? "WRITE" : "READ", offset, length); + + do { + blkno = offset / l_block_size; + if (FS_EMMC_OTP_READ == access_type) { + memset(p_D_Buff, 0xff, l_block_size); + + pr_debug("[%s]: Read Access of page (%d)\n", __func__, + blkno); + + Status = g_emmc_otp_func.read(blkno, p_D_Buff); + *status = Status; + + if (OTP_SUCCESS != Status) { + pr_debug("[%s]: Read status (%d)\n", __func__, + Status); + break; + } + + AccessLength = l_block_size - (offset % l_block_size); + + if (length >= AccessLength) { + memcpy(BufAddr, + (p_D_Buff + (offset % l_block_size)), + AccessLength); + } else { + /* last time */ + memcpy(BufAddr, + (p_D_Buff + (offset % l_block_size)), + length); + } + } else if (FS_EMMC_OTP_WRITE == access_type) { + AccessLength = l_block_size - (offset % l_block_size); + memset(p_D_Buff, 0x0, l_block_size); + + Status = g_emmc_otp_func.read(blkno, p_D_Buff); + *status = Status; + + if (OTP_SUCCESS != Status) { + pr_debug("[%s]: read before write, Read status (%d) blkno (0x%x)\n", + __func__, Status, blkno); + break; + } + + if (length >= AccessLength) { + memcpy((p_D_Buff + (offset % l_block_size)), + BufAddr, AccessLength); + } else { + /* last time */ + memcpy((p_D_Buff + (offset % l_block_size)), + BufAddr, length); + } + + Status = g_emmc_otp_func.write(blkno, p_D_Buff); + *status = Status; + + if (OTP_SUCCESS != Status) { + pr_debug("[%s]: Write status (%d)\n", __func__, + Status); + break; + } + } else { + pr_err("[%s]: Error, neither read nor write operations!\n", + __func__); + break; + } + + offset += AccessLength; + BufAddr += AccessLength; + if (length <= AccessLength) { + length = 0; + break; + } + length -= AccessLength; + pr_debug("[%s]: Remaining %s (%d) !\n", + __func__, access_type ? "WRITE" : "READ", length); + + } while (1); + + + kfree(p_D_Buff); + exit: + return ret; +} + +static long mt_otp_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = 0; + char *pbuf; + + void __user *uarg = (void __user *)arg; + struct otp_ctl otpctl; + + /* Lock */ + /* spin_lock(&g_emmc_otp_lock); */ + + if (copy_from_user(&otpctl, uarg, sizeof(struct otp_ctl))) { + ret = -EFAULT; + goto exit; + } + + /* + if(false == g_bInitDone) + { + pr_err("ERROR: EMMC Flash Not initialized !!\n"); + ret = -EFAULT; + goto exit; + } */ + + pbuf = kmalloc_array(otpctl.Length, sizeof(char), GFP_KERNEL); + if (!pbuf) { + ret = -ENOMEM; + goto exit; + } + + switch (cmd) { + case EMMC_OTP_GET_LENGTH: + pr_debug("OTP IOCTL: EMMC_OTP_GET_LENGTH\n"); + if (('c' == (otpctl.status & 0xff)) + && ('c' == ((otpctl.status >> 8) & 0xff)) + && ('c' == ((otpctl.status >> 16) & 0xff)) + && ('i' == ((otpctl.status >> 24) & 0xff))) { + otpctl.QLength = g_otp_user_ccci; + } else { + g_emmc_otp_func.query_length(&otpctl.QLength); + } + otpctl.status = OTP_SUCCESS; + pr_debug("OTP IOCTL: The Length is %d\n", otpctl.QLength); + break; + case EMMC_OTP_READ: + pr_debug("OTP IOCTL: EMMC_OTP_READ Offset(0x%x), Length(0x%x)\n", + otpctl.Offset, otpctl.Length); + memset(pbuf, 0xff, sizeof(char) * otpctl.Length); + + mt_otp_access(FS_EMMC_OTP_READ, otpctl.Offset, pbuf, + otpctl.Length, &otpctl.status); + + if (copy_to_user(otpctl.BufferPtr, pbuf, + (sizeof(char) * otpctl.Length))) { + pr_err("EMMC_OTP IOCTL: Copy to user buffer Error!\n"); + goto error; + } + break; + case EMMC_OTP_WRITE: + pr_debug("OTP IOCTL: EMMC_OTP_WRITE Offset(0x%x), Length(0x%x)\n", + otpctl.Offset, otpctl.Length); + if (copy_from_user(pbuf, otpctl.BufferPtr, + (sizeof(char) * otpctl.Length))) { + pr_err("EMMC_OTP IOCTL: Copy from user buffer Error!\n"); + goto error; + } + mt_otp_access(FS_EMMC_OTP_WRITE, otpctl.Offset, pbuf, + otpctl.Length, &otpctl.status); + break; + default: + ret = -EINVAL; + } + + ret = copy_to_user(uarg, &otpctl, sizeof(struct otp_ctl)); + + error: + kfree(pbuf); + exit: + /* spin_unlock(&g_emmc_otp_lock); */ + return ret; +} + +#ifdef CONFIG_COMPAT +static int compat_get_otp_ctl_allocation(struct compat_otp_ctl __user *arg32, + struct otp_ctl __user *arg64) +{ + compat_uint_t u; + compat_uptr_t p; + int err; + + err = get_user(u, &(arg32->QLength)); + err |= put_user(u, &(arg64->QLength)); + err |= get_user(u, &(arg32->Offset)); + err |= put_user(u, &(arg64->Offset)); + err |= get_user(u, &(arg32->Length)); + err |= put_user(u, &(arg64->Length)); + err |= get_user(p, &(arg32->BufferPtr)); + err |= put_user(compat_ptr(p), &(arg64->BufferPtr)); + err |= get_user(u, &(arg32->status)); + err |= put_user(u, &(arg64->status)); + + return err; +} + +static int compat_put_otp_ctl_allocation(struct compat_otp_ctl __user *arg32, + struct otp_ctl __user *arg64) +{ + compat_uint_t u; + int err; + + err = get_user(u, &(arg64->QLength)); + err |= put_user(u, &(arg32->QLength)); + err |= get_user(u, &(arg64->Offset)); + err |= put_user(u, &(arg32->Offset)); + err |= get_user(u, &(arg64->Length)); + err |= put_user(u, &(arg32->Length)); + err |= get_user(u, &(arg64->status)); + err |= put_user(u, &(arg32->status)); + + return err; +} + +static long mt_otp_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = 0; + int err = 0; + struct compat_otp_ctl *arg32; + struct otp_ctl *arg64; + + /*void __user *uarg = compat_ptr(arg);*/ + + if (!file->f_op || !file->f_op->unlocked_ioctl) + return -ENOTTY; + + arg32 = compat_ptr(arg); + arg64 = compat_alloc_user_space(sizeof(*arg64)); + if (arg64 == NULL) + return -EFAULT; + + ret = compat_get_otp_ctl_allocation(arg32, arg64); + if (ret) + return ret; + /* Lock */ + /* spin_lock(&g_emmc_otp_lock); */ + + switch (cmd) { + case COMPAT_EMMC_OTP_GET_LENGTH: + ret = mt_otp_ioctl(file, EMMC_OTP_GET_LENGTH, + (unsigned long)arg64); + /*pr_err("OTP IOCTL: COMPAT_EMMC_OTP_GET_LENGTH\n");*/ + if (ret) + pr_err("EMMC_OTP_GET_LENGTH unlocked_ioctl failed."); + + break; + case COMPAT_EMMC_OTP_READ: + /*pr_err("OTP IOCTL: COMPAT_EMMC_OTP_READ\n");*/ + ret = mt_otp_ioctl(file, EMMC_OTP_READ, (unsigned long)arg64); + + if (ret) + pr_err("EMMC_OTP_READ unlocked_ioctl failed."); + + break; + case COMPAT_EMMC_OTP_WRITE: + /*pr_err("OTP IOCTL: COMPAT_EMMC_OTP_WRITE\n");*/ + ret = mt_otp_ioctl(file, EMMC_OTP_WRITE, (unsigned long)arg64); + + if (ret) + pr_err("EMMC_OTP_WRITE unlocked_ioctl failed."); + + break; + default: + ret = -EINVAL; + } + err = compat_put_otp_ctl_allocation(arg32, arg64); + return ret ? ret : err; +} +#endif + +static const struct file_operations emmc_otp_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = mt_otp_ioctl, + .open = mt_otp_open, + .release = mt_otp_release, +#ifdef CONFIG_COMPAT + .compat_ioctl = mt_otp_ioctl_compat, +#endif +}; + +static struct miscdevice emmc_otp_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "otp", + .fops = &emmc_otp_fops, +}; + + +static int emmc_otp_probe(struct platform_device *pdev) +{ + pr_debug("in emmc otp probe function\n"); + + return 0; +} + +static int emmc_otp_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver emmc_otp_driver = { + .probe = emmc_otp_probe, + .remove = emmc_otp_remove, + + .driver = { + .name = DRV_NAME_MISC, + .owner = THIS_MODULE, + }, +}; + +static int __init emmc_otp_init(void) +{ + int err = 0; + + pr_debug("MediaTek EMMC OTP misc driver init\n"); + + /*spin_lock_init(&g_emmc_otp_lock);*/ + + g_emmc_otp_func.query_length = emmc_otp_query_length; + g_emmc_otp_func.read = emmc_otp_read; + g_emmc_otp_func.write = emmc_otp_write; +#if 0 +#ifndef USER_BUILD_KERNEL + entry = create_proc_entry(PROCNAME, 0660, NULL); +#else + entry = create_proc_entry(PROCNAME, 0440, NULL); +#endif + + if (entry == NULL) { + pr_err("emmc OTP: unable to create /proc entry\n"); + return -ENOMEM; + } + + entry->read_proc = emmc_otp_proc_read; + entry->write_proc = emmc_otp_proc_write; + /* entry->owner = THIS_MODULE; */ +#endif + platform_driver_register(&emmc_otp_driver); + + pr_debug("OTP: register EMMC OTP device ...\n"); + err = misc_register(&emmc_otp_dev); + if (unlikely(err)) { + pr_err("OTP: failed to register EMMC OTP device!\n"); + return err; + } + + return 0; +} + +static void __exit emmc_otp_exit(void) +{ + pr_debug("MediaTek EMMC OTP misc driver exit\n"); + + misc_deregister(&emmc_otp_dev); + + g_emmc_otp_func.query_length = NULL; + g_emmc_otp_func.read = NULL; + g_emmc_otp_func.write = NULL; + + platform_driver_unregister(&emmc_otp_driver); + remove_proc_entry(PROCNAME, NULL); +} + + +module_init(emmc_otp_init); +module_exit(emmc_otp_exit); diff --git a/drivers/mmc/host/mediatek/mt6755/msdc_fpga_io.c b/drivers/mmc/host/mediatek/mt6755/msdc_fpga_io.c new file mode 100644 index 0000000000000000000000000000000000000000..4eae4a748ba8045ccadee188e46f42c6e3e54562 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/msdc_fpga_io.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +#include "mt_sd.h" + +#include +#include +#include +#include +#include + +void __iomem *fpga_pwr_gpio; +void __iomem *fpga_pwr_gpio_eo; + +#define FPGA_PWR_GPIO (0xF0001E84) +#define FPGA_PWR_GPIO_EO (0xF0001E88) +#define PWR_GPIO (fpga_pwr_gpio) +#define PWR_GPIO_EO (fpga_pwr_gpio_eo) +#define PWR_GPIO_L4_DIR (1 << 11) +#define PWR_MASK_VOL_33 (1 << 10) +#define PWR_MASK_VOL_18 (1 << 9) +#define PWR_MASK_CARD (1 << 8) +#define PWR_MASK_VOL_33_MASK (~(1 << 10)) +#define PWR_MASK_CARD_MASK (~(1 << 8)) +#define PWR_MASK_VOL_18_MASK (~(1 << 9)) + +void msdc_set_pwr_gpio_dir(void __iomem *fpga_pwr_gpio, + void __iomem *fpga_pwr_gpio_eo) +{ + volatile u16 l_val; + + l_val = MSDC_READ16(PWR_GPIO_EO); + MSDC_WRITE16(PWR_GPIO_EO, + (l_val | /* PWR_GPIO_L4_DIR | */ + PWR_MASK_CARD | PWR_MASK_VOL_33 | PWR_MASK_VOL_18)); + + l_val = MSDC_READ16(PWR_GPIO_EO); + + pr_debug("[%s]: pwr gpio dir = 0x%x\n", __func__, l_val); +} + +void msdc_fpga_pwr_init(void) +{ + if (fpga_pwr_gpio == NULL) { + fpga_pwr_gpio = ioremap(FPGA_PWR_GPIO, 8); + fpga_pwr_gpio_eo = fpga_pwr_gpio + 0x4; + pr_err("FPAG PWR_GPIO, PWR_GPIO_EO address 0x%p, 0x%p\n", + fpga_pwr_gpio, fpga_pwr_gpio_eo); + } + + msdc_set_pwr_gpio_dir(fpga_pwr_gpio, fpga_pwr_gpio_eo); +} + +bool hwPowerOn_fpga(void) +{ + volatile u16 l_val; + + l_val = MSDC_READ16(PWR_GPIO); + l_val &= ~PWR_GPIO_L4_DIR; +#ifdef CONFIG_MTK_EMMC_SUPPORT + MSDC_WRITE16(PWR_GPIO, (l_val | PWR_MASK_VOL_18 | PWR_MASK_CARD)); + /* | PWR_GPIO_L4_DIR)); */ +#else + MSDC_WRITE16(PWR_GPIO, (l_val | PWR_MASK_VOL_33 | PWR_MASK_CARD)); + /* | PWR_GPIO_L4_DIR)); */ +#endif + l_val = MSDC_READ16(PWR_GPIO); + pr_debug("[%s]: pwr gpio = 0x%x\n", __func__, l_val); + return true; +} +EXPORT_SYMBOL(hwPowerOn_fpga); + +bool hwPowerSwitch_fpga(void) +{ + volatile u16 l_val; + + l_val = MSDC_READ16(PWR_GPIO); + MSDC_WRITE16(PWR_GPIO, (l_val & ~(PWR_MASK_VOL_33))); + l_val = MSDC_READ16(PWR_GPIO); + MSDC_WRITE16(PWR_GPIO, (l_val | PWR_MASK_VOL_18)); + + l_val = MSDC_READ16(PWR_GPIO); + pr_debug("[%s]: pwr gpio = 0x%x\n", __func__, l_val); + return true; +} +EXPORT_SYMBOL(hwPowerSwitch_fpga); + +bool hwPowerDown_fpga(void) +{ + volatile u16 l_val; + + l_val = MSDC_READ16(PWR_GPIO); +#ifdef MTK_EMMC_SUPPORT + MSDC_WRITE16(PWR_GPIO, + (l_val & ~(PWR_MASK_VOL_18 | PWR_MASK_CARD))); +#else + MSDC_WRITE16(PWR_GPIO, + (l_val & ~(PWR_MASK_VOL_18 | PWR_MASK_VOL_33 | PWR_MASK_CARD))); +#endif + l_val = MSDC_READ16(PWR_GPIO); + pr_debug("[%s]: pwr gpio = 0x%x\n", __func__, l_val); + return true; +} +EXPORT_SYMBOL(hwPowerDown_fpga); + +void msdc_fpga_power(struct msdc_host *host, u32 on) +{ + if (on) + hwPowerOn_fpga(); + else + hwPowerDown_fpga(); +} + +void msdc_sd_power_switch(struct msdc_host *host, u32 on) +{ + if (on) + hwPowerSwitch_fpga(); +} + +/* clock source for host: global */ +u32 hclks_msdc[] = {12000000, 12000000, 12000000, 12000000, 12000000, + 12000000, 12000000, 12000000, 0}; + +void msdc_select_clksrc(struct msdc_host *host, int clksrc) +{ + u32 *hclks; + + hclks = msdc_get_hclks(host->id); + + pr_err("[%s]: msdc%d change clk_src from %dKHz to %d:%dKHz\n", __func__, + host->id, (host->hclk/1000), clksrc, (hclks[clksrc]/1000)); + + host->hclk = hclks[clksrc]; + host->hw->clk_src = clksrc; +} + +void msdc_clk_status(int *status) +{ +} + +void msdc_polling_axi_status(int line, int dead) +{ +} diff --git a/drivers/mmc/host/mediatek/mt6755/msdc_io.c b/drivers/mmc/host/mediatek/mt6755/msdc_io.c new file mode 100644 index 0000000000000000000000000000000000000000..8577e39e194e56e327358feddf3f05d89a88113f --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/msdc_io.c @@ -0,0 +1,1377 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mt_sd.h" +#include +#include "msdc_tune.h" +#include "dbg.h" + +/**************************************************************/ +/* Section 1: Device Tree Global Variables */ +/**************************************************************/ +const struct of_device_id msdc_of_ids[] = { + { .compatible = DT_COMPATIBLE_NAME, }, + { }, +}; + +void __iomem *gpio_base; +void __iomem *infracfg_ao_reg_base; +void __iomem *infracfg_reg_base; +void __iomem *pericfg_reg_base; +void __iomem *toprgu_reg_base; +void __iomem *apmixed_reg_base; +void __iomem *topckgen_reg_base; + +void __iomem *msdc_io_cfg_bases[HOST_MAX_NUM]; + + +/**************************************************************/ +/* Section 2: Power */ +/**************************************************************/ +u32 g_msdc0_io; +u32 g_msdc0_flash; +u32 g_msdc1_io; +u32 g_msdc1_flash; +u32 g_msdc2_io; +u32 g_msdc2_flash; +u32 g_msdc3_io; +u32 g_msdc3_flash; + +#if !defined(FPGA_PLATFORM) +#include + +int msdc_regulator_set_and_enable(struct regulator *reg, int powerVolt) +{ + regulator_set_voltage(reg, powerVolt, powerVolt); + return regulator_enable(reg); +} + +void msdc_ldo_power(u32 on, struct regulator *reg, int voltage_mv, u32 *status) +{ + int voltage_uv = voltage_mv * 1000; + + if (reg == NULL) + return; + + if (on) { /* want to power on */ + if (*status == 0) { /* can power on */ + /*Comment out to reduce log */ + /* pr_warn("msdc power on<%d>\n", voltage_uv); */ + msdc_regulator_set_and_enable(reg, voltage_uv); + *status = voltage_uv; + } else if (*status == voltage_uv) { + pr_err("msdc power on <%d> again!\n", voltage_uv); + } else { + pr_warn("msdc change<%d> to <%d>\n", + *status, voltage_uv); + regulator_disable(reg); + msdc_regulator_set_and_enable(reg, voltage_uv); + *status = voltage_uv; + } + } else { /* want to power off */ + if (*status != 0) { /* has been powerred on */ + pr_warn("msdc power off\n"); + regulator_disable(reg); + *status = 0; + } else { + pr_err("msdc not power on\n"); + } + } +} + +void msdc_dump_ldo_sts(struct msdc_host *host) +{ + u32 ldo_en = 0, ldo_vol = 0, ldo_cal = 0; + u32 id = host->id; + + switch (id) { + case 0: + pmic_read_interface_nolock(REG_VEMC_EN, &ldo_en, MASK_VEMC_EN, + SHIFT_VEMC_EN); + pmic_read_interface_nolock(REG_VEMC_VOSEL, &ldo_vol, + MASK_VEMC_VOSEL, SHIFT_VEMC_VOSEL); + pmic_read_interface_nolock(REG_VEMC_VOSEL_CAL, &ldo_cal, + MASK_VEMC_VOSEL_CAL, SHIFT_VEMC_VOSEL_CAL); + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pr_err(" VEMC_EN=0x%x, VEMC_VOL=0x%x [2b'00(2.9V),2b'01(3V),2b'10(3.3V)], VEMC_CAL=0x%x\n", + ldo_en, ldo_vol, ldo_cal); + #else + pr_err(" VEMC_EN=0x%x, VEMC_VOL=0x%x [1b'0(3V),1b'1(3.3V)], VEMC_CAL=0x%x\n", + ldo_en, ldo_vol, ldo_cal); + #endif + break; + break; + case 1: + pmic_read_interface_nolock(REG_VMC_EN, &ldo_en, MASK_VMC_EN, + SHIFT_VMC_EN); + pmic_read_interface_nolock(REG_VMC_VOSEL, &ldo_vol, + MASK_VMC_VOSEL, SHIFT_VMC_VOSEL); + pmic_read_interface_nolock(REG_VMCH_VOSEL_CAL, &ldo_cal, + MASK_VMCH_VOSEL_CAL, SHIFT_VMCH_VOSEL_CAL); + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pr_err(" VMC_EN=0x%x, VMC_VOL=0x%x [2b'00(1.8V),2b'01(2.9V),2b'10(3V),2b'11(3.3V)], VMC_CAL=0x%x\n", + ldo_en, ldo_vol, ldo_cal); + #else + pr_err(" VMC_EN=0x%x, VMC_VOL=0x%x [3b'101(2.9V),3b'011(1.8V)], VMC_CAL=0x%x\n", + ldo_en, ldo_vol, ldo_cal); + #endif + + pmic_read_interface_nolock(REG_VMCH_EN, &ldo_en, MASK_VMCH_EN, + SHIFT_VMCH_EN); + pmic_read_interface_nolock(REG_VMCH_VOSEL, &ldo_vol, + MASK_VMCH_VOSEL, SHIFT_VMCH_VOSEL); + pmic_read_interface_nolock(REG_VMC_VOSEL_CAL, &ldo_cal, + MASK_VMC_VOSEL_CAL, SHIFT_VMC_VOSEL_CAL); + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + pr_err(" VMCH_EN=0x%x, VMCH_VOL=0x%x [2b'00(2.9V),2b'01(3V),2b'10(3.3V)], VMC_CAL=0x%x\n", + ldo_en, ldo_vol, ldo_cal); + #else + pr_err(" VMCH_EN=0x%x, VMCH_VOL=0x%x [1b'0(3V),1b'1(3.3V)], VMC_CAL=0x%x\n", + ldo_en, ldo_vol, ldo_cal); + #endif + + break; + default: + break; + } +} + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +void msdc_power_DL_CL_control(struct msdc_host *host, u32 sel) +{ + /* since this function may be invoked with a lock already get, + we use pmic_config_interface_nolock() instead of + pmic_config_interface() to avoid lock dependency */ + u32 DL_on = 0, CL_on = 0; + + if (host->id == 0) { + if (sel == MSDC_POWER_DL_CL_FOR_POWER_OFF) { + CL_on = 0; + DL_on = 0; + } else if (sel == MSDC_POWER_DL_CL_FOR_POWER_ON) { + CL_on = 0; + DL_on = 1; + /* + } else if (sel == MSDC_POWER_DL_CL_FOR_NO_LOAD) { + DL_on = 0; + CL_on = 1; + } else { + DL_on = 1; + CL_on = 1; + */ + } + if (host->power_DL_status != DL_on) + pmic_config_interface_nolock(REG_VEMC_DL_EN, DL_on, + MASK_VEMC_DL_EN, SHIFT_VEMC_DL_EN); + if (host->power_CL_status != CL_on) + pmic_config_interface_nolock(REG_VEMC_CL_EN, CL_on, + MASK_VEMC_CL_EN, SHIFT_VEMC_CL_EN); + + host->power_DL_status = DL_on; + host->power_CL_status = CL_on; + udelay(60); + } else if (host->id == 1) { + CL_on = 0; + if (sel == MSDC_POWER_DL_CL_FOR_POWER_OFF) { + DL_on = 0; + } else if (sel == MSDC_POWER_DL_CL_FOR_POWER_ON) { + DL_on = 1; + /* + } else if (sel == MSDC_POWER_DL_CL_FOR_NO_LOAD) { + DL_on = 0; + } else { + DL_on = 1;*/ + } + + /* VMCH CL always off, DL alwys on */ + if (host->power_DL_status != DL_on) + pmic_config_interface_nolock(REG_VMCH_DL_EN, DL_on, + MASK_VMCH_DL_EN, SHIFT_VMCH_DL_EN); + /* + pmic_config_interface_nolock(REG_VMCH_CL_EN, on, + MASK_VMCH_CL_EN, SHIFT_VMCH_CL_EN); + */ + + /* VMC CL always off, DL alwys on */ + if (host->power_CL_status != DL_on) + pmic_config_interface_nolock(REG_VMC_DL_EN, DL_on, + MASK_VMC_DL_EN, SHIFT_VMC_DL_EN); + /* + pmic_config_interface_nolock(REG_VMC_CL_EN, on, + MASK_VMC_CL_EN, SHIFT_VMC_CL_EN); + */ + + host->power_DL_status = DL_on; + host->power_CL_status = CL_on; + udelay(60); + } + /*pr_err("msdc%d power_control DL(%d) CL(%d)\n", host->id, DL_on, + CL_on);*/ +} +#endif + +void msdc_sd_power_switch(struct msdc_host *host, u32 on) +{ + unsigned int reg_val; + + switch (host->id) { + case 1: + if (on) { + /* VMC calibration +40mV. According to SA's request. */ + reg_val = host->vmc_cal_default - 2; + + pmic_config_interface(REG_VMC_VOSEL_CAL, + reg_val, + MASK_VMC_VOSEL_CAL, + SHIFT_VMC_VOSEL_CAL); + } + + msdc_ldo_power(on, host->mmc->supply.vqmmc, VOL_1800, &g_msdc1_io); + msdc_set_tdsel(host, MSDC_TDRDSEL_1V8, 0); + msdc_set_rdsel(host, MSDC_TDRDSEL_1V8, 0); + msdc_set_driving(host, host->hw, 1); + break; + + default: + break; + } +} + +void msdc_sdio_power(struct msdc_host *host, u32 on) +{ + switch (host->id) { +#if defined(CFG_DEV_MSDC2) + case 2: + g_msdc2_flash = g_msdc2_io; + break; +#endif + + default: + /* if host_id is 3, it uses default 1.8v setting, + which always turns on */ + break; + } + +} + +void msdc_power_calibration_init(struct msdc_host *host) +{ + if (MSDC_EMMC == host->hw->host_function) { + #if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* Set to 3.0V - 100mV + * 4'b0000: 0 mV + * 4'b0001: -20 mV + * 4'b0010: -40 mV + * 4'b0011: -60 mV + * 4'b0100: -80 mV + * 4'b0101: -100 mV*/ + pmic_config_interface(REG_VEMC_VOSEL_CAL, + VEMC_VOSEL_CAL_mV(EMMC_VOL_ACTUAL - VOL_3000), + MASK_VEMC_VOSEL_CAL, + SHIFT_VEMC_VOSEL_CAL); + #endif + } else if (MSDC_SD == host->hw->host_function) { + #if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + u32 val = 0; + + /* VMCH vosel is 3.0V and calibration default is 0mV. + Use calibration -100mv to get target VMCH = 2.9V */ + pmic_read_interface(REG_VMCH_VOSEL_CAL, &val, + MASK_VMCH_VOSEL_CAL, SHIFT_VMCH_VOSEL_CAL); + + pr_err("msdc1, 0xACE=%x\n", val); + + if (5 > val) + val = 0x20 + val - 5; + else + val = val - 5; + + pmic_config_interface(REG_VMCH_VOSEL_CAL, val, + MASK_VMCH_VOSEL_CAL, SHIFT_VMCH_VOSEL_CAL); + + pr_err("msdc1, 0xACE=%x\n", val); + + /* VMC vosel is 2.8V with some calibration value, + Add extra 100mV calibration value to get tar VMC = 2.9V */ + pmic_read_interface(REG_VMC_VOSEL_CAL, &val, + MASK_VMC_VOSEL_CAL, SHIFT_VMC_VOSEL_CAL); + + pr_err("msdc1, 0xAE2=%x\n", val); + + if (0x1b > val) + val = 0x20 + val - 0x1b; + else + val = val - 0x1b; + + host->vmc_cal_default = val; + pmic_config_interface(REG_VMC_VOSEL_CAL, val, + MASK_VMC_VOSEL_CAL, SHIFT_VMC_VOSEL_CAL); + + #else + pmic_read_interface(REG_VMC_VOSEL_CAL, + &host->vmc_cal_default, + MASK_VMC_VOSEL_CAL, SHIFT_VMC_VOSEL_CAL); + #endif + + } +} + +void msdc_oc_check(struct msdc_host *host) +{ + u32 val = 0; + + if (host->id == 1) { + pmic_read_interface(REG_VMCH_OC_STATUS, &val, + MASK_VMCH_OC_STATUS, SHIFT_VMCH_OC_STATUS); + + if (val) { + pr_err("msdc1 OC status = %x\n", val); + host->power_control(host, 0); + } + } +} + +void msdc_emmc_power(struct msdc_host *host, u32 on) +{ + void __iomem *base = host->base; + + if (on == 0) { + if ((MSDC_READ32(MSDC_PS) & 0x10000) != 0x10000) + emmc_sleep_failed = 1; + } else { + msdc_set_driving(host, host->hw, 0); + msdc_set_tdsel(host, MSDC_TDRDSEL_1V8, 0); + msdc_set_rdsel(host, MSDC_TDRDSEL_1V8, 0); + } + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + msdc_power_DL_CL_control(host, ((on == 0) ? 0 : 1)); + #endif + msdc_ldo_power(on, host->mmc->supply.vmmc, VOL_3000, &g_msdc0_flash); + + if (on && EMMC_VOL_ACTUAL != VOL_3000) { + pmic_config_interface(REG_VEMC_VOSEL_CAL, + VEMC_VOSEL_CAL_mV(EMMC_VOL_ACTUAL - VOL_3000), + MASK_VEMC_VOSEL_CAL, + SHIFT_VEMC_VOSEL_CAL); + } + +#ifdef MTK_MSDC_BRINGUP_DEBUG + msdc_dump_ldo_sts(host); +#endif +} + +void msdc_sd_power(struct msdc_host *host, u32 on) +{ + u32 card_on = on; + + switch (host->id) { + case 1: + msdc_set_driving(host, host->hw, 0); + msdc_set_tdsel(host, MSDC_TDRDSEL_3V, 0); + msdc_set_rdsel(host, MSDC_TDRDSEL_3V, 0); + if (host->hw->flags & MSDC_SD_NEED_POWER) + card_on = 1; + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* ramp-up time: 0: 40us, 1: 240us */ + pmic_config_interface(REG_VMCH_RAMPUP_SEL, on, MASK_VMCH_RAMPUP_SEL, + SHIFT_VMCH_RAMPUP_SEL); + msdc_power_DL_CL_control(host, ((on == 0) ? 0 : 1)); + #endif + /* VMCH VOLSEL */ + msdc_ldo_power(card_on, host->mmc->supply.vmmc, VOL_3000, + &g_msdc1_flash); + + /* VMCH Golden for 6750 */ + /* Addr on off mask shift */ + /* vosel: 0xAB2 6 0x7 8 */ + /* DL : 0xAB4 1 0 0x1 8 */ + /* CL : 0xAB4 1 0 0x1 9 */ + /* Ramp : 0xA80 0x1 9 */ + /* EN : 0xA80 1 0 0x1 1 */ + + + /* VMC VOLSEL */ + msdc_ldo_power(on, host->mmc->supply.vqmmc, VOL_3000, + &g_msdc1_io); + + /* VMC Golden for 6750 */ + /* Addr on off mask shift */ + /* vosel: 0xAC2 1 0x3 8 */ + /* DL : 0xAC4 1 0 0x1 4 */ + /* CL : 0xAC4 1 0 0x1 5 */ + /* EN : 0xA7A 1 0 0x1 1 */ + + + break; + + default: + break; + } + +#ifdef MTK_MSDC_BRINGUP_DEBUG + msdc_dump_ldo_sts(host); +#endif +} + +void msdc_sd_power_off(void) +{ + struct msdc_host *host = mtk_msdc_host[1]; + + if (host) { + pr_err("Power Off, SD card\n"); + + /* power must be on */ + g_msdc1_io = VOL_3000 * 1000; + g_msdc1_flash = VOL_3000 * 1000; + + host->power_control(host, 0); + + msdc_set_bad_card_and_remove(host); + } +} +EXPORT_SYMBOL(msdc_sd_power_off); +#endif + +#ifdef MSDC_HQA +/*#define HQA_VCORE 0x48*/ /* HVcore, 1.05V */ +#define HQA_VCORE 0x40 /* NVcore, 1.0V */ +/*#define HQA_VCORE 0x38*/ /* LVcore, 0.95V */ + +void msdc_HQA_set_vcore(struct msdc_host *host) +{ + if (host->first_tune_done == 0) { + pmic_config_interface(REG_VCORE_VOSEL_SW, HQA_VCORE, + VCORE_VOSEL_SW_MASK, 0); + pmic_config_interface(REG_VCORE_VOSEL_HW, HQA_VCORE, + VCORE_VOSEL_HW_MASK, 0); + } +} +#endif + + +/**************************************************************/ +/* Section 3: Clock */ +/**************************************************************/ +#if !defined(FPGA_PLATFORM) +u32 hclks_msdc50[] = { MSDC0_SRC_0, MSDC0_SRC_1, MSDC0_SRC_2, MSDC0_SRC_3, + MSDC0_SRC_4, MSDC0_SRC_5, MSDC0_SRC_6, MSDC0_SRC_7, + MSDC0_SRC_8}; + +/* msdc1/2 clock source reference value is 200M */ +u32 hclks_msdc30[] = { MSDC1_SRC_0, MSDC1_SRC_1, MSDC1_SRC_2, MSDC1_SRC_3, + MSDC1_SRC_4, MSDC1_SRC_5, MSDC1_SRC_6, MSDC1_SRC_7}; + +u32 hclks_msdc30_3[] = { MSDC3_SRC_0, MSDC3_SRC_1, MSDC3_SRC_2, MSDC3_SRC_3, + MSDC3_SRC_4, MSDC3_SRC_5, MSDC3_SRC_6, MSDC3_SRC_7, + MSDC3_SRC_8}; + +u32 *hclks_msdc_all[] = { + hclks_msdc50, + hclks_msdc30, + hclks_msdc30, + hclks_msdc30_3 +}; +u32 *hclks_msdc = hclks_msdc30; + + +#include +#include + +int msdc_cg_clk_id[HOST_MAX_NUM] = { + MSDC0_CG_NAME, + MSDC1_CG_NAME, + MSDC2_CG_NAME, + MSDC3_CG_NAME +}; + +int msdc_get_ccf_clk_pointer(struct platform_device *pdev, + struct msdc_host *host) +{ + static char const * const clk_names[] = { + MSDC0_CLK_NAME, MSDC1_CLK_NAME, MSDC2_CLK_NAME, MSDC3_CLK_NAME + }; + + host->clock_control = devm_clk_get(&pdev->dev, clk_names[pdev->id]); + + if (IS_ERR(host->clock_control)) { + pr_err("can not get msdc%d clock control\n", pdev->id); + return 1; + } + if (clk_prepare(host->clock_control)) { + pr_err("can not prepare msdc%d clock control\n", pdev->id); + return 1; + } + + return 0; +} + +void msdc_select_clksrc(struct msdc_host *host, int clksrc) +{ + u32 *hclks; + + hclks = msdc_get_hclks(host->id); + + pr_err("[%s]: msdc%d select clk_src as %d(%dKHz)\n", __func__, + host->id, clksrc, (hclks[clksrc]/1000)); + + host->hclk = hclks[clksrc]; + host->hw->clk_src = clksrc; +} + +void msdc_dump_clock_sts(void) +{ + void __iomem *reg; + + if (apmixed_reg_base && topckgen_reg_base && infracfg_ao_reg_base) { + reg = apmixed_reg_base + MSDCPLL_PWR_CON0_OFFSET; + pr_err(" MSDCPLL_PWR_CON0[0x%p][bit0~1 should be 2b'01]=0x%x\n", + reg, MSDC_READ32(reg)); + reg = apmixed_reg_base + MSDCPLL_CON0_OFFSET; + pr_err(" MSDCPLL_CON0 [0x%p][bit0 should be 1b'1]=0x%x\n", + reg, MSDC_READ32(reg)); + + reg = topckgen_reg_base + MSDC_CLK_CFG_3_OFFSET; + pr_err(" CLK_CFG_3 [0x%p][bit[19:16]should be 0x1]=0x%x\n", + reg, MSDC_READ32(reg)); + pr_err(" CLK_CFG_3 [0x%p][bit[27:24]should be 0x7]=0x%x\n", + reg, MSDC_READ32(reg)); + reg = topckgen_reg_base + MSDC_CLK_CFG_4_OFFSET; + pr_err(" CLK_CFG_4 [0x%p][bit[3:0]should be 0x7]=0x%x\n", + reg, MSDC_READ32(reg)); + + reg = infracfg_ao_reg_base + MSDC_INFRA_PDN_STA1_OFFSET; + pr_err(" MODULE_SW_CG_1 [0x%p][bit2=msdc0, bit4=msdc1, bit5=msdc2, 0:on,1:off]=0x%x\n", + reg, MSDC_READ32(reg)); + } else { + pr_err(" apmixed_reg_base = %p, topckgen_reg_base = %p, clk_infra_base = %p\n", + apmixed_reg_base, topckgen_reg_base, infracfg_ao_reg_base); + } +} + +void msdc_clk_status(int *status) +{ + int g_clk_gate = 0; + int i = 0; + unsigned long flags; + + for (i = 0; i < HOST_MAX_NUM; i++) { + if (!mtk_msdc_host[i]) + continue; + + spin_lock_irqsave(&mtk_msdc_host[i]->clk_gate_lock, flags); + if (mtk_msdc_host[i]->clk_gate_count > 0) + g_clk_gate |= 1 << msdc_cg_clk_id[i]; + spin_unlock_irqrestore(&mtk_msdc_host[i]->clk_gate_lock, flags); + } + *status = g_clk_gate; +} +#endif + +/**************************************************************/ +/* Section 4: GPIO and Pad */ +/**************************************************************/ +#if !defined(FPGA_PLATFORM) +void msdc_dump_padctl_by_id(u32 id) +{ + switch (id) { + case 0: + pr_err("MSDC0 MODE18[0x%p] =0x%8x\tshould:0x12-- ----\n", + MSDC0_GPIO_MODE18, MSDC_READ32(MSDC0_GPIO_MODE18)); + pr_err("MSDC0 MODE19[0x%p] =0x%8x\tshould:0x1249 1249\n", + MSDC0_GPIO_MODE19, MSDC_READ32(MSDC0_GPIO_MODE19)); + pr_err("MSDC0 IES [0x%p] =0x%8x\tshould:0x---- --1F\n", + MSDC0_GPIO_IES_ADDR, MSDC_READ32(MSDC0_GPIO_IES_ADDR)); + pr_err("MSDC0 SMT [0x%p] =0x%8x\tshould:0x---- --1F\n", + MSDC0_GPIO_SMT_ADDR, MSDC_READ32(MSDC0_GPIO_SMT_ADDR)); + pr_err("MSDC0 TDSEL [0x%p] =0x%8x\tshould:0x---0 0000\n", + MSDC0_GPIO_TDSEL_ADDR, + MSDC_READ32(MSDC0_GPIO_TDSEL_ADDR)); + pr_err("MSDC0 RDSEL [0x%p] =0x%8x\tshould:0x0000 0000\n", + MSDC0_GPIO_RDSEL_ADDR, + MSDC_READ32(MSDC0_GPIO_RDSEL_ADDR)); + pr_err("MSDC0 SR [0x%p] =0x%8x\n", + MSDC0_GPIO_SR_ADDR, + MSDC_READ32(MSDC0_GPIO_SR_ADDR)); + pr_err("MSDC0 DRV [0x%p] =0x%8x\n", + MSDC0_GPIO_DRV_ADDR, + MSDC_READ32(MSDC0_GPIO_DRV_ADDR)); + pr_err("MSDC0 PULL0 [0x%p] =0x%8x\n", + MSDC0_GPIO_PUPD0_ADDR, + MSDC_READ32(MSDC0_GPIO_PUPD0_ADDR)); + pr_err("P-NONE: 0x4444 4444, PU:0x2111 1161, PD:0x6666 6666\n"); + pr_err("MSDC0 PULL1 [0x%p] =0x%8x\n", + MSDC0_GPIO_PUPD1_ADDR, + MSDC_READ32(MSDC0_GPIO_PUPD1_ADDR)); + pr_err("P-NONE: 0x---- 4444, PU:0x---- 6111, PD:0x---- 6666\n"); + break; + + case 1: + pr_err("MSDC1 MODE4 [0x%p] =0x%8x\tshould:0x---1 1249\n", + MSDC1_GPIO_MODE4, MSDC_READ32(MSDC1_GPIO_MODE4)); + pr_err("MSDC1 IES [0x%p] =0x%8x\tshould:0x---- -7--\n", + MSDC1_GPIO_IES_ADDR, MSDC_READ32(MSDC1_GPIO_IES_ADDR)); + pr_err("MSDC1 SMT [0x%p] =0x%8x\tshould:0x---- -7--\n", + MSDC1_GPIO_SMT_ADDR, MSDC_READ32(MSDC1_GPIO_SMT_ADDR)); + pr_err("MSDC1 TDSEL [0x%p] =0x%8x\n", + MSDC1_GPIO_TDSEL_ADDR, + MSDC_READ32(MSDC1_GPIO_TDSEL_ADDR)); + /* FIX ME: Check why sleep shall set as F */ + pr_err("should 1.8v: sleep:0x---- -FFF, awake:0x---- -AAA\n"); + pr_err("MSDC1 RDSEL0[0x%p] =0x%8x\n", + MSDC1_GPIO_RDSEL0_ADDR, + MSDC_READ32(MSDC1_GPIO_RDSEL0_ADDR)); + pr_err("1.8V: 0x-000 ----, 3.3v: 0x-30C ----\n"); + pr_err("MSDC1 RDSEL1[0x%p] =0x%8x\n", + MSDC1_GPIO_RDSEL1_ADDR, + MSDC_READ32(MSDC1_GPIO_RDSEL1_ADDR)); + pr_err("should 1.8V: 0x-000 ----, 3.3v: 0x---- ---C\n"); + pr_err("MSDC1 SR [0x%p] =0x%8x\n", + MSDC1_GPIO_SR_ADDR, MSDC_READ32(MSDC1_GPIO_SR_ADDR)); + pr_err("MSDC1 DRV [0x%p] =0x%8x\n", + MSDC1_GPIO_DRV_ADDR, MSDC_READ32(MSDC1_GPIO_DRV_ADDR)); + pr_err("MSDC1 PULL [0x%p] =0x%8x\n", + MSDC1_GPIO_PUPD_ADDR, + MSDC_READ32(MSDC1_GPIO_PUPD_ADDR)); + pr_err("P-NONE: 0x--44 4444, PU:0x--22 2262, PD:0x--66 6666\n"); + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + pr_err("MSDC2 MODE14[0x%p][21:3] =0x%8x\tshould:0x--0x12 2490\n", + MSDC2_GPIO_MODE14, MSDC_READ32(MSDC2_GPIO_MODE14)); + pr_err("MSDC2 IES [0x%p][5:3] =0x%8x\tshould:0x---- -38-\n", + MSDC2_GPIO_IES_ADDR, MSDC_READ32(MSDC2_GPIO_IES_ADDR)); + pr_err("MSDC2 SMT [0x%p][5:3] =0x%8x\tshould:0x---- -38-\n", + MSDC2_GPIO_SMT_ADDR, MSDC_READ32(MSDC2_GPIO_SMT_ADDR)); + pr_err("MSDC2 TDSEL [0x%p][23:12] =0x%8xtshould:0x--0x--00 0---\n", + MSDC2_GPIO_TDSEL_ADDR, MSDC_READ32(MSDC2_GPIO_TDSEL_ADDR)); + pr_err("MSDC2 RDSEL0[0x%p][11:6] =0x%8xtshould:0x--0x---- -00-\n", + MSDC2_GPIO_RDSEL_ADDR, MSDC_READ32(MSDC2_GPIO_RDSEL_ADDR)); + pr_err("MSDC2 SR DRV[0x%p][23:12] =0x%8x\n", + MSDC2_GPIO_SR_ADDR, MSDC_READ32(MSDC2_GPIO_SR_ADDR)); + pr_err("MSDC2 PULL [0x%p][31:12] =0x%8x\n", + MSDC2_GPIO_PUPD_ADDR0, MSDC_READ32(MSDC2_GPIO_PUPD_ADDR0)); + pr_err("P-NONE: 0x--44444, PU:0x--11611, PD:0x--66666\n"); + pr_err("MSDC2 PULL [0x%p][2:0] =0x%8x\n", + MSDC2_GPIO_PUPD_ADDR1, MSDC_READ32(MSDC2_GPIO_PUPD_ADDR1)); + pr_err("P-NONE: 0x--4, PU:0x--1, PD:0x--6\n"); + break; +#endif + } +} + +void msdc_set_pin_mode(struct msdc_host *host) +{ + switch (host->id) { + case 0: + MSDC_SET_FIELD(MSDC0_GPIO_MODE18, (0x3F << 25), 0x9); + MSDC_SET_FIELD(MSDC0_GPIO_MODE19, 0xFFFFFFFF, 0x12491249); + break; + + case 1: + MSDC_SET_FIELD(MSDC1_GPIO_MODE4, 0x0007FFFF, 0x0011249); + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_SET_FIELD(MSDC2_GPIO_MODE14, 0x003FFFF8, 0x24492); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + + } +} + +void msdc_set_ies_by_id(u32 id, int set_ies) +{ + switch (id) { + case 0: + MSDC_SET_FIELD(MSDC0_GPIO_IES_ADDR, MSDC0_IES_ALL_MASK, + (set_ies ? 0x1F : 0)); + break; + + case 1: + MSDC_SET_FIELD(MSDC1_GPIO_IES_ADDR, MSDC1_IES_ALL_MASK, + (set_ies ? 0x7 : 0)); + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_SET_FIELD(MSDC2_GPIO_IES_ADDR, MSDC2_IES_ALL_MASK, + (set_ies ? 0x7 : 0)); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + } +} + +void msdc_set_smt_by_id(u32 id, int set_smt) +{ + switch (id) { + case 0: + MSDC_SET_FIELD(MSDC0_GPIO_SMT_ADDR, MSDC0_SMT_ALL_MASK, + (set_smt ? 0x1F : 0)); + break; + case 1: + MSDC_SET_FIELD(MSDC1_GPIO_SMT_ADDR, MSDC1_SMT_ALL_MASK, + (set_smt ? 0x7 : 0)); + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_SET_FIELD(MSDC2_GPIO_SMT_ADDR, MSDC2_SMT_ALL_MASK, + (set_smt ? 0x7 : 0)); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + } +} + +void msdc_set_tdsel_by_id(u32 id, u32 flag, u32 value) +{ + u32 cust_val; + + switch (id) { + case 0: + MSDC_SET_FIELD(MSDC0_GPIO_TDSEL_ADDR, MSDC0_TDSEL_ALL_MASK , 0); + break; + case 1: + if (flag == MSDC_TDRDSEL_SLEEP) { + MSDC_SET_FIELD(MSDC1_GPIO_TDSEL_ADDR, + MSDC1_TDSEL_ALL_MASK, 0xFFF); + } else if (flag == MSDC_TDRDSEL_CUST) { + value &= 0xF; + cust_val = value | (value << 4) | (value << 8); + MSDC_SET_FIELD(MSDC1_GPIO_TDSEL_ADDR, + MSDC1_TDSEL_ALL_MASK, cust_val); + } else { + MSDC_SET_FIELD(MSDC1_GPIO_TDSEL_ADDR, + MSDC1_TDSEL_ALL_MASK, 0xAAA); + } + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_SET_FIELD(MSDC2_GPIO_TDSEL_ADDR, MSDC2_TDSEL_ALL_MASK , 0); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + } +} + +void msdc_set_rdsel_by_id(u32 id, u32 flag, u32 value) +{ + switch (id) { + case 0: + MSDC_SET_FIELD(MSDC0_GPIO_RDSEL_ADDR, MSDC0_RDSEL_ALL_MASK, 0); + break; + + case 1: + if (flag == MSDC_TDRDSEL_1V8) { + MSDC_SET_FIELD(MSDC1_GPIO_RDSEL0_ADDR, + MSDC1_RDSEL0_ALL_MASK, 0); + MSDC_SET_FIELD(MSDC1_GPIO_RDSEL1_ADDR, + MSDC1_RDSEL1_ALL_MASK, 0); + } else if (flag == MSDC_TDRDSEL_3V) { + MSDC_SET_FIELD(MSDC1_GPIO_RDSEL0_ADDR, + MSDC1_RDSEL0_ALL_MASK, 0x30C); + MSDC_SET_FIELD(MSDC1_GPIO_RDSEL1_ADDR, + MSDC1_RDSEL1_ALL_MASK, 0xC); + } else if (flag == MSDC_TDRDSEL_CUST) { + MSDC_SET_FIELD(MSDC1_GPIO_RDSEL0_ADDR, + MSDC1_RDSEL0_ALL_MASK, + (value & 0x3F) | ((value & 0x3F) << 6)); + MSDC_SET_FIELD(MSDC1_GPIO_RDSEL1_ADDR, + MSDC1_RDSEL1_ALL_MASK, value & 0x3F); + } + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_SET_FIELD(MSDC2_GPIO_RDSEL_ADDR, MSDC2_RDSEL_ALL_MASK, 0); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + } +} + +void msdc_get_tdsel_by_id(u32 id, u32 *value) +{ + switch (id) { + case 0: + MSDC_GET_FIELD(MSDC0_GPIO_TDSEL_ADDR, + MSDC0_TDSEL_CMD_MASK, *value); + break; + + case 1: + MSDC_GET_FIELD(MSDC1_GPIO_TDSEL_ADDR, + MSDC1_TDSEL_CMD_MASK, *value); + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_GET_FIELD(MSDC2_GPIO_TDSEL_ADDR, + MSDC2_TDSEL_CMD_MASK, *value); + break; +#endif + } +} + +void msdc_get_rdsel_by_id(u32 id, u32 *value) +{ + switch (id) { + case 0: + MSDC_GET_FIELD(MSDC0_GPIO_RDSEL_ADDR, + MSDC0_RDSEL_CMD_MASK, *value); + break; + + case 1: + MSDC_GET_FIELD(MSDC1_GPIO_RDSEL1_ADDR, + MSDC1_RDSEL_CMD_MASK, *value); + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_GET_FIELD(MSDC2_GPIO_RDSEL_ADDR, + MSDC2_RDSEL_CMD_MASK, *value); + break; +#endif + } +} + +void msdc_set_sr_by_id(u32 id, int clk, int cmd, int dat, int rst, int ds) +{ + switch (id) { + case 0: + MSDC_SET_FIELD(MSDC0_GPIO_SR_ADDR, MSDC0_SR_CMD_MASK, + (cmd != 0)); + MSDC_SET_FIELD(MSDC0_GPIO_SR_ADDR, MSDC0_SR_DSL_MASK, + (ds != 0)); + MSDC_SET_FIELD(MSDC0_GPIO_SR_ADDR, MSDC0_SR_CLK_MASK, + (clk != 0)); + MSDC_SET_FIELD(MSDC0_GPIO_SR_ADDR, MSDC0_SR_DAT_MASK, + (dat != 0)); + MSDC_SET_FIELD(MSDC0_GPIO_SR_ADDR, MSDC0_SR_RSTB_MASK, + (rst != 0)); + break; + case 1: + MSDC_SET_FIELD(MSDC1_GPIO_SR_ADDR, MSDC1_SR_CMD_MASK, + (cmd != 0)); + MSDC_SET_FIELD(MSDC1_GPIO_SR_ADDR, MSDC1_SR_CLK_MASK, + (clk != 0)); + MSDC_SET_FIELD(MSDC1_GPIO_SR_ADDR, MSDC1_SR_DAT_MASK, + (dat != 0)); + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_SET_FIELD(MSDC2_GPIO_SR_ADDR, MSDC2_SR_CMD_MASK, + (cmd != 0)); + MSDC_SET_FIELD(MSDC2_GPIO_SR_ADDR, MSDC2_SR_CLK_MASK, + (clk != 0)); + MSDC_SET_FIELD(MSDC2_GPIO_SR_ADDR, MSDC2_SR_DAT_MASK, + (dat != 0)); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + } + +} + +void msdc_set_driving_by_id(u32 id, struct msdc_hw *hw, bool sd_18) +{ + switch (id) { + case 0: + MSDC_SET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_CMD_MASK, + hw->cmd_drv); + MSDC_SET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_DSL_MASK, + hw->ds_drv); + MSDC_SET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_CLK_MASK, + hw->clk_drv); + MSDC_SET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_DAT_MASK, + hw->dat_drv); + MSDC_SET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_RSTB_MASK, + hw->rst_drv); + break; + case 1: + if (sd_18) { + MSDC_SET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_CMD_MASK, + hw->cmd_drv_sd_18); + MSDC_SET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_CLK_MASK, + hw->clk_drv_sd_18); + MSDC_SET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_DAT_MASK, + hw->dat_drv_sd_18); + } else { + MSDC_SET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_CMD_MASK, + hw->cmd_drv); + MSDC_SET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_CLK_MASK, + hw->clk_drv); + MSDC_SET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_DAT_MASK, + hw->dat_drv); + } + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_SET_FIELD(MSDC2_GPIO_DRV_ADDR, MSDC2_DRV_CMD_MASK, + hw->cmd_drv); + MSDC_SET_FIELD(MSDC2_GPIO_DRV_ADDR, MSDC2_DRV_CLK_MASK, + hw->clk_drv); + MSDC_SET_FIELD(MSDC2_GPIO_DRV_ADDR, MSDC2_DRV_DAT_MASK, + hw->dat_drv); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + } +} + +void msdc_set_driving(struct msdc_host *host, struct msdc_hw *hw, bool sd_18) +{ + msdc_set_driving_by_id(host->id, hw, sd_18); +} + +void msdc_get_driving_by_id(u32 id, struct msdc_hw *hw) +{ + switch (id) { + case 0: + MSDC_GET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_CMD_MASK, + hw->cmd_drv); + MSDC_GET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_DSL_MASK, + hw->ds_drv); + MSDC_GET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_CLK_MASK, + hw->clk_drv); + MSDC_GET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_DAT_MASK, + hw->dat_drv); + MSDC_GET_FIELD(MSDC0_GPIO_DRV_ADDR, MSDC0_DRV_RSTB_MASK, + hw->rst_drv); + break; + case 1: + if (g_msdc1_io == 1800000) { + MSDC_GET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_CMD_MASK, + hw->cmd_drv_sd_18); + MSDC_GET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_CLK_MASK, + hw->clk_drv_sd_18); + MSDC_GET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_DAT_MASK, + hw->dat_drv_sd_18); + } else { + MSDC_GET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_CMD_MASK, + hw->cmd_drv); + MSDC_GET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_CLK_MASK, + hw->clk_drv); + MSDC_GET_FIELD(MSDC1_GPIO_DRV_ADDR, MSDC1_DRV_DAT_MASK, + hw->dat_drv); + } + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + MSDC_GET_FIELD(MSDC2_GPIO_DRV_ADDR, MSDC2_DRV_CMD_MASK, + hw->cmd_drv); + MSDC_GET_FIELD(MSDC2_GPIO_DRV_ADDR, MSDC2_DRV_CLK_MASK, + hw->clk_drv); + MSDC_GET_FIELD(MSDC2_GPIO_DRV_ADDR, MSDC2_DRV_DAT_MASK, + hw->dat_drv); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + } +} + +void msdc_pin_config_by_id(u32 id, u32 mode) +{ + u32 val0, val1; + + if ((mode != MSDC_PIN_PULL_NONE) + && (mode != MSDC_PIN_PULL_DOWN) + && (mode != MSDC_PIN_PULL_UP)) + return; + + switch (id) { + case 0: + /*Attention: don't pull CLK high; Don't toggle RST to prevent + from entering boot mode */ + if (MSDC_PIN_PULL_NONE == mode) { + /* high-Z */ + val0 = 0x4444444; + val1 = 0x4444; + } else if (MSDC_PIN_PULL_DOWN == mode) { + /* cmd/clk/dat/(rstb)/dsl:pd-50k*/ + val0 = 0x6666666; + val1 = 0x6666; + } else if (MSDC_PIN_PULL_UP == mode) { + /* clk/dsl:pd-50k, cmd/dat:pu-10k, (rstb:pu-50k)*/ + val0 = 0x1111161; + val1 = 0x6111; + } + MSDC_SET_FIELD(MSDC0_GPIO_PUPD0_ADDR, MSDC0_PUPD0_MASK, val0); + MSDC_SET_FIELD(MSDC0_GPIO_PUPD1_ADDR, MSDC0_PUPD1_MASK, val1); + break; + + case 1: + if (MSDC_PIN_PULL_NONE == mode) { + /* high-Z */ + val0 = 0x444444; + } else if (MSDC_PIN_PULL_DOWN == mode) { + /* cmd/clk/dat:pd-50k */ + val0 = 0x666666; + } else if (MSDC_PIN_PULL_UP == mode) { + /* cmd/dat:pu-50k, clk:pd-50k */ + val0 = 0x222262; + } + MSDC_SET_FIELD(MSDC1_GPIO_PUPD_ADDR, MSDC1_PUPD_MASK, val0); + break; + +#ifdef CFG_DEV_MSDC2 + case 2: + if (MSDC_PIN_PULL_NONE == mode) { + /* high-Z */ + val0 = 0x44444; + val1 = 0x4; + } else if (MSDC_PIN_PULL_DOWN == mode) { + /* cmd/clk/dat:pd-50k */ + val0 = 0x66666; + val1 = 0x6; + } else if (MSDC_PIN_PULL_UP == mode) { + /* cmd/dat:pu-10k, clk:pd-50k, */ + val0 = 0x11611; + val1 = 0x1; + } + MSDC_SET_FIELD(MSDC2_GPIO_PUPD_ADDR0, MSDC2_PUPD_MASK0, val0); + MSDC_SET_FIELD(MSDC2_GPIO_PUPD_ADDR1, MSDC2_PUPD_MASK1, val1); + break; +#endif + + default: + pr_err("[%s] invlalid host->id!\n", __func__); + break; + } + +} +#endif /*if !defined(FPGA_PLATFORM)*/ + +/**************************************************************/ +/* Section 5: Device Tree Init function */ +/* This function is placed here so that all */ +/* functions and variables used by it has already */ +/* been declared */ +/**************************************************************/ +/* + * parse pinctl settings + * Driver strength + */ +static int msdc_get_pinctl_settings(struct msdc_host *host, struct device_node *np) +{ + struct device_node *pinctl_node, *pins_node; + static char const * const pinctl_names[] = { + "pinctl", "pinctl_sdr104", "pinctl_sdr50", "pinctl_ddr50" + }; + + static char const * const pins_names[] = { + "pins_cmd", "pins_dat", "pins_clk", "pins_rst", "pins_ds" + }; + unsigned char *pins_drv[5]; + int i, j; + + for (i = 0; i < sizeof(pinctl_names)/sizeof(pinctl_names[0]); i++) { + pinctl_node = of_parse_phandle(np, pinctl_names[i], 0); + + if (strcmp(pinctl_names[i], "pinctl") == 0) { + pins_drv[0] = &host->hw->cmd_drv; + pins_drv[1] = &host->hw->dat_drv; + pins_drv[2] = &host->hw->clk_drv; + pins_drv[3] = &host->hw->rst_drv; + pins_drv[4] = &host->hw->ds_drv; + } else if (strcmp(pinctl_names[i], "pinctl_sdr104") == 0) { + pins_drv[0] = &host->hw->cmd_drv_sd_18; + pins_drv[1] = &host->hw->dat_drv_sd_18; + pins_drv[2] = &host->hw->clk_drv_sd_18; + } else if (strcmp(pinctl_names[i], "pinctl_sdr50") == 0) { + pins_drv[0] = &host->hw->cmd_drv_sd_18_sdr50; + pins_drv[1] = &host->hw->dat_drv_sd_18_sdr50; + pins_drv[2] = &host->hw->clk_drv_sd_18_sdr50; + } else if (strcmp(pinctl_names[i], "pinctl_ddr50") == 0) { + pins_drv[0] = &host->hw->cmd_drv_sd_18_ddr50; + pins_drv[1] = &host->hw->dat_drv_sd_18_ddr50; + pins_drv[2] = &host->hw->clk_drv_sd_18_ddr50; + } else { + continue; + } + + for (j = 0; j < sizeof(pins_names)/sizeof(pins_names[0]); j++) { + pins_node = of_get_child_by_name(pinctl_node, + pins_names[j]); + if (pins_node) + of_property_read_u8(pins_node, + "drive-strength", pins_drv[j]); + } + } + + return 0; +} + +/* Get msdc register settings + * 1. internal data delay for tuning, FIXME: can be removed when use data tune? + * 2. sample edge + */ +static int msdc_get_register_settings(struct msdc_host *host, struct device_node *np) +{ + struct device_node *register_setting_node = NULL; + int i; + + /* parse hw property settings */ + register_setting_node = of_parse_phandle(np, "register_setting", 0); + if (register_setting_node) { + for (i = 0; i < 8; i++) { + of_property_read_u8_array(register_setting_node, + "datrddly", host->hw->datrddly, 8); + } + + of_property_read_u8(register_setting_node, "datwrddly", + &host->hw->datwrddly); + of_property_read_u8(register_setting_node, "cmdrrddly", + &host->hw->cmdrrddly); + of_property_read_u8(register_setting_node, "cmdrddly", + &host->hw->cmdrddly); + + of_property_read_u8(register_setting_node, "cmd_edge", + &host->hw->cmd_edge); + of_property_read_u8(register_setting_node, "rdata_edge", + &host->hw->rdata_edge); + of_property_read_u8(register_setting_node, "wdata_edge", + &host->hw->wdata_edge); + } else { + pr_err("[msdc%d] register_setting is not found in DT\n", + host->id); + } + + return 0; +} + +/* + * msdc_of_parse() - parse host's device-tree node + * @host: host whose node should be parsed. + * + */ +int msdc_of_parse(struct mmc_host *mmc) +{ + struct device_node *np; + struct msdc_host *host = mmc_priv(mmc); + int len; + int ret; + + ret = mmc_of_parse(mmc); + if (ret) { + pr_err("%s: mmc of parse error!!: %d\n", __func__, ret); + return ret; + } + + np = mmc->parent->of_node; /* mmcx node in projectdts */ + + host->mmc = mmc; /* msdc_check_init_done() need */ + host->hw = kzalloc(sizeof(struct msdc_hw), GFP_KERNEL); + + /* iomap register */ + host->base = of_iomap(np, 0); + if (!host->base) { + pr_err("[msdc%d] of_iomap failed\n", mmc->index); + return -ENOMEM; + } + + /* get irq # */ + host->irq = irq_of_parse_and_map(np, 0); + pr_err("[msdc%d] get irq # %d\n", mmc->index, host->irq); + BUG_ON(host->irq < 0); + + /* get clk_src */ + #if !defined(FPGA_PLATFORM) + if (of_property_read_u8(np, "clk_src", &host->hw->clk_src)) { + pr_err("[msdc%d] error: clk_src isn't found in device tree.\n", + host->id); + BUG_ON(1); + } + #endif + + /* get msdc flag(caps)*/ + if (of_find_property(np, "msdc-sys-suspend", &len)) + host->hw->flags |= MSDC_SYS_SUSPEND; + + /* Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough.*/ + + if (of_property_read_u8(np, "host_function", &host->hw->host_function)) + pr_err("[msdc%d] host_function isn't found in device tree\n", + host->id); + + if (of_find_property(np, "bootable", &len)) + host->hw->boot = 1; + + /* get cd_gpio and cd_level */ + if (of_property_read_u32_index(np, "cd-gpios", 1, &cd_gpio) == 0) { + if (of_property_read_u8(np, "cd_level", &host->hw->cd_level)) + pr_err("[msdc%d] cd_level isn't found in device tree\n", + host->id); + } + + msdc_get_register_settings(host, np); + + #if !defined(FPGA_PLATFORM) + msdc_get_pinctl_settings(host, np); + + mmc->supply.vmmc = regulator_get(mmc_dev(mmc), "vmmc"); + mmc->supply.vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); + + #else + msdc_fpga_pwr_init(); + #endif + +#if defined(CFG_DEV_MSDC2) + if (host->hw->host_function == MSDC_SDIO) { + host->hw->flags |= MSDC_EXT_SDIO_IRQ; + host->hw->request_sdio_eirq = mt_sdio_ops[2].sdio_request_eirq; + host->hw->enable_sdio_eirq = mt_sdio_ops[2].sdio_enable_eirq; + host->hw->disable_sdio_eirq = mt_sdio_ops[2].sdio_disable_eirq; + host->hw->register_pm = mt_sdio_ops[2].sdio_register_pm; + } +#endif + + return 0; +} + +int msdc_dt_init(struct platform_device *pdev, struct mmc_host *mmc) +{ + struct msdc_host *host = mmc_priv(mmc); + unsigned int id = 0; + int ret; + static char const * const msdc_names[] = { + "msdc0", "msdc1", "msdc2", "msdc3"}; + static char const * const ioconfig_names[] = { + MSDC0_IOCFG_NAME, MSDC1_IOCFG_NAME, + MSDC2_IOCFG_NAME, MSDC3_IOCFG_NAME + }; + struct device_node *np; + + pr_err("DT probe %s!\n", pdev->dev.of_node->name); + + for (id = 0; id < HOST_MAX_NUM; id++) { + if (0 == strcmp(pdev->dev.of_node->name, msdc_names[id])) { + pdev->id = id; + break; + } + } + + if (id == HOST_MAX_NUM) { + pr_err("%s: Can not find msdc host\n", __func__); + return 1; + } + + ret = msdc_of_parse(mmc); + if (ret) { + pr_err("msdc%d of parse fail!!: %d\n", id, ret); + return ret; + } + + host = mmc_priv(mmc); + host->id = id; + + if (gpio_base == NULL) { + np = of_find_compatible_node(NULL, NULL, "mediatek,GPIO"); + gpio_base = of_iomap(np, 0); + pr_debug("of_iomap for gpio base @ 0x%p\n", gpio_base); + } + + if (msdc_io_cfg_bases[id] == NULL) { + np = of_find_compatible_node(NULL, NULL, ioconfig_names[id]); + msdc_io_cfg_bases[id] = of_iomap(np, 0); + pr_debug("of_iomap for MSDC%d IOCFG base @ 0x%p\n", + id, msdc_io_cfg_bases[id]); + } + +#ifndef FPGA_PLATFORM + if (infracfg_ao_reg_base == NULL) { + np = of_find_compatible_node(NULL, NULL, + "mediatek,infracfg_ao"); + infracfg_ao_reg_base = of_iomap(np, 0); + pr_debug("of_iomap for infracfg_ao base @ 0x%p\n", + infracfg_ao_reg_base); + } + + if (toprgu_reg_base == NULL) { + np = of_find_compatible_node(NULL, NULL, "mediatek,toprgu"); + toprgu_reg_base = of_iomap(np, 0); + pr_debug("of_iomap for toprgu base @ 0x%p\n", + toprgu_reg_base); + } + + if (apmixed_reg_base == NULL) { + np = of_find_compatible_node(NULL, NULL, "mediatek,apmixed"); + apmixed_reg_base = of_iomap(np, 0); + pr_err("of_iomap for apmixed base @ 0x%p\n", + apmixed_reg_base); + } + + if (topckgen_reg_base == NULL) { + np = of_find_compatible_node(NULL, NULL, + "mediatek,mt6755-topckgen"); + topckgen_reg_base = of_iomap(np, 0); + pr_err("of_iomap for topckgen base @ 0x%p\n", + topckgen_reg_base); + } +#endif + + return 0; +} + diff --git a/drivers/mmc/host/mediatek/mt6755/msdc_io.h b/drivers/mmc/host/mediatek/mt6755/msdc_io.h new file mode 100644 index 0000000000000000000000000000000000000000..6d8b9554d7009cdece8ba7161ba1828b2e4340e8 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/msdc_io.h @@ -0,0 +1,696 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MSDC_IO_H_ +#define _MSDC_IO_H_ + +/**************************************************************/ +/* Section 1: Device Tree */ +/**************************************************************/ +#include +#include +#include +#include +#include + +#include "mt_sd.h" +#include + +extern const struct of_device_id msdc_of_ids[]; +extern unsigned int cd_gpio; + +extern void __iomem *gpio_base; +extern void __iomem *infracfg_ao_reg_base; +extern void __iomem *pericfg_reg_base; +extern void __iomem *apmixed_reg_base; +extern void __iomem *topckgen_reg_base; + +int msdc_dt_init(struct platform_device *pdev, struct mmc_host *mmc); + +#ifdef FPGA_PLATFORM +void msdc_fpga_pwr_init(void); +#endif + +/* Names used for device tree lookup */ +#define DT_COMPATIBLE_NAME "mediatek,mt6755-mmc" +#define MSDC0_CLK_NAME "MSDC0-CLOCK" +#define MSDC1_CLK_NAME "MSDC1-CLOCK" +#define MSDC2_CLK_NAME "MSDC2-CLOCK" +#define MSDC3_CLK_NAME "MSDC3-CLOCK" +#define MSDC0_IOCFG_NAME "mediatek,iocfg_5" +#define MSDC1_IOCFG_NAME "mediatek,iocfg_0" +#define MSDC2_IOCFG_NAME "mediatek,iocfg_4" +#define MSDC3_IOCFG_NAME "NOT EXIST" + +/**************************************************************/ +/* Section 2: Power */ +/**************************************************************/ +#include + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +/*#include */ +#define REG_VEMC_VOSEL_CAL PMIC_RG_VEMC33_CAL_ADDR +#define REG_VEMC_VOSEL PMIC_RG_VEMC33_VOSEL_ADDR +#define REG_VEMC_EN PMIC_LDO_VEMC33_EN_ADDR +#define REG_VEMC_DL_EN PMIC_RG_VEMC33_DL_EN_ADDR +#define REG_VEMC_CL_EN PMIC_RG_VEMC33_CL_EN_ADDR + +#define REG_VMC_VOSEL_CAL PMIC_RG_VMC_CAL_ADDR +#define REG_VMC_VOSEL PMIC_RG_VMC_VOSEL_ADDR +#define REG_VMC_EN PMIC_LDO_VMC_EN_ADDR +#define REG_VMC_DL_EN PMIC_RG_VMC_DL_EN_ADDR +#define REG_VMC_CL_EN PMIC_RG_VMC_CL_EN_ADDR +#define REG_VMCH_VOSEL_CAL PMIC_RG_VMCH_CAL_ADDR +#define REG_VMCH_VOSEL PMIC_RG_VMCH_VOSEL_ADDR +#define REG_VMCH_EN PMIC_LDO_VMCH_EN_ADDR +#define REG_VMCH_DL_EN PMIC_RG_VMCH_DL_EN_ADDR +#define REG_VMCH_CL_EN PMIC_RG_VMCH_CL_EN_ADDR +#define REG_VMCH_OC_STATUS PMIC_OC_STATUS_VMCH_ADDR +#define REG_VMCH_RAMPUP_SEL PMIC_LDO_VMCH_STBTD_ADDR + +#define MASK_VEMC_VOSEL_CAL PMIC_RG_VEMC33_CAL_MASK +#define SHIFT_VEMC_VOSEL_CAL PMIC_RG_VEMC33_CAL_SHIFT +#define FIELD_VEMC_VOSEL_CAL (MASK_VEMC_VOSEL_CAL \ + << SHIFT_VEMC_VOSEL_CAL) +#define MASK_VEMC_VOSEL PMIC_RG_VEMC33_VOSEL_MASK +#define SHIFT_VEMC_VOSEL PMIC_RG_VEMC33_VOSEL_SHIFT +#define FIELD_VEMC_VOSEL (MASK_VEMC_VOSEL << SHIFT_VEMC_VOSEL) +#define MASK_VEMC_EN PMIC_LDO_VEMC33_EN_MASK +#define SHIFT_VEMC_EN PMIC_LDO_VEMC33_EN_SHIFT +#define FIELD_VEMC_EN (MASK_VEMC_EN << SHIFT_VEMC_EN) +#define MASK_VEMC_DL_EN PMIC_RG_VEMC33_DL_EN_MASK +#define SHIFT_VEMC_DL_EN PMIC_RG_VEMC33_DL_EN_SHIFT +#define FIELD_VEMC_DL_EN (MASK_VEMC_DL_EN << SHIFT_VEMC_DL_EN) +#define MASK_VEMC_CL_EN PMIC_RG_VEMC33_CL_EN_MASK +#define SHIFT_VEMC_CL_EN PMIC_RG_VEMC33_CL_EN_SHIFT +#define FIELD_VEMC_CL_EN (MASK_VEMC_CL_EN << SHIFT_VEMC_CL_EN) + +#define MASK_VMC_VOSEL_CAL PMIC_RG_VMC_CAL_MASK +#define SHIFT_VMC_VOSEL_CAL PMIC_RG_VMC_CAL_SHIFT +#define FIELD_VMC_VOSEL_CAL (MASK_VMC_VOSEL_CAL \ + << SHIFT_VMC_VOSEL_CAL) +#define MASK_VMC_VOSEL PMIC_RG_VMC_VOSEL_MASK +#define SHIFT_VMC_VOSEL PMIC_RG_VMC_VOSEL_SHIFT +#define FIELD_VMC_VOSEL (MASK_VMC_VOSEL << SHIFT_VMC_VOSEL) +#define MASK_VMC_EN PMIC_LDO_VMC_EN_MASK +#define SHIFT_VMC_EN PMIC_LDO_VMC_EN_SHIFT +#define FIELD_VMC_EN (MASK_VMC_EN << SHIFT_VMC_EN) +#define MASK_VMC_DL_EN PMIC_RG_VMC_DL_EN_MASK +#define SHIFT_VMC_DL_EN PMIC_RG_VMC_DL_EN_SHIFT +#define FIELD_VMC_DL_EN (MASK_VMC_DL_EN << SHIFT_VMC_DL_EN) +#define MASK_VMC_CL_EN PMIC_RG_VMC_CL_EN_MASK +#define SHIFT_VMC_CL_EN PMIC_RG_VMC_CL_EN_SHIFT +#define FIELD_VMC_CL_EN (MASK_VMC_CL_EN << SHIFT_VMC_CL_EN) + +#define MASK_VMCH_VOSEL_CAL PMIC_RG_VMCH_CAL_MASK +#define SHIFT_VMCH_VOSEL_CAL PMIC_RG_VMCH_CAL_SHIFT +#define FIELD_VMCH_VOSEL_CAL (MASK_VMCH_VOSEL_CAL \ + << SHIFT_VMCH_VOSEL_CAL) +#define MASK_VMCH_VOSEL PMIC_RG_VMCH_VOSEL_MASK +#define SHIFT_VMCH_VOSEL PMIC_RG_VMCH_VOSEL_SHIFT +#define FIELD_VMCH_VOSEL (MASK_VMCH_VOSEL << SHIFT_VMCH_VOSEL) +#define MASK_VMCH_EN PMIC_LDO_VMCH_EN_MASK +#define SHIFT_VMCH_EN PMIC_LDO_VMCH_EN_SHIFT +#define FIELD_VMCH_EN (MASK_VMCH_EN << SHIFT_VMCH_EN) +#define MASK_VMCH_DL_EN PMIC_RG_VMCH_DL_EN_MASK +#define SHIFT_VMCH_DL_EN PMIC_RG_VMCH_DL_EN_SHIFT +#define FIELD_VMCH_DL_EN (MASK_VMCH_DL_EN << SHIFT_VMCH_DL_EN) +#define MASK_VMCH_CL_EN PMIC_RG_VMCH_CL_EN_MASK +#define SHIFT_VMCH_CL_EN PMIC_RG_VMCH_CL_EN_SHIFT +#define FIELD_VMCH_CL_EN (MASK_VMCH_CL_EN << SHIFT_VMCH_CL_EN) +#define MASK_VMCH_OC_STATUS PMIC_OC_STATUS_VMCH_MASK +#define SHIFT_VMCH_OC_STATUS PMIC_OC_STATUS_VMCH_SHIFT +#define FIELD_VMCH_OC_STATUS (MASK_VMCH_OC_STATUS \ + << SHIFT_VMCH_OC_STATUS) +#define MASK_VMCH_RAMPUP_SEL PMIC_LDO_VMCH_STBTD_MASK +#define SHIFT_VMCH_RAMPUP_SEL PMIC_LDO_VMCH_STBTD_SHIFT +#define FIELD_VMCH_RAMPUP_SEL (PMIC_LDO_VMCH_STBTD_MASK \ + << PMIC_LDO_VMCH_STBTD_SHIFT) + +#define VEMC_VOSEL_CAL_mV(cal) ((cal <= 0) ? \ + ((0-(cal))/20) : (16-(cal)/20)) +#define VEMC_VOSEL_2V9 (0) +#define VEMC_VOSEL_3V (1) +#define VEMC_VOSEL_3V3 (2) +#define VMC_VOSEL_1V8 (3) +#define VMC_VOSEL_2V9 (5) +#define VMC_VOSEL_3V (6) +#define VMC_VOSEL_3V3 (7) +#define VMC_VOSEL_CAL_mV(cal) ((cal <= 0) ? \ + ((0-(cal))/20) : (16-(cal)/20)) +#define VMCH_VOSEL_CAL_mV(cal) ((cal <= 0) ? \ + ((0-(cal))/20) : (16-(cal)/20)) +#define VMCH_VOSEL_2V9 (0) +#define VMCH_VOSEL_3V (1) +#define VMCH_VOSEL_3V3 (2) + +#define REG_VCORE_VOSEL_SW PMIC_BUCK_VCORE_VOSEL_ADDR +#define VCORE_VOSEL_SW_MASK PMIC_BUCK_VCORE_VOSEL_MASK +#define VCORE_VOSEL_SW_SHIFT PMIC_BUCK_VCORE_VOSEL_SHIFT +#define REG_VCORE_VOSEL_HW PMIC_BUCK_VCORE_VOSEL_ON_ADDR +#define VCORE_VOSEL_HW_MASK PMIC_BUCK_VCORE_VOSEL_ON_MASK +#define VCORE_VOSEL_HW_SHIFT PMIC_BUCK_VCORE_VOSEL_ON_SHIFT + +#define REG_VIO18_CAL PMIC_RG_VIO18_CAL_ADDR +#define VIO18_CAL_MASK PMIC_RG_VIO18_CAL_MASK +#define VIO18_CAL_SHIFT PMIC_RG_VIO18_CAL_SHIFT + +#define EMMC_VOL_ACTUAL VOL_3000 +#define SD_VOL_ACTUAL VOL_3000 + +#else +#define REG_VEMC_VOSEL_CAL MT6351_PMIC_RG_VEMC_CAL_ADDR +#define REG_VEMC_VOSEL MT6351_PMIC_RG_VEMC_VOSEL_ADDR +#define REG_VEMC_EN MT6351_PMIC_RG_VEMC_EN_ADDR +#define REG_VMC_VOSEL_CAL MT6351_PMIC_RG_VMC_CAL_ADDR +#define REG_VMC_VOSEL MT6351_PMIC_RG_VMC_VOSEL_ADDR +#define REG_VMC_EN MT6351_PMIC_RG_VMC_EN_ADDR +#define REG_VMCH_VOSEL_CAL MT6351_PMIC_RG_VMCH_CAL_ADDR +#define REG_VMCH_VOSEL MT6351_PMIC_RG_VMCH_VOSEL_ADDR +#define REG_VMCH_EN MT6351_PMIC_RG_VMCH_EN_ADDR + +#define MASK_VEMC_VOSEL_CAL MT6351_PMIC_RG_VEMC_CAL_MASK +#define SHIFT_VEMC_VOSEL_CAL MT6351_PMIC_RG_VEMC_CAL_SHIFT +#define FIELD_VEMC_VOSEL_CAL (MASK_VEMC_VOSEL_CAL \ + << SHIFT_VEMC_VOSEL_CAL) +#define MASK_VEMC_VOSEL MT6351_PMIC_RG_VEMC_VOSEL_MASK +#define SHIFT_VEMC_VOSEL MT6351_PMIC_RG_VEMC_VOSEL_SHIFT +#define FIELD_VEMC_VOSEL (MASK_VEMC_VOSEL << SHIFT_VEMC_VOSEL) +#define MASK_VEMC_EN MT6351_PMIC_RG_VEMC_EN_MASK +#define SHIFT_VEMC_EN MT6351_PMIC_RG_VEMC_EN_SHIFT +#define FIELD_VEMC_EN (MASK_VEMC_EN << SHIFT_VEMC_EN) +#define MASK_VMC_VOSEL_CAL MT6351_PMIC_RG_VMC_CAL_MASK +#define SHIFT_VMC_VOSEL_CAL MT6351_PMIC_RG_VMC_CAL_SHIFT +#define MASK_VMC_VOSEL MT6351_PMIC_RG_VMC_VOSEL_MASK +#define SHIFT_VMC_VOSEL MT6351_PMIC_RG_VMC_VOSEL_SHIFT +#define FIELD_VMC_VOSEL (MASK_VMC_VOSEL << SHIFT_VMC_VOSEL) +#define MASK_VMC_EN MT6351_PMIC_RG_VMC_EN_MASK +#define SHIFT_VMC_EN MT6351_PMIC_RG_VMC_EN_SHIFT +#define FIELD_VMC_EN (MASK_VMC_EN << SHIFT_VMC_EN) +#define MASK_VMCH_VOSEL_CAL MT6351_PMIC_RG_VMCH_CAL_MASK +#define SHIFT_VMCH_VOSEL_CAL MT6351_PMIC_RG_VMCH_CAL_SHIFT +#define FIELD_VMCH_VOSEL_CAL (MASK_VMCH_VOSEL_CAL \ + << SHIFT_VMCH_VOSEL_CAL) +#define MASK_VMCH_VOSEL MT6351_PMIC_RG_VMCH_VOSEL_MASK +#define SHIFT_VMCH_VOSEL MT6351_PMIC_RG_VMCH_VOSEL_SHIFT +#define FIELD_VMCH_VOSEL (MASK_VMCH_VOSEL << SHIFT_VMCH_VOSEL) +#define MASK_VMCH_EN MT6351_PMIC_RG_VMCH_EN_MASK +#define SHIFT_VMCH_EN MT6351_PMIC_RG_VMCH_EN_SHIFT +#define FIELD_VMCH_EN (MASK_VMCH_EN << SHIFT_VMCH_EN) + +#define REG_VMCH_OC_STATUS MT6351_PMIC_OC_STATUS_VMCH_ADDR +#define MASK_VMCH_OC_STATUS MT6351_PMIC_OC_STATUS_VMCH_MASK +#define SHIFT_VMCH_OC_STATUS MT6351_PMIC_OC_STATUS_VMCH_SHIFT +#define FIELD_VMCH_OC_STATUS (MASK_VMCH_OC_STATUS \ + << SHIFT_VMCH_OC_STATUS) + +#define VEMC_VOSEL_CAL_mV(cal) ((cal <= 0) ? \ + ((0-(cal))/20) : (32-(cal)/20)) +#define VEMC_VOSEL_3V (0) +#define VEMC_VOSEL_3V3 (1) +#define VMC_VOSEL_1V8 (3) +#define VMC_VOSEL_2V8 (5) +#define VMC_VOSEL_3V (6) +#define VMC_VOSEL_CAL_mV(cal) ((cal <= 0) ? \ + ((0-(cal))/20) : (32-(cal)/20)) +#define VMCH_VOSEL_CAL_mV(cal) ((cal <= 0) ? \ + ((0-(cal))/20) : (32-(cal)/20)) +#define VMCH_VOSEL_3V (0) +#define VMCH_VOSEL_3V3 (1) + +#define REG_VCORE_VOSEL_SW MT6351_PMIC_BUCK_VCORE_VOSEL_ADDR +#define VCORE_VOSEL_SW_MASK MT6351_PMIC_BUCK_VCORE_VOSEL_MASK +#define VCORE_VOSEL_SW_SHIFT MT6351_PMIC_BUCK_VCORE_VOSEL_SHIFT +#define REG_VCORE_VOSEL_HW MT6351_PMIC_BUCK_VCORE_VOSEL_ON_ADDR +#define VCORE_VOSEL_HW_MASK MT6351_PMIC_BUCK_VCORE_VOSEL_ON_MASK +#define VCORE_VOSEL_HW_SHIFT MT6351_PMIC_BUCK_VCORE_VOSEL_ON_SHIFT +#define REG_VIO18_CAL MT6351_PMIC_RG_VIO18_CAL_ADDR +#define VIO18_CAL_MASK MT6351_PMIC_RG_VIO18_CAL_MASK +#define VIO18_CAL_SHIFT MT6351_PMIC_RG_VIO18_CAL_SHIFT + +#define EMMC_VOL_ACTUAL VOL_2900 +#define SD_VOL_ACTUAL VOL_3000 +#endif + +void msdc_sd_power_switch(struct msdc_host *host, u32 on); + +#if !defined(FPGA_PLATFORM) +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) +#define MSDC_POWER_DL_CL_FOR_POWER_OFF (0) +#define MSDC_POWER_DL_CL_FOR_POWER_ON (1) +#define MSDC_POWER_DL_CL_FOR_NO_LOAD (2) +#define MSDC_POWER_DL_CL_FOR_HAS_LOAD (3) +void msdc_power_DL_CL_control(struct msdc_host *host, u32 sel); +#endif +void msdc_power_calibration_init(struct msdc_host *host); +void msdc_oc_check(struct msdc_host *host); +void msdc_emmc_power(struct msdc_host *host, u32 on); +void msdc_sd_power(struct msdc_host *host, u32 on); +void msdc_sdio_power(struct msdc_host *host, u32 on); +void msdc_sd_power_off(void); +void msdc_dump_ldo_sts(struct msdc_host *host); +void msdc_HQA_set_vcore(struct msdc_host *host); +int msdc_regulator_set_and_enable(struct regulator *reg, int powerVolt); +#endif + +#ifdef FPGA_PLATFORM +void msdc_fpga_power(struct msdc_host *host, u32 on); +bool hwPowerOn_fpga(void); +bool hwPowerDown_fpga(void); +bool hwPowerDown_fpga(void); +#define msdc_emmc_power msdc_fpga_power +#define msdc_sd_power msdc_fpga_power +#define msdc_sdio_power msdc_fpga_power +#define msdc_sd_power_off() +#define msdc_dump_ldo_sts(host) +#endif + +extern u32 g_msdc0_io; +extern u32 g_msdc0_flash; +extern u32 g_msdc1_io; +extern u32 g_msdc1_flash; +extern u32 g_msdc2_io; +extern u32 g_msdc2_flash; +extern u32 g_msdc3_io; +extern u32 g_msdc3_flash; + +/**************************************************************/ +/* Section 3: Clock */ +/**************************************************************/ +#if defined(FPGA_PLATFORM) +#define msdc_dump_clock_sts() +extern u32 hclks_msdc[]; +#define msdc_get_hclks(host) hclks_msdc +#define msdc_clk_enable(host) +#define msdc_clk_disable(host) +#endif + +#if !defined(FPGA_PLATFORM) +void msdc_dump_clock_sts(void); +/* define clock related register macro */ +#define MSDCPLL_CON0_OFFSET (0x250) +#define MSDCPLL_CON1_OFFSET (0x254) +#define MSDCPLL_PWR_CON0_OFFSET (0x25C) + +#define MSDC_CLK_UPDATE_OFFSET (0x004) +#define MSDC_CLK_CFG_3_OFFSET (0x070) +#define MSDC_CLK_CFG_4_OFFSET (0x080) + +#define MSDC_INFRA_PDN_SET1_OFFSET (0x0088) +#define MSDC_INFRA_PDN_CLR1_OFFSET (0x008c) +#define MSDC_INFRA_PDN_STA1_OFFSET (0x0094) + +extern u32 *hclks_msdc_all[]; +#define msdc_get_hclks(id) hclks_msdc_all[id] + +int msdc_get_ccf_clk_pointer(struct platform_device *pdev, + struct msdc_host *host); +#define msdc_clk_enable(host) clk_enable(host->clock_control) +#define msdc_clk_disable(host) clk_disable(host->clock_control) + +#endif + +#define MSDC0_SRC_0 260000 +#define MSDC0_SRC_1 400000000 +#define MSDC0_SRC_2 200000000 +#define MSDC0_SRC_3 156000000 +#define MSDC0_SRC_4 182000000 +#define MSDC0_SRC_5 156000000 +#define MSDC0_SRC_6 100000000 +#define MSDC0_SRC_7 624000000 +#define MSDC0_SRC_8 312000000 + +#define MSDC1_SRC_0 260000 +#define MSDC1_SRC_1 208000000 +#define MSDC1_SRC_2 100000000 +#define MSDC1_SRC_3 156000000 +#define MSDC1_SRC_4 182000000 +#define MSDC1_SRC_5 156000000 +#define MSDC1_SRC_6 178000000 +#define MSDC1_SRC_7 200000000 + +#define MSDC3_SRC_0 260000 +#define MSDC3_SRC_1 50000000 +#define MSDC3_SRC_2 100000000 +#define MSDC3_SRC_3 156000000 +#define MSDC3_SRC_4 48000000 +#define MSDC3_SRC_5 156000000 +#define MSDC3_SRC_6 178000000 +#define MSDC3_SRC_7 54000000 +#define MSDC3_SRC_8 25000000 + +#define MSDC0_CG_NAME MT_CG_INFRA0_MSDC0_CG_STA +#define MSDC1_CG_NAME MT_CG_INFRA0_MSDC1_CG_STA +#define MSDC2_CG_NAME MT_CG_INFRA0_MSDC2_CG_STA +#define MSDC3_CG_NAME MT_CG_INFRA0_MSDC3_CG_STA + +/**************************************************************/ +/* Section 4: GPIO and Pad */ +/**************************************************************/ +/******************************************************************************* + *PINMUX and GPIO definition + ******************************************************************************/ + +#define MSDC_PIN_PULL_NONE (0) +#define MSDC_PIN_PULL_DOWN (1) +#define MSDC_PIN_PULL_UP (2) +#define MSDC_PIN_KEEP (3) + +/* add pull down/up mode define */ +#define MSDC_GPIO_PULL_UP (0) +#define MSDC_GPIO_PULL_DOWN (1) + +#define MSDC_TDRDSEL_SLEEP (0) +#define MSDC_TDRDSEL_3V (1) +#define MSDC_TDRDSEL_1V8 (2) +#define MSDC_TDRDSEL_CUST (3) + +/*--------------------------------------------------------------------------*/ +/* MSDC0~3 GPIO and IO Pad Configuration Base */ +/*--------------------------------------------------------------------------*/ +#define MSDC_GPIO_BASE gpio_base +#define MSDC0_IO_PAD_BASE (msdc_io_cfg_bases[0]) +#define MSDC1_IO_PAD_BASE (msdc_io_cfg_bases[1]) +#define MSDC2_IO_PAD_BASE (msdc_io_cfg_bases[2]) +#define MSDC3_IO_PAD_BASE (msdc_io_cfg_bases[3]) + +/*--------------------------------------------------------------------------*/ +/* MSDC GPIO Related Register */ +/*--------------------------------------------------------------------------*/ +#define MSDC0_GPIO_MODE18 (MSDC_GPIO_BASE + 0x410) +#define MSDC0_GPIO_MODE19 (MSDC_GPIO_BASE + 0x420) +#define MSDC0_GPIO_IES_ADDR (MSDC0_IO_PAD_BASE + 0x000) +#define MSDC0_GPIO_SMT_ADDR (MSDC0_IO_PAD_BASE + 0x010) +#define MSDC0_GPIO_TDSEL_ADDR (MSDC0_IO_PAD_BASE + 0x020) +#define MSDC0_GPIO_RDSEL_ADDR (MSDC0_IO_PAD_BASE + 0x040) +#define MSDC0_GPIO_SR_ADDR (MSDC0_IO_PAD_BASE + 0x0a0) +#define MSDC0_GPIO_DRV_ADDR (MSDC0_IO_PAD_BASE + 0x0a0) +#define MSDC0_GPIO_PUPD0_ADDR (MSDC0_IO_PAD_BASE + 0x0c0) +#define MSDC0_GPIO_PUPD1_ADDR (MSDC0_IO_PAD_BASE + 0x0d0) + +#define MSDC1_GPIO_MODE4 (MSDC_GPIO_BASE + 0x330) +#define MSDC1_GPIO_IES_ADDR (MSDC1_IO_PAD_BASE + 0x000) +#define MSDC1_GPIO_SMT_ADDR (MSDC1_IO_PAD_BASE + 0x010) +#define MSDC1_GPIO_TDSEL_ADDR (MSDC1_IO_PAD_BASE + 0x030) +#define MSDC1_GPIO_RDSEL0_ADDR (MSDC1_IO_PAD_BASE + 0x040) +#define MSDC1_GPIO_RDSEL1_ADDR (MSDC1_IO_PAD_BASE + 0x050) +#define MSDC1_GPIO_SR_ADDR (MSDC1_IO_PAD_BASE + 0x0b0) +#define MSDC1_GPIO_DRV_ADDR (MSDC1_IO_PAD_BASE + 0x0b0) +#define MSDC1_GPIO_PUPD_ADDR (MSDC1_IO_PAD_BASE + 0x0c0) + +#define MSDC2_GPIO_MODE14 (MSDC_GPIO_BASE + 0x3D0) +#define MSDC2_GPIO_IES_ADDR (MSDC2_IO_PAD_BASE + 0x000) +#define MSDC2_GPIO_SMT_ADDR (MSDC2_IO_PAD_BASE + 0x010) +#define MSDC2_GPIO_TDSEL_ADDR (MSDC2_IO_PAD_BASE + 0x020) +#define MSDC2_GPIO_RDSEL_ADDR (MSDC2_IO_PAD_BASE + 0x040) +#define MSDC2_GPIO_SR_ADDR (MSDC2_IO_PAD_BASE + 0x0a0) +#define MSDC2_GPIO_DRV_ADDR (MSDC2_IO_PAD_BASE + 0x0a0) +#define MSDC2_GPIO_PUPD_ADDR0 (MSDC2_IO_PAD_BASE + 0x0c0) +#define MSDC2_GPIO_PUPD_ADDR1 (MSDC2_IO_PAD_BASE + 0x0d0) + +/* + * MSDC0 GPIO and PAD register and bitfields definition + */ +/*MSDC0_GPIO_MODE19, Set as pinmux value as 1*/ +#define MSDC0_MODE_DAT7_MASK (7 << 25) +#define MSDC0_MODE_DAT6_MASK (7 << 9) +#define MSDC0_MODE_DAT5_MASK (7 << 6) +#define MSDC0_MODE_DAT4_MASK (7 << 12) +#define MSDC0_MODE_DAT3_MASK (7 << 22) +#define MSDC0_MODE_DAT2_MASK (7 << 19) +#define MSDC0_MODE_DAT1_MASK (7 << 3) +#define MSDC0_MODE_CMD_MASK (7 << 0) +#define MSDC0_MODE_DSL_MASK (7 << 28) +#define MSDC0_MODE_RST_MASK (7 << 16) + +/*MSDC0_GPIO_MODE18, Set as pinmux value as 1*/ +#define MSDC0_MODE_DAT0_MASK (7 << 25) +#define MSDC0_MODE_CLK_MASK (7 << 28) + +/* MSDC0 IES mask*/ +#define MSDC0_IES_DAT_MASK (0x1 << 0) +#define MSDC0_IES_CLK_MASK (0x1 << 1) +#define MSDC0_IES_CMD_MASK (0x1 << 2) +#define MSDC0_IES_RSTB_MASK (0x1 << 3) +#define MSDC0_IES_DSL_MASK (0x1 << 4) +#define MSDC0_IES_ALL_MASK (0x1F << 0) + +/* MSDC0 SMT mask*/ +#define MSDC0_SMT_DAT_MASK (0x1 << 0) +#define MSDC0_SMT_CLK_MASK (0x1 << 1) +#define MSDC0_SMT_CMD_MASK (0x1 << 2) +#define MSDC0_SMT_RSTB_MASK (0x1 << 3) +#define MSDC0_SMT_DSL_MASK (0x1 << 4) +#define MSDC0_SMT_ALL_MASK (0x1F << 0) + +/* MSDC0 TDSEL mask*/ +#define MSDC0_TDSEL_DAT_MASK (0xF << 0) +#define MSDC0_TDSEL_CLK_MASK (0xF << 4) +#define MSDC0_TDSEL_CMD_MASK (0xF << 8) +#define MSDC0_TDSEL_RSTB_MASK (0xF << 12) +#define MSDC0_TDSEL_DSL_MASK (0xF << 16) +#define MSDC0_TDSEL_ALL_MASK (0xFFFFF << 0) + +/* MSDC0 RDSEL mask*/ +#define MSDC0_RDSEL_DAT_MASK (0x3F << 0) +#define MSDC0_RDSEL_CLK_MASK (0x3F << 6) +#define MSDC0_RDSEL_CMD_MASK (0x3F << 12) +#define MSDC0_RDSEL_RSTB_MASK (0x3F << 18) +#define MSDC0_RDSEL_DSL_MASK (0x3F << 24) +#define MSDC0_RDSEL_ALL_MASK (0x3FFFFFFF << 0) + +/* MSDC0 SR mask*/ +#define MSDC0_SR_DAT_MASK (0x1 << 3) +#define MSDC0_SR_CLK_MASK (0x1 << 7) +#define MSDC0_SR_CMD_MASK (0x1 << 11) +#define MSDC0_SR_RSTB_MASK (0x1 << 15) +#define MSDC0_SR_DSL_MASK (0x1 << 19) +/*Attention: bits are not continuous, shall not define MSDC0_SR_ALL_MASK*/ + +/* MSDC0 DRV mask*/ +#define MSDC0_DRV_DAT_MASK (0x7 << 0) +#define MSDC0_DRV_CLK_MASK (0x7 << 4) +#define MSDC0_DRV_CMD_MASK (0x7 << 8) +#define MSDC0_DRV_RSTB_MASK (0x7 << 12) +#define MSDC0_DRV_DSL_MASK (0x7 << 16) +/*Attention: bits are not continuous, shall not define MSDC0_DRV_ALL_MASK*/ + +/* MSDC0 PUPD mask*/ +#define MSDC0_PUPD_DAT0_MASK (0x7 << 0) +#define MSDC0_PUPD_CLK_MASK (0x7 << 4) +#define MSDC0_PUPD_CMD_MASK (0x7 << 8) +#define MSDC0_PUPD_DAT1_MASK (0x7 << 12) +#define MSDC0_PUPD_DAT5_MASK (0x7 << 16) +#define MSDC0_PUPD_DAT6_MASK (0x7 << 20) +#define MSDC0_PUPD_DAT4_MASK (0x7 << 24) +#define MSDC0_PUPD_RSTB_MASK (0x7 << 28) +#define MSDC0_PUPD0_MASK_WITH_RSTB (0x77777777 << 0) +#define MSDC0_PUPD0_MASK (0x7777777 << 0) + +#define MSDC0_PUPD_DAT2_MASK (0x7 << 0) +#define MSDC0_PUPD_DAT3_MASK (0x7 << 4) +#define MSDC0_PUPD_DAT7_MASK (0x7 << 8) +#define MSDC0_PUPD_DSL_MASK (0x7 << 12) +#define MSDC0_PUPD1_MASK (0x7777 << 0) + +/* + * MSDC1 GPIO and PAD register and bitfields definition + */ +/*MSDC0_GPIO_MODE4, Set as pinmux value as 1*/ +#define MSDC1_MODE_CLK_MASK (7 << 0) +#define MSDC1_MODE_CMD_MASK (7 << 6) +#define MSDC1_MODE_DAT0_MASK (7 << 9) +#define MSDC1_MODE_DAT1_MASK (7 << 16) +#define MSDC1_MODE_DAT2_MASK (7 << 12) +#define MSDC1_MODE_DAT3_MASK (7 << 3) + +/* MSDC1 IES mask*/ +#define MSDC1_IES_CLK_MASK (0x1 << 8) +#define MSDC1_IES_DAT_MASK (0x1 << 9) +#define MSDC1_IES_CMD_MASK (0x1 << 10) +#define MSDC1_IES_ALL_MASK (0x7 << 8) + +/* MSDC1 SMT mask*/ +#define MSDC1_SMT_CLK_MASK (0x1 << 8) +#define MSDC1_SMT_DAT_MASK (0x1 << 9) +#define MSDC1_SMT_CMD_MASK (0x1 << 10) +#define MSDC1_SMT_ALL_MASK (0x7 << 8) + +/* MSDC1 TDSEL mask*/ +#define MSDC1_TDSEL_CLK_MASK (0xF << 0) +#define MSDC1_TDSEL_DAT_MASK (0xF << 4) +#define MSDC1_TDSEL_CMD_MASK (0xF << 8) +#define MSDC1_TDSEL_ALL_MASK (0xFFF << 0) + +/* MSDC1 RDSEL mask*/ +/*MSDC1_GPIO_RDSEL0*/ +#define MSDC1_RDSEL_CLK_MASK (0x3F << 16) +#define MSDC1_RDSEL_DAT_MASK (0x3F << 22) +/*MSDC1_GPIO_RDSEL1*/ +#define MSDC1_RDSEL_CMD_MASK (0x3F << 0) +#define MSDC1_RDSEL0_ALL_MASK (0xFFF << 16) +#define MSDC1_RDSEL1_ALL_MASK (0x3F << 0) +/*Attention: not the same address, shall not define MSDC1_RDSEL_ALL_MASK*/ + +/* MSDC1 SR mask*/ +#define MSDC1_SR_CLK_MASK (0x1 << 3) +#define MSDC1_SR_DAT_MASK (0x1 << 7) +#define MSDC1_SR_CMD_MASK (0x1 << 11) +/*Attention: bits are not continuous, shall not define MSDC1_SR_ALL_MASK*/ + +/* MSDC1 DRV mask*/ +#define MSDC1_DRV_CLK_MASK (0x7 << 0) +#define MSDC1_DRV_DAT_MASK (0x7 << 4) +#define MSDC1_DRV_CMD_MASK (0x7 << 8) +/*Attention: bits are not continuous, shall not define MSDC1_DRV_ALL_MASK*/ + +/* MSDC1 PUPD mask*/ +#define MSDC1_PUPD_CLK_MASK (0x7 << 4) +#define MSDC1_PUPD_DAT0_MASK (0x7 << 8) +#define MSDC1_PUPD_CMD_MASK (0x7 << 0) +#define MSDC1_PUPD_DAT1_MASK (0x7 << 12) +#define MSDC1_PUPD_DAT2_MASK (0x7 << 16) +#define MSDC1_PUPD_DAT3_MASK (0x7 << 20) +#define MSDC1_PUPD_MASK (0x777777 << 0) + +/* + * MSDC2 GPIO and PAD register and bitfields definition + */ +/*MSDC2_GPIO_MODE14, Set as pinmux value as 2*/ +#define MSDC2_MODE_CLK_MASK (7 << 9) +#define MSDC2_MODE_CMD_MASK (7 << 6) +#define MSDC2_MODE_DAT0_MASK (7 << 16) +#define MSDC2_MODE_DAT1_MASK (7 << 3) +#define MSDC2_MODE_DAT2_MASK (7 << 19) +#define MSDC2_MODE_DAT3_MASK (7 << 12) + +/* MSDC2 IES mask*/ +#define MSDC2_IES_CLK_MASK (0x1 << 5) +#define MSDC2_IES_CMD_MASK (0x1 << 4) +#define MSDC2_IES_DAT_MASK (0x1 << 3) +#define MSDC2_IES_ALL_MASK (0x7 << 3) + +/* MSDC2 SMT mask*/ +#define MSDC2_SMT_CLK_MASK (0x1 << 5) +#define MSDC2_SMT_CMD_MASK (0x1 << 4) +#define MSDC2_SMT_DAT_MASK (0x1 << 3) +#define MSDC2_SMT_ALL_MASK (0x7 << 3) + +/* MSDC2 TDSEL mask*/ +#define MSDC2_TDSEL_CLK_MASK (0xF << 20) +#define MSDC2_TDSEL_CMD_MASK (0xF << 16) +#define MSDC2_TDSEL_DAT_MASK (0xF << 12) +#define MSDC2_TDSEL_ALL_MASK (0xFFF << 12) + +/* MSDC2 RDSEL mask*/ +#define MSDC2_RDSEL_CLK_MASK (0x3 << 10) +#define MSDC2_RDSEL_CMD_MASK (0x3 << 8) +#define MSDC2_RDSEL_DAT_MASK (0x3 << 6) +#define MSDC2_RDSEL_ALL_MASK (0x3F << 6) + +/* MSDC2 SR mask*/ +#define MSDC2_SR_CLK_MASK (0x1 << 23) +#define MSDC2_SR_CMD_MASK (0x1 << 19) +#define MSDC2_SR_DAT_MASK (0x1 << 15) + +/* MSDC2 DRV mask*/ +#define MSDC2_DRV_CLK_MASK (0x7 << 20) +#define MSDC2_DRV_CMD_MASK (0x7 << 16) +#define MSDC2_DRV_DAT_MASK (0x7 << 12) + +/* MSDC2 PUPD mask*/ +#define MSDC2_PUPD_CLK_MASK (0x7 << 20) +#define MSDC2_PUPD_CMD_MASK (0x7 << 16) +#define MSDC2_PUPD_DAT1_MASK (0x7 << 12) +#define MSDC2_PUPD_DAT3_MASK (0x7 << 24) +#define MSDC2_PUPD_DAT0_MASK (0x7 << 28) +#define MSDC2_PUPD_MASK0 (0xFFFFF << 12) + +#define MSDC2_PUPD_DAT2_MASK (0x7 << 0) +#define MSDC2_PUPD_MASK1 (0xF << 0) + +#ifndef FPGA_PLATFORM +void msdc_set_driving_by_id(u32 id, struct msdc_hw *hw, bool sd_18); +void msdc_set_driving(struct msdc_host *host, struct msdc_hw *hw, bool sd_18); +void msdc_get_driving_by_id(u32 id, struct msdc_hw *hw); +void msdc_set_ies_by_id(u32 id, int set_ies); +void msdc_set_sr_by_id(u32 id, int clk, int cmd, int dat, int rst, int ds); +void msdc_set_smt_by_id(u32 id, int set_smt); +void msdc_set_tdsel_by_id(u32 id, u32 flag, u32 value); +void msdc_set_rdsel_by_id(u32 id, u32 flag, u32 value); +void msdc_get_tdsel_by_id(u32 id, u32 *value); +void msdc_get_rdsel_by_id(u32 id, u32 *value); +void msdc_dump_padctl_by_id(u32 id); +void msdc_pin_config_by_id(u32 id, u32 mode); +#endif + +#ifdef FPGA_PLATFORM +#define msdc_set_driving_by_id(id, hw, sd_18) +/*#define msdc_set_driving(host, hw, sd_18)*/ +#define msdc_get_driving_by_id(id, hw) +#define msdc_set_ies_by_id(id, set_ies) +#define msdc_set_sr_by_id(id, clk, cmd, dat, rst, ds) +#define msdc_set_smt_by_id(id, set_smt) +#define msdc_set_tdsel_by_id(id, flag, value) +#define msdc_set_rdsel_by_id(id, flag, value) +#define msdc_get_tdsel_by_id(id, value) +#define msdc_get_rdsel_by_id(id, value) +#define msdc_dump_padctl_by_id(id) +#define msdc_pin_config_by_id(id, mode) +#define msdc_set_pin_mode(host) + +void msdc_set_driving(struct msdc_host *host, struct msdc_hw *hw, bool sd_18) +{ + /* do nothing, but for build pass */ +} +#endif + +#define msdc_get_driving(host, hw) \ + msdc_get_driving_by_id(host->id, hw) + +/*#define msdc_set_driving(host, hw, sd_18) + msdc_set_driving_by_id(host->id, hw, sd_18)*/ + +#define msdc_set_ies(host, set_ies) \ + msdc_set_ies_by_id(host->id, set_ies) + +#define msdc_set_sr(host, clk, cmd, dat, rst, ds) \ + msdc_set_sr_by_id(host->id, clk, cmd, dat, rst, ds) + +#define msdc_set_smt(host, set_smt) \ + msdc_set_smt_by_id(host->id, set_smt) + +#define msdc_set_tdsel(host, flag, value) \ + msdc_set_tdsel_by_id(host->id, flag, value) + +#define msdc_set_rdsel(host, flag, value) \ + msdc_set_rdsel_by_id(host->id, flag, value) + +#define msdc_get_tdsel(host, value) \ + msdc_get_tdsel_by_id(host->id, value) + +#define msdc_get_rdsel(host, value) \ + msdc_get_rdsel_by_id(host->id, value) + +#define msdc_dump_padctl(host) \ + msdc_dump_padctl_by_id(host->id) + +#define msdc_pin_config(host, mode) \ + msdc_pin_config_by_id(host->id, mode) + +/**************************************************************/ +/* Section 5: MISC */ +/**************************************************************/ +void msdc_polling_axi_status(int line, int dead); + +#endif /* end of _MSDC_IO_H_ */ diff --git a/drivers/mmc/host/mediatek/mt6755/msdc_partition.c b/drivers/mmc/host/mediatek/mt6755/msdc_partition.c new file mode 100644 index 0000000000000000000000000000000000000000..b45a401f78def99caf52702547ce677e08008d68 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/msdc_partition.c @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mt_sd.h" +#include +#include +#include "dbg.h" + +u64 msdc_get_user_capacity(struct msdc_host *host) +{ + u64 capacity = 0; + u32 legacy_capacity = 0; + struct mmc_card *card; + + if ((host != NULL) && (host->mmc != NULL) && (host->mmc->card != NULL)) + card = host->mmc->card; + else + return 0; + + card = host->mmc->card; + if (mmc_card_mmc(card)) { + if (card->csd.read_blkbits) { + legacy_capacity = + (2 << (card->csd.read_blkbits - 1)) + * card->csd.capacity; + } else { + legacy_capacity = card->csd.capacity; + ERR_MSG("XXX read_blkbits = 0 XXX"); + } + capacity = + (u64)(card->ext_csd.sectors) * 512 > legacy_capacity ? + (u64)(card->ext_csd.sectors) * 512 : legacy_capacity; + } else if (mmc_card_sd(card)) { + capacity = (u64) (card->csd.capacity) + << (card->csd.read_blkbits); + } + return capacity; +} + +/*#ifdef MTK_MSDC_USE_CACHE*/ +unsigned long long g_cache_part_start; +unsigned long long g_cache_part_end; +unsigned long long g_usrdata_part_start; +unsigned long long g_usrdata_part_end; + +int msdc_can_apply_cache(unsigned long long start_addr, + unsigned int size) +{ + if (!g_cache_part_start && !g_cache_part_end && + !g_usrdata_part_start && !g_usrdata_part_end) + return 0; + + /* since cache, userdata partition are connected, + so check it as an area, else do check them separately */ + if (g_cache_part_end == g_usrdata_part_start) { + if ((start_addr < g_cache_part_start) || + (start_addr + size >= g_usrdata_part_end)) { + return 0; + } + } else { + if (((start_addr < g_cache_part_start) || + (start_addr + size >= g_cache_part_end)) + && ((start_addr < g_usrdata_part_start) || + (start_addr + size >= g_usrdata_part_end))) { + return 0; + } + } + + return 1; +} + +void msdc_get_cache_region(struct work_struct *work) +{ + struct hd_struct *lp_hd_struct = NULL; + + lp_hd_struct = get_part("cache"); + if (likely(lp_hd_struct)) { + g_cache_part_start = lp_hd_struct->start_sect; + g_cache_part_end = g_cache_part_start + lp_hd_struct->nr_sects; + put_part(lp_hd_struct); + } else { + g_cache_part_start = (sector_t)(-1); + g_cache_part_end = (sector_t)(-1); + pr_err("There is no cache info\n"); + } + + lp_hd_struct = NULL; + lp_hd_struct = get_part("userdata"); + if (likely(lp_hd_struct)) { + g_usrdata_part_start = lp_hd_struct->start_sect; + g_usrdata_part_end = g_usrdata_part_start + + lp_hd_struct->nr_sects; + put_part(lp_hd_struct); + } else { + g_usrdata_part_start = (sector_t)(-1); + g_usrdata_part_end = (sector_t)(-1); + pr_err("There is no userdata info\n"); + } + + pr_err("cache(0x%llX~0x%llX, usrdata(0x%llX~0x%llX)\n", + g_cache_part_start, g_cache_part_end, + g_usrdata_part_start, g_usrdata_part_end); +} + +EXPORT_SYMBOL(msdc_get_cache_region); +static struct delayed_work get_cache_info; +static int __init init_get_cache_work(void) +{ + INIT_DELAYED_WORK(&get_cache_info, msdc_get_cache_region); + schedule_delayed_work(&get_cache_info, 100); + return 0; +} + +u32 msdc_get_other_capacity(struct msdc_host *host, char *name) +{ + u32 device_other_capacity = 0; + int i; + struct mmc_card *card; + + if ((host != NULL) && (host->mmc != NULL) && (host->mmc->card != NULL)) + card = host->mmc->card; + else + return 0; + + for (i = 0; i < card->nr_parts; i++) { + if (!name) { + device_other_capacity += card->part[i].size; + } else if (strcmp(name, card->part[i].name) == 0) { + device_other_capacity = card->part[i].size; + break; + } + } + + return device_other_capacity; +} +/*#endif*/ + +u64 msdc_get_capacity(int get_emmc_total) +{ + u64 user_size = 0; + u32 other_size = 0; + u64 total_size = 0; + int index = 0; + struct msdc_host *host; + + for (index = 0; index < HOST_MAX_NUM; ++index) { + host = mtk_msdc_host[index]; + if ((host != NULL) && (host->hw->boot)) { + user_size = msdc_get_user_capacity(host); +#ifdef CONFIG_MTK_EMMC_SUPPORT + if (get_emmc_total) + other_size = + msdc_get_other_capacity(host, NULL); +#endif + break; + } + } + total_size = user_size + (u64) other_size; + return total_size / 512; +} +EXPORT_SYMBOL(msdc_get_capacity); + +#if defined(CONFIG_MTK_EMMC_SUPPORT) && defined(CONFIG_PROC_FS) +struct mmc_blk_data { + spinlock_t lock; + struct gendisk *disk; + struct mmc_queue queue; + + unsigned int usage; + unsigned int read_only; +}; + +struct gendisk *mmc_get_disk(struct mmc_card *card) +{ + struct mmc_blk_data *md; + /* struct gendisk *disk; */ + + BUG_ON(!card); + md = mmc_get_drvdata(card); + BUG_ON(!md || !md->disk); + + return md->disk; +} + +#if defined(CONFIG_PWR_LOSS_MTK_SPOH) +static struct proc_dir_entry *proc_emmc; + +static inline int emmc_proc_info(struct seq_file *m, struct hd_struct *this) +{ + char *no_partition_name = "n/a"; + + return seq_printf(m, "emmc_p%d: %8.8x %8.8x \"%s\"\n", this->partno, + (unsigned int)this->start_sect, + (unsigned int)this->nr_sects, + ((this->info) ? + (char *)(this->info->volname) : no_partition_name)); +} + +static int proc_emmc_show(struct seq_file *m, void *v) +{ + struct disk_part_iter piter; + struct hd_struct *part; + struct msdc_host *host; + struct gendisk *disk; + + /* emmc always in slot0 */ + host = msdc_get_host(MSDC_EMMC, MSDC_BOOT_EN, 0); + BUG_ON(!host || !host->mmc || !host->mmc->card); + disk = mmc_get_disk(host->mmc->card); + + seq_puts(m, "partno: start_sect nr_sects partition_name\n"); + disk_part_iter_init(&piter, disk, 0); + while ((part = disk_part_iter_next(&piter))) + emmc_proc_info(m, part); + disk_part_iter_exit(&piter); + + return 0; +} + +static int proc_emmc_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_emmc_show, NULL); +} + +static const struct file_operations proc_emmc_fops = { + .open = proc_emmc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void msdc_proc_emmc_create(void) +{ + proc_emmc = proc_create("emmc", 0, NULL, &proc_emmc_fops); +} +#endif +#endif + +#ifdef MTK_MSDC_USE_CACHE +late_initcall_sync(init_get_cache_work); +#endif diff --git a/drivers/mmc/host/mediatek/mt6755/msdc_reg.h b/drivers/mmc/host/mediatek/mt6755/msdc_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..b01db836b48425978d4dc11568549d06c546a9e2 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/msdc_reg.h @@ -0,0 +1,628 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MSDC_REG_H_ +#define _MSDC_REG_H_ + +#include +#include +#include + +/*--------------------------------------------------------------------------*/ +/* Common Macro */ +/*--------------------------------------------------------------------------*/ +#define REG_ADDR(x) ((volatile u32 *)(base + OFFSET_##x)) + +/*--------------------------------------------------------------------------*/ +/* Register Offset */ +/*--------------------------------------------------------------------------*/ +#define OFFSET_MSDC_CFG (0x0) +#define OFFSET_MSDC_IOCON (0x04) +#define OFFSET_MSDC_PS (0x08) +#define OFFSET_MSDC_INT (0x0c) +#define OFFSET_MSDC_INTEN (0x10) +#define OFFSET_MSDC_FIFOCS (0x14) +#define OFFSET_MSDC_TXDATA (0x18) +#define OFFSET_MSDC_RXDATA (0x1c) +#define OFFSET_SDC_CFG (0x30) +#define OFFSET_SDC_CMD (0x34) +#define OFFSET_SDC_ARG (0x38) +#define OFFSET_SDC_STS (0x3c) +#define OFFSET_SDC_RESP0 (0x40) +#define OFFSET_SDC_RESP1 (0x44) +#define OFFSET_SDC_RESP2 (0x48) +#define OFFSET_SDC_RESP3 (0x4c) +#define OFFSET_SDC_BLK_NUM (0x50) +#define OFFSET_SDC_VOL_CHG (0x54) +#define OFFSET_SDC_CSTS (0x58) +#define OFFSET_SDC_CSTS_EN (0x5c) +#define OFFSET_SDC_DCRC_STS (0x60) +#define OFFSET_EMMC_CFG0 (0x70) +#define OFFSET_EMMC_CFG1 (0x74) +#define OFFSET_EMMC_STS (0x78) +#define OFFSET_EMMC_IOCON (0x7c) +#define OFFSET_SDC_ACMD_RESP (0x80) +#define OFFSET_SDC_ACMD19_TRG (0x84) +#define OFFSET_SDC_ACMD19_STS (0x88) +#define OFFSET_MSDC_DMA_SA_HIGH (0x8C) +#define OFFSET_MSDC_DMA_SA (0x90) +#define OFFSET_MSDC_DMA_CA (0x94) +#define OFFSET_MSDC_DMA_CTRL (0x98) +#define OFFSET_MSDC_DMA_CFG (0x9c) +#define OFFSET_MSDC_DBG_SEL (0xa0) +#define OFFSET_MSDC_DBG_OUT (0xa4) +#define OFFSET_MSDC_DMA_LEN (0xa8) +#define OFFSET_MSDC_PATCH_BIT0 (0xb0) +#define OFFSET_MSDC_PATCH_BIT1 (0xb4) +#define OFFSET_MSDC_PATCH_BIT2 (0xb8) +#define OFFSET_DAT0_TUNE_CRC (0xc0) +#define OFFSET_DAT1_TUNE_CRC (0xc4) +#define OFFSET_DAT2_TUNE_CRC (0xc8) +#define OFFSET_DAT3_TUNE_CRC (0xcc) +#define OFFSET_CMD_TUNE_CRC (0xd0) +#define OFFSET_SDIO_TUNE_WIND (0xd4) +#define OFFSET_MSDC_PAD_TUNE0 (0xf0) +#define OFFSET_MSDC_PAD_TUNE1 (0xf4) +#define OFFSET_MSDC_DAT_RDDLY0 (0xf8) +#define OFFSET_MSDC_DAT_RDDLY1 (0xfc) +#define OFFSET_MSDC_DAT_RDDLY2 (0x100) +#define OFFSET_MSDC_DAT_RDDLY3 (0x104) +#define OFFSET_MSDC_HW_DBG (0x110) +#define OFFSET_MSDC_VERSION (0x114) +#define OFFSET_MSDC_ECO_VER (0x118) +#define OFFSET_EMMC50_PAD_CTL0 (0x180) +#define OFFSET_EMMC50_PAD_DS_CTL0 (0x184) +#define OFFSET_EMMC50_PAD_DS_TUNE (0x188) +#define OFFSET_EMMC50_PAD_CMD_TUNE (0x18c) +#define OFFSET_EMMC50_PAD_DAT01_TUNE (0x190) +#define OFFSET_EMMC50_PAD_DAT23_TUNE (0x194) +#define OFFSET_EMMC50_PAD_DAT45_TUNE (0x198) +#define OFFSET_EMMC50_PAD_DAT67_TUNE (0x19c) +#define OFFSET_EMMC51_CFG0 (0x204) +#define OFFSET_EMMC50_CFG0 (0x208) +#define OFFSET_EMMC50_CFG1 (0x20c) +#define OFFSET_EMMC50_CFG2 (0x21c) +#define OFFSET_EMMC50_CFG3 (0x220) +#define OFFSET_EMMC50_CFG4 (0x224) +#define OFFSET_EMMC50_BLOCK_LENGTH (0x228) + +/*--------------------------------------------------------------------------*/ +/* Register Address */ +/*--------------------------------------------------------------------------*/ +/* common register */ +#define MSDC_CFG REG_ADDR(MSDC_CFG) +#define MSDC_IOCON REG_ADDR(MSDC_IOCON) +#define MSDC_PS REG_ADDR(MSDC_PS) +#define MSDC_INT REG_ADDR(MSDC_INT) +#define MSDC_INTEN REG_ADDR(MSDC_INTEN) +#define MSDC_FIFOCS REG_ADDR(MSDC_FIFOCS) +#define MSDC_TXDATA REG_ADDR(MSDC_TXDATA) +#define MSDC_RXDATA REG_ADDR(MSDC_RXDATA) + +/* sdmmc register */ +#define SDC_CFG REG_ADDR(SDC_CFG) +#define SDC_CMD REG_ADDR(SDC_CMD) +#define SDC_ARG REG_ADDR(SDC_ARG) +#define SDC_STS REG_ADDR(SDC_STS) +#define SDC_RESP0 REG_ADDR(SDC_RESP0) +#define SDC_RESP1 REG_ADDR(SDC_RESP1) +#define SDC_RESP2 REG_ADDR(SDC_RESP2) +#define SDC_RESP3 REG_ADDR(SDC_RESP3) +#define SDC_BLK_NUM REG_ADDR(SDC_BLK_NUM) +#define SDC_VOL_CHG REG_ADDR(SDC_VOL_CHG) +#define SDC_CSTS REG_ADDR(SDC_CSTS) +#define SDC_CSTS_EN REG_ADDR(SDC_CSTS_EN) +#define SDC_DCRC_STS REG_ADDR(SDC_DCRC_STS) + +/* emmc register*/ +#define EMMC_CFG0 REG_ADDR(EMMC_CFG0) +#define EMMC_CFG1 REG_ADDR(EMMC_CFG1) +#define EMMC_STS REG_ADDR(EMMC_STS) +#define EMMC_IOCON REG_ADDR(EMMC_IOCON) + +/* auto command register */ +#define SDC_ACMD_RESP REG_ADDR(SDC_ACMD_RESP) +#define SDC_ACMD19_TRG REG_ADDR(SDC_ACMD19_TRG) +#define SDC_ACMD19_STS REG_ADDR(SDC_ACMD19_STS) + +/* dma register */ +#define MSDC_DMA_SA_HIGH REG_ADDR(MSDC_DMA_SA_HIGH) +#define MSDC_DMA_SA REG_ADDR(MSDC_DMA_SA) +#define MSDC_DMA_CA REG_ADDR(MSDC_DMA_CA) +#define MSDC_DMA_CTRL REG_ADDR(MSDC_DMA_CTRL) +#define MSDC_DMA_CFG REG_ADDR(MSDC_DMA_CFG) +#define MSDC_DMA_LEN REG_ADDR(MSDC_DMA_LEN) + +/* data read delay */ +#define MSDC_DAT_RDDLY0 REG_ADDR(MSDC_DAT_RDDLY0) +#define MSDC_DAT_RDDLY1 REG_ADDR(MSDC_DAT_RDDLY1) +#define MSDC_DAT_RDDLY2 REG_ADDR(MSDC_DAT_RDDLY2) +#define MSDC_DAT_RDDLY3 REG_ADDR(MSDC_DAT_RDDLY3) + +/* debug register */ +#define MSDC_DBG_SEL REG_ADDR(MSDC_DBG_SEL) +#define MSDC_DBG_OUT REG_ADDR(MSDC_DBG_OUT) + +/* misc register */ +#define MSDC_PATCH_BIT0 REG_ADDR(MSDC_PATCH_BIT0) +#define MSDC_PATCH_BIT1 REG_ADDR(MSDC_PATCH_BIT1) +#define MSDC_PATCH_BIT2 REG_ADDR(MSDC_PATCH_BIT2) +#define DAT0_TUNE_CRC REG_ADDR(DAT0_TUNE_CRC) +#define DAT1_TUNE_CRC REG_ADDR(DAT1_TUNE_CRC) +#define DAT2_TUNE_CRC REG_ADDR(DAT2_TUNE_CRC) +#define DAT3_TUNE_CRC REG_ADDR(DAT3_TUNE_CRC) +#define CMD_TUNE_CRC REG_ADDR(CMD_TUNE_CRC) +#define SDIO_TUNE_WIND REG_ADDR(SDIO_TUNE_WIND) +#define MSDC_PAD_TUNE0 REG_ADDR(MSDC_PAD_TUNE0) +#define MSDC_PAD_TUNE1 REG_ADDR(MSDC_PAD_TUNE1) +#define MSDC_HW_DBG REG_ADDR(MSDC_HW_DBG) +#define MSDC_VERSION REG_ADDR(MSDC_VERSION) +#define MSDC_ECO_VER REG_ADDR(MSDC_ECO_VER) + +/* eMMC 5.0 register */ +#define EMMC50_PAD_CTL0 REG_ADDR(EMMC50_PAD_CTL0) +#define EMMC50_PAD_DS_CTL0 REG_ADDR(EMMC50_PAD_DS_CTL0) +#define EMMC50_PAD_DS_TUNE REG_ADDR(EMMC50_PAD_DS_TUNE) +#define EMMC50_PAD_CMD_TUNE REG_ADDR(EMMC50_PAD_CMD_TUNE) +#define EMMC50_PAD_DAT01_TUNE REG_ADDR(EMMC50_PAD_DAT01_TUNE) +#define EMMC50_PAD_DAT23_TUNE REG_ADDR(EMMC50_PAD_DAT23_TUNE) +#define EMMC50_PAD_DAT45_TUNE REG_ADDR(EMMC50_PAD_DAT45_TUNE) +#define EMMC50_PAD_DAT67_TUNE REG_ADDR(EMMC50_PAD_DAT67_TUNE) +#define EMMC51_CFG0 REG_ADDR(EMMC51_CFG0) +#define EMMC50_CFG0 REG_ADDR(EMMC50_CFG0) +#define EMMC50_CFG1 REG_ADDR(EMMC50_CFG1) +#define EMMC50_CFG2 REG_ADDR(EMMC50_CFG2) +#define EMMC50_CFG3 REG_ADDR(EMMC50_CFG3) +#define EMMC50_CFG4 REG_ADDR(EMMC50_CFG4) +#define EMMC50_BLOCK_LENGTH REG_ADDR(EMMC50_BLOCK_LENGTH) + +/*--------------------------------------------------------------------------*/ +/* Register Mask */ +/*--------------------------------------------------------------------------*/ + +/* MSDC_CFG mask */ +#define MSDC_CFG_MODE (0x1 << 0) /* RW */ +#define MSDC_CFG_CKPDN (0x1 << 1) /* RW */ +#define MSDC_CFG_RST (0x1 << 2) /* A0 */ +#define MSDC_CFG_PIO (0x1 << 3) /* RW */ +#define MSDC_CFG_CKDRVEN (0x1 << 4) /* RW */ +#define MSDC_CFG_BV18SDT (0x1 << 5) /* RW */ +#define MSDC_CFG_BV18PSS (0x1 << 6) /* R */ +#define MSDC_CFG_CKSTB (0x1 << 7) /* R */ +#define MSDC_CFG_CKDIV (0xfff << 8) /* RW */ +#define MSDC_CFG_CKDIV_BITS (12) +#define MSDC_CFG_CKMOD (0x3 << 20) /* W1C */ +#define MSDC_CFG_CKMOD_BITS (2) +#define MSDC_CFG_CKMOD_HS400 (0x1 << 22) /* RW */ +#define MSDC_CFG_START_BIT (0x3 << 23) /* RW */ +#define MSDC_CFG_SCLK_STOP_DDR (0x1 << 25) /* RW */ +#define MSDC_CFG_DVFS_EN (0x1 << 30) /* RW */ + +/* MSDC_IOCON mask */ +#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */ +#define MSDC_IOCON_RSPL (0x1 << 1) /* RW */ +#define MSDC_IOCON_R_D_SMPL (0x1 << 2) /* RW */ +#define MSDC_IOCON_DDLSEL (0x1 << 3) /* RW */ +#define MSDC_IOCON_DDR50CKD (0x1 << 4) /* RW */ +#define MSDC_IOCON_R_D_SMPL_SEL (0x1 << 5) /* RW */ +#define MSDC_IOCON_W_D_SMPL (0x1 << 8) /* RW */ +#define MSDC_IOCON_W_D_SMPL_SEL (0x1 << 9) /* RW */ +#define MSDC_IOCON_W_D0SPL (0x1 << 10) /* RW */ +#define MSDC_IOCON_W_D1SPL (0x1 << 11) /* RW */ +#define MSDC_IOCON_W_D2SPL (0x1 << 12) /* RW */ +#define MSDC_IOCON_W_D3SPL (0x1 << 13) /* RW */ +#define MSDC_IOCON_R_D0SPL (0x1 << 16) /* RW */ +#define MSDC_IOCON_R_D1SPL (0x1 << 17) /* RW */ +#define MSDC_IOCON_R_D2SPL (0x1 << 18) /* RW */ +#define MSDC_IOCON_R_D3SPL (0x1 << 19) /* RW */ +#define MSDC_IOCON_R_D4SPL (0x1 << 20) /* RW */ +#define MSDC_IOCON_R_D5SPL (0x1 << 21) /* RW */ +#define MSDC_IOCON_R_D6SPL (0x1 << 22) /* RW */ +#define MSDC_IOCON_R_D7SPL (0x1 << 23) /* RW */ + +/* MSDC_PS mask */ +#define MSDC_PS_CDEN (0x1 << 0) /* RW */ +#define MSDC_PS_CDSTS (0x1 << 1) /* R */ +#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */ +#define MSDC_PS_DAT (0xff << 16) /* R */ +#define MSDC_PS_CMD (0x1 << 24) /* R */ +#define MSDC_PS_WP (0x1UL << 31) /* R */ + +/* MSDC_INT mask */ +#define MSDC_INT_MMCIRQ (0x1 << 0) /* W1C */ +#define MSDC_INT_CDSC (0x1 << 1) /* W1C */ +#define MSDC_INT_ACMDRDY (0x1 << 3) /* W1C */ +#define MSDC_INT_ACMDTMO (0x1 << 4) /* W1C */ +#define MSDC_INT_ACMDCRCERR (0x1 << 5) /* W1C */ +#define MSDC_INT_DMAQ_EMPTY (0x1 << 6) /* W1C */ +#define MSDC_INT_SDIOIRQ (0x1 << 7) /* W1C */ +#define MSDC_INT_CMDRDY (0x1 << 8) /* W1C */ +#define MSDC_INT_CMDTMO (0x1 << 9) /* W1C */ +#define MSDC_INT_RSPCRCERR (0x1 << 10) /* W1C */ +#define MSDC_INT_CSTA (0x1 << 11) /* R */ +#define MSDC_INT_XFER_COMPL (0x1 << 12) /* W1C */ +#define MSDC_INT_DXFER_DONE (0x1 << 13) /* W1C */ +#define MSDC_INT_DATTMO (0x1 << 14) /* W1C */ +#define MSDC_INT_DATCRCERR (0x1 << 15) /* W1C */ +#define MSDC_INT_ACMD19_DONE (0x1 << 16) /* W1C */ +#define MSDC_INT_BDCSERR (0x1 << 17) /* W1C */ +#define MSDC_INT_GPDCSERR (0x1 << 18) /* W1C */ +#define MSDC_INT_DMAPRO (0x1 << 19) /* W1C */ +#define MSDC_INT_GEAR_OUT_BOUND (0x1 << 20) /* W1C */ +#define MSDC_INT_ACMD53_DONE (0x1 << 21) /* W1C */ +#define MSDC_INT_ACMD53_FAIL (0x1 << 22) /* W1C */ +#define MSDC_INT_AXI_RESP_ERR (0x1 << 23) /* W1C */ + +/* MSDC_INTEN mask */ +#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */ +#define MSDC_INTEN_CDSC (0x1 << 1) /* RW */ +#define MSDC_INTEN_ACMDRDY (0x1 << 3) /* RW */ +#define MSDC_INTEN_ACMDTMO (0x1 << 4) /* RW */ +#define MSDC_INTEN_ACMDCRCERR (0x1 << 5) /* RW */ +#define MSDC_INTEN_DMAQ_EMPTY (0x1 << 6) /* RW */ +#define MSDC_INTEN_SDIOIRQ (0x1 << 7) /* RW */ +#define MSDC_INTEN_CMDRDY (0x1 << 8) /* RW */ +#define MSDC_INTEN_CMDTMO (0x1 << 9) /* RW */ +#define MSDC_INTEN_RSPCRCERR (0x1 << 10) /* RW */ +#define MSDC_INTEN_CSTA (0x1 << 11) /* RW */ +#define MSDC_INTEN_XFER_COMPL (0x1 << 12) /* RW */ +#define MSDC_INTEN_DXFER_DONE (0x1 << 13) /* RW */ +#define MSDC_INTEN_DATTMO (0x1 << 14) /* RW */ +#define MSDC_INTEN_DATCRCERR (0x1 << 15) /* RW */ +#define MSDC_INTEN_ACMD19_DONE (0x1 << 16) /* RW */ +#define MSDC_INTEN_BDCSERR (0x1 << 17) /* RW */ +#define MSDC_INTEN_GPDCSERR (0x1 << 18) /* RW */ +#define MSDC_INTEN_DMAPRO (0x1 << 19) /* RW */ +#define MSDC_INTEN_GOBOUND (0x1 << 20) /* RW */ +#define MSDC_INTEN_ACMD53_DONE (0x1 << 21) /* RW */ +#define MSDC_INTEN_ACMD53_FAIL (0x1 << 22) /* RW */ +#define MSDC_INTEN_AXI_RESP_ERR (0x1 << 23) /* RW */ + +/* MSDC_FIFOCS mask */ +#define MSDC_FIFOCS_RXCNT (0xff << 0) /* R */ +#define MSDC_FIFOCS_TXCNT (0xff << 16) /* R */ +#define MSDC_FIFOCS_CLR (0x1UL << 31) /* RW */ + +/* SDC_CFG mask */ +#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */ +#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */ +#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */ +#define SDC_CFG_SDIO (0x1 << 19) /* RW */ +#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */ +#define SDC_CFG_INTATGAP (0x1 << 21) /* RW */ +#define SDC_CFG_DTOC (0xffUL << 24) /* RW */ + +/* SDC_CMD mask */ +#define SDC_CMD_OPC (0x3f << 0) /* RW */ +#define SDC_CMD_BRK (0x1 << 6) /* RW */ +#define SDC_CMD_RSPTYP (0x7 << 7) /* RW */ +#define SDC_CMD_DTYP (0x3 << 11) /* RW */ +#define SDC_CMD_RW (0x1 << 13) /* RW */ +#define SDC_CMD_STOP (0x1 << 14) /* RW */ +#define SDC_CMD_GOIRQ (0x1 << 15) /* RW */ +#define SDC_CMD_BLKLEN (0xfff << 16) /* RW */ +#define SDC_CMD_AUTOCMD (0x3 << 28) /* RW */ +#define SDC_CMD_VOLSWTH (0x1 << 30) /* RW */ +#define SDC_CMD_ACMD53 (0x1UL << 31) /* RW */ + +/* SDC_STS mask */ +#define SDC_STS_SDCBUSY (0x1 << 0) /* RW */ +#define SDC_STS_CMDBUSY (0x1 << 1) /* RW */ +#define SDC_STS_CMD_WR_BUSY (0x1 << 16) /* W1C */ +#define SDC_STS_SWR_COMPL (0x1 << 31) /* RO */ + +/* SDC_STS mask */ +#define SDC_VOL_CHGCNT (0xffff << 0) /* RW */ + +/* SDC_DCRC_STS mask */ +#define SDC_DCRC_STS_POS (0xff << 0) /* RO */ +#define SDC_DCRC_STS_NEG (0xff << 8) /* RO */ + +/* EMMC_CFG0 mask */ +#define EMMC_CFG0_BOOTSTART (0x1 << 0) /* W */ +#define EMMC_CFG0_BOOTSTOP (0x1 << 1) /* W */ +#define EMMC_CFG0_BOOTMODE (0x1 << 2) /* RW */ +#define EMMC_CFG0_BOOTACKDIS (0x1 << 3) /* RW */ +#define EMMC_CFG0_BOOTWDLY (0x7 << 12) /* RW */ +#define EMMC_CFG0_BOOTSUPP (0x1 << 15) /* RW */ + +/* EMMC_CFG1 mask */ +#define EMMC_CFG1_BOOTDATTMC (0xfffff << 0) /* RW */ +#define EMMC_CFG1_BOOTACKTMC (0xfffUL << 20) /* RW */ + +/* EMMC_STS mask */ +#define EMMC_STS_BOOTCRCERR (0x1 << 0) /* W1C */ +#define EMMC_STS_BOOTACKERR (0x1 << 1) /* W1C */ +#define EMMC_STS_BOOTDATTMO (0x1 << 2) /* W1C */ +#define EMMC_STS_BOOTACKTMO (0x1 << 3) /* W1C */ +#define EMMC_STS_BOOTUPSTATE (0x1 << 4) /* R */ +#define EMMC_STS_BOOTACKRCV (0x1 << 5) /* W1C */ +#define EMMC_STS_BOOTDATRCV (0x1 << 6) /* R */ + +/* EMMC_IOCON mask */ +#define EMMC_IOCON_BOOTRST (0x1 << 0) /* RW */ + +/* SDC_ACMD19_TRG mask */ +#define SDC_ACMD19_TRG_TUNESEL (0xf << 0) /* RW */ + +/* MSDC_DMA_SA_HIGH */ +#define MSDC_DMA_SURR_ADDR_HIGH4BIT (0xf << 0) /* RW */ + +/* MSDC_DMA_CTRL mask */ +#define MSDC_DMA_CTRL_START (0x1 << 0) /* W */ +#define MSDC_DMA_CTRL_STOP (0x1 << 1) /* W */ +#define MSDC_DMA_CTRL_RESUME (0x1 << 2) /* W */ +#define MSDC_DMA_CTRL_REDAYM (0x1 << 3) /* RO */ +#define MSDC_DMA_CTRL_MODE (0x1 << 8) /* RW */ +#define MSDC_DMA_CTRL_ALIGN (0x1 << 9) /* RW */ +#define MSDC_DMA_CTRL_LASTBUF (0x1 << 10) /* RW */ +#define MSDC_DMA_CTRL_SPLIT1K (0x1 << 11) /* RW */ +#define MSDC_DMA_CTRL_BRUSTSZ (0x7 << 12) /* RW */ + +/* MSDC_DMA_CFG mask */ +#define MSDC_DMA_CFG_STS (0x1 << 0) /* R */ +#define MSDC_DMA_CFG_DECSEN (0x1 << 1) /* RW */ +#define MSDC_DMA_CFG_LOCKDISABLE (0x1 << 2) /* RW */ +#define MSDC_DMA_CFG_AHBEN (0x3 << 8) /* RW */ +#define MSDC_DMA_CFG_ACTEN (0x3 << 12) /* RW */ +#define MSDC_DMA_CFG_CS12B (0x1 << 16) /* RW */ + +/* MSDC_PATCH_BIT0 mask */ +#define MSDC_PB0_RESV1 (0x1 << 0) +#define MSDC_PB0_EN_8BITSUP (0x1 << 1) +#define MSDC_PB0_DIS_RECMDWR (0x1 << 2) +#define MSDC_PB0_RD_DAT_SEL (0x1 << 3) +#define MSDC_PB0_RESV2 (0x3 << 4) +#define MSDC_PB0_DESCUP (0x1 << 6) +#define MSDC_PB0_INT_DAT_LATCH_CK_SEL (0x7 << 7) +#define MSDC_PB0_CKGEN_MSDC_DLY_SEL (0x1F<<10) +#define MSDC_PB0_FIFORD_DIS (0x1 << 15) +#define MSDC_PB0_BLKNUM_SEL (0x1 << 16) +#define MSDC_PB0_SDIO_INTCSEL (0x1 << 17) +#define MSDC_PB0_SDC_BSYDLY (0xf << 18) +#define MSDC_PB0_SDC_WDOD (0xf << 22) +#define MSDC_PB0_CMDIDRTSEL (0x1 << 26) +#define MSDC_PB0_CMDFAILSEL (0x1 << 27) +#define MSDC_PB0_SDIO_INTDLYSEL (0x1 << 28) +#define MSDC_PB0_SPCPUSH (0x1 << 29) +#define MSDC_PB0_DETWR_CRCTMO (0x1 << 30) +#define MSDC_PB0_EN_DRVRSP (0x1UL << 31) + +/* MSDC_PATCH_BIT1 mask */ +#define MSDC_PB1_WRDAT_CRCS_TA_CNTR (0x7 << 0) +#define MSDC_PB1_CMD_RSP_TA_CNTR (0x7 << 3) +#define MSDC_PB1_GET_BUSY_MA (0x1 << 6) +#define MSDC_PB1_GET_CRC_MA (0x1 << 7) +#define MSDC_PB1_BIAS_TUNE_28NM (0xf << 8) +#define MSDC_PB1_BIAS_EN18IO_28NM (0x1 << 12) +#define MSDC_PB1_BIAS_EXT_28NM (0x1 << 13) +#define MSDC_PB1_RESV2 (0x1 << 14) +#define MSDC_PB1_RESET_GDMA (0x1 << 15) +#define MSDC_PB1_SINGLE_BURST (0x1 << 16) +#define MSDC_PB1_FROCE_STOP (0x1 << 17) +#define MSDC_PB1_DCM_DEV_SEL2 (0x3 << 18) +#define MSDC_PB1_DCM_DEV_SEL1 (0x1 << 20) +#define MSDC_PB1_DCM_EN (0x1 << 21) +#define MSDC_PB1_AXI_WRAP_CKEN (0x1 << 22) +#define MSDC_PB1_CKCLK_GDMA_EN (0x1 << 23) +#define MSDC_PB1_CKSPCEN (0x1 << 24) +#define MSDC_PB1_CKPSCEN (0x1 << 25) +#define MSDC_PB1_CKVOLDETEN (0x1 << 26) +#define MSDC_PB1_CKACMDEN (0x1 << 27) +#define MSDC_PB1_CKSDEN (0x1 << 28) +#define MSDC_PB1_CKWCTLEN (0x1 << 29) +#define MSDC_PB1_CKRCTLEN (0x1 << 30) +#define MSDC_PB1_CKSHBFFEN (0x1UL << 31) + +/* MSDC_PATCH_BIT2 mask */ +#define MSDC_PB2_ENHANCEGPD (0x1 << 0) +#define MSDC_PB2_SUPPORT64G (0x1 << 1) +#define MSDC_PB2_RESPWAITCNT (0x3 << 2) +#define MSDC_PB2_CFGRDATCNT (0x1f << 4) +#define MSDC_PB2_CFGRDAT (0x1 << 9) +#define MSDC_PB2_INTCRESPSEL (0x1 << 11) +#define MSDC_PB2_CFGRESPCNT (0x7 << 12) +#define MSDC_PB2_CFGRESP (0x1 << 15) +#define MSDC_PB2_RESPSTENSEL (0x7 << 16) +#define MSDC_PB2_POPENCNT (0xf << 20) +#define MSDC_PB2_CFG_CRCSTS_SEL (0x1 << 24) +#define MSDC_PB2_CFGCRCSTSEDGE (0x1 << 25) +#define MSDC_PB2_CFGCRCSTSCNT (0x3 << 26) +#define MSDC_PB2_CFGCRCSTS (0x1 << 28) +#define MSDC_PB2_CRCSTSENSEL (0x7UL << 29) + +#define MSDC_MASK_ACMD53_CRC_ERR_INTR (0x1<<4) +#define MSDC_ACMD53_FAIL_ONE_SHOT (0X1<<5) + +/* MSDC_PAD_TUNE mask */ +#define MSDC_PAD_TUNE0_DATWRDLY (0x1F << 0) /* RW */ +#define MSDC_PAD_TUNE0_DELAYEN (0x1 << 7) /* RW */ +#define MSDC_PAD_TUNE0_DATRRDLY (0x1F << 8) /* RW */ +#define MSDC_PAD_TUNE0_DATRRDLYSEL (0x1 << 13) /* RW */ +#define MSDC_PAD_TUNE0_RXDLYSEL (0x1 << 15) /* RW */ +#define MSDC_PAD_TUNE0_CMDRDLY (0x1F << 16) /* RW */ +#define MSDC_PAD_TUNE0_CMDRRDLYSEL (0x1 << 21) /* RW */ +#define MSDC_PAD_TUNE0_CMDRRDLY (0x1FUL << 22) /* RW */ +#define MSDC_PAD_TUNE0_CLKTXDLY (0x1FUL << 27) /* RW */ + +/* MSDC_PAD_TUNE1 mask */ +#define MSDC_PAD_TUNE1_DATRRDLY2 (0x1F << 8) /* RW */ +#define MSDC_PAD_TUNE1_DATRRDLY2SEL (0x1 << 13) /* RW */ +#define MSDC_PAD_TUNE1_CMDRDLY2 (0x1F << 16) /* RW */ +#define MSDC_PAD_TUNE1_CMDRRDLY2SEL (0x1 << 21) /* RW */ + +/* MSDC_DAT_RDDLY0/1/2/3 mask */ +#define MSDC_DAT_RDDLY0_D3 (0x1F << 0) /* RW */ +#define MSDC_DAT_RDDLY0_D2 (0x1F << 8) /* RW */ +#define MSDC_DAT_RDDLY0_D1 (0x1F << 16) /* RW */ +#define MSDC_DAT_RDDLY0_D0 (0x1FUL << 24) /* RW */ + +#define MSDC_DAT_RDDLY1_D7 (0x1F << 0) /* RW */ +#define MSDC_DAT_RDDLY1_D6 (0x1F << 8) /* RW */ +#define MSDC_DAT_RDDLY1_D5 (0x1F << 16) /* RW */ +#define MSDC_DAT_RDDLY1_D4 (0x1FUL << 24) /* RW */ + +#define MSDC_DAT_RDDLY2_D3 (0x1F << 0) /* RW */ +#define MSDC_DAT_RDDLY2_D2 (0x1F << 8) /* RW */ +#define MSDC_DAT_RDDLY2_D1 (0x1F << 16) /* RW */ +#define MSDC_DAT_RDDLY2_D0 (0x1FUL << 24) /* RW */ + +#define MSDC_DAT_RDDLY3_D7 (0x1F << 0) /* RW */ +#define MSDC_DAT_RDDLY3_D6 (0x1F << 8) /* RW */ +#define MSDC_DAT_RDDLY3_D5 (0x1F << 16) /* RW */ +#define MSDC_DAT_RDDLY3_D4 (0x1FUL << 24) /* RW */ + +/* MSDC_HW_DBG_SEL mask */ +#define MSDC_HW_DBG0_SEL (0xFF << 0) +#define MSDC_HW_DBG1_SEL (0x3F << 8) +#define MSDC_HW_DBG2_SEL (0xFF << 16) +#define MSDC_HW_DBG3_SEL (0x3F << 24) +#define MSDC_HW_DBG_WRAPTYPE_SEL (0x1 << 30) + +/* MSDC_EMMC50_PAD_CTL0 mask*/ +#define MSDC_EMMC50_PAD_CTL0_DCCSEL (0x1 << 0) +#define MSDC_EMMC50_PAD_CTL0_HLSEL (0x1 << 1) +#define MSDC_EMMC50_PAD_CTL0_DLP0 (0x3 << 2) +#define MSDC_EMMC50_PAD_CTL0_DLN0 (0x3 << 4) +#define MSDC_EMMC50_PAD_CTL0_DLP1 (0x3 << 6) +#define MSDC_EMMC50_PAD_CTL0_DLN1 (0x3 << 8) + +/* MSDC_EMMC50_PAD_DS_CTL0 mask */ +#define MSDC_EMMC50_PAD_DS_CTL0_SR (0x1 << 0) +#define MSDC_EMMC50_PAD_DS_CTL0_R0 (0x1 << 1) +#define MSDC_EMMC50_PAD_DS_CTL0_R1 (0x1 << 2) +#define MSDC_EMMC50_PAD_DS_CTL0_PUPD (0x1 << 3) +#define MSDC_EMMC50_PAD_DS_CTL0_IES (0x1 << 4) +#define MSDC_EMMC50_PAD_DS_CTL0_SMT (0x1 << 5) +#define MSDC_EMMC50_PAD_DS_CTL0_RDSEL (0x3F << 6) +#define MSDC_EMMC50_PAD_DS_CTL0_TDSEL (0xf << 12) +#define MSDC_EMMC50_PAD_DS_CTL0_DRV (0x7 << 16) + +/* EMMC50_PAD_DS_TUNE mask */ +#define MSDC_EMMC50_PAD_DS_TUNE_DLYSEL (0x1 << 0) +#define MSDC_EMMC50_PAD_DS_TUNE_DLY2SEL (0x1 << 1) +#define MSDC_EMMC50_PAD_DS_TUNE_DLY1 (0x1F << 2) +#define MSDC_EMMC50_PAD_DS_TUNE_DLY2 (0x1F << 7) +#define MSDC_EMMC50_PAD_DS_TUNE_DLY3 (0x1F << 12) + +/* EMMC50_PAD_CMD_TUNE mask */ +#define MSDC_EMMC50_PAD_CMD_TUNE_DLY3SEL (0x1 << 0) +#define MSDC_EMMC50_PAD_CMD_TUNE_RXDLY3 (0x1F << 1) +#define MSDC_EMMC50_PAD_CMD_TUNE_TXDLY (0x1F << 6) + +/* EMMC50_PAD_DAT01_TUNE mask */ +#define MSDC_EMMC50_PAD_DAT0_RXDLY3SEL (0x1 << 0) +#define MSDC_EMMC50_PAD_DAT0_RXDLY3 (0x1F << 1) +#define MSDC_EMMC50_PAD_DAT0_TXDLY (0x1F << 6) +#define MSDC_EMMC50_PAD_DAT1_RXDLY3SEL (0x1 << 16) +#define MSDC_EMMC50_PAD_DAT1_RXDLY3 (0x1F << 17) +#define MSDC_EMMC50_PAD_DAT1_TXDLY (0x1F << 22) + +/* EMMC50_PAD_DAT23_TUNE mask */ +#define MSDC_EMMC50_PAD_DAT2_RXDLY3SEL (0x1 << 0) +#define MSDC_EMMC50_PAD_DAT2_RXDLY3 (0x1F << 1) +#define MSDC_EMMC50_PAD_DAT2_TXDLY (0x1F << 6) +#define MSDC_EMMC50_PAD_DAT3_RXDLY3SEL (0x1 << 16) +#define MSDC_EMMC50_PAD_DAT3_RXDLY3 (0x1F << 17) +#define MSDC_EMMC50_PAD_DAT3_TXDLY (0x1F << 22) + +/* EMMC50_PAD_DAT45_TUNE mask */ +#define MSDC_EMMC50_PAD_DAT4_RXDLY3SEL (0x1 << 0) +#define MSDC_EMMC50_PAD_DAT4_RXDLY3 (0x1F << 1) +#define MSDC_EMMC50_PAD_DAT4_TXDLY (0x1F << 6) +#define MSDC_EMMC50_PAD_DAT5_RXDLY3SEL (0x1 << 16) +#define MSDC_EMMC50_PAD_DAT5_RXDLY3 (0x1F << 17) +#define MSDC_EMMC50_PAD_DAT5_TXDLY (0x1F << 22) + +/* EMMC50_PAD_DAT67_TUNE mask */ +#define MSDC_EMMC50_PAD_DAT6_RXDLY3SEL (0x1 << 0) +#define MSDC_EMMC50_PAD_DAT6_RXDLY3 (0x1F << 1) +#define MSDC_EMMC50_PAD_DAT6_TXDLY (0x1F << 6) +#define MSDC_EMMC50_PAD_DAT7_RXDLY3SEL (0x1 << 16) +#define MSDC_EMMC50_PAD_DAT7_RXDLY3 (0x1F << 17) +#define MSDC_EMMC50_PAD_DAT7_TXDLY (0x1F << 22) + +/* EMMC51_CFG0 mask */ +#define MSDC_EMMC51_CFG_CMDQEN (0x1 << 0) +#define MSDC_EMMC51_CFG_NUM (0x3F << 1) +#define MSDC_EMMC51_CFG_RSPTYPE (0x7 << 7) +#define MSDC_EMMC51_CFG_DTYPE (0x3 << 10) +#define MSDC_EMMC51_CFG_RDATCNT (0x3FF << 12) +#define MSDC_EMMC51_CFG_WDATCNT (0x3FF << 22) + +/* EMMC50_CFG0 mask */ +#define MSDC_EMMC50_CFG_PADCMD_LATCHCK (0x1 << 0) +#define MSDC_EMMC50_CFG_CRC_STS_CNT (0x3 << 1) +#define MSDC_EMMC50_CFG_CRC_STS_EDGE (0x1 << 3) +#define MSDC_EMMC50_CFG_CRC_STS_SEL (0x1 << 4) +#define MSDC_EMMC50_CFG_END_BIT_CHK_CNT (0xf << 5) +#define MSDC_EMMC50_CFG_CMD_RESP_SEL (0x1 << 9) +#define MSDC_EMMC50_CFG_CMD_EDGE_SEL (0x1 << 10) +#define MSDC_EMMC50_CFG_ENDBIT_CNT (0x3FF << 11) +#define MSDC_EMMC50_CFG_READ_DAT_CNT (0x7 << 21) +#define MSDC_EMMC50_CFG_EMMC50_MON_SEL (0x1 << 24) +#define MSDC_EMMC50_CFG_MSDC_WR_VALID (0x1 << 25) +#define MSDC_EMMC50_CFG_MSDC_RD_VALID (0x1 << 26) +#define MSDC_EMMC50_CFG_MSDC_WR_VALID_SEL (0x1 << 27) +#define MSDC_EMMC50_CFG_MSDC_RD_VALID_SEL (0x1 << 28) +#define MSDC_EMMC50_CFG_TXSKEW_SEL (0x1 << 29) + +/* EMMC50_CFG1 mask */ +#define MSDC_EMMC50_CFG1_WRPTR_MARGIN (0xFF << 0) +#define MSDC_EMMC50_CFG1_CKSWITCH_CNT (0x7 << 8) +#define MSDC_EMMC50_CFG1_RDDAT_STOP (0x1 << 11) +#define MSDC_EMMC50_CFG1_WAITCLK_CNT (0xF << 12) +#define MSDC_EMMC50_CFG1_DBG_SEL (0xFF << 16) +#define MSDC_EMMC50_CFG1_PSHCNT (0x7 << 24) +#define MSDC_EMMC50_CFG1_PSHPSSEL (0x1 << 27) +#define MSDC_EMMC50_CFG1_DSCFG (0x1 << 28) +#define MSDC_EMMC50_CFG1_SPARE1 (0x7UL << 29) + +/* EMMC50_CFG2_mask */ +/*#define MSDC_EMMC50_CFG2_AXI_GPD_UP (0x1 << 0)*/ +#define MSDC_EMMC50_CFG2_AXI_IOMMU_WR_EMI (0x1 << 1) +#define MSDC_EMMC50_CFG2_AXI_SHARE_EN_WR_EMI (0x1 << 2) +#define MSDC_EMMC50_CFG2_AXI_IOMMU_RD_EMI (0x1 << 7) +#define MSDC_EMMC50_CFG2_AXI_SHARE_EN_RD_EMI (0x1 << 8) +#define MSDC_EMMC50_CFG2_AXI_BOUND_128B (0x1 << 13) +#define MSDC_EMMC50_CFG2_AXI_BOUND_256B (0x1 << 14) +#define MSDC_EMMC50_CFG2_AXI_BOUND_512B (0x1 << 15) +#define MSDC_EMMC50_CFG2_AXI_BOUND_1K (0x1 << 16) +#define MSDC_EMMC50_CFG2_AXI_BOUND_2K (0x1 << 17) +#define MSDC_EMMC50_CFG2_AXI_BOUND_4K (0x1 << 18) +#define MSDC_EMMC50_CFG2_AXI_RD_OUTS_NUM (0x1F << 19) +#define MSDC_EMMC50_CFG2_AXI_SET_LEN (0xf << 24) +#define MSDC_EMMC50_CFG2_AXI_RESP_ERR_TYPE (0x3 << 28) +#define MSDC_EMMC50_CFG2_AXI_BUSY (0x1 << 30) + +/* EMMC50_CFG3_mask */ +#define MSDC_EMMC50_CFG3_OUTS_WR (0x1F << 0) +#define MSDC_EMMC50_CFG3_ULTRA_SET_WR (0x3F << 5) +#define MSDC_EMMC50_CFG3_PREULTRA_SET_WR (0x3F << 11) +#define MSDC_EMMC50_CFG3_ULTRA_SET_RD (0x3F << 17) +#define MSDC_EMMC50_CFG3_PREULTRA_SET_RD (0x3F << 23) + +/* EMMC50_CFG4_mask */ +#define MSDC_EMMC50_CFG4_IMPR_ULTRA_SET_WR (0xFF << 0) +#define MSDC_EMMC50_CFG4_IMPR_ULTRA_SET_RD (0xFF << 8) +#define MSDC_EMMC50_CFG4_ULTRA_EN (0x3 << 16) +#define MSDC_EMMC50_CFG4_AXI_WRAP_DBG_SEL (0x1F << 18) + +/* EMMC50_BLOCK_LENGTH mask */ +#define MSDC_EMMC50_BLOCK_LENGTH_MASK (0x1FF << 0) + +/* SDIO_TUNE_WIND mask*/ +#define MSDC_SDIO_TUNE_WIND (0x1F << 0) + +#endif /* end of _MSDC_REG_H_ */ + diff --git a/drivers/mmc/host/mediatek/mt6755/msdc_tune.c b/drivers/mmc/host/mediatek/mt6755/msdc_tune.c new file mode 100644 index 0000000000000000000000000000000000000000..86209f2c31fa22d5bf087695d0df84f86167bd78 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/msdc_tune.c @@ -0,0 +1,1387 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +#include +#include + +#include "mt_sd.h" +#include +#include "dbg.h" +#include "autok.h" +#include "autok_dvfs.h" + +/* FIX ME: better low freq trigger condition is continual 2 or more times crc or tmo error */ +#define CMD_TUNE_SMPL_MAX_TIME (4) +#define READ_TUNE_SMPL_MAX_TIME (4) +#define WRITE_TUNE_SMPL_MAX_TIME (4) + +#define CMD_TUNE_HS_MAX_TIME (2*63) +#define READ_DATA_TUNE_MAX_TIME (2*63) +#define WRITE_DATA_TUNE_MAX_TIME (2*63) + +#define MSDC_LOWER_FREQ +#define MSDC_MAX_FREQ_DIV (2) +#define MSDC_MAX_TIMEOUT_RETRY (1) +#define MSDC_MAX_TIMEOUT_RETRY_EMMC (2) +#define MSDC_MAX_W_TIMEOUT_TUNE (5) +#define MSDC_MAX_W_TIMEOUT_TUNE_EMMC (64) +#define MSDC_MAX_R_TIMEOUT_TUNE (3) + +#define MSDC_MAX_CONTINUOUS_FAIL_REQUEST_COUNT (50) + +#define MAX_HS400_TUNE_COUNT (576) /*(32*18)*/ + +#define CMD_SET_FOR_MMC_TUNE_CASE1 (0x00000000FB260140ULL) +#define CMD_SET_FOR_MMC_TUNE_CASE2 (0x0000000000000080ULL) +#define CMD_SET_FOR_MMC_TUNE_CASE3 (0x0000000000001000ULL) +#define CMD_SET_FOR_MMC_TUNE_CASE4 (0x0000000000000020ULL) +/*#define CMD_SET_FOR_MMC_TUNE_CASE5 (0x0000000000084000ULL)*/ + +#define CMD_SET_FOR_SD_TUNE_CASE1 (0x000000007B060040ULL) +#define CMD_SET_FOR_APP_TUNE_CASE1 (0x0008000000402000ULL) + +#define IS_IN_CMD_SET(cmd_num, set) ((0x1ULL << cmd_num) & (set)) + +#define MSDC_VERIFY_NEED_TUNE (0) +#define MSDC_VERIFY_ERROR (1) +#define MSDC_VERIFY_NEED_NOT_TUNE (2) + +u8 emmc_id; /* FIX ME: check if it can be removed */ + +u32 sdio_tune_flag = 0; /* FIX ME: check if it can be removed since it is set + but referenced */ + +void msdc_reset_pwr_cycle_counter(struct msdc_host *host) +{ + host->power_cycle = 0; + host->power_cycle_enable = 1; +} + +void msdc_reset_tmo_tune_counter(struct msdc_host *host, unsigned int index) +{ + switch (index) { + case all_counter: + case cmd_counter: + if (host->rwcmd_time_tune != 0) + ERR_MSG("TMO TUNE CMD Times(%d)", + host->rwcmd_time_tune); + host->rwcmd_time_tune = 0; + if (index == cmd_counter) + break; + case read_counter: + if (host->read_time_tune != 0) + ERR_MSG("TMO TUNE READ Times(%d)", + host->read_time_tune); + host->read_time_tune = 0; + if (index == read_counter) + break; + case write_counter: + if (host->write_time_tune != 0) + ERR_MSG("TMO TUNE WRITE Times(%d)", + host->write_time_tune); + host->write_time_tune = 0; + break; + default: + ERR_MSG("msdc%d ==> reset tmo counter index(%d) error!\n", + host->id, index); + break; + } +} + +void msdc_reset_crc_tune_counter(struct msdc_host *host, unsigned int index) +{ + /*void __iomem *base = host->base;*/ + struct tune_counter *t_counter = &host->t_counter; + + switch (index) { + case all_counter: + /* FIX ME: This part might be removed if HS400 AUTOK work fine*/ + if (t_counter->time_hs400 != 0) + ERR_MSG("TUNE HS400 Times(%d)", t_counter->time_hs400); + t_counter->time_hs400 = 0; + /* fallthrough*/ + case cmd_counter: + if (t_counter->time_cmd != 0) + ERR_MSG("CRC TUNE CMD Times(%d)", t_counter->time_cmd); + t_counter->time_cmd = 0; + if (index == cmd_counter) + break; + case read_counter: + if (t_counter->time_read != 0) { + ERR_MSG("CRC TUNE READ Times(%d)", + t_counter->time_read); + } + t_counter->time_read = 0; + if (index == read_counter) + break; + case write_counter: + if (t_counter->time_write != 0) { + ERR_MSG("CRC TUNE WRITE Times(%d)", + t_counter->time_write); + } + t_counter->time_write = 0; + break; + default: + ERR_MSG("msdc%d ==> reset crc counter index(%d) error!\n", + host->id, index); + break; + } +} + +void msdc_save_timing_setting(struct msdc_host *host, int save_mode) +{ + struct msdc_hw *hw = host->hw; + void __iomem *base = host->base; + /* save_mode: 1 emmc_suspend + 2 sdio_suspend + 3 power_tuning + 4 power_off */ + + MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, hw->cmd_edge); + MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_R_D_SMPL, hw->rdata_edge); + MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL, hw->wdata_edge); + + if ((save_mode == 1) || (save_mode == 2)) { + host->saved_para.hz = host->mclk; + host->saved_para.sdc_cfg = MSDC_READ32(SDC_CFG); + } + + if (((save_mode == 1) || (save_mode == 4)) && (hw->host_function == MSDC_EMMC)) { + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY1, + host->saved_para.ds_dly1); + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY3, + host->saved_para.ds_dly3); + host->saved_para.emmc50_pad_cmd_tune = + MSDC_READ32(EMMC50_PAD_CMD_TUNE); + host->saved_para.emmc50_dat01 = + MSDC_READ32(EMMC50_PAD_DAT01_TUNE); + host->saved_para.emmc50_dat23 = + MSDC_READ32(EMMC50_PAD_DAT23_TUNE); + host->saved_para.emmc50_dat45 = + MSDC_READ32(EMMC50_PAD_DAT45_TUNE); + host->saved_para.emmc50_dat67 = + MSDC_READ32(EMMC50_PAD_DAT67_TUNE); + } + + if (save_mode == 1) { + host->saved_para.timing = host->timing; + host->saved_para.msdc_cfg = MSDC_READ32(MSDC_CFG); + host->saved_para.iocon = MSDC_READ32(MSDC_IOCON); + } + + if (save_mode == 2) { + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, host->saved_para.mode); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKDIV, host->saved_para.div); + MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_INT_DAT_LATCH_CK_SEL, + host->saved_para.int_dat_latch_ck_sel); + MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_CKGEN_MSDC_DLY_SEL, + host->saved_para.ckgen_msdc_dly_sel); + MSDC_GET_FIELD(MSDC_INTEN, MSDC_INT_SDIOIRQ, + host->saved_para.inten_sdio_irq); + host->saved_para.msdc_cfg = MSDC_READ32(MSDC_CFG); + + host->saved_para.iocon = MSDC_READ32(MSDC_IOCON); + + host->saved_para.timing = host->timing; + } + + host->saved_para.pad_tune0 = MSDC_READ32(MSDC_PAD_TUNE0); + host->saved_para.pad_tune1 = MSDC_READ32(MSDC_PAD_TUNE1); + + host->saved_para.ddly0 = MSDC_READ32(MSDC_DAT_RDDLY0); + host->saved_para.ddly1 = MSDC_READ32(MSDC_DAT_RDDLY1); + + host->saved_para.pb1 = MSDC_READ32(MSDC_PATCH_BIT1); + host->saved_para.pb2 = MSDC_READ32(MSDC_PATCH_BIT2); + /*msdc_dump_register(host);*/ +} + +void msdc_set_bad_card_and_remove(struct msdc_host *host) +{ + unsigned long flags; + + if (host == NULL) { + ERR_MSG("WARN: host is NULL"); + return; + } + host->card_inserted = 0; + + if ((host->mmc == NULL) || (host->mmc->card == NULL)) { + ERR_MSG("WARN: mmc or card is NULL"); + return; + } + if (host->mmc->card) { + spin_lock_irqsave(&host->remove_bad_card, flags); + host->block_bad_card = 1; + + mmc_card_set_removed(host->mmc->card); + spin_unlock_irqrestore(&host->remove_bad_card, flags); + + if (!(host->mmc->caps & MMC_CAP_NONREMOVABLE) + && (host->hw->cd_level == __gpio_get_value(cd_gpio))) { + /* do nothing*/ + /*tasklet_hi_schedule(&host->card_tasklet);*/ + } else { + mmc_remove_card(host->mmc->card); + host->mmc->card = NULL; + mmc_detach_bus(host->mmc); + mmc_power_off(host->mmc); + } + + ERR_MSG("Remove the bad card, block_bad_card=%d, card_inserted=%d", + host->block_bad_card, host->card_inserted); + } +} + +/* 0 means pass */ +u32 msdc_power_tuning(struct msdc_host *host) +{ + struct mmc_host *mmc = host->mmc; + struct mmc_card *card; + struct mmc_request *mrq; + u32 power_cycle = 0; + int read_timeout_tune = 0; + int write_timeout_tune = 0; + u32 rwcmd_timeout_tune = 0; + u32 read_timeout_tune_uhs104 = 0; + u32 write_timeout_tune_uhs104 = 0; + u32 sw_timeout = 0; + u32 ret = 1; + u32 host_err = 0; + u32 sclk = host->sclk; + + if (!mmc) + return 1; + + card = mmc->card; + if (card == NULL) { + ERR_MSG("mmc->card is NULL"); + return 1; + } + /* eMMC first */ +#ifdef CONFIG_MTK_EMMC_SUPPORT + if (mmc_card_mmc(card) && (host->hw->host_function == MSDC_EMMC)) + return 1; +#endif + + /* if (!host->error_tune_enable) + return 1; + */ + + if ((host->sd_30_busy > 0) + && (host->sd_30_busy <= MSDC_MAX_POWER_CYCLE)) { + host->power_cycle_enable = 1; + } + + if (!mmc_card_sd(card) || (host->hw->host_function != MSDC_SD)) + return ret; + + if (host->power_cycle == MSDC_MAX_POWER_CYCLE) { + if (host->error_tune_enable) { + ERR_MSG("do disable error tune flow of bad SD card"); + host->error_tune_enable = 0; + } + return ret; + } + + if ((host->power_cycle > MSDC_MAX_POWER_CYCLE) || + (!host->power_cycle_enable)) + return ret; + + /* power cycle */ + ERR_MSG("the %d time, Power cycle start", host->power_cycle); + spin_unlock(&host->lock); + + if (host->power_control) + host->power_control(host, 0); + + mdelay(10); + + if (host->power_control) + host->power_control(host, 1); + + spin_lock(&host->lock); + /*msdc_save_timing_setting(host, 3);*/ + msdc_init_tune_setting(host); + if ((sclk > 100000000) && (host->power_cycle >= 1)) + mmc->caps &= ~MMC_CAP_UHS_SDR104; + if (((sclk <= 100000000) && + ((sclk > 50000000) || (host->timing == MMC_TIMING_UHS_DDR50))) + && (host->power_cycle >= 1)) { + mmc->caps &= ~(MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 + | MMC_CAP_UHS_DDR50); + } + + msdc_host_mode[host->id] = mmc->caps; + msdc_host_mode2[host->id] = mmc->caps2; + + /* clock should set to 260K*/ + mmc->ios.clock = HOST_MIN_MCLK; + mmc->ios.bus_width = MMC_BUS_WIDTH_1; + mmc->ios.timing = MMC_TIMING_LEGACY; + msdc_set_mclk(host, MMC_TIMING_LEGACY, HOST_MIN_MCLK); + + /* re-init the card!*/ + mrq = host->mrq; + host->mrq = NULL; + power_cycle = host->power_cycle; + host->power_cycle = MSDC_MAX_POWER_CYCLE; + read_timeout_tune = host->read_time_tune; + write_timeout_tune = host->write_time_tune; + rwcmd_timeout_tune = host->rwcmd_time_tune; + read_timeout_tune_uhs104 = host->read_timeout_uhs104; + write_timeout_tune_uhs104 = host->write_timeout_uhs104; + sw_timeout = host->sw_timeout; + host_err = host->error; + spin_unlock(&host->lock); + ret = mmc_sd_power_cycle(mmc, card->ocr, card); + spin_lock(&host->lock); + host->mrq = mrq; + host->power_cycle = power_cycle; + host->read_time_tune = read_timeout_tune; + host->write_time_tune = write_timeout_tune; + host->rwcmd_time_tune = rwcmd_timeout_tune; + if (sclk > 100000000) { + host->write_timeout_uhs104 = write_timeout_tune_uhs104; + } else { + host->read_timeout_uhs104 = 0; + host->write_timeout_uhs104 = 0; + } + host->sw_timeout = sw_timeout; + host->error = host_err; + if (!ret) + host->power_cycle_enable = 0; + ERR_MSG("the %d time, Power cycle Done, host->error(0x%x), ret(%d)", + host->power_cycle, host->error, ret); + (host->power_cycle)++; + + return ret; +} + +static int msdc_lower_freq(struct msdc_host *host) +{ + u32 div, mode, hs400_div_dis; + void __iomem *base = host->base; + u32 *hclks; + + ERR_MSG("need to lower freq"); + msdc_reset_crc_tune_counter(host, all_counter); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, mode); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKDIV, div); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD_HS400, hs400_div_dis); + + hclks = msdc_get_hclks(host->id); + + if (div >= MSDC_MAX_FREQ_DIV) { + ERR_MSG("div<%d> too large, change to power tuning", div); + return msdc_power_tuning(host); + } else if ((mode == 3) && (host->id == 0)) { + mode = 1; /* change to HS200 */ + div = 0; + msdc_clk_stable(host, mode, div, hs400_div_dis); + host->sclk = hclks[host->hw->clk_src] / 2; + } else if (mode == 1) { + mode = 0; + msdc_clk_stable(host, mode, div, hs400_div_dis); + host->sclk = (div == 0) ? + hclks[host->hw->clk_src]/2 : + hclks[host->hw->clk_src]/(4*div); + } else { + msdc_clk_stable(host, mode, div + 1, hs400_div_dis); + host->sclk = (mode == 2) ? + hclks[host->hw->clk_src]/(2*4*(div+1)) : + hclks[host->hw->clk_src]/(4*(div+1)); + } + + ERR_MSG("new div<%d>, mode<%d> new freq.<%dKHz>", + (mode == 1) ? div : div + 1, mode, host->sclk / 1000); + return 0; +} + +/* FIX ME: remove it if autok works fine */ +/* + * 2013-12-09 + * HS400 error tune flow of read/write data error + * HS400 error tune flow of cmd error is same as eMMC4.5 backward speed mode. + */ +int emmc_hs400_tune_rw(struct msdc_host *host) +{ + void __iomem *base = host->base; + int cur_ds_dly1 = 0, cur_ds_dly3 = 0; + int orig_ds_dly1 = 0, orig_ds_dly3 = 0; + int err = 0; + + if (host->timing != MMC_TIMING_MMC_HS400) + return err; + + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY1, + orig_ds_dly1); + MSDC_GET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY3, + orig_ds_dly3); + + cur_ds_dly1 = orig_ds_dly1 - 1; + cur_ds_dly3 = orig_ds_dly3; + if (cur_ds_dly1 < 0) { + cur_ds_dly1 = 17; + cur_ds_dly3 = orig_ds_dly3 + 1; + if (cur_ds_dly3 >= 32) + cur_ds_dly3 = 0; + } + + if (++host->t_counter.time_hs400 == MAX_HS400_TUNE_COUNT) { + ERR_MSG("Failed to update EMMC50_PAD_DS_TUNE_DLY, cur_ds_dly3=0x%x, cur_ds_dly1=0x%x", + cur_ds_dly3, cur_ds_dly1); +#ifdef MSDC_LOWER_FREQ + err = msdc_lower_freq(host); +#else + err = 1; +#endif + goto out; + } else { + MSDC_SET_FIELD(EMMC50_PAD_DS_TUNE, + MSDC_EMMC50_PAD_DS_TUNE_DLY1, cur_ds_dly1); + if (cur_ds_dly3 != orig_ds_dly3) { + MSDC_SET_FIELD(EMMC50_PAD_DS_TUNE, + MSDC_EMMC50_PAD_DS_TUNE_DLY3, cur_ds_dly3); + } + INIT_MSG("HS400_TUNE: orig_ds_dly1<0x%x>, orig_ds_dly3<0x%x>, cur_ds_dly1<0x%x>, cur_ds_dly3<0x%x>", + orig_ds_dly1, orig_ds_dly3, cur_ds_dly1, cur_ds_dly3); + } + + out: + return err; +} + +/* + register as callback function of WIFI(combo_sdio_register_pm) . + can called by msdc_drv_suspend/resume too. +*/ +void msdc_restore_timing_setting(struct msdc_host *host) +{ + void __iomem *base = host->base; + int retry = 3; + int emmc = (host->hw->host_function == MSDC_EMMC) ? 1 : 0; + int sdio = (host->hw->host_function == MSDC_SDIO) ? 1 : 0; + + if (sdio) { + msdc_reset_hw(host->id); /* force bit5(BV18SDT) to 0 */ + host->saved_para.msdc_cfg = + host->saved_para.msdc_cfg & 0xFFFFFFDF; + MSDC_WRITE32(MSDC_CFG, host->saved_para.msdc_cfg); + } + + do { + msdc_set_mclk(host, host->saved_para.timing, + host->saved_para.hz); + if ((MSDC_READ32(MSDC_CFG) & 0xFFFFFF9F) == + (host->saved_para.msdc_cfg & 0xFFFFFF9F)) + break; + ERR_MSG("msdc set_mclk is unstable (cur_cfg=%x, save_cfg=%x, cur_hz=%d, save_hz=%d)", + MSDC_READ32(MSDC_CFG), + host->saved_para.msdc_cfg, host->mclk, + host->saved_para.hz); + } while (retry--); + + MSDC_WRITE32(SDC_CFG, host->saved_para.sdc_cfg); + + MSDC_WRITE32(MSDC_IOCON, host->saved_para.iocon); + + MSDC_WRITE32(MSDC_PAD_TUNE0, host->saved_para.pad_tune0); + MSDC_WRITE32(MSDC_PAD_TUNE1, host->saved_para.pad_tune1); + + MSDC_WRITE32(MSDC_DAT_RDDLY0, host->saved_para.ddly0); + MSDC_WRITE32(MSDC_DAT_RDDLY1, host->saved_para.ddly1); + + MSDC_WRITE32(MSDC_PATCH_BIT1, host->saved_para.pb1); + MSDC_WRITE32(MSDC_PATCH_BIT2, host->saved_para.pb2); + + if (sdio) { + MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_INT_DAT_LATCH_CK_SEL, + host->saved_para.int_dat_latch_ck_sel); + MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_CKGEN_MSDC_DLY_SEL, + host->saved_para.ckgen_msdc_dly_sel); + MSDC_SET_FIELD(MSDC_INTEN, MSDC_INT_SDIOIRQ, + host->saved_para.inten_sdio_irq); + + autok_init_sdr104(host); + autok_tuning_parameter_init(host, sdio_autok_res[AUTOK_VCORE_HIGH]); + + host->mmc->pm_flags |= MMC_PM_KEEP_POWER; + host->mmc->rescan_entered = 0; + } + + if (emmc) { + MSDC_SET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY1, + host->saved_para.ds_dly1); + MSDC_SET_FIELD(EMMC50_PAD_DS_TUNE, MSDC_EMMC50_PAD_DS_TUNE_DLY3, + host->saved_para.ds_dly3); + MSDC_WRITE32(EMMC50_PAD_CMD_TUNE, + host->saved_para.emmc50_pad_cmd_tune); + MSDC_WRITE32(EMMC50_PAD_DAT01_TUNE, + host->saved_para.emmc50_dat01); + MSDC_WRITE32(EMMC50_PAD_DAT23_TUNE, + host->saved_para.emmc50_dat23); + MSDC_WRITE32(EMMC50_PAD_DAT45_TUNE, + host->saved_para.emmc50_dat45); + MSDC_WRITE32(EMMC50_PAD_DAT67_TUNE, + host->saved_para.emmc50_dat67); + } + + /*msdc_dump_register(host);*/ +} + +void msdc_init_tune_path(struct msdc_host *host, unsigned char timing) +{ + void __iomem *base = host->base; + + if (host->id == 0) + MSDC_WRITE32(MSDC_PAD_TUNE0, 0x00000000); + else + MSDC_SET_FIELD(MSDC_PAD_TUNE0, 0x7FFFFFF, 0x0000000); + + MSDC_CLR_BIT32(MSDC_IOCON, MSDC_IOCON_DDLSEL); + MSDC_CLR_BIT32(MSDC_IOCON, MSDC_IOCON_R_D_SMPL_SEL); + MSDC_CLR_BIT32(MSDC_IOCON, MSDC_IOCON_R_D_SMPL); + if (timing == MMC_TIMING_MMC_HS400) { + MSDC_CLR_BIT32(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLYSEL); + MSDC_CLR_BIT32(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2SEL); + } else { + MSDC_SET_BIT32(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLYSEL); + MSDC_CLR_BIT32(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2SEL); + } + + if (timing == MMC_TIMING_MMC_HS400) + MSDC_CLR_BIT32(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS); + else + MSDC_SET_BIT32(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS); + + MSDC_CLR_BIT32(MSDC_IOCON, MSDC_IOCON_W_D_SMPL_SEL); + + MSDC_CLR_BIT32(MSDC_PATCH_BIT2, MSDC_PB2_CFGRESP); + MSDC_SET_BIT32(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRRDLYSEL); + MSDC_CLR_BIT32(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_CMDRRDLY2SEL); + + MSDC_CLR_BIT32(EMMC50_CFG0, MSDC_EMMC50_CFG_CMD_RESP_SEL); + + /* tune path and related key hw fixed setting should be wrappered follow interface */ + autok_path_sel(host); + +} + +void msdc_init_tune_setting(struct msdc_host *host) +{ + struct msdc_hw *hw = host->hw; + void __iomem *base = host->base; + + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CLKTXDLY, + MSDC_CLKTXDLY); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATWRDLY, + hw->datwrddly); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRRDLY, + hw->cmdrrddly); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRDLY, + hw->cmdrddly); + + MSDC_WRITE32(MSDC_IOCON, 0x00000000); + + MSDC_WRITE32(MSDC_DAT_RDDLY0, 0x00000000); + MSDC_WRITE32(MSDC_DAT_RDDLY1, 0x00000000); + + MSDC_WRITE32(MSDC_PATCH_BIT0, 0x403C000F); + MSDC_WRITE32(MSDC_PATCH_BIT1, 0xFFFE00C9); + + /* 64T + 48T cmd <-> resp */ + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_RESPWAITCNT, 3); + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_RESPSTENSEL, 0); + MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CRCSTSENSEL, 0); + + /* low speed mode should be switch data tune path too even if not covered by autok */ + autok_path_sel(host); +} + +int msdc_tune_cmdrsp(struct msdc_host *host) +{ + int result = 0; + void __iomem *base = host->base; + u32 rsmpl; + u32 dly, dly1, dly2, dly1_sel, dly2_sel; + u32 clkmode, hs400; + + MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, rsmpl); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clkmode); + hs400 = (clkmode == 3) ? 1 : 0; + + rsmpl++; + msdc_set_smpl(host, hs400, rsmpl % 2, TYPE_CMD_RESP_EDGE, NULL); + + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRRDLYSEL, dly1_sel); + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRDLY, dly1); + MSDC_GET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_CMDRRDLY2SEL, dly2_sel); + MSDC_GET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_CMDRDLY2, dly2); + + if (rsmpl >= 2) { + dly = ((dly1_sel ? dly1 : 0) + (dly2_sel ? dly2 : 0) + 1) % 63; + + dly1_sel = 1; + if (dly < 32) { + dly1 = dly; + dly2_sel = 0; + dly2 = 0; + } else { + dly1 = 31; + dly2_sel = 1; + dly2 = dly - 31; + } + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRRDLYSEL, + dly1_sel); + MSDC_SET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_CMDRRDLY2SEL, + dly2_sel); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRDLY, dly1); + MSDC_SET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_CMDRDLY2, dly2); + } + + ++(host->t_counter.time_cmd); + if (host->t_counter.time_cmd == CMD_TUNE_HS_MAX_TIME) { +#ifdef MSDC_LOWER_FREQ + result = msdc_lower_freq(host); +#else + result = 1; +#endif + host->t_counter.time_cmd = 0; + } + + INIT_MSG("TUNE_CMD: rsmpl<%d> dly1<%d> dly2<%d> sfreq.<%d>", + rsmpl & 0x1, dly1, dly2, host->sclk); + + return result; +} + +int msdc_tune_read(struct msdc_host *host) +{ + int result = 0; + void __iomem *base = host->base; + u32 clkmode, hs400, ddr; + u32 dsmpl; + u32 dly, dly1, dly2, dly1_sel, dly2_sel; + int tune_times_max; + + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clkmode); + hs400 = (clkmode == 3) ? 1 : 0; + if (clkmode == 2 || clkmode == 3) + ddr = 1; + else + ddr = 0; + + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DDLSEL, 0); + MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_RD_DAT_SEL, dsmpl); + + if (host->id != 0 && ddr == 0) { + dsmpl++; + msdc_set_smpl(host, hs400, dsmpl % 2, TYPE_READ_DATA_EDGE, + NULL); + tune_times_max = READ_DATA_TUNE_MAX_TIME; + } else { + dsmpl = 2; + tune_times_max = READ_DATA_TUNE_MAX_TIME/2; + } + + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLYSEL, dly1_sel); + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLY, dly1); + MSDC_GET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2SEL, dly2_sel); + MSDC_GET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2, dly2); + + if (dsmpl >= 2) { + dly = ((dly1_sel ? dly1 : 0) + (dly2_sel ? dly2 : 0) + 1) % 63; + + dly1_sel = 1; + if (dly < 32) { + dly1 = dly; + dly2_sel = 0; + dly2 = 0; + } else { + dly1 = 31; + dly2_sel = 1; + dly2 = dly - 31; + } + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLYSEL, + dly1_sel); + MSDC_SET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2SEL, + dly2_sel); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLY, dly1); + MSDC_SET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2, dly2); + } + + ++(host->t_counter.time_read); + if (host->t_counter.time_read == tune_times_max) { +#ifdef MSDC_LOWER_FREQ + result = msdc_lower_freq(host); +#else + result = 1; +#endif + host->t_counter.time_read = 0; + } + + INIT_MSG("TUNE_READ: dsmpl<%d> dly1<0x%x> dly2<0x%x> sfreq.<%d>", + dsmpl & 0x1, dly1, dly2, host->sclk); + + return result; +} + +int msdc_tune_write(struct msdc_host *host) +{ + int result = 0; + void __iomem *base = host->base; + u32 dsmpl; + u32 dly, dly1, dly2, dly1_sel, dly2_sel; + int clkmode, hs400, ddr; + int tune_times_max; + + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clkmode); + hs400 = (clkmode == 3) ? 1 : 0; + if (clkmode == 2 || clkmode == 3) + ddr = 1; + else + ddr = 0; + + if (host->id == 0 && hs400) { + MSDC_GET_FIELD(EMMC50_CFG0, MSDC_EMMC50_CFG_CRC_STS_EDGE, + dsmpl); + } else { + MSDC_GET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTSEDGE, + dsmpl); + } + + if (host->id != 0 && ddr == 0) { + dsmpl++; + msdc_set_smpl(host, hs400, dsmpl % 2, TYPE_WRITE_CRC_EDGE, + NULL); + tune_times_max = WRITE_DATA_TUNE_MAX_TIME; + } else { + dsmpl = 2; + tune_times_max = WRITE_DATA_TUNE_MAX_TIME/2; + } + + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLYSEL, dly1_sel); + MSDC_GET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLY, dly1); + MSDC_GET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2SEL, dly2_sel); + MSDC_GET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2, dly2); + + if (dsmpl >= 2) { + dly = ((dly1_sel ? dly1 : 0) + (dly2_sel ? dly2 : 0) + 1) % 63; + + dly1_sel = 1; + if (dly < 32) { + dly1 = dly; + dly2_sel = 0; + dly2 = 0; + } else { + dly1 = 31; + dly2_sel = 1; + dly2 = dly - 31; + } + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLYSEL, + dly1_sel); + MSDC_SET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2SEL, + dly2_sel); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATRRDLY, dly1); + MSDC_SET_FIELD(MSDC_PAD_TUNE1, MSDC_PAD_TUNE1_DATRRDLY2, dly2); + } + + ++(host->t_counter.time_write); + if (host->t_counter.time_write == tune_times_max) { +#ifdef MSDC_LOWER_FREQ + result = msdc_lower_freq(host); +#else + result = 1; +#endif + host->t_counter.time_write = 0; + } + + INIT_MSG("TUNE_WRITE: dsmpl<%d> dly1<0x%x> dly2<0x%x> sfreq.<%d>", + dsmpl & 0x1, dly1, dly2, host->sclk); + + return result; +} + + + +#ifndef MSDC_WQ_ERROR_TUNE +int msdc_tuning_wo_autok(struct msdc_host *host) +{ + #if 0 + if (host->error & REQ_DAT_ERR) { + if (host->err_mrq_dir & MMC_DATA_WRITE) + return msdc_tune_write_smpl(host); + else if (host->err_mrq_dir & MMC_DATA_WRITE) + return msdc_tune_read_smpl(host); + } else if (host->error & REQ_CMD_EIO) + return msdc_tune_cmdrsp_smpl(host); + /* other error */ + #else + if (host->error & REQ_DAT_ERR) { + if (host->err_mrq_dir & MMC_DATA_WRITE) + return msdc_tune_write(host); + else if (host->err_mrq_dir & MMC_DATA_READ) + return msdc_tune_read(host); + } else if (host->error & REQ_CMD_EIO) { + return msdc_tune_cmdrsp(host); + } + #endif + return 0; +} +#endif + +#define MSDC0_TX_SETTING_NUM (12) +static u32 msdc0_tx_setting_reg[MSDC0_TX_SETTING_NUM][2] = { + {OFFSET_MSDC_IOCON, MSDC_IOCON_DDR50CKD}, + {OFFSET_EMMC50_CFG0, MSDC_EMMC50_CFG_TXSKEW_SEL}, + {OFFSET_MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CLKTXDLY}, + {OFFSET_EMMC50_PAD_CMD_TUNE, MSDC_EMMC50_PAD_CMD_TUNE_TXDLY}, + {OFFSET_EMMC50_PAD_DAT01_TUNE, MSDC_EMMC50_PAD_DAT0_TXDLY}, + {OFFSET_EMMC50_PAD_DAT01_TUNE, MSDC_EMMC50_PAD_DAT1_TXDLY}, + {OFFSET_EMMC50_PAD_DAT23_TUNE, MSDC_EMMC50_PAD_DAT2_TXDLY}, + {OFFSET_EMMC50_PAD_DAT23_TUNE, MSDC_EMMC50_PAD_DAT3_TXDLY}, + {OFFSET_EMMC50_PAD_DAT45_TUNE, MSDC_EMMC50_PAD_DAT4_TXDLY}, + {OFFSET_EMMC50_PAD_DAT45_TUNE, MSDC_EMMC50_PAD_DAT5_TXDLY}, + {OFFSET_EMMC50_PAD_DAT67_TUNE, MSDC_EMMC50_PAD_DAT6_TXDLY}, + {OFFSET_EMMC50_PAD_DAT67_TUNE, MSDC_EMMC50_PAD_DAT7_TXDLY} +}; + +static u8 msdc0_hs400_tx_setting_default_val[MSDC0_TX_SETTING_NUM] = { + MSDC_DDRCKD, + MSDC0_HS400_TXSKEW, + MSDC0_HS400_CLKTXDLY, + MSDC0_HS400_CMDTXDLY, + MSDC0_HS400_DAT0TXDLY, + MSDC0_HS400_DAT1TXDLY, + MSDC0_HS400_DAT2TXDLY, + MSDC0_HS400_DAT3TXDLY, + MSDC0_HS400_DAT4TXDLY, + MSDC0_HS400_DAT5TXDLY, + MSDC0_HS400_DAT6TXDLY, + MSDC0_HS400_DAT7TXDLY +}; + +/* for hs and hs200 */ +static u8 msdc0_hs_tx_setting_default_val[MSDC0_TX_SETTING_NUM] = { + MSDC_DDRCKD, + MSDC0_CLKTXDLY, + MSDC0_TXSKEW, + MSDC0_CMDTXDLY, + MSDC0_DAT0TXDLY, + MSDC0_DAT1TXDLY, + MSDC0_DAT2TXDLY, + MSDC0_DAT3TXDLY, + MSDC0_DAT4TXDLY, + MSDC0_DAT5TXDLY, + MSDC0_DAT6TXDLY, + MSDC0_DAT7TXDLY +}; + +static u8 msdc0_ddr52_tx_setting_default_val[MSDC0_TX_SETTING_NUM] = { + MSDC0_DDR50_DDRCKD, + MSDC0_CLKTXDLY, + MSDC0_TXSKEW, + MSDC0_CMDTXDLY, + MSDC0_DAT0TXDLY, + MSDC0_DAT1TXDLY, + MSDC0_DAT2TXDLY, + MSDC0_DAT3TXDLY, + MSDC0_DAT4TXDLY, + MSDC0_DAT5TXDLY, + MSDC0_DAT6TXDLY, + MSDC0_DAT7TXDLY +}; + +static void msdc_init_tx_setting(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct msdc_host *host = mmc_priv(mmc); + void __iomem *base = host->base; + u8 *tx_setting_default; + int i; + + if (host->hw->host_function == MSDC_EMMC) { + if ((ios->timing == MMC_TIMING_MMC_HS400) && + (ios->clock >= 100000000)) + tx_setting_default = msdc0_hs400_tx_setting_default_val; + else if (ios->timing == MMC_TIMING_MMC_DDR52) + tx_setting_default = msdc0_ddr52_tx_setting_default_val; + else + tx_setting_default = msdc0_hs_tx_setting_default_val; + + for (i = 0; i < MSDC0_TX_SETTING_NUM; i++) { + MSDC_SET_FIELD(base + msdc0_tx_setting_reg[i][0], + msdc0_tx_setting_reg[i][1], + tx_setting_default[i]); + } + } else if (host->hw->host_function == MSDC_SD) { + MSDC_SET_FIELD(MSDC_IOCON, + MSDC_IOCON_DDR50CKD, MSDC_DDRCKD); + if ((ios->timing == MMC_TIMING_UHS_SDR104) && + (ios->clock >= 200000000)) { + MSDC_SET_FIELD(MSDC_PAD_TUNE0, + MSDC_PAD_TUNE0_CLKTXDLY, + MSDC1_CLK_SDR104_TX_VALUE); + } else { + MSDC_SET_FIELD(MSDC_PAD_TUNE0, + MSDC_PAD_TUNE0_CLKTXDLY, + MSDC1_CLK_TX_VALUE); + } + } else if (host->hw->host_function == MSDC_SDIO) { + MSDC_SET_FIELD(MSDC_IOCON, + MSDC_IOCON_DDR50CKD, MSDC_DDRCKD); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, + MSDC_PAD_TUNE0_CLKTXDLY, + MSDC2_CLK_TX_VALUE); + } +} + + +/*For msdc_ios_set_ios()*/ +void msdc_ios_tune_setting(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct msdc_host *host = mmc_priv(mmc); + struct msdc_hw *hw = host->hw; + void __iomem *base = host->base; + u32 mode; + + msdc_set_mclk(host, ios->timing, ios->clock); + if ((ios->timing == MMC_TIMING_MMC_HS400) && + (host->first_tune_done == 0)) + host->first_tune_done = 1; + + if (ios->clock >= 25000000) { + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, mode); + msdc_set_smpl_all(host, mode); + + msdc_init_tx_setting(mmc, ios); + } + + if ((hw->host_function == MSDC_EMMC) && (host->first_tune_done == 1)) { + /*msdc_set_mclk(host, ios->timing, ios->clock);*/ + if (ios->timing == MMC_TIMING_MMC_HS400) { + if (host->mclk >= 100000000) + msdc_execute_tuning(host->mmc, + MMC_SEND_TUNING_BLOCK_HS200); + } else if (ios->timing == MMC_TIMING_MMC_HS200) { + if (host->mclk >= 100000000) + msdc_execute_tuning(host->mmc, + MMC_SEND_TUNING_BLOCK_HS200); + } else { + msdc_init_tune_setting(host); + host->first_tune_done = 0; + } + } +} + +static u32 msdc_status_verify_case1(struct msdc_host *host, + struct mmc_command *cmd) +{ + struct mmc_host *mmc = host->mmc; + u32 status = 0; + u32 state = 0; + u32 err = 0; + unsigned long tmo = jiffies + POLLING_BUSY; + void __iomem *base = host->base; + + while (state != 4) { /* until status to "tran" */ + msdc_reset_hw(host->id); + while ((err = msdc_get_card_status(mmc, host, &status))) { + ERR_MSG("CMD13 ERR<%d>", err); + if (err != (unsigned int)-EILSEQ) { + return msdc_power_tuning(host); + } else if (msdc_tune_cmdrsp(host)) { + ERR_MSG("update cmd para failed"); + return MSDC_VERIFY_ERROR; + } + } + + state = R1_CURRENT_STATE(status); + ERR_MSG("check card state<%d>", state); + if (state == 5 || state == 6) { + ERR_MSG("state<%d> need cmd12 to stop", state); + msdc_send_stop(host); /* don't tuning */ + } else if (state == 7) { /* busy in programing */ + ERR_MSG("state<%d> card is busy", state); + spin_unlock(&host->lock); + msleep(100); + spin_lock(&host->lock); + } else if (state != 4) { + ERR_MSG("state<%d> ??? ", state); + return msdc_power_tuning(host); + } + + if (time_after(jiffies, tmo)) { + ERR_MSG("abort timeout. Do power cycle"); + if ((host->hw->host_function == MSDC_SD) + && (host->sclk >= 100000000 + || (host->timing == MMC_TIMING_UHS_DDR50))) + host->sd_30_busy++; + return msdc_power_tuning(host); + } + } + + msdc_reset_hw(host->id); + return MSDC_VERIFY_NEED_TUNE; +} + +static u32 msdc_status_verify_case2(struct msdc_host *host, + struct mmc_command *cmd) +{ + struct mmc_host *mmc = host->mmc; + u32 status = 0; + u32 state = 0; + u32 err = 0;/*0: can tune normaly; 1: err hapen; 2: tune pass;*/ + struct mmc_card *card = host->mmc->card; + void __iomem *base = host->base; + + while (1) { + msdc_reset_hw(host->id); + err = msdc_get_card_status(mmc, host, &status); + if (!err) { + break; + } else if (err != (unsigned int)-EILSEQ) { + ERR_MSG("CMD13 ERR<%d>", err); + return msdc_power_tuning(host); + } else if (msdc_tune_cmdrsp(host)) { + ERR_MSG("update cmd para failed"); + return MSDC_VERIFY_ERROR; + } + ERR_MSG("CMD13 ERR<%d>", err); + } + state = R1_CURRENT_STATE(status); + + /*wether is right RCA*/ + if (cmd->arg == card->rca << 16) { + return (3 == state || 8 == state) ? MSDC_VERIFY_NEED_TUNE : + MSDC_VERIFY_NEED_NOT_TUNE; + } else { + return (4 == state || 5 == state || 6 == state || 7 == state) + ? MSDC_VERIFY_NEED_TUNE : MSDC_VERIFY_NEED_NOT_TUNE; + } +} + +static u32 msdc_status_verify_case3(struct msdc_host *host, + struct mmc_command *cmd) +{ + struct mmc_host *mmc = host->mmc; + u32 status = 0; + u32 state = 0; + u32 err = 0;/*0: can tune normaly; 1: tune pass;*/ + void __iomem *base = host->base; + + while (1) { + msdc_reset_hw(host->id); + err = msdc_get_card_status(mmc, host, &status); + if (!err) { + break; + } else if (err != (unsigned int)-EILSEQ) { + ERR_MSG("CMD13 ERR<%d>", err); + return msdc_power_tuning(host); + } else if (msdc_tune_cmdrsp(host)) { + ERR_MSG("update cmd para failed"); + return MSDC_VERIFY_ERROR; + } + ERR_MSG("CMD13 ERR<%d>", err); + } + state = R1_CURRENT_STATE(status); + return (5 == state || 6 == state) ? MSDC_VERIFY_NEED_TUNE : + MSDC_VERIFY_NEED_NOT_TUNE; +} + +static u32 msdc_status_verify_case4(struct msdc_host *host, + struct mmc_command *cmd) +{ + struct mmc_host *mmc = host->mmc; + u32 status = 0; + u32 state = 0; + u32 err = 0;/*0: can tune normaly; 1: tune pass;*/ + void __iomem *base = host->base; + + if (cmd->arg & (0x1UL << 15)) + return MSDC_VERIFY_NEED_NOT_TUNE; + while (1) { + msdc_reset_hw(host->id); + err = msdc_get_card_status(mmc, host, &status); + if (!err) { + break; + } else if (err != (unsigned int)-EILSEQ) { + ERR_MSG("CMD13 ERR<%d>", err); + break; + } else if (msdc_tune_cmdrsp(host)) { + ERR_MSG("update cmd para failed"); + return MSDC_VERIFY_ERROR; + } + ERR_MSG("CMD13 ERR<%d>", err); + } + state = R1_CURRENT_STATE(status); + return 3 == state ? MSDC_VERIFY_NEED_NOT_TUNE : + MSDC_VERIFY_NEED_TUNE; +} + +#if 0 +static u32 msdc_status_verify_case5(struct msdc_host *host, + struct mmc_command *cmd) +{ + struct mmc_host *mmc = host->mmc; + u32 status = 0; + u32 state = 0; + u32 err = 0;/*0: can tune normaly; 1: tune pass;*/ + struct mmc_card *card = host->mmc->card; + struct mmc_command cmd_bus_test = { 0 }; + struct mmc_request mrq_bus_sest = { 0 }; + + while ((err = msdc_get_card_status(mmc, host, &status))) { + ERR_MSG("CMD13 ERR<%d>", err); + if (err != (unsigned int)-EILSEQ) { + return msdc_power_tuning(host); + } else if (msdc_tune_cmdrsp(host)) { + ERR_MSG("update cmd para failed"); + return MSDC_VERIFY_ERROR; + } + } + state = R1_CURRENT_STATE(status); + + if (MMC_SEND_TUNING_BLOCK == cmd->opcode) { + if (state == 9) { + /*send cmd14*/ + /*u32 err = -1;*/ + cmd_bus_test.opcode = MMC_BUS_TEST_R; + cmd_bus_test.arg = 0; + cmd_bus_test.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + mrq_bus_sest.cmd = &cmd_bus_test; + cmd_bus_test.mrq = &mrq_bus_sest; + cmd_bus_test.data = NULL; + msdc_do_command(host, &cmd_bus_test, 0, CMD_TIMEOUT); + } + return MSDC_VERIFY_NEED_TUNE; + } + + if (state == 4) { + /*send cmd19*/ + /*u32 err = -1;*/ + cmd_bus_test.opcode = MMC_BUS_TEST_W; + cmd_bus_test.arg = 0; + cmd_bus_test.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + mrq_bus_sest.cmd = &cmd_bus_test; + cmd_bus_test.mrq = &mrq_bus_sest; + cmd_bus_test.data = NULL; + msdc_do_command(host, &cmd_bus_test, 0, CMD_TIMEOUT); + } + return MSDC_VERIFY_NEED_TUNE; +} +#endif + +static u32 msdc_status_verify(struct msdc_host *host, struct mmc_command *cmd) +{ + if (!host->mmc || !host->mmc->card || !host->mmc->card->rca) { + /*card is not identify*/ + return MSDC_VERIFY_NEED_TUNE; + } + + if (((host->hw->host_function == MSDC_EMMC) && + IS_IN_CMD_SET(cmd->opcode, CMD_SET_FOR_MMC_TUNE_CASE1)) + || ((host->hw->host_function == MSDC_SD) && + IS_IN_CMD_SET(cmd->opcode, CMD_SET_FOR_SD_TUNE_CASE1)) + || (host->app_cmd && + IS_IN_CMD_SET(cmd->opcode, CMD_SET_FOR_APP_TUNE_CASE1))) { + return msdc_status_verify_case1(host, cmd); + } else if (IS_IN_CMD_SET(cmd->opcode, CMD_SET_FOR_MMC_TUNE_CASE2)) { + return msdc_status_verify_case2(host, cmd); + } else if (IS_IN_CMD_SET(cmd->opcode, CMD_SET_FOR_MMC_TUNE_CASE3)) { + return msdc_status_verify_case3(host, cmd); + } else if ((host->hw->host_function == MSDC_EMMC) + && IS_IN_CMD_SET(cmd->opcode, CMD_SET_FOR_MMC_TUNE_CASE4)) { + return msdc_status_verify_case4(host, cmd); +#if 0 + } else if ((host->hw->host_function == MSDC_EMMC) + && IS_IN_CMD_SET(cmd->opcode, CMD_SET_FOR_MMC_TUNE_CASE5)) { + return msdc_status_verify_case5(host, cmd); +#endif + } else { + return MSDC_VERIFY_NEED_TUNE; + } + +} + +int msdc_crc_tune(struct msdc_host *host, struct mmc_command *cmd, + struct mmc_data *data, struct mmc_command *stop, + struct mmc_command *sbc) +{ + u32 status_verify = 0; + +#ifdef MTK_MSDC_USE_CMD23 + /* cmd->error also set when autocmd23 crc error */ + if ((cmd->error == (unsigned int)-EILSEQ) + || (stop && (stop->error == (unsigned int)-EILSEQ)) + || (sbc && (sbc->error == (unsigned int)-EILSEQ))) { +#else + if ((cmd->error == (unsigned int)-EILSEQ) + || (stop && (stop->error == (unsigned int)-EILSEQ))) { +#endif + if (msdc_tune_cmdrsp(host)) { + ERR_MSG("failed to updata cmd para"); + return 1; + } + } + + if (data && (data->error == (unsigned int)-EILSEQ)) { + if ((host->id == 0) && + (host->timing == MMC_TIMING_MMC_HS400)) { + if (emmc_hs400_tune_rw(host)) { + ERR_MSG("failed to updata write para"); + return 1; + } + } else if (data->flags & MMC_DATA_READ) { /* read */ + if (msdc_tune_read(host)) { + ERR_MSG("failed to updata read para"); + return 1; + } + } else { + if (msdc_tune_write(host)) { + ERR_MSG("failed to updata write para"); + return 1; + } + } + } + + status_verify = msdc_status_verify(host, cmd); + if (MSDC_VERIFY_ERROR == status_verify) { + ERR_MSG("status verify failed"); + /*data_abort = 1;*/ + if (host->hw->host_function == MSDC_SD) { + if (host->error_tune_enable) { + ERR_MSG("disable error tune of bad SD card"); + host->error_tune_enable = 0; + } + return 1; + } + } else if (MSDC_VERIFY_NEED_NOT_TUNE == status_verify) { + /* clear the error condition. */ + ERR_MSG("need not error tune"); + cmd->error = 0; + return 1; + } + + return 0; +} + +#define CMD_TMO_MSG "exceed max r/w cmd timeout tune times(%d) or SW tmo(%d), Power cycle" +#define RD_TMO_MSG "exceed max read timeout retry times(%d) or SW tmo(%d) or read tmo tuning times(%d), Power cycle" +#define WR_TMO_MSG "exceed max write timeout retry times(%d) or SW tmo(%d) or write tmo tuning time(%d), Power cycle" + +int msdc_cmd_timeout_tune(struct msdc_host *host, struct mmc_command *cmd) +{ + /* CMD TO -> not tuning. + cmd->error also set when autocmd23 TO error */ + if (cmd->error != (unsigned int)-ETIMEDOUT) + return 0; + + if (check_mmc_cmd1718(cmd->opcode) || + check_mmc_cmd2425(cmd->opcode)) { + if ((host->sw_timeout) || + (++(host->rwcmd_time_tune) > MSDC_MAX_TIMEOUT_RETRY)) { + ERR_MSG(CMD_TMO_MSG, + host->rwcmd_time_tune, host->sw_timeout); + if (!(host->sd_30_busy) && msdc_power_tuning(host)) + return 1; + } + } else { + return 1; + } + + return 0; +} + +int msdc_data_timeout_tune(struct msdc_host *host, struct mmc_data *data) +{ + if (!data || (data->error != (unsigned int)-ETIMEDOUT)) + return 0; + + /* [ALPS114710] Patch for data timeout issue. */ + if (data->flags & MMC_DATA_READ) { + if (!(host->sw_timeout) && + (host->hw->host_function == MSDC_SD) && + (host->sclk > 100000000) && + (host->read_timeout_uhs104 < MSDC_MAX_R_TIMEOUT_TUNE)) { + if (host->t_counter.time_read) + host->t_counter.time_read--; + host->read_timeout_uhs104++; + msdc_tune_read(host); + } else if ((host->sw_timeout) || + (host->read_timeout_uhs104 + >= MSDC_MAX_R_TIMEOUT_TUNE) || + (++(host->read_time_tune) + > MSDC_MAX_TIMEOUT_RETRY)) { + ERR_MSG(RD_TMO_MSG, + host->read_time_tune, + host->sw_timeout, host->read_timeout_uhs104); + if (msdc_power_tuning(host)) + return 1; + } + } else if (data->flags & MMC_DATA_WRITE) { + if (!(host->sw_timeout) + && (host->hw->host_function == MSDC_SD) + && (host->sclk > 100000000) + && (host->write_timeout_uhs104 < MSDC_MAX_W_TIMEOUT_TUNE)) { + if (host->t_counter.time_write) + host->t_counter.time_write--; + host->write_timeout_uhs104++; + msdc_tune_write(host); + } else if (!(host->sw_timeout) && + (host->hw->host_function == MSDC_EMMC) && + (host->write_timeout_emmc + < MSDC_MAX_W_TIMEOUT_TUNE_EMMC)) { + if (host->t_counter.time_write) + host->t_counter.time_write--; + host->write_timeout_emmc++; + + if ((host->id == 0) && + (host->timing == MMC_TIMING_MMC_HS400)) + emmc_hs400_tune_rw(host); + else + msdc_tune_write(host); + + } else if ((host->hw->host_function == MSDC_SD) + && ((host->sw_timeout) || + (host->write_timeout_uhs104 + >= MSDC_MAX_W_TIMEOUT_TUNE) || + (++(host->write_time_tune) + > MSDC_MAX_TIMEOUT_RETRY))) { + ERR_MSG(WR_TMO_MSG, + host->write_time_tune, + host->sw_timeout, host->write_timeout_uhs104); + if (!(host->sd_30_busy) && msdc_power_tuning(host)) + return 1; + } else if ((host->hw->host_function == MSDC_EMMC) + && ((host->sw_timeout) || + (++(host->write_time_tune) + > MSDC_MAX_TIMEOUT_RETRY_EMMC))) { + ERR_MSG(WR_TMO_MSG, + host->write_time_tune, + host->sw_timeout, host->write_timeout_emmc); + host->write_timeout_emmc = 0; + return 1; + } + } + + return 0; +} diff --git a/drivers/mmc/host/mediatek/mt6755/msdc_tune.h b/drivers/mmc/host/mediatek/mt6755/msdc_tune.h new file mode 100644 index 0000000000000000000000000000000000000000..9f7c6a753b8b33c0db3563273103ac3947795e74 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/msdc_tune.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _MSDC_TUNE_H_ +#define _MSDC_TUNE_H_ + +#define MSDC_MAX_POWER_CYCLE (5) + +#define MSDC_CLKTXDLY 0 +#define MSDC_DDRCKD 0 + +#define MSDC0_HS400_CLKTXDLY 0 +#define MSDC0_HS400_CMDTXDLY 0xA +#define MSDC0_HS400_DAT0TXDLY 0 +#define MSDC0_HS400_DAT1TXDLY 0 +#define MSDC0_HS400_DAT2TXDLY 0 +#define MSDC0_HS400_DAT3TXDLY 0 +#define MSDC0_HS400_DAT4TXDLY 0 +#define MSDC0_HS400_DAT5TXDLY 0 +#define MSDC0_HS400_DAT6TXDLY 0 +#define MSDC0_HS400_DAT7TXDLY 0 +#define MSDC0_HS400_TXSKEW 1 + +#define MSDC0_DDR50_DDRCKD 1 + +#define MSDC0_CLKTXDLY 0 +#define MSDC0_CMDTXDLY 0 +#define MSDC0_DAT0TXDLY 0 +#define MSDC0_DAT1TXDLY 0 +#define MSDC0_DAT2TXDLY 0 +#define MSDC0_DAT3TXDLY 0 +#define MSDC0_DAT4TXDLY 0 +#define MSDC0_DAT5TXDLY 0 +#define MSDC0_DAT6TXDLY 0 +#define MSDC0_DAT7TXDLY 0 +#define MSDC0_TXSKEW 0 + +#define MSDC1_CLK_TX_VALUE 0 +#define MSDC1_CLK_SDR104_TX_VALUE 3 +#define MSDC2_CLK_TX_VALUE 0 + +/* Declared in msdc_tune.c */ +extern u32 sdio_tune_flag; /* FIX ME: check if it can be removed since it is set + but referenced */ + +void msdc_init_tune_setting(struct msdc_host *host); +void msdc_ios_tune_setting(struct mmc_host *mmc, struct mmc_ios *ios); +void msdc_init_tune_path(struct msdc_host *host, unsigned char timing); + +void msdc_reset_pwr_cycle_counter(struct msdc_host *host); +void msdc_reset_tmo_tune_counter(struct msdc_host *host, unsigned int index); +void msdc_reset_crc_tune_counter(struct msdc_host *host, unsigned int index); +u32 msdc_power_tuning(struct msdc_host *host); +int msdc_tuning_wo_autok(struct msdc_host *host); +int msdc_tune_cmdrsp(struct msdc_host *host); +int emmc_hs400_tune_rw(struct msdc_host *host); +int msdc_tune_read(struct msdc_host *host); +int msdc_tune_write(struct msdc_host *host); +int msdc_crc_tune(struct msdc_host *host, struct mmc_command *cmd, + struct mmc_data *data, struct mmc_command *stop, + struct mmc_command *sbc); +int msdc_cmd_timeout_tune(struct msdc_host *host, struct mmc_command *cmd); +int msdc_data_timeout_tune(struct msdc_host *host, struct mmc_data *data); + +void emmc_clear_timing(void); +void msdc_save_timing_setting(struct msdc_host *host, int save_mode); +void msdc_restore_timing_setting(struct msdc_host *host); + +void msdc_set_bad_card_and_remove(struct msdc_host *host); + +/* For KS only */ +/*int msdc_setting_parameter(struct msdc_hw *hw, unsigned int *para);*/ + +#endif /* end of_MSDC_TUNE_H_ */ diff --git a/drivers/mmc/host/mediatek/mt6755/mt_dump.c b/drivers/mmc/host/mediatek/mt6755/mt_dump.c new file mode 100644 index 0000000000000000000000000000000000000000..61a9b9ddc7829dd165af191d2a245ad4be23bef0 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/mt_dump.c @@ -0,0 +1,2145 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include /* for mdely */ +#include /* __raw_readl */ +#include +#include +#include + +#include "mt_sd.h" +#include +#include "dbg.h" + +#ifdef MTK_MSDC_USE_CACHE +unsigned int g_power_reset; +#endif + +MODULE_LICENSE("GPL"); +/*--------------------------------------------------------------------------*/ +/* head file define */ +/*--------------------------------------------------------------------------*/ +#define MTK_MMC_DUMP_DBG (0) +#if MTK_MMC_DUMP_DBG +#define MTK_DUMP_PR_ERR(fmt, args...) pr_err(fmt, ##args) +#define MTK_DUMP_PR_DBG(fmt, args...) pr_debug(fmt, ##args) +#else +#define MTK_MMC_DUMP(fmt, args...) +#define MTK_DUMP_PR_ERR(fmt, args...) +#define MTK_DUMP_PR_DBG(fmt, args...) +#endif + +#define MAX_POLLING_STATUS (50000) + +struct simp_mmc_card; +struct simp_msdc_host; +#define MSDC_PS_DAT0 (0x1 << 16) /* R */ +struct simp_mmc_host { + int index; + unsigned int f_min; + unsigned int f_max; + unsigned int f_init; + u32 ocr_avail; + + unsigned int caps; /* Host capabilities */ + unsigned int caps2; /* More host capabilities */ + + /* host specific block data */ + unsigned int max_seg_size; /* blk_queue_max_segment_size */ + unsigned short max_segs; /* blk_queue_max_segments */ + unsigned short unused; + unsigned int max_req_size; /* maximum bytes in one req */ + unsigned int max_blk_size; /* maximum size of one block */ + unsigned int max_blk_count; /* maximum blocks in one req */ + unsigned int max_discard_to; /* max. discard timeout in ms */ + + u32 ocr; /* the current OCR setting */ + + struct simp_mmc_card *card; /* card attached to this host */ + + unsigned int actual_clock; /* Actual HC clock */ + + /* add msdc struct */ + struct simp_msdc_host *mtk_host; +}; + +struct simp_mmc_card { + struct simp_mmc_host *host; /* card's belonging host */ + unsigned int rca; /* relative card address */ + unsigned int type; /* card type */ + unsigned int state; /* (our) card state */ + unsigned int quirks; /* card quirks */ + + unsigned int erase_size; /* erase size in sectors */ + unsigned int erase_shift; /* if erase unit is power 2 */ + unsigned int pref_erase; /* in sectors */ + u8 erased_byte; /* value of erased bytes */ + + u32 raw_cid[4]; /* raw card CID */ + u32 raw_csd[4]; /* raw card CSD */ + u32 raw_scr[2]; /* raw card SCR */ + struct mmc_cid cid; /* card identification */ + struct mmc_csd csd; /* card specific */ + struct mmc_ext_csd ext_csd; /* MMC extended card specific */ + struct sd_scr scr; /* extra SD information */ + struct sd_ssr ssr; /* yet more SD information */ + struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ + + unsigned int sd_bus_speed; /* Current Bus Speed Mode */ +}; + +struct simp_msdc_card { + unsigned int rca; /* relative card address */ + unsigned int type; /* card type */ + unsigned short state; /* card state */ + unsigned short file_system; /* FAT16/FAT32 */ + unsigned short card_cap; /* High Capcity/standard */ +}; + +struct simp_msdc_host { + struct simp_msdc_card *card; + void __iomem *base; /* host base address */ + unsigned char id; /* host id number */ + unsigned int clk; /* host clock value from + clock source */ + unsigned int sclk; /* working SD clock speed */ + unsigned char clksrc; /* clock source */ + void *priv; /* private data */ +}; + +enum { + FAT16 = 0, + FAT32 = 1, + exFAT = 2, + _RAW_ = 3, +}; + +enum { + standard_capacity = 0, + high_capacity = 1, + extended_capacity = 2, +}; + +/* command argument */ +#define CMD0_ARG (0) +#define CMD2_ARG (0) +#define CMD3_ARG (0) +#define CMD7_ARG (phost->card->rca) +#define CMD8_ARG_VOL_27_36 (0x100) +#define CMD8_ARG_PATTERN (0x5a) /* or 0xAA */ +#define CMD8_ARG (CMD8_ARG_VOL_27_36 | CMD8_ARG_PATTERN) +#define CMD9_ARG (phost->card->rca) +#define CMD10_ARG (phost->card->rca) +#define CMD12_ARG (0) +#define CMD13_ARG (phost->card->rca) +#define CMD55_ARG (phost->card->rca) + +#define ACMD6_ARG_BUS_WIDTH_4 (0x2) +#define ACMD6_ARG (ACMD6_ARG_BUS_WIDTH_4) + +#define ACMD41_ARG_HCS (1 << 30) +#define ACMD41_ARG_VOL_27_36 (0xff8000) +#define ACMD41_ARG_20 (ACMD41_ARG_VOL_27_36 | ACMD41_ARG_HCS) +#define ACMD41_ARG_10 (ACMD41_ARG_VOL_27_36) + +#define ACMD6_ARG_EMMC ((MMC_SWITCH_MODE_WRITE_BYTE << 24) \ + | (EXT_CSD_BUS_WIDTH << 16) \ + | (EXT_CSD_BUS_WIDTH_4 << 8) \ + | EXT_CSD_CMD_SET_NORMAL) + +#define ACMD6_ARG_DISABLE_CACHE ((MMC_SWITCH_MODE_WRITE_BYTE << 24) \ + | (EXT_CSD_CACHE_CTRL << 16) \ + | (0 << 8) | EXT_CSD_CMD_SET_NORMAL) + +#define CMD_RAW(cmd, rspt, dtyp, rw, len, stop) \ + ((cmd) | (rspt << 7) | (dtyp << 11) | \ + (rw << 13) | (len << 16) | (stop << 14)) + +#define CMD0_RAW CMD_RAW(0 , msdc_rsp[RESP_NONE], 0, 0, 0, 0) +#define CMD1_RAW CMD_RAW(1 , msdc_rsp[RESP_R3] , 0, 0, 0, 0) +#define CMD2_RAW CMD_RAW(2 , msdc_rsp[RESP_R2] , 0, 0, 0, 0) +#define CMD3_RAW CMD_RAW(3 , msdc_rsp[RESP_R1] , 0, 0, 0, 0) +#define CMD7_RAW CMD_RAW(7 , msdc_rsp[RESP_R1] , 0, 0, 0, 0) +#define CMD8_RAW CMD_RAW(8 , msdc_rsp[RESP_R7] , 0, 0, 0, 0) +#define CMD8_RAW_EMMC CMD_RAW(8 , msdc_rsp[RESP_R1] , 1, 0, 512, 0) +#define CMD9_RAW CMD_RAW(9 , msdc_rsp[RESP_R2] , 0, 0, 0, 0) +#define CMD10_RAW CMD_RAW(10, msdc_rsp[RESP_R2] , 0, 0, 0, 0) +#define CMD12_RAW CMD_RAW(12, msdc_rsp[RESP_R1B] , 0, 0, 0, 1) +#define CMD13_RAW CMD_RAW(13, msdc_rsp[RESP_R1] , 0, 0, 0, 0) +#define CMD17_RAW CMD_RAW(17, msdc_rsp[RESP_R1] , 1, 0, 512, 0) +#define CMD18_RAW CMD_RAW(18, msdc_rsp[RESP_R1] , 2, 0, 512, 0) +#define CMD24_RAW CMD_RAW(24, msdc_rsp[RESP_R1] , 1, 1, 512, 0) +#define CMD25_RAW CMD_RAW(25, msdc_rsp[RESP_R1] , 2, 1, 512, 0) +#define CMD55_RAW CMD_RAW(55, msdc_rsp[RESP_R1] , 0, 0, 0, 0) + +#define ACMD6_RAW CMD_RAW(6 , msdc_rsp[RESP_R1] , 0, 0, 0, 0) +#define ACMD6_RAW_EMMC CMD_RAW(6 , msdc_rsp[RESP_R1B] , 0, 0, 0, 0) +#define ACMD41_RAW CMD_RAW(41, msdc_rsp[RESP_R3] , 0, 0, 0, 0) + +/* command response */ +#define R3_OCR_POWER_UP_BIT (1 << 31) +#define R3_OCR_CARD_CAPACITY_BIT (1 << 30) + +/* some marco will be reuse with mmc subsystem */ +static int simp_mmc_init(int card_type, bool boot); +static int module_init_emmc; +static int module_init_sd; +static int emmc_init; +static int sd_init; + +#define SIMP_SUCCESS (0) +#define SIMP_FAILED (-1) + +/* the base address of sd card slot */ +#define BOOT_STORAGE_ID (0) +#define EXTEND_STORAGE_ID (1) + +#define BLK_LEN (512) +#define MAX_SCLK (52000000) +#define NORMAL_SCLK (25000000) +#define MIN_SCLK (260000) + +#define MAX_DMA_CNT (64 * 1024 - 512) + +#define CMD_WAIT_RETRY (0x8FFFFFFF) + +static struct simp_msdc_host g_msdc_host[2]; +static struct simp_msdc_card g_msdc_card[2]; +static struct simp_msdc_host *pmsdc_boot_host = &g_msdc_host[BOOT_STORAGE_ID]; +static struct simp_msdc_host *pmsdc_extend_host = + &g_msdc_host[EXTEND_STORAGE_ID]; +static struct simp_mmc_host g_mmc_host[2]; +static struct simp_mmc_card g_mmc_card[2]; +static struct simp_mmc_host *pmmc_boot_host = &g_mmc_host[BOOT_STORAGE_ID]; +static struct simp_mmc_host *pmmc_extend_host = + &g_mmc_host[EXTEND_STORAGE_ID]; + +static void msdc_mdelay(u32 time) +{ + u64 t_start = 0, t_end = 0; + + t_start = arch_counter_get_cntpct(); + t_end = t_start + time * 1000 * 1000 / 77; + while (t_end > arch_counter_get_cntpct()) + cpu_relax(); +} + +#define mt_dump_msdc_retry(expr, retry, cnt, id) \ + do { \ + int backup = cnt; \ + while (retry) { \ + if (!(expr))\ + break; \ + if (cnt-- == 0) { \ + retry--;\ + msdc_mdelay(1);\ + cnt = backup; \ + } \ + } \ + if (retry == 0) \ + simp_msdc_dump_info(id); \ + WARN_ON(retry == 0); \ + } while (0) + +#define mt_dump_msdc_clr_fifo(id) \ + do { \ + int retry = 3, cnt = 1000; \ + MSDC_SET_BIT32(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \ + mt_dump_msdc_retry(MSDC_READ32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, \ + retry, cnt, id); \ + } while (0) + +static void simp_msdc_dump_info(unsigned int id) +{ + void __iomem *base = g_msdc_host[id].base; + + msdc_dump_register_core(id, base); + msdc_dump_clock_sts(); + msdc_dump_padctl_by_id(id); + msdc_dump_dbg_register_core(id, base); +} + +static void simp_msdc_config_clksrc(struct simp_msdc_host *host, + unsigned int clksrc) +{ + u32 *hclks = msdc_get_hclks(host->id); + host->clksrc = clksrc; + host->clk = hclks[clksrc]; +} + +static void simp_msdc_config_clock(struct simp_msdc_host *host, unsigned int hz) +{ + /* struct msdc_hw *hw = host->priv; */ + void __iomem *base = host->base; + u32 mode; /* use divisor or not */ + u32 div = 0; + u32 sclk; + u32 hclk = host->clk; + u32 orig_clksrc = host->clksrc; + + if (hz >= hclk) { + mode = 0x1; /* no divisor */ + sclk = hclk; + } else { + mode = 0x0; /* use divisor */ + if (hz >= (hclk >> 1)) { + div = 0; /* mean div = 1/2 */ + sclk = hclk >> 1; /* sclk = clk / 2 */ + } else { + div = (hclk + ((hz << 2) - 1)) / (hz << 2); + sclk = (hclk >> 2) / div; + } + } + host->sclk = sclk; + + /* set clock mode and divisor */ + /*simp_msdc_config_clksrc(host, MSDC_CLKSRC_NONE);*/ + + /* designer said: best way is wait clk stable while modify clk + config bit */ + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD|MSDC_CFG_CKDIV, + (mode << 12)|(div % 0xfff)); + + simp_msdc_config_clksrc(host, orig_clksrc); + + /* wait clock stable */ + while (!(MSDC_READ32(MSDC_CFG) & MSDC_CFG_CKSTB)) + ; +} + +static void msdc_set_timeout(struct simp_msdc_host *host, u32 ns, u32 clks) +{ + void __iomem *base = host->base; + u32 timeout, clk_ns; + + clk_ns = 1000000000UL / host->sclk; + timeout = ns / clk_ns + clks; + timeout = timeout >> 20; /* in 2^20 sclk cycle unit */ + timeout = timeout > 1 ? timeout - 1 : 0; + timeout = timeout > 255 ? 255 : timeout; + + MSDC_SET_FIELD(SDC_CFG, SDC_CFG_DTOC, timeout); +} + +#ifndef FPGA_PLATFORM +/* Note: shall be in drivers/misc/mediatek/pmic_wrap/mt6755/pwrap_hal.h */ +#ifdef MT6351_INT_STA +#undef MT6351_INT_STA /*to avoid build warning about redefining in upmu_hw.h*/ +#endif +#include + +#define msdc_power_set_field(reg, field, val) \ + do { \ + unsigned int tv; \ + pwrap_read_nochk(reg, &tv); \ + tv &= ~(field); \ + tv |= ((val) << (uffs((unsigned int)field) - 1)); \ + pwrap_write_nochk(reg, tv); \ + } while (0) + +#define msdc_power_get_field(reg, field, val) \ + do { \ + unsigned int tv; \ + pwrap_read_nochk(reg, &tv); \ + val = ((tv & (field)) >> (uffs((unsigned int)field) - 1)); \ + } while (0) +#endif + +static unsigned int simp_mmc_power_up(struct simp_mmc_host *host, bool on) +{ + MTK_DUMP_PR_ERR("[%s]: on=%d, start\n", __func__, on); + +#ifdef FPGA_PLATFORM + msdc_fpga_power(mtk_msdc_host[host->mtk_host->id], on); +#else + switch (host->mtk_host->id) { + case 0: + if (on) { + msdc_power_set_field(REG_VEMC_VOSEL, + FIELD_VEMC_VOSEL, VEMC_VOSEL_3V); + msdc_power_set_field(REG_VEMC_EN, FIELD_VEMC_EN, 0x1); + } else { + msdc_power_set_field(REG_VEMC_EN, FIELD_VEMC_EN, 0x0); + } + break; + case 1: + if (on) { + msdc_power_set_field(REG_VMC_VOSEL, FIELD_VMC_VOSEL, + VMC_VOSEL_3V); + msdc_power_set_field(REG_VMC_EN, FIELD_VMC_EN, 0x1); + msdc_power_set_field(REG_VMCH_VOSEL, FIELD_VMCH_VOSEL, + VMCH_VOSEL_3V); + msdc_power_set_field(REG_VMCH_EN, FIELD_VMCH_EN, 0x1); + } else{ + msdc_power_set_field(REG_VMC_EN, FIELD_VMC_EN, 0x0); + msdc_power_set_field(REG_VMCH_EN, FIELD_VMCH_EN, 0x0); + } + break; + default: + break; + } +#endif + + MTK_DUMP_PR_ERR("[%s]: on=%d, end\n", __func__, on); + + return SIMP_SUCCESS; +} + +#define clk_readl(addr) \ + MSDC_READ32(addr) + +#define clk_setl(addr, val) \ + mt_reg_sync_writel(clk_readl(addr) | (val), addr) + +#define clk_clrl(addr, val) \ + mt_reg_sync_writel(clk_readl(addr) & ~(val), addr) + +static unsigned int simp_mmc_enable_clk(struct simp_mmc_host *host) +{ +#ifndef FPGA_PLATFORM + /*check base, cause KE too early to initial it at msdc_drv_probe*/ + if (NULL == apmixed_reg_base || NULL == topckgen_reg_base + || NULL == infracfg_ao_reg_base) { + pr_err("apmixed_reg_base=%p, topckgen_reg_base=%p, infracfg_ao_reg_base=%p\n", + apmixed_reg_base, topckgen_reg_base, + infracfg_ao_reg_base); + return SIMP_FAILED; + } + + /* step1: open pll */ + clk_setl(apmixed_reg_base + MSDCPLL_PWR_CON0_OFFSET, 0x3); + msdc_mdelay(1); + clk_setl(apmixed_reg_base + MSDCPLL_PWR_CON0_OFFSET, 0x1); + + clk_setl(apmixed_reg_base + MSDCPLL_CON1_OFFSET, 0x80000000); + + clk_setl(apmixed_reg_base + MSDCPLL_CON0_OFFSET, 0x1); + msdc_mdelay(1); + + /* step2: enable mux */ + mt_reg_sync_writel(0x07010100, + topckgen_reg_base + MSDC_CLK_CFG_3_OFFSET); + + mt_reg_sync_writel(0x01000107, + topckgen_reg_base + MSDC_CLK_CFG_4_OFFSET); + + mt_reg_sync_writel(0x00006000, + topckgen_reg_base + MSDC_CLK_UPDATE_OFFSET); + + mt_reg_sync_writel(0xFFFFFFFF, + infracfg_ao_reg_base + MSDC_INFRA_PDN_CLR1_OFFSET); + +#if MTK_MMC_DUMP_DBG + msdc_dump_clock_sts(); +#endif + +#endif + return SIMP_SUCCESS; +} + +static unsigned int simp_mmc_hw_reset_for_init(struct simp_mmc_host *host) +{ + void __iomem *base; + + base = host->mtk_host->base; + if (0 == host->mtk_host->id) { + /* check emmc card support HW Rst_n or not is better way. + * but if the card does not support it , here just failed. + * if the card support it, Rst_n function enable under DA + * driver, see SDMMC_Download_BL_PostProcess_Internal() */ + /* >=1ms to trigger emmc enter pre-idle state */ + MSDC_SET_BIT32(EMMC_IOCON, EMMC_IOCON_BOOTRST); + msdc_mdelay(1); + MSDC_CLR_BIT32(EMMC_IOCON, EMMC_IOCON_BOOTRST); + + /* clock is need after Rst_n pull high, and the card need + * clock to calculate time for tRSCA, tRSTH */ + MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_CKPDN); + msdc_mdelay(1); + + /* not to close, enable clock free run under mt_dump */ + /*MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_CKPDNT);*/ + } + + return SIMP_SUCCESS; +} + +static void simp_msdc_dma_stop(struct simp_msdc_host *host) +{ + void __iomem *base = host->base; + int retry = 500; + int count = 1000; + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); + mt_dump_msdc_retry((MSDC_READ32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS), + retry, count, host->id); + if (retry == 0) { + pr_err("#### Failed to stop DMA! please check it here ####"); + /*BUG();*/ + } +} + +static unsigned int simp_msdc_init(struct simp_mmc_host *mmc_host) +{ + unsigned int ret = 0; + void __iomem *base; + struct simp_msdc_host *host = mmc_host->mtk_host; + + /*struct msdc_hw *hw;*/ + /* Todo1: struct msdc_hw in board.c */ + + base = host->base; + + /* set to SD/MMC mode, the first step while operation msdc */ + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_MODE, 1); /* MSDC_SDMMC */ + + /* reset controller */ + msdc_reset(host->id); + + sd_debug_zone[host->id] = DBG_EVT_ALL; + simp_msdc_dma_stop(host); + + /* clear FIFO */ + mt_dump_msdc_clr_fifo(host->id); + + /* Disable & Clear all interrupts */ + msdc_clr_int(); + MSDC_WRITE32(MSDC_INTEN, 0); + + /* reset tuning parameter */ + MSDC_WRITE32(MSDC_PAD_TUNE0, 0x00000000); + MSDC_WRITE32(MSDC_DAT_RDDLY0, 0x00000000); + MSDC_WRITE32(MSDC_DAT_RDDLY1, 0x00000000); + MSDC_WRITE32(MSDC_IOCON, 0x00000000); + MSDC_WRITE32(MSDC_PATCH_BIT0, 0x003C000F); + + /* PIO mode */ + MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_PIO); + + /* sdio + inswkup*/ + MSDC_SET_BIT32(SDC_CFG, SDC_CFG_SDIO); + MSDC_SET_BIT32(SDC_CFG, SDC_CFG_INSWKUP); + + /* disable async fifo use interl delay*/ + MSDC_CLR_BIT32(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_RXDLYSEL); + MSDC_SET_BIT32(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS); + MSDC_CLR_BIT32(MSDC_PATCH_BIT2, MSDC_PB2_CFGRESP); + + /* disable support 64G */ + MSDC_SET_BIT32(MSDC_PATCH_BIT2, MSDC_PB2_SUPPORT64G); + + /* set Driving SMT PUPD */ + + msdc_set_driving_by_id(host->id, mtk_msdc_host[host->id]->hw, 0); + + msdc_set_smt_by_id(host->id, 1); + msdc_pin_config_by_id(host->id, MSDC_PIN_PULL_UP); + + /* set sampling edge */ + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, 0); /* rising: 0 */ + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_R_D_SMPL, 0); + + /* write crc timeout detection */ + MSDC_SET_FIELD(MSDC_PATCH_BIT0, 1 << 30, 1); + + /* Clock source select*/ + simp_msdc_config_clksrc(host, host->clksrc); + + /* Bus width to 1 bit*/ + MSDC_SET_FIELD(SDC_CFG, SDC_CFG_BUSWIDTH, 0); + + /* make sure the clock is 260K */ + simp_msdc_config_clock(host, MIN_SCLK); + + /* Set Timeout 100ms*/ + msdc_set_timeout(host, 100000000, 0); + + MSDC_CLR_BIT32(MSDC_PS, MSDC_PS_CDEN); + + /* detect card */ + /* need to check card is insert [Fix me] */ + + /* check write protection [Fix me] */ + +#if 0 + /* simple test for clk output */ + MSDC_WRITE32(MSDC_PATCH_BIT0, 0xF3F); + MSDC_WRITE32(MSDC_CFG, 0x10001013); + MSDC_WRITE32(SDC_CFG, 0x0); + MSDC_WRITE32(SDC_CMD, 0x0); + MSDC_WRITE32(SDC_ARG, 0x0); + + /* dump register for debug */ + simp_msdc_dump_info(host->id); +#endif + + + return ret; +} + + +static void simp_mmc_set_bus_mode(struct simp_mmc_host *host, unsigned int mode) +{ + /* mtk: msdc not support to modify bus mode */ + +} + +/* =======================something for msdc cmd/data */ +u8 simp_ext_csd[512]; +static int simp_msdc_cmd(struct simp_msdc_host *host, + unsigned int cmd, unsigned int raw, + unsigned int arg, int rsptyp, unsigned int *resp) +{ + int retry = 5000; /*CMD_WAIT_RETRY; */ + void __iomem *base = host->base; + unsigned int error = 0; + unsigned int intsts = 0; + unsigned int cmdsts = + MSDC_INT_CMDRDY | MSDC_INT_CMDTMO | MSDC_INT_RSPCRCERR; + + /* wait before send command */ + if (cmd == MMC_SEND_STATUS) { + while (retry--) { + if (!sdc_is_cmd_busy()) + break; + msdc_mdelay(1); + } + if (retry == 0) { + error = 1; + goto end; + } + } else { + while (retry--) { + if (!sdc_is_busy()) + break; + msdc_mdelay(1); + } + if (retry == 0) { + error = 2; + goto end; + } + } + + sdc_send_cmd(raw, arg); + + MTK_DUMP_PR_ERR("cmd=0x%x, arg=0x%x\n", raw, arg); + + /* polling to check the interrupt */ + retry = 5000; /*CMD_WAIT_RETRY;*/ + while ((intsts & cmdsts) == 0) { + intsts = MSDC_READ32(MSDC_INT); + retry--; +#if MTK_MMC_DUMP_DBG + if (retry % 1000 == 0) { + pr_debug("int cmd=0x%x, arg=0x%x, retry=0x%x, intsts=0x%x\n", + raw, arg, retry, intsts); + simp_msdc_dump_info(host->id); + } +#endif + if (retry == 0) { + error = 3; + goto end; + } + msdc_mdelay(1); + } + + intsts &= cmdsts; + MSDC_WRITE32(MSDC_INT, intsts); /* clear interrupts */ + + if (intsts & MSDC_INT_CMDRDY) { + /* get the response */ + switch (rsptyp) { + case RESP_NONE: + break; + case RESP_R2: + *resp++ = MSDC_READ32(SDC_RESP3); + *resp++ = MSDC_READ32(SDC_RESP2); + *resp++ = MSDC_READ32(SDC_RESP1); + *resp = MSDC_READ32(SDC_RESP0); + break; + default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ + *resp = MSDC_READ32(SDC_RESP0); + } + + MTK_DUMP_PR_DBG("msdc cmd<%d> arg<0x%x> resp<0x%x>Ready \r\n", + cmd, arg, *resp); + + } else { + error = 4; + goto end; + } + + if (rsptyp == RESP_R1B) { + retry = 9999; + while ((MSDC_READ32(MSDC_PS) & MSDC_PS_DAT0) != MSDC_PS_DAT0) { + retry--; + if (retry % 5000 == 0) { + pr_debug("int cmd=0x%x, arg=0x%x, retry=0x%x, intsts=0x%x\n", + raw, arg, retry, intsts); + simp_msdc_dump_info(host->id); + } + if (retry == 0) { + error = 5; + goto end; + } + msdc_mdelay(1); + } + + MTK_DUMP_PR_DBG("msdc cmd<%d> done \r\n", cmd); + + } + +end: + if (error) { + pr_err("cmd:%d, arg:0x%x, error=%d, intsts=0x%x\n", + cmd, arg, error, intsts); + simp_msdc_dump_info(host->id); + } + + return error; +} + +/* ======================= */ + +static int simp_mmc_go_idle(struct simp_mmc_host *host) +{ + int err = 0; + unsigned int resp = 0; + struct simp_msdc_host *phost = host->mtk_host; + + err = simp_msdc_cmd(phost, MMC_GO_IDLE_STATE, CMD0_RAW, CMD0_ARG, + RESP_NONE, &resp); + + return err; +} + +static unsigned int simp_mmc_get_status(struct simp_mmc_host *host, + unsigned int *status) +{ + unsigned int resp = 0; + unsigned int err = 0; + struct simp_msdc_host *phost = host->mtk_host; + unsigned int rca = 0; + +#ifdef MTK_MSDC_USE_CACHE + if (g_power_reset) + rca = phost->card->rca << 16; + else + rca = mtk_msdc_host[host->index]->mmc->card->rca << 16; +#else + rca = phost->card->rca << 16; +#endif + + /* pr_debug("rca=0x%x, mtk_msdc_host[%d]->mmc->card->rca=0x%x, + phost->card->rca=0x%x\n", rca, host->index, + mtk_msdc_host[host->index]->mmc->card->rca, phost->card->rca); */ + err = simp_msdc_cmd(phost, MMC_SEND_STATUS, CMD13_RAW, rca, RESP_R1, + &resp); + + *status = resp; + + return err; +} + +static unsigned int simp_mmc_send_stop(struct simp_mmc_host *host) +{ + unsigned int resp = 0; + unsigned int err = 0; + struct simp_msdc_host *phost = host->mtk_host; + + /* send command */ + err = simp_msdc_cmd(phost, MMC_STOP_TRANSMISSION, CMD12_RAW, 0, + RESP_R1B, &resp); + + return err; +} + +static int simp_mmc_send_op_cond(struct simp_mmc_host *host, + unsigned int ocr, unsigned int *rocr) +{ + int err = 0, i; + unsigned int resp = 0; + struct simp_msdc_host *phost = host->mtk_host; + + for (i = 500; i; i--) { + err = simp_msdc_cmd(phost, MMC_SEND_OP_COND, CMD1_RAW, ocr, + RESP_R3, &resp); + if (err) + break; + + /* if we're just probing, do a single pass */ + if (ocr == 0) + break; + + /* otherwise wait until reset completes */ + if (resp & MMC_CARD_BUSY) + break; + + err = -ETIMEDOUT; + + msdc_mdelay(10); + } + + if (rocr) + *rocr = resp; + + if (i <= 400) + pr_err("cmd1: resp(0x%x), i=%d\n", resp, i); + + return err; +} + +static int simp_mmc_all_send_cid(struct simp_mmc_host *host, unsigned int *cid) +{ + int err = 0; + + err = simp_msdc_cmd(host->mtk_host, MMC_ALL_SEND_CID, CMD2_RAW, + CMD2_ARG, RESP_R2, cid); + + MTK_DUMP_PR_DBG("cidp: 0x%x 0x%x 0x%x 0x%x\n", + cid[0], cid[1], cid[2], cid[3]); + + return err; +} + +#if 0 +static int simp_mmc_set_relative_addr(struct simp_mmc_card *card) +{ + int err; + unsigned int resp; + + err = simp_msdc_cmd(card->host->mtk_host, MMC_SET_RELATIVE_ADDR, + CMD3_RAW, card->rca << 16, RESP_R1, &resp); + + return err; +} +#endif + +#if 0 +static int simp_mmc_send_csd(struct simp_mmc_card *card, unsigned int *csd) +{ + int err; + unsigned int resp[4] = { 0 }; + + err = simp_msdc_cmd(card->host->mtk_host, MMC_SEND_CSD, CMD9_RAW, + card->rca << 16, RESP_R2, resp); + + memcpy(csd, resp, sizeof(u32) * 4); + + return err; +} +#endif + +/* +static const unsigned int tran_exp[] = { + 10000, 100000, 1000000, 10000000, + 0, 0, 0, 0 +}; + +static const unsigned char tran_mant[] = { + 0, 10, 12, 13, 15, 20, 25, 30, + 35, 40, 45, 50, 55, 60, 70, 80, +}; + +static const unsigned int tacc_exp[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, +}; + +static const unsigned int tacc_mant[] = { + 0, 10, 12, 13, 15, 20, 25, 30, + 35, 40, 45, 50, 55, 60, 70, 80, +};*/ + +static int simp_mmc_decode_csd(struct simp_mmc_card *card) +{ + struct mmc_csd *csd = &card->csd; + /* + unsigned int e, m, a, b; + */ + u32 *resp = card->raw_csd; + + /* + * We only understand CSD structure v1.1 and v1.2. + * v1.2 has extra information in bits 15, 11 and 10. + * We also support eMMC v4.4 & v4.41. + */ + csd->structure = UNSTUFF_BITS(resp, 126, 2); + if (csd->structure == 0) { + pr_err("unrecognised CSD structure version %d\n", + csd->structure); + return -EINVAL; + } + + csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4); + +/* + m = UNSTUFF_BITS(resp, 115, 4); + e = UNSTUFF_BITS(resp, 112, 3); + csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; + csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; + + m = UNSTUFF_BITS(resp, 99, 4); + e = UNSTUFF_BITS(resp, 96, 3); + csd->max_dtr = tran_exp[e] * tran_mant[m]; + csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); + + e = UNSTUFF_BITS(resp, 47, 3); + m = UNSTUFF_BITS(resp, 62, 12); + csd->capacity = (1 + m) << (e + 2); + + csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); + csd->read_partial = UNSTUFF_BITS(resp, 79, 1); + csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); + csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); + csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); + csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); + csd->write_partial = UNSTUFF_BITS(resp, 21, 1); + + if (csd->write_blkbits >= 9) { + a = UNSTUFF_BITS(resp, 42, 5); + b = UNSTUFF_BITS(resp, 37, 5); + csd->erase_size = (a + 1) * (b + 1); + csd->erase_size <<= csd->write_blkbits - 9; + } +*/ + + return 0; +} + +static int simp_mmc_select_card(struct simp_mmc_host *host, + struct simp_mmc_card *card) +{ + int err; + unsigned int resp; + struct simp_msdc_host *phost = host->mtk_host; + + err = simp_msdc_cmd(phost, MMC_SELECT_CARD, CMD7_RAW, card->rca << 16, + RESP_R1, &resp); + + return 0; +} + +/* + * Mask off any voltages we don't support and select + * the lowest voltage + */ +static unsigned int simp_mmc_select_voltage(struct simp_mmc_host *host, + unsigned int ocr) +{ +#if 0 + int bit; + + ocr &= host->ocr_avail; + + bit = ffs(ocr); + if (bit) { + bit -= 1; + + ocr &= 3 << bit; + + mmc_host_clk_hold(host); + host->ios.vdd = bit; + mmc_set_ios(host); + mmc_host_clk_release(host); + } else { + pr_warn("%s: host doesn't support card's voltages\n", + mmc_hostname(host)); + ocr = 0; + } +#endif + + return ocr; +} + +static int simp_msdc_pio_read(struct simp_msdc_host *host, + unsigned int *ptr, unsigned int size); +static void simp_msdc_set_blknum(struct simp_msdc_host *host, + unsigned int blknum); + +static int simp_mmc_read_ext_csd(struct simp_mmc_host *host, + struct simp_mmc_card *card) +{ + int err = 0; + unsigned int resp; + struct simp_msdc_host *phost = host->mtk_host; + void __iomem *base = phost->base; + memset(simp_ext_csd, 0, 512); + if (card->csd.mmca_vsn < CSD_SPEC_VER_4) { + pr_debug("MSDC MMCA_VSN: %d. Skip EXT_CSD\n", + card->csd.mmca_vsn); + return 0; + } + mt_dump_msdc_clr_fifo(host->mtk_host->id); + simp_msdc_set_blknum(phost, 1); + msdc_set_timeout(phost, 100000000, 0); + + err = simp_msdc_cmd(phost, MMC_SEND_EXT_CSD, CMD8_RAW_EMMC, 0, RESP_R1, + &resp); + if (err) + goto out; + + err = simp_msdc_pio_read(phost, (unsigned int *)(simp_ext_csd), 512); + if (err) { + pr_err("pio read ext csd error(0x%d)\n", err); + goto out; + } + + out: + return err; +} + +/* FIXME : consider to remove it since card->ext_csd.sectors + is never referenced */ +static void simp_mmc_decode_ext_csd(struct simp_mmc_card *card) +{ + card->ext_csd.sectors = + simp_ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | + simp_ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | + simp_ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | + simp_ext_csd[EXT_CSD_SEC_CNT + 3] << 24; +} + +static int simp_emmc_switch_bus(struct simp_mmc_host *host, + struct simp_mmc_card *card) +{ + struct simp_msdc_host *phost = host->mtk_host; + unsigned int resp; + return simp_msdc_cmd(phost, MMC_SWITCH, ACMD6_RAW_EMMC, + ACMD6_ARG_EMMC, RESP_R1B, &resp); +} + +static int simp_mmc_init_card(struct simp_mmc_host *mmc, unsigned int ocr, + struct simp_mmc_card *oldcard) +{ + int err = 0; + unsigned int rocr; + unsigned int cid[4]; + void __iomem *base; + struct simp_mmc_card *card = mmc->card; + + struct simp_msdc_host *phost = mmc->mtk_host; + unsigned int resp[4] = {0}; + + base = mmc->mtk_host->base; + + /* Set correct bus mode for MMC before attempting init */ + /* NULL func now */ + simp_mmc_set_bus_mode(mmc, MMC_BUSMODE_OPENDRAIN); + + /* + * Since we're changing the OCR value, we seem to + * need to tell some cards to go back to the idle + * state. We wait 1ms to give cards time to + * respond. + * mmc_go_idle is needed for eMMC that are asleep + */ + simp_mmc_go_idle(mmc); + + /* The extra bit indicates that we support high capacity */ + err = simp_mmc_send_op_cond(mmc, ocr | (1 << 30), &rocr); + if (err) + goto err; + + err = simp_mmc_all_send_cid(mmc, cid); + + if (err) + goto err; + + card->type = MSDC_EMMC; + card->rca = 1; + mmc->mtk_host->card->rca = 1; + memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); + + /* + * For native busses: set card RCA and quit open drain mode. + */ + #if 0 + err = simp_mmc_set_relative_addr(card); + #else + err = simp_msdc_cmd(phost, MMC_SET_RELATIVE_ADDR, CMD3_RAW, + card->rca << 16, RESP_R1, resp); + #endif + if (err) + goto err; + + simp_mmc_set_bus_mode(mmc, MMC_BUSMODE_PUSHPULL); + + /* + * Fetch CSD from card. + */ + #if 0 + err = simp_mmc_send_csd(card, card->raw_csd); + #else + err = simp_msdc_cmd(mmc->mtk_host, MMC_SEND_CSD, CMD9_RAW, + card->rca << 16, RESP_R2, card->raw_csd); + #endif + if (err) + goto err; + + err = simp_mmc_decode_csd(card); + if (err) + goto err; + + err = simp_mmc_select_card(mmc, card); + if (err) + goto err; + err = simp_mmc_read_ext_csd(mmc, card); + if (err) + goto err; + simp_mmc_decode_ext_csd(card); + + err = simp_emmc_switch_bus(mmc, card); + MSDC_SET_FIELD(SDC_CFG, SDC_CFG_BUSWIDTH, 1); /* 1: 4 bits mode */ + simp_msdc_config_clock(mmc->mtk_host, NORMAL_SCLK); + return SIMP_SUCCESS; + + err: + return SIMP_FAILED; +} + +#define ACMD41_RETRY (20) +static int simp_mmc_sd_init(struct simp_mmc_host *host) +{ + struct simp_msdc_host *phost = host->mtk_host; + u32 ACMD41_ARG = 0; + u8 retry; + void __iomem *base; + unsigned int resp[4] = {0}; + int bRet = 0; + + base = phost->base; + simp_mmc_go_idle(host); + + if (simp_msdc_cmd(phost, SD_SEND_IF_COND, CMD8_RAW, CMD8_ARG, RESP_R7, + resp)) { + /* SD v1.0 will not repsonse to CMD8, then clr HCS bit */ + /*pr_debug("SD v1.0, clr HCS bit\n");*/ + ACMD41_ARG = ACMD41_ARG_10; + } else if (resp[0] == CMD8_ARG) { + /*pr_debug("SD v2.0, set HCS bit\n");*/ + ACMD41_ARG = ACMD41_ARG_20; + } + + retry = ACMD41_RETRY; + while (retry--) { + if (simp_msdc_cmd(phost, MMC_APP_CMD, CMD55_RAW, + CMD55_ARG << 16, RESP_R1, resp)) + goto EXIT; + if (simp_msdc_cmd(phost, SD_APP_OP_COND, ACMD41_RAW, ACMD41_ARG, + RESP_R3, resp)) + goto EXIT; + if (resp[0] & R3_OCR_POWER_UP_BIT) { + phost->card->card_cap = + ((resp[0] & R3_OCR_CARD_CAPACITY_BIT) + ? high_capacity : standard_capacity); + if (phost->card->card_cap == standard_capacity) + pr_debug("Standard_capacity card!!\r\n"); + break; + } + msdc_mdelay(1000 / ACMD41_RETRY); + } + + if (simp_mmc_all_send_cid(host, resp)) + goto EXIT; + + if (simp_msdc_cmd(phost, MMC_SET_RELATIVE_ADDR, CMD3_RAW, CMD3_ARG, + RESP_R6, resp)) + goto EXIT; + + /* save the rca */ + phost->card->rca = (resp[0] & 0xffff0000) >> 16; /* RCA[31:16] */ + + if (simp_msdc_cmd(phost, MMC_SEND_CSD, CMD9_RAW, CMD9_ARG << 16, + RESP_R2, resp)) + goto EXIT; + + if (simp_msdc_cmd(phost, MMC_SEND_STATUS, CMD13_RAW, CMD13_ARG << 16, + RESP_R1, resp)) + goto EXIT; + + if (simp_msdc_cmd(phost, MMC_SELECT_CARD, CMD7_RAW, CMD7_ARG << 16, + RESP_R1, resp)) + goto EXIT; + + /* dump register for debug */ + /*simp_msdc_dump_info(phost->id)*/ + + msdc_mdelay(10); + + if (simp_msdc_cmd(phost, MMC_APP_CMD, CMD55_RAW, CMD55_ARG << 16, + RESP_R1, resp)) + goto EXIT; + + if (simp_msdc_cmd(phost, SD_SWITCH, ACMD6_RAW, ACMD6_ARG, RESP_R1, + resp)) + goto EXIT; + + /* set host bus width to 4 */ + MSDC_SET_FIELD(SDC_CFG, SDC_CFG_BUSWIDTH, 1); /* 1: 4 bits mode */ + simp_msdc_config_clock(phost, NORMAL_SCLK); + + MTK_DUMP_PR_DBG("sd card inited\n"); + + bRet = 1; + + EXIT: + return bRet; +} + +#ifdef MTK_MSDC_USE_CACHE +static int simp_mmc_disable_cache(struct simp_mmc_host *host) +{ + int err = 0; + unsigned int resp; + unsigned int status = 0; + int polling = MAX_POLLING_STATUS; + struct simp_msdc_host *phost = host->mtk_host; + + do { + err = simp_mmc_get_status(host, &status); + if (err) + return -1; + + if (R1_CURRENT_STATE(status) == 5 + || R1_CURRENT_STATE(status) == 6) { + simp_mmc_send_stop(host); + } + /* msdc_mdelay(1); */ + } while (R1_CURRENT_STATE(status) == 7 && polling--); + + if (R1_CURRENT_STATE(status) == 7) + return -2; + + err = simp_msdc_cmd(phost, MMC_SWITCH, ACMD6_RAW_EMMC, + ACMD6_ARG_DISABLE_CACHE, RESP_R1B, &resp); + + if (!err) { + polling = MAX_POLLING_STATUS; + do { + err = simp_mmc_get_status(host, &status); + if (err) + return -3; + /*msdc_mdelay(1); */ + } while (R1_CURRENT_STATE(status) == 7 && polling--); + + if (status & 0xFDFFA000) + pr_err("msdc unexpected status 0x%x after switch", + status); + if (status & R1_SWITCH_ERROR) + return -4; + } + + return err; +} +#endif + +static unsigned int simple_mmc_attach_sd(struct simp_mmc_host *host) +{ + /* int err = SIMP_FAILED; */ + + /* power up host */ + simp_mmc_power_up(host, 0); + msdc_mdelay(20); + simp_mmc_power_up(host, 1); + + /* enable clock */ + if (SIMP_FAILED == simp_mmc_enable_clk(host)) + return SIMP_FAILED; + + /* + * Some eMMCs (with VCCQ always on) may not be reset after power up, so + * do a hardware reset if possible. + */ + simp_mmc_hw_reset_for_init(host); + + /* init msdc host */ + simp_msdc_init(host); + + simp_mmc_sd_init(host); + + return SIMP_SUCCESS; +} + +/* make clk & power always on */ +static unsigned int simple_mmc_attach_mmc(struct simp_mmc_host *host) +{ + int err = 0; + unsigned int ocr; + +#ifdef MTK_MSDC_USE_CACHE + struct msdc_host *host2 = mtk_msdc_host[host->index]; + + g_power_reset = 0; + /* turn off cache will trigger flushing of cache data to + non-volatile storage */ + if (!host2 || !host2->mmc || !host2->mmc->card) { + pr_err("[%s]: host/mmc/card does not exist\n", __func__); + } else if (host2->mmc->card->ext_csd.cache_ctrl & 0x1) { + /* enable clock */ + if (SIMP_FAILED == simp_mmc_enable_clk(host)) + return SIMP_FAILED; + + /* init msdc host */ + simp_msdc_init(host); + + err = simp_mmc_disable_cache(host); + if (err) { + pr_err("[%s]: failed to disable cache ops, err = %d\n", + __func__, err); + simp_msdc_dump_info(host->mtk_host->id); + err = 0; + } else { + MTK_DUMP_PR_DBG("[%s]: successfully disabled cache\n", + __func__); + } + } else { + MTK_DUMP_PR_DBG("[%s]: cache is not enabled, no need to disable\n", + __func__); + } +#endif + + /* power up host */ + simp_mmc_power_up(host, 1); + msdc_mdelay(10); +#ifdef MTK_MSDC_USE_CACHE + g_power_reset = 1; +#endif + + /* + * Some eMMCs (with VCCQ always on) may not be reset after power up, so + * do a hardware reset if possible. + */ + simp_mmc_hw_reset_for_init(host); + + /* enable clock */ + if (SIMP_FAILED == simp_mmc_enable_clk(host)) + return SIMP_FAILED; + + /* init msdc host */ + simp_msdc_init(host); + + /*=================== begin to init emmc card =======================*/ + + /* Set correct bus mode for MMC before attempting attach */ + simp_mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN); + + simp_mmc_go_idle(host); + + err = simp_mmc_send_op_cond(host, 0, &ocr); + + /*=========ok*/ + + /* + * Sanity check the voltages that the card claims to + * support. + */ + if (ocr & 0x7F) { + MTK_DUMP_PR_DBG("msdc0: card claims to support voltages below defined range --> ignored.\n"); + ocr &= ~0x7F; + } + + host->ocr = simp_mmc_select_voltage(host, ocr); + + /* + * Can we support the voltage of the card? + */ + if (!host->ocr) { + pr_err("msdc0: card voltage not support\n"); + err = -EINVAL; + goto err; + } + + /* + * Detect and init the card. + */ + err = simp_mmc_init_card(host, host->ocr, NULL); + if (err == SIMP_FAILED) { + pr_err("init eMMC failed\n"); + goto err; + } + + MTK_DUMP_PR_DBG("init eMMC success\n"); + + /*=================== end mmc card init =============================*/ + return SIMP_SUCCESS; + err: + return SIMP_FAILED; +} + +static unsigned int simp_init_try(int card_type, int *module_init_flag, + int *dev_init_flag) +{ + int i = 0; + int ret = 0; + int boot; + static struct simp_mmc_host *cur_mmc_host; + char *type_str; + + if (card_type == MSDC_EMMC) { + cur_mmc_host = &g_mmc_host[BOOT_STORAGE_ID]; + boot = 1; + type_str = "eMMC"; + } else if (card_type == MSDC_SD) { + cur_mmc_host = &g_mmc_host[EXTEND_STORAGE_ID]; + boot = 0; + type_str = "SD"; + } else + return 1; + + pr_err("Start init %s\n", type_str); + if (0 == *module_init_flag) { + if (SIMP_FAILED == simp_mmc_init(card_type, boot)) { + ret = 1; + goto out; + } + } + + for (i = 0; i < 3; i++) { + if (card_type == MSDC_EMMC) + ret = simple_mmc_attach_mmc(cur_mmc_host); + else + ret = simple_mmc_attach_sd(cur_mmc_host); + if (ret == SIMP_SUCCESS) + break; + } + if (0 == ret) + *dev_init_flag = 1; + + pr_err("%s to init %s\n", (ret ? "Fail" : "Succeed"), type_str); +out: + return ret; +} + +unsigned int reset_boot_up_device(int type) +{ + int ret = 0; + + if (type == MMC_TYPE_MMC) + ret = simp_init_try(MSDC_EMMC, &module_init_emmc, &emmc_init); + else if (type == MMC_TYPE_SD) + ret = simp_init_try(MSDC_SD, &module_init_sd, &sd_init); + else { + pr_err("invalid card type: %d\n", type); + ret = 1; + } + + return ret; +} +EXPORT_SYMBOL(reset_boot_up_device); + +static int simp_msdc_pio_write(struct simp_msdc_host *host, + unsigned int *ptr, unsigned int size) +{ + void __iomem *base = host->base; + unsigned int left = size; + unsigned int status = 0; + unsigned char *u8ptr; + int l_count = 0; + int err = 0; + int print_count = 2; + + while (1) { + status = MSDC_READ32(MSDC_INT); + MSDC_WRITE32(MSDC_INT, status); + if (status & MSDC_INT_DATCRCERR) { + pr_err("[MSDC%d] DAT CRC error (0x%x), Left DAT: %d bytes\n", + host->id, status, left); + err = -5; + simp_msdc_dump_info(host->id); + break; + } else if (status & MSDC_INT_DATTMO) { + pr_err("[MSDC%d] DAT TMO error (0x%x), Left DAT: %d bytes\n", + host->id, status, left); + err = -110; + simp_msdc_dump_info(host->id); + break; + } else if (status & MSDC_INT_XFER_COMPL) { + break; + } + if (left == 0) + continue; + if ((left >= MSDC_FIFO_SZ) && (msdc_txfifocnt() == 0)) { + int count = MSDC_FIFO_SZ >> 2; + do { + msdc_fifo_write32(*ptr); + ptr++; + } while (--count); + left -= MSDC_FIFO_SZ; + } else if (left < MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { + while (left > 3) { + msdc_fifo_write32(*ptr); ptr++; + left -= 4; + } + + u8ptr = (u8 *)ptr; + while (left) { + msdc_fifo_write8(*u8ptr); + u8ptr++; + left--; + } + } else { + status = MSDC_READ32(MSDC_INT); + + if (status & MSDC_INT_DATCRCERR) { + pr_err("[MSDC%d] DAT CRC error (0x%x), Left DAT: %d bytes\n", + host->id, status, left); + err = -5; + } + if (status & MSDC_INT_DATTMO) { + pr_err("[MSDC%d] DAT TMO error (0x%x), Left DAT: %d bytes\n", + host->id, status, left); + err = -110; + } + + if ((status & MSDC_INT_DATCRCERR) + || (status & MSDC_INT_DATTMO)) { + simp_msdc_dump_info(host->id); + + MSDC_WRITE32(MSDC_INT, status); + msdc_reset_hw(host->id); + return err; + } + } + + l_count++; + if (l_count > 50000) { + l_count = 0; + if (print_count > 0) { + pr_err("size= %d, left= %d.\r\n", size, left); + simp_msdc_dump_info(host->id); + print_count--; + } + } + } + + return err; +} + +static int simp_msdc_pio_read(struct simp_msdc_host *host, + unsigned int *ptr, unsigned int size) +{ + void __iomem *base = host->base; + unsigned int left = size; + unsigned int status = 0; + unsigned char *u8ptr; + int l_count = 0; + int err = 0; + int print_count = 2; + int done = 0; + + while (1) { + status = MSDC_READ32(MSDC_INT); + MSDC_WRITE32(MSDC_INT, status); + if (status & MSDC_INT_DATCRCERR) { + pr_err("[MSDC%d] DAT CRC error (0x%x), Left DAT: %d bytes\n", + host->id, status, left); + err = -5; + simp_msdc_dump_info(host->id); + break; + } else if (status & MSDC_INT_DATTMO) { + pr_err("[MSDC%d] DAT TMO error (0x%x), Left DAT: %d bytes\n", + host->id, status, left); + err = -110; + simp_msdc_dump_info(host->id); + break; + } else if (status & MSDC_INT_XFER_COMPL) { + done = 1; + } + if (done && (left == 0)) + break; + + while (left) { + /* pr_err("left(%d)/FIFO(%d)\n", + left,msdc_rxfifocnt()); */ + if ((left >= MSDC_FIFO_THD) && (msdc_rxfifocnt() + >= MSDC_FIFO_THD)) { + int count = MSDC_FIFO_THD >> 2; + do { + *ptr++ = msdc_fifo_read32(); + } while (--count); + left -= MSDC_FIFO_THD; + } else if ((left < MSDC_FIFO_THD) && msdc_rxfifocnt() + >= left) { + while (left > 3) { + *ptr++ = msdc_fifo_read32(); + left -= 4; + } + + u8ptr = (u8 *)ptr; + while (left) { + *u8ptr++ = msdc_fifo_read8(); + left--; + } + } else { + status = MSDC_READ32(MSDC_INT); + + if (status & MSDC_INT_DATCRCERR) { + pr_err("[MSDC%d] DAT CRC error (0x%x), Left DAT: %d bytes\n", + host->id, status, left); + err = -5; + } + if (status & MSDC_INT_DATTMO) { + pr_err("[MSDC%d] DAT TMO error (0x%x), Left DAT: %d bytes\n", + host->id, status, left); + err = -110; + } + + if ((status & MSDC_INT_DATCRCERR) + || (status & MSDC_INT_DATTMO)) { + simp_msdc_dump_info(host->id); + + MSDC_WRITE32(MSDC_INT, status); + msdc_reset_hw(host->id); + return err; + } + } + + /* timeout monitor*/ + l_count++; + if (l_count > 50000) { + l_count = 0; + if (print_count > 0) { + pr_err("size= %d, left= %d, done=%d.\n", + size, left, done); + simp_msdc_dump_info(host->id); + print_count--; + } + } + } + } + + return err; +} + +static void simp_msdc_set_blknum(struct simp_msdc_host *host, + unsigned int blknum) +{ + void __iomem *base = host->base; + MSDC_WRITE32(SDC_BLK_NUM, blknum); +} + +static int simp_mmc_write(struct simp_mmc_host *host, unsigned int addr, + void *buf, unsigned int nblk) +{ + unsigned int resp = 0; + unsigned int err = 0; + /*unsigned int intsts = 0;*/ + struct simp_msdc_host *phost = host->mtk_host; + void __iomem *base = phost->base; + + simp_msdc_set_blknum(phost, nblk); + + /* send command */ + if (nblk == 1) + err = simp_msdc_cmd(phost, MMC_WRITE_BLOCK, CMD24_RAW, addr, + RESP_R1, &resp); + else + err = simp_msdc_cmd(phost, MMC_WRITE_MULTIPLE_BLOCK, CMD25_RAW, + addr, RESP_R1, &resp); + + /* write the data to FIFO */ + err = simp_msdc_pio_write(phost, (unsigned int *)buf, 512*nblk); + if (err) + pr_err("write data: error(%d)\n", err); + + /* make sure contents in fifo flushed to device */ + BUG_ON(msdc_txfifocnt()); + + /* check and clear interrupt */ + + if (nblk > 1) + simp_mmc_send_stop(host); + + return err; +} + +static int simp_mmc_read(struct simp_mmc_host *host, unsigned int addr, + void *buf, unsigned int nblk) +{ + unsigned int resp = 0; + unsigned int err = 0; + struct simp_msdc_host *phost = host->mtk_host; + + simp_msdc_set_blknum(phost, nblk); + + /* send command */ + if (nblk == 1) + err = simp_msdc_cmd(phost, MMC_READ_SINGLE_BLOCK, CMD17_RAW, + addr, RESP_R1, &resp); + else + err = simp_msdc_cmd(phost, MMC_READ_MULTIPLE_BLOCK, CMD18_RAW, + addr, RESP_R1, &resp); + + /* read the data out*/ + err = simp_msdc_pio_read(phost, (unsigned int *)buf, 512*nblk); + if (err) + pr_err("read data: error(%d)\n", err); + + if (nblk > 1) + simp_mmc_send_stop(host); + return err; +} + + +/* card_type tell to use which host, will support PANIC dump info to emmc card + * and KDUMP info to sd card */ +int msdc_init_panic(int dev) +{ + return 1; +} + +static int simp_mmc_init(int card_type, bool boot) +{ + struct simp_msdc_host *cur_msdc_host; + struct simp_mmc_host *cur_mmc_host; + int id; + u32 *hclks; + + if (boot) { + cur_msdc_host = pmsdc_boot_host; + cur_mmc_host = pmmc_boot_host; + id = BOOT_STORAGE_ID; + } else { + cur_msdc_host = pmsdc_extend_host; + cur_mmc_host = pmmc_extend_host; + id = EXTEND_STORAGE_ID; + } + + /* init some struct */ + cur_mmc_host->mtk_host = cur_msdc_host; + cur_mmc_host->card = &g_mmc_card[id]; + cur_mmc_host->card->host = cur_mmc_host; + + memset(cur_msdc_host, 0, sizeof(struct simp_msdc_host)); + cur_msdc_host->id = id; + if (NULL == mtk_msdc_host[id]) + goto out; + + cur_msdc_host->base = (mtk_msdc_host[id])->base; + + hclks = msdc_get_hclks(id); + if (id == 0) + cur_msdc_host->clksrc = MSDC0_CLKSRC_DEFAULT; + else + cur_msdc_host->clksrc = MSDC1_CLKSRC_DEFAULT; + cur_msdc_host->clk = hclks[cur_msdc_host->clksrc]; + cur_msdc_host->card = &g_msdc_card[id]; + + /* not use now, may be delete */ + memset(&g_msdc_card[id], 0, sizeof(struct simp_msdc_card)); + g_msdc_card[id].type = card_type; + + if (boot) { + g_msdc_card[id].file_system = _RAW_; + + /* init host & card */ + module_init_emmc = 1; + + } else { + g_msdc_card[id].file_system = FAT32; + + pmsdc_extend_host->card->card_cap = 1; + + module_init_sd = 0; + } + return SIMP_SUCCESS; +out: + return SIMP_FAILED; +} + + +/*--------------------------------------------------------------------------*/ +/* porting for panic dump interface */ +/*--------------------------------------------------------------------------*/ +static sector_t lp_start_sect = (sector_t)(-1); +static sector_t lp_nr_sects = (sector_t)(-1); + +#ifdef CONFIG_MTK_EMMC_SUPPORT +static int simp_emmc_dump_write(unsigned char *buf, unsigned int len, + unsigned int offset, unsigned int dev) +{ + /* maybe delete in furture */ + unsigned int status = 0; + int polling = MAX_POLLING_STATUS; + unsigned long long l_start_offset; + unsigned int l_addr; + unsigned char *l_buf; + unsigned int ret = 1; /* != 0 means error occur */ + + if (0 != len % 512) { + /* emmc always in slot0 */ + pr_err("debug: parameter error!\n"); + return ret; + } + + /* find the offset in emmc */ + if (lp_start_sect == 0) { + pr_err("Illegal expdb start address (0x0)\n"); + return ret; + } + + if (lp_start_sect == (sector_t)(-1) || lp_nr_sects == (sector_t)(-1)) { + pr_err("partition not found error!\n"); + return ret; + } + + if ((lp_nr_sects < (len >> 9)) || + (lp_nr_sects < (offset >> 9)) || + (lp_nr_sects < ((len + offset) >> 9))) { + pr_err("write operation oversize!\n"); + return ret; + } + + MTK_DUMP_PR_DBG("write start sector = %llu, part size = %llu\n", + (u64)lp_start_sect, (u64)lp_nr_sects); + + l_start_offset = (u64)offset + (u64)(lp_start_sect << 9); + + MTK_DUMP_PR_DBG("write start address = %llu\n", l_start_offset); + + if (emmc_init == 0) { + if (simp_init_try(MSDC_EMMC, &module_init_emmc, &emmc_init) + != 0) + return ret; + } + + l_addr = l_start_offset >> 9; /*blk address*/ + l_buf = buf; + + MTK_DUMP_PR_DBG("l_start_offset =0x%x\n", l_addr); + + ret = simp_mmc_write(pmmc_boot_host, l_addr, l_buf, len / 512); + + do { + simp_mmc_get_status(pmmc_boot_host, &status); + } while (R1_CURRENT_STATE(status) == 7 && polling--); + if (ret == 0) + ret = SIMP_SUCCESS; + return ret; + +} +#endif /* end of CONFIG_MTK_EMMC_SUPPORT */ + +static int simp_sd_dump_write(unsigned char *buf, unsigned int len, + unsigned int offset, unsigned int dev) +{ + /* unsigned int i; */ + unsigned int l_addr; + unsigned char *l_buf; + int polling = MAX_POLLING_STATUS; + unsigned int status = 0; + /* unsigned int l_start_offset; */ + unsigned int ret = SIMP_FAILED; + int err = 0; + + if (0 != len % 512) { + /* emmc always in slot0 */ + pr_err("debug: parameter error!\n"); + return ret; + } +#if 0 + pr_debug("write data:"); + for (i = 0; i < 32; i++) { + pr_debug("0x%x", buf[i]); + if (0 == (i + 1) % 32) + pr_debug("\n"); + } +#endif + /* l_start_offset = offset; */ + l_buf = buf; + if (pmsdc_extend_host->card->card_cap == standard_capacity) + l_addr = offset << 9; + else + l_addr = offset; + + MTK_DUMP_PR_ERR("l_start_offset = 0x%x len = %d buf<0x%p>\n", l_addr, + len, l_buf); + + err = simp_mmc_write(pmmc_extend_host, l_addr, l_buf, len / 512); + + do { + simp_mmc_get_status(pmmc_extend_host, &status); + } while (R1_CURRENT_STATE(status) == 7 && polling--); + if (err == 0) + ret = SIMP_SUCCESS; + return ret; +} + +static int simp_sd_dump_read(unsigned char *buf, unsigned int len, + unsigned int offset) +{ + /* unsigned int i; */ + unsigned int l_addr; + unsigned char *l_buf; + /* unsigned int l_start_offset; */ + unsigned int ret = SIMP_FAILED; + int err = 0; + + if (0 != len % 512) { + pr_err("debug: parameter error!\n"); + return ret; + } + + if (sd_init == 0) { + if (simp_init_try(MSDC_SD, &module_init_sd, &sd_init) != 0) + return ret; + } + /* l_start_offset = offset; */ + l_buf = buf; + + MTK_DUMP_PR_DBG("l_start_offset = 0x%x len = %d\n", offset, len); + + if (pmsdc_extend_host->card->card_cap == standard_capacity) + l_addr = offset << 9; + else + l_addr = offset; + + err = simp_mmc_read(pmmc_extend_host, l_addr, l_buf, len / 512); + +#if 0 + pr_debug("read data:"); + for (i = 0; i < 32; i++) { + pr_debug("0x%x", buf[i]); + if (0 == (i + 1) % 32) + pr_debug("\n"); + } +#endif + if (err == 0) + ret = SIMP_SUCCESS; + return ret; +} + +#ifdef CONFIG_MTK_EMMC_SUPPORT +#define SD_FALSE (-1) +#define SD_TRUE (0) +#define DEBUG_MMC_IOCTL (0) +static int simp_emmc_dump_read(unsigned char *buf, unsigned int len, + unsigned int offset, unsigned int slot) +{ + /* maybe delete in furture */ + struct msdc_ioctl msdc_ctl; + unsigned int i; + unsigned long long l_start_offset = 0; + unsigned int ret = SD_FALSE; + + if ((0 != slot) || (0 != offset % 512) || (0 != len % 512)) { + /* emmc always in slot0 */ + pr_err("debug: slot is not use for emmc!\n"); + return ret; + } + + if (0 != len % 512) { + /* emmc always in slot0 */ + pr_err("debug: parameter error!\n"); + return ret; + } + /* find the offset in emmc */ + if (lp_start_sect == (sector_t)(-1) || lp_nr_sects == (sector_t)(-1)) { + pr_err("not find in scatter file error!\n"); + return ret; + } + if (lp_nr_sects < ((len + offset) >> 9)) { + pr_err("read operation oversize!\n"); + return ret; + } + + MTK_DUMP_PR_DBG("read start sector = %llu, part size = %llu\n", + (u64)lp_start_sect, (u64)lp_nr_sects); + + l_start_offset = (u64)offset + (u64)(lp_start_sect << 9); + + MTK_DUMP_PR_DBG("read start address = %llu\n", l_start_offset); + + /* FIX ME: msdc_ctl.total_size as MAX_DMA_CNT so that CMD18 is used */ + msdc_ctl.partition = 0; + msdc_ctl.iswrite = 0; + msdc_ctl.host_num = slot; + msdc_ctl.opcode = MSDC_CARD_DUNM_FUNC; + msdc_ctl.total_size = MAX_DMA_CNT; + msdc_ctl.trans_type = 0; + msdc_ctl.address = l_start_offset >> 9; + msdc_ctl.buffer = (u32 *) buf; + for (i = 0; i < (len/MAX_DMA_CNT); i++) { +#if DEBUG_MMC_IOCTL + pr_debug("l_start_offset = 0x%x\n", msdc_ctl.address); +#endif + msdc_ctl.result = simple_sd_ioctl_rw(&msdc_ctl); + msdc_ctl.address += MAX_DMA_CNT >> 9; + msdc_ctl.buffer = (u32 *) (buf + MAX_DMA_CNT * (i+1)); + } + + msdc_ctl.total_size = len % MAX_DMA_CNT; + if (0 != msdc_ctl.total_size) { +#if DEBUG_MMC_IOCTL + pr_debug("l_start_offset = 0x%x\n", msdc_ctl.address); +#endif + msdc_ctl.result = simple_sd_ioctl_rw(&msdc_ctl); + } + +#if DEBUG_MMC_IOCTL + pr_debug("read data:"); + for (i = 0; i < 32; i++) { + pr_debug("0x%x", buf[i]); + if (0 == (i+1)%32) + pr_debug("\n"); + } +#endif + return SD_TRUE; +} +#endif + +int card_dump_func_write(unsigned char *buf, unsigned int len, + unsigned long long offset, int dev) +{ + int ret = SIMP_FAILED; + unsigned int sec_offset = 0; + + MTK_DUMP_PR_DBG("card_dump_func_write len<%d> addr<%lld> type<%d>\n", + len, offset, dev); + + if (offset % 512) { + pr_err("Address isn't 512 alignment!\n"); + return SIMP_FAILED; + } + sec_offset = offset / 512; + switch (dev) { + case DUMP_INTO_BOOT_CARD_IPANIC: +#ifdef CONFIG_MTK_EMMC_SUPPORT + ret = simp_emmc_dump_write(buf, len, (unsigned int)offset, dev); +#endif + break; + case DUMP_INTO_BOOT_CARD_KDUMP: + break; + case DUMP_INTO_EXTERN_CARD: + ret = simp_sd_dump_write(buf, len, sec_offset, dev); + break; + default: + pr_err("unknown card type, error!\n"); + break; + } + + return ret; +} +EXPORT_SYMBOL(card_dump_func_write); + +int card_dump_func_read(unsigned char *buf, unsigned int len, + unsigned long long offset, int dev) +{ + unsigned int ret = SIMP_FAILED; + unsigned int sec_offset = 0; + + MTK_DUMP_PR_DBG("card_dump_func_read len<%d> addr<%lld> type<%d>\n", + len, offset, dev); + + if (offset % 512) { + pr_err("Address isn't 512 alignment!\n"); + return SIMP_FAILED; + } + sec_offset = offset / 512; + switch (dev) { + case DUMP_INTO_BOOT_CARD_IPANIC: +#ifdef CONFIG_MTK_EMMC_SUPPORT + ret = simp_emmc_dump_read(buf, len, (unsigned int)offset, dev); +#endif + break; + case DUMP_INTO_BOOT_CARD_KDUMP: + break; + case DUMP_INTO_EXTERN_CARD: + ret = simp_sd_dump_read(buf, len, sec_offset); + break; + default: + pr_err("unknown card type, error!\n"); + break; + } + return ret; + +} +EXPORT_SYMBOL(card_dump_func_read); + +int has_mt_dump_support(void) +{ + return 1; +} +EXPORT_SYMBOL(has_mt_dump_support); + + +/*--------------------------------------------------------------------------*/ +/* porting for kdump interface */ +/*--------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------*/ +/* module init/exit */ +/*--------------------------------------------------------------------------*/ +static int __init emmc_dump_init(void) +{ +#ifdef CONFIG_MTK_EMMC_SUPPORT + simp_mmc_init(MSDC_EMMC, 1); +#endif + simp_mmc_init(MSDC_SD, 0); + + MTK_DUMP_PR_DBG("EMMC/SD dump init\n"); + + return 0; +} + +static void __exit emmc_dump_exit(void) +{ +} +module_init(emmc_dump_init); +module_exit(emmc_dump_exit); + +#ifdef CONFIG_MTK_EMMC_SUPPORT +/* @partition_ready_flag, + * = 0: partition init not ready + * = 1: partition init is done and succeed + * = -1: there is no expdb partition + */ +static int partition_ready_flag; +int get_emmc_dump_status(void) +{ + return partition_ready_flag; +} + +static void get_emmc_dump_info(struct work_struct *work) +{ + struct hd_struct *lp_hd_struct = NULL; + lp_hd_struct = get_part("expdb"); + if (likely(lp_hd_struct)) { + lp_start_sect = lp_hd_struct->start_sect; + lp_nr_sects = lp_hd_struct->nr_sects; + put_part(lp_hd_struct); + partition_ready_flag = 1; + pr_err("get expdb info\n"); + } else { + lp_start_sect = (sector_t)(-1); + lp_nr_sects = (sector_t)(-1); + partition_ready_flag = -1; + pr_err("There is no expdb info\n"); + } + + partition_ready_flag = 1; +} + +static struct delayed_work get_dump_info; +static int __init init_get_dump_work(void) +{ + INIT_DELAYED_WORK(&get_dump_info, get_emmc_dump_info); + if (schedule_delayed_work(&get_dump_info, 100)) + return 1; + + return 0; +} +late_initcall_sync(init_get_dump_work); +#endif diff --git a/drivers/mmc/host/mediatek/mt6755/mt_sd.h b/drivers/mmc/host/mediatek/mt6755/mt_sd.h new file mode 100644 index 0000000000000000000000000000000000000000..bc5f2797b80cb1d9df9a976f1dcc2179a9a15073 --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/mt_sd.h @@ -0,0 +1,826 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef MT_SD_H +#define MT_SD_H + +#ifdef CONFIG_FPGA_EARLY_PORTING +#define FPGA_PLATFORM +#else +/*#define MTK_MSDC_BRINGUP_DEBUG*/ +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define MSDC_WQ_ERROR_TUNE + +#define MSDC_AUTOK_ON_ERROR +#ifdef MSDC_AUTOK_ON_ERROR +/*#define DATA_TUNE_READ_DATA_ALLOW_FALLING_EDGE*/ +#endif + +#define MSDC_DMA_ADDR_DEBUG +/*#define MSDC_HQA*/ + +#define MTK_MSDC_USE_CMD23 +#if defined(CONFIG_MTK_EMMC_CACHE) && defined(MTK_MSDC_USE_CMD23) +#define MTK_MSDC_USE_CACHE +#endif + +#ifdef MTK_MSDC_USE_CMD23 +#define MSDC_USE_AUTO_CMD23 (1) +#endif + +#ifdef MTK_MSDC_USE_CACHE +#ifndef MMC_ENABLED_EMPTY_QUEUE_FLUSH +/* #define MTK_MSDC_FLUSH_BY_CLK_GATE */ +#endif +#endif + +#define HOST_MAX_NUM (4) +#define MAX_REQ_SZ (512 * 1024) + +#ifdef FPGA_PLATFORM +#define HOST_MAX_MCLK (200000000) +#else +#define HOST_MAX_MCLK (200000000) +#endif +#define HOST_MIN_MCLK (260000) + +/* ================================= */ + +#define MAX_GPD_NUM (1 + 1) /* one null gpd */ +#define MAX_BD_NUM (1024) +#define MAX_BD_PER_GPD (MAX_BD_NUM) +#define CLK_SRC_MAX_NUM (1) + +#define SDIO_ERROR_BYPASS + +/*#define MTK_MSDC_DUMP_FIFO*/ + +/*--------------------------------------------------------------------------*/ +/* Common Macro */ +/*--------------------------------------------------------------------------*/ +#define REG_ADDR(x) ((volatile u32 *)(base + OFFSET_##x)) + +/*--------------------------------------------------------------------------*/ +/* Common Definition */ +/*--------------------------------------------------------------------------*/ +#define MSDC_FIFO_SZ (128) +#define MSDC_FIFO_THD (64) /* (128) */ +#define MSDC_NUM (4) + +#define MSDC_MS (0) /* No memory stick mode, + 0 use to gate clock */ +#define MSDC_SDMMC (1) + +#define MSDC_MODE_UNKNOWN (0) +#define MSDC_MODE_PIO (1) +#define MSDC_MODE_DMA_BASIC (2) +#define MSDC_MODE_DMA_DESC (3) +#define MSDC_MODE_DMA_ENHANCED (4) + +#define MSDC_BUS_1BITS (0) +#define MSDC_BUS_4BITS (1) +#define MSDC_BUS_8BITS (2) + +#define MSDC_BRUST_8B (3) +#define MSDC_BRUST_16B (4) +#define MSDC_BRUST_32B (5) +#define MSDC_BRUST_64B (6) + +#define MSDC_AUTOCMD12 (0x0001) +#define MSDC_AUTOCMD23 (0x0002) +#define MSDC_AUTOCMD19 (0x0003) +#define MSDC_AUTOCMD53 (0x0004) + +#define MSDC_EMMC_BOOTMODE0 (0) /* Pull low CMD mode */ +#define MSDC_EMMC_BOOTMODE1 (1) /* Reset CMD mode */ + +enum { + RESP_NONE = 0, + RESP_R1, + RESP_R2, + RESP_R3, + RESP_R4, + RESP_R5, + RESP_R6, + RESP_R7, + RESP_R1B +}; + +#include "msdc_reg.h" + +/* MSDC_CFG[START_BIT] value */ +#define START_AT_RISING (0x0) +#define START_AT_FALLING (0x1) +#define START_AT_RISING_AND_FALLING (0x2) +#define START_AT_RISING_OR_FALLING (0x3) + +#define TYPE_CMD_RESP_EDGE (0) +#define TYPE_WRITE_CRC_EDGE (1) +#define TYPE_READ_DATA_EDGE (2) +#define TYPE_WRITE_DATA_EDGE (3) + +#define CARD_READY_FOR_DATA (1<<8) +#define CARD_CURRENT_STATE(x) ((x&0x00001E00)>>9) + +#define REQ_CMD_EIO (0x1 << 0) +#define REQ_CMD_TMO (0x1 << 1) +#define REQ_DAT_ERR (0x1 << 2) +#define REQ_STOP_EIO (0x1 << 3) +#define REQ_STOP_TMO (0x1 << 4) +#define REQ_CMD23_EIO (0x1 << 5) +#define REQ_CMD23_TMO (0x1 << 6) + +typedef void (*sdio_irq_handler_t)(void *); /* external irq handler */ +typedef void (*pm_callback_t)(pm_message_t state, void *data); + +#ifdef CONFIG_MTK_COMBO_COMM +#include +#define CFG_DEV_MSDC2 +#endif + +#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */ +#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */ +#define MSDC_RST_PIN_EN (1 << 2) /* emmc reset pin is wired */ +#define MSDC_SDIO_IRQ (1 << 3) /* use internal sdio irq (bus) */ +#define MSDC_EXT_SDIO_IRQ (1 << 4) /* use external sdio irq */ +#define MSDC_REMOVABLE (1 << 5) /* removable slot */ +#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */ +#define MSDC_SD_NEED_POWER (1 << 31) /* for some board, need SD power always on!! or cannot recognize the sd card*/ + +#define MSDC_CMD_PIN (0) +#define MSDC_DAT_PIN (1) +#define MSDC_CD_PIN (2) +#define MSDC_WP_PIN (3) +#define MSDC_RST_PIN (4) + +#define MSDC_DATA1_INT (1) +#define MSDC_BOOT_EN (1) + +struct msdc_hw { + unsigned char clk_src; /* host clock source */ + unsigned char cmd_edge; /* command latch edge */ + unsigned char rdata_edge; /* read data latch edge */ + unsigned char wdata_edge; /* write data latch edge */ + unsigned char clk_drv; /* clock pad driving */ + unsigned char cmd_drv; /* command pad driving */ + unsigned char dat_drv; /* data pad driving */ + unsigned char rst_drv; /* RST-N pad driving */ + unsigned char ds_drv; /* eMMC5.0 DS pad driving */ + unsigned char clk_drv_sd_18; /* clock pad driving for SD card at 1.8v sdr104 mode */ + unsigned char cmd_drv_sd_18; /* command pad driving for SD card at 1.8v sdr104 mode */ + unsigned char dat_drv_sd_18; /* data pad driving for SD card at 1.8v sdr104 mode */ + unsigned char clk_drv_sd_18_sdr50; /* clock pad driving for SD card at 1.8v sdr50 mode */ + unsigned char cmd_drv_sd_18_sdr50; /* command pad driving for SD card at 1.8v sdr50 mode */ + unsigned char dat_drv_sd_18_sdr50; /* data pad driving for SD card at 1.8v sdr50 mode */ + unsigned char clk_drv_sd_18_ddr50; /* clock pad driving for SD card at 1.8v ddr50 mode */ + unsigned char cmd_drv_sd_18_ddr50; /* command pad driving for SD card at 1.8v ddr50 mode */ + unsigned char dat_drv_sd_18_ddr50; /* data pad driving for SD card at 1.8v ddr50 mode */ + unsigned long flags; /* hardware capability flags */ + + unsigned char datrddly[8]; /*read; range: 0~31*/ + unsigned char datwrddly; /*write; range: 0~31*/ + unsigned char cmdrrddly; /*cmd; range: 0~31*/ + unsigned char cmdrddly; /*cmd; range: 0~31*/ + + unsigned char cmdrtactr_sdr50; /* command response turn around counter, sdr 50 mode*/ + unsigned char wdatcrctactr_sdr50; /* write data crc turn around counter, sdr 50 mode*/ + unsigned char intdatlatcksel_sdr50; /* internal data latch CK select, sdr 50 mode*/ + unsigned char cmdrtactr_sdr200; /* command response turn around counter, sdr 200 mode*/ + unsigned char wdatcrctactr_sdr200; /* write data crc turn around counter, sdr 200 mode*/ + unsigned char intdatlatcksel_sdr200; /* internal data latch CK select, sdr 200 mode*/ + + unsigned int boot; /* define boot host */ + unsigned char host_function; /* define host function */ + unsigned char cd_level; /* card detection level */ + + /* external power control for card */ + void (*ext_power_on)(void); + void (*ext_power_off)(void); + + /* external sdio irq operations */ + void (*request_sdio_eirq)(sdio_irq_handler_t sdio_irq_handler, void *data); + void (*enable_sdio_eirq)(void); + void (*disable_sdio_eirq)(void); + + /* power management callback for external module */ + void (*register_pm)(pm_callback_t pm_cb, void *data); +}; + + +/*--------------------------------------------------------------------------*/ +/* Descriptor Structure */ +/*--------------------------------------------------------------------------*/ +struct gpd_t { + u32 hwo:1; /* could be changed by hw */ + u32 bdp:1; + u32 rsv0:6; + u32 chksum:8; + u32 intr:1; + u32 rsv1:7; + u32 nexth4:4; + u32 ptrh4:4; + u32 next; + u32 ptr; + u32 buflen:24; + u32 extlen:8; + u32 arg; + u32 blknum; + u32 cmd; +}; + +struct bd_t { + u32 eol:1; + u32 rsv0:7; + u32 chksum:8; + u32 rsv1:1; + u32 blkpad:1; + u32 dwpad:1; + u32 rsv2:5; + u32 nexth4:4; + u32 ptrh4:4; + u32 next; + u32 ptr; + u32 buflen:24; + u32 rsv3:8; +}; + +struct scatterlist_ex { + u32 cmd; + u32 arg; + u32 sglen; + struct scatterlist *sg; +}; + +#define DMA_FLAG_NONE (0x00000000) +#define DMA_FLAG_EN_CHKSUM (0x00000001) +#define DMA_FLAG_PAD_BLOCK (0x00000002) +#define DMA_FLAG_PAD_DWORD (0x00000004) + +struct msdc_dma { + u32 flags; /* flags */ + u32 xfersz; /* xfer size in bytes */ + u32 sglen; /* size of scatter list */ + u32 blklen; /* block size */ + struct scatterlist *sg; /* I/O scatter list */ + struct scatterlist_ex *esg; /* extended I/O scatter list */ + u8 mode; /* dma mode */ + u8 burstsz; /* burst size */ + u8 intr; /* dma done interrupt */ + u8 padding; /* padding */ + u32 cmd; /* enhanced mode command */ + u32 arg; /* enhanced mode arg */ + u32 rsp; /* enhanced mode command response */ + u32 autorsp; /* auto command response */ + + struct gpd_t *gpd; /* pointer to gpd array */ + struct bd_t *bd; /* pointer to bd array */ + dma_addr_t gpd_addr; /* the physical address of gpd array */ + dma_addr_t bd_addr; /* the physical address of bd array */ + u32 used_gpd; /* the number of used gpd elements */ + u32 used_bd; /* the number of used bd elements */ +}; + +struct tune_counter { + u32 time_cmd; + u32 time_read; + u32 time_write; + u32 time_hs400; +}; + +/*FIX ME, consider to move it into msdc_tune.c*/ +struct msdc_saved_para { + u32 pad_tune0; + u32 pad_tune1; + u32 ddly0; + u32 ddly1; + u8 suspend_flag; + u32 msdc_cfg; + u32 mode; + u32 div; + u32 sdc_cfg; + u32 iocon; + u8 timing; + u32 hz; + u8 int_dat_latch_ck_sel; + u8 ckgen_msdc_dly_sel; + u8 inten_sdio_irq; + u8 write_busy_margin; /* for write: 3T need wait before host + check busy after crc status */ + u8 write_crc_margin; /* for write: host check timeout change + to 16T */ + u8 ds_dly1; + u8 ds_dly3; + u32 emmc50_pad_cmd_tune; + u32 emmc50_dat01; + u32 emmc50_dat23; + u32 emmc50_dat45; + u32 emmc50_dat67; + u32 pb1; + u32 pb2; +}; + +struct msdc_host { + struct msdc_hw *hw; + + struct mmc_host *mmc; /* mmc structure */ + struct mmc_command *cmd; + struct mmc_data *data; + struct mmc_request *mrq; + int cmd_rsp; + int cmd_rsp_done; + int cmd_r1b_done; + + int error; + spinlock_t lock; /* mutex */ + spinlock_t clk_gate_lock; + spinlock_t remove_bad_card; /* to solve removing bad card + race condition + with hot-plug enable*/ + spinlock_t sdio_irq_lock; /* avoid race condition + at DAT1 interrupt case*/ + int clk_gate_count; + struct semaphore sem; + + u32 blksz; /* host block size */ + void __iomem *base; /* host base address */ + int id; /* host id */ + + u32 xfer_size; /* total transferred size */ + + struct msdc_dma dma; /* dma channel */ + u64 dma_mask; + u32 dma_addr; /* dma transfer address */ + u32 dma_left_size; /* dma transfer left size */ + u32 dma_xfer_size; /* dma transfer size in bytes */ + int dma_xfer; /* dma transfer mode */ + + u32 write_timeout_ms; /* write busy timeout ms */ + u32 timeout_ns; /* data timeout ns */ + u32 timeout_clks; /* data timeout clks */ + + atomic_t abort; /* abort transfer */ + + int irq; /* host interrupt */ + +#ifdef MTK_MSDC_FLUSH_BY_CLK_GATE + struct tasklet_struct flush_cache_tasklet; +#endif + + struct delayed_work set_vcore_workq; + struct completion autok_done; + bool is_autok_done; + + atomic_t sdio_stopping; + + struct completion cmd_done; + struct completion xfer_done; + struct pm_message pm_state; + + u32 mclk; /* mmc subsystem clock */ + u32 hclk; /* host clock speed */ + u32 sclk; /* SD/MS clock speed */ + u8 core_clkon; /* host clock(cg) status */ + u8 timing; /* timing specification used */ + u8 power_mode; /* host power mode */ + u8 bus_width; + u8 card_inserted; /* card inserted ? */ + u8 suspend; /* host suspended ? */ + u8 app_cmd; /* for app command */ + u32 app_cmd_arg; + u64 starttime; + struct timer_list timer; + struct tune_counter t_counter; + u32 rwcmd_time_tune; + int read_time_tune; + int write_time_tune; + u32 write_timeout_uhs104; + u32 read_timeout_uhs104; + u32 write_timeout_emmc; + u32 read_timeout_emmc; + u8 autocmd; + u32 sw_timeout; + u32 power_cycle; /* power cycle done + in tuning flow*/ + bool power_cycle_enable; /* enable power cycle */ + bool error_tune_enable; /* enable error tune flow */ + u32 sd_30_busy; + bool tune; + bool first_tune_done; + bool async_tuning_in_progress; + bool async_tuning_done; + bool legacy_tuning_in_progress; + bool legacy_tuning_done; + int autok_error; + u32 tune_latch_ck_cnt; +#ifndef MSDC_WQ_ERROR_TUNE + unsigned int err_mrq_dir; +#endif + struct msdc_saved_para saved_para; + struct wakeup_source trans_lock; + bool block_bad_card; + struct delayed_work write_timeout; /* check if write busy timeout*/ +#ifdef SDIO_ERROR_BYPASS + int sdio_error; /* sdio error can't recovery */ +#endif + void (*power_control)(struct msdc_host *host, u32 on); + void (*power_switch)(struct msdc_host *host, u32 on); + u32 vmc_cal_default; + + struct clk *clock_control; + struct delayed_work work_init; /* for init mmc card */ + struct platform_device *pdev; + +#ifdef MSDC_WQ_ERROR_TUNE + struct work_struct work_tune; /* new thread tune */ + struct mmc_request *mrq_tune; /* backup host->mrq */ +#endif + +#if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + u32 power_DL_status; + u32 power_CL_status; +#endif + + int prev_cmd_cause_dump; +}; + +enum { + cmd_counter = 0, + read_counter, + write_counter, + all_counter, +}; + +enum { + TRAN_MOD_PIO, + TRAN_MOD_DMA, + TRAN_MOD_NUM +}; + +enum { + OPER_TYPE_READ, + OPER_TYPE_WRITE, + OPER_TYPE_NUM +}; + +struct dma_addr { + u32 start_address; + u32 size; + u8 end; + struct dma_addr *next; +}; + +struct msdc_reg_control { + ulong addr; + u32 mask; + u32 value; + u32 default_value; + /*int (*restore_func)(int restore);*/ +}; + +static inline unsigned int uffs(unsigned int x) +{ + unsigned int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + +#define MSDC_READ8(reg) __raw_readb((const volatile void *)reg) +#define MSDC_READ16(reg) __raw_readw((const volatile void *)reg) +#define MSDC_READ32(reg) __raw_readl((const volatile void *)reg) +#define MSDC_WRITE8(reg, val) mt_reg_sync_writeb(val, reg) +#define MSDC_WRITE16(reg, val) mt_reg_sync_writew(val, reg) +#define MSDC_WRITE32(reg, val) mt_reg_sync_writel(val, reg) + +#define UNSTUFF_BITS(resp, start, size) \ +({ \ + const int __size = size; \ + const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \ + const int __off = 3 - ((start) / 32); \ + const int __shft = (start) & 31; \ + u32 __res; \ + __res = resp[__off] >> __shft; \ + if (__size + __shft > 32) \ + __res |= resp[__off-1] << ((32 - __shft) % 32); \ + __res & __mask; \ +}) + +#define MSDC_SET_BIT32(reg, bs) \ + do { \ + volatile unsigned int tv = MSDC_READ32(reg);\ + tv |= (u32)(bs); \ + MSDC_WRITE32(reg, tv); \ + } while (0) + +#define MSDC_CLR_BIT32(reg, bs) \ + do { \ + volatile unsigned int tv = MSDC_READ32(reg);\ + tv &= ~((u32)(bs)); \ + MSDC_WRITE32(reg, tv); \ + } while (0) + +#define MSDC_SET_FIELD(reg, field, val) \ + do { \ + volatile unsigned int tv = MSDC_READ32(reg); \ + tv &= ~(field); \ + tv |= ((val) << (uffs((unsigned int)field) - 1)); \ + MSDC_WRITE32(reg, tv); \ + } while (0) + +#define MSDC_GET_FIELD(reg, field, val) \ + do { \ + volatile unsigned int tv = MSDC_READ32(reg); \ + val = ((tv & (field)) >> (uffs((unsigned int)field) - 1)); \ + } while (0) + +#define sdc_is_busy() (MSDC_READ32(SDC_STS) & SDC_STS_SDCBUSY) +#define sdc_is_cmd_busy() (MSDC_READ32(SDC_STS) & SDC_STS_CMDBUSY) + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT +#define sdc_send_cmdq_cmd(opcode, arg) \ + do { \ + MSDC_SET_FIELD(EMMC51_CFG0, MSDC_EMMC51_CFG_CMDQEN \ + | MSDC_EMMC51_CFG_NUM | MSDC_EMMC51_CFG_RSPTYPE \ + | MSDC_EMMC51_CFG_DTYPE, (0x81) | (opcode << 1)); \ + MSDC_WRITE32(SDC_ARG, (arg)); \ + MSDC_WRITE32(SDC_CMD, (0x0)); \ + } while (0) +#endif + +#define sdc_send_cmd(cmd, arg) \ + do { \ + MSDC_WRITE32(SDC_ARG, (arg)); \ + MSDC_WRITE32(SDC_CMD, (cmd)); \ + } while (0) + +#define msdc_retry(expr, retry, cnt, id) \ + do { \ + int backup = cnt; \ + while (retry) { \ + if (!(expr)) \ + break; \ + if (cnt-- == 0) { \ + retry--; mdelay(1); cnt = backup; \ + } \ + } \ + if (retry == 0) { \ + msdc_dump_info(id); \ + } \ + WARN_ON(retry == 0); \ + } while (0) + +#define msdc_reset(id) \ + do { \ + int retry = 3, cnt = 1000; \ + MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_RST); \ + msdc_retry(MSDC_READ32(MSDC_CFG) & MSDC_CFG_RST, retry, \ + cnt, id); \ + } while (0) + +#define msdc_clr_int() \ + do { \ + volatile u32 val = MSDC_READ32(MSDC_INT); \ + MSDC_WRITE32(MSDC_INT, val); \ + } while (0) + +#define msdc_reset_hw(id) \ + do { \ + msdc_reset(id); \ + msdc_clr_fifo(id); \ + msdc_clr_int(); \ + } while (0) + +#define msdc_txfifocnt() ((MSDC_READ32(MSDC_FIFOCS) \ + & MSDC_FIFOCS_TXCNT) >> 16) +#define msdc_rxfifocnt() ((MSDC_READ32(MSDC_FIFOCS) \ + & MSDC_FIFOCS_RXCNT) >> 0) +#define msdc_fifo_write32(v) MSDC_WRITE32(MSDC_TXDATA, (v)) +#define msdc_fifo_write8(v) MSDC_WRITE8(MSDC_TXDATA, (v)) +#define msdc_fifo_read32() MSDC_READ32(MSDC_RXDATA) +#define msdc_fifo_read8() MSDC_READ8(MSDC_RXDATA) + +/* can modify to read h/w register.*/ +/*#define is_card_present(h) \ + ((MSDC_READ32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1);*/ +#define is_card_present(h) (((struct msdc_host *)(h))->card_inserted) +#define is_card_sdio(h) (((struct msdc_host *)(h))->hw->register_pm) + +#define CMD_TIMEOUT (HZ/10 * 5) /* 100ms x5 */ +#define DAT_TIMEOUT (HZ * 5) /* 1000ms x5 */ +#define CLK_TIMEOUT (HZ * 5) /* 5s */ +#define POLLING_BUSY (HZ * 3) + +#ifdef CONFIG_OF +#if defined(CFG_DEV_MSDC2) +extern struct msdc_hw msdc2_hw; +#endif +#if defined(CFG_DEV_MSDC3) +extern struct msdc_hw msdc3_hw; +#endif +#endif + +extern struct msdc_host *mtk_msdc_host[]; +extern unsigned int msdc_latest_transfer_mode[HOST_MAX_NUM]; +#ifdef MSDC_DMA_ADDR_DEBUG +extern struct dma_addr msdc_latest_dma_address[MAX_BD_PER_GPD]; +#endif +extern int g_dma_debug[HOST_MAX_NUM]; + +extern u32 g_emmc_mode_switch; + +enum { + SD_TOOL_ZONE = 0, + SD_TOOL_DMA_SIZE = 1, + SD_TOOL_PM_ENABLE = 2, + SD_TOOL_SDIO_PROFILE = 3, + SD_TOOL_CLK_SRC_SELECT = 4, + SD_TOOL_REG_ACCESS = 5, + SD_TOOL_SET_DRIVING = 6, + SD_TOOL_DESENSE = 7, + RW_BIT_BY_BIT_COMPARE = 8, + SMP_TEST_ON_ONE_HOST = 9, + SMP_TEST_ON_ALL_HOST = 10, + SD_TOOL_MSDC_HOST_MODE = 11, + SD_TOOL_DMA_STATUS = 12, + SD_TOOL_ENABLE_SLEW_RATE = 13, + SD_TOOL_ENABLE_SMT = 14, + MMC_PERF_DEBUG = 15, + MMC_PERF_DEBUG_PRINT = 16, + SD_TOOL_SET_RDTDSEL = 17, + MMC_REGISTER_READ = 18, + MMC_REGISTER_WRITE = 19, + MSDC_READ_WRITE = 20, + MMC_ERROR_TUNE = 21, + MMC_EDC_EMMC_CACHE = 22, + MMC_DUMP_GPD = 23, + MMC_ETT_TUNE = 24, + MMC_CRC_STRESS = 25, + ENABLE_AXI_MODULE = 26, + SDIO_AUTOK_RESULT = 27, + DO_AUTOK_OFFLINE_TUNE_TX = 29, + MMC_CMDQ_STATUS = 30 +}; + +enum { + MODE_PIO = 0, + MODE_DMA = 1, + MODE_SIZE_DEP = 2, +}; + +/* Variable declared in dbg.c */ +extern u32 msdc_host_mode[]; +extern u32 msdc_host_mode2[]; + +extern unsigned int sd_debug_zone[]; +extern u32 drv_mode[]; +extern u32 dma_size[]; +extern unsigned char msdc_clock_src[]; + +extern u32 sdio_pro_enable; + +extern bool emmc_sleep_failed; + +extern int msdc_rsp[]; + + +/**********************************************************/ +/* Functions */ +/**********************************************************/ +#include "msdc_io.h" + +/* Function provided by sd.c */ +int msdc_clk_stable(struct msdc_host *host, u32 mode, u32 div, + u32 hs400_src); +void msdc_clr_fifo(unsigned int id); +unsigned int msdc_do_command(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout); +void msdc_dump_info(u32 id); +void msdc_dump_register(struct msdc_host *host); +void msdc_dump_register_core(u32 id, void __iomem *base); +void msdc_dump_dbg_register_core(u32 id, void __iomem *base); +void msdc_get_cache_region(struct work_struct *work); +int msdc_cache_ctrl(struct msdc_host *host, unsigned int enable, + u32 *status); +int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, + u32 *status); +int msdc_get_dma_status(int host_id); +struct msdc_host *msdc_get_host(int host_function, bool boot, + bool secondary); +int msdc_reinit(struct msdc_host *host); +void msdc_select_clksrc(struct msdc_host *host, int clksrc); +void msdc_send_stop(struct msdc_host *host); +void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz); +void msdc_set_smpl(struct msdc_host *host, u32 clkmode, u8 mode, u8 type, + u8 *edge); +void msdc_set_smpl_all(struct msdc_host *host, u32 clock_mode); +int msdc_switch_part(struct msdc_host *host, char part_id); +int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode); + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT +unsigned int msdc_do_cmdq_command(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout); +#endif + +/* Function provided by msdc_partition.c */ +#ifdef CONFIG_PWR_LOSS_MTK_TEST +void msdc_proc_emmc_create(void); +#endif +int msdc_can_apply_cache(unsigned long long start_addr, + unsigned int size); +struct gendisk *mmc_get_disk(struct mmc_card *card); +u64 msdc_get_capacity(int get_emmc_total); +u64 msdc_get_user_capacity(struct msdc_host *host); +u32 msdc_get_other_capacity(struct msdc_host *host, char *name); + +/* Function provided by mmc/core/sd.c */ +int mmc_sd_power_cycle(struct mmc_host *host, u32 ocr, + struct mmc_card *card); + +/* Function provided by mmc/core/bus.c */ +void mmc_remove_card(struct mmc_card *card); + + +#define check_mmc_cache_ctrl(card) \ + (card && mmc_card_mmc(card) && (card->ext_csd.cache_ctrl & 0x1)) +#define check_mmc_cache_flush_cmd(cmd) \ + ((cmd->opcode == MMC_SWITCH) && \ + (((cmd->arg >> 16) & 0xFF) == EXT_CSD_FLUSH_CACHE) && \ + (((cmd->arg >> 8) & 0x1))) +#define check_mmc_cmd2425(opcode) \ + ((opcode == MMC_WRITE_MULTIPLE_BLOCK) || \ + (opcode == MMC_WRITE_BLOCK)) +#define check_mmc_cmd1718(opcode) \ + ((opcode == MMC_READ_MULTIPLE_BLOCK) || \ + (opcode == MMC_READ_SINGLE_BLOCK)) +#define check_mmc_cmd1825(opcode) \ + ((opcode == MMC_READ_MULTIPLE_BLOCK) || \ + (opcode == MMC_WRITE_MULTIPLE_BLOCK)) +#define check_mmc_cmd01213(opcode) \ + ((opcode == MMC_GO_IDLE_STATE) || \ + (opcode == MMC_STOP_TRANSMISSION) || \ + (opcode == MMC_SEND_STATUS)) +#define check_mmc_cmd4445(opcode) \ + ((opcode == MMC_SET_QUEUE_CONTEXT) || \ + (opcode == MMC_QUEUE_READ_ADDRESS)) +#define check_mmc_cmd4647(opcode) \ + ((opcode == MMC_READ_REQUESTED_QUEUE) || \ + (opcode == MMC_WRITE_REQUESTED_QUEUE)) +#define check_mmc_cmd48(opcode) \ + (opcode == MMC_CMDQ_TASK_MGMT) +#define check_mmc_cmd44(x) \ + ((x) && \ + ((x)->opcode == MMC_SET_QUEUE_CONTEXT)) +#define check_mmc_cmd13_sqs(x) \ + (((x)->opcode == MMC_SEND_STATUS) && \ + ((x)->arg & (1 << 15))) + +#endif /* end of MT_SD_H */ + diff --git a/drivers/mmc/host/mediatek/mt6755/mt_sd_misc.c b/drivers/mmc/host/mediatek/mt6755/mt_sd_misc.c new file mode 100644 index 0000000000000000000000000000000000000000..56c1df689cc2f893a1da7f8657f7c9b14da973bb --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/mt_sd_misc.c @@ -0,0 +1,1421 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_COMPAT +#include +#endif + +#include "mt_sd.h" +#include +#include +#include "msdc_io.h" +#include "dbg.h" + +#define PARTITION_NAME_LENGTH (64) +#define DRV_NAME_MISC "misc-sd" + +#define DEBUG_MMC_IOCTL 0 +#define DEBUG_MSDC_SSC 1 +/* + * For simple_sd_ioctl + */ +#define FORCE_IN_DMA (0x11) +#define FORCE_IN_PIO (0x10) +#define FORCE_NOTHING (0x0) + +static int dma_force[HOST_MAX_NUM] = /* used for sd ioctrol */ +{ + FORCE_NOTHING, + FORCE_NOTHING, + FORCE_NOTHING, + FORCE_NOTHING, +}; + +#define dma_is_forced(host_id) (dma_force[host_id] & 0x10) +#define get_forced_transfer_mode(host_id) (dma_force[host_id] & 0x01) + + +static u32 *sg_msdc_multi_buffer; + +static int simple_sd_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int sd_ioctl_reinit(struct msdc_ioctl *msdc_ctl) +{ + struct msdc_host *host = msdc_get_host(MSDC_SD, 0, 0); + if (NULL != host) + return msdc_reinit(host); + else + return -EINVAL; +} + +static int sd_ioctl_cd_pin_en(struct msdc_ioctl *msdc_ctl) +{ + struct msdc_host *host = msdc_get_host(MSDC_SD, 0, 0); + + if (NULL != host) + return (host->mmc->caps & MMC_CAP_NONREMOVABLE) + == MMC_CAP_NONREMOVABLE; + else + return -EINVAL; +} + +int simple_sd_ioctl_rw(struct msdc_ioctl *msdc_ctl) +{ + struct scatterlist msdc_sg; + struct mmc_data msdc_data; + struct mmc_command msdc_cmd; + struct mmc_command msdc_stop; +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + int is_cmdq_en; +#endif + int ret = 0; +#ifdef CONFIG_MTK_EMMC_SUPPORT + char part_id; +#endif + int no_single_rw; + u32 total_size; + +#ifdef MTK_MSDC_USE_CMD23 + struct mmc_command msdc_sbc; +#endif + + struct mmc_request msdc_mrq; + struct msdc_host *host_ctl; + struct mmc_host *mmc; + + if (!msdc_ctl) + return -EINVAL; + + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + mmc = host_ctl->mmc; + + if ((msdc_ctl->total_size <= 0) || + (msdc_ctl->total_size > host_ctl->mmc->max_seg_size)) + return -EINVAL; + total_size = msdc_ctl->total_size; + + if (msdc_ctl->total_size > 512) + no_single_rw = 1; + else + no_single_rw = 0; + +#ifdef MTK_MSDC_USE_CACHE + if (msdc_ctl->iswrite && mmc_card_mmc(mmc->card) + && (mmc->card->ext_csd.cache_ctrl & 0x1)) + no_single_rw = 1; +#endif + + mmc_claim_host(mmc); + +#if DEBUG_MMC_IOCTL + pr_debug("user want access %d partition\n", msdc_ctl->partition); +#endif + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + is_cmdq_en = false; + if (mmc->card->ext_csd.cmdq_mode_en) { + /* cmdq enabled, turn it off first */ + pr_debug("[MSDC_DBG] cmdq enabled, turn it off\n"); + ret = mmc_blk_cmdq_switch(mmc->card, 0); + if (ret) { + pr_debug("[MSDC_DBG] turn off cmdq en failed\n"); + goto rw_end; + } else + is_cmdq_en = true; + } +#endif + +#ifdef CONFIG_MTK_EMMC_SUPPORT + switch (msdc_ctl->partition) { + case EMMC_PART_BOOT1: + part_id = 1; + break; + case EMMC_PART_BOOT2: + part_id = 2; + break; + default: + /* make sure access partition is user data area */ + part_id = 0; + break; + } + + if (msdc_switch_part(host_ctl, part_id)) + goto rw_end; + +#endif + + memset(&msdc_data, 0, sizeof(struct mmc_data)); + memset(&msdc_mrq, 0, sizeof(struct mmc_request)); + memset(&msdc_cmd, 0, sizeof(struct mmc_command)); + + if (no_single_rw) { + memset(&msdc_stop, 0, sizeof(struct mmc_command)); + +#ifdef MTK_MSDC_USE_CMD23 + memset(&msdc_sbc, 0, sizeof(struct mmc_command)); +#endif + } + + msdc_mrq.cmd = &msdc_cmd; + msdc_mrq.data = &msdc_data; + + if (msdc_ctl->trans_type) + dma_force[host_ctl->id] = FORCE_IN_DMA; + else + dma_force[host_ctl->id] = FORCE_IN_PIO; + + if (msdc_ctl->iswrite) { + msdc_data.flags = MMC_DATA_WRITE; + if (no_single_rw) + msdc_cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; + else + msdc_cmd.opcode = MMC_WRITE_BLOCK; + msdc_data.blocks = total_size / 512; + if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { + if (copy_from_user(sg_msdc_multi_buffer, + msdc_ctl->buffer, total_size)) { + dma_force[host_ctl->id] = FORCE_NOTHING; + ret = -EFAULT; + goto rw_end; + } + } else { + /* called from other kernel module */ + memcpy(sg_msdc_multi_buffer, msdc_ctl->buffer, + total_size); + } + } else { + msdc_data.flags = MMC_DATA_READ; + if (no_single_rw) + msdc_cmd.opcode = MMC_READ_MULTIPLE_BLOCK; + else + msdc_cmd.opcode = MMC_READ_SINGLE_BLOCK; + msdc_data.blocks = total_size / 512; + memset(sg_msdc_multi_buffer, 0, total_size); + } + +#ifdef MTK_MSDC_USE_CMD23 + if (no_single_rw == 0) + goto skip_sbc_prepare; + + if ((mmc_card_mmc(mmc->card) || (mmc_card_sd(mmc->card) + && mmc->card->scr.cmds & SD_SCR_CMD23_SUPPORT)) + && !(mmc->card->quirks & MMC_QUIRK_BLK_NO_CMD23)) { + msdc_mrq.sbc = &msdc_sbc; + msdc_mrq.sbc->opcode = MMC_SET_BLOCK_COUNT; +#ifdef MTK_MSDC_USE_CACHE + /* if ioctl access cacheable partition data, + there is on flush mechanism in msdc driver + * so do reliable write .*/ + if (mmc_card_mmc(mmc->card) + && (mmc->card->ext_csd.cache_ctrl & 0x1) + && (msdc_cmd.opcode == MMC_WRITE_MULTIPLE_BLOCK)) + msdc_mrq.sbc->arg = msdc_data.blocks | (1 << 31); + else + msdc_mrq.sbc->arg = msdc_data.blocks; +#else + msdc_mrq.sbc->arg = msdc_data.blocks; +#endif + msdc_mrq.sbc->flags = MMC_RSP_R1 | MMC_CMD_AC; + } +skip_sbc_prepare: +#endif + + msdc_cmd.arg = msdc_ctl->address; + + if (!mmc_card_blockaddr(mmc->card)) { + pr_debug("this device use byte address!!\n"); + msdc_cmd.arg <<= 9; + } + msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + + if (no_single_rw) { + msdc_stop.opcode = MMC_STOP_TRANSMISSION; + msdc_stop.arg = 0; + msdc_stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + + msdc_data.stop = &msdc_stop; + } else { + msdc_data.stop = NULL; + } + msdc_data.blksz = 512; + msdc_data.sg = &msdc_sg; + msdc_data.sg_len = 1; + +#if DEBUG_MMC_IOCTL + pr_debug("total size is %d\n", total_size); + pr_debug("ueser buf address is 0x%p!\n", msdc_ctl->buffer); +#endif + sg_init_one(&msdc_sg, sg_msdc_multi_buffer, total_size); + mmc_set_data_timeout(&msdc_data, mmc->card); + mmc_wait_for_req(mmc, &msdc_mrq); + + if (msdc_ctl->partition) + msdc_switch_part(host_ctl, 0); + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (is_cmdq_en) { + pr_debug("[MSDC_DBG] turn on cmdq\n"); + ret = mmc_blk_cmdq_switch(host_ctl->mmc->card, 1); + if (ret) + pr_debug("[MSDC_DBG] turn on cmdq en failed\n"); + else + is_cmdq_en = false; + } +#endif + mmc_release_host(mmc); + if (!msdc_ctl->iswrite) { + if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { + if (copy_to_user(msdc_ctl->buffer, sg_msdc_multi_buffer, + total_size)) { + dma_force[host_ctl->id] = FORCE_NOTHING; + ret = -EFAULT; + goto rw_end_without_release; + } + } else { + /* called from other kernel module */ + memcpy(msdc_ctl->buffer, sg_msdc_multi_buffer, + total_size); + } + } + + /* clear the global buffer of R/W IOCTL */ + memset(sg_msdc_multi_buffer, 0 , total_size); + goto rw_end_without_release; + +rw_end: +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (is_cmdq_en) { + pr_debug("[MSDC_DBG] turn on cmdq\n"); + ret = mmc_blk_cmdq_switch(mmc->card, 1); + if (ret) + pr_debug("[MSDC_DBG] turn on cmdq en failed\n"); + else + is_cmdq_en = false; + } +#endif + mmc_release_host(mmc); + +rw_end_without_release: + if (ret) + msdc_ctl->result = ret; + + if (msdc_cmd.error) + msdc_ctl->result = msdc_cmd.error; + + if (msdc_data.error) + msdc_ctl->result = msdc_data.error; + else + msdc_ctl->result = 0; + + dma_force[host_ctl->id] = FORCE_NOTHING; + return msdc_ctl->result; + +} + +static int simple_sd_ioctl_get_cid(struct msdc_ioctl *msdc_ctl) +{ + struct msdc_host *host_ctl; + + if (!msdc_ctl) + return -EINVAL; + + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; + + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + +#if DEBUG_MMC_IOCTL + pr_debug("user want the cid in msdc slot%d\n", msdc_ctl->host_num); +#endif + + if (copy_to_user(msdc_ctl->buffer, &host_ctl->mmc->card->raw_cid, 16)) + return -EFAULT; + +#if DEBUG_MMC_IOCTL + pr_debug("cid:0x%x,0x%x,0x%x,0x%x\n", + host_ctl->mmc->card->raw_cid[0], + host_ctl->mmc->card->raw_cid[1], + host_ctl->mmc->card->raw_cid[2], + host_ctl->mmc->card->raw_cid[3]); +#endif + return 0; + +} + +static int simple_sd_ioctl_get_csd(struct msdc_ioctl *msdc_ctl) +{ + struct msdc_host *host_ctl; + + if (!msdc_ctl) + return -EINVAL; + + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; + + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + +#if DEBUG_MMC_IOCTL + pr_debug("user want the csd in msdc slot%d\n", msdc_ctl->host_num); +#endif + + if (copy_to_user(msdc_ctl->buffer, &host_ctl->mmc->card->raw_csd, 16)) + return -EFAULT; + +#if DEBUG_MMC_IOCTL + pr_debug("csd:0x%x,0x%x,0x%x,0x%x\n", + host_ctl->mmc->card->raw_csd[0], + host_ctl->mmc->card->raw_csd[1], + host_ctl->mmc->card->raw_csd[2], + host_ctl->mmc->card->raw_csd[3]); +#endif + return 0; + +} + +static int simple_sd_ioctl_get_excsd(struct msdc_ioctl *msdc_ctl) +{ + char *l_buf; + struct msdc_host *host_ctl; + struct mmc_host *mmc; + int ret; + +#if DEBUG_MMC_IOCTL + int i; +#endif + + if (!msdc_ctl) + return -EINVAL; + + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; + + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + mmc = host_ctl->mmc; + + l_buf = kzalloc((512), GFP_KERNEL); + if (!l_buf) + return -ENOMEM; + + mmc_claim_host(mmc); + +#if DEBUG_MMC_IOCTL + pr_debug("user want the extend csd in msdc slot%d\n", + msdc_ctl->host_num); +#endif + ret = mmc_send_ext_csd(mmc->card, l_buf); + mmc_release_host(mmc); + if (ret) + goto end; + + if (copy_to_user(msdc_ctl->buffer, l_buf, 512)) + return -EFAULT; + +#if DEBUG_MMC_IOCTL + for (i = 0; i < 512; i++) { + pr_debug("%x", l_buf[i]); + if (0 == ((i + 1) % 16)) + pr_debug("\n"); + } +#endif + +end: + kfree(l_buf); + + return 0; + +} + +static int simple_sd_ioctl_get_bootpart(struct msdc_ioctl *msdc_ctl) +{ + char *l_buf; + struct msdc_host *host_ctl; + struct mmc_host *mmc; + int ret = 0; + int bootpart = 0; + + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + mmc = host_ctl->mmc; + + if (msdc_ctl->buffer == NULL) + return -EINVAL; + + l_buf = kzalloc((512), GFP_KERNEL); + if (!l_buf) + return -ENOMEM; + + mmc_claim_host(mmc); + +#if DEBUG_MMC_IOCTL + pr_debug("user want get boot partition info in msdc slot%d\n", + msdc_ctl->host_num); +#endif + ret = mmc_send_ext_csd(mmc->card, l_buf); + if (ret) { + pr_debug("mmc_send_ext_csd error, get boot part\n"); + goto end; + } + bootpart = (l_buf[EXT_CSD_PART_CFG] & 0x38) >> 3; + +#if DEBUG_MMC_IOCTL + pr_debug("bootpart Byte[EXT_CSD_PART_CFG] =%x, booten=%x\n", + l_buf[EXT_CSD_PART_CFG], bootpart); +#endif + + if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { + if (copy_to_user(msdc_ctl->buffer, &bootpart, 1)) { + ret = -EFAULT; + goto end; + } + } else { + /* called from other kernel module */ + memcpy(msdc_ctl->buffer, &bootpart, 1); + } + +end: + msdc_ctl->result = ret; + + mmc_release_host(mmc); + + kfree(l_buf); + + return ret; +} + +static int simple_sd_ioctl_set_bootpart(struct msdc_ioctl *msdc_ctl) +{ + char *l_buf; + struct msdc_host *host_ctl; + struct mmc_host *mmc; + int ret = 0; + int bootpart = 0; + + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; + + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + mmc = host_ctl->mmc; + + if (msdc_ctl->buffer == NULL) + return -EINVAL; + + l_buf = kzalloc((512), GFP_KERNEL); + if (!l_buf) + return -ENOMEM; + + mmc_claim_host(mmc); + +#if DEBUG_MMC_IOCTL + pr_debug("user want set boot partition in msdc slot%d\n", + msdc_ctl->host_num); +#endif + ret = mmc_send_ext_csd(mmc->card, l_buf); + if (ret) { + pr_debug("mmc_send_ext_csd error, set boot partition\n"); + goto end; + } + + if (copy_from_user(&bootpart, msdc_ctl->buffer, 1)) { + ret = -EFAULT; + goto end; + } + + if ((bootpart != EMMC_BOOT1_EN) + && (bootpart != EMMC_BOOT2_EN) + && (bootpart != EMMC_BOOT_USER)) { + pr_debug("set boot partition error, not support %d\n", + bootpart); + ret = -EFAULT; + goto end; + } + + if (((l_buf[EXT_CSD_PART_CFG] & 0x38) >> 3) != bootpart) { + /* active boot partition */ + l_buf[EXT_CSD_PART_CFG] &= ~0x38; + l_buf[EXT_CSD_PART_CFG] |= (bootpart << 3); + pr_debug("mmc_switch set %x\n", l_buf[EXT_CSD_PART_CFG]); + ret = mmc_switch(mmc->card, 0, EXT_CSD_PART_CFG, + l_buf[EXT_CSD_PART_CFG], 1000); + if (ret) { + pr_debug("mmc_switch error, set boot partition\n"); + } else { + mmc->card->ext_csd.part_config = + l_buf[EXT_CSD_PART_CFG]; + } + } + +end: + msdc_ctl->result = ret; + + mmc_release_host(mmc); + + kfree(l_buf); + return ret; +} + +static int simple_sd_ioctl_get_partition_size(struct msdc_ioctl *msdc_ctl) +{ + struct msdc_host *host_ctl; + unsigned long long partitionsize = 0; + struct mmc_host *mmc; + int ret = 0; + + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; + + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + + mmc = host_ctl->mmc; + + mmc_claim_host(mmc); + +#if DEBUG_MMC_IOCTL + pr_debug("user want get size of partition=%d\n", msdc_ctl->partition); +#endif + + switch (msdc_ctl->partition) { + case EMMC_PART_BOOT1: + partitionsize = msdc_get_other_capacity(host_ctl, "boot0"); + break; + case EMMC_PART_BOOT2: + partitionsize = msdc_get_other_capacity(host_ctl, "boot1"); + break; + case EMMC_PART_RPMB: + partitionsize = msdc_get_other_capacity(host_ctl, "rpmb"); + break; + case EMMC_PART_USER: + partitionsize = msdc_get_user_capacity(host_ctl); + break; + default: + pr_debug("not support partition =%d\n", msdc_ctl->partition); + partitionsize = 0; + break; + } +#if DEBUG_MMC_IOCTL + pr_debug("bootpart partitionsize =%llx\n", partitionsize); +#endif + if (copy_to_user(msdc_ctl->buffer, &partitionsize, 8)) + ret = -EFAULT; + + msdc_ctl->result = ret; + + mmc_release_host(mmc); + return ret; +} + +static int simple_sd_ioctl_set_driving(struct msdc_ioctl *msdc_ctl) +{ + void __iomem *base; + struct msdc_host *host; + + host = mtk_msdc_host[msdc_ctl->host_num]; + if (host == NULL) + return -EINVAL; + + base = host->base; + + msdc_clk_enable(host); + +#if DEBUG_MMC_IOCTL + pr_debug("set: clk driving is 0x%x\n", msdc_ctl->clk_pu_driving); + pr_debug("set: cmd driving is 0x%x\n", msdc_ctl->cmd_pu_driving); + pr_debug("set: dat driving is 0x%x\n", msdc_ctl->dat_pu_driving); + pr_debug("set: rst driving is 0x%x\n", msdc_ctl->rst_pu_driving); + pr_debug("set: ds driving is 0x%x\n", msdc_ctl->ds_pu_driving); +#endif + host->hw->clk_drv = msdc_ctl->clk_pu_driving; + host->hw->cmd_drv = msdc_ctl->cmd_pu_driving; + host->hw->dat_drv = msdc_ctl->dat_pu_driving; + host->hw->rst_drv = msdc_ctl->rst_pu_driving; + host->hw->ds_drv = msdc_ctl->ds_pu_driving; + host->hw->clk_drv_sd_18 = msdc_ctl->clk_pu_driving; + host->hw->cmd_drv_sd_18 = msdc_ctl->cmd_pu_driving; + host->hw->dat_drv_sd_18 = msdc_ctl->dat_pu_driving; + msdc_set_driving(host, host->hw, 0); +#if DEBUG_MMC_IOCTL +#if 0 + msdc_dump_padctl(host); +#endif +#endif + + return 0; +} + +static int simple_sd_ioctl_get_driving(struct msdc_ioctl *msdc_ctl) +{ + void __iomem *base; + struct msdc_host *host; + + host = mtk_msdc_host[msdc_ctl->host_num]; + if (host == NULL) + return -EINVAL; + + base = host->base; + + (void)msdc_clk_enable(host); + + msdc_get_driving(host, host->hw); + + if ((host->id == 1) && (g_msdc1_io == 1800000)) { + msdc_ctl->clk_pu_driving = host->hw->clk_drv_sd_18; + msdc_ctl->cmd_pu_driving = host->hw->cmd_drv_sd_18; + msdc_ctl->dat_pu_driving = host->hw->dat_drv_sd_18; + } else { + msdc_ctl->clk_pu_driving = host->hw->clk_drv; + msdc_ctl->cmd_pu_driving = host->hw->cmd_drv; + msdc_ctl->dat_pu_driving = host->hw->dat_drv; + } + if (host->id == 0) { + msdc_ctl->rst_pu_driving = host->hw->rst_drv; + msdc_ctl->ds_pu_driving = host->hw->ds_drv; + } else { + msdc_ctl->rst_pu_driving = 0; + msdc_ctl->ds_pu_driving = 0; + } + +#if DEBUG_MMC_IOCTL + pr_debug("read: clk driving is 0x%x\n", msdc_ctl->clk_pu_driving); + pr_debug("read: cmd driving is 0x%x\n", msdc_ctl->cmd_pu_driving); + pr_debug("read: dat driving is 0x%x\n", msdc_ctl->dat_pu_driving); + pr_debug("read: rst driving is 0x%x\n", msdc_ctl->rst_pu_driving); + pr_debug("read: ds driving is 0x%x\n", msdc_ctl->ds_pu_driving); +#endif + + return 0; +} + +static int simple_sd_ioctl_sd30_mode_switch(struct msdc_ioctl *msdc_ctl) +{ + int id; + + unsigned int timing_table[2][7] = { + { /* select mode in EM */ + MMC_TIMING_MMC_HS, /*SDHC_HIGHSPEED*/ + MMC_TIMING_LEGACY, /*UHS_SDR12*/ + MMC_TIMING_MMC_HS, /*UHS_SDR25*/ + MMC_TIMING_MMC_HS, /*UHS_SDR50*/ + MMC_TIMING_MMC_HS200, /*UHS_SDR104*/ + MMC_TIMING_MMC_DDR52, /*UHS_DDR50*/ + MMC_TIMING_MMC_HS400 /*EMMC_HS400*/ + }, + { + MMC_TIMING_SD_HS, /*SDHC_HIGHSPEED*/ + MMC_TIMING_UHS_SDR12, /*UHS_SDR12*/ + MMC_TIMING_UHS_SDR25, /*UHS_SDR25*/ + MMC_TIMING_UHS_SDR50, /*UHS_SDR50*/ + MMC_TIMING_UHS_SDR104, /*UHS_SDR104*/ + MMC_TIMING_UHS_DDR50, /*UHS_DDR50*/ + MMC_TIMING_UHS_SDR104 /*EMMC_HS400*/ + }, + }; + unsigned int timing; + + if ((msdc_ctl->sd30_mode < 0) || (msdc_ctl->sd30_mode > 6)) + return -EINVAL; + + id = msdc_ctl->host_num; + + if (mtk_msdc_host[id] == NULL) + return -EINVAL; + + if (id == 0) + timing = timing_table[0][msdc_ctl->sd30_mode]; + else + timing = timing_table[1][msdc_ctl->sd30_mode]; + + msdc_set_host_mode_speed(mtk_msdc_host[id]->mmc, timing, -1); + + return 0; +} + +/* to ensure format operate is clean the emmc device fully(partition erase) */ +struct mbr_part_info { + unsigned int start_sector; + unsigned int nr_sects; + unsigned int part_no; + unsigned char *part_name; +}; + +#define MBR_PART_NUM 6 +#define __MMC_ERASE_ARG 0x00000000 +#define __MMC_TRIM_ARG 0x00000001 +#define __MMC_DISCARD_ARG 0x00000003 + +int msdc_get_info(STORAGE_TPYE storage_type, GET_STORAGE_INFO info_type, + struct storage_info *info) +{ + struct msdc_host *host = NULL; + int host_function = 0; + bool boot = 0; + + if (!info) + return -EINVAL; + + switch (storage_type) { + case EMMC_CARD_BOOT: + host_function = MSDC_EMMC; + boot = MSDC_BOOT_EN; + break; + case EMMC_CARD: + host_function = MSDC_EMMC; + break; + case SD_CARD_BOOT: + host_function = MSDC_SD; + boot = MSDC_BOOT_EN; + break; + case SD_CARD: + host_function = MSDC_SD; + break; + default: + pr_err("No supported storage type!"); + return 0; + } + host = msdc_get_host(host_function, boot, 0); + BUG_ON(!host || !host->mmc); + switch (info_type) { + /* FIX ME: check if any user space program use this EMMC_XXX */ + case CARD_INFO: + if (host->mmc->card) + info->card = host->mmc->card; + else { + pr_err("CARD was not ready!"); + return 0; + } + break; + case DISK_INFO: + if (host->mmc->card) + info->disk = mmc_get_disk(host->mmc->card); + else { + pr_err("CARD was not ready!"); + return 0; + } + break; + case EMMC_USER_CAPACITY: + info->emmc_user_capacity = msdc_get_capacity(0); + break; + case EMMC_CAPACITY: + info->emmc_capacity = msdc_get_capacity(1); + break; + case EMMC_RESERVE: +#ifdef CONFIG_MTK_EMMC_SUPPORT + info->emmc_reserve = 0; +#endif + break; + default: + pr_err("Please check INFO_TYPE"); + return 0; + } + return 1; +} + +#ifdef CONFIG_MTK_EMMC_SUPPORT +static int simple_mmc_get_disk_info(struct mbr_part_info *mpi, + unsigned char *name) +{ + struct disk_part_iter piter; + struct hd_struct *part; + struct msdc_host *host; + struct gendisk *disk; + + /* emmc always in slot0 */ + host = msdc_get_host(MSDC_EMMC, MSDC_BOOT_EN, 0); + + disk = mmc_get_disk(host->mmc->card); + + /* Find partition info in this way to + * avoid addr translation in scatter file and 64bit address calculate */ + disk_part_iter_init(&piter, disk, 0); + while ((part = disk_part_iter_next(&piter))) { +#if DEBUG_MMC_IOCTL + pr_debug("part_name = %s name = %s\n", part->info->volname, + name); +#endif + if (!strncmp(part->info->volname, name, + PARTITION_NAME_LENGTH)) { + mpi->start_sector = part->start_sect; + mpi->nr_sects = part->nr_sects; + mpi->part_no = part->partno; + mpi->part_name = part->info->volname; + disk_part_iter_exit(&piter); + return 0; + } + } + disk_part_iter_exit(&piter); + + return 1; +} + +/* call mmc block layer interface for userspace to do erase operate */ +static int simple_mmc_erase_func(unsigned int start, unsigned int size) +{ + struct msdc_host *host; + struct mmc_host *mmc; + unsigned int arg; + + /* emmc always in slot0 */ + host = msdc_get_host(MSDC_EMMC, MSDC_BOOT_EN, 0); + BUG_ON(!host || !host->mmc || !host->mmc->card); + mmc = host->mmc; + + mmc_claim_host(mmc); + + if (mmc_can_discard(mmc->card)) { + arg = __MMC_DISCARD_ARG; + } else if (mmc_can_trim(mmc->card)) { + arg = __MMC_TRIM_ARG; + } else if (mmc_can_erase(mmc->card)) { + arg = __MMC_ERASE_ARG; + } else { + pr_err("[%s]: emmc card can't support trim / discard / erase\n", + __func__); + goto end; + } + + pr_debug("[%s]: start=0x%x, size=%d, arg=0x%x, can_trim=(0x%x), EXT_CSD_SEC_GB_CL_EN=0x%lx\n", + __func__, start, size, arg, + mmc->card->ext_csd.sec_feature_support, + EXT_CSD_SEC_GB_CL_EN); + mmc_erase(mmc->card, start, size, arg); + +#if DEBUG_MMC_IOCTL + pr_debug("[%s]: erase done....arg=0x%x\n", __func__, arg); +#endif +end: + mmc_release_host(mmc); + + return 0; +} +#endif + +/* These definitiona and functions are coded by reference to + mmc_blk_issue_discard_rq()@block.c*/ +#define INAND_CMD38_ARG_EXT_CSD 113 +#define INAND_CMD38_ARG_ERASE 0x00 +#define INAND_CMD38_ARG_TRIM 0x01 +#define INAND_CMD38_ARG_SECERASE 0x80 +#define INAND_CMD38_ARG_SECTRIM1 0x81 +#define INAND_CMD38_ARG_SECTRIM2 0x88 +static int simple_sd_ioctl_erase_selected_area(struct msdc_ioctl *msdc_ctl) +{ + struct msdc_host *host_ctl; + struct mmc_host *mmc; + unsigned int from, nr, arg; + int err = 0; + + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; + BUG_ON(!host_ctl || !host_ctl->mmc || !host_ctl->mmc->card); + mmc = host_ctl->mmc; + + mmc_claim_host(mmc); + + msdc_switch_part(host_ctl, 0); + + if (!mmc_can_erase(mmc->card)) { + err = -EOPNOTSUPP; + goto out; + } + + from = msdc_ctl->address; + nr = msdc_ctl->total_size; + + if (mmc_can_discard(mmc->card)) + arg = MMC_DISCARD_ARG; + else if (mmc_can_trim(mmc->card)) + arg = MMC_TRIM_ARG; + else + arg = MMC_ERASE_ARG; + +#if DEBUG_MMC_IOCTL + pr_debug("Erase range %x~%x\n", from, from + nr - 1); +#endif + + if (mmc_card_mmc(mmc->card)) { + if (mmc->card->quirks & MMC_QUIRK_INAND_CMD38) { + err = mmc_switch(mmc->card, EXT_CSD_CMD_SET_NORMAL, + INAND_CMD38_ARG_EXT_CSD, + arg == MMC_TRIM_ARG ? + INAND_CMD38_ARG_TRIM : + INAND_CMD38_ARG_ERASE, + 0); + if (err) + goto out; + } + } + + err = mmc_erase(mmc->card, from, nr, arg); +out: + + mmc_release_host(mmc); + + msdc_ctl->result = err; + + return msdc_ctl->result; + +} + +static int simple_mmc_erase_partition(unsigned char *name) +{ +#ifdef CONFIG_MTK_EMMC_SUPPORT + struct mbr_part_info mbr_part; + int l_ret; + + /* just support erase cache & data partition now */ + if (name && + (strncmp(name, "usrdata", 7) == 0 || + strncmp(name, "cache", 5) == 0)) { + /* find erase start address and erase size, + just support high capacity emmc card now */ + l_ret = simple_mmc_get_disk_info(&mbr_part, name); + + if (l_ret == 0) { + /* do erase */ + pr_debug("erase %s start sector: 0x%x size: 0x%x\n", + mbr_part.part_name, + mbr_part.start_sector, mbr_part.nr_sects); + simple_mmc_erase_func(mbr_part.start_sector, + mbr_part.nr_sects); + } + } +#endif + return 0; + +} + +static int simple_mmc_erase_partition_wrap(struct msdc_ioctl *msdc_ctl) +{ + unsigned char name[PARTITION_NAME_LENGTH]; + + if (!msdc_ctl) + return -EINVAL; + + if (msdc_ctl->total_size > PARTITION_NAME_LENGTH) + return -EFAULT; + + if (copy_from_user(name, (unsigned char *)msdc_ctl->buffer, + msdc_ctl->total_size)) + return -EFAULT; + + return simple_mmc_erase_partition(name); +} + +static long simple_sd_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct msdc_ioctl msdc_ctl; + struct msdc_host *host; + int ret = 0; + + if ((struct msdc_ioctl *)arg == NULL) { + switch (cmd) { + case MSDC_REINIT_SDCARD: + pr_err("sd ioctl re-init!!\n"); + ret = sd_ioctl_reinit((struct msdc_ioctl *)arg); + break; + + case MSDC_CD_PIN_EN_SDCARD: + pr_err("sd ioctl cd pin\n"); + ret = sd_ioctl_cd_pin_en((struct msdc_ioctl *)arg); + break; + + case MSDC_SD_POWER_OFF: + pr_err("sd ioctl power off!!!\n"); + host = msdc_get_host(MSDC_SD, 0, 0); + mmc_claim_host(host->mmc); + mmc_power_off(host->mmc); + mmc_release_host(host->mmc); + break; + + case MSDC_SD_POWER_ON: + pr_err("sd ioctl power on!!!\n"); + host = msdc_get_host(MSDC_SD, 0, 0); + /* FIX ME: kernel 3.18 does not provide + mmc_resume_host */ + /* + ret = mmc_resume_host(host->mmc);*/ + break; + + default: + pr_err("mt_sd_ioctl:this opcode value is illegal!!\n"); + return -EINVAL; + } + return ret; + } + + if (copy_from_user(&msdc_ctl, (struct msdc_ioctl *)arg, + sizeof(struct msdc_ioctl))) { + return -EFAULT; + } + + if (msdc_ctl.opcode != MSDC_ERASE_PARTITION) { + if ((msdc_ctl.host_num < 0) + || (msdc_ctl.host_num >= HOST_MAX_NUM)) { + pr_err("invalid host num: %d\n", msdc_ctl.host_num); + return -EINVAL; + } + } + + switch (msdc_ctl.opcode) { + case MSDC_SINGLE_READ_WRITE: + case MSDC_MULTIPLE_READ_WRITE: + msdc_ctl.result = simple_sd_ioctl_rw(&msdc_ctl); + break; + case MSDC_GET_CID: + msdc_ctl.result = simple_sd_ioctl_get_cid(&msdc_ctl); + break; + case MSDC_GET_CSD: + msdc_ctl.result = simple_sd_ioctl_get_csd(&msdc_ctl); + break; + case MSDC_GET_EXCSD: + msdc_ctl.result = simple_sd_ioctl_get_excsd(&msdc_ctl); + break; + case MSDC_DRIVING_SETTING: + if (1 == msdc_ctl.iswrite) { + msdc_ctl.result = + simple_sd_ioctl_set_driving(&msdc_ctl); + } else { + msdc_ctl.result = + simple_sd_ioctl_get_driving(&msdc_ctl); + } + break; + case MSDC_ERASE_PARTITION: + msdc_ctl.result = + simple_mmc_erase_partition_wrap(&msdc_ctl); + break; + case MSDC_ERASE_SELECTED_AREA: + msdc_ctl.result = simple_sd_ioctl_erase_selected_area( + &msdc_ctl); + break; + case MSDC_SD30_MODE_SWITCH: + msdc_ctl.result = + simple_sd_ioctl_sd30_mode_switch(&msdc_ctl); + break; + case MSDC_GET_BOOTPART: + msdc_ctl.result = + simple_sd_ioctl_get_bootpart(&msdc_ctl); + break; + case MSDC_SET_BOOTPART: + msdc_ctl.result = + simple_sd_ioctl_set_bootpart(&msdc_ctl); + break; + case MSDC_GET_PARTSIZE: + msdc_ctl.result = + simple_sd_ioctl_get_partition_size(&msdc_ctl); + break; + default: + pr_err("simple_sd_ioctl:invlalid opcode!!\n"); + return -EINVAL; + } + + if (copy_to_user((struct msdc_ioctl *)arg, &msdc_ctl, + sizeof(struct msdc_ioctl))) { + return -EFAULT; + } + + return msdc_ctl.result; +} + +#ifdef CONFIG_COMPAT + +struct compat_simple_sd_ioctl { + compat_int_t opcode; + compat_int_t host_num; + compat_int_t iswrite; + compat_int_t trans_type; + compat_uint_t total_size; + compat_uint_t address; + compat_uptr_t buffer; + compat_int_t cmd_pu_driving; + compat_int_t cmd_pd_driving; + compat_int_t dat_pu_driving; + compat_int_t dat_pd_driving; + compat_int_t clk_pu_driving; + compat_int_t clk_pd_driving; + compat_int_t ds_pu_driving; + compat_int_t ds_pd_driving; + compat_int_t rst_pu_driving; + compat_int_t rst_pd_driving; + compat_int_t clock_freq; + compat_int_t partition; + compat_int_t hopping_bit; + compat_int_t hopping_time; + compat_int_t result; + compat_int_t sd30_mode; + compat_int_t sd30_max_current; + compat_int_t sd30_drive; + compat_int_t sd30_power_control; +}; + +static int compat_get_simple_ion_allocation( + struct compat_simple_sd_ioctl __user *arg32, + struct msdc_ioctl __user *arg64) +{ + compat_int_t i; + compat_uint_t u; + compat_uptr_t p; + int err; + + err = get_user(i, &(arg32->opcode)); + err |= put_user(i, &(arg64->opcode)); + err |= get_user(i, &(arg32->host_num)); + err |= put_user(i, &(arg64->host_num)); + err |= get_user(i, &(arg32->iswrite)); + err |= put_user(i, &(arg64->iswrite)); + err |= get_user(i, &(arg32->trans_type)); + err |= put_user(i, &(arg64->trans_type)); + err |= get_user(u, &(arg32->total_size)); + err |= put_user(u, &(arg64->total_size)); + err |= get_user(u, &(arg32->address)); + err |= put_user(u, &(arg64->address)); + err |= get_user(p, &(arg32->buffer)); + err |= put_user(compat_ptr(p), &(arg64->buffer)); + err |= get_user(i, &(arg32->cmd_pu_driving)); + err |= put_user(i, &(arg64->cmd_pu_driving)); + err |= get_user(i, &(arg32->cmd_pd_driving)); + err |= put_user(i, &(arg64->cmd_pd_driving)); + err |= get_user(i, &(arg32->dat_pu_driving)); + err |= put_user(i, &(arg64->dat_pu_driving)); + err |= get_user(i, &(arg32->dat_pd_driving)); + err |= put_user(i, &(arg64->dat_pd_driving)); + err |= get_user(i, &(arg32->clk_pu_driving)); + err |= put_user(i, &(arg64->clk_pu_driving)); + err |= get_user(i, &(arg32->clk_pd_driving)); + err |= put_user(i, &(arg64->clk_pd_driving)); + err |= get_user(i, &(arg32->ds_pu_driving)); + err |= put_user(i, &(arg64->ds_pu_driving)); + err |= get_user(i, &(arg32->ds_pd_driving)); + err |= put_user(i, &(arg64->ds_pd_driving)); + err |= get_user(i, &(arg32->rst_pu_driving)); + err |= put_user(i, &(arg64->rst_pu_driving)); + err |= get_user(i, &(arg32->rst_pd_driving)); + err |= put_user(i, &(arg64->rst_pd_driving)); + err |= get_user(i, &(arg32->clock_freq)); + err |= put_user(i, &(arg64->clock_freq)); + err |= get_user(i, &(arg32->partition)); + err |= put_user(i, &(arg64->partition)); + err |= get_user(i, &(arg32->hopping_bit)); + err |= put_user(i, &(arg64->hopping_bit)); + err |= get_user(i, &(arg32->hopping_time)); + err |= put_user(i, &(arg64->hopping_time)); + err |= get_user(i, &(arg32->result)); + err |= put_user(i, &(arg64->result)); + err |= get_user(i, &(arg32->sd30_mode)); + err |= put_user(i, &(arg64->sd30_mode)); + err |= get_user(i, &(arg32->sd30_max_current)); + err |= put_user(i, &(arg64->sd30_max_current)); + err |= get_user(i, &(arg32->sd30_drive)); + err |= put_user(i, &(arg64->sd30_drive)); + err |= get_user(i, &(arg32->sd30_power_control)); + err |= put_user(i, &(arg64->sd30_power_control)); + + return err; +} + +static int compat_put_simple_ion_allocation( + struct compat_simple_sd_ioctl __user *arg32, + struct msdc_ioctl __user *arg64) +{ + compat_int_t i; + compat_uint_t u; + int err; + + err = get_user(i, &(arg64->opcode)); + err |= put_user(i, &(arg32->opcode)); + err |= get_user(i, &(arg64->host_num)); + err |= put_user(i, &(arg32->host_num)); + err |= get_user(i, &(arg64->iswrite)); + err |= put_user(i, &(arg32->iswrite)); + err |= get_user(i, &(arg64->trans_type)); + err |= put_user(i, &(arg32->trans_type)); + err |= get_user(u, &(arg64->total_size)); + err |= put_user(u, &(arg32->total_size)); + err |= get_user(u, &(arg64->address)); + err |= put_user(u, &(arg32->address)); + err |= get_user(i, &(arg64->cmd_pu_driving)); + err |= put_user(i, &(arg32->cmd_pu_driving)); + err |= get_user(i, &(arg64->cmd_pd_driving)); + err |= put_user(i, &(arg32->cmd_pd_driving)); + err |= get_user(i, &(arg64->dat_pu_driving)); + err |= put_user(i, &(arg32->dat_pu_driving)); + err |= get_user(i, &(arg64->dat_pd_driving)); + err |= put_user(i, &(arg32->dat_pd_driving)); + err |= get_user(i, &(arg64->clk_pu_driving)); + err |= put_user(i, &(arg32->clk_pu_driving)); + err |= get_user(i, &(arg64->clk_pd_driving)); + err |= put_user(i, &(arg32->clk_pd_driving)); + err |= get_user(i, &(arg64->ds_pu_driving)); + err |= put_user(i, &(arg32->ds_pu_driving)); + err |= get_user(i, &(arg64->ds_pd_driving)); + err |= put_user(i, &(arg32->ds_pd_driving)); + err |= get_user(i, &(arg64->rst_pu_driving)); + err |= put_user(i, &(arg32->rst_pu_driving)); + err |= get_user(i, &(arg64->rst_pd_driving)); + err |= put_user(i, &(arg32->rst_pd_driving)); + err |= get_user(i, &(arg64->clock_freq)); + err |= put_user(i, &(arg32->clock_freq)); + err |= get_user(i, &(arg64->partition)); + err |= put_user(i, &(arg32->partition)); + err |= get_user(i, &(arg64->hopping_bit)); + err |= put_user(i, &(arg32->hopping_bit)); + err |= get_user(i, &(arg64->hopping_time)); + err |= put_user(i, &(arg32->hopping_time)); + err |= get_user(i, &(arg64->result)); + err |= put_user(i, &(arg32->result)); + err |= get_user(i, &(arg64->sd30_mode)); + err |= put_user(i, &(arg32->sd30_mode)); + err |= get_user(i, &(arg64->sd30_max_current)); + err |= put_user(i, &(arg32->sd30_max_current)); + err |= get_user(i, &(arg64->sd30_drive)); + err |= put_user(i, &(arg32->sd30_drive)); + err |= get_user(i, &(arg64->sd30_power_control)); + err |= put_user(i, &(arg32->sd30_power_control)); + + return err; +} + + +static long simple_sd_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct compat_simple_sd_ioctl *arg32; + struct msdc_ioctl *arg64; + int err, ret; + + if (!file->f_op || !file->f_op->unlocked_ioctl) { + pr_err("f_op or unlocked ioctl is NULL.\n"); + return -ENOTTY; + } + + if ((struct msdc_ioctl *)arg == NULL) { + ret = file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg); + return ret; + } + + arg32 = compat_ptr(arg); + arg64 = compat_alloc_user_space(sizeof(*arg64)); + if (arg64 == NULL) + return -EFAULT; + + err = compat_get_simple_ion_allocation(arg32, arg64); + if (err) + return err; + + ret = file->f_op->unlocked_ioctl(file, arg64->opcode, + (unsigned long)arg64); + + err = compat_put_simple_ion_allocation(arg32, arg64); + + return ret ? ret : err; +} + +#endif + +static const struct file_operations simple_msdc_em_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = simple_sd_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = simple_sd_compat_ioctl, +#endif + .open = simple_sd_open, +}; + +static struct miscdevice simple_msdc_em_dev[] = { + { + .minor = MISC_DYNAMIC_MINOR, + .name = "misc-sd", + .fops = &simple_msdc_em_fops, + } +}; + +static int simple_sd_probe(struct platform_device *pdev) +{ + int ret = 0; + + pr_debug("in misc_sd_probe function\n"); + + return ret; +} + +static int simple_sd_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver simple_sd_driver = { + .probe = simple_sd_probe, + .remove = simple_sd_remove, + + .driver = { + .name = DRV_NAME_MISC, + .owner = THIS_MODULE, + }, +}; + +static int __init simple_sd_init(void) +{ + int ret; + + sg_msdc_multi_buffer = kmalloc(64 * 1024, GFP_KERNEL); + if (sg_msdc_multi_buffer == NULL) + return 0; + + ret = platform_driver_register(&simple_sd_driver); + if (ret) { + pr_err(DRV_NAME_MISC ": Can't register driver\n"); + return ret; + } + pr_debug(DRV_NAME_MISC ": MediaTek simple SD/MMC Card Driver\n"); + + /*msdc0 is for emmc only, just for emmc */ + /* ret = misc_register(&simple_msdc_em_dev[host->id]); */ + ret = misc_register(&simple_msdc_em_dev[0]); + if (ret) { + pr_err("register MSDC Slot[0] misc driver failed (%d)\n", ret); + return ret; + } + + return 0; +} + +static void __exit simple_sd_exit(void) +{ + if (sg_msdc_multi_buffer != NULL) { + kfree(sg_msdc_multi_buffer); + sg_msdc_multi_buffer = NULL; + } + + misc_deregister(&simple_msdc_em_dev[0]); + + platform_driver_unregister(&simple_sd_driver); +} + +module_init(simple_sd_init); +module_exit(simple_sd_exit); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("simple MediaTek SD/MMC Card Driver"); +MODULE_AUTHOR("feifei.wang "); diff --git a/drivers/mmc/host/mediatek/mt6755/sd.c b/drivers/mmc/host/mediatek/mt6755/sd.c new file mode 100644 index 0000000000000000000000000000000000000000..edbc1796288e42e9126da0a34fa2a8f0854a258e --- /dev/null +++ b/drivers/mmc/host/mediatek/mt6755/sd.c @@ -0,0 +1,6265 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mt_sd.h" +#include +#include + +#ifdef CONFIG_MMC_FFU +#include +#endif + +#ifdef MTK_MSDC_BRINGUP_DEBUG +#include +#endif + +#ifdef CONFIG_MTK_AEE_FEATURE +#include +#endif + +#ifdef CONFIG_MTK_HIBERNATION +#include +#endif + +#ifdef CONFIG_PWR_LOSS_MTK_TEST +#include +#else +#define MVG_EMMC_CHECK_BUSY_AND_RESET(...) +#define MVG_EMMC_SETUP(...) +#define MVG_EMMC_RESET(...) +#define MVG_EMMC_WRITE_MATCH(...) +#define MVG_EMMC_ERASE_MATCH(...) +#define MVG_EMMC_ERASE_RESET(...) +#define MVG_EMMC_DECLARE_INT32(...) +#endif + +#include "dbg.h" +#include "msdc_tune.h" +#include "autok.h" +#include "autok_dvfs.h" + +#define CAPACITY_2G (2 * 1024 * 1024 * 1024ULL) + +u32 g_emmc_mode_switch; /*Check if its reference in sd_misc.h can be removed */ + + +#define MSDC_MAX_FLUSH_COUNT (3) +#define CACHE_UN_FLUSHED (0) +#define CACHE_FLUSHED (1) +#ifdef MTK_MSDC_USE_CACHE +static unsigned int g_cache_status = CACHE_UN_FLUSHED; +#endif +static unsigned long long g_flush_data_size; +static unsigned int g_flush_error_count; +static int g_flush_error_happend; + +/* if disable cache by vendor fill CID.MID to g_emmc_cache_quirk[i] */ +unsigned char g_emmc_cache_quirk[256]; +#define CID_MANFID_SANDISK 0x2 +#define CID_MANFID_TOSHIBA 0x11 +#define CID_MANFID_MICRON 0x13 +#define CID_MANFID_SAMSUNG 0x15 +#define CID_MANFID_SANDISK_NEW 0x45 +#define CID_MANFID_HYNIX 0x90 +#define CID_MANFID_KSI 0x70 + +#if (MSDC_DATA1_INT == 1) +static u16 u_sdio_irq_counter; +static u16 u_msdc_irq_counter; +/*static int int_sdio_irq_enable;*/ +#endif + +struct msdc_host *ghost; +int src_clk_control; + +bool emmc_sleep_failed; +static struct workqueue_struct *wq_init; + +#ifdef MSDC_WQ_ERROR_TUNE +static struct workqueue_struct *wq_tune; +#endif + +bool sdio_lock_dvfs; + +#define DRV_NAME "mtk-msdc" + +#define MSDC_COOKIE_PIO (1<<0) +#define MSDC_COOKIE_ASYNC (1<<1) + +#define msdc_use_async(x) (x & MSDC_COOKIE_ASYNC) +#define msdc_use_async_dma(x) (msdc_use_async(x) && (!(x & MSDC_COOKIE_PIO))) +#define msdc_use_async_pio(x) (msdc_use_async(x) && ((x & MSDC_COOKIE_PIO))) + +#define HOST_MAX_BLKSZ (2048) + +#define MSDC_OCR_AVAIL (MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_30_31 \ + | MMC_VDD_31_32 | MMC_VDD_32_33) + +#define DEFAULT_DTOC (3) /* data timeout counter. + 1048576 * 3 sclk. */ + +#define MAX_DMA_CNT (64 * 1024 - 512) + /* a WIFI transaction may be 50K */ +#define MAX_DMA_CNT_SDIO (0xFFFFFFFF - 255) + /* a LTE transaction may be 128K */ + +#define MAX_HW_SGMTS (MAX_BD_NUM) +#define MAX_PHY_SGMTS (MAX_BD_NUM) +#define MAX_SGMT_SZ (MAX_DMA_CNT) +#define MAX_SGMT_SZ_SDIO (MAX_DMA_CNT_SDIO) + +u8 g_emmc_id; +unsigned int cd_gpio = 0; + +struct msdc_host *mtk_msdc_host[] = { NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(mtk_msdc_host); + +int g_dma_debug[HOST_MAX_NUM] = { 0, 0, 0, 0}; +u32 latest_int_status[HOST_MAX_NUM] = { 0, 0, 0, 0}; + +unsigned int msdc_latest_transfer_mode[HOST_MAX_NUM] = { + /* 0 for PIO; 1 for DMA; 2 for nothing */ + TRAN_MOD_NUM, + TRAN_MOD_NUM, + TRAN_MOD_NUM, + TRAN_MOD_NUM, +}; + +unsigned int msdc_latest_op[HOST_MAX_NUM] = { + /* 0 for read; 1 for write; 2 for nothing */ + OPER_TYPE_NUM, + OPER_TYPE_NUM, + OPER_TYPE_NUM, + OPER_TYPE_NUM, +}; + +/* for debug zone */ +unsigned int sd_debug_zone[HOST_MAX_NUM] = { + 0, + 0, + 0, + 0, +}; + +/* for enable/disable register dump */ +unsigned int sd_register_zone[HOST_MAX_NUM] = { + 1, + 1, + 1, + 1, +}; + +/* mode select */ +u32 dma_size[HOST_MAX_NUM] = { + 512, + 8, + 512, + 512, +}; + +u32 drv_mode[HOST_MAX_NUM] = { + MODE_SIZE_DEP, /* using DMA or not depend on the size */ + MODE_SIZE_DEP, + MODE_SIZE_DEP, + MODE_SIZE_DEP, +}; + +u8 msdc_clock_src[HOST_MAX_NUM] = { + 0, + 0, + 0, + 0, +}; + +u32 msdc_host_mode[HOST_MAX_NUM] = { + 0, + 0, + 0, + 0, +}; + +u32 msdc_host_mode2[HOST_MAX_NUM] = { + 0, + 0, + 0, + 0, +}; + +int msdc_rsp[] = { + 0, /* RESP_NONE */ + 1, /* RESP_R1 */ + 2, /* RESP_R2 */ + 3, /* RESP_R3 */ + 4, /* RESP_R4 */ + 1, /* RESP_R5 */ + 1, /* RESP_R6 */ + 1, /* RESP_R7 */ + 7, /* RESP_R1b */ +}; + +/* For Inhanced DMA */ +#define msdc_init_gpd_ex(gpd, extlen, cmd, arg, blknum) \ + do { \ + ((struct gpd_t *)gpd)->extlen = extlen; \ + ((struct gpd_t *)gpd)->cmd = cmd; \ + ((struct gpd_t *)gpd)->arg = arg; \ + ((struct gpd_t *)gpd)->blknum = blknum; \ + } while (0) + +#define msdc_init_bd(bd, blkpad, dwpad, dptr, dlen) \ + do { \ + BUG_ON(dlen > 0xFFFFFFUL); \ + ((struct bd_t *)bd)->blkpad = blkpad; \ + ((struct bd_t *)bd)->dwpad = dwpad; \ + ((struct bd_t *)bd)->ptr = (u32)dptr; \ + ((struct bd_t *)bd)->buflen = dlen; \ + } while (0) + +#ifdef CONFIG_NEED_SG_DMA_LENGTH +#define msdc_sg_len(sg, dma) ((dma) ? (sg)->dma_length : (sg)->length) +#else +#define msdc_sg_len(sg, dma) sg_dma_len(sg) +#endif + +#define msdc_dma_on() MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_PIO) +#define msdc_dma_off() MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_PIO) +#define msdc_dma_status() ((MSDC_READ32(MSDC_CFG) & MSDC_CFG_PIO) >> 3) + +#define pr_reg(OFFSET, VAL) \ + pr_err("%d R[%x]=0x%.8x", id, OFFSET, VAL) + +static u16 msdc_offsets[] = { + OFFSET_MSDC_CFG, + OFFSET_MSDC_IOCON, + OFFSET_MSDC_PS, + OFFSET_MSDC_INT, + OFFSET_MSDC_INTEN, + OFFSET_MSDC_FIFOCS, + OFFSET_SDC_CFG, + OFFSET_SDC_CMD, + OFFSET_SDC_ARG, + OFFSET_SDC_STS, + OFFSET_SDC_RESP0, + OFFSET_SDC_RESP1, + OFFSET_SDC_RESP2, + OFFSET_SDC_RESP3, + OFFSET_SDC_BLK_NUM, + OFFSET_SDC_VOL_CHG, + OFFSET_SDC_CSTS, + OFFSET_SDC_CSTS_EN, + OFFSET_SDC_DCRC_STS, + OFFSET_EMMC_CFG0, + OFFSET_EMMC_CFG1, + OFFSET_EMMC_STS, + OFFSET_EMMC_IOCON, + OFFSET_SDC_ACMD_RESP, + OFFSET_SDC_ACMD19_TRG, + OFFSET_SDC_ACMD19_STS, + OFFSET_MSDC_DMA_SA_HIGH, + OFFSET_MSDC_DMA_SA, + OFFSET_MSDC_DMA_CA, + OFFSET_MSDC_DMA_CTRL, + OFFSET_MSDC_DMA_CFG, + OFFSET_MSDC_DMA_LEN, + OFFSET_MSDC_DBG_SEL, + OFFSET_MSDC_DBG_OUT, + OFFSET_MSDC_PATCH_BIT0, + OFFSET_MSDC_PATCH_BIT1, + OFFSET_MSDC_PATCH_BIT2, + + OFFSET_DAT0_TUNE_CRC, + OFFSET_DAT0_TUNE_CRC, + OFFSET_DAT0_TUNE_CRC, + OFFSET_DAT0_TUNE_CRC, + OFFSET_CMD_TUNE_CRC, + OFFSET_SDIO_TUNE_WIND, + + OFFSET_MSDC_PAD_TUNE0, + OFFSET_MSDC_PAD_TUNE1, + OFFSET_MSDC_DAT_RDDLY0, + OFFSET_MSDC_DAT_RDDLY1, + OFFSET_MSDC_DAT_RDDLY2, + OFFSET_MSDC_DAT_RDDLY3, + OFFSET_MSDC_HW_DBG, + OFFSET_MSDC_VERSION, + + OFFSET_EMMC50_PAD_DS_TUNE, + OFFSET_EMMC50_PAD_CMD_TUNE, + OFFSET_EMMC50_PAD_DAT01_TUNE, + OFFSET_EMMC50_PAD_DAT23_TUNE, + OFFSET_EMMC50_PAD_DAT45_TUNE, + OFFSET_EMMC50_PAD_DAT67_TUNE, + OFFSET_EMMC51_CFG0, + OFFSET_EMMC50_CFG0, + OFFSET_EMMC50_CFG1, + OFFSET_EMMC50_CFG2, + OFFSET_EMMC50_CFG3, + OFFSET_EMMC50_CFG4 +}; + +void msdc_dump_register_core(u32 id, void __iomem *base) +{ + u16 i; + + for (i = 0; i < sizeof(msdc_offsets)/sizeof(msdc_offsets[0]); i++) { + + if (((id != 2) && (id != 3)) + && (msdc_offsets[i] >= OFFSET_DAT0_TUNE_CRC) + && (msdc_offsets[i] <= OFFSET_SDIO_TUNE_WIND)) + continue; + + if ((id != 0) + && (msdc_offsets[i] >= OFFSET_EMMC50_PAD_DS_TUNE)) + break; + + pr_reg(msdc_offsets[i], MSDC_READ32(base + msdc_offsets[i])); + } + + return; +} + +void msdc_dump_register(struct msdc_host *host) +{ + void __iomem *base = host->base; + + msdc_dump_register_core(host->id, base); +} + +void msdc_dump_dbg_register_core(u32 id, void __iomem *base) +{ + u32 i; + + for (i = 0; i <= 0x27; i++) { + MSDC_WRITE32(MSDC_DBG_SEL, i); + SIMPLE_INIT_MSG("SEL:r[%x]=0x%x", OFFSET_MSDC_DBG_SEL, i); + SIMPLE_INIT_MSG("OUT:r[%x]=0x%x", OFFSET_MSDC_DBG_OUT, + MSDC_READ32(MSDC_DBG_OUT)); + } + + MSDC_WRITE32(MSDC_DBG_SEL, 0); +} + +static void msdc_dump_dbg_register(struct msdc_host *host) +{ + void __iomem *base = host->base; + + msdc_dump_dbg_register_core(host->id, base); +} + +void msdc_dump_info(u32 id) +{ + struct msdc_host *host = mtk_msdc_host[id]; + void __iomem *base; + + if (host == NULL) { + pr_err("msdc host<%d> null\r\n", id); + return; + } + + if (host->async_tuning_in_progress || host->legacy_tuning_in_progress) + return; + + /* when detect card, cmd13 will be sent which timeout log is not needed */ + if (!sd_register_zone[id]) { + pr_err("msdc host<%d> is timeout when detect, so don't dump register\n", id); + return; + } + + host->prev_cmd_cause_dump++; + if (host->prev_cmd_cause_dump > 1) + return; + + base = host->base; + + /* 1: dump msdc hw register */ + msdc_dump_register(host); + INIT_MSG("latest_INT_status<0x%.8x>", latest_int_status[id]); + + /* 2: check msdc clock gate and clock source */ + mdelay(10); + msdc_dump_clock_sts(); + + /* 3: check msdc pmic ldo */ + msdc_dump_ldo_sts(host); + + /* 4: check msdc pad control */ + msdc_dump_padctl(host); + + /* 5: For designer */ + mdelay(10); + msdc_dump_dbg_register(host); +} + +/* + * for AHB read / write debug + * return DMA status. + */ +int msdc_get_dma_status(int host_id) +{ + int result = -1; + + if (host_id < 0 || host_id >= HOST_MAX_NUM) { + pr_err("[%s] failed to get dma status, invalid host_id %d\n", + __func__, host_id); + } else if (msdc_latest_transfer_mode[host_id] == TRAN_MOD_DMA) { + if (msdc_latest_op[host_id] == OPER_TYPE_READ) + return 1; /* DMA read */ + else if (msdc_latest_op[host_id] == OPER_TYPE_WRITE) + return 2; /* DMA write */ + } else if (msdc_latest_transfer_mode[host_id] == TRAN_MOD_PIO) { + return 0; /* PIO mode */ + } + + return result; +} +EXPORT_SYMBOL(msdc_get_dma_status); + +void msdc_clr_fifo(unsigned int id) +{ + int retry = 3, cnt = 1000; + void __iomem *base; + + if (id < 0 || id >= HOST_MAX_NUM) + return; + base = mtk_msdc_host[id]->base; + + if (MSDC_READ32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS) { + pr_err("<<>>: msdc%d, clear FIFO when DMA active, MSDC_DMA_CFG=0x%x\n", + id, MSDC_READ32(MSDC_DMA_CFG)); + show_stack(current, NULL); + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); + msdc_retry((MSDC_READ32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS), + retry, cnt, id); + if (retry == 0) { + pr_err("<<>>: msdc%d, faield to stop DMA before clear FIFO, MSDC_DMA_CFG=0x%x\n", + id, MSDC_READ32(MSDC_DMA_CFG)); + return; + } + } + + retry = 3; + cnt = 1000; + MSDC_SET_BIT32(MSDC_FIFOCS, MSDC_FIFOCS_CLR); + msdc_retry(MSDC_READ32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, retry, cnt, id); +} + +int msdc_clk_stable(struct msdc_host *host, u32 mode, u32 div, + u32 hs400_div_dis) +{ + void __iomem *base = host->base; + int retry = 0; + int cnt = 1000; + int retry_cnt = 1; + +#if defined(CFG_DEV_MSDC3) + /*FIXME: check function instead of host->id*/ + /*MSDC3 is dedicated for C2K, need special clock setting*/ + if (host->id == 3) { + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKDIV, 0); + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, 1); + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_SDR104CKS, 1); + return 0; + } +#endif + + do { + retry = 3; + MSDC_SET_FIELD(MSDC_CFG, + MSDC_CFG_CKMOD_HS400 | MSDC_CFG_CKMOD | MSDC_CFG_CKDIV, + (hs400_div_dis << 14) | (mode << 12) | + ((div + retry_cnt) % 0xfff)); + /* MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, mode); */ + msdc_retry(!(MSDC_READ32(MSDC_CFG) & MSDC_CFG_CKSTB), retry, + cnt, host->id); + if (retry == 0) { + pr_err("msdc%d host->onclock(%d)\n", host->id, + host->core_clkon); + + pr_err("msdc%d on clock failed ===> retry twice\n", + host->id); + + msdc_clk_disable(host); + (void)msdc_clk_enable(host); + + msdc_dump_info(host->id); + host->prev_cmd_cause_dump = 0; + } + retry = 3; + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_CKDIV, div); + msdc_retry(!(MSDC_READ32(MSDC_CFG) & MSDC_CFG_CKSTB), retry, + cnt, host->id); + msdc_reset_hw(host->id); + if (retry_cnt == 2) + break; + retry_cnt++; + } while (!retry); + + return 0; +} + +#define msdc_irq_save(val) \ + do { \ + val = MSDC_READ32(MSDC_INTEN); \ + MSDC_CLR_BIT32(MSDC_INTEN, val); \ + } while (0) + +#define msdc_irq_restore(val) \ + MSDC_SET_BIT32(MSDC_INTEN, val) \ + +/* set the edge of data sampling */ +void msdc_set_smpl(struct msdc_host *host, u32 clock_mode, u8 mode, u8 type, u8 *edge) +{ + void __iomem *base = host->base; + int i = 0; + + switch (type) { + case TYPE_CMD_RESP_EDGE: + if (clock_mode == 3) { + MSDC_SET_FIELD(EMMC50_CFG0, + MSDC_EMMC50_CFG_PADCMD_LATCHCK, 0); + MSDC_SET_FIELD(EMMC50_CFG0, + MSDC_EMMC50_CFG_CMD_RESP_SEL, 0); + } + + if (mode == MSDC_SMPL_RISING || mode == MSDC_SMPL_FALLING) { + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, mode); + } else { + ERR_MSG("invalid resp parameter: type=%d, mode=%d\n", + type, mode); + } + break; + case TYPE_WRITE_CRC_EDGE: + if (clock_mode == 3) { + /*latch write crc status at DS pin*/ + MSDC_SET_FIELD(EMMC50_CFG0, + MSDC_EMMC50_CFG_CRC_STS_SEL, 1); + } else { + /*latch write crc status at CLK pin*/ + MSDC_SET_FIELD(EMMC50_CFG0, + MSDC_EMMC50_CFG_CRC_STS_SEL, 0); + } + + if (mode == MSDC_SMPL_RISING || mode == MSDC_SMPL_FALLING) { + if (clock_mode == 3) { + MSDC_SET_FIELD(EMMC50_CFG0, + MSDC_EMMC50_CFG_CRC_STS_EDGE, mode); + } else { + MSDC_SET_FIELD(MSDC_PATCH_BIT2, + MSDC_PB2_CFGCRCSTSEDGE, mode); + } + } else if ((mode == MSDC_SMPL_SEPARATE) && + (edge != NULL) && + (sizeof(edge) == 8)) { + pr_err("Shall not enter here\n"); + + } else { + ERR_MSG("invalid crc parameter: type=%d, mode=%d\n", + type, mode); + } + + break; + + case TYPE_READ_DATA_EDGE: + if (clock_mode == 3) { + /*for HS400, start bit is output on both edge*/ + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_START_BIT, + START_AT_RISING_AND_FALLING); + } else { + /*for the other modes, start bit is only output on + rising edge; but DDR50 can try falling edge + if error casued by pad delay*/ + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_START_BIT, + START_AT_RISING); + } + if (clock_mode == 2) + mode = 0; + + if (mode == MSDC_SMPL_RISING || mode == MSDC_SMPL_FALLING) { + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_R_D_SMPL_SEL, 0); + MSDC_SET_FIELD(MSDC_PATCH_BIT0, + MSDC_PB0_RD_DAT_SEL, mode); + } else if ((mode == MSDC_SMPL_SEPARATE) && + (edge != NULL) && + (sizeof(edge) == 8)) { + pr_err("Shall not enter here\n"); + } else { + ERR_MSG("invalid read parameter: type=%d, mode=%d\n", + type, mode); + } + + break; + + case TYPE_WRITE_DATA_EDGE: + /*latch write crc status at CLK pin*/ + MSDC_SET_FIELD(EMMC50_CFG0, MSDC_EMMC50_CFG_CRC_STS_SEL, 0); + + if (mode == MSDC_SMPL_RISING || mode == MSDC_SMPL_FALLING) { + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL_SEL, 0); + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL, mode); + } else if ((mode == MSDC_SMPL_SEPARATE) && + (edge != NULL) && + (sizeof(edge) >= 4)) { + MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL_SEL, 1); + for (i = 0; i < 4; i++) { + /*dat0~4 is for SDIO card*/ + MSDC_SET_FIELD(MSDC_IOCON, + (MSDC_IOCON_W_D0SPL << i), edge[i]); + } + } else { + ERR_MSG("invalid write parameter: type=%d, mode=%d\n", + type, mode); + } + break; + default: + ERR_MSG("invalid parameter: type=%d, mode=%d\n", type, mode); + break; + } + /*pr_err("finished, HS400=%d, type=%d, mode=%d\n", HS400, type, mode);*/ + +} + +void msdc_set_smpl_all(struct msdc_host *host, u32 clock_mode) +{ + struct msdc_hw *hw = host->hw; + + msdc_set_smpl(host, clock_mode, hw->cmd_edge, TYPE_CMD_RESP_EDGE, + NULL); + msdc_set_smpl(host, clock_mode, hw->rdata_edge, TYPE_READ_DATA_EDGE, + NULL); + msdc_set_smpl(host, clock_mode, hw->wdata_edge, TYPE_WRITE_CRC_EDGE, + NULL); +} + +/*sd card change voltage wait time= (1/freq) * SDC_VOL_CHG_CNT(default 0x145)*/ +#define msdc_set_vol_change_wait_count(count) \ + MSDC_SET_FIELD(SDC_VOL_CHG, SDC_VOL_CHG_CNT, (count)) + +static void msdc_clksrc_onoff(struct msdc_host *host, u32 on) +{ + void __iomem *base = host->base; + u32 div, mode, hs400_div_dis; + + if ((on) && (0 == host->core_clkon)) { + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* + msdc_power_DL_CL_control(host, MSDC_POWER_DL_CL_FOR_HAS_LOAD); + */ + #endif + + (void)msdc_clk_enable(host); + + host->core_clkon = 1; + udelay(10); + + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); + + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, mode); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKDIV, div); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD_HS400, hs400_div_dis); + msdc_clk_stable(host, mode, div, hs400_div_dis); + + } else if ((!on) + && (!((host->hw->flags & MSDC_SDIO_IRQ) && src_clk_control))) { + if (host->core_clkon == 1) { + + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_MODE, MSDC_MS); + + msdc_clk_disable(host); + + host->core_clkon = 0; + + #if defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /* Bug: We cannot know if device is performning internal + operation */ + /* + msdc_power_DL_CL_control(host, + MSDC_POWER_DL_CL_FOR_NO_LOAD); + */ + #endif + } + } +} + +/*host doesn't need the clock on*/ +void msdc_gate_clock(struct msdc_host *host, int delay) +{ + unsigned long flags; + unsigned int suspend; + + /*Use delay<0 for suspend purpose*/ + if (delay < 0) { + suspend = 1; + delay = 0; + } else { + suspend = 0; + } + + spin_lock_irqsave(&host->clk_gate_lock, flags); + if ((suspend == 0) && (host->clk_gate_count > 0)) + host->clk_gate_count--; + if (delay) { + mod_timer(&host->timer, jiffies + CLK_TIMEOUT); + N_MSG(CLK, "[%s]: msdc%d, clk_gate_count=%d, delay=%d", + __func__, host->id, host->clk_gate_count, delay); + } else if (host->clk_gate_count == 0) { + del_timer(&host->timer); + msdc_clksrc_onoff(host, 0); + N_MSG(CLK, "[%s]: msdc%d, clock gated done", + __func__, host->id); + } else { + if (is_card_sdio(host)) + host->error = -EBUSY; + ERR_MSG("[%s]: msdc%d, clock is needed, clk_gate_count=%d", + __func__, host->id, host->clk_gate_count); + } + spin_unlock_irqrestore(&host->clk_gate_lock, flags); +} + +/* host does need the clock on */ +void msdc_ungate_clock(struct msdc_host *host) +{ + unsigned long flags; + + spin_lock_irqsave(&host->clk_gate_lock, flags); + host->clk_gate_count++; + N_MSG(CLK, "[%s]: msdc%d, clk_gate_count=%d", __func__, host->id, + host->clk_gate_count); + if (host->clk_gate_count == 1) + msdc_clksrc_onoff(host, 1); + spin_unlock_irqrestore(&host->clk_gate_lock, flags); +} + +#if 0 +static void msdc_dump_card_status(struct msdc_host *host, u32 status) +{ + static const char const *state[] = { + "Idle", /* 0 */ + "Ready", /* 1 */ + "Ident", /* 2 */ + "Stby", /* 3 */ + "Tran", /* 4 */ + "Data", /* 5 */ + "Rcv", /* 6 */ + "Prg", /* 7 */ + "Dis", /* 8 */ + "Reserved", /* 9 */ + "Reserved", /* 10 */ + "Reserved", /* 11 */ + "Reserved", /* 12 */ + "Reserved", /* 13 */ + "Reserved", /* 14 */ + "I/O mode", /* 15 */ + }; + if (status & R1_OUT_OF_RANGE) + N_MSG(RSP, "[CARD_STATUS] Out of Range"); + if (status & R1_ADDRESS_ERROR) + N_MSG(RSP, "[CARD_STATUS] Address Error"); + if (status & R1_BLOCK_LEN_ERROR) + N_MSG(RSP, "[CARD_STATUS] Block Len Error"); + if (status & R1_ERASE_SEQ_ERROR) + N_MSG(RSP, "[CARD_STATUS] Erase Seq Error"); + if (status & R1_ERASE_PARAM) + N_MSG(RSP, "[CARD_STATUS] Erase Param"); + if (status & R1_WP_VIOLATION) + N_MSG(RSP, "[CARD_STATUS] WP Violation"); + if (status & R1_CARD_IS_LOCKED) + N_MSG(RSP, "[CARD_STATUS] Card is Locked"); + if (status & R1_LOCK_UNLOCK_FAILED) + N_MSG(RSP, "[CARD_STATUS] Lock/Unlock Failed"); + if (status & R1_COM_CRC_ERROR) + N_MSG(RSP, "[CARD_STATUS] Command CRC Error"); + if (status & R1_ILLEGAL_COMMAND) + N_MSG(RSP, "[CARD_STATUS] Illegal Command"); + if (status & R1_CARD_ECC_FAILED) + N_MSG(RSP, "[CARD_STATUS] Card ECC Failed"); + if (status & R1_CC_ERROR) + N_MSG(RSP, "[CARD_STATUS] CC Error"); + if (status & R1_ERROR) + N_MSG(RSP, "[CARD_STATUS] Error"); + if (status & R1_UNDERRUN) + N_MSG(RSP, "[CARD_STATUS] Underrun"); + if (status & R1_OVERRUN) + N_MSG(RSP, "[CARD_STATUS] Overrun"); + if (status & R1_CID_CSD_OVERWRITE) + N_MSG(RSP, "[CARD_STATUS] CID/CSD Overwrite"); + if (status & R1_WP_ERASE_SKIP) + N_MSG(RSP, "[CARD_STATUS] WP Eraser Skip"); + if (status & R1_CARD_ECC_DISABLED) + N_MSG(RSP, "[CARD_STATUS] Card ECC Disabled"); + if (status & R1_ERASE_RESET) + N_MSG(RSP, "[CARD_STATUS] Erase Reset"); + if ((status & R1_READY_FOR_DATA) == 0) + N_MSG(RSP, "[CARD_STATUS] Not Ready for Data"); + if (status & R1_SWITCH_ERROR) + N_MSG(RSP, "[CARD_STATUS] Switch error"); + if (status & R1_APP_CMD) + N_MSG(RSP, "[CARD_STATUS] App Command"); + + N_MSG(RSP, "[CARD_STATUS] '%s' State", state[R1_CURRENT_STATE(status)]); +} +#endif + +static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) +{ + void __iomem *base = host->base; + u32 timeout, clk_ns; + u32 mode = 0; + + host->timeout_ns = ns; + host->timeout_clks = clks; + if (host->sclk == 0) { + timeout = 0; + } else { + clk_ns = 1000000000UL / host->sclk; + timeout = (ns + clk_ns - 1) / clk_ns + clks; + /* in 1048576 sclk cycle unit */ + timeout = (timeout + (1 << 20) - 1) >> 20; + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, mode); + /*DDR mode will double the clk cycles for data timeout*/ + timeout = mode >= 2 ? timeout * 2 : timeout; + timeout = timeout > 1 ? timeout - 1 : 0; + timeout = timeout > 255 ? 255 : timeout; + } + MSDC_SET_FIELD(SDC_CFG, SDC_CFG_DTOC, timeout); + + N_MSG(OPS, "msdc%d, Set read data timeout: %dns %dclks -> %d x 1048576 cycles, mode:%d, clk_freq=%dKHz\n", + host->id, ns, clks, timeout + 1, mode, (host->sclk / 1000)); +} + +/* msdc_eirq_sdio() will be called when EIRQ(for WIFI) */ +static void msdc_eirq_sdio(void *data) +{ + struct msdc_host *host = (struct msdc_host *)data; + + N_MSG(INT, "SDIO EINT"); +#ifdef SDIO_ERROR_BYPASS + if (host->sdio_error != -EILSEQ) { +#endif + mmc_signal_sdio_irq(host->mmc); +#ifdef SDIO_ERROR_BYPASS + } +#endif +} + +volatile int sdio_autok_processed = 0; + +void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) +{ + void __iomem *base = host->base; + u32 mode; + u32 flags; + u32 div; + u32 sclk; + u32 hclk = host->hclk; + u32 hs400_div_dis = 0; /* FOR MSDC_CFG.HS400CKMOD */ + + if (!hz) { /* set mmc system clock to 0*/ + if (is_card_sdio(host) || (host->hw->flags & MSDC_SDIO_IRQ)) { + host->saved_para.hz = hz; +#ifdef SDIO_ERROR_BYPASS + host->sdio_error = 0; +#endif + } + host->mclk = 0; + msdc_reset_hw(host->id); + return; + } + + msdc_irq_save(flags); + + if (timing == MMC_TIMING_MMC_HS400) { + mode = 0x3; /* HS400 mode */ + if (hz >= hclk/2) { + hs400_div_dis = 1; + div = 0; + sclk = hclk/2; + } else { + hs400_div_dis = 0; + if (hz >= (hclk >> 2)) { + div = 0; /* mean div = 1/4 */ + sclk = hclk >> 2; /* sclk = clk / 4 */ + } else { + div = (hclk + ((hz << 2) - 1)) / (hz << 2); + sclk = (hclk >> 2) / div; + div = (div >> 1); + } + } + + } else if ((timing == MMC_TIMING_UHS_DDR50) + || (timing == MMC_TIMING_MMC_DDR52)) { + mode = 0x2; /* ddr mode and use divisor */ + if (hz >= (hclk >> 2)) { + div = 0; /* mean div = 1/4 */ + sclk = hclk >> 2; /* sclk = clk / 4 */ + } else { + div = (hclk + ((hz << 2) - 1)) / (hz << 2); + sclk = (hclk >> 2) / div; + div = (div >> 1); + } +#if !defined(FPGA_PLATFORM) + } else if (hz >= hclk) { + mode = 0x1; /* no divisor */ + div = 0; + sclk = hclk; +#endif + } else { + mode = 0x0; /* use divisor */ + if (hz >= (hclk >> 1)) { + div = 0; /* mean div = 1/2 */ + sclk = hclk >> 1; /* sclk = clk / 2 */ + } else { + div = (hclk + ((hz << 2) - 1)) / (hz << 2); + sclk = (hclk >> 2) / div; + } + } + + msdc_clk_stable(host, mode, div, hs400_div_dis); + + host->sclk = sclk; + host->mclk = hz; + host->timing = timing; + + /* need because clk changed.*/ + msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); + + msdc_set_smpl_all(host, mode); + + pr_err("msdc%d -> !!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz> timing<%d> mode<%d> div<%d> hs400_div_dis<%d>", + host->id, hz/1000, hclk/1000, sclk/1000, (int)timing, mode, div, + hs400_div_dis); + + msdc_irq_restore(flags); +} + +void msdc_send_stop(struct msdc_host *host) +{ + struct mmc_command stop = {0}; + struct mmc_request mrq = {0}; + u32 err; + + stop.opcode = MMC_STOP_TRANSMISSION; + stop.arg = 0; + stop.flags = MMC_RSP_R1B | MMC_CMD_AC; + + mrq.cmd = &stop; + stop.mrq = &mrq; + stop.data = NULL; + + err = msdc_do_command(host, &stop, 0, CMD_TIMEOUT); +} + +static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host) +{ + struct mmc_command cmd = { 0 }; + struct mmc_request mrq = { 0 }; + u32 err; + + cmd.opcode = MMC_APP_CMD; + cmd.arg = host->app_cmd_arg; /* meet mmc->card is null when ACMD6 */ + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + + mrq.cmd = &cmd; + cmd.mrq = &mrq; + cmd.data = NULL; + + err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); + return err; +} + +int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, + u32 *status) +{ + struct mmc_command cmd = { 0 }; + struct mmc_request mrq = { 0 }; + u32 err; + + cmd.opcode = MMC_SEND_STATUS; /* CMD13 */ + cmd.arg = host->app_cmd_arg; + cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; + + mrq.cmd = &cmd; + cmd.mrq = &mrq; + cmd.data = NULL; + + /* tune until CMD13 pass. */ +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (host->mmc->card->ext_csd.cmdq_mode_en) + err = msdc_do_cmdq_command(host, &cmd, 0, CMD_TIMEOUT); + else +#endif + err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); + + if (status) + *status = cmd.resp[0]; + + return err; +} + +#if 0 +static void msdc_remove_card(struct work_struct *work) +{ + struct msdc_host *host = container_of(work, struct msdc_host, + remove_card.work); + + BUG_ON(!host || !host->mmc); + ERR_MSG("Need remove card"); + if (host->mmc->card) { + if (mmc_card_present(host->mmc->card)) { + ERR_MSG("1.remove card"); + mmc_remove_card(host->mmc->card); + } else { + ERR_MSG("card was not present can not remove"); + host->block_bad_card = 0; + host->card_inserted = 1; + host->mmc->card->state &= ~MMC_CARD_REMOVED; + return; + } + mmc_claim_host(host->mmc); + ERR_MSG("2.detach bus"); + host->mmc->card = NULL; + mmc_detach_bus(host->mmc); + ERR_MSG("3.Power off"); + mmc_power_off(host->mmc); + ERR_MSG("4.Gate clock"); + msdc_gate_clock(host, 0); + mmc_release_host(host->mmc); + } + ERR_MSG("Card removed"); +} +#endif + +int msdc_reinit(struct msdc_host *host) +{ + int ret = -1; + u32 err = 0; + u32 status = 0; + unsigned long tmo = 12; + + BUG_ON(!host || !host->mmc || !host->mmc->card); + + if (host->hw->host_function != MSDC_SD) + goto skip_reinit2; + + if (host->block_bad_card) + ERR_MSG("Need block this bad SD card from re-initialization"); + + if (!(host->mmc->caps & MMC_CAP_NONREMOVABLE) || (host->block_bad_card != 0)) + goto skip_reinit1; + + /* power cycle */ + ERR_MSG("SD card Re-Init!"); + mmc_claim_host(host->mmc); + ERR_MSG("SD card Re-Init get host!"); + spin_lock(&host->lock); + ERR_MSG("SD card Re-Init get lock!"); + msdc_clksrc_onoff(host, 1); + if (host->app_cmd_arg) { + while ((err = msdc_get_card_status(host->mmc, host, &status))) { + ERR_MSG("SD card Re-Init in get card status!err(%d)", + err); + if (err == (unsigned int)-EILSEQ) { + if (msdc_tune_cmdrsp(host)) { + ERR_MSG("update cmd para failed"); + break; + } + } else { + break; + } + } + if (err == 0) { + if (status == 0) { + msdc_dump_info(host->id); + } else { + msdc_clksrc_onoff(host, 0); + spin_unlock(&host->lock); + mmc_release_host(host->mmc); + ERR_MSG("SD Card is ready"); + return 0; + } + } + } + msdc_clksrc_onoff(host, 0); + ERR_MSG("Reinit start.."); + host->mmc->ios.clock = HOST_MIN_MCLK; + host->mmc->ios.bus_width = MMC_BUS_WIDTH_1; + host->mmc->ios.timing = MMC_TIMING_LEGACY; + host->card_inserted = 1; + msdc_clksrc_onoff(host, 1); + msdc_set_mclk(host, MMC_TIMING_LEGACY, HOST_MIN_MCLK); + msdc_clksrc_onoff(host, 0); + spin_unlock(&host->lock); + mmc_release_host(host->mmc); + if (host->mmc->card) { + mmc_remove_card(host->mmc->card); + host->mmc->card = NULL; + mmc_claim_host(host->mmc); + mmc_detach_bus(host->mmc); + mmc_release_host(host->mmc); + } + mmc_power_off(host->mmc); + mmc_detect_change(host->mmc, 0); + while (tmo) { + if (host->mmc->card && mmc_card_present(host->mmc->card)) { + ret = 0; + break; + } + msleep(50); + tmo--; + } + ERR_MSG("Reinit %s", ret == 0 ? "success" : "fail"); + +skip_reinit1: + if (!(host->mmc->caps & MMC_CAP_NONREMOVABLE) && (host->mmc->card) + && mmc_card_present(host->mmc->card) + && (!mmc_card_removed(host->mmc->card)) + && (host->block_bad_card == 0)) + ret = 0; +skip_reinit2: + return ret; +} + +static void msdc_pin_reset(struct msdc_host *host, int mode, int force_reset) +{ + struct msdc_hw *hw = (struct msdc_hw *)host->hw; + void __iomem *base = host->base; + + /* Config reset pin */ + if ((hw->flags & MSDC_RST_PIN_EN) || force_reset) { + if (mode == MSDC_PIN_PULL_UP) + MSDC_CLR_BIT32(EMMC_IOCON, EMMC_IOCON_BOOTRST); + else + MSDC_SET_BIT32(EMMC_IOCON, EMMC_IOCON_BOOTRST); + } +} + +static void msdc_card_reset(struct mmc_host *mmc) +{ + /* Note: if HW reset pin is not available, + 2 alternative solution can be used: + 1. Power on/off eMMC + 2. send CMD0 to eMMC + */ + struct msdc_host *host = mmc_priv(mmc); + + msdc_pin_reset(host, MSDC_PIN_PULL_DOWN, 1); + udelay(2); + msdc_pin_reset(host, MSDC_PIN_PULL_UP, 1); + usleep_range(200, 500); +} + +static void msdc_set_power_mode(struct msdc_host *host, u8 mode) +{ + N_MSG(CFG, "Set power mode(%d)", mode); + if (host->power_mode == MMC_POWER_OFF && mode != MMC_POWER_OFF) { + msdc_pin_reset(host, MSDC_PIN_PULL_UP, 0); + msdc_pin_config(host, MSDC_PIN_PULL_UP); + + if (host->power_control) + host->power_control(host, 1); + + mdelay(10); + + msdc_oc_check(host); + + } else if (host->power_mode != MMC_POWER_OFF && mode == MMC_POWER_OFF) { + + if (is_card_sdio(host) || (host->hw->flags & MSDC_SDIO_IRQ)) { + msdc_pin_config(host, MSDC_PIN_PULL_UP); + } else { + + if (host->power_control) + host->power_control(host, 0); + + msdc_pin_config(host, MSDC_PIN_PULL_DOWN); + } + mdelay(20); /* FIX ME: check if delay 10 is enough */ + msdc_pin_reset(host, MSDC_PIN_PULL_DOWN, 0); + } + host->power_mode = mode; +} + +#ifdef CONFIG_PM +static void msdc_pm(pm_message_t state, void *data) +{ + struct msdc_host *host = (struct msdc_host *)data; + void __iomem *base = host->base; + + int evt = state.event; + + msdc_ungate_clock(host); + + if (evt == PM_EVENT_SUSPEND || evt == PM_EVENT_USER_SUSPEND) { + if (host->suspend) + goto end; + + host->suspend = 1; + host->pm_state = state; + + N_MSG(PWR, "msdc%d -> %s Suspend", host->id, + evt == PM_EVENT_SUSPEND ? "PM" : "USR"); + if (host->hw->flags & MSDC_SYS_SUSPEND) { + if (host->hw->host_function == MSDC_EMMC) { + msdc_save_timing_setting(host, 1); + msdc_set_power_mode(host, MMC_POWER_OFF); + } + + msdc_set_tdsel(host, 1, 0); + + } else { + host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; + mmc_remove_host(host->mmc); + } + + host->power_cycle = 0; + } else if (evt == PM_EVENT_RESUME || evt == PM_EVENT_USER_RESUME) { + if (!host->suspend) + goto end; + + if (evt == PM_EVENT_RESUME + && host->pm_state.event == PM_EVENT_USER_SUSPEND) { + ERR_MSG("PM Resume when in USR Suspend"); + goto end; + } + + host->suspend = 0; + host->pm_state = state; + + N_MSG(PWR, "msdc%d -> %s Resume", host->id, + evt == PM_EVENT_RESUME ? "PM" : "USR"); + + if (!(host->hw->flags & MSDC_SYS_SUSPEND)) { + host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; + mmc_add_host(host->mmc); + goto end; + } + + /* Begin for host->hw->flags & MSDC_SYS_SUSPEND*/ + msdc_set_tdsel(host, 1, 0); + + if (host->hw->host_function == MSDC_EMMC) { + msdc_reset_hw(host->id); + msdc_set_power_mode(host, MMC_POWER_ON); + msdc_restore_timing_setting(host); + + if (emmc_sleep_failed) { + msdc_card_reset(host->mmc); + mdelay(200); + mmc_card_clr_sleep(host->mmc->card); + emmc_sleep_failed = 0; + host->mmc->ios.timing = MMC_TIMING_LEGACY; + mmc_set_clock(host->mmc, 260000); + } + } + } + +end: +#ifdef SDIO_ERROR_BYPASS + if (is_card_sdio(host)) + host->sdio_error = 0; +#endif + if ((evt == PM_EVENT_SUSPEND) || (evt == PM_EVENT_USER_SUSPEND)) { + if ((host->hw->host_function == MSDC_SDIO) && + (evt == PM_EVENT_USER_SUSPEND)) { + pr_err("msdc%d -> MSDC Device Request Suspend", + host->id); + } + msdc_gate_clock(host, 0); + } else { + msdc_gate_clock(host, 1); + } + + if (host->hw->host_function == MSDC_SDIO) { + host->mmc->pm_flags |= MMC_PM_KEEP_POWER; + host->mmc->rescan_entered = 0; + } +} +#endif + +struct msdc_host *msdc_get_host(int host_function, bool boot, bool secondary) +{ + int host_index = 0; + struct msdc_host *host = NULL, *host2; + + for (; host_index < HOST_MAX_NUM; ++host_index) { + host2 = mtk_msdc_host[host_index]; + if (!host2) + continue; + if ((host_function == host2->hw->host_function) && + (boot == host2->hw->boot)) { + host = host2; + break; + } + } + if (secondary && (host_function == MSDC_SD)) + host = mtk_msdc_host[2]; + if (host == NULL) { + pr_err("[MSDC] This host( ) isn't in MSDC host config list", + host_function, boot, secondary); + /* BUG(); */ + } + + return host; +} +EXPORT_SYMBOL(msdc_get_host); + +int msdc_switch_part(struct msdc_host *host, char part_id) +{ + int ret = 0; + struct mmc_card *card; + + if ((host != NULL) && (host->mmc != NULL) && (host->mmc->card != NULL)) + card = host->mmc->card; + else + return -ENOMEDIUM; + + if (mmc_card_mmc(card)) { + u8 part_config = card->ext_csd.part_config; + + part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; + part_config |= part_id; + + ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_PART_CONFIG, part_config, + card->ext_csd.part_time); + if (ret) + return ret; + + card->ext_csd.part_config = part_config; + } + + return ret; +} + +static int msdc_cache_onoff(struct mmc_data *data) +{ + u8 *ptr; +#ifdef MTK_MSDC_USE_CACHE + int i; + enum boot_mode_t mode; +#endif + struct scatterlist *sg; + + sg = data->sg; + ptr = (u8 *) sg_virt(sg); + + /* + * if not defined MTK_MSDC_USE_CACHE disable cache + */ +#ifndef MTK_MSDC_USE_CACHE + *(ptr + 252) = *(ptr + 251) = *(ptr + 250) = *(ptr + 249) = 0; + return 0; +#else + /* + * Enable cache by boot mode + * only enable the emmc cache for normal boot up, alarm, and sw reboot + * Other mode will disable it + */ + mode = get_boot_mode(); + if ((mode != NORMAL_BOOT) && (mode != ALARM_BOOT) + && (mode != SW_REBOOT)) { + /* Set cache_size is 0, mmc layer will not enable cache */ + *(ptr + 252) = *(ptr + 251) = *(ptr + 250) = *(ptr + 249) = 0; + return 0; + } + /* + * Enable cache by eMMC vendor + * If eMMC in emmc_cache_quirk[], Don't enable it. + */ + + for (i = 0; i < sizeof(g_emmc_cache_quirk); i++) { + if (g_emmc_cache_quirk[i] == g_emmc_id) { + /* Set cache_size is 0, + * mmc layer will not enable cache + */ + *(ptr + 252) = *(ptr + 251) = 0; + *(ptr + 250) = *(ptr + 249) = 0; + } + } + return 0; +#endif +} + +#ifdef MTK_MSDC_USE_CACHE +static void msdc_set_cache_quirk(struct msdc_host *host) +{ + int i; + /* + * if need disable emmc cache feature by vendor, Add quirk here + * exmple: + * g_emmc_cache_quirk[0] = CID_MANFID_HYNIX; + * g_emmc_cache_quirk[1] = CID_MANFID_SAMSUNG; + */ + + + for (i = 0; i < sizeof(g_emmc_cache_quirk); i++) { + if (g_emmc_cache_quirk[i] == 0) { + /* g_emmc_cache_quirk[i] = eMMC id; */ + pr_debug("msdc%d total emmc cache quirk count=%d\n", + host->id, i); + break; + } + pr_debug("msdc%d,add emmc cache quirk[%d]=0x%x\n", + host->id, i, g_emmc_cache_quirk[i]); + } +} +#endif + +int msdc_cache_ctrl(struct msdc_host *host, unsigned int enable, + u32 *status) +{ + struct mmc_command cmd = { 0 }; + struct mmc_request mrq = { 0 }; + u32 err; + + cmd.opcode = MMC_SWITCH; /* CMD6 */ + cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) + | (EXT_CSD_CACHE_CTRL << 16) | (!!enable << 8) + | EXT_CSD_CMD_SET_NORMAL; + cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + + mrq.cmd = &cmd; + cmd.mrq = &mrq; + cmd.data = NULL; + + ERR_MSG("do disable Cache, cmd=0x%x, arg=0x%x\n", cmd.opcode, cmd.arg); + /* tune until CMD13 pass. */ + err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); + + if (status) + *status = cmd.resp[0]; + if (!err) { + host->mmc->card->ext_csd.cache_ctrl = !!enable; + host->autocmd |= MSDC_AUTOCMD23; + N_MSG(CHE, "enable AUTO_CMD23 because Cache feature is disabled\n"); + } + + return err; +} + +#ifdef MTK_MSDC_USE_CACHE +static void msdc_update_cache_flush_status(struct msdc_host *host, + struct mmc_request *mrq, struct mmc_data *data, + u32 l_bypass_flush) +{ + struct mmc_command *cmd = mrq->cmd; +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + struct mmc_command *sbc; + unsigned int task_id; +#endif + + if (!check_mmc_cache_ctrl(host->mmc->card)) + return; + + if (check_mmc_cmd2425(cmd->opcode)) { + if ((host->error == 0) + && mrq->sbc + && (((mrq->sbc->arg >> 24) & 0x1) || + ((mrq->sbc->arg >> 31) & 0x1))) { + /* if reliable write, or force prg write succeed, + do set cache flushed status */ + if (g_cache_status == CACHE_UN_FLUSHED) { + g_cache_status = CACHE_FLUSHED; + N_MSG(CHE, "reliable/force prg write happend, update g_cache_status = %d", + g_cache_status); + N_MSG(CHE, "reliable/force prg write happend, update g_flush_data_size=%lld", + g_flush_data_size); + g_flush_data_size = 0; + } + } else if (host->error == 0) { + /* if normal write succee, + do clear the cache flushed status */ + if (g_cache_status == CACHE_FLUSHED) { + g_cache_status = CACHE_UN_FLUSHED; + N_MSG(CHE, "normal write happend, update g_cache_status = %d", + g_cache_status); + } + g_flush_data_size += data->blocks; + } else if (host->error) { + g_flush_data_size += data->blocks; + ERR_MSG("write error happend, g_flush_data_size=%lld", + g_flush_data_size); + } +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + } else if (cmd->opcode == MMC_WRITE_REQUESTED_QUEUE) { + if (host->error == 0) { + task_id = (cmd->arg >> 16) & 0x1f; + sbc = host->mmc->areq_que[task_id]->mrq_que->sbc; + if (sbc && (((sbc->arg >> 24) & 0x1) || + ((sbc->arg >> 31) & 0x1))) { + /* if reliable write, or force prg write succeed, + do set cache flushed status */ + if (g_cache_status == CACHE_UN_FLUSHED) { + g_cache_status = CACHE_FLUSHED; + N_MSG(CHE, "reliable/force prg write happend, update g_cache_status = %d", + g_cache_status); + N_MSG(CHE, "reliable/force prg write happend, update g_flush_data_size=%lld", + g_flush_data_size); + g_flush_data_size = 0; + } + } else { + /* if normal write succee, + do clear the cache flushed status */ + if (g_cache_status == CACHE_FLUSHED) { + g_cache_status = CACHE_UN_FLUSHED; + N_MSG(CHE, "normal write happend, update g_cache_status = %d", + g_cache_status); + } + g_flush_data_size += data->blocks; + } + } else if (host->error) { + g_flush_data_size += data->blocks; + ERR_MSG("write error happend, g_flush_data_size=%lld", + g_flush_data_size); + } +#endif + } else if (l_bypass_flush == 0) { + if (host->error == 0) { + /* if flush cache of emmc device successfully, + do set the cache flushed status */ + g_cache_status = CACHE_FLUSHED; + N_MSG(CHE, "flush happend, update g_cache_status = %d, g_flush_data_size=%lld", + g_cache_status, g_flush_data_size); + g_flush_data_size = 0; + } else { + g_flush_error_happend = 1; + } + } +} +#endif + +void msdc_check_cache_flush_error(struct msdc_host *host, + struct mmc_command *cmd) +{ + if (g_flush_error_happend && + check_mmc_cache_ctrl(host->mmc->card) && + check_mmc_cache_flush_cmd(cmd)) { + g_flush_error_count++; + g_flush_error_happend = 0; + ERR_MSG("the %d time flush error happned, g_flush_data_size=%lld", + g_flush_error_count, g_flush_data_size); + /* + * if reinit emmc at resume, cache should not be enabled + * because too much flush error, so add cache quirk for + * this emmmc. + * if awake emmc at resume, cache should not be enabled + * because too much flush error, so force set cache_size = 0 + */ + if (g_flush_error_count >= MSDC_MAX_FLUSH_COUNT) { + if (!msdc_cache_ctrl(host, 0, NULL)) { + g_emmc_cache_quirk[0] = g_emmc_id; + host->mmc->card->ext_csd.cache_size = 0; + } + pr_err("msdc%d:flush cache error count=%d,Disable cache\n", + host->id, g_flush_error_count); + } + } +} + +/*--------------------------------------------------------------------------*/ +/* mmc_host_ops members */ +/*--------------------------------------------------------------------------*/ +static u32 wints_cmd = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | + MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | + MSDC_INT_ACMDTMO; +static unsigned int msdc_command_start(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout) +{ + void __iomem *base = host->base; + u32 opcode = cmd->opcode; + u32 rawcmd; + u32 rawarg; + u32 resp; + unsigned long tmo; + struct mmc_command *sbc = NULL; + char *str; + + if (host->data && host->data->mrq && host->data->mrq->sbc + && (host->autocmd & MSDC_AUTOCMD23)) + sbc = host->data->mrq->sbc; + + /* Protocol layer does not provide response type, but our hardware needs + * to know exact type, not just size! + */ + switch (opcode) { + case MMC_SEND_OP_COND: + case SD_APP_OP_COND: + resp = RESP_R3; + break; + case MMC_SET_RELATIVE_ADDR: + /*case SD_SEND_RELATIVE_ADDR:*/ + /* Since SD_SEND_RELATIVE_ADDR=MMC_SET_RELATIVE_ADDR=3, + only one is allowed in switch case.*/ + resp = (mmc_cmd_type(cmd) == MMC_CMD_BCR) ? RESP_R6 : RESP_R1; + break; + case MMC_FAST_IO: + resp = RESP_R4; + break; + case MMC_GO_IRQ_STATE: + resp = RESP_R5; + break; + case MMC_SELECT_CARD: + resp = (cmd->arg != 0) ? RESP_R1 : RESP_NONE; + host->app_cmd_arg = cmd->arg; + N_MSG(PWR, "msdc%d select card<0x%.8x>", host->id, cmd->arg); + break; + case SD_IO_RW_DIRECT: + case SD_IO_RW_EXTENDED: + /* SDIO workaround. */ + resp = RESP_R1; + break; + case SD_SEND_IF_COND: + resp = RESP_R1; + break; + /* Ignore crc errors when sending status cmd to poll for busy + * MMC_RSP_CRC will be set, then mmc_resp_type will return + * MMC_RSP_NONE. CMD13 will not receive resp + */ + case MMC_SEND_STATUS: + resp = RESP_R1; + break; + default: + switch (mmc_resp_type(cmd)) { + case MMC_RSP_R1: + resp = RESP_R1; + break; + case MMC_RSP_R1B: + resp = RESP_R1B; + break; + case MMC_RSP_R2: + resp = RESP_R2; + break; + case MMC_RSP_R3: + resp = RESP_R3; + break; + case MMC_RSP_NONE: + default: + resp = RESP_NONE; + break; + } + } + + cmd->error = 0; + /* rawcmd : + * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 | + * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | + * opcode + */ + + rawcmd = opcode | msdc_rsp[resp] << 7 | host->blksz << 16; + + switch (opcode) { + case MMC_READ_MULTIPLE_BLOCK: + case MMC_WRITE_MULTIPLE_BLOCK: + rawcmd |= (2 << 11); + if (opcode == MMC_WRITE_MULTIPLE_BLOCK) + rawcmd |= (1 << 13); + if (host->autocmd & MSDC_AUTOCMD12) { + rawcmd |= (1 << 28); + N_MSG(CMD, "AUTOCMD12 is set, addr<0x%x>", cmd->arg); +#ifdef MTK_MSDC_USE_CMD23 + } else if ((host->autocmd & MSDC_AUTOCMD23)) { + unsigned int reg_blk_num; + + rawcmd |= (1 << 29); + if (sbc) { + /* if block number is greater than 0xFFFF, + CMD23 arg will fail to set it.*/ + reg_blk_num = MSDC_READ32(SDC_BLK_NUM); + if (reg_blk_num != (sbc->arg & 0xFFFF)) + pr_err("msdc%d: acmd23 arg(0x%x) fail to match block num(0x%x), SDC_BLK_NUM(0x%x)\n", + host->id, sbc->arg, + host->mrq->cmd->data->blocks, + reg_blk_num); + else + MSDC_WRITE32(SDC_BLK_NUM, sbc->arg); + N_MSG(CMD, "AUTOCMD23 addr<0x%x>, arg<0x%x> ", + cmd->arg, sbc->arg); + } +#endif /* end of MTK_MSDC_USE_CMD23 */ + } + break; + + case MMC_READ_SINGLE_BLOCK: + case MMC_SEND_TUNING_BLOCK: + case MMC_SEND_TUNING_BLOCK_HS200: + rawcmd |= (1 << 11); + break; + case MMC_WRITE_BLOCK: + rawcmd |= ((1 << 11) | (1 << 13)); + break; +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + case MMC_READ_REQUESTED_QUEUE: + rawcmd |= (2 << 11); + break; + case MMC_WRITE_REQUESTED_QUEUE: + rawcmd |= ((2 << 11) | (1 << 13)); + break; + case MMC_CMDQ_TASK_MGMT: + break; +#endif + case SD_IO_RW_EXTENDED: + if (cmd->data->flags & MMC_DATA_WRITE) + rawcmd |= (1 << 13); + if (cmd->data->blocks > 1) + rawcmd |= (2 << 11); + else + rawcmd |= (1 << 11); + break; + case SD_IO_RW_DIRECT: + if (cmd->flags == (unsigned int)-1) + rawcmd |= (1 << 14); + break; + case SD_SWITCH_VOLTAGE: + rawcmd |= (1 << 30); + break; + case SD_APP_SEND_SCR: + case SD_APP_SEND_NUM_WR_BLKS: + rawcmd |= (1 << 11); + break; + case SD_SWITCH: + case SD_APP_SD_STATUS: + case MMC_SEND_EXT_CSD: + if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) + rawcmd |= (1 << 11); + break; + case MMC_STOP_TRANSMISSION: + rawcmd |= (1 << 14); + rawcmd &= ~(0x0FFF << 16); + break; + } + + N_MSG(CMD, "CMD<%d><0x%.8x> Arg<0x%.8x>", opcode, rawcmd, cmd->arg); + + tmo = jiffies + timeout; + + if (opcode == MMC_SEND_STATUS) { + for (;;) { + if (!sdc_is_cmd_busy()) + break; + if (time_after(jiffies, tmo)) { + str = "cmd_busy"; + goto err; + } + } + } else { + for (;;) { + if (!sdc_is_busy()) + break; + if (time_after(jiffies, tmo)) { + str = "sdc_busy"; + goto err; + } + } + } + + host->cmd = cmd; + host->cmd_rsp = resp; + + /* use polling way */ + MSDC_CLR_BIT32(MSDC_INTEN, wints_cmd); + rawarg = cmd->arg; + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + dbg_add_host_log(host->mmc, 0, cmd->opcode, cmd->arg); +#endif + + sdc_send_cmd(rawcmd, rawarg); + + return 0; + +err: + ERR_MSG("XXX %s timeout: before CMD<%d>", str, opcode); + cmd->error = (unsigned int)-ETIMEDOUT; + msdc_dump_register(host); + msdc_reset_hw(host->id); + return cmd->error; + +} + +static u32 msdc_command_resp_polling(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout) +{ + void __iomem *base = host->base; + u32 intsts; + u32 resp; + unsigned long tmo; + /* struct mmc_data *data = host->data; */ + u32 cmdsts = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO; +#ifdef MTK_MSDC_USE_CMD23 + struct mmc_command *sbc = NULL; + + if (host->autocmd & MSDC_AUTOCMD23) { + if (host->data && host->data->mrq && host->data->mrq->sbc) + sbc = host->data->mrq->sbc; + + /* autocmd interrupt disabled, used polling way */ + cmdsts |= MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO; + } +#endif + + resp = host->cmd_rsp; + + /*polling */ + tmo = jiffies + timeout; + while (1) { + intsts = MSDC_READ32(MSDC_INT); + if ((intsts & cmdsts) != 0) { + /* clear all int flag */ +#ifdef MTK_MSDC_USE_CMD23 + /* need clear autocmd23 command ready interrupt */ + intsts &= (cmdsts | MSDC_INT_ACMDRDY); +#else + intsts &= cmdsts; +#endif + MSDC_WRITE32(MSDC_INT, intsts); + break; + } + + if (time_after(jiffies, tmo)) { + pr_err("[%s]: msdc%d CMD<%d> polling_for_completion timeout ARG<0x%.8x>", + __func__, host->id, cmd->opcode, cmd->arg); + cmd->error = (unsigned int)-ETIMEDOUT; + host->sw_timeout++; + msdc_dump_info(host->id); + msdc_reset_hw(host->id); + goto out; + } + } + +#ifdef MTK_MSDC_ERROR_TUNE_DEBUG + msdc_error_tune_debug1(host, cmd, sbc, &intsts); +#endif + + /* command interrupts */ + if (!(intsts & cmdsts)) + goto out; + +#ifdef MTK_MSDC_USE_CMD23 + if (intsts & (MSDC_INT_CMDRDY | MSDC_INT_ACMD19_DONE)) { +#else + if (intsts & (MSDC_INT_CMDRDY | MSDC_INT_ACMD19_DONE + | MSDC_INT_ACMDRDY)) { +#endif + u32 *rsp = NULL; + + rsp = &cmd->resp[0]; + switch (host->cmd_rsp) { + case RESP_NONE: + break; + case RESP_R2: + *rsp++ = MSDC_READ32(SDC_RESP3); + *rsp++ = MSDC_READ32(SDC_RESP2); + *rsp++ = MSDC_READ32(SDC_RESP1); + *rsp++ = MSDC_READ32(SDC_RESP0); + break; + default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ + *rsp = MSDC_READ32(SDC_RESP0); + + if ((cmd->opcode == 13) || (cmd->opcode == 25)) { + if (*rsp & R1_WP_VIOLATION) { + pr_err("[%s]: msdc%d XXX CMD<%d> resp<0x%.8x>, write protection violation\n", + __func__, host->id, cmd->opcode, + *rsp); + } + + /* workaround for latch error */ + if ((*rsp & R1_OUT_OF_RANGE) + && (host->hw->host_function != MSDC_SDIO)) { + pr_err("[%s]: msdc%d XXX CMD<%d> resp<0x%.8x>,bit31=1,force make crc error\n", + __func__, host->id, cmd->opcode, + *rsp); + cmd->error = (unsigned int)-EILSEQ; + } + } + break; + } +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + dbg_add_host_log(host->mmc, 1, cmd->opcode, cmd->resp[0]); +#endif + } else if (intsts & MSDC_INT_RSPCRCERR) { + cmd->error = (unsigned int)-EILSEQ; + if ((cmd->opcode != 19) && (cmd->opcode != 21)) + pr_err("[%s]: msdc%d CMD<%d> MSDC_INT_RSPCRCERR Arg<0x%.8x>", + __func__, host->id, cmd->opcode, cmd->arg); + if (((MMC_RSP_R1B == mmc_resp_type(cmd)) || (cmd->opcode == 13)) + && (host->hw->host_function != MSDC_SDIO)) { + pr_err("[%s]: msdc%d CMD<%d> ARG<0x%.8X> is R1B, CRC not reset hw\n", + __func__, host->id, cmd->opcode, cmd->arg); + } else { + msdc_reset_hw(host->id); + } + } else if (intsts & MSDC_INT_CMDTMO) { + cmd->error = (unsigned int)-ETIMEDOUT; + if ((cmd->opcode != 19) && (cmd->opcode != 21)) + pr_err("[%s]: msdc%d CMD<%d> MSDC_INT_CMDTMO Arg<0x%.8x>", + __func__, host->id, cmd->opcode, cmd->arg); + if ((cmd->opcode != 52) && (cmd->opcode != 8) && + (cmd->opcode != 5) && (cmd->opcode != 55) && + (cmd->opcode != 19) && (cmd->opcode != 21) && + (cmd->opcode != 1) && + ((cmd->opcode != 13) || (g_emmc_mode_switch == 0))) { +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (host->hw->host_function == MSDC_EMMC) + mmc_cmd_dump(host->mmc); +#endif + msdc_dump_info(host->id); + } + + if (((MMC_RSP_R1B == mmc_resp_type(cmd)) || (cmd->opcode == 13)) + && (host->hw->host_function != MSDC_SDIO)) { + pr_err("[%s]: msdc%d XXX CMD<%d> ARG<0x%.8X> is R1B, TMO not reset hw\n", + __func__, host->id, cmd->opcode, cmd->arg); + } else { + msdc_reset_hw(host->id); + } + } +#ifdef MTK_MSDC_USE_CMD23 + if ((sbc != NULL) && (host->autocmd & MSDC_AUTOCMD23)) { + if (intsts & MSDC_INT_ACMDRDY) { + u32 *arsp = &sbc->resp[0]; + *arsp = MSDC_READ32(SDC_ACMD_RESP); + } else if (intsts & MSDC_INT_ACMDCRCERR) { + pr_err("[%s]: msdc%d, autocmd23 crc error\n", + __func__, host->id); + sbc->error = (unsigned int)-EILSEQ; + /* record the error info in current cmd struct */ + cmd->error = (unsigned int)-EILSEQ; + /* host->error |= REQ_CMD23_EILSEQ; */ + msdc_reset_hw(host->id); + } else if (intsts & MSDC_INT_ACMDTMO) { + pr_err("[%s]: msdc%d, autocmd23 tmo error\n", + __func__, host->id); + sbc->error = (unsigned int)-ETIMEDOUT; + /* record the error info in current cmd struct */ + cmd->error = (unsigned int)-ETIMEDOUT; + msdc_dump_info(host->id); + /* host->error |= REQ_CMD23_TMO; */ + msdc_reset_hw(host->id); + } + } +#endif /* end of MTK_MSDC_USE_CMD23 */ + + out: + host->cmd = NULL; + + if (!cmd->data && !cmd->error) + host->prev_cmd_cause_dump = 0; + + return cmd->error; +} + +unsigned int msdc_do_command(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout) +{ + MVG_EMMC_DECLARE_INT32(delay_ns); + MVG_EMMC_DECLARE_INT32(delay_us); + MVG_EMMC_DECLARE_INT32(delay_ms); + + if ((cmd->opcode == MMC_GO_IDLE_STATE) && + (host->hw->host_function == MSDC_SD)) { + mdelay(10); + } + + MVG_EMMC_ERASE_MATCH(host, (u64)cmd->arg, delay_ms, delay_us, + delay_ns, cmd->opcode); + + if (msdc_command_start(host, cmd, tune, timeout)) + goto end; + + MVG_EMMC_ERASE_RESET(delay_ms, delay_us, cmd->opcode); + + if (msdc_command_resp_polling(host, cmd, tune, timeout)) + goto end; + + end: + N_MSG(CMD, " return<%d> resp<0x%.8x>", cmd->error, cmd->resp[0]); + return cmd->error; +} + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT +static unsigned int msdc_cmdq_command_start(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout) +{ + void __iomem *base = host->base; + u32 opcode = cmd->opcode; + u32 rawarg; + u32 resp; + unsigned long tmo; + u32 wints_cq_cmd = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO; + + switch (opcode) { + case MMC_SET_QUEUE_CONTEXT: + case MMC_QUEUE_READ_ADDRESS: + case MMC_SEND_STATUS: + break; + default: + pr_err("[%s]: ERROR, only CMD44/CMD45/CMD13 can issue\n", + __func__); + break; + } + + resp = RESP_R1; + cmd->error = 0; + + N_MSG(CMD, "CMD<%d> Arg<0x%.8x>", opcode, cmd->arg); + + tmo = jiffies + timeout; + + for (;;) { + if (!sdc_is_cmd_busy()) + break; + + if (time_after(jiffies, tmo)) { + ERR_MSG("[%s]: XXX cmd_busy timeout: before CMD<%d>", + __func__ , opcode); + cmd->error = (unsigned int)-ETIMEDOUT; + msdc_reset_hw(host->id); + return cmd->error; + } + } + + host->cmd = cmd; + host->cmd_rsp = resp; + + /* use polling way */ + MSDC_CLR_BIT32(MSDC_INTEN, wints_cq_cmd); + rawarg = cmd->arg; + + dbg_add_host_log(host->mmc, 0, cmd->opcode, cmd->arg); + sdc_send_cmdq_cmd(opcode, rawarg); + + return 0; +} + +static unsigned int msdc_cmdq_command_resp_polling(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout) +{ + void __iomem *base = host->base; + u32 intsts; + u32 resp; + unsigned long tmo; + u32 cmdsts = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO; + + resp = host->cmd_rsp; + + /*polling*/ + tmo = jiffies + timeout; + while (1) { + intsts = MSDC_READ32(MSDC_INT); + if ((intsts & cmdsts) != 0) { + /* clear all int flag */ + intsts &= cmdsts; + MSDC_WRITE32(MSDC_INT, intsts); + break; + } + + if (time_after(jiffies, tmo)) { + pr_err("[%s]: msdc%d CMD<%d> polling_for_completion timeout ARG<0x%.8x>", + __func__, host->id, cmd->opcode, cmd->arg); + cmd->error = (unsigned int)-ETIMEDOUT; + host->sw_timeout++; + msdc_dump_info(host->id); + /*msdc_reset_hw(host->id);*/ + goto out; + } + } + + /* command interrupts */ + if (intsts & cmdsts) { + if (intsts & MSDC_INT_CMDRDY) { + u32 *rsp = NULL; + + rsp = &cmd->resp[0]; + switch (host->cmd_rsp) { + case RESP_NONE: + break; + case RESP_R2: + *rsp++ = MSDC_READ32(SDC_RESP3); + *rsp++ = MSDC_READ32(SDC_RESP2); + *rsp++ = MSDC_READ32(SDC_RESP1); + *rsp++ = MSDC_READ32(SDC_RESP0); + break; + default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ + *rsp = MSDC_READ32(SDC_RESP0); + break; + } + dbg_add_host_log(host->mmc, 1, cmd->opcode, cmd->resp[0]); + } else if (intsts & MSDC_INT_RSPCRCERR) { + cmd->error = (unsigned int)-EILSEQ; + pr_err("[%s]: msdc%d XXX CMD<%d> MSDC_INT_RSPCRCERR Arg<0x%.8x>", + __func__, host->id, cmd->opcode, cmd->arg); + msdc_dump_info(host->id); + /*msdc_reset_hw(host->id);*/ + } else if (intsts & MSDC_INT_CMDTMO) { + cmd->error = (unsigned int)-ETIMEDOUT; + pr_err("[%s]: msdc%d XXX CMD<%d> MSDC_INT_CMDTMO Arg<0x%.8x>", + __func__, host->id, cmd->opcode, cmd->arg); + mmc_cmd_dump(host->mmc); + msdc_dump_info(host->id); + /*msdc_reset_hw(host->id);*/ + } + } +out: + host->cmd = NULL; + MSDC_SET_FIELD(EMMC51_CFG0, MSDC_EMMC51_CFG_CMDQEN, (0)); + + if (!cmd->data && !cmd->error) + host->prev_cmd_cause_dump = 0; + + return cmd->error; +} + +/* do command queue command + - CMD44, CMD45, CMD13 - QSR + Use another register set */ +unsigned int msdc_do_cmdq_command(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout) +{ + if (msdc_cmdq_command_start(host, cmd, tune, timeout)) + goto end; + + if (msdc_cmdq_command_resp_polling(host, cmd, tune, timeout)) + goto end; +end: + N_MSG(CMD, " return<%d> resp<0x%.8x>", cmd->error, cmd->resp[0]); + return cmd->error; +} +#endif + +/* The abort condition when PIO read/write + tmo: +*/ +static int msdc_pio_abort(struct msdc_host *host, struct mmc_data *data, + unsigned long tmo) +{ + int ret = 0; + void __iomem *base = host->base; + + if (atomic_read(&host->abort)) + ret = 1; + + if (time_after(jiffies, tmo)) { + data->error = (unsigned int)-ETIMEDOUT; + ERR_MSG("XXX PIO Data Timeout: CMD<%d>", + host->mrq->cmd->opcode); + msdc_dump_info(host->id); + ret = 1; + } + + if (ret) { + msdc_reset_hw(host->id); + ERR_MSG("msdc pio find abort"); + } + return ret; +} + +/* + Need to add a timeout, or WDT timeout, system reboot. +*/ +/* pio mode data read/write */ +int msdc_pio_read(struct msdc_host *host, struct mmc_data *data) +{ + struct scatterlist *sg = data->sg; + void __iomem *base = host->base; + u32 num = data->sg_len; + u32 *ptr; + u8 *u8ptr; + u32 left = 0; + u32 count, size = 0; + u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR + | MSDC_INTEN_XFER_COMPL; + u32 ints = 0; + bool get_xfer_done = 0; + unsigned long tmo = jiffies + DAT_TIMEOUT; + struct page *hmpage = NULL; + int i = 0, subpage = 0, totalpages = 0; + int flag = 0; + ulong kaddr[DIV_ROUND_UP(MAX_SGMT_SZ, PAGE_SIZE)]; + + BUG_ON(sg == NULL); + /*MSDC_CLR_BIT32(MSDC_INTEN, wints);*/ + while (1) { + if (!get_xfer_done) { + ints = MSDC_READ32(MSDC_INT); + latest_int_status[host->id] = ints; + ints &= wints; + MSDC_WRITE32(MSDC_INT, ints); + } + if (ints & MSDC_INT_DATTMO) { + data->error = (unsigned int)-ETIMEDOUT; + msdc_dump_info(host->id); + msdc_reset_hw(host->id); + break; + } else if (ints & MSDC_INT_DATCRCERR) { + data->error = (unsigned int)-EILSEQ; + /* msdc_dump_info(host->id); */ + msdc_reset_hw(host->id); + /* left = msdc_sg_len(sg, host->dma_xfer); */ + /* ptr = sg_virt(sg); */ + break; + } else if (ints & MSDC_INT_XFER_COMPL) { + get_xfer_done = 1; + } + if (get_xfer_done && (num == 0) && (left == 0)) + break; + if (msdc_pio_abort(host, data, tmo)) + goto end; + if ((num == 0) && (left == 0)) + continue; + left = msdc_sg_len(sg, host->dma_xfer); + ptr = sg_virt(sg); + flag = 0; + + if ((ptr != NULL) && + !(PageHighMem((struct page *)(sg->page_link & ~0x3)))) + goto check_fifo1; + + hmpage = (struct page *)(sg->page_link & ~0x3); + totalpages = DIV_ROUND_UP((left + sg->offset), PAGE_SIZE); + subpage = (left + sg->offset) % PAGE_SIZE; + + if (subpage != 0 || (sg->offset != 0)) + N_MSG(OPS, "msdc%d: read size or start not align %x,%x, hmpage %lx,sg offset %x\n", + host->id, subpage, left, (ulong)hmpage, + sg->offset); + + for (i = 0; i < totalpages; i++) { + kaddr[i] = (ulong) kmap(hmpage + i); + if ((i > 0) && ((kaddr[i] - kaddr[i - 1]) != PAGE_SIZE)) + flag = 1; + if (!kaddr[i]) + ERR_MSG("msdc0:kmap failed %lx", kaddr[i]); + } + + ptr = sg_virt(sg); + + if (ptr == NULL) + ERR_MSG("msdc0:sg_virt %p", ptr); + + if (flag == 0) + goto check_fifo1; + + /* High memory and more than 1 va address va + and not continuous */ + /* pr_err("msdc0: kmap not continuous %x %x %x\n", + left,kaddr[i],kaddr[i-1]); */ + for (i = 0; i < totalpages; i++) { + left = PAGE_SIZE; + ptr = (u32 *) kaddr[i]; + + if (i == 0) { + left = PAGE_SIZE - sg->offset; + ptr = (u32 *) (kaddr[i] + sg->offset); + } + if ((subpage != 0) && (i == (totalpages-1))) + left = subpage; + +check_fifo1: + if ((flag == 1) && (left == 0)) + continue; + else if ((flag == 0) && (left == 0)) + goto check_fifo_end; + + if ((msdc_rxfifocnt() >= MSDC_FIFO_THD) && + (left >= MSDC_FIFO_THD)) { + count = MSDC_FIFO_THD >> 2; + do { +#ifdef MTK_MSDC_DUMP_FIFO + pr_debug("0x%x ", msdc_fifo_read32()); +#else + *ptr++ = msdc_fifo_read32(); +#endif + } while (--count); + left -= MSDC_FIFO_THD; + } else if ((left < MSDC_FIFO_THD) && + msdc_rxfifocnt() >= left) { + while (left > 3) { +#ifdef MTK_MSDC_DUMP_FIFO + pr_debug("0x%x ", msdc_fifo_read32()); +#else + *ptr++ = msdc_fifo_read32(); +#endif + left -= 4; + } + + u8ptr = (u8 *) ptr; + while (left) { +#ifdef MTK_MSDC_DUMP_FIFO + pr_debug("0x%x ", msdc_fifo_read8()); +#else + *u8ptr++ = msdc_fifo_read8(); +#endif + left--; + } + } else { + ints = MSDC_READ32(MSDC_INT); + latest_int_status[host->id] = ints; + + if (ints & MSDC_INT_DATCRCERR) { + ERR_MSG("[msdc%d] DAT CRC error (0x%x), Left DAT: %d bytes\n", + host->id, ints, left); + data->error = (unsigned int)-EILSEQ; + } else if (ints & MSDC_INT_DATTMO) { + ERR_MSG("[msdc%d] DAT TMO error (0x%x), Left DAT: %d bytes\n", + host->id, ints, left); + data->error = (unsigned int)-ETIMEDOUT; + } else { + goto skip_msdc_dump_and_reset1; + } + + if (ints & MSDC_INT_DATTMO) + msdc_dump_info(host->id); + + MSDC_WRITE32(MSDC_INT, ints); + msdc_reset_hw(host->id); + goto end; + } + +skip_msdc_dump_and_reset1: + if (msdc_pio_abort(host, data, tmo)) + goto end; + + goto check_fifo1; + } + +check_fifo_end: + if (hmpage != NULL) { + /* pr_err("read msdc0:unmap %x\n", hmpage); */ + for (i = 0; i < totalpages; i++) + kunmap(hmpage + i); + + hmpage = NULL; + } + size += msdc_sg_len(sg, host->dma_xfer); + sg = sg_next(sg); + num--; + } + end: + if (hmpage != NULL) { + for (i = 0; i < totalpages; i++) + kunmap(hmpage + i); + /* pr_err("msdc0 read unmap:\n"); */ + } + data->bytes_xfered += size; + N_MSG(FIO, " PIO Read<%d>bytes", size); + + if (data->error) + ERR_MSG("read pio data->error<%d> left<%d> size<%d>", + data->error, left, size); + + if (!data->error) + host->prev_cmd_cause_dump = 0; + + return data->error; +} + +/* please make sure won't using PIO when size >= 512 + which means, memory card block read/write won't using pio + then don't need to handle the CMD12 when data error. +*/ +int msdc_pio_write(struct msdc_host *host, struct mmc_data *data) +{ + void __iomem *base = host->base; + struct scatterlist *sg = data->sg; + u32 num = data->sg_len; + u32 *ptr; + u8 *u8ptr; + u32 left = 0; + u32 count, size = 0; + u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR + | MSDC_INTEN_XFER_COMPL; + bool get_xfer_done = 0; + unsigned long tmo = jiffies + DAT_TIMEOUT; + u32 ints = 0; + struct page *hmpage = NULL; + int i = 0, totalpages = 0; + int flag, subpage = 0; + ulong kaddr[DIV_ROUND_UP(MAX_SGMT_SZ, PAGE_SIZE)]; + + /* MSDC_CLR_BIT32(MSDC_INTEN, wints); */ + while (1) { + if (!get_xfer_done) { + ints = MSDC_READ32(MSDC_INT); + latest_int_status[host->id] = ints; + ints &= wints; + MSDC_WRITE32(MSDC_INT, ints); + } + if (ints & MSDC_INT_DATTMO) { + data->error = (unsigned int)-ETIMEDOUT; + msdc_dump_info(host->id); + msdc_reset_hw(host->id); + break; + } else if (ints & MSDC_INT_DATCRCERR) { + data->error = (unsigned int)-EILSEQ; + /* msdc_dump_info(host->id); */ + msdc_reset_hw(host->id); + break; + } else if (ints & MSDC_INT_XFER_COMPL) { + get_xfer_done = 1; + } + if ((get_xfer_done == 1) && (num == 0) && (left == 0)) + break; + if (msdc_pio_abort(host, data, tmo)) + goto end; + if ((num == 0) && (left == 0)) + continue; + left = msdc_sg_len(sg, host->dma_xfer); + ptr = sg_virt(sg); + + flag = 0; + + /* High memory must kmap, if already mapped, + only add counter */ + if ((ptr != NULL) && + !(PageHighMem((struct page *)(sg->page_link & ~0x3)))) + goto check_fifo1; + + hmpage = (struct page *)(sg->page_link & ~0x3); + totalpages = DIV_ROUND_UP(left + sg->offset, PAGE_SIZE); + subpage = (left + sg->offset) % PAGE_SIZE; + + if ((subpage != 0) || (sg->offset != 0)) + N_MSG(OPS, "msdc%d: write size or start not align %x,%x, hmpage %lx,sg offset %x\n", + host->id, subpage, left, (ulong)hmpage, + sg->offset); + + /* Kmap all need pages, */ + for (i = 0; i < totalpages; i++) { + kaddr[i] = (ulong) kmap(hmpage + i); + if ((i > 0) && ((kaddr[i] - kaddr[i - 1]) != PAGE_SIZE)) + flag = 1; + if (!kaddr[i]) + ERR_MSG("msdc0:kmap failed %lx\n", kaddr[i]); + } + + ptr = sg_virt(sg); + + if (ptr == NULL) + ERR_MSG("msdc0:write sg_virt %p\n", ptr); + + if (flag == 0) + goto check_fifo1; + + /* High memory and more than 1 va address va + may be not continuous */ + /*pr_err(ERR "msdc0:w kmap not continuous %x %x %x\n", + left, kaddr[i], kaddr[i-1]);*/ + for (i = 0; i < totalpages; i++) { + left = PAGE_SIZE; + ptr = (u32 *) kaddr[i]; + + if (i == 0) { + left = PAGE_SIZE - sg->offset; + ptr = (u32 *) (kaddr[i] + sg->offset); + } + if (subpage != 0 && (i == (totalpages - 1))) + left = subpage; + +check_fifo1: + if ((flag == 1) && (left == 0)) + continue; + else if ((flag == 0) && (left == 0)) + goto check_fifo_end; + + if (left >= MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { + count = MSDC_FIFO_SZ >> 2; + do { + msdc_fifo_write32(*ptr); + ptr++; + } while (--count); + left -= MSDC_FIFO_SZ; + } else if (left < MSDC_FIFO_SZ && + msdc_txfifocnt() == 0) { + while (left > 3) { + msdc_fifo_write32(*ptr); + ptr++; + left -= 4; + } + u8ptr = (u8 *) ptr; + while (left) { + msdc_fifo_write8(*u8ptr); + u8ptr++; + left--; + } + } else { + ints = MSDC_READ32(MSDC_INT); + latest_int_status[host->id] = ints; + + if (ints & MSDC_INT_DATCRCERR) { + ERR_MSG("[msdc%d] DAT CRC error (0x%x), Left DAT: %d bytes\n", + host->id, ints, left); + data->error = (unsigned int)-EILSEQ; + } else if (ints & MSDC_INT_DATTMO) { + ERR_MSG("[msdc%d] DAT TMO error (0x%x), Left DAT: %d bytes\n", + host->id, ints, left); + data->error = (unsigned int)-ETIMEDOUT; + } else { + goto skip_msdc_dump_and_reset1; + } + + msdc_dump_info(host->id); + + MSDC_WRITE32(MSDC_INT, ints); + msdc_reset_hw(host->id); + goto end; + } + +skip_msdc_dump_and_reset1: + if (msdc_pio_abort(host, data, tmo)) + goto end; + + goto check_fifo1; + } + +check_fifo_end: + if (hmpage != NULL) { + for (i = 0; i < totalpages; i++) + kunmap(hmpage + i); + + hmpage = NULL; + + } + size += msdc_sg_len(sg, host->dma_xfer); + sg = sg_next(sg); + num--; + } + end: + if (hmpage != NULL) { + for (i = 0; i < totalpages; i++) + kunmap(hmpage + i); + pr_err("msdc0 write unmap 0x%x:\n", left); + } + data->bytes_xfered += size; + N_MSG(FIO, " PIO Write<%d>bytes", size); + + if (data->error) + ERR_MSG("write pio data->error<%d> left<%d> size<%d>", + data->error, left, size); + + if (!data->error) + host->prev_cmd_cause_dump = 0; + + /*MSDC_CLR_BIT32(MSDC_INTEN, wints);*/ + return data->error; +} + +static void msdc_dma_start(struct msdc_host *host) +{ + void __iomem *base = host->base; + u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO + | MSDC_INTEN_DATCRCERR; + + if (host->autocmd & MSDC_AUTOCMD12) + wints |= MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO + | MSDC_INT_ACMDRDY; + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1); + + MSDC_SET_BIT32(MSDC_INTEN, wints); + + N_MSG(DMA, "DMA start"); + /* Schedule delayed work to check if data0 keeps busy */ + if (host->data && (host->data->flags & MMC_DATA_WRITE)) { + host->write_timeout_ms = min_t(u32, max_t(u32, + host->data->blocks * 500, + host->data->timeout_ns / 1000000), 10 * 1000); + schedule_delayed_work(&host->write_timeout, + msecs_to_jiffies(host->write_timeout_ms)); + N_MSG(DMA, "DMA Data Busy Timeout:%u ms, schedule_delayed_work", + host->write_timeout_ms); + } +} + +static void msdc_dma_stop(struct msdc_host *host) +{ + void __iomem *base = host->base; + int retry = 500; + int count = 1000; + u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO + | MSDC_INTEN_DATCRCERR; + + /* Clear DMA data busy timeout */ + if (host->data && (host->data->flags & MMC_DATA_WRITE)) { + cancel_delayed_work(&host->write_timeout); + N_MSG(DMA, "DMA Data Busy Timeout:%u ms, cancel_delayed_work", + host->write_timeout_ms); + host->write_timeout_ms = 0; /* clear timeout */ + } + + /* handle autocmd12 error in msdc_irq */ + if (host->autocmd & MSDC_AUTOCMD12) + wints |= MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO + | MSDC_INT_ACMDRDY; + N_MSG(DMA, "DMA status: 0x%.8x", MSDC_READ32(MSDC_DMA_CFG)); + + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); + msdc_retry((MSDC_READ32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS), retry, + count, host->id); + if (retry == 0) { + msdc_dump_info(host->id); + mdelay(10); + msdc_dump_gpd_bd(host->id); + } + + MSDC_CLR_BIT32(MSDC_INTEN, wints); /* Not just xfer_comp */ + + N_MSG(DMA, "DMA stop"); +} + +/* calc checksum */ +static u8 msdc_dma_calcs(u8 *buf, u32 len) +{ + u32 i, sum = 0; + + for (i = 0; i < len; i++) + sum += buf[i]; + return 0xFF - (u8) sum; +} + +/* gpd bd setup + dma registers */ +static int msdc_dma_config(struct msdc_host *host, struct msdc_dma *dma) +{ + void __iomem *base = host->base; + u32 sglen = dma->sglen; + u32 j, num, bdlen; + dma_addr_t dma_address; + u32 dma_len; + u8 blkpad, dwpad, chksum; + struct scatterlist *sg = dma->sg; + struct gpd_t *gpd; + struct bd_t *bd, vbd = {0}; + + switch (dma->mode) { + case MSDC_MODE_DMA_BASIC: + if (host->hw->host_function == MSDC_SDIO) + BUG_ON(dma->xfersz > 0xFFFFFFFF); + else + BUG_ON(dma->xfersz > 65535); + + BUG_ON(dma->sglen != 1); + dma_address = sg_dma_address(sg); + dma_len = msdc_sg_len(sg, host->dma_xfer); + + N_MSG(DMA, "BASIC DMA len<%x> dma_address<%llx>", + dma_len, (u64)dma_address); + + MSDC_WRITE32(MSDC_DMA_SA, dma_address); + + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_LASTBUF, 1); + MSDC_WRITE32(MSDC_DMA_LEN, dma_len); + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, + dma->burstsz); + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 0); + break; + + case MSDC_MODE_DMA_DESC: + blkpad = (dma->flags & DMA_FLAG_PAD_BLOCK) ? 1 : 0; + dwpad = (dma->flags & DMA_FLAG_PAD_DWORD) ? 1 : 0; + chksum = (dma->flags & DMA_FLAG_EN_CHKSUM) ? 1 : 0; + + /* calculate the required number of gpd */ + num = (sglen + MAX_BD_PER_GPD - 1) / MAX_BD_PER_GPD; + BUG_ON(num != 1); + + gpd = dma->gpd; + bd = dma->bd; + bdlen = sglen; + + /* modify gpd */ + gpd->hwo = 1; /* hw will clear it */ + gpd->bdp = 1; + gpd->chksum = 0; /* need to clear first. */ + gpd->chksum = (chksum ? msdc_dma_calcs((u8 *) gpd, 16) : 0); + + /* modify bd */ + for (j = 0; j < bdlen; j++) { +#ifdef MSDC_DMA_VIOLATION_DEBUG + if (g_dma_debug[host->id] && + (msdc_latest_op[host->id] == OPER_TYPE_READ)) { + pr_debug("[%s] msdc%d do write 0x10000\n", + __func__, host->id); + dma_address = 0x10000; + } else { + dma_address = sg_dma_address(sg); + } +#else + dma_address = sg_dma_address(sg); +#endif + + dma_len = msdc_sg_len(sg, host->dma_xfer); + + N_MSG(DMA, "DESC DMA len<%x> dma_address<%llx>", + dma_len, (u64)dma_address); + + memcpy(&vbd, &bd[j], sizeof(struct bd_t)); + + msdc_init_bd(&vbd, blkpad, dwpad, dma_address, + dma_len); + + if (j == bdlen - 1) + vbd.eol = 1; /* the last bd */ + else + vbd.eol = 0; + + /* checksume need to clear first */ + vbd.chksum = 0; + vbd.chksum = (chksum ? + msdc_dma_calcs((u8 *) (&vbd), 16) : 0); + + memcpy(&bd[j], &vbd, sizeof(struct bd_t)); + + sg++; + } +#ifdef MSDC_DMA_VIOLATION_DEBUG + if (g_dma_debug[host->id] && + (msdc_latest_op[host->id] == OPER_TYPE_READ)) + g_dma_debug[host->id] = 0; +#endif + + dma->used_gpd += 2; + dma->used_bd += bdlen; + + MSDC_SET_FIELD(MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, chksum); + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, + dma->burstsz); + MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1); + + MSDC_WRITE32(MSDC_DMA_SA, (u32) dma->gpd_addr); + break; + + default: + break; + } + + N_MSG(DMA, "DMA_CTRL = 0x%x", MSDC_READ32(MSDC_DMA_CTRL)); + N_MSG(DMA, "DMA_CFG = 0x%x", MSDC_READ32(MSDC_DMA_CFG)); + N_MSG(DMA, "DMA_SA = 0x%x", MSDC_READ32(MSDC_DMA_SA)); + + return 0; +} + +static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, + struct scatterlist *sg, unsigned int sglen) +{ + u32 max_dma_len = 0; + + BUG_ON(sglen > MAX_BD_NUM); /* not support currently */ + + dma->sg = sg; + dma->flags = DMA_FLAG_EN_CHKSUM; + /* dma->flags = DMA_FLAG_NONE; */ /* CHECKME */ + dma->sglen = sglen; + dma->xfersz = host->xfer_size; + dma->burstsz = MSDC_BRUST_64B; + + if (host->hw->host_function == MSDC_SDIO) + max_dma_len = MAX_DMA_CNT_SDIO; + else + max_dma_len = MAX_DMA_CNT; + + if (sglen == 1 && + msdc_sg_len(sg, host->dma_xfer) <= max_dma_len) + dma->mode = MSDC_MODE_DMA_BASIC; + else + dma->mode = MSDC_MODE_DMA_DESC; + + N_MSG(DMA, "DMA mode<%d> sglen<%d> xfersz<%d>", dma->mode, dma->sglen, + dma->xfersz); + + msdc_dma_config(host, dma); +} + +static void msdc_dma_clear(struct msdc_host *host) +{ + void __iomem *base = host->base; + + host->data = NULL; + host->mrq = NULL; + host->dma_xfer = 0; + msdc_dma_off(); + host->dma.used_bd = 0; + host->dma.used_gpd = 0; + host->blksz = 0; +} + +/* set block number before send command */ +static void msdc_set_blknum(struct msdc_host *host, u32 blknum) +{ + void __iomem *base = host->base; + + MSDC_WRITE32(SDC_BLK_NUM, blknum); +} + +static void msdc_log_cmd(struct msdc_host *host, struct mmc_command *cmd, + struct mmc_data *data) +{ + N_MSG(OPS, "CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>", + cmd->opcode, (host->dma_xfer ? "dma" : "pio"), + ((data->flags & MMC_DATA_READ) ? "read " : "write"), + data->blksz, data->blocks, data->error); + + if (!(is_card_sdio(host) || (host->hw->flags & MSDC_SDIO_IRQ))) { + if (!check_mmc_cmd2425(cmd->opcode) && + !check_mmc_cmd1718(cmd->opcode)) { + N_MSG(NRW, "CMD<%3d> arg<0x%8x> Resp<0x%8x> data<%s> size<%d>", + cmd->opcode, cmd->arg, cmd->resp[0], + ((data->flags & MMC_DATA_READ) + ? "read " : "write"), + data->blksz * data->blocks); + } else if (cmd->opcode != 13) { /* by pass CMD13 */ + N_MSG(NRW, "CMD<%3d> arg<0x%8x> resp<%8x %8x %8x %8x>", + cmd->opcode, cmd->arg, cmd->resp[0], + cmd->resp[1], cmd->resp[2], cmd->resp[3]); + } else { + N_MSG(RW, "CMD<%3d> arg<0x%8x> Resp<0x%8x> block<%d>", + cmd->opcode, cmd->arg, cmd->resp[0], + data->blocks); + } + } +} + +void msdc_sdio_restore_after_resume(struct msdc_host *host) +{ + void __iomem *base = host->base; + + if (host->saved_para.hz) { + if ((host->saved_para.suspend_flag) + || ((host->saved_para.msdc_cfg != 0) && + ((host->saved_para.msdc_cfg&0xFFFFFF9F) != + (MSDC_READ32(MSDC_CFG)&0xFFFFFF9F)))) { + ERR_MSG("msdc resume[ns] cur_cfg=%x, save_cfg=%x, cur_hz=%d, save_hz=%d", + MSDC_READ32(MSDC_CFG), + host->saved_para.msdc_cfg, host->mclk, + host->saved_para.hz); + host->saved_para.suspend_flag = 0; + msdc_restore_timing_setting(host); + } + } +} + +int msdc_if_send_stop(struct msdc_host *host, + struct mmc_command *cmd, struct mmc_data *data) +{ + if (!data || !data->stop) + return 0; + + if ((cmd->error != 0) + || (data->error != 0) + || !(host->autocmd & MSDC_AUTOCMD12) + || !(check_mmc_cmd1825(cmd->opcode))) { + if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0) + return 1; + } + + return 0; +} + +void msdc_if_set_err(struct msdc_host *host, struct mmc_request *mrq, + struct mmc_command *cmd) +{ + if (mrq->cmd->error == (unsigned int)-EILSEQ) { + if (((cmd->opcode == MMC_SELECT_CARD) || + (cmd->opcode == MMC_SLEEP_AWAKE)) + && ((host->hw->host_function == MSDC_EMMC) || + (host->hw->host_function == MSDC_SD))) { + /* should be deleted in new platform, + as the state verify function has applied*/ + mrq->cmd->error = 0x0; + } else { + host->error |= REQ_CMD_EIO; + } + } + if (mrq->cmd->error == (unsigned int)-ETIMEDOUT) + host->error |= REQ_CMD_TMO; + if (mrq->data && (mrq->data->error)) + host->error |= REQ_DAT_ERR; + if (mrq->stop && (mrq->stop->error == (unsigned int)-EILSEQ)) + host->error |= REQ_STOP_EIO; + if (mrq->stop && (mrq->stop->error == (unsigned int)-ETIMEDOUT)) + host->error |= REQ_STOP_TMO; +} + +int msdc_rw_cmd_dma(struct mmc_host *mmc, struct mmc_command *cmd, + struct mmc_data *data, struct mmc_request *mrq, int tune) +{ + struct msdc_host *host = mmc_priv(mmc); + void __iomem *base = host->base; + int map_sg = 0; + int dir; + + msdc_dma_on(); /* enable DMA mode first!! */ + + init_completion(&host->xfer_done); + + if (msdc_command_start(host, cmd, 0, CMD_TIMEOUT) != 0) + return -1; + + if (tune == 0) { + dir = data->flags & MMC_DATA_READ ? + DMA_FROM_DEVICE : DMA_TO_DEVICE; + (void)dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); + map_sg = 1; + } + + /* then wait command done */ + if (msdc_command_resp_polling(host, cmd, 0, CMD_TIMEOUT) != 0) + return -2; + + /* for read, the data coming too fast, then CRC error + start DMA no business with CRC. */ + msdc_dma_setup(host, &host->dma, data->sg, data->sg_len); + msdc_dma_start(host); + + spin_unlock(&host->lock); + if (!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)) { + ERR_MSG("XXX CMD<%d> ARG<0x%x> wait xfer_done<%d> timeout!!", + cmd->opcode, cmd->arg, data->blocks * data->blksz); + + host->sw_timeout++; + + msdc_dump_info(host->id); + data->error = (unsigned int)-ETIMEDOUT; + msdc_reset(host->id); + } + spin_lock(&host->lock); + + msdc_dma_stop(host); + + if (((host->autocmd & MSDC_AUTOCMD12) && mrq->stop && mrq->stop->error) + || (mrq->data && mrq->data->error) + || (mrq->sbc && (mrq->sbc->error != 0) && + (host->autocmd & MSDC_AUTOCMD23))) { + msdc_clr_fifo(host->id); + msdc_clr_int(); + } + + if (tune) + return 0; + else + return map_sg; +} + +#define PREPARE_NON_ASYNC 0 +#define PREPARE_ASYNC 1 +#define PREPARE_TUNE 2 +int msdc_do_request_prepare(struct msdc_host *host, + struct mmc_request *mrq, + struct mmc_command *cmd, + struct mmc_data *data, + u32 *l_force_prg, + u32 *l_bypass_flush, + int prepare_case) +{ +#ifndef CONFIG_MTK_EMMC_CQ_SUPPORT + void __iomem *base = host->base; +#endif + + #ifndef MSDC_WQ_ERROR_TUNE + if ((prepare_case != PREPARE_TUNE) && (host->mmc->bus_dead != 1)) + host->error = 0; + #else + if (prepare_case != PREPARE_TUNE) + host->error = 0; + #endif + + atomic_set(&host->abort, 0); + +#ifndef CONFIG_MTK_EMMC_CQ_SUPPORT + /* check msdc work ok: RX/TX fifocnt must be zero after last request + * if find abnormal, try to reset msdc first + */ + if (msdc_txfifocnt() || msdc_rxfifocnt()) { + pr_err("[SD%d] register abnormal,please check!\n", host->id); + msdc_reset_hw(host->id); + } +#endif + + if ((prepare_case == PREPARE_NON_ASYNC) && !data) { + +#ifdef MTK_MSDC_USE_CACHE + if ((host->hw->host_function == MSDC_EMMC) && + check_mmc_cache_flush_cmd(cmd)) { + if (g_cache_status == CACHE_FLUSHED) { + N_MSG(CHE, "bypass flush command, g_cache_status=%d", + g_cache_status); + *l_bypass_flush = 1; + return 1; + } + *l_bypass_flush = 0; + } +#endif + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (check_mmc_cmd13_sqs(cmd)) { + if (msdc_do_cmdq_command(host, cmd, 0, CMD_TIMEOUT) != 0) + return 1; + } else { +#endif + if (msdc_do_command(host, cmd, 0, CMD_TIMEOUT) != 0) + return 1; +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + } +#endif + + /* Get emmc_id when send ALL_SEND_CID command */ + if ((host->hw->host_function == MSDC_EMMC) && + (cmd->opcode == MMC_ALL_SEND_CID)) + g_emmc_id = UNSTUFF_BITS(cmd->resp, 120, 8); + + return 1; + } + + BUG_ON(data->blksz > HOST_MAX_BLKSZ); + + data->error = 0; + msdc_latest_op[host->id] = (data->flags & MMC_DATA_READ) + ? OPER_TYPE_READ : OPER_TYPE_WRITE; + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + /* if CMDQ CMD13 QSR, host->data may be data of mrq - CMD46,47 */ + if (!check_mmc_cmd13_sqs(cmd)) + host->data = data; +#else + host->data = data; +#endif + + host->xfer_size = data->blocks * data->blksz; + host->blksz = data->blksz; + if (prepare_case != PREPARE_NON_ASYNC) { + host->dma_xfer = 1; + } else { + /* deside the transfer mode */ + if (drv_mode[host->id] == MODE_PIO) { + host->dma_xfer = 0; + msdc_latest_transfer_mode[host->id] = TRAN_MOD_PIO; + } else if (drv_mode[host->id] == MODE_DMA) { + host->dma_xfer = 1; + msdc_latest_transfer_mode[host->id] = TRAN_MOD_DMA; + } else if (drv_mode[host->id] == MODE_SIZE_DEP) { + host->dma_xfer = (host->xfer_size >= dma_size[host->id]) + ? 1 : 0; + msdc_latest_transfer_mode[host->id] = + host->dma_xfer ? TRAN_MOD_DMA : TRAN_MOD_PIO; + } + } + + if (data->flags & MMC_DATA_READ) { + if ((host->timeout_ns != data->timeout_ns) || + (host->timeout_clks != data->timeout_clks)) { + msdc_set_timeout(host, data->timeout_ns, + data->timeout_clks); + } + } + + msdc_set_blknum(host, data->blocks); + /* msdc_clr_fifo(); */ /* no need */ + +#ifdef MTK_MSDC_USE_CACHE + /* Currently, tuning does not use CMD23, so force programming + cannot be applied */ + if (prepare_case != PREPARE_TUNE + && check_mmc_cache_ctrl(host->mmc->card) + && (cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK)) + *l_force_prg = !msdc_can_apply_cache(cmd->arg, data->blocks); +#endif + + return 0; +} + +int msdc_do_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + struct mmc_data *data; + u32 l_autocmd23_is_set = 0; +#ifdef MTK_MSDC_USE_CMD23 + u32 l_card_no_cmd23 = 0; +#endif +#ifdef MTK_MSDC_USE_CACHE + u32 l_force_prg = 0; + /* 0: flush need, 1: flush bypass, 2: not switch cmd*/ + u32 l_bypass_flush = 2; +#endif + void __iomem *base = host->base; + /* u32 intsts = 0; */ + unsigned int left = 0; + int read = 1, dir = DMA_FROM_DEVICE; + u32 map_sg = 0; + unsigned long pio_tmo; + + if (is_card_sdio(host) || (host->hw->flags & MSDC_SDIO_IRQ)) + msdc_sdio_restore_after_resume(host); + +#if (MSDC_DATA1_INT == 1) + if (host->hw->flags & MSDC_SDIO_IRQ) { + if ((u_sdio_irq_counter > 0) && ((u_sdio_irq_counter%800) == 0)) + ERR_MSG("sdio_irq=%d, msdc_irq=%d SDC_CFG=%x MSDC_INTEN=%x MSDC_INT=%x ", + u_sdio_irq_counter, u_msdc_irq_counter, + MSDC_READ32(SDC_CFG), MSDC_READ32(MSDC_INTEN), + MSDC_READ32(MSDC_INT)); + } +#endif + + BUG_ON(mmc == NULL || mrq == NULL); + + cmd = mrq->cmd; + data = mrq->cmd->data; + +#ifdef MTK_MSDC_USE_CACHE + if (msdc_do_request_prepare(host, mrq, cmd, data, &l_force_prg, + &l_bypass_flush, PREPARE_NON_ASYNC)) +#else + if (msdc_do_request_prepare(host, mrq, cmd, data, NULL, + NULL, PREPARE_NON_ASYNC)) +#endif + goto done; + +#ifdef MTK_MSDC_USE_CMD23 + if (0 == (host->autocmd & MSDC_AUTOCMD23)) { + /* start the cmd23 first, + mrq->sbc is NULL with single r/w */ + if (mrq->sbc) { + host->autocmd &= ~MSDC_AUTOCMD12; + + if (host->hw->host_function == MSDC_EMMC) { +#ifdef MTK_MSDC_USE_CACHE + /* We use force programming to make sure data + * integrity when enable cache except "userdata" + * and "cache" partition + */ + if (!((mrq->sbc->arg >> 31) & 0x1) && + l_force_prg) + mrq->sbc->arg |= (1 << 24); +#endif + } + + if (msdc_command_start(host, mrq->sbc, 0, + CMD_TIMEOUT) != 0) + goto done; + + /* then wait command done */ + if (msdc_command_resp_polling(host, mrq->sbc, 0, + CMD_TIMEOUT) != 0) { + goto stop; + } + } else { + /* some sd card may not support cmd23, + * some emmc card have problem with cmd23, + so use cmd12 here */ + if (host->hw->host_function != MSDC_SDIO) + host->autocmd |= MSDC_AUTOCMD12; + } + } else { + /* enable auto cmd23 */ + if (mrq->sbc) { + host->autocmd &= ~MSDC_AUTOCMD12; + if (host->hw->host_function == MSDC_EMMC) { +#ifdef MTK_MSDC_USE_CACHE + if (!((mrq->sbc->arg >> 31) & 0x1) && + l_force_prg) + mrq->sbc->arg |= (1 << 24); +#endif + } + } else { + /* some sd card may not support cmd23, + * some emmc card have problem with cmd23, + so use cmd12 here */ + if (host->hw->host_function != MSDC_SDIO) { + host->autocmd &= ~MSDC_AUTOCMD23; + host->autocmd |= MSDC_AUTOCMD12; + l_card_no_cmd23 = 1; + } + } + } +#endif /* end of MTK_MSDC_USE_CMD23 */ + + read = data->flags & MMC_DATA_READ ? 1 : 0; + if (host->dma_xfer) { +#ifndef MTK_MSDC_USE_CMD23 + /* start the command first */ + if (host->hw->host_function != MSDC_SDIO) + host->autocmd |= MSDC_AUTOCMD12; +#endif + map_sg = msdc_rw_cmd_dma(mmc, cmd, data, mrq, 0); + if (map_sg == -1) + goto done; + else if (map_sg == -2) + goto stop; + + } else { + /* Turn off dma */ + if (is_card_sdio(host)) { + msdc_reset_hw(host->id); + msdc_dma_off(); + data->error = 0; + } + /* Firstly: send command */ + host->autocmd &= ~MSDC_AUTOCMD12; + + l_autocmd23_is_set = 0; + if (host->autocmd & MSDC_AUTOCMD23) { + l_autocmd23_is_set = 1; + host->autocmd &= ~MSDC_AUTOCMD23; + } + + host->dma_xfer = 0; + if (msdc_do_command(host, cmd, 0, CMD_TIMEOUT) != 0) + goto stop; + + /* Secondly: pio data phase */ + if (read) { +#ifdef MTK_MSDC_DUMP_FIFO + pr_debug("[%s]: start pio read\n", __func__); +#endif + if (msdc_pio_read(host, data)) { + msdc_gate_clock(host, 0); + msdc_ungate_clock(host); + goto stop; /* need cmd12 */ + } + } else { +#ifdef MTK_MSDC_DUMP_FIFO + pr_debug("[%s]: start pio write\n", __func__); +#endif + if (msdc_pio_write(host, data)) { + msdc_gate_clock(host, 0); + msdc_ungate_clock(host); + goto stop; + } + + /* For write case: make sure contents in fifo + flushed to device */ + + pio_tmo = jiffies + DAT_TIMEOUT; + while (1) { + left = msdc_txfifocnt(); + if (left == 0) + break; + + if (msdc_pio_abort(host, data, pio_tmo)) + break; + } + } + } + +stop: + /* pio mode will disable autocmd23 */ + if (l_autocmd23_is_set == 1) { + l_autocmd23_is_set = 0; + host->autocmd |= MSDC_AUTOCMD23; + } + +#ifndef MTK_MSDC_USE_CMD23 + /* Last: stop transfer */ + if (msdc_if_send_stop(host, cmd, data)) + goto done; + +#else + + if (host->hw->host_function == MSDC_EMMC) { + /* multi r/w with no cmd23 and no autocmd12, + need send cmd12 manual */ + /* if PIO mode and autocmd23 enable, cmd12 need send, + because autocmd23 is disable under PIO */ + if (!check_mmc_cmd2425(cmd->opcode)) + goto done; + if (((mrq->sbc == NULL) && + !(host->autocmd & MSDC_AUTOCMD12)) + || (!host->dma_xfer && mrq->sbc && + (host->autocmd & MSDC_AUTOCMD23))) { + if (msdc_do_command(host, data->stop, 0, + CMD_TIMEOUT) != 0) + goto done; + } + } else { + if (msdc_if_send_stop(host, cmd, data)) + goto done; + } +#endif +done: + +#ifdef MTK_MSDC_USE_CMD23 + /* for msdc use cmd23, but card not supported(sbc is NULL), + need enable autocmd23 for next request */ + if (1 == l_card_no_cmd23) { + if (host->hw->host_function != MSDC_SDIO) { + host->autocmd |= MSDC_AUTOCMD23; + host->autocmd &= ~MSDC_AUTOCMD12; + l_card_no_cmd23 = 0; + } + } +#endif + + if (data != NULL) { + host->data = NULL; + + if (host->dma_xfer != 0) { + host->dma_xfer = 0; + msdc_dma_off(); + host->dma.used_bd = 0; + host->dma.used_gpd = 0; + if (map_sg == 1) { + /*if (data->error == 0) { + int retry = 3; + int count = 1000; + msdc_retry(host->dma.gpd->hwo, retry, + count, host->id); + } */ + dma_unmap_sg(mmc_dev(mmc), data->sg, + data->sg_len, dir); + } + } + + /* If eMMC we use is in g_emmc_cache_quirk[] or + * MTK_MSDC_USE_CACHE is closed. Driver should return + * cache_size = 0 in exd_csd to mmc layer + * So, mmc_init_card can disable cache + */ + if ((cmd->opcode == MMC_SEND_EXT_CSD) && + (host->hw->host_function == MSDC_EMMC)) + msdc_cache_onoff(data); + + host->blksz = 0; + + msdc_log_cmd(host, cmd, data); + } + + if (mrq->cmd->error == (unsigned int)-EILSEQ) { + if (((cmd->opcode == MMC_SELECT_CARD) || + (cmd->opcode == MMC_SLEEP_AWAKE)) + && ((host->hw->host_function == MSDC_EMMC) || + (host->hw->host_function == MSDC_SD))) { + /* should be deleted in new platform, + as the state verify function has applied*/ + mrq->cmd->error = 0x0; + } else { + host->error |= REQ_CMD_EIO; + + if (mrq->cmd->opcode == SD_IO_RW_EXTENDED) + sdio_tune_flag |= 0x1; + } + } + + if (mrq->cmd->error == (unsigned int)-ETIMEDOUT) { + if (mrq->cmd->opcode == MMC_SLEEP_AWAKE) { + if (mrq->cmd->arg & 0x8000) { + pr_err("Sleep_Awake CMD timeout, MSDC_PS %0x\n", + MSDC_READ32(MSDC_PS)); + emmc_sleep_failed = 1; + mrq->cmd->error = 0x0; + pr_err("eMMC sleep CMD5 TMO will reinit\n"); + } else { + host->error |= REQ_CMD_TMO; + } + } else { + host->error |= REQ_CMD_TMO; + } + } + + if (mrq->data && mrq->data->error) { + host->error |= REQ_DAT_ERR; + sdio_tune_flag |= 0x10; + + if (mrq->data->flags & MMC_DATA_READ) + sdio_tune_flag |= 0x80; + else + sdio_tune_flag |= 0x40; + } + +#ifdef MTK_MSDC_USE_CMD23 + if (mrq->sbc && (mrq->sbc->error == (unsigned int)-EILSEQ)) + host->error |= REQ_CMD_EIO; + if (mrq->sbc && (mrq->sbc->error == (unsigned int)-ETIMEDOUT)) { +#ifdef CONFIG_MTK_AEE_FEATURE + aee_kernel_warning_api(__FILE__, __LINE__, + DB_OPT_NE_JBT_TRACES|DB_OPT_DISPLAY_HANG_DUMP, + "\n@eMMC FATAL ERROR@\n", "eMMC fatal error "); +#endif + host->error |= REQ_CMD_TMO; + } +#endif + + if (mrq->stop && (mrq->stop->error == (unsigned int)-EILSEQ)) + host->error |= REQ_STOP_EIO; + if (mrq->stop && (mrq->stop->error == (unsigned int)-ETIMEDOUT)) + host->error |= REQ_STOP_TMO; + +#ifdef SDIO_ERROR_BYPASS + if (is_card_sdio(host) && !host->error) + host->sdio_error = 0; +#endif + +#ifdef MTK_MSDC_USE_CACHE + msdc_update_cache_flush_status(host, mrq, data, l_bypass_flush); +#endif + + return host->error; +} + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT +static int msdc_do_discard_task_cq(struct mmc_host *mmc, + struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + u32 task_id; + + task_id = (mrq->sbc->arg >> 16) & 0x1f; + memset(&mmc->deq_cmd, 0, sizeof(struct mmc_command)); + mmc->deq_cmd.opcode = MMC_CMDQ_TASK_MGMT; + mmc->deq_cmd.arg = 2 | (task_id << 16); + mmc->deq_cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1B | MMC_CMD_AC; + mmc->deq_cmd.data = NULL; + msdc_do_command(host, &mmc->deq_cmd, 0, CMD_TIMEOUT); + + pr_debug("[%s]: msdc%d, discard task id %d, CMD<%d> arg<0x%08x> rsp<0x%08x>", + __func__, host->id, task_id, mmc->deq_cmd.opcode, mmc->deq_cmd.arg, mmc->deq_cmd.resp[0]); + + return mmc->deq_cmd.error; +} + +static int msdc_do_request_cq(struct mmc_host *mmc, + struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + struct mmc_data *data; +#ifdef MTK_MSDC_USE_CACHE + u32 l_force_prg = 0; +#endif + + BUG_ON(mmc == NULL); + BUG_ON(mrq == NULL); + BUG_ON(mrq->data); + + host->error = 0; + atomic_set(&host->abort, 0); + + cmd = mrq->sbc; + data = mrq->data; + + mrq->sbc->error = 0; + mrq->cmd->error = 0; + +#ifdef MTK_MSDC_USE_CACHE + /* check cache enabled, write direction */ + if (check_mmc_cache_ctrl(host->mmc->card) && + !((cmd->arg >> 30) & 0x1)) { + l_force_prg = !msdc_can_apply_cache(mrq->cmd->arg, cmd->arg & 0xffff); + /* check not reliable write */ + if (!((cmd->arg >> 31) & 0x1) && + l_force_prg) + cmd->arg |= (1 << 24); + } +#endif + + if (msdc_do_cmdq_command(host, cmd, 0, CMD_TIMEOUT) != 0) + goto done1; + +done1: + if (cmd->error == (unsigned int)-EILSEQ) + host->error |= REQ_CMD_EIO; + else if (cmd->error == (unsigned int)-ETIMEDOUT) + host->error |= REQ_CMD_TMO; + + cmd = mrq->cmd; + data = mrq->cmd->data; + + if (msdc_do_cmdq_command(host, cmd, 0, CMD_TIMEOUT) != 0) + goto done2; + +done2: + if (cmd->error == (unsigned int)-EILSEQ) + host->error |= REQ_CMD_EIO; + else if (cmd->error == (unsigned int)-ETIMEDOUT) + host->error |= REQ_CMD_TMO; + + return host->error; +} + +static int tune_cmdq_cmdrsp(struct mmc_host *mmc, + struct mmc_request *mrq, int *retry) +{ + struct msdc_host *host = mmc_priv(mmc); + void __iomem *base = host->base; + unsigned long polling_tmo = 0, polling_status_tmo; + + u32 err = 0, status = 0; + + /* time for wait device to return to trans state + when needed to send CMD48 */ + polling_status_tmo = jiffies + 30 * HZ; + + do { + err = msdc_get_card_status(mmc, host, &status); + if (err) { + /* wait for transfer done */ + polling_tmo = jiffies + 10 * HZ; + pr_err("msdc%d waiting data transfer done\n", + host->id); + while (mmc->is_data_dma) { + if (time_after(jiffies, polling_tmo)) { + ERR_MSG("waiting data transfer done TMO"); + msdc_dump_info(host->id); + msdc_dma_stop(host); + msdc_dma_clear(host); + msdc_reset_hw(host->id); + return -1; + } + } + + ERR_MSG("get card status, err = %d", err); +#ifdef MSDC_AUTOK_ON_ERROR + if (msdc_execute_tuning(mmc, MMC_SEND_STATUS)) { + ERR_MSG("failed to updata cmd para"); + return 1; + } +#else + if (msdc_tune_cmdrsp(host)) { + ERR_MSG("failed to updata cmd para"); + return 1; + } +#endif + continue; + } + + if (status & (1 << 22)) { + /* illegal command */ + (*retry)--; + ERR_MSG("status = %x, illegal command, retry = %d", + status, *retry); + if ((mrq->cmd->error || mrq->sbc->error) && *retry) + return 0; + else + return 1; + } else { + if (R1_CURRENT_STATE(status) != R1_STATE_TRAN) { + if (time_after(jiffies, polling_status_tmo)) + ERR_MSG("wait transfer state timeout\n"); + else { + err = 1; + continue; + } + } + ERR_MSG("status = %x, discard task, re-send command", + status); + err = msdc_do_discard_task_cq(mmc, mrq); + if (err == (unsigned int)-EIO) + continue; + else + break; + } + } while (err); + + /* wait for transfer done */ + polling_tmo = jiffies + 10 * HZ; + pr_err("msdc%d waiting data transfer done\n", host->id); + while (mmc->is_data_dma) { + if (time_after(jiffies, polling_tmo)) { + ERR_MSG("waiting data transfer done TMO"); + msdc_dump_info(host->id); + msdc_dma_stop(host); + msdc_dma_clear(host); + msdc_reset_hw(host->id); + return -1; + } + } + + if (msdc_execute_tuning(mmc, MMC_SEND_STATUS)) { + pr_err("msdc%d autok failed\n", host->id); + return 1; + } + + return 0; +} + +static int tune_cmdq_data(struct mmc_host *mmc, + struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + int ret = 0; + + if (mrq->cmd && (mrq->cmd->error == (unsigned int)-EILSEQ)) { + ret = msdc_tune_cmdrsp(host); + } else if (mrq->data && (mrq->data->error == (unsigned int)-EILSEQ)) { + if (host->timing == MMC_TIMING_MMC_HS400) { + ret = emmc_hs400_tune_rw(host); + } else if (host->timing == MMC_TIMING_MMC_HS200) { + if (mrq->data->flags & MMC_DATA_READ) + ret = msdc_tune_read(host); + else + ret = msdc_tune_write(host); + } + } + + return ret; +} +#endif + +static int msdc_tune_rw_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + struct mmc_data *data; + int ret; + +#ifdef MTK_MSDC_USE_CMD23 + u32 l_autocmd23_is_set = 0; +#endif + + BUG_ON(mmc == NULL || mrq == NULL); + + cmd = mrq->cmd; + data = mrq->cmd->data; + + msdc_do_request_prepare(host, mrq, cmd, data, NULL, + NULL, PREPARE_TUNE); + + if (host->hw->host_function != MSDC_SDIO) { + host->autocmd |= MSDC_AUTOCMD12; + +#ifdef MTK_MSDC_USE_CMD23 + /* disable autocmd23 in error tuning flow */ + l_autocmd23_is_set = 0; + if (host->autocmd & MSDC_AUTOCMD23) { + l_autocmd23_is_set = 1; + host->autocmd &= ~MSDC_AUTOCMD23; + } +#endif + } + + ret = msdc_rw_cmd_dma(mmc, cmd, data, mrq, 1); + if (ret == -1) + goto done; + else if (ret == -2) + goto stop; + +stop: + /* Last: stop transfer */ + if (msdc_if_send_stop(host, cmd, data)) + goto done; + +done: + msdc_dma_clear(host); + host->mrq = mrq; /* check this can be removed */ + + msdc_log_cmd(host, cmd, data); + + host->error = 0; + + msdc_if_set_err(host, mrq, cmd); + +#ifdef MTK_MSDC_USE_CMD23 + if (l_autocmd23_is_set == 1) { + /* restore the value */ + host->autocmd |= MSDC_AUTOCMD23; + } +#endif + return host->error; +} + +static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, + bool is_first_req) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_data *data; + struct mmc_command *cmd = mrq->cmd; + int read = 1, dir = DMA_FROM_DEVICE; + + BUG_ON(!cmd); + data = mrq->data; + + if (!data) + return; + + data->host_cookie = MSDC_COOKIE_ASYNC; + if (check_mmc_cmd1718(cmd->opcode) || + check_mmc_cmd2425(cmd->opcode)) { + host->xfer_size = data->blocks * data->blksz; + read = data->flags & MMC_DATA_READ ? 1 : 0; + if (drv_mode[host->id] == MODE_PIO) { + data->host_cookie |= MSDC_COOKIE_PIO; + msdc_latest_transfer_mode[host->id] = TRAN_MOD_PIO; + } else if (drv_mode[host->id] == MODE_DMA) { + msdc_latest_transfer_mode[host->id] = TRAN_MOD_DMA; + } else if (drv_mode[host->id] == MODE_SIZE_DEP) { + if (host->xfer_size < dma_size[host->id]) { + data->host_cookie |= MSDC_COOKIE_PIO; + msdc_latest_transfer_mode[host->id] = + TRAN_MOD_PIO; + } else { + msdc_latest_transfer_mode[host->id] = + TRAN_MOD_DMA; + } + } + if (msdc_use_async_dma(data->host_cookie)) { + dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + (void)dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, + dir); + } + N_MSG(OPS, "CMD<%d> ARG<0x%x> data<%s %s> blksz<%d> block<%d> error<%d>", + mrq->cmd->opcode, mrq->cmd->arg, + (data->host_cookie ? "dma" : "pio"), + (read ? "read " : "write"), data->blksz, + data->blocks, data->error); + } +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + else if (data && check_mmc_cmd4647(cmd->opcode)) { + read = data->flags & MMC_DATA_READ ? 1 : 0; + dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + (void)dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); + } +#endif +} + +static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, + int err) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_data *data; + /* struct mmc_command *cmd = mrq->cmd; */ + int dir = DMA_FROM_DEVICE; + + data = mrq->data; + if (data && (msdc_use_async_dma(data->host_cookie))) { +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (!mmc->card->ext_csd.cmdq_mode_en) +#endif + host->xfer_size = data->blocks * data->blksz; + dir = data->flags & MMC_DATA_READ ? + DMA_FROM_DEVICE : DMA_TO_DEVICE; + dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); + data->host_cookie = 0; + N_MSG(OPS, "CMD<%d> ARG<0x%x> blksz<%d> block<%d> error<%d>", + mrq->cmd->opcode, mrq->cmd->arg, data->blksz, + data->blocks, data->error); + } + data->host_cookie = 0; + +} + +static int msdc_do_request_async(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + struct mmc_data *data; + void __iomem *base = host->base; + +#ifdef MTK_MSDC_USE_CMD23 + u32 l_card_no_cmd23 = 0; +#endif + +#ifdef MTK_MSDC_USE_CACHE + u32 l_force_prg = 0; +#endif +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + u32 task_id; +#endif + + MVG_EMMC_DECLARE_INT32(delay_ns); + MVG_EMMC_DECLARE_INT32(delay_us); + MVG_EMMC_DECLARE_INT32(delay_ms); + + BUG_ON(mmc == NULL || mrq == NULL); + + if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) { + ERR_MSG("cmd<%d> arg<0x%x> card<%d> power<%d>", + mrq->cmd->opcode, mrq->cmd->arg, + is_card_present(host), host->power_mode); + mrq->cmd->error = (unsigned int)-ENOMEDIUM; + if (mrq->done) + mrq->done(mrq); /* call done directly. */ + return 0; + } + msdc_ungate_clock(host); + /*#if defined(MSDC_AUTOK_ON_ERROR)*/ + host->async_tuning_in_progress = false; + /*#endif*/ + + spin_lock(&host->lock); + + cmd = mrq->cmd; + data = mrq->cmd->data; + + host->mrq = mrq; + +#ifdef MTK_MSDC_USE_CACHE + if (msdc_do_request_prepare(host, mrq, cmd, data, &l_force_prg, + NULL, PREPARE_ASYNC)) + goto done; +#else + if (msdc_do_request_prepare(host, mrq, cmd, data, NULL, + NULL, PREPARE_ASYNC)) + goto done; +#endif + +#ifdef MTK_MSDC_USE_CMD23 + /* start the cmd23 first */ + if (mrq->sbc) { + host->autocmd &= ~MSDC_AUTOCMD12; + + if (host->hw->host_function == MSDC_EMMC) { +#ifdef MTK_MSDC_USE_CACHE + if (l_force_prg && !((mrq->sbc->arg >> 31) & 0x1)) + mrq->sbc->arg |= (1 << 24); +#endif + } + + if (0 == (host->autocmd & MSDC_AUTOCMD23)) { + if (msdc_command_start(host, mrq->sbc, 0, + CMD_TIMEOUT) != 0) + goto done; + + /* then wait command done */ + if (msdc_command_resp_polling(host, mrq->sbc, 0, + CMD_TIMEOUT) != 0) { + goto stop; + } + } + } else { + /* some sd card may not support cmd23, + * some emmc card have problem with cmd23, + so use cmd12 here */ + if (host->hw->host_function != MSDC_SDIO) { + host->autocmd |= MSDC_AUTOCMD12; + if (0 != (host->autocmd & MSDC_AUTOCMD23)) { + host->autocmd &= ~MSDC_AUTOCMD23; + l_card_no_cmd23 = 1; + } + } + } + +#else + /* start the command first*/ + if (host->hw->host_function != MSDC_SDIO) + host->autocmd |= MSDC_AUTOCMD12; +#endif /* end of MTK_MSDC_USE_CMD23 */ + + msdc_dma_on(); /* enable DMA mode first!! */ + /* init_completion(&host->xfer_done); */ + + if (msdc_command_start(host, cmd, 0, CMD_TIMEOUT) != 0) + goto done; + + /* then wait command done */ + if (msdc_command_resp_polling(host, cmd, 0, CMD_TIMEOUT) != 0) + goto stop; + + /* for read, the data coming too fast, then CRC error + start DMA no business with CRC. */ + msdc_dma_setup(host, &host->dma, data->sg, data->sg_len); + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + mmc->is_data_dma = 1; +#endif + + msdc_dma_start(host); + /*ERR_MSG("0.Power cycle enable(%d)",host->power_cycle_enable);*/ + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (check_mmc_cmd4647(cmd->opcode)) { + task_id = (cmd->arg >> 16) & 0x1f; + MVG_EMMC_WRITE_MATCH(host, + (u64)mmc->areq_que[task_id]->mrq_que->cmd->arg, + delay_ms, delay_us, delay_ns, + cmd->opcode, host->xfer_size); + } else +#endif + MVG_EMMC_WRITE_MATCH(host, (u64)cmd->arg, delay_ms, delay_us, delay_ns, + cmd->opcode, host->xfer_size); + + spin_unlock(&host->lock); + +#ifdef MTK_MSDC_USE_CMD23 + /* for msdc use cmd23, but card not supported(sbc is NULL), + need enable autocmd23 for next request */ + if (1 == l_card_no_cmd23) { + if (host->hw->host_function != MSDC_SDIO) { + host->autocmd |= MSDC_AUTOCMD23; + host->autocmd &= ~MSDC_AUTOCMD12; + l_card_no_cmd23 = 0; + } + } +#endif + +#ifdef MTK_MSDC_USE_CACHE + msdc_update_cache_flush_status(host, mrq, data, 1); +#endif + + return 0; + + +stop: +#ifndef MTK_MSDC_USE_CMD23 + /* Last: stop transfer */ + if (msdc_if_send_stop(host, cmd, data)) + goto done; +#else + + if (host->hw->host_function == MSDC_EMMC) { + /* error handle will do msdc_abort_data() */ + } else { + if (msdc_if_send_stop(host, cmd, data)) + goto done; + } +#endif + +done: +#ifdef MTK_MSDC_USE_CMD23 + /* for msdc use cmd23, but card not supported(sbc is NULL), + need enable autocmd23 for next request */ + if (1 == l_card_no_cmd23) { + if (host->hw->host_function != MSDC_SDIO) { + host->autocmd |= MSDC_AUTOCMD23; + host->autocmd &= ~MSDC_AUTOCMD12; + l_card_no_cmd23 = 0; + } + } +#endif + + msdc_dma_clear(host); + + msdc_log_cmd(host, cmd, data); + +#ifdef MTK_MSDC_USE_CMD23 + if (mrq->sbc && (mrq->sbc->error == (unsigned int)-EILSEQ)) + host->error |= REQ_CMD_EIO; + if (mrq->sbc && (mrq->sbc->error == (unsigned int)-ETIMEDOUT)) { +#ifdef CONFIG_MTK_AEE_FEATURE + aee_kernel_warning_api(__FILE__, __LINE__, + DB_OPT_NE_JBT_TRACES|DB_OPT_DISPLAY_HANG_DUMP, + "\n@eMMC FATAL ERROR@\n", "eMMC fatal error "); +#endif + host->error |= REQ_CMD_TMO; + } +#endif + + msdc_if_set_err(host, mrq, cmd); + +#ifdef MTK_MSDC_USE_CACHE + msdc_update_cache_flush_status(host, mrq, data, 1); +/*end2:*/ +#endif + + if (!host->async_tuning_in_progress +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + && !host->mmc->card->ext_csd.cmdq_mode_en +#endif + ) { + if (data && data->error) { + #ifndef MSDC_WQ_ERROR_TUNE + if (data->flags & MMC_DATA_WRITE) + host->err_mrq_dir |= MMC_DATA_WRITE; + else if (data->flags & MMC_DATA_READ) + host->err_mrq_dir |= MMC_DATA_READ; + #endif + host->async_tuning_done = false; + } + if (cmd->error == (unsigned int)-EILSEQ) + host->async_tuning_done = false; + #ifndef MSDC_WQ_ERROR_TUNE + if (!host->async_tuning_done && + (host->hw->host_function == MSDC_SD)) { + /* fake as bus_dead to prevent from + power cycle */ + host->mmc->bus_dead = 1; + } + #endif + } + + if (mrq->done) + mrq->done(mrq); + + msdc_gate_clock(host, 1); + spin_unlock(&host->lock); + return host->error; +} + +/* #define TUNE_FLOW_TEST */ +#ifdef TUNE_FLOW_TEST +static void msdc_reset_para(struct msdc_host *host) +{ + void __iomem *base = host->base; + u32 dsmpl, rsmpl, clkmode; + int hs400 = 0; + + /* because we have a card, which must work at dsmpl<0> and rsmpl<0> */ + + MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_R_D_SMPL, dsmpl); + MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, rsmpl); + MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clkmode); + hs400 = (clkmode == 3) ? 1 : 0; + + if (dsmpl == 0) { + msdc_set_smpl(host, clkmode, 1, TYPE_READ_DATA_EDGE, NULL); + ERR_MSG("set dspl<0>"); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_CMDRDLY, 0); + } + + if (rsmpl == 0) { + msdc_set_smpl(host, clkmode, 1, TYPE_CMD_RESP_EDGE, NULL); + ERR_MSG("set rspl<0>"); + MSDC_WRITE32(MSDC_DAT_RDDLY0, 0); + MSDC_SET_FIELD(MSDC_PAD_TUNE0, MSDC_PAD_TUNE0_DATWRDLY, 0); + } +} +#endif + +static void msdc_dump_trans_error(struct msdc_host *host, + struct mmc_command *cmd, + struct mmc_data *data, + struct mmc_command *stop, + struct mmc_command *sbc) +{ + if ((cmd->opcode == 52) && (cmd->arg == 0xc00)) + return; + if ((cmd->opcode == 52) && (cmd->arg == 0x80000c08)) + return; + + if (!(is_card_sdio(host) || (host->hw->flags & MSDC_SDIO_IRQ))) { + /* by pass the SDIO CMD TO for SD/eMMC */ + if ((host->hw->host_function == MSDC_SD) && + (cmd->opcode == 5)) + return; + } else { + if (cmd->opcode == 8) + return; + } + + ERR_MSG("XXX CMD<%d><0x%x> Error<%d> Resp<0x%x>", cmd->opcode, cmd->arg, + cmd->error, cmd->resp[0]); + + if (data) { + ERR_MSG("XXX DAT block<%d> Error<%d>", data->blocks, + data->error); + } + if (stop) { + ERR_MSG("XXX STOP<%d><0x%x> Error<%d> Resp<0x%x>", + stop->opcode, stop->arg, stop->error, stop->resp[0]); + } + + if (sbc) { + ERR_MSG("XXX SBC<%d><0x%x> Error<%d> Resp<0x%x>", + sbc->opcode, sbc->arg, sbc->error, sbc->resp[0]); + } + + if ((host->hw->host_function == MSDC_SD) + && (host->sclk > 100000000) + && (data) + && (data->error != (unsigned int)-ETIMEDOUT)) { + if ((data->flags & MMC_DATA_WRITE) && + (host->write_timeout_uhs104)) + host->write_timeout_uhs104 = 0; + if ((data->flags & MMC_DATA_READ) && + (host->read_timeout_uhs104)) + host->read_timeout_uhs104 = 0; + } + + if ((host->hw->host_function == MSDC_EMMC) && + (data) && + (data->error != (unsigned int)-ETIMEDOUT)) { + if ((data->flags & MMC_DATA_WRITE) && + (host->write_timeout_emmc)) + host->write_timeout_emmc = 0; + if ((data->flags & MMC_DATA_READ) && + (host->read_timeout_emmc)) + host->read_timeout_emmc = 0; + } +#ifdef SDIO_ERROR_BYPASS + if (is_card_sdio(host) && + (host->sdio_error != -EILSEQ) && + (cmd->opcode == 53) && + (msdc_sg_len(data->sg, host->dma_xfer) > 4)) { + host->sdio_error = -EILSEQ; + ERR_MSG("XXX SDIO Error ByPass"); + } +#endif +} + +static void msdc_do_request_with_retry(struct msdc_host *host, + struct mmc_request *mrq, + struct mmc_command *cmd, + struct mmc_data *data, + struct mmc_command *stop, + struct mmc_command *sbc, + int async) +{ + struct mmc_host *mmc = host->mmc; + + do { + if (!async) { + if (!msdc_do_request(host->mmc, mrq)) + break; + } + /* there is some error*/ + /* because ISR executing time will be monitor, + try to dump info here.*/ + if (cmd->opcode != 19) + msdc_dump_trans_error(host, cmd, data, stop, sbc); + + if (is_card_sdio(host) || (host->hw->flags & MSDC_SDIO_IRQ)) { + /* sdio will tune*/ + return; + } + + if (host->legacy_tuning_in_progress) + return; + + #ifdef MSDC_AUTOK_ON_ERROR /*define as 0 if runtime tune is used */ + if (mmc->ios.timing != MMC_TIMING_LEGACY + && mmc->ios.timing != MMC_TIMING_SD_HS + && mmc->ios.timing != MMC_TIMING_UHS_DDR50) { + if (!host->legacy_tuning_in_progress) { + if ((cmd->error == (unsigned int)-EILSEQ) + || (sbc && (sbc->error == (unsigned int)-EILSEQ)) + || (stop && (stop->error == (unsigned int)-EILSEQ)) + || (data && data->error)) { + host->legacy_tuning_done = false; + } + + return; + } + } + #endif + +#ifdef MTK_MSDC_USE_CMD23 + if ((sbc != NULL) && + (sbc->error == (unsigned int)-ETIMEDOUT)) { + if (check_mmc_cmd1825(cmd->opcode)) { + /* not tuning, go out directly */ + pr_err("===[%s:%d]==cmd23 timeout==\n", + __func__, __LINE__); + return; + } + } +#endif + + if (msdc_crc_tune(host, cmd, data, stop, sbc)) + return; + + /* CMD TO -> not tuning */ + if (!async) { + if (cmd->error == (unsigned int)-ETIMEDOUT && + !check_mmc_cmd2425(cmd->opcode) && + !check_mmc_cmd1718(cmd->opcode)) + return; + } + + if (cmd->error == (unsigned int)-ENOMEDIUM) + return; + + if (msdc_data_timeout_tune(host, data)) { + if (host->power_cycle >= MSDC_MAX_POWER_CYCLE) { + cmd->error = (unsigned int)-ENOMEDIUM; + data->error = (unsigned int)-ENOMEDIUM; + pr_err("msdc1, data timeout out of limits, return -ENOMEDIUM\n"); + } + return; + } + + /* clear the error condition. */ + cmd->error = 0; + if (data) + data->error = 0; + if (stop) + stop->error = 0; + +#ifdef MTK_MSDC_USE_CMD23 + if (sbc) + sbc->error = 0; +#endif + + /* check if an app commmand. */ + if (!async && host->app_cmd) { + while (msdc_app_cmd(host->mmc, host)) { + if (msdc_tune_cmdrsp(host)) { + ERR_MSG("failed to updata cmd para for app"); + return; + } + } + } + + if (async) + host->sw_timeout = 0; + + if (!is_card_present(host)) + return; + + if (async) { + if (!msdc_tune_rw_request(host->mmc, mrq)) + break; + } + } while (1); + + if (async) { + if ((host->rwcmd_time_tune) + && (check_mmc_cmd1718(cmd->opcode) || + check_mmc_cmd2425(cmd->opcode))) { + host->rwcmd_time_tune = 0; + ERR_MSG("RW cmd recover"); + msdc_dump_trans_error(host, cmd, data, stop, sbc); + } + } + if ((host->read_time_tune) + && check_mmc_cmd1718(cmd->opcode)) { + host->read_time_tune = 0; + ERR_MSG("Read recover"); + msdc_dump_trans_error(host, cmd, data, stop, sbc); + } + if ((host->write_time_tune) + && check_mmc_cmd2425(cmd->opcode)) { + host->write_time_tune = 0; + ERR_MSG("Write recover"); + msdc_dump_trans_error(host, cmd, data, stop, sbc); + } + + if (async) + host->power_cycle_enable = 1; + + host->sw_timeout = 0; + +} + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT +static int msdc_do_cmdq_request_with_retry(struct msdc_host *host, + struct mmc_request *mrq) +{ + struct mmc_host *mmc; + struct mmc_command *cmd; + struct mmc_data *data; + struct mmc_command *stop = NULL; + int ret = 0, retry; + + mmc = host->mmc; + cmd = mrq->cmd; + data = mrq->cmd->data; + if (data) + stop = data->stop; + + retry = 5; + while (msdc_do_request_cq(mmc, mrq)) { + msdc_dump_trans_error(host, cmd, data, stop, mrq->sbc); + if ((cmd->error == (unsigned int)-EILSEQ) || + (cmd->error == (unsigned int)-ETIMEDOUT) || + (mrq->sbc->error == (unsigned int)-EILSEQ) || + (mrq->sbc->error == (unsigned int)-ETIMEDOUT)) { + ret = tune_cmdq_cmdrsp(mmc, mrq, &retry); + if (ret) + return ret; + } else { + ERR_MSG("CMD44 and CMD45 error - error %d %d", + mrq->sbc->error, cmd->error); + break; + } + } + + return ret; +} +#endif + +/* ops.request */ +static void msdc_ops_request_legacy(struct mmc_host *mmc, + struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + struct mmc_data *data; + struct mmc_command *stop = NULL; + struct mmc_command *sbc = NULL; + /* === for sdio profile === */ + u32 old_H32 = 0, old_L32 = 0, new_H32 = 0, new_L32 = 0; + u32 ticks = 0, opcode = 0, sizes = 0, bRx = 0; +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + int ret; +#endif + + msdc_reset_crc_tune_counter(host, all_counter); +#ifndef CONFIG_MTK_EMMC_CQ_SUPPORT + if (host->mrq) { + ERR_MSG("XXX host->mrq<0x%p> cmd<%d>arg<0x%x>", host->mrq, + host->mrq->cmd->opcode, host->mrq->cmd->arg); + BUG(); + } +#endif + + if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) { + ERR_MSG("cmd<%d> arg<0x%x> card<%d> power<%d>", + mrq->cmd->opcode, mrq->cmd->arg, + is_card_present(host), host->power_mode); + mrq->cmd->error = (unsigned int)-ENOMEDIUM; + + if (mrq->done) + mrq->done(mrq); /* call done directly. */ + + return; + } + + /* start to process */ + spin_lock(&host->lock); + host->power_cycle_enable = 1; + + cmd = mrq->cmd; + data = mrq->cmd->data; + if (data) + stop = data->stop; + +#ifdef MTK_MSDC_USE_CMD23 + if (data) + sbc = mrq->sbc; +#endif + + msdc_ungate_clock(host); /* set sw flag */ + + if (sdio_pro_enable) { + /*=== for sdio profile ===*/ + if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) + ; /*GPT_GetCounter64(&old_L32, &old_H32);*/ + } + +#ifndef CONFIG_MTK_EMMC_CQ_SUPPORT + host->mrq = mrq; +#endif + +#ifndef MSDC_WQ_ERROR_TUNE + /* FIX ME: add CMDQ-related code similar to else part */ + if (msdc_do_request(host->mmc, mrq)) { + if (!host->legacy_tuning_in_progress) + msdc_dump_trans_error(host, cmd, data, stop, sbc); + if (data && data->error) { + if (data->flags & MMC_DATA_WRITE) + host->err_mrq_dir |= MMC_DATA_WRITE; + else if (data->flags & MMC_DATA_READ) + host->err_mrq_dir |= MMC_DATA_READ; + host->legacy_tuning_done = false; + } + if (cmd && (cmd->error == (unsigned int)-EILSEQ)) + host->legacy_tuning_done = false; + if (!host->legacy_tuning_done && + (host->hw->host_function == MSDC_SD)) { + /* fake as bus_dead to prevent from + power cycle */ + host->mmc->bus_dead = 1; + } + } +#else + + #ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (check_mmc_cmd44(mrq->sbc)) { + ret = msdc_do_cmdq_request_with_retry(host, mrq); + } else { + /* only CMD0/CMD12/CMD13 can be send + when non-empty queue @ CMDQ on */ + if (mmc->card && mmc->card->ext_csd.cmdq_mode_en + && atomic_read(&mmc->areq_cnt) + && !check_mmc_cmd01213(cmd->opcode) + && !check_mmc_cmd48(cmd->opcode)) { + ERR_MSG("[%s][WARNING] CMDQ on, sending CMD%d\n", + __func__, cmd->opcode); + } + if (!check_mmc_cmd13_sqs(mrq->cmd)) + host->mrq = mrq; + #endif + msdc_do_request_with_retry(host, mrq, cmd, data, stop, sbc, 0); + + #ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + } + #endif + msdc_reset_crc_tune_counter(host, all_counter); +#endif + +#ifdef MTK_MSDC_USE_CACHE + msdc_check_cache_flush_error(host, cmd); +#endif + +#ifdef TUNE_FLOW_TEST + if (!is_card_sdio(host)) + msdc_reset_para(host); +#endif + + /* ==== when request done, check if app_cmd ==== */ + if (mrq->cmd->opcode == MMC_APP_CMD) { + host->app_cmd = 1; + host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */ + } else { + host->app_cmd = 0; + /* host->app_cmd_arg = 0; */ + } + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (!(check_mmc_cmd13_sqs(mrq->cmd) + || check_mmc_cmd44(mrq->sbc))) { + /* if not CMDQ CMD44/45 or CMD13, follow orignal flow to clear host->mrq + if it's CMD44/45 or CMD13 QSR, host->mrq may be CMD46,47 */ + host->mrq = NULL; + } +#else + host->mrq = NULL; +#endif + + /* === for sdio profile === */ + if (sdio_pro_enable) { + if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { + /* GPT_GetCounter64(&new_L32, &new_H32); */ + ticks = msdc_time_calc(old_L32, old_H32, + new_L32, new_H32); + + opcode = mrq->cmd->opcode; + if (mrq->cmd->data) { + sizes = mrq->cmd->data->blocks * + mrq->cmd->data->blksz; + bRx = mrq->cmd->data->flags & MMC_DATA_READ ? + 1 : 0; + } else { + bRx = mrq->cmd->arg & 0x80000000 ? 1 : 0; + } + + if (!mrq->cmd->error) + msdc_performance(opcode, sizes, bRx, ticks); + } + } + + msdc_gate_clock(host, 1); /* clear flag. */ + spin_unlock(&host->lock); + + mmc_request_done(mmc, mrq); + + return; +} + +#ifdef MSDC_WQ_ERROR_TUNE +static void msdc_tune_async_request(struct mmc_host *mmc, + struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + struct mmc_data *data; + struct mmc_command *stop = NULL; + struct mmc_command *sbc = NULL; + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (mmc->card->ext_csd.cmdq_mode_en == 1 + && (atomic_read(&mmc->cq_tuning_now) == 1)) { + tune_cmdq_data(mmc, mrq); + return; + } +#endif + + /* msdc_reset_crc_tune_counter(host,all_counter) */ + if (host->mrq) { +#ifdef CONFIG_MTK_AEE_FEATURE + aee_kernel_warning("MSDC", + "MSDC request not clear.\n host attached<0x%p> current<0x%p>.\n", + host->mrq, mrq); +#else + WARN_ON(host->mrq); +#endif + ERR_MSG("XXX host->mrq<0x%p> cmd<%d>arg<0x%x>", host->mrq, + host->mrq->cmd->opcode, host->mrq->cmd->arg); + if (host->mrq->data) { + ERR_MSG("XXX request data size<%d>", + host->mrq->data->blocks * + host->mrq->data->blksz); + ERR_MSG("XXX request attach to host force data timeout and retry"); + host->mrq->data->error = (unsigned int)-ETIMEDOUT; + } else { + ERR_MSG("XXX request attach to host force cmd timeout and retry"); + host->mrq->cmd->error = (unsigned int)-ETIMEDOUT; + } + ERR_MSG("XXX current request <0x%p> cmd<%d>arg<0x%x>", + mrq, mrq->cmd->opcode, mrq->cmd->arg); + if (mrq->data) + ERR_MSG("XXX current request data size<%d>", + mrq->data->blocks * mrq->data->blksz); + } + + if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) { + ERR_MSG("cmd<%d> arg<0x%x> card<%d> power<%d>", + mrq->cmd->opcode, mrq->cmd->arg, + is_card_present(host), host->power_mode); + mrq->cmd->error = (unsigned int)-ENOMEDIUM; + /* should call done for this request */ + goto done; + } + + cmd = mrq->cmd; + data = mrq->cmd->data; + + if (data) + stop = data->stop; +#ifdef MTK_MSDC_USE_CMD23 + if (data) + sbc = mrq->sbc; +#endif + + /* start to process */ + spin_lock(&host->lock); + + msdc_ungate_clock(host); /* set sw flag */ + /*#if defined(MSDC_AUTOK_ON_ERROR)*/ + host->async_tuning_in_progress = true; + /*#endif*/ + host->mrq = mrq; + + msdc_do_request_with_retry(host, mrq, cmd, data, stop, sbc, 1); + + if (host->sclk <= 50000000 + && (host->timing != MMC_TIMING_MMC_DDR52) + && (host->timing != MMC_TIMING_UHS_DDR50)) + host->sd_30_busy = 0; + msdc_reset_crc_tune_counter(host, all_counter); + host->mrq = NULL; + msdc_gate_clock(host, 1); /* clear flag. */ + /*#if defined(MSDC_AUTOK_ON_ERROR)*/ + host->async_tuning_in_progress = false; + /*#endif*/ + spin_unlock(&host->lock); + +done: + host->mrq_tune = NULL; + mmc_request_done(mmc, mrq); +} + +static void msdc_async_tune(struct work_struct *work) +{ + struct msdc_host *host = NULL; + struct mmc_host *mmc = NULL; + + host = container_of(work, struct msdc_host, work_tune); + BUG_ON(!host || !host->mmc); + mmc = host->mmc; + + msdc_tune_async_request(mmc, host->mrq_tune); +} +#endif + +int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode) +{ + struct msdc_host *host = mmc_priv(mmc); + + host->legacy_tuning_in_progress = true; + /*host->async_tuning_in_progress = true;*/ + + msdc_init_tune_path(host, mmc->ios.timing); + + msdc_ungate_clock(host); + + #if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /*comment out temporarily before PMIC migration done*/ + /*pmic_force_vcore_pwm(true);*/ + #endif + + if (host->hw->host_function == MSDC_SD) { + if (mmc->ios.timing == MMC_TIMING_UHS_SDR104 || + mmc->ios.timing == MMC_TIMING_UHS_SDR50) { + if (host->is_autok_done == 0) { + pr_err("[AUTOK]SD Autok\n"); + autok_execute_tuning(host, sd_autok_res[AUTOK_VCORE_HIGH]); + host->is_autok_done = 1; + } else { + autok_init_sdr104(host); + autok_tuning_parameter_init(host, sd_autok_res[AUTOK_VCORE_HIGH]); + } + } + } else if (host->hw->host_function == MSDC_EMMC) { + #ifdef MSDC_HQA + msdc_HQA_set_vcore(host); + #endif + + if (mmc->ios.timing == MMC_TIMING_MMC_HS200) { + if (opcode == MMC_SEND_STATUS) { + pr_err("[AUTOK]eMMC HS200 Tune CMD only\n"); + hs200_execute_tuning_cmd(host, NULL); + } else { + pr_err("[AUTOK]eMMC HS200 Tune\n"); + hs200_execute_tuning(host, NULL); + } + } else if (mmc->ios.timing == MMC_TIMING_MMC_HS400) { + if (opcode == MMC_SEND_STATUS) { + pr_err("[AUTOK]eMMC HS400 Tune CMD only\n"); + hs400_execute_tuning_cmd(host, NULL); + } else { + pr_err("[AUTOK]eMMC HS400 Tune\n"); + hs400_execute_tuning(host, NULL); + } + } + } else if (host->hw->host_function == MSDC_SDIO) { + /* Default autok result is not exist, always excute tuning */ + if (sdio_autok_res_apply(host, AUTOK_VCORE_HIGH) != 0) { + pr_err("sdio autok result not exist!, excute tuning\n"); + if (host->is_autok_done == 0) { + pr_err("[AUTOK]SDIO SDR104 Tune\n"); + /* Wait DFVS ready for excute autok here */ + sdio_autok_wait_dvfs_ready(); + + /* Performance mode, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_SDIO, OPPI_PERF) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n"); + autok_execute_tuning(host, sdio_autok_res[AUTOK_VCORE_HIGH]); + + #ifdef SDIO_FIX_VCORE_CONDITIONAL + /* Low power mode, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_SDIO, OPPI_LOW_PWR) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n"); + autok_execute_tuning(host, sdio_autok_res[AUTOK_VCORE_LOW]); + + if (autok_res_check(sdio_autok_res[AUTOK_VCORE_HIGH], sdio_autok_res[AUTOK_VCORE_LOW]) + == 0) { + pr_err("[AUTOK] No need change para when dvfs\n"); + } else { + pr_err("[AUTOK] Need change para when dvfs or lock dvfs\n"); + sdio_lock_dvfs = 1; + } + #else + /* SDIO E2 */ + if (sdio_version(host) == 2) { + sdio_set_vcorefs_sram(AUTOK_VCORE_HIGH, 0, host); + /* Low power mode, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_SDIO, OPPI_LOW_PWR) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n"); + autok_execute_tuning(host, sdio_autok_res[AUTOK_VCORE_LOW]); + sdio_set_vcorefs_sram(AUTOK_VCORE_LOW, 1, host); + } + #endif + + /* Un-request, return 0 pass */ + if (vcorefs_request_dvfs_opp(KIR_AUTOK_SDIO, OPPI_UNREQ) != 0) + pr_err("vcorefs_request_dvfs_opp@OPPI_UNREQ fail!\n"); + + host->is_autok_done = 1; + complete(&host->autok_done); + } else { + autok_init_sdr104(host); + autok_tuning_parameter_init(host, sdio_autok_res[AUTOK_VCORE_HIGH]); + } + } else { + autok_init_sdr104(host); + + #ifdef SDIO_FIX_VCORE_CONDITIONAL + if (autok_res_check(sdio_autok_res[AUTOK_VCORE_HIGH], sdio_autok_res[AUTOK_VCORE_LOW]) == 0) { + pr_err("[AUTOK] No need change para when dvfs\n"); + } else { + pr_err("[AUTOK] Need change para when dvfs or lock dvfs\n"); + sdio_lock_dvfs = 1; + } + #else + /* SDIO E2 */ + if (sdio_version(host) == 2) { + sdio_set_vcorefs_sram(AUTOK_VCORE_HIGH, 0, host); + if (sdio_autok_res_apply(host, AUTOK_VCORE_LOW) == 0) + sdio_set_vcorefs_sram(AUTOK_VCORE_LOW, 1, host); + } + #endif + + if (host->is_autok_done == 0) { + host->is_autok_done = 1; + complete(&host->autok_done); + } + } + } + host->legacy_tuning_in_progress = false; + host->legacy_tuning_done = true; + host->first_tune_done = 1; + + #if !defined(CONFIG_MTK_PMIC_CHIP_MT6353) + /*comment out temporarily before PMIC migration done*/ + /*pmic_force_vcore_pwm(false);*/ + #endif + + msdc_gate_clock(host, 1); + + return 0; +} + +static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct mmc_data *data; + int host_cookie = 0; + struct msdc_host *host = mmc_priv(mmc); + BUG_ON(mmc == NULL || mrq == NULL); + + if ((host->hw->host_function == MSDC_SDIO) && + !(host->trans_lock.active)) + __pm_stay_awake(&host->trans_lock); + + /* 6630 in msdc2 and SDIO need lock dvfs */ + if ((host->id == 2) && (sdio_lock_dvfs == 1)) + sdio_set_vcore_performance(host, 1); + + data = mrq->data; + if (data) + host_cookie = data->host_cookie; + + /* Asyn only support DMA and asyc CMD flow */ + if (msdc_use_async_dma(host_cookie)) { + #if defined(MSDC_AUTOK_ON_ERROR) + if (!host->async_tuning_in_progress && + !host->async_tuning_done) { +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (host->mmc->card->ext_csd.cmdq_mode_en) + ERR_MSG("[%s][ERROR] CMDQ on, not support async tuning", + __func__); +#endif + if (mmc->ios.timing == MMC_TIMING_UHS_SDR104 || + mmc->ios.timing == MMC_TIMING_UHS_SDR50) { + msdc_execute_tuning(mmc, + MMC_SEND_TUNING_BLOCK); + } else if (mmc->ios.timing == MMC_TIMING_MMC_HS200 || + mmc->ios.timing == MMC_TIMING_MMC_HS400) { + msdc_execute_tuning(mmc, + MMC_SEND_TUNING_BLOCK_HS200); + #ifndef MSDC_WQ_ERROR_TUNE + } else { + /* Only tuning smpl on:MMC_TIMING_LEGACY + * MMC_TIMING_MMC_HS MMC_TIMING_SD_HS + * MMC_TIMING_UHS_SDR12 MMC_TIMING_UHS_SDR25 + * MMC_TIMING_UHS_DDR50 MMC_TIMING_MMC_DDR52 + */ + if (msdc_tuning_wo_autok(host)) + pr_err("msdc%d tuning smpl failed\n", + host->id); + if (host->mmc->bus_dead) + host->mmc->bus_dead = 0; + #endif + } + host->async_tuning_in_progress = false; + host->async_tuning_done = true; + } + #endif + msdc_do_request_async(mmc, mrq); + } else { + if (!host->legacy_tuning_in_progress + && !host->legacy_tuning_done) { + if (mmc->ios.timing == MMC_TIMING_UHS_SDR104 || + mmc->ios.timing == MMC_TIMING_UHS_SDR50) { + msdc_execute_tuning(mmc, + MMC_SEND_TUNING_BLOCK); + } else if (mmc->ios.timing == MMC_TIMING_MMC_HS200 || + mmc->ios.timing == MMC_TIMING_MMC_HS400) { +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + if (host->error == REQ_CMD_EIO) { + msdc_execute_tuning(mmc, MMC_SEND_STATUS); + host->error &= ~REQ_CMD_EIO; + } else +#endif + { + msdc_execute_tuning(mmc, + MMC_SEND_TUNING_BLOCK_HS200); + } + #ifndef MSDC_WQ_ERROR_TUNE + } else { + /* Only tuning smpl on:MMC_TIMING_LEGACY + * MMC_TIMING_MMC_HS MMC_TIMING_SD_HS + * MMC_TIMING_UHS_SDR12 MMC_TIMING_UHS_SDR25 + * MMC_TIMING_UHS_DDR50 MMC_TIMING_MMC_DDR52 + */ + if (msdc_tuning_wo_autok(host)) + pr_err("msdc%d tuning smpl failed\n", + host->id); + if (host->mmc->bus_dead) + host->mmc->bus_dead = 0; + #endif + } + } + msdc_ops_request_legacy(mmc, mrq); + } + + /* 6630 in msdc2 and SDIO need lock dvfs */ + if ((host->id == 2) && (sdio_lock_dvfs == 1)) + sdio_set_vcore_performance(host, 0); + + if ((host->hw->host_function == MSDC_SDIO) && (host->trans_lock.active)) + __pm_relax(&host->trans_lock); + + return; +} + + +/* called by ops.set_ios */ +static void msdc_set_buswidth(struct msdc_host *host, u32 width) +{ + void __iomem *base = host->base; + u32 val = MSDC_READ32(SDC_CFG); + + val &= ~SDC_CFG_BUSWIDTH; + + switch (width) { + default: + case MMC_BUS_WIDTH_1: + val |= (MSDC_BUS_1BITS << 16); + break; + case MMC_BUS_WIDTH_4: + val |= (MSDC_BUS_4BITS << 16); + break; + case MMC_BUS_WIDTH_8: + val |= (MSDC_BUS_8BITS << 16); + break; + } + + MSDC_WRITE32(SDC_CFG, val); +} + +/* called by msdc_drv_probe */ +static void msdc_init_hw(struct msdc_host *host) +{ + void __iomem *base = host->base; + struct msdc_hw *hw = host->hw; + + /* Power on */ + /*msdc_pin_reset(host, MSDC_PIN_PULL_UP, 0);*/ + + msdc_ungate_clock(host); + + /* Configure to MMC/SD mode */ + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); + + /* Reset */ + msdc_reset_hw(host->id); + + /* Disable card detection */ + MSDC_CLR_BIT32(MSDC_PS, MSDC_PS_CDEN); + + /* Disable and clear all interrupts */ + MSDC_CLR_BIT32(MSDC_INTEN, MSDC_READ32(MSDC_INTEN)); + MSDC_WRITE32(MSDC_INT, MSDC_READ32(MSDC_INT)); + + /* reset tuning parameter */ + msdc_init_tune_setting(host); + + /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO + in pre-loader,uboot,kernel drivers. + SDC_CFG.SDIO_INT_DET_EN will be only set when kernel driver wants + to use SDIO bus interrupt */ + /* Enable SDIO mode. it's must otherwise sdio cmd5 failed */ + MSDC_SET_BIT32(SDC_CFG, SDC_CFG_SDIO); + + /* disable detect SDIO device interrupt function */ + if (host->hw->flags & MSDC_SDIO_IRQ) { + ghost = host; + /* enable sdio detection */ + MSDC_SET_BIT32(SDC_CFG, SDC_CFG_SDIOIDE); + } else { + MSDC_CLR_BIT32(SDC_CFG, SDC_CFG_SDIOIDE); + } + + msdc_set_smt(host, 1); + msdc_set_driving(host, hw, 0); + /*msdc_set_pin_mode(host);*/ + /*msdc_set_ies(host, 1);*/ + + /* write crc timeout detection */ + MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_DETWR_CRCTMO, 1); + + /* Configure to default data timeout */ + MSDC_SET_FIELD(SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC); + + msdc_set_buswidth(host, MMC_BUS_WIDTH_1); + + msdc_gate_clock(host, 1); + + N_MSG(FUC, "init hardware done!"); +} + +/* ops.set_ios */ +static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct msdc_host *host = mmc_priv(mmc); + struct msdc_hw *hw = host->hw; + + spin_lock(&host->lock); + + msdc_ungate_clock(host); + + if (host->power_mode != ios->power_mode) { + switch (ios->power_mode) { + case MMC_POWER_OFF: + case MMC_POWER_UP: + spin_unlock(&host->lock); + msdc_init_hw(host); + msdc_set_power_mode(host, ios->power_mode); + spin_lock(&host->lock); + break; + case MMC_POWER_ON: + default: + break; + } + host->power_mode = ios->power_mode; + } + + if (host->bus_width != ios->bus_width) { + msdc_set_buswidth(host, ios->bus_width); + host->bus_width = ios->bus_width; + } + + if (msdc_clock_src[host->id] != hw->clk_src) { + hw->clk_src = msdc_clock_src[host->id]; + msdc_select_clksrc(host, hw->clk_src); + } + + if (host->mclk != ios->clock || host->timing != ios->timing) { + /* not change when clock Freq. + not changed state need set clock*/ + if (ios->clock > 100000000) + msdc_set_driving(host, hw, 1); + + /* Moved into msdc_ios_tune_setting(mmc, ios); */ + /*msdc_set_mclk(host, ios->timing, ios->clock);*/ + + msdc_ios_tune_setting(mmc, ios); + host->timing = ios->timing; + } + + msdc_gate_clock(host, 1); + spin_unlock(&host->lock); +} + +/* ops.get_ro */ +static int msdc_ops_get_ro(struct mmc_host *mmc) +{ + struct msdc_host *host = mmc_priv(mmc); + void __iomem *base = host->base; + unsigned long flags; + int ro = 0; + + spin_lock_irqsave(&host->lock, flags); + msdc_ungate_clock(host); + if (host->hw->flags & MSDC_WP_PIN_EN) + ro = (MSDC_READ32(MSDC_PS) >> 31); + msdc_gate_clock(host, 1); + spin_unlock_irqrestore(&host->lock, flags); + return ro; +} + +/* ops.get_cd */ +static int msdc_ops_get_cd(struct mmc_host *mmc) +{ + struct msdc_host *host = mmc_priv(mmc); + /* unsigned long flags; */ + int level = 0; + + /* spin_lock_irqsave(&host->lock, flags); */ + + /* for sdio, depends on USER_RESUME */ + if (is_card_sdio(host) && !(host->hw->flags & MSDC_SDIO_IRQ)) { + host->card_inserted = + (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0; + goto end; + } + + /* for emmc, MSDC_REMOVABLE not set, always return 1 */ + if (mmc->caps & MMC_CAP_NONREMOVABLE) { + host->card_inserted = 1; + goto end; + } else { + level = __gpio_get_value(cd_gpio); + /* FIX ME: make sure it is 1:0 or 0:1*/ + host->card_inserted = (host->hw->cd_level == level) ? 1 : 0; + } + + if (host->block_bad_card) + host->card_inserted = 0; + end: + /* enable msdc register dump */ + sd_register_zone[host->id] = 1; + INIT_MSG("Card insert<%d> Block bad card<%d>", + host->card_inserted, host->block_bad_card); + /* spin_unlock_irqrestore(&host->lock, flags); */ + return host->card_inserted; +} + +static void msdc_ops_card_event(struct mmc_host *mmc) +{ + struct msdc_host *host = mmc_priv(mmc); + + host->block_bad_card = 0; + host->is_autok_done = 0; + host->async_tuning_done = true; + host->legacy_tuning_done = true; + msdc_reset_pwr_cycle_counter(host); + msdc_reset_crc_tune_counter(host, all_counter); + msdc_reset_tmo_tune_counter(host, all_counter); + + msdc_ops_get_cd(mmc); + /* when detect card, cmd13 will be sent which timeout log is not needed */ + sd_register_zone[host->id] = 0; +} + +/* ops.enable_sdio_irq */ +static void msdc_ops_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct msdc_host *host = mmc_priv(mmc); + struct msdc_hw *hw = host->hw; + void __iomem *base = host->base; + unsigned long flags; + + if (hw->flags & MSDC_EXT_SDIO_IRQ) { /* yes for sdio */ + if (enable) + hw->enable_sdio_eirq(); /* combo_sdio_enable_eirq */ + else + hw->disable_sdio_eirq(); /* combo_sdio_disable_eirq */ + } else if (hw->flags & MSDC_SDIO_IRQ) { + +#if (MSDC_DATA1_INT == 1) + spin_lock_irqsave(&host->sdio_irq_lock, flags); + + if (enable) { + while (1) { + MSDC_SET_BIT32(MSDC_INTEN, MSDC_INT_SDIOIRQ); + pr_debug("@#0x%08x @e >%d<\n", + (MSDC_READ32(MSDC_INTEN)), + host->mmc->sdio_irq_pending); + if ((MSDC_READ32(MSDC_INTEN) & MSDC_INT_SDIOIRQ) + == 0) { + pr_debug("Should never ever get into this >%d<\n", + host->mmc->sdio_irq_pending); + } else { + break; + } + } + } else { + MSDC_CLR_BIT32(MSDC_INTEN, MSDC_INT_SDIOIRQ); + pr_debug("@#0x%08x @d\n", (MSDC_READ32(MSDC_INTEN))); + } + + spin_unlock_irqrestore(&host->sdio_irq_lock, flags); +#endif + } +} + +static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct msdc_host *host = mmc_priv(mmc); + void __iomem *base = host->base; + unsigned int status = 0; + + if (host->hw->host_function == MSDC_EMMC) + return 0; + if (!host->power_switch) + return 0; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: + pr_err("%s msdc%d set voltage to 3.3V.\n", __func__, host->id); + return 0; + case MMC_SIGNAL_VOLTAGE_180: + pr_err("%s msdc%d set voltage to 1.8V.\n", __func__, host->id); + /* switch voltage */ + host->power_switch(host, 1); + /* Clock is gated by HW after CMD11, + * Must keep clock gate 5ms before switch voltage + */ + usleep_range(5000, 5500); + /* start to provide clock to device */ + MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_BV18SDT); + /* Delay 1ms wait HW to finish voltage switch */ + usleep_range(1000, 1500); + status = MSDC_READ32(MSDC_CFG); + if (!(status & MSDC_CFG_BV18SDT) && (status & MSDC_CFG_BV18PSS)) + return 0; + pr_warn("%s: 1.8V regulator output did not became stable\n", + mmc_hostname(mmc)); + return -EAGAIN; + default: + return 0; + } +} + +static int msdc_ops_switch_volt_sdio(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct msdc_host *host = mmc_priv(mmc); + void __iomem *base = host->base; + int err = 0; + u32 timeout = 100; + u32 retry = 10; + u32 status; + + if (host->hw->host_function == MSDC_EMMC) + return 0; + + if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_330) { + /* make sure SDC is not busy (TBC) */ + /* WAIT_COND(!SDC_IS_BUSY(), timeout, timeout); */ + err = (unsigned int)-EILSEQ; + msdc_retry(sdc_is_busy(), retry, timeout, host->id); + if (retry == 0) { + err = (unsigned int)-ETIMEDOUT; + goto out; + } + + /* pull up disabled in CMD and DAT[3:0] + to allow card drives them to low */ + /* check if CMD/DATA lines both 0 */ + if ((MSDC_READ32(MSDC_PS) & ((1 << 24) | (0xF << 16))) == 0) { + /* pull up disabled in CMD and DAT[3:0] */ + msdc_pin_config(host, MSDC_PIN_PULL_NONE); + + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { + + if (host->power_switch) + host->power_switch(host, 1); + + } + /* wait at least 5ms for card to switch to 1.8v signal*/ + mdelay(10); + + /* config clock to 10~12MHz mode for + volt switch detection by host. */ + + /* For FPGA 13MHz clock, this not work */ + msdc_set_mclk(host, MMC_TIMING_LEGACY, 260000); + + /* pull up enabled in CMD and DAT[3:0] */ + msdc_pin_config(host, MSDC_PIN_PULL_UP); + mdelay(105); + + /* start to detect volt change + by providing 1.8v signal to card */ + MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_BV18SDT); + + /* wait at max. 1ms */ + mdelay(1); + /* ERR_MSG("before read status"); */ + + while ((status = + MSDC_READ32(MSDC_CFG)) & MSDC_CFG_BV18SDT) + ; + + if (status & MSDC_CFG_BV18PSS) + err = 0; + } + } + out: + + return err; +} + +static int msdc_card_busy(struct mmc_host *mmc) +{ + struct msdc_host *host = mmc_priv(mmc); + void __iomem *base = host->base; + u32 status = MSDC_READ32(MSDC_PS); + + /* check if any pin between dat[0:3] is low */ + if (((status >> 16) & 0xf) != 0xf) + return 1; + + return 0; +} + +/* Add this function to check if no interrupt back after write. * + * It may occur when write crc revice, but busy over data->timeout_ns */ +static void msdc_check_write_timeout(struct work_struct *work) +{ + struct msdc_host *host = + container_of(work, struct msdc_host, write_timeout.work); + void __iomem *base = host->base; + struct mmc_data *data = host->data; + struct mmc_request *mrq = host->mrq; + struct mmc_host *mmc = host->mmc; + + u32 status = 0; + u32 state = 0; + u32 err = 0; + unsigned long tmo; + + if (!data || !mrq || !mmc) + return; + + pr_err("[%s]: XXX DMA Data Write Busy Timeout: %u ms, CMD<%d>", + __func__, host->write_timeout_ms, mrq->cmd->opcode); + + if (msdc_use_async_dma(data->host_cookie) && (host->tune == 0)) { + msdc_dump_info(host->id); + + msdc_dma_stop(host); + msdc_dma_clear(host); + msdc_reset_hw(host->id); + + tmo = jiffies + POLLING_BUSY; + + /* check the card state, try to bring back to trans state */ + spin_lock(&host->lock); + do { + /* if anything wrong, let block driver do error + handling. */ + err = msdc_get_card_status(mmc, host, &status); + if (err) { + ERR_MSG("CMD13 ERR<%d>", err); + break; + } + + state = R1_CURRENT_STATE(status); + ERR_MSG("check card state<%d>", state); + if (state == R1_STATE_DATA || state == R1_STATE_RCV) { + ERR_MSG("state<%d> need cmd12 to stop", state); + msdc_send_stop(host); + } else if (state == R1_STATE_PRG) { + ERR_MSG("state<%d> card is busy", state); + spin_unlock(&host->lock); + msleep(100); + spin_lock(&host->lock); + } + + if (time_after(jiffies, tmo)) { + ERR_MSG("abort timeout and stuck in %d state, remove such bad card!", + state); + spin_unlock(&host->lock); + msdc_set_bad_card_and_remove(host); + spin_lock(&host->lock); + break; + } + } while (state != R1_STATE_TRAN); + spin_unlock(&host->lock); + + data->error = (unsigned int)-ETIMEDOUT; + host->sw_timeout++; + + if (mrq->done) + mrq->done(mrq); + + msdc_gate_clock(host, 1); + host->error |= REQ_DAT_ERR; + } else { + /* do nothing, since legacy mode or async tuning + have it own timeout. */ + /* complete(&host->xfer_done); */ + } +} + +static struct mmc_host_ops mt_msdc_ops = { + .post_req = msdc_post_req, + .pre_req = msdc_pre_req, + .request = msdc_ops_request, + .set_ios = msdc_ops_set_ios, + .get_ro = msdc_ops_get_ro, + .get_cd = msdc_ops_get_cd, + .card_event = msdc_ops_card_event, + .enable_sdio_irq = msdc_ops_enable_sdio_irq, + .start_signal_voltage_switch = msdc_ops_switch_volt, + .execute_tuning = msdc_execute_tuning, + .hw_reset = msdc_card_reset, + .card_busy = msdc_card_busy, +}; + +static struct mmc_host_ops mt_msdc_ops_sdio = { + .post_req = msdc_post_req, + .pre_req = msdc_pre_req, + .request = msdc_ops_request, + .set_ios = msdc_ops_set_ios, + .get_ro = msdc_ops_get_ro, + .get_cd = msdc_ops_get_cd, + .card_event = msdc_ops_card_event, + .enable_sdio_irq = msdc_ops_enable_sdio_irq, + .start_signal_voltage_switch = msdc_ops_switch_volt_sdio, + .execute_tuning = msdc_execute_tuning, + .hw_reset = msdc_card_reset, + .card_busy = msdc_card_busy, +}; + +static void msdc_irq_data_complete(struct msdc_host *host, + struct mmc_data *data, int error) +{ + void __iomem *base = host->base; + struct mmc_request *mrq; + #ifdef MSDC_WQ_ERROR_TUNE + struct mmc_host *mmc = host->mmc; + int done_to_mmc_core = 1; + #endif + + if ((msdc_use_async_dma(data->host_cookie)) && + (!host->async_tuning_in_progress)) { + msdc_dma_stop(host); + if (error) { + msdc_clr_fifo(host->id); + msdc_clr_int(); + } + mrq = host->mrq; + msdc_dma_clear(host); + #ifdef MSDC_WQ_ERROR_TUNE + if (error) { + if (((host->hw->host_function == MSDC_SD) && + (mmc->ios.timing != MMC_TIMING_UHS_SDR104) && + (mmc->ios.timing != MMC_TIMING_UHS_SDR50)) + || ((host->hw->host_function == MSDC_EMMC) && + (mmc->ios.timing != MMC_TIMING_MMC_HS200) && + (mmc->ios.timing != MMC_TIMING_MMC_HS400))) { + done_to_mmc_core = 0; + } + } else { + host->prev_cmd_cause_dump = 0; + } + if (done_to_mmc_core) { + if (mrq->done) + mrq->done(mrq); + } + #else + if (mrq->done) + mrq->done(mrq); + #endif + + msdc_gate_clock(host, 1); + if (!error) { + host->error &= ~REQ_DAT_ERR; + } else { + host->error |= REQ_DAT_ERR; + #ifdef MSDC_WQ_ERROR_TUNE + host->mrq_tune = mrq; + if (!done_to_mmc_core) { + if (!queue_work(wq_tune, &host->work_tune)) { + pr_err("msdc%d queue work failed BUG_ON,[%s]L:%d\n", + host->id, __func__, __LINE__); + BUG(); + } + } + #endif + } + } else { + /* Autocmd12 issued but error, data transfer done INT will not issue, + * so cmplete is need here + */ + complete(&host->xfer_done); + } + +} + +static irqreturn_t msdc_irq(int irq, void *dev_id) +{ + struct msdc_host *host = (struct msdc_host *)dev_id; + struct mmc_data *data = host->data; + struct mmc_command *cmd = host->cmd; + struct mmc_command *stop = NULL; + void __iomem *base = host->base; + + u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | + MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY | + MSDC_INT_ACMD19_DONE; +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + u32 cmdqsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY; +#endif + u32 datsts = MSDC_INT_DATCRCERR | MSDC_INT_DATTMO; + u32 intsts, inten; + + if (host->hw->flags & MSDC_SDIO_IRQ) + spin_lock(&host->sdio_irq_lock); + + if (host->core_clkon == 0) { + (void)msdc_clk_enable(host); + host->core_clkon = 1; + MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); + } + intsts = MSDC_READ32(MSDC_INT); + + latest_int_status[host->id] = intsts; + inten = MSDC_READ32(MSDC_INTEN); +#if (MSDC_DATA1_INT == 1) + if (host->hw->flags & MSDC_SDIO_IRQ) { + intsts &= inten; + } else +#endif + { + inten &= intsts; + } + +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + /* don't clear command related interrupt bits, + these will be cleared by command polling response */ + intsts &= ~cmdqsts; +#endif + + MSDC_WRITE32(MSDC_INT, intsts); /* clear interrupts */ + + /* sdio interrupt */ + if (host->hw->flags & MSDC_SDIO_IRQ) { + spin_unlock(&host->sdio_irq_lock); + + #if (MSDC_DATA1_INT == 1) + if (intsts & MSDC_INT_SDIOIRQ) + mmc_signal_sdio_irq(host->mmc); + #endif + } + + /* transfer complete interrupt */ + if (data == NULL) + goto skip_data_interrupts; + +#ifdef MTK_MSDC_ERROR_TUNE_DEBUG + msdc_error_tune_debug2(host, stop, &intsts); +#endif + + stop = data->stop; +#if (MSDC_DATA1_INT == 1) + if ((host->hw->flags & MSDC_SDIO_IRQ) && + (intsts & MSDC_INT_XFER_COMPL)) { + goto done; + } else +#endif + { +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + host->mmc->is_data_dma = 0; +#endif + if (inten & MSDC_INT_XFER_COMPL) { + if (host->hw->host_function == MSDC_SD) + host->power_cycle = 0; + goto done; + } + } + + if (intsts & datsts) { + /* do basic reset, or stop command will sdc_busy */ + if (intsts & MSDC_INT_DATTMO) + msdc_dump_info(host->id); + + if (host->dma_xfer) + msdc_reset(host->id); + else + msdc_reset_hw(host->id); + + atomic_set(&host->abort, 1); /* For PIO mode exit */ + + if (intsts & MSDC_INT_DATTMO) { + data->error = (unsigned int)-ETIMEDOUT; + ERR_MSG("XXX CMD<%d> Arg<0x%.8x> MSDC_INT_DATTMO", + host->mrq->cmd->opcode, host->mrq->cmd->arg); + } else if (intsts & MSDC_INT_DATCRCERR) { + data->error = (unsigned int)-EILSEQ; + ERR_MSG("XXX CMD<%d> Arg<0x%.8x> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>", + host->mrq->cmd->opcode, host->mrq->cmd->arg, + MSDC_READ32(SDC_DCRC_STS)); + } + + goto tune; + + } + if ((stop != NULL) && + (host->autocmd & MSDC_AUTOCMD12) && + (intsts & cmdsts)) { + if (intsts & MSDC_INT_ACMDRDY) { + u32 *arsp = &stop->resp[0]; + *arsp = MSDC_READ32(SDC_ACMD_RESP); + } else if (intsts & MSDC_INT_ACMDCRCERR) { + stop->error = (unsigned int)-EILSEQ; + host->error |= REQ_STOP_EIO; + if (host->dma_xfer) + msdc_reset(host->id); + else + msdc_reset_hw(host->id); + } else if (intsts & MSDC_INT_ACMDTMO) { + stop->error = (unsigned int)-ETIMEDOUT; + host->error |= REQ_STOP_TMO; + if (host->dma_xfer) + msdc_reset(host->id); + else + msdc_reset_hw(host->id); + } + if ((intsts & MSDC_INT_ACMDCRCERR) || + (intsts & MSDC_INT_ACMDTMO)) { + goto tune; + } + } + +skip_data_interrupts: + + /* command interrupts */ + if ((cmd == NULL) || !(intsts & cmdsts)) + goto skip_cmd_interrupts; + +#ifdef MTK_MSDC_ERROR_TUNE_DEBUG + msdc_error_tune_debug3(host, cmd, &intsts); +#endif + +#ifndef CONFIG_MTK_EMMC_CQ_SUPPORT + if (intsts & MSDC_INT_CMDRDY) { + u32 *rsp = NULL; + + rsp = &cmd->resp[0]; + switch (host->cmd_rsp) { + case RESP_NONE: + break; + case RESP_R2: + *rsp++ = MSDC_READ32(SDC_RESP3); + *rsp++ = MSDC_READ32(SDC_RESP2); + *rsp++ = MSDC_READ32(SDC_RESP1); + *rsp++ = MSDC_READ32(SDC_RESP0); + break; + default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ + *rsp = MSDC_READ32(SDC_RESP0); + break; + } + } else if (intsts & MSDC_INT_RSPCRCERR) { + cmd->error = (unsigned int)-EILSEQ; + ERR_MSG("XXX CMD<%d> MSDC_INT_RSPCRCERR Arg<0x%.8x>", + cmd->opcode, cmd->arg); + msdc_reset_hw(host->id); + } else if (intsts & MSDC_INT_CMDTMO) { + cmd->error = (unsigned int)-ETIMEDOUT; + ERR_MSG("XXX CMD<%d> MSDC_INT_CMDTMO Arg<0x%.8x>", + cmd->opcode, cmd->arg); + msdc_reset_hw(host->id); + } + if (intsts & (MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO)) + complete(&host->cmd_done); +#endif + +skip_cmd_interrupts: + /* mmc irq interrupts */ + if (intsts & MSDC_INT_MMCIRQ) { + /* pr_debug("msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n", + host->id, MSDC_READ32(SDC_CSTS)); */ + } + + if (!host->async_tuning_in_progress +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + && (!host->mmc->card || + !host->mmc->card->ext_csd.cmdq_mode_en) +#endif + ) { + if (cmd && (cmd->error == (unsigned int)-EILSEQ)) + host->async_tuning_done = false; + } + + if (host->dma_xfer) + msdc_irq_data_complete(host, data, 1); + latest_int_status[host->id] = 0; + return IRQ_HANDLED; + +done: /* Finished data transfer */ + data->bytes_xfered = host->dma.xfersz; + msdc_irq_data_complete(host, data, 0); + return IRQ_HANDLED; + +tune: /* DMA DATA transfer crc error */ + /* PIO mode can't do complete, because not init */ + + if (!host->async_tuning_in_progress +#ifdef CONFIG_MTK_EMMC_CQ_SUPPORT + && (!host->mmc->card || + !host->mmc->card->ext_csd.cmdq_mode_en) +#endif + ) { + if ((data && data->error) + || (cmd && (cmd->error == (unsigned int)-EILSEQ))) { + #ifndef MSDC_WQ_ERROR_TUNE + if (data->flags & MMC_DATA_WRITE) + host->err_mrq_dir |= MMC_DATA_WRITE; + else if (data->flags & MMC_DATA_READ) + host->err_mrq_dir |= MMC_DATA_READ; + if (host->hw->host_function == MSDC_SD) { + /* fake as bus_dead to prevent from + power cycle */ + host->mmc->bus_dead = 1; + } + #endif + host->async_tuning_done = false; + } + } + + if (host->dma_xfer) + msdc_irq_data_complete(host, data, 1); + + if (data && !data->error) + host->prev_cmd_cause_dump = 0; + + return IRQ_HANDLED; +} + +/* init gpd and bd list in msdc_drv_probe */ +static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma) +{ + struct gpd_t *gpd = dma->gpd; + struct bd_t *bd = dma->bd; + struct bd_t *ptr, *prev; + + /* we just support one gpd */ + int bdlen = MAX_BD_PER_GPD; + + /* init the 2 gpd */ + memset(gpd, 0, sizeof(struct gpd_t) * 2); + gpd->next = (u32)dma->gpd_addr + sizeof(struct gpd_t); + + /* gpd->intr = 0; */ + gpd->bdp = 1; /* hwo, cs, bd pointer */ + /* gpd->ptr = (void*)virt_to_phys(bd); */ + gpd->ptr = (u32)dma->bd_addr; /* physical address */ + + memset(bd, 0, sizeof(struct bd_t) * bdlen); + ptr = bd + bdlen - 1; + while (ptr != bd) { + prev = ptr - 1; + prev->next = (u32)dma->bd_addr + + sizeof(struct bd_t) * (ptr - bd); + ptr = prev; + } +} + +#ifdef MTK_MSDC_FLUSH_BY_CLK_GATE +static void msdc_tasklet_flush_cache(unsigned long arg) +{ + struct msdc_host *host = (struct msdc_host *)arg; + + if (host->mmc->card) { + mmc_claim_host(host->mmc); + mmc_flush_cache(host->mmc->card); + mmc_release_host(host->mmc); + } +} +#endif + +/* This is called by run_timer_softirq */ +static void msdc_timer_pm(unsigned long data) +{ + struct msdc_host *host = (struct msdc_host *)data; + unsigned long flags; + + spin_lock_irqsave(&host->clk_gate_lock, flags); + if (host->clk_gate_count == 0) { + msdc_clksrc_onoff(host, 0); + N_MSG(CLK, "time out, dsiable clock, clk_gate_count=%d", + host->clk_gate_count); + } +#ifdef MTK_MSDC_FLUSH_BY_CLK_GATE + if (check_mmc_cache_ctrl(mmc->card)) + tasklet_hi_schedule(&host->flush_cache_tasklet); +#endif + + spin_unlock_irqrestore(&host->clk_gate_lock, flags); +} + +/* FIX ME : consider if this function can be moved to msdc_io.c */ +static void msdc_set_host_power_control(struct msdc_host *host) +{ + if (MSDC_EMMC == host->hw->host_function) { + host->power_control = msdc_emmc_power; + } else if (MSDC_SD == host->hw->host_function) { + host->power_control = msdc_sd_power; + host->power_switch = msdc_sd_power_switch; + } else if (MSDC_SDIO == host->hw->host_function) { + host->power_control = msdc_sdio_power; + } + + if (host->power_control != NULL) { + msdc_power_calibration_init(host); + } else { + ERR_MSG("Host function defination error for msdc%d", host->id); + BUG(); + } +} + +void SRC_trigger_signal(int i_on) +{ + if ((ghost != NULL) && (ghost->hw->flags & MSDC_SDIO_IRQ)) { + pr_debug("msdc2 SRC_trigger_signal %d\n", i_on); + src_clk_control = i_on; + if (src_clk_control) { + msdc_clksrc_onoff(ghost, 1); + /* mb(); */ + if (ghost->mmc->sdio_irq_thread && + (atomic_read(&ghost->mmc->sdio_irq_thread_abort) + == 0)) {/* if (ghost->mmc->sdio_irq_thread) */ + mmc_signal_sdio_irq(ghost->mmc); + if (u_msdc_irq_counter < 3) + pr_debug("msdc2 SRC_trigger_signal mmc_signal_sdio_irq\n"); + } + /* pr_debug("msdc2 SRC_trigger_signal ghost->id=%d\n", + ghost->id); */ + } + } + +} +EXPORT_SYMBOL(SRC_trigger_signal); + +#ifdef CONFIG_MTK_HIBERNATION +int msdc_drv_pm_restore_noirq(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct mmc_host *mmc = NULL; + struct msdc_host *host = NULL; + BUG_ON(pdev == NULL); + mmc = platform_get_drvdata(pdev); + host = mmc_priv(mmc); + if (host->hw->host_function == MSDC_SD) { + if ((host->id == 1) && !(mmc->caps & MMC_CAP_NONREMOVABLE)) { + if ((host->hw->cd_level == __gpio_get_value(cd_gpio)) + && host->mmc->card) { + mmc_card_set_removed(host->mmc->card); + host->card_inserted = 0; + } + } else if ((host->id == 2) && + !(mmc->caps & MMC_CAP_NONREMOVABLE)) { + /* sdio need handle here */ + } + host->block_bad_card = 0; + } + return 0; +} +#endif + +/* called by msdc_drv_remove */ +static void msdc_deinit_hw(struct msdc_host *host) +{ + void __iomem *base = host->base; + + /* Disable and clear all interrupts */ + MSDC_CLR_BIT32(MSDC_INTEN, MSDC_READ32(MSDC_INTEN)); + MSDC_WRITE32(MSDC_INT, MSDC_READ32(MSDC_INT)); + + /* make sure power down */ + msdc_set_power_mode(host, MMC_POWER_OFF); +} + +static void msdc_add_host(struct work_struct *work) +{ + int ret; + struct msdc_host *host = NULL; + struct mmc_host *mmc = NULL; + + host = container_of(work, struct msdc_host, work_init.work); + BUG_ON(!host); + mmc = host->mmc; + BUG_ON(!mmc); + + ret = mmc_add_host(mmc); + + if (ret) { + free_irq(host->irq, host); + pr_err("[%s]: msdc%d init fail free irq!\n", __func__, host->id); + platform_set_drvdata(host->pdev, NULL); + msdc_deinit_hw(host); + pr_err("[%s]: msdc%d init fail release!\n", __func__, host->id); + kfree(host->hw); + mmc_free_host(mmc); + } +} + +static int msdc_drv_probe(struct platform_device *pdev) +{ + struct mmc_host *mmc = NULL; + struct msdc_host *host = NULL; + struct msdc_hw *hw = NULL; + void __iomem *base = NULL; + u32 *hclks = NULL; + int ret = 0; + + /* Allocate MMC host for this device */ + mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev); + if (!mmc) + return -ENOMEM; + + ret = msdc_dt_init(pdev, mmc); + if (ret) { + mmc_free_host(mmc); + return ret; + } + + host = mmc_priv(mmc); + base = host->base; + hw = host->hw; + + /* Set host parameters to mmc */ + mmc->ops = &mt_msdc_ops; + mmc->f_min = HOST_MIN_MCLK; + mmc->f_max = HOST_MAX_MCLK; + mmc->ocr_avail = MSDC_OCR_AVAIL; + + if (host->hw->host_function == MSDC_SDIO) + mmc->ops = &mt_msdc_ops_sdio; + + /* For sd card: MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | + MSDC_REMOVABLE | MSDC_HIGHSPEED, + For sdio : MSDC_EXT_SDIO_IRQ | MSDC_HIGHSPEED */ + if ((hw->flags & MSDC_SDIO_IRQ) || (hw->flags & MSDC_EXT_SDIO_IRQ)) + mmc->caps |= MMC_CAP_SDIO_IRQ; /* yes for sdio */ + +#ifdef MTK_MSDC_USE_CMD23 + if (host->hw->host_function == MSDC_EMMC) + mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23; + else + mmc->caps |= MMC_CAP_ERASE; +#else + mmc->caps |= MMC_CAP_ERASE; +#endif + + /* If 0 < mmc->max_busy_timeout < cmd.busy_timeout, + * R1B will change to R1, host will not detect DAT0 busy, + * next CMD may send to eMMC at busy state. + */ + mmc->max_busy_timeout = 0; + + /* MMC core transfer sizes tunable parameters */ + mmc->max_segs = MAX_HW_SGMTS; + /*mmc->max_phys_segs = MAX_PHY_SGMTS;*/ + if (hw->host_function == MSDC_SDIO) + mmc->max_seg_size = MAX_SGMT_SZ_SDIO; + else + mmc->max_seg_size = MAX_SGMT_SZ; + mmc->max_blk_size = HOST_MAX_BLKSZ; + mmc->max_req_size = MAX_REQ_SZ; + mmc->max_blk_count = MAX_REQ_SZ / 512; /*mmc->max_req_size;*/ + + hclks = msdc_get_hclks(pdev->id); + + host->error = 0; + host->mclk = 0; /* request clock of mmc */ + host->hclk = hclks[hw->clk_src]; + /* clocksource to msdc */ + host->sclk = 0; /* sd/sdio/emmc bus clock */ + host->pm_state = PMSG_RESUME; + host->suspend = 0; + + /* FIX ME: check if is used */ + INIT_DELAYED_WORK(&(host->set_vcore_workq), sdio_unreq_vcore); + + init_completion(&host->autok_done); + host->is_autok_done = 0; + + host->core_clkon = 0; + host->clk_gate_count = 0; + host->power_mode = MMC_POWER_OFF; + host->power_control = NULL; + host->power_switch = NULL; + + host->dma_mask = DMA_BIT_MASK(33); + mmc_dev(mmc)->dma_mask = &host->dma_mask; + +#ifndef FPGA_PLATFORM + if (msdc_get_ccf_clk_pointer(pdev, host)) + return 1; +#endif + + msdc_set_host_power_control(host); + if ((host->hw->host_function == MSDC_SD) && + !(host->mmc->caps & MMC_CAP_NONREMOVABLE)) { + /* Since SD card power is default on, + it shall be turned off so that removalbe card slot won't + keep power when there is no card plugged */ + msdc_sd_power(host, 1); /* turn on first to match HW/SW state*/ + msdc_sd_power(host, 0); + } + + /* FIX ME: check if this can be removed */ + /* + if (host->hw->host_function == MSDC_EMMC && + !(host->hw->flags & MSDC_UHS1)) + host->mmc->f_max = 50000000; + */ + + host->card_inserted = host->mmc->caps & MMC_CAP_NONREMOVABLE ? 1 : 0; + host->timeout_ns = 0; + host->timeout_clks = DEFAULT_DTOC * 1048576; + +#ifndef MTK_MSDC_USE_CMD23 + if (host->hw->host_function != MSDC_SDIO) + host->autocmd |= MSDC_AUTOCMD12; + else + host->autocmd &= ~MSDC_AUTOCMD12; +#else + if (host->hw->host_function == MSDC_EMMC) { + host->autocmd &= ~MSDC_AUTOCMD12; + +#if (1 == MSDC_USE_AUTO_CMD23) + host->autocmd |= MSDC_AUTOCMD23; +#endif + + } else if (host->hw->host_function == MSDC_SD) { + host->autocmd |= MSDC_AUTOCMD12; + } else { + host->autocmd &= ~MSDC_AUTOCMD12; + } +#endif /* end of MTK_MSDC_USE_CMD23 */ + + host->mrq = NULL; + +#ifdef MTK_MSDC_USE_CACHE + if (host->hw->host_function == MSDC_EMMC) + msdc_set_cache_quirk(host); +#endif + + host->dma.used_gpd = 0; + host->dma.used_bd = 0; + + /* using dma_alloc_coherent *//* todo: using 1, for all 4 slots */ + host->dma.gpd = dma_alloc_coherent(&pdev->dev, + MAX_GPD_NUM * sizeof(struct gpd_t), + &host->dma.gpd_addr, GFP_KERNEL); + host->dma.bd = dma_alloc_coherent(&pdev->dev, + MAX_BD_NUM * sizeof(struct bd_t), + &host->dma.bd_addr, GFP_KERNEL); + BUG_ON((!host->dma.gpd) || (!host->dma.bd)); + msdc_init_gpd_bd(host, &host->dma); + msdc_clock_src[host->id] = hw->clk_src; + msdc_host_mode[host->id] = mmc->caps; + msdc_host_mode2[host->id] = mmc->caps2; + /*for emmc */ + mtk_msdc_host[host->id] = host; + host->write_timeout_uhs104 = 0; + host->write_timeout_emmc = 0; + host->read_timeout_uhs104 = 0; + host->read_timeout_emmc = 0; + host->sw_timeout = 0; + host->async_tuning_in_progress = false; + host->async_tuning_done = true; + host->legacy_tuning_in_progress = false; + host->legacy_tuning_done = true; + #ifndef MSDC_WQ_ERROR_TUNE + host->err_mrq_dir = 0; + #endif + host->timing = 0; + host->block_bad_card = 0; + host->sd_30_busy = 0; + msdc_reset_tmo_tune_counter(host, all_counter); + msdc_reset_pwr_cycle_counter(host); + host->error_tune_enable = 1; + + if (host->hw->host_function == MSDC_SDIO) + wakeup_source_init(&host->trans_lock, "MSDC Transfer Lock"); + +#ifdef MTK_MSDC_FLUSH_BY_CLK_GATE + if (host->mmc->caps2 & MMC_CAP2_CACHE_CTRL) + tasklet_init(&host->flush_cache_tasklet, + msdc_tasklet_flush_cache, (ulong) host); +#endif + INIT_DELAYED_WORK(&host->write_timeout, msdc_check_write_timeout); + INIT_DELAYED_WORK(&host->work_init, msdc_add_host); + + /*INIT_DELAYED_WORK(&host->remove_card, msdc_remove_card);*/ + spin_lock_init(&host->lock); + spin_lock_init(&host->clk_gate_lock); + spin_lock_init(&host->remove_bad_card); + spin_lock_init(&host->sdio_irq_lock); + /* init dynamtic timer */ + init_timer(&host->timer); + /*host->timer.expires = jiffies + HZ;*/ + host->timer.function = msdc_timer_pm; + host->timer.data = (unsigned long)host; + + ret = request_irq((unsigned int)host->irq, msdc_irq, IRQF_TRIGGER_NONE, + DRV_NAME, host); + if (ret) + goto release; + + MVG_EMMC_SETUP(host); + + if (hw->request_sdio_eirq) + /* set to combo_sdio_request_eirq() for WIFI */ + /* msdc_eirq_sdio() will be called when EIRQ */ + hw->request_sdio_eirq(msdc_eirq_sdio, (void *)host); + +#ifdef CONFIG_PM + if (hw->register_pm) {/* only for sdio */ + /* function pointer to combo_sdio_register_pm() */ + hw->register_pm(msdc_pm, (void *)host); + if (hw->flags & MSDC_SYS_SUSPEND) { + /* will not set for WIFI */ + ERR_MSG("MSDC_SYS_SUSPEND and register_pm both set"); + } + /* pm not controlled by system but by client. */ + mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; + } +#endif + + if (host->hw->host_function == MSDC_EMMC) + mmc->pm_flags |= MMC_PM_KEEP_POWER; + + platform_set_drvdata(pdev, mmc); + +#ifdef CONFIG_MTK_HIBERNATION + if (pdev->id == 1) + register_swsusp_restore_noirq_func(ID_M_MSDC, + msdc_drv_pm_restore_noirq, &(pdev->dev)); +#endif + + /* Config card detection pin and enable interrupts */ + if (!(host->mmc->caps & MMC_CAP_NONREMOVABLE)) { + MSDC_CLR_BIT32(MSDC_PS, MSDC_PS_CDEN); + MSDC_CLR_BIT32(MSDC_INTEN, MSDC_INTEN_CDSC); + MSDC_CLR_BIT32(SDC_CFG, SDC_CFG_INSWKUP); + } + + #ifdef MSDC_WQ_ERROR_TUNE + /*config tune at workqueue*/ + INIT_WORK(&host->work_tune, msdc_async_tune); + host->mrq_tune = NULL; + #endif + + /* Use ordered workqueue to reduce msdc moudle init time */ + if (!queue_delayed_work(wq_init, &host->work_init, 0)) { + pr_err("msdc%d queue delay work failed BUG_ON,[%s]L:%d\n", + host->id, __func__, __LINE__); + BUG(); + } + +#ifdef MTK_MSDC_BRINGUP_DEBUG + pr_debug("[%s]: msdc%d, mmc->caps=0x%x, mmc->caps2=0x%x\n", + __func__, host->id, mmc->caps, mmc->caps2); + msdc_dump_clock_sts(); +#endif + + return 0; + +release: + platform_set_drvdata(pdev, NULL); + msdc_deinit_hw(host); + pr_err("[%s]: msdc%d init fail release!\n", __func__, host->id); + +#ifdef MTK_MSDC_FLUSH_BY_CLK_GATE + if (host->mmc->caps2 & MMC_CAP2_CACHE_CTRL) + tasklet_kill(&host->flush_cache_tasklet); +#endif + + kfree(host->hw); + mmc_free_host(mmc); + + return ret; +} + +/* 4 device share one driver, using "drvdata" to show difference */ +static int msdc_drv_remove(struct platform_device *pdev) +{ + struct mmc_host *mmc; + struct msdc_host *host; + struct resource *mem; + + mmc = platform_get_drvdata(pdev); + BUG_ON(!mmc); + + host = mmc_priv(mmc); + BUG_ON(!host); + + ERR_MSG("msdc_drv_remove"); +#ifndef FPGA_PLATFORM + /* clock unprepare */ + if (host->clock_control) + clk_unprepare(host->clock_control); + +#endif + platform_set_drvdata(pdev, NULL); + mmc_remove_host(host->mmc); + msdc_deinit_hw(host); + +#ifdef MTK_MSDC_FLUSH_BY_CLK_GATE + if ((host->hw->host_function == MSDC_EMMC) && + (host->mmc->caps2 & MMC_CAP2_CACHE_CTRL)) + tasklet_kill(&host->flush_cache_tasklet); +#endif + free_irq(host->irq, host); + + dma_free_coherent(NULL, MAX_GPD_NUM * sizeof(struct gpd_t), + host->dma.gpd, host->dma.gpd_addr); + dma_free_coherent(NULL, MAX_BD_NUM * sizeof(struct bd_t), + host->dma.bd, host->dma.bd_addr); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (mem) + release_mem_region(mem->start, mem->end - mem->start + 1); + + kfree(host->hw); + + mmc_free_host(host->mmc); + + return 0; +} + +#ifdef CONFIG_PM +static int msdc_drv_suspend(struct platform_device *pdev, pm_message_t state) +{ + int ret = 0; + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct msdc_host *host; + void __iomem *base; + + if (mmc == NULL) + return 0; + + host = mmc_priv(mmc); + base = host->base; + + if (state.event == PM_EVENT_SUSPEND) { + if (host->hw->flags & MSDC_SYS_SUSPEND) { + /* will set for card */ + msdc_pm(state, (void *)host); + } else { + /* WIFI slot should be off when enter suspend */ + msdc_gate_clock(host, -1); + if (host->error == -EBUSY) { + ret = host->error; + host->error = 0; + } + } + } + + if (is_card_sdio(host) || (host->hw->flags & MSDC_SDIO_IRQ)) { + if (host->clk_gate_count > 0) { + host->error = 0; + return -EBUSY; + } + if (host->saved_para.suspend_flag == 0) { + host->saved_para.hz = host->mclk; + if (host->saved_para.hz) { + host->saved_para.suspend_flag = 1; + /* mb(); */ + msdc_ungate_clock(host); + msdc_save_timing_setting(host, 2); + msdc_gate_clock(host, 0); + if (host->error == -EBUSY) { + ret = host->error; + host->error = 0; + } + } + ERR_MSG("msdc suspend cur_cfg=%x, save_cfg=%x, cur_hz=%d", + MSDC_READ32(MSDC_CFG), + host->saved_para.msdc_cfg, host->mclk); + } + } + return ret; +} + +static int msdc_drv_resume(struct platform_device *pdev) +{ + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct msdc_host *host = mmc_priv(mmc); + struct pm_message state; + + if (host->hw->flags & MSDC_SDIO_IRQ) + pr_err("msdc msdc_drv_resume\n"); + state.event = PM_EVENT_RESUME; + if (mmc && (host->hw->flags & MSDC_SYS_SUSPEND)) { + /* will set for card; + WIFI not controller by PM */ + msdc_pm(state, (void *)host); + } + + /* This mean WIFI not controller by PM */ + if (host->hw->host_function == MSDC_SDIO) { + host->mmc->pm_flags |= MMC_PM_KEEP_POWER; + host->mmc->rescan_entered = 0; + } + + return 0; +} +#endif + +static struct platform_driver mt_msdc_driver = { + .probe = msdc_drv_probe, + .remove = msdc_drv_remove, +#ifdef CONFIG_PM + .suspend = msdc_drv_suspend, + .resume = msdc_drv_resume, +#endif + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = msdc_of_ids, + }, +}; + +/*--------------------------------------------------------------------------*/ +/* module init/exit */ +/*--------------------------------------------------------------------------*/ +static int __init mt_msdc_init(void) +{ + int ret; + + /* Alloc init workqueue */ + wq_init = alloc_ordered_workqueue("msdc-init", 0); + if (!wq_init) { + pr_err("msdc create work_queue failed.[%s]:%d", __func__, __LINE__); + BUG(); + } + + #ifdef MSDC_WQ_ERROR_TUNE + /*Must config tune at workqueue before platform_driver_reigster()*/ + wq_tune = create_workqueue("msdc-tune"); + if (!wq_tune) { + pr_err("msdc create work_queue failed.[%s]:%d", + __func__, __LINE__); + BUG(); + } + #endif + + ret = platform_driver_register(&mt_msdc_driver); + if (ret) { + pr_err(DRV_NAME ": Can't register driver"); + return ret; + } + +#ifdef CONFIG_PWR_LOSS_MTK_TEST + msdc_proc_emmc_create(); +#endif + msdc_debug_proc_init(); + + pr_debug(DRV_NAME ": MediaTek MSDC Driver\n"); + + return 0; +} + +static void __exit mt_msdc_exit(void) +{ + #ifdef MSDC_WQ_ERROR_TUNE + if (wq_tune) { + destroy_workqueue(wq_tune); + wq_tune = NULL; + } + #endif + + platform_driver_unregister(&mt_msdc_driver); + + if (wq_init) { + destroy_workqueue(wq_init); + wq_init = NULL; + } + +#ifdef CONFIG_MTK_HIBERNATION + unregister_swsusp_restore_noirq_func(ID_M_MSDC); +#endif +} + +module_init(mt_msdc_init); +module_exit(mt_msdc_exit); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek SD/MMC Card Driver"); diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6755.c b/drivers/pinctrl/mediatek/pinctrl-mt6755.c new file mode 100644 index 0000000000000000000000000000000000000000..13592e12cc09394fb6f8a8bd9eeb7ba0e8d63a86 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mt6755.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Hongzhou.Yang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include "pinctrl-mtk-common.h" +#include "pinctrl-mtk-mt6755.h" + + + + +#if 0 +/** + * struct mtk_pin_ies_smt_set - For special pins' ies and smt setting. + * @start: The start pin number of those special pins. + * @end: The end pin number of those special pins. + * @offset: The offset of special setting register. + * @bit: The bit of special setting register. + */ +struct mtk_pin_ies_smt_set { + unsigned int start; + unsigned int end; + unsigned int offset; + unsigned char bit; +}; + +#define MTK_PIN_IES_SMT_SET(_start, _end, _offset, _bit) \ + { \ + .start = _start, \ + .end = _end, \ + .bit = _bit, \ + .offset = _offset, \ + } +#endif + +#if 0 +/** + * struct mtk_pin_spec_pupd_set - For special pins' pull up/down setting. + * @pin: The pin number. + * @offset: The offset of special pull up/down setting register. + * @pupd_bit: The pull up/down bit in this register. + * @r0_bit: The r0 bit of pull resistor. + * @r1_bit: The r1 bit of pull resistor. + */ +struct mtk_pin_spec_pupd_set { + unsigned int pin; + unsigned int offset; + unsigned char pupd_bit; + unsigned char r1_bit; + unsigned char r0_bit; +}; + +#define MTK_PIN_PUPD_SPEC(_pin, _offset, _pupd, _r1, _r0) \ + { \ + .pin = _pin, \ + .offset = _offset, \ + .pupd_bit = _pupd, \ + .r1_bit = _r1, \ + .r0_bit = _r0, \ + } +#endif + +#if 0 +static const struct mtk_pin_spec_pupd_set mt6735_spec_pupd[] = { + + MTK_PIN_PUPD_SPEC(45, 0x980, 2, 1, 0), + MTK_PIN_PUPD_SPEC(46, 0x980, 6, 5, 4), + MTK_PIN_PUPD_SPEC(81, 0xA80, 2, 1, 0), + MTK_PIN_PUPD_SPEC(82, 0xA80, 6, 5, 4), + MTK_PIN_PUPD_SPEC(83, 0xA80, 10, 9, 8), + MTK_PIN_PUPD_SPEC(84, 0xA80, 18, 17, 16), + MTK_PIN_PUPD_SPEC(85, 0xA80, 22, 21, 20), + MTK_PIN_PUPD_SPEC(86, 0xA80, 26, 25, 24), + MTK_PIN_PUPD_SPEC(160, 0xC90, 3, 2, 1), + MTK_PIN_PUPD_SPEC(161, 0xC90, 7, 6, 5), + MTK_PIN_PUPD_SPEC(162, 0xC90, 11, 10, 9), + MTK_PIN_PUPD_SPEC(163, 0xC90, 19, 18, 17), + MTK_PIN_PUPD_SPEC(164, 0xC90, 23, 22, 21), + MTK_PIN_PUPD_SPEC(165, 0xC90, 27, 26, 25), + MTK_PIN_PUPD_SPEC(166, 0xC80, 2, 1, 0), + MTK_PIN_PUPD_SPEC(167, 0xC80, 6, 5, 4), + MTK_PIN_PUPD_SPEC(168, 0xC80, 10, 9, 8), + MTK_PIN_PUPD_SPEC(169, 0xC80, 14, 13, 12), + MTK_PIN_PUPD_SPEC(170, 0xC80, 18, 17, 16), + MTK_PIN_PUPD_SPEC(171, 0xC80, 22, 21, 20), + MTK_PIN_PUPD_SPEC(172, 0xD80, 2, 1, 0), + MTK_PIN_PUPD_SPEC(173, 0xD80, 10, 9, 8), + MTK_PIN_PUPD_SPEC(174, 0xD80, 6, 5, 4), + MTK_PIN_PUPD_SPEC(175, 0xD80, 14, 13, 12), + MTK_PIN_PUPD_SPEC(176, 0xD80, 18, 17, 16), + MTK_PIN_PUPD_SPEC(177, 0xD80, 22, 21, 20), + MTK_PIN_PUPD_SPEC(178, 0xD80, 26, 25, 24), + MTK_PIN_PUPD_SPEC(179, 0xD80, 30, 29, 28), + MTK_PIN_PUPD_SPEC(180, 0xD90, 2, 1, 0), + MTK_PIN_PUPD_SPEC(181, 0xD90, 6, 5, 4), + MTK_PIN_PUPD_SPEC(182, 0xD90, 10, 9, 8), + MTK_PIN_PUPD_SPEC(183, 0xD90, 14, 13, 12), + MTK_PIN_PUPD_SPEC(198, 0x880, 2, 1, 0), + MTK_PIN_PUPD_SPEC(199, 0x880, 6, 5, 4), + MTK_PIN_PUPD_SPEC(200, 0x880, 10, 9, 8), + MTK_PIN_PUPD_SPEC(201, 0x880, 14, 13, 12), + MTK_PIN_PUPD_SPEC(202, 0x880, 18, 17, 16), + MTK_PIN_PUPD_SPEC(203, 0x880, 22, 21, 20), + MTK_PIN_PUPD_SPEC(45, 0x980, 2, 1, 0), + MTK_PIN_PUPD_SPEC(46, 0x980, 6, 5, 4), + MTK_PIN_PUPD_SPEC(81, 0xA80, 2, 1, 0), + MTK_PIN_PUPD_SPEC(82, 0xA80, 6, 5, 4), + MTK_PIN_PUPD_SPEC(83, 0xA80, 10, 9, 8), + MTK_PIN_PUPD_SPEC(84, 0xA80, 18, 17, 16), + MTK_PIN_PUPD_SPEC(85, 0xA80, 22, 21, 20), + MTK_PIN_PUPD_SPEC(86, 0xA80, 26, 25, 24), + /* MTK_PIN_PUPD_SPEC(160,0xC90,3,2,1), */ + /* MTK_PIN_PUPD_SPEC(161,0xC90,7,6,5), */ + /* MTK_PIN_PUPD_SPEC(162,0xC90,11,10,9), */ + /* MTK_PIN_PUPD_SPEC(163,0xC90,19,18,17), */ + /* MTK_PIN_PUPD_SPEC(164,0xC90,23,22,21), */ + /* MTK_PIN_PUPD_SPEC(165,0xC90,27,26,25), */ + MTK_PIN_PUPD_SPEC(166, 0xC80, 2, 1, 0), + MTK_PIN_PUPD_SPEC(167, 0xC80, 6, 5, 4), + MTK_PIN_PUPD_SPEC(168, 0xC80, 10, 9, 8), + MTK_PIN_PUPD_SPEC(169, 0xC80, 14, 13, 12), + MTK_PIN_PUPD_SPEC(170, 0xC80, 18, 17, 16), + MTK_PIN_PUPD_SPEC(171, 0xC80, 22, 21, 20), + MTK_PIN_PUPD_SPEC(172, 0xD80, 2, 1, 0), + MTK_PIN_PUPD_SPEC(173, 0xD80, 10, 9, 8), + MTK_PIN_PUPD_SPEC(174, 0xD80, 6, 5, 4), + MTK_PIN_PUPD_SPEC(175, 0xD80, 14, 13, 12), + MTK_PIN_PUPD_SPEC(176, 0xD80, 18, 17, 16), + MTK_PIN_PUPD_SPEC(177, 0xD80, 22, 21, 20), + MTK_PIN_PUPD_SPEC(178, 0xD80, 26, 25, 24), + MTK_PIN_PUPD_SPEC(179, 0xD80, 30, 29, 28), + MTK_PIN_PUPD_SPEC(180, 0xD90, 2, 1, 0), + MTK_PIN_PUPD_SPEC(181, 0xD90, 6, 5, 4), + MTK_PIN_PUPD_SPEC(182, 0xD90, 10, 9, 8), + MTK_PIN_PUPD_SPEC(183, 0xD90, 14, 13, 12), + MTK_PIN_PUPD_SPEC(198, 0x880, 2, 1, 0), + MTK_PIN_PUPD_SPEC(199, 0x880, 6, 5, 4), + MTK_PIN_PUPD_SPEC(200, 0x880, 10, 9, 8), + MTK_PIN_PUPD_SPEC(201, 0x880, 14, 13, 12), + MTK_PIN_PUPD_SPEC(202, 0x880, 18, 17, 16), + MTK_PIN_PUPD_SPEC(203, 0x880, 22, 21, 20), +}; +#endif + +#if 0 +static int spec_pull_set(struct regmap *regmap, unsigned int pin, + unsigned char align, bool isup, unsigned int r1r0) +{ + unsigned int i; + unsigned int reg_pupd, reg_set, reg_rst; + unsigned int bit_pupd, bit_r0, bit_r1; + const struct mtk_pin_spec_pupd_set *spec_pupd_pin; + bool find = false; + + for (i = 0; i < ARRAY_SIZE(mt6735_spec_pupd); i++) { + if (pin == mt6735_spec_pupd[i].pin) { + find = true; + break; + } + } + + if (!find) + return -EINVAL; + + spec_pupd_pin = mt6735_spec_pupd + i; + reg_set = spec_pupd_pin->offset + align; + reg_rst = spec_pupd_pin->offset + (align << 1); + + if (isup) + reg_pupd = reg_rst; + else + reg_pupd = reg_set; + + bit_pupd = BIT(spec_pupd_pin->pupd_bit); + regmap_write(regmap, reg_pupd, bit_pupd); + + bit_r0 = BIT(spec_pupd_pin->r0_bit); + bit_r1 = BIT(spec_pupd_pin->r1_bit); + + switch (r1r0) { + case MTK_PUPD_SET_R1R0_00: + regmap_write(regmap, reg_rst, bit_r0); + regmap_write(regmap, reg_rst, bit_r1); + break; + case MTK_PUPD_SET_R1R0_01: + regmap_write(regmap, reg_set, bit_r0); + regmap_write(regmap, reg_rst, bit_r1); + break; + case MTK_PUPD_SET_R1R0_10: + regmap_write(regmap, reg_rst, bit_r0); + regmap_write(regmap, reg_set, bit_r1); + break; + case MTK_PUPD_SET_R1R0_11: + regmap_write(regmap, reg_set, bit_r0); + regmap_write(regmap, reg_set, bit_r1); + break; + default: + return -EINVAL; + } + + return 0; +} +#endif + +#if 0 +static const struct mtk_pin_ies_smt_set mt6735_ies_smt_set[] = { + MTK_PIN_IES_SMT_SET(0, 4, 0x930, 1), + MTK_PIN_IES_SMT_SET(5, 9, 0x930, 2), + MTK_PIN_IES_SMT_SET(10, 13, 0x930, 10), + MTK_PIN_IES_SMT_SET(14, 15, 0x940, 10), + MTK_PIN_IES_SMT_SET(16, 16, 0x930, 0), + MTK_PIN_IES_SMT_SET(17, 17, 0x950, 2), + MTK_PIN_IES_SMT_SET(18, 21, 0x940, 3), + MTK_PIN_IES_SMT_SET(29, 32, 0x930, 3), + MTK_PIN_IES_SMT_SET(33, 33, 0x930, 4), + MTK_PIN_IES_SMT_SET(34, 36, 0x930, 5), + MTK_PIN_IES_SMT_SET(37, 38, 0x930, 6), + MTK_PIN_IES_SMT_SET(39, 39, 0x930, 7), + MTK_PIN_IES_SMT_SET(40, 41, 0x930, 9), + MTK_PIN_IES_SMT_SET(42, 42, 0x940, 0), + MTK_PIN_IES_SMT_SET(43, 44, 0x930, 11), + MTK_PIN_IES_SMT_SET(45, 46, 0x930, 12), + MTK_PIN_IES_SMT_SET(57, 64, 0xc20, 13), + MTK_PIN_IES_SMT_SET(65, 65, 0xc10, 13), + MTK_PIN_IES_SMT_SET(66, 66, 0xc00, 13), + MTK_PIN_IES_SMT_SET(67, 67, 0xd10, 13), + MTK_PIN_IES_SMT_SET(68, 68, 0xd00, 13), + MTK_PIN_IES_SMT_SET(69, 72, 0x940, 14), + MTK_PIN_IES_SMT_SET(73, 76, 0xc60, 13), + MTK_PIN_IES_SMT_SET(77, 77, 0xc40, 13), + MTK_PIN_IES_SMT_SET(78, 78, 0xc50, 13), + MTK_PIN_IES_SMT_SET(79, 82, 0x940, 15), + MTK_PIN_IES_SMT_SET(83, 83, 0x950, 0), + MTK_PIN_IES_SMT_SET(84, 85, 0x950, 1), + MTK_PIN_IES_SMT_SET(86, 91, 0x950, 2), + MTK_PIN_IES_SMT_SET(92, 92, 0x930, 13), + MTK_PIN_IES_SMT_SET(93, 95, 0x930, 14), + MTK_PIN_IES_SMT_SET(96, 99, 0x930, 15), + MTK_PIN_IES_SMT_SET(100, 103, 0xca0, 13), + MTK_PIN_IES_SMT_SET(104, 104, 0xc80, 13), + MTK_PIN_IES_SMT_SET(105, 105, 0xc90, 13), + MTK_PIN_IES_SMT_SET(106, 107, 0x940, 4), + MTK_PIN_IES_SMT_SET(108, 112, 0x940, 1), + MTK_PIN_IES_SMT_SET(113, 116, 0x940, 2), + MTK_PIN_IES_SMT_SET(117, 118, 0x940, 5), + MTK_PIN_IES_SMT_SET(119, 124, 0x940, 6), + MTK_PIN_IES_SMT_SET(125, 126, 0x940, 7), + MTK_PIN_IES_SMT_SET(127, 127, 0x940, 0), + MTK_PIN_IES_SMT_SET(128, 128, 0x950, 8), + MTK_PIN_IES_SMT_SET(129, 130, 0x950, 9), + MTK_PIN_IES_SMT_SET(131, 132, 0x950, 8), + MTK_PIN_IES_SMT_SET(133, 134, 0x910, 8) +}; +#endif + +#if 0 +int spec_ies_smt_set(struct regmap *regmap, unsigned int pin, + unsigned char align, int value) +{ + unsigned int i, reg_addr, bit; + bool find = false; + + for (i = 0; i < ARRAY_SIZE(mt6735_ies_smt_set); i++) { + if (pin >= mt6735_ies_smt_set[i].start && + pin <= mt6735_ies_smt_set[i].end) { + find = true; + break; + } + } + + if (!find) + return -EINVAL; + + if (value) + reg_addr = mt6735_ies_smt_set[i].offset + align; + else + reg_addr = mt6735_ies_smt_set[i].offset + (align << 1); + + bit = BIT(mt6735_ies_smt_set[i].bit); + regmap_write(regmap, reg_addr, bit); + return 0; +} +#endif + +static const struct mtk_pinctrl_devdata mt6755_pinctrl_data = { + .pins = mtk_pins_mt6755, + .npins = ARRAY_SIZE(mtk_pins_mt6755), + .grp_desc = NULL, + .n_grp_cls = 0, + .pin_drv_grp = NULL, + .n_pin_drv_grps = 0, + /* .spec_pull_set = spec_pull_set, */ + /* .spec_ies_smt_set = spec_ies_smt_set, */ + .spec_set_gpio_mode = mt_set_gpio_mode, + .mt_set_gpio_dir = mt_set_gpio_dir, + .mt_get_gpio_dir = mt_get_gpio_dir, + .mt_get_gpio_out = mt_get_gpio_out, + .mt_set_gpio_out = mt_set_gpio_out, + .mt_set_gpio_ies = mt_set_gpio_ies, + .mt_set_gpio_smt = mt_set_gpio_smt, + .mt_set_gpio_pull_enable = mt_set_gpio_pull_enable, + .mt_set_gpio_pull_select = mt_set_gpio_pull_select, + .mt_get_gpio_in = mt_get_gpio_in, + /* .dir_offset = 0x0000, */ + /* .pullen_offset = 0x0100, */ + /* .pullsel_offset = 0x0200, */ + /* .dout_offset = 0x0100, */ + /* .din_offset = 0x0200, */ + /* .pinmux_offset = 0x300, */ + .type1_start = 204, + .type1_end = 204, + .port_shf = 4, + .port_mask = 0xf, + .port_align = 4, + .chip_type = MTK_CHIP_TYPE_BASE, + /* + .eint_offsets = { + .name = "mt6735_eint", + .stat = 0x000, + .ack = 0x040, + .mask = 0x080, + .mask_set = 0x0c0, + .mask_clr = 0x100, + .sens = 0x140, + .sens_set = 0x180, + .sens_clr = 0x1c0, + .soft = 0x200, + .soft_set = 0x240, + .soft_clr = 0x280, + .pol = 0x300, + .pol_set = 0x340, + .pol_clr = 0x380, + .dom_en = 0x400, + .dbnc_ctrl = 0x500, + .dbnc_set = 0x600, + .dbnc_clr = 0x700, + .port_mask = 7, + .ports = 6, + }, + .ap_num = 224, + .db_cnt = 16, + */ +}; + +static int mt6755_pinctrl_probe(struct platform_device *pdev) +{ + pr_warn("mt6755 pinctrl probe\n"); + return mtk_pctrl_init(pdev, &mt6755_pinctrl_data, NULL); +} + +static struct of_device_id mt6755_pctrl_match[] = { + { + .compatible = "mediatek,mt6755-pinctrl", + }, { + } +}; +MODULE_DEVICE_TABLE(of, mt6755_pctrl_match); + +static struct platform_driver mtk_pinctrl_driver = { + .probe = mt6755_pinctrl_probe, + .driver = { + .name = "mediatek-mt6755-pinctrl", + .owner = THIS_MODULE, + .of_match_table = mt6755_pctrl_match, + }, +}; + +static int __init mtk_pinctrl_init(void) +{ + return platform_driver_register(&mtk_pinctrl_driver); +} + +/* module_init(mtk_pinctrl_init); */ + +postcore_initcall(mtk_pinctrl_init); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek Pinctrl Driver"); +MODULE_AUTHOR("Hongzhou Yang "); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6755.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6755.h new file mode 100644 index 0000000000000000000000000000000000000000..0d65dab797a2e1bcd9644869f9b02964de014d6e --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6755.h @@ -0,0 +1,1796 @@ +/* + * Generated by MTK SP DrvGen Version 03.13.6 for MT6755. Copyright MediaTek Inc. (C) 2013. + * Wed Jul 22 21:04:21 2015 + * Do Not Modify the File. + */ + +/************************* + * GPIO PINCTRLMTK File +*************************/ + +#ifndef __PINCTRL_MTK_MT6755_H +#define __PINCTRL_MTK_MT6755_H + +#include +#include "pinctrl-mtk-common.h" + +static const struct mtk_desc_pin mtk_pins_mt6755[] = { + MTK_PIN( + PINCTRL_PIN(0, "GPIO0"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO0"), + MTK_FUNCTION(2, "EXT_FRAME_SYNC"), + MTK_FUNCTION(3, "CLKM0"), + MTK_FUNCTION(4, "IDDIG"), + MTK_FUNCTION(5, "C2K_EINT0"), + MTK_FUNCTION(6, "I2S3_MCK") + ), + MTK_PIN( + PINCTRL_PIN(1, "GPIO1"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO1"), + MTK_FUNCTION(2, "EXT_FRAME_SYNC"), + MTK_FUNCTION(3, "CLKM1"), + MTK_FUNCTION(4, "USB_DRVVBUS"), + MTK_FUNCTION(5, "C2K_EINT1"), + MTK_FUNCTION(6, "I2S3_BCK") + ), + MTK_PIN( + PINCTRL_PIN(2, "GPIO2"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO2"), + MTK_FUNCTION(1, "CMFLASH"), + MTK_FUNCTION(2, "UTXD1"), + MTK_FUNCTION(3, "CLKM2"), + MTK_FUNCTION(4, "MD_URXD2"), + MTK_FUNCTION(5, "C2K_UTXD1"), + MTK_FUNCTION(6, "I2S3_LRCK") + ), + MTK_PIN( + PINCTRL_PIN(3, "GPIO3"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO3"), + MTK_FUNCTION(1, "PWM_A"), + MTK_FUNCTION(2, "URXD1"), + MTK_FUNCTION(3, "CLKM3"), + MTK_FUNCTION(4, "MD_UTXD2"), + MTK_FUNCTION(5, "C2K_URXD1"), + MTK_FUNCTION(6, "I2S3_DO"), + MTK_FUNCTION(7, "SPI1_B_MI") + ), + MTK_PIN( + PINCTRL_PIN(4, "GPIO4"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO4"), + MTK_FUNCTION(1, "PWM_B"), + MTK_FUNCTION(2, "I2S0_MCK"), + MTK_FUNCTION(3, "UCTS0"), + MTK_FUNCTION(4, "MD_URXD1"), + MTK_FUNCTION(5, "C2K_UTXD0"), + MTK_FUNCTION(6, "ANT_SEL3"), + MTK_FUNCTION(7, "SPI1_B_MI") + ), + MTK_PIN( + PINCTRL_PIN(5, "GPIO5"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO5"), + MTK_FUNCTION(1, "PWM_C"), + MTK_FUNCTION(2, "I2S0_BCK"), + MTK_FUNCTION(3, "URTS0"), + MTK_FUNCTION(4, "MD_UTXD1"), + MTK_FUNCTION(5, "C2K_URXD0"), + MTK_FUNCTION(6, "ANT_SEL4"), + MTK_FUNCTION(7, "SPI1_B_CSB") + ), + MTK_PIN( + PINCTRL_PIN(6, "GPIO6"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO6"), + MTK_FUNCTION(1, "IRTX_OUT"), + MTK_FUNCTION(2, "I2S0_LRCK"), + MTK_FUNCTION(3, "IDDIG"), + MTK_FUNCTION(4, "MD_URXD0"), + MTK_FUNCTION(5, "SDA0"), + MTK_FUNCTION(6, "ANT_SEL5"), + MTK_FUNCTION(7, "SPI1_B_MO") + ), + MTK_PIN( + PINCTRL_PIN(7, "GPIO7"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO7"), + MTK_FUNCTION(1, "IRTX_OUT"), + MTK_FUNCTION(2, "I2S0_DI"), + MTK_FUNCTION(3, "USB_DRVVBUS"), + MTK_FUNCTION(4, "MD_UTXD0"), + MTK_FUNCTION(5, "SCL0"), + MTK_FUNCTION(6, "PCC_PPC_IO"), + MTK_FUNCTION(7, "SPI1_B_CLK") + ), + MTK_PIN( + PINCTRL_PIN(8, "GPIO8"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO8"), + MTK_FUNCTION(1, "PWM_A"), + MTK_FUNCTION(2, "PCC_PPC_IO"), + MTK_FUNCTION(4, "CONN_MCU_TRST_B"), + MTK_FUNCTION(5, "C2K_DM_JTINTP"), + MTK_FUNCTION(6, "IO_JTAG_TRSTN"), + MTK_FUNCTION(7, "DBG_MON_A44") + ), + MTK_PIN( + PINCTRL_PIN(9, "GPIO9"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO9"), + MTK_FUNCTION(1, "PWM_B"), + MTK_FUNCTION(2, "UCTS1"), + MTK_FUNCTION(3, "DAP_SIB1_SWD"), + MTK_FUNCTION(4, "CONN_MCU_DBGACK_N"), + MTK_FUNCTION(5, "IRTX_OUT"), + MTK_FUNCTION(7, "DBG_MON_A45") + ), + MTK_PIN( + PINCTRL_PIN(10, "GPIO10"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO10"), + MTK_FUNCTION(1, "PWM_C"), + MTK_FUNCTION(2, "URTS1"), + MTK_FUNCTION(3, "DAP_SIB1_SWCK"), + MTK_FUNCTION(4, "CONN_MCU_DBGI_N"), + MTK_FUNCTION(5, "EXT_FRAME_SYNC"), + MTK_FUNCTION(7, "DBG_MON_A46") + ), + MTK_PIN( + PINCTRL_PIN(11, "GPIO11"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO11"), + MTK_FUNCTION(1, "IRTX_OUT"), + MTK_FUNCTION(2, "IDDIG"), + MTK_FUNCTION(3, "I2S1_MCK"), + MTK_FUNCTION(4, "PWM_B"), + MTK_FUNCTION(5, "CLKM0"), + MTK_FUNCTION(6, "SRCLKENAI1") + ), + MTK_PIN( + PINCTRL_PIN(12, "GPIO12"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO12"), + MTK_FUNCTION(1, "IRTX_OUT"), + MTK_FUNCTION(2, "USB_DRVVBUS"), + MTK_FUNCTION(3, "I2S2_DI"), + MTK_FUNCTION(4, "PWM_C"), + MTK_FUNCTION(5, "CLKM1"), + MTK_FUNCTION(6, "CMFLASH") + ), + MTK_PIN( + PINCTRL_PIN(13, "GPIO13"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO13"), + MTK_FUNCTION(1, "DPI_D0"), + MTK_FUNCTION(2, "MRG_SYNC"), + MTK_FUNCTION(3, "PCM0_SYNC"), + MTK_FUNCTION(4, "MD_URXD0"), + MTK_FUNCTION(5, "C2K_EINT0"), + MTK_FUNCTION(6, "I2S0_MCK"), + MTK_FUNCTION(7, "DBG_MON_A19") + ), + MTK_PIN( + PINCTRL_PIN(14, "GPIO14"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO14"), + MTK_FUNCTION(1, "DPI_D1"), + MTK_FUNCTION(2, "MRG_CLK"), + MTK_FUNCTION(3, "PCM0_CLK"), + MTK_FUNCTION(4, "MD_UTXD0"), + MTK_FUNCTION(5, "C2K_EINT1"), + MTK_FUNCTION(6, "I2S0_BCK"), + MTK_FUNCTION(7, "DBG_MON_A20") + ), + MTK_PIN( + PINCTRL_PIN(15, "GPIO15"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO15"), + MTK_FUNCTION(1, "DPI_D2"), + MTK_FUNCTION(2, "MRG_DO"), + MTK_FUNCTION(3, "PCM0_DO"), + MTK_FUNCTION(4, "MD_URXD1"), + MTK_FUNCTION(5, "C2K_DM_EINT0"), + MTK_FUNCTION(6, "I2S0_LRCK"), + MTK_FUNCTION(7, "DBG_MON_A21") + ), + MTK_PIN( + PINCTRL_PIN(16, "GPIO16"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO16"), + MTK_FUNCTION(1, "DPI_D3"), + MTK_FUNCTION(2, "MRG_DI"), + MTK_FUNCTION(3, "PCM0_DI"), + MTK_FUNCTION(4, "MD_UTXD1"), + MTK_FUNCTION(5, "C2K_DM_EINT1"), + MTK_FUNCTION(6, "I2S0_DI"), + MTK_FUNCTION(7, "DBG_MON_A22") + ), + MTK_PIN( + PINCTRL_PIN(17, "GPIO17"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO17"), + MTK_FUNCTION(1, "DPI_D4"), + MTK_FUNCTION(2, "UCTS1"), + MTK_FUNCTION(3, "CONN_MCU_TRST_B"), + MTK_FUNCTION(4, "MD_URXD2"), + MTK_FUNCTION(5, "C2K_URXD0"), + MTK_FUNCTION(6, "I2S1_MCK"), + MTK_FUNCTION(7, "DBG_MON_A23") + ), + MTK_PIN( + PINCTRL_PIN(18, "GPIO18"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO18"), + MTK_FUNCTION(1, "DPI_D5"), + MTK_FUNCTION(2, "URTS1"), + MTK_FUNCTION(3, "CONN_MCU_DBGI_N"), + MTK_FUNCTION(4, "MD_UTXD2"), + MTK_FUNCTION(5, "C2K_UTXD0"), + MTK_FUNCTION(6, "I2S1_BCK"), + MTK_FUNCTION(7, "DBG_MON_A24") + ), + MTK_PIN( + PINCTRL_PIN(19, "GPIO19"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO19"), + MTK_FUNCTION(1, "DPI_D6"), + MTK_FUNCTION(2, "URXD1"), + MTK_FUNCTION(3, "CONN_MCU_TDO"), + MTK_FUNCTION(4, "MD_INT2_C2K_UIM1_HOT_PLUG"), + MTK_FUNCTION(6, "I2S1_LRCK"), + MTK_FUNCTION(7, "DBG_MON_A25") + ), + MTK_PIN( + PINCTRL_PIN(20, "GPIO20"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO20"), + MTK_FUNCTION(1, "DPI_D7"), + MTK_FUNCTION(2, "UTXD1"), + MTK_FUNCTION(3, "CONN_MCU_DBGACK_N"), + MTK_FUNCTION(4, "MD_INT1_C2K_UIM0_HOT_PLUG"), + MTK_FUNCTION(6, "I2S1_DO"), + MTK_FUNCTION(7, "DBG_MON_A26") + ), + MTK_PIN( + PINCTRL_PIN(21, "GPIO21"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO21"), + MTK_FUNCTION(1, "DPI_D8"), + MTK_FUNCTION(2, "SRCLKENAI1"), + MTK_FUNCTION(3, "CONN_MCU_TMS"), + MTK_FUNCTION(4, "DAP_SIB1_SWD"), + MTK_FUNCTION(5, "CONN_MCU_AICE_TMSC"), + MTK_FUNCTION(6, "I2S2_MCK"), + MTK_FUNCTION(7, "DBG_MON_A27") + ), + MTK_PIN( + PINCTRL_PIN(22, "GPIO22"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO22"), + MTK_FUNCTION(1, "DPI_D9"), + MTK_FUNCTION(2, "EXT_FRAME_SYNC"), + MTK_FUNCTION(3, "CONN_MCU_TCK"), + MTK_FUNCTION(4, "DAP_SIB1_SWCK"), + MTK_FUNCTION(5, "CONN_MCU_AICE_TCKC"), + MTK_FUNCTION(6, "I2S2_BCK"), + MTK_FUNCTION(7, "DBG_MON_A28") + ), + MTK_PIN( + PINCTRL_PIN(23, "GPIO23"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO23"), + MTK_FUNCTION(1, "DPI_D10"), + MTK_FUNCTION(2, "IDDIG"), + MTK_FUNCTION(3, "CONN_MCU_TDI"), + MTK_FUNCTION(5, "PWM_B"), + MTK_FUNCTION(6, "I2S2_LRCK"), + MTK_FUNCTION(7, "DBG_MON_A29") + ), + MTK_PIN( + PINCTRL_PIN(24, "GPIO24"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO24"), + MTK_FUNCTION(1, "DPI_D11"), + MTK_FUNCTION(2, "USB_DRVVBUS"), + MTK_FUNCTION(3, "CONN_DSP_JCK"), + MTK_FUNCTION(4, "SPI1_A_MI"), + MTK_FUNCTION(5, "PWM_C"), + MTK_FUNCTION(6, "I2S2_DI"), + MTK_FUNCTION(7, "DBG_MON_A30") + ), + MTK_PIN( + PINCTRL_PIN(25, "GPIO25"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO25"), + MTK_FUNCTION(1, "DPI_HSYNC"), + MTK_FUNCTION(2, "SPI1_A_MI"), + MTK_FUNCTION(3, "CONN_DSP_JMS"), + MTK_FUNCTION(4, "CLKM0"), + MTK_FUNCTION(5, "C2K_UTXD1"), + MTK_FUNCTION(6, "I2S3_MCK"), + MTK_FUNCTION(7, "DBG_MON_A31") + ), + MTK_PIN( + PINCTRL_PIN(26, "GPIO26"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO26"), + MTK_FUNCTION(1, "DPI_VSYNC"), + MTK_FUNCTION(2, "SPI1_A_CSB"), + MTK_FUNCTION(3, "CONN_DSP_JDI"), + MTK_FUNCTION(4, "CLKM1"), + MTK_FUNCTION(5, "C2K_URXD1"), + MTK_FUNCTION(6, "I2S3_BCK"), + MTK_FUNCTION(7, "DBG_MON_A32") + ), + MTK_PIN( + PINCTRL_PIN(27, "GPIO27"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO27"), + MTK_FUNCTION(1, "DPI_DE"), + MTK_FUNCTION(2, "SPI1_A_MO"), + MTK_FUNCTION(3, "CONN_DSP_JDO"), + MTK_FUNCTION(4, "CLKM2"), + MTK_FUNCTION(5, "C2K_DM_EINT2"), + MTK_FUNCTION(6, "I2S3_LRCK"), + MTK_FUNCTION(7, "DBG_MON_A33") + ), + MTK_PIN( + PINCTRL_PIN(28, "GPIO28"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO28"), + MTK_FUNCTION(1, "DPI_CK"), + MTK_FUNCTION(2, "SPI1_A_CLK"), + MTK_FUNCTION(3, "CONN_DSP_JINTP"), + MTK_FUNCTION(4, "CLKM3"), + MTK_FUNCTION(5, "C2K_DM_EINT3"), + MTK_FUNCTION(6, "I2S3_DO"), + MTK_FUNCTION(7, "DBG_MON_A34") + ), + MTK_PIN( + PINCTRL_PIN(29, "GPIO29"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO29"), + MTK_FUNCTION(1, "SRCLKENA1") + ), + MTK_PIN( + PINCTRL_PIN(30, "GPIO30"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO30"), + MTK_FUNCTION(1, "MSDC1_CLK"), + MTK_FUNCTION(2, "IO_JTAG_TCK"), + MTK_FUNCTION(4, "CONN_DSP_JCK"), + MTK_FUNCTION(5, "C2K_DM_OTCK"), + MTK_FUNCTION(6, "C2K_TCK"), + MTK_FUNCTION(7, "DBG_MON_A53") + ), + MTK_PIN( + PINCTRL_PIN(31, "GPIO31"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO31"), + MTK_FUNCTION(1, "MSDC1_DAT3"), + MTK_FUNCTION(3, "DAP_SIB1_SWD"), + MTK_FUNCTION(4, "CONN_DSP_JINTP"), + MTK_FUNCTION(5, "C2K_DM_JTINTP"), + MTK_FUNCTION(6, "C2K_RTCK"), + MTK_FUNCTION(7, "DBG_MON_A54") + ), + MTK_PIN( + PINCTRL_PIN(32, "GPIO32"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO32"), + MTK_FUNCTION(1, "MSDC1_CMD"), + MTK_FUNCTION(2, "IO_JTAG_TMS"), + MTK_FUNCTION(4, "CONN_DSP_JMS"), + MTK_FUNCTION(5, "C2K_DM_OTMS"), + MTK_FUNCTION(6, "C2K_TMS"), + MTK_FUNCTION(7, "DBG_MON_A55") + ), + MTK_PIN( + PINCTRL_PIN(33, "GPIO33"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO33"), + MTK_FUNCTION(1, "MSDC1_DAT0"), + MTK_FUNCTION(2, "IO_JTAG_TDI"), + MTK_FUNCTION(4, "CONN_DSP_JDI"), + MTK_FUNCTION(5, "C2K_DM_OTDI"), + MTK_FUNCTION(6, "C2K_TDI"), + MTK_FUNCTION(7, "DBG_MON_A56") + ), + MTK_PIN( + PINCTRL_PIN(34, "GPIO34"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO34"), + MTK_FUNCTION(1, "MSDC1_DAT2"), + MTK_FUNCTION(2, "IO_JTAG_TRSTN"), + MTK_FUNCTION(5, "DAP_SIB1_SWCK"), + MTK_FUNCTION(6, "C2K_NTRST"), + MTK_FUNCTION(7, "DBG_MON_A57") + ), + MTK_PIN( + PINCTRL_PIN(35, "GPIO35"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO35"), + MTK_FUNCTION(1, "MSDC1_DAT1"), + MTK_FUNCTION(2, "IO_JTAG_TDO"), + MTK_FUNCTION(4, "CONN_DSP_JDO"), + MTK_FUNCTION(5, "C2K_DM_OTDO"), + MTK_FUNCTION(6, "C2K_TDO"), + MTK_FUNCTION(7, "DBG_MON_A58") + ), + MTK_PIN( + PINCTRL_PIN(36, "GPIO36"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO36"), + MTK_FUNCTION(1, "MD1_SIM2_SIO"), + MTK_FUNCTION(3, "MD1_SIM1_SIO"), + MTK_FUNCTION(5, "C2K_UIM0_IO"), + MTK_FUNCTION(6, "C2K_UIM1_IO"), + MTK_FUNCTION(7, "DBG_MON_A38") + ), + MTK_PIN( + PINCTRL_PIN(37, "GPIO37"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO37"), + MTK_FUNCTION(1, "MD1_SIM2_SRST"), + MTK_FUNCTION(3, "MD1_SIM1_SRST"), + MTK_FUNCTION(5, "C2K_UIM0_RST"), + MTK_FUNCTION(6, "C2K_UIM1_RST"), + MTK_FUNCTION(7, "DBG_MON_A39") + ), + MTK_PIN( + PINCTRL_PIN(38, "GPIO38"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO38"), + MTK_FUNCTION(1, "MD1_SIM2_SCLK"), + MTK_FUNCTION(3, "MD1_SIM1_SCLK"), + MTK_FUNCTION(5, "C2K_UIM0_CLK"), + MTK_FUNCTION(6, "C2K_UIM1_CLK"), + MTK_FUNCTION(7, "DBG_MON_A40") + ), + MTK_PIN( + PINCTRL_PIN(39, "GPIO39"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO39"), + MTK_FUNCTION(1, "MD1_SIM1_SCLK"), + MTK_FUNCTION(3, "MD1_SIM2_SCLK"), + MTK_FUNCTION(5, "C2K_UIM0_CLK"), + MTK_FUNCTION(6, "C2K_UIM1_CLK"), + MTK_FUNCTION(7, "DBG_MON_A41") + ), + MTK_PIN( + PINCTRL_PIN(40, "GPIO40"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO40"), + MTK_FUNCTION(1, "MD1_SIM1_SRST"), + MTK_FUNCTION(3, "MD1_SIM2_SRST"), + MTK_FUNCTION(5, "C2K_UIM0_RST"), + MTK_FUNCTION(6, "C2K_UIM1_RST"), + MTK_FUNCTION(7, "DBG_MON_A42") + ), + MTK_PIN( + PINCTRL_PIN(41, "GPIO41"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO41"), + MTK_FUNCTION(1, "MD1_SIM1_SIO"), + MTK_FUNCTION(3, "MD1_SIM2_SIO"), + MTK_FUNCTION(5, "C2K_UIM0_IO"), + MTK_FUNCTION(6, "C2K_UIM1_IO"), + MTK_FUNCTION(7, "DBG_MON_A43") + ), + MTK_PIN( + PINCTRL_PIN(42, "GPIO42"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO42"), + MTK_FUNCTION(1, "IDDIG"), + MTK_FUNCTION(2, "URXD1"), + MTK_FUNCTION(3, "UCTS0"), + MTK_FUNCTION(4, "SDA1"), + MTK_FUNCTION(5, "EXT_FRAME_SYNC"), + MTK_FUNCTION(6, "KPCOL2"), + MTK_FUNCTION(7, "DBG_MON_A12") + ), + MTK_PIN( + PINCTRL_PIN(43, "GPIO43"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO43"), + MTK_FUNCTION(1, "USB_DRVVBUS"), + MTK_FUNCTION(2, "UTXD1"), + MTK_FUNCTION(3, "URTS0"), + MTK_FUNCTION(4, "SCL1"), + MTK_FUNCTION(5, "EXT_FRAME_SYNC"), + MTK_FUNCTION(6, "KPROW2"), + MTK_FUNCTION(7, "DBG_MON_A13") + ), + MTK_PIN( + PINCTRL_PIN(44, "GPIO44"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO44"), + MTK_FUNCTION(1, "DSI_TE"), + MTK_FUNCTION(7, "DBG_MON_A15") + ), + MTK_PIN( + PINCTRL_PIN(45, "GPIO45"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO45"), + MTK_FUNCTION(1, "MD_INT2_C2K_UIM1_HOT_PLUG"), + MTK_FUNCTION(2, "URXD1"), + MTK_FUNCTION(3, "UCTS1"), + MTK_FUNCTION(4, "CLKM0"), + MTK_FUNCTION(6, "IDDIG"), + MTK_FUNCTION(7, "DBG_MON_A17") + ), + MTK_PIN( + PINCTRL_PIN(46, "GPIO46"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO46"), + MTK_FUNCTION(1, "MD_INT1_C2K_UIM0_HOT_PLUG"), + MTK_FUNCTION(2, "UTXD1"), + MTK_FUNCTION(3, "URTS1"), + MTK_FUNCTION(4, "PWM_B"), + MTK_FUNCTION(6, "USB_DRVVBUS"), + MTK_FUNCTION(7, "DBG_MON_A18") + ), + MTK_PIN( + PINCTRL_PIN(47, "GPIO47"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO47"), + MTK_FUNCTION(1, "SCL_APPM") + ), + MTK_PIN( + PINCTRL_PIN(48, "GPIO48"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO48"), + MTK_FUNCTION(1, "SDA_APPM") + ), + MTK_PIN( + PINCTRL_PIN(49, "GPIO49"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO49"), + MTK_FUNCTION(1, "SCL3"), + MTK_FUNCTION(2, "IDDIG") + ), + MTK_PIN( + PINCTRL_PIN(50, "GPIO50"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO50"), + MTK_FUNCTION(1, "SDA3"), + MTK_FUNCTION(2, "IDDIG") + ), + MTK_PIN( + PINCTRL_PIN(51, "GPIO51"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO51"), + MTK_FUNCTION(1, "BPI_BUS15"), + MTK_FUNCTION(7, "DBG_MON_B0") + ), + MTK_PIN( + PINCTRL_PIN(52, "GPIO52"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO52"), + MTK_FUNCTION(1, "BPI_BUS14"), + MTK_FUNCTION(7, "DBG_MON_B1") + ), + MTK_PIN( + PINCTRL_PIN(53, "GPIO53"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO53"), + MTK_FUNCTION(1, "BPI_BUS13"), + MTK_FUNCTION(7, "DBG_MON_B2") + ), + MTK_PIN( + PINCTRL_PIN(54, "GPIO54"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO54"), + MTK_FUNCTION(1, "BPI_BUS12"), + MTK_FUNCTION(7, "DBG_MON_B3") + ), + MTK_PIN( + PINCTRL_PIN(55, "GPIO55"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO55"), + MTK_FUNCTION(1, "BPI_BUS11") + ), + MTK_PIN( + PINCTRL_PIN(56, "GPIO56"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO56"), + MTK_FUNCTION(1, "BPI_BUS10") + ), + MTK_PIN( + PINCTRL_PIN(57, "GPIO57"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO57"), + MTK_FUNCTION(1, "BPI_BUS9"), + MTK_FUNCTION(7, "DBG_MON_B4") + ), + MTK_PIN( + PINCTRL_PIN(58, "GPIO58"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO58"), + MTK_FUNCTION(1, "BPI_BUS8"), + MTK_FUNCTION(7, "DBG_MON_B5") + ), + MTK_PIN( + PINCTRL_PIN(59, "GPIO59"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO59"), + MTK_FUNCTION(1, "BPI_BUS7"), + MTK_FUNCTION(7, "DBG_MON_B6") + ), + MTK_PIN( + PINCTRL_PIN(60, "GPIO60"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO60"), + MTK_FUNCTION(1, "BPI_BUS6"), + MTK_FUNCTION(7, "DBG_MON_B7") + ), + MTK_PIN( + PINCTRL_PIN(61, "GPIO61"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO61"), + MTK_FUNCTION(1, "BPI_BUS5"), + MTK_FUNCTION(7, "DBG_MON_B8") + ), + MTK_PIN( + PINCTRL_PIN(62, "GPIO62"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO62"), + MTK_FUNCTION(1, "BPI_BUS4"), + MTK_FUNCTION(7, "DBG_MON_B9") + ), + MTK_PIN( + PINCTRL_PIN(63, "GPIO63"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO63"), + MTK_FUNCTION(1, "MIPI1_SDATA"), + MTK_FUNCTION(7, "DBG_MON_B10") + ), + MTK_PIN( + PINCTRL_PIN(64, "GPIO64"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO64"), + MTK_FUNCTION(1, "MIPI1_SCLK"), + MTK_FUNCTION(7, "DBG_MON_B11") + ), + MTK_PIN( + PINCTRL_PIN(65, "GPIO65"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO65"), + MTK_FUNCTION(1, "MIPI0_SDATA"), + MTK_FUNCTION(7, "DBG_MON_B12") + ), + MTK_PIN( + PINCTRL_PIN(66, "GPIO66"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO66"), + MTK_FUNCTION(1, "MIPI0_SCLK"), + MTK_FUNCTION(7, "DBG_MON_B13") + ), + MTK_PIN( + PINCTRL_PIN(67, "GPIO67"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO67"), + MTK_FUNCTION(1, "RFIC0_BSI_D2"), + MTK_FUNCTION(2, "SPM_BSI_D2"), + MTK_FUNCTION(7, "DBG_MON_B14") + ), + MTK_PIN( + PINCTRL_PIN(68, "GPIO68"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO68"), + MTK_FUNCTION(1, "RFIC0_BSI_D1"), + MTK_FUNCTION(2, "SPM_BSI_D1"), + MTK_FUNCTION(7, "DBG_MON_B15") + ), + MTK_PIN( + PINCTRL_PIN(69, "GPIO69"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO69"), + MTK_FUNCTION(1, "RFIC0_BSI_D0"), + MTK_FUNCTION(2, "SPM_BSI_D0"), + MTK_FUNCTION(7, "DBG_MON_B16") + ), + MTK_PIN( + PINCTRL_PIN(70, "GPIO70"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO70") + ), + MTK_PIN( + PINCTRL_PIN(71, "GPIO71"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO71") + ), + MTK_PIN( + PINCTRL_PIN(72, "GPIO72"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO72") + ), + MTK_PIN( + PINCTRL_PIN(73, "GPIO73"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO73") + ), + MTK_PIN( + PINCTRL_PIN(74, "GPIO74"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO74") + ), + MTK_PIN( + PINCTRL_PIN(75, "GPIO75"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO75"), + MTK_FUNCTION(1, "MIPI3_SDATA"), + MTK_FUNCTION(2, "PWM_C"), + MTK_FUNCTION(3, "IRTX_OUT"), + MTK_FUNCTION(4, "I2S0_DI"), + MTK_FUNCTION(5, "I2S2_DI"), + MTK_FUNCTION(6, "ANT_SEL5"), + MTK_FUNCTION(7, "DBG_MON_B19") + ), + MTK_PIN( + PINCTRL_PIN(76, "GPIO76"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO76"), + MTK_FUNCTION(1, "MIPI3_SCLK"), + MTK_FUNCTION(2, "CLKM3"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(4, "I2S0_LRCK"), + MTK_FUNCTION(5, "I2S2_LRCK"), + MTK_FUNCTION(6, "ANT_SEL4"), + MTK_FUNCTION(7, "DBG_MON_B20") + ), + MTK_PIN( + PINCTRL_PIN(77, "GPIO77"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO77"), + MTK_FUNCTION(1, "MIPI2_SDATA"), + MTK_FUNCTION(2, "USB_DRVVBUS"), + MTK_FUNCTION(3, "IRTX_OUT"), + MTK_FUNCTION(4, "I2S0_BCK"), + MTK_FUNCTION(5, "I2S2_BCK"), + MTK_FUNCTION(6, "ANT_SEL3"), + MTK_FUNCTION(7, "DBG_MON_B21") + ), + MTK_PIN( + PINCTRL_PIN(78, "GPIO78"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO78"), + MTK_FUNCTION(1, "MIPI2_SCLK"), + MTK_FUNCTION(2, "IDDIG"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(4, "I2S0_MCK"), + MTK_FUNCTION(5, "I2S2_MCK"), + MTK_FUNCTION(6, "PCM1_DO0"), + MTK_FUNCTION(7, "DBG_MON_B22") + ), + MTK_PIN( + PINCTRL_PIN(79, "GPIO79"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO79"), + MTK_FUNCTION(1, "BPI_BUS3"), + MTK_FUNCTION(7, "DBG_MON_B23") + ), + MTK_PIN( + PINCTRL_PIN(80, "GPIO80"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO80"), + MTK_FUNCTION(1, "BPI_BUS2"), + MTK_FUNCTION(7, "DBG_MON_B24") + ), + MTK_PIN( + PINCTRL_PIN(81, "GPIO81"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO81"), + MTK_FUNCTION(1, "BPI_BUS1"), + MTK_FUNCTION(7, "DBG_MON_B25") + ), + MTK_PIN( + PINCTRL_PIN(82, "GPIO82"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO82"), + MTK_FUNCTION(1, "BPI_BUS0"), + MTK_FUNCTION(7, "DBG_MON_B26") + ), + MTK_PIN( + PINCTRL_PIN(83, "GPIO83"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO83"), + MTK_FUNCTION(1, "BPI_BUS23"), + MTK_FUNCTION(2, "DET_BPI1"), + MTK_FUNCTION(4, "I2S3_DO"), + MTK_FUNCTION(5, "I2S1_DO"), + MTK_FUNCTION(6, "PCM1_DO1"), + MTK_FUNCTION(7, "DBG_MON_B27") + ), + MTK_PIN( + PINCTRL_PIN(84, "GPIO84"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO84"), + MTK_FUNCTION(1, "BPI_BUS22"), + MTK_FUNCTION(2, "DET_BPI0"), + MTK_FUNCTION(4, "I2S3_LRCK"), + MTK_FUNCTION(5, "I2S1_LRCK"), + MTK_FUNCTION(6, "PCM1_CLK"), + MTK_FUNCTION(7, "DBG_MON_B28") + ), + MTK_PIN( + PINCTRL_PIN(85, "GPIO85"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO85"), + MTK_FUNCTION(1, "BPI_BUS21"), + MTK_FUNCTION(2, "TX_SWAP3"), + MTK_FUNCTION(7, "DBG_MON_B29") + ), + MTK_PIN( + PINCTRL_PIN(86, "GPIO86"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO86"), + MTK_FUNCTION(1, "BPI_BUS20"), + MTK_FUNCTION(2, "TX_SWAP2"), + MTK_FUNCTION(7, "DBG_MON_B30") + ), + MTK_PIN( + PINCTRL_PIN(87, "GPIO87"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO87"), + MTK_FUNCTION(1, "BPI_BUS19"), + MTK_FUNCTION(2, "TX_SWAP1"), + MTK_FUNCTION(7, "DBG_MON_B31") + ), + MTK_PIN( + PINCTRL_PIN(88, "GPIO88"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO88"), + MTK_FUNCTION(1, "BPI_BUS18"), + MTK_FUNCTION(2, "TX_SWAP0") + ), + MTK_PIN( + PINCTRL_PIN(89, "GPIO89"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO89"), + MTK_FUNCTION(1, "BPI_BUS17"), + MTK_FUNCTION(2, "PA_VM1"), + MTK_FUNCTION(4, "I2S3_BCK"), + MTK_FUNCTION(5, "I2S1_BCK"), + MTK_FUNCTION(6, "PCM1_SYNC") + ), + MTK_PIN( + PINCTRL_PIN(90, "GPIO90"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO90"), + MTK_FUNCTION(1, "BPI_BUS16"), + MTK_FUNCTION(2, "PA_VM0"), + MTK_FUNCTION(4, "I2S3_MCK"), + MTK_FUNCTION(5, "I2S1_MCK"), + MTK_FUNCTION(6, "PCM1_DI") + ), + MTK_PIN( + PINCTRL_PIN(91, "GPIO91"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO91"), + MTK_FUNCTION(1, "SDA1"), + MTK_FUNCTION(2, "IDDIG") + ), + MTK_PIN( + PINCTRL_PIN(92, "GPIO92"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO92"), + MTK_FUNCTION(1, "SDA0") + ), + MTK_PIN( + PINCTRL_PIN(93, "GPIO93"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO93"), + MTK_FUNCTION(1, "SCL0") + ), + MTK_PIN( + PINCTRL_PIN(94, "GPIO94"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO94"), + MTK_FUNCTION(1, "SCL1"), + MTK_FUNCTION(2, "IDDIG") + ), + MTK_PIN( + PINCTRL_PIN(95, "GPIO95"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO95"), + MTK_FUNCTION(1, "SPI0_MI"), + MTK_FUNCTION(2, "MRG_SYNC"), + MTK_FUNCTION(3, "PCM0_SYNC"), + MTK_FUNCTION(4, "I2S1_BCK"), + MTK_FUNCTION(5, "SPI0_MO"), + MTK_FUNCTION(6, "DFD_TDO"), + MTK_FUNCTION(7, "JTDO_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(96, "GPIO96"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO96"), + MTK_FUNCTION(1, "SPI0_CSB"), + MTK_FUNCTION(2, "MRG_DO"), + MTK_FUNCTION(3, "PCM0_DO"), + MTK_FUNCTION(4, "I2S1_LRCK"), + MTK_FUNCTION(5, "SDA2"), + MTK_FUNCTION(6, "DFD_TMS"), + MTK_FUNCTION(7, "JTMS_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(97, "GPIO97"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO97"), + MTK_FUNCTION(1, "SPI0_MO"), + MTK_FUNCTION(2, "MRG_CLK"), + MTK_FUNCTION(3, "PCM0_CLK"), + MTK_FUNCTION(4, "I2S1_DO"), + MTK_FUNCTION(5, "SPI0_MI"), + MTK_FUNCTION(6, "DFD_TDI"), + MTK_FUNCTION(7, "JTDI_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(98, "GPIO98"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO98"), + MTK_FUNCTION(1, "SPI0_CLK"), + MTK_FUNCTION(2, "MRG_DI"), + MTK_FUNCTION(3, "PCM0_DI"), + MTK_FUNCTION(4, "I2S1_MCK"), + MTK_FUNCTION(5, "SCL2"), + MTK_FUNCTION(6, "DFD_TCK_XI"), + MTK_FUNCTION(7, "JTCK_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(99, "GPIO99"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO99"), + MTK_FUNCTION(1, "SRCLKENAI0"), + MTK_FUNCTION(2, "UTXD1"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(4, "CLKM2"), + MTK_FUNCTION(5, "PCC_PPC_IO"), + MTK_FUNCTION(6, "ANT_SEL3"), + MTK_FUNCTION(7, "SPI0_MI") + ), + MTK_PIN( + PINCTRL_PIN(100, "GPIO100"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO100"), + MTK_FUNCTION(1, "PWM_A"), + MTK_FUNCTION(2, "URXD1"), + MTK_FUNCTION(3, "MD_INT0"), + MTK_FUNCTION(4, "CLKM3"), + MTK_FUNCTION(5, "MD_INT2_C2K_UIM1_HOT_PLUG"), + MTK_FUNCTION(6, "ANT_SEL4"), + MTK_FUNCTION(7, "DBG_MON_A35") + ), + MTK_PIN( + PINCTRL_PIN(101, "GPIO101"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO101"), + MTK_FUNCTION(1, "KPROW1"), + MTK_FUNCTION(2, "IRTX_OUT"), + MTK_FUNCTION(3, "C2K_UTXD1"), + MTK_FUNCTION(4, "C2K_UTXD0"), + MTK_FUNCTION(5, "C2K_DM_EINT2"), + MTK_FUNCTION(6, "ANT_SEL5"), + MTK_FUNCTION(7, "DBG_MON_A36") + ), + MTK_PIN( + PINCTRL_PIN(102, "GPIO102"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO102"), + MTK_FUNCTION(1, "KPROW0"), + MTK_FUNCTION(5, "C2K_DM_EINT3"), + MTK_FUNCTION(7, "DBG_MON_A37") + ), + MTK_PIN( + PINCTRL_PIN(103, "GPIO103"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO103"), + MTK_FUNCTION(1, "KPCOL0"), + MTK_FUNCTION(5, "C2K_DM_EINT0") + ), + MTK_PIN( + PINCTRL_PIN(104, "GPIO104"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO104"), + MTK_FUNCTION(1, "KPCOL1"), + MTK_FUNCTION(3, "C2K_URXD1"), + MTK_FUNCTION(4, "C2K_URXD0"), + MTK_FUNCTION(5, "C2K_DM_EINT1") + ), + MTK_PIN( + PINCTRL_PIN(105, "GPIO105"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO105"), + MTK_FUNCTION(1, "URXD0"), + MTK_FUNCTION(2, "UTXD0"), + MTK_FUNCTION(3, "MD_URXD0"), + MTK_FUNCTION(4, "MD_URXD1"), + MTK_FUNCTION(5, "C2K_URXD0"), + MTK_FUNCTION(6, "MD_URXD2"), + MTK_FUNCTION(7, "C2K_URXD1") + ), + MTK_PIN( + PINCTRL_PIN(106, "GPIO106"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO106"), + MTK_FUNCTION(1, "UTXD0"), + MTK_FUNCTION(2, "URXD0"), + MTK_FUNCTION(3, "MD_UTXD0"), + MTK_FUNCTION(4, "MD_UTXD1"), + MTK_FUNCTION(5, "C2K_UTXD0"), + MTK_FUNCTION(6, "MD_UTXD2"), + MTK_FUNCTION(7, "C2K_UTXD1") + ), + MTK_PIN( + PINCTRL_PIN(107, "GPIO107"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO107"), + MTK_FUNCTION(1, "UCTS0"), + MTK_FUNCTION(2, "I2S2_MCK"), + MTK_FUNCTION(4, "CONN_MCU_TDO"), + MTK_FUNCTION(5, "C2K_DM_OTDO"), + MTK_FUNCTION(6, "IO_JTAG_TDO"), + MTK_FUNCTION(7, "DBG_MON_A6") + ), + MTK_PIN( + PINCTRL_PIN(108, "GPIO108"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO108"), + MTK_FUNCTION(1, "URTS0"), + MTK_FUNCTION(2, "I2S2_BCK"), + MTK_FUNCTION(4, "CONN_MCU_TMS"), + MTK_FUNCTION(5, "C2K_DM_OTMS"), + MTK_FUNCTION(6, "IO_JTAG_TMS"), + MTK_FUNCTION(7, "DBG_MON_A7") + ), + MTK_PIN( + PINCTRL_PIN(109, "GPIO109"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO109"), + MTK_FUNCTION(1, "CMMCLK1"), + MTK_FUNCTION(2, "PWM_C"), + MTK_FUNCTION(3, "MD_INT0"), + MTK_FUNCTION(4, "CONN_MCU_AICE_TCKC"), + MTK_FUNCTION(5, "MD_INT1_C2K_UIM0_HOT_PLUG"), + MTK_FUNCTION(6, "CMFLASH"), + MTK_FUNCTION(7, "DBG_MON_A9") + ), + MTK_PIN( + PINCTRL_PIN(110, "GPIO110"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO110"), + MTK_FUNCTION(1, "CLKM2"), + MTK_FUNCTION(2, "I2S2_LRCK"), + MTK_FUNCTION(4, "CONN_MCU_TCK"), + MTK_FUNCTION(5, "C2K_DM_OTCK"), + MTK_FUNCTION(6, "IO_JTAG_TCK"), + MTK_FUNCTION(7, "DBG_MON_A10") + ), + MTK_PIN( + PINCTRL_PIN(111, "GPIO111"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO111"), + MTK_FUNCTION(1, "CLKM1"), + MTK_FUNCTION(2, "I2S2_DI"), + MTK_FUNCTION(4, "CONN_MCU_TDI"), + MTK_FUNCTION(5, "C2K_DM_OTDI"), + MTK_FUNCTION(6, "IO_JTAG_TDI"), + MTK_FUNCTION(7, "DBG_MON_A11") + ), + MTK_PIN( + PINCTRL_PIN(112, "GPIO112"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO112"), + MTK_FUNCTION(1, "SCL2") + ), + MTK_PIN( + PINCTRL_PIN(113, "GPIO113"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO113"), + MTK_FUNCTION(1, "SDA2") + ), + MTK_PIN( + PINCTRL_PIN(114, "GPIO114"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO114"), + MTK_FUNCTION(1, "ANT_SEL0"), + MTK_FUNCTION(2, "PWM_A"), + MTK_FUNCTION(3, "CLKM0"), + MTK_FUNCTION(4, "IRTX_OUT"), + MTK_FUNCTION(5, "PCC_PPC_IO"), + MTK_FUNCTION(7, "DBG_MON_A47") + ), + MTK_PIN( + PINCTRL_PIN(115, "GPIO115"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO115"), + MTK_FUNCTION(1, "ANT_SEL1"), + MTK_FUNCTION(2, "PWM_B"), + MTK_FUNCTION(3, "CLKM1"), + MTK_FUNCTION(4, "USB_DRVVBUS"), + MTK_FUNCTION(5, "DAP_SIB1_SWD"), + MTK_FUNCTION(7, "DBG_MON_A48") + ), + MTK_PIN( + PINCTRL_PIN(116, "GPIO116"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO116"), + MTK_FUNCTION(1, "ANT_SEL2"), + MTK_FUNCTION(2, "PWM_C"), + MTK_FUNCTION(3, "CLKM2"), + MTK_FUNCTION(4, "IDDIG"), + MTK_FUNCTION(5, "DAP_SIB1_SWCK"), + MTK_FUNCTION(6, "IRTX_OUT"), + MTK_FUNCTION(7, "DBG_MON_A49") + ), + MTK_PIN( + PINCTRL_PIN(117, "GPIO117"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO117"), + MTK_FUNCTION(1, "F2W_DATA"), + MTK_FUNCTION(2, "PTA_TXD"), + MTK_FUNCTION(3, "PTA_RXD"), + MTK_FUNCTION(4, "AUXIF_ST0"), + MTK_FUNCTION(5, "C2K_UTXD1"), + MTK_FUNCTION(6, "SDA0"), + MTK_FUNCTION(7, "DBG_MON_A50") + ), + MTK_PIN( + PINCTRL_PIN(118, "GPIO118"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO118"), + MTK_FUNCTION(1, "F2W_CK"), + MTK_FUNCTION(2, "PTA_RXD"), + MTK_FUNCTION(3, "PTA_TXD"), + MTK_FUNCTION(4, "AUXIF_CLK0"), + MTK_FUNCTION(5, "C2K_URXD1"), + MTK_FUNCTION(6, "SCL0"), + MTK_FUNCTION(7, "DBG_MON_A51") + ), + MTK_PIN( + PINCTRL_PIN(119, "GPIO119"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO119"), + MTK_FUNCTION(1, "WB_RSTB"), + MTK_FUNCTION(2, "URXD1"), + MTK_FUNCTION(3, "UTXD1"), + MTK_FUNCTION(7, "DBG_MON_A52") + ), + MTK_PIN( + PINCTRL_PIN(120, "GPIO120"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO120"), + MTK_FUNCTION(1, "WB_SCLK"), + MTK_FUNCTION(2, "UTXD1"), + MTK_FUNCTION(3, "URXD1") + ), + MTK_PIN( + PINCTRL_PIN(121, "GPIO121"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO121"), + MTK_FUNCTION(1, "WB_SDATA"), + MTK_FUNCTION(2, "AGPS_SYNC"), + MTK_FUNCTION(4, "AUXIF_ST1"), + MTK_FUNCTION(5, "C2K_UTXD0"), + MTK_FUNCTION(6, "SDA1") + ), + MTK_PIN( + PINCTRL_PIN(122, "GPIO122"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO122"), + MTK_FUNCTION(1, "WB_SEN"), + MTK_FUNCTION(2, "SRCLKENAI1"), + MTK_FUNCTION(4, "AUXIF_CLK1"), + MTK_FUNCTION(5, "C2K_URXD0"), + MTK_FUNCTION(6, "SCL1") + ), + MTK_PIN( + PINCTRL_PIN(123, "GPIO123"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO123") + ), + MTK_PIN( + PINCTRL_PIN(124, "GPIO124"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO124") + ), + MTK_PIN( + PINCTRL_PIN(125, "GPIO125"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO125") + ), + MTK_PIN( + PINCTRL_PIN(126, "GPIO126"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO126") + ), + MTK_PIN( + PINCTRL_PIN(127, "GPIO127"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO127") + ), + MTK_PIN( + PINCTRL_PIN(128, "GPIO128"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO128") + ), + MTK_PIN( + PINCTRL_PIN(129, "GPIO129"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO129") + ), + MTK_PIN( + PINCTRL_PIN(130, "GPIO130"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO130") + ), + MTK_PIN( + PINCTRL_PIN(131, "GPIO131"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO131"), + MTK_FUNCTION(1, "WB_CTRL0"), + MTK_FUNCTION(2, "MSDC2_DAT1"), + MTK_FUNCTION(5, "C2K_NTRST") + ), + MTK_PIN( + PINCTRL_PIN(132, "GPIO132"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO132"), + MTK_FUNCTION(1, "WB_CTRL1"), + MTK_FUNCTION(2, "MSDC2_CMD"), + MTK_FUNCTION(5, "C2K_TCK") + ), + MTK_PIN( + PINCTRL_PIN(133, "GPIO133"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO133"), + MTK_FUNCTION(1, "WB_CTRL2"), + MTK_FUNCTION(2, "MSDC2_CLK"), + MTK_FUNCTION(5, "C2K_TDI") + ), + MTK_PIN( + PINCTRL_PIN(134, "GPIO134"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO134"), + MTK_FUNCTION(1, "WB_CTRL3"), + MTK_FUNCTION(2, "MSDC2_DAT3"), + MTK_FUNCTION(5, "C2K_TMS") + ), + MTK_PIN( + PINCTRL_PIN(135, "GPIO135"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO135"), + MTK_FUNCTION(1, "WB_CTRL4"), + MTK_FUNCTION(2, "MSDC2_DAT0"), + MTK_FUNCTION(5, "C2K_TDO") + ), + MTK_PIN( + PINCTRL_PIN(136, "GPIO136"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO136"), + MTK_FUNCTION(1, "WB_CTRL5"), + MTK_FUNCTION(2, "MSDC2_DAT2"), + MTK_FUNCTION(5, "C2K_RTCK") + ), + MTK_PIN( + PINCTRL_PIN(137, "GPIO137"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO137") + ), + MTK_PIN( + PINCTRL_PIN(138, "GPIO138"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO138") + ), + MTK_PIN( + PINCTRL_PIN(139, "GPIO139"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO139") + ), + MTK_PIN( + PINCTRL_PIN(140, "GPIO140"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO140") + ), + MTK_PIN( + PINCTRL_PIN(141, "GPIO141"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO141") + ), + MTK_PIN( + PINCTRL_PIN(142, "GPIO142"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO142") + ), + MTK_PIN( + PINCTRL_PIN(143, "GPIO143"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO143") + ), + MTK_PIN( + PINCTRL_PIN(144, "GPIO144"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO144") + ), + MTK_PIN( + PINCTRL_PIN(145, "GPIO145"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO145") + ), + MTK_PIN( + PINCTRL_PIN(146, "GPIO146"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO146") + ), + MTK_PIN( + PINCTRL_PIN(147, "GPIO147"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO147"), + MTK_FUNCTION(1, "RTC32K_CK") + ), + MTK_PIN( + PINCTRL_PIN(148, "GPIO148"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO148"), + MTK_FUNCTION(1, "WATCHDOG") + ), + MTK_PIN( + PINCTRL_PIN(149, "GPIO149"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO149"), + MTK_FUNCTION(1, "AUD_CLK_MOSI"), + MTK_FUNCTION(3, "I2S1_BCK") + ), + MTK_PIN( + PINCTRL_PIN(150, "GPIO150"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO150"), + MTK_FUNCTION(1, "AUD_DAT_MOSI"), + MTK_FUNCTION(2, "AUD_DAT_MISO"), + MTK_FUNCTION(3, "I2S1_LRCK") + ), + MTK_PIN( + PINCTRL_PIN(151, "GPIO151"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO151"), + MTK_FUNCTION(1, "AUD_DAT_MISO"), + MTK_FUNCTION(2, "AUD_DAT_MOSI"), + MTK_FUNCTION(3, "I2S1_DO") + ), + MTK_PIN( + PINCTRL_PIN(152, "GPIO152"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO152"), + MTK_FUNCTION(1, "PWRAP_SPI0_MI"), + MTK_FUNCTION(2, "PWRAP_SPI0_MO") + ), + MTK_PIN( + PINCTRL_PIN(153, "GPIO153"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO153"), + MTK_FUNCTION(1, "PWRAP_SPI0_CSN") + ), + MTK_PIN( + PINCTRL_PIN(154, "GPIO154"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO154"), + MTK_FUNCTION(1, "PWRAP_SPI0_MO"), + MTK_FUNCTION(2, "PWRAP_SPI0_MI") + ), + MTK_PIN( + PINCTRL_PIN(155, "GPIO155"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO155"), + MTK_FUNCTION(1, "PWRAP_SPI0_CK") + ), + MTK_PIN( + PINCTRL_PIN(156, "GPIO156"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO156"), + MTK_FUNCTION(1, "SRCLKENA0") + ), + MTK_PIN( + PINCTRL_PIN(157, "GPIO157"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO157"), + MTK_FUNCTION(1, "DISP_PWM"), + MTK_FUNCTION(7, "DBG_MON_A14") + ), + MTK_PIN( + PINCTRL_PIN(158, "GPIO158"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO158"), + MTK_FUNCTION(1, "LCM_RST"), + MTK_FUNCTION(7, "DBG_MON_A16") + ), + MTK_PIN( + PINCTRL_PIN(159, "GPIO159"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO159"), + MTK_FUNCTION(1, "RFIC0_BSI_EN"), + MTK_FUNCTION(2, "SPM_BSI_EN"), + MTK_FUNCTION(7, "DBG_MON_B17") + ), + MTK_PIN( + PINCTRL_PIN(160, "GPIO160"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO160"), + MTK_FUNCTION(1, "RFIC0_BSI_CK"), + MTK_FUNCTION(2, "SPM_BSI_CK"), + MTK_FUNCTION(7, "DBG_MON_B18") + ), + MTK_PIN( + PINCTRL_PIN(161, "GPIO161"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO161"), + MTK_FUNCTION(1, "CMMCLK0"), + MTK_FUNCTION(4, "CONN_MCU_AICE_TMSC"), + MTK_FUNCTION(7, "DBG_MON_A8") + ), + MTK_PIN( + PINCTRL_PIN(162, "GPIO162"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO162") + ), + MTK_PIN( + PINCTRL_PIN(163, "GPIO163"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO163") + ), + MTK_PIN( + PINCTRL_PIN(164, "GPIO164"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO164") + ), + MTK_PIN( + PINCTRL_PIN(165, "GPIO165"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO165") + ), + MTK_PIN( + PINCTRL_PIN(166, "GPIO166"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO166") + ), + MTK_PIN( + PINCTRL_PIN(167, "GPIO167"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO167") + ), + MTK_PIN( + PINCTRL_PIN(168, "GPIO168"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO168") + ), + MTK_PIN( + PINCTRL_PIN(169, "GPIO169"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO169") + ), + MTK_PIN( + PINCTRL_PIN(170, "GPIO170"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO170") + ), + MTK_PIN( + PINCTRL_PIN(171, "GPIO171"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO171") + ), + MTK_PIN( + PINCTRL_PIN(172, "GPIO172"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO172"), + MTK_FUNCTION(2, "CMCSD2") + ), + MTK_PIN( + PINCTRL_PIN(173, "GPIO173"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO173"), + MTK_FUNCTION(2, "CMCSD3") + ), + MTK_PIN( + PINCTRL_PIN(174, "GPIO174"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO174"), + MTK_FUNCTION(2, "CMCSK") + ), + MTK_PIN( + PINCTRL_PIN(175, "GPIO175"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO175") + ), + MTK_PIN( + PINCTRL_PIN(176, "GPIO176"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO176"), + MTK_FUNCTION(2, "CMCSD0") + ), + MTK_PIN( + PINCTRL_PIN(177, "GPIO177"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO177"), + MTK_FUNCTION(2, "CMCSD1") + ), + MTK_PIN( + PINCTRL_PIN(178, "GPIO178"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO178"), + MTK_FUNCTION(1, "MSDC0_DAT0"), + MTK_FUNCTION(7, "DBG_MON_A0") + ), + MTK_PIN( + PINCTRL_PIN(179, "GPIO179"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO179"), + MTK_FUNCTION(1, "MSDC0_CLK"), + MTK_FUNCTION(7, "DBG_MON_A1") + ), + MTK_PIN( + PINCTRL_PIN(180, "GPIO180"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO180"), + MTK_FUNCTION(1, "MSDC0_CMD"), + MTK_FUNCTION(7, "DBG_MON_A2") + ), + MTK_PIN( + PINCTRL_PIN(181, "GPIO181"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO181"), + MTK_FUNCTION(1, "MSDC0_DAT1"), + MTK_FUNCTION(7, "DBG_MON_A3") + ), + MTK_PIN( + PINCTRL_PIN(182, "GPIO182"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO182"), + MTK_FUNCTION(1, "MSDC0_DAT5"), + MTK_FUNCTION(7, "DBG_MON_A4") + ), + MTK_PIN( + PINCTRL_PIN(183, "GPIO183"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO183"), + MTK_FUNCTION(1, "MSDC0_DAT6"), + MTK_FUNCTION(7, "DBG_MON_A5") + ), + MTK_PIN( + PINCTRL_PIN(184, "GPIO184"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO184"), + MTK_FUNCTION(1, "MSDC0_DAT4"), + MTK_FUNCTION(7, "DBG_MON_A59") + ), + MTK_PIN( + PINCTRL_PIN(185, "GPIO185"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO185"), + MTK_FUNCTION(1, "MSDC0_RSTB"), + MTK_FUNCTION(7, "DBG_MON_A60") + ), + MTK_PIN( + PINCTRL_PIN(186, "GPIO186"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO186"), + MTK_FUNCTION(1, "MSDC0_DAT2"), + MTK_FUNCTION(7, "DBG_MON_A61") + ), + MTK_PIN( + PINCTRL_PIN(187, "GPIO187"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO187"), + MTK_FUNCTION(1, "MSDC0_DAT3"), + MTK_FUNCTION(7, "DBG_MON_A62") + ), + MTK_PIN( + PINCTRL_PIN(188, "GPIO188"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO188"), + MTK_FUNCTION(1, "MSDC0_DAT7"), + MTK_FUNCTION(7, "DBG_MON_A63") + ), + MTK_PIN( + PINCTRL_PIN(189, "GPIO189"), + NULL, "mt6755", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO189"), + MTK_FUNCTION(1, "MSDC0_DSL"), + MTK_FUNCTION(7, "DBG_MON_A64") + ), +}; + +#endif /* __PINCTRL_MTK_MT6755_H */ diff --git a/drivers/spi/mediatek/mt6755/Makefile b/drivers/spi/mediatek/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ace803ff551460edd2f9eb21287bbd4c12b7ae11 --- /dev/null +++ b/drivers/spi/mediatek/mt6755/Makefile @@ -0,0 +1,11 @@ +subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include \ + -I$(srctree)/drivers/misc/mediatek/include/mt-plat +ifeq ($(CONFIG_TRUSTONIC_TEE_SUPPORT),y) +subdir-ccflags-y += -I$(srctree)/drivers/spi/trustzone/spi/Tlspi/inc +endif + +ifeq ($(CONFIG_TRUSTONIC_TEE_SUPPORT),y) + include $(srctree)/drivers/misc/mediatek/gud/Makefile.include +endif + +obj-$(CONFIG_MTK_SPI) += spi.o spi-dev.o diff --git a/drivers/spi/mediatek/mt6755/mt_spi.h b/drivers/spi/mediatek/mt6755/mt_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..f6f7ec0e9313b80224d12dac97baf8acac2f2fa1 --- /dev/null +++ b/drivers/spi/mediatek/mt6755/mt_spi.h @@ -0,0 +1,105 @@ +#ifndef __MT_SPI_H__ +#define __MT_SPI_H__ + + +#include +#include +#ifdef CONFIG_TRUSTONIC_TEE_SUPPORT +#include +#include +#endif +/******************************************************************************* +* define struct for spi driver +********************************************************************************/ +enum spi_sample_sel { + POSEDGE, + NEGEDGE +}; +enum spi_cs_pol { + ACTIVE_LOW, + ACTIVE_HIGH +}; + +enum spi_cpol { + SPI_CPOL_0, + SPI_CPOL_1 +}; + +enum spi_cpha { + SPI_CPHA_0, + SPI_CPHA_1 +}; + +enum spi_mlsb { + SPI_LSB, + SPI_MSB +}; + +enum spi_endian { + SPI_LENDIAN, + SPI_BENDIAN +}; + +enum spi_transfer_mode { + FIFO_TRANSFER, + DMA_TRANSFER, + OTHER1, + OTHER2, +}; + +enum spi_pause_mode { + PAUSE_MODE_DISABLE, + PAUSE_MODE_ENABLE +}; +enum spi_finish_intr { + FINISH_INTR_DIS, + FINISH_INTR_EN, +}; + +enum spi_deassert_mode { + DEASSERT_DISABLE, + DEASSERT_ENABLE +}; + +enum spi_ulthigh { + ULTRA_HIGH_DISABLE, + ULTRA_HIGH_ENABLE +}; + +enum spi_tckdly { + TICK_DLY0, + TICK_DLY1, + TICK_DLY2, + TICK_DLY3 +}; + +struct mt_chip_conf { + u32 setuptime; + u32 holdtime; + u32 high_time; + u32 low_time; + u32 cs_idletime; + u32 ulthgh_thrsh; + enum spi_sample_sel sample_sel; + enum spi_cs_pol cs_pol; + enum spi_cpol cpol; + enum spi_cpha cpha; + enum spi_mlsb tx_mlsb; + enum spi_mlsb rx_mlsb; + enum spi_endian tx_endian; + enum spi_endian rx_endian; + enum spi_transfer_mode com_mod; + enum spi_pause_mode pause; + enum spi_finish_intr finish_intr; + enum spi_deassert_mode deassert; + enum spi_ulthigh ulthigh; + enum spi_tckdly tckdly; +}; + +void secspi_enable_clk(struct spi_device *spidev); +#ifdef CONFIG_TRUSTONIC_TEE_SUPPORT +int secspi_session_open(void); +int secspi_execute(u32 cmd, tciSpiMessage_t *param); +#endif + +#endif diff --git a/drivers/spi/mediatek/mt6755/mt_spi_hal.h b/drivers/spi/mediatek/mt6755/mt_spi_hal.h new file mode 100644 index 0000000000000000000000000000000000000000..096cdcca6c21488b1882935e9a40fd85242dbe62 --- /dev/null +++ b/drivers/spi/mediatek/mt6755/mt_spi_hal.h @@ -0,0 +1,99 @@ +#ifndef __MT_SPI_HAL_H__ +#define __MT_SPI_HAL_H__ + +/******************************************************************************* +* define macro for spi register +********************************************************************************/ +#define SPI_CFG0_REG (0x0000) +#define SPI_CFG1_REG (0x0004) +#define SPI_TX_SRC_REG (0x0008) +#define SPI_RX_DST_REG (0x000c) +#define SPI_TX_DATA_REG (0x0010) +#define SPI_RX_DATA_REG (0x0014) +#define SPI_CMD_REG (0x0018) +#define SPI_STATUS0_REG (0x001c) +#define SPI_STATUS1_REG (0x0020) +#define SPI_PAD_SEL_REG (0x0024) +#define SPI_CFG2_REG (0x0028) + +#define MIPI_TX_PU_TDP1_OFFSET 4 +#define MIPI_TX_PU_TDP1_MASK 0x10 +#define MIPI_TX_PD_TDP1_OFFSET 12 +#define MIPI_TX_PD_TDP1_MASK 0x1000 + +#define SPI_CFG0_SCK_HIGH_OFFSET 0 +#define SPI_CFG0_SCK_LOW_OFFSET 16 +#define SPI_CFG0_CS_HOLD_OFFSET 0 +#define SPI_CFG0_CS_SETUP_OFFSET 16 + +#define SPI_CFG0_SCK_HIGH_MASK 0xffff +#define SPI_CFG0_SCK_LOW_MASK 0xffff0000 +#define SPI_CFG0_CS_HOLD_MASK 0xffff +#define SPI_CFG0_CS_SETUP_MASK 0xffff0000 + +#define SPI_CFG1_CS_IDLE_OFFSET 0 +#define SPI_CFG1_PACKET_LOOP_OFFSET 8 +#define SPI_CFG1_PACKET_LENGTH_OFFSET 16 +#define SPI_CFG1_GET_TICK_DLY_OFFSET 29 + +#define SPI_CFG1_CS_IDLE_MASK 0xff +#define SPI_CFG1_PACKET_LOOP_MASK 0xff00 +#define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000 +#define SPI_CFG1_GET_TICK_DLY_MASK 0xe0000000 + +#define SPI_CMD_ACT_OFFSET 0 +#define SPI_CMD_RESUME_OFFSET 1 +#define SPI_CMD_RST_OFFSET 2 +#define SPI_CMD_PAUSE_EN_OFFSET 4 +#define SPI_CMD_DEASSERT_OFFSET 5 +#define SPI_CMD_SAMPLE_SEL_OFFSET 6 +#define SPI_CMD_CS_POL_OFFSET 7 +#define SPI_CMD_CPHA_OFFSET 8 +#define SPI_CMD_CPOL_OFFSET 9 +#define SPI_CMD_RX_DMA_OFFSET 10 +#define SPI_CMD_TX_DMA_OFFSET 11 +#define SPI_CMD_TXMSBF_OFFSET 12 +#define SPI_CMD_RXMSBF_OFFSET 13 +#define SPI_CMD_RX_ENDIAN_OFFSET 14 +#define SPI_CMD_TX_ENDIAN_OFFSET 15 +#define SPI_CMD_FINISH_IE_OFFSET 16 +#define SPI_CMD_PAUSE_IE_OFFSET 17 + +#define SPI_CMD_ACT_MASK 0x1 +#define SPI_CMD_RESUME_MASK 0x2 +#define SPI_CMD_RST_MASK 0x4 +#define SPI_CMD_PAUSE_EN_MASK 0x10 +#define SPI_CMD_DEASSERT_MASK 0x20 +#define SPI_CMD_SAMPLE_SEL_MASK 0x40 +#define SPI_CMD_CS_POL_MASK 0x80 +#define SPI_CMD_CPHA_MASK 0x100 +#define SPI_CMD_CPOL_MASK 0x200 +#define SPI_CMD_RX_DMA_MASK 0x400 +#define SPI_CMD_TX_DMA_MASK 0x800 +#define SPI_CMD_TXMSBF_MASK 0x1000 +#define SPI_CMD_RXMSBF_MASK 0x2000 +#define SPI_CMD_RX_ENDIAN_MASK 0x4000 +#define SPI_CMD_TX_ENDIAN_MASK 0x8000 +#define SPI_CMD_FINISH_IE_MASK 0x10000 +#define SPI_CMD_PAUSE_IE_MASK 0x20000 + +#define SPI_ULTRA_HIGH_EN_OFFSET 0 +#define SPI_ULTRA_HIGH_THRESH_OFFSET 16 + +#define SPI_ULTRA_HIGH_EN_MASK 0x1 +#define SPI_ULTRA_HIGH_THRESH_MASK 0xffff0000 + +#include +#define spi_readl(port, offset) \ + __raw_readl((port)->regs+(offset)) +/* +#define spi_writel(port, offset,value) \ + __raw_writel((value), (port)->regs+(offset)) +*/ +#define spi_writel(port, offset, value) \ + mt_reg_sync_writel((value), (port)->regs+(offset)) + +extern void mt_spi_enable_master_clk(struct spi_device *ms); +extern void mt_spi_disable_master_clk(struct spi_device *ms); + +#endif diff --git a/drivers/spi/mediatek/mt6755/spi-dev.c b/drivers/spi/mediatek/mt6755/spi-dev.c new file mode 100644 index 0000000000000000000000000000000000000000..fc7bada0057238fe3f86cf59c120b21778a17482 --- /dev/null +++ b/drivers/spi/mediatek/mt6755/spi-dev.c @@ -0,0 +1,879 @@ +#include +#include +#include +#include +#include +#include +#include "mt_spi.h" + +#include +#include +#include "mt_spi_hal.h" +#include + +#ifdef CONFIG_TRUSTONIC_TEE_SUPPORT +#define SPI_TRUSTONIC_TEE_SUPPORT +#endif + +#ifdef SPI_TRUSTONIC_TEE_SUPPORT +#include +#include +#endif + +#define SPIDEV_LOG(fmt, args...) pr_debug("[SPI-UT]: [%s]:[%d]" fmt, __func__, __LINE__, ##args) +#define SPIDEV_MSG(fmt, args...) pr_debug(fmt, ##args) +/* #define SPI_STRESS_MAX 512 */ +#define SPI_STRESS_MAX 1 +DECLARE_COMPLETION(mt_spi_done); +static u32 stress_err; +static struct task_struct *spi_concur1; +static struct task_struct *spi_concur2; +static struct task_struct *spi_concur3; +static struct task_struct *spi_concur4; + +static struct spi_transfer stress_xfer[SPI_STRESS_MAX]; +static struct spi_transfer stress_xfer_con[SPI_STRESS_MAX]; + +static struct spi_message stress_msg[SPI_STRESS_MAX]; +static struct spi_device *spi_test; + +static int spi_setup_xfer(struct device *dev, struct spi_transfer *xfer, u32 len, u32 flag) +{ + u32 tx_buffer = 0x12345678; + u32 cnt, i; +#if 0 + u8 *p; +#endif +#define SPI_CROSS_ALIGN_OFFSET 1008 + xfer->len = len; + + xfer->tx_buf = kzalloc(len, GFP_KERNEL); + xfer->rx_buf = kzalloc(len, GFP_KERNEL); + + if ((xfer->tx_buf == NULL) || (xfer->rx_buf == NULL)) + return -1; + + cnt = (len%4)?(len/4 + 1):(len/4); + + if (flag == 0) { + for (i = 0; i < cnt; i++) + *((u32 *)xfer->tx_buf + i) = tx_buffer; + } else if (flag == 1) { + for (i = 0; i < cnt; i++) + *((u32 *)xfer->tx_buf + i) = tx_buffer + i; + } else if (flag == 2) {/* cross 1 K boundary */ + if (len < 2048) + return -EINVAL; + for (i = 0; i < cnt; i++) + *((u32 *)xfer->tx_buf + i) = tx_buffer + i; + + xfer->tx_dma = dma_map_single(dev, (void *)xfer->tx_buf, + xfer->len, DMA_TO_DEVICE); + if (dma_mapping_error(dev, xfer->tx_dma)) { + SPIDEV_LOG("dma mapping tx_buf error.\n"); + return -ENOMEM; + } + xfer->rx_dma = dma_map_single(dev, (void *)xfer->rx_buf, + xfer->len, DMA_TO_DEVICE); + if (dma_mapping_error(dev, xfer->rx_dma)) { + SPIDEV_LOG("dma mapping rx_buf error.\n"); + return -ENOMEM; + } +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + SPIDEV_LOG("Transfer addr:Tx:0x%llx, Rx:0x%llx, before\n", xfer->tx_dma, xfer->rx_dma); +#else + SPIDEV_LOG("Transfer addr:Tx:0x%x, Rx:0x%x, before\n", xfer->tx_dma, xfer->rx_dma); +#endif + xfer->len = 32; +#if 0 + p = xfer->tx_dma; + xfer->tx_dma = (u32)(p + SPI_CROSS_ALIGN_OFFSET); + p = xfer->rx_dma; + xfer->rx_dma = (u32)(p + SPI_CROSS_ALIGN_OFFSET); + + t = (u8 *) xfer->tx_buf; + xfer->tx_buf = (u32 *) (t + SPI_CROSS_ALIGN_OFFSET); + t = (u8 *) xfer->rx_buf; + xfer->rx_buf = (u32 *) (t + SPI_CROSS_ALIGN_OFFSET); +#else + xfer->tx_dma += SPI_CROSS_ALIGN_OFFSET; + xfer->rx_dma += SPI_CROSS_ALIGN_OFFSET; + + xfer->tx_buf += SPI_CROSS_ALIGN_OFFSET; + xfer->rx_buf += SPI_CROSS_ALIGN_OFFSET; +#endif +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + SPIDEV_LOG("Transfer addr:Tx:0x%llx, Rx:0x%llx\n", xfer->tx_dma, xfer->rx_dma); +#else + SPIDEV_LOG("Transfer addr:Tx:0x%x, Rx:0x%x\n", xfer->tx_dma, xfer->rx_dma); +#endif + SPIDEV_LOG("Transfer addr:Tx:0x%p, Rx:0x%p\n", xfer->tx_buf, xfer->rx_buf); + } else { + return -EINVAL; + } + return 0; + +} +static inline int +is_last_xfer(struct spi_message *msg, struct spi_transfer *xfer) +{ + return msg->transfers.prev == &xfer->transfer_list; +} + +static int spi_recv_check(struct spi_message *msg) +{ + + struct spi_transfer *xfer; + u32 cnt, i, err = 0; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + + if (!xfer) { + SPIDEV_MSG("rv msg is NULL.\n"); + return -1; + } +/* SPIDEV_LOG("xfer:0x%p, length is:%d\n", xfer,xfer->len); */ + cnt = (xfer->len%4)?(xfer->len/4 + 1):(xfer->len/4); + for (i = 0; i < cnt; i++) { + if (*((u32 *) xfer->rx_buf + i) != *((u32 *) xfer->tx_buf + i)) { + SPIDEV_LOG("tx xfer %d is:%.8x\n", i, *((u32 *) xfer->tx_buf + i)); + SPIDEV_LOG("rx xfer %d is:%.8x\n", i, *((u32 *) xfer->rx_buf + i)); + /* SPIDEV_LOG("tx xfer %d dma is:%.8x\n",i, ( ( u32 * )xfer->tx_dma + i ) ); */ + /* SPIDEV_LOG("rx xfer %d dma is:%.8x\n",i, ( ( u32 * )xfer->rx_dma + i ) ); */ + SPIDEV_LOG("\n"); + err++; + } + } + /* memset(xfer->tx_buf,0,xfer->len); */ + /* memset(xfer->rx_buf,0,xfer->len); */ + kfree(xfer->tx_buf); + kfree(xfer->rx_buf); + } + + SPIDEV_LOG("Message:0x%p,error %d,actual xfer length is:%d\n", msg, err, msg->actual_length); + + return err; + +} +static int spi_recv_check_all(struct spi_device *spi, struct spi_message *msg) +{ + + struct spi_transfer *xfer; + u32 i, err = 0; + int j; + u8 rec_cac = 0; + + struct mt_chip_conf *chip_config; + + chip_config = (struct mt_chip_conf *) spi->controller_data; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + + if (!xfer) { + SPIDEV_MSG("rv msg is NULL.\n"); + return -1; + } +/* SPIDEV_LOG("xfer:0x%p, length is:%d\n", xfer,xfer->len); */ +/* cnt = (xfer->len%4)?(xfer->len/4 + 1):(xfer->len/4); */ + for (i = 0; i < xfer->len; i++) { + if (chip_config->tx_mlsb ^ chip_config->rx_mlsb) { + rec_cac = 0; + for (j = 7; j >= 0; j--) + rec_cac |= ((*((u8 *)xfer->tx_buf + i) & (1<> j) << (7-j); + } else + rec_cac = *((u8 *) xfer->tx_buf + i); + + if (*((u8 *) xfer->rx_buf + i) != rec_cac) { + SPIDEV_LOG("tx xfer %d is:%x\n", i, *((u8 *) xfer->tx_buf + i)); + SPIDEV_LOG("rx xfer %d is:%x\n", i, *((u8 *) xfer->rx_buf + i)); + err++; + } + } + kfree(xfer->tx_buf); + kfree(xfer->rx_buf); + } + + SPIDEV_LOG("Message:0x%p,error %d,actual xfer length is:%d\n", msg, err, msg->actual_length); + + return err; + +} + +static void spi_complete(void *arg) +{ + static u32 i; + + stress_err += spi_recv_check((struct spi_message *)arg); + if (stress_err > 0) { + + SPIDEV_LOG("Message transfer err:%d\n", stress_err); +/* BUG(); */ + } + +/* SPIDEV_LOG("Message:%d\n", i); */ + if (++i == SPI_STRESS_MAX) { + i = 0; + complete(&mt_spi_done); + } +} + + +static int threadfunc1(void *data) +{ + struct spi_transfer transfer = {0,}; + struct spi_message msg; + struct spi_device *spi = (struct spi_device *) data; + u32 len = 8; + int ret; + + while (1) { + spi_message_init(&msg); + + set_current_state(TASK_INTERRUPTIBLE); + if (kthread_should_stop()) + break; + + spi_setup_xfer(&spi->dev, &transfer, len, 0); + spi_message_add_tail(&transfer, &msg); + ret = spi_sync(spi, &msg); + if (ret < 0) { + stress_err++; + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else{ + ret = spi_recv_check(&msg); + if (ret != 0) { + stress_err += ret; + SPIDEV_LOG("thread Message transfer err:%d\n", ret); + } + } + schedule_timeout(HZ); + } + return 0; +} +static int threadfunc2(void *data) +{ + struct spi_transfer transfer = {0,}; + struct spi_message msg; + struct spi_device *spi = (struct spi_device *) data; + + u32 len = 128; + int ret; + + while (1) { + spi_message_init(&msg); + + set_current_state(TASK_INTERRUPTIBLE); + if (kthread_should_stop()) + break; + + spi_setup_xfer(&spi->dev, &transfer, len, 0); + spi_message_add_tail(&transfer, &msg); + ret = spi_sync(spi, &msg); + if (ret < 0) { + stress_err++; + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else{ + ret = spi_recv_check(&msg); + if (ret != 0) { + stress_err += ret; + SPIDEV_LOG("thread Message transfer err:%d\n", ret); + } + } + schedule_timeout(HZ); + } + return 0; +} +static int threadfunc3(void *data) +{ + /* struct spi_transfer transfer; */ + struct spi_message msg; + struct spi_device *spi = (struct spi_device *) data; + static struct spi_message *p; + u32 len = 64; + int ret; + u16 i; + + while (1) { + spi_message_init(&msg); + + set_current_state(TASK_INTERRUPTIBLE); + if (kthread_should_stop()) + break; + + p = stress_msg; + for (i = 0; i < SPI_STRESS_MAX; i++) { + spi_message_init(p); + ret = spi_setup_xfer(&spi->dev, &stress_xfer[i], len, 0); + if (ret != 0) + SPIDEV_LOG("xfer set up err:%d\n", ret); + spi_message_add_tail(&stress_xfer[i], p); + + p->complete = spi_complete; + p->context = p; + ret = spi_async(spi, p); + if (ret < 0) + SPIDEV_LOG("Message %d transfer err:%d\n", i, ret); + p++; + } + + wait_for_completion(&mt_spi_done); + + schedule_timeout(5*HZ); + } + return 0; +} +static int threadfunc4(void *data) +{ + /* struct spi_transfer transfer; */ + struct spi_message msg; + struct spi_device *spi = (struct spi_device *) data; + + u32 len = 32; + int ret; + u16 i; + + while (1) { + spi_message_init(&msg); + + set_current_state(TASK_INTERRUPTIBLE); + if (kthread_should_stop()) + break; + + for (i = 0; i < SPI_STRESS_MAX; i++) { + ret = spi_setup_xfer(&spi->dev, &stress_xfer_con[i], len, 1); + if (ret != 0) + SPIDEV_LOG("Message set up err:%d\n", ret); + spi_message_add_tail(&stress_xfer_con[i], &msg); + + } + ret = spi_sync(spi, &msg); + if (ret < 0) { + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else{ + ret = spi_recv_check(&msg); + if (ret != 0) { + ret -= ret; + stress_err += ret; + SPIDEV_LOG("Message transfer err:%d\n", ret); + } +/* SPIDEV_LOG("Message multi xfer stress pass\n"); */ + } + + schedule_timeout(2*HZ); + } + return 0; +} + + +static ssize_t spi_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct spi_device *spi; + + struct mt_chip_conf *chip_config; + + u32 setuptime, holdtime, high_time, low_time; + u32 cs_idletime, ulthgh_thrsh; + int cpol, cpha, tx_mlsb, rx_mlsb, tx_endian; + int rx_endian, com_mod, pause, finish_intr; + int deassert, tckdly, ulthigh; + + spi = container_of(dev, struct spi_device, dev); + + SPIDEV_LOG("SPIDEV name is:%s\n", spi->modalias); + + chip_config = (struct mt_chip_conf *) spi->controller_data; + + if (!chip_config) { + SPIDEV_LOG("chip_config is NULL.\n"); + chip_config = kzalloc(sizeof(struct mt_chip_conf), GFP_KERNEL); + if (!chip_config) + return -ENOMEM; + } + if (!buf) { + SPIDEV_LOG("buf is NULL.\n"); + goto out; + } +#ifdef CONFIG_TRUSTONIC_TEE_SUPPORT + if (!strncmp(buf, "-1", 2)) { /*TRANSFER*/ + SPIDEV_MSG("start to access TL SPI driver.\n"); + secspi_session_open(); + secspi_enable_clk(spi); + secspi_execute(1, NULL); + SPIDEV_MSG("secspi_execute 1 finished!!!\n"); + } else if (!strncmp(buf, "-2", 2)) { /*HW CONFIG*/ + SPIDEV_MSG("start to access TL SPI driver.\n"); + secspi_session_open(); + secspi_execute(2, NULL); + SPIDEV_MSG("secspi_execute 2 finished!!!\n"); + } else if (!strncmp(buf, "-3", 2)) { /*DEBUG*/ + SPIDEV_MSG("start to access TL SPI driver.\n"); + secspi_session_open(); + secspi_execute(3, NULL); + SPIDEV_MSG("secspi_execute 3 finished!!!\n"); + } else if (!strncmp(buf, "-4", 2)) { + /*TEST*/SPIDEV_MSG("start to access TL SPI driver.\n"); + secspi_session_open(); + secspi_execute(4, NULL); + SPIDEV_MSG("secspi_execute 4 finished!!!\n"); +#else + if (!strncmp(buf, "-h", 2)) { + SPIDEV_MSG("Please input the parameters for this device.\n"); +#endif + } else if (!strncmp(buf, "-w", 2)) { + buf += 3; + if (!strncmp(buf, "setuptime=", 10) && (1 == sscanf(buf+10, "%d", &setuptime))) { + SPIDEV_MSG("setuptime is:%d\n", setuptime); + chip_config->setuptime = setuptime; + } else if (!strncmp(buf, "holdtime=", 9) && (1 == sscanf(buf+9, "%d", &holdtime))) { + SPIDEV_MSG("Set holdtime is:%d\n", holdtime); + chip_config->holdtime = holdtime; + } else if (!strncmp(buf, "high_time=", 10) && (1 == sscanf(buf+10, "%d", &high_time))) { + SPIDEV_MSG("Set high_time is:%d\n", high_time); + chip_config->high_time = high_time; + } else if (!strncmp(buf, "low_time=", 9) && (1 == sscanf(buf+9, "%d", &low_time))) { + SPIDEV_MSG("Set low_time is:%d\n", low_time); + chip_config->low_time = low_time; + } else if (!strncmp(buf, "cs_idletime=", 12) && (1 == sscanf(buf+12, "%d", &cs_idletime))) { + SPIDEV_MSG("Set cs_idletime is:%d\n", cs_idletime); + chip_config->cs_idletime = cs_idletime; + } else if (!strncmp(buf, "ulthgh_thrsh=", 13) && (1 == sscanf(buf+13, "%d", &ulthgh_thrsh))) { + SPIDEV_MSG("Set slwdown_thrsh is:%d\n", ulthgh_thrsh); + chip_config->ulthgh_thrsh = ulthgh_thrsh; + } else if (!strncmp(buf, "cpol=", 5) && (1 == sscanf(buf+5, "%d", &cpol))) { + SPIDEV_MSG("Set cpol is:%d\n", cpol); + chip_config->cpol = cpol; + } else if (!strncmp(buf, "cpha=", 5) && (1 == sscanf(buf+5, "%d", &cpha))) { + SPIDEV_MSG("Set cpha is:%d\n", cpha); + chip_config->cpha = cpha; + } else if (!strncmp(buf, "tx_mlsb=", 8) && (1 == sscanf(buf+8, "%d", &tx_mlsb))) { + SPIDEV_MSG("Set tx_mlsb is:%d\n", tx_mlsb); + chip_config->tx_mlsb = tx_mlsb; + } else if (!strncmp(buf, "rx_mlsb=", 8) && (1 == sscanf(buf+8, "%d", &rx_mlsb))) { + SPIDEV_MSG("Set rx_mlsb is:%d\n", rx_mlsb); + chip_config->rx_mlsb = rx_mlsb; + } else if (!strncmp(buf, "tx_endian=", 10) && (1 == sscanf(buf+10, "%d", &tx_endian))) { + SPIDEV_MSG("Set tx_endian is:%d\n", tx_endian); + chip_config->tx_endian = tx_endian; + } else if (!strncmp(buf, "rx_endian=", 10) && (1 == sscanf(buf+10, "%d", &rx_endian))) { + SPIDEV_MSG("Set rx_endian is:%d\n", rx_endian); + chip_config->rx_endian = rx_endian; + } else if (!strncmp(buf, "com_mod=", 8) && (1 == sscanf(buf+8, "%d", &com_mod))) { + chip_config->com_mod = com_mod; + SPIDEV_MSG("Set com_mod is:%d\n", com_mod); + } else if (!strncmp(buf, "pause=", 6) && (1 == sscanf(buf+6, "%d", &pause))) { + SPIDEV_MSG("Set pause is:%d\n", pause); + chip_config->pause = pause; + } else if (!strncmp(buf, "finish_intr=", 12) && (1 == sscanf(buf+12, "%d", &finish_intr))) { + SPIDEV_MSG("Set finish_intr is:%d\n", finish_intr); + chip_config->finish_intr = finish_intr; + } else if (!strncmp(buf, "deassert=", 9) && (1 == sscanf(buf+9, "%d", &deassert))) { + SPIDEV_MSG("Set deassert is:%d\n", deassert); + chip_config->deassert = deassert; + } else if (!strncmp(buf, "ulthigh=", 8) && (1 == sscanf(buf+8, "%d", &ulthigh))) { + SPIDEV_MSG("Set ulthigh is:%d\n", ulthigh); + chip_config->ulthigh = ulthigh; + } else if (!strncmp(buf, "tckdly=", 7) && (1 == sscanf(buf+7, "%d", &tckdly))) { + SPIDEV_MSG("Set tckdly is:%d\n", tckdly); + chip_config->tckdly = tckdly; + } else { + SPIDEV_LOG("Wrong parameters.\n"); + goto out; + } + spi->controller_data = chip_config; +/* spi_setup(spi); */ + + } +out: + if (!spi->controller_data) + kfree(chip_config); + return count; +} + +static int tc_spi_cross_1k(struct spi_device *spi) +{ + int ret = 0; + /* struct spi_transfer transfer; */ + /* struct spi_message msg; */ + /* spi_setup_xfer(&transfer,2048,2); */ + /* spi_message_add_tail ( &transfer, &msg ); */ + /* msg.is_dma_mapped=1; */ + /* ret = spi_sync ( spi_test, &msg ); */ + /* if(ret < 0){ */ + /* SPIDEV_LOG("Message transfer err:%d\n", ret); */ + /* }else{ */ + /* ret = spi_recv_check(&msg); */ + /* } */ + return ret; +} +static ssize_t +spi_msg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + /* struct spi_transfer *xfer; */ + /* struct spi_message *msg_str; */ + struct spi_message *p; + + int ret = 0; + struct spi_device *spi; + + struct spi_transfer transfer = {0,}; + struct spi_transfer transfer2 = {0,}; + struct spi_transfer transfer3 = {0,}; + struct spi_message msg; + struct mt_chip_conf *chip_config; + + u32 i, len = 4; + u32 tx_buffer = 0x12345678; + u32 rx_buffer = 0xaaaaaaaa; + + transfer.tx_buf = &tx_buffer; + transfer.rx_buf = &rx_buffer; + transfer.len = 4; + + spi = container_of(dev, struct spi_device, dev); + + if (unlikely(!spi)) { + SPIDEV_LOG("spi device is invalid\n"); + goto out; + } + if (unlikely(!buf)) { + SPIDEV_LOG("buf is invalid\n"); + goto out; + } + spi_message_init(&msg); + + if (!strncmp(buf, "-h", 2)) { + SPIDEV_MSG("Please input the message of this device to send and receive.\n"); + } else if (!strncmp(buf, "-w", 2)) { + buf += 3; + /* if (!buf) { + SPIDEV_LOG("Parameter is not enough.\n"); + goto out; + } */ + if (!strncmp(buf, "len=", 4) && 1 == sscanf(buf + 4, "%d", &len)) { + spi_setup_xfer(&spi->dev, &transfer, len, 0); + spi_message_add_tail(&transfer, &msg); + ret = spi_sync(spi, &msg); + if (ret < 0) { + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else { + ret = spi_recv_check_all(spi, &msg); + if (ret != 0) { + ret = -ret; + SPIDEV_LOG("Message transfer err:%d\n", ret); + goto out; + } + } + } + } else if (!strncmp(buf, "-func", 5)) { + buf += 6; + /* if (!buf) { + SPIDEV_LOG("Parameter is not enough.\n"); + goto out; + } */ + if (!strncmp(buf, "len=", 4) && 1 == sscanf(buf + 4, "%d", &len)) { + spi_setup_xfer(&spi->dev, &transfer, len, 1); + spi_message_add_tail(&transfer, &msg); + ret = spi_sync(spi, &msg); + if (ret < 0) { + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else { + ret = spi_recv_check(&msg); + if (ret != 0) { + ret = -ret; + SPIDEV_LOG("Message transfer err:%d\n", ret); + goto out; + } + } + } + if (!strncmp(buf, "cross", 5)) { + ret = tc_spi_cross_1k(spi); + if (ret < 0) { + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else if (ret != 0) { + ret = -ret; + SPIDEV_LOG("Message transfer err:%d\n", ret); + goto out; + } + } + } else if (!strncmp(buf, "-err", 4)) { + buf += 5; + chip_config = (struct mt_chip_conf *) spi->controller_data; + + if (!strncmp(buf, "buf", 3)) { /* case: tx_buf = NULL,rx_buf = NULL */ + transfer.len = 8; + transfer.tx_buf = NULL; + transfer.rx_buf = NULL; + } else if (!strncmp(buf, "len", 3)) {/* case: tx_buf != NULL,rx_buf != NULL, len = 0 */ + transfer.len = 0; + transfer.tx_buf = kzalloc(8, GFP_KERNEL); + transfer.rx_buf = kzalloc(8, GFP_KERNEL); + } else if (!strncmp(buf, "nomem", 5)) {/* case: DMA mapping error */ + spi_setup_xfer(&spi->dev, &transfer, 8, 0); + } else if (!strncmp(buf, "fifo_len", 8)) {/* case: len exceed FIFO size */ + chip_config->com_mod = 0; + spi_setup_xfer(&spi->dev, &transfer, 33, 0); + } else if (!strncmp(buf, "dma_len", 7)) {/* case: len exceed DMA size */ + chip_config->com_mod = 1; + spi_setup_xfer(&spi->dev, &transfer, 1025, 0); + } else if (!strncmp(buf, "xfer", 4)) {/* case: len exceed DMA size */ + ; + } else if (!strncmp(buf, "msg", 3)) {/* case: len exceed DMA size */ + ; + } else{ + SPIDEV_LOG("Error test Wrong parameters.\n"); + ret = -1; + goto out; + } + + if (strncmp(buf, "xfer", 4)) { /* case: MSG empty */ + spi_message_add_tail(&transfer, &msg); + } + if (!strncmp(buf, "msg", 3)) { /* case: message = NULL */ + ret = spi_sync(spi, NULL); + + } else{ + ret = spi_sync(spi, &msg); + } + if (ret != -EINVAL) + return -100; + SPIDEV_LOG("Message transfer error test passed ret:%d\n", ret); + } else if (!strncmp(buf, "-pause", 6)) { + spi_setup_xfer(&spi->dev, &transfer, 32, 0); + spi_message_add_tail(&transfer, &msg); + spi_setup_xfer(&spi->dev, &transfer2, 1024, 0); + spi_message_add_tail(&transfer2, &msg); + spi_setup_xfer(&spi->dev, &transfer3, 32, 0); + spi_message_add_tail(&transfer3, &msg); + + ret = spi_sync(spi, &msg); + if (ret < 0) { + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else{ + ret = spi_recv_check(&msg); + if (ret != 0) { + ret = -ret; + pr_debug("Message transfer err:%d\n", ret); + } + } + } else if (!strncmp(buf, "-stress", 7) && 1 == sscanf(buf + 8, "%d", &len)) { + stress_err = 0; + if (len == 0) { + /*xfer = kzalloc(SPI_STRESS_MAX*sizeof( struct spi_transfer) , GFP_KERNEL);*/ + /*will release in spi_recv_check() function*/ + SPIDEV_LOG("Message multi xfer stress start\n"); + for (i = 0; i < SPI_STRESS_MAX; i++) { + ret = spi_setup_xfer(&spi->dev, &stress_xfer[i], 32, 0); + if (ret != 0) + SPIDEV_LOG("Message set up err:%d\n", ret); + spi_message_add_tail(&stress_xfer[i], &msg); + + } + ret = spi_sync(spi, &msg); + if (ret < 0) { + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else{ + ret = spi_recv_check(&msg); + if (ret != 0) { + ret = -ret; + SPIDEV_LOG("Message transfer err:%d\n", ret); + } else{ + SPIDEV_LOG("Message multi xfer stress pass\n"); + } + } + } else if (len == 1) { + int loop_count = 0; + /* loop_count =250, take aboat half a hour. */ + for (loop_count = 0; loop_count <= 5000; loop_count++) { + /*msg_str = kzalloc(SPI_STRESS_MAX * sizeof(struct spi_message), GFP_KERNEL);*/ + /*xfer = kzalloc(SPI_STRESS_MAX * sizeof(struct spi_transfer) , GFP_KERNEL);*/ + SPIDEV_LOG("Message multi msg stress start\n"); + p = stress_msg; + for (i = 0; i < SPI_STRESS_MAX; i++) { + spi_message_init(p); + ret = spi_setup_xfer(&spi->dev, &stress_xfer[i], 32, 0); + if (ret != 0) + SPIDEV_LOG("xfer set up err:%d\n", ret); + + spi_message_add_tail(&stress_xfer[i], p); + + p->complete = spi_complete; + p->context = p; + /* ret = spi_async(spi, p); */ + /* if(ret < 0){ */ + /* SPIDEV_LOG("Message %d transfer err:%d\n",i, ret); */ + /* } */ + p++; + } + p = stress_msg; + for (i = 0; i < SPI_STRESS_MAX; i++) { + ret = spi_async(spi, p); + if (ret < 0) + SPIDEV_LOG("Message %d transfer err:%d\n", i, ret); + p++; + } + wait_for_completion(&mt_spi_done); + } + /* kfree(msg_str); */ + if (stress_err != 0) { + ret = -stress_err; + stress_err = 0; + SPIDEV_LOG("Message stress err:%d\n", ret); + } else{ + SPIDEV_LOG("Message stress Pass\n"); + ret = 0; + } + } else{ + } + } else if (!strncmp(buf, "-concurrent", 11)) { + + stress_err = 0; + spi_concur1 = kthread_run(threadfunc1, (void *)spi, "spi_concrrent1"); + if (IS_ERR(spi_concur1)) { + SPIDEV_LOG("Unable to start kernelthread 1\n"); + ret = -5; + goto out; + } + spi_concur2 = kthread_run(threadfunc2, (void *)spi, "spi_concrrent2"); + if (IS_ERR(spi_concur2)) { + SPIDEV_LOG("Unable to start kernelthread 2\n"); + ret = -5; + goto out; + } + spi_concur3 = kthread_run(threadfunc3, (void *)spi, "spi_concrrent3"); + if (IS_ERR(spi_concur3)) { + SPIDEV_LOG("Unable to start kernelthread 3\n"); + ret = -5; + goto out; + } + spi_concur4 = kthread_run(threadfunc4, (void *)spi, "spi_concrrent4"); + if (IS_ERR(spi_concur4)) { + SPIDEV_LOG("Unable to start kernelthread 4\n"); + ret = -5; + goto out; + } + + msleep(10000); + SPIDEV_LOG("stop kernelthread\n"); + + kthread_stop(spi_concur1); + kthread_stop(spi_concur2); + kthread_stop(spi_concur3); + kthread_stop(spi_concur4); + ret = -stress_err; + stress_err = 0; + SPIDEV_LOG("concurrent test done %d\n\n\n", ret); + + } else{ + SPIDEV_LOG("Wrong parameters.\n"); + ret = -1; + goto out; + } + ret = count; + +out: + return ret; + +} + +static DEVICE_ATTR(spi, 0200, NULL, spi_store); +static DEVICE_ATTR(spi_msg, 0200, NULL, spi_msg_store); + + + +static struct device_attribute *spi_attribute[] = { + &dev_attr_spi, + &dev_attr_spi_msg, +}; + +static int spi_create_attribute(struct device *dev) +{ + int num, idx; + int err = 0; + + num = (int)(sizeof(spi_attribute) / sizeof(spi_attribute[0])); + for (idx = 0; idx < num; idx++) { + err = device_create_file(dev, spi_attribute[idx]); + if (err) + break; + } + return err; + +} + +static void spi_remove_attribute(struct device *dev) +{ + int num, idx; + + num = (int)(sizeof(spi_attribute) / sizeof(spi_attribute[0])); + for (idx = 0; idx < num; idx++) + device_remove_file(dev, spi_attribute[idx]); +} + +static int spi_test_remove(struct spi_device *spi) +{ + + SPIDEV_LOG("spi_test_remove.\n"); + spi_remove_attribute(&spi->dev); + return 0; +} + +static int __init spi_test_probe(struct spi_device *spi) +{ + SPIDEV_LOG("spi test probe enter\n"); + spi_test = spi; + spi->mode = SPI_MODE_3; + /* spi->bits_per_word = 32; */ + return spi_create_attribute(&spi->dev); + return 0; +} + +/* struct spi_device_id spi_id_table = {"test_spi", 0}; */ +struct spi_device_id spi_id_table = {"spi-ut", 0}; + +static struct spi_driver spi_test_driver = { + .driver = { + .name = "test_spi", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = spi_test_probe, + .remove = spi_test_remove, + .id_table = &spi_id_table, +}; +static struct spi_board_info spi_board_devs[] __initdata = { + [0] = { + .modalias = "spi-ut", + .bus_num = 0, + .chip_select = 1, + .mode = SPI_MODE_3, + }, + [1] = { + .modalias = "spi-ut", + .bus_num = 1, + .chip_select = 1, + .mode = SPI_MODE_3, + }, +}; + +static int __init spi_dev_init(void) +{ + SPIDEV_LOG("SPI_DEV_INIT.\n"); + spi_register_board_info(spi_board_devs, ARRAY_SIZE(spi_board_devs)); + return spi_register_driver(&spi_test_driver); +} + +static void __exit spi_test_exit(void) +{ + SPIDEV_LOG("SPI_DEV_EXIT.\n"); + spi_unregister_driver(&spi_test_driver); +} + +module_init(spi_dev_init); +module_exit(spi_test_exit); + +MODULE_DESCRIPTION("mt SPI test device driver"); +MODULE_AUTHOR("Ranran Lu "); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/mediatek/mt6755/spi.c b/drivers/spi/mediatek/mt6755/spi.c new file mode 100644 index 0000000000000000000000000000000000000000..a4d506d48a8990d1cb1527c0903ad00956aa79c8 --- /dev/null +++ b/drivers/spi/mediatek/mt6755/spi.c @@ -0,0 +1,1745 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif /* !defined(CONFIG_MTK_CLKMGR) */ +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#endif +/*#include */ +#include "mt_spi.h" +#include "mt_spi_hal.h" +/*#include "mach/memory.h"*/ +#if defined(CONFIG_MTK_LEGACY) +#include +#endif /* defined(CONFIG_MTK_LEGACY) */ +#if defined(CONFIG_MTK_CLKMGR) +#include +#endif /* defined(CONFIG_MTK_CLKMGR) */ + +#ifdef CONFIG_TRUSTONIC_TEE_SUPPORT +#define SPI_TRUSTONIC_TEE_SUPPORT +#endif + +#ifdef SPI_TRUSTONIC_TEE_SUPPORT +#include +#include +#endif + +#if (defined(CONFIG_MTK_FPGA)) +#define CONFIG_MT_SPI_FPGA_ENABLE +#endif +/* auto select transfer mode */ +/* #define SPI_AUTO_SELECT_MODE */ +#ifdef SPI_AUTO_SELECT_MODE +#define SPI_DATA_SIZE 16 +#endif + +/* open base log out */ +/* #define SPI_DEBUG */ + +/* open verbose log out */ +/* #define SPI_VERBOSE */ + +#define IDLE 0 +#define INPROGRESS 1 +#define PAUSED 2 + +#define PACKET_SIZE 0x400 + +#define SPI_FIFO_SIZE 32 +/* #define FIFO_TX 0 */ +/* #define FIFO_RX 1 */ +enum spi_fifo { + FIFO_TX, + FIFO_RX, + FIFO_ALL +}; + +#define INVALID_DMA_ADDRESS 0xffffffff + +struct mt_spi_t { + struct platform_device *pdev; + void __iomem *regs; + int irq; + int running; + u32 pad_macro; + struct wake_lock wk_lock; + struct mt_chip_conf *config; + struct spi_master *master; + + struct spi_transfer *cur_transfer; + struct spi_transfer *next_transfer; + + spinlock_t lock; + struct list_head queue; +#if !defined(CONFIG_MTK_CLKMGR) + struct clk *clk_main; /* main clock for spi bus */ +#endif /* !defined(CONFIG_MTK_LEGACY) */ +}; +/* open time record debug, log can't affect transfer */ +/* #define SPI_REC_DEBUG */ + +/* u32 pad_macro; */ +static void enable_clk(struct mt_spi_t *ms) +{ +#if (!defined(CONFIG_MT_SPI_FPGA_ENABLE)) +#if defined(CONFIG_MTK_CLKMGR) + enable_clock(MT_CG_PERI_SPI0, "spi"); +#else + int ret; +/* clk_prepare_enable(ms->clk_main); */ + ret = clk_enable(ms->clk_main); +#endif +#endif + +} + +void mt_spi_enable_master_clk(struct spi_device *ms) +{ + enable_clk(spi_master_get_devdata(ms->master)); +} + + +static void disable_clk(struct mt_spi_t *ms) +{ +#if (!defined(CONFIG_MT_SPI_FPGA_ENABLE)) +#if defined(CONFIG_MTK_CLKMGR) + disable_clock(MT_CG_PERI_SPI0, "spi"); +#else +/* clk_disable_unprepare(ms->clk_main); */ + clk_disable(ms->clk_main); +#endif +#endif + +} + +void mt_spi_disable_master_clk(struct spi_device *ms) +{ + disable_clk(spi_master_get_devdata(ms->master)); +} + +#ifdef SPI_DEBUG +#define SPI_DBG(fmt, args...) pr_debug("spi.c:%5d: <%s>" fmt, __LINE__, __func__, ##args) + +#ifdef SPI_VERBOSE +#define SPI_INFO(dev, fmt, args...) dev_alert(dev, "spi.c:%5d: <%s>" fmt, __LINE__, __func__, ##args) +static void spi_dump_reg(struct mt_spi_t *ms) +{ + SPI_DBG("||*****************************************||\n"); + SPI_DBG("cfg0:0x%.8x\n", spi_readl(ms, SPI_CFG0_REG)); + SPI_DBG("cfg1:0x%.8x\n", spi_readl(ms, SPI_CFG1_REG)); + SPI_DBG("cmd :0x%.8x\n", spi_readl(ms, SPI_CMD_REG)); + /* SPI_DBG("spi_tx_data_reg:0x%x\n", spi_readl(ms, SPI_TX_DATA_REG)); */ + /* SPI_DBG("spi_rx_data_reg:0x%x\n", spi_readl(ms, SPI_RX_DATA_REG)); */ + SPI_DBG("tx_s:0x%.8x\n", spi_readl(ms, SPI_TX_SRC_REG)); + SPI_DBG("rx_d:0x%.8x\n", spi_readl(ms, SPI_RX_DST_REG)); + SPI_DBG("sta1:0x%.8x\n", spi_readl(ms, SPI_STATUS1_REG)); + SPI_DBG(":0x%.8x\n", spi_readl(ms, SPI_STATUS1_REG)); + + SPI_DBG("||*****************************************||\n"); + +} +#else +#define SPI_INFO(dev, fmt, args...) +static void spi_dump_reg(struct mt_spi_t *ms) +{ +} +#endif +#else +#define SPI_DBG(fmt, args...) +#define SPI_INFO(dev, fmt, args...) +#endif + +#ifdef SPI_REC_DEBUG +/*EVB the clock frequency is 130MHz, may be is reason that ldvt env. + but it is 98500KHz on phone. + */ +#define SPI_CLOCK_PERIED 100000 /* kHz */ + +#include /* getpid() */ +#define SPI_REC_MSG_MAX 500 +#define SPI_REC_NUM 20 +#define SPI_REC_STR_LEN 256 +static u32 spi_speed; +static char msg_rec[SPI_REC_MSG_MAX][SPI_REC_STR_LEN]; +static int rec_count; +static int rec_count_tmp = 1; +static int rec_msg_count; + +static atomic_t rec_log_count = ATOMIC_INIT(0); + +static unsigned long long rec_msg_time[SPI_REC_MSG_MAX]; +static unsigned long long rec_time; + +/* should coding in file kernel/arch/arm/kernel/irq.c. + extern unsigned long long spi_rec_t0; + spi_rec_t0 = sched_clock(); +*/ +unsigned long long spi_rec_t0; /* record interrupt act */ + +DEFINE_SPINLOCK(msg_rec_lock); +/* static unsigned long long t_rec[4]; */ + +/* + the function invoke time averrage 2us. +*/ + +static inline void spi_rec_time(const char *str) +{ + unsigned long flags; + char tmp[64]; + + spin_lock_irqsave(&msg_rec_lock, flags); + + if (strncmp(str, "msgs", 4) == 0) { + rec_msg_count++; + if (rec_msg_count >= SPI_REC_MSG_MAX) + rec_msg_count = 0; + rec_msg_time[rec_msg_count] = sched_clock(); + msg_rec[rec_msg_count][0] = '\0'; + snprintf(tmp, sizeof(tmp), "%s,pid:%4d;", str, sys_getpid()); + strcat(msg_rec[rec_msg_count], tmp); + } else if (strncmp(str, "msgn", 4) == 0) { + rec_count++; + if (rec_count >= SPI_REC_MSG_MAX) + rec_count = 0; + rec_time = sched_clock(); + /* msg_rec[rec_count][0] = '\0'; */ + snprintf(tmp, sizeof(tmp), "%s:%8lld;", str, rec_time - rec_msg_time[rec_count]); + strcat(msg_rec[rec_count], tmp); + /* snprintf(msg_rec[rec_count], sizeof(msg_rec[rec_count]), "msg %3d: ", rec_count); */ + /* if want to spi interrupt action, cancel the comment */ + } /* else if(strncmp(str, "irqs", 4) == 0) { + snprintf(tmp, sizeof(tmp), "%s,%5lld:%8lld;",str, + sched_clock() - spi_rec_t0,sched_clock() - rec_time); + if((strlen(tmp) + strlen(msg_rec[rec_count])) < (SPI_REC_STR_LEN - 64)){ + strcat(msg_rec[rec_count],tmp); + } else { + strcat(msg_rec[rec_count],"#"); + } + } */ + else { + snprintf(tmp, sizeof(tmp), "%s:%8lld;", str, sched_clock() - rec_time); + if ((strlen(tmp) + strlen(msg_rec[rec_count])) < (SPI_REC_STR_LEN - 64)) + strcat(msg_rec[rec_count], tmp); + else + strcat(msg_rec[rec_count], "@"); + } + spin_unlock_irqrestore(&msg_rec_lock, flags); + +} + +void mt_spi_workqueue_handler(void *data) +{ + int i = 0; + + for (i = 0; i < SPI_REC_NUM; i++) { + SPI_DBG("spi-rec%3d-%3d:%s\n", rec_count, rec_count_tmp, msg_rec[rec_count_tmp]); + msg_rec[rec_count_tmp][0] = '\0'; + rec_count_tmp++; + if (rec_count_tmp >= SPI_REC_MSG_MAX) + rec_count_tmp = 0; + } + atomic_dec(&rec_log_count); + +} + +DECLARE_WORK(mt_spi_workqueue, mt_spi_workqueue_handler); + +#else +static inline void spi_rec_time(const char *str) +{ + +} + +#endif + +/* static void disable_clk(void); */ +/* +void mt_spi_msgdone_handler(void *data) +{ + disable_clk(); + return; +} +*/ +/* DECLARE_WORK(mt_spi_msgdone_workqueue,mt_spi_msgdone_handler); */ + +#ifdef SPI_TRUSTONIC_TEE_SUPPORT +#define DEFAULT_HANDLES_NUM (64) +#define MAX_OPEN_SESSIONS (0xffffffff - 1) + +static const struct mc_uuid_t secspi_uuid = { TL_SPI_UUID }; +static struct mc_session_handle secspi_session = { 0 }; + +static u32 secspi_session_ref; +static u32 secspi_devid = MC_DEVICE_ID_DEFAULT; +static tciSpiMessage_t *secspi_tci; + +static DEFINE_MUTEX(secspi_lock); + +int secspi_session_open(void) +{ + enum mc_result mc_ret = MC_DRV_OK; + + mutex_lock(&secspi_lock); + + + pr_warn("secspi_session_open start\n"); + do { + /* sessions reach max numbers ? */ + + if (secspi_session_ref > MAX_OPEN_SESSIONS) { + pr_warn("secspi_session > 0x%x\n", MAX_OPEN_SESSIONS); + break; + } + + if (secspi_session_ref > 0) { + secspi_session_ref++; + break; + } + + /* open device */ + mc_ret = mc_open_device(secspi_devid); + if (MC_DRV_OK != mc_ret) { + pr_warn("mc_open_device failed: %d\n", mc_ret); + break; + } + + /* allocating WSM for DCI */ + mc_ret = + mc_malloc_wsm(secspi_devid, 0, sizeof(tciSpiMessage_t), + (uint8_t **) &secspi_tci, 0); + if (MC_DRV_OK != mc_ret) { + pr_warn("mc_malloc_wsm failed: %d\n", mc_ret); + mc_close_device(secspi_devid); + break; + } + + /* open session */ + secspi_session.device_id = secspi_devid; + mc_ret = + mc_open_session(&secspi_session, &secspi_uuid, (uint8_t *) secspi_tci, + sizeof(tciSpiMessage_t)); + + if (MC_DRV_OK != mc_ret) { + pr_warn("secspi_session_open fail: %d\n", mc_ret); + mc_free_wsm(secspi_devid, (uint8_t *) secspi_tci); + mc_close_device(secspi_devid); + secspi_tci = NULL; + break; + } + secspi_session_ref = 1; + + } while (0); + + pr_warn("secspi_session_open: ret=%d, ref=%d\n", mc_ret, secspi_session_ref); + + mutex_unlock(&secspi_lock); + pr_err("secspi_session_open end\n"); + + if (MC_DRV_OK != mc_ret) + return -ENXIO; + + return 0; +} + +void secspi_enable_clk(struct spi_device *spidev) +{ +#if !defined(CONFIG_MTK_CLKMGR) + int ret; +#endif + struct spi_master *master; + struct mt_spi_t *ms; + + master = spidev->master; + ms = spi_master_get_devdata(master); + +#if !defined(CONFIG_MTK_CLKMGR) + /* + * prepare the clock source + */ + ret = clk_prepare(ms->clk_main); +#endif + enable_clk(ms); +} + +int secspi_execute(u32 cmd, tciSpiMessage_t *param) +{ + enum mc_result mc_ret; + + pr_warn("secspi_execute\n"); + mutex_lock(&secspi_lock); + + if (NULL == secspi_tci) { + mutex_unlock(&secspi_lock); + pr_warn("secspi_tci not exist\n"); + return -ENODEV; + } + + /*set transfer data para */ + if (NULL == param) { + pr_warn("secspi_execute parameter is NULL !!\n"); + } else { + secspi_tci->tx_buf = param->tx_buf; + secspi_tci->rx_buf = param->rx_buf; + secspi_tci->len = param->len; + secspi_tci->is_dma_used = param->is_dma_used; + secspi_tci->tx_dma = param->tx_dma; + secspi_tci->rx_dma = param->rx_dma; + secspi_tci->tl_chip_config = param->tl_chip_config; + } + + secspi_tci->cmd_spi.header.commandId = (tciCommandId_t) cmd; + secspi_tci->cmd_spi.len = 0; + + pr_warn("mc_notify\n"); + + /* enable_clock(MT_CG_PERI_SPI0, "spi"); */ + /* enable_clk(ms); */ + + mc_ret = mc_notify(&secspi_session); + + if (MC_DRV_OK != mc_ret) { + pr_warn("mc_notify failed: %d", mc_ret); + goto exit; + } + + pr_warn("SPI mc_wait_notification\n"); + mc_ret = mc_wait_notification(&secspi_session, -1); + + if (MC_DRV_OK != mc_ret) { + pr_warn("SPI mc_wait_notification failed: %d", mc_ret); + goto exit; + } + +exit: + + mutex_unlock(&secspi_lock); + + if (MC_DRV_OK != mc_ret) + return -ENOSPC; + + return 0; +} + +#if 0 +static int secspi_session_close(void) +{ + enum mc_result mc_ret = MC_DRV_OK; + + mutex_lock(&secspi_lock); + + do { + /* session is already closed ? */ + if (secspi_session_ref == 0) { + pr_warn("spi_session already closed\n"); + break; + } + + if (secspi_session_ref > 1) { + secspi_session_ref--; + break; + } + + /* close session */ + mc_ret = mc_close_session(&secspi_session); + if (MC_DRV_OK != mc_ret) { + pr_warn("SPI mc_close_session failed: %d\n", mc_ret); + break; + } + + /* free WSM for DCI */ + mc_ret = mc_free_wsm(secspi_devid, (uint8_t *) secspi_tci); + if (MC_DRV_OK != mc_ret) { + pr_warn("SPI mc_free_wsm failed: %d\n", mc_ret); + break; + } + secspi_tci = NULL; + secspi_session_ref = 0; + + /* close device */ + mc_ret = mc_close_device(secspi_devid); + if (MC_DRV_OK != mc_ret) + pr_warn("SPI mc_close_device failed: %d\n", mc_ret); + + } while (0); + + pr_warn("secspi_session_close: ret=%d, ref=%d\n", mc_ret, secspi_session_ref); + + mutex_unlock(&secspi_lock); + + if (MC_DRV_OK != mc_ret) + return -ENXIO; + + return 0; + +} +#endif + +/*used for REE to detach IRQ of TEE*/ +void spi_detach_irq_tee(void) +{ + secspi_session_open(); + secspi_execute(2, NULL); + pr_warn("secspi_execute 2 finished!!!\n"); +} +#endif + +static void spi_gpio_set(struct mt_spi_t *ms) +{ + /* mt_set_gpio_mode(GPIO_SPI_CS_PIN, GPIO_SPI_CS_PIN_M_SPI_CS_N); */ + /* mt_set_gpio_mode(GPIO_SPI_SCK_PIN, GPIO_SPI_SCK_PIN_M_SPI_SCK); */ + /* mt_set_gpio_mode(GPIO_SPI_MISO_PIN, GPIO_SPI_MISO_PIN_M_SPI_MISO); */ + /* mt_set_gpio_mode(GPIO_SPI_MOSI_PIN, GPIO_SPI_MOSI_PIN_M_SPI_MOSI); */ + +} + +static void spi_gpio_reset(struct mt_spi_t *ms) +{ + /* set dir pull to save power */ + /* mt_set_gpio_mode(GPIO_SPI_CS_PIN, GPIO_SPI_CS_PIN_M_GPIO); */ + /* mt_set_gpio_mode(GPIO_SPI_SCK_PIN, GPIO_SPI_SCK_PIN_M_GPIO); */ + /* mt_set_gpio_mode(GPIO_SPI_MISO_PIN, GPIO_SPI_MISO_PIN_M_GPIO); */ + /* mt_set_gpio_mode(GPIO_SPI_MOSI_PIN, GPIO_SPI_MOSI_PIN_M_GPIO); */ + +} + +static int is_pause_mode(struct spi_message *msg) +{ + struct mt_chip_conf *conf; + + conf = (struct mt_chip_conf *)msg->state; + return conf->pause; +} + +static int is_fifo_read(struct spi_message *msg) +{ + struct mt_chip_conf *conf; + + conf = (struct mt_chip_conf *)msg->state; + return (conf->com_mod == FIFO_TRANSFER) || (conf->com_mod == OTHER1); +} + +static int is_interrupt_enable(struct mt_spi_t *ms) +{ + u32 cmd; + + cmd = spi_readl(ms, SPI_CMD_REG); + + return (cmd >> SPI_CMD_FINISH_IE_OFFSET) & 1; +} + +static inline void set_pause_bit(struct mt_spi_t *ms) +{ + u32 reg_val; + + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val |= 1 << SPI_CMD_PAUSE_EN_OFFSET; + spi_writel(ms, SPI_CMD_REG, reg_val); + +} + +static inline void clear_pause_bit(struct mt_spi_t *ms) +{ + u32 reg_val; + + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_PAUSE_EN_MASK; + spi_writel(ms, SPI_CMD_REG, reg_val); + +} + +static inline void clear_resume_bit(struct mt_spi_t *ms) +{ + u32 reg_val; + + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_RESUME_MASK; + spi_writel(ms, SPI_CMD_REG, reg_val); + +} + +static inline void spi_disable_dma(struct mt_spi_t *ms) +{ + u32 cmd; + + cmd = spi_readl(ms, SPI_CMD_REG); + cmd &= ~SPI_CMD_TX_DMA_MASK; + cmd &= ~SPI_CMD_RX_DMA_MASK; + spi_writel(ms, SPI_CMD_REG, cmd); + +} + +/* static inline void spi_clear_fifo(struct mt_spi_t *ms, enum spi_fifo fifo) */ +/* { */ +/* u32 volatile reg_val; */ +/* int i; */ +/* */ +/* for(i = 0; i < SPI_FIFO_SIZE/4; i++){ */ +/* #if 1 */ +/* if ( fifo == FIFO_TX ) */ +/* spi_writel( ms, SPI_TX_DATA_REG, 0x0 ); */ +/* else if( fifo == FIFO_RX ) */ +/* reg_val = spi_readl ( ms, SPI_RX_DATA_REG ); */ +/* else if(fifo == FIFO_ALL){ */ +/* spi_writel( ms, SPI_TX_DATA_REG, 0x0 ); */ +/* spi_writel( ms, SPI_RX_DATA_REG, 0x0 ); //clear data */ +/* reg_val = spi_readl( ms, SPI_RX_DATA_REG ); */ +/* }else{ */ +/* SPI_DBG("The parameter is not right.\n"); */ +/* } */ +/* SPI_DBG("SPI_STATUS1_REG:0x%.8x\n", spi_readl(ms, SPI_STATUS1_REG)); */ +/* #endif */ +/* } */ +/* return; */ +/* } */ + +static inline void spi_enable_dma(struct mt_spi_t *ms, u8 mode) +{ + u32 cmd; + + cmd = spi_readl(ms, SPI_CMD_REG); +#define SPI_4B_ALIGN 0x4 + /* set up the DMA bus address */ + if ((mode == DMA_TRANSFER) || (mode == OTHER1)) { + if ((ms->cur_transfer->tx_buf != NULL) + || ((ms->cur_transfer->tx_dma != INVALID_DMA_ADDRESS) + && (ms->cur_transfer->tx_dma != 0))) { + if (ms->cur_transfer->tx_dma & (SPI_4B_ALIGN - 1)) { +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + dev_err(&ms->pdev->dev, + "Warning!Tx_DMA address should be 4Byte alignment,buf:%p,dma:%llx\n", + ms->cur_transfer->tx_buf, ms->cur_transfer->tx_dma); +#else + dev_err(&ms->pdev->dev, + "Warning!Tx_DMA address should be 4Byte alignment,buf:%p,dma:%x\n", + ms->cur_transfer->tx_buf, ms->cur_transfer->tx_dma); +#endif + } + spi_writel(ms, SPI_TX_SRC_REG, cpu_to_le32(ms->cur_transfer->tx_dma)); + cmd |= 1 << SPI_CMD_TX_DMA_OFFSET; + } + } + if ((mode == DMA_TRANSFER) || (mode == OTHER2)) { + if ((ms->cur_transfer->rx_buf != NULL) + || ((ms->cur_transfer->rx_dma != INVALID_DMA_ADDRESS) + && (ms->cur_transfer->rx_dma != 0))) { + if (ms->cur_transfer->rx_dma & (SPI_4B_ALIGN - 1)) { +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + dev_err(&ms->pdev->dev, + "Warning!Rx_DMA address should be 4Byte alignment,buf:%p,dma:%llx\n", + ms->cur_transfer->rx_buf, ms->cur_transfer->rx_dma); +#else + dev_err(&ms->pdev->dev, + "Warning!Rx_DMA address should be 4Byte alignment,buf:%p,dma:%x\n", + ms->cur_transfer->rx_buf, ms->cur_transfer->rx_dma); +#endif + } + spi_writel(ms, SPI_RX_DST_REG, cpu_to_le32(ms->cur_transfer->rx_dma)); + cmd |= 1 << SPI_CMD_RX_DMA_OFFSET; + } + } + mb(); + spi_writel(ms, SPI_CMD_REG, cmd); + +} + +static inline int spi_setup_packet(struct mt_spi_t *ms) +{ + u32 packet_size, packet_loop, cfg1; + + /* set transfer packet and loop */ + if (ms->cur_transfer->len < PACKET_SIZE) + packet_size = ms->cur_transfer->len; + else + packet_size = PACKET_SIZE; + + if (ms->cur_transfer->len % packet_size) { + packet_loop = ms->cur_transfer->len / packet_size + 1; + /* parameter not correct, there will be more data transfer,notice user to change */ + dev_err(&ms->pdev->dev, "ERROR!!The lens must be a multiple of %d, your len %u\n\n", + PACKET_SIZE, ms->cur_transfer->len); + return -EINVAL; + } + packet_loop = (ms->cur_transfer->len) / packet_size; + + SPI_DBG("The packet_size:0x%x packet_loop:0x%x\n", packet_size, packet_loop); + + cfg1 = spi_readl(ms, SPI_CFG1_REG); + cfg1 &= ~(SPI_CFG1_PACKET_LENGTH_MASK + SPI_CFG1_PACKET_LOOP_MASK); + cfg1 |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET; + cfg1 |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET; + spi_writel(ms, SPI_CFG1_REG, cfg1); + + return 0; +} + +/* static int spi_is_busy(struct mt_spi_t *ms) */ +/* { */ +/* u32 reg_val; */ +/* unsigned long flags; */ +/* */ +/* spin_lock_irqsave(&ms->spin_lock, flags); */ +/* reg_val = spi_readl(ms, SPI_STATUS1_REG); */ +/* spin_unlock_irqrestore(&ms->spin_lock, flags); */ +/* if ( reg_val & 0x1) { */ +/* SPI_DBG("is not busy.\n"); */ +/* return 0; */ +/* }else { */ +/* SPI_DBG("is busy.\n"); */ +/* return 1; */ +/* } */ +/* } */ + +static inline void spi_start_transfer(struct mt_spi_t *ms) +{ + u32 reg_val; + + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val |= 1 << SPI_CMD_ACT_OFFSET; + + /* All register must be prepared before setting the start bit [SMP] */ + mb(); + spi_writel(ms, SPI_CMD_REG, reg_val); + +} + +static inline void spi_resume_transfer(struct mt_spi_t *ms) +{ + u32 reg_val; + + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_RESUME_MASK; + reg_val |= 1 << SPI_CMD_RESUME_OFFSET; + /* All register must be prepared before setting the start bit [SMP] */ + mb(); + spi_writel(ms, SPI_CMD_REG, reg_val); + +} + +static void reset_spi(struct mt_spi_t *ms) +{ + u32 reg_val; + + /* set the software reset bit in SPI_CMD_REG. */ + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_RST_MASK; + reg_val |= 1 << SPI_CMD_RST_OFFSET; + spi_writel(ms, SPI_CMD_REG, reg_val); + + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_RST_MASK; + spi_writel(ms, SPI_CMD_REG, reg_val); + +} + +static inline int is_last_xfer(struct spi_message *msg, struct spi_transfer *xfer) +{ + return msg->transfers.prev == &xfer->transfer_list; +} + +static int transfer_dma_mapping(struct mt_spi_t *ms, u8 mode, struct spi_transfer *xfer) +{ + struct device *dev = &ms->pdev->dev; + + xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS; + + if ((mode == DMA_TRANSFER) || (mode == OTHER1)) { + if (xfer->tx_buf) { + xfer->tx_dma = dma_map_single(dev, (void *)xfer->tx_buf, + xfer->len, DMA_TO_DEVICE); + + if (dma_mapping_error(dev, xfer->tx_dma)) { + dev_err(&ms->pdev->dev, "dma mapping tx_buf error.\n"); + return -ENOMEM; + } + } + + } + if ((mode == DMA_TRANSFER) || (mode == OTHER2)) { + if (xfer->rx_buf) { + xfer->rx_dma = dma_map_single(dev, xfer->rx_buf, + xfer->len, DMA_FROM_DEVICE); + + if (dma_mapping_error(dev, xfer->rx_dma)) { + if (xfer->tx_buf) + dma_unmap_single(dev, xfer->tx_dma, + xfer->len, DMA_TO_DEVICE); + + dev_err(&ms->pdev->dev, "dma mapping rx_buf error.\n"); + return -ENOMEM; + } + } + } + if (mode != FIFO_TRANSFER) + SPI_DBG("Transfer_dma_mapping success.\n"); +#if 0 + /* cross 1K test, non 4byte alignment */ + { +#define SPI_CROSS_ALIGN_OFFSET 1009 + + u8 *p; + + SPI_DBG("Transfer dma addr:Tx:0x%x, Rx:0x%x, before\n", xfer->tx_dma, xfer->rx_dma); + SPI_DBG("Transfer buf addr:Tx:0x%x, Rx:0x%x, before\n", xfer->tx_buf, xfer->rx_buf); + xfer->len = 32; + p = (u8 *) xfer->tx_dma; + xfer->tx_dma = (u32 *) (p + SPI_CROSS_ALIGN_OFFSET); + p = (u8 *) xfer->rx_dma; + xfer->rx_dma = (u32 *) (p + SPI_CROSS_ALIGN_OFFSET); + + p = (u8 *) xfer->tx_buf; + xfer->tx_buf = (u32 *) (p + SPI_CROSS_ALIGN_OFFSET); + p = (u8 *) xfer->rx_buf; + xfer->rx_buf = (u32 *) (p + SPI_CROSS_ALIGN_OFFSET); + SPI_DBG("Transfer dma addr:Tx:0x%x, Rx:0x%x\n", xfer->tx_dma, xfer->rx_dma); + SPI_DBG("Transfer buf addr:Tx:0x%x, Rx:0x%x\n", xfer->tx_buf, xfer->rx_buf); + } +#endif + return 0; +} + +static void transfer_dma_unmapping(struct mt_spi_t *ms, struct spi_transfer *xfer) +{ + struct device *dev = &ms->pdev->dev; + + if ((xfer->tx_dma != INVALID_DMA_ADDRESS) && (xfer->tx_dma != 0)) { + dma_unmap_single(dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE); + SPI_INFO(dev, "tx_dma:0x%x,unmapping\n", (unsigned int)xfer->tx_dma); + xfer->tx_dma = INVALID_DMA_ADDRESS; + } + if ((xfer->rx_dma != INVALID_DMA_ADDRESS) && (xfer->rx_dma != 0)) { + dma_unmap_single(dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE); + SPI_INFO(dev, "rx_dma:0x%x,unmapping\n", (unsigned int)xfer->rx_dma); + xfer->rx_dma = INVALID_DMA_ADDRESS; + } + +} + +static void mt_spi_msg_done(struct mt_spi_t *ms, struct spi_message *msg, int status); +static void mt_spi_next_message(struct mt_spi_t *ms); +static int mt_do_spi_setup(struct mt_spi_t *ms, struct mt_chip_conf *chip_config); + +static int mt_spi_next_xfer(struct mt_spi_t *ms, struct spi_message *msg) +{ + struct spi_transfer *xfer; + struct mt_chip_conf *chip_config = (struct mt_chip_conf *)msg->state; + u8 mode, cnt, i; + int ret = 0; + char xfer_rec[32]; +#ifdef SPI_AUTO_SELECT_MODE + u32 reg_val = 0; +#endif + + if (unlikely(!ms)) { + dev_err(&msg->spi->dev, "master wrapper is invalid\n"); + ret = -EINVAL; + goto fail; + } + if (unlikely(!msg)) { + dev_err(&msg->spi->dev, "msg is invalid\n"); + ret = -EINVAL; + goto fail; + } + if (unlikely(!msg->state)) { + dev_err(&msg->spi->dev, "msg config is invalid\n"); + ret = -EINVAL; + goto fail; + } + + if (unlikely(!is_interrupt_enable(ms))) { + dev_err(&msg->spi->dev, "interrupt is disable\n"); + ret = -EINVAL; + goto fail; + } +#ifdef SPI_AUTO_SELECT_MODE + if (ms->cur_transfer.len > SPI_DATA_SIZE) { + chip_config->com_mod = DMA_TRANSFER; + pr_warn("SPI auto select DMA mode\n"); + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val |= ((1 << SPI_CMD_TX_DMA_OFFSET) | (1 << SPI_CMD_RX_DMA_OFFSET)); + spi_writel(ms, SPI_CMD_REG, reg_val); + pr_warn("SPI auto select CMD = 0x%x\n", spi_readl(ms, SPI_CMD_REG)); + } else { + pr_warn("SPI auto select do nothing\n"); + } +#endif + + mode = chip_config->com_mod; + + xfer = ms->cur_transfer; + + SPI_DBG("start xfer 0x%p, mode %d, len %u\n", xfer, mode, xfer->len); + + if ((mode == FIFO_TRANSFER) || (mode == OTHER1) || (mode == OTHER2)) { + if (xfer->len > SPI_FIFO_SIZE) { + ret = -EINVAL; + dev_err(&msg->spi->dev, "xfer len is invalid over fifo size\n"); + goto fail; + } + } + + if (is_last_xfer(msg, xfer)) { + SPI_DBG("The last xfer.\n"); + ms->next_transfer = NULL; + clear_pause_bit(ms); + } else { + SPI_DBG("Not the last xfer.\n"); + ms->next_transfer = list_entry(xfer->transfer_list.next, + struct spi_transfer, transfer_list); + } + /* disable DMA */ + spi_disable_dma(ms); + /* spi_clear_fifo(ms, FIFO_ALL); */ + + ret = spi_setup_packet(ms); + if (ret < 0) + goto fail; + + /* Using FIFO to send data */ + if ((mode == FIFO_TRANSFER) || (mode == OTHER2)) { + cnt = (xfer->len % 4) ? (xfer->len / 4 + 1) : (xfer->len / 4); + for (i = 0; i < cnt; i++) { + if (xfer->tx_buf == NULL) + spi_writel(ms, SPI_TX_DATA_REG, 0); + else + spi_writel(ms, SPI_TX_DATA_REG, *((u32 *) xfer->tx_buf + i)); + SPI_INFO(&msg->spi->dev, "tx_buf data is:%x\n", + *((u32 *) xfer->tx_buf + i)); + SPI_INFO(&msg->spi->dev, "tx_buf addr is:%p\n", (u32 *) xfer->tx_buf + i); + } + } + /* Using DMA to send data */ + if ((mode == DMA_TRANSFER) || (mode == OTHER1) || (mode == OTHER2)) + spi_enable_dma(ms, mode); +#ifdef SPI_VERBOSE + spi_dump_reg(ms); /* Dump register before transfer */ +#endif + + if (ms->running == PAUSED) { + SPI_DBG("pause status to resume.\n"); + + spi_resume_transfer(ms); + } else if (ms->running == IDLE) { + SPI_DBG("The xfer start\n"); + /* if there is only one transfer, pause bit should not be set. */ + if (is_pause_mode(msg) && !is_last_xfer(msg, xfer)) { + SPI_DBG("set pause mode.\n"); + set_pause_bit(ms); + } + /* All register must be prepared before setting the start bit [SMP] */ + + spi_start_transfer(ms); + + } else { + dev_err(&msg->spi->dev, "Wrong status\n"); + ret = -1; + goto fail; + } + snprintf(xfer_rec, sizeof(xfer_rec), "xfer,%3d", xfer->len); + spi_rec_time(xfer_rec); + + ms->running = INPROGRESS; + + /* exit pause mode */ + if (is_pause_mode(msg) && is_last_xfer(msg, xfer)) + clear_resume_bit(ms); + + return 0; +fail: + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if ((!msg->is_dma_mapped)) + transfer_dma_unmapping(ms, xfer); + } + ms->running = IDLE; + mt_spi_msg_done(ms, msg, ret); + return ret; +} + +static void mt_spi_msg_done(struct mt_spi_t *ms, struct spi_message *msg, int status) +{ + + list_del(&msg->queue); + msg->status = status; + + SPI_DBG("msg:%p complete(%d): %u bytes transferred\n", msg, status, msg->actual_length); + + spi_disable_dma(ms); + /* spi_clear_fifo(ms, FIFO_ALL); */ + + msg->complete(msg->context); + + ms->running = IDLE; + ms->cur_transfer = NULL; + ms->next_transfer = NULL; + + /* disable_clk(); */ + spi_rec_time("msge"); +#ifdef SPI_REC_DEBUG + + if (!(rec_count % SPI_REC_NUM)) { + atomic_inc(&rec_log_count); + schedule_work(&mt_spi_workqueue); + } +#if 0 + if (atomic_read(&rec_log_count) > 0) { + schedule_work(&mt_spi_workqueue); + tasklet_schedule(&spi_tasklet); + SPI_OUT_REC_TIME; + rec_count = 0; + } +#endif +#endif + + /* continue if needed */ + if (list_empty(&ms->queue)) { + SPI_DBG("All msg is completion.\n\n"); + /* clock and gpio reset */ + spi_gpio_reset(ms); + + disable_clk(ms); + + /* schedule_work(&mt_spi_msgdone_workqueue);//disable clock */ + + wake_unlock(&ms->wk_lock); + } else + mt_spi_next_message(ms); +} + +static void mt_spi_next_message(struct mt_spi_t *ms) +{ + struct spi_message *msg; + struct mt_chip_conf *chip_config; + char msg_addr[32]; + + msg = list_entry(ms->queue.next, struct spi_message, queue); + chip_config = (struct mt_chip_conf *)msg->state; + +#ifdef SPI_REC_DEBUG + spi_speed = SPI_CLOCK_PERIED / (chip_config->low_time + chip_config->high_time); + snprintf(msg_addr, sizeof(msg_addr), "msgn,%4dKHz", spi_speed); +#else + snprintf(msg_addr, sizeof(msg_addr), "msgn"); +#endif + + /* t_rec[0] = sched_clock(); */ + + spi_rec_time(msg_addr); + /* t_rec[1] = sched_clock(); */ + /* pr_alert("msgs rec consume time%lld", t_rec[1] - t_rec[0]); */ + + SPI_DBG("start transfer message:0x%p\n", msg); + ms->cur_transfer = list_entry(msg->transfers.next, struct spi_transfer, transfer_list); +#if 0 + /* clock and gpio set */ + spi_gpio_set(ms); + enable_clk(); + t_rec[0] = sched_clock(); + spi_rec_time("clke"); + t_rec[1] = sched_clock(); + pr_alert("clke rec consume time%lld", t_rec[1] - t_rec[0]); + reset_spi(ms); +#endif + mt_do_spi_setup(ms, chip_config); + mt_spi_next_xfer(ms, msg); + +} + +static int mt_spi_transfer(struct spi_device *spidev, struct spi_message *msg) +{ + struct spi_master *master; + struct mt_spi_t *ms; + struct spi_transfer *xfer; + struct mt_chip_conf *chip_config; + unsigned long flags; + char msg_addr[32]; + + master = spidev->master; + ms = spi_master_get_devdata(master); + + /* wake_lock(&ms->wk_lock); */ + SPI_DBG("enter,start add msg:0x%p\n", msg); + + if (unlikely(!msg)) { + dev_err(&spidev->dev, "msg is NULL pointer.\n"); + msg->status = -EINVAL; + goto out; + } + if (unlikely(list_empty(&msg->transfers))) { + dev_err(&spidev->dev, "the message is NULL.\n"); + msg->status = -EINVAL; + msg->actual_length = 0; + goto out; + } + + /* if device don't config chip, set default */ + if (master->setup(spidev)) { + dev_err(&spidev->dev, "set up error.\n"); + msg->status = -EINVAL; + msg->actual_length = 0; + goto out; + } + snprintf(msg_addr, sizeof(msg_addr), "msgs:%p", msg); + spi_rec_time(msg_addr); + + chip_config = (struct mt_chip_conf *)spidev->controller_data; + msg->state = chip_config; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (!((xfer->tx_buf || xfer->rx_buf) && xfer->len)) { + dev_err(&spidev->dev, "missing tx %p or rx %p buf, len%d\n", xfer->tx_buf, + xfer->rx_buf, xfer->len); + msg->status = -EINVAL; + goto out; + } + + /* + * DMA map early, for performance (empties dcache ASAP) and + * better fault reporting. + * + * NOTE that if dma_unmap_single() ever starts to do work on + * platforms supported by this driver, we would need to clean + * up mappings for previously-mapped transfers. + */ + if ((!msg->is_dma_mapped)) { + if (transfer_dma_mapping(ms, chip_config->com_mod, xfer) < 0) + return -ENOMEM; + } + } +#ifdef SPI_VERBOSE + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + SPI_INFO(&spidev->dev, "xfer %p: len %04u tx %p/%08x rx %p/%08x\n", + xfer, xfer->len, xfer->tx_buf, (unsigned int)xfer->tx_dma, + xfer->rx_buf, (unsigned int)xfer->rx_dma); + } +#endif + msg->status = -EINPROGRESS; + msg->actual_length = 0; + + spin_lock_irqsave(&ms->lock, flags); + list_add_tail(&msg->queue, &ms->queue); + SPI_DBG("add msg %p to queue\n", msg); + if (!ms->cur_transfer) { + wake_lock(&ms->wk_lock); + spi_gpio_set(ms); + + /* enable_clk(); */ + + enable_clk(ms); + + mt_spi_next_message(ms); + + } + spin_unlock_irqrestore(&ms->lock, flags); + + return 0; + +out: + return -1; + +} + +static irqreturn_t mt_spi_interrupt(int irq, void *dev_id) +{ + struct mt_spi_t *ms = (struct mt_spi_t *)dev_id; + struct spi_message *msg; + struct spi_transfer *xfer; + struct mt_chip_conf *chip_config; + + unsigned long flags; + u32 reg_val, cnt; + u8 mode, i; + + spi_rec_time("irqs"); + + spin_lock_irqsave(&ms->lock, flags); + xfer = ms->cur_transfer; + msg = list_entry(ms->queue.next, struct spi_message, queue); + + /* Clear interrupt status first by reading the register */ + reg_val = spi_readl(ms, SPI_STATUS0_REG); + SPI_DBG("xfer:0x%p interrupt status:%x\n", xfer, reg_val & 0x3); + /* pr_alert("xfer:0x%p interrupt status:%x\n", xfer, reg_val & 0x3); */ + + if (unlikely(!msg)) { + pr_err("msg in interrupt %d is NULL pointer.\n", reg_val & 0x3); + goto out; + } + if (unlikely(!xfer)) { + pr_err("xfer in interrupt %d is NULL pointer.\n", reg_val & 0x3); + goto out; + } + + chip_config = (struct mt_chip_conf *)msg->state; + mode = chip_config->com_mod; + /* clear the interrupt status bits by reading the register */ + /* reg_val = spi_readl(ms,SPI_STATUS0_REG); */ + /* SPI_DBG("xfer:0x%p interrupt status:%x\n", xfer,reg_val & 0x3); */ + /* pr_alert("xfer:0x%p interrupt status:%x\n", xfer,reg_val & 0x3); */ + if ((reg_val & 0x03) == 0) + goto out; + + if (!msg->is_dma_mapped) + transfer_dma_unmapping(ms, ms->cur_transfer); + + if (is_pause_mode(msg)) { + if (ms->running == INPROGRESS) + ms->running = PAUSED; + else + dev_err(&msg->spi->dev, "Wrong spi status.\n"); + } else + ms->running = IDLE; + + if (is_fifo_read(msg) && xfer->rx_buf) { + cnt = (xfer->len % 4) ? (xfer->len / 4 + 1) : (xfer->len / 4); + for (i = 0; i < cnt; i++) { + reg_val = spi_readl(ms, SPI_RX_DATA_REG); /* get the data from rx */ + SPI_INFO(&msg->spi->dev, "SPI_RX_DATA_REG:0x%x", reg_val); + *((u32 *) xfer->rx_buf + i) = reg_val; + } + } + + msg->actual_length += xfer->len; + + if (is_last_xfer(msg, xfer)) { + mt_spi_msg_done(ms, msg, 0); + } else { + ms->cur_transfer = ms->next_transfer; + mt_spi_next_xfer(ms, msg); + } + + spin_unlock_irqrestore(&ms->lock, flags); + return IRQ_HANDLED; +out: + spin_unlock_irqrestore(&ms->lock, flags); + SPI_DBG("return IRQ_NONE.\n"); + return IRQ_NONE; +} + +/* Write chip configuration to HW register */ +static int mt_do_spi_setup(struct mt_spi_t *ms, struct mt_chip_conf *chip_config) +{ + u32 reg_val; + +#ifdef SPI_VERBOSE + u32 speed; +#define SPI_MODULE_CLOCK 134300 + speed = SPI_MODULE_CLOCK / (chip_config->low_time + chip_config->high_time); + SPI_DBG("mode:%d, speed:%d KHz,CPOL%d,CPHA%d\n", chip_config->com_mod, speed, + chip_config->cpol, chip_config->cpha); +#endif + /* clear RST bits */ + /* reg_val = spi_readl ( ms, SPI_CMD_REG ); */ + /* reg_val &= ~ SPI_CMD_RST_MASK; */ + /* spi_writel ( ms, SPI_CMD_REG, reg_val ); */ + + /* set the timing */ + reg_val = spi_readl(ms, SPI_CFG0_REG); + reg_val &= ~(SPI_CFG0_CS_HOLD_MASK | SPI_CFG0_CS_SETUP_MASK); + reg_val |= ((chip_config->holdtime - 1) << SPI_CFG0_CS_HOLD_OFFSET); + reg_val |= ((chip_config->setuptime - 1) << SPI_CFG0_CS_SETUP_OFFSET); + spi_writel(ms, SPI_CFG0_REG, reg_val); + + reg_val = spi_readl(ms, SPI_CFG1_REG); + reg_val &= ~(SPI_CFG1_CS_IDLE_MASK); + reg_val |= ((chip_config->cs_idletime - 1) << SPI_CFG1_CS_IDLE_OFFSET); + + reg_val &= ~(SPI_CFG1_GET_TICK_DLY_MASK); + reg_val |= ((chip_config->tckdly) << SPI_CFG1_GET_TICK_DLY_OFFSET); + spi_writel(ms, SPI_CFG1_REG, reg_val); + + /* set the mlsbx and mlsbtx */ + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~(SPI_CMD_TX_ENDIAN_MASK | SPI_CMD_RX_ENDIAN_MASK); + reg_val &= ~(SPI_CMD_TXMSBF_MASK | SPI_CMD_RXMSBF_MASK); + reg_val &= ~(SPI_CMD_CPHA_MASK | SPI_CMD_CPOL_MASK); + reg_val |= (chip_config->tx_mlsb << SPI_CMD_TXMSBF_OFFSET); + reg_val |= (chip_config->rx_mlsb << SPI_CMD_RXMSBF_OFFSET); + reg_val |= (chip_config->tx_endian << SPI_CMD_TX_ENDIAN_OFFSET); + reg_val |= (chip_config->rx_endian << SPI_CMD_RX_ENDIAN_OFFSET); + reg_val |= (chip_config->sample_sel << SPI_CMD_SAMPLE_SEL_OFFSET); + reg_val |= (chip_config->cs_pol << SPI_CMD_CS_POL_OFFSET); + reg_val |= (chip_config->cpha << SPI_CMD_CPHA_OFFSET); + reg_val |= (chip_config->cpol << SPI_CMD_CPOL_OFFSET); + spi_writel(ms, SPI_CMD_REG, reg_val); + + /* set pause mode */ + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_PAUSE_EN_MASK; + reg_val &= ~SPI_CMD_PAUSE_IE_MASK; + /* if ( chip_config->com_mod == DMA_TRANSFER ) */ + reg_val |= (chip_config->pause << SPI_CMD_PAUSE_IE_OFFSET); + spi_writel(ms, SPI_CMD_REG, reg_val); + + /* set finish interrupt always enable */ + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_FINISH_IE_MASK; + /* reg_val |= ( chip_config->finish_intr << SPI_CMD_FINISH_IE_OFFSET ); */ + reg_val |= (1 << SPI_CMD_FINISH_IE_OFFSET); + + spi_writel(ms, SPI_CMD_REG, reg_val); + + /* set the communication of mode */ + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_TX_DMA_MASK; + reg_val &= ~SPI_CMD_RX_DMA_MASK; + spi_writel(ms, SPI_CMD_REG, reg_val); + + /* set deassert mode */ + reg_val = spi_readl(ms, SPI_CMD_REG); + reg_val &= ~SPI_CMD_DEASSERT_MASK; + reg_val |= (chip_config->deassert << SPI_CMD_DEASSERT_OFFSET); + spi_writel(ms, SPI_CMD_REG, reg_val); + +#if 0 +#if defined(GPIO_SPI_CS_PIN) && defined(GPIO_SPI_SCK_PIN) + &&defined(GPIO_SPI_MISO_PIN) && defined(GPIO_SPI_MOSI_PIN) + spi_writel(ms, SPI_PAD_SEL_REG, 0); /* for spi1 pad macro */ +#elif defined(GPIO_SPI2_CS_PIN) && defined(GPIO_SPI2_SCK_PIN) + &&defined(GPIO_SPI2_MISO_PIN) && defined(GPIO_SPI2_MOSI_PIN) + spi_writel(ms, SPI_PAD_SEL_REG, 1); /* for spi2 pad macro */ +#endif +#endif + spi_writel(ms, SPI_PAD_SEL_REG, ms->pad_macro); + + /* set the timing */ + reg_val = spi_readl(ms, SPI_CFG2_REG); + reg_val &= ~(SPI_CFG0_SCK_HIGH_MASK | SPI_CFG0_SCK_LOW_MASK); + reg_val |= ((chip_config->high_time - 1) << SPI_CFG0_SCK_HIGH_OFFSET); + reg_val |= ((chip_config->low_time - 1) << SPI_CFG0_SCK_LOW_OFFSET); + spi_writel(ms, SPI_CFG2_REG, reg_val); +#if 0 + /* set ultra high priority */ + reg_val &= ~SPI_ULTRA_HIGH_EN_MASK; + reg_val |= chip_config->ulthigh << SPI_ULTRA_HIGH_EN_OFFSET; + + reg_val &= ~SPI_ULTRA_HIGH_THRESH_MASK; + reg_val |= (chip_config->ulthgh_thrsh << SPI_ULTRA_HIGH_THRESH_OFFSET); + + spi_writel(ms, SPI_ULTRA_HIGH_REG, reg_val); +#endif + return 0; +} + +static int mt_spi_setup(struct spi_device *spidev) +{ + struct spi_master *master; + struct mt_spi_t *ms; + + struct mt_chip_conf *chip_config = NULL; + + if (!spidev) { + pr_err("spidev is null. error\n"); + /* dev_err(&spidev->dev, "spi device %s: error.\n", dev_name(&spidev->dev)); */ + return -EINVAL; + } + + master = spidev->master; + ms = spi_master_get_devdata(master); + + if (spidev->chip_select >= master->num_chipselect) { + dev_err(&spidev->dev, "spi device chip select excesses the number of master's chipselect number.\n"); + return -EINVAL; + } + + chip_config = (struct mt_chip_conf *)spidev->controller_data; + if (!chip_config) { + chip_config = kzalloc(sizeof(struct mt_chip_conf), GFP_KERNEL); + if (!chip_config) { + dev_err(&spidev->dev, "spidev %s: can not get enough memory.\n", dev_name(&spidev->dev)); + return -ENOMEM; + } + SPI_DBG("device %s: set default at chip's runtime state\n", dev_name(&spidev->dev)); + + chip_config->setuptime = 3; + chip_config->holdtime = 3; + chip_config->high_time = 10; + chip_config->low_time = 10; + chip_config->cs_idletime = 2; + chip_config->ulthgh_thrsh = 0; + + chip_config->cpol = 0; + chip_config->cpha = 1; + + chip_config->rx_mlsb = 1; + chip_config->tx_mlsb = 1; + + chip_config->tx_endian = 0; + chip_config->rx_endian = 0; + + chip_config->com_mod = DMA_TRANSFER; + chip_config->pause = 0; + chip_config->finish_intr = 1; + chip_config->deassert = 0; + chip_config->ulthigh = 0; + chip_config->tckdly = 0; + + spidev->controller_data = chip_config; + } + + SPI_INFO(&spidev->dev, "set up chip config,mode:%d\n", chip_config->com_mod); + + /* #ifdef SPI_REC_DEBUG */ + /* spi_speed = 134300/(chip_config->low_time + chip_config->high_time); */ + /* #endif */ + /* check chip configuration valid */ + + ms->config = chip_config; + if (!((chip_config->pause == PAUSE_MODE_ENABLE) + || (chip_config->pause == PAUSE_MODE_DISABLE)) || !((chip_config->cpol == SPI_CPOL_0) + || (chip_config->cpol == + SPI_CPOL_1)) + || !((chip_config->cpha == SPI_CPHA_0) || (chip_config->cpha == SPI_CPHA_1)) + || !((chip_config->tx_mlsb == SPI_LSB) || (chip_config->tx_mlsb == SPI_MSB)) + || !((chip_config->com_mod == FIFO_TRANSFER) || (chip_config->com_mod == DMA_TRANSFER) + || (chip_config->com_mod == OTHER1) || (chip_config->com_mod == OTHER2))) { + return -EINVAL; + } + return 0; +} + +static void mt_spi_cleanup(struct spi_device *spidev) +{ + struct spi_master *master; + struct mt_spi_t *ms; + + master = spidev->master; + ms = spi_master_get_devdata(master); + + SPI_DBG("Calling mt_spi_cleanup.\n"); + + spidev->controller_data = NULL; + spidev->master = NULL; + +} + +static int __init mt_spi_probe(struct platform_device *pdev) +{ + int ret = 0; + int irq; + struct resource *res; + struct spi_master *master; + struct mt_spi_t *ms; +#ifdef CONFIG_OF + /*void __iomem *spi_base; + unsigned int pin[4]; + unsigned int pin_mode[4]; + unsigned int if_config = 1; + unsigned int i; */ +#endif + + master = spi_alloc_master(&pdev->dev, sizeof(struct mt_spi_t)); + if (!master) { + dev_err(&pdev->dev, "device %s: alloc spi master fail.\n", dev_name(&pdev->dev)); + /* goto out; */ + return -ENOMEM; + } + + ms = spi_master_get_devdata(master); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "get resource res NULL.\n"); + return -ENXIO; + } + ms->regs = devm_ioremap_resource(&pdev->dev, res); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "platform_get_irq error. get invalid irq\n"); + return irq; + } +#if 0 + if (!request_mem_region(res->start, resource_size(res), pdev->name)) { + dev_err(&pdev->dev, "SPI register memory region failed"); + return -ENOMEM; + } +#endif + +#ifdef CONFIG_OF +#if 0 + spi_base = of_iomap(pdev->dev.of_node, 0); + if (!spi_base) { + dev_err(&pdev->dev, "SPI iomap failed\n"); + return -ENODEV; + } + + irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (!irq) { + dev_err(&pdev->dev, "SPI get irq failed\n"); + return -ENODEV; + } +#endif + if (of_property_read_u32(pdev->dev.of_node, "cell-index", &pdev->id)) { + dev_err(&pdev->dev, "SPI get cell-index failed\n"); + return -ENODEV; + } +#if 0 + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; +#endif + pr_debug("SPI reg: 0x%p irq: %d id: %d\n", ms->regs, irq, pdev->id); + + if (pdev->dev.of_node) { +#if 0 + if (of_property_read_u32_index(pdev->dev.of_node, "spi-cs", 0, &pin[0]) || + of_property_read_u32_index(pdev->dev.of_node, "spi-clk", 0, &pin[1]) || + of_property_read_u32_index(pdev->dev.of_node, "spi-mo", 0, &pin[2]) || + of_property_read_u32_index(pdev->dev.of_node, "spi-mi", 0, &pin[3])) { + if_config = 0; + dev_err(&pdev->dev, + "SPI get DTS spi pin failed, using DCT tool setting as default config\n"); + } + + if (of_property_read_u32_index(pdev->dev.of_node, "spi-cs", 1, &pin_mode[0]) || + of_property_read_u32_index(pdev->dev.of_node, "spi-clk", 1, &pin_mode[1]) || + of_property_read_u32_index(pdev->dev.of_node, "spi-mo", 1, &pin_mode[2]) || + of_property_read_u32_index(pdev->dev.of_node, "spi-mi", 1, &pin_mode[3])) { + dev_err(&pdev->dev, + "SPI get DTS spi pin mode failed, using DCT tool setting as default config\n"); + } + + if (if_config == 1) { + for (i = 0; i < 4; i++) { +#ifndef CONFIG_MTK_FPGA + mt_set_gpio_out((pin[i] | 0x80000000), GPIO_OUT_ONE); + mt_set_gpio_mode((pin[i] | 0x80000000), pin_mode[i]); +#endif + } + } +#endif + + if (of_property_read_u32(pdev->dev.of_node, "spi-padmacro", &(ms->pad_macro))) { + dev_err(&pdev->dev, + "SPI get pad macro fail failed, using DCT defined SPI pin to set macro\n"); + return -ENODEV; + } +#if !defined(CONFIG_MTK_CLKMGR) + ms->clk_main = devm_clk_get(&pdev->dev, "main"); + if (IS_ERR(ms->clk_main)) { + dev_err(&pdev->dev, + "cannot get spi main clock or dma clock. main clk err : %ld .\n", + PTR_ERR(ms->clk_main)); + return PTR_ERR(ms->clk_main); + } +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + + } +#endif + + master->dev.of_node = pdev->dev.of_node; + /* hardware can only connect 1 slave.if you want to multiple, using gpio CS */ + master->num_chipselect = 2; + + master->mode_bits = (SPI_CPOL | SPI_CPHA); + master->bus_num = pdev->id; + master->setup = mt_spi_setup; + master->transfer = mt_spi_transfer; + master->cleanup = mt_spi_cleanup; + platform_set_drvdata(pdev, master); + + ms = spi_master_get_devdata(master); +#if 0 +#ifdef CONFIG_OF + ms->regs = spi_base; +#else + ms->regs = ioremap(res->start, resource_size(res)); +#endif +#endif + ms->pdev = pdev; + ms->irq = irq; + ms->running = IDLE; + ms->cur_transfer = NULL; + ms->next_transfer = NULL; + wake_lock_init(&ms->wk_lock, WAKE_LOCK_SUSPEND, "spi_wakelock"); + + spin_lock_init(&ms->lock); + INIT_LIST_HEAD(&ms->queue); + + SPI_INFO(&pdev->dev, "Controller at 0x%p (irq %d)\n", ms->regs, irq); +#ifdef CONFIG_OF + ret = request_irq(irq, mt_spi_interrupt, IRQF_TRIGGER_NONE, dev_name(&pdev->dev), ms); +#else + ret = request_irq(irq, mt_spi_interrupt, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), ms); +#endif + if (ret) { + dev_err(&pdev->dev, "registering interrupt handler fails.\n"); + /* goto out; */ + return ret; + } + + spi_master_set_devdata(master, ms); +#if !defined(CONFIG_MTK_CLKMGR) + /* + * prepare the clock source + */ + ret = clk_prepare(ms->clk_main); +#endif + /* + * enable clk before access spi register + */ + enable_clk(ms); + reset_spi(ms); + /* + * disable clk when finishing access spi register + */ + disable_clk(ms); + + ret = spi_register_master(master); + if (ret) { + dev_err(&pdev->dev, "spi_register_master fails.\n"); + goto out_free; + } else { + SPI_DBG("spi register master success.\n"); + /* reg_val = spi_readl ( ms, SPI_CMD_REG ); */ + /* reg_val &= SPI_CMD_RST_MASK; */ + /* SPI_DBG ( "SPI_CMD_RST bit is: %d\n", reg_val ); */ + return 0; + } + + pr_debug("SPI probe end\n"); +#if 0 +#ifdef SPI_TRUSTONIC_TEE_SUPPORT + /* + * because of TEE spi usage, always open spi clock. + */ + enable_clk(); +#endif +#endif + +out_free: + free_irq(irq, ms); +/*out:*/ + spi_master_put(master); + return ret; +} + +static int __exit mt_spi_remove(struct platform_device *pdev) +{ + struct mt_spi_t *ms; + struct spi_message *msg; + struct spi_master *master = platform_get_drvdata(pdev); + + if (!master) { + dev_err(&pdev->dev, "master %s: is invalid.\n", dev_name(&pdev->dev)); + return -EINVAL; + } + ms = spi_master_get_devdata(master); + + list_for_each_entry(msg, &ms->queue, queue) { + msg->status = -ESHUTDOWN; + msg->complete(msg->context); + } + ms->cur_transfer = NULL; + ms->running = IDLE; + + reset_spi(ms); + + free_irq(ms->irq, master); + spi_unregister_master(master); + return 0; +} + +#ifdef CONFIG_PM +static int mt_spi_suspend(struct platform_device *pdev, pm_message_t message) +{ + /* if interrupt is enabled, + * then wait for interrupt complete. */ + struct mt_spi_t *ms; + struct spi_master *master = platform_get_drvdata(pdev); + + ms = spi_master_get_devdata(master); + +#if !defined(CONFIG_MTK_CLKMGR) + /* + * unprepare the clock source + */ + clk_unprepare(ms->clk_main); +#endif + + return 0; +} + +static int mt_spi_resume(struct platform_device *pdev) +{ +#if !defined(CONFIG_MTK_CLKMGR) + int ret; +#endif + struct mt_spi_t *ms; + struct spi_master *master = platform_get_drvdata(pdev); + + ms = spi_master_get_devdata(master); + +#if !defined(CONFIG_MTK_CLKMGR) + /* + * prepare the clock source + */ + ret = clk_prepare(ms->clk_main); +#endif + + return 0; +} +#else +#define mt_spi_suspend NULL +#define mt_spi_resume NULL +#endif + +static const struct of_device_id mt_spi_of_match[] = { + {.compatible = "mediatek,mt6755-spi",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, mt_spi_of_match); + +struct platform_driver mt_spi_driver = { + .driver = { + .name = "mt-spi", + .owner = THIS_MODULE, + .of_match_table = mt_spi_of_match, + }, + .probe = mt_spi_probe, + .suspend = mt_spi_suspend, + .resume = mt_spi_resume, + .remove = __exit_p(mt_spi_remove), +}; + +static int __init mt_spi_init(void) +{ + int ret; + + pr_debug("SPI init!\n"); + ret = platform_driver_register(&mt_spi_driver); + return ret; +} + +static void __exit mt_spi_exit(void) +{ + platform_driver_unregister(&mt_spi_driver); +} +module_init(mt_spi_init); +module_exit(mt_spi_exit); + +MODULE_DESCRIPTION("mt SPI Controller driver"); +MODULE_AUTHOR("Ranran Lu "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform: mt_spi"); diff --git a/drivers/watchdog/mediatek/wdt/mt6755/Makefile b/drivers/watchdog/mediatek/wdt/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b6acb5062c482c185ce251f38ededd71144b8091 --- /dev/null +++ b/drivers/watchdog/mediatek/wdt/mt6755/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +ccflags-y += -I$(srctree)/drivers/watchdog/mediatek/include +#obj-$(CONFIG_LOCAL_WDT) += mpcore_wdt.o +obj-y += mtk_wdt.o diff --git a/drivers/watchdog/mediatek/wdt/mt6755/mt_wdt.h b/drivers/watchdog/mediatek/wdt/mt6755/mt_wdt.h new file mode 100644 index 0000000000000000000000000000000000000000..ca6d9298a00df7ac433bca0793b82a232c009bed --- /dev/null +++ b/drivers/watchdog/mediatek/wdt/mt6755/mt_wdt.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __WDT_HW_H__ +#define __WDT_HW_H__ + +#define MTK_WDT_BASE toprgu_base + +#define MTK_WDT_MODE (MTK_WDT_BASE+0x0000) +#define MTK_WDT_LENGTH (MTK_WDT_BASE+0x0004) +#define MTK_WDT_RESTART (MTK_WDT_BASE+0x0008) +#define MTK_WDT_STATUS (MTK_WDT_BASE+0x000C) +#define MTK_WDT_INTERVAL (MTK_WDT_BASE+0x0010) +#define MTK_WDT_SWRST (MTK_WDT_BASE+0x0014) +#define MTK_WDT_SWSYSRST (MTK_WDT_BASE+0x0018) +#define MTK_WDT_NONRST_REG (MTK_WDT_BASE+0x0020) +#define MTK_WDT_NONRST_REG2 (MTK_WDT_BASE+0x0024) +#define MTK_WDT_REQ_MODE (MTK_WDT_BASE+0x0030) +#define MTK_WDT_REQ_IRQ_EN (MTK_WDT_BASE+0x0034) +#define MTK_WDT_EXT_REQ_CON (MTK_WDT_BASE+0x0038) +#define MTK_WDT_DRAMC_CTL (MTK_WDT_BASE+0x0040) + +#define MTK_WDT_RSTDEG_EN1 (MTK_WDT_BASE+0x0080) +#define MTK_WDT_RSTDEG_EN2 (MTK_WDT_BASE+0x0084) +#define MTK_WDT_SYSDBG_DEG_EN1 (MTK_WDT_BASE+0x0088) +#define MTK_WDT_SYSDBG_DEG_EN2 (MTK_WDT_BASE+0x008C) + + +/*WDT_MODE*/ +#define MTK_WDT_MODE_KEYMASK (0xff00) +#define MTK_WDT_MODE_KEY (0x22000000) + +#define MTK_WDT_MODE_DDR_RESERVE (0x0080) +#define MTK_WDT_MODE_DUAL_MODE (0x0040) +#define MTK_WDT_MODE_IN_DIS (0x0020) /* Reserved */ +#define MTK_WDT_MODE_AUTO_RESTART (0x0010) /* Reserved */ +#define MTK_WDT_MODE_IRQ (0x0008) +#define MTK_WDT_MODE_EXTEN (0x0004) +#define MTK_WDT_MODE_EXT_POL (0x0002) +#define MTK_WDT_MODE_ENABLE (0x0001) + + +/*WDT_LENGTH*/ +#define MTK_WDT_LENGTH_TIME_OUT (0xffe0) +#define MTK_WDT_LENGTH_KEYMASK (0x001f) +#define MTK_WDT_LENGTH_KEY (0x0008) + +/*WDT_RESTART*/ +#define MTK_WDT_RESTART_KEY (0x1971) + +/*WDT_STATUS*/ +#define MTK_WDT_STATUS_HWWDT_RST (0x80000000) +#define MTK_WDT_STATUS_SWWDT_RST (0x40000000) +#define MTK_WDT_STATUS_IRQWDT_RST (0x20000000) +#define MTK_WDT_STATUS_DEBUGWDT_RST (0x00080000) +#define MTK_WDT_STATUS_SPMWDT_RST (0x0002) +#define MTK_WDT_STATUS_SPM_THERMAL_RST (0x0001) +#define MTK_WDT_STATUS_THERMAL_DIRECT_RST (1<<18) +#define MTK_WDT_STATUS_SECURITY_RST (1<<28) + +/*WDT_INTERVAL*/ +#define MTK_WDT_INTERVAL_MASK (0x0fff) + +/*WDT_SWRST*/ +#define MTK_WDT_SWRST_KEY (0x1209) + +/*WDT_SWSYSRST*/ +#define MTK_WDT_SWSYS_RST_PWRAP_SPI_CTL_RST (0x0800) +#define MTK_WDT_SWSYS_RST_APMIXED_RST (0x0400) +#define MTK_WDT_SWSYS_RST_MD_LITE_RST (0x0200) +#define MTK_WDT_SWSYS_RST_INFRA_AO_RST (0x0100) +#define MTK_WDT_SWSYS_RST_MD_RST (0x0080) +#define MTK_WDT_SWSYS_RST_DDRPHY_RST (0x0040) +#define MTK_WDT_SWSYS_RST_IMG_RST (0x0020) +#define MTK_WDT_SWSYS_RST_VDEC_RST (0x0010) +#define MTK_WDT_SWSYS_RST_VENC_RST (0x0008) +#define MTK_WDT_SWSYS_RST_MFG_RST (0x0004) +#define MTK_WDT_SWSYS_RST_DISP_RST (0x0002) +#define MTK_WDT_SWSYS_RST_INFRA_RST (0x0001) + + +/* #define MTK_WDT_SWSYS_RST_KEY (0x1500) */ +#define MTK_WDT_SWSYS_RST_KEY (0x88000000) + +/*MTK_WDT_REQ_IRQ*/ +#define MTK_WDT_REQ_IRQ_KEY (0x44000000) +#define MTK_WDT_REQ_IRQ_DEBUG_EN (0x80000) +#define MTK_WDT_REQ_IRQ_SPM_THERMAL_EN (0x0001) +#define MTK_WDT_REQ_IRQ_SPM_SCPSYS_EN (0x0002) +#define MTK_WDT_REQ_IRQ_EINT_EN (1<<2) +#define MTK_WDT_REQ_IRQ_SYSRST_EN (1<<3) +#define MTK_WDT_REQ_IRQ_THERMAL_EN (1<<18) + + +/*MTK_WDT_REQ_MODE*/ +#define MTK_WDT_REQ_MODE_KEY (0x33000000) +#define MTK_WDT_REQ_MODE_DEBUG_EN (0x80000) +#define MTK_WDT_REQ_MODE_SPM_THERMAL (0x0001) +#define MTK_WDT_REQ_MODE_SPM_SCPSYS (0x0002) +#define MTK_WDT_REQ_MODE_EINT (1<<2) +#define MTK_WDT_REQ_MODE_SYSRST (1<<3) +#define MTK_WDT_REQ_MODE_THERMAL (1<<18) + +/*MTK_WDT_RSTDEG_EN*/ +#define MTK_WDT_RSTDEG_EN1_KEY (0xa357) +#define MTK_WDT_RSTDEG_EN2_KEY (0x67d2) + +/*MTK_WDT_SYSDBG_DEG_EN*/ +#define MTK_WDT_SYSDBG_DEG_EN1_KEY (0x1b2a) +#define MTK_WDT_SYSDBG_DEG_EN2_KEY (0x4f59) + + +#endif /*__WDT_HW_H__*/ diff --git a/drivers/watchdog/mediatek/wdt/mt6755/mtk_wdt.c b/drivers/watchdog/mediatek/wdt/mt6755/mtk_wdt.c new file mode 100644 index 0000000000000000000000000000000000000000..9cb46b31d550378731f5c0008e3e747f49d23156 --- /dev/null +++ b/drivers/watchdog/mediatek/wdt/mt6755/mtk_wdt.c @@ -0,0 +1,1005 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 /* For init/exit macros */ +#include /* For MODULE_ marcros */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "mt_wdt.h" +#include + +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include +#include +#include + +#include +#ifdef CONFIG_OF +void __iomem *toprgu_base = 0; +int wdt_irq_id = 0; +int ext_debugkey_io = -1; + +static const struct of_device_id rgu_of_match[] = { + {.compatible = "mediatek,toprgu",}, + {}, +}; +#endif + +/**--------------------------------------------------------------------- + * Sub feature switch region + *---------------------------------------------------------------------- + */ +#define NO_DEBUG 1 + +/*---------------------------------------------------------------------- + * IRQ ID + *--------------------------------------------------------------------*/ +#ifdef CONFIG_OF +#define AP_RGU_WDT_IRQ_ID wdt_irq_id +#else +#define AP_RGU_WDT_IRQ_ID WDT_IRQ_BIT_ID +#endif + +/* + * internal variables + */ +/* static char expect_close; // Not use */ +/* static spinlock_t rgu_reg_operation_spinlock = SPIN_LOCK_UNLOCKED; */ +static DEFINE_SPINLOCK(rgu_reg_operation_spinlock); +#ifndef CONFIG_KICK_SPM_WDT +static unsigned int timeout; +#endif +static bool rgu_wdt_intr_has_trigger; /* For test use */ +static int g_last_time_time_out_value; +static int g_wdt_enable = 1; +#ifdef CONFIG_KICK_SPM_WDT +#include +static void spm_wdt_init(void); + +#endif + +#ifndef __USING_DUMMY_WDT_DRV__ /* FPGA will set this flag */ +/* + this function set the timeout value. + value: second +*/ +void mtk_wdt_set_time_out_value(unsigned int value) +{ + /* + * TimeOut = BitField 15:5 + * Key = BitField 4:0 = 0x08 + */ + spin_lock(&rgu_reg_operation_spinlock); + +#ifdef CONFIG_KICK_SPM_WDT + spm_wdt_set_timeout(value); +#else + + /* 1 tick means 512 * T32K -> 1s = T32/512 tick = 64 */ + /* --> value * (1<<6) */ + timeout = (unsigned int)(value * (1 << 6)); + timeout = timeout << 5; + mt_reg_sync_writel((timeout | MTK_WDT_LENGTH_KEY), MTK_WDT_LENGTH); +#endif + spin_unlock(&rgu_reg_operation_spinlock); +} + +/* + watchdog mode: + debug_en: debug module reset enable. + irq: generate interrupt instead of reset + ext_en: output reset signal to outside + ext_pol: polarity of external reset signal + wdt_en: enable watch dog timer +*/ +void mtk_wdt_mode_config(bool dual_mode_en, bool irq, bool ext_en, bool ext_pol, bool wdt_en) +{ +#ifndef CONFIG_KICK_SPM_WDT + unsigned int tmp; +#endif + spin_lock(&rgu_reg_operation_spinlock); +#ifdef CONFIG_KICK_SPM_WDT + if (wdt_en == TRUE) { + pr_debug("wdt enable spm timer.....\n"); + spm_wdt_enable_timer(); + } else { + pr_debug("wdt disable spm timer.....\n"); + spm_wdt_disable_timer(); + } +#else + /* pr_debug(" mtk_wdt_mode_config mode value=%x,pid=%d\n",DRV_Reg32(MTK_WDT_MODE),current->pid); */ + tmp = __raw_readl(MTK_WDT_MODE); + tmp |= MTK_WDT_MODE_KEY; + + /* Bit 0 : Whether enable watchdog or not */ + if (wdt_en == TRUE) + tmp |= MTK_WDT_MODE_ENABLE; + else + tmp &= ~MTK_WDT_MODE_ENABLE; + + /* Bit 1 : Configure extern reset signal polarity. */ + if (ext_pol == TRUE) + tmp |= MTK_WDT_MODE_EXT_POL; + else + tmp &= ~MTK_WDT_MODE_EXT_POL; + + /* Bit 2 : Whether enable external reset signal */ + if (ext_en == TRUE) + tmp |= MTK_WDT_MODE_EXTEN; + else + tmp &= ~MTK_WDT_MODE_EXTEN; + + /* Bit 3 : Whether generating interrupt instead of reset signal */ + if (irq == TRUE) + tmp |= MTK_WDT_MODE_IRQ; + else + tmp &= ~MTK_WDT_MODE_IRQ; + + /* Bit 6 : Whether enable debug module reset */ + if (dual_mode_en == TRUE) + tmp |= MTK_WDT_MODE_DUAL_MODE; + else + tmp &= ~MTK_WDT_MODE_DUAL_MODE; + + /* Bit 4: WDT_Auto_restart, this is a reserved bit, we use it as bypass powerkey flag. */ + /* Because HW reboot always need reboot to kernel, we set it always. */ + tmp |= MTK_WDT_MODE_AUTO_RESTART; + + mt_reg_sync_writel(tmp, MTK_WDT_MODE); + /* dual_mode(1); //always dual mode */ + /* mdelay(100); */ + /* pr_debug(" mtk_wdt_mode_config mode value=%x, tmp:%x,pid=%d\n", __raw_readl(MTK_WDT_MODE), + tmp, current->pid); */ +#endif + spin_unlock(&rgu_reg_operation_spinlock); +} + +/* EXPORT_SYMBOL(mtk_wdt_mode_config); */ + +int mtk_wdt_enable(enum wk_wdt_en en) +{ + unsigned int tmp = 0; + + spin_lock(&rgu_reg_operation_spinlock); +#ifdef CONFIG_KICK_SPM_WDT + if (WK_WDT_EN == en) { + spm_wdt_enable_timer(); + pr_debug("wdt enable spm timer\n"); + + tmp = __raw_readl(MTK_WDT_REQ_MODE); + tmp |= MTK_WDT_REQ_MODE_KEY; + tmp |= (MTK_WDT_REQ_MODE_SPM_SCPSYS); + mt_reg_sync_writel(tmp, MTK_WDT_REQ_MODE); + g_wdt_enable = 1; + } + if (WK_WDT_DIS == en) { + spm_wdt_disable_timer(); + pr_debug("wdt disable spm timer\n "); + tmp = __raw_readl(MTK_WDT_REQ_MODE); + tmp |= MTK_WDT_REQ_MODE_KEY; + tmp &= ~(MTK_WDT_REQ_MODE_SPM_SCPSYS); + mt_reg_sync_writel(tmp, MTK_WDT_REQ_MODE); + g_wdt_enable = 0; + } +#else + + tmp = __raw_readl(MTK_WDT_MODE); + + tmp |= MTK_WDT_MODE_KEY; + if (WK_WDT_EN == en) { + tmp |= MTK_WDT_MODE_ENABLE; + g_wdt_enable = 1; + } + if (WK_WDT_DIS == en) { + tmp &= ~MTK_WDT_MODE_ENABLE; + g_wdt_enable = 0; + } + pr_debug("mtk_wdt_enable value=%x,pid=%d\n", tmp, current->pid); + mt_reg_sync_writel(tmp, MTK_WDT_MODE); +#endif + spin_unlock(&rgu_reg_operation_spinlock); + return 0; +} + +int mtk_wdt_confirm_hwreboot(void) +{ + /* aee need confirm wd can hw reboot */ + /* pr_debug("mtk_wdt_probe : Initialize to dual mode\n"); */ + mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); + return 0; +} + + +void mtk_wdt_restart(enum wd_restart_type type) +{ + +#ifdef CONFIG_OF + struct device_node *np_rgu; + + np_rgu = of_find_compatible_node(NULL, NULL, rgu_of_match[0].compatible); + + if (!toprgu_base) { + toprgu_base = of_iomap(np_rgu, 0); + if (!toprgu_base) + pr_debug("RGU iomap failed\n"); + /* pr_debug("RGU base: 0x%p RGU irq: %d\n", toprgu_base, wdt_irq_id); */ + } +#endif + + /* pr_debug("WDT:[mtk_wdt_restart] type =%d, pid=%d\n",type,current->pid); */ + + if (type == WD_TYPE_NORMAL) { + /* printk("WDT:ext restart\n" ); */ + spin_lock(&rgu_reg_operation_spinlock); +#ifdef CONFIG_KICK_SPM_WDT + spm_wdt_restart_timer(); +#else + mt_reg_sync_writel(MTK_WDT_RESTART_KEY, MTK_WDT_RESTART); +#endif + spin_unlock(&rgu_reg_operation_spinlock); + } else if (type == WD_TYPE_NOLOCK) { +#ifdef CONFIG_KICK_SPM_WDT + spm_wdt_restart_timer_nolock(); +#else + mt_reg_sync_writel(MTK_WDT_RESTART_KEY, MTK_WDT_RESTART); +#endif + } else + pr_debug("WDT:[mtk_wdt_restart] type=%d error pid =%d\n", type, current->pid); +} + +void wdt_dump_reg(void) +{ + pr_alert("****************dump wdt reg start*************\n"); + pr_alert("MTK_WDT_MODE:0x%x\n", __raw_readl(MTK_WDT_MODE)); + pr_alert("MTK_WDT_LENGTH:0x%x\n", __raw_readl(MTK_WDT_LENGTH)); + pr_alert("MTK_WDT_RESTART:0x%x\n", __raw_readl(MTK_WDT_RESTART)); + pr_alert("MTK_WDT_STATUS:0x%x\n", __raw_readl(MTK_WDT_STATUS)); + pr_alert("MTK_WDT_INTERVAL:0x%x\n", __raw_readl(MTK_WDT_INTERVAL)); + pr_alert("MTK_WDT_SWRST:0x%x\n", __raw_readl(MTK_WDT_SWRST)); + pr_alert("MTK_WDT_NONRST_REG:0x%x\n", __raw_readl(MTK_WDT_NONRST_REG)); + pr_alert("MTK_WDT_NONRST_REG2:0x%x\n", __raw_readl(MTK_WDT_NONRST_REG2)); + pr_alert("MTK_WDT_REQ_MODE:0x%x\n", __raw_readl(MTK_WDT_REQ_MODE)); + pr_alert("MTK_WDT_REQ_IRQ_EN:0x%x\n", __raw_readl(MTK_WDT_REQ_IRQ_EN)); + pr_alert("MTK_WDT_DRAMC_CTL:0x%x\n", __raw_readl(MTK_WDT_DRAMC_CTL)); + pr_alert("****************dump wdt reg end*************\n"); + +} + +void aee_wdt_dump_reg(void) +{ +/* + aee_wdt_printf("***dump wdt reg start***\n"); + aee_wdt_printf("MODE:0x%x\n", __raw_readl(MTK_WDT_MODE)); + aee_wdt_printf("LENGTH:0x%x\n", __raw_readl(MTK_WDT_LENGTH)); + aee_wdt_printf("RESTART:0x%x\n", __raw_readl(MTK_WDT_RESTART)); + aee_wdt_printf("STATUS:0x%x\n", __raw_readl(MTK_WDT_STATUS)); + aee_wdt_printf("INTERVAL:0x%x\n", __raw_readl(MTK_WDT_INTERVAL)); + aee_wdt_printf("SWRST:0x%x\n", __raw_readl(MTK_WDT_SWRST)); + aee_wdt_printf("NONRST_REG:0x%x\n", __raw_readl(MTK_WDT_NONRST_REG)); + aee_wdt_printf("NONRST_REG2:0x%x\n", __raw_readl(MTK_WDT_NONRST_REG2)); + aee_wdt_printf("REQ_MODE:0x%x\n", __raw_readl(MTK_WDT_REQ_MODE)); + aee_wdt_printf("REQ_IRQ_EN:0x%x\n", __raw_readl(MTK_WDT_REQ_IRQ_EN)); + aee_wdt_printf("DRAMC_CTL:0x%x\n", __raw_readl(MTK_WDT_DRAMC_CTL)); + aee_wdt_printf("***dump wdt reg end***\n"); +*/ +} + +void wdt_arch_reset(char mode) +{ + unsigned int wdt_mode_val; +#ifdef CONFIG_OF + struct device_node *np_rgu; +#endif + pr_debug("wdt_arch_reset called@Kernel mode =%c\n", mode); +#ifdef CONFIG_OF + np_rgu = of_find_compatible_node(NULL, NULL, rgu_of_match[0].compatible); + + if (!toprgu_base) { + toprgu_base = of_iomap(np_rgu, 0); + if (!toprgu_base) + pr_err("RGU iomap failed\n"); + pr_debug("RGU base: 0x%p RGU irq: %d\n", toprgu_base, wdt_irq_id); + } +#endif + spin_lock(&rgu_reg_operation_spinlock); + /* Watchdog Rest */ + mt_reg_sync_writel(MTK_WDT_RESTART_KEY, MTK_WDT_RESTART); + wdt_mode_val = __raw_readl(MTK_WDT_MODE); + pr_debug("wdt_arch_reset called MTK_WDT_MODE =%x\n", wdt_mode_val); + /* clear autorestart bit: autoretart: 1, bypass power key, 0: not bypass power key */ + wdt_mode_val &= (~MTK_WDT_MODE_AUTO_RESTART); + /* make sure WDT mode is hw reboot mode, can not config isr mode */ + wdt_mode_val &= (~(MTK_WDT_MODE_IRQ | MTK_WDT_MODE_ENABLE | MTK_WDT_MODE_DUAL_MODE)); + if (mode) + /* mode != 0 means by pass power key reboot, We using auto_restart bit as by pass power key flag */ + wdt_mode_val = + wdt_mode_val | (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN | + MTK_WDT_MODE_AUTO_RESTART); + else + wdt_mode_val = wdt_mode_val | (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN); + + mt_reg_sync_writel(wdt_mode_val, MTK_WDT_MODE); + pr_debug("wdt_arch_reset called end MTK_WDT_MODE =%x\n", wdt_mode_val); + udelay(100); + mt_reg_sync_writel(MTK_WDT_SWRST_KEY, MTK_WDT_SWRST); + pr_debug("wdt_arch_reset: SW_reset happen\n"); + spin_unlock(&rgu_reg_operation_spinlock); + + while (1) { + wdt_dump_reg(); + pr_err("wdt_arch_reset error\n"); + } + +} + +int mtk_rgu_dram_reserved(int enable) +{ + unsigned int tmp; + + if (1 == enable) { + /* enable ddr reserved mode */ + tmp = __raw_readl(MTK_WDT_MODE); + tmp |= (MTK_WDT_MODE_DDR_RESERVE | MTK_WDT_MODE_KEY); + mt_reg_sync_writel(tmp, MTK_WDT_MODE); + } else if (0 == enable) { + /* disable ddr reserved mode, set reset mode, + disable watchdog output reset signal */ + tmp = __raw_readl(MTK_WDT_MODE); + tmp &= (~MTK_WDT_MODE_DDR_RESERVE); + tmp |= MTK_WDT_MODE_KEY; + mt_reg_sync_writel(tmp, MTK_WDT_MODE); + } + + pr_debug("mtk_rgu_dram_reserved:MTK_WDT_MODE(0x%x)\n", __raw_readl(MTK_WDT_MODE)); + return 0; +} + +int mtk_wdt_swsysret_config(int bit, int set_value) +{ + unsigned int wdt_sys_val; + + spin_lock(&rgu_reg_operation_spinlock); + wdt_sys_val = __raw_readl(MTK_WDT_SWSYSRST); + pr_debug("fwq2 before set wdt_sys_val =%x\n", wdt_sys_val); + wdt_sys_val |= MTK_WDT_SWSYS_RST_KEY; + switch (bit) { + case MTK_WDT_SWSYS_RST_MD_RST: + if (1 == set_value) + wdt_sys_val |= MTK_WDT_SWSYS_RST_MD_RST; + if (0 == set_value) + wdt_sys_val &= ~MTK_WDT_SWSYS_RST_MD_RST; + break; + case MTK_WDT_SWSYS_RST_MD_LITE_RST: + if (1 == set_value) + wdt_sys_val |= MTK_WDT_SWSYS_RST_MD_LITE_RST; + if (0 == set_value) + wdt_sys_val &= ~MTK_WDT_SWSYS_RST_MD_LITE_RST; + break; + } + mt_reg_sync_writel(wdt_sys_val, MTK_WDT_SWSYSRST); + spin_unlock(&rgu_reg_operation_spinlock); + + mdelay(10); + pr_debug("after set wdt_sys_val =%x,wdt_sys_val=%x\n", __raw_readl(MTK_WDT_SWSYSRST), + wdt_sys_val); + return 0; +} + +int mtk_wdt_request_en_set(int mark_bit, WD_REQ_CTL en) +{ + int res = 0; + unsigned int tmp, ext_req_con; + struct device_node *np_rgu; + + if (!toprgu_base) { + np_rgu = of_find_compatible_node(NULL, NULL, rgu_of_match[0].compatible); + toprgu_base = of_iomap(np_rgu, 0); + if (!toprgu_base) + pr_err("RGU iomap failed\n"); + pr_debug("RGU base: 0x%p RGU irq: %d\n", toprgu_base, wdt_irq_id); + } + + spin_lock(&rgu_reg_operation_spinlock); + tmp = __raw_readl(MTK_WDT_REQ_MODE); + tmp |= MTK_WDT_REQ_MODE_KEY; + + if (MTK_WDT_REQ_MODE_SPM_SCPSYS == mark_bit) { + if (WD_REQ_EN == en) + tmp |= (MTK_WDT_REQ_MODE_SPM_SCPSYS); + if (WD_REQ_DIS == en) + tmp &= ~(MTK_WDT_REQ_MODE_SPM_SCPSYS); + } else if (MTK_WDT_REQ_MODE_SPM_THERMAL == mark_bit) { + if (WD_REQ_EN == en) + tmp |= (MTK_WDT_REQ_MODE_SPM_THERMAL); + if (WD_REQ_DIS == en) + tmp &= ~(MTK_WDT_REQ_MODE_SPM_THERMAL); + } else if (MTK_WDT_REQ_MODE_EINT == mark_bit) { + if (WD_REQ_EN == en) { + if (ext_debugkey_io != -1) { + ext_req_con = (ext_debugkey_io << 4) | 0x01; + mt_reg_sync_writel(ext_req_con, MTK_WDT_EXT_REQ_CON); + tmp |= (MTK_WDT_REQ_MODE_EINT); + } else { + tmp &= ~(MTK_WDT_REQ_MODE_EINT); + res = -1; + } + } + if (WD_REQ_DIS == en) + tmp &= ~(MTK_WDT_REQ_MODE_EINT); + } else if (MTK_WDT_REQ_MODE_SYSRST == mark_bit) { + /* + if (WD_REQ_EN == en) { + DRV_WriteReg32(MTK_WDT_SYSDBG_DEG_EN1, MTK_WDT_SYSDBG_DEG_EN1_KEY); + DRV_WriteReg32(MTK_WDT_SYSDBG_DEG_EN2, MTK_WDT_SYSDBG_DEG_EN2_KEY); + tmp |= (MTK_WDT_REQ_MODE_SYSRST); + } + if (WD_REQ_DIS == en) + tmp &= ~(MTK_WDT_REQ_MODE_SYSRST); + */ + } else if (MTK_WDT_REQ_MODE_THERMAL == mark_bit) { + if (WD_REQ_EN == en) + tmp |= (MTK_WDT_REQ_MODE_THERMAL); + if (WD_REQ_DIS == en) + tmp &= ~(MTK_WDT_REQ_MODE_THERMAL); + } else + res = -1; + + mt_reg_sync_writel(tmp, MTK_WDT_REQ_MODE); + spin_unlock(&rgu_reg_operation_spinlock); + return res; +} + +int mtk_wdt_request_mode_set(int mark_bit, WD_REQ_MODE mode) +{ + int res = 0; + unsigned int tmp; + struct device_node *np_rgu; + + if (!toprgu_base) { + np_rgu = of_find_compatible_node(NULL, NULL, rgu_of_match[0].compatible); + toprgu_base = of_iomap(np_rgu, 0); + if (!toprgu_base) + pr_err("RGU iomap failed\n"); + pr_debug("RGU base: 0x%p RGU irq: %d\n", toprgu_base, wdt_irq_id); + } + + spin_lock(&rgu_reg_operation_spinlock); + tmp = __raw_readl(MTK_WDT_REQ_IRQ_EN); + tmp |= MTK_WDT_REQ_IRQ_KEY; + + if (MTK_WDT_REQ_MODE_SPM_SCPSYS == mark_bit) { + if (WD_REQ_IRQ_MODE == mode) + tmp |= (MTK_WDT_REQ_IRQ_SPM_SCPSYS_EN); + if (WD_REQ_RST_MODE == mode) + tmp &= ~(MTK_WDT_REQ_IRQ_SPM_SCPSYS_EN); + } else if (MTK_WDT_REQ_MODE_SPM_THERMAL == mark_bit) { + if (WD_REQ_IRQ_MODE == mode) + tmp |= (MTK_WDT_REQ_IRQ_SPM_THERMAL_EN); + if (WD_REQ_RST_MODE == mode) + tmp &= ~(MTK_WDT_REQ_IRQ_SPM_THERMAL_EN); + } else if (MTK_WDT_REQ_MODE_EINT == mark_bit) { + if (WD_REQ_IRQ_MODE == mode) + tmp |= (MTK_WDT_REQ_IRQ_EINT_EN); + if (WD_REQ_RST_MODE == mode) + tmp &= ~(MTK_WDT_REQ_IRQ_EINT_EN); + } else if (MTK_WDT_REQ_MODE_SYSRST == mark_bit) { + /* + if (WD_REQ_IRQ_MODE == mode) + tmp |= (MTK_WDT_REQ_IRQ_SYSRST_EN); + if (WD_REQ_RST_MODE == mode) + tmp &= ~(MTK_WDT_REQ_IRQ_SYSRST_EN); + */ + } else if (MTK_WDT_REQ_MODE_THERMAL == mark_bit) { + if (WD_REQ_IRQ_MODE == mode) + tmp |= (MTK_WDT_REQ_IRQ_THERMAL_EN); + if (WD_REQ_RST_MODE == mode) + tmp &= ~(MTK_WDT_REQ_IRQ_THERMAL_EN); + } else + res = -1; + mt_reg_sync_writel(tmp, MTK_WDT_REQ_IRQ_EN); + spin_unlock(&rgu_reg_operation_spinlock); + return res; +} + +/*this API is for C2K only +* flag: 1 is to clear;0 is to set +* shift: which bit need to do set or clear +*/ +void mtk_wdt_set_c2k_sysrst(unsigned int flag, unsigned int shift) +{ +#ifdef CONFIG_OF + struct device_node *np_rgu; +#endif + unsigned int ret; +#ifdef CONFIG_OF + np_rgu = of_find_compatible_node(NULL, NULL, rgu_of_match[0].compatible); + + if (!toprgu_base) { + toprgu_base = of_iomap(np_rgu, 0); + if (!toprgu_base) + pr_err("mtk_wdt_set_c2k_sysrst RGU iomap failed\n"); + pr_debug("mtk_wdt_set_c2k_sysrst RGU base: 0x%p RGU irq: %d\n", toprgu_base, + wdt_irq_id); + } +#endif + spin_lock(&rgu_reg_operation_spinlock); + if (1 == flag) { + ret = __raw_readl(MTK_WDT_SWSYSRST); + ret &= (~(1 << shift)); + mt_reg_sync_writel((ret | MTK_WDT_SWSYS_RST_KEY), MTK_WDT_SWSYSRST); + } else { /* means set x bit */ + ret = __raw_readl(MTK_WDT_SWSYSRST); + ret |= ((1 << shift)); + mt_reg_sync_writel((ret | MTK_WDT_SWSYS_RST_KEY), MTK_WDT_SWSYSRST); + } + spin_unlock(&rgu_reg_operation_spinlock); +} + +#else +/* ------------------------------------------------------------------------------------------------- */ +/* Dummy functions */ +/* ------------------------------------------------------------------------------------------------- */ +void mtk_wdt_set_time_out_value(unsigned int value) +{ +} + +static void mtk_wdt_set_reset_length(unsigned int value) +{ +} + +void mtk_wdt_mode_config(bool dual_mode_en, bool irq, bool ext_en, bool ext_pol, bool wdt_en) +{ +} + +int mtk_wdt_enable(enum wk_wdt_en en) +{ + return 0; +} + +void mtk_wdt_restart(enum wd_restart_type type) +{ +} + +static void mtk_wdt_sw_trigger(void) +{ +} + +static unsigned char mtk_wdt_check_status(void) +{ + return 0; +} + +void wdt_arch_reset(char mode) +{ +} + +int mtk_wdt_confirm_hwreboot(void) +{ + return 0; +} + +void mtk_wd_suspend(void) +{ +} + +void mtk_wd_resume(void) +{ +} + +void mtk_wd_suspend_sodi(void) +{ +} + +void mtk_wd_resume_sodi(void) +{ +} + +void wdt_dump_reg(void) +{ +} + +int mtk_wdt_swsysret_config(int bit, int set_value) +{ + return 0; +} + +int mtk_wdt_request_mode_set(int mark_bit, WD_REQ_MODE mode) +{ + return 0; +} + +int mtk_wdt_request_en_set(int mark_bit, WD_REQ_CTL en) +{ + return 0; +} + +void mtk_wdt_set_c2k_sysrst(unsigned int flag) +{ +} + +int mtk_rgu_dram_reserved(int enable) +{ + return 0; +} + +#endif /* #ifndef __USING_DUMMY_WDT_DRV__ */ + +#ifndef CONFIG_FIQ_GLUE +static void wdt_report_info(void) +{ + /* extern struct task_struct *wk_tsk; */ + struct task_struct *task; + + task = &init_task; + pr_debug("Qwdt: -- watchdog time out\n"); + + for_each_process(task) { + if (task->state == 0) { + pr_debug("PID: %d, name: %s\n backtrace:\n", task->pid, task->comm); + show_stack(task, NULL); + pr_debug("\n"); + } + } + + pr_debug("backtrace of current task:\n"); + show_stack(NULL, NULL); + pr_debug("Qwdt: -- watchdog time out\n"); +} +#endif + + +#ifdef CONFIG_FIQ_GLUE +static void wdt_fiq(void *arg, void *regs, void *svc_sp) +{ + unsigned int wdt_mode_val; + struct wd_api *wd_api = NULL; + + get_wd_api(&wd_api); + wdt_mode_val = __raw_readl(MTK_WDT_STATUS); + mt_reg_sync_writel(wdt_mode_val, MTK_WDT_NONRST_REG); +#ifdef CONFIG_MTK_WD_KICKER + aee_wdt_printf("\n kick=0x%08x,check=0x%08x,STA=%x\n", wd_api->wd_get_kick_bit(), + wd_api->wd_get_check_bit(), wdt_mode_val); + aee_wdt_dump_reg(); +#endif + + aee_wdt_fiq_info(arg, regs, svc_sp); +#if 0 + asm volatile("mov %0, %1\n\t" + "mov fp, %2\n\t" + : "=r" (sp) + : "r" (svc_sp), "r" (preg[11]) + ); + *((unsigned int *)(0x00000000)); /* trigger exception */ +#endif +} +#else /* CONFIG_FIQ_GLUE */ +static irqreturn_t mtk_wdt_isr(int irq, void *dev_id) +{ + pr_err("fwq mtk_wdt_isr\n"); +#ifndef __USING_DUMMY_WDT_DRV__ /* FPGA will set this flag */ + /* mt65xx_irq_mask(AP_RGU_WDT_IRQ_ID); */ + rgu_wdt_intr_has_trigger = 1; + wdt_report_info(); + BUG(); + +#endif + return IRQ_HANDLED; +} +#endif /* CONFIG_FIQ_GLUE */ + +/* + * Device interface + */ +static int mtk_wdt_probe(struct platform_device *dev) +{ + int ret = 0; + unsigned int interval_val; + struct device_node *node; + u32 ints[2] = { 0, 0 }; + + pr_err("******** MTK WDT driver probe!! ********\n"); +#ifdef CONFIG_OF + if (!toprgu_base) { + toprgu_base = of_iomap(dev->dev.of_node, 0); + if (!toprgu_base) { + pr_err("RGU iomap failed\n"); + return -ENODEV; + } + } + if (!wdt_irq_id) { + wdt_irq_id = irq_of_parse_and_map(dev->dev.of_node, 0); + if (!wdt_irq_id) { + pr_err("RGU get IRQ ID failed\n"); + return -ENODEV; + } + } + pr_debug("RGU base: 0x%p RGU irq: %d\n", toprgu_base, wdt_irq_id); + +#endif + + node = of_find_compatible_node(NULL, NULL, "mediatek, MRDUMP_EXT_RST-eint"); + if (node) { + of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints)); + ext_debugkey_io = ints[0]; + } + pr_err("mtk_wdt_probe: ext_debugkey_io=%d\n", ext_debugkey_io); + +#ifndef __USING_DUMMY_WDT_DRV__ /* FPGA will set this flag */ + +#ifndef CONFIG_FIQ_GLUE + pr_debug("******** MTK WDT register irq ********\n"); + ret = + request_irq(AP_RGU_WDT_IRQ_ID, (irq_handler_t) mtk_wdt_isr, IRQF_TRIGGER_FALLING, + "mtk_watchdog", NULL); +#else + pr_debug("******** MTK WDT register fiq ********\n"); + ret = request_fiq(AP_RGU_WDT_IRQ_ID, wdt_fiq, IRQF_TRIGGER_FALLING, NULL); +#endif + + if (ret != 0) { + pr_err("mtk_wdt_probe : failed to request irq (%d)\n", ret); + return ret; + } + pr_debug("mtk_wdt_probe : Success to request irq\n"); + + /* Set timeout vale and restart counter */ + g_last_time_time_out_value = 30; + mtk_wdt_set_time_out_value(g_last_time_time_out_value); + + mtk_wdt_restart(WD_TYPE_NORMAL); + + /** + * Set the reset length: we will set a special magic key. + * For Power off and power on reset, the INTERVAL default value is 0x7FF. + * We set Interval[1:0] to different value to distinguish different stage. + * Enter pre-loader, we will set it to 0x0 + * Enter u-boot, we will set it to 0x1 + * Enter kernel, we will set it to 0x2 + * And the default value is 0x3 which means reset from a power off and power on reset + */ +#define POWER_OFF_ON_MAGIC (0x3) +#define PRE_LOADER_MAGIC (0x0) +#define U_BOOT_MAGIC (0x1) +#define KERNEL_MAGIC (0x2) +#define MAGIC_NUM_MASK (0x3) + + +#ifdef CONFIG_MTK_WD_KICKER /* Initialize to dual mode */ + pr_debug("mtk_wdt_probe : Initialize to dual mode\n"); + mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); +#else /* Initialize to disable wdt */ + pr_debug("mtk_wdt_probe : Initialize to disable wdt\n"); + mtk_wdt_mode_config(FALSE, FALSE, TRUE, FALSE, FALSE); + g_wdt_enable = 0; +#endif + + + /* Update interval register value and check reboot flag */ + interval_val = __raw_readl(MTK_WDT_INTERVAL); + interval_val &= ~(MAGIC_NUM_MASK); + interval_val |= (KERNEL_MAGIC); + /* Write back INTERVAL REG */ + mt_reg_sync_writel(interval_val, MTK_WDT_INTERVAL); + + /* Reset External debug key */ + mtk_wdt_request_en_set(MTK_WDT_REQ_MODE_SYSRST, WD_REQ_DIS); + mtk_wdt_request_en_set(MTK_WDT_REQ_MODE_EINT, WD_REQ_DIS); + mtk_wdt_request_mode_set(MTK_WDT_REQ_MODE_SYSRST, WD_REQ_IRQ_MODE); + mtk_wdt_request_mode_set(MTK_WDT_REQ_MODE_EINT, WD_REQ_IRQ_MODE); +#endif + udelay(100); + pr_debug("mtk_wdt_probe : done WDT_MODE(%x),MTK_WDT_NONRST_REG(%x)\n", + __raw_readl(MTK_WDT_MODE), __raw_readl(MTK_WDT_NONRST_REG)); + pr_debug("mtk_wdt_probe : done MTK_WDT_REQ_MODE(%x)\n", __raw_readl(MTK_WDT_REQ_MODE)); + pr_debug("mtk_wdt_probe : done MTK_WDT_REQ_IRQ_EN(%x)\n", __raw_readl(MTK_WDT_REQ_IRQ_EN)); + + return ret; +} + +static int mtk_wdt_remove(struct platform_device *dev) +{ + pr_debug("******** MTK wdt driver remove!! ********\n"); + +#ifndef __USING_DUMMY_WDT_DRV__ /* FPGA will set this flag */ + free_irq(AP_RGU_WDT_IRQ_ID, NULL); +#endif + return 0; +} + +static void mtk_wdt_shutdown(struct platform_device *dev) +{ + pr_debug("******** MTK WDT driver shutdown!! ********\n"); + + /* mtk_wdt_ModeSelection(KAL_FALSE, KAL_FALSE, KAL_FALSE); */ + /* kick external wdt */ + /* mtk_wdt_mode_config(TRUE, FALSE, FALSE, FALSE, FALSE); */ + + mtk_wdt_restart(WD_TYPE_NORMAL); + pr_debug("******** MTK WDT driver shutdown done ********\n"); +} + +void mtk_wd_suspend(void) +{ + /* mtk_wdt_ModeSelection(KAL_FALSE, KAL_FALSE, KAL_FALSE); */ + /* en debug, dis irq, dis ext, low pol, dis wdt */ + mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, FALSE); + + mtk_wdt_restart(WD_TYPE_NORMAL); + + /*aee_sram_printk("[WDT] suspend\n"); */ + pr_debug("[WDT] suspend\n"); +} + +void mtk_wd_resume(void) +{ + + if (g_wdt_enable == 1) { + mtk_wdt_set_time_out_value(g_last_time_time_out_value); + mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); + mtk_wdt_restart(WD_TYPE_NORMAL); + } + + /*aee_sram_printk("[WDT] resume(%d)\n", g_wdt_enable); */ + pr_debug("[WDT] resume(%d)\n", g_wdt_enable); +} + +void mtk_wd_suspend_sodi(void) +{ + /* mtk_wdt_ModeSelection(KAL_FALSE, KAL_FALSE, KAL_FALSE); */ + /* en debug, dis irq, dis ext, low pol, dis wdt */ + mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, FALSE); + mtk_wdt_restart(WD_TYPE_NORMAL); +} + +void mtk_wd_resume_sodi(void) +{ + if (g_wdt_enable == 1) { + mtk_wdt_set_time_out_value(g_last_time_time_out_value); + mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); + mtk_wdt_restart(WD_TYPE_NORMAL); + } +} + +static struct platform_driver mtk_wdt_driver = { + + .driver = { + .name = "mtk-wdt", +#ifdef CONFIG_OF + .of_match_table = rgu_of_match, +#endif + }, + .probe = mtk_wdt_probe, + .remove = mtk_wdt_remove, + .shutdown = mtk_wdt_shutdown, +/* .suspend = mtk_wdt_suspend, */ +/* .resume = mtk_wdt_resume, */ +}; + +#ifndef CONFIG_OF +struct platform_device mtk_device_wdt = { + .name = "mtk-wdt", + .id = 0, + .dev = { + } +}; +#endif + +#ifdef CONFIG_KICK_SPM_WDT +static void spm_wdt_init(void) +{ + unsigned int tmp; + /* set scpsys reset mode , not trigger irq */ + /* #ifndef CONFIG_ARM64 */ + /*6795 Macro */ + tmp = __raw_readl(MTK_WDT_REQ_MODE); + tmp |= MTK_WDT_REQ_MODE_KEY; + tmp |= (MTK_WDT_REQ_MODE_SPM_SCPSYS); + mt_reg_sync_writel(tmp, MTK_WDT_REQ_MODE); + + tmp = __raw_readl(MTK_WDT_REQ_IRQ_EN); + tmp |= MTK_WDT_REQ_IRQ_KEY; + tmp &= ~(MTK_WDT_REQ_IRQ_SPM_SCPSYS_EN); + mt_reg_sync_writel(tmp, MTK_WDT_REQ_IRQ_EN); + /* #endif */ + + pr_debug("mtk_wdt_init [MTK_WDT] not use RGU WDT use_SPM_WDT!! ********\n"); + /* pr_alert("WDT REQ_MODE=0x%x, WDT REQ_EN=0x%x\n", + __raw_readl(MTK_WDT_REQ_MODE), __raw_readl(MTK_WDT_REQ_IRQ_EN)); */ + + tmp = __raw_readl(MTK_WDT_MODE); + tmp |= MTK_WDT_MODE_KEY; + /* disable wdt */ + tmp &= (~(MTK_WDT_MODE_IRQ | MTK_WDT_MODE_ENABLE | MTK_WDT_MODE_DUAL_MODE)); + + /* Bit 4: WDT_Auto_restart, this is a reserved bit, we use it as bypass powerkey flag. */ + /* Because HW reboot always need reboot to kernel, we set it always. */ + tmp |= MTK_WDT_MODE_AUTO_RESTART; + /* BIt2 ext signal */ + tmp |= MTK_WDT_MODE_EXTEN; + mt_reg_sync_writel(tmp, MTK_WDT_MODE); + +} +#endif + + +/* + * init and exit function + */ +static int __init mtk_wdt_init(void) +{ + + int ret; + +#ifndef CONFIG_OF + ret = platform_device_register(&mtk_device_wdt); + if (ret) { + pr_err("****[mtk_wdt_driver] Unable to device register(%d)\n", ret); + return ret; + } +#endif + ret = platform_driver_register(&mtk_wdt_driver); + if (ret) { + pr_err("****[mtk_wdt_driver] Unable to register driver (%d)\n", ret); + return ret; + } + pr_alert("mtk_wdt_init ok\n"); + return 0; +} + +static void __exit mtk_wdt_exit(void) +{ +} + +/*this function is for those user who need WDT APIs before WDT driver's probe*/ +static int __init mtk_wdt_get_base_addr(void) +{ +#ifdef CONFIG_OF + struct device_node *np_rgu; + + np_rgu = of_find_compatible_node(NULL, NULL, rgu_of_match[0].compatible); + + if (!toprgu_base) { + toprgu_base = of_iomap(np_rgu, 0); + if (!toprgu_base) + pr_err("RGU iomap failed\n"); + + pr_debug("RGU base: 0x%p\n", toprgu_base); + } +#endif + return 0; +} +core_initcall(mtk_wdt_get_base_addr); +postcore_initcall(mtk_wdt_init); +module_exit(mtk_wdt_exit); + +MODULE_AUTHOR("MTK"); +MODULE_DESCRIPTION("Watchdog Device Driver"); +MODULE_LICENSE("GPL"); diff --git a/include/dt-bindings/clock/mt6755-clk.h b/include/dt-bindings/clock/mt6755-clk.h new file mode 100644 index 0000000000000000000000000000000000000000..f29d3b695d7ce5b5799d597b848678626a3e7a00 --- /dev/null +++ b/include/dt-bindings/clock/mt6755-clk.h @@ -0,0 +1,391 @@ +/* +* Copyright (c) 2014 MediaTek Inc. +* Author: Roy Chen +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* 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. +*/ + +#ifndef _DT_BINDINGS_CLK_MT6755_H +#define _DT_BINDINGS_CLK_MT6755_H + +/* TOPCKGEN */ +#define TOP_MUX_AXI 1 +#define TOP_MUX_MEM 2 +#define TOP_MUX_DDRPHY 3 +#define TOP_MUX_MM 4 +#define TOP_MUX_PWM 5 +#define TOP_MUX_VDEC 6 +#define TOP_MUX_MFG 7 +#define TOP_MUX_CAMTG 8 +#define TOP_MUX_UART 9 +#define TOP_MUX_SPI 10 +#define TOP_MUX_MSDC50_0_HCLK 11 +#define TOP_MUX_MSDC50_0 12 +/*#define TOP_MUX_MSDC30_0 13*/ +#define TOP_MUX_MSDC30_1 14 +#define TOP_MUX_MSDC30_2 15 +#define TOP_MUX_MSDC30_3 16 +#define TOP_MUX_AUDIO 17 +#define TOP_MUX_AUDINTBUS 18 +#define TOP_MUX_PMICSPI 19 +#define TOP_MUX_ATB 20 +#define TOP_MUX_DPI0 21 +#define TOP_MUX_SCAM 22 +/*#define TOP_MUX_MFG13M 23*/ +#define TOP_MUX_AUD1 24 +#define TOP_MUX_AUD2 25 +#define TOP_MUX_DISPPWM 26 +#define TOP_MUX_SSUSBTOPSYS 27 +#define TOP_MUX_USBTOP 28 +#define TOP_MUX_SPM 29 +#define TOP_MUX_BSISPI 30 +#define TOP_MUX_I2C 31 +#define TOP_MUX_DVFSP 32 +#define TOP_AD_APLL1_CK 33 +#define TOP_AD_APLL2_CK 34 +#define TOP_MMPLL_CK 35 +#define TOP_DDRX1_CK 36 +#define TOP_DMPLL_CK 37 +#define TOP_MPLL_208M_CK 38 +#define TOP_MSDCPLL_CK 39 +#define TOP_MSDCPLL_D16 40 +#define TOP_MSDCPLL_D2 41 +#define TOP_MSDCPLL_D4 42 +#define TOP_MSDCPLL_D8 43 +#define TOP_OSC_D2 44 +#define TOP_OSC_D4 45 +#define TOP_OSC_D8 46 +#define TOP_SYSPLL_D3 47 +#define TOP_SYSPLL_D3_D3 48 +#define TOP_SYSPLL_D5 49 +#define TOP_SYSPLL_D7 50 +#define TOP_SYSPLL1_D2 51 +#define TOP_SYSPLL1_D4 52 +#define TOP_SYSPLL1_D8 53 +#define TOP_SYSPLL1_D16 54 +#define TOP_SYSPLL2_D2 55 +#define TOP_SYSPLL2_D4 56 +#define TOP_SYSPLL3_D2 57 +#define TOP_SYSPLL3_D4 58 +#define TOP_SYSPLL4_D2 59 +#define TOP_SYSPLL4_D4 60 +#define TOP_TVDPLL_D2 61 +#define TOP_TVDPLL_D4 62 +#define TOP_TVDPLL_D8 63 +#define TOP_TVDPLL_D16 64 +#define TOP_UNIVPLL_D2 65 +#define TOP_UNIVPLL_D3 66 +#define TOP_UNIVPLL_D5 67 +#define TOP_UNIVPLL_D7 68 +#define TOP_UNIVPLL_D26 69 +#define TOP_UNIVPLL1_D2 70 +#define TOP_UNIVPLL1_D4 71 +#define TOP_UNIVPLL1_D8 72 +#define TOP_UNIVPLL2_D2 73 +#define TOP_UNIVPLL2_D4 74 +#define TOP_UNIVPLL2_D8 75 +#define TOP_UNIVPLL3_D2 76 +#define TOP_UNIVPLL3_D4 77 +#define TOP_VENCPLL_CK 78 +#define TOP_WHPLL_AUDIO_CK 79 +#define TOP_CLKPH_MCK_O 80 +#define TOP_DPI_CK 81 +#define TOP_MUX_USB20 82 +#define TOP_MUX_SCP 83 +#define TOP_MUX_IRDA 84 +#define TOP_MUX_IRTX 85 +#define TOP_AD_SYS_26M_CK 86 +#define TOP_AD_SYS_26M_D2 87 +#define TOP_DMPLL_D2 88 +#define TOP_DMPLL_D4 89 +#define TOP_DMPLL_D8 90 +#define TOP_SYSPLL_D2 91 +#define TOP_SYSPLL4_D2_D8 92 +#define TOP_TVDPLL_CK 93 +#define TOP_VENCPLL_D3 94 + +#define TOP_SYSPLL_CK 95 +#define TOP_SYSPLL1_CK 96 +#define TOP_SYSPLL2_CK 97 +#define TOP_SYSPLL3_CK 98 +#define TOP_SYSPLL4_CK 99 +#define TOP_UNIVPLL_CK 100 +#define TOP_UNIVPLL1_CK 101 +#define TOP_UNIVPLL2_CK 102 +#define TOP_UNIVPLL3_CK 103 +#define TOP_OSC_CK 104 +#define TOP_NR_CLK 105 + +/* APMIXED_SYS */ +#define APMIXED_ARMBPLL 1 +#define APMIXED_ARMSPLL 2 +#define APMIXED_MAINPLL 3 +#define APMIXED_MSDCPLL 4 +#define APMIXED_UNIVPLL 5 +#define APMIXED_MMPLL 6 +#define APMIXED_VENCPLL 7 +#define APMIXED_TVDPLL 8 +#define APMIXED_APLL1 9 +#define APMIXED_APLL2 10 +#define APMIXED_ARMPLL 11 +#define SCP_OSCPLL 12 +#define APMIXED_NR_CLK 13 + +/* INFRA_SYS0, infrasys0 */ +#define INFRA_PMIC_TMR 1 +#define INFRA_PMIC_AP 2 +#define INFRA_PMIC_MD 3 +#define INFRA_PMIC_CONN 4 +/*#define INFRA_SCPSYS*/ +#define INFRA_SEJ 5 +#define INFRA_APXGPT 6 +#define INFRA_ICUSB 7 +#define INFRA_GCE 8 +#define INFRA_THERM 9 +#define INFRA_I2C0 10 +#define INFRA_I2C1 11 +#define INFRA_I2C2 12 +#define INFRA_I2C3 13 +#define INFRA_PWM_HCLK 14 +#define INFRA_PWM1 15 +#define INFRA_PWM2 16 +#define INFRA_PWM3 17 +#define INFRA_PWM4 18 +#define INFRA_PWM 19 +#define INFRA_UART0 20 +#define INFRA_UART1 21 +#define INFRA_UART2 22 +#define INFRA_UART3 23 +#define INFRA_MD2MD_CCIF0 24 +#define INFRA_MD2MD_CCIF1 25 +#define INFRA_MD2MD_CCIF2 26 +#define INFRA_BTIF 27 +/* INFRA_SYS1, infrasys1 */ +#define INFRA_MD2MD_CCIF3 28 +#define INFRA_SPI0 29 +#define INFRA_MSDC0 30 +#define INFRA_MD2MD_CCIF4 31 +#define INFRA_MSDC1 32 +#define INFRA_MSDC2 33 +#define INFRA_MSDC3 34 +#define INFRA_MD2MD_CCIF5 35 +#define INFRA_GCPU 36 +#define INFRA_TRNG 37 +#define INFRA_AUXADC 38 +#define INFRA_CPUM 39 +#define INFRA_CCIF1_AP 40 +#define INFRA_CCIF1_MD 41 +/*#define INFRA_NFI +#define INFRA_NFI_ECC*/ +#define INFRA_AP_DMA 42 +#define INFRA_XIU 43 +#define INFRA_DEVICE_APC 44 +#define INFRA_XIU2AHB 45 +/*#define INFRA_L2C_SRAM*/ +#define INFRA_CCIF_AP 46 +#define INFRA_DEBUGSYS 47 +#define INFRA_AUDIO 48 +#define INFRA_CCIF_MD 49 +#define INFRA_DRAMC_F26M 50 +/* INFRA_SYS2, infrasys2 */ +#define INFRA_IRTX 51 +#define INFRA_SSUSB_TOP 52 +#define INFRA_DISP_PWM 53 +#define INFRA_CLDMA_BCLK 54 +#define INFRA_AUDIO_26M_BCLK 55 +#define INFRA_MD_TEMP_26M_BCLK 56 +#define INFRA_SPI1 57 +#define INFRA_I2C4 58 +#define INFRA_MD_TEMP_SHARE 59 +#define INFRA_CLK_13M 60 +#define INFRA_NR_CLK 61 + + + + + + +#if 0 +#define INFRA_DBGCLK 1 +#define INFRA_GCE 2 +#define INFRA_TRBG 3 +#define INFRA_CPUM 4 +#define INFRA_DEVAPC 5 +#define INFRA_AUDIO 6 +#define INFRA_GCPU 7 +#define INFRA_L2C_SRAM 8 +#define INFRA_CLDMA 9 +#define INFRA_APXGPT 10 +#define INFRA_SEJ 11 +#define INFRA_CCIF0_AP 12 +#define INFRA_CCIF1_AP 13 +#define INFRA_DRMAC_F26M 14 +#define INFRA_M4U 15 +#define INFRA_CONNMCU_BUS 16 +#define INFRA_KP 17 +#define INFRA_PMIC_SPI 18 +#define INFRA_PMIC_WRAP 19 +#define INFRA_NR_CLK 20 +#endif + +/* PERI_SYS, perisys */ +#define PERI_NR_CLK 1 +#if 0 +#define PERI_DISP_PWM 1 +#define PERI_THERM 2 +#define PERI_PWM1 3 +#define PERI_PWM2 4 +#define PERI_PWM3 5 +#define PERI_PWM4 6 +#define PERI_PWM 7 +#define PERI_PWM_HCLK 8 +#define PERI_USB0 9 +#define PERI_SSUSB 10 +#define PERI_APDMA 11 +#define PERI_MSDC30_0 12 +#define PERI_MSDC30_1 13 +#define PERI_MSDC30_2 14 +#define PERI_MSDC30_3 15 +#define PERI_UART0 16 +#define PERI_UART1 17 +#define PERI_UART2 18 +#define PERI_UART3 19 +#define PERI_BTIF 20 +#define PERI_I2C0 21 +#define PERI_I2C1 22 +#define PERI_I2C2 23 +#define PERI_I2C3 24 +#define PERI_I2C4 25 +#define PERI_AUXADC 26 +#define PERI_AUDIO26M 27 +#define PERI_SPI0 28 +#define PERI_SPI1 29 +#define PERI_IRTX 30 +#define PERI_PWM5 31 +#define PERI_PWM6 32 +#define PERI_PWM7 33 +#define PERI_IRDA 34 +#define PERI_UART4 35 +#define PERI_NR_CLK 36 +#endif +/* MFG_SYS, mfgsys */ +#define MFG_BG3D 1 +#define MFG_NR_CLK 2 + +/* IMG_SYS, imgsys */ +#define IMG_IMAGE_LARB2_SMI 1 +#define IMG_IMAGE_LARB2_SMI_M4U 2 +#define IMG_IMAGE_LARB2_SMI_SMI_COMMON 3 +#define IMG_IMAGE_LARB2_SMI_MET_SMI_COMMON 4 +#define IMG_IMAGE_LARB2_SMI_ISPSYS 5 +#define IMG_IMAGE_CAM_SMI 6 +#define IMG_IMAGE_CAM_CAM 7 +#define IMG_IMAGE_SEN_TG 8 +#define IMG_IMAGE_SEN_CAM 9 +#define IMG_IMAGE_CAM_SV 10 +#define IMG_IMAGE_SUFOD 11 +#define IMG_IMAGE_FD 12 +#define IMG_NR_CLK 13 + +/* MM_SYS, mmsys */ +#define MM_DISP0_SMI_COMMON 1 +#define MM_DISP0_SMI_COMMON_M4U 2 +#define MM_DISP0_SMI_COMMON_MALI 3 +#define MM_DISP0_SMI_COMMON_DISPSYS 4 +#define MM_DISP0_SMI_COMMON_SMI_COMMON 5 +#define MM_DISP0_SMI_COMMON_MET_SMI_COMMON 6 +#define MM_DISP0_SMI_COMMON_ISPSYS 7 +#define MM_DISP0_SMI_COMMON_FDVT 8 +#define MM_DISP0_SMI_COMMON_VDEC_GCON 9 +#define MM_DISP0_SMI_COMMON_JPGENC 10 +#define MM_DISP0_SMI_COMMON_JPGDEC 11 +#define MM_DISP0_SMI_LARB0 12 +#define MM_DISP0_SMI_LARB0_M4U 13 +#define MM_DISP0_SMI_LARB0_DISPSYS 14 +#define MM_DISP0_SMI_LARB0_SMI_COMMON 15 +#define MM_DISP0_SMI_LARB0_MET_SMI_COMMON 16 +#define MM_DISP0_CAM_MDP 17 +#define MM_DISP0_MDP_RDMA 18 +#define MM_DISP0_MDP_RSZ0 19 +#define MM_DISP0_MDP_RSZ1 20 +#define MM_DISP0_MDP_TDSHP 21 +#define MM_DISP0_MDP_WDMA 22 +#define MM_DISP0_MDP_WROT 23 +#define MM_DISP0_FAKE_ENG 24 +#define MM_DISP0_DISP_OVL0 25 +#define MM_DISP0_DISP_OVL1 26 +#define MM_DISP0_DISP_RDMA0 27 +#define MM_DISP0_DISP_RDMA1 28 +#define MM_DISP0_DISP_WDMA0 29 +#define MM_DISP0_DISP_COLOR 30 +#define MM_DISP0_DISP_CCORR 31 +#define MM_DISP0_DISP_AAL 32 +#define MM_DISP0_DISP_GAMMA 33 +#define MM_DISP0_DISP_DITHER 34 +#define MM_DISP0_MDP_COLOR 35 +#define MM_DISP0_DISP_UFOE_MOUT 36 +#define MM_DISP0_DISP_WDMA1 37 +#define MM_DISP0_DISP_2L_OVL0 38 +#define MM_DISP0_DISP_2L_OVL1 39 +#define MM_DISP0_DISP_OVL0_MOUT 40 +#define MM_DISP1_DSI_ENGINE 41 +#define MM_DISP1_DSI_DIGITAL 42 +#define MM_DISP1_DPI_ENGINE 43 +#define MM_DISP1_DPI_PIXEL 44 +#define MM_NR_CLK 45 + +/* VDEC_SYS, vdecsys */ +#define VDEC0_VDEC 1 +#define VDEC1_LARB 2 +#define VDEC1_LARB_M4U 3 +#define VDEC1_LARB_SMI_COMMON 4 +#define VDEC1_LARB_MET_SMI_COMMON 5 +#define VDEC1_LARB_VDEC_GCON 6 +#define VDEC_NR_CLK 7 + +/* VENC_SYS, vencsys */ +#define VENC_LARB 1 +#define VENC_LARB_M4U 2 +#define VENC_LARB_SMI_COMMON 3 +#define VENC_LARB_MET_SMI_COMMON 4 +#define VENC_LARB_JPGENC 5 +#define VENC_LARB_JPGDEC 6 +#define VENC_VENC 7 +#define VENC_JPGENC 8 +#define VENC_JPGDEC 9 +#define VENC_NR_CLK 10 + +/* AUDIO_SYS, audiosys */ +#define AUDIO_AFE 1 +#define AUDIO_I2S 2 +#define AUDIO_22M 3 +#define AUDIO_24M 4 +#define AUDIO_APLL2_TUNER 5 +#define AUDIO_APLL_TUNER 6 +#define AUDIO_ADC 7 +#define AUDIO_DAC 8 +#define AUDIO_DAC_PREDIS 9 +#define AUDIO_TML 10 +#define AUDIO_APLL1_DIV0 11 +#define AUDIO_APLL2_DIV0 12 +#define AUDIO_NR_CLK 13 + +/* SCP_SYS */ +#define SCP_SYS_MD1 1 +#define SCP_SYS_MD2 2 +#define SCP_SYS_CONN 3 +#define SCP_SYS_DIS 4 +#define SCP_SYS_MFG 5 +#define SCP_SYS_ISP 6 +#define SCP_SYS_VDE 7 +#define SCP_SYS_VEN 8 +#define SCP_SYS_AUD 9 +#define SCP_NR_SYSS 10 +#endif /* _DT_BINDINGS_CLK_MT6755_H */ diff --git a/include/dt-bindings/mmc/mt6755-msdc.h b/include/dt-bindings/mmc/mt6755-msdc.h new file mode 100644 index 0000000000000000000000000000000000000000..bdb6e803d83fdfbb2e222b1bb959f4241245f5b5 --- /dev/null +++ b/include/dt-bindings/mmc/mt6755-msdc.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Shi.Ma + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _DT_BINDINGS_MMC_MT65XX_H +#define _DT_BINDINGS_MMC_MT65XX_H + +#define MSDC_EMMC (0) +#define MSDC_SD (1) +#define MSDC_SDIO (2) + +#define MSDC_CD_HIGH (1) +#define MSDC_CD_LOW (0) + +#define MSDC50_CLKSRC_26MHZ (0) +#define MSDC50_CLKSRC_400MHZ (1) +#define MSDC50_CLKSRC_200MHZ (2) +#define MSDC50_CLKSRC_156MHZ (3) +#define MSDC50_CLKSRC_182MHZ (4) +#define MSDC50_CLKSRC_NONE (5) +#define MSDC50_CLKSRC_100MHZ (6) +#define MSDC50_CLKSRC_624MHZ (7) +#define MSDC50_CLKSRC_312MHZ (8) + +#define MSDC30_CLKSRC_26MHZ (0) +#define MSDC30_CLKSRC_208MHZ (1) +#define MSDC30_CLKSRC_100MHZ (2) +#define MSDC30_CLKSRC_156MHZ (3) +#define MSDC30_CLKSRC_182MHZ (4) +#define MSDC30_CLKSRC_NONE (5) +#define MSDC30_CLKSRC_178MHZ (6) +#define MSDC30_CLKSRC_200MHZ (7) + +#define MSDC30_3_CLKSRC_26MHZ (0) +#define MSDC30_3_CLKSRC_50MHZ (1) +#define MSDC30_3_CLKSRC_100MHZ (2) +#define MSDC30_3_CLKSRC_156MHZ (3) +#define MSDC30_3_CLKSRC_48MHZ (4) +#define MSDC30_3_CLKSRC_NONE (5) +#define MSDC30_3_CLKSRC_178MHZ (6) +#define MSDC30_3_CLKSRC_54MHZ (7) +#define MSDC30_3_CLKSRC_25MHZ (8) + +#define MSDC0_CLKSRC_DEFAULT MSDC50_CLKSRC_400MHZ +#define MSDC1_CLKSRC_DEFAULT MSDC30_CLKSRC_200MHZ +#define MSDC2_CLKSRC_DEFAULT MSDC30_CLKSRC_200MHZ + +#define MSDC_SMPL_RISING (0) +#define MSDC_SMPL_FALLING (1) +#define MSDC_SMPL_SEPARATE (2) + +#endif /* _DT_BINDINGS_MMC_MT65XX_H */ diff --git a/sound/soc/mediatek/mt6755/AudDrv_Afe.h b/sound/soc/mediatek/mt6755/AudDrv_Afe.h new file mode 100644 index 0000000000000000000000000000000000000000..3ab6e1d24b3d4062aae402ecf27186a76968701a --- /dev/null +++ b/sound/soc/mediatek/mt6755/AudDrv_Afe.h @@ -0,0 +1,688 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + * + * 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. + * You should have received a copy of the GNU General Public License + * along with this program + * If not, see . + */ +/******************************************************************************* + * + * Filename: + * --------- + * AudioAfe.h + * + * Project: + * -------- + * MT6755 Audio Driver Afe Register setting + * + * Description: + * ------------ + * Audio register + * + * Author: + * ------- + * Ir Lian (mtk00976) + * Harvey Huang (mtk03996) + * Chipeng Chang (mtk02308) + * + *------------------------------------------------------------------------------ + * + * + *******************************************************************************/ + +#ifndef _AUDDRV_AFE_H_ +#define _AUDDRV_AFE_H_ + +#include "AudDrv_Common.h" +#include "AudDrv_Def.h" +#include "mt_soc_digital_type.h" +#include + +/***************************************************************************** + * C O M P I L E R F L A G S + *****************************************************************************/ + + +/***************************************************************************** + * E X T E R N A L R E F E R E N C E S + *****************************************************************************/ + +/***************************************************************************** + * D A T A T Y P E S + *****************************************************************************/ + +typedef enum { + AFE_MEM_NONE = 0, + AFE_MEM_DL1, + AFE_MEM_DL1_DATA2, + AFE_MEM_DL2, + AFE_MEM_VUL, + AFE_MEM_DAI, + AFE_MEM_I2S, + AFE_MEM_AWB, + AFE_MEM_MOD_PCM, +} MEM_INTERFACE_T; + +typedef enum { + AFE_8000HZ = 0, + AFE_11025HZ = 1, + AFE_12000HZ = 2, + AFE_16000HZ = 3, + AFE_22050HZ = 4, + AFE_24000HZ = 5, + AFE_32000HZ = 6, + AFE_44100HZ = 7, + AFE_48000HZ = 8 +} SAMPLINGRATE_T; + +typedef enum { + AFE_DAIMOD_8000HZ = 0x0, + AFE_DAIMOD_16000HZ = 0x1, +} DAIMOD_SAMPLINGRATE_T; + +typedef enum { + AFE_STEREO = 0x0, + AFE_MONO = 0x1 +} MEMIF_CH_CFG_T; + +typedef enum { + AFE_MONO_USE_L = 0x0, + AFE_MONO_USE_R = 0x1 +} MEMIF_MONO_SEL_T; + +typedef enum { + AFE_DUP_WR_DISABLE = 0x0, + AFE_DUP_WR_ENABLE = 0x1 +} MEMIF_DUP_WRITE_T; + +typedef struct { + uint32 u4AFE_MEMIF_BUF_BASE; + uint32 u4AFE_MEMIF_BUF_END; + uint32 u4AFE_MEMIF_BUF_WP; + uint32 u4AFE_MEMIF_BUF_RP; +} MEMIF_BUF_T; + +typedef struct { + MEM_INTERFACE_T eMemInterface; + SAMPLINGRATE_T eSamplingRate; + DAIMOD_SAMPLINGRATE_T eDaiModSamplingRate; + MEMIF_CH_CFG_T eChannelConfig; + MEMIF_MONO_SEL_T eMonoSelect; /* Used when AWB and VUL and data is mono */ + MEMIF_DUP_WRITE_T eDupWrite; /* Used when MODPCM and DAI */ + MEMIF_BUF_T rBufferSetting; +} MEMIF_CONFIG_T; + +/* I2S related */ +typedef enum { + I2S_EIAJ = 0x0, + I2S_I2S = 0x1 +} I2SFMT_T; + +typedef enum { + I2S_16BIT = 0x0, + I2S_32BIT = 0x1 +} I2SWLEN_T; + +typedef enum { + I2S_NOSWAP = 0x0, + I2S_LRSWAP = 0x1 +} I2SSWAP_T; + +typedef enum { + I2S_DISABLE = 0x0, + I2S_ENABLE = 0x1 +} I2SEN_T; + +typedef enum { + I2S_MASTER = 0x0, + I2S_SLAVE = 0x1 +} I2SSRC_T; + +typedef enum { + I2S_OUT = 0x0, + I2S_IN = 0x1 +} I2SDIR_T; + + +/* PCM related */ +typedef enum { + PCM_1 = 0x0, /* (O7, O8, I9) */ + PCM_2 = 0x1 /* (O17, O18, I14) */ +} PCM_MODULE; + +typedef enum { + PCM_DISABLE = 0x0, + PCM_ENABLE = 0x1 +} PCMEN_T; + +typedef enum { + PCM_I2S = 0x0, + PCM_EIAJ = 0x1, + PCM_MODEA = 0x2, + PCM_MODEB = 0x3 +} PCMFMT_T; + +typedef enum { + PCM_8K = 0x0, + PCM_16K = 0x1 +} PCMMODE_T; + +typedef enum { + PCM_16BIT = 0x0, + PCM_32BIT = 0x1 +} PCMWLEN_T; + + +typedef enum { + PCM_MASTER = 0x0, + PCM_SLAVE = 0x1 +} PCMCLKSRC_T; + + +typedef enum { + PCM_GO_ASRC = 0x0, /* (ASRC) Set to 0 when source & destination uses different crystal */ + PCM_GO_ASYNC_FIFO = 0x1 /* (Async FIFO) Set to 1 when source & destination uses same crystal */ +} PCMBYPASRC_T; + + +typedef enum { + PCM_DMTX = 0x0, /* dual mic on TX */ + PCM_SMTX = 0x1 /* single mic on TX (In BT mode, only L channel data is sent on PCM TX.) */ +} PCMBTMODE_T; + + +typedef enum { + PCM_SYNC_LEN_1_BCK = 0x0, + PCM_SYNC_LEN_N_BCK = 0x1 +} PCMSYNCTYPE_T; + +typedef enum { + PCM_INT_MD = 0x0, + PCM_EXT_MD = 0x1 +} PCMEXTMODEM_T; + + +typedef enum { + PCM_VBT_16K_MODE_DISABLE = 0x0, + PCM_VBT_16K_MODE_ENABLE = 0x1 +} PCMVBT16KMODE_T; + + +typedef enum { + PCM_NOINV = 0x0, + PCM_INV = 0x1 +} PCMCLKINV_T; + +typedef enum { + PCM_LB_DISABLE = 0x0, + PCM_LB_ENABLE = 0x1 +} PCMLOOPENA_T; + +typedef enum { + PCM_TXFIX_OFF = 0x0, + PCM_TXFIX_ON = 0x1 +} PCMTXFIXEN_T; + +typedef struct { + PCMFMT_T ePcmFmt; + PCMMODE_T ePcm8k16kmode; + PCMWLEN_T ePcmWlen; + PCMCLKSRC_T ePcmClkSrc; + PCMBYPASRC_T ePcmBypassASRC; + PCMEXTMODEM_T ePcmModemSel; + PCMVBT16KMODE_T ePcmVbt16kSel; +} PCM_INFO_T; + + +/* BT PCM */ +typedef enum { + BTPCM_DISABLE = 0x0, + BTPCM_ENABLE = 0x1 +} BTPCMEN_T; + +typedef enum { + BTPCM_8K = 0x0, + BTPCM_16K = 0x1 +} BTPCMMODE_T; + + + +/* Interconnection related */ +typedef enum { + I00 = 0, + I01 = 1, + I02 = 2, + I03 = 3, + I04 = 4, + I05 = 5, + I06 = 6, + I07 = 7, + I08 = 8, + I09 = 9, + IN_MAX +} ITRCON_IN_T; + +typedef enum { + O00 = 0, + O01 = 1, + O02 = 2, + O03 = 3, + O04 = 4, + O05 = 5, + O06 = 6, + O07 = 7, + O08 = 8, + O09 = 9, + O010 = 10, + O011 = 11, + O012 = 12, + OUT_MAX +} ITRCON_OUT_T; + +/* Side tone filter related */ +typedef enum { + I3I4 = 0, + HW_SINE = 1, + I5I6 = 2, +} STF_SRC_T; + +/* Sine wave generator related */ +typedef enum { + SINE_TONE_CH1 = 0, + SINE_TONE_CH2 = 1, + SINE_TONE_STEREO = 2 +} SINE_TONE_CH_T; + +typedef enum { + SINE_TONE_128 = 0, + SINE_TONE_64 = 1, + SINE_TONE_32 = 2, + SINE_TONE_16 = 3, + SINE_TONE_8 = 4, + SINE_TONE_4 = 5, + SINE_TONE_2 = 6, + SINE_TONE_1 = 7 +} SINE_TONE_AMP_T; + +typedef enum { + SINE_TONE_8K = 0, + SINE_TONE_11K = 1, + SINE_TONE_12K = 2, + SINE_TONE_16K = 3, + SINE_TONE_22K = 4, + SINE_TONE_24K = 5, + SINE_TONE_32K = 6, + SINE_TONE_44K = 7, + SINE_TONE_48K = 8, + SINE_TONE_LOOPBACK = 9 +} SINE_TONE_SINEMODE_T; + +typedef enum { + SINE_TONE_LOOPBACK_I0_I1 = 0, + SINE_TONE_LOOPBACK_I2 = 1, + SINE_TONE_LOOPBACK_I3_I4 = 2, + SINE_TONE_LOOPBACK_I5_I6 = 3, + SINE_TONE_LOOPBACK_I7_I8 = 4, + SINE_TONE_LOOPBACK_I9_I10 = 5, + SINE_TONE_LOOPBACK_I11_I12 = 6, + SINE_TONE_LOOPBACK_O0_O1 = 7, + SINE_TONE_LOOPBACK_O2 = 8, + SINE_TONE_LOOPBACK_O3_O4 = 9, + SINE_TONE_LOOPBACK_O5_O6 = 10, + SINE_TONE_LOOPBACK_O7_O8 = 11, + SINE_TONE_LOOPBACK_O9_O10 = 12, + SINE_TONE_LOOPBACK_O11 = 13, + SINE_TONE_LOOPBACK_O12 = 14 +} SINE_TONE_LOOPBACK_T; + +typedef struct { + uint32 u4ch1_freq_div; /* 64/n sample/period */ + SINE_TONE_AMP_T rch1_amp_div; + SINE_TONE_SINEMODE_T rch1_sine_mode; + uint32 u4ch2_freq_div; /* 64/n sample/period */ + SINE_TONE_AMP_T rch2_amp_div; + SINE_TONE_SINEMODE_T rch2_sine_mode; + SINE_TONE_LOOPBACK_T rloopback_mode; +} AFE_SINEGEN_INFO_T; + + +/***************************************************************************** + * C O N S T A N T S + *****************************************************************************/ +#define AUDIO_HW_PHYSICAL_BASE (0x11220000L) +#define AUDIO_CLKCFG_PHYSICAL_BASE (0x10000000L) +/* need enable this register before access all register */ +#define AUDIO_POWER_TOP (0x1000629cL) +#define AUDIO_INFRA_BASE (0x10001000L) +#define AUDIO_HW_VIRTUAL_BASE (0xF1220000L) + +#define APMIXEDSYS_BASE (0x1000C000L) + +#ifdef AUDIO_MEM_IOREMAP +#define AFE_BASE (0L) +#else +#define AFE_BASE (AUDIO_HW_VIRTUAL_BASE) +#endif + +/* Internal sram */ +#define AFE_INTERNAL_SRAM_PHY_BASE (0x11221000L) +#define AFE_INTERNAL_SRAM_VIR_BASE (AUDIO_HW_VIRTUAL_BASE - 0x70000+0x8000) +#define AFE_INTERNAL_SRAM_SIZE (0xC000) /* 48k, for normal mode */ + +/* Dram */ +#define AFE_EXTERNAL_DRAM_SIZE (0xC000) /* 48k */ + +/* IRQ */ +#define AFE_IRQ_MASK (0x43) + +/***************************************************************************** + * M A C R O + *****************************************************************************/ + +/***************************************************************************** + * R E G I S T E R D E F I N I T I O N + *****************************************************************************/ + +#define AUD_GPIO_BASE (0xF0005000L) +#define AUD_GPIO_MODE39 (0x860) +#define AUD_DRV_SEL4 (0xB40) + +#define APLL_PHYSICAL_BASE (0x10209000L) +/* #define AP_PLL_CON5 (0x0014) */ + +#define AUDIO_CLK_CFG_4 (0x0080) +#define AUDIO_CLK_CFG_6 (0x00A0) +#define AUDIO_CLK_CFG_7 (0x00B0) +#define AUDIO_CLK_CFG_8 (0x00C0) /* Jade no */ +#define AUDIO_CG_SET (0x88) +#define AUDIO_CG_CLR (0x8c) +#define AUDIO_CG_STATUS (0x94) + +/* apmixed sys */ /* Jade no */ +#define APLL1_CON0 0x02a0 +#define APLL1_CON1 0x02a4 +#define APLL1_CON2 0x02a8 +#define APLL1_CON3 0x02ac + +#define APLL2_CON0 0x02b4 +#define APLL2_CON1 0x02b8 +#define APLL2_CON2 0x02bc +#define APLL2_CON3 0x02c0 + +#define AUDIO_TOP_CON0 (AFE_BASE + 0x0000) +#define AUDIO_TOP_CON1 (AFE_BASE + 0x0004) +#define AUDIO_TOP_CON3 (AFE_BASE + 0x000c) +#define AFE_DAC_CON0 (AFE_BASE + 0x0010) +#define AFE_DAC_CON1 (AFE_BASE + 0x0014) +#define AFE_I2S_CON (AFE_BASE + 0x0018) +#define AFE_DAIBT_CON0 (AFE_BASE + 0x001c) +#define AFE_CONN0 (AFE_BASE + 0x0020) +#define AFE_CONN1 (AFE_BASE + 0x0024) +#define AFE_CONN2 (AFE_BASE + 0x0028) +#define AFE_CONN3 (AFE_BASE + 0x002c) +#define AFE_CONN4 (AFE_BASE + 0x0030) +#define AFE_I2S_CON1 (AFE_BASE + 0x0034) +#define AFE_I2S_CON2 (AFE_BASE + 0x0038) +#define AFE_MRGIF_CON (AFE_BASE + 0x003c) +#define AFE_DL1_BASE (AFE_BASE + 0x0040) +#define AFE_DL1_CUR (AFE_BASE + 0x0044) +#define AFE_DL1_END (AFE_BASE + 0x0048) +#define AFE_I2S_CON3 (AFE_BASE + 0x004c) +#define AFE_DL2_BASE (AFE_BASE + 0x0050) +#define AFE_DL2_CUR (AFE_BASE + 0x0054) +#define AFE_DL2_END (AFE_BASE + 0x0058) +#define AFE_CONN5 (AFE_BASE + 0x005c) +#define AFE_CONN_24BIT (AFE_BASE + 0x006c) +#define AFE_AWB_BASE (AFE_BASE + 0x0070) +#define AFE_AWB_END (AFE_BASE + 0x0078) +#define AFE_AWB_CUR (AFE_BASE + 0x007c) +#define AFE_VUL_BASE (AFE_BASE + 0x0080) +#define AFE_VUL_END (AFE_BASE + 0x0088) +#define AFE_VUL_CUR (AFE_BASE + 0x008c) +#define AFE_DAI_BASE (AFE_BASE + 0x0090) +#define AFE_DAI_END (AFE_BASE + 0x0098) +#define AFE_DAI_CUR (AFE_BASE + 0x009c) +#define AFE_CONN6 (AFE_BASE + 0x00bc) +#define AFE_MEMIF_MSB (AFE_BASE + 0x00cc) +#define AFE_MEMIF_MON0 (AFE_BASE + 0x00d0) +#define AFE_MEMIF_MON1 (AFE_BASE + 0x00d4) +#define AFE_MEMIF_MON2 (AFE_BASE + 0x00d8) +#define AFE_MEMIF_MON4 (AFE_BASE + 0x00e0) +#define AFE_ADDA_DL_SRC2_CON0 (AFE_BASE + 0x0108) +#define AFE_ADDA_DL_SRC2_CON1 (AFE_BASE + 0x010c) +#define AFE_ADDA_UL_SRC_CON0 (AFE_BASE + 0x0114) +#define AFE_ADDA_UL_SRC_CON1 (AFE_BASE + 0x0118) +#define AFE_ADDA_TOP_CON0 (AFE_BASE + 0x0120) +#define AFE_ADDA_UL_DL_CON0 (AFE_BASE + 0x0124) +#define AFE_ADDA_SRC_DEBUG (AFE_BASE + 0x012c) +#define AFE_ADDA_SRC_DEBUG_MON0 (AFE_BASE + 0x0130) +#define AFE_ADDA_SRC_DEBUG_MON1 (AFE_BASE + 0x0134) +#define AFE_ADDA_NEWIF_CFG0 (AFE_BASE + 0x0138) +#define AFE_ADDA_NEWIF_CFG1 (AFE_BASE + 0x013c) +#define AFE_SIDETONE_DEBUG (AFE_BASE + 0x01d0) +#define AFE_SIDETONE_MON (AFE_BASE + 0x01d4) +#define AFE_SIDETONE_CON0 (AFE_BASE + 0x01e0) +#define AFE_SIDETONE_COEFF (AFE_BASE + 0x01e4) +#define AFE_SIDETONE_CON1 (AFE_BASE + 0x01e8) +#define AFE_SIDETONE_GAIN (AFE_BASE + 0x01ec) +#define AFE_SGEN_CON0 (AFE_BASE + 0x01f0) +#define AFE_TOP_CON0 (AFE_BASE + 0x0200) +#define AFE_ADDA_PREDIS_CON0 (AFE_BASE + 0x0260) +#define AFE_ADDA_PREDIS_CON1 (AFE_BASE + 0x0264) +#define AFE_MRGIF_MON0 (AFE_BASE + 0x0270) +#define AFE_MRGIF_MON1 (AFE_BASE + 0x0274) +#define AFE_MRGIF_MON2 (AFE_BASE + 0x0278) +#define AFE_MOD_DAI_BASE (AFE_BASE + 0x0330) +#define AFE_MOD_DAI_END (AFE_BASE + 0x0338) +#define AFE_MOD_DAI_CUR (AFE_BASE + 0x033c) +#define AFE_VUL_D2_BASE (AFE_BASE + 0x0350) +#define AFE_VUL_D2_END (AFE_BASE + 0x0358) +#define AFE_VUL_D2_CUR (AFE_BASE + 0x035c) +#define AFE_IRQ_MCU_CON (AFE_BASE + 0x03a0) +#define AFE_IRQ_MCU_STATUS (AFE_BASE + 0x03a4) +#define AFE_IRQ_MCU_CLR (AFE_BASE + 0x03a8) +#define AFE_IRQ_MCU_CNT1 (AFE_BASE + 0x03ac) +#define AFE_IRQ_MCU_CNT2 (AFE_BASE + 0x03b0) +#define AFE_IRQ_MCU_EN (AFE_BASE + 0x03b4) +#define AFE_IRQ_MCU_MON2 (AFE_BASE + 0x03b8) +#define AFE_IRQ1_MCU_CNT_MON (AFE_BASE + 0x03c0) +#define AFE_IRQ2_MCU_CNT_MON (AFE_BASE + 0x03c4) +#define AFE_IRQ1_MCU_EN_CNT_MON (AFE_BASE + 0x03c8) +#define AFE_MEMIF_MAXLEN (AFE_BASE + 0x03d4) +#define AFE_MEMIF_PBUF_SIZE (AFE_BASE + 0x03d8) +#define AFE_IRQ_MCU_CNT7 (AFE_BASE + 0x03dc) +#define AFE_APLL1_TUNER_CFG (AFE_BASE + 0x03f0) +#define AFE_APLL2_TUNER_CFG (AFE_BASE + 0x03f4) +#define AFE_GAIN1_CON0 (AFE_BASE + 0x0410) +#define AFE_GAIN1_CON1 (AFE_BASE + 0x0414) +#define AFE_GAIN1_CON2 (AFE_BASE + 0x0418) +#define AFE_GAIN1_CON3 (AFE_BASE + 0x041c) +#define AFE_GAIN1_CONN (AFE_BASE + 0x0420) +#define AFE_GAIN1_CUR (AFE_BASE + 0x0424) +#define AFE_GAIN2_CON0 (AFE_BASE + 0x0428) +#define AFE_GAIN2_CON1 (AFE_BASE + 0x042c) +#define AFE_GAIN2_CON2 (AFE_BASE + 0x0430) +#define AFE_GAIN2_CON3 (AFE_BASE + 0x0434) +#define AFE_GAIN2_CONN (AFE_BASE + 0x0438) +#define AFE_GAIN2_CUR (AFE_BASE + 0x043C) +#define AFE_GAIN2_CONN2 (AFE_BASE + 0x0440) +#define AFE_GAIN2_CONN3 (AFE_BASE + 0x0444) +#define AFE_GAIN1_CONN2 (AFE_BASE + 0x0448) +#define AFE_GAIN1_CONN3 (AFE_BASE + 0x044C) +#define AFE_CONN7 (AFE_BASE + 0x0460) +#define AFE_CONN8 (AFE_BASE + 0x0464) +#define AFE_CONN9 (AFE_BASE + 0x0468) +#define AFE_CONN10 (AFE_BASE + 0x046C) +#define AFE_ASRC_CON0 (AFE_BASE + 0x500) +#define AFE_ASRC_CON1 (AFE_BASE + 0x504) +#define AFE_ASRC_CON2 (AFE_BASE + 0x508) +#define AFE_ASRC_CON3 (AFE_BASE + 0x50C) +#define AFE_ASRC_CON4 (AFE_BASE + 0x510) +#define AFE_ASRC_CON5 (AFE_BASE + 0x514) +#define AFE_ASRC_CON6 (AFE_BASE + 0x518) +#define AFE_ASRC_CON7 (AFE_BASE + 0x51C) +#define AFE_ASRC_CON8 (AFE_BASE + 0x520) +#define AFE_ASRC_CON9 (AFE_BASE + 0x524) +#define AFE_ASRC_CON10 (AFE_BASE + 0x528) +#define AFE_ASRC_CON11 (AFE_BASE + 0x52C) + +#define PCM_INTF_CON1 (AFE_BASE + 0x0530) +#define PCM_INTF_CON2 (AFE_BASE + 0x0538) +#define PCM2_INTF_CON (AFE_BASE + 0x053c) +#define AFE_ASRC_CON13 (AFE_BASE + 0x0550) +#define AFE_ASRC_CON14 (AFE_BASE + 0x0554) +#define AFE_ASRC_CON15 (AFE_BASE + 0x0558) +#define AFE_ASRC_CON16 (AFE_BASE + 0x055c) +#define AFE_ASRC_CON17 (AFE_BASE + 0x0560) +#define AFE_ASRC_CON18 (AFE_BASE + 0x0564) +#define AFE_ASRC_CON19 (AFE_BASE + 0x0568) +#define AFE_ASRC_CON20 (AFE_BASE + 0x056c) +#define AFE_ASRC_CON21 (AFE_BASE + 0x0570) + +#define CLK_AUDDIV_0 (AFE_BASE+0x005A0) +#define CLK_AUDDIV_1 (AFE_BASE+0x005A4) + +#define AFE_ASRC4_CON0 (AFE_BASE+0x06C0) +#define AFE_ASRC4_CON1 (AFE_BASE+0x06C4) +#define AFE_ASRC4_CON2 (AFE_BASE+0x06C8) +#define AFE_ASRC4_CON3 (AFE_BASE+0x06CC) +#define AFE_ASRC4_CON4 (AFE_BASE+0x06D0) +#define AFE_ASRC4_CON5 (AFE_BASE+0x06D4) +#define AFE_ASRC4_CON6 (AFE_BASE+0x06D8) +#define AFE_ASRC4_CON7 (AFE_BASE+0x06DC) +#define AFE_ASRC4_CON8 (AFE_BASE+0x06E0) +#define AFE_ASRC4_CON9 (AFE_BASE+0x06E4) +#define AFE_ASRC4_CON10 (AFE_BASE+0x06E8) +#define AFE_ASRC4_CON11 (AFE_BASE+0x06EC) +#define AFE_ASRC4_CON12 (AFE_BASE+0x06F0) +#define AFE_ASRC4_CON13 (AFE_BASE+0x06F4) +#define AFE_ASRC4_CON14 (AFE_BASE+0x06F8) + +/* Jade no */ +#define FPGA_CFG2 (AFE_BASE + 0x4B8) +#define FPGA_CFG3 (AFE_BASE + 0x4BC) +#define FPGA_CFG0 (AFE_BASE + 0x4C0) +#define FPGA_CFG1 (AFE_BASE + 0x4C4) +#define FPGA_VER (AFE_BASE + 0x4C8) +#define FPGA_STC (AFE_BASE + 0x4CC) +#define AFE_ASRC2_CON0 (AFE_BASE+0x0700) +#define AFE_ASRC2_CON1 (AFE_BASE+0x0704) +#define AFE_ASRC2_CON2 (AFE_BASE+0x0708) +#define AFE_ASRC2_CON3 (AFE_BASE+0x070C) +#define AFE_ASRC2_CON4 (AFE_BASE+0x0710) +#define AFE_ASRC2_CON5 (AFE_BASE+0x0714) +#define AFE_ASRC2_CON6 (AFE_BASE+0x0718) +#define AFE_ASRC2_CON7 (AFE_BASE+0x071C) +#define AFE_ASRC2_CON8 (AFE_BASE+0x0720) +#define AFE_ASRC2_CON9 (AFE_BASE+0x0724) +#define AFE_ASRC2_CON10 (AFE_BASE+0x0728) +#define AFE_ASRC2_CON11 (AFE_BASE+0x072C) +#define AFE_ASRC2_CON12 (AFE_BASE+0x0730) +#define AFE_ASRC2_CON13 (AFE_BASE+0x0734) +#define AFE_ASRC2_CON14 (AFE_BASE+0x0738) +#define AFE_ASRC3_CON0 (AFE_BASE+0x0740) +#define AFE_ASRC3_CON1 (AFE_BASE+0x0744) +#define AFE_ASRC3_CON2 (AFE_BASE+0x0748) +#define AFE_ASRC3_CON3 (AFE_BASE+0x074C) +#define AFE_ASRC3_CON4 (AFE_BASE+0x0750) +#define AFE_ASRC3_CON5 (AFE_BASE+0x0754) +#define AFE_ASRC3_CON6 (AFE_BASE+0x0758) +#define AFE_ASRC3_CON7 (AFE_BASE+0x075C) +#define AFE_ASRC3_CON8 (AFE_BASE+0x0760) +#define AFE_ASRC3_CON9 (AFE_BASE+0x0764) +#define AFE_ASRC3_CON10 (AFE_BASE+0x0768) +#define AFE_ASRC3_CON11 (AFE_BASE+0x076C) +#define AFE_ASRC3_CON12 (AFE_BASE+0x0770) +#define AFE_ASRC3_CON13 (AFE_BASE+0x0774) +#define AFE_ASRC3_CON14 (AFE_BASE+0x0778) +#define AFE_ADDA4_TOP_CON0 (AFE_BASE+0x0780) +#define AFE_ADDA4_UL_SRC_CON0 (AFE_BASE+0x0784) +#define AFE_ADDA4_UL_SRC_CON1 (AFE_BASE+0x0788) +#define AFE_ADDA4_SRC_DEBUG (AFE_BASE+0x078C) +#define AFE_ADDA4_SRC_DEBUG_MON0 (AFE_BASE+0x0790) +#define AFE_ADDA4_SRC_DEBUG_MON1 (AFE_BASE+0x0794) +#define AFE_ADDA4_NEWIF_CFG0 (AFE_BASE+0x0798) +#define AFE_ADDA4_NEWIF_CFG1 (AFE_BASE+0x079C) +#define AFE_ADDA4_ULCF_CFG_02_01 (AFE_BASE+0x07A0) +#define AFE_ADDA4_ULCF_CFG_04_03 (AFE_BASE+0x07A4) +#define AFE_ADDA4_ULCF_CFG_06_05 (AFE_BASE+0x07A8) +#define AFE_ADDA4_ULCF_CFG_08_07 (AFE_BASE+0x07AC) +#define AFE_ADDA4_ULCF_CFG_10_09 (AFE_BASE+0x07B0) +#define AFE_ADDA4_ULCF_CFG_12_11 (AFE_BASE+0x07B4) +#define AFE_ADDA4_ULCF_CFG_14_13 (AFE_BASE+0x07B8) +#define AFE_ADDA4_ULCF_CFG_16_15 (AFE_BASE+0x07BC) +#define AFE_ADDA4_ULCF_CFG_18_17 (AFE_BASE+0x07C0) +#define AFE_ADDA4_ULCF_CFG_20_19 (AFE_BASE+0x07C4) +#define AFE_ADDA4_ULCF_CFG_22_21 (AFE_BASE+0x07C8) +#define AFE_ADDA4_ULCF_CFG_24_23 (AFE_BASE+0x07CC) +#define AFE_ADDA4_ULCF_CFG_26_25 (AFE_BASE+0x07D0) +#define AFE_ADDA4_ULCF_CFG_28_27 (AFE_BASE+0x07D4) +#define AFE_ADDA4_ULCF_CFG_30_29 (AFE_BASE+0x07D8) + +#define AFE_MAXLENGTH (AFE_BASE+0x07D8) +#define AFE_REG_UNDEFINED (AFE_MAXLENGTH + 0x1) + +/* do afe register ioremap */ +void Auddrv_Reg_map(void); + +void Afe_Set_Reg(uint32 offset, uint32 value, uint32 mask); +uint32 Afe_Get_Reg(uint32 offset); + +/* function to Set Cfg */ +uint32 GetClkCfg(uint32 offset); +void SetClkCfg(uint32 offset, uint32 value, uint32 mask); + +/* function to Set Infra Cfg */ +uint32 GetInfraCfg(uint32 offset); +void SetInfraCfg(uint32 offset, uint32 value, uint32 mask); + +/* function to Set pll */ +uint32 GetpllCfg(uint32 offset); +void SetpllCfg(uint32 offset, uint32 value, uint32 mask); + +/* function to apmixed */ +uint32 GetApmixedCfg(uint32 offset); +void SetApmixedCfg(uint32 offset, uint32 value, uint32 mask); + + +/* for debug usage */ +void Afe_Log_Print(void); + +/* function to get pointer */ +unsigned int Get_Afe_Sram_Length(void); +dma_addr_t Get_Afe_Sram_Phys_Addr(void); +dma_addr_t Get_Afe_Sram_Capture_Phys_Addr(void); +void *Get_Afe_SramBase_Pointer(void); +void *Get_Afe_SramCaptureBase_Pointer(void); + +void *Get_Afe_Powertop_Pointer(void); +void *Get_AudClk_Pointer(void); +void *Get_Afe_Infra_Pointer(void); + +void SetChipModemPcmConfig(int modem_index, AudioDigitalPCM p_modem_pcm_attribute); +bool SetChipModemPcmEnable(int modem_index, bool modem_pcm_on); +bool SetI2SASRCConfig(bool bIsUseASRC, unsigned int dToSampleRate); +bool SetI2SASRCEnable(bool bEnable); +bool EnableSideToneFilter(bool stf_on); +bool CleanPreDistortion(void); +bool SetDLSrc2(uint32 SampleRate); + +bool SetSampleRate(uint32 Aud_block, uint32 SampleRate); +bool SetChannels(uint32 Memory_Interface, uint32 channel); +int SetMemifMonoSel(uint32 Memory_Interface, bool mono_use_r_ch); + +bool SetMemDuplicateWrite(uint32 InterfaceType, int dupwrite); + +ssize_t AudDrv_Reg_Dump(char *buffer, int size); + +#endif diff --git a/sound/soc/mediatek/mt6755/AudDrv_Clk.c b/sound/soc/mediatek/mt6755/AudDrv_Clk.c new file mode 100644 index 0000000000000000000000000000000000000000..78e9d2453f4a75181b798ded2b2fb03a5ed3b49f --- /dev/null +++ b/sound/soc/mediatek/mt6755/AudDrv_Clk.c @@ -0,0 +1,2150 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + * + * 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. + * You should have received a copy of the GNU General Public License + * along with this program + * If not, see . + */ +/******************************************************************************* + * + * Filename: + * --------- + * AudDrv_Clk.c + * + * Project: + * -------- + * MT6757 Audio Driver clock control implement + * + * Description: + * ------------ + * Audio register + * + * Author: + * ------- + * Chipeng Chang (MTK02308) + * + *------------------------------------------------------------------------------ + * + * + *******************************************************************************/ + + +/***************************************************************************** + * C O M P I L E R F L A G S + *****************************************************************************/ + + +/***************************************************************************** + * E X T E R N A L R E F E R E N C E S + *****************************************************************************/ + +#ifndef CONFIG_MTK_CLKMGR +#include +#else +#include +#endif + +/*#include */ +/*#include +#include +#include */ + +#include "AudDrv_Common.h" +#include "AudDrv_Clk.h" +#include "AudDrv_Afe.h" +#include "mt_soc_digital_type.h" + +#include +#include +#ifdef _MT_IDLE_HEADER +#include "mt_idle.h" +#include "mt_clk_id.h" +#endif +#include +#include + +/* do not BUG on during FPGA or CCF not ready*/ +#ifdef CONFIG_FPGA_EARLY_PORTING +#ifdef BUG +#undef BUG +#define BUG() +#endif +#endif + +/***************************************************************************** + * D A T A T Y P E S + *****************************************************************************/ + +static int APLL1Counter; +static int APLL2Counter; +static int Aud_APLL_DIV_APLL1_cntr; +static int Aud_APLL_DIV_APLL2_cntr; +static unsigned int MCLKFS = 128; +static unsigned int MCLKFS_HDMI = 256; + +int Aud_Core_Clk_cntr = 0; +int Aud_AFE_Clk_cntr = 0; +int Aud_I2S_Clk_cntr = 0; +int Aud_ADC_Clk_cntr = 0; +int Aud_ADC2_Clk_cntr = 0; +int Aud_ADC3_Clk_cntr = 0; +int Aud_ANA_Clk_cntr = 0; +#ifdef MT6757_READY +int Aud_HDMI_Clk_cntr = 0; +#endif +int Aud_APLL22M_Clk_cntr = 0; +int Aud_APLL24M_Clk_cntr = 0; +int Aud_APLL1_Tuner_cntr = 0; +int Aud_APLL2_Tuner_cntr = 0; +static int Aud_EMI_cntr; + +static DEFINE_SPINLOCK(auddrv_Clk_lock); + +/* amp mutex lock */ +static DEFINE_MUTEX(auddrv_pmic_mutex); +static DEFINE_MUTEX(audEMI_Clk_mutex); + +/* AUDIO_APLL_DIVIDER_GROUP may vary by chip!!! */ +typedef enum { + AUDIO_APLL1_DIV0, + AUDIO_APLL2_DIV0, + AUDIO_APLL12_DIV1, + AUDIO_APLL12_DIV2, + AUDIO_APLL12_DIV3, + AUDIO_APLL12_DIV4, + AUDIO_APLL12_DIVB, + AUDIO_APLL_DIV_NUM +} AUDIO_APLL_DIVIDER_GROUP; + +/* mI2SAPLLDivSelect may vary by chip!!! */ +static const uint32 mI2SAPLLDivSelect[Soc_Aud_I2S_CLKDIV_NUMBER] = { + AUDIO_APLL1_DIV0, + AUDIO_APLL2_DIV0, + AUDIO_APLL12_DIV1, + AUDIO_APLL12_DIV2, + AUDIO_APLL12_DIV3, + AUDIO_APLL12_DIV4, + AUDIO_APLL12_DIVB +}; + +enum audio_system_clock_type { + CLOCK_AFE = 0, + CLOCK_I2S, + CLOCK_DAC, + CLOCK_DAC_PREDIS, + CLOCK_ADC, + CLOCK_TML, + CLOCK_APLL22M, + CLOCK_APLL24M, + CLOCK_APLL1_TUNER, + CLOCK_APLL2_TUNER, + CLOCK_SCP_SYS_AUD, + CLOCK_INFRA_SYS_AUDIO, + CLOCK_PERI_AUDIO26M, + CLOCK_TOP_AUD_MUX1, + CLOCK_TOP_AUD_MUX2, + CLOCK_TOP_AD_APLL1_CK, + CLOCK_TOP_AD_APLL2_CK, + CLOCK_MUX_AUDIOINTBUS, + CLOCK_TOP_SYSPLL1_D4, + CLOCK_APMIXED_APLL1_CK, + CLOCK_APMIXED_APLL2_CK, + CLOCK_CLK26M, + CLOCK_NUM +}; + +struct audio_clock_attr { + const char *name; + bool clk_prepare; + bool clk_status; + struct clk *clock; +}; + +static struct audio_clock_attr aud_clks[CLOCK_NUM] = { + [CLOCK_AFE] = {"aud_afe_clk", false, false, NULL}, + [CLOCK_I2S] = {"aud_i2s_clk", false, false, NULL}, + [CLOCK_DAC] = {"aud_dac_clk", false, false, NULL}, + [CLOCK_DAC_PREDIS] = {"aud_dac_predis_clk", false, false, NULL}, + [CLOCK_ADC] = {"aud_adc_clk", false, false, NULL}, + [CLOCK_TML] = {"aud_tml_clk", false, false, NULL}, + [CLOCK_APLL22M] = {"aud_apll22m_clk", false, false, NULL}, + [CLOCK_APLL24M] = {"aud_apll24m_clk", false, false, NULL}, + [CLOCK_APLL1_TUNER] = {"aud_apll1_tuner_clk", false, false, NULL}, + [CLOCK_APLL2_TUNER] = {"aud_apll2_tuner_clk", false, false, NULL}, + [CLOCK_SCP_SYS_AUD] = {"scp_sys_aud", false, false, NULL}, + [CLOCK_INFRA_SYS_AUDIO] = {"aud_infra_clk", false, false, NULL}, + [CLOCK_PERI_AUDIO26M] = {"aud_peri_26m_clk", false, false, NULL}, + [CLOCK_TOP_AUD_MUX1] = {"aud_mux1_clk", false, false, NULL}, + [CLOCK_TOP_AUD_MUX2] = {"aud_mux2_clk", false, false, NULL}, + [CLOCK_TOP_AD_APLL1_CK] = {"top_ad_apll1_clk", false, false, NULL}, + [CLOCK_TOP_AD_APLL2_CK] = {"top_ad_apll2_clk", false, false, NULL}, + [CLOCK_MUX_AUDIOINTBUS] = {"top_mux_audio_int", false, false, NULL}, + [CLOCK_TOP_SYSPLL1_D4] = {"top_sys_pll1_d4", false, false, NULL}, + [CLOCK_APMIXED_APLL1_CK] = {"apmixed_apll1_clk", false, false, NULL}, + [CLOCK_APMIXED_APLL2_CK] = {"apmixed_apll2_clk", false, false, NULL}, + [CLOCK_CLK26M] = {"top_clk26m_clk", false, false, NULL} +}; + +int AudDrv_Clk_probe(void *dev) +{ + size_t i; + int ret = 0; + + Aud_EMI_cntr = 0; + + pr_debug("%s\n", __func__); + + for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { + aud_clks[i].clock = devm_clk_get(dev, aud_clks[i].name); + if (IS_ERR(aud_clks[i].clock)) { + ret = PTR_ERR(aud_clks[i].clock); + pr_err("%s devm_clk_get %s fail %d\n", __func__, aud_clks[i].name, ret); + break; + } + aud_clks[i].clk_status = true; + } + + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { + if (i == CLOCK_SCP_SYS_AUD) /* CLOCK_SCP_SYS_AUD is MTCMOS */ + continue; + + if (aud_clks[i].clk_status) { + ret = clk_prepare(aud_clks[i].clock); + if (ret) { + pr_err("%s clk_prepare %s fail %d\n", + __func__, aud_clks[i].name, ret); + break; + } + aud_clks[i].clk_prepare = true; + } + } + + return ret; +} + +void AudDrv_Clk_Deinit(void *dev) +{ + size_t i; + + pr_debug("%s\n", __func__); + for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { + if (i == CLOCK_SCP_SYS_AUD) /* CLOCK_SCP_SYS_AUD is MTCMOS */ + continue; + + if (aud_clks[i].clock && !IS_ERR(aud_clks[i].clock) && aud_clks[i].clk_prepare) { + clk_unprepare(aud_clks[i].clock); + aud_clks[i].clk_prepare = false; + } + } +} + +void AudDrv_Clk_Global_Variable_Init(void) +{ + APLL1Counter = 0; + APLL2Counter = 0; + Aud_APLL_DIV_APLL1_cntr = 0; + Aud_APLL_DIV_APLL2_cntr = 0; + MCLKFS = 128; + MCLKFS_HDMI = 256; +} + +void AudDrv_Bus_Init(void) +{ + unsigned long flags; + + pr_debug("%s\n", __func__); + spin_lock_irqsave(&auddrv_Clk_lock, flags); + Afe_Set_Reg(AUDIO_TOP_CON0, 0x00004000, + 0x00004000); /* must set, system will default set bit14 to 0 */ + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} + + +/***************************************************************************** + * FUNCTION + * AudDrv_Clk_Power_On / AudDrv_Clk_Power_Off + * + * DESCRIPTION + * Power on this function , then all register can be access and set. + * + ***************************************************************************** + */ + +void AudDrv_Clk_Power_On(void) +{ + /*volatile uint32 *AFE_Register = (volatile uint32 *)Get_Afe_Powertop_Pointer();*/ + volatile uint32 val_tmp; + + pr_debug("%s", __func__); +#ifdef MT6757_READY + val_tmp = 0x3330000d; +#endif + val_tmp = 0xd; + /*mt_reg_sync_writel(val_tmp, AFE_Register);*/ +} + +void AudDrv_Clk_Power_Off(void) +{ +} + +/***************************************************************************** + * FUNCTION + * AudDrv_Clk_On / AudDrv_Clk_Off + * + * DESCRIPTION + * Enable/Disable PLL(26M clock) \ AFE clock + * + ***************************************************************************** +*/ + +void AudDrv_AUDINTBUS_Sel(int parentidx) +{ + int ret = 0; + + if (parentidx == 1) { + if (aud_clks[CLOCK_MUX_AUDIOINTBUS].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock CLOCK_MUX_AUDIOINTBUS fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock CLOCK_MUX_AUDIOINTBUS fail", + __func__); + BUG(); + goto EXIT; + } + + ret = clk_set_parent(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock, + aud_clks[CLOCK_TOP_SYSPLL1_D4].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_MUX_AUDIOINTBUS].name, + aud_clks[CLOCK_TOP_SYSPLL1_D4].name, ret); + BUG(); + goto EXIT; + } + } else if (parentidx == 0) { + if (aud_clks[CLOCK_MUX_AUDIOINTBUS].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock CLOCK_MUX_AUDIOINTBUS fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock CLOCK_MUX_AUDIOINTBUS fail", + __func__); + BUG(); + goto EXIT; + } + + ret = clk_set_parent(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock, + aud_clks[CLOCK_CLK26M].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_MUX_AUDIOINTBUS].name, + aud_clks[CLOCK_CLK26M].name, ret); + BUG(); + goto EXIT; + } + } +EXIT: + pr_debug("-%s()\n", __func__); +} + + +/***************************************************************************** + * FUNCTION + * AudDrv_AUD_Sel + * + * DESCRIPTION + * TOP_MUX_AUDIO select source + * + ***************************************************************************** +*/ + +void AudDrv_AUD_Sel(int parentidx) +{ + /* Keep for extension */ +} + +void AudDrv_Clk_On(void) +{ + unsigned long flags; + int ret = 0; + + PRINTK_AUD_CLK("+AudDrv_Clk_On, Aud_AFE_Clk_cntr:%d\n", Aud_AFE_Clk_cntr); + spin_lock_irqsave(&auddrv_Clk_lock, flags); + Aud_AFE_Clk_cntr++; + if (Aud_AFE_Clk_cntr == 1) { +#ifdef PM_MANAGER_API + if (aud_clks[CLOCK_INFRA_SYS_AUDIO].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_INFRA_SYS_AUDIO].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock %s fail\n", __func__, + aud_clks[CLOCK_INFRA_SYS_AUDIO].name); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock MT_CG_INFRA_AUDIO fail\n", + __func__); + BUG(); + goto EXIT; + } + /* MT6755 CLOCK_PERI_AUDIO26M + if (aud_clks[CLOCK_INFRA_SYS_AUDIO_26M].clk_prepare) { +*/ + if (aud_clks[CLOCK_PERI_AUDIO26M].clk_prepare) { + + /* MT6755 CLOCK_PERI_AUDIO26M + ret = clk_enable(aud_clks[CLOCK_INFRA_SYS_AUDIO_26M].clock); + */ + ret = clk_enable(aud_clks[CLOCK_PERI_AUDIO26M].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock %s fail\n", __func__, + /* MT6755 CLOCK_PERI_AUDIO26M + aud_clks[CLOCK_INFRA_SYS_AUDIO_26M].name); + */ + aud_clks[CLOCK_PERI_AUDIO26M].name); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock CLOCK_INFRA_SYS_AUDIO_26M fail\n", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_AFE].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_AFE].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock %s fail\n", __func__, + aud_clks[CLOCK_AFE].name); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock MT_CG_AUDIO_AFE fail\n", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_DAC].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_DAC].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock MT_CG_AUDIO_DAC fail\n", __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_status error Aud enable_clock MT_CG_AUDIO_DAC fail\n", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_DAC_PREDIS].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_DAC_PREDIS].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock MT_CG_AUDIO_DAC_PREDIS fail\n", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err + ("%s [CCF]clk_status error Aud enable_clock MT_CG_AUDIO_DAC_PREDIS fail\n", + __func__); + BUG(); + goto EXIT; + } + + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); + /* CLOCK_SCP_SYS_AUD is MTCMOS */ + if (aud_clks[CLOCK_SCP_SYS_AUD].clk_status) { + ret = clk_prepare_enable(aud_clks[CLOCK_SCP_SYS_AUD].clock); + if (ret) { + pr_err("%s [CCF]Aud clk_prepare_enable %s fail\n", __func__, + aud_clks[CLOCK_SCP_SYS_AUD].name); + BUG(); + goto EXIT_SKIP_UNLOCK; + } + } + + goto EXIT_SKIP_UNLOCK; +#else + SetInfraCfg(AUDIO_CG_CLR, 0x2000000, 0x2000000); + /* bit 25=0, without 133m master and 66m slave bus clock cg gating */ + Afe_Set_Reg(AUDIO_TOP_CON0, 0x4000, 0x06004044); +#endif + } +EXIT: + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +EXIT_SKIP_UNLOCK: + PRINTK_AUD_CLK("-AudDrv_Clk_On, Aud_AFE_Clk_cntr:%d\n", Aud_AFE_Clk_cntr); +} +EXPORT_SYMBOL(AudDrv_Clk_On); + +void AudDrv_Clk_Off(void) +{ + unsigned long flags; + + PRINTK_AUD_CLK("+!! AudDrv_Clk_Off, Aud_AFE_Clk_cntr:%d\n", Aud_AFE_Clk_cntr); + spin_lock_irqsave(&auddrv_Clk_lock, flags); + + Aud_AFE_Clk_cntr--; + if (Aud_AFE_Clk_cntr == 0) { + /* Disable AFE clock */ +#ifdef PM_MANAGER_API + /* Make sure all IRQ status is cleared */ + Afe_Set_Reg(AFE_IRQ_MCU_CLR, 0xffff, 0xffff); + + if (aud_clks[CLOCK_AFE].clk_prepare) + clk_disable(aud_clks[CLOCK_AFE].clock); + + if (aud_clks[CLOCK_DAC].clk_prepare) + clk_disable(aud_clks[CLOCK_DAC].clock); + + if (aud_clks[CLOCK_DAC_PREDIS].clk_prepare) + clk_disable(aud_clks[CLOCK_DAC_PREDIS].clock); + /* Disable 26M here? + if (aud_clks[CLOCK_INFRA_SYS_AUDIO_26M].clk_prepare) + clk_disable(aud_clks[CLOCK_INFRA_SYS_AUDIO_26M].clock); + */ + if (aud_clks[CLOCK_INFRA_SYS_AUDIO].clk_prepare) + clk_disable(aud_clks[CLOCK_INFRA_SYS_AUDIO].clock); + + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); + /* CLOCK_SCP_SYS_AUD is MTCMOS */ + if (aud_clks[CLOCK_SCP_SYS_AUD].clk_status) + clk_disable_unprepare(aud_clks[CLOCK_SCP_SYS_AUD].clock); + + if (aud_clks[CLOCK_PERI_AUDIO26M].clk_prepare) + clk_disable(aud_clks[CLOCK_PERI_AUDIO26M].clock); + + goto EXIT_SKIP_UNLOCK; +#else + Afe_Set_Reg(AUDIO_TOP_CON0, 0x06000044, 0x06000044); + SetInfraCfg(AUDIO_CG_SET, 0x2000000, 0x2000000); + /* bit25=1, with 133m mastesr and 66m slave bus clock cg gating */ +#endif + } else if (Aud_AFE_Clk_cntr < 0) { + PRINTK_AUD_ERROR("!! AudDrv_Clk_Off, Aud_AFE_Clk_cntr<0 (%d)\n", + Aud_AFE_Clk_cntr); + AUDIO_ASSERT(true); + Aud_AFE_Clk_cntr = 0; + } + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +EXIT_SKIP_UNLOCK: + PRINTK_AUD_CLK("-!! AudDrv_Clk_Off, Aud_AFE_Clk_cntr:%d\n", Aud_AFE_Clk_cntr); +} +EXPORT_SYMBOL(AudDrv_Clk_Off); + + +/***************************************************************************** + * FUNCTION + * AudDrv_ANA_Clk_On / AudDrv_ANA_Clk_Off + * + * DESCRIPTION + * Enable/Disable analog part clock + * + *****************************************************************************/ +void AudDrv_ANA_Clk_On(void) +{ + mutex_lock(&auddrv_pmic_mutex); + if (Aud_ANA_Clk_cntr == 0) + PRINTK_AUD_CLK("+AudDrv_ANA_Clk_On, Aud_ANA_Clk_cntr:%d\n", Aud_ANA_Clk_cntr); + + Aud_ANA_Clk_cntr++; + mutex_unlock(&auddrv_pmic_mutex); + /* PRINTK_AUD_CLK("-AudDrv_ANA_Clk_Off, Aud_ANA_Clk_cntr:%d\n",Aud_ANA_Clk_cntr); */ +} +EXPORT_SYMBOL(AudDrv_ANA_Clk_On); + +void AudDrv_ANA_Clk_Off(void) +{ + /* PRINTK_AUD_CLK("+AudDrv_ANA_Clk_Off, Aud_ADC_Clk_cntr:%d\n", Aud_ANA_Clk_cntr); */ + mutex_lock(&auddrv_pmic_mutex); + Aud_ANA_Clk_cntr--; + if (Aud_ANA_Clk_cntr == 0) { + PRINTK_AUD_CLK("+AudDrv_ANA_Clk_Off disable_clock Ana clk(%x)\n", + Aud_ANA_Clk_cntr); + /* Disable ADC clock */ +#ifdef PM_MANAGER_API + +#else + /* TODO:: open ADC clock.... */ +#endif + } else if (Aud_ANA_Clk_cntr < 0) { + PRINTK_AUD_ERROR("!! AudDrv_ANA_Clk_Off, Aud_ADC_Clk_cntr<0 (%d)\n", + Aud_ANA_Clk_cntr); + AUDIO_ASSERT(true); + Aud_ANA_Clk_cntr = 0; + } + mutex_unlock(&auddrv_pmic_mutex); + /* PRINTK_AUD_CLK("-AudDrv_ANA_Clk_Off, Aud_ADC_Clk_cntr:%d\n", Aud_ANA_Clk_cntr); */ +} +EXPORT_SYMBOL(AudDrv_ANA_Clk_Off); + +/***************************************************************************** + * FUNCTION + * AudDrv_ADC_Clk_On / AudDrv_ADC_Clk_Off + * + * DESCRIPTION + * Enable/Disable analog part clock + * + *****************************************************************************/ + +void AudDrv_ADC_Clk_On(void) +{ + /* PRINTK_AUDDRV("+AudDrv_ADC_Clk_On, Aud_ADC_Clk_cntr:%d\n", Aud_ADC_Clk_cntr); */ + int ret = 0; + + mutex_lock(&auddrv_pmic_mutex); + + if (Aud_ADC_Clk_cntr == 0) { + PRINTK_AUDDRV("+AudDrv_ADC_Clk_On enable_clock ADC clk(%x)\n", + Aud_ADC_Clk_cntr); + /* Afe_Set_Reg(AUDIO_TOP_CON0, 0 << 24 , 1 << 24); */ +#ifdef PM_MANAGER_API + if (aud_clks[CLOCK_ADC].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_ADC].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock enable_clock ADC fail", __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock ADC fail", __func__); + BUG(); + goto EXIT; + } +#else + Afe_Set_Reg(AUDIO_TOP_CON0, 0 << 24, 1 << 24); +#endif + } + Aud_ADC_Clk_cntr++; +EXIT: + mutex_unlock(&auddrv_pmic_mutex); +} + +void AudDrv_ADC_Clk_Off(void) +{ + /* PRINTK_AUDDRV("+AudDrv_ADC_Clk_Off, Aud_ADC_Clk_cntr:%d\n", Aud_ADC_Clk_cntr); */ + mutex_lock(&auddrv_pmic_mutex); + Aud_ADC_Clk_cntr--; + if (Aud_ADC_Clk_cntr == 0) { + PRINTK_AUDDRV("+AudDrv_ADC_Clk_On disable_clock ADC clk(%x)\n", + Aud_ADC_Clk_cntr); +#ifdef PM_MANAGER_API + if (aud_clks[CLOCK_ADC].clk_prepare) + clk_disable(aud_clks[CLOCK_ADC].clock); +#else + Afe_Set_Reg(AUDIO_TOP_CON0, 1 << 24, 1 << 24); +#endif + } + if (Aud_ADC_Clk_cntr < 0) { + PRINTK_AUDDRV("!! AudDrv_ADC_Clk_Off, Aud_ADC_Clk_cntr<0 (%d)\n", + Aud_ADC_Clk_cntr); + Aud_ADC_Clk_cntr = 0; + } + mutex_unlock(&auddrv_pmic_mutex); + /* PRINTK_AUDDRV("-AudDrv_ADC_Clk_Off, Aud_ADC_Clk_cntr:%d\n", Aud_ADC_Clk_cntr); */ +} + +/***************************************************************************** + * FUNCTION + * AudDrv_ADC2_Clk_On / AudDrv_ADC2_Clk_Off + * + * DESCRIPTION + * Enable/Disable clock + * + *****************************************************************************/ + +void AudDrv_ADC2_Clk_On(void) +{ + PRINTK_AUD_CLK("+%s %d\n", __func__, Aud_ADC2_Clk_cntr); + mutex_lock(&auddrv_pmic_mutex); + + if (Aud_ADC2_Clk_cntr == 0) + PRINTK_AUDDRV("+%s enable_clock ADC2 clk(%x)\n", __func__, Aud_ADC2_Clk_cntr); + + Aud_ADC2_Clk_cntr++; + + mutex_unlock(&auddrv_pmic_mutex); +} + +void AudDrv_ADC2_Clk_Off(void) +{ + /* PRINTK_AUDDRV("+%s %d\n", __func__,Aud_ADC2_Clk_cntr); */ + mutex_lock(&auddrv_pmic_mutex); + Aud_ADC2_Clk_cntr--; + if (Aud_ADC2_Clk_cntr == 0) + PRINTK_AUDDRV("+%s disable_clock ADC clk(%x)\n", __func__, Aud_ADC2_Clk_cntr); + + + if (Aud_ADC2_Clk_cntr < 0) { + PRINTK_AUDDRV("%s <0 (%d)\n", __func__, Aud_ADC2_Clk_cntr); + Aud_ADC2_Clk_cntr = 0; + } + mutex_unlock(&auddrv_pmic_mutex); + /* PRINTK_AUDDRV("-AudDrv_ADC_Clk_Off, Aud_ADC_Clk_cntr:%d\n", Aud_ADC_Clk_cntr); */ +} + + +/***************************************************************************** + * FUNCTION + * AudDrv_ADC3_Clk_On / AudDrv_ADC3_Clk_Off + * + * DESCRIPTION + * Enable/Disable clock + * + *****************************************************************************/ + +void AudDrv_ADC3_Clk_On(void) +{ + PRINTK_AUD_CLK("+%s %d\n", __func__, Aud_ADC3_Clk_cntr); + mutex_lock(&auddrv_pmic_mutex); + + if (Aud_ADC3_Clk_cntr == 0) + PRINTK_AUDDRV("+%s enable_clock ADC clk(%x)\n", __func__, Aud_ADC3_Clk_cntr); + + Aud_ADC3_Clk_cntr++; + mutex_unlock(&auddrv_pmic_mutex); +} + +void AudDrv_ADC3_Clk_Off(void) +{ + /* PRINTK_AUDDRV("+%s %d\n", __func__,Aud_ADC2_Clk_cntr); */ + mutex_lock(&auddrv_pmic_mutex); + Aud_ADC3_Clk_cntr--; + + if (Aud_ADC3_Clk_cntr == 0) + PRINTK_AUDDRV("+%s disable_clock ADC clk(%x)\n", __func__, Aud_ADC3_Clk_cntr); + + + if (Aud_ADC3_Clk_cntr < 0) { + PRINTK_AUDDRV("%s <0 (%d)\n", __func__, Aud_ADC3_Clk_cntr); + Aud_ADC3_Clk_cntr = 0; + } + + mutex_unlock(&auddrv_pmic_mutex); + /* PRINTK_AUDDRV("-AudDrv_ADC_Clk_Off, Aud_ADC_Clk_cntr:%d\n", Aud_ADC_Clk_cntr); */ +} + +/***************************************************************************** + * FUNCTION + * AudDrv_ADC_Hires_Clk_On / AudDrv_ADC_Hires_Clk_Off + * + * DESCRIPTION + * Enable/Disable analog part clock + * + *****************************************************************************/ + +void AudDrv_ADC_Hires_Clk_On(void) +{ + /* No Hires Clk in mt6757 */ +} + +void AudDrv_ADC_Hires_Clk_Off(void) +{ + /* No Hires Clk in mt6757 */ +} + + +/***************************************************************************** + * FUNCTION + * AudDrv_APLL22M_Clk_On / AudDrv_APLL22M_Clk_Off + * + * DESCRIPTION + * Enable/Disable clock + * + *****************************************************************************/ + +void AudDrv_APLL22M_Clk_On(void) +{ + int ret = 0; + + PRINTK_AUD_CLK("+%s counter = %d\n", __func__, Aud_APLL22M_Clk_cntr); + + mutex_lock(&auddrv_pmic_mutex); + + if (Aud_APLL22M_Clk_cntr == 0) { +#ifdef PM_MANAGER_API + /* pdn_aud_1 => power down hf_faud_1_ck, hf_faud_1_ck is mux of 26M and APLL1_CK */ + /* pdn_aud_2 => power down hf_faud_2_ck, hf_faud_2_ck is mux of 26M and APLL2_CK (D1 is WHPLL) */ + + if (aud_clks[CLOCK_TOP_AD_APLL1_CK].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_TOP_AD_APLL1_CK].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock CLOCK_TOP_AD_APLL1_CK fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud CLOCK_TOP_AD_APLL1_CK fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AUD_MUX1].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_TOP_AUD_MUX1].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock CLOCK_TOP_AUD_MUX1 fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock CLOCK_TOP_AUD_MUX1 fail", + __func__); + BUG(); + goto EXIT; + } + + ret = clk_set_parent(aud_clks[CLOCK_TOP_AUD_MUX1].clock, + aud_clks[CLOCK_TOP_AD_APLL1_CK].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_TOP_AUD_MUX1].name, + aud_clks[CLOCK_TOP_AD_APLL1_CK].name, ret); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_APMIXED_APLL1_CK].clk_prepare) { + + ret = clk_set_rate(aud_clks[CLOCK_APMIXED_APLL1_CK].clock, 180633600); + if (ret) { + pr_err("%s clk_set_rate %s-180633600 fail %d\n", + __func__, aud_clks[CLOCK_APMIXED_APLL1_CK].name, ret); + BUG(); + goto EXIT; + } + } + + if (aud_clks[CLOCK_APLL22M].clk_prepare) { + + ret = clk_enable(aud_clks[CLOCK_APLL22M].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock enable_clock aud_apll22m_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_apll22m_clk fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL1_TUNER].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_apll1_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_apll1_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + + +#endif + } + Aud_APLL22M_Clk_cntr++; +EXIT: + mutex_unlock(&auddrv_pmic_mutex); +} + +void AudDrv_APLL22M_Clk_Off(void) +{ + int ret = 0; + + PRINTK_AUD_CLK("+%s counter = %d\n", __func__, Aud_APLL22M_Clk_cntr); + + mutex_lock(&auddrv_pmic_mutex); + + Aud_APLL22M_Clk_cntr--; + + if (Aud_APLL22M_Clk_cntr == 0) { +#ifdef PM_MANAGER_API + if (aud_clks[CLOCK_APLL22M].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL22M].clock); + + if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL1_TUNER].clock); + + ret = clk_set_parent(aud_clks[CLOCK_TOP_AUD_MUX1].clock, + aud_clks[CLOCK_CLK26M].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_TOP_AUD_MUX1].name, + aud_clks[CLOCK_CLK26M].name, ret); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AUD_MUX1].clk_prepare) { + clk_disable(aud_clks[CLOCK_TOP_AUD_MUX1].clock); + pr_debug("%s [CCF]Aud clk_disable CLOCK_TOP_AUD_MUX1", + __func__); + + } else { + pr_err + ("%s [CCF]clk_prepare error clk_disable CLOCK_TOP_AUD_MUX1 fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AD_APLL1_CK].clk_prepare) { + clk_disable(aud_clks[CLOCK_TOP_AD_APLL1_CK].clock); + pr_debug("%s [CCF]Aud clk_disable CLOCK_TOP_AD_APLL1_CK", + __func__); + + } else { + pr_err + ("%s [CCF]clk_prepare error CLOCK_TOP_AD_APLL1_CK fail", + __func__); + BUG(); + goto EXIT; + } + +#endif + } + +EXIT: + if (Aud_APLL22M_Clk_cntr < 0) { + PRINTK_AUD_ERROR("err, %s <0 (%d)\n", __func__, + Aud_APLL22M_Clk_cntr); + Aud_APLL22M_Clk_cntr = 0; + } + mutex_unlock(&auddrv_pmic_mutex); +} + + +/***************************************************************************** + * FUNCTION + * AudDrv_APLL24M_Clk_On / AudDrv_APLL24M_Clk_Off + * + * DESCRIPTION + * Enable/Disable clock + * + *****************************************************************************/ + +void AudDrv_APLL24M_Clk_On(void) +{ + int ret = 0; + + PRINTK_AUD_CLK("+%s counter = %d\n", __func__, Aud_APLL24M_Clk_cntr); + + mutex_lock(&auddrv_pmic_mutex); + + if (Aud_APLL24M_Clk_cntr == 0) { +#ifdef PM_MANAGER_API + if (aud_clks[CLOCK_TOP_AD_APLL2_CK].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_TOP_AD_APLL2_CK].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock CLOCK_TOP_AD_APLL2_CK fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud CLOCK_TOP_AD_APLL2_CK fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AUD_MUX2].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_TOP_AUD_MUX2].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock CLOCK_TOP_AUD_MUX2 fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock CLOCK_TOP_AUD_MUX2 fail", + __func__); + BUG(); + goto EXIT; + } + + ret = clk_set_parent(aud_clks[CLOCK_TOP_AUD_MUX2].clock, + aud_clks[CLOCK_TOP_AD_APLL2_CK].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_TOP_AUD_MUX2].name, + aud_clks[CLOCK_TOP_AD_APLL2_CK].name, ret); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_APMIXED_APLL2_CK].clk_prepare) { + + ret = clk_set_rate(aud_clks[CLOCK_APMIXED_APLL2_CK].clock, 196607998); + if (ret) { + pr_err("%s clk_set_rate %s-196607998 fail %d\n", + __func__, aud_clks[CLOCK_APMIXED_APLL2_CK].name, ret); + BUG(); + goto EXIT; + } + } + + if (aud_clks[CLOCK_APLL24M].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL24M].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock enable_clock aud_apll24m_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_apll24m_clk fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_APLL2_TUNER].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL2_TUNER].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_apll2_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_apll2_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } +#endif + } + Aud_APLL24M_Clk_cntr++; +EXIT: + mutex_unlock(&auddrv_pmic_mutex); +} + +void AudDrv_APLL24M_Clk_Off(void) +{ + int ret = 0; + + PRINTK_AUD_CLK("+%s counter = %d\n", __func__, Aud_APLL24M_Clk_cntr); + + mutex_lock(&auddrv_pmic_mutex); + + Aud_APLL24M_Clk_cntr--; + + if (Aud_APLL24M_Clk_cntr == 0) { +#ifdef PM_MANAGER_API + if (aud_clks[CLOCK_APLL24M].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL24M].clock); + + if (aud_clks[CLOCK_APLL2_TUNER].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL2_TUNER].clock); + + ret = clk_set_parent(aud_clks[CLOCK_TOP_AUD_MUX2].clock, + aud_clks[CLOCK_CLK26M].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_TOP_AUD_MUX2].name, + aud_clks[CLOCK_CLK26M].name, ret); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AUD_MUX2].clk_prepare) { + clk_disable(aud_clks[CLOCK_TOP_AUD_MUX2].clock); + + pr_err("%s [CCF]Aud clk_disable CLOCK_TOP_AUD_MUX2 fail", + __func__); + + } else { + pr_err + ("%s [CCF]clk_prepare error clk_disable CLOCK_TOP_AUD_MUX2 fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AD_APLL2_CK].clk_prepare) { + clk_disable(aud_clks[CLOCK_TOP_AD_APLL2_CK].clock); + pr_debug("%s [CCF]Aud clk_disable CLOCK_TOP_AD_APLL2_CK fail", + __func__); + + } else { + pr_err + ("%s [CCF]clk_prepare error CLOCK_TOP_AD_APLL2_CK fail", + __func__); + BUG(); + goto EXIT; + } + +#endif + } +EXIT: + if (Aud_APLL24M_Clk_cntr < 0) { + PRINTK_AUD_ERROR("%s <0 (%d)\n", __func__, + Aud_APLL24M_Clk_cntr); + Aud_APLL24M_Clk_cntr = 0; + } + + mutex_unlock(&auddrv_pmic_mutex); +} + +/***************************************************************************** + * FUNCTION + * AudDrv_I2S_Clk_On / AudDrv_I2S_Clk_Off + * + * DESCRIPTION + * Enable I2S In clock (bck) + * This should be enabled in slave i2s mode. + * + *****************************************************************************/ +void aud_top_con_pdn_i2s(bool _pdn) +{ + if (_pdn) + Afe_Set_Reg(AUDIO_TOP_CON0, 0x1 << 6, 0x1 << 6); /* power off I2S clock */ + else + Afe_Set_Reg(AUDIO_TOP_CON0, 0x0 << 6, 0x1 << 6); /* power on I2S clock */ +} + +void AudDrv_I2S_Clk_On(void) +{ + unsigned long flags; + + spin_lock_irqsave(&auddrv_Clk_lock, flags); + + if (Aud_I2S_Clk_cntr == 0) + aud_top_con_pdn_i2s(false); + + Aud_I2S_Clk_cntr++; + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} +EXPORT_SYMBOL(AudDrv_I2S_Clk_On); + +void AudDrv_I2S_Clk_Off(void) +{ + unsigned long flags; + + spin_lock_irqsave(&auddrv_Clk_lock, flags); + Aud_I2S_Clk_cntr--; + if (Aud_I2S_Clk_cntr == 0) { + aud_top_con_pdn_i2s(true); + } else if (Aud_I2S_Clk_cntr < 0) { + PRINTK_AUD_ERROR("!! AudDrv_I2S_Clk_Off, Aud_I2S_Clk_cntr<0 (%d)\n", + Aud_I2S_Clk_cntr); + AUDIO_ASSERT(true); + Aud_I2S_Clk_cntr = 0; + } + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} +EXPORT_SYMBOL(AudDrv_I2S_Clk_Off); + +/***************************************************************************** + * FUNCTION + * AudDrv_TDM_Clk_On / AudDrv_TDM_Clk_Off + * + * DESCRIPTION + * Enable/Disable TDM clock + * + *****************************************************************************/ +void aud_top_con_pdn_tdm_ck(bool _pdn) +{ + /* mt6757 no TDM */ +} + +void AudDrv_TDM_Clk_On(void) +{ + /* mt6757 no TDM */ +} +EXPORT_SYMBOL(AudDrv_TDM_Clk_On); + +void AudDrv_TDM_Clk_Off(void) +{ + /* mt6757 no TDM */ +} +EXPORT_SYMBOL(AudDrv_TDM_Clk_Off); + + +/***************************************************************************** + * FUNCTION + * AudDrv_Core_Clk_On / AudDrv_Core_Clk_Off + * + * DESCRIPTION + * Enable/Disable analog part clock + * + *****************************************************************************/ + +void AudDrv_Core_Clk_On(void) +{ + /* PRINTK_AUD_CLK("+AudDrv_Core_Clk_On, Aud_Core_Clk_cntr:%d\n", Aud_Core_Clk_cntr); */ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&auddrv_Clk_lock, flags); + if (Aud_Core_Clk_cntr == 0) { +#ifdef PM_MANAGER_API + if (aud_clks[CLOCK_AFE].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_AFE].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock enable_clock aud_afe_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_afe_clk fail", + __func__); + BUG(); + goto EXIT; + } +#endif + } + Aud_Core_Clk_cntr++; +EXIT: + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); + /* PRINTK_AUD_CLK("-AudDrv_Core_Clk_On, Aud_Core_Clk_cntr:%d\n", Aud_Core_Clk_cntr); */ +} + +void AudDrv_Core_Clk_Off(void) +{ + /* PRINTK_AUD_CLK("+AudDrv_Core_Clk_On, Aud_Core_Clk_cntr:%d\n", Aud_Core_Clk_cntr); */ + unsigned long flags; + + spin_lock_irqsave(&auddrv_Clk_lock, flags); + if (Aud_Core_Clk_cntr == 0) { +#ifdef PM_MANAGER_API + if (aud_clks[CLOCK_AFE].clk_prepare) + clk_disable(aud_clks[CLOCK_AFE].clock); +#endif + } + Aud_Core_Clk_cntr++; + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); + /* PRINTK_AUD_CLK("-AudDrv_Core_Clk_On, Aud_Core_Clk_cntr:%d\n", Aud_Core_Clk_cntr); */ +} + +void AudDrv_APLL1Tuner_Clk_On(void) +{ + unsigned long flags; +#ifndef CONFIG_MTK_CLKMGR + int ret = 0; +#endif + spin_lock_irqsave(&auddrv_Clk_lock, flags); + if (Aud_APLL1_Tuner_cntr == 0) { + PRINTK_AUD_CLK("+AudDrv_APLLTuner_Clk_On, Aud_APLL1_Tuner_cntr:%d\n", + Aud_APLL1_Tuner_cntr); +#ifdef CONFIG_MTK_CLKMGR + Afe_Set_Reg(AUDIO_TOP_CON0, 0x0 << 19, 0x1 << 19); +#else + if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL1_TUNER].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_apll1_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_apll1_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } +#endif + } + Aud_APLL1_Tuner_cntr++; +EXIT: + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} + +void AudDrv_APLL1Tuner_Clk_Off(void) +{ + unsigned long flags; + + spin_lock_irqsave(&auddrv_Clk_lock, flags); + + Aud_APLL1_Tuner_cntr--; + if (Aud_APLL1_Tuner_cntr == 0) { +#ifdef CONFIG_MTK_CLKMGR + Afe_Set_Reg(AUDIO_TOP_CON0, 0x1 << 19, 0x1 << 19); + /*Afe_Set_Reg(AFE_APLL1_TUNER_CFG, 0x00000033, 0x1 << 19);*/ +#else + if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL1_TUNER].clock); +#endif + } + /* handle for clock error */ + else if (Aud_APLL1_Tuner_cntr < 0) { + PRINTK_AUD_ERROR("!! AudDrv_APLLTuner_Clk_Off, Aud_APLL1_Tuner_cntr<0 (%d)\n", + Aud_APLL1_Tuner_cntr); + Aud_APLL1_Tuner_cntr = 0; + } + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} + + +void AudDrv_APLL2Tuner_Clk_On(void) +{ + unsigned long flags; +#ifndef CONFIG_MTK_CLKMGR + int ret = 0; +#endif + spin_lock_irqsave(&auddrv_Clk_lock, flags); + if (Aud_APLL2_Tuner_cntr == 0) { + PRINTK_AUD_CLK("+Aud_APLL2_Tuner_cntr, Aud_APLL2_Tuner_cntr:%d\n", + Aud_APLL2_Tuner_cntr); +#ifdef CONFIG_MTK_CLKMGR + Afe_Set_Reg(AUDIO_TOP_CON0, 0x0 << 18, 0x1 << 18); + /*Afe_Set_Reg(AFE_APLL2_TUNER_CFG, 0x00000033, 0x1 << 19);*/ +#else + if (aud_clks[CLOCK_APLL2_TUNER].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL2_TUNER].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_apll2_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_apll2_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } +#endif + } + Aud_APLL2_Tuner_cntr++; +EXIT: + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} + +void AudDrv_APLL2Tuner_Clk_Off(void) +{ + unsigned long flags; + + spin_lock_irqsave(&auddrv_Clk_lock, flags); + + Aud_APLL2_Tuner_cntr--; + + if (Aud_APLL2_Tuner_cntr == 0) { +#ifdef CONFIG_MTK_CLKMGR + Afe_Set_Reg(AUDIO_TOP_CON0, 0x1 << 18, 0x1 << 18); +#else + if (aud_clks[CLOCK_APLL2_TUNER].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL2_TUNER].clock); +#endif + PRINTK_AUD_CLK("AudDrv_APLL2Tuner_Clk_Off\n"); + } + /* handle for clock error */ + else if (Aud_APLL2_Tuner_cntr < 0) { + PRINTK_AUD_ERROR("!! AudDrv_APLL2Tuner_Clk_Off, Aud_APLL1_Tuner_cntr<0 (%d)\n", + Aud_APLL2_Tuner_cntr); + Aud_APLL2_Tuner_cntr = 0; + } + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} + +/***************************************************************************** + * FUNCTION + * AudDrv_HDMI_Clk_On / AudDrv_HDMI_Clk_Off + * + * DESCRIPTION + * Enable/Disable analog part clock + * + *****************************************************************************/ + +void AudDrv_HDMI_Clk_On(void) +{ +#ifdef _NON_COMMON_FEATURE_READY + PRINTK_AUD_CLK("+AudDrv_HDMI_Clk_On, Aud_I2S_Clk_cntr:%d\n", Aud_HDMI_Clk_cntr); + if (Aud_HDMI_Clk_cntr == 0) { + AudDrv_ANA_Clk_On(); + AudDrv_Clk_On(); + } + Aud_HDMI_Clk_cntr++; +#endif +} + +void AudDrv_HDMI_Clk_Off(void) +{ +#ifdef _NON_COMMON_FEATURE_READY + PRINTK_AUD_CLK("+AudDrv_HDMI_Clk_Off, Aud_I2S_Clk_cntr:%d\n", + Aud_HDMI_Clk_cntr); + Aud_HDMI_Clk_cntr--; + if (Aud_HDMI_Clk_cntr == 0) { + AudDrv_ANA_Clk_Off(); + AudDrv_Clk_Off(); + } else if (Aud_HDMI_Clk_cntr < 0) { + PRINTK_AUD_ERROR("!! AudDrv_Linein_Clk_Off, Aud_I2S_Clk_cntr<0 (%d)\n", + Aud_HDMI_Clk_cntr); + AUDIO_ASSERT(true); + Aud_HDMI_Clk_cntr = 0; + } + PRINTK_AUD_CLK("-AudDrv_I2S_Clk_Off, Aud_I2S_Clk_cntr:%d\n", Aud_HDMI_Clk_cntr); +#endif +} + +/***************************************************************************** +* FUNCTION +* AudDrv_Suspend_Clk_Off / AudDrv_Suspend_Clk_On +* +* DESCRIPTION +* Enable/Disable AFE clock for suspend +* +***************************************************************************** +*/ + +void AudDrv_Suspend_Clk_Off(void) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&auddrv_Clk_lock, flags); + if (Aud_Core_Clk_cntr > 0) { + if (Aud_I2S_Clk_cntr > 0) + aud_top_con_pdn_i2s(true); + + if (Aud_ADC_Clk_cntr > 0) { + if (aud_clks[CLOCK_ADC].clk_prepare) + clk_disable(aud_clks[CLOCK_ADC].clock); + } + + if (Aud_APLL22M_Clk_cntr > 0) { + if (aud_clks[CLOCK_APLL22M].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL22M].clock); + + if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL1_TUNER].clock); + + ret = clk_set_parent(aud_clks[CLOCK_TOP_AUD_MUX1].clock, + aud_clks[CLOCK_CLK26M].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_TOP_AUD_MUX1].name, + aud_clks[CLOCK_CLK26M].name, ret); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AUD_MUX1].clk_prepare) { + clk_disable(aud_clks[CLOCK_TOP_AUD_MUX1].clock); + pr_debug("%s [CCF]Aud clk_disable CLOCK_TOP_AUD_MUX1 fail", + __func__); + + } else { + pr_err + ("%s [CCF]clk_prepare error clk_disable CLOCK_TOP_AUD_MUX1 fail", + __func__); + BUG(); + goto EXIT; + } + /* Follow MT6755 */ + if (aud_clks[CLOCK_TOP_AD_APLL1_CK].clk_prepare) { + clk_disable(aud_clks[CLOCK_TOP_AD_APLL1_CK].clock); + pr_debug("%s [CCF]Aud clk_disable CLOCK_TOP_AD_APLL1_CK fail", + __func__); + + } else { + pr_err + ("%s [CCF]clk_prepare error CLOCK_TOP_AD_APLL1_CK fail", + __func__); + BUG(); + goto EXIT; + } + } + if (Aud_APLL24M_Clk_cntr > 0) { + if (aud_clks[CLOCK_APLL24M].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL24M].clock); + + if (aud_clks[CLOCK_APLL2_TUNER].clk_prepare) + clk_disable(aud_clks[CLOCK_APLL2_TUNER].clock); + + ret = clk_set_parent(aud_clks[CLOCK_TOP_AUD_MUX2].clock, + aud_clks[CLOCK_CLK26M].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_TOP_AUD_MUX2].name, + aud_clks[CLOCK_CLK26M].name, ret); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AUD_MUX2].clk_prepare) { + clk_disable(aud_clks[CLOCK_TOP_AUD_MUX2].clock); + pr_debug("%s [CCF]Aud clk_disable CLOCK_TOP_AUD_MUX2 fail", + __func__); + + } else { + pr_err + ("%s [CCF]clk_prepare error clk_disable CLOCK_TOP_AUD_MUX2 fail", + __func__); + BUG(); + goto EXIT; + } + /* Follow MT6755 */ + if (aud_clks[CLOCK_TOP_AD_APLL2_CK].clk_prepare) { + clk_disable(aud_clks[CLOCK_TOP_AD_APLL2_CK].clock); + pr_debug("%s [CCF]Aud clk_disable CLOCK_TOP_AD_APLL2_CK fail", + __func__); + } else { + pr_err + ("%s [CCF]clk_prepare error CLOCK_TOP_AD_APLL2_CK fail", + __func__); + BUG(); + goto EXIT; + } + } + /* Follow MT6755 + if (Aud_AFE_Clk_cntr > 0) { + if (aud_clks[CLOCK_AFE].clk_prepare) + clk_disable(aud_clks[CLOCK_AFE].clock); + } + */ + } +EXIT: + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} + +void AudDrv_Suspend_Clk_On(void) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&auddrv_Clk_lock, flags); + if (Aud_Core_Clk_cntr > 0) { + if (aud_clks[CLOCK_AFE].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_AFE].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock enable_clock aud_afe_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_afe_clk fail", + __func__); + BUG(); + goto EXIT; + } + /* Follow MT6755 */ + if (Aud_I2S_Clk_cntr > 0) { + if (aud_clks[CLOCK_I2S].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_I2S].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_i2s_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock aud_i2s_clk fail", + __func__); + BUG(); + goto EXIT; + } + } + /* Follow MT6755 */ + if (Aud_ADC_Clk_cntr > 0) { + if (aud_clks[CLOCK_ADC].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_ADC].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock aud_adc_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error aud_adc_clk fail", + __func__); + BUG(); + goto EXIT; + } + } + + if (Aud_APLL22M_Clk_cntr > 0) { + /* Follow MT6755 */ + if (aud_clks[CLOCK_TOP_AD_APLL1_CK].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_TOP_AD_APLL1_CK].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock CLOCK_TOP_AD_APLL1_CK fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud CLOCK_TOP_AD_APLL1_CK fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AUD_MUX1].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_TOP_AUD_MUX1].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock CLOCK_TOP_AUD_MUX1 fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock CLOCK_TOP_AUD_MUX1 fail", + __func__); + BUG(); + goto EXIT; + } + + ret = clk_set_parent(aud_clks[CLOCK_TOP_AUD_MUX1].clock, + aud_clks[CLOCK_TOP_AD_APLL1_CK].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_TOP_AUD_MUX1].name, + aud_clks[CLOCK_TOP_AD_APLL1_CK].name, ret); + BUG(); + goto EXIT; + } + /* Follow MT6755 */ + if (aud_clks[CLOCK_APMIXED_APLL1_CK].clk_prepare) { + + ret = clk_set_rate(aud_clks[CLOCK_APMIXED_APLL1_CK].clock, 180633600); + if (ret) { + pr_err("%s clk_set_rate %s-180633600 fail %d\n", + __func__, aud_clks[CLOCK_APMIXED_APLL1_CK].name, ret); + BUG(); + goto EXIT; + } + } + + if (aud_clks[CLOCK_APLL22M].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL22M].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_apll22m_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err + ("%s [CCF]clk_prepare error Aud enable_clock aud_apll22m_clk fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL1_TUNER].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_apll1_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err + ("%s [CCF]clk_prepare error Aud enable_clock aud_apll1_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + } + + if (Aud_APLL24M_Clk_cntr > 0) { + /* Follow MT6755 */ + if (aud_clks[CLOCK_TOP_AD_APLL2_CK].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_TOP_AD_APLL2_CK].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock CLOCK_TOP_AD_APLL2_CK fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud CLOCK_TOP_AD_APLL2_CK fail", + __func__); + BUG(); + goto EXIT; + } + + if (aud_clks[CLOCK_TOP_AUD_MUX2].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_TOP_AUD_MUX2].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock CLOCK_TOP_AUD_MUX2 fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock CLOCK_TOP_AUD_MUX2 fail", + __func__); + BUG(); + goto EXIT; + } + + ret = clk_set_parent(aud_clks[CLOCK_TOP_AUD_MUX2].clock, + aud_clks[CLOCK_TOP_AD_APLL2_CK].clock); + if (ret) { + pr_err("%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLOCK_TOP_AUD_MUX2].name, + aud_clks[CLOCK_TOP_AD_APLL2_CK].name, ret); + BUG(); + goto EXIT; + } + /* Follow MT6755 */ + if (aud_clks[CLOCK_APMIXED_APLL2_CK].clk_prepare) { + + ret = clk_set_rate(aud_clks[CLOCK_APMIXED_APLL2_CK].clock, 196607998); + if (ret) { + pr_err("%s clk_set_rate %s-196607998 fail %d\n", + __func__, aud_clks[CLOCK_APMIXED_APLL2_CK].name, ret); + BUG(); + goto EXIT; + } + } + + if (aud_clks[CLOCK_APLL24M].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL24M].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_apll24m_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err + ("%s [CCF]clk_prepare error Aud enable_clock aud_apll24m_clk fail", + __func__); + BUG(); + goto EXIT; + } + + + if (aud_clks[CLOCK_APLL2_TUNER].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_APLL2_TUNER].clock); + if (ret) { + pr_err + ("%s [CCF]Aud enable_clock enable_clock aud_apll2_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + } else { + pr_err + ("%s [CCF]clk_prepare error Aud enable_clock aud_apll2_tuner_clk fail", + __func__); + BUG(); + goto EXIT; + } + } + /* Follow MT6755 + if (Aud_I2S_Clk_cntr > 0) + aud_top_con_pdn_i2s(false); + + if (Aud_ADC_Clk_cntr > 0) { + if (aud_clks[CLOCK_ADC].clk_prepare) { + ret = clk_enable(aud_clks[CLOCK_ADC].clock); + if (ret) { + pr_err("%s [CCF]Aud enable_clock enable_clock ADC fail", __func__); + BUG(); + goto EXIT; + } + } else { + pr_err("%s [CCF]clk_prepare error Aud enable_clock ADC fail", __func__); + BUG(); + goto EXIT; + } + } + */ + } +EXIT: + spin_unlock_irqrestore(&auddrv_Clk_lock, flags); +} + +void AudDrv_Emi_Clk_On(void) +{ + mutex_lock(&auddrv_pmic_mutex); + if (Aud_EMI_cntr == 0) { +#ifndef CONFIG_FPGA_EARLY_PORTING +#ifdef _MT_IDLE_HEADER + /* mutex is used in these api */ + disable_dpidle_by_bit(MT_CG_ID_AUDIO_AFE); + disable_soidle_by_bit(MT_CG_ID_AUDIO_AFE); +#endif +#endif + } + Aud_EMI_cntr++; + mutex_unlock(&auddrv_pmic_mutex); +} + +void AudDrv_Emi_Clk_Off(void) +{ + mutex_lock(&auddrv_pmic_mutex); + Aud_EMI_cntr--; + if (Aud_EMI_cntr == 0) { +#ifndef CONFIG_FPGA_EARLY_PORTING +#ifdef _MT_IDLE_HEADER + /* mutex is used in these api */ + enable_dpidle_by_bit(MT_CG_ID_AUDIO_AFE); + enable_soidle_by_bit(MT_CG_ID_AUDIO_AFE); +#endif +#endif + } + + if (Aud_EMI_cntr < 0) { + Aud_EMI_cntr = 0; + PRINTK_AUD_ERROR("Aud_EMI_cntr = %d\n", Aud_EMI_cntr); + } + mutex_unlock(&auddrv_pmic_mutex); +} + +/***************************************************************************** + * FUNCTION + * AudDrv_ANC_Clk_On / AudDrv_ANC_Clk_Off + * + * DESCRIPTION + * Enable/Disable ANC clock + * + *****************************************************************************/ + +void AudDrv_ANC_Clk_On(void) +{ + /* MT6755 ANC? */ +} + +void AudDrv_ANC_Clk_Off(void) +{ + /* MT6755 ANC? */ +} + +uint32 GetApllbySampleRate(uint32 SampleRate) +{ + if (SampleRate == 176400 || SampleRate == 88200 || SampleRate == 44100 || + SampleRate == 22050 || SampleRate == 11025) + return Soc_Aud_APLL1; + else + return Soc_Aud_APLL2; +} + +void SetckSel(uint32 I2snum, uint32 SampleRate) +{ + /* always from APLL1 */ + uint32 ApllSource; + + if (GetApllbySampleRate(SampleRate) == Soc_Aud_APLL1) + ApllSource = 0; + else + ApllSource = 1; + + switch (I2snum) { + case Soc_Aud_I2S0: + Afe_Set_Reg(CLK_AUDDIV_0, ApllSource << 8, 1 << 8); + break; + case Soc_Aud_I2S1: + Afe_Set_Reg(CLK_AUDDIV_0, ApllSource << 9, 1 << 9); + break; + case Soc_Aud_I2S2: + Afe_Set_Reg(CLK_AUDDIV_0, ApllSource << 10, 1 << 10); + break; + case Soc_Aud_I2S3: + Afe_Set_Reg(CLK_AUDDIV_0, ApllSource << 11, 1 << 11); + break; + case Soc_Aud_I2SConnSys: + /* TODO: It may need to be implemented */ + break; + } + pr_debug("%s I2snum = %d ApllSource = %d\n", __func__, I2snum, ApllSource); +} + +void EnableALLbySampleRate(uint32 SampleRate) +{ + pr_debug("%s, APLL1Counter = %d, APLL2Counter = %d, SampleRate = %d\n", __func__, + APLL1Counter, APLL2Counter, SampleRate); + + switch (GetApllbySampleRate(SampleRate)) { + case Soc_Aud_APLL1: + APLL1Counter++; + if (APLL1Counter == 1) { + AudDrv_Clk_On(); + EnableApll1(true); + /*EnableI2SDivPower(AUDIO_APLL1_DIV0, true);*/ + EnableI2SCLKDiv(Soc_Aud_APLL1_DIV, true); + AudDrv_APLL1Tuner_Clk_On(); + /*AudDrv_APLL2Tuner_Clk_On();*/ + } + break; + case Soc_Aud_APLL2: + APLL2Counter++; + if (APLL2Counter == 1) { + AudDrv_Clk_On(); + EnableApll2(true); + /*EnableI2SDivPower(AUDIO_APLL2_DIV0, true);*/ + EnableI2SCLKDiv(Soc_Aud_APLL2_DIV, true); + /*AudDrv_APLL1Tuner_Clk_On();*/ + AudDrv_APLL2Tuner_Clk_On(); + } + break; + default: + pr_warn("[AudioWarn] GetApllbySampleRate(%d) = %d not recognized", + SampleRate, GetApllbySampleRate(SampleRate)); + break; + } +} + +void DisableALLbySampleRate(uint32 SampleRate) +{ + pr_debug("%s, APLL1Counter = %d, APLL2Counter = %d, SampleRate = %d\n", __func__, + APLL1Counter, APLL2Counter, SampleRate); + + switch (GetApllbySampleRate(SampleRate)) { + case Soc_Aud_APLL1: + APLL1Counter--; + if (APLL1Counter == 0) { + /* disable APLL1 */ + /*EnableI2SDivPower(AUDIO_APLL1_DIV0, false);*/ + EnableI2SCLKDiv(Soc_Aud_APLL1_DIV, false); + AudDrv_APLL1Tuner_Clk_Off(); + EnableApll1(false); + AudDrv_Clk_Off(); + } else if (APLL1Counter < 0) { + pr_warn("%s(), APLL1Counter %d < 0\n", + __func__, + APLL1Counter); + APLL1Counter = 0; + } + break; + case Soc_Aud_APLL2: + APLL2Counter--; + if (APLL2Counter == 0) { + /* disable APLL2 */ + /*EnableI2SDivPower(AUDIO_APLL2_DIV0, false);*/ + EnableI2SCLKDiv(Soc_Aud_APLL2_DIV, false); + AudDrv_APLL2Tuner_Clk_Off(); + EnableApll2(false); + AudDrv_Clk_Off(); + } else if (APLL2Counter < 0) { + pr_warn("%s(), APLL2Counter %d < 0\n", + __func__, + APLL2Counter); + APLL2Counter = 0; + } + break; + default: + pr_warn("[AudioWarn] GetApllbySampleRate(%d) = %d not recognized", + SampleRate, GetApllbySampleRate(SampleRate)); + break; + } +} + +void EnableI2SDivPower(uint32 Diveder_name, bool bEnable) +{ + pr_warn("%s bEnable = %d", __func__, bEnable); + if (bEnable) + Afe_Set_Reg(CLK_AUDDIV_0, 0 << Diveder_name, 1 << Diveder_name); + else + Afe_Set_Reg(CLK_AUDDIV_0, 1 << Diveder_name, 1 << Diveder_name); +} + +void EnableI2SCLKDiv(uint32 I2snum, bool bEnable) +{ + pr_warn("%s mI2SAPLLDivSelect = %d, i2snum = %d", __func__, mI2SAPLLDivSelect[I2snum], I2snum); + EnableI2SDivPower(mI2SAPLLDivSelect[I2snum], bEnable); +} + +void EnableApll1(bool bEnable) +{ + pr_warn("%s bEnable = %d", __func__, bEnable); + + if (bEnable) { + if (Aud_APLL_DIV_APLL1_cntr == 0) { + /* apll1_div0_pdn power down */ + Afe_Set_Reg(CLK_AUDDIV_0, 1 << 0, 1 << 0); + + /* apll2_div0_pdn power down */ +/* TODO: KC: this should be unnecessary // Afe_Set_Reg(CLK_AUDDIV_0, 1 << 1, 1 << 1); */ + + /* set appl1_ck_div0 = 7, f_faud_engen1_ck = clock source / 8*/ + /* 180.6336 / 8 = 22.5792MHz */ + Afe_Set_Reg(CLK_AUDDIV_0, 7 << 24, 0xf << 24); + + AudDrv_APLL22M_Clk_On(); + /* apll1_div0_pdn power up */ + Afe_Set_Reg(CLK_AUDDIV_0, 0 << 0, 1 << 0); + + /* apll2_div0_pdn power up. */ +/* TODO: KC: this should be unnecessary // Afe_Set_Reg(CLK_AUDDIV_0, 0x0, 0x2); */ + } + Aud_APLL_DIV_APLL1_cntr++; + } else { + Aud_APLL_DIV_APLL1_cntr--; + if (Aud_APLL_DIV_APLL1_cntr == 0) { + AudDrv_APLL22M_Clk_Off(); + /* apll1_div0_pdn power down */ + Afe_Set_Reg(CLK_AUDDIV_0, 1 << 0, 1 << 0); + } + } +} + +void EnableApll2(bool bEnable) +{ + pr_warn("%s bEnable = %d\n", __func__, bEnable); + + if (bEnable) { + if (Aud_APLL_DIV_APLL2_cntr == 0) { + /* apll2_div0_pdn power down */ + Afe_Set_Reg(CLK_AUDDIV_0, 1 << 1, 1 << 1); + + /* apll2_div0_pdn power down */ +/* TODO: KC: this should be unnecessary // Afe_Set_Reg(CLK_AUDDIV_0, 1 << 1, 1 << 1); */ + + /* set appl2_ck_div0 = 7, f_faud_engen2_ck = clock source / 8 */ + /* 196.608 / 8 = 24.576MHz */ + Afe_Set_Reg(CLK_AUDDIV_0, 7 << 28, 0xf << 28); + + AudDrv_APLL24M_Clk_On(); + + /* apll2_div0_pdn power up */ + Afe_Set_Reg(CLK_AUDDIV_0, 0 << 1, 1 << 1); + } + Aud_APLL_DIV_APLL2_cntr++; + } else { + Aud_APLL_DIV_APLL2_cntr--; + if (Aud_APLL_DIV_APLL2_cntr == 0) { + AudDrv_APLL24M_Clk_Off(); + /* apll2_div0_pdn power down */ + Afe_Set_Reg(CLK_AUDDIV_0, 1 << 1, 1 << 1); + } + } +} + +uint32 SetCLkMclk(uint32 I2snum, uint32 SampleRate) +{ + uint32 I2S_APll = 0; + uint32 I2s_ck_div = 0; + + if (GetApllbySampleRate(SampleRate) == Soc_Aud_APLL1) + I2S_APll = 180633600; + else + I2S_APll = 196608000; + + SetckSel(I2snum, SampleRate); /* set I2Sx mck source */ + + switch (I2snum) { + case Soc_Aud_I2S0: + I2s_ck_div = (I2S_APll / MCLKFS / SampleRate) - 1; + Afe_Set_Reg(CLK_AUDDIV_1, I2s_ck_div << 0, 0xff << 0); + break; + case Soc_Aud_I2S1: + I2s_ck_div = (I2S_APll / MCLKFS / SampleRate) - 1; + Afe_Set_Reg(CLK_AUDDIV_1, I2s_ck_div << 8, 0xff << 8); + break; + case Soc_Aud_I2S2: + I2s_ck_div = (I2S_APll / MCLKFS / SampleRate) - 1; + Afe_Set_Reg(CLK_AUDDIV_1, I2s_ck_div << 16, 0xff << 16); + break; + case Soc_Aud_I2S3: + I2s_ck_div = (I2S_APll / MCLKFS / SampleRate) - 1; + Afe_Set_Reg(CLK_AUDDIV_1, I2s_ck_div << 24, 0xff << 24); + break; + case Soc_Aud_I2SConnSys: + /* TODO: It may need to be implemented */ + break; + default: + pr_warn("[AudioWarn] SetCLkMclk: I2snum = %d not recognized", + I2snum); + break; + } + + pr_debug("%s I2snum = %d I2s_ck_div = %d I2S_APll = %d\n", __func__, I2snum, I2s_ck_div, + I2S_APll); + + return I2s_ck_div; +} + +void SetCLkBclk(uint32 MckDiv, uint32 SampleRate, uint32 Channels, uint32 Wlength) +{ + /* BCK set only required in 6595 TDM function div4/div5 */ + uint32 I2S_APll = 0; + uint32 I2S_Bclk = 0; + uint32 I2s_Bck_div = 0; + + pr_debug("%s MckDiv = %dv SampleRate = %d Channels = %d Wlength = %d\n", __func__, MckDiv, + SampleRate, Channels, Wlength); + MckDiv++; + + if (GetApllbySampleRate(SampleRate) == Soc_Aud_APLL1) + I2S_APll = 180633600; + else + I2S_APll = 196608000; + + I2S_Bclk = SampleRate * Channels * (Wlength + 1) * 16; + I2s_Bck_div = (I2S_APll / MckDiv) / I2S_Bclk; + + pr_warn("%s I2S_APll = %dv I2S_Bclk = %d I2s_Bck_div = %d\n", __func__, I2S_APll, + I2S_Bclk, I2s_Bck_div); + + if (I2s_Bck_div > 0) + I2s_Bck_div--; + + /* Follow MT6755: No TDM + Afe_Set_Reg(CLK_AUDDIV_2, I2s_Bck_div << 8, 0x0000ff00); + */ + +} + +void PowerDownAllI2SDiv(void) +{ + int i = 0; + + for (i = AUDIO_APLL1_DIV0; i < AUDIO_APLL_DIV_NUM; i++) + EnableI2SDivPower(i, false); +} diff --git a/sound/soc/mediatek/mt6755/Makefile b/sound/soc/mediatek/mt6755/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e3e07eeea2abee1e7d3d22627c4fdfab0577aa28 --- /dev/null +++ b/sound/soc/mediatek/mt6755/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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. +# + +# MTK Platform Support +MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) + +# AP object +obj-y += AudDrv_Clk.o +obj-y += mt_soc_afe_connection.o +obj-y += mt6755_sound.o diff --git a/sound/soc/mediatek/mt6755/mt6755_sound.c b/sound/soc/mediatek/mt6755/mt6755_sound.c new file mode 100644 index 0000000000000000000000000000000000000000..acc216a99733e2daa6ae99f6570c940d9d2659e4 --- /dev/null +++ b/sound/soc/mediatek/mt6755/mt6755_sound.c @@ -0,0 +1,1629 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + * + * 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. + * You should have received a copy of the GNU General Public License + * along with this program + * If not, see . + */ +/******************************************************************************* + * + * Filename: + * --------- + * mt6797_sound.c + * + * Project: + * -------- + * MT6797 Audio Driver Kernel Function + * + * Description: + * ------------ + * Audio register + * + * Author: + * ------- + * Chipeng Chang + * + *------------------------------------------------------------------------------ + * + *******************************************************************************/ + + +/***************************************************************************** + * C O M P I L E R F L A G S + *****************************************************************************/ + + +/***************************************************************************** + * E X T E R N A L R E F E R E N C E S + *****************************************************************************/ + +#include "AudDrv_Common.h" +#include "AudDrv_Def.h" +#include "AudDrv_Afe.h" +#include "AudDrv_Ana.h" +#include "AudDrv_Clk.h" +#include "mt_soc_afe_connection.h" +#include "mt_soc_afe_control.h" +#include "mt_soc_digital_type.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/*#include +#include +#include +#include +#include +#include +#include +#include +#include +#include */ + +static const uint16_t kSideToneCoefficientTable16k[] = { + 0x049C, 0x09E8, 0x09E0, 0x089C, + 0xFF54, 0xF488, 0xEAFC, 0xEBAC, + 0xfA40, 0x17AC, 0x3D1C, 0x6028, + 0x7538 +}; + + +static const uint16_t kSideToneCoefficientTable32k[] = { + 0xff58, 0x0063, 0x0086, 0x00bf, + 0x0100, 0x013d, 0x0169, 0x0178, + 0x0160, 0x011c, 0x00aa, 0x0011, + 0xff5d, 0xfea1, 0xfdf6, 0xfd75, + 0xfd39, 0xfd5a, 0xfde8, 0xfeea, + 0x005f, 0x0237, 0x0458, 0x069f, + 0x08e2, 0x0af7, 0x0cb2, 0x0df0, + 0x0e96 +}; + +/* Following structures may vary with chips!!!! */ +typedef enum { + AUDIO_APLL1_DIV0 = 0, + AUDIO_APLL2_DIV0 = 1, + AUDIO_APLL12_DIV0 = 2, + AUDIO_APLL12_DIV1 = 3, + AUDIO_APLL12_DIV2 = 4, + AUDIO_APLL12_DIV3 = 5, + AUDIO_APLL12_DIV4 = 6, + AUDIO_APLL12_DIVB = 7, + AUDIO_APLL_DIV_NUM +} AUDIO_APLL_DIVIDER_GROUP; + +static const uint32 mMemIfSampleRate[Soc_Aud_Digital_Block_MEM_I2S+1][3] = { /* reg, bit position, bit mask */ + {AFE_DAC_CON1, 0, 0xf}, /* Soc_Aud_Digital_Block_MEM_DL1 */ + {AFE_DAC_CON1, 4, 0xf}, /* Soc_Aud_Digital_Block_MEM_DL2 */ + {AFE_DAC_CON1, 16, 0xf}, /* Soc_Aud_Digital_Block_MEM_VUL */ + {AFE_DAC_CON0, 24, 0x3}, /* Soc_Aud_Digital_Block_MEM_DAI */ + {AFE_DAC_CON0, 12, 0xf}, /* Soc_Aud_Digital_Block_MEM_DL3 */ + {AFE_DAC_CON1, 12, 0xf}, /* Soc_Aud_Digital_Block_MEM_AWB */ + {AFE_DAC_CON1, 30, 0x3}, /* Soc_Aud_Digital_Block_MEM_MOD_DAI */ + {AFE_DAC_CON0, 16, 0xf}, /* Soc_Aud_Digital_Block_MEM_DL1_DATA2 */ + {AFE_DAC_CON0, 20, 0xf}, /* Soc_Aud_Digital_Block_MEM_VUL_DATA2 */ + {AFE_DAC_CON1, 8, 0xf}, /* Soc_Aud_Digital_Block_MEM_I2S */ +}; + +static const uint32 mMemIfChannels[Soc_Aud_Digital_Block_MEM_I2S+1][3] = { /* reg, bit position, bit mask */ + {AFE_DAC_CON1, 21, 0x1}, /* Soc_Aud_Digital_Block_MEM_DL1 */ + {AFE_DAC_CON1, 22, 0x1}, /* Soc_Aud_Digital_Block_MEM_DL2 */ + {AFE_DAC_CON1, 27, 0x1}, /* Soc_Aud_Digital_Block_MEM_VUL */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DAI */ + {AFE_DAC_CON1, 23, 0x1}, /* Soc_Aud_Digital_Block_MEM_DL3 */ + {AFE_DAC_CON1, 24, 0x1}, /* Soc_Aud_Digital_Block_MEM_AWB */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_MOD_DAI */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL1_DATA2 */ + {AFE_DAC_CON0, 10, 0x1}, /* Soc_Aud_Digital_Block_MEM_VUL_DATA2 */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_I2S */ +}; + +static const uint32 mMemIfMonoChSelect[Soc_Aud_Digital_Block_MEM_I2S+1][3] = { /* reg, bit position, bit mask */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL1 */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL2 */ + {AFE_DAC_CON1, 28, 0x1}, /* Soc_Aud_Digital_Block_MEM_VUL */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DAI */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL3 */ + {AFE_DAC_CON1, 25, 0x1}, /* Soc_Aud_Digital_Block_MEM_AWB */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_MOD_DAI */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL1_DATA2 */ + {AFE_DAC_CON0, 11, 0x1}, /* Soc_Aud_Digital_Block_MEM_VUL_DATA2 */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_I2S */ +}; + +static const uint32 mMemDuplicateWrite[Soc_Aud_Digital_Block_MEM_I2S+1][3] = { /* reg, bit position, bit mask */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL1 */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL2 */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_VUL */ + {AFE_DAC_CON1, 29, 0x1}, /* Soc_Aud_Digital_Block_MEM_DAI */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL3 */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_AWB */ + {AFE_DAC_CON0, 26, 0x1}, /* Soc_Aud_Digital_Block_MEM_MOD_DAI */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_DL1_DATA2 */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_VUL_DATA2 */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_Digital_Block_MEM_I2S */ +}; + +static const uint32 mMemAudioBlockEnableReg[][MEM_BLOCK_ENABLE_REG_INDEX_NUM] = { /* audio block, reg, bit position */ + {Soc_Aud_Digital_Block_MEM_DL1, AFE_DAC_CON0, 1}, + {Soc_Aud_Digital_Block_MEM_DL2, AFE_DAC_CON0, 2}, + {Soc_Aud_Digital_Block_MEM_VUL, AFE_DAC_CON0, 3}, + {Soc_Aud_Digital_Block_MEM_DAI, AFE_DAC_CON0, 4}, + {Soc_Aud_Digital_Block_MEM_DL3, AFE_DAC_CON0, 5}, + {Soc_Aud_Digital_Block_MEM_AWB, AFE_DAC_CON0, 6}, + {Soc_Aud_Digital_Block_MEM_MOD_DAI, AFE_DAC_CON0, 7}, + {Soc_Aud_Digital_Block_MEM_DL1_DATA2, AFE_DAC_CON0, 8}, + {Soc_Aud_Digital_Block_MEM_VUL_DATA2, AFE_DAC_CON0, 9}, +}; + +const struct Aud_IRQ_CTRL_REG mIRQCtrlRegs[Soc_Aud_IRQ_MCU_MODE_NUM] = { + { /*IRQ0*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ1*/ + {AFE_IRQ_MCU_CON, 0, 0x1}, /* irq on */ + {AFE_IRQ_MCU_CON, 4, 0xf}, /* irq mode */ + {AFE_IRQ_MCU_CNT1, 0, 0x3ffff}, /* irq count */ + {AFE_IRQ_MCU_CLR, 0, 0x1}, /* irq clear */ + {AFE_IRQ_MCU_CLR, 8, 0x1}, /* irq miss clear */ + {AFE_IRQ_MCU_STATUS, 0, 0x1}, /* irq status */ + {AFE_IRQ_MCU_EN, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ2*/ + {AFE_IRQ_MCU_CON, 1, 0x1}, /* irq on */ + {AFE_IRQ_MCU_CON, 8, 0xf}, /* irq mode */ + {AFE_IRQ_MCU_CNT2, 0, 0x3ffff}, /* irq count */ + {AFE_IRQ_MCU_CLR, 1, 0x1}, /* irq clear */ + {AFE_IRQ_MCU_CLR, 9, 0x1}, /* irq miss clear */ + {AFE_IRQ_MCU_STATUS, 1, 0x1}, /* irq status */ + {AFE_IRQ_MCU_EN, 1, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ3*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ4*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ5*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ6*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ7*/ + {AFE_IRQ_MCU_CON, 14, 0x1}, /* irq on */ + {AFE_IRQ_MCU_CON, 24, 0xf}, /* irq mode */ + {AFE_IRQ_MCU_CNT7, 0, 0x3ffff}, /* irq count */ + {AFE_IRQ_MCU_CLR, 6, 0x1}, /* irq clear */ + {AFE_IRQ_MCU_CLR, 14, 0x1}, /* irq miss clear */ + {AFE_IRQ_MCU_STATUS, 6, 0x1}, /* irq status */ + {AFE_IRQ_MCU_EN, 6, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ8*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ9*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ10*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ11*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ12*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ_ACC1*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, + { /*IRQ_ACC2*/ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq on */ + {AFE_REG_UNDEFINED, 0, 0xf}, /* irq mode */ + {AFE_REG_UNDEFINED, 0, 0x3ffff}, /* irq count */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq miss clear */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq status */ + {AFE_REG_UNDEFINED, 0, 0x1}, /* irq enable */ + Soc_Aud_IRQ_MCU /* irq use for specify purpose */ + }, +}; + +const struct Aud_RegBitsInfo mIRQPurposeRegs[Soc_Aud_IRQ_PURPOSE_NUM] = { + {AFE_IRQ_MCU_EN, 0, 0x7f}, /* Soc_Aud_IRQ_MCU */ + {AFE_IRQ_MCU_EN, 8, 0x3f}, /* Soc_Aud_IRQ_MD32 */ + {AFE_IRQ_MCU_EN, 16, 0x3f}, /* Soc_Aud_IRQ_MD32_H */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_IRQ_DSP */ + {AFE_REG_UNDEFINED, 0, 0x0}, /* Soc_Aud_IRQ_CM4 */ +}; + +/* Above structures may vary with chips!!!! */ + +static const int MEM_BLOCK_ENABLE_REG_NUM = sizeof(mMemAudioBlockEnableReg) / sizeof(mMemAudioBlockEnableReg[0]); + +void Afe_Log_Print(void) +{ + AudDrv_Clk_On(); + pr_debug("+AudDrv Afe_Log_Print\n"); + pr_debug("AUDIO_TOP_CON0 = 0x%x\n", Afe_Get_Reg(AUDIO_TOP_CON0)); + pr_debug("AUDIO_TOP_CON1 = 0x%x\n", Afe_Get_Reg(AUDIO_TOP_CON1)); + pr_debug("AUDIO_TOP_CON3 = 0x%x\n", Afe_Get_Reg(AUDIO_TOP_CON3)); + pr_debug("AFE_DAC_CON0 = 0x%x\n", Afe_Get_Reg(AFE_DAC_CON0)); + pr_debug("AFE_DAC_CON1 = 0x%x\n", Afe_Get_Reg(AFE_DAC_CON1)); + pr_debug("AFE_I2S_CON = 0x%x\n", Afe_Get_Reg(AFE_I2S_CON)); + pr_debug("AFE_DAIBT_CON0 = 0x%x\n", Afe_Get_Reg(AFE_DAIBT_CON0)); + pr_debug("AFE_CONN0 = 0x%x\n", Afe_Get_Reg(AFE_CONN0)); + pr_debug("AFE_CONN1 = 0x%x\n", Afe_Get_Reg(AFE_CONN1)); + pr_debug("AFE_CONN2 = 0x%x\n", Afe_Get_Reg(AFE_CONN2)); + pr_debug("AFE_CONN3 = 0x%x\n", Afe_Get_Reg(AFE_CONN3)); + pr_debug("AFE_CONN4 = 0x%x\n", Afe_Get_Reg(AFE_CONN4)); + pr_debug("AFE_I2S_CON1 = 0x%x\n", Afe_Get_Reg(AFE_I2S_CON1)); + pr_debug("AFE_I2S_CON2 = 0x%x\n", Afe_Get_Reg(AFE_I2S_CON2)); + pr_debug("AFE_MRGIF_CON = 0x%x\n", Afe_Get_Reg(AFE_MRGIF_CON)); + pr_debug("AFE_DL1_BASE = 0x%x\n", Afe_Get_Reg(AFE_DL1_BASE)); + pr_debug("AFE_DL1_CUR = 0x%x\n", Afe_Get_Reg(AFE_DL1_CUR)); + pr_debug("AFE_DL1_END = 0x%x\n", Afe_Get_Reg(AFE_DL1_END)); + pr_debug("AFE_VUL_D2_BASE = 0x%x\n", Afe_Get_Reg(AFE_VUL_D2_BASE)); + pr_debug("AFE_VUL_D2_END = 0x%x\n", Afe_Get_Reg(AFE_VUL_D2_END)); + pr_debug("AFE_VUL_D2_CUR = 0x%x\n", Afe_Get_Reg(AFE_VUL_D2_CUR)); + pr_debug("AFE_I2S_CON3 = 0x%x\n", Afe_Get_Reg(AFE_I2S_CON3)); + pr_debug("AFE_DL2_BASE = 0x%x\n", Afe_Get_Reg(AFE_DL2_BASE)); + pr_debug("AFE_DL2_CUR = 0x%x\n", Afe_Get_Reg(AFE_DL2_CUR)); + pr_debug("AFE_DL2_END = 0x%x\n", Afe_Get_Reg(AFE_DL2_END)); + pr_debug("AFE_CONN5 = 0x%x\n", Afe_Get_Reg(AFE_CONN5)); + pr_debug("AFE_CONN_24BIT = 0x%x\n", Afe_Get_Reg(AFE_CONN_24BIT)); + pr_debug("AFE_AWB_BASE = 0x%x\n", Afe_Get_Reg(AFE_AWB_BASE)); + pr_debug("AFE_AWB_END = 0x%x\n", Afe_Get_Reg(AFE_AWB_END)); + pr_debug("AFE_AWB_CUR = 0x%x\n", Afe_Get_Reg(AFE_AWB_CUR)); + pr_debug("AFE_VUL_BASE = 0x%x\n", Afe_Get_Reg(AFE_VUL_BASE)); + pr_debug("AFE_VUL_END = 0x%x\n", Afe_Get_Reg(AFE_VUL_END)); + pr_debug("AFE_VUL_CUR = 0x%x\n", Afe_Get_Reg(AFE_VUL_CUR)); + pr_debug("AFE_DAI_BASE = 0x%x\n", Afe_Get_Reg(AFE_DAI_BASE)); + pr_debug("AFE_DAI_END = 0x%x\n", Afe_Get_Reg(AFE_DAI_END)); + pr_debug("AFE_DAI_CUR = 0x%x\n", Afe_Get_Reg(AFE_DAI_CUR)); + pr_debug("AFE_CONN6 = 0x%x\n", Afe_Get_Reg(AFE_CONN6)); + pr_debug("AFE_MEMIF_MSB = 0x%x\n", Afe_Get_Reg(AFE_MEMIF_MSB)); + pr_debug("AFE_MEMIF_MON0 = 0x%x\n", Afe_Get_Reg(AFE_MEMIF_MON0)); + pr_debug("AFE_MEMIF_MON1 = 0x%x\n", Afe_Get_Reg(AFE_MEMIF_MON1)); + pr_debug("AFE_MEMIF_MON2 = 0x%x\n", Afe_Get_Reg(AFE_MEMIF_MON2)); + pr_debug("AFE_MEMIF_MON4 = 0x%x\n", Afe_Get_Reg(AFE_MEMIF_MON4)); + pr_debug("AFE_ADDA_DL_SRC2_CON0 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_DL_SRC2_CON0)); + pr_debug("AFE_ADDA_DL_SRC2_CON1 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_DL_SRC2_CON1)); + pr_debug("AFE_ADDA_UL_SRC_CON0 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_UL_SRC_CON0)); + pr_debug("AFE_ADDA_UL_SRC_CON1 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_UL_SRC_CON1)); + pr_debug("AFE_ADDA_TOP_CON0 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_TOP_CON0)); + pr_debug("AFE_ADDA_UL_DL_CON0 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_UL_DL_CON0)); + pr_debug("AFE_ADDA_SRC_DEBUG = 0x%x\n", Afe_Get_Reg(AFE_ADDA_SRC_DEBUG)); + pr_debug("AFE_ADDA_SRC_DEBUG_MON0= 0x%x\n", Afe_Get_Reg(AFE_ADDA_SRC_DEBUG_MON0)); + pr_debug("AFE_ADDA_SRC_DEBUG_MON1= 0x%x\n", Afe_Get_Reg(AFE_ADDA_SRC_DEBUG_MON1)); + pr_debug("AFE_ADDA_NEWIF_CFG0 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_NEWIF_CFG0)); + pr_debug("AFE_ADDA_NEWIF_CFG1 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_NEWIF_CFG1)); + pr_debug("AFE_SIDETONE_DEBUG = 0x%x\n", Afe_Get_Reg(AFE_SIDETONE_DEBUG)); + pr_debug("AFE_SIDETONE_MON = 0x%x\n", Afe_Get_Reg(AFE_SIDETONE_MON)); + pr_debug("AFE_SIDETONE_CON0 = 0x%x\n", Afe_Get_Reg(AFE_SIDETONE_CON0)); + pr_debug("AFE_SIDETONE_COEFF = 0x%x\n", Afe_Get_Reg(AFE_SIDETONE_COEFF)); + pr_debug("AFE_SIDETONE_CON1 = 0x%x\n", Afe_Get_Reg(AFE_SIDETONE_CON1)); + pr_debug("AFE_SIDETONE_GAIN = 0x%x\n", Afe_Get_Reg(AFE_SIDETONE_GAIN)); + pr_debug("AFE_SGEN_CON0 = 0x%x\n", Afe_Get_Reg(AFE_SGEN_CON0)); + pr_debug("AFE_TOP_CON0 = 0x%x\n", Afe_Get_Reg(AFE_TOP_CON0)); + pr_debug("AFE_ADDA_PREDIS_CON0 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_PREDIS_CON0)); + pr_debug("AFE_ADDA_PREDIS_CON1 = 0x%x\n", Afe_Get_Reg(AFE_ADDA_PREDIS_CON1)); + pr_debug("AFE_MRGIF_MON0 = 0x%x\n", Afe_Get_Reg(AFE_MRGIF_MON0)); + pr_debug("AFE_MRGIF_MON1 = 0x%x\n", Afe_Get_Reg(AFE_MRGIF_MON1)); + pr_debug("AFE_MRGIF_MON2 = 0x%x\n", Afe_Get_Reg(AFE_MRGIF_MON2)); + pr_debug("AFE_MOD_DAI_BASE = 0x%x\n", Afe_Get_Reg(AFE_MOD_DAI_BASE)); + pr_debug("AFE_MOD_DAI_END = 0x%x\n", Afe_Get_Reg(AFE_MOD_DAI_END)); + pr_debug("AFE_MOD_DAI_CUR = 0x%x\n", Afe_Get_Reg(AFE_MOD_DAI_CUR)); + pr_debug("AFE_IRQ_MCU_CON = 0x%x\n", Afe_Get_Reg(AFE_IRQ_MCU_CON)); + pr_debug("AFE_IRQ_MCU_STATUS = 0x%x\n", Afe_Get_Reg(AFE_IRQ_MCU_STATUS)); + pr_debug("AFE_IRQ_MCU_CLR = 0x%x\n", Afe_Get_Reg(AFE_IRQ_MCU_CLR)); + pr_debug("AFE_IRQ_MCU_CNT1 = 0x%x\n", Afe_Get_Reg(AFE_IRQ_MCU_CNT1)); + pr_debug("AFE_IRQ_MCU_CNT2 = 0x%x\n", Afe_Get_Reg(AFE_IRQ_MCU_CNT2)); + pr_debug("AFE_IRQ_MCU_EN = 0x%x\n", Afe_Get_Reg(AFE_IRQ_MCU_EN)); + pr_debug("AFE_IRQ_MCU_MON2 = 0x%x\n", Afe_Get_Reg(AFE_IRQ_MCU_MON2)); + pr_debug("AFE_IRQ1_MCU_CNT_MON = 0x%x\n", Afe_Get_Reg(AFE_IRQ1_MCU_CNT_MON)); + pr_debug("AFE_IRQ2_MCU_CNT_MON = 0x%x\n", Afe_Get_Reg(AFE_IRQ2_MCU_CNT_MON)); + pr_debug("AFE_IRQ1_MCU_EN_CNT_MON= 0x%x\n", Afe_Get_Reg(AFE_IRQ1_MCU_EN_CNT_MON)); + pr_debug("AFE_MEMIF_MAXLEN = 0x%x\n", Afe_Get_Reg(AFE_MEMIF_MAXLEN)); + pr_debug("AFE_MEMIF_PBUF_SIZE = 0x%x\n", Afe_Get_Reg(AFE_MEMIF_PBUF_SIZE)); + pr_debug("AFE_IRQ_MCU_CNT7 = 0x%x\n", Afe_Get_Reg(AFE_IRQ_MCU_CNT7)); + pr_debug("AFE_APLL1_TUNER_CFG = 0x%x\n", Afe_Get_Reg(AFE_APLL1_TUNER_CFG)); + pr_debug("AFE_APLL2_TUNER_CFG = 0x%x\n", Afe_Get_Reg(AFE_APLL2_TUNER_CFG)); + pr_debug("AFE_GAIN1_CON0 = 0x%x\n", Afe_Get_Reg(AFE_GAIN1_CON0)); + pr_debug("AFE_GAIN1_CON1 = 0x%x\n", Afe_Get_Reg(AFE_GAIN1_CON1)); + pr_debug("AFE_GAIN1_CON2 = 0x%x\n", Afe_Get_Reg(AFE_GAIN1_CON2)); + pr_debug("AFE_GAIN1_CON3 = 0x%x\n", Afe_Get_Reg(AFE_GAIN1_CON3)); + pr_debug("AFE_GAIN1_CONN = 0x%x\n", Afe_Get_Reg(AFE_GAIN1_CONN)); + pr_debug("AFE_GAIN1_CUR = 0x%x\n", Afe_Get_Reg(AFE_GAIN1_CUR)); + pr_debug("AFE_GAIN2_CON0 = 0x%x\n", Afe_Get_Reg(AFE_GAIN2_CON0)); + pr_debug("AFE_GAIN2_CON1 = 0x%x\n", Afe_Get_Reg(AFE_GAIN2_CON1)); + pr_debug("AFE_GAIN2_CON2 = 0x%x\n", Afe_Get_Reg(AFE_GAIN2_CON2)); + pr_debug("AFE_GAIN2_CON3 = 0x%x\n", Afe_Get_Reg(AFE_GAIN2_CON3)); + pr_debug("AFE_GAIN2_CONN = 0x%x\n", Afe_Get_Reg(AFE_GAIN2_CONN)); + pr_debug("AFE_GAIN2_CUR = 0x%x\n", Afe_Get_Reg(AFE_GAIN2_CUR)); + pr_debug("AFE_GAIN2_CONN2 = 0x%x\n", Afe_Get_Reg(AFE_GAIN2_CONN2)); + pr_debug("AFE_GAIN2_CONN3 = 0x%x\n", Afe_Get_Reg(AFE_GAIN2_CONN3)); + pr_debug("AFE_GAIN1_CONN2 = 0x%x\n", Afe_Get_Reg(AFE_GAIN1_CONN2)); + pr_debug("AFE_GAIN1_CONN3 = 0x%x\n", Afe_Get_Reg(AFE_GAIN1_CONN3)); + pr_debug("AFE_CONN7 = 0x%x\n", Afe_Get_Reg(AFE_CONN7)); + pr_debug("AFE_CONN8 = 0x%x\n", Afe_Get_Reg(AFE_CONN8)); + pr_debug("AFE_CONN9 = 0x%x\n", Afe_Get_Reg(AFE_CONN9)); + pr_debug("AFE_CONN10 = 0x%x\n", Afe_Get_Reg(AFE_CONN10)); + pr_debug("FPGA_CFG2 = 0x%x\n", Afe_Get_Reg(FPGA_CFG2)); + pr_debug("FPGA_CFG3 = 0x%x\n", Afe_Get_Reg(FPGA_CFG3)); + pr_debug("FPGA_CFG0 = 0x%x\n", Afe_Get_Reg(FPGA_CFG0)); + pr_debug("FPGA_CFG1 = 0x%x\n", Afe_Get_Reg(FPGA_CFG1)); + pr_debug("FPGA_VER = 0x%x\n", Afe_Get_Reg(FPGA_VER)); + pr_debug("FPGA_STC = 0x%x\n", Afe_Get_Reg(FPGA_STC)); + pr_debug("AFE_ASRC_CON0 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON0)); + pr_debug("AFE_ASRC_CON1 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON1)); + pr_debug("AFE_ASRC_CON2 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON2)); + pr_debug("AFE_ASRC_CON3 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON3)); + pr_debug("AFE_ASRC_CON4 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON4)); + pr_debug("AFE_ASRC_CON5 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON5)); + pr_debug("AFE_ASRC_CON6 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON6)); + pr_debug("AFE_ASRC_CON7 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON7)); + pr_debug("AFE_ASRC_CON8 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON8)); + pr_debug("AFE_ASRC_CON9 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON9)); + pr_debug("AFE_ASRC_CON10 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON10)); + pr_debug("AFE_ASRC_CON11 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON11)); + pr_debug("PCM_INTF_CON1 = 0x%x\n", Afe_Get_Reg(PCM_INTF_CON1)); + pr_debug("PCM_INTF_CON2 = 0x%x\n", Afe_Get_Reg(PCM_INTF_CON2)); + pr_debug("PCM2_INTF_CON = 0x%x\n", Afe_Get_Reg(PCM2_INTF_CON)); + pr_debug("AFE_ASRC_CON13 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON13)); + pr_debug("AFE_ASRC_CON14 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON14)); + pr_debug("AFE_ASRC_CON15 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON15)); + pr_debug("AFE_ASRC_CON16 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON16)); + pr_debug("AFE_ASRC_CON17 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON17)); + pr_debug("AFE_ASRC_CON18 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON18)); + pr_debug("AFE_ASRC_CON19 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON19)); + pr_debug("AFE_ASRC_CON20 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON20)); + pr_debug("AFE_ASRC_CON21 = 0x%x\n", Afe_Get_Reg(AFE_ASRC_CON21)); + pr_debug("AFE_ASRC4_CON0 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON0)); + pr_debug("AFE_ASRC4_CON1 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON1)); + pr_debug("AFE_ASRC4_CON2 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON2)); + pr_debug("AFE_ASRC4_CON3 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON3)); + pr_debug("AFE_ASRC4_CON4 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON4)); + pr_debug("AFE_ASRC4_CON5 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON5)); + pr_debug("AFE_ASRC4_CON6 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON6)); + pr_debug("AFE_ASRC4_CON7 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON7)); + pr_debug("AFE_ASRC4_CON8 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON8)); + pr_debug("AFE_ASRC4_CON9 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON9)); + pr_debug("AFE_ASRC4_CON10 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON10)); + pr_debug("AFE_ASRC4_CON11 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON11)); + pr_debug("AFE_ASRC4_CON12 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON12)); + pr_debug("AFE_ASRC4_CON13 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON13)); + pr_debug("AFE_ASRC4_CON14 = 0x%x\n", Afe_Get_Reg(AFE_ASRC4_CON14)); + pr_debug("AUDIO_CLK_AUDDIV_0 = 0x%x\n", Afe_Get_Reg(CLK_AUDDIV_0)); + pr_debug("AUDIO_CLK_AUDDIV_1 = 0x%x\n", Afe_Get_Reg(CLK_AUDDIV_1)); + AudDrv_Clk_Off(); + pr_debug("-AudDrv Afe_Log_Print\n"); +} +/* export symbols for other module using */ +EXPORT_SYMBOL(Afe_Log_Print); + +void Enable4pin_I2S0_I2S3(uint32 SampleRate, uint32 wLenBit) +{ + /*wLenBit : 0:Soc_Aud_I2S_WLEN_WLEN_32BITS /1:Soc_Aud_I2S_WLEN_WLEN_16BITS */ + uint32 Audio_I2S0 = 0; + uint32 Audio_I2S3 = 0; + + /*Afe_Set_Reg(AUDIO_TOP_CON1, 0x2, 0x2);*/ /* I2S_SOFT_Reset 4 wire i2s mode*/ + Afe_Set_Reg(AUDIO_TOP_CON1, 0x1 << 4, 0x1 << 4); /* I2S0 clock-gated */ + Afe_Set_Reg(AUDIO_TOP_CON1, 0x1 << 7, 0x1 << 7); /* I2S3 clock-gated */ + + /* Set I2S0 configuration */ + Audio_I2S0 |= (Soc_Aud_I2S_IN_PAD_SEL_I2S_IN_FROM_IO_MUX << 28);/* I2S in from io_mux */ + Audio_I2S0 |= Soc_Aud_LOW_JITTER_CLOCK << 12; /* Low jitter mode */ + Audio_I2S0 |= (Soc_Aud_INV_LRCK_NO_INVERSE << 5); + Audio_I2S0 |= (Soc_Aud_I2S_FORMAT_I2S << 3); + Audio_I2S0 |= (wLenBit << 1); + Afe_Set_Reg(AFE_I2S_CON, Audio_I2S0, MASK_ALL); + pr_debug("Audio_I2S0= 0x%x\n", Audio_I2S0); + + SetSampleRate(Soc_Aud_Digital_Block_MEM_I2S, SampleRate); /* set I2S0 sample rate */ + + /* Set I2S3 configuration */ + Audio_I2S3 |= Soc_Aud_LOW_JITTER_CLOCK << 12; /* Low jitter mode */ + Audio_I2S3 |= SampleRateTransform(SampleRate, Soc_Aud_Digital_Block_I2S_IN_2) << 8; + Audio_I2S3 |= Soc_Aud_I2S_FORMAT_I2S << 3; /* I2s format */ + Audio_I2S3 |= wLenBit << 1; /* WLEN */ + Afe_Set_Reg(AFE_I2S_CON3, Audio_I2S3, AFE_MASK_ALL); + pr_debug("Audio_I2S3= 0x%x\n", Audio_I2S3); + + Afe_Set_Reg(AUDIO_TOP_CON1, 0 << 4, 0x1 << 4); /* Clear I2S0 clock-gated */ + Afe_Set_Reg(AUDIO_TOP_CON1, 0 << 7, 0x1 << 7); /* Clear I2S3 clock-gated */ + + udelay(200); + + /*Afe_Set_Reg(AUDIO_TOP_CON1, 0, 0x2);*/ /* Clear I2S_SOFT_Reset 4 wire i2s mode*/ + + Afe_Set_Reg(AFE_I2S_CON, 0x1, 0x1); /* Enable I2S0 */ + + Afe_Set_Reg(AFE_I2S_CON3, 0x1, 0x1); /* Enable I2S3 */ +} + +void SetChipModemPcmConfig(int modem_index, AudioDigitalPCM p_modem_pcm_attribute) +{ + uint32 reg_pcm2_intf_con = 0; + uint32 reg_pcm_intf_con1 = 0; + + pr_debug("+%s()\n", __func__); + + if (modem_index == MODEM_1) { + reg_pcm2_intf_con |= (p_modem_pcm_attribute.mTxLchRepeatSel & 0x1) << 13; + reg_pcm2_intf_con |= (p_modem_pcm_attribute.mVbt16kModeSel & 0x1) << 12; + reg_pcm2_intf_con |= (p_modem_pcm_attribute.mSingelMicSel & 0x1) << 7; + reg_pcm2_intf_con |= (p_modem_pcm_attribute.mAsyncFifoSel & 0x1) << 6; + reg_pcm2_intf_con |= (p_modem_pcm_attribute.mPcmWordLength & 0x1) << 5; + reg_pcm2_intf_con |= (p_modem_pcm_attribute.mPcmModeWidebandSel & 0x3) << 3; + reg_pcm2_intf_con |= (p_modem_pcm_attribute.mPcmFormat & 0x3) << 1; + pr_debug("%s(), PCM2_INTF_CON(0x%lx) = 0x%x\n", __func__, PCM2_INTF_CON, + reg_pcm2_intf_con); + Afe_Set_Reg(PCM2_INTF_CON, reg_pcm2_intf_con, MASK_ALL); +#ifdef _NON_COMMON_FEATURE_READY + if (p_modem_pcm_attribute.mPcmModeWidebandSel == Soc_Aud_PCM_MODE_PCM_MODE_8K) { + Afe_Set_Reg(AFE_ASRC2_CON1, 0x00098580, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON4, 0x00098580, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON7, 0x0004c2c0, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON1, 0x00098580, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON4, 0x00098580, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON7, 0x0004c2c0, 0xffffffff); + } else if (p_modem_pcm_attribute.mPcmModeWidebandSel == + Soc_Aud_PCM_MODE_PCM_MODE_16K) { + Afe_Set_Reg(AFE_ASRC2_CON1, 0x0004c2c0, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON4, 0x0004c2c0, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON7, 0x00026160, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON1, 0x0004c2c0, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON4, 0x0004c2c0, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON7, 0x00026160, 0xffffffff); + } else if (p_modem_pcm_attribute.mPcmModeWidebandSel == + Soc_Aud_PCM_MODE_PCM_MODE_32K) { + Afe_Set_Reg(AFE_ASRC2_CON1, 0x00026160, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON4, 0x00026160, 0xffffffff); + Afe_Set_Reg(AFE_ASRC2_CON7, 0x000130b0, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON1, 0x00026160, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON4, 0x00026160, 0xffffffff); + Afe_Set_Reg(AFE_ASRC3_CON7, 0x000130b0, 0xffffffff); + } +#endif + } else if (modem_index == MODEM_2 || modem_index == MODEM_EXTERNAL) { + /* MODEM_2 use PCM_INTF_CON1 (0x530) !!! */ + if (p_modem_pcm_attribute.mPcmModeWidebandSel == Soc_Aud_PCM_MODE_PCM_MODE_8K) { + Afe_Set_Reg(AFE_ASRC_CON1, 0x00065900, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON4, 0x00065900, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON6, 0x007F188F, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON7, 0x00032C80, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON1, 0x00065900, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON4, 0x00065900, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON6, 0x007F188F, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON7, 0x00032C80, 0xffffffff); + } else if (p_modem_pcm_attribute.mPcmModeWidebandSel == + Soc_Aud_PCM_MODE_PCM_MODE_16K) { + Afe_Set_Reg(AFE_ASRC_CON1, 0x00032C80, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON4, 0x00032C80, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON6, 0x007F188F, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON7, 0x00019640, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON1, 0x00032C80, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON4, 0x00032C80, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON6, 0x007F188F, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON7, 0x00019640, 0xffffffff); + } else if (p_modem_pcm_attribute.mPcmModeWidebandSel == + Soc_Aud_PCM_MODE_PCM_MODE_32K) { + Afe_Set_Reg(AFE_ASRC_CON1, 0x00019640, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON4, 0x00019640, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON6, 0x007F188F, 0xffffffff); + Afe_Set_Reg(AFE_ASRC_CON7, 0x0000CB20, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON1, 0x00019640, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON2, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON3, 0x00400000, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON4, 0x00019640, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON6, 0x007F188F, 0xffffffff); + Afe_Set_Reg(AFE_ASRC4_CON7, 0x0000CB20, 0xffffffff); + } + + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mBclkOutInv & 0x01) << 22; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mTxLchRepeatSel & 0x01) << 19; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mVbt16kModeSel & 0x01) << 18; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mExtModemSel & 0x01) << 17; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mExtendBckSyncLength & 0x1F) << 9; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mExtendBckSyncTypeSel & 0x01) << 8; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mSingelMicSel & 0x01) << 7; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mAsyncFifoSel & 0x01) << 6; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mSlaveModeSel & 0x01) << 5; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mPcmModeWidebandSel & 0x03) << 3; + reg_pcm_intf_con1 |= (p_modem_pcm_attribute.mPcmFormat & 0x03) << 1; + pr_debug("%s(), PCM_INTF_CON1(0x%lx) = 0x%x", __func__, PCM_INTF_CON1, + reg_pcm_intf_con1); + Afe_Set_Reg(PCM_INTF_CON1, reg_pcm_intf_con1, MASK_ALL); + } +} + +bool SetChipModemPcmEnable(int modem_index, bool modem_pcm_on) +{ + uint32 dNeedDisableASM = 0, mPcm1AsyncFifo; + + pr_debug("+%s(), modem_index = %d, modem_pcm_on = %d\n", __func__, modem_index, + modem_pcm_on); + + if (modem_index == MODEM_1) { /* MODEM_1 use PCM2_INTF_CON (0x53C) !!! */ + /* todo:: temp for use fifo */ + Afe_Set_Reg(PCM2_INTF_CON, modem_pcm_on, 0x1); + } else if (modem_index == MODEM_2 || modem_index == MODEM_EXTERNAL) { + /* MODEM_2 use PCM_INTF_CON1 (0x530) !!! */ + if (modem_pcm_on == true) { /* turn on ASRC before Modem PCM on */ + Afe_Set_Reg(PCM_INTF_CON2, (modem_index - 1) << 8, 0x100); + /* selects internal MD2/MD3 PCM interface (0x538[8]) */ + mPcm1AsyncFifo = (Afe_Get_Reg(PCM_INTF_CON1) & 0x0040) >> 6; + if (mPcm1AsyncFifo == 0) { + /* Afe_Set_Reg(AFE_ASRC_CON6, 0x005f188f, MASK_ALL); // denali marked */ + Afe_Set_Reg(AFE_ASRC_CON0, 0x86083031, MASK_ALL); + /* Afe_Set_Reg(AFE_ASRC4_CON6, 0x005f188f, MASK_ALL); // denali marked */ + Afe_Set_Reg(AFE_ASRC4_CON0, 0x06003031, MASK_ALL); + } + Afe_Set_Reg(PCM_INTF_CON1, 0x1, 0x1); + } else if (modem_pcm_on == false) { /* turn off ASRC after Modem PCM off */ + Afe_Set_Reg(PCM_INTF_CON1, 0x0, 0x1); + Afe_Set_Reg(AFE_ASRC_CON6, 0x00000000, MASK_ALL); + dNeedDisableASM = (Afe_Get_Reg(AFE_ASRC_CON0) & 0x1) ? 1 : 0; + Afe_Set_Reg(AFE_ASRC_CON0, 0, (1 << 4 | 1 << 5 | dNeedDisableASM)); + Afe_Set_Reg(AFE_ASRC_CON0, 0x0, 0x1); + Afe_Set_Reg(AFE_ASRC4_CON6, 0x00000000, MASK_ALL); + Afe_Set_Reg(AFE_ASRC4_CON0, 0, (1 << 4 | 1 << 5)); + Afe_Set_Reg(AFE_ASRC4_CON0, 0x0, 0x1); + } + } else { + pr_err("%s(), no such modem_index: %d!!", __func__, modem_index); + return false; + } + + return true; +} + +bool SetI2SASRCConfig(bool bIsUseASRC, unsigned int dToSampleRate) +{ + pr_debug("+%s() bIsUseASRC [%d] dToSampleRate [%d]\n", __func__, bIsUseASRC, dToSampleRate); + + if (true == bIsUseASRC) { + BUG_ON(!(dToSampleRate == 44100 || dToSampleRate == 48000)); + Afe_Set_Reg(AFE_CONN4, 0, 1 << 30); + SetSampleRate(Soc_Aud_Digital_Block_MEM_I2S, dToSampleRate); /* To target sample rate */ + + if (dToSampleRate == 44100) + Afe_Set_Reg(AFE_ASRC_CON14, 0x001B9000, AFE_MASK_ALL); + else + Afe_Set_Reg(AFE_ASRC_CON14, 0x001E0000, AFE_MASK_ALL); + + Afe_Set_Reg(AFE_ASRC_CON15, 0x00140000, AFE_MASK_ALL); + Afe_Set_Reg(AFE_ASRC_CON16, 0x00FF5987, AFE_MASK_ALL); + Afe_Set_Reg(AFE_ASRC_CON17, 0x00007EF4, AFE_MASK_ALL); + Afe_Set_Reg(AFE_ASRC_CON16, 0x00FF5986, AFE_MASK_ALL); + Afe_Set_Reg(AFE_ASRC_CON16, 0x00FF5987, AFE_MASK_ALL); + + Afe_Set_Reg(AFE_ASRC_CON13, 0, 1 << 16); /* 0:Stereo 1:Mono */ + + Afe_Set_Reg(AFE_ASRC_CON20, 0x00036000, AFE_MASK_ALL); /* Calibration setting */ + Afe_Set_Reg(AFE_ASRC_CON21, 0x0002FC00, AFE_MASK_ALL); + } else { + Afe_Set_Reg(AFE_CONN4, 1 << 30, 1 << 30); + } + + return true; +} + +bool SetI2SASRCEnable(bool bEnable) +{ + if (true == bEnable) { + Afe_Set_Reg(AFE_ASRC_CON0, ((1 << 6) | (1 << 0)), ((1 << 6) | (1 << 0))); + } else { + uint32 dNeedDisableASM = (Afe_Get_Reg(AFE_ASRC_CON0) & 0x0030) ? 1 : 0; + + Afe_Set_Reg(AFE_ASRC_CON0, 0, (1 << 6 | dNeedDisableASM)); + } + + return true; +} + +bool EnableSideToneFilter(bool stf_on) +{ + /* MD max support 16K sampling rate */ + const uint8_t kSideToneHalfTapNum = sizeof(kSideToneCoefficientTable16k) / sizeof(uint16_t); + + pr_debug("+%s(), stf_on = %d\n", __func__, stf_on); + AudDrv_Clk_On(); + + if (stf_on == false) { + /* bypass STF result & disable */ + const bool bypass_stf_on = true; + uint32_t reg_value = (bypass_stf_on << 31) | (bypass_stf_on << 30) | (stf_on << 8); + + Afe_Set_Reg(AFE_SIDETONE_CON1, reg_value, MASK_ALL); + pr_debug("%s(), AFE_SIDETONE_CON1[0x%lx] = 0x%x\n", __func__, AFE_SIDETONE_CON1, + reg_value); + /* set side tone gain = 0 */ + Afe_Set_Reg(AFE_SIDETONE_GAIN, 0, MASK_ALL); + pr_debug("%s(), AFE_SIDETONE_GAIN[0x%lx] = 0x%x\n", __func__, AFE_SIDETONE_GAIN, 0); + } else { + const bool bypass_stf_on = false; + /* using STF result & enable & set half tap num */ + uint32_t write_reg_value = + (bypass_stf_on << 31) | (bypass_stf_on << 30) | (stf_on << 8) | kSideToneHalfTapNum; + /* set side tone coefficient */ + const bool enable_read_write = true; /* enable read/write side tone coefficient */ + const bool read_write_sel = true; /* for write case */ + const bool sel_ch2 = false; /* using uplink ch1 as STF input */ + uint32_t read_reg_value = Afe_Get_Reg(AFE_SIDETONE_CON0); + size_t coef_addr = 0; + + pr_debug("%s(), AFE_SIDETONE_GAIN[0x%lx] = 0x%x\n", __func__, AFE_SIDETONE_GAIN, 0); + + /* set side tone gain */ + Afe_Set_Reg(AFE_SIDETONE_GAIN, 0, MASK_ALL); + Afe_Set_Reg(AFE_SIDETONE_CON1, write_reg_value, MASK_ALL); + pr_debug("%s(), AFE_SIDETONE_CON1[0x%lx] = 0x%x\n", __func__, AFE_SIDETONE_CON1, + write_reg_value); + + for (coef_addr = 0; coef_addr < kSideToneHalfTapNum; coef_addr++) { + bool old_write_ready = (read_reg_value >> 29) & 0x1; + bool new_write_ready = 0; + int try_cnt = 0; + + write_reg_value = enable_read_write << 25 | + read_write_sel << 24 | + sel_ch2 << 23 | + coef_addr << 16 | + kSideToneCoefficientTable16k[coef_addr]; + Afe_Set_Reg(AFE_SIDETONE_CON0, write_reg_value, 0x39FFFFF); + pr_warn("%s(), AFE_SIDETONE_CON0[0x%lx] = 0x%x\n", __func__, AFE_SIDETONE_CON0, + write_reg_value); + + /* wait until flag write_ready changed (means write done) */ + for (try_cnt = 0; try_cnt < 10; try_cnt++) { /* max try 10 times */ + /* msleep(3); */ + /* usleep_range(3 * 1000, 20 * 1000); */ + read_reg_value = Afe_Get_Reg(AFE_SIDETONE_CON0); + new_write_ready = (read_reg_value >> 29) & 0x1; + if (new_write_ready == old_write_ready) { /* flip => ok */ + udelay(3); + if (try_cnt == 9) { + BUG_ON(new_write_ready == old_write_ready); + AudDrv_Clk_Off(); + return false; + } + } else { + break; + } + + } + } + + } + + AudDrv_Clk_Off(); + pr_debug("-%s(), stf_on = %d\n", __func__, stf_on); + + return true; +} + +bool CleanPreDistortion(void) +{ + /* printk("%s\n", __FUNCTION__); */ + Afe_Set_Reg(AFE_ADDA_PREDIS_CON0, 0, MASK_ALL); + Afe_Set_Reg(AFE_ADDA_PREDIS_CON1, 0, MASK_ALL); + + return true; +} + +/* Follow 6755 */ +bool SetDLSrc2(uint32 SampleRate) +{ + uint32 AfeAddaDLSrc2Con0, AfeAddaDLSrc2Con1; + + if (SampleRate == 8000) + AfeAddaDLSrc2Con0 = 0; + else if (SampleRate == 11025) + AfeAddaDLSrc2Con0 = 1; + else if (SampleRate == 12000) + AfeAddaDLSrc2Con0 = 2; + else if (SampleRate == 16000) + AfeAddaDLSrc2Con0 = 3; + else if (SampleRate == 22050) + AfeAddaDLSrc2Con0 = 4; + else if (SampleRate == 24000) + AfeAddaDLSrc2Con0 = 5; + else if (SampleRate == 32000) + AfeAddaDLSrc2Con0 = 6; + else if (SampleRate == 44100) + AfeAddaDLSrc2Con0 = 7; + else if (SampleRate == 48000) + AfeAddaDLSrc2Con0 = 8; + else + AfeAddaDLSrc2Con0 = 7; /* Default 44100 */ + + /* ASSERT(0); */ + if (AfeAddaDLSrc2Con0 == 0 || AfeAddaDLSrc2Con0 == 3) { + /* 8k or 16k voice mode */ + AfeAddaDLSrc2Con0 = + (AfeAddaDLSrc2Con0 << 28) | (0x03 << 24) | (0x03 << 11) | (0x01 << 5); + } else { + AfeAddaDLSrc2Con0 = (AfeAddaDLSrc2Con0 << 28) | (0x03 << 24) | (0x03 << 11); + } + + /* SA suggest apply -0.3db to audio/speech path */ + AfeAddaDLSrc2Con0 = AfeAddaDLSrc2Con0 | (0x01 << 1); /* 2013.02.22 for voice mode degrade 0.3 db */ + AfeAddaDLSrc2Con1 = 0xf74f0000; + Afe_Set_Reg(AFE_ADDA_DL_SRC2_CON0, AfeAddaDLSrc2Con0, MASK_ALL); + Afe_Set_Reg(AFE_ADDA_DL_SRC2_CON1, AfeAddaDLSrc2Con1, MASK_ALL); + + return true; +} + +uint32 SampleRateTransformI2s(uint32 SampleRate) +{ + switch (SampleRate) { + case 8000: + return Soc_Aud_I2S_SAMPLERATE_I2S_8K; + case 11025: + return Soc_Aud_I2S_SAMPLERATE_I2S_11K; + case 12000: + return Soc_Aud_I2S_SAMPLERATE_I2S_12K; + case 16000: + return Soc_Aud_I2S_SAMPLERATE_I2S_16K; + case 22050: + return Soc_Aud_I2S_SAMPLERATE_I2S_22K; + case 24000: + return Soc_Aud_I2S_SAMPLERATE_I2S_24K; + case 32000: + return Soc_Aud_I2S_SAMPLERATE_I2S_32K; + case 44100: + return Soc_Aud_I2S_SAMPLERATE_I2S_44K; + case 48000: + return Soc_Aud_I2S_SAMPLERATE_I2S_48K; + case 88200: + return Soc_Aud_I2S_SAMPLERATE_I2S_88K; + case 96000: + return Soc_Aud_I2S_SAMPLERATE_I2S_96K; + case 176400: + return Soc_Aud_I2S_SAMPLERATE_I2S_174K; + case 192000: + return Soc_Aud_I2S_SAMPLERATE_I2S_192K; + case 260000: + return Soc_Aud_I2S_SAMPLERATE_I2S_260K; + default: + break; + } + + return Soc_Aud_I2S_SAMPLERATE_I2S_44K; +} + +bool SetChipI2SAdcIn(AudioDigtalI2S *DigtalI2S, bool audioAdcI2SStatus) +{ + uint32 Audio_I2S_Adc = 0; + AudioDigtalI2S *audioAdcI2S = kzalloc(sizeof(AudioDigtalI2S), GFP_KERNEL); + + memcpy((void *)audioAdcI2S, (void *)DigtalI2S, sizeof(AudioDigtalI2S)); + if (false == audioAdcI2SStatus) { + uint32 eSamplingRate = SampleRateTransformI2s(audioAdcI2S->mI2S_SAMPLERATE); + uint32 dVoiceModeSelect = 0; + + Afe_Set_Reg(AFE_ADDA_TOP_CON0, 0, 0x1); /* Using Internal ADC */ + if (eSamplingRate == Soc_Aud_I2S_SAMPLERATE_I2S_8K) + dVoiceModeSelect = 0; + else if (eSamplingRate == Soc_Aud_I2S_SAMPLERATE_I2S_16K) + dVoiceModeSelect = 1; + else if (eSamplingRate == Soc_Aud_I2S_SAMPLERATE_I2S_32K) + dVoiceModeSelect = 2; + else if (eSamplingRate == Soc_Aud_I2S_SAMPLERATE_I2S_48K) + dVoiceModeSelect = 3; + + Afe_Set_Reg(AFE_ADDA_UL_SRC_CON0, + (dVoiceModeSelect << 19) | (dVoiceModeSelect << 17), 0x001E0000); + Afe_Set_Reg(AFE_ADDA_NEWIF_CFG0, 0x03F87201, 0xFFFFFFFF); /* up8x txif sat on */ + Afe_Set_Reg(AFE_ADDA_NEWIF_CFG1, ((dVoiceModeSelect < 3) ? 1 : 3) << 10, + 0x00000C00); + } else { + Afe_Set_Reg(AFE_ADDA_TOP_CON0, 1, 0x1); /* Using External ADC */ + Audio_I2S_Adc |= (audioAdcI2S->mLR_SWAP << 31); + Audio_I2S_Adc |= (audioAdcI2S->mBuffer_Update_word << 24); + Audio_I2S_Adc |= (audioAdcI2S->mINV_LRCK << 23); + Audio_I2S_Adc |= (audioAdcI2S->mFpga_bit_test << 22); + Audio_I2S_Adc |= (audioAdcI2S->mFpga_bit << 21); + Audio_I2S_Adc |= (audioAdcI2S->mloopback << 20); + Audio_I2S_Adc |= (SampleRateTransformI2s(audioAdcI2S->mI2S_SAMPLERATE) << 8); + Audio_I2S_Adc |= (audioAdcI2S->mI2S_FMT << 3); + Audio_I2S_Adc |= (audioAdcI2S->mI2S_WLEN << 1); + pr_debug("%s Audio_I2S_Adc = 0x%x", __func__, Audio_I2S_Adc); + Afe_Set_Reg(AFE_I2S_CON2, Audio_I2S_Adc, MASK_ALL); + } + kfree(audioAdcI2S); + + return true; +} + +bool setChipDmicPath(bool _enable, uint32 sample_rate) +{ + return true; +} + +bool SetSampleRate(uint32 Aud_block, uint32 SampleRate) +{ + /* pr_warn("%s Aud_block = %d SampleRate = %d\n", __func__, Aud_block, SampleRate); */ + SampleRate = SampleRateTransform(SampleRate, Aud_block); + + switch (Aud_block) { + case Soc_Aud_Digital_Block_MEM_DL1: + case Soc_Aud_Digital_Block_MEM_DL1_DATA2: + case Soc_Aud_Digital_Block_MEM_DL2: + case Soc_Aud_Digital_Block_MEM_DL3: + case Soc_Aud_Digital_Block_MEM_I2S: + case Soc_Aud_Digital_Block_MEM_AWB: + case Soc_Aud_Digital_Block_MEM_VUL: + case Soc_Aud_Digital_Block_MEM_DAI: + case Soc_Aud_Digital_Block_MEM_MOD_DAI: + case Soc_Aud_Digital_Block_MEM_VUL_DATA2: + Afe_Set_Reg(mMemIfSampleRate[Aud_block][0], SampleRate << mMemIfSampleRate[Aud_block][1], + mMemIfSampleRate[Aud_block][2] << mMemIfSampleRate[Aud_block][1]); + break; + default: + pr_err("audio_error: %s(): given Aud_block is not valid!!!!\n", __func__); + return false; + } + return true; +} + + +bool SetChannels(uint32 Memory_Interface, uint32 channel) +{ + const bool bMono = (channel == 1) ? true : false; + /* pr_warn("SetChannels Memory_Interface = %d channels = %d\n", Memory_Interface, channel); */ + switch (Memory_Interface) { + case Soc_Aud_Digital_Block_MEM_DL1: + case Soc_Aud_Digital_Block_MEM_DL2: + case Soc_Aud_Digital_Block_MEM_DL3: + case Soc_Aud_Digital_Block_MEM_AWB: + case Soc_Aud_Digital_Block_MEM_VUL: + case Soc_Aud_Digital_Block_MEM_VUL_DATA2: + Afe_Set_Reg(mMemIfChannels[Memory_Interface][0], bMono << mMemIfChannels[Memory_Interface][1], + mMemIfChannels[Memory_Interface][2] << mMemIfChannels[Memory_Interface][1]); + break; + default: + pr_warn + ("[AudioWarn] SetChannels Memory_Interface = %d, channel = %d, bMono = %d\n", + Memory_Interface, channel, bMono); + return false; + } + return true; +} + +int SetMemifMonoSel(uint32 Memory_Interface, bool mono_use_r_ch) +{ + switch (Memory_Interface) { + case Soc_Aud_Digital_Block_MEM_AWB: + case Soc_Aud_Digital_Block_MEM_VUL: + case Soc_Aud_Digital_Block_MEM_VUL_DATA2: + Afe_Set_Reg(mMemIfMonoChSelect[Memory_Interface][0], + mono_use_r_ch << mMemIfMonoChSelect[Memory_Interface][1], + mMemIfMonoChSelect[Memory_Interface][2] << mMemIfMonoChSelect[Memory_Interface][1]); + break; + default: + pr_warn("[AudioWarn] %s(), invalid Memory_Interface = %d\n", + __func__, Memory_Interface); + return -EINVAL; + } + return 0; +} + +bool SetMemDuplicateWrite(uint32 InterfaceType, int dupwrite) +{ + switch (InterfaceType) { + case Soc_Aud_Digital_Block_MEM_DAI: + case Soc_Aud_Digital_Block_MEM_MOD_DAI: + Afe_Set_Reg(mMemDuplicateWrite[InterfaceType][0], dupwrite << mMemDuplicateWrite[InterfaceType][1], + mMemDuplicateWrite[InterfaceType][2] << mMemDuplicateWrite[InterfaceType][1]); + break; + default: + return false; + } + + return true; +} + +uint32 GetEnableAudioBlockRegInfo(uint32 Aud_block, int index) +{ + int i = 0; + + for (i = 0; i < MEM_BLOCK_ENABLE_REG_NUM; i++) { + if (mMemAudioBlockEnableReg[i][MEM_BLOCK_ENABLE_REG_INDEX_AUDIO_BLOCK] == Aud_block) + return mMemAudioBlockEnableReg[i][index]; + } + return 0; /* 0: no such bit */ +} + +uint32 GetEnableAudioBlockRegAddr(uint32 Aud_block) +{ + return GetEnableAudioBlockRegInfo(Aud_block, MEM_BLOCK_ENABLE_REG_INDEX_REG); +} + +uint32 GetEnableAudioBlockRegOffset(uint32 Aud_block) +{ + return GetEnableAudioBlockRegInfo(Aud_block, MEM_BLOCK_ENABLE_REG_INDEX_OFFSET); +} + +bool SetMemIfFormatReg(uint32 InterfaceType, uint32 eFetchFormat) +{ + switch (InterfaceType) { + case Soc_Aud_Digital_Block_MEM_DL1:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 16, + 0x00030000); + break; + } + case Soc_Aud_Digital_Block_MEM_DL1_DATA2:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 12, + 0x00003000); + break; + } + case Soc_Aud_Digital_Block_MEM_DL2:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 18, + 0x000c0000); + break; + } + case Soc_Aud_Digital_Block_MEM_I2S:{ + /* Afe_Set_Reg(AFE_DAC_CON1, mAudioMEMIF[InterfaceType].mSampleRate << 8 , 0x00000f00); */ + pr_warn("Unsupport MEM_I2S"); + break; + } + case Soc_Aud_Digital_Block_MEM_AWB:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 20, + 0x00300000); + break; + } + case Soc_Aud_Digital_Block_MEM_VUL:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 22, + 0x00C00000); + break; + } + case Soc_Aud_Digital_Block_MEM_VUL_DATA2:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 14, + 0x0000C000); + break; + } + case Soc_Aud_Digital_Block_MEM_DAI:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 24, + 0x03000000); + break; + } + + case Soc_Aud_Digital_Block_MEM_MOD_DAI:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 26, + 0x0C000000); + break; + } + + case Soc_Aud_Digital_Block_MEM_HDMI:{ + Afe_Set_Reg(AFE_MEMIF_PBUF_SIZE, + eFetchFormat << 28, + 0x30000000); + break; + } + default: + return false; + } + + return true; +} + +ssize_t AudDrv_Reg_Dump(char *buffer, int size) +{ + int n = 0; + + pr_debug("mt_soc_debug_read\n"); + n = scnprintf(buffer + n, size - n, "AUDIO_TOP_CON0 = 0x%x\n", + Afe_Get_Reg(AUDIO_TOP_CON0)); + n += scnprintf(buffer + n, size - n, "AUDIO_TOP_CON1 = 0x%x\n", + Afe_Get_Reg(AUDIO_TOP_CON1)); + n += scnprintf(buffer + n, size - n, "AUDIO_TOP_CON3 = 0x%x\n", + Afe_Get_Reg(AUDIO_TOP_CON3)); + n += scnprintf(buffer + n, size - n, "AFE_DAC_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_DAC_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_DAC_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_DAC_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_I2S_CON = 0x%x\n", + Afe_Get_Reg(AFE_I2S_CON)); + n += scnprintf(buffer + n, size - n, "AFE_DAIBT_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_DAIBT_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_CONN0 = 0x%x\n", + Afe_Get_Reg(AFE_CONN0)); + n += scnprintf(buffer + n, size - n, "AFE_CONN1 = 0x%x\n", + Afe_Get_Reg(AFE_CONN1)); + n += scnprintf(buffer + n, size - n, "AFE_CONN2 = 0x%x\n", + Afe_Get_Reg(AFE_CONN2)); + n += scnprintf(buffer + n, size - n, "AFE_CONN3 = 0x%x\n", + Afe_Get_Reg(AFE_CONN3)); + n += scnprintf(buffer + n, size - n, "AFE_CONN4 = 0x%x\n", + Afe_Get_Reg(AFE_CONN4)); + n += scnprintf(buffer + n, size - n, "AFE_I2S_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_I2S_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_I2S_CON2 = 0x%x\n", + Afe_Get_Reg(AFE_I2S_CON2)); + n += scnprintf(buffer + n, size - n, "AFE_MRGIF_CON = 0x%x\n", + Afe_Get_Reg(AFE_MRGIF_CON)); + n += scnprintf(buffer + n, size - n, "AFE_DL1_BASE = 0x%x\n", + Afe_Get_Reg(AFE_DL1_BASE)); + n += scnprintf(buffer + n, size - n, "AFE_DL1_CUR = 0x%x\n", + Afe_Get_Reg(AFE_DL1_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_DL1_END = 0x%x\n", + Afe_Get_Reg(AFE_DL1_END)); + n += scnprintf(buffer + n, size - n, "AFE_VUL_D2_BASE = 0x%x\n", + Afe_Get_Reg(AFE_VUL_D2_BASE)); + n += scnprintf(buffer + n, size - n, "AFE_VUL_D2_END = 0x%x\n", + Afe_Get_Reg(AFE_VUL_D2_END)); + n += scnprintf(buffer + n, size - n, "AFE_VUL_D2_CUR = 0x%x\n", + Afe_Get_Reg(AFE_VUL_D2_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_I2S_CON3 = 0x%x\n", + Afe_Get_Reg(AFE_I2S_CON3)); + n += scnprintf(buffer + n, size - n, "AFE_DL2_BASE = 0x%x\n", + Afe_Get_Reg(AFE_DL2_BASE)); + n += scnprintf(buffer + n, size - n, "AFE_DL2_CUR = 0x%x\n", + Afe_Get_Reg(AFE_DL2_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_DL2_END = 0x%x\n", + Afe_Get_Reg(AFE_DL2_END)); + n += scnprintf(buffer + n, size - n, "AFE_CONN5 = 0x%x\n", + Afe_Get_Reg(AFE_CONN5)); + n += scnprintf(buffer + n, size - n, "AFE_CONN_24BIT = 0x%x\n", + Afe_Get_Reg(AFE_CONN_24BIT)); + n += scnprintf(buffer + n, size - n, "AFE_AWB_BASE = 0x%x\n", + Afe_Get_Reg(AFE_AWB_BASE)); + n += scnprintf(buffer + n, size - n, "AFE_AWB_END = 0x%x\n", + Afe_Get_Reg(AFE_AWB_END)); + n += scnprintf(buffer + n, size - n, "AFE_AWB_CUR = 0x%x\n", + Afe_Get_Reg(AFE_AWB_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_VUL_BASE = 0x%x\n", + Afe_Get_Reg(AFE_VUL_BASE)); + n += scnprintf(buffer + n, size - n, "AFE_VUL_END = 0x%x\n", + Afe_Get_Reg(AFE_VUL_END)); + n += scnprintf(buffer + n, size - n, "AFE_VUL_CUR = 0x%x\n", + Afe_Get_Reg(AFE_VUL_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_DAI_BASE = 0x%x\n", + Afe_Get_Reg(AFE_DAI_BASE)); + n += scnprintf(buffer + n, size - n, "AFE_DAI_END = 0x%x\n", + Afe_Get_Reg(AFE_DAI_END)); + n += scnprintf(buffer + n, size - n, "AFE_DAI_CUR = 0x%x\n", + Afe_Get_Reg(AFE_DAI_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_CONN6 = 0x%x\n", + Afe_Get_Reg(AFE_CONN6)); + n += scnprintf(buffer + n, size - n, "AFE_MEMIF_MSB = 0x%x\n", + Afe_Get_Reg(AFE_MEMIF_MSB)); + n += scnprintf(buffer + n, size - n, "AFE_MEMIF_MON0 = 0x%x\n", + Afe_Get_Reg(AFE_MEMIF_MON0)); + n += scnprintf(buffer + n, size - n, "AFE_MEMIF_MON1 = 0x%x\n", + Afe_Get_Reg(AFE_MEMIF_MON1)); + n += scnprintf(buffer + n, size - n, "AFE_MEMIF_MON2 = 0x%x\n", + Afe_Get_Reg(AFE_MEMIF_MON2)); + n += scnprintf(buffer + n, size - n, "AFE_MEMIF_MON4 = 0x%x\n", + Afe_Get_Reg(AFE_MEMIF_MON4)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_DL_SRC2_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_DL_SRC2_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_DL_SRC2_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_DL_SRC2_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_UL_SRC_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_UL_SRC_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_UL_SRC_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_UL_SRC_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_TOP_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_TOP_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_UL_DL_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_UL_DL_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_SRC_DEBUG = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_SRC_DEBUG)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_SRC_DEBUG_MON0= 0x%x\n", + Afe_Get_Reg(AFE_ADDA_SRC_DEBUG_MON0)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_SRC_DEBUG_MON1= 0x%x\n", + Afe_Get_Reg(AFE_ADDA_SRC_DEBUG_MON1)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_NEWIF_CFG0 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_NEWIF_CFG0)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_NEWIF_CFG1 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_NEWIF_CFG1)); + n += scnprintf(buffer + n, size - n, "AFE_SIDETONE_DEBUG = 0x%x\n", + Afe_Get_Reg(AFE_SIDETONE_DEBUG)); + n += scnprintf(buffer + n, size - n, "AFE_SIDETONE_MON = 0x%x\n", + Afe_Get_Reg(AFE_SIDETONE_MON)); + n += scnprintf(buffer + n, size - n, "AFE_SIDETONE_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_SIDETONE_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_SIDETONE_COEFF = 0x%x\n", + Afe_Get_Reg(AFE_SIDETONE_COEFF)); + n += scnprintf(buffer + n, size - n, "AFE_SIDETONE_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_SIDETONE_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_SIDETONE_GAIN = 0x%x\n", + Afe_Get_Reg(AFE_SIDETONE_GAIN)); + n += scnprintf(buffer + n, size - n, "AFE_SGEN_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_SGEN_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_TOP_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_TOP_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_PREDIS_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_PREDIS_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_ADDA_PREDIS_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_ADDA_PREDIS_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_MRGIF_MON0 = 0x%x\n", + Afe_Get_Reg(AFE_MRGIF_MON0)); + n += scnprintf(buffer + n, size - n, "AFE_MRGIF_MON1 = 0x%x\n", + Afe_Get_Reg(AFE_MRGIF_MON1)); + n += scnprintf(buffer + n, size - n, "AFE_MRGIF_MON2 = 0x%x\n", + Afe_Get_Reg(AFE_MRGIF_MON2)); + n += scnprintf(buffer + n, size - n, "AFE_MOD_DAI_BASE = 0x%x\n", + Afe_Get_Reg(AFE_MOD_DAI_BASE)); + n += scnprintf(buffer + n, size - n, "AFE_MOD_DAI_END = 0x%x\n", + Afe_Get_Reg(AFE_MOD_DAI_END)); + n += scnprintf(buffer + n, size - n, "AFE_MOD_DAI_CUR = 0x%x\n", + Afe_Get_Reg(AFE_MOD_DAI_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ_MCU_CON = 0x%x\n", + Afe_Get_Reg(AFE_IRQ_MCU_CON)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ_MCU_STATUS = 0x%x\n", + Afe_Get_Reg(AFE_IRQ_MCU_STATUS)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ_MCU_CLR = 0x%x\n", + Afe_Get_Reg(AFE_IRQ_MCU_CLR)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ_MCU_CNT1 = 0x%x\n", + Afe_Get_Reg(AFE_IRQ_MCU_CNT1)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ_MCU_CNT2 = 0x%x\n", + Afe_Get_Reg(AFE_IRQ_MCU_CNT2)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ_MCU_EN = 0x%x\n", + Afe_Get_Reg(AFE_IRQ_MCU_EN)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ_MCU_MON2 = 0x%x\n", + Afe_Get_Reg(AFE_IRQ_MCU_MON2)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ1_MCU_CNT_MON = 0x%x\n", + Afe_Get_Reg(AFE_IRQ1_MCU_CNT_MON)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ2_MCU_CNT_MON = 0x%x\n", + Afe_Get_Reg(AFE_IRQ2_MCU_CNT_MON)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ1_MCU_EN_CNT_MON= 0x%x\n", + Afe_Get_Reg(AFE_IRQ1_MCU_EN_CNT_MON)); + n += scnprintf(buffer + n, size - n, "AFE_MEMIF_MAXLEN = 0x%x\n", + Afe_Get_Reg(AFE_MEMIF_MAXLEN)); + n += scnprintf(buffer + n, size - n, "AFE_MEMIF_PBUF_SIZE = 0x%x\n", + Afe_Get_Reg(AFE_MEMIF_PBUF_SIZE)); + n += scnprintf(buffer + n, size - n, "AFE_IRQ_MCU_CNT7 = 0x%x\n", + Afe_Get_Reg(AFE_IRQ_MCU_CNT7)); + n += scnprintf(buffer + n, size - n, "AFE_APLL1_TUNER_CFG = 0x%x\n", + Afe_Get_Reg(AFE_APLL1_TUNER_CFG)); + n += scnprintf(buffer + n, size - n, "AFE_APLL2_TUNER_CFG = 0x%x\n", + Afe_Get_Reg(AFE_APLL2_TUNER_CFG)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN1_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN1_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN1_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN1_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN1_CON2 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN1_CON2)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN1_CON3 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN1_CON3)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN1_CONN = 0x%x\n", + Afe_Get_Reg(AFE_GAIN1_CONN)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN1_CUR = 0x%x\n", + Afe_Get_Reg(AFE_GAIN1_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN2_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN2_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN2_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN2_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN2_CON2 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN2_CON2)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN2_CON3 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN2_CON3)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN2_CONN = 0x%x\n", + Afe_Get_Reg(AFE_GAIN2_CONN)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN2_CUR = 0x%x\n", + Afe_Get_Reg(AFE_GAIN2_CUR)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN2_CONN2 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN2_CONN2)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN2_CONN3 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN2_CONN3)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN1_CONN2 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN1_CONN2)); + n += scnprintf(buffer + n, size - n, "AFE_GAIN1_CONN3 = 0x%x\n", + Afe_Get_Reg(AFE_GAIN1_CONN3)); + n += scnprintf(buffer + n, size - n, "AFE_CONN7 = 0x%x\n", + Afe_Get_Reg(AFE_CONN7)); + n += scnprintf(buffer + n, size - n, "AFE_CONN8 = 0x%x\n", + Afe_Get_Reg(AFE_CONN8)); + n += scnprintf(buffer + n, size - n, "AFE_CONN9 = 0x%x\n", + Afe_Get_Reg(AFE_CONN9)); + n += scnprintf(buffer + n, size - n, "AFE_CONN10 = 0x%x\n", + Afe_Get_Reg(AFE_CONN10)); + n += scnprintf(buffer + n, size - n, "FPGA_CFG0 = 0x%x\n", + Afe_Get_Reg(FPGA_CFG0)); + n += scnprintf(buffer + n, size - n, "FPGA_CFG1 = 0x%x\n", + Afe_Get_Reg(FPGA_CFG1)); + n += scnprintf(buffer + n, size - n, "FPGA_VER = 0x%x\n", + Afe_Get_Reg(FPGA_VER)); + n += scnprintf(buffer + n, size - n, "FPGA_STC = 0x%x\n", + Afe_Get_Reg(FPGA_STC)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON2 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON2)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON3 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON3)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON4 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON4)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON5 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON5)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON6 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON6)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON7 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON7)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON8 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON8)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON9 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON9)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON10 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON10)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON11 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON11)); + n += scnprintf(buffer + n, size - n, "PCM_INTF_CON = 0x%x\n", + Afe_Get_Reg(PCM_INTF_CON1)); + n += scnprintf(buffer + n, size - n, "PCM_INTF_CON2 = 0x%x\n", + Afe_Get_Reg(PCM_INTF_CON2)); + n += scnprintf(buffer + n, size - n, "PCM2_INTF_CON = 0x%x\n", + Afe_Get_Reg(PCM2_INTF_CON)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON13 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON13)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON14 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON14)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON15 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON15)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON16 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON16)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON17 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON17)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON18 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON18)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON19 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON19)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON20 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON20)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC_CON21 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC_CON21)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON0 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON0)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON1 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON1)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON2 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON2)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON3 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON3)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON4 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON4)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON5 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON5)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON6 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON6)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON7 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON7)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON8 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON8)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON9 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON9)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON10 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON10)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON11 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON11)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON12 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON12)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON13 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON13)); + n += scnprintf(buffer + n, size - n, "AFE_ASRC4_CON14 = 0x%x\n", + Afe_Get_Reg(AFE_ASRC4_CON14)); + + n += scnprintf(buffer + n, size - n, "AUDIO_CLK_AUDDIV_0 = 0x%x\n", + Afe_Get_Reg(CLK_AUDDIV_0)); + n += scnprintf(buffer + n, size - n, "AUDIO_CLK_AUDDIV_1 = 0x%x\n", + Afe_Get_Reg(CLK_AUDDIV_1)); + return n; +} + +bool SetFmI2sConnection(uint32 ConnectionState) +{ + SetIntfConnection(ConnectionState, + Soc_Aud_AFE_IO_Block_I2S0, Soc_Aud_AFE_IO_Block_HW_GAIN1_OUT); + SetIntfConnection(ConnectionState, + Soc_Aud_AFE_IO_Block_HW_GAIN1_IN, Soc_Aud_AFE_IO_Block_I2S1_DAC); + SetIntfConnection(ConnectionState, + Soc_Aud_AFE_IO_Block_HW_GAIN1_IN, Soc_Aud_AFE_IO_Block_I2S1_DAC_2); + return true; +} + +bool SetFmAwbConnection(uint32 ConnectionState) +{ + SetIntfConnection(ConnectionState, + Soc_Aud_AFE_IO_Block_I2S0, Soc_Aud_AFE_IO_Block_MEM_AWB); + return true; +} + +int SetFmI2sInEnable(bool enable) +{ + Set2ndI2SInEnable(bEnable); + return 0; +} + +int SetFmI2sIn(AudioDigtalI2S *mDigitalI2S) +{ + return Set2ndI2SIn(mDigitalI2S); +} + +bool GetFmI2sInPathEnable(void) +{ + return GetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2); +} + +bool SetFmI2sInPathEnable(bool bEnable) +{ + return SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_2, bEnable); +} + +int SetFmI2sAsrcEnable(bool enable) +{ + SetI2SASRCEnable(bEnable); + return 0; +} + +int SetFmI2sAsrcConfig(bool bIsUseASRC, unsigned int dToSampleRate) +{ + SetI2SASRCConfig(bIsUseASRC, dToSampleRate); + return 0; +} + +bool SetAncRecordReg(uint32 value, uint32 mask) +{ + return false; +} + +const struct Aud_IRQ_CTRL_REG *GetIRQCtrlReg(enum Soc_Aud_IRQ_MCU_MODE irqIndex) +{ + return &mIRQCtrlRegs[irqIndex]; +} + +const struct Aud_RegBitsInfo *GetIRQPurposeReg(enum Soc_Aud_IRQ_PURPOSE irqPurpose) +{ + return &mIRQPurposeRegs[irqPurpose]; +} + +/*Irq handler function array*/ +static void Aud_IRQ1_Handler(void) +{ + if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_DL1)) + Auddrv_DL1_Interrupt_Handler(); + if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_DL2)) + Auddrv_DL2_Interrupt_Handler(); +} +static void Aud_IRQ2_Handler(void) +{ + if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_VUL)) + Auddrv_UL1_Interrupt_Handler(); + if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_AWB)) + Auddrv_AWB_Interrupt_Handler(); + if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_DAI)) + Auddrv_DAI_Interrupt_Handler(); + if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_VUL_DATA2)) + Auddrv_UL2_Interrupt_Handler(); + if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_MOD_DAI)) + Auddrv_MOD_DAI_Interrupt_Handler(); +} + +static void (*Aud_IRQ_Handler_Funcs[Soc_Aud_IRQ_MCU_MODE_NUM])(void) = { + NULL, + Aud_IRQ1_Handler, + Aud_IRQ2_Handler, + NULL, + NULL, + NULL, + NULL, + NULL, /* Reserved */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +void RunIRQHandler(enum Soc_Aud_IRQ_MCU_MODE irqIndex) +{ + if (Aud_IRQ_Handler_Funcs[irqIndex] != NULL) + Aud_IRQ_Handler_Funcs[irqIndex](); + else + pr_aud("%s(), Aud_IRQ%d_Handler is Null", __func__, irqIndex); +} + +bool SetHighAddr(Soc_Aud_Digital_Block MemBlock, bool usingdram, dma_addr_t addr) +{ + bool highBitEnable = enable_4G() & usingdram; + + /*pr_debug("%s MemBlock = %d usingdram = %d\n", + __func__, + MemBlock, + usingdram);*/ + + switch (MemBlock) { + case Soc_Aud_Digital_Block_MEM_DL1: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 0, 0x1 << 0); + break; + case Soc_Aud_Digital_Block_MEM_DL2: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 1, 0x1 << 1); + break; + case Soc_Aud_Digital_Block_MEM_VUL: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 6, 0x1 << 6); + break; + case Soc_Aud_Digital_Block_MEM_DAI: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 5, 0x1 << 5); + break; + case Soc_Aud_Digital_Block_MEM_AWB: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 3, 0x1 << 3); + break; + case Soc_Aud_Digital_Block_MEM_MOD_DAI: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 4, 0x1 << 4); + break; + case Soc_Aud_Digital_Block_MEM_DL1_DATA2: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 2, 0x1 << 2); + break; + case Soc_Aud_Digital_Block_MEM_VUL_DATA2: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 7, 0x1 << 7); + break; + case Soc_Aud_Digital_Block_MEM_HDMI: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 8, 0x1 << 8); + break; + case Soc_Aud_Digital_Block_MEM_DL3: + Afe_Set_Reg(AFE_MEMIF_MSB, highBitEnable << 11, 0x1 << 11); + break; + default: + break; + } + return true; +} + diff --git a/sound/soc/mediatek/mt6755/mt_soc_afe_connection.c b/sound/soc/mediatek/mt6755/mt_soc_afe_connection.c new file mode 100644 index 0000000000000000000000000000000000000000..e55c6cb6ff7bf48e989238268393587b9fd837eb --- /dev/null +++ b/sound/soc/mediatek/mt6755/mt_soc_afe_connection.c @@ -0,0 +1,1052 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + * + * 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. + * You should have received a copy of the GNU General Public License + * along with this program + * If not, see . + */ +/******************************************************************************* + * + * Filename: + * --------- + * mt_sco_afe_connection.c + * + * Project: + * -------- + * MT6797 Audio Driver Kernel Function + * + * Description: + * ------------ + * Audio register + * + * Author: + * ------- + * Chipeng Chang + * + *------------------------------------------------------------------------------ + * + *******************************************************************************/ + + +/***************************************************************************** + * C O M P I L E R F L A G S + *****************************************************************************/ + + +/***************************************************************************** + * E X T E R N A L R E F E R E N C E S + *****************************************************************************/ + +#include "AudDrv_Common.h" +#include "AudDrv_Def.h" +#include "AudDrv_Afe.h" +#include "AudDrv_Ana.h" +#include "AudDrv_Clk.h" +#include "mt_soc_afe_connection.h" +#include "mt_soc_afe_control.h" +#include "mt_soc_digital_type.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* mutex lock */ +static DEFINE_MUTEX(afe_connection_mutex); + +#define Soc_Aud_InterConnectionOutput_Num_Output_MT6755 (28) +#define Soc_Aud_InterConnectionInput_Num_Input_MT6755 (23) + +/** +* here define conenction table for input and output +*/ +static const char mConnectionTable[Soc_Aud_InterConnectionInput_Num_Input_MT6755] + [Soc_Aud_InterConnectionOutput_Num_Output_MT6755] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 */ + {3, 3, 3, 3, 3, 3, -1, 1, 1, 1, 1, -1, -1, + 1, 1, 3, 3, 1, 1, 3, 25, 1, -1, -1, -1, -1, 1, -1}, /* I00 */ + {3, 3, 3, 3, 3, -1, 3, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 3, -1, -1, 3, 3, -1, 1, -1, 1, -1, -1, 1}, /* I01 */ + {1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, + 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I02 */ + {1, 1, 3, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, + -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1}, /* I03 */ + {1, 1, 3, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, + -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1}, /* I04 */ + {3, 3, 3, 3, 3, 1, -1, 0, -1, 1, -1, -1, -1, + 1, 1, -1, -1, -1, -1, 3, 3, 1, -1, -1, -1, -1, -1, -1}, /* I05 */ + {3, 3, 3, 3, 3, -1, 1, -1, 0, -1, 1, -1, 0, + 1, 1, -1, -1, -1, -1, 3, 3, -1, 1, -1, -1, -1, -1, -1}, /* I06 */ + {3, 3, 3, 3, 3, 1, -1, 0, -1, 0, -1, -1, -1, + 1, 1, -1, -1, -1, -1, 3, 3, 1, -1, -1, -1, -1, -1, -1}, /* I07 */ + {3, 3, 3, 3, 3, -1, 1, -1, 0, -1, 0, -1, 0, + 1, 1, -1, -1, -1, -1, 3, 3, -1, 1, -1, -1, -1, -1, -1}, /* I08 */ + {1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, + -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1}, /* I09 */ + {3, -1, 3, 3, -1, 1, -1, 1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1}, /* I10 */ + {-1, 3, 3, -1, 3, -1, 1, -1, 1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1}, /* I11 */ + {3, -1, 3, 3, -1, 0, -1, 1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1}, /* I12 */ + {-1, 3, 3, -1, 3, -1, 0, -1, 1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1}, /* I13 */ + {1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, + -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1}, /* I14 */ + {3, 3, 3, 3, 3, 3, -1, -1, -1, 1, -1, -1, -1, + 1, 1, 3, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1}, /* I15 */ + {3, 3, 3, 3, 3, -1, 3, -1, -1, -1, 1, -1, -1, + 1, 1, 1, 3, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1}, /* I16 */ + {1, -1, 3, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, + 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1}, /* I17 */ + {-1, 1, 3, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, + 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1}, /* I18 */ + {3, -1, 3, 3, 3, 1, -1, 1, -1, 1, -1, 1, -1, + 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1}, /* I19 */ + {-1, 3, 3, 3, 3, -1, 1, -1, 1, -1, 1, -1, 1, + 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1}, /* I20 */ + {1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, + 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1}, /* I21 */ + {1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, + 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1}, /* I22 */ +}; + + +/* remind for AFE_CONN4 bit31 */ +/** +* connection bits of certain bits +*/ +static const char mConnectionbits[Soc_Aud_InterConnectionInput_Num_Input_MT6755] + [Soc_Aud_InterConnectionOutput_Num_Output_MT6755] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 */ + {0, 16, 0, 16, 0, 16, -1, 2, 5, 8, 12, -1, -1, + 2, 15, 16, 22, 14, 18, 8, 24, 30, -1, -1, -1, -1, -1, -1}, /* I00 */ + {1, 17, 1, 17, 1, -1, 22, 3, 6, 9, 13, -1, -1, + 3, 16, 17, 23, 15, 19, 10, 26, -1, 2, -1, 15, -1, -1, 5}, /* I01 */ + {2, 18, 2, 18, -1, 17, -1, 21, 22, -1, -1, 6, -1, + 4, 17, -1, 24, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I02 */ + {3, 19, 3, 19, 3, 18, -1, 26, -1, 0, -1, -1, -1, + 5, 18, 19, 25, 13, -1, 12, 28, 31, -1, 6, -1, 24, -1, -1}, /* I03 */ + {4, 20, 4, 20, 4, -1, 23, -1, 29, -1, 3, -1, -1, + 6, 19, 20, 26, -1, 16, 13, 29, -1, 3, -1, 9, -1, -1, -1}, /* I04 */ + {5, 21, 5, 21, 5, 19, -1, 27, -1, 1, -1, 7, -1, + 16, 20, 17, 26, 14, -1, 14, 31, 8, -1, -1, -1, -1, -1, -1}, /* I05 */ + {6, 22, 6, 22, 6, -1, 24, -1, 30, -1, 4, -1, 9, + 17, 21, 18, 27, -1, 17, 16, 0, -1, 11, -1, -1, -1, -1, -1}, /* I06 */ + {7, 23, 7, 23, 7, 20, -1, 28, -1, 2, -1, 8, -1, + 18, 22, 19, 28, 15, -1, 18, 2, 9, -1, -1, -1, -1, -1, -1}, /* I07 */ + {8, 24, 8, 24, 8, -1, 25, -1, 31, -1, 5, -1, 10, + 19, 23, 20, 29, -1, 18, 20, 4, -1, 12, -1, -1, -1, -1, -1}, /* I08 */ + {9, 25, 9, 25, 9, 21, 27, -1, -1, 10, -1, -1, 11, + 7, 20, 21, 27, 16, 20, 22, 26, -1, -1, 28, 29, 25, -1, -1}, /* I09 */ + {0, -1, 4, 8, -1, 12, -1, 14, -1, 26, 28, 30, 0, + -1, -1, -1, -1, 24, -1, 28, -1, 0, -1, 2, -1, 6, -1, -1}, /* I10 */ + {-1, 2, 6, -1, 10, -1, 13, -1, 15, 27, 29, 31, 1, + -1, -1, -1, -1, -1, 25, -1, 29, 31, 1, -1, 3, -1, -1, -1}, /* I11 */ + {0, -1, 4, 8, -1, 12, -1, 14, -1, 8, 10, 12, 14, + -1, -1, -1, -1, 6, -1, 2, -1, -1, 6, -1, -1, -1, -1, -1}, /* I12 */ + {-1, 2, 6, -1, 10, -1, 13, -1, 15, 9, 11, 13, 15, + -1, -1, -1, -1, -1, 7, -1, 3, 4, 7, -1, -1, -1, -1, -1}, /* I13 */ + {12, 17, 22, 27, 0, 5, -1, 4, 7, 11, -1, -1, 12, + 8, 21, 28, 1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1}, /* I14 */ + {13, 18, 23, 28, 1, 6, -1, -1, -1, 10, -1, -1, -1, + 9, 22, 29, 2, -1, -1, 23, -1, 10, -1, -1, -1, -1, -1, -1}, /* I15 */ + {14, 19, 24, 29, 2, -1, 8, -1, -1, -1, 11, -1, -1, + 10, 23, 30, 3, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1}, /* I16 */ + {0, 19, 27, 0, 2, 22, 8, 26, -1, 30, 11, 2, -1, + 11, 24, 21, 30, 17, -1, 22, 6, 0, -1, 7, -1, -1, -1, -1}, /* I17 */ + {14, 3, 28, 29, 1, -1, 24, -1, 28, -1, 0, -1, 4, + 12, 25, 22, 31, -1, 21, 23, 7, -1, 4, -1, 10, -1, -1, -1}, /* I18 */ + {1, 19, 10, 14, 18, 23, 8, 27, -1, 31, -1, 3, -1, + 13, 26, 23, 0, 6, -1, 24, 28, 1, -1, 8, -1, -1, -1, -1}, /* I19 */ + {14, 4, 12, 16, 20, -1, 25, -1, 29, -1, 1, -1, 5, + 14, 27, 24, 1, -1, 7, 25, 29, -1, 5, -1, 11, -1, -1, -1}, /* I20 */ + {12, 13, 14, 15, 16, 17, 8, 18, 19, 20, -1, -1, 21, + 4, 5, 6, 7, -1, -1, 22, 23, -1, -1, -1, -1, -1, -1, -1}, /* I21 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I22 */ +}; + +/** +* connection shift bits of certain bits +*/ +static const char mShiftConnectionbits[Soc_Aud_InterConnectionInput_Num_Input_MT6755] + [Soc_Aud_InterConnectionOutput_Num_Output_MT6755] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 */ + {10, 26, 10, 26, 10, 19, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 31, 25, -1, -1, 9, 25, -1, -1, -1, -1, -1}, /* I00 */ + {11, 27, 11, 27, 11, -1, 20, -1, -1, -1, -1, -1, -1, + -1, -1, 16, 4, -1, -1, 11, 27, -1, -1, -1, -1, -1}, /* I01 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I02 */ + {-1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I03 */ + {-1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I04 */ + {12, 28, 12, 28, 12, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 15, 30, -1, -1, -1, -1, -1}, /* I05 */ + {13, 29, 13, 29, 13, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 17, 1, -1, -1, -1, -1, -1}, /* I06 */ + {14, 30, 14, 30, 14, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 19, 3, -1, -1, -1, -1, -1}, /* I07 */ + {15, 31, 15, 31, 15, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 21, 5, -1, -1, -1, -1, -1}, /* I08 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I09 */ + {1, -1, 5, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I10 */ + {-1, 3, 7, -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I11 */ + {1, -1, 5, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I12 */ + {-1, 3, 7, -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I13 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I14 */ + {15, 20, 25, 30, 3, 7, -1, -1, -1, 10, -1, -1, -1, + -1, -1, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I15 */ + {16, 21, 26, 31, 4, -1, 9, -1, -1, -1, 11, -1, -1, + -1, -1, 30, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I16 */ + {14, 19, 30, 29, 2, -1, 8, -1, -1, -1, 11, -1, -1, + -1, -1, 30, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I17 */ + {14, 19, 31, 29, 2, -1, 8, -1, -1, -1, 11, -1, -1, + -1, -1, 30, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I18 */ + {2, 19, 11, 16, 19, -1, 8, -1, -1, -1, 11, -1, -1, + -1, -1, 30, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I19 */ + {14, 5, 13, 17, 21, -1, 8, -1, -1, -1, 11, -1, -1, + -1, -1, 30, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I20 */ + {14, 19, 24, 29, 2, -1, 8, -1, -1, -1, 11, -1, -1, + -1, -1, 30, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I21 */ +}; + +/** +* connection of register +*/ +static const short mConnectionReg[Soc_Aud_InterConnectionInput_Num_Input_MT6755] + [Soc_Aud_InterConnectionOutput_Num_Output_MT6755] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 */ + {0x20, 0x20, 0x24, 0x24, 0x28, 0x28, -1, 0x5c, -1, 0x5c, 0x5c, -1, -1, + 0x448, 0x448, 0x438, 0x438, 0x5c, 0x5c, 0x464, 0x464, -1, -1, -1, -1, -1, -1, -1}, /* I00 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, 0x28, 0x5c, 0x5c, 0x5c, 0x5c, -1, -1, + 0x448, 0x448, 0x438, 0x438, 0x5c, 0x5c, 0x464, 0x464, -1, 0xbc, -1, 0x468, -1, -1, 0x46c}, /* I01 */ + {-1, 0x20, 0x24, 0x24, -1, -1, 0x30, 0x30, -1, -1, -1, 0x2c, -1, + 0x448, 0x448, -1, -1, 0x30, 0x30, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I02 */ + {0x20, 0x20, 0x24, 0x24, 0x28, 0x28, -1, 0x28, -1, 0x2C, -1, -1, -1, + 0x448, 0x448, 0x438, 0x438, 0x30, -1, 0x464, 0x464, 0x5c, -1, 0xbc, -1, 0xbc, -1, -1}, /* I03 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, 0x28, -1, 0x28, -1, 0x2C, -1, -1, + 0x448, 0x448, 0x438, 0x438, -1, 0x30, 0x464, 0x464, -1, 0xbc, -1, 0xbc, -1, -1, -1}, /* I04 */ + {0x20, 0x20, 0x24, 0x24, 0x28, 0x28, -1, 0x28, -1, 0x2C, -1, -1, -1, + 0x420, 0x420, -1, -1, 0x30, -1, 0x464, 0x464, -1, -1, -1, -1, -1, -1, -1}, /* I05 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, 0x28, -1, 0x28, -1, 0x2C, -1, 0x2C, + 0x420, 0x420, -1, -1, -1, 0x30, 0x464, -1, -1, -1, -1, -1, -1, -1, -1}, /* I06 */ + {0x20, 0x20, 0x24, 0x24, 0x28, 0x28, -1, 0x28, -1, 0x2C, -1, -1, -1, + 0x420, 0x420, -1, -1, 0x30, -1, 0x464, -1, -1, -1, -1, -1, -1, -1, -1}, /* I07 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, 0x28, -1, 0x28, -1, 0x2C, -1, 0x2C, + 0x420, 0x420, -1, -1, -1, 0x30, 0x464, -1, -1, -1, -1, -1, -1, -1, -1}, /* I08 */ + {0x20, 0x20, 0x24, 0x24, 0x28, 0x28, -1, -1, -1, 0x5c, -1, -1, 0x2C, + 0x448, 0x448, 0x438, 0x438, 0x5c, 0x5c, 0x5c, 0x5c, -1, -1, 0xbc, 0xbc, 0xbc, -1, -1}, /* I09 */ + {0x420, -1, -1, 0x420, -1, 0x420, -1, 0x420, -1, -1, -1, -1, 0x448, + -1, -1, -1, -1, 0x420, -1, 0x448, -1, 0x448, 0x44c, 0x44c, -1, 0x44c, -1, -1}, /* I10 */ + {-1, 0x420, -1, -1, 0x420, -1, 0x420, -1, 0x420, -1, -1, -1, 0x448, + -1, -1, -1, -1, -1, 0x420, -1, 0x448, 0x448, 0x44c, -1, 0x44c, -1, -1, -1}, /* I11 */ + {0x438, 0x438, -1, 0x438, -1, 0x438, -1, 0x438, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 0x440, -1, 0x444, -1, 0x444, 0x444, -1, -1, -1, -1, -1}, /* I12 */ + {-1, 0x438, -1, -1, 0x438, -1, 0x438, -1, 0x438, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 0x440, -1, 0x444, 0x444, 0x444, -1, -1, -1, -1, -1}, /* I13 */ + {0x2C, 0x2C, 0x2C, 0x2C, 0x30, 0x30, -1, 0x5c, 0x5c, 0x5c, -1, -1, 0x30, + 0x448, 0x448, 0x438, 0x440, -1, -1, 0x5c, 0x5c, -1, -1, -1, 0x44c, -1, -1, -1}, /* I14 */ + {0x2C, 0x2C, 0x2C, 0x2C, 0x30, 0x30, -1, -1, -1, 0x30, -1, -1, -1, + 0x448, 0x448, 0x438, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I15 */ + {0x2C, 0x2C, 0x2C, 0x2C, 0x30, -1, 0x30, -1, -1, -1, 0x30, -1, -1, + 0x448, 0x448, 0x438, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I16 */ + {0x460, 0x2C, 0x2C, 0x5c, 0x30, 0x460, 0x30, 0x460, -1, 0x460, 0x30, 0x464, -1, + 0x448, 0x448, 0x438, 0x440, 0x5c, -1, 0x464, -1, 0xbc, -1, 0xbc, -1, 0xbc, -1, -1}, /* I17 */ + {0x2C, 0x460, 0x2C, 0x2C, 0x5c, -1, 0x460, -1, 0x460, -1, 0x464, -1, 0x464, + 0x448, 0x448, 0x438, 0x440, -1, 0x5c, 0x464, -1, -1, 0xbc, -1, 0xbc, -1, -1, -1}, /* I18 */ + {0x460, 0x2C, 0x460, 0x460, 0x460, 0x460, 0x30, 0x460, -1, 0x460, 0x30, 0x464, -1, + 0x448, 0x448, 0x438, 0x444, 0x464, -1, 0x5c, 0x5c, 0xbc, -1, 0xbc, -1, -1, -1, -1}, /* I19 */ + {0x2C, 0x460, 0x460, 0x460, 0x460, -1, 0x460, -1, 0x460, -1, 0x464, -1, 0x464, + 0x448, 0x448, 0x438, 0x444, -1, 0x464, 0x5c, 0x5c, -1, 0xbc, -1, 0xbc, -1, -1, -1}, /* I20 */ + {0xbc, 0xbc, 0xbc, 0xbc, 0x30, -1, 0x30, 0xbc, 0xbc, 0xbc, 0x30, -1, 0xbc, + 0x44c, 0x44c, 0x438, 0x440, -1, -1, 0xbc, 0xbc, -1, -1, -1, -1, -1, -1, -1}, /* I21 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I22 */ +}; + + +/** +* shift connection of register +*/ +static const short mShiftConnectionReg[Soc_Aud_InterConnectionInput_Num_Input_MT6755] + [Soc_Aud_InterConnectionOutput_Num_Output_MT6755] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 */ + {0x20, 0x20, 0x24, 0x24, 0x28, 0x30, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0x438, -1, -1, -1, 0x464, 0x464, -1, -1, -1, -1, -1}, /* I00 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, 0x30, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0x440, -1, -1, 0x464, 0x464, -1, -1, -1, -1, -1}, /* I01 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I02 */ + {-1, -1, 0x30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I03 */ + {-1, -1, 0x30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I04 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, -1, -1, -1, -1, -1, 0x2C, -1, + -1, -1, -1, -1, -1, -1, 0x464, 0x464, -1, -1, -1, -1, -1}, /* I05 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0x464, -1, -1, -1, -1, -1, -1}, /* I06 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, -1, -1, -1, -1, -1, 0x2C, -1, + -1, -1, -1, -1, -1, -1, 0x464, -1, -1, -1, -1, -1, -1}, /* I07 */ + {0x20, 0x20, 0x24, 0x24, 0x28, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0x464, -1, -1, -1, -1, -1, -1}, /* I08 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I09 */ + {0x420, -1, -1, 0x420, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I10 */ + {0x420, 0x420, -1, -1, 0x420, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I11 */ + {0x438, 0x438, -1, 0x438, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I12 */ + {-1, 0x438, -1, -1, 0x438, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I13 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I14 */ + {0x2C, 0x2C, -1, 0x2C, 0x30, 0x30, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I15 */ + {0x2C, 0x2C, -1, 0x2C, 0x30, -1, 0x30, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I16 */ + {0x2C, 0x2C, 0xbc, 0x2C, 0x30, -1, 0x30, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I17 */ + {0x2C, 0x2C, 0xbc, 0x2C, 0x30, -1, 0x30, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I18 */ + {0x460, 0x2C, 0x460, 0x460, 0x460, -1, 0x30, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I19 */ + {0x2C, 0x460, 0x460, 0x460, 0x460, -1, 0x30, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I20 */ + {0x2C, 0x2C, -1, 0x2C, 0x30, -1, 0x30, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0x440, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* I21 */ +}; + +/** +* connection state of register +*/ +static char mConnectionState[Soc_Aud_InterConnectionInput_Num_Input_MT6755] + [Soc_Aud_InterConnectionOutput_Num_Output_MT6755] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I00 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I01 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I02 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I03 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I04 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I05 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I06 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I07 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I08 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I09 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I10 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I11 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I12 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I13 */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* I14 */ + /* {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // I15 */ + /* {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // I16 */ +}; + +typedef bool (*connection_function)(uint32); + +bool SetDl1ToI2s0(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I05, + Soc_Aud_InterConnectionOutput_O00); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I06, + Soc_Aud_InterConnectionOutput_O01); + return true; +} + +bool SetDl1ToI2s1Dac(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I05, + Soc_Aud_InterConnectionOutput_O03); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I06, + Soc_Aud_InterConnectionOutput_O04); + return true; +} + +bool SetI2s2Adc2ToVulData2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I23, + Soc_Aud_InterConnectionOutput_O21); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I24, + Soc_Aud_InterConnectionOutput_O22); + return true; +} + +bool SetI2s2AdcToVul(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O09); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I04, + Soc_Aud_InterConnectionOutput_O10); + return true; +} + +bool SetDl1ToAwb(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I05, + Soc_Aud_InterConnectionOutput_O05); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I06, + Soc_Aud_InterConnectionOutput_O06); + return true; +} + +bool SetDl2ToAwb(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I07, + Soc_Aud_InterConnectionOutput_O05); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I08, + Soc_Aud_InterConnectionOutput_O06); + return true; +} + +bool SetDl1ToDaiBtOut(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I05, + Soc_Aud_InterConnectionOutput_O02); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I06, + Soc_Aud_InterConnectionOutput_O02); + return true; +} + +bool SetModem1InCh1ToI2s3(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O00); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O01); + return true; +} + +bool SetModem2InCh1ToI2s3(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O00); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O01); + return true; +} + +bool SetI2s0Ch2ToModem1OutCh4(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I01, + Soc_Aud_InterConnectionOutput_O27); + return true; +} + +bool SetI2s0Ch2ToModem2OutCh4(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I01, + Soc_Aud_InterConnectionOutput_O24); + return true; +} + +bool SetDl2ToI2s1Dac(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I07, + Soc_Aud_InterConnectionOutput_O03); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I08, + Soc_Aud_InterConnectionOutput_O04); + return true; +} + +bool SetDl2ToI2s1Dac2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I07, + Soc_Aud_InterConnectionOutput_O28); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I08, + Soc_Aud_InterConnectionOutput_O29); + return true; +} + +bool SetDl2ToVul(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I07, + Soc_Aud_InterConnectionOutput_O09); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I08, + Soc_Aud_InterConnectionOutput_O10); + return true; +} + +bool SetI2s0ToHwGain1Out(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I00, + Soc_Aud_InterConnectionOutput_O13); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I01, + Soc_Aud_InterConnectionOutput_O14); + return true; +} + +bool SetHwGain1InToI2s1Dac(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I10, + Soc_Aud_InterConnectionOutput_O03); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I11, + Soc_Aud_InterConnectionOutput_O04); + return true; +} + +bool SetHwGain1InToI2s1Dac2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I10, + Soc_Aud_InterConnectionOutput_O28); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I11, + Soc_Aud_InterConnectionOutput_O29); + return true; +} + +bool SetI2s0ToAwb(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I00, + Soc_Aud_InterConnectionOutput_O05); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I01, + Soc_Aud_InterConnectionOutput_O06); + return true; +} + +bool SetModem2InCh1ToModemDai(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O12); + return true; +} + +bool SetModem1InCh1ToModemDai(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O12); + return true; +} + +bool SetModem2InCh1ToI2s1Dac2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O28); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O29); + return true; +} + +bool SetModem2InCh2ToI2s1Dac2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I21, + Soc_Aud_InterConnectionOutput_O28); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I21, + Soc_Aud_InterConnectionOutput_O29); + return true; +} + +bool SetModem1InCh1ToI2s1Dac2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O28); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O29); + return true; +} + +bool SetModem1InCh2ToI2s1Dac2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I22, + Soc_Aud_InterConnectionOutput_O28); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I22, + Soc_Aud_InterConnectionOutput_O29); + return true; +} + +bool SetDl1Ch1ToModem2OutCh4(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I05, + Soc_Aud_InterConnectionOutput_O24); + return true; +} + +bool SetDl1ToHwGain1Out(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I15, + Soc_Aud_InterConnectionOutput_O13); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I16, + Soc_Aud_InterConnectionOutput_O14); + return true; +} + +bool SetMrgI2sInToHwGain1Out(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I15, + Soc_Aud_InterConnectionOutput_O13); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I16, + Soc_Aud_InterConnectionOutput_O14); + return true; +} + +bool SetMrgI2sInToAwb(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I15, + Soc_Aud_InterConnectionOutput_O05); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I16, + Soc_Aud_InterConnectionOutput_O06); + return true; +} + +bool SetI2s2AdcToI2s3(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O00); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I04, + Soc_Aud_InterConnectionOutput_O01); + return true; +} + +bool SetI2s2AdcToI2s1Dac(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O03); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I04, + Soc_Aud_InterConnectionOutput_O04); + return true; +} + +bool SetI2s2AdcToI2s1Dac2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O28); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I04, + Soc_Aud_InterConnectionOutput_O29); + return true; +} + +bool SetI2s2AdcCh1ToI2s3(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O00); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O01); + return true; +} + +bool SetI2s2AdcCh1ToI2s1Dac(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O03); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O04); + return true; +} + +bool SetI2s2AdcCh1ToI2s1Dac2(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O28); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O29); + return true; +} + +bool SetI2s2AdcToModem2Out(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O17); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I04, + Soc_Aud_InterConnectionOutput_O18); + return true; +} + +bool SetModem2InCh1ToI2s1Dac(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O03); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O04); + return true; +} + +bool SetDaiBtInToModem2Out(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I02, + Soc_Aud_InterConnectionOutput_O17); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I02, + Soc_Aud_InterConnectionOutput_O18); + return true; +} + +bool SetModem2InCh1ToDaiBtOut(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O02); + return true; +} + +bool SetI2s2AdcToModem1Out(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I03, + Soc_Aud_InterConnectionOutput_O07); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I04, + Soc_Aud_InterConnectionOutput_O08); + return true; +} + +bool SetModem1InCh1ToI2s1Dac(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O03); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O04); + return true; +} + +bool SetDaiBtInToModem1Out(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I02, + Soc_Aud_InterConnectionOutput_O07); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I02, + Soc_Aud_InterConnectionOutput_O08); + return true; +} + +bool SetModem1InCh1ToDaiBtOut(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O02); + return true; +} + +bool SetModem2InCh1ToAwbCh1(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I14, + Soc_Aud_InterConnectionOutput_O05); + return true; +} + +bool SetModem1InCh1ToAwbCh1(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I09, + Soc_Aud_InterConnectionOutput_O05); + return true; +} + +bool SetI2s0ToVul(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I00, + Soc_Aud_InterConnectionOutput_O09); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I01, + Soc_Aud_InterConnectionOutput_O10); + return true; +} + +bool SetDl1ToMrgI2sOut(uint32 ConnectionState) +{ + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I05, + Soc_Aud_InterConnectionOutput_O00); + SetConnectionState(ConnectionState, Soc_Aud_InterConnectionInput_I06, + Soc_Aud_InterConnectionOutput_O01); + return true; +} + +typedef struct connection_link_t { + uint32 input; + uint32 output; + connection_function connectionFunction; +} connection_link_t; + +static const connection_link_t mConnectionLink[] = { + {Soc_Aud_AFE_IO_Block_MEM_DL1, Soc_Aud_AFE_IO_Block_I2S3, SetDl1ToI2s0}, + {Soc_Aud_AFE_IO_Block_MEM_DL1, Soc_Aud_AFE_IO_Block_I2S1_DAC, SetDl1ToI2s1Dac}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC_2, Soc_Aud_AFE_IO_Block_MEM_VUL_DATA2, SetI2s2Adc2ToVulData2}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC, Soc_Aud_AFE_IO_Block_MEM_VUL, SetI2s2AdcToVul}, + {Soc_Aud_AFE_IO_Block_MEM_DL1, Soc_Aud_AFE_IO_Block_MEM_AWB, SetDl1ToAwb}, + {Soc_Aud_AFE_IO_Block_MEM_DL2, Soc_Aud_AFE_IO_Block_MEM_AWB, SetDl2ToAwb}, + {Soc_Aud_AFE_IO_Block_MEM_DL1, Soc_Aud_AFE_IO_Block_DAI_BT_OUT, SetDl1ToDaiBtOut}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_1_I_CH1, Soc_Aud_AFE_IO_Block_I2S3, SetModem1InCh1ToI2s3}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_2_I_CH1, Soc_Aud_AFE_IO_Block_I2S3, SetModem2InCh1ToI2s3}, + {Soc_Aud_AFE_IO_Block_I2S0_CH2, Soc_Aud_AFE_IO_Block_MODEM_PCM_1_O_CH4, SetI2s0Ch2ToModem1OutCh4}, + {Soc_Aud_AFE_IO_Block_I2S0_CH2, Soc_Aud_AFE_IO_Block_MODEM_PCM_2_O_CH4, SetI2s0Ch2ToModem2OutCh4}, + {Soc_Aud_AFE_IO_Block_MEM_DL2, Soc_Aud_AFE_IO_Block_I2S1_DAC, SetDl2ToI2s1Dac}, + {Soc_Aud_AFE_IO_Block_MEM_DL2, Soc_Aud_AFE_IO_Block_I2S1_DAC_2, SetDl2ToI2s1Dac2}, + {Soc_Aud_AFE_IO_Block_MEM_DL2, Soc_Aud_AFE_IO_Block_MEM_VUL, SetDl2ToVul}, + {Soc_Aud_AFE_IO_Block_I2S0, Soc_Aud_AFE_IO_Block_HW_GAIN1_OUT, SetI2s0ToHwGain1Out}, + {Soc_Aud_AFE_IO_Block_HW_GAIN1_IN, Soc_Aud_AFE_IO_Block_I2S1_DAC, SetHwGain1InToI2s1Dac}, + {Soc_Aud_AFE_IO_Block_HW_GAIN1_IN, Soc_Aud_AFE_IO_Block_I2S1_DAC_2, SetHwGain1InToI2s1Dac2}, + {Soc_Aud_AFE_IO_Block_I2S0, Soc_Aud_AFE_IO_Block_MEM_AWB, SetI2s0ToAwb}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_2_I_CH1, Soc_Aud_AFE_IO_Block_MEM_MOD_DAI, SetModem2InCh1ToModemDai}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_1_I_CH1, Soc_Aud_AFE_IO_Block_MEM_MOD_DAI, SetModem1InCh1ToModemDai}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_2_I_CH1, Soc_Aud_AFE_IO_Block_I2S1_DAC_2, SetModem2InCh1ToI2s1Dac2}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_2_I_CH2, Soc_Aud_AFE_IO_Block_I2S1_DAC_2, SetModem2InCh2ToI2s1Dac2}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_1_I_CH1, Soc_Aud_AFE_IO_Block_I2S1_DAC_2, SetModem1InCh1ToI2s1Dac2}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_1_I_CH2, Soc_Aud_AFE_IO_Block_I2S1_DAC_2, SetModem1InCh2ToI2s1Dac2}, + {Soc_Aud_AFE_IO_Block_MEM_DL1_CH1, Soc_Aud_AFE_IO_Block_MODEM_PCM_2_O_CH4, SetDl1Ch1ToModem2OutCh4}, + {Soc_Aud_AFE_IO_Block_MEM_DL1, Soc_Aud_AFE_IO_Block_HW_GAIN1_OUT, SetDl1ToHwGain1Out}, + {Soc_Aud_AFE_IO_Block_MRG_I2S_IN, Soc_Aud_AFE_IO_Block_HW_GAIN1_OUT, SetMrgI2sInToHwGain1Out}, + {Soc_Aud_AFE_IO_Block_MRG_I2S_IN, Soc_Aud_AFE_IO_Block_MEM_AWB, SetMrgI2sInToAwb}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC, Soc_Aud_AFE_IO_Block_I2S3, SetI2s2AdcToI2s3}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC, Soc_Aud_AFE_IO_Block_I2S1_DAC, SetI2s2AdcToI2s1Dac}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC, Soc_Aud_AFE_IO_Block_I2S1_DAC_2, SetI2s2AdcToI2s1Dac2}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC_CH1, Soc_Aud_AFE_IO_Block_I2S3, SetI2s2AdcCh1ToI2s3}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC_CH1, Soc_Aud_AFE_IO_Block_I2S1_DAC, SetI2s2AdcCh1ToI2s1Dac}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC_CH1, Soc_Aud_AFE_IO_Block_I2S1_DAC_2, SetI2s2AdcCh1ToI2s1Dac2}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC, Soc_Aud_AFE_IO_Block_MODEM_PCM_2_O, SetI2s2AdcToModem2Out}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_2_I_CH1, Soc_Aud_AFE_IO_Block_I2S1_DAC, SetModem2InCh1ToI2s1Dac}, + {Soc_Aud_AFE_IO_Block_DAI_BT_IN, Soc_Aud_AFE_IO_Block_MODEM_PCM_2_O, SetDaiBtInToModem2Out}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_2_I_CH1, Soc_Aud_AFE_IO_Block_DAI_BT_OUT, SetModem2InCh1ToDaiBtOut}, + {Soc_Aud_AFE_IO_Block_I2S2_ADC, Soc_Aud_AFE_IO_Block_MODEM_PCM_1_O, SetI2s2AdcToModem1Out}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_1_I_CH1, Soc_Aud_AFE_IO_Block_I2S1_DAC, SetModem1InCh1ToI2s1Dac}, + {Soc_Aud_AFE_IO_Block_DAI_BT_IN, Soc_Aud_AFE_IO_Block_MODEM_PCM_1_O, SetDaiBtInToModem1Out}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_1_I_CH1, Soc_Aud_AFE_IO_Block_DAI_BT_OUT, SetModem1InCh1ToDaiBtOut}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_2_I_CH1, Soc_Aud_AFE_IO_Block_MEM_AWB_CH1, SetModem2InCh1ToAwbCh1}, + {Soc_Aud_AFE_IO_Block_MODEM_PCM_1_I_CH1, Soc_Aud_AFE_IO_Block_MEM_AWB_CH1, SetModem1InCh1ToAwbCh1}, + {Soc_Aud_AFE_IO_Block_I2S0, Soc_Aud_AFE_IO_Block_MEM_VUL, SetI2s0ToVul}, + {Soc_Aud_AFE_IO_Block_MEM_DL1, Soc_Aud_AFE_IO_Block_MRG_I2S_OUT, SetDl1ToMrgI2sOut} +}; +static const int CONNECTION_LINK_NUM = sizeof(mConnectionLink) / sizeof(mConnectionLink[0]); + +static bool CheckBitsandReg(short regaddr, char bits) +{ + if (regaddr <= 0 || bits < 0) { + pr_debug("regaddr = %x bits = %d\n", regaddr, bits); + return false; + } + return true; +} + +bool SetConnectionState(uint32 ConnectionState, uint32 Input, uint32 Output) +{ + /* pr_debug("SetinputConnection ConnectionState = %d + Input = %d Output = %d\n", ConnectionState, Input, Output); */ + if ((mConnectionTable[Input][Output]) < 0) { + pr_warn("no connection mpConnectionTable[%d][%d] = %d\n", Input, Output, + mConnectionTable[Input][Output]); + } else if ((mConnectionTable[Input][Output]) == 0) { + pr_warn("test only !! mpConnectionTable[%d][%d] = %d\n", Input, Output, + mConnectionTable[Input][Output]); + } else { + if (mConnectionTable[Input][Output]) { + int connectionBits = 0; + int connectReg = 0; + + switch (ConnectionState) { + case Soc_Aud_InterCon_DisConnect: + { + /* pr_debug("nConnectionState = %d\n", ConnectionState); */ + if ((mConnectionState[Input][Output] & + Soc_Aud_InterCon_Connection) == + Soc_Aud_InterCon_Connection) { + /* here to disconnect connect bits */ + connectionBits = mConnectionbits[Input][Output]; + connectReg = mConnectionReg[Input][Output]; + if (CheckBitsandReg(connectReg, connectionBits)) { + Afe_Set_Reg(connectReg, 0 << connectionBits, + 1 << connectionBits); + mConnectionState[Input][Output] &= + ~(Soc_Aud_InterCon_Connection); + } + } + if ((mConnectionState[Input][Output] & + Soc_Aud_InterCon_ConnectionShift) == + Soc_Aud_InterCon_ConnectionShift) { + /* here to disconnect connect shift bits */ + connectionBits = + mShiftConnectionbits[Input][Output]; + connectReg = mShiftConnectionReg[Input][Output]; + if (CheckBitsandReg(connectReg, connectionBits)) { + Afe_Set_Reg(connectReg, 0 << connectionBits, + 1 << connectionBits); + mConnectionState[Input][Output] &= + ~(Soc_Aud_InterCon_ConnectionShift); + } + } + break; + } + case Soc_Aud_InterCon_Connection: + { + /* pr_debug("nConnectionState = %d\n", ConnectionState); */ + /* here to disconnect connect shift bits */ + connectionBits = mConnectionbits[Input][Output]; + connectReg = mConnectionReg[Input][Output]; + if (CheckBitsandReg(connectReg, connectionBits)) { + Afe_Set_Reg(connectReg, 1 << connectionBits, + 1 << connectionBits); + mConnectionState[Input][Output] |= + Soc_Aud_InterCon_Connection; + } + break; + } + case Soc_Aud_InterCon_ConnectionShift: + { + /* pr_debug("nConnectionState = %d\n", ConnectionState); */ + if ((mConnectionTable[Input][Output] & + Soc_Aud_InterCon_ConnectionShift) != + Soc_Aud_InterCon_ConnectionShift) { + pr_err("donn't support shift opeartion"); + break; + } + connectionBits = mShiftConnectionbits[Input][Output]; + connectReg = mShiftConnectionReg[Input][Output]; + if (CheckBitsandReg(connectReg, connectionBits)) { + Afe_Set_Reg(connectReg, 1 << connectionBits, + 1 << connectionBits); + mConnectionState[Input][Output] |= + Soc_Aud_InterCon_ConnectionShift; + } + break; + } + default: + pr_err("no this state ConnectionState = %d\n", ConnectionState); + break; + } + } + } + return true; +} +EXPORT_SYMBOL(SetConnectionState); + +connection_function GetConnectionFunction(uint32 Aud_block_In, uint32 Aud_block_Out) +{ + connection_function connectionFunction = 0; + int i = 0; + + for (i = 0; i < CONNECTION_LINK_NUM; i++) { + if ((mConnectionLink[i].input == Aud_block_In) && + (mConnectionLink[i].output == Aud_block_Out)) { + return mConnectionLink[i].connectionFunction; + } + } + return connectionFunction; +} + +bool SetIntfConnectionState(uint32 ConnectionState, uint32 Aud_block_In, uint32 Aud_block_Out) +{ + bool ret = false; + connection_function connectionFunction = GetConnectionFunction(Aud_block_In, Aud_block_Out); + + if (0 == connectionFunction) { + pr_warn("no this connection function\n"); + return ret; + } + return connectionFunction(ConnectionState); +} +EXPORT_SYMBOL(SetIntfConnectionState); + +bool SetIntfConnectionFormat(uint32 ConnectionFormat, uint32 Aud_block) +{ + switch (Aud_block) { + case Soc_Aud_AFE_IO_Block_I2S3: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O00); + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O01); + break; + } + case Soc_Aud_AFE_IO_Block_I2S1_DAC: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O03); + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O04); + break; + } + case Soc_Aud_AFE_IO_Block_MEM_VUL: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O09); + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O10); + break; + } + case Soc_Aud_AFE_IO_Block_MEM_VUL_DATA2: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O21); + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O22); + break; + } + case Soc_Aud_AFE_IO_Block_DAI_BT_OUT: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O02); + break; + } + case Soc_Aud_AFE_IO_Block_I2S1_DAC_2: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O28); + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O29); + break; + } + case Soc_Aud_AFE_IO_Block_MEM_MOD_DAI: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O12); + break; + } + case Soc_Aud_AFE_IO_Block_MEM_AWB: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O05); + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O06); + break; + } + case Soc_Aud_AFE_IO_Block_MRG_I2S_OUT: + { + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O00); + SetoutputConnectionFormat(ConnectionFormat, + Soc_Aud_InterConnectionOutput_O01); + break; + } + default: + pr_warn("no this Aud_block = %d\n", Aud_block); + break; + } + return true; +} +EXPORT_SYMBOL(SetIntfConnectionFormat); + diff --git a/sound/soc/mediatek/mt6755/mt_soc_pcm_platform.h b/sound/soc/mediatek/mt6755/mt_soc_pcm_platform.h new file mode 100644 index 0000000000000000000000000000000000000000..2cd447f684c2f6a45736fb98c0b7b4edecfae593 --- /dev/null +++ b/sound/soc/mediatek/mt6755/mt_soc_pcm_platform.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/****************************************************************************** +* + * + * Filename: + * --------- + * mt_soc_pcm_common + * + * Project: + * -------- + * mt_soc_common function + * + * Description: + * ------------ + * Common function + * + * Author: + * ------- + * Chipeng Chang (MTK02308) + * + *--------------------------------------------------------------------------- +--- + * + +*******************************************************************************/ + +#ifndef AUDIO_MT6797_SOUND_H +#define AUDIO_MT6797_SOUND_H + +#include "AudDrv_Common.h" +#include "AudDrv_Def.h" +#include "AudDrv_Afe.h" +#include "AudDrv_Ana.h" +#include "AudDrv_Clk.h" +#include "AudDrv_Kernel.h" +#include "mt_soc_afe_control.h" +#include "mt_soc_digital_type.h" +#include "mt_soc_analog_type.h" +#include "AudDrv_Common_func.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +/*#include */ +#include +/*#include */ +/*#include */ +/*#include */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ + +/* #define EFUSE_HP_TRIM */ +#define CHIP_SRAM_SIZE (36*1024) + +/* + PCM buffer size and period size setting +*/ +#define BT_DAI_MAX_BUFFER_SIZE (16*1024) +#define BT_DAI_MIN_PERIOD_SIZE 1 +#define BT_DAI_MAX_PERIOD_SIZE BT_DAI_MAX_BUFFER_SIZE + +#define Dl1_MAX_BUFFER_SIZE (48*1024) +#define Dl1_MIN_PERIOD_SIZE 1 +#define Dl1_MAX_PERIOD_SIZE Dl1_MAX_BUFFER_SIZE + +#define Dl2_MAX_BUFFER_SIZE (48*1024) +#define Dl2_MIN_PERIOD_SIZE 1 +#define Dl2_MAX_PERIOD_SIZE Dl2_MAX_BUFFER_SIZE +#define Dl3_MAX_BUFFER_SIZE (32*1024) +#define Dl3_MIN_PERIOD_SIZE 1 +#define Dl3_MAX_PERIOD_SIZE Dl3_MAX_BUFFER_SIZE + +#define MAX_BUFFER_SIZE (32*1024) +#define MIN_PERIOD_SIZE 1 +#define MAX_PERIOD_SIZE MAX_BUFFER_SIZE + +#define UL1_MAX_BUFFER_SIZE (32*1024) +#define UL1_MIN_PERIOD_SIZE 1 +#define UL1_MAX_PERIOD_SIZE UL1_MAX_BUFFER_SIZE + +#define UL2_MAX_BUFFER_SIZE (32*1024) +#define UL2_MIN_PERIOD_SIZE 1 +#define UL2_MAX_PERIOD_SIZE UL2_MAX_BUFFER_SIZE + +#define AWB_MAX_BUFFER_SIZE (64*1024) +#define AWB_MIN_PERIOD_SIZE 1 +#define AWB_MAX_PERIOD_SIZE AWB_MAX_BUFFER_SIZE + +#define MOD_DAI_MAX_BUFFER_SIZE (16*1024) +#define MOD_DAI_MIN_PERIOD_SIZE (1) +#define MOD_DAI_MAX_PERIOD_SIZE MOD_DAI_MAX_BUFFER_SIZE + +#define HDMI_MAX_BUFFER_SIZE (384*1024) +#define HDMI_MIN_PERIOD_SIZE 1 +#define HDMI_MAX_PERIODBYTE_SIZE HDMI_MAX_BUFFER_SIZE +#define HDMI_MAX_2CH_16BIT_PERIOD_SIZE (HDMI_MAX_PERIODBYTE_SIZE/(2*2)) /* 2 channels , 16bits */ +#define HDMI_MAX_8CH_16BIT_PERIOD_SIZE (HDMI_MAX_PERIODBYTE_SIZE/(8*2)) /* 8 channels , 16bits */ +#define HDMI_MAX_2CH_24BIT_PERIOD_SIZE (HDMI_MAX_PERIODBYTE_SIZE/(2*2*2)) /* 2 channels , 24bits */ +#define HDMI_MAX_8CH_24BIT_PERIOD_SIZE (HDMI_MAX_PERIODBYTE_SIZE/(8*2*2)) /* 8 channels , 24bits */ + +#define MRGRX_MAX_BUFFER_SIZE (64*1024) +#define MRGRX_MIN_PERIOD_SIZE 1 +#define MRGRX_MAX_PERIOD_SIZE MRGRX_MAX_BUFFER_SIZE + +#define FM_I2S_MAX_BUFFER_SIZE (64*1024) +#define FM_I2S_MIN_PERIOD_SIZE 1 +#define FM_I2S_MAX_PERIOD_SIZE MRGRX_MAX_BUFFER_SIZE + +#define AUDIO_SRAM_PLAYBACK_FULL_SIZE (1024 * 48) +#define AUDIO_SRAM_PLAYBACK_PARTIAL_SIZE (1024 * 48) +#define AUDIO_DRAM_PLAYBACK_SIZE (1024 * 48) + +#define AUDIO_SRAM_CAPTURE_SIZE (1024 * 48) +#define AUDIO_DRAM_CAPTURE_SIZE (1024 * 48) +#endif diff --git a/tools/dct/old_dct/DCT.log b/tools/dct/old_dct/DCT.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/dct/old_dct/MT6750.fig b/tools/dct/old_dct/MT6750.fig new file mode 100644 index 0000000000000000000000000000000000000000..75089c5dcbb29a8be9ed20214987464c559f3e10 --- /dev/null +++ b/tools/dct/old_dct/MT6750.fig @@ -0,0 +1,290 @@ +[Chip Type] +Chip = MT6750 +GPIO_Pull_Sel = 1 +PMIC_Config = 1 +PMIC_ON_OFF_CONFIG = 1 +GPIO_ModeNum = 8 +EINT_MD1_Config = 1 +EINT_MD1_SRC_PIN = 1 +POWER_Config = 1 +POWER_COUNT = 4 +SpecialKey_Config = 1 +I2C_Config = 1 +CLOCK_BUFFER_CONFIG = 1 +Extend_Key_Config=1 +Reset_Key_Config = 1 +PMIC_APP_Ver = 2 +PMIC_APP_COUNT = 6 +MD1_EINT_SRC_PIN_CFG = 1 +AndroidPhone = 1 + +[GPIO] +GPIO0 = MODE0(GPIO0) MODE1() MODE2(EXT_FRAME_SYNC) MODE3(CLKM0) MODE4(IDDIG) MODE5(C2K_EINT0) MODE6(I2S3_MCK) MODE7() PD SMT_GROUP(0) +GPIO1 = MODE0(GPIO1) MODE1() MODE2(EXT_FRAME_SYNC) MODE3(CLKM1) MODE4(USB_DRVVBUS) MODE5(C2K_EINT1) MODE6(I2S3_BCK) MODE7() PD SMT_GROUP(0) +GPIO2 = MODE0(GPIO2) MODE1(CMFLASH) MODE2(UTXD1) MODE3(CLKM2) MODE4(MD_URXD2) MODE5(C2K_UTXD1) MODE6(I2S3_LRCK) MODE7() PD SMT_GROUP(0) +GPIO3 = MODE0(GPIO3) MODE1(PWM_A) MODE2(URXD1) MODE3(CLKM3) MODE4(MD_UTXD2) MODE5(C2K_URXD1) MODE6(I2S3_DO) MODE7(SPI1_B_MI) PD SMT_GROUP(0) +GPIO4 = MODE0(GPIO4) MODE1(PWM_B) MODE2(I2S0_MCK) MODE3(UCTS0) MODE4(MD_URXD1) MODE5(C2K_UTXD0) MODE6(ANT_SEL3) MODE7(SPI1_B_MI) PD SMT_GROUP(1) +GPIO5 = MODE0(GPIO5) MODE1(PWM_C) MODE2(I2S0_BCK) MODE3(URTS0) MODE4(MD_UTXD1) MODE5(C2K_URXD0) MODE6(ANT_SEL4) MODE7(SPI1_B_CSB) PD SMT_GROUP(1) +GPIO6 = MODE0(GPIO6) MODE1(IRTX_OUT) MODE2(I2S0_LRCK) MODE3(IDDIG) MODE4(MD_URXD0) MODE5(SDA0) MODE6(ANT_SEL5) MODE7(SPI1_B_MO) PD SMT_GROUP(1) +GPIO7 = MODE0(GPIO7) MODE1(IRTX_OUT) MODE2(I2S0_DI) MODE3(USB_DRVVBUS) MODE4(MD_UTXD0) MODE5(SCL0) MODE6(PCC_PPC_IO) MODE7(SPI1_B_CLK) PD SMT_GROUP(1) +GPIO8 = MODE0(GPIO8) MODE1(PWM_A) MODE2(PCC_PPC_IO) MODE3() MODE4(CONN_MCU_TRST_B) MODE5(C2K_DM_JTINTP) MODE6(IO_JTAG_TRSTN) MODE7(DBG_MON_A44) PD SMT_GROUP(2) +GPIO9 = MODE0(GPIO9) MODE1(PWM_B) MODE2(UCTS1) MODE3(DAP_SIB1_SWD) MODE4(CONN_MCU_DBGACK_N) MODE5(IRTX_OUT) MODE6() MODE7(DBG_MON_A45) PD SMT_GROUP(3) +GPIO10 = MODE0(GPIO10) MODE1(PWM_C) MODE2(URTS1) MODE3(DAP_SIB1_SWCK) MODE4(CONN_MCU_DBGI_N) MODE5(EXT_FRAME_SYNC) MODE6() MODE7(DBG_MON_A46) PD SMT_GROUP(3) +GPIO11 = MODE0(GPIO11) MODE1(IRTX_OUT) MODE2(IDDIG) MODE3(I2S1_MCK) MODE4(PWM_B) MODE5(CLKM0) MODE6(SRCLKENAI1) MODE7() PD SMT_GROUP(4) +GPIO12 = MODE0(GPIO12) MODE1(IRTX_OUT) MODE2(USB_DRVVBUS) MODE3(I2S2_DI) MODE4(PWM_C) MODE5(CLKM1) MODE6(CMFLASH) MODE7() PD SMT_GROUP(5) +GPIO13 = MODE0(GPIO13) MODE1(DPI_D0) MODE2(MRG_SYNC) MODE3(PCM0_SYNC) MODE4(MD_URXD0) MODE5(C2K_EINT0) MODE6(I2S0_MCK) MODE7(DBG_MON_A19) PD SMT_GROUP(6) +GPIO14 = MODE0(GPIO14) MODE1(DPI_D1) MODE2(MRG_CLK) MODE3(PCM0_CLK) MODE4(MD_UTXD0) MODE5(C2K_EINT1) MODE6(I2S0_BCK) MODE7(DBG_MON_A20) PD SMT_GROUP(6) +GPIO15 = MODE0(GPIO15) MODE1(DPI_D2) MODE2(MRG_DO) MODE3(PCM0_DO) MODE4(MD_URXD1) MODE5(C2K_DM_EINT0) MODE6(I2S0_LRCK) MODE7(DBG_MON_A21) PD SMT_GROUP(6) +GPIO16 = MODE0(GPIO16) MODE1(DPI_D3) MODE2(MRG_DI) MODE3(PCM0_DI) MODE4(MD_UTXD1) MODE5(C2K_DM_EINT1) MODE6(I2S0_DI) MODE7(DBG_MON_A22) PD SMT_GROUP(6) +GPIO17 = MODE0(GPIO17) MODE1(DPI_D4) MODE2(UCTS1) MODE3(CONN_MCU_TRST_B) MODE4(MD_URXD2) MODE5(C2K_URXD0) MODE6(I2S1_MCK) MODE7(DBG_MON_A23) PD SMT_GROUP(7) +GPIO18 = MODE0(GPIO18) MODE1(DPI_D5) MODE2(URTS1) MODE3(CONN_MCU_DBGI_N) MODE4(MD_UTXD2) MODE5(C2K_UTXD0) MODE6(I2S1_BCK) MODE7(DBG_MON_A24) PD SMT_GROUP(7) +GPIO19 = MODE0(GPIO19) MODE1(DPI_D6) MODE2(URXD1) MODE3(CONN_MCU_TDO) MODE4(MD_INT2_C2K_UIM1_HOT_PLUG) MODE5() MODE6(I2S1_LRCK) MODE7(DBG_MON_A25) PD SMT_GROUP(7) +GPIO20 = MODE0(GPIO20) MODE1(DPI_D7) MODE2(UTXD1) MODE3(CONN_MCU_DBGACK_N) MODE4(MD_INT1_C2K_UIM0_HOT_PLUG) MODE5() MODE6(I2S1_DO) MODE7(DBG_MON_A26) PD SMT_GROUP(7) +GPIO21 = MODE0(GPIO21) MODE1(DPI_D8) MODE2(SRCLKENAI1) MODE3(CONN_MCU_TMS) MODE4(DAP_SIB1_SWD) MODE5(CONN_MCU_AICE_TMSC) MODE6(I2S2_MCK) MODE7(DBG_MON_A27) PD SMT_GROUP(8) +GPIO22 = MODE0(GPIO22) MODE1(DPI_D9) MODE2(EXT_FRAME_SYNC) MODE3(CONN_MCU_TCK) MODE4(DAP_SIB1_SWCK) MODE5(CONN_MCU_AICE_TCKC) MODE6(I2S2_BCK) MODE7(DBG_MON_A28) PD SMT_GROUP(8) +GPIO23 = MODE0(GPIO23) MODE1(DPI_D10) MODE2(IDDIG) MODE3(CONN_MCU_TDI) MODE4() MODE5(PWM_B) MODE6(I2S2_LRCK) MODE7(DBG_MON_A29) PD SMT_GROUP(8) +GPIO24 = MODE0(GPIO24) MODE1(DPI_D11) MODE2(USB_DRVVBUS) MODE3(CONN_DSP_JCK) MODE4(SPI1_A_MI) MODE5(PWM_C) MODE6(I2S2_DI) MODE7(DBG_MON_A30) PD SMT_GROUP(8) +GPIO25 = MODE0(GPIO25) MODE1(DPI_HSYNC) MODE2(SPI1_A_MI) MODE3(CONN_DSP_JMS) MODE4(CLKM0) MODE5(C2K_UTXD1) MODE6(I2S3_MCK) MODE7(DBG_MON_A31) PD SMT_GROUP(9) +GPIO26 = MODE0(GPIO26) MODE1(DPI_VSYNC) MODE2(SPI1_A_CSB) MODE3(CONN_DSP_JDI) MODE4(CLKM1) MODE5(C2K_URXD1) MODE6(I2S3_BCK) MODE7(DBG_MON_A32) PD SMT_GROUP(9) +GPIO27 = MODE0(GPIO27) MODE1(DPI_DE) MODE2(SPI1_A_MO) MODE3(CONN_DSP_JDO) MODE4(CLKM2) MODE5(C2K_DM_EINT2) MODE6(I2S3_LRCK) MODE7(DBG_MON_A33) PD SMT_GROUP(9) +GPIO28 = MODE0(GPIO28) MODE1(DPI_CK) MODE2(SPI1_A_CLK) MODE3(CONN_DSP_JINTP) MODE4(CLKM3) MODE5(C2K_DM_EINT3) MODE6(I2S3_DO) MODE7(DBG_MON_A34) PD SMT_GROUP(9) +GPIO29 = MODE0(GPIO29) MODE1(SRCLKENA1) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(10) +GPIO30 = MODE0(GPIO30) MODE1(MSDC1_CLK) MODE2(IO_JTAG_TCK) MODE3() MODE4(CONN_DSP_JCK) MODE5(C2K_DM_OTCK) MODE6(C2K_TCK) MODE7(DBG_MON_A53) PD SMT_GROUP(11) +GPIO31 = MODE0(GPIO31) MODE1(MSDC1_DAT3) MODE2() MODE3(DAP_SIB1_SWD) MODE4(CONN_DSP_JINTP) MODE5(C2K_DM_JTINTP) MODE6(C2K_RTCK) MODE7(DBG_MON_A54) PU SMT_GROUP(12) +GPIO32 = MODE0(GPIO32) MODE1(MSDC1_CMD) MODE2(IO_JTAG_TMS) MODE3() MODE4(CONN_DSP_JMS) MODE5(C2K_DM_OTMS) MODE6(C2K_TMS) MODE7(DBG_MON_A55) PU SMT_GROUP(13) +GPIO33 = MODE0(GPIO33) MODE1(MSDC1_DAT0) MODE2(IO_JTAG_TDI) MODE3() MODE4(CONN_DSP_JDI) MODE5(C2K_DM_OTDI) MODE6(C2K_TDI) MODE7(DBG_MON_A56) PU SMT_GROUP(12) +GPIO34 = MODE0(GPIO34) MODE1(MSDC1_DAT2) MODE2(IO_JTAG_TRSTN) MODE3() MODE4() MODE5(DAP_SIB1_SWCK) MODE6(C2K_NTRST) MODE7(DBG_MON_A57) PU SMT_GROUP(12) +GPIO35 = MODE0(GPIO35) MODE1(MSDC1_DAT1) MODE2(IO_JTAG_TDO) MODE3() MODE4(CONN_DSP_JDO) MODE5(C2K_DM_OTDO) MODE6(C2K_TDO) MODE7(DBG_MON_A58) PU SMT_GROUP(12) +GPIO36 = MODE0(GPIO36) MODE1(MD1_SIM2_SIO) MODE2() MODE3(MD1_SIM1_SIO) MODE4() MODE5(C2K_UIM0_IO) MODE6(C2K_UIM1_IO) MODE7(DBG_MON_A38) PD SMT_GROUP(14) +GPIO37 = MODE0(GPIO37) MODE1(MD1_SIM2_SRST) MODE2() MODE3(MD1_SIM1_SRST) MODE4() MODE5(C2K_UIM0_RST) MODE6(C2K_UIM1_RST) MODE7(DBG_MON_A39) PD SMT_GROUP(14) +GPIO38 = MODE0(GPIO38) MODE1(MD1_SIM2_SCLK) MODE2() MODE3(MD1_SIM1_SCLK) MODE4() MODE5(C2K_UIM0_CLK) MODE6(C2K_UIM1_CLK) MODE7(DBG_MON_A40) PD SMT_GROUP(14) +GPIO39 = MODE0(GPIO39) MODE1(MD1_SIM1_SCLK) MODE2() MODE3(MD1_SIM2_SCLK) MODE4() MODE5(C2K_UIM0_CLK) MODE6(C2K_UIM1_CLK) MODE7(DBG_MON_A41) PD SMT_GROUP(15) +GPIO40 = MODE0(GPIO40) MODE1(MD1_SIM1_SRST) MODE2() MODE3(MD1_SIM2_SRST) MODE4() MODE5(C2K_UIM0_RST) MODE6(C2K_UIM1_RST) MODE7(DBG_MON_A42) PD SMT_GROUP(15) +GPIO41 = MODE0(GPIO41) MODE1(MD1_SIM1_SIO) MODE2() MODE3(MD1_SIM2_SIO) MODE4() MODE5(C2K_UIM0_IO) MODE6(C2K_UIM1_IO) MODE7(DBG_MON_A43) PD SMT_GROUP(15) +GPIO42 = MODE0(GPIO42) MODE1(IDDIG) MODE2(URXD1) MODE3(UCTS0) MODE4(SDA1) MODE5(EXT_FRAME_SYNC) MODE6(KPCOL2) MODE7(DBG_MON_A12) PD SMT_GROUP(16) +GPIO43 = MODE0(GPIO43) MODE1(USB_DRVVBUS) MODE2(UTXD1) MODE3(URTS0) MODE4(SCL1) MODE5(EXT_FRAME_SYNC) MODE6(KPROW2) MODE7(DBG_MON_A13) PD SMT_GROUP(16) +GPIO44 = MODE0(GPIO44) MODE1(DSI_TE) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A15) PD SMT_GROUP(17) +GPIO45 = MODE0(GPIO45) MODE1(MD_INT2_C2K_UIM1_HOT_PLUG) MODE2(URXD1) MODE3(UCTS1) MODE4(CLKM0) MODE5() MODE6(IDDIG) MODE7(DBG_MON_A17) PD SMT_GROUP(18) +GPIO46 = MODE0(GPIO46) MODE1(MD_INT1_C2K_UIM0_HOT_PLUG) MODE2(UTXD1) MODE3(URTS1) MODE4(PWM_B) MODE5() MODE6(USB_DRVVBUS) MODE7(DBG_MON_A18) PD SMT_GROUP(18) +GPIO47 = MODE0(GPIO47) MODE1(SCL_APPM) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(19) +GPIO48 = MODE0(GPIO48) MODE1(SDA_APPM) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(19) +GPIO49 = MODE0(GPIO49) MODE1(SCL3) MODE2(IDDIG) MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(20) +GPIO50 = MODE0(GPIO50) MODE1(SDA3) MODE2(IDDIG) MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(20) +GPIO51 = MODE0(GPIO51) MODE1(BPI_BUS15) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B0) PD SMT_GROUP(21) +GPIO52 = MODE0(GPIO52) MODE1(BPI_BUS14) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B1) PD SMT_GROUP(21) +GPIO53 = MODE0(GPIO53) MODE1(BPI_BUS13) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B2) PD SMT_GROUP(21) +GPIO54 = MODE0(GPIO54) MODE1(BPI_BUS12) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B3) PD SMT_GROUP(21) +GPIO55 = MODE0(GPIO55) MODE1(BPI_BUS11) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(21) +GPIO56 = MODE0(GPIO56) MODE1(BPI_BUS10) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(21) +GPIO57 = MODE0(GPIO57) MODE1(BPI_BUS9) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B4) PD SMT_GROUP(21) +GPIO58 = MODE0(GPIO58) MODE1(BPI_BUS8) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B5) PD SMT_GROUP(21) +GPIO59 = MODE0(GPIO59) MODE1(BPI_BUS7) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B6) PD SMT_GROUP(21) +GPIO60 = MODE0(GPIO60) MODE1(BPI_BUS6) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B7) PD SMT_GROUP(21) +GPIO61 = MODE0(GPIO61) MODE1(BPI_BUS5) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B8) PD SMT_GROUP(21) +GPIO62 = MODE0(GPIO62) MODE1(BPI_BUS4) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B9) PD SMT_GROUP(21) +GPIO63 = MODE0(GPIO63) MODE1(MIPI1_SDATA) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B10) PD SMT_GROUP(22) +GPIO64 = MODE0(GPIO64) MODE1(MIPI1_SCLK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B11) PD SMT_GROUP(22) +GPIO65 = MODE0(GPIO65) MODE1(MIPI0_SDATA) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B12) PD SMT_GROUP(22) +GPIO66 = MODE0(GPIO66) MODE1(MIPI0_SCLK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B13) PD SMT_GROUP(22) +GPIO67 = MODE0(GPIO67) MODE1(RFIC0_BSI_D2) MODE2(SPM_BSI_D2) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B14) PD SMT_GROUP(23) +GPIO68 = MODE0(GPIO68) MODE1(RFIC0_BSI_D1) MODE2(SPM_BSI_D1) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B15) PD SMT_GROUP(23) +GPIO69 = MODE0(GPIO69) MODE1(RFIC0_BSI_D0) MODE2(SPM_BSI_D0) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B16) PD SMT_GROUP(23) +GPIO70 = MODE0(GPIO70) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO71 = MODE0(GPIO71) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO72 = MODE0(GPIO72) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO73 = MODE0(GPIO73) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO74 = MODE0(GPIO74) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO75 = MODE0(GPIO75) MODE1(MIPI3_SDATA) MODE2(PWM_C) MODE3(IRTX_OUT) MODE4(I2S0_DI) MODE5(I2S2_DI) MODE6(ANT_SEL5) MODE7(DBG_MON_B19) PD SMT_GROUP(24) +GPIO76 = MODE0(GPIO76) MODE1(MIPI3_SCLK) MODE2(CLKM3) MODE3(EXT_FRAME_SYNC) MODE4(I2S0_LRCK) MODE5(I2S2_LRCK) MODE6(ANT_SEL4) MODE7(DBG_MON_B20) PD SMT_GROUP(24) +GPIO77 = MODE0(GPIO77) MODE1(MIPI2_SDATA) MODE2(USB_DRVVBUS) MODE3(IRTX_OUT) MODE4(I2S0_BCK) MODE5(I2S2_BCK) MODE6(ANT_SEL3) MODE7(DBG_MON_B21) PD SMT_GROUP(24) +GPIO78 = MODE0(GPIO78) MODE1(MIPI2_SCLK) MODE2(IDDIG) MODE3(EXT_FRAME_SYNC) MODE4(I2S0_MCK) MODE5(I2S2_MCK) MODE6(PCM1_DO0) MODE7(DBG_MON_B22) PD SMT_GROUP(24) +GPIO79 = MODE0(GPIO79) MODE1(BPI_BUS3) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B23) PD SMT_GROUP(25) +GPIO80 = MODE0(GPIO80) MODE1(BPI_BUS2) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B24) PD SMT_GROUP(25) +GPIO81 = MODE0(GPIO81) MODE1(BPI_BUS1) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B25) PD SMT_GROUP(25) +GPIO82 = MODE0(GPIO82) MODE1(BPI_BUS0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B26) PD SMT_GROUP(25) +GPIO83 = MODE0(GPIO83) MODE1(BPI_BUS23) MODE2(DET_BPI1) MODE3() MODE4(I2S3_DO) MODE5(I2S1_DO) MODE6(PCM1_DO1) MODE7(DBG_MON_B27) PD SMT_GROUP(26) +GPIO84 = MODE0(GPIO84) MODE1(BPI_BUS22) MODE2(DET_BPI0) MODE3() MODE4(I2S3_LRCK) MODE5(I2S1_LRCK) MODE6(PCM1_CLK) MODE7(DBG_MON_B28) PD SMT_GROUP(26) +GPIO85 = MODE0(GPIO85) MODE1(BPI_BUS21) MODE2(TX_SWAP3) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B29) PD SMT_GROUP(26) +GPIO86 = MODE0(GPIO86) MODE1(BPI_BUS20) MODE2(TX_SWAP2) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B30) PD SMT_GROUP(26) +GPIO87 = MODE0(GPIO87) MODE1(BPI_BUS19) MODE2(TX_SWAP1) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B31) PD SMT_GROUP(27) +GPIO88 = MODE0(GPIO88) MODE1(BPI_BUS18) MODE2(TX_SWAP0) MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(27) +GPIO89 = MODE0(GPIO89) MODE1(BPI_BUS17) MODE2(PA_VM1) MODE3() MODE4(I2S3_BCK) MODE5(I2S1_BCK) MODE6(PCM1_SYNC) MODE7() PD SMT_GROUP(27) +GPIO90 = MODE0(GPIO90) MODE1(BPI_BUS16) MODE2(PA_VM0) MODE3() MODE4(I2S3_MCK) MODE5(I2S1_MCK) MODE6(PCM1_DI) MODE7() PD SMT_GROUP(27) +GPIO91 = MODE0(GPIO91) MODE1(SDA1) MODE2(IDDIG) MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(28) +GPIO92 = MODE0(GPIO92) MODE1(SDA0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(29) +GPIO93 = MODE0(GPIO93) MODE1(SCL0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(29) +GPIO94 = MODE0(GPIO94) MODE1(SCL1) MODE2(IDDIG) MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(28) +GPIO95 = MODE0(GPIO95) MODE1(SPI0_MI) MODE2(MRG_SYNC) MODE3(PCM0_SYNC) MODE4(I2S1_BCK) MODE5(SPI0_MO) MODE6(DFD_TDO) MODE7(JTDO_SEL1) PD SMT_GROUP(30) +GPIO96 = MODE0(GPIO96) MODE1(SPI0_CSB) MODE2(MRG_DO) MODE3(PCM0_DO) MODE4(I2S1_LRCK) MODE5(SDA2) MODE6(DFD_TMS) MODE7(JTMS_SEL1) PD SMT_GROUP(30) +GPIO97 = MODE0(GPIO97) MODE1(SPI0_MO) MODE2(MRG_CLK) MODE3(PCM0_CLK) MODE4(I2S1_DO) MODE5(SPI0_MI) MODE6(DFD_TDI) MODE7(JTDI_SEL1) PD SMT_GROUP(30) +GPIO98 = MODE0(GPIO98) MODE1(SPI0_CLK) MODE2(MRG_DI) MODE3(PCM0_DI) MODE4(I2S1_MCK) MODE5(SCL2) MODE6(DFD_TCK_XI) MODE7(JTCK_SEL1) PD SMT_GROUP(30) +GPIO99 = MODE0(GPIO99) MODE1(SRCLKENAI0) MODE2(UTXD1) MODE3(EXT_FRAME_SYNC) MODE4(CLKM2) MODE5(PCC_PPC_IO) MODE6(ANT_SEL3) MODE7(SPI0_MI) PD SMT_GROUP(31) +GPIO100 = MODE0(GPIO100) MODE1(PWM_A) MODE2(URXD1) MODE3(MD_INT0) MODE4(CLKM3) MODE5(MD_INT2_C2K_UIM1_HOT_PLUG) MODE6(ANT_SEL4) MODE7(DBG_MON_A35) PD SMT_GROUP(31) +GPIO101 = MODE0(GPIO101) MODE1(KPROW1) MODE2(IRTX_OUT) MODE3(C2K_UTXD1) MODE4(C2K_UTXD0) MODE5(C2K_DM_EINT2) MODE6(ANT_SEL5) MODE7(DBG_MON_A36) PD SMT_GROUP(32) +GPIO102 = MODE0(GPIO102) MODE1(KPROW0) MODE2() MODE3() MODE4() MODE5(C2K_DM_EINT3) MODE6() MODE7(DBG_MON_A37) PD SMT_GROUP(32) +GPIO103 = MODE0(GPIO103) MODE1(KPCOL0) MODE2() MODE3() MODE4() MODE5(C2K_DM_EINT0) MODE6() MODE7() PU SMT_GROUP(32) +GPIO104 = MODE0(GPIO104) MODE1(KPCOL1) MODE2() MODE3(C2K_URXD1) MODE4(C2K_URXD0) MODE5(C2K_DM_EINT1) MODE6() MODE7() PD SMT_GROUP(32) +GPIO105 = MODE0(GPIO105) MODE1(URXD0) MODE2(UTXD0) MODE3(MD_URXD0) MODE4(MD_URXD1) MODE5(C2K_URXD0) MODE6(MD_URXD2) MODE7(C2K_URXD1) PU SMT_GROUP(33) +GPIO106 = MODE0(GPIO106) MODE1(UTXD0) MODE2(URXD0) MODE3(MD_UTXD0) MODE4(MD_UTXD1) MODE5(C2K_UTXD0) MODE6(MD_UTXD2) MODE7(C2K_UTXD1) PU SMT_GROUP(33) +GPIO107 = MODE0(GPIO107) MODE1(UCTS0) MODE2(I2S2_MCK) MODE3() MODE4(CONN_MCU_TDO) MODE5(C2K_DM_OTDO) MODE6(IO_JTAG_TDO) MODE7(DBG_MON_A6) PD SMT_GROUP(34) +GPIO108 = MODE0(GPIO108) MODE1(URTS0) MODE2(I2S2_BCK) MODE3() MODE4(CONN_MCU_TMS) MODE5(C2K_DM_OTMS) MODE6(IO_JTAG_TMS) MODE7(DBG_MON_A7) PD SMT_GROUP(34) +GPIO109 = MODE0(GPIO109) MODE1(CMMCLK1) MODE2(PWM_C) MODE3(MD_INT0) MODE4(CONN_MCU_AICE_TCKC) MODE5(MD_INT1_C2K_UIM0_HOT_PLUG) MODE6(CMFLASH) MODE7(DBG_MON_A9) PD SMT_GROUP(35) +GPIO110 = MODE0(GPIO110) MODE1(CLKM2) MODE2(I2S2_LRCK) MODE3() MODE4(CONN_MCU_TCK) MODE5(C2K_DM_OTCK) MODE6(IO_JTAG_TCK) MODE7(DBG_MON_A10) PD SMT_GROUP(36) +GPIO111 = MODE0(GPIO111) MODE1(CLKM1) MODE2(I2S2_DI) MODE3() MODE4(CONN_MCU_TDI) MODE5(C2K_DM_OTDI) MODE6(IO_JTAG_TDI) MODE7(DBG_MON_A11) PD SMT_GROUP(36) +GPIO112 = MODE0(GPIO112) MODE1(SCL2) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(37) +GPIO113 = MODE0(GPIO113) MODE1(SDA2) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(37) +GPIO114 = MODE0(GPIO114) MODE1(ANT_SEL0) MODE2(PWM_A) MODE3(CLKM0) MODE4(IRTX_OUT) MODE5(PCC_PPC_IO) MODE6() MODE7(DBG_MON_A47) PD SMT_GROUP(38) +GPIO115 = MODE0(GPIO115) MODE1(ANT_SEL1) MODE2(PWM_B) MODE3(CLKM1) MODE4(USB_DRVVBUS) MODE5(DAP_SIB1_SWD) MODE6() MODE7(DBG_MON_A48) PD SMT_GROUP(38) +GPIO116 = MODE0(GPIO116) MODE1(ANT_SEL2) MODE2(PWM_C) MODE3(CLKM2) MODE4(IDDIG) MODE5(DAP_SIB1_SWCK) MODE6(IRTX_OUT) MODE7(DBG_MON_A49) PD SMT_GROUP(38) +GPIO117 = MODE0(GPIO117) MODE1(F2W_DATA) MODE2(PTA_TXD) MODE3(PTA_RXD) MODE4(AUXIF_ST0) MODE5(C2K_UTXD1) MODE6(SDA0) MODE7(DBG_MON_A50) PD SMT_GROUP(39) +GPIO118 = MODE0(GPIO118) MODE1(F2W_CK) MODE2(PTA_RXD) MODE3(PTA_TXD) MODE4(AUXIF_CLK0) MODE5(C2K_URXD1) MODE6(SCL0) MODE7(DBG_MON_A51) PD SMT_GROUP(39) +GPIO119 = MODE0(GPIO119) MODE1(WB_RSTB) MODE2(URXD1) MODE3(UTXD1) MODE4() MODE5() MODE6() MODE7(DBG_MON_A52) PD SMT_GROUP(40) +GPIO120 = MODE0(GPIO120) MODE1(WB_SCLK) MODE2(UTXD1) MODE3(URXD1) MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(40) +GPIO121 = MODE0(GPIO121) MODE1(WB_SDATA) MODE2(AGPS_SYNC) MODE3() MODE4(AUXIF_ST1) MODE5(C2K_UTXD0) MODE6(SDA1) MODE7() PD SMT_GROUP(40) +GPIO122 = MODE0(GPIO122) MODE1(WB_SEN) MODE2(SRCLKENAI1) MODE3() MODE4(AUXIF_CLK1) MODE5(C2K_URXD0) MODE6(SCL1) MODE7() PD SMT_GROUP(40) +GPIO123 = MODE0(GPIO123) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO124 = MODE0(GPIO124) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO125 = MODE0(GPIO125) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO126 = MODE0(GPIO126) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO127 = MODE0(GPIO127) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO128 = MODE0(GPIO128) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO129 = MODE0(GPIO129) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO130 = MODE0(GPIO130) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO131 = MODE0(GPIO131) MODE1(WB_CTRL0) MODE2(MSDC2_DAT1) MODE3() MODE4() MODE5(C2K_NTRST) MODE6() MODE7() PD SMT_GROUP(41) +GPIO132 = MODE0(GPIO132) MODE1(WB_CTRL1) MODE2(MSDC2_CMD) MODE3() MODE4() MODE5(C2K_TCK) MODE6() MODE7() PD SMT_GROUP(42) +GPIO133 = MODE0(GPIO133) MODE1(WB_CTRL2) MODE2(MSDC2_CLK) MODE3() MODE4() MODE5(C2K_TDI) MODE6() MODE7() PD SMT_GROUP(43) +GPIO134 = MODE0(GPIO134) MODE1(WB_CTRL3) MODE2(MSDC2_DAT3) MODE3() MODE4() MODE5(C2K_TMS) MODE6() MODE7() PD SMT_GROUP(41) +GPIO135 = MODE0(GPIO135) MODE1(WB_CTRL4) MODE2(MSDC2_DAT0) MODE3() MODE4() MODE5(C2K_TDO) MODE6() MODE7() PD SMT_GROUP(41) +GPIO136 = MODE0(GPIO136) MODE1(WB_CTRL5) MODE2(MSDC2_DAT2) MODE3() MODE4() MODE5(C2K_RTCK) MODE6() MODE7() PD SMT_GROUP(41) +GPIO137 = MODE0(GPIO137) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO138 = MODE0(GPIO138) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO139 = MODE0(GPIO139) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO140 = MODE0(GPIO140) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO141 = MODE0(GPIO141) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO142 = MODE0(GPIO142) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO143 = MODE0(GPIO143) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO144 = MODE0(GPIO144) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO145 = MODE0(GPIO145) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO146 = MODE0(GPIO146) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO147 = MODE0(GPIO147) MODE1(RTC32K_CK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(44) +GPIO148 = MODE0(GPIO148) MODE1(WATCHDOG) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(45) +GPIO149 = MODE0(GPIO149) MODE1(AUD_CLK_MOSI) MODE2() MODE3(I2S1_BCK) MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(46) +GPIO150 = MODE0(GPIO150) MODE1(AUD_DAT_MOSI) MODE2(AUD_DAT_MISO) MODE3(I2S1_LRCK) MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(46) +GPIO151 = MODE0(GPIO151) MODE1(AUD_DAT_MISO) MODE2(AUD_DAT_MOSI) MODE3(I2S1_DO) MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(46) +GPIO152 = MODE0(GPIO152) MODE1(PWRAP_SPI0_MI) MODE2(PWRAP_SPI0_MO) MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(47) +GPIO153 = MODE0(GPIO153) MODE1(PWRAP_SPI0_CSN) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(47) +GPIO154 = MODE0(GPIO154) MODE1(PWRAP_SPI0_MO) MODE2(PWRAP_SPI0_MI) MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(47) +GPIO155 = MODE0(GPIO155) MODE1(PWRAP_SPI0_CK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(47) +GPIO156 = MODE0(GPIO156) MODE1(SRCLKENA0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(48) +GPIO157 = MODE0(GPIO157) MODE1(DISP_PWM) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A14) PD SMT_GROUP(17) +GPIO158 = MODE0(GPIO158) MODE1(LCM_RST) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A16) PD SMT_GROUP(17) +GPIO159 = MODE0(GPIO159) MODE1(RFIC0_BSI_EN) MODE2(SPM_BSI_EN) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B17) PD SMT_GROUP(23) +GPIO160 = MODE0(GPIO160) MODE1(RFIC0_BSI_CK) MODE2(SPM_BSI_CK) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B18) PD SMT_GROUP(23) +GPIO161 = MODE0(GPIO161) MODE1(CMMCLK0) MODE2() MODE3() MODE4(CONN_MCU_AICE_TMSC) MODE5() MODE6() MODE7(DBG_MON_A8) PD SMT_GROUP(49) +GPIO162 = MODE0(GPIO162) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO163 = MODE0(GPIO163) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO164 = MODE0(GPIO164) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO165 = MODE0(GPIO165) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO166 = MODE0(GPIO166) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO167 = MODE0(GPIO167) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO168 = MODE0(GPIO168) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO169 = MODE0(GPIO169) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO170 = MODE0(GPIO170) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO171 = MODE0(GPIO171) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO172 = MODE0(GPIO172) MODE1() MODE2(CMCSD2) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO173 = MODE0(GPIO173) MODE1() MODE2(CMCSD3) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO174 = MODE0(GPIO174) MODE1() MODE2(CMCSK) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO175 = MODE0(GPIO175) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO176 = MODE0(GPIO176) MODE1() MODE2(CMCSD0) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO177 = MODE0(GPIO177) MODE1() MODE2(CMCSD1) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO178 = MODE0(GPIO178) MODE1(MSDC0_DAT0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A0) PU SMT_GROUP(50) +GPIO179 = MODE0(GPIO179) MODE1(MSDC0_CLK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A1) PD SMT_GROUP(51) +GPIO180 = MODE0(GPIO180) MODE1(MSDC0_CMD) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A2) PU SMT_GROUP(52) +GPIO181 = MODE0(GPIO181) MODE1(MSDC0_DAT1) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A3) PU SMT_GROUP(50) +GPIO182 = MODE0(GPIO182) MODE1(MSDC0_DAT5) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A4) PU SMT_GROUP(50) +GPIO183 = MODE0(GPIO183) MODE1(MSDC0_DAT6) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A5) PU SMT_GROUP(50) +GPIO184 = MODE0(GPIO184) MODE1(MSDC0_DAT4) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A59) PU SMT_GROUP(50) +GPIO185 = MODE0(GPIO185) MODE1(MSDC0_RSTB) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A60) PU SMT_GROUP(53) +GPIO186 = MODE0(GPIO186) MODE1(MSDC0_DAT2) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A61) PU SMT_GROUP(50) +GPIO187 = MODE0(GPIO187) MODE1(MSDC0_DAT3) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A62) PU SMT_GROUP(50) +GPIO188 = MODE0(GPIO188) MODE1(MSDC0_DAT7) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A63) PU SMT_GROUP(50) +GPIO189 = MODE0(GPIO189) MODE1(MSDC0_DSL) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A64) PD SMT_GROUP(54) + +[GPO] + +[EINT] +EINT_COUNT = 160 +EINT_DEBOUNCE_TIME_COUNT = 12 + +[EINT_EX_PIN] + +[ADC] +ADC_COUNT = 6 + +[ADC_EX_PIN] +0 +1 +12 +13 +14 +15 + +[I2C] +I2C_COUNT = 32 +CHANNEL_COUNT = 5 + +[CLK_BUF] +CLK_BUF_COUNT = 8 + +[KEYPAD] +KEY_ROW = 8 +KEY_COLUMN = 9 + +[KEYPAD_EXTEND_TYPE] +KEY_ROW = 3 +KEY_COLUMN = 6 +KEY_DESIGN_NOTICES = "Please notice that the circuit design are different between single and double keypad, and DO NOT add 1K ohm resistor on double keypad" + +[POWER] +DVDD28_SIM1 +DVDD28_SIM2 +DVDD28_MC1 +DVDD28_MC2 + +[DVDD28_SIM1] +VIO18 +VIO28 + +[DVDD28_SIM2] +VIO18 +VIO28 + +[DVDD28_MC1] +VIO18 +VIO28 + +[DVDD28_MC2] +VIO18 +VIO28 + +[MSDC_POWER_MC1] +MSDC_VIO18_MC1 +MSDC_VIO28_MC1 +MSDC_VMC + +[SRC_PIN] +PAD_CAM_CLK1 +PAD_DPI_D6 +PAD_DPI_D7 +PAD_INT_SIM1 +PAD_INT_SIM2 +PAD_PWM_A + +[SRC_PIN_INDEX] +1 +2 +1 +1 +2 +2 + diff --git a/tools/dct/old_dct/MT6755.fig b/tools/dct/old_dct/MT6755.fig new file mode 100644 index 0000000000000000000000000000000000000000..c4b8b142c13534b699215fa991d60222a481f53a --- /dev/null +++ b/tools/dct/old_dct/MT6755.fig @@ -0,0 +1,290 @@ +[Chip Type] +Chip = MT6755 +GPIO_Pull_Sel = 1 +PMIC_Config = 1 +PMIC_ON_OFF_CONFIG = 1 +GPIO_ModeNum = 8 +EINT_MD1_Config = 1 +EINT_MD1_SRC_PIN = 1 +POWER_Config = 1 +POWER_COUNT = 4 +SpecialKey_Config = 1 +I2C_Config = 1 +CLOCK_BUFFER_CONFIG = 1 +Extend_Key_Config=1 +Reset_Key_Config = 1 +PMIC_APP_Ver = 2 +PMIC_APP_COUNT = 6 +MD1_EINT_SRC_PIN_CFG = 1 +AndroidPhone = 1 + +[GPIO] +GPIO0 = MODE0(GPIO0) MODE1() MODE2(EXT_FRAME_SYNC) MODE3(CLKM0) MODE4(IDDIG) MODE5(C2K_EINT0) MODE6(I2S3_MCK) MODE7() PD SMT_GROUP(0) +GPIO1 = MODE0(GPIO1) MODE1() MODE2(EXT_FRAME_SYNC) MODE3(CLKM1) MODE4(USB_DRVVBUS) MODE5(C2K_EINT1) MODE6(I2S3_BCK) MODE7() PD SMT_GROUP(0) +GPIO2 = MODE0(GPIO2) MODE1(CMFLASH) MODE2(UTXD1) MODE3(CLKM2) MODE4(MD_URXD2) MODE5(C2K_UTXD1) MODE6(I2S3_LRCK) MODE7() PD SMT_GROUP(0) +GPIO3 = MODE0(GPIO3) MODE1(PWM_A) MODE2(URXD1) MODE3(CLKM3) MODE4(MD_UTXD2) MODE5(C2K_URXD1) MODE6(I2S3_DO) MODE7(SPI1_B_MI) PD SMT_GROUP(0) +GPIO4 = MODE0(GPIO4) MODE1(PWM_B) MODE2(I2S0_MCK) MODE3(UCTS0) MODE4(MD_URXD1) MODE5(C2K_UTXD0) MODE6(ANT_SEL3) MODE7(SPI1_B_MI) PD SMT_GROUP(1) +GPIO5 = MODE0(GPIO5) MODE1(PWM_C) MODE2(I2S0_BCK) MODE3(URTS0) MODE4(MD_UTXD1) MODE5(C2K_URXD0) MODE6(ANT_SEL4) MODE7(SPI1_B_CSB) PD SMT_GROUP(1) +GPIO6 = MODE0(GPIO6) MODE1(IRTX_OUT) MODE2(I2S0_LRCK) MODE3(IDDIG) MODE4(MD_URXD0) MODE5(SDA0) MODE6(ANT_SEL5) MODE7(SPI1_B_MO) PD SMT_GROUP(1) +GPIO7 = MODE0(GPIO7) MODE1(IRTX_OUT) MODE2(I2S0_DI) MODE3(USB_DRVVBUS) MODE4(MD_UTXD0) MODE5(SCL0) MODE6(PCC_PPC_IO) MODE7(SPI1_B_CLK) PD SMT_GROUP(1) +GPIO8 = MODE0(GPIO8) MODE1(PWM_A) MODE2(PCC_PPC_IO) MODE3() MODE4(CONN_MCU_TRST_B) MODE5(C2K_DM_JTINTP) MODE6(IO_JTAG_TRSTN) MODE7(DBG_MON_A44) PD SMT_GROUP(2) +GPIO9 = MODE0(GPIO9) MODE1(PWM_B) MODE2(UCTS1) MODE3(DAP_SIB1_SWD) MODE4(CONN_MCU_DBGACK_N) MODE5(IRTX_OUT) MODE6() MODE7(DBG_MON_A45) PD SMT_GROUP(3) +GPIO10 = MODE0(GPIO10) MODE1(PWM_C) MODE2(URTS1) MODE3(DAP_SIB1_SWCK) MODE4(CONN_MCU_DBGI_N) MODE5(EXT_FRAME_SYNC) MODE6() MODE7(DBG_MON_A46) PD SMT_GROUP(3) +GPIO11 = MODE0(GPIO11) MODE1(IRTX_OUT) MODE2(IDDIG) MODE3(I2S1_MCK) MODE4(PWM_B) MODE5(CLKM0) MODE6(SRCLKENAI1) MODE7() PD SMT_GROUP(4) +GPIO12 = MODE0(GPIO12) MODE1(IRTX_OUT) MODE2(USB_DRVVBUS) MODE3(I2S2_DI) MODE4(PWM_C) MODE5(CLKM1) MODE6(CMFLASH) MODE7() PD SMT_GROUP(5) +GPIO13 = MODE0(GPIO13) MODE1(DPI_D0) MODE2(MRG_SYNC) MODE3(PCM0_SYNC) MODE4(MD_URXD0) MODE5(C2K_EINT0) MODE6(I2S0_MCK) MODE7(DBG_MON_A19) PD SMT_GROUP(6) +GPIO14 = MODE0(GPIO14) MODE1(DPI_D1) MODE2(MRG_CLK) MODE3(PCM0_CLK) MODE4(MD_UTXD0) MODE5(C2K_EINT1) MODE6(I2S0_BCK) MODE7(DBG_MON_A20) PD SMT_GROUP(6) +GPIO15 = MODE0(GPIO15) MODE1(DPI_D2) MODE2(MRG_DO) MODE3(PCM0_DO) MODE4(MD_URXD1) MODE5(C2K_DM_EINT0) MODE6(I2S0_LRCK) MODE7(DBG_MON_A21) PD SMT_GROUP(6) +GPIO16 = MODE0(GPIO16) MODE1(DPI_D3) MODE2(MRG_DI) MODE3(PCM0_DI) MODE4(MD_UTXD1) MODE5(C2K_DM_EINT1) MODE6(I2S0_DI) MODE7(DBG_MON_A22) PD SMT_GROUP(6) +GPIO17 = MODE0(GPIO17) MODE1(DPI_D4) MODE2(UCTS1) MODE3(CONN_MCU_TRST_B) MODE4(MD_URXD2) MODE5(C2K_URXD0) MODE6(I2S1_MCK) MODE7(DBG_MON_A23) PD SMT_GROUP(7) +GPIO18 = MODE0(GPIO18) MODE1(DPI_D5) MODE2(URTS1) MODE3(CONN_MCU_DBGI_N) MODE4(MD_UTXD2) MODE5(C2K_UTXD0) MODE6(I2S1_BCK) MODE7(DBG_MON_A24) PD SMT_GROUP(7) +GPIO19 = MODE0(GPIO19) MODE1(DPI_D6) MODE2(URXD1) MODE3(CONN_MCU_TDO) MODE4(MD_INT2_C2K_UIM1_HOT_PLUG) MODE5() MODE6(I2S1_LRCK) MODE7(DBG_MON_A25) PD SMT_GROUP(7) +GPIO20 = MODE0(GPIO20) MODE1(DPI_D7) MODE2(UTXD1) MODE3(CONN_MCU_DBGACK_N) MODE4(MD_INT1_C2K_UIM0_HOT_PLUG) MODE5() MODE6(I2S1_DO) MODE7(DBG_MON_A26) PD SMT_GROUP(7) +GPIO21 = MODE0(GPIO21) MODE1(DPI_D8) MODE2(SRCLKENAI1) MODE3(CONN_MCU_TMS) MODE4(DAP_SIB1_SWD) MODE5(CONN_MCU_AICE_TMSC) MODE6(I2S2_MCK) MODE7(DBG_MON_A27) PD SMT_GROUP(8) +GPIO22 = MODE0(GPIO22) MODE1(DPI_D9) MODE2(EXT_FRAME_SYNC) MODE3(CONN_MCU_TCK) MODE4(DAP_SIB1_SWCK) MODE5(CONN_MCU_AICE_TCKC) MODE6(I2S2_BCK) MODE7(DBG_MON_A28) PD SMT_GROUP(8) +GPIO23 = MODE0(GPIO23) MODE1(DPI_D10) MODE2(IDDIG) MODE3(CONN_MCU_TDI) MODE4() MODE5(PWM_B) MODE6(I2S2_LRCK) MODE7(DBG_MON_A29) PD SMT_GROUP(8) +GPIO24 = MODE0(GPIO24) MODE1(DPI_D11) MODE2(USB_DRVVBUS) MODE3(CONN_DSP_JCK) MODE4(SPI1_A_MI) MODE5(PWM_C) MODE6(I2S2_DI) MODE7(DBG_MON_A30) PD SMT_GROUP(8) +GPIO25 = MODE0(GPIO25) MODE1(DPI_HSYNC) MODE2(SPI1_A_MI) MODE3(CONN_DSP_JMS) MODE4(CLKM0) MODE5(C2K_UTXD1) MODE6(I2S3_MCK) MODE7(DBG_MON_A31) PD SMT_GROUP(9) +GPIO26 = MODE0(GPIO26) MODE1(DPI_VSYNC) MODE2(SPI1_A_CSB) MODE3(CONN_DSP_JDI) MODE4(CLKM1) MODE5(C2K_URXD1) MODE6(I2S3_BCK) MODE7(DBG_MON_A32) PD SMT_GROUP(9) +GPIO27 = MODE0(GPIO27) MODE1(DPI_DE) MODE2(SPI1_A_MO) MODE3(CONN_DSP_JDO) MODE4(CLKM2) MODE5(C2K_DM_EINT2) MODE6(I2S3_LRCK) MODE7(DBG_MON_A33) PD SMT_GROUP(9) +GPIO28 = MODE0(GPIO28) MODE1(DPI_CK) MODE2(SPI1_A_CLK) MODE3(CONN_DSP_JINTP) MODE4(CLKM3) MODE5(C2K_DM_EINT3) MODE6(I2S3_DO) MODE7(DBG_MON_A34) PD SMT_GROUP(9) +GPIO29 = MODE0(GPIO29) MODE1(SRCLKENA1) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(10) +GPIO30 = MODE0(GPIO30) MODE1(MSDC1_CLK) MODE2(IO_JTAG_TCK) MODE3() MODE4(CONN_DSP_JCK) MODE5(C2K_DM_OTCK) MODE6(C2K_TCK) MODE7(DBG_MON_A53) PD SMT_GROUP(11) +GPIO31 = MODE0(GPIO31) MODE1(MSDC1_DAT3) MODE2() MODE3(DAP_SIB1_SWD) MODE4(CONN_DSP_JINTP) MODE5(C2K_DM_JTINTP) MODE6(C2K_RTCK) MODE7(DBG_MON_A54) PU SMT_GROUP(12) +GPIO32 = MODE0(GPIO32) MODE1(MSDC1_CMD) MODE2(IO_JTAG_TMS) MODE3() MODE4(CONN_DSP_JMS) MODE5(C2K_DM_OTMS) MODE6(C2K_TMS) MODE7(DBG_MON_A55) PU SMT_GROUP(13) +GPIO33 = MODE0(GPIO33) MODE1(MSDC1_DAT0) MODE2(IO_JTAG_TDI) MODE3() MODE4(CONN_DSP_JDI) MODE5(C2K_DM_OTDI) MODE6(C2K_TDI) MODE7(DBG_MON_A56) PU SMT_GROUP(12) +GPIO34 = MODE0(GPIO34) MODE1(MSDC1_DAT2) MODE2(IO_JTAG_TRSTN) MODE3() MODE4() MODE5(DAP_SIB1_SWCK) MODE6(C2K_NTRST) MODE7(DBG_MON_A57) PU SMT_GROUP(12) +GPIO35 = MODE0(GPIO35) MODE1(MSDC1_DAT1) MODE2(IO_JTAG_TDO) MODE3() MODE4(CONN_DSP_JDO) MODE5(C2K_DM_OTDO) MODE6(C2K_TDO) MODE7(DBG_MON_A58) PU SMT_GROUP(12) +GPIO36 = MODE0(GPIO36) MODE1(MD1_SIM2_SIO) MODE2() MODE3(MD1_SIM1_SIO) MODE4() MODE5(C2K_UIM0_IO) MODE6(C2K_UIM1_IO) MODE7(DBG_MON_A38) PD SMT_GROUP(14) +GPIO37 = MODE0(GPIO37) MODE1(MD1_SIM2_SRST) MODE2() MODE3(MD1_SIM1_SRST) MODE4() MODE5(C2K_UIM0_RST) MODE6(C2K_UIM1_RST) MODE7(DBG_MON_A39) PD SMT_GROUP(14) +GPIO38 = MODE0(GPIO38) MODE1(MD1_SIM2_SCLK) MODE2() MODE3(MD1_SIM1_SCLK) MODE4() MODE5(C2K_UIM0_CLK) MODE6(C2K_UIM1_CLK) MODE7(DBG_MON_A40) PD SMT_GROUP(14) +GPIO39 = MODE0(GPIO39) MODE1(MD1_SIM1_SCLK) MODE2() MODE3(MD1_SIM2_SCLK) MODE4() MODE5(C2K_UIM0_CLK) MODE6(C2K_UIM1_CLK) MODE7(DBG_MON_A41) PD SMT_GROUP(15) +GPIO40 = MODE0(GPIO40) MODE1(MD1_SIM1_SRST) MODE2() MODE3(MD1_SIM2_SRST) MODE4() MODE5(C2K_UIM0_RST) MODE6(C2K_UIM1_RST) MODE7(DBG_MON_A42) PD SMT_GROUP(15) +GPIO41 = MODE0(GPIO41) MODE1(MD1_SIM1_SIO) MODE2() MODE3(MD1_SIM2_SIO) MODE4() MODE5(C2K_UIM0_IO) MODE6(C2K_UIM1_IO) MODE7(DBG_MON_A43) PD SMT_GROUP(15) +GPIO42 = MODE0(GPIO42) MODE1(IDDIG) MODE2(URXD1) MODE3(UCTS0) MODE4(SDA1) MODE5(EXT_FRAME_SYNC) MODE6(KPCOL2) MODE7(DBG_MON_A12) PD SMT_GROUP(16) +GPIO43 = MODE0(GPIO43) MODE1(USB_DRVVBUS) MODE2(UTXD1) MODE3(URTS0) MODE4(SCL1) MODE5(EXT_FRAME_SYNC) MODE6(KPROW2) MODE7(DBG_MON_A13) PD SMT_GROUP(16) +GPIO44 = MODE0(GPIO44) MODE1(DSI_TE) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A15) PD SMT_GROUP(17) +GPIO45 = MODE0(GPIO45) MODE1(MD_INT2_C2K_UIM1_HOT_PLUG) MODE2(URXD1) MODE3(UCTS1) MODE4(CLKM0) MODE5() MODE6(IDDIG) MODE7(DBG_MON_A17) PD SMT_GROUP(18) +GPIO46 = MODE0(GPIO46) MODE1(MD_INT1_C2K_UIM0_HOT_PLUG) MODE2(UTXD1) MODE3(URTS1) MODE4(PWM_B) MODE5() MODE6(USB_DRVVBUS) MODE7(DBG_MON_A18) PD SMT_GROUP(18) +GPIO47 = MODE0(GPIO47) MODE1(SCL_APPM) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(19) +GPIO48 = MODE0(GPIO48) MODE1(SDA_APPM) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(19) +GPIO49 = MODE0(GPIO49) MODE1(SCL3) MODE2(IDDIG) MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(20) +GPIO50 = MODE0(GPIO50) MODE1(SDA3) MODE2(IDDIG) MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(20) +GPIO51 = MODE0(GPIO51) MODE1(BPI_BUS15) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B0) PD SMT_GROUP(21) +GPIO52 = MODE0(GPIO52) MODE1(BPI_BUS14) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B1) PD SMT_GROUP(21) +GPIO53 = MODE0(GPIO53) MODE1(BPI_BUS13) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B2) PD SMT_GROUP(21) +GPIO54 = MODE0(GPIO54) MODE1(BPI_BUS12) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B3) PD SMT_GROUP(21) +GPIO55 = MODE0(GPIO55) MODE1(BPI_BUS11) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(21) +GPIO56 = MODE0(GPIO56) MODE1(BPI_BUS10) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(21) +GPIO57 = MODE0(GPIO57) MODE1(BPI_BUS9) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B4) PD SMT_GROUP(21) +GPIO58 = MODE0(GPIO58) MODE1(BPI_BUS8) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B5) PD SMT_GROUP(21) +GPIO59 = MODE0(GPIO59) MODE1(BPI_BUS7) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B6) PD SMT_GROUP(21) +GPIO60 = MODE0(GPIO60) MODE1(BPI_BUS6) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B7) PD SMT_GROUP(21) +GPIO61 = MODE0(GPIO61) MODE1(BPI_BUS5) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B8) PD SMT_GROUP(21) +GPIO62 = MODE0(GPIO62) MODE1(BPI_BUS4) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B9) PD SMT_GROUP(21) +GPIO63 = MODE0(GPIO63) MODE1(MIPI1_SDATA) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B10) PD SMT_GROUP(22) +GPIO64 = MODE0(GPIO64) MODE1(MIPI1_SCLK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B11) PD SMT_GROUP(22) +GPIO65 = MODE0(GPIO65) MODE1(MIPI0_SDATA) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B12) PD SMT_GROUP(22) +GPIO66 = MODE0(GPIO66) MODE1(MIPI0_SCLK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B13) PD SMT_GROUP(22) +GPIO67 = MODE0(GPIO67) MODE1(RFIC0_BSI_D2) MODE2(SPM_BSI_D2) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B14) PD SMT_GROUP(23) +GPIO68 = MODE0(GPIO68) MODE1(RFIC0_BSI_D1) MODE2(SPM_BSI_D1) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B15) PD SMT_GROUP(23) +GPIO69 = MODE0(GPIO69) MODE1(RFIC0_BSI_D0) MODE2(SPM_BSI_D0) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B16) PD SMT_GROUP(23) +GPIO70 = MODE0(GPIO70) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO71 = MODE0(GPIO71) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO72 = MODE0(GPIO72) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO73 = MODE0(GPIO73) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO74 = MODE0(GPIO74) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO75 = MODE0(GPIO75) MODE1(MIPI3_SDATA) MODE2(PWM_C) MODE3(IRTX_OUT) MODE4(I2S0_DI) MODE5(I2S2_DI) MODE6(ANT_SEL5) MODE7(DBG_MON_B19) PD SMT_GROUP(24) +GPIO76 = MODE0(GPIO76) MODE1(MIPI3_SCLK) MODE2(CLKM3) MODE3(EXT_FRAME_SYNC) MODE4(I2S0_LRCK) MODE5(I2S2_LRCK) MODE6(ANT_SEL4) MODE7(DBG_MON_B20) PD SMT_GROUP(24) +GPIO77 = MODE0(GPIO77) MODE1(MIPI2_SDATA) MODE2(USB_DRVVBUS) MODE3(IRTX_OUT) MODE4(I2S0_BCK) MODE5(I2S2_BCK) MODE6(ANT_SEL3) MODE7(DBG_MON_B21) PD SMT_GROUP(24) +GPIO78 = MODE0(GPIO78) MODE1(MIPI2_SCLK) MODE2(IDDIG) MODE3(EXT_FRAME_SYNC) MODE4(I2S0_MCK) MODE5(I2S2_MCK) MODE6(PCM1_DO0) MODE7(DBG_MON_B22) PD SMT_GROUP(24) +GPIO79 = MODE0(GPIO79) MODE1(BPI_BUS3) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B23) PD SMT_GROUP(25) +GPIO80 = MODE0(GPIO80) MODE1(BPI_BUS2) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B24) PD SMT_GROUP(25) +GPIO81 = MODE0(GPIO81) MODE1(BPI_BUS1) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B25) PD SMT_GROUP(25) +GPIO82 = MODE0(GPIO82) MODE1(BPI_BUS0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B26) PD SMT_GROUP(25) +GPIO83 = MODE0(GPIO83) MODE1(BPI_BUS23) MODE2(DET_BPI1) MODE3() MODE4(I2S3_DO) MODE5(I2S1_DO) MODE6(PCM1_DO1) MODE7(DBG_MON_B27) PD SMT_GROUP(26) +GPIO84 = MODE0(GPIO84) MODE1(BPI_BUS22) MODE2(DET_BPI0) MODE3() MODE4(I2S3_LRCK) MODE5(I2S1_LRCK) MODE6(PCM1_CLK) MODE7(DBG_MON_B28) PD SMT_GROUP(26) +GPIO85 = MODE0(GPIO85) MODE1(BPI_BUS21) MODE2(TX_SWAP3) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B29) PD SMT_GROUP(26) +GPIO86 = MODE0(GPIO86) MODE1(BPI_BUS20) MODE2(TX_SWAP2) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B30) PD SMT_GROUP(26) +GPIO87 = MODE0(GPIO87) MODE1(BPI_BUS19) MODE2(TX_SWAP1) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B31) PD SMT_GROUP(27) +GPIO88 = MODE0(GPIO88) MODE1(BPI_BUS18) MODE2(TX_SWAP0) MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(27) +GPIO89 = MODE0(GPIO89) MODE1(BPI_BUS17) MODE2(PA_VM1) MODE3() MODE4(I2S3_BCK) MODE5(I2S1_BCK) MODE6(PCM1_SYNC) MODE7() PD SMT_GROUP(27) +GPIO90 = MODE0(GPIO90) MODE1(BPI_BUS16) MODE2(PA_VM0) MODE3() MODE4(I2S3_MCK) MODE5(I2S1_MCK) MODE6(PCM1_DI) MODE7() PD SMT_GROUP(27) +GPIO91 = MODE0(GPIO91) MODE1(SDA1) MODE2(IDDIG) MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(28) +GPIO92 = MODE0(GPIO92) MODE1(SDA0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(29) +GPIO93 = MODE0(GPIO93) MODE1(SCL0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(29) +GPIO94 = MODE0(GPIO94) MODE1(SCL1) MODE2(IDDIG) MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(28) +GPIO95 = MODE0(GPIO95) MODE1(SPI0_MI) MODE2(MRG_SYNC) MODE3(PCM0_SYNC) MODE4(I2S1_BCK) MODE5(SPI0_MO) MODE6(DFD_TDO) MODE7(JTDO_SEL1) PD SMT_GROUP(30) +GPIO96 = MODE0(GPIO96) MODE1(SPI0_CSB) MODE2(MRG_DO) MODE3(PCM0_DO) MODE4(I2S1_LRCK) MODE5(SDA2) MODE6(DFD_TMS) MODE7(JTMS_SEL1) PD SMT_GROUP(30) +GPIO97 = MODE0(GPIO97) MODE1(SPI0_MO) MODE2(MRG_CLK) MODE3(PCM0_CLK) MODE4(I2S1_DO) MODE5(SPI0_MI) MODE6(DFD_TDI) MODE7(JTDI_SEL1) PD SMT_GROUP(30) +GPIO98 = MODE0(GPIO98) MODE1(SPI0_CLK) MODE2(MRG_DI) MODE3(PCM0_DI) MODE4(I2S1_MCK) MODE5(SCL2) MODE6(DFD_TCK_XI) MODE7(JTCK_SEL1) PD SMT_GROUP(30) +GPIO99 = MODE0(GPIO99) MODE1(SRCLKENAI0) MODE2(UTXD1) MODE3(EXT_FRAME_SYNC) MODE4(CLKM2) MODE5(PCC_PPC_IO) MODE6(ANT_SEL3) MODE7(SPI0_MI) PD SMT_GROUP(31) +GPIO100 = MODE0(GPIO100) MODE1(PWM_A) MODE2(URXD1) MODE3(MD_INT0) MODE4(CLKM3) MODE5(MD_INT2_C2K_UIM1_HOT_PLUG) MODE6(ANT_SEL4) MODE7(DBG_MON_A35) PD SMT_GROUP(31) +GPIO101 = MODE0(GPIO101) MODE1(KPROW1) MODE2(IRTX_OUT) MODE3(C2K_UTXD1) MODE4(C2K_UTXD0) MODE5(C2K_DM_EINT2) MODE6(ANT_SEL5) MODE7(DBG_MON_A36) PD SMT_GROUP(32) +GPIO102 = MODE0(GPIO102) MODE1(KPROW0) MODE2() MODE3() MODE4() MODE5(C2K_DM_EINT3) MODE6() MODE7(DBG_MON_A37) PD SMT_GROUP(32) +GPIO103 = MODE0(GPIO103) MODE1(KPCOL0) MODE2() MODE3() MODE4() MODE5(C2K_DM_EINT0) MODE6() MODE7() PU SMT_GROUP(32) +GPIO104 = MODE0(GPIO104) MODE1(KPCOL1) MODE2() MODE3(C2K_URXD1) MODE4(C2K_URXD0) MODE5(C2K_DM_EINT1) MODE6() MODE7() PD SMT_GROUP(32) +GPIO105 = MODE0(GPIO105) MODE1(URXD0) MODE2(UTXD0) MODE3(MD_URXD0) MODE4(MD_URXD1) MODE5(C2K_URXD0) MODE6(MD_URXD2) MODE7(C2K_URXD1) PU SMT_GROUP(33) +GPIO106 = MODE0(GPIO106) MODE1(UTXD0) MODE2(URXD0) MODE3(MD_UTXD0) MODE4(MD_UTXD1) MODE5(C2K_UTXD0) MODE6(MD_UTXD2) MODE7(C2K_UTXD1) PU SMT_GROUP(33) +GPIO107 = MODE0(GPIO107) MODE1(UCTS0) MODE2(I2S2_MCK) MODE3() MODE4(CONN_MCU_TDO) MODE5(C2K_DM_OTDO) MODE6(IO_JTAG_TDO) MODE7(DBG_MON_A6) PD SMT_GROUP(34) +GPIO108 = MODE0(GPIO108) MODE1(URTS0) MODE2(I2S2_BCK) MODE3() MODE4(CONN_MCU_TMS) MODE5(C2K_DM_OTMS) MODE6(IO_JTAG_TMS) MODE7(DBG_MON_A7) PD SMT_GROUP(34) +GPIO109 = MODE0(GPIO109) MODE1(CMMCLK1) MODE2(PWM_C) MODE3(MD_INT0) MODE4(CONN_MCU_AICE_TCKC) MODE5(MD_INT1_C2K_UIM0_HOT_PLUG) MODE6(CMFLASH) MODE7(DBG_MON_A9) PD SMT_GROUP(35) +GPIO110 = MODE0(GPIO110) MODE1(CLKM2) MODE2(I2S2_LRCK) MODE3() MODE4(CONN_MCU_TCK) MODE5(C2K_DM_OTCK) MODE6(IO_JTAG_TCK) MODE7(DBG_MON_A10) PD SMT_GROUP(36) +GPIO111 = MODE0(GPIO111) MODE1(CLKM1) MODE2(I2S2_DI) MODE3() MODE4(CONN_MCU_TDI) MODE5(C2K_DM_OTDI) MODE6(IO_JTAG_TDI) MODE7(DBG_MON_A11) PD SMT_GROUP(36) +GPIO112 = MODE0(GPIO112) MODE1(SCL2) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(37) +GPIO113 = MODE0(GPIO113) MODE1(SDA2) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(37) +GPIO114 = MODE0(GPIO114) MODE1(ANT_SEL0) MODE2(PWM_A) MODE3(CLKM0) MODE4(IRTX_OUT) MODE5(PCC_PPC_IO) MODE6() MODE7(DBG_MON_A47) PD SMT_GROUP(38) +GPIO115 = MODE0(GPIO115) MODE1(ANT_SEL1) MODE2(PWM_B) MODE3(CLKM1) MODE4(USB_DRVVBUS) MODE5(DAP_SIB1_SWD) MODE6() MODE7(DBG_MON_A48) PD SMT_GROUP(38) +GPIO116 = MODE0(GPIO116) MODE1(ANT_SEL2) MODE2(PWM_C) MODE3(CLKM2) MODE4(IDDIG) MODE5(DAP_SIB1_SWCK) MODE6(IRTX_OUT) MODE7(DBG_MON_A49) PD SMT_GROUP(38) +GPIO117 = MODE0(GPIO117) MODE1(F2W_DATA) MODE2(PTA_TXD) MODE3(PTA_RXD) MODE4(AUXIF_ST0) MODE5(C2K_UTXD1) MODE6(SDA0) MODE7(DBG_MON_A50) PD SMT_GROUP(39) +GPIO118 = MODE0(GPIO118) MODE1(F2W_CK) MODE2(PTA_RXD) MODE3(PTA_TXD) MODE4(AUXIF_CLK0) MODE5(C2K_URXD1) MODE6(SCL0) MODE7(DBG_MON_A51) PD SMT_GROUP(39) +GPIO119 = MODE0(GPIO119) MODE1(WB_RSTB) MODE2(URXD1) MODE3(UTXD1) MODE4() MODE5() MODE6() MODE7(DBG_MON_A52) PD SMT_GROUP(40) +GPIO120 = MODE0(GPIO120) MODE1(WB_SCLK) MODE2(UTXD1) MODE3(URXD1) MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(40) +GPIO121 = MODE0(GPIO121) MODE1(WB_SDATA) MODE2(AGPS_SYNC) MODE3() MODE4(AUXIF_ST1) MODE5(C2K_UTXD0) MODE6(SDA1) MODE7() PD SMT_GROUP(40) +GPIO122 = MODE0(GPIO122) MODE1(WB_SEN) MODE2(SRCLKENAI1) MODE3() MODE4(AUXIF_CLK1) MODE5(C2K_URXD0) MODE6(SCL1) MODE7() PD SMT_GROUP(40) +GPIO123 = MODE0(GPIO123) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO124 = MODE0(GPIO124) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO125 = MODE0(GPIO125) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO126 = MODE0(GPIO126) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO127 = MODE0(GPIO127) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO128 = MODE0(GPIO128) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO129 = MODE0(GPIO129) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO130 = MODE0(GPIO130) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO131 = MODE0(GPIO131) MODE1(WB_CTRL0) MODE2(MSDC2_DAT1) MODE3() MODE4() MODE5(C2K_NTRST) MODE6() MODE7() PD SMT_GROUP(41) +GPIO132 = MODE0(GPIO132) MODE1(WB_CTRL1) MODE2(MSDC2_CMD) MODE3() MODE4() MODE5(C2K_TCK) MODE6() MODE7() PD SMT_GROUP(42) +GPIO133 = MODE0(GPIO133) MODE1(WB_CTRL2) MODE2(MSDC2_CLK) MODE3() MODE4() MODE5(C2K_TDI) MODE6() MODE7() PD SMT_GROUP(43) +GPIO134 = MODE0(GPIO134) MODE1(WB_CTRL3) MODE2(MSDC2_DAT3) MODE3() MODE4() MODE5(C2K_TMS) MODE6() MODE7() PD SMT_GROUP(41) +GPIO135 = MODE0(GPIO135) MODE1(WB_CTRL4) MODE2(MSDC2_DAT0) MODE3() MODE4() MODE5(C2K_TDO) MODE6() MODE7() PD SMT_GROUP(41) +GPIO136 = MODE0(GPIO136) MODE1(WB_CTRL5) MODE2(MSDC2_DAT2) MODE3() MODE4() MODE5(C2K_RTCK) MODE6() MODE7() PD SMT_GROUP(41) +GPIO137 = MODE0(GPIO137) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO138 = MODE0(GPIO138) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO139 = MODE0(GPIO139) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO140 = MODE0(GPIO140) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO141 = MODE0(GPIO141) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO142 = MODE0(GPIO142) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO143 = MODE0(GPIO143) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO144 = MODE0(GPIO144) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO145 = MODE0(GPIO145) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO146 = MODE0(GPIO146) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO147 = MODE0(GPIO147) MODE1(RTC32K_CK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(44) +GPIO148 = MODE0(GPIO148) MODE1(WATCHDOG) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(45) +GPIO149 = MODE0(GPIO149) MODE1(AUD_CLK_MOSI) MODE2() MODE3(I2S1_BCK) MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(46) +GPIO150 = MODE0(GPIO150) MODE1(AUD_DAT_MOSI) MODE2(AUD_DAT_MISO) MODE3(I2S1_LRCK) MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(46) +GPIO151 = MODE0(GPIO151) MODE1(AUD_DAT_MISO) MODE2(AUD_DAT_MOSI) MODE3(I2S1_DO) MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(46) +GPIO152 = MODE0(GPIO152) MODE1(PWRAP_SPI0_MI) MODE2(PWRAP_SPI0_MO) MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(47) +GPIO153 = MODE0(GPIO153) MODE1(PWRAP_SPI0_CSN) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(47) +GPIO154 = MODE0(GPIO154) MODE1(PWRAP_SPI0_MO) MODE2(PWRAP_SPI0_MI) MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(47) +GPIO155 = MODE0(GPIO155) MODE1(PWRAP_SPI0_CK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PD SMT_GROUP(47) +GPIO156 = MODE0(GPIO156) MODE1(SRCLKENA0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() PU SMT_GROUP(48) +GPIO157 = MODE0(GPIO157) MODE1(DISP_PWM) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A14) PD SMT_GROUP(17) +GPIO158 = MODE0(GPIO158) MODE1(LCM_RST) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A16) PD SMT_GROUP(17) +GPIO159 = MODE0(GPIO159) MODE1(RFIC0_BSI_EN) MODE2(SPM_BSI_EN) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B17) PD SMT_GROUP(23) +GPIO160 = MODE0(GPIO160) MODE1(RFIC0_BSI_CK) MODE2(SPM_BSI_CK) MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_B18) PD SMT_GROUP(23) +GPIO161 = MODE0(GPIO161) MODE1(CMMCLK0) MODE2() MODE3() MODE4(CONN_MCU_AICE_TMSC) MODE5() MODE6() MODE7(DBG_MON_A8) PD SMT_GROUP(49) +GPIO162 = MODE0(GPIO162) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO163 = MODE0(GPIO163) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO164 = MODE0(GPIO164) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO165 = MODE0(GPIO165) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO166 = MODE0(GPIO166) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO167 = MODE0(GPIO167) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO168 = MODE0(GPIO168) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO169 = MODE0(GPIO169) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO170 = MODE0(GPIO170) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO171 = MODE0(GPIO171) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO172 = MODE0(GPIO172) MODE1() MODE2(CMCSD2) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO173 = MODE0(GPIO173) MODE1() MODE2(CMCSD3) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO174 = MODE0(GPIO174) MODE1() MODE2(CMCSK) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO175 = MODE0(GPIO175) MODE1() MODE2() MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO176 = MODE0(GPIO176) MODE1() MODE2(CMCSD0) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO177 = MODE0(GPIO177) MODE1() MODE2(CMCSD1) MODE3() MODE4() MODE5() MODE6() MODE7() -- +GPIO178 = MODE0(GPIO178) MODE1(MSDC0_DAT0) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A0) PU SMT_GROUP(50) +GPIO179 = MODE0(GPIO179) MODE1(MSDC0_CLK) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A1) PD SMT_GROUP(51) +GPIO180 = MODE0(GPIO180) MODE1(MSDC0_CMD) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A2) PU SMT_GROUP(52) +GPIO181 = MODE0(GPIO181) MODE1(MSDC0_DAT1) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A3) PU SMT_GROUP(50) +GPIO182 = MODE0(GPIO182) MODE1(MSDC0_DAT5) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A4) PU SMT_GROUP(50) +GPIO183 = MODE0(GPIO183) MODE1(MSDC0_DAT6) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A5) PU SMT_GROUP(50) +GPIO184 = MODE0(GPIO184) MODE1(MSDC0_DAT4) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A59) PU SMT_GROUP(50) +GPIO185 = MODE0(GPIO185) MODE1(MSDC0_RSTB) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A60) PU SMT_GROUP(53) +GPIO186 = MODE0(GPIO186) MODE1(MSDC0_DAT2) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A61) PU SMT_GROUP(50) +GPIO187 = MODE0(GPIO187) MODE1(MSDC0_DAT3) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A62) PU SMT_GROUP(50) +GPIO188 = MODE0(GPIO188) MODE1(MSDC0_DAT7) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A63) PU SMT_GROUP(50) +GPIO189 = MODE0(GPIO189) MODE1(MSDC0_DSL) MODE2() MODE3() MODE4() MODE5() MODE6() MODE7(DBG_MON_A64) PD SMT_GROUP(54) + +[GPO] + +[EINT] +EINT_COUNT = 160 +EINT_DEBOUNCE_TIME_COUNT = 12 + +[EINT_EX_PIN] + +[ADC] +ADC_COUNT = 6 + +[ADC_EX_PIN] +0 +1 +12 +13 +14 +15 + +[I2C] +I2C_COUNT = 32 +CHANNEL_COUNT = 4 + +[CLK_BUF] +CLK_BUF_COUNT = 8 + +[KEYPAD] +KEY_ROW = 8 +KEY_COLUMN = 9 + +[KEYPAD_EXTEND_TYPE] +KEY_ROW = 3 +KEY_COLUMN = 6 +KEY_DESIGN_NOTICES = "Please notice that the circuit design are different between single and double keypad, and DO NOT add 1K ohm resistor on double keypad" + +[POWER] +DVDD28_SIM1 +DVDD28_SIM2 +DVDD28_MC1 +DVDD28_MC2 + +[DVDD28_SIM1] +VIO18 +VIO28 + +[DVDD28_SIM2] +VIO18 +VIO28 + +[DVDD28_MC1] +VIO18 +VIO28 + +[DVDD28_MC2] +VIO18 +VIO28 + +[MSDC_POWER_MC1] +MSDC_VIO18_MC1 +MSDC_VIO28_MC1 +MSDC_VMC + +[SRC_PIN] +PAD_CAM_CLK1 +PAD_DPI_D6 +PAD_DPI_D7 +PAD_INT_SIM1 +PAD_INT_SIM2 +PAD_PWM_A + +[SRC_PIN_INDEX] +1 +2 +1 +1 +2 +2 +